From f3a6b6dceabccbc4b92471cf12340b8c390ff14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Wed, 21 Feb 2024 18:14:48 +0800 Subject: [PATCH 001/188] contracts: Fix double charge of gas for host functions (#3361) This PR is fixing a bug in the sync mechanism between wasmi and pallet-contracts. This bug leads to essentially double charging all the gas that was used during the execution of the host function. When the `call` host function is used for recursion this will lead to a quadratic amount of gas consumption with regard to the nesting depth.We also took the chance to refactor the code in question and improve the rust docs. The bug was caused by not updating `GasMeter::executor_consumed` (previously `engine_consumed`) when leaving the host function. This lead to the value being stale (too low) when entering another host function. --------- Co-authored-by: PG Herveou --- prdoc/pr_3361.prdoc | 10 +++ .../contracts/fixtures/contracts/recurse.rs | 53 ++++++++++++ .../frame/contracts/proc-macro/src/lib.rs | 37 ++++---- substrate/frame/contracts/src/gas.rs | 86 +++++++++++++------ substrate/frame/contracts/src/tests.rs | 54 +++++++++++- substrate/frame/contracts/src/wasm/mod.rs | 2 +- 6 files changed, 192 insertions(+), 50 deletions(-) create mode 100644 prdoc/pr_3361.prdoc create mode 100644 substrate/frame/contracts/fixtures/contracts/recurse.rs diff --git a/prdoc/pr_3361.prdoc b/prdoc/pr_3361.prdoc new file mode 100644 index 00000000000..65baa9e94a0 --- /dev/null +++ b/prdoc/pr_3361.prdoc @@ -0,0 +1,10 @@ +title: Fix double charge of host function weight + +doc: + - audience: Runtime Dev + description: | + Fixed a double charge which can lead to quadratic gas consumption of + the `call` and `instantiate` host functions. + +crates: + - name: pallet-contracts diff --git a/substrate/frame/contracts/fixtures/contracts/recurse.rs b/substrate/frame/contracts/fixtures/contracts/recurse.rs new file mode 100644 index 00000000000..b1ded608c2f --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/recurse.rs @@ -0,0 +1,53 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! This fixture calls itself as many times as passed as argument. + +#![no_std] +#![no_main] + +use common::{input, output}; +use uapi::{HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + input!(calls_left: u32, ); + + // own address + output!(addr, [0u8; 32], api::address,); + + if calls_left == 0 { + return + } + + api::call_v2( + uapi::CallFlags::ALLOW_REENTRY, + addr, + 0u64, // How much ref_time to devote for the execution. 0 = all. + 0u64, // How much deposit_limit to devote for the execution. 0 = all. + None, // No deposit limit. + &0u64.to_le_bytes(), // Value transferred to the contract. + &(calls_left - 1).to_le_bytes(), + None, + ) + .unwrap(); +} diff --git a/substrate/frame/contracts/proc-macro/src/lib.rs b/substrate/frame/contracts/proc-macro/src/lib.rs index 403db15ac2c..de961776c32 100644 --- a/substrate/frame/contracts/proc-macro/src/lib.rs +++ b/substrate/frame/contracts/proc-macro/src/lib.rs @@ -638,37 +638,34 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2) }; let sync_gas_before = if expand_blocks { quote! { - // Gas left in the gas meter right before switching to engine execution. - let __gas_before__ = { - let engine_consumed_total = + // Write gas from wasmi into pallet-contracts before entering the host function. + let __gas_left_before__ = { + let executor_total = __caller__.fuel_consumed().expect("Fuel metering is enabled; qed"); - let gas_meter = __caller__.data_mut().ext().gas_meter_mut(); - gas_meter - .charge_fuel(engine_consumed_total) + __caller__ + .data_mut() + .ext() + .gas_meter_mut() + .sync_from_executor(executor_total) .map_err(TrapReason::from) .map_err(#into_host)? - .ref_time() }; } } else { quote! { } }; - // Gas left in the gas meter right after returning from engine execution. + // Write gas from pallet-contracts into wasmi after leaving the host function. let sync_gas_after = if expand_blocks { quote! { - let mut gas_after = __caller__.data_mut().ext().gas_meter().gas_left().ref_time(); - let mut host_consumed = __gas_before__.saturating_sub(gas_after); - // Possible undercharge of at max 1 fuel here, if host consumed less than `instruction_weights.base` - // Not a problem though, as soon as host accounts its spent gas properly. - let fuel_consumed = host_consumed - .checked_div(__caller__.data_mut().ext().schedule().instruction_weights.base as u64) - .ok_or(Error::::InvalidSchedule) - .map_err(TrapReason::from) - .map_err(#into_host)?; + let fuel_consumed = __caller__ + .data_mut() + .ext() + .gas_meter_mut() + .sync_to_executor(__gas_left_before__) + .map_err(TrapReason::from)?; __caller__ - .consume_fuel(fuel_consumed) - .map_err(|_| TrapReason::from(Error::::OutOfGas)) - .map_err(#into_host)?; + .consume_fuel(fuel_consumed.into()) + .map_err(|_| TrapReason::from(Error::::OutOfGas))?; } } else { quote! { } diff --git a/substrate/frame/contracts/src/gas.rs b/substrate/frame/contracts/src/gas.rs index 9271b615d00..b9d91f38f16 100644 --- a/substrate/frame/contracts/src/gas.rs +++ b/substrate/frame/contracts/src/gas.rs @@ -23,7 +23,7 @@ use frame_support::{ DefaultNoBound, }; use sp_core::Get; -use sp_runtime::{traits::Zero, DispatchError}; +use sp_runtime::{traits::Zero, DispatchError, Saturating}; #[cfg(test)] use std::{any::Any, fmt::Debug}; @@ -37,6 +37,24 @@ impl ChargedAmount { } } +/// Used to capture the gas left before entering a host function. +/// +/// Has to be consumed in order to sync back the gas after leaving the host function. +#[must_use] +pub struct RefTimeLeft(u64); + +/// Resource that needs to be synced to the executor. +/// +/// Wrapped to make sure that the resource will be synced back the the executor. +#[must_use] +pub struct Syncable(u64); + +impl From for u64 { + fn from(from: Syncable) -> u64 { + from.0 + } +} + #[cfg(not(test))] pub trait TestAuxiliaries {} #[cfg(not(test))] @@ -84,8 +102,13 @@ pub struct GasMeter { gas_left: Weight, /// Due to `adjust_gas` and `nested` the `gas_left` can temporarily dip below its final value. gas_left_lowest: Weight, - /// Amount of fuel consumed by the engine from the last host function call. - engine_consumed: u64, + /// The amount of resources that was consumed by the execution engine. + /// + /// This should be equivalent to `self.gas_consumed().ref_time()` but expressed in whatever + /// unit the execution engine uses to track resource consumption. We have to track it + /// separately in order to avoid the loss of precision that happens when converting from + /// ref_time to the execution engine unit. + executor_consumed: u64, _phantom: PhantomData, #[cfg(test)] tokens: Vec, @@ -97,7 +120,7 @@ impl GasMeter { gas_limit, gas_left: gas_limit, gas_left_lowest: gas_limit, - engine_consumed: Default::default(), + executor_consumed: 0, _phantom: PhantomData, #[cfg(test)] tokens: Vec::new(), @@ -172,32 +195,41 @@ impl GasMeter { self.gas_left = self.gas_left.saturating_add(adjustment).min(self.gas_limit); } - /// This method is used for gas syncs with the engine. + /// Hand over the gas metering responsibility from the executor to this meter. /// - /// Updates internal `engine_comsumed` tracker of engine fuel consumption. + /// Needs to be called when entering a host function to update this meter with the + /// gas that was tracked by the executor. It tracks the latest seen total value + /// in order to compute the delta that needs to be charged. + pub fn sync_from_executor( + &mut self, + executor_total: u64, + ) -> Result { + let chargable_reftime = executor_total + .saturating_sub(self.executor_consumed) + .saturating_mul(u64::from(T::Schedule::get().instruction_weights.base)); + self.executor_consumed = executor_total; + self.gas_left + .checked_reduce(Weight::from_parts(chargable_reftime, 0)) + .ok_or_else(|| Error::::OutOfGas)?; + Ok(RefTimeLeft(self.gas_left.ref_time())) + } + + /// Hand over the gas metering responsibility from this meter to the executor. /// - /// Charges self with the `ref_time` Weight corresponding to wasmi fuel consumed on the engine - /// side since last sync. Passed value is scaled by multiplying it by the weight of a basic - /// operation, as such an operation in wasmi engine costs 1. + /// Needs to be called when leaving a host function in order to calculate how much + /// gas needs to be charged from the **executor**. It updates the last seen executor + /// total value so that it is correct when `sync_from_executor` is called the next time. /// - /// Returns the updated `gas_left` `Weight` value from the meter. - /// Normally this would never fail, as engine should fail first when out of gas. - pub fn charge_fuel(&mut self, wasmi_fuel_total: u64) -> Result { - // Take the part consumed since the last update. - let wasmi_fuel = wasmi_fuel_total.saturating_sub(self.engine_consumed); - if !wasmi_fuel.is_zero() { - self.engine_consumed = wasmi_fuel_total; - let reftime_consumed = - wasmi_fuel.saturating_mul(T::Schedule::get().instruction_weights.base as u64); - let ref_time_left = self - .gas_left - .ref_time() - .checked_sub(reftime_consumed) - .ok_or_else(|| Error::::OutOfGas)?; - - *(self.gas_left.ref_time_mut()) = ref_time_left; - } - Ok(self.gas_left) + /// It is important that this does **not** actually sync with the executor. That has + /// to be done by the caller. + pub fn sync_to_executor(&mut self, before: RefTimeLeft) -> Result { + let chargable_executor_resource = before + .0 + .saturating_sub(self.gas_left().ref_time()) + .checked_div(u64::from(T::Schedule::get().instruction_weights.base)) + .ok_or(Error::::InvalidSchedule)?; + self.executor_consumed.saturating_accrue(chargable_executor_resource); + Ok(Syncable(chargable_executor_resource)) } /// Returns the amount of gas that is required to run the same call. diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index cd4e43ed4c2..b39fc79b62a 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -35,8 +35,8 @@ use crate::{ tests::test_utils::{get_contract, get_contract_checked}, wasm::{Determinism, ReturnErrorCode as RuntimeReturnCode}, weights::WeightInfo, - BalanceOf, Code, CodeHash, CodeInfoOf, CollectEvents, Config, ContractInfo, ContractInfoOf, - DebugInfo, DefaultAddressGenerator, DeletionQueueCounter, Error, HoldReason, + Array, BalanceOf, Code, CodeHash, CodeInfoOf, CollectEvents, Config, ContractInfo, + ContractInfoOf, DebugInfo, DefaultAddressGenerator, DeletionQueueCounter, Error, HoldReason, MigrationInProgress, Origin, Pallet, PristineCode, Schedule, }; use assert_matches::assert_matches; @@ -5977,3 +5977,53 @@ fn balance_api_returns_free_balance() { ); }); } + +#[test] +fn gas_consumed_is_linear_for_nested_calls() { + let (code, _code_hash) = compile_module::("recurse").unwrap(); + ExtBuilder::default().existential_deposit(200).build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + + let addr = Contracts::bare_instantiate( + ALICE, + 0, + GAS_LIMIT, + None, + Code::Upload(code), + vec![], + vec![], + DebugInfo::Skip, + CollectEvents::Skip, + ) + .result + .unwrap() + .account_id; + + let max_call_depth = ::CallStack::size() as u32; + let [gas_0, gas_1, gas_2, gas_max] = { + [0u32, 1u32, 2u32, max_call_depth] + .iter() + .map(|i| { + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + GAS_LIMIT, + None, + i.encode(), + DebugInfo::Skip, + CollectEvents::Skip, + Determinism::Enforced, + ); + assert_ok!(result.result); + result.gas_consumed + }) + .collect::>() + .try_into() + .unwrap() + }; + + let gas_per_recursion = gas_2.checked_sub(&gas_1).unwrap(); + assert_eq!(gas_max, gas_0 + gas_per_recursion * max_call_depth as u64); + }); +} diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs index 5386f4d0ffd..c96c2856509 100644 --- a/substrate/frame/contracts/src/wasm/mod.rs +++ b/substrate/frame/contracts/src/wasm/mod.rs @@ -386,7 +386,7 @@ impl Executable for WasmBlob { let engine_consumed_total = store.fuel_consumed().expect("Fuel metering is enabled; qed"); let gas_meter = store.data_mut().ext().gas_meter_mut(); - gas_meter.charge_fuel(engine_consumed_total)?; + let _ = gas_meter.sync_from_executor(engine_consumed_total)?; store.into_data().to_execution_result(result) }; -- GitLab From cbeccad65fa3e6f9fb795fe996d522365a72c69b Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 21 Feb 2024 12:24:14 +0200 Subject: [PATCH 002/188] sc-consensus-beefy: reduce log levels (#3418) fixes https://github.com/paritytech/polkadot-sdk/issues/3407 --- .../client/consensus/beefy/src/aux_schema.rs | 4 ++-- substrate/client/consensus/beefy/src/lib.rs | 8 +++++-- .../client/consensus/beefy/src/worker.rs | 21 ++++++++++--------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/substrate/client/consensus/beefy/src/aux_schema.rs b/substrate/client/consensus/beefy/src/aux_schema.rs index 944a00f8372..534f668ae69 100644 --- a/substrate/client/consensus/beefy/src/aux_schema.rs +++ b/substrate/client/consensus/beefy/src/aux_schema.rs @@ -20,7 +20,7 @@ use crate::{error::Error, worker::PersistedState, LOG_TARGET}; use codec::{Decode, Encode}; -use log::{info, trace}; +use log::{debug, trace}; use sc_client_api::{backend::AuxStore, Backend}; use sp_runtime::traits::Block as BlockT; @@ -30,7 +30,7 @@ const WORKER_STATE_KEY: &[u8] = b"beefy_voter_state"; const CURRENT_VERSION: u32 = 4; pub(crate) fn write_current_version(backend: &BE) -> Result<(), Error> { - info!(target: LOG_TARGET, "🥩 write aux schema version {:?}", CURRENT_VERSION); + debug!(target: LOG_TARGET, "🥩 write aux schema version {:?}", CURRENT_VERSION); AuxStore::insert_aux(backend, &[(VERSION_KEY, CURRENT_VERSION.encode().as_slice())], &[]) .map_err(|e| Error::Backend(e.to_string())) } diff --git a/substrate/client/consensus/beefy/src/lib.rs b/substrate/client/consensus/beefy/src/lib.rs index 1f10d8099d8..11a105561e4 100644 --- a/substrate/client/consensus/beefy/src/lib.rs +++ b/substrate/client/consensus/beefy/src/lib.rs @@ -460,10 +460,14 @@ where R::Api: BeefyApi, { let blockchain = backend.blockchain(); - // Walk up the chain looking for the validator set active at 'at_header'. Process both state and // header digests. - debug!(target: LOG_TARGET, "🥩 Trying to find validator set active at header: {:?}", at_header); + debug!( + target: LOG_TARGET, + "🥩 Trying to find validator set active at header(number {:?}, hash {:?})", + at_header.number(), + at_header.hash() + ); let mut header = at_header.clone(); loop { debug!(target: LOG_TARGET, "🥩 Looking for auth set change at block number: {:?}", *header.number()); diff --git a/substrate/client/consensus/beefy/src/worker.rs b/substrate/client/consensus/beefy/src/worker.rs index 19a24b9bc1a..d7a229003cc 100644 --- a/substrate/client/consensus/beefy/src/worker.rs +++ b/substrate/client/consensus/beefy/src/worker.rs @@ -387,7 +387,7 @@ where .flatten() .map(|justifs| justifs.get(BEEFY_ENGINE_ID).is_some()) { - info!( + debug!( target: LOG_TARGET, "🥩 Initialize BEEFY voter at last BEEFY finalized block: {:?}.", *header.number() @@ -439,7 +439,7 @@ where } if let Some(active) = find_authorities_change::(&header) { - info!( + debug!( target: LOG_TARGET, "🥩 Marking block {:?} as BEEFY Mandatory.", *header.number() @@ -471,7 +471,7 @@ where state.set_best_grandpa(best_grandpa.clone()); // Overwrite persisted data with newly provided `min_block_delta`. state.set_min_block_delta(min_block_delta); - info!(target: LOG_TARGET, "🥩 Loading BEEFY voter state from db: {:?}.", state); + debug!(target: LOG_TARGET, "🥩 Loading BEEFY voter state from db: {:?}.", state); // Make sure that all the headers that we need have been synced. let mut new_sessions = vec![]; @@ -489,7 +489,7 @@ where // Make sure we didn't miss any sessions during node restart. for (validator_set, new_session_start) in new_sessions.drain(..).rev() { - info!( + debug!( target: LOG_TARGET, "🥩 Handling missed BEEFY session after node restart: {:?}.", new_session_start @@ -630,13 +630,14 @@ where &mut self, notification: &FinalityNotification, ) -> Result<(), Error> { + let header = ¬ification.header; debug!( target: LOG_TARGET, - "🥩 Finality notification: header {:?} tree_route {:?}", - notification.header, + "🥩 Finality notification: header(number {:?}, hash {:?}) tree_route {:?}", + header.number(), + header.hash(), notification.tree_route, ); - let header = ¬ification.header; self.base .runtime @@ -757,7 +758,7 @@ where match rounds.add_vote(vote) { VoteImportResult::RoundConcluded(signed_commitment) => { let finality_proof = VersionedFinalityProof::V1(signed_commitment); - info!( + debug!( target: LOG_TARGET, "🥩 Round #{} concluded, finality_proof: {:?}.", block_number, finality_proof ); @@ -1165,7 +1166,7 @@ where return Ok(()) } else if let Some(local_id) = self.base.key_store.authority_id(validators) { if offender_id == local_id { - debug!(target: LOG_TARGET, "🥩 Skip equivocation report for own equivocation"); + warn!(target: LOG_TARGET, "🥩 Skip equivocation report for own equivocation"); return Ok(()) } } @@ -1234,7 +1235,7 @@ where // if the mandatory block (session_start) does not have a beefy justification yet, // we vote on it let target = if best_beefy < session_start { - debug!(target: LOG_TARGET, "🥩 vote target - mandatory block: #{:?}", session_start,); + debug!(target: LOG_TARGET, "🥩 vote target - mandatory block: #{:?}", session_start); session_start } else { let diff = best_grandpa.saturating_sub(best_beefy) + 1u32.into(); -- GitLab From bf7c49b33cee9a00d7e94d0f64b1fdb4bf3f9241 Mon Sep 17 00:00:00 2001 From: Egor_P Date: Wed, 21 Feb 2024 20:48:18 +0700 Subject: [PATCH 003/188] Fix failing release notifications GHA (#3416) This PR should fix the issue with the failing GHA which sends notifications to the different matrix channels, when the new release is published --- .../workflows/release-99_notif-published.yml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release-99_notif-published.yml b/.github/workflows/release-99_notif-published.yml index b35120ca4e1..397795fafa4 100644 --- a/.github/workflows/release-99_notif-published.yml +++ b/.github/workflows/release-99_notif-published.yml @@ -8,13 +8,11 @@ on: jobs: ping_matrix: runs-on: ubuntu-latest + environment: release strategy: matrix: channel: # Internal - - name: 'RelEng: Cumulus Release Coordination' - room: '!NAEMyPAHWOiOQHsvus:parity.io' - pre-releases: true - name: "RelEng: Polkadot Release Coordination" room: '!cqAmzdIcbOFwrdrubV:parity.io' pre-release: true @@ -31,18 +29,9 @@ jobs: pre-release: true # Public - # - name: '#KusamaValidatorLounge:polkadot.builders' - # room: '!LhjZccBOqFNYKLdmbb:polkadot.builders' - # pre-releases: false - # - name: '#kusama-announcements:matrix.parity.io' - # room: '!FMwxpQnYhRCNDRsYGI:matrix.parity.io' - # pre-release: false - # - name: '#polkadotvalidatorlounge:web3.foundation' - # room: '!NZrbtteFeqYKCUGQtr:matrix.parity.io' - # pre-release: false - # - name: '#polkadot-announcements:matrix.parity.io' - # room: '!UqHPWiCBGZWxrmYBkF:matrix.parity.io' - # pre-release: false + - name: '#polkadotvalidatorlounge:web3.foundation' + room: '!NZrbtteFeqYKCUGQtr:matrix.parity.io' + pre-releases: false steps: - name: Matrix notification to ${{ matrix.channel.name }} -- GitLab From 5a06771eccb27e58f09189ea34ce20d947b1db4f Mon Sep 17 00:00:00 2001 From: Clara van Staden Date: Wed, 21 Feb 2024 16:48:40 +0200 Subject: [PATCH 004/188] Snowbridge - Test pallet order (#3381) - Adds a test to check the correct digest for Snowbridge outbound messages. For the correct digest to be in the block, the the MessageQueue pallet should be configured after the EthereumOutbound queue pallet. The added test fails if the EthereumOutbound is configured after the MessageQueue pallet. - Adds a helper method `run_to_block_with_finalize` to simulate the block finalizing. The existing `run_to_block` method does not finalize and so it cannot successfully test this condition. Closes: https://github.com/paritytech/polkadot-sdk/issues/3208 --------- Co-authored-by: claravanstaden --- Cargo.lock | 3 + bridges/snowbridge/README.md | 24 ++-- bridges/snowbridge/pallets/system/src/lib.rs | 4 +- .../snowbridge/runtime/test-common/src/lib.rs | 112 +++++++++++++++-- .../snowbridge/scripts/contribute-upstream.sh | 80 ++++++++++++ .../scripts/verify-pallets-build.sh | 116 ------------------ .../runtimes/assets/test-utils/Cargo.toml | 2 + .../assets/test-utils/src/test_cases.rs | 18 ++- .../test-utils/src/test_cases_over_bridge.rs | 9 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 2 +- .../bridge-hub-rococo/tests/snowbridge.rs | 32 ++++- .../bridge-hubs/test-utils/Cargo.toml | 2 + .../test-utils/src/test_cases/helpers.rs | 4 +- .../parachains/runtimes/test-utils/Cargo.toml | 2 + .../parachains/runtimes/test-utils/src/lib.rs | 71 ++++++++++- .../runtimes/test-utils/src/test_cases.rs | 6 +- 16 files changed, 332 insertions(+), 155 deletions(-) create mode 100755 bridges/snowbridge/scripts/contribute-upstream.sh delete mode 100755 bridges/snowbridge/scripts/verify-pallets-build.sh diff --git a/Cargo.lock b/Cargo.lock index 9f2a1a06891..93ee9cc99c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1054,6 +1054,7 @@ dependencies = [ "pallet-balances", "pallet-collator-selection", "pallet-session", + "pallet-timestamp", "pallet-xcm", "pallet-xcm-bridge-hub-router", "parachains-common", @@ -2099,6 +2100,7 @@ dependencies = [ "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", + "pallet-timestamp", "pallet-utility", "parachains-common", "parachains-runtimes-test-utils", @@ -11430,6 +11432,7 @@ dependencies = [ "pallet-balances", "pallet-collator-selection", "pallet-session", + "pallet-timestamp", "pallet-xcm", "parity-scale-codec", "polkadot-parachain-primitives", diff --git a/bridges/snowbridge/README.md b/bridges/snowbridge/README.md index 49b9c2eaf55..6561df40112 100644 --- a/bridges/snowbridge/README.md +++ b/bridges/snowbridge/README.md @@ -1,32 +1,40 @@ -# Snowbridge -[![codecov](https://codecov.io/gh/Snowfork/snowbridge/branch/main/graph/badge.svg?token=9hvgSws4rN)](https://codecov.io/gh/Snowfork/snowbridge) +# Snowbridge · +[![codecov](https://codecov.io/gh/Snowfork/polkadot-sdk/branch/snowbridge/graph/badge.svg?token=9hvgSws4rN)](https://codecov.io/gh/Snowfork/polkadot-sdk) ![GitHub](https://img.shields.io/github/license/Snowfork/snowbridge) Snowbridge is a trustless bridge between Polkadot and Ethereum. For documentation, visit https://docs.snowbridge.network. ## Components +The Snowbridge project lives in two repositories: + +- [Snowfork/Polkadot-sdk](https://github.com/Snowfork/polkadot-sdk): The Snowbridge parachain and pallets live in +a fork of the Polkadot SDK. Changes are eventually contributed back to +[paritytech/Polkadot-sdk](https://github.com/paritytech/polkadot-sdk) +- [Snowfork/snowbridge](https://github.com/Snowfork/snowbridge): The rest of the Snowbridge components, like contracts, +off-chain relayer, end-to-end tests and test-net setup code. + ### Parachain -Polkadot parachain and our pallets. See [parachain/README.md](https://github.com/Snowfork/snowbridge/blob/main/parachain/README.md). +Polkadot parachain and our pallets. See [README.md](https://github.com/Snowfork/polkadot-sdk/blob/snowbridge/bridges/snowbridge/README.md). ### Contracts -Ethereum contracts and unit tests. See [contracts/README.md](https://github.com/Snowfork/snowbridge/blob/main/contracts/README.md) +Ethereum contracts and unit tests. See [Snowfork/snowbridge/contracts/README.md](https://github.com/Snowfork/snowbridge/blob/main/contracts/README.md) ### Relayer Off-chain relayer services for relaying messages between Polkadot and Ethereum. See -[relayer/README.md](https://github.com/Snowfork/snowbridge/blob/main/relayer/README.md) +[Snowfork/snowbridge/relayer/README.md](https://github.com/Snowfork/snowbridge/blob/main/relayer/README.md) ### Local Testnet Scripts to provision a local testnet, running the above services to bridge between local deployments of Polkadot and -Ethereum. See [web/packages/test/README.md](https://github.com/Snowfork/snowbridge/blob/main/web/packages/test/README.md). +Ethereum. See [Snowfork/snowbridge/web/packages/test/README.md](https://github.com/Snowfork/snowbridge/blob/main/web/packages/test/README.md). ### Smoke Tests -Integration tests for our local testnet. See [smoketest/README.md](https://github.com/Snowfork/snowbridge/blob/main/smoketest/README.md). +Integration tests for our local testnet. See [Snowfork/snowbridge/smoketest/README.md](https://github.com/Snowfork/snowbridge/blob/main/smoketest/README.md). ## Development @@ -83,7 +91,7 @@ direnv allow ### Upgrading the Rust toolchain -Sometimes we would like to upgrade rust toolchain. First update `parachain/rust-toolchain.toml` as required and then +Sometimes we would like to upgrade rust toolchain. First update `rust-toolchain.toml` as required and then update `flake.lock` running ```sh nix flake lock --update-input rust-overlay diff --git a/bridges/snowbridge/pallets/system/src/lib.rs b/bridges/snowbridge/pallets/system/src/lib.rs index b7f38fb753d..6e5ceb5e9b1 100644 --- a/bridges/snowbridge/pallets/system/src/lib.rs +++ b/bridges/snowbridge/pallets/system/src/lib.rs @@ -37,8 +37,6 @@ //! `force_update_channel` and extrinsics to manage agents and channels for system parachains. #![cfg_attr(not(feature = "std"), no_std)] -pub use pallet::*; - #[cfg(test)] mod mock; @@ -79,6 +77,8 @@ use xcm_executor::traits::ConvertLocation; #[cfg(feature = "runtime-benchmarks")] use frame_support::traits::OriginTrait; +pub use pallet::*; + pub type BalanceOf = <::Token as Inspect<::AccountId>>::Balance; pub type AccountIdOf = ::AccountId; diff --git a/bridges/snowbridge/runtime/test-common/src/lib.rs b/bridges/snowbridge/runtime/test-common/src/lib.rs index c9bbce98e57..29b0e738c18 100644 --- a/bridges/snowbridge/runtime/test-common/src/lib.rs +++ b/bridges/snowbridge/runtime/test-common/src/lib.rs @@ -13,9 +13,9 @@ use parachains_runtimes_test_utils::{ }; use snowbridge_core::{ChannelId, ParaId}; use snowbridge_pallet_ethereum_client_fixtures::*; -use sp_core::H160; +use sp_core::{H160, U256}; use sp_keyring::AccountKeyring::*; -use sp_runtime::{traits::Header, AccountId32, SaturatedConversion, Saturating}; +use sp_runtime::{traits::Header, AccountId32, DigestItem, SaturatedConversion, Saturating}; use xcm::{ latest::prelude::*, v3::Error::{self, Barrier}, @@ -53,7 +53,8 @@ where + parachain_info::Config + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config, + + snowbridge_pallet_outbound_queue::Config + + pallet_timestamp::Config, XcmConfig: xcm_executor::Config, { let assethub_parachain_location = Location::new(1, Parachain(assethub_parachain_id)); @@ -125,7 +126,8 @@ pub fn send_transfer_token_message_success( + pallet_message_queue::Config + cumulus_pallet_parachain_system::Config + snowbridge_pallet_outbound_queue::Config - + snowbridge_pallet_system::Config, + + snowbridge_pallet_system::Config + + pallet_timestamp::Config, XcmConfig: xcm_executor::Config, ValidatorIdOf: From>, ::AccountId: From + AsRef<[u8]>, @@ -193,12 +195,100 @@ pub fn send_transfer_token_message_success( let digest = included_head.digest(); - //let digest = frame_system::Pallet::::digest(); let digest_items = digest.logs(); assert!(digest_items.len() == 1 && digest_items[0].as_other().is_some()); }); } +pub fn ethereum_outbound_queue_processes_messages_before_message_queue_works< + Runtime, + XcmConfig, + AllPalletsWithoutSystem, +>( + 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 + + pallet_timestamp::Config, + XcmConfig: xcm_executor::Config, + AllPalletsWithoutSystem: + OnInitialize> + OnFinalize>, + 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!( + e, + snowbridge_pallet_outbound_queue::Event::MessageQueued { .. } + ))); + + let next_block_number: U256 = >::block_number() + .saturating_add(BlockNumberFor::::from(1u32)) + .into(); + + let included_head = + RuntimeHelper::::run_to_block_with_finalize( + next_block_number.as_u32(), + ); + let digest = included_head.digest(); + let digest_items = digest.logs(); + + let mut found_outbound_digest = false; + for digest_item in digest_items { + match digest_item { + DigestItem::Other(_) => found_outbound_digest = true, + _ => {}, + } + } + + assert_eq!(found_outbound_digest, true); + }); +} + pub fn send_unpaid_transfer_token_message( collator_session_key: CollatorSessionKeys, runtime_para_id: u32, @@ -213,7 +303,8 @@ pub fn send_unpaid_transfer_token_message( + parachain_info::Config + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config, + + snowbridge_pallet_outbound_queue::Config + + pallet_timestamp::Config, XcmConfig: xcm_executor::Config, ValidatorIdOf: From>, { @@ -301,7 +392,8 @@ pub fn send_transfer_token_message_failure( + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config + snowbridge_pallet_outbound_queue::Config - + snowbridge_pallet_system::Config, + + snowbridge_pallet_system::Config + + pallet_timestamp::Config, XcmConfig: xcm_executor::Config, ValidatorIdOf: From>, { @@ -349,7 +441,8 @@ pub fn ethereum_extrinsic( + cumulus_pallet_parachain_system::Config + snowbridge_pallet_outbound_queue::Config + snowbridge_pallet_system::Config - + snowbridge_pallet_ethereum_client::Config, + + snowbridge_pallet_ethereum_client::Config + + pallet_timestamp::Config, ValidatorIdOf: From>, ::RuntimeCall: From>, @@ -430,7 +523,8 @@ pub fn ethereum_to_polkadot_message_extrinsics_work( + cumulus_pallet_parachain_system::Config + snowbridge_pallet_outbound_queue::Config + snowbridge_pallet_system::Config - + snowbridge_pallet_ethereum_client::Config, + + snowbridge_pallet_ethereum_client::Config + + pallet_timestamp::Config, ValidatorIdOf: From>, ::RuntimeCall: From>, diff --git a/bridges/snowbridge/scripts/contribute-upstream.sh b/bridges/snowbridge/scripts/contribute-upstream.sh new file mode 100755 index 00000000000..8aa2d2a7035 --- /dev/null +++ b/bridges/snowbridge/scripts/contribute-upstream.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# A script to cleanup the Snowfork fork of the polkadot-sdk to contribute it upstream back to parity/polkadot-sdk +# ./bridges/snowbridge/scripts/contribute-upstream.sh + +# show CLI help +function show_help() { + set +x + echo " " + echo Error: $1 + echo "Usage:" + echo " ./bridges/snowbridge/scripts/contribute-upstream.sh Exit with code 0 if pallets code is well decoupled from the other code in the repo" + exit 1 +} + +if [[ -z "$1" ]]; then + echo "Please provide a branch name you would like your upstream branch to be named" + exit 1 +fi + +branch_name=$1 + +set -eux + +# let's avoid any restrictions on where this script can be called for - snowbridge repo may be +# plugged into any other repo folder. So the script (and other stuff that needs to be removed) +# may be located either in call dir, or one of it subdirs. +SNOWBRIDGE_FOLDER="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/../" + +# Get the current Git branch name +current_branch=$(git rev-parse --abbrev-ref HEAD) + +if [ "$current_branch" = "$branch_name" ] || git branch | grep -q "$branch_name"; then + echo "Already on requested branch or branch exists, not creating." +else + git branch "$branch_name" +fi + +git checkout "$branch_name" + +# remove everything we think is not required for our needs +rm -rf rust-toolchain.toml +rm -rf $SNOWBRIDGE_FOLDER/.cargo +rm -rf $SNOWBRIDGE_FOLDER/.github +rm -rf $SNOWBRIDGE_FOLDER/SECURITY.md +rm -rf $SNOWBRIDGE_FOLDER/.gitignore +rm -rf $SNOWBRIDGE_FOLDER/templates +rm -rf $SNOWBRIDGE_FOLDER/pallets/ethereum-client/fuzz + +pushd $SNOWBRIDGE_FOLDER + +# let's test if everything we need compiles +cargo check -p snowbridge-pallet-ethereum-client +cargo check -p snowbridge-pallet-ethereum-client --features runtime-benchmarks +cargo check -p snowbridge-pallet-ethereum-client --features try-runtime +cargo check -p snowbridge-pallet-inbound-queue +cargo check -p snowbridge-pallet-inbound-queue --features runtime-benchmarks +cargo check -p snowbridge-pallet-inbound-queue --features try-runtime +cargo check -p snowbridge-pallet-outbound-queue +cargo check -p snowbridge-pallet-outbound-queue --features runtime-benchmarks +cargo check -p snowbridge-pallet-outbound-queue --features try-runtime +cargo check -p snowbridge-pallet-system +cargo check -p snowbridge-pallet-system --features runtime-benchmarks +cargo check -p snowbridge-pallet-system --features try-runtime + +# we're removing lock file after all checks are done. Otherwise we may use different +# Substrate/Polkadot/Cumulus commits and our checks will fail +rm -f $SNOWBRIDGE_FOLDER/Cargo.toml +rm -f $SNOWBRIDGE_FOLDER/Cargo.lock + +popd + +# Replace Parity's CI files, that we have overwritten in our fork, to run our own CI +rm -rf .github +git remote -v | grep -w parity || git remote add parity https://github.com/paritytech/polkadot-sdk +git fetch parity master +git checkout parity/master -- .github +git add -- .github + +echo "OK" diff --git a/bridges/snowbridge/scripts/verify-pallets-build.sh b/bridges/snowbridge/scripts/verify-pallets-build.sh deleted file mode 100755 index a62f48c84d4..00000000000 --- a/bridges/snowbridge/scripts/verify-pallets-build.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash - -# A script to remove everything from snowbridge repository/subtree, except: -# -# - parachain -# - readme -# - license - -set -eu - -# show CLI help -function show_help() { - set +x - echo " " - echo Error: $1 - echo "Usage:" - echo " ./scripts/verify-pallets-build.sh Exit with code 0 if pallets code is well decoupled from the other code in the repo" - echo "Options:" - echo " --no-revert Leaves only runtime code on exit" - echo " --ignore-git-state Ignores git actual state" - exit 1 -} - -# parse CLI args -NO_REVERT= -IGNORE_GIT_STATE= -for i in "$@" -do - case $i in - --no-revert) - NO_REVERT=true - shift - ;; - --ignore-git-state) - IGNORE_GIT_STATE=true - shift - ;; - *) - show_help "Unknown option: $i" - ;; - esac -done - -# the script is able to work only on clean git copy, unless we want to ignore this check -[[ ! -z "${IGNORE_GIT_STATE}" ]] || [[ -z "$(git status --porcelain)" ]] || { echo >&2 "The git copy must be clean"; exit 1; } - -# let's avoid any restrictions on where this script can be called for - snowbridge repo may be -# plugged into any other repo folder. So the script (and other stuff that needs to be removed) -# may be located either in call dir, or one of it subdirs. -SNOWBRIDGE_FOLDER="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/../.." - -# remove everything we think is not required for our needs -rm -rf $SNOWBRIDGE_FOLDER/.cargo -rm -rf $SNOWBRIDGE_FOLDER/.github -rm -rf $SNOWBRIDGE_FOLDER/contracts -rm -rf $SNOWBRIDGE_FOLDER/codecov.yml -rm -rf $SNOWBRIDGE_FOLDER/docs -rm -rf $SNOWBRIDGE_FOLDER/hooks -rm -rf $SNOWBRIDGE_FOLDER/relayer -rm -rf $SNOWBRIDGE_FOLDER/scripts -rm -rf $SNOWBRIDGE_FOLDER/SECURITY.md -rm -rf $SNOWBRIDGE_FOLDER/smoketest -rm -rf $SNOWBRIDGE_FOLDER/web -rm -rf $SNOWBRIDGE_FOLDER/.envrc-example -rm -rf $SNOWBRIDGE_FOLDER/.gitbook.yaml -rm -rf $SNOWBRIDGE_FOLDER/.gitignore -rm -rf $SNOWBRIDGE_FOLDER/.gitmodules -rm -rf $SNOWBRIDGE_FOLDER/_typos.toml -rm -rf $SNOWBRIDGE_FOLDER/_codecov.yml -rm -rf $SNOWBRIDGE_FOLDER/flake.lock -rm -rf $SNOWBRIDGE_FOLDER/flake.nix -rm -rf $SNOWBRIDGE_FOLDER/go.work -rm -rf $SNOWBRIDGE_FOLDER/go.work.sum -rm -rf $SNOWBRIDGE_FOLDER/polkadot-sdk -rm -rf $SNOWBRIDGE_FOLDER/rust-toolchain.toml -rm -rf $SNOWBRIDGE_FOLDER/parachain/rustfmt.toml -rm -rf $SNOWBRIDGE_FOLDER/parachain/.gitignore -rm -rf $SNOWBRIDGE_FOLDER/parachain/templates -rm -rf $SNOWBRIDGE_FOLDER/parachain/.cargo -rm -rf $SNOWBRIDGE_FOLDER/parachain/.config -rm -rf $SNOWBRIDGE_FOLDER/parachain/pallets/ethereum-client/fuzz - -cd bridges/snowbridge/parachain - -# fix polkadot-sdk paths in Cargo.toml files -find "." -name 'Cargo.toml' | while read -r file; do - replace=$(printf '../../' ) - if [[ "$(uname)" = "Darwin" ]] || [[ "$(uname)" = *BSD ]]; then - sed -i '' "s|polkadot-sdk/|$replace|g" "$file" - else - sed -i "s|polkadot-sdk/|$replace|g" "$file" - fi -done - -# let's test if everything we need compiles -cargo check -p snowbridge-pallet-ethereum-client -cargo check -p snowbridge-pallet-ethereum-client --features runtime-benchmarks -cargo check -p snowbridge-pallet-ethereum-client --features try-runtime -cargo check -p snowbridge-pallet-inbound-queue -cargo check -p snowbridge-pallet-inbound-queue --features runtime-benchmarks -cargo check -p snowbridge-pallet-inbound-queue --features try-runtime -cargo check -p snowbridge-pallet-outbound-queue -cargo check -p snowbridge-pallet-outbound-queue --features runtime-benchmarks -cargo check -p snowbridge-pallet-outbound-queue --features try-runtime -cargo check -p snowbridge-pallet-system -cargo check -p snowbridge-pallet-system --features runtime-benchmarks -cargo check -p snowbridge-pallet-system --features try-runtime - -cd - - -# we're removing lock file after all checks are done. Otherwise we may use different -# Substrate/Polkadot/Cumulus commits and our checks will fail -rm -f $SNOWBRIDGE_FOLDER/parachain/Cargo.toml -rm -f $SNOWBRIDGE_FOLDER/parachain/Cargo.lock - -echo "OK" diff --git a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml index 89c4925cb1a..883c93c97b4 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml @@ -17,6 +17,7 @@ frame-support = { path = "../../../../../substrate/frame/support", default-featu frame-system = { path = "../../../../../substrate/frame/system", default-features = false } pallet-assets = { path = "../../../../../substrate/frame/assets", default-features = false } pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false } +pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false } pallet-session = { path = "../../../../../substrate/frame/session", default-features = false } sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } @@ -59,6 +60,7 @@ std = [ "pallet-balances/std", "pallet-collator-selection/std", "pallet-session/std", + "pallet-timestamp/std", "pallet-xcm-bridge-hub-router/std", "pallet-xcm/std", "parachain-info/std", diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 4007d926983..53e10956bd0 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -70,7 +70,8 @@ pub fn teleports_for_native_asset_works< + parachain_info::Config + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config - + cumulus_pallet_xcmp_queue::Config, + + cumulus_pallet_xcmp_queue::Config + + pallet_timestamp::Config, AllPalletsWithoutSystem: OnInitialize> + OnFinalize>, AccountIdOf: Into<[u8; 32]>, @@ -350,7 +351,8 @@ pub fn teleports_for_foreign_assets_works< + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config + cumulus_pallet_xcmp_queue::Config - + pallet_assets::Config, + + pallet_assets::Config + + pallet_timestamp::Config, AllPalletsWithoutSystem: OnInitialize> + OnFinalize>, AccountIdOf: Into<[u8; 32]>, @@ -701,7 +703,8 @@ pub fn asset_transactor_transfer_with_local_consensus_currency_works: Into<[u8; 32]>, ValidatorIdOf: From>, BalanceOf: From, @@ -826,7 +829,8 @@ pub fn asset_transactor_transfer_with_pallet_assets_instance_works< + parachain_info::Config + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config - + pallet_assets::Config, + + pallet_assets::Config + + pallet_timestamp::Config, AccountIdOf: Into<[u8; 32]>, ValidatorIdOf: From>, BalanceOf: From, @@ -1093,7 +1097,8 @@ pub fn create_and_manage_foreign_assets_for_local_consensus_parachain_assets_wor + parachain_info::Config + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config - + pallet_assets::Config, + + pallet_assets::Config + + pallet_timestamp::Config, AccountIdOf: Into<[u8; 32]>, ValidatorIdOf: From>, BalanceOf: From, @@ -1422,7 +1427,8 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< + parachain_info::Config + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config - + cumulus_pallet_xcmp_queue::Config, + + cumulus_pallet_xcmp_queue::Config + + pallet_timestamp::Config, AllPalletsWithoutSystem: OnInitialize> + OnFinalize>, AccountIdOf: Into<[u8; 32]>, diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 66ed3417951..1cce3b647cf 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -70,7 +70,8 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< + parachain_info::Config + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config - + cumulus_pallet_xcmp_queue::Config, + + cumulus_pallet_xcmp_queue::Config + + pallet_timestamp::Config, AllPalletsWithoutSystem: OnInitialize> + OnFinalize>, AccountIdOf: Into<[u8; 32]>, @@ -347,7 +348,8 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config + cumulus_pallet_xcmp_queue::Config - + pallet_assets::Config, + + pallet_assets::Config + + pallet_timestamp::Config, AllPalletsWithoutSystem: OnInitialize> + OnFinalize>, AccountIdOf: Into<[u8; 32]> + From<[u8; 32]>, @@ -510,7 +512,8 @@ pub fn report_bridge_status_from_xcm_bridge_router_works< + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config + cumulus_pallet_xcmp_queue::Config - + pallet_xcm_bridge_hub_router::Config, + + pallet_xcm_bridge_hub_router::Config + + pallet_timestamp::Config, AllPalletsWithoutSystem: OnInitialize> + OnFinalize>, AccountIdOf: Into<[u8; 32]>, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index d1eac089f67..ae50d2a93cb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -730,7 +730,7 @@ construct_runtime!( // Message Queue. Importantly, is registered last so that messages are processed after // the `on_initialize` hooks of bridging pallets. - MessageQueue: pallet_message_queue = 250, + MessageQueue: pallet_message_queue = 175, } ); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs index b2e5cc9ef06..b9f43624b65 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs @@ -20,9 +20,9 @@ use bp_polkadot_core::Signature; use bridge_hub_rococo_runtime::{ bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages, bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages, - xcm_config::XcmConfig, BridgeRejectObsoleteHeadersAndMessages, Executive, - MessageQueueServiceWeight, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, SignedExtra, - UncheckedExtrinsic, + xcm_config::XcmConfig, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, + Executive, MessageQueueServiceWeight, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, + SignedExtra, UncheckedExtrinsic, }; use codec::{Decode, Encode}; use cumulus_primitives_core::XcmError::{FailedToTransactAsset, NotHoldingFees}; @@ -135,6 +135,32 @@ fn ethereum_to_polkadot_message_extrinsics_work() { ); } +/// Tests that the digest items are as expected when a Ethereum Outbound message is received. +/// If the MessageQueue pallet is configured before (i.e. the MessageQueue pallet is listed before +/// the EthereumOutboundQueue in the construct_runtime macro) the EthereumOutboundQueue, this test +/// will fail. +#[test] +pub fn ethereum_outbound_queue_processes_messages_before_message_queue_works() { + snowbridge_runtime_test_common::ethereum_outbound_queue_processes_messages_before_message_queue_works::< + Runtime, + XcmConfig, + AllPalletsWithoutSystem, + >( + 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, + } + }), + ) +} + fn construct_extrinsic( sender: sp_keyring::AccountKeyring, call: RuntimeCall, diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml index d34b5cd0eed..5f2a6e050d8 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml @@ -25,6 +25,7 @@ sp-std = { path = "../../../../../substrate/primitives/std", default-features = sp-tracing = { path = "../../../../../substrate/primitives/tracing" } pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false } pallet-utility = { path = "../../../../../substrate/frame/utility", default-features = false } +pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false } # Cumulus asset-test-utils = { path = "../../assets/test-utils" } @@ -73,6 +74,7 @@ std = [ "pallet-bridge-messages/std", "pallet-bridge-parachains/std", "pallet-bridge-relayers/std", + "pallet-timestamp/std", "pallet-utility/std", "parachains-common/std", "parachains-runtimes-test-utils/std", diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs index 4f634c184aa..2b48f2e3d51 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs @@ -197,7 +197,9 @@ where pub(crate) fn initialize_bridge_grandpa_pallet( init_data: bp_header_chain::InitializationData>, ) where - Runtime: BridgeGrandpaConfig, + Runtime: BridgeGrandpaConfig + + cumulus_pallet_parachain_system::Config + + pallet_timestamp::Config, { pallet_bridge_grandpa::Pallet::::initialize( RuntimeHelper::::root_origin(), diff --git a/cumulus/parachains/runtimes/test-utils/Cargo.toml b/cumulus/parachains/runtimes/test-utils/Cargo.toml index a61e05de13f..eda88beb7da 100644 --- a/cumulus/parachains/runtimes/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/test-utils/Cargo.toml @@ -17,6 +17,7 @@ frame-support = { path = "../../../../substrate/frame/support", default-features frame-system = { path = "../../../../substrate/frame/system", default-features = false } pallet-balances = { path = "../../../../substrate/frame/balances", default-features = false } pallet-session = { path = "../../../../substrate/frame/session", default-features = false } +pallet-timestamp = { path = "../../../../substrate/frame/timestamp", default-features = false } sp-consensus-aura = { path = "../../../../substrate/primitives/consensus/aura", default-features = false } sp-io = { path = "../../../../substrate/primitives/io", default-features = false } sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false } @@ -59,6 +60,7 @@ std = [ "pallet-balances/std", "pallet-collator-selection/std", "pallet-session/std", + "pallet-timestamp/std", "pallet-xcm/std", "parachain-info/std", "polkadot-parachain-primitives/std", diff --git a/cumulus/parachains/runtimes/test-utils/src/lib.rs b/cumulus/parachains/runtimes/test-utils/src/lib.rs index b4eb57fcb66..e62daa16a12 100644 --- a/cumulus/parachains/runtimes/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/test-utils/src/lib.rs @@ -34,7 +34,7 @@ use polkadot_parachain_primitives::primitives::{ }; use sp_consensus_aura::{SlotDuration, AURA_ENGINE_ID}; use sp_core::{Encode, U256}; -use sp_runtime::{traits::Header, BuildStorage, Digest, DigestItem}; +use sp_runtime::{traits::Header, BuildStorage, Digest, DigestItem, SaturatedConversion}; use xcm::{ latest::{Asset, Location, XcmContext, XcmHash}, prelude::*, @@ -129,6 +129,7 @@ pub trait BasicParachainRuntime: + parachain_info::Config + pallet_collator_selection::Config + cumulus_pallet_parachain_system::Config + + pallet_timestamp::Config { } @@ -140,7 +141,8 @@ where + pallet_xcm::Config + parachain_info::Config + pallet_collator_selection::Config - + cumulus_pallet_parachain_system::Config, + + cumulus_pallet_parachain_system::Config + + pallet_timestamp::Config, ValidatorIdOf: From>, { } @@ -259,8 +261,10 @@ pub struct RuntimeHelper( ); /// Utility function that advances the chain to the desired block number. /// If an author is provided, that author information is injected to all the blocks in the meantime. -impl - RuntimeHelper +impl< + Runtime: frame_system::Config + cumulus_pallet_parachain_system::Config + pallet_timestamp::Config, + AllPalletsWithoutSystem, + > RuntimeHelper where AccountIdOf: Into<<::RuntimeOrigin as OriginTrait>::AccountId>, @@ -296,6 +300,65 @@ where last_header.expect("run_to_block empty block range") } + pub fn run_to_block_with_finalize(n: u32) -> HeaderFor { + let mut last_header = None; + loop { + let block_number = frame_system::Pallet::::block_number(); + if block_number >= n.into() { + break + } + // Set the new block number and author + let header = frame_system::Pallet::::finalize(); + + let pre_digest = Digest { + logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, block_number.encode())], + }; + frame_system::Pallet::::reset_events(); + + let next_block_number = block_number + 1u32.into(); + frame_system::Pallet::::initialize( + &next_block_number, + &header.hash(), + &pre_digest, + ); + AllPalletsWithoutSystem::on_initialize(next_block_number); + + let parent_head = HeadData(header.encode()); + let sproof_builder = RelayStateSproofBuilder { + para_id: ::SelfParaId::get(), + included_para_head: parent_head.clone().into(), + ..Default::default() + }; + + let (relay_parent_storage_root, relay_chain_state) = + sproof_builder.into_state_root_and_proof(); + let inherent_data = ParachainInherentData { + validation_data: PersistedValidationData { + parent_head, + relay_parent_number: (block_number.saturated_into::() * 2 + 1).into(), + relay_parent_storage_root, + max_pov_size: 100_000_000, + }, + relay_chain_state, + downward_messages: Default::default(), + horizontal_messages: Default::default(), + }; + + let _ = cumulus_pallet_parachain_system::Pallet::::set_validation_data( + Runtime::RuntimeOrigin::none(), + inherent_data, + ); + let _ = pallet_timestamp::Pallet::::set( + Runtime::RuntimeOrigin::none(), + 300_u32.into(), + ); + AllPalletsWithoutSystem::on_finalize(next_block_number); + let header = frame_system::Pallet::::finalize(); + last_header = Some(header); + } + last_header.expect("run_to_block empty block range") + } + pub fn root_origin() -> ::RuntimeOrigin { ::RuntimeOrigin::root() } diff --git a/cumulus/parachains/runtimes/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/test-utils/src/test_cases.rs index f78bf9877ec..1c58df189b6 100644 --- a/cumulus/parachains/runtimes/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/test-utils/src/test_cases.rs @@ -37,7 +37,8 @@ pub fn change_storage_constant_by_governance_works: From>, StorageConstant: Get, StorageConstantType: Encode + PartialEq + std::fmt::Debug, @@ -107,7 +108,8 @@ pub fn set_storage_keys_by_governance_works( + pallet_xcm::Config + parachain_info::Config + pallet_collator_selection::Config - + cumulus_pallet_parachain_system::Config, + + cumulus_pallet_parachain_system::Config + + pallet_timestamp::Config, ValidatorIdOf: From>, { let mut runtime = ExtBuilder::::default() -- GitLab From 165d075a5f680791c8e0b128ea60edd590a44f1f Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:56:09 +0100 Subject: [PATCH 005/188] benchmarking-cli: add --list-pallets and --all options (#3395) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #2844 - adds `list-pallets` option which prints all unique available pallets for benchmarking ```bash ./target/release/node benchmark pallet --list=pallets ``` - adds `all` option which runs benchmarks for all available pallets and extrinsics (equivalent to `--pallet * --extrinsic *`) ```bash ./target/release/node benchmark pallet --all ``` - use the `list=pallets` syntax in `run_all_benchmarks.sh` script cc ggwpez --------- Co-authored-by: Bastian Köcher --- prdoc/pr_3395.prdoc | 14 +++++ substrate/scripts/run_all_benchmarks.sh | 11 ++-- .../benchmarking-cli/src/pallet/command.rs | 54 ++++++++++++++----- .../frame/benchmarking-cli/src/pallet/mod.rs | 32 ++++++++--- 4 files changed, 86 insertions(+), 25 deletions(-) create mode 100644 prdoc/pr_3395.prdoc diff --git a/prdoc/pr_3395.prdoc b/prdoc/pr_3395.prdoc new file mode 100644 index 00000000000..a10fb84fd7f --- /dev/null +++ b/prdoc/pr_3395.prdoc @@ -0,0 +1,14 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "`benchmarking-cli` `pallet` subcommand: refactor `--list` and add `--all` option" + +doc: + - audience: Node Dev + description: | + `pallet` subcommand's `--list` now accepts two values: "all" and "pallets". The former will list all available benchmarks, the latter will list only pallets. + Also adds `--all` to run all the available benchmarks and `--no-csv-header` to omit the csv-style header in the output. + NOTE: changes are backward compatible. + +crates: + - name: frame-benchmarking-cli diff --git a/substrate/scripts/run_all_benchmarks.sh b/substrate/scripts/run_all_benchmarks.sh index 83848100a7e..6dd7cede319 100755 --- a/substrate/scripts/run_all_benchmarks.sh +++ b/substrate/scripts/run_all_benchmarks.sh @@ -59,11 +59,12 @@ done if [ "$skip_build" != true ] then echo "[+] Compiling Substrate benchmarks..." - cargo build --profile=production --locked --features=runtime-benchmarks --bin substrate + cargo build --profile=production --locked --features=runtime-benchmarks --bin substrate-node fi # The executable to use. -SUBSTRATE=./target/production/substrate +# Parent directory because of the monorepo structure. +SUBSTRATE=../target/production/substrate-node # Manually exclude some pallets. EXCLUDED_PALLETS=( @@ -80,11 +81,7 @@ EXCLUDED_PALLETS=( # Load all pallet names in an array. ALL_PALLETS=($( - $SUBSTRATE benchmark pallet --list --chain=dev |\ - tail -n+2 |\ - cut -d',' -f1 |\ - sort |\ - uniq + $SUBSTRATE benchmark pallet --list=pallets --no-csv-header --chain=dev )) # Filter out the excluded pallets by concatenating the arrays and discarding duplicates. diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs index dce49db15f7..d5dc6226ab9 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{writer, PalletCmd}; +use super::{writer, ListOutput, PalletCmd}; use codec::{Decode, Encode}; use frame_benchmarking::{ Analysis, BenchmarkBatch, BenchmarkBatchSplitResults, BenchmarkList, BenchmarkParameter, @@ -39,7 +39,13 @@ use sp_externalities::Extensions; use sp_keystore::{testing::MemoryKeystore, KeystoreExt}; use sp_runtime::traits::Hash; use sp_state_machine::StateMachine; -use std::{collections::HashMap, fmt::Debug, fs, str::FromStr, time}; +use std::{ + collections::{BTreeMap, BTreeSet, HashMap}, + fmt::Debug, + fs, + str::FromStr, + time, +}; /// Logging target const LOG_TARGET: &'static str = "frame::benchmark::pallet"; @@ -191,6 +197,7 @@ impl PalletCmd { let spec = config.chain_spec; let pallet = self.pallet.clone().unwrap_or_default(); let pallet = pallet.as_bytes(); + let extrinsic = self.extrinsic.clone().unwrap_or_default(); let extrinsic_split: Vec<&str> = extrinsic.split(',').collect(); let extrinsics: Vec<_> = extrinsic_split.iter().map(|x| x.trim().as_bytes()).collect(); @@ -309,9 +316,8 @@ impl PalletCmd { return Err("No benchmarks found which match your input.".into()) } - if self.list { - // List benchmarks instead of running them - list_benchmark(benchmarks_to_run); + if let Some(list_output) = self.list { + list_benchmark(benchmarks_to_run, list_output, self.no_csv_header); return Ok(()) } @@ -755,19 +761,43 @@ impl CliConfiguration for PalletCmd { /// List the benchmarks available in the runtime, in a CSV friendly format. fn list_benchmark( - mut benchmarks_to_run: Vec<( + benchmarks_to_run: Vec<( Vec, Vec, Vec<(BenchmarkParameter, u32, u32)>, Vec<(String, String)>, )>, + list_output: ListOutput, + no_csv_header: bool, ) { - // Sort and de-dub by pallet and function name. - benchmarks_to_run.sort_by(|(pa, sa, _, _), (pb, sb, _, _)| (pa, sa).cmp(&(pb, sb))); - benchmarks_to_run.dedup_by(|(pa, sa, _, _), (pb, sb, _, _)| (pa, sa) == (pb, sb)); + let mut benchmarks = BTreeMap::new(); - println!("pallet, benchmark"); - for (pallet, extrinsic, _, _) in benchmarks_to_run { - println!("{}, {}", String::from_utf8_lossy(&pallet), String::from_utf8_lossy(&extrinsic)); + // Sort and de-dub by pallet and function name. + benchmarks_to_run.iter().for_each(|(pallet, extrinsic, _, _)| { + benchmarks + .entry(String::from_utf8_lossy(pallet).to_string()) + .or_insert_with(BTreeSet::new) + .insert(String::from_utf8_lossy(extrinsic).to_string()); + }); + + match list_output { + ListOutput::All => { + if !no_csv_header { + println!("pallet,extrinsic"); + } + for (pallet, extrinsics) in benchmarks { + for extrinsic in extrinsics { + println!("{pallet},{extrinsic}"); + } + } + }, + ListOutput::Pallets => { + if !no_csv_header { + println!("pallet"); + }; + for pallet in benchmarks.keys() { + println!("{pallet}"); + } + }, } } diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs index c69ce1765fc..6dc56c0724e 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/mod.rs @@ -19,6 +19,7 @@ mod command; mod writer; use crate::shared::HostInfoParams; +use clap::ValueEnum; use sc_cli::{ WasmExecutionMethod, WasmtimeInstantiationStrategy, DEFAULT_WASMTIME_INSTANTIATION_STRATEGY, DEFAULT_WASM_EXECUTION_METHOD, @@ -31,17 +32,32 @@ fn parse_pallet_name(pallet: &str) -> std::result::Result { Ok(pallet.replace("-", "_")) } +/// List options for available benchmarks. +#[derive(Debug, Clone, Copy, ValueEnum)] +pub enum ListOutput { + /// List all available pallets and extrinsics. + All, + /// List all available pallets only. + Pallets, +} + /// Benchmark the extrinsic weight of FRAME Pallets. #[derive(Debug, clap::Parser)] pub struct PalletCmd { /// Select a FRAME Pallet to benchmark, or `*` for all (in which case `extrinsic` must be `*`). - #[arg(short, long, value_parser = parse_pallet_name, required_unless_present_any = ["list", "json_input"])] + #[arg(short, long, value_parser = parse_pallet_name, required_unless_present_any = ["list", "json_input", "all"], default_value_if("all", "true", Some("*".into())))] pub pallet: Option, /// Select an extrinsic inside the pallet to benchmark, or `*` for all. - #[arg(short, long, required_unless_present_any = ["list", "json_input"])] + #[arg(short, long, required_unless_present_any = ["list", "json_input", "all"], default_value_if("all", "true", Some("*".into())))] pub extrinsic: Option, + /// Run benchmarks for all pallets and extrinsics. + /// + /// This is equivalent to running `--pallet * --extrinsic *`. + #[arg(long)] + pub all: bool, + /// Select how many samples we should take across the variable components. #[arg(short, long, default_value_t = 50)] pub steps: u32, @@ -158,11 +174,15 @@ pub struct PalletCmd { #[arg(long = "db-cache", value_name = "MiB", default_value_t = 1024)] pub database_cache_size: u32, - /// List the benchmarks that match your query rather than running them. + /// List and print available benchmarks in a csv-friendly format. /// - /// When nothing is provided, we list all benchmarks. - #[arg(long)] - pub list: bool, + /// NOTE: `num_args` and `require_equals` are required to allow `--list` + #[arg(long, value_enum, ignore_case = true, num_args = 0..=1, require_equals = true, default_missing_value("All"))] + pub list: Option, + + /// Don't include csv header when listing benchmarks. + #[arg(long, requires("list"))] + pub no_csv_header: bool, /// If enabled, the storage info is not displayed in the output next to the analysis. /// -- GitLab From 1b624c50728b7f38b31075c3dd8f9a55f0ceee55 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:31:49 +0200 Subject: [PATCH 006/188] rpc-v2/tx: Remove the broadcast event from `transaction_submitAndWatch` (#3321) This PR backports the changes from the rpc-v2 spec: https://github.com/paritytech/json-rpc-interface-spec/pull/134 The `Broadcasted` event has been removed: - it is hard to enforce a `Dropped { broadcasted: bool }` event in cases of a load-balancer being placed in front of an RPC server - when the server exists, it is impossible to guarantee this field if the server did not previously send a `Broadcasted` event - the number of peers reported by this event does not guarantee that peers are unique - the same peer can disconnect and reconnect, increasing this metric number - the number of peers that receive this transaction offers no guarantee about the transaction being included in the chain at a later time cc @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile Co-authored-by: James Wilson --- .../rpc-spec-v2/src/transaction/event.rs | 59 ++--------- .../client/rpc-spec-v2/src/transaction/mod.rs | 5 +- .../src/transaction/transaction.rs | 97 ++++++------------- 3 files changed, 38 insertions(+), 123 deletions(-) diff --git a/substrate/client/rpc-spec-v2/src/transaction/event.rs b/substrate/client/rpc-spec-v2/src/transaction/event.rs index 8b80fcda17b..882ac8490b0 100644 --- a/substrate/client/rpc-spec-v2/src/transaction/event.rs +++ b/substrate/client/rpc-spec-v2/src/transaction/event.rs @@ -20,23 +20,6 @@ use serde::{Deserialize, Serialize}; -/// The transaction was broadcasted to a number of peers. -/// -/// # Note -/// -/// The RPC does not guarantee that the peers have received the -/// transaction. -/// -/// When the number of peers is zero, the event guarantees that -/// shutting down the local node will lead to the transaction -/// not being included in the chain. -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct TransactionBroadcasted { - /// The number of peers the transaction was broadcasted to. - pub num_peers: usize, -} - /// The transaction was included in a block of the chain. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -59,9 +42,6 @@ pub struct TransactionError { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TransactionDropped { - /// True if the transaction was broadcasted to other peers and - /// may still be included in the block. - pub broadcasted: bool, /// Reason of the event. pub error: String, } @@ -70,20 +50,17 @@ pub struct TransactionDropped { /// /// The status events can be grouped based on their kinds as: /// -/// 1. Runtime validated the transaction: +/// 1. Runtime validated the transaction and it entered the pool: /// - `Validated` /// -/// 2. Inside the `Ready` queue: -/// - `Broadcast` -/// -/// 3. Leaving the pool: +/// 2. Leaving the pool: /// - `BestChainBlockIncluded` /// - `Invalid` /// -/// 4. Block finalized: +/// 3. Block finalized: /// - `Finalized` /// -/// 5. At any time: +/// 4. At any time: /// - `Dropped` /// - `Error` /// @@ -101,8 +78,6 @@ pub struct TransactionDropped { pub enum TransactionEvent { /// The transaction was validated by the runtime. Validated, - /// The transaction was broadcasted to a number of peers. - Broadcasted(TransactionBroadcasted), /// The transaction was included in a best block of the chain. /// /// # Note @@ -159,7 +134,6 @@ enum TransactionEventBlockIR { #[serde(tag = "event")] enum TransactionEventNonBlockIR { Validated, - Broadcasted(TransactionBroadcasted), Error(TransactionError), Invalid(TransactionError), Dropped(TransactionDropped), @@ -186,8 +160,6 @@ impl From> for TransactionEventIR { match value { TransactionEvent::Validated => TransactionEventIR::NonBlock(TransactionEventNonBlockIR::Validated), - TransactionEvent::Broadcasted(event) => - TransactionEventIR::NonBlock(TransactionEventNonBlockIR::Broadcasted(event)), TransactionEvent::BestChainBlockIncluded(event) => TransactionEventIR::Block(TransactionEventBlockIR::BestChainBlockIncluded(event)), TransactionEvent::Finalized(event) => @@ -207,8 +179,6 @@ impl From> for TransactionEvent { match value { TransactionEventIR::NonBlock(status) => match status { TransactionEventNonBlockIR::Validated => TransactionEvent::Validated, - TransactionEventNonBlockIR::Broadcasted(event) => - TransactionEvent::Broadcasted(event), TransactionEventNonBlockIR::Error(event) => TransactionEvent::Error(event), TransactionEventNonBlockIR::Invalid(event) => TransactionEvent::Invalid(event), TransactionEventNonBlockIR::Dropped(event) => TransactionEvent::Dropped(event), @@ -239,19 +209,6 @@ mod tests { assert_eq!(event_dec, event); } - #[test] - fn broadcasted_event() { - let event: TransactionEvent<()> = - TransactionEvent::Broadcasted(TransactionBroadcasted { num_peers: 2 }); - let ser = serde_json::to_string(&event).unwrap(); - - let exp = r#"{"event":"broadcasted","numPeers":2}"#; - assert_eq!(ser, exp); - - let event_dec: TransactionEvent<()> = serde_json::from_str(exp).unwrap(); - assert_eq!(event_dec, event); - } - #[test] fn best_chain_event() { let event: TransactionEvent<()> = TransactionEvent::BestChainBlockIncluded(None); @@ -320,13 +277,11 @@ mod tests { #[test] fn dropped_event() { - let event: TransactionEvent<()> = TransactionEvent::Dropped(TransactionDropped { - broadcasted: true, - error: "abc".to_string(), - }); + let event: TransactionEvent<()> = + TransactionEvent::Dropped(TransactionDropped { error: "abc".to_string() }); let ser = serde_json::to_string(&event).unwrap(); - let exp = r#"{"event":"dropped","broadcasted":true,"error":"abc"}"#; + let exp = r#"{"event":"dropped","error":"abc"}"#; assert_eq!(ser, exp); let event_dec: TransactionEvent<()> = serde_json::from_str(exp).unwrap(); diff --git a/substrate/client/rpc-spec-v2/src/transaction/mod.rs b/substrate/client/rpc-spec-v2/src/transaction/mod.rs index 74268a5372a..514ccf047dc 100644 --- a/substrate/client/rpc-spec-v2/src/transaction/mod.rs +++ b/substrate/client/rpc-spec-v2/src/transaction/mod.rs @@ -35,9 +35,6 @@ pub mod transaction; pub mod transaction_broadcast; pub use api::{TransactionApiServer, TransactionBroadcastApiServer}; -pub use event::{ - TransactionBlock, TransactionBroadcasted, TransactionDropped, TransactionError, - TransactionEvent, -}; +pub use event::{TransactionBlock, TransactionDropped, TransactionError, TransactionEvent}; pub use transaction::Transaction; pub use transaction_broadcast::TransactionBroadcast; diff --git a/substrate/client/rpc-spec-v2/src/transaction/transaction.rs b/substrate/client/rpc-spec-v2/src/transaction/transaction.rs index 17889b3bad2..d44006392dc 100644 --- a/substrate/client/rpc-spec-v2/src/transaction/transaction.rs +++ b/substrate/client/rpc-spec-v2/src/transaction/transaction.rs @@ -22,10 +22,7 @@ use crate::{ transaction::{ api::TransactionApiServer, error::Error, - event::{ - TransactionBlock, TransactionBroadcasted, TransactionDropped, TransactionError, - TransactionEvent, - }, + event::{TransactionBlock, TransactionDropped, TransactionError, TransactionEvent}, }, SubscriptionTaskExecutor, }; @@ -113,9 +110,7 @@ where match submit.await { Ok(stream) => { - let mut state = TransactionState::new(); - let stream = - stream.filter_map(move |event| async move { state.handle_event(event) }); + let stream = stream.filter_map(move |event| async move { handle_event(event) }); pipe_from_stream(pending, stream.boxed()).await; }, Err(err) => { @@ -131,66 +126,34 @@ where } } -/// The transaction's state that needs to be preserved between -/// multiple events generated by the transaction-pool. -/// -/// # Note -/// -/// In the future, the RPC server can submit only the last event when multiple -/// identical events happen in a row. -#[derive(Clone, Copy)] -struct TransactionState { - /// True if the transaction was previously broadcasted. - broadcasted: bool, -} - -impl TransactionState { - /// Construct a new [`TransactionState`]. - pub fn new() -> Self { - TransactionState { broadcasted: false } - } - - /// Handle events generated by the transaction-pool and convert them - /// to the new API expected state. - #[inline] - pub fn handle_event( - &mut self, - event: TransactionStatus, - ) -> Option> { - match event { - TransactionStatus::Ready | TransactionStatus::Future => - Some(TransactionEvent::::Validated), - TransactionStatus::Broadcast(peers) => { - // Set the broadcasted flag once if we submitted the transaction to - // at least one peer. - self.broadcasted = self.broadcasted || !peers.is_empty(); - - Some(TransactionEvent::Broadcasted(TransactionBroadcasted { - num_peers: peers.len(), - })) - }, - TransactionStatus::InBlock((hash, index)) => - Some(TransactionEvent::BestChainBlockIncluded(Some(TransactionBlock { - hash, - index, - }))), - TransactionStatus::Retracted(_) => Some(TransactionEvent::BestChainBlockIncluded(None)), - TransactionStatus::FinalityTimeout(_) => - Some(TransactionEvent::Dropped(TransactionDropped { - broadcasted: self.broadcasted, - error: "Maximum number of finality watchers has been reached".into(), - })), - TransactionStatus::Finalized((hash, index)) => - Some(TransactionEvent::Finalized(TransactionBlock { hash, index })), - TransactionStatus::Usurped(_) => Some(TransactionEvent::Invalid(TransactionError { - error: "Extrinsic was rendered invalid by another extrinsic".into(), - })), - TransactionStatus::Dropped => Some(TransactionEvent::Invalid(TransactionError { - error: "Extrinsic dropped from the pool due to exceeding limits".into(), - })), - TransactionStatus::Invalid => Some(TransactionEvent::Invalid(TransactionError { - error: "Extrinsic marked as invalid".into(), +/// Handle events generated by the transaction-pool and convert them +/// to the new API expected state. +#[inline] +pub fn handle_event( + event: TransactionStatus, +) -> Option> { + match event { + TransactionStatus::Ready | TransactionStatus::Future => + Some(TransactionEvent::::Validated), + TransactionStatus::InBlock((hash, index)) => + Some(TransactionEvent::BestChainBlockIncluded(Some(TransactionBlock { hash, index }))), + TransactionStatus::Retracted(_) => Some(TransactionEvent::BestChainBlockIncluded(None)), + TransactionStatus::FinalityTimeout(_) => + Some(TransactionEvent::Dropped(TransactionDropped { + error: "Maximum number of finality watchers has been reached".into(), })), - } + TransactionStatus::Finalized((hash, index)) => + Some(TransactionEvent::Finalized(TransactionBlock { hash, index })), + TransactionStatus::Usurped(_) => Some(TransactionEvent::Invalid(TransactionError { + error: "Extrinsic was rendered invalid by another extrinsic".into(), + })), + TransactionStatus::Dropped => Some(TransactionEvent::Invalid(TransactionError { + error: "Extrinsic dropped from the pool due to exceeding limits".into(), + })), + TransactionStatus::Invalid => Some(TransactionEvent::Invalid(TransactionError { + error: "Extrinsic marked as invalid".into(), + })), + // These are the events that are not supported by the new API. + TransactionStatus::Broadcast(_) => None, } } -- GitLab From 318fed32f8ff42e451ac9f750c25c0f2f85320ad Mon Sep 17 00:00:00 2001 From: tmpolaczyk <44604217+tmpolaczyk@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:38:06 +0100 Subject: [PATCH 007/188] ProposerFactory impl Clone (#3389) In Tanssi, we need a way to stop the collator code and then start it again. This is to support rotating the same collator between different runtimes. Currently, this works very well, except for the proposer metrics, because they only get registered the first time they are started. Afterwards, we see this warning log: > Failed to register proposer prometheus metrics: Duplicate metrics collector registration attempted ~~So this PR adds a method to set metrics, to allow us to register metrics manually before creating the `ProposerFactory`, and then clone the same metrics every time we need to start the collator.~~ Implemented Clone instead --- .../basic-authorship/src/basic_authorship.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/substrate/client/basic-authorship/src/basic_authorship.rs b/substrate/client/basic-authorship/src/basic_authorship.rs index c07f3e639c3..fdc3d4918de 100644 --- a/substrate/client/basic-authorship/src/basic_authorship.rs +++ b/substrate/client/basic-authorship/src/basic_authorship.rs @@ -87,6 +87,22 @@ pub struct ProposerFactory { _phantom: PhantomData, } +impl Clone for ProposerFactory { + fn clone(&self) -> Self { + Self { + spawn_handle: self.spawn_handle.clone(), + client: self.client.clone(), + transaction_pool: self.transaction_pool.clone(), + metrics: self.metrics.clone(), + default_block_size_limit: self.default_block_size_limit, + soft_deadline_percent: self.soft_deadline_percent, + telemetry: self.telemetry.clone(), + include_proof_in_block_size_estimation: self.include_proof_in_block_size_estimation, + _phantom: self._phantom, + } + } +} + impl ProposerFactory { /// Create a new proposer factory. /// -- GitLab From cd91c6b782b60906597ed28c4e4a4fdddd8428c9 Mon Sep 17 00:00:00 2001 From: Matteo Muraca <56828990+muraca@users.noreply.github.com> Date: Thu, 22 Feb 2024 00:02:31 +0100 Subject: [PATCH 008/188] removed `pallet::getter` from example pallets (#3371) part of #3326 @ggwpez @kianenigma @shawntabrizi --------- Signed-off-by: Matteo Muraca Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- .../pallets/template/src/lib.rs | 1 - .../pallets/template/src/tests.rs | 4 ++-- prdoc/pr_3371.prdoc | 19 +++++++++++++++++++ .../node-template/pallets/template/src/lib.rs | 4 +--- .../pallets/template/src/tests.rs | 4 ++-- .../frame/examples/basic/src/benchmarking.rs | 2 +- substrate/frame/examples/basic/src/lib.rs | 14 +++----------- substrate/frame/examples/basic/src/tests.rs | 12 ++++++------ .../examples/kitchensink/src/benchmarking.rs | 2 +- .../frame/examples/kitchensink/src/lib.rs | 1 - .../frame/examples/offchain-worker/src/lib.rs | 12 +++++------- substrate/frame/examples/split/src/lib.rs | 2 +- 12 files changed, 41 insertions(+), 36 deletions(-) create mode 100644 prdoc/pr_3371.prdoc diff --git a/cumulus/parachain-template/pallets/template/src/lib.rs b/cumulus/parachain-template/pallets/template/src/lib.rs index 5f3252bfc3a..24226d6cf40 100644 --- a/cumulus/parachain-template/pallets/template/src/lib.rs +++ b/cumulus/parachain-template/pallets/template/src/lib.rs @@ -32,7 +32,6 @@ pub mod pallet { // The pallet's runtime storage items. // https://docs.substrate.io/v3/runtime/storage #[pallet::storage] - #[pallet::getter(fn something)] // Learn more about declaring storage items: // https://docs.substrate.io/v3/runtime/storage#declaring-storage-items pub type Something = StorageValue<_, u32>; diff --git a/cumulus/parachain-template/pallets/template/src/tests.rs b/cumulus/parachain-template/pallets/template/src/tests.rs index 527aec8ed00..9ad3076be2c 100644 --- a/cumulus/parachain-template/pallets/template/src/tests.rs +++ b/cumulus/parachain-template/pallets/template/src/tests.rs @@ -1,4 +1,4 @@ -use crate::{mock::*, Error}; +use crate::{mock::*, Error, Something}; use frame_support::{assert_noop, assert_ok}; #[test] @@ -7,7 +7,7 @@ fn it_works_for_default_value() { // Dispatch a signed extrinsic. assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42)); // Read pallet storage and assert an expected result. - assert_eq!(TemplateModule::something(), Some(42)); + assert_eq!(Something::::get(), Some(42)); }); } diff --git a/prdoc/pr_3371.prdoc b/prdoc/pr_3371.prdoc new file mode 100644 index 00000000000..605d540772f --- /dev/null +++ b/prdoc/pr_3371.prdoc @@ -0,0 +1,19 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: removed `pallet::getter` from example pallets + +doc: + - audience: Runtime Dev + description: | + This PR removes all the `pallet::getter` usages from the template pallets found in the Substrate and Cumulus template nodes, and from the Substrate example pallets. + The purpose is to discourage developers to use this macro, that is currently being removed and soon will be deprecated. + +crates: + - name: pallet-template + - name: pallet-parachain-template + - name: pallet-example-basic + - name: pallet-example-kitchensink + - name: pallet-example-offchain-worker + - name: pallet-example-split + diff --git a/substrate/bin/node-template/pallets/template/src/lib.rs b/substrate/bin/node-template/pallets/template/src/lib.rs index 4a2e53baa77..90dfe370145 100644 --- a/substrate/bin/node-template/pallets/template/src/lib.rs +++ b/substrate/bin/node-template/pallets/template/src/lib.rs @@ -90,9 +90,7 @@ pub mod pallet { /// /// In this template, we are declaring a storage item called `Something` that stores a single /// `u32` value. Learn more about runtime storage here: - /// The [`getter`] macro generates a function to conveniently retrieve the value from storage. #[pallet::storage] - #[pallet::getter(fn something)] pub type Something = StorageValue<_, u32>; /// Events that functions in this pallet can emit. @@ -187,7 +185,7 @@ pub mod pallet { let _who = ensure_signed(origin)?; // Read a value from storage. - match Pallet::::something() { + match Something::::get() { // Return an error if the value has not been set. None => Err(Error::::NoneValue.into()), Some(old) => { diff --git a/substrate/bin/node-template/pallets/template/src/tests.rs b/substrate/bin/node-template/pallets/template/src/tests.rs index 7c2b853ee4d..83e4bea7377 100644 --- a/substrate/bin/node-template/pallets/template/src/tests.rs +++ b/substrate/bin/node-template/pallets/template/src/tests.rs @@ -1,4 +1,4 @@ -use crate::{mock::*, Error, Event}; +use crate::{mock::*, Error, Event, Something}; use frame_support::{assert_noop, assert_ok}; #[test] @@ -9,7 +9,7 @@ fn it_works_for_default_value() { // Dispatch a signed extrinsic. assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42)); // Read pallet storage and assert an expected result. - assert_eq!(TemplateModule::something(), Some(42)); + assert_eq!(Something::::get(), Some(42)); // Assert that the correct event was deposited System::assert_last_event(Event::SomethingStored { something: 42, who: 1 }.into()); }); diff --git a/substrate/frame/examples/basic/src/benchmarking.rs b/substrate/frame/examples/basic/src/benchmarking.rs index 4b2ebb41fbd..65ca3089aba 100644 --- a/substrate/frame/examples/basic/src/benchmarking.rs +++ b/substrate/frame/examples/basic/src/benchmarking.rs @@ -48,7 +48,7 @@ mod benchmarks { set_dummy(RawOrigin::Root, value); // The execution phase is just running `set_dummy` extrinsic call // This is the optional benchmark verification phase, asserting certain states. - assert_eq!(Pallet::::dummy(), Some(value)) + assert_eq!(Dummy::::get(), Some(value)) } // An example method that returns a Result that can be called within a benchmark diff --git a/substrate/frame/examples/basic/src/lib.rs b/substrate/frame/examples/basic/src/lib.rs index dad4d01978f..12cadc969fd 100644 --- a/substrate/frame/examples/basic/src/lib.rs +++ b/substrate/frame/examples/basic/src/lib.rs @@ -286,9 +286,7 @@ pub mod pallet { let _sender = ensure_signed(origin)?; // Read the value of dummy from storage. - // let dummy = Self::dummy(); - // Will also work using the `::get` on the storage item type itself: - // let dummy = >::get(); + // let dummy = Dummy::::get(); // Calculate the new value. // let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by); @@ -381,20 +379,14 @@ pub mod pallet { // - `Foo::put(1); Foo::get()` returns `1`; // - `Foo::kill(); Foo::get()` returns `0` (u32::default()). #[pallet::storage] - // The getter attribute generate a function on `Pallet` placeholder: - // `fn getter_name() -> Type` for basic value items or - // `fn getter_name(key: KeyType) -> ValueType` for map items. - #[pallet::getter(fn dummy)] pub(super) type Dummy = StorageValue<_, T::Balance>; // A map that has enumerable entries. #[pallet::storage] - #[pallet::getter(fn bar)] pub(super) type Bar = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance>; // this one uses the query kind: `ValueQuery`, we'll demonstrate the usage of 'mutate' API. #[pallet::storage] - #[pallet::getter(fn foo)] pub(super) type Foo = StorageValue<_, T::Balance, ValueQuery>; #[pallet::storage] @@ -433,10 +425,10 @@ impl Pallet { fn accumulate_foo(origin: T::RuntimeOrigin, increase_by: T::Balance) -> DispatchResult { let _sender = ensure_signed(origin)?; - let prev = >::get(); + let prev = Foo::::get(); // Because Foo has 'default', the type of 'foo' in closure is the raw type instead of an // Option<> type. - let result = >::mutate(|foo| { + let result = Foo::::mutate(|foo| { *foo = foo.saturating_add(increase_by); *foo }); diff --git a/substrate/frame/examples/basic/src/tests.rs b/substrate/frame/examples/basic/src/tests.rs index 9434ace35ff..207e46e428d 100644 --- a/substrate/frame/examples/basic/src/tests.rs +++ b/substrate/frame/examples/basic/src/tests.rs @@ -119,25 +119,25 @@ fn it_works_for_optional_value() { // Check that GenesisBuilder works properly. let val1 = 42; let val2 = 27; - assert_eq!(Example::dummy(), Some(val1)); + assert_eq!(Dummy::::get(), Some(val1)); // Check that accumulate works when we have Some value in Dummy already. assert_ok!(Example::accumulate_dummy(RuntimeOrigin::signed(1), val2)); - assert_eq!(Example::dummy(), Some(val1 + val2)); + assert_eq!(Dummy::::get(), Some(val1 + val2)); // Check that accumulate works when we Dummy has None in it. >::on_initialize(2); assert_ok!(Example::accumulate_dummy(RuntimeOrigin::signed(1), val1)); - assert_eq!(Example::dummy(), Some(val1 + val2 + val1)); + assert_eq!(Dummy::::get(), Some(val1 + val2 + val1)); }); } #[test] fn it_works_for_default_value() { new_test_ext().execute_with(|| { - assert_eq!(Example::foo(), 24); + assert_eq!(Foo::::get(), 24); assert_ok!(Example::accumulate_foo(RuntimeOrigin::signed(1), 1)); - assert_eq!(Example::foo(), 25); + assert_eq!(Foo::::get(), 25); }); } @@ -146,7 +146,7 @@ fn set_dummy_works() { new_test_ext().execute_with(|| { let test_val = 133; assert_ok!(Example::set_dummy(RuntimeOrigin::root(), test_val.into())); - assert_eq!(Example::dummy(), Some(test_val)); + assert_eq!(Dummy::::get(), Some(test_val)); }); } diff --git a/substrate/frame/examples/kitchensink/src/benchmarking.rs b/substrate/frame/examples/kitchensink/src/benchmarking.rs index 24da581fc96..5f1d378e06f 100644 --- a/substrate/frame/examples/kitchensink/src/benchmarking.rs +++ b/substrate/frame/examples/kitchensink/src/benchmarking.rs @@ -51,7 +51,7 @@ mod benchmarks { set_foo(RawOrigin::Root, value, 10u128); // The execution phase is just running `set_foo` extrinsic call // This is the optional benchmark verification phase, asserting certain states. - assert_eq!(Pallet::::foo(), Some(value)) + assert_eq!(Foo::::get(), Some(value)) } // This line generates test cases for benchmarking, and could be run by: diff --git a/substrate/frame/examples/kitchensink/src/lib.rs b/substrate/frame/examples/kitchensink/src/lib.rs index 18429bc967d..b7425b0c084 100644 --- a/substrate/frame/examples/kitchensink/src/lib.rs +++ b/substrate/frame/examples/kitchensink/src/lib.rs @@ -125,7 +125,6 @@ pub mod pallet { #[pallet::storage] #[pallet::unbounded] // optional #[pallet::storage_prefix = "OtherFoo"] // optional - #[pallet::getter(fn foo)] // optional pub type Foo = StorageValue; #[pallet::type_value] diff --git a/substrate/frame/examples/offchain-worker/src/lib.rs b/substrate/frame/examples/offchain-worker/src/lib.rs index 6c1fa6ea8ec..d21c8b4cfd2 100644 --- a/substrate/frame/examples/offchain-worker/src/lib.rs +++ b/substrate/frame/examples/offchain-worker/src/lib.rs @@ -332,7 +332,6 @@ pub mod pallet { /// /// This is used to calculate average price, should have bounded size. #[pallet::storage] - #[pallet::getter(fn prices)] pub(super) type Prices = StorageValue<_, BoundedVec, ValueQuery>; /// Defines the block when next unsigned transaction will be accepted. @@ -341,7 +340,6 @@ pub mod pallet { /// we only allow one transaction every `T::UnsignedInterval` blocks. /// This storage entry defines when new transaction is going to be accepted. #[pallet::storage] - #[pallet::getter(fn next_unsigned_at)] pub(super) type NextUnsignedAt = StorageValue<_, BlockNumberFor, ValueQuery>; } @@ -479,7 +477,7 @@ impl Pallet { ) -> Result<(), &'static str> { // Make sure we don't fetch the price if unsigned transaction is going to be rejected // anyway. - let next_unsigned_at = >::get(); + let next_unsigned_at = NextUnsignedAt::::get(); if next_unsigned_at > block_number { return Err("Too early to send unsigned transaction") } @@ -513,7 +511,7 @@ impl Pallet { ) -> Result<(), &'static str> { // Make sure we don't fetch the price if unsigned transaction is going to be rejected // anyway. - let next_unsigned_at = >::get(); + let next_unsigned_at = NextUnsignedAt::::get(); if next_unsigned_at > block_number { return Err("Too early to send unsigned transaction") } @@ -543,7 +541,7 @@ impl Pallet { ) -> Result<(), &'static str> { // Make sure we don't fetch the price if unsigned transaction is going to be rejected // anyway. - let next_unsigned_at = >::get(); + let next_unsigned_at = NextUnsignedAt::::get(); if next_unsigned_at > block_number { return Err("Too early to send unsigned transaction") } @@ -664,7 +662,7 @@ impl Pallet { /// Calculate current average price. fn average_price() -> Option { - let prices = >::get(); + let prices = Prices::::get(); if prices.is_empty() { None } else { @@ -677,7 +675,7 @@ impl Pallet { new_price: &u32, ) -> TransactionValidity { // Now let's check if the transaction has any chance to succeed. - let next_unsigned_at = >::get(); + let next_unsigned_at = NextUnsignedAt::::get(); if &next_unsigned_at > block_number { return InvalidTransaction::Stale.into() } diff --git a/substrate/frame/examples/split/src/lib.rs b/substrate/frame/examples/split/src/lib.rs index 74d2e0cc24b..5245d90e390 100644 --- a/substrate/frame/examples/split/src/lib.rs +++ b/substrate/frame/examples/split/src/lib.rs @@ -107,7 +107,7 @@ pub mod pallet { let _who = ensure_signed(origin)?; // Read a value from storage. - match >::get() { + match Something::::get() { // Return an error if the value has not been set. None => return Err(Error::::NoneValue.into()), Some(old) => { -- GitLab From e76b244853c52d523e1d5c7a28948573df60df46 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 22 Feb 2024 01:35:01 +0100 Subject: [PATCH 009/188] [FRAME] Test for sane genesis default (#3412) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes https://github.com/paritytech/polkadot-sdk/issues/2713 --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- cumulus/pallets/aura-ext/src/lib.rs | 6 --- .../chains/relays/rococo/src/genesis.rs | 2 +- .../chains/relays/westend/src/genesis.rs | 2 +- prdoc/pr_3412.prdoc | 17 ++++++++ .../cli/tests/res/default_genesis_config.json | 8 +++- substrate/bin/node/testing/src/genesis.rs | 39 ++----------------- substrate/client/chain-spec/src/chain_spec.rs | 10 +---- .../chain-spec/src/genesis_config_builder.rs | 2 +- .../client/consensus/babe/rpc/src/lib.rs | 2 +- substrate/frame/babe/src/lib.rs | 6 +-- substrate/frame/session/src/lib.rs | 18 +-------- .../src/construct_runtime/expand/config.rs | 11 ++++++ substrate/frame/support/src/lib.rs | 2 +- .../primitives/consensus/babe/src/lib.rs | 6 +++ .../test-utils/runtime/src/genesismap.rs | 1 - substrate/test-utils/runtime/src/lib.rs | 2 +- 16 files changed, 55 insertions(+), 79 deletions(-) create mode 100644 prdoc/pr_3412.prdoc diff --git a/cumulus/pallets/aura-ext/src/lib.rs b/cumulus/pallets/aura-ext/src/lib.rs index 34a41557152..31b571816a0 100644 --- a/cumulus/pallets/aura-ext/src/lib.rs +++ b/cumulus/pallets/aura-ext/src/lib.rs @@ -117,12 +117,6 @@ pub mod pallet { impl BuildGenesisConfig for GenesisConfig { fn build(&self) { let authorities = Aura::::authorities(); - - assert!( - !authorities.is_empty(), - "AuRa authorities empty, maybe wrong order in `construct_runtime!`?", - ); - Authorities::::put(authorities); } } diff --git a/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/genesis.rs b/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/genesis.rs index 7db9679f1c3..55437645b05 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/genesis.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/genesis.rs @@ -78,7 +78,7 @@ pub fn genesis() -> Storage { }, babe: rococo_runtime::BabeConfig { authorities: Default::default(), - epoch_config: Some(rococo_runtime::BABE_GENESIS_EPOCH_CONFIG), + epoch_config: rococo_runtime::BABE_GENESIS_EPOCH_CONFIG, ..Default::default() }, sudo: rococo_runtime::SudoConfig { diff --git a/cumulus/parachains/integration-tests/emulated/chains/relays/westend/src/genesis.rs b/cumulus/parachains/integration-tests/emulated/chains/relays/westend/src/genesis.rs index 578b307dd93..700b80e63f6 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/relays/westend/src/genesis.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/relays/westend/src/genesis.rs @@ -94,7 +94,7 @@ pub fn genesis() -> Storage { }, babe: westend_runtime::BabeConfig { authorities: Default::default(), - epoch_config: Some(westend_runtime::BABE_GENESIS_EPOCH_CONFIG), + epoch_config: westend_runtime::BABE_GENESIS_EPOCH_CONFIG, ..Default::default() }, configuration: westend_runtime::ConfigurationConfig { config: get_host_config() }, diff --git a/prdoc/pr_3412.prdoc b/prdoc/pr_3412.prdoc new file mode 100644 index 00000000000..d68f05e45dc --- /dev/null +++ b/prdoc/pr_3412.prdoc @@ -0,0 +1,17 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "[FRAME] Add genesis test and remove some checks" + +doc: + - audience: Runtime Dev + description: | + The construct_runtime macro now generates a test to assert that all `GenesisConfig`s of all + pallets can be build within the runtime. This ensures that the `BuildGenesisConfig` runtime + API works. + Further, some checks from a few pallets were removed to make this pass. + +crates: + - name: pallet-babe + - name: pallet-aura-ext + - name: pallet-session diff --git a/substrate/bin/node/cli/tests/res/default_genesis_config.json b/substrate/bin/node/cli/tests/res/default_genesis_config.json index 1465a6497ca..e21fbb47da8 100644 --- a/substrate/bin/node/cli/tests/res/default_genesis_config.json +++ b/substrate/bin/node/cli/tests/res/default_genesis_config.json @@ -2,7 +2,13 @@ "system": {}, "babe": { "authorities": [], - "epochConfig": null + "epochConfig": { + "allowed_slots": "PrimaryAndSecondaryVRFSlots", + "c": [ + 1, + 4 + ] + } }, "indices": { "indices": [] diff --git a/substrate/bin/node/testing/src/genesis.rs b/substrate/bin/node/testing/src/genesis.rs index 6ec21fbe093..c79612d6844 100644 --- a/substrate/bin/node/testing/src/genesis.rs +++ b/substrate/bin/node/testing/src/genesis.rs @@ -20,9 +20,8 @@ use crate::keyring::*; use kitchensink_runtime::{ - constants::currency::*, AccountId, AssetsConfig, BabeConfig, BalancesConfig, GluttonConfig, - GrandpaConfig, IndicesConfig, RuntimeGenesisConfig, SessionConfig, SocietyConfig, StakerStatus, - StakingConfig, BABE_GENESIS_EPOCH_CONFIG, + constants::currency::*, AccountId, AssetsConfig, BalancesConfig, IndicesConfig, + RuntimeGenesisConfig, SessionConfig, SocietyConfig, StakerStatus, StakingConfig, }; use sp_keyring::Ed25519Keyring; use sp_runtime::Perbill; @@ -47,7 +46,6 @@ pub fn config_endowed(extra_endowed: Vec) -> RuntimeGenesisConfig { endowed.extend(extra_endowed.into_iter().map(|endowed| (endowed, 100 * DOLLARS))); RuntimeGenesisConfig { - system: Default::default(), indices: IndicesConfig { indices: vec![] }, balances: BalancesConfig { balances: endowed }, session: SessionConfig { @@ -69,39 +67,8 @@ pub fn config_endowed(extra_endowed: Vec) -> RuntimeGenesisConfig { invulnerables: vec![alice(), bob(), charlie()], ..Default::default() }, - babe: BabeConfig { - authorities: vec![], - epoch_config: Some(BABE_GENESIS_EPOCH_CONFIG), - ..Default::default() - }, - grandpa: GrandpaConfig { authorities: vec![], _config: Default::default() }, - beefy: Default::default(), - im_online: Default::default(), - authority_discovery: Default::default(), - democracy: Default::default(), - council: Default::default(), - technical_committee: Default::default(), - technical_membership: Default::default(), - elections: Default::default(), - sudo: Default::default(), - treasury: Default::default(), society: SocietyConfig { pot: 0 }, - vesting: Default::default(), assets: AssetsConfig { assets: vec![(9, alice(), true, 1)], ..Default::default() }, - pool_assets: Default::default(), - transaction_storage: Default::default(), - transaction_payment: Default::default(), - alliance: Default::default(), - alliance_motion: Default::default(), - nomination_pools: Default::default(), - safe_mode: Default::default(), - tx_pause: Default::default(), - glutton: GluttonConfig { - compute: Default::default(), - storage: Default::default(), - trash_data_count: Default::default(), - ..Default::default() - }, - mixnet: Default::default(), + ..Default::default() } } diff --git a/substrate/client/chain-spec/src/chain_spec.rs b/substrate/client/chain-spec/src/chain_spec.rs index fe8fcfda216..78e81e10d2b 100644 --- a/substrate/client/chain-spec/src/chain_spec.rs +++ b/substrate/client/chain-spec/src/chain_spec.rs @@ -1237,15 +1237,7 @@ mod tests { "TestName", "test", ChainType::Local, - move || substrate_test_runtime::RuntimeGenesisConfig { - babe: substrate_test_runtime::BabeConfig { - epoch_config: Some( - substrate_test_runtime::TEST_RUNTIME_BABE_EPOCH_CONFIGURATION, - ), - ..Default::default() - }, - ..Default::default() - }, + || Default::default(), Vec::new(), None, None, diff --git a/substrate/client/chain-spec/src/genesis_config_builder.rs b/substrate/client/chain-spec/src/genesis_config_builder.rs index 8766dd5c5ad..6b956316203 100644 --- a/substrate/client/chain-spec/src/genesis_config_builder.rs +++ b/substrate/client/chain-spec/src/genesis_config_builder.rs @@ -149,7 +149,7 @@ mod tests { ::new(substrate_test_runtime::wasm_binary_unwrap()) .get_default_config() .unwrap(); - let expected = r#"{"system":{},"babe":{"authorities":[],"epochConfig":null},"substrateTest":{"authorities":[]},"balances":{"balances":[]}}"#; + let expected = r#"{"babe": {"authorities": [], "epochConfig": {"allowed_slots": "PrimaryAndSecondaryVRFSlots", "c": [1, 4]}}, "balances": {"balances": []}, "substrateTest": {"authorities": []}, "system": {}}"#; assert_eq!(from_str::(expected).unwrap(), config); } diff --git a/substrate/client/consensus/babe/rpc/src/lib.rs b/substrate/client/consensus/babe/rpc/src/lib.rs index 8b183e7dfdc..a3e811baecf 100644 --- a/substrate/client/consensus/babe/rpc/src/lib.rs +++ b/substrate/client/consensus/babe/rpc/src/lib.rs @@ -258,7 +258,7 @@ mod tests { let request = r#"{"jsonrpc":"2.0","method":"babe_epochAuthorship","params": [],"id":1}"#; let (response, _) = api.raw_json_request(request, 1).await.unwrap(); - let expected = r#"{"jsonrpc":"2.0","result":{"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY":{"primary":[0],"secondary":[1,2,4],"secondary_vrf":[]}},"id":1}"#; + let expected = r#"{"jsonrpc":"2.0","result":{"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY":{"primary":[0],"secondary":[],"secondary_vrf":[1,2,4]}},"id":1}"#; assert_eq!(response, expected); } diff --git a/substrate/frame/babe/src/lib.rs b/substrate/frame/babe/src/lib.rs index a6e44390dbc..5fb107dde3b 100644 --- a/substrate/frame/babe/src/lib.rs +++ b/substrate/frame/babe/src/lib.rs @@ -323,7 +323,7 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - pub epoch_config: Option, + pub epoch_config: BabeEpochConfiguration, #[serde(skip)] pub _config: sp_std::marker::PhantomData, } @@ -333,9 +333,7 @@ pub mod pallet { fn build(&self) { SegmentIndex::::put(0); Pallet::::initialize_genesis_authorities(&self.authorities); - EpochConfig::::put( - self.epoch_config.clone().expect("epoch_config must not be None"), - ); + EpochConfig::::put(&self.epoch_config); } } diff --git a/substrate/frame/session/src/lib.rs b/substrate/frame/session/src/lib.rs index 178d43f596b..fc35cd6ddd8 100644 --- a/substrate/frame/session/src/lib.rs +++ b/substrate/frame/session/src/lib.rs @@ -460,27 +460,13 @@ pub mod pallet { ); self.keys.iter().map(|x| x.1.clone()).collect() }); - assert!( - !initial_validators_0.is_empty(), - "Empty validator set for session 0 in genesis block!" - ); let initial_validators_1 = T::SessionManager::new_session_genesis(1) .unwrap_or_else(|| initial_validators_0.clone()); - assert!( - !initial_validators_1.is_empty(), - "Empty validator set for session 1 in genesis block!" - ); let queued_keys: Vec<_> = initial_validators_1 - .iter() - .cloned() - .map(|v| { - ( - v.clone(), - Pallet::::load_keys(&v).expect("Validator in session 1 missing keys!"), - ) - }) + .into_iter() + .filter_map(|v| Pallet::::load_keys(&v).map(|k| (v, k))) .collect(); // Tell everyone about the genesis session keys diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs index ffe55bceb80..5613047359a 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs @@ -99,6 +99,17 @@ pub fn expand_outer_config( ::on_genesis(); } } + + /// Test the `Default` derive impl of the `RuntimeGenesisConfig`. + #[cfg(test)] + #[test] + fn test_genesis_config_builds() { + #scrate::__private::sp_io::TestExternalities::default().execute_with(|| { + ::build( + &RuntimeGenesisConfig::default() + ); + }); + } } } diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 8935acf4e2b..cd12da6de54 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -780,7 +780,7 @@ macro_rules! assert_err_with_weight { $crate::assert_err!($call.map(|_| ()).map_err(|e| e.error), $err); assert_eq!(dispatch_err_with_post.post_info.actual_weight, $weight); } else { - panic!("expected Err(_), got Ok(_).") + ::core::panic!("expected Err(_), got Ok(_).") } }; } diff --git a/substrate/primitives/consensus/babe/src/lib.rs b/substrate/primitives/consensus/babe/src/lib.rs index d6b2cdd55e0..ff0b4568226 100644 --- a/substrate/primitives/consensus/babe/src/lib.rs +++ b/substrate/primitives/consensus/babe/src/lib.rs @@ -256,6 +256,12 @@ pub struct BabeEpochConfiguration { pub allowed_slots: AllowedSlots, } +impl Default for BabeEpochConfiguration { + fn default() -> Self { + Self { c: (1, 4), allowed_slots: AllowedSlots::PrimaryAndSecondaryVRFSlots } + } +} + /// Verifies the equivocation proof by making sure that: both headers have /// different hashes, are targetting the same slot, and have valid signatures by /// the same authority. diff --git a/substrate/test-utils/runtime/src/genesismap.rs b/substrate/test-utils/runtime/src/genesismap.rs index 5ed9c8a6458..9e972886b37 100644 --- a/substrate/test-utils/runtime/src/genesismap.rs +++ b/substrate/test-utils/runtime/src/genesismap.rs @@ -124,7 +124,6 @@ impl GenesisStorageBuilder { .into_iter() .map(|x| (x.into(), 1)) .collect(), - epoch_config: Some(crate::TEST_RUNTIME_BABE_EPOCH_CONFIGURATION), ..Default::default() }, substrate_test: substrate_test_pallet::GenesisConfig { diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index 8bc6f72a82e..db9ff187b70 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -1291,7 +1291,7 @@ mod tests { let r = Vec::::decode(&mut &r[..]).unwrap(); let json = String::from_utf8(r.into()).expect("returned value is json. qed."); - let expected = r#"{"system":{},"babe":{"authorities":[],"epochConfig":null},"substrateTest":{"authorities":[]},"balances":{"balances":[]}}"#; + let expected = r#"{"system":{},"babe":{"authorities":[],"epochConfig":{"c":[1,4],"allowed_slots":"PrimaryAndSecondaryVRFSlots"}},"substrateTest":{"authorities":[]},"balances":{"balances":[]}}"#; assert_eq!(expected.to_string(), json); } -- GitLab From 60e537b95f2336dc598cb9ce49823316841ee3dd Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:22:31 +0700 Subject: [PATCH 010/188] Elastic scaling: use an assumed `CoreIndex` in `candidate-backing` (#3229) First step in implementing https://github.com/paritytech/polkadot-sdk/issues/3144 ### Summary of changes - switch statement `Table` candidate mapping from `ParaId` to `CoreIndex` - introduce experimental `InjectCoreIndex` node feature. - determine and assume a `CoreIndex` for a candidate based on statement validator index. If the signature is valid it means validator controls the validator that index and we can easily map it to a validator group/core. - introduce a temporary provisioner fix until we fully enable elastic scaling in the subystem. The fix ensures we don't fetch the same backable candidate when calling `get_backable_candidate` for each core. TODO: - [x] fix backing tests - [x] fix statement table tests - [x] add new test --------- Signed-off-by: Andrei Sandu Signed-off-by: alindima Co-authored-by: alindima --- Cargo.lock | 3 + polkadot/node/core/backing/Cargo.toml | 1 + polkadot/node/core/backing/src/error.rs | 3 + polkadot/node/core/backing/src/lib.rs | 285 ++++++++++++++---- polkadot/node/core/backing/src/tests/mod.rs | 128 +++++++- .../src/tests/prospective_parachains.rs | 34 ++- polkadot/node/core/provisioner/src/lib.rs | 12 +- polkadot/primitives/Cargo.toml | 2 + polkadot/primitives/src/v6/mod.rs | 27 +- polkadot/primitives/src/vstaging/mod.rs | 6 +- polkadot/statement-table/Cargo.toml | 1 + polkadot/statement-table/src/generic.rs | 50 ++- polkadot/statement-table/src/lib.rs | 6 +- 13 files changed, 462 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93ee9cc99c4..950b4e0889a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12490,6 +12490,7 @@ dependencies = [ "polkadot-primitives-test-helpers", "polkadot-statement-table", "sc-keystore", + "schnellru", "sp-application-crypto", "sp-core", "sp-keyring", @@ -13159,6 +13160,7 @@ version = "7.0.0" dependencies = [ "bitvec", "hex-literal", + "log", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain-primitives", @@ -13556,6 +13558,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "sp-core", + "tracing-gum", ] [[package]] diff --git a/polkadot/node/core/backing/Cargo.toml b/polkadot/node/core/backing/Cargo.toml index b0cf041e38d..f71b8df80dd 100644 --- a/polkadot/node/core/backing/Cargo.toml +++ b/polkadot/node/core/backing/Cargo.toml @@ -22,6 +22,7 @@ bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } gum = { package = "tracing-gum", path = "../../gum" } thiserror = { workspace = true } fatality = "0.0.6" +schnellru = "0.2.1" [dev-dependencies] sp-core = { path = "../../../../substrate/primitives/core" } diff --git a/polkadot/node/core/backing/src/error.rs b/polkadot/node/core/backing/src/error.rs index 1b00a62510b..64955a39396 100644 --- a/polkadot/node/core/backing/src/error.rs +++ b/polkadot/node/core/backing/src/error.rs @@ -48,6 +48,9 @@ pub enum Error { #[error("Candidate is not found")] CandidateNotFound, + #[error("CoreIndex cannot be determined for a candidate")] + CoreIndexUnavailable, + #[error("Signature is invalid")] InvalidSignature, diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index 98bbd6232ad..cc192607cea 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -70,13 +70,14 @@ use std::{ sync::Arc, }; -use bitvec::vec::BitVec; +use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; use futures::{ channel::{mpsc, oneshot}, future::BoxFuture, stream::FuturesOrdered, FutureExt, SinkExt, StreamExt, TryFutureExt, }; +use schnellru::{ByLength, LruMap}; use error::{Error, FatalResult}; use polkadot_node_primitives::{ @@ -104,10 +105,12 @@ use polkadot_node_subsystem_util::{ Validator, }; use polkadot_primitives::{ + vstaging::{node_features::FeatureIndex, NodeFeatures}, BackedCandidate, CandidateCommitments, CandidateHash, CandidateReceipt, - CommittedCandidateReceipt, CoreIndex, CoreState, ExecutorParams, Hash, Id as ParaId, - PersistedValidationData, PvfExecKind, SigningContext, ValidationCode, ValidatorId, - ValidatorIndex, ValidatorSignature, ValidityAttestation, + CommittedCandidateReceipt, CoreIndex, CoreState, ExecutorParams, GroupIndex, GroupRotationInfo, + Hash, Id as ParaId, IndexedVec, PersistedValidationData, PvfExecKind, SessionIndex, + SigningContext, ValidationCode, ValidatorId, ValidatorIndex, ValidatorSignature, + ValidityAttestation, }; use sp_keystore::KeystorePtr; use statement_table::{ @@ -118,7 +121,7 @@ use statement_table::{ }, Config as TableConfig, Context as TableContextTrait, Table, }; -use util::vstaging::get_disabled_validators_with_fallback; +use util::{runtime::request_node_features, vstaging::get_disabled_validators_with_fallback}; mod error; @@ -209,7 +212,9 @@ struct PerRelayParentState { /// The hash of the relay parent on top of which this job is doing it's work. parent: Hash, /// The `ParaId` assigned to the local validator at this relay parent. - assignment: Option, + assigned_para: Option, + /// The `CoreIndex` assigned to the local validator at this relay parent. + assigned_core: Option, /// The candidates that are backed by enough validators in their group, by hash. backed: HashSet, /// The table of candidates and statements under this relay-parent. @@ -224,6 +229,15 @@ struct PerRelayParentState { fallbacks: HashMap, /// The minimum backing votes threshold. minimum_backing_votes: u32, + /// If true, we're appending extra bits in the BackedCandidate validator indices bitfield, + /// which represent the assigned core index. True if ElasticScalingMVP is enabled. + inject_core_index: bool, + /// The core states for all cores. + cores: Vec, + /// The validator index -> group mapping at this relay parent. + validator_to_group: Arc>>, + /// The associated group rotation information. + group_rotation_info: GroupRotationInfo, } struct PerCandidateState { @@ -275,6 +289,9 @@ struct State { /// This is guaranteed to have an entry for each candidate with a relay parent in the implicit /// or explicit view for which a `Seconded` statement has been successfully imported. per_candidate: HashMap, + /// Cache the per-session Validator->Group mapping. + validator_to_group_cache: + LruMap>>>, /// A cloneable sender which is dispatched to background candidate validation tasks to inform /// the main task of the result. background_validation_tx: mpsc::Sender<(Hash, ValidatedCandidateCommand)>, @@ -292,6 +309,7 @@ impl State { per_leaf: HashMap::default(), per_relay_parent: HashMap::default(), per_candidate: HashMap::new(), + validator_to_group_cache: LruMap::new(ByLength::new(2)), background_validation_tx, keystore, } @@ -379,10 +397,10 @@ struct AttestingData { backing: Vec, } -#[derive(Default)] +#[derive(Default, Debug)] struct TableContext { validator: Option, - groups: HashMap>, + groups: HashMap>, validators: Vec, disabled_validators: Vec, } @@ -404,7 +422,7 @@ impl TableContext { impl TableContextTrait for TableContext { type AuthorityId = ValidatorIndex; type Digest = CandidateHash; - type GroupId = ParaId; + type GroupId = CoreIndex; type Signature = ValidatorSignature; type Candidate = CommittedCandidateReceipt; @@ -412,15 +430,11 @@ impl TableContextTrait for TableContext { candidate.hash() } - fn candidate_group(candidate: &CommittedCandidateReceipt) -> ParaId { - candidate.descriptor().para_id + fn is_member_of(&self, authority: &ValidatorIndex, core: &CoreIndex) -> bool { + self.groups.get(core).map_or(false, |g| g.iter().any(|a| a == authority)) } - fn is_member_of(&self, authority: &ValidatorIndex, group: &ParaId) -> bool { - self.groups.get(group).map_or(false, |g| g.iter().any(|a| a == authority)) - } - - fn get_group_size(&self, group: &ParaId) -> Option { + fn get_group_size(&self, group: &CoreIndex) -> Option { self.groups.get(group).map(|g| g.len()) } } @@ -442,19 +456,20 @@ fn primitive_statement_to_table(s: &SignedFullStatementWithPVD) -> TableSignedSt fn table_attested_to_backed( attested: TableAttestedCandidate< - ParaId, + CoreIndex, CommittedCandidateReceipt, ValidatorIndex, ValidatorSignature, >, table_context: &TableContext, + inject_core_index: bool, ) -> Option { - let TableAttestedCandidate { candidate, validity_votes, group_id: para_id } = attested; + let TableAttestedCandidate { candidate, validity_votes, group_id: core_index } = attested; let (ids, validity_votes): (Vec<_>, Vec) = validity_votes.into_iter().map(|(id, vote)| (id, vote.into())).unzip(); - let group = table_context.groups.get(¶_id)?; + let group = table_context.groups.get(&core_index)?; let mut validator_indices = BitVec::with_capacity(group.len()); @@ -479,6 +494,12 @@ fn table_attested_to_backed( } vote_positions.sort_by_key(|(_orig, pos_in_group)| *pos_in_group); + if inject_core_index { + let core_index_to_inject: BitVec = + BitVec::from_vec(vec![core_index.0 as u8]); + validator_indices.extend(core_index_to_inject); + } + Some(BackedCandidate { candidate, validity_votes: vote_positions @@ -971,7 +992,14 @@ async fn handle_active_leaves_update( // construct a `PerRelayParent` from the runtime API // and insert it. - let per = construct_per_relay_parent_state(ctx, maybe_new, &state.keystore, mode).await?; + let per = construct_per_relay_parent_state( + ctx, + maybe_new, + &state.keystore, + &mut state.validator_to_group_cache, + mode, + ) + .await?; if let Some(per) = per { state.per_relay_parent.insert(maybe_new, per); @@ -981,31 +1009,112 @@ async fn handle_active_leaves_update( Ok(()) } +macro_rules! try_runtime_api { + ($x: expr) => { + match $x { + Ok(x) => x, + Err(err) => { + // Only bubble up fatal errors. + error::log_error(Err(Into::::into(err).into()))?; + + // We can't do candidate validation work if we don't have the + // requisite runtime API data. But these errors should not take + // down the node. + return Ok(None) + }, + } + }; +} + +fn core_index_from_statement( + validator_to_group: &IndexedVec>, + group_rotation_info: &GroupRotationInfo, + cores: &[CoreState], + statement: &SignedFullStatementWithPVD, +) -> Option { + let compact_statement = statement.as_unchecked(); + let candidate_hash = CandidateHash(*compact_statement.unchecked_payload().candidate_hash()); + + let n_cores = cores.len(); + + gum::trace!( + target:LOG_TARGET, + ?group_rotation_info, + ?statement, + ?validator_to_group, + n_cores = ?cores.len(), + ?candidate_hash, + "Extracting core index from statement" + ); + + let statement_validator_index = statement.validator_index(); + let Some(Some(group_index)) = validator_to_group.get(statement_validator_index) else { + gum::debug!( + target: LOG_TARGET, + ?group_rotation_info, + ?statement, + ?validator_to_group, + n_cores = ?cores.len() , + ?candidate_hash, + "Invalid validator index: {:?}", + statement_validator_index + ); + return None + }; + + // First check if the statement para id matches the core assignment. + let core_index = group_rotation_info.core_for_group(*group_index, n_cores); + + if core_index.0 as usize > n_cores { + gum::warn!(target: LOG_TARGET, ?candidate_hash, ?core_index, n_cores, "Invalid CoreIndex"); + return None + } + + if let StatementWithPVD::Seconded(candidate, _pvd) = statement.payload() { + let candidate_para_id = candidate.descriptor.para_id; + let assigned_para_id = match &cores[core_index.0 as usize] { + CoreState::Free => { + gum::debug!(target: LOG_TARGET, ?candidate_hash, "Invalid CoreIndex, core is not assigned to any para_id"); + return None + }, + CoreState::Occupied(occupied) => + if let Some(next) = &occupied.next_up_on_available { + next.para_id + } else { + return None + }, + CoreState::Scheduled(scheduled) => scheduled.para_id, + }; + + if assigned_para_id != candidate_para_id { + gum::debug!( + target: LOG_TARGET, + ?candidate_hash, + ?core_index, + ?assigned_para_id, + ?candidate_para_id, + "Invalid CoreIndex, core is assigned to a different para_id" + ); + return None + } + return Some(core_index) + } else { + return Some(core_index) + } +} + /// Load the data necessary to do backing work on top of a relay-parent. #[overseer::contextbounds(CandidateBacking, prefix = self::overseer)] async fn construct_per_relay_parent_state( ctx: &mut Context, relay_parent: Hash, keystore: &KeystorePtr, + validator_to_group_cache: &mut LruMap< + SessionIndex, + Arc>>, + >, mode: ProspectiveParachainsMode, ) -> Result, Error> { - macro_rules! try_runtime_api { - ($x: expr) => { - match $x { - Ok(x) => x, - Err(err) => { - // Only bubble up fatal errors. - error::log_error(Err(Into::::into(err).into()))?; - - // We can't do candidate validation work if we don't have the - // requisite runtime API data. But these errors should not take - // down the node. - return Ok(None) - }, - } - }; - } - let parent = relay_parent; let (session_index, validators, groups, cores) = futures::try_join!( @@ -1020,6 +1129,16 @@ async fn construct_per_relay_parent_state( .map_err(Error::JoinMultiple)?; let session_index = try_runtime_api!(session_index); + + let inject_core_index = request_node_features(parent, session_index, ctx.sender()) + .await? + .unwrap_or(NodeFeatures::EMPTY) + .get(FeatureIndex::ElasticScalingMVP as usize) + .map(|b| *b) + .unwrap_or(false); + + gum::debug!(target: LOG_TARGET, inject_core_index, ?parent, "New state"); + let validators: Vec<_> = try_runtime_api!(validators); let (validator_groups, group_rotation_info) = try_runtime_api!(groups); let cores = try_runtime_api!(cores); @@ -1055,18 +1174,24 @@ async fn construct_per_relay_parent_state( }, }; - let mut groups = HashMap::new(); let n_cores = cores.len(); - let mut assignment = None; - for (idx, core) in cores.into_iter().enumerate() { + let mut groups = HashMap::>::new(); + let mut assigned_core = None; + let mut assigned_para = None; + + for (idx, core) in cores.iter().enumerate() { let core_para_id = match core { CoreState::Scheduled(scheduled) => scheduled.para_id, CoreState::Occupied(occupied) => if mode.is_enabled() { // Async backing makes it legal to build on top of // occupied core. - occupied.candidate_descriptor.para_id + if let Some(next) = &occupied.next_up_on_available { + next.para_id + } else { + continue + } } else { continue }, @@ -1077,11 +1202,27 @@ async fn construct_per_relay_parent_state( let group_index = group_rotation_info.group_for_core(core_index, n_cores); if let Some(g) = validator_groups.get(group_index.0 as usize) { if validator.as_ref().map_or(false, |v| g.contains(&v.index())) { - assignment = Some(core_para_id); + assigned_para = Some(core_para_id); + assigned_core = Some(core_index); } - groups.insert(core_para_id, g.clone()); + groups.insert(core_index, g.clone()); } } + gum::debug!(target: LOG_TARGET, ?groups, "TableContext"); + + let validator_to_group = validator_to_group_cache + .get_or_insert(session_index, || { + let mut vector = vec![None; validators.len()]; + + for (group_idx, validator_group) in validator_groups.iter().enumerate() { + for validator in validator_group { + vector[validator.0 as usize] = Some(GroupIndex(group_idx as u32)); + } + } + + Arc::new(IndexedVec::<_, _>::from(vector)) + }) + .expect("Just inserted"); let table_context = TableContext { validator, groups, validators, disabled_validators }; let table_config = TableConfig { @@ -1094,7 +1235,8 @@ async fn construct_per_relay_parent_state( Ok(Some(PerRelayParentState { prospective_parachains_mode: mode, parent, - assignment, + assigned_core, + assigned_para, backed: HashSet::new(), table: Table::new(table_config), table_context, @@ -1102,6 +1244,10 @@ async fn construct_per_relay_parent_state( awaiting_validation: HashSet::new(), fallbacks: HashMap::new(), minimum_backing_votes, + inject_core_index, + cores, + validator_to_group: validator_to_group.clone(), + group_rotation_info, })) } @@ -1519,15 +1665,16 @@ async fn import_statement( per_candidate: &mut HashMap, statement: &SignedFullStatementWithPVD, ) -> Result, Error> { + let candidate_hash = statement.payload().candidate_hash(); + gum::debug!( target: LOG_TARGET, statement = ?statement.payload().to_compact(), validator_index = statement.validator_index().0, + ?candidate_hash, "Importing statement", ); - let candidate_hash = statement.payload().candidate_hash(); - // If this is a new candidate (statement is 'seconded' and candidate is unknown), // we need to create an entry in the `PerCandidateState` map. // @@ -1593,7 +1740,15 @@ async fn import_statement( let stmt = primitive_statement_to_table(statement); - Ok(rp_state.table.import_statement(&rp_state.table_context, stmt)) + let core = core_index_from_statement( + &rp_state.validator_to_group, + &rp_state.group_rotation_info, + &rp_state.cores, + statement, + ) + .ok_or(Error::CoreIndexUnavailable)?; + + Ok(rp_state.table.import_statement(&rp_state.table_context, core, stmt)) } /// Handles a summary received from [`import_statement`] and dispatches `Backed` notifications and @@ -1615,7 +1770,11 @@ async fn post_import_statement_actions( // `HashSet::insert` returns true if the thing wasn't in there already. if rp_state.backed.insert(candidate_hash) { - if let Some(backed) = table_attested_to_backed(attested, &rp_state.table_context) { + if let Some(backed) = table_attested_to_backed( + attested, + &rp_state.table_context, + rp_state.inject_core_index, + ) { let para_id = backed.candidate.descriptor.para_id; gum::debug!( target: LOG_TARGET, @@ -1654,8 +1813,14 @@ async fn post_import_statement_actions( ); ctx.send_unbounded_message(message); } + } else { + gum::debug!(target: LOG_TARGET, ?candidate_hash, "Cannot get BackedCandidate"); } + } else { + gum::debug!(target: LOG_TARGET, ?candidate_hash, "Candidate already known"); } + } else { + gum::debug!(target: LOG_TARGET, "No attested candidate"); } issue_new_misbehaviors(ctx, rp_state.parent, &mut rp_state.table); @@ -1859,9 +2024,10 @@ async fn maybe_validate_and_import( let candidate_hash = summary.candidate; - if Some(summary.group_id) != rp_state.assignment { + if Some(summary.group_id) != rp_state.assigned_core { return Ok(()) } + let attesting = match statement.payload() { StatementWithPVD::Seconded(receipt, _) => { let attesting = AttestingData { @@ -2004,10 +2170,11 @@ async fn handle_second_message( } // Sanity check that candidate is from our assignment. - if Some(candidate.descriptor().para_id) != rp_state.assignment { + if Some(candidate.descriptor().para_id) != rp_state.assigned_para { gum::debug!( target: LOG_TARGET, - our_assignment = ?rp_state.assignment, + our_assignment_core = ?rp_state.assigned_core, + our_assignment_para = ?rp_state.assigned_para, collation = ?candidate.descriptor().para_id, "Subsystem asked to second for para outside of our assignment", ); @@ -2015,6 +2182,14 @@ async fn handle_second_message( return Ok(()) } + gum::debug!( + target: LOG_TARGET, + our_assignment_core = ?rp_state.assigned_core, + our_assignment_para = ?rp_state.assigned_para, + collation = ?candidate.descriptor().para_id, + "Current assignments vs collation", + ); + // If the message is a `CandidateBackingMessage::Second`, sign and dispatch a // Seconded statement only if we have not signed a Valid statement for the requested candidate. // @@ -2087,7 +2262,13 @@ fn handle_get_backed_candidates_message( &rp_state.table_context, rp_state.minimum_backing_votes, ) - .and_then(|attested| table_attested_to_backed(attested, &rp_state.table_context)) + .and_then(|attested| { + table_attested_to_backed( + attested, + &rp_state.table_context, + rp_state.inject_core_index, + ) + }) }) .collect(); diff --git a/polkadot/node/core/backing/src/tests/mod.rs b/polkadot/node/core/backing/src/tests/mod.rs index 1957f4e19c5..7223f1e1dfb 100644 --- a/polkadot/node/core/backing/src/tests/mod.rs +++ b/polkadot/node/core/backing/src/tests/mod.rs @@ -65,13 +65,14 @@ fn dummy_pvd() -> PersistedValidationData { } } -struct TestState { +pub(crate) struct TestState { chain_ids: Vec, keystore: KeystorePtr, validators: Vec, validator_public: Vec, validation_data: PersistedValidationData, validator_groups: (Vec>, GroupRotationInfo), + validator_to_group: IndexedVec>, availability_cores: Vec, head_data: HashMap, signing_context: SigningContext, @@ -114,6 +115,11 @@ impl Default for TestState { .into_iter() .map(|g| g.into_iter().map(ValidatorIndex).collect()) .collect(); + let validator_to_group: IndexedVec<_, _> = + vec![Some(0), Some(1), Some(0), Some(0), None, Some(0)] + .into_iter() + .map(|x| x.map(|x| GroupIndex(x))) + .collect(); let group_rotation_info = GroupRotationInfo { session_start_block: 0, group_rotation_frequency: 100, now: 1 }; @@ -143,6 +149,7 @@ impl Default for TestState { validators, validator_public, validator_groups: (validator_groups, group_rotation_info), + validator_to_group, availability_cores, head_data, validation_data, @@ -285,6 +292,16 @@ async fn test_startup(virtual_overseer: &mut VirtualOverseer, test_state: &TestS } ); + // Node features request from runtime: all features are disabled. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(_parent, RuntimeApiRequest::NodeFeatures(_session_index, tx)) + ) => { + tx.send(Ok(Default::default())).unwrap(); + } + ); + // Check if subsystem job issues a request for the minimum backing votes. assert_matches!( virtual_overseer.recv().await, @@ -639,6 +656,107 @@ fn backing_works() { }); } +#[test] +fn extract_core_index_from_statement_works() { + let test_state = TestState::default(); + + let pov_a = PoV { block_data: BlockData(vec![42, 43, 44]) }; + let pvd_a = dummy_pvd(); + let validation_code_a = ValidationCode(vec![1, 2, 3]); + + let pov_hash = pov_a.hash(); + + let mut candidate = TestCandidateBuilder { + para_id: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_hash, + erasure_root: make_erasure_root(&test_state, pov_a.clone(), pvd_a.clone()), + persisted_validation_data_hash: pvd_a.hash(), + validation_code: validation_code_a.0.clone(), + ..Default::default() + } + .build(); + + let public2 = Keystore::sr25519_generate_new( + &*test_state.keystore, + ValidatorId::ID, + Some(&test_state.validators[2].to_seed()), + ) + .expect("Insert key into keystore"); + + let signed_statement_1 = SignedFullStatementWithPVD::sign( + &test_state.keystore, + StatementWithPVD::Seconded(candidate.clone(), pvd_a.clone()), + &test_state.signing_context, + ValidatorIndex(2), + &public2.into(), + ) + .ok() + .flatten() + .expect("should be signed"); + + let public1 = Keystore::sr25519_generate_new( + &*test_state.keystore, + ValidatorId::ID, + Some(&test_state.validators[1].to_seed()), + ) + .expect("Insert key into keystore"); + + let signed_statement_2 = SignedFullStatementWithPVD::sign( + &test_state.keystore, + StatementWithPVD::Seconded(candidate.clone(), pvd_a.clone()), + &test_state.signing_context, + ValidatorIndex(1), + &public1.into(), + ) + .ok() + .flatten() + .expect("should be signed"); + + candidate.descriptor.para_id = test_state.chain_ids[1]; + + let signed_statement_3 = SignedFullStatementWithPVD::sign( + &test_state.keystore, + StatementWithPVD::Seconded(candidate, pvd_a.clone()), + &test_state.signing_context, + ValidatorIndex(1), + &public1.into(), + ) + .ok() + .flatten() + .expect("should be signed"); + + let core_index_1 = core_index_from_statement( + &test_state.validator_to_group, + &test_state.validator_groups.1, + &test_state.availability_cores, + &signed_statement_1, + ) + .unwrap(); + + assert_eq!(core_index_1, CoreIndex(0)); + + let core_index_2 = core_index_from_statement( + &test_state.validator_to_group, + &test_state.validator_groups.1, + &test_state.availability_cores, + &signed_statement_2, + ); + + // Must be none, para_id in descriptor is different than para assigned to core + assert_eq!(core_index_2, None); + + let core_index_3 = core_index_from_statement( + &test_state.validator_to_group, + &test_state.validator_groups.1, + &test_state.availability_cores, + &signed_statement_3, + ) + .unwrap(); + + assert_eq!(core_index_3, CoreIndex(1)); +} + #[test] fn backing_works_while_validation_ongoing() { let test_state = TestState::default(); @@ -1422,7 +1540,7 @@ fn backing_works_after_failed_validation() { fn candidate_backing_reorders_votes() { use sp_core::Encode; - let para_id = ParaId::from(10); + let core_idx = CoreIndex(10); let validators = vec![ Sr25519Keyring::Alice, Sr25519Keyring::Bob, @@ -1436,7 +1554,7 @@ fn candidate_backing_reorders_votes() { let validator_groups = { let mut validator_groups = HashMap::new(); validator_groups - .insert(para_id, vec![0, 1, 2, 3, 4, 5].into_iter().map(ValidatorIndex).collect()); + .insert(core_idx, vec![0, 1, 2, 3, 4, 5].into_iter().map(ValidatorIndex).collect()); validator_groups }; @@ -1466,10 +1584,10 @@ fn candidate_backing_reorders_votes() { (ValidatorIndex(3), fake_attestation(3)), (ValidatorIndex(1), fake_attestation(1)), ], - group_id: para_id, + group_id: core_idx, }; - let backed = table_attested_to_backed(attested, &table_context).unwrap(); + let backed = table_attested_to_backed(attested, &table_context, false).unwrap(); let expected_bitvec = { let mut validator_indices = BitVec::::with_capacity(6); diff --git a/polkadot/node/core/backing/src/tests/prospective_parachains.rs b/polkadot/node/core/backing/src/tests/prospective_parachains.rs index 578f21bef66..94310d2aa16 100644 --- a/polkadot/node/core/backing/src/tests/prospective_parachains.rs +++ b/polkadot/node/core/backing/src/tests/prospective_parachains.rs @@ -185,6 +185,16 @@ async fn activate_leaf( } ); + // Node features request from runtime: all features are disabled. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(parent, RuntimeApiRequest::NodeFeatures(_session_index, tx)) + ) if parent == hash => { + tx.send(Ok(Default::default())).unwrap(); + } + ); + // Check if subsystem job issues a request for the minimum backing votes. assert_matches!( virtual_overseer.recv().await, @@ -305,10 +315,11 @@ async fn assert_hypothetical_frontier_requests( ) => { let idx = match expected_requests.iter().position(|r| r.0 == request) { Some(idx) => idx, - None => panic!( + None => + panic!( "unexpected hypothetical frontier request, no match found for {:?}", request - ), + ), }; let resp = std::mem::take(&mut expected_requests[idx].1); tx.send(resp).unwrap(); @@ -1268,6 +1279,7 @@ fn concurrent_dependent_candidates() { let statement_b = CandidateBackingMessage::Statement(leaf_parent, signed_b.clone()); virtual_overseer.send(FromOrchestra::Communication { msg: statement_a }).await; + // At this point the subsystem waits for response, the previous message is received, // send a second one without blocking. let _ = virtual_overseer @@ -1388,7 +1400,19 @@ fn concurrent_dependent_candidates() { assert_eq!(sess_idx, 1); tx.send(Ok(Some(ExecutorParams::default()))).unwrap(); }, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _parent, + RuntimeApiRequest::ValidatorGroups(tx), + )) => { + tx.send(Ok(test_state.validator_groups.clone())).unwrap(); + }, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _parent, + RuntimeApiRequest::AvailabilityCores(tx), + )) => { + tx.send(Ok(test_state.availability_cores.clone())).unwrap(); + }, _ => panic!("unexpected message received from overseer: {:?}", msg), } } @@ -1419,7 +1443,6 @@ fn seconding_sanity_check_occupy_same_depth() { let leaf_parent = get_parent_hash(leaf_hash); let activated = new_leaf(leaf_hash, LEAF_BLOCK_NUMBER); - let min_block_number = LEAF_BLOCK_NUMBER - LEAF_ANCESTRY_LEN; let min_relay_parents = vec![(para_id_a, min_block_number), (para_id_b, min_block_number)]; let test_leaf_a = TestLeaf { activated, min_relay_parents }; @@ -1555,13 +1578,14 @@ fn occupied_core_assignment() { const LEAF_A_BLOCK_NUMBER: BlockNumber = 100; const LEAF_A_ANCESTRY_LEN: BlockNumber = 3; let para_id = test_state.chain_ids[0]; + let previous_para_id = test_state.chain_ids[1]; // Set the core state to occupied. let mut candidate_descriptor = ::test_helpers::dummy_candidate_descriptor(Hash::zero()); - candidate_descriptor.para_id = para_id; + candidate_descriptor.para_id = previous_para_id; test_state.availability_cores[0] = CoreState::Occupied(OccupiedCore { group_responsible: Default::default(), - next_up_on_available: None, + next_up_on_available: Some(ScheduledCore { para_id, collator: None }), occupied_since: 100_u32, time_out_at: 200_u32, next_up_on_time_out: None, diff --git a/polkadot/node/core/provisioner/src/lib.rs b/polkadot/node/core/provisioner/src/lib.rs index 51f768d782e..d98f6ebfe42 100644 --- a/polkadot/node/core/provisioner/src/lib.rs +++ b/polkadot/node/core/provisioner/src/lib.rs @@ -681,10 +681,17 @@ async fn request_backable_candidates( CoreState::Free => continue, }; + // We should be calling this once per para rather than per core. + // TODO: Will be fixed in https://github.com/paritytech/polkadot-sdk/pull/3233. + // For now, at least make sure we don't supply the same candidate multiple times in case a + // para has multiple cores scheduled. let response = get_backable_candidate(relay_parent, para_id, required_path, sender).await?; - match response { - Some((hash, relay_parent)) => selected_candidates.push((hash, relay_parent)), + Some((hash, relay_parent)) => { + if !selected_candidates.iter().any(|bc| &(hash, relay_parent) == bc) { + selected_candidates.push((hash, relay_parent)) + } + }, None => { gum::debug!( target: LOG_TARGET, @@ -726,6 +733,7 @@ async fn select_candidates( ) .await?, }; + gum::debug!(target: LOG_TARGET, ?selected_candidates, "Got backable candidates"); // now get the backed candidates corresponding to these candidate receipts let (tx, rx) = oneshot::channel(); diff --git a/polkadot/primitives/Cargo.toml b/polkadot/primitives/Cargo.toml index 58d3d100161..e63fb621c78 100644 --- a/polkadot/primitives/Cargo.toml +++ b/polkadot/primitives/Cargo.toml @@ -14,6 +14,7 @@ bitvec = { version = "1.0.0", default-features = false, features = ["alloc", "se hex-literal = "0.4.1" parity-scale-codec = { version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive", "serde"] } +log = { workspace = true, default-features = false } serde = { features = ["alloc", "derive"], workspace = true } application-crypto = { package = "sp-application-crypto", path = "../../substrate/primitives/application-crypto", default-features = false, features = ["serde"] } @@ -38,6 +39,7 @@ std = [ "application-crypto/std", "bitvec/std", "inherents/std", + "log/std", "parity-scale-codec/std", "polkadot-core-primitives/std", "polkadot-parachain-primitives/std", diff --git a/polkadot/primitives/src/v6/mod.rs b/polkadot/primitives/src/v6/mod.rs index 4938d20d2d1..538eb385584 100644 --- a/polkadot/primitives/src/v6/mod.rs +++ b/polkadot/primitives/src/v6/mod.rs @@ -72,6 +72,7 @@ pub use metrics::{ /// The key type ID for a collator key. pub const COLLATOR_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"coll"); +const LOG_TARGET: &str = "runtime::primitives"; mod collator_app { use application_crypto::{app_crypto, sr25519}; @@ -746,17 +747,29 @@ impl BackedCandidate { /// /// Returns either an error, indicating that one of the signatures was invalid or that the index /// was out-of-bounds, or the number of signatures checked. -pub fn check_candidate_backing + Clone + Encode>( +pub fn check_candidate_backing + Clone + Encode + core::fmt::Debug>( backed: &BackedCandidate, signing_context: &SigningContext, group_len: usize, validator_lookup: impl Fn(usize) -> Option, ) -> Result { if backed.validator_indices.len() != group_len { + log::debug!( + target: LOG_TARGET, + "Check candidate backing: indices mismatch: group_len = {} , indices_len = {}", + group_len, + backed.validator_indices.len(), + ); return Err(()) } if backed.validity_votes.len() > group_len { + log::debug!( + target: LOG_TARGET, + "Check candidate backing: Too many votes, expected: {}, found: {}", + group_len, + backed.validity_votes.len(), + ); return Err(()) } @@ -778,11 +791,23 @@ pub fn check_candidate_backing + Clone + Encode>( if sig.verify(&payload[..], &validator_id) { signed += 1; } else { + log::debug!( + target: LOG_TARGET, + "Check candidate backing: Invalid signature. validator_id = {:?}, validator_index = {} ", + validator_id, + val_in_group_idx, + ); return Err(()) } } if signed != backed.validity_votes.len() { + log::error!( + target: LOG_TARGET, + "Check candidate backing: Too many signatures, expected = {}, found = {}", + backed.validity_votes.len() , + signed, + ); return Err(()) } diff --git a/polkadot/primitives/src/vstaging/mod.rs b/polkadot/primitives/src/vstaging/mod.rs index 630bcf8679a..39d9dfc02c5 100644 --- a/polkadot/primitives/src/vstaging/mod.rs +++ b/polkadot/primitives/src/vstaging/mod.rs @@ -64,9 +64,13 @@ pub mod node_features { /// Tells if tranch0 assignments could be sent in a single certificate. /// Reserved for: `` EnableAssignmentsV2 = 0, + /// This feature enables the extension of `BackedCandidate::validator_indices` by 8 bits. + /// The value stored there represents the assumed core index where the candidates + /// are backed. This is needed for the elastic scaling MVP. + ElasticScalingMVP = 1, /// First unassigned feature bit. /// Every time a new feature flag is assigned it should take this value. /// and this should be incremented. - FirstUnassigned = 1, + FirstUnassigned = 2, } } diff --git a/polkadot/statement-table/Cargo.toml b/polkadot/statement-table/Cargo.toml index 6403b822ed9..37b8a99d640 100644 --- a/polkadot/statement-table/Cargo.toml +++ b/polkadot/statement-table/Cargo.toml @@ -13,3 +13,4 @@ workspace = true parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } sp-core = { path = "../../substrate/primitives/core" } primitives = { package = "polkadot-primitives", path = "../primitives" } +gum = { package = "tracing-gum", path = "../node/gum" } diff --git a/polkadot/statement-table/src/generic.rs b/polkadot/statement-table/src/generic.rs index 22bffde5acc..2ee6f6a4f78 100644 --- a/polkadot/statement-table/src/generic.rs +++ b/polkadot/statement-table/src/generic.rs @@ -36,6 +36,7 @@ use primitives::{ }; use parity_scale_codec::{Decode, Encode}; +const LOG_TARGET: &str = "parachain::statement-table"; /// Context for the statement table. pub trait Context { @@ -53,9 +54,6 @@ pub trait Context { /// get the digest of a candidate. fn candidate_digest(candidate: &Self::Candidate) -> Self::Digest; - /// get the group of a candidate. - fn candidate_group(candidate: &Self::Candidate) -> Self::GroupId; - /// Whether a authority is a member of a group. /// Members are meant to submit candidates and vote on validity. fn is_member_of(&self, authority: &Self::AuthorityId, group: &Self::GroupId) -> bool; @@ -342,13 +340,13 @@ impl Table { pub fn import_statement( &mut self, context: &Ctx, + group_id: Ctx::GroupId, statement: SignedStatement, ) -> Option> { let SignedStatement { statement, signature, sender: signer } = statement; - let res = match statement { Statement::Seconded(candidate) => - self.import_candidate(context, signer.clone(), candidate, signature), + self.import_candidate(context, signer.clone(), candidate, signature, group_id), Statement::Valid(digest) => self.validity_vote(context, signer.clone(), digest, ValidityVote::Valid(signature)), }; @@ -387,9 +385,10 @@ impl Table { authority: Ctx::AuthorityId, candidate: Ctx::Candidate, signature: Ctx::Signature, + group: Ctx::GroupId, ) -> ImportResult { - let group = Ctx::candidate_group(&candidate); if !context.is_member_of(&authority, &group) { + gum::debug!(target: LOG_TARGET, authority = ?authority, group = ?group, "New `Misbehavior::UnauthorizedStatement`, candidate backed by validator that doesn't belong to expected group" ); return Err(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { statement: SignedStatement { signature, @@ -634,10 +633,6 @@ mod tests { Digest(candidate.1) } - fn candidate_group(candidate: &Candidate) -> GroupId { - GroupId(candidate.0) - } - fn is_member_of(&self, authority: &AuthorityId, group: &GroupId) -> bool { self.authorities.get(authority).map(|v| v == group).unwrap_or(false) } @@ -675,10 +670,10 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, statement_a); + table.import_statement(&context, GroupId(2), statement_a); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); - table.import_statement(&context, statement_b); + table.import_statement(&context, GroupId(2), statement_b); assert_eq!( table.detected_misbehavior[&AuthorityId(1)][0], Misbehavior::MultipleCandidates(MultipleCandidates { @@ -711,10 +706,10 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, statement_a); + table.import_statement(&context, GroupId(2), statement_a); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); - table.import_statement(&context, statement_b); + table.import_statement(&context, GroupId(2), statement_b); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); } @@ -735,7 +730,7 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, statement); + table.import_statement(&context, GroupId(2), statement); assert_eq!( table.detected_misbehavior[&AuthorityId(1)][0], @@ -769,7 +764,7 @@ mod tests { }; let candidate_a_digest = Digest(100); - table.import_statement(&context, candidate_a); + table.import_statement(&context, GroupId(2), candidate_a); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); @@ -779,7 +774,7 @@ mod tests { signature: Signature(2), sender: AuthorityId(2), }; - table.import_statement(&context, bad_validity_vote); + table.import_statement(&context, GroupId(3), bad_validity_vote); assert_eq!( table.detected_misbehavior[&AuthorityId(2)][0], @@ -811,7 +806,7 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, statement); + table.import_statement(&context, GroupId(2), statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); let invalid_statement = SignedStatement { @@ -820,7 +815,7 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, invalid_statement); + table.import_statement(&context, GroupId(2), invalid_statement); assert!(table.detected_misbehavior.contains_key(&AuthorityId(1))); } @@ -842,7 +837,7 @@ mod tests { }; let candidate_digest = Digest(100); - table.import_statement(&context, statement); + table.import_statement(&context, GroupId(2), statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); let extra_vote = SignedStatement { @@ -851,7 +846,7 @@ mod tests { sender: AuthorityId(1), }; - table.import_statement(&context, extra_vote); + table.import_statement(&context, GroupId(2), extra_vote); assert_eq!( table.detected_misbehavior[&AuthorityId(1)][0], Misbehavior::ValidityDoubleVote(ValidityDoubleVote::IssuedAndValidity( @@ -910,7 +905,7 @@ mod tests { }; let candidate_digest = Digest(100); - table.import_statement(&context, statement); + table.import_statement(&context, GroupId(2), statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); assert!(table.attested_candidate(&candidate_digest, &context, 2).is_none()); @@ -921,7 +916,7 @@ mod tests { sender: AuthorityId(2), }; - table.import_statement(&context, vote); + table.import_statement(&context, GroupId(2), vote); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); assert!(table.attested_candidate(&candidate_digest, &context, 2).is_some()); } @@ -944,7 +939,7 @@ mod tests { }; let summary = table - .import_statement(&context, statement) + .import_statement(&context, GroupId(2), statement) .expect("candidate import to give summary"); assert_eq!(summary.candidate, Digest(100)); @@ -971,7 +966,7 @@ mod tests { }; let candidate_digest = Digest(100); - table.import_statement(&context, statement); + table.import_statement(&context, GroupId(2), statement); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); let vote = SignedStatement { @@ -980,8 +975,9 @@ mod tests { sender: AuthorityId(2), }; - let summary = - table.import_statement(&context, vote).expect("candidate vote to give summary"); + let summary = table + .import_statement(&context, GroupId(2), vote) + .expect("candidate vote to give summary"); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2))); diff --git a/polkadot/statement-table/src/lib.rs b/polkadot/statement-table/src/lib.rs index d4629330ac0..3740d15cc4f 100644 --- a/polkadot/statement-table/src/lib.rs +++ b/polkadot/statement-table/src/lib.rs @@ -35,8 +35,8 @@ pub use generic::{Config, Context, Table}; pub mod v2 { use crate::generic; use primitives::{ - CandidateHash, CommittedCandidateReceipt, CompactStatement as PrimitiveStatement, Id, - ValidatorIndex, ValidatorSignature, + CandidateHash, CommittedCandidateReceipt, CompactStatement as PrimitiveStatement, + CoreIndex, ValidatorIndex, ValidatorSignature, }; /// Statements about candidates on the network. @@ -59,7 +59,7 @@ pub mod v2 { >; /// A summary of import of a statement. - pub type Summary = generic::Summary; + pub type Summary = generic::Summary; impl<'a> From<&'a Statement> for PrimitiveStatement { fn from(s: &'a Statement) -> PrimitiveStatement { -- GitLab From 61ecef444fbd9e1eb4138123f35ecba32fe77565 Mon Sep 17 00:00:00 2001 From: Egor_P Date: Thu, 22 Feb 2024 16:48:52 +0700 Subject: [PATCH 011/188] Add matrix public channels for release announcements (#3430) This PR adds two more public channels in matrix where should the release announcements go --- .github/workflows/release-99_notif-published.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release-99_notif-published.yml b/.github/workflows/release-99_notif-published.yml index 397795fafa4..732db15d9c0 100644 --- a/.github/workflows/release-99_notif-published.yml +++ b/.github/workflows/release-99_notif-published.yml @@ -32,6 +32,12 @@ jobs: - name: '#polkadotvalidatorlounge:web3.foundation' room: '!NZrbtteFeqYKCUGQtr:matrix.parity.io' pre-releases: false + - name: '#polkadot-announcements:parity.io' + room: '!UqHPWiCBGZWxrmYBkF:matrix.parity.io' + pre-releases: false + - name: '#kusama-announce:parity.io' + room: '!FMwxpQnYhRCNDRsYGI:matrix.parity.io' + pre-releases: false steps: - name: Matrix notification to ${{ matrix.channel.name }} -- GitLab From 822082807fd6f146cd1c0561dc340dedab463c40 Mon Sep 17 00:00:00 2001 From: Koute Date: Thu, 22 Feb 2024 19:03:12 +0900 Subject: [PATCH 012/188] Fix `wasm-builder` not exiting if compilation fails (#3439) This PR fixes a subtle bug in `wasm-builder` first introduced in https://github.com/paritytech/polkadot-sdk/pull/1851 (sorry, my bad! I should have caught this during review) where the status code of the `cargo` subprocess is not properly checked, which results in builds silently succeeding when they shouldn't (that is: if we successfully build a runtime blob, and then modify the code so that it won't compile, and recompile it again, then the build will succeed and silently use the *old* blob). cc @athei This is the bug you were seeing. [edit]Also fixes a similar PolkaVM-specific bug where I accidentally used the wrong comparison operator.[/edit] --- substrate/utils/wasm-builder/src/wasm_project.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/utils/wasm-builder/src/wasm_project.rs b/substrate/utils/wasm-builder/src/wasm_project.rs index bc8c9b3b4b3..9ffb5c72fd9 100644 --- a/substrate/utils/wasm-builder/src/wasm_project.rs +++ b/substrate/utils/wasm-builder/src/wasm_project.rs @@ -855,7 +855,7 @@ fn build_bloaty_blob( println!("{} {}", colorize_info_message("Using rustc version:"), cargo_cmd.rustc_version()); // Use `process::exit(1)` to have a clean error output. - if build_cmd.status().map(|s| s.success()).is_err() { + if !matches!(build_cmd.status().map(|s| s.success()), Ok(true)) { process::exit(1); } @@ -877,7 +877,7 @@ fn build_bloaty_blob( if polkavm_path .metadata() .map(|polkavm_metadata| { - polkavm_metadata.modified().unwrap() >= elf_metadata.modified().unwrap() + polkavm_metadata.modified().unwrap() < elf_metadata.modified().unwrap() }) .unwrap_or(true) { -- GitLab From 31546c8d248573e9af33836883d414057a0cf4c9 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 22 Feb 2024 13:44:41 +0200 Subject: [PATCH 013/188] sc-consensus-beefy: pump gossip engine while waiting for initialization conditions (#3435) As part of BEEFY worker/voter initialization the task waits for certain chain and backend conditions to be fulfilled: - BEEFY consensus enabled on-chain & GRANDPA best finalized higher than on-chain BEEFY genesis block, - backend has synced headers for BEEFY mandatory blocks between best BEEFY and best GRANDPA. During this waiting time, any messages gossiped on the BEEFY topic for current chain get enqueued in the gossip engine, leading to RAM bloating and output warning/error messages when the wait time is non-negligible (like during a clean sync). This PR adds logic to pump the gossip engine while waiting for other things to make sure gossiped messages get consumed (practically discarded until worker is fully initialized). Also raises the warning threshold for enqueued messages from 10k to 100k. This is in line with the other gossip protocols on the node. Fixes https://github.com/paritytech/polkadot-sdk/issues/3390 --------- Signed-off-by: Adrian Catangiu --- prdoc/pr_3435.prdoc | 16 + .../beefy/src/communication/gossip.rs | 35 +- .../consensus/beefy/src/communication/mod.rs | 2 - .../client/consensus/beefy/src/import.rs | 2 +- substrate/client/consensus/beefy/src/lib.rs | 414 +++++++++++++---- substrate/client/consensus/beefy/src/tests.rs | 116 +---- .../client/consensus/beefy/src/worker.rs | 419 +++++------------- .../consensus/beefy/src/commitment.rs | 21 + 8 files changed, 520 insertions(+), 505 deletions(-) create mode 100644 prdoc/pr_3435.prdoc diff --git a/prdoc/pr_3435.prdoc b/prdoc/pr_3435.prdoc new file mode 100644 index 00000000000..7d7896bff7d --- /dev/null +++ b/prdoc/pr_3435.prdoc @@ -0,0 +1,16 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Fix BEEFY-related gossip messages error logs + +doc: + - audience: Node Operator + description: | + Added logic to pump the gossip engine while waiting for other things + to make sure gossiped messages get consumed (practically discarded + until worker is fully initialized). + This fixes an issue where node operators saw error logs, and fixes + potential RAM bloat when BEEFY initialization takes a long time + (i.e. during clean sync). +crates: + - name: sc-consensus-beefy diff --git a/substrate/client/consensus/beefy/src/communication/gossip.rs b/substrate/client/consensus/beefy/src/communication/gossip.rs index 8a0b0a74308..eb43c9173d7 100644 --- a/substrate/client/consensus/beefy/src/communication/gossip.rs +++ b/substrate/client/consensus/beefy/src/communication/gossip.rs @@ -56,6 +56,8 @@ pub(super) enum Action { Keep(H, ReputationChange), // discard, applying cost/benefit to originator. Discard(ReputationChange), + // ignore, no cost/benefit applied to originator. + DiscardNoReport, } /// An outcome of examining a message. @@ -68,7 +70,7 @@ enum Consider { /// Message is from the future. Reject. RejectFuture, /// Message cannot be evaluated. Reject. - RejectOutOfScope, + CannotEvaluate, } /// BEEFY gossip message type that gets encoded and sent on the network. @@ -168,18 +170,14 @@ impl Filter { .as_ref() .map(|f| // only from current set and only [filter.start, filter.end] - if set_id < f.validator_set.id() { + if set_id < f.validator_set.id() || round < f.start { Consider::RejectPast - } else if set_id > f.validator_set.id() { - Consider::RejectFuture - } else if round < f.start { - Consider::RejectPast - } else if round > f.end { + } else if set_id > f.validator_set.id() || round > f.end { Consider::RejectFuture } else { Consider::Accept }) - .unwrap_or(Consider::RejectOutOfScope) + .unwrap_or(Consider::CannotEvaluate) } /// Return true if `round` is >= than `max(session_start, best_beefy)`, @@ -199,7 +197,7 @@ impl Filter { Consider::Accept } ) - .unwrap_or(Consider::RejectOutOfScope) + .unwrap_or(Consider::CannotEvaluate) } /// Add new _known_ `round` to the set of seen valid justifications. @@ -244,7 +242,7 @@ where pub(crate) fn new( known_peers: Arc>>, ) -> (GossipValidator, TracingUnboundedReceiver) { - let (tx, rx) = tracing_unbounded("mpsc_beefy_gossip_validator", 10_000); + let (tx, rx) = tracing_unbounded("mpsc_beefy_gossip_validator", 100_000); let val = GossipValidator { votes_topic: votes_topic::(), justifs_topic: proofs_topic::(), @@ -289,7 +287,9 @@ where match filter.consider_vote(round, set_id) { Consider::RejectPast => return Action::Discard(cost::OUTDATED_MESSAGE), Consider::RejectFuture => return Action::Discard(cost::FUTURE_MESSAGE), - Consider::RejectOutOfScope => return Action::Discard(cost::OUT_OF_SCOPE_MESSAGE), + // When we can't evaluate, it's our fault (e.g. filter not initialized yet), we + // discard the vote without punishing or rewarding the sending peer. + Consider::CannotEvaluate => return Action::DiscardNoReport, Consider::Accept => {}, } @@ -330,7 +330,9 @@ where match guard.consider_finality_proof(round, set_id) { Consider::RejectPast => return Action::Discard(cost::OUTDATED_MESSAGE), Consider::RejectFuture => return Action::Discard(cost::FUTURE_MESSAGE), - Consider::RejectOutOfScope => return Action::Discard(cost::OUT_OF_SCOPE_MESSAGE), + // When we can't evaluate, it's our fault (e.g. filter not initialized yet), we + // discard the proof without punishing or rewarding the sending peer. + Consider::CannotEvaluate => return Action::DiscardNoReport, Consider::Accept => {}, } @@ -357,7 +359,9 @@ where Action::Keep(self.justifs_topic, benefit::VALIDATED_PROOF) } }) - .unwrap_or(Action::Discard(cost::OUT_OF_SCOPE_MESSAGE)) + // When we can't evaluate, it's our fault (e.g. filter not initialized yet), we + // discard the proof without punishing or rewarding the sending peer. + .unwrap_or(Action::DiscardNoReport) }; if matches!(action, Action::Keep(_, _)) { self.gossip_filter.write().mark_round_as_proven(round); @@ -404,6 +408,7 @@ where self.report(*sender, cb); ValidationResult::Discard }, + Action::DiscardNoReport => ValidationResult::Discard, } } @@ -579,8 +584,8 @@ pub(crate) mod tests { // filter not initialized let res = gv.validate(&mut context, &sender, &encoded); assert!(matches!(res, ValidationResult::Discard)); - expected_report.cost_benefit = cost::OUT_OF_SCOPE_MESSAGE; - assert_eq!(report_stream.try_recv().unwrap(), expected_report); + // nothing reported + assert!(report_stream.try_recv().is_err()); gv.update_filter(GossipFilterCfg { start: 0, end: 10, validator_set: &validator_set }); // nothing in cache first time diff --git a/substrate/client/consensus/beefy/src/communication/mod.rs b/substrate/client/consensus/beefy/src/communication/mod.rs index 3827559057d..6fda63688e6 100644 --- a/substrate/client/consensus/beefy/src/communication/mod.rs +++ b/substrate/client/consensus/beefy/src/communication/mod.rs @@ -90,8 +90,6 @@ mod cost { pub(super) const BAD_SIGNATURE: Rep = Rep::new(-100, "BEEFY: Bad signature"); // Message received with vote from voter not in validator set. pub(super) const UNKNOWN_VOTER: Rep = Rep::new(-150, "BEEFY: Unknown voter"); - // A message received that cannot be evaluated relative to our current state. - pub(super) const OUT_OF_SCOPE_MESSAGE: Rep = Rep::new(-500, "BEEFY: Out-of-scope message"); // Message containing invalid proof. pub(super) const INVALID_PROOF: Rep = Rep::new(-5000, "BEEFY: Invalid commit"); // Reputation cost per signature checked for invalid proof. diff --git a/substrate/client/consensus/beefy/src/import.rs b/substrate/client/consensus/beefy/src/import.rs index fc19ecc3014..ed8ed68c4e8 100644 --- a/substrate/client/consensus/beefy/src/import.rs +++ b/substrate/client/consensus/beefy/src/import.rs @@ -159,7 +159,7 @@ where // The proof is valid and the block is imported and final, we can import. debug!( target: LOG_TARGET, - "🥩 import justif {:?} for block number {:?}.", proof, number + "🥩 import justif {} for block number {:?}.", proof, number ); // Send the justification to the BEEFY voter for processing. self.justification_sender diff --git a/substrate/client/consensus/beefy/src/lib.rs b/substrate/client/consensus/beefy/src/lib.rs index 11a105561e4..323af1bc830 100644 --- a/substrate/client/consensus/beefy/src/lib.rs +++ b/substrate/client/consensus/beefy/src/lib.rs @@ -31,7 +31,7 @@ use crate::{ import::BeefyBlockImport, metrics::register_metrics, }; -use futures::{stream::Fuse, StreamExt}; +use futures::{stream::Fuse, FutureExt, StreamExt}; use log::{debug, error, info, warn}; use parking_lot::Mutex; use prometheus::Registry; @@ -40,17 +40,21 @@ use sc_consensus::BlockImport; use sc_network::{NetworkRequest, NotificationService, ProtocolName}; use sc_network_gossip::{GossipEngine, Network as GossipNetwork, Syncing as GossipSyncing}; use sp_api::ProvideRuntimeApi; -use sp_blockchain::{ - Backend as BlockchainBackend, Error as ClientError, HeaderBackend, Result as ClientResult, -}; +use sp_blockchain::{Backend as BlockchainBackend, HeaderBackend}; use sp_consensus::{Error as ConsensusError, SyncOracle}; use sp_consensus_beefy::{ - ecdsa_crypto::AuthorityId, BeefyApi, MmrRootHash, PayloadProvider, ValidatorSet, + ecdsa_crypto::AuthorityId, BeefyApi, ConsensusLog, MmrRootHash, PayloadProvider, ValidatorSet, + BEEFY_ENGINE_ID, }; use sp_keystore::KeystorePtr; use sp_mmr_primitives::MmrApi; use sp_runtime::traits::{Block, Header as HeaderT, NumberFor, Zero}; -use std::{collections::BTreeMap, marker::PhantomData, sync::Arc, time::Duration}; +use std::{ + collections::{BTreeMap, VecDeque}, + marker::PhantomData, + sync::Arc, + time::Duration, +}; mod aux_schema; mod error; @@ -63,9 +67,19 @@ pub mod communication; pub mod import; pub mod justification; +use crate::{ + communication::{gossip::GossipValidator, peers::PeerReport}, + justification::BeefyVersionedFinalityProof, + keystore::BeefyKeystore, + metrics::VoterMetrics, + round::Rounds, + worker::{BeefyWorker, PersistedState}, +}; pub use communication::beefy_protocol_name::{ gossip_protocol_name, justifications_protocol_name as justifs_protocol_name, }; +use sc_utils::mpsc::TracingUnboundedReceiver; +use sp_runtime::generic::OpaqueDigestItemId; #[cfg(test)] mod tests; @@ -209,6 +223,247 @@ pub struct BeefyParams { /// Handler for incoming BEEFY justifications requests from a remote peer. pub on_demand_justifications_handler: BeefyJustifsRequestHandler, } +/// Helper object holding BEEFY worker communication/gossip components. +/// +/// These are created once, but will be reused if worker is restarted/reinitialized. +pub(crate) struct BeefyComms { + pub gossip_engine: GossipEngine, + pub gossip_validator: Arc>, + pub gossip_report_stream: TracingUnboundedReceiver, + pub on_demand_justifications: OnDemandJustificationsEngine, +} + +/// Helper builder object for building [worker::BeefyWorker]. +/// +/// It has to do it in two steps: initialization and build, because the first step can sleep waiting +/// for certain chain and backend conditions, and while sleeping we still need to pump the +/// GossipEngine. Once initialization is done, the GossipEngine (and other pieces) are added to get +/// the complete [worker::BeefyWorker] object. +pub(crate) struct BeefyWorkerBuilder { + // utilities + backend: Arc, + runtime: Arc, + key_store: BeefyKeystore, + // voter metrics + metrics: Option, + persisted_state: PersistedState, +} + +impl BeefyWorkerBuilder +where + B: Block + codec::Codec, + BE: Backend, + R: ProvideRuntimeApi, + R::Api: BeefyApi, +{ + /// This will wait for the chain to enable BEEFY (if not yet enabled) and also wait for the + /// backend to sync all headers required by the voter to build a contiguous chain of mandatory + /// justifications. Then it builds the initial voter state using a combination of previously + /// persisted state in AUX DB and latest chain information/progress. + /// + /// Returns a sane `BeefyWorkerBuilder` that can build the `BeefyWorker`. + pub async fn async_initialize( + backend: Arc, + runtime: Arc, + key_store: BeefyKeystore, + metrics: Option, + min_block_delta: u32, + gossip_validator: Arc>, + finality_notifications: &mut Fuse>, + ) -> Result { + // Wait for BEEFY pallet to be active before starting voter. + let (beefy_genesis, best_grandpa) = + wait_for_runtime_pallet(&*runtime, finality_notifications).await?; + + let persisted_state = Self::load_or_init_state( + beefy_genesis, + best_grandpa, + min_block_delta, + backend.clone(), + runtime.clone(), + &key_store, + &metrics, + ) + .await?; + // Update the gossip validator with the right starting round and set id. + persisted_state + .gossip_filter_config() + .map(|f| gossip_validator.update_filter(f))?; + + Ok(BeefyWorkerBuilder { backend, runtime, key_store, metrics, persisted_state }) + } + + /// Takes rest of missing pieces as params and builds the `BeefyWorker`. + pub fn build( + self, + payload_provider: P, + sync: Arc, + comms: BeefyComms, + links: BeefyVoterLinks, + pending_justifications: BTreeMap, BeefyVersionedFinalityProof>, + ) -> BeefyWorker { + BeefyWorker { + backend: self.backend, + runtime: self.runtime, + key_store: self.key_store, + metrics: self.metrics, + persisted_state: self.persisted_state, + payload_provider, + sync, + comms, + links, + pending_justifications, + } + } + + // If no persisted state present, walk back the chain from first GRANDPA notification to either: + // - latest BEEFY finalized block, or if none found on the way, + // - BEEFY pallet genesis; + // Enqueue any BEEFY mandatory blocks (session boundaries) found on the way, for voter to + // finalize. + async fn init_state( + beefy_genesis: NumberFor, + best_grandpa: ::Header, + min_block_delta: u32, + backend: Arc, + runtime: Arc, + ) -> Result, Error> { + let blockchain = backend.blockchain(); + + let beefy_genesis = runtime + .runtime_api() + .beefy_genesis(best_grandpa.hash()) + .ok() + .flatten() + .filter(|genesis| *genesis == beefy_genesis) + .ok_or_else(|| Error::Backend("BEEFY pallet expected to be active.".into()))?; + // Walk back the imported blocks and initialize voter either, at the last block with + // a BEEFY justification, or at pallet genesis block; voter will resume from there. + let mut sessions = VecDeque::new(); + let mut header = best_grandpa.clone(); + let state = loop { + if let Some(true) = blockchain + .justifications(header.hash()) + .ok() + .flatten() + .map(|justifs| justifs.get(BEEFY_ENGINE_ID).is_some()) + { + debug!( + target: LOG_TARGET, + "🥩 Initialize BEEFY voter at last BEEFY finalized block: {:?}.", + *header.number() + ); + let best_beefy = *header.number(); + // If no session boundaries detected so far, just initialize new rounds here. + if sessions.is_empty() { + let active_set = + expect_validator_set(runtime.as_ref(), backend.as_ref(), &header).await?; + let mut rounds = Rounds::new(best_beefy, active_set); + // Mark the round as already finalized. + rounds.conclude(best_beefy); + sessions.push_front(rounds); + } + let state = PersistedState::checked_new( + best_grandpa, + best_beefy, + sessions, + min_block_delta, + beefy_genesis, + ) + .ok_or_else(|| Error::Backend("Invalid BEEFY chain".into()))?; + break state + } + + if *header.number() == beefy_genesis { + // We've reached BEEFY genesis, initialize voter here. + let genesis_set = + expect_validator_set(runtime.as_ref(), backend.as_ref(), &header).await?; + info!( + target: LOG_TARGET, + "🥩 Loading BEEFY voter state from genesis on what appears to be first startup. \ + Starting voting rounds at block {:?}, genesis validator set {:?}.", + beefy_genesis, + genesis_set, + ); + + sessions.push_front(Rounds::new(beefy_genesis, genesis_set)); + break PersistedState::checked_new( + best_grandpa, + Zero::zero(), + sessions, + min_block_delta, + beefy_genesis, + ) + .ok_or_else(|| Error::Backend("Invalid BEEFY chain".into()))? + } + + if let Some(active) = find_authorities_change::(&header) { + debug!( + target: LOG_TARGET, + "🥩 Marking block {:?} as BEEFY Mandatory.", + *header.number() + ); + sessions.push_front(Rounds::new(*header.number(), active)); + } + + // Move up the chain. + header = wait_for_parent_header(blockchain, header, HEADER_SYNC_DELAY).await?; + }; + + aux_schema::write_current_version(backend.as_ref())?; + aux_schema::write_voter_state(backend.as_ref(), &state)?; + Ok(state) + } + + async fn load_or_init_state( + beefy_genesis: NumberFor, + best_grandpa: ::Header, + min_block_delta: u32, + backend: Arc, + runtime: Arc, + key_store: &BeefyKeystore, + metrics: &Option, + ) -> Result, Error> { + // Initialize voter state from AUX DB if compatible. + if let Some(mut state) = crate::aux_schema::load_persistent(backend.as_ref())? + // Verify state pallet genesis matches runtime. + .filter(|state| state.pallet_genesis() == beefy_genesis) + { + // Overwrite persisted state with current best GRANDPA block. + state.set_best_grandpa(best_grandpa.clone()); + // Overwrite persisted data with newly provided `min_block_delta`. + state.set_min_block_delta(min_block_delta); + debug!(target: LOG_TARGET, "🥩 Loading BEEFY voter state from db: {:?}.", state); + + // Make sure that all the headers that we need have been synced. + let mut new_sessions = vec![]; + let mut header = best_grandpa.clone(); + while *header.number() > state.best_beefy() { + if state.voting_oracle().can_add_session(*header.number()) { + if let Some(active) = find_authorities_change::(&header) { + new_sessions.push((active, *header.number())); + } + } + header = + wait_for_parent_header(backend.blockchain(), header, HEADER_SYNC_DELAY).await?; + } + + // Make sure we didn't miss any sessions during node restart. + for (validator_set, new_session_start) in new_sessions.drain(..).rev() { + debug!( + target: LOG_TARGET, + "🥩 Handling missed BEEFY session after node restart: {:?}.", + new_session_start + ); + state.init_session_at(new_session_start, validator_set, key_store, metrics); + } + return Ok(state) + } + + // No valid voter-state persisted, re-initialize from pallet genesis. + Self::init_state(beefy_genesis, best_grandpa, min_block_delta, backend, runtime).await + } +} /// Start the BEEFY gadget. /// @@ -277,7 +532,7 @@ pub async fn start_beefy_gadget( known_peers, prometheus_registry.clone(), ); - let mut beefy_comms = worker::BeefyComms { + let mut beefy_comms = BeefyComms { gossip_engine, gossip_validator, gossip_report_stream, @@ -287,57 +542,45 @@ pub async fn start_beefy_gadget( // We re-create and re-run the worker in this loop in order to quickly reinit and resume after // select recoverable errors. loop { - // Wait for BEEFY pallet to be active before starting voter. - let (beefy_genesis, best_grandpa) = match wait_for_runtime_pallet( - &*runtime, - &mut beefy_comms.gossip_engine, - &mut finality_notifications, - ) - .await - { - Ok(res) => res, - Err(e) => { - error!(target: LOG_TARGET, "Error: {:?}. Terminating.", e); - return - }, - }; - - let mut worker_base = worker::BeefyWorkerBase { - backend: backend.clone(), - runtime: runtime.clone(), - key_store: key_store.clone().into(), - metrics: metrics.clone(), - _phantom: Default::default(), - }; - - let persisted_state = match worker_base - .load_or_init_state(beefy_genesis, best_grandpa, min_block_delta) - .await - { - Ok(state) => state, - Err(e) => { - error!(target: LOG_TARGET, "Error: {:?}. Terminating.", e); - return - }, + // Make sure to pump gossip engine while waiting for initialization conditions. + let worker_builder = loop { + futures::select! { + builder_init_result = BeefyWorkerBuilder::async_initialize( + backend.clone(), + runtime.clone(), + key_store.clone().into(), + metrics.clone(), + min_block_delta, + beefy_comms.gossip_validator.clone(), + &mut finality_notifications, + ).fuse() => { + match builder_init_result { + Ok(builder) => break builder, + Err(e) => { + error!(target: LOG_TARGET, "🥩 Error: {:?}. Terminating.", e); + return + }, + } + }, + // Pump peer reports + _ = &mut beefy_comms.gossip_report_stream.next() => { + continue + }, + // Pump gossip engine. + _ = &mut beefy_comms.gossip_engine => { + error!(target: LOG_TARGET, "🥩 Gossip engine has unexpectedly terminated."); + return + } + } }; - // Update the gossip validator with the right starting round and set id. - if let Err(e) = persisted_state - .gossip_filter_config() - .map(|f| beefy_comms.gossip_validator.update_filter(f)) - { - error!(target: LOG_TARGET, "Error: {:?}. Terminating.", e); - return - } - let worker = worker::BeefyWorker { - base: worker_base, - payload_provider: payload_provider.clone(), - sync: sync.clone(), - comms: beefy_comms, - links: links.clone(), - pending_justifications: BTreeMap::new(), - persisted_state, - }; + let worker = worker_builder.build( + payload_provider.clone(), + sync.clone(), + beefy_comms, + links.clone(), + BTreeMap::new(), + ); match futures::future::select( Box::pin(worker.run(&mut block_import_justif, &mut finality_notifications)), @@ -404,9 +647,8 @@ where /// Should be called only once during worker initialization. async fn wait_for_runtime_pallet( runtime: &R, - mut gossip_engine: &mut GossipEngine, finality: &mut Fuse>, -) -> ClientResult<(NumberFor, ::Header)> +) -> Result<(NumberFor, ::Header), Error> where B: Block, R: ProvideRuntimeApi, @@ -414,33 +656,24 @@ where { info!(target: LOG_TARGET, "🥩 BEEFY gadget waiting for BEEFY pallet to become available..."); loop { - futures::select! { - notif = finality.next() => { - let notif = match notif { - Some(notif) => notif, - None => break - }; - let at = notif.header.hash(); - if let Some(start) = runtime.runtime_api().beefy_genesis(at).ok().flatten() { - if *notif.header.number() >= start { - // Beefy pallet available, return header for best grandpa at the time. - info!( - target: LOG_TARGET, - "🥩 BEEFY pallet available: block {:?} beefy genesis {:?}", - notif.header.number(), start - ); - return Ok((start, notif.header)) - } - } - }, - _ = gossip_engine => { - break + let notif = finality.next().await.ok_or_else(|| { + let err_msg = "🥩 Finality stream has unexpectedly terminated.".into(); + error!(target: LOG_TARGET, "{}", err_msg); + Error::Backend(err_msg) + })?; + let at = notif.header.hash(); + if let Some(start) = runtime.runtime_api().beefy_genesis(at).ok().flatten() { + if *notif.header.number() >= start { + // Beefy pallet available, return header for best grandpa at the time. + info!( + target: LOG_TARGET, + "🥩 BEEFY pallet available: block {:?} beefy genesis {:?}", + notif.header.number(), start + ); + return Ok((start, notif.header)) } } } - let err_msg = "🥩 Gossip engine has unexpectedly terminated.".into(); - error!(target: LOG_TARGET, "{}", err_msg); - Err(ClientError::Backend(err_msg)) } /// Provides validator set active `at_header`. It tries to get it from state, otherwise falls @@ -474,7 +707,7 @@ where if let Ok(Some(active)) = runtime.runtime_api().validator_set(header.hash()) { return Ok(active) } else { - match worker::find_authorities_change::(&header) { + match find_authorities_change::(&header) { Some(active) => return Ok(active), // Move up the chain. Ultimately we'll get it from chain genesis state, or error out // there. @@ -486,3 +719,18 @@ where } } } + +/// Scan the `header` digest log for a BEEFY validator set change. Return either the new +/// validator set or `None` in case no validator set change has been signaled. +pub(crate) fn find_authorities_change(header: &B::Header) -> Option> +where + B: Block, +{ + let id = OpaqueDigestItemId::Consensus(&BEEFY_ENGINE_ID); + + let filter = |log: ConsensusLog| match log { + ConsensusLog::AuthoritiesChange(validator_set) => Some(validator_set), + _ => None, + }; + header.digest().convert_first(|l| l.try_to(id).and_then(filter)) +} diff --git a/substrate/client/consensus/beefy/src/tests.rs b/substrate/client/consensus/beefy/src/tests.rs index 0e6ff210b15..d106c9dcd88 100644 --- a/substrate/client/consensus/beefy/src/tests.rs +++ b/substrate/client/consensus/beefy/src/tests.rs @@ -32,8 +32,8 @@ use crate::{ gossip_protocol_name, justification::*, wait_for_runtime_pallet, - worker::{BeefyWorkerBase, PersistedState}, - BeefyRPCLinks, BeefyVoterLinks, KnownPeers, + worker::PersistedState, + BeefyRPCLinks, BeefyVoterLinks, BeefyWorkerBuilder, KnownPeers, }; use futures::{future, stream::FuturesUnordered, Future, FutureExt, StreamExt}; use parking_lot::Mutex; @@ -368,27 +368,19 @@ async fn voter_init_setup( api: &TestApi, ) -> Result, Error> { let backend = net.peer(0).client().as_backend(); - let known_peers = Arc::new(Mutex::new(KnownPeers::new())); - let (gossip_validator, _) = GossipValidator::new(known_peers); - let gossip_validator = Arc::new(gossip_validator); - let mut gossip_engine = sc_network_gossip::GossipEngine::new( - net.peer(0).network_service().clone(), - net.peer(0).sync_service().clone(), - net.peer(0).take_notification_service(&beefy_gossip_proto_name()).unwrap(), - "/beefy/whatever", - gossip_validator, - None, - ); - let (beefy_genesis, best_grandpa) = - wait_for_runtime_pallet(api, &mut gossip_engine, finality).await.unwrap(); - let mut worker_base = BeefyWorkerBase { + let (beefy_genesis, best_grandpa) = wait_for_runtime_pallet(api, finality).await.unwrap(); + let key_store = None.into(); + let metrics = None; + BeefyWorkerBuilder::load_or_init_state( + beefy_genesis, + best_grandpa, + 1, backend, - runtime: Arc::new(api.clone()), - key_store: None.into(), - metrics: None, - _phantom: Default::default(), - }; - worker_base.load_or_init_state(beefy_genesis, best_grandpa, 1).await + Arc::new(api.clone()), + &key_store, + &metrics, + ) + .await } // Spawns beefy voters. Returns a future to spawn on the runtime. @@ -1065,32 +1057,7 @@ async fn should_initialize_voter_at_custom_genesis() { net.peer(0).client().as_client().finalize_block(hashes[8], None).unwrap(); // load persistent state - nothing in DB, should init at genesis - // - // NOTE: code from `voter_init_setup()` is moved here because the new network event system - // doesn't allow creating a new `GossipEngine` as the notification handle is consumed by the - // first `GossipEngine` - let known_peers = Arc::new(Mutex::new(KnownPeers::new())); - let (gossip_validator, _) = GossipValidator::new(known_peers); - let gossip_validator = Arc::new(gossip_validator); - let mut gossip_engine = sc_network_gossip::GossipEngine::new( - net.peer(0).network_service().clone(), - net.peer(0).sync_service().clone(), - net.peer(0).take_notification_service(&beefy_gossip_proto_name()).unwrap(), - "/beefy/whatever", - gossip_validator, - None, - ); - let (beefy_genesis, best_grandpa) = - wait_for_runtime_pallet(&api, &mut gossip_engine, &mut finality).await.unwrap(); - let mut worker_base = BeefyWorkerBase { - backend: backend.clone(), - runtime: Arc::new(api), - key_store: None.into(), - metrics: None, - _phantom: Default::default(), - }; - let persisted_state = - worker_base.load_or_init_state(beefy_genesis, best_grandpa, 1).await.unwrap(); + let persisted_state = voter_init_setup(&mut net, &mut finality, &api).await.unwrap(); // Test initialization at session boundary. // verify voter initialized with single session starting at block `custom_pallet_genesis` (7) @@ -1120,18 +1087,7 @@ async fn should_initialize_voter_at_custom_genesis() { net.peer(0).client().as_client().finalize_block(hashes[10], None).unwrap(); // load persistent state - state preset in DB, but with different pallet genesis - // the network state persists and uses the old `GossipEngine` initialized for `peer(0)` - let (beefy_genesis, best_grandpa) = - wait_for_runtime_pallet(&api, &mut gossip_engine, &mut finality).await.unwrap(); - let mut worker_base = BeefyWorkerBase { - backend: backend.clone(), - runtime: Arc::new(api), - key_store: None.into(), - metrics: None, - _phantom: Default::default(), - }; - let new_persisted_state = - worker_base.load_or_init_state(beefy_genesis, best_grandpa, 1).await.unwrap(); + let new_persisted_state = voter_init_setup(&mut net, &mut finality, &api).await.unwrap(); // verify voter initialized with single session starting at block `new_pallet_genesis` (10) let sessions = new_persisted_state.voting_oracle().sessions(); @@ -1322,32 +1278,7 @@ async fn should_catch_up_when_loading_saved_voter_state() { let api = TestApi::with_validator_set(&validator_set); // load persistent state - nothing in DB, should init at genesis - // - // NOTE: code from `voter_init_setup()` is moved here because the new network event system - // doesn't allow creating a new `GossipEngine` as the notification handle is consumed by the - // first `GossipEngine` - let known_peers = Arc::new(Mutex::new(KnownPeers::new())); - let (gossip_validator, _) = GossipValidator::new(known_peers); - let gossip_validator = Arc::new(gossip_validator); - let mut gossip_engine = sc_network_gossip::GossipEngine::new( - net.peer(0).network_service().clone(), - net.peer(0).sync_service().clone(), - net.peer(0).take_notification_service(&beefy_gossip_proto_name()).unwrap(), - "/beefy/whatever", - gossip_validator, - None, - ); - let (beefy_genesis, best_grandpa) = - wait_for_runtime_pallet(&api, &mut gossip_engine, &mut finality).await.unwrap(); - let mut worker_base = BeefyWorkerBase { - backend: backend.clone(), - runtime: Arc::new(api.clone()), - key_store: None.into(), - metrics: None, - _phantom: Default::default(), - }; - let persisted_state = - worker_base.load_or_init_state(beefy_genesis, best_grandpa, 1).await.unwrap(); + let persisted_state = voter_init_setup(&mut net, &mut finality, &api).await.unwrap(); // Test initialization at session boundary. // verify voter initialized with two sessions starting at blocks 1 and 10 @@ -1374,18 +1305,7 @@ async fn should_catch_up_when_loading_saved_voter_state() { // finalize 25 without justifications net.peer(0).client().as_client().finalize_block(hashes[25], None).unwrap(); // load persistent state - state preset in DB - // the network state persists and uses the old `GossipEngine` initialized for `peer(0)` - let (beefy_genesis, best_grandpa) = - wait_for_runtime_pallet(&api, &mut gossip_engine, &mut finality).await.unwrap(); - let mut worker_base = BeefyWorkerBase { - backend: backend.clone(), - runtime: Arc::new(api), - key_store: None.into(), - metrics: None, - _phantom: Default::default(), - }; - let persisted_state = - worker_base.load_or_init_state(beefy_genesis, best_grandpa, 1).await.unwrap(); + let persisted_state = voter_init_setup(&mut net, &mut finality, &api).await.unwrap(); // Verify voter initialized with old sessions plus a new one starting at block 20. // There shouldn't be any duplicates. diff --git a/substrate/client/consensus/beefy/src/worker.rs b/substrate/client/consensus/beefy/src/worker.rs index d7a229003cc..c8eb19621ba 100644 --- a/substrate/client/consensus/beefy/src/worker.rs +++ b/substrate/client/consensus/beefy/src/worker.rs @@ -17,46 +17,42 @@ // along with this program. If not, see . use crate::{ - aux_schema, communication::{ - gossip::{proofs_topic, votes_topic, GossipFilterCfg, GossipMessage, GossipValidator}, + gossip::{proofs_topic, votes_topic, GossipFilterCfg, GossipMessage}, peers::PeerReport, - request_response::outgoing_requests_engine::{OnDemandJustificationsEngine, ResponseInfo}, + request_response::outgoing_requests_engine::ResponseInfo, }, error::Error, - expect_validator_set, + find_authorities_change, justification::BeefyVersionedFinalityProof, keystore::BeefyKeystore, metric_inc, metric_set, metrics::VoterMetrics, round::{Rounds, VoteImportResult}, - wait_for_parent_header, BeefyVoterLinks, HEADER_SYNC_DELAY, LOG_TARGET, + BeefyComms, BeefyVoterLinks, LOG_TARGET, }; use codec::{Codec, Decode, DecodeAll, Encode}; use futures::{stream::Fuse, FutureExt, StreamExt}; use log::{debug, error, info, log_enabled, trace, warn}; use sc_client_api::{Backend, FinalityNotification, FinalityNotifications, HeaderBackend}; -use sc_network_gossip::GossipEngine; -use sc_utils::{mpsc::TracingUnboundedReceiver, notification::NotificationReceiver}; +use sc_utils::notification::NotificationReceiver; use sp_api::ProvideRuntimeApi; use sp_arithmetic::traits::{AtLeast32Bit, Saturating}; -use sp_blockchain::Backend as BlockchainBackend; use sp_consensus::SyncOracle; use sp_consensus_beefy::{ check_equivocation_proof, ecdsa_crypto::{AuthorityId, Signature}, - BeefyApi, BeefySignatureHasher, Commitment, ConsensusLog, EquivocationProof, PayloadProvider, - ValidatorSet, VersionedFinalityProof, VoteMessage, BEEFY_ENGINE_ID, + BeefyApi, BeefySignatureHasher, Commitment, EquivocationProof, PayloadProvider, ValidatorSet, + VersionedFinalityProof, VoteMessage, BEEFY_ENGINE_ID, }; use sp_runtime::{ - generic::{BlockId, OpaqueDigestItemId}, + generic::BlockId, traits::{Block, Header, NumberFor, Zero}, SaturatedConversion, }; use std::{ collections::{BTreeMap, BTreeSet, VecDeque}, fmt::Debug, - marker::PhantomData, sync::Arc, }; @@ -180,8 +176,8 @@ impl VoterOracle { } } - // Check if an observed session can be added to the Oracle. - fn can_add_session(&self, session_start: NumberFor) -> bool { + /// Check if an observed session can be added to the Oracle. + pub fn can_add_session(&self, session_start: NumberFor) -> bool { let latest_known_session_start = self.sessions.back().map(|session| session.session_start()); Some(session_start) > latest_known_session_start @@ -319,229 +315,28 @@ impl PersistedState { self.voting_oracle.best_grandpa_block_header = best_grandpa; } + pub fn voting_oracle(&self) -> &VoterOracle { + &self.voting_oracle + } + pub(crate) fn gossip_filter_config(&self) -> Result, Error> { let (start, end) = self.voting_oracle.accepted_interval()?; let validator_set = self.voting_oracle.current_validator_set()?; Ok(GossipFilterCfg { start, end, validator_set }) } -} - -/// Helper object holding BEEFY worker communication/gossip components. -/// -/// These are created once, but will be reused if worker is restarted/reinitialized. -pub(crate) struct BeefyComms { - pub gossip_engine: GossipEngine, - pub gossip_validator: Arc>, - pub gossip_report_stream: TracingUnboundedReceiver, - pub on_demand_justifications: OnDemandJustificationsEngine, -} - -pub(crate) struct BeefyWorkerBase { - // utilities - pub backend: Arc, - pub runtime: Arc, - pub key_store: BeefyKeystore, - - /// BEEFY client metrics. - pub metrics: Option, - - pub _phantom: PhantomData, -} - -impl BeefyWorkerBase -where - B: Block + Codec, - BE: Backend, - R: ProvideRuntimeApi, - R::Api: BeefyApi, -{ - // If no persisted state present, walk back the chain from first GRANDPA notification to either: - // - latest BEEFY finalized block, or if none found on the way, - // - BEEFY pallet genesis; - // Enqueue any BEEFY mandatory blocks (session boundaries) found on the way, for voter to - // finalize. - async fn init_state( - &self, - beefy_genesis: NumberFor, - best_grandpa: ::Header, - min_block_delta: u32, - ) -> Result, Error> { - let blockchain = self.backend.blockchain(); - - let beefy_genesis = self - .runtime - .runtime_api() - .beefy_genesis(best_grandpa.hash()) - .ok() - .flatten() - .filter(|genesis| *genesis == beefy_genesis) - .ok_or_else(|| Error::Backend("BEEFY pallet expected to be active.".into()))?; - // Walk back the imported blocks and initialize voter either, at the last block with - // a BEEFY justification, or at pallet genesis block; voter will resume from there. - let mut sessions = VecDeque::new(); - let mut header = best_grandpa.clone(); - let state = loop { - if let Some(true) = blockchain - .justifications(header.hash()) - .ok() - .flatten() - .map(|justifs| justifs.get(BEEFY_ENGINE_ID).is_some()) - { - debug!( - target: LOG_TARGET, - "🥩 Initialize BEEFY voter at last BEEFY finalized block: {:?}.", - *header.number() - ); - let best_beefy = *header.number(); - // If no session boundaries detected so far, just initialize new rounds here. - if sessions.is_empty() { - let active_set = - expect_validator_set(self.runtime.as_ref(), self.backend.as_ref(), &header) - .await?; - let mut rounds = Rounds::new(best_beefy, active_set); - // Mark the round as already finalized. - rounds.conclude(best_beefy); - sessions.push_front(rounds); - } - let state = PersistedState::checked_new( - best_grandpa, - best_beefy, - sessions, - min_block_delta, - beefy_genesis, - ) - .ok_or_else(|| Error::Backend("Invalid BEEFY chain".into()))?; - break state - } - - if *header.number() == beefy_genesis { - // We've reached BEEFY genesis, initialize voter here. - let genesis_set = - expect_validator_set(self.runtime.as_ref(), self.backend.as_ref(), &header) - .await?; - info!( - target: LOG_TARGET, - "🥩 Loading BEEFY voter state from genesis on what appears to be first startup. \ - Starting voting rounds at block {:?}, genesis validator set {:?}.", - beefy_genesis, - genesis_set, - ); - - sessions.push_front(Rounds::new(beefy_genesis, genesis_set)); - break PersistedState::checked_new( - best_grandpa, - Zero::zero(), - sessions, - min_block_delta, - beefy_genesis, - ) - .ok_or_else(|| Error::Backend("Invalid BEEFY chain".into()))? - } - - if let Some(active) = find_authorities_change::(&header) { - debug!( - target: LOG_TARGET, - "🥩 Marking block {:?} as BEEFY Mandatory.", - *header.number() - ); - sessions.push_front(Rounds::new(*header.number(), active)); - } - - // Move up the chain. - header = wait_for_parent_header(blockchain, header, HEADER_SYNC_DELAY).await?; - }; - - aux_schema::write_current_version(self.backend.as_ref())?; - aux_schema::write_voter_state(self.backend.as_ref(), &state)?; - Ok(state) - } - - pub async fn load_or_init_state( - &mut self, - beefy_genesis: NumberFor, - best_grandpa: ::Header, - min_block_delta: u32, - ) -> Result, Error> { - // Initialize voter state from AUX DB if compatible. - if let Some(mut state) = crate::aux_schema::load_persistent(self.backend.as_ref())? - // Verify state pallet genesis matches runtime. - .filter(|state| state.pallet_genesis() == beefy_genesis) - { - // Overwrite persisted state with current best GRANDPA block. - state.set_best_grandpa(best_grandpa.clone()); - // Overwrite persisted data with newly provided `min_block_delta`. - state.set_min_block_delta(min_block_delta); - debug!(target: LOG_TARGET, "🥩 Loading BEEFY voter state from db: {:?}.", state); - - // Make sure that all the headers that we need have been synced. - let mut new_sessions = vec![]; - let mut header = best_grandpa.clone(); - while *header.number() > state.best_beefy() { - if state.voting_oracle.can_add_session(*header.number()) { - if let Some(active) = find_authorities_change::(&header) { - new_sessions.push((active, *header.number())); - } - } - header = - wait_for_parent_header(self.backend.blockchain(), header, HEADER_SYNC_DELAY) - .await?; - } - - // Make sure we didn't miss any sessions during node restart. - for (validator_set, new_session_start) in new_sessions.drain(..).rev() { - debug!( - target: LOG_TARGET, - "🥩 Handling missed BEEFY session after node restart: {:?}.", - new_session_start - ); - self.init_session_at(&mut state, validator_set, new_session_start); - } - return Ok(state) - } - - // No valid voter-state persisted, re-initialize from pallet genesis. - self.init_state(beefy_genesis, best_grandpa, min_block_delta).await - } - - /// Verify `active` validator set for `block` against the key store - /// - /// We want to make sure that we have _at least one_ key in our keystore that - /// is part of the validator set, that's because if there are no local keys - /// then we can't perform our job as a validator. - /// - /// Note that for a non-authority node there will be no keystore, and we will - /// return an error and don't check. The error can usually be ignored. - fn verify_validator_set( - &self, - block: &NumberFor, - active: &ValidatorSet, - ) -> Result<(), Error> { - let active: BTreeSet<&AuthorityId> = active.validators().iter().collect(); - - let public_keys = self.key_store.public_keys()?; - let store: BTreeSet<&AuthorityId> = public_keys.iter().collect(); - - if store.intersection(&active).count() == 0 { - let msg = "no authority public key found in store".to_string(); - debug!(target: LOG_TARGET, "🥩 for block {:?} {}", block, msg); - metric_inc!(self.metrics, beefy_no_authority_found_in_store); - Err(Error::Keystore(msg)) - } else { - Ok(()) - } - } /// Handle session changes by starting new voting round for mandatory blocks. - fn init_session_at( + pub fn init_session_at( &mut self, - persisted_state: &mut PersistedState, - validator_set: ValidatorSet, new_session_start: NumberFor, + validator_set: ValidatorSet, + key_store: &BeefyKeystore, + metrics: &Option, ) { debug!(target: LOG_TARGET, "🥩 New active validator set: {:?}", validator_set); // BEEFY should finalize a mandatory block during each session. - if let Ok(active_session) = persisted_state.voting_oracle.active_rounds() { + if let Ok(active_session) = self.voting_oracle.active_rounds() { if !active_session.mandatory_done() { debug!( target: LOG_TARGET, @@ -549,20 +344,20 @@ where validator_set.id(), active_session.validator_set_id(), ); - metric_inc!(self.metrics, beefy_lagging_sessions); + metric_inc!(metrics, beefy_lagging_sessions); } } if log_enabled!(target: LOG_TARGET, log::Level::Debug) { // verify the new validator set - only do it if we're also logging the warning - let _ = self.verify_validator_set(&new_session_start, &validator_set); + if verify_validator_set::(&new_session_start, &validator_set, key_store).is_err() { + metric_inc!(metrics, beefy_no_authority_found_in_store); + } } let id = validator_set.id(); - persisted_state - .voting_oracle - .add_session(Rounds::new(new_session_start, validator_set)); - metric_set!(self.metrics, beefy_validator_set_id, id); + self.voting_oracle.add_session(Rounds::new(new_session_start, validator_set)); + metric_set!(metrics, beefy_validator_set_id, id); info!( target: LOG_TARGET, "🥩 New Rounds for validator set id: {:?} with session_start {:?}", @@ -574,9 +369,10 @@ where /// A BEEFY worker/voter that follows the BEEFY protocol pub(crate) struct BeefyWorker { - pub base: BeefyWorkerBase, - - // utils + // utilities + pub backend: Arc, + pub runtime: Arc, + pub key_store: BeefyKeystore, pub payload_provider: P, pub sync: Arc, @@ -592,6 +388,8 @@ pub(crate) struct BeefyWorker { pub pending_justifications: BTreeMap, BeefyVersionedFinalityProof>, /// Persisted voter state. pub persisted_state: PersistedState, + /// BEEFY voter metrics + pub metrics: Option, } impl BeefyWorker @@ -622,8 +420,12 @@ where validator_set: ValidatorSet, new_session_start: NumberFor, ) { - self.base - .init_session_at(&mut self.persisted_state, validator_set, new_session_start); + self.persisted_state.init_session_at( + new_session_start, + validator_set, + &self.key_store, + &self.metrics, + ); } fn handle_finality_notification( @@ -639,8 +441,7 @@ where notification.tree_route, ); - self.base - .runtime + self.runtime .runtime_api() .beefy_genesis(header.hash()) .ok() @@ -654,7 +455,7 @@ where self.persisted_state.set_best_grandpa(header.clone()); // Check all (newly) finalized blocks for new session(s). - let backend = self.base.backend.clone(); + let backend = self.backend.clone(); for header in notification .tree_route .iter() @@ -673,7 +474,7 @@ where } if new_session_added { - crate::aux_schema::write_voter_state(&*self.base.backend, &self.persisted_state) + crate::aux_schema::write_voter_state(&*self.backend, &self.persisted_state) .map_err(|e| Error::Backend(e.to_string()))?; } @@ -707,7 +508,7 @@ where true, ); }, - RoundAction::Drop => metric_inc!(self.base.metrics, beefy_stale_votes), + RoundAction::Drop => metric_inc!(self.metrics, beefy_stale_votes), RoundAction::Enqueue => error!(target: LOG_TARGET, "🥩 unexpected vote: {:?}.", vote), }; Ok(()) @@ -727,23 +528,23 @@ where match self.voting_oracle().triage_round(block_num)? { RoundAction::Process => { debug!(target: LOG_TARGET, "🥩 Process justification for round: {:?}.", block_num); - metric_inc!(self.base.metrics, beefy_imported_justifications); + metric_inc!(self.metrics, beefy_imported_justifications); self.finalize(justification)? }, RoundAction::Enqueue => { debug!(target: LOG_TARGET, "🥩 Buffer justification for round: {:?}.", block_num); if self.pending_justifications.len() < MAX_BUFFERED_JUSTIFICATIONS { self.pending_justifications.entry(block_num).or_insert(justification); - metric_inc!(self.base.metrics, beefy_buffered_justifications); + metric_inc!(self.metrics, beefy_buffered_justifications); } else { - metric_inc!(self.base.metrics, beefy_buffered_justifications_dropped); + metric_inc!(self.metrics, beefy_buffered_justifications_dropped); warn!( target: LOG_TARGET, "🥩 Buffer justification dropped for round: {:?}.", block_num ); } }, - RoundAction::Drop => metric_inc!(self.base.metrics, beefy_stale_justifications), + RoundAction::Drop => metric_inc!(self.metrics, beefy_stale_justifications), }; Ok(()) } @@ -765,7 +566,7 @@ where // We created the `finality_proof` and know to be valid. // New state is persisted after finalization. self.finalize(finality_proof.clone())?; - metric_inc!(self.base.metrics, beefy_good_votes_processed); + metric_inc!(self.metrics, beefy_good_votes_processed); return Ok(Some(finality_proof)) }, VoteImportResult::Ok => { @@ -776,20 +577,17 @@ where .map(|(mandatory_num, _)| mandatory_num == block_number) .unwrap_or(false) { - crate::aux_schema::write_voter_state( - &*self.base.backend, - &self.persisted_state, - ) - .map_err(|e| Error::Backend(e.to_string()))?; + crate::aux_schema::write_voter_state(&*self.backend, &self.persisted_state) + .map_err(|e| Error::Backend(e.to_string()))?; } - metric_inc!(self.base.metrics, beefy_good_votes_processed); + metric_inc!(self.metrics, beefy_good_votes_processed); }, VoteImportResult::Equivocation(proof) => { - metric_inc!(self.base.metrics, beefy_equivocation_votes); + metric_inc!(self.metrics, beefy_equivocation_votes); self.report_equivocation(proof)?; }, - VoteImportResult::Invalid => metric_inc!(self.base.metrics, beefy_invalid_votes), - VoteImportResult::Stale => metric_inc!(self.base.metrics, beefy_stale_votes), + VoteImportResult::Invalid => metric_inc!(self.metrics, beefy_invalid_votes), + VoteImportResult::Stale => metric_inc!(self.metrics, beefy_stale_votes), }; Ok(None) } @@ -816,15 +614,14 @@ where // Set new best BEEFY block number. self.persisted_state.set_best_beefy(block_num); - crate::aux_schema::write_voter_state(&*self.base.backend, &self.persisted_state) + crate::aux_schema::write_voter_state(&*self.backend, &self.persisted_state) .map_err(|e| Error::Backend(e.to_string()))?; - metric_set!(self.base.metrics, beefy_best_block, block_num); + metric_set!(self.metrics, beefy_best_block, block_num); self.comms.on_demand_justifications.cancel_requests_older_than(block_num); if let Err(e) = self - .base .backend .blockchain() .expect_block_hash_from_id(&BlockId::Number(block_num)) @@ -834,8 +631,7 @@ where .notify(|| Ok::<_, ()>(hash)) .expect("forwards closure result; the closure always returns Ok; qed."); - self.base - .backend + self.backend .append_justification(hash, (BEEFY_ENGINE_ID, finality_proof.encode())) }) { debug!( @@ -872,13 +668,13 @@ where for (num, justification) in justifs_to_process.into_iter() { debug!(target: LOG_TARGET, "🥩 Handle buffered justification for: {:?}.", num); - metric_inc!(self.base.metrics, beefy_imported_justifications); + metric_inc!(self.metrics, beefy_imported_justifications); if let Err(err) = self.finalize(justification) { error!(target: LOG_TARGET, "🥩 Error finalizing block: {}", err); } } metric_set!( - self.base.metrics, + self.metrics, beefy_buffered_justifications, self.pending_justifications.len() ); @@ -890,7 +686,7 @@ where fn try_to_vote(&mut self) -> Result<(), Error> { // Vote if there's now a new vote target. if let Some(target) = self.voting_oracle().voting_target() { - metric_set!(self.base.metrics, beefy_should_vote_on, target); + metric_set!(self.metrics, beefy_should_vote_on, target); if target > self.persisted_state.best_voted { self.do_vote(target)?; } @@ -910,7 +706,6 @@ where self.persisted_state.voting_oracle.best_grandpa_block_header.clone() } else { let hash = self - .base .backend .blockchain() .expect_block_hash_from_id(&BlockId::Number(target_number)) @@ -922,7 +717,7 @@ where Error::Backend(err_msg) })?; - self.base.backend.blockchain().expect_header(hash).map_err(|err| { + self.backend.blockchain().expect_header(hash).map_err(|err| { let err_msg = format!( "Couldn't get header for block #{:?} ({:?}) (error: {:?}), skipping vote..", target_number, hash, err @@ -942,7 +737,7 @@ where let rounds = self.persisted_state.voting_oracle.active_rounds_mut()?; let (validators, validator_set_id) = (rounds.validators(), rounds.validator_set_id()); - let authority_id = if let Some(id) = self.base.key_store.authority_id(validators) { + let authority_id = if let Some(id) = self.key_store.authority_id(validators) { debug!(target: LOG_TARGET, "🥩 Local authority id: {:?}", id); id } else { @@ -956,7 +751,7 @@ where let commitment = Commitment { payload, block_number: target_number, validator_set_id }; let encoded_commitment = commitment.encode(); - let signature = match self.base.key_store.sign(&authority_id, &encoded_commitment) { + let signature = match self.key_store.sign(&authority_id, &encoded_commitment) { Ok(sig) => sig, Err(err) => { warn!(target: LOG_TARGET, "🥩 Error signing commitment: {:?}", err); @@ -981,7 +776,7 @@ where .gossip_engine .gossip_message(proofs_topic::(), encoded_proof, true); } else { - metric_inc!(self.base.metrics, beefy_votes_sent); + metric_inc!(self.metrics, beefy_votes_sent); debug!(target: LOG_TARGET, "🥩 Sent vote message: {:?}", vote); let encoded_vote = GossipMessage::::Vote(vote).encode(); self.comms.gossip_engine.gossip_message(votes_topic::(), encoded_vote, false); @@ -989,8 +784,8 @@ where // Persist state after vote to avoid double voting in case of voter restarts. self.persisted_state.best_voted = target_number; - metric_set!(self.base.metrics, beefy_best_voted, target_number); - crate::aux_schema::write_voter_state(&*self.base.backend, &self.persisted_state) + metric_set!(self.metrics, beefy_best_voted, target_number); + crate::aux_schema::write_voter_state(&*self.backend, &self.persisted_state) .map_err(|e| Error::Backend(e.to_string())) } @@ -1164,7 +959,7 @@ where if !check_equivocation_proof::<_, _, BeefySignatureHasher>(&proof) { debug!(target: LOG_TARGET, "🥩 Skip report for bad equivocation {:?}", proof); return Ok(()) - } else if let Some(local_id) = self.base.key_store.authority_id(validators) { + } else if let Some(local_id) = self.key_store.authority_id(validators) { if offender_id == local_id { warn!(target: LOG_TARGET, "🥩 Skip equivocation report for own equivocation"); return Ok(()) @@ -1173,7 +968,6 @@ where let number = *proof.round_number(); let hash = self - .base .backend .blockchain() .expect_block_hash_from_id(&BlockId::Number(number)) @@ -1184,7 +978,7 @@ where ); Error::Backend(err_msg) })?; - let runtime_api = self.base.runtime.runtime_api(); + let runtime_api = self.runtime.runtime_api(); // generate key ownership proof at that block let key_owner_proof = match runtime_api .generate_key_ownership_proof(hash, validator_set_id, offender_id) @@ -1201,7 +995,7 @@ where }; // submit equivocation report at **best** block - let best_block_hash = self.base.backend.blockchain().info().best_hash; + let best_block_hash = self.backend.blockchain().info().best_hash; runtime_api .submit_report_equivocation_unsigned_extrinsic(best_block_hash, proof, key_owner_proof) .map_err(Error::RuntimeApi)?; @@ -1210,21 +1004,6 @@ where } } -/// Scan the `header` digest log for a BEEFY validator set change. Return either the new -/// validator set or `None` in case no validator set change has been signaled. -pub(crate) fn find_authorities_change(header: &B::Header) -> Option> -where - B: Block, -{ - let id = OpaqueDigestItemId::Consensus(&BEEFY_ENGINE_ID); - - let filter = |log: ConsensusLog| match log { - ConsensusLog::AuthoritiesChange(validator_set) => Some(validator_set), - _ => None, - }; - header.digest().convert_first(|l| l.try_to(id).and_then(filter)) -} - /// Calculate next block number to vote on. /// /// Return `None` if there is no votable target yet. @@ -1261,11 +1040,42 @@ where } } +/// Verify `active` validator set for `block` against the key store +/// +/// We want to make sure that we have _at least one_ key in our keystore that +/// is part of the validator set, that's because if there are no local keys +/// then we can't perform our job as a validator. +/// +/// Note that for a non-authority node there will be no keystore, and we will +/// return an error and don't check. The error can usually be ignored. +fn verify_validator_set( + block: &NumberFor, + active: &ValidatorSet, + key_store: &BeefyKeystore, +) -> Result<(), Error> { + let active: BTreeSet<&AuthorityId> = active.validators().iter().collect(); + + let public_keys = key_store.public_keys()?; + let store: BTreeSet<&AuthorityId> = public_keys.iter().collect(); + + if store.intersection(&active).count() == 0 { + let msg = "no authority public key found in store".to_string(); + debug!(target: LOG_TARGET, "🥩 for block {:?} {}", block, msg); + Err(Error::Keystore(msg)) + } else { + Ok(()) + } +} + #[cfg(test)] pub(crate) mod tests { use super::*; use crate::{ - communication::notification::{BeefyBestBlockStream, BeefyVersionedFinalityProofStream}, + communication::{ + gossip::GossipValidator, + notification::{BeefyBestBlockStream, BeefyVersionedFinalityProofStream}, + request_response::outgoing_requests_engine::OnDemandJustificationsEngine, + }, tests::{ create_beefy_keystore, get_beefy_streams, make_beefy_ids, BeefyPeer, BeefyTestNet, TestApi, @@ -1275,6 +1085,7 @@ pub(crate) mod tests { use futures::{future::poll_fn, task::Poll}; use parking_lot::Mutex; use sc_client_api::{Backend as BackendT, HeaderBackend}; + use sc_network_gossip::GossipEngine; use sc_network_sync::SyncingService; use sc_network_test::TestNetFactory; use sp_blockchain::Backend as BlockchainBackendT; @@ -1283,7 +1094,7 @@ pub(crate) mod tests { known_payloads::MMR_ROOT_ID, mmr::MmrRootProvider, test_utils::{generate_equivocation_proof, Keyring}, - Payload, SignedCommitment, + ConsensusLog, Payload, SignedCommitment, }; use sp_runtime::traits::{Header as HeaderT, One}; use substrate_test_runtime_client::{ @@ -1292,10 +1103,6 @@ pub(crate) mod tests { }; impl PersistedState { - pub fn voting_oracle(&self) -> &VoterOracle { - &self.voting_oracle - } - pub fn active_round(&self) -> Result<&Rounds, Error> { self.voting_oracle.active_rounds() } @@ -1391,13 +1198,10 @@ pub(crate) mod tests { on_demand_justifications, }; BeefyWorker { - base: BeefyWorkerBase { - backend, - runtime: api, - key_store: Some(keystore).into(), - metrics, - _phantom: Default::default(), - }, + backend, + runtime: api, + key_store: Some(keystore).into(), + metrics, payload_provider, sync: Arc::new(sync), links, @@ -1675,19 +1479,22 @@ pub(crate) mod tests { let mut worker = create_beefy_worker(net.peer(0), &keys[0], 1, validator_set.clone()); // keystore doesn't contain other keys than validators' - assert_eq!(worker.base.verify_validator_set(&1, &validator_set), Ok(())); + assert_eq!(verify_validator_set::(&1, &validator_set, &worker.key_store), Ok(())); // unknown `Bob` key let keys = &[Keyring::Bob]; let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap(); let err_msg = "no authority public key found in store".to_string(); let expected = Err(Error::Keystore(err_msg)); - assert_eq!(worker.base.verify_validator_set(&1, &validator_set), expected); + assert_eq!(verify_validator_set::(&1, &validator_set, &worker.key_store), expected); // worker has no keystore - worker.base.key_store = None.into(); + worker.key_store = None.into(); let expected_err = Err(Error::Keystore("no Keystore".into())); - assert_eq!(worker.base.verify_validator_set(&1, &validator_set), expected_err); + assert_eq!( + verify_validator_set::(&1, &validator_set, &worker.key_store), + expected_err + ); } #[tokio::test] @@ -1839,7 +1646,7 @@ pub(crate) mod tests { let mut net = BeefyTestNet::new(1); let mut worker = create_beefy_worker(net.peer(0), &keys[0], 1, validator_set.clone()); - worker.base.runtime = api_alice.clone(); + worker.runtime = api_alice.clone(); // let there be a block with num = 1: let _ = net.peer(0).push_blocks(1, false); diff --git a/substrate/primitives/consensus/beefy/src/commitment.rs b/substrate/primitives/consensus/beefy/src/commitment.rs index 1f0fb34ebf1..335c6b604f0 100644 --- a/substrate/primitives/consensus/beefy/src/commitment.rs +++ b/substrate/primitives/consensus/beefy/src/commitment.rs @@ -97,6 +97,19 @@ pub struct SignedCommitment { pub signatures: Vec>, } +impl sp_std::fmt::Display + for SignedCommitment +{ + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + let signatures_count = self.signatures.iter().filter(|s| s.is_some()).count(); + write!( + f, + "SignedCommitment(commitment: {:?}, signatures_count: {})", + self.commitment, signatures_count + ) + } +} + impl SignedCommitment { /// Return the number of collected signatures. pub fn no_of_signatures(&self) -> usize { @@ -241,6 +254,14 @@ pub enum VersionedFinalityProof { V1(SignedCommitment), } +impl sp_std::fmt::Display for VersionedFinalityProof { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + match self { + VersionedFinalityProof::V1(sc) => write!(f, "VersionedFinalityProof::V1({})", sc), + } + } +} + impl From> for VersionedFinalityProof { fn from(commitment: SignedCommitment) -> Self { VersionedFinalityProof::V1(commitment) -- GitLab From 9bf1a5e23884921498b381728bfddaae93f83744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 22 Feb 2024 14:35:00 +0100 Subject: [PATCH 014/188] Check that the validation code matches the parachain code (#3433) This introduces a check to ensure that the parachain code matches the validation code stored in the relay chain state. If not, it will print a warning. This should be mainly useful for parachain builders to make sure they have setup everything correctly. --- .../consensus/aura/src/collators/basic.rs | 22 +++++++- .../consensus/aura/src/collators/lookahead.rs | 17 ++++-- .../consensus/aura/src/collators/mod.rs | 55 +++++++++++++++++++ cumulus/client/consensus/common/src/tests.rs | 9 +++ cumulus/client/network/src/tests.rs | 9 +++ .../src/lib.rs | 15 ++++- .../client/relay-chain-interface/src/lib.rs | 22 +++++++- .../relay-chain-rpc-interface/src/lib.rs | 13 ++++- .../src/rpc_client.rs | 14 +++++ polkadot/node/core/backing/src/lib.rs | 10 ++-- 10 files changed, 173 insertions(+), 13 deletions(-) diff --git a/cumulus/client/consensus/aura/src/collators/basic.rs b/cumulus/client/consensus/aura/src/collators/basic.rs index 8740b06005d..52b83254951 100644 --- a/cumulus/client/consensus/aura/src/collators/basic.rs +++ b/cumulus/client/consensus/aura/src/collators/basic.rs @@ -33,12 +33,12 @@ use cumulus_relay_chain_interface::RelayChainInterface; use polkadot_node_primitives::CollationResult; use polkadot_overseer::Handle as OverseerHandle; -use polkadot_primitives::{CollatorPair, Id as ParaId}; +use polkadot_primitives::{CollatorPair, Id as ParaId, ValidationCode}; use futures::{channel::mpsc::Receiver, prelude::*}; use sc_client_api::{backend::AuxStore, BlockBackend, BlockOf}; use sc_consensus::BlockImport; -use sp_api::ProvideRuntimeApi; +use sp_api::{CallApiAt, ProvideRuntimeApi}; use sp_application_crypto::AppPublic; use sp_blockchain::HeaderBackend; use sp_consensus::SyncOracle; @@ -47,6 +47,7 @@ use sp_core::crypto::Pair; use sp_inherents::CreateInherentDataProviders; use sp_keystore::KeystorePtr; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Member}; +use sp_state_machine::Backend as _; use std::{convert::TryFrom, sync::Arc, time::Duration}; use crate::collator as collator_util; @@ -100,6 +101,7 @@ where + AuxStore + HeaderBackend + BlockBackend + + CallApiAt + Send + Sync + 'static, @@ -172,6 +174,22 @@ where continue } + let Ok(Some(code)) = + params.para_client.state_at(parent_hash).map_err(drop).and_then(|s| { + s.storage(&sp_core::storage::well_known_keys::CODE).map_err(drop) + }) + else { + continue; + }; + + super::check_validation_code_or_log( + &ValidationCode::from(code).hash(), + params.para_id, + ¶ms.relay_client, + *request.relay_parent(), + ) + .await; + let relay_parent_header = match params.relay_client.header(RBlockId::hash(*request.relay_parent())).await { Err(e) => reject_with_error!(e), diff --git a/cumulus/client/consensus/aura/src/collators/lookahead.rs b/cumulus/client/consensus/aura/src/collators/lookahead.rs index a9f33173d83..161f10d55a1 100644 --- a/cumulus/client/consensus/aura/src/collators/lookahead.rs +++ b/cumulus/client/consensus/aura/src/collators/lookahead.rs @@ -290,10 +290,7 @@ where // If the longest chain has space, build upon that. Otherwise, don't // build at all. potential_parents.sort_by_key(|a| a.depth); - let initial_parent = match potential_parents.pop() { - None => continue, - Some(p) => p, - }; + let Some(initial_parent) = potential_parents.pop() else { continue }; // Build in a loop until not allowed. Note that the authorities can change // at any block, so we need to re-claim our slot every time. @@ -301,6 +298,10 @@ where let mut parent_header = initial_parent.header; let overseer_handle = &mut params.overseer_handle; + // We mainly call this to inform users at genesis if there is a mismatch with the + // on-chain data. + collator.collator_service().check_block_status(parent_hash, &parent_header); + // This needs to change to support elastic scaling, but for continuously // scheduled chains this ensures that the backlog will grow steadily. for n_built in 0..2 { @@ -353,6 +354,14 @@ where Some(v) => v, }; + super::check_validation_code_or_log( + &validation_code_hash, + params.para_id, + ¶ms.relay_client, + relay_parent, + ) + .await; + match collator .collate( &parent_header, diff --git a/cumulus/client/consensus/aura/src/collators/mod.rs b/cumulus/client/consensus/aura/src/collators/mod.rs index 4c7b759daf7..6e0067d0ced 100644 --- a/cumulus/client/consensus/aura/src/collators/mod.rs +++ b/cumulus/client/consensus/aura/src/collators/mod.rs @@ -20,5 +20,60 @@ //! included parachain block, as well as the [`lookahead`] collator, which prospectively //! builds on parachain blocks which have not yet been included in the relay chain. +use cumulus_relay_chain_interface::RelayChainInterface; +use polkadot_primitives::{ + Hash as RHash, Id as ParaId, OccupiedCoreAssumption, ValidationCodeHash, +}; + pub mod basic; pub mod lookahead; + +/// Check the `local_validation_code_hash` against the validation code hash in the relay chain +/// state. +/// +/// If the code hashes do not match, it prints a warning. +async fn check_validation_code_or_log( + local_validation_code_hash: &ValidationCodeHash, + para_id: ParaId, + relay_client: &impl RelayChainInterface, + relay_parent: RHash, +) { + let state_validation_code_hash = match relay_client + .validation_code_hash(relay_parent, para_id, OccupiedCoreAssumption::Included) + .await + { + Ok(hash) => hash, + Err(error) => { + tracing::debug!( + target: super::LOG_TARGET, + %error, + ?relay_parent, + %para_id, + "Failed to fetch validation code hash", + ); + return + }, + }; + + match state_validation_code_hash { + Some(state) => + if state != *local_validation_code_hash { + tracing::warn!( + target: super::LOG_TARGET, + %para_id, + ?relay_parent, + ?local_validation_code_hash, + relay_validation_code_hash = ?state, + "Parachain code doesn't match validation code stored in the relay chain state", + ); + }, + None => { + tracing::warn!( + target: super::LOG_TARGET, + %para_id, + ?relay_parent, + "Could not find validation code for parachain in the relay chain state.", + ); + }, + } +} diff --git a/cumulus/client/consensus/common/src/tests.rs b/cumulus/client/consensus/common/src/tests.rs index 597d1ab2acc..bfb95ae388a 100644 --- a/cumulus/client/consensus/common/src/tests.rs +++ b/cumulus/client/consensus/common/src/tests.rs @@ -136,6 +136,15 @@ impl RelayChainInterface for Relaychain { Ok(Some(PersistedValidationData { parent_head, ..Default::default() })) } + async fn validation_code_hash( + &self, + _: PHash, + _: ParaId, + _: OccupiedCoreAssumption, + ) -> RelayChainResult> { + unimplemented!("Not needed for test") + } + async fn candidate_pending_availability( &self, _: PHash, diff --git a/cumulus/client/network/src/tests.rs b/cumulus/client/network/src/tests.rs index e03f470753b..d986635f961 100644 --- a/cumulus/client/network/src/tests.rs +++ b/cumulus/client/network/src/tests.rs @@ -117,6 +117,15 @@ impl RelayChainInterface for DummyRelayChainInterface { })) } + async fn validation_code_hash( + &self, + _: PHash, + _: ParaId, + _: OccupiedCoreAssumption, + ) -> RelayChainResult> { + unimplemented!("Not needed for test") + } + async fn candidate_pending_availability( &self, _: PHash, diff --git a/cumulus/client/relay-chain-inprocess-interface/src/lib.rs b/cumulus/client/relay-chain-inprocess-interface/src/lib.rs index 866214fe2c5..6ea02b2e7c1 100644 --- a/cumulus/client/relay-chain-inprocess-interface/src/lib.rs +++ b/cumulus/client/relay-chain-inprocess-interface/src/lib.rs @@ -21,7 +21,7 @@ use cumulus_primitives_core::{ relay_chain::{ runtime_api::ParachainHost, Block as PBlock, BlockId, CommittedCandidateReceipt, Hash as PHash, Header as PHeader, InboundHrmpMessage, OccupiedCoreAssumption, SessionIndex, - ValidatorId, + ValidationCodeHash, ValidatorId, }, InboundDownwardMessage, ParaId, PersistedValidationData, }; @@ -115,6 +115,19 @@ impl RelayChainInterface for RelayChainInProcessInterface { )?) } + async fn validation_code_hash( + &self, + hash: PHash, + para_id: ParaId, + occupied_core_assumption: OccupiedCoreAssumption, + ) -> RelayChainResult> { + Ok(self.full_client.runtime_api().validation_code_hash( + hash, + para_id, + occupied_core_assumption, + )?) + } + async fn candidate_pending_availability( &self, hash: PHash, diff --git a/cumulus/client/relay-chain-interface/src/lib.rs b/cumulus/client/relay-chain-interface/src/lib.rs index de5e7891b30..bb93e6a168c 100644 --- a/cumulus/client/relay-chain-interface/src/lib.rs +++ b/cumulus/client/relay-chain-interface/src/lib.rs @@ -30,7 +30,7 @@ use cumulus_primitives_core::relay_chain::BlockId; pub use cumulus_primitives_core::{ relay_chain::{ CommittedCandidateReceipt, Hash as PHash, Header as PHeader, InboundHrmpMessage, - OccupiedCoreAssumption, SessionIndex, ValidatorId, + OccupiedCoreAssumption, SessionIndex, ValidationCodeHash, ValidatorId, }, InboundDownwardMessage, ParaId, PersistedValidationData, }; @@ -194,6 +194,15 @@ pub trait RelayChainInterface: Send + Sync { relay_parent: PHash, relevant_keys: &Vec>, ) -> RelayChainResult; + + /// Returns the validation code hash for the given `para_id` using the given + /// `occupied_core_assumption`. + async fn validation_code_hash( + &self, + relay_parent: PHash, + para_id: ParaId, + occupied_core_assumption: OccupiedCoreAssumption, + ) -> RelayChainResult>; } #[async_trait] @@ -301,4 +310,15 @@ where async fn header(&self, block_id: BlockId) -> RelayChainResult> { (**self).header(block_id).await } + + async fn validation_code_hash( + &self, + relay_parent: PHash, + para_id: ParaId, + occupied_core_assumption: OccupiedCoreAssumption, + ) -> RelayChainResult> { + (**self) + .validation_code_hash(relay_parent, para_id, occupied_core_assumption) + .await + } } diff --git a/cumulus/client/relay-chain-rpc-interface/src/lib.rs b/cumulus/client/relay-chain-rpc-interface/src/lib.rs index 96f8fc8b556..3a4c186e301 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/lib.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/lib.rs @@ -19,7 +19,7 @@ use core::time::Duration; use cumulus_primitives_core::{ relay_chain::{ CommittedCandidateReceipt, Hash as RelayHash, Header as RelayHeader, InboundHrmpMessage, - OccupiedCoreAssumption, SessionIndex, ValidatorId, + OccupiedCoreAssumption, SessionIndex, ValidationCodeHash, ValidatorId, }, InboundDownwardMessage, ParaId, PersistedValidationData, }; @@ -110,6 +110,17 @@ impl RelayChainInterface for RelayChainRpcInterface { .await } + async fn validation_code_hash( + &self, + hash: RelayHash, + para_id: ParaId, + occupied_core_assumption: OccupiedCoreAssumption, + ) -> RelayChainResult> { + self.rpc_client + .validation_code_hash(hash, para_id, occupied_core_assumption) + .await + } + async fn candidate_pending_availability( &self, hash: RelayHash, diff --git a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs index a912997e947..6578210a259 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs @@ -647,6 +647,20 @@ impl RelayChainRpcClient { .await } + pub async fn validation_code_hash( + &self, + at: RelayHash, + para_id: ParaId, + occupied_core_assumption: OccupiedCoreAssumption, + ) -> Result, RelayChainError> { + self.call_remote_runtime_function( + "ParachainHost_validation_code_hash", + at, + Some((para_id, occupied_core_assumption)), + ) + .await + } + fn send_register_message_to_worker( &self, message: RpcDispatcherMessage, diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index cc192607cea..26f20a6d48e 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -1887,18 +1887,20 @@ async fn background_validate_and_make_available( if rp_state.awaiting_validation.insert(candidate_hash) { // spawn background task. let bg = async move { - if let Err(e) = validate_and_make_available(params).await { - if let Error::BackgroundValidationMpsc(error) = e { + if let Err(error) = validate_and_make_available(params).await { + if let Error::BackgroundValidationMpsc(error) = error { gum::debug!( target: LOG_TARGET, + ?candidate_hash, ?error, "Mpsc background validation mpsc died during validation- leaf no longer active?" ); } else { gum::error!( target: LOG_TARGET, - "Failed to validate and make available: {:?}", - e + ?candidate_hash, + ?error, + "Failed to validate and make available", ); } } -- GitLab From e4b6b8cd7973633f86d1b92a56abf2a946b7be84 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 23 Feb 2024 09:51:26 +0100 Subject: [PATCH 015/188] Add support for BHP local and BHK local (#3443) Related to https://github.com/paritytech/polkadot-sdk/issues/3400 Extracting small parts of https://github.com/paritytech/polkadot-sdk/pull/3429 into separate PR: - Add support for BHP local and BHK local - Increase the timeout for the bridge zomienet tests --- bridges/testing/tests/0001-asset-transfer/run.sh | 4 ++-- .../tests/0002-mandatory-headers-synced-while-idle/run.sh | 4 ++-- cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs | 8 ++++++++ cumulus/polkadot-parachain/src/command.rs | 6 ++++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/bridges/testing/tests/0001-asset-transfer/run.sh b/bridges/testing/tests/0001-asset-transfer/run.sh index 8a053ee7209..1e0d6cad301 100755 --- a/bridges/testing/tests/0001-asset-transfer/run.sh +++ b/bridges/testing/tests/0001-asset-transfer/run.sh @@ -8,11 +8,11 @@ source "${BASH_SOURCE%/*}/../../utils/zombienet.sh" ${BASH_SOURCE%/*}/../../environments/rococo-westend/spawn.sh --init --start-relayer & env_pid=$! -ensure_process_file $env_pid $TEST_DIR/rococo.env 400 +ensure_process_file $env_pid $TEST_DIR/rococo.env 600 rococo_dir=`cat $TEST_DIR/rococo.env` echo -ensure_process_file $env_pid $TEST_DIR/westend.env 180 +ensure_process_file $env_pid $TEST_DIR/westend.env 300 westend_dir=`cat $TEST_DIR/westend.env` echo diff --git a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh index 423f4a1bcc0..c39796d51d5 100755 --- a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh +++ b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh @@ -10,11 +10,11 @@ source "${BASH_SOURCE%/*}/../../utils/zombienet.sh" ${BASH_SOURCE%/*}/../../environments/rococo-westend/spawn.sh & env_pid=$! -ensure_process_file $env_pid $TEST_DIR/rococo.env 400 +ensure_process_file $env_pid $TEST_DIR/rococo.env 600 rococo_dir=`cat $TEST_DIR/rococo.env` echo -ensure_process_file $env_pid $TEST_DIR/westend.env 180 +ensure_process_file $env_pid $TEST_DIR/westend.env 300 westend_dir=`cat $TEST_DIR/westend.env` echo diff --git a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs index 1db826ea7da..15e8a1bf11a 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs @@ -25,7 +25,10 @@ use std::str::FromStr; #[derive(Debug, PartialEq)] pub enum BridgeHubRuntimeType { Kusama, + KusamaLocal, + Polkadot, + PolkadotLocal, Rococo, RococoLocal, @@ -44,7 +47,9 @@ impl FromStr for BridgeHubRuntimeType { fn from_str(value: &str) -> Result { match value { polkadot::BRIDGE_HUB_POLKADOT => Ok(BridgeHubRuntimeType::Polkadot), + polkadot::BRIDGE_HUB_POLKADOT_LOCAL => Ok(BridgeHubRuntimeType::PolkadotLocal), kusama::BRIDGE_HUB_KUSAMA => Ok(BridgeHubRuntimeType::Kusama), + kusama::BRIDGE_HUB_KUSAMA_LOCAL => Ok(BridgeHubRuntimeType::KusamaLocal), westend::BRIDGE_HUB_WESTEND => Ok(BridgeHubRuntimeType::Westend), westend::BRIDGE_HUB_WESTEND_LOCAL => Ok(BridgeHubRuntimeType::WestendLocal), westend::BRIDGE_HUB_WESTEND_DEVELOPMENT => Ok(BridgeHubRuntimeType::WestendDevelopment), @@ -103,6 +108,7 @@ impl BridgeHubRuntimeType { Some("Bob".to_string()), |_| (), ))), + other => Err(std::format!("No default config present for {:?}", other)), } } } @@ -242,6 +248,7 @@ pub mod rococo { /// Sub-module for Kusama setup pub mod kusama { pub(crate) const BRIDGE_HUB_KUSAMA: &str = "bridge-hub-kusama"; + pub(crate) const BRIDGE_HUB_KUSAMA_LOCAL: &str = "bridge-hub-kusama-local"; } /// Sub-module for Westend setup. @@ -358,4 +365,5 @@ pub mod westend { /// Sub-module for Polkadot setup pub mod polkadot { pub(crate) const BRIDGE_HUB_POLKADOT: &str = "bridge-hub-polkadot"; + pub(crate) const BRIDGE_HUB_POLKADOT_LOCAL: &str = "bridge-hub-polkadot-local"; } diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index acba32f048b..a40c356dcd1 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -755,14 +755,16 @@ pub fn run() -> Result<()> { .map_err(Into::into), BridgeHub(bridge_hub_runtime_type) => match bridge_hub_runtime_type { - chain_spec::bridge_hubs::BridgeHubRuntimeType::Polkadot => + chain_spec::bridge_hubs::BridgeHubRuntimeType::Polkadot | + chain_spec::bridge_hubs::BridgeHubRuntimeType::PolkadotLocal => crate::service::start_generic_aura_node::< RuntimeApi, AuraId, >(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0), - chain_spec::bridge_hubs::BridgeHubRuntimeType::Kusama => + chain_spec::bridge_hubs::BridgeHubRuntimeType::Kusama | + chain_spec::bridge_hubs::BridgeHubRuntimeType::KusamaLocal => crate::service::start_generic_aura_node::< RuntimeApi, AuraId, -- GitLab From 11b5354fd3ced03003da1901aba704791f367849 Mon Sep 17 00:00:00 2001 From: Ignacio Palacios Date: Fri, 23 Feb 2024 12:54:54 +0100 Subject: [PATCH 016/188] Fix `DepositReserveAsset` fees payment (#3340) The `fee` should be calculated with the reanchored asset, otherwise it could lead to a failure where the set aside fee ends up not being enough. @acatangiu --------- Co-authored-by: Adrian Catangiu --- Cargo.lock | 2 + polkadot/node/test/service/src/chain_spec.rs | 1 + .../runtime/test-runtime/src/xcm_config.rs | 54 +++++++++--- .../xcm-executor/integration-tests/Cargo.toml | 2 + .../xcm-executor/integration-tests/src/lib.rs | 83 +++++++++++++++++++ polkadot/xcm/xcm-executor/src/lib.rs | 4 +- 6 files changed, 132 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 950b4e0889a..d9791ec0147 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22323,10 +22323,12 @@ dependencies = [ "pallet-transaction-payment", "pallet-xcm", "parity-scale-codec", + "polkadot-service", "polkadot-test-client", "polkadot-test-runtime", "polkadot-test-service", "sp-consensus", + "sp-core", "sp-keyring", "sp-runtime", "sp-state-machine", diff --git a/polkadot/node/test/service/src/chain_spec.rs b/polkadot/node/test/service/src/chain_spec.rs index 0295090b952..4cc387317c3 100644 --- a/polkadot/node/test/service/src/chain_spec.rs +++ b/polkadot/node/test/service/src/chain_spec.rs @@ -169,6 +169,7 @@ fn polkadot_testnet_genesis( paras_availability_period: 4, no_show_slots: 10, minimum_validation_upgrade_delay: 5, + max_downward_message_size: 1024, ..Default::default() }, } diff --git a/polkadot/runtime/test-runtime/src/xcm_config.rs b/polkadot/runtime/test-runtime/src/xcm_config.rs index a81d35f4d78..a48bca17e9f 100644 --- a/polkadot/runtime/test-runtime/src/xcm_config.rs +++ b/polkadot/runtime/test-runtime/src/xcm_config.rs @@ -16,14 +16,16 @@ use frame_support::{ parameter_types, - traits::{Everything, Nothing}, + traits::{Everything, Get, Nothing}, weights::Weight, }; use frame_system::EnsureRoot; +use polkadot_runtime_parachains::FeeTracker; +use runtime_common::xcm_sender::{ChildParachainRouter, PriceForMessageDelivery}; use xcm::latest::prelude::*; use xcm_builder::{ AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, - SignedAccountId32AsNative, SignedToAccountId32, + SignedAccountId32AsNative, SignedToAccountId32, WithUniqueTopic, }; use xcm_executor::{ traits::{TransactAsset, WeightTrader}, @@ -36,6 +38,8 @@ parameter_types! { pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 16; pub const UniversalLocation: xcm::latest::InteriorLocation = xcm::latest::Junctions::Here; + pub TokenLocation: Location = Here.into_location(); + pub FeeAssetId: AssetId = AssetId(TokenLocation::get()); } /// Type to convert an `Origin` type value into a `Location` value which represents an interior @@ -45,17 +49,43 @@ pub type LocalOriginToLocation = ( SignedToAccountId32, ); -pub struct DoNothingRouter; -impl SendXcm for DoNothingRouter { - type Ticket = (); - fn validate(_dest: &mut Option, _msg: &mut Option>) -> SendResult<()> { - Ok(((), Assets::new())) - } - fn deliver(_: ()) -> Result { - Ok([0; 32]) +/// Implementation of [`PriceForMessageDelivery`], returning a different price +/// based on whether a message contains a reanchored asset or not. +/// This implementation ensures that messages with non-reanchored assets return higher +/// prices than messages with reanchored assets. +/// Useful for `deposit_reserve_asset_works_for_any_xcm_sender` integration test. +pub struct TestDeliveryPrice(sp_std::marker::PhantomData<(A, F)>); +impl, F: FeeTracker> PriceForMessageDelivery for TestDeliveryPrice { + type Id = F::Id; + + fn price_for_delivery(_: Self::Id, msg: &Xcm<()>) -> Assets { + let base_fee: super::Balance = 1_000_000; + + let parents = msg.iter().find_map(|xcm| match xcm { + ReserveAssetDeposited(assets) => { + let AssetId(location) = &assets.inner().first().unwrap().id; + Some(location.parents) + }, + _ => None, + }); + + // If no asset is found, price defaults to `base_fee`. + let amount = base_fee + .saturating_add(base_fee.saturating_mul(parents.unwrap_or(0) as super::Balance)); + + (A::get(), amount).into() } } +pub type PriceForChildParachainDelivery = TestDeliveryPrice; + +/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our +/// individual routers. +pub type XcmRouter = WithUniqueTopic< + // Only one router so far - use DMP to communicate with child parachains. + ChildParachainRouter, +>; + pub type Barrier = AllowUnpaidExecutionFrom; pub struct DummyAssetTransactor; @@ -99,7 +129,7 @@ type OriginConverter = ( pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = super::RuntimeCall; - type XcmSender = DoNothingRouter; + type XcmSender = XcmRouter; type AssetTransactor = DummyAssetTransactor; type OriginConverter = OriginConverter; type IsReserve = (); @@ -133,7 +163,7 @@ impl pallet_xcm::Config for crate::Runtime { type UniversalLocation = UniversalLocation; type SendXcmOrigin = EnsureXcmOrigin; type Weigher = FixedWeightBounds; - type XcmRouter = DoNothingRouter; + type XcmRouter = XcmRouter; type XcmExecuteFilter = Everything; type XcmExecutor = xcm_executor::XcmExecutor; type XcmTeleportFilter = Everything; diff --git a/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml b/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml index cafe12dc587..1e572e6210a 100644 --- a/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml +++ b/polkadot/xcm/xcm-executor/integration-tests/Cargo.toml @@ -20,6 +20,7 @@ pallet-xcm = { path = "../../pallet-xcm" } polkadot-test-client = { path = "../../../node/test/client" } polkadot-test-runtime = { path = "../../../runtime/test-runtime" } polkadot-test-service = { path = "../../../node/test/service" } +polkadot-service = { path = "../../../node/service" } sp-consensus = { path = "../../../../substrate/primitives/consensus/common" } sp-keyring = { path = "../../../../substrate/primitives/keyring" } sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false } @@ -27,6 +28,7 @@ sp-state-machine = { path = "../../../../substrate/primitives/state-machine" } xcm = { package = "staging-xcm", path = "../..", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = ".." } sp-tracing = { path = "../../../../substrate/primitives/tracing" } +sp-core = { path = "../../../../substrate/primitives/core" } [features] default = ["std"] diff --git a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs index 79d6cb1c411..da7fc0d9782 100644 --- a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs +++ b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs @@ -19,12 +19,14 @@ use codec::Encode; use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; +use polkadot_service::chain_spec::get_account_id_from_seed; use polkadot_test_client::{ BlockBuilderExt, ClientBlockImportExt, DefaultTestClientBuilderExt, InitPolkadotBlockBuilder, TestClientBuilder, TestClientBuilderExt, }; use polkadot_test_runtime::{pallet_test_notifier, xcm_config::XcmConfig}; use polkadot_test_service::construct_extrinsic; +use sp_core::sr25519; use sp_runtime::traits::Block; use sp_state_machine::InspectState; use xcm::{latest::prelude::*, VersionedResponse, VersionedXcm}; @@ -323,3 +325,84 @@ fn query_response_elicits_handler() { ))); }); } + +/// Simulates a cross-chain message from Parachain to Parachain through Relay Chain +/// that deposits assets into the reserve of the destination. +/// Regression test for `DepostiReserveAsset` changes in +/// +#[test] +fn deposit_reserve_asset_works_for_any_xcm_sender() { + sp_tracing::try_init_simple(); + let mut client = TestClientBuilder::new().build(); + + // Init values for the simulated origin Parachain + let amount_to_send: u128 = 1_000_000_000_000; + let assets: Assets = (Parent, amount_to_send).into(); + let fee_asset_item = 0; + let max_assets = assets.len() as u32; + let fees = assets.get(fee_asset_item as usize).unwrap().clone(); + let weight_limit = Unlimited; + let reserve = Location::parent(); + let dest = Location::new(1, [Parachain(2000)]); + let beneficiary_id = get_account_id_from_seed::("Alice"); + let beneficiary = Location::new(0, [AccountId32 { network: None, id: beneficiary_id.into() }]); + + // spends up to half of fees for execution on reserve and other half for execution on + // destination + let fee1 = amount_to_send.saturating_div(2); + let fee2 = amount_to_send.saturating_sub(fee1); + let fees_half_1 = Asset::from((fees.id.clone(), Fungible(fee1))); + let fees_half_2 = Asset::from((fees.id.clone(), Fungible(fee2))); + + let reserve_context = ::UniversalLocation::get(); + // identifies fee item as seen by `reserve` - to be used at reserve chain + let reserve_fees = fees_half_1.reanchored(&reserve, &reserve_context).unwrap(); + // identifies fee item as seen by `dest` - to be used at destination chain + let dest_fees = fees_half_2.reanchored(&dest, &reserve_context).unwrap(); + // identifies assets as seen by `reserve` - to be used at reserve chain + let assets_reanchored = assets.reanchored(&reserve, &reserve_context).unwrap(); + // identifies `dest` as seen by `reserve` + let dest = dest.reanchored(&reserve, &reserve_context).unwrap(); + // xcm to be executed at dest + let xcm_on_dest = Xcm(vec![ + BuyExecution { fees: dest_fees, weight_limit: weight_limit.clone() }, + DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + ]); + // xcm to be executed at reserve + let msg = Xcm(vec![ + WithdrawAsset(assets_reanchored), + ClearOrigin, + BuyExecution { fees: reserve_fees, weight_limit }, + DepositReserveAsset { assets: Wild(AllCounted(max_assets)), dest, xcm: xcm_on_dest }, + ]); + + let mut block_builder = client.init_polkadot_block_builder(); + + // Simulate execution of an incoming XCM message at the reserve chain + let execute = construct_extrinsic( + &client, + polkadot_test_runtime::RuntimeCall::Xcm(pallet_xcm::Call::execute { + message: Box::new(VersionedXcm::from(msg)), + max_weight: Weight::from_parts(1_000_000_000, 1024 * 1024), + }), + sp_keyring::Sr25519Keyring::Alice, + 0, + ); + + block_builder.push_polkadot_extrinsic(execute).expect("pushes extrinsic"); + + let block = block_builder.build().expect("Finalizes the block").block; + let block_hash = block.hash(); + + futures::executor::block_on(client.import(sp_consensus::BlockOrigin::Own, block)) + .expect("imports the block"); + + client.state_at(block_hash).expect("state should exist").inspect_state(|| { + assert!(polkadot_test_runtime::System::events().iter().any(|r| matches!( + r.event, + polkadot_test_runtime::RuntimeEvent::Xcm(pallet_xcm::Event::Attempted { + outcome: Outcome::Complete { .. } + }), + ))); + }); +} diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index b26779f3ae9..c61e1e1d15b 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -826,9 +826,9 @@ impl XcmExecutor { // be weighed let to_weigh = self.holding.saturating_take(assets.clone()); self.holding.subsume_assets(to_weigh.clone()); - + let to_weigh_reanchored = Self::reanchored(to_weigh, &dest, None); let mut message_to_weigh = - vec![ReserveAssetDeposited(to_weigh.into()), ClearOrigin]; + vec![ReserveAssetDeposited(to_weigh_reanchored), ClearOrigin]; message_to_weigh.extend(xcm.0.clone().into_iter()); let (_, fee) = validate_send::(dest.clone(), Xcm(message_to_weigh))?; -- GitLab From 64050cf3474adb8705991f8e3a0e2fd36bf5dcd4 Mon Sep 17 00:00:00 2001 From: Sebastian Kunert Date: Fri, 23 Feb 2024 14:04:10 +0100 Subject: [PATCH 017/188] prdoc: Print errors on CI (#3459) By passing `RUST_LOG=info` to the check command, we will be able to see the exact problem with a given prdoc. Before: ``` PR #3243 -> ERR ``` After: ``` [2024-02-23T12:53:55Z INFO prdoclib::commands::check] Checking directory prdoc [2024-02-23T12:53:55Z INFO prdoclib::commands::check] Using schema: /Users/sebastian/work/repos/polkadot-sdk/prdoc/schema_user.json [2024-02-23T12:53:55Z WARN prdoclib::schema] validation_result: false [2024-02-23T12:53:55Z WARN prdoclib::schema] validation_result_strict: false [2024-02-23T12:53:55Z WARN prdoclib::schema] errors: [ Required { path: "/title", }, ] [2024-02-23T12:53:55Z WARN prdoclib::schema] missing: [] [2024-02-23T12:53:55Z ERROR prdoclib::commands::check] Loading the schema failed: [2024-02-23T12:53:55Z ERROR prdoclib::commands::check] ValidationErrors(ValidationState { errors: [Required { path: "/title" }], missing: [], replacement: None, evaluated: {"/doc/0/description", "/crates/0/name", "/doc/0", "/crates", "/crates/0", "", "/doc", "/doc/0/audience"} }) PR #3243 -> ERR ``` --- .github/workflows/check-prdoc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-prdoc.yml b/.github/workflows/check-prdoc.yml index 5503b61d681..91701ca036e 100644 --- a/.github/workflows/check-prdoc.yml +++ b/.github/workflows/check-prdoc.yml @@ -56,4 +56,4 @@ jobs: run: | echo "Checking for PR#${GITHUB_PR}" echo "You can find more information about PRDoc at $PRDOC_DOC" - $ENGINE run --rm -v $PWD:/repo $IMAGE check -n ${GITHUB_PR} + $ENGINE run --rm -v $PWD:/repo -e RUST_LOG=info $IMAGE check -n ${GITHUB_PR} -- GitLab From f2645eec12f080a66228aedbeaecea2c913570ed Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Fri, 23 Feb 2024 14:10:06 +0100 Subject: [PATCH 018/188] Contracts Add new version for marking new stable API (#3415) Add a `ApiVersion` constant to the pallet-contracts Config to communicate with developers the current state of the host functions exposed by the pallet --- .../contracts-rococo/src/contracts.rs | 1 + prdoc/pr_3415.prdoc | 9 +++++++++ substrate/bin/node/runtime/src/lib.rs | 1 + .../src/parachain/contracts_config.rs | 1 + substrate/frame/contracts/src/lib.rs | 18 ++++++++++++++++++ substrate/frame/contracts/src/tests.rs | 1 + 6 files changed, 31 insertions(+) create mode 100644 prdoc/pr_3415.prdoc diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs index 7b89f2df807..681b95ce6a5 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs @@ -72,5 +72,6 @@ impl Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type Debug = (); type Environment = (); + type ApiVersion = (); type Xcm = pallet_xcm::Pallet; } diff --git a/prdoc/pr_3415.prdoc b/prdoc/pr_3415.prdoc new file mode 100644 index 00000000000..c56a5d3ffaa --- /dev/null +++ b/prdoc/pr_3415.prdoc @@ -0,0 +1,9 @@ +title: "[pallet-contracts] Add APIVersion to the config." + +doc: + - audience: Runtime Dev + description: | + Add `APIVersion` to the config to communicate the state of the Host functions exposed by the pallet. + +crates: + - name: pallet-contracts diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 24c8f6f48e9..b34d8c89e56 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1367,6 +1367,7 @@ impl pallet_contracts::Config for Runtime { type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; type Debug = (); type Environment = (); + type ApiVersion = (); type Xcm = (); } diff --git a/substrate/frame/contracts/mock-network/src/parachain/contracts_config.rs b/substrate/frame/contracts/mock-network/src/parachain/contracts_config.rs index dadba394e26..3f26c6f372e 100644 --- a/substrate/frame/contracts/mock-network/src/parachain/contracts_config.rs +++ b/substrate/frame/contracts/mock-network/src/parachain/contracts_config.rs @@ -94,5 +94,6 @@ impl pallet_contracts::Config for Runtime { type WeightPrice = Self; type Debug = (); type Environment = (); + type ApiVersion = (); type Xcm = pallet_xcm::Pallet; } diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs index 943bf5f85d4..d8939ee88ba 100644 --- a/substrate/frame/contracts/src/lib.rs +++ b/substrate/frame/contracts/src/lib.rs @@ -214,6 +214,18 @@ pub struct Environment { block_number: EnvironmentType>, } +/// Defines the current version of the HostFn APIs. +/// This is used to communicate the available APIs in pallet-contracts. +/// +/// The version is bumped any time a new HostFn is added or stabilized. +#[derive(Encode, Decode, TypeInfo)] +pub struct ApiVersion(u16); +impl Default for ApiVersion { + fn default() -> Self { + Self(1) + } +} + #[frame_support::pallet] pub mod pallet { use super::*; @@ -402,6 +414,12 @@ pub mod pallet { #[pallet::constant] type Environment: Get>; + /// The version of the HostFn APIs that are available in the runtime. + /// + /// Only valid value is `()`. + #[pallet::constant] + type ApiVersion: Get; + /// A type that exposes XCM APIs, allowing contracts to interact with other parachains, and /// execute XCM programs. type Xcm: xcm_builder::Controller< diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index b39fc79b62a..2d1c5b315a3 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -465,6 +465,7 @@ impl Config for Test { type MaxDelegateDependencies = MaxDelegateDependencies; type Debug = TestDebug; type Environment = (); + type ApiVersion = (); type Xcm = (); } -- GitLab From 5fc6d67be081b4f2638d3d46d0002f95392b370c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Pa=C4=8Dandi?= <3002868+Dinonard@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:56:32 +0100 Subject: [PATCH 019/188] pallet-membership weights (#3324) ## Summary * use benchamarked weights instead of hardcoded ones for `pallet-membership` * rename benchmark to match extrinsic name * remove unnecessary dependency from `clear_prime` --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi --- prdoc/pr_3324.prdoc | 13 +++ substrate/frame/membership/src/lib.rs | 124 ++++++++++++++-------- substrate/frame/membership/src/weights.rs | 18 ++-- 3 files changed, 99 insertions(+), 56 deletions(-) create mode 100644 prdoc/pr_3324.prdoc diff --git a/prdoc/pr_3324.prdoc b/prdoc/pr_3324.prdoc new file mode 100644 index 00000000000..0425fbf317c --- /dev/null +++ b/prdoc/pr_3324.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Fix weight calculation and event emission in pallet-membership" + +doc: + - audience: Runtime Dev + description: | + Bug fix for the membership pallet to use correct weights. Also no event will be emitted + anymore when `change_key` is called with identical accounts. + +crates: + - name: pallet-membership diff --git a/substrate/frame/membership/src/lib.rs b/substrate/frame/membership/src/lib.rs index 19b5e54d308..f3226397003 100644 --- a/substrate/frame/membership/src/lib.rs +++ b/substrate/frame/membership/src/lib.rs @@ -27,7 +27,7 @@ use frame_support::{ traits::{ChangeMembers, Contains, Get, InitializeMembers, SortedMembers}, BoundedVec, }; -use sp_runtime::traits::StaticLookup; +use sp_runtime::traits::{StaticLookup, UniqueSaturatedInto}; use sp_std::prelude::*; pub mod migrations; @@ -163,12 +163,16 @@ pub mod pallet { /// /// May only be called from `T::AddOrigin`. #[pallet::call_index(0)] - #[pallet::weight({50_000_000})] - pub fn add_member(origin: OriginFor, who: AccountIdLookupOf) -> DispatchResult { + #[pallet::weight(T::WeightInfo::add_member(T::MaxMembers::get()))] + pub fn add_member( + origin: OriginFor, + who: AccountIdLookupOf, + ) -> DispatchResultWithPostInfo { T::AddOrigin::ensure_origin(origin)?; let who = T::Lookup::lookup(who)?; let mut members = >::get(); + let init_length = members.len(); let location = members.binary_search(&who).err().ok_or(Error::::AlreadyMember)?; members .try_insert(location, who.clone()) @@ -179,19 +183,24 @@ pub mod pallet { T::MembershipChanged::change_members_sorted(&[who], &[], &members[..]); Self::deposit_event(Event::MemberAdded); - Ok(()) + + Ok(Some(T::WeightInfo::add_member(init_length as u32)).into()) } /// Remove a member `who` from the set. /// /// May only be called from `T::RemoveOrigin`. #[pallet::call_index(1)] - #[pallet::weight({50_000_000})] - pub fn remove_member(origin: OriginFor, who: AccountIdLookupOf) -> DispatchResult { + #[pallet::weight(T::WeightInfo::remove_member(T::MaxMembers::get()))] + pub fn remove_member( + origin: OriginFor, + who: AccountIdLookupOf, + ) -> DispatchResultWithPostInfo { T::RemoveOrigin::ensure_origin(origin)?; let who = T::Lookup::lookup(who)?; let mut members = >::get(); + let init_length = members.len(); let location = members.binary_search(&who).ok().ok_or(Error::::NotMember)?; members.remove(location); @@ -201,7 +210,7 @@ pub mod pallet { Self::rejig_prime(&members); Self::deposit_event(Event::MemberRemoved); - Ok(()) + Ok(Some(T::WeightInfo::remove_member(init_length as u32)).into()) } /// Swap out one member `remove` for another `add`. @@ -210,18 +219,18 @@ pub mod pallet { /// /// Prime membership is *not* passed from `remove` to `add`, if extant. #[pallet::call_index(2)] - #[pallet::weight({50_000_000})] + #[pallet::weight(T::WeightInfo::swap_member(T::MaxMembers::get()))] pub fn swap_member( origin: OriginFor, remove: AccountIdLookupOf, add: AccountIdLookupOf, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { T::SwapOrigin::ensure_origin(origin)?; let remove = T::Lookup::lookup(remove)?; let add = T::Lookup::lookup(add)?; if remove == add { - return Ok(()) + return Ok(().into()); } let mut members = >::get(); @@ -236,7 +245,7 @@ pub mod pallet { Self::rejig_prime(&members); Self::deposit_event(Event::MembersSwapped); - Ok(()) + Ok(Some(T::WeightInfo::swap_member(members.len() as u32)).into()) } /// Change the membership to a new set, disregarding the existing membership. Be nice and @@ -244,7 +253,7 @@ pub mod pallet { /// /// May only be called from `T::ResetOrigin`. #[pallet::call_index(3)] - #[pallet::weight({50_000_000})] + #[pallet::weight(T::WeightInfo::reset_members(members.len().unique_saturated_into()))] pub fn reset_members(origin: OriginFor, members: Vec) -> DispatchResult { T::ResetOrigin::ensure_origin(origin)?; @@ -267,56 +276,65 @@ pub mod pallet { /// /// Prime membership is passed from the origin account to `new`, if extant. #[pallet::call_index(4)] - #[pallet::weight({50_000_000})] - pub fn change_key(origin: OriginFor, new: AccountIdLookupOf) -> DispatchResult { + #[pallet::weight(T::WeightInfo::change_key(T::MaxMembers::get()))] + pub fn change_key( + origin: OriginFor, + new: AccountIdLookupOf, + ) -> DispatchResultWithPostInfo { let remove = ensure_signed(origin)?; let new = T::Lookup::lookup(new)?; - if remove != new { - let mut members = >::get(); - let location = - members.binary_search(&remove).ok().ok_or(Error::::NotMember)?; - let _ = members.binary_search(&new).err().ok_or(Error::::AlreadyMember)?; - members[location] = new.clone(); - members.sort(); - - >::put(&members); - - T::MembershipChanged::change_members_sorted( - &[new.clone()], - &[remove.clone()], - &members[..], - ); - - if Prime::::get() == Some(remove) { - Prime::::put(&new); - T::MembershipChanged::set_prime(Some(new)); - } + if remove == new { + return Ok(().into()); + } + + let mut members = >::get(); + let members_length = members.len() as u32; + let location = members.binary_search(&remove).ok().ok_or(Error::::NotMember)?; + let _ = members.binary_search(&new).err().ok_or(Error::::AlreadyMember)?; + members[location] = new.clone(); + members.sort(); + + >::put(&members); + + T::MembershipChanged::change_members_sorted( + &[new.clone()], + &[remove.clone()], + &members[..], + ); + + if Prime::::get() == Some(remove) { + Prime::::put(&new); + T::MembershipChanged::set_prime(Some(new)); } Self::deposit_event(Event::KeyChanged); - Ok(()) + Ok(Some(T::WeightInfo::change_key(members_length)).into()) } /// Set the prime member. Must be a current member. /// /// May only be called from `T::PrimeOrigin`. #[pallet::call_index(5)] - #[pallet::weight({50_000_000})] - pub fn set_prime(origin: OriginFor, who: AccountIdLookupOf) -> DispatchResult { + #[pallet::weight(T::WeightInfo::set_prime(T::MaxMembers::get()))] + pub fn set_prime( + origin: OriginFor, + who: AccountIdLookupOf, + ) -> DispatchResultWithPostInfo { T::PrimeOrigin::ensure_origin(origin)?; let who = T::Lookup::lookup(who)?; - Self::members().binary_search(&who).ok().ok_or(Error::::NotMember)?; + let members = Self::members(); + members.binary_search(&who).ok().ok_or(Error::::NotMember)?; Prime::::put(&who); T::MembershipChanged::set_prime(Some(who)); - Ok(()) + Ok(Some(T::WeightInfo::set_prime(members.len() as u32)).into()) } /// Remove the prime member if it exists. /// /// May only be called from `T::PrimeOrigin`. #[pallet::call_index(6)] - #[pallet::weight({50_000_000})] + #[pallet::weight(T::WeightInfo::clear_prime())] pub fn clear_prime(origin: OriginFor) -> DispatchResult { T::PrimeOrigin::ensure_origin(origin)?; Prime::::kill(); @@ -442,7 +460,7 @@ mod benchmark { } // er keep the prime common between incoming and outgoing to make sure it is rejigged. - reset_member { + reset_members { let m in 1 .. T::MaxMembers::get(); let members = (1..m+1).map(|i| account("member", i, SEED)).collect::>(); @@ -500,8 +518,7 @@ mod benchmark { } clear_prime { - let m in 1 .. T::MaxMembers::get(); - let members = (0..m).map(|i| account("member", i, SEED)).collect::>(); + let members = (0..T::MaxMembers::get()).map(|i| account("member", i, SEED)).collect::>(); let prime = members.last().cloned().unwrap(); set_members::(members, None); }: { @@ -526,7 +543,8 @@ mod tests { use sp_runtime::{bounded_vec, traits::BadOrigin, BuildStorage}; use frame_support::{ - assert_noop, assert_ok, derive_impl, ord_parameter_types, parameter_types, + assert_noop, assert_ok, assert_storage_noop, derive_impl, ord_parameter_types, + parameter_types, traits::{ConstU32, StorageVersion}, }; use frame_system::EnsureSignedBy; @@ -716,6 +734,17 @@ mod tests { }); } + #[test] + fn swap_member_with_identical_arguments_changes_nothing() { + new_test_ext().execute_with(|| { + assert_storage_noop!(assert_ok!(Membership::swap_member( + RuntimeOrigin::signed(3), + 10, + 10 + ))); + }); + } + #[test] fn change_key_works() { new_test_ext().execute_with(|| { @@ -745,6 +774,13 @@ mod tests { }); } + #[test] + fn change_key_with_same_caller_as_argument_changes_nothing() { + new_test_ext().execute_with(|| { + assert_storage_noop!(assert_ok!(Membership::change_key(RuntimeOrigin::signed(10), 10))); + }); + } + #[test] fn reset_members_works() { new_test_ext().execute_with(|| { diff --git a/substrate/frame/membership/src/weights.rs b/substrate/frame/membership/src/weights.rs index 18ea7fcb315..2d18848b89a 100644 --- a/substrate/frame/membership/src/weights.rs +++ b/substrate/frame/membership/src/weights.rs @@ -55,10 +55,10 @@ pub trait WeightInfo { fn add_member(m: u32, ) -> Weight; fn remove_member(m: u32, ) -> Weight; fn swap_member(m: u32, ) -> Weight; - fn reset_member(m: u32, ) -> Weight; + fn reset_members(m: u32, ) -> Weight; fn change_key(m: u32, ) -> Weight; fn set_prime(m: u32, ) -> Weight; - fn clear_prime(m: u32, ) -> Weight; + fn clear_prime() -> Weight; } /// Weights for pallet_membership using the Substrate node and recommended hardware. @@ -142,7 +142,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: TechnicalCommittee Prime (r:0 w:1) /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. - fn reset_member(m: u32, ) -> Weight { + fn reset_members(m: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` @@ -200,15 +200,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) /// Storage: TechnicalCommittee Prime (r:0 w:1) /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `m` is `[1, 100]`. - fn clear_prime(m: u32, ) -> Weight { + fn clear_prime() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` // Minimum execution time: 3_373_000 picoseconds. Weight::from_parts(3_750_452, 0) - // Standard Error: 142 - .saturating_add(Weight::from_parts(505, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().writes(2_u64)) } } @@ -293,7 +290,7 @@ impl WeightInfo for () { /// Storage: TechnicalCommittee Prime (r:0 w:1) /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. - fn reset_member(m: u32, ) -> Weight { + fn reset_members(m: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` @@ -351,15 +348,12 @@ impl WeightInfo for () { /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) /// Storage: TechnicalCommittee Prime (r:0 w:1) /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `m` is `[1, 100]`. - fn clear_prime(m: u32, ) -> Weight { + fn clear_prime() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` // Minimum execution time: 3_373_000 picoseconds. Weight::from_parts(3_750_452, 0) - // Standard Error: 142 - .saturating_add(Weight::from_parts(505, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().writes(2_u64)) } } -- GitLab From 3386377b0f88cb2c7cfafe8a5f5b3b41b85dde59 Mon Sep 17 00:00:00 2001 From: Sebastian Kunert Date: Fri, 23 Feb 2024 15:09:49 +0100 Subject: [PATCH 020/188] PoV Reclaim Runtime Side (#3002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Runtime side for PoV Reclaim ## Implementation Overview - Hostfunction to fetch the storage proof size has been added to the PVF. It uses the size tracking recorder that was introduced in my previous PR. - Mechanisms to use the reclaim HostFunction have been introduced. - 1. A SignedExtension that checks the node-reported proof size before and after application of an extrinsic. Then it reclaims the difference. - 2. A manual helper to make reclaiming easier when manual interaction is required, for example in `on_idle` or other hooks. - In order to utilize the manual reclaiming, I modified `WeightMeter` to support the reduction of consumed weight, at least for storage proof size. ## How to use To enable the general functionality for a parachain: 1. Add the SignedExtension to your parachain runtime. 2. Provide the HostFunction to the node 3. Enable proof recording during block import ## TODO - [x] PRDoc --------- Co-authored-by: Dmitry Markin Co-authored-by: Davide Galassi Co-authored-by: Bastian Köcher --- .gitlab/pipeline/check.yml | 4 +- Cargo.lock | 23 + Cargo.toml | 1 + .../src/validate_block/implementation.rs | 29 +- .../src/validate_block/tests.rs | 2 +- .../src/validate_block/trie_recorder.rs | 11 + .../parachain-template/node/src/command.rs | 3 +- .../parachain-template/node/src/service.rs | 8 +- cumulus/parachain-template/runtime/Cargo.toml | 2 + cumulus/parachain-template/runtime/src/lib.rs | 1 + cumulus/polkadot-parachain/src/command.rs | 3 +- cumulus/polkadot-parachain/src/service.rs | 13 +- .../proof-size-hostfunction/src/lib.rs | 4 +- .../storage-weight-reclaim/Cargo.toml | 46 ++ .../storage-weight-reclaim/src/lib.rs | 663 ++++++++++++++++++ cumulus/test/client/Cargo.toml | 1 + cumulus/test/client/src/lib.rs | 20 +- cumulus/test/runtime/Cargo.toml | 2 + cumulus/test/runtime/src/lib.rs | 1 + cumulus/test/service/Cargo.toml | 1 + cumulus/test/service/src/lib.rs | 5 +- prdoc/pr_3002.prdoc | 29 + substrate/frame/system/src/lib.rs | 3 +- .../primitives/weights/src/weight_meter.rs | 20 + substrate/test-utils/client/src/lib.rs | 9 + 25 files changed, 875 insertions(+), 29 deletions(-) create mode 100644 cumulus/primitives/storage-weight-reclaim/Cargo.toml create mode 100644 cumulus/primitives/storage-weight-reclaim/src/lib.rs create mode 100644 prdoc/pr_3002.prdoc diff --git a/.gitlab/pipeline/check.yml b/.gitlab/pipeline/check.yml index cdb5d1b05d0..4d71a473372 100644 --- a/.gitlab/pipeline/check.yml +++ b/.gitlab/pipeline/check.yml @@ -108,8 +108,10 @@ check-toml-format: export RUST_LOG=remote-ext=debug,runtime=debug echo "---------- Downloading try-runtime CLI ----------" - curl -sL https://github.com/paritytech/try-runtime-cli/releases/download/v0.5.0/try-runtime-x86_64-unknown-linux-musl -o try-runtime + curl -sL https://github.com/paritytech/try-runtime-cli/releases/download/v0.5.4/try-runtime-x86_64-unknown-linux-musl -o try-runtime chmod +x ./try-runtime + echo "Using try-runtime-cli version:" + ./try-runtime --version echo "---------- Building ${PACKAGE} runtime ----------" time cargo build --release --locked -p "$PACKAGE" --features try-runtime diff --git a/Cargo.lock b/Cargo.lock index d9791ec0147..fbe2729acba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4047,6 +4047,25 @@ dependencies = [ "sp-trie", ] +[[package]] +name = "cumulus-primitives-storage-weight-reclaim" +version = "1.0.0" +dependencies = [ + "cumulus-primitives-core", + "cumulus-primitives-proof-size-hostfunction", + "cumulus-test-runtime", + "docify", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std 14.0.0", + "sp-trie", +] + [[package]] name = "cumulus-primitives-timestamp" version = "0.7.0" @@ -4209,6 +4228,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", + "cumulus-primitives-storage-weight-reclaim", "cumulus-test-relay-sproof-builder", "cumulus-test-runtime", "cumulus-test-service", @@ -4253,6 +4273,7 @@ version = "0.1.0" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", "frame-executive", "frame-support", "frame-system", @@ -4295,6 +4316,7 @@ dependencies = [ "cumulus-client-service", "cumulus-pallet-parachain-system", "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", "cumulus-relay-chain-inprocess-interface", "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", @@ -11340,6 +11362,7 @@ dependencies = [ "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-utility", "frame-benchmarking", "frame-executive", diff --git a/Cargo.toml b/Cargo.toml index 774ce1b52a3..1d27cfe9539 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -127,6 +127,7 @@ members = [ "cumulus/primitives/core", "cumulus/primitives/parachain-inherent", "cumulus/primitives/proof-size-hostfunction", + "cumulus/primitives/storage-weight-reclaim", "cumulus/primitives/timestamp", "cumulus/primitives/utility", "cumulus/test/client", diff --git a/cumulus/pallets/parachain-system/src/validate_block/implementation.rs b/cumulus/pallets/parachain-system/src/validate_block/implementation.rs index ce3b724420f..ecab7a9a093 100644 --- a/cumulus/pallets/parachain-system/src/validate_block/implementation.rs +++ b/cumulus/pallets/parachain-system/src/validate_block/implementation.rs @@ -16,7 +16,7 @@ //! The actual implementation of the validate block functionality. -use super::{trie_cache, MemoryOptimizedValidationParams}; +use super::{trie_cache, trie_recorder, MemoryOptimizedValidationParams}; use cumulus_primitives_core::{ relay_chain::Hash as RHash, ParachainBlockData, PersistedValidationData, }; @@ -34,12 +34,14 @@ use sp_externalities::{set_and_run_with_externalities, Externalities}; use sp_io::KillStorageResult; use sp_runtime::traits::{Block as BlockT, Extrinsic, HashingFor, Header as HeaderT}; use sp_std::prelude::*; -use sp_trie::MemoryDB; +use sp_trie::{MemoryDB, ProofSizeProvider}; +use trie_recorder::SizeOnlyRecorderProvider; type TrieBackend = sp_state_machine::TrieBackend< MemoryDB>, HashingFor, trie_cache::CacheProvider>, + SizeOnlyRecorderProvider>, >; type Ext<'a, B> = sp_state_machine::Ext<'a, HashingFor, TrieBackend>; @@ -48,6 +50,9 @@ fn with_externalities R, R>(f: F) -> R { sp_externalities::with_externalities(f).expect("Environmental externalities not set.") } +// Recorder instance to be used during this validate_block call. +environmental::environmental!(recorder: trait ProofSizeProvider); + /// Validate the given parachain block. /// /// This function is doing roughly the following: @@ -120,6 +125,7 @@ where sp_std::mem::drop(storage_proof); + let mut recorder = SizeOnlyRecorderProvider::new(); let cache_provider = trie_cache::CacheProvider::new(); // We use the storage root of the `parent_head` to ensure that it is the correct root. // This is already being done above while creating the in-memory db, but let's be paranoid!! @@ -128,6 +134,7 @@ where *parent_header.state_root(), cache_provider, ) + .with_recorder(recorder.clone()) .build(); let _guard = ( @@ -167,9 +174,11 @@ where .replace_implementation(host_default_child_storage_next_key), sp_io::offchain_index::host_set.replace_implementation(host_offchain_index_set), sp_io::offchain_index::host_clear.replace_implementation(host_offchain_index_clear), + cumulus_primitives_proof_size_hostfunction::storage_proof_size::host_storage_proof_size + .replace_implementation(host_storage_proof_size), ); - run_with_externalities::(&backend, || { + run_with_externalities_and_recorder::(&backend, &mut recorder, || { let relay_chain_proof = crate::RelayChainStateProof::new( PSC::SelfParaId::get(), inherent_data.validation_data.relay_parent_storage_root, @@ -190,7 +199,7 @@ where } }); - run_with_externalities::(&backend, || { + run_with_externalities_and_recorder::(&backend, &mut recorder, || { let head_data = HeadData(block.header().encode()); E::execute_block(block); @@ -265,15 +274,17 @@ fn validate_validation_data( ); } -/// Run the given closure with the externalities set. -fn run_with_externalities R>( +/// Run the given closure with the externalities and recorder set. +fn run_with_externalities_and_recorder R>( backend: &TrieBackend, + recorder: &mut SizeOnlyRecorderProvider>, execute: F, ) -> R { let mut overlay = sp_state_machine::OverlayedChanges::default(); let mut ext = Ext::::new(&mut overlay, backend); + recorder.reset(); - set_and_run_with_externalities(&mut ext, || execute()) + recorder::using(recorder, || set_and_run_with_externalities(&mut ext, || execute())) } fn host_storage_read(key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option { @@ -305,6 +316,10 @@ fn host_storage_clear(key: &[u8]) { with_externalities(|ext| ext.place_storage(key.to_vec(), None)) } +fn host_storage_proof_size() -> u64 { + recorder::with(|rec| rec.estimate_encoded_size()).expect("Recorder is always set; qed") as _ +} + fn host_storage_root(version: StateVersion) -> Vec { with_externalities(|ext| ext.storage_root(version)) } diff --git a/cumulus/pallets/parachain-system/src/validate_block/tests.rs b/cumulus/pallets/parachain-system/src/validate_block/tests.rs index f17ac6007a0..a9fb65e1108 100644 --- a/cumulus/pallets/parachain-system/src/validate_block/tests.rs +++ b/cumulus/pallets/parachain-system/src/validate_block/tests.rs @@ -59,7 +59,7 @@ fn call_validate_block( } fn create_test_client() -> (Client, Header) { - let client = TestClientBuilder::new().build(); + let client = TestClientBuilder::new().enable_import_proof_recording().build(); let genesis_header = client .header(client.chain_info().genesis_hash) diff --git a/cumulus/pallets/parachain-system/src/validate_block/trie_recorder.rs b/cumulus/pallets/parachain-system/src/validate_block/trie_recorder.rs index e73aef70aa4..48310670c07 100644 --- a/cumulus/pallets/parachain-system/src/validate_block/trie_recorder.rs +++ b/cumulus/pallets/parachain-system/src/validate_block/trie_recorder.rs @@ -97,6 +97,7 @@ pub(crate) struct SizeOnlyRecorderProvider { } impl SizeOnlyRecorderProvider { + /// Create a new instance of [`SizeOnlyRecorderProvider`] pub fn new() -> Self { Self { seen_nodes: Default::default(), @@ -104,6 +105,13 @@ impl SizeOnlyRecorderProvider { recorded_keys: Default::default(), } } + + /// Reset the internal state. + pub fn reset(&self) { + self.seen_nodes.borrow_mut().clear(); + *self.encoded_size.borrow_mut() = 0; + self.recorded_keys.borrow_mut().clear(); + } } impl sp_trie::TrieRecorderProvider for SizeOnlyRecorderProvider { @@ -281,6 +289,9 @@ mod tests { reference_recorder.estimate_encoded_size(), recorder_for_test.estimate_encoded_size() ); + + recorder_for_test.reset(); + assert_eq!(recorder_for_test.estimate_encoded_size(), 0) } } } diff --git a/cumulus/parachain-template/node/src/command.rs b/cumulus/parachain-template/node/src/command.rs index 72b3ab7bb4b..82624ae0be5 100644 --- a/cumulus/parachain-template/node/src/command.rs +++ b/cumulus/parachain-template/node/src/command.rs @@ -1,5 +1,6 @@ use std::net::SocketAddr; +use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; use log::info; @@ -183,7 +184,7 @@ pub fn run() -> Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::, ()>(config)) + runner.sync_run(|config| cmd.run::, ReclaimHostFunctions>(config)) } else { Err("Benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." diff --git a/cumulus/parachain-template/node/src/service.rs b/cumulus/parachain-template/node/src/service.rs index 830b6e82f96..4dd24803e9b 100644 --- a/cumulus/parachain-template/node/src/service.rs +++ b/cumulus/parachain-template/node/src/service.rs @@ -40,7 +40,10 @@ use substrate_prometheus_endpoint::Registry; pub struct ParachainNativeExecutor; impl sc_executor::NativeExecutionDispatch for ParachainNativeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + type ExtendHostFunctions = ( + cumulus_client_service::storage_proof_size::HostFunctions, + frame_benchmarking::benchmarking::HostFunctions, + ); fn dispatch(method: &str, data: &[u8]) -> Option> { parachain_template_runtime::api::dispatch(method, data) @@ -100,10 +103,11 @@ pub fn new_partial(config: &Configuration) -> Result let executor = ParachainExecutor::new_with_wasm_executor(wasm); let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts_record_import::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, + true, )?; let client = Arc::new(client); diff --git a/cumulus/parachain-template/runtime/Cargo.toml b/cumulus/parachain-template/runtime/Cargo.toml index 44d96ffc4e6..1873bd0a23e 100644 --- a/cumulus/parachain-template/runtime/Cargo.toml +++ b/cumulus/parachain-template/runtime/Cargo.toml @@ -73,6 +73,7 @@ cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false } cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue", default-features = false } cumulus-primitives-core = { path = "../../primitives/core", default-features = false } cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false } +cumulus-primitives-storage-weight-reclaim = { path = "../../primitives/storage-weight-reclaim", default-features = false } pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false } parachains-common = { path = "../../parachains/common", default-features = false } parachain-info = { package = "staging-parachain-info", path = "../../parachains/pallets/parachain-info", default-features = false } @@ -87,6 +88,7 @@ std = [ "cumulus-pallet-xcm/std", "cumulus-pallet-xcmp-queue/std", "cumulus-primitives-core/std", + "cumulus-primitives-storage-weight-reclaim/std", "cumulus-primitives-utility/std", "frame-benchmarking?/std", "frame-executive/std", diff --git a/cumulus/parachain-template/runtime/src/lib.rs b/cumulus/parachain-template/runtime/src/lib.rs index d9bc111fcef..cee9b33bf37 100644 --- a/cumulus/parachain-template/runtime/src/lib.rs +++ b/cumulus/parachain-template/runtime/src/lib.rs @@ -107,6 +107,7 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, ); /// Unchecked extrinsic type as expected by this runtime. diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index a40c356dcd1..4d44879af51 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -23,6 +23,7 @@ use crate::{ }, service::{new_partial, Block}, }; +use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; use log::info; @@ -584,7 +585,7 @@ pub fn run() -> Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::, ()>(config)) + runner.sync_run(|config| cmd.run::, ReclaimHostFunctions>(config)) } else { Err("Benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index 553975b01a8..4e06cd38f1d 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -68,11 +68,15 @@ use substrate_prometheus_endpoint::Registry; use polkadot_primitives::CollatorPair; #[cfg(not(feature = "runtime-benchmarks"))] -type HostFunctions = sp_io::SubstrateHostFunctions; +type HostFunctions = + (sp_io::SubstrateHostFunctions, cumulus_client_service::storage_proof_size::HostFunctions); #[cfg(feature = "runtime-benchmarks")] -type HostFunctions = - (sp_io::SubstrateHostFunctions, frame_benchmarking::benchmarking::HostFunctions); +type HostFunctions = ( + sp_io::SubstrateHostFunctions, + cumulus_client_service::storage_proof_size::HostFunctions, + frame_benchmarking::benchmarking::HostFunctions, +); type ParachainClient = TFullClient>; @@ -274,10 +278,11 @@ where .build(); let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts_record_import::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, + true, )?; let client = Arc::new(client); diff --git a/cumulus/primitives/proof-size-hostfunction/src/lib.rs b/cumulus/primitives/proof-size-hostfunction/src/lib.rs index 6da6235e585..8ebc58ea450 100644 --- a/cumulus/primitives/proof-size-hostfunction/src/lib.rs +++ b/cumulus/primitives/proof-size-hostfunction/src/lib.rs @@ -18,6 +18,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "std")] use sp_externalities::ExternalitiesExt; use sp_runtime_interface::runtime_interface; @@ -35,7 +36,8 @@ pub const PROOF_RECORDING_DISABLED: u64 = u64::MAX; pub trait StorageProofSize { /// Returns the current storage proof size. fn storage_proof_size(&mut self) -> u64 { - self.extension::().map_or(u64::MAX, |e| e.storage_proof_size()) + self.extension::() + .map_or(PROOF_RECORDING_DISABLED, |e| e.storage_proof_size()) } } diff --git a/cumulus/primitives/storage-weight-reclaim/Cargo.toml b/cumulus/primitives/storage-weight-reclaim/Cargo.toml new file mode 100644 index 00000000000..4835fb5192b --- /dev/null +++ b/cumulus/primitives/storage-weight-reclaim/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "cumulus-primitives-storage-weight-reclaim" +version = "1.0.0" +authors.workspace = true +edition.workspace = true +description = "Utilities to reclaim storage weight." +license = "Apache-2.0" + +[lints] +workspace = true + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { workspace = true } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } + +frame-support = { path = "../../../substrate/frame/support", default-features = false } +frame-system = { path = "../../../substrate/frame/system", default-features = false } + +sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } +sp-std = { path = "../../../substrate/primitives/std", default-features = false } + +cumulus-primitives-core = { path = "../../primitives/core", default-features = false } +cumulus-primitives-proof-size-hostfunction = { path = "../../primitives/proof-size-hostfunction", default-features = false } +docify = "0.2.7" + +[dev-dependencies] +sp-trie = { path = "../../../substrate/primitives/trie", default-features = false } +sp-io = { path = "../../../substrate/primitives/io", default-features = false } +cumulus-test-runtime = { path = "../../test/runtime" } + +[features] +default = ["std"] +std = [ + "codec/std", + "cumulus-primitives-core/std", + "cumulus-primitives-proof-size-hostfunction/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "sp-trie/std", +] diff --git a/cumulus/primitives/storage-weight-reclaim/src/lib.rs b/cumulus/primitives/storage-weight-reclaim/src/lib.rs new file mode 100644 index 00000000000..5dddc92e395 --- /dev/null +++ b/cumulus/primitives/storage-weight-reclaim/src/lib.rs @@ -0,0 +1,663 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Mechanism to reclaim PoV proof size weight after an extrinsic has been applied. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use cumulus_primitives_core::Weight; +use cumulus_primitives_proof_size_hostfunction::{ + storage_proof_size::storage_proof_size, PROOF_RECORDING_DISABLED, +}; +use frame_support::{ + dispatch::{DispatchInfo, PostDispatchInfo}, + weights::WeightMeter, +}; +use frame_system::Config; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, + transaction_validity::TransactionValidityError, + DispatchResult, +}; +use sp_std::marker::PhantomData; + +const LOG_TARGET: &'static str = "runtime::storage_reclaim"; + +/// `StorageWeightReclaimer` is a mechanism for manually reclaiming storage weight. +/// +/// It internally keeps track of the proof size and storage weight at initialization time. At +/// reclaim it computes the real consumed storage weight and refunds excess weight. +/// +/// # Example +#[doc = docify::embed!("src/lib.rs", simple_reclaimer_example)] +pub struct StorageWeightReclaimer { + previous_remaining_proof_size: u64, + previous_reported_proof_size: Option, +} + +impl StorageWeightReclaimer { + /// Creates a new `StorageWeightReclaimer` instance and initializes it with the storage + /// size provided by `weight_meter` and reported proof size from the node. + #[must_use = "Must call `reclaim_with_meter` to reclaim the weight"] + pub fn new(weight_meter: &WeightMeter) -> StorageWeightReclaimer { + let previous_remaining_proof_size = weight_meter.remaining().proof_size(); + let previous_reported_proof_size = get_proof_size(); + Self { previous_remaining_proof_size, previous_reported_proof_size } + } + + /// Check the consumed storage weight and calculate the consumed excess weight. + fn reclaim(&mut self, remaining_weight: Weight) -> Option { + let current_remaining_weight = remaining_weight.proof_size(); + let current_storage_proof_size = get_proof_size()?; + let previous_storage_proof_size = self.previous_reported_proof_size?; + let used_weight = + self.previous_remaining_proof_size.saturating_sub(current_remaining_weight); + let reported_used_size = + current_storage_proof_size.saturating_sub(previous_storage_proof_size); + let reclaimable = used_weight.saturating_sub(reported_used_size); + log::trace!( + target: LOG_TARGET, + "Found reclaimable storage weight. benchmarked: {used_weight}, consumed: {reported_used_size}" + ); + + self.previous_remaining_proof_size = current_remaining_weight.saturating_add(reclaimable); + self.previous_reported_proof_size = Some(current_storage_proof_size); + Some(Weight::from_parts(0, reclaimable)) + } + + /// Check the consumed storage weight and add the reclaimed + /// weight budget back to `weight_meter`. + pub fn reclaim_with_meter(&mut self, weight_meter: &mut WeightMeter) -> Option { + let reclaimed = self.reclaim(weight_meter.remaining())?; + weight_meter.reclaim_proof_size(reclaimed.proof_size()); + Some(reclaimed) + } +} + +/// Returns the current storage proof size from the host side. +/// +/// Returns `None` if proof recording is disabled on the host. +pub fn get_proof_size() -> Option { + let proof_size = storage_proof_size(); + (proof_size != PROOF_RECORDING_DISABLED).then_some(proof_size) +} + +/// Storage weight reclaim mechanism. +/// +/// This extension checks the size of the node-side storage proof +/// before and after executing a given extrinsic. The difference between +/// benchmarked and spent weight can be reclaimed. +#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, TypeInfo)] +#[scale_info(skip_type_params(T))] +pub struct StorageWeightReclaim(PhantomData); + +impl StorageWeightReclaim { + /// Create a new `StorageWeightReclaim` instance. + pub fn new() -> Self { + Self(Default::default()) + } +} + +impl core::fmt::Debug for StorageWeightReclaim { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { + let _ = write!(f, "StorageWeightReclaim"); + Ok(()) + } +} + +impl SignedExtension for StorageWeightReclaim +where + T::RuntimeCall: Dispatchable, +{ + const IDENTIFIER: &'static str = "StorageWeightReclaim"; + + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = (); + type Pre = Option; + + fn additional_signed( + &self, + ) -> Result + { + Ok(()) + } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(get_proof_size()) + } + + fn post_dispatch( + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + _len: usize, + _result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + let Some(Some(pre_dispatch_proof_size)) = pre else { + return Ok(()); + }; + + let Some(post_dispatch_proof_size) = get_proof_size() else { + log::debug!( + target: LOG_TARGET, + "Proof recording enabled during pre-dispatch, now disabled. This should not happen." + ); + return Ok(()) + }; + let benchmarked_weight = info.weight.proof_size(); + let consumed_weight = post_dispatch_proof_size.saturating_sub(pre_dispatch_proof_size); + + // Unspent weight according to the `actual_weight` from `PostDispatchInfo` + // This unspent weight will be refunded by the `CheckWeight` extension, so we need to + // account for that. + let unspent = post_info.calc_unspent(info).proof_size(); + let storage_size_diff = + benchmarked_weight.saturating_sub(unspent).abs_diff(consumed_weight as u64); + + // This value will be reclaimed by [`frame_system::CheckWeight`], so we need to calculate + // that in. + frame_system::BlockWeight::::mutate(|current| { + if consumed_weight > benchmarked_weight { + log::error!( + target: LOG_TARGET, + "Benchmarked storage weight smaller than consumed storage weight. benchmarked: {benchmarked_weight} consumed: {consumed_weight} unspent: {unspent}" + ); + current.accrue(Weight::from_parts(0, storage_size_diff), info.class) + } else { + log::trace!( + target: LOG_TARGET, + "Reclaiming storage weight. benchmarked: {benchmarked_weight}, consumed: {consumed_weight} unspent: {unspent}" + ); + current.reduce(Weight::from_parts(0, storage_size_diff), info.class) + } + }); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::{ + assert_ok, + dispatch::DispatchClass, + weights::{Weight, WeightMeter}, + }; + use frame_system::{BlockWeight, CheckWeight}; + use sp_runtime::{AccountId32, BuildStorage}; + use sp_std::marker::PhantomData; + use sp_trie::proof_size_extension::ProofSizeExt; + + type Test = cumulus_test_runtime::Runtime; + const CALL: &::RuntimeCall = + &cumulus_test_runtime::RuntimeCall::System(frame_system::Call::set_heap_pages { + pages: 0u64, + }); + const ALICE: AccountId32 = AccountId32::new([1u8; 32]); + const LEN: usize = 0; + + pub fn new_test_ext() -> sp_io::TestExternalities { + let ext: sp_io::TestExternalities = cumulus_test_runtime::RuntimeGenesisConfig::default() + .build_storage() + .unwrap() + .into(); + ext + } + + struct TestRecorder { + return_values: Box<[usize]>, + counter: std::sync::atomic::AtomicUsize, + } + + impl TestRecorder { + fn new(values: &[usize]) -> Self { + TestRecorder { return_values: values.into(), counter: Default::default() } + } + } + + impl sp_trie::ProofSizeProvider for TestRecorder { + fn estimate_encoded_size(&self) -> usize { + let counter = self.counter.fetch_add(1, core::sync::atomic::Ordering::Relaxed); + self.return_values[counter] + } + } + + fn setup_test_externalities(proof_values: &[usize]) -> sp_io::TestExternalities { + let mut test_ext = new_test_ext(); + let test_recorder = TestRecorder::new(proof_values); + test_ext.register_extension(ProofSizeExt::new(test_recorder)); + test_ext + } + + fn set_current_storage_weight(new_weight: u64) { + BlockWeight::::mutate(|current_weight| { + current_weight.set(Weight::from_parts(0, new_weight), DispatchClass::Normal); + }); + } + + #[test] + fn basic_refund() { + // The real cost will be 100 bytes of storage size + let mut test_ext = setup_test_externalities(&[0, 100]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 500 + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(0)); + + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + // We expect a refund of 400 + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 600); + }) + } + + #[test] + fn does_nothing_without_extension() { + let mut test_ext = new_test_ext(); + + // Proof size extension not registered + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 500 + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, None); + + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1000); + }) + } + + #[test] + fn negative_refund_is_added_to_weight() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 100 + let info = DispatchInfo { weight: Weight::from_parts(0, 100), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // We expect no refund + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1100); + }) + } + + #[test] + fn test_zero_proof_size() { + let mut test_ext = setup_test_externalities(&[0, 0]); + + test_ext.execute_with(|| { + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(0)); + + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 0); + }); + } + + #[test] + fn test_larger_pre_dispatch_proof_size() { + let mut test_ext = setup_test_externalities(&[300, 100]); + + test_ext.execute_with(|| { + set_current_storage_weight(1300); + + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(300)); + + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 800); + }); + } + + #[test] + fn test_incorporates_check_weight_unspent_weight() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 300 + let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; + + // Actual weight is 50 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 250)), + pays_fee: Default::default(), + }; + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 900); + }) + } + + #[test] + fn test_incorporates_check_weight_unspent_weight_on_negative() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 50 + let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; + + // Actual weight is 25 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 25)), + pays_fee: Default::default(), + }; + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1150); + }) + } + + #[test] + fn test_incorporates_check_weight_unspent_weight_reverse_order() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 300 + let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; + + // Actual weight is 50 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 250)), + pays_fee: Default::default(), + }; + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + // `CheckWeight` gets called after `StorageWeightReclaim` this time. + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + + assert_eq!(BlockWeight::::get().total().proof_size(), 900); + }) + } + + #[test] + fn test_incorporates_check_weight_unspent_weight_on_negative_reverse_order() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 50 + let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; + + // Actual weight is 25 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 25)), + pays_fee: Default::default(), + }; + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + // `CheckWeight` gets called after `StorageWeightReclaim` this time. + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1150); + }) + } + + #[test] + fn storage_size_reported_correctly() { + let mut test_ext = setup_test_externalities(&[1000]); + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), Some(1000)); + }); + + let mut test_ext = new_test_ext(); + + let test_recorder = TestRecorder::new(&[0]); + + test_ext.register_extension(ProofSizeExt::new(test_recorder)); + + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), Some(0)); + }); + } + + #[test] + fn storage_size_disabled_reported_correctly() { + let mut test_ext = setup_test_externalities(&[PROOF_RECORDING_DISABLED as usize]); + + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), None); + }); + } + + #[test] + fn test_reclaim_helper() { + let mut test_ext = setup_test_externalities(&[1000, 1300, 1800]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 2000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + remaining_weight_meter.consume(Weight::from_parts(0, 500)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 200))); + + remaining_weight_meter.consume(Weight::from_parts(0, 800)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + assert_eq!(reclaimed, Some(Weight::from_parts(0, 300))); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1200)); + }); + } + + #[test] + fn test_reclaim_helper_does_not_reclaim_negative() { + // Benchmarked weight does not change at all + let mut test_ext = setup_test_externalities(&[1000, 1300]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1000)); + }); + + // Benchmarked weight increases less than storage proof consumes + let mut test_ext = setup_test_externalities(&[1000, 1300]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + remaining_weight_meter.consume(Weight::from_parts(0, 0)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); + }); + } + + /// Just here for doc purposes + fn get_benched_weight() -> Weight { + Weight::from_parts(0, 5) + } + + /// Just here for doc purposes + fn do_work() {} + + #[docify::export_content(simple_reclaimer_example)] + fn reclaim_with_weight_meter() { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(10, 10)); + + let benched_weight = get_benched_weight(); + + // It is important to instantiate the `StorageWeightReclaimer` before we consume the weight + // for a piece of work from the weight meter. + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + + if remaining_weight_meter.try_consume(benched_weight).is_ok() { + // Perform some work that takes has `benched_weight` storage weight. + do_work(); + + // Reclaimer will detect that we only consumed 2 bytes, so 3 bytes are reclaimed. + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + // We reclaimed 3 bytes of storage size! + assert_eq!(reclaimed, Some(Weight::from_parts(0, 3))); + assert_eq!(BlockWeight::::get().total().proof_size(), 10); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(10, 8)); + } + } + + #[test] + fn test_reclaim_helper_works_with_meter() { + // The node will report 12 - 10 = 2 consumed storage size between the calls. + let mut test_ext = setup_test_externalities(&[10, 12]); + + test_ext.execute_with(|| { + // Initial storage size is 10. + set_current_storage_weight(10); + reclaim_with_weight_meter(); + }); + } +} diff --git a/cumulus/test/client/Cargo.toml b/cumulus/test/client/Cargo.toml index 7190172101c..028733ce235 100644 --- a/cumulus/test/client/Cargo.toml +++ b/cumulus/test/client/Cargo.toml @@ -41,6 +41,7 @@ cumulus-test-relay-sproof-builder = { path = "../relay-sproof-builder" } cumulus-primitives-core = { path = "../../primitives/core" } cumulus-primitives-proof-size-hostfunction = { path = "../../primitives/proof-size-hostfunction" } cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent" } +cumulus-primitives-storage-weight-reclaim = { path = "../../primitives/storage-weight-reclaim" } [features] runtime-benchmarks = [ diff --git a/cumulus/test/client/src/lib.rs b/cumulus/test/client/src/lib.rs index df63f683de6..c46f4da7f67 100644 --- a/cumulus/test/client/src/lib.rs +++ b/cumulus/test/client/src/lib.rs @@ -151,6 +151,7 @@ pub fn generate_extrinsic_with_pair( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::::new(), ); let function = function.into(); @@ -158,7 +159,7 @@ pub fn generate_extrinsic_with_pair( let raw_payload = SignedPayload::from_raw( function.clone(), extra.clone(), - ((), VERSION.spec_version, genesis_block, current_block_hash, (), (), ()), + ((), VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|e| origin.sign(e)); @@ -203,13 +204,16 @@ pub fn validate_block( let mut ext_ext = ext.ext(); let heap_pages = HeapAllocStrategy::Static { extra_pages: 1024 }; - let executor = WasmExecutor::::builder() - .with_execution_method(WasmExecutionMethod::default()) - .with_max_runtime_instances(1) - .with_runtime_cache_size(2) - .with_onchain_heap_alloc_strategy(heap_pages) - .with_offchain_heap_alloc_strategy(heap_pages) - .build(); + let executor = WasmExecutor::<( + sp_io::SubstrateHostFunctions, + cumulus_primitives_proof_size_hostfunction::storage_proof_size::HostFunctions, + )>::builder() + .with_execution_method(WasmExecutionMethod::default()) + .with_max_runtime_instances(1) + .with_runtime_cache_size(2) + .with_onchain_heap_alloc_strategy(heap_pages) + .with_offchain_heap_alloc_strategy(heap_pages) + .build(); executor .uncached_call( diff --git a/cumulus/test/runtime/Cargo.toml b/cumulus/test/runtime/Cargo.toml index 5902a62512b..449a8b819bc 100644 --- a/cumulus/test/runtime/Cargo.toml +++ b/cumulus/test/runtime/Cargo.toml @@ -39,6 +39,7 @@ sp-version = { path = "../../../substrate/primitives/version", default-features # Cumulus cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } cumulus-primitives-core = { path = "../../primitives/core", default-features = false } +cumulus-primitives-storage-weight-reclaim = { path = "../../primitives/storage-weight-reclaim", default-features = false } [build-dependencies] substrate-wasm-builder = { path = "../../../substrate/utils/wasm-builder", optional = true } @@ -49,6 +50,7 @@ std = [ "codec/std", "cumulus-pallet-parachain-system/std", "cumulus-primitives-core/std", + "cumulus-primitives-storage-weight-reclaim/std", "frame-executive/std", "frame-support/std", "frame-system-rpc-runtime-api/std", diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index 6068f895c83..5fb31410984 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -331,6 +331,7 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = diff --git a/cumulus/test/service/Cargo.toml b/cumulus/test/service/Cargo.toml index b26f0b9967c..27273f4e0a8 100644 --- a/cumulus/test/service/Cargo.toml +++ b/cumulus/test/service/Cargo.toml @@ -81,6 +81,7 @@ cumulus-relay-chain-minimal-node = { path = "../../client/relay-chain-minimal-no cumulus-client-pov-recovery = { path = "../../client/pov-recovery" } cumulus-test-relay-sproof-builder = { path = "../relay-sproof-builder" } cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } +cumulus-primitives-storage-weight-reclaim = { path = "../../primitives/storage-weight-reclaim" } pallet-timestamp = { path = "../../../substrate/frame/timestamp" } [dev-dependencies] diff --git a/cumulus/test/service/src/lib.rs b/cumulus/test/service/src/lib.rs index 1c2e1db9741..3554a383f21 100644 --- a/cumulus/test/service/src/lib.rs +++ b/cumulus/test/service/src/lib.rs @@ -112,7 +112,7 @@ pub type AnnounceBlockFn = Arc>) + Send + Sync>; pub struct RuntimeExecutor; impl sc_executor::NativeExecutionDispatch for RuntimeExecutor { - type ExtendHostFunctions = (); + type ExtendHostFunctions = cumulus_client_service::storage_proof_size::HostFunctions; fn dispatch(method: &str, data: &[u8]) -> Option> { cumulus_test_runtime::api::dispatch(method, data) @@ -894,11 +894,12 @@ pub fn construct_extrinsic( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::::new(), ); let raw_payload = runtime::SignedPayload::from_raw( function.clone(), extra.clone(), - ((), runtime::VERSION.spec_version, genesis_block, current_block_hash, (), (), ()), + ((), runtime::VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|e| caller.sign(e)); runtime::UncheckedExtrinsic::new_signed( diff --git a/prdoc/pr_3002.prdoc b/prdoc/pr_3002.prdoc new file mode 100644 index 00000000000..511a07e39c4 --- /dev/null +++ b/prdoc/pr_3002.prdoc @@ -0,0 +1,29 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: PoV Reclaim Runtime Side +author: skunert +topic: runtime +doc: + - audience: Runtime Dev + description: | + Adds a mechanism to reclaim proof size weight. + 1. Introduces a new `SignedExtension` that reclaims the difference + between benchmarked proof size weight and actual consumed proof size weight. + 2. Introduces a manual mechanism, `StorageWeightReclaimer`, to reclaim excess storage weight for situations + that require manual weight management. The most prominent case is the `on_idle` hook. + 3. Adds the `storage_proof_size` host function to the PVF. Parachain nodes should add it to ensure compatibility. + + To enable proof size reclaiming, add the host `storage_proof_size` host function to the parachain node. Add the + `StorageWeightReclaim` `SignedExtension` to your runtime and enable proof recording during block import. + + +crates: + - name: "cumulus-primitives-storage-weight-reclaim" +host_functions: + - name: "storage_proof_size" + description: | + This host function is used to pass the current size of the storage proof to the runtime. + It was introduced before but becomes relevant now. + Note: This host function is intended to be used through `cumulus_primitives_storage_weight_reclaim::get_proof_size`. + Direct usage is not recommended. diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 069217bcee4..1405c7303f8 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -148,6 +148,7 @@ use sp_io::TestExternalities; pub mod limits; #[cfg(test)] pub(crate) mod mock; + pub mod offchain; mod extensions; @@ -847,7 +848,7 @@ pub mod pallet { #[pallet::storage] #[pallet::whitelist_storage] #[pallet::getter(fn block_weight)] - pub(super) type BlockWeight = StorageValue<_, ConsumedWeight, ValueQuery>; + pub type BlockWeight = StorageValue<_, ConsumedWeight, ValueQuery>; /// Total length (in bytes) for all extrinsics put together, for the current block. #[pallet::storage] diff --git a/substrate/primitives/weights/src/weight_meter.rs b/substrate/primitives/weights/src/weight_meter.rs index 584d22304c3..1738948e4c3 100644 --- a/substrate/primitives/weights/src/weight_meter.rs +++ b/substrate/primitives/weights/src/weight_meter.rs @@ -149,6 +149,11 @@ impl WeightMeter { pub fn can_consume(&self, w: Weight) -> bool { self.consumed.checked_add(&w).map_or(false, |t| t.all_lte(self.limit)) } + + /// Reclaim the given weight. + pub fn reclaim_proof_size(&mut self, s: u64) { + self.consumed.saturating_reduce(Weight::from_parts(0, s)); + } } #[cfg(test)] @@ -277,6 +282,21 @@ mod tests { assert_eq!(meter.consumed(), Weight::from_parts(5, 10)); } + #[test] + #[cfg(debug_assertions)] + fn reclaim_works() { + let mut meter = WeightMeter::with_limit(Weight::from_parts(5, 10)); + + meter.consume(Weight::from_parts(5, 10)); + assert_eq!(meter.consumed(), Weight::from_parts(5, 10)); + + meter.reclaim_proof_size(3); + assert_eq!(meter.consumed(), Weight::from_parts(5, 7)); + + meter.reclaim_proof_size(10); + assert_eq!(meter.consumed(), Weight::from_parts(5, 0)); + } + #[test] #[cfg(debug_assertions)] #[should_panic(expected = "Weight counter overflow")] diff --git a/substrate/test-utils/client/src/lib.rs b/substrate/test-utils/client/src/lib.rs index e3f06e27563..d283b24f286 100644 --- a/substrate/test-utils/client/src/lib.rs +++ b/substrate/test-utils/client/src/lib.rs @@ -72,6 +72,7 @@ pub struct TestClientBuilder, bad_blocks: BadBlocks, enable_offchain_indexing_api: bool, + enable_import_proof_recording: bool, no_genesis: bool, } @@ -120,6 +121,7 @@ impl bad_blocks: None, enable_offchain_indexing_api: false, no_genesis: false, + enable_import_proof_recording: false, } } @@ -165,6 +167,12 @@ impl self } + /// Enable proof recording on import. + pub fn enable_import_proof_recording(mut self) -> Self { + self.enable_import_proof_recording = true; + self + } + /// Disable writing genesis. pub fn set_no_genesis(mut self) -> Self { self.no_genesis = true; @@ -202,6 +210,7 @@ impl }; let client_config = ClientConfig { + enable_import_proof_recording: self.enable_import_proof_recording, offchain_indexing_api: self.enable_offchain_indexing_api, no_genesis: self.no_genesis, ..Default::default() -- GitLab From 6fc1d41d4487b9164451cd8214674ce195ab06a0 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 23 Feb 2024 16:53:08 +0100 Subject: [PATCH 021/188] Bridge zombienet tests: move all "framework" files under one folder (#3462) Related to https://github.com/paritytech/polkadot-sdk/issues/3400 Moving all bridges testing "framework" files under one folder in order to be able to download the entire folder when we want to add tests in other repos No significant functional changes --- .../rococo-westend/bridges_rococo_westend.sh | 2 +- bridges/testing/environments/rococo-westend/helper.sh | 2 +- .../environments/rococo-westend/rococo-init.zndsl | 4 ++-- .../testing/environments/rococo-westend/rococo.zndsl | 4 ++-- bridges/testing/environments/rococo-westend/spawn.sh | 2 +- .../environments/rococo-westend/start_relayer.sh | 4 ++-- .../environments/rococo-westend/westend-init.zndsl | 4 ++-- .../testing/environments/rococo-westend/westend.zndsl | 4 ++-- .../best-finalized-header-at-bridged-chain.js | 0 .../js-helpers/chains/rococo-at-westend.js | 0 .../js-helpers/chains/westend-at-rococo.js | 0 .../js-helpers/native-assets-balance-increased.js | 0 .../only-mandatory-headers-synced-when-idle.js | 0 .../only-required-headers-synced-when-idle.js | 0 .../{ => framework}/js-helpers/relayer-rewards.js | 0 bridges/testing/{ => framework}/js-helpers/utils.js | 0 .../js-helpers/wait-hrmp-channel-opened.js | 0 .../js-helpers/wrapped-assets-balance.js | 0 bridges/testing/{ => framework}/utils/bridges.sh | 4 ++-- bridges/testing/{ => framework}/utils/common.sh | 0 .../utils/generate_hex_encoded_call/index.js | 0 .../utils/generate_hex_encoded_call/package-lock.json | 0 .../utils/generate_hex_encoded_call/package.json | 0 bridges/testing/{ => framework}/utils/zombienet.sh | 0 bridges/testing/run-new-test.sh | 1 + .../0001-asset-transfer/roc-reaches-westend.zndsl | 8 ++++---- bridges/testing/tests/0001-asset-transfer/run.sh | 8 +++++--- .../tests/0001-asset-transfer/wnd-reaches-rococo.zndsl | 8 ++++---- .../0001-asset-transfer/wroc-reaches-rococo.zndsl | 6 +++--- .../0001-asset-transfer/wwnd-reaches-westend.zndsl | 6 +++--- .../rococo-to-westend.zndsl | 4 ++-- .../0002-mandatory-headers-synced-while-idle/run.sh | 10 +++++----- .../westend-to-rococo.zndsl | 4 ++-- .../bridges_zombienet_tests_injected.Dockerfile | 2 +- 34 files changed, 45 insertions(+), 42 deletions(-) rename bridges/testing/{ => framework}/js-helpers/best-finalized-header-at-bridged-chain.js (100%) rename bridges/testing/{ => framework}/js-helpers/chains/rococo-at-westend.js (100%) rename bridges/testing/{ => framework}/js-helpers/chains/westend-at-rococo.js (100%) rename bridges/testing/{ => framework}/js-helpers/native-assets-balance-increased.js (100%) rename bridges/testing/{ => framework}/js-helpers/only-mandatory-headers-synced-when-idle.js (100%) rename bridges/testing/{ => framework}/js-helpers/only-required-headers-synced-when-idle.js (100%) rename bridges/testing/{ => framework}/js-helpers/relayer-rewards.js (100%) rename bridges/testing/{ => framework}/js-helpers/utils.js (100%) rename bridges/testing/{ => framework}/js-helpers/wait-hrmp-channel-opened.js (100%) rename bridges/testing/{ => framework}/js-helpers/wrapped-assets-balance.js (100%) rename bridges/testing/{ => framework}/utils/bridges.sh (98%) rename bridges/testing/{ => framework}/utils/common.sh (100%) rename bridges/testing/{ => framework}/utils/generate_hex_encoded_call/index.js (100%) rename bridges/testing/{ => framework}/utils/generate_hex_encoded_call/package-lock.json (100%) rename bridges/testing/{ => framework}/utils/generate_hex_encoded_call/package.json (100%) rename bridges/testing/{ => framework}/utils/zombienet.sh (100%) diff --git a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh index 84764cdaca3..de5be2e0af8 100755 --- a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh +++ b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh @@ -1,7 +1,7 @@ #!/bin/bash # import common functions -source "${BASH_SOURCE%/*}/../../utils/bridges.sh" +source "$FRAMEWORK_PATH/utils/bridges.sh" # Expected sovereign accounts. # diff --git a/bridges/testing/environments/rococo-westend/helper.sh b/bridges/testing/environments/rococo-westend/helper.sh index 211a5b53b3d..0a13ded213f 100755 --- a/bridges/testing/environments/rococo-westend/helper.sh +++ b/bridges/testing/environments/rococo-westend/helper.sh @@ -1,3 +1,3 @@ #!/bin/bash -$POLKADOT_SDK_PATH/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh "$@" +$ENV_PATH/bridges_rococo_westend.sh "$@" diff --git a/bridges/testing/environments/rococo-westend/rococo-init.zndsl b/bridges/testing/environments/rococo-westend/rococo-init.zndsl index 145f2df73a6..c913e4db31f 100644 --- a/bridges/testing/environments/rococo-westend/rococo-init.zndsl +++ b/bridges/testing/environments/rococo-westend/rococo-init.zndsl @@ -1,8 +1,8 @@ -Description: User is able to transfer WND from Westend Asset Hub to Rococo Asset Hub and back +Description: Check if the HRMP channel between Rococo BH and Rococo AH was opened successfully Network: ./bridge_hub_rococo_local_network.toml Creds: config # ensure that initialization has completed -asset-hub-rococo-collator1: js-script ../../js-helpers/wait-hrmp-channel-opened.js with "1013" within 300 seconds +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1013" within 300 seconds diff --git a/bridges/testing/environments/rococo-westend/rococo.zndsl b/bridges/testing/environments/rococo-westend/rococo.zndsl index bd8681af219..5b49c7c632f 100644 --- a/bridges/testing/environments/rococo-westend/rococo.zndsl +++ b/bridges/testing/environments/rococo-westend/rococo.zndsl @@ -1,7 +1,7 @@ -Description: User is able to transfer WND from Westend Asset Hub to Rococo Asset Hub and back +Description: Check if the with-Westend GRANPDA pallet was initialized at Rococo BH Network: ./bridge_hub_rococo_local_network.toml Creds: config # relay is already started - let's wait until with-Westend GRANPDA pallet is initialized at Rococo -bridge-hub-rococo-collator1: js-script ../../js-helpers/best-finalized-header-at-bridged-chain.js with "Westend,0" within 400 seconds +bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Westend,0" within 400 seconds diff --git a/bridges/testing/environments/rococo-westend/spawn.sh b/bridges/testing/environments/rococo-westend/spawn.sh index 5a0d65ce65d..cbd0b1bc623 100755 --- a/bridges/testing/environments/rococo-westend/spawn.sh +++ b/bridges/testing/environments/rococo-westend/spawn.sh @@ -4,7 +4,7 @@ set -e trap "trap - SIGTERM && kill -9 -$$" SIGINT SIGTERM EXIT -source "${BASH_SOURCE%/*}/../../utils/zombienet.sh" +source "$FRAMEWORK_PATH/utils/zombienet.sh" # whether to init the chains (open HRMP channels, set XCM version, create reserve assets, etc) init=0 diff --git a/bridges/testing/environments/rococo-westend/start_relayer.sh b/bridges/testing/environments/rococo-westend/start_relayer.sh index c57d4f1a437..7ddd312d395 100755 --- a/bridges/testing/environments/rococo-westend/start_relayer.sh +++ b/bridges/testing/environments/rococo-westend/start_relayer.sh @@ -2,8 +2,8 @@ set -e -source "${BASH_SOURCE%/*}/../../utils/common.sh" -source "${BASH_SOURCE%/*}/../../utils/zombienet.sh" +source "$FRAMEWORK_PATH/utils/common.sh" +source "$FRAMEWORK_PATH/utils/zombienet.sh" rococo_dir=$1 westend_dir=$2 diff --git a/bridges/testing/environments/rococo-westend/westend-init.zndsl b/bridges/testing/environments/rococo-westend/westend-init.zndsl index 2f8e665d592..0f5428eed3b 100644 --- a/bridges/testing/environments/rococo-westend/westend-init.zndsl +++ b/bridges/testing/environments/rococo-westend/westend-init.zndsl @@ -1,7 +1,7 @@ -Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back +Description: Check if the HRMP channel between Westend BH and Westend AH was opened successfully Network: ./bridge_hub_westend_local_network.toml Creds: config # ensure that initialization has completed -asset-hub-westend-collator1: js-script ../../js-helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds diff --git a/bridges/testing/environments/rococo-westend/westend.zndsl b/bridges/testing/environments/rococo-westend/westend.zndsl index c75ae579d27..07968838852 100644 --- a/bridges/testing/environments/rococo-westend/westend.zndsl +++ b/bridges/testing/environments/rococo-westend/westend.zndsl @@ -1,6 +1,6 @@ -Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back +Description: Check if the with-Rococo GRANPDA pallet was initialized at Westend BH Network: ./bridge_hub_westend_local_network.toml Creds: config # relay is already started - let's wait until with-Rococo GRANPDA pallet is initialized at Westend -bridge-hub-westend-collator1: js-script ../../js-helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds +bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds diff --git a/bridges/testing/js-helpers/best-finalized-header-at-bridged-chain.js b/bridges/testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js similarity index 100% rename from bridges/testing/js-helpers/best-finalized-header-at-bridged-chain.js rename to bridges/testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js diff --git a/bridges/testing/js-helpers/chains/rococo-at-westend.js b/bridges/testing/framework/js-helpers/chains/rococo-at-westend.js similarity index 100% rename from bridges/testing/js-helpers/chains/rococo-at-westend.js rename to bridges/testing/framework/js-helpers/chains/rococo-at-westend.js diff --git a/bridges/testing/js-helpers/chains/westend-at-rococo.js b/bridges/testing/framework/js-helpers/chains/westend-at-rococo.js similarity index 100% rename from bridges/testing/js-helpers/chains/westend-at-rococo.js rename to bridges/testing/framework/js-helpers/chains/westend-at-rococo.js diff --git a/bridges/testing/js-helpers/native-assets-balance-increased.js b/bridges/testing/framework/js-helpers/native-assets-balance-increased.js similarity index 100% rename from bridges/testing/js-helpers/native-assets-balance-increased.js rename to bridges/testing/framework/js-helpers/native-assets-balance-increased.js diff --git a/bridges/testing/js-helpers/only-mandatory-headers-synced-when-idle.js b/bridges/testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js similarity index 100% rename from bridges/testing/js-helpers/only-mandatory-headers-synced-when-idle.js rename to bridges/testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js diff --git a/bridges/testing/js-helpers/only-required-headers-synced-when-idle.js b/bridges/testing/framework/js-helpers/only-required-headers-synced-when-idle.js similarity index 100% rename from bridges/testing/js-helpers/only-required-headers-synced-when-idle.js rename to bridges/testing/framework/js-helpers/only-required-headers-synced-when-idle.js diff --git a/bridges/testing/js-helpers/relayer-rewards.js b/bridges/testing/framework/js-helpers/relayer-rewards.js similarity index 100% rename from bridges/testing/js-helpers/relayer-rewards.js rename to bridges/testing/framework/js-helpers/relayer-rewards.js diff --git a/bridges/testing/js-helpers/utils.js b/bridges/testing/framework/js-helpers/utils.js similarity index 100% rename from bridges/testing/js-helpers/utils.js rename to bridges/testing/framework/js-helpers/utils.js diff --git a/bridges/testing/js-helpers/wait-hrmp-channel-opened.js b/bridges/testing/framework/js-helpers/wait-hrmp-channel-opened.js similarity index 100% rename from bridges/testing/js-helpers/wait-hrmp-channel-opened.js rename to bridges/testing/framework/js-helpers/wait-hrmp-channel-opened.js diff --git a/bridges/testing/js-helpers/wrapped-assets-balance.js b/bridges/testing/framework/js-helpers/wrapped-assets-balance.js similarity index 100% rename from bridges/testing/js-helpers/wrapped-assets-balance.js rename to bridges/testing/framework/js-helpers/wrapped-assets-balance.js diff --git a/bridges/testing/utils/bridges.sh b/bridges/testing/framework/utils/bridges.sh similarity index 98% rename from bridges/testing/utils/bridges.sh rename to bridges/testing/framework/utils/bridges.sh index cfde5dfd26b..7c839946158 100755 --- a/bridges/testing/utils/bridges.sh +++ b/bridges/testing/framework/utils/bridges.sh @@ -41,8 +41,8 @@ function ensure_polkadot_js_api() { echo "" echo "" echo "-------------------" - echo "Installing (nodejs) sub module: $(dirname "$0")/generate_hex_encoded_call" - pushd $(dirname "$0")/generate_hex_encoded_call + echo "Installing (nodejs) sub module: ${BASH_SOURCE%/*}/generate_hex_encoded_call" + pushd ${BASH_SOURCE%/*}/generate_hex_encoded_call npm install popd fi diff --git a/bridges/testing/utils/common.sh b/bridges/testing/framework/utils/common.sh similarity index 100% rename from bridges/testing/utils/common.sh rename to bridges/testing/framework/utils/common.sh diff --git a/bridges/testing/utils/generate_hex_encoded_call/index.js b/bridges/testing/framework/utils/generate_hex_encoded_call/index.js similarity index 100% rename from bridges/testing/utils/generate_hex_encoded_call/index.js rename to bridges/testing/framework/utils/generate_hex_encoded_call/index.js diff --git a/bridges/testing/utils/generate_hex_encoded_call/package-lock.json b/bridges/testing/framework/utils/generate_hex_encoded_call/package-lock.json similarity index 100% rename from bridges/testing/utils/generate_hex_encoded_call/package-lock.json rename to bridges/testing/framework/utils/generate_hex_encoded_call/package-lock.json diff --git a/bridges/testing/utils/generate_hex_encoded_call/package.json b/bridges/testing/framework/utils/generate_hex_encoded_call/package.json similarity index 100% rename from bridges/testing/utils/generate_hex_encoded_call/package.json rename to bridges/testing/framework/utils/generate_hex_encoded_call/package.json diff --git a/bridges/testing/utils/zombienet.sh b/bridges/testing/framework/utils/zombienet.sh similarity index 100% rename from bridges/testing/utils/zombienet.sh rename to bridges/testing/framework/utils/zombienet.sh diff --git a/bridges/testing/run-new-test.sh b/bridges/testing/run-new-test.sh index 2ed2a412b8a..7c84a69aa47 100755 --- a/bridges/testing/run-new-test.sh +++ b/bridges/testing/run-new-test.sh @@ -21,6 +21,7 @@ do done export POLKADOT_SDK_PATH=`realpath ${BASH_SOURCE%/*}/../..` +export FRAMEWORK_PATH=`realpath ${BASH_SOURCE%/*}/framework` # set path to binaries if [ "$ZOMBIENET_DOCKER_PATHS" -eq 1 ]; then diff --git a/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl index 203c95b73eb..4725362ae82 100644 --- a/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl @@ -1,12 +1,12 @@ Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back -Network: ../../environments/rococo-westend/bridge_hub_westend_local_network.toml +Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml Creds: config # send ROC to //Alice from Rococo AH to Westend AH -asset-hub-westend-collator1: run ../../environments/rococo-westend/helper.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 120 seconds +asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 120 seconds # check that //Alice received the ROC on Westend AH -asset-hub-westend-collator1: js-script ../../js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Rococo" within 300 seconds +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Rococo" within 300 seconds # check that the relayer //Charlie is rewarded by Westend AH -bridge-hub-westend-collator1: js-script ../../js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726F,ThisChain,0" within 30 seconds +bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726F,ThisChain,0" within 30 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/run.sh b/bridges/testing/tests/0001-asset-transfer/run.sh index 1e0d6cad301..a7bb122919b 100755 --- a/bridges/testing/tests/0001-asset-transfer/run.sh +++ b/bridges/testing/tests/0001-asset-transfer/run.sh @@ -2,10 +2,12 @@ set -e -source "${BASH_SOURCE%/*}/../../utils/common.sh" -source "${BASH_SOURCE%/*}/../../utils/zombienet.sh" +source "${BASH_SOURCE%/*}/../../framework/utils/common.sh" +source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh" -${BASH_SOURCE%/*}/../../environments/rococo-westend/spawn.sh --init --start-relayer & +export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/rococo-westend` + +$ENV_PATH/spawn.sh --init --start-relayer & env_pid=$! ensure_process_file $env_pid $TEST_DIR/rococo.env 600 diff --git a/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl index bbd95db9cfd..77267239c3b 100644 --- a/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl @@ -1,12 +1,12 @@ Description: User is able to transfer WND from Westend Asset Hub to Rococo Asset Hub and back -Network: ../../environments/rococo-westend/bridge_hub_rococo_local_network.toml +Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml Creds: config # send WND to //Alice from Westend AH to Rococo AH -asset-hub-rococo-collator1: run ../../environments/rococo-westend/helper.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 120 seconds +asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 120 seconds # check that //Alice received the WND on Rococo AH -asset-hub-rococo-collator1: js-script ../../js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Westend" within 300 seconds +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Westend" within 300 seconds # check that the relayer //Charlie is rewarded by Rococo AH -bridge-hub-rococo-collator1: js-script ../../js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,ThisChain,0" within 30 seconds +bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,ThisChain,0" within 30 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl index 4c0a4675234..f72b76e6026 100644 --- a/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl @@ -1,10 +1,10 @@ Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back -Network: ../../environments/rococo-westend/bridge_hub_westend_local_network.toml +Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml Creds: config # send wROC back to Alice from Westend AH to Rococo AH -asset-hub-rococo-collator1: run ../../environments/rococo-westend/helper.sh with "withdraw-reserve-assets-from-asset-hub-westend-local" within 120 seconds +asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-westend-local" within 120 seconds # check that //Alice received the wROC on Rococo AH # (we wait until //Alice account increases here - there are no other transactions that may increase it) -asset-hub-rococo-collator1: js-script ../../js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" within 300 seconds +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" within 300 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl index 3acded97d5c..9d893c8d90a 100644 --- a/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl @@ -1,10 +1,10 @@ Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back -Network: ../../environments/rococo-westend/bridge_hub_westend_local_network.toml +Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml Creds: config # send wWND back to Alice from Rococo AH to Westend AH -asset-hub-westend-collator1: run ../../environments/rococo-westend/helper.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local" within 120 seconds +asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local" within 120 seconds # check that //Alice received the wWND on Westend AH # (we wait until //Alice account increases here - there are no other transactions that may increase it) -asset-hub-westend-collator1: js-script ../../js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" within 300 seconds +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" within 300 seconds diff --git a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl index 82a1a103b14..6e381f53773 100644 --- a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl +++ b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl @@ -1,8 +1,8 @@ Description: While relayer is idle, we only sync mandatory Rococo (and a single Rococo BH) headers to Westend BH. -Network: ../../environments/rococo-westend/bridge_hub_westend_local_network.toml +Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml Creds: config # ensure that relayer is only syncing mandatory headers while idle. This includes both headers that were # generated while relay was offline and those in the next 100 seconds while script is active. -bridge-hub-westend-collator1: js-script ../../js-helpers/only-mandatory-headers-synced-when-idle.js with "300,rococo-at-westend" within 600 seconds +bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/only-mandatory-headers-synced-when-idle.js with "300,rococo-at-westend" within 600 seconds diff --git a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh index c39796d51d5..7d5b8d92736 100755 --- a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh +++ b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh @@ -2,12 +2,12 @@ set -e -source "${BASH_SOURCE%/*}/../../utils/common.sh" -source "${BASH_SOURCE%/*}/../../utils/zombienet.sh" +source "${BASH_SOURCE%/*}/../../framework/utils/common.sh" +source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh" -# We use `--relayer-delay` in order to sleep some time before starting relayer. -# We want to sleep for at least 1 session, which is expected to be 60 seconds for test environment. -${BASH_SOURCE%/*}/../../environments/rococo-westend/spawn.sh & +export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/rococo-westend` + +$ENV_PATH/spawn.sh & env_pid=$! ensure_process_file $env_pid $TEST_DIR/rococo.env 600 diff --git a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl index 86581324625..b4b3e436791 100644 --- a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl +++ b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl @@ -1,7 +1,7 @@ Description: While relayer is idle, we only sync mandatory Westend (and a single Westend BH) headers to Rococo BH. -Network: ../../environments/rococo-westend/bridge_hub_rococo_local_network.toml +Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml Creds: config # ensure that relayer is only syncing mandatory headers while idle. This includes both headers that were # generated while relay was offline and those in the next 100 seconds while script is active. -bridge-hub-rococo-collator1: js-script ../../js-helpers/only-mandatory-headers-synced-when-idle.js with "300,westend-at-rococo" within 600 seconds +bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/only-mandatory-headers-synced-when-idle.js with "300,westend-at-rococo" within 600 seconds diff --git a/docker/dockerfiles/bridges_zombienet_tests_injected.Dockerfile b/docker/dockerfiles/bridges_zombienet_tests_injected.Dockerfile index fde9cc6e7cf..4bfb73acda0 100644 --- a/docker/dockerfiles/bridges_zombienet_tests_injected.Dockerfile +++ b/docker/dockerfiles/bridges_zombienet_tests_injected.Dockerfile @@ -45,7 +45,7 @@ RUN mkdir -p /home/nonroot/bridges-polkadot-sdk COPY ./artifacts/bridges-polkadot-sdk /home/nonroot/bridges-polkadot-sdk # also prepare `generate_hex_encoded_call` for running RUN set -eux; \ - cd /home/nonroot/bridges-polkadot-sdk/bridges/testing/utils/generate_hex_encoded_call; \ + cd /home/nonroot/bridges-polkadot-sdk/bridges/testing/framework/utils/generate_hex_encoded_call; \ npm install # check if executable works in this container -- GitLab From 2431001ec012334226bc181d69a754c49f168328 Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Fri, 23 Feb 2024 23:35:48 +0700 Subject: [PATCH 022/188] Runtime: allow backing multiple candidates of same parachain on different cores (#3231) Fixes https://github.com/paritytech/polkadot-sdk/issues/3144 Builds on top of https://github.com/paritytech/polkadot-sdk/pull/3229 ### Summary Some preparations for Runtime to support elastic scaling, guarded by config node features bit `FeatureIndex::ElasticScalingMVP`. This PR introduces a per-candidate `CoreIndex` but does it in a hacky way to avoid changing `CandidateCommitments`, `CandidateReceipts` primitives and networking protocols. #### Including `CoreIndex` in `BackedCandidate` If the `ElasticScalingMVP` feature bit is enabled then `BackedCandidate::validator_indices` is extended by 8 bits. The value stored in these bits represents the assumed core index for the candidate. It is temporary solution which works by creating a mapping from `BackedCandidate` to `CoreIndex` by assuming the `CoreIndex` can be discovered by checking in which validator group the validator that signed the statement is. TODO: - [x] fix tests - [x] add new tests - [x] Bump runtime API for Kusama, so we have that node features thing! -> https://github.com/polkadot-fellows/runtimes/pull/194 --------- Signed-off-by: Andrei Sandu Signed-off-by: alindima Co-authored-by: alindima --- .gitlab/pipeline/zombienet/polkadot.yml | 8 + Cargo.lock | 37 ++ polkadot/node/core/backing/Cargo.toml | 1 + polkadot/node/core/backing/src/lib.rs | 19 +- polkadot/node/core/backing/src/tests/mod.rs | 70 +- polkadot/node/core/provisioner/src/lib.rs | 2 +- polkadot/node/core/provisioner/src/tests.rs | 70 +- polkadot/primitives/src/v6/mod.rs | 208 +++++- polkadot/runtime/parachains/Cargo.toml | 1 + polkadot/runtime/parachains/src/builder.rs | 7 +- .../runtime/parachains/src/inclusion/mod.rs | 91 +-- .../runtime/parachains/src/inclusion/tests.rs | 423 +++++++++--- .../src/paras_inherent/benchmarking.rs | 4 +- .../parachains/src/paras_inherent/mod.rs | 288 ++++++--- .../parachains/src/paras_inherent/tests.rs | 604 ++++++++++++++++-- .../parachains/src/paras_inherent/weights.rs | 4 +- .../functional/0012-elastic-scaling-mvp.toml | 38 ++ .../functional/0012-elastic-scaling-mvp.zndsl | 28 + .../functional/0012-enable-node-feature.js | 37 ++ .../functional/0012-register-para.js | 37 ++ prdoc/pr_3231.prdoc | 11 + 21 files changed, 1640 insertions(+), 348 deletions(-) create mode 100644 polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.toml create mode 100644 polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.zndsl create mode 100644 polkadot/zombienet_tests/functional/0012-enable-node-feature.js create mode 100644 polkadot/zombienet_tests/functional/0012-register-para.js create mode 100644 prdoc/pr_3231.prdoc diff --git a/.gitlab/pipeline/zombienet/polkadot.yml b/.gitlab/pipeline/zombienet/polkadot.yml index 54eb6db48ca..97572f029d0 100644 --- a/.gitlab/pipeline/zombienet/polkadot.yml +++ b/.gitlab/pipeline/zombienet/polkadot.yml @@ -158,6 +158,14 @@ zombienet-polkadot-functional-0011-async-backing-6-seconds-rate: --local-dir="${LOCAL_DIR}/functional" --test="0011-async-backing-6-seconds-rate.zndsl" +zombienet-polkadot-functional-0012-elastic-scaling-mvp: + extends: + - .zombienet-polkadot-common + script: + - /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh + --local-dir="${LOCAL_DIR}/functional" + --test="0012-elastic-scaling-mvp.zndsl" + zombienet-polkadot-smoke-0001-parachains-smoke-test: extends: - .zombienet-polkadot-common diff --git a/Cargo.lock b/Cargo.lock index fbe2729acba..a23be53b34f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12512,6 +12512,7 @@ dependencies = [ "polkadot-primitives", "polkadot-primitives-test-helpers", "polkadot-statement-table", + "rstest", "sc-keystore", "schnellru", "sp-application-crypto", @@ -13350,6 +13351,7 @@ dependencies = [ "polkadot-runtime-metrics", "rand", "rand_chacha 0.3.1", + "rstest", "rustc-hex", "sc-keystore", "scale-info", @@ -14790,6 +14792,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "relative-path" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" + [[package]] name = "remote-ext-tests-bags-list" version = "1.0.0" @@ -15172,6 +15180,35 @@ dependencies = [ "winapi", ] +[[package]] +name = "rstest" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version 0.4.0", +] + +[[package]] +name = "rstest_macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version 0.4.0", + "syn 2.0.50", + "unicode-ident", +] + [[package]] name = "rtnetlink" version = "0.10.1" diff --git a/polkadot/node/core/backing/Cargo.toml b/polkadot/node/core/backing/Cargo.toml index f71b8df80dd..d0c1f9aa483 100644 --- a/polkadot/node/core/backing/Cargo.toml +++ b/polkadot/node/core/backing/Cargo.toml @@ -32,5 +32,6 @@ sc-keystore = { path = "../../../../substrate/client/keystore" } sp-tracing = { path = "../../../../substrate/primitives/tracing" } futures = { version = "0.3.21", features = ["thread-pool"] } assert_matches = "1.4.0" +rstest = "0.18.2" polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" } diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index 26f20a6d48e..69bf2e956a0 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -70,7 +70,7 @@ use std::{ sync::Arc, }; -use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; +use bitvec::vec::BitVec; use futures::{ channel::{mpsc, oneshot}, future::BoxFuture, @@ -494,20 +494,15 @@ fn table_attested_to_backed( } vote_positions.sort_by_key(|(_orig, pos_in_group)| *pos_in_group); - if inject_core_index { - let core_index_to_inject: BitVec = - BitVec::from_vec(vec![core_index.0 as u8]); - validator_indices.extend(core_index_to_inject); - } - - Some(BackedCandidate { + Some(BackedCandidate::new( candidate, - validity_votes: vote_positions + vote_positions .into_iter() .map(|(pos_in_votes, _pos_in_group)| validity_votes[pos_in_votes].clone()) .collect(), validator_indices, - }) + inject_core_index.then_some(core_index), + )) } async fn store_available_data( @@ -1775,7 +1770,7 @@ async fn post_import_statement_actions( &rp_state.table_context, rp_state.inject_core_index, ) { - let para_id = backed.candidate.descriptor.para_id; + let para_id = backed.candidate().descriptor.para_id; gum::debug!( target: LOG_TARGET, candidate_hash = ?candidate_hash, @@ -1796,7 +1791,7 @@ async fn post_import_statement_actions( // notify collator protocol. ctx.send_message(CollatorProtocolMessage::Backed { para_id, - para_head: backed.candidate.descriptor.para_head, + para_head: backed.candidate().descriptor.para_head, }) .await; // Notify statement distribution of backed candidate. diff --git a/polkadot/node/core/backing/src/tests/mod.rs b/polkadot/node/core/backing/src/tests/mod.rs index 7223f1e1dfb..e3cc5727435 100644 --- a/polkadot/node/core/backing/src/tests/mod.rs +++ b/polkadot/node/core/backing/src/tests/mod.rs @@ -33,9 +33,10 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ - CandidateDescriptor, GroupRotationInfo, HeadData, PersistedValidationData, PvfExecKind, - ScheduledCore, SessionIndex, LEGACY_MIN_BACKING_VOTES, + vstaging::node_features, CandidateDescriptor, GroupRotationInfo, HeadData, + PersistedValidationData, PvfExecKind, ScheduledCore, SessionIndex, LEGACY_MIN_BACKING_VOTES, }; +use rstest::rstest; use sp_application_crypto::AppCrypto; use sp_keyring::Sr25519Keyring; use sp_keystore::Keystore; @@ -79,6 +80,7 @@ pub(crate) struct TestState { relay_parent: Hash, minimum_backing_votes: u32, disabled_validators: Vec, + node_features: NodeFeatures, } impl TestState { @@ -157,6 +159,7 @@ impl Default for TestState { relay_parent, minimum_backing_votes: LEGACY_MIN_BACKING_VOTES, disabled_validators: Vec::new(), + node_features: Default::default(), } } } @@ -298,7 +301,7 @@ async fn test_startup(virtual_overseer: &mut VirtualOverseer, test_state: &TestS AllMessages::RuntimeApi( RuntimeApiMessage::Request(_parent, RuntimeApiRequest::NodeFeatures(_session_index, tx)) ) => { - tx.send(Ok(Default::default())).unwrap(); + tx.send(Ok(test_state.node_features.clone())).unwrap(); } ); @@ -494,9 +497,20 @@ fn backing_second_works() { } // Test that the candidate reaches quorum successfully. -#[test] -fn backing_works() { - let test_state = TestState::default(); +#[rstest] +#[case(true)] +#[case(false)] +fn backing_works(#[case] elastic_scaling_mvp: bool) { + let mut test_state = TestState::default(); + if elastic_scaling_mvp { + test_state + .node_features + .resize((node_features::FeatureIndex::ElasticScalingMVP as u8 + 1) as usize, false); + test_state + .node_features + .set(node_features::FeatureIndex::ElasticScalingMVP as u8 as usize, true); + } + test_harness(test_state.keystore.clone(), |mut virtual_overseer| async move { test_startup(&mut virtual_overseer, &test_state).await; @@ -647,6 +661,31 @@ fn backing_works() { virtual_overseer.send(FromOrchestra::Communication { msg: statement }).await; + let (tx, rx) = oneshot::channel(); + let msg = CandidateBackingMessage::GetBackedCandidates( + vec![(candidate_a_hash, test_state.relay_parent)], + tx, + ); + + virtual_overseer.send(FromOrchestra::Communication { msg }).await; + + let candidates = rx.await.unwrap(); + assert_eq!(1, candidates.len()); + assert_eq!(candidates[0].validity_votes().len(), 3); + + let (validator_indices, maybe_core_index) = + candidates[0].validator_indices_and_core_index(elastic_scaling_mvp); + if elastic_scaling_mvp { + assert_eq!(maybe_core_index.unwrap(), CoreIndex(0)); + } else { + assert!(maybe_core_index.is_none()); + } + + assert_eq!( + validator_indices, + bitvec::bitvec![u8, bitvec::order::Lsb0; 1, 1, 0, 1].as_bitslice() + ); + virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( ActiveLeavesUpdate::stop_work(test_state.relay_parent), @@ -919,20 +958,20 @@ fn backing_works_while_validation_ongoing() { let candidates = rx.await.unwrap(); assert_eq!(1, candidates.len()); - assert_eq!(candidates[0].validity_votes.len(), 3); + assert_eq!(candidates[0].validity_votes().len(), 3); assert!(candidates[0] - .validity_votes + .validity_votes() .contains(&ValidityAttestation::Implicit(signed_a.signature().clone()))); assert!(candidates[0] - .validity_votes + .validity_votes() .contains(&ValidityAttestation::Explicit(signed_b.signature().clone()))); assert!(candidates[0] - .validity_votes + .validity_votes() .contains(&ValidityAttestation::Explicit(signed_c.signature().clone()))); assert_eq!( - candidates[0].validator_indices, - bitvec::bitvec![u8, bitvec::order::Lsb0; 1, 0, 1, 1], + candidates[0].validator_indices_and_core_index(false), + (bitvec::bitvec![u8, bitvec::order::Lsb0; 1, 0, 1, 1].as_bitslice(), None) ); virtual_overseer @@ -1604,8 +1643,11 @@ fn candidate_backing_reorders_votes() { let expected_attestations = vec![fake_attestation(1).into(), fake_attestation(3).into(), fake_attestation(5).into()]; - assert_eq!(backed.validator_indices, expected_bitvec); - assert_eq!(backed.validity_votes, expected_attestations); + assert_eq!( + backed.validator_indices_and_core_index(false), + (expected_bitvec.as_bitslice(), None) + ); + assert_eq!(backed.validity_votes(), expected_attestations); } // Test whether we retry on failed PoV fetching. diff --git a/polkadot/node/core/provisioner/src/lib.rs b/polkadot/node/core/provisioner/src/lib.rs index d98f6ebfe42..a29cf72afb1 100644 --- a/polkadot/node/core/provisioner/src/lib.rs +++ b/polkadot/node/core/provisioner/src/lib.rs @@ -766,7 +766,7 @@ async fn select_candidates( // keep only one candidate with validation code. let mut with_validation_code = false; candidates.retain(|c| { - if c.candidate.commitments.new_validation_code.is_some() { + if c.candidate().commitments.new_validation_code.is_some() { if with_validation_code { return false } diff --git a/polkadot/node/core/provisioner/src/tests.rs b/polkadot/node/core/provisioner/src/tests.rs index b26df8ddb91..87c0e7a65d3 100644 --- a/polkadot/node/core/provisioner/src/tests.rs +++ b/polkadot/node/core/provisioner/src/tests.rs @@ -460,13 +460,16 @@ mod select_candidates { let expected_backed = expected_candidates .iter() - .map(|c| BackedCandidate { - candidate: CommittedCandidateReceipt { - descriptor: c.descriptor.clone(), - commitments: Default::default(), - }, - validity_votes: Vec::new(), - validator_indices: default_bitvec(MOCK_GROUP_SIZE), + .map(|c| { + BackedCandidate::new( + CommittedCandidateReceipt { + descriptor: c.descriptor().clone(), + commitments: Default::default(), + }, + Vec::new(), + default_bitvec(MOCK_GROUP_SIZE), + None, + ) }) .collect(); @@ -486,7 +489,7 @@ mod select_candidates { result.into_iter().for_each(|c| { assert!( - expected_candidates.iter().any(|c2| c.candidate.corresponds_to(c2)), + expected_candidates.iter().any(|c2| c.candidate().corresponds_to(c2)), "Failed to find candidate: {:?}", c, ) @@ -532,10 +535,13 @@ mod select_candidates { // Build possible outputs from select_candidates let backed_candidates: Vec<_> = committed_receipts .iter() - .map(|committed_receipt| BackedCandidate { - candidate: committed_receipt.clone(), - validity_votes: Vec::new(), - validator_indices: default_bitvec(MOCK_GROUP_SIZE), + .map(|committed_receipt| { + BackedCandidate::new( + committed_receipt.clone(), + Vec::new(), + default_bitvec(MOCK_GROUP_SIZE), + None, + ) }) .collect(); @@ -566,7 +572,7 @@ mod select_candidates { result.into_iter().for_each(|c| { assert!( - expected_backed_filtered.iter().any(|c2| c.candidate.corresponds_to(c2)), + expected_backed_filtered.iter().any(|c2| c.candidate().corresponds_to(c2)), "Failed to find candidate: {:?}", c, ) @@ -605,13 +611,16 @@ mod select_candidates { let expected_backed = expected_candidates .iter() - .map(|c| BackedCandidate { - candidate: CommittedCandidateReceipt { - descriptor: c.descriptor.clone(), - commitments: Default::default(), - }, - validity_votes: Vec::new(), - validator_indices: default_bitvec(MOCK_GROUP_SIZE), + .map(|c| { + BackedCandidate::new( + CommittedCandidateReceipt { + descriptor: c.descriptor.clone(), + commitments: Default::default(), + }, + Vec::new(), + default_bitvec(MOCK_GROUP_SIZE), + None, + ) }) .collect(); @@ -631,7 +640,7 @@ mod select_candidates { result.into_iter().for_each(|c| { assert!( - expected_candidates.iter().any(|c2| c.candidate.corresponds_to(c2)), + expected_candidates.iter().any(|c2| c.candidate().corresponds_to(c2)), "Failed to find candidate: {:?}", c, ) @@ -671,13 +680,16 @@ mod select_candidates { let expected_backed = expected_candidates .iter() - .map(|c| BackedCandidate { - candidate: CommittedCandidateReceipt { - descriptor: c.descriptor.clone(), - commitments: Default::default(), - }, - validity_votes: Vec::new(), - validator_indices: default_bitvec(MOCK_GROUP_SIZE), + .map(|c| { + BackedCandidate::new( + CommittedCandidateReceipt { + descriptor: c.descriptor().clone(), + commitments: Default::default(), + }, + Vec::new(), + default_bitvec(MOCK_GROUP_SIZE), + None, + ) }) .collect(); @@ -697,7 +709,7 @@ mod select_candidates { result.into_iter().for_each(|c| { assert!( - expected_candidates.iter().any(|c2| c.candidate.corresponds_to(c2)), + expected_candidates.iter().any(|c2| c.candidate().corresponds_to(c2)), "Failed to find candidate: {:?}", c, ) diff --git a/polkadot/primitives/src/v6/mod.rs b/polkadot/primitives/src/v6/mod.rs index 538eb385584..89431f7801f 100644 --- a/polkadot/primitives/src/v6/mod.rs +++ b/polkadot/primitives/src/v6/mod.rs @@ -16,7 +16,7 @@ //! `V6` Primitives. -use bitvec::vec::BitVec; +use bitvec::{field::BitField, slice::BitSlice, vec::BitVec}; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_std::{ @@ -707,19 +707,50 @@ pub type UncheckedSignedAvailabilityBitfields = Vec { /// The candidate referred to. - pub candidate: CommittedCandidateReceipt, + candidate: CommittedCandidateReceipt, /// The validity votes themselves, expressed as signatures. - pub validity_votes: Vec, - /// The indices of the validators within the group, expressed as a bitfield. - pub validator_indices: BitVec, + validity_votes: Vec, + /// The indices of the validators within the group, expressed as a bitfield. May be extended + /// beyond the backing group size to contain the assigned core index, if ElasticScalingMVP is + /// enabled. + validator_indices: BitVec, } impl BackedCandidate { - /// Get a reference to the descriptor of the para. + /// Constructor + pub fn new( + candidate: CommittedCandidateReceipt, + validity_votes: Vec, + validator_indices: BitVec, + core_index: Option, + ) -> Self { + let mut instance = Self { candidate, validity_votes, validator_indices }; + if let Some(core_index) = core_index { + instance.inject_core_index(core_index); + } + instance + } + + /// Get a reference to the descriptor of the candidate. pub fn descriptor(&self) -> &CandidateDescriptor { &self.candidate.descriptor } + /// Get a reference to the committed candidate receipt of the candidate. + pub fn candidate(&self) -> &CommittedCandidateReceipt { + &self.candidate + } + + /// Get a reference to the validity votes of the candidate. + pub fn validity_votes(&self) -> &[ValidityAttestation] { + &self.validity_votes + } + + /// Get a mutable reference to validity votes of the para. + pub fn validity_votes_mut(&mut self) -> &mut Vec { + &mut self.validity_votes + } + /// Compute this candidate's hash. pub fn hash(&self) -> CandidateHash where @@ -735,6 +766,48 @@ impl BackedCandidate { { self.candidate.to_plain() } + + /// Get a copy of the validator indices and the assumed core index, if any. + pub fn validator_indices_and_core_index( + &self, + core_index_enabled: bool, + ) -> (&BitSlice, Option) { + // This flag tells us if the block producers must enable Elastic Scaling MVP hack. + // It extends `BackedCandidate::validity_indices` to store a 8 bit core index. + if core_index_enabled { + let core_idx_offset = self.validator_indices.len().saturating_sub(8); + if core_idx_offset > 0 { + let (validator_indices_slice, core_idx_slice) = + self.validator_indices.split_at(core_idx_offset); + return ( + validator_indices_slice, + Some(CoreIndex(core_idx_slice.load::() as u32)), + ); + } + } + + (&self.validator_indices, None) + } + + /// Inject a core index in the validator_indices bitvec. + fn inject_core_index(&mut self, core_index: CoreIndex) { + let core_index_to_inject: BitVec = + BitVec::from_vec(vec![core_index.0 as u8]); + self.validator_indices.extend(core_index_to_inject); + } + + /// Update the validator indices and core index in the candidate. + pub fn set_validator_indices_and_core_index( + &mut self, + new_indices: BitVec, + maybe_core_index: Option, + ) { + self.validator_indices = new_indices; + + if let Some(core_index) = maybe_core_index { + self.inject_core_index(core_index); + } + } } /// Verify the backing of the given candidate. @@ -748,44 +821,42 @@ impl BackedCandidate { /// Returns either an error, indicating that one of the signatures was invalid or that the index /// was out-of-bounds, or the number of signatures checked. pub fn check_candidate_backing + Clone + Encode + core::fmt::Debug>( - backed: &BackedCandidate, + candidate_hash: CandidateHash, + validity_votes: &[ValidityAttestation], + validator_indices: &BitSlice, signing_context: &SigningContext, group_len: usize, validator_lookup: impl Fn(usize) -> Option, ) -> Result { - if backed.validator_indices.len() != group_len { + if validator_indices.len() != group_len { log::debug!( target: LOG_TARGET, "Check candidate backing: indices mismatch: group_len = {} , indices_len = {}", group_len, - backed.validator_indices.len(), + validator_indices.len(), ); return Err(()) } - if backed.validity_votes.len() > group_len { + if validity_votes.len() > group_len { log::debug!( target: LOG_TARGET, "Check candidate backing: Too many votes, expected: {}, found: {}", group_len, - backed.validity_votes.len(), + validity_votes.len(), ); return Err(()) } - // this is known, even in runtime, to be blake2-256. - let hash = backed.candidate.hash(); - let mut signed = 0; - for ((val_in_group_idx, _), attestation) in backed - .validator_indices + for ((val_in_group_idx, _), attestation) in validator_indices .iter() .enumerate() .filter(|(_, signed)| **signed) - .zip(backed.validity_votes.iter()) + .zip(validity_votes.iter()) { let validator_id = validator_lookup(val_in_group_idx).ok_or(())?; - let payload = attestation.signed_payload(hash, signing_context); + let payload = attestation.signed_payload(candidate_hash, signing_context); let sig = attestation.signature(); if sig.verify(&payload[..], &validator_id) { @@ -801,11 +872,11 @@ pub fn check_candidate_backing + Clone + Encode + core::fmt::Debu } } - if signed != backed.validity_votes.len() { + if signed != validity_votes.len() { log::error!( target: LOG_TARGET, "Check candidate backing: Too many signatures, expected = {}, found = {}", - backed.validity_votes.len() , + validity_votes.len(), signed, ); return Err(()) @@ -1884,6 +1955,34 @@ pub enum PvfExecKind { #[cfg(test)] mod tests { use super::*; + use bitvec::bitvec; + use primitives::sr25519; + + pub fn dummy_committed_candidate_receipt() -> CommittedCandidateReceipt { + let zeros = Hash::zero(); + + CommittedCandidateReceipt { + descriptor: CandidateDescriptor { + para_id: 0.into(), + relay_parent: zeros, + collator: CollatorId::from(sr25519::Public::from_raw([0; 32])), + persisted_validation_data_hash: zeros, + pov_hash: zeros, + erasure_root: zeros, + signature: CollatorSignature::from(sr25519::Signature([0u8; 64])), + para_head: zeros, + validation_code_hash: ValidationCode(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).hash(), + }, + commitments: CandidateCommitments { + head_data: HeadData(vec![]), + upward_messages: vec![].try_into().expect("empty vec fits within bounds"), + new_validation_code: None, + horizontal_messages: vec![].try_into().expect("empty vec fits within bounds"), + processed_downward_messages: 0, + hrmp_watermark: 0_u32, + }, + } + } #[test] fn group_rotation_info_calculations() { @@ -1958,4 +2057,73 @@ mod tests { assert!(zero_b.leading_zeros() >= zero_u.leading_zeros()); } + + #[test] + fn test_backed_candidate_injected_core_index() { + let initial_validator_indices = bitvec![u8, bitvec::order::Lsb0; 0, 1, 0, 1]; + let mut candidate = BackedCandidate::new( + dummy_committed_candidate_receipt(), + vec![], + initial_validator_indices.clone(), + None, + ); + + // No core index supplied, ElasticScalingMVP is off. + let (validator_indices, core_index) = candidate.validator_indices_and_core_index(false); + assert_eq!(validator_indices, initial_validator_indices.as_bitslice()); + assert!(core_index.is_none()); + + // No core index supplied, ElasticScalingMVP is on. Still, decoding will be ok if backing + // group size is <= 8, to give a chance to parachains that don't have multiple cores + // assigned. + let (validator_indices, core_index) = candidate.validator_indices_and_core_index(true); + assert_eq!(validator_indices, initial_validator_indices.as_bitslice()); + assert!(core_index.is_none()); + + let encoded_validator_indices = candidate.validator_indices.clone(); + candidate.set_validator_indices_and_core_index(validator_indices.into(), core_index); + assert_eq!(candidate.validator_indices, encoded_validator_indices); + + // No core index supplied, ElasticScalingMVP is on. Decoding is corrupted if backing group + // size larger than 8. + let candidate = BackedCandidate::new( + dummy_committed_candidate_receipt(), + vec![], + bitvec![u8, bitvec::order::Lsb0; 0, 1, 0, 1, 0, 1, 0, 1, 0], + None, + ); + let (validator_indices, core_index) = candidate.validator_indices_and_core_index(true); + assert_eq!(validator_indices, bitvec![u8, bitvec::order::Lsb0; 0].as_bitslice()); + assert!(core_index.is_some()); + + // Core index supplied, ElasticScalingMVP is off. Core index will be treated as normal + // validator indices. Runtime will check against this. + let candidate = BackedCandidate::new( + dummy_committed_candidate_receipt(), + vec![], + bitvec![u8, bitvec::order::Lsb0; 0, 1, 0, 1], + Some(CoreIndex(10)), + ); + let (validator_indices, core_index) = candidate.validator_indices_and_core_index(false); + assert_eq!( + validator_indices, + bitvec![u8, bitvec::order::Lsb0; 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0] + ); + assert!(core_index.is_none()); + + // Core index supplied, ElasticScalingMVP is on. + let mut candidate = BackedCandidate::new( + dummy_committed_candidate_receipt(), + vec![], + bitvec![u8, bitvec::order::Lsb0; 0, 1, 0, 1], + Some(CoreIndex(10)), + ); + let (validator_indices, core_index) = candidate.validator_indices_and_core_index(true); + assert_eq!(validator_indices, bitvec![u8, bitvec::order::Lsb0; 0, 1, 0, 1]); + assert_eq!(core_index, Some(CoreIndex(10))); + + let encoded_validator_indices = candidate.validator_indices.clone(); + candidate.set_validator_indices_and_core_index(validator_indices.into(), core_index); + assert_eq!(candidate.validator_indices, encoded_validator_indices); + } } diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml index 311a62b6c91..61040145476 100644 --- a/polkadot/runtime/parachains/Cargo.toml +++ b/polkadot/runtime/parachains/Cargo.toml @@ -69,6 +69,7 @@ sp-tracing = { path = "../../../substrate/primitives/tracing" } sp-crypto-hashing = { path = "../../../substrate/primitives/crypto/hashing" } thousands = "0.2.0" assert_matches = "1" +rstest = "0.18.2" serde_json = { workspace = true, default-features = true } [features] diff --git a/polkadot/runtime/parachains/src/builder.rs b/polkadot/runtime/parachains/src/builder.rs index 016b3fca589..500bc70cfa7 100644 --- a/polkadot/runtime/parachains/src/builder.rs +++ b/polkadot/runtime/parachains/src/builder.rs @@ -587,11 +587,12 @@ impl BenchBuilder { }) .collect(); - BackedCandidate:: { + BackedCandidate::::new( candidate, validity_votes, - validator_indices: bitvec::bitvec![u8, bitvec::order::Lsb0; 1; group_validators.len()], - } + bitvec::bitvec![u8, bitvec::order::Lsb0; 1; group_validators.len()], + None, + ) }) .collect() } diff --git a/polkadot/runtime/parachains/src/inclusion/mod.rs b/polkadot/runtime/parachains/src/inclusion/mod.rs index 90af9cde00a..16e2e93b561 100644 --- a/polkadot/runtime/parachains/src/inclusion/mod.rs +++ b/polkadot/runtime/parachains/src/inclusion/mod.rs @@ -47,10 +47,7 @@ use scale_info::TypeInfo; use sp_runtime::{traits::One, DispatchError, SaturatedConversion, Saturating}; #[cfg(feature = "std")] use sp_std::fmt; -use sp_std::{ - collections::{btree_map::BTreeMap, btree_set::BTreeSet}, - prelude::*, -}; +use sp_std::{collections::btree_set::BTreeSet, prelude::*}; pub use pallet::*; @@ -601,18 +598,16 @@ impl Pallet { /// scheduled cores. If these conditions are not met, the execution of the function fails. pub(crate) fn process_candidates( allowed_relay_parents: &AllowedRelayParentsTracker>, - candidates: Vec>, - scheduled: &BTreeMap, + candidates: Vec<(BackedCandidate, CoreIndex)>, group_validators: GV, + core_index_enabled: bool, ) -> Result, DispatchError> where GV: Fn(GroupIndex) -> Option>, { let now = >::block_number(); - ensure!(candidates.len() <= scheduled.len(), Error::::UnscheduledCandidate); - - if scheduled.is_empty() { + if candidates.is_empty() { return Ok(ProcessedCandidates::default()) } @@ -648,7 +643,7 @@ impl Pallet { // // In the meantime, we do certain sanity checks on the candidates and on the scheduled // list. - for (candidate_idx, backed_candidate) in candidates.iter().enumerate() { + for (candidate_idx, (backed_candidate, core_index)) in candidates.iter().enumerate() { let relay_parent_hash = backed_candidate.descriptor().relay_parent; let para_id = backed_candidate.descriptor().para_id; @@ -663,7 +658,7 @@ impl Pallet { let relay_parent_number = match check_ctx.verify_backed_candidate( &allowed_relay_parents, candidate_idx, - backed_candidate, + backed_candidate.candidate(), )? { Err(FailedToCreatePVD) => { log::debug!( @@ -679,11 +674,22 @@ impl Pallet { Ok(rpn) => rpn, }; - let para_id = backed_candidate.descriptor().para_id; + let (validator_indices, _) = + backed_candidate.validator_indices_and_core_index(core_index_enabled); + + log::debug!( + target: LOG_TARGET, + "Candidate {:?} on {:?}, + core_index_enabled = {}", + backed_candidate.hash(), + core_index, + core_index_enabled + ); + + check_assignment_in_order(core_index)?; + let mut backers = bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()]; - let core_idx = *scheduled.get(¶_id).ok_or(Error::::UnscheduledCandidate)?; - check_assignment_in_order(core_idx)?; ensure!( >::get(¶_id).is_none() && >::get(¶_id).is_none(), @@ -694,7 +700,7 @@ impl Pallet { // assigned to core at block `N + 1`. Thus, `relay_parent_number + 1` // will always land in the current session. let group_idx = >::group_assigned_to_core( - core_idx, + *core_index, relay_parent_number + One::one(), ) .ok_or_else(|| { @@ -711,7 +717,9 @@ impl Pallet { // check the signatures in the backing and that it is a majority. { let maybe_amount_validated = primitives::check_candidate_backing( - &backed_candidate, + backed_candidate.candidate().hash(), + backed_candidate.validity_votes(), + validator_indices, &signing_context, group_vals.len(), |intra_group_vi| { @@ -738,16 +746,15 @@ impl Pallet { let mut backer_idx_and_attestation = Vec::<(ValidatorIndex, ValidityAttestation)>::with_capacity( - backed_candidate.validator_indices.count_ones(), + validator_indices.count_ones(), ); let candidate_receipt = backed_candidate.receipt(); - for ((bit_idx, _), attestation) in backed_candidate - .validator_indices + for ((bit_idx, _), attestation) in validator_indices .iter() .enumerate() .filter(|(_, signed)| **signed) - .zip(backed_candidate.validity_votes.iter().cloned()) + .zip(backed_candidate.validity_votes().iter().cloned()) { let val_idx = group_vals.get(bit_idx).expect("this query succeeded above; qed"); @@ -760,7 +767,7 @@ impl Pallet { } core_indices_and_backers.push(( - (core_idx, para_id), + (*core_index, para_id), backers, group_idx, relay_parent_number, @@ -772,7 +779,7 @@ impl Pallet { // one more sweep for actually writing to storage. let core_indices = core_indices_and_backers.iter().map(|(c, ..)| *c).collect(); - for (candidate, (core, backers, group, relay_parent_number)) in + for ((candidate, _), (core, backers, group, relay_parent_number)) in candidates.into_iter().zip(core_indices_and_backers) { let para_id = candidate.descriptor().para_id; @@ -782,16 +789,18 @@ impl Pallet { bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()]; Self::deposit_event(Event::::CandidateBacked( - candidate.candidate.to_plain(), - candidate.candidate.commitments.head_data.clone(), + candidate.candidate().to_plain(), + candidate.candidate().commitments.head_data.clone(), core.0, group, )); - let candidate_hash = candidate.candidate.hash(); + let candidate_hash = candidate.candidate().hash(); - let (descriptor, commitments) = - (candidate.candidate.descriptor, candidate.candidate.commitments); + let (descriptor, commitments) = ( + candidate.candidate().descriptor.clone(), + candidate.candidate().commitments.clone(), + ); >::insert( ¶_id, @@ -1195,10 +1204,10 @@ impl CandidateCheckContext { &self, allowed_relay_parents: &AllowedRelayParentsTracker>, candidate_idx: usize, - backed_candidate: &BackedCandidate<::Hash>, + backed_candidate_receipt: &CommittedCandidateReceipt<::Hash>, ) -> Result, FailedToCreatePVD>, Error> { - let para_id = backed_candidate.descriptor().para_id; - let relay_parent = backed_candidate.descriptor().relay_parent; + let para_id = backed_candidate_receipt.descriptor().para_id; + let relay_parent = backed_candidate_receipt.descriptor().relay_parent; // Check that the relay-parent is one of the allowed relay-parents. let (relay_parent_storage_root, relay_parent_number) = { @@ -1223,13 +1232,13 @@ impl CandidateCheckContext { let expected = persisted_validation_data.hash(); ensure!( - expected == backed_candidate.descriptor().persisted_validation_data_hash, + expected == backed_candidate_receipt.descriptor().persisted_validation_data_hash, Error::::ValidationDataHashMismatch, ); } ensure!( - backed_candidate.descriptor().check_collator_signature().is_ok(), + backed_candidate_receipt.descriptor().check_collator_signature().is_ok(), Error::::NotCollatorSigned, ); @@ -1237,25 +1246,25 @@ impl CandidateCheckContext { // A candidate for a parachain without current validation code is not scheduled. .ok_or_else(|| Error::::UnscheduledCandidate)?; ensure!( - backed_candidate.descriptor().validation_code_hash == validation_code_hash, + backed_candidate_receipt.descriptor().validation_code_hash == validation_code_hash, Error::::InvalidValidationCodeHash, ); ensure!( - backed_candidate.descriptor().para_head == - backed_candidate.candidate.commitments.head_data.hash(), + backed_candidate_receipt.descriptor().para_head == + backed_candidate_receipt.commitments.head_data.hash(), Error::::ParaHeadMismatch, ); if let Err(err) = self.check_validation_outputs( para_id, relay_parent_number, - &backed_candidate.candidate.commitments.head_data, - &backed_candidate.candidate.commitments.new_validation_code, - backed_candidate.candidate.commitments.processed_downward_messages, - &backed_candidate.candidate.commitments.upward_messages, - BlockNumberFor::::from(backed_candidate.candidate.commitments.hrmp_watermark), - &backed_candidate.candidate.commitments.horizontal_messages, + &backed_candidate_receipt.commitments.head_data, + &backed_candidate_receipt.commitments.new_validation_code, + backed_candidate_receipt.commitments.processed_downward_messages, + &backed_candidate_receipt.commitments.upward_messages, + BlockNumberFor::::from(backed_candidate_receipt.commitments.hrmp_watermark), + &backed_candidate_receipt.commitments.horizontal_messages, ) { log::debug!( target: LOG_TARGET, diff --git a/polkadot/runtime/parachains/src/inclusion/tests.rs b/polkadot/runtime/parachains/src/inclusion/tests.rs index 557b7b71a9e..d2b5a67c3e4 100644 --- a/polkadot/runtime/parachains/src/inclusion/tests.rs +++ b/polkadot/runtime/parachains/src/inclusion/tests.rs @@ -120,6 +120,7 @@ pub(crate) fn back_candidate( keystore: &KeystorePtr, signing_context: &SigningContext, kind: BackingKind, + core_index: Option, ) -> BackedCandidate { let mut validator_indices = bitvec::bitvec![u8, BitOrderLsb0; 0; group.len()]; let threshold = effective_minimum_backing_votes( @@ -155,15 +156,20 @@ pub(crate) fn back_candidate( validity_votes.push(ValidityAttestation::Explicit(signature).into()); } - let backed = BackedCandidate { candidate, validity_votes, validator_indices }; + let backed = + BackedCandidate::new(candidate, validity_votes, validator_indices.clone(), core_index); - let successfully_backed = - primitives::check_candidate_backing(&backed, signing_context, group.len(), |i| { - Some(validators[group[i].0 as usize].public().into()) - }) - .ok() - .unwrap_or(0) >= - threshold; + let successfully_backed = primitives::check_candidate_backing( + backed.candidate().hash(), + backed.validity_votes(), + validator_indices.as_bitslice(), + signing_context, + group.len(), + |i| Some(validators[group[i].0 as usize].public().into()), + ) + .ok() + .unwrap_or(0) >= + threshold; match kind { BackingKind::Unanimous | BackingKind::Threshold => assert!(successfully_backed), @@ -919,38 +925,16 @@ fn candidate_checks() { let thread_a_assignment = (thread_a, CoreIndex::from(2)); let allowed_relay_parents = default_allowed_relay_parent_tracker(); - // unscheduled candidate. - { - let mut candidate = TestCandidateBuilder { - para_id: chain_a, - relay_parent: System::parent_hash(), - pov_hash: Hash::repeat_byte(1), - persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(), - hrmp_watermark: RELAY_PARENT_NUM, - ..Default::default() - } - .build(); - collator_sign_candidate(Sr25519Keyring::One, &mut candidate); - - let backed = back_candidate( - candidate, - &validators, - group_validators(GroupIndex::from(0)).unwrap().as_ref(), - &keystore, - &signing_context, - BackingKind::Threshold, - ); - - assert_noop!( - ParaInclusion::process_candidates( - &allowed_relay_parents, - vec![backed], - &[chain_b_assignment].into_iter().collect(), - &group_validators, - ), - Error::::UnscheduledCandidate - ); - } + // no candidates. + assert_eq!( + ParaInclusion::process_candidates( + &allowed_relay_parents, + vec![], + &group_validators, + false + ), + Ok(ProcessedCandidates::default()) + ); // candidates out of order. { @@ -984,6 +968,7 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); let backed_b = back_candidate( @@ -993,15 +978,16 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); // out-of-order manifests as unscheduled. assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed_b, backed_a], - &[chain_a_assignment, chain_b_assignment].into_iter().collect(), + vec![(backed_b, chain_b_assignment.1), (backed_a, chain_a_assignment.1)], &group_validators, + false ), Error::::ScheduledOutOfOrder ); @@ -1027,14 +1013,15 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Lacking, + None, ); assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed], - &[chain_a_assignment].into_iter().collect(), + vec![(backed, chain_a_assignment.1)], &group_validators, + false ), Error::::InsufficientBacking ); @@ -1075,6 +1062,7 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); let backed_b = back_candidate( @@ -1084,14 +1072,15 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed_b, backed_a], - &[chain_a_assignment, chain_b_assignment].into_iter().collect(), + vec![(backed_b, chain_b_assignment.1), (backed_a, chain_a_assignment.1)], &group_validators, + false ), Error::::DisallowedRelayParent ); @@ -1122,14 +1111,15 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed], - &[thread_a_assignment].into_iter().collect(), + vec![(backed, thread_a_assignment.1)], &group_validators, + false ), Error::::NotCollatorSigned ); @@ -1156,6 +1146,7 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); let candidate = TestCandidateBuilder::default().build(); @@ -1177,9 +1168,9 @@ fn candidate_checks() { assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed], - &[chain_a_assignment].into_iter().collect(), + vec![(backed, chain_a_assignment.1)], &group_validators, + false ), Error::::CandidateScheduledBeforeParaFree ); @@ -1212,14 +1203,15 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed], - &[chain_a_assignment].into_iter().collect(), + vec![(backed, chain_a_assignment.1)], &group_validators, + false ), Error::::CandidateScheduledBeforeParaFree ); @@ -1249,6 +1241,7 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); { @@ -1267,9 +1260,9 @@ fn candidate_checks() { assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed], - &[chain_a_assignment].into_iter().collect(), + vec![(backed, chain_a_assignment.1)], &group_validators, + false ), Error::::PrematureCodeUpgrade ); @@ -1296,14 +1289,15 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); assert_eq!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed], - &[chain_a_assignment].into_iter().collect(), + vec![(backed, chain_a_assignment.1)], &group_validators, + false ), Err(Error::::ValidationDataHashMismatch.into()), ); @@ -1331,14 +1325,15 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed], - &[chain_a_assignment].into_iter().collect(), + vec![(backed, chain_a_assignment.1)], &group_validators, + false ), Error::::InvalidValidationCodeHash ); @@ -1366,14 +1361,15 @@ fn candidate_checks() { &keystore, &signing_context, BackingKind::Threshold, + None, ); assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed], - &[chain_a_assignment].into_iter().collect(), + vec![(backed, chain_a_assignment.1)], &group_validators, + false ), Error::::ParaHeadMismatch ); @@ -1486,6 +1482,7 @@ fn backing_works() { &keystore, &signing_context, BackingKind::Threshold, + None, ); let backed_b = back_candidate( @@ -1495,6 +1492,7 @@ fn backing_works() { &keystore, &signing_context, BackingKind::Threshold, + None, ); let backed_c = back_candidate( @@ -1504,15 +1502,20 @@ fn backing_works() { &keystore, &signing_context, BackingKind::Threshold, + None, ); - let backed_candidates = vec![backed_a.clone(), backed_b.clone(), backed_c]; + let backed_candidates = vec![ + (backed_a.clone(), chain_a_assignment.1), + (backed_b.clone(), chain_b_assignment.1), + (backed_c, thread_a_assignment.1), + ]; let get_backing_group_idx = { // the order defines the group implicitly for this test case let backed_candidates_with_groups = backed_candidates .iter() .enumerate() - .map(|(idx, backed_candidate)| (backed_candidate.hash(), GroupIndex(idx as _))) + .map(|(idx, (backed_candidate, _))| (backed_candidate.hash(), GroupIndex(idx as _))) .collect::>(); move |candidate_hash_x: CandidateHash| -> Option { @@ -1532,10 +1535,8 @@ fn backing_works() { } = ParaInclusion::process_candidates( &allowed_relay_parents, backed_candidates.clone(), - &[chain_a_assignment, chain_b_assignment, thread_a_assignment] - .into_iter() - .collect(), &group_validators, + false, ) .expect("candidates scheduled, in order, and backed"); @@ -1554,22 +1555,22 @@ fn backing_works() { CandidateHash, (CandidateReceipt, Vec<(ValidatorIndex, ValidityAttestation)>), >::new(); - backed_candidates.into_iter().for_each(|backed_candidate| { + backed_candidates.into_iter().for_each(|(backed_candidate, _)| { let candidate_receipt_with_backers = intermediate .entry(backed_candidate.hash()) .or_insert_with(|| (backed_candidate.receipt(), Vec::new())); - - assert_eq!( - backed_candidate.validity_votes.len(), - backed_candidate.validator_indices.count_ones() - ); + let (validator_indices, None) = + backed_candidate.validator_indices_and_core_index(false) + else { + panic!("Expected no injected core index") + }; + assert_eq!(backed_candidate.validity_votes().len(), validator_indices.count_ones()); candidate_receipt_with_backers.1.extend( - backed_candidate - .validator_indices + validator_indices .iter() .enumerate() .filter(|(_, signed)| **signed) - .zip(backed_candidate.validity_votes.iter().cloned()) + .zip(backed_candidate.validity_votes().iter().cloned()) .filter_map(|((validator_index_within_group, _), attestation)| { let grp_idx = get_backing_group_idx(backed_candidate.hash()).unwrap(); group_validators(grp_idx).map(|validator_indices| { @@ -1666,6 +1667,257 @@ fn backing_works() { }); } +#[test] +fn backing_works_with_elastic_scaling_mvp() { + let chain_a = ParaId::from(1_u32); + let chain_b = ParaId::from(2_u32); + let thread_a = ParaId::from(3_u32); + + // The block number of the relay-parent for testing. + const RELAY_PARENT_NUM: BlockNumber = 4; + + let paras = vec![ + (chain_a, ParaKind::Parachain), + (chain_b, ParaKind::Parachain), + (thread_a, ParaKind::Parathread), + ]; + let validators = vec![ + Sr25519Keyring::Alice, + Sr25519Keyring::Bob, + Sr25519Keyring::Charlie, + Sr25519Keyring::Dave, + Sr25519Keyring::Ferdie, + ]; + let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); + for validator in validators.iter() { + Keystore::sr25519_generate_new( + &*keystore, + PARACHAIN_KEY_TYPE_ID, + Some(&validator.to_seed()), + ) + .unwrap(); + } + let validator_public = validator_pubkeys(&validators); + + new_test_ext(genesis_config(paras)).execute_with(|| { + shared::Pallet::::set_active_validators_ascending(validator_public.clone()); + shared::Pallet::::set_session_index(5); + + run_to_block(5, |_| None); + + let signing_context = + SigningContext { parent_hash: System::parent_hash(), session_index: 5 }; + + let group_validators = |group_index: GroupIndex| { + match group_index { + group_index if group_index == GroupIndex::from(0) => Some(vec![0, 1]), + group_index if group_index == GroupIndex::from(1) => Some(vec![2, 3]), + group_index if group_index == GroupIndex::from(2) => Some(vec![4]), + _ => panic!("Group index out of bounds for 2 parachains and 1 parathread core"), + } + .map(|vs| vs.into_iter().map(ValidatorIndex).collect::>()) + }; + + // When processing candidates, we compute the group index from scheduler. + let validator_groups = vec![ + vec![ValidatorIndex(0), ValidatorIndex(1)], + vec![ValidatorIndex(2), ValidatorIndex(3)], + vec![ValidatorIndex(4)], + ]; + Scheduler::set_validator_groups(validator_groups); + + let allowed_relay_parents = default_allowed_relay_parent_tracker(); + + let mut candidate_a = TestCandidateBuilder { + para_id: chain_a, + relay_parent: System::parent_hash(), + pov_hash: Hash::repeat_byte(1), + persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + collator_sign_candidate(Sr25519Keyring::One, &mut candidate_a); + + let mut candidate_b_1 = TestCandidateBuilder { + para_id: chain_b, + relay_parent: System::parent_hash(), + pov_hash: Hash::repeat_byte(2), + persisted_validation_data_hash: make_vdata_hash(chain_b).unwrap(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + collator_sign_candidate(Sr25519Keyring::One, &mut candidate_b_1); + + let mut candidate_b_2 = TestCandidateBuilder { + para_id: chain_b, + relay_parent: System::parent_hash(), + pov_hash: Hash::repeat_byte(3), + persisted_validation_data_hash: make_vdata_hash(chain_b).unwrap(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + collator_sign_candidate(Sr25519Keyring::One, &mut candidate_b_2); + + let backed_a = back_candidate( + candidate_a.clone(), + &validators, + group_validators(GroupIndex::from(0)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + None, + ); + + let backed_b_1 = back_candidate( + candidate_b_1.clone(), + &validators, + group_validators(GroupIndex::from(1)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + Some(CoreIndex(1)), + ); + + let backed_b_2 = back_candidate( + candidate_b_2.clone(), + &validators, + group_validators(GroupIndex::from(2)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + Some(CoreIndex(2)), + ); + + let backed_candidates = vec![ + (backed_a.clone(), CoreIndex(0)), + (backed_b_1.clone(), CoreIndex(1)), + (backed_b_2.clone(), CoreIndex(2)), + ]; + let get_backing_group_idx = { + // the order defines the group implicitly for this test case + let backed_candidates_with_groups = backed_candidates + .iter() + .enumerate() + .map(|(idx, (backed_candidate, _))| (backed_candidate.hash(), GroupIndex(idx as _))) + .collect::>(); + + move |candidate_hash_x: CandidateHash| -> Option { + backed_candidates_with_groups.iter().find_map(|(candidate_hash, grp)| { + if *candidate_hash == candidate_hash_x { + Some(*grp) + } else { + None + } + }) + } + }; + + let ProcessedCandidates { + core_indices: occupied_cores, + candidate_receipt_with_backing_validator_indices, + } = ParaInclusion::process_candidates( + &allowed_relay_parents, + backed_candidates.clone(), + &group_validators, + true, + ) + .expect("candidates scheduled, in order, and backed"); + + // Both b candidates will be backed. However, only one will be recorded on-chain and proceed + // with being made available. + assert_eq!( + occupied_cores, + vec![ + (CoreIndex::from(0), chain_a), + (CoreIndex::from(1), chain_b), + (CoreIndex::from(2), chain_b), + ] + ); + + // Transform the votes into the setup we expect + let mut expected = std::collections::HashMap::< + CandidateHash, + (CandidateReceipt, Vec<(ValidatorIndex, ValidityAttestation)>), + >::new(); + backed_candidates.into_iter().for_each(|(backed_candidate, _)| { + let candidate_receipt_with_backers = expected + .entry(backed_candidate.hash()) + .or_insert_with(|| (backed_candidate.receipt(), Vec::new())); + let (validator_indices, _maybe_core_index) = + backed_candidate.validator_indices_and_core_index(true); + assert_eq!(backed_candidate.validity_votes().len(), validator_indices.count_ones()); + candidate_receipt_with_backers.1.extend( + validator_indices + .iter() + .enumerate() + .filter(|(_, signed)| **signed) + .zip(backed_candidate.validity_votes().iter().cloned()) + .filter_map(|((validator_index_within_group, _), attestation)| { + let grp_idx = get_backing_group_idx(backed_candidate.hash()).unwrap(); + group_validators(grp_idx).map(|validator_indices| { + (validator_indices[validator_index_within_group], attestation) + }) + }), + ); + }); + + assert_eq!( + expected, + candidate_receipt_with_backing_validator_indices + .into_iter() + .map(|c| (c.0.hash(), c)) + .collect() + ); + + let backers = { + let num_backers = effective_minimum_backing_votes( + group_validators(GroupIndex(0)).unwrap().len(), + configuration::Pallet::::config().minimum_backing_votes, + ); + backing_bitfield(&(0..num_backers).collect::>()) + }; + assert_eq!( + >::get(&chain_a), + Some(CandidatePendingAvailability { + core: CoreIndex::from(0), + hash: candidate_a.hash(), + descriptor: candidate_a.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers, + backing_group: GroupIndex::from(0), + }) + ); + assert_eq!( + >::get(&chain_a), + Some(candidate_a.commitments), + ); + + // Only one candidate for b will be recorded on chain. + assert_eq!( + >::get(&chain_b), + Some(CandidatePendingAvailability { + core: CoreIndex::from(2), + hash: candidate_b_2.hash(), + descriptor: candidate_b_2.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers: backing_bitfield(&[4]), + backing_group: GroupIndex::from(2), + }) + ); + assert_eq!( + >::get(&chain_b), + Some(candidate_b_2.commitments), + ); + }); +} + #[test] fn can_include_candidate_with_ok_code_upgrade() { let chain_a = ParaId::from(1_u32); @@ -1740,14 +1992,15 @@ fn can_include_candidate_with_ok_code_upgrade() { &keystore, &signing_context, BackingKind::Threshold, + None, ); let ProcessedCandidates { core_indices: occupied_cores, .. } = ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed_a], - &[chain_a_assignment].into_iter().collect(), + vec![(backed_a, chain_a_assignment.1)], &group_validators, + false, ) .expect("candidates scheduled, in order, and backed"); @@ -1932,6 +2185,7 @@ fn check_allowed_relay_parents() { &keystore, &signing_context_a, BackingKind::Threshold, + None, ); let backed_b = back_candidate( @@ -1941,6 +2195,7 @@ fn check_allowed_relay_parents() { &keystore, &signing_context_b, BackingKind::Threshold, + None, ); let backed_c = back_candidate( @@ -1950,17 +2205,20 @@ fn check_allowed_relay_parents() { &keystore, &signing_context_c, BackingKind::Threshold, + None, ); - let backed_candidates = vec![backed_a, backed_b, backed_c]; + let backed_candidates = vec![ + (backed_a, chain_a_assignment.1), + (backed_b, chain_b_assignment.1), + (backed_c, thread_a_assignment.1), + ]; ParaInclusion::process_candidates( &allowed_relay_parents, backed_candidates.clone(), - &[chain_a_assignment, chain_b_assignment, thread_a_assignment] - .into_iter() - .collect(), &group_validators, + false, ) .expect("candidates scheduled, in order, and backed"); }); @@ -2189,14 +2447,15 @@ fn para_upgrade_delay_scheduled_from_inclusion() { &keystore, &signing_context, BackingKind::Threshold, + None, ); let ProcessedCandidates { core_indices: occupied_cores, .. } = ParaInclusion::process_candidates( &allowed_relay_parents, - vec![backed_a], - &[chain_a_assignment].into_iter().collect(), + vec![(backed_a, chain_a_assignment.1)], &group_validators, + false, ) .expect("candidates scheduled, in order, and backed"); diff --git a/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs b/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs index 0f6b23ae1b3..ad3fa8e0dc7 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs @@ -120,7 +120,7 @@ benchmarks! { // with `v` validity votes. // let votes = v as usize; let votes = min(scheduler::Pallet::::group_validators(GroupIndex::from(0)).unwrap().len(), v as usize); - assert_eq!(benchmark.backed_candidates.get(0).unwrap().validity_votes.len(), votes); + assert_eq!(benchmark.backed_candidates.get(0).unwrap().validity_votes().len(), votes); benchmark.bitfields.clear(); benchmark.disputes.clear(); @@ -177,7 +177,7 @@ benchmarks! { // There is 1 backed assert_eq!(benchmark.backed_candidates.len(), 1); assert_eq!( - benchmark.backed_candidates.get(0).unwrap().validity_votes.len(), + benchmark.backed_candidates.get(0).unwrap().validity_votes().len(), votes, ); diff --git a/polkadot/runtime/parachains/src/paras_inherent/mod.rs b/polkadot/runtime/parachains/src/paras_inherent/mod.rs index 81e092f0a99..cebf858c24a 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/mod.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/mod.rs @@ -43,15 +43,14 @@ use frame_support::{ use frame_system::pallet_prelude::*; use pallet_babe::{self, ParentBlockRandomness}; use primitives::{ - effective_minimum_backing_votes, BackedCandidate, CandidateHash, CandidateReceipt, - CheckedDisputeStatementSet, CheckedMultiDisputeStatementSet, CoreIndex, DisputeStatementSet, - InherentData as ParachainsInherentData, MultiDisputeStatementSet, ScrapedOnChainVotes, - SessionIndex, SignedAvailabilityBitfields, SigningContext, UncheckedSignedAvailabilityBitfield, - UncheckedSignedAvailabilityBitfields, ValidatorId, ValidatorIndex, ValidityAttestation, - PARACHAINS_INHERENT_IDENTIFIER, + effective_minimum_backing_votes, vstaging::node_features::FeatureIndex, BackedCandidate, + CandidateHash, CandidateReceipt, CheckedDisputeStatementSet, CheckedMultiDisputeStatementSet, + CoreIndex, DisputeStatementSet, InherentData as ParachainsInherentData, + MultiDisputeStatementSet, ScrapedOnChainVotes, SessionIndex, SignedAvailabilityBitfields, + SigningContext, UncheckedSignedAvailabilityBitfield, UncheckedSignedAvailabilityBitfields, + ValidatorId, ValidatorIndex, ValidityAttestation, PARACHAINS_INHERENT_IDENTIFIER, }; use rand::{seq::SliceRandom, SeedableRng}; - use scale_info::TypeInfo; use sp_runtime::traits::{Header as HeaderT, One}; use sp_std::{ @@ -145,6 +144,10 @@ pub mod pallet { DisputeInvalid, /// A candidate was backed by a disabled validator BackedByDisabled, + /// A candidate was backed even though the paraid was not scheduled. + BackedOnUnscheduledCore, + /// Too many candidates supplied. + UnscheduledCandidate, } /// Whether the paras inherent was included within this block. @@ -585,25 +588,39 @@ impl Pallet { let freed = collect_all_freed_cores::(freed_concluded.iter().cloned()); >::free_cores_and_fill_claimqueue(freed, now); - let scheduled = >::scheduled_paras() - .map(|(core_idx, para_id)| (para_id, core_idx)) - .collect(); METRICS.on_candidates_processed_total(backed_candidates.len() as u64); - let SanitizedBackedCandidates { backed_candidates, votes_from_disabled_were_dropped } = - sanitize_backed_candidates::( - backed_candidates, - &allowed_relay_parents, - |candidate_idx: usize, - backed_candidate: &BackedCandidate<::Hash>| - -> bool { - let para_id = backed_candidate.descriptor().para_id; - let prev_context = >::para_most_recent_context(para_id); - let check_ctx = CandidateCheckContext::::new(prev_context); - - // never include a concluded-invalid candidate - current_concluded_invalid_disputes.contains(&backed_candidate.hash()) || + let core_index_enabled = configuration::Pallet::::config() + .node_features + .get(FeatureIndex::ElasticScalingMVP as usize) + .map(|b| *b) + .unwrap_or(false); + + let mut scheduled: BTreeMap> = BTreeMap::new(); + let mut total_scheduled_cores = 0; + + for (core_idx, para_id) in >::scheduled_paras() { + total_scheduled_cores += 1; + scheduled.entry(para_id).or_default().insert(core_idx); + } + + let SanitizedBackedCandidates { + backed_candidates_with_core, + votes_from_disabled_were_dropped, + dropped_unscheduled_candidates, + } = sanitize_backed_candidates::( + backed_candidates, + &allowed_relay_parents, + |candidate_idx: usize, + backed_candidate: &BackedCandidate<::Hash>| + -> bool { + let para_id = backed_candidate.descriptor().para_id; + let prev_context = >::para_most_recent_context(para_id); + let check_ctx = CandidateCheckContext::::new(prev_context); + + // never include a concluded-invalid candidate + current_concluded_invalid_disputes.contains(&backed_candidate.hash()) || // Instead of checking the candidates with code upgrades twice // move the checking up here and skip it in the training wheels fallback. // That way we avoid possible duplicate checks while assuring all @@ -611,13 +628,19 @@ impl Pallet { // // NOTE: this is the only place where we check the relay-parent. check_ctx - .verify_backed_candidate(&allowed_relay_parents, candidate_idx, backed_candidate) + .verify_backed_candidate(&allowed_relay_parents, candidate_idx, backed_candidate.candidate()) .is_err() - }, - &scheduled, - ); + }, + scheduled, + core_index_enabled, + ); + + ensure!( + backed_candidates_with_core.len() <= total_scheduled_cores, + Error::::UnscheduledCandidate + ); - METRICS.on_candidates_sanitized(backed_candidates.len() as u64); + METRICS.on_candidates_sanitized(backed_candidates_with_core.len() as u64); // In `Enter` context (invoked during execution) there should be no backing votes from // disabled validators because they should have been filtered out during inherent data @@ -626,15 +649,22 @@ impl Pallet { ensure!(!votes_from_disabled_were_dropped, Error::::BackedByDisabled); } + // In `Enter` context (invoked during execution) we shouldn't have filtered any candidates + // due to a para not being scheduled. They have been filtered during inherent data + // preparation (`ProvideInherent` context). Abort in such cases. + if context == ProcessInherentDataContext::Enter { + ensure!(!dropped_unscheduled_candidates, Error::::BackedOnUnscheduledCore); + } + // Process backed candidates according to scheduled cores. let inclusion::ProcessedCandidates::< as HeaderT>::Hash> { core_indices: occupied, candidate_receipt_with_backing_validator_indices, } = >::process_candidates( &allowed_relay_parents, - backed_candidates.clone(), - &scheduled, + backed_candidates_with_core.clone(), >::group_validators, + core_index_enabled, )?; // Note which of the scheduled cores were actually occupied by a backed candidate. >::occupied(occupied.into_iter().map(|e| (e.0, e.1)).collect()); @@ -651,8 +681,15 @@ impl Pallet { let bitfields = bitfields.into_iter().map(|v| v.into_unchecked()).collect(); - let processed = - ParachainsInherentData { bitfields, backed_candidates, disputes, parent_header }; + let processed = ParachainsInherentData { + bitfields, + backed_candidates: backed_candidates_with_core + .into_iter() + .map(|(candidate, _)| candidate) + .collect(), + disputes, + parent_header, + }; Ok((processed, Some(all_weight_after).into())) } } @@ -774,7 +811,7 @@ fn apply_weight_limit( .iter() .enumerate() .filter_map(|(idx, candidate)| { - candidate.candidate.commitments.new_validation_code.as_ref().map(|_code| idx) + candidate.candidate().commitments.new_validation_code.as_ref().map(|_code| idx) }) .collect::>(); @@ -916,16 +953,22 @@ pub(crate) fn sanitize_bitfields( // Result from `sanitize_backed_candidates` #[derive(Debug, PartialEq)] struct SanitizedBackedCandidates { - // Sanitized backed candidates. The `Vec` is sorted according to the occupied core index. - backed_candidates: Vec>, + // Sanitized backed candidates along with the assigned core. The `Vec` is sorted according to + // the occupied core index. + backed_candidates_with_core: Vec<(BackedCandidate, CoreIndex)>, // Set to true if any votes from disabled validators were dropped from the input. votes_from_disabled_were_dropped: bool, + // Set to true if any candidates were dropped due to filtering done in + // `map_candidates_to_cores` + dropped_unscheduled_candidates: bool, } /// Filter out: /// 1. any candidates that have a concluded invalid dispute -/// 2. all backing votes from disabled validators -/// 3. any candidates that end up with less than `effective_minimum_backing_votes` backing votes +/// 2. any unscheduled candidates, as well as candidates whose paraid has multiple cores assigned +/// but have no injected core index. +/// 3. all backing votes from disabled validators +/// 4. any candidates that end up with less than `effective_minimum_backing_votes` backing votes /// /// `scheduled` follows the same naming scheme as provided in the /// guide: Currently `free` but might become `occupied`. @@ -944,7 +987,8 @@ fn sanitize_backed_candidates< mut backed_candidates: Vec>, allowed_relay_parents: &AllowedRelayParentsTracker>, mut candidate_has_concluded_invalid_dispute_or_is_invalid: F, - scheduled: &BTreeMap, + scheduled: BTreeMap>, + core_index_enabled: bool, ) -> SanitizedBackedCandidates { // Remove any candidates that were concluded invalid. // This does not assume sorting. @@ -952,22 +996,23 @@ fn sanitize_backed_candidates< !candidate_has_concluded_invalid_dispute_or_is_invalid(candidate_idx, backed_candidate) }); - // Assure the backed candidate's `ParaId`'s core is free. - // This holds under the assumption that `Scheduler::schedule` is called _before_. - // We don't check the relay-parent because this is done in the closure when - // constructing the inherent and during actual processing otherwise. - - backed_candidates.retain(|backed_candidate| { - let desc = backed_candidate.descriptor(); + let initial_candidate_count = backed_candidates.len(); + // Map candidates to scheduled cores. Filter out any unscheduled candidates. + let mut backed_candidates_with_core = map_candidates_to_cores::( + &allowed_relay_parents, + scheduled, + core_index_enabled, + backed_candidates, + ); - scheduled.get(&desc.para_id).is_some() - }); + let dropped_unscheduled_candidates = + initial_candidate_count != backed_candidates_with_core.len(); // Filter out backing statements from disabled validators - let dropped_disabled = filter_backed_statements_from_disabled_validators::( - &mut backed_candidates, + let votes_from_disabled_were_dropped = filter_backed_statements_from_disabled_validators::( + &mut backed_candidates_with_core, &allowed_relay_parents, - scheduled, + core_index_enabled, ); // Sort the `Vec` last, once there is a guarantee that these @@ -975,14 +1020,12 @@ fn sanitize_backed_candidates< // but more importantly are scheduled for a free core. // This both avoids extra work for obviously invalid candidates, // but also allows this to be done in place. - backed_candidates.sort_by(|x, y| { - // Never panics, since we filtered all panic arguments out in the previous `fn retain`. - scheduled[&x.descriptor().para_id].cmp(&scheduled[&y.descriptor().para_id]) - }); + backed_candidates_with_core.sort_by(|(_x, core_x), (_y, core_y)| core_x.cmp(&core_y)); SanitizedBackedCandidates { - backed_candidates, - votes_from_disabled_were_dropped: dropped_disabled, + dropped_unscheduled_candidates, + votes_from_disabled_were_dropped, + backed_candidates_with_core, } } @@ -1071,9 +1114,12 @@ fn limit_and_sanitize_disputes< // few more sanity checks. Returns `true` if at least one statement is removed and `false` // otherwise. fn filter_backed_statements_from_disabled_validators( - backed_candidates: &mut Vec::Hash>>, + backed_candidates_with_core: &mut Vec<( + BackedCandidate<::Hash>, + CoreIndex, + )>, allowed_relay_parents: &AllowedRelayParentsTracker>, - scheduled: &BTreeMap, + core_index_enabled: bool, ) -> bool { let disabled_validators = BTreeSet::<_>::from_iter(shared::Pallet::::disabled_validators().into_iter()); @@ -1083,7 +1129,7 @@ fn filter_backed_statements_from_disabled_validators *core_idx, - None => { - log::debug!(target: LOG_TARGET, "Can't get core idx of a backed candidate for para id {:?}. Dropping the candidate.", bc.descriptor().para_id); - return false - } - }; + backed_candidates_with_core.retain_mut(|(bc, core_idx)| { + let (validator_indices, maybe_core_index) = bc.validator_indices_and_core_index(core_index_enabled); + let mut validator_indices = BitVec::<_>::from(validator_indices); // Get relay parent block number of the candidate. We need this to get the group index assigned to this core at this block number let relay_parent_block_number = match allowed_relay_parents @@ -1116,7 +1156,7 @@ fn filter_backed_statements_from_disabled_validators>::group_assigned_to_core( - core_idx, + *core_idx, relay_parent_block_number + One::one(), ) { Some(group_idx) => group_idx, @@ -1138,12 +1178,15 @@ fn filter_backed_statements_from_disabled_validators::from_iter(validator_group.iter().map(|idx| disabled_validators.contains(idx))); // The indices of statements from disabled validators in `BackedCandidate`. We have to drop these. - let indices_to_drop = disabled_indices.clone() & &bc.validator_indices; + let indices_to_drop = disabled_indices.clone() & &validator_indices; // Apply the bitmask to drop the disabled validator from `validator_indices` - bc.validator_indices &= !disabled_indices; + validator_indices &= !disabled_indices; + // Update the backed candidate + bc.set_validator_indices_and_core_index(validator_indices, maybe_core_index); + // Remove the corresponding votes from `validity_votes` for idx in indices_to_drop.iter_ones().rev() { - bc.validity_votes.remove(idx); + bc.validity_votes_mut().remove(idx); } // If at least one statement was dropped we need to return `true` @@ -1154,10 +1197,9 @@ fn filter_backed_statements_from_disabled_validators( + allowed_relay_parents: &AllowedRelayParentsTracker>, + mut scheduled: BTreeMap>, + core_index_enabled: bool, + candidates: Vec>, +) -> Vec<(BackedCandidate, CoreIndex)> { + let mut backed_candidates_with_core = Vec::with_capacity(candidates.len()); + + // We keep a candidate if the parachain has only one core assigned or if + // a core index is provided by block author and it's indeed scheduled. + for backed_candidate in candidates { + let maybe_injected_core_index = get_injected_core_index::( + allowed_relay_parents, + &backed_candidate, + core_index_enabled, + ); + + let scheduled_cores = scheduled.get_mut(&backed_candidate.descriptor().para_id); + // Candidates without scheduled cores are silently filtered out. + if let Some(scheduled_cores) = scheduled_cores { + if let Some(core_idx) = maybe_injected_core_index { + if scheduled_cores.contains(&core_idx) { + scheduled_cores.remove(&core_idx); + backed_candidates_with_core.push((backed_candidate, core_idx)); + } + } else if scheduled_cores.len() == 1 { + backed_candidates_with_core + .push((backed_candidate, scheduled_cores.pop_first().expect("Length is 1"))); + } + } + } + + backed_candidates_with_core +} + +fn get_injected_core_index( + allowed_relay_parents: &AllowedRelayParentsTracker>, + candidate: &BackedCandidate, + core_index_enabled: bool, +) -> Option { + // After stripping the 8 bit extensions, the `validator_indices` field length is expected + // to be equal to backing group size. If these don't match, the `CoreIndex` is badly encoded, + // or not supported. + let (validator_indices, maybe_core_idx) = + candidate.validator_indices_and_core_index(core_index_enabled); + + let Some(core_idx) = maybe_core_idx else { return None }; + + let relay_parent_block_number = + match allowed_relay_parents.acquire_info(candidate.descriptor().relay_parent, None) { + Some((_, block_num)) => block_num, + None => { + log::debug!( + target: LOG_TARGET, + "Relay parent {:?} for candidate {:?} is not in the allowed relay parents. Dropping the candidate.", + candidate.descriptor().relay_parent, + candidate.candidate().hash(), + ); + return None + }, + }; + + // Get the backing group of the candidate backed at `core_idx`. + let group_idx = match >::group_assigned_to_core( + core_idx, + relay_parent_block_number + One::one(), + ) { + Some(group_idx) => group_idx, + None => { + log::debug!( + target: LOG_TARGET, + "Can't get the group index for core idx {:?}. Dropping the candidate {:?}.", + core_idx, + candidate.candidate().hash(), + ); + return None + }, + }; + + let group_validators = match >::group_validators(group_idx) { + Some(validators) => validators, + None => return None, + }; + + if group_validators.len() == validator_indices.len() { + Some(core_idx) + } else { + None + } } diff --git a/polkadot/runtime/parachains/src/paras_inherent/tests.rs b/polkadot/runtime/parachains/src/paras_inherent/tests.rs index 6f3eac35685..defb2f4404f 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/tests.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/tests.rs @@ -26,7 +26,10 @@ mod enter { use crate::{ builder::{Bench, BenchBuilder}, mock::{mock_assigner, new_test_ext, BlockLength, BlockWeights, MockGenesisConfig, Test}, - scheduler::common::Assignment, + scheduler::{ + common::{Assignment, AssignmentProvider, AssignmentProviderConfig}, + ParasEntry, + }, }; use assert_matches::assert_matches; use frame_support::assert_ok; @@ -697,6 +700,25 @@ mod enter { 2 ); + // One core was scheduled. We should put the assignment back, before calling enter(). + let now = >::block_number() + 1; + let used_cores = 5; + let cores = (0..used_cores) + .into_iter() + .map(|i| { + let AssignmentProviderConfig { ttl, .. } = + scheduler::Pallet::::assignment_provider_config(CoreIndex(i)); + // Load an assignment into provider so that one is present to pop + let assignment = + ::AssignmentProvider::get_mock_assignment( + CoreIndex(i), + ParaId::from(i), + ); + (CoreIndex(i), [ParasEntry::new(assignment, now + ttl)].into()) + }) + .collect(); + scheduler::ClaimQueue::::set(cores); + assert_ok!(Pallet::::enter( frame_system::RawOrigin::None.into(), limit_inherent_data, @@ -980,6 +1002,7 @@ mod sanitizers { AvailabilityBitfield, GroupIndex, Hash, Id as ParaId, SignedAvailabilityBitfield, ValidatorIndex, }; + use rstest::rstest; use sp_core::crypto::UncheckedFrom; use crate::mock::Test; @@ -1238,12 +1261,13 @@ mod sanitizers { // Backed candidates and scheduled parachains used for `sanitize_backed_candidates` testing struct TestData { backed_candidates: Vec, - scheduled_paras: BTreeMap, + all_backed_candidates_with_core: Vec<(BackedCandidate, CoreIndex)>, + scheduled_paras: BTreeMap>, } // Generate test data for the candidates and assert that the evnironment is set as expected // (check the comments for details) - fn get_test_data() -> TestData { + fn get_test_data(core_index_enabled: bool) -> TestData { const RELAY_PARENT_NUM: u32 = 3; // Add the relay parent to `shared` pallet. Otherwise some code (e.g. filtering backing @@ -1285,9 +1309,14 @@ mod sanitizers { shared::Pallet::::set_active_validators_ascending(validator_ids); // Two scheduled parachains - ParaId(1) on CoreIndex(0) and ParaId(2) on CoreIndex(1) - let scheduled = (0_usize..2) + let scheduled: BTreeMap> = (0_usize..2) .into_iter() - .map(|idx| (ParaId::from(1_u32 + idx as u32), CoreIndex::from(idx as u32))) + .map(|idx| { + ( + ParaId::from(1_u32 + idx as u32), + [CoreIndex::from(idx as u32)].into_iter().collect(), + ) + }) .collect::>(); // Set the validator groups in `scheduler` @@ -1301,7 +1330,7 @@ mod sanitizers { ( CoreIndex::from(0), VecDeque::from([ParasEntry::new( - Assignment::Pool { para_id: 1.into(), core_index: CoreIndex(1) }, + Assignment::Pool { para_id: 1.into(), core_index: CoreIndex(0) }, RELAY_PARENT_NUM, )]), ), @@ -1319,12 +1348,12 @@ mod sanitizers { match group_index { group_index if group_index == GroupIndex::from(0) => Some(vec![0, 1]), group_index if group_index == GroupIndex::from(1) => Some(vec![2, 3]), - _ => panic!("Group index out of bounds for 2 parachains and 1 parathread core"), + _ => panic!("Group index out of bounds"), } .map(|m| m.into_iter().map(ValidatorIndex).collect::>()) }; - // Two backed candidates from each parachain + // One backed candidate from each parachain let backed_candidates = (0_usize..2) .into_iter() .map(|idx0| { @@ -1348,6 +1377,7 @@ mod sanitizers { &keystore, &signing_context, BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(idx0 as u32)), ); backed }) @@ -1369,13 +1399,373 @@ mod sanitizers { ] ); - TestData { backed_candidates, scheduled_paras: scheduled } + let all_backed_candidates_with_core = backed_candidates + .iter() + .map(|candidate| { + // Only one entry for this test data. + ( + candidate.clone(), + scheduled + .get(&candidate.descriptor().para_id) + .unwrap() + .first() + .copied() + .unwrap(), + ) + }) + .collect(); + + TestData { + backed_candidates, + scheduled_paras: scheduled, + all_backed_candidates_with_core, + } } - #[test] - fn happy_path() { + // Generate test data for the candidates and assert that the evnironment is set as expected + // (check the comments for details) + // Para 1 scheduled on core 0 and core 1. Two candidates are supplied. + // Para 2 scheduled on cores 2 and 3. One candidate supplied. + // Para 3 scheduled on core 4. One candidate supplied. + // Para 4 scheduled on core 5. Two candidates supplied. + // Para 5 scheduled on core 6. No candidates supplied. + fn get_test_data_multiple_cores_per_para(core_index_enabled: bool) -> TestData { + const RELAY_PARENT_NUM: u32 = 3; + + // Add the relay parent to `shared` pallet. Otherwise some code (e.g. filtering backing + // votes) won't behave correctly + shared::Pallet::::add_allowed_relay_parent( + default_header().hash(), + Default::default(), + RELAY_PARENT_NUM, + 1, + ); + + let header = default_header(); + let relay_parent = header.hash(); + let session_index = SessionIndex::from(0_u32); + + let keystore = LocalKeystore::in_memory(); + let keystore = Arc::new(keystore) as KeystorePtr; + let signing_context = SigningContext { parent_hash: relay_parent, session_index }; + + let validators = vec![ + keyring::Sr25519Keyring::Alice, + keyring::Sr25519Keyring::Bob, + keyring::Sr25519Keyring::Charlie, + keyring::Sr25519Keyring::Dave, + keyring::Sr25519Keyring::Eve, + keyring::Sr25519Keyring::Ferdie, + keyring::Sr25519Keyring::One, + ]; + for validator in validators.iter() { + Keystore::sr25519_generate_new( + &*keystore, + PARACHAIN_KEY_TYPE_ID, + Some(&validator.to_seed()), + ) + .unwrap(); + } + + // Set active validators in `shared` pallet + let validator_ids = + validators.iter().map(|v| v.public().into()).collect::>(); + shared::Pallet::::set_active_validators_ascending(validator_ids); + + // Set the validator groups in `scheduler` + scheduler::Pallet::::set_validator_groups(vec![ + vec![ValidatorIndex(0)], + vec![ValidatorIndex(1)], + vec![ValidatorIndex(2)], + vec![ValidatorIndex(3)], + vec![ValidatorIndex(4)], + vec![ValidatorIndex(5)], + vec![ValidatorIndex(6)], + ]); + + // Update scheduler's claimqueue with the parachains + scheduler::Pallet::::set_claimqueue(BTreeMap::from([ + ( + CoreIndex::from(0), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 1.into(), core_index: CoreIndex(0) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(1), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 1.into(), core_index: CoreIndex(1) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(2), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 2.into(), core_index: CoreIndex(2) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(3), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 2.into(), core_index: CoreIndex(3) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(4), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 3.into(), core_index: CoreIndex(4) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(5), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 4.into(), core_index: CoreIndex(5) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(6), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 5.into(), core_index: CoreIndex(6) }, + RELAY_PARENT_NUM, + )]), + ), + ])); + + // Callback used for backing candidates + let group_validators = |group_index: GroupIndex| { + match group_index { + group_index if group_index == GroupIndex::from(0) => Some(vec![0]), + group_index if group_index == GroupIndex::from(1) => Some(vec![1]), + group_index if group_index == GroupIndex::from(2) => Some(vec![2]), + group_index if group_index == GroupIndex::from(3) => Some(vec![3]), + group_index if group_index == GroupIndex::from(4) => Some(vec![4]), + group_index if group_index == GroupIndex::from(5) => Some(vec![5]), + group_index if group_index == GroupIndex::from(6) => Some(vec![6]), + + _ => panic!("Group index out of bounds"), + } + .map(|m| m.into_iter().map(ValidatorIndex).collect::>()) + }; + + let mut backed_candidates = vec![]; + let mut all_backed_candidates_with_core = vec![]; + + // Para 1 + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(1), + relay_parent, + pov_hash: Hash::repeat_byte(1 as u8), + persisted_validation_data_hash: [42u8; 32].into(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed: BackedCandidate = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(0 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(0 as u32)), + ); + backed_candidates.push(backed.clone()); + if core_index_enabled { + all_backed_candidates_with_core.push((backed, CoreIndex(0))); + } + + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(1), + relay_parent, + pov_hash: Hash::repeat_byte(2 as u8), + persisted_validation_data_hash: [42u8; 32].into(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(1 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(1 as u32)), + ); + backed_candidates.push(backed.clone()); + if core_index_enabled { + all_backed_candidates_with_core.push((backed, CoreIndex(1))); + } + } + + // Para 2 + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(2), + relay_parent, + pov_hash: Hash::repeat_byte(3 as u8), + persisted_validation_data_hash: [42u8; 32].into(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(2 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(2 as u32)), + ); + backed_candidates.push(backed.clone()); + if core_index_enabled { + all_backed_candidates_with_core.push((backed, CoreIndex(2))); + } + } + + // Para 3 + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(3), + relay_parent, + pov_hash: Hash::repeat_byte(4 as u8), + persisted_validation_data_hash: [42u8; 32].into(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(4 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(4 as u32)), + ); + backed_candidates.push(backed.clone()); + all_backed_candidates_with_core.push((backed, CoreIndex(4))); + } + + // Para 4 + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(4), + relay_parent, + pov_hash: Hash::repeat_byte(5 as u8), + persisted_validation_data_hash: [42u8; 32].into(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(5 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + None, + ); + backed_candidates.push(backed.clone()); + all_backed_candidates_with_core.push((backed, CoreIndex(5))); + + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(4), + relay_parent, + pov_hash: Hash::repeat_byte(6 as u8), + persisted_validation_data_hash: [42u8; 32].into(), + hrmp_watermark: RELAY_PARENT_NUM, + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(5 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(5 as u32)), + ); + backed_candidates.push(backed.clone()); + } + + // No candidate for para 5. + + // State sanity checks + assert_eq!( + >::scheduled_paras().collect::>(), + vec![ + (CoreIndex(0), ParaId::from(1)), + (CoreIndex(1), ParaId::from(1)), + (CoreIndex(2), ParaId::from(2)), + (CoreIndex(3), ParaId::from(2)), + (CoreIndex(4), ParaId::from(3)), + (CoreIndex(5), ParaId::from(4)), + (CoreIndex(6), ParaId::from(5)), + ] + ); + let mut scheduled: BTreeMap> = BTreeMap::new(); + for (core_idx, para_id) in >::scheduled_paras() { + scheduled.entry(para_id).or_default().insert(core_idx); + } + + assert_eq!( + shared::Pallet::::active_validator_indices(), + vec![ + ValidatorIndex(0), + ValidatorIndex(1), + ValidatorIndex(2), + ValidatorIndex(3), + ValidatorIndex(4), + ValidatorIndex(5), + ValidatorIndex(6), + ] + ); + + TestData { + backed_candidates, + scheduled_paras: scheduled, + all_backed_candidates_with_core, + } + } + + #[rstest] + #[case(false)] + #[case(true)] + fn happy_path(#[case] core_index_enabled: bool) { new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { backed_candidates, scheduled_paras: scheduled } = get_test_data(); + let TestData { + backed_candidates, + all_backed_candidates_with_core, + scheduled_paras: scheduled, + } = get_test_data(core_index_enabled); let has_concluded_invalid = |_idx: usize, _backed_candidate: &BackedCandidate| -> bool { false }; @@ -1385,47 +1775,95 @@ mod sanitizers { backed_candidates.clone(), &>::allowed_relay_parents(), has_concluded_invalid, - &scheduled + scheduled, + core_index_enabled ), SanitizedBackedCandidates { - backed_candidates, - votes_from_disabled_were_dropped: false + backed_candidates_with_core: all_backed_candidates_with_core, + votes_from_disabled_were_dropped: false, + dropped_unscheduled_candidates: false } ); + }); + } + + #[rstest] + #[case(false)] + #[case(true)] + fn test_with_multiple_cores_per_para(#[case] core_index_enabled: bool) { + new_test_ext(MockGenesisConfig::default()).execute_with(|| { + let TestData { + backed_candidates, + all_backed_candidates_with_core: expected_all_backed_candidates_with_core, + scheduled_paras: scheduled, + } = get_test_data_multiple_cores_per_para(core_index_enabled); + + let has_concluded_invalid = + |_idx: usize, _backed_candidate: &BackedCandidate| -> bool { false }; - {} + assert_eq!( + sanitize_backed_candidates::( + backed_candidates.clone(), + &>::allowed_relay_parents(), + has_concluded_invalid, + scheduled, + core_index_enabled + ), + SanitizedBackedCandidates { + backed_candidates_with_core: expected_all_backed_candidates_with_core, + votes_from_disabled_were_dropped: false, + dropped_unscheduled_candidates: true + } + ); }); } // nothing is scheduled, so no paraids match, thus all backed candidates are skipped - #[test] - fn nothing_scheduled() { + #[rstest] + #[case(false, false)] + #[case(true, true)] + #[case(false, true)] + #[case(true, false)] + fn nothing_scheduled( + #[case] core_index_enabled: bool, + #[case] multiple_cores_per_para: bool, + ) { new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { backed_candidates, scheduled_paras: _ } = get_test_data(); - let scheduled = &BTreeMap::new(); + let TestData { backed_candidates, .. } = if multiple_cores_per_para { + get_test_data_multiple_cores_per_para(core_index_enabled) + } else { + get_test_data(core_index_enabled) + }; + let scheduled = BTreeMap::new(); let has_concluded_invalid = |_idx: usize, _backed_candidate: &BackedCandidate| -> bool { false }; let SanitizedBackedCandidates { - backed_candidates: sanitized_backed_candidates, + backed_candidates_with_core: sanitized_backed_candidates, votes_from_disabled_were_dropped, + dropped_unscheduled_candidates, } = sanitize_backed_candidates::( backed_candidates.clone(), &>::allowed_relay_parents(), has_concluded_invalid, - &scheduled, + scheduled, + core_index_enabled, ); assert!(sanitized_backed_candidates.is_empty()); assert!(!votes_from_disabled_were_dropped); + assert!(dropped_unscheduled_candidates); }); } // candidates that have concluded as invalid are filtered out - #[test] - fn invalid_are_filtered_out() { + #[rstest] + #[case(false)] + #[case(true)] + fn invalid_are_filtered_out(#[case] core_index_enabled: bool) { new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { backed_candidates, scheduled_paras: scheduled } = get_test_data(); + let TestData { backed_candidates, scheduled_paras: scheduled, .. } = + get_test_data(core_index_enabled); // mark every second one as concluded invalid let set = { @@ -1440,45 +1878,55 @@ mod sanitizers { let has_concluded_invalid = |_idx: usize, candidate: &BackedCandidate| set.contains(&candidate.hash()); let SanitizedBackedCandidates { - backed_candidates: sanitized_backed_candidates, + backed_candidates_with_core: sanitized_backed_candidates, votes_from_disabled_were_dropped, + dropped_unscheduled_candidates, } = sanitize_backed_candidates::( backed_candidates.clone(), &>::allowed_relay_parents(), has_concluded_invalid, - &scheduled, + scheduled, + core_index_enabled, ); assert_eq!(sanitized_backed_candidates.len(), backed_candidates.len() / 2); assert!(!votes_from_disabled_were_dropped); + assert!(!dropped_unscheduled_candidates); }); } - #[test] - fn disabled_non_signing_validator_doesnt_get_filtered() { + #[rstest] + #[case(false)] + #[case(true)] + fn disabled_non_signing_validator_doesnt_get_filtered(#[case] core_index_enabled: bool) { new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { mut backed_candidates, scheduled_paras } = get_test_data(); + let TestData { mut all_backed_candidates_with_core, .. } = + get_test_data(core_index_enabled); // Disable Eve set_disabled_validators(vec![4]); - let before = backed_candidates.clone(); + let before = all_backed_candidates_with_core.clone(); // Eve is disabled but no backing statement is signed by it so nothing should be // filtered assert!(!filter_backed_statements_from_disabled_validators::( - &mut backed_candidates, + &mut all_backed_candidates_with_core, &>::allowed_relay_parents(), - &scheduled_paras + core_index_enabled )); - assert_eq!(backed_candidates, before); + assert_eq!(all_backed_candidates_with_core, before); }); } - - #[test] - fn drop_statements_from_disabled_without_dropping_candidate() { + #[rstest] + #[case(false)] + #[case(true)] + fn drop_statements_from_disabled_without_dropping_candidate( + #[case] core_index_enabled: bool, + ) { new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { mut backed_candidates, scheduled_paras } = get_test_data(); + let TestData { mut all_backed_candidates_with_core, .. } = + get_test_data(core_index_enabled); // Disable Alice set_disabled_validators(vec![0]); @@ -1491,61 +1939,83 @@ mod sanitizers { configuration::Pallet::::force_set_active_config(hc); // Verify the initial state is as expected - assert_eq!(backed_candidates.get(0).unwrap().validity_votes.len(), 2); assert_eq!( - backed_candidates.get(0).unwrap().validator_indices.get(0).unwrap(), - true + all_backed_candidates_with_core.get(0).unwrap().0.validity_votes().len(), + 2 ); - assert_eq!( - backed_candidates.get(0).unwrap().validator_indices.get(1).unwrap(), - true - ); - let untouched = backed_candidates.get(1).unwrap().clone(); + let (validator_indices, maybe_core_index) = all_backed_candidates_with_core + .get(0) + .unwrap() + .0 + .validator_indices_and_core_index(core_index_enabled); + if core_index_enabled { + assert!(maybe_core_index.is_some()); + } else { + assert!(maybe_core_index.is_none()); + } + + assert_eq!(validator_indices.get(0).unwrap(), true); + assert_eq!(validator_indices.get(1).unwrap(), true); + let untouched = all_backed_candidates_with_core.get(1).unwrap().0.clone(); assert!(filter_backed_statements_from_disabled_validators::( - &mut backed_candidates, + &mut all_backed_candidates_with_core, &>::allowed_relay_parents(), - &scheduled_paras + core_index_enabled )); + let (validator_indices, maybe_core_index) = all_backed_candidates_with_core + .get(0) + .unwrap() + .0 + .validator_indices_and_core_index(core_index_enabled); + if core_index_enabled { + assert!(maybe_core_index.is_some()); + } else { + assert!(maybe_core_index.is_none()); + } + // there should still be two backed candidates - assert_eq!(backed_candidates.len(), 2); + assert_eq!(all_backed_candidates_with_core.len(), 2); // but the first one should have only one validity vote - assert_eq!(backed_candidates.get(0).unwrap().validity_votes.len(), 1); - // Validator 0 vote should be dropped, validator 1 - retained assert_eq!( - backed_candidates.get(0).unwrap().validator_indices.get(0).unwrap(), - false - ); - assert_eq!( - backed_candidates.get(0).unwrap().validator_indices.get(1).unwrap(), - true + all_backed_candidates_with_core.get(0).unwrap().0.validity_votes().len(), + 1 ); + // Validator 0 vote should be dropped, validator 1 - retained + assert_eq!(validator_indices.get(0).unwrap(), false); + assert_eq!(validator_indices.get(1).unwrap(), true); // the second candidate shouldn't be modified - assert_eq!(*backed_candidates.get(1).unwrap(), untouched); + assert_eq!(all_backed_candidates_with_core.get(1).unwrap().0, untouched); }); } - #[test] - fn drop_candidate_if_all_statements_are_from_disabled() { + #[rstest] + #[case(false)] + #[case(true)] + fn drop_candidate_if_all_statements_are_from_disabled(#[case] core_index_enabled: bool) { new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { mut backed_candidates, scheduled_paras } = get_test_data(); + let TestData { mut all_backed_candidates_with_core, .. } = + get_test_data(core_index_enabled); // Disable Alice and Bob set_disabled_validators(vec![0, 1]); // Verify the initial state is as expected - assert_eq!(backed_candidates.get(0).unwrap().validity_votes.len(), 2); - let untouched = backed_candidates.get(1).unwrap().clone(); + assert_eq!( + all_backed_candidates_with_core.get(0).unwrap().0.validity_votes().len(), + 2 + ); + let untouched = all_backed_candidates_with_core.get(1).unwrap().0.clone(); assert!(filter_backed_statements_from_disabled_validators::( - &mut backed_candidates, + &mut all_backed_candidates_with_core, &>::allowed_relay_parents(), - &scheduled_paras + core_index_enabled )); - assert_eq!(backed_candidates.len(), 1); - assert_eq!(*backed_candidates.get(0).unwrap(), untouched); + assert_eq!(all_backed_candidates_with_core.len(), 1); + assert_eq!(all_backed_candidates_with_core.get(0).unwrap().0, untouched); }); } } diff --git a/polkadot/runtime/parachains/src/paras_inherent/weights.rs b/polkadot/runtime/parachains/src/paras_inherent/weights.rs index 05cc53fae04..0f4e5be572a 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/weights.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/weights.rs @@ -149,11 +149,11 @@ pub fn backed_candidate_weight( candidate: &BackedCandidate, ) -> Weight { set_proof_size_to_tx_size( - if candidate.candidate.commitments.new_validation_code.is_some() { + if candidate.candidate().commitments.new_validation_code.is_some() { <::WeightInfo as WeightInfo>::enter_backed_candidate_code_upgrade() } else { <::WeightInfo as WeightInfo>::enter_backed_candidates_variable( - candidate.validity_votes.len() as u32, + candidate.validity_votes().len() as u32, ) }, candidate, diff --git a/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.toml b/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.toml new file mode 100644 index 00000000000..0dfd814e10a --- /dev/null +++ b/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.toml @@ -0,0 +1,38 @@ +[settings] +timeout = 1000 +bootnode = true + +[relaychain.genesis.runtimeGenesis.patch.configuration.config] + max_validators_per_core = 2 + needed_approvals = 4 + coretime_cores = 2 + +[relaychain] +default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" +chain = "rococo-local" +default_command = "polkadot" + +[relaychain.default_resources] +limits = { memory = "4G", cpu = "2" } +requests = { memory = "2G", cpu = "1" } + + [[relaychain.nodes]] + name = "alice" + validator = "true" + + [[relaychain.node_groups]] + name = "validator" + count = 3 + args = [ "-lparachain=debug,runtime=debug"] + +[[parachains]] +id = 2000 +default_command = "polkadot-parachain" +add_to_genesis = false +register_para = true +onboard_as_parachain = false + + [parachains.collator] + name = "collator2000" + command = "polkadot-parachain" + args = [ "-lparachain=debug" ] diff --git a/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.zndsl b/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.zndsl new file mode 100644 index 00000000000..a7193c9282b --- /dev/null +++ b/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.zndsl @@ -0,0 +1,28 @@ +Description: Test that a paraid acquiring multiple cores does not brick itself if ElasticScalingMVP feature is enabled +Network: ./0012-elastic-scaling-mvp.toml +Creds: config + +# Check authority status. +validator: reports node_roles is 4 + +validator: reports substrate_block_height{status="finalized"} is at least 10 within 100 seconds + +# Ensure parachain was able to make progress. +validator: parachain 2000 block height is at least 10 within 200 seconds + +# Register the second core assigned to this parachain. +alice: js-script ./0012-register-para.js return is 0 within 600 seconds + +validator: reports substrate_block_height{status="finalized"} is at least 35 within 100 seconds + +# Parachain will now be stalled +validator: parachain 2000 block height is lower than 20 within 300 seconds + +# Enable the ElasticScalingMVP node feature. +alice: js-script ./0012-enable-node-feature.js with "1" return is 0 within 600 seconds + +# Wait two sessions for the config to be updated. +sleep 120 seconds + +# Ensure parachain is now making progress. +validator: parachain 2000 block height is at least 30 within 200 seconds diff --git a/polkadot/zombienet_tests/functional/0012-enable-node-feature.js b/polkadot/zombienet_tests/functional/0012-enable-node-feature.js new file mode 100644 index 00000000000..4822e1f6644 --- /dev/null +++ b/polkadot/zombienet_tests/functional/0012-enable-node-feature.js @@ -0,0 +1,37 @@ +async function run(nodeName, networkInfo, index) { + const { wsUri, userDefinedTypes } = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + await zombie.util.cryptoWaitReady(); + + // account to submit tx + const keyring = new zombie.Keyring({ type: "sr25519" }); + const alice = keyring.addFromUri("//Alice"); + + await new Promise(async (resolve, reject) => { + const unsub = await api.tx.sudo + .sudo(api.tx.configuration.setNodeFeature(Number(index), true)) + .signAndSend(alice, ({ status, isError }) => { + if (status.isInBlock) { + console.log( + `Transaction included at blockhash ${status.asInBlock}`, + ); + } else if (status.isFinalized) { + console.log( + `Transaction finalized at blockHash ${status.asFinalized}`, + ); + unsub(); + return resolve(); + } else if (isError) { + console.log(`Transaction error`); + reject(`Transaction error`); + } + }); + }); + + + + return 0; +} + +module.exports = { run }; diff --git a/polkadot/zombienet_tests/functional/0012-register-para.js b/polkadot/zombienet_tests/functional/0012-register-para.js new file mode 100644 index 00000000000..25c7e4f5ffd --- /dev/null +++ b/polkadot/zombienet_tests/functional/0012-register-para.js @@ -0,0 +1,37 @@ +async function run(nodeName, networkInfo, _jsArgs) { + const { wsUri, userDefinedTypes } = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + await zombie.util.cryptoWaitReady(); + + // account to submit tx + const keyring = new zombie.Keyring({ type: "sr25519" }); + const alice = keyring.addFromUri("//Alice"); + + await new Promise(async (resolve, reject) => { + const unsub = await api.tx.sudo + .sudo(api.tx.coretime.assignCore(0, 35, [[{ task: 2000 }, 57600]], null)) + .signAndSend(alice, ({ status, isError }) => { + if (status.isInBlock) { + console.log( + `Transaction included at blockhash ${status.asInBlock}`, + ); + } else if (status.isFinalized) { + console.log( + `Transaction finalized at blockHash ${status.asFinalized}`, + ); + unsub(); + return resolve(); + } else if (isError) { + console.log(`Transaction error`); + reject(`Transaction error`); + } + }); + }); + + + + return 0; +} + +module.exports = { run }; diff --git a/prdoc/pr_3231.prdoc b/prdoc/pr_3231.prdoc new file mode 100644 index 00000000000..26e96d3635b --- /dev/null +++ b/prdoc/pr_3231.prdoc @@ -0,0 +1,11 @@ +title: Allow parachain which acquires multiple coretime cores to make progress + +doc: + - audience: Node Operator + description: | + Adds the needed changes so that parachains which acquire multiple coretime cores can still make progress. + Only one of the cores will be able to be occupied at a time. + Only works if the ElasticScalingMVP node feature is enabled in the runtime and the block author validator is + updated to include this change. + +crates: [ ] -- GitLab From de6d02591b57d03f70ed8db0c674f045ad2ea029 Mon Sep 17 00:00:00 2001 From: tmpolaczyk <44604217+tmpolaczyk@users.noreply.github.com> Date: Sat, 24 Feb 2024 11:34:05 +0100 Subject: [PATCH 023/188] Use generic hash for runtime wasm in resolve_state_version_from_wasm (#3447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes the runtime hash algorithm used in `resolve_state_version_from_wasm` from `DefaultHasher` to a caller-provided one (usually `HashingFor`), to match the one used elsewhere. This fixes an issue where the runtime wasm is compiled 3 times when starting the `tanssi-node` with `--dev`. With this fix, the runtime wasm is only compiled 2 times. The other redundant compilation is caused by the `GenesisConfigBuilderRuntimeCaller` struct, which ignores the runtime cache. --------- Co-authored-by: Bastian Köcher --- prdoc/pr_3447.prdoc | 13 +++++++++++++ .../client/chain-spec/src/genesis_block.rs | 18 ++++++++---------- substrate/client/service/src/client/client.rs | 6 ++++-- 3 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 prdoc/pr_3447.prdoc diff --git a/prdoc/pr_3447.prdoc b/prdoc/pr_3447.prdoc new file mode 100644 index 00000000000..1d8d4f409f7 --- /dev/null +++ b/prdoc/pr_3447.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Use generic hash for runtime wasm in resolve_state_version_from_wasm + +doc: + - audience: Node Dev + description: | + Changes the runtime hash algorithm used in resolve_state_version_from_wasm from DefaultHasher to a caller-provided + one (usually HashingFor). Fixes a bug where the runtime wasm was being compiled again when it was not + needed, because the hash did not match +crates: + - name: sc-chain-spec diff --git a/substrate/client/chain-spec/src/genesis_block.rs b/substrate/client/chain-spec/src/genesis_block.rs index 6aa156a620a..3c7b9f64dcd 100644 --- a/substrate/client/chain-spec/src/genesis_block.rs +++ b/substrate/client/chain-spec/src/genesis_block.rs @@ -18,23 +18,25 @@ //! Tool for creating the genesis block. -use std::{collections::hash_map::DefaultHasher, marker::PhantomData, sync::Arc}; +use std::{marker::PhantomData, sync::Arc}; +use codec::Encode; use sc_client_api::{backend::Backend, BlockImportOperation}; use sc_executor::RuntimeVersionOf; use sp_core::storage::{well_known_keys, StateVersion, Storage}; use sp_runtime::{ - traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero}, + traits::{Block as BlockT, Hash as HashT, HashingFor, Header as HeaderT, Zero}, BuildStorage, }; /// Return the state version given the genesis storage and executor. -pub fn resolve_state_version_from_wasm( +pub fn resolve_state_version_from_wasm( storage: &Storage, executor: &E, ) -> sp_blockchain::Result where E: RuntimeVersionOf, + H: HashT, { if let Some(wasm) = storage.top.get(well_known_keys::CODE) { let mut ext = sp_state_machine::BasicExternalities::new_empty(); // just to read runtime version. @@ -43,12 +45,7 @@ where let runtime_code = sp_core::traits::RuntimeCode { code_fetcher: &code_fetcher, heap_pages: None, - hash: { - use std::hash::{Hash, Hasher}; - let mut state = DefaultHasher::new(); - wasm.hash(&mut state); - state.finish().to_le_bytes().to_vec() - }, + hash: ::hash(wasm).encode(), }; let runtime_version = RuntimeVersionOf::runtime_version(executor, &mut ext, &runtime_code) .map_err(|e| sp_blockchain::Error::VersionInvalid(e.to_string()))?; @@ -129,7 +126,8 @@ impl, E: RuntimeVersionOf> BuildGenesisBlock sp_blockchain::Result<(Block, Self::BlockImportOperation)> { let Self { genesis_storage, commit_genesis_state, backend, executor, _phantom } = self; - let genesis_state_version = resolve_state_version_from_wasm(&genesis_storage, &executor)?; + let genesis_state_version = + resolve_state_version_from_wasm::<_, HashingFor>(&genesis_storage, &executor)?; let mut op = backend.begin_operation()?; let state_root = op.set_genesis_state(genesis_storage, commit_genesis_state, genesis_state_version)?; diff --git a/substrate/client/service/src/client/client.rs b/substrate/client/service/src/client/client.rs index aa9c1b80a29..108c258595a 100644 --- a/substrate/client/service/src/client/client.rs +++ b/substrate/client/service/src/client/client.rs @@ -675,8 +675,10 @@ where // This is use by fast sync for runtime version to be resolvable from // changes. - let state_version = - resolve_state_version_from_wasm(&storage, &self.executor)?; + let state_version = resolve_state_version_from_wasm::<_, HashingFor>( + &storage, + &self.executor, + )?; let state_root = operation.op.reset_storage(storage, state_version)?; if state_root != *import_headers.post().state_root() { // State root mismatch when importing state. This should not happen in -- GitLab From ce5de99540eb1ceaed4b0a5d085983c4a273fdda Mon Sep 17 00:00:00 2001 From: eskimor Date: Mon, 26 Feb 2024 07:23:28 +0100 Subject: [PATCH 024/188] Remove redundant parachains assigner pallet. (#3457) from Westend and Rococo. --------- Co-authored-by: eskimor Co-authored-by: command-bot <> --- polkadot/runtime/rococo/src/lib.rs | 8 ++------ polkadot/runtime/westend/src/lib.rs | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 03e96ab388b..1566911fc22 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -46,9 +46,8 @@ use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*}; use runtime_parachains::{ assigner_coretime as parachains_assigner_coretime, - assigner_on_demand as parachains_assigner_on_demand, - assigner_parachains as parachains_assigner_parachains, - configuration as parachains_configuration, coretime, disputes as parachains_disputes, + assigner_on_demand as parachains_assigner_on_demand, configuration as parachains_configuration, + coretime, disputes as parachains_disputes, disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, inclusion::{AggregateMessageOrigin, UmpQueueId}, @@ -1038,8 +1037,6 @@ impl parachains_assigner_on_demand::Config for Runtime { type WeightInfo = weights::runtime_parachains_assigner_on_demand::WeightInfo; } -impl parachains_assigner_parachains::Config for Runtime {} - impl parachains_assigner_coretime::Config for Runtime {} impl parachains_initializer::Config for Runtime { @@ -1401,7 +1398,6 @@ construct_runtime! { ParasSlashing: parachains_slashing = 63, MessageQueue: pallet_message_queue = 64, OnDemandAssignmentProvider: parachains_assigner_on_demand = 66, - ParachainsAssignmentProvider: parachains_assigner_parachains = 67, CoretimeAssignmentProvider: parachains_assigner_coretime = 68, // Parachain Onboarding Pallets. Start indices at 70 to leave room. diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index bbb010f60bf..b0b70bff8de 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -68,9 +68,8 @@ use runtime_common::{ }; use runtime_parachains::{ assigner_coretime as parachains_assigner_coretime, - assigner_on_demand as parachains_assigner_on_demand, - assigner_parachains as parachains_assigner_parachains, - configuration as parachains_configuration, coretime, disputes as parachains_disputes, + assigner_on_demand as parachains_assigner_on_demand, configuration as parachains_configuration, + coretime, disputes as parachains_disputes, disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, inclusion::{AggregateMessageOrigin, UmpQueueId}, @@ -1243,8 +1242,6 @@ impl parachains_assigner_on_demand::Config for Runtime { type WeightInfo = weights::runtime_parachains_assigner_on_demand::WeightInfo; } -impl parachains_assigner_parachains::Config for Runtime {} - impl parachains_assigner_coretime::Config for Runtime {} impl parachains_initializer::Config for Runtime { @@ -1505,7 +1502,6 @@ construct_runtime! { ParaSessionInfo: parachains_session_info = 52, ParasDisputes: parachains_disputes = 53, ParasSlashing: parachains_slashing = 54, - ParachainsAssignmentProvider: parachains_assigner_parachains = 55, OnDemandAssignmentProvider: parachains_assigner_on_demand = 56, CoretimeAssignmentProvider: parachains_assigner_coretime = 57, -- GitLab From b9c792a4b8adb4617cafe7e0b8949b88f5a9d247 Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Date: Mon, 26 Feb 2024 10:06:21 +0200 Subject: [PATCH 025/188] Add more debug logs to understand if statement-distribution misbehaving (#3419) Add more debug logs to understand if statement-distribution is in a bad state, should be useful for debugging https://github.com/paritytech/polkadot-sdk/issues/3314 on production networks. Additionally, increase the number of parallel requests should make, since I notice that requests take around 100ms on kusama, and the 5 parallel request was picked mostly random, no reason why we can do more than that. --------- Signed-off-by: Alexandru Gheorghe Co-authored-by: ordian --- .../statement-distribution/src/v2/cluster.rs | 25 ++++++++++++++++++- .../statement-distribution/src/v2/mod.rs | 17 ++++++++++++- .../statement-distribution/src/v2/requests.rs | 14 ++++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/polkadot/node/network/statement-distribution/src/v2/cluster.rs b/polkadot/node/network/statement-distribution/src/v2/cluster.rs index 619114de967..c09916e5620 100644 --- a/polkadot/node/network/statement-distribution/src/v2/cluster.rs +++ b/polkadot/node/network/statement-distribution/src/v2/cluster.rs @@ -55,8 +55,9 @@ //! and to keep track of what we have sent to other validators in the group and what we may //! continue to send them. -use polkadot_primitives::{CandidateHash, CompactStatement, ValidatorIndex}; +use polkadot_primitives::{CandidateHash, CompactStatement, Hash, ValidatorIndex}; +use crate::LOG_TARGET; use std::collections::{HashMap, HashSet}; #[derive(Hash, PartialEq, Eq)] @@ -424,6 +425,28 @@ impl ClusterTracker { fn is_in_group(&self, validator: ValidatorIndex) -> bool { self.validators.contains(&validator) } + + /// Dumps pending statement for this cluster. + /// + /// Normally we should not have pending statements to validators in our cluster, + /// but if we do for all validators in our cluster, then we don't participate + /// in backing. Ocasional pending statements are expected if two authorities + /// can't detect each otehr or after restart, where it takes a while to discover + /// the whole network. + + pub fn warn_if_too_many_pending_statements(&self, parent_hash: Hash) { + if self.pending.iter().filter(|pending| !pending.1.is_empty()).count() >= + self.validators.len() + { + gum::warn!( + target: LOG_TARGET, + pending_statements = ?self.pending, + ?parent_hash, + "Cluster has too many pending statements, something wrong with our connection to our group peers \n + Restart might be needed if validator gets 0 backing rewards for more than 3-4 consecutive sessions" + ); + } + } } /// Incoming statement was accepted. diff --git a/polkadot/node/network/statement-distribution/src/v2/mod.rs b/polkadot/node/network/statement-distribution/src/v2/mod.rs index dc29c19a48e..2c9cdba4ea8 100644 --- a/polkadot/node/network/statement-distribution/src/v2/mod.rs +++ b/polkadot/node/network/statement-distribution/src/v2/mod.rs @@ -251,6 +251,13 @@ impl PerSessionState { if local_index.is_some() { self.local_validator.get_or_insert(LocalValidatorIndex::Inactive); } + + gum::info!( + target: LOG_TARGET, + index_in_gossip_topology = ?local_index, + index_in_parachain_authorities = ?self.local_validator, + "Node uses the following topology indices" + ); } /// Returns `true` if local is neither active or inactive validator node. @@ -768,7 +775,15 @@ pub(crate) fn handle_deactivate_leaves(state: &mut State, leaves: &[Hash]) { let pruned = state.implicit_view.deactivate_leaf(*leaf); for pruned_rp in pruned { // clean up per-relay-parent data based on everything removed. - state.per_relay_parent.remove(&pruned_rp); + state + .per_relay_parent + .remove(&pruned_rp) + .as_ref() + .and_then(|pruned| pruned.active_validator_state()) + .map(|active_state| { + active_state.cluster_tracker.warn_if_too_many_pending_statements(pruned_rp) + }); + // clean up requests related to this relay parent. state.request_manager.remove_by_relay_parent(*leaf); } diff --git a/polkadot/node/network/statement-distribution/src/v2/requests.rs b/polkadot/node/network/statement-distribution/src/v2/requests.rs index bed3d5c18ae..bbcb268415e 100644 --- a/polkadot/node/network/statement-distribution/src/v2/requests.rs +++ b/polkadot/node/network/statement-distribution/src/v2/requests.rs @@ -315,7 +315,16 @@ impl RequestManager { request_props: impl Fn(&CandidateIdentifier) -> Option, peer_advertised: impl Fn(&CandidateIdentifier, &PeerId) -> Option, ) -> Option> { - if response_manager.len() >= MAX_PARALLEL_ATTESTED_CANDIDATE_REQUESTS as usize { + // The number of parallel requests a node can answer is limited by + // `MAX_PARALLEL_ATTESTED_CANDIDATE_REQUESTS`, however there is no + // need for the current node to limit itself to the same amount the + // requests, because the requests are going to different nodes anyways. + // While looking at https://github.com/paritytech/polkadot-sdk/issues/3314, + // found out that this requests take around 100ms to fullfill, so it + // would make sense to try to request things as early as we can, given + // we would need to request it for each candidate, around 25 right now + // on kusama. + if response_manager.len() >= 2 * MAX_PARALLEL_ATTESTED_CANDIDATE_REQUESTS as usize { return None } @@ -1027,6 +1036,7 @@ mod tests { let peer_advertised = |_identifier: &CandidateIdentifier, _peer: &_| { Some(StatementFilter::full(group_size)) }; + let outgoing = request_manager .next_request(&mut response_manager, request_props, peer_advertised) .unwrap(); @@ -1148,6 +1158,7 @@ mod tests { { let request_props = |_identifier: &CandidateIdentifier| Some((&request_properties).clone()); + let outgoing = request_manager .next_request(&mut response_manager, request_props, peer_advertised) .unwrap(); @@ -1230,6 +1241,7 @@ mod tests { { let request_props = |_identifier: &CandidateIdentifier| Some((&request_properties).clone()); + let outgoing = request_manager .next_request(&mut response_manager, request_props, peer_advertised) .unwrap(); -- GitLab From 3d9439f64652e60d1dee85ca98fd865775d9ca45 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 26 Feb 2024 09:12:28 +0100 Subject: [PATCH 026/188] [pallet-xcm] Adjust benchmarks (teleport_assets/reserve_transfer_assets) not relying on ED (#3464) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem During the bumping of the `polkadot-fellows` repository to `polkadot-sdk@1.6.0`, I encountered a situation where the benchmarks `teleport_assets` and `reserve_transfer_assets` in AssetHubKusama started to fail. This issue arose due to a decreased ED balance for AssetHubs introduced [here](https://github.com/polkadot-fellows/runtimes/pull/158/files#diff-80668ff8e793b64f36a9a3ec512df5cbca4ad448c157a5d81abda1b15f35f1daR213), and also because of a [missing CI pipeline](https://github.com/polkadot-fellows/runtimes/issues/197) to check the benchmarks, which went unnoticed. These benchmarks expect the `caller` to have enough: 1. balance to transfer (BTT) 2. balance for paying delivery (BFPD). So the initial balance was calculated as `ED * 100`, which seems reasonable: ``` const ED_MULTIPLIER: u32 = 100; let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into());` ``` The problem arises when the price for delivery is 100 times higher than the existential deposit. In other words, when `ED * 100` does not cover `BTT` + `BFPD`. I check AHR/AHW/AHK/AHP and this problem has only AssetHubKusama ``` ED: 3333333 calculated price to parent delivery: 1031666634 (from xcm logs from the benchmark) --- 3333333 * 100 - BTT(3333333) - BFPD(1031666634) = −701666667 ``` which results in the error; ``` 2024-02-23 09:19:42 Unable to charge fee with error Module(ModuleError { index: 31, error: [17, 0, 0, 0], message: Some("FeesNotMet") }) Error: Input("Benchmark pallet_xcm::reserve_transfer_assets failed: FeesNotMet") ``` ## Solution The benchmarks `teleport_assets` and `reserve_transfer_assets` were fixed by removing `ED * 100` and replacing it with `DeliveryHelper` logic, which calculates the (almost real) price for delivery and sets it along with the existential deposit as the initial balance for the account used in the benchmark. ## TODO - [ ] patch for 1.6 - https://github.com/paritytech/polkadot-sdk/pull/3466 - [ ] patch for 1.7 - https://github.com/paritytech/polkadot-sdk/pull/3465 - [ ] patch for 1.8 - TODO: PR --------- Co-authored-by: Francisco Aguirre --- Cargo.lock | 3 +- cumulus/pallets/parachain-system/Cargo.toml | 4 + cumulus/pallets/parachain-system/src/lib.rs | 9 +++ .../assets/asset-hub-rococo/src/lib.rs | 42 +++++++---- .../assets/asset-hub-westend/src/lib.rs | 42 +++++++---- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 8 +- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 8 +- .../collectives-westend/src/lib.rs | 15 +++- .../contracts/contracts-rococo/src/lib.rs | 23 +++++- .../coretime/coretime-rococo/src/lib.rs | 8 +- .../coretime/coretime-westend/src/lib.rs | 8 +- .../runtimes/people/people-rococo/src/lib.rs | 8 +- .../runtimes/people/people-westend/src/lib.rs | 8 +- cumulus/primitives/utility/Cargo.toml | 3 - cumulus/primitives/utility/src/lib.rs | 11 ++- polkadot/runtime/common/Cargo.toml | 4 - polkadot/runtime/common/src/xcm_sender.rs | 15 +++- polkadot/runtime/rococo/src/lib.rs | 28 +++++-- polkadot/runtime/westend/src/lib.rs | 46 ++++++++---- polkadot/runtime/westend/src/xcm_config.rs | 2 +- polkadot/xcm/pallet-xcm-benchmarks/src/lib.rs | 32 +------- polkadot/xcm/pallet-xcm/src/benchmarking.rs | 73 ++++++++++++------- polkadot/xcm/pallet-xcm/src/mock.rs | 22 ++++++ .../xcm/xcm-builder/src/currency_adapter.rs | 2 +- .../xcm/xcm-builder/src/fungible_adapter.rs | 2 +- .../xcm/xcm-builder/src/fungibles_adapter.rs | 2 +- polkadot/xcm/xcm-builder/src/lib.rs | 2 +- polkadot/xcm/xcm-builder/src/routing.rs | 35 +++++++++ 28 files changed, 329 insertions(+), 136 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a23be53b34f..fae9eacdab9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3874,6 +3874,7 @@ dependencies = [ "pallet-message-queue", "parity-scale-codec", "polkadot-parachain-primitives", + "polkadot-runtime-common", "polkadot-runtime-parachains", "rand", "sc-client-api", @@ -4086,7 +4087,6 @@ dependencies = [ "frame-support", "log", "pallet-asset-conversion", - "pallet-xcm-benchmarks", "parity-scale-codec", "polkadot-runtime-common", "polkadot-runtime-parachains", @@ -13277,7 +13277,6 @@ dependencies = [ "pallet-transaction-payment", "pallet-treasury", "pallet-vesting", - "pallet-xcm-benchmarks", "parity-scale-codec", "polkadot-primitives", "polkadot-primitives-test-helpers", diff --git a/cumulus/pallets/parachain-system/Cargo.toml b/cumulus/pallets/parachain-system/Cargo.toml index 86647290563..7e0442f0b58 100644 --- a/cumulus/pallets/parachain-system/Cargo.toml +++ b/cumulus/pallets/parachain-system/Cargo.toml @@ -36,6 +36,7 @@ sp-version = { path = "../../../substrate/primitives/version", default-features # Polkadot polkadot-parachain-primitives = { path = "../../../polkadot/parachain", default-features = false, features = ["wasm-api"] } polkadot-runtime-parachains = { path = "../../../polkadot/runtime/parachains", default-features = false } +polkadot-runtime-common = { path = "../../../polkadot/runtime/common", default-features = false, optional = true } xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false } # Cumulus @@ -79,6 +80,7 @@ std = [ "log/std", "pallet-message-queue/std", "polkadot-parachain-primitives/std", + "polkadot-runtime-common/std", "polkadot-runtime-parachains/std", "scale-info/std", "sp-core/std", @@ -102,6 +104,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", + "polkadot-runtime-common/runtime-benchmarks", "polkadot-runtime-parachains/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] @@ -110,6 +113,7 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-message-queue/try-runtime", + "polkadot-runtime-common?/try-runtime", "polkadot-runtime-parachains/try-runtime", "sp-runtime/try-runtime", ] diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index 5a0fa57fb17..d86a67e58f4 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -1610,6 +1610,15 @@ impl UpwardMessageSender for Pallet { } } +#[cfg(feature = "runtime-benchmarks")] +impl polkadot_runtime_common::xcm_sender::EnsureForParachain for Pallet { + fn ensure(para_id: ParaId) { + if let ChannelStatus::Closed = Self::get_channel_status(para_id) { + Self::open_outbound_hrmp_channel_for_benchmarks_or_tests(para_id) + } + } +} + /// Something that can check the inherents of a block. #[cfg_attr( feature = "parameterized-consensus-hook", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 7e550c32917..81bb66a56a2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1355,8 +1355,31 @@ impl_runtime_apis! { Config as XcmBridgeHubRouterConfig, }; + parameter_types! { + pub ExistentialDepositAsset: Option = Some(( + TokenLocation::get(), + ExistentialDeposit::get() + ).into()); + pub const RandomParaId: ParaId = ParaId::new(43211234); + } + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = ( + cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >, + polkadot_runtime_common::xcm_sender::ToParachainDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + PriceForSiblingParachainDelivery, + RandomParaId, + ParachainSystem, + > + ); + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -1365,7 +1388,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between AH and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), @@ -1373,17 +1396,13 @@ impl_runtime_apis! { } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { - // AH can reserve transfer native token to some random parachain. - let random_para_id = 43211234; - ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( - random_para_id.into() - ); Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, - ParentThen(Parachain(random_para_id).into()).into(), + // AH can reserve transfer native token to some random parachain. + ParentThen(Parachain(RandomParaId::get().into()).into()).into(), )) } @@ -1469,13 +1488,6 @@ impl_runtime_apis! { use xcm_config::{TokenLocation, MaxAssetsIntoHolding}; use pallet_xcm_benchmarks::asset_instance_from; - parameter_types! { - pub ExistentialDepositAsset: Option = Some(( - TokenLocation::get(), - ExistentialDeposit::get() - ).into()); - } - impl pallet_xcm_benchmarks::Config for Runtime { type XcmConfig = xcm_config::XcmConfig; type AccountIdConverter = xcm_config::LocationToAccountId; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index a3166106073..3f58c679eee 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1427,8 +1427,31 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + parameter_types! { + pub ExistentialDepositAsset: Option = Some(( + WestendLocation::get(), + ExistentialDeposit::get() + ).into()); + pub const RandomParaId: ParaId = ParaId::new(43211234); + } + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = ( + cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >, + polkadot_runtime_common::xcm_sender::ToParachainDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + PriceForSiblingParachainDelivery, + RandomParaId, + ParachainSystem, + > + ); + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -1437,7 +1460,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between AH and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), @@ -1445,17 +1468,13 @@ impl_runtime_apis! { } fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { - // AH can reserve transfer native token to some random parachain. - let random_para_id = 43211234; - ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( - random_para_id.into() - ); Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, - ParentThen(Parachain(random_para_id).into()).into(), + // AH can reserve transfer native token to some random parachain. + ParentThen(Parachain(RandomParaId::get().into()).into()).into(), )) } @@ -1546,13 +1565,6 @@ impl_runtime_apis! { use xcm_config::{MaxAssetsIntoHolding, WestendLocation}; use pallet_xcm_benchmarks::asset_instance_from; - parameter_types! { - pub ExistentialDepositAsset: Option = Some(( - WestendLocation::get(), - ExistentialDeposit::get() - ).into()); - } - impl pallet_xcm_benchmarks::Config for Runtime { type XcmConfig = xcm_config::XcmConfig; type AccountIdConverter = xcm_config::LocationToAccountId; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index ae50d2a93cb..15cf045a995 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -1109,6 +1109,12 @@ impl_runtime_apis! { use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -1117,7 +1123,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between BH and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 997320ffcf2..bd42a33370d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -806,6 +806,12 @@ impl_runtime_apis! { use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -814,7 +820,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between BH and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 4299e8bb3ec..36eb0e07f87 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -986,8 +986,21 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + parameter_types! { + pub ExistentialDepositAsset: Option = Some(( + xcm_config::WndLocation::get(), + ExistentialDeposit::get() + ).into()); + } + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -996,7 +1009,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between Collectives and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }.into(), Parent.into(), diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 94cb0e502e4..541978098ca 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -50,7 +50,7 @@ use frame_support::{ dispatch::DispatchClass, genesis_builder_helper::{build_config, create_default_config}, parameter_types, - traits::{ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8}, + traits::{ConstBool, ConstU16, ConstU32, ConstU64, ConstU8}, weights::{ConstantMultiplier, Weight}, PalletId, }; @@ -205,6 +205,10 @@ impl pallet_authorship::Config for Runtime { type EventHandler = (CollatorSelection,); } +parameter_types! { + pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; +} + impl pallet_balances::Config for Runtime { type MaxLocks = ConstU32<50>; /// The type for recording an account's balance. @@ -212,7 +216,7 @@ impl pallet_balances::Config for Runtime { /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; type DustRemoval = (); - type ExistentialDeposit = ConstU128; + type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = pallet_balances::weights::SubstrateWeight; type MaxReserves = ConstU32<50>; @@ -713,9 +717,22 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + parameter_types! { + pub ExistentialDepositAsset: Option = Some(( + xcm_config::RelayLocation::get(), + ExistentialDeposit::get() + ).into()); + } + use xcm::latest::prelude::*; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -724,7 +741,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between Contracts-System-Para and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index f07bac8b2ef..fcd7576b1e1 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -715,6 +715,12 @@ impl_runtime_apis! { use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -723,7 +729,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between AH and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 85d70d2f17b..80eb7863803 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -706,6 +706,12 @@ impl_runtime_apis! { use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -714,7 +720,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between AH and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 570dc0fa12c..90c39891769 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -686,6 +686,12 @@ impl_runtime_apis! { use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -694,7 +700,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between People and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index a47df66f503..a904f7c3521 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -686,6 +686,12 @@ impl_runtime_apis! { use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn reachable_dest() -> Option { Some(Parent.into()) } @@ -694,7 +700,7 @@ impl_runtime_apis! { // Relay/native token can be teleported between People and Relay. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Parent.into()) }, Parent.into(), diff --git a/cumulus/primitives/utility/Cargo.toml b/cumulus/primitives/utility/Cargo.toml index 45c0e667094..1e2c300b9ba 100644 --- a/cumulus/primitives/utility/Cargo.toml +++ b/cumulus/primitives/utility/Cargo.toml @@ -26,7 +26,6 @@ polkadot-runtime-parachains = { path = "../../../polkadot/runtime/parachains", d xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../../polkadot/xcm/xcm-executor", default-features = false } xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/xcm-builder", default-features = false } -pallet-xcm-benchmarks = { path = "../../../polkadot/xcm/pallet-xcm-benchmarks", default-features = false } # Cumulus cumulus-primitives-core = { path = "../core", default-features = false } @@ -39,7 +38,6 @@ std = [ "frame-support/std", "log/std", "pallet-asset-conversion/std", - "pallet-xcm-benchmarks/std", "polkadot-runtime-common/std", "polkadot-runtime-parachains/std", "sp-io/std", @@ -54,7 +52,6 @@ runtime-benchmarks = [ "cumulus-primitives-core/runtime-benchmarks", "frame-support/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", - "pallet-xcm-benchmarks/runtime-benchmarks", "polkadot-runtime-common/runtime-benchmarks", "polkadot-runtime-parachains/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/cumulus/primitives/utility/src/lib.rs b/cumulus/primitives/utility/src/lib.rs index 0d892122742..abc391bdcb8 100644 --- a/cumulus/primitives/utility/src/lib.rs +++ b/cumulus/primitives/utility/src/lib.rs @@ -760,7 +760,7 @@ mod test_trader { } } -/// Implementation of `pallet_xcm_benchmarks::EnsureDelivery` which helps to ensure delivery to the +/// Implementation of `xcm_builder::EnsureDelivery` which helps to ensure delivery to the /// parent relay chain. Deposits existential deposit for origin (if needed). /// Deposits estimated fee to the origin account (if needed). /// Allows to trigger additional logic for specific `ParaId` (e.g. open HRMP channel) (if neeeded). @@ -774,17 +774,22 @@ impl< XcmConfig: xcm_executor::Config, ExistentialDeposit: Get>, PriceForDelivery: PriceForMessageDelivery, - > pallet_xcm_benchmarks::EnsureDelivery + > xcm_builder::EnsureDelivery for ToParentDeliveryHelper { fn ensure_successful_delivery( origin_ref: &Location, - _dest: &Location, + dest: &Location, fee_reason: xcm_executor::traits::FeeReason, ) -> (Option, Option) { use xcm::latest::{MAX_INSTRUCTIONS_TO_DECODE, MAX_ITEMS_IN_ASSETS}; use xcm_executor::{traits::FeeManager, FeesMode}; + // check if the destination is relay/parent + if dest.ne(&Location::parent()) { + return (None, None); + } + let mut fees_mode = None; if !XcmConfig::FeeManager::is_waived(Some(origin_ref), fee_reason) { // if not waived, we need to set up accounts for paying and receiving fees diff --git a/polkadot/runtime/common/Cargo.toml b/polkadot/runtime/common/Cargo.toml index 2467d123f02..eae5d4fb2ef 100644 --- a/polkadot/runtime/common/Cargo.toml +++ b/polkadot/runtime/common/Cargo.toml @@ -58,8 +58,6 @@ runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parac slot-range-helper = { path = "slot_range_helper", default-features = false } xcm = { package = "staging-xcm", path = "../../xcm", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../xcm/xcm-executor", default-features = false, optional = true } - -pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-features = false, optional = true } xcm-builder = { package = "staging-xcm-builder", path = "../../xcm/xcm-builder", default-features = false } [dev-dependencies] @@ -99,7 +97,6 @@ std = [ "pallet-transaction-payment/std", "pallet-treasury/std", "pallet-vesting/std", - "pallet-xcm-benchmarks/std", "parity-scale-codec/std", "primitives/std", "runtime-parachains/std", @@ -137,7 +134,6 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", - "pallet-xcm-benchmarks/runtime-benchmarks", "primitives/runtime-benchmarks", "runtime-parachains/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/polkadot/runtime/common/src/xcm_sender.rs b/polkadot/runtime/common/src/xcm_sender.rs index 7f1100a1361..46d09afcfb2 100644 --- a/polkadot/runtime/common/src/xcm_sender.rs +++ b/polkadot/runtime/common/src/xcm_sender.rs @@ -136,7 +136,7 @@ where } } -/// Implementation of `pallet_xcm_benchmarks::EnsureDelivery` which helps to ensure delivery to the +/// Implementation of `xcm_builder::EnsureDelivery` which helps to ensure delivery to the /// `ParaId` parachain (sibling or child). Deposits existential deposit for origin (if needed). /// Deposits estimated fee to the origin account (if needed). /// Allows to trigger additional logic for specific `ParaId` (e.g. open HRMP channel) (if neeeded). @@ -164,7 +164,7 @@ impl< PriceForDelivery: PriceForMessageDelivery, Parachain: Get, ToParachainHelper: EnsureForParachain, - > pallet_xcm_benchmarks::EnsureDelivery + > xcm_builder::EnsureDelivery for ToParachainDeliveryHelper< XcmConfig, ExistentialDeposit, @@ -175,7 +175,7 @@ impl< { fn ensure_successful_delivery( origin_ref: &Location, - _dest: &Location, + dest: &Location, fee_reason: xcm_executor::traits::FeeReason, ) -> (Option, Option) { use xcm_executor::{ @@ -183,6 +183,15 @@ impl< FeesMode, }; + // check if the destination matches the expected `Parachain`. + if let Some(Parachain(para_id)) = dest.first_interior() { + if ParaId::from(*para_id) != Parachain::get().into() { + return (None, None) + } + } else { + return (None, None) + } + let mut fees_mode = None; if !XcmConfig::FeeManager::is_waived(Some(origin_ref), fee_reason) { // if not waived, we need to set up accounts for paying and receiving fees diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 1566911fc22..bbc79a13d37 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -2272,12 +2272,30 @@ sp_api::impl_runtime_apis! { TokenLocation::get(), ExistentialDeposit::get() ).into()); - pub ToParachain: ParaId = rococo_runtime_constants::system_parachain::ASSET_HUB_ID.into(); + pub AssetHubParaId: ParaId = rococo_runtime_constants::system_parachain::ASSET_HUB_ID.into(); + pub const RandomParaId: ParaId = ParaId::new(43211234); } impl frame_system_benchmarking::Config for Runtime {} impl frame_benchmarking::baseline::Config for Runtime {} impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = ( + runtime_common::xcm_sender::ToParachainDeliveryHelper< + XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForChildParachainDelivery, + AssetHubParaId, + (), + >, + runtime_common::xcm_sender::ToParachainDeliveryHelper< + XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForChildParachainDelivery, + RandomParaId, + (), + > + ); + fn reachable_dest() -> Option { Some(crate::xcm_config::AssetHub::get()) } @@ -2286,7 +2304,7 @@ sp_api::impl_runtime_apis! { // Relay/native token can be teleported to/from AH. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Here.into()) }, crate::xcm_config::AssetHub::get(), @@ -2297,10 +2315,10 @@ sp_api::impl_runtime_apis! { // Relay can reserve transfer native token to some random parachain. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Here.into()) }, - Parachain(43211234).into(), + Parachain(RandomParaId::get().into()).into(), )) } @@ -2325,7 +2343,7 @@ sp_api::impl_runtime_apis! { XcmConfig, ExistentialDepositAsset, xcm_config::PriceForChildParachainDelivery, - ToParachain, + AssetHubParaId, (), >; fn valid_destination() -> Result { diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index b0b70bff8de..574710b3110 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -2344,7 +2344,36 @@ sp_api::impl_runtime_apis! { impl pallet_session_benchmarking::Config for Runtime {} impl pallet_offences_benchmarking::Config for Runtime {} impl pallet_election_provider_support_benchmarking::Config for Runtime {} + + use xcm_config::{AssetHub, TokenLocation}; + + parameter_types! { + pub ExistentialDepositAsset: Option = Some(( + TokenLocation::get(), + ExistentialDeposit::get() + ).into()); + pub AssetHubParaId: ParaId = westend_runtime_constants::system_parachain::ASSET_HUB_ID.into(); + pub const RandomParaId: ParaId = ParaId::new(43211234); + } + impl pallet_xcm::benchmarking::Config for Runtime { + type DeliveryHelper = ( + runtime_common::xcm_sender::ToParachainDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForChildParachainDelivery, + AssetHubParaId, + (), + >, + runtime_common::xcm_sender::ToParachainDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForChildParachainDelivery, + RandomParaId, + (), + > + ); + fn reachable_dest() -> Option { Some(crate::xcm_config::AssetHub::get()) } @@ -2352,7 +2381,7 @@ sp_api::impl_runtime_apis! { fn teleportable_asset_and_dest() -> Option<(Asset, Location)> { // Relay/native token can be teleported to/from AH. Some(( - Asset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: AssetId(Here.into()) }, + Asset { fun: Fungible(ExistentialDeposit::get()), id: AssetId(Here.into()) }, crate::xcm_config::AssetHub::get(), )) } @@ -2361,10 +2390,10 @@ sp_api::impl_runtime_apis! { // Relay can reserve transfer native token to some random parachain. Some(( Asset { - fun: Fungible(EXISTENTIAL_DEPOSIT), + fun: Fungible(ExistentialDeposit::get()), id: AssetId(Here.into()) }, - crate::Junction::Parachain(43211234).into(), + crate::Junction::Parachain(RandomParaId::get().into()).into(), )) } @@ -2391,15 +2420,6 @@ sp_api::impl_runtime_apis! { AssetId, Fungibility::*, InteriorLocation, Junction, Junctions::*, Asset, Assets, Location, NetworkId, Response, }; - use xcm_config::{AssetHub, TokenLocation}; - - parameter_types! { - pub ExistentialDepositAsset: Option = Some(( - TokenLocation::get(), - ExistentialDeposit::get() - ).into()); - pub ToParachain: ParaId = westend_runtime_constants::system_parachain::ASSET_HUB_ID.into(); - } impl pallet_xcm_benchmarks::Config for Runtime { type XcmConfig = xcm_config::XcmConfig; @@ -2408,7 +2428,7 @@ sp_api::impl_runtime_apis! { xcm_config::XcmConfig, ExistentialDepositAsset, xcm_config::PriceForChildParachainDelivery, - ToParachain, + AssetHubParaId, (), >; fn valid_destination() -> Result { diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 06124d896fb..66c56171af0 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -262,7 +262,7 @@ pub type LocalPalletOriginToLocation = ( StakingAdminToPlurality, // FellowshipAdmin origin to be used in XCM as a corresponding Plurality `Location` value. FellowshipAdminToPlurality, - // `Treasurer` origin to be used in XCM as a corresponding Plurality `MultiLocation` value. + // `Treasurer` origin to be used in XCM as a corresponding Plurality `Location` value. TreasurerToPlurality, ); diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/lib.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/lib.rs index 6ce8d3e99e8..63ed0ac0ca7 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/lib.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/lib.rs @@ -22,10 +22,8 @@ use codec::Encode; use frame_benchmarking::{account, BenchmarkError}; use sp_std::prelude::*; use xcm::latest::prelude::*; -use xcm_executor::{ - traits::{ConvertLocation, FeeReason}, - Config as XcmConfig, FeesMode, -}; +use xcm_builder::EnsureDelivery; +use xcm_executor::{traits::ConvertLocation, Config as XcmConfig}; pub mod fungible; pub mod generic; @@ -114,29 +112,3 @@ pub fn account_and_location(index: u32) -> (T::AccountId, Location) { (account, location) } - -/// Trait for a type which ensures all requirements for successful delivery with XCM transport -/// layers. -pub trait EnsureDelivery { - /// Prepare all requirements for successful `XcmSender: SendXcm` passing (accounts, balances, - /// channels ...). Returns: - /// - possible `FeesMode` which is expected to be set to executor - /// - possible `Assets` which are expected to be subsume to the Holding Register - fn ensure_successful_delivery( - origin_ref: &Location, - dest: &Location, - fee_reason: FeeReason, - ) -> (Option, Option); -} - -/// `()` implementation does nothing which means no special requirements for environment. -impl EnsureDelivery for () { - fn ensure_successful_delivery( - _origin_ref: &Location, - _dest: &Location, - _fee_reason: FeeReason, - ) -> (Option, Option) { - // doing nothing - (None, None) - } -} diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index c7d8fb24e9d..e3ea2fb8c06 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -17,21 +17,26 @@ use super::*; use bounded_collections::{ConstU32, WeakBoundedVec}; use frame_benchmarking::{benchmarks, whitelisted_caller, BenchmarkError, BenchmarkResult}; -use frame_support::{traits::Currency, weights::Weight}; +use frame_support::{ + traits::fungible::{Inspect, Mutate}, + weights::Weight, +}; use frame_system::RawOrigin; use sp_std::prelude::*; use xcm::{latest::prelude::*, v2}; +use xcm_builder::EnsureDelivery; +use xcm_executor::traits::FeeReason; type RuntimeOrigin = ::RuntimeOrigin; -// existential deposit multiplier -const ED_MULTIPLIER: u32 = 100; - /// Pallet we're benchmarking here. pub struct Pallet(crate::Pallet); /// Trait that must be implemented by runtime to be able to benchmark pallet properly. pub trait Config: crate::Config { + /// Helper that ensures successful delivery for extrinsics/benchmarks which need `SendXcm`. + type DeliveryHelper: EnsureDelivery; + /// A `Location` that can be reached via `XcmRouter`. Used only in benchmarks. /// /// If `None`, the benchmarks that depend on a reachable destination will be skipped. @@ -107,23 +112,29 @@ benchmarks! { }.into(); let assets: Assets = asset.into(); - let existential_deposit = T::ExistentialDeposit::get(); - let caller = whitelisted_caller(); - - // Give some multiple of the existential deposit - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - assert!(balance >= transferred_amount); - let _ = as Currency<_>>::make_free_balance_be(&caller, balance); - // verify initial balance - assert_eq!(pallet_balances::Pallet::::free_balance(&caller), balance); - + let caller: T::AccountId = whitelisted_caller(); let send_origin = RawOrigin::Signed(caller.clone()); let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into()) .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; - if !T::XcmTeleportFilter::contains(&(origin_location, assets.clone().into_inner())) { + if !T::XcmTeleportFilter::contains(&(origin_location.clone(), assets.clone().into_inner())) { return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) } + // Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...) + let (_, _) = T::DeliveryHelper::ensure_successful_delivery( + &origin_location, + &destination, + FeeReason::ChargeFees, + ); + + // Actual balance (e.g. `ensure_successful_delivery` could drip delivery fees, ...) + let balance = as Inspect<_>>::balance(&caller); + // Add transferred_amount to origin + as Mutate<_>>::mint_into(&caller, transferred_amount)?; + // verify initial balance + let balance = balance + transferred_amount; + assert_eq!( as Inspect<_>>::balance(&caller), balance); + let recipient = [0u8; 32]; let versioned_dest: VersionedLocation = destination.into(); let versioned_beneficiary: VersionedLocation = @@ -132,7 +143,7 @@ benchmarks! { }: _>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) verify { // verify balance after transfer, decreased by transferred amount (+ maybe XCM delivery fees) - assert!(pallet_balances::Pallet::::free_balance(&caller) <= balance - transferred_amount); + assert!( as Inspect<_>>::balance(&caller) <= balance - transferred_amount); } reserve_transfer_assets { @@ -146,23 +157,29 @@ benchmarks! { }.into(); let assets: Assets = asset.into(); - let existential_deposit = T::ExistentialDeposit::get(); - let caller = whitelisted_caller(); - - // Give some multiple of the existential deposit - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - assert!(balance >= transferred_amount); - let _ = as Currency<_>>::make_free_balance_be(&caller, balance); - // verify initial balance - assert_eq!(pallet_balances::Pallet::::free_balance(&caller), balance); - + let caller: T::AccountId = whitelisted_caller(); let send_origin = RawOrigin::Signed(caller.clone()); let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into()) .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; - if !T::XcmReserveTransferFilter::contains(&(origin_location, assets.clone().into_inner())) { + if !T::XcmReserveTransferFilter::contains(&(origin_location.clone(), assets.clone().into_inner())) { return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) } + // Ensure that origin can send to destination (e.g. setup delivery fees, ensure router setup, ...) + let (_, _) = T::DeliveryHelper::ensure_successful_delivery( + &origin_location, + &destination, + FeeReason::ChargeFees, + ); + + // Actual balance (e.g. `ensure_successful_delivery` could drip delivery fees, ...) + let balance = as Inspect<_>>::balance(&caller); + // Add transferred_amount to origin + as Mutate<_>>::mint_into(&caller, transferred_amount)?; + // verify initial balance + let balance = balance + transferred_amount; + assert_eq!( as Inspect<_>>::balance(&caller), balance); + let recipient = [0u8; 32]; let versioned_dest: VersionedLocation = destination.into(); let versioned_beneficiary: VersionedLocation = @@ -171,7 +188,7 @@ benchmarks! { }: _>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) verify { // verify balance after transfer, decreased by transferred amount (+ maybe XCM delivery fees) - assert!(pallet_balances::Pallet::::free_balance(&caller) <= balance - transferred_amount); + assert!( as Inspect<_>>::balance(&caller) <= balance - transferred_amount); } transfer_assets { diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 004a73ca6ab..17c181387dd 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -563,8 +563,30 @@ impl pallet_test_notifier::Config for Test { type RuntimeCall = RuntimeCall; } +#[cfg(feature = "runtime-benchmarks")] +pub struct TestDeliveryHelper; +#[cfg(feature = "runtime-benchmarks")] +impl xcm_builder::EnsureDelivery for TestDeliveryHelper { + fn ensure_successful_delivery( + origin_ref: &Location, + _dest: &Location, + _fee_reason: xcm_executor::traits::FeeReason, + ) -> (Option, Option) { + use xcm_executor::traits::ConvertLocation; + let account = SovereignAccountOf::convert_location(origin_ref).expect("Valid location"); + // Give the existential deposit at least + let balance = ExistentialDeposit::get(); + let _ = >::make_free_balance_be( + &account, balance, + ); + (None, None) + } +} + #[cfg(feature = "runtime-benchmarks")] impl super::benchmarking::Config for Test { + type DeliveryHelper = TestDeliveryHelper; + fn reachable_dest() -> Option { Some(Parachain(1000).into()) } diff --git a/polkadot/xcm/xcm-builder/src/currency_adapter.rs b/polkadot/xcm/xcm-builder/src/currency_adapter.rs index fe26b7319bb..24261ac0658 100644 --- a/polkadot/xcm/xcm-builder/src/currency_adapter.rs +++ b/polkadot/xcm/xcm-builder/src/currency_adapter.rs @@ -170,7 +170,7 @@ impl< } fn can_check_out(_dest: &Location, what: &Asset, _context: &XcmContext) -> Result { - log::trace!(target: "xcm::currency_adapter", "check_out dest: {:?}, what: {:?}", _dest, what); + log::trace!(target: "xcm::currency_adapter", "can_check_out dest: {:?}, what: {:?}", _dest, what); let amount = Matcher::matches_fungible(what).ok_or(Error::AssetNotHandled)?; match CheckedAccount::get() { Some((checked_account, MintLocation::Local)) => diff --git a/polkadot/xcm/xcm-builder/src/fungible_adapter.rs b/polkadot/xcm/xcm-builder/src/fungible_adapter.rs index 33b766c8560..21c828922b3 100644 --- a/polkadot/xcm/xcm-builder/src/fungible_adapter.rs +++ b/polkadot/xcm/xcm-builder/src/fungible_adapter.rs @@ -151,7 +151,7 @@ impl< fn can_check_out(_dest: &Location, what: &Asset, _context: &XcmContext) -> XcmResult { log::trace!( target: "xcm::fungible_adapter", - "check_out dest: {:?}, what: {:?}", + "can_check_out dest: {:?}, what: {:?}", _dest, what ); diff --git a/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs b/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs index 4574d5ed4c6..b4c418ebf1c 100644 --- a/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs +++ b/polkadot/xcm/xcm-builder/src/fungibles_adapter.rs @@ -235,7 +235,7 @@ impl< fn can_check_out(_origin: &Location, what: &Asset, _context: &XcmContext) -> XcmResult { log::trace!( target: "xcm::fungibles_adapter", - "can_check_in origin: {:?}, what: {:?}", + "can_check_out origin: {:?}, what: {:?}", _origin, what ); // Check we handle this asset. diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs index 42522c64d8a..e2af8187136 100644 --- a/polkadot/xcm/xcm-builder/src/lib.rs +++ b/polkadot/xcm/xcm-builder/src/lib.rs @@ -117,7 +117,7 @@ mod process_xcm_message; pub use process_xcm_message::ProcessXcmMessage; mod routing; -pub use routing::{WithTopicSource, WithUniqueTopic}; +pub use routing::{EnsureDelivery, WithTopicSource, WithUniqueTopic}; mod transactional; pub use transactional::FrameTransactionalProcessor; diff --git a/polkadot/xcm/xcm-builder/src/routing.rs b/polkadot/xcm/xcm-builder/src/routing.rs index 9c0302baee0..529ef80c15f 100644 --- a/polkadot/xcm/xcm-builder/src/routing.rs +++ b/polkadot/xcm/xcm-builder/src/routing.rs @@ -20,6 +20,7 @@ use frame_system::unique; use parity_scale_codec::Encode; use sp_std::{marker::PhantomData, result::Result}; use xcm::prelude::*; +use xcm_executor::{traits::FeeReason, FeesMode}; /// Wrapper router which, if the message does not already end with a `SetTopic` instruction, /// appends one to the message filled with a universally unique ID. This ID is returned from a @@ -104,3 +105,37 @@ impl SendXcm for WithTopicSource (Option, Option); +} + +/// Tuple implementation for `EnsureDelivery`. +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl EnsureDelivery for Tuple { + fn ensure_successful_delivery( + origin_ref: &Location, + dest: &Location, + fee_reason: FeeReason, + ) -> (Option, Option) { + for_tuples!( #( + // If the implementation returns something, we're done; if not, let others try. + match Tuple::ensure_successful_delivery(origin_ref, dest, fee_reason.clone()) { + r @ (Some(_), Some(_)) | r @ (Some(_), None) | r @ (None, Some(_)) => return r, + (None, None) => (), + } + )* ); + // doing nothing + (None, None) + } +} -- GitLab From 49266f102e5b5c07fbc3ef45db29c2fd053a0555 Mon Sep 17 00:00:00 2001 From: brenzi Date: Mon, 26 Feb 2024 09:15:44 +0100 Subject: [PATCH 027/188] add Encointer as trusted teleporter for Westend (#3411) with the deprecation of Rococo, Encointer needs a new staging environment. Paseo will be Polkadot-focused and westend Kusama-focused, so we propose to use Westend --- polkadot/runtime/westend/constants/src/lib.rs | 2 ++ polkadot/runtime/westend/src/xcm_config.rs | 3 +++ prdoc/pr_3411.prdoc | 11 +++++++++++ 3 files changed, 16 insertions(+) create mode 100644 prdoc/pr_3411.prdoc diff --git a/polkadot/runtime/westend/constants/src/lib.rs b/polkadot/runtime/westend/constants/src/lib.rs index 848cccd559d..3bc27177d7a 100644 --- a/polkadot/runtime/westend/constants/src/lib.rs +++ b/polkadot/runtime/westend/constants/src/lib.rs @@ -107,6 +107,8 @@ pub mod system_parachain { pub const COLLECTIVES_ID: u32 = 1001; /// BridgeHub parachain ID. pub const BRIDGE_HUB_ID: u32 = 1002; + /// Encointer parachain ID. + pub const ENCOINTER_ID: u32 = 1003; /// People Chain parachain ID. pub const PEOPLE_ID: u32 = 1004; /// Brokerage parachain ID. diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 66c56171af0..c3aa75a86a4 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -114,12 +114,14 @@ parameter_types! { pub AssetHub: Location = Parachain(ASSET_HUB_ID).into_location(); pub Collectives: Location = Parachain(COLLECTIVES_ID).into_location(); pub BridgeHub: Location = Parachain(BRIDGE_HUB_ID).into_location(); + pub Encointer: Location = Parachain(ENCOINTER_ID).into_location(); pub People: Location = Parachain(PEOPLE_ID).into_location(); pub Broker: Location = Parachain(BROKER_ID).into_location(); pub Wnd: AssetFilter = Wild(AllOf { fun: WildFungible, id: AssetId(TokenLocation::get()) }); pub WndForAssetHub: (AssetFilter, Location) = (Wnd::get(), AssetHub::get()); pub WndForCollectives: (AssetFilter, Location) = (Wnd::get(), Collectives::get()); pub WndForBridgeHub: (AssetFilter, Location) = (Wnd::get(), BridgeHub::get()); + pub WndForEncointer: (AssetFilter, Location) = (Wnd::get(), Encointer::get()); pub WndForPeople: (AssetFilter, Location) = (Wnd::get(), People::get()); pub WndForBroker: (AssetFilter, Location) = (Wnd::get(), Broker::get()); pub MaxInstructions: u32 = 100; @@ -130,6 +132,7 @@ pub type TrustedTeleporters = ( xcm_builder::Case, xcm_builder::Case, xcm_builder::Case, + xcm_builder::Case, xcm_builder::Case, xcm_builder::Case, ); diff --git a/prdoc/pr_3411.prdoc b/prdoc/pr_3411.prdoc new file mode 100644 index 00000000000..d847d6756ac --- /dev/null +++ b/prdoc/pr_3411.prdoc @@ -0,0 +1,11 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: add Encointer as trusted teleporter for Westend + +doc: + - audience: Runtime Dev + description: | + add Encointer as trusted teleporter for Westend with ParaId 1003 + +crates: [ ] -- GitLab From 0893ca1584a41ea632214dbcaf8ae134b990f9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 26 Feb 2024 11:32:35 +0100 Subject: [PATCH 028/188] frame-support: Improve error reporting when having too many pallets (#3478) Instead of only generating the error, we now generate the actual code and the error. This generates in total less errors and helps the user to identify the actual problem and not being confronted with tons of errors. --- .../procedural/src/construct_runtime/mod.rs | 43 ++++--- ...umber_of_pallets_exceeds_tuple_size.stderr | 106 ++++-------------- 2 files changed, 49 insertions(+), 100 deletions(-) diff --git a/substrate/frame/support/procedural/src/construct_runtime/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/mod.rs index 54ed15f7b1d..6e95fdf116a 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/mod.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/mod.rs @@ -233,25 +233,38 @@ pub fn construct_runtime(input: TokenStream) -> TokenStream { let input_copy = input.clone(); let definition = syn::parse_macro_input!(input as RuntimeDeclaration); - let res = match definition { - RuntimeDeclaration::Implicit(implicit_def) => - check_pallet_number(input_copy.clone().into(), implicit_def.pallets.len()).and_then( - |_| construct_runtime_implicit_to_explicit(input_copy.into(), implicit_def), - ), - RuntimeDeclaration::Explicit(explicit_decl) => check_pallet_number( - input_copy.clone().into(), - explicit_decl.pallets.len(), - ) - .and_then(|_| { - construct_runtime_explicit_to_explicit_expanded(input_copy.into(), explicit_decl) - }), - RuntimeDeclaration::ExplicitExpanded(explicit_decl) => - check_pallet_number(input_copy.into(), explicit_decl.pallets.len()) - .and_then(|_| construct_runtime_final_expansion(explicit_decl)), + let (check_pallet_number_res, res) = match definition { + RuntimeDeclaration::Implicit(implicit_def) => ( + check_pallet_number(input_copy.clone().into(), implicit_def.pallets.len()), + construct_runtime_implicit_to_explicit(input_copy.into(), implicit_def), + ), + RuntimeDeclaration::Explicit(explicit_decl) => ( + check_pallet_number(input_copy.clone().into(), explicit_decl.pallets.len()), + construct_runtime_explicit_to_explicit_expanded(input_copy.into(), explicit_decl), + ), + RuntimeDeclaration::ExplicitExpanded(explicit_decl) => ( + check_pallet_number(input_copy.into(), explicit_decl.pallets.len()), + construct_runtime_final_expansion(explicit_decl), + ), }; let res = res.unwrap_or_else(|e| e.to_compile_error()); + // We want to provide better error messages to the user and thus, handle the error here + // separately. If there is an error, we print the error and still generate all of the code to + // get in overall less errors for the user. + let res = if let Err(error) = check_pallet_number_res { + let error = error.to_compile_error(); + + quote! { + #error + + #res + } + } else { + res + }; + let res = expander::Expander::new("construct_runtime") .dry(std::env::var("EXPAND_MACROS").is_err()) .verbose(true) diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr index 3b6329c650f..6160f8234a3 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr @@ -4,88 +4,24 @@ error: The number of pallets exceeds the maximum number of tuple elements. To in 67 | pub struct Runtime | ^^^ -error[E0412]: cannot find type `RuntimeCall` in this scope - --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:35:64 - | -35 | pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; - | ^^^^^^^^^^^ not found in this scope - | -help: you might be missing a type parameter - | -35 | pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; - | +++++++++++++ - -error[E0412]: cannot find type `Runtime` in this scope - --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:37:25 - | -37 | impl pallet::Config for Runtime {} - | ^^^^^^^ not found in this scope - -error[E0412]: cannot find type `Runtime` in this scope - --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:40:31 - | -40 | impl frame_system::Config for Runtime { - | ^^^^^^^ not found in this scope - -error[E0412]: cannot find type `RuntimeOrigin` in this scope - --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:42:23 - | -42 | type RuntimeOrigin = RuntimeOrigin; - | ^^^^^^^^^^^^^ - | -help: you might have meant to use the associated type - | -42 | type RuntimeOrigin = Self::RuntimeOrigin; - | ++++++ - -error[E0412]: cannot find type `RuntimeCall` in this scope - --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:44:21 - | -44 | type RuntimeCall = RuntimeCall; - | ^^^^^^^^^^^ - | -help: you might have meant to use the associated type - | -44 | type RuntimeCall = Self::RuntimeCall; - | ++++++ - -error[E0412]: cannot find type `RuntimeEvent` in this scope - --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:50:22 - | -50 | type RuntimeEvent = RuntimeEvent; - | ^^^^^^^^^^^^ - | -help: you might have meant to use the associated type - | -50 | type RuntimeEvent = Self::RuntimeEvent; - | ++++++ - -error[E0412]: cannot find type `PalletInfo` in this scope - --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:56:20 - | -56 | type PalletInfo = PalletInfo; - | ^^^^^^^^^^ - | -help: you might have meant to use the associated type - | -56 | type PalletInfo = Self::PalletInfo; - | ++++++ -help: consider importing one of these items - | -18 + use frame_benchmarking::__private::traits::PalletInfo; - | -18 + use frame_support::traits::PalletInfo; - | - -error[E0412]: cannot find type `RuntimeTask` in this scope - --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:39:1 - | -39 | #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `frame_system::config_preludes::TestDefaultConfig` which comes from the expansion of the macro `frame_support::macro_magic::forward_tokens_verbatim` (in Nightly builds, run with -Z macro-backtrace for more info) -help: you might have meant to use the associated type - --> $WORKSPACE/substrate/frame/system/src/lib.rs - | - | type Self::RuntimeTask = (); - | ++++++ +error: recursion limit reached while expanding `frame_support::__private::tt_return!` + --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:22:1 + | +22 | / #[frame_support::pallet] +23 | | mod pallet { +24 | | #[pallet::config] +25 | | pub trait Config: frame_system::Config {} +... | +66 | |/ construct_runtime! { +67 | || pub struct Runtime +68 | || { +69 | || System: frame_system::{Pallet, Call, Storage, Config, Event}, +... || +180 | || } +181 | || } + | ||_^ + | |_| + | in this macro invocation + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`$CRATE`) + = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) -- GitLab From 6c5a42a690f96d59dbdf94640188f5d5b5cc47e2 Mon Sep 17 00:00:00 2001 From: Sebastian Kunert Date: Mon, 26 Feb 2024 12:45:30 +0100 Subject: [PATCH 029/188] Introduce Notification block pinning limit (#2935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While investigating some pruning issues I found some room for improvement in the notification pin handling. **Problem:** It was not possible to define an upper limit on notification pins. The block pinning cache has a limit, but only handles bodies and justifications. After this PR, bookkeeping for notifications is managed in the pinning worker. A limit can be defined in the worker. If that limit is crossed, blocks that were pinned for that notification are unpinned, which now affects the state as well as bodies and justifications. The pinned blocks cache still has a limit, but should never be hit. closes #19 --------- Co-authored-by: Bastian Köcher Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> --- Cargo.lock | 1 + substrate/client/api/src/client.rs | 27 +- substrate/client/db/src/lib.rs | 2 +- .../client/db/src/pinned_blocks_cache.rs | 2 +- substrate/client/service/Cargo.toml | 1 + substrate/client/service/src/client/client.rs | 53 +-- substrate/client/service/src/client/mod.rs | 1 + .../src/client/notification_pinning.rs | 353 ++++++++++++++++++ 8 files changed, 406 insertions(+), 34 deletions(-) create mode 100644 substrate/client/service/src/client/notification_pinning.rs diff --git a/Cargo.lock b/Cargo.lock index fae9eacdab9..410b45d0018 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16729,6 +16729,7 @@ dependencies = [ "sc-transaction-pool", "sc-transaction-pool-api", "sc-utils", + "schnellru", "serde", "serde_json", "sp-api", diff --git a/substrate/client/api/src/client.rs b/substrate/client/api/src/client.rs index 46232c74539..2de09840e4d 100644 --- a/substrate/client/api/src/client.rs +++ b/substrate/client/api/src/client.rs @@ -278,7 +278,7 @@ impl fmt::Display for UsageInfo { pub struct UnpinHandleInner { /// Hash of the block pinned by this handle hash: Block::Hash, - unpin_worker_sender: TracingUnboundedSender, + unpin_worker_sender: TracingUnboundedSender>, } impl Debug for UnpinHandleInner { @@ -291,7 +291,7 @@ impl UnpinHandleInner { /// Create a new [`UnpinHandleInner`] pub fn new( hash: Block::Hash, - unpin_worker_sender: TracingUnboundedSender, + unpin_worker_sender: TracingUnboundedSender>, ) -> Self { Self { hash, unpin_worker_sender } } @@ -299,12 +299,25 @@ impl UnpinHandleInner { impl Drop for UnpinHandleInner { fn drop(&mut self) { - if let Err(err) = self.unpin_worker_sender.unbounded_send(self.hash) { + if let Err(err) = + self.unpin_worker_sender.unbounded_send(UnpinWorkerMessage::Unpin(self.hash)) + { log::debug!(target: "db", "Unable to unpin block with hash: {}, error: {:?}", self.hash, err); }; } } +/// Message that signals notification-based pinning actions to the pinning-worker. +/// +/// When the notification is dropped, an `Unpin` message should be sent to the worker. +#[derive(Debug)] +pub enum UnpinWorkerMessage { + /// Should be sent when a import or finality notification is created. + AnnouncePin(Block::Hash), + /// Should be sent when a import or finality notification is dropped. + Unpin(Block::Hash), +} + /// Keeps a specific block pinned while the handle is alive. /// Once the last handle instance for a given block is dropped, the /// block is unpinned in the [`Backend`](crate::backend::Backend::unpin_block). @@ -315,7 +328,7 @@ impl UnpinHandle { /// Create a new [`UnpinHandle`] pub fn new( hash: Block::Hash, - unpin_worker_sender: TracingUnboundedSender, + unpin_worker_sender: TracingUnboundedSender>, ) -> UnpinHandle { UnpinHandle(Arc::new(UnpinHandleInner::new(hash, unpin_worker_sender))) } @@ -353,7 +366,7 @@ impl BlockImportNotification { header: Block::Header, is_new_best: bool, tree_route: Option>>, - unpin_worker_sender: TracingUnboundedSender, + unpin_worker_sender: TracingUnboundedSender>, ) -> Self { Self { hash, @@ -412,7 +425,7 @@ impl FinalityNotification { /// Create finality notification from finality summary. pub fn from_summary( mut summary: FinalizeSummary, - unpin_worker_sender: TracingUnboundedSender, + unpin_worker_sender: TracingUnboundedSender>, ) -> FinalityNotification { let hash = summary.finalized.pop().unwrap_or_default(); FinalityNotification { @@ -436,7 +449,7 @@ impl BlockImportNotification { /// Create finality notification from finality summary. pub fn from_summary( summary: ImportSummary, - unpin_worker_sender: TracingUnboundedSender, + unpin_worker_sender: TracingUnboundedSender>, ) -> BlockImportNotification { let hash = summary.hash; BlockImportNotification { diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index 870b4150b9d..0faa90dfc4f 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/client/db/src/lib.rs @@ -2531,7 +2531,7 @@ impl sc_client_api::backend::Backend for Backend { self.storage.state_db.pin(&hash, number.saturated_into::(), hint).map_err( |_| { sp_blockchain::Error::UnknownBlock(format!( - "State already discarded for `{:?}`", + "Unable to pin: state already discarded for `{:?}`", hash )) }, diff --git a/substrate/client/db/src/pinned_blocks_cache.rs b/substrate/client/db/src/pinned_blocks_cache.rs index 46c9287fb19..ac4aad07765 100644 --- a/substrate/client/db/src/pinned_blocks_cache.rs +++ b/substrate/client/db/src/pinned_blocks_cache.rs @@ -20,7 +20,7 @@ use schnellru::{Limiter, LruMap}; use sp_runtime::{traits::Block as BlockT, Justifications}; const LOG_TARGET: &str = "db::pin"; -const PINNING_CACHE_SIZE: usize = 1024; +const PINNING_CACHE_SIZE: usize = 2048; /// Entry for pinned blocks cache. struct PinnedBlockCacheEntry { diff --git a/substrate/client/service/Cargo.toml b/substrate/client/service/Cargo.toml index 73edceb2ef3..bbf67d1fbd0 100644 --- a/substrate/client/service/Cargo.toml +++ b/substrate/client/service/Cargo.toml @@ -84,6 +84,7 @@ tokio = { version = "1.22.0", features = ["parking_lot", "rt-multi-thread", "tim tempfile = "3.1.0" directories = "5.0.1" static_init = "1.0.3" +schnellru = "0.2.1" [dev-dependencies] substrate-test-runtime-client = { path = "../../test-utils/runtime/client" } diff --git a/substrate/client/service/src/client/client.rs b/substrate/client/service/src/client/client.rs index 108c258595a..35e8b53a09c 100644 --- a/substrate/client/service/src/client/client.rs +++ b/substrate/client/service/src/client/client.rs @@ -19,8 +19,8 @@ //! Substrate Client use super::block_rules::{BlockRules, LookupResult as BlockLookupResult}; -use futures::{FutureExt, StreamExt}; -use log::{error, info, trace, warn}; +use crate::client::notification_pinning::NotificationPinningWorker; +use log::{debug, info, trace, warn}; use parking_lot::{Mutex, RwLock}; use prometheus_endpoint::Registry; use rand::Rng; @@ -38,7 +38,7 @@ use sc_client_api::{ execution_extensions::ExecutionExtensions, notifications::{StorageEventStream, StorageNotifications}, CallExecutor, ExecutorProvider, KeysIter, OnFinalityAction, OnImportAction, PairsIter, - ProofProvider, UsageProvider, + ProofProvider, UnpinWorkerMessage, UsageProvider, }; use sc_consensus::{ BlockCheckParams, BlockImportParams, ForkChoiceStrategy, ImportResult, StateAction, @@ -114,7 +114,7 @@ where block_rules: BlockRules, config: ClientConfig, telemetry: Option, - unpin_worker_sender: TracingUnboundedSender, + unpin_worker_sender: TracingUnboundedSender>, _phantom: PhantomData, } @@ -326,19 +326,35 @@ where // dropped, the block will be unpinned automatically. if let Some(ref notification) = finality_notification { if let Err(err) = self.backend.pin_block(notification.hash) { - error!( + debug!( "Unable to pin block for finality notification. hash: {}, Error: {}", notification.hash, err ); - }; + } else { + let _ = self + .unpin_worker_sender + .unbounded_send(UnpinWorkerMessage::AnnouncePin(notification.hash)) + .map_err(|e| { + log::error!( + "Unable to send AnnouncePin worker message for finality: {e}" + ) + }); + } } if let Some(ref notification) = import_notification { if let Err(err) = self.backend.pin_block(notification.hash) { - error!( + debug!( "Unable to pin block for import notification. hash: {}, Error: {}", notification.hash, err ); + } else { + let _ = self + .unpin_worker_sender + .unbounded_send(UnpinWorkerMessage::AnnouncePin(notification.hash)) + .map_err(|e| { + log::error!("Unable to send AnnouncePin worker message for import: {e}") + }); }; } @@ -416,25 +432,12 @@ where backend.commit_operation(op)?; } - let (unpin_worker_sender, mut rx) = - tracing_unbounded::("unpin-worker-channel", 10_000); - let task_backend = Arc::downgrade(&backend); - spawn_handle.spawn( - "unpin-worker", - None, - async move { - while let Some(message) = rx.next().await { - if let Some(backend) = task_backend.upgrade() { - backend.unpin_block(message); - } else { - log::debug!("Terminating unpin-worker, backend reference was dropped."); - return - } - } - log::debug!("Terminating unpin-worker, stream terminated.") - } - .boxed(), + let (unpin_worker_sender, rx) = tracing_unbounded::>( + "notification-pinning-worker-channel", + 10_000, ); + let unpin_worker = NotificationPinningWorker::new(rx, backend.clone()); + spawn_handle.spawn("notification-pinning-worker", None, Box::pin(unpin_worker.run())); Ok(Client { backend, diff --git a/substrate/client/service/src/client/mod.rs b/substrate/client/service/src/client/mod.rs index a13fd4317e1..0703cc2b47d 100644 --- a/substrate/client/service/src/client/mod.rs +++ b/substrate/client/service/src/client/mod.rs @@ -47,6 +47,7 @@ mod block_rules; mod call_executor; mod client; +mod notification_pinning; mod wasm_override; mod wasm_substitutes; diff --git a/substrate/client/service/src/client/notification_pinning.rs b/substrate/client/service/src/client/notification_pinning.rs new file mode 100644 index 00000000000..80de91c02f1 --- /dev/null +++ b/substrate/client/service/src/client/notification_pinning.rs @@ -0,0 +1,353 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +//! Notification pinning related logic. +//! +//! This file contains a worker that should be started when a new client instance is created. +//! The goal is to avoid pruning of blocks that have active notifications in the node. Every +//! recipient of notifications should receive the chance to act upon them. In addition, notification +//! listeners can hold onto a [`sc_client_api::UnpinHandle`] to keep a block pinned. Once the handle +//! is dropped, a message is sent and the worker unpins the respective block. +use std::{ + marker::PhantomData, + sync::{Arc, Weak}, +}; + +use futures::StreamExt; +use sc_client_api::{Backend, UnpinWorkerMessage}; + +use sc_utils::mpsc::TracingUnboundedReceiver; +use schnellru::Limiter; +use sp_runtime::traits::Block as BlockT; + +const LOG_TARGET: &str = "db::notification_pinning"; +const NOTIFICATION_PINNING_LIMIT: usize = 1024; + +/// A limiter which automatically unpins blocks that leave the data structure. +#[derive(Clone, Debug)] +struct UnpinningByLengthLimiter> { + max_length: usize, + backend: Weak, + _phantom: PhantomData, +} + +impl> UnpinningByLengthLimiter { + /// Creates a new length limiter with a given `max_length`. + pub fn new(max_length: usize, backend: Weak) -> UnpinningByLengthLimiter { + UnpinningByLengthLimiter { max_length, backend, _phantom: PhantomData::::default() } + } +} + +impl> Limiter + for UnpinningByLengthLimiter +{ + type KeyToInsert<'a> = Block::Hash; + type LinkType = usize; + + fn is_over_the_limit(&self, length: usize) -> bool { + length > self.max_length + } + + fn on_insert( + &mut self, + _length: usize, + key: Self::KeyToInsert<'_>, + value: u32, + ) -> Option<(Block::Hash, u32)> { + log::debug!(target: LOG_TARGET, "Pinning block based on notification. hash = {key}"); + if self.max_length > 0 { + Some((key, value)) + } else { + None + } + } + + fn on_replace( + &mut self, + _length: usize, + _old_key: &mut Block::Hash, + _new_key: Block::Hash, + _old_value: &mut u32, + _new_value: &mut u32, + ) -> bool { + true + } + + fn on_removed(&mut self, key: &mut Block::Hash, references: &mut u32) { + // If reference count was larger than 0 on removal, + // the item was removed due to capacity limitations. + // Since the cache should be large enough for pinned items, + // we want to know about these evictions. + if *references > 0 { + log::warn!( + target: LOG_TARGET, + "Notification block pinning limit reached. Unpinning block with hash = {key:?}" + ); + if let Some(backend) = self.backend.upgrade() { + (0..*references).for_each(|_| backend.unpin_block(*key)); + } + } else { + log::trace!( + target: LOG_TARGET, + "Unpinned block. hash = {key:?}", + ) + } + } + + fn on_cleared(&mut self) {} + + fn on_grow(&mut self, _new_memory_usage: usize) -> bool { + true + } +} + +/// Worker for the handling of notification pinning. +/// +/// It receives messages from a receiver and pins/unpins based on the incoming messages. +/// All notification related unpinning should go through this worker. If the maximum number of +/// notification pins is reached, the block from the oldest notification is unpinned. +pub struct NotificationPinningWorker> { + unpin_message_rx: TracingUnboundedReceiver>, + task_backend: Weak, + pinned_blocks: schnellru::LruMap>, +} + +impl> NotificationPinningWorker { + /// Creates a new `NotificationPinningWorker`. + pub fn new( + unpin_message_rx: TracingUnboundedReceiver>, + task_backend: Arc, + ) -> Self { + let pinned_blocks = + schnellru::LruMap::>::new( + UnpinningByLengthLimiter::new( + NOTIFICATION_PINNING_LIMIT, + Arc::downgrade(&task_backend), + ), + ); + Self { unpin_message_rx, task_backend: Arc::downgrade(&task_backend), pinned_blocks } + } + + fn handle_announce_message(&mut self, hash: Block::Hash) { + if let Some(entry) = self.pinned_blocks.get_or_insert(hash, Default::default) { + *entry = *entry + 1; + } + } + + fn handle_unpin_message(&mut self, hash: Block::Hash) -> Result<(), ()> { + if let Some(refcount) = self.pinned_blocks.peek_mut(&hash) { + *refcount = *refcount - 1; + if *refcount == 0 { + self.pinned_blocks.remove(&hash); + } + if let Some(backend) = self.task_backend.upgrade() { + log::debug!(target: LOG_TARGET, "Reducing pinning refcount for block hash = {hash:?}"); + backend.unpin_block(hash); + } else { + log::debug!(target: LOG_TARGET, "Terminating unpin-worker, backend reference was dropped."); + return Err(()) + } + } else { + log::debug!(target: LOG_TARGET, "Received unpin message for already unpinned block. hash = {hash:?}"); + } + Ok(()) + } + + /// Start working on the received messages. + /// + /// The worker maintains a map which keeps track of the pinned blocks and their reference count. + /// Depending upon the received message, it acts to pin/unpin the block. + pub async fn run(mut self) { + while let Some(message) = self.unpin_message_rx.next().await { + match message { + UnpinWorkerMessage::AnnouncePin(hash) => self.handle_announce_message(hash), + UnpinWorkerMessage::Unpin(hash) => + if self.handle_unpin_message(hash).is_err() { + return + }, + } + } + log::debug!(target: LOG_TARGET, "Terminating unpin-worker, stream terminated.") + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use sc_client_api::{Backend, UnpinWorkerMessage}; + use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; + use sp_core::H256; + use sp_runtime::traits::Block as BlockT; + + type Block = substrate_test_runtime_client::runtime::Block; + + use super::{NotificationPinningWorker, UnpinningByLengthLimiter}; + + impl> NotificationPinningWorker { + fn new_with_limit( + unpin_message_rx: TracingUnboundedReceiver>, + task_backend: Arc, + limit: usize, + ) -> Self { + let pinned_blocks = + schnellru::LruMap::>::new( + UnpinningByLengthLimiter::new(limit, Arc::downgrade(&task_backend)), + ); + Self { unpin_message_rx, task_backend: Arc::downgrade(&task_backend), pinned_blocks } + } + + fn lru( + &self, + ) -> &schnellru::LruMap> { + &self.pinned_blocks + } + } + + #[test] + fn pinning_worker_handles_base_case() { + let (_tx, rx) = tracing_unbounded("testing", 1000); + + let backend = Arc::new(sc_client_api::in_mem::Backend::::new()); + + let hash = H256::random(); + + let mut worker = NotificationPinningWorker::new(rx, backend.clone()); + + // Block got pinned and unpin message should unpin in the backend. + let _ = backend.pin_block(hash); + assert_eq!(backend.pin_refs(&hash), Some(1)); + + worker.handle_announce_message(hash); + assert_eq!(worker.lru().len(), 1); + + let _ = worker.handle_unpin_message(hash); + + assert_eq!(backend.pin_refs(&hash), Some(0)); + assert!(worker.lru().is_empty()); + } + + #[test] + fn pinning_worker_handles_multiple_pins() { + let (_tx, rx) = tracing_unbounded("testing", 1000); + + let backend = Arc::new(sc_client_api::in_mem::Backend::::new()); + + let hash = H256::random(); + + let mut worker = NotificationPinningWorker::new(rx, backend.clone()); + // Block got pinned multiple times. + let _ = backend.pin_block(hash); + let _ = backend.pin_block(hash); + let _ = backend.pin_block(hash); + assert_eq!(backend.pin_refs(&hash), Some(3)); + + worker.handle_announce_message(hash); + worker.handle_announce_message(hash); + worker.handle_announce_message(hash); + assert_eq!(worker.lru().len(), 1); + + let _ = worker.handle_unpin_message(hash); + assert_eq!(backend.pin_refs(&hash), Some(2)); + let _ = worker.handle_unpin_message(hash); + assert_eq!(backend.pin_refs(&hash), Some(1)); + let _ = worker.handle_unpin_message(hash); + assert_eq!(backend.pin_refs(&hash), Some(0)); + assert!(worker.lru().is_empty()); + + let _ = worker.handle_unpin_message(hash); + assert_eq!(backend.pin_refs(&hash), Some(0)); + } + + #[test] + fn pinning_worker_handles_too_many_unpins() { + let (_tx, rx) = tracing_unbounded("testing", 1000); + + let backend = Arc::new(sc_client_api::in_mem::Backend::::new()); + + let hash = H256::random(); + let hash2 = H256::random(); + + let mut worker = NotificationPinningWorker::new(rx, backend.clone()); + // Block was announced once but unpinned multiple times. The worker should ignore the + // additional unpins. + let _ = backend.pin_block(hash); + let _ = backend.pin_block(hash); + let _ = backend.pin_block(hash); + assert_eq!(backend.pin_refs(&hash), Some(3)); + + worker.handle_announce_message(hash); + assert_eq!(worker.lru().len(), 1); + + let _ = worker.handle_unpin_message(hash); + assert_eq!(backend.pin_refs(&hash), Some(2)); + let _ = worker.handle_unpin_message(hash); + assert_eq!(backend.pin_refs(&hash), Some(2)); + assert!(worker.lru().is_empty()); + + let _ = worker.handle_unpin_message(hash2); + assert!(worker.lru().is_empty()); + assert_eq!(backend.pin_refs(&hash2), None); + } + + #[test] + fn pinning_worker_should_evict_when_limit_reached() { + let (_tx, rx) = tracing_unbounded("testing", 1000); + + let backend = Arc::new(sc_client_api::in_mem::Backend::::new()); + + let hash1 = H256::random(); + let hash2 = H256::random(); + let hash3 = H256::random(); + let hash4 = H256::random(); + + // Only two items fit into the cache. + let mut worker = NotificationPinningWorker::new_with_limit(rx, backend.clone(), 2); + + // Multiple blocks are announced but the cache size is too small. We expect that blocks + // are evicted by the cache and unpinned in the backend. + let _ = backend.pin_block(hash1); + let _ = backend.pin_block(hash2); + let _ = backend.pin_block(hash3); + assert_eq!(backend.pin_refs(&hash1), Some(1)); + assert_eq!(backend.pin_refs(&hash2), Some(1)); + assert_eq!(backend.pin_refs(&hash3), Some(1)); + + worker.handle_announce_message(hash1); + assert!(worker.lru().peek(&hash1).is_some()); + worker.handle_announce_message(hash2); + assert!(worker.lru().peek(&hash2).is_some()); + worker.handle_announce_message(hash3); + assert!(worker.lru().peek(&hash3).is_some()); + assert!(worker.lru().peek(&hash2).is_some()); + assert_eq!(worker.lru().len(), 2); + + // Hash 1 should have gotten unpinned, since its oldest. + assert_eq!(backend.pin_refs(&hash1), Some(0)); + assert_eq!(backend.pin_refs(&hash2), Some(1)); + assert_eq!(backend.pin_refs(&hash3), Some(1)); + + // Hash 2 is getting bumped. + worker.handle_announce_message(hash2); + assert_eq!(worker.lru().peek(&hash2), Some(&2)); + + // Since hash 2 was accessed, evict hash 3. + worker.handle_announce_message(hash4); + assert_eq!(worker.lru().peek(&hash3), None); + } +} -- GitLab From d05f8c57fb29b3c156e542c5473cbb09fae359bb Mon Sep 17 00:00:00 2001 From: Vladimir Istyufeev Date: Mon, 26 Feb 2024 21:40:02 +0400 Subject: [PATCH 030/188] Limit max execution time for `test-linux-stable` CI jobs (#3483) Tests run as part of the `test-linux-stable` jobs could hang as shown [here](https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5341393). This PR adds a failsafe for such cases. --- .gitlab/pipeline/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index b5e26d19489..9f774aab271 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -48,6 +48,7 @@ test-linux-stable: - target/nextest/default/junit.xml reports: junit: target/nextest/default/junit.xml + timeout: 90m test-linux-oldkernel-stable: extends: test-linux-stable -- GitLab From 4080632ee05fc3d7734c856b3af3a024d63197ef Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 26 Feb 2024 18:23:37 +0100 Subject: [PATCH 031/188] [prdoc] Validate crate names (#3467) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: - Add CI script to check that the `crate` names that are mentioned in prdocs are valid. We can extend it lateron to also validate the correct SemVer bumps as introduced in https://github.com/paritytech/polkadot-sdk/pull/3441. Example output: ```pre $ python3 .github/scripts/check-prdoc.py Cargo.toml prdoc/*.prdoc 🔎 Reading workspace polkadot-sdk/Cargo.toml. 📦 Checking 36 prdocs against 494 crates. ✅ All prdocs are valid. ``` Note that not all old prdocs pass the check since crates have been renamed: ```pre $ python3 .github/scripts/check-prdoc.py Cargo.toml prdoc/**/*.prdoc 🔎 Reading workspace polkadot-sdk/Cargo.toml. 📦 Checking 186 prdocs against 494 crates. ❌ Some prdocs are invalid. 💥 prdoc/1.4.0/pr_1926.prdoc lists invalid crate: node-cli 💥 prdoc/1.4.0/pr_2086.prdoc lists invalid crate: xcm-executor 💥 prdoc/1.4.0/pr_2107.prdoc lists invalid crate: xcm 💥 prdoc/1.6.0/pr_2684.prdoc lists invalid crate: xcm-builder ``` --------- Signed-off-by: Oliver Tale-Yazdi --- .github/scripts/check-prdoc.py | 71 +++++++++++++++++++++++++++++++ .github/workflows/check-prdoc.yml | 8 ++++ prdoc/1.4.0/pr_1246.prdoc | 2 +- prdoc/1.6.0/pr_2689.prdoc | 2 +- prdoc/1.6.0/pr_2771.prdoc | 2 +- prdoc/pr_3412.prdoc | 2 +- 6 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 .github/scripts/check-prdoc.py diff --git a/.github/scripts/check-prdoc.py b/.github/scripts/check-prdoc.py new file mode 100644 index 00000000000..42b063f2885 --- /dev/null +++ b/.github/scripts/check-prdoc.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +''' +Ensure that the prdoc files are valid. + +# Example + +```sh +python3 -m pip install cargo-workspace +python3 .github/scripts/check-prdoc.py Cargo.toml prdoc/*.prdoc +``` + +Produces example output: +```pre +🔎 Reading workspace polkadot-sdk/Cargo.toml +📦 Checking 32 prdocs against 493 crates. +✅ All prdocs are valid +``` +''' + +import os +import yaml +import argparse +import cargo_workspace + +def check_prdoc_crate_names(root, paths): + ''' + Check that all crates of the `crates` section of each prdoc is present in the workspace. + ''' + + print(f'🔎 Reading workspace {root}.') + workspace = cargo_workspace.Workspace.from_path(root) + crate_names = [crate.name for crate in workspace.crates] + + print(f'📦 Checking {len(paths)} prdocs against {len(crate_names)} crates.') + faulty = {} + + for path in paths: + with open(path, 'r') as f: + prdoc = yaml.safe_load(f) + + for crate in prdoc.get('crates', []): + crate = crate['name'] + if crate in crate_names: + continue + + faulty.setdefault(path, []).append(crate) + + if len(faulty) == 0: + print('✅ All prdocs are valid.') + else: + print('❌ Some prdocs are invalid.') + for path, crates in faulty.items(): + print(f'💥 {path} lists invalid crate: {", ".join(crates)}') + exit(1) + +def parse_args(): + parser = argparse.ArgumentParser(description='Check prdoc files') + parser.add_argument('root', help='The cargo workspace manifest', metavar='root', type=str, nargs=1) + parser.add_argument('prdoc', help='The prdoc files', metavar='prdoc', type=str, nargs='*') + args = parser.parse_args() + + if len(args.prdoc) == 0: + print('❌ Need at least one prdoc file as argument.') + exit(1) + + return { 'root': os.path.abspath(args.root[0]), 'prdocs': args.prdoc } + +if __name__ == '__main__': + args = parse_args() + check_prdoc_crate_names(args['root'], args['prdocs']) diff --git a/.github/workflows/check-prdoc.yml b/.github/workflows/check-prdoc.yml index 91701ca036e..c31dee06ec5 100644 --- a/.github/workflows/check-prdoc.yml +++ b/.github/workflows/check-prdoc.yml @@ -57,3 +57,11 @@ jobs: echo "Checking for PR#${GITHUB_PR}" echo "You can find more information about PRDoc at $PRDOC_DOC" $ENGINE run --rm -v $PWD:/repo -e RUST_LOG=info $IMAGE check -n ${GITHUB_PR} + + - name: Validate prdoc for PR#${{ github.event.pull_request.number }} + if: ${{ !contains(steps.get-labels.outputs.labels, 'R0') }} + run: | + echo "Validating PR#${GITHUB_PR}" + python3 --version + python3 -m pip install cargo-workspace==1.2.1 + python3 .github/scripts/check-prdoc.py Cargo.toml prdoc/pr_${GITHUB_PR}.prdoc diff --git a/prdoc/1.4.0/pr_1246.prdoc b/prdoc/1.4.0/pr_1246.prdoc index a4d270c45cb..3b5c2017f22 100644 --- a/prdoc/1.4.0/pr_1246.prdoc +++ b/prdoc/1.4.0/pr_1246.prdoc @@ -11,7 +11,7 @@ migrations: description: "Messages from the DMP dispatch queue will be moved over to the MQ pallet via `on_initialize`. This happens over multiple blocks and emits a `Completed` event at the end. The pallet can be un-deployed and deleted afterwards. Note that the migration reverses the order of messages, which should be acceptable as a one-off." crates: - - name: cumulus_pallet_xcmp_queue + - name: cumulus-pallet-xcmp-queue note: Pallet config must be altered according to the MR description. host_functions: [] diff --git a/prdoc/1.6.0/pr_2689.prdoc b/prdoc/1.6.0/pr_2689.prdoc index 847c3e8026c..5d3081e3a4c 100644 --- a/prdoc/1.6.0/pr_2689.prdoc +++ b/prdoc/1.6.0/pr_2689.prdoc @@ -1,7 +1,7 @@ # Schema: Parity PR Documentation Schema (prdoc) # See doc at https://github.com/paritytech/prdoc -title: BEEFY: Support compatibility with Warp Sync - Allow Warp Sync for Validators +title: "BEEFY: Support compatibility with Warp Sync - Allow Warp Sync for Validators" doc: - audience: Node Operator diff --git a/prdoc/1.6.0/pr_2771.prdoc b/prdoc/1.6.0/pr_2771.prdoc index 1b49162e439..50fb99556ec 100644 --- a/prdoc/1.6.0/pr_2771.prdoc +++ b/prdoc/1.6.0/pr_2771.prdoc @@ -6,4 +6,4 @@ doc: Enable better req-response protocol versioning, by allowing for fallback requests on different protocols. crates: - - name: sc_network + - name: sc-network diff --git a/prdoc/pr_3412.prdoc b/prdoc/pr_3412.prdoc index d68f05e45dc..1ee6edfeb83 100644 --- a/prdoc/pr_3412.prdoc +++ b/prdoc/pr_3412.prdoc @@ -13,5 +13,5 @@ doc: crates: - name: pallet-babe - - name: pallet-aura-ext + - name: cumulus-pallet-aura-ext - name: pallet-session -- GitLab From 81d447a8feca14222fef57ffa721302a8b808562 Mon Sep 17 00:00:00 2001 From: philoniare Date: Tue, 27 Feb 2024 04:40:13 +0800 Subject: [PATCH 032/188] Cleanup String::from_utf8 (#3446) # Description *Refactors `String::from_utf8` usage in the pallet benchmarking Fixes #389 --------- Co-authored-by: command-bot <> --- .../benchmarking-cli/src/pallet/command.rs | 50 ++++++++++--------- .../benchmarking-cli/src/pallet/writer.rs | 46 +++++++---------- 2 files changed, 44 insertions(+), 52 deletions(-) diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs index d5dc6226ab9..c6ba2824016 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs @@ -298,16 +298,23 @@ impl PalletCmd { // Convert `Vec` to `String` for better readability. let benchmarks_to_run: Vec<_> = benchmarks_to_run .into_iter() - .map(|b| { + .map(|(pallet, extrinsic, components, pov_modes)| { + let pallet_name = + String::from_utf8(pallet.clone()).expect("Encoded from String; qed"); + let extrinsic_name = + String::from_utf8(extrinsic.clone()).expect("Encoded from String; qed"); ( - b.0, - b.1, - b.2, - b.3.into_iter() + pallet, + extrinsic, + components, + pov_modes + .into_iter() .map(|(p, s)| { (String::from_utf8(p).unwrap(), String::from_utf8(s).unwrap()) }) .collect(), + pallet_name, + extrinsic_name, ) }) .collect(); @@ -329,12 +336,12 @@ impl PalletCmd { let mut component_ranges = HashMap::<(Vec, Vec), Vec>::new(); let pov_modes = Self::parse_pov_modes(&benchmarks_to_run)?; - for (pallet, extrinsic, components, _) in benchmarks_to_run.clone() { + for (pallet, extrinsic, components, _, pallet_name, extrinsic_name) in + benchmarks_to_run.clone() + { log::info!( target: LOG_TARGET, - "Starting benchmark: {}::{}", - String::from_utf8(pallet.clone()).expect("Encoded from String; qed"), - String::from_utf8(extrinsic.clone()).expect("Encoded from String; qed"), + "Starting benchmark: {pallet_name}::{extrinsic_name}" ); let all_components = if components.is_empty() { vec![Default::default()] @@ -415,12 +422,7 @@ impl PalletCmd { ) .map_err(|e| format!("Failed to decode benchmark results: {:?}", e))? .map_err(|e| { - format!( - "Benchmark {}::{} failed: {}", - String::from_utf8_lossy(&pallet), - String::from_utf8_lossy(&extrinsic), - e - ) + format!("Benchmark {pallet_name}::{extrinsic_name} failed: {e}",) })?; } // Do one loop of DB tracking. @@ -494,11 +496,7 @@ impl PalletCmd { log::info!( target: LOG_TARGET, - "Running benchmark: {}.{}({} args) {}/{} {}/{}", - String::from_utf8(pallet.clone()) - .expect("Encoded from String; qed"), - String::from_utf8(extrinsic.clone()) - .expect("Encoded from String; qed"), + "Running benchmark: {pallet_name}::{extrinsic_name}({} args) {}/{} {}/{}", components.len(), s + 1, // s starts at 0. all_components.len(), @@ -707,12 +705,14 @@ impl PalletCmd { Vec, Vec<(BenchmarkParameter, u32, u32)>, Vec<(String, String)>, + String, + String, )>, ) -> Result { use std::collections::hash_map::Entry; let mut parsed = PovModesMap::new(); - for (pallet, call, _components, pov_modes) in benchmarks { + for (pallet, call, _components, pov_modes, _, _) in benchmarks { for (pallet_storage, mode) in pov_modes { let mode = PovEstimationMode::from_str(&mode)?; let splits = pallet_storage.split("::").collect::>(); @@ -766,6 +766,8 @@ fn list_benchmark( Vec, Vec<(BenchmarkParameter, u32, u32)>, Vec<(String, String)>, + String, + String, )>, list_output: ListOutput, no_csv_header: bool, @@ -773,11 +775,11 @@ fn list_benchmark( let mut benchmarks = BTreeMap::new(); // Sort and de-dub by pallet and function name. - benchmarks_to_run.iter().for_each(|(pallet, extrinsic, _, _)| { + benchmarks_to_run.iter().for_each(|(_, _, _, _, pallet_name, extrinsic_name)| { benchmarks - .entry(String::from_utf8_lossy(pallet).to_string()) + .entry(pallet_name) .or_insert_with(BTreeSet::new) - .insert(String::from_utf8_lossy(extrinsic).to_string()); + .insert(extrinsic_name); }); match list_output { diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/writer.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/writer.rs index 9493a693bbe..bd4b65d8a2e 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/writer.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/writer.rs @@ -153,8 +153,8 @@ fn map_results( continue } - let pallet_string = String::from_utf8(batch.pallet.clone()).unwrap(); - let instance_string = String::from_utf8(batch.instance.clone()).unwrap(); + let pallet_name = String::from_utf8(batch.pallet.clone()).unwrap(); + let instance_name = String::from_utf8(batch.instance.clone()).unwrap(); let benchmark_data = get_benchmark_data( batch, storage_info, @@ -166,7 +166,7 @@ fn map_results( worst_case_map_values, additional_trie_layers, ); - let pallet_benchmarks = all_benchmarks.entry((pallet_string, instance_string)).or_default(); + let pallet_benchmarks = all_benchmarks.entry((pallet_name, instance_name)).or_default(); pallet_benchmarks.push(benchmark_data); } Ok(all_benchmarks) @@ -571,19 +571,22 @@ pub(crate) fn process_storage_results( let mut prefix_result = result.clone(); let key_info = storage_info_map.get(&prefix); + let pallet_name = match key_info { + Some(k) => String::from_utf8(k.pallet_name.clone()).expect("encoded from string"), + None => "".to_string(), + }; + let storage_name = match key_info { + Some(k) => String::from_utf8(k.storage_name.clone()).expect("encoded from string"), + None => "".to_string(), + }; let max_size = key_info.and_then(|k| k.max_size); let override_pov_mode = match key_info { - Some(StorageInfo { pallet_name, storage_name, .. }) => { - let pallet_name = - String::from_utf8(pallet_name.clone()).expect("encoded from string"); - let storage_name = - String::from_utf8(storage_name.clone()).expect("encoded from string"); - + Some(_) => { // Is there an override for the storage key? - pov_modes.get(&(pallet_name.clone(), storage_name)).or( + pov_modes.get(&(pallet_name.clone(), storage_name.clone())).or( // .. or for the storage prefix? - pov_modes.get(&(pallet_name, "ALL".to_string())).or( + pov_modes.get(&(pallet_name.clone(), "ALL".to_string())).or( // .. or for the benchmark? pov_modes.get(&("ALL".to_string(), "ALL".to_string())), ), @@ -662,15 +665,10 @@ pub(crate) fn process_storage_results( // writes. if !is_prefix_identified { match key_info { - Some(key_info) => { + Some(_) => { let comment = format!( "Storage: `{}::{}` (r:{} w:{})", - String::from_utf8(key_info.pallet_name.clone()) - .expect("encoded from string"), - String::from_utf8(key_info.storage_name.clone()) - .expect("encoded from string"), - reads, - writes, + pallet_name, storage_name, reads, writes, ); comments.push(comment) }, @@ -698,11 +696,7 @@ pub(crate) fn process_storage_results( ) { Some(new_pov) => { let comment = format!( - "Proof: `{}::{}` (`max_values`: {:?}, `max_size`: {:?}, added: {}, mode: `{:?}`)", - String::from_utf8(key_info.pallet_name.clone()) - .expect("encoded from string"), - String::from_utf8(key_info.storage_name.clone()) - .expect("encoded from string"), + "Proof: `{pallet_name}::{storage_name}` (`max_values`: {:?}, `max_size`: {:?}, added: {}, mode: `{:?}`)", key_info.max_values, key_info.max_size, new_pov, @@ -711,13 +705,9 @@ pub(crate) fn process_storage_results( comments.push(comment) }, None => { - let pallet = String::from_utf8(key_info.pallet_name.clone()) - .expect("encoded from string"); - let item = String::from_utf8(key_info.storage_name.clone()) - .expect("encoded from string"); let comment = format!( "Proof: `{}::{}` (`max_values`: {:?}, `max_size`: {:?}, mode: `{:?}`)", - pallet, item, key_info.max_values, key_info.max_size, + pallet_name, storage_name, key_info.max_values, key_info.max_size, used_pov_mode, ); comments.push(comment); -- GitLab From f5de090aa56d0801f043c2b13892191b3d0c9f50 Mon Sep 17 00:00:00 2001 From: Javier Viola <363911+pepoviola@users.noreply.github.com> Date: Tue, 27 Feb 2024 08:24:07 -0300 Subject: [PATCH 033/188] fix(zombienet): increase timeout in download artifacts (#3376) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix timeouts downloading the artifacts (e.g https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5246040) Thx! --------- Co-authored-by: Bastian Köcher --- polkadot/zombienet_tests/misc/0002-upgrade-node.zndsl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/polkadot/zombienet_tests/misc/0002-upgrade-node.zndsl b/polkadot/zombienet_tests/misc/0002-upgrade-node.zndsl index db0a60ac1df..5fe1b2ad2f1 100644 --- a/polkadot/zombienet_tests/misc/0002-upgrade-node.zndsl +++ b/polkadot/zombienet_tests/misc/0002-upgrade-node.zndsl @@ -10,9 +10,8 @@ dave: parachain 2001 block height is at least 10 within 200 seconds # POLKADOT_PR_ARTIFACTS_URL=https://gitlab.parity.io/parity/mirrors/polkadot/-/jobs/1842869/artifacts/raw/artifacts # with the version of polkadot you want to download. -# avg 30s in our infra -alice: run ./0002-download-polkadot-from-pr.sh with "{{POLKADOT_PR_ARTIFACTS_URL}}" within 60 seconds -bob: run ./0002-download-polkadot-from-pr.sh with "{{POLKADOT_PR_ARTIFACTS_URL}}" within 60 seconds +alice: run ./0002-download-polkadot-from-pr.sh with "{{POLKADOT_PR_ARTIFACTS_URL}}" within 240 seconds +bob: run ./0002-download-polkadot-from-pr.sh with "{{POLKADOT_PR_ARTIFACTS_URL}}" within 240 seconds # update the cmd to add the flag '--insecure-validator-i-know-what-i-do' # once the base image include the version with this flag we can remove this logic. alice: run ./0002-update-cmd.sh within 60 seconds -- GitLab From 94c54d50322076e78a687785594eb84c78b823d7 Mon Sep 17 00:00:00 2001 From: Clara van Staden Date: Tue, 27 Feb 2024 14:49:31 +0200 Subject: [PATCH 034/188] Snowbridge benchmark tests fix (#3424) When running `cargo test -p bridge-hub-rococo-runtime --features runtime-benchmarks`, two of the Snowbridge benchmark tests fails. The reason is that when the runtime-benchmarks feature is enabled, the `NoopMessageProcessor` message processor is used. The Snowbridge tests rely on the outbound messages to be processed using the message queue, so that we can check the expected nonce and block digest logs. This PR changes the conditional compilation to only use `NoopMessageProcessor` when compiling the executable to run benchmarks against, not when running tests. --------- Co-authored-by: claravanstaden --- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 15cf045a995..f576776696c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -102,8 +102,6 @@ use polkadot_runtime_common::prod_or_fast; #[cfg(feature = "runtime-benchmarks")] use benchmark_helpers::DoNothingRouter; -#[cfg(not(feature = "runtime-benchmarks"))] -use bridge_hub_common::BridgeHubMessageRouter; /// The address format for describing accounts. pub type Address = MultiAddress; @@ -367,11 +365,15 @@ parameter_types! { impl pallet_message_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = weights::pallet_message_queue::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] + // 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(feature = "runtime-benchmarks"))] - type MessageProcessor = BridgeHubMessageRouter< + #[cfg(not(all(not(feature = "std"), feature = "runtime-benchmarks")))] + type MessageProcessor = bridge_hub_common::BridgeHubMessageRouter< xcm_builder::ProcessXcmMessage< AggregateMessageOrigin, xcm_executor::XcmExecutor, -- GitLab From 2cdda0e62dd3088d2fd09cea627059674070c277 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 27 Feb 2024 14:16:23 +0100 Subject: [PATCH 035/188] Bridge zombienet tests: Check amount received at destination (#3490) Related to https://github.com/paritytech/polkadot-sdk/issues/3475 --- .../rococo-westend/bridges_rococo_westend.sh | 12 ++++++++---- .../js-helpers/native-assets-balance-increased.js | 5 +++-- .../0001-asset-transfer/roc-reaches-westend.zndsl | 8 ++++---- .../0001-asset-transfer/wnd-reaches-rococo.zndsl | 8 ++++---- .../0001-asset-transfer/wroc-reaches-rococo.zndsl | 8 ++++---- .../0001-asset-transfer/wwnd-reaches-westend.zndsl | 8 ++++---- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh index de5be2e0af8..479ab833abf 100755 --- a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh +++ b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh @@ -319,6 +319,7 @@ case "$1" in $XCM_VERSION ;; reserve-transfer-assets-from-asset-hub-rococo-local) + amount=$2 ensure_polkadot_js_api # send ROCs to Alice account on AHW limited_reserve_transfer_assets \ @@ -326,11 +327,12 @@ case "$1" in "//Alice" \ "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } } }')" \ "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ - "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 5000000000000 } } ] }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": '$amount' } } ] }')" \ 0 \ "Unlimited" ;; withdraw-reserve-assets-from-asset-hub-rococo-local) + amount=$2 ensure_polkadot_js_api # send back only 100000000000 wrappedWNDs to Alice account on AHW limited_reserve_transfer_assets \ @@ -338,11 +340,12 @@ case "$1" in "//Alice" \ "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } } }')" \ "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ - "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Westend" } } } }, "fun": { "Fungible": 3000000000000 } } ] }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Westend" } } } }, "fun": { "Fungible": '$amount' } } ] }')" \ 0 \ "Unlimited" ;; reserve-transfer-assets-from-asset-hub-westend-local) + amount=$2 ensure_polkadot_js_api # send WNDs to Alice account on AHR limited_reserve_transfer_assets \ @@ -350,11 +353,12 @@ case "$1" in "//Alice" \ "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \ "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ - "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 5000000000000 } } ] }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": '$amount' } } ] }')" \ 0 \ "Unlimited" ;; withdraw-reserve-assets-from-asset-hub-westend-local) + amount=$2 ensure_polkadot_js_api # send back only 100000000000 wrappedROCs to Alice account on AHR limited_reserve_transfer_assets \ @@ -362,7 +366,7 @@ case "$1" in "//Alice" \ "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \ "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ - "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } } }, "fun": { "Fungible": 3000000000000 } } ] }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } } }, "fun": { "Fungible": '$amount' } } ] }')" \ 0 \ "Unlimited" ;; diff --git a/bridges/testing/framework/js-helpers/native-assets-balance-increased.js b/bridges/testing/framework/js-helpers/native-assets-balance-increased.js index a35c753d973..749c3e2fec3 100644 --- a/bridges/testing/framework/js-helpers/native-assets-balance-increased.js +++ b/bridges/testing/framework/js-helpers/native-assets-balance-increased.js @@ -3,12 +3,13 @@ async function run(nodeName, networkInfo, args) { const api = await zombie.connect(wsUri, userDefinedTypes); const accountAddress = args[0]; + const expectedIncrease = BigInt(args[1]); const initialAccountData = await api.query.system.account(accountAddress); const initialAccountBalance = initialAccountData.data['free']; while (true) { const accountData = await api.query.system.account(accountAddress); const accountBalance = accountData.data['free']; - if (accountBalance > initialAccountBalance) { + if (accountBalance > initialAccountBalance + expectedIncrease) { return accountBalance; } @@ -17,4 +18,4 @@ async function run(nodeName, networkInfo, args) { } } -module.exports = { run } +module.exports = {run} diff --git a/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl index 4725362ae82..a58520ccea6 100644 --- a/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl @@ -2,11 +2,11 @@ Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml Creds: config -# send ROC to //Alice from Rococo AH to Westend AH -asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 120 seconds +# send 5 ROC to //Alice from Rococo AH to Westend AH +asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-rococo-local 5000000000000" within 120 seconds -# check that //Alice received the ROC on Westend AH -asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Rococo" within 300 seconds +# check that //Alice received at least 4.8 ROC on Westend AH +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Rococo" within 300 seconds # check that the relayer //Charlie is rewarded by Westend AH bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726F,ThisChain,0" within 30 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl index 77267239c3b..fedb78cc210 100644 --- a/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl @@ -2,11 +2,11 @@ Description: User is able to transfer WND from Westend Asset Hub to Rococo Asset Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml Creds: config -# send WND to //Alice from Westend AH to Rococo AH -asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 120 seconds +# send 5 WND to //Alice from Westend AH to Rococo AH +asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-westend-local 5000000000000" within 120 seconds -# check that //Alice received the WND on Rococo AH -asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Westend" within 300 seconds +# check that //Alice received at least 4.8 WND on Rococo AH +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Westend" within 300 seconds # check that the relayer //Charlie is rewarded by Rococo AH bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,ThisChain,0" within 30 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl index f72b76e6026..68b888b6858 100644 --- a/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl @@ -2,9 +2,9 @@ Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml Creds: config -# send wROC back to Alice from Westend AH to Rococo AH -asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-westend-local" within 120 seconds +# send 3 wROC back to Alice from Westend AH to Rococo AH +asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-westend-local 3000000000000" within 120 seconds -# check that //Alice received the wROC on Rococo AH +# check that //Alice received at least 2.8 wROC on Rococo AH # (we wait until //Alice account increases here - there are no other transactions that may increase it) -asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" within 300 seconds +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 300 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl index 9d893c8d90a..1a8a1618195 100644 --- a/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl @@ -2,9 +2,9 @@ Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml Creds: config -# send wWND back to Alice from Rococo AH to Westend AH -asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local" within 120 seconds +# send 3 wWND back to Alice from Rococo AH to Westend AH +asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local 3000000000000" within 120 seconds -# check that //Alice received the wWND on Westend AH +# check that //Alice received at least 2.8 wWND on Westend AH # (we wait until //Alice account increases here - there are no other transactions that may increase it) -asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" within 300 seconds +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 300 seconds -- GitLab From 29369a4e7ca92d38a305a3a3115609718785eba9 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 27 Feb 2024 14:50:21 +0000 Subject: [PATCH 036/188] Add documentation around FRAME Origin (#3362) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Does the following: - Add a reference doc page named `frame_runtime_types`, which explains what types like `RuntimeOrigin`, `RuntimeCall` etc are. - On top of it, it adds a reference doc page called `frame_origin` which explains a few important patterns that we use around origins - And finally brushes up `#[frame::origin]` docs. - Updates the theme, sidebar and favicon to look like: Screenshot 2024-02-20 at 12 16 00 All of this was inspired by https://substrate.stackexchange.com/questions/10992/how-do-you-find-the-public-key-for-the-medium-spender-track-origin/10993 closes https://github.com/paritytech/polkadot-sdk-docs/issues/45 closes https://github.com/paritytech/polkadot-sdk-docs/issues/43 contributes / overlaps with https://github.com/paritytech/polkadot-sdk/pull/2638 cc @liamaharon deprecation companion: https://github.com/substrate-developer-hub/substrate-docs/pull/2131 pba-content companion: https://github.com/Polkadot-Blockchain-Academy/pba-content/pull/977 --------- Co-authored-by: Radha <86818441+DrW3RK@users.noreply.github.com> Co-authored-by: Sebastian Kunert Co-authored-by: Gonçalo Pestana Co-authored-by: Liam Aharon --- .gitlab/pipeline/build.yml | 2 +- Cargo.lock | 9 + docs/mermaid/IA.mmd | 2 +- docs/mermaid/outer_runtime_types.mmd | 3 + docs/sdk/Cargo.toml | 20 +- docs/sdk/headers/header.html | 139 ++++++++ docs/sdk/headers/theme.css | 16 + docs/sdk/headers/toc.html | 54 ---- docs/sdk/src/guides/your_first_pallet/mod.rs | 9 +- docs/sdk/src/lib.rs | 7 +- docs/sdk/src/meta_contributing.rs | 6 +- .../src/reference_docs/extrinsic_encoding.rs | 2 +- .../reference_docs/frame_composite_enums.rs | 1 - docs/sdk/src/reference_docs/frame_origin.rs | 270 +++++++++++++++- .../src/reference_docs/frame_runtime_types.rs | 306 ++++++++++++++++++ docs/sdk/src/reference_docs/mod.rs | 8 +- substrate/frame/src/lib.rs | 6 + .../src/construct_runtime/expand/origin.rs | 2 +- substrate/frame/support/procedural/src/lib.rs | 17 +- substrate/frame/support/src/lib.rs | 68 +++- substrate/frame/system/src/lib.rs | 1 + 21 files changed, 839 insertions(+), 109 deletions(-) create mode 100644 docs/mermaid/outer_runtime_types.mmd create mode 100644 docs/sdk/headers/header.html create mode 100644 docs/sdk/headers/theme.css delete mode 100644 docs/sdk/headers/toc.html delete mode 100644 docs/sdk/src/reference_docs/frame_composite_enums.rs create mode 100644 docs/sdk/src/reference_docs/frame_runtime_types.rs diff --git a/.gitlab/pipeline/build.yml b/.gitlab/pipeline/build.yml index 15b4869997b..423587c1fb5 100644 --- a/.gitlab/pipeline/build.yml +++ b/.gitlab/pipeline/build.yml @@ -91,7 +91,7 @@ build-rustdoc: - .run-immediately variables: SKIP_WASM_BUILD: 1 - RUSTDOCFLAGS: "" + RUSTDOCFLAGS: "--default-theme=ayu --html-in-header ./docs/sdk/headers/header.html --extend-css ./docs/sdk/headers/theme.css" artifacts: name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}-doc" when: on_success diff --git a/Cargo.lock b/Cargo.lock index 410b45d0018..c52feafe7a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13384,11 +13384,20 @@ dependencies = [ "cumulus-pallet-parachain-system", "docify", "frame", + "frame-system", "kitchensink-runtime", "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collective", "pallet-default-config-example", + "pallet-democracy", "pallet-examples", + "pallet-multisig", + "pallet-proxy", "pallet-timestamp", + "pallet-transaction-payment", + "pallet-utility", "parity-scale-codec", "sc-cli", "sc-client-db", diff --git a/docs/mermaid/IA.mmd b/docs/mermaid/IA.mmd index 93d3e92814c..4eb50bcf96a 100644 --- a/docs/mermaid/IA.mmd +++ b/docs/mermaid/IA.mmd @@ -3,7 +3,7 @@ flowchart devhub --> polkadot_sdk devhub --> reference_docs - devhub --> tutorial + devhub --> guides polkadot_sdk --> substrate polkadot_sdk --> frame diff --git a/docs/mermaid/outer_runtime_types.mmd b/docs/mermaid/outer_runtime_types.mmd new file mode 100644 index 00000000000..c909df16af1 --- /dev/null +++ b/docs/mermaid/outer_runtime_types.mmd @@ -0,0 +1,3 @@ +flowchart LR + RuntimeCall --"TryInto"--> PalletCall + PalletCall --"Into"--> RuntimeCall diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index 05aced8751a..576a81834f8 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -17,7 +17,10 @@ workspace = true # Needed for all FRAME-based code parity-scale-codec = { version = "3.0.0", default-features = false } scale-info = { version = "2.6.0", default-features = false } -frame = { path = "../../substrate/frame", features = ["experimental", "runtime"] } +frame = { path = "../../substrate/frame", features = [ + "experimental", + "runtime", +] } pallet-examples = { path = "../../substrate/frame/examples" } pallet-default-config-example = { path = "../../substrate/frame/examples/default-config" } @@ -52,7 +55,18 @@ cumulus-pallet-parachain-system = { path = "../../cumulus/pallets/parachain-syst ] } parachain-info = { package = "staging-parachain-info", path = "../../cumulus/parachains/pallets/parachain-info" } pallet-aura = { path = "../../substrate/frame/aura", default-features = false } + +# Pallets and FRAME internals pallet-timestamp = { path = "../../substrate/frame/timestamp" } +pallet-balances = { path = "../../substrate/frame/balances" } +pallet-transaction-payment = { path = "../../substrate/frame/transaction-payment" } +pallet-utility = { path = "../../substrate/frame/utility" } +pallet-multisig = { path = "../../substrate/frame/multisig" } +pallet-proxy = { path = "../../substrate/frame/proxy" } +pallet-authorship = { path = "../../substrate/frame/authorship" } +pallet-collective = { path = "../../substrate/frame/collective" } +pallet-democracy = { path = "../../substrate/frame/democracy" } +frame-system = { path = "../../substrate/frame/system" } # Primitives sp-io = { path = "../../substrate/primitives/io" } @@ -64,9 +78,5 @@ sp-runtime = { path = "../../substrate/primitives/runtime" } # XCM xcm = { package = "staging-xcm", path = "../../polkadot/xcm" } -[dev-dependencies] -parity-scale-codec = "3.6.5" -scale-info = "2.9.0" - [features] experimental = ["pallet-aura/experimental"] diff --git a/docs/sdk/headers/header.html b/docs/sdk/headers/header.html new file mode 100644 index 00000000000..68dc5d5509e --- /dev/null +++ b/docs/sdk/headers/header.html @@ -0,0 +1,139 @@ + + + diff --git a/docs/sdk/headers/theme.css b/docs/sdk/headers/theme.css new file mode 100644 index 00000000000..bb9254ec4a8 --- /dev/null +++ b/docs/sdk/headers/theme.css @@ -0,0 +1,16 @@ +:root { + --polkadot-pink: #E6007A ; + --polkadot-green: #56F39A ; + --polkadot-lime: #D3FF33 ; + --polkadot-cyan: #00B2FF ; + --polkadot-purple: #552BBF ; + } + +body > nav.sidebar > div.sidebar-crate > a > img { + /* logo width, given that the sidebar width is 200px; */ + width: 190px; +} + +body nav.sidebar { + flex: 0 0 250px; +} diff --git a/docs/sdk/headers/toc.html b/docs/sdk/headers/toc.html deleted file mode 100644 index a4a074cb4f3..00000000000 --- a/docs/sdk/headers/toc.html +++ /dev/null @@ -1,54 +0,0 @@ - - diff --git a/docs/sdk/src/guides/your_first_pallet/mod.rs b/docs/sdk/src/guides/your_first_pallet/mod.rs index 29cdda36ed1..20a8639b270 100644 --- a/docs/sdk/src/guides/your_first_pallet/mod.rs +++ b/docs/sdk/src/guides/your_first_pallet/mod.rs @@ -128,8 +128,8 @@ //! //! Recall that within our pallet, (almost) all blocks of code are generic over ``. And, //! because `trait Config: frame_system::Config`, we can get access to all items in `Config` (or -//! `frame_system::Config`) using `T::NameOfItem`. This is all within the boundaries of how Rust -//! traits and generics work. If unfamiliar with this pattern, read +//! `frame_system::Config`) using `T::NameOfItem`. This is all within the boundaries of how +//! Rust traits and generics work. If unfamiliar with this pattern, read //! [`crate::reference_docs::trait_based_programming`] before going further. //! //! Crucially, a typical FRAME runtime contains a `struct Runtime`. The main role of this `struct` @@ -270,7 +270,7 @@ #![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", config_v2)] //! //! > These `Runtime*` types are better explained in -//! > [`crate::reference_docs::frame_composite_enums`]. +//! > [`crate::reference_docs::frame_runtime_types`]. //! //! Then, we can rewrite the `transfer` dispatchable as such: #![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", transfer_v2)] @@ -285,7 +285,6 @@ //! [`crate::guides::your_first_pallet::pallet_v2::tests::runtime_v2::RuntimeEvent`]. //! //! -//! //! ## What Next? //! //! The following topics where used in this guide, but not covered in depth. It is suggested to @@ -293,7 +292,7 @@ //! //! - [`crate::reference_docs::safe_defensive_programming`]. //! - [`crate::reference_docs::frame_origin`]. -//! - [`crate::reference_docs::frame_composite_enums`]. +//! - [`crate::reference_docs::frame_runtime_types`]. //! - The pallet we wrote in this guide was using `dev_mode`, learn more in //! [`frame::pallet_macros::config`]. //! - Learn more about the individual pallet items/macros, such as event and errors and call, in diff --git a/docs/sdk/src/lib.rs b/docs/sdk/src/lib.rs index 075d9ddaffe..e211476d251 100644 --- a/docs/sdk/src/lib.rs +++ b/docs/sdk/src/lib.rs @@ -15,7 +15,7 @@ //! - Start by learning about the the [`polkadot_sdk`], its structure and context. //! - Then, head over the [`guides`]. This modules contains in-depth guides about the most important //! user-journeys of the Polkadot SDK. -//! - Whilst reading the guides, you might find back-links to [`crate::reference_docs`]. +//! - Whilst reading the guides, you might find back-links to [`reference_docs`]. //! - Finally, is the parent website of this crate that contains the //! list of further tools related to the Polkadot SDK. //! @@ -25,6 +25,11 @@ #![doc = simple_mermaid::mermaid!("../../mermaid/IA.mmd")] #![warn(rustdoc::broken_intra_doc_links)] #![warn(rustdoc::private_intra_doc_links)] +#![doc(html_favicon_url = "https://polkadot.network/favicon-32x32.png")] +#![doc( + html_logo_url = "https://europe1.discourse-cdn.com/standard21/uploads/polkadot2/original/1X/eb57081e2bb7c39e5fcb1a98b443e423fa4448ae.svg" +)] +#![doc(issue_tracker_base_url = "https://github.com/paritytech/polkadot-sdk/issues")] /// Meta information about this crate, how it is built, what principles dictates its evolution and /// how one can contribute to it. diff --git a/docs/sdk/src/meta_contributing.rs b/docs/sdk/src/meta_contributing.rs index 7ecf8b0adfd..fcdcea9934b 100644 --- a/docs/sdk/src/meta_contributing.rs +++ b/docs/sdk/src/meta_contributing.rs @@ -101,7 +101,7 @@ //! * Before even getting started, what is with all of this ``? We link to //! [`crate::reference_docs::trait_based_programming`]. //! * First, the name. Why is this called `pallet::call`? This goes back to `enum Call`, which is -//! explained in [`crate::reference_docs::frame_composite_enums`]. Build on top of this! +//! explained in [`crate::reference_docs::frame_runtime_types`]. Build on top of this! //! * Then, what is `origin`? Just an account id? [`crate::reference_docs::frame_origin`]. //! * Then, what is `DispatchResult`? Why is this called *dispatch*? Probably something that can be //! explained in the documentation of [`frame::prelude::DispatchResult`]. @@ -138,7 +138,9 @@ //! injected, run: //! //! ```sh -//! SKIP_WASM_BUILD=1 RUSTDOCFLAGS="--html-in-header $(pwd)/docs/sdk/headers/toc.html" cargo doc -p polkadot-sdk-docs --no-deps --open +//! SKIP_WASM_BUILD=1 \ +//! RUSTDOCFLAGS="--html-in-header $(pwd)/docs/sdk/headers/header.html --extend-css $(pwd)/docs/sdk/headers/theme.css --default-theme=ayu" \ +//! cargo doc -p polkadot-sdk-docs --no-deps --open //! ``` //! //! If even faster build time for docs is needed, you can temporarily remove most of the diff --git a/docs/sdk/src/reference_docs/extrinsic_encoding.rs b/docs/sdk/src/reference_docs/extrinsic_encoding.rs index 9008f8f835f..8c8568a228f 100644 --- a/docs/sdk/src/reference_docs/extrinsic_encoding.rs +++ b/docs/sdk/src/reference_docs/extrinsic_encoding.rs @@ -127,7 +127,7 @@ //! runtimes, a call is represented as an enum of enums, where the outer enum represents the FRAME //! pallet being called, and the inner enum represents the call being made within that pallet, and //! any arguments to it. Read more about the call enum -//! [here][crate::reference_docs::frame_composite_enums]. +//! [here][crate::reference_docs::frame_runtime_types]. //! //! FRAME `Call` enums are automatically generated, and end up looking something like this: #![doc = docify::embed!("./src/reference_docs/extrinsic_encoding.rs", call_data)] diff --git a/docs/sdk/src/reference_docs/frame_composite_enums.rs b/docs/sdk/src/reference_docs/frame_composite_enums.rs deleted file mode 100644 index 6051cd53446..00000000000 --- a/docs/sdk/src/reference_docs/frame_composite_enums.rs +++ /dev/null @@ -1 +0,0 @@ -//! # FRAME Composite Enums diff --git a/docs/sdk/src/reference_docs/frame_origin.rs b/docs/sdk/src/reference_docs/frame_origin.rs index a4078377cd7..49533157b01 100644 --- a/docs/sdk/src/reference_docs/frame_origin.rs +++ b/docs/sdk/src/reference_docs/frame_origin.rs @@ -1,14 +1,260 @@ //! # FRAME Origin //! -//! Notes: -//! -//! - Def talk about account abstraction and how it is a solved issue in frame. See Gav's talk in -//! Protocol Berg 2023 -//! - system's raw origin, how it is amalgamated with other origins into one type -//! [`frame_composite_enums`] -//! - signed origin -//! - unsigned origin, link to [`fee_less_runtime`] -//! - Root origin, how no one can obtain it. -//! - Abstract origin: how FRAME allows you to express "origin is 2/3 of the this body or 1/2 of -//! that body or half of the token holders". -//! - `type CustomOrigin: EnsureOrigin<_>` in pallets. +//! Let's start by clarifying a common wrong assumption about Origin: +//! +//! **ORIGIN IS NOT AN ACCOUNT ID**. +//! +//! FRAME's origin abstractions allow you to convey meanings far beyond just an account-id being the +//! caller of an extrinsic. Nonetheless, an account-id having signed an extrinsic is one of the +//! meanings that an origin can convey. This is the commonly used [`frame_system::ensure_signed`], +//! where the return value happens to be an account-id. +//! +//! Instead, let's establish the following as the correct definition of an origin: +//! +//! > The origin type represents the privilege level of the caller of an extrinsic. +//! +//! That is, an extrinsic, through checking the origin, can *express what privilege level it wishes +//! to impose on the caller of the extrinsic*. One of those checks can be as simple as "*any account +//! that has signed a statement can pass*". +//! +//! But the origin system can also express more abstract and complicated privilege levels. For +//! example: +//! +//! * If the majority of token holders agreed upon this. This is more or less what the +//! [`pallet_democracy`] does under the hood ([reference](https://github.com/paritytech/polkadot-sdk/blob/edd95b3749754d2ed0c5738588e872c87be91624/substrate/frame/democracy/src/lib.rs#L1603-L1633)). +//! * If a specific ratio of an instance of [`pallet_collective`]/DAO agrees upon this. +//! * If another consensus system, for example a bridged network or a parachain, agrees upon this. +//! * If the majority of validator/authority set agrees upon this[^1]. +//! * If caller holds a particular NFT. +//! +//! and many more. +//! +//! ## Context +//! +//! First, let's look at where the `origin` type is encountered in a typical pallet. The `origin: +//! OriginFor` has to be the first argument of any given callable extrinsic in FRAME: +#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", call_simple)] +//! +//! Typically, the code of an extrinsic starts with an origin check, such as +//! [`frame_system::ensure_signed`]. +//! +//! Note that [`OriginFor`](frame_system::pallet_prelude::OriginFor) is merely a shorthand for +//! [`frame_system::Config::RuntimeOrigin`]. Given the name prefix `Runtime`, we can learn that +//! `RuntimeOrigin` is similar to `RuntimeCall` and others, a runtime composite enum that is +//! amalgamated at the runtime level. Read [`crate::reference_docs::frame_runtime_types`] to +//! familiarize yourself with these types. +//! +//! To understand this better, we will next create a pallet with a custom origin, which will add a +//! new variant to `RuntimeOrigin`. +//! +//! ## Adding Custom Pallet Origin to the Runtime +//! +//! For example, given a pallet that defines the following custom origin: +#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", custom_origin)] +//! +//! And a runtime with the following pallets: +#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", runtime_exp)] +//! +//! The type [`crate::reference_docs::frame_origin::runtime_for_origin::RuntimeOrigin`] is expanded. +//! This `RuntimeOrigin` contains a variant for the [`frame_system::RawOrigin`] and the custom +//! origin of the pallet. +//! +//! > Notice how the [`frame_system::ensure_signed`] is nothing more than a `match` statement. If +//! > you want to know where the actual origin of an extrinsic is set (and the signature +//! > verification happens, if any), see +//! > [`sp_runtime::generic::CheckedExtrinsic#trait-implementations`], specifically +//! > [`sp_runtime::traits::Applyable`]'s implementation. +//! +//! ## Asserting on a Custom Internal Origin +//! +//! In order to assert on a custom origin that is defined within your pallet, we need a way to first +//! convert the `::RuntimeOrigin` into the local `enum Origin` of the +//! current pallet. This is a common process that is explained in +//! [`crate::reference_docs::frame_runtime_types# +//! adding-further-constraints-to-runtime-composite-enums`]. +//! +//! We use the same process here to express that `RuntimeOrigin` has a number of additional bounds, +//! as follows. +//! +//! 1. Defining a custom `RuntimeOrigin` with further bounds in the pallet. +#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", custom_origin_bound)] +//! +//! 2. Using it in the pallet. +#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", custom_origin_usage)] +//! +//! ## Asserting on a Custom External Origin +//! +//! Very often, a pallet wants to have a parameterized origin that is **NOT** defined within the +//! pallet. In other words, a pallet wants to delegate an origin check to something that is +//! specified later at the runtime level. Like many other parameterizations in FRAME, this implies +//! adding a new associated type to `trait Config`. +#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", external_origin_def)] +//! +//! Then, within the pallet, we can simply use this "unknown" origin check type: +#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", external_origin_usage)] +//! +//! Finally, at the runtime, any implementation of [`frame::traits::EnsureOrigin`] can be passed. +#![doc = docify::embed!("./src/reference_docs/frame_origin.rs", external_origin_provide)] +//! +//! Indeed, some of these implementations of [`frame::traits::EnsureOrigin`] are similar to the ones +//! that we know about: [`frame::runtime::prelude::EnsureSigned`], +//! [`frame::runtime::prelude::EnsureSignedBy`], [`frame::runtime::prelude::EnsureRoot`], +//! [`frame::runtime::prelude::EnsureNone`], etc. But, there are also many more that are not known +//! to us, and are defined in other pallets. +//! +//! For example, [`pallet_collective`] defines [`pallet_collective::EnsureMember`] and +//! [`pallet_collective::EnsureProportionMoreThan`] and many more, which is exactly what we alluded +//! to earlier in this document. +//! +//! Make sure to check the full list of [implementors of +//! `EnsureOrigin`](frame::traits::EnsureOrigin#implementors) for more inspiration. +//! +//! ## Obtaining Abstract Origins +//! +//! So far we have learned that FRAME pallets can assert on custom and abstract origin types, +//! whether they are defined within the pallet or not. But how can we obtain these abstract origins? +//! +//! > All extrinsics that come from the outer world can generally only be obtained as either +//! > `signed` or `none` origin. +//! +//! Generally, these abstract origins are only obtained within the runtime, when a call is +//! dispatched within the runtime. +//! +//! ## Further References +//! +//! - [Gavin Wood's speech about FRAME features at Protocol Berg 2023.](https://youtu.be/j7b8Upipmeg?si=83_XUgYuJxMwWX4g&t=195) +//! - [A related StackExchange question.](https://substrate.stackexchange.com/questions/10992/how-do-you-find-the-public-key-for-the-medium-spender-track-origin) +//! +//! [^1]: Inherents are essentially unsigned extrinsics that need an [`frame_system::ensure_none`] +//! origin check, and through the virtue of being an inherent, are agreed upon by all validators. + +use frame::prelude::*; + +#[frame::pallet(dev_mode)] +pub mod pallet_for_origin { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[docify::export(call_simple)] + #[pallet::call] + impl Pallet { + pub fn do_something(_origin: OriginFor) -> DispatchResult { + // ^^^^^^^^^^^^^^^^^^^^^ + todo!(); + } + } +} + +#[frame::pallet(dev_mode)] +pub mod pallet_with_custom_origin { + use super::*; + + #[docify::export(custom_origin_bound)] + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeOrigin: From<::RuntimeOrigin> + + Into::RuntimeOrigin>>; + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[docify::export(custom_origin)] + /// A dummy custom origin. + #[pallet::origin] + #[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] + pub enum Origin { + /// If all holders of a particular NFT have agreed upon this. + AllNftHolders, + /// If all validators have agreed upon this. + ValidatorSet, + } + + #[docify::export(custom_origin_usage)] + #[pallet::call] + impl Pallet { + pub fn only_validators(origin: OriginFor) -> DispatchResult { + // first, we convert from `::RuntimeOrigin` to `::RuntimeOrigin` + let local_runtime_origin = <::RuntimeOrigin as From< + ::RuntimeOrigin, + >>::from(origin); + // then we convert to `origin`, if possible + let local_origin = + local_runtime_origin.into().map_err(|_| "invalid origin type provided")?; + ensure!(matches!(local_origin, Origin::ValidatorSet), "Not authorized"); + todo!(); + } + } +} + +pub mod runtime_for_origin { + use super::pallet_with_custom_origin; + use frame::{runtime::prelude::*, testing_prelude::*}; + + #[docify::export(runtime_exp)] + construct_runtime!( + pub struct Runtime { + System: frame_system, + PalletWithCustomOrigin: pallet_with_custom_origin, + } + ); + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Runtime { + type Block = MockBlock; + } + + impl pallet_with_custom_origin::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + } +} + +#[frame::pallet(dev_mode)] +pub mod pallet_with_external_origin { + use super::*; + #[docify::export(external_origin_def)] + #[pallet::config] + pub trait Config: frame_system::Config { + type ExternalOrigin: EnsureOrigin; + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[docify::export(external_origin_usage)] + #[pallet::call] + impl Pallet { + pub fn externally_checked_ext(origin: OriginFor) -> DispatchResult { + let _ = T::ExternalOrigin::ensure_origin(origin)?; + todo!(); + } + } +} + +pub mod runtime_for_external_origin { + use super::*; + use frame::{runtime::prelude::*, testing_prelude::*}; + + construct_runtime!( + pub struct Runtime { + System: frame_system, + PalletWithExternalOrigin: pallet_with_external_origin, + } + ); + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Runtime { + type Block = MockBlock; + } + + #[docify::export(external_origin_provide)] + impl pallet_with_external_origin::Config for Runtime { + type ExternalOrigin = EnsureSigned<::AccountId>; + } +} diff --git a/docs/sdk/src/reference_docs/frame_runtime_types.rs b/docs/sdk/src/reference_docs/frame_runtime_types.rs new file mode 100644 index 00000000000..b5838b79e51 --- /dev/null +++ b/docs/sdk/src/reference_docs/frame_runtime_types.rs @@ -0,0 +1,306 @@ +//! # FRAME Runtime Types +//! +//! This reference document briefly explores the idea around types generated at the runtime level by +//! the FRAME macros. +//! +//! > As of now, many of these important types are generated within the internals of +//! > [`construct_runtime`], and there is no easy way for you to visually know they exist. +//! > [#polkadot-sdk#1378](https://github.com/paritytech/polkadot-sdk/pull/1378) is meant to +//! > significantly improve this. Exploring the rust-docs of a runtime, such as [`runtime`] which is +//! > defined in this module is as of now the best way to learn about these types. +//! +//! ## Composite Enums +//! +//! Many types within a FRAME runtime follow the following structure: +//! +//! * Each individual pallet defines a type, for example `Foo`. +//! * At the runtime level, these types are amalgamated into a single type, for example +//! `RuntimeFoo`. +//! +//! As the names suggest, all composite enums in a FRAME runtime start their name with `Runtime`. +//! For example, `RuntimeCall` is a representation of the most high level `Call`-able type in the +//! runtime. +//! +//! Composite enums are generally convertible to their individual parts as such: +#![doc = simple_mermaid::mermaid!("../../../mermaid/outer_runtime_types.mmd")] +//! +//! In that one can always convert from the inner type into the outer type, but not vice versa. This +//! is usually expressed by implementing `From`, `TryFrom`, `From>` and similar traits. +//! +//! ### Example +//! +//! We provide the following two pallets: [`pallet_foo`] and [`pallet_bar`]. Each define a +//! dispatchable, and `Foo` also defines a custom origin. Lastly, `Bar` defines an additional +//! `GenesisConfig`. +#![doc = docify::embed!("./src/reference_docs/frame_runtime_types.rs", pallet_foo)] +#![doc = docify::embed!("./src/reference_docs/frame_runtime_types.rs", pallet_bar)] +//! +//! Let's explore how each of these affect the [`RuntimeCall`], [`RuntimeOrigin`] and +//! [`RuntimeGenesisConfig`] generated in [`runtime`] by respectively. +//! +//! As observed, [`RuntimeCall`] has 3 variants, one for each pallet and one for `frame_system`. If +//! you explore further, you will soon realize that each variant is merely a pointer to the `Call` +//! type in each pallet, for example [`pallet_foo::Call`]. +//! +//! [`RuntimeOrigin`]'s [`OriginCaller`] has two variants, one for system, and one for `pallet_foo` +//! which utilized [`frame::pallet_macros::origin`]. +//! +//! Finally, [`RuntimeGenesisConfig`] is composed of `frame_system` and a variant for `pallet_bar`'s +//! [`pallet_bar::GenesisConfig`]. +//! +//! You can find other composite enums by scanning [`runtime`] for other types who's name starts +//! with `Runtime`. Some of the more noteworthy ones are: +//! +//! - [`RuntimeEvent`] +//! - [`RuntimeError`] +//! - [`RuntimeHoldReason`] +//! +//! ### Adding Further Constraints to Runtime Composite Enums +//! +//! This section explores a common scenario where a pallet has access to one of these runtime +//! composite enums, but it wishes to further specify it by adding more trait bounds to it. +//! +//! Let's take the example of `RuntimeCall`. This is an associated type in +//! [`frame_system::Config::RuntimeCall`], and all pallets have access to this type, because they +//! have access to [`frame_system::Config`]. Finally, this type is meant to be set to outer call of +//! the entire runtime. +//! +//! But, let's not forget that this is information that *we know*, and the Rust compiler does not. +//! All that the rust compiler knows about this type is *ONLY* what the trait bounds of +//! [`frame_system::Config::RuntimeCall`] are specifying: +#![doc = docify::embed!("../../substrate/frame/system/src/lib.rs", system_runtime_call)] +//! +//! So, when at a given pallet, one accesses `::RuntimeCall`, the type is +//! extremely opaque from the perspective of the Rust compiler. +//! +//! How can a pallet access the `RuntimeCall` type with further constraints? For example, each +//! pallet has its own `enum Call`, and knows that its local `Call` is a part of `RuntimeCall`, +//! therefore there should be a `impl From> for RuntimeCall`. +//! +//! The only way to express this using Rust's associated types is for the pallet to **define its own +//! associated type `RuntimeCall`, and further specify what it thinks `RuntimeCall` should be**. +//! +//! In this case, we will want to assert the existence of [`frame::traits::IsSubType`], which is +//! very similar to [`TryFrom`]. +#![doc = docify::embed!("./src/reference_docs/frame_runtime_types.rs", custom_runtime_call)] +//! +//! And indeed, at the runtime level, this associated type would be the same `RuntimeCall` that is +//! passed to `frame_system`. +#![doc = docify::embed!("./src/reference_docs/frame_runtime_types.rs", pallet_with_specific_runtime_call_impl)] +//! +//! > In other words, the degree of specificity that [`frame_system::Config::RuntimeCall`] has is +//! > not enough for the pallet to work with. Therefore, the pallet has to define its own associated +//! > type representing `RuntimeCall`. +//! +//! Another way to look at this is: +//! +//! `pallet_with_specific_runtime_call::Config::RuntimeCall` and `frame_system::Config::RuntimeCall` +//! are two different representations of the same concrete type that is only known when the runtime +//! is being constructed. +//! +//! Now, within this pallet, this new `RuntimeCall` can be used, and it can use its new trait +//! bounds, such as being [`frame::traits::IsSubType`]: +#![doc = docify::embed!("./src/reference_docs/frame_runtime_types.rs", custom_runtime_call_usages)] +//! +//! ### Asserting Equality of Multiple Runtime Composite Enums +//! +//! Recall that in the above example, `::RuntimeCall` and `::RuntimeCall` are expected to be equal types, but at the compile-time we +//! have to represent them with two different associated types with different bounds. Would it not +//! be cool if we had a test to make sure they actually resolve to the same concrete type once the +//! runtime is constructed? The following snippet exactly does that: +#![doc = docify::embed!("./src/reference_docs/frame_runtime_types.rs", assert_equality)] +//! +//! We leave it to the reader to further explore what [`frame::traits::Hooks::integrity_test`] is, +//! and what [`core::any::TypeId`] is. Another way to assert this is using +//! [`frame::traits::IsType`]. +//! +//! ## Type Aliases +//! +//! A number of type aliases are generated by the `construct_runtime` which are also noteworthy: +//! +//! * [`runtime::PalletFoo`] is an alias to [`pallet_foo::Pallet`]. Same for `PalletBar`, and +//! `System` +//! * [`runtime::AllPalletsWithSystem`] is an alias for a tuple of all of the above. This type is +//! important to FRAME internals such as `executive`, as it implements traits such as +//! [`frame::traits::Hooks`]. +//! +//! ## Further Details +//! +//! * [`crate::reference_docs::frame_origin`] explores further details about the usage of +//! `RuntimeOrigin`. +//! * [`RuntimeCall`] is a particularly interesting composite enum as it dictates the encoding of an +//! extrinsic. See [`crate::reference_docs::signed_extensions`] for more information. +//! * See the documentation of [`construct_runtime`]. +//! * See the corresponding lecture in the [pba-book](https://polkadot-blockchain-academy.github.io/pba-book/frame/outer-enum/page.html). +//! +//! +//! [`construct_runtime`]: frame::runtime::prelude::construct_runtime +//! [`runtime::PalletFoo`]: crate::reference_docs::frame_runtime_types::runtime::PalletFoo +//! [`runtime::AllPalletsWithSystem`]: crate::reference_docs::frame_runtime_types::runtime::AllPalletsWithSystem +//! [`runtime`]: crate::reference_docs::frame_runtime_types::runtime +//! [`pallet_foo`]: crate::reference_docs::frame_runtime_types::pallet_foo +//! [`pallet_foo::Call`]: crate::reference_docs::frame_runtime_types::pallet_foo::Call +//! [`pallet_foo::Pallet`]: crate::reference_docs::frame_runtime_types::pallet_foo::Pallet +//! [`pallet_bar`]: crate::reference_docs::frame_runtime_types::pallet_bar +//! [`pallet_bar::GenesisConfig`]: crate::reference_docs::frame_runtime_types::pallet_bar::GenesisConfig +//! [`RuntimeEvent`]: crate::reference_docs::frame_runtime_types::runtime::RuntimeEvent +//! [`RuntimeGenesisConfig`]: +//! crate::reference_docs::frame_runtime_types::runtime::RuntimeGenesisConfig +//! [`RuntimeOrigin`]: crate::reference_docs::frame_runtime_types::runtime::RuntimeOrigin +//! [`OriginCaller`]: crate::reference_docs::frame_runtime_types::runtime::OriginCaller +//! [`RuntimeError`]: crate::reference_docs::frame_runtime_types::runtime::RuntimeError +//! [`RuntimeCall`]: crate::reference_docs::frame_runtime_types::runtime::RuntimeCall +//! [`RuntimeHoldReason`]: crate::reference_docs::frame_runtime_types::runtime::RuntimeHoldReason + +use frame::prelude::*; + +#[docify::export] +#[frame::pallet(dev_mode)] +pub mod pallet_foo { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::origin] + #[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] + pub enum Origin { + A, + B, + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call] + impl Pallet { + pub fn foo(_origin: OriginFor) -> DispatchResult { + todo!(); + } + + pub fn other(_origin: OriginFor) -> DispatchResult { + todo!(); + } + } +} + +#[docify::export] +#[frame::pallet(dev_mode)] +pub mod pallet_bar { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::genesis_config] + #[derive(DefaultNoBound)] + pub struct GenesisConfig { + pub initial_account: Option, + } + + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) {} + } + + #[pallet::call] + impl Pallet { + pub fn bar(_origin: OriginFor) -> DispatchResult { + todo!(); + } + } +} + +pub mod runtime { + use super::{pallet_bar, pallet_foo}; + use frame::{runtime::prelude::*, testing_prelude::*}; + + #[docify::export(runtime_exp)] + construct_runtime!( + pub struct Runtime { + System: frame_system, + PalletFoo: pallet_foo, + PalletBar: pallet_bar, + } + ); + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Runtime { + type Block = MockBlock; + } + + impl pallet_foo::Config for Runtime {} + impl pallet_bar::Config for Runtime {} +} + +#[frame::pallet(dev_mode)] +pub mod pallet_with_specific_runtime_call { + use super::*; + use frame::traits::IsSubType; + + #[docify::export(custom_runtime_call)] + /// A pallet that wants to further narrow down what `RuntimeCall` is. + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeCall: IsSubType>; + } + + #[pallet::pallet] + pub struct Pallet(_); + + // note that this pallet needs some `call` to have a `enum Call`. + #[pallet::call] + impl Pallet { + pub fn foo(_origin: OriginFor) -> DispatchResult { + todo!(); + } + } + + #[docify::export(custom_runtime_call_usages)] + impl Pallet { + fn _do_something_useful_with_runtime_call(call: ::RuntimeCall) { + // check if the runtime call given is of this pallet's variant. + let _maybe_my_call: Option<&Call> = call.is_sub_type(); + todo!(); + } + } + + #[docify::export(assert_equality)] + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + use core::any::TypeId; + assert_eq!( + TypeId::of::<::RuntimeCall>(), + TypeId::of::<::RuntimeCall>() + ); + } + } +} + +pub mod runtime_with_specific_runtime_call { + use super::pallet_with_specific_runtime_call; + use frame::{runtime::prelude::*, testing_prelude::*}; + + construct_runtime!( + pub struct Runtime { + System: frame_system, + PalletWithSpecificRuntimeCall: pallet_with_specific_runtime_call, + } + ); + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Runtime { + type Block = MockBlock; + } + + #[docify::export(pallet_with_specific_runtime_call_impl)] + impl pallet_with_specific_runtime_call::Config for Runtime { + // an implementation of `IsSubType` is provided by `construct_runtime`. + type RuntimeCall = RuntimeCall; + } +} diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index c16122ee428..760bb442c16 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -43,16 +43,16 @@ pub mod extrinsic_encoding; // TODO: @jsdw https://github.com/paritytech/polkadot-sdk-docs/issues/42 pub mod signed_extensions; -/// Learn about *"Origin"* A topic in FRAME that enables complex account abstractions to be built. -// TODO: @shawntabrizi https://github.com/paritytech/polkadot-sdk-docs/issues/43 +/// Learn about *Origins*, a topic in FRAME that enables complex account abstractions to be built. pub mod frame_origin; /// Learn about how to write safe and defensive code in your FRAME runtime. // TODO: @CrackTheCode016 https://github.com/paritytech/polkadot-sdk-docs/issues/44 pub mod safe_defensive_programming; -/// Learn about composite enums in FRAME-based runtimes, such as "RuntimeEvent" and "RuntimeCall". -pub mod frame_composite_enums; +/// Learn about composite enums and other runtime level types, such as "RuntimeEvent" and +/// "RuntimeCall". +pub mod frame_runtime_types; /// Learn about how to make a pallet/runtime that is fee-less and instead uses another mechanism to /// control usage and sybil attacks. diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs index a1715ba4900..a2e5d726fdd 100644 --- a/substrate/frame/src/lib.rs +++ b/substrate/frame/src/lib.rs @@ -163,6 +163,12 @@ pub mod runtime { ConstU32, ConstU64, ConstU8, }; + /// Primary types used to parameterize `EnsureOrigin` and `EnsureRootWithArg`. + pub use frame_system::{ + EnsureNever, EnsureNone, EnsureRoot, EnsureRootWithSuccess, EnsureSigned, + EnsureSignedBy, + }; + /// Types to define your runtime version. pub use sp_version::{create_runtime_str, runtime_version, RuntimeVersion}; diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs index b421d2aaffa..83049919d01 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -104,7 +104,7 @@ pub fn expand_outer_origin( #[doc = #doc_string] #[derive(Clone)] pub struct RuntimeOrigin { - caller: OriginCaller, + pub caller: OriginCaller, filter: #scrate::__private::sp_std::rc::Rc::RuntimeCall) -> bool>>, } diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 20b8d74310f..441b21e26ff 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1480,22 +1480,11 @@ pub fn validate_unsigned(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The `#[pallet::origin]` attribute allows you to define some origin for the pallet. /// -/// Item must be either a type alias, an enum, or a struct. It needs to be public. -/// -/// E.g.: -/// -/// ```ignore -/// #[pallet::origin] -/// pub struct Origin(PhantomData<(T)>); -/// ``` -/// -/// **WARNING**: modifying origin changes the outer runtime origin. This outer runtime origin -/// can be stored on-chain (e.g. in `pallet-scheduler`), thus any change must be done with care -/// as it might require some migration. +/// --- /// -/// NOTE: for instantiable pallets, the origin must be generic over `T` and `I`. +/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// `frame_support::pallet_macros::origin`. #[proc_macro_attribute] pub fn origin(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index cd12da6de54..26fc1fe42c1 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -2274,9 +2274,8 @@ pub mod pallet_macros { pub use frame_support_procedural::{ composite_enum, config, disable_frame_system_supertrait_check, error, event, extra_constants, feeless_if, generate_deposit, generate_store, getter, hooks, - import_section, inherent, no_default, no_default_bounds, origin, pallet_section, - storage_prefix, storage_version, type_value, unbounded, validate_unsigned, weight, - whitelist_storage, + import_section, inherent, no_default, no_default_bounds, pallet_section, storage_prefix, + storage_version, type_value, unbounded, validate_unsigned, weight, whitelist_storage, }; /// Allows a pallet to declare a set of functions as a *dispatchable extrinsic*. In @@ -2718,7 +2717,7 @@ pub mod pallet_macros { /// } /// ``` pub use frame_support_procedural::storage; - /// This attribute is attached to a function inside an `impl` block annoated with + /// This attribute is attached to a function inside an `impl` block annotated with /// [`pallet::tasks_experimental`](`tasks_experimental`) to define the conditions for a /// given work item to be valid. /// @@ -2726,21 +2725,21 @@ pub mod pallet_macros { /// should have the same signature as the function it is attached to, except that it should /// return a `bool` instead. pub use frame_support_procedural::task_condition; - /// This attribute is attached to a function inside an `impl` block annoated with + /// This attribute is attached to a function inside an `impl` block annotated with /// [`pallet::tasks_experimental`](`tasks_experimental`) to define the index of a given /// work item. /// /// It takes an integer literal as input, which is then used to define the index. This /// index should be unique for each function in the `impl` block. pub use frame_support_procedural::task_index; - /// This attribute is attached to a function inside an `impl` block annoated with + /// This attribute is attached to a function inside an `impl` block annotated with /// [`pallet::tasks_experimental`](`tasks_experimental`) to define an iterator over the /// available work items for a task. /// /// It takes an iterator as input that yields a tuple with same types as the function /// arguments. pub use frame_support_procedural::task_list; - /// This attribute is attached to a function inside an `impl` block annoated with + /// This attribute is attached to a function inside an `impl` block annotated with /// [`pallet::tasks_experimental`](`tasks_experimental`) define the weight of a given work /// item. /// @@ -2773,6 +2772,61 @@ pub mod pallet_macros { /// Now, this can be executed as follows: #[doc = docify::embed!("src/tests/tasks.rs", tasks_work)] pub use frame_support_procedural::tasks_experimental; + + /// Allows a pallet to declare a type as an origin. + /// + /// If defined as such, this type will be amalgamated at the runtime level into + /// `RuntimeOrigin`, very similar to [`call`], [`error`] and [`event`]. See + /// [`composite_enum`] for similar cases. + /// + /// Origin is a complex FRAME topics and is further explained in `polkadot_sdk_docs`. + /// + /// ## Syntax Variants + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// # #[pallet::pallet] + /// # pub struct Pallet(_); + /// /// On the spot declaration. + /// #[pallet::origin] + /// #[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] + /// pub enum Origin { + /// Foo, + /// Bar, + /// } + /// } + /// ``` + /// + /// Or, more commonly used:/ + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// # #[pallet::pallet] + /// # pub struct Pallet(_); + /// #[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] + /// pub enum RawOrigin { + /// Foo, + /// Bar, + /// } + /// + /// #[pallet::origin] + /// pub type Origin = RawOrigin; + /// } + /// ``` + /// + /// ## Warning + /// + /// Modifying any pallet's origin type will cause the runtime level origin type to also + /// change in encoding. If stored anywhere on-chain, this will require a data migration. + pub use frame_support_procedural::origin; } #[deprecated(note = "Will be removed after July 2023; Use `sp_runtime::traits` directly instead.")] diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 1405c7303f8..aa6841c008a 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -452,6 +452,7 @@ pub mod pallet { + Clone + OriginTrait; + #[docify::export(system_runtime_call)] /// The aggregated `RuntimeCall` type. #[pallet::no_default_bounds] type RuntimeCall: Parameter -- GitLab From 0cc9b9003c019400a8e26c2e1d5679ab654a63dc Mon Sep 17 00:00:00 2001 From: Petr Mensik Date: Tue, 27 Feb 2024 23:50:07 +0100 Subject: [PATCH 037/188] Add Polkadotters bootnoders per IBP application (#3423) Hey everyone, this PR will replace existing Polkadotters bootnodes for Polkadot, Kusama and Westend and add Paseo bootnode to the relay chain suite. At the same time, it will add new bootnodes for all the system parachains, including People on Westend. This PR is a part of our membership in the IBP, meaning that all the bootnodes are hosted on our hardware housed in the data center in Christchurch, New Zealand. All the bootnodes were tested with an empty chain spec file with the following command yielding 1 peer. The test commands used are as follows: ``` ./polkadot --base-path /tmp/node --reserved-only --chain paseo --reserved-nodes "/dns/paseo.bootnodes.polkadotters.com/tcp/30540/wss/p2p/12D3KooWPbbFy4TefEGTRF5eTYhq8LEzc4VAHdNUVCbY4nAnhqPP" ./polkadot --base-path /tmp/node --reserved-only --chain westend --reserved-nodes "/dns/westend.bootnodes.polkadotters.com/tcp/30310/wss/p2p/12D3KooWHPHb64jXMtSRJDrYFATWeLnvChL8NtWVttY67DCH1eC5" ./polkadot --base-path /tmp/node --reserved-only --chain kusama --reserved-nodes "/dns/kusama.bootnodes.polkadotters.com/tcp/30313/wss/p2p/12D3KooWHB5rTeNkQdXNJ9ynvGz8Lpnmsctt7Tvp7mrYv6bcwbPG" ./polkadot --base-path /tmp/node --no-hardware-benchmarks --reserved-only --chain polkadot --reserved-nodes "/dns/polkadot.bootnodes.polkadotters.com/tcp/30316/wss/p2p/12D3KooWPAVUgBaBk6n8SztLrMk8ESByncbAfRKUdxY1nygb9zG3" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain asset-hub-kusama --reserved-nodes "/dns/asset-hub-kusama.bootnodes.polkadotters.com/tcp/30513/wss/p2p/12D3KooWDpk7wVH7RgjErEvbvAZ2kY5VeaAwRJP5ojmn1e8b8UbU" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain asset-hub-polkadot --reserved-nodes "/dns/asset-hub-polkadot.bootnodes.polkadotters.com/tcp/30510/wss/p2p/12D3KooWKbfY9a9oywxMJKiALmt7yhrdQkjXMtvxhhDDN23vG93R" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain asset-hub-westend --reserved-nodes "/dns/asset-hub-westend.bootnodes.polkadotters.com/tcp/30516/wss/p2p/12D3KooWNFYysCqmojxqjjaTfD2VkWBNngfyUKWjcR4WFixfHNTk" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain bridge-hub-kusama --reserved-nodes "/dns/bridge-hub-kusama.bootnodes.polkadotters.com/tcp/30522/wss/p2p/12D3KooWH3pucezRRS5esoYyzZsUkKWcPSByQxEvmM819QL1HPLV" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain bridge-hub-kusama --reserved-nodes "/dns/bridge-hub-kusama.bootnodes.polkadotters.com/tcp/30522/wss/p2p/12D3KooWH3pucezRRS5esoYyzZsUkKWcPSByQxEvmM819QL1HPLV" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain bridge-hub-westend --reserved-nodes "/dns/bridge-hub-westend.bootnodes.polkadotters.com/tcp/30525/wss/p2p/12D3KooWPkwgJofp4GeeRwNgXqkp2aFwdLkCWv3qodpBJLwK43Jj" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain collectives-polkadot --reserved-nodes "/dns/collectives-polkadot.bootnodes.polkadotters.com/tcp/30528/wss/p2p/12D3KooWNohUjvJtGKUa8Vhy8C1ZBB5N8JATB6e7rdLVCioeb3ff" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain collectives-westend --reserved-nodes "/dns/collectives-westend.bootnodes.polkadotters.com/tcp/30531/wss/p2p/12D3KooWAFkXNSBfyPduZVgfS7pj5NuVpbU8Ee5gHeF8wvos7Yqn" ./polkadot-parachain --base-path /tmp/node --reserved-only --chain people-westend --reserved-nodes "/dns/identity-westend.bootnodes.polkadotters.com/tcp/30534/wss/p2p/12D3KooWKr9San6KTM7REJ95cBaDoiciGcWnW8TTftEJgxGF5Ehb" ``` Best regards, Petr, Polkadotters --- cumulus/parachains/chain-specs/asset-hub-kusama.json | 4 +++- cumulus/parachains/chain-specs/asset-hub-polkadot.json | 4 +++- cumulus/parachains/chain-specs/asset-hub-westend.json | 4 +++- cumulus/parachains/chain-specs/bridge-hub-kusama.json | 4 +++- cumulus/parachains/chain-specs/bridge-hub-polkadot.json | 4 +++- cumulus/parachains/chain-specs/bridge-hub-westend.json | 4 +++- cumulus/parachains/chain-specs/collectives-polkadot.json | 4 +++- cumulus/parachains/chain-specs/collectives-westend.json | 4 +++- cumulus/parachains/chain-specs/people-westend.json | 6 ++++-- polkadot/node/service/chain-specs/kusama.json | 4 ++-- polkadot/node/service/chain-specs/paseo.json | 4 +++- polkadot/node/service/chain-specs/polkadot.json | 4 ++-- polkadot/node/service/chain-specs/westend.json | 4 ++-- 13 files changed, 37 insertions(+), 17 deletions(-) diff --git a/cumulus/parachains/chain-specs/asset-hub-kusama.json b/cumulus/parachains/chain-specs/asset-hub-kusama.json index fba74b17f96..654275eade8 100644 --- a/cumulus/parachains/chain-specs/asset-hub-kusama.json +++ b/cumulus/parachains/chain-specs/asset-hub-kusama.json @@ -25,7 +25,9 @@ "/dns/statemine-bootnode.radiumblock.com/tcp/30336/wss/p2p/12D3KooWCKUrE5uaXQ288ko3Ex3zCyozyJLG47KEYTopinnXNtYL", "/dns/mine14.rotko.net/tcp/33524/p2p/12D3KooWJUFnjR2PNbsJhudwPVaWCoZy1acPGKjM2cSuGj345BBu", "/dns/mine14.rotko.net/tcp/34524/ws/p2p/12D3KooWJUFnjR2PNbsJhudwPVaWCoZy1acPGKjM2cSuGj345BBu", - "/dns/mine14.rotko.net/tcp/35524/wss/p2p/12D3KooWJUFnjR2PNbsJhudwPVaWCoZy1acPGKjM2cSuGj345BBu" + "/dns/mine14.rotko.net/tcp/35524/wss/p2p/12D3KooWJUFnjR2PNbsJhudwPVaWCoZy1acPGKjM2cSuGj345BBu", + "/dns/asset-hub-kusama.bootnodes.polkadotters.com/tcp/30511/p2p/12D3KooWDpk7wVH7RgjErEvbvAZ2kY5VeaAwRJP5ojmn1e8b8UbU", + "/dns/asset-hub-kusama.bootnodes.polkadotters.com/tcp/30513/wss/p2p/12D3KooWDpk7wVH7RgjErEvbvAZ2kY5VeaAwRJP5ojmn1e8b8UbU" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/asset-hub-polkadot.json b/cumulus/parachains/chain-specs/asset-hub-polkadot.json index 685a00ddc71..454060d2a87 100644 --- a/cumulus/parachains/chain-specs/asset-hub-polkadot.json +++ b/cumulus/parachains/chain-specs/asset-hub-polkadot.json @@ -25,7 +25,9 @@ "/dns/statemint-bootnode.radiumblock.com/tcp/30333/p2p/12D3KooWLKxHom7f3XawRJqrF8RwiKK5Sj3qZqz5c7hF6eJeXhTx", "/dns/mint14.rotko.net/tcp/33514/p2p/12D3KooWKkzLjYF6M5eEs7nYiqEtRqY8SGVouoCwo3nCWsRnThDW", "/dns/mint14.rotko.net/tcp/34514/ws/p2p/12D3KooWKkzLjYF6M5eEs7nYiqEtRqY8SGVouoCwo3nCWsRnThDW", - "/dns/mint14.rotko.net/tcp/35514/wss/p2p/12D3KooWKkzLjYF6M5eEs7nYiqEtRqY8SGVouoCwo3nCWsRnThDW" + "/dns/mint14.rotko.net/tcp/35514/wss/p2p/12D3KooWKkzLjYF6M5eEs7nYiqEtRqY8SGVouoCwo3nCWsRnThDW", + "/dns/asset-hub-polkadot.bootnodes.polkadotters.com/tcp/30508/p2p/12D3KooWKbfY9a9oywxMJKiALmt7yhrdQkjXMtvxhhDDN23vG93R", + "/dns/asset-hub-polkadot.bootnodes.polkadotters.com/tcp/30510/wss/p2p/12D3KooWKbfY9a9oywxMJKiALmt7yhrdQkjXMtvxhhDDN23vG93R" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/asset-hub-westend.json b/cumulus/parachains/chain-specs/asset-hub-westend.json index 6f42b5f7d8b..670935c9d24 100644 --- a/cumulus/parachains/chain-specs/asset-hub-westend.json +++ b/cumulus/parachains/chain-specs/asset-hub-westend.json @@ -23,7 +23,9 @@ "/dns/westmint-bootnode.radiumblock.com/tcp/30333/p2p/12D3KooWDoq4PVdWm5nzRSvEz3DSSKjVgRhWVUaKyi5JMKwJKYbk", "/dns/wmint14.rotko.net/tcp/33534/p2p/12D3KooWE4UDXqgtTcMCyUQ8S4uvaT8VMzzTBA6NWmKuYwTacWuN", "/dns/wmint14.rotko.net/tcp/34534/ws/p2p/12D3KooWE4UDXqgtTcMCyUQ8S4uvaT8VMzzTBA6NWmKuYwTacWuN", - "/dns/wmint14.rotko.net/tcp/35534/wss/p2p/12D3KooWE4UDXqgtTcMCyUQ8S4uvaT8VMzzTBA6NWmKuYwTacWuN" + "/dns/wmint14.rotko.net/tcp/35534/wss/p2p/12D3KooWE4UDXqgtTcMCyUQ8S4uvaT8VMzzTBA6NWmKuYwTacWuN", + "/dns/asset-hub-westend.bootnodes.polkadotters.com/tcp/30514/p2p/12D3KooWNFYysCqmojxqjjaTfD2VkWBNngfyUKWjcR4WFixfHNTk", + "/dns/asset-hub-westend.bootnodes.polkadotters.com/tcp/30516/wss/p2p/12D3KooWNFYysCqmojxqjjaTfD2VkWBNngfyUKWjcR4WFixfHNTk" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/bridge-hub-kusama.json b/cumulus/parachains/chain-specs/bridge-hub-kusama.json index 0ef81806cc5..90b70b05016 100644 --- a/cumulus/parachains/chain-specs/bridge-hub-kusama.json +++ b/cumulus/parachains/chain-specs/bridge-hub-kusama.json @@ -25,7 +25,9 @@ "/dns/bridgehub-kusama-bootnode.radiumblock.com/tcp/30336/wss/p2p/12D3KooWQMWofXj8v3RroDNnrhv1iURqm8vnaG98AdGnCn2YoDcW", "/dns/kbr13.rotko.net/tcp/33553/p2p/12D3KooWAmBp54mUEYtvsk2kxNEsDbAvdUMcaghxKXgUQxmPEQ66", "/dns/kbr13.rotko.net/tcp/34553/ws/p2p/12D3KooWAmBp54mUEYtvsk2kxNEsDbAvdUMcaghxKXgUQxmPEQ66", - "/dns/kbr13.rotko.net/tcp/35553/wss/p2p/12D3KooWAmBp54mUEYtvsk2kxNEsDbAvdUMcaghxKXgUQxmPEQ66" + "/dns/kbr13.rotko.net/tcp/35553/wss/p2p/12D3KooWAmBp54mUEYtvsk2kxNEsDbAvdUMcaghxKXgUQxmPEQ66", + "/dns/bridge-hub-kusama.bootnodes.polkadotters.com/tcp/30520/p2p/12D3KooWH3pucezRRS5esoYyzZsUkKWcPSByQxEvmM819QL1HPLV", + "/dns/bridge-hub-kusama.bootnodes.polkadotters.com/tcp/30522/wss/p2p/12D3KooWH3pucezRRS5esoYyzZsUkKWcPSByQxEvmM819QL1HPLV" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/bridge-hub-polkadot.json b/cumulus/parachains/chain-specs/bridge-hub-polkadot.json index 130bdf31ef2..a9444b89e1e 100644 --- a/cumulus/parachains/chain-specs/bridge-hub-polkadot.json +++ b/cumulus/parachains/chain-specs/bridge-hub-polkadot.json @@ -21,7 +21,9 @@ "/dns/bridgehub-polkadot-bootnode.radiumblock.com/tcp/30333/p2p/12D3KooWPNZm78tWUmKbta3SXdkqTPsquRc8ekEbJjZsGGi7YiRi", "/dns/pbr13.rotko.net/tcp/33543/p2p/12D3KooWMxZY7tDc2Rh454VaJJ7RexKAXVS6xSBEvTnXSGCnuGDw", "/dns/pbr13.rotko.net/tcp/34543/ws/p2p/12D3KooWMxZY7tDc2Rh454VaJJ7RexKAXVS6xSBEvTnXSGCnuGDw", - "/dns/pbr13.rotko.net/tcp/35543/wss/p2p/12D3KooWMxZY7tDc2Rh454VaJJ7RexKAXVS6xSBEvTnXSGCnuGDw" + "/dns/pbr13.rotko.net/tcp/35543/wss/p2p/12D3KooWMxZY7tDc2Rh454VaJJ7RexKAXVS6xSBEvTnXSGCnuGDw", + "/dns/bridge-hub-polkadot.bootnodes.polkadotters.com/tcp/30517/p2p/12D3KooWLUNE3LHPDa1WrrZaYT7ArK66CLM1bPv7kKz74UcLnQRB", + "/dns/bridge-hub-polkadot.bootnodes.polkadotters.com/tcp/30519/wss/p2p/12D3KooWLUNE3LHPDa1WrrZaYT7ArK66CLM1bPv7kKz74UcLnQRB" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/bridge-hub-westend.json b/cumulus/parachains/chain-specs/bridge-hub-westend.json index 018ab0ee6fd..447207a5810 100644 --- a/cumulus/parachains/chain-specs/bridge-hub-westend.json +++ b/cumulus/parachains/chain-specs/bridge-hub-westend.json @@ -19,7 +19,9 @@ "/dns/bridgehub-westend-bootnode.radiumblock.com/tcp/30336/wss/p2p/12D3KooWBsBArCMxmQyo3feCEqMWuwyhb2LTRK8hmCCJxgrNeMke", "/dns/wbr13.rotko.net/tcp/33563/p2p/12D3KooWJyeRHpxZZbfBCNEgeUFzmRC5AMSAs2tJhjJS1k5hULkD", "/dns/wbr13.rotko.net/tcp/34563/ws/p2p/12D3KooWJyeRHpxZZbfBCNEgeUFzmRC5AMSAs2tJhjJS1k5hULkD", - "/dns/wbr13.rotko.net/tcp/35563/wss/p2p/12D3KooWJyeRHpxZZbfBCNEgeUFzmRC5AMSAs2tJhjJS1k5hULkD" + "/dns/wbr13.rotko.net/tcp/35563/wss/p2p/12D3KooWJyeRHpxZZbfBCNEgeUFzmRC5AMSAs2tJhjJS1k5hULkD", + "/dns/bridge-hub-westend.bootnodes.polkadotters.com/tcp/30523/p2p/12D3KooWPkwgJofp4GeeRwNgXqkp2aFwdLkCWv3qodpBJLwK43Jj", + "/dns/bridge-hub-westend.bootnodes.polkadotters.com/tcp/30525/wss/p2p/12D3KooWPkwgJofp4GeeRwNgXqkp2aFwdLkCWv3qodpBJLwK43Jj" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/collectives-polkadot.json b/cumulus/parachains/chain-specs/collectives-polkadot.json index e9f690234e4..259669cf37a 100644 --- a/cumulus/parachains/chain-specs/collectives-polkadot.json +++ b/cumulus/parachains/chain-specs/collectives-polkadot.json @@ -25,7 +25,9 @@ "/dns/collectives-polkadot-bootnode.radiumblock.com/tcp/30336/wss/p2p/12D3KooWDumvnNwPbBg5inBEapgjKU7ECdMHHgwfYeGWUkzYUE1c", "/dns/pch13.rotko.net/tcp/33573/p2p/12D3KooWRXudHoazPZ9osMfdY38e8CBxQLD4RhrVeHpRSNNpcDtH", "/dns/pch13.rotko.net/tcp/34573/ws/p2p/12D3KooWRXudHoazPZ9osMfdY38e8CBxQLD4RhrVeHpRSNNpcDtH", - "/dns/pch13.rotko.net/tcp/35573/wss/p2p/12D3KooWRXudHoazPZ9osMfdY38e8CBxQLD4RhrVeHpRSNNpcDtH" + "/dns/pch13.rotko.net/tcp/35573/wss/p2p/12D3KooWRXudHoazPZ9osMfdY38e8CBxQLD4RhrVeHpRSNNpcDtH", + "/dns/collectives-polkadot.bootnodes.polkadotters.com/tcp/30526/p2p/12D3KooWNohUjvJtGKUa8Vhy8C1ZBB5N8JATB6e7rdLVCioeb3ff", + "/dns/collectives-polkadot.bootnodes.polkadotters.com/tcp/30528/wss/p2p/12D3KooWNohUjvJtGKUa8Vhy8C1ZBB5N8JATB6e7rdLVCioeb3ff" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/collectives-westend.json b/cumulus/parachains/chain-specs/collectives-westend.json index ffe73b5a05a..e459c631f8b 100644 --- a/cumulus/parachains/chain-specs/collectives-westend.json +++ b/cumulus/parachains/chain-specs/collectives-westend.json @@ -25,7 +25,9 @@ "/dns/westend-collectives-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWPFM93jgm4pgxx8PM8WJKAJF49qia8jRB95uciUQwYh7m", "/dns/wch13.rotko.net/tcp/33593/p2p/12D3KooWPG85zhuSRoyptjLkFD4iJFistjiBmc15JgQ96B4fdXYr", "/dns/wch13.rotko.net/tcp/34593/ws/p2p/12D3KooWPG85zhuSRoyptjLkFD4iJFistjiBmc15JgQ96B4fdXYr", - "/dns/wch13.rotko.net/tcp/35593/wss/p2p/12D3KooWPG85zhuSRoyptjLkFD4iJFistjiBmc15JgQ96B4fdXYr" + "/dns/wch13.rotko.net/tcp/35593/wss/p2p/12D3KooWPG85zhuSRoyptjLkFD4iJFistjiBmc15JgQ96B4fdXYr", + "/dns/collectives-westend.bootnodes.polkadotters.com/tcp/30529/p2p/12D3KooWAFkXNSBfyPduZVgfS7pj5NuVpbU8Ee5gHeF8wvos7Yqn", + "/dns/collectives-westend.bootnodes.polkadotters.com/tcp/30531/wss/p2p/12D3KooWAFkXNSBfyPduZVgfS7pj5NuVpbU8Ee5gHeF8wvos7Yqn" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/people-westend.json b/cumulus/parachains/chain-specs/people-westend.json index fa29853c70b..29fa0c9cde7 100644 --- a/cumulus/parachains/chain-specs/people-westend.json +++ b/cumulus/parachains/chain-specs/people-westend.json @@ -10,7 +10,9 @@ "/dns/westend-people-collator-node-2.parity-testnet.parity.io/tcp/30333/p2p/12D3KooWGVYTVKW7tYe51JvetvGvVLDPXzqQX1mueJgz14FgkmHG", "/dns/westend-people-collator-node-2.parity-testnet.parity.io/tcp/443/wss/p2p/12D3KooWGVYTVKW7tYe51JvetvGvVLDPXzqQX1mueJgz14FgkmHG", "/dns/westend-people-collator-node-3.parity-testnet.parity.io/tcp/30333/p2p/12D3KooWCF1eA2Gap69zgXD7Df3e9DqDUsGoByocggTGejoHjK23", - "/dns/westend-people-collator-node-3.parity-testnet.parity.io/tcp/443/wss/p2p/12D3KooWCF1eA2Gap69zgXD7Df3e9DqDUsGoByocggTGejoHjK23" + "/dns/westend-people-collator-node-3.parity-testnet.parity.io/tcp/443/wss/p2p/12D3KooWCF1eA2Gap69zgXD7Df3e9DqDUsGoByocggTGejoHjK23", + "/dns/identity-westend.bootnodes.polkadotters.com/tcp/30532/p2p/12D3KooWKr9San6KTM7REJ95cBaDoiciGcWnW8TTftEJgxGF5Ehb", + "/dns/identity-westend.bootnodes.polkadotters.com/tcp/30534/wss/p2p/12D3KooWKr9San6KTM7REJ95cBaDoiciGcWnW8TTftEJgxGF5Ehb" ], "telemetryEndpoints": null, "protocolId": null, @@ -79,4 +81,4 @@ "childrenDefault": {} } } -} \ No newline at end of file +} diff --git a/polkadot/node/service/chain-specs/kusama.json b/polkadot/node/service/chain-specs/kusama.json index 979550c7570..fd60cb8b6c1 100644 --- a/polkadot/node/service/chain-specs/kusama.json +++ b/polkadot/node/service/chain-specs/kusama.json @@ -16,8 +16,8 @@ "/dns/boot-node.helikon.io/tcp/7062/wss/p2p/12D3KooWL4KPqfAsPE2aY1g5Zo1CxsDwcdJ7mmAghK7cg6M2fdbD", "/dns/kusama.bootnode.amforc.com/tcp/30333/p2p/12D3KooWLx6nsj6Fpd8biP1VDyuCUjazvRiGWyBam8PsqRJkbUb9", "/dns/kusama.bootnode.amforc.com/tcp/30334/wss/p2p/12D3KooWLx6nsj6Fpd8biP1VDyuCUjazvRiGWyBam8PsqRJkbUb9", - "/dns/kusama-bootnode.polkadotters.com/tcp/30333/p2p/12D3KooWHB5rTeNkQdXNJ9ynvGz8Lpnmsctt7Tvp7mrYv6bcwbPG", - "/dns/kusama-bootnode.polkadotters.com/tcp/30334/wss/p2p/12D3KooWHB5rTeNkQdXNJ9ynvGz8Lpnmsctt7Tvp7mrYv6bcwbPG", + "/dns/kusama.bootnodes.polkadotters.com/tcp/30311/p2p/12D3KooWHB5rTeNkQdXNJ9ynvGz8Lpnmsctt7Tvp7mrYv6bcwbPG", + "/dns/kusama.bootnodes.polkadotters.com/tcp/30313/wss/p2p/12D3KooWHB5rTeNkQdXNJ9ynvGz8Lpnmsctt7Tvp7mrYv6bcwbPG", "/dns/boot-cr.gatotech.network/tcp/33200/p2p/12D3KooWRNZXf99BfzQDE1C8YhuBbuy7Sj18UEf7FNpD8egbURYD", "/dns/boot-cr.gatotech.network/tcp/35200/wss/p2p/12D3KooWRNZXf99BfzQDE1C8YhuBbuy7Sj18UEf7FNpD8egbURYD", "/dns/boot-kusama.metaspan.io/tcp/23012/p2p/12D3KooWE1tq9ZL9AAxMiUBBqy1ENmh5pwfWabnoBPMo8gFPXhn6", diff --git a/polkadot/node/service/chain-specs/paseo.json b/polkadot/node/service/chain-specs/paseo.json index c8f2b58533c..8db75ff137b 100644 --- a/polkadot/node/service/chain-specs/paseo.json +++ b/polkadot/node/service/chain-specs/paseo.json @@ -12,7 +12,9 @@ "/dns/boot-node.helikon.io/tcp/10020/p2p/12D3KooWBetfzZpf6tGihKrqCo5z854Ub4ZNAUUTRT6eYHNh7FYi", "/dns/boot-node.helikon.io/tcp/10022/wss/p2p/12D3KooWBetfzZpf6tGihKrqCo5z854Ub4ZNAUUTRT6eYHNh7FYi", "/dns/pso16.rotko.net/tcp/33246/p2p/12D3KooWRH8eBMhw8c7bucy6pJfy94q4dKpLkF3pmeGohHmemdRu", - "/dns/pso16.rotko.net/tcp/35246/wss/p2p/12D3KooWRH8eBMhw8c7bucy6pJfy94q4dKpLkF3pmeGohHmemdRu" + "/dns/pso16.rotko.net/tcp/35246/wss/p2p/12D3KooWRH8eBMhw8c7bucy6pJfy94q4dKpLkF3pmeGohHmemdRu", + "/dns/paseo.bootnodes.polkadotters.com/tcp/30538/p2p/12D3KooWPbbFy4TefEGTRF5eTYhq8LEzc4VAHdNUVCbY4nAnhqPP", + "/dns/paseo.bootnodes.polkadotters.com/tcp/30540/wss/p2p/12D3KooWPbbFy4TefEGTRF5eTYhq8LEzc4VAHdNUVCbY4nAnhqPP" ], "telemetryEndpoints": [ [ diff --git a/polkadot/node/service/chain-specs/polkadot.json b/polkadot/node/service/chain-specs/polkadot.json index 71dbb900403..c235cdd09d8 100644 --- a/polkadot/node/service/chain-specs/polkadot.json +++ b/polkadot/node/service/chain-specs/polkadot.json @@ -17,8 +17,8 @@ "/dns/boot-node.helikon.io/tcp/7072/wss/p2p/12D3KooWS9ZcvRxyzrSf6p63QfTCWs12nLoNKhGux865crgxVA4H", "/dns/polkadot.bootnode.amforc.com/tcp/30333/p2p/12D3KooWAsuCEVCzUVUrtib8W82Yne3jgVGhQZN3hizko5FTnDg3", "/dns/polkadot.bootnode.amforc.com/tcp/30334/wss/p2p/12D3KooWAsuCEVCzUVUrtib8W82Yne3jgVGhQZN3hizko5FTnDg3", - "/dns/polkadot-bootnode.polkadotters.com/tcp/30333/p2p/12D3KooWPAVUgBaBk6n8SztLrMk8ESByncbAfRKUdxY1nygb9zG3", - "/dns/polkadot-bootnode.polkadotters.com/tcp/30334/wss/p2p/12D3KooWPAVUgBaBk6n8SztLrMk8ESByncbAfRKUdxY1nygb9zG3", + "/dns/polkadot.bootnodes.polkadotters.com/tcp/30314/p2p/12D3KooWPAVUgBaBk6n8SztLrMk8ESByncbAfRKUdxY1nygb9zG3", + "/dns/polkadot.bootnodes.polkadotters.com/tcp/30316/wss/p2p/12D3KooWPAVUgBaBk6n8SztLrMk8ESByncbAfRKUdxY1nygb9zG3", "/dns/boot-cr.gatotech.network/tcp/33100/p2p/12D3KooWK4E16jKk9nRhvC4RfrDVgcZzExg8Q3Q2G7ABUUitks1w", "/dns/boot-cr.gatotech.network/tcp/35100/wss/p2p/12D3KooWK4E16jKk9nRhvC4RfrDVgcZzExg8Q3Q2G7ABUUitks1w", "/dns/boot-polkadot.metaspan.io/tcp/13012/p2p/12D3KooWRjHFApinuqSBjoaDjQHvxwubQSpEVy5hrgC9Smvh92WF", diff --git a/polkadot/node/service/chain-specs/westend.json b/polkadot/node/service/chain-specs/westend.json index 697675871fc..775f3e72ac7 100644 --- a/polkadot/node/service/chain-specs/westend.json +++ b/polkadot/node/service/chain-specs/westend.json @@ -14,8 +14,8 @@ "/dns/boot-node.helikon.io/tcp/7082/wss/p2p/12D3KooWRFDPyT8vA8mLzh6dJoyujn4QNjeqi6Ch79eSMz9beKXC", "/dns/westend.bootnode.amforc.com/tcp/30333/p2p/12D3KooWJ5y9ZgVepBQNW4aabrxgmnrApdVnscqgKWiUu4BNJbC8", "/dns/westend.bootnode.amforc.com/tcp/30334/wss/p2p/12D3KooWJ5y9ZgVepBQNW4aabrxgmnrApdVnscqgKWiUu4BNJbC8", - "/dns/westend-bootnode.polkadotters.com/tcp/30333/p2p/12D3KooWHPHb64jXMtSRJDrYFATWeLnvChL8NtWVttY67DCH1eC5", - "/dns/westend-bootnode.polkadotters.com/tcp/30334/wss/p2p/12D3KooWHPHb64jXMtSRJDrYFATWeLnvChL8NtWVttY67DCH1eC5", + "/dns/westend.bootnodes.polkadotters.com/tcp/30308/p2p/12D3KooWHPHb64jXMtSRJDrYFATWeLnvChL8NtWVttY67DCH1eC5", + "/dns/westend.bootnodes.polkadotters.com/tcp/30310/wss/p2p/12D3KooWHPHb64jXMtSRJDrYFATWeLnvChL8NtWVttY67DCH1eC5", "/dns/boot-cr.gatotech.network/tcp/33300/p2p/12D3KooWQGR1vUhoy6mvQorFp3bZFn6NNezhQZ6NWnVV7tpFgoPd", "/dns/boot-cr.gatotech.network/tcp/35300/wss/p2p/12D3KooWQGR1vUhoy6mvQorFp3bZFn6NNezhQZ6NWnVV7tpFgoPd", "/dns/boot-westend.metaspan.io/tcp/33012/p2p/12D3KooWNTau7iG4G9cUJSwwt2QJP1W88pUf2SgqsHjRU2RL8pfa", -- GitLab From 95da6583602691fd0c8403e9eda26db1e10dafc4 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 28 Feb 2024 13:13:09 +1100 Subject: [PATCH 038/188] Introduce storage attr macro `#[disable_try_decode_storage]` and set it on `System::Events` and `ParachainSystem::HostConfiguration` (#3454) Closes https://github.com/paritytech/polkadot-sdk/issues/2560 Allows marking storage items with `#[disable_try_decode_storage]`, and uses it with `System::Events`. Question: what's the recommended way to write a test for this? I couldn't find a test for similar existing macro `#[whitelist_storage]`. --- cumulus/pallets/parachain-system/src/lib.rs | 1 + prdoc/pr_3454.prdoc | 19 +++++++++++++++ substrate/frame/support/procedural/src/lib.rs | 19 +++++++++++++++ .../procedural/src/pallet/expand/storage.rs | 5 +++- .../procedural/src/pallet/parse/storage.rs | 24 +++++++++++++++++-- substrate/frame/support/src/lib.rs | 17 +++++++++++-- .../storage_invalid_attribute.stderr | 2 +- substrate/frame/system/src/lib.rs | 1 + 8 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 prdoc/pr_3454.prdoc diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index d86a67e58f4..3439227bc5b 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -840,6 +840,7 @@ pub mod pallet { /// /// This data is also absent from the genesis. #[pallet::storage] + #[pallet::disable_try_decode_storage] #[pallet::getter(fn host_configuration)] pub(super) type HostConfiguration = StorageValue<_, AbridgedHostConfiguration>; diff --git a/prdoc/pr_3454.prdoc b/prdoc/pr_3454.prdoc new file mode 100644 index 00000000000..7f564258f23 --- /dev/null +++ b/prdoc/pr_3454.prdoc @@ -0,0 +1,19 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Introduce storage attr macro #[disable_try_decode_storage] and set it on System::Events and ParachainSystem::HostConfiguration" + +doc: + - audience: Runtime Dev + description: | + Allows marking storage items with \#[disable_try_decode_storage], which disables that storage item from being decoded + during try_decode_entire_state calls. + + Applied the attribute to System::Events to close https://github.com/paritytech/polkadot-sdk/issues/2560. + Applied the attribute to ParachainSystem::HostConfiguration to resolve periodic issues with it. + +crates: + - name: frame-support-procedural + - name: frame-system + - name: cumulus-pallet-parachain-system + diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 441b21e26ff..78729ee3dc3 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1371,6 +1371,25 @@ pub fn whitelist_storage(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } +/// The optional attribute `#[pallet::disable_try_decode_storage]` will declare the +/// storage as whitelisted from decoding during try-runtime checks. This should only be +/// attached to transient storage which cannot be migrated during runtime upgrades. +/// +/// ### Example +/// ```ignore +/// #[pallet::storage] +/// #[pallet::disable_try_decode_storage] +/// pub(super) type Events = StorageValue<_, Vec>>, ValueQuery>; +/// ``` +/// +/// NOTE: As with all `pallet::*` attributes, this one _must_ be written as +/// `#[pallet::disable_try_decode_storage]` and can only be placed inside a `pallet` module in order +/// for it to work properly. +#[proc_macro_attribute] +pub fn disable_try_decode_storage(_: TokenStream, _: TokenStream) -> TokenStream { + pallet_macro_stub() +} + /// The `#[pallet::type_value]` attribute lets you define a struct implementing the `Get` trait /// to ease the use of storage types. This attribute is meant to be used alongside /// [`#[pallet::storage]`](`macro@storage`) to define a storage's default value. This attribute diff --git a/substrate/frame/support/procedural/src/pallet/expand/storage.rs b/substrate/frame/support/procedural/src/pallet/expand/storage.rs index 96c2c8e3120..937b068cfab 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/storage.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/storage.rs @@ -834,7 +834,10 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream { .storages .iter() .filter_map(|storage| { - if storage.cfg_attrs.is_empty() { + // A little hacky; don't generate for cfg gated storages to not get compile errors + // when building "frame-feature-testing" gated storages in the "frame-support-test" + // crate. + if storage.try_decode && storage.cfg_attrs.is_empty() { let ident = &storage.ident; let gen = &def.type_use_generics(storage.attr_span); Some(quote::quote_spanned!(storage.attr_span => #ident<#gen> )) diff --git a/substrate/frame/support/procedural/src/pallet/parse/storage.rs b/substrate/frame/support/procedural/src/pallet/parse/storage.rs index d1c7ba2e5e3..9d96a18b569 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/storage.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/storage.rs @@ -29,6 +29,7 @@ mod keyword { syn::custom_keyword!(storage_prefix); syn::custom_keyword!(unbounded); syn::custom_keyword!(whitelist_storage); + syn::custom_keyword!(disable_try_decode_storage); syn::custom_keyword!(OptionQuery); syn::custom_keyword!(ResultQuery); syn::custom_keyword!(ValueQuery); @@ -39,11 +40,13 @@ mod keyword { /// * `#[pallet::storage_prefix = "CustomName"]` /// * `#[pallet::unbounded]` /// * `#[pallet::whitelist_storage] +/// * `#[pallet::disable_try_decode_storage]` pub enum PalletStorageAttr { Getter(syn::Ident, proc_macro2::Span), StorageName(syn::LitStr, proc_macro2::Span), Unbounded(proc_macro2::Span), WhitelistStorage(proc_macro2::Span), + DisableTryDecodeStorage(proc_macro2::Span), } impl PalletStorageAttr { @@ -53,6 +56,7 @@ impl PalletStorageAttr { Self::StorageName(_, span) | Self::Unbounded(span) | Self::WhitelistStorage(span) => *span, + Self::DisableTryDecodeStorage(span) => *span, } } } @@ -93,6 +97,9 @@ impl syn::parse::Parse for PalletStorageAttr { } else if lookahead.peek(keyword::whitelist_storage) { content.parse::()?; Ok(Self::WhitelistStorage(attr_span)) + } else if lookahead.peek(keyword::disable_try_decode_storage) { + content.parse::()?; + Ok(Self::DisableTryDecodeStorage(attr_span)) } else { Err(lookahead.error()) } @@ -104,6 +111,7 @@ struct PalletStorageAttrInfo { rename_as: Option, unbounded: bool, whitelisted: bool, + try_decode: bool, } impl PalletStorageAttrInfo { @@ -112,6 +120,7 @@ impl PalletStorageAttrInfo { let mut rename_as = None; let mut unbounded = false; let mut whitelisted = false; + let mut disable_try_decode_storage = false; for attr in attrs { match attr { PalletStorageAttr::Getter(ident, ..) if getter.is_none() => getter = Some(ident), @@ -119,6 +128,8 @@ impl PalletStorageAttrInfo { rename_as = Some(name), PalletStorageAttr::Unbounded(..) if !unbounded => unbounded = true, PalletStorageAttr::WhitelistStorage(..) if !whitelisted => whitelisted = true, + PalletStorageAttr::DisableTryDecodeStorage(..) if !disable_try_decode_storage => + disable_try_decode_storage = true, attr => return Err(syn::Error::new( attr.attr_span(), @@ -127,7 +138,13 @@ impl PalletStorageAttrInfo { } } - Ok(PalletStorageAttrInfo { getter, rename_as, unbounded, whitelisted }) + Ok(PalletStorageAttrInfo { + getter, + rename_as, + unbounded, + whitelisted, + try_decode: !disable_try_decode_storage, + }) } } @@ -186,6 +203,8 @@ pub struct StorageDef { pub unbounded: bool, /// Whether or not reads to this storage key will be ignored by benchmarking pub whitelisted: bool, + /// Whether or not to try to decode the storage key when running try-runtime checks. + pub try_decode: bool, /// Whether or not a default hasher is allowed to replace `_` pub use_default_hasher: bool, } @@ -775,7 +794,7 @@ impl StorageDef { }; let attrs: Vec = helper::take_item_pallet_attrs(&mut item.attrs)?; - let PalletStorageAttrInfo { getter, rename_as, mut unbounded, whitelisted } = + let PalletStorageAttrInfo { getter, rename_as, mut unbounded, whitelisted, try_decode } = PalletStorageAttrInfo::from_attrs(attrs)?; // set all storages to be unbounded if dev_mode is enabled @@ -921,6 +940,7 @@ impl StorageDef { named_generics, unbounded, whitelisted, + try_decode, use_default_hasher, }) } diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 26fc1fe42c1..3e97a384275 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -982,6 +982,7 @@ pub mod pallet_prelude { /// * [`pallet::storage_prefix = "SomeName"`](#palletstorage_prefix--somename-optional) /// * [`pallet::unbounded`](#palletunbounded-optional) /// * [`pallet::whitelist_storage`](#palletwhitelist_storage-optional) +/// * [`pallet::disable_try_decode_storage`](#palletdisable_try_decode_storage-optional) /// * [`cfg(..)`](#cfg-for-storage) (on storage items) /// * [`pallet::type_value`](#type-value-pallettype_value-optional) /// * [`pallet::genesis_config`](#genesis-config-palletgenesis_config-optional) @@ -1498,6 +1499,15 @@ pub mod pallet_prelude { /// [`pallet::whitelist_storage`](frame_support::pallet_macros::whitelist_storage) /// for more info. /// +/// ## `#[pallet::disable_try_decode_storage]` (optional) +/// +/// The optional attribute `#[pallet::disable_try_decode_storage]` will declare the storage as +/// whitelisted state decoding during try-runtime logic. +/// +/// See +/// [`pallet::disable_try_decode_storage`](frame_support::pallet_macros::disable_try_decode_storage) +/// for more info. +/// /// ## `#[cfg(..)]` (for storage) /// The optional attributes `#[cfg(..)]` allow conditional compilation for the storage. /// @@ -2272,8 +2282,8 @@ pub use frame_support_procedural::pallet; /// Contains macro stubs for all of the pallet:: macros pub mod pallet_macros { pub use frame_support_procedural::{ - composite_enum, config, disable_frame_system_supertrait_check, error, event, - extra_constants, feeless_if, generate_deposit, generate_store, getter, hooks, + composite_enum, config, disable_frame_system_supertrait_check, disable_try_decode_storage, + error, event, extra_constants, feeless_if, generate_deposit, generate_store, getter, hooks, import_section, inherent, no_default, no_default_bounds, pallet_section, storage_prefix, storage_version, type_value, unbounded, validate_unsigned, weight, whitelist_storage, }; @@ -2698,6 +2708,8 @@ pub mod pallet_macros { /// * [`macro@getter`]: Creates a custom getter function. /// * [`macro@storage_prefix`]: Overrides the default prefix of the storage item. /// * [`macro@unbounded`]: Declares the storage item as unbounded. + /// * [`macro@disable_try_decode_storage`]: Declares that try-runtime checks should not + /// attempt to decode the storage item. /// /// #### Example /// ``` @@ -2713,6 +2725,7 @@ pub mod pallet_macros { /// #[pallet::getter(fn foo)] /// #[pallet::storage_prefix = "OtherFoo"] /// #[pallet::unbounded] + /// #[pallet::disable_try_decode_storage] /// pub type Foo = StorageValue<_, u32, ValueQuery>; /// } /// ``` diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_invalid_attribute.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_invalid_attribute.stderr index 7f125526edf..519fadaa604 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_invalid_attribute.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_invalid_attribute.stderr @@ -1,4 +1,4 @@ -error: expected one of: `getter`, `storage_prefix`, `unbounded`, `whitelist_storage` +error: expected one of: `getter`, `storage_prefix`, `unbounded`, `whitelist_storage`, `disable_try_decode_storage` --> tests/pallet_ui/storage_invalid_attribute.rs:33:12 | 33 | #[pallet::generate_store(pub trait Store)] diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index aa6841c008a..c527a483d88 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -894,6 +894,7 @@ pub mod pallet { /// just in case someone still reads them from within the runtime. #[pallet::storage] #[pallet::whitelist_storage] + #[pallet::disable_try_decode_storage] #[pallet::unbounded] pub(super) type Events = StorageValue<_, Vec>>, ValueQuery>; -- GitLab From 7ec0b8741b4ead5bc85411b30e53b459a03b1938 Mon Sep 17 00:00:00 2001 From: maksimryndin Date: Wed, 28 Feb 2024 05:05:54 +0100 Subject: [PATCH 039/188] Collator overseer builder unification (#3335) resolve https://github.com/paritytech/polkadot-sdk/issues/3116 a follow-up on https://github.com/paritytech/polkadot-sdk/pull/3061#pullrequestreview-1847530265: - [x] reuse collator overseer builder for polkadot-node and collator - [x] run zombienet test (0001-parachains-smoke-test.toml) - [x] make wasm build errors more user-friendly for an easier problem detection when using different toolchains in Rust --------- Co-authored-by: ordian Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> --- Cargo.lock | 1 + .../relay-chain-minimal-node/Cargo.toml | 1 + .../src/collator_overseer.rs | 144 +----------------- .../relay-chain-minimal-node/src/lib.rs | 30 ++-- .../relay-chain-minimal-node/src/network.rs | 8 +- .../src/variants/back_garbage_candidate.rs | 15 +- polkadot/node/malus/src/variants/common.rs | 4 - .../variants/dispute_finalized_candidates.rs | 17 +-- .../src/variants/dispute_valid_candidates.rs | 15 +- .../src/variants/suggest_garbage_candidate.rs | 17 +-- .../malus/src/variants/support_disabled.rs | 15 +- polkadot/node/service/src/lib.rs | 13 +- polkadot/node/service/src/overseer.rs | 76 +++------ .../subsystem-types/src/runtime_client.rs | 64 +++++++- .../utils/wasm-builder/src/prerequisites.rs | 20 ++- 15 files changed, 162 insertions(+), 278 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c52feafe7a7..27ba43780ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4166,6 +4166,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", + "polkadot-service", "sc-authority-discovery", "sc-client-api", "sc-network", diff --git a/cumulus/client/relay-chain-minimal-node/Cargo.toml b/cumulus/client/relay-chain-minimal-node/Cargo.toml index 0b1e001e007..98240c92ada 100644 --- a/cumulus/client/relay-chain-minimal-node/Cargo.toml +++ b/cumulus/client/relay-chain-minimal-node/Cargo.toml @@ -24,6 +24,7 @@ polkadot-node-collation-generation = { path = "../../../polkadot/node/collation- polkadot-node-core-runtime-api = { path = "../../../polkadot/node/core/runtime-api" } polkadot-node-core-chain-api = { path = "../../../polkadot/node/core/chain-api" } polkadot-node-core-prospective-parachains = { path = "../../../polkadot/node/core/prospective-parachains" } +polkadot-service = { path = "../../../polkadot/node/service" } # substrate deps sc-authority-discovery = { path = "../../../substrate/client/authority-discovery" } diff --git a/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs b/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs index 5f5bf338ef9..f01ef8b05ec 100644 --- a/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs +++ b/cumulus/client/relay-chain-minimal-node/src/collator_overseer.rs @@ -15,159 +15,29 @@ // along with Polkadot. If not, see . use futures::{select, StreamExt}; -use parking_lot::Mutex; -use std::{collections::HashMap, sync::Arc}; +use std::sync::Arc; -use polkadot_availability_recovery::AvailabilityRecoverySubsystem; -use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide}; -use polkadot_network_bridge::{ - Metrics as NetworkBridgeMetrics, NetworkBridgeRx as NetworkBridgeRxSubsystem, - NetworkBridgeTx as NetworkBridgeTxSubsystem, -}; -use polkadot_node_collation_generation::CollationGenerationSubsystem; -use polkadot_node_core_chain_api::ChainApiSubsystem; -use polkadot_node_core_prospective_parachains::ProspectiveParachainsSubsystem; -use polkadot_node_core_runtime_api::RuntimeApiSubsystem; -use polkadot_node_network_protocol::{ - peer_set::{PeerSet, PeerSetProtocolNames}, - request_response::{ - v1::{self, AvailableDataFetchingRequest}, - v2, IncomingRequestReceiver, ReqProtocolNames, - }, -}; -use polkadot_node_subsystem_util::metrics::{prometheus::Registry, Metrics}; use polkadot_overseer::{ - BlockInfo, DummySubsystem, Handle, Overseer, OverseerConnector, OverseerHandle, SpawnGlue, - UnpinHandle, + BlockInfo, Handle, Overseer, OverseerConnector, OverseerHandle, SpawnGlue, UnpinHandle, }; -use polkadot_primitives::CollatorPair; +use polkadot_service::overseer::{collator_overseer_builder, OverseerGenArgs}; -use sc_authority_discovery::Service as AuthorityDiscoveryService; -use sc_network::{NetworkStateInfo, NotificationService}; use sc_service::TaskManager; use sc_utils::mpsc::tracing_unbounded; -use cumulus_primitives_core::relay_chain::{Block, Hash as PHash}; use cumulus_relay_chain_interface::RelayChainError; use crate::BlockChainRpcClient; -/// Arguments passed for overseer construction. -pub(crate) struct CollatorOverseerGenArgs<'a> { - /// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others. - pub runtime_client: Arc, - /// Underlying network service implementation. - pub network_service: Arc>, - /// Syncing oracle. - pub sync_oracle: Box, - /// Underlying authority discovery service. - pub authority_discovery_service: AuthorityDiscoveryService, - /// Receiver for collation request protocol v1. - pub collation_req_receiver_v1: IncomingRequestReceiver, - /// Receiver for collation request protocol v2. - pub collation_req_receiver_v2: IncomingRequestReceiver, - /// Receiver for availability request protocol - pub available_data_req_receiver: IncomingRequestReceiver, - /// Prometheus registry, commonly used for production systems, less so for test. - pub registry: Option<&'a Registry>, - /// Task spawner to be used throughout the overseer and the APIs it provides. - pub spawner: sc_service::SpawnTaskHandle, - /// Determines the behavior of the collator. - pub collator_pair: CollatorPair, - /// Request response protocols - pub req_protocol_names: ReqProtocolNames, - /// Peerset protocols name mapping - pub peer_set_protocol_names: PeerSetProtocolNames, - /// Notification services for validation/collation protocols. - pub notification_services: HashMap>, -} - fn build_overseer( connector: OverseerConnector, - CollatorOverseerGenArgs { - runtime_client, - network_service, - sync_oracle, - authority_discovery_service, - collation_req_receiver_v1, - collation_req_receiver_v2, - available_data_req_receiver, - registry, - spawner, - collator_pair, - req_protocol_names, - peer_set_protocol_names, - notification_services, - }: CollatorOverseerGenArgs<'_>, + args: OverseerGenArgs, ) -> Result< (Overseer, Arc>, OverseerHandle), RelayChainError, > { - let spawner = SpawnGlue(spawner); - let network_bridge_metrics: NetworkBridgeMetrics = Metrics::register(registry)?; - let notification_sinks = Arc::new(Mutex::new(HashMap::new())); - - let builder = Overseer::builder() - .availability_distribution(DummySubsystem) - .availability_recovery(AvailabilityRecoverySubsystem::for_collator( - available_data_req_receiver, - Metrics::register(registry)?, - )) - .availability_store(DummySubsystem) - .bitfield_distribution(DummySubsystem) - .bitfield_signing(DummySubsystem) - .candidate_backing(DummySubsystem) - .candidate_validation(DummySubsystem) - .pvf_checker(DummySubsystem) - .chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?)) - .collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?)) - .collator_protocol({ - let side = ProtocolSide::Collator { - peer_id: network_service.local_peer_id(), - collator_pair, - request_receiver_v1: collation_req_receiver_v1, - request_receiver_v2: collation_req_receiver_v2, - metrics: Metrics::register(registry)?, - }; - CollatorProtocolSubsystem::new(side) - }) - .network_bridge_rx(NetworkBridgeRxSubsystem::new( - network_service.clone(), - authority_discovery_service.clone(), - sync_oracle, - network_bridge_metrics.clone(), - peer_set_protocol_names.clone(), - notification_services, - notification_sinks.clone(), - )) - .network_bridge_tx(NetworkBridgeTxSubsystem::new( - network_service, - authority_discovery_service, - network_bridge_metrics, - req_protocol_names, - peer_set_protocol_names, - notification_sinks, - )) - .provisioner(DummySubsystem) - .runtime_api(RuntimeApiSubsystem::new( - runtime_client.clone(), - Metrics::register(registry)?, - spawner.clone(), - )) - .statement_distribution(DummySubsystem) - .prospective_parachains(ProspectiveParachainsSubsystem::new(Metrics::register(registry)?)) - .approval_distribution(DummySubsystem) - .approval_voting(DummySubsystem) - .gossip_support(DummySubsystem) - .dispute_coordinator(DummySubsystem) - .dispute_distribution(DummySubsystem) - .chain_selection(DummySubsystem) - .activation_external_listeners(Default::default()) - .span_per_active_leaf(Default::default()) - .active_leaves(Default::default()) - .supports_parachains(runtime_client) - .metrics(Metrics::register(registry)?) - .spawner(spawner); + let builder = + collator_overseer_builder(args).map_err(|e| RelayChainError::Application(e.into()))?; builder .build_with_connector(connector) @@ -175,7 +45,7 @@ fn build_overseer( } pub(crate) fn spawn_overseer( - overseer_args: CollatorOverseerGenArgs, + overseer_args: OverseerGenArgs, task_manager: &TaskManager, relay_chain_rpc_client: Arc, ) -> Result { diff --git a/cumulus/client/relay-chain-minimal-node/src/lib.rs b/cumulus/client/relay-chain-minimal-node/src/lib.rs index d121d2d3356..4bccca59fe3 100644 --- a/cumulus/client/relay-chain-minimal-node/src/lib.rs +++ b/cumulus/client/relay-chain-minimal-node/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use collator_overseer::{CollatorOverseerGenArgs, NewMinimalNode}; +use collator_overseer::NewMinimalNode; use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult}; use cumulus_relay_chain_rpc_interface::{RelayChainRpcClient, RelayChainRpcInterface, Url}; @@ -29,6 +29,7 @@ use polkadot_node_network_protocol::{ use polkadot_node_subsystem_util::metrics::prometheus::Registry; use polkadot_primitives::CollatorPair; +use polkadot_service::{overseer::OverseerGenArgs, IsParachainNode}; use sc_authority_discovery::Service as AuthorityDiscoveryService; use sc_network::{config::FullNetworkConfiguration, Event, NetworkEventStream, NetworkService}; @@ -172,10 +173,10 @@ async fn new_minimal_relay_chain( } let genesis_hash = relay_chain_rpc_client.block_get_hash(Some(0)).await?.unwrap_or_default(); - let peer_set_protocol_names = + let peerset_protocol_names = PeerSetProtocolNames::new(genesis_hash, config.chain_spec.fork_id()); let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No }; - let notification_services = peer_sets_info(is_authority, &peer_set_protocol_names) + let notification_services = peer_sets_info(is_authority, &peerset_protocol_names) .into_iter() .map(|(config, (peerset, service))| { net_config.add_notification_protocol(config); @@ -184,14 +185,14 @@ async fn new_minimal_relay_chain( .collect::>>(); let request_protocol_names = ReqProtocolNames::new(genesis_hash, config.chain_spec.fork_id()); - let (collation_req_receiver_v1, collation_req_receiver_v2, available_data_req_receiver) = + let (collation_req_v1_receiver, collation_req_v2_receiver, available_data_req_receiver) = build_request_response_protocol_receivers(&request_protocol_names, &mut net_config); let best_header = relay_chain_rpc_client .chain_get_header(None) .await? .ok_or_else(|| RelayChainError::RpcCallError("Unable to fetch best header".to_string()))?; - let (network, network_starter, sync_oracle) = build_collator_network( + let (network, network_starter, sync_service) = build_collator_network( &config, net_config, task_manager.spawn_handle(), @@ -208,19 +209,20 @@ async fn new_minimal_relay_chain( prometheus_registry.cloned(), ); - let overseer_args = CollatorOverseerGenArgs { + let overseer_args = OverseerGenArgs { runtime_client: relay_chain_rpc_client.clone(), network_service: network, - sync_oracle, + sync_service, authority_discovery_service, - collation_req_receiver_v1, - collation_req_receiver_v2, + collation_req_v1_receiver, + collation_req_v2_receiver, available_data_req_receiver, registry: prometheus_registry, spawner: task_manager.spawn_handle(), - collator_pair, + is_parachain_node: IsParachainNode::Collator(collator_pair), + overseer_message_channel_capacity_override: None, req_protocol_names: request_protocol_names, - peer_set_protocol_names, + peerset_protocol_names, notification_services, }; @@ -240,10 +242,10 @@ fn build_request_response_protocol_receivers( IncomingRequestReceiver, IncomingRequestReceiver, ) { - let (collation_req_receiver_v1, cfg) = + let (collation_req_v1_receiver, cfg) = IncomingRequest::get_config_receiver(request_protocol_names); config.add_request_response_protocol(cfg); - let (collation_req_receiver_v2, cfg) = + let (collation_req_v2_receiver, cfg) = IncomingRequest::get_config_receiver(request_protocol_names); config.add_request_response_protocol(cfg); let (available_data_req_receiver, cfg) = @@ -251,5 +253,5 @@ fn build_request_response_protocol_receivers( config.add_request_response_protocol(cfg); let cfg = Protocol::ChunkFetchingV1.get_outbound_only_config(request_protocol_names); config.add_request_response_protocol(cfg); - (collation_req_receiver_v1, collation_req_receiver_v2, available_data_req_receiver) + (collation_req_v1_receiver, collation_req_v2_receiver, available_data_req_receiver) } diff --git a/cumulus/client/relay-chain-minimal-node/src/network.rs b/cumulus/client/relay-chain-minimal-node/src/network.rs index 95785063c1a..7286fab7907 100644 --- a/cumulus/client/relay-chain-minimal-node/src/network.rs +++ b/cumulus/client/relay-chain-minimal-node/src/network.rs @@ -40,7 +40,11 @@ pub(crate) fn build_collator_network( genesis_hash: Hash, best_header: Header, ) -> Result< - (Arc>, NetworkStarter, Box), + ( + Arc>, + NetworkStarter, + Arc, + ), Error, > { let protocol_id = config.protocol_id(); @@ -112,7 +116,7 @@ pub(crate) fn build_collator_network( let network_starter = NetworkStarter::new(network_start_tx); - Ok((network_service, network_starter, Box::new(SyncOracle {}))) + Ok((network_service, network_starter, Arc::new(SyncOracle {}))) } fn adjust_network_config_light_in_peers(config: &mut NetworkConfiguration) { diff --git a/polkadot/node/malus/src/variants/back_garbage_candidate.rs b/polkadot/node/malus/src/variants/back_garbage_candidate.rs index 82475d29142..b939a2151e2 100644 --- a/polkadot/node/malus/src/variants/back_garbage_candidate.rs +++ b/polkadot/node/malus/src/variants/back_garbage_candidate.rs @@ -20,14 +20,13 @@ use polkadot_cli::{ service::{ - AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs, - HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle, - ParachainHost, ProvideRuntimeApi, + AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen, + OverseerGenArgs, OverseerHandle, }, validator_overseer_builder, Cli, }; use polkadot_node_subsystem::SpawnGlue; -use polkadot_node_subsystem_types::DefaultSubsystemClient; +use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient}; use sp_core::traits::SpawnNamed; use crate::{ @@ -63,13 +62,9 @@ impl OverseerGen for BackGarbageCandidates { connector: OverseerConnector, args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ext_args: Option, - ) -> Result< - (Overseer, Arc>>, OverseerHandle), - Error, - > + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin, { let spawner = args.spawner.clone(); diff --git a/polkadot/node/malus/src/variants/common.rs b/polkadot/node/malus/src/variants/common.rs index 011fcc80e37..eb6988f8181 100644 --- a/polkadot/node/malus/src/variants/common.rs +++ b/polkadot/node/malus/src/variants/common.rs @@ -23,10 +23,6 @@ use crate::{ use polkadot_node_core_candidate_validation::find_validation_data; use polkadot_node_primitives::{InvalidCandidate, ValidationResult}; -use polkadot_node_subsystem::{ - messages::{CandidateValidationMessage, ValidationFailed}, - overseer, -}; use polkadot_primitives::{ CandidateCommitments, CandidateDescriptor, CandidateReceipt, PersistedValidationData, diff --git a/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs b/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs index b3555ba2f5b..7a95bdaead2 100644 --- a/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs +++ b/polkadot/node/malus/src/variants/dispute_finalized_candidates.rs @@ -34,14 +34,13 @@ use futures::channel::oneshot; use polkadot_cli::{ service::{ - AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs, - HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle, - ParachainHost, ProvideRuntimeApi, + AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen, + OverseerGenArgs, OverseerHandle, }, validator_overseer_builder, Cli, }; -use polkadot_node_subsystem::{messages::ApprovalVotingMessage, SpawnGlue}; -use polkadot_node_subsystem_types::{DefaultSubsystemClient, OverseerSignal}; +use polkadot_node_subsystem::SpawnGlue; +use polkadot_node_subsystem_types::{ChainApiBackend, OverseerSignal, RuntimeApiSubsystemClient}; use polkadot_node_subsystem_util::request_candidate_events; use polkadot_primitives::CandidateEvent; use sp_core::traits::SpawnNamed; @@ -237,13 +236,9 @@ impl OverseerGen for DisputeFinalizedCandidates { connector: OverseerConnector, args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ext_args: Option, - ) -> Result< - (Overseer, Arc>>, OverseerHandle), - Error, - > + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin, { gum::info!( diff --git a/polkadot/node/malus/src/variants/dispute_valid_candidates.rs b/polkadot/node/malus/src/variants/dispute_valid_candidates.rs index b9812cbb501..a50fdce16e4 100644 --- a/polkadot/node/malus/src/variants/dispute_valid_candidates.rs +++ b/polkadot/node/malus/src/variants/dispute_valid_candidates.rs @@ -24,14 +24,13 @@ use polkadot_cli::{ service::{ - AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs, - HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle, - ParachainHost, ProvideRuntimeApi, + AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen, + OverseerGenArgs, OverseerHandle, }, validator_overseer_builder, Cli, }; use polkadot_node_subsystem::SpawnGlue; -use polkadot_node_subsystem_types::DefaultSubsystemClient; +use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient}; use sp_core::traits::SpawnNamed; // Filter wrapping related types. @@ -80,13 +79,9 @@ impl OverseerGen for DisputeValidCandidates { connector: OverseerConnector, args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ext_args: Option, - ) -> Result< - (Overseer, Arc>>, OverseerHandle), - Error, - > + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin, { let spawner = args.spawner.clone(); diff --git a/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs b/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs index 22b44ddd1dc..739ed40db36 100644 --- a/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs +++ b/polkadot/node/malus/src/variants/suggest_garbage_candidate.rs @@ -25,14 +25,13 @@ use futures::channel::oneshot; use polkadot_cli::{ service::{ - AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs, - HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle, - ParachainHost, ProvideRuntimeApi, + AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen, + OverseerGenArgs, OverseerHandle, }, validator_overseer_builder, Cli, }; use polkadot_node_primitives::{AvailableData, BlockData, PoV}; -use polkadot_node_subsystem_types::DefaultSubsystemClient; +use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient}; use polkadot_primitives::{CandidateDescriptor, CandidateReceipt}; use polkadot_node_subsystem_util::request_validators; @@ -52,7 +51,7 @@ use crate::{ // Import extra types relevant to the particular // subsystem. -use polkadot_node_subsystem::{messages::CandidateBackingMessage, SpawnGlue}; +use polkadot_node_subsystem::SpawnGlue; use std::sync::Arc; @@ -296,13 +295,9 @@ impl OverseerGen for SuggestGarbageCandidates { connector: OverseerConnector, args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ext_args: Option, - ) -> Result< - (Overseer, Arc>>, OverseerHandle), - Error, - > + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin, { gum::info!( diff --git a/polkadot/node/malus/src/variants/support_disabled.rs b/polkadot/node/malus/src/variants/support_disabled.rs index e25df56fd64..169c442db25 100644 --- a/polkadot/node/malus/src/variants/support_disabled.rs +++ b/polkadot/node/malus/src/variants/support_disabled.rs @@ -19,14 +19,13 @@ use polkadot_cli::{ service::{ - AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, ExtendedOverseerGenArgs, - HeaderBackend, Overseer, OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle, - ParachainHost, ProvideRuntimeApi, + AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen, + OverseerGenArgs, OverseerHandle, }, validator_overseer_builder, Cli, }; use polkadot_node_subsystem::SpawnGlue; -use polkadot_node_subsystem_types::DefaultSubsystemClient; +use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient}; use sp_core::traits::SpawnNamed; use crate::interceptor::*; @@ -50,13 +49,9 @@ impl OverseerGen for SupportDisabled { connector: OverseerConnector, args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ext_args: Option, - ) -> Result< - (Overseer, Arc>>, OverseerHandle), - Error, - > + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin, { validator_overseer_builder( diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs index 6dcdec07ca8..83a0afc077e 100644 --- a/polkadot/node/service/src/lib.rs +++ b/polkadot/node/service/src/lib.rs @@ -92,6 +92,7 @@ pub use chain_spec::{GenericChainSpec, RococoChainSpec, WestendChainSpec}; pub use consensus_common::{Proposal, SelectChain}; use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; use mmr_gadget::MmrGadget; +use polkadot_node_subsystem_types::DefaultSubsystemClient; pub use polkadot_primitives::{Block, BlockId, BlockNumber, CollatorPair, Hash, Id as ParaId}; pub use sc_client_api::{Backend, CallExecutor}; pub use sc_consensus::{BlockImport, LongestChain}; @@ -1081,12 +1082,17 @@ pub fn new_full( None }; + let runtime_client = Arc::new(DefaultSubsystemClient::new( + overseer_client.clone(), + OffchainTransactionPoolFactory::new(transaction_pool.clone()), + )); + let overseer_handle = if let Some(authority_discovery_service) = authority_discovery_service { let (overseer, overseer_handle) = overseer_gen - .generate::( + .generate::>( overseer_connector, OverseerGenArgs { - runtime_client: overseer_client.clone(), + runtime_client, network_service: network.clone(), sync_service: sync_service.clone(), authority_discovery_service, @@ -1099,9 +1105,6 @@ pub fn new_full( overseer_message_channel_capacity_override, req_protocol_names, peerset_protocol_names, - offchain_transaction_pool_factory: OffchainTransactionPoolFactory::new( - transaction_pool.clone(), - ), notification_services, }, ext_overseer_args, diff --git a/polkadot/node/service/src/overseer.rs b/polkadot/node/service/src/overseer.rs index b2b0786bfc2..a8167370464 100644 --- a/polkadot/node/service/src/overseer.rs +++ b/polkadot/node/service/src/overseer.rs @@ -14,10 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use super::{AuthorityDiscoveryApi, Block, Error, Hash, IsParachainNode, Registry}; -use polkadot_node_subsystem_types::DefaultSubsystemClient; +use super::{Block, Error, Hash, IsParachainNode, Registry}; +use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient}; use polkadot_overseer::{DummySubsystem, InitializedOverseerBuilder, SubsystemError}; -use sc_transaction_pool_api::OffchainTransactionPoolFactory; use sp_core::traits::SpawnNamed; use polkadot_availability_distribution::IncomingRequestReceivers; @@ -40,14 +39,10 @@ use polkadot_overseer::{ }; use parking_lot::Mutex; -use polkadot_primitives::runtime_api::ParachainHost; use sc_authority_discovery::Service as AuthorityDiscoveryService; use sc_client_api::AuxStore; use sc_keystore::LocalKeystore; use sc_network::{NetworkStateInfo, NotificationService}; -use sp_api::ProvideRuntimeApi; -use sp_blockchain::HeaderBackend; -use sp_consensus_babe::BabeApi; use std::{collections::HashMap, sync::Arc}; pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem; @@ -80,8 +75,6 @@ pub use polkadot_statement_distribution::StatementDistributionSubsystem; /// Arguments passed for overseer construction. pub struct OverseerGenArgs<'a, Spawner, RuntimeClient> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, Spawner: 'static + SpawnNamed + Clone + Unpin, { /// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others. @@ -89,7 +82,7 @@ where /// Underlying network service implementation. pub network_service: Arc>, /// Underlying syncing service implementation. - pub sync_service: Arc>, + pub sync_service: Arc, /// Underlying authority discovery service. pub authority_discovery_service: AuthorityDiscoveryService, /// Collations request receiver for network protocol v1. @@ -111,8 +104,6 @@ where pub req_protocol_names: ReqProtocolNames, /// `PeerSet` protocol names to protocols mapping. pub peerset_protocol_names: PeerSetProtocolNames, - /// The offchain transaction pool factory. - pub offchain_transaction_pool_factory: OffchainTransactionPoolFactory, /// Notification services for validation/collation protocols. pub notification_services: HashMap>, } @@ -160,7 +151,6 @@ pub fn validator_overseer_builder( overseer_message_channel_capacity_override, req_protocol_names, peerset_protocol_names, - offchain_transaction_pool_factory, notification_services, }: OverseerGenArgs, ExtendedOverseerGenArgs { @@ -180,7 +170,7 @@ pub fn validator_overseer_builder( ) -> Result< InitializedOverseerBuilder< SpawnGlue, - Arc>, + Arc, CandidateValidationSubsystem, PvfCheckerSubsystem, CandidateBackingSubsystem, @@ -190,7 +180,7 @@ pub fn validator_overseer_builder( BitfieldSigningSubsystem, BitfieldDistributionSubsystem, ProvisionerSubsystem, - RuntimeApiSubsystem>, + RuntimeApiSubsystem, AvailabilityStoreSubsystem, NetworkBridgeRxSubsystem< Arc>, @@ -214,8 +204,7 @@ pub fn validator_overseer_builder( Error, > where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin, { use polkadot_node_subsystem_util::metrics::Metrics; @@ -227,11 +216,6 @@ where let network_bridge_metrics: NetworkBridgeMetrics = Metrics::register(registry)?; - let runtime_api_client = Arc::new(DefaultSubsystemClient::new( - runtime_client.clone(), - offchain_transaction_pool_factory, - )); - let builder = Overseer::builder() .network_bridge_tx(NetworkBridgeTxSubsystem::new( network_service.clone(), @@ -298,7 +282,7 @@ where }) .provisioner(ProvisionerSubsystem::new(Metrics::register(registry)?)) .runtime_api(RuntimeApiSubsystem::new( - runtime_api_client.clone(), + runtime_client.clone(), Metrics::register(registry)?, spawner.clone(), )) @@ -339,7 +323,7 @@ where .activation_external_listeners(Default::default()) .span_per_active_leaf(Default::default()) .active_leaves(Default::default()) - .supports_parachains(runtime_api_client) + .supports_parachains(runtime_client) .metrics(metrics) .spawner(spawner); @@ -367,13 +351,12 @@ pub fn collator_overseer_builder( overseer_message_channel_capacity_override, req_protocol_names, peerset_protocol_names, - offchain_transaction_pool_factory, notification_services, }: OverseerGenArgs, ) -> Result< InitializedOverseerBuilder< SpawnGlue, - Arc>, + Arc, DummySubsystem, DummySubsystem, DummySubsystem, @@ -383,7 +366,7 @@ pub fn collator_overseer_builder( DummySubsystem, DummySubsystem, DummySubsystem, - RuntimeApiSubsystem>, + RuntimeApiSubsystem, DummySubsystem, NetworkBridgeRxSubsystem< Arc>, @@ -407,24 +390,17 @@ pub fn collator_overseer_builder( Error, > where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, Spawner: 'static + SpawnNamed + Clone + Unpin, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, { use polkadot_node_subsystem_util::metrics::Metrics; - let metrics = ::register(registry)?; let notification_sinks = Arc::new(Mutex::new(HashMap::new())); let spawner = SpawnGlue(spawner); let network_bridge_metrics: NetworkBridgeMetrics = Metrics::register(registry)?; - let runtime_api_client = Arc::new(DefaultSubsystemClient::new( - runtime_client.clone(), - offchain_transaction_pool_factory, - )); - let builder = Overseer::builder() .network_bridge_tx(NetworkBridgeTxSubsystem::new( network_service.clone(), @@ -475,7 +451,7 @@ where }) .provisioner(DummySubsystem) .runtime_api(RuntimeApiSubsystem::new( - runtime_api_client.clone(), + runtime_client.clone(), Metrics::register(registry)?, spawner.clone(), )) @@ -490,8 +466,8 @@ where .activation_external_listeners(Default::default()) .span_per_active_leaf(Default::default()) .active_leaves(Default::default()) - .supports_parachains(runtime_api_client) - .metrics(metrics) + .supports_parachains(runtime_client) + .metrics(Metrics::register(registry)?) .spawner(spawner); let builder = if let Some(capacity) = overseer_message_channel_capacity_override { @@ -510,13 +486,9 @@ pub trait OverseerGen { connector: OverseerConnector, args: OverseerGenArgs, ext_args: Option, - ) -> Result< - (Overseer, Arc>>, OverseerHandle), - Error, - > + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin; // It would be nice to make `create_subsystems` part of this trait, @@ -533,13 +505,9 @@ impl OverseerGen for ValidatorOverseerGen { connector: OverseerConnector, args: OverseerGenArgs, ext_args: Option, - ) -> Result< - (Overseer, Arc>>, OverseerHandle), - Error, - > + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin, { let ext_args = ext_args.ok_or(Error::Overseer(SubsystemError::Context( @@ -561,13 +529,9 @@ impl OverseerGen for CollatorOverseerGen { connector: OverseerConnector, args: OverseerGenArgs, _ext_args: Option, - ) -> Result< - (Overseer, Arc>>, OverseerHandle), - Error, - > + ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static, Spawner: 'static + SpawnNamed + Clone + Unpin, { collator_overseer_builder(args)? diff --git a/polkadot/node/subsystem-types/src/runtime_client.rs b/polkadot/node/subsystem-types/src/runtime_client.rs index 7f618307610..4039fc9127d 100644 --- a/polkadot/node/subsystem-types/src/runtime_client.rs +++ b/polkadot/node/subsystem-types/src/runtime_client.rs @@ -26,13 +26,13 @@ use polkadot_primitives::{ PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, }; -use sc_client_api::HeaderBackend; +use sc_client_api::{AuxStore, HeaderBackend}; use sc_transaction_pool_api::OffchainTransactionPoolFactory; use sp_api::{ApiError, ApiExt, ProvideRuntimeApi}; use sp_authority_discovery::AuthorityDiscoveryApi; -use sp_blockchain::Info; +use sp_blockchain::{BlockStatus, Info}; use sp_consensus_babe::{BabeApi, Epoch}; -use sp_runtime::traits::{Header as HeaderT, NumberFor}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use std::{collections::BTreeMap, sync::Arc}; /// Offers header utilities. @@ -595,3 +595,61 @@ where self.client.runtime_api().approval_voting_params(at) } } + +impl HeaderBackend for DefaultSubsystemClient +where + Client: HeaderBackend, + Block: sp_runtime::traits::Block, +{ + fn header( + &self, + hash: Block::Hash, + ) -> sc_client_api::blockchain::Result> { + self.client.header(hash) + } + + fn info(&self) -> Info { + self.client.info() + } + + fn status(&self, hash: Block::Hash) -> sc_client_api::blockchain::Result { + self.client.status(hash) + } + + fn number( + &self, + hash: Block::Hash, + ) -> sc_client_api::blockchain::Result::Header as HeaderT>::Number>> { + self.client.number(hash) + } + + fn hash( + &self, + number: NumberFor, + ) -> sc_client_api::blockchain::Result> { + self.client.hash(number) + } +} + +impl AuxStore for DefaultSubsystemClient +where + Client: AuxStore, +{ + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >( + &self, + insert: I, + delete: D, + ) -> sp_blockchain::Result<()> { + self.client.insert_aux(insert, delete) + } + + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { + self.client.get_aux(key) + } +} diff --git a/substrate/utils/wasm-builder/src/prerequisites.rs b/substrate/utils/wasm-builder/src/prerequisites.rs index a601e3210dd..22caf895063 100644 --- a/substrate/utils/wasm-builder/src/prerequisites.rs +++ b/substrate/utils/wasm-builder/src/prerequisites.rs @@ -149,6 +149,14 @@ impl<'a> DummyCrate<'a> { sysroot_cmd.output().ok().and_then(|o| String::from_utf8(o.stdout).ok()) } + fn get_toolchain(&self) -> Option { + let sysroot = self.get_sysroot()?; + Path::new(sysroot.trim()) + .file_name() + .and_then(|s| s.to_str()) + .map(|s| s.to_string()) + } + fn try_build(&self) -> Result<(), Option> { let Ok(result) = self.prepare_command("build").output() else { return Err(None) }; if !result.status.success() { @@ -164,14 +172,15 @@ fn check_wasm_toolchain_installed( let dummy_crate = DummyCrate::new(&cargo_command, RuntimeTarget::Wasm); if let Err(error) = dummy_crate.try_build() { + let toolchain = dummy_crate.get_toolchain().unwrap_or("".to_string()); let basic_error_message = colorize_error_message( - "Rust WASM toolchain is not properly installed; please install it!", + &format!("Rust WASM target for toolchain {toolchain} is not properly installed; please install it!") ); return match error { None => Err(basic_error_message), Some(error) if error.contains("the `wasm32-unknown-unknown` target may not be installed") => { - Err(colorize_error_message("Cannot compile the WASM runtime: the `wasm32-unknown-unknown` target is not installed!\n\ - You can install it with `rustup target add wasm32-unknown-unknown` if you're using `rustup`.")) + Err(colorize_error_message(&format!("Cannot compile the WASM runtime: the `wasm32-unknown-unknown` target is not installed!\n\ + You can install it with `rustup target add wasm32-unknown-unknown --toolchain {toolchain}` if you're using `rustup`."))) }, // Apparently this can happen when we're running on a non Tier 1 platform. Some(ref error) if error.contains("linker `rust-lld` not found") => @@ -193,9 +202,10 @@ fn check_wasm_toolchain_installed( let src_path = Path::new(sysroot.trim()).join("lib").join("rustlib").join("src").join("rust"); if !src_path.exists() { + let toolchain = dummy_crate.get_toolchain().unwrap_or("".to_string()); return Err(colorize_error_message( - "Cannot compile the WASM runtime: no standard library sources found!\n\ - You can install them with `rustup component add rust-src` if you're using `rustup`.", + &format!("Cannot compile the WASM runtime: no standard library sources found at {}!\n\ + You can install them with `rustup component add rust-src --toolchain {toolchain}` if you're using `rustup`.", src_path.display()), )) } } -- GitLab From 12ce4f7d049b70918cadb658de4bbe8eb6ffc670 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 28 Feb 2024 18:32:02 +1100 Subject: [PATCH 040/188] Runtime Upgrade ref docs and Single Block Migration example pallet (#1554) Closes https://github.com/paritytech/polkadot-sdk-docs/issues/55 - Changes 'current storage version' terminology to less ambiguous 'in-code storage version' (suggestion by @ggwpez) - Adds a new example pallet `pallet-example-single-block-migrations` - Adds a new reference doc to replace https://docs.substrate.io/maintain/runtime-upgrades/ (temporarily living in the pallet while we wait for developer hub PR to merge) - Adds documentation for the `storage_alias` macro - Improves `trait Hooks` docs - Improves `trait GetStorageVersion` docs - Update the suggested patterns for using `VersionedMigration`, so that version unchecked migrations are never exported - Prevents accidental usage of version unchecked migrations in runtimes https://github.com/paritytech/substrate/pull/14421#discussion_r1255467895 - Unversioned migration code is kept inside `mod version_unchecked`, versioned code is kept in `pub mod versioned` - It is necessary to use modules to limit visibility because the inner migration must be `pub`. See https://github.com/rust-lang/rust/issues/30905 and https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504/40 for more. ### todo - [x] move to reference docs to proper place within sdk-docs (now that https://github.com/paritytech/polkadot-sdk/pull/2102 is merged) - [x] prdoc --------- Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Juan Co-authored-by: Oliver Tale-Yazdi Co-authored-by: command-bot <> Co-authored-by: gupnik --- Cargo.lock | 26 ++ Cargo.toml | 1 + cumulus/pallets/collator-selection/src/lib.rs | 2 +- .../collator-selection/src/migration.rs | 10 +- .../pallets/parachain-system/src/migration.rs | 2 +- cumulus/pallets/xcmp-queue/src/migration.rs | 2 +- .../pallets/collective-content/src/lib.rs | 2 +- .../assets/asset-hub-rococo/src/lib.rs | 14 +- .../assets/asset-hub-westend/src/lib.rs | 6 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 4 +- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 4 +- docs/sdk/Cargo.toml | 7 +- .../reference_docs/frame_runtime_migration.rs | 9 - .../frame_runtime_upgrades_and_migrations.rs | 138 +++++++++++ docs/sdk/src/reference_docs/mod.rs | 5 +- .../node/service/src/parachains_db/upgrade.rs | 2 +- .../common/src/assigned_slots/migration.rs | 12 +- .../runtime/common/src/assigned_slots/mod.rs | 2 +- .../runtime/common/src/crowdloan/migration.rs | 4 +- polkadot/runtime/common/src/crowdloan/mod.rs | 2 +- .../runtime/common/src/paras_registrar/mod.rs | 2 +- .../runtime/parachains/src/configuration.rs | 2 +- polkadot/runtime/parachains/src/disputes.rs | 2 +- .../parachains/src/session_info/migration.rs | 2 +- prdoc/pr_1554.prdoc | 14 ++ substrate/client/executor/src/executor.rs | 14 +- substrate/frame/alliance/src/migration.rs | 8 +- substrate/frame/assets/src/lib.rs | 2 +- substrate/frame/assets/src/migration.rs | 20 +- substrate/frame/balances/src/lib.rs | 2 +- substrate/frame/balances/src/migration.rs | 8 +- substrate/frame/collective/src/lib.rs | 2 +- substrate/frame/contracts/src/lib.rs | 2 +- substrate/frame/contracts/src/migration.rs | 20 +- .../frame/contracts/src/migration/v09.rs | 14 +- .../frame/contracts/src/migration/v10.rs | 24 +- .../frame/contracts/src/migration/v11.rs | 12 +- .../frame/contracts/src/migration/v12.rs | 40 ++-- .../frame/contracts/src/migration/v13.rs | 10 +- .../frame/contracts/src/migration/v14.rs | 20 +- .../frame/contracts/src/migration/v15.rs | 16 +- substrate/frame/democracy/src/lib.rs | 2 +- .../election-provider-multi-phase/src/lib.rs | 2 +- .../src/migrations.rs | 4 +- substrate/frame/elections-phragmen/src/lib.rs | 2 +- substrate/frame/examples/Cargo.toml | 3 + .../single-block-migrations/Cargo.toml | 61 +++++ .../single-block-migrations/src/lib.rs | 213 +++++++++++++++++ .../src/migrations/mod.rs | 20 ++ .../src/migrations/v1.rs | 222 ++++++++++++++++++ .../single-block-migrations/src/mock.rs | 69 ++++++ substrate/frame/examples/src/lib.rs | 3 + .../frame/fast-unstake/src/migrations.rs | 4 +- substrate/frame/grandpa/src/lib.rs | 2 +- substrate/frame/im-online/src/lib.rs | 2 +- substrate/frame/im-online/src/migration.rs | 2 +- substrate/frame/membership/src/lib.rs | 2 +- substrate/frame/multisig/src/lib.rs | 2 +- substrate/frame/multisig/src/migrations.rs | 2 +- substrate/frame/nfts/src/lib.rs | 2 +- substrate/frame/nfts/src/migration.rs | 16 +- substrate/frame/nomination-pools/src/lib.rs | 2 +- .../frame/nomination-pools/src/migration.rs | 28 +-- substrate/frame/preimage/src/lib.rs | 2 +- substrate/frame/referenda/src/lib.rs | 2 +- substrate/frame/referenda/src/migration.rs | 16 +- substrate/frame/scheduler/src/lib.rs | 2 +- substrate/frame/session/src/historical/mod.rs | 2 +- substrate/frame/session/src/lib.rs | 2 +- substrate/frame/society/src/migrations.rs | 54 ++--- substrate/frame/society/src/tests.rs | 44 ++-- substrate/frame/staking/src/migrations.rs | 12 +- substrate/frame/staking/src/pallet/mod.rs | 2 +- substrate/frame/support/procedural/src/lib.rs | 38 ++- .../procedural/src/pallet/expand/hooks.rs | 22 +- .../src/pallet/expand/pallet_struct.rs | 6 +- .../src/pallet/parse/pallet_struct.rs | 2 +- substrate/frame/support/src/lib.rs | 4 +- substrate/frame/support/src/migrations.rs | 55 +++-- substrate/frame/support/src/traits/hooks.rs | 70 +++--- .../frame/support/src/traits/metadata.rs | 71 ++++-- .../support/test/tests/construct_runtime.rs | 2 +- substrate/frame/support/test/tests/pallet.rs | 22 +- .../compare_unset_storage_version.rs | 2 +- .../compare_unset_storage_version.stderr | 2 +- substrate/frame/system/src/lib.rs | 2 +- substrate/frame/tips/src/lib.rs | 2 +- 87 files changed, 1223 insertions(+), 370 deletions(-) delete mode 100644 docs/sdk/src/reference_docs/frame_runtime_migration.rs create mode 100644 docs/sdk/src/reference_docs/frame_runtime_upgrades_and_migrations.rs create mode 100644 prdoc/pr_1554.prdoc create mode 100644 substrate/frame/examples/single-block-migrations/Cargo.toml create mode 100644 substrate/frame/examples/single-block-migrations/src/lib.rs create mode 100644 substrate/frame/examples/single-block-migrations/src/migrations/mod.rs create mode 100644 substrate/frame/examples/single-block-migrations/src/migrations/v1.rs create mode 100644 substrate/frame/examples/single-block-migrations/src/mock.rs diff --git a/Cargo.lock b/Cargo.lock index 27ba43780ed..026786378d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9965,6 +9965,26 @@ dependencies = [ "sp-std 14.0.0", ] +[[package]] +name = "pallet-example-single-block-migrations" +version = "0.0.1" +dependencies = [ + "docify", + "frame-executive", + "frame-support", + "frame-system", + "frame-try-runtime", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 14.0.0", + "sp-version", +] + [[package]] name = "pallet-example-split" version = "10.0.0" @@ -10006,6 +10026,7 @@ dependencies = [ "pallet-example-frame-crate", "pallet-example-kitchensink", "pallet-example-offchain-worker", + "pallet-example-single-block-migrations", "pallet-example-split", "pallet-example-tasks", ] @@ -13385,6 +13406,8 @@ dependencies = [ "cumulus-pallet-parachain-system", "docify", "frame", + "frame-executive", + "frame-support", "frame-system", "kitchensink-runtime", "pallet-aura", @@ -13393,9 +13416,11 @@ dependencies = [ "pallet-collective", "pallet-default-config-example", "pallet-democracy", + "pallet-example-single-block-migrations", "pallet-examples", "pallet-multisig", "pallet-proxy", + "pallet-scheduler", "pallet-timestamp", "pallet-transaction-payment", "pallet-utility", @@ -13418,6 +13443,7 @@ dependencies = [ "sp-io", "sp-keyring", "sp-runtime", + "sp-version", "staging-chain-spec-builder", "staging-node-cli", "staging-parachain-info", diff --git a/Cargo.toml b/Cargo.toml index 1d27cfe9539..654367cc1e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -337,6 +337,7 @@ members = [ "substrate/frame/examples/frame-crate", "substrate/frame/examples/kitchensink", "substrate/frame/examples/offchain-worker", + "substrate/frame/examples/single-block-migrations", "substrate/frame/examples/split", "substrate/frame/examples/tasks", "substrate/frame/executive", diff --git a/cumulus/pallets/collator-selection/src/lib.rs b/cumulus/pallets/collator-selection/src/lib.rs index 7449f4d68c7..fb4c4a445df 100644 --- a/cumulus/pallets/collator-selection/src/lib.rs +++ b/cumulus/pallets/collator-selection/src/lib.rs @@ -118,7 +118,7 @@ pub mod pallet { use sp_staking::SessionIndex; use sp_std::vec::Vec; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); type BalanceOf = diff --git a/cumulus/pallets/collator-selection/src/migration.rs b/cumulus/pallets/collator-selection/src/migration.rs index 58b4cc5b06a..f384981dbae 100644 --- a/cumulus/pallets/collator-selection/src/migration.rs +++ b/cumulus/pallets/collator-selection/src/migration.rs @@ -31,8 +31,8 @@ pub mod v1 { pub struct MigrateToV1(sp_std::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV1 { fn on_runtime_upgrade() -> Weight { - let onchain_version = Pallet::::on_chain_storage_version(); - if onchain_version == 0 { + let on_chain_version = Pallet::::on_chain_storage_version(); + if on_chain_version == 0 { let invulnerables_len = Invulnerables::::get().to_vec().len(); >::mutate(|invulnerables| { invulnerables.sort(); @@ -45,7 +45,7 @@ pub mod v1 { invulnerables_len, ); // Similar complexity to `set_invulnerables` (put storage value) - // Plus 1 read for length, 1 read for `onchain_version`, 1 write to put version + // Plus 1 read for length, 1 read for `on_chain_version`, 1 write to put version T::WeightInfo::set_invulnerables(invulnerables_len as u32) .saturating_add(T::DbWeight::get().reads_writes(2, 1)) } else { @@ -83,8 +83,8 @@ pub mod v1 { "after migration, there should be the same number of invulnerables" ); - let onchain_version = Pallet::::on_chain_storage_version(); - frame_support::ensure!(onchain_version >= 1, "must_upgrade"); + let on_chain_version = Pallet::::on_chain_storage_version(); + frame_support::ensure!(on_chain_version >= 1, "must_upgrade"); Ok(()) } diff --git a/cumulus/pallets/parachain-system/src/migration.rs b/cumulus/pallets/parachain-system/src/migration.rs index a92f85b9cd4..30106aceab5 100644 --- a/cumulus/pallets/parachain-system/src/migration.rs +++ b/cumulus/pallets/parachain-system/src/migration.rs @@ -21,7 +21,7 @@ use frame_support::{ weights::Weight, }; -/// The current storage version. +/// The in-code storage version. pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); /// Migrates the pallet storage to the most recent version. diff --git a/cumulus/pallets/xcmp-queue/src/migration.rs b/cumulus/pallets/xcmp-queue/src/migration.rs index 6c86c3011d2..c7fa61a3e3f 100644 --- a/cumulus/pallets/xcmp-queue/src/migration.rs +++ b/cumulus/pallets/xcmp-queue/src/migration.rs @@ -24,7 +24,7 @@ use frame_support::{ weights::{constants::WEIGHT_REF_TIME_PER_MILLIS, Weight}, }; -/// The current storage version. +/// The in-code storage version. pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); pub const LOG: &str = "runtime::xcmp-queue-migration"; diff --git a/cumulus/parachains/pallets/collective-content/src/lib.rs b/cumulus/parachains/pallets/collective-content/src/lib.rs index 7a685858acc..b1c960ad6a0 100644 --- a/cumulus/parachains/pallets/collective-content/src/lib.rs +++ b/cumulus/parachains/pallets/collective-content/src/lib.rs @@ -59,7 +59,7 @@ pub mod pallet { use frame_system::pallet_prelude::*; use sp_runtime::{traits::BadOrigin, Saturating}; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); #[pallet::pallet] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 81bb66a56a2..6791dc4064e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -986,37 +986,37 @@ impl frame_support::traits::OnRuntimeUpgrade for InitStorageVersions { let mut writes = 0; if PolkadotXcm::on_chain_storage_version() == StorageVersion::new(0) { - PolkadotXcm::current_storage_version().put::(); + PolkadotXcm::in_code_storage_version().put::(); writes.saturating_inc(); } if Multisig::on_chain_storage_version() == StorageVersion::new(0) { - Multisig::current_storage_version().put::(); + Multisig::in_code_storage_version().put::(); writes.saturating_inc(); } if Assets::on_chain_storage_version() == StorageVersion::new(0) { - Assets::current_storage_version().put::(); + Assets::in_code_storage_version().put::(); writes.saturating_inc(); } if Uniques::on_chain_storage_version() == StorageVersion::new(0) { - Uniques::current_storage_version().put::(); + Uniques::in_code_storage_version().put::(); writes.saturating_inc(); } if Nfts::on_chain_storage_version() == StorageVersion::new(0) { - Nfts::current_storage_version().put::(); + Nfts::in_code_storage_version().put::(); writes.saturating_inc(); } if ForeignAssets::on_chain_storage_version() == StorageVersion::new(0) { - ForeignAssets::current_storage_version().put::(); + ForeignAssets::in_code_storage_version().put::(); writes.saturating_inc(); } if PoolAssets::on_chain_storage_version() == StorageVersion::new(0) { - PoolAssets::current_storage_version().put::(); + PoolAssets::in_code_storage_version().put::(); writes.saturating_inc(); } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 3f58c679eee..5352eeb1a1b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1037,17 +1037,17 @@ impl frame_support::traits::OnRuntimeUpgrade for InitStorageVersions { let mut writes = 0; if PolkadotXcm::on_chain_storage_version() == StorageVersion::new(0) { - PolkadotXcm::current_storage_version().put::(); + PolkadotXcm::in_code_storage_version().put::(); writes.saturating_inc(); } if ForeignAssets::on_chain_storage_version() == StorageVersion::new(0) { - ForeignAssets::current_storage_version().put::(); + ForeignAssets::in_code_storage_version().put::(); writes.saturating_inc(); } if PoolAssets::on_chain_storage_version() == StorageVersion::new(0) { - PoolAssets::current_storage_version().put::(); + PoolAssets::in_code_storage_version().put::(); writes.saturating_inc(); } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index f576776696c..db1dfbd45d6 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -168,12 +168,12 @@ impl frame_support::traits::OnRuntimeUpgrade for InitStorageVersions { let mut writes = 0; if PolkadotXcm::on_chain_storage_version() == StorageVersion::new(0) { - PolkadotXcm::current_storage_version().put::(); + PolkadotXcm::in_code_storage_version().put::(); writes.saturating_inc(); } if Balances::on_chain_storage_version() == StorageVersion::new(0) { - Balances::current_storage_version().put::(); + Balances::in_code_storage_version().put::(); writes.saturating_inc(); } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index bd42a33370d..1c8c9aa2075 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -142,12 +142,12 @@ impl frame_support::traits::OnRuntimeUpgrade for InitStorageVersions { let mut writes = 0; if PolkadotXcm::on_chain_storage_version() == StorageVersion::new(0) { - PolkadotXcm::current_storage_version().put::(); + PolkadotXcm::in_code_storage_version().put::(); writes.saturating_inc(); } if Balances::on_chain_storage_version() == StorageVersion::new(0) { - Balances::current_storage_version().put::(); + Balances::in_code_storage_version().put::(); writes.saturating_inc(); } diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index 576a81834f8..b1b60a2d77d 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -33,6 +33,10 @@ node-cli = { package = "staging-node-cli", path = "../../substrate/bin/node/cli" kitchensink-runtime = { path = "../../substrate/bin/node/runtime" } chain-spec-builder = { package = "staging-chain-spec-builder", path = "../../substrate/bin/utils/chain-spec-builder" } subkey = { path = "../../substrate/bin/utils/subkey" } +frame-system = { path = "../../substrate/frame/system", default-features = false } +frame-support = { path = "../../substrate/frame/support", default-features = false } +frame-executive = { path = "../../substrate/frame/executive", default-features = false } +pallet-example-single-block-migrations = { path = "../../substrate/frame/examples/single-block-migrations" } # Substrate sc-network = { path = "../../substrate/client/network" } @@ -66,7 +70,7 @@ pallet-proxy = { path = "../../substrate/frame/proxy" } pallet-authorship = { path = "../../substrate/frame/authorship" } pallet-collective = { path = "../../substrate/frame/collective" } pallet-democracy = { path = "../../substrate/frame/democracy" } -frame-system = { path = "../../substrate/frame/system" } +pallet-scheduler = { path = "../../substrate/frame/scheduler" } # Primitives sp-io = { path = "../../substrate/primitives/io" } @@ -74,6 +78,7 @@ sp-api = { path = "../../substrate/primitives/api" } sp-core = { path = "../../substrate/primitives/core" } sp-keyring = { path = "../../substrate/primitives/keyring" } sp-runtime = { path = "../../substrate/primitives/runtime" } +sp-version = { path = "../../substrate/primitives/version" } # XCM xcm = { package = "staging-xcm", path = "../../polkadot/xcm" } diff --git a/docs/sdk/src/reference_docs/frame_runtime_migration.rs b/docs/sdk/src/reference_docs/frame_runtime_migration.rs deleted file mode 100644 index 0616ccbb6f5..00000000000 --- a/docs/sdk/src/reference_docs/frame_runtime_migration.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! # Runtime Runtime Upgrade and Testing -//! -//! -//! Notes: -//! -//! - Flow of things, when does `on_runtime_upgrade` get called. Link to to `Hooks` and its diagram -//! as source of truth. -//! - Data migration and when it is needed. -//! - Look into the pba-lecture. diff --git a/docs/sdk/src/reference_docs/frame_runtime_upgrades_and_migrations.rs b/docs/sdk/src/reference_docs/frame_runtime_upgrades_and_migrations.rs new file mode 100644 index 00000000000..7d870b43221 --- /dev/null +++ b/docs/sdk/src/reference_docs/frame_runtime_upgrades_and_migrations.rs @@ -0,0 +1,138 @@ +//! # Runtime Upgrades +//! +//! At their core, blockchain logic consists of +//! +//! 1. on-chain state and +//! 2. a state transition function +//! +//! In Substrate-based blockchains, state transition functions are referred to as +//! [runtimes](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/blockchain_state_machines/index.html). +//! +//! Traditionally, before Substrate, upgrading state transition functions required node +//! operators to download new software and restart their nodes in a process called +//! [forking](https://en.wikipedia.org/wiki/Fork_(blockchain)). +//! +//! Substrate-based blockchains do not require forking, and instead upgrade runtimes +//! in a process called "Runtime Upgrades". +//! +//! Forkless runtime upgrades are a defining feature of the Substrate framework. Updating the +//! runtime logic without forking the code base enables your blockchain to seemlessly evolve +//! over time in a deterministic, rules-based manner. It also removes ambiguity for node operators +//! and other participants in the network about what is the canonical runtime. +//! +//! This capability is possible due to the runtime of a blockchain existing in on-chain storage. +//! +//! ## Performing a Runtime Upgrade +//! +//! To upgrade a runtime, an [`Origin`](frame_system::RawOrigin) with the necesarry permissions +//! (usually via governance) changes the `:code` storage. Usually, this is performed via a call to +//! [`set_code`] (or [`set_code_without_checks`]) with the desired new runtime blob, scheduled +//! using [`pallet_scheduler`]. +//! +//! Prior to building the new runtime, don't forget to update the +//! [`RuntimeVersion`](sp_version::RuntimeVersion). +//! +//! # Migrations +//! +//! It is often desirable to define logic to execute immediately after runtime upgrades (see +//! [this diagram](frame::traits::Hooks)). +//! +//! Self-contained pieces of logic that execute after a runtime upgrade are called "Migrations". +//! +//! The typical use case of a migration is to 'migrate' pallet storage from one layout to another, +//! for example when the encoding of a storage item is changed. However, they can also execute +//! arbitary logic such as: +//! +//! - Calling arbitrary pallet methods +//! - Mutating arbitrary on-chain state +//! - Cleaning up some old storage items that are no longer needed +//! +//! ## Single Block Migrations +//! +//! - Execute immediately and entirely at the beginning of the block following +//! a runtime upgrade. +//! - Are suitable for migrations which are guaranteed to not exceed the block weight. +//! - Are simply implementations of [`OnRuntimeUpgrade`]. +//! +//! To learn best practices for writing single block pallet storage migrations, see the +//! [Single Block Migration Example Pallet](pallet_example_single_block_migrations). +//! +//! ### Scheduling the Single Block Migrations to Run Next Runtime Upgrade +//! +//! Schedule migrations to run next runtime upgrade passing them as a generic parameter to your +//! [`Executive`](frame_executive) pallet: +//! +//! ```ignore +//! /// Tuple of migrations (structs that implement `OnRuntimeUpgrade`) +//! type Migrations = ( +//! pallet_example_storage_migration::migrations::v1::versioned::MigrateV0ToV1, +//! MyCustomMigration, +//! // ...more migrations here +//! ); +//! pub type Executive = frame_executive::Executive< +//! Runtime, +//! Block, +//! frame_system::ChainContext, +//! Runtime, +//! AllPalletsWithSystem, +//! Migrations, // <-- pass your migrations to Executive here +//! >; +//! ``` +//! +//! ### Ensuring Single Block Migration Safety +//! +//! "My migration unit tests pass, so it should be safe to deploy right?" +//! +//! No! Unit tests execute the migration in a very simple test environment, and cannot account +//! for the complexities of a real runtime or real on-chain state. +//! +//! Prior to deploying migrations, it is critical to perform additional checks to ensure that when +//! run in our real runtime they will not brick the chain due to: +//! - Panicing +//! - Touching too many storage keys and resulting in an excessively large PoV +//! - Taking too long to execute +//! +//! [`try-runtime-cli`](https://github.com/paritytech/try-runtime-cli) has a sub-command +//! [`on-runtime-upgrade`](https://paritytech.github.io/try-runtime-cli/try_runtime_core/commands/enum.Action.html#variant.OnRuntimeUpgrade) +//! which is designed to help with exactly this. +//! +//! Developers MUST run this command before deploying migrations to ensure they will not +//! inadvertently result in a bricked chain. +//! +//! It is recommended to run as part of your CI pipeline. See the +//! [polkadot-sdk check-runtime-migration job](https://github.com/paritytech/polkadot-sdk/blob/4a293bc5a25be637c06ce950a34490706597615b/.gitlab/pipeline/check.yml#L103-L124) +//! for an example of how to configure this. +//! +//! ### Note on the Manipulability of PoV Size and Execution Time +//! +//! While [`try-runtime-cli`](https://github.com/paritytech/try-runtime-cli) can help ensure with +//! very high certainty that a migration will succeed given **existing** on-chain state, it cannot +//! prevent a malicious actor from manipulating state in a way that will cause the migration to take +//! longer or produce a PoV much larger than previously measured. +//! +//! Therefore, it is important to write migrations in such a way that the execution time or PoV size +//! it adds to the block cannot be easily manipulated. e.g., do not iterate over storage that can +//! quickly or cheaply be bloated. +//! +//! If writing your migration in such a way is not possible, a multi block migration should be used +//! instead. +//! +//! ### Other useful tools +//! +//! [`Chopsticks`](https://github.com/AcalaNetwork/chopsticks) is another tool in the Substrate +//! ecosystem which developers may find useful to use in addition to `try-runtime-cli` when testing +//! their single block migrations. +//! +//! ## Multi Block Migrations +//! +//! Safely and easily execute long-running migrations across multiple blocks. +//! +//! Suitable for migrations which could use arbitrary amounts of block weight. +//! +//! TODO: Link to multi block migration example/s once PR is merged (). +//! +//! [`GetStorageVersion`]: frame_support::traits::GetStorageVersion +//! [`OnRuntimeUpgrade`]: frame_support::traits::OnRuntimeUpgrade +//! [`StorageVersion`]: frame_support::traits::StorageVersion +//! [`set_code`]: frame_system::Call::set_code +//! [`set_code_without_checks`]: frame_system::Call::set_code_without_checks diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index 760bb442c16..b2c751420ce 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -92,9 +92,8 @@ pub mod cli; // TODO: @JoshOrndorff @kianenigma https://github.com/paritytech/polkadot-sdk-docs/issues/54 pub mod consensus_swapping; -/// Learn about all the advance ways to test your coordinate a rutnime upgrade and data migration. -// TODO: @liamaharon https://github.com/paritytech/polkadot-sdk-docs/issues/55 -pub mod frame_runtime_migration; +/// Learn about Runtime Upgrades and best practices for writing Migrations. +pub mod frame_runtime_upgrades_and_migrations; /// Learn about light nodes, how they function, and how Substrate-based chains come /// light-node-first out of the box. diff --git a/polkadot/node/service/src/parachains_db/upgrade.rs b/polkadot/node/service/src/parachains_db/upgrade.rs index d22eebb5c8d..2eceb391b15 100644 --- a/polkadot/node/service/src/parachains_db/upgrade.rs +++ b/polkadot/node/service/src/parachains_db/upgrade.rs @@ -93,7 +93,7 @@ pub(crate) fn try_upgrade_db( } /// Try upgrading parachain's database to the next version. -/// If successfull, it returns the current version. +/// If successful, it returns the current version. pub(crate) fn try_upgrade_db_to_next_version( db_path: &Path, db_kind: DatabaseKind, diff --git a/polkadot/runtime/common/src/assigned_slots/migration.rs b/polkadot/runtime/common/src/assigned_slots/migration.rs index ba3108c0aa3..def6bad692a 100644 --- a/polkadot/runtime/common/src/assigned_slots/migration.rs +++ b/polkadot/runtime/common/src/assigned_slots/migration.rs @@ -29,14 +29,14 @@ pub mod v1 { impl OnRuntimeUpgrade for VersionUncheckedMigrateToV1 { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { - let onchain_version = Pallet::::on_chain_storage_version(); - ensure!(onchain_version < 1, "assigned_slots::MigrateToV1 migration can be deleted"); + let on_chain_version = Pallet::::on_chain_storage_version(); + ensure!(on_chain_version < 1, "assigned_slots::MigrateToV1 migration can be deleted"); Ok(Default::default()) } fn on_runtime_upgrade() -> frame_support::weights::Weight { - let onchain_version = Pallet::::on_chain_storage_version(); - if onchain_version < 1 { + let on_chain_version = Pallet::::on_chain_storage_version(); + if on_chain_version < 1 { const MAX_PERMANENT_SLOTS: u32 = 100; const MAX_TEMPORARY_SLOTS: u32 = 100; @@ -52,8 +52,8 @@ pub mod v1 { #[cfg(feature = "try-runtime")] fn post_upgrade(_state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { - let onchain_version = Pallet::::on_chain_storage_version(); - ensure!(onchain_version == 1, "assigned_slots::MigrateToV1 needs to be run"); + let on_chain_version = Pallet::::on_chain_storage_version(); + ensure!(on_chain_version == 1, "assigned_slots::MigrateToV1 needs to be run"); assert_eq!(>::get(), 100); assert_eq!(>::get(), 100); Ok(()) diff --git a/polkadot/runtime/common/src/assigned_slots/mod.rs b/polkadot/runtime/common/src/assigned_slots/mod.rs index 3419e3497f7..4f032f4dfa3 100644 --- a/polkadot/runtime/common/src/assigned_slots/mod.rs +++ b/polkadot/runtime/common/src/assigned_slots/mod.rs @@ -107,7 +107,7 @@ type LeasePeriodOf = <::Leaser as Leaser>>::Le pub mod pallet { use super::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/polkadot/runtime/common/src/crowdloan/migration.rs b/polkadot/runtime/common/src/crowdloan/migration.rs index 5133c14ada9..3afd6b3fbc9 100644 --- a/polkadot/runtime/common/src/crowdloan/migration.rs +++ b/polkadot/runtime/common/src/crowdloan/migration.rs @@ -24,9 +24,9 @@ use frame_support::{ pub struct MigrateToTrackInactiveV2(sp_std::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToTrackInactiveV2 { fn on_runtime_upgrade() -> Weight { - let onchain_version = Pallet::::on_chain_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); - if onchain_version == 1 { + if on_chain_version == 1 { let mut translated = 0u64; for item in Funds::::iter_values() { let b = diff --git a/polkadot/runtime/common/src/crowdloan/mod.rs b/polkadot/runtime/common/src/crowdloan/mod.rs index 7d1b892dfa7..35d075f2ff6 100644 --- a/polkadot/runtime/common/src/crowdloan/mod.rs +++ b/polkadot/runtime/common/src/crowdloan/mod.rs @@ -180,7 +180,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); #[pallet::pallet] diff --git a/polkadot/runtime/common/src/paras_registrar/mod.rs b/polkadot/runtime/common/src/paras_registrar/mod.rs index 5450c4309e4..4541b88ec6f 100644 --- a/polkadot/runtime/common/src/paras_registrar/mod.rs +++ b/polkadot/runtime/common/src/paras_registrar/mod.rs @@ -106,7 +106,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/polkadot/runtime/parachains/src/configuration.rs b/polkadot/runtime/parachains/src/configuration.rs index 7cc5b31fc8f..b0e9d03df88 100644 --- a/polkadot/runtime/parachains/src/configuration.rs +++ b/polkadot/runtime/parachains/src/configuration.rs @@ -505,7 +505,7 @@ impl WeightInfo for TestWeightInfo { pub mod pallet { use super::*; - /// The current storage version. + /// The in-code storage version. /// /// v0-v1: /// v1-v2: diff --git a/polkadot/runtime/parachains/src/disputes.rs b/polkadot/runtime/parachains/src/disputes.rs index c2383dad305..da95b060c14 100644 --- a/polkadot/runtime/parachains/src/disputes.rs +++ b/polkadot/runtime/parachains/src/disputes.rs @@ -379,7 +379,7 @@ pub mod pallet { type WeightInfo: WeightInfo; } - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/polkadot/runtime/parachains/src/session_info/migration.rs b/polkadot/runtime/parachains/src/session_info/migration.rs index 228c1e3bb25..ea6f81834b5 100644 --- a/polkadot/runtime/parachains/src/session_info/migration.rs +++ b/polkadot/runtime/parachains/src/session_info/migration.rs @@ -18,5 +18,5 @@ use frame_support::traits::StorageVersion; -/// The current storage version. +/// The in-code storage version. pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); diff --git a/prdoc/pr_1554.prdoc b/prdoc/pr_1554.prdoc new file mode 100644 index 00000000000..bfce7c5edaf --- /dev/null +++ b/prdoc/pr_1554.prdoc @@ -0,0 +1,14 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Runtime Upgrade ref docs and Single Block Migration example pallet + +doc: + - audience: Runtime Dev + description: | + `frame_support::traits::GetStorageVersion::current_storage_version` has been renamed `frame_support::traits::GetStorageVersion::in_code_storage_version`. + A simple find-replace is sufficient to handle this change. + +crates: + - name: "frame-support" + diff --git a/substrate/client/executor/src/executor.rs b/substrate/client/executor/src/executor.rs index 499bb704b16..d56a3b389ef 100644 --- a/substrate/client/executor/src/executor.rs +++ b/substrate/client/executor/src/executor.rs @@ -518,7 +518,7 @@ where runtime_code, ext, heap_alloc_strategy, - |_, mut instance, _onchain_version, mut ext| { + |_, mut instance, _on_chain_version, mut ext| { with_externalities_safe(&mut **ext, move || instance.call_export(method, data)) }, ); @@ -682,18 +682,18 @@ impl CodeExecutor for NativeElseWasmExecut runtime_code, ext, heap_alloc_strategy, - |_, mut instance, onchain_version, mut ext| { - let onchain_version = - onchain_version.ok_or_else(|| Error::ApiError("Unknown version".into()))?; + |_, mut instance, on_chain_version, mut ext| { + let on_chain_version = + on_chain_version.ok_or_else(|| Error::ApiError("Unknown version".into()))?; let can_call_with = - onchain_version.can_call_with(&self.native_version.runtime_version); + on_chain_version.can_call_with(&self.native_version.runtime_version); if use_native && can_call_with { tracing::trace!( target: "executor", native = %self.native_version.runtime_version, - chain = %onchain_version, + chain = %on_chain_version, "Request for native execution succeeded", ); @@ -705,7 +705,7 @@ impl CodeExecutor for NativeElseWasmExecut tracing::trace!( target: "executor", native = %self.native_version.runtime_version, - chain = %onchain_version, + chain = %on_chain_version, "Request for native execution failed", ); } diff --git a/substrate/frame/alliance/src/migration.rs b/substrate/frame/alliance/src/migration.rs index e3a44a7887e..432f09a16f4 100644 --- a/substrate/frame/alliance/src/migration.rs +++ b/substrate/frame/alliance/src/migration.rs @@ -19,19 +19,19 @@ use crate::{Config, Pallet, Weight, LOG_TARGET}; use frame_support::{pallet_prelude::*, storage::migration, traits::OnRuntimeUpgrade}; use log; -/// The current storage version. +/// The in-code storage version. pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); /// Wrapper for all migrations of this pallet. pub fn migrate, I: 'static>() -> Weight { - let onchain_version = Pallet::::on_chain_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); let mut weight: Weight = Weight::zero(); - if onchain_version < 1 { + if on_chain_version < 1 { weight = weight.saturating_add(v0_to_v1::migrate::()); } - if onchain_version < 2 { + if on_chain_version < 2 { weight = weight.saturating_add(v1_to_v2::migrate::()); } diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs index cafe7bb1a3b..60316f8cdcf 100644 --- a/substrate/frame/assets/src/lib.rs +++ b/substrate/frame/assets/src/lib.rs @@ -208,7 +208,7 @@ pub mod pallet { }; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/substrate/frame/assets/src/migration.rs b/substrate/frame/assets/src/migration.rs index ff0ffbff0d3..dd7c12293e8 100644 --- a/substrate/frame/assets/src/migration.rs +++ b/substrate/frame/assets/src/migration.rs @@ -67,9 +67,9 @@ pub mod v1 { pub struct MigrateToV1(core::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV1 { fn on_runtime_upgrade() -> Weight { - let current_version = Pallet::::current_storage_version(); - let onchain_version = Pallet::::on_chain_storage_version(); - if onchain_version == 0 && current_version == 1 { + let in_code_version = Pallet::::in_code_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); + if on_chain_version == 0 && in_code_version == 1 { let mut translated = 0u64; Asset::::translate::< OldAssetDetails>, @@ -78,12 +78,12 @@ pub mod v1 { translated.saturating_inc(); Some(old_value.migrate_to_v1()) }); - current_version.put::>(); + in_code_version.put::>(); log::info!( target: LOG_TARGET, "Upgraded {} pools, storage to version {:?}", translated, - current_version + in_code_version ); T::DbWeight::get().reads_writes(translated + 1, translated + 1) } else { @@ -116,13 +116,13 @@ pub mod v1 { "the asset count before and after the migration should be the same" ); - let current_version = Pallet::::current_storage_version(); - let onchain_version = Pallet::::on_chain_storage_version(); + let in_code_version = Pallet::::in_code_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); - frame_support::ensure!(current_version == 1, "must_upgrade"); + frame_support::ensure!(in_code_version == 1, "must_upgrade"); ensure!( - current_version == onchain_version, - "after migration, the current_version and onchain_version should be the same" + in_code_version == on_chain_version, + "after migration, the in_code_version and on_chain_version should be the same" ); Asset::::iter().try_for_each(|(_id, asset)| -> Result<(), TryRuntimeError> { diff --git a/substrate/frame/balances/src/lib.rs b/substrate/frame/balances/src/lib.rs index 7dd087eabd6..e87aa6f9311 100644 --- a/substrate/frame/balances/src/lib.rs +++ b/substrate/frame/balances/src/lib.rs @@ -320,7 +320,7 @@ pub mod pallet { type MaxFreezes: Get; } - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: frame_support::traits::StorageVersion = frame_support::traits::StorageVersion::new(1); diff --git a/substrate/frame/balances/src/migration.rs b/substrate/frame/balances/src/migration.rs index ba6819ec6e8..38d9c07ff7e 100644 --- a/substrate/frame/balances/src/migration.rs +++ b/substrate/frame/balances/src/migration.rs @@ -22,9 +22,9 @@ use frame_support::{ }; fn migrate_v0_to_v1, I: 'static>(accounts: &[T::AccountId]) -> Weight { - let onchain_version = Pallet::::on_chain_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); - if onchain_version == 0 { + if on_chain_version == 0 { let total = accounts .iter() .map(|a| Pallet::::total_balance(a)) @@ -76,9 +76,9 @@ impl, A: Get>, I: 'static> OnRuntimeUpgrade pub struct ResetInactive(PhantomData<(T, I)>); impl, I: 'static> OnRuntimeUpgrade for ResetInactive { fn on_runtime_upgrade() -> Weight { - let onchain_version = Pallet::::on_chain_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); - if onchain_version == 1 { + if on_chain_version == 1 { // Remove the old `StorageVersion` type. frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix( Pallet::::name().as_bytes(), diff --git a/substrate/frame/collective/src/lib.rs b/substrate/frame/collective/src/lib.rs index c084784e0a9..dd481b53681 100644 --- a/substrate/frame/collective/src/lib.rs +++ b/substrate/frame/collective/src/lib.rs @@ -176,7 +176,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); #[pallet::pallet] diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs index d8939ee88ba..32d789a458f 100644 --- a/substrate/frame/contracts/src/lib.rs +++ b/substrate/frame/contracts/src/lib.rs @@ -234,7 +234,7 @@ pub mod pallet { use frame_system::pallet_prelude::*; use sp_runtime::Perbill; - /// The current storage version. + /// The in-code storage version. pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(15); #[pallet::pallet] diff --git a/substrate/frame/contracts/src/migration.rs b/substrate/frame/contracts/src/migration.rs index 6d61cb6b1e1..f30ae1ebfad 100644 --- a/substrate/frame/contracts/src/migration.rs +++ b/substrate/frame/contracts/src/migration.rs @@ -263,10 +263,10 @@ impl Migration { impl OnRuntimeUpgrade for Migration { fn on_runtime_upgrade() -> Weight { let name = >::name(); - let current_version = >::current_storage_version(); + let in_code_version = >::in_code_storage_version(); let on_chain_version = >::on_chain_storage_version(); - if on_chain_version == current_version { + if on_chain_version == in_code_version { log::warn!( target: LOG_TARGET, "{name}: No Migration performed storage_version = latest_version = {:?}", @@ -289,7 +289,7 @@ impl OnRuntimeUpgrade for Migration OnRuntimeUpgrade for Migration>::on_chain_storage_version(); - let current_version = >::current_storage_version(); + let in_code_version = >::in_code_storage_version(); - if on_chain_version == current_version { + if on_chain_version == in_code_version { return Ok(Default::default()) } log::debug!( target: LOG_TARGET, - "Requested migration of {} from {:?}(on-chain storage version) to {:?}(current storage version)", - >::name(), on_chain_version, current_version + "Requested migration of {} from {:?}(on-chain storage version) to {:?}(in-code storage version)", + >::name(), on_chain_version, in_code_version ); ensure!( - T::Migrations::is_upgrade_supported(on_chain_version, current_version), - "Unsupported upgrade: VERSION_RANGE should be (on-chain storage version + 1, current storage version)" + T::Migrations::is_upgrade_supported(on_chain_version, in_code_version), + "Unsupported upgrade: VERSION_RANGE should be (on-chain storage version + 1, in-code storage version)" ); Ok(Default::default()) @@ -421,7 +421,7 @@ impl Migration { }, StepResult::Completed { steps_done } => { in_progress_version.put::>(); - if >::current_storage_version() != in_progress_version { + if >::in_code_storage_version() != in_progress_version { log::info!( target: LOG_TARGET, "{name}: Next migration is {:?},", diff --git a/substrate/frame/contracts/src/migration/v09.rs b/substrate/frame/contracts/src/migration/v09.rs index 98fcccc2c0b..f19bff9d674 100644 --- a/substrate/frame/contracts/src/migration/v09.rs +++ b/substrate/frame/contracts/src/migration/v09.rs @@ -28,7 +28,7 @@ use frame_support::{pallet_prelude::*, storage_alias, DefaultNoBound, Identity}; use sp_runtime::TryRuntimeError; use sp_std::prelude::*; -mod old { +mod v8 { use super::*; #[derive(Encode, Decode)] @@ -50,14 +50,14 @@ mod old { #[cfg(feature = "runtime-benchmarks")] pub fn store_old_dummy_code(len: usize) { use sp_runtime::traits::Hash; - let module = old::PrefabWasmModule { + let module = v8::PrefabWasmModule { instruction_weights_version: 0, initial: 0, maximum: 0, code: vec![42u8; len], }; let hash = T::Hashing::hash(&module.code); - old::CodeStorage::::insert(hash, module); + v8::CodeStorage::::insert(hash, module); } #[derive(Encode, Decode)] @@ -89,9 +89,9 @@ impl MigrationStep for Migration { fn step(&mut self) -> (IsFinished, Weight) { let mut iter = if let Some(last_key) = self.last_code_hash.take() { - old::CodeStorage::::iter_from(old::CodeStorage::::hashed_key_for(last_key)) + v8::CodeStorage::::iter_from(v8::CodeStorage::::hashed_key_for(last_key)) } else { - old::CodeStorage::::iter() + v8::CodeStorage::::iter() }; if let Some((key, old)) = iter.next() { @@ -115,7 +115,7 @@ impl MigrationStep for Migration { #[cfg(feature = "try-runtime")] fn pre_upgrade_step() -> Result, TryRuntimeError> { - let sample: Vec<_> = old::CodeStorage::::iter().take(100).collect(); + let sample: Vec<_> = v8::CodeStorage::::iter().take(100).collect(); log::debug!(target: LOG_TARGET, "Taking sample of {} contract codes", sample.len()); Ok(sample.encode()) @@ -123,7 +123,7 @@ impl MigrationStep for Migration { #[cfg(feature = "try-runtime")] fn post_upgrade_step(state: Vec) -> Result<(), TryRuntimeError> { - let sample = , old::PrefabWasmModule)> as Decode>::decode(&mut &state[..]) + let sample = , v8::PrefabWasmModule)> as Decode>::decode(&mut &state[..]) .expect("pre_upgrade_step provides a valid state; qed"); log::debug!(target: LOG_TARGET, "Validating sample of {} contract codes", sample.len()); diff --git a/substrate/frame/contracts/src/migration/v10.rs b/substrate/frame/contracts/src/migration/v10.rs index d64673aac7d..1bee86e6a77 100644 --- a/substrate/frame/contracts/src/migration/v10.rs +++ b/substrate/frame/contracts/src/migration/v10.rs @@ -47,7 +47,7 @@ use sp_runtime::{ }; use sp_std::prelude::*; -mod old { +mod v9 { use super::*; pub type BalanceOf = ( ) where OldCurrency: ReservableCurrency<::AccountId> + 'static, { - let info = old::ContractInfo { + let info = v9::ContractInfo { trie_id: info.trie_id, code_hash: info.code_hash, storage_bytes: Default::default(), @@ -94,7 +94,7 @@ pub fn store_old_contract_info( storage_item_deposit: Default::default(), storage_base_deposit: Default::default(), }; - old::ContractInfoOf::::insert(account, info); + v9::ContractInfoOf::::insert(account, info); } #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebugNoBound, TypeInfo, MaxEncodedLen)] @@ -120,9 +120,9 @@ where pub code_hash: CodeHash, storage_bytes: u32, storage_items: u32, - pub storage_byte_deposit: old::BalanceOf, - storage_item_deposit: old::BalanceOf, - storage_base_deposit: old::BalanceOf, + pub storage_byte_deposit: v9::BalanceOf, + storage_item_deposit: v9::BalanceOf, + storage_base_deposit: v9::BalanceOf, } #[derive(Encode, Decode, MaxEncodedLen, DefaultNoBound)] @@ -152,7 +152,7 @@ fn deposit_address( impl MigrationStep for Migration where OldCurrency: ReservableCurrency<::AccountId> - + Inspect<::AccountId, Balance = old::BalanceOf>, + + Inspect<::AccountId, Balance = v9::BalanceOf>, { const VERSION: u16 = 10; @@ -162,11 +162,11 @@ where fn step(&mut self) -> (IsFinished, Weight) { let mut iter = if let Some(last_account) = self.last_account.take() { - old::ContractInfoOf::::iter_from( - old::ContractInfoOf::::hashed_key_for(last_account), + v9::ContractInfoOf::::iter_from( + v9::ContractInfoOf::::hashed_key_for(last_account), ) } else { - old::ContractInfoOf::::iter() + v9::ContractInfoOf::::iter() }; if let Some((account, contract)) = iter.next() { @@ -276,7 +276,7 @@ where #[cfg(feature = "try-runtime")] fn pre_upgrade_step() -> Result, TryRuntimeError> { - let sample: Vec<_> = old::ContractInfoOf::::iter().take(10).collect(); + let sample: Vec<_> = v9::ContractInfoOf::::iter().take(10).collect(); log::debug!(target: LOG_TARGET, "Taking sample of {} contracts", sample.len()); Ok(sample.encode()) @@ -284,7 +284,7 @@ where #[cfg(feature = "try-runtime")] fn post_upgrade_step(state: Vec) -> Result<(), TryRuntimeError> { - let sample = )> as Decode>::decode( + let sample = )> as Decode>::decode( &mut &state[..], ) .expect("pre_upgrade_step provides a valid state; qed"); diff --git a/substrate/frame/contracts/src/migration/v11.rs b/substrate/frame/contracts/src/migration/v11.rs index a5b11f6e089..9bfbb25edfb 100644 --- a/substrate/frame/contracts/src/migration/v11.rs +++ b/substrate/frame/contracts/src/migration/v11.rs @@ -29,7 +29,7 @@ use sp_runtime::TryRuntimeError; use codec::{Decode, Encode}; use frame_support::{pallet_prelude::*, storage_alias, DefaultNoBound}; use sp_std::{marker::PhantomData, prelude::*}; -mod old { +mod v10 { use super::*; #[derive(Encode, Decode, TypeInfo, MaxEncodedLen)] @@ -51,11 +51,11 @@ pub struct DeletionQueueManager { #[cfg(any(feature = "runtime-benchmarks", feature = "try-runtime"))] pub fn fill_old_queue(len: usize) { - let queue: Vec = - core::iter::repeat_with(|| old::DeletedContract { trie_id: Default::default() }) + let queue: Vec = + core::iter::repeat_with(|| v10::DeletedContract { trie_id: Default::default() }) .take(len) .collect(); - old::DeletionQueue::::set(Some(queue)); + v10::DeletionQueue::::set(Some(queue)); } #[storage_alias] @@ -80,7 +80,7 @@ impl MigrationStep for Migration { } fn step(&mut self) -> (IsFinished, Weight) { - let Some(old_queue) = old::DeletionQueue::::take() else { + let Some(old_queue) = v10::DeletionQueue::::take() else { return (IsFinished::Yes, Weight::zero()) }; let len = old_queue.len(); @@ -106,7 +106,7 @@ impl MigrationStep for Migration { #[cfg(feature = "try-runtime")] fn pre_upgrade_step() -> Result, TryRuntimeError> { - let old_queue = old::DeletionQueue::::take().unwrap_or_default(); + let old_queue = v10::DeletionQueue::::take().unwrap_or_default(); if old_queue.is_empty() { let len = 10u32; diff --git a/substrate/frame/contracts/src/migration/v12.rs b/substrate/frame/contracts/src/migration/v12.rs index 7dee3150310..d9128286df3 100644 --- a/substrate/frame/contracts/src/migration/v12.rs +++ b/substrate/frame/contracts/src/migration/v12.rs @@ -34,7 +34,7 @@ use sp_runtime::TryRuntimeError; use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128, Saturating}; use sp_std::prelude::*; -mod old { +mod v11 { use super::*; pub type BalanceOf = , #[codec(compact)] - deposit: old::BalanceOf, + deposit: v11::BalanceOf, #[codec(compact)] refcount: u64, determinism: Determinism, @@ -112,17 +112,17 @@ where let hash = T::Hashing::hash(&code); PristineCode::::insert(hash, code.clone()); - let module = old::PrefabWasmModule { + let module = v11::PrefabWasmModule { instruction_weights_version: Default::default(), initial: Default::default(), maximum: Default::default(), code, determinism: Determinism::Enforced, }; - old::CodeStorage::::insert(hash, module); + v11::CodeStorage::::insert(hash, module); - let info = old::OwnerInfo { owner: account, deposit: u32::MAX.into(), refcount: u64::MAX }; - old::OwnerInfoOf::::insert(hash, info); + let info = v11::OwnerInfo { owner: account, deposit: u32::MAX.into(), refcount: u64::MAX }; + v11::OwnerInfoOf::::insert(hash, info); } #[derive(Encode, Decode, MaxEncodedLen, DefaultNoBound)] @@ -148,16 +148,16 @@ where fn step(&mut self) -> (IsFinished, Weight) { let mut iter = if let Some(last_key) = self.last_code_hash.take() { - old::OwnerInfoOf::::iter_from( - old::OwnerInfoOf::::hashed_key_for(last_key), + v11::OwnerInfoOf::::iter_from( + v11::OwnerInfoOf::::hashed_key_for(last_key), ) } else { - old::OwnerInfoOf::::iter() + v11::OwnerInfoOf::::iter() }; if let Some((hash, old_info)) = iter.next() { log::debug!(target: LOG_TARGET, "Migrating OwnerInfo for code_hash {:?}", hash); - let module = old::CodeStorage::::take(hash) + let module = v11::CodeStorage::::take(hash) .expect(format!("No PrefabWasmModule found for code_hash: {:?}", hash).as_str()); let code_len = module.code.len(); @@ -184,7 +184,7 @@ where let bytes_before = module .encoded_size() .saturating_add(code_len) - .saturating_add(old::OwnerInfo::::max_encoded_len()) + .saturating_add(v11::OwnerInfo::::max_encoded_len()) as u32; let items_before = 3u32; let deposit_expected_before = price_per_byte @@ -241,10 +241,10 @@ where fn pre_upgrade_step() -> Result, TryRuntimeError> { let len = 100; log::debug!(target: LOG_TARGET, "Taking sample of {} OwnerInfo(s)", len); - let sample: Vec<_> = old::OwnerInfoOf::::iter() + let sample: Vec<_> = v11::OwnerInfoOf::::iter() .take(len) .map(|(k, v)| { - let module = old::CodeStorage::::get(k) + let module = v11::CodeStorage::::get(k) .expect("No PrefabWasmModule found for code_hash: {:?}"); let info: CodeInfo = CodeInfo { determinism: module.determinism, @@ -258,9 +258,9 @@ where .collect(); let storage: u32 = - old::CodeStorage::::iter().map(|(_k, v)| v.encoded_size() as u32).sum(); - let mut deposit: old::BalanceOf = Default::default(); - old::OwnerInfoOf::::iter().for_each(|(_k, v)| deposit += v.deposit); + v11::CodeStorage::::iter().map(|(_k, v)| v.encoded_size() as u32).sum(); + let mut deposit: v11::BalanceOf = Default::default(); + v11::OwnerInfoOf::::iter().for_each(|(_k, v)| deposit += v.deposit); Ok((sample, deposit, storage).encode()) } @@ -269,7 +269,7 @@ where fn post_upgrade_step(state: Vec) -> Result<(), TryRuntimeError> { let state = <( Vec<(CodeHash, CodeInfo)>, - old::BalanceOf, + v11::BalanceOf, u32, ) as Decode>::decode(&mut &state[..]) .unwrap(); @@ -283,7 +283,7 @@ where ensure!(info.refcount == old.refcount, "invalid refcount"); } - if let Some((k, _)) = old::CodeStorage::::iter().next() { + if let Some((k, _)) = v11::CodeStorage::::iter().next() { log::warn!( target: LOG_TARGET, "CodeStorage is still NOT empty, found code_hash: {:?}", @@ -292,7 +292,7 @@ where } else { log::debug!(target: LOG_TARGET, "CodeStorage is empty."); } - if let Some((k, _)) = old::OwnerInfoOf::::iter().next() { + if let Some((k, _)) = v11::OwnerInfoOf::::iter().next() { log::warn!( target: LOG_TARGET, "OwnerInfoOf is still NOT empty, found code_hash: {:?}", @@ -302,7 +302,7 @@ where log::debug!(target: LOG_TARGET, "OwnerInfoOf is empty."); } - let mut deposit: old::BalanceOf = Default::default(); + let mut deposit: v11::BalanceOf = Default::default(); let mut items = 0u32; let mut storage_info = 0u32; CodeInfoOf::::iter().for_each(|(_k, v)| { diff --git a/substrate/frame/contracts/src/migration/v13.rs b/substrate/frame/contracts/src/migration/v13.rs index dd2eb12eb62..498c44d53ab 100644 --- a/substrate/frame/contracts/src/migration/v13.rs +++ b/substrate/frame/contracts/src/migration/v13.rs @@ -28,7 +28,7 @@ use frame_support::{pallet_prelude::*, storage_alias, DefaultNoBound}; use sp_runtime::BoundedBTreeMap; use sp_std::prelude::*; -mod old { +mod v12 { use super::*; #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] @@ -59,7 +59,7 @@ pub fn store_old_contract_info(account: T::AccountId, info: crate::Co let entropy = (b"contract_depo_v1", account.clone()).using_encoded(T::Hashing::hash); let deposit_account = Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) .expect("infinite length input; no invalid inputs for type; qed"); - let info = old::ContractInfo { + let info = v12::ContractInfo { trie_id: info.trie_id.clone(), deposit_account, code_hash: info.code_hash, @@ -69,7 +69,7 @@ pub fn store_old_contract_info(account: T::AccountId, info: crate::Co storage_item_deposit: Default::default(), storage_base_deposit: Default::default(), }; - old::ContractInfoOf::::insert(account, info); + v12::ContractInfoOf::::insert(account, info); } #[storage_alias] @@ -104,11 +104,11 @@ impl MigrationStep for Migration { fn step(&mut self) -> (IsFinished, Weight) { let mut iter = if let Some(last_account) = self.last_account.take() { - old::ContractInfoOf::::iter_from(old::ContractInfoOf::::hashed_key_for( + v12::ContractInfoOf::::iter_from(v12::ContractInfoOf::::hashed_key_for( last_account, )) } else { - old::ContractInfoOf::::iter() + v12::ContractInfoOf::::iter() }; if let Some((key, old)) = iter.next() { diff --git a/substrate/frame/contracts/src/migration/v14.rs b/substrate/frame/contracts/src/migration/v14.rs index 94534d05fdf..09da09e5bcf 100644 --- a/substrate/frame/contracts/src/migration/v14.rs +++ b/substrate/frame/contracts/src/migration/v14.rs @@ -44,7 +44,7 @@ use sp_runtime::{traits::Zero, Saturating}; #[cfg(feature = "try-runtime")] use sp_std::collections::btree_map::BTreeMap; -mod old { +mod v13 { use super::*; pub type BalanceOf = , #[codec(compact)] - pub deposit: old::BalanceOf, + pub deposit: v13::BalanceOf, #[codec(compact)] pub refcount: u64, pub determinism: Determinism, @@ -86,14 +86,14 @@ where let code = vec![42u8; len as usize]; let hash = T::Hashing::hash(&code); - let info = old::CodeInfo { + let info = v13::CodeInfo { owner: account, deposit: 10_000u32.into(), refcount: u64::MAX, determinism: Determinism::Enforced, code_len: len, }; - old::CodeInfoOf::::insert(hash, info); + v13::CodeInfoOf::::insert(hash, info); } #[cfg(feature = "try-runtime")] @@ -105,9 +105,9 @@ where OldCurrency: ReservableCurrency<::AccountId>, { /// Total reserved balance as code upload deposit for the owner. - reserved: old::BalanceOf, + reserved: v13::BalanceOf, /// Total balance of the owner. - total: old::BalanceOf, + total: v13::BalanceOf, } #[derive(Encode, Decode, MaxEncodedLen, DefaultNoBound)] @@ -134,11 +134,11 @@ where fn step(&mut self) -> (IsFinished, Weight) { let mut iter = if let Some(last_hash) = self.last_code_hash.take() { - old::CodeInfoOf::::iter_from( - old::CodeInfoOf::::hashed_key_for(last_hash), + v13::CodeInfoOf::::iter_from( + v13::CodeInfoOf::::hashed_key_for(last_hash), ) } else { - old::CodeInfoOf::::iter() + v13::CodeInfoOf::::iter() }; if let Some((hash, code_info)) = iter.next() { @@ -194,7 +194,7 @@ where #[cfg(feature = "try-runtime")] fn pre_upgrade_step() -> Result, TryRuntimeError> { - let info: Vec<_> = old::CodeInfoOf::::iter().collect(); + let info: Vec<_> = v13::CodeInfoOf::::iter().collect(); let mut owner_balance_allocation = BTreeMap::, BalanceAllocation>::new(); diff --git a/substrate/frame/contracts/src/migration/v15.rs b/substrate/frame/contracts/src/migration/v15.rs index 180fe855ca6..c77198d6fea 100644 --- a/substrate/frame/contracts/src/migration/v15.rs +++ b/substrate/frame/contracts/src/migration/v15.rs @@ -46,7 +46,7 @@ use sp_runtime::{traits::Zero, Saturating}; #[cfg(feature = "try-runtime")] use sp_std::vec::Vec; -mod old { +mod v14 { use super::*; #[derive( @@ -81,7 +81,7 @@ pub fn store_old_contract_info(account: T::AccountId, info: crate::Co let entropy = (b"contract_depo_v1", account.clone()).using_encoded(T::Hashing::hash); let deposit_account = Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) .expect("infinite length input; no invalid inputs for type; qed"); - let info = old::ContractInfo { + let info = v14::ContractInfo { trie_id: info.trie_id.clone(), deposit_account, code_hash: info.code_hash, @@ -92,7 +92,7 @@ pub fn store_old_contract_info(account: T::AccountId, info: crate::Co storage_base_deposit: info.storage_base_deposit(), delegate_dependencies: info.delegate_dependencies().clone(), }; - old::ContractInfoOf::::insert(account, info); + v14::ContractInfoOf::::insert(account, info); } #[derive(Encode, Decode, CloneNoBound, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] @@ -127,11 +127,11 @@ impl MigrationStep for Migration { fn step(&mut self) -> (IsFinished, Weight) { let mut iter = if let Some(last_account) = self.last_account.take() { - old::ContractInfoOf::::iter_from(old::ContractInfoOf::::hashed_key_for( + v14::ContractInfoOf::::iter_from(v14::ContractInfoOf::::hashed_key_for( last_account, )) } else { - old::ContractInfoOf::::iter() + v14::ContractInfoOf::::iter() }; if let Some((account, old_contract)) = iter.next() { @@ -243,11 +243,11 @@ impl MigrationStep for Migration { #[cfg(feature = "try-runtime")] fn pre_upgrade_step() -> Result, TryRuntimeError> { - let sample: Vec<_> = old::ContractInfoOf::::iter().take(100).collect(); + let sample: Vec<_> = v14::ContractInfoOf::::iter().take(100).collect(); log::debug!(target: LOG_TARGET, "Taking sample of {} contracts", sample.len()); - let state: Vec<(T::AccountId, old::ContractInfo, BalanceOf, BalanceOf)> = sample + let state: Vec<(T::AccountId, v14::ContractInfo, BalanceOf, BalanceOf)> = sample .iter() .map(|(account, contract)| { ( @@ -265,7 +265,7 @@ impl MigrationStep for Migration { #[cfg(feature = "try-runtime")] fn post_upgrade_step(state: Vec) -> Result<(), TryRuntimeError> { let sample = - , BalanceOf, BalanceOf)> as Decode>::decode( + , BalanceOf, BalanceOf)> as Decode>::decode( &mut &state[..], ) .expect("pre_upgrade_step provides a valid state; qed"); diff --git a/substrate/frame/democracy/src/lib.rs b/substrate/frame/democracy/src/lib.rs index 089556191cd..08e2a7599f5 100644 --- a/substrate/frame/democracy/src/lib.rs +++ b/substrate/frame/democracy/src/lib.rs @@ -211,7 +211,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/substrate/frame/election-provider-multi-phase/src/lib.rs b/substrate/frame/election-provider-multi-phase/src/lib.rs index 4f43f89abed..6bf4dfe4f1e 100644 --- a/substrate/frame/election-provider-multi-phase/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/src/lib.rs @@ -1343,7 +1343,7 @@ pub mod pallet { #[pallet::getter(fn minimum_untrusted_score)] pub type MinimumUntrustedScore = StorageValue<_, ElectionScore>; - /// The current storage version. + /// The in-code storage version. /// /// v1: https://github.com/paritytech/substrate/pull/12237/ const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); diff --git a/substrate/frame/election-provider-multi-phase/src/migrations.rs b/substrate/frame/election-provider-multi-phase/src/migrations.rs index 50b821e6db6..156f1c02e27 100644 --- a/substrate/frame/election-provider-multi-phase/src/migrations.rs +++ b/substrate/frame/election-provider-multi-phase/src/migrations.rs @@ -27,12 +27,12 @@ pub mod v1 { pub struct MigrateToV1(sp_std::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV1 { fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let current = Pallet::::in_code_storage_version(); let onchain = Pallet::::on_chain_storage_version(); log!( info, - "Running migration with current storage version {:?} / onchain {:?}", + "Running migration with in-code storage version {:?} / onchain {:?}", current, onchain ); diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs index a078361a5f7..308f2cdc1aa 100644 --- a/substrate/frame/elections-phragmen/src/lib.rs +++ b/substrate/frame/elections-phragmen/src/lib.rs @@ -188,7 +188,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); #[pallet::pallet] diff --git a/substrate/frame/examples/Cargo.toml b/substrate/frame/examples/Cargo.toml index eb6355edd31..45c7440eb89 100644 --- a/substrate/frame/examples/Cargo.toml +++ b/substrate/frame/examples/Cargo.toml @@ -23,6 +23,7 @@ pallet-example-frame-crate = { path = "frame-crate", default-features = false } pallet-example-kitchensink = { path = "kitchensink", default-features = false } pallet-example-offchain-worker = { path = "offchain-worker", default-features = false } pallet-example-split = { path = "split", default-features = false } +pallet-example-single-block-migrations = { path = "single-block-migrations", default-features = false } pallet-example-tasks = { path = "tasks", default-features = false } [features] @@ -34,6 +35,7 @@ std = [ "pallet-example-frame-crate/std", "pallet-example-kitchensink/std", "pallet-example-offchain-worker/std", + "pallet-example-single-block-migrations/std", "pallet-example-split/std", "pallet-example-tasks/std", ] @@ -43,6 +45,7 @@ try-runtime = [ "pallet-example-basic/try-runtime", "pallet-example-kitchensink/try-runtime", "pallet-example-offchain-worker/try-runtime", + "pallet-example-single-block-migrations/try-runtime", "pallet-example-split/try-runtime", "pallet-example-tasks/try-runtime", ] diff --git a/substrate/frame/examples/single-block-migrations/Cargo.toml b/substrate/frame/examples/single-block-migrations/Cargo.toml new file mode 100644 index 00000000000..5059b2433c7 --- /dev/null +++ b/substrate/frame/examples/single-block-migrations/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "pallet-example-single-block-migrations" +version = "0.0.1" +authors.workspace = true +edition.workspace = true +license = "MIT-0" +homepage = "https://substrate.io" +repository.workspace = true +description = "FRAME example pallet demonstrating best-practices for writing storage migrations." +publish = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +docify = { version = "0.2.3", default-features = false } +log = { version = "0.4.20", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +frame-support = { path = "../../support", default-features = false } +frame-executive = { path = "../../executive", default-features = false } +frame-system = { path = "../../system", default-features = false } +frame-try-runtime = { path = "../../try-runtime", default-features = false, optional = true } +pallet-balances = { path = "../../balances", default-features = false } +sp-std = { path = "../../../primitives/std", default-features = false } +sp-runtime = { path = "../../../primitives/runtime", default-features = false } +sp-core = { path = "../../../primitives/core", default-features = false } +sp-io = { path = "../../../primitives/io", default-features = false } +sp-version = { path = "../../../primitives/version", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-executive/std", + "frame-support/std", + "frame-system/std", + "frame-try-runtime/std", + "log/std", + "pallet-balances/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "sp-version/std", +] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-balances/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/substrate/frame/examples/single-block-migrations/src/lib.rs b/substrate/frame/examples/single-block-migrations/src/lib.rs new file mode 100644 index 00000000000..86a9e5d6e95 --- /dev/null +++ b/substrate/frame/examples/single-block-migrations/src/lib.rs @@ -0,0 +1,213 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! # Single Block Migration Example Pallet +//! +//! An example pallet demonstrating best-practices for writing single-block migrations in the +//! context of upgrading pallet storage. +//! +//! ## Forwarning +//! +//! Single block migrations **MUST** execute in a single block, therefore when executed on a +//! parachain are only appropriate when guaranteed to not exceed block weight limits. If a +//! parachain submits a block that exceeds the block weight limit it will **brick the chain**! +//! +//! If weight is a concern or you are not sure which type of migration to use, you should probably +//! use a multi-block migration. +//! +//! TODO: Link above to multi-block migration example. +//! +//! ## Pallet Overview +//! +//! This example pallet contains a single storage item [`Value`](pallet::Value), which may be set by +//! any signed origin by calling the [`set_value`](crate::Call::set_value) extrinsic. +//! +//! For the purposes of this exercise, we imagine that in [`StorageVersion`] V0 of this pallet +//! [`Value`](pallet::Value) is a `u32`, and this what is currently stored on-chain. +//! +//! ```ignore +//! // (Old) Storage Version V0 representation of `Value` +//! #[pallet::storage] +//! pub type Value = StorageValue<_, u32>; +//! ``` +//! +//! In [`StorageVersion`] V1 of the pallet a new struct [`CurrentAndPreviousValue`] is introduced: +#![doc = docify::embed!("src/lib.rs", CurrentAndPreviousValue)] +//! and [`Value`](pallet::Value) is updated to store this new struct instead of a `u32`: +#![doc = docify::embed!("src/lib.rs", Value)] +//! +//! In StorageVersion V1 of the pallet when [`set_value`](crate::Call::set_value) is called, the +//! new value is stored in the `current` field of [`CurrentAndPreviousValue`], and the previous +//! value (if it exists) is stored in the `previous` field. +#![doc = docify::embed!("src/lib.rs", pallet_calls)] +//! +//! ## Why a migration is necessary +//! +//! Without a migration, there will be a discrepancy between the on-chain storage for [`Value`] (in +//! V0 it is a `u32`) and the current storage for [`Value`] (in V1 it was changed to a +//! [`CurrentAndPreviousValue`] struct). +//! +//! The on-chain storage for [`Value`] would be a `u32` but the runtime would try to read it as a +//! [`CurrentAndPreviousValue`]. This would result in unacceptable undefined behavior. +//! +//! ## Adding a migration module +//! +//! Writing a pallets migrations in a seperate module is strongly recommended. +//! +//! Here's how the migration module is defined for this pallet: +//! +//! ```text +//! substrate/frame/examples/single-block-migrations/src/ +//! ├── lib.rs <-- pallet definition +//! ├── Cargo.toml <-- pallet manifest +//! └── migrations/ +//! ├── mod.rs <-- migrations module definition +//! └── v1.rs <-- migration logic for the V0 to V1 transition +//! ``` +//! +//! This structure allows keeping migration logic separate from the pallet logic and +//! easily adding new migrations in the future. +//! +//! ## Writing the Migration +//! +//! All code related to the migration can be found under +//! [`v1.rs`](migrations::v1). +//! +//! See the migration source code for detailed comments. +//! +//! To keep the migration logic organised, it is split across additional modules: +//! +//! ### `mod v0` +//! +//! Here we define a [`storage_alias`](frame_support::storage_alias) for the old v0 [`Value`] +//! format. +//! +//! This allows reading the old v0 value from storage during the migration. +//! +//! ### `mod version_unchecked` +//! +//! Here we define our raw migration logic, +//! `version_unchecked::MigrateV0ToV1` which implements the [`OnRuntimeUpgrade`] trait. +//! +//! Importantly, it is kept in a private module so that it cannot be accidentally used in a runtime. +//! +//! Private modules cannot be referenced in docs, so please read the code directly. +//! +//! #### Standalone Struct or Pallet Hook? +//! +//! Note that the storage migration logic is attached to a standalone struct implementing +//! [`OnRuntimeUpgrade`], rather than implementing the +//! [`Hooks::on_runtime_upgrade`](frame_support::traits::Hooks::on_runtime_upgrade) hook directly on +//! the pallet. The pallet hook is better suited for special types of logic that need to execute on +//! every runtime upgrade, but not so much for one-off storage migrations. +//! +//! ### `pub mod versioned` +//! +//! Here, `version_unchecked::MigrateV0ToV1` is wrapped in a +//! [`VersionedMigration`] to define +//! [`versioned::MigrateV0ToV1`](crate::migrations::v1::versioned::MigrateV0ToV1), which may be used +//! in runtimes. +//! +//! Using [`VersionedMigration`] ensures that +//! - The migration only runs once when the on-chain storage version is `0` +//! - The on-chain storage version is updated to `1` after the migration executes +//! - Reads and writes from checking and setting the on-chain storage version are accounted for in +//! the final [`Weight`](frame_support::weights::Weight) +//! +//! This is the only public module exported from `v1`. +//! +//! ### `mod test` +//! +//! Here basic unit tests are defined for the migration. +//! +//! When writing migration tests, don't forget to check: +//! - `on_runtime_upgrade` returns the expected weight +//! - `post_upgrade` succeeds when given the bytes returned by `pre_upgrade` +//! - Pallet storage is in the expected state after the migration +//! +//! [`VersionedMigration`]: frame_support::migrations::VersionedMigration +//! [`GetStorageVersion`]: frame_support::traits::GetStorageVersion +//! [`OnRuntimeUpgrade`]: frame_support::traits::OnRuntimeUpgrade +//! [`MigrateV0ToV1`]: crate::migrations::v1::versioned::MigrationV0ToV1 + +// We make sure this pallet uses `no_std` for compiling to Wasm. +#![cfg_attr(not(feature = "std"), no_std)] +// allow non-camel-case names for storage version V0 value +#![allow(non_camel_case_types)] + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +// Export migrations so they may be used in the runtime. +pub mod migrations; +#[doc(hidden)] +mod mock; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::traits::StorageVersion; +use sp_runtime::RuntimeDebug; + +/// Example struct holding the most recently set [`u32`] and the +/// second most recently set [`u32`] (if one existed). +#[docify::export] +#[derive( + Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen, +)] +pub struct CurrentAndPreviousValue { + /// The most recently set value. + pub current: u32, + /// The previous value, if one existed. + pub previous: Option, +} + +// Pallet for demonstrating storage migrations. +#[frame_support::pallet(dev_mode)] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + /// Define the current [`StorageVersion`] of the pallet. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + + #[pallet::pallet] + #[pallet::storage_version(STORAGE_VERSION)] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + /// [`StorageVersion`] V1 of [`Value`]. + /// + /// Currently used. + #[docify::export] + #[pallet::storage] + pub type Value = StorageValue<_, CurrentAndPreviousValue>; + + #[docify::export(pallet_calls)] + #[pallet::call] + impl Pallet { + pub fn set_value(origin: OriginFor, value: u32) -> DispatchResult { + ensure_signed(origin)?; + + let previous = Value::::get().map(|v| v.current); + let new_struct = CurrentAndPreviousValue { current: value, previous }; + >::put(new_struct); + + Ok(()) + } + } +} diff --git a/substrate/frame/examples/single-block-migrations/src/migrations/mod.rs b/substrate/frame/examples/single-block-migrations/src/migrations/mod.rs new file mode 100644 index 00000000000..80a33f69941 --- /dev/null +++ b/substrate/frame/examples/single-block-migrations/src/migrations/mod.rs @@ -0,0 +1,20 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +/// Module containing all logic associated with the example migration from +/// [`StorageVersion`](frame_support::traits::StorageVersion) V0 to V1. +pub mod v1; diff --git a/substrate/frame/examples/single-block-migrations/src/migrations/v1.rs b/substrate/frame/examples/single-block-migrations/src/migrations/v1.rs new file mode 100644 index 00000000000..b46640a3202 --- /dev/null +++ b/substrate/frame/examples/single-block-migrations/src/migrations/v1.rs @@ -0,0 +1,222 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use frame_support::{ + storage_alias, + traits::{Get, OnRuntimeUpgrade}, +}; + +#[cfg(feature = "try-runtime")] +use sp_std::vec::Vec; + +/// Collection of storage item formats from the previous storage version. +/// +/// Required so we can read values in the v0 storage format during the migration. +mod v0 { + use super::*; + + /// V0 type for [`crate::Value`]. + #[storage_alias] + pub type Value = StorageValue, u32>; +} + +/// Private module containing *version unchecked* migration logic. +/// +/// Should only be used by the [`VersionedMigration`](frame_support::migrations::VersionedMigration) +/// type in this module to create something to export. +/// +/// The unversioned migration should be kept private so the unversioned migration cannot +/// accidentally be used in any runtimes. +/// +/// For more about this pattern of keeping items private, see +/// - +/// - +mod version_unchecked { + use super::*; + + /// Implements [`OnRuntimeUpgrade`], migrating the state of this pallet from V0 to V1. + /// + /// In V0 of the template [`crate::Value`] is just a `u32`. In V1, it has been upgraded to + /// contain the struct [`crate::CurrentAndPreviousValue`]. + /// + /// In this migration, update the on-chain storage for the pallet to reflect the new storage + /// layout. + pub struct MigrateV0ToV1(sp_std::marker::PhantomData); + + impl OnRuntimeUpgrade for MigrateV0ToV1 { + /// Return the existing [`crate::Value`] so we can check that it was correctly set in + /// `version_unchecked::MigrateV0ToV1::post_upgrade`. + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + use codec::Encode; + + // Access the old value using the `storage_alias` type + let old_value = v0::Value::::get(); + // Return it as an encoded `Vec` + Ok(old_value.encode()) + } + + /// Migrate the storage from V0 to V1. + /// + /// - If the value doesn't exist, there is nothing to do. + /// - If the value exists, it is read and then written back to storage inside a + /// [`crate::CurrentAndPreviousValue`]. + fn on_runtime_upgrade() -> frame_support::weights::Weight { + // Read the old value from storage + if let Some(old_value) = v0::Value::::take() { + // Write the new value to storage + let new = crate::CurrentAndPreviousValue { current: old_value, previous: None }; + crate::Value::::put(new); + // One read for the old value, one write for the new value + T::DbWeight::get().reads_writes(1, 1) + } else { + // One read for trying to access the old value + T::DbWeight::get().reads(1) + } + } + + /// Verifies the storage was migrated correctly. + /// + /// - If there was no old value, the new value should not be set. + /// - If there was an old value, the new value should be a + /// [`crate::CurrentAndPreviousValue`]. + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + use codec::Decode; + use frame_support::ensure; + + let maybe_old_value = Option::::decode(&mut &state[..]).map_err(|_| { + sp_runtime::TryRuntimeError::Other("Failed to decode old value from storage") + })?; + + match maybe_old_value { + Some(old_value) => { + let expected_new_value = + crate::CurrentAndPreviousValue { current: old_value, previous: None }; + let actual_new_value = crate::Value::::get(); + + ensure!(actual_new_value.is_some(), "New value not set"); + ensure!( + actual_new_value == Some(expected_new_value), + "New value not set correctly" + ); + }, + None => { + ensure!(crate::Value::::get().is_none(), "New value unexpectedly set"); + }, + }; + Ok(()) + } + } +} + +/// Public module containing *version checked* migration logic. +/// +/// This is the only module that should be exported from this module. +/// +/// See [`VersionedMigration`](frame_support::migrations::VersionedMigration) docs for more about +/// how it works. +pub mod versioned { + use super::*; + + /// `version_unchecked::MigrateV0ToV1` wrapped in a + /// [`VersionedMigration`](frame_support::migrations::VersionedMigration), which ensures that: + /// - The migration only runs once when the on-chain storage version is 0 + /// - The on-chain storage version is updated to `1` after the migration executes + /// - Reads/Writes from checking/settings the on-chain storage version are accounted for + pub type MigrateV0ToV1 = frame_support::migrations::VersionedMigration< + 0, // The migration will only execute when the on-chain storage version is 0 + 1, // The on-chain storage version will be set to 1 after the migration is complete + version_unchecked::MigrateV0ToV1, + crate::pallet::Pallet, + ::DbWeight, + >; +} + +/// Tests for our migration. +/// +/// When writing migration tests, it is important to check: +/// 1. `on_runtime_upgrade` returns the expected weight +/// 2. `post_upgrade` succeeds when given the bytes returned by `pre_upgrade` +/// 3. The storage is in the expected state after the migration +#[cfg(any(all(feature = "try-runtime", test), doc))] +mod test { + use super::*; + use crate::mock::{new_test_ext, MockRuntime}; + use frame_support::assert_ok; + use version_unchecked::MigrateV0ToV1; + + #[test] + fn handles_no_existing_value() { + new_test_ext().execute_with(|| { + // By default, no value should be set. Verify this assumption. + assert!(crate::Value::::get().is_none()); + assert!(v0::Value::::get().is_none()); + + // Get the pre_upgrade bytes + let bytes = match MigrateV0ToV1::::pre_upgrade() { + Ok(bytes) => bytes, + Err(e) => panic!("pre_upgrade failed: {:?}", e), + }; + + // Execute the migration + let weight = MigrateV0ToV1::::on_runtime_upgrade(); + + // Verify post_upgrade succeeds + assert_ok!(MigrateV0ToV1::::post_upgrade(bytes)); + + // The weight should be just 1 read for trying to access the old value. + assert_eq!(weight, ::DbWeight::get().reads(1)); + + // After the migration, no value should have been set. + assert!(crate::Value::::get().is_none()); + }) + } + + #[test] + fn handles_existing_value() { + new_test_ext().execute_with(|| { + // Set up an initial value + let initial_value = 42; + v0::Value::::put(initial_value); + + // Get the pre_upgrade bytes + let bytes = match MigrateV0ToV1::::pre_upgrade() { + Ok(bytes) => bytes, + Err(e) => panic!("pre_upgrade failed: {:?}", e), + }; + + // Execute the migration + let weight = MigrateV0ToV1::::on_runtime_upgrade(); + + // Verify post_upgrade succeeds + assert_ok!(MigrateV0ToV1::::post_upgrade(bytes)); + + // The weight used should be 1 read for the old value, and 1 write for the new + // value. + assert_eq!( + weight, + ::DbWeight::get().reads_writes(1, 1) + ); + + // After the migration, the new value should be set as the `current` value. + let expected_new_value = + crate::CurrentAndPreviousValue { current: initial_value, previous: None }; + assert_eq!(crate::Value::::get(), Some(expected_new_value)); + }) + } +} diff --git a/substrate/frame/examples/single-block-migrations/src/mock.rs b/substrate/frame/examples/single-block-migrations/src/mock.rs new file mode 100644 index 00000000000..02f72e01836 --- /dev/null +++ b/substrate/frame/examples/single-block-migrations/src/mock.rs @@ -0,0 +1,69 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#![cfg(any(all(feature = "try-runtime", test), doc))] + +use crate::*; +use frame_support::{derive_impl, traits::ConstU64, weights::constants::ParityDbWeight}; + +// Re-export crate as its pallet name for construct_runtime. +use crate as pallet_example_storage_migration; + +type Block = frame_system::mocking::MockBlock; + +// For testing the pallet, we construct a mock runtime. +frame_support::construct_runtime!( + pub struct MockRuntime { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Example: pallet_example_storage_migration::{Pallet, Call, Storage}, + } +); + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for MockRuntime { + type Block = Block; + type AccountData = pallet_balances::AccountData; + type DbWeight = ParityDbWeight; +} + +impl pallet_balances::Config for MockRuntime { + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = RuntimeFreezeReason; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type WeightInfo = (); + type FreezeIdentifier = (); + type MaxFreezes = (); +} + +impl Config for MockRuntime {} + +pub fn new_test_ext() -> sp_io::TestExternalities { + use sp_runtime::BuildStorage; + + let t = RuntimeGenesisConfig { system: Default::default(), balances: Default::default() } + .build_storage() + .unwrap(); + t.into() +} diff --git a/substrate/frame/examples/src/lib.rs b/substrate/frame/examples/src/lib.rs index f38bbe52dc1..dee23a41379 100644 --- a/substrate/frame/examples/src/lib.rs +++ b/substrate/frame/examples/src/lib.rs @@ -43,6 +43,9 @@ //! - [`pallet_example_frame_crate`]: Example pallet showcasing how one can be //! built using only the `frame` umbrella crate. //! +//! - [`pallet_example_single_block_migrations`]: An example pallet demonstrating best-practices for +//! writing storage migrations. +//! //! - [`pallet_example_tasks`]: This pallet demonstrates the use of `Tasks` to execute service work. //! //! **Tip**: Use `cargo doc --package --open` to view each pallet's documentation. diff --git a/substrate/frame/fast-unstake/src/migrations.rs b/substrate/frame/fast-unstake/src/migrations.rs index 56438840704..97ad86bfff4 100644 --- a/substrate/frame/fast-unstake/src/migrations.rs +++ b/substrate/frame/fast-unstake/src/migrations.rs @@ -33,12 +33,12 @@ pub mod v1 { pub struct MigrateToV1(sp_std::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV1 { fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let current = Pallet::::in_code_storage_version(); let onchain = Pallet::::on_chain_storage_version(); log!( info, - "Running migration with current storage version {:?} / onchain {:?}", + "Running migration with in-code storage version {:?} / onchain {:?}", current, onchain ); diff --git a/substrate/frame/grandpa/src/lib.rs b/substrate/frame/grandpa/src/lib.rs index 0b9f2b35827..90bcd8721df 100644 --- a/substrate/frame/grandpa/src/lib.rs +++ b/substrate/frame/grandpa/src/lib.rs @@ -73,7 +73,7 @@ pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); #[pallet::pallet] diff --git a/substrate/frame/im-online/src/lib.rs b/substrate/frame/im-online/src/lib.rs index 1de89dd00c8..f14093aa09a 100644 --- a/substrate/frame/im-online/src/lib.rs +++ b/substrate/frame/im-online/src/lib.rs @@ -251,7 +251,7 @@ type OffchainResult = Result>>; pub mod pallet { use super::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/substrate/frame/im-online/src/migration.rs b/substrate/frame/im-online/src/migration.rs index 0d2c0a055b6..754a2e672e6 100644 --- a/substrate/frame/im-online/src/migration.rs +++ b/substrate/frame/im-online/src/migration.rs @@ -72,7 +72,7 @@ pub mod v1 { if StorageVersion::get::>() != 0 { log::warn!( target: TARGET, - "Skipping migration because current storage version is not 0" + "Skipping migration because in-code storage version is not 0" ); return weight } diff --git a/substrate/frame/membership/src/lib.rs b/substrate/frame/membership/src/lib.rs index f3226397003..f4ac697130d 100644 --- a/substrate/frame/membership/src/lib.rs +++ b/substrate/frame/membership/src/lib.rs @@ -46,7 +46,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); #[pallet::pallet] diff --git a/substrate/frame/multisig/src/lib.rs b/substrate/frame/multisig/src/lib.rs index e4426c64b41..a83b78e316f 100644 --- a/substrate/frame/multisig/src/lib.rs +++ b/substrate/frame/multisig/src/lib.rs @@ -168,7 +168,7 @@ pub mod pallet { type WeightInfo: WeightInfo; } - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/substrate/frame/multisig/src/migrations.rs b/substrate/frame/multisig/src/migrations.rs index d03e42a66a5..e6402600d0d 100644 --- a/substrate/frame/multisig/src/migrations.rs +++ b/substrate/frame/multisig/src/migrations.rs @@ -51,7 +51,7 @@ pub mod v1 { fn on_runtime_upgrade() -> Weight { use sp_runtime::Saturating; - let current = Pallet::::current_storage_version(); + let current = Pallet::::in_code_storage_version(); let onchain = Pallet::::on_chain_storage_version(); if onchain > 0 { diff --git a/substrate/frame/nfts/src/lib.rs b/substrate/frame/nfts/src/lib.rs index a7d505e2e39..7cf7cdc61a7 100644 --- a/substrate/frame/nfts/src/lib.rs +++ b/substrate/frame/nfts/src/lib.rs @@ -76,7 +76,7 @@ pub mod pallet { use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/substrate/frame/nfts/src/migration.rs b/substrate/frame/nfts/src/migration.rs index d4cdf7e820d..8f82e092262 100644 --- a/substrate/frame/nfts/src/migration.rs +++ b/substrate/frame/nfts/src/migration.rs @@ -54,17 +54,17 @@ pub mod v1 { pub struct MigrateToV1(core::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV1 { fn on_runtime_upgrade() -> Weight { - let current_version = Pallet::::current_storage_version(); - let onchain_version = Pallet::::on_chain_storage_version(); + let in_code_version = Pallet::::in_code_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); log::info!( target: LOG_TARGET, - "Running migration with current storage version {:?} / onchain {:?}", - current_version, - onchain_version + "Running migration with in-code storage version {:?} / onchain {:?}", + in_code_version, + on_chain_version ); - if onchain_version == 0 && current_version == 1 { + if on_chain_version == 0 && in_code_version == 1 { let mut translated = 0u64; let mut configs_iterated = 0u64; Collection::::translate::< @@ -77,13 +77,13 @@ pub mod v1 { Some(old_value.migrate_to_v1(item_configs)) }); - current_version.put::>(); + in_code_version.put::>(); log::info!( target: LOG_TARGET, "Upgraded {} records, storage to version {:?}", translated, - current_version + in_code_version ); T::DbWeight::get().reads_writes(translated + configs_iterated + 1, translated + 1) } else { diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 074d59931ad..c64db9ed692 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -1576,7 +1576,7 @@ pub mod pallet { use frame_system::{ensure_signed, pallet_prelude::*}; use sp_runtime::Perbill; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(8); #[pallet::pallet] diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 6887fcfa7ec..14410339f59 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -342,25 +342,25 @@ pub mod v5 { pub struct MigrateToV5(sp_std::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV5 { fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let in_code = Pallet::::in_code_storage_version(); let onchain = Pallet::::on_chain_storage_version(); log!( info, - "Running migration with current storage version {:?} / onchain {:?}", - current, + "Running migration with in-code storage version {:?} / onchain {:?}", + in_code, onchain ); - if current == 5 && onchain == 4 { + if in_code == 5 && onchain == 4 { let mut translated = 0u64; RewardPools::::translate::, _>(|_id, old_value| { translated.saturating_inc(); Some(old_value.migrate_to_v5()) }); - current.put::>(); - log!(info, "Upgraded {} pools, storage to version {:?}", translated, current); + in_code.put::>(); + log!(info, "Upgraded {} pools, storage to version {:?}", translated, in_code); // reads: translated + onchain version. // writes: translated + current.put. @@ -498,12 +498,12 @@ pub mod v4 { #[allow(deprecated)] impl> OnRuntimeUpgrade for MigrateToV4 { fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let current = Pallet::::in_code_storage_version(); let onchain = Pallet::::on_chain_storage_version(); log!( info, - "Running migration with current storage version {:?} / onchain {:?}", + "Running migration with in-code storage version {:?} / onchain {:?}", current, onchain ); @@ -579,13 +579,13 @@ pub mod v3 { pub struct MigrateToV3(sp_std::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV3 { fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let current = Pallet::::in_code_storage_version(); let onchain = Pallet::::on_chain_storage_version(); if onchain == 2 { log!( info, - "Running migration with current storage version {:?} / onchain {:?}", + "Running migration with in-code storage version {:?} / onchain {:?}", current, onchain ); @@ -859,12 +859,12 @@ pub mod v2 { impl OnRuntimeUpgrade for MigrateToV2 { fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let current = Pallet::::in_code_storage_version(); let onchain = Pallet::::on_chain_storage_version(); log!( info, - "Running migration with current storage version {:?} / onchain {:?}", + "Running migration with in-code storage version {:?} / onchain {:?}", current, onchain ); @@ -976,12 +976,12 @@ pub mod v1 { pub struct MigrateToV1(sp_std::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV1 { fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let current = Pallet::::in_code_storage_version(); let onchain = Pallet::::on_chain_storage_version(); log!( info, - "Running migration with current storage version {:?} / onchain {:?}", + "Running migration with in-code storage version {:?} / onchain {:?}", current, onchain ); diff --git a/substrate/frame/preimage/src/lib.rs b/substrate/frame/preimage/src/lib.rs index e344bdfe2d8..4e474685166 100644 --- a/substrate/frame/preimage/src/lib.rs +++ b/substrate/frame/preimage/src/lib.rs @@ -102,7 +102,7 @@ pub const MAX_HASH_UPGRADE_BULK_COUNT: u32 = 1024; pub mod pallet { use super::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::config] diff --git a/substrate/frame/referenda/src/lib.rs b/substrate/frame/referenda/src/lib.rs index c5bf2266e67..e616056c302 100644 --- a/substrate/frame/referenda/src/lib.rs +++ b/substrate/frame/referenda/src/lib.rs @@ -143,7 +143,7 @@ pub mod pallet { use frame_support::{pallet_prelude::*, traits::EnsureOriginWithArg}; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/substrate/frame/referenda/src/migration.rs b/substrate/frame/referenda/src/migration.rs index a80897242ee..631eb7340e5 100644 --- a/substrate/frame/referenda/src/migration.rs +++ b/substrate/frame/referenda/src/migration.rs @@ -109,16 +109,16 @@ pub mod v1 { } fn on_runtime_upgrade() -> Weight { - let current_version = Pallet::::current_storage_version(); - let onchain_version = Pallet::::on_chain_storage_version(); + let in_code_version = Pallet::::in_code_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); let mut weight = T::DbWeight::get().reads(1); log::info!( target: TARGET, - "running migration with current storage version {:?} / onchain {:?}.", - current_version, - onchain_version + "running migration with in-code storage version {:?} / onchain {:?}.", + in_code_version, + on_chain_version ); - if onchain_version != 0 { + if on_chain_version != 0 { log::warn!(target: TARGET, "skipping migration from v0 to v1."); return weight } @@ -149,8 +149,8 @@ pub mod v1 { #[cfg(feature = "try-runtime")] fn post_upgrade(state: Vec) -> Result<(), TryRuntimeError> { - let onchain_version = Pallet::::on_chain_storage_version(); - ensure!(onchain_version == 1, "must upgrade from version 0 to 1."); + let on_chain_version = Pallet::::on_chain_storage_version(); + ensure!(on_chain_version == 1, "must upgrade from version 0 to 1."); let pre_referendum_count: u32 = Decode::decode(&mut &state[..]) .expect("failed to decode the state from pre-upgrade."); let post_referendum_count = ReferendumInfoFor::::iter().count() as u32; diff --git a/substrate/frame/scheduler/src/lib.rs b/substrate/frame/scheduler/src/lib.rs index daebebdee99..af3abd8ac4f 100644 --- a/substrate/frame/scheduler/src/lib.rs +++ b/substrate/frame/scheduler/src/lib.rs @@ -229,7 +229,7 @@ pub mod pallet { use frame_support::{dispatch::PostDispatchInfo, pallet_prelude::*}; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); #[pallet::pallet] diff --git a/substrate/frame/session/src/historical/mod.rs b/substrate/frame/session/src/historical/mod.rs index d74e9dd0b7c..b9cecea1a7f 100644 --- a/substrate/frame/session/src/historical/mod.rs +++ b/substrate/frame/session/src/historical/mod.rs @@ -58,7 +58,7 @@ pub mod pallet { use super::*; use frame_support::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/substrate/frame/session/src/lib.rs b/substrate/frame/session/src/lib.rs index fc35cd6ddd8..7d8128dbc1f 100644 --- a/substrate/frame/session/src/lib.rs +++ b/substrate/frame/session/src/lib.rs @@ -368,7 +368,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); #[pallet::pallet] diff --git a/substrate/frame/society/src/migrations.rs b/substrate/frame/society/src/migrations.rs index dafb1e0b9e5..6a102911451 100644 --- a/substrate/frame/society/src/migrations.rs +++ b/substrate/frame/society/src/migrations.rs @@ -40,11 +40,11 @@ impl< { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, TryRuntimeError> { - let current = Pallet::::current_storage_version(); - let onchain = Pallet::::on_chain_storage_version(); - ensure!(onchain == 0 && current == 2, "pallet_society: invalid version"); + let in_code = Pallet::::in_code_storage_version(); + let on_chain = Pallet::::on_chain_storage_version(); + ensure!(on_chain == 0 && in_code == 2, "pallet_society: invalid version"); - Ok((old::Candidates::::get(), old::Members::::get()).encode()) + Ok((v0::Candidates::::get(), v0::Members::::get()).encode()) } fn on_runtime_upgrade() -> Weight { @@ -103,7 +103,7 @@ pub type MigrateToV2 = frame_support::migrations::VersionedMi ::DbWeight, >; -pub(crate) mod old { +pub(crate) mod v0 { use super::*; use frame_support::storage_alias; @@ -230,37 +230,37 @@ pub fn assert_internal_consistency, I: Instance + 'static>() { } // We don't use these - make sure they don't exist. - assert_eq!(old::SuspendedCandidates::::iter().count(), 0); - assert_eq!(old::Strikes::::iter().count(), 0); - assert_eq!(old::Vouching::::iter().count(), 0); - assert!(!old::Defender::::exists()); - assert!(!old::Members::::exists()); + assert_eq!(v0::SuspendedCandidates::::iter().count(), 0); + assert_eq!(v0::Strikes::::iter().count(), 0); + assert_eq!(v0::Vouching::::iter().count(), 0); + assert!(!v0::Defender::::exists()); + assert!(!v0::Members::::exists()); } pub fn from_original, I: Instance + 'static>( past_payouts: &mut [(::AccountId, BalanceOf)], ) -> Result { // Migrate Bids from old::Bids (just a trunctation). - Bids::::put(BoundedVec::<_, T::MaxBids>::truncate_from(old::Bids::::take())); + Bids::::put(BoundedVec::<_, T::MaxBids>::truncate_from(v0::Bids::::take())); // Initialise round counter. RoundCount::::put(0); // Migrate Candidates from old::Candidates - for Bid { who: candidate, kind, value } in old::Candidates::::take().into_iter() { + for Bid { who: candidate, kind, value } in v0::Candidates::::take().into_iter() { let mut tally = Tally::default(); // Migrate Votes from old::Votes // No need to drain, since we're overwriting values. - for (voter, vote) in old::Votes::::iter_prefix(&candidate) { + for (voter, vote) in v0::Votes::::iter_prefix(&candidate) { Votes::::insert( &candidate, &voter, - Vote { approve: vote == old::Vote::Approve, weight: 1 }, + Vote { approve: vote == v0::Vote::Approve, weight: 1 }, ); match vote { - old::Vote::Approve => tally.approvals.saturating_inc(), - old::Vote::Reject => tally.rejections.saturating_inc(), - old::Vote::Skeptic => Skeptic::::put(&voter), + v0::Vote::Approve => tally.approvals.saturating_inc(), + v0::Vote::Reject => tally.rejections.saturating_inc(), + v0::Vote::Skeptic => Skeptic::::put(&voter), } } Candidates::::insert( @@ -271,9 +271,9 @@ pub fn from_original, I: Instance + 'static>( // Migrate Members from old::Members old::Strikes old::Vouching let mut member_count = 0; - for member in old::Members::::take() { - let strikes = old::Strikes::::take(&member); - let vouching = old::Vouching::::take(&member); + for member in v0::Members::::take() { + let strikes = v0::Strikes::::take(&member); + let vouching = v0::Vouching::::take(&member); let record = MemberRecord { index: member_count, rank: 0, strikes, vouching }; Members::::insert(&member, record); MemberByIndex::::insert(member_count, &member); @@ -314,7 +314,7 @@ pub fn from_original, I: Instance + 'static>( // Migrate Payouts from: old::Payouts and raw info (needed since we can't query old chain // state). past_payouts.sort(); - for (who, mut payouts) in old::Payouts::::iter() { + for (who, mut payouts) in v0::Payouts::::iter() { payouts.truncate(T::MaxPayouts::get() as usize); // ^^ Safe since we already truncated. let paid = past_payouts @@ -329,19 +329,19 @@ pub fn from_original, I: Instance + 'static>( } // Migrate SuspendedMembers from old::SuspendedMembers old::Strikes old::Vouching. - for who in old::SuspendedMembers::::iter_keys() { - let strikes = old::Strikes::::take(&who); - let vouching = old::Vouching::::take(&who); + for who in v0::SuspendedMembers::::iter_keys() { + let strikes = v0::Strikes::::take(&who); + let vouching = v0::Vouching::::take(&who); let record = MemberRecord { index: 0, rank: 0, strikes, vouching }; SuspendedMembers::::insert(&who, record); } // Any suspended candidates remaining are rejected. - let _ = old::SuspendedCandidates::::clear(u32::MAX, None); + let _ = v0::SuspendedCandidates::::clear(u32::MAX, None); // We give the current defender the benefit of the doubt. - old::Defender::::kill(); - let _ = old::DefenderVotes::::clear(u32::MAX, None); + v0::Defender::::kill(); + let _ = v0::DefenderVotes::::clear(u32::MAX, None); Ok(T::BlockWeights::get().max_block) } diff --git a/substrate/frame/society/src/tests.rs b/substrate/frame/society/src/tests.rs index 940643168fb..411567e1ded 100644 --- a/substrate/frame/society/src/tests.rs +++ b/substrate/frame/society/src/tests.rs @@ -18,7 +18,7 @@ //! Tests for the module. use super::*; -use migrations::old; +use migrations::v0; use mock::*; use frame_support::{assert_noop, assert_ok}; @@ -32,41 +32,41 @@ use RuntimeOrigin as Origin; #[test] fn migration_works() { EnvBuilder::new().founded(false).execute(|| { - use old::Vote::*; + use v0::Vote::*; // Initialise the old storage items. Founder::::put(10); Head::::put(30); - old::Members::::put(vec![10, 20, 30]); - old::Vouching::::insert(30, Vouching); - old::Vouching::::insert(40, Banned); - old::Strikes::::insert(20, 1); - old::Strikes::::insert(30, 2); - old::Strikes::::insert(40, 5); - old::Payouts::::insert(20, vec![(1, 1)]); - old::Payouts::::insert( + v0::Members::::put(vec![10, 20, 30]); + v0::Vouching::::insert(30, Vouching); + v0::Vouching::::insert(40, Banned); + v0::Strikes::::insert(20, 1); + v0::Strikes::::insert(30, 2); + v0::Strikes::::insert(40, 5); + v0::Payouts::::insert(20, vec![(1, 1)]); + v0::Payouts::::insert( 30, (0..=::MaxPayouts::get()) .map(|i| (i as u64, i as u64)) .collect::>(), ); - old::SuspendedMembers::::insert(40, true); + v0::SuspendedMembers::::insert(40, true); - old::Defender::::put(20); - old::DefenderVotes::::insert(10, Approve); - old::DefenderVotes::::insert(20, Approve); - old::DefenderVotes::::insert(30, Reject); + v0::Defender::::put(20); + v0::DefenderVotes::::insert(10, Approve); + v0::DefenderVotes::::insert(20, Approve); + v0::DefenderVotes::::insert(30, Reject); - old::SuspendedCandidates::::insert(50, (10, Deposit(100))); + v0::SuspendedCandidates::::insert(50, (10, Deposit(100))); - old::Candidates::::put(vec![ + v0::Candidates::::put(vec![ Bid { who: 60, kind: Deposit(100), value: 200 }, Bid { who: 70, kind: Vouch(30, 30), value: 100 }, ]); - old::Votes::::insert(60, 10, Approve); - old::Votes::::insert(70, 10, Reject); - old::Votes::::insert(70, 20, Approve); - old::Votes::::insert(70, 30, Approve); + v0::Votes::::insert(60, 10, Approve); + v0::Votes::::insert(70, 10, Reject); + v0::Votes::::insert(70, 20, Approve); + v0::Votes::::insert(70, 30, Approve); let bids = (0..=::MaxBids::get()) .map(|i| Bid { @@ -75,7 +75,7 @@ fn migration_works() { value: 10u64 + i as u64, }) .collect::>(); - old::Bids::::put(bids); + v0::Bids::::put(bids); migrations::from_original::(&mut [][..]).expect("migration failed"); migrations::assert_internal_consistency::(); diff --git a/substrate/frame/staking/src/migrations.rs b/substrate/frame/staking/src/migrations.rs index 98984be9920..3e3b1113a81 100644 --- a/substrate/frame/staking/src/migrations.rs +++ b/substrate/frame/staking/src/migrations.rs @@ -67,11 +67,11 @@ pub mod v14 { pub struct MigrateToV14(core::marker::PhantomData); impl OnRuntimeUpgrade for MigrateToV14 { fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let in_code = Pallet::::in_code_storage_version(); let on_chain = Pallet::::on_chain_storage_version(); - if current == 14 && on_chain == 13 { - current.put::>(); + if in_code == 14 && on_chain == 13 { + in_code.put::>(); log!(info, "v14 applied successfully."); T::DbWeight::get().reads_writes(1, 1) @@ -108,12 +108,12 @@ pub mod v13 { } fn on_runtime_upgrade() -> Weight { - let current = Pallet::::current_storage_version(); + let in_code = Pallet::::in_code_storage_version(); let onchain = StorageVersion::::get(); - if current == 13 && onchain == ObsoleteReleases::V12_0_0 { + if in_code == 13 && onchain == ObsoleteReleases::V12_0_0 { StorageVersion::::kill(); - current.put::>(); + in_code.put::>(); log!(info, "v13 applied successfully"); T::DbWeight::get().reads_writes(1, 2) diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index e0213efd507..992a7fe2c9c 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -66,7 +66,7 @@ pub mod pallet { use super::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(14); #[pallet::pallet] diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 78729ee3dc3..5840377d722 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -555,6 +555,42 @@ pub fn __create_tt_macro(input: TokenStream) -> TokenStream { tt_macro::create_tt_return_macro(input) } +/// Allows accessing on-chain pallet storage that is no longer accessible via the pallet. +/// +/// This is especially useful when writing storage migrations, when types of storage items are +/// modified or outright removed, but the previous definition is required to perform the migration. +/// +/// ## Example +/// +/// Imagine a pallet with the following storage definition: +/// ```ignore +/// #[pallet::storage] +/// pub type Value = StorageValue<_, u32>; +/// ``` +/// `Value` can be accessed by calling `Value::::get()`. +/// +/// Now imagine the definition of `Value` is updated to a `(u32, u32)`: +/// ```ignore +/// #[pallet::storage] +/// pub type Value = StorageValue<_, (u32, u32)>; +/// ``` +/// The on-chain value of `Value` is `u32`, but `Value::::get()` expects it to be `(u32, u32)`. +/// +/// In this instance the developer must write a storage migration to reading the old value of +/// `Value` and writing it back to storage in the new format, so that the on-chain storage layout is +/// consistent with what is defined in the pallet. +/// +/// We can read the old v0 value of `Value` in the migration by creating a `storage_alias`: +/// ```ignore +/// pub(crate) mod v0 { +/// use super::*; +/// +/// #[storage_alias] +/// pub type Value = StorageValue, u32>; +/// } +/// ``` +/// +/// The developer can now access the old value of `Value` by calling `v0::Value::::get()`. #[proc_macro_attribute] pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream { storage_alias::storage_alias(attributes.into(), input.into()) @@ -1058,7 +1094,7 @@ pub fn generate_store(_: TokenStream, _: TokenStream) -> TokenStream { /// pub struct Pallet(_); /// ``` /// -/// If not present, the current storage version is set to the default value. +/// If not present, the in-code storage version is set to the default value. #[proc_macro_attribute] pub fn storage_version(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() diff --git a/substrate/frame/support/procedural/src/pallet/expand/hooks.rs b/substrate/frame/support/procedural/src/pallet/expand/hooks.rs index 5044d4285bb..6b25ddcba1a 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/hooks.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/hooks.rs @@ -42,7 +42,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { >::name::().unwrap_or("") }; - let initialize_on_chain_storage_version = if let Some(current_version) = + let initialize_on_chain_storage_version = if let Some(in_code_version) = &def.pallet_struct.storage_version { quote::quote! { @@ -50,9 +50,9 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { target: #frame_support::LOG_TARGET, "🐥 New pallet {:?} detected in the runtime. Initializing the on-chain storage version to match the storage version defined in the pallet: {:?}", #pallet_name, - #current_version + #in_code_version ); - #current_version.put::(); + #in_code_version.put::(); } } else { quote::quote! { @@ -73,10 +73,10 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::__private::log::info!( target: #frame_support::LOG_TARGET, "⚠️ {} declares internal migrations (which *might* execute). \ - On-chain `{:?}` vs current storage version `{:?}`", + On-chain `{:?}` vs in-code storage version `{:?}`", #pallet_name, ::on_chain_storage_version(), - ::current_storage_version(), + ::in_code_storage_version(), ); } } else { @@ -102,23 +102,23 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { }; // If a storage version is set, we should ensure that the storage version on chain matches the - // current storage version. This assumes that `Executive` is running custom migrations before + // in-code storage version. This assumes that `Executive` is running custom migrations before // the pallets are called. let post_storage_version_check = if def.pallet_struct.storage_version.is_some() { quote::quote! { let on_chain_version = ::on_chain_storage_version(); - let current_version = ::current_storage_version(); + let in_code_version = ::in_code_storage_version(); - if on_chain_version != current_version { + if on_chain_version != in_code_version { #frame_support::__private::log::error!( target: #frame_support::LOG_TARGET, - "{}: On chain storage version {:?} doesn't match current storage version {:?}.", + "{}: On chain storage version {:?} doesn't match in-code storage version {:?}.", #pallet_name, on_chain_version, - current_version, + in_code_version, ); - return Err("On chain and current storage version do not match. Missing runtime upgrade?".into()); + return Err("On chain and in-code storage version do not match. Missing runtime upgrade?".into()); } } } else { diff --git a/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs index c2102f0284d..7cdf6bde9de 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs @@ -160,7 +160,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { } ); - let (storage_version, current_storage_version_ty) = + let (storage_version, in_code_storage_version_ty) = if let Some(v) = def.pallet_struct.storage_version.as_ref() { (quote::quote! { #v }, quote::quote! { #frame_support::traits::StorageVersion }) } else { @@ -203,9 +203,9 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream { for #pallet_ident<#type_use_gen> #config_where_clause { - type CurrentStorageVersion = #current_storage_version_ty; + type InCodeStorageVersion = #in_code_storage_version_ty; - fn current_storage_version() -> Self::CurrentStorageVersion { + fn in_code_storage_version() -> Self::InCodeStorageVersion { #storage_version } diff --git a/substrate/frame/support/procedural/src/pallet/parse/pallet_struct.rs b/substrate/frame/support/procedural/src/pallet/parse/pallet_struct.rs index f4af86aa3e9..c2855ae38ef 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/pallet_struct.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/pallet_struct.rs @@ -44,7 +44,7 @@ pub struct PalletStructDef { /// Whether to specify the storages max encoded len when implementing `StorageInfoTrait`. /// Contains the span of the attribute. pub without_storage_info: Option, - /// The current storage version of the pallet. + /// The in-code storage version of the pallet. pub storage_version: Option, } diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 3e97a384275..d2d9a33053f 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -1178,7 +1178,7 @@ pub mod pallet_prelude { /// # `pallet::storage_version` /// /// Because the [`pallet::pallet`](#pallet-struct-placeholder-palletpallet-mandatory) macro -/// implements [`traits::GetStorageVersion`], the current storage version needs to be +/// implements [`traits::GetStorageVersion`], the in-code storage version needs to be /// communicated to the macro. This can be done by using the `pallet::storage_version` /// attribute: /// @@ -1190,7 +1190,7 @@ pub mod pallet_prelude { /// pub struct Pallet(_); /// ``` /// -/// If not present, the current storage version is set to the default value. +/// If not present, the in-code storage version is set to the default value. /// /// Also see [`pallet::storage_version`](`frame_support::pallet_macros::storage_version`) /// diff --git a/substrate/frame/support/src/migrations.rs b/substrate/frame/support/src/migrations.rs index d059a992a86..f7541059023 100644 --- a/substrate/frame/support/src/migrations.rs +++ b/substrate/frame/support/src/migrations.rs @@ -43,12 +43,30 @@ use sp_std::marker::PhantomData; /// Otherwise, a warning is logged notifying the developer that the upgrade was a noop and should /// probably be removed. /// +/// It is STRONGLY RECOMMENDED to write the unversioned migration logic in a private module and +/// only export the versioned migration logic to prevent accidentally using the unversioned +/// migration in any runtimes. +/// /// ### Examples /// ```ignore /// // In file defining migrations -/// pub struct VersionUncheckedMigrateV5ToV6(sp_std::marker::PhantomData); -/// impl OnRuntimeUpgrade for VersionUncheckedMigrateV5ToV6 { -/// // OnRuntimeUpgrade implementation... +/// +/// /// Private module containing *version unchecked* migration logic. +/// /// +/// /// Should only be used by the [`VersionedMigration`] type in this module to create something to +/// /// export. +/// /// +/// /// We keep this private so the unversioned migration cannot accidentally be used in any runtimes. +/// /// +/// /// For more about this pattern of keeping items private, see +/// /// - https://github.com/rust-lang/rust/issues/30905 +/// /// - https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504/40 +/// mod version_unchecked { +/// use super::*; +/// pub struct MigrateV5ToV6(sp_std::marker::PhantomData); +/// impl OnRuntimeUpgrade for VersionUncheckedMigrateV5ToV6 { +/// // OnRuntimeUpgrade implementation... +/// } /// } /// /// pub type MigrateV5ToV6 = @@ -91,7 +109,7 @@ impl< const FROM: u16, const TO: u16, Inner: crate::traits::OnRuntimeUpgrade, - Pallet: GetStorageVersion + PalletInfoAccess, + Pallet: GetStorageVersion + PalletInfoAccess, DbWeight: Get, > crate::traits::OnRuntimeUpgrade for VersionedMigration { @@ -163,25 +181,25 @@ impl< } } -/// Can store the current pallet version in storage. -pub trait StoreCurrentStorageVersion { - /// Write the current storage version to the storage. - fn store_current_storage_version(); +/// Can store the in-code pallet version on-chain. +pub trait StoreInCodeStorageVersion { + /// Write the in-code storage version on-chain. + fn store_in_code_storage_version(); } -impl + PalletInfoAccess> - StoreCurrentStorageVersion for StorageVersion +impl + PalletInfoAccess> + StoreInCodeStorageVersion for StorageVersion { - fn store_current_storage_version() { - let version = ::current_storage_version(); + fn store_in_code_storage_version() { + let version = ::in_code_storage_version(); version.put::(); } } -impl + PalletInfoAccess> - StoreCurrentStorageVersion for NoStorageVersionSet +impl + PalletInfoAccess> + StoreInCodeStorageVersion for NoStorageVersionSet { - fn store_current_storage_version() { + fn store_in_code_storage_version() { StorageVersion::default().put::(); } } @@ -193,7 +211,7 @@ pub trait PalletVersionToStorageVersionHelper { impl PalletVersionToStorageVersionHelper for T where - T::CurrentStorageVersion: StoreCurrentStorageVersion, + T::InCodeStorageVersion: StoreInCodeStorageVersion, { fn migrate(db_weight: &RuntimeDbWeight) -> Weight { const PALLET_VERSION_STORAGE_KEY_POSTFIX: &[u8] = b":__PALLET_VERSION__:"; @@ -204,8 +222,7 @@ where sp_io::storage::clear(&pallet_version_key(::name())); - >::store_current_storage_version( - ); + >::store_in_code_storage_version(); db_weight.writes(2) } @@ -226,7 +243,7 @@ impl PalletVersionToStorageVersionHelper for T { /// Migrate from the `PalletVersion` struct to the new [`StorageVersion`] struct. /// -/// This will remove all `PalletVersion's` from the state and insert the current storage version. +/// This will remove all `PalletVersion's` from the state and insert the in-code storage version. pub fn migrate_from_pallet_version_to_storage_version< Pallets: PalletVersionToStorageVersionHelper, >( diff --git a/substrate/frame/support/src/traits/hooks.rs b/substrate/frame/support/src/traits/hooks.rs index 20788ce932d..72f047c3a73 100644 --- a/substrate/frame/support/src/traits/hooks.rs +++ b/substrate/frame/support/src/traits/hooks.rs @@ -90,7 +90,7 @@ impl OnIdle for Tuple { /// /// Implementing this trait for a pallet let's you express operations that should /// happen at genesis. It will be called in an externalities provided environment and -/// will see the genesis state after all pallets have written their genesis state. +/// will set the genesis state after all pallets have written their genesis state. #[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))] #[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))] #[cfg_attr(feature = "tuples-128", impl_for_tuples(128))] @@ -306,19 +306,23 @@ pub trait IntegrityTest { /// end /// ``` /// -/// * `OnRuntimeUpgrade` is only executed before everything else if a code -/// * `OnRuntimeUpgrade` is mandatorily at the beginning of the block body (extrinsics) being -/// processed. change is detected. -/// * Extrinsics start with inherents, and continue with other signed or unsigned extrinsics. -/// * `OnIdle` optionally comes after extrinsics. -/// `OnFinalize` mandatorily comes after `OnIdle`. +/// * [`OnRuntimeUpgrade`](Hooks::OnRuntimeUpgrade) hooks are only executed when a code change is +/// detected. +/// * [`OnRuntimeUpgrade`](Hooks::OnRuntimeUpgrade) hooks are mandatorily executed at the very +/// beginning of the block body, before any extrinsics are processed. +/// * [`Inherents`](sp_inherents) are always executed before any other other signed or unsigned +/// extrinsics. +/// * [`OnIdle`](Hooks::OnIdle) hooks are executed after extrinsics if there is weight remaining in +/// the block. +/// * [`OnFinalize`](Hooks::OnFinalize) hooks are mandatorily executed after +/// [`OnIdle`](Hooks::OnIdle). /// -/// > `OffchainWorker` is not part of this flow, as it is not really part of the consensus/main -/// > block import path, and is called optionally, and in other circumstances. See -/// > [`crate::traits::misc::OffchainWorker`] for more information. +/// > [`OffchainWorker`](crate::traits::misc::OffchainWorker) hooks are not part of this flow, +/// > because they are not part of the consensus/main block building logic. See +/// > [`OffchainWorker`](crate::traits::misc::OffchainWorker) for more information. /// -/// To learn more about the execution of hooks see `frame-executive` as this component is is charge -/// of dispatching extrinsics and placing the hooks in the correct order. +/// To learn more about the execution of hooks see the FRAME `Executive` pallet which is in charge +/// of dispatching extrinsics and calling hooks in the correct order. pub trait Hooks { /// Block initialization hook. This is called at the very beginning of block execution. /// @@ -370,30 +374,38 @@ pub trait Hooks { Weight::zero() } - /// Hook executed when a code change (aka. a "runtime upgrade") is detected by FRAME. + /// Hook executed when a code change (aka. a "runtime upgrade") is detected by the FRAME + /// `Executive` pallet. /// /// Be aware that this is called before [`Hooks::on_initialize`] of any pallet; therefore, a lot /// of the critical storage items such as `block_number` in system pallet might have not been - /// set. + /// set yet. /// - /// Vert similar to [`Hooks::on_initialize`], any code in this block is mandatory and MUST - /// execute. Use with care. + /// Similar to [`Hooks::on_initialize`], any code in this block is mandatory and MUST execute. + /// It is strongly recommended to dry-run the execution of these hooks using + /// [try-runtime-cli](https://github.com/paritytech/try-runtime-cli) to ensure they will not + /// produce and overweight block which can brick your chain. Use with care! /// - /// ## Implementation Note: Versioning + /// ## Implementation Note: Standalone Migrations /// - /// 1. An implementation of this should typically follow a pattern where the version of the - /// pallet is checked against the onchain version, and a decision is made about what needs to be - /// done. This is helpful to prevent accidental repetitive execution of this hook, which can be - /// catastrophic. + /// Additional migrations can be created by directly implementing [`OnRuntimeUpgrade`] on + /// structs and passing them to `Executive`. /// - /// Alternatively, [`frame_support::migrations::VersionedMigration`] can be used to assist with - /// this. + /// ## Implementation Note: Pallet Versioning /// - /// ## Implementation Note: Runtime Level Migration + /// Implementations of this hook are typically wrapped in + /// [`crate::migrations::VersionedMigration`] to ensure the migration is executed exactly + /// once and only when it is supposed to. /// - /// Additional "upgrade hooks" can be created by pallets by a manual implementation of - /// [`Hooks::on_runtime_upgrade`] which can be passed on to `Executive` at the top level - /// runtime. + /// Alternatively, developers can manually implement version checks. + /// + /// Failure to adequately check storage versions can result in accidental repetitive execution + /// of the hook, which can be catastrophic. + /// + /// ## Implementation Note: Weight + /// + /// Typically, implementations of this method are simple enough that weights can be calculated + /// manually. However, if required, a benchmark can also be used. fn on_runtime_upgrade() -> Weight { Weight::zero() } @@ -403,7 +415,7 @@ pub trait Hooks { /// It should focus on certain checks to ensure that the state is sensible. This is never /// executed in a consensus code-path, therefore it can consume as much weight as it needs. /// - /// This hook should not alter any storage. + /// This hook must not alter any storage. #[cfg(feature = "try-runtime")] fn try_state(_n: BlockNumber) -> Result<(), TryRuntimeError> { Ok(()) @@ -415,7 +427,7 @@ pub trait Hooks { /// which will be passed to `post_upgrade` after upgrading for post-check. An empty vector /// should be returned if there is no such need. /// - /// This hook is never meant to be executed on-chain but is meant to be used by testing tools. + /// This hook is never executed on-chain but instead used by testing tools. #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, TryRuntimeError> { Ok(Vec::new()) diff --git a/substrate/frame/support/src/traits/metadata.rs b/substrate/frame/support/src/traits/metadata.rs index 586af20511a..8bda4186bc9 100644 --- a/substrate/frame/support/src/traits/metadata.rs +++ b/substrate/frame/support/src/traits/metadata.rs @@ -261,41 +261,64 @@ impl Add for StorageVersion { } } -/// Special marker struct if no storage version is set for a pallet. +/// Special marker struct used when [`storage_version`](crate::pallet_macros::storage_version) is +/// not defined for a pallet. /// /// If you (the reader) end up here, it probably means that you tried to compare /// [`GetStorageVersion::on_chain_storage_version`] against -/// [`GetStorageVersion::current_storage_version`]. This basically means that the -/// [`storage_version`](crate::pallet_macros::storage_version) is missing in the pallet where the -/// mentioned functions are being called. +/// [`GetStorageVersion::in_code_storage_version`]. This basically means that the +/// [`storage_version`](crate::pallet_macros::storage_version) is missing from the pallet where the +/// mentioned functions are being called, and needs to be defined. #[derive(Debug, Default)] pub struct NoStorageVersionSet; -/// Provides information about the storage version of a pallet. +/// Provides information about a pallet's storage versions. /// -/// It differentiates between current and on-chain storage version. Both should be only out of sync -/// when a new runtime upgrade was applied and the runtime migrations did not yet executed. -/// Otherwise it means that the pallet works with an unsupported storage version and unforeseen -/// stuff can happen. +/// Every pallet has two storage versions: +/// 1. An in-code storage version +/// 2. An on-chain storage version /// -/// The current storage version is the version of the pallet as supported at runtime. The active -/// storage version is the version of the pallet in the storage. +/// The in-code storage version is the version of the pallet as defined in the runtime blob, and the +/// on-chain storage version is the version of the pallet stored on-chain. /// -/// It is required to update the on-chain storage version manually when a migration was applied. +/// Storage versions should be only ever be out of sync when a pallet has been updated to a new +/// version and the in-code version is incremented, but the migration has not yet been executed +/// on-chain as part of a runtime upgrade. +/// +/// It is the responsibility of the developer to ensure that the on-chain storage version is set +/// correctly during a migration so that it matches the in-code storage version. pub trait GetStorageVersion { - /// This will be filled out by the [`pallet`](crate::pallet) macro. + /// This type is generated by the [`pallet`](crate::pallet) macro. + /// + /// If the [`storage_version`](crate::pallet_macros::storage_version) attribute isn't specified, + /// this is set to [`NoStorageVersionSet`] to signify that it is missing. + /// + /// If the [`storage_version`](crate::pallet_macros::storage_version) attribute is specified, + /// this is be set to a [`StorageVersion`] corresponding to the attribute. /// - /// If the [`storage_version`](crate::pallet_macros::storage_version) attribute isn't given - /// this is set to [`NoStorageVersionSet`] to inform the user that the attribute is missing. - /// This should prevent that the user forgets to set a storage version when required. However, - /// this will only work when the user actually tries to call [`Self::current_storage_version`] - /// to compare it against the [`Self::on_chain_storage_version`]. If the attribute is given, - /// this will be set to [`StorageVersion`]. - type CurrentStorageVersion; - - /// Returns the current storage version as supported by the pallet. - fn current_storage_version() -> Self::CurrentStorageVersion; - /// Returns the on-chain storage version of the pallet as stored in the storage. + /// The intention of using [`NoStorageVersionSet`] instead of defaulting to a [`StorageVersion`] + /// of zero is to prevent developers from forgetting to set + /// [`storage_version`](crate::pallet_macros::storage_version) when it is required, like in the + /// case that they wish to compare the in-code storage version to the on-chain storage version. + type InCodeStorageVersion; + + #[deprecated( + note = "This method has been renamed to `in_code_storage_version` and will be removed after March 2024." + )] + /// DEPRECATED: Use [`Self::current_storage_version`] instead. + /// + /// Returns the in-code storage version as specified in the + /// [`storage_version`](crate::pallet_macros::storage_version) attribute, or + /// [`NoStorageVersionSet`] if the attribute is missing. + fn current_storage_version() -> Self::InCodeStorageVersion { + Self::in_code_storage_version() + } + + /// Returns the in-code storage version as specified in the + /// [`storage_version`](crate::pallet_macros::storage_version) attribute, or + /// [`NoStorageVersionSet`] if the attribute is missing. + fn in_code_storage_version() -> Self::InCodeStorageVersion; + /// Returns the storage version of the pallet as last set in the actual on-chain storage. fn on_chain_storage_version() -> StorageVersion; } diff --git a/substrate/frame/support/test/tests/construct_runtime.rs b/substrate/frame/support/test/tests/construct_runtime.rs index b8341b25cb0..b7698681886 100644 --- a/substrate/frame/support/test/tests/construct_runtime.rs +++ b/substrate/frame/support/test/tests/construct_runtime.rs @@ -683,7 +683,7 @@ fn test_metadata() { name: "Version", ty: meta_type::(), value: RuntimeVersion::default().encode(), - docs: maybe_docs(vec![ " Get the chain's current version."]), + docs: maybe_docs(vec![ " Get the chain's in-code version."]), }, PalletConstantMetadata { name: "SS58Prefix", diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 9b4381c2f82..7bee4b7c820 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -590,7 +590,7 @@ pub mod pallet2 { Self::deposit_event(Event::Something(31)); if UpdateStorageVersion::get() { - Self::current_storage_version().put::(); + Self::in_code_storage_version().put::(); } Weight::zero() @@ -1310,7 +1310,7 @@ fn pallet_on_genesis() { assert_eq!(pallet::Pallet::::on_chain_storage_version(), StorageVersion::new(0)); pallet::Pallet::::on_genesis(); assert_eq!( - pallet::Pallet::::current_storage_version(), + pallet::Pallet::::in_code_storage_version(), pallet::Pallet::::on_chain_storage_version(), ); }) @@ -2257,10 +2257,10 @@ fn pallet_on_chain_storage_version_initializes_correctly() { AllPalletsWithSystem, >; - // Simple example of a pallet with current version 10 being added to the runtime for the first + // Simple example of a pallet with in-code version 10 being added to the runtime for the first // time. TestExternalities::default().execute_with(|| { - let current_version = Example::current_storage_version(); + let in_code_version = Example::in_code_storage_version(); // Check the pallet has no storage items set. let pallet_hashed_prefix = twox_128(Example::name().as_bytes()); @@ -2271,14 +2271,14 @@ fn pallet_on_chain_storage_version_initializes_correctly() { // version. Executive::execute_on_runtime_upgrade(); - // Check that the storage version was initialized to the current version + // Check that the storage version was initialized to the in-code version let on_chain_version_after = StorageVersion::get::(); - assert_eq!(on_chain_version_after, current_version); + assert_eq!(on_chain_version_after, in_code_version); }); - // Pallet with no current storage version should have the on-chain version initialized to 0. + // Pallet with no in-code storage version should have the on-chain version initialized to 0. TestExternalities::default().execute_with(|| { - // Example4 current_storage_version is NoStorageVersionSet. + // Example4 in_code_storage_version is NoStorageVersionSet. // Check the pallet has no storage items set. let pallet_hashed_prefix = twox_128(Example4::name().as_bytes()); @@ -2308,7 +2308,7 @@ fn post_runtime_upgrade_detects_storage_version_issues() { impl OnRuntimeUpgrade for CustomUpgrade { fn on_runtime_upgrade() -> Weight { - Example2::current_storage_version().put::(); + Example2::in_code_storage_version().put::(); Default::default() } @@ -2351,14 +2351,14 @@ fn post_runtime_upgrade_detects_storage_version_issues() { >; TestExternalities::default().execute_with(|| { - // Set the on-chain version to one less than the current version for `Example`, simulating a + // Set the on-chain version to one less than the in-code version for `Example`, simulating a // forgotten migration StorageVersion::new(9).put::(); // The version isn't changed, we should detect it. assert!( Executive::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost).unwrap_err() == - "On chain and current storage version do not match. Missing runtime upgrade?" + "On chain and in-code storage version do not match. Missing runtime upgrade?" .into() ); }); diff --git a/substrate/frame/support/test/tests/pallet_ui/compare_unset_storage_version.rs b/substrate/frame/support/test/tests/pallet_ui/compare_unset_storage_version.rs index 840a6dee20c..d2ca9fc8099 100644 --- a/substrate/frame/support/test/tests/pallet_ui/compare_unset_storage_version.rs +++ b/substrate/frame/support/test/tests/pallet_ui/compare_unset_storage_version.rs @@ -29,7 +29,7 @@ mod pallet { #[pallet::hooks] impl Hooks> for Pallet { fn on_runtime_upgrade() -> Weight { - if Self::current_storage_version() != Self::on_chain_storage_version() { + if Self::in_code_storage_version() != Self::on_chain_storage_version() { } diff --git a/substrate/frame/support/test/tests/pallet_ui/compare_unset_storage_version.stderr b/substrate/frame/support/test/tests/pallet_ui/compare_unset_storage_version.stderr index 1b48197cc9e..3256e69528a 100644 --- a/substrate/frame/support/test/tests/pallet_ui/compare_unset_storage_version.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/compare_unset_storage_version.stderr @@ -1,7 +1,7 @@ error[E0369]: binary operation `!=` cannot be applied to type `NoStorageVersionSet` --> tests/pallet_ui/compare_unset_storage_version.rs:32:39 | -32 | if Self::current_storage_version() != Self::on_chain_storage_version() { +32 | if Self::in_code_storage_version() != Self::on_chain_storage_version() { | ------------------------------- ^^ -------------------------------- StorageVersion | | | NoStorageVersionSet diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index c527a483d88..01df09106d9 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -525,7 +525,7 @@ pub mod pallet { #[pallet::constant] type DbWeight: Get; - /// Get the chain's current version. + /// Get the chain's in-code version. #[pallet::constant] type Version: Get; diff --git a/substrate/frame/tips/src/lib.rs b/substrate/frame/tips/src/lib.rs index 4c7cfc3028a..8c360fb57d7 100644 --- a/substrate/frame/tips/src/lib.rs +++ b/substrate/frame/tips/src/lib.rs @@ -122,7 +122,7 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// The current storage version. + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); #[pallet::pallet] -- GitLab From f1b2189e8312821a9f8a79dc4f0183d314273faa Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Wed, 28 Feb 2024 11:43:58 +0200 Subject: [PATCH 041/188] rpc-v2/tx/tests: Add transaction broadcast tests and check propagated tx status (#3193) This PR adds tests for the `transaction_broadcast` method. The testing needs to coordinate the following components: - The `TestApi` marks transactions as invalid and implements `ChainApi::validate_transaction` - this is what dictates if a transaction is valid or not and is called from within the `BasicPool` - The `BasicPool` which maintains the transactions and implements `submit_and_watch` needed by the tx broadcast to submit the transaction - The status of the transaction pool is exposed by mocking the BasicPool - The `ChainHeadMockClient` which mocks the `BlockchainEvents::import_notification_stream` needed by the tx broadcast to know to which blocks the transaction is submitted The following changes have been added to the substrate testing to accommodate this: - `TestApi` gets ` remove_invalid`, counterpart to `add_invalid` to ensure an invalid transaction can become valid again; as well as a priority setter for extrinsics - `BasicPool` test constructor is extended with options for the `PoolRotator` - this mechanism is needed because transactions are banned for 30mins (default) after they are declared invalid - testing bypasses this by providing a `Duration::ZERO` ### Testing Scenarios - Capture the status of the transaction as it is normally broadcasted - `transaction_stop` is valid while the transaction is in progress - A future transaction is handled when the dependencies are completed - Try to resubmit the transaction at a later block (currently invalid) - An invalid transaction status is propagated; the transaction is marked as temporarily banned; then the ban expires and transaction is resubmitted This builds on top of: https://github.com/paritytech/polkadot-sdk/pull/3079 Part of: https://github.com/paritytech/polkadot-sdk/issues/3084 cc @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile Co-authored-by: James Wilson --- .../rpc-spec-v2/src/chain_head/test_utils.rs | 4 +- .../rpc-spec-v2/src/transaction/tests.rs | 238 -------- .../src/transaction/tests/executor.rs | 100 ++++ .../src/transaction/tests/middleware_pool.rs | 187 +++++++ .../rpc-spec-v2/src/transaction/tests/mod.rs | 24 + .../src/transaction/tests/setup.rs | 120 ++++ .../tests/transaction_broadcast_tests.rs | 523 ++++++++++++++++++ substrate/client/transaction-pool/src/lib.rs | 3 +- .../client/transaction-pool/tests/pool.rs | 3 +- .../runtime/transaction-pool/src/lib.rs | 27 +- 10 files changed, 985 insertions(+), 244 deletions(-) delete mode 100644 substrate/client/rpc-spec-v2/src/transaction/tests.rs create mode 100644 substrate/client/rpc-spec-v2/src/transaction/tests/executor.rs create mode 100644 substrate/client/rpc-spec-v2/src/transaction/tests/middleware_pool.rs create mode 100644 substrate/client/rpc-spec-v2/src/transaction/tests/mod.rs create mode 100644 substrate/client/rpc-spec-v2/src/transaction/tests/setup.rs create mode 100644 substrate/client/rpc-spec-v2/src/transaction/tests/transaction_broadcast_tests.rs diff --git a/substrate/client/rpc-spec-v2/src/chain_head/test_utils.rs b/substrate/client/rpc-spec-v2/src/chain_head/test_utils.rs index d63a98a5cb0..e81bd4bfa0b 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/test_utils.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/test_utils.rs @@ -63,7 +63,7 @@ impl ChainHeadMockClient { BlockImportNotification::new(header.hash(), BlockOrigin::Own, header, true, None, sink); for sink in self.import_sinks.lock().iter_mut() { - sink.unbounded_send(notification.clone()).unwrap(); + let _ = sink.unbounded_send(notification.clone()); } } @@ -83,7 +83,7 @@ impl ChainHeadMockClient { let notification = FinalityNotification::from_summary(summary, sink); for sink in self.finality_sinks.lock().iter_mut() { - sink.unbounded_send(notification.clone()).unwrap(); + let _ = sink.unbounded_send(notification.clone()); } } } diff --git a/substrate/client/rpc-spec-v2/src/transaction/tests.rs b/substrate/client/rpc-spec-v2/src/transaction/tests.rs deleted file mode 100644 index 382f5adeae1..00000000000 --- a/substrate/client/rpc-spec-v2/src/transaction/tests.rs +++ /dev/null @@ -1,238 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program 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. - -// This program 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 this program. If not, see . - -use super::*; -use crate::{ - chain_head::test_utils::ChainHeadMockClient, hex_string, - transaction::TransactionBroadcast as RpcTransactionBroadcast, -}; -use assert_matches::assert_matches; -use codec::Encode; -use futures::Future; -use jsonrpsee::{rpc_params, MethodsError as Error, RpcModule}; -use sc_transaction_pool::*; -use sc_transaction_pool_api::{ChainEvent, MaintainedTransactionPool, TransactionPool}; -use sp_core::{testing::TaskExecutor, traits::SpawnNamed}; -use std::{pin::Pin, sync::Arc, time::Duration}; -use substrate_test_runtime_client::{prelude::*, AccountKeyring::*, Client}; -use substrate_test_runtime_transaction_pool::{uxt, TestApi}; -use tokio::sync::mpsc; - -type Block = substrate_test_runtime_client::runtime::Block; - -/// Wrap the `TaskExecutor` to know when the broadcast future is dropped. -#[derive(Clone)] -struct TaskExecutorBroadcast { - executor: TaskExecutor, - sender: mpsc::UnboundedSender<()>, -} - -/// The channel that receives events when the broadcast futures are dropped. -type TaskExecutorRecv = mpsc::UnboundedReceiver<()>; - -impl TaskExecutorBroadcast { - /// Construct a new `TaskExecutorBroadcast` and a receiver to know when the broadcast futures - /// are dropped. - fn new() -> (Self, TaskExecutorRecv) { - let (sender, recv) = mpsc::unbounded_channel(); - - (Self { executor: TaskExecutor::new(), sender }, recv) - } -} - -impl SpawnNamed for TaskExecutorBroadcast { - fn spawn( - &self, - name: &'static str, - group: Option<&'static str>, - future: futures::future::BoxFuture<'static, ()>, - ) { - let sender = self.sender.clone(); - let future = Box::pin(async move { - future.await; - let _ = sender.send(()); - }); - - self.executor.spawn(name, group, future) - } - - fn spawn_blocking( - &self, - name: &'static str, - group: Option<&'static str>, - future: futures::future::BoxFuture<'static, ()>, - ) { - let sender = self.sender.clone(); - let future = Box::pin(async move { - future.await; - let _ = sender.send(()); - }); - - self.executor.spawn_blocking(name, group, future) - } -} - -/// Initial Alice account nonce. -const ALICE_NONCE: u64 = 209; - -fn create_basic_pool_with_genesis( - test_api: Arc, -) -> (BasicPool, Pin + Send>>) { - let genesis_hash = { - test_api - .chain() - .read() - .block_by_number - .get(&0) - .map(|blocks| blocks[0].0.header.hash()) - .expect("there is block 0. qed") - }; - BasicPool::new_test(test_api, genesis_hash, genesis_hash) -} - -fn maintained_pool() -> (BasicPool, Arc, futures::executor::ThreadPool) { - let api = Arc::new(TestApi::with_alice_nonce(ALICE_NONCE)); - let (pool, background_task) = create_basic_pool_with_genesis(api.clone()); - - let thread_pool = futures::executor::ThreadPool::new().unwrap(); - thread_pool.spawn_ok(background_task); - (pool, api, thread_pool) -} - -fn setup_api() -> ( - Arc, - Arc>, - Arc>>, - RpcModule< - TransactionBroadcast, ChainHeadMockClient>>, - >, - TaskExecutorRecv, -) { - let (pool, api, _) = maintained_pool(); - let pool = Arc::new(pool); - - let builder = TestClientBuilder::new(); - let client = Arc::new(builder.build()); - let client_mock = Arc::new(ChainHeadMockClient::new(client.clone())); - - let (task_executor, executor_recv) = TaskExecutorBroadcast::new(); - - let tx_api = - RpcTransactionBroadcast::new(client_mock.clone(), pool.clone(), Arc::new(task_executor)) - .into_rpc(); - - (api, pool, client_mock, tx_api, executor_recv) -} - -#[tokio::test] -async fn tx_broadcast_enters_pool() { - let (api, pool, client_mock, tx_api, _) = setup_api(); - - // Start at block 1. - let block_1_header = api.push_block(1, vec![], true); - - let uxt = uxt(Alice, ALICE_NONCE); - let xt = hex_string(&uxt.encode()); - - let operation_id: String = - tx_api.call("transaction_unstable_broadcast", rpc_params![&xt]).await.unwrap(); - - // Announce block 1 to `transaction_unstable_broadcast`. - client_mock.trigger_import_stream(block_1_header).await; - - // Ensure the tx propagated from `transaction_unstable_broadcast` to the transaction pool. - - // TODO: Improve testability by extending the `transaction_unstable_broadcast` with - // a middleware trait that intercepts the transaction status for testing. - let mut num_retries = 12; - while num_retries > 0 && pool.status().ready != 1 { - tokio::time::sleep(Duration::from_secs(5)).await; - num_retries -= 1; - } - assert_eq!(1, pool.status().ready); - assert_eq!(uxt.encode().len(), pool.status().ready_bytes); - - // Import block 2 with the transaction included. - let block_2_header = api.push_block(2, vec![uxt.clone()], true); - let block_2 = block_2_header.hash(); - - // Announce block 2 to the pool. - let event = ChainEvent::NewBestBlock { hash: block_2, tree_route: None }; - pool.maintain(event).await; - - assert_eq!(0, pool.status().ready); - - // Stop call can still be made. - let _: () = tx_api - .call("transaction_unstable_stop", rpc_params![&operation_id]) - .await - .unwrap(); -} - -#[tokio::test] -async fn tx_broadcast_invalid_tx() { - let (_, pool, _, tx_api, mut exec_recv) = setup_api(); - - // Invalid parameters. - let err = tx_api - .call::<_, serde_json::Value>("transaction_unstable_broadcast", [1u8]) - .await - .unwrap_err(); - assert_matches!(err, - Error::JsonRpc(err) if err.code() == super::error::json_rpc_spec::INVALID_PARAM_ERROR && err.message() == "Invalid params" - ); - - assert_eq!(0, pool.status().ready); - - // Invalid transaction that cannot be decoded. The broadcast silently exits. - let xt = "0xdeadbeef"; - let operation_id: String = - tx_api.call("transaction_unstable_broadcast", rpc_params![&xt]).await.unwrap(); - - assert_eq!(0, pool.status().ready); - - // Await the broadcast future to exit. - // Without this we'd be subject to races, where we try to call the stop before the tx is - // dropped. - exec_recv.recv().await.unwrap(); - - // The broadcast future was dropped, and the operation is no longer active. - // When the operation is not active, either from the tx being finalized or a - // terminal error; the stop method should return an error. - let err = tx_api - .call::<_, serde_json::Value>("transaction_unstable_stop", rpc_params![&operation_id]) - .await - .unwrap_err(); - assert_matches!(err, - Error::JsonRpc(err) if err.code() == super::error::json_rpc_spec::INVALID_PARAM_ERROR && err.message() == "Invalid operation id" - ); -} - -#[tokio::test] -async fn tx_invalid_stop() { - let (_, _, _, tx_api, _) = setup_api(); - - // Make an invalid stop call. - let err = tx_api - .call::<_, serde_json::Value>("transaction_unstable_stop", ["invalid_operation_id"]) - .await - .unwrap_err(); - assert_matches!(err, - Error::JsonRpc(err) if err.code() == super::error::json_rpc_spec::INVALID_PARAM_ERROR && err.message() == "Invalid operation id" - ); -} diff --git a/substrate/client/rpc-spec-v2/src/transaction/tests/executor.rs b/substrate/client/rpc-spec-v2/src/transaction/tests/executor.rs new file mode 100644 index 00000000000..ff9aca79887 --- /dev/null +++ b/substrate/client/rpc-spec-v2/src/transaction/tests/executor.rs @@ -0,0 +1,100 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +use sp_core::{testing::TaskExecutor, traits::SpawnNamed}; +use std::sync::{atomic::AtomicUsize, Arc}; +use tokio::sync::mpsc; + +/// Wrap the `TaskExecutor` to know when the broadcast future is dropped. +#[derive(Clone)] +pub struct TaskExecutorBroadcast { + executor: TaskExecutor, + sender: mpsc::UnboundedSender<()>, + num_tasks: Arc, +} + +/// The channel that receives events when the broadcast futures are dropped. +pub type TaskExecutorRecv = mpsc::UnboundedReceiver<()>; + +/// The state of the `TaskExecutorBroadcast`. +pub struct TaskExecutorState { + pub recv: TaskExecutorRecv, + pub num_tasks: Arc, +} + +impl TaskExecutorState { + pub fn num_tasks(&self) -> usize { + self.num_tasks.load(std::sync::atomic::Ordering::Acquire) + } +} + +impl TaskExecutorBroadcast { + /// Construct a new `TaskExecutorBroadcast` and a receiver to know when the broadcast futures + /// are dropped. + pub fn new() -> (Self, TaskExecutorState) { + let (sender, recv) = mpsc::unbounded_channel(); + let num_tasks = Arc::new(AtomicUsize::new(0)); + + ( + Self { executor: TaskExecutor::new(), sender, num_tasks: num_tasks.clone() }, + TaskExecutorState { recv, num_tasks }, + ) + } +} + +impl SpawnNamed for TaskExecutorBroadcast { + fn spawn( + &self, + name: &'static str, + group: Option<&'static str>, + future: futures::future::BoxFuture<'static, ()>, + ) { + let sender = self.sender.clone(); + let num_tasks = self.num_tasks.clone(); + + let future = Box::pin(async move { + num_tasks.fetch_add(1, std::sync::atomic::Ordering::AcqRel); + future.await; + num_tasks.fetch_sub(1, std::sync::atomic::Ordering::AcqRel); + + let _ = sender.send(()); + }); + + self.executor.spawn(name, group, future) + } + + fn spawn_blocking( + &self, + name: &'static str, + group: Option<&'static str>, + future: futures::future::BoxFuture<'static, ()>, + ) { + let sender = self.sender.clone(); + let num_tasks = self.num_tasks.clone(); + + let future = Box::pin(async move { + num_tasks.fetch_add(1, std::sync::atomic::Ordering::AcqRel); + future.await; + num_tasks.fetch_sub(1, std::sync::atomic::Ordering::AcqRel); + + let _ = sender.send(()); + }); + + self.executor.spawn_blocking(name, group, future) + } +} diff --git a/substrate/client/rpc-spec-v2/src/transaction/tests/middleware_pool.rs b/substrate/client/rpc-spec-v2/src/transaction/tests/middleware_pool.rs new file mode 100644 index 00000000000..aa8ac572dec --- /dev/null +++ b/substrate/client/rpc-spec-v2/src/transaction/tests/middleware_pool.rs @@ -0,0 +1,187 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +use codec::Encode; +use futures::Future; +use sc_transaction_pool::BasicPool; +use sc_transaction_pool_api::{ + ImportNotificationStream, PoolFuture, PoolStatus, ReadyTransactions, TransactionFor, + TransactionPool, TransactionSource, TransactionStatusStreamFor, TxHash, +}; + +use crate::hex_string; +use futures::{FutureExt, StreamExt}; + +use sp_runtime::traits::{Block as BlockT, NumberFor}; +use std::{collections::HashMap, pin::Pin, sync::Arc}; +use substrate_test_runtime_transaction_pool::TestApi; +use tokio::sync::mpsc; + +pub type Block = substrate_test_runtime_client::runtime::Block; + +pub type TxTestPool = MiddlewarePool; +pub type TxStatusType = sc_transaction_pool_api::TransactionStatus< + sc_transaction_pool_api::TxHash, + sc_transaction_pool_api::BlockHash, +>; +pub type TxStatusTypeTest = TxStatusType; + +/// The type of the event that the middleware captures. +#[derive(Debug, PartialEq)] +pub enum MiddlewarePoolEvent { + TransactionStatus { + transaction: String, + status: sc_transaction_pool_api::TransactionStatus< + ::Hash, + ::Hash, + >, + }, + PoolError { + transaction: String, + err: String, + }, +} + +/// The channel that receives events when the broadcast futures are dropped. +pub type MiddlewarePoolRecv = mpsc::UnboundedReceiver; + +/// Add a middleware to the transaction pool. +/// +/// This wraps the `submit_and_watch` to gain access to the events. +pub struct MiddlewarePool { + pub inner_pool: Arc>, + /// Send the middleware events to the test. + sender: mpsc::UnboundedSender, +} + +impl MiddlewarePool { + /// Construct a new [`MiddlewarePool`]. + pub fn new(pool: Arc>) -> (Self, MiddlewarePoolRecv) { + let (sender, recv) = mpsc::unbounded_channel(); + (MiddlewarePool { inner_pool: pool, sender }, recv) + } +} + +impl TransactionPool for MiddlewarePool { + type Block = as TransactionPool>::Block; + type Hash = as TransactionPool>::Hash; + type InPoolTransaction = as TransactionPool>::InPoolTransaction; + type Error = as TransactionPool>::Error; + + fn submit_at( + &self, + at: ::Hash, + source: TransactionSource, + xts: Vec>, + ) -> PoolFuture, Self::Error>>, Self::Error> { + self.inner_pool.submit_at(at, source, xts) + } + + fn submit_one( + &self, + at: ::Hash, + source: TransactionSource, + xt: TransactionFor, + ) -> PoolFuture, Self::Error> { + self.inner_pool.submit_one(at, source, xt) + } + + fn submit_and_watch( + &self, + at: ::Hash, + source: TransactionSource, + xt: TransactionFor, + ) -> PoolFuture>>, Self::Error> { + let pool = self.inner_pool.clone(); + let sender = self.sender.clone(); + let transaction = hex_string(&xt.encode()); + + async move { + let watcher = match pool.submit_and_watch(at, source, xt).await { + Ok(watcher) => watcher, + Err(err) => { + let _ = sender.send(MiddlewarePoolEvent::PoolError { + transaction: transaction.clone(), + err: err.to_string(), + }); + return Err(err); + }, + }; + + let watcher = watcher.map(move |status| { + let sender = sender.clone(); + let transaction = transaction.clone(); + + let _ = sender.send(MiddlewarePoolEvent::TransactionStatus { + transaction, + status: status.clone(), + }); + + status + }); + + Ok(watcher.boxed()) + } + .boxed() + } + + fn remove_invalid(&self, hashes: &[TxHash]) -> Vec> { + self.inner_pool.remove_invalid(hashes) + } + + fn status(&self) -> PoolStatus { + self.inner_pool.status() + } + + fn import_notification_stream(&self) -> ImportNotificationStream> { + self.inner_pool.import_notification_stream() + } + + fn hash_of(&self, xt: &TransactionFor) -> TxHash { + self.inner_pool.hash_of(xt) + } + + fn on_broadcasted(&self, propagations: HashMap, Vec>) { + self.inner_pool.on_broadcasted(propagations) + } + + fn ready_transaction(&self, hash: &TxHash) -> Option> { + self.inner_pool.ready_transaction(hash) + } + + fn ready_at( + &self, + at: NumberFor, + ) -> Pin< + Box< + dyn Future< + Output = Box> + Send>, + > + Send, + >, + > { + self.inner_pool.ready_at(at) + } + + fn ready(&self) -> Box> + Send> { + self.inner_pool.ready() + } + + fn futures(&self) -> Vec { + self.inner_pool.futures() + } +} diff --git a/substrate/client/rpc-spec-v2/src/transaction/tests/mod.rs b/substrate/client/rpc-spec-v2/src/transaction/tests/mod.rs new file mode 100644 index 00000000000..ab0caaf906f --- /dev/null +++ b/substrate/client/rpc-spec-v2/src/transaction/tests/mod.rs @@ -0,0 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +mod executor; +mod middleware_pool; +#[macro_use] +mod setup; + +mod transaction_broadcast_tests; diff --git a/substrate/client/rpc-spec-v2/src/transaction/tests/setup.rs b/substrate/client/rpc-spec-v2/src/transaction/tests/setup.rs new file mode 100644 index 00000000000..04ee7b9b4c9 --- /dev/null +++ b/substrate/client/rpc-spec-v2/src/transaction/tests/setup.rs @@ -0,0 +1,120 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +use crate::{ + chain_head::test_utils::ChainHeadMockClient, + transaction::{ + api::TransactionBroadcastApiServer, + tests::executor::{TaskExecutorBroadcast, TaskExecutorState}, + TransactionBroadcast as RpcTransactionBroadcast, + }, +}; +use futures::Future; +use jsonrpsee::RpcModule; +use sc_transaction_pool::*; +use std::{pin::Pin, sync::Arc}; +use substrate_test_runtime_client::{prelude::*, Client}; +use substrate_test_runtime_transaction_pool::TestApi; + +use crate::transaction::tests::middleware_pool::{MiddlewarePool, MiddlewarePoolRecv}; + +pub type Block = substrate_test_runtime_client::runtime::Block; + +/// Initial Alice account nonce. +pub const ALICE_NONCE: u64 = 209; + +fn create_basic_pool_with_genesis( + test_api: Arc, + options: Options, +) -> (BasicPool, Pin + Send>>) { + let genesis_hash = { + test_api + .chain() + .read() + .block_by_number + .get(&0) + .map(|blocks| blocks[0].0.header.hash()) + .expect("there is block 0. qed") + }; + BasicPool::new_test(test_api, genesis_hash, genesis_hash, options) +} + +fn maintained_pool( + options: Options, +) -> (BasicPool, Arc, futures::executor::ThreadPool) { + let api = Arc::new(TestApi::with_alice_nonce(ALICE_NONCE)); + let (pool, background_task) = create_basic_pool_with_genesis(api.clone(), options); + + let thread_pool = futures::executor::ThreadPool::new().unwrap(); + thread_pool.spawn_ok(background_task); + (pool, api, thread_pool) +} + +pub fn setup_api( + options: Options, +) -> ( + Arc, + Arc, + Arc>>, + RpcModule>>>, + TaskExecutorState, + MiddlewarePoolRecv, +) { + let (pool, api, _) = maintained_pool(options); + let (pool, pool_state) = MiddlewarePool::new(Arc::new(pool).clone()); + let pool = Arc::new(pool); + + let builder = TestClientBuilder::new(); + let client = Arc::new(builder.build()); + let client_mock = Arc::new(ChainHeadMockClient::new(client.clone())); + + let (task_executor, executor_recv) = TaskExecutorBroadcast::new(); + + let tx_api = + RpcTransactionBroadcast::new(client_mock.clone(), pool.clone(), Arc::new(task_executor)) + .into_rpc(); + + (api, pool, client_mock, tx_api, executor_recv, pool_state) +} + +/// Get the next event from the provided middleware in at most 5 seconds. +macro_rules! get_next_event { + ($middleware:expr) => { + tokio::time::timeout(std::time::Duration::from_secs(5), $middleware.recv()) + .await + .unwrap() + .unwrap() + }; +} + +/// Collect the next number of transaction events from the provided middleware. +macro_rules! get_next_tx_events { + ($middleware:expr, $num:expr) => {{ + let mut events = std::collections::HashMap::new(); + for _ in 0..$num { + let event = get_next_event!($middleware); + match event { + crate::transaction::tests::middleware_pool::MiddlewarePoolEvent::TransactionStatus { transaction, status } => { + events.entry(transaction).or_insert_with(|| vec![]).push(status); + }, + other => panic!("Expected TransactionStatus, received {:?}", other), + }; + } + events + }}; +} diff --git a/substrate/client/rpc-spec-v2/src/transaction/tests/transaction_broadcast_tests.rs b/substrate/client/rpc-spec-v2/src/transaction/tests/transaction_broadcast_tests.rs new file mode 100644 index 00000000000..690a1a64d74 --- /dev/null +++ b/substrate/client/rpc-spec-v2/src/transaction/tests/transaction_broadcast_tests.rs @@ -0,0 +1,523 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +use crate::{hex_string, transaction::error::json_rpc_spec}; +use assert_matches::assert_matches; +use codec::Encode; +use jsonrpsee::{rpc_params, MethodsError as Error}; +use sc_transaction_pool::{Options, PoolLimit}; +use sc_transaction_pool_api::{ChainEvent, MaintainedTransactionPool, TransactionPool}; +use std::sync::Arc; +use substrate_test_runtime_client::AccountKeyring::*; +use substrate_test_runtime_transaction_pool::uxt; + +// Test helpers. +use crate::transaction::tests::{ + middleware_pool::{MiddlewarePoolEvent, TxStatusTypeTest}, + setup::{setup_api, ALICE_NONCE}, +}; + +#[tokio::test] +async fn tx_broadcast_enters_pool() { + let (api, pool, client_mock, tx_api, mut exec_middleware, mut pool_middleware) = + setup_api(Default::default()); + + // Start at block 1. + let block_1_header = api.push_block(1, vec![], true); + + let uxt = uxt(Alice, ALICE_NONCE); + let xt = hex_string(&uxt.encode()); + + let operation_id: String = + tx_api.call("transaction_unstable_broadcast", rpc_params![&xt]).await.unwrap(); + + // Announce block 1 to `transaction_unstable_broadcast`. + client_mock.trigger_import_stream(block_1_header).await; + + // Ensure the tx propagated from `transaction_unstable_broadcast` to the transaction pool. + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::Ready + } + ); + + assert_eq!(1, pool.inner_pool.status().ready); + assert_eq!(uxt.encode().len(), pool.inner_pool.status().ready_bytes); + + // Import block 2 with the transaction included. + let block_2_header = api.push_block(2, vec![uxt.clone()], true); + let block_2 = block_2_header.hash(); + + // Announce block 2 to the pool. + let event = ChainEvent::NewBestBlock { hash: block_2, tree_route: None }; + pool.inner_pool.maintain(event).await; + assert_eq!(0, pool.inner_pool.status().ready); + + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::InBlock((block_2, 0)) + } + ); + + // The future broadcast awaits for the finalized status to be reached. + // Force the future to exit by calling stop. + let _: () = tx_api + .call("transaction_unstable_stop", rpc_params![&operation_id]) + .await + .unwrap(); + + // Ensure the broadcast future finishes. + let _ = get_next_event!(&mut exec_middleware.recv); + assert_eq!(0, exec_middleware.num_tasks()); +} + +#[tokio::test] +async fn tx_broadcast_invalid_tx() { + let (_, pool, _, tx_api, mut exec_middleware, _) = setup_api(Default::default()); + + // Invalid parameters. + let err = tx_api + .call::<_, serde_json::Value>("transaction_unstable_broadcast", [1u8]) + .await + .unwrap_err(); + assert_matches!(err, + Error::JsonRpc(err) if err.code() == json_rpc_spec::INVALID_PARAM_ERROR && err.message() == "Invalid params" + ); + + assert_eq!(0, pool.status().ready); + + // Invalid transaction that cannot be decoded. The broadcast silently exits. + let xt = "0xdeadbeef"; + let operation_id: String = + tx_api.call("transaction_unstable_broadcast", rpc_params![&xt]).await.unwrap(); + + assert_eq!(0, pool.status().ready); + + // Await the broadcast future to exit. + // Without this we'd be subject to races, where we try to call the stop before the tx is + // dropped. + let _ = get_next_event!(&mut exec_middleware.recv); + assert_eq!(0, exec_middleware.num_tasks()); + + // The broadcast future was dropped, and the operation is no longer active. + // When the operation is not active, either from the tx being finalized or a + // terminal error; the stop method should return an error. + let err = tx_api + .call::<_, serde_json::Value>("transaction_unstable_stop", rpc_params![&operation_id]) + .await + .unwrap_err(); + assert_matches!(err, + Error::JsonRpc(err) if err.code() == json_rpc_spec::INVALID_PARAM_ERROR && err.message() == "Invalid operation id" + ); +} + +#[tokio::test] +async fn tx_stop_with_invalid_operation_id() { + let (_, _, _, tx_api, _, _) = setup_api(Default::default()); + + // Make an invalid stop call. + let err = tx_api + .call::<_, serde_json::Value>("transaction_unstable_stop", ["invalid_operation_id"]) + .await + .unwrap_err(); + assert_matches!(err, + Error::JsonRpc(err) if err.code() == json_rpc_spec::INVALID_PARAM_ERROR && err.message() == "Invalid operation id" + ); +} + +#[tokio::test] +async fn tx_broadcast_resubmits_future_nonce_tx() { + let (api, pool, client_mock, tx_api, mut exec_middleware, mut pool_middleware) = + setup_api(Default::default()); + + // Start at block 1. + let block_1_header = api.push_block(1, vec![], true); + let block_1 = block_1_header.hash(); + + let current_uxt = uxt(Alice, ALICE_NONCE); + let current_xt = hex_string(¤t_uxt.encode()); + // This lives in the future. + let future_uxt = uxt(Alice, ALICE_NONCE + 1); + let future_xt = hex_string(&future_uxt.encode()); + + let future_operation_id: String = tx_api + .call("transaction_unstable_broadcast", rpc_params![&future_xt]) + .await + .unwrap(); + + // Announce block 1 to `transaction_unstable_broadcast`. + client_mock.trigger_import_stream(block_1_header).await; + + // Ensure the tx propagated from `transaction_unstable_broadcast` to the transaction pool. + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: future_xt.clone(), + status: TxStatusTypeTest::Future + } + ); + + let event = ChainEvent::NewBestBlock { hash: block_1, tree_route: None }; + pool.inner_pool.maintain(event).await; + assert_eq!(0, pool.inner_pool.status().ready); + // Ensure the tx is in the future. + assert_eq!(1, pool.inner_pool.status().future); + + let block_2_header = api.push_block(2, vec![], true); + let block_2 = block_2_header.hash(); + + let operation_id: String = tx_api + .call("transaction_unstable_broadcast", rpc_params![¤t_xt]) + .await + .unwrap(); + assert_ne!(future_operation_id, operation_id); + + // Announce block 2 to `transaction_unstable_broadcast`. + client_mock.trigger_import_stream(block_2_header).await; + + // Collect the events of both transactions. + let events = get_next_tx_events!(&mut pool_middleware, 2); + // Transactions entered the ready queue. + assert_eq!(events.get(¤t_xt).unwrap(), &vec![TxStatusTypeTest::Ready]); + assert_eq!(events.get(&future_xt).unwrap(), &vec![TxStatusTypeTest::Ready]); + + let event = ChainEvent::NewBestBlock { hash: block_2, tree_route: None }; + pool.inner_pool.maintain(event).await; + assert_eq!(2, pool.inner_pool.status().ready); + assert_eq!(0, pool.inner_pool.status().future); + + // Finalize transactions. + let block_3_header = api.push_block(3, vec![current_uxt, future_uxt], true); + let block_3 = block_3_header.hash(); + client_mock.trigger_import_stream(block_3_header).await; + + let event = ChainEvent::Finalized { hash: block_3, tree_route: Arc::from(vec![]) }; + pool.inner_pool.maintain(event).await; + assert_eq!(0, pool.inner_pool.status().ready); + assert_eq!(0, pool.inner_pool.status().future); + + let events = get_next_tx_events!(&mut pool_middleware, 4); + assert_eq!( + events.get(¤t_xt).unwrap(), + &vec![TxStatusTypeTest::InBlock((block_3, 0)), TxStatusTypeTest::Finalized((block_3, 0))] + ); + assert_eq!( + events.get(&future_xt).unwrap(), + &vec![TxStatusTypeTest::InBlock((block_3, 1)), TxStatusTypeTest::Finalized((block_3, 1))] + ); + + // Both broadcast futures must exit. + let _ = get_next_event!(&mut exec_middleware.recv); + let _ = get_next_event!(&mut exec_middleware.recv); + assert_eq!(0, exec_middleware.num_tasks()); +} + +/// This test is similar to `tx_broadcast_enters_pool` +/// However the last block is announced as finalized to force the +/// broadcast future to exit before the `stop` is called. +#[tokio::test] +async fn tx_broadcast_stop_after_broadcast_finishes() { + let (api, pool, client_mock, tx_api, mut exec_middleware, mut pool_middleware) = + setup_api(Default::default()); + + // Start at block 1. + let block_1_header = api.push_block(1, vec![], true); + + let uxt = uxt(Alice, ALICE_NONCE); + let xt = hex_string(&uxt.encode()); + + let operation_id: String = + tx_api.call("transaction_unstable_broadcast", rpc_params![&xt]).await.unwrap(); + + // Announce block 1 to `transaction_unstable_broadcast`. + client_mock.trigger_import_stream(block_1_header).await; + + // Ensure the tx propagated from `transaction_unstable_broadcast` to the transaction + // pool.inner_pool. + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::Ready + } + ); + + assert_eq!(1, pool.inner_pool.status().ready); + assert_eq!(uxt.encode().len(), pool.inner_pool.status().ready_bytes); + + // Import block 2 with the transaction included. + let block_2_header = api.push_block(2, vec![uxt.clone()], true); + let block_2 = block_2_header.hash(); + + // Announce block 2 to the pool.inner_pool. + let event = ChainEvent::Finalized { hash: block_2, tree_route: Arc::from(vec![]) }; + pool.inner_pool.maintain(event).await; + + assert_eq!(0, pool.inner_pool.status().ready); + + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::InBlock((block_2, 0)) + } + ); + + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::Finalized((block_2, 0)) + } + ); + + // Ensure the broadcast future terminated properly. + let _ = get_next_event!(&mut exec_middleware.recv); + assert_eq!(0, exec_middleware.num_tasks()); + + // The operation ID is no longer valid, check that the broadcast future + // cleared out the inner state of the operation. + let err = tx_api + .call::<_, serde_json::Value>("transaction_unstable_stop", rpc_params![&operation_id]) + .await + .unwrap_err(); + assert_matches!(err, + Error::JsonRpc(err) if err.code() == json_rpc_spec::INVALID_PARAM_ERROR && err.message() == "Invalid operation id" + ); +} + +#[tokio::test] +async fn tx_broadcast_resubmits_invalid_tx() { + let limits = PoolLimit { count: 8192, total_bytes: 20 * 1024 * 1024 }; + let options = Options { + ready: limits.clone(), + future: limits, + reject_future_transactions: false, + // This ensures that a transaction is not banned. + ban_time: std::time::Duration::ZERO, + }; + + let (api, pool, client_mock, tx_api, mut exec_middleware, mut pool_middleware) = + setup_api(options); + + let uxt = uxt(Alice, ALICE_NONCE); + let xt = hex_string(&uxt.encode()); + let _operation_id: String = + tx_api.call("transaction_unstable_broadcast", rpc_params![&xt]).await.unwrap(); + + let block_1_header = api.push_block(1, vec![], true); + let block_1 = block_1_header.hash(); + // Announce block 1 to `transaction_unstable_broadcast`. + client_mock.trigger_import_stream(block_1_header).await; + + // Ensure the tx propagated from `transaction_unstable_broadcast` to the transaction pool. + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::Ready, + } + ); + assert_eq!(1, pool.inner_pool.status().ready); + assert_eq!(uxt.encode().len(), pool.inner_pool.status().ready_bytes); + + // Mark the transaction as invalid from the API, causing a temporary ban. + api.add_invalid(&uxt); + + // Push an event to the pool to ensure the transaction is excluded. + let event = ChainEvent::NewBestBlock { hash: block_1, tree_route: None }; + pool.inner_pool.maintain(event).await; + assert_eq!(1, pool.inner_pool.status().ready); + + // Ensure the `transaction_unstable_broadcast` is aware of the invalid transaction. + let event = get_next_event!(&mut pool_middleware); + // Because we have received an `Invalid` status, we try to broadcast the transaction with the + // next announced block. + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::Invalid + } + ); + + // Import block 2. + let block_2_header = api.push_block(2, vec![], true); + client_mock.trigger_import_stream(block_2_header).await; + + // Ensure we propagate the temporary ban error to `submit_and_watch`. + // This ensures we'll loop again with the next annmounced block and try to resubmit the + // transaction. The transaction remains temporarily banned until the pool is maintained. + let event = get_next_event!(&mut pool_middleware); + assert_matches!(event, MiddlewarePoolEvent::PoolError { transaction, err } if transaction == xt && err.contains("Transaction temporarily Banned")); + + // Import block 3. + let block_3_header = api.push_block(3, vec![], true); + let block_3 = block_3_header.hash(); + // Remove the invalid transaction from the pool to allow it to pass through. + api.remove_invalid(&uxt); + let event = ChainEvent::NewBestBlock { hash: block_3, tree_route: None }; + // We have to maintain the pool to ensure the transaction is no longer invalid. + // This clears out the banned transactions. + pool.inner_pool.maintain(event).await; + assert_eq!(0, pool.inner_pool.status().ready); + + // Announce block to `transaction_unstable_broadcast`. + client_mock.trigger_import_stream(block_3_header).await; + + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::Ready, + } + ); + assert_eq!(1, pool.inner_pool.status().ready); + + let block_4_header = api.push_block(4, vec![uxt], true); + let block_4 = block_4_header.hash(); + let event = ChainEvent::Finalized { hash: block_4, tree_route: Arc::from(vec![]) }; + pool.inner_pool.maintain(event).await; + + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::InBlock((block_4, 0)), + } + ); + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: xt.clone(), + status: TxStatusTypeTest::Finalized((block_4, 0)), + } + ); + + // Ensure the broadcast future terminated properly. + let _ = get_next_event!(&mut exec_middleware.recv); + assert_eq!(0, exec_middleware.num_tasks()); +} + +/// This is similar to `tx_broadcast_resubmits_invalid_tx`. +/// However, it forces the tx to be resubmited because of the pool +/// limits. Which is a different code path than the invalid tx. +#[tokio::test] +async fn tx_broadcast_resubmits_dropped_tx() { + let limits = PoolLimit { count: 1, total_bytes: 1000 }; + let options = Options { + ready: limits.clone(), + future: limits, + reject_future_transactions: false, + // This ensures that a transaction is not banned. + ban_time: std::time::Duration::ZERO, + }; + + let (api, pool, client_mock, tx_api, _, mut pool_middleware) = setup_api(options); + + let current_uxt = uxt(Alice, ALICE_NONCE); + let current_xt = hex_string(¤t_uxt.encode()); + // This lives in the future. + let future_uxt = uxt(Alice, ALICE_NONCE + 1); + let future_xt = hex_string(&future_uxt.encode()); + + // By default the `validate_transaction` mock uses priority 1 for + // transactions. Bump the priority to ensure other transactions + // are immediately dropped. + api.set_priority(¤t_uxt, 10); + + let current_operation_id: String = tx_api + .call("transaction_unstable_broadcast", rpc_params![¤t_xt]) + .await + .unwrap(); + + // Announce block 1 to `transaction_unstable_broadcast`. + let block_1_header = api.push_block(1, vec![], true); + let event = + ChainEvent::Finalized { hash: block_1_header.hash(), tree_route: Arc::from(vec![]) }; + pool.inner_pool.maintain(event).await; + client_mock.trigger_import_stream(block_1_header).await; + + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::TransactionStatus { + transaction: current_xt.clone(), + status: TxStatusTypeTest::Ready, + } + ); + assert_eq!(1, pool.inner_pool.status().ready); + + // The future tx has priority 2, smaller than the current 10. + api.set_priority(&future_uxt, 2); + let future_operation_id: String = tx_api + .call("transaction_unstable_broadcast", rpc_params![&future_xt]) + .await + .unwrap(); + assert_ne!(current_operation_id, future_operation_id); + + let block_2_header = api.push_block(2, vec![], true); + let event = + ChainEvent::Finalized { hash: block_2_header.hash(), tree_route: Arc::from(vec![]) }; + pool.inner_pool.maintain(event).await; + client_mock.trigger_import_stream(block_2_header).await; + + // We must have at most 1 transaction in the pool, as per limits above. + assert_eq!(1, pool.inner_pool.status().ready); + + let event = get_next_event!(&mut pool_middleware); + assert_eq!( + event, + MiddlewarePoolEvent::PoolError { + transaction: future_xt.clone(), + err: "Transaction couldn't enter the pool because of the limit".into() + } + ); + + let block_3_header = api.push_block(3, vec![current_uxt], true); + let event = + ChainEvent::Finalized { hash: block_3_header.hash(), tree_route: Arc::from(vec![]) }; + pool.inner_pool.maintain(event).await; + client_mock.trigger_import_stream(block_3_header.clone()).await; + + // The first tx is in a finalzied block; the future tx must enter the pool. + let events = get_next_tx_events!(&mut pool_middleware, 3); + assert_eq!( + events.get(¤t_xt).unwrap(), + &vec![ + TxStatusTypeTest::InBlock((block_3_header.hash(), 0)), + TxStatusTypeTest::Finalized((block_3_header.hash(), 0)) + ] + ); + // The dropped transaction was resubmitted. + assert_eq!(events.get(&future_xt).unwrap(), &vec![TxStatusTypeTest::Ready]); +} diff --git a/substrate/client/transaction-pool/src/lib.rs b/substrate/client/transaction-pool/src/lib.rs index faa3f455a58..64b301e6bf3 100644 --- a/substrate/client/transaction-pool/src/lib.rs +++ b/substrate/client/transaction-pool/src/lib.rs @@ -164,8 +164,9 @@ where pool_api: Arc, best_block_hash: Block::Hash, finalized_hash: Block::Hash, + options: graph::Options, ) -> (Self, Pin + Send>>) { - let pool = Arc::new(graph::Pool::new(Default::default(), true.into(), pool_api.clone())); + let pool = Arc::new(graph::Pool::new(options, true.into(), pool_api.clone())); let (revalidation_queue, background_task) = revalidation::RevalidationQueue::new_background( pool_api.clone(), pool.clone(), diff --git a/substrate/client/transaction-pool/tests/pool.rs b/substrate/client/transaction-pool/tests/pool.rs index 6b1a197440c..461b9860d41 100644 --- a/substrate/client/transaction-pool/tests/pool.rs +++ b/substrate/client/transaction-pool/tests/pool.rs @@ -73,7 +73,7 @@ fn create_basic_pool_with_genesis( .map(|blocks| blocks[0].0.header.hash()) .expect("there is block 0. qed") }; - BasicPool::new_test(test_api, genesis_hash, genesis_hash) + BasicPool::new_test(test_api, genesis_hash, genesis_hash, Default::default()) } fn create_basic_pool(test_api: TestApi) -> BasicPool { @@ -994,6 +994,7 @@ fn import_notification_to_pool_maintain_works() { )), best_hash, finalized_hash, + Default::default(), ) .0, ); diff --git a/substrate/test-utils/runtime/transaction-pool/src/lib.rs b/substrate/test-utils/runtime/transaction-pool/src/lib.rs index 8c8345b06bd..5202e6e6515 100644 --- a/substrate/test-utils/runtime/transaction-pool/src/lib.rs +++ b/substrate/test-utils/runtime/transaction-pool/src/lib.rs @@ -81,6 +81,7 @@ pub struct ChainState { pub block_by_hash: HashMap, pub nonces: HashMap, pub invalid_hashes: HashSet, + pub priorities: HashMap, } /// Test Api for transaction pool. @@ -214,6 +215,22 @@ impl TestApi { self.chain.write().invalid_hashes.insert(Self::hash_and_length_inner(xts).0); } + /// Remove a transaction that was previously declared as invalid via `[Self::add_invalid]`. + /// + /// Next time transaction pool will try to validate this + /// extrinsic, api will succeed. + pub fn remove_invalid(&self, xts: &Extrinsic) { + self.chain.write().invalid_hashes.remove(&Self::hash_and_length_inner(xts).0); + } + + /// Set a transaction priority. + pub fn set_priority(&self, xts: &Extrinsic, priority: u64) { + self.chain + .write() + .priorities + .insert(Self::hash_and_length_inner(xts).0, priority); + } + /// Query validation requests received. pub fn validation_requests(&self) -> Vec { self.validation_requests.read().clone() @@ -300,8 +317,14 @@ impl ChainApi for TestApi { return ready(Ok(Err(TransactionValidityError::Invalid(InvalidTransaction::Custom(0))))) } - let mut validity = - ValidTransaction { priority: 1, requires, provides, longevity: 64, propagate: true }; + let priority = self.chain.read().priorities.get(&self.hash_and_length(&uxt).0).cloned(); + let mut validity = ValidTransaction { + priority: priority.unwrap_or(1), + requires, + provides, + longevity: 64, + propagate: true, + }; (self.valid_modifier.read())(&mut validity); -- GitLab From f4eedcebafa4d2addb8b71ba31ab1bc579ba3c4a Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 28 Feb 2024 13:13:27 +0100 Subject: [PATCH 042/188] [prdoc] Optional SemVer bumps and Docs (#3441) Changes: - Add an optional `bump` field to the crates in a prdoc. - Explain the cargo semver interpretation for <1 versions in the release doc. --------- Signed-off-by: Oliver Tale-Yazdi --- docs/RELEASE.md | 12 +++++++++--- prdoc/schema_user.json | 33 +++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/docs/RELEASE.md b/docs/RELEASE.md index 6d681d78f36..e73be2779a9 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -18,10 +18,16 @@ Rococo. To easily refer to a release, it shall be named by its date in the form ## Crate -We try to follow [SemVer 2.0.0](https://semver.org/) as best as possible for versioning our crates. SemVer requires a -piece of software to first declare a public API. The public API of the Polkadot SDK is hereby declared as the sum of all -crates' public APIs. +We try to follow [SemVer 2.0.0](https://semver.org/) as best as possible for versioning our crates. The definitions of +`major`, `minor` and `patch` version for Rust crates are slightly altered from their standard for pre `1.0.0` versions. +Quoting [rust-lang.org](https://doc.rust-lang.org/cargo/reference/semver.html): +>Initial development releases starting with “0.y.z” can treat changes in “y” as a major release, and “z” as a minor +release. “0.0.z” releases are always major changes. This is because Cargo uses the convention that only changes in the +left-most non-zero component are considered incompatible. + +SemVer requires a piece of software to first declare a public API. The public API of the Polkadot SDK +is hereby declared as the sum of all crates' public APIs. Inductively, the public API of our library crates is declared as all public items that are neither: - Inside a `__private` module diff --git a/prdoc/schema_user.json b/prdoc/schema_user.json index 82215d51866..1bd0b3b93ee 100644 --- a/prdoc/schema_user.json +++ b/prdoc/schema_user.json @@ -3,9 +3,8 @@ "$id": "https://raw.githubusercontent.com/paritytech/prdoc/master/prdoc_schema_user.json", "version": { "major": 1, - "minor": 0, - "patch": 0, - "timestamp": 20230817152351 + "minor": 1, + "patch": 0 }, "title": "Polkadot SDK PRDoc Schema", "description": "JSON Schema definition for the Polkadot SDK PR documentation", @@ -125,10 +124,16 @@ "name": { "type": "string" }, + "bump": { + "$ref": "#/$defs/semver_bump" + }, "note": { "type": "string" } - } + }, + "required": [ + "name" + ] }, "migration_db": { "type": "object", @@ -165,6 +170,26 @@ "description" ] }, + "semver_bump": { + "description": "The type of bump to apply to the crate version according to Cargo SemVer: https://doc.rust-lang.org/cargo/reference/semver.html. Please check docs/RELEASE.md for more information.", + "oneOf": [ + { + "const": "major", + "title": "Major", + "description": "A bump to the leftmost non-zero digit of the version number." + }, + { + "const": "minor", + "title": "Minor", + "description": "A bump to the second leftmost non-zero digit of the version number." + }, + { + "const": "patch", + "title": "Patch", + "description": "A bump to the third leftmost non-zero digit of the version number." + } + ] + }, "doc": { "type": "object", "description": "You have the the option to provide different description of your PR for different audiences.", -- GitLab From 14530269b7a76f50dc939bf57b1e3d38270b662b Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Wed, 28 Feb 2024 13:07:14 +0000 Subject: [PATCH 043/188] Add documentation around FRAME Offchain workers (#3463) - deprecation companion: https://github.com/substrate-developer-hub/substrate-docs/pull/2136 - inspired by https://substrate.stackexchange.com/questions/11058/how-can-i-create-ocw-that-wont-activates-every-block-but-will-activates-only-w/11060#11060 --------- Co-authored-by: Sergej Sakac <73715684+Szegoo@users.noreply.github.com> --- Cargo.lock | 2 + docs/sdk/Cargo.toml | 5 +- .../reference_docs/frame_offchain_workers.rs | 115 ++++++++++++++++++ docs/sdk/src/reference_docs/mod.rs | 4 + substrate/frame/support/src/traits/hooks.rs | 2 +- 5 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 docs/sdk/src/reference_docs/frame_offchain_workers.rs diff --git a/Cargo.lock b/Cargo.lock index 026786378d5..ef510986257 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13416,6 +13416,7 @@ dependencies = [ "pallet-collective", "pallet-default-config-example", "pallet-democracy", + "pallet-example-offchain-worker", "pallet-example-single-block-migrations", "pallet-examples", "pallet-multisig", @@ -13442,6 +13443,7 @@ dependencies = [ "sp-core", "sp-io", "sp-keyring", + "sp-offchain", "sp-runtime", "sp-version", "staging-chain-spec-builder", diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index b1b60a2d77d..735b3d7df61 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -23,6 +23,7 @@ frame = { path = "../../substrate/frame", features = [ ] } pallet-examples = { path = "../../substrate/frame/examples" } pallet-default-config-example = { path = "../../substrate/frame/examples/default-config" } +pallet-example-offchain-worker = { path = "../../substrate/frame/examples/offchain-worker" } # How we build docs in rust-docs simple-mermaid = "0.1.1" @@ -38,7 +39,7 @@ frame-support = { path = "../../substrate/frame/support", default-features = fal frame-executive = { path = "../../substrate/frame/executive", default-features = false } pallet-example-single-block-migrations = { path = "../../substrate/frame/examples/single-block-migrations" } -# Substrate +# Substrate Client sc-network = { path = "../../substrate/client/network" } sc-rpc-api = { path = "../../substrate/client/rpc-api" } sc-rpc = { path = "../../substrate/client/rpc" } @@ -50,6 +51,7 @@ sc-consensus-grandpa = { path = "../../substrate/client/consensus/grandpa" } sc-consensus-beefy = { path = "../../substrate/client/consensus/beefy" } sc-consensus-manual-seal = { path = "../../substrate/client/consensus/manual-seal" } sc-consensus-pow = { path = "../../substrate/client/consensus/pow" } + substrate-wasm-builder = { path = "../../substrate/utils/wasm-builder" } # Cumulus @@ -78,6 +80,7 @@ sp-api = { path = "../../substrate/primitives/api" } sp-core = { path = "../../substrate/primitives/core" } sp-keyring = { path = "../../substrate/primitives/keyring" } sp-runtime = { path = "../../substrate/primitives/runtime" } +sp-offchain = { path = "../../substrate/primitives/offchain" } sp-version = { path = "../../substrate/primitives/version" } # XCM diff --git a/docs/sdk/src/reference_docs/frame_offchain_workers.rs b/docs/sdk/src/reference_docs/frame_offchain_workers.rs new file mode 100644 index 00000000000..7999707e5ee --- /dev/null +++ b/docs/sdk/src/reference_docs/frame_offchain_workers.rs @@ -0,0 +1,115 @@ +//! # Offchain Workers +//! +//! This reference document explains how offchain workers work in Substrate and FRAME. The main +//! focus is upon FRAME's implementation of this functionality. Nonetheless, offchain workers are a +//! Substrate-provided feature and can be used with possible alternatives to [`frame`] as well. +//! +//! Offchain workers are a commonly misunderstood topic, therefore we explain them bottom-up, +//! starting at the fundamentals and then describing the developer interface. +//! +//! ## Context +//! +//! Recall from [`crate::reference_docs::wasm_meta_protocol`] that the node and the runtime +//! communicate with one another via host functions and runtime APIs. Many of these interactions +//! contribute to the actual state transition of the blockchain. For example [`sp_api::Core`] is the +//! main runtime API that is called to execute new blocks. +//! +//! Offchain workers are in principle not different in any way: It is a runtime API exposed by the +//! wasm blob ([`sp_offchain::OffchainWorkerApi`]), and the node software calls into it when it +//! deems fit. But, crucially, this API call is different in that: +//! +//! 1. It can have no impact on the state ie. it is _OFF (the) CHAIN_. If any state is altered +//! during the execution of this API call, it is discarded. +//! 2. It has access to an extended set of host functions that allow the wasm blob to do more. For +//! example, call into HTTP requests. +//! +//! > The main way through which an offchain worker can interact with the state is by submitting an +//! > extrinsic to the chain. This is the ONLY way to alter the state from an offchain worker. +//! > [`pallet_example_offchain_worker`] provides an example of this. +//! +//! +//! Given the "Off Chain" nature of this API, it is important to remember that calling this API is +//! entirely optional. Some nodes might call into it, some might not, and it would have no impact on +//! the execution of your blockchain because no state is altered no matter the execution of the +//! offchain worker API. +//! +//! Substrate's CLI allows some degree of configuration about this, allowing node operators to +//! specify when they want to run the offchain worker API. See +//! [`sc_cli::RunCmd::offchain_worker_params`]. +//! +//! ## Nondeterministic Execution +//! +//! Needless to say, given the above description, the code in your offchain worker API can be +//! nondeterministic, as it is not part of the blockchain's STF, so it can be executed at unknown +//! times, by unknown nodes, and has no impact on the state. This is why an HTTP +//! ([`sp_runtime::offchain::http`]) API is readily provided to the offchain worker APIs. Because +//! there is no need for determinism in this context. +//! +//! > A common mistake here is for novice developers to see this HTTP API, and imagine that +//! > `polkadot-sdk` somehow magically solved the determinism in blockchains, and now a blockchain +//! > can make HTTP calls and it will all work. This is absolutely NOT the case. An HTTP call made +//! > by the offchain worker is non-deterministic by design. Blockchains can't and always won't be +//! > able to perform non-deterministic operations such as making HTTP calls to a foreign server. +//! +//! ## FRAME's API +//! +//! [`frame`] provides a simple API through which pallets can define offchain worker functions. This +//! is part of [`frame::traits::Hooks`], which is implemented as a part of +//! [`frame::pallet_macros::hooks`]. +//! +//! ``` +//! +//! #[frame::pallet] +//! pub mod pallet { +//! use frame::prelude::*; +//! +//! #[pallet::config] +//! pub trait Config: frame_system::Config {} +//! +//! #[pallet::pallet] +//! pub struct Pallet(_); +//! +//! #[pallet::hooks] +//! impl Hooks> for Pallet { +//! fn offchain_worker(block_number: BlockNumberFor) { +//! // ... +//! } +//! } +//! } +//! ``` +//! +//! Additionally, [`sp_runtime::offchain`] provides a set of utilities that can be used to moderate +//! the execution of offchain workers. +//! +//! ## Think Twice: Why Use Substrate's Offchain Workers? +//! +//! Consider the fact that in principle, an offchain worker code written using the above API is no +//! different than an equivalent written with an _actual offchain interaction library_, such as +//! [Polkadot-JS](https://polkadot.js.org/docs/), or any of the other ones listed [here](https://github.com/substrate-developer-hub/awesome-substrate?tab=readme-ov-file#client-libraries). +//! +//! They can both read from the state, and have no means of updating the state, other than the route +//! of submitting an extrinsic to the chain. Therefore, it is worth thinking twice before embedding +//! a logic as a part of Substrate's offchain worker API. Does it have to be there? can it not be a +//! simple, actual offchain application that lives outside of the chain's WASM blob? +//! +//! Some of the reasons why you might want to do the opposite, and actually embed an offchain worker +//! API into the WASM blob are: +//! +//! * Accessing the state is easier within the `offchain_worker` function, as it is already a part +//! of the runtime, and [`frame::pallet_macros::storage`] provides all the tools needed to read +//! the state. Other client libraries might provide varying degrees of capability here. +//! * It will be updated in synchrony with the runtime. A Substrate's offchain application is part +//! of the same WASM blob, and is therefore guaranteed to be up to date. +//! +//! For example, imagine you have modified a storage item to have a new type. This will possibly +//! require a [`crate::reference_docs::frame_runtime_upgrades_and_migrations`], and any offchain +//! code, such as a Polkadot-JS application, will have to be updated to reflect this change. Whereas +//! the WASM offchain worker code is guaranteed to already be updated, or else the runtime code will +//! not even compile. +//! +//! +//! ## Further References +//! +//! - +//! - +//! - [Offchain worker example](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame/examples/offchain-worker) diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index b2c751420ce..0bd204e4b6a 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -99,3 +99,7 @@ pub mod frame_runtime_upgrades_and_migrations; /// light-node-first out of the box. // TODO: @jsdw @josepot https://github.com/paritytech/polkadot-sdk-docs/issues/68 pub mod light_nodes; + +/// Learn about the offchain workers, how they function, and how to use them, as provided by the +/// [`frame`] APIs. +pub mod frame_offchain_workers; diff --git a/substrate/frame/support/src/traits/hooks.rs b/substrate/frame/support/src/traits/hooks.rs index 72f047c3a73..c37fb0f54bc 100644 --- a/substrate/frame/support/src/traits/hooks.rs +++ b/substrate/frame/support/src/traits/hooks.rs @@ -446,7 +446,7 @@ pub trait Hooks { } /// Implementing this function on a pallet allows you to perform long-running tasks that are - /// dispatched as separate threads, and entirely independent of the main wasm runtime. + /// dispatched as separate threads, and entirely independent of the main blockchain execution. /// /// This function can freely read from the state, but any change it makes to the state is /// meaningless. Writes can be pushed back to the chain by submitting extrinsics from the -- GitLab From 426136671a42ff759127b4a7a71eac6335744675 Mon Sep 17 00:00:00 2001 From: maksimryndin Date: Wed, 28 Feb 2024 17:29:27 +0100 Subject: [PATCH 044/188] PVF: re-preparing artifact on failed runtime construction (#3187) resolve https://github.com/paritytech/polkadot-sdk/issues/3139 - [x] use a distinguishable error for `execute_artifact` - [x] remove artifact in case of a `RuntimeConstruction` error during the execution - [x] augment the `validate_candidate_with_retry` of `ValidationBackend` with the case of retriable `RuntimeConstruction` error during the execution - [x] update the book (https://paritytech.github.io/polkadot-sdk/book/node/utility/pvf-host-and-workers.html#retrying-execution-requests) - [x] add a test - [x] run zombienet tests --------- Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> --- .../node/core/candidate-validation/src/lib.rs | 53 +++++++----- polkadot/node/core/pvf/common/src/error.rs | 1 + polkadot/node/core/pvf/common/src/execute.rs | 15 ++++ .../core/pvf/common/src/executor_interface.rs | 4 +- .../node/core/pvf/execute-worker/src/lib.rs | 10 ++- polkadot/node/core/pvf/src/artifacts.rs | 8 ++ polkadot/node/core/pvf/src/error.rs | 4 + polkadot/node/core/pvf/src/execute/mod.rs | 2 +- polkadot/node/core/pvf/src/execute/queue.rs | 68 ++++++++++++--- .../core/pvf/src/execute/worker_interface.rs | 8 ++ polkadot/node/core/pvf/src/host.rs | 53 +++++++++++- polkadot/node/core/pvf/tests/it/main.rs | 83 +++++++++++++++++-- polkadot/primitives/src/v6/executor_params.rs | 10 +-- .../src/node/utility/pvf-host-and-workers.md | 8 ++ prdoc/pr_3187.prdoc | 16 ++++ 15 files changed, 294 insertions(+), 49 deletions(-) create mode 100644 prdoc/pr_3187.prdoc diff --git a/polkadot/node/core/candidate-validation/src/lib.rs b/polkadot/node/core/candidate-validation/src/lib.rs index bf6e09fd1b6..8237137fdca 100644 --- a/polkadot/node/core/candidate-validation/src/lib.rs +++ b/polkadot/node/core/candidate-validation/src/lib.rs @@ -695,6 +695,8 @@ async fn validate_candidate_exhaustive( ))), Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::JobError(err))) => Ok(ValidationResult::Invalid(InvalidCandidate::ExecutionError(err))), + Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::RuntimeConstruction(err))) => + Ok(ValidationResult::Invalid(InvalidCandidate::ExecutionError(err))), Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::AmbiguousJobDeath(err))) => Ok(ValidationResult::Invalid(InvalidCandidate::ExecutionError(format!( @@ -780,40 +782,50 @@ trait ValidationBackend { return validation_result } + macro_rules! break_if_no_retries_left { + ($counter:ident) => { + if $counter > 0 { + $counter -= 1; + } else { + break + } + }; + } + // Allow limited retries for each kind of error. let mut num_death_retries_left = 1; let mut num_job_error_retries_left = 1; let mut num_internal_retries_left = 1; + let mut num_runtime_construction_retries_left = 1; loop { // Stop retrying if we exceeded the timeout. if total_time_start.elapsed() + retry_delay > exec_timeout { break } - + let mut retry_immediately = false; match validation_result { Err(ValidationError::PossiblyInvalid( PossiblyInvalidError::AmbiguousWorkerDeath | PossiblyInvalidError::AmbiguousJobDeath(_), - )) => - if num_death_retries_left > 0 { - num_death_retries_left -= 1; - } else { - break - }, + )) => break_if_no_retries_left!(num_death_retries_left), Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::JobError(_))) => - if num_job_error_retries_left > 0 { - num_job_error_retries_left -= 1; - } else { - break - }, + break_if_no_retries_left!(num_job_error_retries_left), Err(ValidationError::Internal(_)) => - if num_internal_retries_left > 0 { - num_internal_retries_left -= 1; - } else { - break - }, + break_if_no_retries_left!(num_internal_retries_left), + + Err(ValidationError::PossiblyInvalid( + PossiblyInvalidError::RuntimeConstruction(_), + )) => { + break_if_no_retries_left!(num_runtime_construction_retries_left); + self.precheck_pvf(pvf.clone()).await?; + // In this case the error is deterministic + // And a retry forces the ValidationBackend + // to re-prepare the artifact so + // there is no need to wait before the retry + retry_immediately = true; + }, Ok(_) | Err(ValidationError::Invalid(_) | ValidationError::Preparation(_)) => break, } @@ -821,8 +833,11 @@ trait ValidationBackend { // If we got a possibly transient error, retry once after a brief delay, on the // assumption that the conditions that caused this error may have resolved on their own. { - // Wait a brief delay before retrying. - futures_timer::Delay::new(retry_delay).await; + // In case of many transient errors it is necessary to wait a little bit + // for the error to be probably resolved + if !retry_immediately { + futures_timer::Delay::new(retry_delay).await; + } let new_timeout = exec_timeout.saturating_sub(total_time_start.elapsed()); diff --git a/polkadot/node/core/pvf/common/src/error.rs b/polkadot/node/core/pvf/common/src/error.rs index f8faefc24e6..cf274044456 100644 --- a/polkadot/node/core/pvf/common/src/error.rs +++ b/polkadot/node/core/pvf/common/src/error.rs @@ -16,6 +16,7 @@ use crate::prepare::{PrepareSuccess, PrepareWorkerSuccess}; use parity_scale_codec::{Decode, Encode}; +pub use sc_executor_common::error::Error as ExecuteError; /// Result of PVF preparation from a worker, with checksum of the compiled PVF and stats of the /// preparation if successful. diff --git a/polkadot/node/core/pvf/common/src/execute.rs b/polkadot/node/core/pvf/common/src/execute.rs index 6b3becf524d..18c97b03cbc 100644 --- a/polkadot/node/core/pvf/common/src/execute.rs +++ b/polkadot/node/core/pvf/common/src/execute.rs @@ -40,6 +40,9 @@ pub enum WorkerResponse { }, /// The candidate is invalid. InvalidCandidate(String), + /// Instantiation of the WASM module instance failed during an execution. + /// Possibly related to local issues or dirty node update. May be retried with re-preparation. + RuntimeConstruction(String), /// The job timed out. JobTimedOut, /// The job process has died. We must kill the worker just in case. @@ -68,6 +71,9 @@ pub enum JobResponse { /// The result of parachain validation. result_descriptor: ValidationResult, }, + /// A possibly transient runtime instantiation error happened during the execution; may be + /// retried with re-preparation + RuntimeConstruction(String), /// The candidate is invalid. InvalidCandidate(String), } @@ -81,6 +87,15 @@ impl JobResponse { Self::InvalidCandidate(format!("{}: {}", ctx, msg)) } } + + /// Creates a may retry response from a context `ctx` and a message `msg` (which can be empty). + pub fn runtime_construction(ctx: &'static str, msg: &str) -> Self { + if msg.is_empty() { + Self::RuntimeConstruction(ctx.to_string()) + } else { + Self::RuntimeConstruction(format!("{}: {}", ctx, msg)) + } + } } /// An unexpected error occurred in the execution job process. Because this comes from the job, diff --git a/polkadot/node/core/pvf/common/src/executor_interface.rs b/polkadot/node/core/pvf/common/src/executor_interface.rs index 4cd2f5c85ee..b69a87890f6 100644 --- a/polkadot/node/core/pvf/common/src/executor_interface.rs +++ b/polkadot/node/core/pvf/common/src/executor_interface.rs @@ -16,6 +16,7 @@ //! Interface to the Substrate Executor +use crate::error::ExecuteError; use polkadot_primitives::{ executor_params::{DEFAULT_LOGICAL_STACK_MAX, DEFAULT_NATIVE_STACK_MAX}, ExecutorParam, ExecutorParams, @@ -109,7 +110,7 @@ pub unsafe fn execute_artifact( compiled_artifact_blob: &[u8], executor_params: &ExecutorParams, params: &[u8], -) -> Result, String> { +) -> Result, ExecuteError> { let mut extensions = sp_externalities::Extensions::new(); extensions.register(sp_core::traits::ReadRuntimeVersionExt::new(ReadRuntimeVersion)); @@ -123,7 +124,6 @@ pub unsafe fn execute_artifact( Ok(Ok(ok)) => Ok(ok), Ok(Err(err)) | Err(err) => Err(err), } - .map_err(|err| format!("execute error: {:?}", err)) } /// Constructs the runtime for the given PVF, given the artifact bytes. diff --git a/polkadot/node/core/pvf/execute-worker/src/lib.rs b/polkadot/node/core/pvf/execute-worker/src/lib.rs index 0cfa5a78694..bd7e76010a6 100644 --- a/polkadot/node/core/pvf/execute-worker/src/lib.rs +++ b/polkadot/node/core/pvf/execute-worker/src/lib.rs @@ -16,7 +16,9 @@ //! Contains the logic for executing PVFs. Used by the polkadot-execute-worker binary. -pub use polkadot_node_core_pvf_common::executor_interface::execute_artifact; +pub use polkadot_node_core_pvf_common::{ + error::ExecuteError, executor_interface::execute_artifact, +}; // NOTE: Initializing logging in e.g. tests will not have an effect in the workers, as they are // separate spawned processes. Run with e.g. `RUST_LOG=parachain::pvf-execute-worker=trace`. @@ -237,7 +239,9 @@ fn validate_using_artifact( // [`executor_interface::prepare`]. execute_artifact(compiled_artifact_blob, executor_params, params) } { - Err(err) => return JobResponse::format_invalid("execute", &err), + Err(ExecuteError::RuntimeConstruction(wasmerr)) => + return JobResponse::runtime_construction("execute", &wasmerr.to_string()), + Err(err) => return JobResponse::format_invalid("execute", &err.to_string()), Ok(d) => d, }; @@ -550,6 +554,8 @@ fn handle_parent_process( Ok(WorkerResponse::Ok { result_descriptor, duration: cpu_tv }) }, Ok(JobResponse::InvalidCandidate(err)) => Ok(WorkerResponse::InvalidCandidate(err)), + Ok(JobResponse::RuntimeConstruction(err)) => + Ok(WorkerResponse::RuntimeConstruction(err)), Err(job_error) => { gum::warn!( target: LOG_TARGET, diff --git a/polkadot/node/core/pvf/src/artifacts.rs b/polkadot/node/core/pvf/src/artifacts.rs index 78dfe71adad..6288755526d 100644 --- a/polkadot/node/core/pvf/src/artifacts.rs +++ b/polkadot/node/core/pvf/src/artifacts.rs @@ -238,6 +238,14 @@ impl Artifacts { .is_none()); } + /// Remove artifact by its id. + pub fn remove(&mut self, artifact_id: ArtifactId) -> Option<(ArtifactId, PathBuf)> { + self.inner.remove(&artifact_id).and_then(|state| match state { + ArtifactState::Prepared { path, .. } => Some((artifact_id, path)), + _ => None, + }) + } + /// Remove artifacts older than the given TTL and return id and path of the removed ones. pub fn prune(&mut self, artifact_ttl: Duration) -> Vec<(ArtifactId, PathBuf)> { let now = SystemTime::now(); diff --git a/polkadot/node/core/pvf/src/error.rs b/polkadot/node/core/pvf/src/error.rs index 80d41d5c64b..8dc96305ead 100644 --- a/polkadot/node/core/pvf/src/error.rs +++ b/polkadot/node/core/pvf/src/error.rs @@ -86,6 +86,10 @@ pub enum PossiblyInvalidError { /// vote invalid. #[error("possibly invalid: job error: {0}")] JobError(String), + /// Instantiation of the WASM module instance failed during an execution. + /// Possibly related to local issues or dirty node update. May be retried with re-preparation. + #[error("possibly invalid: runtime construction: {0}")] + RuntimeConstruction(String), } impl From for ValidationError { diff --git a/polkadot/node/core/pvf/src/execute/mod.rs b/polkadot/node/core/pvf/src/execute/mod.rs index c6d9cf90fa2..365e98196ca 100644 --- a/polkadot/node/core/pvf/src/execute/mod.rs +++ b/polkadot/node/core/pvf/src/execute/mod.rs @@ -23,4 +23,4 @@ mod queue; mod worker_interface; -pub use queue::{start, PendingExecutionRequest, ToQueue}; +pub use queue::{start, FromQueue, PendingExecutionRequest, ToQueue}; diff --git a/polkadot/node/core/pvf/src/execute/queue.rs b/polkadot/node/core/pvf/src/execute/queue.rs index aa91d11781f..bdc3c7327b0 100644 --- a/polkadot/node/core/pvf/src/execute/queue.rs +++ b/polkadot/node/core/pvf/src/execute/queue.rs @@ -25,7 +25,7 @@ use crate::{ InvalidCandidate, PossiblyInvalidError, ValidationError, LOG_TARGET, }; use futures::{ - channel::mpsc, + channel::{mpsc, oneshot}, future::BoxFuture, stream::{FuturesUnordered, StreamExt as _}, Future, FutureExt, @@ -54,6 +54,12 @@ pub enum ToQueue { Enqueue { artifact: ArtifactPathId, pending_execution_request: PendingExecutionRequest }, } +/// A response from queue. +#[derive(Debug)] +pub enum FromQueue { + RemoveArtifact { artifact: ArtifactId, reply_to: oneshot::Sender<()> }, +} + /// An execution request that should execute the PVF (known in the context) and send the results /// to the given result sender. #[derive(Debug)] @@ -137,6 +143,8 @@ struct Queue { /// The receiver that receives messages to the pool. to_queue_rx: mpsc::Receiver, + /// The sender to send messages back to validation host. + from_queue_tx: mpsc::UnboundedSender, // Some variables related to the current session. program_path: PathBuf, @@ -161,6 +169,7 @@ impl Queue { node_version: Option, security_status: SecurityStatus, to_queue_rx: mpsc::Receiver, + from_queue_tx: mpsc::UnboundedSender, ) -> Self { Self { metrics, @@ -170,6 +179,7 @@ impl Queue { node_version, security_status, to_queue_rx, + from_queue_tx, queue: VecDeque::new(), mux: Mux::new(), workers: Workers { @@ -301,7 +311,7 @@ async fn handle_mux(queue: &mut Queue, event: QueueEvent) { handle_worker_spawned(queue, idle, handle, job); }, QueueEvent::StartWork(worker, outcome, artifact_id, result_tx) => { - handle_job_finish(queue, worker, outcome, artifact_id, result_tx); + handle_job_finish(queue, worker, outcome, artifact_id, result_tx).await; }, } } @@ -327,42 +337,69 @@ fn handle_worker_spawned( /// If there are pending jobs in the queue, schedules the next of them onto the just freed up /// worker. Otherwise, puts back into the available workers list. -fn handle_job_finish( +async fn handle_job_finish( queue: &mut Queue, worker: Worker, outcome: Outcome, artifact_id: ArtifactId, result_tx: ResultSender, ) { - let (idle_worker, result, duration) = match outcome { + let (idle_worker, result, duration, sync_channel) = match outcome { Outcome::Ok { result_descriptor, duration, idle_worker } => { // TODO: propagate the soft timeout - (Some(idle_worker), Ok(result_descriptor), Some(duration)) + (Some(idle_worker), Ok(result_descriptor), Some(duration), None) }, Outcome::InvalidCandidate { err, idle_worker } => ( Some(idle_worker), Err(ValidationError::Invalid(InvalidCandidate::WorkerReportedInvalid(err))), None, + None, ), - Outcome::InternalError { err } => (None, Err(ValidationError::Internal(err)), None), + Outcome::RuntimeConstruction { err, idle_worker } => { + // The task for artifact removal is executed concurrently with + // the message to the host on the execution result. + let (result_tx, result_rx) = oneshot::channel(); + queue + .from_queue_tx + .unbounded_send(FromQueue::RemoveArtifact { + artifact: artifact_id.clone(), + reply_to: result_tx, + }) + .expect("from execute queue receiver is listened by the host; qed"); + ( + Some(idle_worker), + Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::RuntimeConstruction( + err, + ))), + None, + Some(result_rx), + ) + }, + Outcome::InternalError { err } => (None, Err(ValidationError::Internal(err)), None, None), // Either the worker or the job timed out. Kill the worker in either case. Treated as // definitely-invalid, because if we timed out, there's no time left for a retry. Outcome::HardTimeout => - (None, Err(ValidationError::Invalid(InvalidCandidate::HardTimeout)), None), + (None, Err(ValidationError::Invalid(InvalidCandidate::HardTimeout)), None, None), // "Maybe invalid" errors (will retry). Outcome::WorkerIntfErr => ( None, Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::AmbiguousWorkerDeath)), None, + None, ), Outcome::JobDied { err } => ( None, Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::AmbiguousJobDeath(err))), None, + None, + ), + Outcome::JobError { err } => ( + None, + Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::JobError(err))), + None, + None, ), - Outcome::JobError { err } => - (None, Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::JobError(err))), None), }; queue.metrics.execute_finished(); @@ -386,6 +423,12 @@ fn handle_job_finish( ); } + if let Some(sync_channel) = sync_channel { + // err means the sender is dropped (the artifact is already removed from the cache) + // so that's legitimate to ignore the result + let _ = sync_channel.await; + } + // First we send the result. It may fail due to the other end of the channel being dropped, // that's legitimate and we don't treat that as an error. let _ = result_tx.send(result); @@ -521,8 +564,10 @@ pub fn start( spawn_timeout: Duration, node_version: Option, security_status: SecurityStatus, -) -> (mpsc::Sender, impl Future) { +) -> (mpsc::Sender, mpsc::UnboundedReceiver, impl Future) { let (to_queue_tx, to_queue_rx) = mpsc::channel(20); + let (from_queue_tx, from_queue_rx) = mpsc::unbounded(); + let run = Queue::new( metrics, program_path, @@ -532,7 +577,8 @@ pub fn start( node_version, security_status, to_queue_rx, + from_queue_tx, ) .run(); - (to_queue_tx, run) + (to_queue_tx, from_queue_rx, run) } diff --git a/polkadot/node/core/pvf/src/execute/worker_interface.rs b/polkadot/node/core/pvf/src/execute/worker_interface.rs index 9f7738f00e6..db81da118d7 100644 --- a/polkadot/node/core/pvf/src/execute/worker_interface.rs +++ b/polkadot/node/core/pvf/src/execute/worker_interface.rs @@ -87,6 +87,10 @@ pub enum Outcome { /// a trap. Errors related to the preparation process are not expected to be encountered by the /// execution workers. InvalidCandidate { err: String, idle_worker: IdleWorker }, + /// The error is probably transient. It may be for example + /// because the artifact was prepared with a Wasmtime version different from the version + /// in the current execution environment. + RuntimeConstruction { err: String, idle_worker: IdleWorker }, /// The execution time exceeded the hard limit. The worker is terminated. HardTimeout, /// An I/O error happened during communication with the worker. This may mean that the worker @@ -193,6 +197,10 @@ pub async fn start_work( err, idle_worker: IdleWorker { stream, pid, worker_dir }, }, + WorkerResponse::RuntimeConstruction(err) => Outcome::RuntimeConstruction { + err, + idle_worker: IdleWorker { stream, pid, worker_dir }, + }, WorkerResponse::JobTimedOut => Outcome::HardTimeout, WorkerResponse::JobDied { err, job_pid: _ } => Outcome::JobDied { err }, WorkerResponse::JobError(err) => Outcome::JobError { err }, diff --git a/polkadot/node/core/pvf/src/host.rs b/polkadot/node/core/pvf/src/host.rs index ae9fdc7d2de..8ec46f4b08f 100644 --- a/polkadot/node/core/pvf/src/host.rs +++ b/polkadot/node/core/pvf/src/host.rs @@ -274,7 +274,7 @@ pub async fn start( from_prepare_pool, ); - let (to_execute_queue_tx, run_execute_queue) = execute::start( + let (to_execute_queue_tx, from_execute_queue_rx, run_execute_queue) = execute::start( metrics, config.execute_worker_program_path.to_owned(), config.cache_path.clone(), @@ -296,6 +296,7 @@ pub async fn start( to_prepare_queue_tx, from_prepare_queue_rx, to_execute_queue_tx, + from_execute_queue_rx, to_sweeper_tx, awaiting_prepare: AwaitingPrepare::default(), }) @@ -342,6 +343,8 @@ struct Inner { from_prepare_queue_rx: mpsc::UnboundedReceiver, to_execute_queue_tx: mpsc::Sender, + from_execute_queue_rx: mpsc::UnboundedReceiver, + to_sweeper_tx: mpsc::Sender, awaiting_prepare: AwaitingPrepare, @@ -358,6 +361,7 @@ async fn run( to_host_rx, from_prepare_queue_rx, mut to_prepare_queue_tx, + from_execute_queue_rx, mut to_execute_queue_tx, mut to_sweeper_tx, mut awaiting_prepare, @@ -384,10 +388,21 @@ async fn run( let mut to_host_rx = to_host_rx.fuse(); let mut from_prepare_queue_rx = from_prepare_queue_rx.fuse(); + let mut from_execute_queue_rx = from_execute_queue_rx.fuse(); loop { // biased to make it behave deterministically for tests. futures::select_biased! { + from_execute_queue_rx = from_execute_queue_rx.next() => { + let from_queue = break_if_fatal!(from_execute_queue_rx.ok_or(Fatal)); + let execute::FromQueue::RemoveArtifact { artifact, reply_to } = from_queue; + break_if_fatal!(handle_artifact_removal( + &mut to_sweeper_tx, + &mut artifacts, + artifact, + reply_to, + ).await); + }, () = cleanup_pulse.select_next_some() => { // `select_next_some` because we don't expect this to fail, but if it does, we // still don't fail. The trade-off is that the compiled cache will start growing @@ -861,6 +876,37 @@ async fn handle_cleanup_pulse( Ok(()) } +async fn handle_artifact_removal( + sweeper_tx: &mut mpsc::Sender, + artifacts: &mut Artifacts, + artifact_id: ArtifactId, + reply_to: oneshot::Sender<()>, +) -> Result<(), Fatal> { + let (artifact_id, path) = if let Some(artifact) = artifacts.remove(artifact_id) { + artifact + } else { + // if we haven't found the artifact by its id, + // it has been probably removed + // anyway with the randomness of the artifact name + // it is safe to ignore + return Ok(()); + }; + reply_to + .send(()) + .expect("the execute queue waits for the artifact remove confirmation; qed"); + // Thanks to the randomness of the artifact name (see + // `artifacts::generate_artifact_path`) there is no issue with any name conflict on + // future repreparation. + // So we can confirm the artifact removal already + gum::debug!( + target: LOG_TARGET, + validation_code_hash = ?artifact_id.code_hash, + "PVF pruning: pruning artifact by request from the execute queue", + ); + sweeper_tx.send(path).await.map_err(|_| Fatal)?; + Ok(()) +} + /// A simple task which sole purpose is to delete files thrown at it. async fn sweeper_task(mut sweeper_rx: mpsc::Receiver) { loop { @@ -968,6 +1014,8 @@ pub(crate) mod tests { to_prepare_queue_rx: mpsc::Receiver, from_prepare_queue_tx: mpsc::UnboundedSender, to_execute_queue_rx: mpsc::Receiver, + #[allow(unused)] + from_execute_queue_tx: mpsc::UnboundedSender, to_sweeper_rx: mpsc::Receiver, run: BoxFuture<'static, ()>, @@ -979,6 +1027,7 @@ pub(crate) mod tests { let (to_prepare_queue_tx, to_prepare_queue_rx) = mpsc::channel(10); let (from_prepare_queue_tx, from_prepare_queue_rx) = mpsc::unbounded(); let (to_execute_queue_tx, to_execute_queue_rx) = mpsc::channel(10); + let (from_execute_queue_tx, from_execute_queue_rx) = mpsc::unbounded(); let (to_sweeper_tx, to_sweeper_rx) = mpsc::channel(10); let run = run(Inner { @@ -989,6 +1038,7 @@ pub(crate) mod tests { to_prepare_queue_tx, from_prepare_queue_rx, to_execute_queue_tx, + from_execute_queue_rx, to_sweeper_tx, awaiting_prepare: AwaitingPrepare::default(), }) @@ -999,6 +1049,7 @@ pub(crate) mod tests { to_prepare_queue_rx, from_prepare_queue_tx, to_execute_queue_rx, + from_execute_queue_tx, to_sweeper_rx, run, } diff --git a/polkadot/node/core/pvf/tests/it/main.rs b/polkadot/node/core/pvf/tests/it/main.rs index bcc10749e74..cdfbcd8e578 100644 --- a/polkadot/node/core/pvf/tests/it/main.rs +++ b/polkadot/node/core/pvf/tests/it/main.rs @@ -21,13 +21,14 @@ use parity_scale_codec::Encode as _; #[cfg(all(feature = "ci-only-tests", target_os = "linux"))] use polkadot_node_core_pvf::SecurityStatus; use polkadot_node_core_pvf::{ - start, testing::build_workers_and_get_paths, Config, InvalidCandidate, Metrics, PrepareError, - PrepareJobKind, PvfPrepData, ValidationError, ValidationHost, JOB_TIMEOUT_WALL_CLOCK_FACTOR, + start, testing::build_workers_and_get_paths, Config, InvalidCandidate, Metrics, + PossiblyInvalidError, PrepareError, PrepareJobKind, PvfPrepData, ValidationError, + ValidationHost, JOB_TIMEOUT_WALL_CLOCK_FACTOR, }; use polkadot_parachain_primitives::primitives::{BlockData, ValidationParams, ValidationResult}; use polkadot_primitives::{ExecutorParam, ExecutorParams}; -use std::time::Duration; +use std::{io::Write, time::Duration}; use tokio::sync::Mutex; mod adder; @@ -352,10 +353,80 @@ async fn deleting_prepared_artifact_does_not_dispute() { ) .await; - match result { - Err(ValidationError::Invalid(InvalidCandidate::HardTimeout)) => {}, - r => panic!("{:?}", r), + assert_matches!(result, Err(ValidationError::Invalid(InvalidCandidate::HardTimeout))); +} + +// Test that corruption of a prepared artifact does not lead to a dispute when we try to execute it. +#[tokio::test] +async fn corrupted_prepared_artifact_does_not_dispute() { + let host = TestHost::new().await; + let cache_dir = host.cache_dir.path(); + + let _stats = host.precheck_pvf(halt::wasm_binary_unwrap(), Default::default()).await.unwrap(); + + // Manually corrupting the prepared artifact from disk. The in-memory artifacts table won't + // change. + let artifact_path = { + // Get the artifact path (asserting it exists). + let mut cache_dir: Vec<_> = std::fs::read_dir(cache_dir).unwrap().collect(); + // Should contain the artifact and the worker dir. + assert_eq!(cache_dir.len(), 2); + let mut artifact_path = cache_dir.pop().unwrap().unwrap(); + if artifact_path.path().is_dir() { + artifact_path = cache_dir.pop().unwrap().unwrap(); + } + + // Corrupt the artifact. + let mut f = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(artifact_path.path()) + .unwrap(); + f.write_all(b"corrupted wasm").unwrap(); + f.flush().unwrap(); + artifact_path + }; + + assert!(artifact_path.path().exists()); + + // Try to validate, artifact should get removed because of the corruption. + let result = host + .validate_candidate( + halt::wasm_binary_unwrap(), + ValidationParams { + block_data: BlockData(Vec::new()), + parent_head: Default::default(), + relay_parent_number: 1, + relay_parent_storage_root: Default::default(), + }, + Default::default(), + ) + .await; + + assert_matches!( + result, + Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::RuntimeConstruction(_))) + ); + + // because of RuntimeConstruction we may retry + host.precheck_pvf(halt::wasm_binary_unwrap(), Default::default()).await.unwrap(); + + // The actual artifact removal is done concurrently + // with sending of the result of the execution + // it is not a problem for further re-preparation as + // artifact filenames are random + for _ in 1..5 { + if !artifact_path.path().exists() { + break; + } + tokio::time::sleep(Duration::from_secs(1)).await; } + + assert!( + !artifact_path.path().exists(), + "the corrupted artifact ({}) should be deleted by the host", + artifact_path.path().display() + ); } #[tokio::test] diff --git a/polkadot/primitives/src/v6/executor_params.rs b/polkadot/primitives/src/v6/executor_params.rs index 112a529f62b..1e19f3b23fe 100644 --- a/polkadot/primitives/src/v6/executor_params.rs +++ b/polkadot/primitives/src/v6/executor_params.rs @@ -159,7 +159,9 @@ impl sp_std::fmt::LowerHex for ExecutorParamsHash { // into individual fields of the structure. Thus, complex migrations shall be avoided when adding // new entries and removing old ones. At the moment, there's no mandatory parameters defined. If // they show up, they must be clearly documented as mandatory ones. -#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, TypeInfo, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, Encode, Decode, PartialEq, Eq, TypeInfo, Serialize, Deserialize, +)] pub struct ExecutorParams(Vec); impl ExecutorParams { @@ -334,9 +336,3 @@ impl From<&[ExecutorParam]> for ExecutorParams { ExecutorParams(arr.to_vec()) } } - -impl Default for ExecutorParams { - fn default() -> Self { - ExecutorParams(vec![]) - } -} diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/pvf-host-and-workers.md b/polkadot/roadmap/implementers-guide/src/node/utility/pvf-host-and-workers.md index e0984bd58d1..39a317a07c8 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/pvf-host-and-workers.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/pvf-host-and-workers.md @@ -125,6 +125,14 @@ execution request: reason, which may or may not be independent of the candidate or PVF. 5. **Internal errors:** See "Internal Errors" section. In this case, after the retry we abstain from voting. +6. **RuntimeConstruction** error. The precheck handles a general case of a wrong + artifact but doesn't guarantee its consistency between the preparation and + the execution. If something happened with the artifact between + the preparation of the artifact and its execution (e.g. the artifact was + corrupted on disk or a dirty node upgrade happened when the prepare worker + has a wasmtime version different from the execute worker's wasmtime version). + We treat such an error as possibly transient due to local issues and retry + one time. ### Preparation timeouts diff --git a/prdoc/pr_3187.prdoc b/prdoc/pr_3187.prdoc new file mode 100644 index 00000000000..bda41142d86 --- /dev/null +++ b/prdoc/pr_3187.prdoc @@ -0,0 +1,16 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Retrying an execution on failed runtime construction + +doc: + - audience: Node Dev + description: | + If a runtime construction error happened during the execution request, then the artifact is re-prepared + and the execution request is retried at most once. See also the related issue. + +crates: + - name: polkadot-node-core-candidate-validation + - name: polkadot-node-core-pvf + - name: polkadot-node-core-pvf-execute-worker + - name: polkadot-node-core-pvf-common -- GitLab From 576681b867a234b42aac282940455f9be71d108b Mon Sep 17 00:00:00 2001 From: Clara van Staden Date: Wed, 28 Feb 2024 21:42:35 +0200 Subject: [PATCH 045/188] Snowbridge - Extract Ethereum Chain ID (#3501) While adding runtime tests to https://github.com/polkadot-fellows/runtimes/pull/130, I noticed the Ethereum chain ID was hardcoded. For Kusama + Polkadot, the Ethereum chain ID should 1 (Mainnet), whereas on Rococo it is 11155111 (Sepolia). This PR also updates the Snowbridge crates versions to the current versions on crates.io. --------- Co-authored-by: claravanstaden --- Cargo.lock | 28 +++++++++---------- .../pallets/ethereum-client/Cargo.toml | 2 +- .../pallets/inbound-queue/Cargo.toml | 2 +- .../pallets/inbound-queue/fixtures/Cargo.toml | 2 +- .../pallets/outbound-queue/Cargo.toml | 2 +- .../outbound-queue/merkle-tree/Cargo.toml | 2 +- .../outbound-queue/runtime-api/Cargo.toml | 2 +- bridges/snowbridge/pallets/system/Cargo.toml | 2 +- .../pallets/system/runtime-api/Cargo.toml | 2 +- .../snowbridge/primitives/beacon/Cargo.toml | 2 +- bridges/snowbridge/primitives/core/Cargo.toml | 2 +- .../snowbridge/primitives/ethereum/Cargo.toml | 2 +- .../snowbridge/primitives/router/Cargo.toml | 2 +- .../runtime/runtime-common/Cargo.toml | 2 +- .../snowbridge/runtime/test-common/Cargo.toml | 2 +- .../snowbridge/runtime/test-common/src/lib.rs | 12 ++++++-- .../snowbridge/scripts/contribute-upstream.sh | 2 ++ .../bridge-hub-rococo/tests/snowbridge.rs | 5 ++++ 18 files changed, 45 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef510986257..197d05e2633 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17856,7 +17856,7 @@ dependencies = [ [[package]] name = "snowbridge-beacon-primitives" -version = "0.0.0" +version = "0.2.0" dependencies = [ "byte-slice-cast", "frame-support", @@ -17880,7 +17880,7 @@ dependencies = [ [[package]] name = "snowbridge-core" -version = "0.0.0" +version = "0.2.0" dependencies = [ "ethabi-decode", "frame-support", @@ -17903,7 +17903,7 @@ dependencies = [ [[package]] name = "snowbridge-ethereum" -version = "0.1.0" +version = "0.3.0" dependencies = [ "ethabi-decode", "ethbloom", @@ -17942,7 +17942,7 @@ dependencies = [ [[package]] name = "snowbridge-outbound-queue-merkle-tree" -version = "0.1.1" +version = "0.3.0" dependencies = [ "array-bytes 4.2.0", "env_logger 0.9.3", @@ -17957,7 +17957,7 @@ dependencies = [ [[package]] name = "snowbridge-outbound-queue-runtime-api" -version = "0.0.0" +version = "0.2.0" dependencies = [ "frame-support", "parity-scale-codec", @@ -17971,7 +17971,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-ethereum-client" -version = "0.0.0" +version = "0.2.0" dependencies = [ "bp-runtime", "byte-slice-cast", @@ -18017,7 +18017,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-inbound-queue" -version = "0.0.0" +version = "0.2.0" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -18050,7 +18050,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-inbound-queue-fixtures" -version = "0.9.0" +version = "0.10.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -18064,7 +18064,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-outbound-queue" -version = "0.0.0" +version = "0.2.0" dependencies = [ "bridge-hub-common", "ethabi-decode", @@ -18089,7 +18089,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-system" -version = "0.0.0" +version = "0.2.0" dependencies = [ "ethabi-decode", "frame-benchmarking", @@ -18117,7 +18117,7 @@ dependencies = [ [[package]] name = "snowbridge-router-primitives" -version = "0.0.0" +version = "0.9.0" dependencies = [ "ethabi-decode", "frame-support", @@ -18140,7 +18140,7 @@ dependencies = [ [[package]] name = "snowbridge-runtime-common" -version = "0.0.0" +version = "0.2.0" dependencies = [ "frame-support", "frame-system", @@ -18156,7 +18156,7 @@ dependencies = [ [[package]] name = "snowbridge-runtime-test-common" -version = "0.0.0" +version = "0.2.0" dependencies = [ "assets-common", "bridge-hub-test-utils", @@ -18233,7 +18233,7 @@ dependencies = [ [[package]] name = "snowbridge-system-runtime-api" -version = "0.0.0" +version = "0.2.0" dependencies = [ "parity-scale-codec", "snowbridge-core", diff --git a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml index 99b42905311..c8999633c97 100644 --- a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml +++ b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-pallet-ethereum-client" description = "Snowbridge Ethereum Client Pallet" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/pallets/inbound-queue/Cargo.toml b/bridges/snowbridge/pallets/inbound-queue/Cargo.toml index c26ef90a22d..b850496cd4e 100644 --- a/bridges/snowbridge/pallets/inbound-queue/Cargo.toml +++ b/bridges/snowbridge/pallets/inbound-queue/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-pallet-inbound-queue" description = "Snowbridge Inbound Queue Pallet" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/pallets/inbound-queue/fixtures/Cargo.toml b/bridges/snowbridge/pallets/inbound-queue/fixtures/Cargo.toml index 61f1421e056..64605a42f0d 100644 --- a/bridges/snowbridge/pallets/inbound-queue/fixtures/Cargo.toml +++ b/bridges/snowbridge/pallets/inbound-queue/fixtures/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-pallet-inbound-queue-fixtures" description = "Snowbridge Inbound Queue Test Fixtures" -version = "0.9.0" +version = "0.10.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/pallets/outbound-queue/Cargo.toml b/bridges/snowbridge/pallets/outbound-queue/Cargo.toml index 40e57db4bbd..f16a28cb1e4 100644 --- a/bridges/snowbridge/pallets/outbound-queue/Cargo.toml +++ b/bridges/snowbridge/pallets/outbound-queue/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-pallet-outbound-queue" description = "Snowbridge Outbound Queue Pallet" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/pallets/outbound-queue/merkle-tree/Cargo.toml b/bridges/snowbridge/pallets/outbound-queue/merkle-tree/Cargo.toml index c185d5af706..0606e9de330 100644 --- a/bridges/snowbridge/pallets/outbound-queue/merkle-tree/Cargo.toml +++ b/bridges/snowbridge/pallets/outbound-queue/merkle-tree/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-outbound-queue-merkle-tree" description = "Snowbridge Outbound Queue Merkle Tree" -version = "0.1.1" +version = "0.3.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/pallets/outbound-queue/runtime-api/Cargo.toml b/bridges/snowbridge/pallets/outbound-queue/runtime-api/Cargo.toml index 347b3bae493..cb68fd0a250 100644 --- a/bridges/snowbridge/pallets/outbound-queue/runtime-api/Cargo.toml +++ b/bridges/snowbridge/pallets/outbound-queue/runtime-api/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-outbound-queue-runtime-api" description = "Snowbridge Outbound Queue Runtime API" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/pallets/system/Cargo.toml b/bridges/snowbridge/pallets/system/Cargo.toml index f6c642e7376..5ad04290de0 100644 --- a/bridges/snowbridge/pallets/system/Cargo.toml +++ b/bridges/snowbridge/pallets/system/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-pallet-system" description = "Snowbridge System Pallet" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/pallets/system/runtime-api/Cargo.toml b/bridges/snowbridge/pallets/system/runtime-api/Cargo.toml index 355d2d29147..eb02ae1db52 100644 --- a/bridges/snowbridge/pallets/system/runtime-api/Cargo.toml +++ b/bridges/snowbridge/pallets/system/runtime-api/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-system-runtime-api" description = "Snowbridge System Runtime API" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/primitives/beacon/Cargo.toml b/bridges/snowbridge/primitives/beacon/Cargo.toml index e021bb01071..d181fa1d394 100644 --- a/bridges/snowbridge/primitives/beacon/Cargo.toml +++ b/bridges/snowbridge/primitives/beacon/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-beacon-primitives" description = "Snowbridge Beacon Primitives" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/primitives/core/Cargo.toml b/bridges/snowbridge/primitives/core/Cargo.toml index 090c48c403f..9a299ad0ae9 100644 --- a/bridges/snowbridge/primitives/core/Cargo.toml +++ b/bridges/snowbridge/primitives/core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-core" description = "Snowbridge Core" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/primitives/ethereum/Cargo.toml b/bridges/snowbridge/primitives/ethereum/Cargo.toml index 399139cef38..9fa725a6c05 100644 --- a/bridges/snowbridge/primitives/ethereum/Cargo.toml +++ b/bridges/snowbridge/primitives/ethereum/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-ethereum" description = "Snowbridge Ethereum" -version = "0.1.0" +version = "0.3.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/primitives/router/Cargo.toml b/bridges/snowbridge/primitives/router/Cargo.toml index 750a2a73e63..ded773e0d38 100644 --- a/bridges/snowbridge/primitives/router/Cargo.toml +++ b/bridges/snowbridge/primitives/router/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-router-primitives" description = "Snowbridge Router Primitives" -version = "0.0.0" +version = "0.9.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/runtime/runtime-common/Cargo.toml b/bridges/snowbridge/runtime/runtime-common/Cargo.toml index d4c86f8aa75..bf5e9a8832d 100644 --- a/bridges/snowbridge/runtime/runtime-common/Cargo.toml +++ b/bridges/snowbridge/runtime/runtime-common/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-runtime-common" description = "Snowbridge Runtime Common" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition.workspace = true repository.workspace = true diff --git a/bridges/snowbridge/runtime/test-common/Cargo.toml b/bridges/snowbridge/runtime/test-common/Cargo.toml index ec4466b3426..4e8b311cb97 100644 --- a/bridges/snowbridge/runtime/test-common/Cargo.toml +++ b/bridges/snowbridge/runtime/test-common/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snowbridge-runtime-test-common" description = "Snowbridge Runtime Tests" -version = "0.0.0" +version = "0.2.0" authors = ["Snowfork "] edition = "2021" license = "Apache-2.0" diff --git a/bridges/snowbridge/runtime/test-common/src/lib.rs b/bridges/snowbridge/runtime/test-common/src/lib.rs index 29b0e738c18..7455adf7617 100644 --- a/bridges/snowbridge/runtime/test-common/src/lib.rs +++ b/bridges/snowbridge/runtime/test-common/src/lib.rs @@ -40,6 +40,7 @@ where } pub fn send_transfer_token_message( + ethereum_chain_id: u64, assethub_parachain_id: u32, weth_contract_address: H160, destination_address: H160, @@ -89,7 +90,7 @@ where WithdrawAsset(Assets::from(vec![fee.clone()])), BuyExecution { fees: fee, weight_limit: Unlimited }, ExportMessage { - network: Ethereum { chain_id: 11155111 }, + network: Ethereum { chain_id: ethereum_chain_id }, destination: Here, xcm: inner_xcm, }, @@ -107,6 +108,7 @@ where } pub fn send_transfer_token_message_success( + ethereum_chain_id: u64, collator_session_key: CollatorSessionKeys, runtime_para_id: u32, assethub_parachain_id: u32, @@ -149,6 +151,7 @@ pub fn send_transfer_token_message_success( initial_fund::(assethub_parachain_id, 5_000_000_000_000); let outcome = send_transfer_token_message::( + ethereum_chain_id, assethub_parachain_id, weth_contract_address, destination_address, @@ -205,6 +208,7 @@ pub fn ethereum_outbound_queue_processes_messages_before_message_queue_works< XcmConfig, AllPalletsWithoutSystem, >( + ethereum_chain_id: u64, collator_session_key: CollatorSessionKeys, runtime_para_id: u32, assethub_parachain_id: u32, @@ -249,6 +253,7 @@ pub fn ethereum_outbound_queue_processes_messages_before_message_queue_works< initial_fund::(assethub_parachain_id, 5_000_000_000_000); let outcome = send_transfer_token_message::( + ethereum_chain_id, assethub_parachain_id, weth_contract_address, destination_address, @@ -290,6 +295,7 @@ pub fn ethereum_outbound_queue_processes_messages_before_message_queue_works< } pub fn send_unpaid_transfer_token_message( + ethereum_chain_id: u64, collator_session_key: CollatorSessionKeys, runtime_para_id: u32, assethub_parachain_id: u32, @@ -353,7 +359,7 @@ pub fn send_unpaid_transfer_token_message( let xcm = Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, ExportMessage { - network: Ethereum { chain_id: 11155111 }, + network: Ethereum { chain_id: ethereum_chain_id }, destination: Here, xcm: inner_xcm, }, @@ -375,6 +381,7 @@ pub fn send_unpaid_transfer_token_message( #[allow(clippy::too_many_arguments)] pub fn send_transfer_token_message_failure( + ethereum_chain_id: u64, collator_session_key: CollatorSessionKeys, runtime_para_id: u32, assethub_parachain_id: u32, @@ -414,6 +421,7 @@ pub fn send_transfer_token_message_failure( initial_fund::(assethub_parachain_id, initial_amount); let outcome = send_transfer_token_message::( + ethereum_chain_id, assethub_parachain_id, weth_contract_address, destination_address, diff --git a/bridges/snowbridge/scripts/contribute-upstream.sh b/bridges/snowbridge/scripts/contribute-upstream.sh index 8aa2d2a7035..32005b770ec 100755 --- a/bridges/snowbridge/scripts/contribute-upstream.sh +++ b/bridges/snowbridge/scripts/contribute-upstream.sh @@ -40,10 +40,12 @@ git checkout "$branch_name" # remove everything we think is not required for our needs rm -rf rust-toolchain.toml +rm -rf codecov.yml rm -rf $SNOWBRIDGE_FOLDER/.cargo rm -rf $SNOWBRIDGE_FOLDER/.github rm -rf $SNOWBRIDGE_FOLDER/SECURITY.md rm -rf $SNOWBRIDGE_FOLDER/.gitignore +rm -rf $SNOWBRIDGE_FOLDER/rustfmt.toml rm -rf $SNOWBRIDGE_FOLDER/templates rm -rf $SNOWBRIDGE_FOLDER/pallets/ethereum-client/fuzz diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs index b9f43624b65..239bd946e75 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs @@ -51,6 +51,7 @@ fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys( + 11155111, collator_session_keys(), 1013, 1000, @@ -69,6 +70,7 @@ pub fn transfer_token_to_ethereum_works() { #[test] pub fn unpaid_transfer_token_to_ethereum_fails_with_barrier() { snowbridge_runtime_test_common::send_unpaid_transfer_token_message::( + 11155111, collator_session_keys(), 1013, 1000, @@ -80,6 +82,7 @@ pub fn unpaid_transfer_token_to_ethereum_fails_with_barrier() { #[test] pub fn transfer_token_to_ethereum_fee_not_enough() { snowbridge_runtime_test_common::send_transfer_token_message_failure::( + 11155111, collator_session_keys(), 1013, 1000, @@ -95,6 +98,7 @@ pub fn transfer_token_to_ethereum_fee_not_enough() { #[test] pub fn transfer_token_to_ethereum_insufficient_fund() { snowbridge_runtime_test_common::send_transfer_token_message_failure::( + 11155111, collator_session_keys(), 1013, 1000, @@ -146,6 +150,7 @@ pub fn ethereum_outbound_queue_processes_messages_before_message_queue_works() { XcmConfig, AllPalletsWithoutSystem, >( + 11155111, collator_session_keys(), 1013, 1000, -- GitLab From eefd5fe4499515da66d088505093f75b5aa22550 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 28 Feb 2024 20:49:00 +0100 Subject: [PATCH 046/188] Multi-Block-Migrations, `poll` hook and new System callbacks (#1781) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This MR is the merge of https://github.com/paritytech/substrate/pull/14414 and https://github.com/paritytech/substrate/pull/14275. It implements [RFC#13](https://github.com/polkadot-fellows/RFCs/pull/13), closes https://github.com/paritytech/polkadot-sdk/issues/198. ----- This Merge request introduces three major topicals: 1. Multi-Block-Migrations 1. New pallet `poll` hook for periodic service work 1. Replacement hooks for `on_initialize` and `on_finalize` in cases where `poll` cannot be used and some more general changes to FRAME. The changes for each topical span over multiple crates. They are listed in topical order below. # 1.) Multi-Block-Migrations Multi-Block-Migrations are facilitated by creating `pallet_migrations` and configuring `System::Config::MultiBlockMigrator` to point to it. Executive picks this up and triggers one step of the migrations pallet per block. The chain is in lockdown mode for as long as an MBM is ongoing. Executive does this by polling `MultiBlockMigrator::ongoing` and not allowing any transaction in a block, if true. A MBM is defined through trait `SteppedMigration`. A condensed version looks like this: ```rust /// A migration that can proceed in multiple steps. pub trait SteppedMigration { type Cursor: FullCodec + MaxEncodedLen; type Identifier: FullCodec + MaxEncodedLen; fn id() -> Self::Identifier; fn max_steps() -> Option; fn step( cursor: Option, meter: &mut WeightMeter, ) -> Result, SteppedMigrationError>; } ``` `pallet_migrations` can be configured with an aggregated tuple of these migrations. It then starts to migrate them one-by-one on the next runtime upgrade. Two things are important here: - 1. Doing another runtime upgrade while MBMs are ongoing is not a good idea and can lead to messed up state. - 2. **Pallet Migrations MUST BE CONFIGURED IN `System::Config`, otherwise it is not used.** The pallet supports an `UpgradeStatusHandler` that can be used to notify external logic of upgrade start/finish (for example to pause XCM dispatch). Error recovery is very limited in the case that a migration errors or times out (exceeds its `max_steps`). Currently the runtime dev can decide in `FailedMigrationHandler::failed` how to handle this. One follow-up would be to pair this with the `SafeMode` pallet and enact safe mode when an upgrade fails, to allow governance to rescue the chain. This is currently not possible, since governance is not `Mandatory`. ## Runtime API - `Core`: `initialize_block` now returns `ExtrinsicInclusionMode` to inform the Block Author whether they can push transactions. ### Integration Add it to your runtime implementation of `Core` and `BlockBuilder`: ```patch diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs @@ impl_runtime_apis! { impl sp_block_builder::Core for Runtime { - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> RuntimeExecutiveMode { Executive::initialize_block(header) } ... } ``` # 2.) `poll` hook A new pallet hook is introduced: `poll`. `Poll` is intended to replace mostly all usage of `on_initialize`. The reason for this is that any code that can be called from `on_initialize` cannot be migrated through an MBM. Currently there is no way to statically check this; the implication is to use `on_initialize` as rarely as possible. Failing to do so can result in broken storage invariants. The implementation of the poll hook depends on the `Runtime API` changes that are explained above. # 3.) Hard-Deadline callbacks Three new callbacks are introduced and configured on `System::Config`: `PreInherents`, `PostInherents` and `PostTransactions`. These hooks are meant as replacement for `on_initialize` and `on_finalize` in cases where the code that runs cannot be moved to `poll`. The reason for this is to make the usage of HD-code (hard deadline) more explicit - again to prevent broken invariants by MBMs. # 4.) FRAME (general changes) ## `frame_system` pallet A new memorize storage item `InherentsApplied` is added. It is used by executive to track whether inherents have already been applied. Executive and can then execute the MBMs directly between inherents and transactions. The `Config` gets five new items: - `SingleBlockMigrations` this is the new way of configuring migrations that run in a single block. Previously they were defined as last generic argument of `Executive`. This shift is brings all central configuration about migrations closer into view of the developer (migrations that are configured in `Executive` will still work for now but is deprecated). - `MultiBlockMigrator` this can be configured to an engine that drives MBMs. One example would be the `pallet_migrations`. Note that this is only the engine; the exact MBMs are injected into the engine. - `PreInherents` a callback that executes after `on_initialize` but before inherents. - `PostInherents` a callback that executes after all inherents ran (including MBMs and `poll`). - `PostTransactions` in symmetry to `PreInherents`, this one is called before `on_finalize` but after all transactions. A sane default is to set all of these to `()`. Example diff suitable for any chain: ```patch @@ impl frame_system::Config for Test { type MaxConsumers = ConstU32<16>; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); } ``` An overview of how the block execution now looks like is here. The same graph is also in the rust doc.
Block Execution Flow

![Screenshot 2023-12-04 at 19 11 29](https://github.com/paritytech/polkadot-sdk/assets/10380170/e88a80c4-ef11-4faa-8df5-8b33a724c054)

## Inherent Order Moved to https://github.com/paritytech/polkadot-sdk/pull/2154 --------------- ## TODO - [ ] Check that `try-runtime` still works - [ ] Ensure backwards compatibility with old Runtime APIs - [x] Consume weight correctly - [x] Cleanup --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Liam Aharon Co-authored-by: Juan Girini Co-authored-by: command-bot <> Co-authored-by: Francisco Aguirre Co-authored-by: Gavin Wood Co-authored-by: Bastian Köcher --- Cargo.lock | 110 +- Cargo.toml | 1 + .../pallets/inbound-queue/src/mock.rs | 13 +- .../pallets/outbound-queue/src/mock.rs | 14 +- bridges/snowbridge/pallets/system/src/mock.rs | 15 +- .../ethereum-beacon-client/src/mock.rs | 259 +++ cumulus/parachain-template/runtime/src/lib.rs | 2 +- .../assets/asset-hub-rococo/src/lib.rs | 2 +- .../assets/asset-hub-westend/src/lib.rs | 2 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 2 +- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 2 +- .../collectives-westend/src/lib.rs | 2 +- .../contracts/contracts-rococo/src/lib.rs | 2 +- .../coretime/coretime-rococo/src/lib.rs | 2 +- .../coretime/coretime-westend/src/lib.rs | 2 +- .../glutton/glutton-westend/src/lib.rs | 2 +- .../runtimes/people/people-rococo/src/lib.rs | 2 +- .../runtimes/people/people-westend/src/lib.rs | 2 +- .../runtimes/starters/seedling/src/lib.rs | 2 +- .../runtimes/starters/shell/src/lib.rs | 2 +- .../runtimes/testing/penpal/src/lib.rs | 2 +- .../testing/rococo-parachain/src/lib.rs | 2 +- .../asset_hub_polkadot_aura.rs | 2 +- .../src/fake_runtime_api/aura.rs | 2 +- cumulus/test/runtime/src/lib.rs | 2 +- polkadot/node/service/src/fake_runtime_api.rs | 2 +- polkadot/runtime/common/src/claims.rs | 29 +- polkadot/runtime/rococo/src/lib.rs | 2 +- polkadot/runtime/test-runtime/src/lib.rs | 2 +- polkadot/runtime/westend/src/lib.rs | 2 +- prdoc/pr_1781.prdoc | 45 + substrate/bin/minimal/runtime/src/lib.rs | 5 +- .../bin/node-template/runtime/src/lib.rs | 2 +- substrate/bin/node/runtime/Cargo.toml | 4 + substrate/bin/node/runtime/src/lib.rs | 24 +- .../basic-authorship/src/basic_authorship.rs | 13 +- substrate/client/block-builder/src/lib.rs | 26 +- substrate/client/proposer-metrics/src/lib.rs | 4 + .../rpc-spec-v2/src/chain_head/tests.rs | 6 +- substrate/client/rpc/src/state/tests.rs | 2 +- substrate/frame/executive/Cargo.toml | 2 + substrate/frame/executive/src/lib.rs | 1194 +++----------- substrate/frame/executive/src/tests.rs | 1389 +++++++++++++++++ substrate/frame/migrations/Cargo.toml | 64 + .../frame/migrations/src/benchmarking.rs | 222 +++ substrate/frame/migrations/src/lib.rs | 746 +++++++++ substrate/frame/migrations/src/mock.rs | 163 ++ .../frame/migrations/src/mock_helpers.rs | 142 ++ substrate/frame/migrations/src/tests.rs | 335 ++++ substrate/frame/migrations/src/weights.rs | 358 +++++ substrate/frame/src/lib.rs | 2 +- .../src/construct_runtime/expand/inherent.rs | 63 +- .../procedural/src/pallet/expand/hooks.rs | 16 + substrate/frame/support/src/migrations.rs | 636 +++++++- .../support/src/storage/transactional.rs | 16 + substrate/frame/support/src/traits.rs | 11 +- substrate/frame/support/src/traits/hooks.rs | 70 + substrate/frame/support/src/traits/misc.rs | 17 +- .../undefined_inherent_part.stderr | 23 +- .../test/tests/pallet_outer_enums_explicit.rs | 1 + .../test/tests/pallet_outer_enums_implicit.rs | 1 + .../support/test/tests/runtime_metadata.rs | 6 +- substrate/frame/system/src/lib.rs | 74 +- substrate/frame/system/src/mock.rs | 16 + substrate/frame/system/src/tests.rs | 22 + .../api/proc-macro/src/decl_runtime_apis.rs | 1 + .../proc-macro/src/mock_impl_runtime_apis.rs | 2 +- substrate/primitives/api/src/lib.rs | 18 +- .../api/test/tests/decl_and_impl.rs | 2 +- .../ui/impl_incorrect_method_signature.rs | 2 +- .../api/test/tests/ui/impl_missing_version.rs | 2 +- .../test/tests/ui/missing_versioned_method.rs | 2 +- .../missing_versioned_method_multiple_vers.rs | 2 +- .../ui/positive_cases/custom_where_bound.rs | 2 +- .../tests/ui/positive_cases/default_impls.rs | 2 +- ...ype_reference_in_impl_runtime_apis_call.rs | 2 +- substrate/primitives/runtime/src/lib.rs | 10 + substrate/test-utils/runtime/src/lib.rs | 6 +- 78 files changed, 5072 insertions(+), 1188 deletions(-) create mode 100644 bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs create mode 100644 prdoc/pr_1781.prdoc create mode 100644 substrate/frame/executive/src/tests.rs create mode 100644 substrate/frame/migrations/Cargo.toml create mode 100644 substrate/frame/migrations/src/benchmarking.rs create mode 100644 substrate/frame/migrations/src/lib.rs create mode 100644 substrate/frame/migrations/src/mock.rs create mode 100644 substrate/frame/migrations/src/mock_helpers.rs create mode 100644 substrate/frame/migrations/src/tests.rs create mode 100644 substrate/frame/migrations/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 197d05e2633..3838ed0e94a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -322,6 +322,20 @@ dependencies = [ "num-traits", ] +[[package]] +name = "aquamarine" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da02abba9f9063d786eab1509833ebb2fac0f966862ca59439c76b9c566760" +dependencies = [ + "include_dir", + "itertools 0.10.5", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "aquamarine" version = "0.5.0" @@ -4055,7 +4069,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-proof-size-hostfunction", "cumulus-test-runtime", - "docify", + "docify 0.2.7", "frame-support", "frame-system", "log", @@ -4736,13 +4750,39 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "docify" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1b04e6ef3d21119d3eb7b032bca17f99fe041e9c072f30f32cc0e1a2b1f3c4" +dependencies = [ + "docify_macros 0.1.16", +] + [[package]] name = "docify" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cc4fd38aaa9fb98ac70794c82a00360d1e165a87fbf96a8a91f9dfc602aaee2" dependencies = [ - "docify_macros", + "docify_macros 0.2.7", +] + +[[package]] +name = "docify_macros" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b5610df7f2acf89a1bb5d1a66ae56b1c7fcdcfe3948856fb3ace3f644d70eb7" +dependencies = [ + "common-path", + "derive-syn-parse", + "lazy_static", + "proc-macro2", + "quote", + "regex", + "syn 2.0.50", + "termcolor", + "walkdir", ] [[package]] @@ -5451,7 +5491,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" name = "frame" version = "0.0.1-dev" dependencies = [ - "docify", + "docify 0.2.7", "frame-executive", "frame-support", "frame-system", @@ -5619,6 +5659,7 @@ dependencies = [ name = "frame-executive" version = "28.0.0" dependencies = [ + "aquamarine 0.3.3", "array-bytes 6.1.0", "frame-support", "frame-system", @@ -5675,11 +5716,11 @@ dependencies = [ name = "frame-support" version = "28.0.0" dependencies = [ - "aquamarine", + "aquamarine 0.5.0", "array-bytes 6.1.0", "assert_matches", "bitflags 1.3.2", - "docify", + "docify 0.2.7", "environmental", "frame-metadata", "frame-support-procedural", @@ -5822,7 +5863,7 @@ version = "28.0.0" dependencies = [ "cfg-if", "criterion 0.4.0", - "docify", + "docify 0.2.7", "frame-support", "log", "parity-scale-codec", @@ -7081,6 +7122,7 @@ dependencies = [ "pallet-lottery", "pallet-membership", "pallet-message-queue", + "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", @@ -9301,8 +9343,8 @@ dependencies = [ name = "pallet-bags-list" version = "27.0.0" dependencies = [ - "aquamarine", - "docify", + "aquamarine 0.5.0", + "docify 0.2.7", "frame-benchmarking", "frame-election-provider-support", "frame-support", @@ -9350,7 +9392,7 @@ dependencies = [ name = "pallet-balances" version = "28.0.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -9969,7 +10011,7 @@ dependencies = [ name = "pallet-example-single-block-migrations" version = "0.0.1" dependencies = [ - "docify", + "docify 0.2.7", "frame-executive", "frame-support", "frame-system", @@ -10035,7 +10077,7 @@ dependencies = [ name = "pallet-fast-unstake" version = "27.0.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-election-provider-support", "frame-support", @@ -10232,6 +10274,30 @@ dependencies = [ "sp-weights", ] +[[package]] +name = "pallet-migrations" +version = "1.0.0" +dependencies = [ + "docify 0.1.16", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "pretty_assertions", + "scale-info", + "sp-api", + "sp-block-builder", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 14.0.0", + "sp-tracing 16.0.0", + "sp-version", +] + [[package]] name = "pallet-mixnet" version = "0.4.0" @@ -10507,7 +10573,7 @@ dependencies = [ name = "pallet-paged-list" version = "0.6.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -10550,7 +10616,7 @@ dependencies = [ name = "pallet-parameters" version = "0.0.1" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -10711,7 +10777,7 @@ dependencies = [ name = "pallet-safe-mode" version = "9.0.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -10768,7 +10834,7 @@ dependencies = [ name = "pallet-scheduler" version = "29.0.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -10981,7 +11047,7 @@ dependencies = [ name = "pallet-sudo" version = "28.0.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -11012,7 +11078,7 @@ dependencies = [ name = "pallet-timestamp" version = "27.0.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -11116,7 +11182,7 @@ dependencies = [ name = "pallet-treasury" version = "27.0.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -11136,7 +11202,7 @@ dependencies = [ name = "pallet-tx-pause" version = "9.0.0" dependencies = [ - "docify", + "docify 0.2.7", "frame-benchmarking", "frame-support", "frame-system", @@ -13404,7 +13470,7 @@ version = "0.0.1" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", - "docify", + "docify 0.2.7", "frame", "frame-executive", "frame-support", @@ -15665,7 +15731,7 @@ name = "sc-chain-spec" version = "27.0.0" dependencies = [ "array-bytes 6.1.0", - "docify", + "docify 0.2.7", "log", "memmap2 0.9.3", "parity-scale-codec", @@ -18931,7 +18997,7 @@ dependencies = [ name = "sp-runtime" version = "31.0.1" dependencies = [ - "docify", + "docify 0.2.7", "either", "hash256-std-hasher", "impl-trait-for-tuples", diff --git a/Cargo.toml b/Cargo.toml index 654367cc1e2..48aa25f5c5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -352,6 +352,7 @@ members = [ "substrate/frame/membership", "substrate/frame/merkle-mountain-range", "substrate/frame/message-queue", + "substrate/frame/migrations", "substrate/frame/mixnet", "substrate/frame/multisig", "substrate/frame/nft-fractionalization", diff --git a/bridges/snowbridge/pallets/inbound-queue/src/mock.rs b/bridges/snowbridge/pallets/inbound-queue/src/mock.rs index 110f611c676..749fb0367f3 100644 --- a/bridges/snowbridge/pallets/inbound-queue/src/mock.rs +++ b/bridges/snowbridge/pallets/inbound-queue/src/mock.rs @@ -3,7 +3,7 @@ use super::*; use frame_support::{ - parameter_types, + derive_impl, parameter_types, traits::{ConstU128, ConstU32, Everything}, weights::IdentityFee, }; @@ -47,10 +47,9 @@ parameter_types! { type Balance = u128; +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = Everything; - type BlockWeights = (); - type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeTask = RuntimeTask; @@ -60,16 +59,8 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; type Nonce = u64; type Block = Block; } diff --git a/bridges/snowbridge/pallets/outbound-queue/src/mock.rs b/bridges/snowbridge/pallets/outbound-queue/src/mock.rs index dd8fee4e2ed..6e78fb44672 100644 --- a/bridges/snowbridge/pallets/outbound-queue/src/mock.rs +++ b/bridges/snowbridge/pallets/outbound-queue/src/mock.rs @@ -3,7 +3,7 @@ use super::*; use frame_support::{ - parameter_types, + derive_impl, parameter_types, traits::{Everything, Hooks}, weights::IdentityFee, }; @@ -37,10 +37,9 @@ parameter_types! { pub const BlockHashCount: u64 = 250; } +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = Everything; - type BlockWeights = (); - type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeTask = RuntimeTask; @@ -50,16 +49,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; type Nonce = u64; type Block = Block; } diff --git a/bridges/snowbridge/pallets/system/src/mock.rs b/bridges/snowbridge/pallets/system/src/mock.rs index edc3f141b07..de2970dd550 100644 --- a/bridges/snowbridge/pallets/system/src/mock.rs +++ b/bridges/snowbridge/pallets/system/src/mock.rs @@ -2,8 +2,8 @@ // SPDX-FileCopyrightText: 2023 Snowfork use crate as snowbridge_system; use frame_support::{ - parameter_types, - traits::{tokens::fungible::Mutate, ConstU128, ConstU16, ConstU64, ConstU8}, + derive_impl, parameter_types, + traits::{tokens::fungible::Mutate, ConstU128, ConstU64, ConstU8}, weights::IdentityFee, PalletId, }; @@ -95,11 +95,9 @@ frame_support::construct_runtime!( } ); +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeTask = RuntimeTask; @@ -109,15 +107,8 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU64<250>; - type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; type Nonce = u64; type Block = Block; } diff --git a/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs b/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs new file mode 100644 index 00000000000..77b5c1aa631 --- /dev/null +++ b/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +use crate as ethereum_beacon_client; +use frame_support::parameter_types; +use pallet_timestamp; +use primitives::{Fork, ForkVersions}; +use sp_core::H256; +use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; + +#[cfg(not(feature = "beacon-spec-mainnet"))] +pub mod minimal { + use super::*; + + use crate::config; + use frame_support::derive_impl; + use hex_literal::hex; + use primitives::CompactExecutionHeader; + use snowbridge_core::inbound::{Log, Proof}; + use sp_runtime::BuildStorage; + use std::{fs::File, path::PathBuf}; + + type Block = frame_system::mocking::MockBlock; + + frame_support::construct_runtime!( + pub enum Test { + System: frame_system::{Pallet, Call, Storage, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + EthereumBeaconClient: ethereum_beacon_client::{Pallet, Call, Storage, Event}, + } + ); + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; + } + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type PalletInfo = PalletInfo; + type SS58Prefix = SS58Prefix; + type Nonce = u64; + type Block = Block; + } + + impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = (); + type WeightInfo = (); + } + + parameter_types! { + pub const ExecutionHeadersPruneThreshold: u32 = 10; + pub const ChainForkVersions: ForkVersions = ForkVersions{ + genesis: Fork { + version: [0, 0, 0, 1], // 0x00000001 + epoch: 0, + }, + altair: Fork { + version: [1, 0, 0, 1], // 0x01000001 + epoch: 0, + }, + bellatrix: Fork { + version: [2, 0, 0, 1], // 0x02000001 + epoch: 0, + }, + capella: Fork { + version: [3, 0, 0, 1], // 0x03000001 + epoch: 0, + }, + }; + } + + impl ethereum_beacon_client::Config for Test { + type RuntimeEvent = RuntimeEvent; + type ForkVersions = ChainForkVersions; + type MaxExecutionHeadersToKeep = ExecutionHeadersPruneThreshold; + type WeightInfo = (); + } + + // Build genesis storage according to the mock runtime. + pub fn new_tester() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + let _ = ext.execute_with(|| Timestamp::set(RuntimeOrigin::signed(1), 30_000)); + ext + } + + fn load_fixture(basename: &str) -> Result + where + T: for<'de> serde::Deserialize<'de>, + { + let filepath: PathBuf = + [env!("CARGO_MANIFEST_DIR"), "tests", "fixtures", basename].iter().collect(); + serde_json::from_reader(File::open(filepath).unwrap()) + } + + pub fn load_execution_header_update_fixture() -> primitives::ExecutionHeaderUpdate { + load_fixture("execution-header-update.minimal.json").unwrap() + } + + pub fn load_checkpoint_update_fixture( + ) -> primitives::CheckpointUpdate<{ config::SYNC_COMMITTEE_SIZE }> { + load_fixture("initial-checkpoint.minimal.json").unwrap() + } + + pub fn load_sync_committee_update_fixture( + ) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { + load_fixture("sync-committee-update.minimal.json").unwrap() + } + + pub fn load_finalized_header_update_fixture( + ) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { + load_fixture("finalized-header-update.minimal.json").unwrap() + } + + pub fn load_next_sync_committee_update_fixture( + ) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { + load_fixture("next-sync-committee-update.minimal.json").unwrap() + } + + pub fn load_next_finalized_header_update_fixture( + ) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { + load_fixture("next-finalized-header-update.minimal.json").unwrap() + } + + pub fn get_message_verification_payload() -> (Log, Proof) { + ( + Log { + address: hex!("ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0").into(), + topics: vec![ + hex!("1b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ad").into(), + hex!("00000000000000000000000000000000000000000000000000000000000003e8").into(), + hex!("0000000000000000000000000000000000000000000000000000000000000001").into(), + ], + data: hex!("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000").into(), + }, + Proof { + block_hash: hex!("05aaa60b0f27cce9e71909508527264b77ee14da7b5bf915fcc4e32715333213").into(), + tx_index: 0, + data: (vec![ + hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb").to_vec(), + hex!("d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c185510").to_vec(), + hex!("b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646").to_vec(), + ], vec![ + hex!("f90131a0b601337b3aa10a671caa724eba641e759399979856141d3aea6b6b4ac59b889ba00c7d5dd48be9060221a02fb8fa213860b4c50d47046c8fa65ffaba5737d569e0a094601b62a1086cd9c9cb71a7ebff9e718f3217fd6e837efe4246733c0a196f63a06a4b0dd0aefc37b3c77828c8f07d1b7a2455ceb5dbfd3c77d7d6aeeddc2f7e8ca0d6e8e23142cdd8ec219e1f5d8b56aa18e456702b195deeaa210327284d42ade4a08a313d4c87023005d1ab631bbfe3f5de1e405d0e66d0bef3e033f1e5711b5521a0bf09a5d9a48b10ade82b8d6a5362a15921c8b5228a3487479b467db97411d82fa0f95cccae2a7c572ef3c566503e30bac2b2feb2d2f26eebf6d870dcf7f8cf59cea0d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c1855108080808080808080").to_vec(), + hex!("f851a0b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646a060a634b9280e3a23fb63375e7bbdd9ab07fd379ab6a67e2312bbc112195fa358808080808080808080808080808080").to_vec(), + hex!("f9030820b9030402f90300018301d6e2b9010000000000000800000000000020040008000000000000000000000000400000008000000000000000000000000000000000000000000000000000000000042010000000001000000000000000000000000000000000040000000000000000000000000000000000000000000000008000000000000000002000000000000000000000000200000000000000200000000000100000000040000001000200008000000000000200000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000f901f5f87a942ffa5ecdbe006d30397c7636d3e015eee251369ff842a0c965575a00553e094ca7c5d14f02e107c258dda06867cbf9e0e69f80e71bbcc1a000000000000000000000000000000000000000000000000000000000000003e8a000000000000000000000000000000000000000000000000000000000000003e8f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000f858948cf6147918a5cbb672703f879f385036f8793a24e1a01449abf21e49fd025f33495e77f7b1461caefdd3d4bb646424a3f445c4576a5ba0000000000000000000000000440edffa1352b13227e8ee646f3ea37456dec701").to_vec(), + ]), + } + ) + } + + pub fn get_message_verification_header() -> CompactExecutionHeader { + CompactExecutionHeader { + parent_hash: hex!("04a7f6ab8282203562c62f38b0ab41d32aaebe2c7ea687702b463148a6429e04") + .into(), + block_number: 55, + state_root: hex!("894d968712976d613519f973a317cb0781c7b039c89f27ea2b7ca193f7befdb3") + .into(), + receipts_root: hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb") + .into(), + } + } +} + +#[cfg(feature = "beacon-spec-mainnet")] +pub mod mainnet { + use super::*; + use frame_support::derive_impl; + + type Block = frame_system::mocking::MockBlock; + use sp_runtime::BuildStorage; + + frame_support::construct_runtime!( + pub enum Test { + System: frame_system::{Pallet, Call, Storage, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + EthereumBeaconClient: ethereum_beacon_client::{Pallet, Call, Storage, Event}, + } + ); + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; + } + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type PalletInfo = PalletInfo; + type SS58Prefix = SS58Prefix; + type Nonce = u64; + type Block = Block; + } + + impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = (); + type WeightInfo = (); + } + + parameter_types! { + pub const ChainForkVersions: ForkVersions = ForkVersions{ + genesis: Fork { + version: [0, 0, 16, 32], // 0x00001020 + epoch: 0, + }, + altair: Fork { + version: [1, 0, 16, 32], // 0x01001020 + epoch: 36660, + }, + bellatrix: Fork { + version: [2, 0, 16, 32], // 0x02001020 + epoch: 112260, + }, + capella: Fork { + version: [3, 0, 16, 32], // 0x03001020 + epoch: 162304, + }, + }; + pub const ExecutionHeadersPruneThreshold: u32 = 10; + } + + impl ethereum_beacon_client::Config for Test { + type RuntimeEvent = RuntimeEvent; + type ForkVersions = ChainForkVersions; + type MaxExecutionHeadersToKeep = ExecutionHeadersPruneThreshold; + type WeightInfo = (); + } + + // Build genesis storage according to the mock runtime. + pub fn new_tester() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + let _ = ext.execute_with(|| Timestamp::set(RuntimeOrigin::signed(1), 30_000)); + ext + } +} diff --git a/cumulus/parachain-template/runtime/src/lib.rs b/cumulus/parachain-template/runtime/src/lib.rs index cee9b33bf37..004a5d70ebc 100644 --- a/cumulus/parachain-template/runtime/src/lib.rs +++ b/cumulus/parachain-template/runtime/src/lib.rs @@ -560,7 +560,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 6791dc4064e..1c4f49fea0e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1093,7 +1093,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 5352eeb1a1b..e015c7bfca3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1124,7 +1124,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index db1dfbd45d6..0f6af1b51f1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -816,7 +816,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 1c8c9aa2075..206743ba6ac 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -566,7 +566,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 36eb0e07f87..3ed9d6e8e16 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -803,7 +803,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 541978098ca..c4df5b9a565 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -466,7 +466,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index fcd7576b1e1..0cdfebce742 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -521,7 +521,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 80eb7863803..7797329b526 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -512,7 +512,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index 10408aaf39a..e09ad42ea9f 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -332,7 +332,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 90c39891769..616da5519a5 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -495,7 +495,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index a904f7c3521..9f572330cac 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -495,7 +495,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs index ba077ef8879..4cc0a81ef49 100644 --- a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs @@ -300,7 +300,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/starters/shell/src/lib.rs b/cumulus/parachains/runtimes/starters/shell/src/lib.rs index 457394760d9..829754731a4 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/lib.rs @@ -357,7 +357,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index bf8dcbc24c8..0030287edb3 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -699,7 +699,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 57969d9a4f1..b69c2341d6b 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -689,7 +689,7 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/cumulus/polkadot-parachain/src/fake_runtime_api/asset_hub_polkadot_aura.rs b/cumulus/polkadot-parachain/src/fake_runtime_api/asset_hub_polkadot_aura.rs index 76dd7347ccb..7778d1bf7d2 100644 --- a/cumulus/polkadot-parachain/src/fake_runtime_api/asset_hub_polkadot_aura.rs +++ b/cumulus/polkadot-parachain/src/fake_runtime_api/asset_hub_polkadot_aura.rs @@ -39,7 +39,7 @@ sp_api::impl_runtime_apis! { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/cumulus/polkadot-parachain/src/fake_runtime_api/aura.rs b/cumulus/polkadot-parachain/src/fake_runtime_api/aura.rs index 0f01b85ebcf..880f5d760c7 100644 --- a/cumulus/polkadot-parachain/src/fake_runtime_api/aura.rs +++ b/cumulus/polkadot-parachain/src/fake_runtime_api/aura.rs @@ -39,7 +39,7 @@ sp_api::impl_runtime_apis! { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index 5fb31410984..5ccec8983e9 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -377,7 +377,7 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/polkadot/node/service/src/fake_runtime_api.rs b/polkadot/node/service/src/fake_runtime_api.rs index ccc3da22400..085ea93fdc7 100644 --- a/polkadot/node/service/src/fake_runtime_api.rs +++ b/polkadot/node/service/src/fake_runtime_api.rs @@ -60,7 +60,7 @@ sp_api::impl_runtime_apis! { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/polkadot/runtime/common/src/claims.rs b/polkadot/runtime/common/src/claims.rs index 86550ea8b4e..68f42914e44 100644 --- a/polkadot/runtime/common/src/claims.rs +++ b/polkadot/runtime/common/src/claims.rs @@ -702,7 +702,6 @@ mod tests { use secp_utils::*; use parity_scale_codec::Encode; - use sp_core::H256; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use crate::claims; @@ -715,11 +714,8 @@ mod tests { }; use pallet_balances; use sp_runtime::{ - traits::{BlakeTwo256, Identity, IdentityLookup}, - transaction_validity::TransactionLongevity, - BuildStorage, - DispatchError::BadOrigin, - TokenError, + traits::Identity, transaction_validity::TransactionLongevity, BuildStorage, + DispatchError::BadOrigin, TokenError, }; type Block = frame_system::mocking::MockBlock; @@ -734,34 +730,13 @@ mod tests { } ); - parameter_types! { - pub const BlockHashCount: u32 = 250; - } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; - type Nonce = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; } diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index bbc79a13d37..173301e1ad9 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -1768,7 +1768,7 @@ sp_api::impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index b74def5de8a..6c899c52701 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -767,7 +767,7 @@ sp_api::impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 574710b3110..91047d953f5 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1793,7 +1793,7 @@ sp_api::impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/prdoc/pr_1781.prdoc b/prdoc/pr_1781.prdoc new file mode 100644 index 00000000000..e3560842d15 --- /dev/null +++ b/prdoc/pr_1781.prdoc @@ -0,0 +1,45 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Multi-Block-Migrations, `poll` hook and new System Callbacks" + +doc: + - audience: Runtime Dev + description: | + The major things that this MR touches are: + + **Multi-Block-Migrations**: `pallet-migrations` is introduced that can be configured in the + `System` of a runtime to act as multi-block migrator. The `migrations` pallet then in turn + receives the list of MBMs as config parameter. The list of migrations can be an aggregated + tuple of `SteppedMigration` trait implementation. + It is paramount that the `migrations` pallet is configured in `System` once it is deployed. A + test is in place to double check this. + + To integrate this into your runtime, it is only necessary to change the return type of + `initialize_block` to `RuntimeExecutiveMode`. For extended info please see + https://github.com/paritytech/polkadot-sdk/pull/1781. + + **poll**: a new pallet hook named `poll` is added. This can be used for places where the code + that should be executed is not deadline critical. Runtime devs are advised to skim their usage + of `on_initialize` and `on_finalize` to see whether they can be replace with `poll`. `poll` is + not guaranteed to be called each block. In fact it will not be called when MBMs are ongoing. + + **System Callbacks**: The `system` pallet gets five new config items - all of which can be + safely set to `()` as default. They are: + - `SingleBlockMigrations`: replaces the `Executive` now for configuring migrations. + - `MultiBlockMigrator`: the `pallet-migrations` would be set here, if deployed. + - `PreInherents`: a hook that runs before any inherent. + - `PostInherents`: a hook to run between inherents and `poll`/MBM logic. + - `PostTransactions`: a hook to run after all transactions but before `on_idle`. + +crates: + - name: frame-executive + - name: frame-system + - name: frame-support + - name: frame-support-procedural + - name: pallet-migrations + - name: sc-basic-authorship + - name: sc-block-builder + - name: sp-api + - name: sp-api-proc-macro + - name: sp-runtime diff --git a/substrate/bin/minimal/runtime/src/lib.rs b/substrate/bin/minimal/runtime/src/lib.rs index 610289693d9..fb996aef46b 100644 --- a/substrate/bin/minimal/runtime/src/lib.rs +++ b/substrate/bin/minimal/runtime/src/lib.rs @@ -26,7 +26,8 @@ use frame::{ prelude::*, runtime::{ apis::{ - self, impl_runtime_apis, ApplyExtrinsicResult, CheckInherentsResult, OpaqueMetadata, + self, impl_runtime_apis, ApplyExtrinsicResult, CheckInherentsResult, + ExtrinsicInclusionMode, OpaqueMetadata, }, prelude::*, }, @@ -121,7 +122,7 @@ impl_runtime_apis! { RuntimeExecutive::execute_block(block) } - fn initialize_block(header: &Header) { + fn initialize_block(header: &Header) -> ExtrinsicInclusionMode { RuntimeExecutive::initialize_block(header) } } diff --git a/substrate/bin/node-template/runtime/src/lib.rs b/substrate/bin/node-template/runtime/src/lib.rs index 3b6a74be251..159697f427f 100644 --- a/substrate/bin/node-template/runtime/src/lib.rs +++ b/substrate/bin/node-template/runtime/src/lib.rs @@ -331,7 +331,7 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml index aa13c3d292b..9607d05daf0 100644 --- a/substrate/bin/node/runtime/Cargo.toml +++ b/substrate/bin/node/runtime/Cargo.toml @@ -88,6 +88,7 @@ pallet-election-provider-support-benchmarking = { path = "../../../frame/electio pallet-elections-phragmen = { path = "../../../frame/elections-phragmen", default-features = false } pallet-example-tasks = { path = "../../../frame/examples/tasks", default-features = false } pallet-fast-unstake = { path = "../../../frame/fast-unstake", default-features = false } +pallet-migrations = { path = "../../../frame/migrations", default-features = false } pallet-nis = { path = "../../../frame/nis", default-features = false } pallet-grandpa = { path = "../../../frame/grandpa", default-features = false } pallet-im-online = { path = "../../../frame/im-online", default-features = false } @@ -198,6 +199,7 @@ std = [ "pallet-lottery/std", "pallet-membership/std", "pallet-message-queue/std", + "pallet-migrations/std", "pallet-mixnet/std", "pallet-mmr/std", "pallet-multisig/std", @@ -302,6 +304,7 @@ runtime-benchmarks = [ "pallet-lottery/runtime-benchmarks", "pallet-membership/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", + "pallet-migrations/runtime-benchmarks", "pallet-mixnet/runtime-benchmarks", "pallet-mmr/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", @@ -381,6 +384,7 @@ try-runtime = [ "pallet-lottery/try-runtime", "pallet-membership/try-runtime", "pallet-message-queue/try-runtime", + "pallet-migrations/try-runtime", "pallet-mixnet/try-runtime", "pallet-mmr/try-runtime", "pallet-multisig/try-runtime", diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index b34d8c89e56..5431628c747 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -310,6 +310,7 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = frame_system::weights::SubstrateWeight; type SS58Prefix = ConstU16<42>; type MaxConsumers = ConstU32<16>; + type MultiBlockMigrator = MultiBlockMigrations; } impl pallet_insecure_randomness_collective_flip::Config for Runtime {} @@ -2007,6 +2008,25 @@ impl pallet_statement::Config for Runtime { type MaxAllowedBytes = MaxAllowedBytes; } +parameter_types! { + pub MbmServiceWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_migrations::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + #[cfg(not(feature = "runtime-benchmarks"))] + type Migrations = (); + // Benchmarks need mocked migrations to guarantee that they succeed. + #[cfg(feature = "runtime-benchmarks")] + type Migrations = pallet_migrations::mock_helpers::MockedMigrations; + type CursorMaxLen = ConstU32<65_536>; + type IdentifierMaxLen = ConstU32<256>; + type MigrationStatusHandler = (); + type FailedMigrationHandler = frame_support::migrations::FreezeChainOnFailedMigration; + type MaxServiceWeight = MbmServiceWeight; + type WeightInfo = pallet_migrations::weights::SubstrateWeight; +} + parameter_types! { pub const BrokerPalletId: PalletId = PalletId(*b"py/broke"); } @@ -2241,6 +2261,7 @@ construct_runtime!( TxPause: pallet_tx_pause, SafeMode: pallet_safe_mode, Statement: pallet_statement, + MultiBlockMigrations: pallet_migrations, Broker: pallet_broker, TasksExample: pallet_example_tasks, Mixnet: pallet_mixnet, @@ -2372,6 +2393,7 @@ mod benches { [pallet_lottery, Lottery] [pallet_membership, TechnicalMembership] [pallet_message_queue, MessageQueue] + [pallet_migrations, MultiBlockMigrations] [pallet_mmr, Mmr] [pallet_multisig, Multisig] [pallet_nomination_pools, NominationPoolsBench::] @@ -2417,7 +2439,7 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/substrate/client/basic-authorship/src/basic_authorship.rs b/substrate/client/basic-authorship/src/basic_authorship.rs index fdc3d4918de..932287ac865 100644 --- a/substrate/client/basic-authorship/src/basic_authorship.rs +++ b/substrate/client/basic-authorship/src/basic_authorship.rs @@ -38,7 +38,7 @@ use sp_core::traits::SpawnNamed; use sp_inherents::InherentData; use sp_runtime::{ traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, - Digest, Percent, SaturatedConversion, + Digest, ExtrinsicInclusionMode, Percent, SaturatedConversion, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -335,11 +335,12 @@ where self.apply_inherents(&mut block_builder, inherent_data)?; - // TODO call `after_inherents` and check if we should apply extrinsincs here - // - - let end_reason = - self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?; + let mode = block_builder.extrinsic_inclusion_mode(); + let end_reason = match mode { + ExtrinsicInclusionMode::AllExtrinsics => + self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?, + ExtrinsicInclusionMode::OnlyInherents => EndProposingReason::TransactionForbidden, + }; let (block, storage_changes, proof) = block_builder.build()?.into_inner(); let block_took = block_timer.elapsed(); diff --git a/substrate/client/block-builder/src/lib.rs b/substrate/client/block-builder/src/lib.rs index 258e39d962b..2f22cd42591 100644 --- a/substrate/client/block-builder/src/lib.rs +++ b/substrate/client/block-builder/src/lib.rs @@ -37,7 +37,7 @@ use sp_core::traits::CallContext; use sp_runtime::{ legacy, traits::{Block as BlockT, Hash, HashingFor, Header as HeaderT, NumberFor, One}, - Digest, + Digest, ExtrinsicInclusionMode, }; use std::marker::PhantomData; @@ -198,10 +198,12 @@ pub struct BlockBuilder<'a, Block: BlockT, C: ProvideRuntimeApi + 'a> { extrinsics: Vec, api: ApiRef<'a, C::Api>, call_api_at: &'a C, + /// Version of the [`BlockBuilderApi`] runtime API. version: u32, parent_hash: Block::Hash, /// The estimated size of the block header. estimated_header_size: usize, + extrinsic_inclusion_mode: ExtrinsicInclusionMode, } impl<'a, Block, C> BlockBuilder<'a, Block, C> @@ -244,9 +246,19 @@ where api.set_call_context(CallContext::Onchain); - api.initialize_block(parent_hash, &header)?; + let core_version = api + .api_version::>(parent_hash)? + .ok_or_else(|| Error::VersionInvalid("Core".to_string()))?; - let version = api + let extrinsic_inclusion_mode = if core_version >= 5 { + api.initialize_block(parent_hash, &header)? + } else { + #[allow(deprecated)] + api.initialize_block_before_version_5(parent_hash, &header)?; + ExtrinsicInclusionMode::AllExtrinsics + }; + + let bb_version = api .api_version::>(parent_hash)? .ok_or_else(|| Error::VersionInvalid("BlockBuilderApi".to_string()))?; @@ -254,12 +266,18 @@ where parent_hash, extrinsics: Vec::new(), api, - version, + version: bb_version, estimated_header_size, call_api_at, + extrinsic_inclusion_mode, }) } + /// The extrinsic inclusion mode of the runtime for this block. + pub fn extrinsic_inclusion_mode(&self) -> ExtrinsicInclusionMode { + self.extrinsic_inclusion_mode + } + /// Push onto the block's list of extrinsics. /// /// This will ensure the extrinsic can be validly executed (by executing it). diff --git a/substrate/client/proposer-metrics/src/lib.rs b/substrate/client/proposer-metrics/src/lib.rs index 012e8ca769a..2856300cf80 100644 --- a/substrate/client/proposer-metrics/src/lib.rs +++ b/substrate/client/proposer-metrics/src/lib.rs @@ -44,11 +44,14 @@ impl MetricsLink { } /// The reason why proposing a block ended. +#[derive(Clone, Copy, PartialEq, Eq)] pub enum EndProposingReason { NoMoreTransactions, HitDeadline, HitBlockSizeLimit, HitBlockWeightLimit, + /// No transactions are allowed in the block. + TransactionForbidden, } /// Authorship metrics. @@ -112,6 +115,7 @@ impl Metrics { EndProposingReason::NoMoreTransactions => "no_more_transactions", EndProposingReason::HitBlockSizeLimit => "hit_block_size_limit", EndProposingReason::HitBlockWeightLimit => "hit_block_weight_limit", + EndProposingReason::TransactionForbidden => "transactions_forbidden", }; self.end_proposing_reason.with_label_values(&[reason]).inc(); diff --git a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs index 9544736d84c..89d8c4ce271 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs @@ -242,12 +242,12 @@ async fn follow_with_runtime() { let event: FollowEvent = get_next_event(&mut sub).await; // it is basically json-encoded substrate_test_runtime_client::runtime::VERSION - let runtime_str = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":0,\ - \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\ + let runtime_str = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ + \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",5],\ [\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\ [\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\ [\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\ - [\"0xed99c5acb25eedf5\",3],[\"0xfbc577b9d747efd6\",1]],\"transactionVersion\":1,\"stateVersion\":0}"; + [\"0xed99c5acb25eedf5\",3],[\"0xfbc577b9d747efd6\",1]],\"transactionVersion\":1,\"stateVersion\":1}"; let runtime: RuntimeVersion = serde_json::from_str(runtime_str).unwrap(); diff --git a/substrate/client/rpc/src/state/tests.rs b/substrate/client/rpc/src/state/tests.rs index 96f4c1be960..dd866e671c5 100644 --- a/substrate/client/rpc/src/state/tests.rs +++ b/substrate/client/rpc/src/state/tests.rs @@ -475,7 +475,7 @@ async fn should_return_runtime_version() { // it is basically json-encoded substrate_test_runtime_client::runtime::VERSION let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ - \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\ + \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",5],\ [\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\ [\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\ [\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\ diff --git a/substrate/frame/executive/Cargo.toml b/substrate/frame/executive/Cargo.toml index a4ca265f617..63285e4cb49 100644 --- a/substrate/frame/executive/Cargo.toml +++ b/substrate/frame/executive/Cargo.toml @@ -16,6 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] +aquamarine = "0.3.2" codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ "derive", ] } @@ -44,6 +45,7 @@ default = ["std"] with-tracing = ["sp-tracing/with-tracing"] std = [ "codec/std", + "frame-support/experimental", "frame-support/std", "frame-system/std", "frame-try-runtime/std", diff --git a/substrate/frame/executive/src/lib.rs b/substrate/frame/executive/src/lib.rs index 48ff675f808..3028eaf318e 100644 --- a/substrate/frame/executive/src/lib.rs +++ b/substrate/frame/executive/src/lib.rs @@ -15,6 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![cfg_attr(not(feature = "std"), no_std)] + //! # Executive Module //! //! The Executive module acts as the orchestration layer for the runtime. It dispatches incoming @@ -35,6 +37,8 @@ //! - Finalize a block. //! - Start an off-chain worker. //! +//! The flow of their application in a block is explained in the [block flowchart](block_flowchart). +//! //! ### Implementations //! //! The Executive module provides the following implementations: @@ -114,17 +118,51 @@ //! pub type Executive = executive::Executive; //! ``` -#![cfg_attr(not(feature = "std"), no_std)] +#[cfg(doc)] +#[cfg_attr(doc, aquamarine::aquamarine)] +/// # Block Execution +/// +/// These are the steps of block execution as done by [`Executive::execute_block`]. A block is +/// invalid if any of them fail. +/// +/// ```mermaid +/// flowchart TD +/// Executive::execute_block --> on_runtime_upgrade +/// on_runtime_upgrade --> System::initialize +/// Executive::initialize_block --> System::initialize +/// System::initialize --> on_initialize +/// on_initialize --> PreInherents[System::PreInherents] +/// PreInherents --> Inherents[Apply Inherents] +/// Inherents --> PostInherents[System::PostInherents] +/// PostInherents --> Check{MBM ongoing?} +/// Check -->|No| poll +/// Check -->|Yes| post_transactions_2[System::PostTransaction] +/// post_transactions_2 --> Step[MBMs::step] +/// Step --> on_finalize +/// poll --> transactions[Apply Transactions] +/// transactions --> post_transactions_1[System::PostTransaction] +/// post_transactions_1 --> CheckIdle{Weight remaining?} +/// CheckIdle -->|Yes| on_idle +/// CheckIdle -->|No| on_finalize +/// on_idle --> on_finalize +/// ``` +pub mod block_flowchart {} + +#[cfg(test)] +mod tests; use codec::{Codec, Encode}; use frame_support::{ + defensive_assert, dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo}, + migrations::MultiStepMigrator, pallet_prelude::InvalidTransaction, traits::{ BeforeAllRuntimeMigrations, EnsureInherentsAreFirst, ExecuteBlock, OffchainWorker, - OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade, + OnFinalize, OnIdle, OnInitialize, OnPoll, OnRuntimeUpgrade, PostInherents, + PostTransactions, PreInherents, }, - weights::Weight, + weights::{Weight, WeightMeter}, }; use frame_system::pallet_prelude::BlockNumberFor; use sp_runtime::{ @@ -134,7 +172,7 @@ use sp_runtime::{ ValidateUnsigned, Zero, }, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, + ApplyExtrinsicResult, ExtrinsicInclusionMode, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -198,7 +236,8 @@ impl< + OnInitialize> + OnIdle> + OnFinalize> - + OffchainWorker>, + + OffchainWorker> + + OnPoll>, COnRuntimeUpgrade: OnRuntimeUpgrade, > ExecuteBlock for Executive @@ -237,6 +276,7 @@ impl< + OnIdle> + OnFinalize> + OffchainWorker> + + OnPoll> + TryState> + TryDecodeEntireStorage, COnRuntimeUpgrade: OnRuntimeUpgrade, @@ -272,36 +312,50 @@ where select, ); - Self::initialize_block(block.header()); - Self::initial_checks(&block); - + let mode = Self::initialize_block(block.header()); + let num_inherents = Self::initial_checks(&block) as usize; let (header, extrinsics) = block.deconstruct(); + // Check if there are any forbidden non-inherents in the block. + if mode == ExtrinsicInclusionMode::OnlyInherents && extrinsics.len() > num_inherents { + return Err("Only inherents allowed".into()) + } + let try_apply_extrinsic = |uxt: Block::Extrinsic| -> ApplyExtrinsicResult { sp_io::init_tracing(); let encoded = uxt.encode(); let encoded_len = encoded.len(); + let is_inherent = System::is_inherent(&uxt); // skip signature verification. let xt = if signature_check { uxt.check(&Default::default()) } else { uxt.unchecked_into_checked_i_know_what_i_am_doing(&Default::default()) }?; - >::note_extrinsic(encoded); let dispatch_info = xt.get_dispatch_info(); + if !is_inherent && !>::inherents_applied() { + Self::inherents_applied(); + } + + >::note_extrinsic(encoded); let r = Applyable::apply::(xt, &dispatch_info, encoded_len)?; + if r.is_err() && dispatch_info.class == DispatchClass::Mandatory { + return Err(InvalidTransaction::BadMandatory.into()) + } + >::note_applied_extrinsic(&r, dispatch_info); Ok(r.map(|_| ()).map_err(|e| e.error)) }; - for e in extrinsics { + // Apply extrinsics: + for e in extrinsics.iter() { if let Err(err) = try_apply_extrinsic(e.clone()) { log::error!( - target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", + target: LOG_TARGET, "transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", e, err, ); @@ -309,9 +363,17 @@ where } } + // In this case there were no transactions to trigger this state transition: + if !>::inherents_applied() { + Self::inherents_applied(); + } + // post-extrinsics book-keeping >::note_finished_extrinsics(); - Self::idle_and_finalize_hook(*header.number()); + ::PostTransactions::post_transactions(); + + Self::on_idle_hook(*header.number()); + Self::on_finalize_hook(*header.number()); // run the try-state checks of all pallets, ensuring they don't alter any state. let _guard = frame_support::StorageNoopGuard::default(); @@ -449,7 +511,8 @@ impl< + OnInitialize> + OnIdle> + OnFinalize> - + OffchainWorker>, + + OffchainWorker> + + OnPoll>, COnRuntimeUpgrade: OnRuntimeUpgrade, > Executive where @@ -464,16 +527,36 @@ where pub fn execute_on_runtime_upgrade() -> Weight { let before_all_weight = ::before_all_runtime_migrations(); - <(COnRuntimeUpgrade, AllPalletsWithSystem) as OnRuntimeUpgrade>::on_runtime_upgrade() - .saturating_add(before_all_weight) + + let runtime_upgrade_weight = <( + COnRuntimeUpgrade, + ::SingleBlockMigrations, + // We want to run the migrations before we call into the pallets as they may + // access any state that would then not be migrated. + AllPalletsWithSystem, + ) as OnRuntimeUpgrade>::on_runtime_upgrade(); + + before_all_weight.saturating_add(runtime_upgrade_weight) } /// Start the execution of a particular block. - pub fn initialize_block(header: &frame_system::pallet_prelude::HeaderFor) { + pub fn initialize_block( + header: &frame_system::pallet_prelude::HeaderFor, + ) -> ExtrinsicInclusionMode { sp_io::init_tracing(); sp_tracing::enter_span!(sp_tracing::Level::TRACE, "init_block"); let digests = Self::extract_pre_digest(header); Self::initialize_block_impl(header.number(), header.parent_hash(), &digests); + + Self::extrinsic_mode() + } + + fn extrinsic_mode() -> ExtrinsicInclusionMode { + if ::MultiBlockMigrator::ongoing() { + ExtrinsicInclusionMode::OnlyInherents + } else { + ExtrinsicInclusionMode::AllExtrinsics + } } fn extract_pre_digest(header: &frame_system::pallet_prelude::HeaderFor) -> Digest { @@ -519,6 +602,7 @@ where ); frame_system::Pallet::::note_finished_initialize(); + ::PreInherents::pre_inherents(); } /// Returns if the runtime has been upgraded, based on [`frame_system::LastRuntimeUpgrade`]. @@ -529,7 +613,8 @@ where last.map(|v| v.was_upgraded(¤t)).unwrap_or(true) } - fn initial_checks(block: &Block) { + /// Returns the number of inherents in the block. + fn initial_checks(block: &Block) -> u32 { sp_tracing::enter_span!(sp_tracing::Level::TRACE, "initial_checks"); let header = block.header(); @@ -542,8 +627,9 @@ where "Parent hash should be valid.", ); - if let Err(i) = System::ensure_inherents_are_first(block) { - panic!("Invalid inherent position for extrinsic at index {}", i); + match System::ensure_inherents_are_first(block) { + Ok(num) => num, + Err(i) => panic!("Invalid inherent position for extrinsic at index {}", i), } } @@ -552,53 +638,90 @@ where sp_io::init_tracing(); sp_tracing::within_span! { sp_tracing::info_span!("execute_block", ?block); + // Execute `on_runtime_upgrade` and `on_initialize`. + let mode = Self::initialize_block(block.header()); + let num_inherents = Self::initial_checks(&block) as usize; + let (header, extrinsics) = block.deconstruct(); + let num_extrinsics = extrinsics.len(); - Self::initialize_block(block.header()); + if mode == ExtrinsicInclusionMode::OnlyInherents && num_extrinsics > num_inherents { + // Invalid block + panic!("Only inherents are allowed in this block") + } - // any initial checks - Self::initial_checks(&block); + Self::apply_extrinsics(extrinsics.into_iter()); - // execute extrinsics - let (header, extrinsics) = block.deconstruct(); - Self::execute_extrinsics_with_book_keeping(extrinsics, *header.number()); + // In this case there were no transactions to trigger this state transition: + if !>::inherents_applied() { + defensive_assert!(num_inherents == num_extrinsics); + Self::inherents_applied(); + } - // any final checks + >::note_finished_extrinsics(); + ::PostTransactions::post_transactions(); + + Self::on_idle_hook(*header.number()); + Self::on_finalize_hook(*header.number()); Self::final_checks(&header); } } - /// Execute given extrinsics and take care of post-extrinsics book-keeping. - fn execute_extrinsics_with_book_keeping( - extrinsics: Vec, - block_number: NumberFor, - ) { + /// Logic that runs directly after inherent application. + /// + /// It advances the Multi-Block-Migrations or runs the `on_poll` hook. + pub fn inherents_applied() { + >::note_inherents_applied(); + ::PostInherents::post_inherents(); + + if ::MultiBlockMigrator::ongoing() { + let used_weight = ::MultiBlockMigrator::step(); + >::register_extra_weight_unchecked( + used_weight, + DispatchClass::Mandatory, + ); + } else { + let block_number = >::block_number(); + Self::on_poll_hook(block_number); + } + } + + /// Execute given extrinsics. + fn apply_extrinsics(extrinsics: impl Iterator) { extrinsics.into_iter().for_each(|e| { if let Err(e) = Self::apply_extrinsic(e) { let err: &'static str = e.into(); panic!("{}", err) } }); - - // post-extrinsics book-keeping - >::note_finished_extrinsics(); - - Self::idle_and_finalize_hook(block_number); } /// Finalize the block - it is up the caller to ensure that all header fields are valid /// except state-root. + // Note: Only used by the block builder - not Executive itself. pub fn finalize_block() -> frame_system::pallet_prelude::HeaderFor { sp_io::init_tracing(); sp_tracing::enter_span!(sp_tracing::Level::TRACE, "finalize_block"); - >::note_finished_extrinsics(); - let block_number = >::block_number(); - Self::idle_and_finalize_hook(block_number); + // In this case there were no transactions to trigger this state transition: + if !>::inherents_applied() { + Self::inherents_applied(); + } + >::note_finished_extrinsics(); + ::PostTransactions::post_transactions(); + let block_number = >::block_number(); + Self::on_idle_hook(block_number); + Self::on_finalize_hook(block_number); >::finalize() } - fn idle_and_finalize_hook(block_number: NumberFor) { + /// Run the `on_idle` hook of all pallet, but only if there is weight remaining and there are no + /// ongoing MBMs. + fn on_idle_hook(block_number: NumberFor) { + if ::MultiBlockMigrator::ongoing() { + return + } + let weight = >::block_weight(); let max_weight = >::get().max_block; let remaining_weight = max_weight.saturating_sub(weight.total()); @@ -613,7 +736,33 @@ where DispatchClass::Mandatory, ); } + } + + fn on_poll_hook(block_number: NumberFor) { + defensive_assert!( + !::MultiBlockMigrator::ongoing(), + "on_poll should not be called during migrations" + ); + let weight = >::block_weight(); + let max_weight = >::get().max_block; + let remaining = max_weight.saturating_sub(weight.total()); + + if remaining.all_gt(Weight::zero()) { + let mut meter = WeightMeter::with_limit(remaining); + >>::on_poll( + block_number, + &mut meter, + ); + >::register_extra_weight_unchecked( + meter.consumed(), + DispatchClass::Mandatory, + ); + } + } + + /// Run the `on_finalize` hook of all pallet. + fn on_finalize_hook(block_number: NumberFor) { >>::on_finalize(block_number); } @@ -627,8 +776,18 @@ where let encoded_len = encoded.len(); sp_tracing::enter_span!(sp_tracing::info_span!("apply_extrinsic", ext=?sp_core::hexdisplay::HexDisplay::from(&encoded))); + + // We use the dedicated `is_inherent` check here, since just relying on `Mandatory` dispatch + // class does not capture optional inherents. + let is_inherent = System::is_inherent(&uxt); + // Verify that the signature is good. let xt = uxt.check(&Default::default())?; + let dispatch_info = xt.get_dispatch_info(); + + if !is_inherent && !>::inherents_applied() { + Self::inherents_applied(); + } // We don't need to make sure to `note_extrinsic` only after we know it's going to be // executed to prevent it from leaking in storage since at this point, it will either @@ -637,8 +796,6 @@ where // AUDIT: Under no circumstances may this function panic from here onwards. - // Decode parameters and dispatch - let dispatch_info = xt.get_dispatch_info(); let r = Applyable::apply::(xt, &dispatch_info, encoded_len)?; // Mandatory(inherents) are not allowed to fail. @@ -745,956 +902,3 @@ where ) } } - -#[cfg(test)] -mod tests { - use super::*; - - use sp_core::H256; - use sp_runtime::{ - generic::{DigestItem, Era}, - testing::{Block, Digest, Header}, - traits::{BlakeTwo256, Block as BlockT, Header as HeaderT, IdentityLookup}, - transaction_validity::{ - InvalidTransaction, TransactionValidityError, UnknownTransaction, ValidTransaction, - }, - BuildStorage, DispatchError, - }; - - use frame_support::{ - assert_err, derive_impl, parameter_types, - traits::{fungible, ConstU32, ConstU64, ConstU8, Currency}, - weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFee}, - }; - use frame_system::{ChainContext, LastRuntimeUpgrade, LastRuntimeUpgradeInfo}; - use pallet_balances::Call as BalancesCall; - use pallet_transaction_payment::CurrencyAdapter; - - const TEST_KEY: &[u8] = b":test:key:"; - - #[frame_support::pallet(dev_mode)] - mod custom { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::hooks] - impl Hooks> for Pallet { - // module hooks. - // one with block number arg and one without - fn on_initialize(n: BlockNumberFor) -> Weight { - println!("on_initialize({})", n); - Weight::from_parts(175, 0) - } - - fn on_idle(n: BlockNumberFor, remaining_weight: Weight) -> Weight { - println!("on_idle{}, {})", n, remaining_weight); - Weight::from_parts(175, 0) - } - - fn on_finalize(n: BlockNumberFor) { - println!("on_finalize({})", n); - } - - fn on_runtime_upgrade() -> Weight { - sp_io::storage::set(super::TEST_KEY, "module".as_bytes()); - Weight::from_parts(200, 0) - } - - fn offchain_worker(n: BlockNumberFor) { - assert_eq!(BlockNumberFor::::from(1u32), n); - } - } - - #[pallet::call] - impl Pallet { - pub fn some_function(origin: OriginFor) -> DispatchResult { - // NOTE: does not make any different. - frame_system::ensure_signed(origin)?; - Ok(()) - } - - #[pallet::weight((200, DispatchClass::Operational))] - pub fn some_root_operation(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } - - pub fn some_unsigned_message(origin: OriginFor) -> DispatchResult { - frame_system::ensure_none(origin)?; - Ok(()) - } - - pub fn allowed_unsigned(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } - - pub fn unallowed_unsigned(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } - - #[pallet::weight((0, DispatchClass::Mandatory))] - pub fn inherent_call(origin: OriginFor) -> DispatchResult { - frame_system::ensure_none(origin)?; - Ok(()) - } - - pub fn calculate_storage_root(_origin: OriginFor) -> DispatchResult { - let root = sp_io::storage::root(sp_runtime::StateVersion::V1); - sp_io::storage::set("storage_root".as_bytes(), &root); - Ok(()) - } - } - - #[pallet::inherent] - impl ProvideInherent for Pallet { - type Call = Call; - - type Error = sp_inherents::MakeFatalError<()>; - - const INHERENT_IDENTIFIER: [u8; 8] = *b"test1234"; - - fn create_inherent(_data: &InherentData) -> Option { - None - } - - fn is_inherent(call: &Self::Call) -> bool { - *call == Call::::inherent_call {} - } - } - - #[pallet::validate_unsigned] - impl ValidateUnsigned for Pallet { - type Call = Call; - - // Inherent call is accepted for being dispatched - fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { - match call { - Call::allowed_unsigned { .. } => Ok(()), - Call::inherent_call { .. } => Ok(()), - _ => Err(UnknownTransaction::NoUnsignedValidator.into()), - } - } - - // Inherent call is not validated as unsigned - fn validate_unsigned( - _source: TransactionSource, - call: &Self::Call, - ) -> TransactionValidity { - match call { - Call::allowed_unsigned { .. } => Ok(Default::default()), - _ => UnknownTransaction::NoUnsignedValidator.into(), - } - } - } - } - - frame_support::construct_runtime!( - pub enum Runtime { - System: frame_system, - Balances: pallet_balances, - TransactionPayment: pallet_transaction_payment, - Custom: custom, - } - ); - - parameter_types! { - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::builder() - .base_block(Weight::from_parts(10, 0)) - .for_class(DispatchClass::all(), |weights| weights.base_extrinsic = Weight::from_parts(5, 0)) - .for_class(DispatchClass::non_mandatory(), |weights| weights.max_total = Weight::from_parts(1024, u64::MAX).into()) - .build_or_panic(); - pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 10, - write: 100, - }; - } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] - impl frame_system::Config for Runtime { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = BlockWeights; - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; - type Hash = sp_core::H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Block = TestBlock; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = RuntimeVersion; - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; - } - - type Balance = u64; - impl pallet_balances::Config for Runtime { - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU64<1>; - type AccountStore = System; - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = ConstU32<1>; - type RuntimeHoldReason = (); - type RuntimeFreezeReason = (); - } - - parameter_types! { - pub const TransactionByteFee: Balance = 0; - } - impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; - type OperationalFeeMultiplier = ConstU8<5>; - type WeightToFee = IdentityFee; - type LengthToFee = ConstantMultiplier; - type FeeMultiplierUpdate = (); - } - impl custom::Config for Runtime {} - - pub struct RuntimeVersion; - impl frame_support::traits::Get for RuntimeVersion { - fn get() -> sp_version::RuntimeVersion { - RuntimeVersionTestValues::get().clone() - } - } - - parameter_types! { - pub static RuntimeVersionTestValues: sp_version::RuntimeVersion = - Default::default(); - } - - type SignedExtra = ( - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, - ); - type TestXt = sp_runtime::testing::TestXt; - type TestBlock = Block; - - // Will contain `true` when the custom runtime logic was called. - const CUSTOM_ON_RUNTIME_KEY: &[u8] = b":custom:on_runtime"; - - struct CustomOnRuntimeUpgrade; - impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { - fn on_runtime_upgrade() -> Weight { - sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes()); - sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode()); - System::deposit_event(frame_system::Event::CodeUpdated); - - assert_eq!(0, System::last_runtime_upgrade_spec_version()); - - Weight::from_parts(100, 0) - } - } - - type Executive = super::Executive< - Runtime, - Block, - ChainContext, - Runtime, - AllPalletsWithSystem, - CustomOnRuntimeUpgrade, - >; - - fn extra(nonce: u64, fee: Balance) -> SignedExtra { - ( - frame_system::CheckEra::from(Era::Immortal), - frame_system::CheckNonce::from(nonce), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(fee), - ) - } - - fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { - Some((who, extra(nonce, fee))) - } - - fn call_transfer(dest: u64, value: u64) -> RuntimeCall { - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) - } - - #[test] - fn balance_transfer_dispatch_works() { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 211)] } - .assimilate_storage(&mut t) - .unwrap(); - let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0)); - let weight = xt.get_dispatch_info().weight + - ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - let fee: Balance = - ::WeightToFee::weight_to_fee(&weight); - let mut t = sp_io::TestExternalities::new(t); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - let r = Executive::apply_extrinsic(xt); - assert!(r.is_ok()); - assert_eq!(>::total_balance(&1), 142 - fee); - assert_eq!(>::total_balance(&2), 69); - }); - } - - fn new_test_ext(balance_factor: Balance) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } - .assimilate_storage(&mut t) - .unwrap(); - t.into() - } - - fn new_test_ext_v0(balance_factor: Balance) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } - .assimilate_storage(&mut t) - .unwrap(); - (t, sp_runtime::StateVersion::V0).into() - } - - #[test] - fn block_import_works() { - block_import_works_inner( - new_test_ext_v0(1), - array_bytes::hex_n_into_unchecked( - "65e953676859e7a33245908af7ad3637d6861eb90416d433d485e95e2dd174a1", - ), - ); - block_import_works_inner( - new_test_ext(1), - array_bytes::hex_n_into_unchecked( - "5a19b3d6fdb7241836349fdcbe2d9df4d4f945b949d979e31ad50bff1cbcd1c2", - ), - ); - } - fn block_import_works_inner(mut ext: sp_io::TestExternalities, state_root: H256) { - ext.execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root, - extrinsics_root: array_bytes::hex_n_into_unchecked( - "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", - ), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_state_root_fails() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: [0u8; 32].into(), - extrinsics_root: array_bytes::hex_n_into_unchecked( - "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", - ), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_extrinsic_root_fails() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: array_bytes::hex_n_into_unchecked( - "75e7d8f360d375bbe91bcf8019c01ab6362448b4a89e3b329717eb9d910340e5", - ), - extrinsics_root: [0u8; 32].into(), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - fn bad_extrinsic_not_inserted() { - let mut t = new_test_ext(1); - // bad nonce check! - let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0)); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - assert_err!( - Executive::apply_extrinsic(xt), - TransactionValidityError::Invalid(InvalidTransaction::Future) - ); - assert_eq!(>::extrinsic_index(), Some(0)); - }); - } - - #[test] - fn block_weight_limit_enforced() { - let mut t = new_test_ext(10000); - // given: TestXt uses the encoded len as fixed Len: - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - let encoded = xt.encode(); - let encoded_len = encoded.len() as u64; - // on_initialize weight + base block execution weight - let block_weights = ::BlockWeights::get(); - let base_block_weight = Weight::from_parts(175, 0) + block_weights.base_block; - let limit = block_weights.get(DispatchClass::Normal).max_total.unwrap() - base_block_weight; - let num_to_exhaust_block = limit.ref_time() / (encoded_len + 5); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - // Base block execution weight + `on_initialize` weight from the custom module. - assert_eq!(>::block_weight().total(), base_block_weight); - - for nonce in 0..=num_to_exhaust_block { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { - dest: 33, - value: 0, - }), - sign_extra(1, nonce.into(), 0), - ); - let res = Executive::apply_extrinsic(xt); - if nonce != num_to_exhaust_block { - assert!(res.is_ok()); - assert_eq!( - >::block_weight().total(), - //--------------------- on_initialize + block_execution + extrinsic_base weight - Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, - ); - assert_eq!( - >::extrinsic_index(), - Some(nonce as u32 + 1) - ); - } else { - assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); - } - } - }); - } - - #[test] - fn block_weight_and_size_is_stored_per_tx() { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - let x1 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 1, 0), - ); - let x2 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 2, 0), - ); - let len = xt.clone().encode().len() as u32; - let mut t = new_test_ext(1); - t.execute_with(|| { - // Block execution weight + on_initialize weight from custom module - let base_block_weight = Weight::from_parts(175, 0) + - ::BlockWeights::get().base_block; - - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - assert_eq!(>::block_weight().total(), base_block_weight); - assert_eq!(>::all_extrinsics_len(), 0); - - assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); - assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); - assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); - - // default weight for `TestXt` == encoded length. - let extrinsic_weight = Weight::from_parts(len as u64, 0) + - ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - assert_eq!( - >::block_weight().total(), - base_block_weight + 3u64 * extrinsic_weight, - ); - assert_eq!(>::all_extrinsics_len(), 3 * len); - - let _ = >::finalize(); - // All extrinsics length cleaned on `System::finalize` - assert_eq!(>::all_extrinsics_len(), 0); - - // New Block - Executive::initialize_block(&Header::new( - 2, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - // Block weight cleaned up on `System::initialize` - assert_eq!(>::block_weight().total(), base_block_weight); - }); - } - - #[test] - fn validate_unsigned() { - let valid = TestXt::new(RuntimeCall::Custom(custom::Call::allowed_unsigned {}), None); - let invalid = TestXt::new(RuntimeCall::Custom(custom::Call::unallowed_unsigned {}), None); - let mut t = new_test_ext(1); - - t.execute_with(|| { - assert_eq!( - Executive::validate_transaction( - TransactionSource::InBlock, - valid.clone(), - Default::default(), - ), - Ok(ValidTransaction::default()), - ); - assert_eq!( - Executive::validate_transaction( - TransactionSource::InBlock, - invalid.clone(), - Default::default(), - ), - Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)), - ); - assert_eq!(Executive::apply_extrinsic(valid), Ok(Err(DispatchError::BadOrigin))); - assert_eq!( - Executive::apply_extrinsic(invalid), - Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)) - ); - }); - } - - #[test] - fn can_not_pay_for_tx_fee_on_full_lock() { - let mut t = new_test_ext(1); - t.execute_with(|| { - as fungible::MutateFreeze>::set_freeze( - &(), - &1, - 110, - ) - .unwrap(); - let xt = TestXt::new( - RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), - sign_extra(1, 0, 0), - ); - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - assert_eq!(Executive::apply_extrinsic(xt), Err(InvalidTransaction::Payment.into()),); - assert_eq!(>::total_balance(&1), 111); - }); - } - - #[test] - fn block_hooks_weight_is_stored() { - new_test_ext(1).execute_with(|| { - Executive::initialize_block(&Header::new_from_number(1)); - Executive::finalize_block(); - // NOTE: might need updates over time if new weights are introduced. - // For now it only accounts for the base block execution weight and - // the `on_initialize` weight defined in the custom test module. - assert_eq!( - >::block_weight().total(), - Weight::from_parts(175 + 175 + 10, 0) - ); - }) - } - - #[test] - fn runtime_upgraded_should_work() { - new_test_ext(1).execute_with(|| { - RuntimeVersionTestValues::mutate(|v| *v = Default::default()); - // It should be added at genesis - assert!(LastRuntimeUpgrade::::exists()); - assert!(!Executive::runtime_upgraded()); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - assert!(Executive::runtime_upgraded()); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { - spec_version: 1, - spec_name: "test".into(), - ..Default::default() - } - }); - assert!(Executive::runtime_upgraded()); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { - spec_version: 0, - impl_version: 2, - ..Default::default() - } - }); - assert!(!Executive::runtime_upgraded()); - - LastRuntimeUpgrade::::take(); - assert!(Executive::runtime_upgraded()); - }) - } - - #[test] - fn last_runtime_upgrade_was_upgraded_works() { - let test_data = vec![ - (0, "", 1, "", true), - (1, "", 1, "", false), - (1, "", 1, "test", true), - (1, "", 0, "", false), - (1, "", 0, "test", true), - ]; - - for (spec_version, spec_name, c_spec_version, c_spec_name, result) in test_data { - let current = sp_version::RuntimeVersion { - spec_version: c_spec_version, - spec_name: c_spec_name.into(), - ..Default::default() - }; - - let last = LastRuntimeUpgradeInfo { - spec_version: spec_version.into(), - spec_name: spec_name.into(), - }; - - assert_eq!(result, last.was_upgraded(¤t)); - } - } - - #[test] - fn custom_runtime_upgrade_is_called_before_modules() { - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); - assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); - assert_eq!( - Some(RuntimeVersionTestValues::get().into()), - LastRuntimeUpgrade::::get(), - ) - }); - } - - #[test] - fn event_from_runtime_upgrade_is_included() { - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - // set block number to non zero so events are not excluded - System::set_block_number(1); - - Executive::initialize_block(&Header::new( - 2, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - System::assert_last_event(frame_system::Event::::CodeUpdated.into()); - }); - } - - /// Regression test that ensures that the custom on runtime upgrade is called when executive is - /// used through the `ExecuteBlock` trait. - #[test] - fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - - let header = new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - // Reset to get the correct new genesis below. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 0, ..Default::default() } - }); - - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - >>::execute_block(Block::new(header, vec![xt])); - - assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); - assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); - }); - } - - #[test] - fn all_weights_are_recorded_correctly() { - // Reset to get the correct new genesis below. - RuntimeVersionTestValues::take(); - - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called for maximum complexity - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - let block_number = 1; - - Executive::initialize_block(&Header::new( - block_number, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - // Reset the last runtime upgrade info, to make the second call to `on_runtime_upgrade` - // succeed. - LastRuntimeUpgrade::::take(); - - // All weights that show up in the `initialize_block_impl` - let custom_runtime_upgrade_weight = CustomOnRuntimeUpgrade::on_runtime_upgrade(); - let runtime_upgrade_weight = - ::on_runtime_upgrade(); - let on_initialize_weight = - >::on_initialize(block_number); - let base_block_weight = - ::BlockWeights::get().base_block; - - // Weights are recorded correctly - assert_eq!( - frame_system::Pallet::::block_weight().total(), - custom_runtime_upgrade_weight + - runtime_upgrade_weight + - on_initialize_weight + base_block_weight, - ); - }); - } - - #[test] - fn offchain_worker_works_as_expected() { - new_test_ext(1).execute_with(|| { - let parent_hash = sp_core::H256::from([69u8; 32]); - let mut digest = Digest::default(); - digest.push(DigestItem::Seal([1, 2, 3, 4], vec![5, 6, 7, 8])); - - let header = - Header::new(1, H256::default(), H256::default(), parent_hash, digest.clone()); - - Executive::offchain_worker(&header); - - assert_eq!(digest, System::digest()); - assert_eq!(parent_hash, System::block_hash(0)); - assert_eq!(header.hash(), System::block_hash(1)); - }); - } - - #[test] - fn calculating_storage_root_twice_works() { - let call = RuntimeCall::Custom(custom::Call::calculate_storage_root {}); - let xt = TestXt::new(call, sign_extra(1, 0, 0)); - - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt])); - }); - } - - #[test] - #[should_panic(expected = "Invalid inherent position for extrinsic at index 1")] - fn invalid_inherent_position_fail() { - let xt1 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - let xt2 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); - Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt1, xt2])); - }); - } - - #[test] - fn valid_inherents_position_works() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); - - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); - Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt1, xt2])); - }); - } - - #[test] - #[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] - fn invalid_inherents_fail_block_execution() { - let xt1 = - TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), sign_extra(1, 0, 0)); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new( - Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - ), - vec![xt1], - )); - }); - } - - // Inherents are created by the runtime and don't need to be validated. - #[test] - fn inherents_fail_validate_block() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - - new_test_ext(1).execute_with(|| { - assert_eq!( - Executive::validate_transaction(TransactionSource::External, xt1, H256::random()) - .unwrap_err(), - InvalidTransaction::MandatoryValidation.into() - ); - }) - } -} diff --git a/substrate/frame/executive/src/tests.rs b/substrate/frame/executive/src/tests.rs new file mode 100644 index 00000000000..70b55f6e855 --- /dev/null +++ b/substrate/frame/executive/src/tests.rs @@ -0,0 +1,1389 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Test the `frame-executive` crate. + +use super::*; + +use sp_core::H256; +use sp_runtime::{ + generic::{DigestItem, Era}, + testing::{Block, Digest, Header}, + traits::{Block as BlockT, Header as HeaderT}, + transaction_validity::{ + InvalidTransaction, TransactionValidityError, UnknownTransaction, ValidTransaction, + }, + BuildStorage, DispatchError, +}; + +use frame_support::{ + assert_err, assert_ok, derive_impl, + migrations::MultiStepMigrator, + pallet_prelude::*, + parameter_types, + traits::{fungible, ConstU8, Currency, IsInherent}, + weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightMeter, WeightToFee}, +}; +use frame_system::{pallet_prelude::*, ChainContext, LastRuntimeUpgrade, LastRuntimeUpgradeInfo}; +use pallet_balances::Call as BalancesCall; +use pallet_transaction_payment::CurrencyAdapter; + +const TEST_KEY: &[u8] = b":test:key:"; + +#[frame_support::pallet(dev_mode)] +mod custom { + use super::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::hooks] + impl Hooks> for Pallet { + // module hooks. + // one with block number arg and one without + fn on_initialize(_: BlockNumberFor) -> Weight { + Weight::from_parts(175, 0) + } + + fn on_idle(_: BlockNumberFor, _: Weight) -> Weight { + Weight::from_parts(175, 0) + } + + fn on_poll(_: BlockNumberFor, _: &mut WeightMeter) {} + + fn on_finalize(_: BlockNumberFor) {} + + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(super::TEST_KEY, "module".as_bytes()); + Weight::from_parts(200, 0) + } + + fn offchain_worker(n: BlockNumberFor) { + assert_eq!(BlockNumberFor::::from(1u32), n); + } + } + + #[pallet::call] + impl Pallet { + pub fn some_function(origin: OriginFor) -> DispatchResult { + // NOTE: does not make any difference. + frame_system::ensure_signed(origin)?; + Ok(()) + } + + #[pallet::weight((200, DispatchClass::Operational))] + pub fn some_root_operation(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } + + pub fn some_unsigned_message(origin: OriginFor) -> DispatchResult { + frame_system::ensure_none(origin)?; + Ok(()) + } + + pub fn allowed_unsigned(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } + + pub fn unallowed_unsigned(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } + + #[pallet::weight((0, DispatchClass::Mandatory))] + pub fn inherent(origin: OriginFor) -> DispatchResult { + frame_system::ensure_none(origin)?; + Ok(()) + } + + pub fn calculate_storage_root(_origin: OriginFor) -> DispatchResult { + let root = sp_io::storage::root(sp_runtime::StateVersion::V1); + sp_io::storage::set("storage_root".as_bytes(), &root); + Ok(()) + } + } + + #[pallet::inherent] + impl ProvideInherent for Pallet { + type Call = Call; + + type Error = sp_inherents::MakeFatalError<()>; + + const INHERENT_IDENTIFIER: [u8; 8] = *b"test1234"; + + fn create_inherent(_data: &InherentData) -> Option { + None + } + + fn is_inherent(call: &Self::Call) -> bool { + *call == Call::::inherent {} + } + } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + + // Inherent call is accepted for being dispatched + fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { + match call { + Call::allowed_unsigned { .. } => Ok(()), + Call::inherent { .. } => Ok(()), + _ => Err(UnknownTransaction::NoUnsignedValidator.into()), + } + } + + // Inherent call is not validated as unsigned + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { + match call { + Call::allowed_unsigned { .. } => Ok(Default::default()), + _ => UnknownTransaction::NoUnsignedValidator.into(), + } + } + } +} + +#[frame_support::pallet(dev_mode)] +mod custom2 { + use super::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::hooks] + impl Hooks> for Pallet { + // module hooks. + // one with block number arg and one without + fn on_initialize(_: BlockNumberFor) -> Weight { + assert!( + !MockedSystemCallbacks::pre_inherent_called(), + "Pre inherent hook goes after on_initialize" + ); + + Weight::from_parts(0, 0) + } + + fn on_idle(_: BlockNumberFor, _: Weight) -> Weight { + assert!( + MockedSystemCallbacks::post_transactions_called(), + "Post transactions hook goes before after on_idle" + ); + Weight::from_parts(0, 0) + } + + fn on_finalize(_: BlockNumberFor) { + assert!( + MockedSystemCallbacks::post_transactions_called(), + "Post transactions hook goes before after on_finalize" + ); + } + + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(super::TEST_KEY, "module".as_bytes()); + Weight::from_parts(0, 0) + } + } + + #[pallet::call] + impl Pallet { + pub fn allowed_unsigned(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } + + pub fn some_call(_: OriginFor) -> DispatchResult { + assert!(MockedSystemCallbacks::post_inherent_called()); + assert!(!MockedSystemCallbacks::post_transactions_called()); + assert!(System::inherents_applied()); + + Ok(()) + } + + #[pallet::weight({0})] + pub fn optional_inherent(origin: OriginFor) -> DispatchResult { + frame_system::ensure_none(origin)?; + + assert!(MockedSystemCallbacks::pre_inherent_called()); + assert!(!MockedSystemCallbacks::post_inherent_called(), "Should not already be called"); + assert!(!System::inherents_applied()); + + Ok(()) + } + + #[pallet::weight((0, DispatchClass::Mandatory))] + pub fn inherent(origin: OriginFor) -> DispatchResult { + frame_system::ensure_none(origin)?; + + assert!(MockedSystemCallbacks::pre_inherent_called()); + assert!(!MockedSystemCallbacks::post_inherent_called(), "Should not already be called"); + assert!(!System::inherents_applied()); + + Ok(()) + } + } + + #[pallet::inherent] + impl ProvideInherent for Pallet { + type Call = Call; + + type Error = sp_inherents::MakeFatalError<()>; + + const INHERENT_IDENTIFIER: [u8; 8] = *b"test1235"; + + fn create_inherent(_data: &InherentData) -> Option { + None + } + + fn is_inherent(call: &Self::Call) -> bool { + matches!(call, Call::::inherent {} | Call::::optional_inherent {}) + } + } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + + // Inherent call is accepted for being dispatched + fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { + match call { + Call::allowed_unsigned { .. } | + Call::optional_inherent { .. } | + Call::inherent { .. } => Ok(()), + _ => Err(UnknownTransaction::NoUnsignedValidator.into()), + } + } + + // Inherent call is not validated as unsigned + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { + match call { + Call::allowed_unsigned { .. } => Ok(Default::default()), + _ => UnknownTransaction::NoUnsignedValidator.into(), + } + } + } +} + +frame_support::construct_runtime!( + pub struct Runtime + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, + Custom: custom::{Pallet, Call, ValidateUnsigned, Inherent}, + Custom2: custom2::{Pallet, Call, ValidateUnsigned, Inherent}, + } +); + +parameter_types! { + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::builder() + .base_block(Weight::from_parts(10, 0)) + .for_class(DispatchClass::all(), |weights| weights.base_extrinsic = Weight::from_parts(5, 0)) + .for_class(DispatchClass::non_mandatory(), |weights| weights.max_total = Weight::from_parts(1024, u64::MAX).into()) + .build_or_panic(); + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 10, + write: 100, + }; +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Runtime { + type BlockWeights = BlockWeights; + type RuntimeOrigin = RuntimeOrigin; + type Nonce = u64; + type RuntimeCall = RuntimeCall; + type Block = TestBlock; + type RuntimeEvent = RuntimeEvent; + type Version = RuntimeVersion; + type AccountData = pallet_balances::AccountData; + type PreInherents = MockedSystemCallbacks; + type PostInherents = MockedSystemCallbacks; + type PostTransactions = MockedSystemCallbacks; + type MultiBlockMigrator = MockedModeGetter; +} + +type Balance = u64; + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type AccountStore = System; +} + +parameter_types! { + pub const TransactionByteFee: Balance = 0; +} +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = IdentityFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = (); +} + +impl custom::Config for Runtime {} +impl custom2::Config for Runtime {} + +pub struct RuntimeVersion; +impl frame_support::traits::Get for RuntimeVersion { + fn get() -> sp_version::RuntimeVersion { + RuntimeVersionTestValues::get().clone() + } +} + +parameter_types! { + pub static RuntimeVersionTestValues: sp_version::RuntimeVersion = + Default::default(); +} + +type SignedExtra = ( + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +type TestXt = sp_runtime::testing::TestXt; +type TestBlock = Block; + +// Will contain `true` when the custom runtime logic was called. +const CUSTOM_ON_RUNTIME_KEY: &[u8] = b":custom:on_runtime"; + +struct CustomOnRuntimeUpgrade; +impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes()); + sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode()); + System::deposit_event(frame_system::Event::CodeUpdated); + + assert_eq!(0, System::last_runtime_upgrade_spec_version()); + + Weight::from_parts(100, 0) + } +} + +type Executive = super::Executive< + Runtime, + Block, + ChainContext, + Runtime, + AllPalletsWithSystem, + CustomOnRuntimeUpgrade, +>; + +parameter_types! { + pub static SystemCallbacksCalled: u32 = 0; +} + +pub struct MockedSystemCallbacks; +impl PreInherents for MockedSystemCallbacks { + fn pre_inherents() { + assert_eq!(SystemCallbacksCalled::get(), 0); + SystemCallbacksCalled::set(1); + // Change the storage to modify the root hash: + frame_support::storage::unhashed::put(b":pre_inherent", b"0"); + } +} + +impl PostInherents for MockedSystemCallbacks { + fn post_inherents() { + assert_eq!(SystemCallbacksCalled::get(), 1); + SystemCallbacksCalled::set(2); + // Change the storage to modify the root hash: + frame_support::storage::unhashed::put(b":post_inherent", b"0"); + } +} + +impl PostTransactions for MockedSystemCallbacks { + fn post_transactions() { + assert_eq!(SystemCallbacksCalled::get(), 2); + SystemCallbacksCalled::set(3); + // Change the storage to modify the root hash: + frame_support::storage::unhashed::put(b":post_transaction", b"0"); + } +} + +impl MockedSystemCallbacks { + fn pre_inherent_called() -> bool { + SystemCallbacksCalled::get() >= 1 + } + + fn post_inherent_called() -> bool { + SystemCallbacksCalled::get() >= 2 + } + + fn post_transactions_called() -> bool { + SystemCallbacksCalled::get() >= 3 + } + + fn reset() { + SystemCallbacksCalled::set(0); + frame_support::storage::unhashed::kill(b":pre_inherent"); + frame_support::storage::unhashed::kill(b":post_inherent"); + frame_support::storage::unhashed::kill(b":post_transaction"); + } +} + +parameter_types! { + pub static MbmActive: bool = false; +} + +pub struct MockedModeGetter; +impl MultiStepMigrator for MockedModeGetter { + fn ongoing() -> bool { + MbmActive::get() + } + + fn step() -> Weight { + Weight::zero() + } +} + +fn extra(nonce: u64, fee: Balance) -> SignedExtra { + ( + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(nonce), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(fee), + ) +} + +fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { + Some((who, extra(nonce, fee))) +} + +fn call_transfer(dest: u64, value: u64) -> RuntimeCall { + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) +} + +#[test] +fn balance_transfer_dispatch_works() { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 211)] } + .assimilate_storage(&mut t) + .unwrap(); + let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0)); + let weight = xt.get_dispatch_info().weight + + ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let fee: Balance = + ::WeightToFee::weight_to_fee(&weight); + let mut t = sp_io::TestExternalities::new(t); + t.execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + let r = Executive::apply_extrinsic(xt); + assert!(r.is_ok()); + assert_eq!(>::total_balance(&1), 142 - fee); + assert_eq!(>::total_balance(&2), 69); + }); +} + +fn new_test_ext(balance_factor: Balance) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } + .assimilate_storage(&mut t) + .unwrap(); + let mut ext: sp_io::TestExternalities = t.into(); + ext.execute_with(|| { + SystemCallbacksCalled::set(0); + }); + ext +} + +fn new_test_ext_v0(balance_factor: Balance) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } + .assimilate_storage(&mut t) + .unwrap(); + (t, sp_runtime::StateVersion::V0).into() +} + +#[test] +fn block_import_works() { + block_import_works_inner( + new_test_ext_v0(1), + array_bytes::hex_n_into_unchecked( + "4826d3bdf87dbbc883d2ab274cbe272f58ed94a904619b59953e48294d1142d2", + ), + ); + block_import_works_inner( + new_test_ext(1), + array_bytes::hex_n_into_unchecked( + "d6b465f5a50c9f8d5a6edc0f01d285a6b19030f097d3aaf1649b7be81649f118", + ), + ); +} +fn block_import_works_inner(mut ext: sp_io::TestExternalities, state_root: H256) { + ext.execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root, + extrinsics_root: array_bytes::hex_n_into_unchecked( + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + ), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], + }); + }); +} + +#[test] +#[should_panic] +fn block_import_of_bad_state_root_fails() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: [0u8; 32].into(), + extrinsics_root: array_bytes::hex_n_into_unchecked( + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + ), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], + }); + }); +} + +#[test] +#[should_panic] +fn block_import_of_bad_extrinsic_root_fails() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: array_bytes::hex_n_into_unchecked( + "75e7d8f360d375bbe91bcf8019c01ab6362448b4a89e3b329717eb9d910340e5", + ), + extrinsics_root: [0u8; 32].into(), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], + }); + }); +} + +#[test] +fn bad_extrinsic_not_inserted() { + let mut t = new_test_ext(1); + // bad nonce check! + let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0)); + t.execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + assert_err!( + Executive::apply_extrinsic(xt), + TransactionValidityError::Invalid(InvalidTransaction::Future) + ); + assert_eq!(>::extrinsic_index(), Some(0)); + }); +} + +#[test] +fn block_weight_limit_enforced() { + let mut t = new_test_ext(10000); + // given: TestXt uses the encoded len as fixed Len: + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let encoded = xt.encode(); + let encoded_len = encoded.len() as u64; + // on_initialize weight + base block execution weight + let block_weights = ::BlockWeights::get(); + let base_block_weight = Weight::from_parts(175, 0) + block_weights.base_block; + let limit = block_weights.get(DispatchClass::Normal).max_total.unwrap() - base_block_weight; + let num_to_exhaust_block = limit.ref_time() / (encoded_len + 5); + t.execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + // Base block execution weight + `on_initialize` weight from the custom module. + assert_eq!(>::block_weight().total(), base_block_weight); + + for nonce in 0..=num_to_exhaust_block { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, nonce.into(), 0), + ); + let res = Executive::apply_extrinsic(xt); + if nonce != num_to_exhaust_block { + assert!(res.is_ok()); + assert_eq!( + >::block_weight().total(), + //--------------------- on_initialize + block_execution + extrinsic_base weight + Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, + ); + assert_eq!( + >::extrinsic_index(), + Some(nonce as u32 + 1) + ); + } else { + assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); + } + } + }); +} + +#[test] +fn block_weight_and_size_is_stored_per_tx() { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let x1 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 1, 0), + ); + let x2 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 2, 0), + ); + let len = xt.clone().encode().len() as u32; + let mut t = new_test_ext(1); + t.execute_with(|| { + // Block execution weight + on_initialize weight from custom module + let base_block_weight = Weight::from_parts(175, 0) + + ::BlockWeights::get().base_block; + + Executive::initialize_block(&Header::new_from_number(1)); + + assert_eq!(>::block_weight().total(), base_block_weight); + assert_eq!(>::all_extrinsics_len(), 0); + + assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); + + // default weight for `TestXt` == encoded length. + let extrinsic_weight = Weight::from_parts(len as u64, 0) + + ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + assert_eq!( + >::block_weight().total(), + base_block_weight + 3u64 * extrinsic_weight, + ); + assert_eq!(>::all_extrinsics_len(), 3 * len); + + let _ = >::finalize(); + // All extrinsics length cleaned on `System::finalize` + assert_eq!(>::all_extrinsics_len(), 0); + + // Reset to a new block. + SystemCallbacksCalled::take(); + Executive::initialize_block(&Header::new_from_number(2)); + + // Block weight cleaned up on `System::initialize` + assert_eq!(>::block_weight().total(), base_block_weight); + }); +} + +#[test] +fn validate_unsigned() { + let valid = TestXt::new(RuntimeCall::Custom(custom::Call::allowed_unsigned {}), None); + let invalid = TestXt::new(RuntimeCall::Custom(custom::Call::unallowed_unsigned {}), None); + let mut t = new_test_ext(1); + + t.execute_with(|| { + assert_eq!( + Executive::validate_transaction( + TransactionSource::InBlock, + valid.clone(), + Default::default(), + ), + Ok(ValidTransaction::default()), + ); + assert_eq!( + Executive::validate_transaction( + TransactionSource::InBlock, + invalid.clone(), + Default::default(), + ), + Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)), + ); + // Need to initialize the block before applying extrinsics for the `MockedSystemCallbacks` + // check. + Executive::initialize_block(&Header::new_from_number(1)); + assert_eq!(Executive::apply_extrinsic(valid), Ok(Err(DispatchError::BadOrigin))); + assert_eq!( + Executive::apply_extrinsic(invalid), + Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)) + ); + }); +} + +#[test] +fn can_not_pay_for_tx_fee_on_full_lock() { + let mut t = new_test_ext(1); + t.execute_with(|| { + as fungible::MutateFreeze>::set_freeze(&(), &1, 110) + .unwrap(); + let xt = TestXt::new( + RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), + sign_extra(1, 0, 0), + ); + Executive::initialize_block(&Header::new_from_number(1)); + + assert_eq!(Executive::apply_extrinsic(xt), Err(InvalidTransaction::Payment.into()),); + assert_eq!(>::total_balance(&1), 111); + }); +} + +#[test] +fn block_hooks_weight_is_stored() { + new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + Executive::finalize_block(); + // NOTE: might need updates over time if new weights are introduced. + // For now it only accounts for the base block execution weight and + // the `on_initialize` weight defined in the custom test module. + assert_eq!( + >::block_weight().total(), + Weight::from_parts(175 + 175 + 10, 0) + ); + }) +} + +#[test] +fn runtime_upgraded_should_work() { + new_test_ext(1).execute_with(|| { + RuntimeVersionTestValues::mutate(|v| *v = Default::default()); + // It should be added at genesis + assert!(LastRuntimeUpgrade::::exists()); + assert!(!Executive::runtime_upgraded()); + + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + assert!(Executive::runtime_upgraded()); + + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { + spec_version: 1, + spec_name: "test".into(), + ..Default::default() + } + }); + assert!(Executive::runtime_upgraded()); + + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { + spec_version: 0, + impl_version: 2, + ..Default::default() + } + }); + assert!(!Executive::runtime_upgraded()); + + LastRuntimeUpgrade::::take(); + assert!(Executive::runtime_upgraded()); + }) +} + +#[test] +fn last_runtime_upgrade_was_upgraded_works() { + let test_data = vec![ + (0, "", 1, "", true), + (1, "", 1, "", false), + (1, "", 1, "test", true), + (1, "", 0, "", false), + (1, "", 0, "test", true), + ]; + + for (spec_version, spec_name, c_spec_version, c_spec_name, result) in test_data { + let current = sp_version::RuntimeVersion { + spec_version: c_spec_version, + spec_name: c_spec_name.into(), + ..Default::default() + }; + + let last = LastRuntimeUpgradeInfo { + spec_version: spec_version.into(), + spec_name: spec_name.into(), + }; + + assert_eq!(result, last.was_upgraded(¤t)); + } +} + +#[test] +fn custom_runtime_upgrade_is_called_before_modules() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + Executive::initialize_block(&Header::new_from_number(1)); + + assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); + assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); + assert_eq!( + Some(RuntimeVersionTestValues::get().into()), + LastRuntimeUpgrade::::get(), + ) + }); +} + +#[test] +fn event_from_runtime_upgrade_is_included() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + // set block number to non zero so events are not excluded + System::set_block_number(1); + + Executive::initialize_block(&Header::new_from_number(2)); + System::assert_last_event(frame_system::Event::::CodeUpdated.into()); + }); +} + +/// Regression test that ensures that the custom on runtime upgrade is called when executive is +/// used through the `ExecuteBlock` trait. +#[test] +fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + + let header = new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + // Let's build some fake block. + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + // Reset to get the correct new genesis below. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 0, ..Default::default() } + }); + + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + >>::execute_block(Block::new(header, vec![xt])); + + assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); + assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); + }); +} + +#[test] +fn all_weights_are_recorded_correctly() { + // Reset to get the correct new genesis below. + RuntimeVersionTestValues::take(); + + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called for maximum complexity + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + let block_number = 1; + + Executive::initialize_block(&Header::new_from_number(block_number)); + + // Reset the last runtime upgrade info, to make the second call to `on_runtime_upgrade` + // succeed. + LastRuntimeUpgrade::::take(); + MockedSystemCallbacks::reset(); + + // All weights that show up in the `initialize_block_impl` + let custom_runtime_upgrade_weight = CustomOnRuntimeUpgrade::on_runtime_upgrade(); + let runtime_upgrade_weight = + ::on_runtime_upgrade(); + let on_initialize_weight = + >::on_initialize(block_number); + let base_block_weight = ::BlockWeights::get().base_block; + + // Weights are recorded correctly + assert_eq!( + frame_system::Pallet::::block_weight().total(), + custom_runtime_upgrade_weight + + runtime_upgrade_weight + + on_initialize_weight + + base_block_weight, + ); + }); +} + +#[test] +fn offchain_worker_works_as_expected() { + new_test_ext(1).execute_with(|| { + let parent_hash = sp_core::H256::from([69u8; 32]); + let mut digest = Digest::default(); + digest.push(DigestItem::Seal([1, 2, 3, 4], vec![5, 6, 7, 8])); + + let header = Header::new(1, H256::default(), H256::default(), parent_hash, digest.clone()); + + Executive::offchain_worker(&header); + + assert_eq!(digest, System::digest()); + assert_eq!(parent_hash, System::block_hash(0)); + assert_eq!(header.hash(), System::block_hash(1)); + }); +} + +#[test] +fn calculating_storage_root_twice_works() { + let call = RuntimeCall::Custom(custom::Call::calculate_storage_root {}); + let xt = TestXt::new(call, sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt])); + }); +} + +#[test] +#[should_panic(expected = "Invalid inherent position for extrinsic at index 1")] +fn invalid_inherent_position_fail() { + let xt1 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let xt2 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} + +#[test] +fn valid_inherents_position_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} + +#[test] +#[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] +fn invalid_inherents_fail_block_execution() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), sign_extra(1, 0, 0)); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new( + Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default()), + vec![xt1], + )); + }); +} + +// Inherents are created by the runtime and don't need to be validated. +#[test] +fn inherents_fail_validate_block() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + + new_test_ext(1).execute_with(|| { + assert_eq!( + Executive::validate_transaction(TransactionSource::External, xt1, H256::random()) + .unwrap_err(), + InvalidTransaction::MandatoryValidation.into() + ); + }) +} + +/// Inherents still work while `initialize_block` forbids transactions. +#[test] +fn inherents_ok_while_exts_forbidden_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + + let header = new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + // This is not applied: + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + // Tell `initialize_block` to forbid extrinsics: + Executive::execute_block(Block::new(header, vec![xt1])); + }); +} + +/// Refuses to import blocks with transactions during `OnlyInherents` mode. +#[test] +#[should_panic = "Only inherents are allowed in this block"] +fn transactions_in_only_inherents_block_errors() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + MbmActive::set(true); + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} + +/// Same as above but no error. +#[test] +fn transactions_in_normal_block_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + // Tell `initialize_block` to forbid extrinsics: + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} + +#[test] +#[cfg(feature = "try-runtime")] +fn try_execute_block_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::try_execute_block( + Block::new(header, vec![xt1, xt2]), + true, + true, + frame_try_runtime::TryStateSelect::All, + ) + .unwrap(); + }); +} + +/// Same as `extrinsic_while_exts_forbidden_errors` but using the try-runtime function. +#[test] +#[cfg(feature = "try-runtime")] +#[should_panic = "Only inherents allowed"] +fn try_execute_tx_forbidden_errors() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + MbmActive::set(true); + Executive::try_execute_block( + Block::new(header, vec![xt1, xt2]), + true, + true, + frame_try_runtime::TryStateSelect::All, + ) + .unwrap(); + }); +} + +/// Check that `ensure_inherents_are_first` reports the correct indices. +#[test] +fn ensure_inherents_are_first_works() { + let in1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let in2 = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + // Mocked empty header: + let header = new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + assert_ok!(Runtime::ensure_inherents_are_first(&Block::new(header.clone(), vec![]),), 0); + assert_ok!( + Runtime::ensure_inherents_are_first(&Block::new(header.clone(), vec![xt2.clone()]),), + 0 + ); + assert_ok!( + Runtime::ensure_inherents_are_first(&Block::new(header.clone(), vec![in1.clone()])), + 1 + ); + assert_ok!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![in1.clone(), xt2.clone()] + ),), + 1 + ); + assert_ok!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![in2.clone(), in1.clone(), xt2.clone()] + ),), + 2 + ); + + assert_eq!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![xt2.clone(), in1.clone()] + ),), + Err(1) + ); + assert_eq!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![xt2.clone(), xt2.clone(), in1.clone()] + ),), + Err(2) + ); + assert_eq!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![xt2.clone(), xt2.clone(), xt2.clone(), in2.clone()] + ),), + Err(3) + ); + }); +} + +/// Check that block execution rejects blocks with transactions in them while MBMs are active and +/// also that all the system callbacks are called correctly. +#[test] +fn callbacks_in_block_execution_works() { + callbacks_in_block_execution_works_inner(false); + callbacks_in_block_execution_works_inner(true); +} + +fn callbacks_in_block_execution_works_inner(mbms_active: bool) { + MbmActive::set(mbms_active); + + for (n_in, n_tx) in (0..10usize).zip(0..10usize) { + let mut extrinsics = Vec::new(); + + let header = new_test_ext(10).execute_with(|| { + MockedSystemCallbacks::reset(); + Executive::initialize_block(&Header::new_from_number(1)); + assert_eq!(SystemCallbacksCalled::get(), 1); + + for i in 0..n_in { + let xt = if i % 2 == 0 { + TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None) + } else { + TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None) + }; + Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + extrinsics.push(xt); + } + + for t in 0..n_tx { + let xt = TestXt::new( + RuntimeCall::Custom2(custom2::Call::some_call {}), + sign_extra(1, t as u64, 0), + ); + // Extrinsics can be applied even when MBMs are active. Only the `execute_block` + // will reject it. + Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + extrinsics.push(xt); + } + + Executive::finalize_block() + }); + assert_eq!(SystemCallbacksCalled::get(), 3); + + new_test_ext(10).execute_with(|| { + let header = std::panic::catch_unwind(|| { + Executive::execute_block(Block::new(header, extrinsics)); + }); + + match header { + Err(e) => { + let err = e.downcast::<&str>().unwrap(); + assert_eq!(*err, "Only inherents are allowed in this block"); + assert!( + MbmActive::get() && n_tx > 0, + "Transactions should be rejected when MBMs are active" + ); + }, + Ok(_) => { + assert_eq!(SystemCallbacksCalled::get(), 3); + assert!( + !MbmActive::get() || n_tx == 0, + "MBMs should be deactivated after finalization" + ); + }, + } + }); + } +} + +#[test] +fn post_inherent_called_after_all_inherents() { + let in1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); + let xt1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::some_call {}), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(in1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + #[cfg(feature = "try-runtime")] + new_test_ext(1).execute_with(|| { + Executive::try_execute_block( + Block::new(header.clone(), vec![in1.clone(), xt1.clone()]), + true, + true, + frame_try_runtime::TryStateSelect::All, + ) + .unwrap(); + assert!(MockedSystemCallbacks::post_transactions_called()); + }); + + new_test_ext(1).execute_with(|| { + MockedSystemCallbacks::reset(); + Executive::execute_block(Block::new(header, vec![in1, xt1])); + assert!(MockedSystemCallbacks::post_transactions_called()); + }); +} + +/// Regression test for AppSec finding #40. +#[test] +fn post_inherent_called_after_all_optional_inherents() { + let in1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None); + let xt1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::some_call {}), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new_from_number(1)); + + Executive::apply_extrinsic(in1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + #[cfg(feature = "try-runtime")] + new_test_ext(1).execute_with(|| { + Executive::try_execute_block( + Block::new(header.clone(), vec![in1.clone(), xt1.clone()]), + true, + true, + frame_try_runtime::TryStateSelect::All, + ) + .unwrap(); + assert!(MockedSystemCallbacks::post_transactions_called()); + }); + + new_test_ext(1).execute_with(|| { + MockedSystemCallbacks::reset(); + Executive::execute_block(Block::new(header, vec![in1, xt1])); + assert!(MockedSystemCallbacks::post_transactions_called()); + }); +} + +#[test] +fn is_inherent_works() { + let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); + assert!(Runtime::is_inherent(&ext)); + let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None); + assert!(Runtime::is_inherent(&ext)); + + let ext = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + assert!(!Runtime::is_inherent(&ext)); + + let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::allowed_unsigned {}), None); + assert!(!Runtime::is_inherent(&ext), "Unsigned ext are not automatically inherents"); +} diff --git a/substrate/frame/migrations/Cargo.toml b/substrate/frame/migrations/Cargo.toml new file mode 100644 index 00000000000..2914aa9ea97 --- /dev/null +++ b/substrate/frame/migrations/Cargo.toml @@ -0,0 +1,64 @@ +[package] +name = "pallet-migrations" +version = "1.0.0" +description = "FRAME pallet to execute multi-block migrations." +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +docify = "0.1.14" +impl-trait-for-tuples = "0.2.2" +log = "0.4.18" +scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } + +frame-benchmarking = { default-features = false, optional = true, path = "../benchmarking" } +frame-support = { default-features = false, path = "../support" } +frame-system = { default-features = false, path = "../system" } +sp-core = { path = "../../primitives/core", default-features = false } +sp-std = { path = "../../primitives/std", default-features = false } +sp-runtime = { path = "../../primitives/runtime", default-features = false } + +[dev-dependencies] +frame-executive = { path = "../executive" } +sp-api = { path = "../../primitives/api", features = ["std"] } +sp-block-builder = { path = "../../primitives/block-builder", features = ["std"] } +sp-io = { path = "../../primitives/io", features = ["std"] } +sp-tracing = { path = "../../primitives/tracing", features = ["std"] } +sp-version = { path = "../../primitives/version", features = ["std"] } + +pretty_assertions = "1.3.0" + +[features] +default = ["std"] + +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] + +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] + +try-runtime = [ + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/substrate/frame/migrations/src/benchmarking.rs b/substrate/frame/migrations/src/benchmarking.rs new file mode 100644 index 00000000000..8ad1fa50d14 --- /dev/null +++ b/substrate/frame/migrations/src/benchmarking.rs @@ -0,0 +1,222 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use frame_benchmarking::{v2::*, BenchmarkError}; +use frame_system::{Pallet as System, RawOrigin}; +use sp_runtime::traits::One; + +fn assert_last_event(generic_event: ::RuntimeEvent) { + frame_system::Pallet::::assert_last_event(generic_event.into()); +} + +#[benchmarks] +mod benches { + use super::*; + use frame_support::traits::Hooks; + + #[benchmark] + fn onboard_new_mbms() { + T::Migrations::set_fail_after(0); // Should not be called anyway. + assert!(!Cursor::::exists()); + + #[block] + { + Pallet::::onboard_new_mbms(); + } + + assert_last_event::(Event::UpgradeStarted { migrations: 1 }.into()); + } + + #[benchmark] + fn progress_mbms_none() { + T::Migrations::set_fail_after(0); // Should not be called anyway. + assert!(!Cursor::::exists()); + + #[block] + { + Pallet::::progress_mbms(One::one()); + } + } + + /// All migrations completed. + #[benchmark] + fn exec_migration_completed() -> Result<(), BenchmarkError> { + T::Migrations::set_fail_after(0); // Should not be called anyway. + assert_eq!(T::Migrations::len(), 1, "Setup failed"); + let c = ActiveCursor { index: 1, inner_cursor: None, started_at: 0u32.into() }; + let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get()); + System::::set_block_number(1u32.into()); + + #[block] + { + Pallet::::exec_migration(c, false, &mut meter); + } + + assert_last_event::(Event::UpgradeCompleted {}.into()); + + Ok(()) + } + + /// No migration runs since it is skipped as historic. + #[benchmark] + fn exec_migration_skipped_historic() -> Result<(), BenchmarkError> { + T::Migrations::set_fail_after(0); // Should not be called anyway. + assert_eq!(T::Migrations::len(), 1, "Setup failed"); + let c = ActiveCursor { index: 0, inner_cursor: None, started_at: 0u32.into() }; + + let id: IdentifierOf = T::Migrations::nth_id(0).unwrap().try_into().unwrap(); + Historic::::insert(id, ()); + + let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get()); + System::::set_block_number(1u32.into()); + + #[block] + { + Pallet::::exec_migration(c, false, &mut meter); + } + + assert_last_event::(Event::MigrationSkipped { index: 0 }.into()); + + Ok(()) + } + + /// Advance a migration by one step. + #[benchmark] + fn exec_migration_advance() -> Result<(), BenchmarkError> { + T::Migrations::set_success_after(1); + assert_eq!(T::Migrations::len(), 1, "Setup failed"); + let c = ActiveCursor { index: 0, inner_cursor: None, started_at: 0u32.into() }; + let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get()); + System::::set_block_number(1u32.into()); + + #[block] + { + Pallet::::exec_migration(c, false, &mut meter); + } + + assert_last_event::(Event::MigrationAdvanced { index: 0, took: One::one() }.into()); + + Ok(()) + } + + /// Successfully complete a migration. + #[benchmark] + fn exec_migration_complete() -> Result<(), BenchmarkError> { + T::Migrations::set_success_after(0); + assert_eq!(T::Migrations::len(), 1, "Setup failed"); + let c = ActiveCursor { index: 0, inner_cursor: None, started_at: 0u32.into() }; + let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get()); + System::::set_block_number(1u32.into()); + + #[block] + { + Pallet::::exec_migration(c, false, &mut meter); + } + + assert_last_event::(Event::MigrationCompleted { index: 0, took: One::one() }.into()); + + Ok(()) + } + + #[benchmark] + fn exec_migration_fail() -> Result<(), BenchmarkError> { + T::Migrations::set_fail_after(0); + assert_eq!(T::Migrations::len(), 1, "Setup failed"); + let c = ActiveCursor { index: 0, inner_cursor: None, started_at: 0u32.into() }; + let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get()); + System::::set_block_number(1u32.into()); + + #[block] + { + Pallet::::exec_migration(c, false, &mut meter); + } + + assert_last_event::(Event::UpgradeFailed {}.into()); + + Ok(()) + } + + #[benchmark] + fn on_init_loop() { + T::Migrations::set_fail_after(0); // Should not be called anyway. + System::::set_block_number(1u32.into()); + Pallet::::on_runtime_upgrade(); + + #[block] + { + Pallet::::on_initialize(1u32.into()); + } + } + + #[benchmark] + fn force_set_cursor() { + #[extrinsic_call] + _(RawOrigin::Root, Some(cursor::())); + } + + #[benchmark] + fn force_set_active_cursor() { + #[extrinsic_call] + _(RawOrigin::Root, 0, None, None); + } + + #[benchmark] + fn force_onboard_mbms() { + #[extrinsic_call] + _(RawOrigin::Root); + } + + #[benchmark] + fn clear_historic(n: Linear<0, { DEFAULT_HISTORIC_BATCH_CLEAR_SIZE * 2 }>) { + let id_max_len = ::IdentifierMaxLen::get(); + assert!(id_max_len >= 4, "Precondition violated"); + + for i in 0..DEFAULT_HISTORIC_BATCH_CLEAR_SIZE * 2 { + let id = IdentifierOf::::truncate_from( + i.encode().into_iter().cycle().take(id_max_len as usize).collect::>(), + ); + + Historic::::insert(&id, ()); + } + + #[extrinsic_call] + _( + RawOrigin::Root, + HistoricCleanupSelector::Wildcard { limit: n.into(), previous_cursor: None }, + ); + } + + fn cursor() -> CursorOf { + // Note: The weight of a function can depend on the weight of reading the `inner_cursor`. + // `Cursor` is a user provided type. Now instead of requiring something like `Cursor: + // From`, we instead rely on the fact that it is MEL and the PoV benchmarking will + // therefore already take the MEL bound, even when the cursor in storage is `None`. + MigrationCursor::Active(ActiveCursor { + index: u32::MAX, + inner_cursor: None, + started_at: 0u32.into(), + }) + } + + // Implements a test for each benchmark. Execute with: + // `cargo test -p pallet-migrations --features runtime-benchmarks`. + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/substrate/frame/migrations/src/lib.rs b/substrate/frame/migrations/src/lib.rs new file mode 100644 index 00000000000..cd57d89f440 --- /dev/null +++ b/substrate/frame/migrations/src/lib.rs @@ -0,0 +1,746 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#![deny(missing_docs)] +#![deny(rustdoc::broken_intra_doc_links)] + +//! # `pallet-migrations` +//! +//! Provides multi block migrations for FRAME runtimes. +//! +//! ## Overview +//! +//! The pallet takes care of executing a batch of multi-step migrations over multiple blocks. The +//! process starts on each runtime upgrade. Normal and operational transactions are paused while +//! migrations are on-going. +//! +//! ### Example +//! +//! This example demonstrates a simple mocked walk through of a basic success scenario. The pallet +//! is configured with two migrations: one succeeding after just one step, and the second one +//! succeeding after two steps. A runtime upgrade is then enacted and the block number is advanced +//! until all migrations finish executing. Afterwards, the recorded historic migrations are +//! checked and events are asserted. +#![doc = docify::embed!("substrate/frame/migrations/src/tests.rs", simple_works)] +//! +//! ## Pallet API +//! +//! See the [`pallet`] module for more information about the interfaces this pallet exposes, +//! including its configuration trait, dispatchables, storage items, events and errors. +//! +//! Otherwise noteworthy API of this pallet include its implementation of the +//! [`MultiStepMigrator`] trait. This must be plugged into +//! [`frame_system::Config::MultiBlockMigrator`] for proper function. +//! +//! The API contains some calls for emergency management. They are all prefixed with `force_` and +//! should normally not be needed. Pay special attention prior to using them. +//! +//! ### Design Goals +//! +//! 1. Must automatically execute migrations over multiple blocks. +//! 2. Must expose information about whether migrations are ongoing. +//! 3. Must respect pessimistic weight bounds of migrations. +//! 4. Must execute migrations in order. Skipping is not allowed; migrations are run on a +//! all-or-nothing basis. +//! 5. Must prevent re-execution of past migrations. +//! 6. Must provide transactional storage semantics for migrations. +//! 7. Must guarantee progress. +//! +//! ### Design +//! +//! Migrations are provided to the pallet through the associated type [`Config::Migrations`] of type +//! [`SteppedMigrations`]. This allows multiple migrations to be aggregated through a tuple. It +//! simplifies the trait bounds since all associated types of the trait must be provided by the +//! pallet. The actual progress of the pallet is stored in the [`Cursor`] storage item. This can +//! either be [`MigrationCursor::Active`] or [`MigrationCursor::Stuck`]. In the active case it +//! points to the currently active migration and stores its inner cursor. The inner cursor can then +//! be used by the migration to store its inner state and advance. Each time when the migration +//! returns `Some(cursor)`, it signals the pallet that it is not done yet. +//! The cursor is reset on each runtime upgrade. This ensures that it starts to execute at the +//! first migration in the vector. The pallets cursor is only ever incremented or set to `Stuck` +//! once it encounters an error (Goal 4). Once in the stuck state, the pallet will stay stuck until +//! it is fixed through manual governance intervention. +//! As soon as the cursor of the pallet becomes `Some(_)`; [`MultiStepMigrator::ongoing`] returns +//! `true` (Goal 2). This can be used by upstream code to possibly pause transactions. +//! In `on_initialize` the pallet will load the current migration and check whether it was already +//! executed in the past by checking for membership of its ID in the [`Historic`] set. Historic +//! migrations are skipped without causing an error. Each successfully executed migration is added +//! to this set (Goal 5). +//! This proceeds until no more migrations remain. At that point, the event `UpgradeCompleted` is +//! emitted (Goal 1). +//! The execution of each migration happens by calling [`SteppedMigration::transactional_step`]. +//! This function wraps the inner `step` function into a transactional layer to allow rollback in +//! the error case (Goal 6). +//! Weight limits must be checked by the migration itself. The pallet provides a [`WeightMeter`] for +//! that purpose. The pallet may return [`SteppedMigrationError::InsufficientWeight`] at any point. +//! In that scenario, one of two things will happen: if that migration was exclusively executed +//! in this block, and therefore required more than the maximum amount of weight possible, the +//! process becomes `Stuck`. Otherwise, one re-attempt is executed with the same logic in the next +//! block (Goal 3). Progress through the migrations is guaranteed by providing a timeout for each +//! migration via [`SteppedMigration::max_steps`]. The pallet **ONLY** guarantees progress if this +//! is set to sensible limits (Goal 7). +//! +//! ### Scenario: Governance cleanup +//! +//! Every now and then, governance can make use of the [`clear_historic`][Pallet::clear_historic] +//! call. This ensures that no old migrations pile up in the [`Historic`] set. This can be done very +//! rarely, since the storage should not grow quickly and the lookup weight does not suffer much. +//! Another possibility would be to have a synchronous single-block migration perpetually deployed +//! that cleans them up before the MBMs start. +//! +//! ### Scenario: Successful upgrade +//! +//! The standard procedure for a successful runtime upgrade can look like this: +//! 1. Migrations are configured in the `Migrations` config item. All migrations expose +//! [`max_steps`][SteppedMigration::max_steps], are error tolerant, check their weight bounds and +//! have a unique identifier. +//! 2. The runtime upgrade is enacted. An `UpgradeStarted` event is +//! followed by lots of `MigrationAdvanced` and `MigrationCompleted` events. Finally +//! `UpgradeCompleted` is emitted. +//! 3. Cleanup as described in the governance scenario be executed at any time after the migrations +//! completed. +//! +//! ### Advice: Failed upgrades +//! +//! Failed upgrades cannot be recovered from automatically and require governance intervention. Set +//! up monitoring for `UpgradeFailed` events to be made aware of any failures. The hook +//! [`FailedMigrationHandler::failed`] should be setup in a way that it allows governance to act, +//! but still prevent other transactions from interacting with the inconsistent storage state. Note +//! that this is paramount, since the inconsistent state might contain a faulty balance amount or +//! similar that could cause great harm if user transactions don't remain suspended. One way to +//! implement this would be to use the `SafeMode` or `TxPause` pallets that can prevent most user +//! interactions but still allow a whitelisted set of governance calls. +//! +//! ### Remark: Failed migrations +//! +//! Failed migrations are not added to the `Historic` set. This means that an erroneous +//! migration must be removed and fixed manually. This already applies, even before considering the +//! historic set. +//! +//! ### Remark: Transactional processing +//! +//! You can see the transactional semantics for migration steps as mostly useless, since in the +//! stuck case the state is already messed up. This just prevents it from becoming even more messed +//! up, but doesn't prevent it in the first place. + +#![cfg_attr(not(feature = "std"), no_std)] + +mod benchmarking; +mod mock; +pub mod mock_helpers; +mod tests; +pub mod weights; + +pub use pallet::*; +pub use weights::WeightInfo; + +use codec::{Decode, Encode, MaxEncodedLen}; +use core::ops::ControlFlow; +use frame_support::{ + defensive, defensive_assert, + migrations::*, + traits::Get, + weights::{Weight, WeightMeter}, + BoundedVec, +}; +use frame_system::{pallet_prelude::BlockNumberFor, Pallet as System}; +use sp_runtime::Saturating; +use sp_std::vec::Vec; + +/// Points to the next migration to execute. +#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)] +pub enum MigrationCursor { + /// Points to the currently active migration and its inner cursor. + Active(ActiveCursor), + + /// Migration got stuck and cannot proceed. This is bad. + Stuck, +} + +impl MigrationCursor { + /// Try to return self as an [`ActiveCursor`]. + pub fn as_active(&self) -> Option<&ActiveCursor> { + match self { + MigrationCursor::Active(active) => Some(active), + MigrationCursor::Stuck => None, + } + } +} + +impl From> + for MigrationCursor +{ + fn from(active: ActiveCursor) -> Self { + MigrationCursor::Active(active) + } +} + +/// Points to the currently active migration and its inner cursor. +#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)] +pub struct ActiveCursor { + /// The index of the migration in the MBM tuple. + pub index: u32, + /// The cursor of the migration that is referenced by `index`. + pub inner_cursor: Option, + /// The block number that the migration started at. + /// + /// This is used to calculate how many blocks it took. + pub started_at: BlockNumber, +} + +impl ActiveCursor { + /// Advance the overarching cursor to the next migration. + pub(crate) fn goto_next_migration(&mut self, current_block: BlockNumber) { + self.index.saturating_inc(); + self.inner_cursor = None; + self.started_at = current_block; + } +} + +/// How to clear the records of historic migrations. +#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode, scale_info::TypeInfo)] +pub enum HistoricCleanupSelector { + /// Clear exactly these entries. + /// + /// This is the advised way of doing it. + Specific(Vec), + + /// Clear up to this many entries + Wildcard { + /// How many should be cleared in this call at most. + limit: Option, + /// The cursor that was emitted from any previous `HistoricCleared`. + /// + /// Does not need to be passed when clearing the first batch. + previous_cursor: Option>, + }, +} + +/// The default number of entries that should be cleared by a `HistoricCleanupSelector::Wildcard`. +/// +/// The caller can explicitly specify a higher amount. Benchmarks are run with twice this value. +const DEFAULT_HISTORIC_BATCH_CLEAR_SIZE: u32 = 128; + +impl HistoricCleanupSelector { + /// The maximal number of entries that this will remove. + /// + /// Needed for weight calculation. + pub fn limit(&self) -> u32 { + match self { + Self::Specific(ids) => ids.len() as u32, + Self::Wildcard { limit, .. } => limit.unwrap_or(DEFAULT_HISTORIC_BATCH_CLEAR_SIZE), + } + } +} + +/// Convenience alias for [`MigrationCursor`]. +pub type CursorOf = MigrationCursor, BlockNumberFor>; + +/// Convenience alias for the raw inner cursor of a migration. +pub type RawCursorOf = BoundedVec::CursorMaxLen>; + +/// Convenience alias for the identifier of a migration. +pub type IdentifierOf = BoundedVec::IdentifierMaxLen>; + +/// Convenience alias for [`ActiveCursor`]. +pub type ActiveCursorOf = ActiveCursor, BlockNumberFor>; + +/// Trait for a tuple of No-OP migrations with one element. +pub trait MockedMigrations: SteppedMigrations { + /// The migration should fail after `n` steps. + fn set_fail_after(n: u32); + /// The migration should succeed after `n` steps. + fn set_success_after(n: u32); +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type of the runtime. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// All the multi-block migrations to run. + /// + /// Should only be updated in a runtime-upgrade once all the old migrations have completed. + /// (Check that [`Cursor`] is `None`). + #[cfg(not(feature = "runtime-benchmarks"))] + type Migrations: SteppedMigrations; + + /// Mocked migrations for benchmarking only. + /// + /// Should be configured to [`crate::mock_helpers::MockedMigrations`] in benchmarks. + #[cfg(feature = "runtime-benchmarks")] + type Migrations: MockedMigrations; + + /// The maximal length of an encoded cursor. + /// + /// A good default needs to selected such that no migration will ever have a cursor with MEL + /// above this limit. This is statically checked in `integrity_test`. + #[pallet::constant] + type CursorMaxLen: Get; + + /// The maximal length of an encoded identifier. + /// + /// A good default needs to selected such that no migration will ever have an identifier + /// with MEL above this limit. This is statically checked in `integrity_test`. + #[pallet::constant] + type IdentifierMaxLen: Get; + + /// Notifications for status updates of a runtime upgrade. + /// + /// Could be used to pause XCM etc. + type MigrationStatusHandler: MigrationStatusHandler; + + /// Handler for failed migrations. + type FailedMigrationHandler: FailedMigrationHandler; + + /// The maximum weight to spend each block to execute migrations. + type MaxServiceWeight: Get; + + /// Weight information for the calls and functions of this pallet. + type WeightInfo: WeightInfo; + } + + /// The currently active migration to run and its cursor. + /// + /// `None` indicates that no migration is running. + #[pallet::storage] + pub type Cursor = StorageValue<_, CursorOf, OptionQuery>; + + /// Set of all successfully executed migrations. + /// + /// This is used as blacklist, to not re-execute migrations that have not been removed from the + /// codebase yet. Governance can regularly clear this out via `clear_historic`. + #[pallet::storage] + pub type Historic = StorageMap<_, Twox64Concat, IdentifierOf, (), OptionQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// A Runtime upgrade started. + /// + /// Its end is indicated by `UpgradeCompleted` or `UpgradeFailed`. + UpgradeStarted { + /// The number of migrations that this upgrade contains. + /// + /// This can be used to design a progress indicator in combination with counting the + /// `MigrationCompleted` and `MigrationSkipped` events. + migrations: u32, + }, + /// The current runtime upgrade completed. + /// + /// This implies that all of its migrations completed successfully as well. + UpgradeCompleted, + /// Runtime upgrade failed. + /// + /// This is very bad and will require governance intervention. + UpgradeFailed, + /// A migration was skipped since it was already executed in the past. + MigrationSkipped { + /// The index of the skipped migration within the [`Config::Migrations`] list. + index: u32, + }, + /// A migration progressed. + MigrationAdvanced { + /// The index of the migration within the [`Config::Migrations`] list. + index: u32, + /// The number of blocks that this migration took so far. + took: BlockNumberFor, + }, + /// A Migration completed. + MigrationCompleted { + /// The index of the migration within the [`Config::Migrations`] list. + index: u32, + /// The number of blocks that this migration took so far. + took: BlockNumberFor, + }, + /// A Migration failed. + /// + /// This implies that the whole upgrade failed and governance intervention is required. + MigrationFailed { + /// The index of the migration within the [`Config::Migrations`] list. + index: u32, + /// The number of blocks that this migration took so far. + took: BlockNumberFor, + }, + /// The set of historical migrations has been cleared. + HistoricCleared { + /// Should be passed to `clear_historic` in a successive call. + next_cursor: Option>, + }, + } + + #[pallet::error] + pub enum Error { + /// The operation cannot complete since some MBMs are ongoing. + Ongoing, + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_runtime_upgrade() -> Weight { + Self::onboard_new_mbms() + } + + #[cfg(feature = "std")] + fn integrity_test() { + // Check that the migrations tuple is legit. + frame_support::assert_ok!(T::Migrations::integrity_test()); + + // Very important! Ensure that the pallet is configured in `System::Config`. + { + assert!(!Cursor::::exists(), "Externalities storage should be clean"); + assert!(!::MultiBlockMigrator::ongoing()); + + Cursor::::put(MigrationCursor::Stuck); + assert!(::MultiBlockMigrator::ongoing()); + + Cursor::::kill(); + } + + // The per-block service weight is sane. + #[cfg(not(test))] + { + let want = T::MaxServiceWeight::get(); + let max = ::BlockWeights::get().max_block; + + assert!(want.all_lte(max), "Service weight is larger than a block: {want} > {max}",); + } + + // Cursor MEL + { + let mel = T::Migrations::cursor_max_encoded_len(); + let max_mel = T::CursorMaxLen::get() as usize; + assert!( + mel <= max_mel, + "A Cursor is not guaranteed to fit into the storage: {mel} > {max_mel}", + ); + } + + // Identifier MEL + { + let mel = T::Migrations::identifier_max_encoded_len(); + let max_mel = T::IdentifierMaxLen::get() as usize; + assert!( + mel <= max_mel, + "An Identifier is not guaranteed to fit into the storage: {mel} > {max_mel}", + ); + } + } + } + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + /// Allows root to set a cursor to forcefully start, stop or forward the migration process. + /// + /// Should normally not be needed and is only in place as emergency measure. Note that + /// restarting the migration process in this manner will not call the + /// [`MigrationStatusHandler::started`] hook or emit an `UpgradeStarted` event. + #[pallet::call_index(0)] + pub fn force_set_cursor( + origin: OriginFor, + cursor: Option>, + ) -> DispatchResult { + ensure_root(origin)?; + + Cursor::::set(cursor); + + Ok(()) + } + + /// Allows root to set an active cursor to forcefully start/forward the migration process. + /// + /// This is an edge-case version of [`Self::force_set_cursor`] that allows to set the + /// `started_at` value to the next block number. Otherwise this would not be possible, since + /// `force_set_cursor` takes an absolute block number. Setting `started_at` to `None` + /// indicates that the current block number plus one should be used. + #[pallet::call_index(1)] + pub fn force_set_active_cursor( + origin: OriginFor, + index: u32, + inner_cursor: Option>, + started_at: Option>, + ) -> DispatchResult { + ensure_root(origin)?; + + let started_at = started_at.unwrap_or( + System::::block_number().saturating_add(sp_runtime::traits::One::one()), + ); + Cursor::::put(MigrationCursor::Active(ActiveCursor { + index, + inner_cursor, + started_at, + })); + + Ok(()) + } + + /// Forces the onboarding of the migrations. + /// + /// This process happens automatically on a runtime upgrade. It is in place as an emergency + /// measurement. The cursor needs to be `None` for this to succeed. + #[pallet::call_index(2)] + pub fn force_onboard_mbms(origin: OriginFor) -> DispatchResult { + ensure_root(origin)?; + + ensure!(!Cursor::::exists(), Error::::Ongoing); + Self::onboard_new_mbms(); + + Ok(()) + } + + /// Clears the `Historic` set. + /// + /// `map_cursor` must be set to the last value that was returned by the + /// `HistoricCleared` event. The first time `None` can be used. `limit` must be chosen in a + /// way that will result in a sensible weight. + #[pallet::call_index(3)] + #[pallet::weight(T::WeightInfo::clear_historic(selector.limit()))] + pub fn clear_historic( + origin: OriginFor, + selector: HistoricCleanupSelector>, + ) -> DispatchResult { + ensure_root(origin)?; + + match &selector { + HistoricCleanupSelector::Specific(ids) => { + for id in ids { + Historic::::remove(id); + } + Self::deposit_event(Event::HistoricCleared { next_cursor: None }); + }, + HistoricCleanupSelector::Wildcard { previous_cursor, .. } => { + let next = Historic::::clear(selector.limit(), previous_cursor.as_deref()); + Self::deposit_event(Event::HistoricCleared { next_cursor: next.maybe_cursor }); + }, + } + + Ok(()) + } + } +} + +impl Pallet { + /// Onboard all new Multi-Block-Migrations and start the process of executing them. + /// + /// Should only be called once all previous migrations completed. + fn onboard_new_mbms() -> Weight { + if let Some(cursor) = Cursor::::get() { + log::error!("Ongoing migrations interrupted - chain stuck"); + + let maybe_index = cursor.as_active().map(|c| c.index); + Self::upgrade_failed(maybe_index); + return T::WeightInfo::onboard_new_mbms() + } + + let migrations = T::Migrations::len(); + log::debug!("Onboarding {migrations} new MBM migrations"); + + if migrations > 0 { + // Set the cursor to the first migration: + Cursor::::set(Some( + ActiveCursor { + index: 0, + inner_cursor: None, + started_at: System::::block_number(), + } + .into(), + )); + Self::deposit_event(Event::UpgradeStarted { migrations }); + T::MigrationStatusHandler::started(); + } + + T::WeightInfo::onboard_new_mbms() + } + + /// Tries to make progress on the Multi-Block-Migrations process. + fn progress_mbms(n: BlockNumberFor) -> Weight { + let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get()); + meter.consume(T::WeightInfo::progress_mbms_none()); + + let mut cursor = match Cursor::::get() { + None => { + log::trace!("[Block {n:?}] Waiting for cursor to become `Some`."); + return meter.consumed() + }, + Some(MigrationCursor::Active(cursor)) => { + log::debug!("Progressing MBM #{}", cursor.index); + cursor + }, + Some(MigrationCursor::Stuck) => { + log::error!("Migration stuck. Governance intervention required."); + return meter.consumed() + }, + }; + debug_assert!(Self::ongoing()); + + // The limit here is a defensive measure to prevent an infinite loop. It expresses that we + // allow no more than 8 MBMs to finish in a single block. This should be harmless, since we + // generally expect *Multi*-Block-Migrations to take *multiple* blocks. + for i in 0..8 { + match Self::exec_migration(cursor, i == 0, &mut meter) { + None => return meter.consumed(), + Some(ControlFlow::Continue(next_cursor)) => { + cursor = next_cursor; + }, + Some(ControlFlow::Break(last_cursor)) => { + cursor = last_cursor; + break + }, + } + } + + Cursor::::set(Some(cursor.into())); + + meter.consumed() + } + + /// Try to make progress on the current migration. + /// + /// Returns whether processing should continue or break for this block. The return value means: + /// - `None`: The migration process is completely finished. + /// - `ControlFlow::Break`: Continue in the *next* block with the given cursor. + /// - `ControlFlow::Continue`: Continue in the *current* block with the given cursor. + fn exec_migration( + mut cursor: ActiveCursorOf, + is_first: bool, + meter: &mut WeightMeter, + ) -> Option, ActiveCursorOf>> { + // The differences between the single branches' weights is not that big. And since we do + // only one step per block, we can just use the maximum instead of more precise accounting. + if meter.try_consume(Self::exec_migration_max_weight()).is_err() { + defensive_assert!(!is_first, "There should be enough weight to do this at least once"); + return Some(ControlFlow::Break(cursor)) + } + + let Some(id) = T::Migrations::nth_id(cursor.index) else { + // No more migrations in the tuple - we are done. + defensive_assert!(cursor.index == T::Migrations::len(), "Inconsistent MBMs tuple"); + Self::deposit_event(Event::UpgradeCompleted); + Cursor::::kill(); + T::MigrationStatusHandler::completed(); + return None; + }; + + let Ok(bounded_id): Result, _> = id.try_into() else { + defensive!("integrity_test ensures that all identifiers' MEL bounds fit into CursorMaxLen; qed."); + Self::upgrade_failed(Some(cursor.index)); + return None + }; + + if Historic::::contains_key(&bounded_id) { + Self::deposit_event(Event::MigrationSkipped { index: cursor.index }); + cursor.goto_next_migration(System::::block_number()); + return Some(ControlFlow::Continue(cursor)) + } + + let max_steps = T::Migrations::nth_max_steps(cursor.index); + let next_cursor = T::Migrations::nth_transactional_step( + cursor.index, + cursor.inner_cursor.clone().map(|c| c.into_inner()), + meter, + ); + let Some((max_steps, next_cursor)) = max_steps.zip(next_cursor) else { + defensive!("integrity_test ensures that the tuple is valid; qed"); + Self::upgrade_failed(Some(cursor.index)); + return None + }; + + let took = System::::block_number().saturating_sub(cursor.started_at); + match next_cursor { + Ok(Some(next_cursor)) => { + let Ok(bound_next_cursor) = next_cursor.try_into() else { + defensive!("The integrity check ensures that all cursors' MEL bound fits into CursorMaxLen; qed"); + Self::upgrade_failed(Some(cursor.index)); + return None + }; + + Self::deposit_event(Event::MigrationAdvanced { index: cursor.index, took }); + cursor.inner_cursor = Some(bound_next_cursor); + + if max_steps.map_or(false, |max| took > max.into()) { + Self::deposit_event(Event::MigrationFailed { index: cursor.index, took }); + Self::upgrade_failed(Some(cursor.index)); + None + } else { + // A migration cannot progress more than one step per block, we therefore break. + Some(ControlFlow::Break(cursor)) + } + }, + Ok(None) => { + // A migration is done when it returns cursor `None`. + Self::deposit_event(Event::MigrationCompleted { index: cursor.index, took }); + Historic::::insert(&bounded_id, ()); + cursor.goto_next_migration(System::::block_number()); + Some(ControlFlow::Continue(cursor)) + }, + Err(SteppedMigrationError::InsufficientWeight { required }) => { + if is_first || required.any_gt(meter.limit()) { + Self::deposit_event(Event::MigrationFailed { index: cursor.index, took }); + Self::upgrade_failed(Some(cursor.index)); + None + } else { + // Retry and hope that there is more weight in the next block. + Some(ControlFlow::Break(cursor)) + } + }, + Err(SteppedMigrationError::InvalidCursor | SteppedMigrationError::Failed) => { + Self::deposit_event(Event::MigrationFailed { index: cursor.index, took }); + Self::upgrade_failed(Some(cursor.index)); + None + }, + } + } + + /// Fail the current runtime upgrade, caused by `migration`. + fn upgrade_failed(migration: Option) { + use FailedMigrationHandling::*; + Self::deposit_event(Event::UpgradeFailed); + + match T::FailedMigrationHandler::failed(migration) { + KeepStuck => Cursor::::set(Some(MigrationCursor::Stuck)), + ForceUnstuck => Cursor::::kill(), + Ignore => {}, + } + } + + fn exec_migration_max_weight() -> Weight { + T::WeightInfo::exec_migration_complete() + .max(T::WeightInfo::exec_migration_completed()) + .max(T::WeightInfo::exec_migration_skipped_historic()) + .max(T::WeightInfo::exec_migration_advance()) + .max(T::WeightInfo::exec_migration_fail()) + } +} + +impl MultiStepMigrator for Pallet { + fn ongoing() -> bool { + Cursor::::exists() + } + + fn step() -> Weight { + Self::progress_mbms(System::::block_number()) + } +} diff --git a/substrate/frame/migrations/src/mock.rs b/substrate/frame/migrations/src/mock.rs new file mode 100644 index 00000000000..37292647554 --- /dev/null +++ b/substrate/frame/migrations/src/mock.rs @@ -0,0 +1,163 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Mocked runtime for testing the migrations pallet. + +#![cfg(test)] + +use crate::{mock_helpers::*, Event, Historic}; + +use frame_support::{ + derive_impl, + migrations::*, + traits::{OnFinalize, OnInitialize}, + weights::Weight, +}; +use frame_system::EventRecord; +use sp_core::{ConstU32, H256}; + +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test { + System: frame_system, + Migrations: crate, + } +); + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Test { + type Block = Block; + type PalletInfo = PalletInfo; + type MultiBlockMigrator = Migrations; +} + +frame_support::parameter_types! { + pub const MaxServiceWeight: Weight = Weight::MAX.div(10); +} + +impl crate::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Migrations = MockedMigrations; + type CursorMaxLen = ConstU32<65_536>; + type IdentifierMaxLen = ConstU32<256>; + type MigrationStatusHandler = MockedMigrationStatusHandler; + type FailedMigrationHandler = MockedFailedMigrationHandler; + type MaxServiceWeight = MaxServiceWeight; + type WeightInfo = (); +} + +frame_support::parameter_types! { + /// The number of started upgrades. + pub static UpgradesStarted: u32 = 0; + /// The number of completed upgrades. + pub static UpgradesCompleted: u32 = 0; + /// The migrations that failed. + pub static UpgradesFailed: Vec> = vec![]; + /// Return value of [`MockedFailedMigrationHandler::failed`]. + pub static FailedUpgradeResponse: FailedMigrationHandling = FailedMigrationHandling::KeepStuck; +} + +/// Records all started and completed upgrades in `UpgradesStarted` and `UpgradesCompleted`. +pub struct MockedMigrationStatusHandler; +impl MigrationStatusHandler for MockedMigrationStatusHandler { + fn started() { + log::info!("MigrationStatusHandler started"); + UpgradesStarted::mutate(|v| *v += 1); + } + + fn completed() { + log::info!("MigrationStatusHandler completed"); + UpgradesCompleted::mutate(|v| *v += 1); + } +} + +/// Records all failed upgrades in `UpgradesFailed`. +pub struct MockedFailedMigrationHandler; +impl FailedMigrationHandler for MockedFailedMigrationHandler { + fn failed(migration: Option) -> FailedMigrationHandling { + UpgradesFailed::mutate(|v| v.push(migration)); + let res = FailedUpgradeResponse::get(); + log::error!("FailedMigrationHandler failed at: {migration:?}, handling as {res:?}"); + res + } +} + +/// Returns the number of `(started, completed, failed)` upgrades and resets their numbers. +pub fn upgrades_started_completed_failed() -> (u32, u32, u32) { + (UpgradesStarted::take(), UpgradesCompleted::take(), UpgradesFailed::take().len() as u32) +} + +/// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + sp_io::TestExternalities::new(Default::default()) +} + +/// Run this closure in test externalities. +pub fn test_closure(f: impl FnOnce() -> R) -> R { + let mut ext = new_test_ext(); + ext.execute_with(f) +} + +pub fn run_to_block(n: u32) { + while System::block_number() < n as u64 { + log::debug!("Block {}", System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Migrations::on_initialize(System::block_number()); + // Executive calls this: + ::step(); + + Migrations::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + } +} + +/// Returns the historic migrations, sorted by their identifier. +pub fn historic() -> Vec { + let mut historic = Historic::::iter_keys().collect::>(); + historic.sort(); + historic +} + +// Traits to make using events less insufferable: +pub trait IntoRecord { + fn into_record(self) -> EventRecord<::RuntimeEvent, H256>; +} + +impl IntoRecord for Event { + fn into_record(self) -> EventRecord<::RuntimeEvent, H256> { + let re: ::RuntimeEvent = self.into(); + EventRecord { phase: frame_system::Phase::Initialization, event: re, topics: vec![] } + } +} + +pub trait IntoRecords { + fn into_records(self) -> Vec::RuntimeEvent, H256>>; +} + +impl IntoRecords for Vec { + fn into_records(self) -> Vec::RuntimeEvent, H256>> { + self.into_iter().map(|e| e.into_record()).collect() + } +} + +pub fn assert_events(events: Vec) { + pretty_assertions::assert_eq!(events.into_records(), System::events()); + System::reset_events(); +} diff --git a/substrate/frame/migrations/src/mock_helpers.rs b/substrate/frame/migrations/src/mock_helpers.rs new file mode 100644 index 00000000000..c5e23efb4e3 --- /dev/null +++ b/substrate/frame/migrations/src/mock_helpers.rs @@ -0,0 +1,142 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Test helpers for internal and external usage. + +#![allow(missing_docs)] + +use codec::{Decode, Encode}; +use frame_support::{ + migrations::*, + weights::{Weight, WeightMeter}, +}; +use sp_core::ConstU32; +use sp_runtime::BoundedVec; +use sp_std::{vec, vec::Vec}; + +/// Opaque identifier of a migration. +pub type MockedIdentifier = BoundedVec>; + +/// How a mocked migration should behave. +#[derive(Debug, Clone, Copy, Encode, Decode)] +pub enum MockedMigrationKind { + /// Succeed after its number of steps elapsed. + SucceedAfter, + /// Fail after its number of steps elapsed. + FailAfter, + /// Never terminate. + TimeoutAfter, + /// Cause an [`SteppedMigrationError::InsufficientWeight`] error after its number of steps + /// elapsed. + HighWeightAfter(Weight), +} +use MockedMigrationKind::*; // C style + +/// Creates a migration identifier with a specific `kind` and `steps`. +pub fn mocked_id(kind: MockedMigrationKind, steps: u32) -> MockedIdentifier { + (b"MockedMigration", kind, steps).encode().try_into().unwrap() +} + +frame_support::parameter_types! { + /// The configs for the migrations to run. + storage MIGRATIONS: Vec<(MockedMigrationKind, u32)> = vec![]; +} + +/// Allows to set the migrations to run at runtime instead of compile-time. +/// +/// It achieves this by using the storage to store the migrations to run. +pub struct MockedMigrations; +impl SteppedMigrations for MockedMigrations { + fn len() -> u32 { + MIGRATIONS::get().len() as u32 + } + + fn nth_id(n: u32) -> Option> { + let k = MIGRATIONS::get().get(n as usize).copied(); + k.map(|(kind, steps)| mocked_id(kind, steps).into_inner()) + } + + fn nth_step( + n: u32, + cursor: Option>, + _meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>> { + let (kind, steps) = MIGRATIONS::get()[n as usize]; + + let mut count: u32 = + cursor.as_ref().and_then(|c| Decode::decode(&mut &c[..]).ok()).unwrap_or(0); + log::debug!("MockedMigration: Step {}", count); + if count != steps || matches!(kind, TimeoutAfter) { + count += 1; + return Some(Ok(Some(count.encode()))) + } + + Some(match kind { + SucceedAfter => { + log::debug!("MockedMigration: Succeeded after {} steps", count); + Ok(None) + }, + HighWeightAfter(required) => { + log::debug!("MockedMigration: Not enough weight after {} steps", count); + Err(SteppedMigrationError::InsufficientWeight { required }) + }, + FailAfter => { + log::debug!("MockedMigration: Failed after {} steps", count); + Err(SteppedMigrationError::Failed) + }, + TimeoutAfter => unreachable!(), + }) + } + + fn nth_transactional_step( + n: u32, + cursor: Option>, + meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>> { + // This is a hack but should be fine. We dont need it in testing. + Self::nth_step(n, cursor, meter) + } + + fn nth_max_steps(n: u32) -> Option> { + MIGRATIONS::get().get(n as usize).map(|(_, s)| Some(*s)) + } + + fn cursor_max_encoded_len() -> usize { + 65_536 + } + + fn identifier_max_encoded_len() -> usize { + 256 + } +} + +impl MockedMigrations { + /// Set the migrations to run. + pub fn set(migrations: Vec<(MockedMigrationKind, u32)>) { + MIGRATIONS::set(&migrations); + } +} + +impl crate::MockedMigrations for MockedMigrations { + fn set_fail_after(steps: u32) { + MIGRATIONS::set(&vec![(FailAfter, steps)]); + } + + fn set_success_after(steps: u32) { + MIGRATIONS::set(&vec![(SucceedAfter, steps)]); + } +} diff --git a/substrate/frame/migrations/src/tests.rs b/substrate/frame/migrations/src/tests.rs new file mode 100644 index 00000000000..9c9043d37a6 --- /dev/null +++ b/substrate/frame/migrations/src/tests.rs @@ -0,0 +1,335 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#![cfg(test)] + +use crate::{ + mock::{Test as T, *}, + mock_helpers::{MockedMigrationKind::*, *}, + Cursor, Event, FailedMigrationHandling, MigrationCursor, +}; +use frame_support::{pallet_prelude::Weight, traits::OnRuntimeUpgrade}; + +#[docify::export] +#[test] +fn simple_works() { + use Event::*; + test_closure(|| { + // Add three migrations, each taking one block longer than the previous. + MockedMigrations::set(vec![(SucceedAfter, 0), (SucceedAfter, 1), (SucceedAfter, 2)]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(10); + + // Check that the executed migrations are recorded in `Historical`. + assert_eq!( + historic(), + vec![ + mocked_id(SucceedAfter, 0), + mocked_id(SucceedAfter, 1), + mocked_id(SucceedAfter, 2), + ] + ); + + // Check that we got all events. + assert_events(vec![ + UpgradeStarted { migrations: 3 }, + MigrationCompleted { index: 0, took: 1 }, + MigrationAdvanced { index: 1, took: 0 }, + MigrationCompleted { index: 1, took: 1 }, + MigrationAdvanced { index: 2, took: 0 }, + MigrationAdvanced { index: 2, took: 1 }, + MigrationCompleted { index: 2, took: 2 }, + UpgradeCompleted, + ]); + }); +} + +#[test] +fn failing_migration_sets_cursor_to_stuck() { + test_closure(|| { + FailedUpgradeResponse::set(FailedMigrationHandling::KeepStuck); + MockedMigrations::set(vec![(FailAfter, 2)]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(10); + + // Failed migrations are not recorded in `Historical`. + assert!(historic().is_empty()); + // Check that we got all events. + assert_events(vec![ + Event::UpgradeStarted { migrations: 1 }, + Event::MigrationAdvanced { index: 0, took: 1 }, + Event::MigrationAdvanced { index: 0, took: 2 }, + Event::MigrationFailed { index: 0, took: 3 }, + Event::UpgradeFailed, + ]); + + // Check that the handler was called correctly. + assert_eq!(UpgradesStarted::take(), 1); + assert_eq!(UpgradesCompleted::take(), 0); + assert_eq!(UpgradesFailed::take(), vec![Some(0)]); + + assert_eq!(Cursor::::get(), Some(MigrationCursor::Stuck), "Must stuck the chain"); + }); +} + +#[test] +fn failing_migration_force_unstuck_works() { + test_closure(|| { + FailedUpgradeResponse::set(FailedMigrationHandling::ForceUnstuck); + MockedMigrations::set(vec![(FailAfter, 2)]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(10); + + // Failed migrations are not recorded in `Historical`. + assert!(historic().is_empty()); + // Check that we got all events. + assert_events(vec![ + Event::UpgradeStarted { migrations: 1 }, + Event::MigrationAdvanced { index: 0, took: 1 }, + Event::MigrationAdvanced { index: 0, took: 2 }, + Event::MigrationFailed { index: 0, took: 3 }, + Event::UpgradeFailed, + ]); + + // Check that the handler was called correctly. + assert_eq!(UpgradesStarted::take(), 1); + assert_eq!(UpgradesCompleted::take(), 0); + assert_eq!(UpgradesFailed::take(), vec![Some(0)]); + + assert!(Cursor::::get().is_none(), "Must unstuck the chain"); + }); +} + +/// A migration that reports not getting enough weight errors if it is the first one to run in that +/// block. +#[test] +fn high_weight_migration_singular_fails() { + test_closure(|| { + MockedMigrations::set(vec![(HighWeightAfter(Weight::zero()), 2)]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(10); + + // Failed migrations are not recorded in `Historical`. + assert!(historic().is_empty()); + // Check that we got all events. + assert_events(vec![ + Event::UpgradeStarted { migrations: 1 }, + Event::MigrationAdvanced { index: 0, took: 1 }, + Event::MigrationAdvanced { index: 0, took: 2 }, + Event::MigrationFailed { index: 0, took: 3 }, + Event::UpgradeFailed, + ]); + + // Check that the handler was called correctly. + assert_eq!(upgrades_started_completed_failed(), (1, 0, 1)); + assert_eq!(Cursor::::get(), Some(MigrationCursor::Stuck)); + }); +} + +/// A migration that reports of not getting enough weight is retried once, if it is not the first +/// one to run in a block. +#[test] +fn high_weight_migration_retries_once() { + test_closure(|| { + MockedMigrations::set(vec![(SucceedAfter, 0), (HighWeightAfter(Weight::zero()), 0)]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(10); + + assert_eq!(historic(), vec![mocked_id(SucceedAfter, 0)]); + // Check that we got all events. + assert_events::>(vec![ + Event::UpgradeStarted { migrations: 2 }, + Event::MigrationCompleted { index: 0, took: 1 }, + // `took=1` means that it was retried once. + Event::MigrationFailed { index: 1, took: 1 }, + Event::UpgradeFailed, + ]); + + // Check that the handler was called correctly. + assert_eq!(upgrades_started_completed_failed(), (1, 0, 1)); + assert_eq!(Cursor::::get(), Some(MigrationCursor::Stuck)); + }); +} + +/// If a migration uses more weight than the limit, then it will not retry but fail even when it is +/// not the first one in the block. +// Note: Same as `high_weight_migration_retries_once` but with different required weight for the +// migration. +#[test] +fn high_weight_migration_permanently_overweight_fails() { + test_closure(|| { + MockedMigrations::set(vec![(SucceedAfter, 0), (HighWeightAfter(Weight::MAX), 0)]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(10); + + assert_eq!(historic(), vec![mocked_id(SucceedAfter, 0)]); + // Check that we got all events. + assert_events::>(vec![ + Event::UpgradeStarted { migrations: 2 }, + Event::MigrationCompleted { index: 0, took: 1 }, + // `blocks=0` means that it was not retried. + Event::MigrationFailed { index: 1, took: 0 }, + Event::UpgradeFailed, + ]); + + // Check that the handler was called correctly. + assert_eq!(upgrades_started_completed_failed(), (1, 0, 1)); + assert_eq!(Cursor::::get(), Some(MigrationCursor::Stuck)); + }); +} + +#[test] +fn historic_skipping_works() { + test_closure(|| { + MockedMigrations::set(vec![ + (SucceedAfter, 0), + (SucceedAfter, 0), // duplicate + (SucceedAfter, 1), + (SucceedAfter, 2), + (SucceedAfter, 1), // duplicate + ]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(10); + + // Just three historical ones, since two were added twice. + assert_eq!( + historic(), + vec![ + mocked_id(SucceedAfter, 0), + mocked_id(SucceedAfter, 1), + mocked_id(SucceedAfter, 2), + ] + ); + // Events received. + assert_events(vec![ + Event::UpgradeStarted { migrations: 5 }, + Event::MigrationCompleted { index: 0, took: 1 }, + Event::MigrationSkipped { index: 1 }, + Event::MigrationAdvanced { index: 2, took: 0 }, + Event::MigrationCompleted { index: 2, took: 1 }, + Event::MigrationAdvanced { index: 3, took: 0 }, + Event::MigrationAdvanced { index: 3, took: 1 }, + Event::MigrationCompleted { index: 3, took: 2 }, + Event::MigrationSkipped { index: 4 }, + Event::UpgradeCompleted, + ]); + assert_eq!(upgrades_started_completed_failed(), (1, 1, 0)); + + // Now go for another upgrade; just to make sure that it wont execute again. + System::reset_events(); + Migrations::on_runtime_upgrade(); + run_to_block(20); + + // Same historical ones as before. + assert_eq!( + historic(), + vec![ + mocked_id(SucceedAfter, 0), + mocked_id(SucceedAfter, 1), + mocked_id(SucceedAfter, 2), + ] + ); + + // Everything got skipped. + assert_events(vec![ + Event::UpgradeStarted { migrations: 5 }, + Event::MigrationSkipped { index: 0 }, + Event::MigrationSkipped { index: 1 }, + Event::MigrationSkipped { index: 2 }, + Event::MigrationSkipped { index: 3 }, + Event::MigrationSkipped { index: 4 }, + Event::UpgradeCompleted, + ]); + assert_eq!(upgrades_started_completed_failed(), (1, 1, 0)); + }); +} + +/// When another upgrade happens while a migration is still running, it should set the cursor to +/// stuck. +#[test] +fn upgrade_fails_when_migration_active() { + test_closure(|| { + MockedMigrations::set(vec![(SucceedAfter, 10)]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(3); + + // Events received. + assert_events(vec![ + Event::UpgradeStarted { migrations: 1 }, + Event::MigrationAdvanced { index: 0, took: 1 }, + Event::MigrationAdvanced { index: 0, took: 2 }, + ]); + assert_eq!(upgrades_started_completed_failed(), (1, 0, 0)); + + // Upgrade again. + Migrations::on_runtime_upgrade(); + // -- Defensive path -- + assert_eq!(Cursor::::get(), Some(MigrationCursor::Stuck)); + assert_events(vec![Event::UpgradeFailed]); + assert_eq!(upgrades_started_completed_failed(), (0, 0, 1)); + }); +} + +#[test] +fn migration_timeout_errors() { + test_closure(|| { + MockedMigrations::set(vec![(TimeoutAfter, 3)]); + + System::set_block_number(1); + Migrations::on_runtime_upgrade(); + run_to_block(5); + + // Times out after taking more than 3 steps. + assert_events(vec![ + Event::UpgradeStarted { migrations: 1 }, + Event::MigrationAdvanced { index: 0, took: 1 }, + Event::MigrationAdvanced { index: 0, took: 2 }, + Event::MigrationAdvanced { index: 0, took: 3 }, + Event::MigrationAdvanced { index: 0, took: 4 }, + Event::MigrationFailed { index: 0, took: 4 }, + Event::UpgradeFailed, + ]); + assert_eq!(upgrades_started_completed_failed(), (1, 0, 1)); + + // Failed migrations are not black-listed. + assert!(historic().is_empty()); + assert_eq!(Cursor::::get(), Some(MigrationCursor::Stuck)); + + Migrations::on_runtime_upgrade(); + run_to_block(6); + + assert_events(vec![Event::UpgradeFailed]); + assert_eq!(Cursor::::get(), Some(MigrationCursor::Stuck)); + assert_eq!(upgrades_started_completed_failed(), (0, 0, 1)); + }); +} diff --git a/substrate/frame/migrations/src/weights.rs b/substrate/frame/migrations/src/weights.rs new file mode 100644 index 00000000000..c9b63258c44 --- /dev/null +++ b/substrate/frame/migrations/src/weights.rs @@ -0,0 +1,358 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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_migrations` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `loud1`, CPU: `AMD EPYC 7282 16-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// target/release/substrate-node +// benchmark +// pallet +// --chain +// dev +// --pallet +// pallet-migrations +// --extrinsic +// +// --output +// weight.rs +// --template +// ../../polkadot-sdk/substrate/.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_migrations`. +pub trait WeightInfo { + fn onboard_new_mbms() -> Weight; + fn progress_mbms_none() -> Weight; + fn exec_migration_completed() -> Weight; + fn exec_migration_skipped_historic() -> Weight; + fn exec_migration_advance() -> Weight; + fn exec_migration_complete() -> Weight; + fn exec_migration_fail() -> Weight; + fn on_init_loop() -> Weight; + fn force_set_cursor() -> Weight; + fn force_set_active_cursor() -> Weight; + fn force_onboard_mbms() -> Weight; + fn clear_historic(n: u32, ) -> Weight; +} + +/// Weights for `pallet_migrations` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + fn onboard_new_mbms() -> Weight { + // Proof Size summary in bytes: + // Measured: `243` + // Estimated: `67035` + // Minimum execution time: 13_980_000 picoseconds. + Weight::from_parts(14_290_000, 67035) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn progress_mbms_none() -> Weight { + // Proof Size summary in bytes: + // Measured: `109` + // Estimated: `67035` + // Minimum execution time: 3_770_000 picoseconds. + Weight::from_parts(4_001_000, 67035) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn exec_migration_completed() -> Weight { + // Proof Size summary in bytes: + // Measured: `134` + // Estimated: `3599` + // Minimum execution time: 10_900_000 picoseconds. + Weight::from_parts(11_251_000, 3599) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_skipped_historic() -> Weight { + // Proof Size summary in bytes: + // Measured: `297` + // Estimated: `3762` + // Minimum execution time: 17_891_000 picoseconds. + Weight::from_parts(18_501_000, 3762) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_advance() -> Weight { + // Proof Size summary in bytes: + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 18_271_000 picoseconds. + Weight::from_parts(18_740_000, 3731) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:1) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_complete() -> Weight { + // Proof Size summary in bytes: + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 21_241_000 picoseconds. + Weight::from_parts(21_911_000, 3731) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn exec_migration_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 22_740_000 picoseconds. + Weight::from_parts(23_231_000, 3731) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + fn on_init_loop() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 440_000 picoseconds. + Weight::from_parts(500_000, 0) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn force_set_cursor() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 5_751_000 picoseconds. + Weight::from_parts(5_950_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn force_set_active_cursor() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_350_000 picoseconds. + Weight::from_parts(6_560_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + fn force_onboard_mbms() -> Weight { + // Proof Size summary in bytes: + // Measured: `218` + // Estimated: `67035` + // Minimum execution time: 11_121_000 picoseconds. + Weight::from_parts(11_530_000, 67035) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 256]`. + fn clear_historic(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1089 + n * (271 ±0)` + // Estimated: `3834 + n * (2740 ±0)` + // Minimum execution time: 21_891_000 picoseconds. + Weight::from_parts(18_572_306, 3834) + // Standard Error: 3_236 + .saturating_add(Weight::from_parts(1_648_429, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + fn onboard_new_mbms() -> Weight { + // Proof Size summary in bytes: + // Measured: `243` + // Estimated: `67035` + // Minimum execution time: 13_980_000 picoseconds. + Weight::from_parts(14_290_000, 67035) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn progress_mbms_none() -> Weight { + // Proof Size summary in bytes: + // Measured: `109` + // Estimated: `67035` + // Minimum execution time: 3_770_000 picoseconds. + Weight::from_parts(4_001_000, 67035) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn exec_migration_completed() -> Weight { + // Proof Size summary in bytes: + // Measured: `134` + // Estimated: `3599` + // Minimum execution time: 10_900_000 picoseconds. + Weight::from_parts(11_251_000, 3599) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_skipped_historic() -> Weight { + // Proof Size summary in bytes: + // Measured: `297` + // Estimated: `3762` + // Minimum execution time: 17_891_000 picoseconds. + Weight::from_parts(18_501_000, 3762) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_advance() -> Weight { + // Proof Size summary in bytes: + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 18_271_000 picoseconds. + Weight::from_parts(18_740_000, 3731) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:1) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_complete() -> Weight { + // Proof Size summary in bytes: + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 21_241_000 picoseconds. + Weight::from_parts(21_911_000, 3731) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn exec_migration_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 22_740_000 picoseconds. + Weight::from_parts(23_231_000, 3731) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + fn on_init_loop() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 440_000 picoseconds. + Weight::from_parts(500_000, 0) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn force_set_cursor() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 5_751_000 picoseconds. + Weight::from_parts(5_950_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn force_set_active_cursor() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_350_000 picoseconds. + Weight::from_parts(6_560_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + fn force_onboard_mbms() -> Weight { + // Proof Size summary in bytes: + // Measured: `218` + // Estimated: `67035` + // Minimum execution time: 11_121_000 picoseconds. + Weight::from_parts(11_530_000, 67035) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 256]`. + fn clear_historic(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1089 + n * (271 ±0)` + // Estimated: `3834 + n * (2740 ±0)` + // Minimum execution time: 21_891_000 picoseconds. + Weight::from_parts(18_572_306, 3834) + // Standard Error: 3_236 + .saturating_add(Weight::from_parts(1_648_429, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) + } +} diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs index a2e5d726fdd..52db7c34bfd 100644 --- a/substrate/frame/src/lib.rs +++ b/substrate/frame/src/lib.rs @@ -197,7 +197,7 @@ pub mod runtime { // Types often used in the runtime APIs. pub use sp_core::OpaqueMetadata; pub use sp_inherents::{CheckInherentsResult, InherentData}; - pub use sp_runtime::ApplyExtrinsicResult; + pub use sp_runtime::{ApplyExtrinsicResult, ExtrinsicInclusionMode}; pub use frame_system_rpc_runtime_api::*; pub use sp_api::{self, *}; diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs index 34b9d21d8ce..da483fa6cf0 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -204,47 +204,50 @@ pub fn expand_outer_inherent( } } + impl #scrate::traits::IsInherent<<#block as #scrate::sp_runtime::traits::Block>::Extrinsic> for #runtime { + fn is_inherent(ext: &<#block as #scrate::sp_runtime::traits::Block>::Extrinsic) -> bool { + use #scrate::inherent::ProvideInherent; + use #scrate::traits::{IsSubType, ExtrinsicCall}; + + if #scrate::sp_runtime::traits::Extrinsic::is_signed(ext).unwrap_or(false) { + // Signed extrinsics are never inherents. + return false + } + + #( + #pallet_attrs + { + let call = <#unchecked_extrinsic as ExtrinsicCall>::call(ext); + if let Some(call) = IsSubType::<_>::is_sub_type(call) { + if <#pallet_names as ProvideInherent>::is_inherent(&call) { + return true; + } + } + } + )* + false + } + } + impl #scrate::traits::EnsureInherentsAreFirst<#block> for #runtime { - fn ensure_inherents_are_first(block: &#block) -> Result<(), u32> { + fn ensure_inherents_are_first(block: &#block) -> Result { use #scrate::inherent::ProvideInherent; use #scrate::traits::{IsSubType, ExtrinsicCall}; use #scrate::sp_runtime::traits::Block as _; - let mut first_signed_observed = false; + let mut num_inherents = 0u32; for (i, xt) in block.extrinsics().iter().enumerate() { - let is_signed = #scrate::sp_runtime::traits::Extrinsic::is_signed(xt) - .unwrap_or(false); - - let is_inherent = if is_signed { - // Signed extrinsics are not inherents. - false - } else { - let mut is_inherent = false; - #( - #pallet_attrs - { - let call = <#unchecked_extrinsic as ExtrinsicCall>::call(xt); - if let Some(call) = IsSubType::<_>::is_sub_type(call) { - if #pallet_names::is_inherent(&call) { - is_inherent = true; - } - } - } - )* - is_inherent - }; - - if !is_inherent { - first_signed_observed = true; - } + if >::is_inherent(xt) { + if num_inherents != i as u32 { + return Err(i as u32); + } - if first_signed_observed && is_inherent { - return Err(i as u32) + num_inherents += 1; // Safe since we are in an `enumerate` loop. } } - Ok(()) + Ok(num_inherents) } } } diff --git a/substrate/frame/support/procedural/src/pallet/expand/hooks.rs b/substrate/frame/support/procedural/src/pallet/expand/hooks.rs index 6b25ddcba1a..3623b595268 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/hooks.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/hooks.rs @@ -175,6 +175,22 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream { } } + impl<#type_impl_gen> + #frame_support::traits::OnPoll<#frame_system::pallet_prelude::BlockNumberFor::> + for #pallet_ident<#type_use_gen> #where_clause + { + fn on_poll( + n: #frame_system::pallet_prelude::BlockNumberFor::, + weight: &mut #frame_support::weights::WeightMeter + ) { + < + Self as #frame_support::traits::Hooks< + #frame_system::pallet_prelude::BlockNumberFor:: + > + >::on_poll(n, weight); + } + } + impl<#type_impl_gen> #frame_support::traits::OnInitialize<#frame_system::pallet_prelude::BlockNumberFor::> for #pallet_ident<#type_use_gen> #where_clause diff --git a/substrate/frame/support/src/migrations.rs b/substrate/frame/support/src/migrations.rs index f7541059023..2ceab44cb16 100644 --- a/substrate/frame/support/src/migrations.rs +++ b/substrate/frame/support/src/migrations.rs @@ -16,13 +16,21 @@ // limitations under the License. use crate::{ - traits::{GetStorageVersion, NoStorageVersionSet, PalletInfoAccess, StorageVersion}, - weights::{RuntimeDbWeight, Weight}, + defensive, + storage::transactional::with_transaction_opaque_err, + traits::{ + Defensive, GetStorageVersion, NoStorageVersionSet, PalletInfoAccess, SafeMode, + StorageVersion, + }, + weights::{RuntimeDbWeight, Weight, WeightMeter}, }; +use codec::{Decode, Encode, MaxEncodedLen}; use impl_trait_for_tuples::impl_for_tuples; +use sp_arithmetic::traits::Bounded; use sp_core::Get; use sp_io::{hashing::twox_128, storage::clear_prefix, KillStorageResult}; -use sp_std::marker::PhantomData; +use sp_runtime::traits::Zero; +use sp_std::{marker::PhantomData, vec::Vec}; /// Handles storage migration pallet versioning. /// @@ -91,7 +99,7 @@ pub struct VersionedMigration), @@ -118,7 +126,6 @@ impl< /// migration ran or not. #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { - use codec::Encode; let on_chain_version = Pallet::on_chain_storage_version(); if on_chain_version == FROM { Ok(VersionedPostUpgradeData::MigrationExecuted(Inner::pre_upgrade()?).encode()) @@ -361,3 +368,622 @@ impl, DbWeight: Get> frame_support::traits Ok(()) } } + +/// A migration that can proceed in multiple steps. +pub trait SteppedMigration { + /// The cursor type that stores the progress (aka. state) of this migration. + type Cursor: codec::FullCodec + codec::MaxEncodedLen; + + /// The unique identifier type of this migration. + type Identifier: codec::FullCodec + codec::MaxEncodedLen; + + /// The unique identifier of this migration. + /// + /// If two migrations have the same identifier, then they are assumed to be identical. + fn id() -> Self::Identifier; + + /// The maximum number of steps that this migration can take. + /// + /// This can be used to enforce progress and prevent migrations becoming stuck forever. A + /// migration that exceeds its max steps is treated as failed. `None` means that there is no + /// limit. + fn max_steps() -> Option { + None + } + + /// Try to migrate as much as possible with the given weight. + /// + /// **ANY STORAGE CHANGES MUST BE ROLLED-BACK BY THE CALLER UPON ERROR.** This is necessary + /// since the caller cannot return a cursor in the error case. [`Self::transactional_step`] is + /// provided as convenience for a caller. A cursor of `None` implies that the migration is at + /// its end. A migration that once returned `Nonce` is guaranteed to never be called again. + fn step( + cursor: Option, + meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError>; + + /// Same as [`Self::step`], but rolls back pending changes in the error case. + fn transactional_step( + mut cursor: Option, + meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError> { + with_transaction_opaque_err(move || match Self::step(cursor, meter) { + Ok(new_cursor) => { + cursor = new_cursor; + sp_runtime::TransactionOutcome::Commit(Ok(cursor)) + }, + Err(err) => sp_runtime::TransactionOutcome::Rollback(Err(err)), + }) + .map_err(|()| SteppedMigrationError::Failed)? + } +} + +/// Error that can occur during a [`SteppedMigration`]. +#[derive(Debug, Encode, Decode, MaxEncodedLen, scale_info::TypeInfo)] +pub enum SteppedMigrationError { + // Transient errors: + /// The remaining weight is not enough to do anything. + /// + /// Can be resolved by calling with at least `required` weight. Note that calling it with + /// exactly `required` weight could cause it to not make any progress. + InsufficientWeight { + /// Amount of weight required to make progress. + required: Weight, + }, + // Permanent errors: + /// The migration cannot decode its cursor and therefore not proceed. + /// + /// This should not happen unless (1) the migration itself returned an invalid cursor in a + /// previous iteration, (2) the storage got corrupted or (3) there is a bug in the caller's + /// code. + InvalidCursor, + /// The migration encountered a permanent error and cannot continue. + Failed, +} + +/// Notification handler for status updates regarding Multi-Block-Migrations. +#[impl_trait_for_tuples::impl_for_tuples(8)] +pub trait MigrationStatusHandler { + /// Notifies of the start of a runtime migration. + fn started() {} + + /// Notifies of the completion of a runtime migration. + fn completed() {} +} + +/// Handles a failed runtime migration. +/// +/// This should never happen, but is here for completeness. +pub trait FailedMigrationHandler { + /// Infallibly handle a failed runtime migration. + /// + /// Gets passed in the optional index of the migration in the batch that caused the failure. + /// Returning `None` means that no automatic handling should take place and the callee decides + /// in the implementation what to do. + fn failed(migration: Option) -> FailedMigrationHandling; +} + +/// Do now allow any transactions to be processed after a runtime upgrade failed. +/// +/// This is **not a sane default**, since it prevents governance intervention. +pub struct FreezeChainOnFailedMigration; + +impl FailedMigrationHandler for FreezeChainOnFailedMigration { + fn failed(_migration: Option) -> FailedMigrationHandling { + FailedMigrationHandling::KeepStuck + } +} + +/// Enter safe mode on a failed runtime upgrade. +/// +/// This can be very useful to manually intervene and fix the chain state. `Else` is used in case +/// that the safe mode could not be entered. +pub struct EnterSafeModeOnFailedMigration( + PhantomData<(SM, Else)>, +); + +impl FailedMigrationHandler + for EnterSafeModeOnFailedMigration +where + ::BlockNumber: Bounded, +{ + fn failed(migration: Option) -> FailedMigrationHandling { + let entered = if SM::is_entered() { + SM::extend(Bounded::max_value()) + } else { + SM::enter(Bounded::max_value()) + }; + + // If we could not enter or extend safe mode (for whatever reason), then we try the next. + if entered.is_err() { + Else::failed(migration) + } else { + FailedMigrationHandling::KeepStuck + } + } +} + +/// How to proceed after a runtime upgrade failed. +/// +/// There is NO SANE DEFAULT HERE. All options are very dangerous and should be used with care. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum FailedMigrationHandling { + /// Resume extrinsic processing of the chain. This will not resume the upgrade. + /// + /// This should be supplemented with additional measures to ensure that the broken chain state + /// does not get further messed up by user extrinsics. + ForceUnstuck, + /// Set the cursor to `Stuck` and keep blocking extrinsics. + KeepStuck, + /// Don't do anything with the cursor and let the handler decide. + /// + /// This can be useful in cases where the other two options would overwrite any changes that + /// were done by the handler to the cursor. + Ignore, +} + +/// Something that can do multi step migrations. +pub trait MultiStepMigrator { + /// Hint for whether [`Self::step`] should be called. + fn ongoing() -> bool; + + /// Do the next step in the MBM process. + /// + /// Must gracefully handle the case that it is currently not upgrading. + fn step() -> Weight; +} + +impl MultiStepMigrator for () { + fn ongoing() -> bool { + false + } + + fn step() -> Weight { + Weight::zero() + } +} + +/// Multiple [`SteppedMigration`]. +pub trait SteppedMigrations { + /// The number of migrations that `Self` aggregates. + fn len() -> u32; + + /// The `n`th [`SteppedMigration::id`]. + /// + /// Is guaranteed to return `Some` if `n < Self::len()`. + fn nth_id(n: u32) -> Option>; + + /// The [`SteppedMigration::max_steps`] of the `n`th migration. + /// + /// Is guaranteed to return `Some` if `n < Self::len()`. + fn nth_max_steps(n: u32) -> Option>; + + /// Do a [`SteppedMigration::step`] on the `n`th migration. + /// + /// Is guaranteed to return `Some` if `n < Self::len()`. + fn nth_step( + n: u32, + cursor: Option>, + meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>>; + + /// Do a [`SteppedMigration::transactional_step`] on the `n`th migration. + /// + /// Is guaranteed to return `Some` if `n < Self::len()`. + fn nth_transactional_step( + n: u32, + cursor: Option>, + meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>>; + + /// The maximal encoded length across all cursors. + fn cursor_max_encoded_len() -> usize; + + /// The maximal encoded length across all identifiers. + fn identifier_max_encoded_len() -> usize; + + /// Assert the integrity of the migrations. + /// + /// Should be executed as part of a test prior to runtime usage. May or may not need + /// externalities. + #[cfg(feature = "std")] + fn integrity_test() -> Result<(), &'static str> { + use crate::ensure; + let l = Self::len(); + + for n in 0..l { + ensure!(Self::nth_id(n).is_some(), "id is None"); + ensure!(Self::nth_max_steps(n).is_some(), "steps is None"); + + // The cursor that we use does not matter. Hence use empty. + ensure!( + Self::nth_step(n, Some(vec![]), &mut WeightMeter::new()).is_some(), + "steps is None" + ); + ensure!( + Self::nth_transactional_step(n, Some(vec![]), &mut WeightMeter::new()).is_some(), + "steps is None" + ); + } + + Ok(()) + } +} + +impl SteppedMigrations for () { + fn len() -> u32 { + 0 + } + + fn nth_id(_n: u32) -> Option> { + None + } + + fn nth_max_steps(_n: u32) -> Option> { + None + } + + fn nth_step( + _n: u32, + _cursor: Option>, + _meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>> { + None + } + + fn nth_transactional_step( + _n: u32, + _cursor: Option>, + _meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>> { + None + } + + fn cursor_max_encoded_len() -> usize { + 0 + } + + fn identifier_max_encoded_len() -> usize { + 0 + } +} + +// A collection consisting of only a single migration. +impl SteppedMigrations for T { + fn len() -> u32 { + 1 + } + + fn nth_id(_n: u32) -> Option> { + Some(T::id().encode()) + } + + fn nth_max_steps(n: u32) -> Option> { + // It should be generally fine to call with n>0, but the code should not attempt to. + n.is_zero() + .then_some(T::max_steps()) + .defensive_proof("nth_max_steps should only be called with n==0") + } + + fn nth_step( + _n: u32, + cursor: Option>, + meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>> { + if !_n.is_zero() { + defensive!("nth_step should only be called with n==0"); + return None + } + + let cursor = match cursor { + Some(cursor) => match T::Cursor::decode(&mut &cursor[..]) { + Ok(cursor) => Some(cursor), + Err(_) => return Some(Err(SteppedMigrationError::InvalidCursor)), + }, + None => None, + }; + + Some(T::step(cursor, meter).map(|cursor| cursor.map(|cursor| cursor.encode()))) + } + + fn nth_transactional_step( + n: u32, + cursor: Option>, + meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>> { + if n != 0 { + defensive!("nth_transactional_step should only be called with n==0"); + return None + } + + let cursor = match cursor { + Some(cursor) => match T::Cursor::decode(&mut &cursor[..]) { + Ok(cursor) => Some(cursor), + Err(_) => return Some(Err(SteppedMigrationError::InvalidCursor)), + }, + None => None, + }; + + Some( + T::transactional_step(cursor, meter).map(|cursor| cursor.map(|cursor| cursor.encode())), + ) + } + + fn cursor_max_encoded_len() -> usize { + T::Cursor::max_encoded_len() + } + + fn identifier_max_encoded_len() -> usize { + T::Identifier::max_encoded_len() + } +} + +#[impl_trait_for_tuples::impl_for_tuples(1, 30)] +impl SteppedMigrations for Tuple { + fn len() -> u32 { + for_tuples!( #( Tuple::len() )+* ) + } + + fn nth_id(n: u32) -> Option> { + let mut i = 0; + + for_tuples!( #( + if (i + Tuple::len()) > n { + return Tuple::nth_id(n - i) + } + + i += Tuple::len(); + )* ); + + None + } + + fn nth_step( + n: u32, + cursor: Option>, + meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>> { + let mut i = 0; + + for_tuples!( #( + if (i + Tuple::len()) > n { + return Tuple::nth_step(n - i, cursor, meter) + } + + i += Tuple::len(); + )* ); + + None + } + + fn nth_transactional_step( + n: u32, + cursor: Option>, + meter: &mut WeightMeter, + ) -> Option>, SteppedMigrationError>> { + let mut i = 0; + + for_tuples! ( #( + if (i + Tuple::len()) > n { + return Tuple::nth_transactional_step(n - i, cursor, meter) + } + + i += Tuple::len(); + )* ); + + None + } + + fn nth_max_steps(n: u32) -> Option> { + let mut i = 0; + + for_tuples!( #( + if (i + Tuple::len()) > n { + return Tuple::nth_max_steps(n - i) + } + + i += Tuple::len(); + )* ); + + None + } + + fn cursor_max_encoded_len() -> usize { + let mut max_len = 0; + + for_tuples!( #( + max_len = max_len.max(Tuple::cursor_max_encoded_len()); + )* ); + + max_len + } + + fn identifier_max_encoded_len() -> usize { + let mut max_len = 0; + + for_tuples!( #( + max_len = max_len.max(Tuple::identifier_max_encoded_len()); + )* ); + + max_len + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{assert_ok, storage::unhashed}; + + #[derive(Decode, Encode, MaxEncodedLen, Eq, PartialEq)] + pub enum Either { + Left(L), + Right(R), + } + + pub struct M0; + impl SteppedMigration for M0 { + type Cursor = (); + type Identifier = u8; + + fn id() -> Self::Identifier { + 0 + } + + fn step( + _cursor: Option, + _meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError> { + log::info!("M0"); + unhashed::put(&[0], &()); + Ok(None) + } + } + + pub struct M1; + impl SteppedMigration for M1 { + type Cursor = (); + type Identifier = u8; + + fn id() -> Self::Identifier { + 1 + } + + fn step( + _cursor: Option, + _meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError> { + log::info!("M1"); + unhashed::put(&[1], &()); + Ok(None) + } + + fn max_steps() -> Option { + Some(1) + } + } + + pub struct M2; + impl SteppedMigration for M2 { + type Cursor = (); + type Identifier = u8; + + fn id() -> Self::Identifier { + 2 + } + + fn step( + _cursor: Option, + _meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError> { + log::info!("M2"); + unhashed::put(&[2], &()); + Ok(None) + } + + fn max_steps() -> Option { + Some(2) + } + } + + pub struct F0; + impl SteppedMigration for F0 { + type Cursor = (); + type Identifier = u8; + + fn id() -> Self::Identifier { + 3 + } + + fn step( + _cursor: Option, + _meter: &mut WeightMeter, + ) -> Result, SteppedMigrationError> { + log::info!("F0"); + unhashed::put(&[3], &()); + Err(SteppedMigrationError::Failed) + } + } + + // Three migrations combined to execute in order: + type Triple = (M0, (M1, M2)); + // Six migrations, just concatenating the ones from before: + type Hextuple = (Triple, Triple); + + #[test] + fn singular_migrations_work() { + assert_eq!(M0::max_steps(), None); + assert_eq!(M1::max_steps(), Some(1)); + assert_eq!(M2::max_steps(), Some(2)); + + assert_eq!(<(M0, M1)>::nth_max_steps(0), Some(None)); + assert_eq!(<(M0, M1)>::nth_max_steps(1), Some(Some(1))); + assert_eq!(<(M0, M1, M2)>::nth_max_steps(2), Some(Some(2))); + + assert_eq!(<(M0, M1)>::nth_max_steps(2), None); + } + + #[test] + fn tuple_migrations_work() { + assert_eq!(<() as SteppedMigrations>::len(), 0); + assert_eq!(<((), ((), ())) as SteppedMigrations>::len(), 0); + assert_eq!(::len(), 3); + assert_eq!(::len(), 6); + + // Check the IDs. The index specific functions all return an Option, + // to account for the out-of-range case. + assert_eq!(::nth_id(0), Some(0u8.encode())); + assert_eq!(::nth_id(1), Some(1u8.encode())); + assert_eq!(::nth_id(2), Some(2u8.encode())); + + sp_io::TestExternalities::default().execute_with(|| { + for n in 0..3 { + ::nth_step( + n, + Default::default(), + &mut WeightMeter::new(), + ); + } + }); + } + + #[test] + fn integrity_test_works() { + sp_io::TestExternalities::default().execute_with(|| { + assert_ok!(<() as SteppedMigrations>::integrity_test()); + assert_ok!(::integrity_test()); + assert_ok!(::integrity_test()); + assert_ok!(::integrity_test()); + assert_ok!(::integrity_test()); + assert_ok!(::integrity_test()); + }); + } + + #[test] + fn transactional_rollback_works() { + sp_io::TestExternalities::default().execute_with(|| { + assert_ok!(<(M0, F0) as SteppedMigrations>::nth_transactional_step( + 0, + Default::default(), + &mut WeightMeter::new() + ) + .unwrap()); + assert!(unhashed::exists(&[0])); + + let _g = crate::StorageNoopGuard::new(); + assert!(<(M0, F0) as SteppedMigrations>::nth_transactional_step( + 1, + Default::default(), + &mut WeightMeter::new() + ) + .unwrap() + .is_err()); + assert!(<(F0, M1) as SteppedMigrations>::nth_transactional_step( + 0, + Default::default(), + &mut WeightMeter::new() + ) + .unwrap() + .is_err()); + }); + } +} diff --git a/substrate/frame/support/src/storage/transactional.rs b/substrate/frame/support/src/storage/transactional.rs index d42e1809e91..0671db4a3a8 100644 --- a/substrate/frame/support/src/storage/transactional.rs +++ b/substrate/frame/support/src/storage/transactional.rs @@ -127,6 +127,22 @@ where } } +/// Same as [`with_transaction`] but casts any internal error to `()`. +/// +/// This rids `E` of the `From` bound that is required by `with_transaction`. +pub fn with_transaction_opaque_err(f: F) -> Result, ()> +where + F: FnOnce() -> TransactionOutcome>, +{ + with_transaction(move || -> TransactionOutcome, DispatchError>> { + match f() { + TransactionOutcome::Commit(res) => TransactionOutcome::Commit(Ok(res)), + TransactionOutcome::Rollback(res) => TransactionOutcome::Rollback(Ok(res)), + } + }) + .map_err(|_| ()) +} + /// Same as [`with_transaction`] but without a limit check on nested transactional layers. /// /// This is mostly for backwards compatibility before there was a transactional layer limit. diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs index 3d0429f71b1..1997d8fc223 100644 --- a/substrate/frame/support/src/traits.rs +++ b/substrate/frame/support/src/traits.rs @@ -59,10 +59,10 @@ pub use misc::{ AccountTouch, Backing, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, DefensiveMax, DefensiveMin, DefensiveSaturating, DefensiveTruncateFrom, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, - ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, - Len, OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time, - TryCollect, TryDrop, TypedGet, UnixTime, VariantCount, VariantCountOf, WrapperKeepOpaque, - WrapperOpaque, + ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsInherent, + IsSubType, IsType, Len, OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, + SameOrOther, Time, TryCollect, TryDrop, TypedGet, UnixTime, VariantCount, VariantCountOf, + WrapperKeepOpaque, WrapperOpaque, }; #[allow(deprecated)] pub use misc::{PreimageProvider, PreimageRecipient}; @@ -86,7 +86,8 @@ mod hooks; pub use hooks::GenesisBuild; pub use hooks::{ BeforeAllRuntimeMigrations, BuildGenesisConfig, Hooks, IntegrityTest, OnFinalize, OnGenesis, - OnIdle, OnInitialize, OnRuntimeUpgrade, OnTimestampSet, + OnIdle, OnInitialize, OnPoll, OnRuntimeUpgrade, OnTimestampSet, PostInherents, + PostTransactions, PreInherents, }; pub mod schedule; diff --git a/substrate/frame/support/src/traits/hooks.rs b/substrate/frame/support/src/traits/hooks.rs index c37fb0f54bc..7d0e5aa1e89 100644 --- a/substrate/frame/support/src/traits/hooks.rs +++ b/substrate/frame/support/src/traits/hooks.rs @@ -25,10 +25,74 @@ use crate::weights::Weight; use impl_trait_for_tuples::impl_for_tuples; use sp_runtime::traits::AtLeast32BitUnsigned; use sp_std::prelude::*; +use sp_weights::WeightMeter; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; +/// Provides a callback to execute logic before the all inherents. +pub trait PreInherents { + /// Called before all inherents were applied but after `on_initialize`. + fn pre_inherents() {} +} + +#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))] +#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))] +#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))] +impl PreInherents for Tuple { + fn pre_inherents() { + for_tuples!( #( Tuple::pre_inherents(); )* ); + } +} + +/// Provides a callback to execute logic after the all inherents. +pub trait PostInherents { + /// Called after all inherents were applied. + fn post_inherents() {} +} + +#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))] +#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))] +#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))] +impl PostInherents for Tuple { + fn post_inherents() { + for_tuples!( #( Tuple::post_inherents(); )* ); + } +} + +/// Provides a callback to execute logic before the all transactions. +pub trait PostTransactions { + /// Called after all transactions were applied but before `on_finalize`. + fn post_transactions() {} +} + +#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))] +#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))] +#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))] +impl PostTransactions for Tuple { + fn post_transactions() { + for_tuples!( #( Tuple::post_transactions(); )* ); + } +} + +/// Periodically executes logic. Is not guaranteed to run within a specific timeframe and should +/// only be used on logic that has no deadline. +pub trait OnPoll { + /// Code to execute every now and then at the beginning of the block after inherent application. + /// + /// The remaining weight limit must be respected. + fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter) {} +} + +#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))] +#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))] +#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))] +impl OnPoll for Tuple { + fn on_poll(n: BlockNumber, weight: &mut WeightMeter) { + for_tuples!( #( Tuple::on_poll(n.clone(), weight); )* ); + } +} + /// See [`Hooks::on_initialize`]. pub trait OnInitialize { /// See [`Hooks::on_initialize`]. @@ -374,6 +438,12 @@ pub trait Hooks { Weight::zero() } + /// A hook to run logic after inherent application. + /// + /// Is not guaranteed to execute in a block and should therefore only be used in no-deadline + /// scenarios. + fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter) {} + /// Hook executed when a code change (aka. a "runtime upgrade") is detected by the FRAME /// `Executive` pallet. /// diff --git a/substrate/frame/support/src/traits/misc.rs b/substrate/frame/support/src/traits/misc.rs index eafd9c8abdd..1f634a64282 100644 --- a/substrate/frame/support/src/traits/misc.rs +++ b/substrate/frame/support/src/traits/misc.rs @@ -23,6 +23,7 @@ use impl_trait_for_tuples::impl_for_tuples; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; use sp_arithmetic::traits::{CheckedAdd, CheckedMul, CheckedSub, One, Saturating}; use sp_core::bounded::bounded_vec::TruncateFrom; + #[doc(hidden)] pub use sp_runtime::traits::{ ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128, ConstU16, ConstU32, @@ -895,11 +896,21 @@ pub trait GetBacking { /// A trait to ensure the inherent are before non-inherent in a block. /// /// This is typically implemented on runtime, through `construct_runtime!`. -pub trait EnsureInherentsAreFirst { +pub trait EnsureInherentsAreFirst: + IsInherent<::Extrinsic> +{ /// Ensure the position of inherent is correct, i.e. they are before non-inherents. /// - /// On error return the index of the inherent with invalid position (counting from 0). - fn ensure_inherents_are_first(block: &Block) -> Result<(), u32>; + /// On error return the index of the inherent with invalid position (counting from 0). On + /// success it returns the index of the last inherent. `0` therefore means that there are no + /// inherents. + fn ensure_inherents_are_first(block: &Block) -> Result; +} + +/// A trait to check if an extrinsic is an inherent. +pub trait IsInherent { + /// Whether this extrinsic is an inherent. + fn is_inherent(ext: &Extrinsic) -> bool; } /// An extrinsic on which we can get access to call. diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr index a4c7ecf7865..30005c07cb6 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/undefined_inherent_part.stderr @@ -53,8 +53,9 @@ error[E0599]: no function or associated item named `is_inherent` found for struc | |_^ function or associated item not found in `Pallet` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `is_inherent`, perhaps you need to implement it: + = note: the following traits define an item `is_inherent`, perhaps you need to implement one of them: candidate #1: `ProvideInherent` + candidate #2: `IsInherent` = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: no function or associated item named `check_inherent` found for struct `pallet::Pallet` in the current scope @@ -119,3 +120,23 @@ error[E0599]: no function or associated item named `is_inherent_required` found = note: the following trait defines an item `is_inherent_required`, perhaps you need to implement it: candidate #1: `ProvideInherent` = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `pallet::Pallet: ProvideInherent` is not satisfied + --> tests/construct_runtime_ui/undefined_inherent_part.rs:70:3 + | +70 | Pallet: pallet expanded::{}::{Pallet, Inherent}, + | ^^^^^^ the trait `ProvideInherent` is not implemented for `pallet::Pallet` + +error[E0277]: the trait bound `pallet::Pallet: ProvideInherent` is not satisfied + --> tests/construct_runtime_ui/undefined_inherent_part.rs:66:1 + | +66 | / construct_runtime! { +67 | | pub struct Runtime +68 | | { +69 | | System: frame_system expanded::{}::{Pallet, Call, Storage, Config, Event}, +70 | | Pallet: pallet expanded::{}::{Pallet, Inherent}, +71 | | } +72 | | } + | |_^ the trait `ProvideInherent` is not implemented for `pallet::Pallet` + | + = note: this error originates in the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs index 79e9d678671..33b96dea948 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs @@ -90,6 +90,7 @@ fn module_error_outer_enum_expand_explicit() { frame_system::Error::NonDefaultComposite => (), frame_system::Error::NonZeroRefCount => (), frame_system::Error::CallFiltered => (), + frame_system::Error::MultiBlockMigrationsOngoing => (), #[cfg(feature = "experimental")] frame_system::Error::InvalidTask => (), #[cfg(feature = "experimental")] diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs index 4bd8ee0bb39..db006fe7935 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs @@ -90,6 +90,7 @@ fn module_error_outer_enum_expand_implicit() { frame_system::Error::NonDefaultComposite => (), frame_system::Error::NonZeroRefCount => (), frame_system::Error::CallFiltered => (), + frame_system::Error::MultiBlockMigrationsOngoing => (), #[cfg(feature = "experimental")] frame_system::Error::InvalidTask => (), #[cfg(feature = "experimental")] diff --git a/substrate/frame/support/test/tests/runtime_metadata.rs b/substrate/frame/support/test/tests/runtime_metadata.rs index bb7f7d2822e..40e70b219ba 100644 --- a/substrate/frame/support/test/tests/runtime_metadata.rs +++ b/substrate/frame/support/test/tests/runtime_metadata.rs @@ -101,7 +101,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } @@ -200,8 +200,8 @@ fn runtime_metadata() { name: "header", ty: meta_type::<&::Header>(), }], - output: meta_type::<()>(), - docs: maybe_docs(vec![" Initialize a block with the given header."]), + output: meta_type::(), + docs: maybe_docs(vec![" Initialize a block with the given header and return the runtime executive mode."]), }, ], docs: maybe_docs(vec![ diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 01df09106d9..3b659916379 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -130,11 +130,13 @@ use frame_support::{ DispatchResult, DispatchResultWithPostInfo, PerDispatchClass, PostDispatchInfo, }, ensure, impl_ensure_origin_with_arg_ignoring_arg, + migrations::MultiStepMigrator, pallet_prelude::Pays, storage::{self, StorageStreamIter}, traits::{ ConstU32, Contains, EnsureOrigin, EnsureOriginWithArg, Get, HandleLifetime, - OnKilledAccount, OnNewAccount, OriginTrait, PalletInfo, SortedMembers, StoredMap, TypedGet, + OnKilledAccount, OnNewAccount, OnRuntimeUpgrade, OriginTrait, PalletInfo, SortedMembers, + StoredMap, TypedGet, }, Parameter, }; @@ -169,6 +171,7 @@ pub use extensions::{ // Backward compatible re-export. pub use extensions::check_mortality::CheckMortality as CheckEra; pub use frame_support::dispatch::RawOrigin; +use frame_support::traits::{PostInherents, PostTransactions, PreInherents}; pub use weights::WeightInfo; const LOG_TARGET: &str = "runtime::system"; @@ -299,6 +302,11 @@ pub mod pallet { type BaseCallFilter = frame_support::traits::Everything; type BlockHashCount = frame_support::traits::ConstU64<10>; type OnSetCode = (); + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); } /// Default configurations of this pallet in a solo-chain environment. @@ -393,6 +401,11 @@ pub mod pallet { /// The set code logic, just the default since we're not a parachain. type OnSetCode = (); + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); } /// Default configurations of this pallet in a relay-chain environment. @@ -572,6 +585,35 @@ pub mod pallet { /// The maximum number of consumers allowed on a single account. type MaxConsumers: ConsumerLimits; + + /// All migrations that should run in the next runtime upgrade. + /// + /// These used to be formerly configured in `Executive`. Parachains need to ensure that + /// running all these migrations in one block will not overflow the weight limit of a block. + /// The migrations are run *before* the pallet `on_runtime_upgrade` hooks, just like the + /// `OnRuntimeUpgrade` migrations. + type SingleBlockMigrations: OnRuntimeUpgrade; + + /// The migrator that is used to run Multi-Block-Migrations. + /// + /// Can be set to [`pallet-migrations`] or an alternative implementation of the interface. + /// The diagram in `frame_executive::block_flowchart` explains when it runs. + type MultiBlockMigrator: MultiStepMigrator; + + /// A callback that executes in *every block* directly before all inherents were applied. + /// + /// See `frame_executive::block_flowchart` for a in-depth explanation when it runs. + type PreInherents: PreInherents; + + /// A callback that executes in *every block* directly after all inherents were applied. + /// + /// See `frame_executive::block_flowchart` for a in-depth explanation when it runs. + type PostInherents: PostInherents; + + /// A callback that executes in *every block* directly after all transactions were applied. + /// + /// See `frame_executive::block_flowchart` for a in-depth explanation when it runs. + type PostTransactions: PostTransactions; } #[pallet::pallet] @@ -619,6 +661,9 @@ pub mod pallet { } /// Set the new runtime code without doing any checks of the given `code`. + /// + /// Note that runtime upgrades will not run if this is called with a not-increasing spec + /// version! #[pallet::call_index(3)] #[pallet::weight((T::SystemWeightInfo::set_code(), DispatchClass::Operational))] pub fn set_code_without_checks( @@ -814,6 +859,8 @@ pub mod pallet { NonZeroRefCount, /// The origin filter prevent the call to be dispatched. CallFiltered, + /// A multi-block migration is ongoing and prevents the current code from being replaced. + MultiBlockMigrationsOngoing, #[cfg(feature = "experimental")] /// The specified [`Task`] is not valid. InvalidTask, @@ -845,6 +892,10 @@ pub mod pallet { #[pallet::storage] pub(super) type ExtrinsicCount = StorageValue<_, u32>; + /// Whether all inherents have been applied. + #[pallet::storage] + pub type InherentsApplied = StorageValue<_, bool, ValueQuery>; + /// The current weight for the block. #[pallet::storage] #[pallet::whitelist_storage] @@ -1373,6 +1424,19 @@ impl Pallet { Self::deposit_event(Event::CodeUpdated); } + /// Whether all inherents have been applied. + pub fn inherents_applied() -> bool { + InherentsApplied::::get() + } + + /// Note that all inherents have been applied. + /// + /// Should be called immediately after all inherents have been applied. Must be called at least + /// once per block. + pub fn note_inherents_applied() { + InherentsApplied::::put(true); + } + /// Increment the reference counter on an account. #[deprecated = "Use `inc_consumers` instead"] pub fn inc_ref(who: &T::AccountId) { @@ -1692,6 +1756,7 @@ impl Pallet { >::put(digest); >::put(parent_hash); >::insert(*number - One::one(), parent_hash); + >::kill(); // Remove previous block data from storage BlockWeight::::kill(); @@ -1738,6 +1803,7 @@ impl Pallet { ExecutionPhase::::kill(); AllExtrinsicsLen::::kill(); storage::unhashed::kill(well_known_keys::INTRABLOCK_ENTROPY); + InherentsApplied::::kill(); // The following fields // @@ -1981,10 +2047,14 @@ impl Pallet { /// Determine whether or not it is possible to update the code. /// - /// Checks the given code if it is a valid runtime wasm blob by instantianting + /// Checks the given code if it is a valid runtime wasm blob by instantiating /// it and extracting the runtime version of it. It checks that the runtime version /// of the old and new runtime has the same spec name and that the spec version is increasing. pub fn can_set_code(code: &[u8]) -> Result<(), sp_runtime::DispatchError> { + if T::MultiBlockMigrator::ongoing() { + return Err(Error::::MultiBlockMigrationsOngoing.into()) + } + let current_version = T::Version::get(); let new_version = sp_io::misc::runtime_version(code) .and_then(|v| RuntimeVersion::decode(&mut &v[..]).ok()) diff --git a/substrate/frame/system/src/mock.rs b/substrate/frame/system/src/mock.rs index c4108099e39..7059845a7df 100644 --- a/substrate/frame/system/src/mock.rs +++ b/substrate/frame/system/src/mock.rs @@ -86,6 +86,22 @@ impl Config for Test { type Version = Version; type AccountData = u32; type OnKilledAccount = RecordKilled; + type MultiBlockMigrator = MockedMigrator; +} + +parameter_types! { + pub static Ongoing: bool = false; +} + +pub struct MockedMigrator; +impl frame_support::migrations::MultiStepMigrator for MockedMigrator { + fn ongoing() -> bool { + Ongoing::get() + } + + fn step() -> Weight { + Weight::zero() + } } pub type SysEvent = frame_system::Event; diff --git a/substrate/frame/system/src/tests.rs b/substrate/frame/system/src/tests.rs index e437e7f9f39..b889b5ca046 100644 --- a/substrate/frame/system/src/tests.rs +++ b/substrate/frame/system/src/tests.rs @@ -675,6 +675,28 @@ fn set_code_with_real_wasm_blob() { }); } +#[test] +fn set_code_rejects_during_mbm() { + Ongoing::set(true); + + let executor = substrate_test_runtime_client::new_native_or_wasm_executor(); + let mut ext = new_test_ext(); + ext.register_extension(sp_core::traits::ReadRuntimeVersionExt::new(executor)); + ext.execute_with(|| { + System::set_block_number(1); + let res = System::set_code( + RawOrigin::Root.into(), + substrate_test_runtime_client::runtime::wasm_binary_unwrap().to_vec(), + ); + assert_eq!( + res, + Err(DispatchErrorWithPostInfo::from(Error::::MultiBlockMigrationsOngoing)) + ); + + assert!(System::events().is_empty()); + }); +} + #[test] fn set_code_via_authorization_works() { let executor = substrate_test_runtime_client::new_native_or_wasm_executor(); diff --git a/substrate/primitives/api/proc-macro/src/decl_runtime_apis.rs b/substrate/primitives/api/proc-macro/src/decl_runtime_apis.rs index 2b1e65ec885..e34e4c0e767 100644 --- a/substrate/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/substrate/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -456,6 +456,7 @@ impl<'a> ToClientSideDecl<'a> { |err| #crate_::ApiError::FailedToDecodeReturnValue { function: #function_name, error: err, + raw: r.clone(), } ) ) diff --git a/substrate/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/substrate/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index c1339ff6621..1761e0ac9db 100644 --- a/substrate/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/substrate/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -158,7 +158,7 @@ fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result::Hash, _: &<#block_type as #crate_::BlockT>::Header, - ) -> std::result::Result<(), #crate_::ApiError> { + ) -> std::result::Result<#crate_::__private::ExtrinsicInclusionMode, #crate_::ApiError> { unimplemented!("`Core::initialize_block` not implemented for runtime api mocks") } } diff --git a/substrate/primitives/api/src/lib.rs b/substrate/primitives/api/src/lib.rs index 190de1ab3fd..a945b9f21f3 100644 --- a/substrate/primitives/api/src/lib.rs +++ b/substrate/primitives/api/src/lib.rs @@ -101,7 +101,7 @@ pub mod __private { generic::BlockId, traits::{Block as BlockT, Hash as HashT, HashingFor, Header as HeaderT, NumberFor}, transaction_validity::TransactionValidity, - RuntimeString, TransactionOutcome, + ExtrinsicInclusionMode, RuntimeString, TransactionOutcome, }; pub use sp_std::{mem, slice, vec}; pub use sp_version::{create_apis_vec, ApiId, ApisVec, RuntimeVersion}; @@ -115,11 +115,11 @@ pub use sp_core::traits::CallContext; use sp_core::OpaqueMetadata; #[cfg(feature = "std")] use sp_externalities::{Extension, Extensions}; -use sp_runtime::traits::Block as BlockT; #[cfg(feature = "std")] use sp_runtime::traits::HashingFor; #[cfg(feature = "std")] pub use sp_runtime::TransactionOutcome; +use sp_runtime::{traits::Block as BlockT, ExtrinsicInclusionMode}; #[cfg(feature = "std")] pub use sp_state_machine::StorageProof; #[cfg(feature = "std")] @@ -280,7 +280,7 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// ```rust /// use sp_version::create_runtime_str; /// # -/// # use sp_runtime::traits::Block as BlockT; +/// # use sp_runtime::{ExtrinsicInclusionMode, traits::Block as BlockT}; /// # use sp_test_primitives::Block; /// # /// # /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro @@ -307,7 +307,9 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// # unimplemented!() /// # } /// # fn execute_block(_block: Block) {} -/// # fn initialize_block(_header: &::Header) {} +/// # fn initialize_block(_header: &::Header) -> ExtrinsicInclusionMode { +/// # unimplemented!() +/// # } /// # } /// /// impl self::Balance for Runtime { @@ -540,11 +542,12 @@ pub fn init_runtime_logger() { #[cfg(feature = "std")] #[derive(Debug, thiserror::Error)] pub enum ApiError { - #[error("Failed to decode return value of {function}")] + #[error("Failed to decode return value of {function}: {error} raw data: {raw:?}")] FailedToDecodeReturnValue { function: &'static str, #[source] error: codec::Error, + raw: Vec, }, #[error("Failed to convert return value from runtime to node of {function}")] FailedToConvertReturnValue { @@ -800,15 +803,18 @@ pub fn deserialize_runtime_api_info(bytes: [u8; RUNTIME_API_INFO_SIZE]) -> ([u8; decl_runtime_apis! { /// The `Core` runtime api that every Substrate runtime needs to implement. #[core_trait] - #[api_version(4)] + #[api_version(5)] pub trait Core { /// Returns the version of the runtime. fn version() -> RuntimeVersion; /// Execute the given block. fn execute_block(block: Block); /// Initialize a block with the given header. + #[changed_in(5)] #[renamed("initialise_block", 2)] fn initialize_block(header: &::Header); + /// Initialize a block with the given header and return the runtime executive mode. + fn initialize_block(header: &::Header) -> ExtrinsicInclusionMode; } /// The `Metadata` api trait that returns metadata for the runtime. diff --git a/substrate/primitives/api/test/tests/decl_and_impl.rs b/substrate/primitives/api/test/tests/decl_and_impl.rs index d68470551d2..211a08561fd 100644 --- a/substrate/primitives/api/test/tests/decl_and_impl.rs +++ b/substrate/primitives/api/test/tests/decl_and_impl.rs @@ -139,7 +139,7 @@ impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/substrate/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs b/substrate/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs index 43718e4cd04..262a874213a 100644 --- a/substrate/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs +++ b/substrate/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs @@ -40,7 +40,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/substrate/primitives/api/test/tests/ui/impl_missing_version.rs b/substrate/primitives/api/test/tests/ui/impl_missing_version.rs index 560257b5168..58850ab343f 100644 --- a/substrate/primitives/api/test/tests/ui/impl_missing_version.rs +++ b/substrate/primitives/api/test/tests/ui/impl_missing_version.rs @@ -45,7 +45,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/substrate/primitives/api/test/tests/ui/missing_versioned_method.rs b/substrate/primitives/api/test/tests/ui/missing_versioned_method.rs index 6ead545f85a..70f75d06515 100644 --- a/substrate/primitives/api/test/tests/ui/missing_versioned_method.rs +++ b/substrate/primitives/api/test/tests/ui/missing_versioned_method.rs @@ -44,7 +44,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/substrate/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs b/substrate/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs index 8eebc1d79ba..63032000040 100644 --- a/substrate/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs +++ b/substrate/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs @@ -47,7 +47,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/substrate/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs b/substrate/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs index 594556d57be..0858813bc99 100644 --- a/substrate/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs +++ b/substrate/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs @@ -51,7 +51,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/substrate/primitives/api/test/tests/ui/positive_cases/default_impls.rs b/substrate/primitives/api/test/tests/ui/positive_cases/default_impls.rs index ae573238ffe..3e0cb79156c 100644 --- a/substrate/primitives/api/test/tests/ui/positive_cases/default_impls.rs +++ b/substrate/primitives/api/test/tests/ui/positive_cases/default_impls.rs @@ -46,7 +46,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs b/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs index 921bf0d0435..b2caea7ab7e 100644 --- a/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs +++ b/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs @@ -42,7 +42,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/substrate/primitives/runtime/src/lib.rs b/substrate/primitives/runtime/src/lib.rs index ddf92554c83..44bf3c969e5 100644 --- a/substrate/primitives/runtime/src/lib.rs +++ b/substrate/primitives/runtime/src/lib.rs @@ -998,6 +998,16 @@ impl TransactionOutcome { } } +/// Confines the kind of extrinsics that can be included in a block. +#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)] +pub enum ExtrinsicInclusionMode { + /// All extrinsics are allowed to be included in this block. + #[default] + AllExtrinsics, + /// Inherents are allowed to be included. + OnlyInherents, +} + #[cfg(test)] mod tests { use crate::traits::BlakeTwo256; diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index db9ff187b70..63e0aa6e137 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -61,7 +61,7 @@ use sp_runtime::{ create_runtime_str, impl_opaque_keys, traits::{BlakeTwo256, Block as BlockT, DispatchInfoOf, NumberFor, Verify}, transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, - ApplyExtrinsicResult, Perbill, + ApplyExtrinsicResult, ExtrinsicInclusionMode, Perbill, }; #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; @@ -480,9 +480,9 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> ExtrinsicInclusionMode { log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); - Executive::initialize_block(header); + Executive::initialize_block(header) } } -- GitLab From 833bafdbf7b178b639f895e0d43c43eb502de30c Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Date: Thu, 29 Feb 2024 01:43:53 +0200 Subject: [PATCH 047/188] Fixup multi-collator parachain transition to async backing (#3510) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing: ``` Verification failed for block 0x07bbf1e04121d70a4bdb21cc055132b53ac2390fa95c4d05497fc91b1e8bf7f5 received from (12D3KooWJzLd8skcAgA24EcJey7aJAhYctfUxWGjSP5Usk9wbpPZ): "Header 0x07bbf1e04121d70a4bdb21cc055132b53ac2390fa95c4d05497fc91b1e8bf7f5 rejected: too far in the future" ``` --------- Signed-off-by: Alexandru Gheorghe Co-authored-by: Dmitry Sinyavin Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Co-authored-by: Bastian Köcher --- cumulus/client/consensus/aura/src/lib.rs | 5 ++- cumulus/polkadot-parachain/src/service.rs | 33 +++++++++++-------- prdoc/pr_3510.prdoc | 13 ++++++++ .../bin/node-template/node/src/service.rs | 26 +++++++++------ 4 files changed, 52 insertions(+), 25 deletions(-) create mode 100644 prdoc/pr_3510.prdoc diff --git a/cumulus/client/consensus/aura/src/lib.rs b/cumulus/client/consensus/aura/src/lib.rs index 8e4bc658e44..ed6f5bdd4d6 100644 --- a/cumulus/client/consensus/aura/src/lib.rs +++ b/cumulus/client/consensus/aura/src/lib.rs @@ -54,7 +54,10 @@ use std::{ mod import_queue; pub use import_queue::{build_verifier, import_queue, BuildVerifierParams, ImportQueueParams}; -pub use sc_consensus_aura::{slot_duration, AuraVerifier, BuildAuraWorkerParams, SlotProportion}; +pub use sc_consensus_aura::{ + slot_duration, standalone::slot_duration_at, AuraVerifier, BuildAuraWorkerParams, + SlotProportion, +}; pub use sc_consensus_slots::InherentDataProviderExt; pub mod collator; diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index 4e06cd38f1d..386551102e4 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -1251,28 +1251,33 @@ where <::Pair as Pair>::Signature: TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, { - let client2 = client.clone(); + let verifier_client = client.clone(); let aura_verifier = move || { - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client2).unwrap(); - Box::new(cumulus_client_consensus_aura::build_verifier::< ::Pair, _, _, _, >(cumulus_client_consensus_aura::BuildVerifierParams { - client: client2.clone(), - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) + client: verifier_client.clone(), + create_inherent_data_providers: move |parent_hash, _| { + let cidp_client = verifier_client.clone(); + async move { + let slot_duration = cumulus_client_consensus_aura::slot_duration_at( + &*cidp_client, + parent_hash, + )?; + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + } }, telemetry: telemetry_handle, })) as Box<_> diff --git a/prdoc/pr_3510.prdoc b/prdoc/pr_3510.prdoc new file mode 100644 index 00000000000..6ee2f9a81f7 --- /dev/null +++ b/prdoc/pr_3510.prdoc @@ -0,0 +1,13 @@ +title: "Fix multi-collator parachain transition to async backing" + +doc: + - audience: Node Operator + description: | + The dynamic Aura slot duration, introduced in PR#3211, didn't take the block import pipeline + into account. The result was the parachain backed by multiple collators not being able to + keep producing blocks after its runtime was upgraded to support async backing, requiring to + restart all the collator nodes. This change fixes the issue, introducing the dynamic Aura + slot duration into the block import pipeline. + +crates: + - name: "polkadot-parachain-bin" diff --git a/substrate/bin/node-template/node/src/service.rs b/substrate/bin/node-template/node/src/service.rs index 25cd6511784..125cca13927 100644 --- a/substrate/bin/node-template/node/src/service.rs +++ b/substrate/bin/node-template/node/src/service.rs @@ -80,23 +80,29 @@ pub fn new_partial(config: &Configuration) -> Result { telemetry.as_ref().map(|x| x.handle()), )?; - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - + let cidp_client = client.clone(); let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { block_import: grandpa_block_import.clone(), justification_import: Some(Box::new(grandpa_block_import.clone())), client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + create_inherent_data_providers: move |parent_hash, _| { + let cidp_client = cidp_client.clone(); + async move { + let slot_duration = sc_consensus_aura::standalone::slot_duration_at( + &*cidp_client, + parent_hash, + )?; + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); - Ok((slot, timestamp)) + Ok((slot, timestamp)) + } }, spawner: &task_manager.spawn_essential_handle(), registry: config.prometheus_registry(), -- GitLab From a22319cdd5fcdcec3bbedfe41f6d11a6b5446cf9 Mon Sep 17 00:00:00 2001 From: philoniare Date: Thu, 29 Feb 2024 13:17:24 +0800 Subject: [PATCH 048/188] [Deprecation] Remove sp_weights::OldWeight (#3491) # Description *Removes `sp_weights::OldWeight` and its usage* Fixes #144 --------- Co-authored-by: Liam Aharon --- prdoc/pr_3491.prdoc | 12 +++ substrate/frame/contracts/src/wasm/mod.rs | 11 --- substrate/primitives/weights/src/lib.rs | 27 +------ .../primitives/weights/src/weight_meter.rs | 81 ++++++++----------- 4 files changed, 47 insertions(+), 84 deletions(-) create mode 100644 prdoc/pr_3491.prdoc diff --git a/prdoc/pr_3491.prdoc b/prdoc/pr_3491.prdoc new file mode 100644 index 00000000000..e36afb916a6 --- /dev/null +++ b/prdoc/pr_3491.prdoc @@ -0,0 +1,12 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Remove Deprecated OldWeight + +doc: + - audience: Runtime Dev + description: | + Removed deprecated sp_weights::OldWeight type. Use [`weight_v2::Weight`] instead. + +crates: + - name: frame-support diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs index c96c2856509..34b45cba5d2 100644 --- a/substrate/frame/contracts/src/wasm/mod.rs +++ b/substrate/frame/contracts/src/wasm/mod.rs @@ -1821,17 +1821,6 @@ mod tests { assert!(weight_left.all_gt(actual_left), "gas_left must be greater than final"); } - /// Test that [`frame_support::weights::OldWeight`] en/decodes the same as our - /// [`crate::OldWeight`]. - #[test] - fn old_weight_decode() { - #![allow(deprecated)] - let sp = frame_support::weights::OldWeight(42).encode(); - let our = crate::OldWeight::decode(&mut &*sp).unwrap(); - - assert_eq!(our, 42); - } - const CODE_VALUE_TRANSFERRED: &str = r#" (module (import "seal0" "seal_value_transferred" (func $seal_value_transferred (param i32 i32))) diff --git a/substrate/primitives/weights/src/lib.rs b/substrate/primitives/weights/src/lib.rs index aede9473535..b2c956266e2 100644 --- a/substrate/primitives/weights/src/lib.rs +++ b/substrate/primitives/weights/src/lib.rs @@ -18,9 +18,6 @@ //! # Primitives for transaction weighting. #![cfg_attr(not(feature = "std"), no_std)] -// TODO remove once `OldWeight` is gone. I dont know why this is needed, maybe by one of the macros -// of `OldWeight`. -#![allow(deprecated)] extern crate self as sp_weights; @@ -28,7 +25,7 @@ mod weight_meter; mod weight_v2; use bounded_collections::Get; -use codec::{CompactAs, Decode, Encode, MaxEncodedLen}; +use codec::{Decode, Encode}; use scale_info::TypeInfo; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -52,28 +49,6 @@ pub mod constants { pub const WEIGHT_PROOF_SIZE_PER_KB: u64 = 1024; } -/// The old weight type. -/// -/// NOTE: This type exists purely for compatibility purposes! Use [`weight_v2::Weight`] in all other -/// cases. -#[derive( - Decode, - Encode, - CompactAs, - PartialEq, - Eq, - Clone, - Copy, - RuntimeDebug, - Default, - MaxEncodedLen, - TypeInfo, -)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(transparent))] -#[deprecated(note = "Will be removed soon; use `Weight` instead.")] -pub struct OldWeight(pub u64); - /// The weight of database operations that the runtime can invoke. /// /// NOTE: This is currently only measured in computational time, and will probably diff --git a/substrate/primitives/weights/src/weight_meter.rs b/substrate/primitives/weights/src/weight_meter.rs index 1738948e4c3..cfe8396ae6d 100644 --- a/substrate/primitives/weights/src/weight_meter.rs +++ b/substrate/primitives/weights/src/weight_meter.rs @@ -118,13 +118,6 @@ impl WeightMeter { debug_assert!(self.consumed.all_lte(self.limit), "Weight counter overflow"); } - /// Consume the given weight after checking that it can be consumed and return `true`. Otherwise - /// do nothing and return `false`. - #[deprecated(note = "Use `try_consume` instead. Will be removed after December 2023.")] - pub fn check_accrue(&mut self, w: Weight) -> bool { - self.try_consume(w).is_ok() - } - /// Consume the given weight after checking that it can be consumed. /// /// Returns `Ok` if the weight can be consumed or otherwise an `Err`. @@ -139,12 +132,6 @@ impl WeightMeter { }) } - /// Check if the given weight can be consumed. - #[deprecated(note = "Use `can_consume` instead. Will be removed after December 2023.")] - pub fn can_accrue(&self, w: Weight) -> bool { - self.can_consume(w) - } - /// Check if the given weight can be consumed. pub fn can_consume(&self, w: Weight) -> bool { self.consumed.checked_add(&w).map_or(false, |t| t.all_lte(self.limit)) @@ -165,80 +152,80 @@ mod tests { fn weight_meter_remaining_works() { let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 20)); - assert!(meter.check_accrue(Weight::from_parts(5, 0))); + assert_eq!(meter.try_consume(Weight::from_parts(5, 0)), Ok(())); assert_eq!(meter.consumed, Weight::from_parts(5, 0)); assert_eq!(meter.remaining(), Weight::from_parts(5, 20)); - assert!(meter.check_accrue(Weight::from_parts(2, 10))); + assert_eq!(meter.try_consume(Weight::from_parts(2, 10)), Ok(())); assert_eq!(meter.consumed, Weight::from_parts(7, 10)); assert_eq!(meter.remaining(), Weight::from_parts(3, 10)); - assert!(meter.check_accrue(Weight::from_parts(3, 10))); + assert_eq!(meter.try_consume(Weight::from_parts(3, 10)), Ok(())); assert_eq!(meter.consumed, Weight::from_parts(10, 20)); assert_eq!(meter.remaining(), Weight::from_parts(0, 0)); } #[test] - fn weight_meter_can_accrue_works() { + fn weight_meter_can_consume_works() { let meter = WeightMeter::with_limit(Weight::from_parts(1, 1)); - assert!(meter.can_accrue(Weight::from_parts(0, 0))); - assert!(meter.can_accrue(Weight::from_parts(1, 1))); - assert!(!meter.can_accrue(Weight::from_parts(0, 2))); - assert!(!meter.can_accrue(Weight::from_parts(2, 0))); - assert!(!meter.can_accrue(Weight::from_parts(2, 2))); + assert!(meter.can_consume(Weight::from_parts(0, 0))); + assert!(meter.can_consume(Weight::from_parts(1, 1))); + assert!(!meter.can_consume(Weight::from_parts(0, 2))); + assert!(!meter.can_consume(Weight::from_parts(2, 0))); + assert!(!meter.can_consume(Weight::from_parts(2, 2))); } #[test] - fn weight_meter_check_accrue_works() { + fn weight_meter_try_consume_works() { let mut meter = WeightMeter::with_limit(Weight::from_parts(2, 2)); - assert!(meter.check_accrue(Weight::from_parts(0, 0))); - assert!(meter.check_accrue(Weight::from_parts(1, 1))); - assert!(!meter.check_accrue(Weight::from_parts(0, 2))); - assert!(!meter.check_accrue(Weight::from_parts(2, 0))); - assert!(!meter.check_accrue(Weight::from_parts(2, 2))); - assert!(meter.check_accrue(Weight::from_parts(0, 1))); - assert!(meter.check_accrue(Weight::from_parts(1, 0))); + assert_eq!(meter.try_consume(Weight::from_parts(0, 0)), Ok(())); + assert_eq!(meter.try_consume(Weight::from_parts(1, 1)), Ok(())); + assert_eq!(meter.try_consume(Weight::from_parts(0, 2)), Err(())); + assert_eq!(meter.try_consume(Weight::from_parts(2, 0)), Err(())); + assert_eq!(meter.try_consume(Weight::from_parts(2, 2)), Err(())); + assert_eq!(meter.try_consume(Weight::from_parts(0, 1)), Ok(())); + assert_eq!(meter.try_consume(Weight::from_parts(1, 0)), Ok(())); } #[test] - fn weight_meter_check_and_can_accrue_works() { + fn weight_meter_check_and_can_consume_works() { let mut meter = WeightMeter::new(); - assert!(meter.can_accrue(Weight::from_parts(u64::MAX, 0))); - assert!(meter.check_accrue(Weight::from_parts(u64::MAX, 0))); + assert!(meter.can_consume(Weight::from_parts(u64::MAX, 0))); + assert_eq!(meter.try_consume(Weight::from_parts(u64::MAX, 0)), Ok(())); - assert!(meter.can_accrue(Weight::from_parts(0, u64::MAX))); - assert!(meter.check_accrue(Weight::from_parts(0, u64::MAX))); + assert!(meter.can_consume(Weight::from_parts(0, u64::MAX))); + assert_eq!(meter.try_consume(Weight::from_parts(0, u64::MAX)), Ok(())); - assert!(!meter.can_accrue(Weight::from_parts(0, 1))); - assert!(!meter.check_accrue(Weight::from_parts(0, 1))); + assert!(!meter.can_consume(Weight::from_parts(0, 1))); + assert_eq!(meter.try_consume(Weight::from_parts(0, 1)), Err(())); - assert!(!meter.can_accrue(Weight::from_parts(1, 0))); - assert!(!meter.check_accrue(Weight::from_parts(1, 0))); + assert!(!meter.can_consume(Weight::from_parts(1, 0))); + assert_eq!(meter.try_consume(Weight::from_parts(1, 0)), Err(())); - assert!(meter.can_accrue(Weight::zero())); - assert!(meter.check_accrue(Weight::zero())); + assert!(meter.can_consume(Weight::zero())); + assert_eq!(meter.try_consume(Weight::zero()), Ok(())); } #[test] fn consumed_ratio_works() { let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 20)); - assert!(meter.check_accrue(Weight::from_parts(5, 0))); + assert_eq!(meter.try_consume(Weight::from_parts(5, 0)), Ok(())); assert_eq!(meter.consumed_ratio(), Perbill::from_percent(50)); - assert!(meter.check_accrue(Weight::from_parts(0, 12))); + assert_eq!(meter.try_consume(Weight::from_parts(0, 12)), Ok(())); assert_eq!(meter.consumed_ratio(), Perbill::from_percent(60)); - assert!(meter.check_accrue(Weight::from_parts(2, 0))); + assert_eq!(meter.try_consume(Weight::from_parts(2, 0)), Ok(())); assert_eq!(meter.consumed_ratio(), Perbill::from_percent(70)); - assert!(meter.check_accrue(Weight::from_parts(0, 4))); + assert_eq!(meter.try_consume(Weight::from_parts(0, 4)), Ok(())); assert_eq!(meter.consumed_ratio(), Perbill::from_percent(80)); - assert!(meter.check_accrue(Weight::from_parts(3, 0))); + assert_eq!(meter.try_consume(Weight::from_parts(3, 0)), Ok(())); assert_eq!(meter.consumed_ratio(), Perbill::from_percent(100)); - assert!(meter.check_accrue(Weight::from_parts(0, 4))); + assert_eq!(meter.try_consume(Weight::from_parts(0, 4)), Ok(())); assert_eq!(meter.consumed_ratio(), Perbill::from_percent(100)); } -- GitLab From a035dc9be718c6327420c87fecb7a752954492f4 Mon Sep 17 00:00:00 2001 From: Tsvetomir Dimitrov Date: Thu, 29 Feb 2024 09:12:02 +0200 Subject: [PATCH 049/188] Remove `AssignmentProviderConfig` and use parameters from `HostConfiguration` instead (#3181) This PR removes `AssignmentProviderConfig` and uses the corresponding ondemand parameters from `HostConfiguration` instead. Additionally `scheduling_lookahead` and all coretime/ondemand related parameters are extracted in a separate struct - `SchedulerParams`. The most relevant commit from the PR is [this one](https://github.com/paritytech/polkadot-sdk/pull/3181/commits/830bc0f5e858944474171bbe33382ad96040b535). Fixes https://github.com/paritytech/polkadot-sdk/issues/2268 --------- Co-authored-by: command-bot <> --- .../zombienet/tests/0002-pov_recovery.toml | 2 +- polkadot/node/service/src/chain_spec.rs | 16 +- polkadot/node/test/service/src/chain_spec.rs | 11 +- polkadot/primitives/src/vstaging/mod.rs | 76 ++++ .../implementers-guide/src/types/runtime.md | 118 +----- .../src/assigner_coretime/mock_helpers.rs | 11 +- .../parachains/src/assigner_coretime/mod.rs | 16 +- .../src/assigner_on_demand/benchmarking.rs | 2 +- .../src/assigner_on_demand/mock_helpers.rs | 11 +- .../parachains/src/assigner_on_demand/mod.rs | 18 +- .../parachains/src/assigner_parachains.rs | 12 +- .../src/assigner_parachains/mock_helpers.rs | 11 +- polkadot/runtime/parachains/src/builder.rs | 19 +- .../runtime/parachains/src/configuration.rs | 133 +++---- .../src/configuration/benchmarking.rs | 2 + .../parachains/src/configuration/migration.rs | 1 + .../src/configuration/migration/v11.rs | 113 +++++- .../src/configuration/migration/v12.rs | 349 ++++++++++++++++++ .../parachains/src/configuration/tests.rs | 51 ++- .../parachains/src/coretime/migration.rs | 19 +- .../runtime/parachains/src/coretime/mod.rs | 4 +- .../runtime/parachains/src/inclusion/tests.rs | 10 +- polkadot/runtime/parachains/src/mock.rs | 23 +- .../runtime/parachains/src/paras/tests.rs | 7 +- .../parachains/src/paras_inherent/tests.rs | 11 +- polkadot/runtime/parachains/src/scheduler.rs | 43 +-- .../parachains/src/scheduler/common.rs | 19 +- .../runtime/parachains/src/scheduler/tests.rs | 81 ++-- .../parachains/src/session_info/tests.rs | 4 +- polkadot/runtime/rococo/src/lib.rs | 1 + .../runtime_parachains_configuration.rs | 50 ++- polkadot/runtime/westend/src/lib.rs | 1 + .../runtime_parachains_configuration.rs | 50 ++- .../functional/0002-parachains-disputes.toml | 4 +- .../0004-parachains-garbage-candidate.toml | 4 +- ...0005-parachains-disputes-past-session.toml | 4 +- .../0006-parachains-max-tranche0.toml | 4 +- .../0007-dispute-freshly-finalized.toml | 4 +- .../0008-dispute-old-finalized.toml | 4 +- .../functional/0010-validator-disabling.toml | 4 +- .../0011-async-backing-6-seconds-rate.toml | 7 +- .../functional/0012-elastic-scaling-mvp.toml | 6 +- .../zombienet_tests/misc/0001-paritydb.toml | 4 +- 43 files changed, 901 insertions(+), 439 deletions(-) create mode 100644 polkadot/runtime/parachains/src/configuration/migration/v12.rs diff --git a/cumulus/zombienet/tests/0002-pov_recovery.toml b/cumulus/zombienet/tests/0002-pov_recovery.toml index fe42fd4b2f6..15a61eba2a0 100644 --- a/cumulus/zombienet/tests/0002-pov_recovery.toml +++ b/cumulus/zombienet/tests/0002-pov_recovery.toml @@ -4,7 +4,7 @@ default_command = "polkadot" chain = "rococo-local" -[relaychain.genesis.runtimeGenesis.patch.configuration.config] +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] # set parameters such that collators only connect to 1 validator as a backing group max_validators_per_core = 1 group_rotation_frequency = 100 # 10 mins diff --git a/polkadot/node/service/src/chain_spec.rs b/polkadot/node/service/src/chain_spec.rs index af241d1cbc5..af05af87a46 100644 --- a/polkadot/node/service/src/chain_spec.rs +++ b/polkadot/node/service/src/chain_spec.rs @@ -24,6 +24,8 @@ use polkadot_primitives::{AccountId, AccountPublic, AssignmentId, ValidatorId}; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; +#[cfg(any(feature = "rococo-native", feature = "westend-native",))] +use polkadot_primitives::vstaging::SchedulerParams; #[cfg(feature = "rococo-native")] use rococo_runtime as rococo; #[cfg(feature = "rococo-native")] @@ -129,8 +131,6 @@ fn default_parachains_host_configuration( max_code_size: MAX_CODE_SIZE, max_pov_size: MAX_POV_SIZE, max_head_data_size: 32 * 1024, - group_rotation_frequency: 20, - paras_availability_period: 4, max_upward_queue_count: 8, max_upward_queue_size: 1024 * 1024, max_downward_message_size: 1024 * 1024, @@ -151,11 +151,16 @@ fn default_parachains_host_configuration( relay_vrf_modulo_samples: 2, zeroth_delay_tranche_width: 0, minimum_validation_upgrade_delay: 5, - scheduling_lookahead: 2, async_backing_params: AsyncBackingParams { max_candidate_depth: 3, allowed_ancestry_len: 2, }, + scheduler_params: SchedulerParams { + lookahead: 2, + group_rotation_frequency: 20, + paras_availability_period: 4, + ..Default::default() + }, ..Default::default() } } @@ -891,7 +896,10 @@ pub fn rococo_testnet_genesis( "sudo": { "key": Some(root_key.clone()) }, "configuration": { "config": polkadot_runtime_parachains::configuration::HostConfiguration { - max_validators_per_core: Some(1), + scheduler_params: SchedulerParams { + max_validators_per_core: Some(1), + ..default_parachains_host_configuration().scheduler_params + }, ..default_parachains_host_configuration() }, }, diff --git a/polkadot/node/test/service/src/chain_spec.rs b/polkadot/node/test/service/src/chain_spec.rs index 4cc387317c3..f14fa9fde58 100644 --- a/polkadot/node/test/service/src/chain_spec.rs +++ b/polkadot/node/test/service/src/chain_spec.rs @@ -19,7 +19,9 @@ use babe_primitives::AuthorityId as BabeId; use grandpa::AuthorityId as GrandpaId; use pallet_staking::Forcing; -use polkadot_primitives::{AccountId, AssignmentId, ValidatorId, MAX_CODE_SIZE, MAX_POV_SIZE}; +use polkadot_primitives::{ + vstaging::SchedulerParams, AccountId, AssignmentId, ValidatorId, MAX_CODE_SIZE, MAX_POV_SIZE, +}; use polkadot_service::chain_spec::{get_account_id_from_seed, get_from_seed, Extensions}; use polkadot_test_runtime::BABE_GENESIS_EPOCH_CONFIG; use sc_chain_spec::{ChainSpec, ChainType}; @@ -165,11 +167,14 @@ fn polkadot_testnet_genesis( max_code_size: MAX_CODE_SIZE, max_pov_size: MAX_POV_SIZE, max_head_data_size: 32 * 1024, - group_rotation_frequency: 20, - paras_availability_period: 4, no_show_slots: 10, minimum_validation_upgrade_delay: 5, max_downward_message_size: 1024, + scheduler_params: SchedulerParams { + group_rotation_frequency: 20, + paras_availability_period: 4, + ..Default::default() + }, ..Default::default() }, } diff --git a/polkadot/primitives/src/vstaging/mod.rs b/polkadot/primitives/src/vstaging/mod.rs index 39d9dfc02c5..bd2a5106c44 100644 --- a/polkadot/primitives/src/vstaging/mod.rs +++ b/polkadot/primitives/src/vstaging/mod.rs @@ -23,6 +23,7 @@ use sp_std::prelude::*; use parity_scale_codec::{Decode, Encode}; use primitives::RuntimeDebug; use scale_info::TypeInfo; +use sp_arithmetic::Perbill; /// Approval voting configuration parameters #[derive( @@ -50,6 +51,81 @@ impl Default for ApprovalVotingParams { } } +/// Scheduler configuration parameters. All coretime/ondemand parameters are here. +#[derive( + RuntimeDebug, + Copy, + Clone, + PartialEq, + Encode, + Decode, + TypeInfo, + serde::Serialize, + serde::Deserialize, +)] +pub struct SchedulerParams { + /// How often parachain groups should be rotated across parachains. + /// + /// Must be non-zero. + pub group_rotation_frequency: BlockNumber, + /// Availability timeout for a block on a core, measured in blocks. + /// + /// This is the maximum amount of blocks after a core became occupied that validators have time + /// to make the block available. + /// + /// This value only has effect on group rotations. If backers backed something at the end of + /// their rotation, the occupied core affects the backing group that comes afterwards. We limit + /// the effect one backing group can have on the next to `paras_availability_period` blocks. + /// + /// Within a group rotation there is no timeout as backers are only affecting themselves. + /// + /// Must be at least 1. With a value of 1, the previous group will not be able to negatively + /// affect the following group at the expense of a tight availability timeline at group + /// rotation boundaries. + pub paras_availability_period: BlockNumber, + /// The maximum number of validators to have per core. + /// + /// `None` means no maximum. + pub max_validators_per_core: Option, + /// The amount of blocks ahead to schedule paras. + pub lookahead: u32, + /// How many cores are managed by the coretime chain. + pub num_cores: u32, + /// The max number of times a claim can time out in availability. + pub max_availability_timeouts: u32, + /// The maximum queue size of the pay as you go module. + pub on_demand_queue_max_size: u32, + /// The target utilization of the spot price queue in percentages. + pub on_demand_target_queue_utilization: Perbill, + /// How quickly the fee rises in reaction to increased utilization. + /// The lower the number the slower the increase. + pub on_demand_fee_variability: Perbill, + /// The minimum amount needed to claim a slot in the spot pricing queue. + pub on_demand_base_fee: Balance, + /// The number of blocks a claim stays in the scheduler's claimqueue before getting cleared. + /// This number should go reasonably higher than the number of blocks in the async backing + /// lookahead. + pub ttl: BlockNumber, +} + +impl> Default for SchedulerParams { + fn default() -> Self { + Self { + group_rotation_frequency: 1u32.into(), + paras_availability_period: 1u32.into(), + max_validators_per_core: Default::default(), + lookahead: 1, + num_cores: Default::default(), + max_availability_timeouts: Default::default(), + on_demand_queue_max_size: ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, + on_demand_target_queue_utilization: Perbill::from_percent(25), + on_demand_fee_variability: Perbill::from_percent(3), + on_demand_base_fee: 10_000_000u128, + ttl: 5u32.into(), + } + } +} + use bitvec::vec::BitVec; /// Bit indices in the `HostConfiguration.node_features` that correspond to different node features. diff --git a/polkadot/roadmap/implementers-guide/src/types/runtime.md b/polkadot/roadmap/implementers-guide/src/types/runtime.md index 4b97409f8df..1dfabd96db7 100644 --- a/polkadot/roadmap/implementers-guide/src/types/runtime.md +++ b/polkadot/roadmap/implementers-guide/src/types/runtime.md @@ -4,106 +4,24 @@ Types used within the runtime exclusively and pervasively. ## Host Configuration -The internal-to-runtime configuration of the parachain host. This is expected to be altered only by governance procedures. - -```rust -struct HostConfiguration { - /// The minimum period, in blocks, between which parachains can update their validation code. - pub validation_upgrade_cooldown: BlockNumber, - /// The delay, in blocks, before a validation upgrade is applied. - pub validation_upgrade_delay: BlockNumber, - /// How long to keep code on-chain, in blocks. This should be sufficiently long that disputes - /// have concluded. - pub code_retention_period: BlockNumber, - /// The maximum validation code size, in bytes. - pub max_code_size: u32, - /// The maximum head-data size, in bytes. - pub max_head_data_size: u32, - /// The amount of availability cores to dedicate to parathreads (on-demand parachains). - pub parathread_cores: u32, - /// The number of retries that a parathread (on-demand parachain) author has to submit their block. - pub parathread_retries: u32, - /// How often parachain groups should be rotated across parachains. - pub group_rotation_frequency: BlockNumber, - /// The availability period, in blocks, for parachains. This is the amount of blocks - /// after inclusion that validators have to make the block available and signal its availability to - /// the chain. Must be at least 1. - pub chain_availability_period: BlockNumber, - /// The availability period, in blocks, for parathreads (on-demand parachains). Same as the `chain_availability_period`, - /// but a differing timeout due to differing requirements. Must be at least 1. - pub thread_availability_period: BlockNumber, - /// The amount of blocks ahead to schedule on-demand parachains. - pub scheduling_lookahead: u32, - /// The maximum number of validators to have per core. `None` means no maximum. - pub max_validators_per_core: Option, - /// The maximum number of validators to use for parachains, in total. `None` means no maximum. - pub max_validators: Option, - /// The amount of sessions to keep for disputes. - pub dispute_period: SessionIndex, - /// How long after dispute conclusion to accept statements. - pub dispute_post_conclusion_acceptance_period: BlockNumber, - /// The maximum number of dispute spam slots - pub dispute_max_spam_slots: u32, - /// The amount of consensus slots that must pass between submitting an assignment and - /// submitting an approval vote before a validator is considered a no-show. - /// Must be at least 1. - pub no_show_slots: u32, - /// The number of delay tranches in total. - pub n_delay_tranches: u32, - /// The width of the zeroth delay tranche for approval assignments. This many delay tranches - /// beyond 0 are all consolidated to form a wide 0 tranche. - pub zeroth_delay_tranche_width: u32, - /// The number of validators needed to approve a block. - pub needed_approvals: u32, - /// The number of samples to use in `RelayVRFModulo` or `RelayVRFModuloCompact` approval assignment criterions. - pub relay_vrf_modulo_samples: u32, - /// Total number of individual messages allowed in the parachain -> relay-chain message queue. - pub max_upward_queue_count: u32, - /// Total size of messages allowed in the parachain -> relay-chain message queue before which - /// no further messages may be added to it. If it exceeds this then the queue may contain only - /// a single message. - pub max_upward_queue_size: u32, - /// The maximum size of an upward message that can be sent by a candidate. - /// - /// This parameter affects the upper bound of size of `CandidateCommitments`. - pub max_upward_message_size: u32, - /// The maximum number of messages that a candidate can contain. - /// - /// This parameter affects the upper bound of size of `CandidateCommitments`. - pub max_upward_message_num_per_candidate: u32, - /// The maximum size of a message that can be put in a downward message queue. - /// - /// Since we require receiving at least one DMP message the obvious upper bound of the size is - /// the PoV size. Of course, there is a lot of other different things that a parachain may - /// decide to do with its PoV so this value in practice will be picked as a fraction of the PoV - /// size. - pub max_downward_message_size: u32, - /// The deposit that the sender should provide for opening an HRMP channel. - pub hrmp_sender_deposit: u32, - /// The deposit that the recipient should provide for accepting opening an HRMP channel. - pub hrmp_recipient_deposit: u32, - /// The maximum number of messages allowed in an HRMP channel at once. - pub hrmp_channel_max_capacity: u32, - /// The maximum total size of messages in bytes allowed in an HRMP channel at once. - pub hrmp_channel_max_total_size: u32, - /// The maximum number of inbound HRMP channels a parachain is allowed to accept. - pub hrmp_max_parachain_inbound_channels: u32, - /// The maximum number of inbound HRMP channels a parathread (on-demand parachain) is allowed to accept. - pub hrmp_max_parathread_inbound_channels: u32, - /// The maximum size of a message that could ever be put into an HRMP channel. - /// - /// This parameter affects the upper bound of size of `CandidateCommitments`. - pub hrmp_channel_max_message_size: u32, - /// The maximum number of outbound HRMP channels a parachain is allowed to open. - pub hrmp_max_parachain_outbound_channels: u32, - /// The maximum number of outbound HRMP channels a parathread (on-demand parachain) is allowed to open. - pub hrmp_max_parathread_outbound_channels: u32, - /// The maximum number of outbound HRMP messages can be sent by a candidate. - /// - /// This parameter affects the upper bound of size of `CandidateCommitments`. - pub hrmp_max_message_num_per_candidate: u32, -} -``` +The internal-to-runtime configuration of the parachain host is kept in `struct HostConfiguration`. This is expected to +be altered only by governance procedures or via migrations from the Polkadot-SDK codebase. The latest definition of +`HostConfiguration` can be found in the project repo +[here](https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/runtime/parachains/src/configuration.rs). Each +parameter has got a doc comment so for any details please refer to the code. + +Some related parameters in `HostConfiguration` are grouped together so that they can be managed easily. These are: +* `async_backing_params` in `struct AsyncBackingParams` +* `executor_params` in `struct ExecutorParams` +* `approval_voting_params` in `struct ApprovalVotingParams` +* `scheduler_params` in `struct SchedulerParams` + +Check the definitions of these structs for further details. + +### Configuration migrations +Modifying `HostConfiguration` requires a storage migration. These migrations are located in the +[`migrations`](https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/runtime/parachains/src/configuration.rs) +subfolder of Polkadot-SDK repo. ## ParaInherentData diff --git a/polkadot/runtime/parachains/src/assigner_coretime/mock_helpers.rs b/polkadot/runtime/parachains/src/assigner_coretime/mock_helpers.rs index 71c3f1fa39f..e2ba0b4f7ea 100644 --- a/polkadot/runtime/parachains/src/assigner_coretime/mock_helpers.rs +++ b/polkadot/runtime/parachains/src/assigner_coretime/mock_helpers.rs @@ -64,11 +64,12 @@ impl GenesisConfigBuilder { pub(super) fn build(self) -> MockGenesisConfig { let mut genesis = default_genesis_config(); let config = &mut genesis.configuration.config; - config.coretime_cores = self.on_demand_cores; - config.on_demand_base_fee = self.on_demand_base_fee; - config.on_demand_fee_variability = self.on_demand_fee_variability; - config.on_demand_queue_max_size = self.on_demand_max_queue_size; - config.on_demand_target_queue_utilization = self.on_demand_target_queue_utilization; + config.scheduler_params.num_cores = self.on_demand_cores; + config.scheduler_params.on_demand_base_fee = self.on_demand_base_fee; + config.scheduler_params.on_demand_fee_variability = self.on_demand_fee_variability; + config.scheduler_params.on_demand_queue_max_size = self.on_demand_max_queue_size; + config.scheduler_params.on_demand_target_queue_utilization = + self.on_demand_target_queue_utilization; let paras = &mut genesis.paras.paras; for para_id in self.onboarded_on_demand_chains { diff --git a/polkadot/runtime/parachains/src/assigner_coretime/mod.rs b/polkadot/runtime/parachains/src/assigner_coretime/mod.rs index 9da81dc816c..e2da89fadd4 100644 --- a/polkadot/runtime/parachains/src/assigner_coretime/mod.rs +++ b/polkadot/runtime/parachains/src/assigner_coretime/mod.rs @@ -30,7 +30,7 @@ mod tests; use crate::{ assigner_on_demand, configuration, paras::AssignCoretime, - scheduler::common::{Assignment, AssignmentProvider, AssignmentProviderConfig}, + scheduler::common::{Assignment, AssignmentProvider}, ParaId, }; @@ -316,14 +316,6 @@ impl AssignmentProvider> for Pallet { } } - fn get_provider_config(_core_idx: CoreIndex) -> AssignmentProviderConfig> { - let config = >::config(); - AssignmentProviderConfig { - max_availability_timeouts: config.on_demand_retries, - ttl: config.on_demand_ttl, - } - } - #[cfg(any(feature = "runtime-benchmarks", test))] fn get_mock_assignment(_: CoreIndex, para_id: primitives::Id) -> Assignment { // Given that we are not tracking anything in `Bulk` assignments, it is safe to always @@ -333,7 +325,7 @@ impl AssignmentProvider> for Pallet { fn session_core_count() -> u32 { let config = >::config(); - config.coretime_cores + config.scheduler_params.num_cores } } @@ -482,8 +474,8 @@ impl AssignCoretime for Pallet { // Add a new core and assign the para to it. let mut config = >::config(); - let core = config.coretime_cores; - config.coretime_cores.saturating_inc(); + let core = config.scheduler_params.num_cores; + config.scheduler_params.num_cores.saturating_inc(); // `assign_coretime` is only called at genesis or by root, so setting the active // config here is fine. diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/benchmarking.rs b/polkadot/runtime/parachains/src/assigner_on_demand/benchmarking.rs index 5a6060cd2b4..8360e7a78d0 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/benchmarking.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/benchmarking.rs @@ -43,7 +43,7 @@ where { ParasShared::::set_session_index(SESSION_INDEX); let mut config = HostConfiguration::default(); - config.coretime_cores = 1; + config.scheduler_params.num_cores = 1; ConfigurationPallet::::force_set_active_config(config); let mut parachains = ParachainsCache::new(); ParasPallet::::initialize_para_now( diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/mock_helpers.rs b/polkadot/runtime/parachains/src/assigner_on_demand/mock_helpers.rs index de30330ac84..f8d1a894f0e 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/mock_helpers.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/mock_helpers.rs @@ -63,11 +63,12 @@ impl GenesisConfigBuilder { pub(super) fn build(self) -> MockGenesisConfig { let mut genesis = default_genesis_config(); let config = &mut genesis.configuration.config; - config.coretime_cores = self.on_demand_cores; - config.on_demand_base_fee = self.on_demand_base_fee; - config.on_demand_fee_variability = self.on_demand_fee_variability; - config.on_demand_queue_max_size = self.on_demand_max_queue_size; - config.on_demand_target_queue_utilization = self.on_demand_target_queue_utilization; + config.scheduler_params.num_cores = self.on_demand_cores; + config.scheduler_params.on_demand_base_fee = self.on_demand_base_fee; + config.scheduler_params.on_demand_fee_variability = self.on_demand_fee_variability; + config.scheduler_params.on_demand_queue_max_size = self.on_demand_max_queue_size; + config.scheduler_params.on_demand_target_queue_utilization = + self.on_demand_target_queue_utilization; let paras = &mut genesis.paras.paras; for para_id in self.onboarded_on_demand_chains { diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs index 1b746e88694..bc450dc7812 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs @@ -201,10 +201,10 @@ pub mod pallet { let old_traffic = SpotTraffic::::get(); match Self::calculate_spot_traffic( old_traffic, - config.on_demand_queue_max_size, + config.scheduler_params.on_demand_queue_max_size, Self::queue_size(), - config.on_demand_target_queue_utilization, - config.on_demand_fee_variability, + config.scheduler_params.on_demand_target_queue_utilization, + config.scheduler_params.on_demand_fee_variability, ) { Ok(new_traffic) => { // Only update storage on change @@ -330,8 +330,9 @@ where let traffic = SpotTraffic::::get(); // Calculate spot price - let spot_price: BalanceOf = - traffic.saturating_mul_int(config.on_demand_base_fee.saturated_into::>()); + let spot_price: BalanceOf = traffic.saturating_mul_int( + config.scheduler_params.on_demand_base_fee.saturated_into::>(), + ); // Is the current price higher than `max_amount` ensure!(spot_price.le(&max_amount), Error::::SpotPriceHigherThanMaxAmount); @@ -450,7 +451,10 @@ where OnDemandQueue::::try_mutate(|queue| { // Abort transaction if queue is too large - ensure!(Self::queue_size() < config.on_demand_queue_max_size, Error::::QueueFull); + ensure!( + Self::queue_size() < config.scheduler_params.on_demand_queue_max_size, + Error::::QueueFull + ); match location { QueuePushDirection::Back => queue.push_back(order), QueuePushDirection::Front => queue.push_front(order), @@ -472,7 +476,7 @@ where target: LOG_TARGET, "Failed to fetch the on demand queue size, returning the max size." ); - return config.on_demand_queue_max_size + return config.scheduler_params.on_demand_queue_max_size }, } } diff --git a/polkadot/runtime/parachains/src/assigner_parachains.rs b/polkadot/runtime/parachains/src/assigner_parachains.rs index 34b5d3c1ec5..b5f342563e9 100644 --- a/polkadot/runtime/parachains/src/assigner_parachains.rs +++ b/polkadot/runtime/parachains/src/assigner_parachains.rs @@ -27,7 +27,7 @@ use primitives::CoreIndex; use crate::{ configuration, paras, - scheduler::common::{Assignment, AssignmentProvider, AssignmentProviderConfig}, + scheduler::common::{Assignment, AssignmentProvider}, }; pub use pallet::*; @@ -58,16 +58,6 @@ impl AssignmentProvider> for Pallet { /// this is a no-op in the case of a bulk assignment slot. fn push_back_assignment(_: Assignment) {} - fn get_provider_config(_core_idx: CoreIndex) -> AssignmentProviderConfig> { - AssignmentProviderConfig { - // The next assignment already goes to the same [`ParaId`], no timeout tracking needed. - max_availability_timeouts: 0, - // The next assignment already goes to the same [`ParaId`], this can be any number - // that's high enough to clear the time it takes to clear backing/availability. - ttl: 10u32.into(), - } - } - #[cfg(any(feature = "runtime-benchmarks", test))] fn get_mock_assignment(_: CoreIndex, para_id: primitives::Id) -> Assignment { Assignment::Bulk(para_id) diff --git a/polkadot/runtime/parachains/src/assigner_parachains/mock_helpers.rs b/polkadot/runtime/parachains/src/assigner_parachains/mock_helpers.rs index e6e9fb074aa..a46e114daea 100644 --- a/polkadot/runtime/parachains/src/assigner_parachains/mock_helpers.rs +++ b/polkadot/runtime/parachains/src/assigner_parachains/mock_helpers.rs @@ -60,11 +60,12 @@ impl GenesisConfigBuilder { pub(super) fn build(self) -> MockGenesisConfig { let mut genesis = default_genesis_config(); let config = &mut genesis.configuration.config; - config.coretime_cores = self.on_demand_cores; - config.on_demand_base_fee = self.on_demand_base_fee; - config.on_demand_fee_variability = self.on_demand_fee_variability; - config.on_demand_queue_max_size = self.on_demand_max_queue_size; - config.on_demand_target_queue_utilization = self.on_demand_target_queue_utilization; + config.scheduler_params.num_cores = self.on_demand_cores; + config.scheduler_params.on_demand_base_fee = self.on_demand_base_fee; + config.scheduler_params.on_demand_fee_variability = self.on_demand_fee_variability; + config.scheduler_params.on_demand_queue_max_size = self.on_demand_max_queue_size; + config.scheduler_params.on_demand_target_queue_utilization = + self.on_demand_target_queue_utilization; let paras = &mut genesis.paras.paras; for para_id in self.onboarded_on_demand_chains { diff --git a/polkadot/runtime/parachains/src/builder.rs b/polkadot/runtime/parachains/src/builder.rs index 500bc70cfa7..0e4e659fef2 100644 --- a/polkadot/runtime/parachains/src/builder.rs +++ b/polkadot/runtime/parachains/src/builder.rs @@ -18,11 +18,7 @@ use crate::{ configuration, inclusion, initializer, paras, paras::ParaKind, paras_inherent, - scheduler::{ - self, - common::{AssignmentProvider, AssignmentProviderConfig}, - CoreOccupied, ParasEntry, - }, + scheduler::{self, common::AssignmentProvider, CoreOccupied, ParasEntry}, session_info, shared, }; use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; @@ -197,7 +193,10 @@ impl BenchBuilder { /// Maximum number of validators per core (a.k.a. max validators per group). This value is used /// if none is explicitly set on the builder. pub(crate) fn fallback_max_validators_per_core() -> u32 { - configuration::Pallet::::config().max_validators_per_core.unwrap_or(5) + configuration::Pallet::::config() + .scheduler_params + .max_validators_per_core + .unwrap_or(5) } /// Specify a mapping of core index/ para id to the number of dispute statements for the @@ -684,7 +683,7 @@ impl BenchBuilder { // We are currently in Session 0, so these changes will take effect in Session 2. Self::setup_para_ids(used_cores); configuration::ActiveConfig::::mutate(|c| { - c.coretime_cores = used_cores; + c.scheduler_params.num_cores = used_cores; }); let validator_ids = Self::generate_validator_pairs(self.max_validators()); @@ -715,8 +714,7 @@ impl BenchBuilder { let cores = (0..used_cores) .into_iter() .map(|i| { - let AssignmentProviderConfig { ttl, .. } = - scheduler::Pallet::::assignment_provider_config(CoreIndex(i)); + let ttl = configuration::Pallet::::config().scheduler_params.ttl; // Load an assignment into provider so that one is present to pop let assignment = ::AssignmentProvider::get_mock_assignment( CoreIndex(i), @@ -731,8 +729,7 @@ impl BenchBuilder { let cores = (0..used_cores) .into_iter() .map(|i| { - let AssignmentProviderConfig { ttl, .. } = - scheduler::Pallet::::assignment_provider_config(CoreIndex(i)); + let ttl = configuration::Pallet::::config().scheduler_params.ttl; // Load an assignment into provider so that one is present to pop let assignment = ::AssignmentProvider::get_mock_assignment( diff --git a/polkadot/runtime/parachains/src/configuration.rs b/polkadot/runtime/parachains/src/configuration.rs index b0e9d03df88..364a15215d3 100644 --- a/polkadot/runtime/parachains/src/configuration.rs +++ b/polkadot/runtime/parachains/src/configuration.rs @@ -29,7 +29,6 @@ use primitives::{ vstaging::{ApprovalVotingParams, NodeFeatures}, AsyncBackingParams, Balance, ExecutorParamError, ExecutorParams, SessionIndex, LEGACY_MIN_BACKING_VOTES, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, - ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, }; use sp_runtime::{traits::Zero, Perbill}; use sp_std::prelude::*; @@ -43,6 +42,7 @@ mod benchmarking; pub mod migration; pub use pallet::*; +use primitives::vstaging::SchedulerParams; const LOG_TARGET: &str = "runtime::configuration"; @@ -118,9 +118,9 @@ pub struct HostConfiguration { /// been completed. /// /// Note, there are situations in which `expected_at` in the past. For example, if - /// [`paras_availability_period`](Self::paras_availability_period) is less than the delay set - /// by this field or if PVF pre-check took more time than the delay. In such cases, the upgrade - /// is further at the earliest possible time determined by + /// [`paras_availability_period`](SchedulerParams::paras_availability_period) is less than the + /// delay set by this field or if PVF pre-check took more time than the delay. In such cases, + /// the upgrade is further at the earliest possible time determined by /// [`minimum_validation_upgrade_delay`](Self::minimum_validation_upgrade_delay). /// /// The rationale for this delay has to do with relay-chain reversions. In case there is an @@ -172,48 +172,7 @@ pub struct HostConfiguration { /// How long to keep code on-chain, in blocks. This should be sufficiently long that disputes /// have concluded. pub code_retention_period: BlockNumber, - /// How many cores are managed by the coretime chain. - pub coretime_cores: u32, - /// The number of retries that a on demand author has to submit their block. - pub on_demand_retries: u32, - /// The maximum queue size of the pay as you go module. - pub on_demand_queue_max_size: u32, - /// The target utilization of the spot price queue in percentages. - pub on_demand_target_queue_utilization: Perbill, - /// How quickly the fee rises in reaction to increased utilization. - /// The lower the number the slower the increase. - pub on_demand_fee_variability: Perbill, - /// The minimum amount needed to claim a slot in the spot pricing queue. - pub on_demand_base_fee: Balance, - /// The number of blocks an on demand claim stays in the scheduler's claimqueue before getting - /// cleared. This number should go reasonably higher than the number of blocks in the async - /// backing lookahead. - pub on_demand_ttl: BlockNumber, - /// How often parachain groups should be rotated across parachains. - /// - /// Must be non-zero. - pub group_rotation_frequency: BlockNumber, - /// The minimum availability period, in blocks. - /// - /// This is the minimum amount of blocks after a core became occupied that validators have time - /// to make the block available. - /// - /// This value only has effect on group rotations. If backers backed something at the end of - /// their rotation, the occupied core affects the backing group that comes afterwards. We limit - /// the effect one backing group can have on the next to `paras_availability_period` blocks. - /// - /// Within a group rotation there is no timeout as backers are only affecting themselves. - /// - /// Must be at least 1. With a value of 1, the previous group will not be able to negatively - /// affect the following group at the expense of a tight availability timeline at group - /// rotation boundaries. - pub paras_availability_period: BlockNumber, - /// The amount of blocks ahead to schedule paras. - pub scheduling_lookahead: u32, - /// The maximum number of validators to have per core. - /// - /// `None` means no maximum. - pub max_validators_per_core: Option, + /// The maximum number of validators to use for parachain consensus, period. /// /// `None` means no maximum. @@ -257,7 +216,7 @@ pub struct HostConfiguration { /// scheduled. This number is controlled by this field. /// /// This value should be greater than - /// [`paras_availability_period`](Self::paras_availability_period). + /// [`paras_availability_period`](SchedulerParams::paras_availability_period). pub minimum_validation_upgrade_delay: BlockNumber, /// The minimum number of valid backing statements required to consider a parachain candidate /// backable. @@ -266,6 +225,8 @@ pub struct HostConfiguration { pub node_features: NodeFeatures, /// Params used by approval-voting pub approval_voting_params: ApprovalVotingParams, + /// Scheduler parameters + pub scheduler_params: SchedulerParams, } impl> Default for HostConfiguration { @@ -275,8 +236,6 @@ impl> Default for HostConfiguration> Default for HostConfiguration> Default for HostConfiguration { ZeroMinimumBackingVotes, /// `executor_params` are inconsistent. InconsistentExecutorParams { inner: ExecutorParamError }, + /// TTL should be bigger than lookahead + LookaheadExceedsTTL, } impl HostConfiguration @@ -373,11 +326,11 @@ where pub fn check_consistency(&self) -> Result<(), InconsistentError> { use InconsistentError::*; - if self.group_rotation_frequency.is_zero() { + if self.scheduler_params.group_rotation_frequency.is_zero() { return Err(ZeroGroupRotationFrequency) } - if self.paras_availability_period.is_zero() { + if self.scheduler_params.paras_availability_period.is_zero() { return Err(ZeroParasAvailabilityPeriod) } @@ -399,10 +352,11 @@ where return Err(MaxPovSizeExceedHardLimit { max_pov_size: self.max_pov_size }) } - if self.minimum_validation_upgrade_delay <= self.paras_availability_period { + if self.minimum_validation_upgrade_delay <= self.scheduler_params.paras_availability_period + { return Err(MinimumValidationUpgradeDelayLessThanChainAvailabilityPeriod { minimum_validation_upgrade_delay: self.minimum_validation_upgrade_delay.clone(), - paras_availability_period: self.paras_availability_period.clone(), + paras_availability_period: self.scheduler_params.paras_availability_period.clone(), }) } @@ -447,6 +401,10 @@ where return Err(InconsistentExecutorParams { inner }) } + if self.scheduler_params.ttl < self.scheduler_params.lookahead.into() { + return Err(LookaheadExceedsTTL) + } + Ok(()) } @@ -471,6 +429,7 @@ pub trait WeightInfo { fn set_config_with_executor_params() -> Weight; fn set_config_with_perbill() -> Weight; fn set_node_feature() -> Weight; + fn set_config_with_scheduler_params() -> Weight; } pub struct TestWeightInfo; @@ -499,6 +458,9 @@ impl WeightInfo for TestWeightInfo { fn set_node_feature() -> Weight { Weight::MAX } + fn set_config_with_scheduler_params() -> Weight { + Weight::MAX + } } #[frame_support::pallet] @@ -520,7 +482,8 @@ pub mod pallet { /// v8-v9: /// v9-v10: /// v10-11: - const STORAGE_VERSION: StorageVersion = StorageVersion::new(11); + /// v11-12: + const STORAGE_VERSION: StorageVersion = StorageVersion::new(12); #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] @@ -679,16 +642,16 @@ pub mod pallet { Self::set_coretime_cores_unchecked(new) } - /// Set the number of retries for a particular on demand. + /// Set the max number of times a claim may timeout on a core before it is abandoned #[pallet::call_index(7)] #[pallet::weight(( T::WeightInfo::set_config_with_u32(), DispatchClass::Operational, ))] - pub fn set_on_demand_retries(origin: OriginFor, new: u32) -> DispatchResult { + pub fn set_max_availability_timeouts(origin: OriginFor, new: u32) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.on_demand_retries = new; + config.scheduler_params.max_availability_timeouts = new; }) } @@ -704,7 +667,7 @@ pub mod pallet { ) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.group_rotation_frequency = new; + config.scheduler_params.group_rotation_frequency = new; }) } @@ -720,7 +683,7 @@ pub mod pallet { ) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.paras_availability_period = new; + config.scheduler_params.paras_availability_period = new; }) } @@ -733,7 +696,7 @@ pub mod pallet { pub fn set_scheduling_lookahead(origin: OriginFor, new: u32) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.scheduling_lookahead = new; + config.scheduler_params.lookahead = new; }) } @@ -749,7 +712,7 @@ pub mod pallet { ) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.max_validators_per_core = new; + config.scheduler_params.max_validators_per_core = new; }) } @@ -1141,7 +1104,7 @@ pub mod pallet { pub fn set_on_demand_base_fee(origin: OriginFor, new: Balance) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.on_demand_base_fee = new; + config.scheduler_params.on_demand_base_fee = new; }) } @@ -1154,7 +1117,7 @@ pub mod pallet { pub fn set_on_demand_fee_variability(origin: OriginFor, new: Perbill) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.on_demand_fee_variability = new; + config.scheduler_params.on_demand_fee_variability = new; }) } @@ -1167,7 +1130,7 @@ pub mod pallet { pub fn set_on_demand_queue_max_size(origin: OriginFor, new: u32) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.on_demand_queue_max_size = new; + config.scheduler_params.on_demand_queue_max_size = new; }) } /// Set the on demand (parathreads) fee variability. @@ -1182,7 +1145,7 @@ pub mod pallet { ) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.on_demand_target_queue_utilization = new; + config.scheduler_params.on_demand_target_queue_utilization = new; }) } /// Set the on demand (parathreads) ttl in the claimqueue. @@ -1194,7 +1157,7 @@ pub mod pallet { pub fn set_on_demand_ttl(origin: OriginFor, new: BlockNumberFor) -> DispatchResult { ensure_root(origin)?; Self::schedule_config_update(|config| { - config.on_demand_ttl = new; + config.scheduler_params.ttl = new; }) } @@ -1244,6 +1207,22 @@ pub mod pallet { config.approval_voting_params = new; }) } + + /// Set scheduler-params. + #[pallet::call_index(55)] + #[pallet::weight(( + T::WeightInfo::set_config_with_scheduler_params(), + DispatchClass::Operational, + ))] + pub fn set_scheduler_params( + origin: OriginFor, + new: SchedulerParams>, + ) -> DispatchResult { + ensure_root(origin)?; + Self::schedule_config_update(|config| { + config.scheduler_params = new; + }) + } } impl Pallet { @@ -1252,7 +1231,7 @@ pub mod pallet { /// To be used if authorization is checked otherwise. pub fn set_coretime_cores_unchecked(new: u32) -> DispatchResult { Self::schedule_config_update(|config| { - config.coretime_cores = new; + config.scheduler_params.num_cores = new; }) } } @@ -1393,7 +1372,7 @@ impl Pallet { let base_config_consistent = base_config.check_consistency().is_ok(); // Now, we need to decide what the new configuration should be. - // We also move the `base_config` to `new_config` to empahsize that the base config was + // We also move the `base_config` to `new_config` to emphasize that the base config was // destroyed by the `updater`. updater(&mut base_config); let new_config = base_config; diff --git a/polkadot/runtime/parachains/src/configuration/benchmarking.rs b/polkadot/runtime/parachains/src/configuration/benchmarking.rs index 67daf1c4598..882b5aab096 100644 --- a/polkadot/runtime/parachains/src/configuration/benchmarking.rs +++ b/polkadot/runtime/parachains/src/configuration/benchmarking.rs @@ -51,6 +51,8 @@ benchmarks! { set_node_feature{}: set_node_feature(RawOrigin::Root, 255, true) + set_config_with_scheduler_params {} : set_scheduler_params(RawOrigin::Root, SchedulerParams::default()) + impl_benchmark_test_suite!( Pallet, crate::mock::new_test_ext(Default::default()), diff --git a/polkadot/runtime/parachains/src/configuration/migration.rs b/polkadot/runtime/parachains/src/configuration/migration.rs index 2838b73092d..87b30b177e7 100644 --- a/polkadot/runtime/parachains/src/configuration/migration.rs +++ b/polkadot/runtime/parachains/src/configuration/migration.rs @@ -18,6 +18,7 @@ pub mod v10; pub mod v11; +pub mod v12; pub mod v6; pub mod v7; pub mod v8; diff --git a/polkadot/runtime/parachains/src/configuration/migration/v11.rs b/polkadot/runtime/parachains/src/configuration/migration/v11.rs index a69061ac138..f6e0e043164 100644 --- a/polkadot/runtime/parachains/src/configuration/migration/v11.rs +++ b/polkadot/runtime/parachains/src/configuration/migration/v11.rs @@ -21,13 +21,122 @@ use frame_support::{ migrations::VersionedMigration, pallet_prelude::*, traits::Defensive, weights::Weight, }; use frame_system::pallet_prelude::BlockNumberFor; -use primitives::{vstaging::ApprovalVotingParams, SessionIndex}; +use primitives::{ + vstaging::ApprovalVotingParams, AsyncBackingParams, ExecutorParams, SessionIndex, + LEGACY_MIN_BACKING_VOTES, ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, +}; use sp_std::vec::Vec; use frame_support::traits::OnRuntimeUpgrade; +use polkadot_core_primitives::Balance; +use primitives::vstaging::NodeFeatures; +use sp_arithmetic::Perbill; use super::v10::V10HostConfiguration; -type V11HostConfiguration = configuration::HostConfiguration; + +#[derive(Clone, Encode, PartialEq, Decode, Debug)] +pub struct V11HostConfiguration { + pub max_code_size: u32, + pub max_head_data_size: u32, + pub max_upward_queue_count: u32, + pub max_upward_queue_size: u32, + pub max_upward_message_size: u32, + pub max_upward_message_num_per_candidate: u32, + pub hrmp_max_message_num_per_candidate: u32, + pub validation_upgrade_cooldown: BlockNumber, + pub validation_upgrade_delay: BlockNumber, + pub async_backing_params: AsyncBackingParams, + pub max_pov_size: u32, + pub max_downward_message_size: u32, + pub hrmp_max_parachain_outbound_channels: u32, + pub hrmp_sender_deposit: Balance, + pub hrmp_recipient_deposit: Balance, + pub hrmp_channel_max_capacity: u32, + pub hrmp_channel_max_total_size: u32, + pub hrmp_max_parachain_inbound_channels: u32, + pub hrmp_channel_max_message_size: u32, + pub executor_params: ExecutorParams, + pub code_retention_period: BlockNumber, + pub coretime_cores: u32, + pub on_demand_retries: u32, + pub on_demand_queue_max_size: u32, + pub on_demand_target_queue_utilization: Perbill, + pub on_demand_fee_variability: Perbill, + pub on_demand_base_fee: Balance, + pub on_demand_ttl: BlockNumber, + pub group_rotation_frequency: BlockNumber, + pub paras_availability_period: BlockNumber, + pub scheduling_lookahead: u32, + pub max_validators_per_core: Option, + pub max_validators: Option, + pub dispute_period: SessionIndex, + pub dispute_post_conclusion_acceptance_period: BlockNumber, + pub no_show_slots: u32, + pub n_delay_tranches: u32, + pub zeroth_delay_tranche_width: u32, + pub needed_approvals: u32, + pub relay_vrf_modulo_samples: u32, + pub pvf_voting_ttl: SessionIndex, + pub minimum_validation_upgrade_delay: BlockNumber, + pub minimum_backing_votes: u32, + pub node_features: NodeFeatures, + pub approval_voting_params: ApprovalVotingParams, +} + +impl> Default for V11HostConfiguration { + fn default() -> Self { + Self { + async_backing_params: AsyncBackingParams { + max_candidate_depth: 0, + allowed_ancestry_len: 0, + }, + group_rotation_frequency: 1u32.into(), + paras_availability_period: 1u32.into(), + no_show_slots: 1u32.into(), + validation_upgrade_cooldown: Default::default(), + validation_upgrade_delay: 2u32.into(), + code_retention_period: Default::default(), + max_code_size: Default::default(), + max_pov_size: Default::default(), + max_head_data_size: Default::default(), + coretime_cores: Default::default(), + on_demand_retries: Default::default(), + scheduling_lookahead: 1, + max_validators_per_core: Default::default(), + max_validators: None, + dispute_period: 6, + dispute_post_conclusion_acceptance_period: 100.into(), + n_delay_tranches: Default::default(), + zeroth_delay_tranche_width: Default::default(), + needed_approvals: Default::default(), + relay_vrf_modulo_samples: Default::default(), + max_upward_queue_count: Default::default(), + max_upward_queue_size: Default::default(), + max_downward_message_size: Default::default(), + max_upward_message_size: Default::default(), + max_upward_message_num_per_candidate: Default::default(), + hrmp_sender_deposit: Default::default(), + hrmp_recipient_deposit: Default::default(), + hrmp_channel_max_capacity: Default::default(), + hrmp_channel_max_total_size: Default::default(), + hrmp_max_parachain_inbound_channels: Default::default(), + hrmp_channel_max_message_size: Default::default(), + hrmp_max_parachain_outbound_channels: Default::default(), + hrmp_max_message_num_per_candidate: Default::default(), + pvf_voting_ttl: 2u32.into(), + minimum_validation_upgrade_delay: 2.into(), + executor_params: Default::default(), + approval_voting_params: ApprovalVotingParams { max_approval_coalesce_count: 1 }, + on_demand_queue_max_size: ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, + on_demand_base_fee: 10_000_000u128, + on_demand_fee_variability: Perbill::from_percent(3), + on_demand_target_queue_utilization: Perbill::from_percent(25), + on_demand_ttl: 5u32.into(), + minimum_backing_votes: LEGACY_MIN_BACKING_VOTES, + node_features: NodeFeatures::EMPTY, + } + } +} mod v10 { use super::*; diff --git a/polkadot/runtime/parachains/src/configuration/migration/v12.rs b/polkadot/runtime/parachains/src/configuration/migration/v12.rs new file mode 100644 index 00000000000..4295a79893e --- /dev/null +++ b/polkadot/runtime/parachains/src/configuration/migration/v12.rs @@ -0,0 +1,349 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! A module that is responsible for migration of storage. + +use crate::configuration::{self, migration::v11::V11HostConfiguration, Config, Pallet}; +use frame_support::{ + migrations::VersionedMigration, + pallet_prelude::*, + traits::{Defensive, OnRuntimeUpgrade}, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use primitives::vstaging::SchedulerParams; +use sp_core::Get; +use sp_staking::SessionIndex; +use sp_std::vec::Vec; + +type V12HostConfiguration = configuration::HostConfiguration; + +mod v11 { + use super::*; + + #[frame_support::storage_alias] + pub(crate) type ActiveConfig = + StorageValue, V11HostConfiguration>, OptionQuery>; + + #[frame_support::storage_alias] + pub(crate) type PendingConfigs = StorageValue< + Pallet, + Vec<(SessionIndex, V11HostConfiguration>)>, + OptionQuery, + >; +} + +mod v12 { + use super::*; + + #[frame_support::storage_alias] + pub(crate) type ActiveConfig = + StorageValue, V12HostConfiguration>, OptionQuery>; + + #[frame_support::storage_alias] + pub(crate) type PendingConfigs = StorageValue< + Pallet, + Vec<(SessionIndex, V12HostConfiguration>)>, + OptionQuery, + >; +} + +pub type MigrateToV12 = VersionedMigration< + 11, + 12, + UncheckedMigrateToV12, + Pallet, + ::DbWeight, +>; + +pub struct UncheckedMigrateToV12(sp_std::marker::PhantomData); + +impl OnRuntimeUpgrade for UncheckedMigrateToV12 { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + log::trace!(target: crate::configuration::LOG_TARGET, "Running pre_upgrade() for HostConfiguration MigrateToV12"); + Ok(Vec::new()) + } + + fn on_runtime_upgrade() -> Weight { + log::info!(target: configuration::LOG_TARGET, "HostConfiguration MigrateToV12 started"); + let weight_consumed = migrate_to_v12::(); + + log::info!(target: configuration::LOG_TARGET, "HostConfiguration MigrateToV12 executed successfully"); + + weight_consumed + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + log::trace!(target: crate::configuration::LOG_TARGET, "Running post_upgrade() for HostConfiguration MigrateToV12"); + ensure!( + StorageVersion::get::>() >= 12, + "Storage version should be >= 12 after the migration" + ); + + Ok(()) + } +} + +fn migrate_to_v12() -> Weight { + // Unusual formatting is justified: + // - make it easier to verify that fields assign what they supposed to assign. + // - this code is transient and will be removed after all migrations are done. + // - this code is important enough to optimize for legibility sacrificing consistency. + #[rustfmt::skip] + let translate = + |pre: V11HostConfiguration>| -> + V12HostConfiguration> + { + V12HostConfiguration { + max_code_size : pre.max_code_size, + max_head_data_size : pre.max_head_data_size, + max_upward_queue_count : pre.max_upward_queue_count, + max_upward_queue_size : pre.max_upward_queue_size, + max_upward_message_size : pre.max_upward_message_size, + max_upward_message_num_per_candidate : pre.max_upward_message_num_per_candidate, + hrmp_max_message_num_per_candidate : pre.hrmp_max_message_num_per_candidate, + validation_upgrade_cooldown : pre.validation_upgrade_cooldown, + validation_upgrade_delay : pre.validation_upgrade_delay, + max_pov_size : pre.max_pov_size, + max_downward_message_size : pre.max_downward_message_size, + hrmp_sender_deposit : pre.hrmp_sender_deposit, + hrmp_recipient_deposit : pre.hrmp_recipient_deposit, + hrmp_channel_max_capacity : pre.hrmp_channel_max_capacity, + hrmp_channel_max_total_size : pre.hrmp_channel_max_total_size, + hrmp_max_parachain_inbound_channels : pre.hrmp_max_parachain_inbound_channels, + hrmp_max_parachain_outbound_channels : pre.hrmp_max_parachain_outbound_channels, + hrmp_channel_max_message_size : pre.hrmp_channel_max_message_size, + code_retention_period : pre.code_retention_period, + max_validators : pre.max_validators, + dispute_period : pre.dispute_period, + dispute_post_conclusion_acceptance_period: pre.dispute_post_conclusion_acceptance_period, + no_show_slots : pre.no_show_slots, + n_delay_tranches : pre.n_delay_tranches, + zeroth_delay_tranche_width : pre.zeroth_delay_tranche_width, + needed_approvals : pre.needed_approvals, + relay_vrf_modulo_samples : pre.relay_vrf_modulo_samples, + pvf_voting_ttl : pre.pvf_voting_ttl, + minimum_validation_upgrade_delay : pre.minimum_validation_upgrade_delay, + async_backing_params : pre.async_backing_params, + executor_params : pre.executor_params, + minimum_backing_votes : pre.minimum_backing_votes, + node_features : pre.node_features, + approval_voting_params : pre.approval_voting_params, + scheduler_params: SchedulerParams { + group_rotation_frequency : pre.group_rotation_frequency, + paras_availability_period : pre.paras_availability_period, + max_validators_per_core : pre.max_validators_per_core, + lookahead : pre.scheduling_lookahead, + num_cores : pre.coretime_cores, + max_availability_timeouts : pre.on_demand_retries, + on_demand_queue_max_size : pre.on_demand_queue_max_size, + on_demand_target_queue_utilization : pre.on_demand_target_queue_utilization, + on_demand_fee_variability : pre.on_demand_fee_variability, + on_demand_base_fee : pre.on_demand_base_fee, + ttl : pre.on_demand_ttl, + } + } + }; + + let v11 = v11::ActiveConfig::::get() + .defensive_proof("Could not decode old config") + .unwrap_or_default(); + let v12 = translate(v11); + v12::ActiveConfig::::set(Some(v12)); + + // Allowed to be empty. + let pending_v11 = v11::PendingConfigs::::get().unwrap_or_default(); + let mut pending_v12 = Vec::new(); + + for (session, v11) in pending_v11.into_iter() { + let v12 = translate(v11); + pending_v12.push((session, v12)); + } + v12::PendingConfigs::::set(Some(pending_v12.clone())); + + let num_configs = (pending_v12.len() + 1) as u64; + T::DbWeight::get().reads_writes(num_configs, num_configs) +} + +#[cfg(test)] +mod tests { + use primitives::LEGACY_MIN_BACKING_VOTES; + use sp_arithmetic::Perbill; + + use super::*; + use crate::mock::{new_test_ext, Test}; + + #[test] + fn v12_deserialized_from_actual_data() { + // Example how to get new `raw_config`: + // We'll obtain the raw_config at a specified a block + // Steps: + // 1. Go to Polkadot.js -> Developer -> Chain state -> Storage: https://polkadot.js.org/apps/#/chainstate + // 2. Set these parameters: + // 2.1. selected state query: configuration; activeConfig(): + // PolkadotRuntimeParachainsConfigurationHostConfiguration + // 2.2. blockhash to query at: + // 0xf89d3ab5312c5f70d396dc59612f0aa65806c798346f9db4b35278baed2e0e53 (the hash of + // the block) + // 2.3. Note the value of encoded storage key -> + // 0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385 for the + // referenced block. + // 2.4. You'll also need the decoded values to update the test. + // 3. Go to Polkadot.js -> Developer -> Chain state -> Raw storage + // 3.1 Enter the encoded storage key and you get the raw config. + + // This exceeds the maximal line width length, but that's fine, since this is not code and + // doesn't need to be read and also leaving it as one line allows to easily copy it. + let raw_config = + hex_literal::hex![ + "0000300000800000080000000000100000c8000005000000050000000200000002000000000000000000000000005000000010000400000000000000000000000000000000000000000000000000000000000000000000000800000000200000040000000000100000b004000000060000006400000002000000190000000000000002000000020000000200000005000000020000000001000000140000000400000001010000000100000001000000000000001027000080b2e60e80c3c9018096980000000000000000000000000005000000" + ]; + + let v12 = + V12HostConfiguration::::decode(&mut &raw_config[..]).unwrap(); + + // We check only a sample of the values here. If we missed any fields or messed up data + // types that would skew all the fields coming after. + assert_eq!(v12.max_code_size, 3_145_728); + assert_eq!(v12.validation_upgrade_cooldown, 2); + assert_eq!(v12.max_pov_size, 5_242_880); + assert_eq!(v12.hrmp_channel_max_message_size, 1_048_576); + assert_eq!(v12.n_delay_tranches, 25); + assert_eq!(v12.minimum_validation_upgrade_delay, 5); + assert_eq!(v12.minimum_backing_votes, LEGACY_MIN_BACKING_VOTES); + assert_eq!(v12.approval_voting_params.max_approval_coalesce_count, 1); + assert_eq!(v12.scheduler_params.group_rotation_frequency, 20); + assert_eq!(v12.scheduler_params.paras_availability_period, 4); + assert_eq!(v12.scheduler_params.lookahead, 1); + assert_eq!(v12.scheduler_params.num_cores, 1); + assert_eq!(v12.scheduler_params.max_availability_timeouts, 0); + assert_eq!(v12.scheduler_params.on_demand_queue_max_size, 10_000); + assert_eq!( + v12.scheduler_params.on_demand_target_queue_utilization, + Perbill::from_percent(25) + ); + assert_eq!(v12.scheduler_params.on_demand_fee_variability, Perbill::from_percent(3)); + assert_eq!(v12.scheduler_params.on_demand_base_fee, 10_000_000); + assert_eq!(v12.scheduler_params.ttl, 5); + } + + #[test] + fn test_migrate_to_v12() { + // Host configuration has lots of fields. However, in this migration we only add one + // field. The most important part to check are a couple of the last fields. We also pick + // extra fields to check arbitrarily, e.g. depending on their position (i.e. the middle) and + // also their type. + // + // We specify only the picked fields and the rest should be provided by the `Default` + // implementation. That implementation is copied over between the two types and should work + // fine. + let v11 = V11HostConfiguration:: { + needed_approvals: 69, + paras_availability_period: 55, + hrmp_recipient_deposit: 1337, + max_pov_size: 1111, + minimum_validation_upgrade_delay: 20, + on_demand_ttl: 3, + on_demand_retries: 10, + ..Default::default() + }; + + let mut pending_configs = Vec::new(); + pending_configs.push((100, v11.clone())); + pending_configs.push((300, v11.clone())); + + new_test_ext(Default::default()).execute_with(|| { + // Implant the v10 version in the state. + v11::ActiveConfig::::set(Some(v11.clone())); + v11::PendingConfigs::::set(Some(pending_configs)); + + migrate_to_v12::(); + + let v12 = v12::ActiveConfig::::get().unwrap(); + assert_eq!(v12.approval_voting_params.max_approval_coalesce_count, 1); + + let mut configs_to_check = v12::PendingConfigs::::get().unwrap(); + configs_to_check.push((0, v12.clone())); + + for (_, v12) in configs_to_check { + #[rustfmt::skip] + { + assert_eq!(v11.max_code_size , v12.max_code_size); + assert_eq!(v11.max_head_data_size , v12.max_head_data_size); + assert_eq!(v11.max_upward_queue_count , v12.max_upward_queue_count); + assert_eq!(v11.max_upward_queue_size , v12.max_upward_queue_size); + assert_eq!(v11.max_upward_message_size , v12.max_upward_message_size); + assert_eq!(v11.max_upward_message_num_per_candidate , v12.max_upward_message_num_per_candidate); + assert_eq!(v11.hrmp_max_message_num_per_candidate , v12.hrmp_max_message_num_per_candidate); + assert_eq!(v11.validation_upgrade_cooldown , v12.validation_upgrade_cooldown); + assert_eq!(v11.validation_upgrade_delay , v12.validation_upgrade_delay); + assert_eq!(v11.max_pov_size , v12.max_pov_size); + assert_eq!(v11.max_downward_message_size , v12.max_downward_message_size); + assert_eq!(v11.hrmp_max_parachain_outbound_channels , v12.hrmp_max_parachain_outbound_channels); + assert_eq!(v11.hrmp_sender_deposit , v12.hrmp_sender_deposit); + assert_eq!(v11.hrmp_recipient_deposit , v12.hrmp_recipient_deposit); + assert_eq!(v11.hrmp_channel_max_capacity , v12.hrmp_channel_max_capacity); + assert_eq!(v11.hrmp_channel_max_total_size , v12.hrmp_channel_max_total_size); + assert_eq!(v11.hrmp_max_parachain_inbound_channels , v12.hrmp_max_parachain_inbound_channels); + assert_eq!(v11.hrmp_channel_max_message_size , v12.hrmp_channel_max_message_size); + assert_eq!(v11.code_retention_period , v12.code_retention_period); + assert_eq!(v11.max_validators , v12.max_validators); + assert_eq!(v11.dispute_period , v12.dispute_period); + assert_eq!(v11.no_show_slots , v12.no_show_slots); + assert_eq!(v11.n_delay_tranches , v12.n_delay_tranches); + assert_eq!(v11.zeroth_delay_tranche_width , v12.zeroth_delay_tranche_width); + assert_eq!(v11.needed_approvals , v12.needed_approvals); + assert_eq!(v11.relay_vrf_modulo_samples , v12.relay_vrf_modulo_samples); + assert_eq!(v11.pvf_voting_ttl , v12.pvf_voting_ttl); + assert_eq!(v11.minimum_validation_upgrade_delay , v12.minimum_validation_upgrade_delay); + assert_eq!(v11.async_backing_params.allowed_ancestry_len, v12.async_backing_params.allowed_ancestry_len); + assert_eq!(v11.async_backing_params.max_candidate_depth , v12.async_backing_params.max_candidate_depth); + assert_eq!(v11.executor_params , v12.executor_params); + assert_eq!(v11.minimum_backing_votes , v12.minimum_backing_votes); + assert_eq!(v11.group_rotation_frequency , v12.scheduler_params.group_rotation_frequency); + assert_eq!(v11.paras_availability_period , v12.scheduler_params.paras_availability_period); + assert_eq!(v11.max_validators_per_core , v12.scheduler_params.max_validators_per_core); + assert_eq!(v11.scheduling_lookahead , v12.scheduler_params.lookahead); + assert_eq!(v11.coretime_cores , v12.scheduler_params.num_cores); + assert_eq!(v11.on_demand_retries , v12.scheduler_params.max_availability_timeouts); + assert_eq!(v11.on_demand_queue_max_size , v12.scheduler_params.on_demand_queue_max_size); + assert_eq!(v11.on_demand_target_queue_utilization , v12.scheduler_params.on_demand_target_queue_utilization); + assert_eq!(v11.on_demand_fee_variability , v12.scheduler_params.on_demand_fee_variability); + assert_eq!(v11.on_demand_base_fee , v12.scheduler_params.on_demand_base_fee); + assert_eq!(v11.on_demand_ttl , v12.scheduler_params.ttl); + }; // ; makes this a statement. `rustfmt::skip` cannot be put on an expression. + } + }); + } + + // Test that migration doesn't panic in case there are no pending configurations upgrades in + // pallet's storage. + #[test] + fn test_migrate_to_v12_no_pending() { + let v11 = V11HostConfiguration::::default(); + + new_test_ext(Default::default()).execute_with(|| { + // Implant the v10 version in the state. + v11::ActiveConfig::::set(Some(v11)); + // Ensure there are no pending configs. + v12::PendingConfigs::::set(None); + + // Shouldn't fail. + migrate_to_v12::(); + }); + } +} diff --git a/polkadot/runtime/parachains/src/configuration/tests.rs b/polkadot/runtime/parachains/src/configuration/tests.rs index f1570017dd7..254511231ca 100644 --- a/polkadot/runtime/parachains/src/configuration/tests.rs +++ b/polkadot/runtime/parachains/src/configuration/tests.rs @@ -226,8 +226,11 @@ fn invariants() { ); ActiveConfig::::put(HostConfiguration { - paras_availability_period: 10, minimum_validation_upgrade_delay: 11, + scheduler_params: SchedulerParams { + paras_availability_period: 10, + ..Default::default() + }, ..Default::default() }); assert_err!( @@ -283,12 +286,6 @@ fn setting_pending_config_members() { max_code_size: 100_000, max_pov_size: 1024, max_head_data_size: 1_000, - coretime_cores: 2, - on_demand_retries: 5, - group_rotation_frequency: 20, - paras_availability_period: 10, - scheduling_lookahead: 3, - max_validators_per_core: None, max_validators: None, dispute_period: 239, dispute_post_conclusion_acceptance_period: 10, @@ -314,13 +311,21 @@ fn setting_pending_config_members() { minimum_validation_upgrade_delay: 20, executor_params: Default::default(), approval_voting_params: ApprovalVotingParams { max_approval_coalesce_count: 1 }, - on_demand_queue_max_size: 10_000u32, - on_demand_base_fee: 10_000_000u128, - on_demand_fee_variability: Perbill::from_percent(3), - on_demand_target_queue_utilization: Perbill::from_percent(25), - on_demand_ttl: 5u32, minimum_backing_votes: 5, node_features: bitvec![u8, Lsb0; 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1], + scheduler_params: SchedulerParams { + group_rotation_frequency: 20, + paras_availability_period: 10, + max_validators_per_core: None, + lookahead: 3, + num_cores: 2, + max_availability_timeouts: 5, + on_demand_queue_max_size: 10_000u32, + on_demand_base_fee: 10_000_000u128, + on_demand_fee_variability: Perbill::from_percent(3), + on_demand_target_queue_utilization: Perbill::from_percent(25), + ttl: 5u32, + }, }; Configuration::set_validation_upgrade_cooldown( @@ -342,13 +347,19 @@ fn setting_pending_config_members() { Configuration::set_max_pov_size(RuntimeOrigin::root(), new_config.max_pov_size).unwrap(); Configuration::set_max_head_data_size(RuntimeOrigin::root(), new_config.max_head_data_size) .unwrap(); - Configuration::set_coretime_cores(RuntimeOrigin::root(), new_config.coretime_cores) - .unwrap(); - Configuration::set_on_demand_retries(RuntimeOrigin::root(), new_config.on_demand_retries) - .unwrap(); + Configuration::set_coretime_cores( + RuntimeOrigin::root(), + new_config.scheduler_params.num_cores, + ) + .unwrap(); + Configuration::set_max_availability_timeouts( + RuntimeOrigin::root(), + new_config.scheduler_params.max_availability_timeouts, + ) + .unwrap(); Configuration::set_group_rotation_frequency( RuntimeOrigin::root(), - new_config.group_rotation_frequency, + new_config.scheduler_params.group_rotation_frequency, ) .unwrap(); // This comes out of order to satisfy the validity criteria for the chain and thread @@ -360,17 +371,17 @@ fn setting_pending_config_members() { .unwrap(); Configuration::set_paras_availability_period( RuntimeOrigin::root(), - new_config.paras_availability_period, + new_config.scheduler_params.paras_availability_period, ) .unwrap(); Configuration::set_scheduling_lookahead( RuntimeOrigin::root(), - new_config.scheduling_lookahead, + new_config.scheduler_params.lookahead, ) .unwrap(); Configuration::set_max_validators_per_core( RuntimeOrigin::root(), - new_config.max_validators_per_core, + new_config.scheduler_params.max_validators_per_core, ) .unwrap(); Configuration::set_max_validators(RuntimeOrigin::root(), new_config.max_validators) diff --git a/polkadot/runtime/parachains/src/coretime/migration.rs b/polkadot/runtime/parachains/src/coretime/migration.rs index 9bc0a20ef5b..03fecc58570 100644 --- a/polkadot/runtime/parachains/src/coretime/migration.rs +++ b/polkadot/runtime/parachains/src/coretime/migration.rs @@ -114,7 +114,7 @@ mod v_coretime { let legacy_paras = paras::Parachains::::get(); let config = >::config(); - let total_core_count = config.coretime_cores + legacy_paras.len() as u32; + let total_core_count = config.scheduler_params.num_cores + legacy_paras.len() as u32; let dmp_queue_size = crate::dmp::Pallet::::dmq_contents(T::BrokerId::get().into()).len() as u32; @@ -150,7 +150,7 @@ mod v_coretime { // Migrate to Coretime. // - // NOTE: Also migrates coretime_cores config value in configuration::ActiveConfig. + // NOTE: Also migrates `num_cores` config value in configuration::ActiveConfig. fn migrate_to_coretime< T: Config, SendXcm: xcm::v4::SendXcm, @@ -176,8 +176,8 @@ mod v_coretime { } let config = >::config(); - // coretime_cores was on_demand_cores until now: - for on_demand in 0..config.coretime_cores { + // num_cores was on_demand_cores until now: + for on_demand in 0..config.scheduler_params.num_cores { let core = CoreIndex(legacy_count.saturating_add(on_demand as _)); let r = assigner_coretime::Pallet::::assign_core( core, @@ -189,9 +189,9 @@ mod v_coretime { log::error!("Creating assignment for existing on-demand core, failed: {:?}", err); } } - let total_cores = config.coretime_cores + legacy_count; + let total_cores = config.scheduler_params.num_cores + legacy_count; configuration::ActiveConfig::::mutate(|c| { - c.coretime_cores = total_cores; + c.scheduler_params.num_cores = total_cores; }); if let Err(err) = migrate_send_assignments_to_coretime_chain::() { @@ -200,7 +200,9 @@ mod v_coretime { let single_weight = ::WeightInfo::assign_core(1); single_weight - .saturating_mul(u64::from(legacy_count.saturating_add(config.coretime_cores))) + .saturating_mul(u64::from( + legacy_count.saturating_add(config.scheduler_params.num_cores), + )) // Second read from sending assignments to the coretime chain. .saturating_add(T::DbWeight::get().reads_writes(2, 1)) } @@ -244,7 +246,8 @@ mod v_coretime { Some(mk_coretime_call(crate::coretime::CoretimeCalls::SetLease(p.into(), time_slice))) }); - let core_count: u16 = configuration::Pallet::::config().coretime_cores.saturated_into(); + let core_count: u16 = + configuration::Pallet::::config().scheduler_params.num_cores.saturated_into(); let set_core_count = iter::once(mk_coretime_call( crate::coretime::CoretimeCalls::NotifyCoreCount(core_count), )); diff --git a/polkadot/runtime/parachains/src/coretime/mod.rs b/polkadot/runtime/parachains/src/coretime/mod.rs index 531f5c2e4e4..eb9646d7e86 100644 --- a/polkadot/runtime/parachains/src/coretime/mod.rs +++ b/polkadot/runtime/parachains/src/coretime/mod.rs @@ -214,8 +214,8 @@ impl Pallet { } pub fn initializer_on_new_session(notification: &SessionChangeNotification>) { - let old_core_count = notification.prev_config.coretime_cores; - let new_core_count = notification.new_config.coretime_cores; + let old_core_count = notification.prev_config.scheduler_params.num_cores; + let new_core_count = notification.new_config.scheduler_params.num_cores; if new_core_count != old_core_count { let core_count: u16 = new_core_count.saturated_into(); let message = Xcm(vec![ diff --git a/polkadot/runtime/parachains/src/inclusion/tests.rs b/polkadot/runtime/parachains/src/inclusion/tests.rs index d2b5a67c3e4..3fe7d7f0c7d 100644 --- a/polkadot/runtime/parachains/src/inclusion/tests.rs +++ b/polkadot/runtime/parachains/src/inclusion/tests.rs @@ -47,10 +47,10 @@ use test_helpers::{dummy_collator, dummy_collator_signature, dummy_validation_co fn default_config() -> HostConfiguration { let mut config = HostConfiguration::default(); - config.coretime_cores = 1; + config.scheduler_params.num_cores = 1; config.max_code_size = 0b100000; config.max_head_data_size = 0b100000; - config.group_rotation_frequency = u32::MAX; + config.scheduler_params.group_rotation_frequency = u32::MAX; config } @@ -224,7 +224,7 @@ pub(crate) fn run_to_block( } pub(crate) fn expected_bits() -> usize { - Paras::parachains().len() + Configuration::config().coretime_cores as usize + Paras::parachains().len() + Configuration::config().scheduler_params.num_cores as usize } fn default_bitfield() -> AvailabilityBitfield { @@ -386,7 +386,7 @@ fn collect_pending_cleans_up_pending() { (thread_a, ParaKind::Parathread), ]; let mut config = genesis_config(paras); - config.configuration.config.group_rotation_frequency = 3; + config.configuration.config.scheduler_params.group_rotation_frequency = 3; new_test_ext(config).execute_with(|| { let default_candidate = TestCandidateBuilder::default().build(); >::insert( @@ -2062,7 +2062,7 @@ fn check_allowed_relay_parents() { } let validator_public = validator_pubkeys(&validators); let mut config = genesis_config(paras); - config.configuration.config.group_rotation_frequency = 1; + config.configuration.config.scheduler_params.group_rotation_frequency = 1; new_test_ext(config).execute_with(|| { shared::Pallet::::set_active_validators_ascending(validator_public.clone()); diff --git a/polkadot/runtime/parachains/src/mock.rs b/polkadot/runtime/parachains/src/mock.rs index 1925ca19501..e18be03bdeb 100644 --- a/polkadot/runtime/parachains/src/mock.rs +++ b/polkadot/runtime/parachains/src/mock.rs @@ -23,7 +23,7 @@ use crate::{ initializer, origin, paras, paras::ParaKind, paras_inherent, scheduler, - scheduler::common::{AssignmentProvider, AssignmentProviderConfig}, + scheduler::common::AssignmentProvider, session_info, shared, ParaId, }; use frame_support::pallet_prelude::*; @@ -463,10 +463,6 @@ pub mod mock_assigner { pub(super) type MockAssignmentQueue = StorageValue<_, VecDeque, ValueQuery>; - #[pallet::storage] - pub(super) type MockProviderConfig = - StorageValue<_, AssignmentProviderConfig, OptionQuery>; - #[pallet::storage] pub(super) type MockCoreCount = StorageValue<_, u32, OptionQuery>; } @@ -478,12 +474,6 @@ pub mod mock_assigner { MockAssignmentQueue::::mutate(|queue| queue.push_back(assignment)); } - // This configuration needs to be customized to service `get_provider_config` in - // scheduler tests. - pub fn set_assignment_provider_config(config: AssignmentProviderConfig) { - MockProviderConfig::::set(Some(config)); - } - // Allows for customized core count in scheduler tests, rather than a core count // derived from on-demand config + parachain count. pub fn set_core_count(count: u32) { @@ -512,17 +502,6 @@ pub mod mock_assigner { // in the mock assigner. fn push_back_assignment(_assignment: Assignment) {} - // Gets the provider config we set earlier using `set_assignment_provider_config`, falling - // back to the on demand parachain configuration if none was set. - fn get_provider_config(_core_idx: CoreIndex) -> AssignmentProviderConfig { - match MockProviderConfig::::get() { - Some(config) => config, - None => AssignmentProviderConfig { - max_availability_timeouts: 1, - ttl: BlockNumber::from(5u32), - }, - } - } #[cfg(any(feature = "runtime-benchmarks", test))] fn get_mock_assignment(_: CoreIndex, para_id: ParaId) -> Assignment { Assignment::Bulk(para_id) diff --git a/polkadot/runtime/parachains/src/paras/tests.rs b/polkadot/runtime/parachains/src/paras/tests.rs index 24ea919ec87..262ec9d3fdb 100644 --- a/polkadot/runtime/parachains/src/paras/tests.rs +++ b/polkadot/runtime/parachains/src/paras/tests.rs @@ -17,7 +17,7 @@ use super::*; use frame_support::{assert_err, assert_ok, assert_storage_noop}; use keyring::Sr25519Keyring; -use primitives::{BlockNumber, PARACHAIN_KEY_TYPE_ID}; +use primitives::{vstaging::SchedulerParams, BlockNumber, PARACHAIN_KEY_TYPE_ID}; use sc_keystore::LocalKeystore; use sp_keystore::{Keystore, KeystorePtr}; use std::sync::Arc; @@ -909,7 +909,10 @@ fn full_parachain_cleanup_storage() { minimum_validation_upgrade_delay: 2, // Those are not relevant to this test. However, HostConfiguration is still a // subject for the consistency check. - paras_availability_period: 1, + scheduler_params: SchedulerParams { + paras_availability_period: 1, + ..Default::default() + }, ..Default::default() }, }, diff --git a/polkadot/runtime/parachains/src/paras_inherent/tests.rs b/polkadot/runtime/parachains/src/paras_inherent/tests.rs index defb2f4404f..b7285ec884a 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/tests.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/tests.rs @@ -27,13 +27,14 @@ mod enter { builder::{Bench, BenchBuilder}, mock::{mock_assigner, new_test_ext, BlockLength, BlockWeights, MockGenesisConfig, Test}, scheduler::{ - common::{Assignment, AssignmentProvider, AssignmentProviderConfig}, + common::{Assignment, AssignmentProvider}, ParasEntry, }, }; use assert_matches::assert_matches; use frame_support::assert_ok; use frame_system::limits; + use primitives::vstaging::SchedulerParams; use sp_runtime::Perbill; use sp_std::collections::btree_map::BTreeMap; @@ -87,7 +88,7 @@ mod enter { // `create_inherent` and will not cause `enter` to early. fn include_backed_candidates() { let config = MockGenesisConfig::default(); - assert!(config.configuration.config.scheduling_lookahead > 0); + assert!(config.configuration.config.scheduler_params.lookahead > 0); new_test_ext(config).execute_with(|| { let dispute_statements = BTreeMap::new(); @@ -625,7 +626,7 @@ mod enter { #[test] fn limit_candidates_over_weight_1() { let config = MockGenesisConfig::default(); - assert!(config.configuration.config.scheduling_lookahead > 0); + assert!(config.configuration.config.scheduler_params.lookahead > 0); new_test_ext(config).execute_with(|| { // Create the inherent data for this block @@ -706,8 +707,8 @@ mod enter { let cores = (0..used_cores) .into_iter() .map(|i| { - let AssignmentProviderConfig { ttl, .. } = - scheduler::Pallet::::assignment_provider_config(CoreIndex(i)); + let SchedulerParams { ttl, .. } = + >::config().scheduler_params; // Load an assignment into provider so that one is present to pop let assignment = ::AssignmentProvider::get_mock_assignment( diff --git a/polkadot/runtime/parachains/src/scheduler.rs b/polkadot/runtime/parachains/src/scheduler.rs index 3dbb050fb4e..61ab36dbe96 100644 --- a/polkadot/runtime/parachains/src/scheduler.rs +++ b/polkadot/runtime/parachains/src/scheduler.rs @@ -51,7 +51,7 @@ use sp_std::{ pub mod common; -use common::{Assignment, AssignmentProvider, AssignmentProviderConfig}; +use common::{Assignment, AssignmentProvider}; pub use pallet::*; @@ -222,7 +222,7 @@ impl Pallet { let n_cores = core::cmp::max( T::AssignmentProvider::session_core_count(), - match config.max_validators_per_core { + match config.scheduler_params.max_validators_per_core { Some(x) if x != 0 => validators.len() as u32 / x, _ => 0, }, @@ -350,6 +350,7 @@ impl Pallet { fn drop_expired_claims_from_claimqueue() { let now = >::block_number(); let availability_cores = AvailabilityCores::::get(); + let ttl = >::config().scheduler_params.ttl; ClaimQueue::::mutate(|cq| { for (idx, _) in (0u32..).zip(availability_cores) { @@ -382,8 +383,6 @@ impl Pallet { if let Some(assignment) = T::AssignmentProvider::pop_assignment_for_core(core_idx) { - let AssignmentProviderConfig { ttl, .. } = - T::AssignmentProvider::get_provider_config(core_idx); core_claimqueue.push_back(ParasEntry::new(assignment, now + ttl)); } } @@ -428,7 +427,7 @@ impl Pallet { } let rotations_since_session_start: BlockNumberFor = - (at - session_start_block) / config.group_rotation_frequency; + (at - session_start_block) / config.scheduler_params.group_rotation_frequency; let rotations_since_session_start = as TryInto>::try_into(rotations_since_session_start) @@ -460,9 +459,9 @@ impl Pallet { // Note: blocks backed in this rotation will never time out here as backed_in + // config.paras_availability_period will always be > now for these blocks, as // otherwise above condition would not be true. - pending_since + config.paras_availability_period + pending_since + config.scheduler_params.paras_availability_period } else { - next_rotation + config.paras_availability_period + next_rotation + config.scheduler_params.paras_availability_period }; AvailabilityTimeoutStatus { timed_out: time_out_at <= now, live_until: time_out_at } @@ -478,7 +477,8 @@ impl Pallet { let now = >::block_number() + One::one(); let rotation_info = Self::group_rotation_info(now); - let current_window = rotation_info.last_rotation_at() + config.paras_availability_period; + let current_window = + rotation_info.last_rotation_at() + config.scheduler_params.paras_availability_period; now < current_window } @@ -488,7 +488,7 @@ impl Pallet { ) -> GroupRotationInfo> { let session_start_block = Self::session_start_block(); let group_rotation_frequency = - >::config().group_rotation_frequency; + >::config().scheduler_params.group_rotation_frequency; GroupRotationInfo { session_start_block, now, group_rotation_frequency } } @@ -508,6 +508,8 @@ impl Pallet { /// Return the next thing that will be scheduled on this core assuming it is currently /// occupied and the candidate occupying it times out. pub(crate) fn next_up_on_time_out(core: CoreIndex) -> Option { + let max_availability_timeouts = + >::config().scheduler_params.max_availability_timeouts; Self::next_up_on_available(core).or_else(|| { // Or, if none, the claim currently occupying the core, // as it would be put back on the queue after timing out if number of retries is not at @@ -515,16 +517,12 @@ impl Pallet { let cores = AvailabilityCores::::get(); cores.get(core.0 as usize).and_then(|c| match c { CoreOccupied::Free => None, - CoreOccupied::Paras(pe) => { - let AssignmentProviderConfig { max_availability_timeouts, .. } = - T::AssignmentProvider::get_provider_config(core); - + CoreOccupied::Paras(pe) => if pe.availability_timeouts < max_availability_timeouts { Some(Self::paras_entry_to_scheduled_core(pe)) } else { None - } - }, + }, }) }) } @@ -566,7 +564,7 @@ impl Pallet { // ClaimQueue related functions // fn claimqueue_lookahead() -> u32 { - >::config().scheduling_lookahead + >::config().scheduler_params.lookahead } /// Frees cores and fills the free claimqueue spots by popping from the `AssignmentProvider`. @@ -585,15 +583,15 @@ impl Pallet { let n_lookahead = Self::claimqueue_lookahead().max(1); let n_session_cores = T::AssignmentProvider::session_core_count(); let cq = ClaimQueue::::get(); - let ttl = >::config().on_demand_ttl; + let config = >::config(); + let max_availability_timeouts = config.scheduler_params.max_availability_timeouts; + let ttl = config.scheduler_params.ttl; for core_idx in 0..n_session_cores { let core_idx = CoreIndex::from(core_idx); // add previously timedout paras back into the queue if let Some(mut entry) = timedout_paras.remove(&core_idx) { - let AssignmentProviderConfig { max_availability_timeouts, .. } = - T::AssignmentProvider::get_provider_config(core_idx); if entry.availability_timeouts < max_availability_timeouts { // Increment the timeout counter. entry.availability_timeouts += 1; @@ -668,13 +666,6 @@ impl Pallet { .filter_map(|(core_idx, v)| v.front().map(|e| (core_idx, e.assignment.para_id()))) } - #[cfg(any(feature = "runtime-benchmarks", test))] - pub(crate) fn assignment_provider_config( - core_idx: CoreIndex, - ) -> AssignmentProviderConfig> { - T::AssignmentProvider::get_provider_config(core_idx) - } - #[cfg(any(feature = "try-runtime", test))] fn claimqueue_len() -> usize { ClaimQueue::::get().iter().map(|la_vec| la_vec.1.len()).sum() diff --git a/polkadot/runtime/parachains/src/scheduler/common.rs b/polkadot/runtime/parachains/src/scheduler/common.rs index 2eb73385803..66a4e6d30be 100644 --- a/polkadot/runtime/parachains/src/scheduler/common.rs +++ b/polkadot/runtime/parachains/src/scheduler/common.rs @@ -48,22 +48,10 @@ impl Assignment { } } -#[derive(Encode, Decode, TypeInfo)] -/// A set of variables required by the scheduler in order to operate. -pub struct AssignmentProviderConfig { - /// How many times a collation can time out on availability. - /// Zero timeouts still means that a collation can be provided as per the slot auction - /// assignment provider. - pub max_availability_timeouts: u32, - - /// How long the collator has to provide a collation to the backing group before being dropped. - pub ttl: BlockNumber, -} - pub trait AssignmentProvider { /// Pops an [`Assignment`] from the provider for a specified [`CoreIndex`]. /// - /// This is where assignments come into existance. + /// This is where assignments come into existence. fn pop_assignment_for_core(core_idx: CoreIndex) -> Option; /// A previously popped `Assignment` has been fully processed. @@ -77,14 +65,11 @@ pub trait AssignmentProvider { /// Push back a previously popped assignment. /// /// If the assignment could not be processed within the current session, it can be pushed back - /// to the assignment provider in order to be poppped again later. + /// to the assignment provider in order to be popped again later. /// /// This is the second way the life of an assignment can come to an end. fn push_back_assignment(assignment: Assignment); - /// Returns a set of variables needed by the scheduler - fn get_provider_config(core_idx: CoreIndex) -> AssignmentProviderConfig; - /// Push some assignment for mocking/benchmarks purposes. /// /// Useful for benchmarks and testing. The returned assignment is "valid" and can if need be diff --git a/polkadot/runtime/parachains/src/scheduler/tests.rs b/polkadot/runtime/parachains/src/scheduler/tests.rs index 9af23ce64bd..28b3a6b4f5d 100644 --- a/polkadot/runtime/parachains/src/scheduler/tests.rs +++ b/polkadot/runtime/parachains/src/scheduler/tests.rs @@ -18,7 +18,9 @@ use super::*; use frame_support::assert_ok; use keyring::Sr25519Keyring; -use primitives::{BlockNumber, SessionIndex, ValidationCode, ValidatorId}; +use primitives::{ + vstaging::SchedulerParams, BlockNumber, SessionIndex, ValidationCode, ValidatorId, +}; use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; use crate::{ @@ -103,15 +105,19 @@ fn run_to_end_of_block( fn default_config() -> HostConfiguration { HostConfiguration { - coretime_cores: 3, - group_rotation_frequency: 10, - paras_availability_period: 3, - scheduling_lookahead: 2, // This field does not affect anything that scheduler does. However, `HostConfiguration` // is still a subject to consistency test. It requires that // `minimum_validation_upgrade_delay` is greater than `chain_availability_period` and // `thread_availability_period`. minimum_validation_upgrade_delay: 6, + scheduler_params: SchedulerParams { + group_rotation_frequency: 10, + paras_availability_period: 3, + lookahead: 2, + num_cores: 3, + max_availability_timeouts: 1, + ..Default::default() + }, ..Default::default() } } @@ -155,7 +161,7 @@ fn scheduled_entries() -> impl Iterator(vec![para_a])); } else { assert!(!claimqueue_contains_para_ids::(vec![para_a])); @@ -822,7 +825,7 @@ fn on_demand_claims_are_pruned_after_timing_out() { assert!(!availability_cores_contains_para_ids::(vec![para_a])); // #25 - now += max_retries + 2; + now += max_timeouts + 2; // Add assignment back to the mix. MockAssigner::add_test_assignment(assignment_a.clone()); @@ -833,7 +836,7 @@ fn on_demand_claims_are_pruned_after_timing_out() { // #26 now += 1; // Run to block #n but this time have group 1 conclude the availabilty. - for n in now..=(now + max_retries + 1) { + for n in now..=(now + max_timeouts + 1) { // #n run_to_block(n, |_| None); // Time out core 0 if group 0 is assigned to it, if group 1 is assigned, conclude. @@ -874,10 +877,8 @@ fn on_demand_claims_are_pruned_after_timing_out() { fn availability_predicate_works() { let genesis_config = genesis_config(&default_config()); - let HostConfiguration { group_rotation_frequency, paras_availability_period, .. } = - default_config(); - - assert!(paras_availability_period < group_rotation_frequency); + let SchedulerParams { group_rotation_frequency, paras_availability_period, .. } = + default_config().scheduler_params; new_test_ext(genesis_config).execute_with(|| { run_to_block(1 + paras_availability_period, |_| None); @@ -1044,7 +1045,7 @@ fn next_up_on_time_out_reuses_claim_if_nothing_queued() { #[test] fn session_change_requires_reschedule_dropping_removed_paras() { let mut config = default_config(); - config.scheduling_lookahead = 1; + config.scheduler_params.lookahead = 1; let genesis_config = genesis_config(&config); let para_a = ParaId::from(1_u32); @@ -1056,7 +1057,7 @@ fn session_change_requires_reschedule_dropping_removed_paras() { new_test_ext(genesis_config).execute_with(|| { // Setting explicit core count MockAssigner::set_core_count(5); - let assignment_provider_ttl = MockAssigner::get_provider_config(CoreIndex::from(0)).ttl; + let coretime_ttl = >::config().scheduler_params.ttl; schedule_blank_para(para_a); schedule_blank_para(para_b); @@ -1120,7 +1121,7 @@ fn session_change_requires_reschedule_dropping_removed_paras() { vec![ParasEntry::new( Assignment::Bulk(para_a), // At end of block 2 - assignment_provider_ttl + 2 + coretime_ttl + 2 )] .into_iter() .collect() @@ -1169,7 +1170,7 @@ fn session_change_requires_reschedule_dropping_removed_paras() { vec![ParasEntry::new( Assignment::Bulk(para_a), // At block 3 - assignment_provider_ttl + 3 + coretime_ttl + 3 )] .into_iter() .collect() @@ -1179,7 +1180,7 @@ fn session_change_requires_reschedule_dropping_removed_paras() { vec![ParasEntry::new( Assignment::Bulk(para_b), // At block 3 - assignment_provider_ttl + 3 + coretime_ttl + 3 )] .into_iter() .collect() diff --git a/polkadot/runtime/parachains/src/session_info/tests.rs b/polkadot/runtime/parachains/src/session_info/tests.rs index 92a50575ded..a5bfeae0745 100644 --- a/polkadot/runtime/parachains/src/session_info/tests.rs +++ b/polkadot/runtime/parachains/src/session_info/tests.rs @@ -25,7 +25,7 @@ use crate::{ util::take_active_subset, }; use keyring::Sr25519Keyring; -use primitives::{BlockNumber, ValidatorId, ValidatorIndex}; +use primitives::{vstaging::SchedulerParams, BlockNumber, ValidatorId, ValidatorIndex}; fn run_to_block( to: BlockNumber, @@ -62,9 +62,9 @@ fn run_to_block( fn default_config() -> HostConfiguration { HostConfiguration { - coretime_cores: 1, dispute_period: 2, needed_approvals: 3, + scheduler_params: SchedulerParams { num_cores: 1, ..Default::default() }, ..Default::default() } } diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 173301e1ad9..f3c0c3d6bd8 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -1658,6 +1658,7 @@ pub mod migrations { parachains_configuration::migration::v11::MigrateToV11, // This needs to come after the `parachains_configuration` above as we are reading the configuration. coretime::migration::MigrateToCoretime, + parachains_configuration::migration::v12::MigrateToV12, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs index 34541b83597..ca0575cb1b6 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `runtime_parachains::configuration` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -58,8 +58,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_793_000 picoseconds. - Weight::from_parts(8_192_000, 0) + // Minimum execution time: 7_789_000 picoseconds. + Weight::from_parts(8_269_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -74,8 +74,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_819_000 picoseconds. - Weight::from_parts(8_004_000, 0) + // Minimum execution time: 7_851_000 picoseconds. + Weight::from_parts(8_152_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_760_000 picoseconds. - Weight::from_parts(8_174_000, 0) + // Minimum execution time: 7_960_000 picoseconds. + Weight::from_parts(8_276_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -116,8 +116,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_814_000 picoseconds. - Weight::from_parts(8_098_000, 0) + // Minimum execution time: 7_912_000 picoseconds. + Weight::from_parts(8_164_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -132,8 +132,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 10_028_000 picoseconds. - Weight::from_parts(10_386_000, 0) + // Minimum execution time: 9_782_000 picoseconds. + Weight::from_parts(10_373_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -148,8 +148,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_867_000 picoseconds. - Weight::from_parts(8_191_000, 0) + // Minimum execution time: 7_870_000 picoseconds. + Weight::from_parts(8_274_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -164,8 +164,24 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 10_158_000 picoseconds. - Weight::from_parts(10_430_000, 0) + // Minimum execution time: 9_960_000 picoseconds. + Weight::from_parts(10_514_000, 0) + .saturating_add(Weight::from_parts(0, 1636)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Configuration::PendingConfigs` (r:1 w:1) + /// Proof: `Configuration::PendingConfigs` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Configuration::BypassConsistencyCheck` (r:1 w:0) + /// Proof: `Configuration::BypassConsistencyCheck` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn set_config_with_scheduler_params() -> Weight { + // Proof Size summary in bytes: + // Measured: `151` + // Estimated: `1636` + // Minimum execution time: 7_913_000 picoseconds. + Weight::from_parts(8_338_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 91047d953f5..a7772303a95 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1699,6 +1699,7 @@ pub mod migrations { // Migrate Identity pallet for Usernames pallet_identity::migration::versioned::V0ToV1, parachains_configuration::migration::v11::MigrateToV11, + parachains_configuration::migration::v12::MigrateToV12, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, // Migrate from legacy lease to coretime. Needs to run after configuration v11 diff --git a/polkadot/runtime/westend/src/weights/runtime_parachains_configuration.rs b/polkadot/runtime/westend/src/weights/runtime_parachains_configuration.rs index 3a4813b667c..8fa3207c644 100644 --- a/polkadot/runtime/westend/src/weights/runtime_parachains_configuration.rs +++ b/polkadot/runtime/westend/src/weights/runtime_parachains_configuration.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `runtime_parachains::configuration` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -58,8 +58,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 8_065_000 picoseconds. - Weight::from_parts(8_389_000, 0) + // Minimum execution time: 7_775_000 picoseconds. + Weight::from_parts(8_036_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -74,8 +74,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 8_038_000 picoseconds. - Weight::from_parts(8_463_000, 0) + // Minimum execution time: 7_708_000 picoseconds. + Weight::from_parts(7_971_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +90,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_843_000 picoseconds. - Weight::from_parts(8_216_000, 0) + // Minimum execution time: 7_746_000 picoseconds. + Weight::from_parts(8_028_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -116,8 +116,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_969_000 picoseconds. - Weight::from_parts(8_362_000, 0) + // Minimum execution time: 7_729_000 picoseconds. + Weight::from_parts(7_954_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -132,8 +132,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 10_084_000 picoseconds. - Weight::from_parts(10_451_000, 0) + // Minimum execution time: 9_871_000 picoseconds. + Weight::from_parts(10_075_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -148,8 +148,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_948_000 picoseconds. - Weight::from_parts(8_268_000, 0) + // Minimum execution time: 7_869_000 picoseconds. + Weight::from_parts(8_000_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -164,8 +164,24 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 10_257_000 picoseconds. - Weight::from_parts(10_584_000, 0) + // Minimum execution time: 9_797_000 picoseconds. + Weight::from_parts(10_373_000, 0) + .saturating_add(Weight::from_parts(0, 1636)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Configuration::PendingConfigs` (r:1 w:1) + /// Proof: `Configuration::PendingConfigs` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Configuration::BypassConsistencyCheck` (r:1 w:0) + /// Proof: `Configuration::BypassConsistencyCheck` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn set_config_with_scheduler_params() -> Weight { + // Proof Size summary in bytes: + // Measured: `151` + // Estimated: `1636` + // Minimum execution time: 7_718_000 picoseconds. + Weight::from_parts(7_984_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/zombienet_tests/functional/0002-parachains-disputes.toml b/polkadot/zombienet_tests/functional/0002-parachains-disputes.toml index f6bdfeb4877..2561661de1f 100644 --- a/polkadot/zombienet_tests/functional/0002-parachains-disputes.toml +++ b/polkadot/zombienet_tests/functional/0002-parachains-disputes.toml @@ -2,9 +2,11 @@ timeout = 1000 [relaychain.genesis.runtimeGenesis.patch.configuration.config] - max_validators_per_core = 5 needed_approvals = 8 +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 5 + [relaychain.genesis.runtimeGenesis.patch.configuration.config.approval_voting_params] max_approval_coalesce_count = 5 diff --git a/polkadot/zombienet_tests/functional/0004-parachains-garbage-candidate.toml b/polkadot/zombienet_tests/functional/0004-parachains-garbage-candidate.toml index 5d6f299d461..a2a2621f842 100644 --- a/polkadot/zombienet_tests/functional/0004-parachains-garbage-candidate.toml +++ b/polkadot/zombienet_tests/functional/0004-parachains-garbage-candidate.toml @@ -2,8 +2,10 @@ timeout = 1000 bootnode = true -[relaychain.genesis.runtimeGenesis.patch.configuration.config] +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] max_validators_per_core = 1 + +[relaychain.genesis.runtimeGenesis.patch.configuration.config] needed_approvals = 2 [relaychain] diff --git a/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.toml b/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.toml index e2fbec079b1..a3bbc82e74b 100644 --- a/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.toml +++ b/polkadot/zombienet_tests/functional/0005-parachains-disputes-past-session.toml @@ -3,8 +3,10 @@ timeout = 1000 bootnode = true [relaychain.genesis.runtimeGenesis.patch.configuration.config] - max_validators_per_core = 1 needed_approvals = 2 + +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 1 group_rotation_frequency = 2 [relaychain] diff --git a/polkadot/zombienet_tests/functional/0006-parachains-max-tranche0.toml b/polkadot/zombienet_tests/functional/0006-parachains-max-tranche0.toml index bef54cb8ca4..858f87b9cfe 100644 --- a/polkadot/zombienet_tests/functional/0006-parachains-max-tranche0.toml +++ b/polkadot/zombienet_tests/functional/0006-parachains-max-tranche0.toml @@ -3,10 +3,12 @@ timeout = 1000 bootnode = true [relaychain.genesis.runtimeGenesis.patch.configuration.config] - max_validators_per_core = 1 needed_approvals = 7 relay_vrf_modulo_samples = 5 +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 1 + [relaychain] default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" chain = "rococo-local" diff --git a/polkadot/zombienet_tests/functional/0007-dispute-freshly-finalized.toml b/polkadot/zombienet_tests/functional/0007-dispute-freshly-finalized.toml index 69eb0804d8c..573ccf96138 100644 --- a/polkadot/zombienet_tests/functional/0007-dispute-freshly-finalized.toml +++ b/polkadot/zombienet_tests/functional/0007-dispute-freshly-finalized.toml @@ -2,9 +2,11 @@ timeout = 1000 [relaychain.genesis.runtimeGenesis.patch.configuration.config] - max_validators_per_core = 1 needed_approvals = 1 +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 1 + [relaychain] default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" chain = "rococo-local" diff --git a/polkadot/zombienet_tests/functional/0008-dispute-old-finalized.toml b/polkadot/zombienet_tests/functional/0008-dispute-old-finalized.toml index 1ea385c3a42..ea1c93a1403 100644 --- a/polkadot/zombienet_tests/functional/0008-dispute-old-finalized.toml +++ b/polkadot/zombienet_tests/functional/0008-dispute-old-finalized.toml @@ -2,9 +2,11 @@ timeout = 1000 [relaychain.genesis.runtimeGenesis.patch.configuration.config] - max_validators_per_core = 1 needed_approvals = 1 +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 1 + [relaychain] default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" chain = "rococo-local" diff --git a/polkadot/zombienet_tests/functional/0010-validator-disabling.toml b/polkadot/zombienet_tests/functional/0010-validator-disabling.toml index 6701d60d74d..c9d79c5f8f2 100644 --- a/polkadot/zombienet_tests/functional/0010-validator-disabling.toml +++ b/polkadot/zombienet_tests/functional/0010-validator-disabling.toml @@ -3,8 +3,10 @@ timeout = 1000 bootnode = true [relaychain.genesis.runtimeGenesis.patch.configuration.config] - max_validators_per_core = 1 needed_approvals = 2 + +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 1 group_rotation_frequency = 10 [relaychain] diff --git a/polkadot/zombienet_tests/functional/0011-async-backing-6-seconds-rate.toml b/polkadot/zombienet_tests/functional/0011-async-backing-6-seconds-rate.toml index 5a6832b149b..b776622fdce 100644 --- a/polkadot/zombienet_tests/functional/0011-async-backing-6-seconds-rate.toml +++ b/polkadot/zombienet_tests/functional/0011-async-backing-6-seconds-rate.toml @@ -8,13 +8,16 @@ chain = "rococo-local" [relaychain.genesis.runtimeGenesis.patch.configuration.config] needed_approvals = 4 relay_vrf_modulo_samples = 6 - scheduling_lookahead = 2 - group_rotation_frequency = 4 [relaychain.genesis.runtimeGenesis.patch.configuration.config.async_backing_params] max_candidate_depth = 3 allowed_ancestry_len = 2 +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + lookahead = 2 + group_rotation_frequency = 4 + + [relaychain.default_resources] limits = { memory = "4G", cpu = "2" } requests = { memory = "2G", cpu = "1" } diff --git a/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.toml b/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.toml index 0dfd814e10a..9b3576eaa3c 100644 --- a/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.toml +++ b/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.toml @@ -3,9 +3,11 @@ timeout = 1000 bootnode = true [relaychain.genesis.runtimeGenesis.patch.configuration.config] - max_validators_per_core = 2 needed_approvals = 4 - coretime_cores = 2 + +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 2 + num_cores = 2 [relaychain] default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" diff --git a/polkadot/zombienet_tests/misc/0001-paritydb.toml b/polkadot/zombienet_tests/misc/0001-paritydb.toml index 399f848d3ac..b3ce2081b11 100644 --- a/polkadot/zombienet_tests/misc/0001-paritydb.toml +++ b/polkadot/zombienet_tests/misc/0001-paritydb.toml @@ -3,9 +3,11 @@ timeout = 1000 bootnode = true [relaychain.genesis.runtimeGenesis.patch.configuration.config] - max_validators_per_core = 1 needed_approvals = 3 +[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] + max_validators_per_core = 1 + [relaychain] default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" chain = "rococo-local" -- GitLab From 761937ecdc8f208361ae2a1154e0f1e6ecf57429 Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Date: Thu, 29 Feb 2024 10:21:00 +0200 Subject: [PATCH 050/188] Fix accidental no-shows on node restart (#3277) If approval was in progress we didn't actually restart it, so we end up in a situation where we distribute our assignment, but we don't distribute any approval. --------- Signed-off-by: Alexandru Gheorghe --- polkadot/node/core/approval-voting/src/lib.rs | 85 +- .../approval-voting/src/persisted_entries.rs | 7 + .../node/core/approval-voting/src/tests.rs | 744 +++++++++++++++++- 3 files changed, 780 insertions(+), 56 deletions(-) diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index 456ae319787..8cc16a6e1ec 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -1253,13 +1253,20 @@ async fn handle_actions( Action::BecomeActive => { *mode = Mode::Active; - let messages = distribution_messages_for_activation( + let (messages, next_actions) = distribution_messages_for_activation( + ctx, overlayed_db, state, delayed_approvals_timers, - )?; + session_info_provider, + ) + .await?; ctx.send_messages(messages.into_iter()).await; + let next_actions: Vec = + next_actions.into_iter().map(|v| v.clone()).chain(actions_iter).collect(); + + actions_iter = next_actions.into_iter(); }, Action::Conclude => { conclude = true; @@ -1313,15 +1320,19 @@ fn get_assignment_core_indices( } } -fn distribution_messages_for_activation( +#[overseer::contextbounds(ApprovalVoting, prefix = self::overseer)] +async fn distribution_messages_for_activation( + ctx: &mut Context, db: &OverlayedBackend<'_, impl Backend>, state: &State, delayed_approvals_timers: &mut DelayedApprovalTimer, -) -> SubsystemResult> { + session_info_provider: &mut RuntimeInfo, +) -> SubsystemResult<(Vec, Vec)> { let all_blocks: Vec = db.load_all_blocks()?; let mut approval_meta = Vec::with_capacity(all_blocks.len()); let mut messages = Vec::new(); + let mut actions = Vec::new(); messages.push(ApprovalDistributionMessage::NewBlocks(Vec::new())); // dummy value. @@ -1396,16 +1407,60 @@ fn distribution_messages_for_activation( &claimed_core_indices, &block_entry, ) { - Ok(bitfield) => messages.push( - ApprovalDistributionMessage::DistributeAssignment( - IndirectAssignmentCertV2 { - block_hash, - validator: assignment.validator_index(), - cert: assignment.cert().clone(), - }, - bitfield, - ), - ), + Ok(bitfield) => { + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?candidate_entry.candidate_receipt().hash(), + ?block_hash, + "Discovered, triggered assignment, not approved yet", + ); + + let indirect_cert = IndirectAssignmentCertV2 { + block_hash, + validator: assignment.validator_index(), + cert: assignment.cert().clone(), + }; + messages.push( + ApprovalDistributionMessage::DistributeAssignment( + indirect_cert.clone(), + bitfield.clone(), + ), + ); + + if !block_entry + .candidate_is_pending_signature(*candidate_hash) + { + let ExtendedSessionInfo { ref executor_params, .. } = + match get_extended_session_info( + session_info_provider, + ctx.sender(), + block_entry.block_hash(), + block_entry.session(), + ) + .await + { + Some(i) => i, + None => continue, + }; + + actions.push(Action::LaunchApproval { + claimed_candidate_indices: bitfield, + candidate_hash: candidate_entry + .candidate_receipt() + .hash(), + indirect_cert, + assignment_tranche: assignment.tranche(), + relay_block_hash: block_hash, + session: block_entry.session(), + executor_params: executor_params.clone(), + candidate: candidate_entry + .candidate_receipt() + .clone(), + backing_group: approval_entry.backing_group(), + distribute_assignment: false, + }); + } + }, Err(err) => { // Should never happen. If we fail here it means the // assignment is null (no cores claimed). @@ -1496,7 +1551,7 @@ fn distribution_messages_for_activation( } messages[0] = ApprovalDistributionMessage::NewBlocks(approval_meta); - Ok(messages) + Ok((messages, actions)) } // Handle an incoming signal from the overseer. Returns true if execution should conclude. diff --git a/polkadot/node/core/approval-voting/src/persisted_entries.rs b/polkadot/node/core/approval-voting/src/persisted_entries.rs index ef47bdb2213..b924a1b52cc 100644 --- a/polkadot/node/core/approval-voting/src/persisted_entries.rs +++ b/polkadot/node/core/approval-voting/src/persisted_entries.rs @@ -588,6 +588,13 @@ impl BlockEntry { !self.candidates_pending_signature.is_empty() } + /// Returns true if candidate hash is in the queue for a signature. + pub fn candidate_is_pending_signature(&self, candidate_hash: CandidateHash) -> bool { + self.candidates_pending_signature + .values() + .any(|context| context.candidate_hash == candidate_hash) + } + /// Candidate hashes for candidates pending signatures fn candidate_hashes_pending_signature(&self) -> Vec { self.candidates_pending_signature diff --git a/polkadot/node/core/approval-voting/src/tests.rs b/polkadot/node/core/approval-voting/src/tests.rs index 9220e84a255..c9053232a4c 100644 --- a/polkadot/node/core/approval-voting/src/tests.rs +++ b/polkadot/node/core/approval-voting/src/tests.rs @@ -78,6 +78,7 @@ struct TestSyncOracle { struct TestSyncOracleHandle { done_syncing_receiver: oneshot::Receiver<()>, + is_major_syncing: Arc, } impl TestSyncOracleHandle { @@ -108,8 +109,9 @@ impl SyncOracle for TestSyncOracle { fn make_sync_oracle(val: bool) -> (Box, TestSyncOracleHandle) { let (tx, rx) = oneshot::channel(); let flag = Arc::new(AtomicBool::new(val)); - let oracle = TestSyncOracle { flag, done_syncing_sender: Arc::new(Mutex::new(Some(tx))) }; - let handle = TestSyncOracleHandle { done_syncing_receiver: rx }; + let oracle = + TestSyncOracle { flag: flag.clone(), done_syncing_sender: Arc::new(Mutex::new(Some(tx))) }; + let handle = TestSyncOracleHandle { done_syncing_receiver: rx, is_major_syncing: flag }; (Box::new(oracle), handle) } @@ -465,6 +467,7 @@ struct HarnessConfigBuilder { clock: Option, backend: Option, assignment_criteria: Option>, + major_syncing: bool, } impl HarnessConfigBuilder { @@ -476,9 +479,19 @@ impl HarnessConfigBuilder { self } + pub fn major_syncing(&mut self, value: bool) -> &mut Self { + self.major_syncing = value; + self + } + + pub fn backend(&mut self, store: TestStore) -> &mut Self { + self.backend = Some(store); + self + } + pub fn build(&mut self) -> HarnessConfig { let (sync_oracle, sync_oracle_handle) = - self.sync_oracle.take().unwrap_or_else(|| make_sync_oracle(false)); + self.sync_oracle.take().unwrap_or_else(|| make_sync_oracle(self.major_syncing)); let assignment_criteria = self .assignment_criteria @@ -736,11 +749,13 @@ struct BlockConfig { slot: Slot, candidates: Option>, session_info: Option, + end_syncing: bool, } struct ChainBuilder { blocks_by_hash: HashMap, blocks_at_height: BTreeMap>, + is_major_syncing: Arc, } impl ChainBuilder { @@ -748,16 +763,28 @@ impl ChainBuilder { const GENESIS_PARENT_HASH: Hash = Hash::repeat_byte(0x00); pub fn new() -> Self { - let mut builder = - Self { blocks_by_hash: HashMap::new(), blocks_at_height: BTreeMap::new() }; + let mut builder = Self { + blocks_by_hash: HashMap::new(), + blocks_at_height: BTreeMap::new(), + is_major_syncing: Arc::new(AtomicBool::new(false)), + }; builder.add_block_inner( Self::GENESIS_HASH, Self::GENESIS_PARENT_HASH, 0, - BlockConfig { slot: Slot::from(0), candidates: None, session_info: None }, + BlockConfig { + slot: Slot::from(0), + candidates: None, + session_info: None, + end_syncing: false, + }, ); builder } + pub fn major_syncing(&mut self, major_syncing: Arc) -> &mut Self { + self.is_major_syncing = major_syncing; + self + } pub fn add_block( &mut self, @@ -808,8 +835,16 @@ impl ChainBuilder { } ancestry.reverse(); - import_block(overseer, ancestry.as_ref(), *number, block_config, false, i > 0) - .await; + import_block( + overseer, + ancestry.as_ref(), + *number, + block_config, + false, + i > 0, + self.is_major_syncing.clone(), + ) + .await; let _: Option<()> = future::pending().timeout(Duration::from_millis(100)).await; } } @@ -863,6 +898,7 @@ async fn import_block( config: &BlockConfig, gap: bool, fork: bool, + major_syncing: Arc, ) { let (new_head, new_header) = &hashes[hashes.len() - 1]; let candidates = config.candidates.clone().unwrap_or(vec![( @@ -891,6 +927,12 @@ async fn import_block( h_tx.send(Ok(Some(new_header.clone()))).unwrap(); } ); + + let is_major_syncing = major_syncing.load(Ordering::SeqCst); + if config.end_syncing { + major_syncing.store(false, Ordering::SeqCst); + } + if !fork { let mut _ancestry_step = 0; if gap { @@ -931,7 +973,7 @@ async fn import_block( } } - if number > 0 { + if number > 0 && !is_major_syncing { assert_matches!( overseer_recv(overseer).await, AllMessages::RuntimeApi( @@ -944,7 +986,6 @@ async fn import_block( c_tx.send(Ok(inclusion_events)).unwrap(); } ); - assert_matches!( overseer_recv(overseer).await, AllMessages::RuntimeApi( @@ -984,14 +1025,14 @@ async fn import_block( ); } - if number == 0 { + if number == 0 && !is_major_syncing { assert_matches!( overseer_recv(overseer).await, AllMessages::ApprovalDistribution(ApprovalDistributionMessage::NewBlocks(v)) => { assert_eq!(v.len(), 0usize); } ); - } else { + } else if number > 0 && !is_major_syncing { if !fork { // SessionInfo won't be called for forks - it's already cached assert_matches!( @@ -1031,20 +1072,23 @@ async fn import_block( ); } - assert_matches!( - overseer_recv(overseer).await, - AllMessages::ApprovalDistribution( - ApprovalDistributionMessage::NewBlocks(mut approval_vec) - ) => { - assert_eq!(approval_vec.len(), 1); - let metadata = approval_vec.pop().unwrap(); - let hash = &hashes[number as usize]; - let parent_hash = &hashes[(number - 1) as usize]; - assert_eq!(metadata.hash, hash.0.clone()); - assert_eq!(metadata.parent_hash, parent_hash.0.clone()); - assert_eq!(metadata.slot, config.slot); - } - ); + if !is_major_syncing { + assert_matches!( + overseer_recv(overseer).await, + + AllMessages::ApprovalDistribution( + ApprovalDistributionMessage::NewBlocks(mut approval_vec) + ) => { + assert_eq!(approval_vec.len(), 1); + let metadata = approval_vec.pop().unwrap(); + let hash = &hashes[number as usize]; + let parent_hash = &hashes[(number - 1) as usize]; + assert_eq!(metadata.hash, hash.0.clone()); + assert_eq!(metadata.parent_hash, parent_hash.0.clone()); + assert_eq!(metadata.slot, config.slot); + } + ); + } } } @@ -1072,7 +1116,7 @@ fn subsystem_rejects_bad_assignment_ok_criteria() { block_hash, head, 1, - BlockConfig { slot, candidates: None, session_info: None }, + BlockConfig { slot, candidates: None, session_info: None, end_syncing: false }, ); builder.build(&mut virtual_overseer).await; @@ -1135,7 +1179,7 @@ fn subsystem_rejects_bad_assignment_err_criteria() { block_hash, head, 1, - BlockConfig { slot, candidates: None, session_info: None }, + BlockConfig { slot, candidates: None, session_info: None, end_syncing: false }, ); builder.build(&mut virtual_overseer).await; @@ -1240,6 +1284,7 @@ fn subsystem_rejects_approval_if_no_candidate_entry() { slot, candidates: Some(vec![(candidate_descriptor, CoreIndex(1), GroupIndex(1))]), session_info: None, + end_syncing: false, }, ); builder.build(&mut virtual_overseer).await; @@ -1345,7 +1390,12 @@ fn subsystem_rejects_approval_before_assignment() { block_hash, ChainBuilder::GENESIS_HASH, 1, - BlockConfig { slot: Slot::from(1), candidates: None, session_info: None }, + BlockConfig { + slot: Slot::from(1), + candidates: None, + session_info: None, + end_syncing: false, + }, ) .build(&mut virtual_overseer) .await; @@ -1398,7 +1448,12 @@ fn subsystem_rejects_assignment_in_future() { block_hash, ChainBuilder::GENESIS_HASH, 1, - BlockConfig { slot: Slot::from(0), candidates: None, session_info: None }, + BlockConfig { + slot: Slot::from(0), + candidates: None, + session_info: None, + end_syncing: false, + }, ) .build(&mut virtual_overseer) .await; @@ -1472,6 +1527,7 @@ fn subsystem_accepts_duplicate_assignment() { (candidate_receipt2, CoreIndex(1), GroupIndex(1)), ]), session_info: None, + end_syncing: false, }, ) .build(&mut virtual_overseer) @@ -1537,7 +1593,12 @@ fn subsystem_rejects_assignment_with_unknown_candidate() { block_hash, ChainBuilder::GENESIS_HASH, 1, - BlockConfig { slot: Slot::from(1), candidates: None, session_info: None }, + BlockConfig { + slot: Slot::from(1), + candidates: None, + session_info: None, + end_syncing: false, + }, ) .build(&mut virtual_overseer) .await; @@ -1582,7 +1643,12 @@ fn subsystem_rejects_oversized_bitfields() { block_hash, ChainBuilder::GENESIS_HASH, 1, - BlockConfig { slot: Slot::from(1), candidates: None, session_info: None }, + BlockConfig { + slot: Slot::from(1), + candidates: None, + session_info: None, + end_syncing: false, + }, ) .build(&mut virtual_overseer) .await; @@ -1650,7 +1716,12 @@ fn subsystem_accepts_and_imports_approval_after_assignment() { block_hash, ChainBuilder::GENESIS_HASH, 1, - BlockConfig { slot: Slot::from(1), candidates: None, session_info: None }, + BlockConfig { + slot: Slot::from(1), + candidates: None, + session_info: None, + end_syncing: false, + }, ) .build(&mut virtual_overseer) .await; @@ -1741,6 +1812,7 @@ fn subsystem_second_approval_import_only_schedules_wakeups() { slot: Slot::from(0), candidates: None, session_info: Some(session_info), + end_syncing: false, }, ) .build(&mut virtual_overseer) @@ -1824,7 +1896,12 @@ fn subsystem_assignment_import_updates_candidate_entry_and_schedules_wakeup() { block_hash, ChainBuilder::GENESIS_HASH, 1, - BlockConfig { slot: Slot::from(1), candidates: None, session_info: None }, + BlockConfig { + slot: Slot::from(1), + candidates: None, + session_info: None, + end_syncing: false, + }, ) .build(&mut virtual_overseer) .await; @@ -1873,7 +1950,12 @@ fn subsystem_process_wakeup_schedules_wakeup() { block_hash, ChainBuilder::GENESIS_HASH, 1, - BlockConfig { slot: Slot::from(1), candidates: None, session_info: None }, + BlockConfig { + slot: Slot::from(1), + candidates: None, + session_info: None, + end_syncing: false, + }, ) .build(&mut virtual_overseer) .await; @@ -1925,7 +2007,7 @@ fn linear_import_act_on_leaf() { hash, head, i, - BlockConfig { slot, candidates: None, session_info: None }, + BlockConfig { slot, candidates: None, session_info: None, end_syncing: false }, ); head = hash; } @@ -1983,7 +2065,7 @@ fn forkful_import_at_same_height_act_on_leaf() { hash, head, i, - BlockConfig { slot, candidates: None, session_info: None }, + BlockConfig { slot, candidates: None, session_info: None, end_syncing: false }, ); head = hash; } @@ -1997,7 +2079,7 @@ fn forkful_import_at_same_height_act_on_leaf() { hash, head, session, - BlockConfig { slot, candidates: None, session_info: None }, + BlockConfig { slot, candidates: None, session_info: None, end_syncing: false }, ); } builder.build(&mut virtual_overseer).await; @@ -2168,6 +2250,7 @@ fn import_checked_approval_updates_entries_and_schedules() { slot, candidates: Some(vec![(candidate_descriptor, CoreIndex(0), GroupIndex(0))]), session_info: Some(session_info), + end_syncing: false, }, ); builder.build(&mut virtual_overseer).await; @@ -2323,6 +2406,7 @@ fn subsystem_import_checked_approval_sets_one_block_bit_at_a_time() { (candidate_receipt2, CoreIndex(1), GroupIndex(1)), ]), session_info: Some(session_info), + end_syncing: false, }, ) .build(&mut virtual_overseer) @@ -2445,6 +2529,7 @@ fn approved_ancestor_test( slot: Slot::from(i as u64), candidates: Some(vec![(candidate_receipt, CoreIndex(0), GroupIndex(0))]), session_info: None, + end_syncing: false, }, ); } @@ -2623,13 +2708,19 @@ fn subsystem_validate_approvals_cache() { slot, candidates: candidates.clone(), session_info: Some(session_info.clone()), + end_syncing: false, }, ) .add_block( fork_block_hash, ChainBuilder::GENESIS_HASH, 1, - BlockConfig { slot, candidates, session_info: Some(session_info) }, + BlockConfig { + slot, + candidates, + session_info: Some(session_info), + end_syncing: false, + }, ) .build(&mut virtual_overseer) .await; @@ -2740,6 +2831,7 @@ fn subsystem_doesnt_distribute_duplicate_compact_assignments() { (candidate_receipt2.clone(), CoreIndex(1), GroupIndex(1)), ]), session_info: None, + end_syncing: false, }, ) .build(&mut virtual_overseer) @@ -2997,6 +3089,7 @@ where slot, candidates: Some(vec![(candidate_receipt, CoreIndex(0), GroupIndex(2))]), session_info: Some(session_info), + end_syncing: false, }, ) .build(&mut virtual_overseer) @@ -3314,6 +3407,7 @@ fn pre_covers_dont_stall_approval() { slot, candidates: Some(vec![(candidate_descriptor, CoreIndex(0), GroupIndex(0))]), session_info: Some(session_info), + end_syncing: false, }, ); builder.build(&mut virtual_overseer).await; @@ -3491,6 +3585,7 @@ fn waits_until_approving_assignments_are_old_enough() { slot, candidates: Some(vec![(candidate_descriptor, CoreIndex(0), GroupIndex(0))]), session_info: Some(session_info), + end_syncing: false, }, ); builder.build(&mut virtual_overseer).await; @@ -3705,6 +3800,7 @@ fn test_approval_is_sent_on_max_approval_coalesce_count() { slot, candidates: candidates.clone(), session_info: Some(session_info.clone()), + end_syncing: false, }, ) .build(&mut virtual_overseer) @@ -3943,8 +4039,7 @@ fn test_approval_is_sent_on_max_approval_coalesce_wait() { let store = config.backend(); test_harness(config, |test_harness| async move { - let TestHarness { mut virtual_overseer, clock, sync_oracle_handle: _sync_oracle_handle } = - test_harness; + let TestHarness { mut virtual_overseer, clock, sync_oracle_handle: _ } = test_harness; assert_matches!( overseer_recv(&mut virtual_overseer).await, @@ -4006,6 +4101,7 @@ fn test_approval_is_sent_on_max_approval_coalesce_wait() { slot, candidates: candidates.clone(), session_info: Some(session_info.clone()), + end_syncing: false, }, ) .build(&mut virtual_overseer) @@ -4040,3 +4136,569 @@ fn test_approval_is_sent_on_max_approval_coalesce_wait() { virtual_overseer }); } + +// Builds a chain with a fork where both relay blocks include the same candidate. +async fn build_chain_with_two_blocks_with_one_candidate_each( + block_hash1: Hash, + block_hash2: Hash, + slot: Slot, + sync_oracle_handle: TestSyncOracleHandle, + candidate_receipt: CandidateReceipt, +) -> (ChainBuilder, SessionInfo) { + let validators = vec![ + Sr25519Keyring::Alice, + Sr25519Keyring::Bob, + Sr25519Keyring::Charlie, + Sr25519Keyring::Dave, + Sr25519Keyring::Eve, + ]; + let session_info = SessionInfo { + validator_groups: IndexedVec::>::from(vec![ + vec![ValidatorIndex(0), ValidatorIndex(1)], + vec![ValidatorIndex(2)], + vec![ValidatorIndex(3), ValidatorIndex(4)], + ]), + ..session_info(&validators) + }; + + let candidates = Some(vec![(candidate_receipt.clone(), CoreIndex(0), GroupIndex(0))]); + let mut chain_builder = ChainBuilder::new(); + + chain_builder + .major_syncing(sync_oracle_handle.is_major_syncing.clone()) + .add_block( + block_hash1, + ChainBuilder::GENESIS_HASH, + 1, + BlockConfig { + slot, + candidates: candidates.clone(), + session_info: Some(session_info.clone()), + end_syncing: false, + }, + ) + .add_block( + block_hash2, + ChainBuilder::GENESIS_HASH, + 1, + BlockConfig { + slot, + candidates, + session_info: Some(session_info.clone()), + end_syncing: true, + }, + ); + (chain_builder, session_info) +} + +async fn setup_overseer_with_two_blocks_each_with_one_assignment_triggered( + virtual_overseer: &mut VirtualOverseer, + store: TestStore, + clock: &Box, + sync_oracle_handle: TestSyncOracleHandle, +) { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber(rx)) => { + rx.send(Ok(0)).unwrap(); + } + ); + + let block_hash = Hash::repeat_byte(0x01); + let fork_block_hash = Hash::repeat_byte(0x02); + let candidate_commitments = CandidateCommitments::default(); + let mut candidate_receipt = dummy_candidate_receipt(block_hash); + candidate_receipt.commitments_hash = candidate_commitments.hash(); + let candidate_hash = candidate_receipt.hash(); + let slot = Slot::from(1); + let (chain_builder, _session_info) = build_chain_with_two_blocks_with_one_candidate_each( + block_hash, + fork_block_hash, + slot, + sync_oracle_handle, + candidate_receipt, + ) + .await; + chain_builder.build(virtual_overseer).await; + + assert!(!clock.inner.lock().current_wakeup_is(1)); + clock.inner.lock().wakeup_all(1); + + assert!(clock.inner.lock().current_wakeup_is(slot_to_tick(slot))); + clock.inner.lock().wakeup_all(slot_to_tick(slot)); + + futures_timer::Delay::new(Duration::from_millis(200)).await; + + clock.inner.lock().wakeup_all(slot_to_tick(slot + 2)); + + assert_eq!(clock.inner.lock().wakeups.len(), 0); + + futures_timer::Delay::new(Duration::from_millis(200)).await; + + let candidate_entry = store.load_candidate_entry(&candidate_hash).unwrap().unwrap(); + let our_assignment = + candidate_entry.approval_entry(&block_hash).unwrap().our_assignment().unwrap(); + assert!(our_assignment.triggered()); +} + +// Tests that for candidates that we did not approve yet, for which we triggered the assignment and +// the approval work we restart the work to approve it. +#[test] +fn subsystem_relaunches_approval_work_on_restart() { + let assignment_criteria = Box::new(MockAssignmentCriteria( + || { + let mut assignments = HashMap::new(); + let _ = assignments.insert( + CoreIndex(0), + approval_db::v2::OurAssignment { + cert: garbage_assignment_cert(AssignmentCertKind::RelayVRFModulo { sample: 0 }) + .into(), + tranche: 0, + validator_index: ValidatorIndex(0), + triggered: false, + } + .into(), + ); + + let _ = assignments.insert( + CoreIndex(0), + approval_db::v2::OurAssignment { + cert: garbage_assignment_cert_v2(AssignmentCertKindV2::RelayVRFModuloCompact { + core_bitfield: vec![CoreIndex(0), CoreIndex(1), CoreIndex(2)] + .try_into() + .unwrap(), + }), + tranche: 0, + validator_index: ValidatorIndex(0), + triggered: false, + } + .into(), + ); + assignments + }, + |_| Ok(0), + )); + let config = HarnessConfigBuilder::default().assignment_criteria(assignment_criteria).build(); + let store = config.backend(); + let store_clone = config.backend(); + + test_harness(config, |test_harness| async move { + let TestHarness { mut virtual_overseer, clock, sync_oracle_handle } = test_harness; + + setup_overseer_with_two_blocks_each_with_one_assignment_triggered( + &mut virtual_overseer, + store, + &clock, + sync_oracle_handle, + ) + .await; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + _, + )) => { + } + ); + + recover_available_data(&mut virtual_overseer).await; + fetch_validation_code(&mut virtual_overseer).await; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + _ + )) => { + } + ); + + // Bail early after the assignment has been distributed but before we answer with the mocked + // approval from CandidateValidation. + virtual_overseer + }); + + // Restart a new approval voting subsystem with the same database and major syncing true untill + // the last leaf. + let config = HarnessConfigBuilder::default().backend(store_clone).major_syncing(true).build(); + + test_harness(config, |test_harness| async move { + let TestHarness { mut virtual_overseer, clock, sync_oracle_handle } = test_harness; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber(rx)) => { + rx.send(Ok(0)).unwrap(); + } + ); + + let block_hash = Hash::repeat_byte(0x01); + let fork_block_hash = Hash::repeat_byte(0x02); + let candidate_commitments = CandidateCommitments::default(); + let mut candidate_receipt = dummy_candidate_receipt(block_hash); + candidate_receipt.commitments_hash = candidate_commitments.hash(); + let slot = Slot::from(1); + clock.inner.lock().set_tick(slot_to_tick(slot + 2)); + let (chain_builder, session_info) = build_chain_with_two_blocks_with_one_candidate_each( + block_hash, + fork_block_hash, + slot, + sync_oracle_handle, + candidate_receipt, + ) + .await; + + chain_builder.build(&mut virtual_overseer).await; + + futures_timer::Delay::new(Duration::from_millis(2000)).await; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + _, + RuntimeApiRequest::SessionInfo(_, si_tx), + ) + ) => { + si_tx.send(Ok(Some(session_info.clone()))).unwrap(); + } + ); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + _, + RuntimeApiRequest::SessionExecutorParams(_, si_tx), + ) + ) => { + // Make sure all SessionExecutorParams calls are not made for the leaf (but for its relay parent) + si_tx.send(Ok(Some(ExecutorParams::default()))).unwrap(); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(_, si_tx), ) + ) => { + si_tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); + } + ); + + // On major syncing ending Approval voting should send all the necessary messages for a + // candidate to be approved. + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::NewBlocks( + _, + )) => { + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + _, + )) => { + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + _, + )) => { + } + ); + + // Guarantees the approval work has been relaunched. + recover_available_data(&mut virtual_overseer).await; + fetch_validation_code(&mut virtual_overseer).await; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::CandidateValidation(CandidateValidationMessage::ValidateFromExhaustive { + exec_kind, + response_sender, + .. + }) if exec_kind == PvfExecKind::Approval => { + response_sender.send(Ok(ValidationResult::Valid(Default::default(), Default::default()))) + .unwrap(); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::ApprovalVotingParams(_, sender))) => { + let _ = sender.send(Ok(ApprovalVotingParams { + max_approval_coalesce_count: 1, + })); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeApproval(_)) + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::ApprovalVotingParams(_, sender))) => { + let _ = sender.send(Ok(ApprovalVotingParams { + max_approval_coalesce_count: 1, + })); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeApproval(_)) + ); + + // Assert that there are no more messages being sent by the subsystem + assert!(overseer_recv(&mut virtual_overseer).timeout(TIMEOUT / 2).await.is_none()); + + virtual_overseer + }); +} + +// Test that cached approvals, which are candidates that we approved but we didn't issue +// the signature yet because we want to coalesce it with more candidate are sent after restart. +#[test] +fn subsystem_sends_pending_approvals_on_approval_restart() { + let assignment_criteria = Box::new(MockAssignmentCriteria( + || { + let mut assignments = HashMap::new(); + let _ = assignments.insert( + CoreIndex(0), + approval_db::v2::OurAssignment { + cert: garbage_assignment_cert(AssignmentCertKind::RelayVRFModulo { sample: 0 }) + .into(), + tranche: 0, + validator_index: ValidatorIndex(0), + triggered: false, + } + .into(), + ); + + let _ = assignments.insert( + CoreIndex(0), + approval_db::v2::OurAssignment { + cert: garbage_assignment_cert_v2(AssignmentCertKindV2::RelayVRFModuloCompact { + core_bitfield: vec![CoreIndex(0), CoreIndex(1), CoreIndex(2)] + .try_into() + .unwrap(), + }), + tranche: 0, + validator_index: ValidatorIndex(0), + triggered: false, + } + .into(), + ); + assignments + }, + |_| Ok(0), + )); + let config = HarnessConfigBuilder::default().assignment_criteria(assignment_criteria).build(); + let store = config.backend(); + let store_clone = config.backend(); + + test_harness(config, |test_harness| async move { + let TestHarness { mut virtual_overseer, clock, sync_oracle_handle } = test_harness; + + setup_overseer_with_two_blocks_each_with_one_assignment_triggered( + &mut virtual_overseer, + store, + &clock, + sync_oracle_handle, + ) + .await; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + _, + )) => { + } + ); + + recover_available_data(&mut virtual_overseer).await; + fetch_validation_code(&mut virtual_overseer).await; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + _ + )) => { + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::CandidateValidation(CandidateValidationMessage::ValidateFromExhaustive { + exec_kind, + response_sender, + .. + }) if exec_kind == PvfExecKind::Approval => { + response_sender.send(Ok(ValidationResult::Valid(Default::default(), Default::default()))) + .unwrap(); + } + ); + + // Configure a big coalesce number, so that the signature is cached instead of being sent to + // approval-distribution. + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::ApprovalVotingParams(_, sender))) => { + let _ = sender.send(Ok(ApprovalVotingParams { + max_approval_coalesce_count: 6, + })); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::ApprovalVotingParams(_, sender))) => { + let _ = sender.send(Ok(ApprovalVotingParams { + max_approval_coalesce_count: 6, + })); + } + ); + + // Assert that there are no more messages being sent by the subsystem + assert!(overseer_recv(&mut virtual_overseer).timeout(TIMEOUT / 2).await.is_none()); + + virtual_overseer + }); + + let config = HarnessConfigBuilder::default().backend(store_clone).major_syncing(true).build(); + // On restart signatures should be sent to approval-distribution without relaunching the + // approval work. + test_harness(config, |test_harness| async move { + let TestHarness { mut virtual_overseer, clock, sync_oracle_handle } = test_harness; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber(rx)) => { + rx.send(Ok(0)).unwrap(); + } + ); + + let block_hash = Hash::repeat_byte(0x01); + let fork_block_hash = Hash::repeat_byte(0x02); + let candidate_commitments = CandidateCommitments::default(); + let mut candidate_receipt = dummy_candidate_receipt(block_hash); + candidate_receipt.commitments_hash = candidate_commitments.hash(); + let slot = Slot::from(1); + + clock.inner.lock().set_tick(slot_to_tick(slot + 2)); + let (chain_builder, session_info) = build_chain_with_two_blocks_with_one_candidate_each( + block_hash, + fork_block_hash, + slot, + sync_oracle_handle, + candidate_receipt, + ) + .await; + chain_builder.build(&mut virtual_overseer).await; + + futures_timer::Delay::new(Duration::from_millis(2000)).await; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::NewBlocks( + _, + )) => { + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + _, + )) => { + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + _, + )) => { + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::ApprovalVotingParams(_, sender))) => { + let _ = sender.send(Ok(ApprovalVotingParams { + max_approval_coalesce_count: 1, + })); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + _, + RuntimeApiRequest::SessionInfo(_, si_tx), + ) + ) => { + si_tx.send(Ok(Some(session_info.clone()))).unwrap(); + } + ); + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request( + _, + RuntimeApiRequest::SessionExecutorParams(_, si_tx), + ) + ) => { + // Make sure all SessionExecutorParams calls are not made for the leaf (but for its relay parent) + si_tx.send(Ok(Some(ExecutorParams::default()))).unwrap(); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(_, si_tx), ) + ) => { + si_tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeApproval(_)) + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::ApprovalVotingParams(_, sender))) => { + let _ = sender.send(Ok(ApprovalVotingParams { + max_approval_coalesce_count: 1, + })); + } + ); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeApproval(_)) + ); + + // Assert that there are no more messages being sent by the subsystem + assert!(overseer_recv(&mut virtual_overseer).timeout(TIMEOUT / 2).await.is_none()); + + virtual_overseer + }); +} -- GitLab From c244a94e4a77c0798c5a45d3004ec2389378b394 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 29 Feb 2024 11:41:11 +0000 Subject: [PATCH 051/188] update development setup in sdk-docs (#3506) Co-authored-by: Liam Aharon --- .../development_environment_advice.rs | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/docs/sdk/src/reference_docs/development_environment_advice.rs b/docs/sdk/src/reference_docs/development_environment_advice.rs index 43176959793..21bbe78836c 100644 --- a/docs/sdk/src/reference_docs/development_environment_advice.rs +++ b/docs/sdk/src/reference_docs/development_environment_advice.rs @@ -111,3 +111,74 @@ //! If you have a powerful remote server available, you may consider using //! [cargo-remote](https://github.com/sgeisler/cargo-remote) to execute cargo commands on it, //! freeing up local resources for other tasks like `rust-analyzer`. +//! +//! When using `cargo-remote`, you can configure your editor to perform the the typical +//! "check-on-save" remotely as well. The configuration for VSCode is as follows: +//! +//! ```json +//! { +//! "rust-analyzer.cargo.buildScripts.overrideCommand": [ +//! "cargo", +//! "remote", +//! "--build-env", +//! "SKIP_WASM_BUILD=1", +//! "--", +//! "check", +//! "--message-format=json", +//! "--all-targets", +//! "--all-features", +//! "--target-dir=target/rust-analyzer" +//! ], +//! "rust-analyzer.check.overrideCommand": [ +//! "cargo", +//! "remote", +//! "--build-env", +//! "SKIP_WASM_BUILD=1", +//! "--", +//! "check", +//! "--workspace", +//! "--message-format=json", +//! "--all-targets", +//! "--all-features", +//! "--target-dir=target/rust-analyzer" +//! ], +//! } +//! ``` +//! +//! //! and the same in Lua for `neovim/nvim-lspconfig`: +//! +//! ```lua +//! ["rust-analyzer"] = { +//! cargo = { +//! buildScripts = { +//! overrideCommand = { +//! "cargo", +//! "remote", +//! "--build-env", +//! "SKIP_WASM_BUILD=1", +//! "--", +//! "check", +//! "--message-format=json", +//! "--all-targets", +//! "--all-features", +//! "--target-dir=target/rust-analyzer" +//! }, +//! }, +//! check = { +//! overrideCommand = { +//! "cargo", +//! "remote", +//! "--build-env", +//! "SKIP_WASM_BUILD=1", +//! "--", +//! "check", +//! "--workspace", +//! "--message-format=json", +//! "--all-targets", +//! "--all-features", +//! "--target-dir=target/rust-analyzer" +//! }, +//! }, +//! }, +//! }, +//! ``` -- GitLab From 7f5d308d2983dcce324a8625edf3f2a838209da8 Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Thu, 29 Feb 2024 15:32:58 +0200 Subject: [PATCH 052/188] Enable elastic scaling node feature in local testnets genesis (#3509) Signed-off-by: Andrei Sandu --- Cargo.lock | 1 + polkadot/node/service/Cargo.toml | 5 ++- polkadot/node/service/src/chain_spec.rs | 7 +++- polkadot/runtime/parachains/src/builder.rs | 24 ++++++++---- .../functional/0012-elastic-scaling-mvp.zndsl | 11 +----- .../functional/0012-enable-node-feature.js | 37 ------------------- 6 files changed, 27 insertions(+), 58 deletions(-) delete mode 100644 polkadot/zombienet_tests/functional/0012-enable-node-feature.js diff --git a/Cargo.lock b/Cargo.lock index 3838ed0e94a..991541ee84e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13526,6 +13526,7 @@ version = "7.0.0" dependencies = [ "assert_matches", "async-trait", + "bitvec", "env_logger 0.9.3", "frame-benchmarking", "frame-benchmarking-cli", diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml index 8fd9f20b7bc..734dcbdeb44 100644 --- a/polkadot/node/service/Cargo.toml +++ b/polkadot/node/service/Cargo.toml @@ -93,6 +93,7 @@ kvdb-rocksdb = { version = "0.19.0", optional = true } parity-db = { version = "0.4.12", optional = true } codec = { package = "parity-scale-codec", version = "3.6.1" } parking_lot = "0.12.1" +bitvec = { version = "1.0.1", optional = true } # Polkadot polkadot-core-primitives = { path = "../../core-primitives" } @@ -184,8 +185,8 @@ full-node = [ ] # Configure the native runtimes to use. -westend-native = ["westend-runtime", "westend-runtime-constants"] -rococo-native = ["rococo-runtime", "rococo-runtime-constants"] +westend-native = ["bitvec", "westend-runtime", "westend-runtime-constants"] +rococo-native = ["bitvec", "rococo-runtime", "rococo-runtime-constants"] runtime-benchmarks = [ "frame-benchmarking-cli/runtime-benchmarks", diff --git a/polkadot/node/service/src/chain_spec.rs b/polkadot/node/service/src/chain_spec.rs index af05af87a46..1c44b17b6fd 100644 --- a/polkadot/node/service/src/chain_spec.rs +++ b/polkadot/node/service/src/chain_spec.rs @@ -122,7 +122,9 @@ pub fn wococo_config() -> Result { fn default_parachains_host_configuration( ) -> polkadot_runtime_parachains::configuration::HostConfiguration { - use polkadot_primitives::{AsyncBackingParams, MAX_CODE_SIZE, MAX_POV_SIZE}; + use polkadot_primitives::{ + vstaging::node_features::FeatureIndex, AsyncBackingParams, MAX_CODE_SIZE, MAX_POV_SIZE, + }; polkadot_runtime_parachains::configuration::HostConfiguration { validation_upgrade_cooldown: 2u32, @@ -155,6 +157,9 @@ fn default_parachains_host_configuration( max_candidate_depth: 3, allowed_ancestry_len: 2, }, + node_features: bitvec::vec::BitVec::from_element( + 1u8 << (FeatureIndex::ElasticScalingMVP as usize), + ), scheduler_params: SchedulerParams { lookahead: 2, group_rotation_frequency: 20, diff --git a/polkadot/runtime/parachains/src/builder.rs b/polkadot/runtime/parachains/src/builder.rs index 0e4e659fef2..5b218addb1a 100644 --- a/polkadot/runtime/parachains/src/builder.rs +++ b/polkadot/runtime/parachains/src/builder.rs @@ -25,12 +25,13 @@ use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use primitives::{ - collator_signature_payload, AvailabilityBitfield, BackedCandidate, CandidateCommitments, - CandidateDescriptor, CandidateHash, CollatorId, CollatorSignature, CommittedCandidateReceipt, - CompactStatement, CoreIndex, DisputeStatement, DisputeStatementSet, GroupIndex, HeadData, - Id as ParaId, IndexedVec, InherentData as ParachainsInherentData, InvalidDisputeStatementKind, - PersistedValidationData, SessionIndex, SigningContext, UncheckedSigned, - ValidDisputeStatementKind, ValidationCode, ValidatorId, ValidatorIndex, ValidityAttestation, + collator_signature_payload, vstaging::node_features::FeatureIndex, AvailabilityBitfield, + BackedCandidate, CandidateCommitments, CandidateDescriptor, CandidateHash, CollatorId, + CollatorSignature, CommittedCandidateReceipt, CompactStatement, CoreIndex, DisputeStatement, + DisputeStatementSet, GroupIndex, HeadData, Id as ParaId, IndexedVec, + InherentData as ParachainsInherentData, InvalidDisputeStatementKind, PersistedValidationData, + SessionIndex, SigningContext, UncheckedSigned, ValidDisputeStatementKind, ValidationCode, + ValidatorId, ValidatorIndex, ValidityAttestation, }; use sp_core::{sr25519, H256}; use sp_runtime::{ @@ -509,7 +510,7 @@ impl BenchBuilder { .iter() .map(|(seed, num_votes)| { assert!(*num_votes <= validators.len() as u32); - let (para_id, _core_idx, group_idx) = self.create_indexes(*seed); + let (para_id, core_idx, group_idx) = self.create_indexes(*seed); // This generates a pair and adds it to the keystore, returning just the public. let collator_public = CollatorId::generate_pair(None); @@ -586,11 +587,18 @@ impl BenchBuilder { }) .collect(); + // Check if the elastic scaling bit is set, if so we need to supply the core index + // in the generated candidate. + let core_idx = configuration::Pallet::::config() + .node_features + .get(FeatureIndex::ElasticScalingMVP as usize) + .map(|_the_bit| core_idx); + BackedCandidate::::new( candidate, validity_votes, bitvec::bitvec![u8, bitvec::order::Lsb0; 1; group_validators.len()], - None, + core_idx, ) }) .collect() diff --git a/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.zndsl b/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.zndsl index a7193c9282b..edc87c802a0 100644 --- a/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.zndsl +++ b/polkadot/zombienet_tests/functional/0012-elastic-scaling-mvp.zndsl @@ -1,4 +1,4 @@ -Description: Test that a paraid acquiring multiple cores does not brick itself if ElasticScalingMVP feature is enabled +Description: Test that a paraid acquiring multiple cores does not brick itself if ElasticScalingMVP feature is enabled in genesis Network: ./0012-elastic-scaling-mvp.toml Creds: config @@ -15,14 +15,5 @@ alice: js-script ./0012-register-para.js return is 0 within 600 seconds validator: reports substrate_block_height{status="finalized"} is at least 35 within 100 seconds -# Parachain will now be stalled -validator: parachain 2000 block height is lower than 20 within 300 seconds - -# Enable the ElasticScalingMVP node feature. -alice: js-script ./0012-enable-node-feature.js with "1" return is 0 within 600 seconds - -# Wait two sessions for the config to be updated. -sleep 120 seconds - # Ensure parachain is now making progress. validator: parachain 2000 block height is at least 30 within 200 seconds diff --git a/polkadot/zombienet_tests/functional/0012-enable-node-feature.js b/polkadot/zombienet_tests/functional/0012-enable-node-feature.js deleted file mode 100644 index 4822e1f6644..00000000000 --- a/polkadot/zombienet_tests/functional/0012-enable-node-feature.js +++ /dev/null @@ -1,37 +0,0 @@ -async function run(nodeName, networkInfo, index) { - const { wsUri, userDefinedTypes } = networkInfo.nodesByName[nodeName]; - const api = await zombie.connect(wsUri, userDefinedTypes); - - await zombie.util.cryptoWaitReady(); - - // account to submit tx - const keyring = new zombie.Keyring({ type: "sr25519" }); - const alice = keyring.addFromUri("//Alice"); - - await new Promise(async (resolve, reject) => { - const unsub = await api.tx.sudo - .sudo(api.tx.configuration.setNodeFeature(Number(index), true)) - .signAndSend(alice, ({ status, isError }) => { - if (status.isInBlock) { - console.log( - `Transaction included at blockhash ${status.asInBlock}`, - ); - } else if (status.isFinalized) { - console.log( - `Transaction finalized at blockHash ${status.asFinalized}`, - ); - unsub(); - return resolve(); - } else if (isError) { - console.log(`Transaction error`); - reject(`Transaction error`); - } - }); - }); - - - - return 0; -} - -module.exports = { run }; -- GitLab From c0e52a9ed61451152c4e096c58f24fb4e329bd64 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 29 Feb 2024 19:08:08 +0000 Subject: [PATCH 053/188] Fix call enum's metadata regression (#3513) This fixes an issue introduced in https://github.com/paritytech/substrate/pull/14101, in which I removed the `Call` enum's documentation and replaced it with a link to the `Pallet` struct, but this also removed any docs related to call from the metadata. I tried to add a regression test for this, but it seems to me that this is not possible, given that using `type-info` we only assert in type-ids for `Call`, `Event` and `Error`. I removed some doc comments from a test setup in `frame-support-test` to demonstrate the issue there. @jsdw do you have any comments on this? I also fixed a small issue in the custom html/css of `polkadot-sdk-doc` crate, making sure it does not affect the rust-doc page of all other crates. - [x] Investigate a regression test - [x] prdoc --- docs/sdk/headers/header.html | 111 +++++++++--------- docs/sdk/headers/theme.css | 25 ++-- prdoc/pr_3513.prdoc | 18 +++ substrate/frame/support/Cargo.toml | 21 +++- .../procedural/src/pallet/expand/call.rs | 21 +--- substrate/frame/support/test/tests/pallet.rs | 64 +++++++--- 6 files changed, 157 insertions(+), 103 deletions(-) create mode 100644 prdoc/pr_3513.prdoc diff --git a/docs/sdk/headers/header.html b/docs/sdk/headers/header.html index 68dc5d5509e..e28458c4ccc 100644 --- a/docs/sdk/headers/header.html +++ b/docs/sdk/headers/header.html @@ -54,7 +54,7 @@ sidebarElems.style.display = 'none'; // Add click event listener to the button - expandButton.addEventListener('click', function() { + expandButton.addEventListener('click', function () { // Toggle the display of the '.sidebar-elems' if (sidebarElems.style.display === 'none') { sidebarElems.style.display = 'block'; @@ -72,6 +72,9 @@ if (!crate_name.textContent.startsWith("polkadot_sdk_docs")) { console.log("skipping -- not `polkadot_sdk_docs`"); return; + } else { + // insert class 'sdk-docs' to the body, so it enables the custom css rules. + document.body.classList.add("sdk-docs"); } createToC(); @@ -82,58 +85,60 @@ diff --git a/docs/sdk/headers/theme.css b/docs/sdk/headers/theme.css index bb9254ec4a8..a488e15c36b 100644 --- a/docs/sdk/headers/theme.css +++ b/docs/sdk/headers/theme.css @@ -1,16 +1,17 @@ :root { - --polkadot-pink: #E6007A ; - --polkadot-green: #56F39A ; - --polkadot-lime: #D3FF33 ; - --polkadot-cyan: #00B2FF ; - --polkadot-purple: #552BBF ; - } - -body > nav.sidebar > div.sidebar-crate > a > img { - /* logo width, given that the sidebar width is 200px; */ - width: 190px; + --polkadot-pink: #E6007A; + --polkadot-green: #56F39A; + --polkadot-lime: #D3FF33; + --polkadot-cyan: #00B2FF; + --polkadot-purple: #552BBF; } -body nav.sidebar { - flex: 0 0 250px; +body.sdk-docs { + nav.sidebar>div.sidebar-crate>a>img { + width: 190px; + } + + nav.sidebar { + flex: 0 0 250px; + } } diff --git a/prdoc/pr_3513.prdoc b/prdoc/pr_3513.prdoc new file mode 100644 index 00000000000..e1f2afe280a --- /dev/null +++ b/prdoc/pr_3513.prdoc @@ -0,0 +1,18 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Fix call enum's metadata regression + +doc: + - audience: Runtime Dev + - audience: Runtime User + description: | + This PR fixes an issue where in the metadata of all FRAME-based chains, the documentation for + all extrinsic/call/transactions has been replaced by a single line saying "see Pallet::name". + + Many wallets display the metadata of transactions to the user before signing, and this bug + might have affected this process. + +crates: + - name: frame + - name: frame-support diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml index 72e2d0bfa56..c19f478c803 100644 --- a/substrate/frame/support/Cargo.toml +++ b/substrate/frame/support/Cargo.toml @@ -18,13 +18,24 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] array-bytes = { version = "6.1", default-features = false } serde = { features = ["alloc", "derive"], workspace = true } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -frame-metadata = { version = "16.0.0", default-features = false, features = ["current"] } -sp-api = { path = "../../primitives/api", default-features = false, features = ["frame-metadata"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", + "max-encoded-len", +] } +scale-info = { version = "2.10.0", default-features = false, features = [ + "derive", +] } +frame-metadata = { version = "16.0.0", default-features = false, features = [ + "current", +] } +sp-api = { path = "../../primitives/api", default-features = false, features = [ + "frame-metadata", +] } sp-std = { path = "../../primitives/std", default-features = false } sp-io = { path = "../../primitives/io", default-features = false } -sp-runtime = { path = "../../primitives/runtime", default-features = false, features = ["serde"] } +sp-runtime = { path = "../../primitives/runtime", default-features = false, features = [ + "serde", +] } sp-tracing = { path = "../../primitives/tracing", default-features = false } sp-core = { path = "../../primitives/core", default-features = false } sp-arithmetic = { path = "../../primitives/arithmetic", default-features = false } diff --git a/substrate/frame/support/procedural/src/pallet/expand/call.rs b/substrate/frame/support/procedural/src/pallet/expand/call.rs index f43faba1ee0..f395872c8a8 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/call.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/call.rs @@ -18,7 +18,7 @@ use crate::{ pallet::{ expand::warnings::{weight_constant_warning, weight_witness_warning}, - parse::call::{CallVariantDef, CallWeightDef}, + parse::call::CallWeightDef, Def, }, COUNTER, @@ -112,22 +112,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { } debug_assert_eq!(fn_weight.len(), methods.len()); - let map_fn_docs = if !def.dev_mode { - // Emit the [`Pallet::method`] documentation only for non-dev modes. - |method: &CallVariantDef| { - let reference = format!("See [`Pallet::{}`].", method.name); - quote!(#reference) - } - } else { - // For the dev-mode do not provide a documenation link as it will break the - // `cargo doc` if the pallet is private inside a test. - |method: &CallVariantDef| { - let reference = format!("See `Pallet::{}`.", method.name); - quote!(#reference) - } - }; - - let fn_doc = methods.iter().map(map_fn_docs).collect::>(); + let fn_doc = methods.iter().map(|method| &method.docs).collect::>(); let args_name = methods .iter() @@ -309,7 +294,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { ), #( #cfg_attrs - #[doc = #fn_doc] + #( #[doc = #fn_doc] )* #[codec(index = #call_index)] #fn_name { #( diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 7bee4b7c820..607f54ccc13 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -209,7 +209,7 @@ pub mod pallet { where T::AccountId: From + From + SomeAssociation1, { - /// Doc comment put in metadata + /// call foo doc comment put in metadata #[pallet::call_index(0)] #[pallet::weight(Weight::from_parts(*foo as u64, 0))] pub fn foo( @@ -225,7 +225,7 @@ pub mod pallet { Ok(().into()) } - /// Doc comment put in metadata + /// call foo_storage_layer doc comment put in metadata #[pallet::call_index(1)] #[pallet::weight({1})] pub fn foo_storage_layer( @@ -270,7 +270,7 @@ pub mod pallet { #[pallet::error] #[derive(PartialEq, Eq)] pub enum Error { - /// doc comment put into metadata + /// error doc comment put in metadata InsufficientProposersBalance, NonExistentStorageValue, Code(u8), @@ -287,9 +287,8 @@ pub mod pallet { where T::AccountId: SomeAssociation1 + From, { - /// doc comment put in metadata + /// event doc comment put in metadata Proposed(::AccountId), - /// doc Spending(BalanceOf), Something(u32), SomethingElse(::_1), @@ -750,8 +749,7 @@ pub type UncheckedExtrinsic = sp_runtime::testing::TestXt>; frame_support::construct_runtime!( - pub struct Runtime - { + pub struct Runtime { // Exclude part `Storage` in order not to check its metadata in tests. System: frame_system exclude_parts { Pallet, Storage }, Example: pallet, @@ -772,6 +770,14 @@ fn _ensure_call_is_correctly_excluded_and_included(call: RuntimeCall) { } } +fn maybe_docs(doc: Vec<&'static str>) -> Vec<&'static str> { + if cfg!(feature = "no-metadata-docs") { + vec![] + } else { + doc + } +} + #[test] fn transactional_works() { TestExternalities::default().execute_with(|| { @@ -1362,19 +1368,47 @@ fn migrate_from_pallet_version_to_storage_version() { }); } +#[test] +fn pallet_item_docs_in_metadata() { + // call + let call_variants = match meta_type::>().type_info().type_def { + scale_info::TypeDef::Variant(variants) => variants.variants, + _ => unreachable!(), + }; + + assert_eq!(call_variants[0].docs, maybe_docs(vec!["call foo doc comment put in metadata"])); + assert_eq!( + call_variants[1].docs, + maybe_docs(vec!["call foo_storage_layer doc comment put in metadata"]) + ); + assert!(call_variants[2].docs.is_empty()); + + // event + let event_variants = match meta_type::>().type_info().type_def { + scale_info::TypeDef::Variant(variants) => variants.variants, + _ => unreachable!(), + }; + + assert_eq!(event_variants[0].docs, maybe_docs(vec!["event doc comment put in metadata"])); + assert!(event_variants[1].docs.is_empty()); + + // error + let error_variants = match meta_type::>().type_info().type_def { + scale_info::TypeDef::Variant(variants) => variants.variants, + _ => unreachable!(), + }; + + assert_eq!(error_variants[0].docs, maybe_docs(vec!["error doc comment put in metadata"])); + assert!(error_variants[1].docs.is_empty()); + + // storage is already covered in the main `fn metadata` test. +} + #[test] fn metadata() { use codec::Decode; use frame_metadata::{v15::*, *}; - fn maybe_docs(doc: Vec<&'static str>) -> Vec<&'static str> { - if cfg!(feature = "no-metadata-docs") { - vec![] - } else { - doc - } - } - let readme = "Support code for the runtime.\n\nLicense: Apache-2.0\n"; let expected_pallet_doc = vec![" Pallet documentation", readme, readme]; -- GitLab From 650886683d42de45fbcb92645d988248dda6dbba Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Fri, 1 Mar 2024 08:31:48 +0100 Subject: [PATCH 054/188] Add `claim_assets` extrinsic to `pallet-xcm` (#3403) If an XCM execution fails or ends with leftover assets, these will be trapped. In order to claim them, a custom XCM has to be executed, with the `ClaimAsset` instruction. However, arbitrary XCM execution is not allowed everywhere yet and XCM itself is still not easy enough to use for users out there with trapped assets. This new extrinsic in `pallet-xcm` will allow these users to easily claim their assets, without concerning themselves with writing arbitrary XCMs. Part of fixing https://github.com/paritytech/polkadot-sdk/issues/3495 --------- Co-authored-by: command-bot <> Co-authored-by: Adrian Catangiu --- .../assets/asset-hub-rococo/src/lib.rs | 7 + .../src/weights/pallet_xcm.rs | 146 ++++--- .../assets/asset-hub-westend/src/lib.rs | 7 + .../src/weights/pallet_xcm.rs | 150 ++++--- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 7 + .../src/weights/pallet_xcm.rs | 142 +++--- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 7 + .../src/weights/pallet_xcm.rs | 146 ++++--- .../collectives-westend/src/lib.rs | 7 + .../src/weights/pallet_xcm.rs | 142 +++--- .../contracts/contracts-rococo/src/lib.rs | 7 + .../coretime/coretime-rococo/src/lib.rs | 7 + .../coretime-rococo/src/weights/pallet_xcm.rs | 154 ++++--- .../coretime/coretime-westend/src/lib.rs | 7 + .../src/weights/pallet_xcm.rs | 94 ++-- .../runtimes/people/people-rococo/src/lib.rs | 7 + .../people-rococo/src/weights/pallet_xcm.rs | 412 +++++++++--------- .../runtimes/people/people-westend/src/lib.rs | 7 + .../people-westend/src/weights/pallet_xcm.rs | 412 +++++++++--------- polkadot/runtime/rococo/src/lib.rs | 7 + .../runtime/rococo/src/weights/pallet_xcm.rs | 230 ++++++---- polkadot/runtime/westend/src/lib.rs | 7 + .../runtime/westend/src/weights/pallet_xcm.rs | 238 ++++++---- polkadot/xcm/pallet-xcm/src/benchmarking.rs | 21 +- polkadot/xcm/pallet-xcm/src/lib.rs | 63 +++ polkadot/xcm/pallet-xcm/src/mock.rs | 6 +- polkadot/xcm/pallet-xcm/src/tests/mod.rs | 51 +++ polkadot/xcm/src/lib.rs | 31 +- prdoc/pr_3403.prdoc | 22 + 29 files changed, 1501 insertions(+), 1043 deletions(-) create mode 100644 prdoc/pr_3403.prdoc diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 1c4f49fea0e..a64d4bc2365 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1454,6 +1454,13 @@ impl_runtime_apis! { }); Some((assets, fee_index as u32, dest, verify)) } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } impl XcmBridgeHubRouterConfig for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm.rs index f8820bbb58c..51b6543bae8 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-r43aesjn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 25_003_000 picoseconds. - Weight::from_parts(25_800_000, 0) + // Minimum execution time: 22_136_000 picoseconds. + Weight::from_parts(22_518_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +90,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 88_832_000 picoseconds. - Weight::from_parts(90_491_000, 0) + // Minimum execution time: 92_277_000 picoseconds. + Weight::from_parts(94_843_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -118,8 +118,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `400` // Estimated: `6196` - // Minimum execution time: 138_911_000 picoseconds. - Weight::from_parts(142_483_000, 0) + // Minimum execution time: 120_110_000 picoseconds. + Weight::from_parts(122_968_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) @@ -148,8 +148,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `496` // Estimated: `6208` - // Minimum execution time: 146_932_000 picoseconds. - Weight::from_parts(153_200_000, 0) + // Minimum execution time: 143_116_000 picoseconds. + Weight::from_parts(147_355_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(7)) @@ -170,8 +170,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_081_000 picoseconds. - Weight::from_parts(7_397_000, 0) + // Minimum execution time: 6_517_000 picoseconds. + Weight::from_parts(6_756_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -181,8 +181,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_007_000 picoseconds. - Weight::from_parts(2_183_000, 0) + // Minimum execution time: 1_894_000 picoseconds. + Weight::from_parts(2_024_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -208,8 +208,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 28_790_000 picoseconds. - Weight::from_parts(29_767_000, 0) + // Minimum execution time: 27_314_000 picoseconds. + Weight::from_parts(28_787_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -234,8 +234,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `363` // Estimated: `3828` - // Minimum execution time: 30_951_000 picoseconds. - Weight::from_parts(31_804_000, 0) + // Minimum execution time: 29_840_000 picoseconds. + Weight::from_parts(30_589_000, 0) .saturating_add(Weight::from_parts(0, 3828)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -246,45 +246,45 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_164_000 picoseconds. - Weight::from_parts(2_311_000, 0) + // Minimum execution time: 1_893_000 picoseconds. + Weight::from_parts(2_017_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `PolkadotXcm::SupportedVersion` (r:4 w:2) + /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `162` - // Estimated: `11052` - // Minimum execution time: 16_906_000 picoseconds. - Weight::from_parts(17_612_000, 0) - .saturating_add(Weight::from_parts(0, 11052)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `159` + // Estimated: `13524` + // Minimum execution time: 19_211_000 picoseconds. + Weight::from_parts(19_552_000, 0) + .saturating_add(Weight::from_parts(0, 13524)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifiers` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `166` - // Estimated: `11056` - // Minimum execution time: 17_443_000 picoseconds. - Weight::from_parts(18_032_000, 0) - .saturating_add(Weight::from_parts(0, 11056)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `163` + // Estimated: `13528` + // Minimum execution time: 19_177_000 picoseconds. + Weight::from_parts(19_704_000, 0) + .saturating_add(Weight::from_parts(0, 13528)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `173` - // Estimated: `13538` - // Minimum execution time: 18_992_000 picoseconds. - Weight::from_parts(19_464_000, 0) - .saturating_add(Weight::from_parts(0, 13538)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `16013` + // Minimum execution time: 20_449_000 picoseconds. + Weight::from_parts(21_075_000, 0) + .saturating_add(Weight::from_parts(0, 16013)) + .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -304,36 +304,36 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `6152` - // Minimum execution time: 28_011_000 picoseconds. - Weight::from_parts(28_716_000, 0) + // Minimum execution time: 26_578_000 picoseconds. + Weight::from_parts(27_545_000, 0) .saturating_add(Weight::from_parts(0, 6152)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:3 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_target_migration_fail() -> Weight { // Proof Size summary in bytes: // Measured: `206` - // Estimated: `8621` - // Minimum execution time: 9_533_000 picoseconds. - Weight::from_parts(9_856_000, 0) - .saturating_add(Weight::from_parts(0, 8621)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `11096` + // Minimum execution time: 11_646_000 picoseconds. + Weight::from_parts(11_944_000, 0) + .saturating_add(Weight::from_parts(0, 11096)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// 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: `173` - // Estimated: `11063` - // Minimum execution time: 17_628_000 picoseconds. - Weight::from_parts(18_146_000, 0) - .saturating_add(Weight::from_parts(0, 11063)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `170` + // Estimated: `13535` + // Minimum execution time: 19_301_000 picoseconds. + Weight::from_parts(19_664_000, 0) + .saturating_add(Weight::from_parts(0, 13535)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -349,12 +349,12 @@ 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: `215` - // Estimated: `11105` - // Minimum execution time: 34_877_000 picoseconds. - Weight::from_parts(35_607_000, 0) - .saturating_add(Weight::from_parts(0, 11105)) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `212` + // Estimated: `13577` + // Minimum execution time: 35_715_000 picoseconds. + Weight::from_parts(36_915_000, 0) + .saturating_add(Weight::from_parts(0, 13577)) + .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -365,8 +365,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `1588` - // Minimum execution time: 5_370_000 picoseconds. - Weight::from_parts(5_616_000, 0) + // Minimum execution time: 4_871_000 picoseconds. + Weight::from_parts(5_066_000, 0) .saturating_add(Weight::from_parts(0, 1588)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -377,10 +377,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7740` // Estimated: `11205` - // Minimum execution time: 26_820_000 picoseconds. - Weight::from_parts(27_143_000, 0) + // Minimum execution time: 25_150_000 picoseconds. + Weight::from_parts(26_119_000, 0) .saturating_add(Weight::from_parts(0, 11205)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// Proof: `PolkadotXcm::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn claim_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `160` + // Estimated: `3625` + // Minimum execution time: 38_248_000 picoseconds. + Weight::from_parts(39_122_000, 0) + .saturating_add(Weight::from_parts(0, 3625)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index e015c7bfca3..5778ed362ee 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1526,6 +1526,13 @@ impl_runtime_apis! { }); Some((assets, fee_index as u32, dest, verify)) } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } use pallet_xcm_bridge_hub_router::benchmarking::{ diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm.rs index 504731f4a9e..71facff87d3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-r43aesjn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 25_482_000 picoseconds. - Weight::from_parts(26_622_000, 0) + // Minimum execution time: 21_630_000 picoseconds. + Weight::from_parts(22_306_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +90,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 87_319_000 picoseconds. - Weight::from_parts(89_764_000, 0) + // Minimum execution time: 91_802_000 picoseconds. + Weight::from_parts(93_672_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -118,8 +118,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `367` // Estimated: `6196` - // Minimum execution time: 139_133_000 picoseconds. - Weight::from_parts(141_507_000, 0) + // Minimum execution time: 118_930_000 picoseconds. + Weight::from_parts(122_306_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) @@ -148,8 +148,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `496` // Estimated: `6208` - // Minimum execution time: 144_241_000 picoseconds. - Weight::from_parts(149_709_000, 0) + // Minimum execution time: 140_527_000 picoseconds. + Weight::from_parts(144_501_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(7)) @@ -158,8 +158,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 10_392_000 picoseconds. - Weight::from_parts(10_779_000, 0) + // Minimum execution time: 7_556_000 picoseconds. + Weight::from_parts(7_798_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) @@ -168,8 +168,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_088_000 picoseconds. - Weight::from_parts(7_257_000, 0) + // Minimum execution time: 6_373_000 picoseconds. + Weight::from_parts(6_603_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -179,8 +179,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_095_000 picoseconds. - Weight::from_parts(2_136_000, 0) + // Minimum execution time: 1_941_000 picoseconds. + Weight::from_parts(2_088_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -206,8 +206,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 28_728_000 picoseconds. - Weight::from_parts(29_349_000, 0) + // Minimum execution time: 27_080_000 picoseconds. + Weight::from_parts(27_820_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -232,8 +232,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `363` // Estimated: `3828` - // Minimum execution time: 30_605_000 picoseconds. - Weight::from_parts(31_477_000, 0) + // Minimum execution time: 28_850_000 picoseconds. + Weight::from_parts(29_506_000, 0) .saturating_add(Weight::from_parts(0, 3828)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -244,45 +244,45 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_137_000 picoseconds. - Weight::from_parts(2_303_000, 0) + // Minimum execution time: 2_033_000 picoseconds. + Weight::from_parts(2_201_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `PolkadotXcm::SupportedVersion` (r:4 w:2) + /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `162` - // Estimated: `11052` - // Minimum execution time: 16_719_000 picoseconds. - Weight::from_parts(17_329_000, 0) - .saturating_add(Weight::from_parts(0, 11052)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `159` + // Estimated: `13524` + // Minimum execution time: 18_844_000 picoseconds. + Weight::from_parts(19_197_000, 0) + .saturating_add(Weight::from_parts(0, 13524)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifiers` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `166` - // Estimated: `11056` - // Minimum execution time: 16_687_000 picoseconds. - Weight::from_parts(17_405_000, 0) - .saturating_add(Weight::from_parts(0, 11056)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `163` + // Estimated: `13528` + // Minimum execution time: 18_940_000 picoseconds. + Weight::from_parts(19_450_000, 0) + .saturating_add(Weight::from_parts(0, 13528)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `173` - // Estimated: `13538` - // Minimum execution time: 18_751_000 picoseconds. - Weight::from_parts(19_130_000, 0) - .saturating_add(Weight::from_parts(0, 13538)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `16013` + // Minimum execution time: 20_521_000 picoseconds. + Weight::from_parts(21_076_000, 0) + .saturating_add(Weight::from_parts(0, 16013)) + .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -302,36 +302,36 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `6152` - // Minimum execution time: 27_189_000 picoseconds. - Weight::from_parts(27_760_000, 0) + // Minimum execution time: 26_007_000 picoseconds. + Weight::from_parts(26_448_000, 0) .saturating_add(Weight::from_parts(0, 6152)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:3 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_target_migration_fail() -> Weight { // Proof Size summary in bytes: // Measured: `206` - // Estimated: `8621` - // Minimum execution time: 9_307_000 picoseconds. - Weight::from_parts(9_691_000, 0) - .saturating_add(Weight::from_parts(0, 8621)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `11096` + // Minimum execution time: 11_584_000 picoseconds. + Weight::from_parts(12_080_000, 0) + .saturating_add(Weight::from_parts(0, 11096)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// 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: `173` - // Estimated: `11063` - // Minimum execution time: 17_607_000 picoseconds. - Weight::from_parts(18_090_000, 0) - .saturating_add(Weight::from_parts(0, 11063)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `170` + // Estimated: `13535` + // Minimum execution time: 19_157_000 picoseconds. + Weight::from_parts(19_513_000, 0) + .saturating_add(Weight::from_parts(0, 13535)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -347,12 +347,12 @@ 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: `215` - // Estimated: `11105` - // Minimum execution time: 34_322_000 picoseconds. - Weight::from_parts(35_754_000, 0) - .saturating_add(Weight::from_parts(0, 11105)) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `212` + // Estimated: `13577` + // Minimum execution time: 34_878_000 picoseconds. + Weight::from_parts(35_623_000, 0) + .saturating_add(Weight::from_parts(0, 13577)) + .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -363,8 +363,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `1588` - // Minimum execution time: 4_513_000 picoseconds. - Weight::from_parts(4_754_000, 0) + // Minimum execution time: 3_900_000 picoseconds. + Weight::from_parts(4_161_000, 0) .saturating_add(Weight::from_parts(0, 1588)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -375,10 +375,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7740` // Estimated: `11205` - // Minimum execution time: 27_860_000 picoseconds. - Weight::from_parts(28_279_000, 0) + // Minimum execution time: 25_731_000 picoseconds. + Weight::from_parts(26_160_000, 0) .saturating_add(Weight::from_parts(0, 11205)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// Proof: `PolkadotXcm::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn claim_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `160` + // Estimated: `3625` + // Minimum execution time: 37_251_000 picoseconds. + Weight::from_parts(38_075_000, 0) + .saturating_add(Weight::from_parts(0, 3625)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 0f6af1b51f1..ee472f006fa 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -1148,6 +1148,13 @@ impl_runtime_apis! { dest ) } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } use xcm::latest::prelude::*; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_xcm.rs index 5faded42aa8..a732e1a5734 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_xcm.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-r43aesjn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 23_683_000 picoseconds. - Weight::from_parts(24_199_000, 0) + // Minimum execution time: 18_513_000 picoseconds. + Weight::from_parts(19_156_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +90,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `70` // Estimated: `3593` - // Minimum execution time: 89_524_000 picoseconds. - Weight::from_parts(91_401_000, 0) + // Minimum execution time: 88_096_000 picoseconds. + Weight::from_parts(89_732_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -126,8 +126,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `70` // Estimated: `3593` - // Minimum execution time: 91_890_000 picoseconds. - Weight::from_parts(93_460_000, 0) + // Minimum execution time: 88_239_000 picoseconds. + Weight::from_parts(89_729_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -148,8 +148,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_152_000 picoseconds. - Weight::from_parts(7_355_000, 0) + // Minimum execution time: 5_955_000 picoseconds. + Weight::from_parts(6_266_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -159,8 +159,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_081_000 picoseconds. - Weight::from_parts(2_258_000, 0) + // Minimum execution time: 1_868_000 picoseconds. + Weight::from_parts(1_961_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -186,8 +186,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 28_067_000 picoseconds. - Weight::from_parts(28_693_000, 0) + // Minimum execution time: 24_388_000 picoseconds. + Weight::from_parts(25_072_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -212,8 +212,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `255` // Estimated: `3720` - // Minimum execution time: 30_420_000 picoseconds. - Weight::from_parts(31_373_000, 0) + // Minimum execution time: 26_762_000 picoseconds. + Weight::from_parts(27_631_000, 0) .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -224,45 +224,45 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_087_000 picoseconds. - Weight::from_parts(2_243_000, 0) + // Minimum execution time: 1_856_000 picoseconds. + Weight::from_parts(2_033_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `PolkadotXcm::SupportedVersion` (r:4 w:2) + /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `95` - // Estimated: `10985` - // Minimum execution time: 15_142_000 picoseconds. - Weight::from_parts(15_598_000, 0) - .saturating_add(Weight::from_parts(0, 10985)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `89` + // Estimated: `13454` + // Minimum execution time: 17_718_000 picoseconds. + Weight::from_parts(18_208_000, 0) + .saturating_add(Weight::from_parts(0, 13454)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifiers` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `99` - // Estimated: `10989` - // Minimum execution time: 15_041_000 picoseconds. - Weight::from_parts(15_493_000, 0) - .saturating_add(Weight::from_parts(0, 10989)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `93` + // Estimated: `13458` + // Minimum execution time: 17_597_000 picoseconds. + Weight::from_parts(18_090_000, 0) + .saturating_add(Weight::from_parts(0, 13458)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `13471` - // Minimum execution time: 16_624_000 picoseconds. - Weight::from_parts(17_031_000, 0) - .saturating_add(Weight::from_parts(0, 13471)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `15946` + // Minimum execution time: 19_533_000 picoseconds. + Weight::from_parts(20_164_000, 0) + .saturating_add(Weight::from_parts(0, 15946)) + .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -282,36 +282,36 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `6046` - // Minimum execution time: 26_398_000 picoseconds. - Weight::from_parts(26_847_000, 0) + // Minimum execution time: 24_958_000 picoseconds. + Weight::from_parts(25_628_000, 0) .saturating_add(Weight::from_parts(0, 6046)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:3 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) /// 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: `8551` - // Minimum execution time: 8_741_000 picoseconds. - Weight::from_parts(8_954_000, 0) - .saturating_add(Weight::from_parts(0, 8551)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `11026` + // Minimum execution time: 12_209_000 picoseconds. + Weight::from_parts(12_612_000, 0) + .saturating_add(Weight::from_parts(0, 11026)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// 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: `106` - // Estimated: `10996` - // Minimum execution time: 15_306_000 picoseconds. - Weight::from_parts(15_760_000, 0) - .saturating_add(Weight::from_parts(0, 10996)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `100` + // Estimated: `13465` + // Minimum execution time: 17_844_000 picoseconds. + Weight::from_parts(18_266_000, 0) + .saturating_add(Weight::from_parts(0, 13465)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -327,12 +327,12 @@ 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: `112` - // Estimated: `11002` - // Minimum execution time: 33_127_000 picoseconds. - Weight::from_parts(33_938_000, 0) - .saturating_add(Weight::from_parts(0, 11002)) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `106` + // Estimated: `13471` + // Minimum execution time: 34_131_000 picoseconds. + Weight::from_parts(34_766_000, 0) + .saturating_add(Weight::from_parts(0, 13471)) + .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -343,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 4_290_000 picoseconds. - Weight::from_parts(4_450_000, 0) + // Minimum execution time: 3_525_000 picoseconds. + Weight::from_parts(3_724_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -355,10 +355,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 26_408_000 picoseconds. - Weight::from_parts(26_900_000, 0) + // Minimum execution time: 24_975_000 picoseconds. + Weight::from_parts(25_517_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// 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_761_000 picoseconds. + Weight::from_parts(34_674_000, 0) + .saturating_add(Weight::from_parts(0, 3555)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 206743ba6ac..60d959b4053 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -843,6 +843,13 @@ impl_runtime_apis! { dest ) } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } use xcm::latest::prelude::*; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_xcm.rs index 83e4260e771..a78ff2355ef 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_xcm.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-r43aesjn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 23_219_000 picoseconds. - Weight::from_parts(23_818_000, 0) + // Minimum execution time: 19_527_000 picoseconds. + Weight::from_parts(19_839_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -88,10 +88,10 @@ 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: `70` + // Measured: `107` // Estimated: `3593` - // Minimum execution time: 90_120_000 picoseconds. - Weight::from_parts(92_545_000, 0) + // Minimum execution time: 90_938_000 picoseconds. + Weight::from_parts(92_822_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -124,10 +124,10 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `70` + // Measured: `107` // Estimated: `3593` - // Minimum execution time: 91_339_000 picoseconds. - Weight::from_parts(93_204_000, 0) + // Minimum execution time: 90_133_000 picoseconds. + Weight::from_parts(92_308_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -148,8 +148,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_976_000 picoseconds. - Weight::from_parts(7_284_000, 0) + // Minimum execution time: 6_205_000 picoseconds. + Weight::from_parts(6_595_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -159,8 +159,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_044_000 picoseconds. - Weight::from_parts(2_223_000, 0) + // Minimum execution time: 1_927_000 picoseconds. + Weight::from_parts(2_062_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -186,8 +186,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 27_778_000 picoseconds. - Weight::from_parts(28_318_000, 0) + // Minimum execution time: 25_078_000 picoseconds. + Weight::from_parts(25_782_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -212,8 +212,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `255` // Estimated: `3720` - // Minimum execution time: 30_446_000 picoseconds. - Weight::from_parts(31_925_000, 0) + // Minimum execution time: 28_188_000 picoseconds. + Weight::from_parts(28_826_000, 0) .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -224,45 +224,45 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_037_000 picoseconds. - Weight::from_parts(2_211_000, 0) + // Minimum execution time: 1_886_000 picoseconds. + Weight::from_parts(1_991_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `PolkadotXcm::SupportedVersion` (r:4 w:2) + /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `95` - // Estimated: `10985` - // Minimum execution time: 15_620_000 picoseconds. - Weight::from_parts(15_984_000, 0) - .saturating_add(Weight::from_parts(0, 10985)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `89` + // Estimated: `13454` + // Minimum execution time: 17_443_000 picoseconds. + Weight::from_parts(17_964_000, 0) + .saturating_add(Weight::from_parts(0, 13454)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifiers` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `99` - // Estimated: `10989` - // Minimum execution time: 15_689_000 picoseconds. - Weight::from_parts(16_093_000, 0) - .saturating_add(Weight::from_parts(0, 10989)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `93` + // Estimated: `13458` + // Minimum execution time: 17_357_000 picoseconds. + Weight::from_parts(18_006_000, 0) + .saturating_add(Weight::from_parts(0, 13458)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `13471` - // Minimum execution time: 16_946_000 picoseconds. - Weight::from_parts(17_192_000, 0) - .saturating_add(Weight::from_parts(0, 13471)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `15946` + // Minimum execution time: 18_838_000 picoseconds. + Weight::from_parts(19_688_000, 0) + .saturating_add(Weight::from_parts(0, 15946)) + .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -282,36 +282,36 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `6046` - // Minimum execution time: 27_164_000 picoseconds. - Weight::from_parts(27_760_000, 0) + // Minimum execution time: 25_517_000 picoseconds. + Weight::from_parts(26_131_000, 0) .saturating_add(Weight::from_parts(0, 6046)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:3 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) /// 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: `8551` - // Minimum execution time: 8_689_000 picoseconds. - Weight::from_parts(8_874_000, 0) - .saturating_add(Weight::from_parts(0, 8551)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `11026` + // Minimum execution time: 11_587_000 picoseconds. + Weight::from_parts(11_963_000, 0) + .saturating_add(Weight::from_parts(0, 11026)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// 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: `106` - // Estimated: `10996` - // Minimum execution time: 15_944_000 picoseconds. - Weight::from_parts(16_381_000, 0) - .saturating_add(Weight::from_parts(0, 10996)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `100` + // Estimated: `13465` + // Minimum execution time: 17_490_000 picoseconds. + Weight::from_parts(18_160_000, 0) + .saturating_add(Weight::from_parts(0, 13465)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -327,12 +327,12 @@ 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: `112` - // Estimated: `11002` - // Minimum execution time: 33_826_000 picoseconds. - Weight::from_parts(34_784_000, 0) - .saturating_add(Weight::from_parts(0, 11002)) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `106` + // Estimated: `13471` + // Minimum execution time: 34_088_000 picoseconds. + Weight::from_parts(34_598_000, 0) + .saturating_add(Weight::from_parts(0, 13471)) + .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -343,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 4_257_000 picoseconds. - Weight::from_parts(4_383_000, 0) + // Minimum execution time: 3_566_000 picoseconds. + Weight::from_parts(3_754_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -355,10 +355,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 26_924_000 picoseconds. - Weight::from_parts(27_455_000, 0) + // Minimum execution time: 25_078_000 picoseconds. + Weight::from_parts(25_477_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// 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: 34_661_000 picoseconds. + Weight::from_parts(35_411_000, 0) + .saturating_add(Weight::from_parts(0, 3555)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 3ed9d6e8e16..9a88ca174df 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -1032,6 +1032,13 @@ impl_runtime_apis! { dest ) } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } let whitelist: Vec = vec![ diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs index 50dfbffde01..5d427d85004 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-r43aesjn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 24_540_000 picoseconds. - Weight::from_parts(25_439_000, 0) + // Minimum execution time: 21_813_000 picoseconds. + Weight::from_parts(22_332_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +90,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `214` // Estimated: `3679` - // Minimum execution time: 86_614_000 picoseconds. - Weight::from_parts(88_884_000, 0) + // Minimum execution time: 93_243_000 picoseconds. + Weight::from_parts(95_650_000, 0) .saturating_add(Weight::from_parts(0, 3679)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -126,8 +126,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `214` // Estimated: `3679` - // Minimum execution time: 87_915_000 picoseconds. - Weight::from_parts(90_219_000, 0) + // Minimum execution time: 96_199_000 picoseconds. + Weight::from_parts(98_620_000, 0) .saturating_add(Weight::from_parts(0, 3679)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -148,8 +148,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_872_000 picoseconds. - Weight::from_parts(7_110_000, 0) + // Minimum execution time: 6_442_000 picoseconds. + Weight::from_parts(6_682_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -159,8 +159,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_009_000 picoseconds. - Weight::from_parts(2_163_000, 0) + // Minimum execution time: 1_833_000 picoseconds. + Weight::from_parts(1_973_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -186,8 +186,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 28_858_000 picoseconds. - Weight::from_parts(29_355_000, 0) + // Minimum execution time: 27_318_000 picoseconds. + Weight::from_parts(28_224_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -212,8 +212,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `363` // Estimated: `3828` - // Minimum execution time: 30_598_000 picoseconds. - Weight::from_parts(31_168_000, 0) + // Minimum execution time: 29_070_000 picoseconds. + Weight::from_parts(30_205_000, 0) .saturating_add(Weight::from_parts(0, 3828)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -224,45 +224,45 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_090_000 picoseconds. - Weight::from_parts(2_253_000, 0) + // Minimum execution time: 1_904_000 picoseconds. + Weight::from_parts(2_033_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `PolkadotXcm::SupportedVersion` (r:4 w:2) + /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `162` - // Estimated: `11052` - // Minimum execution time: 16_133_000 picoseconds. - Weight::from_parts(16_433_000, 0) - .saturating_add(Weight::from_parts(0, 11052)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `159` + // Estimated: `13524` + // Minimum execution time: 18_348_000 picoseconds. + Weight::from_parts(18_853_000, 0) + .saturating_add(Weight::from_parts(0, 13524)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifiers` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `166` - // Estimated: `11056` - // Minimum execution time: 16_012_000 picoseconds. - Weight::from_parts(16_449_000, 0) - .saturating_add(Weight::from_parts(0, 11056)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `163` + // Estimated: `13528` + // Minimum execution time: 17_964_000 picoseconds. + Weight::from_parts(18_548_000, 0) + .saturating_add(Weight::from_parts(0, 13528)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `173` - // Estimated: `13538` - // Minimum execution time: 17_922_000 picoseconds. - Weight::from_parts(18_426_000, 0) - .saturating_add(Weight::from_parts(0, 13538)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `16013` + // Minimum execution time: 19_708_000 picoseconds. + Weight::from_parts(20_157_000, 0) + .saturating_add(Weight::from_parts(0, 16013)) + .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -282,36 +282,36 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `6152` - // Minimum execution time: 27_280_000 picoseconds. - Weight::from_parts(28_026_000, 0) + // Minimum execution time: 26_632_000 picoseconds. + Weight::from_parts(27_314_000, 0) .saturating_add(Weight::from_parts(0, 6152)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:3 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_target_migration_fail() -> Weight { // Proof Size summary in bytes: // Measured: `206` - // Estimated: `8621` - // Minimum execution time: 9_387_000 picoseconds. - Weight::from_parts(9_644_000, 0) - .saturating_add(Weight::from_parts(0, 8621)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `11096` + // Minimum execution time: 11_929_000 picoseconds. + Weight::from_parts(12_304_000, 0) + .saturating_add(Weight::from_parts(0, 11096)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// 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: `173` - // Estimated: `11063` - // Minimum execution time: 16_649_000 picoseconds. - Weight::from_parts(17_025_000, 0) - .saturating_add(Weight::from_parts(0, 11063)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `170` + // Estimated: `13535` + // Minimum execution time: 18_599_000 picoseconds. + Weight::from_parts(19_195_000, 0) + .saturating_add(Weight::from_parts(0, 13535)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -327,12 +327,12 @@ 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: `215` - // Estimated: `11105` - // Minimum execution time: 34_355_000 picoseconds. - Weight::from_parts(35_295_000, 0) - .saturating_add(Weight::from_parts(0, 11105)) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `212` + // Estimated: `13577` + // Minimum execution time: 35_524_000 picoseconds. + Weight::from_parts(36_272_000, 0) + .saturating_add(Weight::from_parts(0, 13577)) + .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -343,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `1588` - // Minimum execution time: 4_527_000 picoseconds. - Weight::from_parts(4_699_000, 0) + // Minimum execution time: 4_044_000 picoseconds. + Weight::from_parts(4_238_000, 0) .saturating_add(Weight::from_parts(0, 1588)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -355,10 +355,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7740` // Estimated: `11205` - // Minimum execution time: 27_011_000 picoseconds. - Weight::from_parts(27_398_000, 0) + // Minimum execution time: 25_741_000 picoseconds. + Weight::from_parts(26_301_000, 0) .saturating_add(Weight::from_parts(0, 11205)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// Proof: `PolkadotXcm::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn claim_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `160` + // Estimated: `3625` + // Minimum execution time: 35_925_000 picoseconds. + Weight::from_parts(36_978_000, 0) + .saturating_add(Weight::from_parts(0, 3625)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index c4df5b9a565..c73d2225ebd 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -764,6 +764,13 @@ impl_runtime_apis! { dest ) } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(EXISTENTIAL_DEPOSIT), + } + } } let whitelist: Vec = vec![ diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 0cdfebce742..d95e68d85c4 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -740,6 +740,13 @@ impl_runtime_apis! { // Reserve transfers are disabled None } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } parameter_types! { diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs index 0e34cba4aaf..c5d315467c1 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs @@ -16,26 +16,24 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=coretime-rococo-dev -// --wasm-execution=compiled -// --pallet=pallet_xcm -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm +// --chain=coretime-rococo-dev // --header=./cumulus/file_header.txt // --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/ @@ -64,8 +62,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 22_669_000 picoseconds. - Weight::from_parts(23_227_000, 0) + // Minimum execution time: 35_051_000 picoseconds. + Weight::from_parts(35_200_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -86,8 +84,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 64_486_000 picoseconds. - Weight::from_parts(65_247_000, 0) + // Minimum execution time: 56_235_000 picoseconds. + Weight::from_parts(58_178_000, 0) .saturating_add(Weight::from_parts(0, 3571)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -128,8 +126,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_020_000 picoseconds. - Weight::from_parts(7_300_000, 0) + // Minimum execution time: 6_226_000 picoseconds. + Weight::from_parts(6_403_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -139,8 +137,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_022_000 picoseconds. - Weight::from_parts(2_141_000, 0) + // Minimum execution time: 2_020_000 picoseconds. + Weight::from_parts(2_100_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -164,8 +162,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 26_893_000 picoseconds. - Weight::from_parts(27_497_000, 0) + // Minimum execution time: 24_387_000 picoseconds. + Weight::from_parts(24_814_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) @@ -188,8 +186,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `292` // Estimated: `3757` - // Minimum execution time: 29_673_000 picoseconds. - Weight::from_parts(30_693_000, 0) + // Minimum execution time: 27_039_000 picoseconds. + Weight::from_parts(27_693_000, 0) .saturating_add(Weight::from_parts(0, 3757)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -200,45 +198,45 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_990_000 picoseconds. - Weight::from_parts(2_105_000, 0) + // Minimum execution time: 1_920_000 picoseconds. + Weight::from_parts(2_082_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `PolkadotXcm::SupportedVersion` (r:4 w:2) + /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `95` - // Estimated: `10985` - // Minimum execution time: 14_819_000 picoseconds. - Weight::from_parts(15_180_000, 0) - .saturating_add(Weight::from_parts(0, 10985)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `89` + // Estimated: `13454` + // Minimum execution time: 17_141_000 picoseconds. + Weight::from_parts(17_500_000, 0) + .saturating_add(Weight::from_parts(0, 13454)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifiers` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `99` - // Estimated: `10989` - // Minimum execution time: 14_935_000 picoseconds. - Weight::from_parts(15_335_000, 0) - .saturating_add(Weight::from_parts(0, 10989)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `93` + // Estimated: `13458` + // Minimum execution time: 17_074_000 picoseconds. + Weight::from_parts(17_431_000, 0) + .saturating_add(Weight::from_parts(0, 13458)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `13471` - // Minimum execution time: 16_278_000 picoseconds. - Weight::from_parts(16_553_000, 0) - .saturating_add(Weight::from_parts(0, 13471)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `15946` + // Minimum execution time: 19_139_000 picoseconds. + Weight::from_parts(19_474_000, 0) + .saturating_add(Weight::from_parts(0, 15946)) + .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -256,36 +254,36 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `6082` - // Minimum execution time: 26_360_000 picoseconds. - Weight::from_parts(26_868_000, 0) + // Minimum execution time: 24_346_000 picoseconds. + Weight::from_parts(25_318_000, 0) .saturating_add(Weight::from_parts(0, 6082)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:3 w:0) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) /// 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: `8551` - // Minimum execution time: 8_615_000 picoseconds. - Weight::from_parts(8_903_000, 0) - .saturating_add(Weight::from_parts(0, 8551)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `11026` + // Minimum execution time: 11_777_000 picoseconds. + Weight::from_parts(12_051_000, 0) + .saturating_add(Weight::from_parts(0, 11026)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// 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: `106` - // Estimated: `10996` - // Minimum execution time: 15_284_000 picoseconds. - Weight::from_parts(15_504_000, 0) - .saturating_add(Weight::from_parts(0, 10996)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `100` + // Estimated: `13465` + // Minimum execution time: 17_538_000 picoseconds. + Weight::from_parts(17_832_000, 0) + .saturating_add(Weight::from_parts(0, 13465)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:2) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`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`) @@ -299,12 +297,12 @@ 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: `148` - // Estimated: `11038` - // Minimum execution time: 32_675_000 picoseconds. - Weight::from_parts(33_816_000, 0) - .saturating_add(Weight::from_parts(0, 11038)) - .saturating_add(T::DbWeight::get().reads(9)) + // Measured: `142` + // Estimated: `13507` + // Minimum execution time: 33_623_000 picoseconds. + Weight::from_parts(34_186_000, 0) + .saturating_add(Weight::from_parts(0, 13507)) + .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -315,8 +313,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 4_058_000 picoseconds. - Weight::from_parts(4_170_000, 0) + // Minimum execution time: 3_363_000 picoseconds. + Weight::from_parts(3_511_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -327,10 +325,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 25_375_000 picoseconds. - Weight::from_parts(26_026_000, 0) + // Minimum execution time: 23_969_000 picoseconds. + Weight::from_parts(24_347_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// 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: 34_071_000 picoseconds. + Weight::from_parts(35_031_000, 0) + .saturating_add(Weight::from_parts(0, 3555)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 7797329b526..4b9b180321d 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -731,6 +731,13 @@ impl_runtime_apis! { // Reserve transfers are disabled None } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } parameter_types! { diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs index d821a581b0d..0082db3099d 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs @@ -17,25 +17,23 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=coretime-westend-dev -// --wasm-execution=compiled -// --pallet=pallet_xcm -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm +// --chain=coretime-westend-dev // --header=./cumulus/file_header.txt // --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/ @@ -64,8 +62,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 17_946_000 picoseconds. - Weight::from_parts(18_398_000, 0) + // Minimum execution time: 18_410_000 picoseconds. + Weight::from_parts(18_657_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -86,8 +84,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 47_982_000 picoseconds. - Weight::from_parts(49_215_000, 0) + // Minimum execution time: 56_616_000 picoseconds. + Weight::from_parts(57_751_000, 0) .saturating_add(Weight::from_parts(0, 3571)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -128,8 +126,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_042_000 picoseconds. - Weight::from_parts(6_257_000, 0) + // Minimum execution time: 6_014_000 picoseconds. + Weight::from_parts(6_412_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -139,8 +137,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_845_000 picoseconds. - Weight::from_parts(1_993_000, 0) + // Minimum execution time: 1_844_000 picoseconds. + Weight::from_parts(1_957_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -164,8 +162,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 24_062_000 picoseconds. - Weight::from_parts(24_666_000, 0) + // Minimum execution time: 24_067_000 picoseconds. + Weight::from_parts(24_553_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) @@ -188,8 +186,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `292` // Estimated: `3757` - // Minimum execution time: 26_486_000 picoseconds. - Weight::from_parts(27_528_000, 0) + // Minimum execution time: 27_023_000 picoseconds. + Weight::from_parts(27_620_000, 0) .saturating_add(Weight::from_parts(0, 3757)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -200,8 +198,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_881_000 picoseconds. - Weight::from_parts(2_008_000, 0) + // Minimum execution time: 1_866_000 picoseconds. + Weight::from_parts(1_984_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -211,8 +209,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 15_971_000 picoseconds. - Weight::from_parts(16_455_000, 0) + // Minimum execution time: 16_425_000 picoseconds. + Weight::from_parts(16_680_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -223,8 +221,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 16_603_000 picoseconds. - Weight::from_parts(17_037_000, 0) + // Minimum execution time: 16_171_000 picoseconds. + Weight::from_parts(16_564_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -235,8 +233,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 17_821_000 picoseconds. - Weight::from_parts(18_200_000, 0) + // Minimum execution time: 17_785_000 picoseconds. + Weight::from_parts(18_123_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -256,8 +254,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `6082` - // Minimum execution time: 23_878_000 picoseconds. - Weight::from_parts(24_721_000, 0) + // Minimum execution time: 23_903_000 picoseconds. + Weight::from_parts(24_769_000, 0) .saturating_add(Weight::from_parts(0, 6082)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -268,8 +266,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 10_566_000 picoseconds. - Weight::from_parts(11_053_000, 0) + // Minimum execution time: 10_617_000 picoseconds. + Weight::from_parts(10_843_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -279,8 +277,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 16_020_000 picoseconds. - Weight::from_parts(16_619_000, 0) + // Minimum execution time: 16_656_000 picoseconds. + Weight::from_parts(17_106_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -301,8 +299,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `13507` - // Minimum execution time: 32_136_000 picoseconds. - Weight::from_parts(32_610_000, 0) + // Minimum execution time: 31_721_000 picoseconds. + Weight::from_parts(32_547_000, 0) .saturating_add(Weight::from_parts(0, 13507)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) @@ -315,8 +313,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_336_000 picoseconds. - Weight::from_parts(3_434_000, 0) + // Minimum execution time: 3_439_000 picoseconds. + Weight::from_parts(3_619_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -327,10 +325,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 23_977_000 picoseconds. - Weight::from_parts(24_413_000, 0) + // Minimum execution time: 24_657_000 picoseconds. + Weight::from_parts(24_971_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// 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: 34_028_000 picoseconds. + Weight::from_parts(34_697_000, 0) + .saturating_add(Weight::from_parts(0, 3555)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 616da5519a5..28b8062e0e0 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -710,6 +710,13 @@ impl_runtime_apis! { fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { None } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } use xcm::latest::prelude::*; diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_xcm.rs index 0f793524de9..fabce29b5fd 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_xcm.rs @@ -1,40 +1,41 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// 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. +// 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 . //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("people-kusama-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./artifacts/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=people-kusama-dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet=pallet_xcm -// --extrinsic=* // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-kusama/src/weights/pallet_xcm.rs +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm +// --chain=people-rococo-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,57 +48,28 @@ use core::marker::PhantomData; /// Weight functions for `pallet_xcm`. pub struct WeightInfo(PhantomData); impl pallet_xcm::WeightInfo for WeightInfo { - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), 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::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 send() -> Weight { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 25_931_000 picoseconds. - Weight::from_parts(26_340_000, 0) + // Minimum execution time: 17_830_000 picoseconds. + Weight::from_parts(18_411_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - fn teleport_assets() -> Weight { - // Proof Size summary in bytes: - // Measured: `32` - // Estimated: `1489` - // Minimum execution time: 25_691_000 picoseconds. - Weight::from_parts(25_971_000, 0) - .saturating_add(Weight::from_parts(0, 1489)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (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)) - } /// 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) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) @@ -108,18 +80,38 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// 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 teleport_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `70` + // Estimated: `3535` + // Minimum execution time: 55_456_000 picoseconds. + Weight::from_parts(56_808_000, 0) + .saturating_add(Weight::from_parts(0, 3535)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`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)) + } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `496` - // Estimated: `6208` - // Minimum execution time: 146_932_000 picoseconds. - Weight::from_parts(153_200_000, 0) - .saturating_add(Weight::from_parts(0, 6208)) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(7)) + // 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)) } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn execute() -> Weight { // Proof Size summary in bytes: // Measured: `0` @@ -128,189 +120,189 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: PolkadotXcm SupportedVersion (r:0 w:1) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_572_000 picoseconds. - Weight::from_parts(9_924_000, 0) + // Minimum execution time: 5_996_000 picoseconds. + Weight::from_parts(6_154_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: PolkadotXcm SafeXcmVersion (r:0 w:1) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:0 w:1) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn force_default_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_997_000 picoseconds. - Weight::from_parts(3_136_000, 0) + // Minimum execution time: 1_768_000 picoseconds. + Weight::from_parts(1_914_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm QueryCounter (r:1 w:1) - /// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm Queries (r:0 w:1) - /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) + /// Proof: `PolkadotXcm::QueryCounter` (`max_values`: Some(1), `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::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`) + /// Storage: `PolkadotXcm::Queries` (r:0 w:1) + /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_subscribe_version_notify() -> Weight { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 30_271_000 picoseconds. - Weight::from_parts(30_819_000, 0) + // Minimum execution time: 24_120_000 picoseconds. + Weight::from_parts(24_745_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm Queries (r:0 w:1) - /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionNotifiers` (`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::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`) + /// Storage: `PolkadotXcm::Queries` (r:0 w:1) + /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_unsubscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `220` - // Estimated: `3685` - // Minimum execution time: 32_302_000 picoseconds. - Weight::from_parts(32_807_000, 0) - .saturating_add(Weight::from_parts(0, 3685)) + // Measured: `255` + // Estimated: `3720` + // Minimum execution time: 26_630_000 picoseconds. + Weight::from_parts(27_289_000, 0) + .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: PolkadotXcm XcmExecutionSuspended (r:0 w:1) - /// Proof Skipped: PolkadotXcm XcmExecutionSuspended (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::XcmExecutionSuspended` (r:0 w:1) + /// Proof: `PolkadotXcm::XcmExecutionSuspended` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn force_suspension() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_960_000 picoseconds. - Weight::from_parts(3_094_000, 0) + // Minimum execution time: 1_821_000 picoseconds. + Weight::from_parts(1_946_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: PolkadotXcm SupportedVersion (r:4 w:2) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `95` - // Estimated: `10985` - // Minimum execution time: 14_877_000 picoseconds. - Weight::from_parts(15_296_000, 0) - .saturating_add(Weight::from_parts(0, 10985)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `89` + // Estimated: `13454` + // Minimum execution time: 16_586_000 picoseconds. + Weight::from_parts(16_977_000, 0) + .saturating_add(Weight::from_parts(0, 13454)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: PolkadotXcm VersionNotifiers (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) + /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `99` - // Estimated: `10989` - // Minimum execution time: 14_835_000 picoseconds. - Weight::from_parts(15_115_000, 0) - .saturating_add(Weight::from_parts(0, 10989)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `93` + // Estimated: `13458` + // Minimum execution time: 16_923_000 picoseconds. + Weight::from_parts(17_415_000, 0) + .saturating_add(Weight::from_parts(0, 13458)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:5 w:0) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) + /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `13471` - // Minimum execution time: 15_368_000 picoseconds. - Weight::from_parts(15_596_000, 0) - .saturating_add(Weight::from_parts(0, 13471)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `15946` + // Minimum execution time: 18_596_000 picoseconds. + Weight::from_parts(18_823_000, 0) + .saturating_add(Weight::from_parts(0, 15946)) + .saturating_add(T::DbWeight::get().reads(6)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:2 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) + /// Proof: `PolkadotXcm::VersionNotifyTargets` (`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::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 notify_current_targets() -> Weight { // Proof Size summary in bytes: // Measured: `106` // Estimated: `6046` - // Minimum execution time: 28_025_000 picoseconds. - Weight::from_parts(28_524_000, 0) + // Minimum execution time: 23_817_000 picoseconds. + Weight::from_parts(24_520_000, 0) .saturating_add(Weight::from_parts(0, 6046)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:3 w:0) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) + /// 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: `8551` - // Minimum execution time: 8_166_000 picoseconds. - Weight::from_parts(8_314_000, 0) - .saturating_add(Weight::from_parts(0, 8551)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `11026` + // Minimum execution time: 11_042_000 picoseconds. + Weight::from_parts(11_578_000, 0) + .saturating_add(Weight::from_parts(0, 11026)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// 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: `106` - // Estimated: `10996` - // Minimum execution time: 14_871_000 picoseconds. - Weight::from_parts(15_374_000, 0) - .saturating_add(Weight::from_parts(0, 10996)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `100` + // Estimated: `13465` + // Minimum execution time: 17_306_000 picoseconds. + Weight::from_parts(17_817_000, 0) + .saturating_add(Weight::from_parts(0, 13465)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) + /// Proof: `PolkadotXcm::VersionNotifyTargets` (`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::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 migrate_and_notify_old_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `112` - // Estimated: `11002` - // Minimum execution time: 33_611_000 picoseconds. - Weight::from_parts(34_008_000, 0) - .saturating_add(Weight::from_parts(0, 11002)) - .saturating_add(T::DbWeight::get().reads(9)) + // Measured: `106` + // Estimated: `13471` + // Minimum execution time: 32_141_000 picoseconds. + Weight::from_parts(32_954_000, 0) + .saturating_add(Weight::from_parts(0, 13471)) + .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -319,11 +311,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: `103` - // Estimated: `1588` - // Minimum execution time: 5_496_000 picoseconds. - Weight::from_parts(5_652_000, 0) - .saturating_add(Weight::from_parts(0, 1588)) + // Measured: `32` + // Estimated: `1517` + // Minimum execution time: 3_410_000 picoseconds. + Weight::from_parts(3_556_000, 0) + .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -331,11 +323,23 @@ 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: `7740` - // Estimated: `11205` - // Minimum execution time: 26_140_000 picoseconds. - Weight::from_parts(26_824_000, 0) - .saturating_add(Weight::from_parts(0, 11205)) + // Measured: `7669` + // Estimated: `11134` + // Minimum execution time: 25_021_000 picoseconds. + Weight::from_parts(25_240_000, 0) + .saturating_add(Weight::from_parts(0, 11134)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// 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_801_000 picoseconds. + Weight::from_parts(34_655_000, 0) + .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 9f572330cac..b2b32445613 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -710,6 +710,13 @@ impl_runtime_apis! { fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> { None } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::parent()), + fun: Fungible(ExistentialDeposit::get()), + } + } } use xcm::latest::prelude::*; diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_xcm.rs index d3b60471b85..c337289243b 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_xcm.rs @@ -1,40 +1,41 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// 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. +// 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 . //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("people-polkadot-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./artifacts/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=people-polkadot-dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet=pallet_xcm -// --extrinsic=* // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-polkadot/src/weights/pallet_xcm.rs +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm +// --chain=people-westend-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,57 +48,28 @@ use core::marker::PhantomData; /// Weight functions for `pallet_xcm`. pub struct WeightInfo(PhantomData); impl pallet_xcm::WeightInfo for WeightInfo { - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), 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::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 send() -> Weight { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 25_783_000 picoseconds. - Weight::from_parts(26_398_000, 0) + // Minimum execution time: 17_856_000 picoseconds. + Weight::from_parts(18_473_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - fn teleport_assets() -> Weight { - // Proof Size summary in bytes: - // Measured: `32` - // Estimated: `1489` - // Minimum execution time: 25_511_000 picoseconds. - Weight::from_parts(26_120_000, 0) - .saturating_add(Weight::from_parts(0, 1489)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (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)) - } /// 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) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) @@ -108,18 +80,38 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// 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 teleport_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `70` + // Estimated: `3535` + // Minimum execution time: 56_112_000 picoseconds. + Weight::from_parts(57_287_000, 0) + .saturating_add(Weight::from_parts(0, 3535)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`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)) + } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `496` - // Estimated: `6208` - // Minimum execution time: 146_932_000 picoseconds. - Weight::from_parts(153_200_000, 0) - .saturating_add(Weight::from_parts(0, 6208)) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(7)) + // 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)) } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn execute() -> Weight { // Proof Size summary in bytes: // Measured: `0` @@ -128,189 +120,189 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: PolkadotXcm SupportedVersion (r:0 w:1) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_707_000 picoseconds. - Weight::from_parts(9_874_000, 0) + // Minimum execution time: 6_186_000 picoseconds. + Weight::from_parts(6_420_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: PolkadotXcm SafeXcmVersion (r:0 w:1) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:0 w:1) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn force_default_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_073_000 picoseconds. - Weight::from_parts(3_183_000, 0) + // Minimum execution time: 1_824_000 picoseconds. + Weight::from_parts(1_999_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm QueryCounter (r:1 w:1) - /// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm Queries (r:0 w:1) - /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) + /// Proof: `PolkadotXcm::QueryCounter` (`max_values`: Some(1), `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::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`) + /// Storage: `PolkadotXcm::Queries` (r:0 w:1) + /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_subscribe_version_notify() -> Weight { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 30_999_000 picoseconds. - Weight::from_parts(31_641_000, 0) + // Minimum execution time: 23_833_000 picoseconds. + Weight::from_parts(24_636_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm Queries (r:0 w:1) - /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionNotifiers` (`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::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`) + /// Storage: `PolkadotXcm::Queries` (r:0 w:1) + /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_unsubscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `220` - // Estimated: `3685` - // Minimum execution time: 33_036_000 picoseconds. - Weight::from_parts(33_596_000, 0) - .saturating_add(Weight::from_parts(0, 3685)) + // Measured: `255` + // Estimated: `3720` + // Minimum execution time: 26_557_000 picoseconds. + Weight::from_parts(27_275_000, 0) + .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: PolkadotXcm XcmExecutionSuspended (r:0 w:1) - /// Proof Skipped: PolkadotXcm XcmExecutionSuspended (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::XcmExecutionSuspended` (r:0 w:1) + /// Proof: `PolkadotXcm::XcmExecutionSuspended` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn force_suspension() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_035_000 picoseconds. - Weight::from_parts(3_154_000, 0) + // Minimum execution time: 1_921_000 picoseconds. + Weight::from_parts(2_040_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: PolkadotXcm SupportedVersion (r:4 w:2) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::SupportedVersion` (r:5 w:2) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `95` - // Estimated: `10985` - // Minimum execution time: 14_805_000 picoseconds. - Weight::from_parts(15_120_000, 0) - .saturating_add(Weight::from_parts(0, 10985)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `89` + // Estimated: `13454` + // Minimum execution time: 16_832_000 picoseconds. + Weight::from_parts(17_312_000, 0) + .saturating_add(Weight::from_parts(0, 13454)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: PolkadotXcm VersionNotifiers (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifiers` (r:5 w:2) + /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `99` - // Estimated: `10989` - // Minimum execution time: 14_572_000 picoseconds. - Weight::from_parts(14_909_000, 0) - .saturating_add(Weight::from_parts(0, 10989)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `93` + // Estimated: `13458` + // Minimum execution time: 16_687_000 picoseconds. + Weight::from_parts(17_123_000, 0) + .saturating_add(Weight::from_parts(0, 13458)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:5 w:0) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:0) + /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `13471` - // Minimum execution time: 15_341_000 picoseconds. - Weight::from_parts(15_708_000, 0) - .saturating_add(Weight::from_parts(0, 13471)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `15946` + // Minimum execution time: 18_164_000 picoseconds. + Weight::from_parts(18_580_000, 0) + .saturating_add(Weight::from_parts(0, 15946)) + .saturating_add(T::DbWeight::get().reads(6)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:2 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) + /// Proof: `PolkadotXcm::VersionNotifyTargets` (`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::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 notify_current_targets() -> Weight { // Proof Size summary in bytes: // Measured: `106` // Estimated: `6046` - // Minimum execution time: 27_840_000 picoseconds. - Weight::from_parts(28_248_000, 0) + // Minimum execution time: 23_577_000 picoseconds. + Weight::from_parts(24_324_000, 0) .saturating_add(Weight::from_parts(0, 6046)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:3 w:0) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:4 w:0) + /// 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: `8551` - // Minimum execution time: 8_245_000 picoseconds. - Weight::from_parts(8_523_000, 0) - .saturating_add(Weight::from_parts(0, 8551)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `11026` + // Minimum execution time: 11_014_000 picoseconds. + Weight::from_parts(11_223_000, 0) + .saturating_add(Weight::from_parts(0, 11026)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// 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: `106` - // Estimated: `10996` - // Minimum execution time: 14_780_000 picoseconds. - Weight::from_parts(15_173_000, 0) - .saturating_add(Weight::from_parts(0, 10996)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `100` + // Estimated: `13465` + // Minimum execution time: 16_887_000 picoseconds. + Weight::from_parts(17_361_000, 0) + .saturating_add(Weight::from_parts(0, 13465)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) + /// Proof: `PolkadotXcm::VersionNotifyTargets` (`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::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 migrate_and_notify_old_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `112` - // Estimated: `11002` - // Minimum execution time: 33_422_000 picoseconds. - Weight::from_parts(34_076_000, 0) - .saturating_add(Weight::from_parts(0, 11002)) - .saturating_add(T::DbWeight::get().reads(9)) + // Measured: `106` + // Estimated: `13471` + // Minimum execution time: 31_705_000 picoseconds. + Weight::from_parts(32_166_000, 0) + .saturating_add(Weight::from_parts(0, 13471)) + .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) @@ -319,11 +311,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: `103` - // Estimated: `1588` - // Minimum execution time: 5_496_000 picoseconds. - Weight::from_parts(5_652_000, 0) - .saturating_add(Weight::from_parts(0, 1588)) + // Measured: `32` + // Estimated: `1517` + // Minimum execution time: 3_568_000 picoseconds. + Weight::from_parts(3_669_000, 0) + .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -331,11 +323,23 @@ 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: `7740` - // Estimated: `11205` - // Minimum execution time: 26_140_000 picoseconds. - Weight::from_parts(26_824_000, 0) - .saturating_add(Weight::from_parts(0, 11205)) + // Measured: `7669` + // Estimated: `11134` + // Minimum execution time: 24_823_000 picoseconds. + Weight::from_parts(25_344_000, 0) + .saturating_add(Weight::from_parts(0, 11134)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) + /// 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: 34_516_000 picoseconds. + Weight::from_parts(35_478_000, 0) + .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index f3c0c3d6bd8..48395f45238 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -2336,6 +2336,13 @@ sp_api::impl_runtime_apis! { dest ) } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::here()), + fun: Fungible(ExistentialDeposit::get()), + } + } } impl pallet_xcm_benchmarks::Config for Runtime { type XcmConfig = XcmConfig; diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs index 177407ef708..5544ca44658 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -48,10 +48,6 @@ use core::marker::PhantomData; /// Weight functions for `pallet_xcm`. pub struct WeightInfo(PhantomData); impl pallet_xcm::WeightInfo for WeightInfo { - fn transfer_assets() -> Weight { - // TODO: run benchmarks - Weight::zero() - } /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) @@ -62,36 +58,80 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn send() -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `3607` - // Minimum execution time: 27_328_000 picoseconds. - Weight::from_parts(27_976_000, 0) - .saturating_add(Weight::from_parts(0, 3607)) + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 25_043_000 picoseconds. + Weight::from_parts(25_682_000, 0) + .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn teleport_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 16_280_000 picoseconds. - Weight::from_parts(16_904_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 107_570_000 picoseconds. + Weight::from_parts(109_878_000, 0) + .saturating_add(Weight::from_parts(0, 3645)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`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: 15_869_000 picoseconds. - Weight::from_parts(16_264_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `232` + // Estimated: `3697` + // Minimum execution time: 106_341_000 picoseconds. + Weight::from_parts(109_135_000, 0) + .saturating_add(Weight::from_parts(0, 3697)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn transfer_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 108_372_000 picoseconds. + Weight::from_parts(112_890_000, 0) + .saturating_add(Weight::from_parts(0, 3645)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } fn execute() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_923_000 picoseconds. - Weight::from_parts(7_432_000, 0) + // Minimum execution time: 6_957_000 picoseconds. + Weight::from_parts(7_417_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::SupportedVersion` (r:0 w:1) @@ -100,8 +140,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_333_000 picoseconds. - Weight::from_parts(7_566_000, 0) + // Minimum execution time: 7_053_000 picoseconds. + Weight::from_parts(7_462_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -109,8 +149,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_219_000 picoseconds. - Weight::from_parts(2_375_000, 0) + // Minimum execution time: 1_918_000 picoseconds. + Weight::from_parts(2_037_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::VersionNotifiers` (r:1 w:1) @@ -129,11 +169,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_subscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `3607` - // Minimum execution time: 30_650_000 picoseconds. - Weight::from_parts(31_683_000, 0) - .saturating_add(Weight::from_parts(0, 3607)) + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 30_417_000 picoseconds. + Weight::from_parts(31_191_000, 0) + .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -151,11 +191,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_unsubscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `322` - // Estimated: `3787` - // Minimum execution time: 37_666_000 picoseconds. - Weight::from_parts(38_920_000, 0) - .saturating_add(Weight::from_parts(0, 3787)) + // Measured: `360` + // Estimated: `3825` + // Minimum execution time: 36_666_000 picoseconds. + Weight::from_parts(37_779_000, 0) + .saturating_add(Weight::from_parts(0, 3825)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -165,45 +205,45 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_244_000 picoseconds. - Weight::from_parts(2_425_000, 0) + // Minimum execution time: 1_869_000 picoseconds. + Weight::from_parts(2_003_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `XcmPallet::SupportedVersion` (r:4 w:2) + /// Storage: `XcmPallet::SupportedVersion` (r:5 w:2) /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `26` - // Estimated: `10916` - // Minimum execution time: 14_710_000 picoseconds. - Weight::from_parts(15_156_000, 0) - .saturating_add(Weight::from_parts(0, 10916)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `22` + // Estimated: `13387` + // Minimum execution time: 16_188_000 picoseconds. + Weight::from_parts(16_435_000, 0) + .saturating_add(Weight::from_parts(0, 13387)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `XcmPallet::VersionNotifiers` (r:4 w:2) + /// Storage: `XcmPallet::VersionNotifiers` (r:5 w:2) /// Proof: `XcmPallet::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `30` - // Estimated: `10920` - // Minimum execution time: 14_630_000 picoseconds. - Weight::from_parts(15_290_000, 0) - .saturating_add(Weight::from_parts(0, 10920)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `26` + // Estimated: `13391` + // Minimum execution time: 16_431_000 picoseconds. + Weight::from_parts(16_935_000, 0) + .saturating_add(Weight::from_parts(0, 13391)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:5 w:0) + /// Storage: `XcmPallet::VersionNotifyTargets` (r:6 w:0) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `40` - // Estimated: `13405` - // Minimum execution time: 16_686_000 picoseconds. - Weight::from_parts(17_332_000, 0) - .saturating_add(Weight::from_parts(0, 13405)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `15880` + // Minimum execution time: 18_460_000 picoseconds. + Weight::from_parts(18_885_000, 0) + .saturating_add(Weight::from_parts(0, 15880)) + .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `XcmPallet::VersionNotifyTargets` (r:2 w:1) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -217,38 +257,38 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_current_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `178` - // Estimated: `6118` - // Minimum execution time: 30_180_000 picoseconds. - Weight::from_parts(31_351_000, 0) - .saturating_add(Weight::from_parts(0, 6118)) + // Measured: `216` + // Estimated: `6156` + // Minimum execution time: 29_623_000 picoseconds. + Weight::from_parts(30_661_000, 0) + .saturating_add(Weight::from_parts(0, 6156)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:3 w:0) + /// Storage: `XcmPallet::VersionNotifyTargets` (r:4 w:0) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_target_migration_fail() -> Weight { // Proof Size summary in bytes: // Measured: `69` - // Estimated: `8484` - // Minimum execution time: 9_624_000 picoseconds. - Weight::from_parts(10_029_000, 0) - .saturating_add(Weight::from_parts(0, 8484)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `10959` + // Minimum execution time: 12_043_000 picoseconds. + Weight::from_parts(12_360_000, 0) + .saturating_add(Weight::from_parts(0, 10959)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:4 w:2) + /// Storage: `XcmPallet::VersionNotifyTargets` (r:5 w:2) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notify_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `37` - // Estimated: `10927` - // Minimum execution time: 15_139_000 picoseconds. - Weight::from_parts(15_575_000, 0) - .saturating_add(Weight::from_parts(0, 10927)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `33` + // Estimated: `13398` + // Minimum execution time: 16_511_000 picoseconds. + Weight::from_parts(17_011_000, 0) + .saturating_add(Weight::from_parts(0, 13398)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:4 w:2) + /// Storage: `XcmPallet::VersionNotifyTargets` (r:5 w:2) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -260,12 +300,12 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_and_notify_old_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `182` - // Estimated: `11072` - // Minimum execution time: 37_871_000 picoseconds. - Weight::from_parts(38_940_000, 0) - .saturating_add(Weight::from_parts(0, 11072)) - .saturating_add(T::DbWeight::get().reads(8)) + // Measured: `216` + // Estimated: `13581` + // Minimum execution time: 39_041_000 picoseconds. + Weight::from_parts(39_883_000, 0) + .saturating_add(Weight::from_parts(0, 13581)) + .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `XcmPallet::QueryCounter` (r:1 w:1) @@ -276,8 +316,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 2_732_000 picoseconds. - Weight::from_parts(2_892_000, 0) + // Minimum execution time: 2_030_000 picoseconds. + Weight::from_parts(2_150_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -288,10 +328,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7576` // Estimated: `11041` - // Minimum execution time: 23_813_000 picoseconds. - Weight::from_parts(24_201_000, 0) + // Minimum execution time: 22_615_000 picoseconds. + Weight::from_parts(23_008_000, 0) .saturating_add(Weight::from_parts(0, 11041)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `XcmPallet::AssetTraps` (r:1 w:1) + /// Proof: `XcmPallet::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn claim_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `23` + // Estimated: `3488` + // Minimum execution time: 34_438_000 picoseconds. + Weight::from_parts(35_514_000, 0) + .saturating_add(Weight::from_parts(0, 3488)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index a7772303a95..4ac2202b8fc 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -2412,6 +2412,13 @@ sp_api::impl_runtime_apis! { dest ) } + + fn get_asset() -> Asset { + Asset { + id: AssetId(Location::here()), + fun: Fungible(ExistentialDeposit::get()), + } + } } impl frame_system_benchmarking::Config for Runtime {} impl pallet_nomination_pools_benchmarking::Config for Runtime {} diff --git a/polkadot/runtime/westend/src/weights/pallet_xcm.rs b/polkadot/runtime/westend/src/weights/pallet_xcm.rs index 493acd0f9e7..10725cecf24 100644 --- a/polkadot/runtime/westend/src/weights/pallet_xcm.rs +++ b/polkadot/runtime/westend/src/weights/pallet_xcm.rs @@ -16,26 +16,24 @@ //! Autogenerated weights for `pallet_xcm` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=westend-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_xcm // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm +// --chain=westend-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/westend/src/weights/ @@ -50,10 +48,6 @@ use core::marker::PhantomData; /// Weight functions for `pallet_xcm`. pub struct WeightInfo(PhantomData); impl pallet_xcm::WeightInfo for WeightInfo { - fn transfer_assets() -> Weight { - // TODO: run benchmarks - Weight::zero() - } /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) @@ -64,29 +58,73 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn send() -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `3574` - // Minimum execution time: 28_098_000 picoseconds. - Weight::from_parts(28_887_000, 0) - .saturating_add(Weight::from_parts(0, 3574)) + // Measured: `147` + // Estimated: `3612` + // Minimum execution time: 25_725_000 picoseconds. + Weight::from_parts(26_174_000, 0) + .saturating_add(Weight::from_parts(0, 3612)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn teleport_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 17_609_000 picoseconds. - Weight::from_parts(18_000_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `250` + // Estimated: `6196` + // Minimum execution time: 113_140_000 picoseconds. + Weight::from_parts(116_204_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) } + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`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: 17_007_000 picoseconds. - Weight::from_parts(17_471_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `302` + // Estimated: `6196` + // Minimum execution time: 108_571_000 picoseconds. + Weight::from_parts(110_650_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn transfer_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `250` + // Estimated: `6196` + // Minimum execution time: 111_836_000 picoseconds. + Weight::from_parts(114_435_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Benchmark::Override` (r:0 w:0) /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -104,8 +142,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_444_000 picoseconds. - Weight::from_parts(7_671_000, 0) + // Minimum execution time: 7_160_000 picoseconds. + Weight::from_parts(7_477_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -113,8 +151,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_126_000 picoseconds. - Weight::from_parts(2_253_000, 0) + // Minimum execution time: 1_934_000 picoseconds. + Weight::from_parts(2_053_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::VersionNotifiers` (r:1 w:1) @@ -133,11 +171,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_subscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `3574` - // Minimum execution time: 31_318_000 picoseconds. - Weight::from_parts(32_413_000, 0) - .saturating_add(Weight::from_parts(0, 3574)) + // Measured: `147` + // Estimated: `3612` + // Minimum execution time: 31_123_000 picoseconds. + Weight::from_parts(31_798_000, 0) + .saturating_add(Weight::from_parts(0, 3612)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } @@ -155,11 +193,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_unsubscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `289` - // Estimated: `3754` - // Minimum execution time: 35_282_000 picoseconds. - Weight::from_parts(35_969_000, 0) - .saturating_add(Weight::from_parts(0, 3754)) + // Measured: `327` + // Estimated: `3792` + // Minimum execution time: 35_175_000 picoseconds. + Weight::from_parts(36_098_000, 0) + .saturating_add(Weight::from_parts(0, 3792)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -169,45 +207,45 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_247_000 picoseconds. - Weight::from_parts(2_381_000, 0) + // Minimum execution time: 1_974_000 picoseconds. + Weight::from_parts(2_096_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `XcmPallet::SupportedVersion` (r:4 w:2) + /// Storage: `XcmPallet::SupportedVersion` (r:5 w:2) /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `26` - // Estimated: `10916` - // Minimum execution time: 14_512_000 picoseconds. - Weight::from_parts(15_042_000, 0) - .saturating_add(Weight::from_parts(0, 10916)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `22` + // Estimated: `13387` + // Minimum execution time: 16_626_000 picoseconds. + Weight::from_parts(17_170_000, 0) + .saturating_add(Weight::from_parts(0, 13387)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `XcmPallet::VersionNotifiers` (r:4 w:2) + /// Storage: `XcmPallet::VersionNotifiers` (r:5 w:2) /// Proof: `XcmPallet::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `30` - // Estimated: `10920` - // Minimum execution time: 14_659_000 picoseconds. - Weight::from_parts(15_164_000, 0) - .saturating_add(Weight::from_parts(0, 10920)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `26` + // Estimated: `13391` + // Minimum execution time: 16_937_000 picoseconds. + Weight::from_parts(17_447_000, 0) + .saturating_add(Weight::from_parts(0, 13391)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:5 w:0) + /// Storage: `XcmPallet::VersionNotifyTargets` (r:6 w:0) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: // Measured: `40` - // Estimated: `13405` - // Minimum execution time: 16_261_000 picoseconds. - Weight::from_parts(16_986_000, 0) - .saturating_add(Weight::from_parts(0, 13405)) - .saturating_add(T::DbWeight::get().reads(5)) + // Estimated: `15880` + // Minimum execution time: 19_157_000 picoseconds. + Weight::from_parts(19_659_000, 0) + .saturating_add(Weight::from_parts(0, 15880)) + .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `XcmPallet::VersionNotifyTargets` (r:2 w:1) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -221,38 +259,38 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_current_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `6085` - // Minimum execution time: 30_539_000 picoseconds. - Weight::from_parts(31_117_000, 0) - .saturating_add(Weight::from_parts(0, 6085)) + // Measured: `183` + // Estimated: `6123` + // Minimum execution time: 30_699_000 picoseconds. + Weight::from_parts(31_537_000, 0) + .saturating_add(Weight::from_parts(0, 6123)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:3 w:0) + /// Storage: `XcmPallet::VersionNotifyTargets` (r:4 w:0) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_target_migration_fail() -> Weight { // Proof Size summary in bytes: // Measured: `69` - // Estimated: `8484` - // Minimum execution time: 9_463_000 picoseconds. - Weight::from_parts(9_728_000, 0) - .saturating_add(Weight::from_parts(0, 8484)) - .saturating_add(T::DbWeight::get().reads(3)) + // Estimated: `10959` + // Minimum execution time: 12_303_000 picoseconds. + Weight::from_parts(12_670_000, 0) + .saturating_add(Weight::from_parts(0, 10959)) + .saturating_add(T::DbWeight::get().reads(4)) } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:4 w:2) + /// Storage: `XcmPallet::VersionNotifyTargets` (r:5 w:2) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notify_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `37` - // Estimated: `10927` - // Minimum execution time: 15_169_000 picoseconds. - Weight::from_parts(15_694_000, 0) - .saturating_add(Weight::from_parts(0, 10927)) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `33` + // Estimated: `13398` + // Minimum execution time: 17_129_000 picoseconds. + Weight::from_parts(17_668_000, 0) + .saturating_add(Weight::from_parts(0, 13398)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:4 w:2) + /// Storage: `XcmPallet::VersionNotifyTargets` (r:5 w:2) /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -264,12 +302,12 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_and_notify_old_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `149` - // Estimated: `11039` - // Minimum execution time: 37_549_000 picoseconds. - Weight::from_parts(38_203_000, 0) - .saturating_add(Weight::from_parts(0, 11039)) - .saturating_add(T::DbWeight::get().reads(8)) + // Measured: `183` + // Estimated: `13548` + // Minimum execution time: 39_960_000 picoseconds. + Weight::from_parts(41_068_000, 0) + .saturating_add(Weight::from_parts(0, 13548)) + .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `XcmPallet::QueryCounter` (r:1 w:1) @@ -280,8 +318,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 2_947_000 picoseconds. - Weight::from_parts(3_117_000, 0) + // Minimum execution time: 2_333_000 picoseconds. + Weight::from_parts(2_504_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -292,10 +330,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7576` // Estimated: `11041` - // Minimum execution time: 24_595_000 picoseconds. - Weight::from_parts(24_907_000, 0) + // Minimum execution time: 22_932_000 picoseconds. + Weight::from_parts(23_307_000, 0) .saturating_add(Weight::from_parts(0, 11041)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `XcmPallet::AssetTraps` (r:1 w:1) + /// Proof: `XcmPallet::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn claim_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `23` + // Estimated: `3488` + // Minimum execution time: 34_558_000 picoseconds. + Weight::from_parts(35_299_000, 0) + .saturating_add(Weight::from_parts(0, 3488)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index e3ea2fb8c06..ed42f93692b 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -79,6 +79,13 @@ pub trait Config: crate::Config { fn set_up_complex_asset_transfer() -> Option<(Assets, u32, Location, Box)> { None } + + /// Gets an asset that can be handled by the AssetTransactor. + /// + /// Used only in benchmarks. + /// + /// Used, for example, in the benchmark for `claim_assets`. + fn get_asset() -> Asset; } benchmarks! { @@ -341,11 +348,23 @@ benchmarks! { u32::MAX, ).unwrap()).collect::>(); crate::Pallet::::expect_response(query_id, Response::PalletsInfo(infos.try_into().unwrap())); - }: { as QueryHandler>::take_response(query_id); } + claim_assets { + let claim_origin = RawOrigin::Signed(whitelisted_caller()); + let claim_location = T::ExecuteXcmOrigin::try_origin(claim_origin.clone().into()).map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; + let asset: Asset = T::get_asset(); + // Trap assets for claiming later + crate::Pallet::::drop_assets( + &claim_location, + asset.clone().into(), + &XcmContext { origin: None, message_id: [0u8; 32], topic: None } + ); + let versioned_assets = VersionedAssets::V4(asset.into()); + }: _>(claim_origin.into(), Box::new(versioned_assets), Box::new(VersionedLocation::V4(claim_location))) + impl_benchmark_test_suite!( Pallet, crate::mock::new_test_ext_with_balances(Vec::new()), diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 5e1a3e55f9b..1a1f8b402a3 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -85,6 +85,7 @@ pub trait WeightInfo { fn migrate_and_notify_old_targets() -> Weight; fn new_query() -> Weight; fn take_response() -> Weight; + fn claim_assets() -> Weight; } /// fallback implementation @@ -165,6 +166,10 @@ impl WeightInfo for TestWeightInfo { fn take_response() -> Weight { Weight::from_parts(100_000_000, 0) } + + fn claim_assets() -> Weight { + Weight::from_parts(100_000_000, 0) + } } #[frame_support::pallet] @@ -1386,6 +1391,64 @@ pub mod pallet { weight_limit, ) } + + /// Claims assets trapped on this pallet because of leftover assets during XCM execution. + /// + /// - `origin`: Anyone can call this extrinsic. + /// - `assets`: The exact assets that were trapped. Use the version to specify what version + /// was the latest when they were trapped. + /// - `beneficiary`: The location/account where the claimed assets will be deposited. + #[pallet::call_index(12)] + #[pallet::weight({ + let assets_version = assets.identify_version(); + let maybe_assets: Result = (*assets.clone()).try_into(); + let maybe_beneficiary: Result = (*beneficiary.clone()).try_into(); + match (maybe_assets, maybe_beneficiary) { + (Ok(assets), Ok(beneficiary)) => { + let ticket: Location = GeneralIndex(assets_version as u128).into(); + let mut message = Xcm(vec![ + ClaimAsset { assets: assets.clone(), ticket }, + DepositAsset { assets: AllCounted(assets.len() as u32).into(), beneficiary }, + ]); + T::Weigher::weight(&mut message).map_or(Weight::MAX, |w| T::WeightInfo::claim_assets().saturating_add(w)) + } + _ => Weight::MAX + } + })] + pub fn claim_assets( + origin: OriginFor, + assets: Box, + beneficiary: Box, + ) -> DispatchResult { + let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; + log::debug!(target: "xcm::pallet_xcm::claim_assets", "origin: {:?}, assets: {:?}, beneficiary: {:?}", origin_location, assets, beneficiary); + // Extract version from `assets`. + let assets_version = assets.identify_version(); + let assets: Assets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; + let number_of_assets = assets.len() as u32; + let beneficiary: Location = + (*beneficiary).try_into().map_err(|()| Error::::BadVersion)?; + let ticket: Location = GeneralIndex(assets_version as u128).into(); + let mut message = Xcm(vec![ + ClaimAsset { assets, ticket }, + DepositAsset { assets: AllCounted(number_of_assets).into(), beneficiary }, + ]); + let weight = + T::Weigher::weight(&mut message).map_err(|()| Error::::UnweighableMessage)?; + let mut hash = message.using_encoded(sp_io::hashing::blake2_256); + let outcome = T::XcmExecutor::prepare_and_execute( + origin_location, + message, + &mut hash, + weight, + weight, + ); + outcome.ensure_complete().map_err(|error| { + log::error!(target: "xcm::pallet_xcm::claim_assets", "XCM execution failed with error: {:?}", error); + Error::::LocalExecutionIncomplete + })?; + Ok(()) + } } } diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 17c181387dd..d5ba7312a3a 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -172,7 +172,7 @@ impl SendXcm for TestSendXcm { msg: &mut Option>, ) -> SendResult<(Location, Xcm<()>)> { if FAIL_SEND_XCM.with(|q| *q.borrow()) { - return Err(SendError::Transport("Intentional send failure used in tests")) + return Err(SendError::Transport("Intentional send failure used in tests")); } let pair = (dest.take().unwrap(), msg.take().unwrap()); Ok((pair, Assets::new())) @@ -654,6 +654,10 @@ impl super::benchmarking::Config for Test { }); Some((assets, fee_index as u32, dest, verify)) } + + fn get_asset() -> Asset { + Asset { id: AssetId(Location::here()), fun: Fungible(ExistentialDeposit::get()) } + } } pub(crate) fn last_event() -> RuntimeEvent { diff --git a/polkadot/xcm/pallet-xcm/src/tests/mod.rs b/polkadot/xcm/pallet-xcm/src/tests/mod.rs index 28c7d197443..13022d9a8b1 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/mod.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/mod.rs @@ -467,6 +467,57 @@ fn trapped_assets_can_be_claimed() { }); } +// Like `trapped_assets_can_be_claimed` but using the `claim_assets` extrinsic. +#[test] +fn claim_assets_works() { + let balances = vec![(ALICE, INITIAL_BALANCE)]; + new_test_ext_with_balances(balances).execute_with(|| { + // First trap some assets. + let trapping_program = + Xcm::builder_unsafe().withdraw_asset((Here, SEND_AMOUNT).into()).build(); + // Even though assets are trapped, the extrinsic returns success. + assert_ok!(XcmPallet::execute( + RuntimeOrigin::signed(ALICE), + Box::new(VersionedXcm::V4(trapping_program)), + BaseXcmWeight::get() * 2, + )); + assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); + + // Expected `AssetsTrapped` event info. + let source: Location = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + let versioned_assets = VersionedAssets::V4(Assets::from((Here, SEND_AMOUNT))); + let hash = BlakeTwo256::hash_of(&(source.clone(), versioned_assets.clone())); + + // Assets were indeed trapped. + assert_eq!( + last_events(2), + vec![ + RuntimeEvent::XcmPallet(crate::Event::AssetsTrapped { + hash, + origin: source, + assets: versioned_assets + }), + RuntimeEvent::XcmPallet(crate::Event::Attempted { + outcome: Outcome::Complete { used: BaseXcmWeight::get() * 1 } + }) + ], + ); + let trapped = AssetTraps::::iter().collect::>(); + assert_eq!(trapped, vec![(hash, 1)]); + + // Now claim them with the extrinsic. + assert_ok!(XcmPallet::claim_assets( + RuntimeOrigin::signed(ALICE), + Box::new(VersionedAssets::V4((Here, SEND_AMOUNT).into())), + Box::new(VersionedLocation::V4( + AccountId32 { network: None, id: ALICE.clone().into() }.into() + )), + )); + assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); + assert_eq!(AssetTraps::::iter().collect::>(), vec![]); + }); +} + /// Test failure to complete execution reverts intermediate side-effects. /// /// XCM program will withdraw and deposit some assets, then fail execution of a further withdraw. diff --git a/polkadot/xcm/src/lib.rs b/polkadot/xcm/src/lib.rs index c90ad25c0d8..ba8d726aecf 100644 --- a/polkadot/xcm/src/lib.rs +++ b/polkadot/xcm/src/lib.rs @@ -165,6 +165,15 @@ macro_rules! versioned_type { <$v3>::max_encoded_len() } } + impl IdentifyVersion for $n { + fn identify_version(&self) -> Version { + use $n::*; + match self { + V3(_) => v3::VERSION, + V4(_) => v4::VERSION, + } + } + } }; ($(#[$attr:meta])* pub enum $n:ident { @@ -287,6 +296,16 @@ macro_rules! versioned_type { <$v3>::max_encoded_len() } } + impl IdentifyVersion for $n { + fn identify_version(&self) -> Version { + use $n::*; + match self { + V2(_) => v2::VERSION, + V3(_) => v3::VERSION, + V4(_) => v4::VERSION, + } + } + } }; } @@ -493,6 +512,12 @@ pub trait WrapVersion { ) -> Result, ()>; } +/// Used to get the version out of a versioned type. +// TODO(XCMv5): This could be `GetVersion` and we change the current one to `GetVersionFor`. +pub trait IdentifyVersion { + fn identify_version(&self) -> Version; +} + /// Check and return the `Version` that should be used for the `Xcm` datum for the destination /// `Location`, which will interpret it. pub trait GetVersion { @@ -572,9 +597,9 @@ pub type AlwaysLts = AlwaysV4; pub mod prelude { pub use super::{ latest::prelude::*, AlwaysLatest, AlwaysLts, AlwaysV2, AlwaysV3, AlwaysV4, GetVersion, - IntoVersion, Unsupported, Version as XcmVersion, VersionedAsset, VersionedAssetId, - VersionedAssets, VersionedInteriorLocation, VersionedLocation, VersionedResponse, - VersionedXcm, WrapVersion, + IdentifyVersion, IntoVersion, Unsupported, Version as XcmVersion, VersionedAsset, + VersionedAssetId, VersionedAssets, VersionedInteriorLocation, VersionedLocation, + VersionedResponse, VersionedXcm, WrapVersion, }; } diff --git a/prdoc/pr_3403.prdoc b/prdoc/pr_3403.prdoc new file mode 100644 index 00000000000..086e769da3c --- /dev/null +++ b/prdoc/pr_3403.prdoc @@ -0,0 +1,22 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Add `claim_assets` extrinsic to `pallet-xcm`" + +doc: + - audience: Runtime User + description: | + There's a new extrinsic in `pallet-xcm` for claiming assets. + This means that if your assets ever get trapped while teleporting or doing reserve asset transfers, + you can easily claim them by calling this new extrinsic. + - audience: Runtime Dev + description: | + There's a new extrinsic in `pallet-xcm` that needs a new configuration item for its benchmarks. + It's a simple function in `pallet_xcm::benchmarking::Config`, `get_asset`, that returns a valid asset + handled by the AssetTransactor of the chain. + If you're already using `pallet-xcm-benchmarks`, then you already have this function there and can + just copy and paste it. + +crates: + - name: pallet-xcm + - name: staging-xcm -- GitLab From 59b2661444de2a25f2125a831bd786035a9fac4b Mon Sep 17 00:00:00 2001 From: Egor_P Date: Fri, 1 Mar 2024 15:51:53 +0700 Subject: [PATCH 055/188] [Backport] Node version and spec_version bumps and ordering of the prdoc files from 1.8.0 (#3508) This PR backports Node version and `spec_version` bumps to `1.8.0` from the latest release and orders prdoc files related to it. --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 4 ++-- .../runtimes/assets/asset-hub-westend/src/lib.rs | 2 +- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 2 +- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 2 +- .../collectives/collectives-westend/src/lib.rs | 2 +- .../runtimes/contracts/contracts-rococo/src/lib.rs | 2 +- .../runtimes/coretime/coretime-rococo/src/lib.rs | 2 +- .../runtimes/coretime/coretime-westend/src/lib.rs | 2 +- .../runtimes/glutton/glutton-westend/src/lib.rs | 2 +- .../runtimes/people/people-rococo/src/lib.rs | 2 +- .../runtimes/people/people-westend/src/lib.rs | 2 +- .../runtimes/testing/rococo-parachain/src/lib.rs | 2 +- polkadot/node/primitives/src/lib.rs | 2 +- polkadot/runtime/rococo/src/lib.rs | 2 +- polkadot/runtime/westend/src/lib.rs | 2 +- prdoc/{ => 1.8.0}/pr_1660.prdoc | 0 prdoc/{ => 1.8.0}/pr_2061.prdoc | 0 prdoc/{ => 1.8.0}/pr_2290.prdoc | 0 prdoc/{ => 1.8.0}/pr_2903.prdoc | 0 ...9-async-backing-on-all-testnet-system-chains.prdoc | 0 prdoc/{ => 1.8.0}/pr_3007.prdoc | 0 prdoc/{ => 1.8.0}/pr_3052.prdoc | 0 prdoc/{ => 1.8.0}/pr_3060.prdoc | 0 prdoc/{ => 1.8.0}/pr_3079.prdoc | 0 prdoc/{ => 1.8.0}/pr_3154.prdoc | 0 prdoc/{ => 1.8.0}/pr_3160.prdoc | 0 prdoc/{ => 1.8.0}/pr_3166.prdoc | 0 prdoc/{ => 1.8.0}/pr_3184.prdoc | 0 prdoc/{ => 1.8.0}/pr_3212.prdoc | 0 prdoc/{ => 1.8.0}/pr_3225.prdoc | 0 prdoc/{ => 1.8.0}/pr_3230.prdoc | 0 prdoc/{ => 1.8.0}/pr_3232.prdoc | 0 prdoc/{ => 1.8.0}/pr_3243.prdoc | 0 prdoc/{ => 1.8.0}/pr_3244.prdoc | 0 prdoc/{ => 1.8.0}/pr_3272.prdoc | 0 prdoc/{ => 1.8.0}/pr_3301.prdoc | 0 prdoc/{ => 1.8.0}/pr_3308.prdoc | 0 prdoc/{ => 1.8.0}/pr_3319.prdoc | 0 prdoc/{ => 1.8.0}/pr_3325.prdoc | 0 prdoc/{ => 1.8.0}/pr_3358.prdoc | 0 prdoc/{ => 1.8.0}/pr_3361.prdoc | 0 prdoc/{ => 1.8.0}/pr_3364.prdoc | 0 prdoc/{ => 1.8.0}/pr_3370.prdoc | 0 prdoc/{ => 1.8.0}/pr_3384.prdoc | 0 prdoc/{ => 1.8.0}/pr_3395.prdoc | 0 prdoc/{ => 1.8.0}/pr_3415.prdoc | 0 prdoc/{ => 1.8.0}/pr_3435.prdoc | 0 prdoc/1.8.0/pr_3477.prdoc | 11 +++++++++++ 48 files changed, 27 insertions(+), 16 deletions(-) rename prdoc/{ => 1.8.0}/pr_1660.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_2061.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_2290.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_2903.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_2949-async-backing-on-all-testnet-system-chains.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3007.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3052.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3060.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3079.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3154.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3160.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3166.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3184.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3212.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3225.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3230.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3232.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3243.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3244.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3272.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3301.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3308.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3319.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3325.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3358.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3361.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3364.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3370.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3384.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3395.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3415.prdoc (100%) rename prdoc/{ => 1.8.0}/pr_3435.prdoc (100%) create mode 100644 prdoc/1.8.0/pr_3477.prdoc diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index a64d4bc2365..17a12dd2f6f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -113,7 +113,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemine"), impl_name: create_runtime_str!("statemine"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 14, @@ -126,7 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemine"), impl_name: create_runtime_str!("statemine"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 14, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 5778ed362ee..1ead2897855 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -110,7 +110,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("westmint"), impl_name: create_runtime_str!("westmint"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 14, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index ee472f006fa..0b48d1717fa 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -202,7 +202,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bridge-hub-rococo"), impl_name: create_runtime_str!("bridge-hub-rococo"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 4, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 60d959b4053..e1344fce63d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -176,7 +176,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bridge-hub-westend"), impl_name: create_runtime_str!("bridge-hub-westend"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 4, diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 9a88ca174df..6bcf98c428f 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -117,7 +117,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("collectives-westend"), impl_name: create_runtime_str!("collectives-westend"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 5, diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index c73d2225ebd..0668b9a4c7d 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -133,7 +133,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("contracts-rococo"), impl_name: create_runtime_str!("contracts-rococo"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 6, diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index d95e68d85c4..cdff371c505 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -133,7 +133,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("coretime-rococo"), impl_name: create_runtime_str!("coretime-rococo"), authoring_version: 1, - spec_version: 1_007_001, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0, diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 4b9b180321d..7fa70647992 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -133,7 +133,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("coretime-westend"), impl_name: create_runtime_str!("coretime-westend"), authoring_version: 1, - spec_version: 1_007_001, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0, diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index e09ad42ea9f..232a82115a8 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -100,7 +100,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("glutton-westend"), impl_name: create_runtime_str!("glutton-westend"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 28b8062e0e0..2b8cc32f67c 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -126,7 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("people-rococo"), impl_name: create_runtime_str!("people-rococo"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0, diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index b2b32445613..2dc2d06a66b 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -126,7 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("people-westend"), impl_name: create_runtime_str!("people-westend"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0, diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index b69c2341d6b..2b21a12c3ca 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -107,7 +107,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("test-parachain"), impl_name: create_runtime_str!("test-parachain"), authoring_version: 1, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 6, diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index 6e3eefbcbe8..d295c21cce1 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -58,7 +58,7 @@ pub use disputes::{ /// relatively rare. /// /// The associated worker binaries should use the same version as the node that spawns them. -pub const NODE_VERSION: &'static str = "1.7.0"; +pub const NODE_VERSION: &'static str = "1.8.0"; // For a 16-ary Merkle Prefix Trie, we can expect at most 16 32-byte hashes per node // plus some overhead: diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 48395f45238..96e8c4e0979 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -149,7 +149,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("rococo"), impl_name: create_runtime_str!("parity-rococo-v2.0"), authoring_version: 0, - spec_version: 1_007_000, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 24, diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 4ac2202b8fc..b55d68ee0f6 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -150,7 +150,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("westend"), impl_name: create_runtime_str!("parity-westend"), authoring_version: 2, - spec_version: 1_007_001, + spec_version: 1_008_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 24, diff --git a/prdoc/pr_1660.prdoc b/prdoc/1.8.0/pr_1660.prdoc similarity index 100% rename from prdoc/pr_1660.prdoc rename to prdoc/1.8.0/pr_1660.prdoc diff --git a/prdoc/pr_2061.prdoc b/prdoc/1.8.0/pr_2061.prdoc similarity index 100% rename from prdoc/pr_2061.prdoc rename to prdoc/1.8.0/pr_2061.prdoc diff --git a/prdoc/pr_2290.prdoc b/prdoc/1.8.0/pr_2290.prdoc similarity index 100% rename from prdoc/pr_2290.prdoc rename to prdoc/1.8.0/pr_2290.prdoc diff --git a/prdoc/pr_2903.prdoc b/prdoc/1.8.0/pr_2903.prdoc similarity index 100% rename from prdoc/pr_2903.prdoc rename to prdoc/1.8.0/pr_2903.prdoc diff --git a/prdoc/pr_2949-async-backing-on-all-testnet-system-chains.prdoc b/prdoc/1.8.0/pr_2949-async-backing-on-all-testnet-system-chains.prdoc similarity index 100% rename from prdoc/pr_2949-async-backing-on-all-testnet-system-chains.prdoc rename to prdoc/1.8.0/pr_2949-async-backing-on-all-testnet-system-chains.prdoc diff --git a/prdoc/pr_3007.prdoc b/prdoc/1.8.0/pr_3007.prdoc similarity index 100% rename from prdoc/pr_3007.prdoc rename to prdoc/1.8.0/pr_3007.prdoc diff --git a/prdoc/pr_3052.prdoc b/prdoc/1.8.0/pr_3052.prdoc similarity index 100% rename from prdoc/pr_3052.prdoc rename to prdoc/1.8.0/pr_3052.prdoc diff --git a/prdoc/pr_3060.prdoc b/prdoc/1.8.0/pr_3060.prdoc similarity index 100% rename from prdoc/pr_3060.prdoc rename to prdoc/1.8.0/pr_3060.prdoc diff --git a/prdoc/pr_3079.prdoc b/prdoc/1.8.0/pr_3079.prdoc similarity index 100% rename from prdoc/pr_3079.prdoc rename to prdoc/1.8.0/pr_3079.prdoc diff --git a/prdoc/pr_3154.prdoc b/prdoc/1.8.0/pr_3154.prdoc similarity index 100% rename from prdoc/pr_3154.prdoc rename to prdoc/1.8.0/pr_3154.prdoc diff --git a/prdoc/pr_3160.prdoc b/prdoc/1.8.0/pr_3160.prdoc similarity index 100% rename from prdoc/pr_3160.prdoc rename to prdoc/1.8.0/pr_3160.prdoc diff --git a/prdoc/pr_3166.prdoc b/prdoc/1.8.0/pr_3166.prdoc similarity index 100% rename from prdoc/pr_3166.prdoc rename to prdoc/1.8.0/pr_3166.prdoc diff --git a/prdoc/pr_3184.prdoc b/prdoc/1.8.0/pr_3184.prdoc similarity index 100% rename from prdoc/pr_3184.prdoc rename to prdoc/1.8.0/pr_3184.prdoc diff --git a/prdoc/pr_3212.prdoc b/prdoc/1.8.0/pr_3212.prdoc similarity index 100% rename from prdoc/pr_3212.prdoc rename to prdoc/1.8.0/pr_3212.prdoc diff --git a/prdoc/pr_3225.prdoc b/prdoc/1.8.0/pr_3225.prdoc similarity index 100% rename from prdoc/pr_3225.prdoc rename to prdoc/1.8.0/pr_3225.prdoc diff --git a/prdoc/pr_3230.prdoc b/prdoc/1.8.0/pr_3230.prdoc similarity index 100% rename from prdoc/pr_3230.prdoc rename to prdoc/1.8.0/pr_3230.prdoc diff --git a/prdoc/pr_3232.prdoc b/prdoc/1.8.0/pr_3232.prdoc similarity index 100% rename from prdoc/pr_3232.prdoc rename to prdoc/1.8.0/pr_3232.prdoc diff --git a/prdoc/pr_3243.prdoc b/prdoc/1.8.0/pr_3243.prdoc similarity index 100% rename from prdoc/pr_3243.prdoc rename to prdoc/1.8.0/pr_3243.prdoc diff --git a/prdoc/pr_3244.prdoc b/prdoc/1.8.0/pr_3244.prdoc similarity index 100% rename from prdoc/pr_3244.prdoc rename to prdoc/1.8.0/pr_3244.prdoc diff --git a/prdoc/pr_3272.prdoc b/prdoc/1.8.0/pr_3272.prdoc similarity index 100% rename from prdoc/pr_3272.prdoc rename to prdoc/1.8.0/pr_3272.prdoc diff --git a/prdoc/pr_3301.prdoc b/prdoc/1.8.0/pr_3301.prdoc similarity index 100% rename from prdoc/pr_3301.prdoc rename to prdoc/1.8.0/pr_3301.prdoc diff --git a/prdoc/pr_3308.prdoc b/prdoc/1.8.0/pr_3308.prdoc similarity index 100% rename from prdoc/pr_3308.prdoc rename to prdoc/1.8.0/pr_3308.prdoc diff --git a/prdoc/pr_3319.prdoc b/prdoc/1.8.0/pr_3319.prdoc similarity index 100% rename from prdoc/pr_3319.prdoc rename to prdoc/1.8.0/pr_3319.prdoc diff --git a/prdoc/pr_3325.prdoc b/prdoc/1.8.0/pr_3325.prdoc similarity index 100% rename from prdoc/pr_3325.prdoc rename to prdoc/1.8.0/pr_3325.prdoc diff --git a/prdoc/pr_3358.prdoc b/prdoc/1.8.0/pr_3358.prdoc similarity index 100% rename from prdoc/pr_3358.prdoc rename to prdoc/1.8.0/pr_3358.prdoc diff --git a/prdoc/pr_3361.prdoc b/prdoc/1.8.0/pr_3361.prdoc similarity index 100% rename from prdoc/pr_3361.prdoc rename to prdoc/1.8.0/pr_3361.prdoc diff --git a/prdoc/pr_3364.prdoc b/prdoc/1.8.0/pr_3364.prdoc similarity index 100% rename from prdoc/pr_3364.prdoc rename to prdoc/1.8.0/pr_3364.prdoc diff --git a/prdoc/pr_3370.prdoc b/prdoc/1.8.0/pr_3370.prdoc similarity index 100% rename from prdoc/pr_3370.prdoc rename to prdoc/1.8.0/pr_3370.prdoc diff --git a/prdoc/pr_3384.prdoc b/prdoc/1.8.0/pr_3384.prdoc similarity index 100% rename from prdoc/pr_3384.prdoc rename to prdoc/1.8.0/pr_3384.prdoc diff --git a/prdoc/pr_3395.prdoc b/prdoc/1.8.0/pr_3395.prdoc similarity index 100% rename from prdoc/pr_3395.prdoc rename to prdoc/1.8.0/pr_3395.prdoc diff --git a/prdoc/pr_3415.prdoc b/prdoc/1.8.0/pr_3415.prdoc similarity index 100% rename from prdoc/pr_3415.prdoc rename to prdoc/1.8.0/pr_3415.prdoc diff --git a/prdoc/pr_3435.prdoc b/prdoc/1.8.0/pr_3435.prdoc similarity index 100% rename from prdoc/pr_3435.prdoc rename to prdoc/1.8.0/pr_3435.prdoc diff --git a/prdoc/1.8.0/pr_3477.prdoc b/prdoc/1.8.0/pr_3477.prdoc new file mode 100644 index 00000000000..26e96d3635b --- /dev/null +++ b/prdoc/1.8.0/pr_3477.prdoc @@ -0,0 +1,11 @@ +title: Allow parachain which acquires multiple coretime cores to make progress + +doc: + - audience: Node Operator + description: | + Adds the needed changes so that parachains which acquire multiple coretime cores can still make progress. + Only one of the cores will be able to be occupied at a time. + Only works if the ElasticScalingMVP node feature is enabled in the runtime and the block author validator is + updated to include this change. + +crates: [ ] -- GitLab From a1b57a8c181bc39b254ff4d6d774f6ff348e509d Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 1 Mar 2024 13:19:17 +0200 Subject: [PATCH 056/188] Fix crash of synced parachain node run with `--sync=warp` (#3523) Fixes https://github.com/paritytech/polkadot-sdk/issues/3496. --- prdoc/pr_3523.prdoc | 19 ++++ substrate/client/network/sync/src/engine.rs | 2 + substrate/client/network/sync/src/strategy.rs | 88 +++++++++++++++++-- 3 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 prdoc/pr_3523.prdoc diff --git a/prdoc/pr_3523.prdoc b/prdoc/pr_3523.prdoc new file mode 100644 index 00000000000..c31d9d096dc --- /dev/null +++ b/prdoc/pr_3523.prdoc @@ -0,0 +1,19 @@ +title: Fix crash of synced parachain node run with `--sync=warp` + +doc: + - audience: Node Operator + description: | + Fix crash of `SyncingEngine` when an already synced parachain node is run with `--sync=warp` + (issue https://github.com/paritytech/polkadot-sdk/issues/3496). + The issue manifests itself by errors in the logs: + ``` + [Parachain] Cannot set warp sync target block: no warp sync strategy is active. + [Parachain] Failed to set warp sync target block header, terminating `SyncingEngine`. + ``` + Followed by a stream of messages: + ``` + [Parachain] Protocol command streams have been shut down + ``` + +crates: + - name: sc-network-sync diff --git a/substrate/client/network/sync/src/engine.rs b/substrate/client/network/sync/src/engine.rs index c1a7009eeb0..24640fdc455 100644 --- a/substrate/client/network/sync/src/engine.rs +++ b/substrate/client/network/sync/src/engine.rs @@ -656,6 +656,8 @@ where Some(event) => self.process_notification_event(event), None => return, }, + // TODO: setting of warp sync target block should be moved to the initialization of + // `SyncingEngine`, see https://github.com/paritytech/polkadot-sdk/issues/3537. warp_target_block_header = &mut self.warp_sync_target_block_header_rx_fused => { if let Err(_) = self.pass_warp_sync_target_block_header(warp_target_block_header) { error!( diff --git a/substrate/client/network/sync/src/strategy.rs b/substrate/client/network/sync/src/strategy.rs index 7d6e6a8d3b8..dabcf37ae63 100644 --- a/substrate/client/network/sync/src/strategy.rs +++ b/substrate/client/network/sync/src/strategy.rs @@ -30,7 +30,7 @@ use crate::{ }; use chain_sync::{ChainSync, ChainSyncAction, ChainSyncMode}; use libp2p::PeerId; -use log::{debug, error, info}; +use log::{debug, error, info, warn}; use prometheus_endpoint::Registry; use sc_client_api::{BlockBackend, ProofProvider}; use sc_consensus::{BlockImportError, BlockImportStatus, IncomingBlock}; @@ -159,7 +159,7 @@ impl From> for SyncingAction { /// Proxy to specific syncing strategies. pub struct SyncingStrategy { - /// Syncing configuration. + /// Initial syncing configuration. config: SyncingConfig, /// Client used by syncing strategies. client: Arc, @@ -466,15 +466,27 @@ where &mut self, target_header: B::Header, ) -> Result<(), ()> { - match self.warp { - Some(ref mut warp) => { - warp.set_target_block(target_header); - Ok(()) + match self.config.mode { + SyncMode::Warp => match self.warp { + Some(ref mut warp) => { + warp.set_target_block(target_header); + Ok(()) + }, + None => { + // As mode is set to warp sync, but no warp sync strategy is active, this means + // that warp sync has already finished / was skipped. + warn!( + target: LOG_TARGET, + "Discarding warp sync target, as warp sync was seemingly skipped due \ + to node being (partially) synced.", + ); + Ok(()) + }, }, - None => { + _ => { error!( target: LOG_TARGET, - "Cannot set warp sync target block: no warp sync strategy is active." + "Cannot set warp sync target block: not in warp sync mode." ); debug_assert!(false); Err(()) @@ -587,3 +599,63 @@ where } } } + +#[cfg(test)] +mod test { + use super::*; + use futures::executor::block_on; + use sc_block_builder::BlockBuilderBuilder; + use substrate_test_runtime_client::{ + ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt, TestClientBuilder, + TestClientBuilderExt, + }; + + /// Regression test for crash when starting already synced parachain node with `--sync=warp`. + /// We must remove this after setting of warp sync target block is moved to initialization of + /// `SyncingEngine` (issue https://github.com/paritytech/polkadot-sdk/issues/3537). + #[test] + fn set_target_block_finished_warp_sync() { + // Populate database with finalized state. + let mut client = Arc::new(TestClientBuilder::new().build()); + let block = BlockBuilderBuilder::new(&*client) + .on_parent_block(client.chain_info().best_hash) + .with_parent_block_number(client.chain_info().best_number) + .build() + .unwrap() + .build() + .unwrap() + .block; + block_on(client.import(BlockOrigin::Own, block.clone())).unwrap(); + let just = (*b"TEST", Vec::new()); + client.finalize_block(block.hash(), Some(just)).unwrap(); + let target_block = BlockBuilderBuilder::new(&*client) + .on_parent_block(client.chain_info().best_hash) + .with_parent_block_number(client.chain_info().best_number) + .build() + .unwrap() + .build() + .unwrap() + .block; + + // Initialize syncing strategy. + let config = SyncingConfig { + mode: SyncMode::Warp, + max_parallel_downloads: 3, + max_blocks_per_request: 64, + metrics_registry: None, + }; + let mut strategy = + SyncingStrategy::new(config, client, Some(WarpSyncConfig::WaitForTarget)).unwrap(); + + // Warp sync instantly finishes as we have finalized state in DB. + let actions = strategy.actions().unwrap(); + assert_eq!(actions.len(), 1); + assert!(matches!(actions[0], SyncingAction::Finished)); + assert!(strategy.warp.is_none()); + + // Try setting the target block. We mustn't crash. + strategy + .set_warp_sync_target_block_header(target_block.header().clone()) + .unwrap(); + } +} -- GitLab From 6f81a4a09270a5930b8786e2dc765347078b4d4a Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Sat, 2 Mar 2024 01:23:21 +1300 Subject: [PATCH 057/188] make SelfParaId a metadata constant (#3517) expose para id via metadata #2116 is blocked by this --- cumulus/pallets/parachain-system/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index 3439227bc5b..81965a2a313 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -205,6 +205,7 @@ pub mod pallet { type OnSystemEvent: OnSystemEvent; /// Returns the parachain ID we are running with. + #[pallet::constant] type SelfParaId: Get; /// The place where outbound XCMP messages come from. This is queried in `finalize_block`. -- GitLab From f0e589d72e5228472c7658c525e0ff80d122d777 Mon Sep 17 00:00:00 2001 From: Andrei Eres Date: Fri, 1 Mar 2024 15:30:43 +0100 Subject: [PATCH 058/188] subsystem-bench: add regression tests for availability read and write (#3311) ### What's been done - `subsystem-bench` has been split into two parts: a cli benchmark runner and a library. - The cli runner is quite simple. It just allows us to run `.yaml` based test sequences. Now it should only be used to run benchmarks during development. - The library is used in the cli runner and in regression tests. Some code is changed to make the library independent of the runner. - Added first regression tests for availability read and write that replicate existing test sequences. ### How we run regression tests - Regression tests are simply rust integration tests without the harnesses. - They should only be compiled under the `subsystem-benchmarks` feature to prevent them from running with other tests. - This doesn't work when running tests with `nextest` in CI, so additional filters have been added to the `nextest` runs. - Each benchmark run takes a different time in the beginning, so we "warm up" the tests until their CPU usage differs by only 1%. - After the warm-up, we run the benchmarks a few more times and compare the average with the exception using a precision. ### What is still wrong? - I haven't managed to set up approval voting tests. The spread of their results is too large and can't be narrowed down in a reasonable amount of time in the warm-up phase. - The tests start an unconfigurable prometheus endpoint inside, which causes errors because they use the same 9999 port. I disable it with a flag, but I think it's better to extract the endpoint launching outside the test, as we already do with `valgrind` and `pyroscope`. But we still use `prometheus` inside the tests. ### Future work * https://github.com/paritytech/polkadot-sdk/issues/3528 * https://github.com/paritytech/polkadot-sdk/issues/3529 * https://github.com/paritytech/polkadot-sdk/issues/3530 * https://github.com/paritytech/polkadot-sdk/issues/3531 --------- Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> --- .gitlab/pipeline/test.yml | 3 +- Cargo.lock | 2 + .../availability-distribution/Cargo.toml | 11 ++ ...ilability-distribution-regression-bench.rs | 113 +++++++++++++ .../network/availability-recovery/Cargo.toml | 7 + .../availability-recovery-regression-bench.rs | 103 ++++++++++++ polkadot/node/subsystem-bench/Cargo.toml | 6 +- polkadot/node/subsystem-bench/README.md | 146 +++++++++-------- .../examples/approvals_no_shows.yaml | 6 +- .../examples/approvals_throughput.yaml | 3 +- .../approvals_throughput_best_case.yaml | 2 +- ...s_throughput_no_optimisations_enabled.yaml | 2 +- .../subsystem-bench/src/availability/cli.rs | 37 ----- .../src/{ => cli}/subsystem-bench.rs | 149 ++++++++---------- .../subsystem-bench/src/{ => cli}/valgrind.rs | 0 .../src/{ => lib}/approval/helpers.rs | 2 +- .../{ => lib}/approval/message_generator.rs | 19 +-- .../approval/mock_chain_selection.rs | 0 .../src/{ => lib}/approval/mod.rs | 50 +++--- .../src/{ => lib}/approval/test_message.rs | 5 +- .../availability/av_store_helpers.rs | 2 +- .../src/{ => lib}/availability/mod.rs | 70 ++++---- .../src/{core => lib}/configuration.rs | 113 ++++++------- .../src/{core => lib}/display.rs | 28 ++-- .../src/{core => lib}/environment.rs | 78 +++------ .../src/{core => lib}/keyring.rs | 0 .../src/{core/mod.rs => lib/lib.rs} | 7 +- .../src/{core => lib}/mock/av_store.rs | 2 +- .../src/{core => lib}/mock/chain_api.rs | 0 .../src/{core => lib}/mock/dummy.rs | 0 .../src/{core => lib}/mock/mod.rs | 4 +- .../src/{core => lib}/mock/network_bridge.rs | 2 +- .../src/{core => lib}/mock/runtime_api.rs | 2 +- .../src/{core => lib}/network.rs | 2 +- .../node/subsystem-bench/src/lib/usage.rs | 146 +++++++++++++++++ 35 files changed, 711 insertions(+), 411 deletions(-) create mode 100644 polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs create mode 100644 polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs delete mode 100644 polkadot/node/subsystem-bench/src/availability/cli.rs rename polkadot/node/subsystem-bench/src/{ => cli}/subsystem-bench.rs (62%) rename polkadot/node/subsystem-bench/src/{ => cli}/valgrind.rs (100%) rename polkadot/node/subsystem-bench/src/{ => lib}/approval/helpers.rs (99%) rename polkadot/node/subsystem-bench/src/{ => lib}/approval/message_generator.rs (97%) rename polkadot/node/subsystem-bench/src/{ => lib}/approval/mock_chain_selection.rs (100%) rename polkadot/node/subsystem-bench/src/{ => lib}/approval/mod.rs (97%) rename polkadot/node/subsystem-bench/src/{ => lib}/approval/test_message.rs (98%) rename polkadot/node/subsystem-bench/src/{ => lib}/availability/av_store_helpers.rs (94%) rename polkadot/node/subsystem-bench/src/{ => lib}/availability/mod.rs (94%) rename polkadot/node/subsystem-bench/src/{core => lib}/configuration.rs (83%) rename polkadot/node/subsystem-bench/src/{core => lib}/display.rs (89%) rename polkadot/node/subsystem-bench/src/{core => lib}/environment.rs (88%) rename polkadot/node/subsystem-bench/src/{core => lib}/keyring.rs (100%) rename polkadot/node/subsystem-bench/src/{core/mod.rs => lib/lib.rs} (88%) rename polkadot/node/subsystem-bench/src/{core => lib}/mock/av_store.rs (99%) rename polkadot/node/subsystem-bench/src/{core => lib}/mock/chain_api.rs (100%) rename polkadot/node/subsystem-bench/src/{core => lib}/mock/dummy.rs (100%) rename polkadot/node/subsystem-bench/src/{core => lib}/mock/mod.rs (97%) rename polkadot/node/subsystem-bench/src/{core => lib}/mock/network_bridge.rs (99%) rename polkadot/node/subsystem-bench/src/{core => lib}/mock/runtime_api.rs (99%) rename polkadot/node/subsystem-bench/src/{core => lib}/network.rs (99%) create mode 100644 polkadot/node/subsystem-bench/src/lib/usage.rs diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index 9f774aab271..5c41a3e6e08 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -25,6 +25,7 @@ test-linux-stable: # "upgrade_version_checks_should_work" is currently failing - | time cargo nextest run \ + --filter-expr 'not deps(/polkadot-subsystem-bench/)' \ --workspace \ --locked \ --release \ @@ -69,7 +70,7 @@ test-linux-stable-runtime-benchmarks: # but still want to have debug assertions. RUSTFLAGS: "-Cdebug-assertions=y -Dwarnings" script: - - time cargo nextest run --workspace --features runtime-benchmarks benchmark --locked --cargo-profile testnet + - time cargo nextest run --filter-expr 'not deps(/polkadot-subsystem-bench/)' --workspace --features runtime-benchmarks benchmark --locked --cargo-profile testnet # can be used to run all tests # test-linux-stable-all: diff --git a/Cargo.lock b/Cargo.lock index 991541ee84e..b12006bbcf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12269,6 +12269,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "polkadot-primitives-test-helpers", + "polkadot-subsystem-bench", "rand", "sc-network", "schnellru", @@ -12300,6 +12301,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "polkadot-primitives-test-helpers", + "polkadot-subsystem-bench", "rand", "sc-network", "schnellru", diff --git a/polkadot/node/network/availability-distribution/Cargo.toml b/polkadot/node/network/availability-distribution/Cargo.toml index 432501ed23f..182d92cb163 100644 --- a/polkadot/node/network/availability-distribution/Cargo.toml +++ b/polkadot/node/network/availability-distribution/Cargo.toml @@ -36,3 +36,14 @@ sc-network = { path = "../../../../substrate/client/network" } futures-timer = "3.0.2" assert_matches = "1.4.0" polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } +polkadot-subsystem-bench = { path = "../../subsystem-bench" } + + +[[test]] +name = "availability-distribution-regression-bench" +path = "tests/availability-distribution-regression-bench.rs" +harness = false +required-features = ["subsystem-benchmarks"] + +[features] +subsystem-benchmarks = [] diff --git a/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs b/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs new file mode 100644 index 00000000000..f2872f3c72b --- /dev/null +++ b/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs @@ -0,0 +1,113 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! availability-read regression tests +//! +//! TODO: Explain the test case after configuration adjusted to Kusama +//! +//! Subsystems involved: +//! - availability-distribution +//! - bitfield-distribution +//! - availability-store + +use polkadot_subsystem_bench::{ + availability::{benchmark_availability_write, prepare_test, TestDataAvailability, TestState}, + configuration::{PeerLatency, TestConfiguration}, + usage::BenchmarkUsage, +}; + +const BENCH_COUNT: usize = 3; +const WARM_UP_COUNT: usize = 20; +const WARM_UP_PRECISION: f64 = 0.01; + +fn main() -> Result<(), String> { + let mut messages = vec![]; + + // TODO: Adjust the test configurations to Kusama values + let mut config = TestConfiguration::default(); + config.latency = Some(PeerLatency { mean_latency_ms: 30, std_dev: 2.0 }); + config.n_validators = 1000; + config.n_cores = 200; + config.max_validators_per_core = 5; + config.min_pov_size = 5120; + config.max_pov_size = 5120; + config.peer_bandwidth = 52428800; + config.bandwidth = 52428800; + config.connectivity = 75; + config.num_blocks = 3; + config.generate_pov_sizes(); + + warm_up(config.clone())?; + let usage = benchmark(config.clone()); + + messages.extend(usage.check_network_usage(&[ + ("Received from peers", 4330.0, 0.05), + ("Sent to peers", 15900.0, 0.05), + ])); + messages.extend(usage.check_cpu_usage(&[ + ("availability-distribution", 0.025, 0.05), + ("bitfield-distribution", 0.085, 0.05), + ("availability-store", 0.180, 0.05), + ])); + + if messages.is_empty() { + Ok(()) + } else { + eprintln!("{}", messages.join("\n")); + Err("Regressions found".to_string()) + } +} + +fn warm_up(config: TestConfiguration) -> Result<(), String> { + println!("Warming up..."); + let mut prev_run: Option = None; + for _ in 0..WARM_UP_COUNT { + let curr = run(config.clone()); + if let Some(ref prev) = prev_run { + let av_distr_diff = + curr.cpu_usage_diff(prev, "availability-distribution").expect("Must exist"); + let bitf_distr_diff = + curr.cpu_usage_diff(prev, "bitfield-distribution").expect("Must exist"); + let av_store_diff = + curr.cpu_usage_diff(prev, "availability-store").expect("Must exist"); + if av_distr_diff < WARM_UP_PRECISION && + bitf_distr_diff < WARM_UP_PRECISION && + av_store_diff < WARM_UP_PRECISION + { + return Ok(()) + } + } + prev_run = Some(curr); + } + + Err("Can't warm up".to_string()) +} + +fn benchmark(config: TestConfiguration) -> BenchmarkUsage { + println!("Benchmarking..."); + let usages: Vec = (0..BENCH_COUNT).map(|_| run(config.clone())).collect(); + let usage = BenchmarkUsage::average(&usages); + println!("{}", usage); + usage +} + +fn run(config: TestConfiguration) -> BenchmarkUsage { + let mut state = TestState::new(&config); + let (mut env, _protocol_config) = + prepare_test(config.clone(), &mut state, TestDataAvailability::Write, false); + env.runtime() + .block_on(benchmark_availability_write("data_availability_write", &mut env, state)) +} diff --git a/polkadot/node/network/availability-recovery/Cargo.toml b/polkadot/node/network/availability-recovery/Cargo.toml index 9eddf5c86d2..12b6ce7a057 100644 --- a/polkadot/node/network/availability-recovery/Cargo.toml +++ b/polkadot/node/network/availability-recovery/Cargo.toml @@ -41,6 +41,13 @@ sc-network = { path = "../../../../substrate/client/network" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } +polkadot-subsystem-bench = { path = "../../subsystem-bench" } + +[[test]] +name = "availability-recovery-regression-bench" +path = "tests/availability-recovery-regression-bench.rs" +harness = false +required-features = ["subsystem-benchmarks"] [features] subsystem-benchmarks = [] diff --git a/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs b/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs new file mode 100644 index 00000000000..beb063e7ae0 --- /dev/null +++ b/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs @@ -0,0 +1,103 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! availability-write regression tests +//! +//! TODO: Explain the test case after configuration adjusted to Kusama +//! +//! Subsystems involved: +//! - availability-recovery + +use polkadot_subsystem_bench::{ + availability::{ + benchmark_availability_read, prepare_test, DataAvailabilityReadOptions, + TestDataAvailability, TestState, + }, + configuration::{PeerLatency, TestConfiguration}, + usage::BenchmarkUsage, +}; + +const BENCH_COUNT: usize = 3; +const WARM_UP_COUNT: usize = 10; +const WARM_UP_PRECISION: f64 = 0.01; + +fn main() -> Result<(), String> { + let mut messages = vec![]; + + // TODO: Adjust the test configurations to Kusama values + let options = DataAvailabilityReadOptions { fetch_from_backers: true }; + let mut config = TestConfiguration::default(); + config.latency = Some(PeerLatency { mean_latency_ms: 100, std_dev: 1.0 }); + config.n_validators = 300; + config.n_cores = 20; + config.min_pov_size = 5120; + config.max_pov_size = 5120; + config.peer_bandwidth = 52428800; + config.bandwidth = 52428800; + config.num_blocks = 3; + config.connectivity = 90; + config.generate_pov_sizes(); + + warm_up(config.clone(), options.clone())?; + let usage = benchmark(config.clone(), options.clone()); + + messages.extend(usage.check_network_usage(&[ + ("Received from peers", 102400.000, 0.05), + ("Sent to peers", 0.335, 0.05), + ])); + messages.extend(usage.check_cpu_usage(&[("availability-recovery", 3.850, 0.05)])); + + if messages.is_empty() { + Ok(()) + } else { + eprintln!("{}", messages.join("\n")); + Err("Regressions found".to_string()) + } +} + +fn warm_up(config: TestConfiguration, options: DataAvailabilityReadOptions) -> Result<(), String> { + println!("Warming up..."); + let mut prev_run: Option = None; + for _ in 0..WARM_UP_COUNT { + let curr = run(config.clone(), options.clone()); + if let Some(ref prev) = prev_run { + let diff = curr.cpu_usage_diff(prev, "availability-recovery").expect("Must exist"); + if diff < WARM_UP_PRECISION { + return Ok(()) + } + } + prev_run = Some(curr); + } + + Err("Can't warm up".to_string()) +} + +fn benchmark(config: TestConfiguration, options: DataAvailabilityReadOptions) -> BenchmarkUsage { + println!("Benchmarking..."); + let usages: Vec = + (0..BENCH_COUNT).map(|_| run(config.clone(), options.clone())).collect(); + let usage = BenchmarkUsage::average(&usages); + println!("{}", usage); + usage +} + +fn run(config: TestConfiguration, options: DataAvailabilityReadOptions) -> BenchmarkUsage { + let mut state = TestState::new(&config); + let (mut env, _protocol_config) = + prepare_test(config.clone(), &mut state, TestDataAvailability::Read(options), false); + env.runtime() + .block_on(benchmark_availability_read("data_availability_read", &mut env, state)) +} diff --git a/polkadot/node/subsystem-bench/Cargo.toml b/polkadot/node/subsystem-bench/Cargo.toml index 7de91d8cd5d..726e7de4587 100644 --- a/polkadot/node/subsystem-bench/Cargo.toml +++ b/polkadot/node/subsystem-bench/Cargo.toml @@ -8,9 +8,13 @@ license.workspace = true readme = "README.md" publish = false +[lib] +name = "polkadot_subsystem_bench" +path = "src/lib/lib.rs" + [[bin]] name = "subsystem-bench" -path = "src/subsystem-bench.rs" +path = "src/cli/subsystem-bench.rs" # Prevent rustdoc error. Already documented from top-level Cargo.toml. doc = false diff --git a/polkadot/node/subsystem-bench/README.md b/polkadot/node/subsystem-bench/README.md index e090a0392cb..3aac2810ad5 100644 --- a/polkadot/node/subsystem-bench/README.md +++ b/polkadot/node/subsystem-bench/README.md @@ -1,6 +1,6 @@ # Subsystem benchmark client -Run parachain consensus stress and performance tests on your development machine. +Run parachain consensus stress and performance tests on your development machine or in CI. ## Motivation @@ -32,7 +32,8 @@ a local Grafana/Prometheus stack is needed. ### Run Prometheus, Pyroscope and Graphana in Docker -If docker is not usable, then follow the next sections to manually install Prometheus, Pyroscope and Graphana on your machine. +If docker is not usable, then follow the next sections to manually install Prometheus, Pyroscope and Graphana +on your machine. ```bash cd polkadot/node/subsystem-bench/docker @@ -95,39 +96,16 @@ If you are running the servers in Docker, use the following URLs: Follow [this guide](https://grafana.com/docs/grafana/latest/dashboards/manage-dashboards/#export-and-import-dashboards) to import the dashboards from the repository `grafana` folder. -## How to run a test - -To run a test, you need to first choose a test objective. Currently, we support the following: - -``` -target/testnet/subsystem-bench --help -The almighty Subsystem Benchmark Tool™️ - -Usage: subsystem-bench [OPTIONS] - -Commands: - data-availability-read Benchmark availability recovery strategies +### Standard test options ``` +$ subsystem-bench --help +Usage: subsystem-bench [OPTIONS] -Note: `test-sequence` is a special test objective that wraps up an arbitrary number of test objectives. It is tipically - used to run a suite of tests defined in a `yaml` file like in this [example](examples/availability_read.yaml). +Arguments: + Path to the test sequence configuration file -### Standard test options - -``` - --network The type of network to be emulated [default: ideal] [possible values: ideal, healthy, - degraded] - --n-cores Number of cores to fetch availability for [default: 100] - --n-validators Number of validators to fetch chunks from [default: 500] - --min-pov-size The minimum pov size in KiB [default: 5120] - --max-pov-size The maximum pov size bytes [default: 5120] - -n, --num-blocks The number of blocks the test is going to run [default: 1] - -p, --peer-bandwidth The bandwidth of emulated remote peers in KiB - -b, --bandwidth The bandwidth of our node in KiB - --connectivity Emulated peer connection ratio [0-100] - --peer-mean-latency Mean remote peer latency in milliseconds [0-5000] - --peer-latency-std-dev Remote peer latency standard deviation +Options: --profile Enable CPU Profiling with Pyroscope --pyroscope-url Pyroscope Server URL [default: http://localhost:4040] --pyroscope-sample-rate Pyroscope Sample Rate [default: 113] @@ -135,27 +113,17 @@ Note: `test-sequence` is a special test objective that wraps up an arbitrary num -h, --help Print help ``` -These apply to all test objectives, except `test-sequence` which relies on the values being specified in a file. - -### Test objectives - -Each test objective can have it's specific configuration options, in contrast with the standard test options. +## How to run a test -For `data-availability-read` the recovery strategy to be used is configurable. +To run a test, you need to use a path to a test objective: ``` -target/testnet/subsystem-bench data-availability-read --help -Benchmark availability recovery strategies - -Usage: subsystem-bench data-availability-read [OPTIONS] - -Options: - -f, --fetch-from-backers Turbo boost AD Read by fetching the full availability datafrom backers first. Saves CPU - as we don't need to re-construct from chunks. Tipically this is only faster if nodes - have enough bandwidth - -h, --help Print help +target/testnet/subsystem-bench polkadot/node/subsystem-bench/examples/availability_read.yaml ``` +Note: test objectives may be wrapped up into a test sequence. +It is tipically used to run a suite of tests like in this [example](examples/availability_read.yaml). + ### Understanding the test configuration A single test configuration `TestConfiguration` struct applies to a single run of a certain test objective. @@ -175,36 +143,65 @@ the test is started. ### Example run -Let's run an availabilty read test which will recover availability for 10 cores with max PoV size on a 500 +Let's run an availabilty read test which will recover availability for 200 cores with max PoV size on a 1000 node validator network. + + ``` - target/testnet/subsystem-bench --n-cores 10 data-availability-read -[2023-11-28T09:01:59Z INFO subsystem_bench::core::display] n_validators = 500, n_cores = 10, pov_size = 5120 - 5120, - latency = None -[2023-11-28T09:01:59Z INFO subsystem-bench::availability] Generating template candidate index=0 pov_size=5242880 -[2023-11-28T09:01:59Z INFO subsystem-bench::availability] Created test environment. -[2023-11-28T09:01:59Z INFO subsystem-bench::availability] Pre-generating 10 candidates. -[2023-11-28T09:02:01Z INFO subsystem-bench::core] Initializing network emulation for 500 peers. -[2023-11-28T09:02:01Z INFO substrate_prometheus_endpoint] 〽️ Prometheus exporter started at 127.0.0.1:9999 -[2023-11-28T09:02:01Z INFO subsystem-bench::availability] Current block 1/1 -[2023-11-28T09:02:01Z INFO subsystem_bench::availability] 10 recoveries pending -[2023-11-28T09:02:04Z INFO subsystem_bench::availability] Block time 3231ms -[2023-11-28T09:02:04Z INFO subsystem-bench::availability] Sleeping till end of block (2768ms) -[2023-11-28T09:02:07Z INFO subsystem_bench::availability] All blocks processed in 6001ms -[2023-11-28T09:02:07Z INFO subsystem_bench::availability] Throughput: 51200 KiB/block -[2023-11-28T09:02:07Z INFO subsystem_bench::availability] Block time: 6001 ms -[2023-11-28T09:02:07Z INFO subsystem_bench::availability] - - Total received from network: 66 MiB - Total sent to network: 58 KiB - Total subsystem CPU usage 4.16s - CPU usage per block 4.16s - Total test environment CPU usage 0.00s - CPU usage per block 0.00s +target/testnet/subsystem-bench polkadot/node/subsystem-bench/examples/availability_write.yaml +[2024-02-19T14:10:32.981Z INFO subsystem_bench] Sequence contains 1 step(s) +[2024-02-19T14:10:32.981Z INFO subsystem-bench::cli] Step 1/1 +[2024-02-19T14:10:32.981Z INFO subsystem-bench::cli] [objective = DataAvailabilityWrite] n_validators = 1000, n_cores = 200, pov_size = 5120 - 5120, connectivity = 75, latency = Some(PeerLatency { mean_latency_ms: 30, std_dev: 2.0 }) +[2024-02-19T14:10:32.982Z INFO subsystem-bench::availability] Generating template candidate index=0 pov_size=5242880 +[2024-02-19T14:10:33.106Z INFO subsystem-bench::availability] Created test environment. +[2024-02-19T14:10:33.106Z INFO subsystem-bench::availability] Pre-generating 600 candidates. +[2024-02-19T14:10:34.096Z INFO subsystem-bench::network] Initializing emulation for a 1000 peer network. +[2024-02-19T14:10:34.096Z INFO subsystem-bench::network] connectivity 75%, latency Some(PeerLatency { mean_latency_ms: 30, std_dev: 2.0 }) +[2024-02-19T14:10:34.098Z INFO subsystem-bench::network] Network created, connected validator count 749 +[2024-02-19T14:10:34.099Z INFO subsystem-bench::availability] Seeding availability store with candidates ... +[2024-02-19T14:10:34.100Z INFO substrate_prometheus_endpoint] 〽️ Prometheus exporter started at 127.0.0.1:9999 +[2024-02-19T14:10:34.387Z INFO subsystem-bench::availability] Done +[2024-02-19T14:10:34.387Z INFO subsystem-bench::availability] Current block #1 +[2024-02-19T14:10:34.389Z INFO subsystem-bench::availability] Waiting for all emulated peers to receive their chunk from us ... +[2024-02-19T14:10:34.625Z INFO subsystem-bench::availability] All chunks received in 237ms +[2024-02-19T14:10:34.626Z INFO polkadot_subsystem_bench::availability] Waiting for 749 bitfields to be received and processed +[2024-02-19T14:10:35.710Z INFO subsystem-bench::availability] All bitfields processed +[2024-02-19T14:10:35.710Z INFO subsystem-bench::availability] All work for block completed in 1322ms +[2024-02-19T14:10:35.710Z INFO subsystem-bench::availability] Current block #2 +[2024-02-19T14:10:35.712Z INFO subsystem-bench::availability] Waiting for all emulated peers to receive their chunk from us ... +[2024-02-19T14:10:35.947Z INFO subsystem-bench::availability] All chunks received in 236ms +[2024-02-19T14:10:35.947Z INFO polkadot_subsystem_bench::availability] Waiting for 749 bitfields to be received and processed +[2024-02-19T14:10:37.038Z INFO subsystem-bench::availability] All bitfields processed +[2024-02-19T14:10:37.038Z INFO subsystem-bench::availability] All work for block completed in 1328ms +[2024-02-19T14:10:37.039Z INFO subsystem-bench::availability] Current block #3 +[2024-02-19T14:10:37.040Z INFO subsystem-bench::availability] Waiting for all emulated peers to receive their chunk from us ... +[2024-02-19T14:10:37.276Z INFO subsystem-bench::availability] All chunks received in 237ms +[2024-02-19T14:10:37.276Z INFO polkadot_subsystem_bench::availability] Waiting for 749 bitfields to be received and processed +[2024-02-19T14:10:38.362Z INFO subsystem-bench::availability] All bitfields processed +[2024-02-19T14:10:38.362Z INFO subsystem-bench::availability] All work for block completed in 1323ms +[2024-02-19T14:10:38.362Z INFO subsystem-bench::availability] All blocks processed in 3974ms +[2024-02-19T14:10:38.362Z INFO subsystem-bench::availability] Avg block time: 1324 ms +[2024-02-19T14:10:38.362Z INFO parachain::availability-store] received `Conclude` signal, exiting +[2024-02-19T14:10:38.362Z INFO parachain::bitfield-distribution] Conclude +[2024-02-19T14:10:38.362Z INFO subsystem-bench::network] Downlink channel closed, network interface task exiting + +polkadot/node/subsystem-bench/examples/availability_write.yaml #1 DataAvailabilityWrite + +Network usage, KiB total per block +Received from peers 12922.000 4307.333 +Sent to peers 47705.000 15901.667 + +CPU usage, seconds total per block +availability-distribution 0.045 0.015 +bitfield-distribution 0.104 0.035 +availability-store 0.304 0.101 +Test environment 3.213 1.071 ``` -`Block time` in the context of `data-availability-read` has a different meaning. It measures the amount of time it + + +`Block time` in the current context has a different meaning. It measures the amount of time it took the subsystem to finish processing all of the messages sent in the context of the current test block. ### Test logs @@ -233,8 +230,9 @@ Since the execution will be very slow, it's recommended not to run it together w benchmark results into account. A report is saved in a file `cachegrind_report.txt`. Example run results: + ``` -$ target/testnet/subsystem-bench --n-cores 10 --cache-misses data-availability-read +$ target/testnet/subsystem-bench --cache-misses cache-misses-data-availability-read.yaml $ cat cachegrind_report.txt I refs: 64,622,081,485 I1 misses: 3,018,168 @@ -275,7 +273,7 @@ happy and negative scenarios (low bandwidth, network errors and low connectivity To faster write a new test objective you need to use some higher level wrappers and logic: `TestEnvironment`, `TestConfiguration`, `TestAuthorities`, `NetworkEmulator`. To create the `TestEnvironment` you will -need to also build an `Overseer`, but that should be easy using the mockups for subsystems in`core::mock`. +need to also build an `Overseer`, but that should be easy using the mockups for subsystems in `mock`. ### Mocking diff --git a/polkadot/node/subsystem-bench/examples/approvals_no_shows.yaml b/polkadot/node/subsystem-bench/examples/approvals_no_shows.yaml index 758c7fbbf11..146da57d44c 100644 --- a/polkadot/node/subsystem-bench/examples/approvals_no_shows.yaml +++ b/polkadot/node/subsystem-bench/examples/approvals_no_shows.yaml @@ -1,14 +1,14 @@ TestConfiguration: # Test 1 - objective: !ApprovalVoting - last_considered_tranche: 89 coalesce_mean: 3.0 coalesce_std_dev: 1.0 + enable_assignments_v2: true + last_considered_tranche: 89 stop_when_approved: true coalesce_tranche_diff: 12 - workdir_prefix: "/tmp/" - enable_assignments_v2: true num_no_shows_per_candidate: 10 + workdir_prefix: "/tmp/" n_validators: 500 n_cores: 100 min_pov_size: 1120 diff --git a/polkadot/node/subsystem-bench/examples/approvals_throughput.yaml b/polkadot/node/subsystem-bench/examples/approvals_throughput.yaml index 9eeeefc53a4..6b17e62c20a 100644 --- a/polkadot/node/subsystem-bench/examples/approvals_throughput.yaml +++ b/polkadot/node/subsystem-bench/examples/approvals_throughput.yaml @@ -7,11 +7,10 @@ TestConfiguration: last_considered_tranche: 89 stop_when_approved: false coalesce_tranche_diff: 12 - workdir_prefix: "/tmp" num_no_shows_per_candidate: 0 + workdir_prefix: "/tmp" n_validators: 500 n_cores: 100 - n_included_candidates: 100 min_pov_size: 1120 max_pov_size: 5120 peer_bandwidth: 524288000000 diff --git a/polkadot/node/subsystem-bench/examples/approvals_throughput_best_case.yaml b/polkadot/node/subsystem-bench/examples/approvals_throughput_best_case.yaml index 370bb31a5c4..e946c28e8ef 100644 --- a/polkadot/node/subsystem-bench/examples/approvals_throughput_best_case.yaml +++ b/polkadot/node/subsystem-bench/examples/approvals_throughput_best_case.yaml @@ -7,8 +7,8 @@ TestConfiguration: last_considered_tranche: 89 stop_when_approved: true coalesce_tranche_diff: 12 - workdir_prefix: "/tmp/" num_no_shows_per_candidate: 0 + workdir_prefix: "/tmp/" n_validators: 500 n_cores: 100 min_pov_size: 1120 diff --git a/polkadot/node/subsystem-bench/examples/approvals_throughput_no_optimisations_enabled.yaml b/polkadot/node/subsystem-bench/examples/approvals_throughput_no_optimisations_enabled.yaml index 30b9ac8dc50..8f4b050e72f 100644 --- a/polkadot/node/subsystem-bench/examples/approvals_throughput_no_optimisations_enabled.yaml +++ b/polkadot/node/subsystem-bench/examples/approvals_throughput_no_optimisations_enabled.yaml @@ -7,8 +7,8 @@ TestConfiguration: last_considered_tranche: 89 stop_when_approved: false coalesce_tranche_diff: 12 - workdir_prefix: "/tmp/" num_no_shows_per_candidate: 0 + workdir_prefix: "/tmp/" n_validators: 500 n_cores: 100 min_pov_size: 1120 diff --git a/polkadot/node/subsystem-bench/src/availability/cli.rs b/polkadot/node/subsystem-bench/src/availability/cli.rs deleted file mode 100644 index 65df8c1552a..00000000000 --- a/polkadot/node/subsystem-bench/src/availability/cli.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -use serde::{Deserialize, Serialize}; - -#[derive(clap::ValueEnum, Clone, Copy, Debug, PartialEq)] -#[value(rename_all = "kebab-case")] -#[non_exhaustive] -pub enum NetworkEmulation { - Ideal, - Healthy, - Degraded, -} - -#[derive(Debug, Clone, Serialize, Deserialize, clap::Parser)] -#[clap(rename_all = "kebab-case")] -#[allow(missing_docs)] -pub struct DataAvailabilityReadOptions { - #[clap(short, long, default_value_t = false)] - /// Turbo boost AD Read by fetching the full availability datafrom backers first. Saves CPU as - /// we don't need to re-construct from chunks. Tipically this is only faster if nodes have - /// enough bandwidth. - pub fetch_from_backers: bool, -} diff --git a/polkadot/node/subsystem-bench/src/subsystem-bench.rs b/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs similarity index 62% rename from polkadot/node/subsystem-bench/src/subsystem-bench.rs rename to polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs index 0803f175474..deb351360d7 100644 --- a/polkadot/node/subsystem-bench/src/subsystem-bench.rs +++ b/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs @@ -14,54 +14,32 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! A tool for running subsystem benchmark tests designed for development and -//! CI regression testing. - -use approval::{bench_approvals, ApprovalsOptions}; -use availability::{ - cli::{DataAvailabilityReadOptions, NetworkEmulation}, - prepare_test, TestState, -}; +//! A tool for running subsystem benchmark tests +//! designed for development and CI regression testing. + use clap::Parser; -use clap_num::number_range; use color_eyre::eyre; use colored::Colorize; -use core::{ - configuration::TestConfiguration, - display::display_configuration, - environment::{TestEnvironment, GENESIS_HASH}, -}; +use polkadot_subsystem_bench::{approval, availability, configuration}; use pyroscope::PyroscopeAgent; use pyroscope_pprofrs::{pprof_backend, PprofConfig}; use serde::{Deserialize, Serialize}; use std::path::Path; -mod approval; -mod availability; -mod core; mod valgrind; -const LOG_TARGET: &str = "subsystem-bench"; - -fn le_100(s: &str) -> Result { - number_range(s, 0, 100) -} - -fn le_5000(s: &str) -> Result { - number_range(s, 0, 5000) -} +const LOG_TARGET: &str = "subsystem-bench::cli"; /// Supported test objectives #[derive(Debug, Clone, Parser, Serialize, Deserialize)] #[command(rename_all = "kebab-case")] pub enum TestObjective { /// Benchmark availability recovery strategies. - DataAvailabilityRead(DataAvailabilityReadOptions), + DataAvailabilityRead(availability::DataAvailabilityReadOptions), /// Benchmark availability and bitfield distribution. DataAvailabilityWrite, /// Benchmark the approval-voting and approval-distribution subsystems. - ApprovalVoting(ApprovalsOptions), - Unimplemented, + ApprovalVoting(approval::ApprovalsOptions), } impl std::fmt::Display for TestObjective { @@ -73,39 +51,37 @@ impl std::fmt::Display for TestObjective { Self::DataAvailabilityRead(_) => "DataAvailabilityRead", Self::DataAvailabilityWrite => "DataAvailabilityWrite", Self::ApprovalVoting(_) => "ApprovalVoting", - Self::Unimplemented => "Unimplemented", } ) } } -#[derive(Debug, Parser)] -#[allow(missing_docs)] -struct BenchCli { - #[arg(long, value_enum, ignore_case = true, default_value_t = NetworkEmulation::Ideal)] - /// The type of network to be emulated - pub network: NetworkEmulation, - - #[clap(short, long)] - /// The bandwidth of emulated remote peers in KiB - pub peer_bandwidth: Option, - - #[clap(short, long)] - /// The bandwidth of our node in KiB - pub bandwidth: Option, - - #[clap(long, value_parser=le_100)] - /// Emulated peer connection ratio [0-100]. - pub connectivity: Option, +/// The test input parameters +#[derive(Clone, Debug, Serialize, Deserialize)] +struct CliTestConfiguration { + /// Test Objective + pub objective: TestObjective, + /// Test Configuration + #[serde(flatten)] + pub test_config: configuration::TestConfiguration, +} - #[clap(long, value_parser=le_5000)] - /// Mean remote peer latency in milliseconds [0-5000]. - pub peer_mean_latency: Option, +#[derive(Serialize, Deserialize)] +pub struct TestSequence { + #[serde(rename(serialize = "TestConfiguration", deserialize = "TestConfiguration"))] + test_configurations: Vec, +} - #[clap(long, value_parser=le_5000)] - /// Remote peer latency standard deviation - pub peer_latency_std_dev: Option, +impl TestSequence { + fn new_from_file(path: &Path) -> std::io::Result { + let string = String::from_utf8(std::fs::read(path)?).expect("File is valid UTF8"); + Ok(serde_yaml::from_str(&string).expect("File is valid test sequence YA")) + } +} +#[derive(Debug, Parser)] +#[allow(missing_docs)] +struct BenchCli { #[clap(long, default_value_t = false)] /// Enable CPU Profiling with Pyroscope pub profile: bool, @@ -122,10 +98,6 @@ struct BenchCli { /// Enable Cache Misses Profiling with Valgrind. Linux only, Valgrind must be in the PATH pub cache_misses: bool, - #[clap(long, default_value_t = false)] - /// Shows the output in YAML format - pub yaml_output: bool, - #[arg(required = true)] /// Path to the test sequence configuration file pub path: String, @@ -148,49 +120,60 @@ impl BenchCli { None }; - let test_sequence = core::configuration::TestSequence::new_from_file(Path::new(&self.path)) + let test_sequence = TestSequence::new_from_file(Path::new(&self.path)) .expect("File exists") - .into_vec(); + .test_configurations; let num_steps = test_sequence.len(); gum::info!("{}", format!("Sequence contains {} step(s)", num_steps).bright_purple()); - for (index, test_config) in test_sequence.into_iter().enumerate() { - let benchmark_name = format!("{} #{} {}", &self.path, index + 1, test_config.objective); - gum::info!(target: LOG_TARGET, "{}", format!("Step {}/{}", index + 1, num_steps).bright_purple(),); - display_configuration(&test_config); - let usage = match test_config.objective { - TestObjective::DataAvailabilityRead(ref _opts) => { - let mut state = TestState::new(&test_config); - let (mut env, _protocol_config) = prepare_test(test_config, &mut state); + for (index, CliTestConfiguration { objective, mut test_config }) in + test_sequence.into_iter().enumerate() + { + let benchmark_name = format!("{} #{} {}", &self.path, index + 1, objective); + gum::info!(target: LOG_TARGET, "{}", format!("Step {}/{}", index + 1, num_steps).bright_purple(),); + gum::info!(target: LOG_TARGET, "[{}] {}", format!("objective = {:?}", objective).green(), test_config); + test_config.generate_pov_sizes(); + + let usage = match objective { + TestObjective::DataAvailabilityRead(opts) => { + let mut state = availability::TestState::new(&test_config); + let (mut env, _protocol_config) = availability::prepare_test( + test_config, + &mut state, + availability::TestDataAvailability::Read(opts), + true, + ); env.runtime().block_on(availability::benchmark_availability_read( &benchmark_name, &mut env, state, )) }, - TestObjective::ApprovalVoting(ref options) => { - let (mut env, state) = - approval::prepare_test(test_config.clone(), options.clone()); - env.runtime().block_on(bench_approvals(&benchmark_name, &mut env, state)) - }, TestObjective::DataAvailabilityWrite => { - let mut state = TestState::new(&test_config); - let (mut env, _protocol_config) = prepare_test(test_config, &mut state); + let mut state = availability::TestState::new(&test_config); + let (mut env, _protocol_config) = availability::prepare_test( + test_config, + &mut state, + availability::TestDataAvailability::Write, + true, + ); env.runtime().block_on(availability::benchmark_availability_write( &benchmark_name, &mut env, state, )) }, - TestObjective::Unimplemented => todo!(), - }; - - let output = if self.yaml_output { - serde_yaml::to_string(&vec![usage])? - } else { - usage.to_string() + TestObjective::ApprovalVoting(ref options) => { + let (mut env, state) = + approval::prepare_test(test_config.clone(), options.clone(), true); + env.runtime().block_on(approval::bench_approvals( + &benchmark_name, + &mut env, + state, + )) + }, }; - println!("{}", output); + println!("{}", usage); } if let Some(agent_running) = agent_running { diff --git a/polkadot/node/subsystem-bench/src/valgrind.rs b/polkadot/node/subsystem-bench/src/cli/valgrind.rs similarity index 100% rename from polkadot/node/subsystem-bench/src/valgrind.rs rename to polkadot/node/subsystem-bench/src/cli/valgrind.rs diff --git a/polkadot/node/subsystem-bench/src/approval/helpers.rs b/polkadot/node/subsystem-bench/src/lib/approval/helpers.rs similarity index 99% rename from polkadot/node/subsystem-bench/src/approval/helpers.rs rename to polkadot/node/subsystem-bench/src/lib/approval/helpers.rs index 623d91848f5..af5ff5aa1fa 100644 --- a/polkadot/node/subsystem-bench/src/approval/helpers.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/helpers.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use crate::core::configuration::TestAuthorities; +use crate::configuration::TestAuthorities; use itertools::Itertools; use polkadot_node_core_approval_voting::time::{Clock, SystemClock, Tick}; use polkadot_node_network_protocol::{ diff --git a/polkadot/node/subsystem-bench/src/approval/message_generator.rs b/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs similarity index 97% rename from polkadot/node/subsystem-bench/src/approval/message_generator.rs rename to polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs index a7103401324..c1b31a509f6 100644 --- a/polkadot/node/subsystem-bench/src/approval/message_generator.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs @@ -18,15 +18,12 @@ use crate::{ approval::{ helpers::{generate_babe_epoch, generate_topology}, test_message::{MessagesBundle, TestMessageInfo}, - ApprovalTestState, BlockTestData, GeneratedState, BUFFER_FOR_GENERATION_MILLIS, LOG_TARGET, - SLOT_DURATION_MILLIS, + ApprovalTestState, ApprovalsOptions, BlockTestData, GeneratedState, + BUFFER_FOR_GENERATION_MILLIS, LOG_TARGET, SLOT_DURATION_MILLIS, }, - core::{ - configuration::{TestAuthorities, TestConfiguration}, - mock::runtime_api::session_info_for_peers, - NODE_UNDER_TEST, - }, - ApprovalsOptions, TestObjective, + configuration::{TestAuthorities, TestConfiguration}, + mock::runtime_api::session_info_for_peers, + NODE_UNDER_TEST, }; use futures::SinkExt; use itertools::Itertools; @@ -132,11 +129,7 @@ impl PeerMessagesGenerator { options: &ApprovalsOptions, ) -> String { let mut fingerprint = options.fingerprint(); - let mut exclude_objective = configuration.clone(); - // The objective contains the full content of `ApprovalOptions`, we don't want to put all of - // that in fingerprint, so execlute it because we add it manually see above. - exclude_objective.objective = TestObjective::Unimplemented; - let configuration_bytes = bincode::serialize(&exclude_objective).unwrap(); + let configuration_bytes = bincode::serialize(&configuration).unwrap(); fingerprint.extend(configuration_bytes); let mut sha1 = sha1::Sha1::new(); sha1.update(fingerprint); diff --git a/polkadot/node/subsystem-bench/src/approval/mock_chain_selection.rs b/polkadot/node/subsystem-bench/src/lib/approval/mock_chain_selection.rs similarity index 100% rename from polkadot/node/subsystem-bench/src/approval/mock_chain_selection.rs rename to polkadot/node/subsystem-bench/src/lib/approval/mock_chain_selection.rs diff --git a/polkadot/node/subsystem-bench/src/approval/mod.rs b/polkadot/node/subsystem-bench/src/lib/approval/mod.rs similarity index 97% rename from polkadot/node/subsystem-bench/src/approval/mod.rs rename to polkadot/node/subsystem-bench/src/lib/approval/mod.rs index f07912de188..450faf06123 100644 --- a/polkadot/node/subsystem-bench/src/approval/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/mod.rs @@ -24,25 +24,21 @@ use crate::{ mock_chain_selection::MockChainSelection, test_message::{MessagesBundle, TestMessageInfo}, }, - core::{ - configuration::TestAuthorities, - environment::{ - BenchmarkUsage, TestEnvironment, TestEnvironmentDependencies, MAX_TIME_OF_FLIGHT, - }, - mock::{ - chain_api::{ChainApiState, MockChainApi}, - dummy_builder, - network_bridge::{MockNetworkBridgeRx, MockNetworkBridgeTx}, - runtime_api::MockRuntimeApi, - AlwaysSupportsParachains, TestSyncOracle, - }, - network::{ - new_network, HandleNetworkMessage, NetworkEmulatorHandle, NetworkInterface, - NetworkInterfaceReceiver, - }, - NODE_UNDER_TEST, + configuration::{TestAuthorities, TestConfiguration}, + dummy_builder, + environment::{TestEnvironment, TestEnvironmentDependencies, MAX_TIME_OF_FLIGHT}, + mock::{ + chain_api::{ChainApiState, MockChainApi}, + network_bridge::{MockNetworkBridgeRx, MockNetworkBridgeTx}, + runtime_api::MockRuntimeApi, + AlwaysSupportsParachains, TestSyncOracle, }, - TestConfiguration, + network::{ + new_network, HandleNetworkMessage, NetworkEmulatorHandle, NetworkInterface, + NetworkInterfaceReceiver, + }, + usage::BenchmarkUsage, + NODE_UNDER_TEST, }; use colored::Colorize; use futures::channel::oneshot; @@ -472,11 +468,9 @@ impl ApprovalTestState { impl HandleNetworkMessage for ApprovalTestState { fn handle( &self, - _message: crate::core::network::NetworkMessage, - _node_sender: &mut futures::channel::mpsc::UnboundedSender< - crate::core::network::NetworkMessage, - >, - ) -> Option { + _message: crate::network::NetworkMessage, + _node_sender: &mut futures::channel::mpsc::UnboundedSender, + ) -> Option { self.total_sent_messages_from_node .as_ref() .fetch_add(1, std::sync::atomic::Ordering::SeqCst); @@ -841,8 +835,14 @@ fn build_overseer( pub fn prepare_test( config: TestConfiguration, options: ApprovalsOptions, + with_prometheus_endpoint: bool, ) -> (TestEnvironment, ApprovalTestState) { - prepare_test_inner(config, TestEnvironmentDependencies::default(), options) + prepare_test_inner( + config, + TestEnvironmentDependencies::default(), + options, + with_prometheus_endpoint, + ) } /// Build the test environment for an Approval benchmark. @@ -850,6 +850,7 @@ fn prepare_test_inner( config: TestConfiguration, dependencies: TestEnvironmentDependencies, options: ApprovalsOptions, + with_prometheus_endpoint: bool, ) -> (TestEnvironment, ApprovalTestState) { gum::info!("Prepare test state"); let state = ApprovalTestState::new(&config, options, &dependencies); @@ -878,6 +879,7 @@ fn prepare_test_inner( overseer, overseer_handle, state.test_authorities.clone(), + with_prometheus_endpoint, ), state, ) diff --git a/polkadot/node/subsystem-bench/src/approval/test_message.rs b/polkadot/node/subsystem-bench/src/lib/approval/test_message.rs similarity index 98% rename from polkadot/node/subsystem-bench/src/approval/test_message.rs rename to polkadot/node/subsystem-bench/src/lib/approval/test_message.rs index 8aaabc3426c..63e383509be 100644 --- a/polkadot/node/subsystem-bench/src/approval/test_message.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/test_message.rs @@ -15,9 +15,8 @@ // along with Polkadot. If not, see . use crate::{ - approval::{BlockTestData, CandidateTestData}, - core::configuration::TestAuthorities, - ApprovalsOptions, + approval::{ApprovalsOptions, BlockTestData, CandidateTestData}, + configuration::TestAuthorities, }; use itertools::Itertools; use parity_scale_codec::{Decode, Encode}; diff --git a/polkadot/node/subsystem-bench/src/availability/av_store_helpers.rs b/polkadot/node/subsystem-bench/src/lib/availability/av_store_helpers.rs similarity index 94% rename from polkadot/node/subsystem-bench/src/availability/av_store_helpers.rs rename to polkadot/node/subsystem-bench/src/lib/availability/av_store_helpers.rs index 261dbd0376c..3300def2235 100644 --- a/polkadot/node/subsystem-bench/src/availability/av_store_helpers.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/av_store_helpers.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use crate::core::{environment::TestEnvironmentDependencies, mock::TestSyncOracle}; +use crate::{environment::TestEnvironmentDependencies, mock::TestSyncOracle}; use polkadot_node_core_av_store::{AvailabilityStoreSubsystem, Config}; use polkadot_node_metrics::metrics::Metrics; use polkadot_node_subsystem_util::database::Database; diff --git a/polkadot/node/subsystem-bench/src/availability/mod.rs b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs similarity index 94% rename from polkadot/node/subsystem-bench/src/availability/mod.rs rename to polkadot/node/subsystem-bench/src/lib/availability/mod.rs index ad9a17ff8f4..f012a5a907e 100644 --- a/polkadot/node/subsystem-bench/src/availability/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs @@ -15,22 +15,18 @@ // along with Polkadot. If not, see . use crate::{ - core::{ - configuration::TestConfiguration, - environment::{BenchmarkUsage, TestEnvironmentDependencies}, - mock::{ - av_store, - av_store::MockAvailabilityStore, - chain_api::{ChainApiState, MockChainApi}, - dummy_builder, - network_bridge::{self, MockNetworkBridgeRx, MockNetworkBridgeTx}, - runtime_api, - runtime_api::MockRuntimeApi, - AlwaysSupportsParachains, - }, - network::new_network, + configuration::TestConfiguration, + dummy_builder, + environment::{TestEnvironment, TestEnvironmentDependencies, GENESIS_HASH}, + mock::{ + av_store::{self, MockAvailabilityStore}, + chain_api::{ChainApiState, MockChainApi}, + network_bridge::{self, MockNetworkBridgeRx, MockNetworkBridgeTx}, + runtime_api::{self, MockRuntimeApi}, + AlwaysSupportsParachains, }, - TestEnvironment, TestObjective, GENESIS_HASH, + network::new_network, + usage::BenchmarkUsage, }; use av_store::NetworkAvailabilityState; use av_store_helpers::new_av_store; @@ -73,14 +69,30 @@ use sc_network::{ PeerId, }; use sc_service::SpawnTaskHandle; +use serde::{Deserialize, Serialize}; use sp_core::H256; use std::{collections::HashMap, iter::Cycle, ops::Sub, sync::Arc, time::Instant}; mod av_store_helpers; -pub(crate) mod cli; const LOG_TARGET: &str = "subsystem-bench::availability"; +#[derive(Debug, Clone, Serialize, Deserialize, clap::Parser)] +#[clap(rename_all = "kebab-case")] +#[allow(missing_docs)] +pub struct DataAvailabilityReadOptions { + #[clap(short, long, default_value_t = false)] + /// Turbo boost AD Read by fetching the full availability datafrom backers first. Saves CPU as + /// we don't need to re-construct from chunks. Tipically this is only faster if nodes have + /// enough bandwidth. + pub fetch_from_backers: bool, +} + +pub enum TestDataAvailability { + Read(DataAvailabilityReadOptions), + Write, +} + fn build_overseer_for_availability_read( spawn_task_handle: SpawnTaskHandle, runtime_api: MockRuntimeApi, @@ -141,14 +153,24 @@ fn build_overseer_for_availability_write( pub fn prepare_test( config: TestConfiguration, state: &mut TestState, + mode: TestDataAvailability, + with_prometheus_endpoint: bool, ) -> (TestEnvironment, Vec) { - prepare_test_inner(config, state, TestEnvironmentDependencies::default()) + prepare_test_inner( + config, + state, + mode, + TestEnvironmentDependencies::default(), + with_prometheus_endpoint, + ) } fn prepare_test_inner( config: TestConfiguration, state: &mut TestState, + mode: TestDataAvailability, dependencies: TestEnvironmentDependencies, + with_prometheus_endpoint: bool, ) -> (TestEnvironment, Vec) { // Generate test authorities. let test_authorities = config.generate_authorities(); @@ -216,8 +238,8 @@ fn prepare_test_inner( let network_bridge_rx = network_bridge::MockNetworkBridgeRx::new(network_receiver, Some(chunk_req_cfg.clone())); - let (overseer, overseer_handle) = match &state.config().objective { - TestObjective::DataAvailabilityRead(options) => { + let (overseer, overseer_handle) = match &mode { + TestDataAvailability::Read(options) => { let use_fast_path = options.fetch_from_backers; let subsystem = if use_fast_path { @@ -247,7 +269,7 @@ fn prepare_test_inner( &dependencies, ) }, - TestObjective::DataAvailabilityWrite => { + TestDataAvailability::Write => { let availability_distribution = AvailabilityDistributionSubsystem::new( test_authorities.keyring.keystore(), IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, @@ -284,9 +306,6 @@ fn prepare_test_inner( &dependencies, ) }, - _ => { - unimplemented!("Invalid test objective") - }, }; ( @@ -297,6 +316,7 @@ fn prepare_test_inner( overseer, overseer_handle, test_authorities, + with_prometheus_endpoint, ), req_cfgs, ) @@ -326,10 +346,6 @@ pub struct TestState { } impl TestState { - fn config(&self) -> &TestConfiguration { - &self.config - } - pub fn next_candidate(&mut self) -> Option { let candidate = self.candidates.next(); let candidate_hash = candidate.as_ref().unwrap().hash(); diff --git a/polkadot/node/subsystem-bench/src/core/configuration.rs b/polkadot/node/subsystem-bench/src/lib/configuration.rs similarity index 83% rename from polkadot/node/subsystem-bench/src/core/configuration.rs rename to polkadot/node/subsystem-bench/src/lib/configuration.rs index 00be2a86b17..c7693308527 100644 --- a/polkadot/node/subsystem-bench/src/core/configuration.rs +++ b/polkadot/node/subsystem-bench/src/lib/configuration.rs @@ -16,7 +16,7 @@ //! Test configuration definition and helpers. -use crate::{core::keyring::Keyring, TestObjective}; +use crate::keyring::Keyring; use itertools::Itertools; use polkadot_primitives::{AssignmentId, AuthorityDiscoveryId, ValidatorId}; use rand::thread_rng; @@ -24,17 +24,7 @@ use rand_distr::{Distribution, Normal, Uniform}; use sc_network::PeerId; use serde::{Deserialize, Serialize}; use sp_consensus_babe::AuthorityId; -use std::{collections::HashMap, path::Path}; - -pub fn random_pov_size(min_pov_size: usize, max_pov_size: usize) -> usize { - random_uniform_sample(min_pov_size, max_pov_size) -} - -fn random_uniform_sample + From>(min_value: T, max_value: T) -> T { - Uniform::from(min_value.into()..=max_value.into()) - .sample(&mut thread_rng()) - .into() -} +use std::collections::HashMap; /// Peer networking latency configuration. #[derive(Clone, Debug, Default, Serialize, Deserialize)] @@ -87,8 +77,6 @@ fn default_no_show_slots() -> usize { /// The test input parameters #[derive(Clone, Debug, Serialize, Deserialize)] pub struct TestConfiguration { - /// The test objective - pub objective: TestObjective, /// Number of validators pub n_validators: usize, /// Number of cores @@ -115,7 +103,7 @@ pub struct TestConfiguration { pub max_pov_size: usize, /// Randomly sampled pov_sizes #[serde(skip)] - pov_sizes: Vec, + pub pov_sizes: Vec, /// The amount of bandiwdth remote validators have. #[serde(default = "default_bandwidth")] pub peer_bandwidth: usize, @@ -133,56 +121,32 @@ pub struct TestConfiguration { pub num_blocks: usize, } -fn generate_pov_sizes(count: usize, min_kib: usize, max_kib: usize) -> Vec { - (0..count).map(|_| random_pov_size(min_kib * 1024, max_kib * 1024)).collect() -} - -#[derive(Serialize, Deserialize)] -pub struct TestSequence { - #[serde(rename(serialize = "TestConfiguration", deserialize = "TestConfiguration"))] - test_configurations: Vec, -} - -impl TestSequence { - pub fn into_vec(self) -> Vec { - self.test_configurations - .into_iter() - .map(|mut config| { - config.pov_sizes = - generate_pov_sizes(config.n_cores, config.min_pov_size, config.max_pov_size); - config - }) - .collect() - } -} - -impl TestSequence { - pub fn new_from_file(path: &Path) -> std::io::Result { - let string = String::from_utf8(std::fs::read(path)?).expect("File is valid UTF8"); - Ok(serde_yaml::from_str(&string).expect("File is valid test sequence YA")) +impl Default for TestConfiguration { + fn default() -> Self { + Self { + n_validators: Default::default(), + n_cores: Default::default(), + needed_approvals: default_needed_approvals(), + zeroth_delay_tranche_width: default_zeroth_delay_tranche_width(), + relay_vrf_modulo_samples: default_relay_vrf_modulo_samples(), + n_delay_tranches: default_n_delay_tranches(), + no_show_slots: default_no_show_slots(), + max_validators_per_core: default_backing_group_size(), + min_pov_size: default_pov_size(), + max_pov_size: default_pov_size(), + pov_sizes: Default::default(), + peer_bandwidth: default_bandwidth(), + bandwidth: default_bandwidth(), + latency: Default::default(), + connectivity: default_connectivity(), + num_blocks: Default::default(), + } } } -/// Helper struct for authority related state. -#[derive(Clone)] -pub struct TestAuthorities { - pub keyring: Keyring, - pub validator_public: Vec, - pub validator_authority_id: Vec, - pub validator_babe_id: Vec, - pub validator_assignment_id: Vec, - pub key_seeds: Vec, - pub peer_ids: Vec, - pub peer_id_to_authority: HashMap, -} - impl TestConfiguration { - #[allow(unused)] - pub fn write_to_disk(&self) { - // Serialize a slice of configurations - let yaml = serde_yaml::to_string(&TestSequence { test_configurations: vec![self.clone()] }) - .unwrap(); - std::fs::write("last_test.yaml", yaml).unwrap(); + pub fn generate_pov_sizes(&mut self) { + self.pov_sizes = generate_pov_sizes(self.n_cores, self.min_pov_size, self.max_pov_size); } pub fn pov_sizes(&self) -> &[usize] { @@ -239,6 +203,33 @@ impl TestConfiguration { } } +fn random_uniform_sample + From>(min_value: T, max_value: T) -> T { + Uniform::from(min_value.into()..=max_value.into()) + .sample(&mut thread_rng()) + .into() +} + +fn random_pov_size(min_pov_size: usize, max_pov_size: usize) -> usize { + random_uniform_sample(min_pov_size, max_pov_size) +} + +fn generate_pov_sizes(count: usize, min_kib: usize, max_kib: usize) -> Vec { + (0..count).map(|_| random_pov_size(min_kib * 1024, max_kib * 1024)).collect() +} + +/// Helper struct for authority related state. +#[derive(Clone)] +pub struct TestAuthorities { + pub keyring: Keyring, + pub validator_public: Vec, + pub validator_authority_id: Vec, + pub validator_babe_id: Vec, + pub validator_assignment_id: Vec, + pub key_seeds: Vec, + pub peer_ids: Vec, + pub peer_id_to_authority: HashMap, +} + /// Sample latency (in milliseconds) from a normal distribution with parameters /// specified in `maybe_peer_latency`. pub fn random_latency(maybe_peer_latency: Option<&PeerLatency>) -> usize { diff --git a/polkadot/node/subsystem-bench/src/core/display.rs b/polkadot/node/subsystem-bench/src/lib/display.rs similarity index 89% rename from polkadot/node/subsystem-bench/src/core/display.rs rename to polkadot/node/subsystem-bench/src/lib/display.rs index 13a349382e2..b153d54a7c3 100644 --- a/polkadot/node/subsystem-bench/src/core/display.rs +++ b/polkadot/node/subsystem-bench/src/lib/display.rs @@ -19,7 +19,7 @@ //! //! Currently histogram buckets are skipped. -use crate::{TestConfiguration, LOG_TARGET}; +use crate::configuration::TestConfiguration; use colored::Colorize; use prometheus::{ proto::{MetricFamily, MetricType}, @@ -27,6 +27,8 @@ use prometheus::{ }; use std::fmt::Display; +const LOG_TARGET: &str = "subsystem-bench::display"; + #[derive(Default, Debug)] pub struct MetricCollection(Vec); @@ -85,6 +87,7 @@ impl Display for MetricCollection { Ok(()) } } + #[derive(Debug, Clone)] pub struct TestMetric { name: String, @@ -184,15 +187,16 @@ pub fn parse_metrics(registry: &Registry) -> MetricCollection { test_metrics.into() } -pub fn display_configuration(test_config: &TestConfiguration) { - gum::info!( - "[{}] {}, {}, {}, {}, {}", - format!("objective = {:?}", test_config.objective).green(), - format!("n_validators = {}", test_config.n_validators).blue(), - format!("n_cores = {}", test_config.n_cores).blue(), - format!("pov_size = {} - {}", test_config.min_pov_size, test_config.max_pov_size) - .bright_black(), - format!("connectivity = {}", test_config.connectivity).bright_black(), - format!("latency = {:?}", test_config.latency).bright_black(), - ); +impl Display for TestConfiguration { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}, {}, {}, {}, {}", + format!("n_validators = {}", self.n_validators).blue(), + format!("n_cores = {}", self.n_cores).blue(), + format!("pov_size = {} - {}", self.min_pov_size, self.max_pov_size).bright_black(), + format!("connectivity = {}", self.connectivity).bright_black(), + format!("latency = {:?}", self.latency).bright_black(), + ) + } } diff --git a/polkadot/node/subsystem-bench/src/core/environment.rs b/polkadot/node/subsystem-bench/src/lib/environment.rs similarity index 88% rename from polkadot/node/subsystem-bench/src/core/environment.rs rename to polkadot/node/subsystem-bench/src/lib/environment.rs index ca4c41cf45f..958ed50d089 100644 --- a/polkadot/node/subsystem-bench/src/core/environment.rs +++ b/polkadot/node/subsystem-bench/src/lib/environment.rs @@ -17,13 +17,11 @@ //! Test environment implementation use crate::{ - core::{ - configuration::TestAuthorities, mock::AlwaysSupportsParachains, - network::NetworkEmulatorHandle, - }, - TestConfiguration, + configuration::{TestAuthorities, TestConfiguration}, + mock::AlwaysSupportsParachains, + network::NetworkEmulatorHandle, + usage::{BenchmarkUsage, ResourceUsage}, }; -use colored::Colorize; use core::time::Duration; use futures::{Future, FutureExt}; use polkadot_node_subsystem::{messages::AllMessages, Overseer, SpawnGlue, TimeoutExt}; @@ -33,7 +31,6 @@ use polkadot_node_subsystem_util::metrics::prometheus::{ }; use polkadot_overseer::{BlockInfo, Handle as OverseerHandle}; use sc_service::{SpawnTaskHandle, TaskManager}; -use serde::{Deserialize, Serialize}; use std::net::{Ipv4Addr, SocketAddr}; use tokio::runtime::Handle; @@ -204,6 +201,7 @@ impl TestEnvironment { overseer: Overseer, AlwaysSupportsParachains>, overseer_handle: OverseerHandle, authorities: TestAuthorities, + with_prometheus_endpoint: bool, ) -> Self { let metrics = TestEnvironmentMetrics::new(&dependencies.registry) .expect("Metrics need to be registered"); @@ -211,19 +209,21 @@ impl TestEnvironment { let spawn_handle = dependencies.task_manager.spawn_handle(); spawn_handle.spawn_blocking("overseer", "overseer", overseer.run().boxed()); - let registry_clone = dependencies.registry.clone(); - dependencies.task_manager.spawn_handle().spawn_blocking( - "prometheus", - "test-environment", - async move { - prometheus_endpoint::init_prometheus( - SocketAddr::new(std::net::IpAddr::V4(Ipv4Addr::LOCALHOST), 9999), - registry_clone, - ) - .await - .unwrap(); - }, - ); + if with_prometheus_endpoint { + let registry_clone = dependencies.registry.clone(); + dependencies.task_manager.spawn_handle().spawn_blocking( + "prometheus", + "test-environment", + async move { + prometheus_endpoint::init_prometheus( + SocketAddr::new(std::net::IpAddr::V4(Ipv4Addr::LOCALHOST), 9999), + registry_clone, + ) + .await + .unwrap(); + }, + ); + } TestEnvironment { runtime_handle: dependencies.runtime.handle().clone(), @@ -411,41 +411,3 @@ impl TestEnvironment { usage } } - -#[derive(Debug, Serialize, Deserialize)] -pub struct BenchmarkUsage { - benchmark_name: String, - network_usage: Vec, - cpu_usage: Vec, -} - -impl std::fmt::Display for BenchmarkUsage { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "\n{}\n\n{}\n{}\n\n{}\n{}\n", - self.benchmark_name.purple(), - format!("{:<32}{:>12}{:>12}", "Network usage, KiB", "total", "per block").blue(), - self.network_usage - .iter() - .map(|v| v.to_string()) - .collect::>() - .join("\n"), - format!("{:<32}{:>12}{:>12}", "CPU usage in seconds", "total", "per block").blue(), - self.cpu_usage.iter().map(|v| v.to_string()).collect::>().join("\n") - ) - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ResourceUsage { - resource_name: String, - total: f64, - per_block: f64, -} - -impl std::fmt::Display for ResourceUsage { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{:<32}{:>12.3}{:>12.3}", self.resource_name.cyan(), self.total, self.per_block) - } -} diff --git a/polkadot/node/subsystem-bench/src/core/keyring.rs b/polkadot/node/subsystem-bench/src/lib/keyring.rs similarity index 100% rename from polkadot/node/subsystem-bench/src/core/keyring.rs rename to polkadot/node/subsystem-bench/src/lib/keyring.rs diff --git a/polkadot/node/subsystem-bench/src/core/mod.rs b/polkadot/node/subsystem-bench/src/lib/lib.rs similarity index 88% rename from polkadot/node/subsystem-bench/src/core/mod.rs rename to polkadot/node/subsystem-bench/src/lib/lib.rs index 764184c5b37..d06f2822a89 100644 --- a/polkadot/node/subsystem-bench/src/core/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/lib.rs @@ -15,11 +15,14 @@ // along with Polkadot. If not, see . // The validator index that represent the node that is under test. -pub(crate) const NODE_UNDER_TEST: u32 = 0; +pub const NODE_UNDER_TEST: u32 = 0; -pub(crate) mod configuration; +pub mod approval; +pub mod availability; +pub mod configuration; pub(crate) mod display; pub(crate) mod environment; pub(crate) mod keyring; pub(crate) mod mock; pub(crate) mod network; +pub mod usage; diff --git a/polkadot/node/subsystem-bench/src/core/mock/av_store.rs b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs similarity index 99% rename from polkadot/node/subsystem-bench/src/core/mock/av_store.rs rename to polkadot/node/subsystem-bench/src/lib/mock/av_store.rs index 0a7725c91e0..41c4fe2cbad 100644 --- a/polkadot/node/subsystem-bench/src/core/mock/av_store.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs @@ -16,7 +16,7 @@ //! A generic av store subsystem mockup suitable to be used in benchmarks. -use crate::core::network::{HandleNetworkMessage, NetworkMessage}; +use crate::network::{HandleNetworkMessage, NetworkMessage}; use futures::{channel::oneshot, FutureExt}; use parity_scale_codec::Encode; use polkadot_node_network_protocol::request_response::{ diff --git a/polkadot/node/subsystem-bench/src/core/mock/chain_api.rs b/polkadot/node/subsystem-bench/src/lib/mock/chain_api.rs similarity index 100% rename from polkadot/node/subsystem-bench/src/core/mock/chain_api.rs rename to polkadot/node/subsystem-bench/src/lib/mock/chain_api.rs diff --git a/polkadot/node/subsystem-bench/src/core/mock/dummy.rs b/polkadot/node/subsystem-bench/src/lib/mock/dummy.rs similarity index 100% rename from polkadot/node/subsystem-bench/src/core/mock/dummy.rs rename to polkadot/node/subsystem-bench/src/lib/mock/dummy.rs diff --git a/polkadot/node/subsystem-bench/src/core/mock/mod.rs b/polkadot/node/subsystem-bench/src/lib/mock/mod.rs similarity index 97% rename from polkadot/node/subsystem-bench/src/core/mock/mod.rs rename to polkadot/node/subsystem-bench/src/lib/mock/mod.rs index 46fdeb196c0..6dda9a47d39 100644 --- a/polkadot/node/subsystem-bench/src/core/mock/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/mod.rs @@ -34,9 +34,10 @@ impl HeadSupportsParachains for AlwaysSupportsParachains { } // An orchestra with dummy subsystems +#[macro_export] macro_rules! dummy_builder { ($spawn_task_handle: ident, $metrics: ident) => {{ - use $crate::core::mock::dummy::*; + use $crate::mock::dummy::*; // Initialize a mock overseer. // All subsystem except approval_voting and approval_distribution are mock subsystems. @@ -72,7 +73,6 @@ macro_rules! dummy_builder { .spawner(SpawnGlue($spawn_task_handle)) }}; } -pub(crate) use dummy_builder; #[derive(Clone)] pub struct TestSyncOracle {} diff --git a/polkadot/node/subsystem-bench/src/core/mock/network_bridge.rs b/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs similarity index 99% rename from polkadot/node/subsystem-bench/src/core/mock/network_bridge.rs rename to polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs index 4682c7ec79a..d598f6447d3 100644 --- a/polkadot/node/subsystem-bench/src/core/mock/network_bridge.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs @@ -17,7 +17,7 @@ //! Mocked `network-bridge` subsystems that uses a `NetworkInterface` to access //! the emulated network. -use crate::core::{ +use crate::{ configuration::TestAuthorities, network::{NetworkEmulatorHandle, NetworkInterfaceReceiver, NetworkMessage, RequestExt}, }; diff --git a/polkadot/node/subsystem-bench/src/core/mock/runtime_api.rs b/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs similarity index 99% rename from polkadot/node/subsystem-bench/src/core/mock/runtime_api.rs rename to polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs index 0dd76efcbaf..53faf562f03 100644 --- a/polkadot/node/subsystem-bench/src/core/mock/runtime_api.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs @@ -16,7 +16,7 @@ //! A generic runtime api subsystem mockup suitable to be used in benchmarks. -use crate::core::configuration::{TestAuthorities, TestConfiguration}; +use crate::configuration::{TestAuthorities, TestConfiguration}; use bitvec::prelude::BitVec; use futures::FutureExt; use itertools::Itertools; diff --git a/polkadot/node/subsystem-bench/src/core/network.rs b/polkadot/node/subsystem-bench/src/lib/network.rs similarity index 99% rename from polkadot/node/subsystem-bench/src/core/network.rs rename to polkadot/node/subsystem-bench/src/lib/network.rs index e9124726d7c..1e09441792d 100644 --- a/polkadot/node/subsystem-bench/src/core/network.rs +++ b/polkadot/node/subsystem-bench/src/lib/network.rs @@ -33,7 +33,7 @@ // | // Subsystems under test -use crate::core::{ +use crate::{ configuration::{random_latency, TestAuthorities, TestConfiguration}, environment::TestEnvironmentDependencies, NODE_UNDER_TEST, diff --git a/polkadot/node/subsystem-bench/src/lib/usage.rs b/polkadot/node/subsystem-bench/src/lib/usage.rs new file mode 100644 index 00000000000..b83ef7d98d9 --- /dev/null +++ b/polkadot/node/subsystem-bench/src/lib/usage.rs @@ -0,0 +1,146 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Test usage implementation + +use colored::Colorize; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +#[derive(Debug, Serialize, Deserialize)] +pub struct BenchmarkUsage { + pub benchmark_name: String, + pub network_usage: Vec, + pub cpu_usage: Vec, +} + +impl std::fmt::Display for BenchmarkUsage { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!( + f, + "\n{}\n\n{}\n{}\n\n{}\n{}\n", + self.benchmark_name.purple(), + format!("{:<32}{:>12}{:>12}", "Network usage, KiB", "total", "per block").blue(), + self.network_usage + .iter() + .map(|v| v.to_string()) + .collect::>() + .join("\n"), + format!("{:<32}{:>12}{:>12}", "CPU usage, seconds", "total", "per block").blue(), + self.cpu_usage.iter().map(|v| v.to_string()).collect::>().join("\n") + ) + } +} + +impl BenchmarkUsage { + pub fn average(usages: &[Self]) -> Self { + let all_network_usages: Vec<&ResourceUsage> = + usages.iter().flat_map(|v| &v.network_usage).collect(); + let all_cpu_usage: Vec<&ResourceUsage> = usages.iter().flat_map(|v| &v.cpu_usage).collect(); + + Self { + benchmark_name: usages.first().map(|v| v.benchmark_name.clone()).unwrap_or_default(), + network_usage: ResourceUsage::average_by_resource_name(&all_network_usages), + cpu_usage: ResourceUsage::average_by_resource_name(&all_cpu_usage), + } + } + + pub fn check_network_usage(&self, checks: &[ResourceUsageCheck]) -> Vec { + check_usage(&self.benchmark_name, &self.network_usage, checks) + } + + pub fn check_cpu_usage(&self, checks: &[ResourceUsageCheck]) -> Vec { + check_usage(&self.benchmark_name, &self.cpu_usage, checks) + } + + pub fn cpu_usage_diff(&self, other: &Self, resource_name: &str) -> Option { + let self_res = self.cpu_usage.iter().find(|v| v.resource_name == resource_name); + let other_res = other.cpu_usage.iter().find(|v| v.resource_name == resource_name); + + match (self_res, other_res) { + (Some(self_res), Some(other_res)) => Some(self_res.diff(other_res)), + _ => None, + } + } +} + +fn check_usage( + benchmark_name: &str, + usage: &[ResourceUsage], + checks: &[ResourceUsageCheck], +) -> Vec { + checks + .iter() + .filter_map(|check| { + check_resource_usage(usage, check) + .map(|message| format!("{}: {}", benchmark_name, message)) + }) + .collect() +} + +fn check_resource_usage( + usage: &[ResourceUsage], + (resource_name, base, precision): &ResourceUsageCheck, +) -> Option { + if let Some(usage) = usage.iter().find(|v| v.resource_name == *resource_name) { + let diff = (base - usage.per_block).abs() / base; + if diff < *precision { + None + } else { + Some(format!( + "The resource `{}` is expected to be equal to {} with a precision {}, but the current value is {}", + resource_name, base, precision, usage.per_block + )) + } + } else { + Some(format!("The resource `{}` is not found", resource_name)) + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ResourceUsage { + pub resource_name: String, + pub total: f64, + pub per_block: f64, +} + +impl std::fmt::Display for ResourceUsage { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{:<32}{:>12.3}{:>12.3}", self.resource_name.cyan(), self.total, self.per_block) + } +} + +impl ResourceUsage { + fn average_by_resource_name(usages: &[&Self]) -> Vec { + let mut by_name: HashMap> = Default::default(); + for usage in usages { + by_name.entry(usage.resource_name.clone()).or_default().push(usage); + } + let mut average = vec![]; + for (resource_name, values) in by_name { + let total = values.iter().map(|v| v.total).sum::() / values.len() as f64; + let per_block = values.iter().map(|v| v.per_block).sum::() / values.len() as f64; + average.push(Self { resource_name, total, per_block }); + } + average + } + + fn diff(&self, other: &Self) -> f64 { + (self.per_block - other.per_block).abs() / self.per_block + } +} + +type ResourceUsageCheck<'a> = (&'a str, f64, f64); -- GitLab From 62b78a16157134a1c38e0081eb60a1c03ac15df3 Mon Sep 17 00:00:00 2001 From: Alin Dima Date: Fri, 1 Mar 2024 20:25:24 +0200 Subject: [PATCH 059/188] provisioner: allow multiple cores assigned to the same para (#3233) https://github.com/paritytech/polkadot-sdk/issues/3130 builds on top of https://github.com/paritytech/polkadot-sdk/pull/3160 Processes the availability cores and builds a record of how many candidates it should request from prospective-parachains and their predecessors. Tries to supply as many candidates as the runtime can back. Note that the runtime changes to back multiple candidates per para are not yet done, but this paves the way for it. The following backing/inclusion policy is assumed: 1. the runtime will never back candidates of the same para which don't form a chain with the already backed candidates. Even if the others are still pending availability. We're optimistic that they won't time out and we don't want to back parachain forks (as the complexity would be huge). 2. if a candidate is timed out of the core before being included, all of its successors occupying a core will be evicted. 3. only the candidates which are made available and form a chain starting from the on-chain para head may be included/enacted and cleared from the cores. In other words, if para head is at A and the cores are occupied by B->C->D, and B and D are made available, only B will be included and its core cleared. C and D will remain on the cores awaiting for C to be made available or timed out. As point (2) above already says, if C is timed out, D will also be dropped. 4. The runtime will deduplicate candidates which form a cycle. For example if the provisioner supplies candidates A->B->A, the runtime will only back A (as the state output will be the same) Note that if a candidate is timed out, we don't guarantee that in the next relay chain block the block author will be able to fill all of the timed out cores of the para. That increases complexity by a lot. Instead, the provisioner will supply N candidates where N is the number of candidates timed out, but doesn't include their successors which will be also deleted by the runtime. This'll be backfilled in the next relay chain block. Adjacent changes: - Also fixes: https://github.com/paritytech/polkadot-sdk/issues/3141 - For non prospective-parachains, don't supply multiple candidates per para (we can't have elastic scaling without prospective parachains enabled). paras_inherent should already sanitise this input but it's more efficient this way. Note: all of these changes are backwards-compatible with the non-elastic-scaling scenario (one core per para). --- Cargo.lock | 3 + .../core/prospective-parachains/Cargo.toml | 1 + .../src/fragment_tree.rs | 570 ++++++++++++++-- .../core/prospective-parachains/src/lib.rs | 19 +- .../core/prospective-parachains/src/tests.rs | 497 +++++--------- polkadot/node/core/provisioner/Cargo.toml | 2 + polkadot/node/core/provisioner/src/error.rs | 12 +- polkadot/node/core/provisioner/src/lib.rs | 234 ++++--- polkadot/node/core/provisioner/src/tests.rs | 629 +++++++++++++++--- polkadot/node/subsystem-types/src/messages.rs | 14 +- prdoc/pr_3233.prdoc | 12 + 11 files changed, 1412 insertions(+), 581 deletions(-) create mode 100644 prdoc/pr_3233.prdoc diff --git a/Cargo.lock b/Cargo.lock index b12006bbcf7..c42ec612e6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12756,6 +12756,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "polkadot-primitives-test-helpers", + "rstest", "sc-keystore", "sp-application-crypto", "sp-core", @@ -12779,6 +12780,8 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "polkadot-primitives-test-helpers", + "rstest", + "schnellru", "sp-application-crypto", "sp-keystore", "thiserror", diff --git a/polkadot/node/core/prospective-parachains/Cargo.toml b/polkadot/node/core/prospective-parachains/Cargo.toml index 5b62d90c1d4..f66a66e859e 100644 --- a/polkadot/node/core/prospective-parachains/Cargo.toml +++ b/polkadot/node/core/prospective-parachains/Cargo.toml @@ -23,6 +23,7 @@ polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } [dev-dependencies] +rstest = "0.18.2" assert_matches = "1" polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } polkadot-node-subsystem-types = { path = "../../subsystem-types" } diff --git a/polkadot/node/core/prospective-parachains/src/fragment_tree.rs b/polkadot/node/core/prospective-parachains/src/fragment_tree.rs index 04ee42a9de0..8061dc82d83 100644 --- a/polkadot/node/core/prospective-parachains/src/fragment_tree.rs +++ b/polkadot/node/core/prospective-parachains/src/fragment_tree.rs @@ -96,6 +96,7 @@ use std::{ use super::LOG_TARGET; use bitvec::prelude::*; +use polkadot_node_subsystem::messages::Ancestors; use polkadot_node_subsystem_util::inclusion_emulator::{ ConstraintModifications, Constraints, Fragment, ProspectiveCandidate, RelayChainBlockInfo, }; @@ -756,45 +757,46 @@ impl FragmentTree { depths.iter_ones().collect() } - /// Select `count` candidates after the given `required_path` which pass + /// Select `count` candidates after the given `ancestors` which pass /// the predicate and have not already been backed on chain. /// - /// Does an exhaustive search into the tree starting after `required_path`. - /// If there are multiple possibilities of size `count`, this will select the first one. - /// If there is no chain of size `count` that matches the criteria, this will return the largest - /// chain it could find with the criteria. - /// If there are no candidates meeting those criteria, returns an empty `Vec`. - /// Cycles are accepted, see module docs for the `Cycles` section. + /// Does an exhaustive search into the tree after traversing the ancestors path. + /// If the ancestors draw out a path that can be traversed in multiple ways, no + /// candidates will be returned. + /// If the ancestors do not draw out a full path (the path contains holes), candidates will be + /// suggested that may fill these holes. + /// If the ancestors don't draw out a valid path, no candidates will be returned. If there are + /// multiple possibilities of the same size, this will select the first one. If there is no + /// chain of size `count` that matches the criteria, this will return the largest chain it could + /// find with the criteria. If there are no candidates meeting those criteria, returns an empty + /// `Vec`. + /// Cycles are accepted, but this code expects that the runtime will deduplicate + /// identical candidates when occupying the cores (when proposing to back A->B->A, only A will + /// be backed on chain). /// - /// The intention of the `required_path` is to allow queries on the basis of + /// The intention of the `ancestors` is to allow queries on the basis of /// one or more candidates which were previously pending availability becoming - /// available and opening up more room on the core. - pub(crate) fn select_children( + /// available or candidates timing out. + pub(crate) fn find_backable_chain( &self, - required_path: &[CandidateHash], + ancestors: Ancestors, count: u32, pred: impl Fn(&CandidateHash) -> bool, ) -> Vec { - let base_node = { - // traverse the required path. - let mut node = NodePointer::Root; - for required_step in required_path { - if let Some(next_node) = self.node_candidate_child(node, &required_step) { - node = next_node; - } else { - return vec![] - }; - } - - node - }; - - // TODO: taking the first best selection might introduce bias - // or become gameable. - // - // For plausibly unique parachains, this shouldn't matter much. - // figure out alternative selection criteria? - self.select_children_inner(base_node, count, count, &pred, &mut vec![]) + if count == 0 { + return vec![] + } + // First, we need to order the ancestors. + // The node returned is the one from which we can start finding new backable candidates. + let Some(base_node) = self.find_ancestor_path(ancestors) else { return vec![] }; + + self.find_backable_chain_inner( + base_node, + count, + count, + &pred, + &mut Vec::with_capacity(count as usize), + ) } // Try finding a candidate chain starting from `base_node` of length `expected_count`. @@ -805,7 +807,7 @@ impl FragmentTree { // Cycles are accepted, but this doesn't allow for infinite execution time, because the maximum // depth we'll reach is `expected_count`. // - // Worst case performance is `O(num_forks ^ expected_count)`. + // Worst case performance is `O(num_forks ^ expected_count)`, the same as populating the tree. // Although an exponential function, this is actually a constant that can only be altered via // sudo/governance, because: // 1. `num_forks` at a given level is at most `max_candidate_depth * max_validators_per_core` @@ -817,7 +819,7 @@ impl FragmentTree { // scaling scenario). For non-elastic-scaling, this is just 1. In practice, this should be a // small number (1-3), capped by the total number of available cores (a constant alterable // only via governance/sudo). - fn select_children_inner( + fn find_backable_chain_inner( &self, base_node: NodePointer, expected_count: u32, @@ -857,7 +859,7 @@ impl FragmentTree { for (child_ptr, child_hash) in children { accumulator.push(child_hash); - let result = self.select_children_inner( + let result = self.find_backable_chain_inner( child_ptr, expected_count, remaining_count - 1, @@ -869,6 +871,9 @@ impl FragmentTree { // Short-circuit the search if we've found the right length. Otherwise, we'll // search for a max. + // Taking the first best selection doesn't introduce bias or become gameable, + // because `find_ancestor_path` uses a `HashSet` to track the ancestors, which + // makes the order in which ancestors are visited non-deterministic. if result.len() == expected_count as usize { return result } else if best_result.len() < result.len() { @@ -879,6 +884,93 @@ impl FragmentTree { best_result } + // Orders the ancestors into a viable path from root to the last one. + // Returns a pointer to the last node in the path. + // We assume that the ancestors form a chain (that the + // av-cores do not back parachain forks), None is returned otherwise. + // If we cannot use all ancestors, stop at the first found hole in the chain. This usually + // translates to a timed out candidate. + fn find_ancestor_path(&self, mut ancestors: Ancestors) -> Option { + // The number of elements in the path we've processed so far. + let mut depth = 0; + let mut last_node = NodePointer::Root; + let mut next_node: Option = Some(NodePointer::Root); + + while let Some(node) = next_node { + if depth > self.scope.max_depth { + return None; + } + + last_node = node; + + next_node = match node { + NodePointer::Root => { + let children = self + .nodes + .iter() + .enumerate() + .take_while(|n| n.1.parent == NodePointer::Root) + .map(|(index, node)| (NodePointer::Storage(index), node.candidate_hash)) + .collect::>(); + + self.find_valid_child(&mut ancestors, children.iter()).ok()? + }, + NodePointer::Storage(ptr) => { + let children = self.nodes.get(ptr).and_then(|n| Some(n.children.iter())); + if let Some(children) = children { + self.find_valid_child(&mut ancestors, children).ok()? + } else { + None + } + }, + }; + + depth += 1; + } + + Some(last_node) + } + + // Find a node from the given iterator which is present in the ancestors + // collection. If there are multiple such nodes, return an error and log a warning. We don't + // accept forks in a parachain to be backed. The supplied ancestors should all form a chain. + // If there is no such node, return None. + fn find_valid_child<'a>( + &self, + ancestors: &'a mut Ancestors, + nodes: impl Iterator + 'a, + ) -> Result, ()> { + let mut possible_children = + nodes.filter_map(|(node_ptr, hash)| match ancestors.remove(&hash) { + true => Some(node_ptr), + false => None, + }); + + // We don't accept forks in a parachain to be backed. The supplied ancestors + // should all form a chain. + let next = possible_children.next(); + if let Some(second_child) = possible_children.next() { + if let (Some(NodePointer::Storage(first_child)), NodePointer::Storage(second_child)) = + (next, second_child) + { + gum::error!( + target: LOG_TARGET, + para_id = ?self.scope.para, + relay_parent = ?self.scope.relay_parent, + "Trying to find new backable candidates for a parachain for which we've backed a fork.\ + This is a bug and the runtime should not have allowed it.\n\ + Backed candidates with the same parent: {}, {}", + self.nodes[*first_child].candidate_hash, + self.nodes[*second_child].candidate_hash, + ); + } + + Err(()) + } else { + Ok(next.copied()) + } + } + fn populate_from_bases(&mut self, storage: &CandidateStorage, initial_bases: Vec) { // Populate the tree breadth-first. let mut last_sweep_start = None; @@ -1061,8 +1153,18 @@ mod tests { use polkadot_node_subsystem_util::inclusion_emulator::InboundHrmpLimitations; use polkadot_primitives::{BlockNumber, CandidateCommitments, CandidateDescriptor, HeadData}; use polkadot_primitives_test_helpers as test_helpers; + use rstest::rstest; use std::iter; + impl NodePointer { + fn unwrap_idx(self) -> usize { + match self { + NodePointer::Root => panic!("Unexpected root"), + NodePointer::Storage(index) => index, + } + } + } + fn make_constraints( min_relay_parent_number: BlockNumber, valid_watermarks: Vec, @@ -1546,6 +1648,373 @@ mod tests { assert_eq!(tree.nodes[1].parent, NodePointer::Storage(0)); } + #[test] + fn test_find_ancestor_path_and_find_backable_chain_empty_tree() { + let para_id = ParaId::from(5u32); + let relay_parent = Hash::repeat_byte(1); + let required_parent: HeadData = vec![0xff].into(); + let max_depth = 10; + + // Empty tree + let storage = CandidateStorage::new(); + let base_constraints = make_constraints(0, vec![0], required_parent.clone()); + + let relay_parent_info = + RelayChainBlockInfo { number: 0, hash: relay_parent, storage_root: Hash::zero() }; + + let scope = Scope::with_ancestors( + para_id, + relay_parent_info, + base_constraints, + vec![], + max_depth, + vec![], + ) + .unwrap(); + let tree = FragmentTree::populate(scope, &storage); + assert_eq!(tree.candidates().collect::>().len(), 0); + assert_eq!(tree.nodes.len(), 0); + + assert_eq!(tree.find_ancestor_path(Ancestors::new()).unwrap(), NodePointer::Root); + assert_eq!(tree.find_backable_chain(Ancestors::new(), 2, |_| true), vec![]); + // Invalid candidate. + let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect(); + assert_eq!(tree.find_ancestor_path(ancestors.clone()), Some(NodePointer::Root)); + assert_eq!(tree.find_backable_chain(ancestors, 2, |_| true), vec![]); + } + + #[rstest] + #[case(true, 13)] + #[case(false, 8)] + // The tree with no cycles looks like: + // Make a tree that looks like this (note that there's no cycle): + // +-(root)-+ + // | | + // +----0---+ 7 + // | | + // 1----+ 5 + // | | + // | | + // 2 6 + // | + // 3 + // | + // 4 + // + // The tree with cycles is the same as the first but has a cycle from 4 back to the state + // produced by 0 (It's bounded by the max_depth + 1). + // +-(root)-+ + // | | + // +----0---+ 7 + // | | + // 1----+ 5 + // | | + // | | + // 2 6 + // | + // 3 + // | + // 4---+ + // | | + // 1 5 + // | + // 2 + // | + // 3 + fn test_find_ancestor_path_and_find_backable_chain( + #[case] has_cycle: bool, + #[case] expected_node_count: usize, + ) { + let para_id = ParaId::from(5u32); + let relay_parent = Hash::repeat_byte(1); + let required_parent: HeadData = vec![0xff].into(); + let max_depth = 7; + let relay_parent_number = 0; + let relay_parent_storage_root = Hash::repeat_byte(69); + + let mut candidates = vec![]; + + // Candidate 0 + candidates.push(make_committed_candidate( + para_id, + relay_parent, + 0, + required_parent.clone(), + vec![0].into(), + 0, + )); + // Candidate 1 + candidates.push(make_committed_candidate( + para_id, + relay_parent, + 0, + vec![0].into(), + vec![1].into(), + 0, + )); + // Candidate 2 + candidates.push(make_committed_candidate( + para_id, + relay_parent, + 0, + vec![1].into(), + vec![2].into(), + 0, + )); + // Candidate 3 + candidates.push(make_committed_candidate( + para_id, + relay_parent, + 0, + vec![2].into(), + vec![3].into(), + 0, + )); + // Candidate 4 + candidates.push(make_committed_candidate( + para_id, + relay_parent, + 0, + vec![3].into(), + vec![4].into(), + 0, + )); + // Candidate 5 + candidates.push(make_committed_candidate( + para_id, + relay_parent, + 0, + vec![0].into(), + vec![5].into(), + 0, + )); + // Candidate 6 + candidates.push(make_committed_candidate( + para_id, + relay_parent, + 0, + vec![1].into(), + vec![6].into(), + 0, + )); + // Candidate 7 + candidates.push(make_committed_candidate( + para_id, + relay_parent, + 0, + required_parent.clone(), + vec![7].into(), + 0, + )); + + if has_cycle { + candidates[4] = make_committed_candidate( + para_id, + relay_parent, + 0, + vec![3].into(), + vec![0].into(), // put the cycle here back to the output state of 0. + 0, + ); + } + + let base_constraints = make_constraints(0, vec![0], required_parent.clone()); + let mut storage = CandidateStorage::new(); + + let relay_parent_info = RelayChainBlockInfo { + number: relay_parent_number, + hash: relay_parent, + storage_root: relay_parent_storage_root, + }; + + for (pvd, candidate) in candidates.iter() { + storage.add_candidate(candidate.clone(), pvd.clone()).unwrap(); + } + let candidates = + candidates.into_iter().map(|(_pvd, candidate)| candidate).collect::>(); + let scope = Scope::with_ancestors( + para_id, + relay_parent_info, + base_constraints, + vec![], + max_depth, + vec![], + ) + .unwrap(); + let tree = FragmentTree::populate(scope, &storage); + + assert_eq!(tree.candidates().collect::>().len(), candidates.len()); + assert_eq!(tree.nodes.len(), expected_node_count); + + // Do some common tests on both trees. + { + // No ancestors supplied. + assert_eq!(tree.find_ancestor_path(Ancestors::new()).unwrap(), NodePointer::Root); + assert_eq!( + tree.find_backable_chain(Ancestors::new(), 4, |_| true), + [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + // Ancestor which is not part of the tree. Will be ignored. + let ancestors: Ancestors = [CandidateHash::default()].into_iter().collect(); + assert_eq!(tree.find_ancestor_path(ancestors.clone()).unwrap(), NodePointer::Root); + assert_eq!( + tree.find_backable_chain(ancestors, 4, |_| true), + [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + // A chain fork. + let ancestors: Ancestors = + [(candidates[0].hash()), (candidates[7].hash())].into_iter().collect(); + assert_eq!(tree.find_ancestor_path(ancestors.clone()), None); + assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]); + + // Ancestors which are part of the tree but don't form a path. Will be ignored. + let ancestors: Ancestors = + [candidates[1].hash(), candidates[2].hash()].into_iter().collect(); + assert_eq!(tree.find_ancestor_path(ancestors.clone()).unwrap(), NodePointer::Root); + assert_eq!( + tree.find_backable_chain(ancestors, 4, |_| true), + [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + + // Valid ancestors. + let ancestors: Ancestors = [candidates[7].hash()].into_iter().collect(); + let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); + let candidate = &tree.nodes[res.unwrap_idx()]; + assert_eq!(candidate.candidate_hash, candidates[7].hash()); + assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]); + + let ancestors: Ancestors = + [candidates[2].hash(), candidates[0].hash(), candidates[1].hash()] + .into_iter() + .collect(); + let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); + let candidate = &tree.nodes[res.unwrap_idx()]; + assert_eq!(candidate.candidate_hash, candidates[2].hash()); + assert_eq!( + tree.find_backable_chain(ancestors.clone(), 2, |_| true), + [3, 4].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + + // Valid ancestors with candidates which have been omitted due to timeouts + let ancestors: Ancestors = + [candidates[0].hash(), candidates[2].hash()].into_iter().collect(); + let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); + let candidate = &tree.nodes[res.unwrap_idx()]; + assert_eq!(candidate.candidate_hash, candidates[0].hash()); + assert_eq!( + tree.find_backable_chain(ancestors, 3, |_| true), + [1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + + let ancestors: Ancestors = + [candidates[0].hash(), candidates[1].hash(), candidates[3].hash()] + .into_iter() + .collect(); + let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); + let candidate = &tree.nodes[res.unwrap_idx()]; + assert_eq!(candidate.candidate_hash, candidates[1].hash()); + if has_cycle { + assert_eq!( + tree.find_backable_chain(ancestors, 2, |_| true), + [2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + } else { + assert_eq!( + tree.find_backable_chain(ancestors, 4, |_| true), + [2, 3, 4].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + } + + let ancestors: Ancestors = + [candidates[1].hash(), candidates[2].hash()].into_iter().collect(); + let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); + assert_eq!(res, NodePointer::Root); + assert_eq!( + tree.find_backable_chain(ancestors, 4, |_| true), + [0, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + + // Requested count is 0. + assert_eq!(tree.find_backable_chain(Ancestors::new(), 0, |_| true), vec![]); + + let ancestors: Ancestors = + [candidates[2].hash(), candidates[0].hash(), candidates[1].hash()] + .into_iter() + .collect(); + assert_eq!(tree.find_backable_chain(ancestors, 0, |_| true), vec![]); + + let ancestors: Ancestors = + [candidates[2].hash(), candidates[0].hash()].into_iter().collect(); + assert_eq!(tree.find_backable_chain(ancestors, 0, |_| true), vec![]); + } + + // Now do some tests only on the tree with cycles + if has_cycle { + // Exceeds the maximum tree depth. 0-1-2-3-4-1-2-3-4, when the tree stops at + // 0-1-2-3-4-1-2-3. + let ancestors: Ancestors = [ + candidates[0].hash(), + candidates[1].hash(), + candidates[2].hash(), + candidates[3].hash(), + candidates[4].hash(), + ] + .into_iter() + .collect(); + let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); + let candidate = &tree.nodes[res.unwrap_idx()]; + assert_eq!(candidate.candidate_hash, candidates[4].hash()); + assert_eq!( + tree.find_backable_chain(ancestors, 4, |_| true), + [1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + + // 0-1-2. + let ancestors: Ancestors = + [candidates[0].hash(), candidates[1].hash(), candidates[2].hash()] + .into_iter() + .collect(); + let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); + let candidate = &tree.nodes[res.unwrap_idx()]; + assert_eq!(candidate.candidate_hash, candidates[2].hash()); + assert_eq!( + tree.find_backable_chain(ancestors.clone(), 1, |_| true), + [3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + assert_eq!( + tree.find_backable_chain(ancestors, 5, |_| true), + [3, 4, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>() + ); + + // 0-1 + let ancestors: Ancestors = + [candidates[0].hash(), candidates[1].hash()].into_iter().collect(); + let res = tree.find_ancestor_path(ancestors.clone()).unwrap(); + let candidate = &tree.nodes[res.unwrap_idx()]; + assert_eq!(candidate.candidate_hash, candidates[1].hash()); + assert_eq!( + tree.find_backable_chain(ancestors, 6, |_| true), + [2, 3, 4, 1, 2, 3].into_iter().map(|i| candidates[i].hash()).collect::>(), + ); + + // For 0-1-2-3-4-5, there's more than 1 way of finding this path in + // the tree. `None` should be returned. The runtime should not have accepted this. + let ancestors: Ancestors = [ + candidates[0].hash(), + candidates[1].hash(), + candidates[2].hash(), + candidates[3].hash(), + candidates[4].hash(), + candidates[5].hash(), + ] + .into_iter() + .collect(); + let res = tree.find_ancestor_path(ancestors.clone()); + assert_eq!(res, None); + assert_eq!(tree.find_backable_chain(ancestors, 1, |_| true), vec![]); + } + } + #[test] fn graceful_cycle_of_0() { let mut storage = CandidateStorage::new(); @@ -1602,13 +2071,17 @@ mod tests { for count in 1..10 { assert_eq!( - tree.select_children(&[], count, |_| true), + tree.find_backable_chain(Ancestors::new(), count, |_| true), iter::repeat(candidate_a_hash) .take(std::cmp::min(count as usize, max_depth + 1)) .collect::>() ); assert_eq!( - tree.select_children(&[candidate_a_hash], count - 1, |_| true), + tree.find_backable_chain( + [candidate_a_hash].into_iter().collect(), + count - 1, + |_| true + ), iter::repeat(candidate_a_hash) .take(std::cmp::min(count as usize - 1, max_depth)) .collect::>() @@ -1682,22 +2155,22 @@ mod tests { assert_eq!(tree.nodes[3].candidate_hash, candidate_b_hash); assert_eq!(tree.nodes[4].candidate_hash, candidate_a_hash); - assert_eq!(tree.select_children(&[], 1, |_| true), vec![candidate_a_hash],); + assert_eq!(tree.find_backable_chain(Ancestors::new(), 1, |_| true), vec![candidate_a_hash],); assert_eq!( - tree.select_children(&[], 2, |_| true), + tree.find_backable_chain(Ancestors::new(), 2, |_| true), vec![candidate_a_hash, candidate_b_hash], ); assert_eq!( - tree.select_children(&[], 3, |_| true), + tree.find_backable_chain(Ancestors::new(), 3, |_| true), vec![candidate_a_hash, candidate_b_hash, candidate_a_hash], ); assert_eq!( - tree.select_children(&[candidate_a_hash], 2, |_| true), + tree.find_backable_chain([candidate_a_hash].into_iter().collect(), 2, |_| true), vec![candidate_b_hash, candidate_a_hash], ); assert_eq!( - tree.select_children(&[], 6, |_| true), + tree.find_backable_chain(Ancestors::new(), 6, |_| true), vec![ candidate_a_hash, candidate_b_hash, @@ -1706,10 +2179,17 @@ mod tests { candidate_a_hash ], ); - assert_eq!( - tree.select_children(&[candidate_a_hash, candidate_b_hash], 6, |_| true), - vec![candidate_a_hash, candidate_b_hash, candidate_a_hash,], - ); + + for count in 3..7 { + assert_eq!( + tree.find_backable_chain( + [candidate_a_hash, candidate_b_hash].into_iter().collect(), + count, + |_| true + ), + vec![candidate_a_hash, candidate_b_hash, candidate_a_hash], + ); + } } #[test] diff --git a/polkadot/node/core/prospective-parachains/src/lib.rs b/polkadot/node/core/prospective-parachains/src/lib.rs index 5937a1c1fb9..2b14e09b4fb 100644 --- a/polkadot/node/core/prospective-parachains/src/lib.rs +++ b/polkadot/node/core/prospective-parachains/src/lib.rs @@ -35,7 +35,7 @@ use futures::{channel::oneshot, prelude::*}; use polkadot_node_subsystem::{ messages::{ - ChainApiMessage, FragmentTreeMembership, HypotheticalCandidate, + Ancestors, ChainApiMessage, FragmentTreeMembership, HypotheticalCandidate, HypotheticalFrontierRequest, IntroduceCandidateRequest, ProspectiveParachainsMessage, ProspectiveValidationDataRequest, RuntimeApiMessage, RuntimeApiRequest, }, @@ -150,16 +150,9 @@ async fn run_iteration( relay_parent, para, count, - required_path, + ancestors, tx, - ) => answer_get_backable_candidates( - &view, - relay_parent, - para, - count, - required_path, - tx, - ), + ) => answer_get_backable_candidates(&view, relay_parent, para, count, ancestors, tx), ProspectiveParachainsMessage::GetHypotheticalFrontier(request, tx) => answer_hypothetical_frontier_request(&view, request, tx), ProspectiveParachainsMessage::GetTreeMembership(para, candidate, tx) => @@ -565,7 +558,7 @@ fn answer_get_backable_candidates( relay_parent: Hash, para: ParaId, count: u32, - required_path: Vec, + ancestors: Ancestors, tx: oneshot::Sender>, ) { let data = match view.active_leaves.get(&relay_parent) { @@ -614,7 +607,7 @@ fn answer_get_backable_candidates( }; let backable_candidates: Vec<_> = tree - .select_children(&required_path, count, |candidate| storage.is_backed(candidate)) + .find_backable_chain(ancestors.clone(), count, |candidate| storage.is_backed(candidate)) .into_iter() .filter_map(|child_hash| { storage.relay_parent_by_candidate_hash(&child_hash).map_or_else( @@ -635,7 +628,7 @@ fn answer_get_backable_candidates( if backable_candidates.is_empty() { gum::trace!( target: LOG_TARGET, - ?required_path, + ?ancestors, para_id = ?para, %relay_parent, "Could not find any backable candidate", diff --git a/polkadot/node/core/prospective-parachains/src/tests.rs b/polkadot/node/core/prospective-parachains/src/tests.rs index 732736b101d..0beddbf1416 100644 --- a/polkadot/node/core/prospective-parachains/src/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/tests.rs @@ -407,7 +407,7 @@ async fn get_backable_candidates( virtual_overseer: &mut VirtualOverseer, leaf: &TestLeaf, para_id: ParaId, - required_path: Vec, + ancestors: Ancestors, count: u32, expected_result: Vec<(CandidateHash, Hash)>, ) { @@ -415,11 +415,7 @@ async fn get_backable_candidates( virtual_overseer .send(overseer::FromOrchestra::Communication { msg: ProspectiveParachainsMessage::GetBackableCandidates( - leaf.hash, - para_id, - count, - required_path, - tx, + leaf.hash, para_id, count, ancestors, tx, ), }) .await; @@ -903,7 +899,7 @@ fn check_backable_query_single_candidate() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a], + vec![candidate_hash_a].into_iter().collect(), 1, vec![], ) @@ -912,12 +908,20 @@ fn check_backable_query_single_candidate() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a], + vec![candidate_hash_a].into_iter().collect(), + 0, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + Ancestors::new(), 0, vec![], ) .await; - get_backable_candidates(&mut virtual_overseer, &leaf_a, 1.into(), vec![], 0, vec![]).await; // Second candidates. second_candidate(&mut virtual_overseer, candidate_a.clone()).await; @@ -928,7 +932,7 @@ fn check_backable_query_single_candidate() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a], + vec![candidate_hash_a].into_iter().collect(), 1, vec![], ) @@ -939,12 +943,20 @@ fn check_backable_query_single_candidate() { back_candidate(&mut virtual_overseer, &candidate_b, candidate_hash_b).await; // Should not get any backable candidates for the other para. - get_backable_candidates(&mut virtual_overseer, &leaf_a, 2.into(), vec![], 1, vec![]).await; get_backable_candidates( &mut virtual_overseer, &leaf_a, 2.into(), - vec![candidate_hash_a], + Ancestors::new(), + 1, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + vec![candidate_hash_a].into_iter().collect(), 1, vec![], ) @@ -955,7 +967,7 @@ fn check_backable_query_single_candidate() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![], + Ancestors::new(), 1, vec![(candidate_hash_a, leaf_a.hash)], ) @@ -964,20 +976,20 @@ fn check_backable_query_single_candidate() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a], + vec![candidate_hash_a].into_iter().collect(), 1, vec![(candidate_hash_b, leaf_a.hash)], ) .await; - // Should not get anything at the wrong path. + // Wrong path get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_b], + vec![candidate_hash_b].into_iter().collect(), 1, - vec![], + vec![(candidate_hash_a, leaf_a.hash)], ) .await; @@ -1075,15 +1087,29 @@ fn check_backable_query_multiple_candidates() { make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_i, 10); // Should not get any backable candidates for the other para. - get_backable_candidates(&mut virtual_overseer, &leaf_a, 2.into(), vec![], 1, vec![]) - .await; - get_backable_candidates(&mut virtual_overseer, &leaf_a, 2.into(), vec![], 5, vec![]) - .await; get_backable_candidates( &mut virtual_overseer, &leaf_a, 2.into(), - vec![candidate_hash_a], + Ancestors::new(), + 1, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + Ancestors::new(), + 5, + vec![], + ) + .await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 2.into(), + vec![candidate_hash_a].into_iter().collect(), 1, vec![], ) @@ -1097,7 +1123,7 @@ fn check_backable_query_multiple_candidates() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![], + Ancestors::new(), 1, vec![(candidate_hash_a, leaf_a.hash)], ) @@ -1106,7 +1132,7 @@ fn check_backable_query_multiple_candidates() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![], + Ancestors::new(), 4, vec![ (candidate_hash_a, leaf_a.hash), @@ -1124,7 +1150,7 @@ fn check_backable_query_multiple_candidates() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a], + vec![candidate_hash_a].into_iter().collect(), 1, vec![(candidate_hash_b, leaf_a.hash)], ) @@ -1133,16 +1159,7 @@ fn check_backable_query_multiple_candidates() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a], - 2, - vec![(candidate_hash_b, leaf_a.hash), (candidate_hash_d, leaf_a.hash)], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a], + vec![candidate_hash_a].into_iter().collect(), 3, vec![ (candidate_hash_b, leaf_a.hash), @@ -1159,7 +1176,7 @@ fn check_backable_query_multiple_candidates() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a], + vec![candidate_hash_a].into_iter().collect(), count, vec![ (candidate_hash_c, leaf_a.hash), @@ -1172,26 +1189,30 @@ fn check_backable_query_multiple_candidates() { } } - // required path of 2 + // required path of 2 and higher { get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a, candidate_hash_b], + vec![candidate_hash_a, candidate_hash_i, candidate_hash_h, candidate_hash_c] + .into_iter() + .collect(), 1, - vec![(candidate_hash_d, leaf_a.hash)], + vec![(candidate_hash_j, leaf_a.hash)], ) .await; + get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a, candidate_hash_c], + vec![candidate_hash_a, candidate_hash_b].into_iter().collect(), 1, - vec![(candidate_hash_h, leaf_a.hash)], + vec![(candidate_hash_d, leaf_a.hash)], ) .await; + // If the requested count exceeds the largest chain, return the longest // chain we can get. for count in 4..10 { @@ -1199,7 +1220,7 @@ fn check_backable_query_multiple_candidates() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a, candidate_hash_c], + vec![candidate_hash_a, candidate_hash_c].into_iter().collect(), count, vec![ (candidate_hash_h, leaf_a.hash), @@ -1213,317 +1234,127 @@ fn check_backable_query_multiple_candidates() { // No more candidates in any chain. { - let required_paths = vec![ - vec![candidate_hash_a, candidate_hash_b, candidate_hash_e], - vec![ - candidate_hash_a, - candidate_hash_c, - candidate_hash_h, - candidate_hash_i, - candidate_hash_j, - ], - ]; - for path in required_paths { - for count in 1..4 { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - path.clone(), - count, - vec![], - ) - .await; - } + for count in 1..4 { + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_a, candidate_hash_b, candidate_hash_e] + .into_iter() + .collect(), + count, + vec![], + ) + .await; + + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![ + candidate_hash_a, + candidate_hash_c, + candidate_hash_h, + candidate_hash_i, + candidate_hash_j, + ] + .into_iter() + .collect(), + count, + vec![], + ) + .await; } } - // Should not get anything at the wrong path. + // Wrong paths. get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_b], + vec![candidate_hash_b].into_iter().collect(), 1, - vec![], + vec![(candidate_hash_a, leaf_a.hash)], ) .await; get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_b, candidate_hash_a], + vec![candidate_hash_b, candidate_hash_f].into_iter().collect(), 3, - vec![], + vec![ + (candidate_hash_a, leaf_a.hash), + (candidate_hash_b, leaf_a.hash), + (candidate_hash_d, leaf_a.hash), + ], ) .await; get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a, candidate_hash_b, candidate_hash_c], - 3, - vec![], + vec![candidate_hash_a, candidate_hash_h].into_iter().collect(), + 4, + vec![ + (candidate_hash_c, leaf_a.hash), + (candidate_hash_h, leaf_a.hash), + (candidate_hash_i, leaf_a.hash), + (candidate_hash_j, leaf_a.hash), + ], ) .await; - - virtual_overseer - }); - - assert_eq!(view.active_leaves.len(), 1); - assert_eq!(view.candidate_storage.len(), 2); - // 10 candidates and 7 parents on para 1. - assert_eq!(view.candidate_storage.get(&1.into()).unwrap().len(), (7, 10)); - assert_eq!(view.candidate_storage.get(&2.into()).unwrap().len(), (0, 0)); - } - - // A tree with multiple roots. - // Parachain 1 looks like this: - // (imaginary root) - // | | - // +----B---+ A - // | | | | - // | | | C - // D E F | - // | H - // G | - // I - // | - // J - { - let test_state = TestState::default(); - let view = test_harness(|mut virtual_overseer| async move { - // Leaf A - let leaf_a = TestLeaf { - number: 100, - hash: Hash::from_low_u64_be(130), - para_data: vec![ - (1.into(), PerParaData::new(97, HeadData(vec![1, 2, 3]))), - (2.into(), PerParaData::new(100, HeadData(vec![2, 3, 4]))), - ], - }; - - // Activate leaves. - activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; - - // Candidate B - let (candidate_b, pvd_b) = make_candidate( - leaf_a.hash, - leaf_a.number, + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, 1.into(), - HeadData(vec![1, 2, 3]), - HeadData(vec![2]), - test_state.validation_code_hash, - ); - let candidate_hash_b = candidate_b.hash(); - introduce_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; - second_candidate(&mut virtual_overseer, candidate_b.clone()).await; - back_candidate(&mut virtual_overseer, &candidate_b, candidate_hash_b).await; + vec![candidate_hash_e, candidate_hash_h].into_iter().collect(), + 2, + vec![(candidate_hash_a, leaf_a.hash), (candidate_hash_b, leaf_a.hash)], + ) + .await; - // Candidate A - let (candidate_a, pvd_a) = make_candidate( - leaf_a.hash, - leaf_a.number, + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, 1.into(), - HeadData(vec![1, 2, 3]), - HeadData(vec![1]), - test_state.validation_code_hash, - ); - let candidate_hash_a = candidate_a.hash(); - introduce_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; - second_candidate(&mut virtual_overseer, candidate_a.clone()).await; - back_candidate(&mut virtual_overseer, &candidate_a, candidate_hash_a).await; - - let (candidate_c, candidate_hash_c) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_a, 3); - let (_candidate_d, candidate_hash_d) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_b, 4); - let (_candidate_e, candidate_hash_e) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_b, 5); - let (candidate_f, candidate_hash_f) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_b, 6); - let (_candidate_g, candidate_hash_g) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_f, 7); - let (candidate_h, candidate_hash_h) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_c, 8); - let (candidate_i, candidate_hash_i) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_h, 9); - let (_candidate_j, candidate_hash_j) = - make_and_back_candidate!(test_state, virtual_overseer, leaf_a, &candidate_i, 10); + vec![candidate_hash_a, candidate_hash_c, candidate_hash_d].into_iter().collect(), + 2, + vec![(candidate_hash_h, leaf_a.hash), (candidate_hash_i, leaf_a.hash)], + ) + .await; - // Should not get any backable candidates for the other para. - get_backable_candidates(&mut virtual_overseer, &leaf_a, 2.into(), vec![], 1, vec![]) - .await; - get_backable_candidates(&mut virtual_overseer, &leaf_a, 2.into(), vec![], 5, vec![]) - .await; + // Parachain fork. get_backable_candidates( &mut virtual_overseer, &leaf_a, - 2.into(), - vec![candidate_hash_a], + 1.into(), + vec![candidate_hash_a, candidate_hash_b, candidate_hash_c].into_iter().collect(), 1, vec![], ) .await; - // Test various scenarios with various counts. - - // empty required_path - { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![], - 1, - vec![(candidate_hash_b, leaf_a.hash)], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![], - 2, - vec![(candidate_hash_b, leaf_a.hash), (candidate_hash_d, leaf_a.hash)], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![], - 4, - vec![ - (candidate_hash_a, leaf_a.hash), - (candidate_hash_c, leaf_a.hash), - (candidate_hash_h, leaf_a.hash), - (candidate_hash_i, leaf_a.hash), - ], - ) - .await; - } - - // required path of 1 - { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a], - 1, - vec![(candidate_hash_c, leaf_a.hash)], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_b], - 1, - vec![(candidate_hash_d, leaf_a.hash)], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a], - 2, - vec![(candidate_hash_c, leaf_a.hash), (candidate_hash_h, leaf_a.hash)], - ) - .await; - - // If the requested count exceeds the largest chain, return the longest - // chain we can get. - for count in 2..10 { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_b], - count, - vec![(candidate_hash_f, leaf_a.hash), (candidate_hash_g, leaf_a.hash)], - ) - .await; - } - } - - // required path of 2 - { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_b, candidate_hash_f], - 1, - vec![(candidate_hash_g, leaf_a.hash)], - ) - .await; - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a, candidate_hash_c], - 1, - vec![(candidate_hash_h, leaf_a.hash)], - ) - .await; - // If the requested count exceeds the largest chain, return the longest - // chain we can get. - for count in 4..10 { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - vec![candidate_hash_a, candidate_hash_c], - count, - vec![ - (candidate_hash_h, leaf_a.hash), - (candidate_hash_i, leaf_a.hash), - (candidate_hash_j, leaf_a.hash), - ], - ) - .await; - } - } - - // No more candidates in any chain. - { - let required_paths = vec![ - vec![candidate_hash_b, candidate_hash_f, candidate_hash_g], - vec![candidate_hash_b, candidate_hash_e], - vec![candidate_hash_b, candidate_hash_d], - vec![ - candidate_hash_a, - candidate_hash_c, - candidate_hash_h, - candidate_hash_i, - candidate_hash_j, - ], - ]; - for path in required_paths { - for count in 1..4 { - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - 1.into(), - path.clone(), - count, - vec![], - ) - .await; - } - } - } + // Non-existent candidate. + get_backable_candidates( + &mut virtual_overseer, + &leaf_a, + 1.into(), + vec![candidate_hash_a, CandidateHash(Hash::from_low_u64_be(100))] + .into_iter() + .collect(), + 2, + vec![(candidate_hash_b, leaf_a.hash), (candidate_hash_d, leaf_a.hash)], + ) + .await; - // Should not get anything at the wrong path. + // Requested count is zero. get_backable_candidates( &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_d], - 1, + Ancestors::new(), + 0, vec![], ) .await; @@ -1531,8 +1362,8 @@ fn check_backable_query_multiple_candidates() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_b, candidate_hash_a], - 3, + vec![candidate_hash_a].into_iter().collect(), + 0, vec![], ) .await; @@ -1540,8 +1371,8 @@ fn check_backable_query_multiple_candidates() { &mut virtual_overseer, &leaf_a, 1.into(), - vec![candidate_hash_a, candidate_hash_c, candidate_hash_d], - 3, + vec![candidate_hash_a, candidate_hash_b].into_iter().collect(), + 0, vec![], ) .await; @@ -1853,8 +1684,8 @@ fn check_pvd_query() { assert_eq!(view.candidate_storage.len(), 2); } -// Test simultaneously activating and deactivating leaves, and simultaneously deactivating multiple -// leaves. +// Test simultaneously activating and deactivating leaves, and simultaneously deactivating +// multiple leaves. #[test] fn correctly_updates_leaves() { let test_state = TestState::default(); @@ -2048,7 +1879,7 @@ fn persists_pending_availability_candidate() { &mut virtual_overseer, &leaf_b, para_id, - vec![candidate_hash_a], + vec![candidate_hash_a].into_iter().collect(), 1, vec![(candidate_hash_b, leaf_b_hash)], ) @@ -2113,7 +1944,7 @@ fn backwards_compatible() { &mut virtual_overseer, &leaf_a, para_id, - vec![], + Ancestors::new(), 1, vec![(candidate_hash_a, candidate_relay_parent)], ) @@ -2135,7 +1966,15 @@ fn backwards_compatible() { ) .await; - get_backable_candidates(&mut virtual_overseer, &leaf_b, para_id, vec![], 1, vec![]).await; + get_backable_candidates( + &mut virtual_overseer, + &leaf_b, + para_id, + Ancestors::new(), + 1, + vec![], + ) + .await; virtual_overseer }); @@ -2162,13 +2001,13 @@ fn uses_ancestry_only_within_session() { .await; assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::AsyncBackingParams(tx)) - ) if parent == hash => { - tx.send(Ok(AsyncBackingParams { max_candidate_depth: 0, allowed_ancestry_len: ancestry_len })).unwrap(); - } - ); + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(parent, RuntimeApiRequest::AsyncBackingParams(tx)) + ) if parent == hash => { + tx.send(Ok(AsyncBackingParams { max_candidate_depth: 0, allowed_ancestry_len: ancestry_len + })).unwrap(); } + ); assert_matches!( virtual_overseer.recv().await, diff --git a/polkadot/node/core/provisioner/Cargo.toml b/polkadot/node/core/provisioner/Cargo.toml index 24cdfd6b57b..2a09e2b5b2c 100644 --- a/polkadot/node/core/provisioner/Cargo.toml +++ b/polkadot/node/core/provisioner/Cargo.toml @@ -20,9 +20,11 @@ polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } futures-timer = "3.0.2" fatality = "0.0.6" +schnellru = "0.2.1" [dev-dependencies] sp-application-crypto = { path = "../../../../substrate/primitives/application-crypto" } sp-keystore = { path = "../../../../substrate/primitives/keystore" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" } +rstest = "0.18.2" diff --git a/polkadot/node/core/provisioner/src/error.rs b/polkadot/node/core/provisioner/src/error.rs index 376d69f276f..aae3234c3cc 100644 --- a/polkadot/node/core/provisioner/src/error.rs +++ b/polkadot/node/core/provisioner/src/error.rs @@ -44,14 +44,17 @@ pub enum Error { #[error("failed to get block number")] CanceledBlockNumber(#[source] oneshot::Canceled), + #[error("failed to get session index")] + CanceledSessionIndex(#[source] oneshot::Canceled), + #[error("failed to get backed candidates")] CanceledBackedCandidates(#[source] oneshot::Canceled), #[error("failed to get votes on dispute")] CanceledCandidateVotes(#[source] oneshot::Canceled), - #[error("failed to get backable candidate from prospective parachains")] - CanceledBackableCandidate(#[source] oneshot::Canceled), + #[error("failed to get backable candidates from prospective parachains")] + CanceledBackableCandidates(#[source] oneshot::Canceled), #[error(transparent)] ChainApi(#[from] ChainApiError), @@ -71,11 +74,6 @@ pub enum Error { #[error("failed to send return message with Inherents")] InherentDataReturnChannel, - #[error( - "backed candidate does not correspond to selected candidate; check logic in provisioner" - )] - BackedCandidateOrderingProblem, - #[fatal] #[error("Failed to spawn background task")] FailedToSpawnBackgroundTask, diff --git a/polkadot/node/core/provisioner/src/lib.rs b/polkadot/node/core/provisioner/src/lib.rs index a29cf72afb1..c9ed873d3c2 100644 --- a/polkadot/node/core/provisioner/src/lib.rs +++ b/polkadot/node/core/provisioner/src/lib.rs @@ -24,26 +24,29 @@ use futures::{ channel::oneshot, future::BoxFuture, prelude::*, stream::FuturesUnordered, FutureExt, }; use futures_timer::Delay; +use schnellru::{ByLength, LruMap}; use polkadot_node_subsystem::{ jaeger, messages::{ - CandidateBackingMessage, ChainApiMessage, ProspectiveParachainsMessage, ProvisionableData, - ProvisionerInherentData, ProvisionerMessage, RuntimeApiRequest, + Ancestors, CandidateBackingMessage, ChainApiMessage, ProspectiveParachainsMessage, + ProvisionableData, ProvisionerInherentData, ProvisionerMessage, RuntimeApiRequest, }, overseer, ActivatedLeaf, ActiveLeavesUpdate, FromOrchestra, OverseerSignal, PerLeafSpan, SpawnedSubsystem, SubsystemError, }; use polkadot_node_subsystem_util::{ has_required_runtime, request_availability_cores, request_persisted_validation_data, - runtime::{prospective_parachains_mode, ProspectiveParachainsMode}, + request_session_index_for_child, + runtime::{prospective_parachains_mode, request_node_features, ProspectiveParachainsMode}, TimeoutExt, }; use polkadot_primitives::{ - BackedCandidate, BlockNumber, CandidateHash, CandidateReceipt, CoreState, Hash, Id as ParaId, - OccupiedCoreAssumption, SignedAvailabilityBitfield, ValidatorIndex, + vstaging::{node_features::FeatureIndex, NodeFeatures}, + BackedCandidate, BlockNumber, CandidateHash, CandidateReceipt, CoreIndex, CoreState, Hash, + Id as ParaId, OccupiedCoreAssumption, SessionIndex, SignedAvailabilityBitfield, ValidatorIndex, }; -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, HashMap, HashSet}; mod disputes; mod error; @@ -77,11 +80,18 @@ impl ProvisionerSubsystem { } } +/// Per-session info we need for the provisioner subsystem. +pub struct PerSession { + prospective_parachains_mode: ProspectiveParachainsMode, + elastic_scaling_mvp: bool, +} + /// A per-relay-parent state for the provisioning subsystem. pub struct PerRelayParent { leaf: ActivatedLeaf, backed_candidates: Vec, prospective_parachains_mode: ProspectiveParachainsMode, + elastic_scaling_mvp: bool, signed_bitfields: Vec, is_inherent_ready: bool, awaiting_inherent: Vec>, @@ -89,13 +99,14 @@ pub struct PerRelayParent { } impl PerRelayParent { - fn new(leaf: ActivatedLeaf, prospective_parachains_mode: ProspectiveParachainsMode) -> Self { + fn new(leaf: ActivatedLeaf, per_session: &PerSession) -> Self { let span = PerLeafSpan::new(leaf.span.clone(), "provisioner"); Self { leaf, backed_candidates: Vec::new(), - prospective_parachains_mode, + prospective_parachains_mode: per_session.prospective_parachains_mode, + elastic_scaling_mvp: per_session.elastic_scaling_mvp, signed_bitfields: Vec::new(), is_inherent_ready: false, awaiting_inherent: Vec::new(), @@ -124,10 +135,17 @@ impl ProvisionerSubsystem { async fn run(mut ctx: Context, metrics: Metrics) -> FatalResult<()> { let mut inherent_delays = InherentDelays::new(); let mut per_relay_parent = HashMap::new(); + let mut per_session = LruMap::new(ByLength::new(2)); loop { - let result = - run_iteration(&mut ctx, &mut per_relay_parent, &mut inherent_delays, &metrics).await; + let result = run_iteration( + &mut ctx, + &mut per_relay_parent, + &mut per_session, + &mut inherent_delays, + &metrics, + ) + .await; match result { Ok(()) => break, @@ -142,6 +160,7 @@ async fn run(mut ctx: Context, metrics: Metrics) -> FatalResult<()> { async fn run_iteration( ctx: &mut Context, per_relay_parent: &mut HashMap, + per_session: &mut LruMap, inherent_delays: &mut InherentDelays, metrics: &Metrics, ) -> Result<(), Error> { @@ -151,7 +170,7 @@ async fn run_iteration( // Map the error to ensure that the subsystem exits when the overseer is gone. match from_overseer.map_err(Error::OverseerExited)? { FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update)) => - handle_active_leaves_update(ctx.sender(), update, per_relay_parent, inherent_delays).await?, + handle_active_leaves_update(ctx.sender(), update, per_relay_parent, per_session, inherent_delays).await?, FromOrchestra::Signal(OverseerSignal::BlockFinalized(..)) => {}, FromOrchestra::Signal(OverseerSignal::Conclude) => return Ok(()), FromOrchestra::Communication { msg } => { @@ -183,6 +202,7 @@ async fn handle_active_leaves_update( sender: &mut impl overseer::ProvisionerSenderTrait, update: ActiveLeavesUpdate, per_relay_parent: &mut HashMap, + per_session: &mut LruMap, inherent_delays: &mut InherentDelays, ) -> Result<(), Error> { gum::trace!(target: LOG_TARGET, "Handle ActiveLeavesUpdate"); @@ -191,10 +211,31 @@ async fn handle_active_leaves_update( } if let Some(leaf) = update.activated { + let session_index = request_session_index_for_child(leaf.hash, sender) + .await + .await + .map_err(Error::CanceledSessionIndex)??; + if per_session.get(&session_index).is_none() { + let prospective_parachains_mode = + prospective_parachains_mode(sender, leaf.hash).await?; + let elastic_scaling_mvp = request_node_features(leaf.hash, session_index, sender) + .await? + .unwrap_or(NodeFeatures::EMPTY) + .get(FeatureIndex::ElasticScalingMVP as usize) + .map(|b| *b) + .unwrap_or(false); + + per_session.insert( + session_index, + PerSession { prospective_parachains_mode, elastic_scaling_mvp }, + ); + } + + let session_info = per_session.get(&session_index).expect("Just inserted"); + gum::trace!(target: LOG_TARGET, leaf_hash=?leaf.hash, "Adding delay"); - let prospective_parachains_mode = prospective_parachains_mode(sender, leaf.hash).await?; let delay_fut = Delay::new(PRE_PROPOSE_TIMEOUT).map(move |_| leaf.hash).boxed(); - per_relay_parent.insert(leaf.hash, PerRelayParent::new(leaf, prospective_parachains_mode)); + per_relay_parent.insert(leaf.hash, PerRelayParent::new(leaf, session_info)); inherent_delays.push(delay_fut); } @@ -253,6 +294,7 @@ async fn send_inherent_data_bg( let signed_bitfields = per_relay_parent.signed_bitfields.clone(); let backed_candidates = per_relay_parent.backed_candidates.clone(); let mode = per_relay_parent.prospective_parachains_mode; + let elastic_scaling_mvp = per_relay_parent.elastic_scaling_mvp; let span = per_relay_parent.span.child("req-inherent-data"); let mut sender = ctx.sender().clone(); @@ -272,6 +314,7 @@ async fn send_inherent_data_bg( &signed_bitfields, &backed_candidates, mode, + elastic_scaling_mvp, return_senders, &mut sender, &metrics, @@ -383,6 +426,7 @@ async fn send_inherent_data( bitfields: &[SignedAvailabilityBitfield], candidates: &[CandidateReceipt], prospective_parachains_mode: ProspectiveParachainsMode, + elastic_scaling_mvp: bool, return_senders: Vec>, from_job: &mut impl overseer::ProvisionerSenderTrait, metrics: &Metrics, @@ -434,6 +478,7 @@ async fn send_inherent_data( &bitfields, candidates, prospective_parachains_mode, + elastic_scaling_mvp, leaf.hash, from_job, ) @@ -558,6 +603,8 @@ async fn select_candidate_hashes_from_tracked( let mut selected_candidates = Vec::with_capacity(candidates.len().min(availability_cores.len())); + let mut selected_parachains = + HashSet::with_capacity(candidates.len().min(availability_cores.len())); gum::debug!( target: LOG_TARGET, @@ -591,6 +638,12 @@ async fn select_candidate_hashes_from_tracked( CoreState::Free => continue, }; + if selected_parachains.contains(&scheduled_core.para_id) { + // We already picked a candidate for this parachain. Elastic scaling only works with + // prospective parachains mode. + continue + } + let validation_data = match request_persisted_validation_data( relay_parent, scheduled_core.para_id, @@ -624,6 +677,7 @@ async fn select_candidate_hashes_from_tracked( "Selected candidate receipt", ); + selected_parachains.insert(candidate.descriptor.para_id); selected_candidates.push((candidate_hash, candidate.descriptor.relay_parent)); } } @@ -637,70 +691,93 @@ async fn select_candidate_hashes_from_tracked( /// Should be called when prospective parachains are enabled. async fn request_backable_candidates( availability_cores: &[CoreState], + elastic_scaling_mvp: bool, bitfields: &[SignedAvailabilityBitfield], relay_parent: Hash, sender: &mut impl overseer::ProvisionerSenderTrait, ) -> Result, Error> { let block_number = get_block_number_under_construction(relay_parent, sender).await?; - let mut selected_candidates = Vec::with_capacity(availability_cores.len()); + // Record how many cores are scheduled for each paraid. Use a BTreeMap because + // we'll need to iterate through them. + let mut scheduled_cores: BTreeMap = BTreeMap::new(); + // The on-chain ancestors of a para present in availability-cores. + let mut ancestors: HashMap = + HashMap::with_capacity(availability_cores.len()); for (core_idx, core) in availability_cores.iter().enumerate() { - let (para_id, required_path) = match core { + let core_idx = CoreIndex(core_idx as u32); + match core { CoreState::Scheduled(scheduled_core) => { - // The core is free, pick the first eligible candidate from - // the fragment tree. - (scheduled_core.para_id, Vec::new()) + *scheduled_cores.entry(scheduled_core.para_id).or_insert(0) += 1; }, CoreState::Occupied(occupied_core) => { - if bitfields_indicate_availability(core_idx, bitfields, &occupied_core.availability) - { + let is_available = bitfields_indicate_availability( + core_idx.0 as usize, + bitfields, + &occupied_core.availability, + ); + + if is_available { + ancestors + .entry(occupied_core.para_id()) + .or_default() + .insert(occupied_core.candidate_hash); + if let Some(ref scheduled_core) = occupied_core.next_up_on_available { - // The candidate occupying the core is available, choose its - // child in the fragment tree. - // - // TODO: doesn't work for on-demand parachains. We lean hard on the - // assumption that cores are fixed to specific parachains within a session. - // https://github.com/paritytech/polkadot/issues/5492 - (scheduled_core.para_id, vec![occupied_core.candidate_hash]) - } else { - continue - } - } else { - if occupied_core.time_out_at != block_number { - continue + // Request a new backable candidate for the newly scheduled para id. + *scheduled_cores.entry(scheduled_core.para_id).or_insert(0) += 1; } + } else if occupied_core.time_out_at <= block_number { + // Timed out before being available. + if let Some(ref scheduled_core) = occupied_core.next_up_on_time_out { // Candidate's availability timed out, practically same as scheduled. - (scheduled_core.para_id, Vec::new()) - } else { - continue + *scheduled_cores.entry(scheduled_core.para_id).or_insert(0) += 1; } + } else { + // Not timed out and not available. + ancestors + .entry(occupied_core.para_id()) + .or_default() + .insert(occupied_core.candidate_hash); } }, CoreState::Free => continue, }; + } - // We should be calling this once per para rather than per core. - // TODO: Will be fixed in https://github.com/paritytech/polkadot-sdk/pull/3233. - // For now, at least make sure we don't supply the same candidate multiple times in case a - // para has multiple cores scheduled. - let response = get_backable_candidate(relay_parent, para_id, required_path, sender).await?; - match response { - Some((hash, relay_parent)) => { - if !selected_candidates.iter().any(|bc| &(hash, relay_parent) == bc) { - selected_candidates.push((hash, relay_parent)) - } - }, - None => { - gum::debug!( - target: LOG_TARGET, - leaf_hash = ?relay_parent, - core = core_idx, - "No backable candidate returned by prospective parachains", - ); - }, + let mut selected_candidates: Vec<(CandidateHash, Hash)> = + Vec::with_capacity(availability_cores.len()); + + for (para_id, core_count) in scheduled_cores { + let para_ancestors = ancestors.remove(¶_id).unwrap_or_default(); + + // If elastic scaling MVP is disabled, only allow one candidate per parachain. + if !elastic_scaling_mvp && core_count > 1 { + continue } + + let response = get_backable_candidates( + relay_parent, + para_id, + para_ancestors, + core_count as u32, + sender, + ) + .await?; + + if response.is_empty() { + gum::debug!( + target: LOG_TARGET, + leaf_hash = ?relay_parent, + ?para_id, + "No backable candidate returned by prospective parachains", + ); + continue + } + + selected_candidates.extend(response.into_iter().take(core_count)); } Ok(selected_candidates) @@ -713,6 +790,7 @@ async fn select_candidates( bitfields: &[SignedAvailabilityBitfield], candidates: &[CandidateReceipt], prospective_parachains_mode: ProspectiveParachainsMode, + elastic_scaling_mvp: bool, relay_parent: Hash, sender: &mut impl overseer::ProvisionerSenderTrait, ) -> Result, Error> { @@ -722,7 +800,14 @@ async fn select_candidates( let selected_candidates = match prospective_parachains_mode { ProspectiveParachainsMode::Enabled { .. } => - request_backable_candidates(availability_cores, bitfields, relay_parent, sender).await?, + request_backable_candidates( + availability_cores, + elastic_scaling_mvp, + bitfields, + relay_parent, + sender, + ) + .await?, ProspectiveParachainsMode::Disabled => select_candidate_hashes_from_tracked( availability_cores, @@ -745,24 +830,6 @@ async fn select_candidates( gum::trace!(target: LOG_TARGET, leaf_hash=?relay_parent, "Got {} backed candidates", candidates.len()); - // `selected_candidates` is generated in ascending order by core index, and - // `GetBackedCandidates` _should_ preserve that property, but let's just make sure. - // - // We can't easily map from `BackedCandidate` to `core_idx`, but we know that every selected - // candidate maps to either 0 or 1 backed candidate, and the hashes correspond. Therefore, by - // checking them in order, we can ensure that the backed candidates are also in order. - let mut backed_idx = 0; - for selected in selected_candidates { - if selected.0 == - candidates.get(backed_idx).ok_or(Error::BackedCandidateOrderingProblem)?.hash() - { - backed_idx += 1; - } - } - if candidates.len() != backed_idx { - Err(Error::BackedCandidateOrderingProblem)?; - } - // keep only one candidate with validation code. let mut with_validation_code = false; candidates.retain(|c| { @@ -804,28 +871,27 @@ async fn get_block_number_under_construction( } } -/// Requests backable candidate from Prospective Parachains based on -/// the given path in the fragment tree. -async fn get_backable_candidate( +/// Requests backable candidates from Prospective Parachains based on +/// the given ancestors in the fragment tree. The ancestors may not be ordered. +async fn get_backable_candidates( relay_parent: Hash, para_id: ParaId, - required_path: Vec, + ancestors: Ancestors, + count: u32, sender: &mut impl overseer::ProvisionerSenderTrait, -) -> Result, Error> { +) -> Result, Error> { let (tx, rx) = oneshot::channel(); sender .send_message(ProspectiveParachainsMessage::GetBackableCandidates( relay_parent, para_id, - 1, // core count hardcoded to 1, until elastic scaling is implemented and enabled. - required_path, + count, + ancestors, tx, )) .await; - rx.await - .map_err(Error::CanceledBackableCandidate) - .map(|res| res.get(0).copied()) + rx.await.map_err(Error::CanceledBackableCandidates) } /// The availability bitfield for a given core is the transpose diff --git a/polkadot/node/core/provisioner/src/tests.rs b/polkadot/node/core/provisioner/src/tests.rs index 87c0e7a65d3..bdb4f85f400 100644 --- a/polkadot/node/core/provisioner/src/tests.rs +++ b/polkadot/node/core/provisioner/src/tests.rs @@ -22,6 +22,9 @@ use polkadot_primitives::{OccupiedCore, ScheduledCore}; const MOCK_GROUP_SIZE: usize = 5; pub fn occupied_core(para_id: u32) -> CoreState { + let mut candidate_descriptor = dummy_candidate_descriptor(dummy_hash()); + candidate_descriptor.para_id = para_id.into(); + CoreState::Occupied(OccupiedCore { group_responsible: para_id.into(), next_up_on_available: None, @@ -29,7 +32,7 @@ pub fn occupied_core(para_id: u32) -> CoreState { time_out_at: 200_u32, next_up_on_time_out: None, availability: bitvec![u8, bitvec::order::Lsb0; 0; 32], - candidate_descriptor: dummy_candidate_descriptor(dummy_hash()), + candidate_descriptor, candidate_hash: Default::default(), }) } @@ -254,10 +257,56 @@ mod select_candidates { use polkadot_primitives::{ BlockNumber, CandidateCommitments, CommittedCandidateReceipt, PersistedValidationData, }; + use rstest::rstest; const BLOCK_UNDER_PRODUCTION: BlockNumber = 128; - // For test purposes, we always return this set of availability cores: + fn dummy_candidate_template() -> CandidateReceipt { + let empty_hash = PersistedValidationData::::default().hash(); + + let mut descriptor_template = dummy_candidate_descriptor(dummy_hash()); + descriptor_template.persisted_validation_data_hash = empty_hash; + CandidateReceipt { + descriptor: descriptor_template, + commitments_hash: CandidateCommitments::default().hash(), + } + } + + fn make_candidates( + core_count: usize, + expected_backed_indices: Vec, + ) -> (Vec, Vec) { + let candidate_template = dummy_candidate_template(); + let candidates: Vec<_> = std::iter::repeat(candidate_template) + .take(core_count) + .enumerate() + .map(|(idx, mut candidate)| { + candidate.descriptor.para_id = idx.into(); + candidate + }) + .collect(); + + let expected_backed = expected_backed_indices + .iter() + .map(|&idx| candidates[idx].clone()) + .map(|c| { + BackedCandidate::new( + CommittedCandidateReceipt { + descriptor: c.descriptor.clone(), + commitments: Default::default(), + }, + Vec::new(), + default_bitvec(MOCK_GROUP_SIZE), + None, + ) + }) + .collect(); + let candidate_hashes = candidates.into_iter().map(|c| c.hash()).collect(); + + (candidate_hashes, expected_backed) + } + + // For testing only one core assigned to a parachain, we return this set of availability cores: // // [ // 0: Free, @@ -273,7 +322,7 @@ mod select_candidates { // 10: Occupied(both next_up set, not available, timeout), // 11: Occupied(next_up_on_available and available, but different successor para_id) // ] - fn mock_availability_cores() -> Vec { + fn mock_availability_cores_one_per_para() -> Vec { use std::ops::Not; use CoreState::{Free, Scheduled}; @@ -292,6 +341,7 @@ mod select_candidates { build_occupied_core(4, |core| { core.next_up_on_available = Some(scheduled_core(4)); core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(41)); }), // 5: Occupied(next_up_on_time_out set but not timeout), build_occupied_core(5, |core| { @@ -307,12 +357,14 @@ mod select_candidates { build_occupied_core(7, |core| { core.next_up_on_time_out = Some(scheduled_core(7)); core.time_out_at = BLOCK_UNDER_PRODUCTION; + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(71)); }), // 8: Occupied(both next_up set, available), build_occupied_core(8, |core| { core.next_up_on_available = Some(scheduled_core(8)); core.next_up_on_time_out = Some(scheduled_core(8)); core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(81)); }), // 9: Occupied(both next_up set, not available, no timeout), build_occupied_core(9, |core| { @@ -324,6 +376,7 @@ mod select_candidates { core.next_up_on_available = Some(scheduled_core(10)); core.next_up_on_time_out = Some(scheduled_core(10)); core.time_out_at = BLOCK_UNDER_PRODUCTION; + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(101)); }), // 11: Occupied(next_up_on_available and available, but different successor para_id) build_occupied_core(11, |core| { @@ -333,20 +386,189 @@ mod select_candidates { ] } + // For test purposes with multiple possible cores assigned to a para, we always return this set + // of availability cores: + fn mock_availability_cores_multiple_per_para() -> Vec { + use std::ops::Not; + use CoreState::{Free, Scheduled}; + + vec![ + // 0: Free, + Free, + // 1: Scheduled(default), + Scheduled(scheduled_core(1)), + // 2: Occupied(no next_up set), + occupied_core(2), + // 3: Occupied(next_up_on_available set but not available), + build_occupied_core(3, |core| { + core.next_up_on_available = Some(scheduled_core(3)); + }), + // 4: Occupied(next_up_on_available set and available), + build_occupied_core(4, |core| { + core.next_up_on_available = Some(scheduled_core(4)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(41)); + }), + // 5: Occupied(next_up_on_time_out set but not timeout), + build_occupied_core(5, |core| { + core.next_up_on_time_out = Some(scheduled_core(5)); + }), + // 6: Occupied(next_up_on_time_out set and timeout but available), + build_occupied_core(6, |core| { + core.next_up_on_time_out = Some(scheduled_core(6)); + core.time_out_at = BLOCK_UNDER_PRODUCTION; + core.availability = core.availability.clone().not(); + }), + // 7: Occupied(next_up_on_time_out set and timeout and not available), + build_occupied_core(7, |core| { + core.next_up_on_time_out = Some(scheduled_core(7)); + core.time_out_at = BLOCK_UNDER_PRODUCTION; + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(71)); + }), + // 8: Occupied(both next_up set, available), + build_occupied_core(8, |core| { + core.next_up_on_available = Some(scheduled_core(8)); + core.next_up_on_time_out = Some(scheduled_core(8)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(81)); + }), + // 9: Occupied(both next_up set, not available, no timeout), + build_occupied_core(9, |core| { + core.next_up_on_available = Some(scheduled_core(9)); + core.next_up_on_time_out = Some(scheduled_core(9)); + }), + // 10: Occupied(both next_up set, not available, timeout), + build_occupied_core(10, |core| { + core.next_up_on_available = Some(scheduled_core(10)); + core.next_up_on_time_out = Some(scheduled_core(10)); + core.time_out_at = BLOCK_UNDER_PRODUCTION; + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(101)); + }), + // 11: Occupied(next_up_on_available and available, but different successor para_id) + build_occupied_core(11, |core| { + core.next_up_on_available = Some(scheduled_core(12)); + core.availability = core.availability.clone().not(); + }), + // 12-14: Occupied(next_up_on_available and available, same para_id). + build_occupied_core(12, |core| { + core.next_up_on_available = Some(scheduled_core(12)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(121)); + }), + build_occupied_core(12, |core| { + core.next_up_on_available = Some(scheduled_core(12)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(122)); + }), + build_occupied_core(12, |core| { + core.next_up_on_available = Some(scheduled_core(12)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(123)); + }), + // 15: Scheduled on same para_id as 12-14. + Scheduled(scheduled_core(12)), + // 16: Occupied(13, no next_up set, not available) + build_occupied_core(13, |core| { + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(131)); + }), + // 17: Occupied(13, no next_up set, available) + build_occupied_core(13, |core| { + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(132)); + }), + // 18: Occupied(13, next_up_on_available set to 13 but not available) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(13)); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(133)); + }), + // 19: Occupied(13, next_up_on_available set to 13 and available) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(13)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(134)); + }), + // 20: Occupied(13, next_up_on_time_out set to 13 but not timeout) + build_occupied_core(13, |core| { + core.next_up_on_time_out = Some(scheduled_core(13)); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(135)); + }), + // 21: Occupied(13, next_up_on_available set to 14 and available) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(14)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(136)); + }), + // 22: Occupied(13, next_up_on_available set to 14 but not available) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(14)); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(137)); + }), + // 23: Occupied(13, both next_up set to 14, available) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(14)); + core.next_up_on_time_out = Some(scheduled_core(14)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(138)); + }), + // 24: Occupied(13, both next_up set to 14, not available, timeout) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(14)); + core.next_up_on_time_out = Some(scheduled_core(14)); + core.time_out_at = BLOCK_UNDER_PRODUCTION; + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(1399)); + }), + // 25: Occupied(13, next_up_on_available and available, but successor para_id 15) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(15)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(139)); + }), + // 26: Occupied(15, next_up_on_available and available, but successor para_id 13) + build_occupied_core(15, |core| { + core.next_up_on_available = Some(scheduled_core(13)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(151)); + }), + // 27: Occupied(15, both next_up, both available and timed out) + build_occupied_core(15, |core| { + core.next_up_on_available = Some(scheduled_core(15)); + core.availability = core.availability.clone().not(); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(152)); + core.time_out_at = BLOCK_UNDER_PRODUCTION; + }), + // 28: Occupied(13, both next_up set to 13, not available) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(13)); + core.next_up_on_time_out = Some(scheduled_core(13)); + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(1398)); + }), + // 29: Occupied(13, both next_up set to 13, not available, timeout) + build_occupied_core(13, |core| { + core.next_up_on_available = Some(scheduled_core(13)); + core.next_up_on_time_out = Some(scheduled_core(13)); + core.time_out_at = BLOCK_UNDER_PRODUCTION; + core.candidate_hash = CandidateHash(Hash::from_low_u64_be(1397)); + }), + ] + } + async fn mock_overseer( mut receiver: mpsc::UnboundedReceiver, - expected: Vec, + mock_availability_cores: Vec, + mut expected: Vec, + mut expected_ancestors: HashMap, Ancestors>, prospective_parachains_mode: ProspectiveParachainsMode, ) { use ChainApiMessage::BlockNumber; use RuntimeApiMessage::Request; + let mut backed_iter = expected.clone().into_iter(); + + expected.sort_by_key(|c| c.candidate().descriptor.para_id); let mut candidates_iter = expected .iter() .map(|candidate| (candidate.hash(), candidate.descriptor().relay_parent)); - let mut backed_iter = expected.clone().into_iter(); - while let Some(from_job) = receiver.next().await { match from_job { AllMessages::ChainApi(BlockNumber(_relay_parent, tx)) => @@ -356,7 +578,7 @@ mod select_candidates { PersistedValidationDataReq(_para_id, _assumption, tx), )) => tx.send(Ok(Some(Default::default()))).unwrap(), AllMessages::RuntimeApi(Request(_parent_hash, AvailabilityCores(tx))) => - tx.send(Ok(mock_availability_cores())).unwrap(), + tx.send(Ok(mock_availability_cores.clone())).unwrap(), AllMessages::CandidateBacking(CandidateBackingMessage::GetBackedCandidates( hashes, sender, @@ -373,35 +595,71 @@ mod select_candidates { let _ = sender.send(response); }, AllMessages::ProspectiveParachains( - ProspectiveParachainsMessage::GetBackableCandidates(_, _, count, _, tx), - ) => { - assert_eq!(count, 1); - - match prospective_parachains_mode { - ProspectiveParachainsMode::Enabled { .. } => { - let _ = - tx.send(candidates_iter.next().map_or_else(Vec::new, |c| vec![c])); - }, - ProspectiveParachainsMode::Disabled => - panic!("unexpected prospective parachains request"), - } + ProspectiveParachainsMessage::GetBackableCandidates( + _, + _para_id, + count, + actual_ancestors, + tx, + ), + ) => match prospective_parachains_mode { + ProspectiveParachainsMode::Enabled { .. } => { + assert!(count > 0); + let candidates = + (&mut candidates_iter).take(count as usize).collect::>(); + assert_eq!(candidates.len(), count as usize); + + if !expected_ancestors.is_empty() { + if let Some(expected_required_ancestors) = expected_ancestors.remove( + &(candidates + .clone() + .into_iter() + .take(actual_ancestors.len()) + .map(|(c_hash, _)| c_hash) + .collect::>()), + ) { + assert_eq!(expected_required_ancestors, actual_ancestors); + } else { + assert_eq!(actual_ancestors.len(), 0); + } + } + + let _ = tx.send(candidates); + }, + ProspectiveParachainsMode::Disabled => + panic!("unexpected prospective parachains request"), }, _ => panic!("Unexpected message: {:?}", from_job), } } + + if let ProspectiveParachainsMode::Enabled { .. } = prospective_parachains_mode { + assert_eq!(candidates_iter.next(), None); + } + assert_eq!(expected_ancestors.len(), 0); } - #[test] - fn can_succeed() { + #[rstest] + #[case(ProspectiveParachainsMode::Disabled)] + #[case(ProspectiveParachainsMode::Enabled {max_candidate_depth: 0, allowed_ancestry_len: 0})] + fn can_succeed(#[case] prospective_parachains_mode: ProspectiveParachainsMode) { test_harness( - |r| mock_overseer(r, Vec::new(), ProspectiveParachainsMode::Disabled), + |r| { + mock_overseer( + r, + Vec::new(), + Vec::new(), + HashMap::new(), + prospective_parachains_mode, + ) + }, |mut tx: TestSubsystemSender| async move { - let prospective_parachains_mode = ProspectiveParachainsMode::Disabled; select_candidates( &[], &[], &[], prospective_parachains_mode, + false, Default::default(), &mut tx, ) @@ -411,22 +669,22 @@ mod select_candidates { ) } - // this tests that only the appropriate candidates get selected. - // To accomplish this, we supply a candidate list containing one candidate per possible core; - // the candidate selection algorithm must filter them to the appropriate set - #[test] - fn selects_correct_candidates() { - let mock_cores = mock_availability_cores(); - - let empty_hash = PersistedValidationData::::default().hash(); - - let mut descriptor_template = dummy_candidate_descriptor(dummy_hash()); - descriptor_template.persisted_validation_data_hash = empty_hash; - let candidate_template = CandidateReceipt { - descriptor: descriptor_template, - commitments_hash: CandidateCommitments::default().hash(), - }; - + // Test candidate selection when prospective parachains mode is disabled. + // This tests that only the appropriate candidates get selected when prospective parachains mode + // is disabled. To accomplish this, we supply a candidate list containing one candidate per + // possible core; the candidate selection algorithm must filter them to the appropriate set + #[rstest] + // why those particular indices? see the comments on mock_availability_cores_*() functions. + #[case(mock_availability_cores_one_per_para(), vec![1, 4, 7, 8, 10], true)] + #[case(mock_availability_cores_one_per_para(), vec![1, 4, 7, 8, 10], false)] + #[case(mock_availability_cores_multiple_per_para(), vec![1, 4, 7, 8, 10, 12, 13, 14, 15], true)] + #[case(mock_availability_cores_multiple_per_para(), vec![1, 4, 7, 8, 10, 12, 13, 14, 15], false)] + fn test_in_subsystem_selection( + #[case] mock_cores: Vec, + #[case] expected_candidates: Vec, + #[case] elastic_scaling_mvp: bool, + ) { + let candidate_template = dummy_candidate_template(); let candidates: Vec<_> = std::iter::repeat(candidate_template) .take(mock_cores.len()) .enumerate() @@ -453,9 +711,8 @@ mod select_candidates { }) .collect(); - // why those particular indices? see the comments on mock_availability_cores() let expected_candidates: Vec<_> = - [1, 4, 7, 8, 10].iter().map(|&idx| candidates[idx].clone()).collect(); + expected_candidates.into_iter().map(|idx| candidates[idx].clone()).collect(); let prospective_parachains_mode = ProspectiveParachainsMode::Disabled; let expected_backed = expected_candidates @@ -473,14 +730,24 @@ mod select_candidates { }) .collect(); + let mock_cores_clone = mock_cores.clone(); test_harness( - |r| mock_overseer(r, expected_backed, prospective_parachains_mode), + |r| { + mock_overseer( + r, + mock_cores_clone, + expected_backed, + HashMap::new(), + prospective_parachains_mode, + ) + }, |mut tx: TestSubsystemSender| async move { - let result = select_candidates( + let result: Vec = select_candidates( &mock_cores, &[], &candidates, prospective_parachains_mode, + elastic_scaling_mvp, Default::default(), &mut tx, ) @@ -498,20 +765,24 @@ mod select_candidates { ) } - #[test] - fn selects_max_one_code_upgrade() { - let mock_cores = mock_availability_cores(); + #[rstest] + #[case(ProspectiveParachainsMode::Disabled)] + #[case(ProspectiveParachainsMode::Enabled {max_candidate_depth: 0, allowed_ancestry_len: 0})] + fn selects_max_one_code_upgrade( + #[case] prospective_parachains_mode: ProspectiveParachainsMode, + ) { + let mock_cores = mock_availability_cores_one_per_para(); let empty_hash = PersistedValidationData::::default().hash(); // why those particular indices? see the comments on mock_availability_cores() - // the first candidate with code is included out of [1, 4, 7, 8, 10]. - let cores = [1, 4, 7, 8, 10]; + // the first candidate with code is included out of [1, 4, 7, 8, 10, 12]. + let cores = [1, 4, 7, 8, 10, 12]; let cores_with_code = [1, 4, 8]; - let expected_cores = [1, 7, 10]; + let expected_cores = [1, 7, 10, 12]; - let committed_receipts: Vec<_> = (0..mock_cores.len()) + let committed_receipts: Vec<_> = (0..=mock_cores.len()) .map(|i| { let mut descriptor = dummy_candidate_descriptor(dummy_hash()); descriptor.para_id = i.into(); @@ -552,23 +823,32 @@ mod select_candidates { let expected_backed_filtered: Vec<_> = expected_cores.iter().map(|&idx| candidates[idx].clone()).collect(); - let prospective_parachains_mode = ProspectiveParachainsMode::Disabled; + let mock_cores_clone = mock_cores.clone(); test_harness( - |r| mock_overseer(r, expected_backed, prospective_parachains_mode), + |r| { + mock_overseer( + r, + mock_cores_clone, + expected_backed, + HashMap::new(), + prospective_parachains_mode, + ) + }, |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], &candidates, prospective_parachains_mode, + false, Default::default(), &mut tx, ) .await .unwrap(); - assert_eq!(result.len(), 3); + assert_eq!(result.len(), 4); result.into_iter().for_each(|c| { assert!( @@ -581,66 +861,214 @@ mod select_candidates { ) } - #[test] - fn request_from_prospective_parachains() { - let mock_cores = mock_availability_cores(); - let empty_hash = PersistedValidationData::::default().hash(); + #[rstest] + #[case(true)] + #[case(false)] + fn request_from_prospective_parachains_one_core_per_para(#[case] elastic_scaling_mvp: bool) { + let mock_cores = mock_availability_cores_one_per_para(); - let mut descriptor_template = dummy_candidate_descriptor(dummy_hash()); - descriptor_template.persisted_validation_data_hash = empty_hash; - let candidate_template = CandidateReceipt { - descriptor: descriptor_template, - commitments_hash: CandidateCommitments::default().hash(), - }; + // why those particular indices? see the comments on mock_availability_cores() + let expected_candidates: Vec<_> = vec![1, 4, 7, 8, 10, 12]; + let (candidates, expected_candidates) = + make_candidates(mock_cores.len() + 1, expected_candidates); - let candidates: Vec<_> = std::iter::repeat(candidate_template) - .take(mock_cores.len()) - .enumerate() - .map(|(idx, mut candidate)| { - candidate.descriptor.para_id = idx.into(); - candidate - }) - .collect(); + // Expect prospective parachains subsystem requests. + let prospective_parachains_mode = + ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; + + let mut required_ancestors: HashMap, Ancestors> = HashMap::new(); + required_ancestors.insert( + vec![candidates[4]], + vec![CandidateHash(Hash::from_low_u64_be(41))].into_iter().collect(), + ); + required_ancestors.insert( + vec![candidates[8]], + vec![CandidateHash(Hash::from_low_u64_be(81))].into_iter().collect(), + ); + + let mock_cores_clone = mock_cores.clone(); + let expected_candidates_clone = expected_candidates.clone(); + test_harness( + |r| { + mock_overseer( + r, + mock_cores_clone, + expected_candidates_clone, + required_ancestors, + prospective_parachains_mode, + ) + }, + |mut tx: TestSubsystemSender| async move { + let result = select_candidates( + &mock_cores, + &[], + &[], + prospective_parachains_mode, + elastic_scaling_mvp, + Default::default(), + &mut tx, + ) + .await + .unwrap(); + + assert_eq!(result.len(), expected_candidates.len()); + result.into_iter().for_each(|c| { + assert!( + expected_candidates + .iter() + .any(|c2| c.candidate().corresponds_to(&c2.receipt())), + "Failed to find candidate: {:?}", + c, + ) + }); + }, + ) + } + + #[test] + fn request_from_prospective_parachains_multiple_cores_per_para_elastic_scaling_mvp() { + let mock_cores = mock_availability_cores_multiple_per_para(); // why those particular indices? see the comments on mock_availability_cores() let expected_candidates: Vec<_> = - [1, 4, 7, 8, 10].iter().map(|&idx| candidates[idx].clone()).collect(); + vec![1, 4, 7, 8, 10, 12, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15]; // Expect prospective parachains subsystem requests. let prospective_parachains_mode = ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; - let expected_backed = expected_candidates - .iter() - .map(|c| { - BackedCandidate::new( - CommittedCandidateReceipt { - descriptor: c.descriptor.clone(), - commitments: Default::default(), - }, - Vec::new(), - default_bitvec(MOCK_GROUP_SIZE), - None, + let (candidates, expected_candidates) = + make_candidates(mock_cores.len(), expected_candidates); + + let mut required_ancestors: HashMap, Ancestors> = HashMap::new(); + required_ancestors.insert( + vec![candidates[4]], + vec![CandidateHash(Hash::from_low_u64_be(41))].into_iter().collect(), + ); + required_ancestors.insert( + vec![candidates[8]], + vec![CandidateHash(Hash::from_low_u64_be(81))].into_iter().collect(), + ); + required_ancestors.insert( + [12, 12, 12].iter().map(|&idx| candidates[idx]).collect::>(), + vec![ + CandidateHash(Hash::from_low_u64_be(121)), + CandidateHash(Hash::from_low_u64_be(122)), + CandidateHash(Hash::from_low_u64_be(123)), + ] + .into_iter() + .collect(), + ); + required_ancestors.insert( + [13, 13, 13].iter().map(|&idx| candidates[idx]).collect::>(), + (131..=139) + .map(|num| CandidateHash(Hash::from_low_u64_be(num))) + .chain(std::iter::once(CandidateHash(Hash::from_low_u64_be(1398)))) + .collect(), + ); + + required_ancestors.insert( + [15, 15].iter().map(|&idx| candidates[idx]).collect::>(), + vec![ + CandidateHash(Hash::from_low_u64_be(151)), + CandidateHash(Hash::from_low_u64_be(152)), + ] + .into_iter() + .collect(), + ); + + let mock_cores_clone = mock_cores.clone(); + let expected_candidates_clone = expected_candidates.clone(); + test_harness( + |r| { + mock_overseer( + r, + mock_cores_clone, + expected_candidates, + required_ancestors, + prospective_parachains_mode, ) - }) - .collect(); + }, + |mut tx: TestSubsystemSender| async move { + let result = select_candidates( + &mock_cores, + &[], + &[], + prospective_parachains_mode, + true, + Default::default(), + &mut tx, + ) + .await + .unwrap(); + assert_eq!(result.len(), expected_candidates_clone.len()); + result.into_iter().for_each(|c| { + assert!( + expected_candidates_clone + .iter() + .any(|c2| c.candidate().corresponds_to(&c2.receipt())), + "Failed to find candidate: {:?}", + c, + ) + }); + }, + ) + } + + #[test] + fn request_from_prospective_parachains_multiple_cores_per_para_elastic_scaling_mvp_disabled() { + let mock_cores = mock_availability_cores_multiple_per_para(); + + // why those particular indices? see the comments on mock_availability_cores() + let expected_candidates: Vec<_> = vec![1, 4, 7, 8, 10]; + // Expect prospective parachains subsystem requests. + let prospective_parachains_mode = + ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; + + let (candidates, expected_candidates) = + make_candidates(mock_cores.len(), expected_candidates); + + let mut required_ancestors: HashMap, Ancestors> = HashMap::new(); + required_ancestors.insert( + vec![candidates[4]], + vec![CandidateHash(Hash::from_low_u64_be(41))].into_iter().collect(), + ); + required_ancestors.insert( + vec![candidates[8]], + vec![CandidateHash(Hash::from_low_u64_be(81))].into_iter().collect(), + ); + + let mock_cores_clone = mock_cores.clone(); + let expected_candidates_clone = expected_candidates.clone(); test_harness( - |r| mock_overseer(r, expected_backed, prospective_parachains_mode), + |r| { + mock_overseer( + r, + mock_cores_clone, + expected_candidates, + required_ancestors, + prospective_parachains_mode, + ) + }, |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], &[], prospective_parachains_mode, + false, Default::default(), &mut tx, ) .await .unwrap(); + assert_eq!(result.len(), expected_candidates_clone.len()); result.into_iter().for_each(|c| { assert!( - expected_candidates.iter().any(|c2| c.candidate().corresponds_to(c2)), + expected_candidates_clone + .iter() + .any(|c2| c.candidate().corresponds_to(&c2.receipt())), "Failed to find candidate: {:?}", c, ) @@ -651,18 +1079,11 @@ mod select_candidates { #[test] fn request_receipts_based_on_relay_parent() { - let mock_cores = mock_availability_cores(); - let empty_hash = PersistedValidationData::::default().hash(); - - let mut descriptor_template = dummy_candidate_descriptor(dummy_hash()); - descriptor_template.persisted_validation_data_hash = empty_hash; - let candidate_template = CandidateReceipt { - descriptor: descriptor_template, - commitments_hash: CandidateCommitments::default().hash(), - }; + let mock_cores = mock_availability_cores_one_per_para(); + let candidate_template = dummy_candidate_template(); let candidates: Vec<_> = std::iter::repeat(candidate_template) - .take(mock_cores.len()) + .take(mock_cores.len() + 1) .enumerate() .map(|(idx, mut candidate)| { candidate.descriptor.para_id = idx.into(); @@ -673,7 +1094,7 @@ mod select_candidates { // why those particular indices? see the comments on mock_availability_cores() let expected_candidates: Vec<_> = - [1, 4, 7, 8, 10].iter().map(|&idx| candidates[idx].clone()).collect(); + [1, 4, 7, 8, 10, 12].iter().map(|&idx| candidates[idx].clone()).collect(); // Expect prospective parachains subsystem requests. let prospective_parachains_mode = ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; @@ -693,14 +1114,24 @@ mod select_candidates { }) .collect(); + let mock_cores_clone = mock_cores.clone(); test_harness( - |r| mock_overseer(r, expected_backed, prospective_parachains_mode), + |r| { + mock_overseer( + r, + mock_cores_clone, + expected_backed, + HashMap::new(), + prospective_parachains_mode, + ) + }, |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], &[], prospective_parachains_mode, + false, Default::default(), &mut tx, ) diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 549e43a671d..f11291fd0ea 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -1112,6 +1112,9 @@ pub struct ProspectiveValidationDataRequest { /// is present in and the depths of that tree the candidate is present in. pub type FragmentTreeMembership = Vec<(Hash, Vec)>; +/// A collection of ancestor candidates of a parachain. +pub type Ancestors = HashSet; + /// Messages sent to the Prospective Parachains subsystem. #[derive(Debug)] pub enum ProspectiveParachainsMessage { @@ -1128,15 +1131,18 @@ pub enum ProspectiveParachainsMessage { /// has been backed. This requires that the candidate was successfully introduced in /// the past. CandidateBacked(ParaId, CandidateHash), - /// Get N backable candidate hashes along with their relay parents for the given parachain, - /// under the given relay-parent hash, which is a descendant of the given candidate hashes. + /// Try getting N backable candidate hashes along with their relay parents for the given + /// parachain, under the given relay-parent hash, which is a descendant of the given ancestors. + /// Timed out ancestors should not be included in the collection. /// N should represent the number of scheduled cores of this ParaId. - /// Returns `None` on the channel if no such candidate exists. + /// A timed out ancestor frees the cores of all of its descendants, so if there's a hole in the + /// supplied ancestor path, we'll get candidates that backfill those timed out slots first. It + /// may also return less/no candidates, if there aren't enough backable candidates recorded. GetBackableCandidates( Hash, ParaId, u32, - Vec, + Ancestors, oneshot::Sender>, ), /// Get the hypothetical frontier membership of candidates with the given properties diff --git a/prdoc/pr_3233.prdoc b/prdoc/pr_3233.prdoc new file mode 100644 index 00000000000..ed4e8cce31f --- /dev/null +++ b/prdoc/pr_3233.prdoc @@ -0,0 +1,12 @@ +title: "provisioner: allow multiple cores assigned to the same para" + +topic: Node + +doc: + - audience: Node Dev + description: | + Enable supplying multiple backable candidates to the paras_inherent pallet for the same paraid. + +crates: + - name: polkadot-node-core-prospective-parachains + - name: polkadot-node-core-provisioner -- GitLab From cdc8d197e6d487ef54f7e16767b5c1ab041c8b10 Mon Sep 17 00:00:00 2001 From: gupnik Date: Sat, 2 Mar 2024 18:19:12 +0530 Subject: [PATCH 060/188] Remove `as frame_system::DefaultConfig` from the required syntax in `derive_impl` (#3505) Step in https://github.com/paritytech/polkadot-sdk/issues/171 This PR removes the need to specify `as [disambiguation_path]` for cases where the trait definition resides within the same scope as default impl path. For example, in the following macro invocation ```rust #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Runtime { ... } ``` the trait `DefaultConfig` lies within the `frame_system` scope and `TestDefaultConfig` impls the `DefaultConfig` trait. Using this information, we can compute the disambiguation path internally, thus removing the need of an explicit specification. In cases where the trait lies outside this scope, we would still need to specify it explicitly, but this should take care of most (if not all) uses of `derive_impl` within FRAME's context. --- prdoc/pr_3505.prdoc | 36 ++++++++++ .../frame/examples/default-config/src/lib.rs | 2 +- .../support/procedural/src/derive_impl.rs | 68 +++++++++++++++---- substrate/frame/support/procedural/src/lib.rs | 5 ++ 4 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 prdoc/pr_3505.prdoc diff --git a/prdoc/pr_3505.prdoc b/prdoc/pr_3505.prdoc new file mode 100644 index 00000000000..08ad909739c --- /dev/null +++ b/prdoc/pr_3505.prdoc @@ -0,0 +1,36 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Removes `as [disambiguation_path]` from the required syntax in `derive_impl` + +doc: + - audience: Runtime Dev + description: | + This PR removes the need to specify `as [disambiguation_path]` for cases where the trait + definition resides within the same scope as default impl path. + + For example, in the following macro invocation + ```rust + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Runtime { + ... + } + ``` + the trait `DefaultConfig` lies within the `frame_system` scope and `TestDefaultConfig` impls + the `DefaultConfig` trait. + + Using this information, we can compute the disambiguation path internally, thus removing the + need of an explicit specification: + ```rust + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] + impl frame_system::Config for Runtime { + ... + } + ``` + + In cases where the trait lies outside this scope, we would still need to specify it explicitly, + but this should take care of most (if not all) uses of `derive_impl` within FRAME's context. + +crates: + - name: frame-support-procedural + - name: pallet-default-config-example diff --git a/substrate/frame/examples/default-config/src/lib.rs b/substrate/frame/examples/default-config/src/lib.rs index cd1653e6c76..69eca055965 100644 --- a/substrate/frame/examples/default-config/src/lib.rs +++ b/substrate/frame/examples/default-config/src/lib.rs @@ -149,7 +149,7 @@ pub mod tests { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { // these items are defined by frame-system as `no_default`, so we must specify them here. type Block = Block; diff --git a/substrate/frame/support/procedural/src/derive_impl.rs b/substrate/frame/support/procedural/src/derive_impl.rs index d6d5bf68efd..8740ccd401a 100644 --- a/substrate/frame/support/procedural/src/derive_impl.rs +++ b/substrate/frame/support/procedural/src/derive_impl.rs @@ -172,6 +172,33 @@ fn combine_impls( final_impl } +/// Computes the disambiguation path for the `derive_impl` attribute macro. +/// +/// When specified explicitly using `as [disambiguation_path]` in the macro attr, the +/// disambiguation is used as is. If not, we infer the disambiguation path from the +/// `foreign_impl_path` and the computed scope. +fn compute_disambiguation_path( + disambiguation_path: Option, + foreign_impl: ItemImpl, + default_impl_path: Path, +) -> Result { + match (disambiguation_path, foreign_impl.clone().trait_) { + (Some(disambiguation_path), _) => Ok(disambiguation_path), + (None, Some((_, foreign_impl_path, _))) => + if default_impl_path.segments.len() > 1 { + let scope = default_impl_path.segments.first(); + Ok(parse_quote!(#scope :: #foreign_impl_path)) + } else { + Ok(foreign_impl_path) + }, + _ => Err(syn::Error::new( + default_impl_path.span(), + "Impl statement must have a defined type being implemented \ + for a defined type such as `impl A for B`", + )), + } +} + /// Internal implementation behind [`#[derive_impl(..)]`](`macro@crate::derive_impl`). /// /// `default_impl_path`: the module path of the external `impl` statement whose tokens we are @@ -194,18 +221,11 @@ pub fn derive_impl( let foreign_impl = parse2::(foreign_tokens)?; let default_impl_path = parse2::(default_impl_path)?; - // have disambiguation_path default to the item being impl'd in the foreign impl if we - // don't specify an `as [disambiguation_path]` in the macro attr - let disambiguation_path = match (disambiguation_path, foreign_impl.clone().trait_) { - (Some(disambiguation_path), _) => disambiguation_path, - (None, Some((_, foreign_impl_path, _))) => foreign_impl_path, - _ => - return Err(syn::Error::new( - foreign_impl.span(), - "Impl statement must have a defined type being implemented \ - for a defined type such as `impl A for B`", - )), - }; + let disambiguation_path = compute_disambiguation_path( + disambiguation_path, + foreign_impl.clone(), + default_impl_path.clone(), + )?; // generate the combined impl let combined_impl = combine_impls( @@ -257,3 +277,27 @@ fn test_runtime_type_with_doc() { } } } + +#[test] +fn test_disambugation_path() { + let foreign_impl: ItemImpl = parse_quote!(impl SomeTrait for SomeType {}); + let default_impl_path: Path = parse_quote!(SomeScope::SomeType); + + // disambiguation path is specified + let disambiguation_path = compute_disambiguation_path( + Some(parse_quote!(SomeScope::SomePath)), + foreign_impl.clone(), + default_impl_path.clone(), + ); + assert_eq!(disambiguation_path.unwrap(), parse_quote!(SomeScope::SomePath)); + + // disambiguation path is not specified and the default_impl_path has more than one segment + let disambiguation_path = + compute_disambiguation_path(None, foreign_impl.clone(), default_impl_path.clone()); + assert_eq!(disambiguation_path.unwrap(), parse_quote!(SomeScope::SomeTrait)); + + // disambiguation path is not specified and the default_impl_path has only one segment + let disambiguation_path = + compute_disambiguation_path(None, foreign_impl.clone(), parse_quote!(SomeType)); + assert_eq!(disambiguation_path.unwrap(), parse_quote!(SomeTrait)); +} diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 5840377d722..ed920d6a1da 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -639,6 +639,11 @@ pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream /// default to `A` from the `impl A for B` part of the default impl. This is useful for scenarios /// where all of the relevant types are already in scope via `use` statements. /// +/// In case the `default_impl_path` is scoped to a different module such as +/// `some::path::TestTraitImpl`, the same scope is assumed for the `disambiguation_path`, i.e. +/// `some::A`. This enables the use of `derive_impl` attribute without having to specify the +/// `disambiguation_path` in most (if not all) uses within FRAME's context. +/// /// Conversely, the `default_impl_path` argument is required and cannot be omitted. /// /// Optionally, `no_aggregated_types` can be specified as follows: -- GitLab From b0741d4f78ebc424c7544e1d2d5db7968132e577 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sun, 3 Mar 2024 19:37:41 +1100 Subject: [PATCH 061/188] Finish documenting `#[pallet::xxx]` macros (#2638) Closes https://github.com/paritytech/polkadot-sdk-docs/issues/35 - Moves pallet proc macro docs to `frame_support` - Adds missing docs - Revise revise existing docs, adding compiling doctests where appropriate --------- Co-authored-by: command-bot <> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- Cargo.lock | 1 + docs/sdk/src/guides/your_first_pallet/mod.rs | 20 +- substrate/frame/support/Cargo.toml | 2 + substrate/frame/support/procedural/src/lib.rs | 746 +----- substrate/frame/support/src/lib.rs | 2345 +++++++---------- 5 files changed, 1127 insertions(+), 1987 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c42ec612e6c..ad218001b40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5750,6 +5750,7 @@ dependencies = [ "sp-staking", "sp-state-machine", "sp-std 14.0.0", + "sp-timestamp", "sp-tracing 16.0.0", "sp-weights", "static_assertions", diff --git a/docs/sdk/src/guides/your_first_pallet/mod.rs b/docs/sdk/src/guides/your_first_pallet/mod.rs index 20a8639b270..6a262924824 100644 --- a/docs/sdk/src/guides/your_first_pallet/mod.rs +++ b/docs/sdk/src/guides/your_first_pallet/mod.rs @@ -250,14 +250,16 @@ // of event is probably not the best. //! //! With the explanation out of the way, let's see how these components can be added. Both follow a -//! fairly familiar syntax: normal Rust enums, with an extra `#[frame::event/error]` attribute -//! attached. +//! fairly familiar syntax: normal Rust enums, with extra +//! [`#[frame::event]`](frame::pallet_macros::event) and +//! [`#[frame::error]`](frame::pallet_macros::error) attributes attached. #![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", Event)] #![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", Error)] //! -//! One slightly custom part of this is the `#[pallet::generate_deposit(pub(super) fn -//! deposit_event)]` part. Without going into too much detail, in order for a pallet to emit events -//! to the rest of the system, it needs to do two things: +//! One slightly custom part of this is the [`#[pallet::generate_deposit(pub(super) fn +//! deposit_event)]`](frame::pallet_macros::generate_deposit) part. Without going into too +//! much detail, in order for a pallet to emit events to the rest of the system, it needs to do two +//! things: //! //! 1. Declare a type in its `Config` that refers to the overarching event type of the runtime. In //! short, by doing this, the pallet is expressing an important bound: `type RuntimeEvent: @@ -266,7 +268,8 @@ //! store it where needed. //! //! 2. But, doing this conversion and storing is too much to expect each pallet to define. FRAME -//! provides a default way of storing events, and this is what `pallet::generate_deposit` is doing. +//! provides a default way of storing events, and this is what +//! [`pallet::generate_deposit`](frame::pallet_macros::generate_deposit) is doing. #![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", config_v2)] //! //! > These `Runtime*` types are better explained in @@ -280,8 +283,9 @@ #![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", runtime_v2)] //! //! In this snippet, the actual `RuntimeEvent` type (right hand side of `type RuntimeEvent = -//! RuntimeEvent`) is generated by `construct_runtime`. An interesting way to inspect this type is -//! to see its definition in rust-docs: +//! RuntimeEvent`) is generated by +//! [`construct_runtime`](frame::runtime::prelude::construct_runtime). An interesting way to inspect +//! this type is to see its definition in rust-docs: //! [`crate::guides::your_first_pallet::pallet_v2::tests::runtime_v2::RuntimeEvent`]. //! //! diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml index c19f478c803..fb9cb3d4511 100644 --- a/substrate/frame/support/Cargo.toml +++ b/substrate/frame/support/Cargo.toml @@ -66,6 +66,7 @@ aquamarine = { version = "0.5.0" } [dev-dependencies] assert_matches = "1.3.0" pretty_assertions = "1.2.1" +sp-timestamp = { path = "../../primitives/timestamp", default-features = false } frame-system = { path = "../system" } sp-crypto-hashing = { path = "../../primitives/crypto/hashing" } @@ -96,6 +97,7 @@ std = [ "sp-std/std", "sp-tracing/std", "sp-weights/std", + "sp-timestamp/std" ] runtime-benchmarks = [ "frame-system/runtime-benchmarks", diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index ed920d6a1da..036da52a7ba 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -188,133 +188,11 @@ pub fn construct_runtime(input: TokenStream) -> TokenStream { construct_runtime::construct_runtime(input) } -/// The pallet struct placeholder `#[pallet::pallet]` is mandatory and allows you to specify -/// pallet information. /// -/// The struct must be defined as follows: -/// ```ignore -/// #[pallet::pallet] -/// pub struct Pallet(_); -/// ``` -/// I.e. a regular struct definition named `Pallet`, with generic T and no where clause. -/// -/// ## Macro expansion: -/// -/// The macro adds this attribute to the struct definition: -/// ```ignore -/// #[derive( -/// frame_support::CloneNoBound, -/// frame_support::EqNoBound, -/// frame_support::PartialEqNoBound, -/// frame_support::RuntimeDebugNoBound, -/// )] -/// ``` -/// and replaces the type `_` with `PhantomData`. It also implements on the pallet: -/// * `GetStorageVersion` -/// * `OnGenesis`: contains some logic to write the pallet version into storage. -/// * `PalletErrorTypeInfo`: provides the type information for the pallet error, if defined. -/// -/// It declares `type Module` type alias for `Pallet`, used by `construct_runtime`. -/// -/// It implements `PalletInfoAccess` on `Pallet` to ease access to pallet information given by -/// `frame_support::traits::PalletInfo`. (The implementation uses the associated type -/// `frame_system::Config::PalletInfo`). -/// -/// It implements `StorageInfoTrait` on `Pallet` which give information about all storages. -/// -/// If the attribute `generate_store` is set then the macro creates the trait `Store` and -/// implements it on `Pallet`. -/// -/// If the attribute `set_storage_max_encoded_len` is set then the macro calls -/// `StorageInfoTrait` for each storage in the implementation of `StorageInfoTrait` for the -/// pallet. Otherwise it implements `StorageInfoTrait` for the pallet using the -/// `PartialStorageInfoTrait` implementation of storages. -/// -/// ## Dev Mode (`#[pallet(dev_mode)]`) -/// -/// Specifying the argument `dev_mode` will allow you to enable dev mode for a pallet. The aim -/// of dev mode is to loosen some of the restrictions and requirements placed on production -/// pallets for easy tinkering and development. Dev mode pallets should not be used in -/// production. Enabling dev mode has the following effects: -/// -/// * Weights no longer need to be specified on every `#[pallet::call]` declaration. By default, dev -/// mode pallets will assume a weight of zero (`0`) if a weight is not specified. This is -/// equivalent to specifying `#[weight(0)]` on all calls that do not specify a weight. -/// * Call indices no longer need to be specified on every `#[pallet::call]` declaration. By -/// default, dev mode pallets will assume a call index based on the order of the call. -/// * All storages are marked as unbounded, meaning you do not need to implement `MaxEncodedLen` on -/// storage types. This is equivalent to specifying `#[pallet::unbounded]` on all storage type -/// definitions. -/// * Storage hashers no longer need to be specified and can be replaced by `_`. In dev mode, these -/// will be replaced by `Blake2_128Concat`. In case of explicit key-binding, `Hasher` can simply -/// be ignored when in `dev_mode`. -/// -/// Note that the `dev_mode` argument can only be supplied to the `#[pallet]` or -/// `#[frame_support::pallet]` attribute macro that encloses your pallet module. This argument -/// cannot be specified anywhere else, including but not limited to the `#[pallet::pallet]` -/// attribute macro. -/// -///
-/// WARNING:
-/// You should not deploy or use dev mode pallets in production. Doing so can break your chain
-/// and therefore should never be done. Once you are done tinkering, you should remove the
-/// 'dev_mode' argument from your #[pallet] declaration and fix any compile errors before
-/// attempting to use your pallet in a production scenario.
-/// 
-/// -/// See `frame_support::pallet` docs for more info. -/// -/// ## Runtime Metadata Documentation -/// -/// The documentation added to this pallet is included in the runtime metadata. -/// -/// The documentation can be defined in the following ways: -/// -/// ```ignore -/// #[pallet::pallet] -/// /// Documentation for pallet 1 -/// #[doc = "Documentation for pallet 2"] -/// #[doc = include_str!("../README.md")] -/// #[pallet_doc("../doc1.md")] -/// #[pallet_doc("../doc2.md")] -/// pub mod pallet {} -/// ``` -/// -/// The runtime metadata for this pallet contains the following -/// - " Documentation for pallet 1" (captured from `///`) -/// - "Documentation for pallet 2" (captured from `#[doc]`) -/// - content of ../README.md (captured from `#[doc]` with `include_str!`) -/// - content of "../doc1.md" (captured from `pallet_doc`) -/// - content of "../doc2.md" (captured from `pallet_doc`) -/// -/// ### `doc` attribute -/// -/// The value of the `doc` attribute is included in the runtime metadata, as well as -/// expanded on the pallet module. The previous example is expanded to: -/// -/// ```ignore -/// /// Documentation for pallet 1 -/// /// Documentation for pallet 2 -/// /// Content of README.md -/// pub mod pallet {} -/// ``` -/// -/// If you want to specify the file from which the documentation is loaded, you can use the -/// `include_str` macro. However, if you only want the documentation to be included in the -/// runtime metadata, use the `pallet_doc` attribute. -/// -/// ### `pallet_doc` attribute -/// -/// Unlike the `doc` attribute, the documentation provided to the `pallet_doc` attribute is -/// not inserted on the module. -/// -/// The `pallet_doc` attribute can only be provided with one argument, -/// which is the file path that holds the documentation to be added to the metadata. +/// --- /// -/// This approach is beneficial when you use the `include_str` macro at the beginning of the file -/// and want that documentation to extend to the runtime metadata, without reiterating the -/// documentation on the pallet module itself. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet`. #[proc_macro_attribute] pub fn pallet(attr: TokenStream, item: TokenStream) -> TokenStream { pallet::pallet(attr, item) @@ -408,19 +286,28 @@ pub fn transactional(attr: TokenStream, input: TokenStream) -> TokenStream { transactional::transactional(attr, input).unwrap_or_else(|e| e.to_compile_error().into()) } +/// +/// --- +/// +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::require_transactional`. #[proc_macro_attribute] pub fn require_transactional(attr: TokenStream, input: TokenStream) -> TokenStream { transactional::require_transactional(attr, input) .unwrap_or_else(|e| e.to_compile_error().into()) } -/// Derive [`Clone`] but do not bound any generic. Docs are at `frame_support::CloneNoBound`. +/// Derive [`Clone`] but do not bound any generic. +/// +/// Docs at `frame_support::CloneNoBound`. #[proc_macro_derive(CloneNoBound)] pub fn derive_clone_no_bound(input: TokenStream) -> TokenStream { no_bound::clone::derive_clone_no_bound(input) } -/// Derive [`Debug`] but do not bound any generics. Docs are at `frame_support::DebugNoBound`. +/// Derive [`Debug`] but do not bound any generics. +/// +/// Docs at `frame_support::DebugNoBound`. #[proc_macro_derive(DebugNoBound)] pub fn derive_debug_no_bound(input: TokenStream) -> TokenStream { no_bound::debug::derive_debug_no_bound(input) @@ -452,14 +339,17 @@ pub fn derive_runtime_debug_no_bound(input: TokenStream) -> TokenStream { } } -/// Derive [`PartialEq`] but do not bound any generic. Docs are at -/// `frame_support::PartialEqNoBound`. +/// Derive [`PartialEq`] but do not bound any generic. +/// +/// Docs at `frame_support::PartialEqNoBound`. #[proc_macro_derive(PartialEqNoBound)] pub fn derive_partial_eq_no_bound(input: TokenStream) -> TokenStream { no_bound::partial_eq::derive_partial_eq_no_bound(input) } -/// Derive [`Eq`] but do no bound any generic. Docs are at `frame_support::EqNoBound`. +/// DeriveEq but do no bound any generic. +/// +/// Docs at `frame_support::EqNoBound`. #[proc_macro_derive(EqNoBound)] pub fn derive_eq_no_bound(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); @@ -494,6 +384,7 @@ pub fn derive_default_no_bound(input: TokenStream) -> TokenStream { no_bound::default::derive_default_no_bound(input) } +/// Macro used internally in FRAME to generate the crate version for a pallet. #[proc_macro] pub fn crate_to_crate_version(input: TokenStream) -> TokenStream { crate_version::crate_to_crate_version(input) @@ -555,42 +446,11 @@ pub fn __create_tt_macro(input: TokenStream) -> TokenStream { tt_macro::create_tt_return_macro(input) } -/// Allows accessing on-chain pallet storage that is no longer accessible via the pallet. -/// -/// This is especially useful when writing storage migrations, when types of storage items are -/// modified or outright removed, but the previous definition is required to perform the migration. /// -/// ## Example -/// -/// Imagine a pallet with the following storage definition: -/// ```ignore -/// #[pallet::storage] -/// pub type Value = StorageValue<_, u32>; -/// ``` -/// `Value` can be accessed by calling `Value::::get()`. -/// -/// Now imagine the definition of `Value` is updated to a `(u32, u32)`: -/// ```ignore -/// #[pallet::storage] -/// pub type Value = StorageValue<_, (u32, u32)>; -/// ``` -/// The on-chain value of `Value` is `u32`, but `Value::::get()` expects it to be `(u32, u32)`. -/// -/// In this instance the developer must write a storage migration to reading the old value of -/// `Value` and writing it back to storage in the new format, so that the on-chain storage layout is -/// consistent with what is defined in the pallet. -/// -/// We can read the old v0 value of `Value` in the migration by creating a `storage_alias`: -/// ```ignore -/// pub(crate) mod v0 { -/// use super::*; -/// -/// #[storage_alias] -/// pub type Value = StorageValue, u32>; -/// } -/// ``` +/// --- /// -/// The developer can now access the old value of `Value` by calling `v0::Value::::get()`. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::storage_alias`. #[proc_macro_attribute] pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream { storage_alias::storage_alias(attributes.into(), input.into()) @@ -826,24 +686,21 @@ pub fn derive_impl(attrs: TokenStream, input: TokenStream) -> TokenStream { .into() } -/// The optional attribute `#[pallet::no_default]` can be attached to trait items within a -/// `Config` trait impl that has [`#[pallet::config(with_default)]`](`macro@config`) attached. /// -/// Attaching this attribute to a trait item ensures that that trait item will not be used as a -/// default with the [`#[derive_impl(..)]`](`macro@derive_impl`) attribute macro. +/// --- +/// +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::no_default`. #[proc_macro_attribute] pub fn no_default(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The optional attribute `#[pallet::no_default_bounds]` can be attached to trait items within a -/// `Config` trait impl that has [`#[pallet::config(with_default)]`](`macro@config`) attached. /// -/// Attaching this attribute to a trait item ensures that the generated trait `DefaultConfig` -/// will not have any bounds for this trait item. +/// --- /// -/// As an example, if you have a trait item `type AccountId: SomeTrait;` in your `Config` trait, -/// the generated `DefaultConfig` will only have `type AccountId;` with no trait bound. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::no_default_bounds`. #[proc_macro_attribute] pub fn no_default_bounds(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -923,6 +780,11 @@ pub fn register_default_impl(attrs: TokenStream, tokens: TokenStream) -> TokenSt } } +/// +/// --- +/// +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_prelude::inject_runtime_type`. #[proc_macro_attribute] pub fn inject_runtime_type(_: TokenStream, tokens: TokenStream) -> TokenStream { let item = tokens.clone(); @@ -956,75 +818,11 @@ fn pallet_macro_stub() -> TokenStream { .into() } -/// The mandatory attribute `#[pallet::config]` defines the configurable options for the pallet. -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::config] -/// pub trait Config: frame_system::Config + $optionally_some_other_supertraits -/// $optional_where_clause -/// { -/// ... -/// } -/// ``` -/// -/// I.e. a regular trait definition named `Config`, with the supertrait -/// `frame_system::pallet::Config`, and optionally other supertraits and a where clause. -/// (Specifying other supertraits here is known as [tight -/// coupling](https://docs.substrate.io/reference/how-to-guides/pallet-design/use-tight-coupling/)) -/// -/// The associated type `RuntimeEvent` is reserved. If defined, it must have the bounds -/// `From` and `IsType<::RuntimeEvent>`. /// -/// [`pallet::event`](`macro@event`) must be present if `RuntimeEvent` exists as a config item -/// in your `#[pallet::config]`. -/// -/// ## Optional: `with_default` -/// -/// An optional `with_default` argument may also be specified. Doing so will automatically -/// generate a `DefaultConfig` trait inside your pallet which is suitable for use with -/// [`[#[derive_impl(..)]`](`macro@derive_impl`) to derive a default testing config: -/// -/// ```ignore -/// #[pallet::config(with_default)] -/// pub trait Config: frame_system::Config { -/// type RuntimeEvent: Parameter -/// + Member -/// + From> -/// + Debug -/// + IsType<::RuntimeEvent>; -/// -/// #[pallet::no_default] -/// type BaseCallFilter: Contains; -/// // ... -/// } -/// ``` -/// -/// As shown above, you may also attach the [`#[pallet::no_default]`](`macro@no_default`) -/// attribute to specify that a particular trait item _cannot_ be used as a default when a test -/// `Config` is derived using the [`#[derive_impl(..)]`](`macro@derive_impl`) attribute macro. -/// This will cause that particular trait item to simply not appear in default testing configs -/// based on this config (the trait item will not be included in `DefaultConfig`). -/// -/// ### `DefaultConfig` Caveats -/// -/// The auto-generated `DefaultConfig` trait: -/// - is always a _subset_ of your pallet's `Config` trait. -/// - can only contain items that don't rely on externalities, such as `frame_system::Config`. -/// -/// Trait items that _do_ rely on externalities should be marked with -/// [`#[pallet::no_default]`](`macro@no_default`) -/// -/// Consequently: -/// - Any items that rely on externalities _must_ be marked with -/// [`#[pallet::no_default]`](`macro@no_default`) or your trait will fail to compile when used -/// with [`derive_impl`](`macro@derive_impl`). -/// - Items marked with [`#[pallet::no_default]`](`macro@no_default`) are entirely excluded from the -/// `DefaultConfig` trait, and therefore any impl of `DefaultConfig` doesn't need to implement -/// such items. +/// --- /// -/// For more information, see [`macro@derive_impl`]. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::config`. #[proc_macro_attribute] pub fn config(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -1033,7 +831,7 @@ pub fn config(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// Rust-Analyzer Users: Documentation for this macro can be found at /// `frame_support::pallet_macros::constant`. #[proc_macro_attribute] pub fn constant(_: TokenStream, _: TokenStream) -> TokenStream { @@ -1043,106 +841,58 @@ pub fn constant(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// Rust-Analyzer Users: Documentation for this macro can be found at /// `frame_support::pallet_macros::constant_name`. #[proc_macro_attribute] pub fn constant_name(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// To bypass the `frame_system::Config` supertrait check, use the attribute -/// `pallet::disable_frame_system_supertrait_check`, e.g.: /// -/// ```ignore -/// #[pallet::config] -/// #[pallet::disable_frame_system_supertrait_check] -/// pub trait Config: pallet_timestamp::Config {} -/// ``` +/// --- /// -/// NOTE: Bypassing the `frame_system::Config` supertrait check is typically desirable when you -/// want to write an alternative to the `frame_system` pallet. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::disable_frame_system_supertrait_check`. #[proc_macro_attribute] pub fn disable_frame_system_supertrait_check(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// To generate a `Store` trait associating all storages, annotate your `Pallet` struct with -/// the attribute `#[pallet::generate_store($vis trait Store)]`, e.g.: -/// -/// ```ignore -/// #[pallet::pallet] -/// #[pallet::generate_store(pub(super) trait Store)] -/// pub struct Pallet(_); -/// ``` -/// More precisely, the `Store` trait contains an associated type for each storage. It is -/// implemented for `Pallet` allowing access to the storage from pallet struct. /// -/// Thus when defining a storage named `Foo`, it can later be accessed from `Pallet` using -/// `::Foo`. +/// --- /// -/// NOTE: this attribute is only valid when applied _directly_ to your `Pallet` struct -/// definition. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::generate_store`. #[proc_macro_attribute] pub fn generate_store(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// Because the `pallet::pallet` macro implements `GetStorageVersion`, the current storage -/// version needs to be communicated to the macro. This can be done by using the -/// `pallet::storage_version` attribute: -/// -/// ```ignore -/// const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); /// -/// #[pallet::pallet] -/// #[pallet::storage_version(STORAGE_VERSION)] -/// pub struct Pallet(_); -/// ``` +/// --- /// -/// If not present, the in-code storage version is set to the default value. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::storage_version`. #[proc_macro_attribute] pub fn storage_version(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The `#[pallet::hooks]` attribute allows you to specify a `Hooks` implementation for -/// `Pallet` that specifies pallet-specific logic. /// -/// The item the attribute attaches to must be defined as follows: -/// ```ignore -/// #[pallet::hooks] -/// impl Hooks> for Pallet $optional_where_clause { -/// ... -/// } -/// ``` -/// I.e. a regular trait implementation with generic bound: `T: Config`, for the trait -/// `Hooks>` (they are defined in preludes), for the type `Pallet` and -/// with an optional where clause. -/// -/// If no `#[pallet::hooks]` exists, then the following default implementation is -/// automatically generated: -/// ```ignore -/// #[pallet::hooks] -/// impl Hooks> for Pallet {} -/// ``` -/// -/// ## Macro expansion -/// -/// The macro implements the traits `OnInitialize`, `OnIdle`, `OnFinalize`, `OnRuntimeUpgrade`, -/// `OffchainWorker`, and `IntegrityTest` using the provided `Hooks` implementation. -/// -/// NOTE: `OnRuntimeUpgrade` is implemented with `Hooks::on_runtime_upgrade` and some -/// additional logic. E.g. logic to write the pallet version into storage. +/// --- /// -/// NOTE: The macro also adds some tracing logic when implementing the above traits. The -/// following hooks emit traces: `on_initialize`, `on_finalize` and `on_runtime_upgrade`. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::hooks`. #[proc_macro_attribute] pub fn hooks(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// Each dispatchable needs to define a weight with `#[pallet::weight($expr)]` attribute, the -/// first argument must be `origin: OriginFor`. +/// +/// --- +/// +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::weight`. #[proc_macro_attribute] pub fn weight(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -1151,8 +901,8 @@ pub fn weight(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in -/// [`frame_support::pallet_macros::call`](../../frame_support/pallet_macros/attr.call.html). +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::compact`. #[proc_macro_attribute] pub fn compact(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -1161,8 +911,8 @@ pub fn compact(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in -/// [`frame_support::pallet_macros::call`](../../frame_support/pallet_macros/attr.call.html). +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::call`. #[proc_macro_attribute] pub fn call(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -1173,164 +923,60 @@ pub fn call(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in -/// [`frame_support::pallet_macros::call`](../../frame_support/pallet_macros/attr.call.html). +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::call_index`. #[proc_macro_attribute] pub fn call_index(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// Each dispatchable may be annotated with the `#[pallet::feeless_if($closure)]` attribute, -/// which explicitly defines the condition for the dispatchable to be feeless. -/// -/// The arguments for the closure must be the referenced arguments of the dispatchable function. -/// -/// The closure must return `bool`. -/// -/// ### Example -/// ```ignore -/// #[pallet::feeless_if(|_origin: &OriginFor, something: &u32| -> bool { -/// *something == 0 -/// })] -/// pub fn do_something(origin: OriginFor, something: u32) -> DispatchResult { -/// .... -/// } -/// ``` /// -/// Please note that this only works for signed dispatchables and requires a signed extension -/// such as `SkipCheckIfFeeless` as defined in `pallet-skip-feeless-payment` to wrap the existing -/// payment extension. Else, this is completely ignored and the dispatchable is still charged. +/// --- /// -/// ### Macro expansion +/// Rust-Analyzer Users: Documentation for this macro can be found at /// -/// The macro implements the `CheckIfFeeless` trait on the dispatchable and calls the corresponding -/// closure in the implementation. +/// `frame_support::pallet_macros::feeless_if`. #[proc_macro_attribute] pub fn feeless_if(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// Allows you to define some extra constants to be added into constant metadata. /// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::extra_constants] -/// impl Pallet where $optional_where_clause { -/// /// $some_doc -/// $vis fn $fn_name() -> $some_return_type { -/// ... -/// } -/// ... -/// } -/// ``` -/// I.e. a regular rust `impl` block with some optional where clause and functions with 0 args, -/// 0 generics, and some return type. +/// --- /// -/// ## Macro expansion +/// Rust-Analyzer Users: Documentation for this macro can be found at /// -/// The macro add some extra constants to pallet constant metadata. +/// `frame_support::pallet_macros::extra_constants`. #[proc_macro_attribute] pub fn extra_constants(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The `#[pallet::error]` attribute allows you to define an error enum that will be returned -/// from the dispatchable when an error occurs. The information for this error type is then -/// stored in metadata. -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::error] -/// pub enum Error { -/// /// $some_optional_doc -/// $SomeFieldLessVariant, -/// /// $some_more_optional_doc -/// $SomeVariantWithOneField(FieldType), -/// ... -/// } -/// ``` -/// I.e. a regular enum named `Error`, with generic `T` and fieldless or multiple-field -/// variants. /// -/// Any field type in the enum variants must implement `TypeInfo` in order to be properly used -/// in the metadata, and its encoded size should be as small as possible, preferably 1 byte in -/// size in order to reduce storage size. The error enum itself has an absolute maximum encoded -/// size specified by `MAX_MODULE_ERROR_ENCODED_SIZE`. -/// -/// (1 byte can still be 256 different errors. The more specific the error, the easier it is to -/// diagnose problems and give a better experience to the user. Don't skimp on having lots of -/// individual error conditions.) -/// -/// Field types in enum variants must also implement `PalletError`, otherwise the pallet will -/// fail to compile. Rust primitive types have already implemented the `PalletError` trait -/// along with some commonly used stdlib types such as [`Option`] and `PhantomData`, and hence -/// in most use cases, a manual implementation is not necessary and is discouraged. -/// -/// The generic `T` must not bound anything and a `where` clause is not allowed. That said, -/// bounds and/or a where clause should not needed for any use-case. -/// -/// ## Macro expansion -/// -/// The macro implements the [`Debug`] trait and functions `as_u8` using variant position, and -/// `as_str` using variant doc. +/// --- /// -/// The macro also implements `From>` for `&'static str` and `From>` for -/// `DispatchError`. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::error`. #[proc_macro_attribute] pub fn error(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The `#[pallet::event]` attribute allows you to define pallet events. Pallet events are -/// stored under the `system` / `events` key when the block is applied (and then replaced when -/// the next block writes it's events). /// -/// The Event enum must be defined as follows: -/// -/// ```ignore -/// #[pallet::event] -/// #[pallet::generate_deposit($visibility fn deposit_event)] // Optional -/// pub enum Event<$some_generic> $optional_where_clause { -/// /// Some doc -/// $SomeName($SomeType, $YetanotherType, ...), -/// ... -/// } -/// ``` -/// -/// I.e. an enum (with named or unnamed fields variant), named `Event`, with generic: none or -/// `T` or `T: Config`, and optional w here clause. +/// --- /// -/// Each field must implement [`Clone`], [`Eq`], [`PartialEq`], `Encode`, `Decode`, and -/// [`Debug`] (on std only). For ease of use, bound by the trait `Member`, available in -/// `frame_support::pallet_prelude`. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::event`. #[proc_macro_attribute] pub fn event(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The attribute `#[pallet::generate_deposit($visibility fn deposit_event)]` generates a -/// helper function on `Pallet` that handles deposit events. /// -/// NOTE: For instantiable pallets, the event must be generic over `T` and `I`. -/// -/// ## Macro expansion -/// -/// The macro will add on enum `Event` the attributes: -/// * `#[derive(frame_support::CloneNoBound)]` -/// * `#[derive(frame_support::EqNoBound)]` -/// * `#[derive(frame_support::PartialEqNoBound)]` -/// * `#[derive(frame_support::RuntimeDebugNoBound)]` -/// * `#[derive(codec::Encode)]` -/// * `#[derive(codec::Decode)]` -/// -/// The macro implements `From>` for (). -/// -/// The macro implements a metadata function on `Event` returning the `EventMetadata`. +/// --- /// -/// If `#[pallet::generate_deposit]` is present then the macro implements `fn deposit_event` on -/// `Pallet`. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::generate_deposit`. #[proc_macro_attribute] pub fn generate_deposit(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -1339,124 +985,68 @@ pub fn generate_deposit(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// Rust-Analyzer Users: Documentation for this macro can be found at /// `frame_support::pallet_macros::storage`. #[proc_macro_attribute] pub fn storage(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The optional attribute `#[pallet::getter(fn $my_getter_fn_name)]` allows you to define a -/// getter function on `Pallet`. /// -/// Also see [`pallet::storage`](`macro@storage`) +/// --- +/// +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::getter`. #[proc_macro_attribute] pub fn getter(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The optional attribute `#[pallet::storage_prefix = "SomeName"]` allows you to define the -/// storage prefix to use. This is helpful if you wish to rename the storage field but don't -/// want to perform a migration. -/// -/// E.g: /// -/// ```ignore -/// #[pallet::storage] -/// #[pallet::storage_prefix = "foo"] -/// #[pallet::getter(fn my_storage)] -/// pub(super) type MyStorage = StorageMap; -/// ``` -/// -/// or +/// --- /// -/// ```ignore -/// #[pallet::storage] -/// #[pallet::getter(fn my_storage)] -/// pub(super) type MyStorage = StorageMap<_, Blake2_128Concat, u32, u32>; -/// ``` +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::storage_prefix`. #[proc_macro_attribute] pub fn storage_prefix(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The optional attribute `#[pallet::unbounded]` declares the storage as unbounded. When -/// implementating the storage info (when `#[pallet::generate_storage_info]` is specified on -/// the pallet struct placeholder), the size of the storage will be declared as unbounded. This -/// can be useful for storage which can never go into PoV (Proof of Validity). +/// +/// --- +/// +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::unbounded`. #[proc_macro_attribute] pub fn unbounded(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The optional attribute `#[pallet::whitelist_storage]` will declare the -/// storage as whitelisted from benchmarking. Doing so will exclude reads of -/// that value's storage key from counting towards weight calculations during -/// benchmarking. -/// -/// This attribute should only be attached to storages that are known to be -/// read/used in every block. This will result in a more accurate benchmarking weight. /// -/// ### Example -/// ```ignore -/// #[pallet::storage] -/// #[pallet::whitelist_storage] -/// pub(super) type Number = StorageValue<_, frame_system::pallet_prelude::BlockNumberFor::, ValueQuery>; -/// ``` +/// --- /// -/// NOTE: As with all `pallet::*` attributes, this one _must_ be written as -/// `#[pallet::whitelist_storage]` and can only be placed inside a `pallet` module in order for -/// it to work properly. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::whitelist_storage`. #[proc_macro_attribute] pub fn whitelist_storage(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The optional attribute `#[pallet::disable_try_decode_storage]` will declare the -/// storage as whitelisted from decoding during try-runtime checks. This should only be -/// attached to transient storage which cannot be migrated during runtime upgrades. /// -/// ### Example -/// ```ignore -/// #[pallet::storage] -/// #[pallet::disable_try_decode_storage] -/// pub(super) type Events = StorageValue<_, Vec>>, ValueQuery>; -/// ``` +/// --- /// -/// NOTE: As with all `pallet::*` attributes, this one _must_ be written as -/// `#[pallet::disable_try_decode_storage]` and can only be placed inside a `pallet` module in order -/// for it to work properly. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::disable_try_decode_storage`. #[proc_macro_attribute] pub fn disable_try_decode_storage(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The `#[pallet::type_value]` attribute lets you define a struct implementing the `Get` trait -/// to ease the use of storage types. This attribute is meant to be used alongside -/// [`#[pallet::storage]`](`macro@storage`) to define a storage's default value. This attribute -/// can be used multiple times. -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::type_value] -/// fn $MyDefaultName<$some_generic>() -> $default_type $optional_where_clause { $expr } -/// ``` -/// -/// I.e.: a function definition with generics none or `T: Config` and a returned type. -/// -/// E.g.: -/// -/// ```ignore -/// #[pallet::type_value] -/// fn MyDefault() -> T::Balance { 3.into() } -/// ``` /// -/// ## Macro expansion +/// --- /// -/// The macro renames the function to some internal name, generates a struct with the original -/// name of the function and its generic, and implements `Get<$ReturnType>` by calling the user -/// defined function. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::type_value`. #[proc_macro_attribute] pub fn type_value(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -1465,7 +1055,7 @@ pub fn type_value(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// Rust-Analyzer Users: Documentation for this macro can be found at /// `frame_support::pallet_macros::genesis_config`. #[proc_macro_attribute] pub fn genesis_config(_: TokenStream, _: TokenStream) -> TokenStream { @@ -1475,66 +1065,28 @@ pub fn genesis_config(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// Rust-Analyzer Users: Documentation for this macro can be found at /// `frame_support::pallet_macros::genesis_build`. #[proc_macro_attribute] pub fn genesis_build(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The `#[pallet::inherent]` attribute allows the pallet to provide some -/// [inherent](https://docs.substrate.io/fundamentals/transaction-types/#inherent-transactions). -/// An inherent is some piece of data that is inserted by a block authoring node at block -/// creation time and can either be accepted or rejected by validators based on whether the -/// data falls within an acceptable range. -/// -/// The most common inherent is the `timestamp` that is inserted into every block. Since there -/// is no way to validate timestamps, validators simply check that the timestamp reported by -/// the block authoring node falls within an acceptable range. /// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::inherent] -/// impl ProvideInherent for Pallet { -/// // ... regular trait implementation -/// } -/// ``` -/// -/// I.e. a trait implementation with bound `T: Config`, of trait `ProvideInherent` for type -/// `Pallet`, and some optional where clause. -/// -/// ## Macro expansion +/// --- /// -/// The macro currently makes no use of this information, but it might use this information in -/// the future to give information directly to `construct_runtime`. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::inherent`. #[proc_macro_attribute] pub fn inherent(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The `#[pallet::validate_unsigned]` attribute allows the pallet to validate some unsigned -/// transaction: -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::validate_unsigned] -/// impl ValidateUnsigned for Pallet { -/// // ... regular trait implementation -/// } -/// ``` -/// -/// I.e. a trait implementation with bound `T: Config`, of trait `ValidateUnsigned` for type -/// `Pallet`, and some optional where clause. /// -/// NOTE: There is also the `sp_runtime::traits::SignedExtension` trait that can be used to add -/// some specific logic for transaction validation. -/// -/// ## Macro expansion +/// --- /// -/// The macro currently makes no use of this information, but it might use this information in -/// the future to give information directly to `construct_runtime`. +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::validate_unsigned`. #[proc_macro_attribute] pub fn validate_unsigned(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -1543,36 +1095,18 @@ pub fn validate_unsigned(_: TokenStream, _: TokenStream) -> TokenStream { /// /// --- /// -/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// Rust-Analyzer Users: Documentation for this macro can be found at /// `frame_support::pallet_macros::origin`. #[proc_macro_attribute] pub fn origin(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// The `#[pallet::composite_enum]` attribute allows you to define an enum that gets composed as an -/// aggregate enum by `construct_runtime`. This is similar in principle with `#[pallet::event]` and -/// `#[pallet::error]`. /// -/// The attribute currently only supports enum definitions, and identifiers that are named -/// `FreezeReason`, `HoldReason`, `LockId` or `SlashReason`. Arbitrary identifiers for the enum are -/// not supported. The aggregate enum generated by `construct_runtime` will have the name of -/// `RuntimeFreezeReason`, `RuntimeHoldReason`, `RuntimeLockId` and `RuntimeSlashReason` -/// respectively. -/// -/// NOTE: The aggregate enum generated by `construct_runtime` generates a conversion function from -/// the pallet enum to the aggregate enum, and automatically derives the following traits: -/// -/// ```ignore -/// Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, TypeInfo, -/// RuntimeDebug -/// ``` +/// --- /// -/// For ease of usage, when no `#[derive]` attributes are found for the enum under -/// `#[pallet::composite_enum]`, the aforementioned traits are automatically derived for it. The -/// inverse is also true: if there are any `#[derive]` attributes found for the enum, then no traits -/// will automatically be derived for it (this implies that you need to provide the -/// `frame_support::traits::VariantCount` implementation). +/// Rust-Analyzer Users: Documentation for this macro can be found at +/// `frame_support::pallet_macros::composite_enum`. #[proc_macro_attribute] pub fn composite_enum(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() @@ -1628,25 +1162,11 @@ pub fn task_index(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } -/// Can be attached to a module. Doing so will declare that module as importable into a pallet -/// via [`#[import_section]`](`macro@import_section`). -/// -/// Note that sections are imported by their module name/ident, and should be referred to by -/// their _full path_ from the perspective of the target pallet. Do not attempt to make use -/// of `use` statements to bring pallet sections into scope, as this will not work (unless -/// you do so as part of a wildcard import, in which case it will work). -/// -/// ## Naming Logistics /// -/// Also note that because of how `#[pallet_section]` works, pallet section names must be -/// globally unique _within the crate in which they are defined_. For more information on -/// why this must be the case, see macro_magic's -/// [`#[export_tokens]`](https://docs.rs/macro_magic/latest/macro_magic/attr.export_tokens.html) macro. +/// --- /// -/// Optionally, you may provide an argument to `#[pallet_section]` such as -/// `#[pallet_section(some_ident)]`, in the event that there is another pallet section in -/// same crate with the same ident/name. The ident you specify can then be used instead of -/// the module's ident name when you go to import it via `#[import_section]`. +/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// `frame_support::pallet_macros::pallet_section`. #[proc_macro_attribute] pub fn pallet_section(attr: TokenStream, tokens: TokenStream) -> TokenStream { let tokens_clone = tokens.clone(); @@ -1660,39 +1180,11 @@ pub fn pallet_section(attr: TokenStream, tokens: TokenStream) -> TokenStream { } } -/// An attribute macro that can be attached to a module declaration. Doing so will -/// Imports the contents of the specified external pallet section that was defined -/// previously using [`#[pallet_section]`](`macro@pallet_section`). /// -/// ## Example -/// ```ignore -/// #[import_section(some_section)] -/// #[pallet] -/// pub mod pallet { -/// // ... -/// } -/// ``` -/// where `some_section` was defined elsewhere via: -/// ```ignore -/// #[pallet_section] -/// pub mod some_section { -/// // ... -/// } -/// ``` -/// -/// This will result in the contents of `some_section` being _verbatim_ imported into -/// the pallet above. Note that since the tokens for `some_section` are essentially -/// copy-pasted into the target pallet, you cannot refer to imports that don't also -/// exist in the target pallet, but this is easily resolved by including all relevant -/// `use` statements within your pallet section, so they are imported as well, or by -/// otherwise ensuring that you have the same imports on the target pallet. -/// -/// It is perfectly permissible to import multiple pallet sections into the same pallet, -/// which can be done by having multiple `#[import_section(something)]` attributes -/// attached to the pallet. +/// --- /// -/// Note that sections are imported by their module name/ident, and should be referred to by -/// their _full path_ from the perspective of the target pallet. +/// **Rust-Analyzer users**: See the documentation of the Rust item in +/// `frame_support::pallet_macros::import_section`. #[import_tokens_attr { format!( "{}::macro_magic", diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index d2d9a33053f..caf9457d666 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -900,18 +900,20 @@ pub mod pallet_prelude { }; pub use codec::{Decode, Encode, MaxEncodedLen}; pub use frame_support::pallet_macros::*; + /// The optional attribute `#[inject_runtime_type]` can be attached to `RuntimeCall`, /// `RuntimeEvent`, `RuntimeOrigin` or `PalletInfo` in an impl statement that has /// `#[register_default_impl]` attached to indicate that this item is generated by /// `construct_runtime`. /// /// Attaching this attribute to such an item ensures that the combined impl generated via - /// [`#[derive_impl(..)]`](`macro@super::derive_impl`) will use the correct type - /// auto-generated by `construct_runtime!`. + /// [`#[derive_impl(..)]`](`frame_support::derive_impl`) will use the correct + /// type auto-generated by + /// `construct_runtime!`. #[doc = docify::embed!("src/tests/inject_runtime_type.rs", derive_impl_works_with_runtime_type_injection)] /// /// However, if `no_aggregated_types` is specified while using - /// `[`#[derive_impl(..)]`](`macro@super::derive_impl`)`, then these items are attached + /// `[`#[derive_impl(..)]`](`frame_support::derive_impl`)`, then these items are attached /// verbatim to the combined impl. #[doc = docify::embed!("src/tests/inject_runtime_type.rs", derive_impl_works_with_no_aggregated_types)] pub use frame_support_procedural::inject_runtime_type; @@ -931,130 +933,26 @@ pub mod pallet_prelude { pub use sp_weights::Weight; } -/// The `pallet` attribute macro defines a pallet that can be used with -/// [`construct_runtime!`]. It must be attached to a module named `pallet` as follows: +/// The pallet struct placeholder `#[pallet::pallet]` is mandatory and allows you to +/// specify pallet information. /// -/// ```ignore -/// #[pallet] -/// pub mod pallet { -/// ... -/// } +/// The struct must be defined as follows: /// ``` +/// #[frame_support::pallet] +/// mod pallet { +/// #[pallet::pallet] // <- the macro +/// pub struct Pallet(_); // <- the struct definition /// -/// Note that various types can be automatically imported using -/// [`frame_support::pallet_prelude`] and `frame_system::pallet_prelude`: -/// -/// ```ignore -/// #[pallet] -/// pub mod pallet { -/// use frame_support::pallet_prelude::*; -/// use frame_system::pallet_prelude::*; -/// ... +/// #[pallet::config] +/// pub trait Config: frame_system::Config {} /// } /// ``` /// -/// # pallet::* Attributes -/// -/// The `pallet` macro will parse any items within your `pallet` module that are annotated with -/// `#[pallet::*]` attributes. Some of these attributes are mandatory and some are optional, -/// and they can attach to different types of items within your pallet depending on the -/// attribute in question. The full list of `#[pallet::*]` attributes is shown below in the -/// order in which they are mentioned in this document: -/// -/// * [`pallet::pallet`](#pallet-struct-placeholder-palletpallet-mandatory) -/// * [`pallet::config`](#config-trait-palletconfig-mandatory) -/// * [`pallet::constant`](#palletconstant) -/// * [`pallet::disable_frame_system_supertrait_check`](#disable_supertrait_check) -/// * [`pallet::generate_store($vis trait Store)`](#palletgenerate_storevis-trait-store) -/// * [`pallet::storage_version`](#palletstorage_version) -/// * [`pallet::hooks`](#hooks-pallethooks-optional) -/// * [`pallet::call`](#call-palletcall-optional) -/// * [`pallet::weight($expr)`](#palletweightexpr) -/// * [`pallet::compact`](#palletcompact-some_arg-some_type) -/// * [`pallet::call_index($idx)`](#palletcall_indexidx) -/// * [`pallet::extra_constants`](#extra-constants-palletextra_constants-optional) -/// * [`pallet::error`](#error-palleterror-optional) -/// * [`pallet::event`](#event-palletevent-optional) -/// * [`pallet::generate_deposit($visibility fn -/// deposit_event)`](#palletgenerate_depositvisibility-fn-deposit_event) -/// * [`pallet::storage`](#storage-palletstorage-optional) -/// * [`pallet::getter(fn $my_getter_fn_name)`](#palletgetterfn-my_getter_fn_name-optional) -/// * [`pallet::storage_prefix = "SomeName"`](#palletstorage_prefix--somename-optional) -/// * [`pallet::unbounded`](#palletunbounded-optional) -/// * [`pallet::whitelist_storage`](#palletwhitelist_storage-optional) -/// * [`pallet::disable_try_decode_storage`](#palletdisable_try_decode_storage-optional) -/// * [`cfg(..)`](#cfg-for-storage) (on storage items) -/// * [`pallet::type_value`](#type-value-pallettype_value-optional) -/// * [`pallet::genesis_config`](#genesis-config-palletgenesis_config-optional) -/// * [`pallet::genesis_build`](#genesis-build-palletgenesis_build-optional) -/// * [`pallet::inherent`](#inherent-palletinherent-optional) -/// * [`pallet::validate_unsigned`](#validate-unsigned-palletvalidate_unsigned-optional) -/// * [`pallet::origin`](#origin-palletorigin-optional) -/// * [`pallet::composite_enum`](#composite-enum-palletcomposite_enum-optional) -/// -/// Note that at compile-time, the `#[pallet]` macro will analyze and expand all of these -/// attributes, ultimately removing their AST nodes before they can be parsed as real -/// attribute macro calls. This means that technically we do not need attribute macro -/// definitions for any of these attributes, however, for consistency and discoverability -/// reasons, we still maintain stub attribute macro definitions for all of these attributes in -/// the [`pallet_macros`] module which is automatically included in all pallets as part of the -/// pallet prelude. The actual "work" for all of these attribute macros can be found in the -/// macro expansion for `#[pallet]`. -/// -/// Also note that in this document, pallet attributes are explained using the syntax of -/// non-instantiable pallets. For an example of an instantiable pallet, see [this -/// example](#example-of-an-instantiable-pallet). -/// -/// # Dev Mode (`#[pallet(dev_mode)]`) -/// -/// Specifying the argument `dev_mode` on the `#[pallet]` or `#[frame_support::pallet]` -/// attribute attached to your pallet module will allow you to enable dev mode for a pallet. -/// The aim of dev mode is to loosen some of the restrictions and requirements placed on -/// production pallets for easy tinkering and development. Dev mode pallets should not be used -/// in production. Enabling dev mode has the following effects: -/// -/// * Weights no longer need to be specified on every `#[pallet::call]` declaration. By -/// default, dev mode pallets will assume a weight of zero (`0`) if a weight is not -/// specified. This is equivalent to specifying `#[weight(0)]` on all calls that do not -/// specify a weight. -/// * Call indices no longer need to be specified on every `#[pallet::call]` declaration. By -/// default, dev mode pallets will assume a call index based on the order of the call. -/// * All storages are marked as unbounded, meaning you do not need to implement -/// `MaxEncodedLen` on storage types. This is equivalent to specifying `#[pallet::unbounded]` -/// on all storage type definitions. -/// * Storage hashers no longer need to be specified and can be replaced by `_`. In dev mode, -/// these will be replaced by `Blake2_128Concat`. In case of explicit key-binding, `Hasher` -/// can simply be ignored when in `dev_mode`. -/// -/// Note that the `dev_mode` argument can only be supplied to the `#[pallet]` or -/// `#[frame_support::pallet]` attribute macro that encloses your pallet module. This argument -/// cannot be specified anywhere else, including but not limited to the `#[pallet::pallet]` -/// attribute macro. -/// -///
-/// WARNING:
-/// You should not deploy or use dev mode pallets in production. Doing so can break your chain
-/// and therefore should never be done. Once you are done tinkering, you should remove the
-/// 'dev_mode' argument from your #[pallet] declaration and fix any compile errors before
-/// attempting to use your pallet in a production scenario.
-/// 
-/// -/// # Pallet struct placeholder: `#[pallet::pallet]` (mandatory) -/// -/// The pallet struct placeholder `#[pallet::pallet]` is mandatory and allows you to specify -/// pallet information. -/// -/// The struct must be defined as follows: -/// ```ignore -/// #[pallet::pallet] -/// pub struct Pallet(_); -/// ``` /// I.e. a regular struct definition named `Pallet`, with generic T and no where clause. /// /// ## Macro expansion: /// -/// The macro adds this attribute to the struct definition: +/// The macro adds this attribute to the Pallet struct definition: /// ```ignore /// #[derive( /// frame_support::CloneNoBound, @@ -1063,1233 +961,947 @@ pub mod pallet_prelude { /// frame_support::RuntimeDebugNoBound, /// )] /// ``` -/// and replaces the type `_` with `PhantomData`. It also implements on the pallet: -/// * [`GetStorageVersion`](`traits::GetStorageVersion`) -/// * [`OnGenesis`](`traits::OnGenesis`): contains some logic to write the pallet version into -/// storage. -/// * `PalletErrorTypeInfo`: provides the type information for the pallet error, if defined. -/// -/// It declares `type Module` type alias for `Pallet`, used by `construct_runtime`. +/// and replaces the type `_` with `PhantomData`. /// -/// It implements [`PalletInfoAccess`](`traits::PalletInfoAccess') on `Pallet` to ease access -/// to pallet information given by [`frame_support::traits::PalletInfo`]. (The implementation -/// uses the associated type `frame_system::Config::PalletInfo`). +/// It also implements on the pallet: /// -/// It implements [`StorageInfoTrait`](`traits::StorageInfoTrait`) on `Pallet` which give -/// information about all storages. -/// -/// If the attribute `generate_store` is set then the macro creates the trait `Store` and -/// implements it on `Pallet`. +/// * [`GetStorageVersion`](frame_support::traits::GetStorageVersion) +/// * [`OnGenesis`](frame_support::traits::OnGenesis): contains some logic to write the pallet +/// version into storage. +/// * [`PalletInfoAccess`](frame_support::traits::PalletInfoAccess) to ease access to pallet +/// information given by [`frame_support::traits::PalletInfo`]. (The implementation uses the +/// associated type [`frame_support::traits::PalletInfo`]). +/// * [`StorageInfoTrait`](frame_support::traits::StorageInfoTrait) to give information about +/// storages. /// /// If the attribute `set_storage_max_encoded_len` is set then the macro calls -/// [`StorageInfoTrait`](`traits::StorageInfoTrait`) for each storage in the implementation of -/// [`StorageInfoTrait`](`traits::StorageInfoTrait`) for the pallet. Otherwise it implements -/// [`StorageInfoTrait`](`traits::StorageInfoTrait`) for the pallet using the -/// [`PartialStorageInfoTrait`](`traits::PartialStorageInfoTrait`) implementation of storages. -/// -/// # Config trait: `#[pallet::config]` (mandatory) -/// -/// The mandatory attribute `#[pallet::config]` defines the configurable options for the -/// pallet. -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::config] -/// pub trait Config: frame_system::Config + $optionally_some_other_supertraits -/// $optional_where_clause -/// { -/// ... -/// } -/// ``` -/// -/// I.e. a regular trait definition named `Config`, with the supertrait -/// `frame_system::pallet::Config`, and optionally other supertraits and a where clause. -/// (Specifying other supertraits here is known as [tight -/// coupling](https://docs.substrate.io/reference/how-to-guides/pallet-design/use-tight-coupling/)) -/// -/// The associated type `RuntimeEvent` is reserved. If defined, it must have the bounds -/// `From` and `IsType<::RuntimeEvent>`. -/// -/// [`pallet::event`](`frame_support::pallet_macros::event`) must be present if `RuntimeEvent` -/// exists as a config item in your `#[pallet::config]`. -/// -/// Also see [`pallet::config`](`frame_support::pallet_macros::config`) -/// -/// ## `pallet::constant` -/// -/// The `#[pallet::constant]` attribute can be used to add an associated type trait bounded by -/// [`Get`](crate::traits::Get) from [`pallet::config`](#palletconfig) into metadata, e.g.: +/// [`StorageInfoTrait`](frame_support::traits::StorageInfoTrait) for each storage in the +/// implementation of [`StorageInfoTrait`](frame_support::traits::StorageInfoTrait) for the +/// pallet. Otherwise it implements +/// [`StorageInfoTrait`](frame_support::traits::StorageInfoTrait) for the pallet using the +/// [`PartialStorageInfoTrait`](frame_support::traits::PartialStorageInfoTrait) +/// implementation of storages. /// -/// ```ignore -/// #[pallet::config] -/// pub trait Config: frame_system::Config { -/// #[pallet::constant] -/// type Foo: Get; -/// } -/// ``` -/// -/// Also see [`pallet::constant`](`frame_support::pallet_macros::constant`) -/// -/// ## `pallet::disable_frame_system_supertrait_check` -/// -/// -/// To bypass the `frame_system::Config` supertrait check, use the attribute -/// `pallet::disable_frame_system_supertrait_check`, e.g.: -/// -/// ```ignore -/// #[pallet::config] -/// #[pallet::disable_frame_system_supertrait_check] -/// pub trait Config: pallet_timestamp::Config {} -/// ``` -/// -/// NOTE: Bypassing the `frame_system::Config` supertrait check is typically desirable when you -/// want to write an alternative to the `frame_system` pallet. -/// -/// Also see -/// [`pallet::disable_frame_system_supertrait_check`](`frame_support::pallet_macros::disable_frame_system_supertrait_check`) -/// -/// ## Macro expansion: -/// -/// The macro expands pallet constant metadata with the information given by -/// `#[pallet::constant]`. -/// -/// # `pallet::generate_store($vis trait Store)` -/// -/// To generate a `Store` trait associating all storages, annotate your `Pallet` struct with -/// the attribute `#[pallet::generate_store($vis trait Store)]`, e.g.: -/// -/// ```ignore -/// #[pallet::pallet] -/// #[pallet::generate_store(pub(super) trait Store)] -/// pub struct Pallet(_); -/// ``` -/// More precisely, the `Store` trait contains an associated type for each storage. It is -/// implemented for `Pallet` allowing access to the storage from pallet struct. -/// -/// Thus when defining a storage named `Foo`, it can later be accessed from `Pallet` using -/// `::Foo`. -/// -/// NOTE: this attribute is only valid when applied _directly_ to your `Pallet` struct -/// definition. -/// -/// Also see [`pallet::generate_store`](`frame_support::pallet_macros::generate_store`). -/// -/// # `pallet::storage_version` -/// -/// Because the [`pallet::pallet`](#pallet-struct-placeholder-palletpallet-mandatory) macro -/// implements [`traits::GetStorageVersion`], the in-code storage version needs to be -/// communicated to the macro. This can be done by using the `pallet::storage_version` -/// attribute: -/// -/// ```ignore -/// const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); -/// -/// #[pallet::pallet] -/// #[pallet::storage_version(STORAGE_VERSION)] -/// pub struct Pallet(_); -/// ``` -/// -/// If not present, the in-code storage version is set to the default value. -/// -/// Also see [`pallet::storage_version`](`frame_support::pallet_macros::storage_version`) -/// -/// # Hooks: `#[pallet::hooks]` (optional) -/// -/// The `pallet::hooks` attribute allows you to specify a `Hooks` implementation for `Pallet` -/// that specifies pallet-specific logic. -/// -/// The item the attribute attaches to must be defined as follows: -/// ```ignore -/// #[pallet::hooks] -/// impl Hooks> for Pallet $optional_where_clause { -/// ... -/// } -/// ``` -/// I.e. a regular trait implementation with generic bound: `T: Config`, for the trait -/// `Hooks>` (they are defined in preludes), for the type `Pallet` and -/// with an optional where clause. -/// -/// If no `#[pallet::hooks]` exists, then the following default implementation is -/// automatically generated: -/// ```ignore -/// #[pallet::hooks] -/// impl Hooks> for Pallet {} -/// ``` -/// -/// Also see [`pallet::hooks`](`frame_support::pallet_macros::hooks`) -/// -/// # Call: `#[pallet::call]` (optional) -/// -/// Implementation of pallet dispatchables. -/// -/// Item must be defined as: -/// ```ignore -/// #[pallet::call] -/// impl Pallet { -/// /// $some_doc -/// #[pallet::weight($ExpressionResultingInWeight)] -/// pub fn $fn_name( -/// origin: OriginFor, -/// $some_arg: $some_type, -/// // or with compact attribute: #[pallet::compact] $some_arg: $some_type, -/// ... -/// ) -> DispatchResultWithPostInfo { // or `-> DispatchResult` -/// ... -/// } -/// ... -/// } -/// ``` -/// I.e. a regular type implementation, with generic `T: Config`, on type `Pallet`, with -/// an optional where clause. +/// ## Dev Mode (`#[pallet(dev_mode)]`) /// -/// ## `#[pallet::weight($expr)]` +/// Specifying the argument `dev_mode` will allow you to enable dev mode for a pallet. The +/// aim of dev mode is to loosen some of the restrictions and requirements placed on +/// production pallets for easy tinkering and development. Dev mode pallets should not be +/// used in production. Enabling dev mode has the following effects: /// -/// Each dispatchable needs to define a weight with `#[pallet::weight($expr)]` attribute, the -/// first argument must be `origin: OriginFor`. -/// -/// Also see [`pallet::weight`](`frame_support::pallet_macros::weight`) -/// -/// ### `#[pallet::compact] $some_arg: $some_type` -/// -/// Compact encoding for arguments can be achieved via `#[pallet::compact]`. The function must -/// return a `DispatchResultWithPostInfo` or `DispatchResult`. -/// -/// Also see [`pallet::compact`](`frame_support::pallet_macros::compact`) -/// -/// ## `#[pallet::call_index($idx)]` -/// -/// Each dispatchable may also be annotated with the `#[pallet::call_index($idx)]` attribute, -/// which explicitly defines the codec index for the dispatchable function in the `Call` enum. -/// -/// All call indexes start from 0, until it encounters a dispatchable function with a defined -/// call index. The dispatchable function that lexically follows the function with a defined -/// call index will have that call index, but incremented by 1, e.g. if there are 3 -/// dispatchable functions `fn foo`, `fn bar` and `fn qux` in that order, and only `fn bar` -/// has a call index of 10, then `fn qux` will have an index of 11, instead of 1. -/// -/// **WARNING**: modifying dispatchables, changing their order, removing some, etc., must be -/// done with care. Indeed this will change the outer runtime call type (which is an enum with -/// one variant per pallet), this outer runtime call can be stored on-chain (e.g. in -/// `pallet-scheduler`). Thus migration might be needed. To mitigate against some of this, the -/// `#[pallet::call_index($idx)]` attribute can be used to fix the order of the dispatchable so -/// that the `Call` enum encoding does not change after modification. As a general rule of -/// thumb, it is therefore adventageous to always add new calls to the end so you can maintain -/// the existing order of calls. -/// -/// Also see [`pallet::call_index`](`frame_support::pallet_macros::call_index`) -/// -/// # Extra constants: `#[pallet::extra_constants]` (optional) -/// -/// Allows you to define some extra constants to be added into constant metadata. -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::extra_constants] -/// impl Pallet where $optional_where_clause { -/// /// $some_doc -/// $vis fn $fn_name() -> $some_return_type { -/// ... -/// } -/// ... -/// } -/// ``` -/// I.e. a regular rust `impl` block with some optional where clause and functions with 0 args, -/// 0 generics, and some return type. -/// -/// ## Macro expansion -/// -/// The macro add some extra constants to pallet constant metadata. -/// -/// Also see: [`pallet::extra_constants`](`frame_support::pallet_macros::extra_constants`) -/// -/// # Error: `#[pallet::error]` (optional) -/// -/// The `#[pallet::error]` attribute allows you to define an error enum that will be returned -/// from the dispatchable when an error occurs. The information for this error type is then -/// stored in metadata. -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::error] -/// pub enum Error { -/// /// $some_optional_doc -/// $SomeFieldLessVariant, -/// /// $some_more_optional_doc -/// $SomeVariantWithOneField(FieldType), -/// ... -/// } -/// ``` -/// I.e. a regular enum named `Error`, with generic `T` and fieldless or multiple-field -/// variants. -/// -/// Any field type in the enum variants must implement [`scale_info::TypeInfo`] in order to be -/// properly used in the metadata, and its encoded size should be as small as possible, -/// preferably 1 byte in size in order to reduce storage size. The error enum itself has an -/// absolute maximum encoded size specified by [`MAX_MODULE_ERROR_ENCODED_SIZE`]. -/// -/// (1 byte can still be 256 different errors. The more specific the error, the easier it is to -/// diagnose problems and give a better experience to the user. Don't skimp on having lots of -/// individual error conditions.) -/// -/// Field types in enum variants must also implement [`PalletError`](traits::PalletError), -/// otherwise the pallet will fail to compile. Rust primitive types have already implemented -/// the [`PalletError`](traits::PalletError) trait along with some commonly used stdlib types -/// such as [`Option`] and -/// [`PhantomData`](`frame_support::__private::sp_std::marker::PhantomData`), and hence in most -/// use cases, a manual implementation is not necessary and is discouraged. -/// -/// The generic `T` must not bound anything and a `where` clause is not allowed. That said, -/// bounds and/or a where clause should not needed for any use-case. -/// -/// Also see: [`pallet::error`](`frame_support::pallet_macros::error`) -/// -/// # Event: `#[pallet::event]` (optional) -/// -/// Allows you to define pallet events. Pallet events are stored under the `system` / `events` -/// key when the block is applied (and then replaced when the next block writes it's events). -/// -/// The Event enum must be defined as follows: -/// -/// ```ignore -/// #[pallet::event] -/// #[pallet::generate_deposit($visibility fn deposit_event)] // Optional -/// pub enum Event<$some_generic> $optional_where_clause { -/// /// Some doc -/// $SomeName($SomeType, $YetanotherType, ...), -/// ... -/// } -/// ``` -/// -/// I.e. an enum (with named or unnamed fields variant), named `Event`, with generic: none or -/// `T` or `T: Config`, and optional w here clause. -/// -/// Each field must implement [`Clone`], [`Eq`], [`PartialEq`], [`Encode`], [`Decode`], and -/// [`Debug`] (on std only). For ease of use, bound by the trait -/// [`Member`](`frame_support::pallet_prelude::Member`), available in -/// frame_support::pallet_prelude. -/// -/// Also see [`pallet::event`](`frame_support::pallet_macros::event`) -/// -/// ## `#[pallet::generate_deposit($visibility fn deposit_event)]` -/// -/// The attribute `#[pallet::generate_deposit($visibility fn deposit_event)]` generates a -/// helper function on `Pallet` that handles deposit events. -/// -/// NOTE: For instantiable pallets, the event must be generic over `T` and `I`. -/// -/// Also see [`pallet::generate_deposit`](`frame_support::pallet_macros::generate_deposit`) -/// -/// # Storage: `#[pallet::storage]` (optional) -/// -/// The `#[pallet::storage]` attribute lets you define some abstract storage inside of runtime -/// storage and also set its metadata. This attribute can be used multiple times. -/// -/// Item should be defined as: -/// -/// ```ignore -/// #[pallet::storage] -/// #[pallet::getter(fn $getter_name)] // optional -/// $vis type $StorageName<$some_generic> $optional_where_clause -/// = $StorageType<$generic_name = $some_generics, $other_name = $some_other, ...>; -/// ``` -/// -/// or with unnamed generic: -/// -/// ```ignore -/// #[pallet::storage] -/// #[pallet::getter(fn $getter_name)] // optional -/// $vis type $StorageName<$some_generic> $optional_where_clause -/// = $StorageType<_, $some_generics, ...>; -/// ``` -/// -/// I.e. it must be a type alias, with generics: `T` or `T: Config`. The aliased type must be -/// one of [`StorageValue`](`pallet_prelude::StorageValue`), -/// [`StorageMap`](`pallet_prelude::StorageMap`) or -/// [`StorageDoubleMap`](`pallet_prelude::StorageDoubleMap`). The generic arguments of the -/// storage type can be given in two manners: named and unnamed. For named generic arguments, -/// the name for each argument should match the name defined for it on the storage struct: -/// * [`StorageValue`](`pallet_prelude::StorageValue`) expects `Value` and optionally -/// `QueryKind` and `OnEmpty`, -/// * [`StorageMap`](`pallet_prelude::StorageMap`) expects `Hasher`, `Key`, `Value` and -/// optionally `QueryKind` and `OnEmpty`, -/// * [`CountedStorageMap`](`pallet_prelude::CountedStorageMap`) expects `Hasher`, `Key`, -/// `Value` and optionally `QueryKind` and `OnEmpty`, -/// * [`StorageDoubleMap`](`pallet_prelude::StorageDoubleMap`) expects `Hasher1`, `Key1`, -/// `Hasher2`, `Key2`, `Value` and optionally `QueryKind` and `OnEmpty`. -/// -/// For unnamed generic arguments: Their first generic must be `_` as it is replaced by the -/// macro and other generic must declared as a normal generic type declaration. -/// -/// The `Prefix` generic written by the macro is generated using -/// `PalletInfo::name::>()` and the name of the storage type. E.g. if runtime names -/// the pallet "MyExample" then the storage `type Foo = ...` should use the prefix: -/// `Twox128(b"MyExample") ++ Twox128(b"Foo")`. -/// -/// For the [`CountedStorageMap`](`pallet_prelude::CountedStorageMap`) variant, the `Prefix` -/// also implements -/// [`CountedStorageMapInstance`](`frame_support::storage::types::CountedStorageMapInstance`). -/// It also associates a [`CounterPrefix`](`pallet_prelude::CounterPrefix'), which is -/// implemented the same as above, but the storage prefix is prepend with `"CounterFor"`. E.g. -/// if runtime names the pallet "MyExample" then the storage `type Foo = -/// CountedStorageaMap<...>` will store its counter at the prefix: `Twox128(b"MyExample") ++ -/// Twox128(b"CounterForFoo")`. -/// -/// E.g: -/// -/// ```ignore -/// #[pallet::storage] -/// pub(super) type MyStorage = StorageMap; -/// ``` -/// -/// In this case the final prefix used by the map is `Twox128(b"MyExample") ++ -/// Twox128(b"OtherName")`. -/// -/// Also see [`pallet::storage`](`frame_support::pallet_macros::storage`) -/// -/// ## `#[pallet::getter(fn $my_getter_fn_name)]` (optional) -/// -/// The optional attribute `#[pallet::getter(fn $my_getter_fn_name)]` allows you to define a -/// getter function on `Pallet`. -/// -/// Also see [`pallet::getter`](`frame_support::pallet_macros::getter`) -/// -/// ## `#[pallet::storage_prefix = "SomeName"]` (optional) -/// -/// The optional attribute `#[pallet::storage_prefix = "SomeName"]` allows you to define the -/// storage prefix to use, see how `Prefix` generic is implemented above. This is helpful if -/// you wish to rename the storage field but don't want to perform a migration. -/// -/// E.g: -/// -/// ```ignore -/// #[pallet::storage] -/// #[pallet::storage_prefix = "foo"] -/// #[pallet::getter(fn my_storage)] -/// pub(super) type MyStorage = StorageMap; -/// ``` -/// -/// or -/// -/// ```ignore -/// #[pallet::storage] -/// #[pallet::getter(fn my_storage)] -/// pub(super) type MyStorage = StorageMap<_, Blake2_128Concat, u32, u32>; -/// ``` -/// -/// Also see [`pallet::storage_prefix`](`frame_support::pallet_macros::storage_prefix`) -/// -/// ## `#[pallet::unbounded]` (optional) -/// -/// The optional attribute `#[pallet::unbounded]` declares the storage as unbounded. When -/// implementating the storage info (when `#[pallet::generate_storage_info]` is specified on -/// the pallet struct placeholder), the size of the storage will be declared as unbounded. This -/// can be useful for storage which can never go into PoV (Proof of Validity). -/// -/// Also see [`pallet::unbounded`](`frame_support::pallet_macros::unbounded`) -/// -/// ## `#[pallet::whitelist_storage]` (optional) -/// -/// The optional attribute `#[pallet::whitelist_storage]` will declare the storage as -/// whitelisted from benchmarking. -/// -/// See -/// [`pallet::whitelist_storage`](frame_support::pallet_macros::whitelist_storage) -/// for more info. -/// -/// ## `#[pallet::disable_try_decode_storage]` (optional) -/// -/// The optional attribute `#[pallet::disable_try_decode_storage]` will declare the storage as -/// whitelisted state decoding during try-runtime logic. -/// -/// See -/// [`pallet::disable_try_decode_storage`](frame_support::pallet_macros::disable_try_decode_storage) -/// for more info. -/// -/// ## `#[cfg(..)]` (for storage) -/// The optional attributes `#[cfg(..)]` allow conditional compilation for the storage. -/// -/// E.g: -/// -/// ```ignore -/// #[cfg(feature = "my-feature")] -/// #[pallet::storage] -/// pub(super) type MyStorage = StorageValue; -/// ``` -/// -/// All the `cfg` attributes are automatically copied to the items generated for the storage, -/// i.e. the getter, storage prefix, and the metadata element etc. -/// -/// Any type placed as the `QueryKind` parameter must implement -/// [`frame_support::storage::types::QueryKindTrait`]. There are 3 implementations of this -/// trait by default: -/// -/// 1. [`OptionQuery`](`frame_support::storage::types::OptionQuery`), the default `QueryKind` -/// used when this type parameter is omitted. Specifying this as the `QueryKind` would cause -/// storage map APIs that return a `QueryKind` to instead return an [`Option`], returning -/// `Some` when a value does exist under a specified storage key, and `None` otherwise. -/// 2. [`ValueQuery`](`frame_support::storage::types::ValueQuery`) causes storage map APIs that -/// return a `QueryKind` to instead return the value type. In cases where a value does not -/// exist under a specified storage key, the `OnEmpty` type parameter on `QueryKindTrait` is -/// used to return an appropriate value. -/// 3. [`ResultQuery`](`frame_support::storage::types::ResultQuery`) causes storage map APIs -/// that return a `QueryKind` to instead return a `Result`, with `T` being the value -/// type and `E` being the pallet error type specified by the `#[pallet::error]` attribute. -/// In cases where a value does not exist under a specified storage key, an `Err` with the -/// specified pallet error variant is returned. -/// -/// NOTE: If the `QueryKind` generic parameter is still generic at this stage or is using some -/// type alias then the generation of the getter might fail. In this case the getter can be -/// implemented manually. -/// -/// NOTE: The generic `Hasher` must implement the [`StorageHasher`] trait (or the type is not -/// usable at all). We use [`StorageHasher::METADATA`] for the metadata of the hasher of the -/// storage item. Thus generic hasher is supported. -/// -/// ## Macro expansion -/// -/// For each storage item the macro generates a struct named -/// `_GeneratedPrefixForStorage$NameOfStorage`, and implements -/// [`StorageInstance`](traits::StorageInstance) on it using the pallet and storage name. It -/// then uses it as the first generic of the aliased type. For -/// [`CountedStorageMap`](`pallet_prelude::CountedStorageMap`), -/// [`CountedStorageMapInstance`](`frame_support::storage::types::CountedStorageMapInstance`) -/// is implemented, and another similar struct is generated. -/// -/// For a named generic, the macro will reorder the generics, and remove the names. -/// -/// The macro implements the function `storage_metadata` on the `Pallet` implementing the -/// metadata for all storage items based on their kind: -/// * for a storage value, the type of the value is copied into the metadata -/// * for a storage map, the type of the values and the key's type is copied into the metadata -/// * for a storage double map, the type of the values, and the types of `key1` and `key2` are -/// copied into the metadata. -/// -/// # Type value: `#[pallet::type_value]` (optional) -/// -/// The `#[pallet::type_value]` attribute lets you define a struct implementing the -/// [`Get`](crate::traits::Get) trait to ease use of storage types. This attribute is meant to -/// be used alongside [`#[pallet::storage]`](#storage-palletstorage-optional) to define a -/// storage's default value. This attribute can be used multiple times. -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::type_value] -/// fn $MyDefaultName<$some_generic>() -> $default_type $optional_where_clause { $expr } -/// ``` -/// -/// I.e.: a function definition with generics none or `T: Config` and a returned type. -/// -/// E.g.: -/// -/// ```ignore -/// #[pallet::type_value] -/// fn MyDefault() -> T::Balance { 3.into() } -/// ``` -/// -/// Also see [`pallet::type_value`](`frame_support::pallet_macros::type_value`) -/// -/// # Genesis config: `#[pallet::genesis_config]` (optional) -/// -/// The `#[pallet::genesis_config]` attribute allows you to define the genesis configuration -/// for the pallet. -/// -/// Item is defined as either an enum or a struct. It needs to be public and implement the -/// trait [`BuildGenesisConfig`](`traits::BuildGenesisConfig`) with -/// [`#[pallet::genesis_build]`](#genesis-build-palletgenesis_build-optional). The type -/// generics are constrained to be either none, or `T` or `T: Config`. -/// -/// E.g: -/// -/// ```ignore -/// #[pallet::genesis_config] -/// pub struct GenesisConfig { -/// _myfield: BalanceOf, -/// } -/// ``` -/// -/// Also see [`pallet::genesis_config`](`frame_support::pallet_macros::genesis_config`) -/// -/// # Genesis build: `#[pallet::genesis_build]` (optional) -/// -/// The `#[pallet::genesis_build]` attribute allows you to define how `genesis_configuration` -/// is built. This takes as input the `GenesisConfig` type (as `self`) and constructs the -/// pallet's initial state. -/// -/// The impl must be defined as: -/// -/// ```ignore -/// #[pallet::genesis_build] -/// impl GenesisBuild for GenesisConfig<$maybe_generics> { -/// fn build(&self) { $expr } -/// } -/// ``` -/// -/// I.e. a trait implementation with generic `T: Config`, of trait `GenesisBuild` on -/// type `GenesisConfig` with generics none or `T`. -/// -/// E.g.: -/// -/// ```ignore -/// #[pallet::genesis_build] -/// impl GenesisBuild for GenesisConfig { -/// fn build(&self) {} -/// } -/// ``` -/// -/// Also see [`pallet::genesis_build`](`frame_support::pallet_macros::genesis_build`) -/// -/// # Inherent: `#[pallet::inherent]` (optional) -/// -/// The `#[pallet::inherent]` attribute allows the pallet to provide some -/// [inherent](https://docs.substrate.io/fundamentals/transaction-types/#inherent-transactions). -/// An inherent is some piece of data that is inserted by a block authoring node at block -/// creation time and can either be accepted or rejected by validators based on whether the -/// data falls within an acceptable range. -/// -/// The most common inherent is the `timestamp` that is inserted into every block. Since there -/// is no way to validate timestamps, validators simply check that the timestamp reported by -/// the block authoring node falls within an acceptable range. -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::inherent] -/// impl ProvideInherent for Pallet { -/// // ... regular trait implementation -/// } -/// ``` -/// -/// I.e. a trait implementation with bound `T: Config`, of trait -/// [`ProvideInherent`](`pallet_prelude::ProvideInherent`) for type `Pallet`, and some -/// optional where clause. -/// -/// Also see [`pallet::inherent`](`frame_support::pallet_macros::inherent`) -/// -/// # Validate unsigned: `#[pallet::validate_unsigned]` (optional) -/// -/// The `#[pallet::validate_unsigned]` attribute allows the pallet to validate some unsigned -/// transaction: -/// -/// Item must be defined as: -/// -/// ```ignore -/// #[pallet::validate_unsigned] -/// impl ValidateUnsigned for Pallet { -/// // ... regular trait implementation -/// } -/// ``` -/// -/// I.e. a trait implementation with bound `T: Config`, of trait -/// [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`) for type `Pallet`, and some -/// optional where clause. -/// -/// NOTE: There is also the [`sp_runtime::traits::SignedExtension`] trait that can be used to -/// add some specific logic for transaction validation. -/// -/// Also see [`pallet::validate_unsigned`](`frame_support::pallet_macros::validate_unsigned`) -/// -/// # Origin: `#[pallet::origin]` (optional) -/// -/// The `#[pallet::origin]` attribute allows you to define some origin for the pallet. -/// -/// Item must be either a type alias, an enum, or a struct. It needs to be public. -/// -/// E.g.: -/// -/// ```ignore -/// #[pallet::origin] -/// pub struct Origin(PhantomData<(T)>); -/// ``` -/// -/// **WARNING**: modifying origin changes the outer runtime origin. This outer runtime origin -/// can be stored on-chain (e.g. in `pallet-scheduler`), thus any change must be done with care -/// as it might require some migration. -/// -/// NOTE: for instantiable pallets, the origin must be generic over `T` and `I`. -/// -/// Also see [`pallet::origin`](`frame_support::pallet_macros::origin`) -/// -/// # Composite enum `#[pallet::composite_enum]` (optional) -/// -/// The `#[pallet::composite_enum]` attribute allows you to define an enum on the pallet which -/// will then instruct `construct_runtime` to amalgamate all similarly-named enums from other -/// pallets into an aggregate enum. This is similar in principle with how the aggregate enum is -/// generated for `#[pallet::event]` or `#[pallet::error]`. -/// -/// The item tagged with `#[pallet::composite_enum]` MUST be an enum declaration, and can ONLY -/// be the following identifiers: `FreezeReason`, `HoldReason`, `LockId` or `SlashReason`. -/// Custom identifiers are not supported. -/// -/// NOTE: For ease of usage, when no `#[derive]` attributes are detected, the -/// `#[pallet::composite_enum]` attribute will automatically derive the following traits for -/// the enum: -/// -/// ```ignore -/// Copy, Clone, Eq, PartialEq, Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebug -/// ``` -/// -/// The inverse is also true: if there are any #[derive] attributes present for the enum, then -/// the attribute will not automatically derive any of the traits described above. -/// -/// # General notes on instantiable pallets -/// -/// An instantiable pallet is one where Config is generic, i.e. `Config`. This allows -/// runtime to implement multiple instances of the pallet, by using different types for the -/// generic. This is the sole purpose of the generic `I`, but because -/// [`PalletInfo`](`traits::PalletInfo`) requires the `Pallet` placeholder to be static, it is -/// important to bound by `'static` whenever [`PalletInfo`](`traits::PalletInfo`) can be used. -/// Additionally, in order to make an instantiable pallet usable as a regular pallet without an -/// instance, it is important to bound by `= ()` on every type. -/// -/// Thus impl bound looks like `impl, I: 'static>`, and types look like -/// `SomeType` or `SomeType, I: 'static = ()>`. -/// -/// # Example of a non-instantiable pallet -/// -/// ``` -/// pub use pallet::*; // reexport in crate namespace for `construct_runtime!` -/// -/// #[frame_support::pallet] -/// // NOTE: The name of the pallet is provided by `construct_runtime` and is used as -/// // the unique identifier for the pallet's storage. It is not defined in the pallet itself. -/// pub mod pallet { -/// use frame_support::pallet_prelude::*; // Import various types used in the pallet definition -/// use frame_system::pallet_prelude::*; // Import some system helper types. -/// -/// type BalanceOf = ::Balance; -/// -/// // Define the generic parameter of the pallet -/// // The macro parses `#[pallet::constant]` attributes and uses them to generate metadata -/// // for the pallet's constants. -/// #[pallet::config] -/// pub trait Config: frame_system::Config { -/// #[pallet::constant] // put the constant in metadata -/// type MyGetParam: Get; -/// type Balance: Parameter + MaxEncodedLen + From; -/// type RuntimeEvent: From> + IsType<::RuntimeEvent>; -/// } -/// -/// // Define some additional constant to put into the constant metadata. -/// #[pallet::extra_constants] -/// impl Pallet { -/// /// Some description -/// fn exra_constant_name() -> u128 { 4u128 } -/// } -/// -/// // Define the pallet struct placeholder, various pallet function are implemented on it. -/// #[pallet::pallet] -/// #[pallet::generate_store(pub(super) trait Store)] -/// pub struct Pallet(_); -/// -/// // Implement the pallet hooks. -/// #[pallet::hooks] -/// impl Hooks> for Pallet { -/// fn on_initialize(_n: BlockNumberFor) -> Weight { -/// unimplemented!(); -/// } -/// -/// // can implement also: on_finalize, on_runtime_upgrade, offchain_worker, ... -/// // see `Hooks` trait -/// } -/// -/// // Declare Call struct and implement dispatchables. -/// // -/// // WARNING: Each parameter used in functions must implement: Clone, Debug, Eq, PartialEq, -/// // Codec. -/// // -/// // The macro parses `#[pallet::compact]` attributes on function arguments and implements -/// // the `Call` encoding/decoding accordingly. -/// #[pallet::call] -/// impl Pallet { -/// /// Doc comment put in metadata -/// #[pallet::weight(0)] // Defines weight for call (function parameters are in scope) -/// pub fn toto( -/// origin: OriginFor, -/// #[pallet::compact] _foo: u32, -/// ) -> DispatchResultWithPostInfo { -/// let _ = origin; -/// unimplemented!(); -/// } -/// } -/// -/// // Declare the pallet `Error` enum (this is optional). -/// // The macro generates error metadata using the doc comment on each variant. -/// #[pallet::error] -/// pub enum Error { -/// /// doc comment put into metadata -/// InsufficientProposersBalance, -/// } -/// -/// // Declare pallet Event enum (this is optional). -/// // -/// // WARNING: Each type used in variants must implement: Clone, Debug, Eq, PartialEq, Codec. -/// // -/// // The macro generates event metadata, and derive Clone, Debug, Eq, PartialEq and Codec -/// #[pallet::event] -/// // Generate a funciton on Pallet to deposit an event. -/// #[pallet::generate_deposit(pub(super) fn deposit_event)] -/// pub enum Event { -/// /// doc comment put in metadata -/// // `::AccountId` is not defined in metadata list, the last -/// // Thus the metadata is `::AccountId`. -/// Proposed(::AccountId), -/// /// doc -/// // here metadata will be `Balance` as define in metadata list -/// Spending(BalanceOf), -/// // here metadata will be `Other` as define in metadata list -/// Something(u32), -/// } -/// -/// // Define a struct which implements `frame_support::traits::Get` (optional). -/// #[pallet::type_value] -/// pub(super) fn MyDefault() -> T::Balance { 3.into() } -/// -/// // Declare a storage item. Any amount of storage items can be declared (optional). -/// // -/// // Is expected either `StorageValue`, `StorageMap` or `StorageDoubleMap`. -/// // The macro generates the prefix type and replaces the first generic `_`. -/// // -/// // The macro expands the metadata for the storage item with the type used: -/// // * for a storage value the type of the value is copied into the metadata -/// // * for a storage map the type of the values and the type of the key is copied into the metadata -/// // * for a storage double map the types of the values and keys are copied into the -/// // metadata. -/// // -/// // NOTE: The generic `Hasher` must implement the `StorageHasher` trait (or the type is not -/// // usable at all). We use [`StorageHasher::METADATA`] for the metadata of the hasher of the -/// // storage item. Thus generic hasher is supported. -/// #[pallet::storage] -/// pub(super) type MyStorageValue = -/// StorageValue>; -/// -/// // Another storage declaration -/// #[pallet::storage] -/// #[pallet::getter(fn my_storage)] -/// #[pallet::storage_prefix = "SomeOtherName"] -/// pub(super) type MyStorage = -/// StorageMap; -/// -/// // Declare the genesis config (optional). -/// // -/// // The macro accepts either a struct or an enum; it checks that generics are consistent. -/// // -/// // Type must implement the `Default` trait. -/// #[pallet::genesis_config] -/// #[derive(frame_support::DefaultNoBound)] -/// pub struct GenesisConfig { -/// _config: sp_std::marker::PhantomData, -/// _myfield: u32, -/// } -/// -/// // Declare genesis builder. (This is need only if GenesisConfig is declared) -/// #[pallet::genesis_build] -/// impl BuildGenesisConfig for GenesisConfig { -/// fn build(&self) {} -/// } -/// -/// // Declare a pallet origin (this is optional). -/// // -/// // The macro accept type alias or struct or enum, it checks generics are consistent. -/// #[pallet::origin] -/// pub struct Origin(PhantomData); -/// -/// // Declare a hold reason (this is optional). -/// // -/// // Creates a hold reason for this pallet that is aggregated by `construct_runtime`. -/// // A similar enum can be defined for `FreezeReason`, `LockId` or `SlashReason`. -/// #[pallet::composite_enum] -/// pub enum HoldReason { -/// SomeHoldReason -/// } -/// -/// // Declare validate_unsigned implementation (this is optional). -/// #[pallet::validate_unsigned] -/// impl ValidateUnsigned for Pallet { -/// type Call = Call; -/// fn validate_unsigned( -/// source: TransactionSource, -/// call: &Self::Call -/// ) -> TransactionValidity { -/// Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) -/// } -/// } -/// -/// // Declare inherent provider for pallet (this is optional). -/// #[pallet::inherent] -/// impl ProvideInherent for Pallet { -/// type Call = Call; -/// type Error = InherentError; -/// -/// const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; -/// -/// fn create_inherent(_data: &InherentData) -> Option { -/// unimplemented!(); -/// } -/// -/// fn is_inherent(_call: &Self::Call) -> bool { -/// unimplemented!(); -/// } -/// } -/// -/// // Regular rust code needed for implementing ProvideInherent trait -/// -/// #[derive(codec::Encode, sp_runtime::RuntimeDebug)] -/// #[cfg_attr(feature = "std", derive(codec::Decode))] -/// pub enum InherentError { -/// } -/// -/// impl sp_inherents::IsFatalError for InherentError { -/// fn is_fatal_error(&self) -> bool { -/// unimplemented!(); -/// } -/// } -/// -/// pub const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"testpall"; -/// } -/// ``` -/// -/// # Example of an instantiable pallet -/// -/// ``` -/// pub use pallet::*; -/// -/// #[frame_support::pallet] -/// pub mod pallet { -/// use frame_support::pallet_prelude::*; -/// use frame_system::pallet_prelude::*; -/// -/// type BalanceOf = >::Balance; +/// * Weights no longer need to be specified on every `#[pallet::call]` declaration. By +/// default, dev mode pallets will assume a weight of zero (`0`) if a weight is not +/// specified. This is equivalent to specifying `#[weight(0)]` on all calls that do not +/// specify a weight. +/// * Call indices no longer need to be specified on every `#[pallet::call]` declaration. By +/// default, dev mode pallets will assume a call index based on the order of the call. +/// * All storages are marked as unbounded, meaning you do not need to implement +/// [`MaxEncodedLen`](frame_support::pallet_prelude::MaxEncodedLen) on storage types. This is +/// equivalent to specifying `#[pallet::unbounded]` on all storage type definitions. +/// * Storage hashers no longer need to be specified and can be replaced by `_`. In dev mode, +/// these will be replaced by `Blake2_128Concat`. In case of explicit key-binding, `Hasher` +/// can simply be ignored when in `dev_mode`. /// -/// #[pallet::config] -/// pub trait Config: frame_system::Config { -/// #[pallet::constant] -/// type MyGetParam: Get; -/// type Balance: Parameter + MaxEncodedLen + From; -/// type RuntimeEvent: From> + IsType<::RuntimeEvent>; -/// } -/// -/// #[pallet::extra_constants] -/// impl, I: 'static> Pallet { -/// /// Some description -/// fn extra_constant_name() -> u128 { 4u128 } -/// } -/// -/// #[pallet::pallet] -/// #[pallet::generate_store(pub(super) trait Store)] -/// pub struct Pallet(PhantomData<(T, I)>); -/// -/// #[pallet::hooks] -/// impl, I: 'static> Hooks> for Pallet { -/// } -/// -/// #[pallet::call] -/// impl, I: 'static> Pallet { -/// /// Doc comment put in metadata -/// #[pallet::weight(0)] -/// pub fn toto(origin: OriginFor, #[pallet::compact] _foo: u32) -> DispatchResultWithPostInfo { -/// let _ = origin; -/// unimplemented!(); -/// } -/// } -/// -/// #[pallet::error] -/// pub enum Error { -/// /// doc comment put into metadata -/// InsufficientProposersBalance, -/// } -/// -/// #[pallet::event] -/// #[pallet::generate_deposit(pub(super) fn deposit_event)] -/// pub enum Event, I: 'static = ()> { -/// /// doc comment put in metadata -/// Proposed(::AccountId), -/// /// doc -/// Spending(BalanceOf), -/// Something(u32), -/// } -/// -/// #[pallet::type_value] -/// pub(super) fn MyDefault, I: 'static>() -> T::Balance { 3.into() } -/// -/// #[pallet::storage] -/// pub(super) type MyStorageValue, I: 'static = ()> = -/// StorageValue>; -/// -/// #[pallet::storage] -/// #[pallet::getter(fn my_storage)] -/// #[pallet::storage_prefix = "SomeOtherName"] -/// pub(super) type MyStorage = -/// StorageMap; -/// -/// #[pallet::genesis_config] -/// #[derive(frame_support::DefaultNoBound)] -/// pub struct GenesisConfig, I: 'static = ()> { -/// _config: sp_std::marker::PhantomData<(T,I)>, -/// _myfield: u32, -/// } -/// -/// #[pallet::genesis_build] -/// impl, I: 'static> BuildGenesisConfig for GenesisConfig { -/// fn build(&self) {} -/// } -/// -/// #[pallet::origin] -/// pub struct Origin(PhantomData<(T, I)>); -/// -/// #[pallet::composite_enum] -/// pub enum HoldReason { -/// SomeHoldReason -/// } -/// -/// #[pallet::validate_unsigned] -/// impl, I: 'static> ValidateUnsigned for Pallet { -/// type Call = Call; -/// fn validate_unsigned( -/// source: TransactionSource, -/// call: &Self::Call -/// ) -> TransactionValidity { -/// Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) -/// } -/// } -/// -/// #[pallet::inherent] -/// impl, I: 'static> ProvideInherent for Pallet { -/// type Call = Call; -/// type Error = InherentError; -/// -/// const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; -/// -/// fn create_inherent(_data: &InherentData) -> Option { -/// unimplemented!(); -/// } -/// -/// fn is_inherent(_call: &Self::Call) -> bool { -/// unimplemented!(); -/// } -/// } -/// -/// // Regular rust code needed for implementing ProvideInherent trait -/// -/// #[derive(codec::Encode, sp_runtime::RuntimeDebug)] -/// #[cfg_attr(feature = "std", derive(codec::Decode))] -/// pub enum InherentError { -/// } -/// -/// impl sp_inherents::IsFatalError for InherentError { -/// fn is_fatal_error(&self) -> bool { -/// unimplemented!(); -/// } -/// } -/// -/// pub const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"testpall"; -/// } -/// ``` +/// Note that the `dev_mode` argument can only be supplied to the `#[pallet]` or +/// `#[frame_support::pallet]` attribute macro that encloses your pallet module. This +/// argument cannot be specified anywhere else, including but not limited to the +/// `#[pallet::pallet]` attribute macro. /// -/// # Upgrade guidelines -/// -/// 1. Export the metadata of the pallet for later checks -/// - run your node with the pallet active -/// - query the metadata using the `state_getMetadata` RPC and curl, or use `subsee -p -/// > meta.json` -/// 2. Generate the template upgrade for the pallet provided by `decl_storage` with the -/// environment variable `PRINT_PALLET_UPGRADE`: `PRINT_PALLET_UPGRADE=1 cargo check -p -/// my_pallet`. This template can be used as it contains all information for storages, -/// genesis config and genesis build. -/// 3. Reorganize the pallet to have the trait `Config`, `decl_*` macros, -/// [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`), -/// [`ProvideInherent`](`pallet_prelude::ProvideInherent`), and Origin` all together in one -/// file. Suggested order: -/// * `Config`, -/// * `decl_module`, -/// * `decl_event`, -/// * `decl_error`, -/// * `decl_storage`, -/// * `origin`, -/// * `validate_unsigned`, -/// * `provide_inherent`, so far it should compile and all be correct. -/// 4. start writing the new pallet module -/// ```ignore -/// pub use pallet::*; -/// -/// #[frame_support::pallet] -/// pub mod pallet { -/// use frame_support::pallet_prelude::*; -/// use frame_system::pallet_prelude::*; -/// use super::*; -/// -/// #[pallet::pallet] -/// #[pallet::generate_store($visibility_of_trait_store trait Store)] -/// // NOTE: if the visibility of trait store is private but you want to make it available -/// // in super, then use `pub(super)` or `pub(crate)` to make it available in crate. -/// pub struct Pallet(_); -/// // pub struct Pallet(PhantomData); // for instantiable pallet -/// } -/// ``` -/// 5. **migrate Config**: move trait into the module with -/// * all const in `decl_module` to [`#[pallet::constant]`](#palletconstant) -/// * add the bound `IsType<::RuntimeEvent>` to `type -/// RuntimeEvent` -/// 7. **migrate decl_module**: write: -/// ```ignore -/// #[pallet::hooks] -/// impl Hooks for Pallet { -/// } -/// ``` -/// and write inside `on_initialize`, `on_finalize`, `on_runtime_upgrade`, -/// `offchain_worker`, and `integrity_test`. -/// -/// then write: -/// ```ignore -/// #[pallet::call] -/// impl Pallet { -/// } -/// ``` -/// and write inside all the calls in `decl_module` with a few changes in the signature: -/// - origin must now be written completely, e.g. `origin: OriginFor` -/// - result type must be `DispatchResultWithPostInfo`, you need to write it and also you -/// might need to put `Ok(().into())` at the end or the function. -/// - `#[compact]` must now be written -/// [`#[pallet::compact]`](#palletcompact-some_arg-some_type) -/// - `#[weight = ..]` must now be written [`#[pallet::weight(..)]`](#palletweightexpr) -/// -/// 7. **migrate event**: rewrite as a simple enum with the attribute -/// [`#[pallet::event]`](#event-palletevent-optional), use [`#[pallet::generate_deposit($vis -/// fn deposit_event)]`](#event-palletevent-optional) to generate `deposit_event`, -/// 8. **migrate error**: rewrite it with attribute -/// [`#[pallet::error]`](#error-palleterror-optional). -/// 9. **migrate storage**: `decl_storage` provide an upgrade template (see 3.). All storages, -/// genesis config, genesis build and default implementation of genesis config can be taken -/// from it directly. -/// -/// Otherwise here is the manual process: -/// -/// first migrate the genesis logic. write: -/// ```ignore -/// #[pallet::genesis_config] -/// struct GenesisConfig { -/// // fields of add_extra_genesis -/// } -/// impl Default for GenesisConfig { -/// // type default or default provided for fields -/// } -/// #[pallet::genesis_build] -/// impl GenesisBuild for GenesisConfig { -/// // for instantiable pallet: -/// // `impl GenesisBuild for GenesisConfig { -/// fn build() { -/// // The add_extra_genesis build logic -/// } -/// } -/// ``` -/// for each storage, if it contains `config(..)` then add fields, and make it default to -/// the value in `= ..;` or the type default if none, if it contains no build then also add -/// the logic to build the value. for each storage if it contains `build(..)` then add the -/// logic to `genesis_build`. -/// -/// NOTE: within `decl_storage`: the individual config is executed first, followed by the -/// build and finally the `add_extra_genesis` build. -/// -/// Once this is done you can migrate storages individually, a few notes: -/// - for private storage use `pub(crate) type ` or `pub(super) type` or nothing, -/// - for storages with `get(fn ..)` use [`#[pallet::getter(fn -/// ...)]`](#palletgetterfn-my_getter_fn_name-optional) -/// - for storages with value being `Option<$something>` make generic `Value` being -/// `$something` and generic `QueryKind` being `OptionQuery` (note: this is default). -/// Otherwise make `Value` the complete value type and `QueryKind` being `ValueQuery`. -/// - for storages with default value: `= $expr;` provide some specific `OnEmpty` generic. -/// To do so use of `#[pallet::type_value]` to generate the wanted struct to put. -/// example: `MyStorage: u32 = 3u32` would be written: -/// -/// ```ignore -/// #[pallet::type_value] fn MyStorageOnEmpty() -> u32 { 3u32 } -/// #[pallet::storage] -/// pub(super) type MyStorage = StorageValue<_, u32, ValueQuery, MyStorageOnEmpty>; -/// ``` -/// -/// NOTE: `decl_storage` also generates the functions `assimilate_storage` and -/// `build_storage` directly on `GenesisConfig`, and these are sometimes used in tests. -/// In order not to break they can be implemented manually, one can implement those -/// functions by calling the `GenesisBuild` implementation. -/// 10. **migrate origin**: move the origin to the pallet module to be under a -/// [`#[pallet::origin]`](#origin-palletorigin-optional) attribute -/// 11. **migrate validate_unsigned**: move the -/// [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`) implementation to the pallet -/// module under a -/// [`#[pallet::validate_unsigned]`](#validate-unsigned-palletvalidate_unsigned-optional) -/// attribute -/// 12. **migrate provide_inherent**: move the -/// [`ProvideInherent`](`pallet_prelude::ProvideInherent`) implementation to the pallet -/// module under a [`#[pallet::inherent]`](#inherent-palletinherent-optional) attribute -/// 13. rename the usage of `Module` to `Pallet` inside the crate. -/// 14. migration is done, now double check the migration with the checking migration -/// guidelines shown below. -/// -/// # Checking upgrade guidelines: -/// -/// * compare metadata. Use [subsee](https://github.com/ascjones/subsee) to fetch the metadata -/// and do a diff of the resulting json before and after migration. This checks for: -/// * call, names, signature, docs -/// * event names, docs -/// * error names, docs -/// * storage names, hasher, prefixes, default value -/// * error, error, constant -/// * manually check that: -/// * `Origin` was moved inside the macro under -/// [`#[pallet::origin]`](#origin-palletorigin-optional) if it exists -/// * [`ValidateUnsigned`](`pallet_prelude::ValidateUnsigned`) was moved inside the macro -/// under -/// [`#[pallet::validate_unsigned)]`](#validate-unsigned-palletvalidate_unsigned-optional) -/// if it exists -/// * [`ProvideInherent`](`pallet_prelude::ProvideInherent`) was moved inside the macro -/// under [`#[pallet::inherent)]`](#inherent-palletinherent-optional) if it exists -/// * `on_initialize` / `on_finalize` / `on_runtime_upgrade` / `offchain_worker` were moved -/// to the `Hooks` implementation -/// * storages with `config(..)` were converted to `GenesisConfig` field, and their default -/// is `= $expr;` if the storage has a default value -/// * storages with `build($expr)` or `config(..)` were built in `GenesisBuild::build` -/// * `add_extra_genesis` fields were converted to `GenesisConfig` field with their correct -/// default if specified -/// * `add_extra_genesis` build was written into `GenesisBuild::build` -/// * storage items defined with [`pallet`] use the name of the pallet provided by -/// [`traits::PalletInfo::name`] as `pallet_prefix` (in `decl_storage`, storage items used -/// the `pallet_prefix` given as input of `decl_storage` with the syntax `as Example`). Thus -/// a runtime using the pallet must be careful with this change. To handle this change: -/// * either ensure that the name of the pallet given to `construct_runtime!` is the same -/// as the name the pallet was giving to `decl_storage`, -/// * or do a storage migration from the old prefix used to the new prefix used. -/// -/// NOTE: The prefixes used by storage items are in metadata. Thus, ensuring the metadata -/// hasn't changed ensures that the `pallet_prefix`s used by the storage items haven't changed. -/// -/// # Notes when macro fails to show proper error message spans: -/// -/// Rustc loses span for some macro input. Some tips to fix it: -/// * do not use inner attribute: -/// ```ignore -/// #[pallet] -/// pub mod pallet { -/// //! This inner attribute will make span fail -/// .. -/// } -/// ``` -/// * use the newest nightly possible. +///
+/// WARNING:
+/// You should not deploy or use dev mode pallets in production. Doing so can break your
+/// chain and therefore should never be done. Once you are done tinkering, you should
+/// remove the 'dev_mode' argument from your #[pallet] declaration and fix any compile
+/// errors before attempting to use your pallet in a production scenario.
+/// 
pub use frame_support_procedural::pallet; -/// Contains macro stubs for all of the pallet:: macros -pub mod pallet_macros { - pub use frame_support_procedural::{ - composite_enum, config, disable_frame_system_supertrait_check, disable_try_decode_storage, - error, event, extra_constants, feeless_if, generate_deposit, generate_store, getter, hooks, - import_section, inherent, no_default, no_default_bounds, pallet_section, storage_prefix, - storage_version, type_value, unbounded, validate_unsigned, weight, whitelist_storage, - }; +/// Contains macro stubs for all of the `pallet::` macros +pub mod pallet_macros { + /// Declare the storage as whitelisted from benchmarking. + /// + /// Doing so will exclude reads of that value's storage key from counting towards weight + /// calculations during benchmarking. + /// + /// This attribute should only be attached to storages that are known to be + /// read/used in every block. This will result in a more accurate benchmarking weight. + /// + /// ### Example + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::storage] + /// #[pallet::whitelist_storage] + /// pub type MyStorage = StorageValue<_, u32>; + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + pub use frame_support_procedural::whitelist_storage; + + /// Allows specifying the weight of a call. + /// + /// Each dispatchable needs to define a weight with the `#[pallet::weight($expr)]` + /// attribute. The first argument must be `origin: OriginFor`. + /// + /// ## Example + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # use frame_system::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::call] + /// impl Pallet { + /// #[pallet::weight({0})] // <- set actual weight here + /// #[pallet::call_index(0)] + /// pub fn something( + /// _: OriginFor, + /// foo: u32, + /// ) -> DispatchResult { + /// unimplemented!() + /// } + /// } + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + pub use frame_support_procedural::weight; + + /// Allows whitelisting a storage item from decoding during try-runtime checks. + /// + /// The optional attribute `#[pallet::disable_try_decode_storage]` will declare the + /// storage as whitelisted from decoding during try-runtime checks. This should only be + /// attached to transient storage which cannot be migrated during runtime upgrades. + /// + /// ### Example + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::storage] + /// #[pallet::disable_try_decode_storage] + /// pub type MyStorage = StorageValue<_, u32>; + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + pub use frame_support_procedural::disable_try_decode_storage; + + /// Declares a storage as unbounded in potential size. + /// + /// When implementating the storage info (when `#[pallet::generate_storage_info]` is + /// specified on the pallet struct placeholder), the size of the storage will be declared + /// as unbounded. This can be useful for storage which can never go into PoV (Proof of + /// Validity). + /// + /// ## Example + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::storage] + /// #[pallet::unbounded] + /// pub type MyStorage = StorageValue<_, u32>; + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + pub use frame_support_procedural::unbounded; + + /// Defines what storage prefix to use for a storage item when building the trie. + /// + /// This is helpful if you wish to rename the storage field but don't want to perform a + /// migration. + /// + /// ## Example + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::storage] + /// #[pallet::storage_prefix = "foo"] + /// pub type MyStorage = StorageValue<_, u32>; + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + pub use frame_support_procedural::storage_prefix; + + /// Ensures the generated `DefaultConfig` will not have any bounds for + /// that trait item. + /// + /// Attaching this attribute to a trait item ensures that the generated trait + /// `DefaultConfig` will not have any bounds for this trait item. + /// + /// As an example, if you have a trait item `type AccountId: SomeTrait;` in your `Config` + /// trait, the generated `DefaultConfig` will only have `type AccountId;` with no trait + /// bound. + pub use frame_support_procedural::no_default_bounds; + + /// Ensures the trait item will not be used as a default with the + /// `#[derive_impl(..)]` attribute macro. + /// + /// The optional attribute `#[pallet::no_default]` can be attached to trait items within a + /// `Config` trait impl that has [`#[pallet::config(with_default)]`](`config`) + /// attached. + pub use frame_support_procedural::no_default; + + /// Declares a module as importable into a pallet via + /// [`#[import_section]`](`import_section`). + /// + /// Note that sections are imported by their module name/ident, and should be referred to + /// by their _full path_ from the perspective of the target pallet. Do not attempt to make + /// use of `use` statements to bring pallet sections into scope, as this will not work + /// (unless you do so as part of a wildcard import, in which case it will work). + /// + /// ## Naming Logistics + /// + /// Also note that because of how `#[pallet_section]` works, pallet section names must be + /// globally unique _within the crate in which they are defined_. For more information on + /// why this must be the case, see macro_magic's + /// [`#[export_tokens]`](https://docs.rs/macro_magic/latest/macro_magic/attr.export_tokens.html) macro. + /// + /// Optionally, you may provide an argument to `#[pallet_section]` such as + /// `#[pallet_section(some_ident)]`, in the event that there is another pallet section in + /// same crate with the same ident/name. The ident you specify can then be used instead of + /// the module's ident name when you go to import it via + /// [`#[import_section]`](`import_section`). + pub use frame_support_procedural::pallet_section; + + /// The `#[pallet::inherent]` attribute allows the pallet to provide + /// [inherents](https://docs.substrate.io/fundamentals/transaction-types/#inherent-transactions). + /// + /// An inherent is some piece of data that is inserted by a block authoring node at block + /// creation time and can either be accepted or rejected by validators based on whether the + /// data falls within an acceptable range. + /// + /// The most common inherent is the `timestamp` that is inserted into every block. Since + /// there is no way to validate timestamps, validators simply check that the timestamp + /// reported by the block authoring node falls within an acceptable range. + /// + /// Example usage: + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # use frame_support::inherent::IsFatalError; + /// # use sp_timestamp::InherentError; + /// # use sp_std::result; + /// # + /// // Example inherent identifier + /// pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0"; + /// + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::inherent] + /// impl ProvideInherent for Pallet { + /// type Call = Call; + /// type Error = InherentError; + /// const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + /// + /// fn create_inherent(data: &InherentData) -> Option { + /// unimplemented!() + /// } + /// + /// fn check_inherent( + /// call: &Self::Call, + /// data: &InherentData, + /// ) -> result::Result<(), Self::Error> { + /// unimplemented!() + /// } + /// + /// fn is_inherent(call: &Self::Call) -> bool { + /// unimplemented!() + /// } + /// } + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + /// + /// I.e. a trait implementation with bound `T: Config`, of trait `ProvideInherent` for type + /// `Pallet`, and some optional where clause. + /// + /// ## Macro expansion + /// + /// The macro currently makes no use of this information, but it might use this information + /// in the future to give information directly to `construct_runtime`. + pub use frame_support_procedural::inherent; + + /// Splits a pallet declaration into multiple parts. + /// + /// An attribute macro that can be attached to a module declaration. Doing so will + /// import the contents of the specified external pallet section that is defined + /// elsewhere using [`#[pallet_section]`](`pallet_section`). + /// + /// ## Example + /// ``` + /// # use frame_support::pallet_macros::pallet_section; + /// # use frame_support::pallet_macros::import_section; + /// # + /// /// A [`pallet_section`] that defines the events for a pallet. + /// /// This can later be imported into the pallet using [`import_section`]. + /// #[pallet_section] + /// mod events { + /// #[pallet::event] + /// #[pallet::generate_deposit(pub(super) fn deposit_event)] + /// pub enum Event { + /// /// Event documentation should end with an array that provides descriptive names for event + /// /// parameters. [something, who] + /// SomethingStored { something: u32, who: T::AccountId }, + /// } + /// } + /// + /// #[import_section(events)] + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config { + /// # type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// # } + /// } + /// ``` + /// + /// This will result in the contents of `some_section` being _verbatim_ imported into + /// the pallet above. Note that since the tokens for `some_section` are essentially + /// copy-pasted into the target pallet, you cannot refer to imports that don't also + /// exist in the target pallet, but this is easily resolved by including all relevant + /// `use` statements within your pallet section, so they are imported as well, or by + /// otherwise ensuring that you have the same imports on the target pallet. + /// + /// It is perfectly permissible to import multiple pallet sections into the same pallet, + /// which can be done by having multiple `#[import_section(something)]` attributes + /// attached to the pallet. + /// + /// Note that sections are imported by their module name/ident, and should be referred to + /// by their _full path_ from the perspective of the target pallet. + pub use frame_support_procedural::import_section; + + /// Allows defining getter functions on `Pallet` storage. + /// + /// ## Example + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::storage] + /// #[pallet::getter(fn my_getter_fn_name)] + /// pub type MyStorage = StorageValue<_, u32>; + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + /// + /// See [`pallet::storage`](`frame_support::pallet_macros::storage`) for more info. + pub use frame_support_procedural::getter; + + /// Allows generating the `Store` trait for all storages. + /// + /// DEPRECATED: Will be removed, do not use. + /// See for more details. + /// + /// To generate a `Store` trait associating all storages, annotate your `Pallet` struct + /// with the attribute `#[pallet::generate_store($vis trait Store)]`, e.g.: + /// + /// ```ignore + /// #[pallet::pallet] + /// #[pallet::generate_store(pub(super) trait Store)] + /// pub struct Pallet(_); + /// ``` + /// More precisely, the `Store` trait contains an associated type for each storage. It is + /// implemented for `Pallet` allowing access to the storage from pallet struct. + /// + /// Thus when defining a storage named `Foo`, it can later be accessed from `Pallet` using + /// `::Foo`. + pub use frame_support_procedural::generate_store; + + /// Defines constants that are added to the constant field of + /// [`PalletMetadata`](frame_metadata::v15::PalletMetadata) struct for this pallet. + /// + /// Must be defined like: + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// # + /// #[pallet::extra_constants] + /// impl Pallet // $optional_where_clause + /// { + /// #[pallet::constant_name(SomeU32ConstantName)] + /// /// Some doc + /// fn some_u32_constant() -> u32 { + /// 100u32 + /// } + /// } + /// } + /// ``` + /// + /// I.e. a regular rust `impl` block with some optional where clause and functions with 0 + /// args, 0 generics, and some return type. + pub use frame_support_procedural::extra_constants; + + #[rustfmt::skip] + /// Allows bypassing the `frame_system::Config` supertrait check. + /// + /// To bypass the syntactic `frame_system::Config` supertrait check, use the attribute + /// `pallet::disable_frame_system_supertrait_check`. + /// + /// Note this bypass is purely syntactic, and does not actually remove the requirement that your + /// pallet implements `frame_system::Config`. When using this check, your config is still required to implement + /// `frame_system::Config` either via + /// - Implementing a trait that itself implements `frame_system::Config` + /// - Tightly coupling it with another pallet which itself implements `frame_system::Config` + /// + /// e.g. + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # use frame_system::pallet_prelude::*; + /// trait OtherTrait: frame_system::Config {} + /// + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::config] + /// #[pallet::disable_frame_system_supertrait_check] + /// pub trait Config: OtherTrait {} + /// } + /// ``` + /// + /// To learn more about supertraits, see the + /// [trait_based_programming](../../polkadot_sdk_docs/reference_docs/trait_based_programming/index.html) + /// reference doc. + pub use frame_support_procedural::disable_frame_system_supertrait_check; + + /// The mandatory attribute allowing definition of configurable types for the pallet. + /// + /// Item must be defined as: + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::config] + /// pub trait Config: frame_system::Config // + $optionally_some_other_supertraits + /// // $optional_where_clause + /// { + /// // config items here + /// } + /// } + /// ``` + /// + /// I.e. a regular trait definition named `Config`, with the supertrait + /// [`frame_system::pallet::Config`](../../frame_system/pallet/trait.Config.html), and + /// optionally other supertraits and a where clause. (Specifying other supertraits here is + /// known as [tight coupling](https://docs.substrate.io/reference/how-to-guides/pallet-design/use-tight-coupling/)) + /// + /// The associated type `RuntimeEvent` is reserved. If defined, it must have the bounds + /// `From` and `IsType<::RuntimeEvent>`. + /// + /// [`#[pallet::event]`](`event`) must be present if `RuntimeEvent` + /// exists as a config item in your `#[pallet::config]`. + /// + /// ## Optional: `with_default` + /// + /// An optional `with_default` argument may also be specified. Doing so will automatically + /// generate a `DefaultConfig` trait inside your pallet which is suitable for use with + /// [`#[derive_impl(..)`](`frame_support::derive_impl`) to derive a default testing + /// config: + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # use frame_system::pallet_prelude::*; + /// # use core::fmt::Debug; + /// # use frame_support::traits::Contains; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::config(with_default)] // <- with_default is optional + /// pub trait Config: frame_system::Config { + /// /// The overarching event type. + /// #[pallet::no_default_bounds] // Default is not supported for RuntimeEvent + /// type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// + /// // ...other config items get default + /// } + /// + /// #[pallet::event] + /// pub enum Event { + /// SomeEvent(u16, u32), + /// } + /// } + /// ``` + /// + /// As shown above, you may also attach the [`#[pallet::no_default]`](`no_default`) + /// attribute to specify that a particular trait item _cannot_ be used as a default when a + /// test `Config` is derived using the [`#[derive_impl(..)]`](`frame_support::derive_impl`) + /// attribute macro. This will cause that particular trait item to simply not appear in + /// default testing configs based on this config (the trait item will not be included in + /// `DefaultConfig`). + /// + /// ### `DefaultConfig` Caveats + /// + /// The auto-generated `DefaultConfig` trait: + /// - is always a _subset_ of your pallet's `Config` trait. + /// - can only contain items that don't rely on externalities, such as + /// `frame_system::Config`. + /// + /// Trait items that _do_ rely on externalities should be marked with + /// [`#[pallet::no_default]`](`no_default`) + /// + /// Consequently: + /// - Any items that rely on externalities _must_ be marked with + /// [`#[pallet::no_default]`](`no_default`) or your trait will fail to compile when used + /// with [`derive_impl`](`frame_support::derive_impl`). + /// - Items marked with [`#[pallet::no_default]`](`no_default`) are entirely excluded from + /// the `DefaultConfig` trait, and therefore any impl of `DefaultConfig` doesn't need to + /// implement such items. + /// + /// For more information, see [`frame_support::derive_impl`]. + pub use frame_support_procedural::config; + + /// Allows defining an enum that gets composed as an aggregate enum by `construct_runtime`. + /// + /// The `#[pallet::composite_enum]` attribute allows you to define an enum that gets + /// composed as an aggregate enum by `construct_runtime`. This is similar in principle with + /// [frame_support_procedural::event] and [frame_support_procedural::error]. + /// + /// The attribute currently only supports enum definitions, and identifiers that are named + /// `FreezeReason`, `HoldReason`, `LockId` or `SlashReason`. Arbitrary identifiers for the + /// enum are not supported. The aggregate enum generated by + /// [`frame_support::construct_runtime`](frame_support::construct_runtime) will have the + /// name of `RuntimeFreezeReason`, `RuntimeHoldReason`, `RuntimeLockId` and + /// `RuntimeSlashReason` respectively. + /// + /// NOTE: The aggregate enum generated by `construct_runtime` generates a conversion + /// function from the pallet enum to the aggregate enum, and automatically derives the + /// following traits: + /// + /// ```ignore + /// Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, TypeInfo, + /// RuntimeDebug + /// ``` + /// + /// For ease of usage, when no `#[derive]` attributes are found for the enum under + /// [`#[pallet::composite_enum]`](composite_enum), the aforementioned traits are + /// automatically derived for it. The inverse is also true: if there are any `#[derive]` + /// attributes found for the enum, then no traits will automatically be derived for it. + /// + /// e.g, defining `HoldReason` in a pallet + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::composite_enum] + /// pub enum HoldReason { + /// /// The NIS Pallet has reserved it for a non-fungible receipt. + /// #[codec(index = 0)] + /// SomeHoldReason, + /// #[codec(index = 1)] + /// SomeOtherHoldReason, + /// } + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + pub use frame_support_procedural::composite_enum; + + /// Allows the pallet to validate unsigned transactions. + /// + /// Item must be defined as: + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::validate_unsigned] + /// impl sp_runtime::traits::ValidateUnsigned for Pallet { + /// type Call = Call; + /// + /// fn validate_unsigned(_source: TransactionSource, _call: &Self::Call) -> TransactionValidity { + /// // Your implementation details here + /// unimplemented!() + /// } + /// } + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + /// + /// I.e. a trait implementation with bound `T: Config`, of trait + /// [`ValidateUnsigned`](frame_support::pallet_prelude::ValidateUnsigned) for + /// type `Pallet`, and some optional where clause. + /// + /// NOTE: There is also the [`sp_runtime::traits::SignedExtension`] trait that can be used + /// to add some specific logic for transaction validation. + /// + /// ## Macro expansion + /// + /// The macro currently makes no use of this information, but it might use this information + /// in the future to give information directly to [`frame_support::construct_runtime`]. + pub use frame_support_procedural::validate_unsigned; + + /// Allows defining a struct implementing the [`Get`](frame_support::traits::Get) trait to + /// ease the use of storage types. + /// + /// This attribute is meant to be used alongside [`#[pallet::storage]`](`storage`) to + /// define a storage's default value. This attribute can be used multiple times. + /// + /// Item must be defined as: + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use sp_runtime::FixedU128; + /// # use frame_support::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::storage] + /// pub(super) type SomeStorage = + /// StorageValue<_, FixedU128, ValueQuery, DefaultForSomeValue>; + /// + /// // Define default for ParachainId + /// #[pallet::type_value] + /// pub fn DefaultForSomeValue() -> FixedU128 { + /// FixedU128::from_u32(1) + /// } + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + /// + /// ## Macro expansion + /// + /// The macro renames the function to some internal name, generates a struct with the + /// original name of the function and its generic, and implements `Get<$ReturnType>` by + /// calling the user defined function. + pub use frame_support_procedural::type_value; + + /// Allows defining a storage version for the pallet. + /// + /// Because the `pallet::pallet` macro implements + /// [`GetStorageVersion`](frame_support::traits::GetStorageVersion), the current storage + /// version needs to be communicated to the macro. This can be done by using the + /// `pallet::storage_version` attribute: + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::StorageVersion; + /// # use frame_support::traits::GetStorageVersion; + /// # + /// const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); + /// + /// #[pallet::pallet] + /// #[pallet::storage_version(STORAGE_VERSION)] + /// pub struct Pallet(_); + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + /// + /// If not present, the current storage version is set to the default value. + pub use frame_support_procedural::storage_version; + + /// The `#[pallet::hooks]` attribute allows you to specify a + /// [`frame_support::traits::Hooks`] implementation for `Pallet` that specifies + /// pallet-specific logic. + /// + /// The item the attribute attaches to must be defined as follows: + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # use frame_system::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::hooks] + /// impl Hooks> for Pallet { + /// // Implement hooks here + /// } + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + /// I.e. a regular trait implementation with generic bound: `T: Config`, for the trait + /// `Hooks>` (they are defined in preludes), for the type `Pallet`. + /// + /// Optionally, you could add a where clause. + /// + /// ## Macro expansion + /// + /// The macro implements the traits + /// [`OnInitialize`](frame_support::traits::OnInitialize), + /// [`OnIdle`](frame_support::traits::OnIdle), + /// [`OnFinalize`](frame_support::traits::OnFinalize), + /// [`OnRuntimeUpgrade`](frame_support::traits::OnRuntimeUpgrade), + /// [`OffchainWorker`](frame_support::traits::OffchainWorker), and + /// [`IntegrityTest`](frame_support::traits::IntegrityTest) using + /// the provided [`Hooks`](frame_support::traits::Hooks) implementation. + /// + /// NOTE: `OnRuntimeUpgrade` is implemented with `Hooks::on_runtime_upgrade` and some + /// additional logic. E.g. logic to write the pallet version into storage. + /// + /// NOTE: The macro also adds some tracing logic when implementing the above traits. The + /// following hooks emit traces: `on_initialize`, `on_finalize` and `on_runtime_upgrade`. + pub use frame_support_procedural::hooks; + + /// Generates a helper function on `Pallet` that handles deposit events. + /// + /// NOTE: For instantiable pallets, the event must be generic over `T` and `I`. + /// + /// ## Macro expansion + /// + /// The macro will add on enum `Event` the attributes: + /// * `#[derive(`[`frame_support::CloneNoBound`]`)]` + /// * `#[derive(`[`frame_support::EqNoBound`]`)]` + /// * `#[derive(`[`frame_support::PartialEqNoBound`]`)]` + /// * `#[derive(`[`frame_support::RuntimeDebugNoBound`]`)]` + /// * `#[derive(`[`codec::Encode`]`)]` + /// * `#[derive(`[`codec::Decode`]`)]` + /// + /// The macro implements `From>` for (). + /// + /// The macro implements a metadata function on `Event` returning the `EventMetadata`. + /// + /// If `#[pallet::generate_deposit]` is present then the macro implements `fn + /// deposit_event` on `Pallet`. + pub use frame_support_procedural::generate_deposit; + + /// Allows defining logic to make an extrinsic call feeless. + /// + /// Each dispatchable may be annotated with the `#[pallet::feeless_if($closure)]` + /// attribute, which explicitly defines the condition for the dispatchable to be feeless. + /// + /// The arguments for the closure must be the referenced arguments of the dispatchable + /// function. + /// + /// The closure must return `bool`. + /// + /// ### Example + /// + /// ``` + /// #[frame_support::pallet(dev_mode)] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # use frame_system::pallet_prelude::*; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::call] + /// impl Pallet { + /// #[pallet::call_index(0)] + /// /// Marks this call as feeless if `foo` is zero. + /// #[pallet::feeless_if(|_origin: &OriginFor, foo: &u32| -> bool { + /// *foo == 0 + /// })] + /// pub fn something( + /// _: OriginFor, + /// foo: u32, + /// ) -> DispatchResult { + /// unimplemented!() + /// } + /// } + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + /// + /// Please note that this only works for signed dispatchables and requires a signed + /// extension such as [`pallet_skip_feeless_payment::SkipCheckIfFeeless`] to wrap the + /// existing payment extension. Else, this is completely ignored and the dispatchable is + /// still charged. + /// + /// ### Macro expansion + /// + /// The macro implements the [`pallet_skip_feeless_payment::CheckIfFeeless`] trait on the + /// dispatchable and calls the corresponding closure in the implementation. + /// + /// [`pallet_skip_feeless_payment::SkipCheckIfFeeless`]: ../../pallet_skip_feeless_payment/struct.SkipCheckIfFeeless.html + /// [`pallet_skip_feeless_payment::CheckIfFeeless`]: ../../pallet_skip_feeless_payment/struct.SkipCheckIfFeeless.html + pub use frame_support_procedural::feeless_if; + + /// Allows defining an error enum that will be returned from the dispatchable when an error + /// occurs. + /// + /// The information for this error type is then stored in runtime metadata. + /// + /// Item must be defined as so: + /// + /// ``` + /// #[frame_support::pallet(dev_mode)] + /// mod pallet { + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::error] + /// pub enum Error { + /// /// SomeFieldLessVariant doc + /// SomeFieldLessVariant, + /// /// SomeVariantWithOneField doc + /// SomeVariantWithOneField(u32), + /// } + /// # + /// # #[pallet::config] + /// # pub trait Config: frame_system::Config {} + /// } + /// ``` + /// I.e. a regular enum named `Error`, with generic `T` and fieldless or multiple-field + /// variants. + /// + /// Any field type in the enum variants must implement [`scale_info::TypeInfo`] in order to + /// be properly used in the metadata, and its encoded size should be as small as possible, + /// preferably 1 byte in size in order to reduce storage size. The error enum itself has an + /// absolute maximum encoded size specified by + /// [`frame_support::MAX_MODULE_ERROR_ENCODED_SIZE`]. + /// + /// (1 byte can still be 256 different errors. The more specific the error, the easier it + /// is to diagnose problems and give a better experience to the user. Don't skimp on having + /// lots of individual error conditions.) + /// + /// Field types in enum variants must also implement [`frame_support::PalletError`], + /// otherwise the pallet will fail to compile. Rust primitive types have already + /// implemented the [`frame_support::PalletError`] trait along with some commonly used + /// stdlib types such as [`Option`] and [`sp_std::marker::PhantomData`], and hence + /// in most use cases, a manual implementation is not necessary and is discouraged. + /// + /// The generic `T` must not bound anything and a `where` clause is not allowed. That said, + /// bounds and/or a where clause should not needed for any use-case. + /// + /// ## Macro expansion + /// + /// The macro implements the [`Debug`] trait and functions `as_u8` using variant position, + /// and `as_str` using variant doc. + /// + /// The macro also implements `From>` for `&'static str` and `From>` for + /// `DispatchError`. + pub use frame_support_procedural::error; + + /// Allows defining pallet events. + /// + /// Pallet events are stored under the `system` / `events` key when the block is applied + /// (and then replaced when the next block writes it's events). + /// + /// The Event enum can be defined as follows: + /// + /// ``` + /// #[frame_support::pallet(dev_mode)] + /// mod pallet { + /// # use frame_support::pallet_prelude::IsType; + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::event] + /// #[pallet::generate_deposit(fn deposit_event)] // Optional + /// pub enum Event { + /// /// SomeEvent doc + /// SomeEvent(u16, u32), // SomeEvent with two fields + /// } + /// + /// #[pallet::config] + /// pub trait Config: frame_system::Config { + /// /// The overarching runtime event type. + /// type RuntimeEvent: From> + /// + IsType<::RuntimeEvent>; + /// } + /// } + /// ``` + /// + /// I.e. an enum (with named or unnamed fields variant), named `Event`, with generic: none + /// or `T` or `T: Config`, and optional w here clause. + /// + /// `RuntimeEvent` must be defined in the `Config`, as shown in the example. + /// + /// Each field must implement [`Clone`], [`Eq`], [`PartialEq`], [`codec::Encode`], + /// [`codec::Decode`], and [`Debug`] (on std only). For ease of use, bound by the trait + /// `Member`, available in [`frame_support::pallet_prelude`]. + pub use frame_support_procedural::event; - /// Allows a pallet to declare a set of functions as a *dispatchable extrinsic*. In - /// slightly simplified terms, this macro declares the set of "transactions" of a pallet. + /// Allows a pallet to declare a set of functions as a *dispatchable extrinsic*. + /// + /// In slightly simplified terms, this macro declares the set of "transactions" of a + /// pallet. /// /// > The exact definition of **extrinsic** can be found in /// > [`sp_runtime::generic::UncheckedExtrinsic`]. @@ -2391,14 +2003,24 @@ pub mod pallet_macros { /// If no `#[pallet::call]` exists, then a default implementation corresponding to the /// following code is automatically generated: /// - /// ```ignore - /// #[pallet::call] - /// impl Pallet {} + /// ``` + /// #[frame_support::pallet(dev_mode)] + /// mod pallet { + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::call] // <- automatically generated + /// impl Pallet {} // <- automatically generated + /// + /// #[pallet::config] + /// pub trait Config: frame_system::Config {} + /// } /// ``` pub use frame_support_procedural::call; - /// Enforce the index of a variant in the generated `enum Call`. See [`call`] for more - /// information. + /// Enforce the index of a variant in the generated `enum Call`. + /// + /// See [`call`] for more information. /// /// All call indexes start from 0, until it encounters a dispatchable function with a /// defined call index. The dispatchable function that lexically follows the function with @@ -2408,7 +2030,9 @@ pub mod pallet_macros { pub use frame_support_procedural::call_index; /// Declares the arguments of a [`call`] function to be encoded using - /// [`codec::Compact`]. This will results in smaller extrinsic encoding. + /// [`codec::Compact`]. + /// + /// This will results in smaller extrinsic encoding. /// /// A common example of `compact` is for numeric values that are often times far far away /// from their theoretical maximum. For example, in the context of a crypto-currency, the @@ -2504,8 +2128,8 @@ pub mod pallet_macros { /// ``` pub use frame_support_procedural::genesis_build; - /// The `#[pallet::constant]` attribute can be used to add an associated type trait bounded - /// by [`Get`](frame_support::pallet_prelude::Get) from [`pallet::config`](`macro@config`) + /// Allows adding an associated type trait bounded by + /// [`Get`](frame_support::pallet_prelude::Get) from [`pallet::config`](`macro@config`) /// into metadata. /// /// ## Example @@ -2526,9 +2150,10 @@ pub mod pallet_macros { /// ``` pub use frame_support_procedural::constant; - /// Declares a type alias as a storage item. Storage items are pointers to data stored - /// on-chain (the *blockchain state*), under a specific key. The exact key is dependent on - /// the type of the storage. + /// Declares a type alias as a storage item. + /// + /// Storage items are pointers to data stored on-chain (the *blockchain state*), under a + /// specific key. The exact key is dependent on the type of the storage. /// /// > From the perspective of this pallet, the entire blockchain state is abstracted behind /// > a key-value api, namely [`sp_io::storage`]. @@ -2730,7 +2355,10 @@ pub mod pallet_macros { /// } /// ``` pub use frame_support_procedural::storage; - /// This attribute is attached to a function inside an `impl` block annotated with + + /// Allows defining conditions for a task to run. + /// + /// This attribute is attached to a function inside an `impl` block annoated with /// [`pallet::tasks_experimental`](`tasks_experimental`) to define the conditions for a /// given work item to be valid. /// @@ -2738,29 +2366,39 @@ pub mod pallet_macros { /// should have the same signature as the function it is attached to, except that it should /// return a `bool` instead. pub use frame_support_procedural::task_condition; - /// This attribute is attached to a function inside an `impl` block annotated with + + /// Allows defining an index for a task. + /// + /// This attribute is attached to a function inside an `impl` block annoated with /// [`pallet::tasks_experimental`](`tasks_experimental`) to define the index of a given /// work item. /// /// It takes an integer literal as input, which is then used to define the index. This /// index should be unique for each function in the `impl` block. pub use frame_support_procedural::task_index; - /// This attribute is attached to a function inside an `impl` block annotated with - /// [`pallet::tasks_experimental`](`tasks_experimental`) to define an iterator over the - /// available work items for a task. + + /// Allows defining an iterator over available work items for a task. + /// + /// This attribute is attached to a function inside an `impl` block annoated with + /// [`pallet::tasks_experimental`](`tasks_experimental`). /// /// It takes an iterator as input that yields a tuple with same types as the function /// arguments. pub use frame_support_procedural::task_list; - /// This attribute is attached to a function inside an `impl` block annotated with + + /// Allows defining the weight of a task. + /// + /// This attribute is attached to a function inside an `impl` block annoated with /// [`pallet::tasks_experimental`](`tasks_experimental`) define the weight of a given work /// item. /// /// It takes a closure as input, which should return a `Weight` value. pub use frame_support_procedural::task_weight; + /// Allows you to define some service work that can be recognized by a script or an - /// off-chain worker. Such a script can then create and submit all such work items at any - /// given time. + /// off-chain worker. + /// + /// Such a script can then create and submit all such work items at any given time. /// /// These work items are defined as instances of the [`Task`](frame_support::traits::Task) /// trait. [`pallet:tasks_experimental`](`tasks_experimental`) when attached to an `impl` @@ -2814,7 +2452,7 @@ pub mod pallet_macros { /// } /// ``` /// - /// Or, more commonly used:/ + /// Or, more commonly used: /// /// ``` /// #[frame_support::pallet] @@ -2839,6 +2477,9 @@ pub mod pallet_macros { /// /// Modifying any pallet's origin type will cause the runtime level origin type to also /// change in encoding. If stored anywhere on-chain, this will require a data migration. + /// + /// Read more about origins at the [Origin Reference + /// Docs](../../polkadot_sdk_docs/reference_docs/frame_origin/index.html). pub use frame_support_procedural::origin; } -- GitLab From fd5f9292f500652e1d4792b09fb8ac60e1268ce4 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Mon, 4 Mar 2024 20:12:43 +0100 Subject: [PATCH 062/188] FRAME: Create `TransactionExtension` as a replacement for `SignedExtension` (#2280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #2160 First part of [Extrinsic Horizon](https://github.com/paritytech/polkadot-sdk/issues/2415) Introduces a new trait `TransactionExtension` to replace `SignedExtension`. Introduce the idea of transactions which obey the runtime's extensions and have according Extension data (né Extra data) yet do not have hard-coded signatures. Deprecate the terminology of "Unsigned" when used for transactions/extrinsics owing to there now being "proper" unsigned transactions which obey the extension framework and "old-style" unsigned which do not. Instead we have __*General*__ for the former and __*Bare*__ for the latter. (Ultimately, the latter will be phased out as a type of transaction, and Bare will only be used for Inherents.) Types of extrinsic are now therefore: - Bare (no hardcoded signature, no Extra data; used to be known as "Unsigned") - Bare transactions (deprecated): Gossiped, validated with `ValidateUnsigned` (deprecated) and the `_bare_compat` bits of `TransactionExtension` (deprecated). - Inherents: Not gossiped, validated with `ProvideInherent`. - Extended (Extra data): Gossiped, validated via `TransactionExtension`. - Signed transactions (with a hardcoded signature). - General transactions (without a hardcoded signature). `TransactionExtension` differs from `SignedExtension` because: - A signature on the underlying transaction may validly not be present. - It may alter the origin during validation. - `pre_dispatch` is renamed to `prepare` and need not contain the checks present in `validate`. - `validate` and `prepare` is passed an `Origin` rather than a `AccountId`. - `validate` may pass arbitrary information into `prepare` via a new user-specifiable type `Val`. - `AdditionalSigned`/`additional_signed` is renamed to `Implicit`/`implicit`. It is encoded *for the entire transaction* and passed in to each extension as a new argument to `validate`. This facilitates the ability of extensions to acts as underlying crypto. There is a new `DispatchTransaction` trait which contains only default function impls and is impl'ed for any `TransactionExtension` impler. It provides several utility functions which reduce some of the tedium from using `TransactionExtension` (indeed, none of its regular functions should now need to be called directly). Three transaction version discriminator ("versions") are now permissible: - 0b000000100: Bare (used to be called "Unsigned"): contains Signature or Extra (extension data). After bare transactions are no longer supported, this will strictly identify an Inherents only. - 0b100000100: Old-school "Signed" Transaction: contains Signature and Extra (extension data). - 0b010000100: New-school "General" Transaction: contains Extra (extension data), but no Signature. For the New-school General Transaction, it becomes trivial for authors to publish extensions to the mechanism for authorizing an Origin, e.g. through new kinds of key-signing schemes, ZK proofs, pallet state, mutations over pre-authenticated origins or any combination of the above. ## Code Migration ### NOW: Getting it to build Wrap your `SignedExtension`s in `AsTransactionExtension`. This should be accompanied by renaming your aggregate type in line with the new terminology. E.g. Before: ```rust /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( /* snip */ MySpecialSignedExtension, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; ``` After: ```rust /// The extension to the basic transaction logic. pub type TxExtension = ( /* snip */ AsTransactionExtension, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; ``` You'll also need to alter any transaction building logic to add a `.into()` to make the conversion happen. E.g. Before: ```rust fn construct_extrinsic( /* snip */ ) -> UncheckedExtrinsic { let extra: SignedExtra = ( /* snip */ MySpecialSignedExtension::new(/* snip */), ); let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); UncheckedExtrinsic::new_signed( /* snip */ Signature::Sr25519(signature), extra, ) } ``` After: ```rust fn construct_extrinsic( /* snip */ ) -> UncheckedExtrinsic { let tx_ext: TxExtension = ( /* snip */ MySpecialSignedExtension::new(/* snip */).into(), ); let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); UncheckedExtrinsic::new_signed( /* snip */ Signature::Sr25519(signature), tx_ext, ) } ``` ### SOON: Migrating to `TransactionExtension` Most `SignedExtension`s can be trivially converted to become a `TransactionExtension`. There are a few things to know. - Instead of a single trait like `SignedExtension`, you should now implement two traits individually: `TransactionExtensionBase` and `TransactionExtension`. - Weights are now a thing and must be provided via the new function `fn weight`. #### `TransactionExtensionBase` This trait takes care of anything which is not dependent on types specific to your runtime, most notably `Call`. - `AdditionalSigned`/`additional_signed` is renamed to `Implicit`/`implicit`. - Weight must be returned by implementing the `weight` function. If your extension is associated with a pallet, you'll probably want to do this via the pallet's existing benchmarking infrastructure. #### `TransactionExtension` Generally: - `pre_dispatch` is now `prepare` and you *should not reexecute the `validate` functionality in there*! - You don't get an account ID any more; you get an origin instead. If you need to presume an account ID, then you can use the trait function `AsSystemOriginSigner::as_system_origin_signer`. - You get an additional ticket, similar to `Pre`, called `Val`. This defines data which is passed from `validate` into `prepare`. This is important since you should not be duplicating logic from `validate` to `prepare`, you need a way of passing your working from the former into the latter. This is it. - This trait takes two type parameters: `Call` and `Context`. `Call` is the runtime call type which used to be an associated type; you can just move it to become a type parameter for your trait impl. `Context` is not currently used and you can safely implement over it as an unbounded type. - There's no `AccountId` associated type any more. Just remove it. Regarding `validate`: - You get three new parameters in `validate`; all can be ignored when migrating from `SignedExtension`. - `validate` returns a tuple on success; the second item in the tuple is the new ticket type `Self::Val` which gets passed in to `prepare`. If you use any information extracted during `validate` (off-chain and on-chain, non-mutating) in `prepare` (on-chain, mutating) then you can pass it through with this. For the tuple's last item, just return the `origin` argument. Regarding `prepare`: - This is renamed from `pre_dispatch`, but there is one change: - FUNCTIONALITY TO VALIDATE THE TRANSACTION NEED NOT BE DUPLICATED FROM `validate`!! - (This is different to `SignedExtension` which was required to run the same checks in `pre_dispatch` as in `validate`.) Regarding `post_dispatch`: - Since there are no unsigned transactions handled by `TransactionExtension`, `Pre` is always defined, so the first parameter is `Self::Pre` rather than `Option`. If you make use of `SignedExtension::validate_unsigned` or `SignedExtension::pre_dispatch_unsigned`, then: - Just use the regular versions of these functions instead. - Have your logic execute in the case that the `origin` is `None`. - Ensure your transaction creation logic creates a General Transaction rather than a Bare Transaction; this means having to include all `TransactionExtension`s' data. - `ValidateUnsigned` can still be used (for now) if you need to be able to construct transactions which contain none of the extension data, however these will be phased out in stage 2 of the Transactions Horizon, so you should consider moving to an extension-centric design. ## TODO - [x] Introduce `CheckSignature` impl of `TransactionExtension` to ensure it's possible to have crypto be done wholly in a `TransactionExtension`. - [x] Deprecate `SignedExtension` and move all uses in codebase to `TransactionExtension`. - [x] `ChargeTransactionPayment` - [x] `DummyExtension` - [x] `ChargeAssetTxPayment` (asset-tx-payment) - [x] `ChargeAssetTxPayment` (asset-conversion-tx-payment) - [x] `CheckWeight` - [x] `CheckTxVersion` - [x] `CheckSpecVersion` - [x] `CheckNonce` - [x] `CheckNonZeroSender` - [x] `CheckMortality` - [x] `CheckGenesis` - [x] `CheckOnlySudoAccount` - [x] `WatchDummy` - [x] `PrevalidateAttests` - [x] `GenericSignedExtension` - [x] `SignedExtension` (chain-polkadot-bulletin) - [x] `RefundSignedExtensionAdapter` - [x] Implement `fn weight` across the board. - [ ] Go through all pre-existing extensions which assume an account signer and explicitly handle the possibility of another kind of origin. - [x] `CheckNonce` should probably succeed in the case of a non-account origin. - [x] `CheckNonZeroSender` should succeed in the case of a non-account origin. - [x] `ChargeTransactionPayment` and family should fail in the case of a non-account origin. - [ ] - [x] Fix any broken tests. --------- Signed-off-by: georgepisaltu Signed-off-by: Alexandru Vasile Signed-off-by: dependabot[bot] Signed-off-by: Oliver Tale-Yazdi Signed-off-by: Alexandru Gheorghe Signed-off-by: Andrei Sandu Co-authored-by: Nikhil Gupta <17176722+gupnik@users.noreply.github.com> Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com> Co-authored-by: Chevdor Co-authored-by: Bastian Köcher Co-authored-by: Maciej Co-authored-by: Javier Viola Co-authored-by: Marcin S. Co-authored-by: Tsvetomir Dimitrov Co-authored-by: Javier Bullrich Co-authored-by: Koute Co-authored-by: Adrian Catangiu Co-authored-by: Vladimir Istyufeev Co-authored-by: Ross Bulat Co-authored-by: Gonçalo Pestana Co-authored-by: Liam Aharon Co-authored-by: Svyatoslav Nikolsky Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: Oliver Tale-Yazdi Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Co-authored-by: ordian Co-authored-by: Sebastian Kunert Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com> Co-authored-by: Dmitry Markin Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Co-authored-by: Julian Eager Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Co-authored-by: Davide Galassi Co-authored-by: Dónal Murray Co-authored-by: yjh Co-authored-by: Tom Mi Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Will | Paradox | ParaNodes.io <79228812+paradox-tt@users.noreply.github.com> Co-authored-by: Bastian Köcher Co-authored-by: Joshy Orndorff Co-authored-by: Joshy Orndorff Co-authored-by: PG Herveou Co-authored-by: Alexander Theißen Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Juan Girini Co-authored-by: bader y Co-authored-by: James Wilson Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: asynchronous rob Co-authored-by: Parth Co-authored-by: Andrew Jones Co-authored-by: Jonathan Udd Co-authored-by: Serban Iorga Co-authored-by: Egor_P Co-authored-by: Branislav Kontur Co-authored-by: Evgeny Snitko Co-authored-by: Just van Stam Co-authored-by: Francisco Aguirre Co-authored-by: gupnik Co-authored-by: dzmitry-lahoda Co-authored-by: zhiqiangxu <652732310@qq.com> Co-authored-by: Nazar Mokrynskyi Co-authored-by: Anwesh Co-authored-by: cheme Co-authored-by: Sam Johnson Co-authored-by: kianenigma Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> Co-authored-by: Muharem Co-authored-by: joepetrowski Co-authored-by: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Co-authored-by: Gabriel Facco de Arruda Co-authored-by: Squirrel Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Co-authored-by: georgepisaltu Co-authored-by: command-bot <> --- Cargo.lock | 35 +- bridges/bin/runtime-common/Cargo.toml | 1 + bridges/bin/runtime-common/src/lib.rs | 72 +- bridges/bin/runtime-common/src/mock.rs | 2 +- .../runtime-common/src/priority_calculator.rs | 11 +- .../src/refund_relayer_extension.rs | 154 +- .../chain-bridge-hub-cumulus/src/lib.rs | 4 +- .../chain-bridge-hub-rococo/src/lib.rs | 2 +- bridges/primitives/chain-kusama/src/lib.rs | 4 +- .../chain-polkadot-bulletin/src/lib.rs | 51 +- bridges/primitives/chain-polkadot/src/lib.rs | 4 +- bridges/primitives/chain-rococo/src/lib.rs | 4 +- bridges/primitives/chain-westend/src/lib.rs | 4 +- bridges/primitives/polkadot-core/src/lib.rs | 37 +- bridges/primitives/runtime/src/extensions.rs | 135 +- .../snowbridge/runtime/test-common/Cargo.toml | 1 + cumulus/parachain-template/runtime/Cargo.toml | 2 + cumulus/parachain-template/runtime/src/lib.rs | 10 +- .../assets/asset-hub-rococo/Cargo.toml | 2 + .../assets/asset-hub-rococo/src/lib.rs | 77 +- .../src/weights/frame_system_extensions.rs | 121 + .../asset-hub-rococo/src/weights/mod.rs | 3 + .../pallet_asset_conversion_tx_payment.rs | 92 + .../src/weights/pallet_transaction_payment.rs | 67 + .../assets/asset-hub-westend/Cargo.toml | 2 + .../assets/asset-hub-westend/src/lib.rs | 77 +- .../src/weights/frame_system_extensions.rs | 121 + .../asset-hub-westend/src/weights/mod.rs | 3 + .../pallet_asset_conversion_tx_payment.rs | 92 + .../src/weights/pallet_transaction_payment.rs | 67 + .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 1 + .../src/bridge_to_bulletin_config.rs | 4 +- .../src/bridge_to_westend_config.rs | 4 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 27 +- .../src/weights/frame_system_extensions.rs | 121 + .../bridge-hub-rococo/src/weights/mod.rs | 2 + .../src/weights/pallet_transaction_payment.rs | 67 + .../bridge-hub-rococo/tests/snowbridge.rs | 8 +- .../bridge-hub-rococo/tests/tests.rs | 11 +- .../bridge-hubs/bridge-hub-westend/Cargo.toml | 1 + .../src/bridge_to_rococo_config.rs | 4 +- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 25 +- .../src/weights/frame_system_extensions.rs | 121 + .../bridge-hub-westend/src/weights/mod.rs | 2 + .../src/weights/pallet_transaction_payment.rs | 67 + .../bridge-hub-westend/tests/tests.rs | 11 +- .../collectives-westend/Cargo.toml | 1 + .../collectives-westend/src/lib.rs | 12 +- .../src/weights/frame_system_extensions.rs | 121 + .../collectives-westend/src/weights/mod.rs | 2 + .../src/weights/pallet_transaction_payment.rs | 67 + .../contracts/contracts-rococo/Cargo.toml | 1 + .../contracts/contracts-rococo/src/lib.rs | 10 +- .../coretime/coretime-rococo/Cargo.toml | 1 + .../coretime/coretime-rococo/src/lib.rs | 9 +- .../src/weights/frame_system_extensions.rs | 121 + .../coretime-rococo/src/weights/mod.rs | 2 + .../src/weights/pallet_transaction_payment.rs | 67 + .../coretime/coretime-westend/Cargo.toml | 1 + .../coretime/coretime-westend/src/lib.rs | 9 +- .../src/weights/frame_system_extensions.rs | 121 + .../coretime-westend/src/weights/mod.rs | 2 + .../src/weights/pallet_transaction_payment.rs | 67 + .../glutton/glutton-westend/src/lib.rs | 9 +- .../src/weights/frame_system_extensions.rs | 119 + .../runtimes/people/people-rococo/Cargo.toml | 1 + .../runtimes/people/people-rococo/src/lib.rs | 9 +- .../src/weights/frame_system_extensions.rs | 121 + .../people/people-rococo/src/weights/mod.rs | 2 + .../src/weights/pallet_transaction_payment.rs | 67 + .../runtimes/people/people-westend/Cargo.toml | 1 + .../runtimes/people/people-westend/src/lib.rs | 8 +- .../src/weights/frame_system_extensions.rs | 121 + .../people/people-westend/src/weights/mod.rs | 2 + .../src/weights/pallet_transaction_payment.rs | 67 + .../runtimes/starters/seedling/src/lib.rs | 6 +- .../runtimes/starters/shell/src/lib.rs | 64 +- .../runtimes/testing/penpal/Cargo.toml | 1 + .../runtimes/testing/penpal/src/lib.rs | 26 +- .../testing/rococo-parachain/Cargo.toml | 1 + .../testing/rococo-parachain/src/lib.rs | 7 +- cumulus/polkadot-parachain/Cargo.toml | 1 + .../storage-weight-reclaim/Cargo.toml | 13 +- .../src/benchmarking.rs | 70 + .../storage-weight-reclaim/src/lib.rs | 522 +--- .../storage-weight-reclaim/src/tests.rs | 484 ++++ cumulus/test/client/Cargo.toml | 2 + cumulus/test/client/src/lib.rs | 13 +- cumulus/test/runtime/src/lib.rs | 9 +- cumulus/test/service/Cargo.toml | 2 + cumulus/test/service/src/bench_utils.rs | 4 +- cumulus/test/service/src/lib.rs | 9 +- .../src/reference_docs/extrinsic_encoding.rs | 101 +- .../src/reference_docs/frame_runtime_types.rs | 2 +- docs/sdk/src/reference_docs/mod.rs | 4 +- .../src/reference_docs/signed_extensions.rs | 79 - .../reference_docs/transaction_extensions.rs | 57 + polkadot/node/service/Cargo.toml | 1 + polkadot/node/service/src/benchmarking.rs | 18 +- polkadot/node/test/service/Cargo.toml | 1 + polkadot/node/test/service/src/lib.rs | 11 +- polkadot/runtime/common/Cargo.toml | 1 + polkadot/runtime/common/src/claims.rs | 150 +- polkadot/runtime/rococo/Cargo.toml | 1 + .../constants/src/weights/block_weights.rs | 29 +- .../src/weights/extrinsic_weights.rs | 29 +- polkadot/runtime/rococo/src/lib.rs | 45 +- .../weights/frame_benchmarking_baseline.rs | 43 +- .../rococo/src/weights/frame_system.rs | 103 +- .../src/weights/frame_system_extensions.rs | 123 + polkadot/runtime/rococo/src/weights/mod.rs | 2 + .../rococo/src/weights/pallet_asset_rate.rs | 63 +- .../src/weights/pallet_balances_balances.rs | 58 +- ...allet_balances_nis_counterpart_balances.rs | 58 +- .../rococo/src/weights/pallet_bounties.rs | 218 +- .../src/weights/pallet_child_bounties.rs | 181 +- .../src/weights/pallet_conviction_voting.rs | 196 +- .../rococo/src/weights/pallet_identity.rs | 409 +-- .../rococo/src/weights/pallet_indices.rs | 73 +- .../src/weights/pallet_message_queue.rs | 168 +- .../rococo/src/weights/pallet_multisig.rs | 123 +- .../runtime/rococo/src/weights/pallet_nis.rs | 243 +- .../rococo/src/weights/pallet_preimage.rs | 252 +- .../rococo/src/weights/pallet_proxy.rs | 195 +- .../src/weights/pallet_ranked_collective.rs | 66 +- .../rococo/src/weights/pallet_recovery.rs | 186 ++ .../pallet_referenda_fellowship_referenda.rs | 235 +- .../src/weights/pallet_referenda_referenda.rs | 283 +-- .../rococo/src/weights/pallet_scheduler.rs | 146 +- .../runtime/rococo/src/weights/pallet_sudo.rs | 45 +- .../rococo/src/weights/pallet_timestamp.rs | 35 +- .../src/weights/pallet_transaction_payment.rs | 68 + .../rococo/src/weights/pallet_treasury.rs | 233 +- .../rococo/src/weights/pallet_utility.rs | 47 +- .../rococo/src/weights/pallet_vesting.rs | 254 +- .../rococo/src/weights/pallet_whitelist.rs | 68 +- .../runtime/rococo/src/weights/pallet_xcm.rs | 90 +- .../weights/pallet_xcm_benchmarks_fungible.rs | 191 ++ .../weights/pallet_xcm_benchmarks_generic.rs | 347 +++ .../weights/runtime_common_assigned_slots.rs | 70 +- .../src/weights/runtime_common_auctions.rs | 137 +- .../src/weights/runtime_common_claims.rs | 180 +- .../src/weights/runtime_common_coretime.rs | 86 + .../src/weights/runtime_common_crowdloan.rs | 239 +- .../runtime_common_identity_migrator.rs | 83 +- .../weights/runtime_common_paras_registrar.rs | 281 ++- .../src/weights/runtime_common_slots.rs | 127 +- .../runtime_parachains_assigner_on_demand.rs | 50 +- .../runtime_parachains_configuration.rs | 48 +- .../weights/runtime_parachains_disputes.rs | 23 +- .../src/weights/runtime_parachains_hrmp.rs | 389 ++- .../weights/runtime_parachains_inclusion.rs | 45 +- .../weights/runtime_parachains_initializer.rs | 27 +- .../src/weights/runtime_parachains_paras.rs | 368 +-- .../runtime_parachains_paras_inherent.rs | 429 +++- polkadot/runtime/test-runtime/Cargo.toml | 1 + polkadot/runtime/test-runtime/src/lib.rs | 40 +- polkadot/runtime/westend/Cargo.toml | 1 + polkadot/runtime/westend/src/lib.rs | 25 +- .../src/weights/frame_system_extensions.rs | 116 + polkadot/runtime/westend/src/weights/mod.rs | 2 + .../westend/src/weights/pallet_sudo.rs | 11 + .../src/weights/pallet_transaction_payment.rs | 65 + polkadot/xcm/xcm-builder/Cargo.toml | 1 + .../xcm/xcm-builder/src/tests/pay/mock.rs | 12 +- .../xcm/xcm-simulator/fuzzer/src/parachain.rs | 4 +- .../xcm-simulator/fuzzer/src/relay_chain.rs | 4 +- prdoc/pr_2280.prdoc | 144 ++ substrate/.maintain/frame-weight-template.hbs | 2 +- substrate/bin/minimal/runtime/src/lib.rs | 4 +- substrate/bin/node-template/node/Cargo.toml | 1 + .../node-template/node/src/benchmarking.rs | 9 +- .../bin/node-template/runtime/Cargo.toml | 1 + .../bin/node-template/runtime/src/lib.rs | 12 +- substrate/bin/node/cli/Cargo.toml | 2 + .../bin/node/cli/benches/block_production.rs | 2 +- substrate/bin/node/cli/benches/executor.rs | 6 +- substrate/bin/node/cli/src/service.rs | 77 +- substrate/bin/node/cli/tests/basic.rs | 26 +- substrate/bin/node/cli/tests/fees.rs | 24 +- .../bin/node/cli/tests/submit_transaction.rs | 10 +- substrate/bin/node/runtime/Cargo.toml | 2 + substrate/bin/node/runtime/src/lib.rs | 165 +- substrate/bin/node/testing/src/bench.rs | 26 +- substrate/bin/node/testing/src/keyring.rs | 44 +- .../client/api/src/notifications/tests.rs | 7 +- substrate/client/db/benches/state_access.rs | 5 +- substrate/client/db/src/lib.rs | 262 +- substrate/client/db/src/utils.rs | 11 +- .../network-gossip/src/state_machine.rs | 5 +- substrate/client/network/sync/src/blocks.rs | 7 +- substrate/client/transaction-pool/src/lib.rs | 9 +- substrate/frame/alliance/src/weights.rs | 1033 ++++---- .../frame/asset-conversion/src/weights.rs | 126 +- substrate/frame/asset-rate/src/weights.rs | 73 +- substrate/frame/assets/src/weights.rs | 841 +++---- substrate/frame/babe/src/mock.rs | 5 +- substrate/frame/bags-list/src/weights.rs | 165 +- substrate/frame/balances/Cargo.toml | 1 + .../balances/src/tests/currency_tests.rs | 17 +- substrate/frame/balances/src/tests/mod.rs | 4 +- substrate/frame/balances/src/weights.rs | 98 +- substrate/frame/beefy/src/mock.rs | 6 +- substrate/frame/benchmarking/src/weights.rs | 81 +- substrate/frame/bounties/src/weights.rs | 405 ++- substrate/frame/broker/src/weights.rs | 357 +-- substrate/frame/child-bounties/src/weights.rs | 381 ++- substrate/frame/collective/src/tests.rs | 2 +- substrate/frame/collective/src/weights.rs | 677 ++--- substrate/frame/contracts/src/weights.rs | 2222 +++++++++-------- .../frame/conviction-voting/src/weights.rs | 405 +-- .../frame/core-fellowship/src/weights.rs | 429 ++-- substrate/frame/democracy/src/weights.rs | 1093 ++++---- .../election-provider-multi-phase/src/mock.rs | 2 +- .../src/unsigned.rs | 4 +- .../src/weights.rs | 517 ++-- .../test-staking-e2e/src/mock.rs | 4 +- substrate/frame/elections-phragmen/src/lib.rs | 2 +- .../frame/elections-phragmen/src/weights.rs | 655 ++--- substrate/frame/examples/basic/src/lib.rs | 76 +- substrate/frame/examples/basic/src/tests.rs | 9 +- .../examples/offchain-worker/src/tests.rs | 22 +- substrate/frame/examples/tasks/src/weights.rs | 78 +- substrate/frame/executive/src/tests.rs | 225 +- substrate/frame/fast-unstake/src/weights.rs | 473 ++-- substrate/frame/glutton/src/weights.rs | 249 +- substrate/frame/grandpa/src/mock.rs | 9 +- substrate/frame/identity/src/weights.rs | 825 +++--- substrate/frame/im-online/src/mock.rs | 4 +- substrate/frame/im-online/src/tests.rs | 4 +- substrate/frame/im-online/src/weights.rs | 85 +- substrate/frame/indices/src/weights.rs | 121 +- substrate/frame/lottery/src/weights.rs | 301 +-- substrate/frame/membership/src/weights.rs | 385 ++- substrate/frame/message-queue/src/weights.rs | 247 +- substrate/frame/migrations/src/weights.rs | 183 +- substrate/frame/multisig/src/weights.rs | 243 +- .../nft-fractionalization/src/weights.rs | 209 +- substrate/frame/nfts/src/weights.rs | 1692 ++++++------- substrate/frame/nis/src/weights.rs | 429 ++-- .../frame/nomination-pools/src/weights.rs | 258 +- .../frame/offences/benchmarking/src/mock.rs | 2 +- substrate/frame/parameters/src/weights.rs | 38 +- substrate/frame/preimage/src/weights.rs | 332 +-- substrate/frame/proxy/src/weights.rs | 377 +-- .../frame/ranked-collective/src/weights.rs | 353 +-- substrate/frame/recovery/src/weights.rs | 305 +-- substrate/frame/referenda/src/weights.rs | 1037 ++++---- substrate/frame/remark/src/weights.rs | 37 +- substrate/frame/safe-mode/src/weights.rs | 142 +- substrate/frame/salary/src/weights.rs | 217 +- substrate/frame/sassafras/src/mock.rs | 5 +- substrate/frame/scheduler/src/weights.rs | 266 +- substrate/frame/session/src/weights.rs | 117 +- substrate/frame/society/src/weights.rs | 974 ++++++-- substrate/frame/src/lib.rs | 6 +- substrate/frame/staking/src/weights.rs | 422 ++-- .../frame/state-trie-migration/src/lib.rs | 2 +- .../frame/state-trie-migration/src/weights.rs | 118 +- substrate/frame/sudo/src/benchmarking.rs | 29 +- substrate/frame/sudo/src/extension.rs | 78 +- substrate/frame/sudo/src/lib.rs | 4 +- substrate/frame/sudo/src/weights.rs | 71 +- substrate/frame/support/Cargo.toml | 2 +- .../src/construct_runtime/expand/inherent.rs | 18 +- .../src/construct_runtime/expand/metadata.rs | 6 +- .../src/construct_runtime/expand/origin.rs | 14 + substrate/frame/support/src/dispatch.rs | 29 +- substrate/frame/support/src/lib.rs | 8 +- .../frame/support/src/traits/dispatch.rs | 21 +- substrate/frame/support/src/traits/misc.rs | 13 +- .../support/src/transaction_extensions.rs | 89 + .../support/src/weights/block_weights.rs | 31 +- .../support/src/weights/extrinsic_weights.rs | 31 +- .../support/test/tests/construct_runtime.rs | 2 +- .../deprecated_where_block.stderr | 4 +- substrate/frame/support/test/tests/pallet.rs | 143 +- .../support/test/tests/pallet_instance.rs | 2 +- .../system/benchmarking/src/extensions.rs | 213 ++ .../frame/system/benchmarking/src/lib.rs | 1 + .../frame/system/benchmarking/src/mock.rs | 1 + .../system/src/extensions/check_genesis.rs | 33 +- .../system/src/extensions/check_mortality.rs | 83 +- .../src/extensions/check_non_zero_sender.rs | 95 +- .../system/src/extensions/check_nonce.rs | 184 +- .../src/extensions/check_spec_version.rs | 33 +- .../system/src/extensions/check_tx_version.rs | 32 +- .../system/src/extensions/check_weight.rs | 228 +- substrate/frame/system/src/extensions/mod.rs | 3 + .../frame/system/src/extensions/weights.rs | 196 ++ substrate/frame/system/src/lib.rs | 10 +- substrate/frame/system/src/offchain.rs | 22 +- substrate/frame/system/src/weights.rs | 249 +- substrate/frame/timestamp/src/weights.rs | 65 +- substrate/frame/tips/src/weights.rs | 241 +- .../frame/transaction-payment/Cargo.toml | 9 + .../asset-conversion-tx-payment/Cargo.toml | 12 + .../asset-conversion-tx-payment/README.md | 2 +- .../src/benchmarking.rs | 125 + .../asset-conversion-tx-payment/src/lib.rs | 233 +- .../asset-conversion-tx-payment/src/mock.rs | 70 +- .../asset-conversion-tx-payment/src/tests.rs | 150 +- .../src/weights.rs | 150 ++ .../asset-tx-payment/Cargo.toml | 1 + .../asset-tx-payment/README.md | 2 +- .../asset-tx-payment/src/benchmarking.rs | 123 + .../asset-tx-payment/src/lib.rs | 199 +- .../asset-tx-payment/src/mock.rs | 54 +- .../asset-tx-payment/src/tests.rs | 184 +- .../asset-tx-payment/src/weights.rs | 146 ++ .../skip-feeless-payment/src/lib.rs | 111 +- .../skip-feeless-payment/src/mock.rs | 30 +- .../skip-feeless-payment/src/tests.rs | 5 +- .../transaction-payment/src/benchmarking.rs | 81 + .../frame/transaction-payment/src/lib.rs | 146 +- .../frame/transaction-payment/src/mock.rs | 10 + .../frame/transaction-payment/src/payment.rs | 56 +- .../frame/transaction-payment/src/tests.rs | 444 ++-- .../frame/transaction-payment/src/types.rs | 2 +- .../frame/transaction-payment/src/weights.rs | 92 + .../frame/transaction-storage/src/weights.rs | 185 +- substrate/frame/treasury/src/weights.rs | 348 +-- substrate/frame/tx-pause/src/weights.rs | 38 +- substrate/frame/uniques/src/weights.rs | 368 +-- substrate/frame/utility/src/weights.rs | 161 +- substrate/frame/vesting/src/weights.rs | 234 +- substrate/frame/whitelist/src/weights.rs | 193 +- substrate/primitives/inherents/src/lib.rs | 4 +- substrate/primitives/metadata-ir/src/lib.rs | 2 +- substrate/primitives/metadata-ir/src/types.rs | 19 +- substrate/primitives/metadata-ir/src/v14.rs | 10 +- substrate/primitives/metadata-ir/src/v15.rs | 8 +- substrate/primitives/runtime/Cargo.toml | 2 + .../runtime/src/generic/checked_extrinsic.rs | 112 +- .../primitives/runtime/src/generic/mod.rs | 4 +- .../src/generic/unchecked_extrinsic.rs | 730 ++++-- substrate/primitives/runtime/src/lib.rs | 19 +- substrate/primitives/runtime/src/testing.rs | 195 +- .../runtime/src/{traits.rs => traits/mod.rs} | 244 +- .../as_transaction_extension.rs | 133 + .../dispatch_transaction.rs | 141 ++ .../src/traits/transaction_extension/mod.rs | 526 ++++ .../runtime/src/transaction_validity.rs | 6 +- substrate/scripts/run_all_benchmarks.sh | 13 + substrate/test-utils/runtime/src/extrinsic.rs | 17 +- substrate/test-utils/runtime/src/lib.rs | 93 +- .../benchmarking-cli/src/pallet/template.hbs | 4 + .../frame/remote-externalities/src/lib.rs | 5 +- substrate/utils/frame/rpc/client/src/lib.rs | 8 +- 349 files changed, 25345 insertions(+), 16846 deletions(-) create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_conversion_tx_payment.rs create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_conversion_tx_payment.rs create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs create mode 100644 cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_transaction_payment.rs create mode 100644 cumulus/primitives/storage-weight-reclaim/src/benchmarking.rs create mode 100644 cumulus/primitives/storage-weight-reclaim/src/tests.rs delete mode 100644 docs/sdk/src/reference_docs/signed_extensions.rs create mode 100644 docs/sdk/src/reference_docs/transaction_extensions.rs create mode 100644 polkadot/runtime/rococo/src/weights/frame_system_extensions.rs create mode 100644 polkadot/runtime/rococo/src/weights/pallet_recovery.rs create mode 100644 polkadot/runtime/rococo/src/weights/pallet_transaction_payment.rs create mode 100644 polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs create mode 100644 polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs create mode 100644 polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs create mode 100644 polkadot/runtime/westend/src/weights/frame_system_extensions.rs create mode 100644 polkadot/runtime/westend/src/weights/pallet_transaction_payment.rs create mode 100644 prdoc/pr_2280.prdoc create mode 100644 substrate/frame/support/src/transaction_extensions.rs create mode 100644 substrate/frame/system/benchmarking/src/extensions.rs create mode 100644 substrate/frame/system/src/extensions/weights.rs create mode 100644 substrate/frame/transaction-payment/asset-conversion-tx-payment/src/benchmarking.rs create mode 100644 substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs create mode 100644 substrate/frame/transaction-payment/asset-tx-payment/src/benchmarking.rs create mode 100644 substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs create mode 100644 substrate/frame/transaction-payment/src/benchmarking.rs create mode 100644 substrate/frame/transaction-payment/src/weights.rs rename substrate/primitives/runtime/src/{traits.rs => traits/mod.rs} (94%) create mode 100644 substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs create mode 100644 substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs create mode 100644 substrate/primitives/runtime/src/traits/transaction_extension/mod.rs diff --git a/Cargo.lock b/Cargo.lock index ad218001b40..81881984378 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4070,11 +4070,13 @@ dependencies = [ "cumulus-primitives-proof-size-hostfunction", "cumulus-test-runtime", "docify 0.2.7", + "frame-benchmarking", "frame-support", "frame-system", "log", "parity-scale-codec", "scale-info", + "sp-core", "sp-io", "sp-runtime", "sp-std 14.0.0", @@ -5938,7 +5940,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f9df8a11882c4e3335eb2d18a0137c505d9ca927470b0cac9c6f0ae07d28f7" dependencies = [ - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -6827,7 +6829,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.2", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -7834,9 +7836,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lioness" @@ -9177,6 +9179,7 @@ dependencies = [ name = "pallet-asset-conversion-tx-payment" version = "10.0.0" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "pallet-asset-conversion", @@ -11119,6 +11122,7 @@ dependencies = [ name = "pallet-transaction-payment" version = "28.0.0" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "pallet-balances", @@ -14333,7 +14337,7 @@ dependencies = [ "hex", "lazy_static", "procfs-core", - "rustix 0.38.21", + "rustix 0.38.25", ] [[package]] @@ -15458,14 +15462,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.10", + "linux-raw-sys 0.4.11", "windows-sys 0.48.0", ] @@ -18721,7 +18725,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.4.1" -source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf590a34fca09b72dc5f" +source = "git+https://github.com/paritytech/polkadot-sdk#838a534da874cf6071fba1df07643c6c5b033ae0" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -19026,6 +19030,7 @@ dependencies = [ "sp-tracing 16.0.0", "sp-weights", "substrate-test-runtime-client", + "tuplex", "zstd 0.12.4", ] @@ -19074,7 +19079,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf590a34fca09b72dc5f" +source = "git+https://github.com/paritytech/polkadot-sdk#838a534da874cf6071fba1df07643c6c5b033ae0" dependencies = [ "Inflector", "proc-macro-crate 1.3.1", @@ -20293,7 +20298,7 @@ dependencies = [ "cfg-if", "fastrand 2.0.0", "redox_syscall 0.4.1", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -20312,7 +20317,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -21158,6 +21163,12 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tuplex" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "676ac81d5454c4dcf37955d34fa8626ede3490f744b86ca14a7b90168d2a08aa" + [[package]] name = "twox-hash" version = "1.6.3" diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml index fac88b20ca5..ee54f15f38b 100644 --- a/bridges/bin/runtime-common/Cargo.toml +++ b/bridges/bin/runtime-common/Cargo.toml @@ -93,6 +93,7 @@ runtime-benchmarks = [ "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bridges/bin/runtime-common/src/lib.rs b/bridges/bin/runtime-common/src/lib.rs index 2722f6f1c6d..035077408c4 100644 --- a/bridges/bin/runtime-common/src/lib.rs +++ b/bridges/bin/runtime-common/src/lib.rs @@ -105,43 +105,48 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { ($call:ty, $account_id:ty, $($filter_call:ty),*) => { #[derive(Clone, codec::Decode, Default, codec::Encode, Eq, PartialEq, sp_runtime::RuntimeDebug, scale_info::TypeInfo)] pub struct BridgeRejectObsoleteHeadersAndMessages; - impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages { + impl sp_runtime::traits::TransactionExtensionBase for BridgeRejectObsoleteHeadersAndMessages { const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages"; - type AccountId = $account_id; - type Call = $call; - type AdditionalSigned = (); + type Implicit = (); + } + impl sp_runtime::traits::TransactionExtension<$call, Context> for BridgeRejectObsoleteHeadersAndMessages { type Pre = (); - - fn additional_signed(&self) -> sp_std::result::Result< - (), - sp_runtime::transaction_validity::TransactionValidityError, - > { - Ok(()) - } + type Val = (); fn validate( &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, + origin: <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, + call: &$call, + _info: &sp_runtime::traits::DispatchInfoOf<$call>, _len: usize, - ) -> sp_runtime::transaction_validity::TransactionValidity { - let valid = sp_runtime::transaction_validity::ValidTransaction::default(); + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl codec::Encode, + ) -> Result< + ( + sp_runtime::transaction_validity::ValidTransaction, + Self::Val, + <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, + ), sp_runtime::transaction_validity::TransactionValidityError + > { + let tx_validity = sp_runtime::transaction_validity::ValidTransaction::default(); $( - let valid = valid - .combine_with(<$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?); + let call_filter_validity = <$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?; + let tx_validity = tx_validity.combine_with(call_filter_validity); )* - Ok(valid) + Ok((tx_validity, (), origin)) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &sp_runtime::traits::DispatchInfoOf, - len: usize, + _val: Self::Val, + _origin: &<$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, + _call: &$call, + _info: &sp_runtime::traits::DispatchInfoOf<$call>, + _len: usize, + _context: &Context, ) -> Result { - self.validate(who, call, info, len).map(drop) + Ok(()) } } }; @@ -150,12 +155,14 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { #[cfg(test)] mod tests { use crate::BridgeRuntimeFilterCall; - use frame_support::{assert_err, assert_ok}; + use codec::Encode; + use frame_support::assert_err; use sp_runtime::{ - traits::SignedExtension, + traits::DispatchTransaction, transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, }; + #[derive(Encode)] pub struct MockCall { data: u32, } @@ -206,17 +213,20 @@ mod tests { ); assert_err!( - BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 1 }, &(), 0), + BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 1 }, &(), 0), InvalidTransaction::Custom(1) ); assert_err!( - BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 2 }, &(), 0), + BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 2 }, &(), 0), InvalidTransaction::Custom(2) ); - assert_ok!( - BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 3 }, &(), 0), + assert_eq!( + BridgeRejectObsoleteHeadersAndMessages + .validate_only((), &MockCall { data: 3 }, &(), 0) + .unwrap() + .0, ValidTransaction { priority: 3, ..Default::default() } ) } diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs index 8877a4fd95c..f147f1404f0 100644 --- a/bridges/bin/runtime-common/src/mock.rs +++ b/bridges/bin/runtime-common/src/mock.rs @@ -164,6 +164,7 @@ impl pallet_balances::Config for TestRuntime { type AccountStore = System; } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for TestRuntime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; @@ -176,7 +177,6 @@ impl pallet_transaction_payment::Config for TestRuntime { MinimumMultiplier, MaximumMultiplier, >; - type RuntimeEvent = RuntimeEvent; } impl pallet_bridge_grandpa::Config for TestRuntime { diff --git a/bridges/bin/runtime-common/src/priority_calculator.rs b/bridges/bin/runtime-common/src/priority_calculator.rs index a597fb9e2f4..0c53018330e 100644 --- a/bridges/bin/runtime-common/src/priority_calculator.rs +++ b/bridges/bin/runtime-common/src/priority_calculator.rs @@ -169,12 +169,15 @@ mod integrity_tests { // nodes to the proof (x0.5 because we expect some nodes to be reused) let estimated_message_size = 512; // let's say all our messages have the same dispatch weight - let estimated_message_dispatch_weight = - Runtime::WeightInfo::message_dispatch_weight(estimated_message_size); + let estimated_message_dispatch_weight = >::WeightInfo::message_dispatch_weight( + estimated_message_size + ); // messages proof argument size is (for every message) messages size + some additional // trie nodes. Some of them are reused by different messages, so let's take 2/3 of default // "overhead" constant - let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size() + let messages_proof_size = >::WeightInfo::expected_extra_storage_proof_size() .saturating_mul(2) .saturating_div(3) .saturating_add(estimated_message_size) @@ -182,7 +185,7 @@ mod integrity_tests { // finally we are able to estimate transaction size and weight let transaction_size = base_tx_size.saturating_add(messages_proof_size); - let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight( + let transaction_weight = >::WeightInfo::receive_messages_proof_weight( &PreComputedSize(transaction_size as _), messages as _, estimated_message_dispatch_weight.saturating_mul(messages), diff --git a/bridges/bin/runtime-common/src/refund_relayer_extension.rs b/bridges/bin/runtime-common/src/refund_relayer_extension.rs index bfcb82ad166..b912f8445ac 100644 --- a/bridges/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bridges/bin/runtime-common/src/refund_relayer_extension.rs @@ -48,9 +48,12 @@ use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTra use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, SignedExtension, Zero}, + traits::{ + AsSystemOriginSigner, DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, + TransactionExtension, TransactionExtensionBase, ValidateResult, Zero, + }, transaction_validity::{ - TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransactionBuilder, + InvalidTransaction, TransactionPriority, TransactionValidityError, ValidTransactionBuilder, }, DispatchResult, FixedPointOperand, RuntimeDebug, }; @@ -239,8 +242,8 @@ pub enum RelayerAccountAction { Slash(AccountId, RewardsAccountParams), } -/// Everything common among our refund signed extensions. -pub trait RefundSignedExtension: +/// Everything common among our refund transaction extensions. +pub trait RefundTransactionExtension: 'static + Clone + Codec + sp_std::fmt::Debug + Default + Eq + PartialEq + Send + Sync + TypeInfo where >::BridgedChain: @@ -456,8 +459,8 @@ where } } -/// Adapter that allow implementing `sp_runtime::traits::SignedExtension` for any -/// `RefundSignedExtension`. +/// Adapter that allow implementing `sp_runtime::traits::TransactionExtension` for any +/// `RefundTransactionExtension`. #[derive( DefaultNoBound, CloneNoBound, @@ -468,12 +471,13 @@ where RuntimeDebugNoBound, TypeInfo, )] -pub struct RefundSignedExtensionAdapter(T) +pub struct RefundTransactionExtensionAdapter(T) where >::BridgedChain: Chain; -impl SignedExtension for RefundSignedExtensionAdapter +impl TransactionExtensionBase + for RefundTransactionExtensionAdapter where >::BridgedChain: Chain, @@ -483,22 +487,35 @@ where + MessagesCallSubType::Instance>, { const IDENTIFIER: &'static str = T::Id::STR; - type AccountId = AccountIdOf; - type Call = CallOf; - type AdditionalSigned = (); - type Pre = Option>>; + type Implicit = (); +} - fn additional_signed(&self) -> Result<(), TransactionValidityError> { - Ok(()) - } +impl TransactionExtension, Context> + for RefundTransactionExtensionAdapter +where + >::BridgedChain: + Chain, + CallOf: Dispatchable + + IsSubType, T::Runtime>> + + GrandpaCallSubType + + MessagesCallSubType::Instance>, + as Dispatchable>::RuntimeOrigin: + AsSystemOriginSigner> + Clone, +{ + type Pre = Option>>; + type Val = Option; fn validate( &self, - who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, + origin: as Dispatchable>::RuntimeOrigin, + call: &CallOf, + _info: &DispatchInfoOf>, _len: usize, - ) -> TransactionValidity { + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult> { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; // this is the only relevant line of code for the `pre_dispatch` // // we're not calling `validate` from `pre_dispatch` directly because of performance @@ -511,12 +528,12 @@ where // we only boost priority of presumably correct message delivery transactions let bundled_messages = match T::bundled_messages_for_priority_boost(parsed_call.as_ref()) { Some(bundled_messages) => bundled_messages, - None => return Ok(Default::default()), + None => return Ok((Default::default(), parsed_call, origin)), }; // we only boost priority if relayer has staked required balance if !RelayersPallet::::is_registration_active(who) { - return Ok(Default::default()) + return Ok((Default::default(), parsed_call, origin)) } // compute priority boost @@ -535,20 +552,21 @@ where priority_boost, ); - valid_transaction.build() + let validity = valid_transaction.build()?; + Ok((validity, parsed_call, origin)) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, + val: Self::Val, + origin: & as Dispatchable>::RuntimeOrigin, + _call: &CallOf, + _info: &DispatchInfoOf>, _len: usize, + _context: &Context, ) -> Result { - // this is a relevant piece of `validate` that we need here (in `pre_dispatch`) - let parsed_call = T::parse_and_check_for_obsolete_call(call)?; - - Ok(parsed_call.map(|call_info| { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + Ok(val.map(|call_info| { log::trace!( target: "runtime::bridge", "{} via {:?} parsed bridge transaction in pre-dispatch: {:?}", @@ -561,13 +579,14 @@ where } fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Self::Pre, + info: &DispatchInfoOf>, + post_info: &PostDispatchInfoOf>, len: usize, result: &DispatchResult, + _context: &Context, ) -> Result<(), TransactionValidityError> { - let call_result = T::analyze_call_result(pre, info, post_info, len, result); + let call_result = T::analyze_call_result(Some(pre), info, post_info, len, result); match call_result { RelayerAccountAction::None => (), @@ -595,7 +614,7 @@ where } } -/// Signed extension that refunds a relayer for new messages coming from a parachain. +/// Transaction extension that refunds a relayer for new messages coming from a parachain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and @@ -636,7 +655,7 @@ pub struct RefundBridgedParachainMessages, ); -impl RefundSignedExtension +impl RefundTransactionExtension for RefundBridgedParachainMessages where Self: 'static + Send + Sync, @@ -730,13 +749,13 @@ where } } -/// Signed extension that refunds a relayer for new messages coming from a standalone (GRANDPA) +/// Transaction extension that refunds a relayer for new messages coming from a standalone (GRANDPA) /// chain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and -/// parachain head, or just parachain head. Corresponding headers must be used in messages -/// proof verification. +/// parachain head, or just parachain head. Corresponding headers must be used in messages proof +/// verification. /// /// Extension does not refund transaction tip due to security reasons. #[derive( @@ -771,7 +790,7 @@ pub struct RefundBridgedGrandpaMessages, ); -impl RefundSignedExtension +impl RefundTransactionExtension for RefundBridgedGrandpaMessages where Self: 'static + Send + Sync, @@ -869,8 +888,8 @@ mod tests { Call as ParachainsCall, Pallet as ParachainsPallet, RelayBlockHash, }; use sp_runtime::{ - traits::{ConstU64, Header as HeaderT}, - transaction_validity::{InvalidTransaction, ValidTransaction}, + traits::{ConstU64, DispatchTransaction, Header as HeaderT}, + transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, DispatchError, }; @@ -899,7 +918,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; - type TestGrandpaExtension = RefundSignedExtensionAdapter; + type TestGrandpaExtension = RefundTransactionExtensionAdapter; type TestExtensionProvider = RefundBridgedParachainMessages< TestRuntime, DefaultRefundableParachainId<(), TestParachain>, @@ -908,7 +927,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; - type TestExtension = RefundSignedExtensionAdapter; + type TestExtension = RefundTransactionExtensionAdapter; fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance { let test_stake: ThisChainBalance = TestStake::get(); @@ -1407,14 +1426,28 @@ mod tests { fn run_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestExtension = - RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); - extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension + .validate_only( + Some(relayer_account_at_this_chain()).into(), + &call, + &DispatchInfo::default(), + 0, + ) + .map(|res| res.0) } fn run_grandpa_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestGrandpaExtension = - RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); - extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); + extension + .validate_only( + Some(relayer_account_at_this_chain()).into(), + &call, + &DispatchInfo::default(), + 0, + ) + .map(|res| res.0) } fn run_validate_ignore_priority(call: RuntimeCall) -> TransactionValidity { @@ -1428,16 +1461,30 @@ mod tests { call: RuntimeCall, ) -> Result>, TransactionValidityError> { let extension: TestExtension = - RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); - extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension + .validate_and_prepare( + Some(relayer_account_at_this_chain()).into(), + &call, + &DispatchInfo::default(), + 0, + ) + .map(|(pre, _)| pre) } fn run_grandpa_pre_dispatch( call: RuntimeCall, ) -> Result>, TransactionValidityError> { let extension: TestGrandpaExtension = - RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); - extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); + extension + .validate_and_prepare( + Some(relayer_account_at_this_chain()).into(), + &call, + &DispatchInfo::default(), + 0, + ) + .map(|(pre, _)| pre) } fn dispatch_info() -> DispatchInfo { @@ -1460,11 +1507,12 @@ mod tests { dispatch_result: DispatchResult, ) { let post_dispatch_result = TestExtension::post_dispatch( - Some(pre_dispatch_data), + pre_dispatch_data, &dispatch_info(), &post_dispatch_info(), 1024, &dispatch_result, + &(), ); assert_eq!(post_dispatch_result, Ok(())); } diff --git a/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs b/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs index c49aa4b8563..f186f6427ae 100644 --- a/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -26,7 +26,7 @@ pub use bp_polkadot_core::{ }; use bp_messages::*; -use bp_polkadot_core::SuffixedCommonSignedExtension; +use bp_polkadot_core::SuffixedCommonTransactionExtension; use bp_runtime::extensions::{ BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, }; @@ -164,7 +164,7 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// Signed extension that is used by all bridge hubs. -pub type SignedExtension = SuffixedCommonSignedExtension<( +pub type TransactionExtension = SuffixedCommonTransactionExtension<( BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, )>; diff --git a/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs b/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs index c4e697fbe95..992ef1bd7a1 100644 --- a/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -107,5 +107,5 @@ frame_support::parameter_types! { /// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation. /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_829_647; + pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_904_835; } diff --git a/bridges/primitives/chain-kusama/src/lib.rs b/bridges/primitives/chain-kusama/src/lib.rs index e3b4d0520f6..253a1010e83 100644 --- a/bridges/primitives/chain-kusama/src/lib.rs +++ b/bridges/primitives/chain-kusama/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Kusama { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The SignedExtension used by Kusama. -pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; +// The TransactionExtension used by Kusama. +pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; /// Name of the parachains pallet in the Kusama runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/bridges/primitives/chain-polkadot-bulletin/src/lib.rs b/bridges/primitives/chain-polkadot-bulletin/src/lib.rs index f2eebf93124..73dd122bd15 100644 --- a/bridges/primitives/chain-polkadot-bulletin/src/lib.rs +++ b/bridges/primitives/chain-polkadot-bulletin/src/lib.rs @@ -25,7 +25,7 @@ use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, extensions::{ CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion, - CheckWeight, GenericSignedExtension, GenericSignedExtensionSchema, + CheckWeight, GenericTransactionExtension, GenericTransactionExtensionSchema, }, Chain, ChainId, TransactionEra, }; @@ -37,7 +37,12 @@ use frame_support::{ }; use frame_system::limits; use scale_info::TypeInfo; -use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidityError, Perbill}; +use sp_runtime::{ + impl_tx_ext_default, + traits::{Dispatchable, TransactionExtensionBase}, + transaction_validity::TransactionValidityError, + Perbill, +}; // This chain reuses most of Polkadot primitives. pub use bp_polkadot_core::{ @@ -71,10 +76,10 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// This signed extension is used to ensure that the chain transactions are signed by proper -pub type ValidateSigned = GenericSignedExtensionSchema<(), ()>; +pub type ValidateSigned = GenericTransactionExtensionSchema<(), ()>; /// Signed extension schema, used by Polkadot Bulletin. -pub type SignedExtensionSchema = GenericSignedExtension<( +pub type TransactionExtensionSchema = GenericTransactionExtension<( ( CheckNonZeroSender, CheckSpecVersion, @@ -87,34 +92,30 @@ pub type SignedExtensionSchema = GenericSignedExtension<( ValidateSigned, )>; -/// Signed extension, used by Polkadot Bulletin. +/// Transaction extension, used by Polkadot Bulletin. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct SignedExtension(SignedExtensionSchema); +pub struct TransactionExtension(TransactionExtensionSchema); -impl sp_runtime::traits::SignedExtension for SignedExtension { +impl TransactionExtensionBase for TransactionExtension { const IDENTIFIER: &'static str = "Not needed."; - type AccountId = (); - type Call = (); - type AdditionalSigned = - ::AdditionalSigned; - type Pre = (); + type Implicit = ::Implicit; - fn additional_signed(&self) -> Result { - self.0.additional_signed() + fn implicit(&self) -> Result { + ::implicit(&self.0) } +} - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result { - Ok(()) - } +impl sp_runtime::traits::TransactionExtension for TransactionExtension +where + C: Dispatchable, +{ + type Pre = (); + type Val = (); + + impl_tx_ext_default!(C; Context; validate prepare); } -impl SignedExtension { +impl TransactionExtension { /// Create signed extension from its components. pub fn from_params( spec_version: u32, @@ -123,7 +124,7 @@ impl SignedExtension { genesis_hash: Hash, nonce: Nonce, ) -> Self { - Self(GenericSignedExtension::new( + Self(GenericTransactionExtension::new( ( ( (), // non-zero sender diff --git a/bridges/primitives/chain-polkadot/src/lib.rs b/bridges/primitives/chain-polkadot/src/lib.rs index fc5e10308a8..e5e2e7c3a04 100644 --- a/bridges/primitives/chain-polkadot/src/lib.rs +++ b/bridges/primitives/chain-polkadot/src/lib.rs @@ -61,8 +61,8 @@ impl ChainWithGrandpa for Polkadot { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -/// The SignedExtension used by Polkadot. -pub type SignedExtension = SuffixedCommonSignedExtension; +/// The TransactionExtension used by Polkadot. +pub type TransactionExtension = SuffixedCommonTransactionExtension; /// Name of the parachains pallet in the Polkadot runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/bridges/primitives/chain-rococo/src/lib.rs b/bridges/primitives/chain-rococo/src/lib.rs index f1b256f0f09..267c6b2b1f0 100644 --- a/bridges/primitives/chain-rococo/src/lib.rs +++ b/bridges/primitives/chain-rococo/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Rococo { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The SignedExtension used by Rococo. -pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; +// The TransactionExtension used by Rococo. +pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/bridges/primitives/chain-westend/src/lib.rs b/bridges/primitives/chain-westend/src/lib.rs index f03fd2160a7..afa02e8ee54 100644 --- a/bridges/primitives/chain-westend/src/lib.rs +++ b/bridges/primitives/chain-westend/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Westend { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The SignedExtension used by Westend. -pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; +// The TransactionExtension used by Westend. +pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/bridges/primitives/polkadot-core/src/lib.rs b/bridges/primitives/polkadot-core/src/lib.rs index df2836495bb..d59b99db4b5 100644 --- a/bridges/primitives/polkadot-core/src/lib.rs +++ b/bridges/primitives/polkadot-core/src/lib.rs @@ -24,8 +24,8 @@ use bp_runtime::{ self, extensions::{ ChargeTransactionPayment, CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, - CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension, - SignedExtensionSchema, + CheckSpecVersion, CheckTxVersion, CheckWeight, GenericTransactionExtension, + TransactionExtensionSchema, }, EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra, }; @@ -229,8 +229,12 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic, Signature, SignedExt>; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< + AccountAddress, + EncodedOrDecodedCall, + Signature, + TransactionExt, +>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; @@ -275,7 +279,7 @@ impl AccountInfoStorageMapKeyProvider { } /// Extra signed extension data that is used by most chains. -pub type CommonSignedExtra = ( +pub type CommonTransactionExtra = ( CheckNonZeroSender, CheckSpecVersion, CheckTxVersion, @@ -286,12 +290,12 @@ pub type CommonSignedExtra = ( ChargeTransactionPayment, ); -/// Extra signed extension data that starts with `CommonSignedExtra`. -pub type SuffixedCommonSignedExtension = - GenericSignedExtension<(CommonSignedExtra, Suffix)>; +/// Extra transaction extension data that starts with `CommonTransactionExtra`. +pub type SuffixedCommonTransactionExtension = + GenericTransactionExtension<(CommonTransactionExtra, Suffix)>; -/// Helper trait to define some extra methods on `SuffixedCommonSignedExtension`. -pub trait SuffixedCommonSignedExtensionExt { +/// Helper trait to define some extra methods on `SuffixedCommonTransactionExtension`. +pub trait SuffixedCommonTransactionExtensionExt { /// Create signed extension from its components. fn from_params( spec_version: u32, @@ -300,7 +304,7 @@ pub trait SuffixedCommonSignedExtensionExt { genesis_hash: Hash, nonce: Nonce, tip: Balance, - extra: (Suffix::Payload, Suffix::AdditionalSigned), + extra: (Suffix::Payload, Suffix::Implicit), ) -> Self; /// Return transaction nonce. @@ -310,9 +314,10 @@ pub trait SuffixedCommonSignedExtensionExt { fn tip(&self) -> Balance; } -impl SuffixedCommonSignedExtensionExt for SuffixedCommonSignedExtension +impl SuffixedCommonTransactionExtensionExt + for SuffixedCommonTransactionExtension where - Suffix: SignedExtensionSchema, + Suffix: TransactionExtensionSchema, { fn from_params( spec_version: u32, @@ -321,9 +326,9 @@ where genesis_hash: Hash, nonce: Nonce, tip: Balance, - extra: (Suffix::Payload, Suffix::AdditionalSigned), + extra: (Suffix::Payload, Suffix::Implicit), ) -> Self { - GenericSignedExtension::new( + GenericTransactionExtension::new( ( ( (), // non-zero sender @@ -365,7 +370,7 @@ where } /// Signed extension that is used by most chains. -pub type CommonSignedExtension = SuffixedCommonSignedExtension<()>; +pub type CommonTransactionExtension = SuffixedCommonTransactionExtension<()>; #[cfg(test)] mod tests { diff --git a/bridges/primitives/runtime/src/extensions.rs b/bridges/primitives/runtime/src/extensions.rs index d896bc92eff..a31e7b5bb47 100644 --- a/bridges/primitives/runtime/src/extensions.rs +++ b/bridges/primitives/runtime/src/extensions.rs @@ -20,135 +20,138 @@ use codec::{Compact, Decode, Encode}; use impl_trait_for_tuples::impl_for_tuples; use scale_info::{StaticTypeInfo, TypeInfo}; use sp_runtime::{ - traits::{DispatchInfoOf, SignedExtension}, + impl_tx_ext_default, + traits::{Dispatchable, TransactionExtension, TransactionExtensionBase}, transaction_validity::TransactionValidityError, }; use sp_std::{fmt::Debug, marker::PhantomData}; -/// Trait that describes some properties of a `SignedExtension` that are needed in order to send a -/// transaction to the chain. -pub trait SignedExtensionSchema: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo { +/// Trait that describes some properties of a `TransactionExtension` that are needed in order to +/// send a transaction to the chain. +pub trait TransactionExtensionSchema: + Encode + Decode + Debug + Eq + Clone + StaticTypeInfo +{ /// A type of the data encoded as part of the transaction. type Payload: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; /// Parameters which are part of the payload used to produce transaction signature, /// but don't end up in the transaction itself (i.e. inherent part of the runtime). - type AdditionalSigned: Encode + Debug + Eq + Clone + StaticTypeInfo; + type Implicit: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; } -impl SignedExtensionSchema for () { +impl TransactionExtensionSchema for () { type Payload = (); - type AdditionalSigned = (); + type Implicit = (); } -/// An implementation of `SignedExtensionSchema` using generic params. +/// An implementation of `TransactionExtensionSchema` using generic params. #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)] -pub struct GenericSignedExtensionSchema(PhantomData<(P, S)>); +pub struct GenericTransactionExtensionSchema(PhantomData<(P, S)>); -impl SignedExtensionSchema for GenericSignedExtensionSchema +impl TransactionExtensionSchema for GenericTransactionExtensionSchema where P: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, - S: Encode + Debug + Eq + Clone + StaticTypeInfo, + S: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, { type Payload = P; - type AdditionalSigned = S; + type Implicit = S; } -/// The `SignedExtensionSchema` for `frame_system::CheckNonZeroSender`. -pub type CheckNonZeroSender = GenericSignedExtensionSchema<(), ()>; +/// The `TransactionExtensionSchema` for `frame_system::CheckNonZeroSender`. +pub type CheckNonZeroSender = GenericTransactionExtensionSchema<(), ()>; -/// The `SignedExtensionSchema` for `frame_system::CheckSpecVersion`. -pub type CheckSpecVersion = GenericSignedExtensionSchema<(), u32>; +/// The `TransactionExtensionSchema` for `frame_system::CheckSpecVersion`. +pub type CheckSpecVersion = GenericTransactionExtensionSchema<(), u32>; -/// The `SignedExtensionSchema` for `frame_system::CheckTxVersion`. -pub type CheckTxVersion = GenericSignedExtensionSchema<(), u32>; +/// The `TransactionExtensionSchema` for `frame_system::CheckTxVersion`. +pub type CheckTxVersion = GenericTransactionExtensionSchema<(), u32>; -/// The `SignedExtensionSchema` for `frame_system::CheckGenesis`. -pub type CheckGenesis = GenericSignedExtensionSchema<(), Hash>; +/// The `TransactionExtensionSchema` for `frame_system::CheckGenesis`. +pub type CheckGenesis = GenericTransactionExtensionSchema<(), Hash>; -/// The `SignedExtensionSchema` for `frame_system::CheckEra`. -pub type CheckEra = GenericSignedExtensionSchema; +/// The `TransactionExtensionSchema` for `frame_system::CheckEra`. +pub type CheckEra = GenericTransactionExtensionSchema; -/// The `SignedExtensionSchema` for `frame_system::CheckNonce`. -pub type CheckNonce = GenericSignedExtensionSchema, ()>; +/// The `TransactionExtensionSchema` for `frame_system::CheckNonce`. +pub type CheckNonce = GenericTransactionExtensionSchema, ()>; -/// The `SignedExtensionSchema` for `frame_system::CheckWeight`. -pub type CheckWeight = GenericSignedExtensionSchema<(), ()>; +/// The `TransactionExtensionSchema` for `frame_system::CheckWeight`. +pub type CheckWeight = GenericTransactionExtensionSchema<(), ()>; -/// The `SignedExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. -pub type ChargeTransactionPayment = GenericSignedExtensionSchema, ()>; +/// The `TransactionExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. +pub type ChargeTransactionPayment = + GenericTransactionExtensionSchema, ()>; -/// The `SignedExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. -pub type PrevalidateAttests = GenericSignedExtensionSchema<(), ()>; +/// The `TransactionExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. +pub type PrevalidateAttests = GenericTransactionExtensionSchema<(), ()>; -/// The `SignedExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. -pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<(), ()>; +/// The `TransactionExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. +pub type BridgeRejectObsoleteHeadersAndMessages = GenericTransactionExtensionSchema<(), ()>; -/// The `SignedExtensionSchema` for `RefundBridgedParachainMessages`. +/// The `TransactionExtensionSchema` for `RefundBridgedParachainMessages`. /// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as /// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (), /// ())` is the same. So runtime can contains any kind of tuple: /// `(BridgeRefundBridgeHubRococoMessages)` /// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWestendMessages)` /// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)` -pub type RefundBridgedParachainMessagesSchema = GenericSignedExtensionSchema<(), ()>; +pub type RefundBridgedParachainMessagesSchema = GenericTransactionExtensionSchema<(), ()>; #[impl_for_tuples(1, 12)] -impl SignedExtensionSchema for Tuple { +impl TransactionExtensionSchema for Tuple { for_tuples!( type Payload = ( #( Tuple::Payload ),* ); ); - for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); + for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); ); } /// A simplified version of signed extensions meant for producing signed transactions /// and signed payloads in the client code. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct GenericSignedExtension { +pub struct GenericTransactionExtension { /// A payload that is included in the transaction. pub payload: S::Payload, #[codec(skip)] // It may be set to `None` if extensions are decoded. We are never reconstructing transactions - // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to - // read fields of the `payload`. And when resigning transaction, we're reconstructing - // `SignedExtensions` from scratch. - additional_signed: Option, + // (and it makes no sense to do that) => decoded version of `TransactionExtensions` is only + // used to read fields of the `payload`. And when resigning transaction, we're reconstructing + // `TransactionExtensions` from scratch. + implicit: Option, } -impl GenericSignedExtension { - /// Create new `GenericSignedExtension` object. - pub fn new(payload: S::Payload, additional_signed: Option) -> Self { - Self { payload, additional_signed } +impl GenericTransactionExtension { + /// Create new `GenericTransactionExtension` object. + pub fn new(payload: S::Payload, implicit: Option) -> Self { + Self { payload, implicit } } } -impl SignedExtension for GenericSignedExtension +impl TransactionExtensionBase for GenericTransactionExtension where - S: SignedExtensionSchema, + S: TransactionExtensionSchema, S::Payload: Send + Sync, - S::AdditionalSigned: Send + Sync, + S::Implicit: Send + Sync, { const IDENTIFIER: &'static str = "Not needed."; - type AccountId = (); - type Call = (); - type AdditionalSigned = S::AdditionalSigned; - type Pre = (); + type Implicit = S::Implicit; - fn additional_signed(&self) -> Result { + fn implicit(&self) -> Result { // we shall not ever see this error in relay, because we are never signing decoded // transactions. Instead we're constructing and signing new transactions. So the error code // is kinda random here - self.additional_signed.clone().ok_or( - frame_support::unsigned::TransactionValidityError::Unknown( + self.implicit + .clone() + .ok_or(frame_support::unsigned::TransactionValidityError::Unknown( frame_support::unsigned::UnknownTransaction::Custom(0xFF), - ), - ) + )) } +} +impl TransactionExtension for GenericTransactionExtension +where + C: Dispatchable, + S: TransactionExtensionSchema, + S::Payload: Send + Sync, + S::Implicit: Send + Sync, +{ + type Pre = (); + type Val = (); - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result { - Ok(()) - } + impl_tx_ext_default!(C; Context; validate prepare); } diff --git a/bridges/snowbridge/runtime/test-common/Cargo.toml b/bridges/snowbridge/runtime/test-common/Cargo.toml index 4e8b311cb97..5f169e82f49 100644 --- a/bridges/snowbridge/runtime/test-common/Cargo.toml +++ b/bridges/snowbridge/runtime/test-common/Cargo.toml @@ -181,6 +181,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachain-template/runtime/Cargo.toml b/cumulus/parachain-template/runtime/Cargo.toml index 1873bd0a23e..60d8d6f5136 100644 --- a/cumulus/parachain-template/runtime/Cargo.toml +++ b/cumulus/parachain-template/runtime/Cargo.toml @@ -138,6 +138,7 @@ runtime-benchmarks = [ "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", "cumulus-primitives-core/runtime-benchmarks", + "cumulus-primitives-storage-weight-reclaim/runtime-benchmarks", "cumulus-primitives-utility/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", @@ -150,6 +151,7 @@ runtime-benchmarks = [ "pallet-parachain-template/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/cumulus/parachain-template/runtime/src/lib.rs b/cumulus/parachain-template/runtime/src/lib.rs index 004a5d70ebc..f7754e594e6 100644 --- a/cumulus/parachain-template/runtime/src/lib.rs +++ b/cumulus/parachain-template/runtime/src/lib.rs @@ -97,8 +97,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -112,7 +112,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -353,6 +353,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; + type WeightInfo = (); } impl pallet_sudo::Config for Runtime { @@ -529,6 +530,7 @@ construct_runtime!( mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] @@ -712,6 +714,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; let mut list = Vec::::new(); @@ -727,6 +730,7 @@ impl_runtime_apis! { use frame_benchmarking::{BenchmarkError, Benchmarking, BenchmarkBatch}; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index 05936e93993..3eb63a24b74 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -119,6 +119,7 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-asset-conversion-tx-payment/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -130,6 +131,7 @@ runtime-benchmarks = [ "pallet-proxy/runtime-benchmarks", "pallet-state-trie-migration/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 17a12dd2f6f..32966ab6341 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -178,6 +178,7 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; @@ -234,6 +235,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -761,6 +763,9 @@ impl pallet_asset_conversion_tx_payment::Config for Runtime { type Fungibles = LocalAndForeignAssets; type OnChargeAssetTransaction = AssetConversionAdapter; + type WeightInfo = weights::pallet_asset_conversion_tx_payment::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = AssetConversionTxHelper; } parameter_types! { @@ -948,8 +953,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -961,7 +966,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( pallet_collator_selection::migration::v1::MigrateToV1, @@ -1034,14 +1039,77 @@ pub type Executive = frame_executive::Executive< Migrations, >; +#[cfg(feature = "runtime-benchmarks")] +pub struct AssetConversionTxHelper; + +#[cfg(feature = "runtime-benchmarks")] +impl + pallet_asset_conversion_tx_payment::BenchmarkHelperTrait< + AccountId, + xcm::v3::MultiLocation, + xcm::v3::MultiLocation, + > for AssetConversionTxHelper +{ + fn create_asset_id_parameter(seed: u32) -> (xcm::v3::MultiLocation, xcm::v3::MultiLocation) { + // Use a different parachain' foreign assets pallet so that the asset is indeed foreign. + let asset_id = xcm::v3::MultiLocation::new( + 1, + xcm::v3::Junctions::X3( + xcm::v3::Junction::Parachain(3000), + xcm::v3::Junction::PalletInstance(53), + xcm::v3::Junction::GeneralIndex(seed.into()), + ), + ); + (asset_id, asset_id) + } + + fn setup_balances_and_pool(asset_id: xcm::v3::MultiLocation, account: AccountId) { + use frame_support::{assert_ok, traits::fungibles::Mutate}; + assert_ok!(ForeignAssets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + account.clone().into(), /* owner */ + true, /* is_sufficient */ + 1, + )); + + let lp_provider = account.clone(); + use frame_support::traits::Currency; + let _ = Balances::deposit_creating(&lp_provider, u64::MAX.into()); + assert_ok!(ForeignAssets::mint_into(asset_id.into(), &lp_provider, u64::MAX.into())); + + let token_native = Box::new(TokenLocationV3::get()); + let token_second = Box::new(asset_id); + + assert_ok!(AssetConversion::create_pool( + RuntimeOrigin::signed(lp_provider.clone()), + token_native.clone(), + token_second.clone() + )); + + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(lp_provider.clone()), + token_native, + token_second, + (u32::MAX / 8).into(), // 1 desired + u32::MAX.into(), // 2 desired + 1, // 1 min + 1, // 2 min + lp_provider, + )); + } +} + #[cfg(feature = "runtime-benchmarks")] mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_assets, Local] [pallet_assets, Foreign] [pallet_assets, Pool] [pallet_asset_conversion, AssetConversion] + [pallet_asset_conversion_tx_payment, AssetTxPayment] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] @@ -1052,6 +1120,7 @@ mod benches { [pallet_uniques, Uniques] [pallet_utility, Utility] [pallet_timestamp, Timestamp] + [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -1302,6 +1371,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; @@ -1336,6 +1406,7 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..ed2c5f3056e --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/ +// --chain=asset-hub-rococo-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_637_000 picoseconds. + Weight::from_parts(6_382_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_841_000 picoseconds. + Weight::from_parts(8_776_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 561_000 picoseconds. + Weight::from_parts(2_705_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_316_000 picoseconds. + Weight::from_parts(5_771_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 511_000 picoseconds. + Weight::from_parts(2_575_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 501_000 picoseconds. + Weight::from_parts(2_595_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_687_000 picoseconds. + Weight::from_parts(6_192_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs index fa9e86102c6..134b5341a40 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs @@ -19,7 +19,9 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_asset_conversion; +pub mod pallet_asset_conversion_tx_payment; pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; @@ -32,6 +34,7 @@ pub mod pallet_nfts; pub mod pallet_proxy; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_conversion_tx_payment.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_conversion_tx_payment.rs new file mode 100644 index 00000000000..0a639b368af --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_conversion_tx_payment.rs @@ -0,0 +1,92 @@ +// 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 . + +//! Autogenerated weights for `pallet_asset_conversion_tx_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-04, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `Georges-MacBook-Pro.local`, CPU: `` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/debug/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_asset_conversion_tx_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/ +// --chain=asset-hub-rococo-dev + +#![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_asset_conversion_tx_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_asset_conversion_tx_payment::WeightInfo for WeightInfo { + fn charge_asset_tx_payment_zero() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(10_000_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_asset_tx_payment_native() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 209_000_000 picoseconds. + Weight::from_parts(212_000_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Asset` (r:1 w:1) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Account` (r:2 w:2) + /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_asset_tx_payment_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `631` + // Estimated: `7404` + // Minimum execution time: 1_228_000_000 picoseconds. + Weight::from_parts(1_268_000_000, 0) + .saturating_add(Weight::from_parts(0, 7404)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..035f9a6dbe5 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/ +// --chain=asset-hub-rococo-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 33_363_000 picoseconds. + Weight::from_parts(38_793_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index 78c48507a7a..c10e02bd8a6 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -110,6 +110,7 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "hex-literal", + "pallet-asset-conversion-tx-payment/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -120,6 +121,7 @@ runtime-benchmarks = [ "pallet-nfts/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 1ead2897855..5246828da31 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -162,6 +162,7 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; @@ -218,6 +219,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -735,6 +737,9 @@ impl pallet_asset_conversion_tx_payment::Config for Runtime { type Fungibles = LocalAndForeignAssets; type OnChargeAssetTransaction = AssetConversionAdapter; + type WeightInfo = weights::pallet_asset_conversion_tx_payment::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = AssetConversionTxHelper; } parameter_types! { @@ -920,8 +925,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -933,7 +938,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -1065,14 +1070,77 @@ pub type Executive = frame_executive::Executive< Migrations, >; +#[cfg(feature = "runtime-benchmarks")] +pub struct AssetConversionTxHelper; + +#[cfg(feature = "runtime-benchmarks")] +impl + pallet_asset_conversion_tx_payment::BenchmarkHelperTrait< + AccountId, + xcm::v3::MultiLocation, + xcm::v3::MultiLocation, + > for AssetConversionTxHelper +{ + fn create_asset_id_parameter(seed: u32) -> (xcm::v3::MultiLocation, xcm::v3::MultiLocation) { + // Use a different parachain' foreign assets pallet so that the asset is indeed foreign. + let asset_id = xcm::v3::MultiLocation::new( + 1, + xcm::v3::Junctions::X3( + xcm::v3::Junction::Parachain(3000), + xcm::v3::Junction::PalletInstance(53), + xcm::v3::Junction::GeneralIndex(seed.into()), + ), + ); + (asset_id, asset_id) + } + + fn setup_balances_and_pool(asset_id: xcm::v3::MultiLocation, account: AccountId) { + use frame_support::{assert_ok, traits::fungibles::Mutate}; + assert_ok!(ForeignAssets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + account.clone().into(), /* owner */ + true, /* is_sufficient */ + 1, + )); + + let lp_provider = account.clone(); + use frame_support::traits::Currency; + let _ = Balances::deposit_creating(&lp_provider, u64::MAX.into()); + assert_ok!(ForeignAssets::mint_into(asset_id.into(), &lp_provider, u64::MAX.into())); + + let token_native = Box::new(xcm::v3::MultiLocation::new(1, xcm::v3::Junctions::Here)); + let token_second = Box::new(asset_id); + + assert_ok!(AssetConversion::create_pool( + RuntimeOrigin::signed(lp_provider.clone()), + token_native.clone(), + token_second.clone() + )); + + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(lp_provider.clone()), + token_native, + token_second, + (u32::MAX / 2).into(), // 1 desired + u32::MAX.into(), // 2 desired + 1, // 1 min + 1, // 2 min + lp_provider, + )); + } +} + #[cfg(feature = "runtime-benchmarks")] mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_assets, Local] [pallet_assets, Foreign] [pallet_assets, Pool] [pallet_asset_conversion, AssetConversion] + [pallet_asset_conversion_tx_payment, AssetTxPayment] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] @@ -1083,6 +1151,7 @@ mod benches { [pallet_uniques, Uniques] [pallet_utility, Utility] [pallet_timestamp, Timestamp] + [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -1379,6 +1448,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; @@ -1413,6 +1483,7 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..46f4f2bfd96 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/ +// --chain=asset-hub-westend-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_206_000 picoseconds. + Weight::from_parts(6_212_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_851_000 picoseconds. + Weight::from_parts(8_847_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 631_000 picoseconds. + Weight::from_parts(3_086_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_446_000 picoseconds. + Weight::from_parts(5_911_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 481_000 picoseconds. + Weight::from_parts(2_916_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 501_000 picoseconds. + Weight::from_parts(2_595_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_927_000 picoseconds. + Weight::from_parts(6_613_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs index 2f1fcfb05f3..691ed2e5730 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs @@ -18,7 +18,9 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_asset_conversion; +pub mod pallet_asset_conversion_tx_payment; pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; @@ -31,6 +33,7 @@ pub mod pallet_nfts; pub mod pallet_proxy; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_conversion_tx_payment.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_conversion_tx_payment.rs new file mode 100644 index 00000000000..8fe302630fb --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_conversion_tx_payment.rs @@ -0,0 +1,92 @@ +// 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 . + +//! Autogenerated weights for `pallet_asset_conversion_tx_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-04, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `Georges-MacBook-Pro.local`, CPU: `` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/debug/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_asset_conversion_tx_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/ +// --chain=asset-hub-westend-dev + +#![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_asset_conversion_tx_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_asset_conversion_tx_payment::WeightInfo for WeightInfo { + fn charge_asset_tx_payment_zero() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 8_000_000 picoseconds. + Weight::from_parts(9_000_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_asset_tx_payment_native() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 214_000_000 picoseconds. + Weight::from_parts(219_000_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Asset` (r:1 w:1) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Account` (r:2 w:2) + /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_asset_tx_payment_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `631` + // Estimated: `7404` + // Minimum execution time: 1_211_000_000 picoseconds. + Weight::from_parts(1_243_000_000, 0) + .saturating_add(Weight::from_parts(0, 7404)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..b4c78a78b48 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/ +// --chain=asset-hub-westend-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 40_847_000 picoseconds. + Weight::from_parts(49_674_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 7a1951fd24b..242627815d3 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -242,6 +242,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-bridge-hub/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs index 6dbf96edc2a..323e6ed65e6 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs @@ -40,7 +40,7 @@ use bridge_runtime_common::{ XcmBlobMessageDispatch, XcmVersionOfDestAndRemoteBridge, }, refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedGrandpaMessages, RefundSignedExtensionAdapter, + ActualFeeRefund, RefundBridgedGrandpaMessages, RefundTransactionExtensionAdapter, RefundableMessagesLane, }, }; @@ -168,7 +168,7 @@ impl messages::BridgedChainWithMessages for RococoBulletin {} /// Signed extension that refunds relayers that are delivering messages from the Rococo Bulletin /// chain. -pub type OnBridgeHubRococoRefundRococoBulletinMessages = RefundSignedExtensionAdapter< +pub type OnBridgeHubRococoRefundRococoBulletinMessages = RefundTransactionExtensionAdapter< RefundBridgedGrandpaMessages< Runtime, BridgeGrandpaRococoBulletinInstance, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs index 5d55d7afbac..05d1aa188d2 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs @@ -39,7 +39,7 @@ use bridge_runtime_common::{ XcmBlobMessageDispatch, XcmVersionOfDestAndRemoteBridge, }, refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedParachainMessages, RefundSignedExtensionAdapter, + ActualFeeRefund, RefundBridgedParachainMessages, RefundTransactionExtensionAdapter, RefundableMessagesLane, RefundableParachain, }, }; @@ -173,7 +173,7 @@ impl UnderlyingChainProvider for BridgeHubWestend { impl messages::BridgedChainWithMessages for BridgeHubWestend {} /// Signed extension that refunds relayers that are delivering messages from the Westend parachain. -pub type OnBridgeHubRococoRefundBridgeHubWestendMessages = RefundSignedExtensionAdapter< +pub type OnBridgeHubRococoRefundBridgeHubWestendMessages = RefundTransactionExtensionAdapter< RefundBridgedParachainMessages< Runtime, RefundableParachain< diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 0b48d1717fa..16e3b2e8600 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -115,8 +115,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The TransactionExtension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -134,7 +134,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -262,6 +262,8 @@ impl frame_system::Config for Runtime { type DbWeight = RocksDbWeight; /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = weights::frame_system::WeightInfo; + /// Weight information for the extensions of this pallet. + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; /// Block & extrinsics weights: base values and limits. type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). @@ -324,6 +326,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -759,12 +762,14 @@ bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] + [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -1065,6 +1070,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -1095,6 +1101,7 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); @@ -1478,16 +1485,16 @@ mod tests { use codec::Encode; use sp_runtime::{ generic::Era, - traits::{SignedExtension, Zero}, + traits::{TransactionExtensionBase, Zero}, }; #[test] fn ensure_signed_extension_definition_is_compatible_with_relay() { - use bp_polkadot_core::SuffixedCommonSignedExtensionExt; + use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; sp_io::TestExternalities::default().execute_with(|| { frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); - let payload: SignedExtra = ( + let payload: TxExtension = ( frame_system::CheckNonZeroSender::new(), frame_system::CheckSpecVersion::new(), frame_system::CheckTxVersion::new(), @@ -1501,11 +1508,11 @@ mod tests { bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(), bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages::default(), ) - ); + ).into(); // for BridgeHubRococo { - let bhr_indirect_payload = bp_bridge_hub_rococo::SignedExtension::from_params( + let bhr_indirect_payload = bp_bridge_hub_rococo::TransactionExtension::from_params( VERSION.spec_version, VERSION.transaction_version, bp_runtime::TransactionEra::Immortal, @@ -1516,8 +1523,8 @@ mod tests { ); assert_eq!(payload.encode(), bhr_indirect_payload.encode()); assert_eq!( - payload.additional_signed().unwrap().encode(), - bhr_indirect_payload.additional_signed().unwrap().encode() + payload.implicit().unwrap().encode(), + bhr_indirect_payload.implicit().unwrap().encode() ) } }); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..99e3d6aeba0 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/ +// --chain=bridge-hub-rococo-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_136_000 picoseconds. + Weight::from_parts(5_842_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_771_000 picoseconds. + Weight::from_parts(8_857_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 732_000 picoseconds. + Weight::from_parts(2_875_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_627_000 picoseconds. + Weight::from_parts(6_322_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 471_000 picoseconds. + Weight::from_parts(2_455_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 491_000 picoseconds. + Weight::from_parts(2_916_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_798_000 picoseconds. + Weight::from_parts(6_272_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs index aac39a4564f..d97a30db954 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs @@ -25,6 +25,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_bridge_grandpa; pub mod pallet_bridge_messages_rococo_to_rococo_bulletin; @@ -36,6 +37,7 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..71d17e7259f --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/ +// --chain=bridge-hub-rococo-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3593` + // Minimum execution time: 34_956_000 picoseconds. + Weight::from_parts(40_788_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs index 239bd946e75..46c5df18a15 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs @@ -22,7 +22,7 @@ use bridge_hub_rococo_runtime::{ bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages, xcm_config::XcmConfig, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, MessageQueueServiceWeight, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, - SignedExtra, UncheckedExtrinsic, + TxExtension, UncheckedExtrinsic, }; use codec::{Decode, Encode}; use cumulus_primitives_core::XcmError::{FailedToTransactAsset, NotHoldingFees}; @@ -171,7 +171,7 @@ fn construct_extrinsic( call: RuntimeCall, ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); - let extra: SignedExtra = ( + let tx_ext: TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -188,13 +188,13 @@ fn construct_extrinsic( OnBridgeHubRococoRefundRococoBulletinMessages::default(), ), ); - let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); + let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); UncheckedExtrinsic::new_signed( call, account_id.into(), Signature::Sr25519(signature.clone()), - extra, + tx_ext, ) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index f11954cf165..565343c55a5 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -22,7 +22,7 @@ use bridge_hub_rococo_runtime::{ xcm_config::{RelayNetwork, TokenLocation, XcmConfig}, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, EthereumGatewayAddress, Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, - RuntimeEvent, RuntimeOrigin, SessionKeys, SignedExtra, TransactionPayment, UncheckedExtrinsic, + RuntimeEvent, RuntimeOrigin, SessionKeys, TransactionPayment, TxExtension, UncheckedExtrinsic, }; use bridge_hub_test_utils::SlotDurations; use codec::{Decode, Encode}; @@ -48,7 +48,7 @@ fn construct_extrinsic( call: RuntimeCall, ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); - let extra: SignedExtra = ( + let tx_ext: TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -64,14 +64,15 @@ fn construct_extrinsic( bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(), bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages::default(), ), - ); - let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); + ) + .into(); + let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); UncheckedExtrinsic::new_signed( call, account_id.into(), Signature::Sr25519(signature.clone()), - extra, + tx_ext, ) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml index 8623f7cb366..b5fe093b8be 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml @@ -204,6 +204,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-bridge-hub/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs index bce722aa5f8..934dce5c2c4 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs @@ -36,7 +36,7 @@ use bridge_runtime_common::{ XcmBlobMessageDispatch, XcmVersionOfDestAndRemoteBridge, }, refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedParachainMessages, RefundSignedExtensionAdapter, + ActualFeeRefund, RefundBridgedParachainMessages, RefundTransactionExtensionAdapter, RefundableMessagesLane, RefundableParachain, }, }; @@ -190,7 +190,7 @@ impl ThisChainWithMessages for BridgeHubWestend { } /// Signed extension that refunds relayers that are delivering messages from the Rococo parachain. -pub type OnBridgeHubWestendRefundBridgeHubRococoMessages = RefundSignedExtensionAdapter< +pub type OnBridgeHubWestendRefundBridgeHubRococoMessages = RefundTransactionExtensionAdapter< RefundBridgedParachainMessages< Runtime, RefundableParachain, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index e1344fce63d..86ed8b2f488 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -97,8 +97,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The TransactionExtension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -113,7 +113,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -298,6 +298,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -515,12 +516,14 @@ bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] + [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -761,6 +764,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -790,6 +794,7 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); @@ -1135,16 +1140,16 @@ mod tests { use codec::Encode; use sp_runtime::{ generic::Era, - traits::{SignedExtension, Zero}, + traits::{TransactionExtensionBase, Zero}, }; #[test] fn ensure_signed_extension_definition_is_compatible_with_relay() { - use bp_polkadot_core::SuffixedCommonSignedExtensionExt; + use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; sp_io::TestExternalities::default().execute_with(|| { frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); - let payload: SignedExtra = ( + let payload: TxExtension = ( frame_system::CheckNonZeroSender::new(), frame_system::CheckSpecVersion::new(), frame_system::CheckTxVersion::new(), @@ -1157,10 +1162,10 @@ mod tests { ( bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages::default(), ), - ); + ).into(); { - let bh_indirect_payload = bp_bridge_hub_westend::SignedExtension::from_params( + let bh_indirect_payload = bp_bridge_hub_westend::TransactionExtension::from_params( VERSION.spec_version, VERSION.transaction_version, bp_runtime::TransactionEra::Immortal, @@ -1171,8 +1176,8 @@ mod tests { ); assert_eq!(payload.encode(), bh_indirect_payload.encode()); assert_eq!( - payload.additional_signed().unwrap().encode(), - bh_indirect_payload.additional_signed().unwrap().encode() + payload.implicit().unwrap().encode(), + bh_indirect_payload.implicit().unwrap().encode() ) } }); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..06f1114b4de --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/ +// --chain=bridge-hub-westend-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_166_000 picoseconds. + Weight::from_parts(6_021_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_651_000 picoseconds. + Weight::from_parts(9_177_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 601_000 picoseconds. + Weight::from_parts(2_805_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_727_000 picoseconds. + Weight::from_parts(6_051_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 471_000 picoseconds. + Weight::from_parts(2_494_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 521_000 picoseconds. + Weight::from_parts(2_655_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_808_000 picoseconds. + Weight::from_parts(6_402_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs index a65ee31d3e5..e23033e0dfd 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs @@ -25,6 +25,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_bridge_grandpa; pub mod pallet_bridge_messages; @@ -35,6 +36,7 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..92c53b91879 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/ +// --chain=bridge-hub-westend-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3593` + // Minimum execution time: 40_286_000 picoseconds. + Weight::from_parts(45_816_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs index 149a3bbeb75..7ea22befe95 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs @@ -24,7 +24,7 @@ use bridge_hub_westend_runtime::{ xcm_config::{RelayNetwork, WestendLocation, XcmConfig}, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, - SignedExtra, TransactionPayment, UncheckedExtrinsic, + TransactionPayment, TxExtension, UncheckedExtrinsic, }; use bridge_to_rococo_config::{ BridgeGrandpaRococoInstance, BridgeHubRococoChainId, BridgeHubRococoLocation, @@ -65,7 +65,7 @@ fn construct_extrinsic( call: RuntimeCall, ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); - let extra: SignedExtra = ( + let tx_ext: TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -78,14 +78,15 @@ fn construct_extrinsic( pallet_transaction_payment::ChargeTransactionPayment::::from(0), BridgeRejectObsoleteHeadersAndMessages::default(), (bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages::default(),), - ); - let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); + ) + .into(); + let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); UncheckedExtrinsic::new_signed( call, account_id.into(), Signature::Sr25519(signature.clone()), - extra, + tx_ext, ) } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml index ed264f28c26..32d7e97bc45 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml @@ -117,6 +117,7 @@ runtime-benchmarks = [ "pallet-salary/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 6bcf98c428f..3887a1d74ec 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -175,6 +175,7 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = ConstU16<0>; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; @@ -231,6 +232,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -707,8 +709,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -719,7 +721,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// All migrations executed on runtime upgrade as a nested tuple of types implementing /// `OnRuntimeUpgrade`. Included migrations must be idempotent. type Migrations = ( @@ -745,6 +747,7 @@ pub type Executive = frame_executive::Executive< mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] @@ -752,6 +755,7 @@ mod benches { [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] + [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -955,6 +959,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -972,6 +977,7 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..f3030cc4f6a --- /dev/null +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/ +// --chain=collectives-westend-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_497_000 picoseconds. + Weight::from_parts(5_961_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_240_000 picoseconds. + Weight::from_parts(8_175_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 671_000 picoseconds. + Weight::from_parts(3_005_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_426_000 picoseconds. + Weight::from_parts(6_131_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 501_000 picoseconds. + Weight::from_parts(2_715_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 491_000 picoseconds. + Weight::from_parts(2_635_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_958_000 picoseconds. + Weight::from_parts(6_753_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs index a9a298e547e..00b3bd92d5e 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs @@ -18,6 +18,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_alliance; pub mod pallet_asset_rate; pub mod pallet_balances; @@ -39,6 +40,7 @@ pub mod pallet_salary_fellowship_salary; pub mod pallet_scheduler; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_treasury; pub mod pallet_utility; pub mod pallet_xcm; diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..5d077b89d56 --- /dev/null +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/ +// --chain=collectives-westend-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 39_815_000 picoseconds. + Weight::from_parts(46_067_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml index dcc6c4e853a..747f75cf2e2 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml @@ -158,6 +158,7 @@ runtime-benchmarks = [ "pallet-multisig/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 0668b9a4c7d..8ce46ccd34f 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -80,8 +80,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -93,7 +93,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -240,6 +240,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; + type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } parameter_types! { @@ -423,6 +424,7 @@ construct_runtime!( mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] @@ -686,6 +688,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -703,6 +706,7 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml index 0bc3b510ed5..70a6a81bdcf 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml @@ -156,6 +156,7 @@ runtime-benchmarks = [ "pallet-multisig/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index cdff371c505..9913e47a93a 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -89,8 +89,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The TransactionExtension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -103,7 +103,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -192,6 +192,8 @@ impl frame_system::Config for Runtime { type DbWeight = RocksDbWeight; /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = weights::frame_system::WeightInfo; + /// Weight information for the extensions of this pallet. + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; /// Block & extrinsics weights: base values and limits. type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). @@ -251,6 +253,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..aac73680ad1 --- /dev/null +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/ +// --chain=coretime-rococo-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_637_000 picoseconds. + Weight::from_parts(6_382_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_841_000 picoseconds. + Weight::from_parts(8_776_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 561_000 picoseconds. + Weight::from_parts(2_705_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_316_000 picoseconds. + Weight::from_parts(5_771_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 511_000 picoseconds. + Weight::from_parts(2_575_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 501_000 picoseconds. + Weight::from_parts(2_595_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_687_000 picoseconds. + Weight::from_parts(6_192_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs index f1050b3ae63..7b6ab611e6f 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs @@ -22,6 +22,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_broker; pub mod pallet_collator_selection; @@ -29,6 +30,7 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..29d48abab89 --- /dev/null +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/ +// --chain=coretime-rococo-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 33_363_000 picoseconds. + Weight::from_parts(38_793_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml index a7d52dfd784..549ef7ce4d7 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml @@ -153,6 +153,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 7fa70647992..1a330821d3f 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -89,8 +89,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The TransactionExtension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -103,7 +103,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -192,6 +192,8 @@ impl frame_system::Config for Runtime { type DbWeight = RocksDbWeight; /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = weights::frame_system::WeightInfo; + /// Weight information for the extensions of this pallet. + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; /// Block & extrinsics weights: base values and limits. type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). @@ -251,6 +253,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..0683158a01a --- /dev/null +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/ +// --chain=coretime-westend-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_637_000 picoseconds. + Weight::from_parts(6_382_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_841_000 picoseconds. + Weight::from_parts(8_776_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 561_000 picoseconds. + Weight::from_parts(2_705_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_316_000 picoseconds. + Weight::from_parts(5_771_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 511_000 picoseconds. + Weight::from_parts(2_575_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 501_000 picoseconds. + Weight::from_parts(2_595_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_687_000 picoseconds. + Weight::from_parts(6_192_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs index f1050b3ae63..7b6ab611e6f 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs @@ -22,6 +22,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_broker; pub mod pallet_collator_selection; @@ -29,6 +30,7 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..f159f877afe --- /dev/null +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/ +// --chain=coretime-westend-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 33_363_000 picoseconds. + Weight::from_parts(38_793_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index 232a82115a8..199057c3764 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -289,8 +289,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( pallet_sudo::CheckOnlySudoAccount, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, @@ -301,7 +301,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -316,6 +316,7 @@ mod benches { frame_benchmarking::define_benchmarks!( [cumulus_pallet_parachain_system, ParachainSystem] [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_glutton, Glutton] [pallet_message_queue, MessageQueue] [pallet_timestamp, Timestamp] @@ -439,6 +440,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -455,6 +457,7 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..e6efa762308 --- /dev/null +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs @@ -0,0 +1,119 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("glutton-westend-dev-1300")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/ +// --chain=glutton-westend-dev-1300 + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_908_000 picoseconds. + Weight::from_parts(4_007_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_510_000 picoseconds. + Weight::from_parts(6_332_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 651_000 picoseconds. + Weight::from_parts(851_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_387_000 picoseconds. + Weight::from_parts(3_646_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 491_000 picoseconds. + Weight::from_parts(651_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 451_000 picoseconds. + Weight::from_parts(662_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1489` + // Minimum execution time: 3_537_000 picoseconds. + Weight::from_parts(4_208_000, 0) + .saturating_add(Weight::from_parts(0, 1489)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml index c0b8fb7636b..c9781639c3e 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml @@ -152,6 +152,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 2b8cc32f67c..c5e420785de 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -83,8 +83,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The TransactionExtension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -97,7 +97,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -178,6 +178,7 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = ConstU32<16>; @@ -232,6 +233,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -453,6 +455,7 @@ mod benches { [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] + [pallet_transaction_payment, TransactionPayment] // Polkadot [polkadot_runtime_common::identity_migrator, IdentityMigrator] // Cumulus diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..1ba2010991f --- /dev/null +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights/ +// --chain=people-rococo-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_637_000 picoseconds. + Weight::from_parts(6_382_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_841_000 picoseconds. + Weight::from_parts(8_776_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 561_000 picoseconds. + Weight::from_parts(2_705_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_316_000 picoseconds. + Weight::from_parts(5_771_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 511_000 picoseconds. + Weight::from_parts(2_575_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 501_000 picoseconds. + Weight::from_parts(2_595_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_687_000 picoseconds. + Weight::from_parts(6_192_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs index 3396a8caea0..c4cea99ee5a 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs @@ -20,6 +20,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_collator_selection; pub mod pallet_identity; @@ -27,6 +28,7 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..555fd5a32fa --- /dev/null +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights/ +// --chain=people-rococo-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 33_363_000 picoseconds. + Weight::from_parts(38_793_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml index e87e825a34e..8d8421332c1 100644 --- a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml @@ -152,6 +152,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 2dc2d06a66b..dea079a4a98 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -83,8 +83,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The transactionExtension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -97,7 +97,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -178,6 +178,7 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = ConstU32<16>; @@ -232,6 +233,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..7130a62ab6a --- /dev/null +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights/ +// --chain=people-westend-dev + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_637_000 picoseconds. + Weight::from_parts(6_382_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_841_000 picoseconds. + Weight::from_parts(8_776_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 561_000 picoseconds. + Weight::from_parts(2_705_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_316_000 picoseconds. + Weight::from_parts(5_771_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 511_000 picoseconds. + Weight::from_parts(2_575_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 501_000 picoseconds. + Weight::from_parts(2_595_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::BlockWeight` (r:1 w:1) + /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1533` + // Minimum execution time: 3_687_000 picoseconds. + Weight::from_parts(6_192_000, 0) + .saturating_add(Weight::from_parts(0, 1533)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs index 3396a8caea0..c4cea99ee5a 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs @@ -20,6 +20,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_collator_selection; pub mod pallet_identity; @@ -27,6 +28,7 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..30e4524e586 --- /dev/null +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,67 @@ +// 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 . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot-parachain +// benchmark +// pallet +// --wasm-execution=compiled +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --steps=2 +// --repeat=2 +// --json +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights/ +// --chain=people-westend-dev + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3593` + // Minimum execution time: 33_363_000 picoseconds. + Weight::from_parts(38_793_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs index 4cc0a81ef49..023c9978302 100644 --- a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs @@ -258,8 +258,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, @@ -269,7 +269,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< diff --git a/cumulus/parachains/runtimes/starters/shell/src/lib.rs b/cumulus/parachains/runtimes/starters/shell/src/lib.rs index 829754731a4..fedac36e48d 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/lib.rs @@ -34,15 +34,19 @@ pub mod xcm_config; use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use cumulus_primitives_core::AggregateMessageOrigin; -use frame_support::unsigned::TransactionValidityError; use scale_info::TypeInfo; use sp_api::impl_runtime_apis; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf}, - transaction_validity::{TransactionSource, TransactionValidity}, + traits::{ + AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, OriginOf, + TransactionExtension, TransactionExtensionBase, ValidateResult, + }, + transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, + }, ApplyExtrinsicResult, }; use sp_std::prelude::*; @@ -275,35 +279,37 @@ construct_runtime! { /// Simple implementation which fails any transaction which is signed. #[derive(Eq, PartialEq, Clone, Default, sp_core::RuntimeDebug, Encode, Decode, TypeInfo)] pub struct DisallowSigned; -impl sp_runtime::traits::SignedExtension for DisallowSigned { + +impl TransactionExtensionBase for DisallowSigned { const IDENTIFIER: &'static str = "DisallowSigned"; - type AccountId = AccountId; - type Call = RuntimeCall; - type AdditionalSigned = (); + type Implicit = (); +} + +impl TransactionExtension for DisallowSigned { + type Val = (); type Pre = (); - fn additional_signed( + fn validate( &self, - ) -> sp_std::result::Result<(), sp_runtime::transaction_validity::TransactionValidityError> { - Ok(()) + _origin: OriginOf, + _call: &RuntimeCall, + _info: &DispatchInfoOf, + _len: usize, + _context: &mut C, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult { + Err(InvalidTransaction::BadProof.into()) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) - } - fn validate( - &self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, + _val: Self::Val, + _origin: &OriginOf, + _call: &RuntimeCall, + _info: &DispatchInfoOf, _len: usize, - ) -> TransactionValidity { - let i = sp_runtime::transaction_validity::InvalidTransaction::BadProof; - Err(sp_runtime::transaction_validity::TransactionValidityError::Invalid(i)) + _context: &C, + ) -> Result { + Err(InvalidTransaction::BadProof.into()) } } @@ -323,11 +329,11 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = DisallowSigned; +/// The extension to the basic transaction logic. +pub type TxExtension = DisallowSigned; /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, diff --git a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml index 08e5987d43a..bca6aca051f 100644 --- a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml @@ -158,6 +158,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 0030287edb3..62065619e42 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -114,8 +114,8 @@ pub type BlockId = generic::BlockId; // Id used for identifying assets. pub type AssetId = u32; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -128,7 +128,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; pub type Migrations = ( pallet_balances::migration::MigrateToTrackInactive, @@ -419,6 +419,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; + type WeightInfo = (); } parameter_types! { @@ -608,6 +609,19 @@ impl pallet_collator_selection::Config for Runtime { type WeightInfo = (); } +#[cfg(feature = "runtime-benchmarks")] +pub struct AssetTxHelper; + +#[cfg(feature = "runtime-benchmarks")] +impl pallet_asset_tx_payment::BenchmarkHelperTrait for AssetTxHelper { + fn create_asset_id_parameter(_id: u32) -> (u32, u32) { + unimplemented!("Penpal uses default weights"); + } + fn setup_balances_and_pool(_asset_id: u32, _account: AccountId) { + unimplemented!("Penpal uses default weights"); + } +} + impl pallet_asset_tx_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = Assets; @@ -620,6 +634,9 @@ impl pallet_asset_tx_payment::Config for Runtime { >, AssetsToBlockAuthor, >; + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = AssetTxHelper; } impl pallet_sudo::Config for Runtime { @@ -668,6 +685,7 @@ construct_runtime!( mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_session, SessionBench::] @@ -851,6 +869,7 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; let mut list = Vec::::new(); @@ -867,6 +886,7 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime {} use cumulus_pallet_session_benchmarking::Pallet as SessionBench; diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml index 42169e8949f..2023d9abf5d 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml @@ -126,6 +126,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 2b21a12c3ca..469f06a1aa6 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -267,6 +267,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; + type WeightInfo = (); } impl pallet_sudo::Config for Runtime { @@ -644,8 +645,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -657,7 +658,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index 84a232e954f..a92e8a4c12a 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -136,6 +136,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "glutton-westend-runtime/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "parachains-common/runtime-benchmarks", "penpal-runtime/runtime-benchmarks", "people-rococo-runtime/runtime-benchmarks", diff --git a/cumulus/primitives/storage-weight-reclaim/Cargo.toml b/cumulus/primitives/storage-weight-reclaim/Cargo.toml index 4835fb5192b..9e8f60783d4 100644 --- a/cumulus/primitives/storage-weight-reclaim/Cargo.toml +++ b/cumulus/primitives/storage-weight-reclaim/Cargo.toml @@ -14,9 +14,12 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-support = { path = "../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../substrate/frame/system", default-features = false } +sp-core = { path = "../../../substrate/primitives/core", default-features = false } +sp-io = { path = "../../../substrate/primitives/io", default-features = false } sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } sp-std = { path = "../../../substrate/primitives/std", default-features = false } @@ -26,19 +29,27 @@ docify = "0.2.7" [dev-dependencies] sp-trie = { path = "../../../substrate/primitives/trie", default-features = false } -sp-io = { path = "../../../substrate/primitives/io", default-features = false } cumulus-test-runtime = { path = "../../test/runtime" } [features] default = ["std"] +runtime-benchmarks = [ + "cumulus-primitives-core/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] std = [ "codec/std", "cumulus-primitives-core/std", "cumulus-primitives-proof-size-hostfunction/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", "log/std", "scale-info/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", diff --git a/cumulus/primitives/storage-weight-reclaim/src/benchmarking.rs b/cumulus/primitives/storage-weight-reclaim/src/benchmarking.rs new file mode 100644 index 00000000000..2980d08271a --- /dev/null +++ b/cumulus/primitives/storage-weight-reclaim/src/benchmarking.rs @@ -0,0 +1,70 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Benchmarking setup for cumulus-primitives-storage-weight-reclaim + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use frame_benchmarking::{account, v2::*, BenchmarkError}; +use frame_support::pallet_prelude::DispatchClass; +use frame_system::{BlockWeight, RawOrigin}; +use sp_runtime::traits::{DispatchTransaction, Get}; +use sp_std::{ + marker::{Send, Sync}, + prelude::*, +}; + +/// Pallet we're benchmarking here. +pub struct Pallet(frame_system::Pallet); + +#[benchmarks(where + T: Send + Sync, + T::RuntimeCall: Dispatchable +)] +mod benchmarks { + use super::*; + + #[benchmark] + fn storage_weight_reclaim() -> Result<(), BenchmarkError> { + let caller = account("caller", 0, 0); + BlockWeight::::mutate(|current_weight| { + current_weight.set(Weight::from_parts(0, 1000), DispatchClass::Normal); + }); + let base_extrinsic = ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(0, 200)), + pays_fee: Default::default(), + }; + let len = 0_usize; + let ext = StorageWeightReclaim::::new(); + + #[block] + { + ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(post_info)) + .unwrap() + .unwrap(); + } + + assert_eq!(BlockWeight::::get().total().proof_size(), 700 + base_extrinsic.proof_size()); + + Ok(()) + } +} diff --git a/cumulus/primitives/storage-weight-reclaim/src/lib.rs b/cumulus/primitives/storage-weight-reclaim/src/lib.rs index 5dddc92e395..4bb40176b78 100644 --- a/cumulus/primitives/storage-weight-reclaim/src/lib.rs +++ b/cumulus/primitives/storage-weight-reclaim/src/lib.rs @@ -29,12 +29,22 @@ use frame_support::{ use frame_system::Config; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, + impl_tx_ext_default, + traits::{ + DispatchInfoOf, Dispatchable, PostDispatchInfoOf, TransactionExtension, + TransactionExtensionBase, + }, transaction_validity::TransactionValidityError, DispatchResult, }; use sp_std::marker::PhantomData; +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + const LOG_TARGET: &'static str = "runtime::storage_reclaim"; /// `StorageWeightReclaimer` is a mechanism for manually reclaiming storage weight. @@ -43,7 +53,7 @@ const LOG_TARGET: &'static str = "runtime::storage_reclaim"; /// reclaim it computes the real consumed storage weight and refunds excess weight. /// /// # Example -#[doc = docify::embed!("src/lib.rs", simple_reclaimer_example)] +#[doc = docify::embed!("src/tests.rs", simple_reclaimer_example)] pub struct StorageWeightReclaimer { previous_remaining_proof_size: u64, previous_reported_proof_size: Option, @@ -119,42 +129,40 @@ impl core::fmt::Debug for StorageWeightReclaim { } } -impl SignedExtension for StorageWeightReclaim +impl TransactionExtensionBase for StorageWeightReclaim { + const IDENTIFIER: &'static str = "StorageWeightReclaim"; + type Implicit = (); +} + +impl TransactionExtension + for StorageWeightReclaim where T::RuntimeCall: Dispatchable, { - const IDENTIFIER: &'static str = "StorageWeightReclaim"; - - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); + type Val = (); type Pre = Option; - fn additional_signed( - &self, - ) -> Result - { - Ok(()) - } - - fn pre_dispatch( + fn prepare( self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, + _val: Self::Val, + _origin: &T::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, _len: usize, - ) -> Result { + _context: &Context, + ) -> Result { Ok(get_proof_size()) } fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, _len: usize, _result: &DispatchResult, + _context: &Context, ) -> Result<(), TransactionValidityError> { - let Some(Some(pre_dispatch_proof_size)) = pre else { + let Some(pre_dispatch_proof_size) = pre else { return Ok(()); }; @@ -194,470 +202,6 @@ where }); Ok(()) } -} - -#[cfg(test)] -mod tests { - use super::*; - use frame_support::{ - assert_ok, - dispatch::DispatchClass, - weights::{Weight, WeightMeter}, - }; - use frame_system::{BlockWeight, CheckWeight}; - use sp_runtime::{AccountId32, BuildStorage}; - use sp_std::marker::PhantomData; - use sp_trie::proof_size_extension::ProofSizeExt; - - type Test = cumulus_test_runtime::Runtime; - const CALL: &::RuntimeCall = - &cumulus_test_runtime::RuntimeCall::System(frame_system::Call::set_heap_pages { - pages: 0u64, - }); - const ALICE: AccountId32 = AccountId32::new([1u8; 32]); - const LEN: usize = 0; - - pub fn new_test_ext() -> sp_io::TestExternalities { - let ext: sp_io::TestExternalities = cumulus_test_runtime::RuntimeGenesisConfig::default() - .build_storage() - .unwrap() - .into(); - ext - } - - struct TestRecorder { - return_values: Box<[usize]>, - counter: std::sync::atomic::AtomicUsize, - } - - impl TestRecorder { - fn new(values: &[usize]) -> Self { - TestRecorder { return_values: values.into(), counter: Default::default() } - } - } - - impl sp_trie::ProofSizeProvider for TestRecorder { - fn estimate_encoded_size(&self) -> usize { - let counter = self.counter.fetch_add(1, core::sync::atomic::Ordering::Relaxed); - self.return_values[counter] - } - } - - fn setup_test_externalities(proof_values: &[usize]) -> sp_io::TestExternalities { - let mut test_ext = new_test_ext(); - let test_recorder = TestRecorder::new(proof_values); - test_ext.register_extension(ProofSizeExt::new(test_recorder)); - test_ext - } - - fn set_current_storage_weight(new_weight: u64) { - BlockWeight::::mutate(|current_weight| { - current_weight.set(Weight::from_parts(0, new_weight), DispatchClass::Normal); - }); - } - - #[test] - fn basic_refund() { - // The real cost will be 100 bytes of storage size - let mut test_ext = setup_test_externalities(&[0, 100]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - - // Benchmarked storage weight: 500 - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(0)); - - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - // We expect a refund of 400 - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 600); - }) - } - - #[test] - fn does_nothing_without_extension() { - let mut test_ext = new_test_ext(); - - // Proof size extension not registered - test_ext.execute_with(|| { - set_current_storage_weight(1000); - - // Benchmarked storage weight: 500 - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, None); - - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 1000); - }) - } - - #[test] - fn negative_refund_is_added_to_weight() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - // Benchmarked storage weight: 100 - let info = DispatchInfo { weight: Weight::from_parts(0, 100), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - // We expect no refund - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 1100); - }) - } - - #[test] - fn test_zero_proof_size() { - let mut test_ext = setup_test_externalities(&[0, 0]); - - test_ext.execute_with(|| { - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(0)); - - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 0); - }); - } - - #[test] - fn test_larger_pre_dispatch_proof_size() { - let mut test_ext = setup_test_externalities(&[300, 100]); - - test_ext.execute_with(|| { - set_current_storage_weight(1300); - - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(300)); - - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 800); - }); - } - - #[test] - fn test_incorporates_check_weight_unspent_weight() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - - // Benchmarked storage weight: 300 - let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; - - // Actual weight is 50 - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(50, 250)), - pays_fee: Default::default(), - }; - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` - // we always need to call `post_dispatch` to verify that they interoperate correctly. - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 900); - }) - } - - #[test] - fn test_incorporates_check_weight_unspent_weight_on_negative() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - // Benchmarked storage weight: 50 - let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; - - // Actual weight is 25 - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(50, 25)), - pays_fee: Default::default(), - }; - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` - // we always need to call `post_dispatch` to verify that they interoperate correctly. - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 1150); - }) - } - - #[test] - fn test_incorporates_check_weight_unspent_weight_reverse_order() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - - // Benchmarked storage weight: 300 - let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; - - // Actual weight is 50 - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(50, 250)), - pays_fee: Default::default(), - }; - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - // `CheckWeight` gets called after `StorageWeightReclaim` this time. - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` - // we always need to call `post_dispatch` to verify that they interoperate correctly. - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - - assert_eq!(BlockWeight::::get().total().proof_size(), 900); - }) - } - - #[test] - fn test_incorporates_check_weight_unspent_weight_on_negative_reverse_order() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - // Benchmarked storage weight: 50 - let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; - // Actual weight is 25 - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(50, 25)), - pays_fee: Default::default(), - }; - - let pre = StorageWeightReclaim::(PhantomData) - .pre_dispatch(&ALICE, CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - assert_ok!(StorageWeightReclaim::::post_dispatch( - Some(pre), - &info, - &post_info, - LEN, - &Ok(()) - )); - // `CheckWeight` gets called after `StorageWeightReclaim` this time. - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` - // we always need to call `post_dispatch` to verify that they interoperate correctly. - assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - - assert_eq!(BlockWeight::::get().total().proof_size(), 1150); - }) - } - - #[test] - fn storage_size_reported_correctly() { - let mut test_ext = setup_test_externalities(&[1000]); - test_ext.execute_with(|| { - assert_eq!(get_proof_size(), Some(1000)); - }); - - let mut test_ext = new_test_ext(); - - let test_recorder = TestRecorder::new(&[0]); - - test_ext.register_extension(ProofSizeExt::new(test_recorder)); - - test_ext.execute_with(|| { - assert_eq!(get_proof_size(), Some(0)); - }); - } - - #[test] - fn storage_size_disabled_reported_correctly() { - let mut test_ext = setup_test_externalities(&[PROOF_RECORDING_DISABLED as usize]); - - test_ext.execute_with(|| { - assert_eq!(get_proof_size(), None); - }); - } - - #[test] - fn test_reclaim_helper() { - let mut test_ext = setup_test_externalities(&[1000, 1300, 1800]); - - test_ext.execute_with(|| { - let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 2000)); - let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); - remaining_weight_meter.consume(Weight::from_parts(0, 500)); - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - - assert_eq!(reclaimed, Some(Weight::from_parts(0, 200))); - - remaining_weight_meter.consume(Weight::from_parts(0, 800)); - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - assert_eq!(reclaimed, Some(Weight::from_parts(0, 300))); - assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1200)); - }); - } - - #[test] - fn test_reclaim_helper_does_not_reclaim_negative() { - // Benchmarked weight does not change at all - let mut test_ext = setup_test_externalities(&[1000, 1300]); - - test_ext.execute_with(|| { - let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); - let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - - assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); - assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1000)); - }); - - // Benchmarked weight increases less than storage proof consumes - let mut test_ext = setup_test_externalities(&[1000, 1300]); - - test_ext.execute_with(|| { - let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); - let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); - remaining_weight_meter.consume(Weight::from_parts(0, 0)); - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - - assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); - }); - } - - /// Just here for doc purposes - fn get_benched_weight() -> Weight { - Weight::from_parts(0, 5) - } - - /// Just here for doc purposes - fn do_work() {} - - #[docify::export_content(simple_reclaimer_example)] - fn reclaim_with_weight_meter() { - let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(10, 10)); - - let benched_weight = get_benched_weight(); - - // It is important to instantiate the `StorageWeightReclaimer` before we consume the weight - // for a piece of work from the weight meter. - let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); - - if remaining_weight_meter.try_consume(benched_weight).is_ok() { - // Perform some work that takes has `benched_weight` storage weight. - do_work(); - - // Reclaimer will detect that we only consumed 2 bytes, so 3 bytes are reclaimed. - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - - // We reclaimed 3 bytes of storage size! - assert_eq!(reclaimed, Some(Weight::from_parts(0, 3))); - assert_eq!(BlockWeight::::get().total().proof_size(), 10); - assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(10, 8)); - } - } - - #[test] - fn test_reclaim_helper_works_with_meter() { - // The node will report 12 - 10 = 2 consumed storage size between the calls. - let mut test_ext = setup_test_externalities(&[10, 12]); - - test_ext.execute_with(|| { - // Initial storage size is 10. - set_current_storage_weight(10); - reclaim_with_weight_meter(); - }); - } + impl_tx_ext_default!(T::RuntimeCall; Context; validate); } diff --git a/cumulus/primitives/storage-weight-reclaim/src/tests.rs b/cumulus/primitives/storage-weight-reclaim/src/tests.rs new file mode 100644 index 00000000000..631827cf442 --- /dev/null +++ b/cumulus/primitives/storage-weight-reclaim/src/tests.rs @@ -0,0 +1,484 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use super::*; +use frame_support::{ + assert_ok, + dispatch::DispatchClass, + weights::{Weight, WeightMeter}, +}; +use frame_system::{BlockWeight, CheckWeight}; +use sp_runtime::{traits::DispatchTransaction, AccountId32, BuildStorage}; +use sp_std::marker::PhantomData; +use sp_trie::proof_size_extension::ProofSizeExt; + +type Test = cumulus_test_runtime::Runtime; +const CALL: &::RuntimeCall = + &cumulus_test_runtime::RuntimeCall::System(frame_system::Call::set_heap_pages { pages: 0u64 }); +const ALICE: AccountId32 = AccountId32::new([1u8; 32]); +const LEN: usize = 0; + +fn new_test_ext() -> sp_io::TestExternalities { + let ext: sp_io::TestExternalities = cumulus_test_runtime::RuntimeGenesisConfig::default() + .build_storage() + .unwrap() + .into(); + ext +} + +struct TestRecorder { + return_values: Box<[usize]>, + counter: std::sync::atomic::AtomicUsize, +} + +impl TestRecorder { + fn new(values: &[usize]) -> Self { + TestRecorder { return_values: values.into(), counter: Default::default() } + } +} + +impl sp_trie::ProofSizeProvider for TestRecorder { + fn estimate_encoded_size(&self) -> usize { + let counter = self.counter.fetch_add(1, core::sync::atomic::Ordering::Relaxed); + self.return_values[counter] + } +} + +fn setup_test_externalities(proof_values: &[usize]) -> sp_io::TestExternalities { + let mut test_ext = new_test_ext(); + let test_recorder = TestRecorder::new(proof_values); + test_ext.register_extension(ProofSizeExt::new(test_recorder)); + test_ext +} + +fn set_current_storage_weight(new_weight: u64) { + BlockWeight::::mutate(|current_weight| { + current_weight.set(Weight::from_parts(0, new_weight), DispatchClass::Normal); + }); +} + +#[test] +fn basic_refund() { + // The real cost will be 100 bytes of storage size + let mut test_ext = setup_test_externalities(&[0, 100]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 500 + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(0)); + + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + // We expect a refund of 400 + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 600); + }) +} + +#[test] +fn does_nothing_without_extension() { + let mut test_ext = new_test_ext(); + + // Proof size extension not registered + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 500 + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, None); + + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1000); + }) +} + +#[test] +fn negative_refund_is_added_to_weight() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 100 + let info = DispatchInfo { weight: Weight::from_parts(0, 100), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // We expect no refund + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1100); + }) +} + +#[test] +fn test_zero_proof_size() { + let mut test_ext = setup_test_externalities(&[0, 0]); + + test_ext.execute_with(|| { + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(0)); + + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 0); + }); +} + +#[test] +fn test_larger_pre_dispatch_proof_size() { + let mut test_ext = setup_test_externalities(&[300, 100]); + + test_ext.execute_with(|| { + set_current_storage_weight(1300); + + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(300)); + + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 800); + }); +} + +#[test] +fn test_incorporates_check_weight_unspent_weight() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 300 + let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; + + // Actual weight is 50 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 250)), + pays_fee: Default::default(), + }; + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 900); + }) +} + +#[test] +fn test_incorporates_check_weight_unspent_weight_on_negative() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 50 + let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; + + // Actual weight is 25 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 25)), + pays_fee: Default::default(), + }; + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1150); + }) +} + +#[test] +fn test_incorporates_check_weight_unspent_weight_reverse_order() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 300 + let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; + + // Actual weight is 50 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 250)), + pays_fee: Default::default(), + }; + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + // `CheckWeight` gets called after `StorageWeightReclaim` this time. + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + + assert_eq!(BlockWeight::::get().total().proof_size(), 900); + }) +} + +#[test] +fn test_incorporates_check_weight_unspent_weight_on_negative_reverse_order() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 50 + let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; + + // Actual weight is 25 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 25)), + pays_fee: Default::default(), + }; + + let (pre, _) = StorageWeightReclaim::(PhantomData) + .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + assert_ok!(StorageWeightReclaim::::post_dispatch( + pre, + &info, + &post_info, + LEN, + &Ok(()), + &() + )); + // `CheckWeight` gets called after `StorageWeightReclaim` this time. + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1150); + }) +} + +#[test] +fn storage_size_reported_correctly() { + let mut test_ext = setup_test_externalities(&[1000]); + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), Some(1000)); + }); + + let mut test_ext = new_test_ext(); + + let test_recorder = TestRecorder::new(&[0]); + + test_ext.register_extension(ProofSizeExt::new(test_recorder)); + + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), Some(0)); + }); +} + +#[test] +fn storage_size_disabled_reported_correctly() { + let mut test_ext = setup_test_externalities(&[PROOF_RECORDING_DISABLED as usize]); + + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), None); + }); +} + +#[test] +fn test_reclaim_helper() { + let mut test_ext = setup_test_externalities(&[1000, 1300, 1800]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 2000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + remaining_weight_meter.consume(Weight::from_parts(0, 500)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 200))); + + remaining_weight_meter.consume(Weight::from_parts(0, 800)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + assert_eq!(reclaimed, Some(Weight::from_parts(0, 300))); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1200)); + }); +} + +#[test] +fn test_reclaim_helper_does_not_reclaim_negative() { + // Benchmarked weight does not change at all + let mut test_ext = setup_test_externalities(&[1000, 1300]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1000)); + }); + + // Benchmarked weight increases less than storage proof consumes + let mut test_ext = setup_test_externalities(&[1000, 1300]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + remaining_weight_meter.consume(Weight::from_parts(0, 0)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); + }); +} + +/// Just here for doc purposes +fn get_benched_weight() -> Weight { + Weight::from_parts(0, 5) +} + +/// Just here for doc purposes +fn do_work() {} + +#[docify::export_content(simple_reclaimer_example)] +fn reclaim_with_weight_meter() { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(10, 10)); + + let benched_weight = get_benched_weight(); + + // It is important to instantiate the `StorageWeightReclaimer` before we consume the weight + // for a piece of work from the weight meter. + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + + if remaining_weight_meter.try_consume(benched_weight).is_ok() { + // Perform some work that takes has `benched_weight` storage weight. + do_work(); + + // Reclaimer will detect that we only consumed 2 bytes, so 3 bytes are reclaimed. + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + // We reclaimed 3 bytes of storage size! + assert_eq!(reclaimed, Some(Weight::from_parts(0, 3))); + assert_eq!(BlockWeight::::get().total().proof_size(), 10); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(10, 8)); + } +} + +#[test] +fn test_reclaim_helper_works_with_meter() { + // The node will report 12 - 10 = 2 consumed storage size between the calls. + let mut test_ext = setup_test_externalities(&[10, 12]); + + test_ext.execute_with(|| { + // Initial storage size is 10. + set_current_storage_weight(10); + reclaim_with_weight_meter(); + }); +} diff --git a/cumulus/test/client/Cargo.toml b/cumulus/test/client/Cargo.toml index 028733ce235..9dfa6ecb351 100644 --- a/cumulus/test/client/Cargo.toml +++ b/cumulus/test/client/Cargo.toml @@ -46,9 +46,11 @@ cumulus-primitives-storage-weight-reclaim = { path = "../../primitives/storage-w [features] runtime-benchmarks = [ "cumulus-primitives-core/runtime-benchmarks", + "cumulus-primitives-storage-weight-reclaim/runtime-benchmarks", "cumulus-test-service/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", "sc-service/runtime-benchmarks", diff --git a/cumulus/test/client/src/lib.rs b/cumulus/test/client/src/lib.rs index c46f4da7f67..9239ff0f23e 100644 --- a/cumulus/test/client/src/lib.rs +++ b/cumulus/test/client/src/lib.rs @@ -19,7 +19,7 @@ mod block_builder; use codec::{Decode, Encode}; use runtime::{ - Balance, Block, BlockHashCount, Runtime, RuntimeCall, Signature, SignedExtra, SignedPayload, + Balance, Block, BlockHashCount, Runtime, RuntimeCall, Signature, SignedPayload, TxExtension, UncheckedExtrinsic, VERSION, }; use sc_executor::HeapAllocStrategy; @@ -125,7 +125,7 @@ impl DefaultTestClientBuilderExt for TestClientBuilder { /// Create an unsigned extrinsic from a runtime call. pub fn generate_unsigned(function: impl Into) -> UncheckedExtrinsic { - UncheckedExtrinsic::new_unsigned(function.into()) + UncheckedExtrinsic::new_bare(function.into()) } /// Create a signed extrinsic from a runtime call and sign @@ -143,7 +143,7 @@ pub fn generate_extrinsic_with_pair( let period = BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; let tip = 0; - let extra: SignedExtra = ( + let tx_ext: TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckGenesis::::new(), @@ -152,13 +152,14 @@ pub fn generate_extrinsic_with_pair( frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::::new(), - ); + ) + .into(); let function = function.into(); let raw_payload = SignedPayload::from_raw( function.clone(), - extra.clone(), + tx_ext.clone(), ((), VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|e| origin.sign(e)); @@ -167,7 +168,7 @@ pub fn generate_extrinsic_with_pair( function, origin.public().into(), Signature::Sr25519(signature), - extra, + tx_ext, ) } diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index 5ccec8983e9..154948a24b4 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -246,6 +246,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; + type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } impl pallet_sudo::Config for Runtime { @@ -322,8 +323,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckGenesis, @@ -335,7 +336,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -346,7 +347,7 @@ pub type Executive = frame_executive::Executive< TestOnRuntimeUpgrade, >; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; pub struct TestOnRuntimeUpgrade; diff --git a/cumulus/test/service/Cargo.toml b/cumulus/test/service/Cargo.toml index 27273f4e0a8..39e8aeba433 100644 --- a/cumulus/test/service/Cargo.toml +++ b/cumulus/test/service/Cargo.toml @@ -104,10 +104,12 @@ substrate-test-utils = { path = "../../../substrate/test-utils" } runtime-benchmarks = [ "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-primitives-core/runtime-benchmarks", + "cumulus-primitives-storage-weight-reclaim/runtime-benchmarks", "cumulus-test-client/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-cli/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", diff --git a/cumulus/test/service/src/bench_utils.rs b/cumulus/test/service/src/bench_utils.rs index 4ace894b392..15128b23787 100644 --- a/cumulus/test/service/src/bench_utils.rs +++ b/cumulus/test/service/src/bench_utils.rs @@ -69,7 +69,7 @@ pub fn extrinsic_set_time(client: &TestClient) -> OpaqueExtrinsic { let timestamp = best_number as u64 * cumulus_test_runtime::MinimumPeriod::get(); cumulus_test_runtime::UncheckedExtrinsic { - signature: None, + preamble: sp_runtime::generic::Preamble::Bare, function: cumulus_test_runtime::RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: timestamp, }), @@ -102,7 +102,7 @@ pub fn extrinsic_set_validation_data( }; cumulus_test_runtime::UncheckedExtrinsic { - signature: None, + preamble: sp_runtime::generic::Preamble::Bare, function: cumulus_test_runtime::RuntimeCall::ParachainSystem( cumulus_pallet_parachain_system::Call::set_validation_data { data }, ), diff --git a/cumulus/test/service/src/lib.rs b/cumulus/test/service/src/lib.rs index 3554a383f21..f05dc5f180f 100644 --- a/cumulus/test/service/src/lib.rs +++ b/cumulus/test/service/src/lib.rs @@ -883,7 +883,7 @@ pub fn construct_extrinsic( .map(|c| c / 2) .unwrap_or(2) as u64; let tip = 0; - let extra: runtime::SignedExtra = ( + let tx_ext: runtime::TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckGenesis::::new(), @@ -895,10 +895,11 @@ pub fn construct_extrinsic( frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::::new(), - ); + ) + .into(); let raw_payload = runtime::SignedPayload::from_raw( function.clone(), - extra.clone(), + tx_ext.clone(), ((), runtime::VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|e| caller.sign(e)); @@ -906,7 +907,7 @@ pub fn construct_extrinsic( function, caller.public().into(), runtime::Signature::Sr25519(signature), - extra, + tx_ext, ) } diff --git a/docs/sdk/src/reference_docs/extrinsic_encoding.rs b/docs/sdk/src/reference_docs/extrinsic_encoding.rs index 8c8568a228f..be1af500038 100644 --- a/docs/sdk/src/reference_docs/extrinsic_encoding.rs +++ b/docs/sdk/src/reference_docs/extrinsic_encoding.rs @@ -56,7 +56,7 @@ //! version_and_signed, //! from_address, //! signature, -//! signed_extensions_extra, +//! transaction_extensions_extra, //! ) //! ``` //! @@ -90,31 +90,31 @@ //! The signature type used on the Polkadot relay chain is [`sp_runtime::MultiSignature`]; the //! variants there are the types of signature that can be provided. //! -//! ### signed_extensions_extra +//! ### transaction_extensions_extra //! //! This is the concatenation of the [SCALE encoded][frame::deps::codec] bytes representing each of -//! the [_signed extensions_][sp_runtime::traits::SignedExtension], and are configured by the -//! fourth generic parameter of [`sp_runtime::generic::UncheckedExtrinsic`]. Learn more about -//! signed extensions [here][crate::reference_docs::signed_extensions]. +//! the [_transaction extensions_][sp_runtime::traits::TransactionExtension], and are configured by +//! the fourth generic parameter of [`sp_runtime::generic::UncheckedExtrinsic`]. Learn more about +//! transaction extensions [here][crate::reference_docs::transaction_extensions]. //! -//! When it comes to constructing an extrinsic, each signed extension has two things that we are -//! interested in here: +//! When it comes to constructing an extrinsic, each transaction extension has two things that we +//! are interested in here: //! -//! - The actual SCALE encoding of the signed extension type itself; this is what will form our -//! `signed_extensions_extra` bytes. -//! - An `AdditionalSigned` type. This is SCALE encoded into the `signed_extensions_additional` data -//! of the _signed payload_ (see below). +//! - The actual SCALE encoding of the transaction extension type itself; this is what will form our +//! `transaction_extensions_extra` bytes. +//! - An `Implicit` type. This is SCALE encoded into the `transaction_extensions_implicit` data of +//! the _signed payload_ (see below). //! //! Either (or both) of these can encode to zero bytes. //! -//! Each chain configures the set of signed extensions that it uses in its runtime configuration. -//! At the time of writing, Polkadot configures them +//! Each chain configures the set of transaction extensions that it uses in its runtime +//! configuration. At the time of writing, Polkadot configures them //! [here](https://github.com/polkadot-fellows/runtimes/blob/1dc04eb954eadf8aadb5d83990b89662dbb5a074/relay/polkadot/src/lib.rs#L1432C25-L1432C25). -//! Some of the common signed extensions are defined -//! [here][frame::deps::frame_system#signed-extensions]. +//! Some of the common transaction extensions are defined +//! [here][frame::deps::frame_system#transaction-extensions]. //! -//! Information about exactly which signed extensions are present on a chain and in what order is -//! also a part of the metadata for the chain. For V15 metadata, it can be +//! Information about exactly which transaction extensions are present on a chain and in what order +//! is also a part of the metadata for the chain. For V15 metadata, it can be //! [found here][frame::deps::frame_support::__private::metadata::v15::ExtrinsicMetadata]. //! //! ## call_data @@ -163,8 +163,8 @@ //! ```text //! signed_payload = concat( //! call_data, -//! signed_extensions_extra, -//! signed_extensions_additional, +//! transaction_extensions_extra, +//! transaction_extensions_implicit, //! ) //! //! if length(signed_payload) > 256 { @@ -172,16 +172,16 @@ //! } //! ``` //! -//! The bytes representing `call_data` and `signed_extensions_extra` can be obtained as described -//! above. `signed_extensions_additional` is constructed by SCALE encoding the -//! ["additional signed" data][sp_runtime::traits::SignedExtension::AdditionalSigned] for each -//! signed extension that the chain is using, in order. +//! The bytes representing `call_data` and `transaction_extensions_extra` can be obtained as +//! descibed above. `transaction_extensions_implicit` is constructed by SCALE encoding the +//! ["implicit" data][sp_runtime::traits::TransactionExtensionBase::Implicit] for each +//! transaction extension that the chain is using, in order. //! //! Once we've concatenated those together, we hash the result if it's greater than 256 bytes in //! length using a Blake2 256bit hasher. //! //! The [`sp_runtime::generic::SignedPayload`] type takes care of assembling the correct payload -//! for us, given `call_data` and a tuple of signed extensions. +//! for us, given `call_data` and a tuple of transaction extensions. //! //! # Example Encoding //! @@ -192,11 +192,12 @@ #[docify::export] pub mod call_data { use parity_scale_codec::{Decode, Encode}; + use sp_runtime::{traits::Dispatchable, DispatchResultWithInfo}; // The outer enum composes calls within // different pallets together. We have two // pallets, "PalletA" and "PalletB". - #[derive(Encode, Decode)] + #[derive(Encode, Decode, Clone)] pub enum Call { #[codec(index = 0)] PalletA(PalletACall), @@ -207,23 +208,33 @@ pub mod call_data { // An inner enum represents the calls within // a specific pallet. "PalletA" has one call, // "Foo". - #[derive(Encode, Decode)] + #[derive(Encode, Decode, Clone)] pub enum PalletACall { #[codec(index = 0)] Foo(String), } - #[derive(Encode, Decode)] + #[derive(Encode, Decode, Clone)] pub enum PalletBCall { #[codec(index = 0)] Bar(String), } + + impl Dispatchable for Call { + type RuntimeOrigin = (); + type Config = (); + type Info = (); + type PostInfo = (); + fn dispatch(self, _origin: Self::RuntimeOrigin) -> DispatchResultWithInfo { + Ok(()) + } + } } #[docify::export] pub mod encoding_example { use super::call_data::{Call, PalletACall}; - use crate::reference_docs::signed_extensions::signed_extensions_example; + use crate::reference_docs::transaction_extensions::transaction_extensions_example; use parity_scale_codec::Encode; use sp_core::crypto::AccountId32; use sp_keyring::sr25519::Keyring; @@ -232,34 +243,40 @@ pub mod encoding_example { MultiAddress, MultiSignature, }; - // Define some signed extensions to use. We'll use a couple of examples - // from the signed extensions reference doc. - type SignedExtensions = - (signed_extensions_example::AddToPayload, signed_extensions_example::AddToSignaturePayload); + // Define some transaction extensions to use. We'll use a couple of examples + // from the transaction extensions reference doc. + type TransactionExtensions = ( + transaction_extensions_example::AddToPayload, + transaction_extensions_example::AddToSignaturePayload, + ); // We'll use `UncheckedExtrinsic` to encode our extrinsic for us. We set // the address and signature type to those used on Polkadot, use our custom - // `Call` type, and use our custom set of `SignedExtensions`. - type Extrinsic = - UncheckedExtrinsic, Call, MultiSignature, SignedExtensions>; + // `Call` type, and use our custom set of `TransactionExtensions`. + type Extrinsic = UncheckedExtrinsic< + MultiAddress, + Call, + MultiSignature, + TransactionExtensions, + >; pub fn encode_demo_extrinsic() -> Vec { // The "from" address will be our Alice dev account. let from_address = MultiAddress::::Id(Keyring::Alice.to_account_id()); - // We provide some values for our expected signed extensions. - let signed_extensions = ( - signed_extensions_example::AddToPayload(1), - signed_extensions_example::AddToSignaturePayload, + // We provide some values for our expected transaction extensions. + let transaction_extensions = ( + transaction_extensions_example::AddToPayload(1), + transaction_extensions_example::AddToSignaturePayload, ); // Construct our call data: let call_data = Call::PalletA(PalletACall::Foo("Hello".to_string())); // The signed payload. This takes care of encoding the call_data, - // signed_extensions_extra and signed_extensions_additional, and hashing + // transaction_extensions_extra and transaction_extensions_implicit, and hashing // the result if it's > 256 bytes: - let signed_payload = SignedPayload::new(&call_data, signed_extensions.clone()); + let signed_payload = SignedPayload::new(call_data.clone(), transaction_extensions.clone()); // Sign the signed payload with our Alice dev account's private key, // and wrap the signature into the expected type: @@ -269,7 +286,7 @@ pub mod encoding_example { }; // Now, we can build and encode our extrinsic: - let ext = Extrinsic::new_signed(call_data, from_address, signature, signed_extensions); + let ext = Extrinsic::new_signed(call_data, from_address, signature, transaction_extensions); let encoded_ext = ext.encode(); encoded_ext diff --git a/docs/sdk/src/reference_docs/frame_runtime_types.rs b/docs/sdk/src/reference_docs/frame_runtime_types.rs index b5838b79e51..883892729d1 100644 --- a/docs/sdk/src/reference_docs/frame_runtime_types.rs +++ b/docs/sdk/src/reference_docs/frame_runtime_types.rs @@ -130,7 +130,7 @@ //! * [`crate::reference_docs::frame_origin`] explores further details about the usage of //! `RuntimeOrigin`. //! * [`RuntimeCall`] is a particularly interesting composite enum as it dictates the encoding of an -//! extrinsic. See [`crate::reference_docs::signed_extensions`] for more information. +//! extrinsic. See [`crate::reference_docs::transaction_extensions`] for more information. //! * See the documentation of [`construct_runtime`]. //! * See the corresponding lecture in the [pba-book](https://polkadot-blockchain-academy.github.io/pba-book/frame/outer-enum/page.html). //! diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index 0bd204e4b6a..3fd815d2a15 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -39,9 +39,9 @@ pub mod runtime_vs_smart_contract; /// Learn about how extrinsics are encoded to be transmitted to a node and stored in blocks. pub mod extrinsic_encoding; -/// Learn about the signed extensions that form a part of extrinsics. +/// Learn about the transaction extensions that form a part of extrinsics. // TODO: @jsdw https://github.com/paritytech/polkadot-sdk-docs/issues/42 -pub mod signed_extensions; +pub mod transaction_extensions; /// Learn about *Origins*, a topic in FRAME that enables complex account abstractions to be built. pub mod frame_origin; diff --git a/docs/sdk/src/reference_docs/signed_extensions.rs b/docs/sdk/src/reference_docs/signed_extensions.rs deleted file mode 100644 index 28b1426536b..00000000000 --- a/docs/sdk/src/reference_docs/signed_extensions.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! Signed extensions are, briefly, a means for different chains to extend the "basic" extrinsic -//! format with custom data that can be checked by the runtime. -//! -//! # Example -//! -//! Defining a couple of very simple signed extensions looks like the following: -#![doc = docify::embed!("./src/reference_docs/signed_extensions.rs", signed_extensions_example)] - -#[docify::export] -pub mod signed_extensions_example { - use parity_scale_codec::{Decode, Encode}; - use scale_info::TypeInfo; - use sp_runtime::traits::SignedExtension; - - // This doesn't actually check anything, but simply allows - // some arbitrary `u32` to be added to the extrinsic payload - #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] - pub struct AddToPayload(pub u32); - - impl SignedExtension for AddToPayload { - const IDENTIFIER: &'static str = "AddToPayload"; - type AccountId = (); - type Call = (); - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed( - &self, - ) -> Result< - Self::AdditionalSigned, - sp_runtime::transaction_validity::TransactionValidityError, - > { - Ok(()) - } - - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, - _len: usize, - ) -> Result { - Ok(()) - } - } - - // This is the opposite; nothing will be added to the extrinsic payload, - // but the AdditionalSigned type (`1234u32`) will be added to the - // payload to be signed. - #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] - pub struct AddToSignaturePayload; - - impl SignedExtension for AddToSignaturePayload { - const IDENTIFIER: &'static str = "AddToSignaturePayload"; - type AccountId = (); - type Call = (); - type AdditionalSigned = u32; - type Pre = (); - - fn additional_signed( - &self, - ) -> Result< - Self::AdditionalSigned, - sp_runtime::transaction_validity::TransactionValidityError, - > { - Ok(1234) - } - - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, - _len: usize, - ) -> Result { - Ok(()) - } - } -} diff --git a/docs/sdk/src/reference_docs/transaction_extensions.rs b/docs/sdk/src/reference_docs/transaction_extensions.rs new file mode 100644 index 00000000000..4f96d665d9b --- /dev/null +++ b/docs/sdk/src/reference_docs/transaction_extensions.rs @@ -0,0 +1,57 @@ +//! Transaction extensions are, briefly, a means for different chains to extend the "basic" +//! extrinsic format with custom data that can be checked by the runtime. +//! +//! # Example +//! +//! Defining a couple of very simple transaction extensions looks like the following: +#![doc = docify::embed!("./src/reference_docs/transaction_extensions.rs", transaction_extensions_example)] + +#[docify::export] +pub mod transaction_extensions_example { + use parity_scale_codec::{Decode, Encode}; + use scale_info::TypeInfo; + use sp_runtime::{ + impl_tx_ext_default, + traits::{Dispatchable, TransactionExtension, TransactionExtensionBase}, + TransactionValidityError, + }; + + // This doesn't actually check anything, but simply allows + // some arbitrary `u32` to be added to the extrinsic payload + #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] + pub struct AddToPayload(pub u32); + + impl TransactionExtensionBase for AddToPayload { + const IDENTIFIER: &'static str = "AddToPayload"; + type Implicit = (); + } + + impl TransactionExtension for AddToPayload { + type Pre = (); + type Val = (); + + impl_tx_ext_default!(Call; (); validate prepare); + } + + // This is the opposite; nothing will be added to the extrinsic payload, + // but the Implicit type (`1234u32`) will be added to the + // payload to be signed. + #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] + pub struct AddToSignaturePayload; + + impl TransactionExtensionBase for AddToSignaturePayload { + const IDENTIFIER: &'static str = "AddToSignaturePayload"; + type Implicit = u32; + + fn implicit(&self) -> Result { + Ok(1234) + } + } + + impl TransactionExtension for AddToSignaturePayload { + type Pre = (); + type Val = (); + + impl_tx_ext_default!(Call; (); validate prepare); + } +} diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml index 734dcbdeb44..180de70ad6c 100644 --- a/polkadot/node/service/Cargo.toml +++ b/polkadot/node/service/Cargo.toml @@ -196,6 +196,7 @@ runtime-benchmarks = [ "pallet-babe/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", "pallet-staking/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", "polkadot-runtime-parachains/runtime-benchmarks", diff --git a/polkadot/node/service/src/benchmarking.rs b/polkadot/node/service/src/benchmarking.rs index 400daf1aee3..29acc5c3ca8 100644 --- a/polkadot/node/service/src/benchmarking.rs +++ b/polkadot/node/service/src/benchmarking.rs @@ -189,7 +189,7 @@ fn westend_sign_call( use sp_core::Pair; use westend_runtime as runtime; - let extra: runtime::SignedExtra = ( + let tx_ext: runtime::TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -201,11 +201,12 @@ fn westend_sign_call( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); + ) + .into(); let payload = runtime::SignedPayload::from_raw( call.clone(), - extra.clone(), + tx_ext.clone(), ( (), runtime::VERSION.spec_version, @@ -223,7 +224,7 @@ fn westend_sign_call( call, sp_runtime::AccountId32::from(acc.public()).into(), polkadot_core_primitives::Signature::Sr25519(signature.clone()), - extra, + tx_ext, ) .into() } @@ -241,7 +242,7 @@ fn rococo_sign_call( use rococo_runtime as runtime; use sp_core::Pair; - let extra: runtime::SignedExtra = ( + let tx_ext: runtime::TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -253,11 +254,12 @@ fn rococo_sign_call( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); + ) + .into(); let payload = runtime::SignedPayload::from_raw( call.clone(), - extra.clone(), + tx_ext.clone(), ( (), runtime::VERSION.spec_version, @@ -275,7 +277,7 @@ fn rococo_sign_call( call, sp_runtime::AccountId32::from(acc.public()).into(), polkadot_core_primitives::Signature::Sr25519(signature.clone()), - extra, + tx_ext, ) .into() } diff --git a/polkadot/node/test/service/Cargo.toml b/polkadot/node/test/service/Cargo.toml index e7892abcd87..02b227e6f34 100644 --- a/polkadot/node/test/service/Cargo.toml +++ b/polkadot/node/test/service/Cargo.toml @@ -71,6 +71,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-staking/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", "polkadot-runtime-common/runtime-benchmarks", diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs index ca904bae28d..1876595c7b4 100644 --- a/polkadot/node/test/service/src/lib.rs +++ b/polkadot/node/test/service/src/lib.rs @@ -32,7 +32,7 @@ use polkadot_service::{ Error, FullClient, IsParachainNode, NewFull, OverseerGen, PrometheusConfig, }; use polkadot_test_runtime::{ - ParasCall, ParasSudoWrapperCall, Runtime, SignedExtra, SignedPayload, SudoCall, + ParasCall, ParasSudoWrapperCall, Runtime, SignedPayload, SudoCall, TxExtension, UncheckedExtrinsic, VERSION, }; @@ -382,7 +382,7 @@ pub fn construct_extrinsic( let period = BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; let tip = 0; - let extra: SignedExtra = ( + let tx_ext: TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -391,10 +391,11 @@ pub fn construct_extrinsic( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ); + ) + .into(); let raw_payload = SignedPayload::from_raw( function.clone(), - extra.clone(), + tx_ext.clone(), ( (), VERSION.spec_version, @@ -411,7 +412,7 @@ pub fn construct_extrinsic( function.clone(), polkadot_test_runtime::Address::Id(caller.public().into()), polkadot_primitives::Signature::Sr25519(signature.clone()), - extra.clone(), + tx_ext.clone(), ) } diff --git a/polkadot/runtime/common/Cargo.toml b/polkadot/runtime/common/Cargo.toml index eae5d4fb2ef..c2205938295 100644 --- a/polkadot/runtime/common/Cargo.toml +++ b/polkadot/runtime/common/Cargo.toml @@ -132,6 +132,7 @@ runtime-benchmarks = [ "pallet-identity/runtime-benchmarks", "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", "primitives/runtime-benchmarks", diff --git a/polkadot/runtime/common/src/claims.rs b/polkadot/runtime/common/src/claims.rs index 68f42914e44..57a95b22af3 100644 --- a/polkadot/runtime/common/src/claims.rs +++ b/polkadot/runtime/common/src/claims.rs @@ -29,7 +29,11 @@ use scale_info::TypeInfo; use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; use sp_io::{crypto::secp256k1_ecdsa_recover, hashing::keccak_256}; use sp_runtime::{ - traits::{CheckedSub, DispatchInfoOf, SignedExtension, Zero}, + impl_tx_ext_default, + traits::{ + AsSystemOriginSigner, CheckedSub, DispatchInfoOf, Dispatchable, TransactionExtension, + TransactionExtensionBase, Zero, + }, transaction_validity::{ InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, }, @@ -50,6 +54,7 @@ pub trait WeightInfo { fn claim_attest() -> Weight; fn attest() -> Weight; fn move_claim() -> Weight; + fn prevalidate_attests() -> Weight; } pub struct TestWeightInfo; @@ -69,6 +74,9 @@ impl WeightInfo for TestWeightInfo { fn move_claim() -> Weight { Weight::zero() } + fn prevalidate_attests() -> Weight { + Weight::zero() + } } /// The kind of statement an account needs to make for a claim to be valid. @@ -84,7 +92,7 @@ pub enum StatementKind { impl StatementKind { /// Convert this to the (English) statement it represents. - fn to_text(self) -> &'static [u8] { + pub fn to_text(self) -> &'static [u8] { match self { StatementKind::Regular => &b"I hereby agree to the terms of the statement whose SHA-256 multihash is \ @@ -166,6 +174,13 @@ pub mod pallet { #[pallet::without_storage_info] pub struct Pallet(_); + #[cfg(feature = "runtime-benchmarks")] + /// Helper trait to benchmark the `PrevalidateAttests` transaction extension. + pub trait BenchmarkHelperTrait { + /// `Call` to be used when benchmarking the transaction extension. + fn default_call_and_info() -> (RuntimeCall, DispatchInfo); + } + /// Configuration trait. #[pallet::config] pub trait Config: frame_system::Config { @@ -176,6 +191,12 @@ pub mod pallet { type Prefix: Get<&'static [u8]>; type MoveClaimOrigin: EnsureOrigin; type WeightInfo: WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + /// Benchmark helper + type BenchmarkHelper: BenchmarkHelperTrait< + Self::RuntimeCall, + DispatchInfoOf, + >; } #[pallet::event] @@ -402,7 +423,7 @@ pub mod pallet { /// Attest to a statement, needed to finalize the claims process. /// /// WARNING: Insecure unless your chain includes `PrevalidateAttests` as a - /// `SignedExtension`. + /// `TransactionExtension`. /// /// Unsigned Validation: /// A call to attest is deemed valid if the sender has a `Preclaim` registered @@ -612,46 +633,46 @@ impl PrevalidateAttests where ::RuntimeCall: IsSubType>, { - /// Create new `SignedExtension` to check runtime version. + /// Create new `TransactionExtension` to check runtime version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl SignedExtension for PrevalidateAttests +impl TransactionExtensionBase for PrevalidateAttests where ::RuntimeCall: IsSubType>, { - type AccountId = T::AccountId; - type Call = ::RuntimeCall; - type AdditionalSigned = (); - type Pre = (); const IDENTIFIER: &'static str = "PrevalidateAttests"; + type Implicit = (); +} - fn additional_signed(&self) -> Result { - Ok(()) - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) - } +impl TransactionExtension for PrevalidateAttests +where + ::RuntimeCall: IsSubType>, + <::RuntimeCall as Dispatchable>::RuntimeOrigin: + AsSystemOriginSigner + Clone, +{ + type Pre = (); + type Val = (); // // The weight of this logic is included in the `attest` dispatchable. // fn validate( &self, - who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + call: &T::RuntimeCall, + _info: &DispatchInfoOf, _len: usize, - ) -> TransactionValidity { + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> Result< + (ValidTransaction, Self::Val, ::RuntimeOrigin), + TransactionValidityError, + > { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; if let Some(local_call) = call.is_sub_type() { if let Call::attest { statement: attested_statement } = local_call { let signer = Preclaims::::get(who) @@ -662,8 +683,9 @@ where } } } - Ok(ValidTransaction::default()) + Ok((ValidTransaction::default(), (), origin)) } + impl_tx_ext_default!(T::RuntimeCall; Context; prepare); } #[cfg(any(test, feature = "runtime-benchmarks"))] @@ -696,7 +718,7 @@ mod secp_utils { } #[cfg(test)] -mod tests { +pub(super) mod tests { use super::*; use hex_literal::hex; use secp_utils::*; @@ -714,8 +736,11 @@ mod tests { }; use pallet_balances; use sp_runtime::{ - traits::Identity, transaction_validity::TransactionLongevity, BuildStorage, - DispatchError::BadOrigin, TokenError, + traits::{DispatchTransaction, Identity}, + transaction_validity::TransactionLongevity, + BuildStorage, + DispatchError::BadOrigin, + TokenError, }; type Block = frame_system::mocking::MockBlock; @@ -790,6 +815,19 @@ mod tests { type Prefix = Prefix; type MoveClaimOrigin = frame_system::EnsureSignedBy; type WeightInfo = TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + } + + #[cfg(feature = "runtime-benchmarks")] + impl BenchmarkHelperTrait> for () { + fn default_call_and_info() -> (RuntimeCall, DispatchInfoOf) { + let call = RuntimeCall::Claims(crate::claims::Call::attest { + statement: StatementKind::Regular.to_text().to_vec(), + }); + let info = call.get_dispatch_info(); + (call, info) + } } fn alice() -> libsecp256k1::SecretKey { @@ -1071,8 +1109,8 @@ mod tests { }); let di = c.get_dispatch_info(); assert_eq!(di.pays_fee, Pays::No); - let r = p.validate(&42, &c, &di, 20); - assert_eq!(r, TransactionValidity::Ok(ValidTransaction::default())); + let r = p.validate_only(Some(42).into(), &c, &di, 20); + assert_eq!(r.unwrap().0, ValidTransaction::default()); }); } @@ -1084,13 +1122,13 @@ mod tests { statement: StatementKind::Regular.to_text().to_vec(), }); let di = c.get_dispatch_info(); - let r = p.validate(&42, &c, &di, 20); + let r = p.validate_only(Some(42).into(), &c, &di, 20); assert!(r.is_err()); let c = RuntimeCall::Claims(ClaimsCall::attest { statement: StatementKind::Saft.to_text().to_vec(), }); let di = c.get_dispatch_info(); - let r = p.validate(&69, &c, &di, 20); + let r = p.validate_only(Some(69).into(), &c, &di, 20); assert!(r.is_err()); }); } @@ -1444,14 +1482,17 @@ mod tests { } #[cfg(feature = "runtime-benchmarks")] -mod benchmarking { +pub(super) mod benchmarking { use super::*; use crate::claims::Call; use frame_benchmarking::{account, benchmarks}; use frame_support::traits::UnfilteredDispatchable; use frame_system::RawOrigin; use secp_utils::*; - use sp_runtime::{traits::ValidateUnsigned, DispatchResult}; + use sp_runtime::{ + traits::{DispatchTransaction, ValidateUnsigned}, + DispatchResult, + }; const SEED: u32 = 0; @@ -1487,6 +1528,11 @@ mod benchmarking { } benchmarks! { + where_clause { where ::RuntimeCall: IsSubType>, + <::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner + Clone, + <::RuntimeCall as Dispatchable>::PostInfo: Default, + } + // Benchmark `claim` including `validate_unsigned` logic. claim { let c = MAX_CLAIMS; @@ -1665,6 +1711,38 @@ mod benchmarking { } } + prevalidate_attests { + let c = MAX_CLAIMS; + + for i in 0 .. c / 2 { + create_claim::(c)?; + create_claim_attest::(u32::MAX - c)?; + } + + let ext = PrevalidateAttests::::new(); + let (call, info) = T::BenchmarkHelper::default_call_and_info(); + let attest_c = u32::MAX - c; + let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&attest_c.encode())).unwrap(); + let eth_address = eth(&secret_key); + let account: T::AccountId = account("user", c, SEED); + let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into())); + let statement = StatementKind::Regular; + let signature = sig::(&secret_key, &account.encode(), statement.to_text()); + super::Pallet::::mint_claim(RawOrigin::Root.into(), eth_address, VALUE.into(), vesting, Some(statement))?; + Preclaims::::insert(&account, eth_address); + assert_eq!(Claims::::get(eth_address), Some(VALUE.into())); + }: { + assert!(ext.test_run( + RawOrigin::Signed(account).into(), + &call, + &info, + 0, + |_| { + Ok(Default::default()) + } + ).unwrap().is_ok()); + } + impl_benchmark_test_suite!( Pallet, crate::claims::tests::new_test_ext(), diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index 3dc59cc1728..61ca1635ac9 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -246,6 +246,7 @@ runtime-benchmarks = [ "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-tips/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", diff --git a/polkadot/runtime/rococo/constants/src/weights/block_weights.rs b/polkadot/runtime/rococo/constants/src/weights/block_weights.rs index e2aa4a6cab7..f7dc2f19316 100644 --- a/polkadot/runtime/rococo/constants/src/weights/block_weights.rs +++ b/polkadot/runtime/rococo/constants/src/weights/block_weights.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26 (Y/M/D) -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29 (Y/M/D) +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! //! SHORT-NAME: `block`, LONG-NAME: `BlockExecution`, RUNTIME: `Development` //! WARMUPS: `10`, REPEAT: `100` -//! WEIGHT-PATH: `runtime/rococo/constants/src/weights/` +//! WEIGHT-PATH: `./polkadot/runtime/rococo/constants/src/weights/` //! WEIGHT-METRIC: `Average`, WEIGHT-MUL: `1.0`, WEIGHT-ADD: `0` // Executed Command: @@ -28,12 +28,11 @@ // benchmark // overhead // --chain=rococo-dev -// --execution=wasm // --wasm-execution=compiled -// --weight-path=runtime/rococo/constants/src/weights/ +// --weight-path=./polkadot/runtime/rococo/constants/src/weights/ // --warmup=10 // --repeat=100 -// --header=./file_header.txt +// --header=./polkadot/file_header.txt use sp_core::parameter_types; use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; @@ -43,17 +42,17 @@ parameter_types! { /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 408_659, 450_716 - /// Average: 417_412 - /// Median: 411_177 - /// Std-Dev: 12242.31 + /// Min, Max: 440_142, 476_907 + /// Average: 450_240 + /// Median: 448_633 + /// Std-Dev: 7301.18 /// /// Percentiles nanoseconds: - /// 99th: 445_142 - /// 95th: 442_275 - /// 75th: 414_217 + /// 99th: 470_733 + /// 95th: 465_082 + /// 75th: 452_536 pub const BlockExecutionWeight: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(417_412), 0); + Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(450_240), 0); } #[cfg(test)] diff --git a/polkadot/runtime/rococo/constants/src/weights/extrinsic_weights.rs b/polkadot/runtime/rococo/constants/src/weights/extrinsic_weights.rs index adce840ebbc..000cee8a237 100644 --- a/polkadot/runtime/rococo/constants/src/weights/extrinsic_weights.rs +++ b/polkadot/runtime/rococo/constants/src/weights/extrinsic_weights.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26 (Y/M/D) -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29 (Y/M/D) +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! //! SHORT-NAME: `extrinsic`, LONG-NAME: `ExtrinsicBase`, RUNTIME: `Development` //! WARMUPS: `10`, REPEAT: `100` -//! WEIGHT-PATH: `runtime/rococo/constants/src/weights/` +//! WEIGHT-PATH: `./polkadot/runtime/rococo/constants/src/weights/` //! WEIGHT-METRIC: `Average`, WEIGHT-MUL: `1.0`, WEIGHT-ADD: `0` // Executed Command: @@ -28,12 +28,11 @@ // benchmark // overhead // --chain=rococo-dev -// --execution=wasm // --wasm-execution=compiled -// --weight-path=runtime/rococo/constants/src/weights/ +// --weight-path=./polkadot/runtime/rococo/constants/src/weights/ // --warmup=10 // --repeat=100 -// --header=./file_header.txt +// --header=./polkadot/file_header.txt use sp_core::parameter_types; use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; @@ -43,17 +42,17 @@ parameter_types! { /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 97_574, 100_119 - /// Average: 98_236 - /// Median: 98_179 - /// Std-Dev: 394.9 + /// Min, Max: 92_961, 94_143 + /// Average: 93_369 + /// Median: 93_331 + /// Std-Dev: 217.39 /// /// Percentiles nanoseconds: - /// 99th: 99_893 - /// 95th: 98_850 - /// 75th: 98_318 + /// 99th: 93_848 + /// 95th: 93_691 + /// 75th: 93_514 pub const ExtrinsicBaseWeight: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(98_236), 0); + Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(93_369), 0); } #[cfg(test)] diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 96e8c4e0979..ff54c777670 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -199,6 +199,7 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type MaxConsumers = frame_support::traits::ConstU32<16>; } @@ -329,6 +330,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -591,7 +593,7 @@ where // so the actual block number is `n`. .saturating_sub(1); let tip = 0; - let extra: SignedExtra = ( + let tx_ext: TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -603,16 +605,17 @@ where frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ); - let raw_payload = SignedPayload::new(call, extra) + ) + .into(); + let raw_payload = SignedPayload::new(call, tx_ext) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; - let (call, extra, _) = raw_payload.deconstruct(); + let (call, tx_ext, _) = raw_payload.deconstruct(); let address = ::Lookup::unlookup(account); - Some((call, (address, signature, extra))) + Some((call, (address, signature, tx_ext))) } } @@ -633,12 +636,32 @@ parameter_types! { pub Prefix: &'static [u8] = b"Pay ROCs to the Rococo account:"; } +#[cfg(feature = "runtime-benchmarks")] +pub struct ClaimsHelper; + +#[cfg(feature = "runtime-benchmarks")] +use frame_support::dispatch::DispatchInfo; + +#[cfg(feature = "runtime-benchmarks")] +impl claims::BenchmarkHelperTrait for ClaimsHelper { + fn default_call_and_info() -> (RuntimeCall, DispatchInfo) { + use frame_support::dispatch::GetDispatchInfo; + let call = RuntimeCall::Claims(claims::Call::attest { + statement: claims::StatementKind::Regular.to_text().to_vec(), + }); + let info = call.get_dispatch_info(); + (call, info) + } +} + impl claims::Config for Runtime { type RuntimeEvent = RuntimeEvent; type VestingSchedule = Vesting; type Prefix = Prefix; type MoveClaimOrigin = EnsureRoot; type WeightInfo = weights::runtime_common_claims::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = ClaimsHelper; } parameter_types! { @@ -1447,8 +1470,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// `BlockId` type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The `SignedExtension` to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -1461,7 +1484,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// All migrations that will run on the next runtime upgrade. /// @@ -1675,7 +1698,7 @@ pub type Executive = frame_executive::Executive< Migrations, >; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; parameter_types! { // The deposit configuration for the singed migration. Specially if you want to allow any signed account to do the migration (see `SignedFilter`, these deposits should be high) @@ -1746,7 +1769,9 @@ mod benches { [pallet_scheduler, Scheduler] [pallet_sudo, Sudo] [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_timestamp, Timestamp] + [pallet_transaction_payment, TransactionPayment] [pallet_treasury, Treasury] [pallet_utility, Utility] [pallet_vesting, Vesting] @@ -2240,6 +2265,7 @@ sp_api::impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use frame_benchmarking::baseline::Pallet as Baseline; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -2260,6 +2286,7 @@ sp_api::impl_runtime_apis! { use frame_support::traits::WhitelistedStorageKeys; use frame_benchmarking::{Benchmarking, BenchmarkBatch, BenchmarkError}; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use frame_benchmarking::baseline::Pallet as Baseline; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use sp_storage::TrackedStorageKey; diff --git a/polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs b/polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs index dfba0cfc4aa..0f68a5c6fb3 100644 --- a/polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs +++ b/polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `frame_benchmarking::baseline` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=frame_benchmarking::baseline // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/frame_benchmarking_baseline.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -52,8 +55,8 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 157_000 picoseconds. - Weight::from_parts(175_233, 0) + // Minimum execution time: 172_000 picoseconds. + Weight::from_parts(199_481, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `i` is `[0, 1000000]`. @@ -61,8 +64,8 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 149_000 picoseconds. - Weight::from_parts(183_285, 0) + // Minimum execution time: 171_000 picoseconds. + Weight::from_parts(197_821, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `i` is `[0, 1000000]`. @@ -70,8 +73,8 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 158_000 picoseconds. - Weight::from_parts(184_720, 0) + // Minimum execution time: 172_000 picoseconds. + Weight::from_parts(200_942, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `i` is `[0, 1000000]`. @@ -79,16 +82,16 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 152_000 picoseconds. - Weight::from_parts(177_496, 0) + // Minimum execution time: 170_000 picoseconds. + Weight::from_parts(196_906, 0) .saturating_add(Weight::from_parts(0, 0)) } fn hashing() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 19_907_376_000 picoseconds. - Weight::from_parts(19_988_727_000, 0) + // Minimum execution time: 23_346_876_000 picoseconds. + Weight::from_parts(23_363_744_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `i` is `[0, 100]`. @@ -96,10 +99,10 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 198_000 picoseconds. - Weight::from_parts(228_000, 0) + // Minimum execution time: 201_000 picoseconds. + Weight::from_parts(219_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 20_467 - .saturating_add(Weight::from_parts(47_443_635, 0).saturating_mul(i.into())) + // Standard Error: 14_372 + .saturating_add(Weight::from_parts(45_375_800, 0).saturating_mul(i.into())) } } diff --git a/polkadot/runtime/rococo/src/weights/frame_system.rs b/polkadot/runtime/rococo/src/weights/frame_system.rs index 2e49483dcc6..1742a761ca7 100644 --- a/polkadot/runtime/rococo/src/weights/frame_system.rs +++ b/polkadot/runtime/rococo/src/weights/frame_system.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `frame_system` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=frame_system // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -52,91 +55,91 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_283_000 picoseconds. - Weight::from_parts(2_305_000, 0) + // Minimum execution time: 1_541_000 picoseconds. + Weight::from_parts(2_581_470, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(366, 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: 7_435_000 picoseconds. - Weight::from_parts(7_581_000, 0) + // Minimum execution time: 5_060_000 picoseconds. + Weight::from_parts(5_167_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1_408, 0).saturating_mul(b.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_696, 0).saturating_mul(b.into())) } - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a686561707061676573` (r:0 w:1) - /// Proof Skipped: unknown `0x3a686561707061676573` (r:0 w:1) + /// Storage: `System::Digest` (r:1 w:1) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) fn set_heap_pages() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 4_010_000 picoseconds. - Weight::from_parts(4_112_000, 0) + // Minimum execution time: 2_649_000 picoseconds. + Weight::from_parts(2_909_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a636f6465` (r:0 w:1) - /// Proof Skipped: unknown `0x3a636f6465` (r:0 w:1) + /// Storage: `System::Digest` (r:1 w:1) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) fn set_code() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 80_405_511_000 picoseconds. - Weight::from_parts(83_066_478_000, 0) + // Minimum execution time: 88_417_540_000 picoseconds. + Weight::from_parts(91_809_291_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_210_000 picoseconds. - Weight::from_parts(2_247_000, 0) + // Minimum execution time: 1_538_000 picoseconds. + Weight::from_parts(1_589_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2_058 - .saturating_add(Weight::from_parts(673_943, 0).saturating_mul(i.into())) + // Standard Error: 1_740 + .saturating_add(Weight::from_parts(730_941, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_125_000 picoseconds. - Weight::from_parts(2_154_000, 0) + // Minimum execution time: 1_567_000 picoseconds. + Weight::from_parts(1_750_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 816 - .saturating_add(Weight::from_parts(491_194, 0).saturating_mul(i.into())) + // Standard Error: 835 + .saturating_add(Weight::from_parts(543_218, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `129 + p * (69 ±0)` - // Estimated: `125 + p * (70 ±0)` - // Minimum execution time: 4_002_000 picoseconds. - Weight::from_parts(4_145_000, 0) - .saturating_add(Weight::from_parts(0, 125)) - // Standard Error: 1_108 - .saturating_add(Weight::from_parts(1_014_971, 0).saturating_mul(p.into())) + // Measured: `80 + p * (69 ±0)` + // Estimated: `83 + p * (70 ±0)` + // Minimum execution time: 3_412_000 picoseconds. + Weight::from_parts(3_448_000, 0) + .saturating_add(Weight::from_parts(0, 83)) + // Standard Error: 1_395 + .saturating_add(Weight::from_parts(1_142_347, 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())) @@ -147,8 +150,8 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 33_027_000 picoseconds. - Weight::from_parts(33_027_000, 0) + // Minimum execution time: 9_178_000 picoseconds. + Weight::from_parts(9_780_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -162,8 +165,8 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `22` // Estimated: `1518` - // Minimum execution time: 118_101_992_000 picoseconds. - Weight::from_parts(118_101_992_000, 0) + // Minimum execution time: 94_523_563_000 picoseconds. + Weight::from_parts(96_983_131_000, 0) .saturating_add(Weight::from_parts(0, 1518)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs b/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..40520591f53 --- /dev/null +++ b/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs @@ -0,0 +1,123 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot +// benchmark +// pallet +// --chain=rococo-dev +// --steps=50 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=frame_system_extensions +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ + +#![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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_262_000 picoseconds. + Weight::from_parts(3_497_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_416_000 picoseconds. + Weight::from_parts(5_690_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 471_000 picoseconds. + Weight::from_parts(552_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `101` + // Estimated: `3593` + // Minimum execution time: 4_847_000 picoseconds. + Weight::from_parts(5_091_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 388_000 picoseconds. + Weight::from_parts(421_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 378_000 picoseconds. + Weight::from_parts(440_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1489` + // Minimum execution time: 3_402_000 picoseconds. + Weight::from_parts(3_627_000, 0) + .saturating_add(Weight::from_parts(0, 1489)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/polkadot/runtime/rococo/src/weights/mod.rs b/polkadot/runtime/rococo/src/weights/mod.rs index 7328dca9393..128a3083a9c 100644 --- a/polkadot/runtime/rococo/src/weights/mod.rs +++ b/polkadot/runtime/rococo/src/weights/mod.rs @@ -16,6 +16,7 @@ //! A list of the different weight modules for our runtime. pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_asset_rate; pub mod pallet_balances_balances; pub mod pallet_balances_nis_counterpart_balances; @@ -36,6 +37,7 @@ pub mod pallet_scheduler; pub mod pallet_session; pub mod pallet_sudo; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_treasury; pub mod pallet_utility; pub mod pallet_vesting; diff --git a/polkadot/runtime/rococo/src/weights/pallet_asset_rate.rs b/polkadot/runtime/rococo/src/weights/pallet_asset_rate.rs index da2d1958cef..56b1e2cbc57 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_asset_rate.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_asset_rate.rs @@ -16,25 +16,28 @@ //! Autogenerated weights for `pallet_asset_rate` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-03, STEPS: `50`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `cob`, CPU: `` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/debug/polkadot +// ./target/production/polkadot // benchmark // pallet // --chain=rococo-dev // --steps=50 -// --repeat=2 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_asset_rate // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --output=./runtime/rococo/src/weights/ -// --header=./file_header.txt +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,39 +50,39 @@ use core::marker::PhantomData; /// Weight functions for `pallet_asset_rate`. pub struct WeightInfo(PhantomData); impl pallet_asset_rate::WeightInfo for WeightInfo { - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(1237), added: 3712, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `42` - // Estimated: `4702` - // Minimum execution time: 143_000_000 picoseconds. - Weight::from_parts(155_000_000, 0) - .saturating_add(Weight::from_parts(0, 4702)) + // Measured: `142` + // Estimated: `4703` + // Minimum execution time: 10_277_000 picoseconds. + Weight::from_parts(10_487_000, 0) + .saturating_add(Weight::from_parts(0, 4703)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(1237), added: 3712, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`) fn update() -> Weight { // Proof Size summary in bytes: - // Measured: `110` - // Estimated: `4702` - // Minimum execution time: 156_000_000 picoseconds. - Weight::from_parts(172_000_000, 0) - .saturating_add(Weight::from_parts(0, 4702)) + // Measured: `210` + // Estimated: `4703` + // Minimum execution time: 10_917_000 picoseconds. + Weight::from_parts(11_249_000, 0) + .saturating_add(Weight::from_parts(0, 4703)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(1237), added: 3712, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`) fn remove() -> Weight { // Proof Size summary in bytes: - // Measured: `110` - // Estimated: `4702` - // Minimum execution time: 150_000_000 picoseconds. - Weight::from_parts(160_000_000, 0) - .saturating_add(Weight::from_parts(0, 4702)) + // Measured: `210` + // Estimated: `4703` + // Minimum execution time: 11_332_000 picoseconds. + Weight::from_parts(11_866_000, 0) + .saturating_add(Weight::from_parts(0, 4703)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs b/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs index 1b0ae1eeece..3fa54f2c369 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs @@ -16,24 +16,26 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_balances // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_balances -// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -54,8 +56,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 44_127_000 picoseconds. - Weight::from_parts(45_099_000, 0) + // Minimum execution time: 45_336_000 picoseconds. + Weight::from_parts(46_189_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +68,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 34_265_000 picoseconds. - Weight::from_parts(35_083_000, 0) + // Minimum execution time: 34_880_000 picoseconds. + Weight::from_parts(35_770_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -78,8 +80,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 12_189_000 picoseconds. - Weight::from_parts(12_655_000, 0) + // Minimum execution time: 12_904_000 picoseconds. + Weight::from_parts(13_260_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +92,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_910_000 picoseconds. - Weight::from_parts(17_474_000, 0) + // Minimum execution time: 17_669_000 picoseconds. + Weight::from_parts(18_228_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -102,8 +104,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 45_212_000 picoseconds. - Weight::from_parts(46_320_000, 0) + // Minimum execution time: 46_492_000 picoseconds. + Weight::from_parts(47_639_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -114,8 +116,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 42_500_000 picoseconds. - Weight::from_parts(43_991_000, 0) + // Minimum execution time: 44_342_000 picoseconds. + Weight::from_parts(45_144_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -126,8 +128,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 15_197_000 picoseconds. - Weight::from_parts(15_749_000, 0) + // Minimum execution time: 15_260_000 picoseconds. + Weight::from_parts(15_775_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -140,11 +142,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_414_000 picoseconds. - Weight::from_parts(14_685_000, 0) + // Minimum execution time: 14_703_000 picoseconds. + Weight::from_parts(14_950_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 7_918 - .saturating_add(Weight::from_parts(13_095_420, 0).saturating_mul(u.into())) + // Standard Error: 7_665 + .saturating_add(Weight::from_parts(13_335_803, 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())) @@ -153,8 +155,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_239_000 picoseconds. - Weight::from_parts(5_617_000, 0) + // Minimum execution time: 5_506_000 picoseconds. + Weight::from_parts(5_753_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs b/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs index 6cca9b9320a..1852ba6c2c4 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs @@ -16,24 +16,26 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_balances // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_balances -// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -56,8 +58,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 41_978_000 picoseconds. - Weight::from_parts(42_989_000, 0) + // Minimum execution time: 42_443_000 picoseconds. + Weight::from_parts(43_250_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -70,8 +72,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 32_250_000 picoseconds. - Weight::from_parts(33_074_000, 0) + // Minimum execution time: 32_417_000 picoseconds. + Weight::from_parts(33_247_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -82,8 +84,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3577` - // Minimum execution time: 9_906_000 picoseconds. - Weight::from_parts(10_397_000, 0) + // Minimum execution time: 10_091_000 picoseconds. + Weight::from_parts(10_426_000, 0) .saturating_add(Weight::from_parts(0, 3577)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -96,8 +98,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `277` // Estimated: `3593` - // Minimum execution time: 16_298_000 picoseconds. - Weight::from_parts(17_115_000, 0) + // Minimum execution time: 16_546_000 picoseconds. + Weight::from_parts(17_259_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -110,8 +112,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `206` // Estimated: `6196` - // Minimum execution time: 43_283_000 picoseconds. - Weight::from_parts(44_033_000, 0) + // Minimum execution time: 44_322_000 picoseconds. + Weight::from_parts(45_319_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) @@ -124,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 40_564_000 picoseconds. - Weight::from_parts(41_597_000, 0) + // Minimum execution time: 40_852_000 picoseconds. + Weight::from_parts(42_205_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -138,8 +140,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `277` // Estimated: `3593` - // Minimum execution time: 15_018_000 picoseconds. - Weight::from_parts(15_532_000, 0) + // Minimum execution time: 15_050_000 picoseconds. + Weight::from_parts(15_813_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -154,11 +156,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (256 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_470_000 picoseconds. - Weight::from_parts(14_828_000, 0) + // Minimum execution time: 14_830_000 picoseconds. + Weight::from_parts(15_061_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 15_515 - .saturating_add(Weight::from_parts(14_505_553, 0).saturating_mul(u.into())) + // Standard Error: 16_072 + .saturating_add(Weight::from_parts(14_981_430, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -167,8 +169,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_277_000 picoseconds. - Weight::from_parts(5_628_000, 0) + // Minimum execution time: 5_344_000 picoseconds. + Weight::from_parts(5_735_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_bounties.rs b/polkadot/runtime/rococo/src/weights/pallet_bounties.rs index 38d3645316f..8f8be5f2386 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_bounties.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_bounties.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_bounties` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_bounties // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,118 +50,181 @@ use core::marker::PhantomData; /// Weight functions for `pallet_bounties`. pub struct WeightInfo(PhantomData); impl pallet_bounties::WeightInfo for WeightInfo { - /// Storage: Bounties BountyCount (r:1 w:1) - /// Proof: Bounties BountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(16400), added: 18875, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:0 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: `Bounties::BountyCount` (r:1 w:1) + /// Proof: `Bounties::BountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:0 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) /// The range of component `d` is `[0, 16384]`. fn propose_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `210` // Estimated: `3593` - // Minimum execution time: 28_907_000 picoseconds. - Weight::from_parts(31_356_074, 0) + // Minimum execution time: 21_772_000 picoseconds. + Weight::from_parts(22_861_341, 0) .saturating_add(Weight::from_parts(0, 3593)) - // Standard Error: 18 - .saturating_add(Weight::from_parts(606, 0).saturating_mul(d.into())) + // Standard Error: 3 + .saturating_add(Weight::from_parts(721, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn approve_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `302` + // Estimated: `3642` + // Minimum execution time: 11_218_000 picoseconds. + Weight::from_parts(11_796_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `322` + // Estimated: `3642` + // Minimum execution time: 10_959_000 picoseconds. + Weight::from_parts(11_658_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `498` + // Estimated: `3642` + // Minimum execution time: 37_419_000 picoseconds. + Weight::from_parts(38_362_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `494` + // Estimated: `3642` + // Minimum execution time: 27_328_000 picoseconds. + Weight::from_parts(27_661_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn award_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `400` + // Estimated: `3642` + // Minimum execution time: 16_067_000 picoseconds. + Weight::from_parts(16_865_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn claim_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `764` + // Estimated: `8799` + // Minimum execution time: 101_153_000 picoseconds. + Weight::from_parts(102_480_000, 0) + .saturating_add(Weight::from_parts(0, 8799)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:0) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(16400), added: 18875, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn close_bounty_proposed() -> Weight { // Proof Size summary in bytes: - // Measured: `482` + // Measured: `444` // Estimated: `3642` - // Minimum execution time: 46_020_000 picoseconds. - Weight::from_parts(46_711_000, 0) + // Minimum execution time: 38_838_000 picoseconds. + Weight::from_parts(39_549_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn close_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `680` + // Estimated: `6196` + // Minimum execution time: 68_592_000 picoseconds. + Weight::from_parts(70_727_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn extend_bounty_expiry() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `358` + // Estimated: `3642` + // Minimum execution time: 11_272_000 picoseconds. + Weight::from_parts(11_592_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Bounties BountyApprovals (r:1 w:1) - /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:100 w:100) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:200 w:200) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `b` is `[0, 100]`. - fn spend_funds(_b: u32, ) -> Weight { + fn spend_funds(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `1887` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(2_405_233, 0) + // Measured: `0 + b * (297 ±0)` + // Estimated: `1887 + b * (5206 ±0)` + // Minimum execution time: 2_844_000 picoseconds. + Weight::from_parts(2_900_000, 0) .saturating_add(Weight::from_parts(0, 1887)) + // Standard Error: 9_467 + .saturating_add(Weight::from_parts(32_326_595, 0).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(b.into()))) + .saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into())) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_child_bounties.rs b/polkadot/runtime/rococo/src/weights/pallet_child_bounties.rs index e8c798d45e7..47ae3a5c90d 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_child_bounties.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_child_bounties.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_child_bounties` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_child_bounties // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,69 +50,153 @@ use core::marker::PhantomData; /// Weight functions for `pallet_child_bounties`. pub struct WeightInfo(PhantomData); impl pallet_child_bounties::WeightInfo for WeightInfo { + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyCount` (r:1 w:1) + /// Proof: `ChildBounties::ChildBountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:0 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) /// The range of component `d` is `[0, 16384]`. - fn add_child_bounty(_d: u32, ) -> Weight { + fn add_child_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `540` + // Estimated: `6196` + // Minimum execution time: 57_964_000 picoseconds. + Weight::from_parts(59_559_565, 0) + .saturating_add(Weight::from_parts(0, 6196)) + // Standard Error: 11 + .saturating_add(Weight::from_parts(697, 0).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(6)) } + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `594` + // Estimated: `3642` + // Minimum execution time: 17_527_000 picoseconds. + Weight::from_parts(18_257_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `740` + // Estimated: `3642` + // Minimum execution time: 29_354_000 picoseconds. + Weight::from_parts(30_629_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `740` + // Estimated: `3642` + // Minimum execution time: 40_643_000 picoseconds. + Weight::from_parts(42_072_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) fn award_child_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `637` + // Estimated: `3642` + // Minimum execution time: 18_616_000 picoseconds. + Weight::from_parts(19_316_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn claim_child_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `576` + // Estimated: `8799` + // Minimum execution time: 96_376_000 picoseconds. + Weight::from_parts(98_476_000, 0) + .saturating_add(Weight::from_parts(0, 8799)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(6)) } + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn close_child_bounty_added() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `840` + // Estimated: `6196` + // Minimum execution time: 64_640_000 picoseconds. + Weight::from_parts(66_174_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(6)) } + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn close_child_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `1027` + // Estimated: `8799` + // Minimum execution time: 78_159_000 picoseconds. + Weight::from_parts(79_820_000, 0) + .saturating_add(Weight::from_parts(0, 8799)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(7)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_conviction_voting.rs b/polkadot/runtime/rococo/src/weights/pallet_conviction_voting.rs index ba505737f1b..5d92c158df4 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_conviction_voting.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_conviction_voting.rs @@ -16,17 +16,17 @@ //! Autogenerated weights for `pallet_conviction_voting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot // benchmark // pallet -// --chain=kusama-dev +// --chain=rococo-dev // --steps=50 // --repeat=20 // --no-storage-info @@ -36,8 +36,8 @@ // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/kusama/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,144 +50,152 @@ use core::marker::PhantomData; /// Weight functions for `pallet_conviction_voting`. pub struct WeightInfo(PhantomData); impl pallet_conviction_voting::WeightInfo for WeightInfo { - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(311), added: 2786, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(311), added: 2786, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `13445` + // Measured: `13407` // Estimated: `42428` - // Minimum execution time: 151_077_000 picoseconds. - Weight::from_parts(165_283_000, 0) + // Minimum execution time: 128_378_000 picoseconds. + Weight::from_parts(131_028_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(311), added: 2786, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(311), added: 2786, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `14166` + // Measured: `14128` // Estimated: `83866` - // Minimum execution time: 232_420_000 picoseconds. - Weight::from_parts(244_439_000, 0) + // Minimum execution time: 155_379_000 picoseconds. + Weight::from_parts(161_597_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn remove_vote() -> Weight { // Proof Size summary in bytes: // Measured: `13918` // Estimated: `83866` - // Minimum execution time: 205_017_000 picoseconds. - Weight::from_parts(216_594_000, 0) + // Minimum execution time: 130_885_000 picoseconds. + Weight::from_parts(138_080_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn remove_other_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `13004` + // Measured: `13005` // Estimated: `30706` - // Minimum execution time: 84_226_000 picoseconds. - Weight::from_parts(91_255_000, 0) + // Minimum execution time: 71_743_000 picoseconds. + Weight::from_parts(75_170_000, 0) .saturating_add(Weight::from_parts(0, 30706)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: ConvictionVoting VotingFor (r:2 w:2) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:512 w:512) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(311), added: 2786, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:512 w:512) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(311), added: 2786, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:50) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 512]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `29640 + r * (365 ±0)` + // Measured: `29602 + r * (365 ±0)` // Estimated: `83866 + r * (3411 ±0)` - // Minimum execution time: 78_708_000 picoseconds. - Weight::from_parts(2_053_488_615, 0) + // Minimum execution time: 58_504_000 picoseconds. + Weight::from_parts(814_301_018, 0) .saturating_add(Weight::from_parts(0, 83866)) - // Standard Error: 179_271 - .saturating_add(Weight::from_parts(47_806_482, 0).saturating_mul(r.into())) + // Standard Error: 59_961 + .saturating_add(Weight::from_parts(20_002_833, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes(45)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 3411).saturating_mul(r.into())) } - /// Storage: ConvictionVoting VotingFor (r:2 w:2) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:512 w:512) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:512 w:512) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:50) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 512]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `29555 + r * (365 ±0)` // Estimated: `83866 + r * (3411 ±0)` - // Minimum execution time: 45_232_000 picoseconds. - Weight::from_parts(2_045_021_014, 0) + // Minimum execution time: 34_970_000 picoseconds. + Weight::from_parts(771_155_804, 0) .saturating_add(Weight::from_parts(0, 83866)) - // Standard Error: 185_130 - .saturating_add(Weight::from_parts(47_896_011, 0).saturating_mul(r.into())) + // Standard Error: 57_795 + .saturating_add(Weight::from_parts(19_781_645, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(43)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 3411).saturating_mul(r.into())) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(311), added: 2786, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(311), added: 2786, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) fn unlock() -> Weight { // Proof Size summary in bytes: - // Measured: `12218` + // Measured: `12180` // Estimated: `30706` - // Minimum execution time: 116_446_000 picoseconds. - Weight::from_parts(124_043_000, 0) + // Minimum execution time: 89_648_000 picoseconds. + Weight::from_parts(97_144_000, 0) .saturating_add(Weight::from_parts(0, 30706)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_identity.rs b/polkadot/runtime/rococo/src/weights/pallet_identity.rs index b334e21ea03..6df16351f2c 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_identity.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_identity.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_identity` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_identity // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,290 +50,291 @@ use core::marker::PhantomData; /// Weight functions for `pallet_identity`. pub struct WeightInfo(PhantomData); impl pallet_identity::WeightInfo for WeightInfo { - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `32 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 12_290_000 picoseconds. - Weight::from_parts(12_664_362, 0) + // Minimum execution time: 7_673_000 picoseconds. + Weight::from_parts(8_351_866, 0) .saturating_add(Weight::from_parts(0, 2626)) - // Standard Error: 1_347 - .saturating_add(Weight::from_parts(88_179, 0).saturating_mul(r.into())) + // Standard Error: 1_302 + .saturating_add(Weight::from_parts(79_198, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn set_identity(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `442 + r * (5 ±0)` - // Estimated: `11003` - // Minimum execution time: 31_373_000 picoseconds. - Weight::from_parts(30_435_545, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 2_307 - .saturating_add(Weight::from_parts(92_753, 0).saturating_mul(r.into())) + // Measured: `6978 + r * (5 ±0)` + // Estimated: `11037` + // Minimum execution time: 111_646_000 picoseconds. + Weight::from_parts(113_254_991, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 6_611 + .saturating_add(Weight::from_parts(162_119, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:100 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:100 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `101` - // Estimated: `11003 + s * (2589 ±0)` - // Minimum execution time: 9_251_000 picoseconds. - Weight::from_parts(22_039_210, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 40_779 - .saturating_add(Weight::from_parts(2_898_525, 0).saturating_mul(s.into())) + // Estimated: `11037 + s * (2589 ±0)` + // Minimum execution time: 8_010_000 picoseconds. + Weight::from_parts(19_868_412, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 5_018 + .saturating_add(Weight::from_parts(3_115_007, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 2589).saturating_mul(s.into())) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `194 + p * (32 ±0)` - // Estimated: `11003` - // Minimum execution time: 9_329_000 picoseconds. - Weight::from_parts(24_055_061, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 3_428 - .saturating_add(Weight::from_parts(1_130_604, 0).saturating_mul(p.into())) + // Estimated: `11037` + // Minimum execution time: 8_111_000 picoseconds. + Weight::from_parts(19_482_392, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 3_156 + .saturating_add(Weight::from_parts(1_305_890, 0).saturating_mul(p.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(p.into()))) } - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. - fn clear_identity(_r: u32, s: u32, ) -> Weight { + fn clear_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `469 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 53_365_000 picoseconds. - Weight::from_parts(35_391_422, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 1_353 - .saturating_add(Weight::from_parts(1_074_019, 0).saturating_mul(s.into())) + // Measured: `7070 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11037` + // Minimum execution time: 54_107_000 picoseconds. + Weight::from_parts(56_347_715, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 10_944 + .saturating_add(Weight::from_parts(191_321, 0).saturating_mul(r.into())) + // Standard Error: 2_135 + .saturating_add(Weight::from_parts(1_295_872, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: Identity Registrars (r:1 w:0) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:0) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn request_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `367 + r * (57 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 32_509_000 picoseconds. - Weight::from_parts(31_745_585, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 2_214 - .saturating_add(Weight::from_parts(83_822, 0).saturating_mul(r.into())) - + // Measured: `6968 + r * (57 ±0)` + // Estimated: `11037` + // Minimum execution time: 75_780_000 picoseconds. + Weight::from_parts(76_869_773, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 5_456 + .saturating_add(Weight::from_parts(135_316, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn cancel_request(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `398 + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 29_609_000 picoseconds. - Weight::from_parts(28_572_602, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 2_528 - .saturating_add(Weight::from_parts(85_593, 0).saturating_mul(r.into())) + // Measured: `6999` + // Estimated: `11037` + // Minimum execution time: 75_769_000 picoseconds. + Weight::from_parts(76_805_143, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 3_598 + .saturating_add(Weight::from_parts(84_593, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_793_000 picoseconds. - Weight::from_parts(8_173_888, 0) + // Minimum execution time: 5_357_000 picoseconds. + Weight::from_parts(5_732_132, 0) .saturating_add(Weight::from_parts(0, 2626)) - // Standard Error: 1_569 - .saturating_add(Weight::from_parts(72_367, 0).saturating_mul(r.into())) + // Standard Error: 927 + .saturating_add(Weight::from_parts(70_832, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_708_000 picoseconds. - Weight::from_parts(8_091_149, 0) + // Minimum execution time: 5_484_000 picoseconds. + Weight::from_parts(5_892_704, 0) .saturating_add(Weight::from_parts(0, 2626)) - // Standard Error: 869 - .saturating_add(Weight::from_parts(87_993, 0).saturating_mul(r.into())) + // Standard Error: 947 + .saturating_add(Weight::from_parts(71_231, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_601_000 picoseconds. - Weight::from_parts(8_038_414, 0) + // Minimum execution time: 5_310_000 picoseconds. + Weight::from_parts(5_766_651, 0) .saturating_add(Weight::from_parts(0, 2626)) - // Standard Error: 1_041 - .saturating_add(Weight::from_parts(82_588, 0).saturating_mul(r.into())) + // Standard Error: 916 + .saturating_add(Weight::from_parts(74_776, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity Registrars (r:1 w:0) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:0) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn provide_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `445 + r * (57 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 23_114_000 picoseconds. - Weight::from_parts(22_076_548, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 2_881 - .saturating_add(Weight::from_parts(109_812, 0).saturating_mul(r.into())) + // Measured: `7046 + r * (57 ±0)` + // Estimated: `11037` + // Minimum execution time: 98_200_000 picoseconds. + Weight::from_parts(100_105_482, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 6_152 + .saturating_add(Weight::from_parts(58_906, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. fn kill_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `676 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 70_007_000 picoseconds. - Weight::from_parts(50_186_495, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 6_533 - .saturating_add(Weight::from_parts(15_486, 0).saturating_mul(r.into())) - // Standard Error: 1_275 - .saturating_add(Weight::from_parts(1_085_117, 0).saturating_mul(s.into())) + // Measured: `7277 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11037` + // Minimum execution time: 64_647_000 picoseconds. + Weight::from_parts(68_877_027, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 9_965 + .saturating_add(Weight::from_parts(135_044, 0).saturating_mul(r.into())) + // Standard Error: 1_944 + .saturating_add(Weight::from_parts(1_388_151, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `475 + s * (36 ±0)` - // Estimated: `11003` - // Minimum execution time: 28_453_000 picoseconds. - Weight::from_parts(33_165_934, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 1_217 - .saturating_add(Weight::from_parts(65_401, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 23_550_000 picoseconds. + Weight::from_parts(29_439_842, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 1_453 + .saturating_add(Weight::from_parts(96_324, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `591 + s * (3 ±0)` - // Estimated: `11003` - // Minimum execution time: 12_846_000 picoseconds. - Weight::from_parts(14_710_284, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 496 - .saturating_add(Weight::from_parts(19_539, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 13_704_000 picoseconds. + Weight::from_parts(15_241_441, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 498 + .saturating_add(Weight::from_parts(40_973, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `638 + s * (35 ±0)` - // Estimated: `11003` - // Minimum execution time: 32_183_000 picoseconds. - Weight::from_parts(35_296_731, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 854 - .saturating_add(Weight::from_parts(52_028, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 29_310_000 picoseconds. + Weight::from_parts(31_712_666, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 967 + .saturating_add(Weight::from_parts(81_250, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `704 + s * (37 ±0)` // Estimated: `6723` - // Minimum execution time: 24_941_000 picoseconds. - Weight::from_parts(27_433_059, 0) + // Minimum execution time: 22_906_000 picoseconds. + Weight::from_parts(24_638_729, 0) .saturating_add(Weight::from_parts(0, 6723)) - // Standard Error: 856 - .saturating_add(Weight::from_parts(57_463, 0).saturating_mul(s.into())) + // Standard Error: 645 + .saturating_add(Weight::from_parts(75_121, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -340,90 +344,93 @@ impl pallet_identity::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_873_000 picoseconds. - Weight::from_parts(13_873_000, 0) + // Minimum execution time: 6_056_000 picoseconds. + Weight::from_parts(6_349_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::UsernameAuthorities` (r:0 w:1) + /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn remove_username_authority() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 10_653_000 picoseconds. - Weight::from_parts(10_653_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `80` + // Estimated: `3517` + // Minimum execution time: 9_003_000 picoseconds. + Weight::from_parts(9_276_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Identity::PendingUsernames` (r:1 w:0) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_username_for() -> Weight { // Proof Size summary in bytes: // Measured: `80` // Estimated: `11037` - // Minimum execution time: 75_928_000 picoseconds. - Weight::from_parts(75_928_000, 0) + // Minimum execution time: 64_724_000 picoseconds. + Weight::from_parts(66_597_000, 0) .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:0 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) fn accept_username() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `115` // Estimated: `11037` - // Minimum execution time: 38_157_000 picoseconds. - Weight::from_parts(38_157_000, 0) + // Minimum execution time: 19_538_000 picoseconds. + Weight::from_parts(20_204_000, 0) .saturating_add(Weight::from_parts(0, 11037)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn remove_expired_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `106` - // Estimated: `3542` - // Minimum execution time: 46_821_000 picoseconds. - Weight::from_parts(46_821_000, 0) - .saturating_add(Weight::from_parts(0, 3542)) + // Measured: `115` + // Estimated: `3550` + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(19_354_000, 0) + .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:0) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_primary_username() -> Weight { // Proof Size summary in bytes: - // Measured: `247` + // Measured: `257` // Estimated: `11037` - // Minimum execution time: 22_515_000 picoseconds. - Weight::from_parts(22_515_000, 0) + // Minimum execution time: 15_298_000 picoseconds. + Weight::from_parts(15_760_000, 0) .saturating_add(Weight::from_parts(0, 11037)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:0) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn remove_dangling_username() -> Weight { // Proof Size summary in bytes: - // Measured: `126` + // Measured: `98` // Estimated: `11037` - // Minimum execution time: 15_997_000 picoseconds. - Weight::from_parts(15_997_000, 0) + // Minimum execution time: 10_829_000 picoseconds. + Weight::from_parts(11_113_000, 0) .saturating_add(Weight::from_parts(0, 11037)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_indices.rs b/polkadot/runtime/rococo/src/weights/pallet_indices.rs index 99ffd3210ed..434db97d4a7 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_indices.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_indices.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_indices` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_indices // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,66 +50,66 @@ use core::marker::PhantomData; /// Weight functions for `pallet_indices`. pub struct WeightInfo(PhantomData); impl pallet_indices::WeightInfo for WeightInfo { - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn claim() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `4` // Estimated: `3534` - // Minimum execution time: 25_107_000 picoseconds. - Weight::from_parts(25_655_000, 0) + // Minimum execution time: 18_092_000 picoseconds. + Weight::from_parts(18_533_000, 0) .saturating_add(Weight::from_parts(0, 3534)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `341` + // Measured: `203` // Estimated: `3593` - // Minimum execution time: 36_208_000 picoseconds. - Weight::from_parts(36_521_000, 0) + // Minimum execution time: 31_616_000 picoseconds. + Weight::from_parts(32_556_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn free() -> Weight { // Proof Size summary in bytes: - // Measured: `238` + // Measured: `100` // Estimated: `3534` - // Minimum execution time: 25_915_000 picoseconds. - Weight::from_parts(26_220_000, 0) + // Minimum execution time: 19_593_000 picoseconds. + Weight::from_parts(20_100_000, 0) .saturating_add(Weight::from_parts(0, 3534)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `341` + // Measured: `203` // Estimated: `3593` - // Minimum execution time: 28_232_000 picoseconds. - Weight::from_parts(28_845_000, 0) + // Minimum execution time: 21_429_000 picoseconds. + Weight::from_parts(22_146_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn freeze() -> Weight { // Proof Size summary in bytes: - // Measured: `238` + // Measured: `100` // Estimated: `3534` - // Minimum execution time: 27_282_000 picoseconds. - Weight::from_parts(27_754_000, 0) + // Minimum execution time: 20_425_000 picoseconds. + Weight::from_parts(21_023_000, 0) .saturating_add(Weight::from_parts(0, 3534)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_message_queue.rs b/polkadot/runtime/rococo/src/weights/pallet_message_queue.rs index e1e360d374a..6ebfcd060b6 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_message_queue.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_message_queue.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_message_queue` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_message_queue // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,150 +50,149 @@ use core::marker::PhantomData; /// Weight functions for `pallet_message_queue`. pub struct WeightInfo(PhantomData); impl pallet_message_queue::WeightInfo for WeightInfo { - /// Storage: MessageQueue ServiceHead (r:1 w:0) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(6), added: 501, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:0) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(6), added: 501, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) fn ready_ring_knit() -> Weight { // Proof Size summary in bytes: - // Measured: `248` + // Measured: `281` // Estimated: `6050` - // Minimum execution time: 12_106_000 picoseconds. - Weight::from_parts(12_387_000, 0) + // Minimum execution time: 12_830_000 picoseconds. + Weight::from_parts(13_476_000, 0) .saturating_add(Weight::from_parts(0, 6050)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(6), added: 501, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(6), added: 501, mode: `MaxEncodedLen`) fn ready_ring_unknit() -> Weight { // Proof Size summary in bytes: - // Measured: `248` + // Measured: `281` // Estimated: `6050` - // Minimum execution time: 11_227_000 picoseconds. - Weight::from_parts(11_616_000, 0) + // Minimum execution time: 11_583_000 picoseconds. + Weight::from_parts(11_902_000, 0) .saturating_add(Weight::from_parts(0, 6050)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) fn service_queue_base() -> Weight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3520` - // Minimum execution time: 5_052_000 picoseconds. - Weight::from_parts(5_216_000, 0) + // Minimum execution time: 3_801_000 picoseconds. + Weight::from_parts(3_943_000, 0) .saturating_add(Weight::from_parts(0, 3520)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) fn service_page_base_completion() -> Weight { // Proof Size summary in bytes: // Measured: `115` // Estimated: `36283` - // Minimum execution time: 6_522_000 picoseconds. - Weight::from_parts(6_794_000, 0) + // Minimum execution time: 5_517_000 picoseconds. + Weight::from_parts(5_861_000, 0) .saturating_add(Weight::from_parts(0, 36283)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) fn service_page_base_no_completion() -> Weight { // Proof Size summary in bytes: // Measured: `115` // Estimated: `36283` - // Minimum execution time: 6_918_000 picoseconds. - Weight::from_parts(7_083_000, 0) + // Minimum execution time: 5_870_000 picoseconds. + Weight::from_parts(6_028_000, 0) .saturating_add(Weight::from_parts(0, 36283)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `MessageQueue::BookStateFor` (r:0 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:0 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) fn service_page_item() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 28_445_000 picoseconds. - Weight::from_parts(28_659_000, 0) + // Minimum execution time: 80_681_000 picoseconds. + Weight::from_parts(81_818_000, 0) .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(6), added: 501, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:0) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(6), added: 501, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) fn bump_service_head() -> Weight { // Proof Size summary in bytes: - // Measured: `149` + // Measured: `220` // Estimated: `3520` - // Minimum execution time: 7_224_000 picoseconds. - Weight::from_parts(7_441_000, 0) + // Minimum execution time: 8_641_000 picoseconds. + Weight::from_parts(8_995_000, 0) .saturating_add(Weight::from_parts(0, 3520)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Proof Skipped: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Storage: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) - /// Proof Skipped: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Storage: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Proof: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) fn reap_page() -> Weight { // Proof Size summary in bytes: - // Measured: `33232` + // Measured: `32945` // Estimated: `36283` - // Minimum execution time: 45_211_000 picoseconds. - Weight::from_parts(45_505_000, 0) + // Minimum execution time: 38_473_000 picoseconds. + Weight::from_parts(39_831_000, 0) .saturating_add(Weight::from_parts(0, 36283)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Proof Skipped: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Storage: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) - /// Proof Skipped: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Storage: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Proof: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) fn execute_overweight_page_removed() -> Weight { // Proof Size summary in bytes: - // Measured: `33232` + // Measured: `32945` // Estimated: `36283` - // Minimum execution time: 52_346_000 picoseconds. - Weight::from_parts(52_745_000, 0) + // Minimum execution time: 48_717_000 picoseconds. + Weight::from_parts(49_724_000, 0) .saturating_add(Weight::from_parts(0, 36283)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Proof Skipped: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Storage: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) - /// Proof Skipped: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Storage: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Proof: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) fn execute_overweight_page_updated() -> Weight { // Proof Size summary in bytes: - // Measured: `33232` + // Measured: `32945` // Estimated: `36283` - // Minimum execution time: 72_567_000 picoseconds. - Weight::from_parts(73_300_000, 0) + // Minimum execution time: 72_718_000 picoseconds. + Weight::from_parts(74_081_000, 0) .saturating_add(Weight::from_parts(0, 36283)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_multisig.rs b/polkadot/runtime/rococo/src/weights/pallet_multisig.rs index a4f33fe198c..f1b81759ece 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_multisig.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_multisig.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_multisig // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -52,110 +55,110 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_475_000 picoseconds. - Weight::from_parts(11_904_745, 0) + // Minimum execution time: 12_023_000 picoseconds. + Weight::from_parts(12_643_116, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(492, 0).saturating_mul(z.into())) + // Standard Error: 3 + .saturating_add(Weight::from_parts(582, 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) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `193 + s * (2 ±0)` + // Measured: `229 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 38_857_000 picoseconds. - Weight::from_parts(33_611_791, 0) + // Minimum execution time: 39_339_000 picoseconds. + Weight::from_parts(27_243_033, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 400 - .saturating_add(Weight::from_parts(59_263, 0).saturating_mul(s.into())) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_211, 0).saturating_mul(z.into())) + // Standard Error: 1_319 + .saturating_add(Weight::from_parts(142_212, 0).saturating_mul(s.into())) + // Standard Error: 12 + .saturating_add(Weight::from_parts(1_592, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `248` // Estimated: `6811` - // Minimum execution time: 25_715_000 picoseconds. - Weight::from_parts(20_607_294, 0) + // Minimum execution time: 27_647_000 picoseconds. + Weight::from_parts(15_828_725, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 285 - .saturating_add(Weight::from_parts(58_225, 0).saturating_mul(s.into())) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_160, 0).saturating_mul(z.into())) + // Standard Error: 908 + .saturating_add(Weight::from_parts(130_880, 0).saturating_mul(s.into())) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_532, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `317 + s * (33 ±0)` + // Measured: `354 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 43_751_000 picoseconds. - Weight::from_parts(37_398_513, 0) + // Minimum execution time: 46_971_000 picoseconds. + Weight::from_parts(32_150_393, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 426 - .saturating_add(Weight::from_parts(70_904, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_235, 0).saturating_mul(z.into())) + // Standard Error: 1_129 + .saturating_add(Weight::from_parts(154_796, 0).saturating_mul(s.into())) + // Standard Error: 11 + .saturating_add(Weight::from_parts(1_603, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `193 + s * (2 ±0)` + // Measured: `229 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 31_278_000 picoseconds. - Weight::from_parts(32_075_573, 0) + // Minimum execution time: 24_947_000 picoseconds. + Weight::from_parts(26_497_183, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 452 - .saturating_add(Weight::from_parts(62_018, 0).saturating_mul(s.into())) + // Standard Error: 1_615 + .saturating_add(Weight::from_parts(147_071, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `248` // Estimated: `6811` - // Minimum execution time: 18_178_000 picoseconds. - Weight::from_parts(18_649_867, 0) + // Minimum execution time: 13_897_000 picoseconds. + Weight::from_parts(14_828_339, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 293 - .saturating_add(Weight::from_parts(56_475, 0).saturating_mul(s.into())) + // Standard Error: 1_136 + .saturating_add(Weight::from_parts(133_925, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `383 + s * (1 ±0)` + // Measured: `420 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 32_265_000 picoseconds. - Weight::from_parts(32_984_014, 0) + // Minimum execution time: 28_984_000 picoseconds. + Weight::from_parts(29_853_232, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 452 - .saturating_add(Weight::from_parts(59_934, 0).saturating_mul(s.into())) + // Standard Error: 650 + .saturating_add(Weight::from_parts(113_440, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_nis.rs b/polkadot/runtime/rococo/src/weights/pallet_nis.rs index 35dad482129..38b41f3a8e2 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_nis.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_nis.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_nis` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_nis // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,202 +50,186 @@ use core::marker::PhantomData; /// Weight functions for `pallet_nis`. pub struct WeightInfo(PhantomData); impl pallet_nis::WeightInfo for WeightInfo { - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 999]`. fn place_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6209 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 44_704_000 picoseconds. - Weight::from_parts(44_933_886, 0) + // Minimum execution time: 39_592_000 picoseconds. + Weight::from_parts(38_234_037, 0) .saturating_add(Weight::from_parts(0, 51487)) - // Standard Error: 712 - .saturating_add(Weight::from_parts(71_570, 0).saturating_mul(l.into())) + // Standard Error: 1_237 + .saturating_add(Weight::from_parts(88_816, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) fn place_bid_max() -> Weight { // Proof Size summary in bytes: // Measured: `54211` // Estimated: `51487` - // Minimum execution time: 126_544_000 picoseconds. - Weight::from_parts(128_271_000, 0) + // Minimum execution time: 134_847_000 picoseconds. + Weight::from_parts(139_510_000, 0) .saturating_add(Weight::from_parts(0, 51487)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) /// The range of component `l` is `[1, 1000]`. fn retract_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6209 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 47_640_000 picoseconds. - Weight::from_parts(42_214_261, 0) + // Minimum execution time: 43_330_000 picoseconds. + Weight::from_parts(35_097_881, 0) .saturating_add(Weight::from_parts(0, 51487)) - // Standard Error: 732 - .saturating_add(Weight::from_parts(87_277, 0).saturating_mul(l.into())) + // Standard Error: 1_119 + .saturating_add(Weight::from_parts(73_640, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Nis Summary (r:1 w:0) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: Balances InactiveIssuance (r:1 w:0) - /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Nis::Summary` (r:1 w:0) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn fund_deficit() -> Weight { // Proof Size summary in bytes: // Measured: `225` // Estimated: `3593` - // Minimum execution time: 38_031_000 picoseconds. - Weight::from_parts(38_441_000, 0) + // Minimum execution time: 29_989_000 picoseconds. + Weight::from_parts(30_865_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) - /// Proof: NisCounterpartBalances TotalIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: NisCounterpartBalances Account (r:1 w:1) - /// Proof: NisCounterpartBalances Account (max_values: None, max_size: Some(112), added: 2587, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `NisCounterpartBalances::Account` (r:1 w:1) + /// Proof: `NisCounterpartBalances::Account` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`) fn communify() -> Weight { // Proof Size summary in bytes: - // Measured: `469` + // Measured: `387` // Estimated: `3593` - // Minimum execution time: 69_269_000 picoseconds. - Weight::from_parts(70_000_000, 0) + // Minimum execution time: 58_114_000 picoseconds. + Weight::from_parts(59_540_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: Balances InactiveIssuance (r:1 w:0) - /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: NisCounterpartBalances Account (r:1 w:1) - /// Proof: NisCounterpartBalances Account (max_values: None, max_size: Some(112), added: 2587, mode: MaxEncodedLen) - /// Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) - /// Proof: NisCounterpartBalances TotalIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NisCounterpartBalances::Account` (r:1 w:1) + /// Proof: `NisCounterpartBalances::Account` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) fn privatize() -> Weight { // Proof Size summary in bytes: - // Measured: `659` + // Measured: `543` // Estimated: `3593` - // Minimum execution time: 85_763_000 picoseconds. - Weight::from_parts(86_707_000, 0) + // Minimum execution time: 75_780_000 picoseconds. + Weight::from_parts(77_097_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: Balances InactiveIssuance (r:1 w:0) - /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) fn thaw_private() -> Weight { // Proof Size summary in bytes: // Measured: `387` // Estimated: `3593` - // Minimum execution time: 47_336_000 picoseconds. - Weight::from_parts(47_623_000, 0) + // Minimum execution time: 46_133_000 picoseconds. + Weight::from_parts(47_250_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: NisCounterpartBalances Account (r:1 w:1) - /// Proof: NisCounterpartBalances Account (max_values: None, max_size: Some(112), added: 2587, mode: MaxEncodedLen) - /// Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) - /// Proof: NisCounterpartBalances TotalIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Balances InactiveIssuance (r:1 w:0) - /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `NisCounterpartBalances::Account` (r:1 w:1) + /// Proof: `NisCounterpartBalances::Account` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn thaw_communal() -> Weight { // Proof Size summary in bytes: - // Measured: `604` + // Measured: `488` // Estimated: `3593` - // Minimum execution time: 90_972_000 picoseconds. - Weight::from_parts(92_074_000, 0) + // Minimum execution time: 77_916_000 picoseconds. + Weight::from_parts(79_427_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: Balances InactiveIssuance (r:1 w:0) - /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) fn process_queues() -> Weight { // Proof Size summary in bytes: // Measured: `6658` // Estimated: `7487` - // Minimum execution time: 21_469_000 picoseconds. - Weight::from_parts(21_983_000, 0) + // Minimum execution time: 22_992_000 picoseconds. + Weight::from_parts(24_112_000, 0) .saturating_add(Weight::from_parts(0, 7487)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) fn process_queue() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `51487` - // Minimum execution time: 4_912_000 picoseconds. - Weight::from_parts(5_013_000, 0) + // Minimum execution time: 3_856_000 picoseconds. + Weight::from_parts(4_125_000, 0) .saturating_add(Weight::from_parts(0, 51487)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Nis Receipts (r:0 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:0 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) fn process_bid() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_048_000 picoseconds. - Weight::from_parts(7_278_000, 0) + // Minimum execution time: 4_344_000 picoseconds. + Weight::from_parts(4_545_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_preimage.rs b/polkadot/runtime/rococo/src/weights/pallet_preimage.rs index e051ebd5bba..7a2b77b84d8 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_preimage.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_preimage.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_preimage` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_preimage // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,184 +50,219 @@ use core::marker::PhantomData; /// Weight functions for `pallet_preimage`. pub struct WeightInfo(PhantomData); impl pallet_preimage::WeightInfo for WeightInfo { - fn ensure_updated(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `193 + n * (91 ±0)` - // Estimated: `3593 + n * (2566 ±0)` - // Minimum execution time: 2_000_000 picoseconds. - Weight::from_parts(2_000_000, 3593) - // Standard Error: 13_720 - .saturating_add(Weight::from_parts(17_309_199, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2566).saturating_mul(n.into())) - } - - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Preimage PreimageFor (r:0 w:1) - /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `Preimage::PreimageFor` (r:0 w:1) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `215` - // Estimated: `3556` - // Minimum execution time: 31_040_000 picoseconds. - Weight::from_parts(31_236_000, 0) - .saturating_add(Weight::from_parts(0, 3556)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_974, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `114` + // Estimated: `3568` + // Minimum execution time: 40_363_000 picoseconds. + Weight::from_parts(41_052_000, 0) + .saturating_add(Weight::from_parts(0, 3568)) + // Standard Error: 6 + .saturating_add(Weight::from_parts(2_298, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Preimage PreimageFor (r:0 w:1) - /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::PreimageFor` (r:0 w:1) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 18_025_000 picoseconds. - Weight::from_parts(18_264_000, 0) + // Minimum execution time: 14_570_000 picoseconds. + Weight::from_parts(14_890_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_974, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) + // Standard Error: 2 + .saturating_add(Weight::from_parts(2_364, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Preimage PreimageFor (r:0 w:1) - /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::PreimageFor` (r:0 w:1) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 17_122_000 picoseconds. - Weight::from_parts(17_332_000, 0) + // Minimum execution time: 13_933_000 picoseconds. + Weight::from_parts(14_290_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_968, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) + // Standard Error: 2 + .saturating_add(Weight::from_parts(2_349, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Preimage PreimageFor (r:0 w:1) - /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `Preimage::PreimageFor` (r:0 w:1) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `361` - // Estimated: `3556` - // Minimum execution time: 38_218_000 picoseconds. - Weight::from_parts(39_841_000, 0) - .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `315` + // Estimated: `3568` + // Minimum execution time: 54_373_000 picoseconds. + Weight::from_parts(58_205_000, 0) + .saturating_add(Weight::from_parts(0, 3568)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Preimage PreimageFor (r:0 w:1) - /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::PreimageFor` (r:0 w:1) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3556` - // Minimum execution time: 23_217_000 picoseconds. - Weight::from_parts(24_246_000, 0) + // Minimum execution time: 24_267_000 picoseconds. + Weight::from_parts(27_063_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `260` // Estimated: `3556` - // Minimum execution time: 21_032_000 picoseconds. - Weight::from_parts(21_844_000, 0) + // Minimum execution time: 25_569_000 picoseconds. + Weight::from_parts(27_895_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3556` - // Minimum execution time: 13_954_000 picoseconds. - Weight::from_parts(14_501_000, 0) + // Minimum execution time: 14_182_000 picoseconds. + Weight::from_parts(16_098_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_unnoted_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `114` // Estimated: `3556` - // Minimum execution time: 14_874_000 picoseconds. - Weight::from_parts(15_380_000, 0) + // Minimum execution time: 14_681_000 picoseconds. + Weight::from_parts(15_549_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_requested_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 10_199_000 picoseconds. - Weight::from_parts(10_493_000, 0) + // Minimum execution time: 9_577_000 picoseconds. + Weight::from_parts(10_146_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Preimage PreimageFor (r:0 w:1) - /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::PreimageFor` (r:0 w:1) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unrequest_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3556` - // Minimum execution time: 21_772_000 picoseconds. - Weight::from_parts(22_554_000, 0) + // Minimum execution time: 21_003_000 picoseconds. + Weight::from_parts(23_549_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn unrequest_unnoted_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 10_115_000 picoseconds. - Weight::from_parts(10_452_000, 0) + // Minimum execution time: 9_507_000 picoseconds. + Weight::from_parts(10_013_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn unrequest_multi_referenced_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 10_031_000 picoseconds. - Weight::from_parts(10_310_000, 0) + // Minimum execution time: 9_293_000 picoseconds. + Weight::from_parts(10_055_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `Preimage::StatusFor` (r:1023 w:1023) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1023 w:1023) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1023 w:1023) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:0 w:1023) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1024]`. + fn ensure_updated(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + n * (227 ±0)` + // Estimated: `990 + n * (2603 ±0)` + // Minimum execution time: 48_846_000 picoseconds. + Weight::from_parts(49_378_000, 0) + .saturating_add(Weight::from_parts(0, 990)) + // Standard Error: 38_493 + .saturating_add(Weight::from_parts(47_418_285, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2603).saturating_mul(n.into())) + } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_proxy.rs b/polkadot/runtime/rococo/src/weights/pallet_proxy.rs index d9737a85c05..c9202593095 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_proxy.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_proxy.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_proxy` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_proxy // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,172 +50,176 @@ use core::marker::PhantomData; /// Weight functions for `pallet_proxy`. pub struct WeightInfo(PhantomData); impl pallet_proxy::WeightInfo for WeightInfo { - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `227 + p * (37 ±0)` + // Measured: `89 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 15_956_000 picoseconds. - Weight::from_parts(16_300_358, 0) + // Minimum execution time: 11_267_000 picoseconds. + Weight::from_parts(11_798_007, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 652 - .saturating_add(Weight::from_parts(30_807, 0).saturating_mul(p.into())) + // Standard Error: 858 + .saturating_add(Weight::from_parts(43_735, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) } - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `554 + a * (68 ±0) + p * (37 ±0)` + // Measured: `416 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 37_584_000 picoseconds. - Weight::from_parts(37_858_207, 0) + // Minimum execution time: 32_791_000 picoseconds. + Weight::from_parts(32_776_904, 0) .saturating_add(Weight::from_parts(0, 5698)) - // Standard Error: 1_868 - .saturating_add(Weight::from_parts(148_967, 0).saturating_mul(a.into())) - // Standard Error: 1_930 - .saturating_add(Weight::from_parts(13_017, 0).saturating_mul(p.into())) + // Standard Error: 2_382 + .saturating_add(Weight::from_parts(143_857, 0).saturating_mul(a.into())) + // Standard Error: 2_461 + .saturating_add(Weight::from_parts(40_024, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. - fn remove_announcement(a: u32, _p: u32, ) -> Weight { + fn remove_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `469 + a * (68 ±0)` + // Measured: `331 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 24_642_000 picoseconds. - Weight::from_parts(25_526_588, 0) + // Minimum execution time: 21_831_000 picoseconds. + Weight::from_parts(22_479_938, 0) .saturating_add(Weight::from_parts(0, 5698)) - // Standard Error: 1_138 - .saturating_add(Weight::from_parts(131_157, 0).saturating_mul(a.into())) + // Standard Error: 1_738 + .saturating_add(Weight::from_parts(146_532, 0).saturating_mul(a.into())) + // Standard Error: 1_796 + .saturating_add(Weight::from_parts(7_499, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. - fn reject_announcement(a: u32, _p: u32, ) -> Weight { + fn reject_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `469 + a * (68 ±0)` + // Measured: `331 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 24_377_000 picoseconds. - Weight::from_parts(25_464_033, 0) + // Minimum execution time: 21_776_000 picoseconds. + Weight::from_parts(22_762_843, 0) .saturating_add(Weight::from_parts(0, 5698)) - // Standard Error: 1_116 - .saturating_add(Weight::from_parts(130_722, 0).saturating_mul(a.into())) + // Standard Error: 1_402 + .saturating_add(Weight::from_parts(137_512, 0).saturating_mul(a.into())) + // Standard Error: 1_449 + .saturating_add(Weight::from_parts(3_645, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `486 + a * (68 ±0) + p * (37 ±0)` + // Measured: `348 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 34_202_000 picoseconds. - Weight::from_parts(34_610_079, 0) + // Minimum execution time: 29_108_000 picoseconds. + Weight::from_parts(29_508_910, 0) .saturating_add(Weight::from_parts(0, 5698)) - // Standard Error: 1_234 - .saturating_add(Weight::from_parts(134_197, 0).saturating_mul(a.into())) - // Standard Error: 1_275 - .saturating_add(Weight::from_parts(15_970, 0).saturating_mul(p.into())) + // Standard Error: 2_268 + .saturating_add(Weight::from_parts(144_770, 0).saturating_mul(a.into())) + // Standard Error: 2_343 + .saturating_add(Weight::from_parts(25_851, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `227 + p * (37 ±0)` + // Measured: `89 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 25_492_000 picoseconds. - Weight::from_parts(25_984_867, 0) + // Minimum execution time: 18_942_000 picoseconds. + Weight::from_parts(19_518_812, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 893 - .saturating_add(Weight::from_parts(51_868, 0).saturating_mul(p.into())) + // Standard Error: 1_078 + .saturating_add(Weight::from_parts(46_147, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `227 + p * (37 ±0)` + // Measured: `89 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 25_492_000 picoseconds. - Weight::from_parts(26_283_445, 0) + // Minimum execution time: 18_993_000 picoseconds. + Weight::from_parts(19_871_741, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 1_442 - .saturating_add(Weight::from_parts(53_504, 0).saturating_mul(p.into())) + // Standard Error: 1_883 + .saturating_add(Weight::from_parts(46_033, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `227 + p * (37 ±0)` + // Measured: `89 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 22_083_000 picoseconds. - Weight::from_parts(22_688_835, 0) + // Minimum execution time: 17_849_000 picoseconds. + Weight::from_parts(18_776_170, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 994 - .saturating_add(Weight::from_parts(32_994, 0).saturating_mul(p.into())) + // Standard Error: 1_239 + .saturating_add(Weight::from_parts(27_960, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `239` + // Measured: `101` // Estimated: `4706` - // Minimum execution time: 27_042_000 picoseconds. - Weight::from_parts(27_624_587, 0) + // Minimum execution time: 20_049_000 picoseconds. + Weight::from_parts(20_881_515, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 671 - .saturating_add(Weight::from_parts(5_888, 0).saturating_mul(p.into())) + // Standard Error: 952 + .saturating_add(Weight::from_parts(5_970, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `264 + p * (37 ±0)` + // Measured: `126 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 23_396_000 picoseconds. - Weight::from_parts(24_003_080, 0) + // Minimum execution time: 18_528_000 picoseconds. + Weight::from_parts(19_384_189, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 684 - .saturating_add(Weight::from_parts(29_878, 0).saturating_mul(p.into())) + // Standard Error: 1_106 + .saturating_add(Weight::from_parts(35_698, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_ranked_collective.rs b/polkadot/runtime/rococo/src/weights/pallet_ranked_collective.rs index ce9d5fcc0c7..fa2decb1671 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_ranked_collective.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_ranked_collective.rs @@ -16,24 +16,26 @@ //! Autogenerated weights for `pallet_ranked_collective` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_ranked_collective // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_ranked_collective -// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -60,8 +62,8 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `42` // Estimated: `3507` - // Minimum execution time: 13_480_000 picoseconds. - Weight::from_parts(13_786_000, 0) + // Minimum execution time: 13_428_000 picoseconds. + Weight::from_parts(14_019_000, 0) .saturating_add(Weight::from_parts(0, 3507)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) @@ -79,11 +81,11 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `516 + r * (281 ±0)` // Estimated: `3519 + r * (2529 ±0)` - // Minimum execution time: 28_771_000 picoseconds. - Weight::from_parts(29_256_825, 0) + // Minimum execution time: 28_566_000 picoseconds. + Weight::from_parts(29_346_952, 0) .saturating_add(Weight::from_parts(0, 3519)) - // Standard Error: 21_594 - .saturating_add(Weight::from_parts(14_649_527, 0).saturating_mul(r.into())) + // Standard Error: 21_068 + .saturating_add(Weight::from_parts(14_471_237, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(6)) @@ -103,11 +105,11 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `214 + r * (17 ±0)` // Estimated: `3507` - // Minimum execution time: 16_117_000 picoseconds. - Weight::from_parts(16_978_453, 0) + // Minimum execution time: 16_161_000 picoseconds. + Weight::from_parts(16_981_334, 0) .saturating_add(Weight::from_parts(0, 3507)) - // Standard Error: 4_511 - .saturating_add(Weight::from_parts(324_261, 0).saturating_mul(r.into())) + // Standard Error: 4_596 + .saturating_add(Weight::from_parts(313_386, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -124,11 +126,11 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `532 + r * (72 ±0)` // Estimated: `3519` - // Minimum execution time: 28_995_000 picoseconds. - Weight::from_parts(31_343_215, 0) + // Minimum execution time: 28_406_000 picoseconds. + Weight::from_parts(31_178_557, 0) .saturating_add(Weight::from_parts(0, 3519)) - // Standard Error: 16_438 - .saturating_add(Weight::from_parts(637_462, 0).saturating_mul(r.into())) + // Standard Error: 17_737 + .saturating_add(Weight::from_parts(627_757, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(6)) } @@ -140,15 +142,17 @@ impl pallet_ranked_collective::WeightInfo for WeightInf /// Proof: `FellowshipCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote() -> Weight { // Proof Size summary in bytes: // Measured: `603` // Estimated: `83866` - // Minimum execution time: 38_820_000 picoseconds. - Weight::from_parts(40_240_000, 0) + // Minimum execution time: 41_164_000 picoseconds. + Weight::from_parts(42_163_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:0) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -161,11 +165,11 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `400 + n * (50 ±0)` // Estimated: `4365 + n * (2540 ±0)` - // Minimum execution time: 12_972_000 picoseconds. - Weight::from_parts(15_829_333, 0) + // Minimum execution time: 13_183_000 picoseconds. + Weight::from_parts(15_604_064, 0) .saturating_add(Weight::from_parts(0, 4365)) - // Standard Error: 1_754 - .saturating_add(Weight::from_parts(1_116_520, 0).saturating_mul(n.into())) + // Standard Error: 2_018 + .saturating_add(Weight::from_parts(1_101_088, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -183,8 +187,8 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `337` // Estimated: `6048` - // Minimum execution time: 44_601_000 picoseconds. - Weight::from_parts(45_714_000, 0) + // Minimum execution time: 43_603_000 picoseconds. + Weight::from_parts(44_809_000, 0) .saturating_add(Weight::from_parts(0, 6048)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(10)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_recovery.rs b/polkadot/runtime/rococo/src/weights/pallet_recovery.rs new file mode 100644 index 00000000000..ed79aa2b1f1 --- /dev/null +++ b/polkadot/runtime/rococo/src/weights/pallet_recovery.rs @@ -0,0 +1,186 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Autogenerated weights for `pallet_recovery` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot +// benchmark +// pallet +// --chain=rococo-dev +// --steps=50 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_recovery +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ + +#![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_recovery`. +pub struct WeightInfo(PhantomData); +impl pallet_recovery::WeightInfo for WeightInfo { + /// Storage: `Recovery::Proxy` (r:1 w:0) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + fn as_recovered() -> Weight { + // Proof Size summary in bytes: + // Measured: `215` + // Estimated: `3545` + // Minimum execution time: 7_899_000 picoseconds. + Weight::from_parts(8_205_000, 0) + .saturating_add(Weight::from_parts(0, 3545)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `Recovery::Proxy` (r:0 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + fn set_recovered() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_258_000 picoseconds. + Weight::from_parts(6_494_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Recovery::Recoverable` (r:1 w:1) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 9]`. + fn create_recovery(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `109` + // Estimated: `3816` + // Minimum execution time: 19_369_000 picoseconds. + Weight::from_parts(20_185_132, 0) + .saturating_add(Weight::from_parts(0, 3816)) + // Standard Error: 4_275 + .saturating_add(Weight::from_parts(78_024, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + fn initiate_recovery() -> Weight { + // Proof Size summary in bytes: + // Measured: `206` + // Estimated: `3854` + // Minimum execution time: 22_425_000 picoseconds. + Weight::from_parts(23_171_000, 0) + .saturating_add(Weight::from_parts(0, 3854)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 9]`. + fn vouch_recovery(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `294 + n * (64 ±0)` + // Estimated: `3854` + // Minimum execution time: 17_308_000 picoseconds. + Weight::from_parts(18_118_782, 0) + .saturating_add(Weight::from_parts(0, 3854)) + // Standard Error: 4_309 + .saturating_add(Weight::from_parts(126_278, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `Recovery::Proxy` (r:1 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 9]`. + fn claim_recovery(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `326 + n * (64 ±0)` + // Estimated: `3854` + // Minimum execution time: 20_755_000 picoseconds. + Weight::from_parts(21_821_713, 0) + .saturating_add(Weight::from_parts(0, 3854)) + // Standard Error: 4_550 + .saturating_add(Weight::from_parts(101_916, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 9]`. + fn close_recovery(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `447 + n * (32 ±0)` + // Estimated: `3854` + // Minimum execution time: 29_957_000 picoseconds. + Weight::from_parts(31_010_309, 0) + .saturating_add(Weight::from_parts(0, 3854)) + // Standard Error: 5_913 + .saturating_add(Weight::from_parts(110_070, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `Recovery::Recoverable` (r:1 w:1) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 9]`. + fn remove_recovery(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `204 + n * (32 ±0)` + // Estimated: `3854` + // Minimum execution time: 24_430_000 picoseconds. + Weight::from_parts(24_462_856, 0) + .saturating_add(Weight::from_parts(0, 3854)) + // Standard Error: 13_646 + .saturating_add(Weight::from_parts(507_715, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Recovery::Proxy` (r:1 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + fn cancel_recovered() -> Weight { + // Proof Size summary in bytes: + // Measured: `215` + // Estimated: `3545` + // Minimum execution time: 9_686_000 picoseconds. + Weight::from_parts(10_071_000, 0) + .saturating_add(Weight::from_parts(0, 3545)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/polkadot/runtime/rococo/src/weights/pallet_referenda_fellowship_referenda.rs b/polkadot/runtime/rococo/src/weights/pallet_referenda_fellowship_referenda.rs index 96f172230e1..6dfcea2b832 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_referenda_fellowship_referenda.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_referenda_fellowship_referenda.rs @@ -16,27 +16,28 @@ //! Autogenerated weights for `pallet_referenda` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-xerhrdyb-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: `Some(Wasm)`, WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_referenda // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json -// --pallet=pallet_referenda -// --chain=rococo-dev -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -59,10 +60,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) fn submit() -> Weight { // Proof Size summary in bytes: - // Measured: `327` + // Measured: `292` // Estimated: `42428` - // Minimum execution time: 29_909_000 picoseconds. - Weight::from_parts(30_645_000, 0) + // Minimum execution time: 24_053_000 picoseconds. + Weight::from_parts(25_121_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -71,15 +72,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `438` + // Measured: `403` // Estimated: `83866` - // Minimum execution time: 54_405_000 picoseconds. - Weight::from_parts(55_583_000, 0) + // Minimum execution time: 45_064_000 picoseconds. + Weight::from_parts(46_112_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -89,15 +92,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `2076` + // Measured: `2041` // Estimated: `42428` - // Minimum execution time: 110_477_000 picoseconds. - Weight::from_parts(119_187_000, 0) + // Minimum execution time: 94_146_000 picoseconds. + Weight::from_parts(98_587_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -107,15 +112,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `2117` + // Measured: `2082` // Estimated: `42428` - // Minimum execution time: 111_467_000 picoseconds. - Weight::from_parts(117_758_000, 0) + // Minimum execution time: 93_002_000 picoseconds. + Weight::from_parts(96_924_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -125,15 +132,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `774` + // Measured: `739` // Estimated: `83866` - // Minimum execution time: 191_135_000 picoseconds. - Weight::from_parts(210_535_000, 0) + // Minimum execution time: 160_918_000 picoseconds. + Weight::from_parts(175_603_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -143,24 +152,26 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `639` + // Measured: `604` // Estimated: `83866` - // Minimum execution time: 67_168_000 picoseconds. - Weight::from_parts(68_895_000, 0) + // Minimum execution time: 55_253_000 picoseconds. + Weight::from_parts(56_488_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) fn refund_decision_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `351` + // Measured: `317` // Estimated: `4365` - // Minimum execution time: 31_298_000 picoseconds. - Weight::from_parts(32_570_000, 0) + // Minimum execution time: 24_497_000 picoseconds. + Weight::from_parts(25_280_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -169,10 +180,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) fn refund_submission_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `201` + // Measured: `167` // Estimated: `4365` - // Minimum execution time: 15_674_000 picoseconds. - Weight::from_parts(16_190_000, 0) + // Minimum execution time: 11_374_000 picoseconds. + Weight::from_parts(11_817_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -181,15 +192,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `383` + // Measured: `348` // Estimated: `83866` - // Minimum execution time: 38_927_000 picoseconds. - Weight::from_parts(40_545_000, 0) + // Minimum execution time: 31_805_000 picoseconds. + Weight::from_parts(32_622_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -197,15 +210,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `FellowshipReferenda::MetadataOf` (r:1 w:0) /// Proof: `FellowshipReferenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn kill() -> Weight { // Proof Size summary in bytes: - // Measured: `484` + // Measured: `449` // Estimated: `83866` - // Minimum execution time: 80_209_000 picoseconds. - Weight::from_parts(82_084_000, 0) + // Minimum execution time: 62_364_000 picoseconds. + Weight::from_parts(63_798_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `FellowshipReferenda::TrackQueue` (r:1 w:0) /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) @@ -213,10 +228,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) fn one_fewer_deciding_queue_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `174` + // Measured: `140` // Estimated: `4277` - // Minimum execution time: 9_520_000 picoseconds. - Weight::from_parts(10_088_000, 0) + // Minimum execution time: 8_811_000 picoseconds. + Weight::from_parts(9_224_000, 0) .saturating_add(Weight::from_parts(0, 4277)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -231,10 +246,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `2376` + // Measured: `2341` // Estimated: `42428` - // Minimum execution time: 93_893_000 picoseconds. - Weight::from_parts(101_065_000, 0) + // Minimum execution time: 83_292_000 picoseconds. + Weight::from_parts(89_114_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -249,10 +264,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `2362` + // Measured: `2327` // Estimated: `42428` - // Minimum execution time: 98_811_000 picoseconds. - Weight::from_parts(103_590_000, 0) + // Minimum execution time: 84_648_000 picoseconds. + Weight::from_parts(89_332_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -263,10 +278,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_insertion() -> Weight { // Proof Size summary in bytes: - // Measured: `1841` + // Measured: `1807` // Estimated: `4365` - // Minimum execution time: 43_230_000 picoseconds. - Weight::from_parts(46_120_000, 0) + // Minimum execution time: 40_529_000 picoseconds. + Weight::from_parts(45_217_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -277,10 +292,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_slide() -> Weight { // Proof Size summary in bytes: - // Measured: `1808` + // Measured: `1774` // Estimated: `4365` - // Minimum execution time: 43_092_000 picoseconds. - Weight::from_parts(46_018_000, 0) + // Minimum execution time: 40_894_000 picoseconds. + Weight::from_parts(45_726_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -293,10 +308,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) fn nudge_referendum_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `1824` + // Measured: `1790` // Estimated: `4365` - // Minimum execution time: 49_697_000 picoseconds. - Weight::from_parts(53_795_000, 0) + // Minimum execution time: 48_187_000 picoseconds. + Weight::from_parts(52_655_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -309,10 +324,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) fn nudge_referendum_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `1865` + // Measured: `1831` // Estimated: `4365` - // Minimum execution time: 50_417_000 picoseconds. - Weight::from_parts(53_214_000, 0) + // Minimum execution time: 47_548_000 picoseconds. + Weight::from_parts(51_547_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -323,10 +338,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_no_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `335` + // Measured: `300` // Estimated: `42428` - // Minimum execution time: 25_688_000 picoseconds. - Weight::from_parts(26_575_000, 0) + // Minimum execution time: 20_959_000 picoseconds. + Weight::from_parts(21_837_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -337,10 +352,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `383` + // Measured: `348` // Estimated: `42428` - // Minimum execution time: 26_230_000 picoseconds. - Weight::from_parts(27_235_000, 0) + // Minimum execution time: 21_628_000 picoseconds. + Weight::from_parts(22_192_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -349,10 +364,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) fn nudge_referendum_timed_out() -> Weight { // Proof Size summary in bytes: - // Measured: `242` + // Measured: `208` // Estimated: `4365` - // Minimum execution time: 17_585_000 picoseconds. - Weight::from_parts(18_225_000, 0) + // Minimum execution time: 12_309_000 picoseconds. + Weight::from_parts(12_644_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -367,10 +382,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `584` + // Measured: `549` // Estimated: `42428` - // Minimum execution time: 38_243_000 picoseconds. - Weight::from_parts(39_959_000, 0) + // Minimum execution time: 31_871_000 picoseconds. + Weight::from_parts(33_123_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -385,10 +400,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `719` + // Measured: `684` // Estimated: `42428` - // Minimum execution time: 88_424_000 picoseconds. - Weight::from_parts(92_969_000, 0) + // Minimum execution time: 73_715_000 picoseconds. + Weight::from_parts(79_980_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -401,10 +416,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `770` + // Measured: `735` // Estimated: `42428` - // Minimum execution time: 138_207_000 picoseconds. - Weight::from_parts(151_726_000, 0) + // Minimum execution time: 128_564_000 picoseconds. + Weight::from_parts(138_536_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -417,10 +432,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_end_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `755` + // Measured: `720` // Estimated: `42428` - // Minimum execution time: 131_001_000 picoseconds. - Weight::from_parts(148_651_000, 0) + // Minimum execution time: 129_775_000 picoseconds. + Weight::from_parts(139_001_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -433,10 +448,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_continue_not_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `770` + // Measured: `735` // Estimated: `42428` - // Minimum execution time: 109_612_000 picoseconds. - Weight::from_parts(143_626_000, 0) + // Minimum execution time: 128_233_000 picoseconds. + Weight::from_parts(135_796_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -449,10 +464,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_continue_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `776` + // Measured: `741` // Estimated: `42428` - // Minimum execution time: 71_754_000 picoseconds. - Weight::from_parts(77_329_000, 0) + // Minimum execution time: 66_995_000 picoseconds. + Weight::from_parts(72_678_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -467,10 +482,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn nudge_referendum_approved() -> Weight { // Proof Size summary in bytes: - // Measured: `776` + // Measured: `741` // Estimated: `83866` - // Minimum execution time: 153_244_000 picoseconds. - Weight::from_parts(169_961_000, 0) + // Minimum execution time: 137_764_000 picoseconds. + Weight::from_parts(152_260_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -483,10 +498,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_rejected() -> Weight { // Proof Size summary in bytes: - // Measured: `772` + // Measured: `737` // Estimated: `42428` - // Minimum execution time: 137_997_000 picoseconds. - Weight::from_parts(157_862_000, 0) + // Minimum execution time: 119_992_000 picoseconds. + Weight::from_parts(134_805_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -495,16 +510,18 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `FellowshipReferenda::MetadataOf` (r:0 w:1) /// Proof: `FellowshipReferenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_some_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `458` + // Measured: `424` // Estimated: `4365` - // Minimum execution time: 21_794_000 picoseconds. - Weight::from_parts(22_341_000, 0) + // Minimum execution time: 20_927_000 picoseconds. + Weight::from_parts(21_802_000, 0) .saturating_add(Weight::from_parts(0, 4365)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:0) @@ -513,10 +530,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `319` + // Measured: `285` // Estimated: `4365` - // Minimum execution time: 18_458_000 picoseconds. - Weight::from_parts(19_097_000, 0) + // Minimum execution time: 14_253_000 picoseconds. + Weight::from_parts(15_031_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_referenda_referenda.rs b/polkadot/runtime/rococo/src/weights/pallet_referenda_referenda.rs index b7cc5df28b9..c35925198f9 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_referenda_referenda.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_referenda_referenda.rs @@ -16,27 +16,28 @@ //! Autogenerated weights for `pallet_referenda` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-xerhrdyb-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: `Some(Wasm)`, WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_referenda // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json -// --pallet=pallet_referenda -// --chain=rococo-dev -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,10 +58,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn submit() -> Weight { // Proof Size summary in bytes: - // Measured: `324` + // Measured: `185` // Estimated: `42428` - // Minimum execution time: 39_852_000 picoseconds. - Weight::from_parts(41_610_000, 0) + // Minimum execution time: 28_612_000 picoseconds. + Weight::from_parts(30_060_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) @@ -69,15 +70,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `577` + // Measured: `438` // Estimated: `83866` - // Minimum execution time: 52_588_000 picoseconds. - Weight::from_parts(54_154_000, 0) + // Minimum execution time: 42_827_000 picoseconds. + Weight::from_parts(44_072_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) @@ -87,15 +90,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3334` + // Measured: `3225` // Estimated: `42428` - // Minimum execution time: 70_483_000 picoseconds. - Weight::from_parts(72_731_000, 0) + // Minimum execution time: 56_475_000 picoseconds. + Weight::from_parts(58_888_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) @@ -105,60 +110,62 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3354` + // Measured: `3245` // Estimated: `42428` - // Minimum execution time: 68_099_000 picoseconds. - Weight::from_parts(71_560_000, 0) + // Minimum execution time: 56_542_000 picoseconds. + Weight::from_parts(58_616_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Referenda::DecidingCount` (r:1 w:1) /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `577` + // Measured: `438` // Estimated: `83866` - // Minimum execution time: 64_357_000 picoseconds. - Weight::from_parts(66_081_000, 0) + // Minimum execution time: 51_218_000 picoseconds. + Weight::from_parts(53_148_000, 0) .saturating_add(Weight::from_parts(0, 83866)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Referenda::DecidingCount` (r:1 w:1) /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `577` + // Measured: `438` // Estimated: `83866` - // Minimum execution time: 62_709_000 picoseconds. - Weight::from_parts(64_534_000, 0) + // Minimum execution time: 49_097_000 picoseconds. + Weight::from_parts(50_796_000, 0) .saturating_add(Weight::from_parts(0, 83866)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn refund_decision_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `279` // Estimated: `4401` - // Minimum execution time: 31_296_000 picoseconds. - Weight::from_parts(32_221_000, 0) + // Minimum execution time: 23_720_000 picoseconds. + Weight::from_parts(24_327_000, 0) .saturating_add(Weight::from_parts(0, 4401)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -167,10 +174,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn refund_submission_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `407` + // Measured: `269` // Estimated: `4401` - // Minimum execution time: 31_209_000 picoseconds. - Weight::from_parts(32_168_000, 0) + // Minimum execution time: 24_089_000 picoseconds. + Weight::from_parts(24_556_000, 0) .saturating_add(Weight::from_parts(0, 4401)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -179,15 +186,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `346` // Estimated: `83866` - // Minimum execution time: 38_887_000 picoseconds. - Weight::from_parts(40_193_000, 0) + // Minimum execution time: 29_022_000 picoseconds. + Weight::from_parts(29_590_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) @@ -195,15 +204,17 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Referenda::MetadataOf` (r:1 w:0) /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn kill() -> Weight { // Proof Size summary in bytes: - // Measured: `726` + // Measured: `587` // Estimated: `83866` - // Minimum execution time: 106_054_000 picoseconds. - Weight::from_parts(108_318_000, 0) + // Minimum execution time: 81_920_000 picoseconds. + Weight::from_parts(84_492_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::TrackQueue` (r:1 w:0) /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) @@ -211,10 +222,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) fn one_fewer_deciding_queue_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `240` + // Measured: `102` // Estimated: `5477` - // Minimum execution time: 9_263_000 picoseconds. - Weight::from_parts(9_763_000, 0) + // Minimum execution time: 8_134_000 picoseconds. + Weight::from_parts(8_574_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -223,36 +234,32 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `3254` + // Measured: `3115` // Estimated: `42428` - // Minimum execution time: 50_080_000 picoseconds. - Weight::from_parts(51_858_000, 0) + // Minimum execution time: 39_932_000 picoseconds. + Weight::from_parts(42_086_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::TrackQueue` (r:1 w:1) /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `3254` + // Measured: `3115` // Estimated: `42428` - // Minimum execution time: 53_889_000 picoseconds. - Weight::from_parts(55_959_000, 0) + // Minimum execution time: 42_727_000 picoseconds. + Weight::from_parts(44_280_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) @@ -261,10 +268,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_insertion() -> Weight { // Proof Size summary in bytes: - // Measured: `3077` + // Measured: `2939` // Estimated: `5477` - // Minimum execution time: 23_266_000 picoseconds. - Weight::from_parts(24_624_000, 0) + // Minimum execution time: 20_918_000 picoseconds. + Weight::from_parts(22_180_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -275,10 +282,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_slide() -> Weight { // Proof Size summary in bytes: - // Measured: `3077` + // Measured: `2939` // Estimated: `5477` - // Minimum execution time: 22_846_000 picoseconds. - Weight::from_parts(24_793_000, 0) + // Minimum execution time: 20_943_000 picoseconds. + Weight::from_parts(21_932_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -291,10 +298,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3081` + // Measured: `2943` // Estimated: `5477` - // Minimum execution time: 28_284_000 picoseconds. - Weight::from_parts(29_940_000, 0) + // Minimum execution time: 25_197_000 picoseconds. + Weight::from_parts(26_083_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -307,10 +314,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3101` + // Measured: `2963` // Estimated: `5477` - // Minimum execution time: 28_133_000 picoseconds. - Weight::from_parts(29_638_000, 0) + // Minimum execution time: 24_969_000 picoseconds. + Weight::from_parts(26_096_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -321,10 +328,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_no_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `437` + // Measured: `298` // Estimated: `42428` - // Minimum execution time: 25_710_000 picoseconds. - Weight::from_parts(26_500_000, 0) + // Minimum execution time: 18_050_000 picoseconds. + Weight::from_parts(18_790_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -335,10 +342,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `346` // Estimated: `42428` - // Minimum execution time: 25_935_000 picoseconds. - Weight::from_parts(26_803_000, 0) + // Minimum execution time: 18_357_000 picoseconds. + Weight::from_parts(18_957_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -347,10 +354,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn nudge_referendum_timed_out() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `206` // Estimated: `4401` - // Minimum execution time: 17_390_000 picoseconds. - Weight::from_parts(18_042_000, 0) + // Minimum execution time: 11_479_000 picoseconds. + Weight::from_parts(11_968_000, 0) .saturating_add(Weight::from_parts(0, 4401)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -359,150 +366,136 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Referenda::DecidingCount` (r:1 w:1) /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `346` // Estimated: `42428` - // Minimum execution time: 35_141_000 picoseconds. - Weight::from_parts(36_318_000, 0) + // Minimum execution time: 24_471_000 picoseconds. + Weight::from_parts(25_440_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Referenda::DecidingCount` (r:1 w:1) /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `346` // Estimated: `42428` - // Minimum execution time: 37_815_000 picoseconds. - Weight::from_parts(39_243_000, 0) + // Minimum execution time: 26_580_000 picoseconds. + Weight::from_parts(27_570_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `538` + // Measured: `399` // Estimated: `42428` - // Minimum execution time: 30_779_000 picoseconds. - Weight::from_parts(31_845_000, 0) + // Minimum execution time: 24_331_000 picoseconds. + Weight::from_parts(25_291_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_end_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `521` + // Measured: `382` // Estimated: `42428` - // Minimum execution time: 31_908_000 picoseconds. - Weight::from_parts(33_253_000, 0) + // Minimum execution time: 24_768_000 picoseconds. + Weight::from_parts(25_746_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_continue_not_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `538` + // Measured: `399` // Estimated: `42428` - // Minimum execution time: 28_951_000 picoseconds. - Weight::from_parts(30_004_000, 0) + // Minimum execution time: 23_171_000 picoseconds. + Weight::from_parts(24_161_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_continue_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `542` + // Measured: `403` // Estimated: `42428` - // Minimum execution time: 27_750_000 picoseconds. - Weight::from_parts(28_588_000, 0) + // Minimum execution time: 22_263_000 picoseconds. + Weight::from_parts(23_062_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Lookup` (r:1 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn nudge_referendum_approved() -> Weight { // Proof Size summary in bytes: - // Measured: `542` + // Measured: `403` // Estimated: `83866` - // Minimum execution time: 43_950_000 picoseconds. - Weight::from_parts(46_164_000, 0) + // Minimum execution time: 33_710_000 picoseconds. + Weight::from_parts(34_871_000, 0) .saturating_add(Weight::from_parts(0, 83866)) - .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Balances::InactiveIssuance` (r:1 w:0) - /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_rejected() -> Weight { // Proof Size summary in bytes: - // Measured: `538` + // Measured: `399` // Estimated: `42428` - // Minimum execution time: 31_050_000 picoseconds. - Weight::from_parts(32_169_000, 0) + // Minimum execution time: 24_260_000 picoseconds. + Weight::from_parts(25_104_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Referenda::MetadataOf` (r:0 w:1) /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_some_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `560` + // Measured: `422` // Estimated: `4401` - // Minimum execution time: 21_193_000 picoseconds. - Weight::from_parts(22_116_000, 0) + // Minimum execution time: 19_821_000 picoseconds. + Weight::from_parts(20_641_000, 0) .saturating_add(Weight::from_parts(0, 4401)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) @@ -511,10 +504,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `421` + // Measured: `283` // Estimated: `4401` - // Minimum execution time: 18_065_000 picoseconds. - Weight::from_parts(18_781_000, 0) + // Minimum execution time: 13_411_000 picoseconds. + Weight::from_parts(14_070_000, 0) .saturating_add(Weight::from_parts(0, 4401)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_scheduler.rs b/polkadot/runtime/rococo/src/weights/pallet_scheduler.rs index 0f36dbd384d..5f6b41d2b54 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_scheduler.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_scheduler.rs @@ -16,24 +16,26 @@ //! Autogenerated weights for `pallet_scheduler` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_scheduler // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_scheduler -// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -54,8 +56,8 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `68` // Estimated: `1489` - // Minimum execution time: 2_869_000 picoseconds. - Weight::from_parts(3_109_000, 0) + // Minimum execution time: 3_114_000 picoseconds. + Weight::from_parts(3_245_000, 0) .saturating_add(Weight::from_parts(0, 1489)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -67,11 +69,11 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `115 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 3_326_000 picoseconds. - Weight::from_parts(5_818_563, 0) + // Minimum execution time: 3_430_000 picoseconds. + Weight::from_parts(6_250_920, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 1_261 - .saturating_add(Weight::from_parts(336_446, 0).saturating_mul(s.into())) + // Standard Error: 1_350 + .saturating_add(Weight::from_parts(333_245, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -79,8 +81,8 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_007_000 picoseconds. - Weight::from_parts(3_197_000, 0) + // Minimum execution time: 3_166_000 picoseconds. + Weight::from_parts(3_295_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Preimage::PreimageFor` (r:1 w:1) @@ -94,11 +96,11 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `251 + s * (1 ±0)` // Estimated: `3716 + s * (1 ±0)` - // Minimum execution time: 16_590_000 picoseconds. - Weight::from_parts(16_869_000, 0) + // Minimum execution time: 17_072_000 picoseconds. + Weight::from_parts(17_393_000, 0) .saturating_add(Weight::from_parts(0, 3716)) - // Standard Error: 9 - .saturating_add(Weight::from_parts(1_308, 0).saturating_mul(s.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_204, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(s.into())) @@ -109,8 +111,8 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_320_000 picoseconds. - Weight::from_parts(4_594_000, 0) + // Minimum execution time: 4_566_000 picoseconds. + Weight::from_parts(4_775_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -118,24 +120,24 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_956_000 picoseconds. - Weight::from_parts(3_216_000, 0) + // Minimum execution time: 3_180_000 picoseconds. + Weight::from_parts(3_339_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn execute_dispatch_signed() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_824_000 picoseconds. - Weight::from_parts(1_929_000, 0) + // Minimum execution time: 1_656_000 picoseconds. + Weight::from_parts(1_829_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn execute_dispatch_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_749_000 picoseconds. - Weight::from_parts(1_916_000, 0) + // Minimum execution time: 1_628_000 picoseconds. + Weight::from_parts(1_840_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Scheduler::Agenda` (r:1 w:1) @@ -145,16 +147,18 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `115 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 9_086_000 picoseconds. - Weight::from_parts(11_733_696, 0) + // Minimum execution time: 9_523_000 picoseconds. + Weight::from_parts(12_482_434, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 1_362 - .saturating_add(Weight::from_parts(375_266, 0).saturating_mul(s.into())) + // Standard Error: 1_663 + .saturating_add(Weight::from_parts(370_122, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Lookup` (r:0 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 50]`. @@ -162,13 +166,13 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `115 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 12_716_000 picoseconds. - Weight::from_parts(12_529_180, 0) + // Minimum execution time: 14_649_000 picoseconds. + Weight::from_parts(14_705_132, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 867 - .saturating_add(Weight::from_parts(548_188, 0).saturating_mul(s.into())) + // Standard Error: 1_126 + .saturating_add(Weight::from_parts(547_438, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Scheduler::Lookup` (r:1 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) @@ -179,11 +183,11 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `292 + s * (185 ±0)` // Estimated: `42428` - // Minimum execution time: 12_053_000 picoseconds. - Weight::from_parts(15_358_056, 0) + // Minimum execution time: 12_335_000 picoseconds. + Weight::from_parts(16_144_217, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 3_176 - .saturating_add(Weight::from_parts(421_589, 0).saturating_mul(s.into())) + // Standard Error: 3_533 + .saturating_add(Weight::from_parts(413_823, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -191,49 +195,48 @@ impl pallet_scheduler::WeightInfo for WeightInfo { /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 50]`. fn cancel_named(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `318 + s * (185 ±0)` // Estimated: `42428` - // Minimum execution time: 14_803_000 picoseconds. - Weight::from_parts(15_805_714, 0) + // Minimum execution time: 16_906_000 picoseconds. + Weight::from_parts(17_846_662, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 2_597 - .saturating_add(Weight::from_parts(611_053, 0).saturating_mul(s.into())) + // Standard Error: 2_687 + .saturating_add(Weight::from_parts(613_356, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Scheduler::Retries` (r:1 w:2) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Lookup` (r:0 w:1) - /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 50]`. fn schedule_retry(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `196` + // Measured: `155` // Estimated: `42428` - // Minimum execution time: 13_156_000 picoseconds. - Weight::from_parts(13_801_287, 0) + // Minimum execution time: 8_988_000 picoseconds. + Weight::from_parts(9_527_838, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 568 - .saturating_add(Weight::from_parts(35_441, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(4)) + // Standard Error: 523 + .saturating_add(Weight::from_parts(25_453, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Scheduler::Agenda` (r:1 w:0) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Retries` (r:0 w:1) /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) - /// The range of component `s` is `[1, 50]`. fn set_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `115 + s * (177 ±0)` + // Measured: `8965` // Estimated: `42428` - // Minimum execution time: 7_912_000 picoseconds. - Weight::from_parts(8_081_460, 0) + // Minimum execution time: 23_337_000 picoseconds. + Weight::from_parts(24_255_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -244,13 +247,12 @@ impl pallet_scheduler::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Retries` (r:0 w:1) /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) - /// The range of component `s` is `[1, 50]`. fn set_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `324 + s * (185 ±0)` + // Measured: `9643` // Estimated: `42428` - // Minimum execution time: 10_673_000 picoseconds. - Weight::from_parts(12_212_185, 0) + // Minimum execution time: 30_704_000 picoseconds. + Weight::from_parts(31_646_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -259,13 +261,12 @@ impl pallet_scheduler::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Retries` (r:0 w:1) /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) - /// The range of component `s` is `[1, 50]`. fn cancel_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `115 + s * (177 ±0)` + // Measured: `8977` // Estimated: `42428` - // Minimum execution time: 7_912_000 picoseconds. - Weight::from_parts(8_081_460, 0) + // Minimum execution time: 22_279_000 picoseconds. + Weight::from_parts(23_106_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -276,13 +277,12 @@ impl pallet_scheduler::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Retries` (r:0 w:1) /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) - /// The range of component `s` is `[1, 50]`. fn cancel_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `324 + s * (185 ±0)` + // Measured: `9655` // Estimated: `42428` - // Minimum execution time: 10_673_000 picoseconds. - Weight::from_parts(12_212_185, 0) + // Minimum execution time: 29_649_000 picoseconds. + Weight::from_parts(30_472_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_sudo.rs b/polkadot/runtime/rococo/src/weights/pallet_sudo.rs index 694174954fc..ecc31dc3fa9 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_sudo.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_sudo.rs @@ -16,24 +16,26 @@ //! Autogenerated weights for `pallet_sudo` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_sudo // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_sudo -// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -54,8 +56,8 @@ impl pallet_sudo::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `132` // Estimated: `1517` - // Minimum execution time: 8_432_000 picoseconds. - Weight::from_parts(8_757_000, 0) + // Minimum execution time: 8_336_000 picoseconds. + Weight::from_parts(8_569_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -66,8 +68,8 @@ impl pallet_sudo::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `132` // Estimated: `1517` - // Minimum execution time: 9_167_000 picoseconds. - Weight::from_parts(9_397_000, 0) + // Minimum execution time: 8_858_000 picoseconds. + Weight::from_parts(9_238_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -77,8 +79,8 @@ impl pallet_sudo::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `132` // Estimated: `1517` - // Minimum execution time: 9_133_000 picoseconds. - Weight::from_parts(9_573_000, 0) + // Minimum execution time: 8_921_000 picoseconds. + Weight::from_parts(9_324_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -88,10 +90,21 @@ impl pallet_sudo::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `132` // Estimated: `1517` - // Minimum execution time: 7_374_000 picoseconds. - Weight::from_parts(7_702_000, 0) + // Minimum execution time: 7_398_000 picoseconds. + Weight::from_parts(7_869_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `Sudo::Key` (r:1 w:0) + /// Proof: `Sudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + fn check_only_sudo_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `132` + // Estimated: `1517` + // Minimum execution time: 3_146_000 picoseconds. + Weight::from_parts(3_314_000, 0) + .saturating_add(Weight::from_parts(0, 1517)) + .saturating_add(T::DbWeight::get().reads(1)) + } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_timestamp.rs b/polkadot/runtime/rococo/src/weights/pallet_timestamp.rs index 1bb2e227ab7..7d79621b9e6 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_timestamp.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_timestamp.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_timestamp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_timestamp // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,26 +50,26 @@ use core::marker::PhantomData; /// Weight functions for `pallet_timestamp`. pub struct WeightInfo(PhantomData); impl pallet_timestamp::WeightInfo for WeightInfo { - /// Storage: Timestamp Now (r:1 w:1) - /// Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Babe CurrentSlot (r:1 w:0) - /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Timestamp::Now` (r:1 w:1) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Babe::CurrentSlot` (r:1 w:0) + /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn set() -> Weight { // Proof Size summary in bytes: - // Measured: `311` + // Measured: `137` // Estimated: `1493` - // Minimum execution time: 10_103_000 picoseconds. - Weight::from_parts(10_597_000, 0) + // Minimum execution time: 5_596_000 picoseconds. + Weight::from_parts(5_823_000, 0) .saturating_add(Weight::from_parts(0, 1493)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } fn on_finalize() -> Weight { // Proof Size summary in bytes: - // Measured: `94` + // Measured: `57` // Estimated: `0` - // Minimum execution time: 4_718_000 picoseconds. - Weight::from_parts(4_839_000, 0) + // Minimum execution time: 2_777_000 picoseconds. + Weight::from_parts(2_900_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_transaction_payment.rs b/polkadot/runtime/rococo/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..44dfab289fb --- /dev/null +++ b/polkadot/runtime/rococo/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,68 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot +// benchmark +// pallet +// --chain=rococo-dev +// --steps=50 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_transaction_payment +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ + +#![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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `252` + // Estimated: `1737` + // Minimum execution time: 33_070_000 picoseconds. + Weight::from_parts(33_730_000, 0) + .saturating_add(Weight::from_parts(0, 1737)) + .saturating_add(T::DbWeight::get().reads(3)) + } +} diff --git a/polkadot/runtime/rococo/src/weights/pallet_treasury.rs b/polkadot/runtime/rococo/src/weights/pallet_treasury.rs index 144e9d5b872..acf09989afc 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_treasury.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_treasury.rs @@ -16,25 +16,28 @@ //! Autogenerated weights for `pallet_treasury` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-07, STEPS: `50`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `cob`, CPU: `` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/debug/polkadot +// ./target/production/polkadot // benchmark // pallet // --chain=rococo-dev // --steps=50 -// --repeat=2 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_treasury // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --output=./runtime/rococo/src/weights/ -// --header=./file_header.txt +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,176 +50,168 @@ use core::marker::PhantomData; /// Weight functions for `pallet_treasury`. pub struct WeightInfo(PhantomData); impl pallet_treasury::WeightInfo for WeightInfo { - /// Storage: Treasury ProposalCount (r:1 w:1) - /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:0 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: `Treasury::ProposalCount` (r:1 w:1) + /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:0 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn spend_local() -> Weight { // Proof Size summary in bytes: - // Measured: `42` + // Measured: `142` // Estimated: `1887` - // Minimum execution time: 177_000_000 picoseconds. - Weight::from_parts(191_000_000, 0) + // Minimum execution time: 9_928_000 picoseconds. + Weight::from_parts(10_560_000, 0) .saturating_add(Weight::from_parts(0, 1887)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Treasury ProposalCount (r:1 w:1) - /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:0 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: `Treasury::ProposalCount` (r:1 w:1) + /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:0 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn propose_spend() -> Weight { // Proof Size summary in bytes: - // Measured: `143` + // Measured: `243` // Estimated: `1489` - // Minimum execution time: 354_000_000 picoseconds. - Weight::from_parts(376_000_000, 0) + // Minimum execution time: 20_714_000 picoseconds. + Weight::from_parts(21_137_000, 0) .saturating_add(Weight::from_parts(0, 1489)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Treasury Proposals (r:1 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Treasury::Proposals` (r:1 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn reject_proposal() -> Weight { // Proof Size summary in bytes: - // Measured: `301` + // Measured: `401` // Estimated: `3593` - // Minimum execution time: 547_000_000 picoseconds. - Weight::from_parts(550_000_000, 0) + // Minimum execution time: 31_665_000 picoseconds. + Weight::from_parts(32_442_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Treasury Proposals (r:1 w:0) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Proposals` (r:1 w:0) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `470 + p * (8 ±0)` + // Measured: `570 + p * (8 ±0)` // Estimated: `3573` - // Minimum execution time: 104_000_000 picoseconds. - Weight::from_parts(121_184_402, 0) + // Minimum execution time: 6_988_000 picoseconds. + Weight::from_parts(11_464_972, 0) .saturating_add(Weight::from_parts(0, 3573)) - // Standard Error: 42_854 - .saturating_add(Weight::from_parts(153_112, 0).saturating_mul(p.into())) + // Standard Error: 1_722 + .saturating_add(Weight::from_parts(84_536, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn remove_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `127` + // Measured: `227` // Estimated: `1887` - // Minimum execution time: 80_000_000 picoseconds. - Weight::from_parts(82_000_000, 0) + // Minimum execution time: 5_386_000 picoseconds. + Weight::from_parts(5_585_000, 0) .saturating_add(Weight::from_parts(0, 1887)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Treasury Deactivated (r:1 w:1) - /// Proof: Treasury Deactivated (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Balances InactiveIssuance (r:1 w:1) - /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:99 w:99) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: System Account (r:199 w:199) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyApprovals (r:1 w:1) - /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Deactivated` (r:1 w:1) + /// Proof: `Treasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:99 w:99) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:199 w:199) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 99]`. fn on_initialize_proposals(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `331 + p * (251 ±0)` + // Measured: `431 + p * (251 ±0)` // Estimated: `3593 + p * (5206 ±0)` - // Minimum execution time: 887_000_000 picoseconds. - Weight::from_parts(828_616_021, 0) + // Minimum execution time: 43_737_000 picoseconds. + Weight::from_parts(39_883_021, 0) .saturating_add(Weight::from_parts(0, 3593)) - // Standard Error: 695_351 - .saturating_add(Weight::from_parts(566_114_524, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(5)) + // Standard Error: 12_917 + .saturating_add(Weight::from_parts(31_796_205, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(p.into()))) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(p.into())) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:0) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(1237), added: 3712, mode: MaxEncodedLen) - /// Storage: Treasury SpendCount (r:1 w:1) - /// Proof: Treasury SpendCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Spends (r:0 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(1848), added: 4323, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:0) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`) + /// Storage: `Treasury::SpendCount` (r:1 w:1) + /// Proof: `Treasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Spends` (r:0 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`) fn spend() -> Weight { // Proof Size summary in bytes: - // Measured: `114` - // Estimated: `4702` - // Minimum execution time: 208_000_000 picoseconds. - Weight::from_parts(222_000_000, 0) - .saturating_add(Weight::from_parts(0, 4702)) + // Measured: `215` + // Estimated: `4703` + // Minimum execution time: 16_829_000 picoseconds. + Weight::from_parts(17_251_000, 0) + .saturating_add(Weight::from_parts(0, 4703)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(1848), added: 4323, mode: MaxEncodedLen) - /// Storage: XcmPallet QueryCounter (r:1 w:1) - /// Proof Skipped: XcmPallet QueryCounter (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DeliveryFeeFactor (r:1 w:0) - /// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured) - /// Storage: XcmPallet SupportedVersion (r:1 w:0) - /// Proof Skipped: XcmPallet SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: XcmPallet VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: XcmPallet SafeXcmVersion (r:1 w:0) - /// Proof Skipped: XcmPallet SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) - /// Storage: XcmPallet Queries (r:0 w:1) - /// Proof Skipped: XcmPallet Queries (max_values: None, max_size: None, mode: Measured) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`) + /// Storage: `XcmPallet::QueryCounter` (r:1 w:1) + /// Proof: `XcmPallet::QueryCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::Queries` (r:0 w:1) + /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn payout() -> Weight { // Proof Size summary in bytes: - // Measured: `737` - // Estimated: `5313` - // Minimum execution time: 551_000_000 picoseconds. - Weight::from_parts(569_000_000, 0) - .saturating_add(Weight::from_parts(0, 5313)) - .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(6)) + // Measured: `458` + // Estimated: `5318` + // Minimum execution time: 41_554_000 picoseconds. + Weight::from_parts(42_451_000, 0) + .saturating_add(Weight::from_parts(0, 5318)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(1848), added: 4323, mode: MaxEncodedLen) - /// Storage: XcmPallet Queries (r:1 w:1) - /// Proof Skipped: XcmPallet Queries (max_values: None, max_size: None, mode: Measured) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`) + /// Storage: `XcmPallet::Queries` (r:1 w:1) + /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn check_status() -> Weight { // Proof Size summary in bytes: - // Measured: `442` - // Estimated: `5313` - // Minimum execution time: 245_000_000 picoseconds. - Weight::from_parts(281_000_000, 0) - .saturating_add(Weight::from_parts(0, 5313)) + // Measured: `306` + // Estimated: `5318` + // Minimum execution time: 22_546_000 picoseconds. + Weight::from_parts(23_151_000, 0) + .saturating_add(Weight::from_parts(0, 5318)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(1848), added: 4323, mode: MaxEncodedLen) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`) fn void_spend() -> Weight { // Proof Size summary in bytes: - // Measured: `172` - // Estimated: `5313` - // Minimum execution time: 147_000_000 picoseconds. - Weight::from_parts(160_000_000, 0) - .saturating_add(Weight::from_parts(0, 5313)) + // Measured: `278` + // Estimated: `5318` + // Minimum execution time: 12_169_000 picoseconds. + Weight::from_parts(12_484_000, 0) + .saturating_add(Weight::from_parts(0, 5318)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_utility.rs b/polkadot/runtime/rococo/src/weights/pallet_utility.rs index f50f60eaad7..6f2a374247f 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_utility.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_utility.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_utility` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_utility // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -52,18 +55,18 @@ impl pallet_utility::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_738_000 picoseconds. - Weight::from_parts(2_704_821, 0) + // Minimum execution time: 4_041_000 picoseconds. + Weight::from_parts(5_685_496, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2_999 - .saturating_add(Weight::from_parts(4_627_278, 0).saturating_mul(c.into())) + // Standard Error: 810 + .saturating_add(Weight::from_parts(3_177_197, 0).saturating_mul(c.into())) } fn as_derivative() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_294_000 picoseconds. - Weight::from_parts(5_467_000, 0) + // Minimum execution time: 3_667_000 picoseconds. + Weight::from_parts(3_871_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `c` is `[0, 1000]`. @@ -71,18 +74,18 @@ impl pallet_utility::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_828_000 picoseconds. - Weight::from_parts(4_650_678, 0) + // Minimum execution time: 4_116_000 picoseconds. + Weight::from_parts(6_453_932, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2_789 - .saturating_add(Weight::from_parts(4_885_004, 0).saturating_mul(c.into())) + // Standard Error: 825 + .saturating_add(Weight::from_parts(3_366_112, 0).saturating_mul(c.into())) } fn dispatch_as() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_020_000 picoseconds. - Weight::from_parts(9_205_000, 0) + // Minimum execution time: 5_630_000 picoseconds. + Weight::from_parts(5_956_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `c` is `[0, 1000]`. @@ -90,10 +93,10 @@ impl pallet_utility::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_852_000 picoseconds. - Weight::from_parts(20_703_134, 0) + // Minimum execution time: 4_165_000 picoseconds. + Weight::from_parts(5_442_561, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 3_924 - .saturating_add(Weight::from_parts(4_604_529, 0).saturating_mul(c.into())) + // Standard Error: 460 + .saturating_add(Weight::from_parts(3_173_577, 0).saturating_mul(c.into())) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_vesting.rs b/polkadot/runtime/rococo/src/weights/pallet_vesting.rs index 2596207d583..c21ab087774 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_vesting.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_vesting.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_vesting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=pallet_vesting // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,143 +50,143 @@ use core::marker::PhantomData; /// Weight functions for `pallet_vesting`. pub struct WeightInfo(PhantomData); impl pallet_vesting::WeightInfo for WeightInfo { - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_locked(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `277 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 32_820_000 picoseconds. - Weight::from_parts(31_640_992, 0) + // Minimum execution time: 29_288_000 picoseconds. + Weight::from_parts(29_095_507, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 449 - .saturating_add(Weight::from_parts(45_254, 0).saturating_mul(l.into())) - // Standard Error: 800 - .saturating_add(Weight::from_parts(72_178, 0).saturating_mul(s.into())) + // Standard Error: 1_679 + .saturating_add(Weight::from_parts(33_164, 0).saturating_mul(l.into())) + // Standard Error: 2_988 + .saturating_add(Weight::from_parts(67_092, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_unlocked(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `277 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 36_054_000 picoseconds. - Weight::from_parts(35_825_428, 0) + // Minimum execution time: 31_003_000 picoseconds. + Weight::from_parts(30_528_438, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 749 - .saturating_add(Weight::from_parts(31_738, 0).saturating_mul(l.into())) - // Standard Error: 1_333 - .saturating_add(Weight::from_parts(40_580, 0).saturating_mul(s.into())) + // Standard Error: 1_586 + .saturating_add(Weight::from_parts(35_429, 0).saturating_mul(l.into())) + // Standard Error: 2_823 + .saturating_add(Weight::from_parts(76_505, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_other_locked(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `380 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 35_440_000 picoseconds. - Weight::from_parts(34_652_647, 0) + // Minimum execution time: 31_269_000 picoseconds. + Weight::from_parts(30_661_898, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 517 - .saturating_add(Weight::from_parts(41_942, 0).saturating_mul(l.into())) - // Standard Error: 920 - .saturating_add(Weight::from_parts(66_074, 0).saturating_mul(s.into())) + // Standard Error: 1_394 + .saturating_add(Weight::from_parts(39_300, 0).saturating_mul(l.into())) + // Standard Error: 2_480 + .saturating_add(Weight::from_parts(78_849, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_other_unlocked(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `380 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 38_880_000 picoseconds. - Weight::from_parts(39_625_819, 0) + // Minimum execution time: 33_040_000 picoseconds. + Weight::from_parts(32_469_674, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_032 - .saturating_add(Weight::from_parts(29_856, 0).saturating_mul(l.into())) - // Standard Error: 1_837 - .saturating_add(Weight::from_parts(6_210, 0).saturating_mul(s.into())) + // Standard Error: 1_418 + .saturating_add(Weight::from_parts(44_206, 0).saturating_mul(l.into())) + // Standard Error: 2_523 + .saturating_add(Weight::from_parts(74_224, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[0, 27]`. fn vested_transfer(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `451 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 68_294_000 picoseconds. - Weight::from_parts(68_313_394, 0) + // Minimum execution time: 62_032_000 picoseconds. + Weight::from_parts(63_305_621, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 983 - .saturating_add(Weight::from_parts(48_156, 0).saturating_mul(l.into())) - // Standard Error: 1_750 - .saturating_add(Weight::from_parts(87_719, 0).saturating_mul(s.into())) + // Standard Error: 2_277 + .saturating_add(Weight::from_parts(42_767, 0).saturating_mul(l.into())) + // Standard Error: 4_051 + .saturating_add(Weight::from_parts(65_487, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[0, 27]`. fn force_vested_transfer(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `554 + l * (25 ±0) + s * (36 ±0)` // Estimated: `6196` - // Minimum execution time: 70_529_000 picoseconds. - Weight::from_parts(70_619_962, 0) + // Minimum execution time: 63_303_000 picoseconds. + Weight::from_parts(65_180_847, 0) .saturating_add(Weight::from_parts(0, 6196)) - // Standard Error: 1_259 - .saturating_add(Weight::from_parts(50_685, 0).saturating_mul(l.into())) - // Standard Error: 2_241 - .saturating_add(Weight::from_parts(91_444, 0).saturating_mul(s.into())) + // Standard Error: 2_220 + .saturating_add(Weight::from_parts(28_829, 0).saturating_mul(l.into())) + // Standard Error: 3_951 + .saturating_add(Weight::from_parts(84_970, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -192,59 +195,70 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[2, 28]`. - fn force_remove_vesting_schedule(l: u32, s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `555 + l * (25 ±0) + s * (36 ±0)` - // Estimated: `4764` - // Minimum execution time: 41_497_000 picoseconds. - Weight::from_parts(38_763_834, 4764) - // Standard Error: 2_030 - .saturating_add(Weight::from_parts(99_580, 0).saturating_mul(l.into())) - // Standard Error: 3_750 - .saturating_add(Weight::from_parts(132_188, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } fn not_unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `378 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 36_428_000 picoseconds. - Weight::from_parts(35_604_430, 0) + // Minimum execution time: 31_440_000 picoseconds. + Weight::from_parts(30_773_053, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 504 - .saturating_add(Weight::from_parts(43_191, 0).saturating_mul(l.into())) - // Standard Error: 931 - .saturating_add(Weight::from_parts(66_795, 0).saturating_mul(s.into())) + // Standard Error: 1_474 + .saturating_add(Weight::from_parts(43_019, 0).saturating_mul(l.into())) + // Standard Error: 2_723 + .saturating_add(Weight::from_parts(73_360, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[2, 28]`. fn unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `378 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 40_696_000 picoseconds. - Weight::from_parts(39_741_284, 0) + // Minimum execution time: 34_221_000 picoseconds. + Weight::from_parts(33_201_125, 0) + .saturating_add(Weight::from_parts(0, 4764)) + // Standard Error: 1_751 + .saturating_add(Weight::from_parts(44_088, 0).saturating_mul(l.into())) + // Standard Error: 3_234 + .saturating_add(Weight::from_parts(86_228, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `l` is `[0, 49]`. + /// The range of component `s` is `[2, 28]`. + fn force_remove_vesting_schedule(l: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `451 + l * (25 ±0) + s * (36 ±0)` + // Estimated: `4764` + // Minimum execution time: 35_553_000 picoseconds. + Weight::from_parts(34_974_083, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 478 - .saturating_add(Weight::from_parts(43_792, 0).saturating_mul(l.into())) - // Standard Error: 883 - .saturating_add(Weight::from_parts(66_540, 0).saturating_mul(s.into())) + // Standard Error: 1_560 + .saturating_add(Weight::from_parts(34_615, 0).saturating_mul(l.into())) + // Standard Error: 2_882 + .saturating_add(Weight::from_parts(83_419, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_whitelist.rs b/polkadot/runtime/rococo/src/weights/pallet_whitelist.rs index 7c307deec4c..ec67268d144 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_whitelist.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_whitelist.rs @@ -16,26 +16,28 @@ //! Autogenerated weights for `pallet_whitelist` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-08-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-aahe6cbd-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_whitelist // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json -// --pallet=pallet_whitelist -// --chain=rococo-dev -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,67 +52,75 @@ pub struct WeightInfo(PhantomData); impl pallet_whitelist::WeightInfo for WeightInfo { /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:1) + /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn whitelist_call() -> Weight { // Proof Size summary in bytes: // Measured: `223` // Estimated: `3556` - // Minimum execution time: 20_035_000 picoseconds. - Weight::from_parts(20_452_000, 0) + // Minimum execution time: 16_686_000 picoseconds. + Weight::from_parts(17_042_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:1) + /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn remove_whitelisted_call() -> Weight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `3556` - // Minimum execution time: 20_247_000 picoseconds. - Weight::from_parts(20_808_000, 0) + // Minimum execution time: 18_250_000 picoseconds. + Weight::from_parts(19_026_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:1 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) - /// Storage: `Preimage::StatusFor` (r:1 w:1) + /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 4194294]`. fn dispatch_whitelisted_call(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `428 + n * (1 ±0)` // Estimated: `3892 + n * (1 ±0)` - // Minimum execution time: 32_633_000 picoseconds. - Weight::from_parts(32_855_000, 0) + // Minimum execution time: 28_741_000 picoseconds. + Weight::from_parts(29_024_000, 0) .saturating_add(Weight::from_parts(0, 3892)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_223, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(3)) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_305, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:1) + /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 10000]`. fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `3556` - // Minimum execution time: 23_833_000 picoseconds. - Weight::from_parts(24_698_994, 0) + // Minimum execution time: 21_670_000 picoseconds. + Weight::from_parts(22_561_364, 0) .saturating_add(Weight::from_parts(0, 3556)) // Standard Error: 4 - .saturating_add(Weight::from_parts(1_454, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(Weight::from_parts(1_468, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs index 5544ca44658..d5cf33515e6 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs @@ -17,23 +17,25 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_xcm // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_xcm -// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -60,8 +62,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 25_043_000 picoseconds. - Weight::from_parts(25_682_000, 0) + // Minimum execution time: 25_521_000 picoseconds. + Weight::from_parts(25_922_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) @@ -80,8 +82,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 107_570_000 picoseconds. - Weight::from_parts(109_878_000, 0) + // Minimum execution time: 112_185_000 picoseconds. + Weight::from_parts(115_991_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -100,8 +102,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `232` // Estimated: `3697` - // Minimum execution time: 106_341_000 picoseconds. - Weight::from_parts(109_135_000, 0) + // Minimum execution time: 108_693_000 picoseconds. + Weight::from_parts(111_853_000, 0) .saturating_add(Weight::from_parts(0, 3697)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -120,8 +122,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 108_372_000 picoseconds. - Weight::from_parts(112_890_000, 0) + // Minimum execution time: 113_040_000 picoseconds. + Weight::from_parts(115_635_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -130,8 +132,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_957_000 picoseconds. - Weight::from_parts(7_417_000, 0) + // Minimum execution time: 6_979_000 picoseconds. + Weight::from_parts(7_342_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::SupportedVersion` (r:0 w:1) @@ -140,8 +142,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_053_000 picoseconds. - Weight::from_parts(7_462_000, 0) + // Minimum execution time: 7_144_000 picoseconds. + Weight::from_parts(7_297_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -149,8 +151,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_918_000 picoseconds. - Weight::from_parts(2_037_000, 0) + // Minimum execution time: 1_886_000 picoseconds. + Weight::from_parts(1_995_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::VersionNotifiers` (r:1 w:1) @@ -171,8 +173,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 30_417_000 picoseconds. - Weight::from_parts(31_191_000, 0) + // Minimum execution time: 31_238_000 picoseconds. + Weight::from_parts(31_955_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) @@ -193,8 +195,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `360` // Estimated: `3825` - // Minimum execution time: 36_666_000 picoseconds. - Weight::from_parts(37_779_000, 0) + // Minimum execution time: 37_237_000 picoseconds. + Weight::from_parts(38_569_000, 0) .saturating_add(Weight::from_parts(0, 3825)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -205,8 +207,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_869_000 picoseconds. - Weight::from_parts(2_003_000, 0) + // Minimum execution time: 1_884_000 picoseconds. + Weight::from_parts(2_028_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -216,8 +218,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `22` // Estimated: `13387` - // Minimum execution time: 16_188_000 picoseconds. - Weight::from_parts(16_435_000, 0) + // Minimum execution time: 16_048_000 picoseconds. + Weight::from_parts(16_617_000, 0) .saturating_add(Weight::from_parts(0, 13387)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -228,8 +230,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `26` // Estimated: `13391` - // Minimum execution time: 16_431_000 picoseconds. - Weight::from_parts(16_935_000, 0) + // Minimum execution time: 16_073_000 picoseconds. + Weight::from_parts(16_672_000, 0) .saturating_add(Weight::from_parts(0, 13391)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -240,8 +242,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `40` // Estimated: `15880` - // Minimum execution time: 18_460_000 picoseconds. - Weight::from_parts(18_885_000, 0) + // Minimum execution time: 18_422_000 picoseconds. + Weight::from_parts(18_900_000, 0) .saturating_add(Weight::from_parts(0, 15880)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -259,8 +261,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `216` // Estimated: `6156` - // Minimum execution time: 29_623_000 picoseconds. - Weight::from_parts(30_661_000, 0) + // Minimum execution time: 30_373_000 picoseconds. + Weight::from_parts(30_972_000, 0) .saturating_add(Weight::from_parts(0, 6156)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) @@ -271,8 +273,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `69` // Estimated: `10959` - // Minimum execution time: 12_043_000 picoseconds. - Weight::from_parts(12_360_000, 0) + // Minimum execution time: 11_863_000 picoseconds. + Weight::from_parts(12_270_000, 0) .saturating_add(Weight::from_parts(0, 10959)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -282,8 +284,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `33` // Estimated: `13398` - // Minimum execution time: 16_511_000 picoseconds. - Weight::from_parts(17_011_000, 0) + // Minimum execution time: 16_733_000 picoseconds. + Weight::from_parts(17_094_000, 0) .saturating_add(Weight::from_parts(0, 13398)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -302,8 +304,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `216` // Estimated: `13581` - // Minimum execution time: 39_041_000 picoseconds. - Weight::from_parts(39_883_000, 0) + // Minimum execution time: 39_236_000 picoseconds. + Weight::from_parts(40_587_000, 0) .saturating_add(Weight::from_parts(0, 13581)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(4)) @@ -316,8 +318,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 2_030_000 picoseconds. - Weight::from_parts(2_150_000, 0) + // Minimum execution time: 2_145_000 picoseconds. + Weight::from_parts(2_255_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -328,8 +330,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7576` // Estimated: `11041` - // Minimum execution time: 22_615_000 picoseconds. - Weight::from_parts(23_008_000, 0) + // Minimum execution time: 22_518_000 picoseconds. + Weight::from_parts(22_926_000, 0) .saturating_add(Weight::from_parts(0, 11041)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs new file mode 100644 index 00000000000..dc5e5d8ca4b --- /dev/null +++ b/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs @@ -0,0 +1,191 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Autogenerated weights for `pallet_xcm_benchmarks::fungible` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot +// benchmark +// pallet +// --chain=rococo-dev +// --steps=50 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_xcm_benchmarks::fungible +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs + +#![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_xcm_benchmarks::fungible`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_benchmarks::fungible::WeightInfo for WeightInfo { + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `101` + // Estimated: `3593` + // Minimum execution time: 27_223_000 picoseconds. + Weight::from_parts(27_947_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn transfer_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `101` + // Estimated: `6196` + // Minimum execution time: 36_502_000 picoseconds. + Weight::from_parts(37_023_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:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn transfer_reserve_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `281` + // Estimated: `6196` + // Minimum execution time: 85_152_000 picoseconds. + Weight::from_parts(86_442_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn reserve_asset_deposited() -> 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)) + } + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn initiate_reserve_withdraw() -> Weight { + // Proof Size summary in bytes: + // Measured: `281` + // Estimated: `3746` + // Minimum execution time: 56_571_000 picoseconds. + Weight::from_parts(58_163_000, 0) + .saturating_add(Weight::from_parts(0, 3746)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn receive_teleported_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `103` + // Estimated: `3593` + // Minimum execution time: 27_411_000 picoseconds. + Weight::from_parts(27_953_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn deposit_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `3593` + // Minimum execution time: 20_776_000 picoseconds. + Weight::from_parts(21_145_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn deposit_reserve_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 51_738_000 picoseconds. + Weight::from_parts(53_251_000, 0) + .saturating_add(Weight::from_parts(0, 3645)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn initiate_teleport() -> Weight { + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 39_333_000 picoseconds. + Weight::from_parts(40_515_000, 0) + .saturating_add(Weight::from_parts(0, 3645)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs new file mode 100644 index 00000000000..b62f36172ba --- /dev/null +++ b/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs @@ -0,0 +1,347 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Autogenerated weights for `pallet_xcm_benchmarks::generic` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot +// benchmark +// pallet +// --chain=rococo-dev +// --steps=50 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=pallet_xcm_benchmarks::generic +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs + +#![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_xcm_benchmarks::generic`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_benchmarks::generic::WeightInfo for WeightInfo { + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn report_holding() -> Weight { + // Proof Size summary in bytes: + // Measured: `281` + // Estimated: `3746` + // Minimum execution time: 55_210_000 picoseconds. + Weight::from_parts(56_613_000, 0) + .saturating_add(Weight::from_parts(0, 3746)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + fn buy_execution() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_246_000 picoseconds. + Weight::from_parts(1_339_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `XcmPallet::Queries` (r:1 w:0) + /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn query_response() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 5_377_000 picoseconds. + Weight::from_parts(5_549_000, 0) + .saturating_add(Weight::from_parts(0, 3465)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn transact() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_008_000 picoseconds. + Weight::from_parts(7_361_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn refund_surplus() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_700_000 picoseconds. + Weight::from_parts(1_848_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn set_error_handler() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_198_000 picoseconds. + Weight::from_parts(1_265_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn set_appendix() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_197_000 picoseconds. + Weight::from_parts(1_267_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn clear_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_193_000 picoseconds. + Weight::from_parts(1_258_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn descend_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_268_000 picoseconds. + Weight::from_parts(1_342_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn clear_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_173_000 picoseconds. + Weight::from_parts(1_248_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn report_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `281` + // Estimated: `3746` + // Minimum execution time: 53_715_000 picoseconds. + Weight::from_parts(54_860_000, 0) + .saturating_add(Weight::from_parts(0, 3746)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: `XcmPallet::AssetTraps` (r:1 w:1) + /// Proof: `XcmPallet::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn claim_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `23` + // Estimated: `3488` + // Minimum execution time: 8_621_000 picoseconds. + Weight::from_parts(8_903_000, 0) + .saturating_add(Weight::from_parts(0, 3488)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn trap() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_211_000 picoseconds. + Weight::from_parts(1_281_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `XcmPallet::VersionNotifyTargets` (r:1 w:1) + /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn subscribe_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 26_448_000 picoseconds. + Weight::from_parts(27_057_000, 0) + .saturating_add(Weight::from_parts(0, 3645)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: `XcmPallet::VersionNotifyTargets` (r:0 w:1) + /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn unsubscribe_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_498_000 picoseconds. + Weight::from_parts(3_614_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn burn_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_575_000 picoseconds. + Weight::from_parts(1_698_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn expect_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_334_000 picoseconds. + Weight::from_parts(1_435_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn expect_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_244_000 picoseconds. + Weight::from_parts(1_337_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn expect_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_244_000 picoseconds. + Weight::from_parts(1_331_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn expect_transact_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_407_000 picoseconds. + Weight::from_parts(1_522_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn query_pallet() -> Weight { + // Proof Size summary in bytes: + // Measured: `281` + // Estimated: `3746` + // Minimum execution time: 62_963_000 picoseconds. + Weight::from_parts(64_556_000, 0) + .saturating_add(Weight::from_parts(0, 3746)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + fn expect_pallet() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 8_458_000 picoseconds. + Weight::from_parts(8_741_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn report_transact_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `281` + // Estimated: `3746` + // Minimum execution time: 54_068_000 picoseconds. + Weight::from_parts(55_665_000, 0) + .saturating_add(Weight::from_parts(0, 3746)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + fn clear_transact_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_290_000 picoseconds. + Weight::from_parts(1_348_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn set_topic() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_189_000 picoseconds. + Weight::from_parts(1_268_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn clear_topic() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_197_000 picoseconds. + Weight::from_parts(1_276_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn set_fees_mode() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_197_000 picoseconds. + Weight::from_parts(1_253_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn unpaid_execution() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_250_000 picoseconds. + Weight::from_parts(1_354_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } +} diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs b/polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs index a6beeded428..f41a5d4ebf8 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs @@ -16,26 +16,28 @@ //! Autogenerated weights for `runtime_common::assigned_slots` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-08-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-ynta1nyy-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=runtime_common::assigned_slots // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json -// --pallet=runtime_common::assigned_slots -// --chain=rococo-dev -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -48,7 +50,7 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::assigned_slots`. pub struct WeightInfo(PhantomData); impl runtime_common::assigned_slots::WeightInfo for WeightInfo { - /// Storage: `Registrar::Paras` (r:1 w:1) + /// Storage: `Registrar::Paras` (r:1 w:0) /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Paras::ParaLifecycles` (r:1 w:1) /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -68,15 +70,15 @@ impl runtime_common::assigned_slots::WeightInfo for Wei /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) fn assign_perm_parachain_slot() -> Weight { // Proof Size summary in bytes: - // Measured: `673` - // Estimated: `4138` - // Minimum execution time: 84_646_000 picoseconds. - Weight::from_parts(91_791_000, 0) - .saturating_add(Weight::from_parts(0, 4138)) + // Measured: `730` + // Estimated: `4195` + // Minimum execution time: 71_337_000 picoseconds. + Weight::from_parts(80_807_000, 0) + .saturating_add(Weight::from_parts(0, 4195)) .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: `Registrar::Paras` (r:1 w:1) + /// Storage: `Registrar::Paras` (r:1 w:0) /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Paras::ParaLifecycles` (r:1 w:1) /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -98,13 +100,13 @@ impl runtime_common::assigned_slots::WeightInfo for Wei /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) fn assign_temp_parachain_slot() -> Weight { // Proof Size summary in bytes: - // Measured: `673` - // Estimated: `4138` - // Minimum execution time: 68_091_000 picoseconds. - Weight::from_parts(77_310_000, 0) - .saturating_add(Weight::from_parts(0, 4138)) + // Measured: `730` + // Estimated: `4195` + // Minimum execution time: 60_188_000 picoseconds. + Weight::from_parts(63_932_000, 0) + .saturating_add(Weight::from_parts(0, 4195)) .saturating_add(T::DbWeight::get().reads(10)) - .saturating_add(T::DbWeight::get().writes(7)) + .saturating_add(T::DbWeight::get().writes(6)) } /// Storage: `AssignedSlots::PermanentSlots` (r:1 w:0) /// Proof: `AssignedSlots::PermanentSlots` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) @@ -118,11 +120,11 @@ impl runtime_common::assigned_slots::WeightInfo for Wei /// Proof: `AssignedSlots::TemporarySlotCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn unassign_parachain_slot() -> Weight { // Proof Size summary in bytes: - // Measured: `823` - // Estimated: `4288` - // Minimum execution time: 38_081_000 picoseconds. - Weight::from_parts(40_987_000, 0) - .saturating_add(Weight::from_parts(0, 4288)) + // Measured: `856` + // Estimated: `4321` + // Minimum execution time: 35_764_000 picoseconds. + Weight::from_parts(38_355_000, 0) + .saturating_add(Weight::from_parts(0, 4321)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -132,8 +134,8 @@ impl runtime_common::assigned_slots::WeightInfo for Wei // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_182_000 picoseconds. - Weight::from_parts(7_437_000, 0) + // Minimum execution time: 4_634_000 picoseconds. + Weight::from_parts(4_852_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -143,8 +145,8 @@ impl runtime_common::assigned_slots::WeightInfo for Wei // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_153_000 picoseconds. - Weight::from_parts(7_456_000, 0) + // Minimum execution time: 4_563_000 picoseconds. + Weight::from_parts(4_829_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs b/polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs index 3cd7c7a47e9..2b756802289 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::auctions` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_common::auctions // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_common_auctions.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,92 +50,90 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::auctions`. pub struct WeightInfo(PhantomData); impl runtime_common::auctions::WeightInfo for WeightInfo { - /// Storage: Auctions AuctionInfo (r:1 w:1) - /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Auctions AuctionCounter (r:1 w:1) - /// Proof: Auctions AuctionCounter (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Auctions::AuctionInfo` (r:1 w:1) + /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Auctions::AuctionCounter` (r:1 w:1) + /// Proof: `Auctions::AuctionCounter` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn new_auction() -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `1493` - // Minimum execution time: 12_805_000 picoseconds. - Weight::from_parts(13_153_000, 0) + // Minimum execution time: 7_307_000 picoseconds. + Weight::from_parts(7_680_000, 0) .saturating_add(Weight::from_parts(0, 1493)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Paras ParaLifecycles (r:1 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Auctions AuctionCounter (r:1 w:0) - /// Proof: Auctions AuctionCounter (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Auctions AuctionInfo (r:1 w:0) - /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Slots Leases (r:1 w:0) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) - /// Storage: Auctions Winning (r:1 w:1) - /// Proof: Auctions Winning (max_values: None, max_size: Some(1920), added: 4395, mode: MaxEncodedLen) - /// Storage: Auctions ReservedAmounts (r:2 w:2) - /// Proof: Auctions ReservedAmounts (max_values: None, max_size: Some(60), added: 2535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Auctions::AuctionCounter` (r:1 w:0) + /// Proof: `Auctions::AuctionCounter` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Auctions::AuctionInfo` (r:1 w:0) + /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Slots::Leases` (r:1 w:0) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Auctions::Winning` (r:1 w:1) + /// Proof: `Auctions::Winning` (`max_values`: None, `max_size`: Some(1920), added: 4395, mode: `MaxEncodedLen`) + /// Storage: `Auctions::ReservedAmounts` (r:2 w:2) + /// Proof: `Auctions::ReservedAmounts` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn bid() -> Weight { // Proof Size summary in bytes: - // Measured: `728` + // Measured: `761` // Estimated: `6060` - // Minimum execution time: 77_380_000 picoseconds. - Weight::from_parts(80_503_000, 0) + // Minimum execution time: 75_448_000 picoseconds. + Weight::from_parts(78_716_000, 0) .saturating_add(Weight::from_parts(0, 6060)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Auctions AuctionInfo (r:1 w:1) - /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Babe NextRandomness (r:1 w:0) - /// Proof: Babe NextRandomness (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: Babe EpochStart (r:1 w:0) - /// Proof: Babe EpochStart (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Auctions AuctionCounter (r:1 w:0) - /// Proof: Auctions AuctionCounter (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Auctions Winning (r:3600 w:3600) - /// Proof: Auctions Winning (max_values: None, max_size: Some(1920), added: 4395, mode: MaxEncodedLen) - /// Storage: Auctions ReservedAmounts (r:37 w:36) - /// Proof: Auctions ReservedAmounts (max_values: None, max_size: Some(60), added: 2535, mode: MaxEncodedLen) - /// Storage: System Account (r:36 w:36) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Slots Leases (r:2 w:2) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:1) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ActionsQueue (r:1 w:1) - /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) - /// Storage: Registrar Paras (r:1 w:1) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: `Auctions::AuctionInfo` (r:1 w:1) + /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Babe::NextRandomness` (r:1 w:0) + /// Proof: `Babe::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `Babe::EpochStart` (r:1 w:0) + /// Proof: `Babe::EpochStart` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Auctions::AuctionCounter` (r:1 w:0) + /// Proof: `Auctions::AuctionCounter` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Auctions::Winning` (r:3600 w:3600) + /// Proof: `Auctions::Winning` (`max_values`: None, `max_size`: Some(1920), added: 4395, mode: `MaxEncodedLen`) + /// Storage: `Auctions::ReservedAmounts` (r:37 w:36) + /// Proof: `Auctions::ReservedAmounts` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:36 w:36) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Slots::Leases` (r:2 w:2) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:1) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ActionsQueue` (r:1 w:1) + /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) fn on_initialize() -> Weight { // Proof Size summary in bytes: - // Measured: `6947789` + // Measured: `6947017` // Estimated: `15822990` - // Minimum execution time: 6_311_055_000 picoseconds. - Weight::from_parts(6_409_142_000, 0) + // Minimum execution time: 7_120_207_000 picoseconds. + Weight::from_parts(7_273_496_000, 0) .saturating_add(Weight::from_parts(0, 15822990)) - .saturating_add(T::DbWeight::get().reads(3683)) - .saturating_add(T::DbWeight::get().writes(3678)) + .saturating_add(T::DbWeight::get().reads(3682)) + .saturating_add(T::DbWeight::get().writes(3677)) } - /// Storage: Auctions ReservedAmounts (r:37 w:36) - /// Proof: Auctions ReservedAmounts (max_values: None, max_size: Some(60), added: 2535, mode: MaxEncodedLen) - /// Storage: System Account (r:36 w:36) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Auctions Winning (r:3600 w:3600) - /// Proof: Auctions Winning (max_values: None, max_size: Some(1920), added: 4395, mode: MaxEncodedLen) - /// Storage: Auctions AuctionInfo (r:0 w:1) - /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Auctions::ReservedAmounts` (r:37 w:36) + /// Proof: `Auctions::ReservedAmounts` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:36 w:36) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Auctions::Winning` (r:3600 w:3600) + /// Proof: `Auctions::Winning` (`max_values`: None, `max_size`: Some(1920), added: 4395, mode: `MaxEncodedLen`) + /// Storage: `Auctions::AuctionInfo` (r:0 w:1) + /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn cancel_auction() -> Weight { // Proof Size summary in bytes: // Measured: `177732` // Estimated: `15822990` - // Minimum execution time: 4_849_561_000 picoseconds. - Weight::from_parts(4_955_226_000, 0) + // Minimum execution time: 5_536_281_000 picoseconds. + Weight::from_parts(5_675_163_000, 0) .saturating_add(Weight::from_parts(0, 15822990)) .saturating_add(T::DbWeight::get().reads(3673)) .saturating_add(T::DbWeight::get().writes(3673)) diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_claims.rs b/polkadot/runtime/rococo/src/weights/runtime_common_claims.rs index 52e0dd24afa..de2bb71933b 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_claims.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_claims.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::claims` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_common::claims // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_common_claims.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_common_claims.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,120 +50,133 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::claims`. pub struct WeightInfo(PhantomData); impl runtime_common::claims::WeightInfo for WeightInfo { - /// Storage: Claims Claims (r:1 w:1) - /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Signing (r:1 w:1) - /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Total (r:1 w:1) - /// Proof Skipped: Claims Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Claims Vesting (r:1 w:1) - /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `Claims::Claims` (r:1 w:1) + /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Signing` (r:1 w:1) + /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Total` (r:1 w:1) + /// Proof: `Claims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Vesting` (r:1 w:1) + /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) fn claim() -> Weight { // Proof Size summary in bytes: // Measured: `558` // Estimated: `4764` - // Minimum execution time: 144_931_000 picoseconds. - Weight::from_parts(156_550_000, 0) + // Minimum execution time: 181_028_000 picoseconds. + Weight::from_parts(194_590_000, 0) .saturating_add(Weight::from_parts(0, 4764)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: Claims Total (r:1 w:1) - /// Proof Skipped: Claims Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Claims Vesting (r:0 w:1) - /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Claims (r:0 w:1) - /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Signing (r:0 w:1) - /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) + /// Storage: `Claims::Total` (r:1 w:1) + /// Proof: `Claims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Vesting` (r:0 w:1) + /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Claims` (r:0 w:1) + /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Signing` (r:0 w:1) + /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) fn mint_claim() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `1701` - // Minimum execution time: 11_300_000 picoseconds. - Weight::from_parts(11_642_000, 0) + // Minimum execution time: 11_224_000 picoseconds. + Weight::from_parts(13_342_000, 0) .saturating_add(Weight::from_parts(0, 1701)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Claims Claims (r:1 w:1) - /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Signing (r:1 w:1) - /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Total (r:1 w:1) - /// Proof Skipped: Claims Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Claims Vesting (r:1 w:1) - /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `Claims::Claims` (r:1 w:1) + /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Signing` (r:1 w:1) + /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Total` (r:1 w:1) + /// Proof: `Claims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Vesting` (r:1 w:1) + /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) fn claim_attest() -> Weight { // Proof Size summary in bytes: // Measured: `558` // Estimated: `4764` - // Minimum execution time: 149_112_000 picoseconds. - Weight::from_parts(153_872_000, 0) + // Minimum execution time: 187_964_000 picoseconds. + Weight::from_parts(202_553_000, 0) .saturating_add(Weight::from_parts(0, 4764)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: Claims Preclaims (r:1 w:1) - /// Proof Skipped: Claims Preclaims (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Signing (r:1 w:1) - /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Claims (r:1 w:1) - /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Total (r:1 w:1) - /// Proof Skipped: Claims Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Claims Vesting (r:1 w:1) - /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) - /// Storage: Vesting Vesting (r:1 w:1) - /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `Claims::Preclaims` (r:1 w:1) + /// Proof: `Claims::Preclaims` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Signing` (r:1 w:1) + /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Claims` (r:1 w:1) + /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Total` (r:1 w:1) + /// Proof: `Claims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Vesting` (r:1 w:1) + /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Vesting::Vesting` (r:1 w:1) + /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) fn attest() -> Weight { // Proof Size summary in bytes: // Measured: `632` // Estimated: `4764` - // Minimum execution time: 69_619_000 picoseconds. - Weight::from_parts(79_242_000, 0) + // Minimum execution time: 78_210_000 picoseconds. + Weight::from_parts(84_581_000, 0) .saturating_add(Weight::from_parts(0, 4764)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: Claims Claims (r:1 w:2) - /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Vesting (r:1 w:2) - /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Signing (r:1 w:2) - /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) - /// Storage: Claims Preclaims (r:1 w:1) - /// Proof Skipped: Claims Preclaims (max_values: None, max_size: None, mode: Measured) + /// Storage: `Claims::Claims` (r:1 w:2) + /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Vesting` (r:1 w:2) + /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Signing` (r:1 w:2) + /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Preclaims` (r:1 w:1) + /// Proof: `Claims::Preclaims` (`max_values`: None, `max_size`: None, mode: `Measured`) fn move_claim() -> Weight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `3905` - // Minimum execution time: 22_066_000 picoseconds. - Weight::from_parts(22_483_000, 0) + // Minimum execution time: 33_940_000 picoseconds. + Weight::from_parts(48_438_000, 0) .saturating_add(Weight::from_parts(0, 3905)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(7)) } + /// Storage: `Claims::Preclaims` (r:1 w:0) + /// Proof: `Claims::Preclaims` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Claims::Signing` (r:1 w:0) + /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn prevalidate_attests() -> Weight { + // Proof Size summary in bytes: + // Measured: `296` + // Estimated: `3761` + // Minimum execution time: 9_025_000 picoseconds. + Weight::from_parts(10_563_000, 0) + .saturating_add(Weight::from_parts(0, 3761)) + .saturating_add(T::DbWeight::get().reads(2)) + } } diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs b/polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs new file mode 100644 index 00000000000..d068f07e759 --- /dev/null +++ b/polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs @@ -0,0 +1,86 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Autogenerated weights for `runtime_common::coretime` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot +// benchmark +// pallet +// --chain=rococo-dev +// --steps=50 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=runtime_common::coretime +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs + +#![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 `runtime_common::coretime`. +pub struct WeightInfo(PhantomData); +impl runtime_common::coretime::WeightInfo for WeightInfo { + /// Storage: `Configuration::PendingConfigs` (r:1 w:1) + /// Proof: `Configuration::PendingConfigs` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Configuration::BypassConsistencyCheck` (r:1 w:0) + /// Proof: `Configuration::BypassConsistencyCheck` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn request_core_count() -> Weight { + // Proof Size summary in bytes: + // Measured: `151` + // Estimated: `1636` + // Minimum execution time: 7_543_000 picoseconds. + Weight::from_parts(7_745_000, 0) + .saturating_add(Weight::from_parts(0, 1636)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreSchedules` (r:0 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreSchedules` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `s` is `[1, 100]`. + fn assign_core(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 9_367_000 picoseconds. + Weight::from_parts(9_932_305, 0) + .saturating_add(Weight::from_parts(0, 3645)) + // Standard Error: 231 + .saturating_add(Weight::from_parts(12_947, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs b/polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs index 0e7420cba2e..8ebab3d551e 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::crowdloan` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_common::crowdloan // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_common_crowdloan.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,172 +50,168 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::crowdloan`. pub struct WeightInfo(PhantomData); impl runtime_common::crowdloan::WeightInfo for WeightInfo { - /// Storage: Crowdloan Funds (r:1 w:1) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) - /// Storage: Registrar Paras (r:1 w:1) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Crowdloan NextFundIndex (r:1 w:1) - /// Proof Skipped: Crowdloan NextFundIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Crowdloan::Funds` (r:1 w:1) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Crowdloan::NextFundIndex` (r:1 w:1) + /// Proof: `Crowdloan::NextFundIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `438` // Estimated: `3903` - // Minimum execution time: 50_399_000 picoseconds. - Weight::from_parts(51_641_000, 0) + // Minimum execution time: 46_095_000 picoseconds. + Weight::from_parts(48_111_000, 0) .saturating_add(Weight::from_parts(0, 3903)) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Crowdloan Funds (r:1 w:1) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) - /// Storage: Slots Leases (r:1 w:0) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) - /// Storage: Auctions AuctionInfo (r:1 w:0) - /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances InactiveIssuance (r:1 w:1) - /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Crowdloan EndingsCount (r:1 w:0) - /// Proof Skipped: Crowdloan EndingsCount (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Crowdloan NewRaise (r:1 w:1) - /// Proof Skipped: Crowdloan NewRaise (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) - /// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) + /// Storage: `Crowdloan::Funds` (r:1 w:1) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Slots::Leases` (r:1 w:0) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Auctions::AuctionInfo` (r:1 w:0) + /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Crowdloan::EndingsCount` (r:1 w:0) + /// Proof: `Crowdloan::EndingsCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Crowdloan::NewRaise` (r:1 w:1) + /// Proof: `Crowdloan::NewRaise` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) + /// Proof: UNKNOWN KEY `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) fn contribute() -> Weight { // Proof Size summary in bytes: - // Measured: `530` - // Estimated: `3995` - // Minimum execution time: 128_898_000 picoseconds. - Weight::from_parts(130_277_000, 0) - .saturating_add(Weight::from_parts(0, 3995)) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(5)) + // Measured: `563` + // Estimated: `4028` + // Minimum execution time: 133_059_000 picoseconds. + Weight::from_parts(136_515_000, 0) + .saturating_add(Weight::from_parts(0, 4028)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Crowdloan Funds (r:1 w:1) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances InactiveIssuance (r:1 w:1) - /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: unknown `0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0` (r:1 w:1) - /// Proof Skipped: unknown `0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0` (r:1 w:1) + /// Storage: `Crowdloan::Funds` (r:1 w:1) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0` (r:1 w:1) + /// Proof: UNKNOWN KEY `0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0` (r:1 w:1) fn withdraw() -> Weight { // Proof Size summary in bytes: - // Measured: `689` + // Measured: `687` // Estimated: `6196` - // Minimum execution time: 69_543_000 picoseconds. - Weight::from_parts(71_522_000, 0) + // Minimum execution time: 71_733_000 picoseconds. + Weight::from_parts(74_034_000, 0) .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `k` is `[0, 1000]`. fn refund(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `127 + k * (189 ±0)` - // Estimated: `140 + k * (189 ±0)` - // Minimum execution time: 50_735_000 picoseconds. - Weight::from_parts(52_282_000, 0) - .saturating_add(Weight::from_parts(0, 140)) - // Standard Error: 21_607 - .saturating_add(Weight::from_parts(38_955_985, 0).saturating_mul(k.into())) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `125 + k * (189 ±0)` + // Estimated: `138 + k * (189 ±0)` + // Minimum execution time: 46_016_000 picoseconds. + Weight::from_parts(48_260_000, 0) + .saturating_add(Weight::from_parts(0, 138)) + // Standard Error: 21_140 + .saturating_add(Weight::from_parts(39_141_925, 0).saturating_mul(k.into())) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(k.into()))) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(k.into()))) .saturating_add(Weight::from_parts(0, 189).saturating_mul(k.into())) } - /// Storage: Crowdloan Funds (r:1 w:1) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Crowdloan::Funds` (r:1 w:1) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn dissolve() -> Weight { // Proof Size summary in bytes: - // Measured: `515` + // Measured: `514` // Estimated: `6196` - // Minimum execution time: 43_100_000 picoseconds. - Weight::from_parts(44_272_000, 0) + // Minimum execution time: 44_724_000 picoseconds. + Weight::from_parts(47_931_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Crowdloan Funds (r:1 w:1) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: `Crowdloan::Funds` (r:1 w:1) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) fn edit() -> Weight { // Proof Size summary in bytes: - // Measured: `235` - // Estimated: `3700` - // Minimum execution time: 18_702_000 picoseconds. - Weight::from_parts(19_408_000, 0) - .saturating_add(Weight::from_parts(0, 3700)) + // Measured: `234` + // Estimated: `3699` + // Minimum execution time: 19_512_000 picoseconds. + Weight::from_parts(21_129_000, 0) + .saturating_add(Weight::from_parts(0, 3699)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Crowdloan Funds (r:1 w:0) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) - /// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) - /// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) + /// Storage: `Crowdloan::Funds` (r:1 w:0) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: UNKNOWN KEY `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) + /// Proof: UNKNOWN KEY `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) fn add_memo() -> Weight { // Proof Size summary in bytes: // Measured: `412` // Estimated: `3877` - // Minimum execution time: 25_568_000 picoseconds. - Weight::from_parts(26_203_000, 0) + // Minimum execution time: 33_529_000 picoseconds. + Weight::from_parts(37_082_000, 0) .saturating_add(Weight::from_parts(0, 3877)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Crowdloan Funds (r:1 w:0) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) - /// Storage: Crowdloan NewRaise (r:1 w:1) - /// Proof Skipped: Crowdloan NewRaise (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Crowdloan::Funds` (r:1 w:0) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Crowdloan::NewRaise` (r:1 w:1) + /// Proof: `Crowdloan::NewRaise` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn poke() -> Weight { // Proof Size summary in bytes: - // Measured: `239` - // Estimated: `3704` - // Minimum execution time: 17_832_000 picoseconds. - Weight::from_parts(18_769_000, 0) - .saturating_add(Weight::from_parts(0, 3704)) + // Measured: `238` + // Estimated: `3703` + // Minimum execution time: 23_153_000 picoseconds. + Weight::from_parts(24_181_000, 0) + .saturating_add(Weight::from_parts(0, 3703)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Auctions AuctionInfo (r:1 w:0) - /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Crowdloan EndingsCount (r:1 w:1) - /// Proof Skipped: Crowdloan EndingsCount (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Crowdloan NewRaise (r:1 w:1) - /// Proof Skipped: Crowdloan NewRaise (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Crowdloan Funds (r:100 w:0) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) - /// Storage: Auctions AuctionCounter (r:1 w:0) - /// Proof: Auctions AuctionCounter (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Paras ParaLifecycles (r:100 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Slots Leases (r:100 w:0) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) - /// Storage: Auctions Winning (r:1 w:1) - /// Proof: Auctions Winning (max_values: None, max_size: Some(1920), added: 4395, mode: MaxEncodedLen) - /// Storage: Auctions ReservedAmounts (r:100 w:100) - /// Proof: Auctions ReservedAmounts (max_values: None, max_size: Some(60), added: 2535, mode: MaxEncodedLen) - /// Storage: System Account (r:100 w:100) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Auctions::AuctionInfo` (r:1 w:0) + /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Crowdloan::EndingsCount` (r:1 w:1) + /// Proof: `Crowdloan::EndingsCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Crowdloan::NewRaise` (r:1 w:1) + /// Proof: `Crowdloan::NewRaise` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Crowdloan::Funds` (r:100 w:0) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Auctions::AuctionCounter` (r:1 w:0) + /// Proof: `Auctions::AuctionCounter` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Paras::ParaLifecycles` (r:100 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Slots::Leases` (r:100 w:0) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Auctions::Winning` (r:1 w:1) + /// Proof: `Auctions::Winning` (`max_values`: None, `max_size`: Some(1920), added: 4395, mode: `MaxEncodedLen`) + /// Storage: `Auctions::ReservedAmounts` (r:100 w:100) + /// Proof: `Auctions::ReservedAmounts` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:100 w:100) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `n` is `[2, 100]`. fn on_initialize(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `197 + n * (356 ±0)` + // Measured: `229 + n * (356 ±0)` // Estimated: `5385 + n * (2832 ±0)` - // Minimum execution time: 128_319_000 picoseconds. - Weight::from_parts(130_877_000, 0) + // Minimum execution time: 120_164_000 picoseconds. + Weight::from_parts(3_390_119, 0) .saturating_add(Weight::from_parts(0, 5385)) - // Standard Error: 61_381 - .saturating_add(Weight::from_parts(60_209_202, 0).saturating_mul(n.into())) + // Standard Error: 41_727 + .saturating_add(Weight::from_parts(54_453_016, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs b/polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs index cec357453b6..9b0cb98e6c0 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs @@ -1,36 +1,43 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Polkadot. -// 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. +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . //! Autogenerated weights for `runtime_common::identity_migrator` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-07, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `sbtb`, CPU: `13th Gen Intel(R) Core(TM) i7-1365U` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/release/polkadot +// ./target/production/polkadot // benchmark // pallet // --chain=rococo-dev -// --steps=2 -// --repeat=1 +// --steps=50 +// --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_common::identity_migrator // --extrinsic=* -// --output=./migrator-release.rs +// --execution=wasm +// --wasm-execution=compiled +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -44,7 +51,7 @@ use core::marker::PhantomData; pub struct WeightInfo(PhantomData); impl runtime_common::identity_migrator::WeightInfo for WeightInfo { /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// Storage: `Identity::SubsOf` (r:1 w:1) /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:2 w:2) @@ -63,34 +70,34 @@ impl runtime_common::identity_migrator::WeightInfo for /// The range of component `s` is `[0, 100]`. fn reap_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7292 + r * (8 ±0) + s * (32 ±0)` - // Estimated: `11003 + r * (8 ±0) + s * (33 ±0)` - // Minimum execution time: 163_756_000 picoseconds. - Weight::from_parts(158_982_500, 0) - .saturating_add(Weight::from_parts(0, 11003)) - // Standard Error: 1_143_629 - .saturating_add(Weight::from_parts(238_675, 0).saturating_mul(r.into())) - // Standard Error: 228_725 - .saturating_add(Weight::from_parts(1_529_645, 0).saturating_mul(s.into())) + // Measured: `7457 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11037 + r * (7 ±0) + s * (32 ±0)` + // Minimum execution time: 157_343_000 picoseconds. + Weight::from_parts(159_289_236, 0) + .saturating_add(Weight::from_parts(0, 11037)) + // Standard Error: 16_439 + .saturating_add(Weight::from_parts(224_293, 0).saturating_mul(r.into())) + // Standard Error: 3_367 + .saturating_add(Weight::from_parts(1_383_637, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes(6)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) - .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) - .saturating_add(Weight::from_parts(0, 33).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 32).saturating_mul(s.into())) } /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Identity::SubsOf` (r:1 w:1) /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) fn poke_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `7229` - // Estimated: `11003` - // Minimum execution time: 137_570_000 picoseconds. - Weight::from_parts(137_570_000, 0) - .saturating_add(Weight::from_parts(0, 11003)) + // Measured: `7242` + // Estimated: `11037` + // Minimum execution time: 114_384_000 picoseconds. + Weight::from_parts(115_741_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs b/polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs index 0a56562a1a9..e066106e134 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::paras_registrar` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_common::paras_registrar // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_common_paras_registrar.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,175 +50,169 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::paras_registrar`. pub struct WeightInfo(PhantomData); impl runtime_common::paras_registrar::WeightInfo for WeightInfo { - /// Storage: Registrar NextFreeParaId (r:1 w:1) - /// Proof Skipped: Registrar NextFreeParaId (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Registrar Paras (r:1 w:1) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: `Registrar::NextFreeParaId` (r:1 w:1) + /// Proof: `Registrar::NextFreeParaId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:1) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) fn reserve() -> Weight { // Proof Size summary in bytes: - // Measured: `97` - // Estimated: `3562` - // Minimum execution time: 29_948_000 picoseconds. - Weight::from_parts(30_433_000, 0) - .saturating_add(Weight::from_parts(0, 3562)) + // Measured: `96` + // Estimated: `3561` + // Minimum execution time: 24_109_000 picoseconds. + Weight::from_parts(24_922_000, 0) + .saturating_add(Weight::from_parts(0, 3561)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Registrar Paras (r:1 w:1) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:1) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CodeByHash (r:1 w:1) - /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteList (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras CodeByHashRefs (r:1 w:1) - /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CurrentCodeHash (r:0 w:1) - /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpcomingParasGenesis (r:0 w:1) - /// Proof Skipped: Paras UpcomingParasGenesis (max_values: None, max_size: None, mode: Measured) + /// Storage: `Registrar::Paras` (r:1 w:1) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:1) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHash` (r:1 w:1) + /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) + /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:0 w:1) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpcomingParasGenesis` (r:0 w:1) + /// Proof: `Paras::UpcomingParasGenesis` (`max_values`: None, `max_size`: None, mode: `Measured`) fn register() -> Weight { // Proof Size summary in bytes: - // Measured: `616` - // Estimated: `4081` - // Minimum execution time: 6_332_113_000 picoseconds. - Weight::from_parts(6_407_158_000, 0) - .saturating_add(Weight::from_parts(0, 4081)) - .saturating_add(T::DbWeight::get().reads(8)) + // Measured: `352` + // Estimated: `3817` + // Minimum execution time: 7_207_580_000 picoseconds. + Weight::from_parts(7_298_567_000, 0) + .saturating_add(Weight::from_parts(0, 3817)) + .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(8)) } - /// Storage: Registrar Paras (r:1 w:1) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:1) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CodeByHash (r:1 w:1) - /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteList (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras CodeByHashRefs (r:1 w:1) - /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CurrentCodeHash (r:0 w:1) - /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpcomingParasGenesis (r:0 w:1) - /// Proof Skipped: Paras UpcomingParasGenesis (max_values: None, max_size: None, mode: Measured) + /// Storage: `Registrar::Paras` (r:1 w:1) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:1) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHash` (r:1 w:1) + /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) + /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:0 w:1) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpcomingParasGenesis` (r:0 w:1) + /// Proof: `Paras::UpcomingParasGenesis` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_register() -> Weight { // Proof Size summary in bytes: - // Measured: `533` - // Estimated: `3998` - // Minimum execution time: 6_245_403_000 picoseconds. - Weight::from_parts(6_289_575_000, 0) - .saturating_add(Weight::from_parts(0, 3998)) - .saturating_add(T::DbWeight::get().reads(8)) + // Measured: `269` + // Estimated: `3734` + // Minimum execution time: 7_196_460_000 picoseconds. + Weight::from_parts(7_385_729_000, 0) + .saturating_add(Weight::from_parts(0, 3734)) + .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(8)) } - /// Storage: Registrar Paras (r:1 w:1) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:1) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras FutureCodeHash (r:1 w:0) - /// Proof Skipped: Paras FutureCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ActionsQueue (r:1 w:1) - /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) - /// Storage: MessageQueue BookStateFor (r:1 w:0) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) - /// Storage: Registrar PendingSwap (r:0 w:1) - /// Proof Skipped: Registrar PendingSwap (max_values: None, max_size: None, mode: Measured) + /// Storage: `Registrar::Paras` (r:1 w:1) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:1) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeHash` (r:1 w:0) + /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ActionsQueue` (r:1 w:1) + /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `Registrar::PendingSwap` (r:0 w:1) + /// Proof: `Registrar::PendingSwap` (`max_values`: None, `max_size`: None, mode: `Measured`) fn deregister() -> Weight { // Proof Size summary in bytes: - // Measured: `476` - // Estimated: `3941` - // Minimum execution time: 49_822_000 picoseconds. - Weight::from_parts(50_604_000, 0) - .saturating_add(Weight::from_parts(0, 3941)) + // Measured: `499` + // Estimated: `3964` + // Minimum execution time: 54_761_000 picoseconds. + Weight::from_parts(57_931_000, 0) + .saturating_add(Weight::from_parts(0, 3964)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Registrar Paras (r:1 w:0) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:2 w:2) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Registrar PendingSwap (r:1 w:1) - /// Proof Skipped: Registrar PendingSwap (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ActionsQueue (r:1 w:1) - /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) - /// Storage: Crowdloan Funds (r:2 w:2) - /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) - /// Storage: Slots Leases (r:2 w:2) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:2 w:2) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::PendingSwap` (r:1 w:1) + /// Proof: `Registrar::PendingSwap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ActionsQueue` (r:1 w:1) + /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Crowdloan::Funds` (r:2 w:2) + /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Slots::Leases` (r:2 w:2) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) fn swap() -> Weight { // Proof Size summary in bytes: - // Measured: `780` - // Estimated: `6720` - // Minimum execution time: 55_166_000 picoseconds. - Weight::from_parts(56_913_000, 0) - .saturating_add(Weight::from_parts(0, 6720)) + // Measured: `837` + // Estimated: `6777` + // Minimum execution time: 59_564_000 picoseconds. + Weight::from_parts(62_910_000, 0) + .saturating_add(Weight::from_parts(0, 6777)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(8)) } - /// Storage: Paras FutureCodeHash (r:1 w:1) - /// Proof Skipped: Paras FutureCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeRestrictionSignal (r:1 w:1) - /// Proof Skipped: Paras UpgradeRestrictionSignal (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras CurrentCodeHash (r:1 w:0) - /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeCooldowns (r:1 w:1) - /// Proof Skipped: Paras UpgradeCooldowns (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CodeByHash (r:1 w:1) - /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteList (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras CodeByHashRefs (r:1 w:1) - /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) - /// The range of component `b` is `[1, 3145728]`. + /// Storage: `Paras::FutureCodeHash` (r:1 w:1) + /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeRestrictionSignal` (r:1 w:1) + /// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeCooldowns` (r:1 w:1) + /// Proof: `Paras::UpgradeCooldowns` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHash` (r:1 w:1) + /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) + /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `b` is `[9, 3145728]`. fn schedule_code_upgrade(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `464` - // Estimated: `3929` - // Minimum execution time: 43_650_000 picoseconds. - Weight::from_parts(43_918_000, 0) - .saturating_add(Weight::from_parts(0, 3929)) - // Standard Error: 6 - .saturating_add(Weight::from_parts(2_041, 0).saturating_mul(b.into())) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `201` + // Estimated: `3666` + // Minimum execution time: 33_106_000 picoseconds. + Weight::from_parts(33_526_000, 0) + .saturating_add(Weight::from_parts(0, 3666)) + // Standard Error: 2 + .saturating_add(Weight::from_parts(2_334, 0).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: Paras Heads (r:0 w:1) - /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `b` is `[1, 1048576]`. fn set_current_head(b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_666_000 picoseconds. - Weight::from_parts(8_893_000, 0) + // Minimum execution time: 5_992_000 picoseconds. + Weight::from_parts(12_059_689, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(855, 0).saturating_mul(b.into())) + // Standard Error: 0 + .saturating_add(Weight::from_parts(959, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_slots.rs b/polkadot/runtime/rococo/src/weights/runtime_common_slots.rs index 23ab1ed3ee0..dd10dbbf1f1 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_slots.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_slots.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::slots` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_common::slots // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_common_slots.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_common_slots.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,86 +50,82 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::slots`. pub struct WeightInfo(PhantomData); impl runtime_common::slots::WeightInfo for WeightInfo { - /// Storage: Slots Leases (r:1 w:1) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Slots::Leases` (r:1 w:1) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_lease() -> Weight { // Proof Size summary in bytes: - // Measured: `287` - // Estimated: `3752` - // Minimum execution time: 29_932_000 picoseconds. - Weight::from_parts(30_334_000, 0) - .saturating_add(Weight::from_parts(0, 3752)) + // Measured: `320` + // Estimated: `3785` + // Minimum execution time: 26_570_000 picoseconds. + Weight::from_parts(27_619_000, 0) + .saturating_add(Weight::from_parts(0, 3785)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Paras Parachains (r:1 w:0) - /// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Slots Leases (r:101 w:100) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:200 w:200) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ActionsQueue (r:1 w:1) - /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) - /// Storage: Registrar Paras (r:100 w:100) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::Parachains` (r:1 w:0) + /// Proof: `Paras::Parachains` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Slots::Leases` (r:101 w:100) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:200 w:200) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ActionsQueue` (r:1 w:1) + /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 100]`. /// The range of component `t` is `[0, 100]`. fn manage_lease_period_start(c: u32, t: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `26 + c * (47 ±0) + t * (308 ±0)` - // Estimated: `2800 + c * (2526 ±0) + t * (2789 ±0)` - // Minimum execution time: 634_547_000 picoseconds. - Weight::from_parts(643_045_000, 0) - .saturating_add(Weight::from_parts(0, 2800)) - // Standard Error: 81_521 - .saturating_add(Weight::from_parts(2_705_219, 0).saturating_mul(c.into())) - // Standard Error: 81_521 - .saturating_add(Weight::from_parts(11_464_132, 0).saturating_mul(t.into())) + // Measured: `594 + c * (20 ±0) + t * (234 ±0)` + // Estimated: `4065 + c * (2496 ±0) + t * (2709 ±0)` + // Minimum execution time: 729_793_000 picoseconds. + Weight::from_parts(740_820_000, 0) + .saturating_add(Weight::from_parts(0, 4065)) + // Standard Error: 88_206 + .saturating_add(Weight::from_parts(2_793_142, 0).saturating_mul(c.into())) + // Standard Error: 88_206 + .saturating_add(Weight::from_parts(8_933_065, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(t.into()))) + .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(t.into()))) - .saturating_add(Weight::from_parts(0, 2526).saturating_mul(c.into())) - .saturating_add(Weight::from_parts(0, 2789).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(t.into()))) + .saturating_add(Weight::from_parts(0, 2496).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(0, 2709).saturating_mul(t.into())) } - /// Storage: Slots Leases (r:1 w:1) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:8 w:8) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Slots::Leases` (r:1 w:1) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:8 w:8) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn clear_all_leases() -> Weight { // Proof Size summary in bytes: - // Measured: `2759` + // Measured: `2792` // Estimated: `21814` - // Minimum execution time: 129_756_000 picoseconds. - Weight::from_parts(131_810_000, 0) + // Minimum execution time: 123_888_000 picoseconds. + Weight::from_parts(131_245_000, 0) .saturating_add(Weight::from_parts(0, 21814)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(9)) } - /// Storage: Slots Leases (r:1 w:0) - /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:1) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ActionsQueue (r:1 w:1) - /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) - /// Storage: Registrar Paras (r:1 w:1) - /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: `Slots::Leases` (r:1 w:0) + /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:1) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ActionsQueue` (r:1 w:1) + /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) fn trigger_onboard() -> Weight { // Proof Size summary in bytes: - // Measured: `707` - // Estimated: `4172` - // Minimum execution time: 29_527_000 picoseconds. - Weight::from_parts(30_055_000, 0) - .saturating_add(Weight::from_parts(0, 4172)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `612` + // Estimated: `4077` + // Minimum execution time: 27_341_000 picoseconds. + Weight::from_parts(28_697_000, 0) + .saturating_add(Weight::from_parts(0, 4077)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs index ac0f05301b4..653e1009f31 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs @@ -16,26 +16,28 @@ //! Autogenerated weights for `runtime_parachains::assigner_on_demand` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-08-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-fljshgub-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=runtime_parachains::assigner_on_demand // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json -// --pallet=runtime_parachains::assigner_on_demand -// --chain=rococo-dev -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -57,13 +59,13 @@ impl runtime_parachains::assigner_on_demand::WeightInfo /// The range of component `s` is `[1, 9999]`. fn place_order_keep_alive(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `297 + s * (4 ±0)` - // Estimated: `3762 + s * (4 ±0)` - // Minimum execution time: 33_522_000 picoseconds. - Weight::from_parts(35_436_835, 0) - .saturating_add(Weight::from_parts(0, 3762)) - // Standard Error: 129 - .saturating_add(Weight::from_parts(14_041, 0).saturating_mul(s.into())) + // Measured: `363 + s * (4 ±0)` + // Estimated: `3828 + s * (4 ±0)` + // Minimum execution time: 25_298_000 picoseconds. + Weight::from_parts(21_486_098, 0) + .saturating_add(Weight::from_parts(0, 3828)) + // Standard Error: 136 + .saturating_add(Weight::from_parts(13_943, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) @@ -77,13 +79,13 @@ impl runtime_parachains::assigner_on_demand::WeightInfo /// The range of component `s` is `[1, 9999]`. fn place_order_allow_death(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `297 + s * (4 ±0)` - // Estimated: `3762 + s * (4 ±0)` - // Minimum execution time: 33_488_000 picoseconds. - Weight::from_parts(34_848_934, 0) - .saturating_add(Weight::from_parts(0, 3762)) - // Standard Error: 143 - .saturating_add(Weight::from_parts(14_215, 0).saturating_mul(s.into())) + // Measured: `363 + s * (4 ±0)` + // Estimated: `3828 + s * (4 ±0)` + // Minimum execution time: 25_421_000 picoseconds. + Weight::from_parts(21_828_043, 0) + .saturating_add(Weight::from_parts(0, 3828)) + // Standard Error: 133 + .saturating_add(Weight::from_parts(13_831, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs index ca0575cb1b6..caad090ae15 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs @@ -17,25 +17,27 @@ //! Autogenerated weights for `runtime_parachains::configuration` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/production/polkadot +// ./target/production/polkadot // benchmark // pallet +// --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --pallet=runtime_parachains::configuration // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=runtime_parachains::configuration -// --chain=rococo-dev // --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -58,8 +60,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_789_000 picoseconds. - Weight::from_parts(8_269_000, 0) + // Minimum execution time: 7_689_000 picoseconds. + Weight::from_parts(8_089_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -74,8 +76,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_851_000 picoseconds. - Weight::from_parts(8_152_000, 0) + // Minimum execution time: 7_735_000 picoseconds. + Weight::from_parts(8_150_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -90,8 +92,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_960_000 picoseconds. - Weight::from_parts(8_276_000, 0) + // Minimum execution time: 7_902_000 picoseconds. + Weight::from_parts(8_196_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -116,8 +118,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_912_000 picoseconds. - Weight::from_parts(8_164_000, 0) + // Minimum execution time: 7_634_000 picoseconds. + Weight::from_parts(7_983_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -132,8 +134,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 9_782_000 picoseconds. - Weight::from_parts(10_373_000, 0) + // Minimum execution time: 9_580_000 picoseconds. + Weight::from_parts(9_989_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -148,8 +150,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_870_000 picoseconds. - Weight::from_parts(8_274_000, 0) + // Minimum execution time: 7_787_000 picoseconds. + Weight::from_parts(8_008_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -164,8 +166,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 9_960_000 picoseconds. - Weight::from_parts(10_514_000, 0) + // Minimum execution time: 9_557_000 picoseconds. + Weight::from_parts(9_994_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -180,8 +182,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_913_000 picoseconds. - Weight::from_parts(8_338_000, 0) + // Minimum execution time: 7_775_000 picoseconds. + Weight::from_parts(7_989_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs index 63a8c3addc7..cf1aa36e10e 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::disputes` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_parachains::disputes // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_parachains_disputes.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,14 +50,14 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::disputes`. pub struct WeightInfo(PhantomData); impl runtime_parachains::disputes::WeightInfo for WeightInfo { - /// Storage: ParasDisputes Frozen (r:0 w:1) - /// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ParasDisputes::Frozen` (r:0 w:1) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn force_unfreeze() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_937_000 picoseconds. - Weight::from_parts(3_082_000, 0) + // Minimum execution time: 1_855_000 picoseconds. + Weight::from_parts(2_015_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs index 417820e6627..a3b912491e5 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::hrmp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_parachains::hrmp // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_parachains_hrmp.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,105 +50,97 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::hrmp`. pub struct WeightInfo(PhantomData); impl runtime_parachains::hrmp::WeightInfo for WeightInfo { - /// Storage: Paras ParaLifecycles (r:2 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_init_open_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `704` - // Estimated: `6644` - // Minimum execution time: 41_564_000 picoseconds. - Weight::from_parts(42_048_000, 0) - .saturating_add(Weight::from_parts(0, 6644)) - .saturating_add(T::DbWeight::get().reads(10)) + // Measured: `488` + // Estimated: `3953` + // Minimum execution time: 34_911_000 picoseconds. + Weight::from_parts(35_762_000, 0) + .saturating_add(Weight::from_parts(0, 3953)) + .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_accept_open_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `936` - // Estimated: `4401` - // Minimum execution time: 43_570_000 picoseconds. - Weight::from_parts(44_089_000, 0) - .saturating_add(Weight::from_parts(0, 4401)) - .saturating_add(T::DbWeight::get().reads(7)) + // Measured: `478` + // Estimated: `3943` + // Minimum execution time: 31_483_000 picoseconds. + Weight::from_parts(32_230_000, 0) + .saturating_add(Weight::from_parts(0, 3943)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) fn hrmp_close_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `807` - // Estimated: `4272` - // Minimum execution time: 36_594_000 picoseconds. - Weight::from_parts(37_090_000, 0) - .saturating_add(Weight::from_parts(0, 4272)) - .saturating_add(T::DbWeight::get().reads(6)) + // Measured: `591` + // Estimated: `4056` + // Minimum execution time: 32_153_000 picoseconds. + Weight::from_parts(32_982_000, 0) + .saturating_add(Weight::from_parts(0, 4056)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:254 w:254) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelContents (r:0 w:254) - /// Proof Skipped: Hrmp HrmpChannelContents (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:254 w:254) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:0 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelContents` (r:0 w:254) + /// Proof: `Hrmp::HrmpChannelContents` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:0 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 127]`. /// The range of component `e` is `[0, 127]`. fn force_clean_hrmp(i: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `264 + e * (100 ±0) + i * (100 ±0)` - // Estimated: `3726 + e * (2575 ±0) + i * (2575 ±0)` - // Minimum execution time: 1_085_140_000 picoseconds. - Weight::from_parts(1_100_901_000, 0) - .saturating_add(Weight::from_parts(0, 3726)) - // Standard Error: 98_982 - .saturating_add(Weight::from_parts(3_229_112, 0).saturating_mul(i.into())) - // Standard Error: 98_982 - .saturating_add(Weight::from_parts(3_210_944, 0).saturating_mul(e.into())) + // Measured: `297 + e * (100 ±0) + i * (100 ±0)` + // Estimated: `3759 + e * (2575 ±0) + i * (2575 ±0)` + // Minimum execution time: 1_240_769_000 picoseconds. + Weight::from_parts(1_249_285_000, 0) + .saturating_add(Weight::from_parts(0, 3759)) + // Standard Error: 112_346 + .saturating_add(Weight::from_parts(3_449_114, 0).saturating_mul(i.into())) + // Standard Error: 112_346 + .saturating_add(Weight::from_parts(3_569_184, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(e.into()))) @@ -155,139 +150,139 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf .saturating_add(Weight::from_parts(0, 2575).saturating_mul(e.into())) .saturating_add(Weight::from_parts(0, 2575).saturating_mul(i.into())) } - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:256 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:128 w:128) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:0 w:128) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:256 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:128 w:128) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:0 w:128) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_open(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `779 + c * (136 ±0)` - // Estimated: `2234 + c * (5086 ±0)` - // Minimum execution time: 10_497_000 picoseconds. - Weight::from_parts(6_987_455, 0) - .saturating_add(Weight::from_parts(0, 2234)) - // Standard Error: 18_540 - .saturating_add(Weight::from_parts(18_788_534, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(2)) + // Measured: `525 + c * (136 ±0)` + // Estimated: `1980 + c * (5086 ±0)` + // Minimum execution time: 6_026_000 picoseconds. + Weight::from_parts(6_257_000, 0) + .saturating_add(Weight::from_parts(0, 1980)) + // Standard Error: 9_732 + .saturating_add(Weight::from_parts(21_049_890, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((6_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 5086).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpCloseChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:128 w:128) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpCloseChannelRequests (r:0 w:128) - /// Proof Skipped: Hrmp HrmpCloseChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelContents (r:0 w:128) - /// Proof Skipped: Hrmp HrmpChannelContents (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpCloseChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpCloseChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:128 w:128) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpCloseChannelRequests` (r:0 w:128) + /// Proof: `Hrmp::HrmpCloseChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelContents` (r:0 w:128) + /// Proof: `Hrmp::HrmpChannelContents` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_close(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `335 + c * (124 ±0)` - // Estimated: `1795 + c * (2600 ±0)` - // Minimum execution time: 6_575_000 picoseconds. - Weight::from_parts(1_228_642, 0) - .saturating_add(Weight::from_parts(0, 1795)) - // Standard Error: 14_826 - .saturating_add(Weight::from_parts(11_604_038, 0).saturating_mul(c.into())) + // Measured: `368 + c * (124 ±0)` + // Estimated: `1828 + c * (2600 ±0)` + // Minimum execution time: 4_991_000 picoseconds. + Weight::from_parts(984_758, 0) + .saturating_add(Weight::from_parts(0, 1828)) + // Standard Error: 11_918 + .saturating_add(Weight::from_parts(13_018_813, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2600).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn hrmp_cancel_open_request(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1026 + c * (13 ±0)` - // Estimated: `4295 + c * (15 ±0)` - // Minimum execution time: 22_301_000 picoseconds. - Weight::from_parts(26_131_473, 0) - .saturating_add(Weight::from_parts(0, 4295)) - // Standard Error: 830 - .saturating_add(Weight::from_parts(49_448, 0).saturating_mul(c.into())) + // Measured: `1059 + c * (13 ±0)` + // Estimated: `4328 + c * (15 ±0)` + // Minimum execution time: 17_299_000 picoseconds. + Weight::from_parts(27_621_478, 0) + .saturating_add(Weight::from_parts(0, 4328)) + // Standard Error: 2_527 + .saturating_add(Weight::from_parts(121_149, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(Weight::from_parts(0, 15).saturating_mul(c.into())) } - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:128 w:128) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:128 w:128) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[0, 128]`. fn clean_open_channel_requests(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `243 + c * (63 ±0)` - // Estimated: `1722 + c * (2538 ±0)` - // Minimum execution time: 5_234_000 picoseconds. - Weight::from_parts(7_350_270, 0) - .saturating_add(Weight::from_parts(0, 1722)) - // Standard Error: 3_105 - .saturating_add(Weight::from_parts(2_981_935, 0).saturating_mul(c.into())) + // Measured: `276 + c * (63 ±0)` + // Estimated: `1755 + c * (2538 ±0)` + // Minimum execution time: 3_764_000 picoseconds. + Weight::from_parts(5_935_301, 0) + .saturating_add(Weight::from_parts(0, 1755)) + // Standard Error: 3_761 + .saturating_add(Weight::from_parts(3_290_277, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2538).saturating_mul(c.into())) } - /// Storage: Paras ParaLifecycles (r:2 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannels (r:1 w:0) - /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:2 w:2) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueueHeads (r:2 w:2) - /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) - /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) - /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) - fn force_open_hrmp_channel(_c: u32, ) -> Weight { + /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) + /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:2 w:2) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:1 w:0) + /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:1 w:1) + /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `c` is `[0, 1]`. + fn force_open_hrmp_channel(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `704` - // Estimated: `6644` - // Minimum execution time: 55_611_000 picoseconds. - Weight::from_parts(56_488_000, 0) - .saturating_add(Weight::from_parts(0, 6644)) - .saturating_add(T::DbWeight::get().reads(14)) + // Measured: `488 + c * (235 ±0)` + // Estimated: `6428 + c * (235 ±0)` + // Minimum execution time: 49_506_000 picoseconds. + Weight::from_parts(51_253_075, 0) + .saturating_add(Weight::from_parts(0, 6428)) + // Standard Error: 144_082 + .saturating_add(Weight::from_parts(12_862_224, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(8)) + .saturating_add(Weight::from_parts(0, 235).saturating_mul(c.into())) } /// Storage: `Paras::ParaLifecycles` (r:1 w:0) /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -311,11 +306,11 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) fn establish_system_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `6357` - // Minimum execution time: 629_674_000 picoseconds. - Weight::from_parts(640_174_000, 0) - .saturating_add(Weight::from_parts(0, 6357)) + // Measured: `488` + // Estimated: `6428` + // Minimum execution time: 50_016_000 picoseconds. + Weight::from_parts(50_933_000, 0) + .saturating_add(Weight::from_parts(0, 6428)) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(8)) } @@ -323,11 +318,11 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) fn poke_channel_deposits() -> Weight { // Proof Size summary in bytes: - // Measured: `263` - // Estimated: `3728` - // Minimum execution time: 173_371_000 picoseconds. - Weight::from_parts(175_860_000, 0) - .saturating_add(Weight::from_parts(0, 3728)) + // Measured: `296` + // Estimated: `3761` + // Minimum execution time: 12_280_000 picoseconds. + Weight::from_parts(12_863_000, 0) + .saturating_add(Weight::from_parts(0, 3761)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs index a121ad774ce..b9ec7565bd5 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::inclusion` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_parachains::inclusion // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_parachains_inclusion.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,27 +50,25 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::inclusion`. pub struct WeightInfo(PhantomData); impl runtime_parachains::inclusion::WeightInfo for WeightInfo { - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:999) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Proof Skipped: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Storage: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) - /// Proof Skipped: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:999) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Storage: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Proof: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) /// The range of component `i` is `[1, 1000]`. fn receive_upward_messages(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `33280` + // Measured: `32993` // Estimated: `36283` - // Minimum execution time: 71_094_000 picoseconds. - Weight::from_parts(71_436_000, 0) + // Minimum execution time: 72_675_000 picoseconds. + Weight::from_parts(73_290_000, 0) .saturating_add(Weight::from_parts(0, 36283)) - // Standard Error: 22_149 - .saturating_add(Weight::from_parts(51_495_472, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(3)) + // Standard Error: 16_067 + .saturating_add(Weight::from_parts(57_735_739, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs index 5c627507dfb..e8c554610c9 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::initializer` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_parachains::initializer // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_parachains_initializer.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,18 +50,18 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::initializer`. pub struct WeightInfo(PhantomData); impl runtime_parachains::initializer::WeightInfo for WeightInfo { - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `System::Digest` (r:1 w:1) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `d` is `[0, 65536]`. fn force_approve(d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + d * (11 ±0)` // Estimated: `1480 + d * (11 ±0)` - // Minimum execution time: 3_771_000 picoseconds. - Weight::from_parts(6_491_437, 0) + // Minimum execution time: 2_634_000 picoseconds. + Weight::from_parts(2_728_000, 0) .saturating_add(Weight::from_parts(0, 1480)) - // Standard Error: 9 - .saturating_add(Weight::from_parts(1_356, 0).saturating_mul(d.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(2_499, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 11).saturating_mul(d.into())) diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs index dfd95006dc7..af26bfc9ae9 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::paras` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,12 +29,15 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_parachains::paras // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/runtime_parachains_paras.rs +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -47,247 +50,248 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::paras`. pub struct WeightInfo(PhantomData); impl runtime_parachains::paras::WeightInfo for WeightInfo { - /// Storage: Paras CurrentCodeHash (r:1 w:1) - /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CodeByHashRefs (r:1 w:1) - /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras PastCodeMeta (r:1 w:1) - /// Proof Skipped: Paras PastCodeMeta (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras PastCodePruning (r:1 w:1) - /// Proof Skipped: Paras PastCodePruning (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PastCodeHash (r:0 w:1) - /// Proof Skipped: Paras PastCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CodeByHash (r:0 w:1) - /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:1) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) + /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PastCodeMeta` (r:1 w:1) + /// Proof: `Paras::PastCodeMeta` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PastCodePruning` (r:1 w:1) + /// Proof: `Paras::PastCodePruning` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PastCodeHash` (r:0 w:1) + /// Proof: `Paras::PastCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHash` (r:0 w:1) + /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 3145728]`. fn force_set_current_code(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `8309` // Estimated: `11774` - // Minimum execution time: 31_941_000 picoseconds. - Weight::from_parts(32_139_000, 0) + // Minimum execution time: 27_488_000 picoseconds. + Weight::from_parts(27_810_000, 0) .saturating_add(Weight::from_parts(0, 11774)) - // Standard Error: 5 - .saturating_add(Weight::from_parts(2_011, 0).saturating_mul(c.into())) + // Standard Error: 8 + .saturating_add(Weight::from_parts(2_189, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: Paras Heads (r:0 w:1) - /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `s` is `[1, 1048576]`. fn force_set_current_head(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_275_000 picoseconds. - Weight::from_parts(8_321_000, 0) + // Minimum execution time: 5_793_000 picoseconds. + Weight::from_parts(7_987_606, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(858, 0).saturating_mul(s.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(971, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().writes(1)) } - // Storage: Paras Heads (r:0 w:1) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_set_most_recent_context() -> Weight { - Weight::from_parts(10_155_000, 0) - // Standard Error: 0 - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_733_000 picoseconds. + Weight::from_parts(2_954_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras FutureCodeHash (r:1 w:1) - /// Proof Skipped: Paras FutureCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CurrentCodeHash (r:1 w:0) - /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeCooldowns (r:1 w:1) - /// Proof Skipped: Paras UpgradeCooldowns (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CodeByHash (r:1 w:1) - /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteList (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras CodeByHashRefs (r:1 w:1) - /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeRestrictionSignal (r:0 w:1) - /// Proof Skipped: Paras UpgradeRestrictionSignal (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::FutureCodeHash` (r:1 w:1) + /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeCooldowns` (r:1 w:1) + /// Proof: `Paras::UpgradeCooldowns` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHash` (r:1 w:1) + /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) + /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeRestrictionSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 3145728]`. fn force_schedule_code_upgrade(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `8715` - // Estimated: `12180` - // Minimum execution time: 49_923_000 picoseconds. - Weight::from_parts(50_688_000, 0) - .saturating_add(Weight::from_parts(0, 12180)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_976, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(7)) + // Measured: `8452` + // Estimated: `11917` + // Minimum execution time: 6_072_000 picoseconds. + Weight::from_parts(6_128_000, 0) + .saturating_add(Weight::from_parts(0, 11917)) + // Standard Error: 2 + .saturating_add(Weight::from_parts(2_334, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: Paras FutureCodeUpgrades (r:1 w:0) - /// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Heads (r:0 w:1) - /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeGoAheadSignal (r:0 w:1) - /// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `s` is `[1, 1048576]`. fn force_note_new_head(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `95` - // Estimated: `3560` - // Minimum execution time: 14_408_000 picoseconds. - Weight::from_parts(14_647_000, 0) - .saturating_add(Weight::from_parts(0, 3560)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(858, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `163` + // Estimated: `3628` + // Minimum execution time: 15_166_000 picoseconds. + Weight::from_parts(21_398_053, 0) + .saturating_add(Weight::from_parts(0, 3628)) + // Standard Error: 1 + .saturating_add(Weight::from_parts(976, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ActionsQueue (r:1 w:1) - /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ActionsQueue` (r:1 w:1) + /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_queue_action() -> Weight { // Proof Size summary in bytes: - // Measured: `4288` - // Estimated: `7753` - // Minimum execution time: 20_009_000 picoseconds. - Weight::from_parts(20_518_000, 0) - .saturating_add(Weight::from_parts(0, 7753)) + // Measured: `4312` + // Estimated: `7777` + // Minimum execution time: 16_345_000 picoseconds. + Weight::from_parts(16_712_000, 0) + .saturating_add(Weight::from_parts(0, 7777)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteList (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ActionsQueue (r:1 w:1) - /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ActionsQueue` (r:1 w:1) + /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 3145728]`. fn add_trusted_validation_code(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `946` - // Estimated: `4411` - // Minimum execution time: 80_626_000 picoseconds. - Weight::from_parts(52_721_755, 0) - .saturating_add(Weight::from_parts(0, 4411)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_443, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `683` + // Estimated: `4148` + // Minimum execution time: 78_076_000 picoseconds. + Weight::from_parts(123_193_814, 0) + .saturating_add(Weight::from_parts(0, 4148)) + // Standard Error: 5 + .saturating_add(Weight::from_parts(1_770, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: Paras CodeByHashRefs (r:1 w:0) - /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras CodeByHash (r:0 w:1) - /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) + /// Storage: `Paras::CodeByHashRefs` (r:1 w:0) + /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CodeByHash` (r:0 w:1) + /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) fn poke_unused_validation_code() -> Weight { // Proof Size summary in bytes: // Measured: `28` // Estimated: `3493` - // Minimum execution time: 6_692_000 picoseconds. - Weight::from_parts(7_009_000, 0) + // Minimum execution time: 5_184_000 picoseconds. + Weight::from_parts(5_430_000, 0) .saturating_add(Weight::from_parts(0, 3493)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) fn include_pvf_check_statement() -> Weight { // Proof Size summary in bytes: - // Measured: `26682` - // Estimated: `30147` - // Minimum execution time: 87_994_000 picoseconds. - Weight::from_parts(89_933_000, 0) - .saturating_add(Weight::from_parts(0, 30147)) + // Measured: `26706` + // Estimated: `30171` + // Minimum execution time: 102_995_000 picoseconds. + Weight::from_parts(108_977_000, 0) + .saturating_add(Weight::from_parts(0, 30171)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteList (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras UpcomingUpgrades (r:1 w:1) - /// Proof Skipped: Paras UpcomingUpgrades (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras FutureCodeUpgrades (r:0 w:100) - /// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpcomingUpgrades` (r:1 w:1) + /// Proof: `Paras::UpcomingUpgrades` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Digest` (r:1 w:1) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:0 w:100) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { // Proof Size summary in bytes: - // Measured: `27523` - // Estimated: `30988` - // Minimum execution time: 783_222_000 picoseconds. - Weight::from_parts(794_959_000, 0) - .saturating_add(Weight::from_parts(0, 30988)) - .saturating_add(T::DbWeight::get().reads(7)) + // Measured: `27360` + // Estimated: `30825` + // Minimum execution time: 709_433_000 picoseconds. + Weight::from_parts(725_074_000, 0) + .saturating_add(Weight::from_parts(0, 30825)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(104)) } - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { // Proof Size summary in bytes: - // Measured: `27214` - // Estimated: `30679` - // Minimum execution time: 87_424_000 picoseconds. - Weight::from_parts(88_737_000, 0) - .saturating_add(Weight::from_parts(0, 30679)) + // Measured: `27338` + // Estimated: `30803` + // Minimum execution time: 98_973_000 picoseconds. + Weight::from_parts(104_715_000, 0) + .saturating_add(Weight::from_parts(0, 30803)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteList (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Configuration ActiveConfig (r:1 w:0) - /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras ActionsQueue (r:1 w:1) - /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ActionsQueue` (r:1 w:1) + /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { // Proof Size summary in bytes: - // Measured: `26991` - // Estimated: `30456` - // Minimum execution time: 612_485_000 picoseconds. - Weight::from_parts(621_670_000, 0) - .saturating_add(Weight::from_parts(0, 30456)) - .saturating_add(T::DbWeight::get().reads(6)) + // Measured: `26728` + // Estimated: `30193` + // Minimum execution time: 550_958_000 picoseconds. + Weight::from_parts(564_497_000, 0) + .saturating_add(Weight::from_parts(0, 30193)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras PvfActiveVoteMap (r:1 w:1) - /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) + /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { // Proof Size summary in bytes: - // Measured: `26682` - // Estimated: `30147` - // Minimum execution time: 86_673_000 picoseconds. - Weight::from_parts(87_424_000, 0) - .saturating_add(Weight::from_parts(0, 30147)) + // Measured: `26706` + // Estimated: `30171` + // Minimum execution time: 97_088_000 picoseconds. + Weight::from_parts(103_617_000, 0) + .saturating_add(Weight::from_parts(0, 30171)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs index a102d1903b2..374927f8470 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs @@ -13,161 +13,334 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . + //! Autogenerated weights for `runtime_parachains::paras_inherent` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 128 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/release/polkadot +// ./target/production/polkadot // benchmark +// pallet // --chain=rococo-dev // --steps=50 // --repeat=20 +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --pallet=runtime_parachains::paras_inherent // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --output=./runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs -// --header=./file_header.txt +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{traits::Get, weights::Weight}; -use sp_std::marker::PhantomData; +use core::marker::PhantomData; /// Weight functions for `runtime_parachains::paras_inherent`. pub struct WeightInfo(PhantomData); impl runtime_parachains::paras_inherent::WeightInfo for WeightInfo { - // Storage: ParaInherent Included (r:1 w:1) - // Storage: System ParentHash (r:1 w:0) - // Storage: ParaScheduler AvailabilityCores (r:1 w:1) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParaSessionInfo Sessions (r:1 w:0) - // Storage: ParasDisputes Disputes (r:1 w:1) - // Storage: ParasDisputes Included (r:1 w:1) - // Storage: ParasDisputes SpamSlots (r:1 w:1) - // Storage: ParasDisputes Frozen (r:1 w:0) - // Storage: ParaInclusion PendingAvailability (r:2 w:1) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: Paras Parachains (r:1 w:0) - // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - // Storage: Hrmp HrmpChannelDigests (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: ParaScheduler SessionStartBlock (r:1 w:0) - // Storage: ParaScheduler ParathreadQueue (r:1 w:1) - // Storage: ParaScheduler Scheduled (r:1 w:1) - // Storage: ParaScheduler ValidatorGroups (r:1 w:0) - // Storage: Ump NeedsDispatch (r:1 w:1) - // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) - // Storage: ParaInherent OnChainVotes (r:0 w:1) - // Storage: Hrmp HrmpWatermarks (r:0 w:1) - // Storage: Paras Heads (r:0 w:1) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaSessionInfo::Sessions` (r:1 w:0) + /// Proof: `ParaSessionInfo::Sessions` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:1) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::BackersOnDisputes` (r:1 w:1) + /// Proof: `ParasDisputes::BackersOnDisputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:1 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::PendingAvailability` (r:2 w:1) + /// Proof: `ParaInclusion::PendingAvailability` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::PendingAvailabilityCommitments` (r:1 w:1) + /// Proof: `ParaInclusion::PendingAvailabilityCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `v` is `[10, 200]`. fn enter_variable_disputes(v: u32, ) -> Weight { - Weight::from_parts(352_590_000 as u64, 0) - // Standard Error: 13_000 - .saturating_add(Weight::from_parts(49_254_000 as u64, 0).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(24 as u64)) - .saturating_add(T::DbWeight::get().writes(16 as u64)) + // Proof Size summary in bytes: + // Measured: `67819` + // Estimated: `73759 + v * (23 ±0)` + // Minimum execution time: 874_229_000 picoseconds. + Weight::from_parts(486_359_072, 0) + .saturating_add(Weight::from_parts(0, 73759)) + // Standard Error: 19_197 + .saturating_add(Weight::from_parts(41_842_161, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(26)) + .saturating_add(T::DbWeight::get().writes(16)) + .saturating_add(Weight::from_parts(0, 23).saturating_mul(v.into())) } - // Storage: ParaInherent Included (r:1 w:1) - // Storage: System ParentHash (r:1 w:0) - // Storage: ParaScheduler AvailabilityCores (r:1 w:1) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasDisputes Frozen (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: Paras Parachains (r:1 w:0) - // Storage: ParaInclusion PendingAvailability (r:2 w:1) - // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - // Storage: Hrmp HrmpChannelDigests (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: ParasDisputes Disputes (r:1 w:0) - // Storage: ParaScheduler SessionStartBlock (r:1 w:0) - // Storage: ParaScheduler ParathreadQueue (r:1 w:1) - // Storage: ParaScheduler Scheduled (r:1 w:1) - // Storage: ParaScheduler ValidatorGroups (r:1 w:0) - // Storage: Ump NeedsDispatch (r:1 w:1) - // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) - // Storage: ParaInclusion AvailabilityBitfields (r:0 w:1) - // Storage: ParaInherent OnChainVotes (r:0 w:1) - // Storage: ParasDisputes Included (r:0 w:1) - // Storage: Hrmp HrmpWatermarks (r:0 w:1) - // Storage: Paras Heads (r:0 w:1) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::PendingAvailability` (r:2 w:1) + /// Proof: `ParaInclusion::PendingAvailability` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::PendingAvailabilityCommitments` (r:1 w:1) + /// Proof: `ParaInclusion::PendingAvailabilityCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::AvailabilityBitfields` (r:0 w:1) + /// Proof: `ParaInclusion::AvailabilityBitfields` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) fn enter_bitfields() -> Weight { - Weight::from_parts(299_878_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(21 as u64)) - .saturating_add(T::DbWeight::get().writes(15 as u64)) + // Proof Size summary in bytes: + // Measured: `42791` + // Estimated: `48731` + // Minimum execution time: 428_757_000 picoseconds. + Weight::from_parts(449_681_000, 0) + .saturating_add(Weight::from_parts(0, 48731)) + .saturating_add(T::DbWeight::get().reads(24)) + .saturating_add(T::DbWeight::get().writes(17)) } - // Storage: ParaInherent Included (r:1 w:1) - // Storage: System ParentHash (r:1 w:0) - // Storage: ParaScheduler AvailabilityCores (r:1 w:1) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasDisputes Frozen (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: Paras Parachains (r:1 w:0) - // Storage: ParaInclusion PendingAvailability (r:2 w:1) - // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - // Storage: Hrmp HrmpChannelDigests (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: ParasDisputes Disputes (r:2 w:0) - // Storage: ParaScheduler SessionStartBlock (r:1 w:0) - // Storage: ParaScheduler ParathreadQueue (r:1 w:1) - // Storage: ParaScheduler Scheduled (r:1 w:1) - // Storage: ParaScheduler ValidatorGroups (r:1 w:0) - // Storage: Paras PastCodeMeta (r:1 w:0) - // Storage: Paras CurrentCodeHash (r:1 w:0) - // Storage: Ump RelayDispatchQueueSize (r:1 w:0) - // Storage: Ump NeedsDispatch (r:1 w:1) - // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) - // Storage: ParaInherent OnChainVotes (r:0 w:1) - // Storage: ParasDisputes Included (r:0 w:1) - // Storage: Hrmp HrmpWatermarks (r:0 w:1) - // Storage: Paras Heads (r:0 w:1) - fn enter_backed_candidates_variable(_v: u32) -> Weight { - Weight::from_parts(442_472_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(25 as u64)) - .saturating_add(T::DbWeight::get().writes(14 as u64)) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::PendingAvailability` (r:2 w:1) + /// Proof: `ParaInclusion::PendingAvailability` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::PendingAvailabilityCommitments` (r:1 w:1) + /// Proof: `ParaInclusion::PendingAvailabilityCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `v` is `[101, 200]`. + fn enter_backed_candidates_variable(v: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `42863` + // Estimated: `48803` + // Minimum execution time: 1_276_079_000 picoseconds. + Weight::from_parts(1_313_585_212, 0) + .saturating_add(Weight::from_parts(0, 48803)) + // Standard Error: 18_279 + .saturating_add(Weight::from_parts(43_528, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(27)) + .saturating_add(T::DbWeight::get().writes(16)) } - // Storage: ParaInherent Included (r:1 w:1) - // Storage: System ParentHash (r:1 w:0) - // Storage: ParaScheduler AvailabilityCores (r:1 w:1) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasDisputes Frozen (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: Paras Parachains (r:1 w:0) - // Storage: ParaInclusion PendingAvailability (r:2 w:1) - // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - // Storage: Hrmp HrmpChannelDigests (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: ParasDisputes Disputes (r:2 w:0) - // Storage: ParaScheduler SessionStartBlock (r:1 w:0) - // Storage: ParaScheduler ParathreadQueue (r:1 w:1) - // Storage: ParaScheduler Scheduled (r:1 w:1) - // Storage: ParaScheduler ValidatorGroups (r:1 w:0) - // Storage: Paras PastCodeMeta (r:1 w:0) - // Storage: Paras CurrentCodeHash (r:1 w:0) - // Storage: Ump RelayDispatchQueueSize (r:1 w:0) - // Storage: Ump NeedsDispatch (r:1 w:1) - // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) - // Storage: ParaInherent OnChainVotes (r:0 w:1) - // Storage: ParasDisputes Included (r:0 w:1) - // Storage: Hrmp HrmpWatermarks (r:0 w:1) - // Storage: Paras Heads (r:0 w:1) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::PendingAvailability` (r:2 w:1) + /// Proof: `ParaInclusion::PendingAvailability` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::PendingAvailabilityCommitments` (r:1 w:1) + /// Proof: `ParaInclusion::PendingAvailabilityCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeHash` (r:1 w:0) + /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeRestrictionSignal` (r:1 w:0) + /// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) fn enter_backed_candidate_code_upgrade() -> Weight { - Weight::from_parts(36_903_411_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(25 as u64)) - .saturating_add(T::DbWeight::get().writes(14 as u64)) + // Proof Size summary in bytes: + // Measured: `42876` + // Estimated: `48816` + // Minimum execution time: 34_352_245_000 picoseconds. + Weight::from_parts(34_587_559_000, 0) + .saturating_add(Weight::from_parts(0, 48816)) + .saturating_add(T::DbWeight::get().reads(29)) + .saturating_add(T::DbWeight::get().writes(16)) } } diff --git a/polkadot/runtime/test-runtime/Cargo.toml b/polkadot/runtime/test-runtime/Cargo.toml index 9753a409304..bdf68864605 100644 --- a/polkadot/runtime/test-runtime/Cargo.toml +++ b/polkadot/runtime/test-runtime/Cargo.toml @@ -155,6 +155,7 @@ runtime-benchmarks = [ "pallet-staking/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index 6c899c52701..a0617b3108f 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -238,6 +238,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = frame_support::weights::ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = (); } parameter_types! { @@ -393,7 +394,7 @@ where let current_block = System::block_number().saturated_into::().saturating_sub(1); let tip = 0; - let extra: SignedExtra = ( + let tx_ext: TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -405,16 +406,17 @@ where frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ); - let raw_payload = SignedPayload::new(call, extra) + ) + .into(); + let raw_payload = SignedPayload::new(call, tx_ext) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; - let (call, extra, _) = raw_payload.deconstruct(); + let (call, tx_ext, _) = raw_payload.deconstruct(); let address = Indices::unlookup(account); - Some((call, (address, signature, extra))) + Some((call, (address, signature, tx_ext))) } } @@ -442,12 +444,32 @@ parameter_types! { pub Prefix: &'static [u8] = b"Pay KSMs to the Kusama account:"; } +#[cfg(feature = "runtime-benchmarks")] +pub struct ClaimsHelper; + +#[cfg(feature = "runtime-benchmarks")] +use frame_support::dispatch::DispatchInfo; + +#[cfg(feature = "runtime-benchmarks")] +impl claims::BenchmarkHelperTrait for ClaimsHelper { + fn default_call_and_info() -> (RuntimeCall, DispatchInfo) { + use frame_support::dispatch::GetDispatchInfo; + let call = RuntimeCall::Claims(claims::Call::attest { + statement: claims::StatementKind::Regular.to_text().to_vec(), + }); + let info = call.get_dispatch_info(); + (call, info) + } +} + impl claims::Config for Runtime { type RuntimeEvent = RuntimeEvent; type VestingSchedule = Vesting; type Prefix = Prefix; type MoveClaimOrigin = frame_system::EnsureRoot; type WeightInfo = claims::TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = ClaimsHelper; } parameter_types! { @@ -728,8 +750,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// `BlockId` type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The `SignedExtension` to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -741,7 +763,7 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -752,7 +774,7 @@ pub type Executive = frame_executive::Executive< AllPalletsWithSystem, >; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; pub type Hash = ::Hash; pub type Extrinsic = ::Extrinsic; diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml index 4180828bcfb..6899edeeaeb 100644 --- a/polkadot/runtime/westend/Cargo.toml +++ b/polkadot/runtime/westend/Cargo.toml @@ -270,6 +270,7 @@ runtime-benchmarks = [ "pallet-state-trie-migration/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index b55d68ee0f6..45bbd0260e5 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -200,6 +200,7 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; + type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type MaxConsumers = frame_support::traits::ConstU32<16>; } @@ -385,6 +386,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -820,7 +822,7 @@ where // so the actual block number is `n`. .saturating_sub(1); let tip = 0; - let extra: SignedExtra = ( + let tx_ext: TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -832,16 +834,17 @@ where frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ); - let raw_payload = SignedPayload::new(call, extra) + ) + .into(); + let raw_payload = SignedPayload::new(call, tx_ext) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; - let (call, extra, _) = raw_payload.deconstruct(); + let (call, tx_ext, _) = raw_payload.deconstruct(); let address = ::Lookup::unlookup(account); - Some((call, (address, signature, extra))) + Some((call, (address, signature, tx_ext))) } } @@ -1548,8 +1551,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// `BlockId` type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The `SignedExtension` to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -1713,7 +1716,7 @@ pub mod migrations { /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -1724,7 +1727,7 @@ pub type Executive = frame_executive::Executive< Migrations, >; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; #[cfg(feature = "runtime-benchmarks")] mod benches { @@ -1770,7 +1773,9 @@ mod benches { [pallet_staking, Staking] [pallet_sudo, Sudo] [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_timestamp, Timestamp] + [pallet_transaction_payment, TransactionPayment] [pallet_treasury, Treasury] [pallet_utility, Utility] [pallet_vesting, Vesting] @@ -2312,6 +2317,7 @@ sp_api::impl_runtime_apis! { use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; @@ -2340,6 +2346,7 @@ sp_api::impl_runtime_apis! { use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; impl pallet_session_benchmarking::Config for Runtime {} diff --git a/polkadot/runtime/westend/src/weights/frame_system_extensions.rs b/polkadot/runtime/westend/src/weights/frame_system_extensions.rs new file mode 100644 index 00000000000..e4e1a799ec6 --- /dev/null +++ b/polkadot/runtime/westend/src/weights/frame_system_extensions.rs @@ -0,0 +1,116 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Autogenerated weights for `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-20, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot +// benchmark +// pallet +// --steps=2 +// --repeat=2 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --pallet=frame-system-extensions +// --chain=westend-dev +// --output=./polkadot/runtime/westend/src/weights/ +// --header=./polkadot/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 `frame_system_extensions`. +pub struct WeightInfo(PhantomData); +impl frame_system::ExtensionsWeightInfo for WeightInfo { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_356_000 picoseconds. + Weight::from_parts(7_805_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 5_510_000 picoseconds. + Weight::from_parts(10_009_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 761_000 picoseconds. + Weight::from_parts(4_308_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_396_000 picoseconds. + Weight::from_parts(7_585_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 521_000 picoseconds. + Weight::from_parts(4_168_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 541_000 picoseconds. + Weight::from_parts(4_228_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1489` + // Minimum execution time: 3_807_000 picoseconds. + Weight::from_parts(8_025_000, 0) + .saturating_add(Weight::from_parts(0, 1489)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/polkadot/runtime/westend/src/weights/mod.rs b/polkadot/runtime/westend/src/weights/mod.rs index f6a9008d718..8aeb4216550 100644 --- a/polkadot/runtime/westend/src/weights/mod.rs +++ b/polkadot/runtime/westend/src/weights/mod.rs @@ -17,6 +17,7 @@ pub mod frame_election_provider_support; pub mod frame_system; +pub mod frame_system_extensions; pub mod pallet_asset_rate; pub mod pallet_bags_list; pub mod pallet_balances; @@ -37,6 +38,7 @@ pub mod pallet_session; pub mod pallet_staking; pub mod pallet_sudo; pub mod pallet_timestamp; +pub mod pallet_transaction_payment; pub mod pallet_treasury; pub mod pallet_utility; pub mod pallet_vesting; diff --git a/polkadot/runtime/westend/src/weights/pallet_sudo.rs b/polkadot/runtime/westend/src/weights/pallet_sudo.rs index e9ab3ad37a4..649c43e031d 100644 --- a/polkadot/runtime/westend/src/weights/pallet_sudo.rs +++ b/polkadot/runtime/westend/src/weights/pallet_sudo.rs @@ -94,4 +94,15 @@ impl pallet_sudo::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `Sudo::Key` (r:1 w:0) + /// Proof: `Sudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + fn check_only_sudo_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `132` + // Estimated: `1517` + // Minimum execution time: 2_875_000 picoseconds. + Weight::from_parts(6_803_000, 0) + .saturating_add(Weight::from_parts(0, 1517)) + .saturating_add(T::DbWeight::get().reads(1)) + } } diff --git a/polkadot/runtime/westend/src/weights/pallet_transaction_payment.rs b/polkadot/runtime/westend/src/weights/pallet_transaction_payment.rs new file mode 100644 index 00000000000..001a09f103d --- /dev/null +++ b/polkadot/runtime/westend/src/weights/pallet_transaction_payment.rs @@ -0,0 +1,65 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Autogenerated weights for `pallet_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/polkadot +// benchmark +// pallet +// --steps=2 +// --repeat=2 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --pallet=pallet_transaction_payment +// --chain=westend-dev +// --output=./polkadot/runtime/westend/src/weights/ +// --header=./polkadot/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_transaction_payment`. +pub struct WeightInfo(PhantomData); +impl pallet_transaction_payment::WeightInfo for WeightInfo { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `156` + // Estimated: `1641` + // Minimum execution time: 30_888_000 picoseconds. + Weight::from_parts(41_308_000, 0) + .saturating_add(Weight::from_parts(0, 1641)) + .saturating_add(T::DbWeight::get().reads(3)) + } +} diff --git a/polkadot/xcm/xcm-builder/Cargo.toml b/polkadot/xcm/xcm-builder/Cargo.toml index 10726b0f511..660a30605e5 100644 --- a/polkadot/xcm/xcm-builder/Cargo.toml +++ b/polkadot/xcm/xcm-builder/Cargo.toml @@ -47,6 +47,7 @@ runtime-benchmarks = [ "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-salary/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-runtime-parachains/runtime-benchmarks", diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 9892c500f2e..3bd2fa4b4f5 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -25,14 +25,22 @@ use frame_support::{ traits::{ConstU32, Everything}, }; use frame_system::{EnsureRoot, EnsureSigned}; -use polkadot_test_runtime::SignedExtra; use primitives::{AccountIndex, BlakeTwo256, Signature}; use sp_runtime::{generic, traits::MaybeEquivalence, AccountId32, BuildStorage}; use xcm_executor::{traits::ConvertLocation, XcmExecutor}; +pub type TxExtension = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckMortality, + frame_system::CheckNonce, + frame_system::CheckWeight, +); pub type Address = sp_runtime::MultiAddress; pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; pub type Header = generic::Header; pub type Block = generic::Block; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index a20390b64f9..f953e54111c 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -46,13 +46,13 @@ use xcm_builder::{ }; use xcm_executor::{Config, XcmExecutor}; -pub type SignedExtra = (frame_system::CheckNonZeroSender,); +pub type TxExtension = (frame_system::CheckNonZeroSender,); pub type BlockNumber = u64; pub type Address = MultiAddress; pub type Header = generic::Header; pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; pub type Block = generic::Block; pub type Signature = MultiSignature; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index 5bf65fa9f9a..a11e535492c 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -45,13 +45,13 @@ use xcm_builder::{ }; use xcm_executor::{Config, XcmExecutor}; -pub type SignedExtra = (frame_system::CheckNonZeroSender,); +pub type TxExtension = (frame_system::CheckNonZeroSender,); pub type BlockNumber = u64; pub type Address = MultiAddress; pub type Header = generic::Header; pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; pub type Block = generic::Block; pub type Signature = MultiSignature; diff --git a/prdoc/pr_2280.prdoc b/prdoc/pr_2280.prdoc new file mode 100644 index 00000000000..3026dc254e6 --- /dev/null +++ b/prdoc/pr_2280.prdoc @@ -0,0 +1,144 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: FRAME Create `TransactionExtension` as a replacement for `SignedExtension` + +doc: + - audience: Runtime User + description: | + Introduces a new trait `TransactionExtension` to replace `SignedExtension`. Introduce the + idea of transactions which obey the runtime's extensions and have according Extension data + (né Extra data) yet do not have hard-coded signatures. + + Deprecate the terminology of "Unsigned" when used for transactions/extrinsics owing to there + now being "proper" unsigned transactions which obey the extension framework and "old-style" + unsigned which do not. Instead we have `General` for the former and `Bare` for the latter. + Unsigned will be phased out as a type of transaction, and `Bare` will only be used for + Inherents. + + Types of extrinsic are now therefore + - Bare (no hardcoded signature, no Extra data; used to be known as "Unsigned") + - Bare transactions (deprecated) - Gossiped, validated with `ValidateUnsigned` + (deprecated) and the `_bare_compat` bits of `TransactionExtension` (deprecated). + - Inherents - Not gossiped, validated with `ProvideInherent`. + - Extended (Extra data) - Gossiped, validated via `TransactionExtension`. + - Signed transactions (with a hardcoded signature). + - General transactions (without a hardcoded signature). + + Notable information on `TransactionExtension` and the differences from `SignedExtension` + - `AdditionalSigned`/`additional_signed` is renamed to `Implicit`/`implicit`. It is encoded + for the entire transaction and passed in to each extension as a new argument to validate. + - `pre_dispatch` is renamed to `prepare`. + - `validate` runs transaction validation logic both off-chain and on-chain, and is + non-mutating. + - `prepare` runs on-chain pre-execution logic using information extracted during validation + and is mutating. + - `validate` and `prepare` are now passed an `Origin` rather than an `AccountId`. If the + extension logic presumes an `AccountId`, consider using the trait function + `AsSystemOriginSigner::as_system_origin_signer`. + - A signature on the underlying transaction may validly not be present. + - The origin may be altered during validation. + - Validation functionality present in `validate` should not be repeated in `prepare`. + Useful information obtained during `validate` should now be passsed in to `prepare` using + the new user-specifiable type `Val`. + - Unsigned logic should be migrated from the old `*_unsigned` functions into the regular + versions of the new functions where the `Origin` is `None`. + - The `Call` type defining the runtime call is now a type parameter. + - `TransactionExtension` now takes a `Context` type parameter. This defines some arbitrary + contextual data that is injected into the transaction extension logic. It is unused in + instances migrated from `SignedExtension`. + - Extensions now track the weight they consume during valdiation, preparation and + post-dispatch through the `TransactionExtensionBase::weight` function. + - `TestXt` was removed and its usage in tests was replaced with `UncheckedExtrinsic` + instances. + + To fix the build issues introduced by this change, use the `AsTransactionExtension` adapter + to wrap existing `SignedExtension`s by converting them using the `From` + generic implementation for `AsTransactionExtension`. More details on migrating existing + `SignedExtension` implementations to `TransactionExtension` in the PR description. + +crates: + - name: bridge-runtime-common + - name: bp-bridge-hub-cumulus + - name: bp-kusama + - name: bp-polkadot-bulletin + - name: bp-polkadot + - name: bp-rococo + - name: bp-westend + - name: bp-polkadot-core + - name: bp-runtime + - name: snowbridge-pallet-inbound-queue + - name: snowbridge-pallet-outbound-queue + - name: snowbridge-pallet-system + - name: snowbridge-runtime-test-common + - name: parachain-template-runtime + - name: asset-hub-rococo-runtime + - name: asset-hub-westend-runtime + - name: bridge-hub-rococo-runtime + - name: bridge-hub-westend-runtime + - name: collectives-westend-runtime + - name: contracts-rococo-runtime + - name: coretime-rococo-runtime + - name: coretime-westend-runtime + - name: glutton-westend-runtime + - name: people-rococo-runtime + - name: people-westend-runtime + - name: seedling-runtime + - name: shell-runtime + - name: penpal-runtime + - name: rococo-parachain-runtime + - name: polkadot-parachain-bin + - name: cumulus-primitives-storage-weight-reclaim + - name: cumulus-test-client + - name: cumulus-test-runtime + - name: cumulus-test-service + - name: polkadot-sdk-docs + - name: polkadot-service + - name: polkadot-test-service + - name: polkadot-runtime-common + - name: rococo-runtime + - name: polkadot-test-runtime + - name: westend-runtime + - name: staging-xcm-builder + - name: minimal-runtime + - name: node-template + - name: node-template-runtime + - name: staging-node-cli + - name: kitchensink-runtime + - name: node-testing + - name: sc-client-api + - name: sc-client-db + - name: sc-network-gossip + - name: sc-network-sync + - name: sc-transaction-pool + - name: frame + - name: pallet-babe + - name: pallet-balances + - name: pallet-beefy + - name: pallet-collective + - name: pallet-election-provider-multi-phase + - name: pallet-elections-phragmen + - name: pallet-example-basic + - name: pallet-example-offchain-worker + - name: frame-executive + - name: pallet-grandpa + - name: pallet-im-online + - name: pallet-offences + - name: pallet-sassafras + - name: pallet-state-trie-migration + - name: pallet-sudo + - name: frame-support-procedural + - name: frame-support + - name: frame-system + - name: frame-system-benchmarking + - name: pallet-transaction-payment + - name: pallet-asset-conversion-tx-payment + - name: pallet-asset-tx-payment + - name: pallet-skip-feeless-payment + - name: sp-inherents + - name: sp-metadata-ir + - name: sp-runtime + - name: substrate-test-runtime + - name: frame-benchmarking-cli + - name: frame-remote-externalities + - name: substrate-rpc-client diff --git a/substrate/.maintain/frame-weight-template.hbs b/substrate/.maintain/frame-weight-template.hbs index ecd384a5145..ec9eee205ce 100644 --- a/substrate/.maintain/frame-weight-template.hbs +++ b/substrate/.maintain/frame-weight-template.hbs @@ -33,7 +33,7 @@ pub trait WeightInfo { /// Weights for `{{pallet}}` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); -{{#if (eq pallet "frame_system")}} +{{#if (or (eq pallet "frame_system") (eq pallet "frame_system_extensions"))}} impl WeightInfo for SubstrateWeight { {{else}} impl WeightInfo for SubstrateWeight { diff --git a/substrate/bin/minimal/runtime/src/lib.rs b/substrate/bin/minimal/runtime/src/lib.rs index fb996aef46b..d3e8a2e8ec0 100644 --- a/substrate/bin/minimal/runtime/src/lib.rs +++ b/substrate/bin/minimal/runtime/src/lib.rs @@ -52,7 +52,7 @@ pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } -type SignedExtra = ( +type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -104,7 +104,7 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = FixedFee<1, ::Balance>; } -type Block = frame::runtime::types_common::BlockOf; +type Block = frame::runtime::types_common::BlockOf; type Header = HeaderFor; type RuntimeExecutive = diff --git a/substrate/bin/node-template/node/Cargo.toml b/substrate/bin/node-template/node/Cargo.toml index 9cba2b5a366..2f31947e492 100644 --- a/substrate/bin/node-template/node/Cargo.toml +++ b/substrate/bin/node-template/node/Cargo.toml @@ -78,6 +78,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "node-template-runtime/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "sc-service/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/substrate/bin/node-template/node/src/benchmarking.rs b/substrate/bin/node-template/node/src/benchmarking.rs index 6e29ad1a123..eacc367669c 100644 --- a/substrate/bin/node-template/node/src/benchmarking.rs +++ b/substrate/bin/node-template/node/src/benchmarking.rs @@ -109,7 +109,7 @@ pub fn create_benchmark_extrinsic( .checked_next_power_of_two() .map(|c| c / 2) .unwrap_or(2) as u64; - let extra: runtime::SignedExtra = ( + let tx_ext: runtime::TxExtension = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -121,11 +121,12 @@ pub fn create_benchmark_extrinsic( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); + ) + .into(); let raw_payload = runtime::SignedPayload::from_raw( call.clone(), - extra.clone(), + tx_ext.clone(), ( (), runtime::VERSION.spec_version, @@ -143,7 +144,7 @@ pub fn create_benchmark_extrinsic( call, sp_runtime::AccountId32::from(sender.public()).into(), runtime::Signature::Sr25519(signature), - extra, + tx_ext, ) } diff --git a/substrate/bin/node-template/runtime/Cargo.toml b/substrate/bin/node-template/runtime/Cargo.toml index 86bab0ca375..c7cffa568db 100644 --- a/substrate/bin/node-template/runtime/Cargo.toml +++ b/substrate/bin/node-template/runtime/Cargo.toml @@ -106,6 +106,7 @@ runtime-benchmarks = [ "pallet-sudo/runtime-benchmarks", "pallet-template/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ diff --git a/substrate/bin/node-template/runtime/src/lib.rs b/substrate/bin/node-template/runtime/src/lib.rs index 159697f427f..ee622a691b4 100644 --- a/substrate/bin/node-template/runtime/src/lib.rs +++ b/substrate/bin/node-template/runtime/src/lib.rs @@ -241,6 +241,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; type FeeMultiplierUpdate = ConstFeeMultiplier; + type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } impl pallet_sudo::Config for Runtime { @@ -276,8 +277,8 @@ pub type Address = sp_runtime::MultiAddress; pub type Header = generic::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( +/// The extension to the basic transaction logic. +pub type TxExtension = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -296,9 +297,9 @@ type Migrations = (); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -314,6 +315,7 @@ mod benches { frame_benchmarking::define_benchmarks!( [frame_benchmarking, BaselineBench::] [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_timestamp, Timestamp] [pallet_sudo, Sudo] @@ -498,6 +500,7 @@ impl_runtime_apis! { use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); @@ -514,6 +517,7 @@ impl_runtime_apis! { use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch}; use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use baseline::Pallet as BaselineBench; impl frame_system_benchmarking::Config for Runtime {} diff --git a/substrate/bin/node/cli/Cargo.toml b/substrate/bin/node/cli/Cargo.toml index abe284c41da..c91a83e6d6e 100644 --- a/substrate/bin/node/cli/Cargo.toml +++ b/substrate/bin/node/cli/Cargo.toml @@ -196,6 +196,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "kitchensink-runtime/runtime-benchmarks", "node-inspect?/runtime-benchmarks", + "pallet-asset-conversion-tx-payment/runtime-benchmarks", "pallet-asset-tx-payment/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -205,6 +206,7 @@ runtime-benchmarks = [ "pallet-skip-feeless-payment/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "sc-client-db/runtime-benchmarks", "sc-service/runtime-benchmarks", diff --git a/substrate/bin/node/cli/benches/block_production.rs b/substrate/bin/node/cli/benches/block_production.rs index 23a62cc0bd2..b98a321c338 100644 --- a/substrate/bin/node/cli/benches/block_production.rs +++ b/substrate/bin/node/cli/benches/block_production.rs @@ -110,7 +110,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { fn extrinsic_set_time(now: u64) -> OpaqueExtrinsic { kitchensink_runtime::UncheckedExtrinsic { - signature: None, + preamble: sp_runtime::generic::Preamble::Bare, function: kitchensink_runtime::RuntimeCall::Timestamp(pallet_timestamp::Call::set { now }), } .into() diff --git a/substrate/bin/node/cli/benches/executor.rs b/substrate/bin/node/cli/benches/executor.rs index a326e1a79ea..e13d34f9657 100644 --- a/substrate/bin/node/cli/benches/executor.rs +++ b/substrate/bin/node/cli/benches/executor.rs @@ -29,7 +29,7 @@ use sp_core::{ storage::well_known_keys, traits::{CallContext, CodeExecutor, RuntimeCode}, }; -use sp_runtime::traits::BlakeTwo256; +use sp_runtime::{generic::ExtrinsicFormat, traits::BlakeTwo256}; use sp_state_machine::TestExternalities as CoreTestExternalities; use staging_node_cli::service::RuntimeExecutor; @@ -144,11 +144,11 @@ fn test_blocks( ) -> Vec<(Vec, Hash)> { let mut test_ext = new_test_ext(genesis_config); let mut block1_extrinsics = vec![CheckedExtrinsic { - signed: None, + format: ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: 0 }), }]; block1_extrinsics.extend((0..20).map(|i| CheckedExtrinsic { - signed: Some((alice(), signed_extra(i, 0))), + format: ExtrinsicFormat::Signed(alice(), tx_ext(i, 0)), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 1 * DOLLARS, diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index 8f2aba6b44c..157f278fb53 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -107,18 +107,21 @@ pub fn create_extrinsic( .map(|c| c / 2) .unwrap_or(2) as u64; let tip = 0; - let extra: kitchensink_runtime::SignedExtra = + let tx_ext: kitchensink_runtime::TxExtension = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(generic::Era::mortal( - period, - best_block.saturated_into(), - )), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), + ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal( + period, + best_block.saturated_into(), + )), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), + ) + .into(), pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::< kitchensink_runtime::Runtime, @@ -128,15 +131,17 @@ pub fn create_extrinsic( let raw_payload = kitchensink_runtime::SignedPayload::from_raw( function.clone(), - extra.clone(), + tx_ext.clone(), ( - (), - kitchensink_runtime::VERSION.spec_version, - kitchensink_runtime::VERSION.transaction_version, - genesis_hash, - best_hash, - (), - (), + ( + (), + kitchensink_runtime::VERSION.spec_version, + kitchensink_runtime::VERSION.transaction_version, + genesis_hash, + best_hash, + (), + (), + ), (), ), ); @@ -146,7 +151,7 @@ pub fn create_extrinsic( function, sp_runtime::AccountId32::from(sender.public()).into(), kitchensink_runtime::Signature::Sr25519(signature), - extra, + tx_ext, ) } @@ -791,7 +796,7 @@ mod tests { use codec::Encode; use kitchensink_runtime::{ constants::{currency::CENTS, time::SLOT_DURATION}, - Address, BalancesCall, RuntimeCall, UncheckedExtrinsic, + Address, BalancesCall, RuntimeCall, TxExtension, UncheckedExtrinsic, }; use node_primitives::{Block, DigestItem, Signature}; use sc_client_api::BlockBackend; @@ -993,25 +998,31 @@ mod tests { let tx_payment = pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::from(0, None), ); - let extra = ( - check_non_zero_sender, - check_spec_version, - check_tx_version, - check_genesis, - check_era, - check_nonce, - check_weight, + let tx_ext: TxExtension = ( + ( + check_non_zero_sender, + check_spec_version, + check_tx_version, + check_genesis, + check_era, + check_nonce, + check_weight, + ) + .into(), tx_payment, ); let raw_payload = SignedPayload::from_raw( function, - extra, - ((), spec_version, transaction_version, genesis_hash, genesis_hash, (), (), ()), + tx_ext, + ( + ((), spec_version, transaction_version, genesis_hash, genesis_hash, (), ()), + (), + ), ); let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let (function, extra, _) = raw_payload.deconstruct(); + let (function, tx_ext, _) = raw_payload.deconstruct(); index += 1; - UncheckedExtrinsic::new_signed(function, from.into(), signature.into(), extra) + UncheckedExtrinsic::new_signed(function, from.into(), signature.into(), tx_ext) .into() }, ); diff --git a/substrate/bin/node/cli/tests/basic.rs b/substrate/bin/node/cli/tests/basic.rs index 525ab2e39c1..5fcb2295ef0 100644 --- a/substrate/bin/node/cli/tests/basic.rs +++ b/substrate/bin/node/cli/tests/basic.rs @@ -67,7 +67,7 @@ fn transfer_fee(extrinsic: &E) -> Balance { fn xt() -> UncheckedExtrinsic { sign(CheckedExtrinsic { - signed: Some((alice(), signed_extra(0, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(0, 0)), function: RuntimeCall::Balances(default_transfer_call()), }) } @@ -84,11 +84,11 @@ fn changes_trie_block() -> (Vec, Hash) { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time }), }, CheckedExtrinsic { - signed: Some((alice(), signed_extra(0, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(0, 0)), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 69 * DOLLARS, @@ -111,11 +111,11 @@ fn blocks() -> ((Vec, Hash), (Vec, Hash)) { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time1 }), }, CheckedExtrinsic { - signed: Some((alice(), signed_extra(0, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(0, 0)), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 69 * DOLLARS, @@ -131,18 +131,18 @@ fn blocks() -> ((Vec, Hash), (Vec, Hash)) { block1.1, vec![ CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time2 }), }, CheckedExtrinsic { - signed: Some((bob(), signed_extra(0, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(bob(), tx_ext(0, 0)), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: alice().into(), value: 5 * DOLLARS, }), }, CheckedExtrinsic { - signed: Some((alice(), signed_extra(1, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(1, 0)), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 15 * DOLLARS, @@ -166,11 +166,11 @@ fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec, Hash) { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time * 1000 }), }, CheckedExtrinsic { - signed: Some((alice(), signed_extra(nonce, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(nonce, 0)), function: RuntimeCall::System(frame_system::Call::remark { remark: vec![0; size] }), }, ], @@ -677,11 +677,11 @@ fn deploying_wasm_contract_should_work() { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time }), }, CheckedExtrinsic { - signed: Some((charlie(), signed_extra(0, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(charlie(), tx_ext(0, 0)), function: RuntimeCall::Contracts(pallet_contracts::Call::instantiate_with_code::< Runtime, > { @@ -694,7 +694,7 @@ fn deploying_wasm_contract_should_work() { }), }, CheckedExtrinsic { - signed: Some((charlie(), signed_extra(1, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(charlie(), tx_ext(1, 0)), function: RuntimeCall::Contracts(pallet_contracts::Call::call:: { dest: sp_runtime::MultiAddress::Id(addr.clone()), value: 10, diff --git a/substrate/bin/node/cli/tests/fees.rs b/substrate/bin/node/cli/tests/fees.rs index 8c7b3c87315..9d6407067a3 100644 --- a/substrate/bin/node/cli/tests/fees.rs +++ b/substrate/bin/node/cli/tests/fees.rs @@ -54,11 +54,11 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time1 }), }, CheckedExtrinsic { - signed: Some((charlie(), signed_extra(0, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(charlie(), tx_ext(0, 0)), function: RuntimeCall::Sudo(pallet_sudo::Call::sudo { call: Box::new(RuntimeCall::RootTesting( pallet_root_testing::Call::fill_block { ratio: Perbill::from_percent(60) }, @@ -77,11 +77,11 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() { block1.1, vec![ CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time2 }), }, CheckedExtrinsic { - signed: Some((charlie(), signed_extra(1, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(charlie(), tx_ext(1, 0)), function: RuntimeCall::System(frame_system::Call::remark { remark: vec![0; 1] }), }, ], @@ -147,7 +147,7 @@ fn transaction_fee_is_correct() { let tip = 1_000_000; let xt = sign(CheckedExtrinsic { - signed: Some((alice(), signed_extra(0, tip))), + format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(0, tip)), function: RuntimeCall::Balances(default_transfer_call()), }); @@ -211,7 +211,10 @@ fn block_weight_capacity_report() { let num_transfers = block_number * factor; let mut xts = (0..num_transfers) .map(|i| CheckedExtrinsic { - signed: Some((charlie(), signed_extra(nonce + i as Nonce, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed( + charlie(), + tx_ext(nonce + i as Nonce, 0), + ), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 0, @@ -222,7 +225,7 @@ fn block_weight_capacity_report() { xts.insert( 0, CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time * 1000 }), }, ); @@ -285,13 +288,16 @@ fn block_length_capacity_report() { previous_hash, vec![ CheckedExtrinsic { - signed: None, + format: sp_runtime::generic::ExtrinsicFormat::Bare, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time * 1000, }), }, CheckedExtrinsic { - signed: Some((charlie(), signed_extra(nonce, 0))), + format: sp_runtime::generic::ExtrinsicFormat::Signed( + charlie(), + tx_ext(nonce, 0), + ), function: RuntimeCall::System(frame_system::Call::remark { remark: vec![0u8; (block_number * factor) as usize], }), diff --git a/substrate/bin/node/cli/tests/submit_transaction.rs b/substrate/bin/node/cli/tests/submit_transaction.rs index 5cbb0103d47..f3a5bac8fb5 100644 --- a/substrate/bin/node/cli/tests/submit_transaction.rs +++ b/substrate/bin/node/cli/tests/submit_transaction.rs @@ -130,8 +130,8 @@ fn should_submit_signed_twice_from_the_same_account() { // now check that the transaction nonces are not equal let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { - let extra = tx.signature.unwrap().2; - extra.5 + let extra = tx.preamble.to_signed().unwrap().2; + (extra.0).5 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -179,8 +179,8 @@ fn should_submit_signed_twice_from_all_accounts() { // now check that the transaction nonces are not equal let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { - let extra = tx.signature.unwrap().2; - extra.5 + let extra = tx.preamble.to_signed().unwrap().2; + (extra.0).5 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -236,7 +236,7 @@ fn submitted_transaction_should_be_valid() { let source = TransactionSource::External; let extrinsic = UncheckedExtrinsic::decode(&mut &*tx0).unwrap(); // add balance to the account - let author = extrinsic.signature.clone().unwrap().0; + let author = extrinsic.preamble.clone().to_signed().clone().unwrap().0; let address = Indices::lookup(author).unwrap(); let data = pallet_balances::AccountData { free: 5_000_000_000_000, ..Default::default() }; let account = frame_system::AccountInfo { providers: 1, data, ..Default::default() }; diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml index 9607d05daf0..bdef42474d0 100644 --- a/substrate/bin/node/runtime/Cargo.toml +++ b/substrate/bin/node/runtime/Cargo.toml @@ -276,6 +276,7 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-alliance/runtime-benchmarks", + "pallet-asset-conversion-tx-payment/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-asset-rate/runtime-benchmarks", "pallet-asset-tx-payment/runtime-benchmarks", @@ -333,6 +334,7 @@ runtime-benchmarks = [ "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-tips/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-transaction-storage/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-tx-pause/runtime-benchmarks", diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 5431628c747..f4615802515 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -560,6 +560,7 @@ impl pallet_transaction_payment::Config for Runtime { MinimumMultiplier, MaximumMultiplier, >; + type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } impl pallet_asset_tx_payment::Config for Runtime { @@ -569,6 +570,9 @@ impl pallet_asset_tx_payment::Config for Runtime { pallet_assets::BalanceToAssetBalance, CreditToBlockAuthor, >; + type WeightInfo = pallet_asset_tx_payment::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = AssetTxHelper; } impl pallet_asset_conversion_tx_payment::Config for Runtime { @@ -579,6 +583,9 @@ impl pallet_asset_conversion_tx_payment::Config for Runtime { AssetConversion, Native, >; + type WeightInfo = pallet_asset_conversion_tx_payment::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = AssetConversionTxHelper; } impl pallet_skip_feeless_payment::Config for Runtime { @@ -1407,29 +1414,33 @@ where // so the actual block number is `n`. .saturating_sub(1); let era = Era::mortal(period, current_block); - let extra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(era), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), + let tx_ext: TxExtension = ( + ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(era), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), + ) + .into(), pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::::from( tip, None, ), ), ); - let raw_payload = SignedPayload::new(call, extra) + + let raw_payload = SignedPayload::new(call, tx_ext) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; let address = Indices::unlookup(account); - let (call, extra, _) = raw_payload.deconstruct(); - Some((call, (address, signature, extra))) + let (call, tx_ext, _) = raw_payload.deconstruct(); + Some((call, (address, signature, tx_ext))) } } @@ -2280,19 +2291,21 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. +/// The TransactionExtension to the basic transaction logic. /// /// When you change this, you **MUST** modify [`sign`] in `bin/node/testing/src/keyring.rs`! /// /// [`sign`]: <../../testing/src/keyring.rs.html> -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, +pub type TxExtension = ( + ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + ), pallet_skip_feeless_payment::SkipCheckIfFeeless< Runtime, pallet_asset_conversion_tx_payment::ChargeAssetTxPayment, @@ -2301,11 +2314,11 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; /// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; +pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -2360,6 +2373,106 @@ mod mmr { pub type Hashing = ::Hashing; } +#[cfg(feature = "runtime-benchmarks")] +pub struct AssetConversionTxHelper; + +#[cfg(feature = "runtime-benchmarks")] +impl pallet_asset_conversion_tx_payment::BenchmarkHelperTrait + for AssetConversionTxHelper +{ + fn create_asset_id_parameter(seed: u32) -> (u32, u32) { + (seed, seed) + } + + fn setup_balances_and_pool(asset_id: u32, account: AccountId) { + use frame_support::{assert_ok, traits::fungibles::Mutate}; + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + account.clone().into(), /* owner */ + true, /* is_sufficient */ + 1, + )); + + let lp_provider = account.clone(); + let _ = Balances::deposit_creating(&lp_provider, ((u64::MAX as u128) * 100).into()); + assert_ok!(Assets::mint_into( + asset_id.into(), + &lp_provider, + ((u64::MAX as u128) * 100).into() + )); + + let token_native = Box::new(NativeOrWithId::Native); + let token_second = Box::new(NativeOrWithId::WithId(asset_id)); + + assert_ok!(AssetConversion::create_pool( + RuntimeOrigin::signed(lp_provider.clone()), + token_native.clone(), + token_second.clone() + )); + + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(lp_provider.clone()), + token_native, + token_second, + u64::MAX.into(), // 1 desired + u64::MAX.into(), // 2 desired + 1, // 1 min + 1, // 2 min + lp_provider, + )); + } +} + +#[cfg(feature = "runtime-benchmarks")] +pub struct AssetTxHelper; + +#[cfg(feature = "runtime-benchmarks")] +impl pallet_asset_tx_payment::BenchmarkHelperTrait for AssetTxHelper { + fn create_asset_id_parameter(seed: u32) -> (u32, u32) { + (seed, seed) + } + + fn setup_balances_and_pool(asset_id: u32, account: AccountId) { + use frame_support::{assert_ok, traits::fungibles::Mutate}; + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + account.clone().into(), /* owner */ + true, /* is_sufficient */ + 1, + )); + + let lp_provider = account.clone(); + let _ = Balances::deposit_creating(&lp_provider, ((u64::MAX as u128) * 100).into()); + assert_ok!(Assets::mint_into( + asset_id.into(), + &lp_provider, + ((u64::MAX as u128) * 100).into() + )); + + let token_native = Box::new(NativeOrWithId::Native); + let token_second = Box::new(NativeOrWithId::WithId(asset_id)); + + assert_ok!(AssetConversion::create_pool( + RuntimeOrigin::signed(lp_provider.clone()), + token_native.clone(), + token_second.clone() + )); + + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(lp_provider.clone()), + token_native, + token_second, + u64::MAX.into(), // 1 desired + u64::MAX.into(), // 2 desired + 1, // 1 min + 1, // 2 min + lp_provider, + )); + } +} + #[cfg(feature = "runtime-benchmarks")] mod benches { frame_benchmarking::define_benchmarks!( @@ -2380,6 +2493,9 @@ mod benches { [tasks_example, TasksExample] [pallet_democracy, Democracy] [pallet_asset_conversion, AssetConversion] + [pallet_asset_conversion_tx_payment, AssetConversionTxPayment] + [pallet_asset_tx_payment, AssetTxPayment] + [pallet_transaction_payment, TransactionPayment] [pallet_election_provider_multi_phase, ElectionProviderMultiPhase] [pallet_election_provider_support_benchmarking, EPSBench::] [pallet_elections_phragmen, Elections] @@ -2413,6 +2529,7 @@ mod benches { [pallet_state_trie_migration, StateTrieMigration] [pallet_sudo, Sudo] [frame_system, SystemBench::] + [frame_system_extensions, SystemExtensionsBench::] [pallet_timestamp, Timestamp] [pallet_tips, Tips] [pallet_transaction_storage, TransactionStorage] @@ -2960,6 +3077,7 @@ impl_runtime_apis! { use pallet_offences_benchmarking::Pallet as OffencesBench; use pallet_election_provider_support_benchmarking::Pallet as EPSBench; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use baseline::Pallet as BaselineBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; @@ -2984,6 +3102,7 @@ impl_runtime_apis! { use pallet_offences_benchmarking::Pallet as OffencesBench; use pallet_election_provider_support_benchmarking::Pallet as EPSBench; use frame_system_benchmarking::Pallet as SystemBench; + use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use baseline::Pallet as BaselineBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; diff --git a/substrate/bin/node/testing/src/bench.rs b/substrate/bin/node/testing/src/bench.rs index df302a6453b..ccf79eed884 100644 --- a/substrate/bin/node/testing/src/bench.rs +++ b/substrate/bin/node/testing/src/bench.rs @@ -51,6 +51,7 @@ use sp_core::{ed25519, sr25519, traits::SpawnNamed, Pair, Public}; use sp_crypto_hashing::blake2_256; use sp_inherents::InherentData; use sp_runtime::{ + generic::{ExtrinsicFormat, Preamble}, traits::{Block as BlockT, IdentifyAccount, Verify}, OpaqueExtrinsic, }; @@ -295,10 +296,10 @@ impl<'a> Iterator for BlockContentIterator<'a> { let signed = self.keyring.sign( CheckedExtrinsic { - signed: Some(( + format: ExtrinsicFormat::Signed( sender, - signed_extra(0, kitchensink_runtime::ExistentialDeposit::get() + 1), - )), + tx_ext(0, kitchensink_runtime::ExistentialDeposit::get() + 1), + ), function: match self.content.block_type { BlockType::RandomTransfersKeepAlive => RuntimeCall::Balances(BalancesCall::transfer_keep_alive { @@ -562,11 +563,11 @@ impl BenchKeyring { tx_version: u32, genesis_hash: [u8; 32], ) -> UncheckedExtrinsic { - match xt.signed { - Some((signed, extra)) => { + match xt.format { + ExtrinsicFormat::Signed(signed, tx_ext) => { let payload = ( xt.function, - extra.clone(), + tx_ext.clone(), spec_version, tx_version, genesis_hash, @@ -581,11 +582,20 @@ impl BenchKeyring { } }); UncheckedExtrinsic { - signature: Some((sp_runtime::MultiAddress::Id(signed), signature, extra)), + preamble: Preamble::Signed( + sp_runtime::MultiAddress::Id(signed), + signature, + tx_ext, + ), function: payload.0, } }, - None => UncheckedExtrinsic { signature: None, function: xt.function }, + ExtrinsicFormat::Bare => + UncheckedExtrinsic { preamble: Preamble::Bare, function: xt.function }, + ExtrinsicFormat::General(tx_ext) => UncheckedExtrinsic { + preamble: sp_runtime::generic::Preamble::General(tx_ext), + function: xt.function, + }, } } diff --git a/substrate/bin/node/testing/src/keyring.rs b/substrate/bin/node/testing/src/keyring.rs index f712191bed6..13daf915325 100644 --- a/substrate/bin/node/testing/src/keyring.rs +++ b/substrate/bin/node/testing/src/keyring.rs @@ -19,13 +19,13 @@ //! Test accounts. use codec::Encode; -use kitchensink_runtime::{CheckedExtrinsic, SessionKeys, SignedExtra, UncheckedExtrinsic}; +use kitchensink_runtime::{CheckedExtrinsic, SessionKeys, TxExtension, UncheckedExtrinsic}; use node_cli::chain_spec::get_from_seed; use node_primitives::{AccountId, Balance, Nonce}; use sp_core::{ecdsa, ed25519, sr25519}; use sp_crypto_hashing::blake2_256; use sp_keyring::AccountKeyring; -use sp_runtime::generic::Era; +use sp_runtime::generic::{Era, ExtrinsicFormat}; /// Alice's account id. pub fn alice() -> AccountId { @@ -70,15 +70,18 @@ pub fn session_keys_from_seed(seed: &str) -> SessionKeys { } /// Returns transaction extra. -pub fn signed_extra(nonce: Nonce, extra_fee: Balance) -> SignedExtra { +pub fn tx_ext(nonce: Nonce, extra_fee: Balance) -> TxExtension { ( - frame_system::CheckNonZeroSender::new(), - frame_system::CheckSpecVersion::new(), - frame_system::CheckTxVersion::new(), - frame_system::CheckGenesis::new(), - frame_system::CheckEra::from(Era::mortal(256, 0)), - frame_system::CheckNonce::from(nonce), - frame_system::CheckWeight::new(), + ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::mortal(256, 0)), + frame_system::CheckNonce::from(nonce), + frame_system::CheckWeight::new(), + ) + .into(), pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::from(extra_fee, None), ), @@ -92,10 +95,10 @@ pub fn sign( tx_version: u32, genesis_hash: [u8; 32], ) -> UncheckedExtrinsic { - match xt.signed { - Some((signed, extra)) => { + match xt.format { + ExtrinsicFormat::Signed(signed, tx_ext) => { let payload = - (xt.function, extra.clone(), spec_version, tx_version, genesis_hash, genesis_hash); + (xt.function, tx_ext.clone(), spec_version, tx_version, genesis_hash, genesis_hash); let key = AccountKeyring::from_account_id(&signed).unwrap(); let signature = payload @@ -108,10 +111,21 @@ pub fn sign( }) .into(); UncheckedExtrinsic { - signature: Some((sp_runtime::MultiAddress::Id(signed), signature, extra)), + preamble: sp_runtime::generic::Preamble::Signed( + sp_runtime::MultiAddress::Id(signed), + signature, + tx_ext, + ), function: payload.0, } }, - None => UncheckedExtrinsic { signature: None, function: xt.function }, + ExtrinsicFormat::Bare => UncheckedExtrinsic { + preamble: sp_runtime::generic::Preamble::Bare, + function: xt.function, + }, + ExtrinsicFormat::General(tx_ext) => UncheckedExtrinsic { + preamble: sp_runtime::generic::Preamble::General(tx_ext), + function: xt.function, + }, } } diff --git a/substrate/client/api/src/notifications/tests.rs b/substrate/client/api/src/notifications/tests.rs index fba829b1cf9..7afdcbd9543 100644 --- a/substrate/client/api/src/notifications/tests.rs +++ b/substrate/client/api/src/notifications/tests.rs @@ -18,7 +18,10 @@ use super::*; -use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, H256 as Hash}; +use sp_runtime::{ + generic::UncheckedExtrinsic, + testing::{Block as RawBlock, H256 as Hash}, +}; use std::iter::{empty, Empty}; type TestChangeSet = ( @@ -50,7 +53,7 @@ impl PartialEq for StorageChangeSet { } } -type Block = RawBlock>; +type Block = RawBlock>; #[test] fn triggering_change_should_notify_wildcard_listeners() { diff --git a/substrate/client/db/benches/state_access.rs b/substrate/client/db/benches/state_access.rs index e47559e710d..9f3b8ca77c2 100644 --- a/substrate/client/db/benches/state_access.rs +++ b/substrate/client/db/benches/state_access.rs @@ -22,12 +22,13 @@ use sc_client_api::{Backend as _, BlockImportOperation, NewBlockState, StateBack use sc_client_db::{Backend, BlocksPruning, DatabaseSettings, DatabaseSource, PruningMode}; use sp_core::H256; use sp_runtime::{ - testing::{Block as RawBlock, ExtrinsicWrapper, Header}, + generic::UncheckedExtrinsic, + testing::{Block as RawBlock, Header, MockCallU64}, StateVersion, Storage, }; use tempfile::TempDir; -pub(crate) type Block = RawBlock>; +pub(crate) type Block = RawBlock>; fn insert_blocks(db: &Backend, storage: Vec<(Vec, Vec)>) -> H256 { let mut op = db.begin_operation().unwrap(); diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index 0faa90dfc4f..f22022ef29a 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/client/db/src/lib.rs @@ -2573,7 +2573,8 @@ pub(crate) mod tests { use sp_blockchain::{lowest_common_ancestor, tree_route}; use sp_core::H256; use sp_runtime::{ - testing::{Block as RawBlock, ExtrinsicWrapper, Header}, + generic::UncheckedExtrinsic, + testing::{Block as RawBlock, Header, MockCallU64}, traits::{BlakeTwo256, Hash}, ConsensusEngineId, StateVersion, }; @@ -2581,7 +2582,8 @@ pub(crate) mod tests { const CONS0_ENGINE_ID: ConsensusEngineId = *b"CON0"; const CONS1_ENGINE_ID: ConsensusEngineId = *b"CON1"; - pub(crate) type Block = RawBlock>; + type UncheckedXt = UncheckedExtrinsic; + pub(crate) type Block = RawBlock; pub fn insert_header( backend: &Backend, @@ -2600,7 +2602,7 @@ pub(crate) mod tests { parent_hash: H256, _changes: Option, Vec)>>, extrinsics_root: H256, - body: Vec>, + body: Vec, transaction_index: Option>, ) -> Result { use sp_runtime::testing::Digest; @@ -3414,7 +3416,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![i.into()], + vec![UncheckedXt::new_transaction(i.into(), ())], None, ) .unwrap(); @@ -3436,11 +3438,20 @@ pub(crate) mod tests { assert_eq!(None, bc.body(blocks[0]).unwrap()); assert_eq!(None, bc.body(blocks[1]).unwrap()); assert_eq!(None, bc.body(blocks[2]).unwrap()); - assert_eq!(Some(vec![3.into()]), bc.body(blocks[3]).unwrap()); - assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(3.into(), ())]), + bc.body(blocks[3]).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(4.into(), ())]), + bc.body(blocks[4]).unwrap() + ); } else { for i in 0..5 { - assert_eq!(Some(vec![(i as u64).into()]), bc.body(blocks[i]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction((i as u64).into(), ())]), + bc.body(blocks[i]).unwrap() + ); } } } @@ -3464,7 +3475,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![i.into()], + vec![UncheckedXt::new_transaction(i.into(), ())], None, ) .unwrap(); @@ -3473,16 +3484,26 @@ pub(crate) mod tests { } // insert a fork at block 2 - let fork_hash_root = - insert_block(&backend, 2, blocks[1], None, H256::random(), vec![2.into()], None) - .unwrap(); + let fork_hash_root = insert_block( + &backend, + 2, + blocks[1], + None, + H256::random(), + vec![UncheckedXt::new_transaction(2.into(), ())], + None, + ) + .unwrap(); insert_block( &backend, 3, fork_hash_root, None, H256::random(), - vec![3.into(), 11.into()], + vec![ + UncheckedXt::new_transaction(3.into(), ()), + UncheckedXt::new_transaction(11.into(), ()), + ], None, ) .unwrap(); @@ -3492,7 +3513,10 @@ pub(crate) mod tests { backend.commit_operation(op).unwrap(); let bc = backend.blockchain(); - assert_eq!(Some(vec![2.into()]), bc.body(fork_hash_root).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(2.into(), ())]), + bc.body(fork_hash_root).unwrap() + ); for i in 1..5 { let mut op = backend.begin_operation().unwrap(); @@ -3506,16 +3530,28 @@ pub(crate) mod tests { assert_eq!(None, bc.body(blocks[1]).unwrap()); assert_eq!(None, bc.body(blocks[2]).unwrap()); - assert_eq!(Some(vec![3.into()]), bc.body(blocks[3]).unwrap()); - assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(3.into(), ())]), + bc.body(blocks[3]).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(4.into(), ())]), + bc.body(blocks[4]).unwrap() + ); } else { for i in 0..5 { - assert_eq!(Some(vec![(i as u64).into()]), bc.body(blocks[i]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction((i as u64).into(), ())]), + bc.body(blocks[i]).unwrap() + ); } } if matches!(pruning, BlocksPruning::KeepAll) { - assert_eq!(Some(vec![2.into()]), bc.body(fork_hash_root).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(2.into(), ())]), + bc.body(fork_hash_root).unwrap() + ); } else { assert_eq!(None, bc.body(fork_hash_root).unwrap()); } @@ -3536,8 +3572,16 @@ pub(crate) mod tests { let backend = Backend::::new_test_with_tx_storage(BlocksPruning::Some(10), 10); let make_block = |index, parent, val: u64| { - insert_block(&backend, index, parent, None, H256::random(), vec![val.into()], None) - .unwrap() + insert_block( + &backend, + index, + parent, + None, + H256::random(), + vec![UncheckedXt::new_transaction(val.into(), ())], + None, + ) + .unwrap() }; let block_0 = make_block(0, Default::default(), 0x00); @@ -3565,18 +3609,30 @@ pub(crate) mod tests { let bc = backend.blockchain(); assert_eq!(None, bc.body(block_1b).unwrap()); assert_eq!(None, bc.body(block_2b).unwrap()); - assert_eq!(Some(vec![0x00.into()]), bc.body(block_0).unwrap()); - assert_eq!(Some(vec![0x1a.into()]), bc.body(block_1a).unwrap()); - assert_eq!(Some(vec![0x2a.into()]), bc.body(block_2a).unwrap()); - assert_eq!(Some(vec![0x3a.into()]), bc.body(block_3a).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(0x00.into(), ())]), + bc.body(block_0).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(0x1a.into(), ())]), + bc.body(block_1a).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(0x2a.into(), ())]), + bc.body(block_2a).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(0x3a.into(), ())]), + bc.body(block_3a).unwrap() + ); } #[test] fn indexed_data_block_body() { let backend = Backend::::new_test_with_tx_storage(BlocksPruning::Some(1), 10); - let x0 = ExtrinsicWrapper::from(0u64).encode(); - let x1 = ExtrinsicWrapper::from(1u64).encode(); + let x0 = UncheckedXt::new_transaction(0.into(), ()).encode(); + let x1 = UncheckedXt::new_transaction(1.into(), ()).encode(); let x0_hash = as sp_core::Hasher>::hash(&x0[1..]); let x1_hash = as sp_core::Hasher>::hash(&x1[1..]); let index = vec![ @@ -3597,7 +3653,10 @@ pub(crate) mod tests { Default::default(), None, Default::default(), - vec![0u64.into(), 1u64.into()], + vec![ + UncheckedXt::new_transaction(0.into(), ()), + UncheckedXt::new_transaction(1.into(), ()), + ], Some(index), ) .unwrap(); @@ -3619,8 +3678,9 @@ pub(crate) mod tests { fn index_invalid_size() { let backend = Backend::::new_test_with_tx_storage(BlocksPruning::Some(1), 10); - let x0 = ExtrinsicWrapper::from(0u64).encode(); - let x1 = ExtrinsicWrapper::from(1u64).encode(); + let x0 = UncheckedXt::new_transaction(0.into(), ()).encode(); + let x1 = UncheckedXt::new_transaction(1.into(), ()).encode(); + let x0_hash = as sp_core::Hasher>::hash(&x0[..]); let x1_hash = as sp_core::Hasher>::hash(&x1[..]); let index = vec![ @@ -3641,7 +3701,10 @@ pub(crate) mod tests { Default::default(), None, Default::default(), - vec![0u64.into(), 1u64.into()], + vec![ + UncheckedXt::new_transaction(0.into(), ()), + UncheckedXt::new_transaction(1.into(), ()), + ], Some(index), ) .unwrap(); @@ -3655,7 +3718,7 @@ pub(crate) mod tests { let backend = Backend::::new_test_with_tx_storage(BlocksPruning::Some(2), 10); let mut blocks = Vec::new(); let mut prev_hash = Default::default(); - let x1 = ExtrinsicWrapper::from(0u64).encode(); + let x1 = UncheckedXt::new_transaction(0.into(), ()).encode(); let x1_hash = as sp_core::Hasher>::hash(&x1[1..]); for i in 0..10 { let mut index = Vec::new(); @@ -3675,7 +3738,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![i.into()], + vec![UncheckedXt::new_transaction(i.into(), ())], Some(index), ) .unwrap(); @@ -3709,7 +3772,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![i.into()], + vec![UncheckedXt::new_transaction(i.into(), ())], None, ) .unwrap(); @@ -3724,7 +3787,7 @@ pub(crate) mod tests { blocks[1], None, sp_core::H256::random(), - vec![i.into()], + vec![UncheckedXt::new_transaction(i.into(), ())], None, ) .unwrap(); @@ -3738,7 +3801,7 @@ pub(crate) mod tests { blocks[0], None, sp_core::H256::random(), - vec![42.into()], + vec![UncheckedXt::new_transaction(42.into(), ())], None, ) .unwrap(); @@ -4211,7 +4274,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![i.into()], + vec![UncheckedXt::new_transaction(i.into(), ())], None, ) .unwrap(); @@ -4226,7 +4289,10 @@ pub(crate) mod tests { // Check that we can properly access values when there is reference count // but no value. - assert_eq!(Some(vec![1.into()]), bc.body(blocks[1]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(1.into(), ())]), + bc.body(blocks[1]).unwrap() + ); // Block 1 gets pinned three times backend.pin_block(blocks[1]).unwrap(); @@ -4243,27 +4309,42 @@ pub(crate) mod tests { // Block 0, 1, 2, 3 are pinned, so all values should be cached. // Block 4 is inside the pruning window, its value is in db. - assert_eq!(Some(vec![0.into()]), bc.body(blocks[0]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(0.into(), ())]), + bc.body(blocks[0]).unwrap() + ); - assert_eq!(Some(vec![1.into()]), bc.body(blocks[1]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(1.into(), ())]), + bc.body(blocks[1]).unwrap() + ); assert_eq!( Some(Justifications::from(build_justification(1))), bc.justifications(blocks[1]).unwrap() ); - assert_eq!(Some(vec![2.into()]), bc.body(blocks[2]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(2.into(), ())]), + bc.body(blocks[2]).unwrap() + ); assert_eq!( Some(Justifications::from(build_justification(2))), bc.justifications(blocks[2]).unwrap() ); - assert_eq!(Some(vec![3.into()]), bc.body(blocks[3]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(3.into(), ())]), + bc.body(blocks[3]).unwrap() + ); assert_eq!( Some(Justifications::from(build_justification(3))), bc.justifications(blocks[3]).unwrap() ); - assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(4.into(), ())]), + bc.body(blocks[4]).unwrap() + ); assert_eq!( Some(Justifications::from(build_justification(4))), bc.justifications(blocks[4]).unwrap() @@ -4294,7 +4375,10 @@ pub(crate) mod tests { assert!(bc.justifications(blocks[1]).unwrap().is_none()); // Block 4 is inside the pruning window and still kept - assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(4.into(), ())]), + bc.body(blocks[4]).unwrap() + ); assert_eq!( Some(Justifications::from(build_justification(4))), bc.justifications(blocks[4]).unwrap() @@ -4302,9 +4386,16 @@ pub(crate) mod tests { // Block tree: // 0 -> 1 -> 2 -> 3 -> 4 -> 5 - let hash = - insert_block(&backend, 5, prev_hash, None, Default::default(), vec![5.into()], None) - .unwrap(); + let hash = insert_block( + &backend, + 5, + prev_hash, + None, + Default::default(), + vec![UncheckedXt::new_transaction(5.into(), ())], + None, + ) + .unwrap(); blocks.push(hash); backend.pin_block(blocks[4]).unwrap(); @@ -4319,12 +4410,18 @@ pub(crate) mod tests { assert!(bc.body(blocks[2]).unwrap().is_none()); assert!(bc.body(blocks[3]).unwrap().is_none()); - assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(4.into(), ())]), + bc.body(blocks[4]).unwrap() + ); assert_eq!( Some(Justifications::from(build_justification(4))), bc.justifications(blocks[4]).unwrap() ); - assert_eq!(Some(vec![5.into()]), bc.body(blocks[5]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(5.into(), ())]), + bc.body(blocks[5]).unwrap() + ); assert!(bc.header(blocks[5]).ok().flatten().is_some()); backend.unpin_block(blocks[4]); @@ -4334,9 +4431,16 @@ pub(crate) mod tests { // Append a justification to block 5. backend.append_justification(blocks[5], ([0, 0, 0, 1], vec![42])).unwrap(); - let hash = - insert_block(&backend, 6, blocks[5], None, Default::default(), vec![6.into()], None) - .unwrap(); + let hash = insert_block( + &backend, + 6, + blocks[5], + None, + Default::default(), + vec![UncheckedXt::new_transaction(6.into(), ())], + None, + ) + .unwrap(); blocks.push(hash); // Pin block 5 so it gets loaded into the cache on prune @@ -4349,7 +4453,10 @@ pub(crate) mod tests { op.mark_finalized(blocks[6], None).unwrap(); backend.commit_operation(op).unwrap(); - assert_eq!(Some(vec![5.into()]), bc.body(blocks[5]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(5.into(), ())]), + bc.body(blocks[5]).unwrap() + ); assert!(bc.header(blocks[5]).ok().flatten().is_some()); let mut expected = Justifications::from(build_justification(5)); expected.append(([0, 0, 0, 1], vec![42])); @@ -4371,7 +4478,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![i.into()], + vec![UncheckedXt::new_transaction(i.into(), ())], None, ) .unwrap(); @@ -4387,16 +4494,26 @@ pub(crate) mod tests { // Block tree: // 0 -> 1 -> 2 -> 3 -> 4 // \ -> 2 -> 3 - let fork_hash_root = - insert_block(&backend, 2, blocks[1], None, H256::random(), vec![2.into()], None) - .unwrap(); + let fork_hash_root = insert_block( + &backend, + 2, + blocks[1], + None, + H256::random(), + vec![UncheckedXt::new_transaction(2.into(), ())], + None, + ) + .unwrap(); let fork_hash_3 = insert_block( &backend, 3, fork_hash_root, None, H256::random(), - vec![3.into(), 11.into()], + vec![ + UncheckedXt::new_transaction(3.into(), ()), + UncheckedXt::new_transaction(11.into(), ()), + ], None, ) .unwrap(); @@ -4417,14 +4534,35 @@ pub(crate) mod tests { } let bc = backend.blockchain(); - assert_eq!(Some(vec![0.into()]), bc.body(blocks[0]).unwrap()); - assert_eq!(Some(vec![1.into()]), bc.body(blocks[1]).unwrap()); - assert_eq!(Some(vec![2.into()]), bc.body(blocks[2]).unwrap()); - assert_eq!(Some(vec![3.into()]), bc.body(blocks[3]).unwrap()); - assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(0.into(), ())]), + bc.body(blocks[0]).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(1.into(), ())]), + bc.body(blocks[1]).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(2.into(), ())]), + bc.body(blocks[2]).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(3.into(), ())]), + bc.body(blocks[3]).unwrap() + ); + assert_eq!( + Some(vec![UncheckedXt::new_transaction(4.into(), ())]), + bc.body(blocks[4]).unwrap() + ); // Check the fork hashes. assert_eq!(None, bc.body(fork_hash_root).unwrap()); - assert_eq!(Some(vec![3.into(), 11.into()]), bc.body(fork_hash_3).unwrap()); + assert_eq!( + Some(vec![ + UncheckedXt::new_transaction(3.into(), ()), + UncheckedXt::new_transaction(11.into(), ()) + ]), + bc.body(fork_hash_3).unwrap() + ); // Unpin all blocks, except the forked one. for block in &blocks { diff --git a/substrate/client/db/src/utils.rs b/substrate/client/db/src/utils.rs index abf9c4629ce..d2a5f7e718a 100644 --- a/substrate/client/db/src/utils.rs +++ b/substrate/client/db/src/utils.rs @@ -582,14 +582,19 @@ impl<'a, 'b> codec::Input for JoinInput<'a, 'b> { mod tests { use super::*; use codec::Input; - use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper}; - type Block = RawBlock>; + use sp_runtime::{ + generic::UncheckedExtrinsic, + testing::{Block as RawBlock, MockCallU64}, + }; + + pub type UncheckedXt = UncheckedExtrinsic; + type Block = RawBlock; #[cfg(feature = "rocksdb")] #[test] fn database_type_subdir_migration() { use std::path::PathBuf; - type Block = RawBlock>; + type Block = RawBlock; fn check_dir_for_db_type( db_type: DatabaseType, diff --git a/substrate/client/network-gossip/src/state_machine.rs b/substrate/client/network-gossip/src/state_machine.rs index 069d7cdba16..f1c830341ea 100644 --- a/substrate/client/network-gossip/src/state_machine.rs +++ b/substrate/client/network-gossip/src/state_machine.rs @@ -550,7 +550,8 @@ mod tests { NotificationSenderError, NotificationSenderT as NotificationSender, ReputationChange, }; use sp_runtime::{ - testing::{Block as RawBlock, ExtrinsicWrapper, H256}, + generic::UncheckedExtrinsic, + testing::{Block as RawBlock, MockCallU64, H256}, traits::NumberFor, }; use std::{ @@ -559,7 +560,7 @@ mod tests { sync::{Arc, Mutex}, }; - type Block = RawBlock>; + type Block = RawBlock>; macro_rules! push_msg { ($consensus:expr, $topic:expr, $hash: expr, $m:expr) => { diff --git a/substrate/client/network/sync/src/blocks.rs b/substrate/client/network/sync/src/blocks.rs index 4988045a478..a115ee94767 100644 --- a/substrate/client/network/sync/src/blocks.rs +++ b/substrate/client/network/sync/src/blocks.rs @@ -265,9 +265,12 @@ mod test { use libp2p::PeerId; use sc_network_common::sync::message; use sp_core::H256; - use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper}; + use sp_runtime::{ + generic::UncheckedExtrinsic, + testing::{Block as RawBlock, MockCallU64}, + }; - type Block = RawBlock>; + type Block = RawBlock>; fn is_empty(bc: &BlockCollection) -> bool { bc.blocks.is_empty() && bc.peer_requests.is_empty() diff --git a/substrate/client/transaction-pool/src/lib.rs b/substrate/client/transaction-pool/src/lib.rs index 64b301e6bf3..730cfe36712 100644 --- a/substrate/client/transaction-pool/src/lib.rs +++ b/substrate/client/transaction-pool/src/lib.rs @@ -659,8 +659,13 @@ where }) .unwrap_or_default() .into_iter() - .filter(|tx| tx.is_signed().unwrap_or(true)); - + // TODO [#2415]: This isn't really what we mean - we really want a + // `tx.is_transaction`, since bare transactions may be gossipped as in the case + // of Frontier txs or claims. This will be sorted once we dispense with the + // concept of bare transactions and make inherents the only possible type of + // extrinsics which are bare. At this point we can change this to + // `tx.is_transaction()`. + .filter(|tx| !tx.is_bare()); let mut resubmitted_to_report = 0; resubmit_transactions.extend(block_transactions.into_iter().filter(|tx| { diff --git a/substrate/frame/alliance/src/weights.rs b/substrate/frame/alliance/src/weights.rs index b5bb5095720..0b2d1fca43c 100644 --- a/substrate/frame/alliance/src/weights.rs +++ b/substrate/frame/alliance/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_alliance +//! Autogenerated weights for `pallet_alliance` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/alliance/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/alliance/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_alliance. +/// Weight functions needed for `pallet_alliance`. pub trait WeightInfo { fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight; fn vote(m: u32, ) -> Weight; @@ -74,205 +73,209 @@ pub trait WeightInfo { fn abdicate_fellow_status() -> Weight; } -/// Weights for pallet_alliance using the Substrate node and recommended hardware. +/// Weights for `pallet_alliance` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion ProposalOf (r:1 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalCount (r:1 w:1) - /// Proof Skipped: AllianceMotion ProposalCount (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Voting (r:0 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::ProposalOf` (r:1 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalCount` (r:1 w:1) + /// Proof: `AllianceMotion::ProposalCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Voting` (r:0 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `653 + m * (32 ±0) + p * (35 ±0)` + // Measured: `654 + m * (32 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (32 ±0) + p * (36 ±0)` - // Minimum execution time: 36_908_000 picoseconds. - Weight::from_parts(39_040_304, 6676) - // Standard Error: 131 - .saturating_add(Weight::from_parts(781, 0).saturating_mul(b.into())) - // Standard Error: 1_375 - .saturating_add(Weight::from_parts(48_745, 0).saturating_mul(m.into())) - // Standard Error: 1_358 - .saturating_add(Weight::from_parts(148_047, 0).saturating_mul(p.into())) + // Minimum execution time: 30_801_000 picoseconds. + Weight::from_parts(32_942_969, 6676) + // Standard Error: 112 + .saturating_add(Weight::from_parts(614, 0).saturating_mul(b.into())) + // Standard Error: 1_177 + .saturating_add(Weight::from_parts(45_758, 0).saturating_mul(m.into())) + // Standard Error: 1_162 + .saturating_add(Weight::from_parts(136_600, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1042 + m * (64 ±0)` + // Measured: `1113 + m * (64 ±0)` // Estimated: `6676 + m * (64 ±0)` - // Minimum execution time: 30_166_000 picoseconds. - Weight::from_parts(32_798_454, 6676) - // Standard Error: 1_432 - .saturating_add(Weight::from_parts(83_001, 0).saturating_mul(m.into())) + // Minimum execution time: 29_705_000 picoseconds. + Weight::from_parts(30_274_070, 6676) + // Standard Error: 884 + .saturating_add(Weight::from_parts(71_178, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:1 w:0) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalOf (r:0 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:1 w:0) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `576 + m * (96 ±0) + p * (36 ±0)` + // Measured: `640 + m * (96 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 45_173_000 picoseconds. - Weight::from_parts(42_192_020, 6676) - // Standard Error: 1_456 - .saturating_add(Weight::from_parts(66_751, 0).saturating_mul(m.into())) - // Standard Error: 1_420 - .saturating_add(Weight::from_parts(158_161, 0).saturating_mul(p.into())) + // Minimum execution time: 38_596_000 picoseconds. + Weight::from_parts(36_445_536, 6676) + // Standard Error: 1_217 + .saturating_add(Weight::from_parts(69_976, 0).saturating_mul(m.into())) + // Standard Error: 1_187 + .saturating_add(Weight::from_parts(149_706, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:1 w:0) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalOf (r:1 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:1 w:0) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalOf` (r:1 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1087 + m * (96 ±0) + p * (39 ±0)` + // Measured: `1220 + m * (96 ±0) + p * (39 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (40 ±0)` - // Minimum execution time: 58_290_000 picoseconds. - Weight::from_parts(54_924_919, 6676) - // Standard Error: 157 - .saturating_add(Weight::from_parts(464, 0).saturating_mul(b.into())) - // Standard Error: 1_665 - .saturating_add(Weight::from_parts(73_183, 0).saturating_mul(m.into())) - // Standard Error: 1_623 - .saturating_add(Weight::from_parts(168_318, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Minimum execution time: 57_602_000 picoseconds. + Weight::from_parts(55_147_214, 6676) + // Standard Error: 127 + .saturating_add(Weight::from_parts(1_650, 0).saturating_mul(b.into())) + // Standard Error: 1_346 + .saturating_add(Weight::from_parts(56_056, 0).saturating_mul(m.into())) + // Standard Error: 1_312 + .saturating_add(Weight::from_parts(168_247, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:1 w:0) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:1 w:0) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalOf (r:0 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:1 w:0) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:1 w:0) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `577 + m * (96 ±0) + p * (36 ±0)` + // Measured: `641 + m * (96 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 46_794_000 picoseconds. - Weight::from_parts(43_092_958, 6676) - // Standard Error: 1_273 - .saturating_add(Weight::from_parts(71_054, 0).saturating_mul(m.into())) - // Standard Error: 1_257 - .saturating_add(Weight::from_parts(152_820, 0).saturating_mul(p.into())) + // Minimum execution time: 40_755_000 picoseconds. + Weight::from_parts(36_953_935, 6676) + // Standard Error: 1_177 + .saturating_add(Weight::from_parts(73_240, 0).saturating_mul(m.into())) + // Standard Error: 1_162 + .saturating_add(Weight::from_parts(149_412, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:1 w:0) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:1 w:0) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalOf (r:0 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:1 w:0) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:1 w:0) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[5, 100]`. /// The range of component `p` is `[1, 100]`. fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `684 + m * (96 ±0) + p * (35 ±0)` + // Measured: `694 + m * (96 ±0) + p * (35 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 47_338_000 picoseconds. - Weight::from_parts(41_257_479, 6676) - // Standard Error: 119 - .saturating_add(Weight::from_parts(1_019, 0).saturating_mul(b.into())) - // Standard Error: 1_277 - .saturating_add(Weight::from_parts(78_453, 0).saturating_mul(m.into())) - // Standard Error: 1_231 - .saturating_add(Weight::from_parts(150_991, 0).saturating_mul(p.into())) + // Minimum execution time: 41_113_000 picoseconds. + Weight::from_parts(36_610_116, 6676) + // Standard Error: 92 + .saturating_add(Weight::from_parts(1_157, 0).saturating_mul(b.into())) + // Standard Error: 984 + .saturating_add(Weight::from_parts(63_050, 0).saturating_mul(m.into())) + // Standard Error: 949 + .saturating_add(Weight::from_parts(150_420, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:2 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Members (r:1 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:2 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Members` (r:1 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 100]`. /// The range of component `z` is `[0, 100]`. fn init_members(m: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `217` + // Measured: `250` // Estimated: `12362` - // Minimum execution time: 35_012_000 picoseconds. - Weight::from_parts(24_288_079, 12362) - // Standard Error: 878 - .saturating_add(Weight::from_parts(153_615, 0).saturating_mul(m.into())) - // Standard Error: 867 - .saturating_add(Weight::from_parts(129_307, 0).saturating_mul(z.into())) + // Minimum execution time: 30_249_000 picoseconds. + Weight::from_parts(21_364_868, 12362) + // Standard Error: 887 + .saturating_add(Weight::from_parts(131_624, 0).saturating_mul(m.into())) + // Standard Error: 877 + .saturating_add(Weight::from_parts(105_379, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Alliance Members (r:2 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Alliance DepositOf (r:200 w:50) - /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) - /// Storage: System Account (r:50 w:50) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:2 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Alliance::DepositOf` (r:200 w:50) + /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:50 w:50) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `x` is `[1, 100]`. /// The range of component `y` is `[0, 100]`. /// The range of component `z` is `[0, 50]`. @@ -280,14 +283,14 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + x * (50 ±0) + y * (51 ±0) + z * (251 ±0)` // Estimated: `12362 + x * (2539 ±0) + y * (2539 ±0) + z * (2603 ±1)` - // Minimum execution time: 309_235_000 picoseconds. - Weight::from_parts(311_279_000, 12362) - // Standard Error: 26_510 - .saturating_add(Weight::from_parts(543_475, 0).saturating_mul(x.into())) - // Standard Error: 26_382 - .saturating_add(Weight::from_parts(603_169, 0).saturating_mul(y.into())) - // Standard Error: 52_716 - .saturating_add(Weight::from_parts(16_264_836, 0).saturating_mul(z.into())) + // Minimum execution time: 307_414_000 picoseconds. + Weight::from_parts(309_960_000, 12362) + // Standard Error: 29_278 + .saturating_add(Weight::from_parts(588_774, 0).saturating_mul(x.into())) + // Standard Error: 29_137 + .saturating_add(Weight::from_parts(563_245, 0).saturating_mul(y.into())) + // Standard Error: 58_221 + .saturating_add(Weight::from_parts(13_947_604, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y.into()))) @@ -298,397 +301,401 @@ impl WeightInfo for SubstrateWeight { .saturating_add(Weight::from_parts(0, 2539).saturating_mul(y.into())) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(z.into())) } - /// Storage: Alliance Rule (r:0 w:1) - /// Proof: Alliance Rule (max_values: Some(1), max_size: Some(87), added: 582, mode: MaxEncodedLen) + /// Storage: `Alliance::Rule` (r:0 w:1) + /// Proof: `Alliance::Rule` (`max_values`: Some(1), `max_size`: Some(87), added: 582, mode: `MaxEncodedLen`) fn set_rule() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_833_000 picoseconds. - Weight::from_parts(9_313_000, 0) + // Minimum execution time: 6_156_000 picoseconds. + Weight::from_parts(6_560_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Alliance Announcements (r:1 w:1) - /// Proof: Alliance Announcements (max_values: Some(1), max_size: Some(8702), added: 9197, mode: MaxEncodedLen) + /// Storage: `Alliance::Announcements` (r:1 w:1) + /// Proof: `Alliance::Announcements` (`max_values`: Some(1), `max_size`: Some(8702), added: 9197, mode: `MaxEncodedLen`) fn announce() -> Weight { // Proof Size summary in bytes: - // Measured: `246` + // Measured: `279` // Estimated: `10187` - // Minimum execution time: 12_231_000 picoseconds. - Weight::from_parts(12_761_000, 10187) + // Minimum execution time: 8_988_000 picoseconds. + Weight::from_parts(9_476_000, 10187) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Alliance Announcements (r:1 w:1) - /// Proof: Alliance Announcements (max_values: Some(1), max_size: Some(8702), added: 9197, mode: MaxEncodedLen) + /// Storage: `Alliance::Announcements` (r:1 w:1) + /// Proof: `Alliance::Announcements` (`max_values`: Some(1), `max_size`: Some(8702), added: 9197, mode: `MaxEncodedLen`) fn remove_announcement() -> Weight { // Proof Size summary in bytes: - // Measured: `319` + // Measured: `352` // Estimated: `10187` - // Minimum execution time: 13_079_000 picoseconds. - Weight::from_parts(13_612_000, 10187) + // Minimum execution time: 10_126_000 picoseconds. + Weight::from_parts(10_755_000, 10187) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Alliance Members (r:3 w:1) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: Alliance UnscrupulousAccounts (r:1 w:0) - /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Alliance DepositOf (r:0 w:1) - /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) + /// Storage: `Alliance::Members` (r:3 w:1) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:0) + /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Alliance::DepositOf` (r:0 w:1) + /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) fn join_alliance() -> Weight { // Proof Size summary in bytes: - // Measured: `468` + // Measured: `501` // Estimated: `18048` - // Minimum execution time: 44_574_000 picoseconds. - Weight::from_parts(46_157_000, 18048) + // Minimum execution time: 38_878_000 picoseconds. + Weight::from_parts(40_493_000, 18048) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Alliance Members (r:3 w:1) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: Alliance UnscrupulousAccounts (r:1 w:0) - /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: `Alliance::Members` (r:3 w:1) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:0) + /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) fn nominate_ally() -> Weight { // Proof Size summary in bytes: - // Measured: `367` + // Measured: `400` // Estimated: `18048` - // Minimum execution time: 26_114_000 picoseconds. - Weight::from_parts(27_069_000, 18048) + // Minimum execution time: 23_265_000 picoseconds. + Weight::from_parts(24_703_000, 18048) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Alliance Members (r:2 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:2 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn elevate_ally() -> Weight { // Proof Size summary in bytes: - // Measured: `443` + // Measured: `476` // Estimated: `12362` - // Minimum execution time: 25_882_000 picoseconds. - Weight::from_parts(26_923_000, 12362) + // Minimum execution time: 23_049_000 picoseconds. + Weight::from_parts(23_875_000, 12362) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Alliance Members (r:4 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Alliance RetiringMembers (r:0 w:1) - /// Proof: Alliance RetiringMembers (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Alliance::Members` (r:4 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Alliance::RetiringMembers` (r:0 w:1) + /// Proof: `Alliance::RetiringMembers` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn give_retirement_notice() -> Weight { // Proof Size summary in bytes: - // Measured: `443` + // Measured: `476` // Estimated: `23734` - // Minimum execution time: 34_112_000 picoseconds. - Weight::from_parts(35_499_000, 23734) + // Minimum execution time: 29_124_000 picoseconds. + Weight::from_parts(30_369_000, 23734) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Alliance RetiringMembers (r:1 w:1) - /// Proof: Alliance RetiringMembers (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: Alliance Members (r:1 w:1) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: Alliance DepositOf (r:1 w:1) - /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Alliance::RetiringMembers` (r:1 w:1) + /// Proof: `Alliance::RetiringMembers` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Alliance::Members` (r:1 w:1) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `Alliance::DepositOf` (r:1 w:1) + /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn retire() -> Weight { // Proof Size summary in bytes: - // Measured: `687` + // Measured: `720` // Estimated: `6676` - // Minimum execution time: 41_239_000 picoseconds. - Weight::from_parts(42_764_000, 6676) + // Minimum execution time: 36_376_000 picoseconds. + Weight::from_parts(38_221_000, 6676) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Alliance Members (r:3 w:1) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Alliance DepositOf (r:1 w:1) - /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:3 w:1) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Alliance::DepositOf` (r:1 w:1) + /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn kick_member() -> Weight { // Proof Size summary in bytes: - // Measured: `707` + // Measured: `740` // Estimated: `18048` - // Minimum execution time: 68_071_000 picoseconds. - Weight::from_parts(71_808_000, 18048) + // Minimum execution time: 56_560_000 picoseconds. + Weight::from_parts(58_621_000, 18048) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Alliance UnscrupulousAccounts (r:1 w:1) - /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: Alliance UnscrupulousWebsites (r:1 w:1) - /// Proof: Alliance UnscrupulousWebsites (max_values: Some(1), max_size: Some(25702), added: 26197, mode: MaxEncodedLen) + /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:1) + /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `Alliance::UnscrupulousWebsites` (r:1 w:1) + /// Proof: `Alliance::UnscrupulousWebsites` (`max_values`: Some(1), `max_size`: Some(25702), added: 26197, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. /// The range of component `l` is `[0, 255]`. fn add_unscrupulous_items(n: u32, l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `246` + // Measured: `279` // Estimated: `27187` - // Minimum execution time: 7_006_000 picoseconds. - Weight::from_parts(7_253_000, 27187) - // Standard Error: 3_403 - .saturating_add(Weight::from_parts(1_680_082, 0).saturating_mul(n.into())) - // Standard Error: 1_333 - .saturating_add(Weight::from_parts(72_943, 0).saturating_mul(l.into())) + // Minimum execution time: 5_191_000 picoseconds. + Weight::from_parts(5_410_000, 27187) + // Standard Error: 3_215 + .saturating_add(Weight::from_parts(1_018_569, 0).saturating_mul(n.into())) + // Standard Error: 1_259 + .saturating_add(Weight::from_parts(68_712, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Alliance UnscrupulousAccounts (r:1 w:1) - /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: Alliance UnscrupulousWebsites (r:1 w:1) - /// Proof: Alliance UnscrupulousWebsites (max_values: Some(1), max_size: Some(25702), added: 26197, mode: MaxEncodedLen) + /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:1) + /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `Alliance::UnscrupulousWebsites` (r:1 w:1) + /// Proof: `Alliance::UnscrupulousWebsites` (`max_values`: Some(1), `max_size`: Some(25702), added: 26197, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. /// The range of component `l` is `[0, 255]`. fn remove_unscrupulous_items(n: u32, l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + l * (100 ±0) + n * (289 ±0)` // Estimated: `27187` - // Minimum execution time: 7_292_000 picoseconds. - Weight::from_parts(7_629_000, 27187) - // Standard Error: 176_225 - .saturating_add(Weight::from_parts(16_646_429, 0).saturating_mul(n.into())) - // Standard Error: 69_017 - .saturating_add(Weight::from_parts(310_978, 0).saturating_mul(l.into())) + // Minimum execution time: 5_361_000 picoseconds. + Weight::from_parts(5_494_000, 27187) + // Standard Error: 181_133 + .saturating_add(Weight::from_parts(16_322_982, 0).saturating_mul(n.into())) + // Standard Error: 70_940 + .saturating_add(Weight::from_parts(343_581, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Alliance Members (r:3 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:3 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn abdicate_fellow_status() -> Weight { // Proof Size summary in bytes: - // Measured: `443` + // Measured: `476` // Estimated: `18048` - // Minimum execution time: 31_798_000 picoseconds. - Weight::from_parts(33_463_000, 18048) + // Minimum execution time: 28_856_000 picoseconds. + Weight::from_parts(29_875_000, 18048) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion ProposalOf (r:1 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalCount (r:1 w:1) - /// Proof Skipped: AllianceMotion ProposalCount (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Voting (r:0 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::ProposalOf` (r:1 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalCount` (r:1 w:1) + /// Proof: `AllianceMotion::ProposalCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Voting` (r:0 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `653 + m * (32 ±0) + p * (35 ±0)` + // Measured: `654 + m * (32 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (32 ±0) + p * (36 ±0)` - // Minimum execution time: 36_908_000 picoseconds. - Weight::from_parts(39_040_304, 6676) - // Standard Error: 131 - .saturating_add(Weight::from_parts(781, 0).saturating_mul(b.into())) - // Standard Error: 1_375 - .saturating_add(Weight::from_parts(48_745, 0).saturating_mul(m.into())) - // Standard Error: 1_358 - .saturating_add(Weight::from_parts(148_047, 0).saturating_mul(p.into())) + // Minimum execution time: 30_801_000 picoseconds. + Weight::from_parts(32_942_969, 6676) + // Standard Error: 112 + .saturating_add(Weight::from_parts(614, 0).saturating_mul(b.into())) + // Standard Error: 1_177 + .saturating_add(Weight::from_parts(45_758, 0).saturating_mul(m.into())) + // Standard Error: 1_162 + .saturating_add(Weight::from_parts(136_600, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1042 + m * (64 ±0)` + // Measured: `1113 + m * (64 ±0)` // Estimated: `6676 + m * (64 ±0)` - // Minimum execution time: 30_166_000 picoseconds. - Weight::from_parts(32_798_454, 6676) - // Standard Error: 1_432 - .saturating_add(Weight::from_parts(83_001, 0).saturating_mul(m.into())) + // Minimum execution time: 29_705_000 picoseconds. + Weight::from_parts(30_274_070, 6676) + // Standard Error: 884 + .saturating_add(Weight::from_parts(71_178, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:1 w:0) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalOf (r:0 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:1 w:0) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `576 + m * (96 ±0) + p * (36 ±0)` + // Measured: `640 + m * (96 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 45_173_000 picoseconds. - Weight::from_parts(42_192_020, 6676) - // Standard Error: 1_456 - .saturating_add(Weight::from_parts(66_751, 0).saturating_mul(m.into())) - // Standard Error: 1_420 - .saturating_add(Weight::from_parts(158_161, 0).saturating_mul(p.into())) + // Minimum execution time: 38_596_000 picoseconds. + Weight::from_parts(36_445_536, 6676) + // Standard Error: 1_217 + .saturating_add(Weight::from_parts(69_976, 0).saturating_mul(m.into())) + // Standard Error: 1_187 + .saturating_add(Weight::from_parts(149_706, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:1 w:0) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalOf (r:1 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:1 w:0) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalOf` (r:1 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1087 + m * (96 ±0) + p * (39 ±0)` + // Measured: `1220 + m * (96 ±0) + p * (39 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (40 ±0)` - // Minimum execution time: 58_290_000 picoseconds. - Weight::from_parts(54_924_919, 6676) - // Standard Error: 157 - .saturating_add(Weight::from_parts(464, 0).saturating_mul(b.into())) - // Standard Error: 1_665 - .saturating_add(Weight::from_parts(73_183, 0).saturating_mul(m.into())) - // Standard Error: 1_623 - .saturating_add(Weight::from_parts(168_318, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Minimum execution time: 57_602_000 picoseconds. + Weight::from_parts(55_147_214, 6676) + // Standard Error: 127 + .saturating_add(Weight::from_parts(1_650, 0).saturating_mul(b.into())) + // Standard Error: 1_346 + .saturating_add(Weight::from_parts(56_056, 0).saturating_mul(m.into())) + // Standard Error: 1_312 + .saturating_add(Weight::from_parts(168_247, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:1 w:0) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:1 w:0) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalOf (r:0 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:1 w:0) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:1 w:0) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `577 + m * (96 ±0) + p * (36 ±0)` + // Measured: `641 + m * (96 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 46_794_000 picoseconds. - Weight::from_parts(43_092_958, 6676) - // Standard Error: 1_273 - .saturating_add(Weight::from_parts(71_054, 0).saturating_mul(m.into())) - // Standard Error: 1_257 - .saturating_add(Weight::from_parts(152_820, 0).saturating_mul(p.into())) + // Minimum execution time: 40_755_000 picoseconds. + Weight::from_parts(36_953_935, 6676) + // Standard Error: 1_177 + .saturating_add(Weight::from_parts(73_240, 0).saturating_mul(m.into())) + // Standard Error: 1_162 + .saturating_add(Weight::from_parts(149_412, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:1 w:0) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Voting (r:1 w:1) - /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:1 w:0) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:1 w:0) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Proposals (r:1 w:1) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion ProposalOf (r:0 w:1) - /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:1 w:0) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Voting` (r:1 w:1) + /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:1 w:0) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:1 w:0) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:1) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) + /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[5, 100]`. /// The range of component `p` is `[1, 100]`. fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `684 + m * (96 ±0) + p * (35 ±0)` + // Measured: `694 + m * (96 ±0) + p * (35 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 47_338_000 picoseconds. - Weight::from_parts(41_257_479, 6676) - // Standard Error: 119 - .saturating_add(Weight::from_parts(1_019, 0).saturating_mul(b.into())) - // Standard Error: 1_277 - .saturating_add(Weight::from_parts(78_453, 0).saturating_mul(m.into())) - // Standard Error: 1_231 - .saturating_add(Weight::from_parts(150_991, 0).saturating_mul(p.into())) + // Minimum execution time: 41_113_000 picoseconds. + Weight::from_parts(36_610_116, 6676) + // Standard Error: 92 + .saturating_add(Weight::from_parts(1_157, 0).saturating_mul(b.into())) + // Standard Error: 984 + .saturating_add(Weight::from_parts(63_050, 0).saturating_mul(m.into())) + // Standard Error: 949 + .saturating_add(Weight::from_parts(150_420, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Alliance Members (r:2 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Members (r:1 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:2 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Members` (r:1 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 100]`. /// The range of component `z` is `[0, 100]`. fn init_members(m: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `217` + // Measured: `250` // Estimated: `12362` - // Minimum execution time: 35_012_000 picoseconds. - Weight::from_parts(24_288_079, 12362) - // Standard Error: 878 - .saturating_add(Weight::from_parts(153_615, 0).saturating_mul(m.into())) - // Standard Error: 867 - .saturating_add(Weight::from_parts(129_307, 0).saturating_mul(z.into())) + // Minimum execution time: 30_249_000 picoseconds. + Weight::from_parts(21_364_868, 12362) + // Standard Error: 887 + .saturating_add(Weight::from_parts(131_624, 0).saturating_mul(m.into())) + // Standard Error: 877 + .saturating_add(Weight::from_parts(105_379, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Alliance Members (r:2 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Alliance DepositOf (r:200 w:50) - /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) - /// Storage: System Account (r:50 w:50) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:2 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Alliance::DepositOf` (r:200 w:50) + /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:50 w:50) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `x` is `[1, 100]`. /// The range of component `y` is `[0, 100]`. /// The range of component `z` is `[0, 50]`. @@ -696,14 +703,14 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + x * (50 ±0) + y * (51 ±0) + z * (251 ±0)` // Estimated: `12362 + x * (2539 ±0) + y * (2539 ±0) + z * (2603 ±1)` - // Minimum execution time: 309_235_000 picoseconds. - Weight::from_parts(311_279_000, 12362) - // Standard Error: 26_510 - .saturating_add(Weight::from_parts(543_475, 0).saturating_mul(x.into())) - // Standard Error: 26_382 - .saturating_add(Weight::from_parts(603_169, 0).saturating_mul(y.into())) - // Standard Error: 52_716 - .saturating_add(Weight::from_parts(16_264_836, 0).saturating_mul(z.into())) + // Minimum execution time: 307_414_000 picoseconds. + Weight::from_parts(309_960_000, 12362) + // Standard Error: 29_278 + .saturating_add(Weight::from_parts(588_774, 0).saturating_mul(x.into())) + // Standard Error: 29_137 + .saturating_add(Weight::from_parts(563_245, 0).saturating_mul(y.into())) + // Standard Error: 58_221 + .saturating_add(Weight::from_parts(13_947_604, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(y.into()))) @@ -714,194 +721,194 @@ impl WeightInfo for () { .saturating_add(Weight::from_parts(0, 2539).saturating_mul(y.into())) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(z.into())) } - /// Storage: Alliance Rule (r:0 w:1) - /// Proof: Alliance Rule (max_values: Some(1), max_size: Some(87), added: 582, mode: MaxEncodedLen) + /// Storage: `Alliance::Rule` (r:0 w:1) + /// Proof: `Alliance::Rule` (`max_values`: Some(1), `max_size`: Some(87), added: 582, mode: `MaxEncodedLen`) fn set_rule() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_833_000 picoseconds. - Weight::from_parts(9_313_000, 0) + // Minimum execution time: 6_156_000 picoseconds. + Weight::from_parts(6_560_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Alliance Announcements (r:1 w:1) - /// Proof: Alliance Announcements (max_values: Some(1), max_size: Some(8702), added: 9197, mode: MaxEncodedLen) + /// Storage: `Alliance::Announcements` (r:1 w:1) + /// Proof: `Alliance::Announcements` (`max_values`: Some(1), `max_size`: Some(8702), added: 9197, mode: `MaxEncodedLen`) fn announce() -> Weight { // Proof Size summary in bytes: - // Measured: `246` + // Measured: `279` // Estimated: `10187` - // Minimum execution time: 12_231_000 picoseconds. - Weight::from_parts(12_761_000, 10187) + // Minimum execution time: 8_988_000 picoseconds. + Weight::from_parts(9_476_000, 10187) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Alliance Announcements (r:1 w:1) - /// Proof: Alliance Announcements (max_values: Some(1), max_size: Some(8702), added: 9197, mode: MaxEncodedLen) + /// Storage: `Alliance::Announcements` (r:1 w:1) + /// Proof: `Alliance::Announcements` (`max_values`: Some(1), `max_size`: Some(8702), added: 9197, mode: `MaxEncodedLen`) fn remove_announcement() -> Weight { // Proof Size summary in bytes: - // Measured: `319` + // Measured: `352` // Estimated: `10187` - // Minimum execution time: 13_079_000 picoseconds. - Weight::from_parts(13_612_000, 10187) + // Minimum execution time: 10_126_000 picoseconds. + Weight::from_parts(10_755_000, 10187) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Alliance Members (r:3 w:1) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: Alliance UnscrupulousAccounts (r:1 w:0) - /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Alliance DepositOf (r:0 w:1) - /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) + /// Storage: `Alliance::Members` (r:3 w:1) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:0) + /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Alliance::DepositOf` (r:0 w:1) + /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) fn join_alliance() -> Weight { // Proof Size summary in bytes: - // Measured: `468` + // Measured: `501` // Estimated: `18048` - // Minimum execution time: 44_574_000 picoseconds. - Weight::from_parts(46_157_000, 18048) + // Minimum execution time: 38_878_000 picoseconds. + Weight::from_parts(40_493_000, 18048) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Alliance Members (r:3 w:1) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: Alliance UnscrupulousAccounts (r:1 w:0) - /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: `Alliance::Members` (r:3 w:1) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:0) + /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) fn nominate_ally() -> Weight { // Proof Size summary in bytes: - // Measured: `367` + // Measured: `400` // Estimated: `18048` - // Minimum execution time: 26_114_000 picoseconds. - Weight::from_parts(27_069_000, 18048) + // Minimum execution time: 23_265_000 picoseconds. + Weight::from_parts(24_703_000, 18048) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Alliance Members (r:2 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:2 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn elevate_ally() -> Weight { // Proof Size summary in bytes: - // Measured: `443` + // Measured: `476` // Estimated: `12362` - // Minimum execution time: 25_882_000 picoseconds. - Weight::from_parts(26_923_000, 12362) + // Minimum execution time: 23_049_000 picoseconds. + Weight::from_parts(23_875_000, 12362) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Alliance Members (r:4 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Alliance RetiringMembers (r:0 w:1) - /// Proof: Alliance RetiringMembers (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Alliance::Members` (r:4 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Alliance::RetiringMembers` (r:0 w:1) + /// Proof: `Alliance::RetiringMembers` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn give_retirement_notice() -> Weight { // Proof Size summary in bytes: - // Measured: `443` + // Measured: `476` // Estimated: `23734` - // Minimum execution time: 34_112_000 picoseconds. - Weight::from_parts(35_499_000, 23734) + // Minimum execution time: 29_124_000 picoseconds. + Weight::from_parts(30_369_000, 23734) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Alliance RetiringMembers (r:1 w:1) - /// Proof: Alliance RetiringMembers (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: Alliance Members (r:1 w:1) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: Alliance DepositOf (r:1 w:1) - /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Alliance::RetiringMembers` (r:1 w:1) + /// Proof: `Alliance::RetiringMembers` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Alliance::Members` (r:1 w:1) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `Alliance::DepositOf` (r:1 w:1) + /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn retire() -> Weight { // Proof Size summary in bytes: - // Measured: `687` + // Measured: `720` // Estimated: `6676` - // Minimum execution time: 41_239_000 picoseconds. - Weight::from_parts(42_764_000, 6676) + // Minimum execution time: 36_376_000 picoseconds. + Weight::from_parts(38_221_000, 6676) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Alliance Members (r:3 w:1) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Alliance DepositOf (r:1 w:1) - /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:3 w:1) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Alliance::DepositOf` (r:1 w:1) + /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn kick_member() -> Weight { // Proof Size summary in bytes: - // Measured: `707` + // Measured: `740` // Estimated: `18048` - // Minimum execution time: 68_071_000 picoseconds. - Weight::from_parts(71_808_000, 18048) + // Minimum execution time: 56_560_000 picoseconds. + Weight::from_parts(58_621_000, 18048) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Alliance UnscrupulousAccounts (r:1 w:1) - /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: Alliance UnscrupulousWebsites (r:1 w:1) - /// Proof: Alliance UnscrupulousWebsites (max_values: Some(1), max_size: Some(25702), added: 26197, mode: MaxEncodedLen) + /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:1) + /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `Alliance::UnscrupulousWebsites` (r:1 w:1) + /// Proof: `Alliance::UnscrupulousWebsites` (`max_values`: Some(1), `max_size`: Some(25702), added: 26197, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. /// The range of component `l` is `[0, 255]`. fn add_unscrupulous_items(n: u32, l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `246` + // Measured: `279` // Estimated: `27187` - // Minimum execution time: 7_006_000 picoseconds. - Weight::from_parts(7_253_000, 27187) - // Standard Error: 3_403 - .saturating_add(Weight::from_parts(1_680_082, 0).saturating_mul(n.into())) - // Standard Error: 1_333 - .saturating_add(Weight::from_parts(72_943, 0).saturating_mul(l.into())) + // Minimum execution time: 5_191_000 picoseconds. + Weight::from_parts(5_410_000, 27187) + // Standard Error: 3_215 + .saturating_add(Weight::from_parts(1_018_569, 0).saturating_mul(n.into())) + // Standard Error: 1_259 + .saturating_add(Weight::from_parts(68_712, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Alliance UnscrupulousAccounts (r:1 w:1) - /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: Alliance UnscrupulousWebsites (r:1 w:1) - /// Proof: Alliance UnscrupulousWebsites (max_values: Some(1), max_size: Some(25702), added: 26197, mode: MaxEncodedLen) + /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:1) + /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `Alliance::UnscrupulousWebsites` (r:1 w:1) + /// Proof: `Alliance::UnscrupulousWebsites` (`max_values`: Some(1), `max_size`: Some(25702), added: 26197, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. /// The range of component `l` is `[0, 255]`. fn remove_unscrupulous_items(n: u32, l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + l * (100 ±0) + n * (289 ±0)` // Estimated: `27187` - // Minimum execution time: 7_292_000 picoseconds. - Weight::from_parts(7_629_000, 27187) - // Standard Error: 176_225 - .saturating_add(Weight::from_parts(16_646_429, 0).saturating_mul(n.into())) - // Standard Error: 69_017 - .saturating_add(Weight::from_parts(310_978, 0).saturating_mul(l.into())) + // Minimum execution time: 5_361_000 picoseconds. + Weight::from_parts(5_494_000, 27187) + // Standard Error: 181_133 + .saturating_add(Weight::from_parts(16_322_982, 0).saturating_mul(n.into())) + // Standard Error: 70_940 + .saturating_add(Weight::from_parts(343_581, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Alliance Members (r:3 w:2) - /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) - /// Storage: AllianceMotion Proposals (r:1 w:0) - /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Members (r:0 w:1) - /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: AllianceMotion Prime (r:0 w:1) - /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Alliance::Members` (r:3 w:2) + /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) + /// Storage: `AllianceMotion::Proposals` (r:1 w:0) + /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Members` (r:0 w:1) + /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AllianceMotion::Prime` (r:0 w:1) + /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn abdicate_fellow_status() -> Weight { // Proof Size summary in bytes: - // Measured: `443` + // Measured: `476` // Estimated: `18048` - // Minimum execution time: 31_798_000 picoseconds. - Weight::from_parts(33_463_000, 18048) + // Minimum execution time: 28_856_000 picoseconds. + Weight::from_parts(29_875_000, 18048) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } diff --git a/substrate/frame/asset-conversion/src/weights.rs b/substrate/frame/asset-conversion/src/weights.rs index a0e687f7a41..4eaa115c694 100644 --- a/substrate/frame/asset-conversion/src/weights.rs +++ b/substrate/frame/asset-conversion/src/weights.rs @@ -17,24 +17,28 @@ //! Autogenerated weights for `pallet_asset_conversion` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-30, STEPS: `5`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `cob`, CPU: `` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/debug/substrate-node +// ./target/production/substrate-node // benchmark // pallet // --chain=dev -// --steps=5 -// --repeat=2 -// --pallet=pallet-asset-conversion +// --steps=50 +// --repeat=20 +// --pallet=pallet_asset_conversion +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 // --output=./substrate/frame/asset-conversion/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -59,11 +63,9 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// Storage: `AssetConversion::Pools` (r:1 w:1) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:2 w:2) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:2 w:2) + /// Storage: `Assets::Asset` (r:2 w:0) /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetConversion::NextPoolAssetId` (r:1 w:1) /// Proof: `AssetConversion::NextPoolAssetId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -73,12 +75,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `1081` + // Measured: `910` // Estimated: `6360` - // Minimum execution time: 1_576_000_000 picoseconds. - Weight::from_parts(1_668_000_000, 6360) - .saturating_add(T::DbWeight::get().reads(10_u64)) - .saturating_add(T::DbWeight::get().writes(10_u64)) + // Minimum execution time: 82_941_000 picoseconds. + Weight::from_parts(85_526_000, 6360) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `AssetConversion::Pools` (r:1 w:0) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) @@ -86,18 +88,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `Assets::Account` (r:4 w:4) /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `PoolAssets::Asset` (r:1 w:1) /// Proof: `PoolAssets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `PoolAssets::Account` (r:2 w:2) /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn add_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `1761` + // Measured: `1507` // Estimated: `11426` - // Minimum execution time: 1_636_000_000 picoseconds. - Weight::from_parts(1_894_000_000, 11426) - .saturating_add(T::DbWeight::get().reads(10_u64)) - .saturating_add(T::DbWeight::get().writes(9_u64)) + // Minimum execution time: 138_424_000 picoseconds. + Weight::from_parts(142_083_000, 11426) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(10_u64)) } /// Storage: `AssetConversion::Pools` (r:1 w:0) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) @@ -111,10 +115,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn remove_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `1750` + // Measured: `1650` // Estimated: `11426` - // Minimum execution time: 1_507_000_000 picoseconds. - Weight::from_parts(1_524_000_000, 11426) + // Minimum execution time: 122_132_000 picoseconds. + Weight::from_parts(125_143_000, 11426) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -125,12 +129,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[2, 4]`. fn swap_exact_tokens_for_tokens(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + n * (522 ±0)` + // Measured: `89 + n * (419 ±0)` // Estimated: `990 + n * (5218 ±0)` - // Minimum execution time: 937_000_000 picoseconds. - Weight::from_parts(941_000_000, 990) - // Standard Error: 40_863_477 - .saturating_add(Weight::from_parts(205_862_068, 0).saturating_mul(n.into())) + // Minimum execution time: 77_183_000 picoseconds. + Weight::from_parts(78_581_000, 990) + // Standard Error: 306_918 + .saturating_add(Weight::from_parts(10_581_054, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 5218).saturating_mul(n.into())) @@ -142,12 +146,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[2, 4]`. fn swap_tokens_for_exact_tokens(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + n * (522 ±0)` + // Measured: `89 + n * (419 ±0)` // Estimated: `990 + n * (5218 ±0)` - // Minimum execution time: 935_000_000 picoseconds. - Weight::from_parts(947_000_000, 990) - // Standard Error: 46_904_620 - .saturating_add(Weight::from_parts(218_275_862, 0).saturating_mul(n.into())) + // Minimum execution time: 76_962_000 picoseconds. + Weight::from_parts(78_315_000, 990) + // Standard Error: 311_204 + .saturating_add(Weight::from_parts(10_702_400, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 5218).saturating_mul(n.into())) @@ -158,11 +162,9 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { /// Storage: `AssetConversion::Pools` (r:1 w:1) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:2 w:2) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:2 w:2) + /// Storage: `Assets::Asset` (r:2 w:0) /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetConversion::NextPoolAssetId` (r:1 w:1) /// Proof: `AssetConversion::NextPoolAssetId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -172,12 +174,12 @@ impl WeightInfo for () { /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `1081` + // Measured: `910` // Estimated: `6360` - // Minimum execution time: 1_576_000_000 picoseconds. - Weight::from_parts(1_668_000_000, 6360) - .saturating_add(RocksDbWeight::get().reads(10_u64)) - .saturating_add(RocksDbWeight::get().writes(10_u64)) + // Minimum execution time: 82_941_000 picoseconds. + Weight::from_parts(85_526_000, 6360) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `AssetConversion::Pools` (r:1 w:0) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) @@ -185,18 +187,20 @@ impl WeightInfo for () { /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `Assets::Account` (r:4 w:4) /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `PoolAssets::Asset` (r:1 w:1) /// Proof: `PoolAssets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `PoolAssets::Account` (r:2 w:2) /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn add_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `1761` + // Measured: `1507` // Estimated: `11426` - // Minimum execution time: 1_636_000_000 picoseconds. - Weight::from_parts(1_894_000_000, 11426) - .saturating_add(RocksDbWeight::get().reads(10_u64)) - .saturating_add(RocksDbWeight::get().writes(9_u64)) + // Minimum execution time: 138_424_000 picoseconds. + Weight::from_parts(142_083_000, 11426) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(RocksDbWeight::get().writes(10_u64)) } /// Storage: `AssetConversion::Pools` (r:1 w:0) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) @@ -210,10 +214,10 @@ impl WeightInfo for () { /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn remove_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `1750` + // Measured: `1650` // Estimated: `11426` - // Minimum execution time: 1_507_000_000 picoseconds. - Weight::from_parts(1_524_000_000, 11426) + // Minimum execution time: 122_132_000 picoseconds. + Weight::from_parts(125_143_000, 11426) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } @@ -224,12 +228,12 @@ impl WeightInfo for () { /// The range of component `n` is `[2, 4]`. fn swap_exact_tokens_for_tokens(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + n * (522 ±0)` + // Measured: `89 + n * (419 ±0)` // Estimated: `990 + n * (5218 ±0)` - // Minimum execution time: 937_000_000 picoseconds. - Weight::from_parts(941_000_000, 990) - // Standard Error: 40_863_477 - .saturating_add(Weight::from_parts(205_862_068, 0).saturating_mul(n.into())) + // Minimum execution time: 77_183_000 picoseconds. + Weight::from_parts(78_581_000, 990) + // Standard Error: 306_918 + .saturating_add(Weight::from_parts(10_581_054, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 5218).saturating_mul(n.into())) @@ -241,12 +245,12 @@ impl WeightInfo for () { /// The range of component `n` is `[2, 4]`. fn swap_tokens_for_exact_tokens(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + n * (522 ±0)` + // Measured: `89 + n * (419 ±0)` // Estimated: `990 + n * (5218 ±0)` - // Minimum execution time: 935_000_000 picoseconds. - Weight::from_parts(947_000_000, 990) - // Standard Error: 46_904_620 - .saturating_add(Weight::from_parts(218_275_862, 0).saturating_mul(n.into())) + // Minimum execution time: 76_962_000 picoseconds. + Weight::from_parts(78_315_000, 990) + // Standard Error: 311_204 + .saturating_add(Weight::from_parts(10_702_400, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 5218).saturating_mul(n.into())) diff --git a/substrate/frame/asset-rate/src/weights.rs b/substrate/frame/asset-rate/src/weights.rs index 582e20e56d7..b8723ee3bed 100644 --- a/substrate/frame/asset-rate/src/weights.rs +++ b/substrate/frame/asset-rate/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_asset_rate +//! Autogenerated weights for `pallet_asset_rate` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/asset-rate/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/asset-rate/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,83 +49,83 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_asset_rate. +/// Weight functions needed for `pallet_asset_rate`. pub trait WeightInfo { fn create() -> Weight; fn update() -> Weight; fn remove() -> Weight; } -/// Weights for pallet_asset_rate using the Substrate node and recommended hardware. +/// Weights for `pallet_asset_rate` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3501` - // Minimum execution time: 11_700_000 picoseconds. - Weight::from_parts(12_158_000, 3501) + // Minimum execution time: 9_447_000 picoseconds. + Weight::from_parts(10_078_000, 3501) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn update() -> Weight { // Proof Size summary in bytes: // Measured: `137` // Estimated: `3501` - // Minimum execution time: 12_119_000 picoseconds. - Weight::from_parts(12_548_000, 3501) + // Minimum execution time: 9_844_000 picoseconds. + Weight::from_parts(10_240_000, 3501) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn remove() -> Weight { // Proof Size summary in bytes: // Measured: `137` // Estimated: `3501` - // Minimum execution time: 12_541_000 picoseconds. - Weight::from_parts(12_956_000, 3501) + // Minimum execution time: 10_411_000 picoseconds. + Weight::from_parts(10_686_000, 3501) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3501` - // Minimum execution time: 11_700_000 picoseconds. - Weight::from_parts(12_158_000, 3501) + // Minimum execution time: 9_447_000 picoseconds. + Weight::from_parts(10_078_000, 3501) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn update() -> Weight { // Proof Size summary in bytes: // Measured: `137` // Estimated: `3501` - // Minimum execution time: 12_119_000 picoseconds. - Weight::from_parts(12_548_000, 3501) + // Minimum execution time: 9_844_000 picoseconds. + Weight::from_parts(10_240_000, 3501) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:1) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn remove() -> Weight { // Proof Size summary in bytes: // Measured: `137` // Estimated: `3501` - // Minimum execution time: 12_541_000 picoseconds. - Weight::from_parts(12_956_000, 3501) + // Minimum execution time: 10_411_000 picoseconds. + Weight::from_parts(10_686_000, 3501) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/assets/src/weights.rs b/substrate/frame/assets/src/weights.rs index f20f7e317cf..f5199105fe3 100644 --- a/substrate/frame/assets/src/weights.rs +++ b/substrate/frame/assets/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_assets +//! Autogenerated weights for `pallet_assets` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/assets/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/assets/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_assets. +/// Weight functions needed for `pallet_assets`. pub trait WeightInfo { fn create() -> Weight; fn force_create() -> Weight; @@ -86,882 +85,890 @@ pub trait WeightInfo { fn block() -> Weight; } -/// Weights for pallet_assets using the Substrate node and recommended hardware. +/// Weights for `pallet_assets` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `293` // Estimated: `3675` - // Minimum execution time: 31_340_000 picoseconds. - Weight::from_parts(31_977_000, 3675) + // Minimum execution time: 24_690_000 picoseconds. + Weight::from_parts(25_878_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `153` // Estimated: `3675` - // Minimum execution time: 13_342_000 picoseconds. - Weight::from_parts(13_782_000, 3675) + // Minimum execution time: 10_997_000 picoseconds. + Weight::from_parts(11_369_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn start_destroy() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 14_437_000 picoseconds. - Weight::from_parts(14_833_000, 3675) + // Minimum execution time: 11_536_000 picoseconds. + Weight::from_parts(12_309_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// 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:1001 w:1000) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: System Account (r:1000 w:1000) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1001 w:1000) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1000 w:1000) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn destroy_accounts(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + c * (208 ±0)` // Estimated: `3675 + c * (2609 ±0)` - // Minimum execution time: 18_728_000 picoseconds. - Weight::from_parts(18_982_000, 3675) - // Standard Error: 11_708 - .saturating_add(Weight::from_parts(14_363_570, 0).saturating_mul(c.into())) + // Minimum execution time: 15_798_000 picoseconds. + Weight::from_parts(16_005_000, 3675) + // Standard Error: 7_818 + .saturating_add(Weight::from_parts(12_826_278, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2609).saturating_mul(c.into())) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1001 w:1000) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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::Approvals` (r:1001 w:1000) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 1000]`. fn destroy_approvals(a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `522 + a * (86 ±0)` // Estimated: `3675 + a * (2623 ±0)` - // Minimum execution time: 18_611_000 picoseconds. - Weight::from_parts(18_970_000, 3675) - // Standard Error: 13_224 - .saturating_add(Weight::from_parts(16_397_299, 0).saturating_mul(a.into())) + // Minimum execution time: 16_334_000 picoseconds. + Weight::from_parts(16_616_000, 3675) + // Standard Error: 6_402 + .saturating_add(Weight::from_parts(13_502_238, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) .saturating_add(Weight::from_parts(0, 2623).saturating_mul(a.into())) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:0) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, 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::Metadata` (r:1 w:0) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) fn finish_destroy() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 14_504_000 picoseconds. - Weight::from_parts(14_906_000, 3675) + // Minimum execution time: 12_278_000 picoseconds. + Weight::from_parts(12_834_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 26_653_000 picoseconds. - Weight::from_parts(27_260_000, 3675) + // Minimum execution time: 21_793_000 picoseconds. + Weight::from_parts(22_284_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 33_625_000 picoseconds. - Weight::from_parts(34_474_000, 3675) + // Minimum execution time: 28_712_000 picoseconds. + Weight::from_parts(29_710_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 47_609_000 picoseconds. - Weight::from_parts(48_476_000, 6208) + // Minimum execution time: 41_331_000 picoseconds. + Weight::from_parts(42_362_000, 6208) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_keep_alive() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 41_625_000 picoseconds. - Weight::from_parts(43_030_000, 6208) + // Minimum execution time: 37_316_000 picoseconds. + Weight::from_parts(38_200_000, 6208) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 47_661_000 picoseconds. - Weight::from_parts(48_469_000, 6208) + // Minimum execution time: 41_347_000 picoseconds. + Weight::from_parts(42_625_000, 6208) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn freeze() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 17_727_000 picoseconds. - Weight::from_parts(18_384_000, 3675) + // Minimum execution time: 15_072_000 picoseconds. + Weight::from_parts(15_925_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn thaw() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 17_657_000 picoseconds. - Weight::from_parts(18_282_000, 3675) + // Minimum execution time: 14_991_000 picoseconds. + Weight::from_parts(15_987_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn freeze_asset() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 13_743_000 picoseconds. - Weight::from_parts(14_193_000, 3675) + // Minimum execution time: 11_296_000 picoseconds. + Weight::from_parts(12_052_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn thaw_asset() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 13_653_000 picoseconds. - Weight::from_parts(14_263_000, 3675) + // Minimum execution time: 11_446_000 picoseconds. + Weight::from_parts(11_791_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:0) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, 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::Metadata` (r:1 w:0) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 15_328_000 picoseconds. - Weight::from_parts(16_042_000, 3675) + // Minimum execution time: 13_134_000 picoseconds. + Weight::from_parts(13_401_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 14_097_000 picoseconds. - Weight::from_parts(14_641_000, 3675) + // Minimum execution time: 11_395_000 picoseconds. + Weight::from_parts(11_718_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 50]`. /// The range of component `s` is `[0, 50]`. - fn set_metadata(_n: u32, _s: u32, ) -> Weight { + fn set_metadata(n: u32, _s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 29_535_000 picoseconds. - Weight::from_parts(31_456_892, 3675) + // Minimum execution time: 25_147_000 picoseconds. + Weight::from_parts(26_614_272, 3675) + // Standard Error: 959 + .saturating_add(Weight::from_parts(2_300, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `515` // Estimated: `3675` - // Minimum execution time: 30_680_000 picoseconds. - Weight::from_parts(31_930_000, 3675) + // Minimum execution time: 26_094_000 picoseconds. + Weight::from_parts(27_199_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 50]`. /// The range of component `s` is `[0, 50]`. - fn force_set_metadata(_n: u32, s: u32, ) -> Weight { + fn force_set_metadata(n: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `190` // Estimated: `3675` - // Minimum execution time: 14_660_000 picoseconds. - Weight::from_parts(15_718_387, 3675) - // Standard Error: 622 - .saturating_add(Weight::from_parts(2_640, 0).saturating_mul(s.into())) + // Minimum execution time: 11_977_000 picoseconds. + Weight::from_parts(12_719_933, 3675) + // Standard Error: 429 + .saturating_add(Weight::from_parts(3_239, 0).saturating_mul(n.into())) + // Standard Error: 429 + .saturating_add(Weight::from_parts(3_941, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) fn force_clear_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `515` // Estimated: `3675` - // Minimum execution time: 30_853_000 picoseconds. - Weight::from_parts(31_483_000, 3675) + // Minimum execution time: 25_859_000 picoseconds. + Weight::from_parts(26_654_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn force_asset_status() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 13_632_000 picoseconds. - Weight::from_parts(14_077_000, 3675) + // Minimum execution time: 10_965_000 picoseconds. + Weight::from_parts(11_595_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1 w:1) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 33_780_000 picoseconds. - Weight::from_parts(34_533_000, 3675) + // Minimum execution time: 28_427_000 picoseconds. + Weight::from_parts(29_150_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1 w:1) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_approved() -> Weight { // Proof Size summary in bytes: // Measured: `668` // Estimated: `6208` - // Minimum execution time: 67_712_000 picoseconds. - Weight::from_parts(69_946_000, 6208) + // Minimum execution time: 60_227_000 picoseconds. + Weight::from_parts(61_839_000, 6208) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1 w:1) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `555` // Estimated: `3675` - // Minimum execution time: 36_668_000 picoseconds. - Weight::from_parts(37_637_000, 3675) + // Minimum execution time: 30_738_000 picoseconds. + Weight::from_parts(31_988_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1 w:1) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) fn force_cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `555` // Estimated: `3675` - // Minimum execution time: 36_685_000 picoseconds. - Weight::from_parts(37_950_000, 3675) + // Minimum execution time: 31_444_000 picoseconds. + Weight::from_parts(32_126_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn set_min_balance() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 14_466_000 picoseconds. - Weight::from_parts(14_924_000, 3675) + // Minimum execution time: 11_890_000 picoseconds. + Weight::from_parts(12_462_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn touch() -> Weight { // Proof Size summary in bytes: // Measured: `453` // Estimated: `3675` - // Minimum execution time: 34_874_000 picoseconds. - Weight::from_parts(36_330_000, 3675) + // Minimum execution time: 30_675_000 picoseconds. + Weight::from_parts(31_749_000, 3675) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn touch_other() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 33_278_000 picoseconds. - Weight::from_parts(34_104_000, 3675) + // Minimum execution time: 28_290_000 picoseconds. + Weight::from_parts(29_405_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn refund() -> Weight { // Proof Size summary in bytes: // Measured: `579` // Estimated: `3675` - // Minimum execution time: 32_898_000 picoseconds. - Weight::from_parts(33_489_000, 3675) + // Minimum execution time: 30_195_000 picoseconds. + Weight::from_parts(31_105_000, 3675) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn refund_other() -> Weight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `3675` - // Minimum execution time: 31_243_000 picoseconds. - Weight::from_parts(31_909_000, 3675) + // Minimum execution time: 27_785_000 picoseconds. + Weight::from_parts(28_783_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn block() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 17_692_000 picoseconds. - Weight::from_parts(18_253_000, 3675) + // Minimum execution time: 15_318_000 picoseconds. + Weight::from_parts(16_113_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `293` // Estimated: `3675` - // Minimum execution time: 31_340_000 picoseconds. - Weight::from_parts(31_977_000, 3675) + // Minimum execution time: 24_690_000 picoseconds. + Weight::from_parts(25_878_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `153` // Estimated: `3675` - // Minimum execution time: 13_342_000 picoseconds. - Weight::from_parts(13_782_000, 3675) + // Minimum execution time: 10_997_000 picoseconds. + Weight::from_parts(11_369_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn start_destroy() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 14_437_000 picoseconds. - Weight::from_parts(14_833_000, 3675) + // Minimum execution time: 11_536_000 picoseconds. + Weight::from_parts(12_309_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// 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:1001 w:1000) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: System Account (r:1000 w:1000) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1001 w:1000) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1000 w:1000) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn destroy_accounts(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + c * (208 ±0)` // Estimated: `3675 + c * (2609 ±0)` - // Minimum execution time: 18_728_000 picoseconds. - Weight::from_parts(18_982_000, 3675) - // Standard Error: 11_708 - .saturating_add(Weight::from_parts(14_363_570, 0).saturating_mul(c.into())) + // Minimum execution time: 15_798_000 picoseconds. + Weight::from_parts(16_005_000, 3675) + // Standard Error: 7_818 + .saturating_add(Weight::from_parts(12_826_278, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(c.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2609).saturating_mul(c.into())) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1001 w:1000) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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::Approvals` (r:1001 w:1000) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 1000]`. fn destroy_approvals(a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `522 + a * (86 ±0)` // Estimated: `3675 + a * (2623 ±0)` - // Minimum execution time: 18_611_000 picoseconds. - Weight::from_parts(18_970_000, 3675) - // Standard Error: 13_224 - .saturating_add(Weight::from_parts(16_397_299, 0).saturating_mul(a.into())) + // Minimum execution time: 16_334_000 picoseconds. + Weight::from_parts(16_616_000, 3675) + // Standard Error: 6_402 + .saturating_add(Weight::from_parts(13_502_238, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) .saturating_add(Weight::from_parts(0, 2623).saturating_mul(a.into())) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:0) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, 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::Metadata` (r:1 w:0) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) fn finish_destroy() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 14_504_000 picoseconds. - Weight::from_parts(14_906_000, 3675) + // Minimum execution time: 12_278_000 picoseconds. + Weight::from_parts(12_834_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 26_653_000 picoseconds. - Weight::from_parts(27_260_000, 3675) + // Minimum execution time: 21_793_000 picoseconds. + Weight::from_parts(22_284_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 33_625_000 picoseconds. - Weight::from_parts(34_474_000, 3675) + // Minimum execution time: 28_712_000 picoseconds. + Weight::from_parts(29_710_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 47_609_000 picoseconds. - Weight::from_parts(48_476_000, 6208) + // Minimum execution time: 41_331_000 picoseconds. + Weight::from_parts(42_362_000, 6208) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_keep_alive() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 41_625_000 picoseconds. - Weight::from_parts(43_030_000, 6208) + // Minimum execution time: 37_316_000 picoseconds. + Weight::from_parts(38_200_000, 6208) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 47_661_000 picoseconds. - Weight::from_parts(48_469_000, 6208) + // Minimum execution time: 41_347_000 picoseconds. + Weight::from_parts(42_625_000, 6208) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn freeze() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 17_727_000 picoseconds. - Weight::from_parts(18_384_000, 3675) + // Minimum execution time: 15_072_000 picoseconds. + Weight::from_parts(15_925_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn thaw() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 17_657_000 picoseconds. - Weight::from_parts(18_282_000, 3675) + // Minimum execution time: 14_991_000 picoseconds. + Weight::from_parts(15_987_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn freeze_asset() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 13_743_000 picoseconds. - Weight::from_parts(14_193_000, 3675) + // Minimum execution time: 11_296_000 picoseconds. + Weight::from_parts(12_052_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn thaw_asset() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 13_653_000 picoseconds. - Weight::from_parts(14_263_000, 3675) + // Minimum execution time: 11_446_000 picoseconds. + Weight::from_parts(11_791_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:0) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, 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::Metadata` (r:1 w:0) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 15_328_000 picoseconds. - Weight::from_parts(16_042_000, 3675) + // Minimum execution time: 13_134_000 picoseconds. + Weight::from_parts(13_401_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 14_097_000 picoseconds. - Weight::from_parts(14_641_000, 3675) + // Minimum execution time: 11_395_000 picoseconds. + Weight::from_parts(11_718_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 50]`. /// The range of component `s` is `[0, 50]`. - fn set_metadata(_n: u32, _s: u32, ) -> Weight { + fn set_metadata(n: u32, _s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 29_535_000 picoseconds. - Weight::from_parts(31_456_892, 3675) + // Minimum execution time: 25_147_000 picoseconds. + Weight::from_parts(26_614_272, 3675) + // Standard Error: 959 + .saturating_add(Weight::from_parts(2_300, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `515` // Estimated: `3675` - // Minimum execution time: 30_680_000 picoseconds. - Weight::from_parts(31_930_000, 3675) + // Minimum execution time: 26_094_000 picoseconds. + Weight::from_parts(27_199_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 50]`. /// The range of component `s` is `[0, 50]`. - fn force_set_metadata(_n: u32, s: u32, ) -> Weight { + fn force_set_metadata(n: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `190` // Estimated: `3675` - // Minimum execution time: 14_660_000 picoseconds. - Weight::from_parts(15_718_387, 3675) - // Standard Error: 622 - .saturating_add(Weight::from_parts(2_640, 0).saturating_mul(s.into())) + // Minimum execution time: 11_977_000 picoseconds. + Weight::from_parts(12_719_933, 3675) + // Standard Error: 429 + .saturating_add(Weight::from_parts(3_239, 0).saturating_mul(n.into())) + // Standard Error: 429 + .saturating_add(Weight::from_parts(3_941, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) fn force_clear_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `515` // Estimated: `3675` - // Minimum execution time: 30_853_000 picoseconds. - Weight::from_parts(31_483_000, 3675) + // Minimum execution time: 25_859_000 picoseconds. + Weight::from_parts(26_654_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn force_asset_status() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 13_632_000 picoseconds. - Weight::from_parts(14_077_000, 3675) + // Minimum execution time: 10_965_000 picoseconds. + Weight::from_parts(11_595_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1 w:1) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 33_780_000 picoseconds. - Weight::from_parts(34_533_000, 3675) + // Minimum execution time: 28_427_000 picoseconds. + Weight::from_parts(29_150_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1 w:1) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer_approved() -> Weight { // Proof Size summary in bytes: // Measured: `668` // Estimated: `6208` - // Minimum execution time: 67_712_000 picoseconds. - Weight::from_parts(69_946_000, 6208) + // Minimum execution time: 60_227_000 picoseconds. + Weight::from_parts(61_839_000, 6208) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1 w:1) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `555` // Estimated: `3675` - // Minimum execution time: 36_668_000 picoseconds. - Weight::from_parts(37_637_000, 3675) + // Minimum execution time: 30_738_000 picoseconds. + Weight::from_parts(31_988_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Approvals (r:1 w:1) - /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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::Approvals` (r:1 w:1) + /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, mode: `MaxEncodedLen`) fn force_cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `555` // Estimated: `3675` - // Minimum execution time: 36_685_000 picoseconds. - Weight::from_parts(37_950_000, 3675) + // Minimum execution time: 31_444_000 picoseconds. + Weight::from_parts(32_126_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn set_min_balance() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 14_466_000 picoseconds. - Weight::from_parts(14_924_000, 3675) + // Minimum execution time: 11_890_000 picoseconds. + Weight::from_parts(12_462_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn touch() -> Weight { // Proof Size summary in bytes: // Measured: `453` // Estimated: `3675` - // Minimum execution time: 34_874_000 picoseconds. - Weight::from_parts(36_330_000, 3675) + // Minimum execution time: 30_675_000 picoseconds. + Weight::from_parts(31_749_000, 3675) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn touch_other() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 33_278_000 picoseconds. - Weight::from_parts(34_104_000, 3675) + // Minimum execution time: 28_290_000 picoseconds. + Weight::from_parts(29_405_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn refund() -> Weight { // Proof Size summary in bytes: // Measured: `579` // Estimated: `3675` - // Minimum execution time: 32_898_000 picoseconds. - Weight::from_parts(33_489_000, 3675) + // Minimum execution time: 30_195_000 picoseconds. + Weight::from_parts(31_105_000, 3675) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) fn refund_other() -> Weight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `3675` - // Minimum execution time: 31_243_000 picoseconds. - Weight::from_parts(31_909_000, 3675) + // Minimum execution time: 27_785_000 picoseconds. + Weight::from_parts(28_783_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Assets Asset (r:1 w:0) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn block() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 17_692_000 picoseconds. - Weight::from_parts(18_253_000, 3675) + // Minimum execution time: 15_318_000 picoseconds. + Weight::from_parts(16_113_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/babe/src/mock.rs b/substrate/frame/babe/src/mock.rs index b693f4fce9b..1ba0cdd0cc1 100644 --- a/substrate/frame/babe/src/mock.rs +++ b/substrate/frame/babe/src/mock.rs @@ -37,8 +37,9 @@ use sp_core::{ use sp_io; use sp_runtime::{ curve::PiecewiseLinear, + generic::UncheckedExtrinsic, impl_opaque_keys, - testing::{Digest, DigestItem, Header, TestXt}, + testing::{Digest, DigestItem, Header}, traits::{Header as _, OpaqueKeys}, BuildStorage, Perbill, }; @@ -74,7 +75,7 @@ where RuntimeCall: From, { type OverarchingCall = RuntimeCall; - type Extrinsic = TestXt; + type Extrinsic = UncheckedExtrinsic; } impl_opaque_keys! { diff --git a/substrate/frame/bags-list/src/weights.rs b/substrate/frame/bags-list/src/weights.rs index d929c6bb959..804b702cc9a 100644 --- a/substrate/frame/bags-list/src/weights.rs +++ b/substrate/frame/bags-list/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_bags_list +//! Autogenerated weights for `pallet_bags_list` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/bags-list/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/bags-list/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,123 +49,123 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_bags_list. +/// Weight functions needed for `pallet_bags_list`. pub trait WeightInfo { fn rebag_non_terminal() -> Weight; fn rebag_terminal() -> Weight; fn put_in_front_of() -> Weight; } -/// Weights for pallet_bags_list using the Substrate node and recommended hardware. +/// Weights for `pallet_bags_list` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:4 w:4) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:4 w:4) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn rebag_non_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1724` + // Measured: `1719` // Estimated: `11506` - // Minimum execution time: 62_137_000 picoseconds. - Weight::from_parts(64_050_000, 11506) + // Minimum execution time: 55_856_000 picoseconds. + Weight::from_parts(59_022_000, 11506) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn rebag_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1618` + // Measured: `1613` // Estimated: `8877` - // Minimum execution time: 60_880_000 picoseconds. - Weight::from_parts(62_078_000, 8877) + // Minimum execution time: 55_418_000 picoseconds. + Weight::from_parts(57_352_000, 8877) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: VoterList ListNodes (r:4 w:4) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:2 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:2 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `VoterList::ListNodes` (r:4 w:4) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:2 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:2 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn put_in_front_of() -> Weight { // Proof Size summary in bytes: - // Measured: `1930` + // Measured: `1925` // Estimated: `11506` - // Minimum execution time: 68_911_000 picoseconds. - Weight::from_parts(70_592_000, 11506) + // Minimum execution time: 63_820_000 picoseconds. + Weight::from_parts(65_530_000, 11506) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:4 w:4) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:4 w:4) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn rebag_non_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1724` + // Measured: `1719` // Estimated: `11506` - // Minimum execution time: 62_137_000 picoseconds. - Weight::from_parts(64_050_000, 11506) + // Minimum execution time: 55_856_000 picoseconds. + Weight::from_parts(59_022_000, 11506) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:3 w:3) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:2 w:2) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:3 w:3) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:2 w:2) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn rebag_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1618` + // Measured: `1613` // Estimated: `8877` - // Minimum execution time: 60_880_000 picoseconds. - Weight::from_parts(62_078_000, 8877) + // Minimum execution time: 55_418_000 picoseconds. + Weight::from_parts(57_352_000, 8877) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: VoterList ListNodes (r:4 w:4) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:2 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:2 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: `VoterList::ListNodes` (r:4 w:4) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:2 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:2 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn put_in_front_of() -> Weight { // Proof Size summary in bytes: - // Measured: `1930` + // Measured: `1925` // Estimated: `11506` - // Minimum execution time: 68_911_000 picoseconds. - Weight::from_parts(70_592_000, 11506) + // Minimum execution time: 63_820_000 picoseconds. + Weight::from_parts(65_530_000, 11506) .saturating_add(RocksDbWeight::get().reads(10_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } diff --git a/substrate/frame/balances/Cargo.toml b/substrate/frame/balances/Cargo.toml index 64ae90c6757..db114290ed8 100644 --- a/substrate/frame/balances/Cargo.toml +++ b/substrate/frame/balances/Cargo.toml @@ -53,6 +53,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ diff --git a/substrate/frame/balances/src/tests/currency_tests.rs b/substrate/frame/balances/src/tests/currency_tests.rs index 46a4c4caefc..10bb79901f8 100644 --- a/substrate/frame/balances/src/tests/currency_tests.rs +++ b/substrate/frame/balances/src/tests/currency_tests.rs @@ -30,6 +30,7 @@ use frame_support::{ StorageNoopGuard, }; use frame_system::Event as SysEvent; +use sp_runtime::traits::DispatchTransaction; const ID_1: LockIdentifier = *b"1 "; const ID_2: LockIdentifier = *b"2 "; @@ -240,17 +241,17 @@ fn lock_should_work_reserve() { TokenError::Frozen ); assert_noop!(Balances::reserve(&1, 1), Error::::LiquidityRestrictions,); - assert!( as SignedExtension>::pre_dispatch( + assert!(ChargeTransactionPayment::::validate_and_prepare( ChargeTransactionPayment::from(1), - &1, + Some(1).into(), CALL, &info_from_weight(Weight::from_parts(1, 0)), 1, ) .is_err()); - assert!( as SignedExtension>::pre_dispatch( + assert!(ChargeTransactionPayment::::validate_and_prepare( ChargeTransactionPayment::from(0), - &1, + Some(1).into(), CALL, &info_from_weight(Weight::from_parts(1, 0)), 1, @@ -271,17 +272,17 @@ fn lock_should_work_tx_fee() { TokenError::Frozen ); assert_noop!(Balances::reserve(&1, 1), Error::::LiquidityRestrictions,); - assert!( as SignedExtension>::pre_dispatch( + assert!(ChargeTransactionPayment::::validate_and_prepare( ChargeTransactionPayment::from(1), - &1, + Some(1).into(), CALL, &info_from_weight(Weight::from_parts(1, 0)), 1, ) .is_err()); - assert!( as SignedExtension>::pre_dispatch( + assert!(ChargeTransactionPayment::::validate_and_prepare( ChargeTransactionPayment::from(0), - &1, + Some(1).into(), CALL, &info_from_weight(Weight::from_parts(1, 0)), 1, diff --git a/substrate/frame/balances/src/tests/mod.rs b/substrate/frame/balances/src/tests/mod.rs index 599909fa943..ee076a10fd1 100644 --- a/substrate/frame/balances/src/tests/mod.rs +++ b/substrate/frame/balances/src/tests/mod.rs @@ -37,7 +37,7 @@ use scale_info::TypeInfo; use sp_core::hexdisplay::HexDisplay; use sp_io; use sp_runtime::{ - traits::{BadOrigin, SignedExtension, Zero}, + traits::{BadOrigin, Zero}, ArithmeticError, BuildStorage, DispatchError, DispatchResult, FixedPointNumber, RuntimeDebug, TokenError, }; @@ -96,13 +96,13 @@ impl frame_system::Config for Test { type AccountData = super::AccountData; } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for Test { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter, ()>; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; - type FeeMultiplierUpdate = (); } pub(crate) type Balance = u64; diff --git a/substrate/frame/balances/src/weights.rs b/substrate/frame/balances/src/weights.rs index f875ea189ba..6bcfe050af7 100644 --- a/substrate/frame/balances/src/weights.rs +++ b/substrate/frame/balances/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_balances +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_balances -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/balances/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -69,8 +71,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 46_329_000 picoseconds. - Weight::from_parts(47_297_000, 3593) + // Minimum execution time: 46_407_000 picoseconds. + Weight::from_parts(47_561_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -80,8 +82,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 36_187_000 picoseconds. - Weight::from_parts(36_900_000, 3593) + // Minimum execution time: 36_574_000 picoseconds. + Weight::from_parts(37_682_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -91,8 +93,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 13_498_000 picoseconds. - Weight::from_parts(14_143_000, 3593) + // Minimum execution time: 13_990_000 picoseconds. + Weight::from_parts(14_568_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -102,8 +104,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 18_756_000 picoseconds. - Weight::from_parts(19_553_000, 3593) + // Minimum execution time: 19_594_000 picoseconds. + Weight::from_parts(20_148_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -113,8 +115,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 47_826_000 picoseconds. - Weight::from_parts(48_834_000, 6196) + // Minimum execution time: 47_945_000 picoseconds. + Weight::from_parts(49_363_000, 6196) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -124,8 +126,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 44_621_000 picoseconds. - Weight::from_parts(45_151_000, 3593) + // Minimum execution time: 45_205_000 picoseconds. + Weight::from_parts(45_952_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -135,8 +137,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_194_000 picoseconds. - Weight::from_parts(16_945_000, 3593) + // Minimum execution time: 16_593_000 picoseconds. + Weight::from_parts(17_123_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -147,10 +149,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 15_782_000 picoseconds. - Weight::from_parts(16_118_000, 990) - // Standard Error: 10_499 - .saturating_add(Weight::from_parts(13_327_660, 0).saturating_mul(u.into())) + // Minimum execution time: 16_182_000 picoseconds. + Weight::from_parts(16_412_000, 990) + // Standard Error: 10_148 + .saturating_add(Weight::from_parts(13_382_459, 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())) @@ -159,8 +161,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_157_000 picoseconds. - Weight::from_parts(6_507_000, 0) + // Minimum execution time: 6_478_000 picoseconds. + Weight::from_parts(6_830_000, 0) } } @@ -172,8 +174,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 46_329_000 picoseconds. - Weight::from_parts(47_297_000, 3593) + // Minimum execution time: 46_407_000 picoseconds. + Weight::from_parts(47_561_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -183,8 +185,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 36_187_000 picoseconds. - Weight::from_parts(36_900_000, 3593) + // Minimum execution time: 36_574_000 picoseconds. + Weight::from_parts(37_682_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -194,8 +196,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 13_498_000 picoseconds. - Weight::from_parts(14_143_000, 3593) + // Minimum execution time: 13_990_000 picoseconds. + Weight::from_parts(14_568_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -205,8 +207,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 18_756_000 picoseconds. - Weight::from_parts(19_553_000, 3593) + // Minimum execution time: 19_594_000 picoseconds. + Weight::from_parts(20_148_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -216,8 +218,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 47_826_000 picoseconds. - Weight::from_parts(48_834_000, 6196) + // Minimum execution time: 47_945_000 picoseconds. + Weight::from_parts(49_363_000, 6196) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -227,8 +229,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 44_621_000 picoseconds. - Weight::from_parts(45_151_000, 3593) + // Minimum execution time: 45_205_000 picoseconds. + Weight::from_parts(45_952_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -238,8 +240,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_194_000 picoseconds. - Weight::from_parts(16_945_000, 3593) + // Minimum execution time: 16_593_000 picoseconds. + Weight::from_parts(17_123_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -250,10 +252,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 15_782_000 picoseconds. - Weight::from_parts(16_118_000, 990) - // Standard Error: 10_499 - .saturating_add(Weight::from_parts(13_327_660, 0).saturating_mul(u.into())) + // Minimum execution time: 16_182_000 picoseconds. + Weight::from_parts(16_412_000, 990) + // Standard Error: 10_148 + .saturating_add(Weight::from_parts(13_382_459, 0).saturating_mul(u.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -262,7 +264,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_157_000 picoseconds. - Weight::from_parts(6_507_000, 0) + // Minimum execution time: 6_478_000 picoseconds. + Weight::from_parts(6_830_000, 0) } } diff --git a/substrate/frame/beefy/src/mock.rs b/substrate/frame/beefy/src/mock.rs index 9cce479890a..5d963d309a4 100644 --- a/substrate/frame/beefy/src/mock.rs +++ b/substrate/frame/beefy/src/mock.rs @@ -29,8 +29,8 @@ use pallet_session::historical as pallet_session_historical; use sp_core::{crypto::KeyTypeId, ConstU128}; use sp_io::TestExternalities; use sp_runtime::{ - app_crypto::ecdsa::Public, curve::PiecewiseLinear, impl_opaque_keys, testing::TestXt, - traits::OpaqueKeys, BuildStorage, Perbill, + app_crypto::ecdsa::Public, curve::PiecewiseLinear, generic::UncheckedExtrinsic, + impl_opaque_keys, traits::OpaqueKeys, BuildStorage, Perbill, }; use sp_staking::{EraIndex, SessionIndex}; use sp_state_machine::BasicExternalities; @@ -73,7 +73,7 @@ where RuntimeCall: From, { type OverarchingCall = RuntimeCall; - type Extrinsic = TestXt; + type Extrinsic = UncheckedExtrinsic; } parameter_types! { diff --git a/substrate/frame/benchmarking/src/weights.rs b/substrate/frame/benchmarking/src/weights.rs index 13d73e420cc..76f9a3fe52b 100644 --- a/substrate/frame/benchmarking/src/weights.rs +++ b/substrate/frame/benchmarking/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for frame_benchmarking +//! Autogenerated weights for `frame_benchmarking` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/benchmarking/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/benchmarking/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for frame_benchmarking. +/// Weight functions needed for `frame_benchmarking`. pub trait WeightInfo { fn addition(i: u32, ) -> Weight; fn subtraction(i: u32, ) -> Weight; @@ -60,7 +59,7 @@ pub trait WeightInfo { fn sr25519_verification(i: u32, ) -> Weight; } -/// Weights for frame_benchmarking using the Substrate node and recommended hardware. +/// Weights for `frame_benchmarking` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 1000000]`. @@ -68,101 +67,101 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 147_000 picoseconds. - Weight::from_parts(185_656, 0) + // Minimum execution time: 150_000 picoseconds. + Weight::from_parts(190_440, 0) } /// The range of component `i` is `[0, 1000000]`. fn subtraction(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 146_000 picoseconds. - Weight::from_parts(189_816, 0) + // Minimum execution time: 151_000 picoseconds. + Weight::from_parts(201_397, 0) } /// The range of component `i` is `[0, 1000000]`. fn multiplication(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 148_000 picoseconds. - Weight::from_parts(202_367, 0) + // Minimum execution time: 152_000 picoseconds. + Weight::from_parts(187_862, 0) } /// The range of component `i` is `[0, 1000000]`. fn division(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 143_000 picoseconds. - Weight::from_parts(189_693, 0) + // Minimum execution time: 146_000 picoseconds. + Weight::from_parts(215_191, 0) } fn hashing() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 24_167_071_000 picoseconds. - Weight::from_parts(24_391_749_000, 0) + // Minimum execution time: 25_432_823_000 picoseconds. + Weight::from_parts(25_568_846_000, 0) } /// The range of component `i` is `[0, 100]`. fn sr25519_verification(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 231_000 picoseconds. - Weight::from_parts(2_998_013, 0) - // Standard Error: 6_256 - .saturating_add(Weight::from_parts(55_456_705, 0).saturating_mul(i.into())) + // Minimum execution time: 193_000 picoseconds. + Weight::from_parts(3_846_690, 0) + // Standard Error: 6_694 + .saturating_add(Weight::from_parts(40_647_582, 0).saturating_mul(i.into())) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { /// The range of component `i` is `[0, 1000000]`. fn addition(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 147_000 picoseconds. - Weight::from_parts(185_656, 0) + // Minimum execution time: 150_000 picoseconds. + Weight::from_parts(190_440, 0) } /// The range of component `i` is `[0, 1000000]`. fn subtraction(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 146_000 picoseconds. - Weight::from_parts(189_816, 0) + // Minimum execution time: 151_000 picoseconds. + Weight::from_parts(201_397, 0) } /// The range of component `i` is `[0, 1000000]`. fn multiplication(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 148_000 picoseconds. - Weight::from_parts(202_367, 0) + // Minimum execution time: 152_000 picoseconds. + Weight::from_parts(187_862, 0) } /// The range of component `i` is `[0, 1000000]`. fn division(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 143_000 picoseconds. - Weight::from_parts(189_693, 0) + // Minimum execution time: 146_000 picoseconds. + Weight::from_parts(215_191, 0) } fn hashing() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 24_167_071_000 picoseconds. - Weight::from_parts(24_391_749_000, 0) + // Minimum execution time: 25_432_823_000 picoseconds. + Weight::from_parts(25_568_846_000, 0) } /// The range of component `i` is `[0, 100]`. fn sr25519_verification(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 231_000 picoseconds. - Weight::from_parts(2_998_013, 0) - // Standard Error: 6_256 - .saturating_add(Weight::from_parts(55_456_705, 0).saturating_mul(i.into())) + // Minimum execution time: 193_000 picoseconds. + Weight::from_parts(3_846_690, 0) + // Standard Error: 6_694 + .saturating_add(Weight::from_parts(40_647_582, 0).saturating_mul(i.into())) } } diff --git a/substrate/frame/bounties/src/weights.rs b/substrate/frame/bounties/src/weights.rs index a172d15b56c..1f0e38b6702 100644 --- a/substrate/frame/bounties/src/weights.rs +++ b/substrate/frame/bounties/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_bounties +//! Autogenerated weights for `pallet_bounties` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/bounties/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/bounties/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_bounties. +/// Weight functions needed for `pallet_bounties`. pub trait WeightInfo { fn propose_bounty(d: u32, ) -> Weight; fn approve_bounty() -> Weight; @@ -65,169 +64,169 @@ pub trait WeightInfo { fn spend_funds(b: u32, ) -> Weight; } -/// Weights for pallet_bounties using the Substrate node and recommended hardware. +/// Weights for `pallet_bounties` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Bounties BountyCount (r:1 w:1) - /// Proof: Bounties BountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:0 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: `Bounties::BountyCount` (r:1 w:1) + /// Proof: `Bounties::BountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:0 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) /// The range of component `d` is `[0, 300]`. fn propose_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `309` // Estimated: `3593` - // Minimum execution time: 29_384_000 picoseconds. - Weight::from_parts(30_820_018, 3593) - // Standard Error: 298 - .saturating_add(Weight::from_parts(2_920, 0).saturating_mul(d.into())) + // Minimum execution time: 24_286_000 picoseconds. + Weight::from_parts(25_657_314, 3593) + // Standard Error: 215 + .saturating_add(Weight::from_parts(1_116, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: Bounties BountyApprovals (r:1 w:1) - /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn approve_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `368` + // Measured: `401` // Estimated: `3642` - // Minimum execution time: 10_873_000 picoseconds. - Weight::from_parts(11_421_000, 3642) + // Minimum execution time: 12_526_000 picoseconds. + Weight::from_parts(13_373_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `388` + // Measured: `421` // Estimated: `3642` - // Minimum execution time: 9_181_000 picoseconds. - Weight::from_parts(9_726_000, 3642) + // Minimum execution time: 11_807_000 picoseconds. + Weight::from_parts(12_340_000, 3642) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `564` + // Measured: `597` // Estimated: `3642` - // Minimum execution time: 30_257_000 picoseconds. - Weight::from_parts(30_751_000, 3642) + // Minimum execution time: 27_183_000 picoseconds. + Weight::from_parts(28_250_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `560` + // Measured: `593` // Estimated: `3642` - // Minimum execution time: 27_850_000 picoseconds. - Weight::from_parts(28_821_000, 3642) + // Minimum execution time: 26_775_000 picoseconds. + Weight::from_parts(27_667_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:0) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn award_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `572` + // Measured: `605` // Estimated: `3642` - // Minimum execution time: 19_164_000 picoseconds. - Weight::from_parts(20_136_000, 3642) + // Minimum execution time: 16_089_000 picoseconds. + Weight::from_parts(16_909_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn claim_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `936` + // Measured: `969` // Estimated: `8799` - // Minimum execution time: 120_235_000 picoseconds. - Weight::from_parts(121_673_000, 8799) + // Minimum execution time: 104_973_000 picoseconds. + Weight::from_parts(107_696_000, 8799) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:0) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_bounty_proposed() -> Weight { // Proof Size summary in bytes: - // Measured: `616` + // Measured: `649` // Estimated: `3642` - // Minimum execution time: 35_713_000 picoseconds. - Weight::from_parts(37_174_000, 3642) + // Minimum execution time: 30_702_000 picoseconds. + Weight::from_parts(32_615_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:0) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `852` + // Measured: `885` // Estimated: `6196` - // Minimum execution time: 81_037_000 picoseconds. - Weight::from_parts(83_294_000, 6196) + // Minimum execution time: 72_055_000 picoseconds. + Weight::from_parts(73_900_000, 6196) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn extend_bounty_expiry() -> Weight { // Proof Size summary in bytes: - // Measured: `424` + // Measured: `457` // Estimated: `3642` - // Minimum execution time: 15_348_000 picoseconds. - Weight::from_parts(15_776_000, 3642) + // Minimum execution time: 12_057_000 picoseconds. + Weight::from_parts(12_744_000, 3642) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Bounties BountyApprovals (r:1 w:1) - /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:100 w:100) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:200 w:200) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:100 w:100) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:200 w:200) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `b` is `[0, 100]`. fn spend_funds(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `4 + b * (297 ±0)` + // Measured: `37 + b * (297 ±0)` // Estimated: `1887 + b * (5206 ±0)` - // Minimum execution time: 5_082_000 picoseconds. - Weight::from_parts(5_126_000, 1887) - // Standard Error: 21_949 - .saturating_add(Weight::from_parts(42_635_308, 0).saturating_mul(b.into())) + // Minimum execution time: 3_489_000 picoseconds. + Weight::from_parts(8_384_129, 1887) + // Standard Error: 18_066 + .saturating_add(Weight::from_parts(31_612_331, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -236,168 +235,168 @@ impl WeightInfo for SubstrateWeight { } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Bounties BountyCount (r:1 w:1) - /// Proof: Bounties BountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:0 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: `Bounties::BountyCount` (r:1 w:1) + /// Proof: `Bounties::BountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:0 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) /// The range of component `d` is `[0, 300]`. fn propose_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `309` // Estimated: `3593` - // Minimum execution time: 29_384_000 picoseconds. - Weight::from_parts(30_820_018, 3593) - // Standard Error: 298 - .saturating_add(Weight::from_parts(2_920, 0).saturating_mul(d.into())) + // Minimum execution time: 24_286_000 picoseconds. + Weight::from_parts(25_657_314, 3593) + // Standard Error: 215 + .saturating_add(Weight::from_parts(1_116, 0).saturating_mul(d.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: Bounties BountyApprovals (r:1 w:1) - /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn approve_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `368` + // Measured: `401` // Estimated: `3642` - // Minimum execution time: 10_873_000 picoseconds. - Weight::from_parts(11_421_000, 3642) + // Minimum execution time: 12_526_000 picoseconds. + Weight::from_parts(13_373_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `388` + // Measured: `421` // Estimated: `3642` - // Minimum execution time: 9_181_000 picoseconds. - Weight::from_parts(9_726_000, 3642) + // Minimum execution time: 11_807_000 picoseconds. + Weight::from_parts(12_340_000, 3642) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `564` + // Measured: `597` // Estimated: `3642` - // Minimum execution time: 30_257_000 picoseconds. - Weight::from_parts(30_751_000, 3642) + // Minimum execution time: 27_183_000 picoseconds. + Weight::from_parts(28_250_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `560` + // Measured: `593` // Estimated: `3642` - // Minimum execution time: 27_850_000 picoseconds. - Weight::from_parts(28_821_000, 3642) + // Minimum execution time: 26_775_000 picoseconds. + Weight::from_parts(27_667_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:0) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn award_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `572` + // Measured: `605` // Estimated: `3642` - // Minimum execution time: 19_164_000 picoseconds. - Weight::from_parts(20_136_000, 3642) + // Minimum execution time: 16_089_000 picoseconds. + Weight::from_parts(16_909_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn claim_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `936` + // Measured: `969` // Estimated: `8799` - // Minimum execution time: 120_235_000 picoseconds. - Weight::from_parts(121_673_000, 8799) + // Minimum execution time: 104_973_000 picoseconds. + Weight::from_parts(107_696_000, 8799) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:0) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_bounty_proposed() -> Weight { // Proof Size summary in bytes: - // Measured: `616` + // Measured: `649` // Estimated: `3642` - // Minimum execution time: 35_713_000 picoseconds. - Weight::from_parts(37_174_000, 3642) + // Minimum execution time: 30_702_000 picoseconds. + Weight::from_parts(32_615_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:0) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyDescriptions (r:0 w:1) - /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `852` + // Measured: `885` // Estimated: `6196` - // Minimum execution time: 81_037_000 picoseconds. - Weight::from_parts(83_294_000, 6196) + // Minimum execution time: 72_055_000 picoseconds. + Weight::from_parts(73_900_000, 6196) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Bounties Bounties (r:1 w:1) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn extend_bounty_expiry() -> Weight { // Proof Size summary in bytes: - // Measured: `424` + // Measured: `457` // Estimated: `3642` - // Minimum execution time: 15_348_000 picoseconds. - Weight::from_parts(15_776_000, 3642) + // Minimum execution time: 12_057_000 picoseconds. + Weight::from_parts(12_744_000, 3642) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Bounties BountyApprovals (r:1 w:1) - /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:100 w:100) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:200 w:200) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:100 w:100) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:200 w:200) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `b` is `[0, 100]`. fn spend_funds(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `4 + b * (297 ±0)` + // Measured: `37 + b * (297 ±0)` // Estimated: `1887 + b * (5206 ±0)` - // Minimum execution time: 5_082_000 picoseconds. - Weight::from_parts(5_126_000, 1887) - // Standard Error: 21_949 - .saturating_add(Weight::from_parts(42_635_308, 0).saturating_mul(b.into())) + // Minimum execution time: 3_489_000 picoseconds. + Weight::from_parts(8_384_129, 1887) + // Standard Error: 18_066 + .saturating_add(Weight::from_parts(31_612_331, 0).saturating_mul(b.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(b.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) diff --git a/substrate/frame/broker/src/weights.rs b/substrate/frame/broker/src/weights.rs index a8f50eeee6e..133ea63e35f 100644 --- a/substrate/frame/broker/src/weights.rs +++ b/substrate/frame/broker/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_broker` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-09-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-pzhd7p6z-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_broker +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_broker -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/broker/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -87,8 +89,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_040_000 picoseconds. - Weight::from_parts(3_344_000, 0) + // Minimum execution time: 2_701_000 picoseconds. + Weight::from_parts(2_902_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -97,8 +99,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 21_259_000 picoseconds. - Weight::from_parts(22_110_000, 7496) + // Minimum execution time: 18_056_000 picoseconds. + Weight::from_parts(19_093_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -108,8 +110,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 20_330_000 picoseconds. - Weight::from_parts(20_826_000, 7496) + // Minimum execution time: 17_233_000 picoseconds. + Weight::from_parts(17_788_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -119,8 +121,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 13_411_000 picoseconds. - Weight::from_parts(13_960_000, 1526) + // Minimum execution time: 9_740_000 picoseconds. + Weight::from_parts(10_504_000, 1526) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -139,14 +141,12 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(n: u32, ) -> Weight { + fn start_sales(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 57_770_000 picoseconds. - Weight::from_parts(61_047_512, 8499) - // Standard Error: 165 - .saturating_add(Weight::from_parts(3, 0).saturating_mul(n.into())) + // Minimum execution time: 49_728_000 picoseconds. + Weight::from_parts(52_765_861, 8499) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(16_u64)) } @@ -162,10 +162,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn purchase() -> Weight { // Proof Size summary in bytes: - // Measured: `568` - // Estimated: `2053` - // Minimum execution time: 51_196_000 picoseconds. - Weight::from_parts(52_382_000, 2053) + // Measured: `635` + // Estimated: `2120` + // Minimum execution time: 41_986_000 picoseconds. + Weight::from_parts(43_465_000, 2120) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -185,10 +185,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `686` + // Measured: `753` // Estimated: `4698` - // Minimum execution time: 71_636_000 picoseconds. - Weight::from_parts(73_679_000, 4698) + // Minimum execution time: 61_779_000 picoseconds. + Weight::from_parts(62_563_000, 4698) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -198,8 +198,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 19_182_000 picoseconds. - Weight::from_parts(19_775_000, 3550) + // Minimum execution time: 16_962_000 picoseconds. + Weight::from_parts(17_733_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -209,21 +209,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 20_688_000 picoseconds. - Weight::from_parts(21_557_000, 3550) + // Minimum execution time: 18_380_000 picoseconds. + Weight::from_parts(19_105_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Broker::Regions` (r:1 w:2) + /// Storage: `Broker::Regions` (r:1 w:3) /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn interlace() -> Weight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 21_190_000 picoseconds. - Weight::from_parts(22_215_000, 3550) + // Minimum execution time: 20_115_000 picoseconds. + Weight::from_parts(20_741_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) @@ -237,8 +237,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `740` // Estimated: `4681` - // Minimum execution time: 34_591_000 picoseconds. - Weight::from_parts(36_227_000, 4681) + // Minimum execution time: 31_339_000 picoseconds. + Weight::from_parts(32_639_000, 4681) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -256,8 +256,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `775` // Estimated: `5996` - // Minimum execution time: 40_346_000 picoseconds. - Weight::from_parts(41_951_000, 5996) + // Minimum execution time: 37_542_000 picoseconds. + Weight::from_parts(38_521_000, 5996) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -272,10 +272,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 75_734_000 picoseconds. - Weight::from_parts(78_168_395, 6196) - // Standard Error: 63_180 - .saturating_add(Weight::from_parts(1_076_259, 0).saturating_mul(m.into())) + // Minimum execution time: 66_176_000 picoseconds. + Weight::from_parts(68_356_745, 6196) + // Standard Error: 68_008 + .saturating_add(Weight::from_parts(1_558_419, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) @@ -287,8 +287,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 46_383_000 picoseconds. - Weight::from_parts(47_405_000, 3593) + // Minimum execution time: 41_130_000 picoseconds. + Weight::from_parts(41_914_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -300,8 +300,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `603` // Estimated: `3550` - // Minimum execution time: 30_994_000 picoseconds. - Weight::from_parts(31_979_000, 3550) + // Minimum execution time: 31_042_000 picoseconds. + Weight::from_parts(34_087_000, 3550) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -315,8 +315,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 37_584_000 picoseconds. - Weight::from_parts(44_010_000, 3533) + // Minimum execution time: 39_116_000 picoseconds. + Weight::from_parts(39_990_000, 3533) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -330,10 +330,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_history() -> Weight { // Proof Size summary in bytes: - // Measured: `830` + // Measured: `995` // Estimated: `3593` - // Minimum execution time: 45_266_000 picoseconds. - Weight::from_parts(48_000_000, 3593) + // Minimum execution time: 47_547_000 picoseconds. + Weight::from_parts(50_274_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -343,34 +343,32 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: - // Measured: `525` + // Measured: `661` // Estimated: `4698` - // Minimum execution time: 25_365_000 picoseconds. - Weight::from_parts(26_920_000, 4698) + // Minimum execution time: 26_707_000 picoseconds. + Weight::from_parts(27_217_000, 4698) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// The range of component `n` is `[0, 1000]`. - fn request_core_count(n: u32, ) -> Weight { + fn request_core_count(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_519_000 picoseconds. - Weight::from_parts(7_098_698, 0) - // Standard Error: 20 - .saturating_add(Weight::from_parts(8, 0).saturating_mul(n.into())) + // Minimum execution time: 4_651_000 picoseconds. + Weight::from_parts(5_231_385, 0) } - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: `Broker::CoreCountInbox` (r:1 w:1) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn process_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `98` - // Estimated: `3563` - // Minimum execution time: 7_608_000 picoseconds. - Weight::from_parts(8_157_815, 3563) - // Standard Error: 26 - .saturating_add(Weight::from_parts(48, 0).saturating_mul(n.into())) + // Measured: `404` + // Estimated: `1487` + // Minimum execution time: 6_806_000 picoseconds. + Weight::from_parts(7_264_002, 1487) + // Standard Error: 21 + .saturating_add(Weight::from_parts(31, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -386,10 +384,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn process_revenue() -> Weight { // Proof Size summary in bytes: - // Measured: `905` - // Estimated: `4370` - // Minimum execution time: 59_993_000 picoseconds. - Weight::from_parts(61_752_000, 4370) + // Measured: `972` + // Estimated: `4437` + // Minimum execution time: 48_297_000 picoseconds. + Weight::from_parts(49_613_000, 4437) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -408,10 +406,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 41_863_000 picoseconds. - Weight::from_parts(44_033_031, 8499) - // Standard Error: 116 - .saturating_add(Weight::from_parts(764, 0).saturating_mul(n.into())) + // Minimum execution time: 36_715_000 picoseconds. + Weight::from_parts(38_580_380, 8499) + // Standard Error: 91 + .saturating_add(Weight::from_parts(1_163, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)) } @@ -423,8 +421,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 9_588_000 picoseconds. - Weight::from_parts(9_925_000, 3493) + // Minimum execution time: 7_564_000 picoseconds. + Weight::from_parts(7_932_000, 3493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -436,8 +434,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 19_308_000 picoseconds. - Weight::from_parts(20_482_000, 4681) + // Minimum execution time: 17_082_000 picoseconds. + Weight::from_parts(17_662_000, 4681) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -445,28 +443,35 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 147_000 picoseconds. - Weight::from_parts(184_000, 0) + // Minimum execution time: 175_000 picoseconds. + Weight::from_parts(223_000, 0) } + /// Storage: `Broker::CoreCountInbox` (r:0 w:1) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) fn notify_core_count() -> Weight { - T::DbWeight::get().reads_writes(1, 1) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_432_000 picoseconds. + Weight::from_parts(2_536_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:1) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: `Broker::CoreCountInbox` (r:1 w:0) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) fn do_tick_base() -> Weight { // Proof Size summary in bytes: - // Measured: `699` - // Estimated: `4164` - // Minimum execution time: 19_824_000 picoseconds. - Weight::from_parts(20_983_000, 4164) + // Measured: `603` + // Estimated: `4068` + // Minimum execution time: 13_080_000 picoseconds. + Weight::from_parts(13_937_000, 4068) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } } @@ -478,8 +483,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_040_000 picoseconds. - Weight::from_parts(3_344_000, 0) + // Minimum execution time: 2_701_000 picoseconds. + Weight::from_parts(2_902_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -488,8 +493,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 21_259_000 picoseconds. - Weight::from_parts(22_110_000, 7496) + // Minimum execution time: 18_056_000 picoseconds. + Weight::from_parts(19_093_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -499,8 +504,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 20_330_000 picoseconds. - Weight::from_parts(20_826_000, 7496) + // Minimum execution time: 17_233_000 picoseconds. + Weight::from_parts(17_788_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -510,8 +515,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 13_411_000 picoseconds. - Weight::from_parts(13_960_000, 1526) + // Minimum execution time: 9_740_000 picoseconds. + Weight::from_parts(10_504_000, 1526) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -530,14 +535,12 @@ impl WeightInfo for () { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(n: u32, ) -> Weight { + fn start_sales(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 57_770_000 picoseconds. - Weight::from_parts(61_047_512, 8499) - // Standard Error: 165 - .saturating_add(Weight::from_parts(3, 0).saturating_mul(n.into())) + // Minimum execution time: 49_728_000 picoseconds. + Weight::from_parts(52_765_861, 8499) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(16_u64)) } @@ -553,10 +556,10 @@ impl WeightInfo for () { /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn purchase() -> Weight { // Proof Size summary in bytes: - // Measured: `568` - // Estimated: `2053` - // Minimum execution time: 51_196_000 picoseconds. - Weight::from_parts(52_382_000, 2053) + // Measured: `635` + // Estimated: `2120` + // Minimum execution time: 41_986_000 picoseconds. + Weight::from_parts(43_465_000, 2120) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -576,10 +579,10 @@ impl WeightInfo for () { /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `686` + // Measured: `753` // Estimated: `4698` - // Minimum execution time: 71_636_000 picoseconds. - Weight::from_parts(73_679_000, 4698) + // Minimum execution time: 61_779_000 picoseconds. + Weight::from_parts(62_563_000, 4698) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -589,8 +592,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 19_182_000 picoseconds. - Weight::from_parts(19_775_000, 3550) + // Minimum execution time: 16_962_000 picoseconds. + Weight::from_parts(17_733_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -600,21 +603,21 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 20_688_000 picoseconds. - Weight::from_parts(21_557_000, 3550) + // Minimum execution time: 18_380_000 picoseconds. + Weight::from_parts(19_105_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Broker::Regions` (r:1 w:2) + /// Storage: `Broker::Regions` (r:1 w:3) /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn interlace() -> Weight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 21_190_000 picoseconds. - Weight::from_parts(22_215_000, 3550) + // Minimum execution time: 20_115_000 picoseconds. + Weight::from_parts(20_741_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) @@ -628,8 +631,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `740` // Estimated: `4681` - // Minimum execution time: 34_591_000 picoseconds. - Weight::from_parts(36_227_000, 4681) + // Minimum execution time: 31_339_000 picoseconds. + Weight::from_parts(32_639_000, 4681) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -647,8 +650,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `775` // Estimated: `5996` - // Minimum execution time: 40_346_000 picoseconds. - Weight::from_parts(41_951_000, 5996) + // Minimum execution time: 37_542_000 picoseconds. + Weight::from_parts(38_521_000, 5996) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -663,10 +666,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 75_734_000 picoseconds. - Weight::from_parts(78_168_395, 6196) - // Standard Error: 63_180 - .saturating_add(Weight::from_parts(1_076_259, 0).saturating_mul(m.into())) + // Minimum execution time: 66_176_000 picoseconds. + Weight::from_parts(68_356_745, 6196) + // Standard Error: 68_008 + .saturating_add(Weight::from_parts(1_558_419, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(RocksDbWeight::get().writes(5_u64)) @@ -678,8 +681,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 46_383_000 picoseconds. - Weight::from_parts(47_405_000, 3593) + // Minimum execution time: 41_130_000 picoseconds. + Weight::from_parts(41_914_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -691,8 +694,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `603` // Estimated: `3550` - // Minimum execution time: 30_994_000 picoseconds. - Weight::from_parts(31_979_000, 3550) + // Minimum execution time: 31_042_000 picoseconds. + Weight::from_parts(34_087_000, 3550) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -706,8 +709,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 37_584_000 picoseconds. - Weight::from_parts(44_010_000, 3533) + // Minimum execution time: 39_116_000 picoseconds. + Weight::from_parts(39_990_000, 3533) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -721,10 +724,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_history() -> Weight { // Proof Size summary in bytes: - // Measured: `830` + // Measured: `995` // Estimated: `3593` - // Minimum execution time: 45_266_000 picoseconds. - Weight::from_parts(48_000_000, 3593) + // Minimum execution time: 47_547_000 picoseconds. + Weight::from_parts(50_274_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -734,34 +737,32 @@ impl WeightInfo for () { /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: - // Measured: `525` + // Measured: `661` // Estimated: `4698` - // Minimum execution time: 25_365_000 picoseconds. - Weight::from_parts(26_920_000, 4698) + // Minimum execution time: 26_707_000 picoseconds. + Weight::from_parts(27_217_000, 4698) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// The range of component `n` is `[0, 1000]`. - fn request_core_count(n: u32, ) -> Weight { + fn request_core_count(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_519_000 picoseconds. - Weight::from_parts(7_098_698, 0) - // Standard Error: 20 - .saturating_add(Weight::from_parts(8, 0).saturating_mul(n.into())) + // Minimum execution time: 4_651_000 picoseconds. + Weight::from_parts(5_231_385, 0) } - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: `Broker::CoreCountInbox` (r:1 w:1) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn process_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `98` - // Estimated: `3563` - // Minimum execution time: 7_608_000 picoseconds. - Weight::from_parts(8_157_815, 3563) - // Standard Error: 26 - .saturating_add(Weight::from_parts(48, 0).saturating_mul(n.into())) + // Measured: `404` + // Estimated: `1487` + // Minimum execution time: 6_806_000 picoseconds. + Weight::from_parts(7_264_002, 1487) + // Standard Error: 21 + .saturating_add(Weight::from_parts(31, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -777,10 +778,10 @@ impl WeightInfo for () { /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn process_revenue() -> Weight { // Proof Size summary in bytes: - // Measured: `905` - // Estimated: `4370` - // Minimum execution time: 59_993_000 picoseconds. - Weight::from_parts(61_752_000, 4370) + // Measured: `972` + // Estimated: `4437` + // Minimum execution time: 48_297_000 picoseconds. + Weight::from_parts(49_613_000, 4437) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -799,10 +800,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 41_863_000 picoseconds. - Weight::from_parts(44_033_031, 8499) - // Standard Error: 116 - .saturating_add(Weight::from_parts(764, 0).saturating_mul(n.into())) + // Minimum execution time: 36_715_000 picoseconds. + Weight::from_parts(38_580_380, 8499) + // Standard Error: 91 + .saturating_add(Weight::from_parts(1_163, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(15_u64)) } @@ -814,8 +815,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 9_588_000 picoseconds. - Weight::from_parts(9_925_000, 3493) + // Minimum execution time: 7_564_000 picoseconds. + Weight::from_parts(7_932_000, 3493) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -827,8 +828,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 19_308_000 picoseconds. - Weight::from_parts(20_482_000, 4681) + // Minimum execution time: 17_082_000 picoseconds. + Weight::from_parts(17_662_000, 4681) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -836,28 +837,34 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 147_000 picoseconds. - Weight::from_parts(184_000, 0) + // Minimum execution time: 175_000 picoseconds. + Weight::from_parts(223_000, 0) } + /// Storage: `Broker::CoreCountInbox` (r:0 w:1) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) fn notify_core_count() -> Weight { - RocksDbWeight::get().reads(1) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_432_000 picoseconds. + Weight::from_parts(2_536_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:1) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: `Broker::CoreCountInbox` (r:1 w:0) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) fn do_tick_base() -> Weight { // Proof Size summary in bytes: - // Measured: `699` - // Estimated: `4164` - // Minimum execution time: 19_824_000 picoseconds. - Weight::from_parts(20_983_000, 4164) + // Measured: `603` + // Estimated: `4068` + // Minimum execution time: 13_080_000 picoseconds. + Weight::from_parts(13_937_000, 4068) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/substrate/frame/child-bounties/src/weights.rs b/substrate/frame/child-bounties/src/weights.rs index e4c1f238e88..6427517b45b 100644 --- a/substrate/frame/child-bounties/src/weights.rs +++ b/substrate/frame/child-bounties/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_child_bounties +//! Autogenerated weights for `pallet_child_bounties` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/child-bounties/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/child-bounties/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_child_bounties. +/// Weight functions needed for `pallet_child_bounties`. pub trait WeightInfo { fn add_child_bounty(d: u32, ) -> Weight; fn propose_curator() -> Weight; @@ -62,288 +61,288 @@ pub trait WeightInfo { fn close_child_bounty_active() -> Weight; } -/// Weights for pallet_child_bounties using the Substrate node and recommended hardware. +/// Weights for `pallet_child_bounties` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: ChildBounties ParentChildBounties (r:1 w:1) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyCount (r:1 w:1) - /// Proof: ChildBounties ChildBountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:0 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyCount` (r:1 w:1) + /// Proof: `ChildBounties::ChildBountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:0 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) /// The range of component `d` is `[0, 300]`. fn add_child_bounty(_d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `712` + // Measured: `745` // Estimated: `6196` - // Minimum execution time: 69_805_000 picoseconds. - Weight::from_parts(73_216_717, 6196) + // Minimum execution time: 60_674_000 picoseconds. + Weight::from_parts(63_477_428, 6196) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `766` + // Measured: `799` // Estimated: `3642` - // Minimum execution time: 18_190_000 picoseconds. - Weight::from_parts(18_932_000, 3642) + // Minimum execution time: 17_754_000 picoseconds. + Weight::from_parts(18_655_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `912` + // Measured: `945` // Estimated: `3642` - // Minimum execution time: 35_035_000 picoseconds. - Weight::from_parts(35_975_000, 3642) + // Minimum execution time: 31_580_000 picoseconds. + Weight::from_parts(32_499_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `912` + // Measured: `945` // Estimated: `3642` - // Minimum execution time: 37_636_000 picoseconds. - Weight::from_parts(38_610_000, 3642) + // Minimum execution time: 33_536_000 picoseconds. + Weight::from_parts(34_102_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) fn award_child_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `842` // Estimated: `3642` - // Minimum execution time: 22_457_000 picoseconds. - Weight::from_parts(23_691_000, 3642) + // Minimum execution time: 18_295_000 picoseconds. + Weight::from_parts(19_496_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:1) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn claim_child_bounty() -> Weight { // Proof Size summary in bytes: // Measured: `682` // Estimated: `8799` - // Minimum execution time: 118_272_000 picoseconds. - Weight::from_parts(121_646_000, 8799) + // Minimum execution time: 102_367_000 picoseconds. + Weight::from_parts(104_352_000, 8799) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:1) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_child_bounty_added() -> Weight { // Proof Size summary in bytes: - // Measured: `1012` + // Measured: `1045` // Estimated: `6196` - // Minimum execution time: 75_717_000 picoseconds. - Weight::from_parts(77_837_000, 6196) + // Minimum execution time: 69_051_000 picoseconds. + Weight::from_parts(71_297_000, 6196) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:1) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_child_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `1199` + // Measured: `1232` // Estimated: `8799` - // Minimum execution time: 94_215_000 picoseconds. - Weight::from_parts(97_017_000, 8799) + // Minimum execution time: 84_053_000 picoseconds. + Weight::from_parts(86_072_000, 8799) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: ChildBounties ParentChildBounties (r:1 w:1) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyCount (r:1 w:1) - /// Proof: ChildBounties ChildBountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:0 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyCount` (r:1 w:1) + /// Proof: `ChildBounties::ChildBountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:0 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) /// The range of component `d` is `[0, 300]`. fn add_child_bounty(_d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `712` + // Measured: `745` // Estimated: `6196` - // Minimum execution time: 69_805_000 picoseconds. - Weight::from_parts(73_216_717, 6196) + // Minimum execution time: 60_674_000 picoseconds. + Weight::from_parts(63_477_428, 6196) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `766` + // Measured: `799` // Estimated: `3642` - // Minimum execution time: 18_190_000 picoseconds. - Weight::from_parts(18_932_000, 3642) + // Minimum execution time: 17_754_000 picoseconds. + Weight::from_parts(18_655_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `912` + // Measured: `945` // Estimated: `3642` - // Minimum execution time: 35_035_000 picoseconds. - Weight::from_parts(35_975_000, 3642) + // Minimum execution time: 31_580_000 picoseconds. + Weight::from_parts(32_499_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `912` + // Measured: `945` // Estimated: `3642` - // Minimum execution time: 37_636_000 picoseconds. - Weight::from_parts(38_610_000, 3642) + // Minimum execution time: 33_536_000 picoseconds. + Weight::from_parts(34_102_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) fn award_child_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `842` // Estimated: `3642` - // Minimum execution time: 22_457_000 picoseconds. - Weight::from_parts(23_691_000, 3642) + // Minimum execution time: 18_295_000 picoseconds. + Weight::from_parts(19_496_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:1) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn claim_child_bounty() -> Weight { // Proof Size summary in bytes: // Measured: `682` // Estimated: `8799` - // Minimum execution time: 118_272_000 picoseconds. - Weight::from_parts(121_646_000, 8799) + // Minimum execution time: 102_367_000 picoseconds. + Weight::from_parts(104_352_000, 8799) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:1) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_child_bounty_added() -> Weight { // Proof Size summary in bytes: - // Measured: `1012` + // Measured: `1045` // Estimated: `6196` - // Minimum execution time: 75_717_000 picoseconds. - Weight::from_parts(77_837_000, 6196) + // Minimum execution time: 69_051_000 picoseconds. + Weight::from_parts(71_297_000, 6196) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: Bounties Bounties (r:1 w:0) - /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBounties (r:1 w:1) - /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) - /// Storage: System Account (r:3 w:3) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) - /// Storage: ChildBounties ParentChildBounties (r:1 w:1) - /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: `Bounties::Bounties` (r:1 w:0) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) + /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) + /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) + /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_child_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `1199` + // Measured: `1232` // Estimated: `8799` - // Minimum execution time: 94_215_000 picoseconds. - Weight::from_parts(97_017_000, 8799) + // Minimum execution time: 84_053_000 picoseconds. + Weight::from_parts(86_072_000, 8799) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } diff --git a/substrate/frame/collective/src/tests.rs b/substrate/frame/collective/src/tests.rs index aae17b7ffc2..ac5797c638c 100644 --- a/substrate/frame/collective/src/tests.rs +++ b/substrate/frame/collective/src/tests.rs @@ -29,7 +29,7 @@ use sp_core::H256; use sp_runtime::{testing::Header, traits::BlakeTwo256, BuildStorage}; pub type Block = sp_runtime::generic::Block; -pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; frame_support::construct_runtime!( pub enum Test diff --git a/substrate/frame/collective/src/weights.rs b/substrate/frame/collective/src/weights.rs index eece6a006b8..85744b4de9d 100644 --- a/substrate/frame/collective/src/weights.rs +++ b/substrate/frame/collective/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_collective +//! Autogenerated weights for `pallet_collective` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/collective/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/collective/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_collective. +/// Weight functions needed for `pallet_collective`. pub trait WeightInfo { fn set_members(m: u32, n: u32, p: u32, ) -> Weight; fn execute(b: u32, m: u32, ) -> Weight; @@ -64,30 +63,30 @@ pub trait WeightInfo { fn disapprove_proposal(p: u32, ) -> Weight; } -/// Weights for pallet_collective using the Substrate node and recommended hardware. +/// Weights for `pallet_collective` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Council Members (r:1 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:100 w:100) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Prime (r:0 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:1) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:0) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Voting` (r:100 w:100) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:0 w:1) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[0, 100]`. /// The range of component `n` is `[0, 100]`. /// The range of component `p` is `[0, 100]`. fn set_members(m: u32, _n: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + m * (3232 ±0) + p * (3190 ±0)` - // Estimated: `15861 + m * (1967 ±24) + p * (4332 ±24)` - // Minimum execution time: 17_506_000 picoseconds. - Weight::from_parts(17_767_000, 15861) - // Standard Error: 60_220 - .saturating_add(Weight::from_parts(4_374_805, 0).saturating_mul(m.into())) - // Standard Error: 60_220 - .saturating_add(Weight::from_parts(8_398_316, 0).saturating_mul(p.into())) + // Estimated: `15894 + m * (1967 ±23) + p * (4332 ±23)` + // Minimum execution time: 15_559_000 picoseconds. + Weight::from_parts(15_870_000, 15894) + // Standard Error: 54_310 + .saturating_add(Weight::from_parts(4_117_753, 0).saturating_mul(m.into())) + // Standard Error: 54_310 + .saturating_add(Weight::from_parts(7_677_627, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -95,245 +94,261 @@ impl WeightInfo for SubstrateWeight { .saturating_add(Weight::from_parts(0, 1967).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 4332).saturating_mul(p.into())) } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `202 + m * (32 ±0)` - // Estimated: `1688 + m * (32 ±0)` - // Minimum execution time: 16_203_000 picoseconds. - Weight::from_parts(15_348_267, 1688) - // Standard Error: 37 - .saturating_add(Weight::from_parts(1_766, 0).saturating_mul(b.into())) - // Standard Error: 382 - .saturating_add(Weight::from_parts(15_765, 0).saturating_mul(m.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Measured: `380 + m * (32 ±0)` + // Estimated: `3997 + m * (32 ±0)` + // Minimum execution time: 19_024_000 picoseconds. + Weight::from_parts(18_153_872, 3997) + // Standard Error: 46 + .saturating_add(Weight::from_parts(1_933, 0).saturating_mul(b.into())) + // Standard Error: 478 + .saturating_add(Weight::from_parts(18_872, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:0) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:1 w:0) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `202 + m * (32 ±0)` - // Estimated: `3668 + m * (32 ±0)` - // Minimum execution time: 18_642_000 picoseconds. - Weight::from_parts(17_708_609, 3668) - // Standard Error: 58 - .saturating_add(Weight::from_parts(2_285, 0).saturating_mul(b.into())) - // Standard Error: 598 - .saturating_add(Weight::from_parts(30_454, 0).saturating_mul(m.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `380 + m * (32 ±0)` + // Estimated: `3997 + m * (32 ±0)` + // Minimum execution time: 20_895_000 picoseconds. + Weight::from_parts(20_081_761, 3997) + // Standard Error: 57 + .saturating_add(Weight::from_parts(1_982, 0).saturating_mul(b.into())) + // Standard Error: 594 + .saturating_add(Weight::from_parts(32_085, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalCount (r:1 w:1) - /// Proof Skipped: Council ProposalCount (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:0 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:1 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalCount` (r:1 w:1) + /// Proof: `Council::ProposalCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Voting` (r:0 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `492 + m * (32 ±0) + p * (36 ±0)` - // Estimated: `3884 + m * (33 ±0) + p * (36 ±0)` - // Minimum execution time: 27_067_000 picoseconds. - Weight::from_parts(25_456_964, 3884) - // Standard Error: 112 - .saturating_add(Weight::from_parts(3_773, 0).saturating_mul(b.into())) - // Standard Error: 1_177 - .saturating_add(Weight::from_parts(32_783, 0).saturating_mul(m.into())) - // Standard Error: 1_162 - .saturating_add(Weight::from_parts(194_388, 0).saturating_mul(p.into())) + // Measured: `525 + m * (32 ±0) + p * (36 ±0)` + // Estimated: `3917 + m * (33 ±0) + p * (36 ±0)` + // Minimum execution time: 22_068_000 picoseconds. + Weight::from_parts(19_639_088, 3917) + // Standard Error: 104 + .saturating_add(Weight::from_parts(3_896, 0).saturating_mul(b.into())) + // Standard Error: 1_095 + .saturating_add(Weight::from_parts(31_634, 0).saturating_mul(m.into())) + // Standard Error: 1_081 + .saturating_add(Weight::from_parts(178_702, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 33).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `941 + m * (64 ±0)` - // Estimated: `4405 + m * (64 ±0)` - // Minimum execution time: 26_055_000 picoseconds. - Weight::from_parts(27_251_907, 4405) - // Standard Error: 1_008 - .saturating_add(Weight::from_parts(65_947, 0).saturating_mul(m.into())) + // Measured: `974 + m * (64 ±0)` + // Estimated: `4438 + m * (64 ±0)` + // Minimum execution time: 22_395_000 picoseconds. + Weight::from_parts(23_025_217, 4438) + // Standard Error: 842 + .saturating_add(Weight::from_parts(58_102, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:0 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `530 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `3975 + m * (65 ±0) + p * (36 ±0)` - // Minimum execution time: 28_363_000 picoseconds. - Weight::from_parts(28_733_464, 3975) - // Standard Error: 1_275 - .saturating_add(Weight::from_parts(43_236, 0).saturating_mul(m.into())) - // Standard Error: 1_244 - .saturating_add(Weight::from_parts(180_187, 0).saturating_mul(p.into())) + // Measured: `563 + m * (64 ±0) + p * (36 ±0)` + // Estimated: `4008 + m * (65 ±0) + p * (36 ±0)` + // Minimum execution time: 24_179_000 picoseconds. + Weight::from_parts(23_846_394, 4008) + // Standard Error: 1_052 + .saturating_add(Weight::from_parts(40_418, 0).saturating_mul(m.into())) + // Standard Error: 1_026 + .saturating_add(Weight::from_parts(171_653, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 65).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:1 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `832 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `4149 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` - // Minimum execution time: 40_391_000 picoseconds. - Weight::from_parts(42_695_215, 4149) - // Standard Error: 167 - .saturating_add(Weight::from_parts(3_622, 0).saturating_mul(b.into())) - // Standard Error: 1_772 - .saturating_add(Weight::from_parts(33_830, 0).saturating_mul(m.into())) - // Standard Error: 1_727 - .saturating_add(Weight::from_parts(205_374, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Measured: `1010 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` + // Estimated: `4327 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` + // Minimum execution time: 42_129_000 picoseconds. + Weight::from_parts(40_808_957, 4327) + // Standard Error: 134 + .saturating_add(Weight::from_parts(3_579, 0).saturating_mul(b.into())) + // Standard Error: 1_425 + .saturating_add(Weight::from_parts(37_166, 0).saturating_mul(m.into())) + // Standard Error: 1_389 + .saturating_add(Weight::from_parts(200_986, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) .saturating_add(Weight::from_parts(0, 66).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:0) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:1 w:0) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:0 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `550 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `3995 + m * (65 ±0) + p * (36 ±0)` - // Minimum execution time: 31_368_000 picoseconds. - Weight::from_parts(32_141_835, 3995) - // Standard Error: 1_451 - .saturating_add(Weight::from_parts(36_372, 0).saturating_mul(m.into())) - // Standard Error: 1_415 - .saturating_add(Weight::from_parts(210_635, 0).saturating_mul(p.into())) + // Measured: `583 + m * (64 ±0) + p * (36 ±0)` + // Estimated: `4028 + m * (65 ±0) + p * (36 ±0)` + // Minimum execution time: 26_385_000 picoseconds. + Weight::from_parts(25_713_839, 4028) + // Standard Error: 1_254 + .saturating_add(Weight::from_parts(36_206, 0).saturating_mul(m.into())) + // Standard Error: 1_223 + .saturating_add(Weight::from_parts(195_114, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 65).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:0) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:1 w:0) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:1 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `852 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `4169 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` - // Minimum execution time: 43_271_000 picoseconds. - Weight::from_parts(45_495_648, 4169) - // Standard Error: 174 - .saturating_add(Weight::from_parts(3_034, 0).saturating_mul(b.into())) - // Standard Error: 1_840 - .saturating_add(Weight::from_parts(42_209, 0).saturating_mul(m.into())) - // Standard Error: 1_793 - .saturating_add(Weight::from_parts(207_525, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Measured: `1030 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` + // Estimated: `4347 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` + // Minimum execution time: 42_903_000 picoseconds. + Weight::from_parts(43_152_907, 4347) + // Standard Error: 146 + .saturating_add(Weight::from_parts(3_459, 0).saturating_mul(b.into())) + // Standard Error: 1_548 + .saturating_add(Weight::from_parts(35_321, 0).saturating_mul(m.into())) + // Standard Error: 1_509 + .saturating_add(Weight::from_parts(202_541, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) .saturating_add(Weight::from_parts(0, 66).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:0 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Voting` (r:0 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:0 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `359 + p * (32 ±0)` - // Estimated: `1844 + p * (32 ±0)` - // Minimum execution time: 15_170_000 picoseconds. - Weight::from_parts(17_567_243, 1844) - // Standard Error: 1_430 - .saturating_add(Weight::from_parts(169_040, 0).saturating_mul(p.into())) + // Measured: `392 + p * (32 ±0)` + // Estimated: `1877 + p * (32 ±0)` + // Minimum execution time: 12_656_000 picoseconds. + Weight::from_parts(14_032_951, 1877) + // Standard Error: 1_025 + .saturating_add(Weight::from_parts(159_143, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(p.into())) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Council Members (r:1 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:100 w:100) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Prime (r:0 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:1) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:0) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Voting` (r:100 w:100) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:0 w:1) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[0, 100]`. /// The range of component `n` is `[0, 100]`. /// The range of component `p` is `[0, 100]`. fn set_members(m: u32, _n: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + m * (3232 ±0) + p * (3190 ±0)` - // Estimated: `15861 + m * (1967 ±24) + p * (4332 ±24)` - // Minimum execution time: 17_506_000 picoseconds. - Weight::from_parts(17_767_000, 15861) - // Standard Error: 60_220 - .saturating_add(Weight::from_parts(4_374_805, 0).saturating_mul(m.into())) - // Standard Error: 60_220 - .saturating_add(Weight::from_parts(8_398_316, 0).saturating_mul(p.into())) + // Estimated: `15894 + m * (1967 ±23) + p * (4332 ±23)` + // Minimum execution time: 15_559_000 picoseconds. + Weight::from_parts(15_870_000, 15894) + // Standard Error: 54_310 + .saturating_add(Weight::from_parts(4_117_753, 0).saturating_mul(m.into())) + // Standard Error: 54_310 + .saturating_add(Weight::from_parts(7_677_627, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -341,216 +356,232 @@ impl WeightInfo for () { .saturating_add(Weight::from_parts(0, 1967).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 4332).saturating_mul(p.into())) } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `202 + m * (32 ±0)` - // Estimated: `1688 + m * (32 ±0)` - // Minimum execution time: 16_203_000 picoseconds. - Weight::from_parts(15_348_267, 1688) - // Standard Error: 37 - .saturating_add(Weight::from_parts(1_766, 0).saturating_mul(b.into())) - // Standard Error: 382 - .saturating_add(Weight::from_parts(15_765, 0).saturating_mul(m.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Measured: `380 + m * (32 ±0)` + // Estimated: `3997 + m * (32 ±0)` + // Minimum execution time: 19_024_000 picoseconds. + Weight::from_parts(18_153_872, 3997) + // Standard Error: 46 + .saturating_add(Weight::from_parts(1_933, 0).saturating_mul(b.into())) + // Standard Error: 478 + .saturating_add(Weight::from_parts(18_872, 0).saturating_mul(m.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:0) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:1 w:0) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `202 + m * (32 ±0)` - // Estimated: `3668 + m * (32 ±0)` - // Minimum execution time: 18_642_000 picoseconds. - Weight::from_parts(17_708_609, 3668) - // Standard Error: 58 - .saturating_add(Weight::from_parts(2_285, 0).saturating_mul(b.into())) - // Standard Error: 598 - .saturating_add(Weight::from_parts(30_454, 0).saturating_mul(m.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `380 + m * (32 ±0)` + // Estimated: `3997 + m * (32 ±0)` + // Minimum execution time: 20_895_000 picoseconds. + Weight::from_parts(20_081_761, 3997) + // Standard Error: 57 + .saturating_add(Weight::from_parts(1_982, 0).saturating_mul(b.into())) + // Standard Error: 594 + .saturating_add(Weight::from_parts(32_085, 0).saturating_mul(m.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalCount (r:1 w:1) - /// Proof Skipped: Council ProposalCount (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:0 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:1 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalCount` (r:1 w:1) + /// Proof: `Council::ProposalCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Voting` (r:0 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `492 + m * (32 ±0) + p * (36 ±0)` - // Estimated: `3884 + m * (33 ±0) + p * (36 ±0)` - // Minimum execution time: 27_067_000 picoseconds. - Weight::from_parts(25_456_964, 3884) - // Standard Error: 112 - .saturating_add(Weight::from_parts(3_773, 0).saturating_mul(b.into())) - // Standard Error: 1_177 - .saturating_add(Weight::from_parts(32_783, 0).saturating_mul(m.into())) - // Standard Error: 1_162 - .saturating_add(Weight::from_parts(194_388, 0).saturating_mul(p.into())) + // Measured: `525 + m * (32 ±0) + p * (36 ±0)` + // Estimated: `3917 + m * (33 ±0) + p * (36 ±0)` + // Minimum execution time: 22_068_000 picoseconds. + Weight::from_parts(19_639_088, 3917) + // Standard Error: 104 + .saturating_add(Weight::from_parts(3_896, 0).saturating_mul(b.into())) + // Standard Error: 1_095 + .saturating_add(Weight::from_parts(31_634, 0).saturating_mul(m.into())) + // Standard Error: 1_081 + .saturating_add(Weight::from_parts(178_702, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 33).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `941 + m * (64 ±0)` - // Estimated: `4405 + m * (64 ±0)` - // Minimum execution time: 26_055_000 picoseconds. - Weight::from_parts(27_251_907, 4405) - // Standard Error: 1_008 - .saturating_add(Weight::from_parts(65_947, 0).saturating_mul(m.into())) + // Measured: `974 + m * (64 ±0)` + // Estimated: `4438 + m * (64 ±0)` + // Minimum execution time: 22_395_000 picoseconds. + Weight::from_parts(23_025_217, 4438) + // Standard Error: 842 + .saturating_add(Weight::from_parts(58_102, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:0 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `530 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `3975 + m * (65 ±0) + p * (36 ±0)` - // Minimum execution time: 28_363_000 picoseconds. - Weight::from_parts(28_733_464, 3975) - // Standard Error: 1_275 - .saturating_add(Weight::from_parts(43_236, 0).saturating_mul(m.into())) - // Standard Error: 1_244 - .saturating_add(Weight::from_parts(180_187, 0).saturating_mul(p.into())) + // Measured: `563 + m * (64 ±0) + p * (36 ±0)` + // Estimated: `4008 + m * (65 ±0) + p * (36 ±0)` + // Minimum execution time: 24_179_000 picoseconds. + Weight::from_parts(23_846_394, 4008) + // Standard Error: 1_052 + .saturating_add(Weight::from_parts(40_418, 0).saturating_mul(m.into())) + // Standard Error: 1_026 + .saturating_add(Weight::from_parts(171_653, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 65).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:1 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `832 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `4149 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` - // Minimum execution time: 40_391_000 picoseconds. - Weight::from_parts(42_695_215, 4149) - // Standard Error: 167 - .saturating_add(Weight::from_parts(3_622, 0).saturating_mul(b.into())) - // Standard Error: 1_772 - .saturating_add(Weight::from_parts(33_830, 0).saturating_mul(m.into())) - // Standard Error: 1_727 - .saturating_add(Weight::from_parts(205_374, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + // Measured: `1010 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` + // Estimated: `4327 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` + // Minimum execution time: 42_129_000 picoseconds. + Weight::from_parts(40_808_957, 4327) + // Standard Error: 134 + .saturating_add(Weight::from_parts(3_579, 0).saturating_mul(b.into())) + // Standard Error: 1_425 + .saturating_add(Weight::from_parts(37_166, 0).saturating_mul(m.into())) + // Standard Error: 1_389 + .saturating_add(Weight::from_parts(200_986, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) .saturating_add(Weight::from_parts(0, 66).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:0) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:1 w:0) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:0 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `550 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `3995 + m * (65 ±0) + p * (36 ±0)` - // Minimum execution time: 31_368_000 picoseconds. - Weight::from_parts(32_141_835, 3995) - // Standard Error: 1_451 - .saturating_add(Weight::from_parts(36_372, 0).saturating_mul(m.into())) - // Standard Error: 1_415 - .saturating_add(Weight::from_parts(210_635, 0).saturating_mul(p.into())) + // Measured: `583 + m * (64 ±0) + p * (36 ±0)` + // Estimated: `4028 + m * (65 ±0) + p * (36 ±0)` + // Minimum execution time: 26_385_000 picoseconds. + Weight::from_parts(25_713_839, 4028) + // Standard Error: 1_254 + .saturating_add(Weight::from_parts(36_206, 0).saturating_mul(m.into())) + // Standard Error: 1_223 + .saturating_add(Weight::from_parts(195_114, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 65).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: Council Voting (r:1 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Members (r:1 w:0) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:0) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:1 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Council::Voting` (r:1 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:1 w:0) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:1 w:0) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:1 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `852 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `4169 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` - // Minimum execution time: 43_271_000 picoseconds. - Weight::from_parts(45_495_648, 4169) - // Standard Error: 174 - .saturating_add(Weight::from_parts(3_034, 0).saturating_mul(b.into())) - // Standard Error: 1_840 - .saturating_add(Weight::from_parts(42_209, 0).saturating_mul(m.into())) - // Standard Error: 1_793 - .saturating_add(Weight::from_parts(207_525, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Measured: `1030 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` + // Estimated: `4347 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` + // Minimum execution time: 42_903_000 picoseconds. + Weight::from_parts(43_152_907, 4347) + // Standard Error: 146 + .saturating_add(Weight::from_parts(3_459, 0).saturating_mul(b.into())) + // Standard Error: 1_548 + .saturating_add(Weight::from_parts(35_321, 0).saturating_mul(m.into())) + // Standard Error: 1_509 + .saturating_add(Weight::from_parts(202_541, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) .saturating_add(Weight::from_parts(0, 66).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: Council Proposals (r:1 w:1) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Voting (r:0 w:1) - /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council ProposalOf (r:0 w:1) - /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: `Council::Proposals` (r:1 w:1) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Voting` (r:0 w:1) + /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::ProposalOf` (r:0 w:1) + /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `359 + p * (32 ±0)` - // Estimated: `1844 + p * (32 ±0)` - // Minimum execution time: 15_170_000 picoseconds. - Weight::from_parts(17_567_243, 1844) - // Standard Error: 1_430 - .saturating_add(Weight::from_parts(169_040, 0).saturating_mul(p.into())) + // Measured: `392 + p * (32 ±0)` + // Estimated: `1877 + p * (32 ±0)` + // Minimum execution time: 12_656_000 picoseconds. + Weight::from_parts(14_032_951, 1877) + // Standard Error: 1_025 + .saturating_add(Weight::from_parts(159_143, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(p.into())) diff --git a/substrate/frame/contracts/src/weights.rs b/substrate/frame/contracts/src/weights.rs index 962591290b3..47ca17c7d80 100644 --- a/substrate/frame/contracts/src/weights.rs +++ b/substrate/frame/contracts/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_contracts` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_contracts +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_contracts -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/contracts/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -141,8 +143,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 1_997_000 picoseconds. - Weight::from_parts(2_130_000, 1627) + // Minimum execution time: 2_103_000 picoseconds. + Weight::from_parts(2_260_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -152,10 +154,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `452 + k * (69 ±0)` // Estimated: `442 + k * (70 ±0)` - // Minimum execution time: 12_276_000 picoseconds. - Weight::from_parts(1_593_881, 442) - // Standard Error: 1_135 - .saturating_add(Weight::from_parts(1_109_302, 0).saturating_mul(k.into())) + // Minimum execution time: 12_173_000 picoseconds. + Weight::from_parts(12_515_000, 442) + // Standard Error: 1_033 + .saturating_add(Weight::from_parts(1_075_765, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -169,8 +171,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_176_000 picoseconds. - Weight::from_parts(8_555_388, 6149) + // Minimum execution time: 8_054_000 picoseconds. + Weight::from_parts(8_503_485, 6149) // Standard Error: 1 .saturating_add(Weight::from_parts(1_184, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) @@ -185,8 +187,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 16_270_000 picoseconds. - Weight::from_parts(16_779_000, 6450) + // Minimum execution time: 16_966_000 picoseconds. + Weight::from_parts(17_445_000, 6450) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -199,10 +201,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_572_000 picoseconds. - Weight::from_parts(1_950_905, 3635) - // Standard Error: 1_597 - .saturating_add(Weight::from_parts(1_123_190, 0).saturating_mul(k.into())) + // Minimum execution time: 3_643_000 picoseconds. + Weight::from_parts(3_714_000, 3635) + // Standard Error: 1_056 + .saturating_add(Weight::from_parts(1_089_042, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -212,6 +214,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553053f13fd319a03c211337c76e0fe776df` (r:2 w:0) /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:0 w:1) @@ -219,13 +223,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `c` is `[0, 125952]`. fn v12_migration_step(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `325 + c * (1 ±0)` - // Estimated: `6263 + c * (1 ±0)` - // Minimum execution time: 16_873_000 picoseconds. - Weight::from_parts(16_790_402, 6263) + // Measured: `328 + c * (1 ±0)` + // Estimated: `6266 + c * (1 ±0)` + // Minimum execution time: 19_891_000 picoseconds. + Weight::from_parts(19_961_608, 6266) // Standard Error: 1 - .saturating_add(Weight::from_parts(396, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(Weight::from_parts(429, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } @@ -235,8 +239,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 11_904_000 picoseconds. - Weight::from_parts(12_785_000, 6380) + // Minimum execution time: 12_483_000 picoseconds. + Weight::from_parts(13_205_000, 6380) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -245,13 +249,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) fn v14_migration_step() -> Weight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `6292` - // Minimum execution time: 44_920_000 picoseconds. - Weight::from_parts(46_163_000, 6292) + // Minimum execution time: 42_443_000 picoseconds. + Weight::from_parts(43_420_000, 6292) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -263,8 +267,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 53_864_000 picoseconds. - Weight::from_parts(55_139_000, 6534) + // Minimum execution time: 52_282_000 picoseconds. + Weight::from_parts(54_110_000, 6534) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -274,8 +278,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_375_000 picoseconds. - Weight::from_parts(2_487_000, 1627) + // Minimum execution time: 2_539_000 picoseconds. + Weight::from_parts(2_644_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -287,8 +291,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 11_580_000 picoseconds. - Weight::from_parts(11_980_000, 3631) + // Minimum execution time: 9_473_000 picoseconds. + Weight::from_parts(9_907_000, 3631) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -298,8 +302,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 4_557_000 picoseconds. - Weight::from_parts(4_807_000, 3607) + // Minimum execution time: 3_532_000 picoseconds. + Weight::from_parts(3_768_000, 3607) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -310,8 +314,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 6_253_000 picoseconds. - Weight::from_parts(6_479_000, 3632) + // Minimum execution time: 5_036_000 picoseconds. + Weight::from_parts(5_208_000, 3632) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -322,13 +326,15 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 6_166_000 picoseconds. - Weight::from_parts(6_545_000, 3607) + // Minimum execution time: 4_881_000 picoseconds. + Weight::from_parts(5_149_000, 3607) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -344,22 +350,24 @@ impl WeightInfo for SubstrateWeight { /// The range of component `c` is `[0, 125952]`. fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `801 + c * (1 ±0)` - // Estimated: `6739 + c * (1 ±0)` - // Minimum execution time: 282_232_000 picoseconds. - Weight::from_parts(266_148_573, 6739) - // Standard Error: 69 - .saturating_add(Weight::from_parts(34_592, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `804 + c * (1 ±0)` + // Estimated: `9217 + c * (1 ±0)` + // Minimum execution time: 280_047_000 picoseconds. + Weight::from_parts(270_065_882, 9217) + // Standard Error: 86 + .saturating_add(Weight::from_parts(34_361, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:3 w:3) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) @@ -377,17 +385,17 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[0, 1048576]`. fn instantiate_with_code(c: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `323` - // Estimated: `8737` - // Minimum execution time: 3_760_879_000 picoseconds. - Weight::from_parts(794_812_431, 8737) + // Measured: `326` + // Estimated: `8740` + // Minimum execution time: 3_776_071_000 picoseconds. + Weight::from_parts(706_212_213, 8740) // Standard Error: 149 - .saturating_add(Weight::from_parts(101_881, 0).saturating_mul(c.into())) - // Standard Error: 18 - .saturating_add(Weight::from_parts(1_404, 0).saturating_mul(i.into())) - // Standard Error: 18 - .saturating_add(Weight::from_parts(1_544, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(Weight::from_parts(98_798, 0).saturating_mul(c.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(1_560, 0).saturating_mul(i.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(1_476, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) @@ -396,6 +404,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -407,24 +417,26 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:2 w:2) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `560` - // Estimated: `6504` - // Minimum execution time: 1_953_162_000 picoseconds. - Weight::from_parts(374_252_840, 6504) + // Measured: `563` + // Estimated: `8982` + // Minimum execution time: 1_966_301_000 picoseconds. + Weight::from_parts(376_287_434, 8982) // Standard Error: 7 - .saturating_add(Weight::from_parts(1_630, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(1_643, 0).saturating_mul(i.into())) // Standard Error: 7 - .saturating_add(Weight::from_parts(1_650, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(10_u64)) + .saturating_add(Weight::from_parts(1_667, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -439,19 +451,21 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `826` - // Estimated: `6766` - // Minimum execution time: 187_899_000 picoseconds. - Weight::from_parts(195_510_000, 6766) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `829` + // Estimated: `9244` + // Minimum execution time: 197_571_000 picoseconds. + Weight::from_parts(206_612_000, 9244) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -459,13 +473,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `c` is `[0, 125952]`. fn upload_code(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `3607` - // Minimum execution time: 254_800_000 picoseconds. - Weight::from_parts(285_603_050, 3607) - // Standard Error: 62 - .saturating_add(Weight::from_parts(66_212, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Measured: `145` + // Estimated: `6085` + // Minimum execution time: 266_006_000 picoseconds. + Weight::from_parts(287_700_788, 6085) + // Standard Error: 67 + .saturating_add(Weight::from_parts(63_196, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) @@ -473,7 +487,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -482,8 +496,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 43_553_000 picoseconds. - Weight::from_parts(45_036_000, 3780) + // Minimum execution time: 42_714_000 picoseconds. + Weight::from_parts(44_713_000, 3780) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -499,8 +513,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `552` // Estimated: `8967` - // Minimum execution time: 33_223_000 picoseconds. - Weight::from_parts(34_385_000, 8967) + // Minimum execution time: 33_516_000 picoseconds. + Weight::from_parts(34_823_000, 8967) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -508,6 +522,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -521,13 +537,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_caller(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `866 + r * (6 ±0)` - // Estimated: `6806 + r * (6 ±0)` - // Minimum execution time: 254_213_000 picoseconds. - Weight::from_parts(273_464_980, 6806) - // Standard Error: 1_362 - .saturating_add(Weight::from_parts(322_619, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `869 + r * (6 ±0)` + // Estimated: `9284 + r * (6 ±0)` + // Minimum execution time: 246_563_000 picoseconds. + Weight::from_parts(274_999_814, 9284) + // Standard Error: 628 + .saturating_add(Weight::from_parts(347_395, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -535,6 +551,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -548,13 +566,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_is_contract(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `922 + r * (209 ±0)` - // Estimated: `6826 + r * (2684 ±0)` - // Minimum execution time: 250_273_000 picoseconds. - Weight::from_parts(122_072_782, 6826) - // Standard Error: 5_629 - .saturating_add(Weight::from_parts(3_490_256, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `925 + r * (209 ±0)` + // Estimated: `9304 + r * (2684 ±0)` + // Minimum execution time: 252_236_000 picoseconds. + Weight::from_parts(121_390_081, 9304) + // Standard Error: 6_206 + .saturating_add(Weight::from_parts(3_558_718, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 2684).saturating_mul(r.into())) @@ -563,6 +581,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -576,13 +596,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `921 + r * (213 ±0)` - // Estimated: `6830 + r * (2688 ±0)` - // Minimum execution time: 255_187_000 picoseconds. - Weight::from_parts(118_082_505, 6830) - // Standard Error: 6_302 - .saturating_add(Weight::from_parts(4_246_968, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `924 + r * (213 ±0)` + // Estimated: `9308 + r * (2688 ±0)` + // Minimum execution time: 269_427_000 picoseconds. + Weight::from_parts(134_879_389, 9308) + // Standard Error: 6_711 + .saturating_add(Weight::from_parts(4_408_658, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 2688).saturating_mul(r.into())) @@ -591,6 +611,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -604,13 +626,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_own_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `873 + r * (6 ±0)` - // Estimated: `6815 + r * (6 ±0)` - // Minimum execution time: 256_833_000 picoseconds. - Weight::from_parts(273_330_216, 6815) - // Standard Error: 881 - .saturating_add(Weight::from_parts(400_105, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `876 + r * (6 ±0)` + // Estimated: `9293 + r * (6 ±0)` + // Minimum execution time: 249_382_000 picoseconds. + Weight::from_parts(266_305_110, 9293) + // Standard Error: 1_592 + .saturating_add(Weight::from_parts(460_001, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -618,6 +640,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -631,18 +655,20 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_caller_is_origin(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (3 ±0)` - // Estimated: `6804 + r * (3 ±0)` - // Minimum execution time: 244_193_000 picoseconds. - Weight::from_parts(271_221_908, 6804) - // Standard Error: 442 - .saturating_add(Weight::from_parts(176_480, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `866 + r * (3 ±0)` + // Estimated: `9282 + r * (3 ±0)` + // Minimum execution time: 252_145_000 picoseconds. + Weight::from_parts(277_211_668, 9282) + // Standard Error: 371 + .saturating_add(Weight::from_parts(174_394, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -656,13 +682,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_caller_is_root(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `753 + r * (3 ±0)` - // Estimated: `6693 + r * (3 ±0)` - // Minimum execution time: 232_603_000 picoseconds. - Weight::from_parts(260_577_368, 6693) - // Standard Error: 365 - .saturating_add(Weight::from_parts(158_126, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Measured: `756 + r * (3 ±0)` + // Estimated: `9171 + r * (3 ±0)` + // Minimum execution time: 251_595_000 picoseconds. + Weight::from_parts(268_102_575, 9171) + // Standard Error: 334 + .saturating_add(Weight::from_parts(154_836, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } @@ -670,6 +696,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -683,13 +711,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_address(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `867 + r * (6 ±0)` - // Estimated: `6807 + r * (6 ±0)` - // Minimum execution time: 247_564_000 picoseconds. - Weight::from_parts(275_108_914, 6807) - // Standard Error: 505 - .saturating_add(Weight::from_parts(315_065, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `870 + r * (6 ±0)` + // Estimated: `9285 + r * (6 ±0)` + // Minimum execution time: 251_404_000 picoseconds. + Weight::from_parts(278_747_574, 9285) + // Standard Error: 782 + .saturating_add(Weight::from_parts(341_598, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -697,6 +725,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -710,13 +740,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_gas_left(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (6 ±0)` - // Estimated: `6806 + r * (6 ±0)` - // Minimum execution time: 258_799_000 picoseconds. - Weight::from_parts(274_338_256, 6806) - // Standard Error: 632 - .saturating_add(Weight::from_parts(355_032, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `866 + r * (6 ±0)` + // Estimated: `9284 + r * (6 ±0)` + // Minimum execution time: 255_649_000 picoseconds. + Weight::from_parts(276_509_641, 9284) + // Standard Error: 1_262 + .saturating_add(Weight::from_parts(380_225, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -724,6 +754,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:2 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -737,13 +769,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_balance(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1007 + r * (6 ±0)` - // Estimated: `6931 + r * (6 ±0)` - // Minimum execution time: 253_335_000 picoseconds. - Weight::from_parts(273_013_859, 6931) - // Standard Error: 2_007 - .saturating_add(Weight::from_parts(1_540_735, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `1010 + r * (6 ±0)` + // Estimated: `9409 + r * (6 ±0)` + // Minimum execution time: 267_143_000 picoseconds. + Weight::from_parts(298_166_116, 9409) + // Standard Error: 3_765 + .saturating_add(Weight::from_parts(1_620_886, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -751,6 +783,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -764,13 +798,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_value_transferred(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `877 + r * (6 ±0)` - // Estimated: `6823 + r * (6 ±0)` - // Minimum execution time: 252_325_000 picoseconds. - Weight::from_parts(274_733_944, 6823) - // Standard Error: 603 - .saturating_add(Weight::from_parts(314_467, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `880 + r * (6 ±0)` + // Estimated: `9301 + r * (6 ±0)` + // Minimum execution time: 250_013_000 picoseconds. + Weight::from_parts(281_469_583, 9301) + // Standard Error: 730 + .saturating_add(Weight::from_parts(339_260, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -778,6 +812,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -791,13 +827,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_minimum_balance(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `875 + r * (6 ±0)` - // Estimated: `6816 + r * (6 ±0)` - // Minimum execution time: 250_698_000 picoseconds. - Weight::from_parts(271_707_578, 6816) - // Standard Error: 952 - .saturating_add(Weight::from_parts(318_412, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `878 + r * (6 ±0)` + // Estimated: `9294 + r * (6 ±0)` + // Minimum execution time: 256_219_000 picoseconds. + Weight::from_parts(275_309_266, 9294) + // Standard Error: 1_199 + .saturating_add(Weight::from_parts(350_824, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -805,6 +841,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -818,13 +856,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_block_number(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `872 + r * (6 ±0)` - // Estimated: `6819 + r * (6 ±0)` - // Minimum execution time: 251_854_000 picoseconds. - Weight::from_parts(272_002_212, 6819) - // Standard Error: 622 - .saturating_add(Weight::from_parts(313_353, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `875 + r * (6 ±0)` + // Estimated: `9297 + r * (6 ±0)` + // Minimum execution time: 264_644_000 picoseconds. + Weight::from_parts(283_856_744, 9297) + // Standard Error: 623 + .saturating_add(Weight::from_parts(334_175, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -832,6 +870,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -845,13 +885,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_now(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (6 ±0)` - // Estimated: `6804 + r * (6 ±0)` - // Minimum execution time: 252_010_000 picoseconds. - Weight::from_parts(270_387_000, 6804) - // Standard Error: 659 - .saturating_add(Weight::from_parts(325_856, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `866 + r * (6 ±0)` + // Estimated: `9282 + r * (6 ±0)` + // Minimum execution time: 263_364_000 picoseconds. + Weight::from_parts(281_379_508, 9282) + // Standard Error: 639 + .saturating_add(Weight::from_parts(338_021, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -859,6 +899,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -874,13 +916,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_weight_to_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `937 + r * (14 ±0)` - // Estimated: `6872 + r * (14 ±0)` - // Minimum execution time: 247_933_000 picoseconds. - Weight::from_parts(281_550_162, 6872) - // Standard Error: 660 - .saturating_add(Weight::from_parts(1_090_869, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `940 + r * (14 ±0)` + // Estimated: `9350 + r * (14 ±0)` + // Minimum execution time: 269_667_000 picoseconds. + Weight::from_parts(284_662_802, 9350) + // Standard Error: 691 + .saturating_add(Weight::from_parts(799_249, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 14).saturating_mul(r.into())) } @@ -888,6 +930,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -901,13 +945,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_input(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `865 + r * (6 ±0)` - // Estimated: `6807 + r * (6 ±0)` - // Minimum execution time: 251_158_000 picoseconds. - Weight::from_parts(274_623_152, 6807) - // Standard Error: 491 - .saturating_add(Weight::from_parts(263_916, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `868 + r * (6 ±0)` + // Estimated: `9285 + r * (6 ±0)` + // Minimum execution time: 267_018_000 picoseconds. + Weight::from_parts(281_842_630, 9285) + // Standard Error: 453 + .saturating_add(Weight::from_parts(255_373, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -915,6 +959,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -928,19 +974,21 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_input_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `869` - // Estimated: `6809` - // Minimum execution time: 263_205_000 picoseconds. - Weight::from_parts(216_792_893, 6809) + // Measured: `872` + // Estimated: `9287` + // Minimum execution time: 258_208_000 picoseconds. + Weight::from_parts(227_686_792, 9287) // Standard Error: 23 .saturating_add(Weight::from_parts(989, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -954,11 +1002,11 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1]`. fn seal_return(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `853 + r * (45 ±0)` - // Estimated: `6793 + r * (45 ±0)` - // Minimum execution time: 239_663_000 picoseconds. - Weight::from_parts(266_124_565, 6793) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `856 + r * (45 ±0)` + // Estimated: `9271 + r * (45 ±0)` + // Minimum execution time: 245_714_000 picoseconds. + Weight::from_parts(272_527_059, 9271) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 45).saturating_mul(r.into())) } @@ -966,6 +1014,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -979,19 +1029,21 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_return_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863` - // Estimated: `6810` - // Minimum execution time: 241_763_000 picoseconds. - Weight::from_parts(266_535_552, 6810) + // Measured: `866` + // Estimated: `9288` + // Minimum execution time: 256_060_000 picoseconds. + Weight::from_parts(276_710_811, 9288) // Standard Error: 0 - .saturating_add(Weight::from_parts(320, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(312, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:2) @@ -1005,28 +1057,30 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `Contracts::DeletionQueue` (r:0 w:1) /// Proof: `Contracts::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) /// The range of component `r` is `[0, 1]`. fn seal_terminate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2972 + r * (316 ±0)` - // Estimated: `8912 + r * (5266 ±0)` - // Minimum execution time: 265_888_000 picoseconds. - Weight::from_parts(291_232_232, 8912) - // Standard Error: 845_475 - .saturating_add(Weight::from_parts(104_398_867, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(r.into()))) + // Measured: `2902 + r * (529 ±0)` + // Estimated: `11317 + r * (5479 ±0)` + // Minimum execution time: 270_479_000 picoseconds. + Weight::from_parts(296_706_989, 11317) + // Standard Error: 813_407 + .saturating_add(Weight::from_parts(109_236_910, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((10_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 5266).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 5479).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1042,13 +1096,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_random(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `944 + r * (10 ±0)` - // Estimated: `6885 + r * (10 ±0)` - // Minimum execution time: 248_500_000 picoseconds. - Weight::from_parts(282_353_053, 6885) - // Standard Error: 1_144 - .saturating_add(Weight::from_parts(1_193_841, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `947 + r * (10 ±0)` + // Estimated: `9363 + r * (10 ±0)` + // Minimum execution time: 251_787_000 picoseconds. + Weight::from_parts(284_036_313, 9363) + // Standard Error: 2_560 + .saturating_add(Weight::from_parts(1_238_301, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) } @@ -1056,6 +1110,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1069,13 +1125,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_deposit_event(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (10 ±0)` - // Estimated: `6805 + r * (10 ±0)` - // Minimum execution time: 248_130_000 picoseconds. - Weight::from_parts(279_583_178, 6805) - // Standard Error: 971 - .saturating_add(Weight::from_parts(1_987_941, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `866 + r * (10 ±0)` + // Estimated: `9283 + r * (10 ±0)` + // Minimum execution time: 250_566_000 picoseconds. + Weight::from_parts(275_402_784, 9283) + // Standard Error: 3_939 + .saturating_add(Weight::from_parts(1_941_995, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) } @@ -1083,6 +1139,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1097,15 +1155,15 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_deposit_event_per_topic_and_byte(t: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `880 + t * (32 ±0)` - // Estimated: `6825 + t * (2508 ±0)` - // Minimum execution time: 258_594_000 picoseconds. - Weight::from_parts(276_734_422, 6825) - // Standard Error: 102_093 - .saturating_add(Weight::from_parts(2_559_383, 0).saturating_mul(t.into())) + // Measured: `883 + t * (32 ±0)` + // Estimated: `9303 + t * (2508 ±0)` + // Minimum execution time: 267_544_000 picoseconds. + Weight::from_parts(280_117_825, 9303) + // Standard Error: 102_111 + .saturating_add(Weight::from_parts(3_253_038, 0).saturating_mul(t.into())) // Standard Error: 28 - .saturating_add(Weight::from_parts(501, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(668, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into()))) @@ -1115,6 +1173,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1128,13 +1188,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_debug_message(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `862 + r * (7 ±0)` - // Estimated: `6807 + r * (7 ±0)` - // Minimum execution time: 154_564_000 picoseconds. - Weight::from_parts(168_931_365, 6807) - // Standard Error: 349 - .saturating_add(Weight::from_parts(226_848, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `865 + r * (7 ±0)` + // Estimated: `9285 + r * (7 ±0)` + // Minimum execution time: 157_769_000 picoseconds. + Weight::from_parts(173_026_565, 9285) + // Standard Error: 405 + .saturating_add(Weight::from_parts(219_727, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) } @@ -1142,6 +1202,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1155,13 +1217,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 1048576]`. fn seal_debug_message_per_byte(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `125813` - // Estimated: `131755` - // Minimum execution time: 394_382_000 picoseconds. - Weight::from_parts(376_780_500, 131755) + // Measured: `125816` + // Estimated: `131758` + // Minimum execution time: 403_961_000 picoseconds. + Weight::from_parts(376_480_872, 131758) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_026, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(1_041, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1169,13 +1231,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_set_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `924 + r * (292 ±0)` - // Estimated: `926 + r * (293 ±0)` - // Minimum execution time: 249_757_000 picoseconds. - Weight::from_parts(177_324_374, 926) - // Standard Error: 9_512 - .saturating_add(Weight::from_parts(6_176_717, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `927 + r * (292 ±0)` + // Estimated: `929 + r * (293 ±0)` + // Minimum execution time: 256_272_000 picoseconds. + Weight::from_parts(181_058_379, 929) + // Standard Error: 9_838 + .saturating_add(Weight::from_parts(6_316_677, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -1186,13 +1248,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_set_storage_per_new_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1447` - // Estimated: `1430` - // Minimum execution time: 267_564_000 picoseconds. - Weight::from_parts(328_701_080, 1430) - // Standard Error: 61 - .saturating_add(Weight::from_parts(576, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(12_u64)) + // Measured: `1450` + // Estimated: `1433` + // Minimum execution time: 268_713_000 picoseconds. + Weight::from_parts(328_329_131, 1433) + // Standard Error: 66 + .saturating_add(Weight::from_parts(962, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1200,13 +1262,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_set_storage_per_old_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1253 + n * (1 ±0)` - // Estimated: `1253 + n * (1 ±0)` - // Minimum execution time: 266_347_000 picoseconds. - Weight::from_parts(289_824_718, 1253) - // Standard Error: 34 - .saturating_add(Weight::from_parts(184, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `1256 + n * (1 ±0)` + // Estimated: `1256 + n * (1 ±0)` + // Minimum execution time: 265_683_000 picoseconds. + Weight::from_parts(293_784_477, 1256) + // Standard Error: 31 + .saturating_add(Weight::from_parts(377, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1215,13 +1277,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_clear_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `921 + r * (288 ±0)` - // Estimated: `927 + r * (289 ±0)` - // Minimum execution time: 247_207_000 picoseconds. - Weight::from_parts(179_856_075, 927) - // Standard Error: 9_383 - .saturating_add(Weight::from_parts(6_053_198, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `924 + r * (288 ±0)` + // Estimated: `930 + r * (289 ±0)` + // Minimum execution time: 269_959_000 picoseconds. + Weight::from_parts(186_065_911, 930) + // Standard Error: 9_679 + .saturating_add(Weight::from_parts(6_286_855, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -1232,13 +1294,11 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_clear_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1249 + n * (1 ±0)` - // Estimated: `1249 + n * (1 ±0)` - // Minimum execution time: 262_655_000 picoseconds. - Weight::from_parts(289_482_543, 1249) - // Standard Error: 35 - .saturating_add(Weight::from_parts(92, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `1252 + n * (1 ±0)` + // Estimated: `1252 + n * (1 ±0)` + // Minimum execution time: 265_805_000 picoseconds. + Weight::from_parts(294_633_695, 1252) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1247,13 +1307,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_get_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `921 + r * (296 ±0)` - // Estimated: `923 + r * (297 ±0)` - // Minimum execution time: 247_414_000 picoseconds. - Weight::from_parts(203_317_182, 923) - // Standard Error: 7_191 - .saturating_add(Weight::from_parts(4_925_154, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `924 + r * (296 ±0)` + // Estimated: `926 + r * (297 ±0)` + // Minimum execution time: 264_592_000 picoseconds. + Weight::from_parts(204_670_461, 926) + // Standard Error: 6_869 + .saturating_add(Weight::from_parts(5_137_920, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 297).saturating_mul(r.into())) @@ -1263,13 +1323,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_get_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1265 + n * (1 ±0)` - // Estimated: `1265 + n * (1 ±0)` - // Minimum execution time: 258_910_000 picoseconds. - Weight::from_parts(283_086_514, 1265) - // Standard Error: 39 - .saturating_add(Weight::from_parts(980, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `1268 + n * (1 ±0)` + // Estimated: `1268 + n * (1 ±0)` + // Minimum execution time: 273_165_000 picoseconds. + Weight::from_parts(297_883_669, 1268) + // Standard Error: 37 + .saturating_add(Weight::from_parts(576, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1278,13 +1338,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_contains_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `932 + r * (288 ±0)` - // Estimated: `929 + r * (289 ±0)` - // Minimum execution time: 252_410_000 picoseconds. - Weight::from_parts(201_227_879, 929) - // Standard Error: 6_899 - .saturating_add(Weight::from_parts(4_774_983, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `935 + r * (288 ±0)` + // Estimated: `932 + r * (289 ±0)` + // Minimum execution time: 252_257_000 picoseconds. + Weight::from_parts(205_018_595, 932) + // Standard Error: 7_605 + .saturating_add(Weight::from_parts(4_933_378, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 289).saturating_mul(r.into())) @@ -1294,13 +1354,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_contains_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1252 + n * (1 ±0)` - // Estimated: `1252 + n * (1 ±0)` - // Minimum execution time: 259_053_000 picoseconds. - Weight::from_parts(283_392_084, 1252) - // Standard Error: 41 - .saturating_add(Weight::from_parts(213, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `1255 + n * (1 ±0)` + // Estimated: `1255 + n * (1 ±0)` + // Minimum execution time: 266_839_000 picoseconds. + Weight::from_parts(292_064_487, 1255) + // Standard Error: 34 + .saturating_add(Weight::from_parts(194, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1309,13 +1369,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_take_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `914 + r * (296 ±0)` - // Estimated: `919 + r * (297 ±0)` - // Minimum execution time: 251_371_000 picoseconds. - Weight::from_parts(177_119_717, 919) - // Standard Error: 9_421 - .saturating_add(Weight::from_parts(6_226_005, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `917 + r * (296 ±0)` + // Estimated: `922 + r * (297 ±0)` + // Minimum execution time: 266_072_000 picoseconds. + Weight::from_parts(189_018_352, 922) + // Standard Error: 9_530 + .saturating_add(Weight::from_parts(6_481_011, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -1326,13 +1386,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 16384]`. fn seal_take_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1266 + n * (1 ±0)` - // Estimated: `1266 + n * (1 ±0)` - // Minimum execution time: 263_350_000 picoseconds. - Weight::from_parts(284_323_917, 1266) - // Standard Error: 31 - .saturating_add(Weight::from_parts(921, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `1269 + n * (1 ±0)` + // Estimated: `1269 + n * (1 ±0)` + // Minimum execution time: 270_703_000 picoseconds. + Weight::from_parts(292_867_105, 1269) + // Standard Error: 30 + .saturating_add(Weight::from_parts(800, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1340,6 +1400,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1602 w:1601) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1353,13 +1415,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_transfer(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1415 + r * (45 ±0)` - // Estimated: `7307 + r * (2520 ±0)` - // Minimum execution time: 248_701_000 picoseconds. - Weight::from_parts(17_811_969, 7307) - // Standard Error: 35_154 - .saturating_add(Weight::from_parts(31_809_738, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `1418 + r * (45 ±0)` + // Estimated: `9785 + r * (2520 ±0)` + // Minimum execution time: 251_843_000 picoseconds. + Weight::from_parts(181_026_888, 9785) + // Standard Error: 38_221 + .saturating_add(Weight::from_parts(30_626_681, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -1369,6 +1431,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -1382,13 +1446,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 800]`. fn seal_call(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1260 + r * (245 ±0)` - // Estimated: `9440 + r * (2721 ±0)` - // Minimum execution time: 247_335_000 picoseconds. - Weight::from_parts(264_025_000, 9440) - // Standard Error: 121_299 - .saturating_add(Weight::from_parts(234_770_827, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) + // Measured: `1263 + r * (245 ±0)` + // Estimated: `9635 + r * (2721 ±0)` + // Minimum execution time: 254_881_000 picoseconds. + Weight::from_parts(272_871_000, 9635) + // Standard Error: 94_527 + .saturating_add(Weight::from_parts(233_379_497, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(r.into()))) @@ -1398,6 +1462,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:736 w:0) @@ -1412,12 +1478,12 @@ impl WeightInfo for SubstrateWeight { fn seal_delegate_call(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (576 ±0)` - // Estimated: `6812 + r * (2637 ±3)` - // Minimum execution time: 261_011_000 picoseconds. - Weight::from_parts(264_554_000, 6812) - // Standard Error: 104_415 - .saturating_add(Weight::from_parts(231_627_084, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Estimated: `9290 + r * (2637 ±3)` + // Minimum execution time: 266_704_000 picoseconds. + Weight::from_parts(273_165_000, 9290) + // Standard Error: 141_486 + .saturating_add(Weight::from_parts(232_947_049, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -1427,6 +1493,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -1441,15 +1509,15 @@ impl WeightInfo for SubstrateWeight { /// The range of component `c` is `[0, 1048576]`. fn seal_call_per_transfer_clone_byte(t: u32, c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1307 + t * (277 ±0)` - // Estimated: `12197 + t * (5227 ±0)` - // Minimum execution time: 445_561_000 picoseconds. - Weight::from_parts(62_287_490, 12197) - // Standard Error: 11_797_697 - .saturating_add(Weight::from_parts(357_530_529, 0).saturating_mul(t.into())) + // Measured: `1310 + t * (277 ±0)` + // Estimated: `12200 + t * (5227 ±0)` + // Minimum execution time: 446_451_000 picoseconds. + Weight::from_parts(68_175_222, 12200) + // Standard Error: 11_619_250 + .saturating_add(Weight::from_parts(354_237_260, 0).saturating_mul(t.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(970, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(13_u64)) + .saturating_add(Weight::from_parts(987, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(16_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(t.into()))) @@ -1459,6 +1527,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:802 w:802) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:801 w:800) @@ -1472,17 +1542,17 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:803 w:803) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:800 w:800) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `r` is `[1, 800]`. fn seal_instantiate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1278 + r * (255 ±0)` - // Estimated: `9620 + r * (2731 ±0)` - // Minimum execution time: 621_897_000 picoseconds. - Weight::from_parts(631_687_000, 9620) - // Standard Error: 215_241 - .saturating_add(Weight::from_parts(350_527_831, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) + // Measured: `1281 + r * (255 ±0)` + // Estimated: `9623 + r * (2731 ±0)` + // Minimum execution time: 628_156_000 picoseconds. + Weight::from_parts(642_052_000, 9623) + // Standard Error: 223_957 + .saturating_add(Weight::from_parts(348_660_264, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(7_u64)) .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(r.into()))) @@ -1492,6 +1562,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:1) @@ -1505,23 +1577,23 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. fn seal_instantiate_per_transfer_input_salt_byte(t: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1303 + t * (104 ±0)` - // Estimated: `12211 + t * (2549 ±1)` - // Minimum execution time: 2_181_184_000 picoseconds. - Weight::from_parts(1_194_190_111, 12211) - // Standard Error: 11_578_766 - .saturating_add(Weight::from_parts(6_361_884, 0).saturating_mul(t.into())) - // Standard Error: 18 - .saturating_add(Weight::from_parts(1_025, 0).saturating_mul(i.into())) - // Standard Error: 18 - .saturating_add(Weight::from_parts(1_158, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(16_u64)) + // Measured: `1306 + t * (104 ±0)` + // Estimated: `12214 + t * (2549 ±1)` + // Minimum execution time: 2_106_379_000 picoseconds. + Weight::from_parts(1_098_227_098, 12214) + // Standard Error: 12_549_729 + .saturating_add(Weight::from_parts(21_628_382, 0).saturating_mul(t.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_059, 0).saturating_mul(i.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_220, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(19_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(11_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into()))) @@ -1531,6 +1603,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1544,13 +1618,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_hash_sha2_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `862 + r * (8 ±0)` - // Estimated: `6801 + r * (8 ±0)` - // Minimum execution time: 241_609_000 picoseconds. - Weight::from_parts(268_716_874, 6801) - // Standard Error: 617 - .saturating_add(Weight::from_parts(377_753, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `865 + r * (8 ±0)` + // Estimated: `9279 + r * (8 ±0)` + // Minimum execution time: 257_102_000 picoseconds. + Weight::from_parts(278_920_692, 9279) + // Standard Error: 464 + .saturating_add(Weight::from_parts(374_120, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) } @@ -1558,6 +1632,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1571,19 +1647,21 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `870` - // Estimated: `6808` - // Minimum execution time: 261_296_000 picoseconds. - Weight::from_parts(255_531_654, 6808) + // Measured: `873` + // Estimated: `9286` + // Minimum execution time: 266_609_000 picoseconds. + Weight::from_parts(263_034_132, 9286) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_081, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(1_082, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1597,13 +1675,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_hash_keccak_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `864 + r * (8 ±0)` - // Estimated: `6806 + r * (8 ±0)` - // Minimum execution time: 243_583_000 picoseconds. - Weight::from_parts(270_025_058, 6806) - // Standard Error: 560 - .saturating_add(Weight::from_parts(767_519, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `867 + r * (8 ±0)` + // Estimated: `9284 + r * (8 ±0)` + // Minimum execution time: 246_275_000 picoseconds. + Weight::from_parts(279_091_594, 9284) + // Standard Error: 887 + .saturating_add(Weight::from_parts(810_394, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) } @@ -1611,6 +1689,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1624,19 +1704,21 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `872` - // Estimated: `6814` - // Minimum execution time: 253_798_000 picoseconds. - Weight::from_parts(265_542_351, 6814) + // Measured: `875` + // Estimated: `9292` + // Minimum execution time: 249_254_000 picoseconds. + Weight::from_parts(270_833_823, 9292) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_343, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(3_347, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1650,13 +1732,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_hash_blake2_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `864 + r * (8 ±0)` - // Estimated: `6808 + r * (8 ±0)` - // Minimum execution time: 247_332_000 picoseconds. - Weight::from_parts(269_183_656, 6808) - // Standard Error: 665 - .saturating_add(Weight::from_parts(443_386, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `867 + r * (8 ±0)` + // Estimated: `9286 + r * (8 ±0)` + // Minimum execution time: 259_131_000 picoseconds. + Weight::from_parts(272_665_020, 9286) + // Standard Error: 862 + .saturating_add(Weight::from_parts(451_247, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) } @@ -1664,6 +1746,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1677,19 +1761,21 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `872` - // Estimated: `6813` - // Minimum execution time: 250_855_000 picoseconds. - Weight::from_parts(258_752_975, 6813) + // Measured: `875` + // Estimated: `9291` + // Minimum execution time: 276_465_000 picoseconds. + Weight::from_parts(269_450_297, 9291) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_202, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(1_190, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1703,13 +1789,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_hash_blake2_128(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `864 + r * (8 ±0)` - // Estimated: `6805 + r * (8 ±0)` - // Minimum execution time: 240_733_000 picoseconds. - Weight::from_parts(269_134_358, 6805) - // Standard Error: 512 - .saturating_add(Weight::from_parts(440_043, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `867 + r * (8 ±0)` + // Estimated: `9283 + r * (8 ±0)` + // Minimum execution time: 248_349_000 picoseconds. + Weight::from_parts(273_660_686, 9283) + // Standard Error: 656 + .saturating_add(Weight::from_parts(444_293, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) } @@ -1717,6 +1803,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1730,19 +1818,21 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `872` - // Estimated: `6811` - // Minimum execution time: 247_377_000 picoseconds. - Weight::from_parts(261_077_322, 6811) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1_195, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `875` + // Estimated: `9289` + // Minimum execution time: 252_107_000 picoseconds. + Weight::from_parts(267_427_726, 9289) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_199, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1756,13 +1846,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 125697]`. fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `997 + n * (1 ±0)` - // Estimated: `6934 + n * (1 ±0)` - // Minimum execution time: 307_337_000 picoseconds. - Weight::from_parts(326_710_473, 6934) - // Standard Error: 9 - .saturating_add(Weight::from_parts(5_765, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `1000 + n * (1 ±0)` + // Estimated: `9412 + n * (1 ±0)` + // Minimum execution time: 311_252_000 picoseconds. + Weight::from_parts(333_250_773, 9412) + // Standard Error: 12 + .saturating_add(Weight::from_parts(5_668, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1770,6 +1860,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1783,13 +1875,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 160]`. fn seal_sr25519_verify(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `805 + r * (112 ±0)` - // Estimated: `6748 + r * (112 ±0)` - // Minimum execution time: 245_432_000 picoseconds. - Weight::from_parts(294_206_377, 6748) - // Standard Error: 7_229 - .saturating_add(Weight::from_parts(41_480_485, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `810 + r * (112 ±0)` + // Estimated: `9226 + r * (112 ±0)` + // Minimum execution time: 267_431_000 picoseconds. + Weight::from_parts(300_733_048, 9226) + // Standard Error: 8_806 + .saturating_add(Weight::from_parts(42_169_197, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(r.into())) } @@ -1797,6 +1889,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1810,13 +1904,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 160]`. fn seal_ecdsa_recover(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `907 + r * (76 ±0)` - // Estimated: `6802 + r * (77 ±0)` - // Minimum execution time: 247_788_000 picoseconds. - Weight::from_parts(303_940_062, 6802) - // Standard Error: 10_671 - .saturating_add(Weight::from_parts(45_730_772, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `910 + r * (76 ±0)` + // Estimated: `9279 + r * (77 ±0)` + // Minimum execution time: 265_905_000 picoseconds. + Weight::from_parts(305_381_951, 9279) + // Standard Error: 9_863 + .saturating_add(Weight::from_parts(45_771_182, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 77).saturating_mul(r.into())) } @@ -1824,6 +1918,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1837,13 +1933,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 160]`. fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `877 + r * (42 ±0)` - // Estimated: `6816 + r * (42 ±0)` - // Minimum execution time: 248_825_000 picoseconds. - Weight::from_parts(286_832_225, 6816) - // Standard Error: 5_274 - .saturating_add(Weight::from_parts(11_889_262, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `880 + r * (42 ±0)` + // Estimated: `9294 + r * (42 ±0)` + // Minimum execution time: 266_701_000 picoseconds. + Weight::from_parts(292_407_888, 9294) + // Standard Error: 5_394 + .saturating_add(Weight::from_parts(11_896_065, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(r.into())) } @@ -1851,6 +1947,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536) @@ -1865,12 +1963,12 @@ impl WeightInfo for SubstrateWeight { fn seal_set_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (965 ±0)` - // Estimated: `6807 + r * (3090 ±7)` - // Minimum execution time: 244_982_000 picoseconds. - Weight::from_parts(265_297_000, 6807) - // Standard Error: 39_895 - .saturating_add(Weight::from_parts(22_435_888, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Estimated: `9285 + r * (3090 ±7)` + // Minimum execution time: 268_755_000 picoseconds. + Weight::from_parts(272_300_000, 9285) + // Standard Error: 43_747 + .saturating_add(Weight::from_parts(25_001_889, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(r.into()))) @@ -1880,6 +1978,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -1893,22 +1993,24 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 32]`. fn lock_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `928 + r * (131 ±0)` - // Estimated: `6878 + r * (2606 ±0)` - // Minimum execution time: 246_455_000 picoseconds. - Weight::from_parts(275_334_919, 6878) - // Standard Error: 20_911 - .saturating_add(Weight::from_parts(6_427_525, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `937 + r * (131 ±0)` + // Estimated: `9346 + r * (2607 ±0)` + // Minimum execution time: 255_190_000 picoseconds. + Weight::from_parts(285_643_922, 9346) + // Standard Error: 23_582 + .saturating_add(Weight::from_parts(6_289_940, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2606).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 2607).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -1922,13 +2024,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 32]`. fn unlock_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `969 + r * (183 ±0)` + // Measured: `972 + r * (184 ±0)` // Estimated: `129453 + r * (2568 ±0)` - // Minimum execution time: 254_472_000 picoseconds. - Weight::from_parts(280_657_909, 129453) - // Standard Error: 20_131 - .saturating_add(Weight::from_parts(5_644_006, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Minimum execution time: 260_061_000 picoseconds. + Weight::from_parts(286_849_343, 129453) + // Standard Error: 22_406 + .saturating_add(Weight::from_parts(5_661_459, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -1938,6 +2040,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1951,13 +2055,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_reentrance_count(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `858 + r * (3 ±0)` - // Estimated: `6804 + r * (3 ±0)` - // Minimum execution time: 250_535_000 picoseconds. - Weight::from_parts(270_318_376, 6804) - // Standard Error: 386 - .saturating_add(Weight::from_parts(174_627, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `861 + r * (3 ±0)` + // Estimated: `9282 + r * (3 ±0)` + // Minimum execution time: 250_922_000 picoseconds. + Weight::from_parts(277_294_913, 9282) + // Standard Error: 391 + .saturating_add(Weight::from_parts(169_457, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } @@ -1965,6 +2069,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1978,13 +2084,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_account_reentrance_count(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2109 + r * (39 ±0)` - // Estimated: `7899 + r * (40 ±0)` - // Minimum execution time: 248_174_000 picoseconds. - Weight::from_parts(301_826_520, 7899) - // Standard Error: 801 - .saturating_add(Weight::from_parts(248_479, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `2112 + r * (39 ±0)` + // Estimated: `10377 + r * (40 ±0)` + // Minimum execution time: 267_293_000 picoseconds. + Weight::from_parts(309_125_635, 10377) + // Standard Error: 637 + .saturating_add(Weight::from_parts(245_508, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 40).saturating_mul(r.into())) } @@ -1992,6 +2098,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2007,13 +2115,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 1600]`. fn seal_instantiation_nonce(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `861 + r * (3 ±0)` - // Estimated: `6801 + r * (3 ±0)` - // Minimum execution time: 246_540_000 picoseconds. - Weight::from_parts(268_913_509, 6801) - // Standard Error: 378 - .saturating_add(Weight::from_parts(154_950, 0).saturating_mul(r.into())) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Measured: `864 + r * (3 ±0)` + // Estimated: `9279 + r * (3 ±0)` + // Minimum execution time: 256_057_000 picoseconds. + Weight::from_parts(278_068_870, 9279) + // Standard Error: 335 + .saturating_add(Weight::from_parts(152_083, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } @@ -2022,10 +2130,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_777_000 picoseconds. - Weight::from_parts(1_707_601, 0) - // Standard Error: 14 - .saturating_add(Weight::from_parts(15_392, 0).saturating_mul(r.into())) + // Minimum execution time: 1_846_000 picoseconds. + Weight::from_parts(1_808_029, 0) + // Standard Error: 9 + .saturating_add(Weight::from_parts(14_937, 0).saturating_mul(r.into())) } } @@ -2037,8 +2145,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 1_997_000 picoseconds. - Weight::from_parts(2_130_000, 1627) + // Minimum execution time: 2_103_000 picoseconds. + Weight::from_parts(2_260_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -2048,10 +2156,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `452 + k * (69 ±0)` // Estimated: `442 + k * (70 ±0)` - // Minimum execution time: 12_276_000 picoseconds. - Weight::from_parts(1_593_881, 442) - // Standard Error: 1_135 - .saturating_add(Weight::from_parts(1_109_302, 0).saturating_mul(k.into())) + // Minimum execution time: 12_173_000 picoseconds. + Weight::from_parts(12_515_000, 442) + // Standard Error: 1_033 + .saturating_add(Weight::from_parts(1_075_765, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -2065,8 +2173,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_176_000 picoseconds. - Weight::from_parts(8_555_388, 6149) + // Minimum execution time: 8_054_000 picoseconds. + Weight::from_parts(8_503_485, 6149) // Standard Error: 1 .saturating_add(Weight::from_parts(1_184, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) @@ -2081,8 +2189,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 16_270_000 picoseconds. - Weight::from_parts(16_779_000, 6450) + // Minimum execution time: 16_966_000 picoseconds. + Weight::from_parts(17_445_000, 6450) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2095,10 +2203,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_572_000 picoseconds. - Weight::from_parts(1_950_905, 3635) - // Standard Error: 1_597 - .saturating_add(Weight::from_parts(1_123_190, 0).saturating_mul(k.into())) + // Minimum execution time: 3_643_000 picoseconds. + Weight::from_parts(3_714_000, 3635) + // Standard Error: 1_056 + .saturating_add(Weight::from_parts(1_089_042, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -2108,6 +2216,8 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553053f13fd319a03c211337c76e0fe776df` (r:2 w:0) /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:0 w:1) @@ -2115,13 +2225,13 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 125952]`. fn v12_migration_step(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `325 + c * (1 ±0)` - // Estimated: `6263 + c * (1 ±0)` - // Minimum execution time: 16_873_000 picoseconds. - Weight::from_parts(16_790_402, 6263) + // Measured: `328 + c * (1 ±0)` + // Estimated: `6266 + c * (1 ±0)` + // Minimum execution time: 19_891_000 picoseconds. + Weight::from_parts(19_961_608, 6266) // Standard Error: 1 - .saturating_add(Weight::from_parts(396, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(Weight::from_parts(429, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } @@ -2131,8 +2241,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 11_904_000 picoseconds. - Weight::from_parts(12_785_000, 6380) + // Minimum execution time: 12_483_000 picoseconds. + Weight::from_parts(13_205_000, 6380) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2141,13 +2251,13 @@ impl WeightInfo for () { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) fn v14_migration_step() -> Weight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `6292` - // Minimum execution time: 44_920_000 picoseconds. - Weight::from_parts(46_163_000, 6292) + // Minimum execution time: 42_443_000 picoseconds. + Weight::from_parts(43_420_000, 6292) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2159,8 +2269,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 53_864_000 picoseconds. - Weight::from_parts(55_139_000, 6534) + // Minimum execution time: 52_282_000 picoseconds. + Weight::from_parts(54_110_000, 6534) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2170,8 +2280,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_375_000 picoseconds. - Weight::from_parts(2_487_000, 1627) + // Minimum execution time: 2_539_000 picoseconds. + Weight::from_parts(2_644_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2183,8 +2293,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 11_580_000 picoseconds. - Weight::from_parts(11_980_000, 3631) + // Minimum execution time: 9_473_000 picoseconds. + Weight::from_parts(9_907_000, 3631) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2194,8 +2304,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 4_557_000 picoseconds. - Weight::from_parts(4_807_000, 3607) + // Minimum execution time: 3_532_000 picoseconds. + Weight::from_parts(3_768_000, 3607) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -2206,8 +2316,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 6_253_000 picoseconds. - Weight::from_parts(6_479_000, 3632) + // Minimum execution time: 5_036_000 picoseconds. + Weight::from_parts(5_208_000, 3632) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -2218,13 +2328,15 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 6_166_000 picoseconds. - Weight::from_parts(6_545_000, 3607) + // Minimum execution time: 4_881_000 picoseconds. + Weight::from_parts(5_149_000, 3607) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2240,22 +2352,24 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 125952]`. fn call_with_code_per_byte(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `801 + c * (1 ±0)` - // Estimated: `6739 + c * (1 ±0)` - // Minimum execution time: 282_232_000 picoseconds. - Weight::from_parts(266_148_573, 6739) - // Standard Error: 69 - .saturating_add(Weight::from_parts(34_592, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `804 + c * (1 ±0)` + // Estimated: `9217 + c * (1 ±0)` + // Minimum execution time: 280_047_000 picoseconds. + Weight::from_parts(270_065_882, 9217) + // Standard Error: 86 + .saturating_add(Weight::from_parts(34_361, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:3 w:3) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) @@ -2273,17 +2387,17 @@ impl WeightInfo for () { /// The range of component `s` is `[0, 1048576]`. fn instantiate_with_code(c: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `323` - // Estimated: `8737` - // Minimum execution time: 3_760_879_000 picoseconds. - Weight::from_parts(794_812_431, 8737) + // Measured: `326` + // Estimated: `8740` + // Minimum execution time: 3_776_071_000 picoseconds. + Weight::from_parts(706_212_213, 8740) // Standard Error: 149 - .saturating_add(Weight::from_parts(101_881, 0).saturating_mul(c.into())) - // Standard Error: 18 - .saturating_add(Weight::from_parts(1_404, 0).saturating_mul(i.into())) - // Standard Error: 18 - .saturating_add(Weight::from_parts(1_544, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(Weight::from_parts(98_798, 0).saturating_mul(c.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(1_560, 0).saturating_mul(i.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(1_476, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) @@ -2292,6 +2406,8 @@ impl WeightInfo for () { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -2303,24 +2419,26 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:2 w:2) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `560` - // Estimated: `6504` - // Minimum execution time: 1_953_162_000 picoseconds. - Weight::from_parts(374_252_840, 6504) + // Measured: `563` + // Estimated: `8982` + // Minimum execution time: 1_966_301_000 picoseconds. + Weight::from_parts(376_287_434, 8982) // Standard Error: 7 - .saturating_add(Weight::from_parts(1_630, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(1_643, 0).saturating_mul(i.into())) // Standard Error: 7 - .saturating_add(Weight::from_parts(1_650, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(10_u64)) + .saturating_add(Weight::from_parts(1_667, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2335,19 +2453,21 @@ impl WeightInfo for () { /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `826` - // Estimated: `6766` - // Minimum execution time: 187_899_000 picoseconds. - Weight::from_parts(195_510_000, 6766) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `829` + // Estimated: `9244` + // Minimum execution time: 197_571_000 picoseconds. + Weight::from_parts(206_612_000, 9244) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -2355,13 +2475,13 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 125952]`. fn upload_code(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `3607` - // Minimum execution time: 254_800_000 picoseconds. - Weight::from_parts(285_603_050, 3607) - // Standard Error: 62 - .saturating_add(Weight::from_parts(66_212, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + // Measured: `145` + // Estimated: `6085` + // Minimum execution time: 266_006_000 picoseconds. + Weight::from_parts(287_700_788, 6085) + // Standard Error: 67 + .saturating_add(Weight::from_parts(63_196, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) @@ -2369,7 +2489,7 @@ impl WeightInfo for () { /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -2378,8 +2498,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 43_553_000 picoseconds. - Weight::from_parts(45_036_000, 3780) + // Minimum execution time: 42_714_000 picoseconds. + Weight::from_parts(44_713_000, 3780) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2395,8 +2515,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `552` // Estimated: `8967` - // Minimum execution time: 33_223_000 picoseconds. - Weight::from_parts(34_385_000, 8967) + // Minimum execution time: 33_516_000 picoseconds. + Weight::from_parts(34_823_000, 8967) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -2404,6 +2524,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2417,13 +2539,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_caller(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `866 + r * (6 ±0)` - // Estimated: `6806 + r * (6 ±0)` - // Minimum execution time: 254_213_000 picoseconds. - Weight::from_parts(273_464_980, 6806) - // Standard Error: 1_362 - .saturating_add(Weight::from_parts(322_619, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `869 + r * (6 ±0)` + // Estimated: `9284 + r * (6 ±0)` + // Minimum execution time: 246_563_000 picoseconds. + Weight::from_parts(274_999_814, 9284) + // Standard Error: 628 + .saturating_add(Weight::from_parts(347_395, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2431,6 +2553,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2444,13 +2568,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_is_contract(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `922 + r * (209 ±0)` - // Estimated: `6826 + r * (2684 ±0)` - // Minimum execution time: 250_273_000 picoseconds. - Weight::from_parts(122_072_782, 6826) - // Standard Error: 5_629 - .saturating_add(Weight::from_parts(3_490_256, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `925 + r * (209 ±0)` + // Estimated: `9304 + r * (2684 ±0)` + // Minimum execution time: 252_236_000 picoseconds. + Weight::from_parts(121_390_081, 9304) + // Standard Error: 6_206 + .saturating_add(Weight::from_parts(3_558_718, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 2684).saturating_mul(r.into())) @@ -2459,6 +2583,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2472,13 +2598,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `921 + r * (213 ±0)` - // Estimated: `6830 + r * (2688 ±0)` - // Minimum execution time: 255_187_000 picoseconds. - Weight::from_parts(118_082_505, 6830) - // Standard Error: 6_302 - .saturating_add(Weight::from_parts(4_246_968, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `924 + r * (213 ±0)` + // Estimated: `9308 + r * (2688 ±0)` + // Minimum execution time: 269_427_000 picoseconds. + Weight::from_parts(134_879_389, 9308) + // Standard Error: 6_711 + .saturating_add(Weight::from_parts(4_408_658, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 2688).saturating_mul(r.into())) @@ -2487,6 +2613,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2500,13 +2628,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_own_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `873 + r * (6 ±0)` - // Estimated: `6815 + r * (6 ±0)` - // Minimum execution time: 256_833_000 picoseconds. - Weight::from_parts(273_330_216, 6815) - // Standard Error: 881 - .saturating_add(Weight::from_parts(400_105, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `876 + r * (6 ±0)` + // Estimated: `9293 + r * (6 ±0)` + // Minimum execution time: 249_382_000 picoseconds. + Weight::from_parts(266_305_110, 9293) + // Standard Error: 1_592 + .saturating_add(Weight::from_parts(460_001, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2514,6 +2642,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2527,18 +2657,20 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_caller_is_origin(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (3 ±0)` - // Estimated: `6804 + r * (3 ±0)` - // Minimum execution time: 244_193_000 picoseconds. - Weight::from_parts(271_221_908, 6804) - // Standard Error: 442 - .saturating_add(Weight::from_parts(176_480, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `866 + r * (3 ±0)` + // Estimated: `9282 + r * (3 ±0)` + // Minimum execution time: 252_145_000 picoseconds. + Weight::from_parts(277_211_668, 9282) + // Standard Error: 371 + .saturating_add(Weight::from_parts(174_394, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2552,13 +2684,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_caller_is_root(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `753 + r * (3 ±0)` - // Estimated: `6693 + r * (3 ±0)` - // Minimum execution time: 232_603_000 picoseconds. - Weight::from_parts(260_577_368, 6693) - // Standard Error: 365 - .saturating_add(Weight::from_parts(158_126, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(7_u64)) + // Measured: `756 + r * (3 ±0)` + // Estimated: `9171 + r * (3 ±0)` + // Minimum execution time: 251_595_000 picoseconds. + Weight::from_parts(268_102_575, 9171) + // Standard Error: 334 + .saturating_add(Weight::from_parts(154_836, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(10_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } @@ -2566,6 +2698,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2579,13 +2713,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_address(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `867 + r * (6 ±0)` - // Estimated: `6807 + r * (6 ±0)` - // Minimum execution time: 247_564_000 picoseconds. - Weight::from_parts(275_108_914, 6807) - // Standard Error: 505 - .saturating_add(Weight::from_parts(315_065, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `870 + r * (6 ±0)` + // Estimated: `9285 + r * (6 ±0)` + // Minimum execution time: 251_404_000 picoseconds. + Weight::from_parts(278_747_574, 9285) + // Standard Error: 782 + .saturating_add(Weight::from_parts(341_598, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2593,6 +2727,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2606,13 +2742,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_gas_left(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (6 ±0)` - // Estimated: `6806 + r * (6 ±0)` - // Minimum execution time: 258_799_000 picoseconds. - Weight::from_parts(274_338_256, 6806) - // Standard Error: 632 - .saturating_add(Weight::from_parts(355_032, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `866 + r * (6 ±0)` + // Estimated: `9284 + r * (6 ±0)` + // Minimum execution time: 255_649_000 picoseconds. + Weight::from_parts(276_509_641, 9284) + // Standard Error: 1_262 + .saturating_add(Weight::from_parts(380_225, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2620,6 +2756,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:2 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2633,13 +2771,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_balance(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1007 + r * (6 ±0)` - // Estimated: `6931 + r * (6 ±0)` - // Minimum execution time: 253_335_000 picoseconds. - Weight::from_parts(273_013_859, 6931) - // Standard Error: 2_007 - .saturating_add(Weight::from_parts(1_540_735, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `1010 + r * (6 ±0)` + // Estimated: `9409 + r * (6 ±0)` + // Minimum execution time: 267_143_000 picoseconds. + Weight::from_parts(298_166_116, 9409) + // Standard Error: 3_765 + .saturating_add(Weight::from_parts(1_620_886, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2647,6 +2785,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2660,13 +2800,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_value_transferred(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `877 + r * (6 ±0)` - // Estimated: `6823 + r * (6 ±0)` - // Minimum execution time: 252_325_000 picoseconds. - Weight::from_parts(274_733_944, 6823) - // Standard Error: 603 - .saturating_add(Weight::from_parts(314_467, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `880 + r * (6 ±0)` + // Estimated: `9301 + r * (6 ±0)` + // Minimum execution time: 250_013_000 picoseconds. + Weight::from_parts(281_469_583, 9301) + // Standard Error: 730 + .saturating_add(Weight::from_parts(339_260, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2674,6 +2814,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2687,13 +2829,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_minimum_balance(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `875 + r * (6 ±0)` - // Estimated: `6816 + r * (6 ±0)` - // Minimum execution time: 250_698_000 picoseconds. - Weight::from_parts(271_707_578, 6816) - // Standard Error: 952 - .saturating_add(Weight::from_parts(318_412, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `878 + r * (6 ±0)` + // Estimated: `9294 + r * (6 ±0)` + // Minimum execution time: 256_219_000 picoseconds. + Weight::from_parts(275_309_266, 9294) + // Standard Error: 1_199 + .saturating_add(Weight::from_parts(350_824, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2701,6 +2843,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2714,13 +2858,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_block_number(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `872 + r * (6 ±0)` - // Estimated: `6819 + r * (6 ±0)` - // Minimum execution time: 251_854_000 picoseconds. - Weight::from_parts(272_002_212, 6819) - // Standard Error: 622 - .saturating_add(Weight::from_parts(313_353, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `875 + r * (6 ±0)` + // Estimated: `9297 + r * (6 ±0)` + // Minimum execution time: 264_644_000 picoseconds. + Weight::from_parts(283_856_744, 9297) + // Standard Error: 623 + .saturating_add(Weight::from_parts(334_175, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2728,6 +2872,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2741,13 +2887,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_now(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (6 ±0)` - // Estimated: `6804 + r * (6 ±0)` - // Minimum execution time: 252_010_000 picoseconds. - Weight::from_parts(270_387_000, 6804) - // Standard Error: 659 - .saturating_add(Weight::from_parts(325_856, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `866 + r * (6 ±0)` + // Estimated: `9282 + r * (6 ±0)` + // Minimum execution time: 263_364_000 picoseconds. + Weight::from_parts(281_379_508, 9282) + // Standard Error: 639 + .saturating_add(Weight::from_parts(338_021, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2755,6 +2901,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2770,13 +2918,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_weight_to_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `937 + r * (14 ±0)` - // Estimated: `6872 + r * (14 ±0)` - // Minimum execution time: 247_933_000 picoseconds. - Weight::from_parts(281_550_162, 6872) - // Standard Error: 660 - .saturating_add(Weight::from_parts(1_090_869, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `940 + r * (14 ±0)` + // Estimated: `9350 + r * (14 ±0)` + // Minimum execution time: 269_667_000 picoseconds. + Weight::from_parts(284_662_802, 9350) + // Standard Error: 691 + .saturating_add(Weight::from_parts(799_249, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 14).saturating_mul(r.into())) } @@ -2784,6 +2932,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2797,13 +2947,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_input(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `865 + r * (6 ±0)` - // Estimated: `6807 + r * (6 ±0)` - // Minimum execution time: 251_158_000 picoseconds. - Weight::from_parts(274_623_152, 6807) - // Standard Error: 491 - .saturating_add(Weight::from_parts(263_916, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `868 + r * (6 ±0)` + // Estimated: `9285 + r * (6 ±0)` + // Minimum execution time: 267_018_000 picoseconds. + Weight::from_parts(281_842_630, 9285) + // Standard Error: 453 + .saturating_add(Weight::from_parts(255_373, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) } @@ -2811,6 +2961,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2824,19 +2976,21 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_input_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `869` - // Estimated: `6809` - // Minimum execution time: 263_205_000 picoseconds. - Weight::from_parts(216_792_893, 6809) + // Measured: `872` + // Estimated: `9287` + // Minimum execution time: 258_208_000 picoseconds. + Weight::from_parts(227_686_792, 9287) // Standard Error: 23 .saturating_add(Weight::from_parts(989, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2850,11 +3004,11 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1]`. fn seal_return(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `853 + r * (45 ±0)` - // Estimated: `6793 + r * (45 ±0)` - // Minimum execution time: 239_663_000 picoseconds. - Weight::from_parts(266_124_565, 6793) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `856 + r * (45 ±0)` + // Estimated: `9271 + r * (45 ±0)` + // Minimum execution time: 245_714_000 picoseconds. + Weight::from_parts(272_527_059, 9271) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 45).saturating_mul(r.into())) } @@ -2862,6 +3016,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2875,19 +3031,21 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_return_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863` - // Estimated: `6810` - // Minimum execution time: 241_763_000 picoseconds. - Weight::from_parts(266_535_552, 6810) + // Measured: `866` + // Estimated: `9288` + // Minimum execution time: 256_060_000 picoseconds. + Weight::from_parts(276_710_811, 9288) // Standard Error: 0 - .saturating_add(Weight::from_parts(320, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(312, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:2) @@ -2901,28 +3059,30 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `Contracts::DeletionQueue` (r:0 w:1) /// Proof: `Contracts::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) /// The range of component `r` is `[0, 1]`. fn seal_terminate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2972 + r * (316 ±0)` - // Estimated: `8912 + r * (5266 ±0)` - // Minimum execution time: 265_888_000 picoseconds. - Weight::from_parts(291_232_232, 8912) - // Standard Error: 845_475 - .saturating_add(Weight::from_parts(104_398_867, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(r.into()))) + // Measured: `2902 + r * (529 ±0)` + // Estimated: `11317 + r * (5479 ±0)` + // Minimum execution time: 270_479_000 picoseconds. + Weight::from_parts(296_706_989, 11317) + // Standard Error: 813_407 + .saturating_add(Weight::from_parts(109_236_910, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((10_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 5266).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 5479).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2938,13 +3098,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_random(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `944 + r * (10 ±0)` - // Estimated: `6885 + r * (10 ±0)` - // Minimum execution time: 248_500_000 picoseconds. - Weight::from_parts(282_353_053, 6885) - // Standard Error: 1_144 - .saturating_add(Weight::from_parts(1_193_841, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `947 + r * (10 ±0)` + // Estimated: `9363 + r * (10 ±0)` + // Minimum execution time: 251_787_000 picoseconds. + Weight::from_parts(284_036_313, 9363) + // Standard Error: 2_560 + .saturating_add(Weight::from_parts(1_238_301, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) } @@ -2952,6 +3112,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2965,13 +3127,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_deposit_event(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (10 ±0)` - // Estimated: `6805 + r * (10 ±0)` - // Minimum execution time: 248_130_000 picoseconds. - Weight::from_parts(279_583_178, 6805) - // Standard Error: 971 - .saturating_add(Weight::from_parts(1_987_941, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `866 + r * (10 ±0)` + // Estimated: `9283 + r * (10 ±0)` + // Minimum execution time: 250_566_000 picoseconds. + Weight::from_parts(275_402_784, 9283) + // Standard Error: 3_939 + .saturating_add(Weight::from_parts(1_941_995, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) } @@ -2979,6 +3141,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2993,15 +3157,15 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_deposit_event_per_topic_and_byte(t: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `880 + t * (32 ±0)` - // Estimated: `6825 + t * (2508 ±0)` - // Minimum execution time: 258_594_000 picoseconds. - Weight::from_parts(276_734_422, 6825) - // Standard Error: 102_093 - .saturating_add(Weight::from_parts(2_559_383, 0).saturating_mul(t.into())) + // Measured: `883 + t * (32 ±0)` + // Estimated: `9303 + t * (2508 ±0)` + // Minimum execution time: 267_544_000 picoseconds. + Weight::from_parts(280_117_825, 9303) + // Standard Error: 102_111 + .saturating_add(Weight::from_parts(3_253_038, 0).saturating_mul(t.into())) // Standard Error: 28 - .saturating_add(Weight::from_parts(501, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(668, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(t.into()))) @@ -3011,6 +3175,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3024,13 +3190,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_debug_message(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `862 + r * (7 ±0)` - // Estimated: `6807 + r * (7 ±0)` - // Minimum execution time: 154_564_000 picoseconds. - Weight::from_parts(168_931_365, 6807) - // Standard Error: 349 - .saturating_add(Weight::from_parts(226_848, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `865 + r * (7 ±0)` + // Estimated: `9285 + r * (7 ±0)` + // Minimum execution time: 157_769_000 picoseconds. + Weight::from_parts(173_026_565, 9285) + // Standard Error: 405 + .saturating_add(Weight::from_parts(219_727, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) } @@ -3038,6 +3204,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3051,13 +3219,13 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 1048576]`. fn seal_debug_message_per_byte(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `125813` - // Estimated: `131755` - // Minimum execution time: 394_382_000 picoseconds. - Weight::from_parts(376_780_500, 131755) + // Measured: `125816` + // Estimated: `131758` + // Minimum execution time: 403_961_000 picoseconds. + Weight::from_parts(376_480_872, 131758) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_026, 0).saturating_mul(i.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(1_041, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -3065,13 +3233,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_set_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `924 + r * (292 ±0)` - // Estimated: `926 + r * (293 ±0)` - // Minimum execution time: 249_757_000 picoseconds. - Weight::from_parts(177_324_374, 926) - // Standard Error: 9_512 - .saturating_add(Weight::from_parts(6_176_717, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `927 + r * (292 ±0)` + // Estimated: `929 + r * (293 ±0)` + // Minimum execution time: 256_272_000 picoseconds. + Weight::from_parts(181_058_379, 929) + // Standard Error: 9_838 + .saturating_add(Weight::from_parts(6_316_677, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -3082,13 +3250,13 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_set_storage_per_new_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1447` - // Estimated: `1430` - // Minimum execution time: 267_564_000 picoseconds. - Weight::from_parts(328_701_080, 1430) - // Standard Error: 61 - .saturating_add(Weight::from_parts(576, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(12_u64)) + // Measured: `1450` + // Estimated: `1433` + // Minimum execution time: 268_713_000 picoseconds. + Weight::from_parts(328_329_131, 1433) + // Standard Error: 66 + .saturating_add(Weight::from_parts(962, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(15_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -3096,13 +3264,13 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_set_storage_per_old_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1253 + n * (1 ±0)` - // Estimated: `1253 + n * (1 ±0)` - // Minimum execution time: 266_347_000 picoseconds. - Weight::from_parts(289_824_718, 1253) - // Standard Error: 34 - .saturating_add(Weight::from_parts(184, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `1256 + n * (1 ±0)` + // Estimated: `1256 + n * (1 ±0)` + // Minimum execution time: 265_683_000 picoseconds. + Weight::from_parts(293_784_477, 1256) + // Standard Error: 31 + .saturating_add(Weight::from_parts(377, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -3111,13 +3279,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_clear_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `921 + r * (288 ±0)` - // Estimated: `927 + r * (289 ±0)` - // Minimum execution time: 247_207_000 picoseconds. - Weight::from_parts(179_856_075, 927) - // Standard Error: 9_383 - .saturating_add(Weight::from_parts(6_053_198, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `924 + r * (288 ±0)` + // Estimated: `930 + r * (289 ±0)` + // Minimum execution time: 269_959_000 picoseconds. + Weight::from_parts(186_065_911, 930) + // Standard Error: 9_679 + .saturating_add(Weight::from_parts(6_286_855, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -3128,13 +3296,11 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_clear_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1249 + n * (1 ±0)` - // Estimated: `1249 + n * (1 ±0)` - // Minimum execution time: 262_655_000 picoseconds. - Weight::from_parts(289_482_543, 1249) - // Standard Error: 35 - .saturating_add(Weight::from_parts(92, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `1252 + n * (1 ±0)` + // Estimated: `1252 + n * (1 ±0)` + // Minimum execution time: 265_805_000 picoseconds. + Weight::from_parts(294_633_695, 1252) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -3143,13 +3309,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_get_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `921 + r * (296 ±0)` - // Estimated: `923 + r * (297 ±0)` - // Minimum execution time: 247_414_000 picoseconds. - Weight::from_parts(203_317_182, 923) - // Standard Error: 7_191 - .saturating_add(Weight::from_parts(4_925_154, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `924 + r * (296 ±0)` + // Estimated: `926 + r * (297 ±0)` + // Minimum execution time: 264_592_000 picoseconds. + Weight::from_parts(204_670_461, 926) + // Standard Error: 6_869 + .saturating_add(Weight::from_parts(5_137_920, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 297).saturating_mul(r.into())) @@ -3159,13 +3325,13 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_get_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1265 + n * (1 ±0)` - // Estimated: `1265 + n * (1 ±0)` - // Minimum execution time: 258_910_000 picoseconds. - Weight::from_parts(283_086_514, 1265) - // Standard Error: 39 - .saturating_add(Weight::from_parts(980, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `1268 + n * (1 ±0)` + // Estimated: `1268 + n * (1 ±0)` + // Minimum execution time: 273_165_000 picoseconds. + Weight::from_parts(297_883_669, 1268) + // Standard Error: 37 + .saturating_add(Weight::from_parts(576, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -3174,13 +3340,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_contains_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `932 + r * (288 ±0)` - // Estimated: `929 + r * (289 ±0)` - // Minimum execution time: 252_410_000 picoseconds. - Weight::from_parts(201_227_879, 929) - // Standard Error: 6_899 - .saturating_add(Weight::from_parts(4_774_983, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `935 + r * (288 ±0)` + // Estimated: `932 + r * (289 ±0)` + // Minimum execution time: 252_257_000 picoseconds. + Weight::from_parts(205_018_595, 932) + // Standard Error: 7_605 + .saturating_add(Weight::from_parts(4_933_378, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 289).saturating_mul(r.into())) @@ -3190,13 +3356,13 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_contains_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1252 + n * (1 ±0)` - // Estimated: `1252 + n * (1 ±0)` - // Minimum execution time: 259_053_000 picoseconds. - Weight::from_parts(283_392_084, 1252) - // Standard Error: 41 - .saturating_add(Weight::from_parts(213, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `1255 + n * (1 ±0)` + // Estimated: `1255 + n * (1 ±0)` + // Minimum execution time: 266_839_000 picoseconds. + Weight::from_parts(292_064_487, 1255) + // Standard Error: 34 + .saturating_add(Weight::from_parts(194, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -3205,13 +3371,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_take_storage(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `914 + r * (296 ±0)` - // Estimated: `919 + r * (297 ±0)` - // Minimum execution time: 251_371_000 picoseconds. - Weight::from_parts(177_119_717, 919) - // Standard Error: 9_421 - .saturating_add(Weight::from_parts(6_226_005, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `917 + r * (296 ±0)` + // Estimated: `922 + r * (297 ±0)` + // Minimum execution time: 266_072_000 picoseconds. + Weight::from_parts(189_018_352, 922) + // Standard Error: 9_530 + .saturating_add(Weight::from_parts(6_481_011, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -3222,13 +3388,13 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 16384]`. fn seal_take_storage_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1266 + n * (1 ±0)` - // Estimated: `1266 + n * (1 ±0)` - // Minimum execution time: 263_350_000 picoseconds. - Weight::from_parts(284_323_917, 1266) - // Standard Error: 31 - .saturating_add(Weight::from_parts(921, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `1269 + n * (1 ±0)` + // Estimated: `1269 + n * (1 ±0)` + // Minimum execution time: 270_703_000 picoseconds. + Weight::from_parts(292_867_105, 1269) + // Standard Error: 30 + .saturating_add(Weight::from_parts(800, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -3236,6 +3402,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1602 w:1601) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3249,13 +3417,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_transfer(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1415 + r * (45 ±0)` - // Estimated: `7307 + r * (2520 ±0)` - // Minimum execution time: 248_701_000 picoseconds. - Weight::from_parts(17_811_969, 7307) - // Standard Error: 35_154 - .saturating_add(Weight::from_parts(31_809_738, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `1418 + r * (45 ±0)` + // Estimated: `9785 + r * (2520 ±0)` + // Minimum execution time: 251_843_000 picoseconds. + Weight::from_parts(181_026_888, 9785) + // Standard Error: 38_221 + .saturating_add(Weight::from_parts(30_626_681, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -3265,6 +3433,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -3278,13 +3448,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 800]`. fn seal_call(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1260 + r * (245 ±0)` - // Estimated: `9440 + r * (2721 ±0)` - // Minimum execution time: 247_335_000 picoseconds. - Weight::from_parts(264_025_000, 9440) - // Standard Error: 121_299 - .saturating_add(Weight::from_parts(234_770_827, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) + // Measured: `1263 + r * (245 ±0)` + // Estimated: `9635 + r * (2721 ±0)` + // Minimum execution time: 254_881_000 picoseconds. + Weight::from_parts(272_871_000, 9635) + // Standard Error: 94_527 + .saturating_add(Weight::from_parts(233_379_497, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(r.into()))) @@ -3294,6 +3464,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:736 w:0) @@ -3308,12 +3480,12 @@ impl WeightInfo for () { fn seal_delegate_call(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (576 ±0)` - // Estimated: `6812 + r * (2637 ±3)` - // Minimum execution time: 261_011_000 picoseconds. - Weight::from_parts(264_554_000, 6812) - // Standard Error: 104_415 - .saturating_add(Weight::from_parts(231_627_084, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Estimated: `9290 + r * (2637 ±3)` + // Minimum execution time: 266_704_000 picoseconds. + Weight::from_parts(273_165_000, 9290) + // Standard Error: 141_486 + .saturating_add(Weight::from_parts(232_947_049, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -3323,6 +3495,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -3337,15 +3511,15 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 1048576]`. fn seal_call_per_transfer_clone_byte(t: u32, c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1307 + t * (277 ±0)` - // Estimated: `12197 + t * (5227 ±0)` - // Minimum execution time: 445_561_000 picoseconds. - Weight::from_parts(62_287_490, 12197) - // Standard Error: 11_797_697 - .saturating_add(Weight::from_parts(357_530_529, 0).saturating_mul(t.into())) + // Measured: `1310 + t * (277 ±0)` + // Estimated: `12200 + t * (5227 ±0)` + // Minimum execution time: 446_451_000 picoseconds. + Weight::from_parts(68_175_222, 12200) + // Standard Error: 11_619_250 + .saturating_add(Weight::from_parts(354_237_260, 0).saturating_mul(t.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(970, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(13_u64)) + .saturating_add(Weight::from_parts(987, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(16_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(t.into()))) @@ -3355,6 +3529,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:802 w:802) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:801 w:800) @@ -3368,17 +3544,17 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:803 w:803) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:800 w:800) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `r` is `[1, 800]`. fn seal_instantiate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1278 + r * (255 ±0)` - // Estimated: `9620 + r * (2731 ±0)` - // Minimum execution time: 621_897_000 picoseconds. - Weight::from_parts(631_687_000, 9620) - // Standard Error: 215_241 - .saturating_add(Weight::from_parts(350_527_831, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) + // Measured: `1281 + r * (255 ±0)` + // Estimated: `9623 + r * (2731 ±0)` + // Minimum execution time: 628_156_000 picoseconds. + Weight::from_parts(642_052_000, 9623) + // Standard Error: 223_957 + .saturating_add(Weight::from_parts(348_660_264, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().reads((6_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(7_u64)) .saturating_add(RocksDbWeight::get().writes((5_u64).saturating_mul(r.into()))) @@ -3388,6 +3564,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:1) @@ -3401,23 +3579,23 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. fn seal_instantiate_per_transfer_input_salt_byte(t: u32, i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1303 + t * (104 ±0)` - // Estimated: `12211 + t * (2549 ±1)` - // Minimum execution time: 2_181_184_000 picoseconds. - Weight::from_parts(1_194_190_111, 12211) - // Standard Error: 11_578_766 - .saturating_add(Weight::from_parts(6_361_884, 0).saturating_mul(t.into())) - // Standard Error: 18 - .saturating_add(Weight::from_parts(1_025, 0).saturating_mul(i.into())) - // Standard Error: 18 - .saturating_add(Weight::from_parts(1_158, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(16_u64)) + // Measured: `1306 + t * (104 ±0)` + // Estimated: `12214 + t * (2549 ±1)` + // Minimum execution time: 2_106_379_000 picoseconds. + Weight::from_parts(1_098_227_098, 12214) + // Standard Error: 12_549_729 + .saturating_add(Weight::from_parts(21_628_382, 0).saturating_mul(t.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_059, 0).saturating_mul(i.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_220, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(19_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(11_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(t.into()))) @@ -3427,6 +3605,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3440,13 +3620,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_hash_sha2_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `862 + r * (8 ±0)` - // Estimated: `6801 + r * (8 ±0)` - // Minimum execution time: 241_609_000 picoseconds. - Weight::from_parts(268_716_874, 6801) - // Standard Error: 617 - .saturating_add(Weight::from_parts(377_753, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `865 + r * (8 ±0)` + // Estimated: `9279 + r * (8 ±0)` + // Minimum execution time: 257_102_000 picoseconds. + Weight::from_parts(278_920_692, 9279) + // Standard Error: 464 + .saturating_add(Weight::from_parts(374_120, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) } @@ -3454,6 +3634,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3467,19 +3649,21 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_sha2_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `870` - // Estimated: `6808` - // Minimum execution time: 261_296_000 picoseconds. - Weight::from_parts(255_531_654, 6808) + // Measured: `873` + // Estimated: `9286` + // Minimum execution time: 266_609_000 picoseconds. + Weight::from_parts(263_034_132, 9286) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_081, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(1_082, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3493,13 +3677,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_hash_keccak_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `864 + r * (8 ±0)` - // Estimated: `6806 + r * (8 ±0)` - // Minimum execution time: 243_583_000 picoseconds. - Weight::from_parts(270_025_058, 6806) - // Standard Error: 560 - .saturating_add(Weight::from_parts(767_519, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `867 + r * (8 ±0)` + // Estimated: `9284 + r * (8 ±0)` + // Minimum execution time: 246_275_000 picoseconds. + Weight::from_parts(279_091_594, 9284) + // Standard Error: 887 + .saturating_add(Weight::from_parts(810_394, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) } @@ -3507,6 +3691,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3520,19 +3706,21 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `872` - // Estimated: `6814` - // Minimum execution time: 253_798_000 picoseconds. - Weight::from_parts(265_542_351, 6814) + // Measured: `875` + // Estimated: `9292` + // Minimum execution time: 249_254_000 picoseconds. + Weight::from_parts(270_833_823, 9292) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_343, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(3_347, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3546,13 +3734,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_hash_blake2_256(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `864 + r * (8 ±0)` - // Estimated: `6808 + r * (8 ±0)` - // Minimum execution time: 247_332_000 picoseconds. - Weight::from_parts(269_183_656, 6808) - // Standard Error: 665 - .saturating_add(Weight::from_parts(443_386, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `867 + r * (8 ±0)` + // Estimated: `9286 + r * (8 ±0)` + // Minimum execution time: 259_131_000 picoseconds. + Weight::from_parts(272_665_020, 9286) + // Standard Error: 862 + .saturating_add(Weight::from_parts(451_247, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) } @@ -3560,6 +3748,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3573,19 +3763,21 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_256_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `872` - // Estimated: `6813` - // Minimum execution time: 250_855_000 picoseconds. - Weight::from_parts(258_752_975, 6813) + // Measured: `875` + // Estimated: `9291` + // Minimum execution time: 276_465_000 picoseconds. + Weight::from_parts(269_450_297, 9291) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_202, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(Weight::from_parts(1_190, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3599,13 +3791,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_hash_blake2_128(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `864 + r * (8 ±0)` - // Estimated: `6805 + r * (8 ±0)` - // Minimum execution time: 240_733_000 picoseconds. - Weight::from_parts(269_134_358, 6805) - // Standard Error: 512 - .saturating_add(Weight::from_parts(440_043, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `867 + r * (8 ±0)` + // Estimated: `9283 + r * (8 ±0)` + // Minimum execution time: 248_349_000 picoseconds. + Weight::from_parts(273_660_686, 9283) + // Standard Error: 656 + .saturating_add(Weight::from_parts(444_293, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) } @@ -3613,6 +3805,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3626,19 +3820,21 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1048576]`. fn seal_hash_blake2_128_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `872` - // Estimated: `6811` - // Minimum execution time: 247_377_000 picoseconds. - Weight::from_parts(261_077_322, 6811) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1_195, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `875` + // Estimated: `9289` + // Minimum execution time: 252_107_000 picoseconds. + Weight::from_parts(267_427_726, 9289) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_199, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3652,13 +3848,13 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 125697]`. fn seal_sr25519_verify_per_byte(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `997 + n * (1 ±0)` - // Estimated: `6934 + n * (1 ±0)` - // Minimum execution time: 307_337_000 picoseconds. - Weight::from_parts(326_710_473, 6934) - // Standard Error: 9 - .saturating_add(Weight::from_parts(5_765, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `1000 + n * (1 ±0)` + // Estimated: `9412 + n * (1 ±0)` + // Minimum execution time: 311_252_000 picoseconds. + Weight::from_parts(333_250_773, 9412) + // Standard Error: 12 + .saturating_add(Weight::from_parts(5_668, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -3666,6 +3862,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3679,13 +3877,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 160]`. fn seal_sr25519_verify(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `805 + r * (112 ±0)` - // Estimated: `6748 + r * (112 ±0)` - // Minimum execution time: 245_432_000 picoseconds. - Weight::from_parts(294_206_377, 6748) - // Standard Error: 7_229 - .saturating_add(Weight::from_parts(41_480_485, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `810 + r * (112 ±0)` + // Estimated: `9226 + r * (112 ±0)` + // Minimum execution time: 267_431_000 picoseconds. + Weight::from_parts(300_733_048, 9226) + // Standard Error: 8_806 + .saturating_add(Weight::from_parts(42_169_197, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(r.into())) } @@ -3693,6 +3891,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3706,13 +3906,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 160]`. fn seal_ecdsa_recover(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `907 + r * (76 ±0)` - // Estimated: `6802 + r * (77 ±0)` - // Minimum execution time: 247_788_000 picoseconds. - Weight::from_parts(303_940_062, 6802) - // Standard Error: 10_671 - .saturating_add(Weight::from_parts(45_730_772, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `910 + r * (76 ±0)` + // Estimated: `9279 + r * (77 ±0)` + // Minimum execution time: 265_905_000 picoseconds. + Weight::from_parts(305_381_951, 9279) + // Standard Error: 9_863 + .saturating_add(Weight::from_parts(45_771_182, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 77).saturating_mul(r.into())) } @@ -3720,6 +3920,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3733,13 +3935,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 160]`. fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `877 + r * (42 ±0)` - // Estimated: `6816 + r * (42 ±0)` - // Minimum execution time: 248_825_000 picoseconds. - Weight::from_parts(286_832_225, 6816) - // Standard Error: 5_274 - .saturating_add(Weight::from_parts(11_889_262, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `880 + r * (42 ±0)` + // Estimated: `9294 + r * (42 ±0)` + // Minimum execution time: 266_701_000 picoseconds. + Weight::from_parts(292_407_888, 9294) + // Standard Error: 5_394 + .saturating_add(Weight::from_parts(11_896_065, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(r.into())) } @@ -3747,6 +3949,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536) @@ -3761,12 +3965,12 @@ impl WeightInfo for () { fn seal_set_code_hash(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (965 ±0)` - // Estimated: `6807 + r * (3090 ±7)` - // Minimum execution time: 244_982_000 picoseconds. - Weight::from_parts(265_297_000, 6807) - // Standard Error: 39_895 - .saturating_add(Weight::from_parts(22_435_888, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Estimated: `9285 + r * (3090 ±7)` + // Minimum execution time: 268_755_000 picoseconds. + Weight::from_parts(272_300_000, 9285) + // Standard Error: 43_747 + .saturating_add(Weight::from_parts(25_001_889, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(r.into()))) @@ -3776,6 +3980,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -3789,22 +3995,24 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 32]`. fn lock_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `928 + r * (131 ±0)` - // Estimated: `6878 + r * (2606 ±0)` - // Minimum execution time: 246_455_000 picoseconds. - Weight::from_parts(275_334_919, 6878) - // Standard Error: 20_911 - .saturating_add(Weight::from_parts(6_427_525, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `937 + r * (131 ±0)` + // Estimated: `9346 + r * (2607 ±0)` + // Minimum execution time: 255_190_000 picoseconds. + Weight::from_parts(285_643_922, 9346) + // Standard Error: 23_582 + .saturating_add(Weight::from_parts(6_289_940, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2606).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 2607).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -3818,13 +4026,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 32]`. fn unlock_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `969 + r * (183 ±0)` + // Measured: `972 + r * (184 ±0)` // Estimated: `129453 + r * (2568 ±0)` - // Minimum execution time: 254_472_000 picoseconds. - Weight::from_parts(280_657_909, 129453) - // Standard Error: 20_131 - .saturating_add(Weight::from_parts(5_644_006, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Minimum execution time: 260_061_000 picoseconds. + Weight::from_parts(286_849_343, 129453) + // Standard Error: 22_406 + .saturating_add(Weight::from_parts(5_661_459, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) @@ -3834,6 +4042,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3847,13 +4057,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_reentrance_count(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `858 + r * (3 ±0)` - // Estimated: `6804 + r * (3 ±0)` - // Minimum execution time: 250_535_000 picoseconds. - Weight::from_parts(270_318_376, 6804) - // Standard Error: 386 - .saturating_add(Weight::from_parts(174_627, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `861 + r * (3 ±0)` + // Estimated: `9282 + r * (3 ±0)` + // Minimum execution time: 250_922_000 picoseconds. + Weight::from_parts(277_294_913, 9282) + // Standard Error: 391 + .saturating_add(Weight::from_parts(169_457, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } @@ -3861,6 +4071,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3874,13 +4086,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_account_reentrance_count(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2109 + r * (39 ±0)` - // Estimated: `7899 + r * (40 ±0)` - // Minimum execution time: 248_174_000 picoseconds. - Weight::from_parts(301_826_520, 7899) - // Standard Error: 801 - .saturating_add(Weight::from_parts(248_479, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `2112 + r * (39 ±0)` + // Estimated: `10377 + r * (40 ±0)` + // Minimum execution time: 267_293_000 picoseconds. + Weight::from_parts(309_125_635, 10377) + // Standard Error: 637 + .saturating_add(Weight::from_parts(245_508, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 40).saturating_mul(r.into())) } @@ -3888,6 +4100,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3903,13 +4117,13 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 1600]`. fn seal_instantiation_nonce(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `861 + r * (3 ±0)` - // Estimated: `6801 + r * (3 ±0)` - // Minimum execution time: 246_540_000 picoseconds. - Weight::from_parts(268_913_509, 6801) - // Standard Error: 378 - .saturating_add(Weight::from_parts(154_950, 0).saturating_mul(r.into())) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Measured: `864 + r * (3 ±0)` + // Estimated: `9279 + r * (3 ±0)` + // Minimum execution time: 256_057_000 picoseconds. + Weight::from_parts(278_068_870, 9279) + // Standard Error: 335 + .saturating_add(Weight::from_parts(152_083, 0).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } @@ -3918,9 +4132,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_777_000 picoseconds. - Weight::from_parts(1_707_601, 0) - // Standard Error: 14 - .saturating_add(Weight::from_parts(15_392, 0).saturating_mul(r.into())) + // Minimum execution time: 1_846_000 picoseconds. + Weight::from_parts(1_808_029, 0) + // Standard Error: 9 + .saturating_add(Weight::from_parts(14_937, 0).saturating_mul(r.into())) } } diff --git a/substrate/frame/conviction-voting/src/weights.rs b/substrate/frame/conviction-voting/src/weights.rs index 225f5c2cadd..75d9e8499ed 100644 --- a/substrate/frame/conviction-voting/src/weights.rs +++ b/substrate/frame/conviction-voting/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_conviction_voting +//! Autogenerated weights for `pallet_conviction_voting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/conviction-voting/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/conviction-voting/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_conviction_voting. +/// Weight functions needed for `pallet_conviction_voting`. pub trait WeightInfo { fn vote_new() -> Weight; fn vote_existing() -> Weight; @@ -61,280 +60,300 @@ pub trait WeightInfo { fn unlock() -> Weight; } -/// Weights for pallet_conviction_voting using the Substrate node and recommended hardware. +/// Weights for `pallet_conviction_voting` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `13074` + // Measured: `13141` // Estimated: `219984` - // Minimum execution time: 112_936_000 picoseconds. - Weight::from_parts(116_972_000, 219984) + // Minimum execution time: 102_539_000 picoseconds. + Weight::from_parts(105_873_000, 219984) .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `20216` + // Measured: `20283` // Estimated: `219984` - // Minimum execution time: 291_971_000 picoseconds. - Weight::from_parts(301_738_000, 219984) + // Minimum execution time: 275_424_000 picoseconds. + Weight::from_parts(283_690_000, 219984) .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn remove_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `19968` + // Measured: `20035` // Estimated: `219984` - // Minimum execution time: 262_582_000 picoseconds. - Weight::from_parts(270_955_000, 219984) + // Minimum execution time: 275_109_000 picoseconds. + Weight::from_parts(281_315_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn remove_other_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `12675` + // Measured: `12742` // Estimated: `30706` - // Minimum execution time: 52_909_000 picoseconds. - Weight::from_parts(56_365_000, 30706) + // Minimum execution time: 49_629_000 picoseconds. + Weight::from_parts(51_300_000, 30706) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: ConvictionVoting VotingFor (r:2 w:2) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 1]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `240 + r * (1627 ±0)` + // Measured: `306 + r * (1628 ±0)` // Estimated: `109992 + r * (109992 ±0)` - // Minimum execution time: 54_640_000 picoseconds. - Weight::from_parts(57_185_281, 109992) - // Standard Error: 193_362 - .saturating_add(Weight::from_parts(44_897_418, 0).saturating_mul(r.into())) + // Minimum execution time: 45_776_000 picoseconds. + Weight::from_parts(47_917_822, 109992) + // Standard Error: 124_174 + .saturating_add(Weight::from_parts(43_171_077, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 109992).saturating_mul(r.into())) } - /// Storage: ConvictionVoting VotingFor (r:2 w:2) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 1]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `406 + r * (1376 ±0)` + // Measured: `472 + r * (1377 ±0)` // Estimated: `109992 + r * (109992 ±0)` - // Minimum execution time: 26_514_000 picoseconds. - Weight::from_parts(28_083_732, 109992) - // Standard Error: 104_905 - .saturating_add(Weight::from_parts(40_722_467, 0).saturating_mul(r.into())) + // Minimum execution time: 23_600_000 picoseconds. + Weight::from_parts(25_001_426, 109992) + // Standard Error: 72_034 + .saturating_add(Weight::from_parts(37_851_873, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 109992).saturating_mul(r.into())) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn unlock() -> Weight { // Proof Size summary in bytes: - // Measured: `11734` + // Measured: `11800` // Estimated: `30706` - // Minimum execution time: 71_140_000 picoseconds. - Weight::from_parts(77_388_000, 30706) + // Minimum execution time: 66_247_000 picoseconds. + Weight::from_parts(67_552_000, 30706) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `13074` + // Measured: `13141` // Estimated: `219984` - // Minimum execution time: 112_936_000 picoseconds. - Weight::from_parts(116_972_000, 219984) + // Minimum execution time: 102_539_000 picoseconds. + Weight::from_parts(105_873_000, 219984) .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `20216` + // Measured: `20283` // Estimated: `219984` - // Minimum execution time: 291_971_000 picoseconds. - Weight::from_parts(301_738_000, 219984) + // Minimum execution time: 275_424_000 picoseconds. + Weight::from_parts(283_690_000, 219984) .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn remove_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `19968` + // Measured: `20035` // Estimated: `219984` - // Minimum execution time: 262_582_000 picoseconds. - Weight::from_parts(270_955_000, 219984) + // Minimum execution time: 275_109_000 picoseconds. + Weight::from_parts(281_315_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn remove_other_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `12675` + // Measured: `12742` // Estimated: `30706` - // Minimum execution time: 52_909_000 picoseconds. - Weight::from_parts(56_365_000, 30706) + // Minimum execution time: 49_629_000 picoseconds. + Weight::from_parts(51_300_000, 30706) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: ConvictionVoting VotingFor (r:2 w:2) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 1]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `240 + r * (1627 ±0)` + // Measured: `306 + r * (1628 ±0)` // Estimated: `109992 + r * (109992 ±0)` - // Minimum execution time: 54_640_000 picoseconds. - Weight::from_parts(57_185_281, 109992) - // Standard Error: 193_362 - .saturating_add(Weight::from_parts(44_897_418, 0).saturating_mul(r.into())) + // Minimum execution time: 45_776_000 picoseconds. + Weight::from_parts(47_917_822, 109992) + // Standard Error: 124_174 + .saturating_add(Weight::from_parts(43_171_077, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(r.into()))) + .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 109992).saturating_mul(r.into())) } - /// Storage: ConvictionVoting VotingFor (r:2 w:2) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 1]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `406 + r * (1376 ±0)` + // Measured: `472 + r * (1377 ±0)` // Estimated: `109992 + r * (109992 ±0)` - // Minimum execution time: 26_514_000 picoseconds. - Weight::from_parts(28_083_732, 109992) - // Standard Error: 104_905 - .saturating_add(Weight::from_parts(40_722_467, 0).saturating_mul(r.into())) + // Minimum execution time: 23_600_000 picoseconds. + Weight::from_parts(25_001_426, 109992) + // Standard Error: 72_034 + .saturating_add(Weight::from_parts(37_851_873, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(r.into()))) + .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 109992).saturating_mul(r.into())) } - /// Storage: ConvictionVoting VotingFor (r:1 w:1) - /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) - /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) - /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) + /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) + /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) + /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn unlock() -> Weight { // Proof Size summary in bytes: - // Measured: `11734` + // Measured: `11800` // Estimated: `30706` - // Minimum execution time: 71_140_000 picoseconds. - Weight::from_parts(77_388_000, 30706) + // Minimum execution time: 66_247_000 picoseconds. + Weight::from_parts(67_552_000, 30706) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/substrate/frame/core-fellowship/src/weights.rs b/substrate/frame/core-fellowship/src/weights.rs index 8bbfd1a4dd8..fce1d3747a8 100644 --- a/substrate/frame/core-fellowship/src/weights.rs +++ b/substrate/frame/core-fellowship/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_core_fellowship +//! Autogenerated weights for `pallet_core_fellowship` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/core-fellowship/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/core-fellowship/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_core_fellowship. +/// Weight functions needed for `pallet_core_fellowship`. pub trait WeightInfo { fn set_params() -> Weight; fn bump_offboard() -> Weight; @@ -64,336 +63,344 @@ pub trait WeightInfo { fn submit_evidence() -> Weight; } -/// Weights for pallet_core_fellowship using the Substrate node and recommended hardware. +/// Weights for `pallet_core_fellowship` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: CoreFellowship Params (r:0 w:1) - /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Params` (r:0 w:1) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) fn set_params() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_454_000 picoseconds. - Weight::from_parts(9_804_000, 0) + // Minimum execution time: 7_146_000 picoseconds. + Weight::from_parts(7_426_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Params (r:1 w:0) - /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:1 w:0) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Params` (r:1 w:0) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn bump_offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `16887` + // Measured: `17274` // Estimated: `19894` - // Minimum execution time: 58_489_000 picoseconds. - Weight::from_parts(60_202_000, 19894) + // Minimum execution time: 54_511_000 picoseconds. + Weight::from_parts(56_995_000, 19894) .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Params (r:1 w:0) - /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:1 w:0) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Params` (r:1 w:0) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn bump_demote() -> Weight { // Proof Size summary in bytes: - // Measured: `16997` + // Measured: `17384` // Estimated: `19894` - // Minimum execution time: 60_605_000 picoseconds. - Weight::from_parts(63_957_000, 19894) + // Minimum execution time: 56_453_000 picoseconds. + Weight::from_parts(59_030_000, 19894) .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) fn set_active() -> Weight { // Proof Size summary in bytes: // Measured: `388` // Estimated: `3514` - // Minimum execution time: 17_816_000 picoseconds. - Weight::from_parts(18_524_000, 3514) + // Minimum execution time: 15_940_000 picoseconds. + Weight::from_parts(16_381_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:0 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:0 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn induct() -> Weight { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3514` - // Minimum execution time: 27_249_000 picoseconds. - Weight::from_parts(28_049_000, 3514) + // Minimum execution time: 24_193_000 picoseconds. + Weight::from_parts(24_963_000, 3514) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: CoreFellowship Params (r:1 w:0) - /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:0 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:0 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Params` (r:1 w:0) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn promote() -> Weight { // Proof Size summary in bytes: // Measured: `16865` // Estimated: `19894` - // Minimum execution time: 56_642_000 picoseconds. - Weight::from_parts(59_353_000, 19894) + // Minimum execution time: 48_138_000 picoseconds. + Weight::from_parts(50_007_000, 19894) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:0 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:0 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) fn offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `359` + // Measured: `293` // Estimated: `3514` - // Minimum execution time: 17_459_000 picoseconds. - Weight::from_parts(18_033_000, 3514) + // Minimum execution time: 15_225_000 picoseconds. + Weight::from_parts(15_730_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) fn import() -> Weight { // Proof Size summary in bytes: // Measured: `313` // Estimated: `3514` - // Minimum execution time: 16_728_000 picoseconds. - Weight::from_parts(17_263_000, 3514) + // Minimum execution time: 14_507_000 picoseconds. + Weight::from_parts(14_935_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) fn approve() -> Weight { // Proof Size summary in bytes: // Measured: `16843` // Estimated: `19894` - // Minimum execution time: 41_487_000 picoseconds. - Weight::from_parts(43_459_000, 19894) + // Minimum execution time: 34_050_000 picoseconds. + Weight::from_parts(36_323_000, 19894) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: CoreFellowship Member (r:1 w:0) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:0) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) fn submit_evidence() -> Weight { // Proof Size summary in bytes: // Measured: `79` // Estimated: `19894` - // Minimum execution time: 26_033_000 picoseconds. - Weight::from_parts(26_612_000, 19894) + // Minimum execution time: 24_016_000 picoseconds. + Weight::from_parts(24_607_000, 19894) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: CoreFellowship Params (r:0 w:1) - /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Params` (r:0 w:1) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) fn set_params() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_454_000 picoseconds. - Weight::from_parts(9_804_000, 0) + // Minimum execution time: 7_146_000 picoseconds. + Weight::from_parts(7_426_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Params (r:1 w:0) - /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:1 w:0) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Params` (r:1 w:0) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn bump_offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `16887` + // Measured: `17274` // Estimated: `19894` - // Minimum execution time: 58_489_000 picoseconds. - Weight::from_parts(60_202_000, 19894) + // Minimum execution time: 54_511_000 picoseconds. + Weight::from_parts(56_995_000, 19894) .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Params (r:1 w:0) - /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:1 w:0) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Params` (r:1 w:0) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn bump_demote() -> Weight { // Proof Size summary in bytes: - // Measured: `16997` + // Measured: `17384` // Estimated: `19894` - // Minimum execution time: 60_605_000 picoseconds. - Weight::from_parts(63_957_000, 19894) + // Minimum execution time: 56_453_000 picoseconds. + Weight::from_parts(59_030_000, 19894) .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) fn set_active() -> Weight { // Proof Size summary in bytes: // Measured: `388` // Estimated: `3514` - // Minimum execution time: 17_816_000 picoseconds. - Weight::from_parts(18_524_000, 3514) + // Minimum execution time: 15_940_000 picoseconds. + Weight::from_parts(16_381_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:0 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:0 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn induct() -> Weight { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3514` - // Minimum execution time: 27_249_000 picoseconds. - Weight::from_parts(28_049_000, 3514) + // Minimum execution time: 24_193_000 picoseconds. + Weight::from_parts(24_963_000, 3514) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: CoreFellowship Params (r:1 w:0) - /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:0 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:0 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Params` (r:1 w:0) + /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn promote() -> Weight { // Proof Size summary in bytes: // Measured: `16865` // Estimated: `19894` - // Minimum execution time: 56_642_000 picoseconds. - Weight::from_parts(59_353_000, 19894) + // Minimum execution time: 48_138_000 picoseconds. + Weight::from_parts(50_007_000, 19894) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:0 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:0 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) fn offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `359` + // Measured: `293` // Estimated: `3514` - // Minimum execution time: 17_459_000 picoseconds. - Weight::from_parts(18_033_000, 3514) + // Minimum execution time: 15_225_000 picoseconds. + Weight::from_parts(15_730_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) fn import() -> Weight { // Proof Size summary in bytes: // Measured: `313` // Estimated: `3514` - // Minimum execution time: 16_728_000 picoseconds. - Weight::from_parts(17_263_000, 3514) + // Minimum execution time: 14_507_000 picoseconds. + Weight::from_parts(14_935_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: CoreFellowship Member (r:1 w:1) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:1 w:1) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) fn approve() -> Weight { // Proof Size summary in bytes: // Measured: `16843` // Estimated: `19894` - // Minimum execution time: 41_487_000 picoseconds. - Weight::from_parts(43_459_000, 19894) + // Minimum execution time: 34_050_000 picoseconds. + Weight::from_parts(36_323_000, 19894) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: CoreFellowship Member (r:1 w:0) - /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: CoreFellowship MemberEvidence (r:1 w:1) - /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: `CoreFellowship::Member` (r:1 w:0) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) fn submit_evidence() -> Weight { // Proof Size summary in bytes: // Measured: `79` // Estimated: `19894` - // Minimum execution time: 26_033_000 picoseconds. - Weight::from_parts(26_612_000, 19894) + // Minimum execution time: 24_016_000 picoseconds. + Weight::from_parts(24_607_000, 19894) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/democracy/src/weights.rs b/substrate/frame/democracy/src/weights.rs index 241f6c3cb38..d6097922a82 100644 --- a/substrate/frame/democracy/src/weights.rs +++ b/substrate/frame/democracy/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_democracy +//! Autogenerated weights for `pallet_democracy` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/democracy/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/democracy/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_democracy. +/// Weight functions needed for `pallet_democracy`. pub trait WeightInfo { fn propose() -> Weight; fn second() -> Weight; @@ -82,904 +81,916 @@ pub trait WeightInfo { fn clear_referendum_metadata() -> Weight; } -/// Weights for pallet_democracy using the Substrate node and recommended hardware. +/// Weights for `pallet_democracy` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Democracy PublicPropCount (r:1 w:1) - /// Proof: Democracy PublicPropCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy PublicProps (r:1 w:1) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy Blacklist (r:1 w:0) - /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) - /// Storage: Democracy DepositOf (r:0 w:1) - /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicPropCount` (r:1 w:1) + /// Proof: `Democracy::PublicPropCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::PublicProps` (r:1 w:1) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Blacklist` (r:1 w:0) + /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) + /// Storage: `Democracy::DepositOf` (r:0 w:1) + /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) fn propose() -> Weight { // Proof Size summary in bytes: - // Measured: `4801` + // Measured: `4834` // Estimated: `18187` - // Minimum execution time: 49_339_000 picoseconds. - Weight::from_parts(50_942_000, 18187) + // Minimum execution time: 39_930_000 picoseconds. + Weight::from_parts(41_746_000, 18187) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Democracy DepositOf (r:1 w:1) - /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) + /// Storage: `Democracy::DepositOf` (r:1 w:1) + /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) fn second() -> Weight { // Proof Size summary in bytes: - // Measured: `3556` + // Measured: `3589` // Estimated: `6695` - // Minimum execution time: 43_291_000 picoseconds. - Weight::from_parts(44_856_000, 6695) + // Minimum execution time: 36_490_000 picoseconds. + Weight::from_parts(37_615_000, 6695) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `3470` + // Measured: `3503` // Estimated: `7260` - // Minimum execution time: 61_890_000 picoseconds. - Weight::from_parts(63_626_000, 7260) + // Minimum execution time: 54_257_000 picoseconds. + Weight::from_parts(55_912_000, 7260) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `3492` + // Measured: `3525` // Estimated: `7260` - // Minimum execution time: 67_802_000 picoseconds. - Weight::from_parts(69_132_000, 7260) + // Minimum execution time: 56_878_000 picoseconds. + Weight::from_parts(58_796_000, 7260) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy Cancellations (r:1 w:1) - /// Proof: Democracy Cancellations (max_values: None, max_size: Some(33), added: 2508, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Cancellations` (r:1 w:1) + /// Proof: `Democracy::Cancellations` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn emergency_cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `366` + // Measured: `399` // Estimated: `3666` - // Minimum execution time: 25_757_000 picoseconds. - Weight::from_parts(27_226_000, 3666) + // Minimum execution time: 22_700_000 picoseconds. + Weight::from_parts(23_539_000, 3666) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Democracy PublicProps (r:1 w:1) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy DepositOf (r:1 w:1) - /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:3 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) - /// Storage: Democracy NextExternal (r:1 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy Blacklist (r:0 w:1) - /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:1 w:1) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::DepositOf` (r:1 w:1) + /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:3 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `Democracy::NextExternal` (r:1 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Blacklist` (r:0 w:1) + /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) fn blacklist() -> Weight { // Proof Size summary in bytes: - // Measured: `5910` + // Measured: `5943` // Estimated: `18187` - // Minimum execution time: 113_060_000 picoseconds. - Weight::from_parts(114_813_000, 18187) + // Minimum execution time: 95_398_000 picoseconds. + Weight::from_parts(97_261_000, 18187) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } - /// Storage: Democracy NextExternal (r:1 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy Blacklist (r:1 w:0) - /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Blacklist` (r:1 w:0) + /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) fn external_propose() -> Weight { // Proof Size summary in bytes: - // Measured: `3416` + // Measured: `3449` // Estimated: `6703` - // Minimum execution time: 13_413_000 picoseconds. - Weight::from_parts(13_794_000, 6703) + // Minimum execution time: 11_745_000 picoseconds. + Weight::from_parts(12_304_000, 6703) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy NextExternal (r:0 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:0 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) fn external_propose_majority() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_213_000 picoseconds. - Weight::from_parts(3_429_000, 0) + // Minimum execution time: 2_710_000 picoseconds. + Weight::from_parts(2_918_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy NextExternal (r:0 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:0 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) fn external_propose_default() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_280_000 picoseconds. - Weight::from_parts(3_389_000, 0) + // Minimum execution time: 2_664_000 picoseconds. + Weight::from_parts(2_776_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy NextExternal (r:1 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumCount (r:1 w:1) - /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:2) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:0 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumCount` (r:1 w:1) + /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:2) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:0 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) fn fast_track() -> Weight { // Proof Size summary in bytes: - // Measured: `286` + // Measured: `319` // Estimated: `3518` - // Minimum execution time: 28_142_000 picoseconds. - Weight::from_parts(28_862_000, 3518) + // Minimum execution time: 22_585_000 picoseconds. + Weight::from_parts(23_689_000, 3518) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Democracy NextExternal (r:1 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy Blacklist (r:1 w:1) - /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Blacklist` (r:1 w:1) + /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn veto_external() -> Weight { // Proof Size summary in bytes: - // Measured: `3519` + // Measured: `3552` // Estimated: `6703` - // Minimum execution time: 32_395_000 picoseconds. - Weight::from_parts(33_617_000, 6703) + // Minimum execution time: 26_391_000 picoseconds. + Weight::from_parts(27_141_000, 6703) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Democracy PublicProps (r:1 w:1) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy DepositOf (r:1 w:1) - /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:1 w:1) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::DepositOf` (r:1 w:1) + /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn cancel_proposal() -> Weight { // Proof Size summary in bytes: - // Measured: `5821` + // Measured: `5854` // Estimated: `18187` - // Minimum execution time: 92_255_000 picoseconds. - Weight::from_parts(93_704_000, 18187) + // Minimum execution time: 77_905_000 picoseconds. + Weight::from_parts(79_628_000, 18187) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:0 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:0 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) fn cancel_referendum() -> Weight { // Proof Size summary in bytes: - // Measured: `271` + // Measured: `304` // Estimated: `3518` - // Minimum execution time: 19_623_000 picoseconds. - Weight::from_parts(20_545_000, 3518) + // Minimum execution time: 15_735_000 picoseconds. + Weight::from_parts(16_525_000, 3518) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Democracy LowestUnbaked (r:1 w:1) - /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumCount (r:1 w:0) - /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:99 w:0) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::LowestUnbaked` (r:1 w:1) + /// Proof: `Democracy::LowestUnbaked` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumCount` (r:1 w:0) + /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:0) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn on_initialize_base(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `244 + r * (86 ±0)` + // Measured: `277 + r * (86 ±0)` // Estimated: `1489 + r * (2676 ±0)` - // Minimum execution time: 7_032_000 picoseconds. - Weight::from_parts(7_931_421, 1489) - // Standard Error: 7_395 - .saturating_add(Weight::from_parts(3_236_964, 0).saturating_mul(r.into())) + // Minimum execution time: 5_274_000 picoseconds. + Weight::from_parts(6_162_399, 1489) + // Standard Error: 6_924 + .saturating_add(Weight::from_parts(3_186_702, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: Democracy LowestUnbaked (r:1 w:1) - /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumCount (r:1 w:0) - /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy LastTabledWasExternal (r:1 w:0) - /// Proof: Democracy LastTabledWasExternal (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: Democracy NextExternal (r:1 w:0) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy PublicProps (r:1 w:0) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:99 w:0) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::LowestUnbaked` (r:1 w:1) + /// Proof: `Democracy::LowestUnbaked` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumCount` (r:1 w:0) + /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::LastTabledWasExternal` (r:1 w:0) + /// Proof: `Democracy::LastTabledWasExternal` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Democracy::NextExternal` (r:1 w:0) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::PublicProps` (r:1 w:0) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:0) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `244 + r * (86 ±0)` + // Measured: `277 + r * (86 ±0)` // Estimated: `18187 + r * (2676 ±0)` - // Minimum execution time: 10_524_000 picoseconds. - Weight::from_parts(10_369_064, 18187) - // Standard Error: 8_385 - .saturating_add(Weight::from_parts(3_242_334, 0).saturating_mul(r.into())) + // Minimum execution time: 7_950_000 picoseconds. + Weight::from_parts(7_381_228, 18187) + // Standard Error: 6_650 + .saturating_add(Weight::from_parts(3_198_515, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: Democracy VotingOf (r:3 w:3) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:99 w:99) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Democracy::VotingOf` (r:3 w:3) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:99) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (108 ±0)` + // Measured: `863 + r * (108 ±0)` // Estimated: `19800 + r * (2676 ±0)` - // Minimum execution time: 46_106_000 picoseconds. - Weight::from_parts(48_936_654, 19800) - // Standard Error: 8_879 - .saturating_add(Weight::from_parts(4_708_141, 0).saturating_mul(r.into())) + // Minimum execution time: 40_109_000 picoseconds. + Weight::from_parts(43_164_384, 19800) + // Standard Error: 7_267 + .saturating_add(Weight::from_parts(4_161_526, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: Democracy VotingOf (r:2 w:2) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:99 w:99) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::VotingOf` (r:2 w:2) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:99) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `493 + r * (108 ±0)` + // Measured: `526 + r * (108 ±0)` // Estimated: `13530 + r * (2676 ±0)` - // Minimum execution time: 21_078_000 picoseconds. - Weight::from_parts(22_732_737, 13530) - // Standard Error: 7_969 - .saturating_add(Weight::from_parts(4_626_458, 0).saturating_mul(r.into())) + // Minimum execution time: 17_466_000 picoseconds. + Weight::from_parts(18_004_456, 13530) + // Standard Error: 6_327 + .saturating_add(Weight::from_parts(4_194_583, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: Democracy PublicProps (r:0 w:1) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:0 w:1) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) fn clear_public_proposals() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_229_000 picoseconds. - Weight::from_parts(3_415_000, 0) + // Minimum execution time: 2_824_000 picoseconds. + Weight::from_parts(2_948_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn unlock_remove(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `563` + // Measured: `596` // Estimated: `7260` - // Minimum execution time: 25_735_000 picoseconds. - Weight::from_parts(41_341_468, 7260) - // Standard Error: 3_727 - .saturating_add(Weight::from_parts(94_755, 0).saturating_mul(r.into())) + // Minimum execution time: 23_373_000 picoseconds. + Weight::from_parts(34_306_582, 7260) + // Standard Error: 2_849 + .saturating_add(Weight::from_parts(85_027, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn unlock_set(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `564 + r * (22 ±0)` + // Measured: `597 + r * (22 ±0)` // Estimated: `7260` - // Minimum execution time: 36_233_000 picoseconds. - Weight::from_parts(39_836_017, 7260) - // Standard Error: 1_791 - .saturating_add(Weight::from_parts(132_158, 0).saturating_mul(r.into())) + // Minimum execution time: 31_574_000 picoseconds. + Weight::from_parts(33_906_658, 7260) + // Standard Error: 1_514 + .saturating_add(Weight::from_parts(124_471, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 100]`. fn remove_vote(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `728 + r * (26 ±0)` + // Measured: `761 + r * (26 ±0)` // Estimated: `7260` - // Minimum execution time: 16_081_000 picoseconds. - Weight::from_parts(19_624_101, 7260) - // Standard Error: 1_639 - .saturating_add(Weight::from_parts(133_630, 0).saturating_mul(r.into())) + // Minimum execution time: 15_204_000 picoseconds. + Weight::from_parts(18_405_879, 7260) + // Standard Error: 1_851 + .saturating_add(Weight::from_parts(119_018, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 100]`. fn remove_other_vote(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `728 + r * (26 ±0)` + // Measured: `761 + r * (26 ±0)` // Estimated: `7260` - // Minimum execution time: 15_634_000 picoseconds. - Weight::from_parts(19_573_407, 7260) - // Standard Error: 1_790 - .saturating_add(Weight::from_parts(139_707, 0).saturating_mul(r.into())) + // Minimum execution time: 15_120_000 picoseconds. + Weight::from_parts(18_282_222, 7260) + // Standard Error: 1_669 + .saturating_add(Weight::from_parts(127_649, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Democracy NextExternal (r:1 w:0) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:0) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:0 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:0) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:0 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn set_external_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `356` + // Measured: `456` // Estimated: `3556` - // Minimum execution time: 18_344_000 picoseconds. - Weight::from_parts(18_727_000, 3556) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 17_351_000 picoseconds. + Weight::from_parts(17_964_000, 3556) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy NextExternal (r:1 w:0) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:0) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn clear_external_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `286` + // Measured: `319` // Estimated: `3518` - // Minimum execution time: 16_497_000 picoseconds. - Weight::from_parts(16_892_000, 3518) + // Minimum execution time: 13_669_000 picoseconds. + Weight::from_parts(14_410_000, 3518) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy PublicProps (r:1 w:0) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:0) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:0 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:1 w:0) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:0 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn set_proposal_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `4888` + // Measured: `4988` // Estimated: `18187` - // Minimum execution time: 39_517_000 picoseconds. - Weight::from_parts(40_632_000, 18187) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 39_162_000 picoseconds. + Weight::from_parts(40_109_000, 18187) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy PublicProps (r:1 w:0) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:1 w:0) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn clear_proposal_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `4822` + // Measured: `4855` // Estimated: `18187` - // Minimum execution time: 37_108_000 picoseconds. - Weight::from_parts(37_599_000, 18187) + // Minimum execution time: 34_141_000 picoseconds. + Weight::from_parts(34_732_000, 18187) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Preimage StatusFor (r:1 w:0) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:0 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:0 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn set_referendum_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `144` + // Measured: `211` // Estimated: `3556` - // Minimum execution time: 13_997_000 picoseconds. - Weight::from_parts(14_298_000, 3556) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 13_413_000 picoseconds. + Weight::from_parts(14_039_000, 3556) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:0) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:0) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn clear_referendum_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `302` + // Measured: `335` // Estimated: `3666` - // Minimum execution time: 18_122_000 picoseconds. - Weight::from_parts(18_655_000, 3666) + // Minimum execution time: 16_010_000 picoseconds. + Weight::from_parts(16_474_000, 3666) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Democracy PublicPropCount (r:1 w:1) - /// Proof: Democracy PublicPropCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy PublicProps (r:1 w:1) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy Blacklist (r:1 w:0) - /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) - /// Storage: Democracy DepositOf (r:0 w:1) - /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicPropCount` (r:1 w:1) + /// Proof: `Democracy::PublicPropCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::PublicProps` (r:1 w:1) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Blacklist` (r:1 w:0) + /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) + /// Storage: `Democracy::DepositOf` (r:0 w:1) + /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) fn propose() -> Weight { // Proof Size summary in bytes: - // Measured: `4801` + // Measured: `4834` // Estimated: `18187` - // Minimum execution time: 49_339_000 picoseconds. - Weight::from_parts(50_942_000, 18187) + // Minimum execution time: 39_930_000 picoseconds. + Weight::from_parts(41_746_000, 18187) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Democracy DepositOf (r:1 w:1) - /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) + /// Storage: `Democracy::DepositOf` (r:1 w:1) + /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) fn second() -> Weight { // Proof Size summary in bytes: - // Measured: `3556` + // Measured: `3589` // Estimated: `6695` - // Minimum execution time: 43_291_000 picoseconds. - Weight::from_parts(44_856_000, 6695) + // Minimum execution time: 36_490_000 picoseconds. + Weight::from_parts(37_615_000, 6695) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `3470` + // Measured: `3503` // Estimated: `7260` - // Minimum execution time: 61_890_000 picoseconds. - Weight::from_parts(63_626_000, 7260) + // Minimum execution time: 54_257_000 picoseconds. + Weight::from_parts(55_912_000, 7260) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `3492` + // Measured: `3525` // Estimated: `7260` - // Minimum execution time: 67_802_000 picoseconds. - Weight::from_parts(69_132_000, 7260) + // Minimum execution time: 56_878_000 picoseconds. + Weight::from_parts(58_796_000, 7260) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy Cancellations (r:1 w:1) - /// Proof: Democracy Cancellations (max_values: None, max_size: Some(33), added: 2508, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Cancellations` (r:1 w:1) + /// Proof: `Democracy::Cancellations` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn emergency_cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `366` + // Measured: `399` // Estimated: `3666` - // Minimum execution time: 25_757_000 picoseconds. - Weight::from_parts(27_226_000, 3666) + // Minimum execution time: 22_700_000 picoseconds. + Weight::from_parts(23_539_000, 3666) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Democracy PublicProps (r:1 w:1) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy DepositOf (r:1 w:1) - /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:3 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) - /// Storage: Democracy NextExternal (r:1 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy Blacklist (r:0 w:1) - /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:1 w:1) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::DepositOf` (r:1 w:1) + /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:3 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `Democracy::NextExternal` (r:1 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Blacklist` (r:0 w:1) + /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) fn blacklist() -> Weight { // Proof Size summary in bytes: - // Measured: `5910` + // Measured: `5943` // Estimated: `18187` - // Minimum execution time: 113_060_000 picoseconds. - Weight::from_parts(114_813_000, 18187) + // Minimum execution time: 95_398_000 picoseconds. + Weight::from_parts(97_261_000, 18187) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } - /// Storage: Democracy NextExternal (r:1 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy Blacklist (r:1 w:0) - /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Blacklist` (r:1 w:0) + /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) fn external_propose() -> Weight { // Proof Size summary in bytes: - // Measured: `3416` + // Measured: `3449` // Estimated: `6703` - // Minimum execution time: 13_413_000 picoseconds. - Weight::from_parts(13_794_000, 6703) + // Minimum execution time: 11_745_000 picoseconds. + Weight::from_parts(12_304_000, 6703) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy NextExternal (r:0 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:0 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) fn external_propose_majority() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_213_000 picoseconds. - Weight::from_parts(3_429_000, 0) + // Minimum execution time: 2_710_000 picoseconds. + Weight::from_parts(2_918_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy NextExternal (r:0 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:0 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) fn external_propose_default() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_280_000 picoseconds. - Weight::from_parts(3_389_000, 0) + // Minimum execution time: 2_664_000 picoseconds. + Weight::from_parts(2_776_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy NextExternal (r:1 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumCount (r:1 w:1) - /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:2) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:0 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumCount` (r:1 w:1) + /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:2) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:0 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) fn fast_track() -> Weight { // Proof Size summary in bytes: - // Measured: `286` + // Measured: `319` // Estimated: `3518` - // Minimum execution time: 28_142_000 picoseconds. - Weight::from_parts(28_862_000, 3518) + // Minimum execution time: 22_585_000 picoseconds. + Weight::from_parts(23_689_000, 3518) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Democracy NextExternal (r:1 w:1) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy Blacklist (r:1 w:1) - /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:1) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::Blacklist` (r:1 w:1) + /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn veto_external() -> Weight { // Proof Size summary in bytes: - // Measured: `3519` + // Measured: `3552` // Estimated: `6703` - // Minimum execution time: 32_395_000 picoseconds. - Weight::from_parts(33_617_000, 6703) + // Minimum execution time: 26_391_000 picoseconds. + Weight::from_parts(27_141_000, 6703) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Democracy PublicProps (r:1 w:1) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy DepositOf (r:1 w:1) - /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:1 w:1) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::DepositOf` (r:1 w:1) + /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn cancel_proposal() -> Weight { // Proof Size summary in bytes: - // Measured: `5821` + // Measured: `5854` // Estimated: `18187` - // Minimum execution time: 92_255_000 picoseconds. - Weight::from_parts(93_704_000, 18187) + // Minimum execution time: 77_905_000 picoseconds. + Weight::from_parts(79_628_000, 18187) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:0 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:0 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) fn cancel_referendum() -> Weight { // Proof Size summary in bytes: - // Measured: `271` + // Measured: `304` // Estimated: `3518` - // Minimum execution time: 19_623_000 picoseconds. - Weight::from_parts(20_545_000, 3518) + // Minimum execution time: 15_735_000 picoseconds. + Weight::from_parts(16_525_000, 3518) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Democracy LowestUnbaked (r:1 w:1) - /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumCount (r:1 w:0) - /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:99 w:0) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::LowestUnbaked` (r:1 w:1) + /// Proof: `Democracy::LowestUnbaked` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumCount` (r:1 w:0) + /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:0) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn on_initialize_base(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `244 + r * (86 ±0)` + // Measured: `277 + r * (86 ±0)` // Estimated: `1489 + r * (2676 ±0)` - // Minimum execution time: 7_032_000 picoseconds. - Weight::from_parts(7_931_421, 1489) - // Standard Error: 7_395 - .saturating_add(Weight::from_parts(3_236_964, 0).saturating_mul(r.into())) + // Minimum execution time: 5_274_000 picoseconds. + Weight::from_parts(6_162_399, 1489) + // Standard Error: 6_924 + .saturating_add(Weight::from_parts(3_186_702, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: Democracy LowestUnbaked (r:1 w:1) - /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumCount (r:1 w:0) - /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Democracy LastTabledWasExternal (r:1 w:0) - /// Proof: Democracy LastTabledWasExternal (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: Democracy NextExternal (r:1 w:0) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy PublicProps (r:1 w:0) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:99 w:0) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::LowestUnbaked` (r:1 w:1) + /// Proof: `Democracy::LowestUnbaked` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumCount` (r:1 w:0) + /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Democracy::LastTabledWasExternal` (r:1 w:0) + /// Proof: `Democracy::LastTabledWasExternal` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `Democracy::NextExternal` (r:1 w:0) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::PublicProps` (r:1 w:0) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:0) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `244 + r * (86 ±0)` + // Measured: `277 + r * (86 ±0)` // Estimated: `18187 + r * (2676 ±0)` - // Minimum execution time: 10_524_000 picoseconds. - Weight::from_parts(10_369_064, 18187) - // Standard Error: 8_385 - .saturating_add(Weight::from_parts(3_242_334, 0).saturating_mul(r.into())) + // Minimum execution time: 7_950_000 picoseconds. + Weight::from_parts(7_381_228, 18187) + // Standard Error: 6_650 + .saturating_add(Weight::from_parts(3_198_515, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: Democracy VotingOf (r:3 w:3) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:99 w:99) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Democracy::VotingOf` (r:3 w:3) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:99) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `830 + r * (108 ±0)` + // Measured: `863 + r * (108 ±0)` // Estimated: `19800 + r * (2676 ±0)` - // Minimum execution time: 46_106_000 picoseconds. - Weight::from_parts(48_936_654, 19800) - // Standard Error: 8_879 - .saturating_add(Weight::from_parts(4_708_141, 0).saturating_mul(r.into())) + // Minimum execution time: 40_109_000 picoseconds. + Weight::from_parts(43_164_384, 19800) + // Standard Error: 7_267 + .saturating_add(Weight::from_parts(4_161_526, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: Democracy VotingOf (r:2 w:2) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Democracy ReferendumInfoOf (r:99 w:99) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: `Democracy::VotingOf` (r:2 w:2) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:99) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `493 + r * (108 ±0)` + // Measured: `526 + r * (108 ±0)` // Estimated: `13530 + r * (2676 ±0)` - // Minimum execution time: 21_078_000 picoseconds. - Weight::from_parts(22_732_737, 13530) - // Standard Error: 7_969 - .saturating_add(Weight::from_parts(4_626_458, 0).saturating_mul(r.into())) + // Minimum execution time: 17_466_000 picoseconds. + Weight::from_parts(18_004_456, 13530) + // Standard Error: 6_327 + .saturating_add(Weight::from_parts(4_194_583, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: Democracy PublicProps (r:0 w:1) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:0 w:1) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) fn clear_public_proposals() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_229_000 picoseconds. - Weight::from_parts(3_415_000, 0) + // Minimum execution time: 2_824_000 picoseconds. + Weight::from_parts(2_948_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn unlock_remove(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `563` + // Measured: `596` // Estimated: `7260` - // Minimum execution time: 25_735_000 picoseconds. - Weight::from_parts(41_341_468, 7260) - // Standard Error: 3_727 - .saturating_add(Weight::from_parts(94_755, 0).saturating_mul(r.into())) + // Minimum execution time: 23_373_000 picoseconds. + Weight::from_parts(34_306_582, 7260) + // Standard Error: 2_849 + .saturating_add(Weight::from_parts(85_027, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 99]`. fn unlock_set(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `564 + r * (22 ±0)` + // Measured: `597 + r * (22 ±0)` // Estimated: `7260` - // Minimum execution time: 36_233_000 picoseconds. - Weight::from_parts(39_836_017, 7260) - // Standard Error: 1_791 - .saturating_add(Weight::from_parts(132_158, 0).saturating_mul(r.into())) + // Minimum execution time: 31_574_000 picoseconds. + Weight::from_parts(33_906_658, 7260) + // Standard Error: 1_514 + .saturating_add(Weight::from_parts(124_471, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 100]`. fn remove_vote(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `728 + r * (26 ±0)` + // Measured: `761 + r * (26 ±0)` // Estimated: `7260` - // Minimum execution time: 16_081_000 picoseconds. - Weight::from_parts(19_624_101, 7260) - // Standard Error: 1_639 - .saturating_add(Weight::from_parts(133_630, 0).saturating_mul(r.into())) + // Minimum execution time: 15_204_000 picoseconds. + Weight::from_parts(18_405_879, 7260) + // Standard Error: 1_851 + .saturating_add(Weight::from_parts(119_018, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:1) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy VotingOf (r:1 w:1) - /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::VotingOf` (r:1 w:1) + /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 100]`. fn remove_other_vote(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `728 + r * (26 ±0)` + // Measured: `761 + r * (26 ±0)` // Estimated: `7260` - // Minimum execution time: 15_634_000 picoseconds. - Weight::from_parts(19_573_407, 7260) - // Standard Error: 1_790 - .saturating_add(Weight::from_parts(139_707, 0).saturating_mul(r.into())) + // Minimum execution time: 15_120_000 picoseconds. + Weight::from_parts(18_282_222, 7260) + // Standard Error: 1_669 + .saturating_add(Weight::from_parts(127_649, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Democracy NextExternal (r:1 w:0) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:0) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:0 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:0) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:0 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn set_external_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `356` + // Measured: `456` // Estimated: `3556` - // Minimum execution time: 18_344_000 picoseconds. - Weight::from_parts(18_727_000, 3556) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Minimum execution time: 17_351_000 picoseconds. + Weight::from_parts(17_964_000, 3556) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy NextExternal (r:1 w:0) - /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::NextExternal` (r:1 w:0) + /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn clear_external_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `286` + // Measured: `319` // Estimated: `3518` - // Minimum execution time: 16_497_000 picoseconds. - Weight::from_parts(16_892_000, 3518) + // Minimum execution time: 13_669_000 picoseconds. + Weight::from_parts(14_410_000, 3518) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy PublicProps (r:1 w:0) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:0) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:0 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:1 w:0) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:0 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn set_proposal_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `4888` + // Measured: `4988` // Estimated: `18187` - // Minimum execution time: 39_517_000 picoseconds. - Weight::from_parts(40_632_000, 18187) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Minimum execution time: 39_162_000 picoseconds. + Weight::from_parts(40_109_000, 18187) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy PublicProps (r:1 w:0) - /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::PublicProps` (r:1 w:0) + /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn clear_proposal_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `4822` + // Measured: `4855` // Estimated: `18187` - // Minimum execution time: 37_108_000 picoseconds. - Weight::from_parts(37_599_000, 18187) + // Minimum execution time: 34_141_000 picoseconds. + Weight::from_parts(34_732_000, 18187) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Preimage StatusFor (r:1 w:0) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:0 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:0 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn set_referendum_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `144` + // Measured: `211` // Estimated: `3556` - // Minimum execution time: 13_997_000 picoseconds. - Weight::from_parts(14_298_000, 3556) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Minimum execution time: 13_413_000 picoseconds. + Weight::from_parts(14_039_000, 3556) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Democracy ReferendumInfoOf (r:1 w:0) - /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) - /// Storage: Democracy MetadataOf (r:1 w:1) - /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:0) + /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: `Democracy::MetadataOf` (r:1 w:1) + /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) fn clear_referendum_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `302` + // Measured: `335` // Estimated: `3666` - // Minimum execution time: 18_122_000 picoseconds. - Weight::from_parts(18_655_000, 3666) + // Minimum execution time: 16_010_000 picoseconds. + Weight::from_parts(16_474_000, 3666) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/election-provider-multi-phase/src/mock.rs b/substrate/frame/election-provider-multi-phase/src/mock.rs index 18dcd7061c1..312dc557090 100644 --- a/substrate/frame/election-provider-multi-phase/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/src/mock.rs @@ -441,7 +441,7 @@ where type Extrinsic = Extrinsic; } -pub type Extrinsic = sp_runtime::testing::TestXt; +pub type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; parameter_types! { pub MaxNominations: u32 = ::LIMIT as u32; diff --git a/substrate/frame/election-provider-multi-phase/src/unsigned.rs b/substrate/frame/election-provider-multi-phase/src/unsigned.rs index 94348181334..94cfd059b6c 100644 --- a/substrate/frame/election-provider-multi-phase/src/unsigned.rs +++ b/substrate/frame/election-provider-multi-phase/src/unsigned.rs @@ -1813,7 +1813,7 @@ mod tests { let encoded = pool.read().transactions[0].clone(); let extrinsic: Extrinsic = codec::Decode::decode(&mut &*encoded).unwrap(); - let call = extrinsic.call; + let call = extrinsic.function; assert!(matches!(call, RuntimeCall::MultiPhase(Call::submit_unsigned { .. }))); }) } @@ -1830,7 +1830,7 @@ mod tests { let encoded = pool.read().transactions[0].clone(); let extrinsic = Extrinsic::decode(&mut &*encoded).unwrap(); - let call = match extrinsic.call { + let call = match extrinsic.function { RuntimeCall::MultiPhase(call @ Call::submit_unsigned { .. }) => call, _ => panic!("bad call: unexpected submission"), }; diff --git a/substrate/frame/election-provider-multi-phase/src/weights.rs b/substrate/frame/election-provider-multi-phase/src/weights.rs index be578fac8c4..ed3e942716e 100644 --- a/substrate/frame/election-provider-multi-phase/src/weights.rs +++ b/substrate/frame/election-provider-multi-phase/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_election_provider_multi_phase +//! Autogenerated weights for `pallet_election_provider_multi_phase` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/election-provider-multi-phase/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/election-provider-multi-phase/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_election_provider_multi_phase. +/// Weight functions needed for `pallet_election_provider_multi_phase`. pub trait WeightInfo { fn on_initialize_nothing() -> Weight; fn on_initialize_open_signed() -> Weight; @@ -64,169 +63,171 @@ pub trait WeightInfo { fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight; } -/// Weights for pallet_election_provider_multi_phase using the Substrate node and recommended hardware. +/// Weights for `pallet_election_provider_multi_phase` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CurrentPlannedSession (r:1 w:0) - /// Proof: Staking CurrentPlannedSession (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasStartSessionIndex (r:1 w:0) - /// Proof: Staking ErasStartSessionIndex (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: Babe EpochIndex (r:1 w:0) - /// Proof: Babe EpochIndex (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Babe GenesisSlot (r:1 w:0) - /// Proof: Babe GenesisSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Babe CurrentSlot (r:1 w:0) - /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Staking ForceEra (r:1 w:0) - /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentPlannedSession` (r:1 w:0) + /// Proof: `Staking::CurrentPlannedSession` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::ErasStartSessionIndex` (r:1 w:0) + /// Proof: `Staking::ErasStartSessionIndex` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `Babe::EpochIndex` (r:1 w:0) + /// Proof: `Babe::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Babe::GenesisSlot` (r:1 w:0) + /// Proof: `Babe::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Babe::CurrentSlot` (r:1 w:0) + /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Staking::ForceEra` (r:1 w:0) + /// Proof: `Staking::ForceEra` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn on_initialize_nothing() -> Weight { // Proof Size summary in bytes: - // Measured: `1028` + // Measured: `1061` // Estimated: `3481` - // Minimum execution time: 22_089_000 picoseconds. - Weight::from_parts(22_677_000, 3481) + // Minimum execution time: 19_340_000 picoseconds. + Weight::from_parts(19_886_000, 3481) .saturating_add(T::DbWeight::get().reads(8_u64)) } - /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn on_initialize_open_signed() -> Weight { // Proof Size summary in bytes: // Measured: `148` // Estimated: `1633` - // Minimum execution time: 11_986_000 picoseconds. - Weight::from_parts(12_445_000, 1633) + // Minimum execution time: 8_067_000 picoseconds. + Weight::from_parts(8_508_000, 1633) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn on_initialize_open_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `148` // Estimated: `1633` - // Minimum execution time: 12_988_000 picoseconds. - Weight::from_parts(13_281_000, 1633) + // Minimum execution time: 8_810_000 picoseconds. + Weight::from_parts(9_061_000, 1633) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn finalize_signed_phase_accept_solution() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 32_659_000 picoseconds. - Weight::from_parts(33_281_000, 3593) + // Minimum execution time: 24_339_000 picoseconds. + Weight::from_parts(25_322_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn finalize_signed_phase_reject_solution() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 22_471_000 picoseconds. - Weight::from_parts(23_046_000, 3593) + // Minimum execution time: 16_635_000 picoseconds. + Weight::from_parts(17_497_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. fn create_snapshot_internal(v: u32, _t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 262_360_000 picoseconds. - Weight::from_parts(279_313_000, 0) - // Standard Error: 2_384 - .saturating_add(Weight::from_parts(176_415, 0).saturating_mul(v.into())) + // Minimum execution time: 170_730_000 picoseconds. + Weight::from_parts(175_009_000, 0) + // Standard Error: 2_010 + .saturating_add(Weight::from_parts(224_974, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionIndices (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionNextIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionsMap (max_values: None, max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase QueuedSolution (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Round (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionIndices` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionsMap` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionsMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn elect_queued(a: u32, d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `371 + a * (768 ±0) + d * (48 ±0)` // Estimated: `3923 + a * (768 ±0) + d * (49 ±0)` - // Minimum execution time: 301_283_000 picoseconds. - Weight::from_parts(324_586_000, 3923) - // Standard Error: 4_763 - .saturating_add(Weight::from_parts(279_812, 0).saturating_mul(a.into())) + // Minimum execution time: 280_705_000 picoseconds. + Weight::from_parts(303_018_000, 3923) + // Standard Error: 4_633 + .saturating_add(Weight::from_parts(307_274, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) .saturating_add(Weight::from_parts(0, 768).saturating_mul(a.into())) .saturating_add(Weight::from_parts(0, 49).saturating_mul(d.into())) } - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) - /// Proof: TransactionPayment NextFeeMultiplier (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionIndices (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionNextIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionsMap (max_values: None, max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionIndices` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionsMap` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionsMap` (`max_values`: None, `max_size`: None, mode: `Measured`) fn submit() -> Weight { // Proof Size summary in bytes: // Measured: `927` // Estimated: `2412` - // Minimum execution time: 52_276_000 picoseconds. - Weight::from_parts(53_846_000, 2412) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Minimum execution time: 43_405_000 picoseconds. + Weight::from_parts(45_734_000, 2412) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase QueuedSolution (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase MinimumUntrustedScore (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::MinimumUntrustedScore` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::MinimumUntrustedScore` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `a` is `[500, 800]`. @@ -235,25 +236,25 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `253 + t * (32 ±0) + v * (553 ±0)` // Estimated: `1738 + t * (32 ±0) + v * (553 ±0)` - // Minimum execution time: 5_448_459_000 picoseconds. - Weight::from_parts(5_525_622_000, 1738) - // Standard Error: 21_478 - .saturating_add(Weight::from_parts(256_345, 0).saturating_mul(v.into())) - // Standard Error: 63_648 - .saturating_add(Weight::from_parts(5_103_224, 0).saturating_mul(a.into())) + // Minimum execution time: 5_059_092_000 picoseconds. + Weight::from_parts(5_263_076_000, 1738) + // Standard Error: 17_317 + .saturating_add(Weight::from_parts(384_051, 0).saturating_mul(v.into())) + // Standard Error: 51_319 + .saturating_add(Weight::from_parts(4_095_128, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(t.into())) .saturating_add(Weight::from_parts(0, 553).saturating_mul(v.into())) } - /// Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase MinimumUntrustedScore (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::MinimumUntrustedScore` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::MinimumUntrustedScore` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `a` is `[500, 800]`. @@ -262,180 +263,182 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `228 + t * (32 ±0) + v * (553 ±0)` // Estimated: `1713 + t * (32 ±0) + v * (553 ±0)` - // Minimum execution time: 4_724_399_000 picoseconds. - Weight::from_parts(4_886_472_000, 1713) - // Standard Error: 15_220 - .saturating_add(Weight::from_parts(365_569, 0).saturating_mul(v.into())) - // Standard Error: 45_104 - .saturating_add(Weight::from_parts(3_176_675, 0).saturating_mul(a.into())) + // Minimum execution time: 4_426_416_000 picoseconds. + Weight::from_parts(4_466_923_000, 1713) + // Standard Error: 15_415 + .saturating_add(Weight::from_parts(334_047, 0).saturating_mul(v.into())) + // Standard Error: 45_682 + .saturating_add(Weight::from_parts(3_097_318, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(t.into())) .saturating_add(Weight::from_parts(0, 553).saturating_mul(v.into())) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CurrentPlannedSession (r:1 w:0) - /// Proof: Staking CurrentPlannedSession (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasStartSessionIndex (r:1 w:0) - /// Proof: Staking ErasStartSessionIndex (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) - /// Storage: Babe EpochIndex (r:1 w:0) - /// Proof: Babe EpochIndex (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Babe GenesisSlot (r:1 w:0) - /// Proof: Babe GenesisSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Babe CurrentSlot (r:1 w:0) - /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Staking ForceEra (r:1 w:0) - /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentPlannedSession` (r:1 w:0) + /// Proof: `Staking::CurrentPlannedSession` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::ErasStartSessionIndex` (r:1 w:0) + /// Proof: `Staking::ErasStartSessionIndex` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: `Babe::EpochIndex` (r:1 w:0) + /// Proof: `Babe::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Babe::GenesisSlot` (r:1 w:0) + /// Proof: `Babe::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Babe::CurrentSlot` (r:1 w:0) + /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Staking::ForceEra` (r:1 w:0) + /// Proof: `Staking::ForceEra` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn on_initialize_nothing() -> Weight { // Proof Size summary in bytes: - // Measured: `1028` + // Measured: `1061` // Estimated: `3481` - // Minimum execution time: 22_089_000 picoseconds. - Weight::from_parts(22_677_000, 3481) + // Minimum execution time: 19_340_000 picoseconds. + Weight::from_parts(19_886_000, 3481) .saturating_add(RocksDbWeight::get().reads(8_u64)) } - /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn on_initialize_open_signed() -> Weight { // Proof Size summary in bytes: // Measured: `148` // Estimated: `1633` - // Minimum execution time: 11_986_000 picoseconds. - Weight::from_parts(12_445_000, 1633) + // Minimum execution time: 8_067_000 picoseconds. + Weight::from_parts(8_508_000, 1633) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn on_initialize_open_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `148` // Estimated: `1633` - // Minimum execution time: 12_988_000 picoseconds. - Weight::from_parts(13_281_000, 1633) + // Minimum execution time: 8_810_000 picoseconds. + Weight::from_parts(9_061_000, 1633) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn finalize_signed_phase_accept_solution() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 32_659_000 picoseconds. - Weight::from_parts(33_281_000, 3593) + // Minimum execution time: 24_339_000 picoseconds. + Weight::from_parts(25_322_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn finalize_signed_phase_reject_solution() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 22_471_000 picoseconds. - Weight::from_parts(23_046_000, 3593) + // Minimum execution time: 16_635_000 picoseconds. + Weight::from_parts(17_497_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. fn create_snapshot_internal(v: u32, _t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 262_360_000 picoseconds. - Weight::from_parts(279_313_000, 0) - // Standard Error: 2_384 - .saturating_add(Weight::from_parts(176_415, 0).saturating_mul(v.into())) + // Minimum execution time: 170_730_000 picoseconds. + Weight::from_parts(175_009_000, 0) + // Standard Error: 2_010 + .saturating_add(Weight::from_parts(224_974, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionIndices (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionNextIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionsMap (max_values: None, max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase QueuedSolution (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Round (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionIndices` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionsMap` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionsMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn elect_queued(a: u32, d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `371 + a * (768 ±0) + d * (48 ±0)` // Estimated: `3923 + a * (768 ±0) + d * (49 ±0)` - // Minimum execution time: 301_283_000 picoseconds. - Weight::from_parts(324_586_000, 3923) - // Standard Error: 4_763 - .saturating_add(Weight::from_parts(279_812, 0).saturating_mul(a.into())) + // Minimum execution time: 280_705_000 picoseconds. + Weight::from_parts(303_018_000, 3923) + // Standard Error: 4_633 + .saturating_add(Weight::from_parts(307_274, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) .saturating_add(Weight::from_parts(0, 768).saturating_mul(a.into())) .saturating_add(Weight::from_parts(0, 49).saturating_mul(d.into())) } - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) - /// Proof: TransactionPayment NextFeeMultiplier (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionIndices (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionNextIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) - /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionsMap (max_values: None, max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionIndices` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::SignedSubmissionsMap` (r:0 w:1) + /// Proof: `ElectionProviderMultiPhase::SignedSubmissionsMap` (`max_values`: None, `max_size`: None, mode: `Measured`) fn submit() -> Weight { // Proof Size summary in bytes: // Measured: `927` // Estimated: `2412` - // Minimum execution time: 52_276_000 picoseconds. - Weight::from_parts(53_846_000, 2412) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Minimum execution time: 43_405_000 picoseconds. + Weight::from_parts(45_734_000, 2412) + .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase QueuedSolution (r:1 w:1) - /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase MinimumUntrustedScore (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:1 w:1) + /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::MinimumUntrustedScore` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::MinimumUntrustedScore` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `a` is `[500, 800]`. @@ -444,25 +447,25 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `253 + t * (32 ±0) + v * (553 ±0)` // Estimated: `1738 + t * (32 ±0) + v * (553 ±0)` - // Minimum execution time: 5_448_459_000 picoseconds. - Weight::from_parts(5_525_622_000, 1738) - // Standard Error: 21_478 - .saturating_add(Weight::from_parts(256_345, 0).saturating_mul(v.into())) - // Standard Error: 63_648 - .saturating_add(Weight::from_parts(5_103_224, 0).saturating_mul(a.into())) + // Minimum execution time: 5_059_092_000 picoseconds. + Weight::from_parts(5_263_076_000, 1738) + // Standard Error: 17_317 + .saturating_add(Weight::from_parts(384_051, 0).saturating_mul(v.into())) + // Standard Error: 51_319 + .saturating_add(Weight::from_parts(4_095_128, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(t.into())) .saturating_add(Weight::from_parts(0, 553).saturating_mul(v.into())) } - /// Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase MinimumUntrustedScore (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ElectionProviderMultiPhase::MinimumUntrustedScore` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::MinimumUntrustedScore` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `a` is `[500, 800]`. @@ -471,12 +474,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `228 + t * (32 ±0) + v * (553 ±0)` // Estimated: `1713 + t * (32 ±0) + v * (553 ±0)` - // Minimum execution time: 4_724_399_000 picoseconds. - Weight::from_parts(4_886_472_000, 1713) - // Standard Error: 15_220 - .saturating_add(Weight::from_parts(365_569, 0).saturating_mul(v.into())) - // Standard Error: 45_104 - .saturating_add(Weight::from_parts(3_176_675, 0).saturating_mul(a.into())) + // Minimum execution time: 4_426_416_000 picoseconds. + Weight::from_parts(4_466_923_000, 1713) + // Standard Error: 15_415 + .saturating_add(Weight::from_parts(334_047, 0).saturating_mul(v.into())) + // Standard Error: 45_682 + .saturating_add(Weight::from_parts(3_097_318, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(t.into())) .saturating_add(Weight::from_parts(0, 553).saturating_mul(v.into())) diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs index 882b894bb22..7fade251e6d 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs @@ -62,7 +62,7 @@ pub const INIT_TIMESTAMP: BlockNumber = 30_000; pub const BLOCK_TIME: BlockNumber = 1000; type Block = frame_system::mocking::MockBlockU32; -type Extrinsic = testing::TestXt; +type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; frame_support::construct_runtime!( pub enum Runtime { @@ -699,7 +699,7 @@ pub fn roll_to_with_ocw(n: BlockNumber, pool: Arc>, delay_solu for encoded in &pool.read().transactions { let extrinsic = Extrinsic::decode(&mut &encoded[..]).unwrap(); - let _ = match extrinsic.call { + let _ = match extrinsic.function { RuntimeCall::ElectionProviderMultiPhase( call @ Call::submit_unsigned { .. }, ) => { diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs index 308f2cdc1aa..e08412a6e87 100644 --- a/substrate/frame/elections-phragmen/src/lib.rs +++ b/substrate/frame/elections-phragmen/src/lib.rs @@ -1422,7 +1422,7 @@ mod tests { pub type Block = sp_runtime::generic::Block; pub type UncheckedExtrinsic = - sp_runtime::generic::UncheckedExtrinsic; + sp_runtime::generic::UncheckedExtrinsic; frame_support::construct_runtime!( pub enum Test diff --git a/substrate/frame/elections-phragmen/src/weights.rs b/substrate/frame/elections-phragmen/src/weights.rs index b7ed13dae9f..cd67918e85b 100644 --- a/substrate/frame/elections-phragmen/src/weights.rs +++ b/substrate/frame/elections-phragmen/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_elections_phragmen +//! Autogenerated weights for `pallet_elections_phragmen` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/elections-phragmen/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/elections-phragmen/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_elections_phragmen. +/// Weight functions needed for `pallet_elections_phragmen`. pub trait WeightInfo { fn vote_equal(v: u32, ) -> Weight; fn vote_more(v: u32, ) -> Weight; @@ -66,165 +65,165 @@ pub trait WeightInfo { fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight; } -/// Weights for pallet_elections_phragmen using the Substrate node and recommended hardware. +/// Weights for `pallet_elections_phragmen` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Elections Candidates (r:1 w:0) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Voting (r:1 w:1) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Elections::Candidates` (r:1 w:0) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Voting` (r:1 w:1) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `v` is `[1, 16]`. fn vote_equal(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 33_028_000 picoseconds. - Weight::from_parts(34_073_914, 4764) - // Standard Error: 3_474 - .saturating_add(Weight::from_parts(205_252, 0).saturating_mul(v.into())) + // Minimum execution time: 29_390_000 picoseconds. + Weight::from_parts(30_525_476, 4764) + // Standard Error: 3_185 + .saturating_add(Weight::from_parts(143_073, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: Elections Candidates (r:1 w:0) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Voting (r:1 w:1) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Elections::Candidates` (r:1 w:0) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Voting` (r:1 w:1) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `v` is `[2, 16]`. fn vote_more(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `371 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 45_725_000 picoseconds. - Weight::from_parts(47_169_586, 4764) - // Standard Error: 5_148 - .saturating_add(Weight::from_parts(213_742, 0).saturating_mul(v.into())) + // Minimum execution time: 39_765_000 picoseconds. + Weight::from_parts(41_374_102, 4764) + // Standard Error: 4_310 + .saturating_add(Weight::from_parts(153_015, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: Elections Candidates (r:1 w:0) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Voting (r:1 w:1) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Elections::Candidates` (r:1 w:0) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Voting` (r:1 w:1) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `v` is `[2, 16]`. fn vote_less(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 45_519_000 picoseconds. - Weight::from_parts(47_339_108, 4764) - // Standard Error: 5_501 - .saturating_add(Weight::from_parts(195_247, 0).saturating_mul(v.into())) + // Minimum execution time: 39_647_000 picoseconds. + Weight::from_parts(41_474_523, 4764) + // Standard Error: 5_503 + .saturating_add(Weight::from_parts(149_029, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: Elections Voting (r:1 w:1) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Elections::Voting` (r:1 w:1) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn remove_voter() -> Weight { // Proof Size summary in bytes: // Measured: `925` // Estimated: `4764` - // Minimum execution time: 50_386_000 picoseconds. - Weight::from_parts(51_378_000, 4764) + // Minimum execution time: 41_882_000 picoseconds. + Weight::from_parts(42_794_000, 4764) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Elections Candidates (r:1 w:1) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Candidates` (r:1 w:1) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 64]`. fn submit_candidacy(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1570 + c * (48 ±0)` // Estimated: `3055 + c * (48 ±0)` - // Minimum execution time: 38_987_000 picoseconds. - Weight::from_parts(41_302_276, 3055) - // Standard Error: 2_047 - .saturating_add(Weight::from_parts(125_200, 0).saturating_mul(c.into())) + // Minimum execution time: 33_719_000 picoseconds. + Weight::from_parts(35_017_073, 3055) + // Standard Error: 1_587 + .saturating_add(Weight::from_parts(121_130, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into())) } - /// Storage: Elections Candidates (r:1 w:1) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Candidates` (r:1 w:1) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 64]`. fn renounce_candidacy_candidate(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `285 + c * (48 ±0)` // Estimated: `1770 + c * (48 ±0)` - // Minimum execution time: 33_510_000 picoseconds. - Weight::from_parts(34_947_760, 1770) - // Standard Error: 1_781 - .saturating_add(Weight::from_parts(78_851, 0).saturating_mul(c.into())) + // Minimum execution time: 27_263_000 picoseconds. + Weight::from_parts(28_215_666, 1770) + // Standard Error: 1_196 + .saturating_add(Weight::from_parts(86_804, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into())) } - /// Storage: Elections Members (r:1 w:1) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:1) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Members (r:0 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Members` (r:1 w:1) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:1) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:1 w:1) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:0) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:0 w:1) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn renounce_candidacy_members() -> Weight { // Proof Size summary in bytes: - // Measured: `1900` - // Estimated: `3385` - // Minimum execution time: 50_603_000 picoseconds. - Weight::from_parts(51_715_000, 3385) + // Measured: `1933` + // Estimated: `3418` + // Minimum execution time: 41_531_000 picoseconds. + Weight::from_parts(42_937_000, 3418) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Elections RunnersUp (r:1 w:1) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::RunnersUp` (r:1 w:1) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn renounce_candidacy_runners_up() -> Weight { // Proof Size summary in bytes: // Measured: `880` // Estimated: `2365` - // Minimum execution time: 33_441_000 picoseconds. - Weight::from_parts(34_812_000, 2365) + // Minimum execution time: 27_680_000 picoseconds. + Weight::from_parts(28_810_000, 2365) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn remove_member_without_replacement() -> Weight { // Proof Size summary in bytes: // Measured: `0` @@ -232,87 +231,90 @@ impl WeightInfo for SubstrateWeight { // Minimum execution time: 2_000_000_000_000 picoseconds. Weight::from_parts(2_000_000_000_000, 0) } - /// Storage: Elections Members (r:1 w:1) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Elections RunnersUp (r:1 w:1) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Members (r:0 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Members` (r:1 w:1) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Elections::RunnersUp` (r:1 w:1) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:1 w:1) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:0) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:0 w:1) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn remove_member_with_replacement() -> Weight { // Proof Size summary in bytes: - // Measured: `1900` + // Measured: `1933` // Estimated: `3593` - // Minimum execution time: 57_289_000 picoseconds. - Weight::from_parts(58_328_000, 3593) + // Minimum execution time: 45_333_000 picoseconds. + Weight::from_parts(46_523_000, 3593) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Elections Voting (r:513 w:512) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Candidates (r:1 w:0) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Balances Locks (r:512 w:512) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:512 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:512 w:512) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Elections::Voting` (r:257 w:256) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Candidates` (r:1 w:0) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:256 w:256) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:256 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:256 w:256) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `v` is `[256, 512]`. /// The range of component `d` is `[0, 256]`. - fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { + fn clean_defunct_voters(v: u32, d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1149 + v * (811 ±0)` - // Estimated: `4621 + v * (3774 ±0)` - // Minimum execution time: 18_774_231_000 picoseconds. - Weight::from_parts(18_933_040_000, 4621) - // Standard Error: 301_534 - .saturating_add(Weight::from_parts(44_306_903, 0).saturating_mul(v.into())) + // Measured: `0 + d * (818 ±0) + v * (57 ±0)` + // Estimated: `24906 + d * (3774 ±1) + v * (24 ±0)` + // Minimum execution time: 5_620_000 picoseconds. + Weight::from_parts(5_817_000, 24906) + // Standard Error: 18_357 + .saturating_add(Weight::from_parts(106_164, 0).saturating_mul(v.into())) + // Standard Error: 39_980 + .saturating_add(Weight::from_parts(52_456_337, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(v.into()))) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) - .saturating_add(Weight::from_parts(0, 3774).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(d.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(d.into()))) + .saturating_add(Weight::from_parts(0, 3774).saturating_mul(d.into())) + .saturating_add(Weight::from_parts(0, 24).saturating_mul(v.into())) } - /// Storage: Elections Candidates (r:1 w:1) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:1) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:1) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Voting (r:513 w:0) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:44 w:44) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Elections ElectionRounds (r:1 w:1) - /// Proof Skipped: Elections ElectionRounds (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Members (r:0 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:0 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Candidates` (r:1 w:1) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:1) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:1) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Voting` (r:513 w:0) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:0) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:44 w:44) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Elections::ElectionRounds` (r:1 w:1) + /// Proof: `Elections::ElectionRounds` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:0 w:1) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:0 w:1) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 64]`. /// The range of component `v` is `[1, 512]`. /// The range of component `e` is `[512, 8192]`. fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + e * (28 ±0) + v * (606 ±0)` - // Estimated: `178887 + c * (2135 ±7) + e * (12 ±0) + v * (2653 ±6)` - // Minimum execution time: 1_281_877_000 picoseconds. - Weight::from_parts(1_288_147_000, 178887) - // Standard Error: 528_851 - .saturating_add(Weight::from_parts(17_761_407, 0).saturating_mul(v.into())) - // Standard Error: 33_932 - .saturating_add(Weight::from_parts(698_277, 0).saturating_mul(e.into())) + // Estimated: `178920 + c * (2135 ±7) + e * (12 ±0) + v * (2653 ±6)` + // Minimum execution time: 1_082_582_000 picoseconds. + Weight::from_parts(1_084_730_000, 178920) + // Standard Error: 594_096 + .saturating_add(Weight::from_parts(19_096_288, 0).saturating_mul(v.into())) + // Standard Error: 38_118 + .saturating_add(Weight::from_parts(792_945, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(21_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) @@ -324,164 +326,164 @@ impl WeightInfo for SubstrateWeight { } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Elections Candidates (r:1 w:0) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Voting (r:1 w:1) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Elections::Candidates` (r:1 w:0) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Voting` (r:1 w:1) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `v` is `[1, 16]`. fn vote_equal(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 33_028_000 picoseconds. - Weight::from_parts(34_073_914, 4764) - // Standard Error: 3_474 - .saturating_add(Weight::from_parts(205_252, 0).saturating_mul(v.into())) + // Minimum execution time: 29_390_000 picoseconds. + Weight::from_parts(30_525_476, 4764) + // Standard Error: 3_185 + .saturating_add(Weight::from_parts(143_073, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: Elections Candidates (r:1 w:0) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Voting (r:1 w:1) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Elections::Candidates` (r:1 w:0) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Voting` (r:1 w:1) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `v` is `[2, 16]`. fn vote_more(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `371 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 45_725_000 picoseconds. - Weight::from_parts(47_169_586, 4764) - // Standard Error: 5_148 - .saturating_add(Weight::from_parts(213_742, 0).saturating_mul(v.into())) + // Minimum execution time: 39_765_000 picoseconds. + Weight::from_parts(41_374_102, 4764) + // Standard Error: 4_310 + .saturating_add(Weight::from_parts(153_015, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: Elections Candidates (r:1 w:0) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Voting (r:1 w:1) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Elections::Candidates` (r:1 w:0) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Voting` (r:1 w:1) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// The range of component `v` is `[2, 16]`. fn vote_less(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 45_519_000 picoseconds. - Weight::from_parts(47_339_108, 4764) - // Standard Error: 5_501 - .saturating_add(Weight::from_parts(195_247, 0).saturating_mul(v.into())) + // Minimum execution time: 39_647_000 picoseconds. + Weight::from_parts(41_474_523, 4764) + // Standard Error: 5_503 + .saturating_add(Weight::from_parts(149_029, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: Elections Voting (r:1 w:1) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `Elections::Voting` (r:1 w:1) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn remove_voter() -> Weight { // Proof Size summary in bytes: // Measured: `925` // Estimated: `4764` - // Minimum execution time: 50_386_000 picoseconds. - Weight::from_parts(51_378_000, 4764) + // Minimum execution time: 41_882_000 picoseconds. + Weight::from_parts(42_794_000, 4764) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Elections Candidates (r:1 w:1) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Candidates` (r:1 w:1) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 64]`. fn submit_candidacy(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1570 + c * (48 ±0)` // Estimated: `3055 + c * (48 ±0)` - // Minimum execution time: 38_987_000 picoseconds. - Weight::from_parts(41_302_276, 3055) - // Standard Error: 2_047 - .saturating_add(Weight::from_parts(125_200, 0).saturating_mul(c.into())) + // Minimum execution time: 33_719_000 picoseconds. + Weight::from_parts(35_017_073, 3055) + // Standard Error: 1_587 + .saturating_add(Weight::from_parts(121_130, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into())) } - /// Storage: Elections Candidates (r:1 w:1) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Candidates` (r:1 w:1) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 64]`. fn renounce_candidacy_candidate(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `285 + c * (48 ±0)` // Estimated: `1770 + c * (48 ±0)` - // Minimum execution time: 33_510_000 picoseconds. - Weight::from_parts(34_947_760, 1770) - // Standard Error: 1_781 - .saturating_add(Weight::from_parts(78_851, 0).saturating_mul(c.into())) + // Minimum execution time: 27_263_000 picoseconds. + Weight::from_parts(28_215_666, 1770) + // Standard Error: 1_196 + .saturating_add(Weight::from_parts(86_804, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into())) } - /// Storage: Elections Members (r:1 w:1) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:1) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Members (r:0 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Members` (r:1 w:1) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:1) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:1 w:1) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:0) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:0 w:1) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn renounce_candidacy_members() -> Weight { // Proof Size summary in bytes: - // Measured: `1900` - // Estimated: `3385` - // Minimum execution time: 50_603_000 picoseconds. - Weight::from_parts(51_715_000, 3385) + // Measured: `1933` + // Estimated: `3418` + // Minimum execution time: 41_531_000 picoseconds. + Weight::from_parts(42_937_000, 3418) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Elections RunnersUp (r:1 w:1) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::RunnersUp` (r:1 w:1) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn renounce_candidacy_runners_up() -> Weight { // Proof Size summary in bytes: // Measured: `880` // Estimated: `2365` - // Minimum execution time: 33_441_000 picoseconds. - Weight::from_parts(34_812_000, 2365) + // Minimum execution time: 27_680_000 picoseconds. + Weight::from_parts(28_810_000, 2365) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) fn remove_member_without_replacement() -> Weight { // Proof Size summary in bytes: // Measured: `0` @@ -489,87 +491,90 @@ impl WeightInfo for () { // Minimum execution time: 2_000_000_000_000 picoseconds. Weight::from_parts(2_000_000_000_000, 0) } - /// Storage: Elections Members (r:1 w:1) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Elections RunnersUp (r:1 w:1) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:1 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Members (r:0 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Members` (r:1 w:1) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Elections::RunnersUp` (r:1 w:1) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:1 w:1) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:0) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:0 w:1) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn remove_member_with_replacement() -> Weight { // Proof Size summary in bytes: - // Measured: `1900` + // Measured: `1933` // Estimated: `3593` - // Minimum execution time: 57_289_000 picoseconds. - Weight::from_parts(58_328_000, 3593) + // Minimum execution time: 45_333_000 picoseconds. + Weight::from_parts(46_523_000, 3593) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Elections Voting (r:513 w:512) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:0) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Candidates (r:1 w:0) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Balances Locks (r:512 w:512) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:512 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: System Account (r:512 w:512) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Elections::Voting` (r:257 w:256) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:0) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Candidates` (r:1 w:0) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Balances::Locks` (r:256 w:256) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:256 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:256 w:256) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `v` is `[256, 512]`. /// The range of component `d` is `[0, 256]`. - fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { + fn clean_defunct_voters(v: u32, d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1149 + v * (811 ±0)` - // Estimated: `4621 + v * (3774 ±0)` - // Minimum execution time: 18_774_231_000 picoseconds. - Weight::from_parts(18_933_040_000, 4621) - // Standard Error: 301_534 - .saturating_add(Weight::from_parts(44_306_903, 0).saturating_mul(v.into())) + // Measured: `0 + d * (818 ±0) + v * (57 ±0)` + // Estimated: `24906 + d * (3774 ±1) + v * (24 ±0)` + // Minimum execution time: 5_620_000 picoseconds. + Weight::from_parts(5_817_000, 24906) + // Standard Error: 18_357 + .saturating_add(Weight::from_parts(106_164, 0).saturating_mul(v.into())) + // Standard Error: 39_980 + .saturating_add(Weight::from_parts(52_456_337, 0).saturating_mul(d.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(v.into()))) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(v.into()))) - .saturating_add(Weight::from_parts(0, 3774).saturating_mul(v.into())) + .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(d.into()))) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(d.into()))) + .saturating_add(Weight::from_parts(0, 3774).saturating_mul(d.into())) + .saturating_add(Weight::from_parts(0, 24).saturating_mul(v.into())) } - /// Storage: Elections Candidates (r:1 w:1) - /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:1) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections RunnersUp (r:1 w:1) - /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Elections Voting (r:513 w:0) - /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) - /// Storage: Council Proposals (r:1 w:0) - /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:44 w:44) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Elections ElectionRounds (r:1 w:1) - /// Proof Skipped: Elections ElectionRounds (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Members (r:0 w:1) - /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Council Prime (r:0 w:1) - /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Elections::Candidates` (r:1 w:1) + /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:1) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::RunnersUp` (r:1 w:1) + /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Voting` (r:513 w:0) + /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Council::Proposals` (r:1 w:0) + /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:44 w:44) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Elections::ElectionRounds` (r:1 w:1) + /// Proof: `Elections::ElectionRounds` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Members` (r:0 w:1) + /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Council::Prime` (r:0 w:1) + /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `c` is `[1, 64]`. /// The range of component `v` is `[1, 512]`. /// The range of component `e` is `[512, 8192]`. fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + e * (28 ±0) + v * (606 ±0)` - // Estimated: `178887 + c * (2135 ±7) + e * (12 ±0) + v * (2653 ±6)` - // Minimum execution time: 1_281_877_000 picoseconds. - Weight::from_parts(1_288_147_000, 178887) - // Standard Error: 528_851 - .saturating_add(Weight::from_parts(17_761_407, 0).saturating_mul(v.into())) - // Standard Error: 33_932 - .saturating_add(Weight::from_parts(698_277, 0).saturating_mul(e.into())) + // Estimated: `178920 + c * (2135 ±7) + e * (12 ±0) + v * (2653 ±6)` + // Minimum execution time: 1_082_582_000 picoseconds. + Weight::from_parts(1_084_730_000, 178920) + // Standard Error: 594_096 + .saturating_add(Weight::from_parts(19_096_288, 0).saturating_mul(v.into())) + // Standard Error: 38_118 + .saturating_add(Weight::from_parts(792_945, 0).saturating_mul(e.into())) .saturating_add(RocksDbWeight::get().reads(21_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) diff --git a/substrate/frame/examples/basic/src/lib.rs b/substrate/frame/examples/basic/src/lib.rs index 12cadc969fd..94b2f276e00 100644 --- a/substrate/frame/examples/basic/src/lib.rs +++ b/substrate/frame/examples/basic/src/lib.rs @@ -46,9 +46,10 @@ //! use the [`Config::WeightInfo`] trait to calculate call weights. This can also be overridden, //! as demonstrated by [`Call::set_dummy`]. //! - A private function that performs a storage update. -//! - A simple signed extension implementation (see: [`sp_runtime::traits::SignedExtension`]) which -//! increases the priority of the [`Call::set_dummy`] if it's present and drops any transaction -//! with an encoded length higher than 200 bytes. +//! - A simple transaction extension implementation (see: +//! [`sp_runtime::traits::TransactionExtension`]) which increases the priority of the +//! [`Call::set_dummy`] if it's present and drops any transaction with an encoded length higher +//! than 200 bytes. // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] @@ -64,10 +65,12 @@ use frame_system::ensure_signed; use log::info; use scale_info::TypeInfo; use sp_runtime::{ - traits::{Bounded, DispatchInfoOf, SaturatedConversion, Saturating, SignedExtension}, - transaction_validity::{ - InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + impl_tx_ext_default, + traits::{ + Bounded, DispatchInfoOf, OriginOf, SaturatedConversion, Saturating, TransactionExtension, + TransactionExtensionBase, ValidateResult, }, + transaction_validity::{InvalidTransaction, ValidTransaction}, }; use sp_std::vec::Vec; @@ -440,8 +443,8 @@ impl Pallet { // Similar to other FRAME pallets, your pallet can also define a signed extension and perform some // checks and [pre/post]processing [before/after] the transaction. A signed extension can be any -// decodable type that implements `SignedExtension`. See the trait definition for the full list of -// bounds. As a convention, you can follow this approach to create an extension for your pallet: +// decodable type that implements `TransactionExtension`. See the trait definition for the full list +// of bounds. As a convention, you can follow this approach to create an extension for your pallet: // - If the extension does not carry any data, then use a tuple struct with just a `marker` // (needed for the compiler to accept `T: Config`) will suffice. // - Otherwise, create a tuple struct which contains the external data. Of course, for the entire @@ -455,18 +458,18 @@ impl Pallet { // // Using the extension, you can add some hooks to the life cycle of each transaction. Note that by // default, an extension is applied to all `Call` functions (i.e. all transactions). the `Call` enum -// variant is given to each function of `SignedExtension`. Hence, you can filter based on pallet or -// a particular call if needed. +// variant is given to each function of `TransactionExtension`. Hence, you can filter based on +// pallet or a particular call if needed. // // Some extra information, such as encoded length, some static dispatch info like weight and the // sender of the transaction (if signed) are also provided. // // The full list of hooks that can be added to a signed extension can be found -// [here](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html). +// [here](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.TransactionExtension.html). // // The signed extensions are aggregated in the runtime file of a substrate chain. All extensions // should be aggregated in a tuple and passed to the `CheckedExtrinsic` and `UncheckedExtrinsic` -// types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and +// types defined in the runtime. Lookup `pub type TxExtension = (...)` in `node/runtime` and // `node-template` for an example of this. /// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the @@ -484,52 +487,45 @@ impl core::fmt::Debug for WatchDummy { } } -impl SignedExtension for WatchDummy +impl TransactionExtensionBase for WatchDummy { + const IDENTIFIER: &'static str = "WatchDummy"; + type Implicit = (); +} +impl + TransactionExtension<::RuntimeCall, Context> for WatchDummy where ::RuntimeCall: IsSubType>, { - const IDENTIFIER: &'static str = "WatchDummy"; - type AccountId = T::AccountId; - type Call = ::RuntimeCall; - type AdditionalSigned = (); type Pre = (); - - fn additional_signed(&self) -> core::result::Result<(), TransactionValidityError> { - Ok(()) - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) - } + type Val = (); fn validate( &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, + origin: OriginOf<::RuntimeCall>, + call: &::RuntimeCall, + _info: &DispatchInfoOf<::RuntimeCall>, len: usize, - ) -> TransactionValidity { + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult::RuntimeCall> { // if the transaction is too big, just drop it. if len > 200 { - return InvalidTransaction::ExhaustsResources.into() + return Err(InvalidTransaction::ExhaustsResources.into()) } // check for `set_dummy` - match call.is_sub_type() { + let validity = match call.is_sub_type() { Some(Call::set_dummy { .. }) => { sp_runtime::print("set_dummy was received."); let valid_tx = ValidTransaction { priority: Bounded::max_value(), ..Default::default() }; - Ok(valid_tx) + valid_tx }, - _ => Ok(Default::default()), - } + _ => Default::default(), + }; + Ok((validity, (), origin)) } + impl_tx_ext_default!(::RuntimeCall; Context; prepare); } diff --git a/substrate/frame/examples/basic/src/tests.rs b/substrate/frame/examples/basic/src/tests.rs index 207e46e428d..e460ad0992f 100644 --- a/substrate/frame/examples/basic/src/tests.rs +++ b/substrate/frame/examples/basic/src/tests.rs @@ -27,7 +27,7 @@ use sp_core::H256; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, + traits::{BlakeTwo256, DispatchTransaction, IdentityLookup}, BuildStorage, }; // Reexport crate as its pallet name for construct_runtime. @@ -158,13 +158,16 @@ fn signed_ext_watch_dummy_works() { assert_eq!( WatchDummy::(PhantomData) - .validate(&1, &call, &info, 150) + .validate_only(Some(1).into(), &call, &info, 150) .unwrap() + .0 .priority, u64::MAX, ); assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, &info, 250), + WatchDummy::(PhantomData) + .validate_only(Some(1).into(), &call, &info, 250) + .unwrap_err(), InvalidTransaction::ExhaustsResources.into(), ); }) diff --git a/substrate/frame/examples/offchain-worker/src/tests.rs b/substrate/frame/examples/offchain-worker/src/tests.rs index ea37a2da493..81f2a40840b 100644 --- a/substrate/frame/examples/offchain-worker/src/tests.rs +++ b/substrate/frame/examples/offchain-worker/src/tests.rs @@ -30,7 +30,7 @@ use sp_core::{ use sp_keystore::{testing::MemoryKeystore, Keystore, KeystoreExt}; use sp_runtime::{ - testing::TestXt, + generic::UncheckedExtrinsic, traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentifyAccount, IdentityLookup, Verify}, RuntimeAppPublic, }; @@ -73,7 +73,7 @@ impl frame_system::Config for Test { type MaxConsumers = ConstU32<16>; } -type Extrinsic = TestXt; +type Extrinsic = UncheckedExtrinsic; type AccountId = <::Signer as IdentifyAccount>::AccountId; impl frame_system::offchain::SigningTypes for Test { @@ -99,7 +99,7 @@ where _account: AccountId, nonce: u64, ) -> Option<(RuntimeCall, ::SignaturePayload)> { - Some((call, (nonce, ()))) + Some((call, (nonce, (), ()))) } } @@ -219,8 +219,8 @@ fn should_submit_signed_transaction_on_chain() { let tx = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx = Extrinsic::decode(&mut &*tx).unwrap(); - assert_eq!(tx.signature.unwrap().0, 0); - assert_eq!(tx.call, RuntimeCall::Example(crate::Call::submit_price { price: 15523 })); + assert!(matches!(tx.preamble, sp_runtime::generic::Preamble::Signed(0, (), ()))); + assert_eq!(tx.function, RuntimeCall::Example(crate::Call::submit_price { price: 15523 })); }); } @@ -259,11 +259,11 @@ fn should_submit_unsigned_transaction_on_chain_for_any_account() { // then let tx = pool_state.write().transactions.pop().unwrap(); let tx = Extrinsic::decode(&mut &*tx).unwrap(); - assert_eq!(tx.signature, None); + assert!(tx.is_inherent()); if let RuntimeCall::Example(crate::Call::submit_price_unsigned_with_signed_payload { price_payload: body, signature, - }) = tx.call + }) = tx.function { assert_eq!(body, price_payload); @@ -313,11 +313,11 @@ fn should_submit_unsigned_transaction_on_chain_for_all_accounts() { // then let tx = pool_state.write().transactions.pop().unwrap(); let tx = Extrinsic::decode(&mut &*tx).unwrap(); - assert_eq!(tx.signature, None); + assert!(tx.is_inherent()); if let RuntimeCall::Example(crate::Call::submit_price_unsigned_with_signed_payload { price_payload: body, signature, - }) = tx.call + }) = tx.function { assert_eq!(body, price_payload); @@ -353,9 +353,9 @@ fn should_submit_raw_unsigned_transaction_on_chain() { let tx = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx = Extrinsic::decode(&mut &*tx).unwrap(); - assert_eq!(tx.signature, None); + assert!(tx.is_inherent()); assert_eq!( - tx.call, + tx.function, RuntimeCall::Example(crate::Call::submit_price_unsigned { block_number: 1, price: 15523 diff --git a/substrate/frame/examples/tasks/src/weights.rs b/substrate/frame/examples/tasks/src/weights.rs index 793af6e9622..c9ddea6f9a8 100644 --- a/substrate/frame/examples/tasks/src/weights.rs +++ b/substrate/frame/examples/tasks/src/weights.rs @@ -15,30 +15,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_example_tasks` +//! Autogenerated weights for `tasks_example` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-02, STEPS: `20`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `MacBook.local`, CPU: `` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/release/node-template +// ./target/production/substrate-node // benchmark // pallet -// --chain -// dev -// --pallet -// pallet_example_tasks -// --extrinsic -// * -// --steps -// 20 -// --repeat -// 10 -// --output -// frame/examples/tasks/src/weights.rs +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=tasks_example +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./substrate/frame/examples/tasks/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -48,37 +49,42 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_template. +/// Weight functions needed for `tasks_example`. pub trait WeightInfo { fn add_number_into_total() -> Weight; } -/// Weight functions for `pallet_example_kitchensink`. +/// Weights for `tasks_example` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Kitchensink OtherFoo (r:0 w:1) - /// Proof Skipped: Kitchensink OtherFoo (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TasksExample::Numbers` (r:1 w:1) + /// Proof: `TasksExample::Numbers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TasksExample::Total` (r:1 w:1) + /// Proof: `TasksExample::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn add_number_into_total() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(1_000_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) + // Measured: `149` + // Estimated: `3614` + // Minimum execution time: 5_776_000 picoseconds. + Weight::from_parts(6_178_000, 3614) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } } +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Kitchensink OtherFoo (r:0 w:1) - /// Proof Skipped: Kitchensink OtherFoo (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TasksExample::Numbers` (r:1 w:1) + /// Proof: `TasksExample::Numbers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TasksExample::Total` (r:1 w:1) + /// Proof: `TasksExample::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn add_number_into_total() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(1_000_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Measured: `149` + // Estimated: `3614` + // Minimum execution time: 5_776_000 picoseconds. + Weight::from_parts(6_178_000, 3614) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/substrate/frame/executive/src/tests.rs b/substrate/frame/executive/src/tests.rs index 70b55f6e855..a3f70a9fc3c 100644 --- a/substrate/frame/executive/src/tests.rs +++ b/substrate/frame/executive/src/tests.rs @@ -327,10 +327,42 @@ impl frame_system::Config for Runtime { type Balance = u64; +pub struct BalancesWeights; +impl pallet_balances::WeightInfo for BalancesWeights { + fn transfer_allow_death() -> Weight { + Weight::from_parts(25, 0) + } + fn transfer_keep_alive() -> Weight { + Weight::zero() + } + fn force_set_balance_creating() -> Weight { + Weight::zero() + } + fn force_set_balance_killing() -> Weight { + Weight::zero() + } + fn force_transfer() -> Weight { + Weight::zero() + } + fn transfer_all() -> Weight { + Weight::zero() + } + fn force_unreserve() -> Weight { + Weight::zero() + } + fn upgrade_accounts(_u: u32) -> Weight { + Weight::zero() + } + fn force_adjust_total_issuance() -> Weight { + Weight::zero() + } +} + #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for Runtime { type Balance = Balance; type AccountStore = System; + type WeightInfo = BalancesWeights; } parameter_types! { @@ -343,6 +375,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = IdentityFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = (); + type WeightInfo = (); } impl custom::Config for Runtime {} @@ -355,19 +388,46 @@ impl frame_support::traits::Get for RuntimeVersion { } } +#[derive(Clone, Debug, Encode, codec::Decode, PartialEq, Eq, scale_info::TypeInfo)] +pub struct AccountU64(u64); +impl sp_runtime::traits::IdentifyAccount for AccountU64 { + type AccountId = u64; + fn into_account(self) -> u64 { + self.0 + } +} + +impl sp_runtime::traits::Verify for AccountU64 { + type Signer = AccountU64; + fn verify>( + &self, + _msg: L, + _signer: &::AccountId, + ) -> bool { + true + } +} + +impl From for AccountU64 { + fn from(value: u64) -> Self { + Self(value) + } +} + parameter_types! { pub static RuntimeVersionTestValues: sp_version::RuntimeVersion = Default::default(); } -type SignedExtra = ( +type TxExtension = ( frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, ); -type TestXt = sp_runtime::testing::TestXt; -type TestBlock = Block; +type UncheckedXt = + sp_runtime::generic::UncheckedExtrinsic; +type TestBlock = Block; // Will contain `true` when the custom runtime logic was called. const CUSTOM_ON_RUNTIME_KEY: &[u8] = b":custom:on_runtime"; @@ -387,7 +447,7 @@ impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { type Executive = super::Executive< Runtime, - Block, + Block, ChainContext, Runtime, AllPalletsWithSystem, @@ -462,17 +522,14 @@ impl MultiStepMigrator for MockedModeGetter { } } -fn extra(nonce: u64, fee: Balance) -> SignedExtra { +fn tx_ext(nonce: u64, fee: Balance) -> TxExtension { ( frame_system::CheckEra::from(Era::Immortal), frame_system::CheckNonce::from(nonce), frame_system::CheckWeight::new(), pallet_transaction_payment::ChargeTransactionPayment::from(fee), ) -} - -fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { - Some((who, extra(nonce, fee))) + .into() } fn call_transfer(dest: u64, value: u64) -> RuntimeCall { @@ -485,7 +542,7 @@ fn balance_transfer_dispatch_works() { pallet_balances::GenesisConfig:: { balances: vec![(1, 211)] } .assimilate_storage(&mut t) .unwrap(); - let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0)); + let xt = UncheckedXt::new_signed(call_transfer(2, 69), 1, 1.into(), tx_ext(0, 0)); let weight = xt.get_dispatch_info().weight + ::BlockWeights::get() .get(DispatchClass::Normal) @@ -596,7 +653,7 @@ fn block_import_of_bad_extrinsic_root_fails() { fn bad_extrinsic_not_inserted() { let mut t = new_test_ext(1); // bad nonce check! - let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0)); + let xt = UncheckedXt::new_signed(call_transfer(33, 69), 1, 1.into(), tx_ext(30, 0)); t.execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); assert_err!( @@ -610,27 +667,24 @@ fn bad_extrinsic_not_inserted() { #[test] fn block_weight_limit_enforced() { let mut t = new_test_ext(10000); - // given: TestXt uses the encoded len as fixed Len: - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - let encoded = xt.encode(); - let encoded_len = encoded.len() as u64; + let transfer_weight = + <::WeightInfo as pallet_balances::WeightInfo>::transfer_allow_death(); // on_initialize weight + base block execution weight let block_weights = ::BlockWeights::get(); let base_block_weight = Weight::from_parts(175, 0) + block_weights.base_block; let limit = block_weights.get(DispatchClass::Normal).max_total.unwrap() - base_block_weight; - let num_to_exhaust_block = limit.ref_time() / (encoded_len + 5); + let num_to_exhaust_block = limit.ref_time() / (transfer_weight.ref_time() + 5); t.execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); // Base block execution weight + `on_initialize` weight from the custom module. assert_eq!(>::block_weight().total(), base_block_weight); for nonce in 0..=num_to_exhaust_block { - let xt = TestXt::new( + let xt = UncheckedXt::new_signed( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, nonce.into(), 0), + 1, + 1.into(), + tx_ext(nonce.into(), 0), ); let res = Executive::apply_extrinsic(xt); if nonce != num_to_exhaust_block { @@ -638,7 +692,8 @@ fn block_weight_limit_enforced() { assert_eq!( >::block_weight().total(), //--------------------- on_initialize + block_execution + extrinsic_base weight - Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, + Weight::from_parts((transfer_weight.ref_time() + 5) * (nonce + 1), 0) + + base_block_weight, ); assert_eq!( >::extrinsic_index(), @@ -653,19 +708,26 @@ fn block_weight_limit_enforced() { #[test] fn block_weight_and_size_is_stored_per_tx() { - let xt = TestXt::new( + let xt = UncheckedXt::new_signed( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), + 1, + 1.into(), + tx_ext(0, 0), ); - let x1 = TestXt::new( + let x1 = UncheckedXt::new_signed( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 1, 0), + 1, + 1.into(), + tx_ext(1, 0), ); - let x2 = TestXt::new( + let x2 = UncheckedXt::new_signed( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 2, 0), + 1, + 1.into(), + tx_ext(2, 0), ); let len = xt.clone().encode().len() as u32; + let transfer_weight = <::WeightInfo as pallet_balances::WeightInfo>::transfer_allow_death(); let mut t = new_test_ext(1); t.execute_with(|| { // Block execution weight + on_initialize weight from custom module @@ -681,8 +743,7 @@ fn block_weight_and_size_is_stored_per_tx() { assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); - // default weight for `TestXt` == encoded length. - let extrinsic_weight = Weight::from_parts(len as u64, 0) + + let extrinsic_weight = transfer_weight + ::BlockWeights::get() .get(DispatchClass::Normal) .base_extrinsic; @@ -707,8 +768,8 @@ fn block_weight_and_size_is_stored_per_tx() { #[test] fn validate_unsigned() { - let valid = TestXt::new(RuntimeCall::Custom(custom::Call::allowed_unsigned {}), None); - let invalid = TestXt::new(RuntimeCall::Custom(custom::Call::unallowed_unsigned {}), None); + let valid = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::allowed_unsigned {})); + let invalid = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::unallowed_unsigned {})); let mut t = new_test_ext(1); t.execute_with(|| { @@ -745,9 +806,11 @@ fn can_not_pay_for_tx_fee_on_full_lock() { t.execute_with(|| { as fungible::MutateFreeze>::set_freeze(&(), &1, 110) .unwrap(); - let xt = TestXt::new( + let xt = UncheckedXt::new_signed( RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), - sign_extra(1, 0, 0), + 1, + 1.into(), + tx_ext(0, 0), ); Executive::initialize_block(&Header::new_from_number(1)); @@ -872,9 +935,11 @@ fn event_from_runtime_upgrade_is_included() { /// used through the `ExecuteBlock` trait. #[test] fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { - let xt = TestXt::new( + let xt = UncheckedXt::new_signed( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), + 1, + 1.into(), + tx_ext(0, 0), ); let header = new_test_ext(1).execute_with(|| { @@ -902,7 +967,10 @@ fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } }); - >>::execute_block(Block::new(header, vec![xt])); + >>::execute_block(Block::new( + header, + vec![xt], + )); assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); @@ -968,7 +1036,7 @@ fn offchain_worker_works_as_expected() { #[test] fn calculating_storage_root_twice_works() { let call = RuntimeCall::Custom(custom::Call::calculate_storage_root {}); - let xt = TestXt::new(call, sign_extra(1, 0, 0)); + let xt = UncheckedXt::new_signed(call, 1, 1.into(), tx_ext(0, 0)); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -987,11 +1055,13 @@ fn calculating_storage_root_twice_works() { #[test] #[should_panic(expected = "Invalid inherent position for extrinsic at index 1")] fn invalid_inherent_position_fail() { - let xt1 = TestXt::new( + let xt1 = UncheckedXt::new_signed( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), + 1, + 1.into(), + tx_ext(0, 0), ); - let xt2 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1010,8 +1080,8 @@ fn invalid_inherent_position_fail() { #[test] fn valid_inherents_position_works() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1031,7 +1101,12 @@ fn valid_inherents_position_works() { #[test] #[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] fn invalid_inherents_fail_block_execution() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), sign_extra(1, 0, 0)); + let xt1 = UncheckedXt::new_signed( + RuntimeCall::Custom(custom::Call::inherent {}), + 1, + 1.into(), + tx_ext(0, 0), + ); new_test_ext(1).execute_with(|| { Executive::execute_block(Block::new( @@ -1044,7 +1119,7 @@ fn invalid_inherents_fail_block_execution() { // Inherents are created by the runtime and don't need to be validated. #[test] fn inherents_fail_validate_block() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); new_test_ext(1).execute_with(|| { assert_eq!( @@ -1058,7 +1133,7 @@ fn inherents_fail_validate_block() { /// Inherents still work while `initialize_block` forbids transactions. #[test] fn inherents_ok_while_exts_forbidden_works() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); @@ -1078,8 +1153,8 @@ fn inherents_ok_while_exts_forbidden_works() { #[test] #[should_panic = "Only inherents are allowed in this block"] fn transactions_in_only_inherents_block_errors() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); @@ -1099,8 +1174,8 @@ fn transactions_in_only_inherents_block_errors() { /// Same as above but no error. #[test] fn transactions_in_normal_block_works() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); @@ -1120,8 +1195,8 @@ fn transactions_in_normal_block_works() { #[test] #[cfg(feature = "try-runtime")] fn try_execute_block_works() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); @@ -1148,8 +1223,8 @@ fn try_execute_block_works() { #[cfg(feature = "try-runtime")] #[should_panic = "Only inherents allowed"] fn try_execute_tx_forbidden_errors() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1176,9 +1251,9 @@ fn try_execute_tx_forbidden_errors() { /// Check that `ensure_inherents_are_first` reports the correct indices. #[test] fn ensure_inherents_are_first_works() { - let in1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); - let in2 = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + let in1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let in2 = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::inherent {})); + let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); // Mocked empty header: let header = new_test_ext(1).execute_with(|| { @@ -1256,18 +1331,20 @@ fn callbacks_in_block_execution_works_inner(mbms_active: bool) { for i in 0..n_in { let xt = if i % 2 == 0 { - TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None) + UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})) } else { - TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None) + UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::optional_inherent {})) }; Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); extrinsics.push(xt); } for t in 0..n_tx { - let xt = TestXt::new( + let xt = UncheckedXt::new_signed( RuntimeCall::Custom2(custom2::Call::some_call {}), - sign_extra(1, t as u64, 0), + 1, + 1.into(), + tx_ext(t as u64, 0), ); // Extrinsics can be applied even when MBMs are active. Only the `execute_block` // will reject it. @@ -1307,8 +1384,13 @@ fn callbacks_in_block_execution_works_inner(mbms_active: bool) { #[test] fn post_inherent_called_after_all_inherents() { - let in1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); - let xt1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::some_call {}), sign_extra(1, 0, 0)); + let in1 = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::inherent {})); + let xt1 = UncheckedXt::new_signed( + RuntimeCall::Custom2(custom2::Call::some_call {}), + 1, + 1.into(), + tx_ext(0, 0), + ); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1342,8 +1424,13 @@ fn post_inherent_called_after_all_inherents() { /// Regression test for AppSec finding #40. #[test] fn post_inherent_called_after_all_optional_inherents() { - let in1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None); - let xt1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::some_call {}), sign_extra(1, 0, 0)); + let in1 = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::optional_inherent {})); + let xt1 = UncheckedXt::new_signed( + RuntimeCall::Custom2(custom2::Call::some_call {}), + 1, + 1.into(), + tx_ext(0, 0), + ); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1376,14 +1463,14 @@ fn post_inherent_called_after_all_optional_inherents() { #[test] fn is_inherent_works() { - let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); + let ext = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::inherent {})); assert!(Runtime::is_inherent(&ext)); - let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None); + let ext = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::optional_inherent {})); assert!(Runtime::is_inherent(&ext)); - let ext = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + let ext = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); assert!(!Runtime::is_inherent(&ext)); - let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::allowed_unsigned {}), None); + let ext = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::allowed_unsigned {})); assert!(!Runtime::is_inherent(&ext), "Unsigned ext are not automatically inherents"); } diff --git a/substrate/frame/fast-unstake/src/weights.rs b/substrate/frame/fast-unstake/src/weights.rs index 9c25a409f74..d783ba921bf 100644 --- a/substrate/frame/fast-unstake/src/weights.rs +++ b/substrate/frame/fast-unstake/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_fast_unstake +//! Autogenerated weights for `pallet_fast_unstake` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/fast-unstake/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/fast-unstake/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_fast_unstake. +/// Weight functions needed for `pallet_fast_unstake`. pub trait WeightInfo { fn on_idle_unstake(b: u32, ) -> Weight; fn on_idle_check(v: u32, b: u32, ) -> Weight; @@ -59,301 +58,305 @@ pub trait WeightInfo { fn control() -> Weight; } -/// Weights for pallet_fast_unstake using the Substrate node and recommended hardware. +/// Weights for `pallet_fast_unstake` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ValidatorCount (r:1 w:0) - /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: FastUnstake Head (r:1 w:1) - /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) - /// Storage: FastUnstake CounterForQueue (r:1 w:0) - /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:64 w:0) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Bonded (r:64 w:64) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:64 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:64 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: System Account (r:64 w:64) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:64 w:64) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:64 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:0 w:64) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:64) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::ValidatorCount` (r:1 w:0) + /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Head` (r:1 w:1) + /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::CounterForQueue` (r:1 w:0) + /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::SlashingSpans` (r:64 w:0) + /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::Bonded` (r:64 w:64) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:64 w:64) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:64 w:64) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:64 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:64 w:64) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:64 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:64 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:64) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// The range of component `b` is `[1, 64]`. fn on_idle_unstake(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1378 + b * (343 ±0)` + // Measured: `1475 + b * (452 ±0)` // Estimated: `7253 + b * (3774 ±0)` - // Minimum execution time: 92_847_000 picoseconds. - Weight::from_parts(42_300_813, 7253) - // Standard Error: 40_514 - .saturating_add(Weight::from_parts(58_412_402, 0).saturating_mul(b.into())) + // Minimum execution time: 89_005_000 picoseconds. + Weight::from_parts(50_257_055, 7253) + // Standard Error: 68_836 + .saturating_add(Weight::from_parts(57_329_950, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().reads((8_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 3774).saturating_mul(b.into())) } - /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ValidatorCount (r:1 w:0) - /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: FastUnstake Head (r:1 w:1) - /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) - /// Storage: FastUnstake CounterForQueue (r:1 w:0) - /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasStakers (r:257 w:0) - /// Proof Skipped: Staking ErasStakers (max_values: None, max_size: None, mode: Measured) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::ValidatorCount` (r:1 w:0) + /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Head` (r:1 w:1) + /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::CounterForQueue` (r:1 w:0) + /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::ErasStakers` (r:1 w:0) + /// Proof: `Staking::ErasStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::ErasStakersPaged` (r:257 w:0) + /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `v` is `[1, 256]`. /// The range of component `b` is `[1, 64]`. fn on_idle_check(v: u32, b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1546 + b * (48 ±0) + v * (10037 ±0)` - // Estimated: `7253 + b * (49 ±0) + v * (12513 ±0)` - // Minimum execution time: 1_685_784_000 picoseconds. - Weight::from_parts(1_693_370_000, 7253) - // Standard Error: 13_295_842 - .saturating_add(Weight::from_parts(425_349_148, 0).saturating_mul(v.into())) - // Standard Error: 53_198_180 - .saturating_add(Weight::from_parts(1_673_328_444, 0).saturating_mul(b.into())) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Measured: `1879 + b * (55 ±0) + v * (10055 ±0)` + // Estimated: `7253 + b * (56 ±0) + v * (12531 ±0)` + // Minimum execution time: 1_737_131_000 picoseconds. + Weight::from_parts(1_746_770_000, 7253) + // Standard Error: 13_401_143 + .saturating_add(Weight::from_parts(426_946_450, 0).saturating_mul(v.into())) + // Standard Error: 53_619_501 + .saturating_add(Weight::from_parts(1_664_681_508, 0).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 49).saturating_mul(b.into())) - .saturating_add(Weight::from_parts(0, 12513).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(0, 56).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(0, 12531).saturating_mul(v.into())) } - /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: FastUnstake Queue (r:1 w:1) - /// Proof: FastUnstake Queue (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) - /// Storage: FastUnstake Head (r:1 w:0) - /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: FastUnstake CounterForQueue (r:1 w:1) - /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Queue` (r:1 w:1) + /// Proof: `FastUnstake::Queue` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Head` (r:1 w:0) + /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:1 w:1) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::CounterForQueue` (r:1 w:1) + /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn register_fast_unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `1964` + // Measured: `1955` // Estimated: `7253` - // Minimum execution time: 125_512_000 picoseconds. - Weight::from_parts(129_562_000, 7253) + // Minimum execution time: 112_632_000 picoseconds. + Weight::from_parts(117_267_000, 7253) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } - /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: FastUnstake Queue (r:1 w:1) - /// Proof: FastUnstake Queue (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) - /// Storage: FastUnstake Head (r:1 w:0) - /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) - /// Storage: FastUnstake CounterForQueue (r:1 w:1) - /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Queue` (r:1 w:1) + /// Proof: `FastUnstake::Queue` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Head` (r:1 w:0) + /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::CounterForQueue` (r:1 w:1) + /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn deregister() -> Weight { // Proof Size summary in bytes: - // Measured: `1223` + // Measured: `1251` // Estimated: `7253` - // Minimum execution time: 43_943_000 picoseconds. - Weight::from_parts(45_842_000, 7253) + // Minimum execution time: 39_253_000 picoseconds. + Weight::from_parts(40_053_000, 7253) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:0 w:1) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn control() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_677_000 picoseconds. - Weight::from_parts(2_849_000, 0) + // Minimum execution time: 2_386_000 picoseconds. + Weight::from_parts(2_508_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ValidatorCount (r:1 w:0) - /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: FastUnstake Head (r:1 w:1) - /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) - /// Storage: FastUnstake CounterForQueue (r:1 w:0) - /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking SlashingSpans (r:64 w:0) - /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) - /// Storage: Staking Bonded (r:64 w:64) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:64 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:64 w:0) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: System Account (r:64 w:64) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:64 w:64) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:64 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:0 w:64) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Staking Payee (r:0 w:64) - /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::ValidatorCount` (r:1 w:0) + /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Head` (r:1 w:1) + /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::CounterForQueue` (r:1 w:0) + /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::SlashingSpans` (r:64 w:0) + /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::Bonded` (r:64 w:64) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:64 w:64) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:64 w:64) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:64 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:64 w:64) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:64 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:64 w:0) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::Payee` (r:0 w:64) + /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// The range of component `b` is `[1, 64]`. fn on_idle_unstake(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1378 + b * (343 ±0)` + // Measured: `1475 + b * (452 ±0)` // Estimated: `7253 + b * (3774 ±0)` - // Minimum execution time: 92_847_000 picoseconds. - Weight::from_parts(42_300_813, 7253) - // Standard Error: 40_514 - .saturating_add(Weight::from_parts(58_412_402, 0).saturating_mul(b.into())) + // Minimum execution time: 89_005_000 picoseconds. + Weight::from_parts(50_257_055, 7253) + // Standard Error: 68_836 + .saturating_add(Weight::from_parts(57_329_950, 0).saturating_mul(b.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(b.into()))) + .saturating_add(RocksDbWeight::get().reads((8_u64).saturating_mul(b.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((5_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 3774).saturating_mul(b.into())) } - /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ValidatorCount (r:1 w:0) - /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: FastUnstake Head (r:1 w:1) - /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) - /// Storage: FastUnstake CounterForQueue (r:1 w:0) - /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) - /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking ErasStakers (r:257 w:0) - /// Proof Skipped: Staking ErasStakers (max_values: None, max_size: None, mode: Measured) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::ValidatorCount` (r:1 w:0) + /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Head` (r:1 w:1) + /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::CounterForQueue` (r:1 w:0) + /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) + /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::ErasStakers` (r:1 w:0) + /// Proof: `Staking::ErasStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::ErasStakersPaged` (r:257 w:0) + /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `v` is `[1, 256]`. /// The range of component `b` is `[1, 64]`. fn on_idle_check(v: u32, b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1546 + b * (48 ±0) + v * (10037 ±0)` - // Estimated: `7253 + b * (49 ±0) + v * (12513 ±0)` - // Minimum execution time: 1_685_784_000 picoseconds. - Weight::from_parts(1_693_370_000, 7253) - // Standard Error: 13_295_842 - .saturating_add(Weight::from_parts(425_349_148, 0).saturating_mul(v.into())) - // Standard Error: 53_198_180 - .saturating_add(Weight::from_parts(1_673_328_444, 0).saturating_mul(b.into())) - .saturating_add(RocksDbWeight::get().reads(7_u64)) + // Measured: `1879 + b * (55 ±0) + v * (10055 ±0)` + // Estimated: `7253 + b * (56 ±0) + v * (12531 ±0)` + // Minimum execution time: 1_737_131_000 picoseconds. + Weight::from_parts(1_746_770_000, 7253) + // Standard Error: 13_401_143 + .saturating_add(Weight::from_parts(426_946_450, 0).saturating_mul(v.into())) + // Standard Error: 53_619_501 + .saturating_add(Weight::from_parts(1_664_681_508, 0).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 49).saturating_mul(b.into())) - .saturating_add(Weight::from_parts(0, 12513).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(0, 56).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(0, 12531).saturating_mul(v.into())) } - /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:1) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: FastUnstake Queue (r:1 w:1) - /// Proof: FastUnstake Queue (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) - /// Storage: FastUnstake Head (r:1 w:0) - /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) - /// Storage: Staking Bonded (r:1 w:0) - /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) - /// Storage: Staking Validators (r:1 w:0) - /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) - /// Storage: Staking Nominators (r:1 w:1) - /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) - /// Storage: Staking CounterForNominators (r:1 w:1) - /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: VoterList ListNodes (r:1 w:1) - /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) - /// Storage: VoterList ListBags (r:1 w:1) - /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) - /// Storage: VoterList CounterForListNodes (r:1 w:1) - /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking CurrentEra (r:1 w:0) - /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - /// Storage: Balances Freezes (r:1 w:0) - /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: FastUnstake CounterForQueue (r:1 w:1) - /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Queue` (r:1 w:1) + /// Proof: `FastUnstake::Queue` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Head` (r:1 w:0) + /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:1 w:1) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::CounterForQueue` (r:1 w:1) + /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn register_fast_unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `1964` + // Measured: `1955` // Estimated: `7253` - // Minimum execution time: 125_512_000 picoseconds. - Weight::from_parts(129_562_000, 7253) + // Minimum execution time: 112_632_000 picoseconds. + Weight::from_parts(117_267_000, 7253) .saturating_add(RocksDbWeight::get().reads(15_u64)) .saturating_add(RocksDbWeight::get().writes(9_u64)) } - /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: FastUnstake Queue (r:1 w:1) - /// Proof: FastUnstake Queue (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) - /// Storage: FastUnstake Head (r:1 w:0) - /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) - /// Storage: FastUnstake CounterForQueue (r:1 w:1) - /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Queue` (r:1 w:1) + /// Proof: `FastUnstake::Queue` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::Head` (r:1 w:0) + /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) + /// Storage: `FastUnstake::CounterForQueue` (r:1 w:1) + /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn deregister() -> Weight { // Proof Size summary in bytes: - // Measured: `1223` + // Measured: `1251` // Estimated: `7253` - // Minimum execution time: 43_943_000 picoseconds. - Weight::from_parts(45_842_000, 7253) + // Minimum execution time: 39_253_000 picoseconds. + Weight::from_parts(40_053_000, 7253) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) - /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:0 w:1) + /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn control() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_677_000 picoseconds. - Weight::from_parts(2_849_000, 0) + // Minimum execution time: 2_386_000 picoseconds. + Weight::from_parts(2_508_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/glutton/src/weights.rs b/substrate/frame/glutton/src/weights.rs index cbc0fb022f5..b2e28dc488a 100644 --- a/substrate/frame/glutton/src/weights.rs +++ b/substrate/frame/glutton/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_glutton +//! Autogenerated weights for `pallet_glutton` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/glutton/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/glutton/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_glutton. +/// Weight functions needed for `pallet_glutton`. pub trait WeightInfo { fn initialize_pallet_grow(n: u32, ) -> Weight; fn initialize_pallet_shrink(n: u32, ) -> Weight; @@ -63,39 +62,39 @@ pub trait WeightInfo { fn set_storage() -> Weight; } -/// Weights for pallet_glutton using the Substrate node and recommended hardware. +/// Weights for `pallet_glutton` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Glutton TrashDataCount (r:1 w:1) - /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Glutton TrashData (r:0 w:1000) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::TrashDataCount` (r:1 w:1) + /// Proof: `Glutton::TrashDataCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Glutton::TrashData` (r:0 w:1000) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn initialize_pallet_grow(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1489` - // Minimum execution time: 11_488_000 picoseconds. - Weight::from_parts(93_073_710, 1489) - // Standard Error: 22_390 - .saturating_add(Weight::from_parts(9_572_012, 0).saturating_mul(n.into())) + // Minimum execution time: 8_443_000 picoseconds. + Weight::from_parts(103_698_651, 1489) + // Standard Error: 21_777 + .saturating_add(Weight::from_parts(9_529_476, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) } - /// Storage: Glutton TrashDataCount (r:1 w:1) - /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Glutton TrashData (r:0 w:1000) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::TrashDataCount` (r:1 w:1) + /// Proof: `Glutton::TrashDataCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Glutton::TrashData` (r:0 w:1000) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn initialize_pallet_shrink(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `119` // Estimated: `1489` - // Minimum execution time: 11_378_000 picoseconds. - Weight::from_parts(5_591_508, 1489) - // Standard Error: 1_592 - .saturating_add(Weight::from_parts(1_163_758, 0).saturating_mul(n.into())) + // Minimum execution time: 8_343_000 picoseconds. + Weight::from_parts(304_498, 1489) + // Standard Error: 1_568 + .saturating_add(Weight::from_parts(1_146_553, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -105,119 +104,119 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 669_000 picoseconds. - Weight::from_parts(990_745, 0) - // Standard Error: 10 - .saturating_add(Weight::from_parts(105_224, 0).saturating_mul(i.into())) + // Minimum execution time: 656_000 picoseconds. + Weight::from_parts(1_875_128, 0) + // Standard Error: 8 + .saturating_add(Weight::from_parts(103_381, 0).saturating_mul(i.into())) } - /// Storage: Glutton TrashData (r:5000 w:0) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::TrashData` (r:5000 w:0) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) /// The range of component `i` is `[0, 5000]`. fn waste_proof_size_some(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `119114 + i * (1022 ±0)` // Estimated: `990 + i * (3016 ±0)` - // Minimum execution time: 435_000 picoseconds. - Weight::from_parts(66_547_542, 990) - // Standard Error: 4_557 - .saturating_add(Weight::from_parts(5_851_324, 0).saturating_mul(i.into())) + // Minimum execution time: 454_000 picoseconds. + Weight::from_parts(521_000, 990) + // Standard Error: 1_940 + .saturating_add(Weight::from_parts(5_729_831, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3016).saturating_mul(i.into())) } - /// Storage: Glutton Storage (r:1 w:0) - /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton Compute (r:1 w:0) - /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton TrashData (r:1737 w:0) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::Storage` (r:1 w:0) + /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::Compute` (r:1 w:0) + /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::TrashData` (r:1737 w:0) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) fn on_idle_high_proof_waste() -> Weight { // Proof Size summary in bytes: // Measured: `1900497` // Estimated: `5239782` - // Minimum execution time: 67_699_845_000 picoseconds. - Weight::from_parts(67_893_204_000, 5239782) + // Minimum execution time: 55_403_909_000 picoseconds. + Weight::from_parts(55_472_412_000, 5239782) .saturating_add(T::DbWeight::get().reads(1739_u64)) } - /// Storage: Glutton Storage (r:1 w:0) - /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton Compute (r:1 w:0) - /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton TrashData (r:5 w:0) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::Storage` (r:1 w:0) + /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::Compute` (r:1 w:0) + /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::TrashData` (r:5 w:0) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) fn on_idle_low_proof_waste() -> Weight { // Proof Size summary in bytes: // Measured: `9547` // Estimated: `16070` - // Minimum execution time: 122_297_527_000 picoseconds. - Weight::from_parts(122_394_818_000, 16070) + // Minimum execution time: 97_959_007_000 picoseconds. + Weight::from_parts(98_030_476_000, 16070) .saturating_add(T::DbWeight::get().reads(7_u64)) } - /// Storage: Glutton Storage (r:1 w:0) - /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton Compute (r:1 w:0) - /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Glutton::Storage` (r:1 w:0) + /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::Compute` (r:1 w:0) + /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn empty_on_idle() -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1493` - // Minimum execution time: 5_882_000 picoseconds. - Weight::from_parts(6_138_000, 1493) + // Minimum execution time: 5_011_000 picoseconds. + Weight::from_parts(5_183_000, 1493) .saturating_add(T::DbWeight::get().reads(2_u64)) } - /// Storage: Glutton Compute (r:0 w:1) - /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Glutton::Compute` (r:0 w:1) + /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn set_compute() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_830_000 picoseconds. - Weight::from_parts(8_366_000, 0) + // Minimum execution time: 5_591_000 picoseconds. + Weight::from_parts(5_970_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Glutton Storage (r:0 w:1) - /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Glutton::Storage` (r:0 w:1) + /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn set_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_933_000 picoseconds. - Weight::from_parts(8_213_000, 0) + // Minimum execution time: 5_689_000 picoseconds. + Weight::from_parts(6_038_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Glutton TrashDataCount (r:1 w:1) - /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Glutton TrashData (r:0 w:1000) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::TrashDataCount` (r:1 w:1) + /// Proof: `Glutton::TrashDataCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Glutton::TrashData` (r:0 w:1000) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn initialize_pallet_grow(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1489` - // Minimum execution time: 11_488_000 picoseconds. - Weight::from_parts(93_073_710, 1489) - // Standard Error: 22_390 - .saturating_add(Weight::from_parts(9_572_012, 0).saturating_mul(n.into())) + // Minimum execution time: 8_443_000 picoseconds. + Weight::from_parts(103_698_651, 1489) + // Standard Error: 21_777 + .saturating_add(Weight::from_parts(9_529_476, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) } - /// Storage: Glutton TrashDataCount (r:1 w:1) - /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Glutton TrashData (r:0 w:1000) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::TrashDataCount` (r:1 w:1) + /// Proof: `Glutton::TrashDataCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Glutton::TrashData` (r:0 w:1000) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn initialize_pallet_shrink(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `119` // Estimated: `1489` - // Minimum execution time: 11_378_000 picoseconds. - Weight::from_parts(5_591_508, 1489) - // Standard Error: 1_592 - .saturating_add(Weight::from_parts(1_163_758, 0).saturating_mul(n.into())) + // Minimum execution time: 8_343_000 picoseconds. + Weight::from_parts(304_498, 1489) + // Standard Error: 1_568 + .saturating_add(Weight::from_parts(1_146_553, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -227,83 +226,83 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 669_000 picoseconds. - Weight::from_parts(990_745, 0) - // Standard Error: 10 - .saturating_add(Weight::from_parts(105_224, 0).saturating_mul(i.into())) + // Minimum execution time: 656_000 picoseconds. + Weight::from_parts(1_875_128, 0) + // Standard Error: 8 + .saturating_add(Weight::from_parts(103_381, 0).saturating_mul(i.into())) } - /// Storage: Glutton TrashData (r:5000 w:0) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::TrashData` (r:5000 w:0) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) /// The range of component `i` is `[0, 5000]`. fn waste_proof_size_some(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `119114 + i * (1022 ±0)` // Estimated: `990 + i * (3016 ±0)` - // Minimum execution time: 435_000 picoseconds. - Weight::from_parts(66_547_542, 990) - // Standard Error: 4_557 - .saturating_add(Weight::from_parts(5_851_324, 0).saturating_mul(i.into())) + // Minimum execution time: 454_000 picoseconds. + Weight::from_parts(521_000, 990) + // Standard Error: 1_940 + .saturating_add(Weight::from_parts(5_729_831, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3016).saturating_mul(i.into())) } - /// Storage: Glutton Storage (r:1 w:0) - /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton Compute (r:1 w:0) - /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton TrashData (r:1737 w:0) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::Storage` (r:1 w:0) + /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::Compute` (r:1 w:0) + /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::TrashData` (r:1737 w:0) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) fn on_idle_high_proof_waste() -> Weight { // Proof Size summary in bytes: // Measured: `1900497` // Estimated: `5239782` - // Minimum execution time: 67_699_845_000 picoseconds. - Weight::from_parts(67_893_204_000, 5239782) + // Minimum execution time: 55_403_909_000 picoseconds. + Weight::from_parts(55_472_412_000, 5239782) .saturating_add(RocksDbWeight::get().reads(1739_u64)) } - /// Storage: Glutton Storage (r:1 w:0) - /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton Compute (r:1 w:0) - /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton TrashData (r:5 w:0) - /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// Storage: `Glutton::Storage` (r:1 w:0) + /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::Compute` (r:1 w:0) + /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::TrashData` (r:5 w:0) + /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) fn on_idle_low_proof_waste() -> Weight { // Proof Size summary in bytes: // Measured: `9547` // Estimated: `16070` - // Minimum execution time: 122_297_527_000 picoseconds. - Weight::from_parts(122_394_818_000, 16070) + // Minimum execution time: 97_959_007_000 picoseconds. + Weight::from_parts(98_030_476_000, 16070) .saturating_add(RocksDbWeight::get().reads(7_u64)) } - /// Storage: Glutton Storage (r:1 w:0) - /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Glutton Compute (r:1 w:0) - /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Glutton::Storage` (r:1 w:0) + /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Glutton::Compute` (r:1 w:0) + /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn empty_on_idle() -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1493` - // Minimum execution time: 5_882_000 picoseconds. - Weight::from_parts(6_138_000, 1493) + // Minimum execution time: 5_011_000 picoseconds. + Weight::from_parts(5_183_000, 1493) .saturating_add(RocksDbWeight::get().reads(2_u64)) } - /// Storage: Glutton Compute (r:0 w:1) - /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Glutton::Compute` (r:0 w:1) + /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn set_compute() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_830_000 picoseconds. - Weight::from_parts(8_366_000, 0) + // Minimum execution time: 5_591_000 picoseconds. + Weight::from_parts(5_970_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Glutton Storage (r:0 w:1) - /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Glutton::Storage` (r:0 w:1) + /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn set_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_933_000 picoseconds. - Weight::from_parts(8_213_000, 0) + // Minimum execution time: 5_689_000 picoseconds. + Weight::from_parts(6_038_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/grandpa/src/mock.rs b/substrate/frame/grandpa/src/mock.rs index 5d48f974c31..e1be487dbb7 100644 --- a/substrate/frame/grandpa/src/mock.rs +++ b/substrate/frame/grandpa/src/mock.rs @@ -35,11 +35,8 @@ use sp_consensus_grandpa::{RoundNumber, SetId, GRANDPA_ENGINE_ID}; use sp_core::{crypto::KeyTypeId, H256}; use sp_keyring::Ed25519Keyring; use sp_runtime::{ - curve::PiecewiseLinear, - impl_opaque_keys, - testing::{TestXt, UintAuthorityId}, - traits::OpaqueKeys, - BuildStorage, DigestItem, Perbill, + curve::PiecewiseLinear, generic::UncheckedExtrinsic, impl_opaque_keys, + testing::UintAuthorityId, traits::OpaqueKeys, BuildStorage, DigestItem, Perbill, }; use sp_staking::{EraIndex, SessionIndex}; @@ -77,7 +74,7 @@ where RuntimeCall: From, { type OverarchingCall = RuntimeCall; - type Extrinsic = TestXt; + type Extrinsic = UncheckedExtrinsic; } parameter_types! { diff --git a/substrate/frame/identity/src/weights.rs b/substrate/frame/identity/src/weights.rs index 1feb8252c84..81de520d7f2 100644 --- a/substrate/frame/identity/src/weights.rs +++ b/substrate/frame/identity/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_identity +//! Autogenerated weights for `pallet_identity` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/identity/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/identity/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_identity. +/// Weight functions needed for `pallet_identity`. pub trait WeightInfo { fn add_registrar(r: u32, ) -> Weight; fn set_identity(r: u32, ) -> Weight; @@ -77,278 +76,274 @@ pub trait WeightInfo { fn remove_dangling_username() -> Weight; } -/// Weights for pallet_identity using the Substrate node and recommended hardware. +/// Weights for `pallet_identity` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `32 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 11_683_000 picoseconds. - Weight::from_parts(12_515_830, 2626) - // Standard Error: 2_154 - .saturating_add(Weight::from_parts(147_919, 0).saturating_mul(r.into())) + // Minimum execution time: 8_857_000 picoseconds. + Weight::from_parts(9_331_464, 2626) + // Standard Error: 1_745 + .saturating_add(Weight::from_parts(94_096, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. - fn set_identity(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `442 + r * (5 ±0)` - // Estimated: `11003` - // Minimum execution time: 32_949_000 picoseconds. - Weight::from_parts(31_329_634, 11003) - // Standard Error: 4_496 - .saturating_add(Weight::from_parts(203_570, 0).saturating_mul(r.into())) + fn set_identity(_r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `6978 + r * (5 ±0)` + // Estimated: `11037` + // Minimum execution time: 96_522_000 picoseconds. + Weight::from_parts(102_738_605, 11037) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:100 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:100 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `101` - // Estimated: `11003 + s * (2589 ±0)` - // Minimum execution time: 9_157_000 picoseconds. - Weight::from_parts(24_917_444, 11003) - // Standard Error: 4_554 - .saturating_add(Weight::from_parts(3_279_868, 0).saturating_mul(s.into())) + // Estimated: `11037 + s * (2589 ±0)` + // Minimum execution time: 9_112_000 picoseconds. + Weight::from_parts(22_676_873, 11037) + // Standard Error: 6_494 + .saturating_add(Weight::from_parts(3_279_196, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 2589).saturating_mul(s.into())) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `194 + p * (32 ±0)` - // Estimated: `11003` - // Minimum execution time: 9_240_000 picoseconds. - Weight::from_parts(23_326_035, 11003) - // Standard Error: 3_664 - .saturating_add(Weight::from_parts(1_439_873, 0).saturating_mul(p.into())) + // Estimated: `11037` + // Minimum execution time: 8_902_000 picoseconds. + Weight::from_parts(21_168_031, 11037) + // Standard Error: 3_576 + .saturating_add(Weight::from_parts(1_431_542, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. - fn clear_identity(r: u32, s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `469 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 55_687_000 picoseconds. - Weight::from_parts(30_695_182, 11003) - // Standard Error: 9_921 - .saturating_add(Weight::from_parts(162_357, 0).saturating_mul(r.into())) - // Standard Error: 1_937 - .saturating_add(Weight::from_parts(1_427_998, 0).saturating_mul(s.into())) + fn clear_identity(_r: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `7070 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11037` + // Minimum execution time: 52_468_000 picoseconds. + Weight::from_parts(56_065_452, 11037) + // Standard Error: 2_274 + .saturating_add(Weight::from_parts(1_399_051, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: Identity Registrars (r:1 w:0) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:0) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn request_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `367 + r * (57 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 34_876_000 picoseconds. - Weight::from_parts(32_207_018, 11003) - // Standard Error: 5_247 - .saturating_add(Weight::from_parts(249_156, 0).saturating_mul(r.into())) + // Measured: `6968 + r * (57 ±0)` + // Estimated: `11037` + // Minimum execution time: 67_951_000 picoseconds. + Weight::from_parts(69_591_058, 11037) + // Standard Error: 4_420 + .saturating_add(Weight::from_parts(209_239, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn cancel_request(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `398 + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 30_689_000 picoseconds. - Weight::from_parts(31_967_170, 11003) - // Standard Error: 5_387 - .saturating_add(Weight::from_parts(42_676, 0).saturating_mul(r.into())) + // Measured: `6999` + // Estimated: `11037` + // Minimum execution time: 67_818_000 picoseconds. + Weight::from_parts(70_356_319, 11037) + // Standard Error: 5_116 + .saturating_add(Weight::from_parts(4_264, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_357_000 picoseconds. - Weight::from_parts(7_932_950, 2626) - // Standard Error: 1_804 - .saturating_add(Weight::from_parts(132_653, 0).saturating_mul(r.into())) + // Minimum execution time: 6_096_000 picoseconds. + Weight::from_parts(6_470_752, 2626) + // Standard Error: 1_328 + .saturating_add(Weight::from_parts(94_764, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_437_000 picoseconds. - Weight::from_parts(8_051_889, 2626) - // Standard Error: 1_997 - .saturating_add(Weight::from_parts(129_592, 0).saturating_mul(r.into())) + // Minimum execution time: 6_278_000 picoseconds. + Weight::from_parts(6_678_997, 2626) + // Standard Error: 1_396 + .saturating_add(Weight::from_parts(87_207, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_385_000 picoseconds. - Weight::from_parts(7_911_589, 2626) - // Standard Error: 1_791 - .saturating_add(Weight::from_parts(125_788, 0).saturating_mul(r.into())) + // Minimum execution time: 6_130_000 picoseconds. + Weight::from_parts(6_516_146, 2626) + // Standard Error: 1_356 + .saturating_add(Weight::from_parts(88_455, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity Registrars (r:1 w:0) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:0) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn provide_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `445 + r * (57 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 24_073_000 picoseconds. - Weight::from_parts(17_817_684, 11003) - // Standard Error: 8_612 - .saturating_add(Weight::from_parts(406_251, 0).saturating_mul(r.into())) + // Measured: `7046 + r * (57 ±0)` + // Estimated: `11037` + // Minimum execution time: 87_100_000 picoseconds. + Weight::from_parts(87_601_945, 11037) + // Standard Error: 22_724 + .saturating_add(Weight::from_parts(458_296, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. fn kill_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `676 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 73_981_000 picoseconds. - Weight::from_parts(51_684_057, 11003) - // Standard Error: 12_662 - .saturating_add(Weight::from_parts(145_285, 0).saturating_mul(r.into())) - // Standard Error: 2_472 - .saturating_add(Weight::from_parts(1_421_039, 0).saturating_mul(s.into())) + // Measured: `7277 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11037` + // Minimum execution time: 65_925_000 picoseconds. + Weight::from_parts(70_786_250, 11037) + // Standard Error: 19_680 + .saturating_add(Weight::from_parts(29_782, 0).saturating_mul(r.into())) + // Standard Error: 3_839 + .saturating_add(Weight::from_parts(1_377_604, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `475 + s * (36 ±0)` - // Estimated: `11003` - // Minimum execution time: 29_367_000 picoseconds. - Weight::from_parts(34_214_998, 11003) - // Standard Error: 1_522 - .saturating_add(Weight::from_parts(114_551, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 25_916_000 picoseconds. + Weight::from_parts(29_781_270, 11037) + // Standard Error: 1_326 + .saturating_add(Weight::from_parts(101_515, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `591 + s * (3 ±0)` - // Estimated: `11003` - // Minimum execution time: 12_384_000 picoseconds. - Weight::from_parts(14_417_903, 11003) - // Standard Error: 539 - .saturating_add(Weight::from_parts(38_371, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 12_142_000 picoseconds. + Weight::from_parts(14_179_741, 11037) + // Standard Error: 538 + .saturating_add(Weight::from_parts(38_847, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `638 + s * (35 ±0)` - // Estimated: `11003` - // Minimum execution time: 33_327_000 picoseconds. - Weight::from_parts(36_208_941, 11003) - // Standard Error: 1_240 - .saturating_add(Weight::from_parts(105_805, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 29_327_000 picoseconds. + Weight::from_parts(32_163_402, 11037) + // Standard Error: 1_047 + .saturating_add(Weight::from_parts(87_159, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `704 + s * (37 ±0)` // Estimated: `6723` - // Minimum execution time: 23_764_000 picoseconds. - Weight::from_parts(26_407_731, 6723) - // Standard Error: 1_025 - .saturating_add(Weight::from_parts(101_112, 0).saturating_mul(s.into())) + // Minimum execution time: 22_380_000 picoseconds. + Weight::from_parts(24_557_574, 6723) + // Standard Error: 1_131 + .saturating_add(Weight::from_parts(86_358, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -358,367 +353,359 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_873_000 picoseconds. - Weight::from_parts(13_873_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) + // Minimum execution time: 6_791_000 picoseconds. + Weight::from_parts(7_126_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::UsernameAuthorities` (r:0 w:1) + /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn remove_username_authority() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 10_653_000 picoseconds. - Weight::from_parts(10_653_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) + // Measured: `80` + // Estimated: `3517` + // Minimum execution time: 9_657_000 picoseconds. + Weight::from_parts(9_922_000, 3517) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Identity::PendingUsernames` (r:1 w:0) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_username_for() -> Weight { // Proof Size summary in bytes: // Measured: `80` // Estimated: `11037` - // Minimum execution time: 75_928_000 picoseconds. - Weight::from_parts(75_928_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) + // Minimum execution time: 67_928_000 picoseconds. + Weight::from_parts(69_993_000, 11037) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:0 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) fn accept_username() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `115` // Estimated: `11037` - // Minimum execution time: 38_157_000 picoseconds. - Weight::from_parts(38_157_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(3)) + // Minimum execution time: 20_496_000 picoseconds. + Weight::from_parts(20_971_000, 11037) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn remove_expired_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `106` - // Estimated: `3542` - // Minimum execution time: 46_821_000 picoseconds. - Weight::from_parts(46_821_000, 0) - .saturating_add(Weight::from_parts(0, 3542)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) + // Measured: `115` + // Estimated: `3550` + // Minimum execution time: 13_845_000 picoseconds. + Weight::from_parts(16_201_000, 3550) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:0) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_primary_username() -> Weight { // Proof Size summary in bytes: - // Measured: `247` + // Measured: `257` // Estimated: `11037` - // Minimum execution time: 22_515_000 picoseconds. - Weight::from_parts(22_515_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) + // Minimum execution time: 15_900_000 picoseconds. + Weight::from_parts(16_716_000, 11037) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:0) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn remove_dangling_username() -> Weight { // Proof Size summary in bytes: - // Measured: `126` + // Measured: `98` // Estimated: `11037` - // Minimum execution time: 15_997_000 picoseconds. - Weight::from_parts(15_997_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) + // Minimum execution time: 11_538_000 picoseconds. + Weight::from_parts(11_898_000, 11037) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `32 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 11_683_000 picoseconds. - Weight::from_parts(12_515_830, 2626) - // Standard Error: 2_154 - .saturating_add(Weight::from_parts(147_919, 0).saturating_mul(r.into())) + // Minimum execution time: 8_857_000 picoseconds. + Weight::from_parts(9_331_464, 2626) + // Standard Error: 1_745 + .saturating_add(Weight::from_parts(94_096, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. - fn set_identity(r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `442 + r * (5 ±0)` - // Estimated: `11003` - // Minimum execution time: 32_949_000 picoseconds. - Weight::from_parts(31_329_634, 11003) - // Standard Error: 4_496 - .saturating_add(Weight::from_parts(203_570, 0).saturating_mul(r.into())) + fn set_identity(_r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `6978 + r * (5 ±0)` + // Estimated: `11037` + // Minimum execution time: 96_522_000 picoseconds. + Weight::from_parts(102_738_605, 11037) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:100 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:100 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `101` - // Estimated: `11003 + s * (2589 ±0)` - // Minimum execution time: 9_157_000 picoseconds. - Weight::from_parts(24_917_444, 11003) - // Standard Error: 4_554 - .saturating_add(Weight::from_parts(3_279_868, 0).saturating_mul(s.into())) + // Estimated: `11037 + s * (2589 ±0)` + // Minimum execution time: 9_112_000 picoseconds. + Weight::from_parts(22_676_873, 11037) + // Standard Error: 6_494 + .saturating_add(Weight::from_parts(3_279_196, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 2589).saturating_mul(s.into())) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `194 + p * (32 ±0)` - // Estimated: `11003` - // Minimum execution time: 9_240_000 picoseconds. - Weight::from_parts(23_326_035, 11003) - // Standard Error: 3_664 - .saturating_add(Weight::from_parts(1_439_873, 0).saturating_mul(p.into())) + // Estimated: `11037` + // Minimum execution time: 8_902_000 picoseconds. + Weight::from_parts(21_168_031, 11037) + // Standard Error: 3_576 + .saturating_add(Weight::from_parts(1_431_542, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(p.into()))) } - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. - fn clear_identity(r: u32, s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `469 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 55_687_000 picoseconds. - Weight::from_parts(30_695_182, 11003) - // Standard Error: 9_921 - .saturating_add(Weight::from_parts(162_357, 0).saturating_mul(r.into())) - // Standard Error: 1_937 - .saturating_add(Weight::from_parts(1_427_998, 0).saturating_mul(s.into())) + fn clear_identity(_r: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `7070 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11037` + // Minimum execution time: 52_468_000 picoseconds. + Weight::from_parts(56_065_452, 11037) + // Standard Error: 2_274 + .saturating_add(Weight::from_parts(1_399_051, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: Identity Registrars (r:1 w:0) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:0) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn request_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `367 + r * (57 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 34_876_000 picoseconds. - Weight::from_parts(32_207_018, 11003) - // Standard Error: 5_247 - .saturating_add(Weight::from_parts(249_156, 0).saturating_mul(r.into())) + // Measured: `6968 + r * (57 ±0)` + // Estimated: `11037` + // Minimum execution time: 67_951_000 picoseconds. + Weight::from_parts(69_591_058, 11037) + // Standard Error: 4_420 + .saturating_add(Weight::from_parts(209_239, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. fn cancel_request(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `398 + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 30_689_000 picoseconds. - Weight::from_parts(31_967_170, 11003) - // Standard Error: 5_387 - .saturating_add(Weight::from_parts(42_676, 0).saturating_mul(r.into())) + // Measured: `6999` + // Estimated: `11037` + // Minimum execution time: 67_818_000 picoseconds. + Weight::from_parts(70_356_319, 11037) + // Standard Error: 5_116 + .saturating_add(Weight::from_parts(4_264, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_357_000 picoseconds. - Weight::from_parts(7_932_950, 2626) - // Standard Error: 1_804 - .saturating_add(Weight::from_parts(132_653, 0).saturating_mul(r.into())) + // Minimum execution time: 6_096_000 picoseconds. + Weight::from_parts(6_470_752, 2626) + // Standard Error: 1_328 + .saturating_add(Weight::from_parts(94_764, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_437_000 picoseconds. - Weight::from_parts(8_051_889, 2626) - // Standard Error: 1_997 - .saturating_add(Weight::from_parts(129_592, 0).saturating_mul(r.into())) + // Minimum execution time: 6_278_000 picoseconds. + Weight::from_parts(6_678_997, 2626) + // Standard Error: 1_396 + .saturating_add(Weight::from_parts(87_207, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity Registrars (r:1 w:1) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:1) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_385_000 picoseconds. - Weight::from_parts(7_911_589, 2626) - // Standard Error: 1_791 - .saturating_add(Weight::from_parts(125_788, 0).saturating_mul(r.into())) + // Minimum execution time: 6_130_000 picoseconds. + Weight::from_parts(6_516_146, 2626) + // Standard Error: 1_356 + .saturating_add(Weight::from_parts(88_455, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity Registrars (r:1 w:0) - /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: `Identity::Registrars` (r:1 w:0) + /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 19]`. fn provide_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `445 + r * (57 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 24_073_000 picoseconds. - Weight::from_parts(17_817_684, 11003) - // Standard Error: 8_612 - .saturating_add(Weight::from_parts(406_251, 0).saturating_mul(r.into())) + // Measured: `7046 + r * (57 ±0)` + // Estimated: `11037` + // Minimum execution time: 87_100_000 picoseconds. + Weight::from_parts(87_601_945, 11037) + // Standard Error: 22_724 + .saturating_add(Weight::from_parts(458_296, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: Identity IdentityOf (r:1 w:1) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:0 w:100) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `Identity::IdentityOf` (r:1 w:1) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:0 w:100) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. fn kill_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `676 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` - // Estimated: `11003` - // Minimum execution time: 73_981_000 picoseconds. - Weight::from_parts(51_684_057, 11003) - // Standard Error: 12_662 - .saturating_add(Weight::from_parts(145_285, 0).saturating_mul(r.into())) - // Standard Error: 2_472 - .saturating_add(Weight::from_parts(1_421_039, 0).saturating_mul(s.into())) + // Measured: `7277 + r * (5 ±0) + s * (32 ±0)` + // Estimated: `11037` + // Minimum execution time: 65_925_000 picoseconds. + Weight::from_parts(70_786_250, 11037) + // Standard Error: 19_680 + .saturating_add(Weight::from_parts(29_782, 0).saturating_mul(r.into())) + // Standard Error: 3_839 + .saturating_add(Weight::from_parts(1_377_604, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `475 + s * (36 ±0)` - // Estimated: `11003` - // Minimum execution time: 29_367_000 picoseconds. - Weight::from_parts(34_214_998, 11003) - // Standard Error: 1_522 - .saturating_add(Weight::from_parts(114_551, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 25_916_000 picoseconds. + Weight::from_parts(29_781_270, 11037) + // Standard Error: 1_326 + .saturating_add(Weight::from_parts(101_515, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `591 + s * (3 ±0)` - // Estimated: `11003` - // Minimum execution time: 12_384_000 picoseconds. - Weight::from_parts(14_417_903, 11003) - // Standard Error: 539 - .saturating_add(Weight::from_parts(38_371, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 12_142_000 picoseconds. + Weight::from_parts(14_179_741, 11037) + // Standard Error: 538 + .saturating_add(Weight::from_parts(38_847, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Identity IdentityOf (r:1 w:0) - /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: `Identity::IdentityOf` (r:1 w:0) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `638 + s * (35 ±0)` - // Estimated: `11003` - // Minimum execution time: 33_327_000 picoseconds. - Weight::from_parts(36_208_941, 11003) - // Standard Error: 1_240 - .saturating_add(Weight::from_parts(105_805, 0).saturating_mul(s.into())) + // Estimated: `11037` + // Minimum execution time: 29_327_000 picoseconds. + Weight::from_parts(32_163_402, 11037) + // Standard Error: 1_047 + .saturating_add(Weight::from_parts(87_159, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Identity SuperOf (r:1 w:1) - /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: Identity SubsOf (r:1 w:1) - /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Identity::SuperOf` (r:1 w:1) + /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `Identity::SubsOf` (r:1 w:1) + /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `704 + s * (37 ±0)` // Estimated: `6723` - // Minimum execution time: 23_764_000 picoseconds. - Weight::from_parts(26_407_731, 6723) - // Standard Error: 1_025 - .saturating_add(Weight::from_parts(101_112, 0).saturating_mul(s.into())) + // Minimum execution time: 22_380_000 picoseconds. + Weight::from_parts(24_557_574, 6723) + // Standard Error: 1_131 + .saturating_add(Weight::from_parts(86_358, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -728,92 +715,88 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_873_000 picoseconds. - Weight::from_parts(13_873_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Minimum execution time: 6_791_000 picoseconds. + Weight::from_parts(7_126_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::UsernameAuthorities` (r:0 w:1) + /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn remove_username_authority() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 10_653_000 picoseconds. - Weight::from_parts(10_653_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Measured: `80` + // Estimated: `3517` + // Minimum execution time: 9_657_000 picoseconds. + Weight::from_parts(9_922_000, 3517) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Identity::PendingUsernames` (r:1 w:0) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_username_for() -> Weight { // Proof Size summary in bytes: // Measured: `80` // Estimated: `11037` - // Minimum execution time: 75_928_000 picoseconds. - Weight::from_parts(75_928_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(RocksDbWeight::get().reads(3)) - .saturating_add(RocksDbWeight::get().writes(3)) + // Minimum execution time: 67_928_000 picoseconds. + Weight::from_parts(69_993_000, 11037) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:0 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) fn accept_username() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `115` // Estimated: `11037` - // Minimum execution time: 38_157_000 picoseconds. - Weight::from_parts(38_157_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(3)) + // Minimum execution time: 20_496_000 picoseconds. + Weight::from_parts(20_971_000, 11037) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn remove_expired_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `106` - // Estimated: `3542` - // Minimum execution time: 46_821_000 picoseconds. - Weight::from_parts(46_821_000, 0) - .saturating_add(Weight::from_parts(0, 3542)) - .saturating_add(RocksDbWeight::get().reads(1)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Measured: `115` + // Estimated: `3550` + // Minimum execution time: 13_845_000 picoseconds. + Weight::from_parts(16_201_000, 3550) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:0) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_primary_username() -> Weight { // Proof Size summary in bytes: - // Measured: `247` + // Measured: `257` // Estimated: `11037` - // Minimum execution time: 22_515_000 picoseconds. - Weight::from_parts(22_515_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Minimum execution time: 15_900_000 picoseconds. + Weight::from_parts(16_716_000, 11037) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:0) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn remove_dangling_username() -> Weight { // Proof Size summary in bytes: - // Measured: `126` + // Measured: `98` // Estimated: `11037` - // Minimum execution time: 15_997_000 picoseconds. - Weight::from_parts(15_997_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Minimum execution time: 11_538_000 picoseconds. + Weight::from_parts(11_898_000, 11037) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/im-online/src/mock.rs b/substrate/frame/im-online/src/mock.rs index 9dad148b10f..c0ba9143e13 100644 --- a/substrate/frame/im-online/src/mock.rs +++ b/substrate/frame/im-online/src/mock.rs @@ -27,7 +27,7 @@ use frame_support::{ use pallet_session::historical as pallet_session_historical; use sp_core::H256; use sp_runtime::{ - testing::{TestXt, UintAuthorityId}, + testing::UintAuthorityId, traits::{BlakeTwo256, ConvertInto, IdentityLookup}, BuildStorage, Permill, }; @@ -78,7 +78,7 @@ impl pallet_session::historical::SessionManager for TestSessionManager } /// An extrinsic type used for tests. -pub type Extrinsic = TestXt; +pub type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; type IdentificationTuple = (u64, u64); type Offence = crate::UnresponsivenessOffence; diff --git a/substrate/frame/im-online/src/tests.rs b/substrate/frame/im-online/src/tests.rs index 79036760c2d..7efca926eb0 100644 --- a/substrate/frame/im-online/src/tests.rs +++ b/substrate/frame/im-online/src/tests.rs @@ -231,7 +231,7 @@ fn should_generate_heartbeats() { // check stuff about the transaction. let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); - let heartbeat = match ex.call { + let heartbeat = match ex.function { crate::mock::RuntimeCall::ImOnline(crate::Call::heartbeat { heartbeat, .. }) => heartbeat, e => panic!("Unexpected call: {:?}", e), @@ -345,7 +345,7 @@ fn should_not_send_a_report_if_already_online() { assert_eq!(pool_state.read().transactions.len(), 0); // check stuff about the transaction. let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); - let heartbeat = match ex.call { + let heartbeat = match ex.function { crate::mock::RuntimeCall::ImOnline(crate::Call::heartbeat { heartbeat, .. }) => heartbeat, e => panic!("Unexpected call: {:?}", e), diff --git a/substrate/frame/im-online/src/weights.rs b/substrate/frame/im-online/src/weights.rs index c3db02af257..11357b1e7b7 100644 --- a/substrate/frame/im-online/src/weights.rs +++ b/substrate/frame/im-online/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_im_online +//! Autogenerated weights for `pallet_im_online` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/im-online/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/im-online/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,60 +49,60 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_im_online. +/// Weight functions needed for `pallet_im_online`. pub trait WeightInfo { fn validate_unsigned_and_then_heartbeat(k: u32, ) -> Weight; } -/// Weights for pallet_im_online using the Substrate node and recommended hardware. +/// Weights for `pallet_im_online` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Session Validators (r:1 w:0) - /// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Session CurrentIndex (r:1 w:0) - /// Proof Skipped: Session CurrentIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ImOnline Keys (r:1 w:0) - /// Proof: ImOnline Keys (max_values: Some(1), max_size: Some(320002), added: 320497, mode: MaxEncodedLen) - /// Storage: ImOnline ReceivedHeartbeats (r:1 w:1) - /// Proof: ImOnline ReceivedHeartbeats (max_values: None, max_size: Some(25), added: 2500, mode: MaxEncodedLen) - /// Storage: ImOnline AuthoredBlocks (r:1 w:0) - /// Proof: ImOnline AuthoredBlocks (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) + /// Storage: `Session::Validators` (r:1 w:0) + /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::CurrentIndex` (r:1 w:0) + /// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ImOnline::Keys` (r:1 w:0) + /// Proof: `ImOnline::Keys` (`max_values`: Some(1), `max_size`: Some(320002), added: 320497, mode: `MaxEncodedLen`) + /// Storage: `ImOnline::ReceivedHeartbeats` (r:1 w:1) + /// Proof: `ImOnline::ReceivedHeartbeats` (`max_values`: None, `max_size`: Some(25), added: 2500, mode: `MaxEncodedLen`) + /// Storage: `ImOnline::AuthoredBlocks` (r:1 w:0) + /// Proof: `ImOnline::AuthoredBlocks` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) /// The range of component `k` is `[1, 1000]`. fn validate_unsigned_and_then_heartbeat(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `295 + k * (32 ±0)` + // Measured: `327 + k * (32 ±0)` // Estimated: `321487 + k * (1761 ±0)` - // Minimum execution time: 80_568_000 picoseconds. - Weight::from_parts(95_175_595, 321487) - // Standard Error: 627 - .saturating_add(Weight::from_parts(39_094, 0).saturating_mul(k.into())) + // Minimum execution time: 65_515_000 picoseconds. + Weight::from_parts(74_765_329, 321487) + // Standard Error: 500 + .saturating_add(Weight::from_parts(39_171, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1761).saturating_mul(k.into())) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Session Validators (r:1 w:0) - /// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Session CurrentIndex (r:1 w:0) - /// Proof Skipped: Session CurrentIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ImOnline Keys (r:1 w:0) - /// Proof: ImOnline Keys (max_values: Some(1), max_size: Some(320002), added: 320497, mode: MaxEncodedLen) - /// Storage: ImOnline ReceivedHeartbeats (r:1 w:1) - /// Proof: ImOnline ReceivedHeartbeats (max_values: None, max_size: Some(25), added: 2500, mode: MaxEncodedLen) - /// Storage: ImOnline AuthoredBlocks (r:1 w:0) - /// Proof: ImOnline AuthoredBlocks (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) + /// Storage: `Session::Validators` (r:1 w:0) + /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::CurrentIndex` (r:1 w:0) + /// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ImOnline::Keys` (r:1 w:0) + /// Proof: `ImOnline::Keys` (`max_values`: Some(1), `max_size`: Some(320002), added: 320497, mode: `MaxEncodedLen`) + /// Storage: `ImOnline::ReceivedHeartbeats` (r:1 w:1) + /// Proof: `ImOnline::ReceivedHeartbeats` (`max_values`: None, `max_size`: Some(25), added: 2500, mode: `MaxEncodedLen`) + /// Storage: `ImOnline::AuthoredBlocks` (r:1 w:0) + /// Proof: `ImOnline::AuthoredBlocks` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) /// The range of component `k` is `[1, 1000]`. fn validate_unsigned_and_then_heartbeat(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `295 + k * (32 ±0)` + // Measured: `327 + k * (32 ±0)` // Estimated: `321487 + k * (1761 ±0)` - // Minimum execution time: 80_568_000 picoseconds. - Weight::from_parts(95_175_595, 321487) - // Standard Error: 627 - .saturating_add(Weight::from_parts(39_094, 0).saturating_mul(k.into())) + // Minimum execution time: 65_515_000 picoseconds. + Weight::from_parts(74_765_329, 321487) + // Standard Error: 500 + .saturating_add(Weight::from_parts(39_171, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1761).saturating_mul(k.into())) diff --git a/substrate/frame/indices/src/weights.rs b/substrate/frame/indices/src/weights.rs index d081cc738b1..6b571164eb6 100644 --- a/substrate/frame/indices/src/weights.rs +++ b/substrate/frame/indices/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_indices +//! Autogenerated weights for `pallet_indices` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/indices/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/indices/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_indices. +/// Weight functions needed for `pallet_indices`. pub trait WeightInfo { fn claim() -> Weight; fn transfer() -> Weight; @@ -59,128 +58,128 @@ pub trait WeightInfo { fn freeze() -> Weight; } -/// Weights for pallet_indices using the Substrate node and recommended hardware. +/// Weights for `pallet_indices` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn claim() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3534` - // Minimum execution time: 25_491_000 picoseconds. - Weight::from_parts(26_456_000, 3534) + // Minimum execution time: 20_825_000 picoseconds. + Weight::from_parts(21_507_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `3593` - // Minimum execution time: 38_027_000 picoseconds. - Weight::from_parts(38_749_000, 3593) + // Minimum execution time: 31_091_000 picoseconds. + Weight::from_parts(31_923_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn free() -> Weight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `3534` - // Minimum execution time: 26_652_000 picoseconds. - Weight::from_parts(27_273_000, 3534) + // Minimum execution time: 21_832_000 picoseconds. + Weight::from_parts(22_436_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `3593` - // Minimum execution time: 29_464_000 picoseconds. - Weight::from_parts(30_959_000, 3593) + // Minimum execution time: 23_876_000 picoseconds. + Weight::from_parts(24_954_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn freeze() -> Weight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `3534` - // Minimum execution time: 29_015_000 picoseconds. - Weight::from_parts(29_714_000, 3534) + // Minimum execution time: 22_954_000 picoseconds. + Weight::from_parts(23_792_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn claim() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3534` - // Minimum execution time: 25_491_000 picoseconds. - Weight::from_parts(26_456_000, 3534) + // Minimum execution time: 20_825_000 picoseconds. + Weight::from_parts(21_507_000, 3534) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `3593` - // Minimum execution time: 38_027_000 picoseconds. - Weight::from_parts(38_749_000, 3593) + // Minimum execution time: 31_091_000 picoseconds. + Weight::from_parts(31_923_000, 3593) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn free() -> Weight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `3534` - // Minimum execution time: 26_652_000 picoseconds. - Weight::from_parts(27_273_000, 3534) + // Minimum execution time: 21_832_000 picoseconds. + Weight::from_parts(22_436_000, 3534) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `3593` - // Minimum execution time: 29_464_000 picoseconds. - Weight::from_parts(30_959_000, 3593) + // Minimum execution time: 23_876_000 picoseconds. + Weight::from_parts(24_954_000, 3593) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Indices Accounts (r:1 w:1) - /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Indices::Accounts` (r:1 w:1) + /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn freeze() -> Weight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `3534` - // Minimum execution time: 29_015_000 picoseconds. - Weight::from_parts(29_714_000, 3534) + // Minimum execution time: 22_954_000 picoseconds. + Weight::from_parts(23_792_000, 3534) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/lottery/src/weights.rs b/substrate/frame/lottery/src/weights.rs index 3b4e5623753..7e56cdf90db 100644 --- a/substrate/frame/lottery/src/weights.rs +++ b/substrate/frame/lottery/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_lottery +//! Autogenerated weights for `pallet_lottery` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/lottery/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/lottery/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_lottery. +/// Weight functions needed for `pallet_lottery`. pub trait WeightInfo { fn buy_ticket() -> Weight; fn set_calls(n: u32, ) -> Weight; @@ -60,214 +59,222 @@ pub trait WeightInfo { fn on_initialize_repeat() -> Weight; } -/// Weights for pallet_lottery using the Substrate node and recommended hardware. +/// Weights for `pallet_lottery` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Lottery Lottery (r:1 w:0) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) - /// Storage: Lottery CallIndices (r:1 w:0) - /// Proof: Lottery CallIndices (max_values: Some(1), max_size: Some(21), added: 516, mode: MaxEncodedLen) - /// Storage: Lottery TicketsCount (r:1 w:1) - /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Lottery Participants (r:1 w:1) - /// Proof: Lottery Participants (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: Lottery LotteryIndex (r:1 w:0) - /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Lottery Tickets (r:0 w:1) - /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Lottery` (r:1 w:0) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: `Lottery::CallIndices` (r:1 w:0) + /// Proof: `Lottery::CallIndices` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) + /// Storage: `Lottery::TicketsCount` (r:1 w:1) + /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Participants` (r:1 w:1) + /// Proof: `Lottery::Participants` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `Lottery::LotteryIndex` (r:1 w:0) + /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Tickets` (r:0 w:1) + /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) fn buy_ticket() -> Weight { // Proof Size summary in bytes: - // Measured: `452` - // Estimated: `3593` - // Minimum execution time: 60_298_000 picoseconds. - Weight::from_parts(62_058_000, 3593) - .saturating_add(T::DbWeight::get().reads(6_u64)) + // Measured: `492` + // Estimated: `3997` + // Minimum execution time: 57_891_000 picoseconds. + Weight::from_parts(59_508_000, 3997) + .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Lottery CallIndices (r:0 w:1) - /// Proof: Lottery CallIndices (max_values: Some(1), max_size: Some(21), added: 516, mode: MaxEncodedLen) + /// Storage: `Lottery::CallIndices` (r:0 w:1) + /// Proof: `Lottery::CallIndices` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 10]`. fn set_calls(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_291_000 picoseconds. - Weight::from_parts(8_178_186, 0) - // Standard Error: 3_048 - .saturating_add(Weight::from_parts(330_871, 0).saturating_mul(n.into())) + // Minimum execution time: 5_026_000 picoseconds. + Weight::from_parts(5_854_666, 0) + // Standard Error: 3_233 + .saturating_add(Weight::from_parts(334_818, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Lottery Lottery (r:1 w:1) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) - /// Storage: Lottery LotteryIndex (r:1 w:1) - /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Lottery::Lottery` (r:1 w:1) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: `Lottery::LotteryIndex` (r:1 w:1) + /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn start_lottery() -> Weight { // Proof Size summary in bytes: - // Measured: `161` + // Measured: `194` // Estimated: `3593` - // Minimum execution time: 36_741_000 picoseconds. - Weight::from_parts(38_288_000, 3593) + // Minimum execution time: 26_216_000 picoseconds. + Weight::from_parts(27_216_000, 3593) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Lottery Lottery (r:1 w:1) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: `Lottery::Lottery` (r:1 w:1) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) fn stop_repeat() -> Weight { // Proof Size summary in bytes: - // Measured: `219` + // Measured: `252` // Estimated: `1514` - // Minimum execution time: 7_270_000 picoseconds. - Weight::from_parts(7_578_000, 1514) + // Minimum execution time: 6_208_000 picoseconds. + Weight::from_parts(6_427_000, 1514) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) - /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) - /// Storage: Lottery Lottery (r:1 w:1) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Lottery TicketsCount (r:1 w:1) - /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Lottery Tickets (r:1 w:0) - /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) + /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) + /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Lottery` (r:1 w:1) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Lottery::TicketsCount` (r:1 w:1) + /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Tickets` (r:1 w:0) + /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) fn on_initialize_end() -> Weight { // Proof Size summary in bytes: - // Measured: `558` + // Measured: `591` // Estimated: `6196` - // Minimum execution time: 76_611_000 picoseconds. - Weight::from_parts(78_107_000, 6196) + // Minimum execution time: 58_660_000 picoseconds. + Weight::from_parts(59_358_000, 6196) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) - /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) - /// Storage: Lottery Lottery (r:1 w:1) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Lottery TicketsCount (r:1 w:1) - /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Lottery Tickets (r:1 w:0) - /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) - /// Storage: Lottery LotteryIndex (r:1 w:1) - /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) + /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Lottery` (r:1 w:1) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Lottery::TicketsCount` (r:1 w:1) + /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Tickets` (r:1 w:0) + /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `Lottery::LotteryIndex` (r:1 w:1) + /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn on_initialize_repeat() -> Weight { // Proof Size summary in bytes: - // Measured: `558` + // Measured: `591` // Estimated: `6196` - // Minimum execution time: 78_731_000 picoseconds. - Weight::from_parts(80_248_000, 6196) + // Minimum execution time: 59_376_000 picoseconds. + Weight::from_parts(60_598_000, 6196) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Lottery Lottery (r:1 w:0) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) - /// Storage: Lottery CallIndices (r:1 w:0) - /// Proof: Lottery CallIndices (max_values: Some(1), max_size: Some(21), added: 516, mode: MaxEncodedLen) - /// Storage: Lottery TicketsCount (r:1 w:1) - /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Lottery Participants (r:1 w:1) - /// Proof: Lottery Participants (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: Lottery LotteryIndex (r:1 w:0) - /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Lottery Tickets (r:0 w:1) - /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Lottery` (r:1 w:0) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: `Lottery::CallIndices` (r:1 w:0) + /// Proof: `Lottery::CallIndices` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) + /// Storage: `Lottery::TicketsCount` (r:1 w:1) + /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Participants` (r:1 w:1) + /// Proof: `Lottery::Participants` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `Lottery::LotteryIndex` (r:1 w:0) + /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Tickets` (r:0 w:1) + /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) fn buy_ticket() -> Weight { // Proof Size summary in bytes: - // Measured: `452` - // Estimated: `3593` - // Minimum execution time: 60_298_000 picoseconds. - Weight::from_parts(62_058_000, 3593) - .saturating_add(RocksDbWeight::get().reads(6_u64)) + // Measured: `492` + // Estimated: `3997` + // Minimum execution time: 57_891_000 picoseconds. + Weight::from_parts(59_508_000, 3997) + .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Lottery CallIndices (r:0 w:1) - /// Proof: Lottery CallIndices (max_values: Some(1), max_size: Some(21), added: 516, mode: MaxEncodedLen) + /// Storage: `Lottery::CallIndices` (r:0 w:1) + /// Proof: `Lottery::CallIndices` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 10]`. fn set_calls(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_291_000 picoseconds. - Weight::from_parts(8_178_186, 0) - // Standard Error: 3_048 - .saturating_add(Weight::from_parts(330_871, 0).saturating_mul(n.into())) + // Minimum execution time: 5_026_000 picoseconds. + Weight::from_parts(5_854_666, 0) + // Standard Error: 3_233 + .saturating_add(Weight::from_parts(334_818, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Lottery Lottery (r:1 w:1) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) - /// Storage: Lottery LotteryIndex (r:1 w:1) - /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Lottery::Lottery` (r:1 w:1) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: `Lottery::LotteryIndex` (r:1 w:1) + /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn start_lottery() -> Weight { // Proof Size summary in bytes: - // Measured: `161` + // Measured: `194` // Estimated: `3593` - // Minimum execution time: 36_741_000 picoseconds. - Weight::from_parts(38_288_000, 3593) + // Minimum execution time: 26_216_000 picoseconds. + Weight::from_parts(27_216_000, 3593) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Lottery Lottery (r:1 w:1) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: `Lottery::Lottery` (r:1 w:1) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) fn stop_repeat() -> Weight { // Proof Size summary in bytes: - // Measured: `219` + // Measured: `252` // Estimated: `1514` - // Minimum execution time: 7_270_000 picoseconds. - Weight::from_parts(7_578_000, 1514) + // Minimum execution time: 6_208_000 picoseconds. + Weight::from_parts(6_427_000, 1514) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) - /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) - /// Storage: Lottery Lottery (r:1 w:1) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Lottery TicketsCount (r:1 w:1) - /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Lottery Tickets (r:1 w:0) - /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) + /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) + /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Lottery` (r:1 w:1) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Lottery::TicketsCount` (r:1 w:1) + /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Tickets` (r:1 w:0) + /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) fn on_initialize_end() -> Weight { // Proof Size summary in bytes: - // Measured: `558` + // Measured: `591` // Estimated: `6196` - // Minimum execution time: 76_611_000 picoseconds. - Weight::from_parts(78_107_000, 6196) + // Minimum execution time: 58_660_000 picoseconds. + Weight::from_parts(59_358_000, 6196) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) - /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) - /// Storage: Lottery Lottery (r:1 w:1) - /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Lottery TicketsCount (r:1 w:1) - /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Lottery Tickets (r:1 w:0) - /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) - /// Storage: Lottery LotteryIndex (r:1 w:1) - /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) + /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Lottery` (r:1 w:1) + /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Lottery::TicketsCount` (r:1 w:1) + /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Lottery::Tickets` (r:1 w:0) + /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `Lottery::LotteryIndex` (r:1 w:1) + /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn on_initialize_repeat() -> Weight { // Proof Size summary in bytes: - // Measured: `558` + // Measured: `591` // Estimated: `6196` - // Minimum execution time: 78_731_000 picoseconds. - Weight::from_parts(80_248_000, 6196) + // Minimum execution time: 59_376_000 picoseconds. + Weight::from_parts(60_598_000, 6196) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } diff --git a/substrate/frame/membership/src/weights.rs b/substrate/frame/membership/src/weights.rs index 2d18848b89a..f21867d6870 100644 --- a/substrate/frame/membership/src/weights.rs +++ b/substrate/frame/membership/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_membership +//! Autogenerated weights for `pallet_membership` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/membership/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/membership/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_membership. +/// Weight functions needed for `pallet_membership`. pub trait WeightInfo { fn add_member(m: u32, ) -> Weight; fn remove_member(m: u32, ) -> Weight; @@ -61,299 +60,299 @@ pub trait WeightInfo { fn clear_prime() -> Weight; } -/// Weights for pallet_membership using the Substrate node and recommended hardware. +/// Weights for `pallet_membership` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 99]`. fn add_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `208 + m * (64 ±0)` + // Measured: `207 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 17_040_000 picoseconds. - Weight::from_parts(18_344_571, 4687) - // Standard Error: 847 - .saturating_add(Weight::from_parts(50_842, 0).saturating_mul(m.into())) + // Minimum execution time: 12_126_000 picoseconds. + Weight::from_parts(13_085_583, 4687) + // Standard Error: 659 + .saturating_add(Weight::from_parts(36_103, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalMembership Prime (r:1 w:0) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalMembership::Prime` (r:1 w:0) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[2, 100]`. fn remove_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `312 + m * (64 ±0)` + // Measured: `311 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 20_088_000 picoseconds. - Weight::from_parts(21_271_384, 4687) - // Standard Error: 786 - .saturating_add(Weight::from_parts(44_806, 0).saturating_mul(m.into())) + // Minimum execution time: 14_571_000 picoseconds. + Weight::from_parts(15_532_232, 4687) + // Standard Error: 531 + .saturating_add(Weight::from_parts(35_757, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalMembership Prime (r:1 w:0) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalMembership::Prime` (r:1 w:0) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[2, 100]`. fn swap_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `312 + m * (64 ±0)` + // Measured: `311 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 20_308_000 picoseconds. - Weight::from_parts(21_469_843, 4687) - // Standard Error: 782 - .saturating_add(Weight::from_parts(56_893, 0).saturating_mul(m.into())) + // Minimum execution time: 14_833_000 picoseconds. + Weight::from_parts(15_657_084, 4687) + // Standard Error: 650 + .saturating_add(Weight::from_parts(44_467, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalMembership Prime (r:1 w:0) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalMembership::Prime` (r:1 w:0) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 100]`. fn reset_members(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `312 + m * (64 ±0)` + // Measured: `311 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 19_464_000 picoseconds. - Weight::from_parts(21_223_702, 4687) - // Standard Error: 1_068 - .saturating_add(Weight::from_parts(165_438, 0).saturating_mul(m.into())) + // Minimum execution time: 14_629_000 picoseconds. + Weight::from_parts(15_578_203, 4687) + // Standard Error: 910 + .saturating_add(Weight::from_parts(145_101, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalMembership Prime (r:1 w:1) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalMembership::Prime` (r:1 w:1) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 100]`. fn change_key(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `312 + m * (64 ±0)` + // Measured: `311 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 20_965_000 picoseconds. - Weight::from_parts(22_551_007, 4687) - // Standard Error: 860 - .saturating_add(Weight::from_parts(52_397, 0).saturating_mul(m.into())) + // Minimum execution time: 15_218_000 picoseconds. + Weight::from_parts(16_388_690, 4687) + // Standard Error: 626 + .saturating_add(Weight::from_parts(46_204, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:0) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalMembership Prime (r:0 w:1) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:0) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalMembership::Prime` (r:0 w:1) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 100]`. fn set_prime(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32 + m * (32 ±0)` + // Measured: `31 + m * (32 ±0)` // Estimated: `4687 + m * (32 ±0)` - // Minimum execution time: 7_481_000 picoseconds. - Weight::from_parts(7_959_053, 4687) - // Standard Error: 364 - .saturating_add(Weight::from_parts(18_653, 0).saturating_mul(m.into())) + // Minimum execution time: 5_954_000 picoseconds. + Weight::from_parts(6_544_638, 4687) + // Standard Error: 346 + .saturating_add(Weight::from_parts(17_638, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Prime (r:0 w:1) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Prime` (r:0 w:1) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn clear_prime() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_373_000 picoseconds. - Weight::from_parts(3_750_452, 0) + // Minimum execution time: 2_569_000 picoseconds. + Weight::from_parts(2_776_000, 0) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 99]`. fn add_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `208 + m * (64 ±0)` + // Measured: `207 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 17_040_000 picoseconds. - Weight::from_parts(18_344_571, 4687) - // Standard Error: 847 - .saturating_add(Weight::from_parts(50_842, 0).saturating_mul(m.into())) + // Minimum execution time: 12_126_000 picoseconds. + Weight::from_parts(13_085_583, 4687) + // Standard Error: 659 + .saturating_add(Weight::from_parts(36_103, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalMembership Prime (r:1 w:0) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalMembership::Prime` (r:1 w:0) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[2, 100]`. fn remove_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `312 + m * (64 ±0)` + // Measured: `311 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 20_088_000 picoseconds. - Weight::from_parts(21_271_384, 4687) - // Standard Error: 786 - .saturating_add(Weight::from_parts(44_806, 0).saturating_mul(m.into())) + // Minimum execution time: 14_571_000 picoseconds. + Weight::from_parts(15_532_232, 4687) + // Standard Error: 531 + .saturating_add(Weight::from_parts(35_757, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalMembership Prime (r:1 w:0) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalMembership::Prime` (r:1 w:0) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[2, 100]`. fn swap_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `312 + m * (64 ±0)` + // Measured: `311 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 20_308_000 picoseconds. - Weight::from_parts(21_469_843, 4687) - // Standard Error: 782 - .saturating_add(Weight::from_parts(56_893, 0).saturating_mul(m.into())) + // Minimum execution time: 14_833_000 picoseconds. + Weight::from_parts(15_657_084, 4687) + // Standard Error: 650 + .saturating_add(Weight::from_parts(44_467, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalMembership Prime (r:1 w:0) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalMembership::Prime` (r:1 w:0) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 100]`. fn reset_members(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `312 + m * (64 ±0)` + // Measured: `311 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 19_464_000 picoseconds. - Weight::from_parts(21_223_702, 4687) - // Standard Error: 1_068 - .saturating_add(Weight::from_parts(165_438, 0).saturating_mul(m.into())) + // Minimum execution time: 14_629_000 picoseconds. + Weight::from_parts(15_578_203, 4687) + // Standard Error: 910 + .saturating_add(Weight::from_parts(145_101, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:1) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Proposals (r:1 w:0) - /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalMembership Prime (r:1 w:1) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Members (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:1) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) + /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalMembership::Prime` (r:1 w:1) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Members` (r:0 w:1) + /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 100]`. fn change_key(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `312 + m * (64 ±0)` + // Measured: `311 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 20_965_000 picoseconds. - Weight::from_parts(22_551_007, 4687) - // Standard Error: 860 - .saturating_add(Weight::from_parts(52_397, 0).saturating_mul(m.into())) + // Minimum execution time: 15_218_000 picoseconds. + Weight::from_parts(16_388_690, 4687) + // Standard Error: 626 + .saturating_add(Weight::from_parts(46_204, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Members (r:1 w:0) - /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) - /// Storage: TechnicalMembership Prime (r:0 w:1) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Members` (r:1 w:0) + /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `TechnicalMembership::Prime` (r:0 w:1) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `m` is `[1, 100]`. fn set_prime(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32 + m * (32 ±0)` + // Measured: `31 + m * (32 ±0)` // Estimated: `4687 + m * (32 ±0)` - // Minimum execution time: 7_481_000 picoseconds. - Weight::from_parts(7_959_053, 4687) - // Standard Error: 364 - .saturating_add(Weight::from_parts(18_653, 0).saturating_mul(m.into())) + // Minimum execution time: 5_954_000 picoseconds. + Weight::from_parts(6_544_638, 4687) + // Standard Error: 346 + .saturating_add(Weight::from_parts(17_638, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: TechnicalMembership Prime (r:0 w:1) - /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TechnicalCommittee Prime (r:0 w:1) - /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `TechnicalMembership::Prime` (r:0 w:1) + /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) + /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn clear_prime() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_373_000 picoseconds. - Weight::from_parts(3_750_452, 0) + // Minimum execution time: 2_569_000 picoseconds. + Weight::from_parts(2_776_000, 0) .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/substrate/frame/message-queue/src/weights.rs b/substrate/frame/message-queue/src/weights.rs index e86f23e274f..001e2834e1c 100644 --- a/substrate/frame/message-queue/src/weights.rs +++ b/substrate/frame/message-queue/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_message_queue +//! Autogenerated weights for `pallet_message_queue` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/message-queue/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/message-queue/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_message_queue. +/// Weight functions needed for `pallet_message_queue`. pub trait WeightInfo { fn ready_ring_knit() -> Weight; fn ready_ring_unknit() -> Weight; @@ -64,246 +63,256 @@ pub trait WeightInfo { fn execute_overweight_page_updated() -> Weight; } -/// Weights for pallet_message_queue using the Substrate node and recommended hardware. +/// Weights for `pallet_message_queue` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: MessageQueue ServiceHead (r:1 w:0) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:0) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) fn ready_ring_knit() -> Weight { // Proof Size summary in bytes: - // Measured: `267` + // Measured: `301` // Estimated: `6038` - // Minimum execution time: 12_025_000 picoseconds. - Weight::from_parts(12_597_000, 6038) + // Minimum execution time: 11_563_000 picoseconds. + Weight::from_parts(11_956_000, 6038) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn ready_ring_unknit() -> Weight { // Proof Size summary in bytes: - // Measured: `267` + // Measured: `301` // Estimated: `6038` - // Minimum execution time: 11_563_000 picoseconds. - Weight::from_parts(11_785_000, 6038) + // Minimum execution time: 10_263_000 picoseconds. + Weight::from_parts(10_638_000, 6038) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) fn service_queue_base() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3514` - // Minimum execution time: 4_467_000 picoseconds. - Weight::from_parts(4_655_000, 3514) + // Minimum execution time: 4_335_000 picoseconds. + Weight::from_parts(4_552_000, 3514) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn service_page_base_completion() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `69049` - // Minimum execution time: 6_103_000 picoseconds. - Weight::from_parts(6_254_000, 69049) + // Minimum execution time: 6_016_000 picoseconds. + Weight::from_parts(6_224_000, 69049) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn service_page_base_no_completion() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `69049` - // Minimum execution time: 6_320_000 picoseconds. - Weight::from_parts(6_565_000, 69049) + // Minimum execution time: 6_183_000 picoseconds. + Weight::from_parts(6_348_000, 69049) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: `MessageQueue::BookStateFor` (r:0 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:0 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn service_page_item() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 66_062_000 picoseconds. - Weight::from_parts(66_371_000, 0) + // Minimum execution time: 112_864_000 picoseconds. + Weight::from_parts(114_269_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:0) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) fn bump_service_head() -> Weight { // Proof Size summary in bytes: - // Measured: `174` + // Measured: `246` // Estimated: `3514` - // Minimum execution time: 6_788_000 picoseconds. - Weight::from_parts(7_176_000, 3514) + // Minimum execution time: 6_665_000 picoseconds. + Weight::from_parts(7_108_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn reap_page() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 52_865_000 picoseconds. - Weight::from_parts(54_398_000, 69049) + // Minimum execution time: 51_420_000 picoseconds. + Weight::from_parts(52_252_000, 69049) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn execute_overweight_page_removed() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 69_168_000 picoseconds. - Weight::from_parts(70_560_000, 69049) + // Minimum execution time: 71_195_000 picoseconds. + Weight::from_parts(72_981_000, 69049) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn execute_overweight_page_updated() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 80_947_000 picoseconds. - Weight::from_parts(82_715_000, 69049) + // Minimum execution time: 83_238_000 picoseconds. + Weight::from_parts(84_422_000, 69049) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: MessageQueue ServiceHead (r:1 w:0) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:0) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) fn ready_ring_knit() -> Weight { // Proof Size summary in bytes: - // Measured: `267` + // Measured: `301` // Estimated: `6038` - // Minimum execution time: 12_025_000 picoseconds. - Weight::from_parts(12_597_000, 6038) + // Minimum execution time: 11_563_000 picoseconds. + Weight::from_parts(11_956_000, 6038) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn ready_ring_unknit() -> Weight { // Proof Size summary in bytes: - // Measured: `267` + // Measured: `301` // Estimated: `6038` - // Minimum execution time: 11_563_000 picoseconds. - Weight::from_parts(11_785_000, 6038) + // Minimum execution time: 10_263_000 picoseconds. + Weight::from_parts(10_638_000, 6038) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) fn service_queue_base() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3514` - // Minimum execution time: 4_467_000 picoseconds. - Weight::from_parts(4_655_000, 3514) + // Minimum execution time: 4_335_000 picoseconds. + Weight::from_parts(4_552_000, 3514) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn service_page_base_completion() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `69049` - // Minimum execution time: 6_103_000 picoseconds. - Weight::from_parts(6_254_000, 69049) + // Minimum execution time: 6_016_000 picoseconds. + Weight::from_parts(6_224_000, 69049) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn service_page_base_no_completion() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `69049` - // Minimum execution time: 6_320_000 picoseconds. - Weight::from_parts(6_565_000, 69049) + // Minimum execution time: 6_183_000 picoseconds. + Weight::from_parts(6_348_000, 69049) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + /// Storage: `MessageQueue::BookStateFor` (r:0 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:0 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn service_page_item() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 66_062_000 picoseconds. - Weight::from_parts(66_371_000, 0) + // Minimum execution time: 112_864_000 picoseconds. + Weight::from_parts(114_269_000, 0) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:0) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) fn bump_service_head() -> Weight { // Proof Size summary in bytes: - // Measured: `174` + // Measured: `246` // Estimated: `3514` - // Minimum execution time: 6_788_000 picoseconds. - Weight::from_parts(7_176_000, 3514) + // Minimum execution time: 6_665_000 picoseconds. + Weight::from_parts(7_108_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn reap_page() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 52_865_000 picoseconds. - Weight::from_parts(54_398_000, 69049) + // Minimum execution time: 51_420_000 picoseconds. + Weight::from_parts(52_252_000, 69049) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn execute_overweight_page_removed() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 69_168_000 picoseconds. - Weight::from_parts(70_560_000, 69049) + // Minimum execution time: 71_195_000 picoseconds. + Weight::from_parts(72_981_000, 69049) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::Pages` (r:1 w:1) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn execute_overweight_page_updated() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 80_947_000 picoseconds. - Weight::from_parts(82_715_000, 69049) + // Minimum execution time: 83_238_000 picoseconds. + Weight::from_parts(84_422_000, 69049) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/migrations/src/weights.rs b/substrate/frame/migrations/src/weights.rs index c9b63258c44..9eca48ac3fd 100644 --- a/substrate/frame/migrations/src/weights.rs +++ b/substrate/frame/migrations/src/weights.rs @@ -17,26 +17,29 @@ //! Autogenerated weights for `pallet_migrations` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `loud1`, CPU: `AMD EPYC 7282 16-Core Processor` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/release/substrate-node +// ./target/production/substrate-node // benchmark // pallet -// --chain -// dev -// --pallet -// pallet-migrations -// --extrinsic -// -// --output -// weight.rs -// --template -// ../../polkadot-sdk/substrate/.maintain/frame-weight-template.hbs +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_migrations +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./substrate/frame/migrations/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -71,10 +74,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `243` + // Measured: `276` // Estimated: `67035` - // Minimum execution time: 13_980_000 picoseconds. - Weight::from_parts(14_290_000, 67035) + // Minimum execution time: 7_932_000 picoseconds. + Weight::from_parts(8_428_000, 67035) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -82,10 +85,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `109` + // Measured: `142` // Estimated: `67035` - // Minimum execution time: 3_770_000 picoseconds. - Weight::from_parts(4_001_000, 67035) + // Minimum execution time: 2_229_000 picoseconds. + Weight::from_parts(2_329_000, 67035) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -96,8 +99,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `134` // Estimated: `3599` - // Minimum execution time: 10_900_000 picoseconds. - Weight::from_parts(11_251_000, 3599) + // Minimum execution time: 6_051_000 picoseconds. + Weight::from_parts(6_483_000, 3599) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -107,10 +110,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `297` - // Estimated: `3762` - // Minimum execution time: 17_891_000 picoseconds. - Weight::from_parts(18_501_000, 3762) + // Measured: `330` + // Estimated: `3795` + // Minimum execution time: 10_066_000 picoseconds. + Weight::from_parts(10_713_000, 3795) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -119,10 +122,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `243` - // Estimated: `3731` - // Minimum execution time: 18_271_000 picoseconds. - Weight::from_parts(18_740_000, 3731) + // Measured: `276` + // Estimated: `3741` + // Minimum execution time: 10_026_000 picoseconds. + Weight::from_parts(10_379_000, 3741) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -131,10 +134,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `243` - // Estimated: `3731` - // Minimum execution time: 21_241_000 picoseconds. - Weight::from_parts(21_911_000, 3731) + // Measured: `276` + // Estimated: `3741` + // Minimum execution time: 11_680_000 picoseconds. + Weight::from_parts(12_184_000, 3741) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -146,10 +149,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `243` - // Estimated: `3731` - // Minimum execution time: 22_740_000 picoseconds. - Weight::from_parts(23_231_000, 3731) + // Measured: `276` + // Estimated: `3741` + // Minimum execution time: 12_334_000 picoseconds. + Weight::from_parts(12_899_000, 3741) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -157,8 +160,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 440_000 picoseconds. - Weight::from_parts(500_000, 0) + // Minimum execution time: 187_000 picoseconds. + Weight::from_parts(209_000, 0) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -166,8 +169,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_751_000 picoseconds. - Weight::from_parts(5_950_000, 0) + // Minimum execution time: 2_688_000 picoseconds. + Weight::from_parts(2_874_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) @@ -176,8 +179,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_350_000 picoseconds. - Weight::from_parts(6_560_000, 0) + // Minimum execution time: 3_108_000 picoseconds. + Weight::from_parts(3_263_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) @@ -186,10 +189,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `218` + // Measured: `251` // Estimated: `67035` - // Minimum execution time: 11_121_000 picoseconds. - Weight::from_parts(11_530_000, 67035) + // Minimum execution time: 5_993_000 picoseconds. + Weight::from_parts(6_359_000, 67035) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) @@ -197,12 +200,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1089 + n * (271 ±0)` + // Measured: `1122 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 21_891_000 picoseconds. - Weight::from_parts(18_572_306, 3834) - // Standard Error: 3_236 - .saturating_add(Weight::from_parts(1_648_429, 0).saturating_mul(n.into())) + // Minimum execution time: 16_003_000 picoseconds. + Weight::from_parts(14_453_014, 3834) + // Standard Error: 3_305 + .saturating_add(Weight::from_parts(1_325_026, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -218,10 +221,10 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `243` + // Measured: `276` // Estimated: `67035` - // Minimum execution time: 13_980_000 picoseconds. - Weight::from_parts(14_290_000, 67035) + // Minimum execution time: 7_932_000 picoseconds. + Weight::from_parts(8_428_000, 67035) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -229,10 +232,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `109` + // Measured: `142` // Estimated: `67035` - // Minimum execution time: 3_770_000 picoseconds. - Weight::from_parts(4_001_000, 67035) + // Minimum execution time: 2_229_000 picoseconds. + Weight::from_parts(2_329_000, 67035) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -243,8 +246,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `134` // Estimated: `3599` - // Minimum execution time: 10_900_000 picoseconds. - Weight::from_parts(11_251_000, 3599) + // Minimum execution time: 6_051_000 picoseconds. + Weight::from_parts(6_483_000, 3599) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -254,10 +257,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `297` - // Estimated: `3762` - // Minimum execution time: 17_891_000 picoseconds. - Weight::from_parts(18_501_000, 3762) + // Measured: `330` + // Estimated: `3795` + // Minimum execution time: 10_066_000 picoseconds. + Weight::from_parts(10_713_000, 3795) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -266,10 +269,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `243` - // Estimated: `3731` - // Minimum execution time: 18_271_000 picoseconds. - Weight::from_parts(18_740_000, 3731) + // Measured: `276` + // Estimated: `3741` + // Minimum execution time: 10_026_000 picoseconds. + Weight::from_parts(10_379_000, 3741) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -278,10 +281,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `243` - // Estimated: `3731` - // Minimum execution time: 21_241_000 picoseconds. - Weight::from_parts(21_911_000, 3731) + // Measured: `276` + // Estimated: `3741` + // Minimum execution time: 11_680_000 picoseconds. + Weight::from_parts(12_184_000, 3741) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -293,10 +296,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `243` - // Estimated: `3731` - // Minimum execution time: 22_740_000 picoseconds. - Weight::from_parts(23_231_000, 3731) + // Measured: `276` + // Estimated: `3741` + // Minimum execution time: 12_334_000 picoseconds. + Weight::from_parts(12_899_000, 3741) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -304,8 +307,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 440_000 picoseconds. - Weight::from_parts(500_000, 0) + // Minimum execution time: 187_000 picoseconds. + Weight::from_parts(209_000, 0) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -313,8 +316,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_751_000 picoseconds. - Weight::from_parts(5_950_000, 0) + // Minimum execution time: 2_688_000 picoseconds. + Weight::from_parts(2_874_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) @@ -323,8 +326,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_350_000 picoseconds. - Weight::from_parts(6_560_000, 0) + // Minimum execution time: 3_108_000 picoseconds. + Weight::from_parts(3_263_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) @@ -333,10 +336,10 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `218` + // Measured: `251` // Estimated: `67035` - // Minimum execution time: 11_121_000 picoseconds. - Weight::from_parts(11_530_000, 67035) + // Minimum execution time: 5_993_000 picoseconds. + Weight::from_parts(6_359_000, 67035) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) @@ -344,12 +347,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1089 + n * (271 ±0)` + // Measured: `1122 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 21_891_000 picoseconds. - Weight::from_parts(18_572_306, 3834) - // Standard Error: 3_236 - .saturating_add(Weight::from_parts(1_648_429, 0).saturating_mul(n.into())) + // Minimum execution time: 16_003_000 picoseconds. + Weight::from_parts(14_453_014, 3834) + // Standard Error: 3_305 + .saturating_add(Weight::from_parts(1_325_026, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) diff --git a/substrate/frame/multisig/src/weights.rs b/substrate/frame/multisig/src/weights.rs index 7b87d258d38..4cbe7bb03b7 100644 --- a/substrate/frame/multisig/src/weights.rs +++ b/substrate/frame/multisig/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_multisig +//! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/multisig/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/multisig/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_multisig. +/// Weight functions needed for `pallet_multisig`. pub trait WeightInfo { fn as_multi_threshold_1(z: u32, ) -> Weight; fn as_multi_create(s: u32, z: u32, ) -> Weight; @@ -61,220 +60,238 @@ pub trait WeightInfo { fn cancel_as_multi(s: u32, ) -> Weight; } -/// Weights for pallet_multisig using the Substrate node and recommended hardware. +/// Weights for `pallet_multisig` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 13_452_000 picoseconds. - Weight::from_parts(14_425_869, 0) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 18_893_000 picoseconds. + Weight::from_parts(20_278_307, 3997) // Standard Error: 4 - .saturating_add(Weight::from_parts(493, 0).saturating_mul(z.into())) + .saturating_add(Weight::from_parts(488, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `301 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 46_012_000 picoseconds. - Weight::from_parts(34_797_344, 6811) - // Standard Error: 833 - .saturating_add(Weight::from_parts(127_671, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_498, 0).saturating_mul(z.into())) + // Minimum execution time: 39_478_000 picoseconds. + Weight::from_parts(29_195_487, 6811) + // Standard Error: 739 + .saturating_add(Weight::from_parts(118_766, 0).saturating_mul(s.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_511, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `320` // Estimated: `6811` - // Minimum execution time: 29_834_000 picoseconds. - Weight::from_parts(20_189_154, 6811) - // Standard Error: 637 - .saturating_add(Weight::from_parts(110_080, 0).saturating_mul(s.into())) - // Standard Error: 6 - .saturating_add(Weight::from_parts(1_483, 0).saturating_mul(z.into())) + // Minimum execution time: 26_401_000 picoseconds. + Weight::from_parts(17_277_296, 6811) + // Standard Error: 492 + .saturating_add(Weight::from_parts(101_763, 0).saturating_mul(s.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(1_486, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `426 + s * (33 ±0)` + // Measured: `571 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 51_464_000 picoseconds. - Weight::from_parts(39_246_644, 6811) - // Standard Error: 1_251 - .saturating_add(Weight::from_parts(143_313, 0).saturating_mul(s.into())) + // Minimum execution time: 52_430_000 picoseconds. + Weight::from_parts(40_585_478, 6811) + // Standard Error: 1_240 + .saturating_add(Weight::from_parts(161_405, 0).saturating_mul(s.into())) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_523, 0).saturating_mul(z.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(Weight::from_parts(1_547, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `301 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 33_275_000 picoseconds. - Weight::from_parts(34_073_221, 6811) - // Standard Error: 1_163 - .saturating_add(Weight::from_parts(124_815, 0).saturating_mul(s.into())) + // Minimum execution time: 27_797_000 picoseconds. + Weight::from_parts(29_064_584, 6811) + // Standard Error: 817 + .saturating_add(Weight::from_parts(108_179, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `320` // Estimated: `6811` - // Minimum execution time: 18_411_000 picoseconds. - Weight::from_parts(19_431_787, 6811) - // Standard Error: 694 - .saturating_add(Weight::from_parts(107_220, 0).saturating_mul(s.into())) + // Minimum execution time: 15_236_000 picoseconds. + Weight::from_parts(16_360_247, 6811) + // Standard Error: 584 + .saturating_add(Weight::from_parts(94_917, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `492 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 33_985_000 picoseconds. - Weight::from_parts(35_547_970, 6811) - // Standard Error: 1_135 - .saturating_add(Weight::from_parts(116_537, 0).saturating_mul(s.into())) + // Minimum execution time: 28_730_000 picoseconds. + Weight::from_parts(30_056_661, 6811) + // Standard Error: 792 + .saturating_add(Weight::from_parts(108_212, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 13_452_000 picoseconds. - Weight::from_parts(14_425_869, 0) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 18_893_000 picoseconds. + Weight::from_parts(20_278_307, 3997) // Standard Error: 4 - .saturating_add(Weight::from_parts(493, 0).saturating_mul(z.into())) + .saturating_add(Weight::from_parts(488, 0).saturating_mul(z.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `301 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 46_012_000 picoseconds. - Weight::from_parts(34_797_344, 6811) - // Standard Error: 833 - .saturating_add(Weight::from_parts(127_671, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_498, 0).saturating_mul(z.into())) + // Minimum execution time: 39_478_000 picoseconds. + Weight::from_parts(29_195_487, 6811) + // Standard Error: 739 + .saturating_add(Weight::from_parts(118_766, 0).saturating_mul(s.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_511, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `320` // Estimated: `6811` - // Minimum execution time: 29_834_000 picoseconds. - Weight::from_parts(20_189_154, 6811) - // Standard Error: 637 - .saturating_add(Weight::from_parts(110_080, 0).saturating_mul(s.into())) - // Standard Error: 6 - .saturating_add(Weight::from_parts(1_483, 0).saturating_mul(z.into())) + // Minimum execution time: 26_401_000 picoseconds. + Weight::from_parts(17_277_296, 6811) + // Standard Error: 492 + .saturating_add(Weight::from_parts(101_763, 0).saturating_mul(s.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(1_486, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `426 + s * (33 ±0)` + // Measured: `571 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 51_464_000 picoseconds. - Weight::from_parts(39_246_644, 6811) - // Standard Error: 1_251 - .saturating_add(Weight::from_parts(143_313, 0).saturating_mul(s.into())) + // Minimum execution time: 52_430_000 picoseconds. + Weight::from_parts(40_585_478, 6811) + // Standard Error: 1_240 + .saturating_add(Weight::from_parts(161_405, 0).saturating_mul(s.into())) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_523, 0).saturating_mul(z.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(Weight::from_parts(1_547, 0).saturating_mul(z.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `301 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 33_275_000 picoseconds. - Weight::from_parts(34_073_221, 6811) - // Standard Error: 1_163 - .saturating_add(Weight::from_parts(124_815, 0).saturating_mul(s.into())) + // Minimum execution time: 27_797_000 picoseconds. + Weight::from_parts(29_064_584, 6811) + // Standard Error: 817 + .saturating_add(Weight::from_parts(108_179, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `320` // Estimated: `6811` - // Minimum execution time: 18_411_000 picoseconds. - Weight::from_parts(19_431_787, 6811) - // Standard Error: 694 - .saturating_add(Weight::from_parts(107_220, 0).saturating_mul(s.into())) + // Minimum execution time: 15_236_000 picoseconds. + Weight::from_parts(16_360_247, 6811) + // Standard Error: 584 + .saturating_add(Weight::from_parts(94_917, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `492 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 33_985_000 picoseconds. - Weight::from_parts(35_547_970, 6811) - // Standard Error: 1_135 - .saturating_add(Weight::from_parts(116_537, 0).saturating_mul(s.into())) + // Minimum execution time: 28_730_000 picoseconds. + Weight::from_parts(30_056_661, 6811) + // Standard Error: 792 + .saturating_add(Weight::from_parts(108_212, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/nft-fractionalization/src/weights.rs b/substrate/frame/nft-fractionalization/src/weights.rs index ebb4aa0fbcf..07872ebaea9 100644 --- a/substrate/frame/nft-fractionalization/src/weights.rs +++ b/substrate/frame/nft-fractionalization/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_nft_fractionalization +//! Autogenerated weights for `pallet_nft_fractionalization` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/nft-fractionalization/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/nft-fractionalization/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,136 +49,136 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_nft_fractionalization. +/// Weight functions needed for `pallet_nft_fractionalization`. pub trait WeightInfo { fn fractionalize() -> Weight; fn unify() -> Weight; } -/// Weights for pallet_nft_fractionalization using the Substrate node and recommended hardware. +/// Weights for `pallet_nft_fractionalization` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: NftFractionalization NftToAsset (r:0 w:1) - /// Proof: NftFractionalization NftToAsset (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: `NftFractionalization::NftToAsset` (r:0 w:1) + /// Proof: `NftFractionalization::NftToAsset` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn fractionalize() -> Weight { // Proof Size summary in bytes: // Measured: `609` // Estimated: `4326` - // Minimum execution time: 187_416_000 picoseconds. - Weight::from_parts(191_131_000, 4326) + // Minimum execution time: 164_764_000 picoseconds. + Weight::from_parts(168_243_000, 4326) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } - /// Storage: NftFractionalization NftToAsset (r:1 w:1) - /// Proof: NftFractionalization NftToAsset (max_values: None, max_size: Some(92), added: 2567, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: `NftFractionalization::NftToAsset` (r:1 w:1) + /// Proof: `NftFractionalization::NftToAsset` (`max_values`: None, `max_size`: Some(92), added: 2567, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn unify() -> Weight { // Proof Size summary in bytes: // Measured: `1422` // Estimated: `4326` - // Minimum execution time: 134_159_000 picoseconds. - Weight::from_parts(136_621_000, 4326) + // Minimum execution time: 120_036_000 picoseconds. + Weight::from_parts(123_550_000, 4326) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Assets Metadata (r:1 w:1) - /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: NftFractionalization NftToAsset (r:0 w:1) - /// Proof: NftFractionalization NftToAsset (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Assets::Metadata` (r:1 w:1) + /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: `NftFractionalization::NftToAsset` (r:0 w:1) + /// Proof: `NftFractionalization::NftToAsset` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn fractionalize() -> Weight { // Proof Size summary in bytes: // Measured: `609` // Estimated: `4326` - // Minimum execution time: 187_416_000 picoseconds. - Weight::from_parts(191_131_000, 4326) + // Minimum execution time: 164_764_000 picoseconds. + Weight::from_parts(168_243_000, 4326) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } - /// Storage: NftFractionalization NftToAsset (r:1 w:1) - /// Proof: NftFractionalization NftToAsset (max_values: None, max_size: Some(92), added: 2567, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: `NftFractionalization::NftToAsset` (r:1 w:1) + /// Proof: `NftFractionalization::NftToAsset` (`max_values`: None, `max_size`: Some(92), added: 2567, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn unify() -> Weight { // Proof Size summary in bytes: // Measured: `1422` // Estimated: `4326` - // Minimum execution time: 134_159_000 picoseconds. - Weight::from_parts(136_621_000, 4326) + // Minimum execution time: 120_036_000 picoseconds. + Weight::from_parts(123_550_000, 4326) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } diff --git a/substrate/frame/nfts/src/weights.rs b/substrate/frame/nfts/src/weights.rs index 6b8c577bb12..4fcc1e601f4 100644 --- a/substrate/frame/nfts/src/weights.rs +++ b/substrate/frame/nfts/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_nfts +//! Autogenerated weights for `pallet_nfts` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -37,9 +37,9 @@ // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/nfts/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/nfts/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_nfts. +/// Weight functions needed for `pallet_nfts`. pub trait WeightInfo { fn create() -> Weight; fn force_create() -> Weight; @@ -92,564 +92,568 @@ pub trait WeightInfo { fn set_attributes_pre_signed(n: u32, ) -> Weight; } -/// Weights for pallet_nfts using the Substrate node and recommended hardware. +/// Weights for `pallet_nfts` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Nfts NextCollectionId (r:1 w:1) - /// Proof: Nfts NextCollectionId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:0 w:1) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:0 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:1) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3549` - // Minimum execution time: 40_489_000 picoseconds. - Weight::from_parts(41_320_000, 3549) + // Minimum execution time: 34_035_000 picoseconds. + Weight::from_parts(35_228_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Nfts NextCollectionId (r:1 w:1) - /// Proof: Nfts NextCollectionId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:0 w:1) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:0 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:1) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3549` - // Minimum execution time: 23_257_000 picoseconds. - Weight::from_parts(23_770_000, 3549) + // Minimum execution time: 19_430_000 picoseconds. + Weight::from_parts(20_054_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:0) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:1 w:1) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1001 w:1000) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1000 w:1000) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts CollectionMetadataOf (r:0 w:1) - /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:0 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:1) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32220 + a * (332 ±0)` - // Estimated: `2523990 + a * (2921 ±0)` - // Minimum execution time: 1_310_198_000 picoseconds. - Weight::from_parts(1_479_261_043, 2523990) - // Standard Error: 4_415 - .saturating_add(Weight::from_parts(6_016_212, 0).saturating_mul(a.into())) + // Measured: `32204 + a * (366 ±0)` + // Estimated: `2523990 + a * (2954 ±0)` + // Minimum execution time: 1_249_733_000 picoseconds. + Weight::from_parts(1_293_703_849, 2523990) + // Standard Error: 4_764 + .saturating_add(Weight::from_parts(6_433_523, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1004_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) - .saturating_add(Weight::from_parts(0, 2921).saturating_mul(a.into())) - } - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + .saturating_add(Weight::from_parts(0, 2954).saturating_mul(a.into())) + } + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: // Measured: `455` // Estimated: `4326` - // Minimum execution time: 51_910_000 picoseconds. - Weight::from_parts(53_441_000, 4326) + // Minimum execution time: 48_645_000 picoseconds. + Weight::from_parts(50_287_000, 4326) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: // Measured: `455` // Estimated: `4326` - // Minimum execution time: 50_168_000 picoseconds. - Weight::from_parts(51_380_000, 4326) + // Minimum execution time: 46_688_000 picoseconds. + Weight::from_parts(47_680_000, 4326) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:0) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) - /// Storage: Nfts ItemAttributesApprovalsOf (r:0 w:1) - /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: // Measured: `564` // Estimated: `4326` - // Minimum execution time: 50_738_000 picoseconds. - Weight::from_parts(51_850_000, 4326) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Minimum execution time: 51_771_000 picoseconds. + Weight::from_parts(53_492_000, 4326) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:0) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:2) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `593` // Estimated: `4326` - // Minimum execution time: 41_055_000 picoseconds. - Weight::from_parts(42_336_000, 4326) + // Minimum execution time: 39_166_000 picoseconds. + Weight::from_parts(40_128_000, 4326) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:5000 w:5000) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:5000 w:5000) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `763 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 15_688_000 picoseconds. - Weight::from_parts(15_921_000, 3549) - // Standard Error: 14_827 - .saturating_add(Weight::from_parts(17_105_395, 0).saturating_mul(i.into())) + // Minimum execution time: 13_804_000 picoseconds. + Weight::from_parts(14_159_000, 3549) + // Standard Error: 13_812 + .saturating_add(Weight::from_parts(14_661_284, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3336).saturating_mul(i.into())) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 19_981_000 picoseconds. - Weight::from_parts(20_676_000, 3534) + // Minimum execution time: 17_485_000 picoseconds. + Weight::from_parts(18_412_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 19_911_000 picoseconds. - Weight::from_parts(20_612_000, 3534) + // Minimum execution time: 17_335_000 picoseconds. + Weight::from_parts(18_543_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3549` - // Minimum execution time: 16_441_000 picoseconds. - Weight::from_parts(16_890_000, 3549) + // Minimum execution time: 14_608_000 picoseconds. + Weight::from_parts(15_696_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts OwnershipAcceptance (r:1 w:1) - /// Proof: Nfts OwnershipAcceptance (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:2) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `388` - // Estimated: `3549` - // Minimum execution time: 22_610_000 picoseconds. - Weight::from_parts(23_422_000, 3549) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Measured: `562` + // Estimated: `3593` + // Minimum execution time: 25_686_000 picoseconds. + Weight::from_parts(26_433_000, 3593) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:2 w:4) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: // Measured: `369` // Estimated: `6078` - // Minimum execution time: 39_739_000 picoseconds. - Weight::from_parts(41_306_000, 6078) + // Minimum execution time: 37_192_000 picoseconds. + Weight::from_parts(38_561_000, 6078) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:2) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: // Measured: `311` // Estimated: `3549` - // Minimum execution time: 17_685_000 picoseconds. - Weight::from_parts(18_258_000, 3549) + // Minimum execution time: 15_401_000 picoseconds. + Weight::from_parts(15_826_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:0 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `276` // Estimated: `3549` - // Minimum execution time: 13_734_000 picoseconds. - Weight::from_parts(14_337_000, 3549) + // Minimum execution time: 11_683_000 picoseconds. + Weight::from_parts(12_255_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 19_269_000 picoseconds. - Weight::from_parts(19_859_000, 3534) + // Minimum execution time: 16_899_000 picoseconds. + Weight::from_parts(17_404_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: // Measured: `539` - // Estimated: `3911` - // Minimum execution time: 51_540_000 picoseconds. - Weight::from_parts(52_663_000, 3911) + // Estimated: `3944` + // Minimum execution time: 46_768_000 picoseconds. + Weight::from_parts(47_834_000, 3944) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: // Measured: `344` - // Estimated: `3911` - // Minimum execution time: 26_529_000 picoseconds. - Weight::from_parts(27_305_000, 3911) + // Estimated: `3944` + // Minimum execution time: 23_356_000 picoseconds. + Weight::from_parts(24_528_000, 3944) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `950` - // Estimated: `3911` - // Minimum execution time: 46_951_000 picoseconds. - Weight::from_parts(48_481_000, 3911) + // Measured: `983` + // Estimated: `3944` + // Minimum execution time: 43_061_000 picoseconds. + Weight::from_parts(44_024_000, 3944) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) - /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: // Measured: `381` // Estimated: `4326` - // Minimum execution time: 17_222_000 picoseconds. - Weight::from_parts(17_819_000, 4326) + // Minimum execution time: 14_929_000 picoseconds. + Weight::from_parts(15_344_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) - /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1001 w:1000) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `837 + n * (364 ±0)` - // Estimated: `4326 + n * (2921 ±0)` - // Minimum execution time: 26_185_000 picoseconds. - Weight::from_parts(27_038_000, 4326) - // Standard Error: 2_378 - .saturating_add(Weight::from_parts(6_067_888, 0).saturating_mul(n.into())) + // Measured: `831 + n * (398 ±0)` + // Estimated: `4326 + n * (2954 ±0)` + // Minimum execution time: 23_707_000 picoseconds. + Weight::from_parts(24_688_000, 4326) + // Standard Error: 3_813 + .saturating_add(Weight::from_parts(6_422_256, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) - } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:1) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `539` - // Estimated: `3605` - // Minimum execution time: 42_120_000 picoseconds. - Weight::from_parts(43_627_000, 3605) + // Estimated: `3812` + // Minimum execution time: 37_882_000 picoseconds. + Weight::from_parts(39_222_000, 3812) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:1) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `642` - // Estimated: `3605` - // Minimum execution time: 40_732_000 picoseconds. - Weight::from_parts(42_760_000, 3605) + // Measured: `849` + // Estimated: `3812` + // Minimum execution time: 36_629_000 picoseconds. + Weight::from_parts(37_351_000, 3812) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionMetadataOf (r:1 w:1) - /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `398` - // Estimated: `3552` - // Minimum execution time: 39_443_000 picoseconds. - Weight::from_parts(40_482_000, 3552) + // Estimated: `3759` + // Minimum execution time: 34_853_000 picoseconds. + Weight::from_parts(35_914_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts CollectionMetadataOf (r:1 w:1) - /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `509` - // Estimated: `3552` - // Minimum execution time: 37_676_000 picoseconds. - Weight::from_parts(39_527_000, 3552) + // Measured: `716` + // Estimated: `3759` + // Minimum execution time: 33_759_000 picoseconds. + Weight::from_parts(34_729_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `410` // Estimated: `4326` - // Minimum execution time: 20_787_000 picoseconds. - Weight::from_parts(21_315_000, 4326) + // Minimum execution time: 17_583_000 picoseconds. + Weight::from_parts(18_675_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `4326` - // Minimum execution time: 18_200_000 picoseconds. - Weight::from_parts(19_064_000, 4326) + // Minimum execution time: 15_036_000 picoseconds. + Weight::from_parts(15_995_000, 4326) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `4326` - // Minimum execution time: 17_128_000 picoseconds. - Weight::from_parts(17_952_000, 4326) + // Minimum execution time: 14_666_000 picoseconds. + Weight::from_parts(15_152_000, 4326) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts OwnershipAcceptance (r:1 w:1) - /// Proof: Nfts OwnershipAcceptance (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3517` - // Minimum execution time: 14_667_000 picoseconds. - Weight::from_parts(15_262_000, 3517) + // Minimum execution time: 12_393_000 picoseconds. + Weight::from_parts(12_895_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts CollectionConfigOf (r:1 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3549` - // Minimum execution time: 18_435_000 picoseconds. - Weight::from_parts(18_775_000, 3549) + // Minimum execution time: 16_034_000 picoseconds. + Weight::from_parts(16_617_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: // Measured: `323` // Estimated: `3538` - // Minimum execution time: 18_125_000 picoseconds. - Weight::from_parts(18_415_000, 3538) + // Minimum execution time: 15_812_000 picoseconds. + Weight::from_parts(16_644_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn set_price() -> Weight { // Proof Size summary in bytes: // Measured: `518` // Estimated: `4326` - // Minimum execution time: 23_237_000 picoseconds. - Weight::from_parts(24_128_000, 4326) + // Minimum execution time: 21_650_000 picoseconds. + Weight::from_parts(22_443_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:1 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:0) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:2) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: // Measured: `705` // Estimated: `4326` - // Minimum execution time: 53_291_000 picoseconds. - Weight::from_parts(54_614_000, 4326) + // Minimum execution time: 49_463_000 picoseconds. + Weight::from_parts(50_937_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -658,681 +662,685 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_192_000 picoseconds. - Weight::from_parts(4_039_901, 0) - // Standard Error: 10_309 - .saturating_add(Weight::from_parts(3_934_017, 0).saturating_mul(n.into())) - } - /// Storage: Nfts Item (r:2 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + // Minimum execution time: 2_029_000 picoseconds. + Weight::from_parts(3_749_829, 0) + // Standard Error: 8_497 + .saturating_add(Weight::from_parts(1_913_514, 0).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:2 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn create_swap() -> Weight { // Proof Size summary in bytes: // Measured: `494` // Estimated: `7662` - // Minimum execution time: 21_011_000 picoseconds. - Weight::from_parts(22_065_000, 7662) + // Minimum execution time: 18_181_000 picoseconds. + Weight::from_parts(18_698_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts PendingSwapOf (r:1 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: `Nfts::PendingSwapOf` (r:1 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_swap() -> Weight { // Proof Size summary in bytes: // Measured: `513` // Estimated: `4326` - // Minimum execution time: 21_423_000 picoseconds. - Weight::from_parts(21_743_000, 4326) + // Minimum execution time: 18_228_000 picoseconds. + Weight::from_parts(18_940_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:2 w:2) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:1 w:2) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:2 w:0) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:2 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:4) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:2) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:2 w:2) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:2 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:4) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: // Measured: `834` // Estimated: `7662` - // Minimum execution time: 86_059_000 picoseconds. - Weight::from_parts(88_401_000, 7662) + // Minimum execution time: 77_983_000 picoseconds. + Weight::from_parts(79_887_000, 7662) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } - /// Storage: Nfts CollectionRoleOf (r:2 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:10 w:10) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:1) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `629` - // Estimated: `6078 + n * (2921 ±0)` - // Minimum execution time: 146_746_000 picoseconds. - Weight::from_parts(152_885_862, 6078) - // Standard Error: 40_442 - .saturating_add(Weight::from_parts(32_887_800, 0).saturating_mul(n.into())) + // Estimated: `6078 + n * (2954 ±0)` + // Minimum execution time: 126_998_000 picoseconds. + Weight::from_parts(134_149_389, 6078) + // Standard Error: 33_180 + .saturating_add(Weight::from_parts(30_711_206, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) - } - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) - /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:10 w:10) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `659` - // Estimated: `4326 + n * (2921 ±0)` - // Minimum execution time: 83_960_000 picoseconds. - Weight::from_parts(98_609_885, 4326) - // Standard Error: 85_991 - .saturating_add(Weight::from_parts(32_633_495, 0).saturating_mul(n.into())) + // Estimated: `4326 + n * (2954 ±0)` + // Minimum execution time: 66_213_000 picoseconds. + Weight::from_parts(81_661_819, 4326) + // Standard Error: 87_003 + .saturating_add(Weight::from_parts(29_550_476, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Nfts NextCollectionId (r:1 w:1) - /// Proof: Nfts NextCollectionId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:0 w:1) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:0 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:1) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3549` - // Minimum execution time: 40_489_000 picoseconds. - Weight::from_parts(41_320_000, 3549) + // Minimum execution time: 34_035_000 picoseconds. + Weight::from_parts(35_228_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Nfts NextCollectionId (r:1 w:1) - /// Proof: Nfts NextCollectionId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:0 w:1) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:0 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:1) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3549` - // Minimum execution time: 23_257_000 picoseconds. - Weight::from_parts(23_770_000, 3549) + // Minimum execution time: 19_430_000 picoseconds. + Weight::from_parts(20_054_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:0) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:1 w:1) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1001 w:1000) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1000 w:1000) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts CollectionMetadataOf (r:0 w:1) - /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:0 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:1) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32220 + a * (332 ±0)` - // Estimated: `2523990 + a * (2921 ±0)` - // Minimum execution time: 1_310_198_000 picoseconds. - Weight::from_parts(1_479_261_043, 2523990) - // Standard Error: 4_415 - .saturating_add(Weight::from_parts(6_016_212, 0).saturating_mul(a.into())) + // Measured: `32204 + a * (366 ±0)` + // Estimated: `2523990 + a * (2954 ±0)` + // Minimum execution time: 1_249_733_000 picoseconds. + Weight::from_parts(1_293_703_849, 2523990) + // Standard Error: 4_764 + .saturating_add(Weight::from_parts(6_433_523, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(1004_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) - .saturating_add(Weight::from_parts(0, 2921).saturating_mul(a.into())) - } - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + .saturating_add(Weight::from_parts(0, 2954).saturating_mul(a.into())) + } + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: // Measured: `455` // Estimated: `4326` - // Minimum execution time: 51_910_000 picoseconds. - Weight::from_parts(53_441_000, 4326) + // Minimum execution time: 48_645_000 picoseconds. + Weight::from_parts(50_287_000, 4326) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: // Measured: `455` // Estimated: `4326` - // Minimum execution time: 50_168_000 picoseconds. - Weight::from_parts(51_380_000, 4326) + // Minimum execution time: 46_688_000 picoseconds. + Weight::from_parts(47_680_000, 4326) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:0) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) - /// Storage: Nfts ItemAttributesApprovalsOf (r:0 w:1) - /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: // Measured: `564` // Estimated: `4326` - // Minimum execution time: 50_738_000 picoseconds. - Weight::from_parts(51_850_000, 4326) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + // Minimum execution time: 51_771_000 picoseconds. + Weight::from_parts(53_492_000, 4326) + .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:0) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:2) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `593` // Estimated: `4326` - // Minimum execution time: 41_055_000 picoseconds. - Weight::from_parts(42_336_000, 4326) + // Minimum execution time: 39_166_000 picoseconds. + Weight::from_parts(40_128_000, 4326) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:5000 w:5000) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:5000 w:5000) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `763 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 15_688_000 picoseconds. - Weight::from_parts(15_921_000, 3549) - // Standard Error: 14_827 - .saturating_add(Weight::from_parts(17_105_395, 0).saturating_mul(i.into())) + // Minimum execution time: 13_804_000 picoseconds. + Weight::from_parts(14_159_000, 3549) + // Standard Error: 13_812 + .saturating_add(Weight::from_parts(14_661_284, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3336).saturating_mul(i.into())) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 19_981_000 picoseconds. - Weight::from_parts(20_676_000, 3534) + // Minimum execution time: 17_485_000 picoseconds. + Weight::from_parts(18_412_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 19_911_000 picoseconds. - Weight::from_parts(20_612_000, 3534) + // Minimum execution time: 17_335_000 picoseconds. + Weight::from_parts(18_543_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3549` - // Minimum execution time: 16_441_000 picoseconds. - Weight::from_parts(16_890_000, 3549) + // Minimum execution time: 14_608_000 picoseconds. + Weight::from_parts(15_696_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts OwnershipAcceptance (r:1 w:1) - /// Proof: Nfts OwnershipAcceptance (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:2) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `388` - // Estimated: `3549` - // Minimum execution time: 22_610_000 picoseconds. - Weight::from_parts(23_422_000, 3549) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Measured: `562` + // Estimated: `3593` + // Minimum execution time: 25_686_000 picoseconds. + Weight::from_parts(26_433_000, 3593) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:2 w:4) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: // Measured: `369` // Estimated: `6078` - // Minimum execution time: 39_739_000 picoseconds. - Weight::from_parts(41_306_000, 6078) + // Minimum execution time: 37_192_000 picoseconds. + Weight::from_parts(38_561_000, 6078) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionAccount (r:0 w:2) - /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: // Measured: `311` // Estimated: `3549` - // Minimum execution time: 17_685_000 picoseconds. - Weight::from_parts(18_258_000, 3549) + // Minimum execution time: 15_401_000 picoseconds. + Weight::from_parts(15_826_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:0 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `276` // Estimated: `3549` - // Minimum execution time: 13_734_000 picoseconds. - Weight::from_parts(14_337_000, 3549) + // Minimum execution time: 11_683_000 picoseconds. + Weight::from_parts(12_255_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 19_269_000 picoseconds. - Weight::from_parts(19_859_000, 3534) + // Minimum execution time: 16_899_000 picoseconds. + Weight::from_parts(17_404_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: // Measured: `539` - // Estimated: `3911` - // Minimum execution time: 51_540_000 picoseconds. - Weight::from_parts(52_663_000, 3911) + // Estimated: `3944` + // Minimum execution time: 46_768_000 picoseconds. + Weight::from_parts(47_834_000, 3944) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: // Measured: `344` - // Estimated: `3911` - // Minimum execution time: 26_529_000 picoseconds. - Weight::from_parts(27_305_000, 3911) + // Estimated: `3944` + // Minimum execution time: 23_356_000 picoseconds. + Weight::from_parts(24_528_000, 3944) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Nfts Attribute (r:1 w:1) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `950` - // Estimated: `3911` - // Minimum execution time: 46_951_000 picoseconds. - Weight::from_parts(48_481_000, 3911) + // Measured: `983` + // Estimated: `3944` + // Minimum execution time: 43_061_000 picoseconds. + Weight::from_parts(44_024_000, 3944) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) - /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: // Measured: `381` // Estimated: `4326` - // Minimum execution time: 17_222_000 picoseconds. - Weight::from_parts(17_819_000, 4326) + // Minimum execution time: 14_929_000 picoseconds. + Weight::from_parts(15_344_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) - /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1001 w:1000) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `837 + n * (364 ±0)` - // Estimated: `4326 + n * (2921 ±0)` - // Minimum execution time: 26_185_000 picoseconds. - Weight::from_parts(27_038_000, 4326) - // Standard Error: 2_378 - .saturating_add(Weight::from_parts(6_067_888, 0).saturating_mul(n.into())) + // Measured: `831 + n * (398 ±0)` + // Estimated: `4326 + n * (2954 ±0)` + // Minimum execution time: 23_707_000 picoseconds. + Weight::from_parts(24_688_000, 4326) + // Standard Error: 3_813 + .saturating_add(Weight::from_parts(6_422_256, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) - } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:1) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `539` - // Estimated: `3605` - // Minimum execution time: 42_120_000 picoseconds. - Weight::from_parts(43_627_000, 3605) + // Estimated: `3812` + // Minimum execution time: 37_882_000 picoseconds. + Weight::from_parts(39_222_000, 3812) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:1) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `642` - // Estimated: `3605` - // Minimum execution time: 40_732_000 picoseconds. - Weight::from_parts(42_760_000, 3605) + // Measured: `849` + // Estimated: `3812` + // Minimum execution time: 36_629_000 picoseconds. + Weight::from_parts(37_351_000, 3812) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionMetadataOf (r:1 w:1) - /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `398` - // Estimated: `3552` - // Minimum execution time: 39_443_000 picoseconds. - Weight::from_parts(40_482_000, 3552) + // Estimated: `3759` + // Minimum execution time: 34_853_000 picoseconds. + Weight::from_parts(35_914_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts CollectionMetadataOf (r:1 w:1) - /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `509` - // Estimated: `3552` - // Minimum execution time: 37_676_000 picoseconds. - Weight::from_parts(39_527_000, 3552) + // Measured: `716` + // Estimated: `3759` + // Minimum execution time: 33_759_000 picoseconds. + Weight::from_parts(34_729_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `410` // Estimated: `4326` - // Minimum execution time: 20_787_000 picoseconds. - Weight::from_parts(21_315_000, 4326) + // Minimum execution time: 17_583_000 picoseconds. + Weight::from_parts(18_675_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `4326` - // Minimum execution time: 18_200_000 picoseconds. - Weight::from_parts(19_064_000, 4326) + // Minimum execution time: 15_036_000 picoseconds. + Weight::from_parts(15_995_000, 4326) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `4326` - // Minimum execution time: 17_128_000 picoseconds. - Weight::from_parts(17_952_000, 4326) + // Minimum execution time: 14_666_000 picoseconds. + Weight::from_parts(15_152_000, 4326) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts OwnershipAcceptance (r:1 w:1) - /// Proof: Nfts OwnershipAcceptance (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3517` - // Minimum execution time: 14_667_000 picoseconds. - Weight::from_parts(15_262_000, 3517) + // Minimum execution time: 12_393_000 picoseconds. + Weight::from_parts(12_895_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts CollectionConfigOf (r:1 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3549` - // Minimum execution time: 18_435_000 picoseconds. - Weight::from_parts(18_775_000, 3549) + // Minimum execution time: 16_034_000 picoseconds. + Weight::from_parts(16_617_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts CollectionRoleOf (r:1 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:1) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: // Measured: `323` // Estimated: `3538` - // Minimum execution time: 18_125_000 picoseconds. - Weight::from_parts(18_415_000, 3538) + // Minimum execution time: 15_812_000 picoseconds. + Weight::from_parts(16_644_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn set_price() -> Weight { // Proof Size summary in bytes: // Measured: `518` // Estimated: `4326` - // Minimum execution time: 23_237_000 picoseconds. - Weight::from_parts(24_128_000, 4326) + // Minimum execution time: 21_650_000 picoseconds. + Weight::from_parts(22_443_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:1 w:1) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:1 w:0) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:2) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: // Measured: `705` // Estimated: `4326` - // Minimum execution time: 53_291_000 picoseconds. - Weight::from_parts(54_614_000, 4326) + // Minimum execution time: 49_463_000 picoseconds. + Weight::from_parts(50_937_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1341,120 +1349,120 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_192_000 picoseconds. - Weight::from_parts(4_039_901, 0) - // Standard Error: 10_309 - .saturating_add(Weight::from_parts(3_934_017, 0).saturating_mul(n.into())) - } - /// Storage: Nfts Item (r:2 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:0 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + // Minimum execution time: 2_029_000 picoseconds. + Weight::from_parts(3_749_829, 0) + // Standard Error: 8_497 + .saturating_add(Weight::from_parts(1_913_514, 0).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:2 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn create_swap() -> Weight { // Proof Size summary in bytes: // Measured: `494` // Estimated: `7662` - // Minimum execution time: 21_011_000 picoseconds. - Weight::from_parts(22_065_000, 7662) + // Minimum execution time: 18_181_000 picoseconds. + Weight::from_parts(18_698_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts PendingSwapOf (r:1 w:1) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: `Nfts::PendingSwapOf` (r:1 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_swap() -> Weight { // Proof Size summary in bytes: // Measured: `513` // Estimated: `4326` - // Minimum execution time: 21_423_000 picoseconds. - Weight::from_parts(21_743_000, 4326) + // Minimum execution time: 18_228_000 picoseconds. + Weight::from_parts(18_940_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nfts Item (r:2 w:2) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts PendingSwapOf (r:1 w:2) - /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:0) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:2 w:0) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:2 w:0) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:4) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) - /// Storage: Nfts ItemPriceOf (r:0 w:2) - /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: `Nfts::Item` (r:2 w:2) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:2 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:4) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: // Measured: `834` // Estimated: `7662` - // Minimum execution time: 86_059_000 picoseconds. - Weight::from_parts(88_401_000, 7662) + // Minimum execution time: 77_983_000 picoseconds. + Weight::from_parts(79_887_000, 7662) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } - /// Storage: Nfts CollectionRoleOf (r:2 w:0) - /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Item (r:1 w:1) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts ItemConfigOf (r:1 w:1) - /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:10 w:10) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: Nfts ItemMetadataOf (r:1 w:1) - /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) - /// Storage: Nfts Account (r:0 w:1) - /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `629` - // Estimated: `6078 + n * (2921 ±0)` - // Minimum execution time: 146_746_000 picoseconds. - Weight::from_parts(152_885_862, 6078) - // Standard Error: 40_442 - .saturating_add(Weight::from_parts(32_887_800, 0).saturating_mul(n.into())) + // Estimated: `6078 + n * (2954 ±0)` + // Minimum execution time: 126_998_000 picoseconds. + Weight::from_parts(134_149_389, 6078) + // Standard Error: 33_180 + .saturating_add(Weight::from_parts(30_711_206, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) - } - /// Storage: Nfts Item (r:1 w:0) - /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) - /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) - /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) - /// Storage: Nfts CollectionConfigOf (r:1 w:0) - /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) - /// Storage: Nfts Collection (r:1 w:1) - /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) - /// Storage: Nfts Attribute (r:10 w:10) - /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `659` - // Estimated: `4326 + n * (2921 ±0)` - // Minimum execution time: 83_960_000 picoseconds. - Weight::from_parts(98_609_885, 4326) - // Standard Error: 85_991 - .saturating_add(Weight::from_parts(32_633_495, 0).saturating_mul(n.into())) + // Estimated: `4326 + n * (2954 ±0)` + // Minimum execution time: 66_213_000 picoseconds. + Weight::from_parts(81_661_819, 4326) + // Standard Error: 87_003 + .saturating_add(Weight::from_parts(29_550_476, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } } diff --git a/substrate/frame/nis/src/weights.rs b/substrate/frame/nis/src/weights.rs index cba2f004905..63908271391 100644 --- a/substrate/frame/nis/src/weights.rs +++ b/substrate/frame/nis/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_nis +//! Autogenerated weights for `pallet_nis` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/nis/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/nis/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_nis. +/// Weight functions needed for `pallet_nis`. pub trait WeightInfo { fn place_bid(l: u32, ) -> Weight; fn place_bid_max() -> Weight; @@ -65,367 +64,367 @@ pub trait WeightInfo { fn process_bid() -> Weight; } -/// Weights for pallet_nis using the Substrate node and recommended hardware. +/// Weights for `pallet_nis` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 999]`. fn place_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6176 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 49_410_000 picoseconds. - Weight::from_parts(57_832_282, 51487) - // Standard Error: 288 - .saturating_add(Weight::from_parts(51_621, 0).saturating_mul(l.into())) + // Minimum execution time: 47_908_000 picoseconds. + Weight::from_parts(50_096_676, 51487) + // Standard Error: 208 + .saturating_add(Weight::from_parts(41_318, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) fn place_bid_max() -> Weight { // Proof Size summary in bytes: // Measured: `54178` // Estimated: `51487` - // Minimum execution time: 119_696_000 picoseconds. - Weight::from_parts(121_838_000, 51487) + // Minimum execution time: 100_836_000 picoseconds. + Weight::from_parts(102_497_000, 51487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) /// The range of component `l` is `[1, 1000]`. fn retract_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6176 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 50_843_000 picoseconds. - Weight::from_parts(54_237_365, 51487) - // Standard Error: 243 - .saturating_add(Weight::from_parts(67_732, 0).saturating_mul(l.into())) + // Minimum execution time: 45_830_000 picoseconds. + Weight::from_parts(46_667_676, 51487) + // Standard Error: 130 + .saturating_add(Weight::from_parts(33_007, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Nis Summary (r:1 w:0) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Nis::Summary` (r:1 w:0) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn fund_deficit() -> Weight { // Proof Size summary in bytes: // Measured: `191` // Estimated: `3593` - // Minimum execution time: 40_752_000 picoseconds. - Weight::from_parts(41_899_000, 3593) + // Minimum execution time: 30_440_000 picoseconds. + Weight::from_parts(31_240_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn communify() -> Weight { // Proof Size summary in bytes: // Measured: `668` // Estimated: `3675` - // Minimum execution time: 79_779_000 picoseconds. - Weight::from_parts(82_478_000, 3675) + // Minimum execution time: 71_017_000 picoseconds. + Weight::from_parts(72_504_000, 3675) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn privatize() -> Weight { // Proof Size summary in bytes: // Measured: `829` // Estimated: `3675` - // Minimum execution time: 99_588_000 picoseconds. - Weight::from_parts(102_340_000, 3675) + // Minimum execution time: 89_138_000 picoseconds. + Weight::from_parts(91_290_000, 3675) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn thaw_private() -> Weight { // Proof Size summary in bytes: // Measured: `354` - // Estimated: `3593` - // Minimum execution time: 53_094_000 picoseconds. - Weight::from_parts(54_543_000, 3593) + // Estimated: `3658` + // Minimum execution time: 47_917_000 picoseconds. + Weight::from_parts(49_121_000, 3658) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn thaw_communal() -> Weight { // Proof Size summary in bytes: // Measured: `773` // Estimated: `3675` - // Minimum execution time: 107_248_000 picoseconds. - Weight::from_parts(109_923_000, 3675) + // Minimum execution time: 91_320_000 picoseconds. + Weight::from_parts(93_080_000, 3675) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) fn process_queues() -> Weight { // Proof Size summary in bytes: // Measured: `6624` // Estimated: `7487` - // Minimum execution time: 27_169_000 picoseconds. - Weight::from_parts(29_201_000, 7487) + // Minimum execution time: 20_117_000 picoseconds. + Weight::from_parts(20_829_000, 7487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) fn process_queue() -> Weight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `51487` - // Minimum execution time: 4_540_000 picoseconds. - Weight::from_parts(4_699_000, 51487) + // Minimum execution time: 4_460_000 picoseconds. + Weight::from_parts(4_797_000, 51487) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nis Receipts (r:0 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:0 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) fn process_bid() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_085_000 picoseconds. - Weight::from_parts(7_336_000, 0) + // Minimum execution time: 4_609_000 picoseconds. + Weight::from_parts(4_834_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 999]`. fn place_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6176 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 49_410_000 picoseconds. - Weight::from_parts(57_832_282, 51487) - // Standard Error: 288 - .saturating_add(Weight::from_parts(51_621, 0).saturating_mul(l.into())) + // Minimum execution time: 47_908_000 picoseconds. + Weight::from_parts(50_096_676, 51487) + // Standard Error: 208 + .saturating_add(Weight::from_parts(41_318, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) fn place_bid_max() -> Weight { // Proof Size summary in bytes: // Measured: `54178` // Estimated: `51487` - // Minimum execution time: 119_696_000 picoseconds. - Weight::from_parts(121_838_000, 51487) + // Minimum execution time: 100_836_000 picoseconds. + Weight::from_parts(102_497_000, 51487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) /// The range of component `l` is `[1, 1000]`. fn retract_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6176 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 50_843_000 picoseconds. - Weight::from_parts(54_237_365, 51487) - // Standard Error: 243 - .saturating_add(Weight::from_parts(67_732, 0).saturating_mul(l.into())) + // Minimum execution time: 45_830_000 picoseconds. + Weight::from_parts(46_667_676, 51487) + // Standard Error: 130 + .saturating_add(Weight::from_parts(33_007, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Nis Summary (r:1 w:0) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Nis::Summary` (r:1 w:0) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn fund_deficit() -> Weight { // Proof Size summary in bytes: // Measured: `191` // Estimated: `3593` - // Minimum execution time: 40_752_000 picoseconds. - Weight::from_parts(41_899_000, 3593) + // Minimum execution time: 30_440_000 picoseconds. + Weight::from_parts(31_240_000, 3593) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn communify() -> Weight { // Proof Size summary in bytes: // Measured: `668` // Estimated: `3675` - // Minimum execution time: 79_779_000 picoseconds. - Weight::from_parts(82_478_000, 3675) + // Minimum execution time: 71_017_000 picoseconds. + Weight::from_parts(72_504_000, 3675) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn privatize() -> Weight { // Proof Size summary in bytes: // Measured: `829` // Estimated: `3675` - // Minimum execution time: 99_588_000 picoseconds. - Weight::from_parts(102_340_000, 3675) + // Minimum execution time: 89_138_000 picoseconds. + Weight::from_parts(91_290_000, 3675) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Balances Holds (r:1 w:1) - /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn thaw_private() -> Weight { // Proof Size summary in bytes: // Measured: `354` - // Estimated: `3593` - // Minimum execution time: 53_094_000 picoseconds. - Weight::from_parts(54_543_000, 3593) + // Estimated: `3658` + // Minimum execution time: 47_917_000 picoseconds. + Weight::from_parts(49_121_000, 3658) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Nis Receipts (r:1 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, 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:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:1 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn thaw_communal() -> Weight { // Proof Size summary in bytes: // Measured: `773` // Estimated: `3675` - // Minimum execution time: 107_248_000 picoseconds. - Weight::from_parts(109_923_000, 3675) + // Minimum execution time: 91_320_000 picoseconds. + Weight::from_parts(93_080_000, 3675) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Nis Summary (r:1 w:1) - /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Nis QueueTotals (r:1 w:1) - /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) + /// Storage: `Nis::Summary` (r:1 w:1) + /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nis::QueueTotals` (r:1 w:1) + /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) fn process_queues() -> Weight { // Proof Size summary in bytes: // Measured: `6624` // Estimated: `7487` - // Minimum execution time: 27_169_000 picoseconds. - Weight::from_parts(29_201_000, 7487) + // Minimum execution time: 20_117_000 picoseconds. + Weight::from_parts(20_829_000, 7487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Nis Queues (r:1 w:1) - /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: `Nis::Queues` (r:1 w:1) + /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) fn process_queue() -> Weight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `51487` - // Minimum execution time: 4_540_000 picoseconds. - Weight::from_parts(4_699_000, 51487) + // Minimum execution time: 4_460_000 picoseconds. + Weight::from_parts(4_797_000, 51487) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nis Receipts (r:0 w:1) - /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: `Nis::Receipts` (r:0 w:1) + /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) fn process_bid() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_085_000 picoseconds. - Weight::from_parts(7_336_000, 0) + // Minimum execution time: 4_609_000 picoseconds. + Weight::from_parts(4_834_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/nomination-pools/src/weights.rs b/substrate/frame/nomination-pools/src/weights.rs index 047a17c3f9a..2749af7937f 100644 --- a/substrate/frame/nomination-pools/src/weights.rs +++ b/substrate/frame/nomination-pools/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_nomination_pools` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_nomination_pools +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_nomination_pools -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/nomination-pools/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -112,8 +114,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3425` // Estimated: `8877` - // Minimum execution time: 184_295_000 picoseconds. - Weight::from_parts(188_860_000, 8877) + // Minimum execution time: 181_861_000 picoseconds. + Weight::from_parts(186_375_000, 8877) .saturating_add(T::DbWeight::get().reads(20_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } @@ -145,8 +147,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3435` // Estimated: `8877` - // Minimum execution time: 188_777_000 picoseconds. - Weight::from_parts(192_646_000, 8877) + // Minimum execution time: 182_273_000 picoseconds. + Weight::from_parts(186_635_000, 8877) .saturating_add(T::DbWeight::get().reads(17_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } @@ -180,8 +182,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3500` // Estimated: `8877` - // Minimum execution time: 221_728_000 picoseconds. - Weight::from_parts(227_569_000, 8877) + // Minimum execution time: 217_878_000 picoseconds. + Weight::from_parts(221_493_000, 8877) .saturating_add(T::DbWeight::get().reads(18_u64)) .saturating_add(T::DbWeight::get().writes(14_u64)) } @@ -201,8 +203,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1172` // Estimated: `3719` - // Minimum execution time: 75_310_000 picoseconds. - Weight::from_parts(77_709_000, 3719) + // Minimum execution time: 74_509_000 picoseconds. + Weight::from_parts(76_683_000, 3719) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -242,8 +244,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3622` // Estimated: `27847` - // Minimum execution time: 170_656_000 picoseconds. - Weight::from_parts(174_950_000, 27847) + // Minimum execution time: 166_424_000 picoseconds. + Weight::from_parts(169_698_000, 27847) .saturating_add(T::DbWeight::get().reads(20_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } @@ -259,18 +261,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1817` + // Measured: `1848` // Estimated: `4764` - // Minimum execution time: 68_866_000 picoseconds. - Weight::from_parts(72_312_887, 4764) - // Standard Error: 1_635 - .saturating_add(Weight::from_parts(41_679, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Minimum execution time: 66_110_000 picoseconds. + Weight::from_parts(68_620_141, 4764) + // Standard Error: 1_379 + .saturating_add(Weight::from_parts(54_961, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -291,6 +295,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) @@ -300,13 +306,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2207` + // Measured: `2238` // Estimated: `27847` - // Minimum execution time: 131_383_000 picoseconds. - Weight::from_parts(136_595_971, 27847) - // Standard Error: 2_715 - .saturating_add(Weight::from_parts(52_351, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(11_u64)) + // Minimum execution time: 125_669_000 picoseconds. + Weight::from_parts(130_907_641, 27847) + // Standard Error: 2_490 + .saturating_add(Weight::from_parts(75_219, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -333,12 +339,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:0) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::RewardPools` (r:1 w:1) @@ -360,8 +366,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2525` // Estimated: `27847` - // Minimum execution time: 233_314_000 picoseconds. - Weight::from_parts(241_694_316, 27847) + // Minimum execution time: 225_700_000 picoseconds. + Weight::from_parts(234_390_990, 27847) .saturating_add(T::DbWeight::get().reads(24_u64)) .saturating_add(T::DbWeight::get().writes(20_u64)) } @@ -413,8 +419,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1169` // Estimated: `8538` - // Minimum execution time: 171_465_000 picoseconds. - Weight::from_parts(176_478_000, 8538) + // Minimum execution time: 167_171_000 picoseconds. + Weight::from_parts(170_531_000, 8538) .saturating_add(T::DbWeight::get().reads(23_u64)) .saturating_add(T::DbWeight::get().writes(17_u64)) } @@ -447,10 +453,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1808` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 63_588_000 picoseconds. - Weight::from_parts(64_930_584, 4556) - // Standard Error: 9_167 - .saturating_add(Weight::from_parts(1_595_779, 0).saturating_mul(n.into())) + // Minimum execution time: 63_785_000 picoseconds. + Weight::from_parts(64_592_302, 4556) + // Standard Error: 9_416 + .saturating_add(Weight::from_parts(1_524_398, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) @@ -466,8 +472,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1434` // Estimated: `4556` - // Minimum execution time: 32_899_000 picoseconds. - Weight::from_parts(33_955_000, 4556) + // Minimum execution time: 32_096_000 picoseconds. + Weight::from_parts(33_533_000, 4556) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -482,10 +488,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3735` - // Minimum execution time: 13_778_000 picoseconds. - Weight::from_parts(14_770_006, 3735) - // Standard Error: 151 - .saturating_add(Weight::from_parts(1_900, 0).saturating_mul(n.into())) + // Minimum execution time: 13_914_000 picoseconds. + Weight::from_parts(14_800_402, 3735) + // Standard Error: 146 + .saturating_add(Weight::from_parts(940, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -505,8 +511,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_550_000 picoseconds. - Weight::from_parts(4_935_000, 0) + // Minimum execution time: 4_373_000 picoseconds. + Weight::from_parts(4_592_000, 0) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -515,8 +521,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_759_000 picoseconds. - Weight::from_parts(17_346_000, 3719) + // Minimum execution time: 16_662_000 picoseconds. + Weight::from_parts(17_531_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -542,8 +548,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1971` // Estimated: `4556` - // Minimum execution time: 61_970_000 picoseconds. - Weight::from_parts(63_738_000, 4556) + // Minimum execution time: 61_348_000 picoseconds. + Weight::from_parts(63_712_000, 4556) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -559,8 +565,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `804` // Estimated: `3719` - // Minimum execution time: 31_950_000 picoseconds. - Weight::from_parts(33_190_000, 3719) + // Minimum execution time: 32_232_000 picoseconds. + Weight::from_parts(33_433_000, 3719) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -572,8 +578,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `572` // Estimated: `3719` - // Minimum execution time: 16_807_000 picoseconds. - Weight::from_parts(17_733_000, 3719) + // Minimum execution time: 16_774_000 picoseconds. + Weight::from_parts(17_671_000, 3719) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -583,8 +589,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_710_000 picoseconds. - Weight::from_parts(17_563_000, 3719) + // Minimum execution time: 16_724_000 picoseconds. + Weight::from_parts(17_181_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -594,8 +600,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_493_000 picoseconds. - Weight::from_parts(17_022_000, 3719) + // Minimum execution time: 16_362_000 picoseconds. + Weight::from_parts(17_135_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -607,8 +613,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `542` // Estimated: `3702` - // Minimum execution time: 14_248_000 picoseconds. - Weight::from_parts(15_095_000, 3702) + // Minimum execution time: 14_125_000 picoseconds. + Weight::from_parts(14_705_000, 3702) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -624,8 +630,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1002` // Estimated: `3719` - // Minimum execution time: 61_969_000 picoseconds. - Weight::from_parts(63_965_000, 3719) + // Minimum execution time: 61_699_000 picoseconds. + Weight::from_parts(63_605_000, 3719) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -641,8 +647,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `901` // Estimated: `4764` - // Minimum execution time: 65_462_000 picoseconds. - Weight::from_parts(67_250_000, 4764) + // Minimum execution time: 64_930_000 picoseconds. + Weight::from_parts(66_068_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -686,8 +692,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3425` // Estimated: `8877` - // Minimum execution time: 184_295_000 picoseconds. - Weight::from_parts(188_860_000, 8877) + // Minimum execution time: 181_861_000 picoseconds. + Weight::from_parts(186_375_000, 8877) .saturating_add(RocksDbWeight::get().reads(20_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } @@ -719,8 +725,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3435` // Estimated: `8877` - // Minimum execution time: 188_777_000 picoseconds. - Weight::from_parts(192_646_000, 8877) + // Minimum execution time: 182_273_000 picoseconds. + Weight::from_parts(186_635_000, 8877) .saturating_add(RocksDbWeight::get().reads(17_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } @@ -754,8 +760,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3500` // Estimated: `8877` - // Minimum execution time: 221_728_000 picoseconds. - Weight::from_parts(227_569_000, 8877) + // Minimum execution time: 217_878_000 picoseconds. + Weight::from_parts(221_493_000, 8877) .saturating_add(RocksDbWeight::get().reads(18_u64)) .saturating_add(RocksDbWeight::get().writes(14_u64)) } @@ -775,8 +781,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1172` // Estimated: `3719` - // Minimum execution time: 75_310_000 picoseconds. - Weight::from_parts(77_709_000, 3719) + // Minimum execution time: 74_509_000 picoseconds. + Weight::from_parts(76_683_000, 3719) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -816,8 +822,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3622` // Estimated: `27847` - // Minimum execution time: 170_656_000 picoseconds. - Weight::from_parts(174_950_000, 27847) + // Minimum execution time: 166_424_000 picoseconds. + Weight::from_parts(169_698_000, 27847) .saturating_add(RocksDbWeight::get().reads(20_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } @@ -833,18 +839,20 @@ impl WeightInfo for () { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1817` + // Measured: `1848` // Estimated: `4764` - // Minimum execution time: 68_866_000 picoseconds. - Weight::from_parts(72_312_887, 4764) - // Standard Error: 1_635 - .saturating_add(Weight::from_parts(41_679, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(7_u64)) + // Minimum execution time: 66_110_000 picoseconds. + Weight::from_parts(68_620_141, 4764) + // Standard Error: 1_379 + .saturating_add(Weight::from_parts(54_961, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -865,6 +873,8 @@ impl WeightInfo for () { /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) @@ -874,13 +884,13 @@ impl WeightInfo for () { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2207` + // Measured: `2238` // Estimated: `27847` - // Minimum execution time: 131_383_000 picoseconds. - Weight::from_parts(136_595_971, 27847) - // Standard Error: 2_715 - .saturating_add(Weight::from_parts(52_351, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(11_u64)) + // Minimum execution time: 125_669_000 picoseconds. + Weight::from_parts(130_907_641, 27847) + // Standard Error: 2_490 + .saturating_add(Weight::from_parts(75_219, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(9_u64)) } /// Storage: `NominationPools::PoolMembers` (r:1 w:1) @@ -907,12 +917,12 @@ impl WeightInfo for () { /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:0) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::RewardPools` (r:1 w:1) @@ -934,8 +944,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2525` // Estimated: `27847` - // Minimum execution time: 233_314_000 picoseconds. - Weight::from_parts(241_694_316, 27847) + // Minimum execution time: 225_700_000 picoseconds. + Weight::from_parts(234_390_990, 27847) .saturating_add(RocksDbWeight::get().reads(24_u64)) .saturating_add(RocksDbWeight::get().writes(20_u64)) } @@ -987,8 +997,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1169` // Estimated: `8538` - // Minimum execution time: 171_465_000 picoseconds. - Weight::from_parts(176_478_000, 8538) + // Minimum execution time: 167_171_000 picoseconds. + Weight::from_parts(170_531_000, 8538) .saturating_add(RocksDbWeight::get().reads(23_u64)) .saturating_add(RocksDbWeight::get().writes(17_u64)) } @@ -1021,10 +1031,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1808` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 63_588_000 picoseconds. - Weight::from_parts(64_930_584, 4556) - // Standard Error: 9_167 - .saturating_add(Weight::from_parts(1_595_779, 0).saturating_mul(n.into())) + // Minimum execution time: 63_785_000 picoseconds. + Weight::from_parts(64_592_302, 4556) + // Standard Error: 9_416 + .saturating_add(Weight::from_parts(1_524_398, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(5_u64)) @@ -1040,8 +1050,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1434` // Estimated: `4556` - // Minimum execution time: 32_899_000 picoseconds. - Weight::from_parts(33_955_000, 4556) + // Minimum execution time: 32_096_000 picoseconds. + Weight::from_parts(33_533_000, 4556) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1056,10 +1066,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3735` - // Minimum execution time: 13_778_000 picoseconds. - Weight::from_parts(14_770_006, 3735) - // Standard Error: 151 - .saturating_add(Weight::from_parts(1_900, 0).saturating_mul(n.into())) + // Minimum execution time: 13_914_000 picoseconds. + Weight::from_parts(14_800_402, 3735) + // Standard Error: 146 + .saturating_add(Weight::from_parts(940, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1079,8 +1089,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_550_000 picoseconds. - Weight::from_parts(4_935_000, 0) + // Minimum execution time: 4_373_000 picoseconds. + Weight::from_parts(4_592_000, 0) .saturating_add(RocksDbWeight::get().writes(6_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -1089,8 +1099,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_759_000 picoseconds. - Weight::from_parts(17_346_000, 3719) + // Minimum execution time: 16_662_000 picoseconds. + Weight::from_parts(17_531_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1116,8 +1126,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1971` // Estimated: `4556` - // Minimum execution time: 61_970_000 picoseconds. - Weight::from_parts(63_738_000, 4556) + // Minimum execution time: 61_348_000 picoseconds. + Weight::from_parts(63_712_000, 4556) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1133,8 +1143,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `804` // Estimated: `3719` - // Minimum execution time: 31_950_000 picoseconds. - Weight::from_parts(33_190_000, 3719) + // Minimum execution time: 32_232_000 picoseconds. + Weight::from_parts(33_433_000, 3719) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1146,8 +1156,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `572` // Estimated: `3719` - // Minimum execution time: 16_807_000 picoseconds. - Weight::from_parts(17_733_000, 3719) + // Minimum execution time: 16_774_000 picoseconds. + Weight::from_parts(17_671_000, 3719) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1157,8 +1167,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_710_000 picoseconds. - Weight::from_parts(17_563_000, 3719) + // Minimum execution time: 16_724_000 picoseconds. + Weight::from_parts(17_181_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1168,8 +1178,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_493_000 picoseconds. - Weight::from_parts(17_022_000, 3719) + // Minimum execution time: 16_362_000 picoseconds. + Weight::from_parts(17_135_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1181,8 +1191,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `542` // Estimated: `3702` - // Minimum execution time: 14_248_000 picoseconds. - Weight::from_parts(15_095_000, 3702) + // Minimum execution time: 14_125_000 picoseconds. + Weight::from_parts(14_705_000, 3702) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1198,8 +1208,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1002` // Estimated: `3719` - // Minimum execution time: 61_969_000 picoseconds. - Weight::from_parts(63_965_000, 3719) + // Minimum execution time: 61_699_000 picoseconds. + Weight::from_parts(63_605_000, 3719) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1215,8 +1225,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `901` // Estimated: `4764` - // Minimum execution time: 65_462_000 picoseconds. - Weight::from_parts(67_250_000, 4764) + // Minimum execution time: 64_930_000 picoseconds. + Weight::from_parts(66_068_000, 4764) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/offences/benchmarking/src/mock.rs b/substrate/frame/offences/benchmarking/src/mock.rs index 01ad8d64f10..b3260f0841f 100644 --- a/substrate/frame/offences/benchmarking/src/mock.rs +++ b/substrate/frame/offences/benchmarking/src/mock.rs @@ -148,7 +148,7 @@ parameter_types! { pub static ElectionsBounds: ElectionBounds = ElectionBoundsBuilder::default().build(); } -pub type Extrinsic = sp_runtime::testing::TestXt; +pub type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; pub struct OnChainSeqPhragmen; impl onchain::Config for OnChainSeqPhragmen { diff --git a/substrate/frame/parameters/src/weights.rs b/substrate/frame/parameters/src/weights.rs index 6746960b1b7..340eb9e31b7 100644 --- a/substrate/frame/parameters/src/weights.rs +++ b/substrate/frame/parameters/src/weights.rs @@ -18,25 +18,27 @@ //! Autogenerated weights for `pallet_parameters` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_parameters +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_parameters -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/parameters/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -55,22 +57,30 @@ pub trait WeightInfo { /// Weights for `pallet_parameters` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { + /// Storage: `Parameters::Parameters` (r:1 w:1) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn set_parameter() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) + // Measured: `3` + // Estimated: `3501` + // Minimum execution time: 8_400_000 picoseconds. + Weight::from_parts(8_682_000, 3501) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } // For backwards compatibility and tests. impl WeightInfo for () { + /// Storage: `Parameters::Parameters` (r:1 w:1) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn set_parameter() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 0_000 picoseconds. - Weight::from_parts(0, 0) + // Measured: `3` + // Estimated: `3501` + // Minimum execution time: 8_400_000 picoseconds. + Weight::from_parts(8_682_000, 3501) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/preimage/src/weights.rs b/substrate/frame/preimage/src/weights.rs index c11ab74c1e5..6167cd53029 100644 --- a/substrate/frame/preimage/src/weights.rs +++ b/substrate/frame/preimage/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_preimage` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-09-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-mia4uyug-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_preimage +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_preimage -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/preimage/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -70,200 +72,209 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `42` - // Estimated: `3556` - // Minimum execution time: 15_936_000 picoseconds. - Weight::from_parts(16_271_000, 3556) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_916, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `112` + // Estimated: `6012` + // Minimum execution time: 48_893_000 picoseconds. + Weight::from_parts(44_072_327, 6012) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_684, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 16_468_000 picoseconds. - Weight::from_parts(17_031_000, 3556) + // Minimum execution time: 15_675_000 picoseconds. + Weight::from_parts(4_564_145, 3556) // Standard Error: 2 - .saturating_add(Weight::from_parts(1_948, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_678, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 16_342_000 picoseconds. - Weight::from_parts(16_535_000, 3556) + // Minimum execution time: 14_959_000 picoseconds. + Weight::from_parts(15_335_000, 3556) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_906, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_687, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `172` - // Estimated: `3556` - // Minimum execution time: 31_047_000 picoseconds. - Weight::from_parts(34_099_000, 3556) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `311` + // Estimated: `3658` + // Minimum execution time: 47_378_000 picoseconds. + Weight::from_parts(48_776_000, 3658) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `144` + // Measured: `211` // Estimated: `3556` - // Minimum execution time: 32_559_000 picoseconds. - Weight::from_parts(36_677_000, 3556) + // Minimum execution time: 20_939_000 picoseconds. + Weight::from_parts(21_577_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `172` + // Measured: `255` // Estimated: `3556` - // Minimum execution time: 27_887_000 picoseconds. - Weight::from_parts(30_303_000, 3556) + // Minimum execution time: 17_945_000 picoseconds. + Weight::from_parts(18_448_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `144` + // Measured: `211` // Estimated: `3556` - // Minimum execution time: 17_256_000 picoseconds. - Weight::from_parts(19_481_000, 3556) + // Minimum execution time: 12_132_000 picoseconds. + Weight::from_parts(12_710_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_unnoted_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `42` + // Measured: `109` // Estimated: `3556` - // Minimum execution time: 22_344_000 picoseconds. - Weight::from_parts(23_868_000, 3556) + // Minimum execution time: 13_014_000 picoseconds. + Weight::from_parts(13_726_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_requested_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 10_542_000 picoseconds. - Weight::from_parts(11_571_000, 3556) + // Minimum execution time: 9_785_000 picoseconds. + Weight::from_parts(10_266_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unrequest_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `144` + // Measured: `211` // Estimated: `3556` - // Minimum execution time: 29_054_000 picoseconds. - Weight::from_parts(32_996_000, 3556) + // Minimum execution time: 18_764_000 picoseconds. + Weight::from_parts(19_635_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn unrequest_unnoted_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 10_775_000 picoseconds. - Weight::from_parts(11_937_000, 3556) + // Minimum execution time: 9_624_000 picoseconds. + Weight::from_parts(10_044_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn unrequest_multi_referenced_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 10_696_000 picoseconds. - Weight::from_parts(11_717_000, 3556) + // Minimum execution time: 9_432_000 picoseconds. + Weight::from_parts(9_991_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Preimage::StatusFor` (r:1024 w:1024) + /// Storage: `Preimage::StatusFor` (r:1023 w:1023) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) + /// Storage: `System::Account` (r:1023 w:1023) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:0 w:1024) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) - /// The range of component `n` is `[0, 1024]`. + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1023 w:1023) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:0 w:1023) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1024]`. fn ensure_updated(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `193 + n * (91 ±0)` - // Estimated: `3593 + n * (2566 ±0)` - // Minimum execution time: 2_452_000 picoseconds. - Weight::from_parts(2_641_000, 3593) - // Standard Error: 19_797 - .saturating_add(Weight::from_parts(15_620_946, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2566).saturating_mul(n.into())) + // Measured: `0 + n * (227 ±0)` + // Estimated: `6012 + n * (2668 ±0)` + // Minimum execution time: 54_056_000 picoseconds. + Weight::from_parts(54_912_000, 6012) + // Standard Error: 42_469 + .saturating_add(Weight::from_parts(50_710_258, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2668).saturating_mul(n.into())) } } @@ -272,199 +283,208 @@ impl WeightInfo for () { /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `42` - // Estimated: `3556` - // Minimum execution time: 15_936_000 picoseconds. - Weight::from_parts(16_271_000, 3556) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_916, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `112` + // Estimated: `6012` + // Minimum execution time: 48_893_000 picoseconds. + Weight::from_parts(44_072_327, 6012) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_684, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 16_468_000 picoseconds. - Weight::from_parts(17_031_000, 3556) + // Minimum execution time: 15_675_000 picoseconds. + Weight::from_parts(4_564_145, 3556) // Standard Error: 2 - .saturating_add(Weight::from_parts(1_948, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_678, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 16_342_000 picoseconds. - Weight::from_parts(16_535_000, 3556) + // Minimum execution time: 14_959_000 picoseconds. + Weight::from_parts(15_335_000, 3556) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_906, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_687, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `172` - // Estimated: `3556` - // Minimum execution time: 31_047_000 picoseconds. - Weight::from_parts(34_099_000, 3556) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `311` + // Estimated: `3658` + // Minimum execution time: 47_378_000 picoseconds. + Weight::from_parts(48_776_000, 3658) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `144` + // Measured: `211` // Estimated: `3556` - // Minimum execution time: 32_559_000 picoseconds. - Weight::from_parts(36_677_000, 3556) + // Minimum execution time: 20_939_000 picoseconds. + Weight::from_parts(21_577_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `172` + // Measured: `255` // Estimated: `3556` - // Minimum execution time: 27_887_000 picoseconds. - Weight::from_parts(30_303_000, 3556) + // Minimum execution time: 17_945_000 picoseconds. + Weight::from_parts(18_448_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `144` + // Measured: `211` // Estimated: `3556` - // Minimum execution time: 17_256_000 picoseconds. - Weight::from_parts(19_481_000, 3556) + // Minimum execution time: 12_132_000 picoseconds. + Weight::from_parts(12_710_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_unnoted_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `42` + // Measured: `109` // Estimated: `3556` - // Minimum execution time: 22_344_000 picoseconds. - Weight::from_parts(23_868_000, 3556) + // Minimum execution time: 13_014_000 picoseconds. + Weight::from_parts(13_726_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn request_requested_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 10_542_000 picoseconds. - Weight::from_parts(11_571_000, 3556) + // Minimum execution time: 9_785_000 picoseconds. + Weight::from_parts(10_266_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unrequest_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `144` + // Measured: `211` // Estimated: `3556` - // Minimum execution time: 29_054_000 picoseconds. - Weight::from_parts(32_996_000, 3556) + // Minimum execution time: 18_764_000 picoseconds. + Weight::from_parts(19_635_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn unrequest_unnoted_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 10_775_000 picoseconds. - Weight::from_parts(11_937_000, 3556) + // Minimum execution time: 9_624_000 picoseconds. + Weight::from_parts(10_044_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn unrequest_multi_referenced_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `106` + // Measured: `173` // Estimated: `3556` - // Minimum execution time: 10_696_000 picoseconds. - Weight::from_parts(11_717_000, 3556) + // Minimum execution time: 9_432_000 picoseconds. + Weight::from_parts(9_991_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Preimage::StatusFor` (r:1024 w:1024) + /// Storage: `Preimage::StatusFor` (r:1023 w:1023) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) + /// Storage: `System::Account` (r:1023 w:1023) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:0 w:1024) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) - /// The range of component `n` is `[0, 1024]`. + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1023 w:1023) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:0 w:1023) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1024]`. fn ensure_updated(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `193 + n * (91 ±0)` - // Estimated: `3593 + n * (2566 ±0)` - // Minimum execution time: 2_452_000 picoseconds. - Weight::from_parts(2_641_000, 3593) - // Standard Error: 19_797 - .saturating_add(Weight::from_parts(15_620_946, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2566).saturating_mul(n.into())) + // Measured: `0 + n * (227 ±0)` + // Estimated: `6012 + n * (2668 ±0)` + // Minimum execution time: 54_056_000 picoseconds. + Weight::from_parts(54_912_000, 6012) + // Standard Error: 42_469 + .saturating_add(Weight::from_parts(50_710_258, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) + .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2668).saturating_mul(n.into())) } } diff --git a/substrate/frame/proxy/src/weights.rs b/substrate/frame/proxy/src/weights.rs index f30fe73d27a..3c37c91d500 100644 --- a/substrate/frame/proxy/src/weights.rs +++ b/substrate/frame/proxy/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_proxy +//! Autogenerated weights for `pallet_proxy` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/proxy/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/proxy/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_proxy. +/// Weight functions needed for `pallet_proxy`. pub trait WeightInfo { fn proxy(p: u32, ) -> Weight; fn proxy_announced(a: u32, p: u32, ) -> Weight; @@ -64,336 +63,352 @@ pub trait WeightInfo { fn kill_pure(p: u32, ) -> Weight; } -/// Weights for pallet_proxy using the Substrate node and recommended hardware. +/// Weights for `pallet_proxy` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `161 + p * (37 ±0)` + // Measured: `306 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 15_182_000 picoseconds. - Weight::from_parts(15_919_146, 4706) - // Standard Error: 1_586 - .saturating_add(Weight::from_parts(31_768, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 18_437_000 picoseconds. + Weight::from_parts(19_610_577, 4706) + // Standard Error: 2_531 + .saturating_add(Weight::from_parts(26_001, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) } - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `488 + a * (68 ±0) + p * (37 ±0)` + // Measured: `633 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 40_256_000 picoseconds. - Weight::from_parts(40_373_648, 5698) - // Standard Error: 3_978 - .saturating_add(Weight::from_parts(166_936, 0).saturating_mul(a.into())) - // Standard Error: 4_110 - .saturating_add(Weight::from_parts(54_329, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 40_426_000 picoseconds. + Weight::from_parts(40_200_295, 5698) + // Standard Error: 2_922 + .saturating_add(Weight::from_parts(161_885, 0).saturating_mul(a.into())) + // Standard Error: 3_019 + .saturating_add(Weight::from_parts(69_710, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn remove_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 25_040_000 picoseconds. - Weight::from_parts(25_112_188, 5698) - // Standard Error: 2_143 - .saturating_add(Weight::from_parts(189_027, 0).saturating_mul(a.into())) - // Standard Error: 2_214 - .saturating_add(Weight::from_parts(26_683, 0).saturating_mul(p.into())) + // Minimum execution time: 21_905_000 picoseconds. + Weight::from_parts(22_717_430, 5698) + // Standard Error: 2_004 + .saturating_add(Weight::from_parts(153_390, 0).saturating_mul(a.into())) + // Standard Error: 2_071 + .saturating_add(Weight::from_parts(5_676, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn reject_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 24_884_000 picoseconds. - Weight::from_parts(25_359_291, 5698) - // Standard Error: 2_019 - .saturating_add(Weight::from_parts(181_470, 0).saturating_mul(a.into())) - // Standard Error: 2_086 - .saturating_add(Weight::from_parts(17_725, 0).saturating_mul(p.into())) + // Minimum execution time: 21_974_000 picoseconds. + Weight::from_parts(22_484_324, 5698) + // Standard Error: 1_846 + .saturating_add(Weight::from_parts(153_904, 0).saturating_mul(a.into())) + // Standard Error: 1_907 + .saturating_add(Weight::from_parts(9_616, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `420 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 35_039_000 picoseconds. - Weight::from_parts(36_727_868, 5698) - // Standard Error: 4_463 - .saturating_add(Weight::from_parts(167_060, 0).saturating_mul(a.into())) - // Standard Error: 4_611 - .saturating_add(Weight::from_parts(59_836, 0).saturating_mul(p.into())) + // Minimum execution time: 30_454_000 picoseconds. + Weight::from_parts(32_128_158, 5698) + // Standard Error: 3_778 + .saturating_add(Weight::from_parts(137_366, 0).saturating_mul(a.into())) + // Standard Error: 3_904 + .saturating_add(Weight::from_parts(53_040, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 25_697_000 picoseconds. - Weight::from_parts(26_611_090, 4706) - // Standard Error: 2_306 - .saturating_add(Weight::from_parts(85_165, 0).saturating_mul(p.into())) + // Minimum execution time: 21_391_000 picoseconds. + Weight::from_parts(22_202_614, 4706) + // Standard Error: 1_750 + .saturating_add(Weight::from_parts(49_639, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 25_638_000 picoseconds. - Weight::from_parts(26_904_510, 4706) - // Standard Error: 2_669 - .saturating_add(Weight::from_parts(61_668, 0).saturating_mul(p.into())) + // Minimum execution time: 21_375_000 picoseconds. + Weight::from_parts(22_392_601, 4706) + // Standard Error: 2_415 + .saturating_add(Weight::from_parts(40_345, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 22_737_000 picoseconds. - Weight::from_parts(23_618_441, 4706) - // Standard Error: 1_729 - .saturating_add(Weight::from_parts(44_009, 0).saturating_mul(p.into())) + // Minimum execution time: 19_833_000 picoseconds. + Weight::from_parts(20_839_747, 4706) + // Standard Error: 1_742 + .saturating_add(Weight::from_parts(40_874, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `173` // Estimated: `4706` - // Minimum execution time: 27_364_000 picoseconds. - Weight::from_parts(28_632_271, 4706) - // Standard Error: 1_613 - .saturating_add(Weight::from_parts(2_453, 0).saturating_mul(p.into())) + // Minimum execution time: 22_231_000 picoseconds. + Weight::from_parts(23_370_995, 4706) + // Standard Error: 1_521 + .saturating_add(Weight::from_parts(4_892, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `198 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 23_552_000 picoseconds. - Weight::from_parts(24_874_553, 4706) - // Standard Error: 1_919 - .saturating_add(Weight::from_parts(38_799, 0).saturating_mul(p.into())) + // Minimum execution time: 20_614_000 picoseconds. + Weight::from_parts(21_845_970, 4706) + // Standard Error: 1_636 + .saturating_add(Weight::from_parts(34_480, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `161 + p * (37 ±0)` + // Measured: `306 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 15_182_000 picoseconds. - Weight::from_parts(15_919_146, 4706) - // Standard Error: 1_586 - .saturating_add(Weight::from_parts(31_768, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Minimum execution time: 18_437_000 picoseconds. + Weight::from_parts(19_610_577, 4706) + // Standard Error: 2_531 + .saturating_add(Weight::from_parts(26_001, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) } - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `488 + a * (68 ±0) + p * (37 ±0)` + // Measured: `633 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 40_256_000 picoseconds. - Weight::from_parts(40_373_648, 5698) - // Standard Error: 3_978 - .saturating_add(Weight::from_parts(166_936, 0).saturating_mul(a.into())) - // Standard Error: 4_110 - .saturating_add(Weight::from_parts(54_329, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Minimum execution time: 40_426_000 picoseconds. + Weight::from_parts(40_200_295, 5698) + // Standard Error: 2_922 + .saturating_add(Weight::from_parts(161_885, 0).saturating_mul(a.into())) + // Standard Error: 3_019 + .saturating_add(Weight::from_parts(69_710, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn remove_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 25_040_000 picoseconds. - Weight::from_parts(25_112_188, 5698) - // Standard Error: 2_143 - .saturating_add(Weight::from_parts(189_027, 0).saturating_mul(a.into())) - // Standard Error: 2_214 - .saturating_add(Weight::from_parts(26_683, 0).saturating_mul(p.into())) + // Minimum execution time: 21_905_000 picoseconds. + Weight::from_parts(22_717_430, 5698) + // Standard Error: 2_004 + .saturating_add(Weight::from_parts(153_390, 0).saturating_mul(a.into())) + // Standard Error: 2_071 + .saturating_add(Weight::from_parts(5_676, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn reject_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 24_884_000 picoseconds. - Weight::from_parts(25_359_291, 5698) - // Standard Error: 2_019 - .saturating_add(Weight::from_parts(181_470, 0).saturating_mul(a.into())) - // Standard Error: 2_086 - .saturating_add(Weight::from_parts(17_725, 0).saturating_mul(p.into())) + // Minimum execution time: 21_974_000 picoseconds. + Weight::from_parts(22_484_324, 5698) + // Standard Error: 1_846 + .saturating_add(Weight::from_parts(153_904, 0).saturating_mul(a.into())) + // Standard Error: 1_907 + .saturating_add(Weight::from_parts(9_616, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Proxy Proxies (r:1 w:0) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) - /// Storage: Proxy Announcements (r:1 w:1) - /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:0) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: `Proxy::Announcements` (r:1 w:1) + /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `420 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 35_039_000 picoseconds. - Weight::from_parts(36_727_868, 5698) - // Standard Error: 4_463 - .saturating_add(Weight::from_parts(167_060, 0).saturating_mul(a.into())) - // Standard Error: 4_611 - .saturating_add(Weight::from_parts(59_836, 0).saturating_mul(p.into())) + // Minimum execution time: 30_454_000 picoseconds. + Weight::from_parts(32_128_158, 5698) + // Standard Error: 3_778 + .saturating_add(Weight::from_parts(137_366, 0).saturating_mul(a.into())) + // Standard Error: 3_904 + .saturating_add(Weight::from_parts(53_040, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 25_697_000 picoseconds. - Weight::from_parts(26_611_090, 4706) - // Standard Error: 2_306 - .saturating_add(Weight::from_parts(85_165, 0).saturating_mul(p.into())) + // Minimum execution time: 21_391_000 picoseconds. + Weight::from_parts(22_202_614, 4706) + // Standard Error: 1_750 + .saturating_add(Weight::from_parts(49_639, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 25_638_000 picoseconds. - Weight::from_parts(26_904_510, 4706) - // Standard Error: 2_669 - .saturating_add(Weight::from_parts(61_668, 0).saturating_mul(p.into())) + // Minimum execution time: 21_375_000 picoseconds. + Weight::from_parts(22_392_601, 4706) + // Standard Error: 2_415 + .saturating_add(Weight::from_parts(40_345, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 22_737_000 picoseconds. - Weight::from_parts(23_618_441, 4706) - // Standard Error: 1_729 - .saturating_add(Weight::from_parts(44_009, 0).saturating_mul(p.into())) + // Minimum execution time: 19_833_000 picoseconds. + Weight::from_parts(20_839_747, 4706) + // Standard Error: 1_742 + .saturating_add(Weight::from_parts(40_874, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `173` // Estimated: `4706` - // Minimum execution time: 27_364_000 picoseconds. - Weight::from_parts(28_632_271, 4706) - // Standard Error: 1_613 - .saturating_add(Weight::from_parts(2_453, 0).saturating_mul(p.into())) + // Minimum execution time: 22_231_000 picoseconds. + Weight::from_parts(23_370_995, 4706) + // Standard Error: 1_521 + .saturating_add(Weight::from_parts(4_892, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Proxy Proxies (r:1 w:1) - /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: `Proxy::Proxies` (r:1 w:1) + /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `198 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 23_552_000 picoseconds. - Weight::from_parts(24_874_553, 4706) - // Standard Error: 1_919 - .saturating_add(Weight::from_parts(38_799, 0).saturating_mul(p.into())) + // Minimum execution time: 20_614_000 picoseconds. + Weight::from_parts(21_845_970, 4706) + // Standard Error: 1_636 + .saturating_add(Weight::from_parts(34_480, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/ranked-collective/src/weights.rs b/substrate/frame/ranked-collective/src/weights.rs index 4ff0c3337d5..5721858f7e2 100644 --- a/substrate/frame/ranked-collective/src/weights.rs +++ b/substrate/frame/ranked-collective/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_ranked_collective +//! Autogenerated weights for `pallet_ranked_collective` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/ranked-collective/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/ranked-collective/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_ranked_collective. +/// Weight functions needed for `pallet_ranked_collective`. pub trait WeightInfo { fn add_member() -> Weight; fn remove_member(r: u32, ) -> Weight; @@ -61,283 +60,295 @@ pub trait WeightInfo { fn exchange_member() -> Weight; } -/// Weights for pallet_ranked_collective using the Substrate node and recommended hardware. +/// Weights for `pallet_ranked_collective` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:0 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:0 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn add_member() -> Weight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3507` - // Minimum execution time: 17_245_000 picoseconds. - Weight::from_parts(17_930_000, 3507) + // Minimum execution time: 15_389_000 picoseconds. + Weight::from_parts(15_901_000, 3507) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:11 w:11) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:11 w:11) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:11 w:11) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:11 w:11) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:11 w:22) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:11 w:22) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 10]`. fn remove_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `616 + r * (281 ±0)` // Estimated: `3519 + r * (2529 ±0)` - // Minimum execution time: 29_534_000 picoseconds. - Weight::from_parts(32_847_495, 3519) - // Standard Error: 24_211 - .saturating_add(Weight::from_parts(13_949_639, 0).saturating_mul(r.into())) + // Minimum execution time: 29_541_000 picoseconds. + Weight::from_parts(32_239_358, 3519) + // Standard Error: 23_406 + .saturating_add(Weight::from_parts(16_030_191, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2529).saturating_mul(r.into())) } - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:0 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:0 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 10]`. fn promote_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `314 + r * (17 ±0)` // Estimated: `3507` - // Minimum execution time: 20_333_000 picoseconds. - Weight::from_parts(21_592_224, 3507) - // Standard Error: 6_423 - .saturating_add(Weight::from_parts(321_314, 0).saturating_mul(r.into())) + // Minimum execution time: 17_939_000 picoseconds. + Weight::from_parts(19_290_416, 3507) + // Standard Error: 5_710 + .saturating_add(Weight::from_parts(374_399, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:1 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:1 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:1 w:2) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:1 w:2) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 10]`. fn demote_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `632 + r * (72 ±0)` // Estimated: `3519` - // Minimum execution time: 29_446_000 picoseconds. - Weight::from_parts(32_447_715, 3519) - // Standard Error: 28_791 - .saturating_add(Weight::from_parts(822_890, 0).saturating_mul(r.into())) + // Minimum execution time: 29_609_000 picoseconds. + Weight::from_parts(32_686_167, 3519) + // Standard Error: 27_588 + .saturating_add(Weight::from_parts(789_212, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedPolls ReferendumInfoFor (r:1 w:1) - /// Proof: RankedPolls ReferendumInfoFor (max_values: None, max_size: Some(330), added: 2805, mode: MaxEncodedLen) - /// Storage: RankedCollective Voting (r:1 w:1) - /// Proof: RankedCollective Voting (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedPolls::ReferendumInfoFor` (r:1 w:1) + /// Proof: `RankedPolls::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(330), added: 2805, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Voting` (r:1 w:1) + /// Proof: `RankedCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote() -> Weight { // Proof Size summary in bytes: // Measured: `628` // Estimated: `219984` - // Minimum execution time: 45_474_000 picoseconds. - Weight::from_parts(47_228_000, 219984) + // Minimum execution time: 41_151_000 picoseconds. + Weight::from_parts(42_435_000, 219984) .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: RankedPolls ReferendumInfoFor (r:1 w:0) - /// Proof: RankedPolls ReferendumInfoFor (max_values: None, max_size: Some(330), added: 2805, mode: MaxEncodedLen) - /// Storage: RankedCollective VotingCleanup (r:1 w:0) - /// Proof: RankedCollective VotingCleanup (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: RankedCollective Voting (r:100 w:100) - /// Proof: RankedCollective Voting (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `RankedPolls::ReferendumInfoFor` (r:1 w:0) + /// Proof: `RankedPolls::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(330), added: 2805, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::VotingCleanup` (r:1 w:0) + /// Proof: `RankedCollective::VotingCleanup` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Voting` (r:100 w:100) + /// Proof: `RankedCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. fn cleanup_poll(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `462 + n * (50 ±0)` // Estimated: `3795 + n * (2540 ±0)` - // Minimum execution time: 13_903_000 picoseconds. - Weight::from_parts(18_209_102, 3795) - // Standard Error: 2_556 - .saturating_add(Weight::from_parts(1_237_454, 0).saturating_mul(n.into())) + // Minimum execution time: 13_563_000 picoseconds. + Weight::from_parts(17_495_215, 3795) + // Standard Error: 2_294 + .saturating_add(Weight::from_parts(1_207_393, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2540).saturating_mul(n.into())) } - /// Storage: `RankedCollective::Members` (r:2 w:2) /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:2 w:2) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:2 w:2) + /// Storage: `RankedCollective::IdToIndex` (r:2 w:4) /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:2 w:2) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:0) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:2 w:2) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::IndexToId` (r:0 w:2) /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn exchange_member() -> Weight { // Proof Size summary in bytes: - // Measured: `437` - // Estimated: `6048` - // Minimum execution time: 138_000_000 picoseconds. - Weight::from_parts(141_000_000, 0) - .saturating_add(Weight::from_parts(0, 6048)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(8)) + // Measured: `625` + // Estimated: `19894` + // Minimum execution time: 70_713_000 picoseconds. + Weight::from_parts(72_831_000, 19894) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(14_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:0 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:0 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn add_member() -> Weight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3507` - // Minimum execution time: 17_245_000 picoseconds. - Weight::from_parts(17_930_000, 3507) + // Minimum execution time: 15_389_000 picoseconds. + Weight::from_parts(15_901_000, 3507) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:11 w:11) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:11 w:11) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:11 w:11) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:11 w:11) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:11 w:22) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:11 w:22) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 10]`. fn remove_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `616 + r * (281 ±0)` // Estimated: `3519 + r * (2529 ±0)` - // Minimum execution time: 29_534_000 picoseconds. - Weight::from_parts(32_847_495, 3519) - // Standard Error: 24_211 - .saturating_add(Weight::from_parts(13_949_639, 0).saturating_mul(r.into())) + // Minimum execution time: 29_541_000 picoseconds. + Weight::from_parts(32_239_358, 3519) + // Standard Error: 23_406 + .saturating_add(Weight::from_parts(16_030_191, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(r.into()))) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes((5_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2529).saturating_mul(r.into())) } - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:0 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:0 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:0 w:1) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 10]`. fn promote_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `314 + r * (17 ±0)` // Estimated: `3507` - // Minimum execution time: 20_333_000 picoseconds. - Weight::from_parts(21_592_224, 3507) - // Standard Error: 6_423 - .saturating_add(Weight::from_parts(321_314, 0).saturating_mul(r.into())) + // Minimum execution time: 17_939_000 picoseconds. + Weight::from_parts(19_290_416, 3507) + // Standard Error: 5_710 + .saturating_add(Weight::from_parts(374_399, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: RankedCollective Members (r:1 w:1) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedCollective MemberCount (r:1 w:1) - /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: RankedCollective IdToIndex (r:1 w:1) - /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) - /// Storage: RankedCollective IndexToId (r:1 w:1) - /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:1) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::MemberCount` (r:1 w:1) + /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IdToIndex` (r:1 w:2) + /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::IndexToId` (r:1 w:2) + /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) /// The range of component `r` is `[0, 10]`. fn demote_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `632 + r * (72 ±0)` // Estimated: `3519` - // Minimum execution time: 29_446_000 picoseconds. - Weight::from_parts(32_447_715, 3519) - // Standard Error: 28_791 - .saturating_add(Weight::from_parts(822_890, 0).saturating_mul(r.into())) + // Minimum execution time: 29_609_000 picoseconds. + Weight::from_parts(32_686_167, 3519) + // Standard Error: 27_588 + .saturating_add(Weight::from_parts(789_212, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: RankedPolls ReferendumInfoFor (r:1 w:1) - /// Proof: RankedPolls ReferendumInfoFor (max_values: None, max_size: Some(330), added: 2805, mode: MaxEncodedLen) - /// Storage: RankedCollective Voting (r:1 w:1) - /// Proof: RankedCollective Voting (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `RankedPolls::ReferendumInfoFor` (r:1 w:1) + /// Proof: `RankedPolls::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(330), added: 2805, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Voting` (r:1 w:1) + /// Proof: `RankedCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote() -> Weight { // Proof Size summary in bytes: // Measured: `628` // Estimated: `219984` - // Minimum execution time: 45_474_000 picoseconds. - Weight::from_parts(47_228_000, 219984) + // Minimum execution time: 41_151_000 picoseconds. + Weight::from_parts(42_435_000, 219984) .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: RankedPolls ReferendumInfoFor (r:1 w:0) - /// Proof: RankedPolls ReferendumInfoFor (max_values: None, max_size: Some(330), added: 2805, mode: MaxEncodedLen) - /// Storage: RankedCollective VotingCleanup (r:1 w:0) - /// Proof: RankedCollective VotingCleanup (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) - /// Storage: RankedCollective Voting (r:100 w:100) - /// Proof: RankedCollective Voting (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: `RankedPolls::ReferendumInfoFor` (r:1 w:0) + /// Proof: `RankedPolls::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(330), added: 2805, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::VotingCleanup` (r:1 w:0) + /// Proof: `RankedCollective::VotingCleanup` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Voting` (r:100 w:100) + /// Proof: `RankedCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. fn cleanup_poll(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `462 + n * (50 ±0)` // Estimated: `3795 + n * (2540 ±0)` - // Minimum execution time: 13_903_000 picoseconds. - Weight::from_parts(18_209_102, 3795) - // Standard Error: 2_556 - .saturating_add(Weight::from_parts(1_237_454, 0).saturating_mul(n.into())) + // Minimum execution time: 13_563_000 picoseconds. + Weight::from_parts(17_495_215, 3795) + // Standard Error: 2_294 + .saturating_add(Weight::from_parts(1_207_393, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2540).saturating_mul(n.into())) } - /// Storage: `RankedCollective::Members` (r:2 w:2) /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:2 w:2) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:2 w:2) + /// Storage: `RankedCollective::IdToIndex` (r:2 w:4) /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::Member` (r:2 w:2) + /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:0) + /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:2 w:2) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::IndexToId` (r:0 w:2) /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn exchange_member() -> Weight { // Proof Size summary in bytes: - // Measured: `437` - // Estimated: `6048` - // Minimum execution time: 138_000_000 picoseconds. - Weight::from_parts(141_000_000, 0) - .saturating_add(Weight::from_parts(0, 6048)) - .saturating_add(RocksDbWeight::get().reads(6)) - .saturating_add(RocksDbWeight::get().writes(8)) + // Measured: `625` + // Estimated: `19894` + // Minimum execution time: 70_713_000 picoseconds. + Weight::from_parts(72_831_000, 19894) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(RocksDbWeight::get().writes(14_u64)) } } diff --git a/substrate/frame/recovery/src/weights.rs b/substrate/frame/recovery/src/weights.rs index 84b19ae694e..fe5dbcfc222 100644 --- a/substrate/frame/recovery/src/weights.rs +++ b/substrate/frame/recovery/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_recovery +//! Autogenerated weights for `pallet_recovery` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/recovery/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/recovery/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_recovery. +/// Weight functions needed for `pallet_recovery`. pub trait WeightInfo { fn as_recovered() -> Weight; fn set_recovered() -> Weight; @@ -63,258 +62,266 @@ pub trait WeightInfo { fn cancel_recovered() -> Weight; } -/// Weights for pallet_recovery using the Substrate node and recommended hardware. +/// Weights for `pallet_recovery` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Recovery Proxy (r:1 w:0) - /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: `Recovery::Proxy` (r:1 w:0) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) fn as_recovered() -> Weight { // Proof Size summary in bytes: - // Measured: `281` - // Estimated: `3545` - // Minimum execution time: 9_360_000 picoseconds. - Weight::from_parts(9_773_000, 3545) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Measured: `497` + // Estimated: `3997` + // Minimum execution time: 14_898_000 picoseconds. + Weight::from_parts(15_464_000, 3997) + .saturating_add(T::DbWeight::get().reads(3_u64)) } - /// Storage: Recovery Proxy (r:0 w:1) - /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: `Recovery::Proxy` (r:0 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) fn set_recovered() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_146_000 picoseconds. - Weight::from_parts(9_507_000, 0) + // Minimum execution time: 7_424_000 picoseconds. + Weight::from_parts(7_830_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Recovery Recoverable (r:1 w:1) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: `Recovery::Recoverable` (r:1 w:1) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn create_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `175` + // Measured: `246` // Estimated: `3816` - // Minimum execution time: 26_472_000 picoseconds. - Weight::from_parts(27_917_651, 3816) - // Standard Error: 7_129 - .saturating_add(Weight::from_parts(59_239, 0).saturating_mul(n.into())) + // Minimum execution time: 21_968_000 picoseconds. + Weight::from_parts(23_594_232, 3816) + // Standard Error: 5_848 + .saturating_add(Weight::from_parts(24_843, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Recovery Recoverable (r:1 w:0) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) - /// Storage: Recovery ActiveRecoveries (r:1 w:1) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) fn initiate_recovery() -> Weight { // Proof Size summary in bytes: - // Measured: `272` + // Measured: `343` // Estimated: `3854` - // Minimum execution time: 29_618_000 picoseconds. - Weight::from_parts(30_192_000, 3854) + // Minimum execution time: 25_494_000 picoseconds. + Weight::from_parts(26_290_000, 3854) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Recovery Recoverable (r:1 w:0) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) - /// Storage: Recovery ActiveRecoveries (r:1 w:1) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn vouch_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `360 + n * (64 ±0)` + // Measured: `431 + n * (64 ±0)` // Estimated: `3854` - // Minimum execution time: 19_464_000 picoseconds. - Weight::from_parts(20_642_522, 3854) - // Standard Error: 5_974 - .saturating_add(Weight::from_parts(142_308, 0).saturating_mul(n.into())) + // Minimum execution time: 17_044_000 picoseconds. + Weight::from_parts(18_299_617, 3854) + // Standard Error: 5_580 + .saturating_add(Weight::from_parts(187_568, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Recovery Recoverable (r:1 w:0) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) - /// Storage: Recovery ActiveRecoveries (r:1 w:0) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) - /// Storage: Recovery Proxy (r:1 w:1) - /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `Recovery::Proxy` (r:1 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn claim_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `392 + n * (64 ±0)` + // Measured: `463 + n * (64 ±0)` // Estimated: `3854` - // Minimum execution time: 23_656_000 picoseconds. - Weight::from_parts(24_903_269, 3854) - // Standard Error: 5_771 - .saturating_add(Weight::from_parts(117_343, 0).saturating_mul(n.into())) + // Minimum execution time: 22_186_000 picoseconds. + Weight::from_parts(23_476_807, 3854) + // Standard Error: 6_392 + .saturating_add(Weight::from_parts(89_770, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Recovery ActiveRecoveries (r:1 w:1) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn close_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `513 + n * (32 ±0)` + // Measured: `584 + n * (32 ±0)` // Estimated: `3854` - // Minimum execution time: 34_866_000 picoseconds. - Weight::from_parts(36_368_748, 3854) - // Standard Error: 6_600 - .saturating_add(Weight::from_parts(118_610, 0).saturating_mul(n.into())) + // Minimum execution time: 31_045_000 picoseconds. + Weight::from_parts(32_623_578, 3854) + // Standard Error: 7_203 + .saturating_add(Weight::from_parts(61_466, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Recovery ActiveRecoveries (r:1 w:0) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) - /// Storage: Recovery Recoverable (r:1 w:1) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `Recovery::Recoverable` (r:1 w:1) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn remove_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `270 + n * (32 ±0)` + // Measured: `341 + n * (32 ±0)` // Estimated: `3854` - // Minimum execution time: 31_405_000 picoseconds. - Weight::from_parts(32_552_838, 3854) - // Standard Error: 8_043 - .saturating_add(Weight::from_parts(171_605, 0).saturating_mul(n.into())) + // Minimum execution time: 27_925_000 picoseconds. + Weight::from_parts(29_258_264, 3854) + // Standard Error: 8_192 + .saturating_add(Weight::from_parts(128_124, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Recovery Proxy (r:1 w:1) - /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: `Recovery::Proxy` (r:1 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) fn cancel_recovered() -> Weight { // Proof Size summary in bytes: - // Measured: `281` + // Measured: `352` // Estimated: `3545` - // Minimum execution time: 11_530_000 picoseconds. - Weight::from_parts(11_851_000, 3545) + // Minimum execution time: 11_623_000 picoseconds. + Weight::from_parts(12_043_000, 3545) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Recovery Proxy (r:1 w:0) - /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: `Recovery::Proxy` (r:1 w:0) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) fn as_recovered() -> Weight { // Proof Size summary in bytes: - // Measured: `281` - // Estimated: `3545` - // Minimum execution time: 9_360_000 picoseconds. - Weight::from_parts(9_773_000, 3545) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Measured: `497` + // Estimated: `3997` + // Minimum execution time: 14_898_000 picoseconds. + Weight::from_parts(15_464_000, 3997) + .saturating_add(RocksDbWeight::get().reads(3_u64)) } - /// Storage: Recovery Proxy (r:0 w:1) - /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: `Recovery::Proxy` (r:0 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) fn set_recovered() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_146_000 picoseconds. - Weight::from_parts(9_507_000, 0) + // Minimum execution time: 7_424_000 picoseconds. + Weight::from_parts(7_830_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Recovery Recoverable (r:1 w:1) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: `Recovery::Recoverable` (r:1 w:1) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn create_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `175` + // Measured: `246` // Estimated: `3816` - // Minimum execution time: 26_472_000 picoseconds. - Weight::from_parts(27_917_651, 3816) - // Standard Error: 7_129 - .saturating_add(Weight::from_parts(59_239, 0).saturating_mul(n.into())) + // Minimum execution time: 21_968_000 picoseconds. + Weight::from_parts(23_594_232, 3816) + // Standard Error: 5_848 + .saturating_add(Weight::from_parts(24_843, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Recovery Recoverable (r:1 w:0) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) - /// Storage: Recovery ActiveRecoveries (r:1 w:1) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) fn initiate_recovery() -> Weight { // Proof Size summary in bytes: - // Measured: `272` + // Measured: `343` // Estimated: `3854` - // Minimum execution time: 29_618_000 picoseconds. - Weight::from_parts(30_192_000, 3854) + // Minimum execution time: 25_494_000 picoseconds. + Weight::from_parts(26_290_000, 3854) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Recovery Recoverable (r:1 w:0) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) - /// Storage: Recovery ActiveRecoveries (r:1 w:1) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn vouch_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `360 + n * (64 ±0)` + // Measured: `431 + n * (64 ±0)` // Estimated: `3854` - // Minimum execution time: 19_464_000 picoseconds. - Weight::from_parts(20_642_522, 3854) - // Standard Error: 5_974 - .saturating_add(Weight::from_parts(142_308, 0).saturating_mul(n.into())) + // Minimum execution time: 17_044_000 picoseconds. + Weight::from_parts(18_299_617, 3854) + // Standard Error: 5_580 + .saturating_add(Weight::from_parts(187_568, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Recovery Recoverable (r:1 w:0) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) - /// Storage: Recovery ActiveRecoveries (r:1 w:0) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) - /// Storage: Recovery Proxy (r:1 w:1) - /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: `Recovery::Recoverable` (r:1 w:0) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `Recovery::Proxy` (r:1 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn claim_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `392 + n * (64 ±0)` + // Measured: `463 + n * (64 ±0)` // Estimated: `3854` - // Minimum execution time: 23_656_000 picoseconds. - Weight::from_parts(24_903_269, 3854) - // Standard Error: 5_771 - .saturating_add(Weight::from_parts(117_343, 0).saturating_mul(n.into())) + // Minimum execution time: 22_186_000 picoseconds. + Weight::from_parts(23_476_807, 3854) + // Standard Error: 6_392 + .saturating_add(Weight::from_parts(89_770, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Recovery ActiveRecoveries (r:1 w:1) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn close_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `513 + n * (32 ±0)` + // Measured: `584 + n * (32 ±0)` // Estimated: `3854` - // Minimum execution time: 34_866_000 picoseconds. - Weight::from_parts(36_368_748, 3854) - // Standard Error: 6_600 - .saturating_add(Weight::from_parts(118_610, 0).saturating_mul(n.into())) + // Minimum execution time: 31_045_000 picoseconds. + Weight::from_parts(32_623_578, 3854) + // Standard Error: 7_203 + .saturating_add(Weight::from_parts(61_466, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Recovery ActiveRecoveries (r:1 w:0) - /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) - /// Storage: Recovery Recoverable (r:1 w:1) - /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) + /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: `Recovery::Recoverable` (r:1 w:1) + /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 9]`. fn remove_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `270 + n * (32 ±0)` + // Measured: `341 + n * (32 ±0)` // Estimated: `3854` - // Minimum execution time: 31_405_000 picoseconds. - Weight::from_parts(32_552_838, 3854) - // Standard Error: 8_043 - .saturating_add(Weight::from_parts(171_605, 0).saturating_mul(n.into())) + // Minimum execution time: 27_925_000 picoseconds. + Weight::from_parts(29_258_264, 3854) + // Standard Error: 8_192 + .saturating_add(Weight::from_parts(128_124, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Recovery Proxy (r:1 w:1) - /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) + /// Storage: `Recovery::Proxy` (r:1 w:1) + /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) fn cancel_recovered() -> Weight { // Proof Size summary in bytes: - // Measured: `281` + // Measured: `352` // Estimated: `3545` - // Minimum execution time: 11_530_000 picoseconds. - Weight::from_parts(11_851_000, 3545) + // Minimum execution time: 11_623_000 picoseconds. + Weight::from_parts(12_043_000, 3545) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/referenda/src/weights.rs b/substrate/frame/referenda/src/weights.rs index 4b89379b311..1f1b69873eb 100644 --- a/substrate/frame/referenda/src/weights.rs +++ b/substrate/frame/referenda/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_referenda +//! Autogenerated weights for `pallet_referenda` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/referenda/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/referenda/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_referenda. +/// Weight functions needed for `pallet_referenda`. pub trait WeightInfo { fn submit() -> Weight; fn place_decision_deposit_preparing() -> Weight; @@ -84,842 +83,874 @@ pub trait WeightInfo { fn clear_metadata() -> Weight; } -/// Weights for pallet_referenda using the Substrate node and recommended hardware. +/// Weights for `pallet_referenda` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Referenda ReferendumCount (r:1 w:1) - /// Proof: Referenda ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:0 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumCount` (r:1 w:1) + /// Proof: `Referenda::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:0 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn submit() -> Weight { // Proof Size summary in bytes: - // Measured: `220` + // Measured: `286` // Estimated: `110487` - // Minimum execution time: 40_175_000 picoseconds. - Weight::from_parts(41_107_000, 110487) + // Minimum execution time: 31_536_000 picoseconds. + Weight::from_parts(32_797_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `473` + // Measured: `539` // Estimated: `219984` - // Minimum execution time: 50_922_000 picoseconds. - Weight::from_parts(52_179_000, 219984) + // Minimum execution time: 42_579_000 picoseconds. + Weight::from_parts(43_877_000, 219984) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:0) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:0) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3260` + // Measured: `3326` // Estimated: `110487` - // Minimum execution time: 69_559_000 picoseconds. - Weight::from_parts(72_143_000, 110487) + // Minimum execution time: 61_439_000 picoseconds. + Weight::from_parts(63_681_000, 110487) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:0) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:0) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3280` + // Measured: `3346` // Estimated: `110487` - // Minimum execution time: 68_833_000 picoseconds. - Weight::from_parts(70_987_000, 110487) + // Minimum execution time: 60_136_000 picoseconds. + Weight::from_parts(61_841_000, 110487) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `473` + // Measured: `539` // Estimated: `219984` - // Minimum execution time: 61_794_000 picoseconds. - Weight::from_parts(62_846_000, 219984) + // Minimum execution time: 49_865_000 picoseconds. + Weight::from_parts(51_347_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) - } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `473` + // Measured: `539` // Estimated: `219984` - // Minimum execution time: 58_664_000 picoseconds. - Weight::from_parts(60_195_000, 219984) + // Minimum execution time: 47_887_000 picoseconds. + Weight::from_parts(49_927_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn refund_decision_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `351` + // Measured: `417` // Estimated: `3831` - // Minimum execution time: 30_850_000 picoseconds. - Weight::from_parts(32_130_000, 3831) + // Minimum execution time: 25_721_000 picoseconds. + Weight::from_parts(26_922_000, 3831) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn refund_submission_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `341` + // Measured: `407` // Estimated: `3831` - // Minimum execution time: 30_747_000 picoseconds. - Weight::from_parts(32_196_000, 3831) + // Minimum execution time: 25_840_000 picoseconds. + Weight::from_parts(26_498_000, 3831) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `381` + // Measured: `447` // Estimated: `219984` - // Minimum execution time: 36_139_000 picoseconds. - Weight::from_parts(37_252_000, 219984) + // Minimum execution time: 30_530_000 picoseconds. + Weight::from_parts(31_547_000, 219984) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) - /// Storage: Referenda MetadataOf (r:1 w:0) - /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Referenda::MetadataOf` (r:1 w:0) + /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn kill() -> Weight { // Proof Size summary in bytes: - // Measured: `622` + // Measured: `688` // Estimated: `219984` - // Minimum execution time: 80_862_000 picoseconds. - Weight::from_parts(83_045_000, 219984) + // Minimum execution time: 64_011_000 picoseconds. + Weight::from_parts(65_240_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Referenda TrackQueue (r:1 w:0) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: `Referenda::TrackQueue` (r:1 w:0) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) fn one_fewer_deciding_queue_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `174` + // Measured: `240` // Estimated: `5477` - // Minimum execution time: 10_136_000 picoseconds. - Weight::from_parts(10_638_000, 5477) + // Minimum execution time: 9_568_000 picoseconds. + Weight::from_parts(10_004_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `3150` + // Measured: `3216` // Estimated: `110487` - // Minimum execution time: 52_022_000 picoseconds. - Weight::from_parts(53_910_000, 110487) + // Minimum execution time: 43_325_000 picoseconds. + Weight::from_parts(45_335_000, 110487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `3150` + // Measured: `3216` // Estimated: `110487` - // Minimum execution time: 53_683_000 picoseconds. - Weight::from_parts(55_707_000, 110487) + // Minimum execution time: 44_287_000 picoseconds. + Weight::from_parts(45_164_000, 110487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_insertion() -> Weight { // Proof Size summary in bytes: - // Measured: `3011` + // Measured: `3077` // Estimated: `5477` - // Minimum execution time: 24_043_000 picoseconds. - Weight::from_parts(24_512_000, 5477) + // Minimum execution time: 21_909_000 picoseconds. + Weight::from_parts(22_641_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_slide() -> Weight { // Proof Size summary in bytes: - // Measured: `3011` + // Measured: `3077` // Estimated: `5477` - // Minimum execution time: 23_588_000 picoseconds. - Weight::from_parts(24_422_000, 5477) + // Minimum execution time: 21_626_000 picoseconds. + Weight::from_parts(22_338_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:0) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:0) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3015` + // Measured: `3081` // Estimated: `5477` - // Minimum execution time: 31_443_000 picoseconds. - Weight::from_parts(32_725_000, 5477) + // Minimum execution time: 29_245_000 picoseconds. + Weight::from_parts(30_147_000, 5477) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:0) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:0) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3035` + // Measured: `3101` // Estimated: `5477` - // Minimum execution time: 30_319_000 picoseconds. - Weight::from_parts(31_652_000, 5477) + // Minimum execution time: 28_512_000 picoseconds. + Weight::from_parts(29_781_000, 5477) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_no_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `333` + // Measured: `399` // Estimated: `110487` - // Minimum execution time: 23_062_000 picoseconds. - Weight::from_parts(23_614_000, 110487) + // Minimum execution time: 19_208_000 picoseconds. + Weight::from_parts(19_947_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `381` + // Measured: `447` // Estimated: `110487` - // Minimum execution time: 23_537_000 picoseconds. - Weight::from_parts(24_267_000, 110487) + // Minimum execution time: 19_708_000 picoseconds. + Weight::from_parts(20_783_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn nudge_referendum_timed_out() -> Weight { // Proof Size summary in bytes: - // Measured: `278` + // Measured: `344` // Estimated: `3831` - // Minimum execution time: 16_388_000 picoseconds. - Weight::from_parts(16_676_000, 3831) + // Minimum execution time: 12_947_000 picoseconds. + Weight::from_parts(13_582_000, 3831) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `381` + // Measured: `447` // Estimated: `110487` - // Minimum execution time: 32_801_000 picoseconds. - Weight::from_parts(34_053_000, 110487) + // Minimum execution time: 26_699_000 picoseconds. + Weight::from_parts(28_048_000, 110487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `381` + // Measured: `447` // Estimated: `110487` - // Minimum execution time: 35_704_000 picoseconds. - Weight::from_parts(36_451_000, 110487) + // Minimum execution time: 28_132_000 picoseconds. + Weight::from_parts(29_520_000, 110487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_begin_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `434` + // Measured: `500` // Estimated: `110487` - // Minimum execution time: 29_151_000 picoseconds. - Weight::from_parts(30_055_000, 110487) + // Minimum execution time: 23_212_000 picoseconds. + Weight::from_parts(24_200_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_end_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `483` // Estimated: `110487` - // Minimum execution time: 29_265_000 picoseconds. - Weight::from_parts(30_213_000, 110487) + // Minimum execution time: 22_807_000 picoseconds. + Weight::from_parts(23_858_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_continue_not_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `434` + // Measured: `500` // Estimated: `110487` - // Minimum execution time: 27_760_000 picoseconds. - Weight::from_parts(28_381_000, 110487) + // Minimum execution time: 22_862_000 picoseconds. + Weight::from_parts(23_627_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_continue_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `438` + // Measured: `504` // Estimated: `110487` - // Minimum execution time: 25_464_000 picoseconds. - Weight::from_parts(26_348_000, 110487) + // Minimum execution time: 21_030_000 picoseconds. + Weight::from_parts(21_710_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) - /// Storage: Scheduler Lookup (r:1 w:1) - /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Lookup` (r:1 w:1) + /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn nudge_referendum_approved() -> Weight { // Proof Size summary in bytes: - // Measured: `438` + // Measured: `504` // Estimated: `219984` - // Minimum execution time: 42_629_000 picoseconds. - Weight::from_parts(43_732_000, 219984) + // Minimum execution time: 33_031_000 picoseconds. + Weight::from_parts(34_518_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_rejected() -> Weight { // Proof Size summary in bytes: - // Measured: `434` + // Measured: `500` // Estimated: `110487` - // Minimum execution time: 30_015_000 picoseconds. - Weight::from_parts(30_827_000, 110487) + // Minimum execution time: 23_198_000 picoseconds. + Weight::from_parts(24_238_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:0) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Referenda MetadataOf (r:0 w:1) - /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Referenda::MetadataOf` (r:0 w:1) + /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_some_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `422` + // Measured: `555` // Estimated: `3831` - // Minimum execution time: 19_901_000 picoseconds. - Weight::from_parts(20_681_000, 3831) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 19_502_000 picoseconds. + Weight::from_parts(20_105_000, 3831) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda MetadataOf (r:1 w:1) - /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::MetadataOf` (r:1 w:1) + /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `355` + // Measured: `421` // Estimated: `3831` - // Minimum execution time: 17_323_000 picoseconds. - Weight::from_parts(18_227_000, 3831) + // Minimum execution time: 15_417_000 picoseconds. + Weight::from_parts(15_916_000, 3831) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Referenda ReferendumCount (r:1 w:1) - /// Proof: Referenda ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:0 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumCount` (r:1 w:1) + /// Proof: `Referenda::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:0 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn submit() -> Weight { // Proof Size summary in bytes: - // Measured: `220` + // Measured: `286` // Estimated: `110487` - // Minimum execution time: 40_175_000 picoseconds. - Weight::from_parts(41_107_000, 110487) + // Minimum execution time: 31_536_000 picoseconds. + Weight::from_parts(32_797_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `473` + // Measured: `539` // Estimated: `219984` - // Minimum execution time: 50_922_000 picoseconds. - Weight::from_parts(52_179_000, 219984) + // Minimum execution time: 42_579_000 picoseconds. + Weight::from_parts(43_877_000, 219984) .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:0) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:0) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3260` + // Measured: `3326` // Estimated: `110487` - // Minimum execution time: 69_559_000 picoseconds. - Weight::from_parts(72_143_000, 110487) + // Minimum execution time: 61_439_000 picoseconds. + Weight::from_parts(63_681_000, 110487) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:0) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:0) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3280` + // Measured: `3346` // Estimated: `110487` - // Minimum execution time: 68_833_000 picoseconds. - Weight::from_parts(70_987_000, 110487) + // Minimum execution time: 60_136_000 picoseconds. + Weight::from_parts(61_841_000, 110487) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `473` + // Measured: `539` // Estimated: `219984` - // Minimum execution time: 61_794_000 picoseconds. - Weight::from_parts(62_846_000, 219984) + // Minimum execution time: 49_865_000 picoseconds. + Weight::from_parts(51_347_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `473` + // Measured: `539` // Estimated: `219984` - // Minimum execution time: 58_664_000 picoseconds. - Weight::from_parts(60_195_000, 219984) + // Minimum execution time: 47_887_000 picoseconds. + Weight::from_parts(49_927_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn refund_decision_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `351` + // Measured: `417` // Estimated: `3831` - // Minimum execution time: 30_850_000 picoseconds. - Weight::from_parts(32_130_000, 3831) + // Minimum execution time: 25_721_000 picoseconds. + Weight::from_parts(26_922_000, 3831) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn refund_submission_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `341` + // Measured: `407` // Estimated: `3831` - // Minimum execution time: 30_747_000 picoseconds. - Weight::from_parts(32_196_000, 3831) + // Minimum execution time: 25_840_000 picoseconds. + Weight::from_parts(26_498_000, 3831) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `381` + // Measured: `447` // Estimated: `219984` - // Minimum execution time: 36_139_000 picoseconds. - Weight::from_parts(37_252_000, 219984) + // Minimum execution time: 30_530_000 picoseconds. + Weight::from_parts(31_547_000, 219984) .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) - /// Storage: Referenda MetadataOf (r:1 w:0) - /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Referenda::MetadataOf` (r:1 w:0) + /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn kill() -> Weight { // Proof Size summary in bytes: - // Measured: `622` + // Measured: `688` // Estimated: `219984` - // Minimum execution time: 80_862_000 picoseconds. - Weight::from_parts(83_045_000, 219984) + // Minimum execution time: 64_011_000 picoseconds. + Weight::from_parts(65_240_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Referenda TrackQueue (r:1 w:0) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: `Referenda::TrackQueue` (r:1 w:0) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) fn one_fewer_deciding_queue_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `174` + // Measured: `240` // Estimated: `5477` - // Minimum execution time: 10_136_000 picoseconds. - Weight::from_parts(10_638_000, 5477) + // Minimum execution time: 9_568_000 picoseconds. + Weight::from_parts(10_004_000, 5477) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `3150` + // Measured: `3216` // Estimated: `110487` - // Minimum execution time: 52_022_000 picoseconds. - Weight::from_parts(53_910_000, 110487) + // Minimum execution time: 43_325_000 picoseconds. + Weight::from_parts(45_335_000, 110487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `3150` + // Measured: `3216` // Estimated: `110487` - // Minimum execution time: 53_683_000 picoseconds. - Weight::from_parts(55_707_000, 110487) + // Minimum execution time: 44_287_000 picoseconds. + Weight::from_parts(45_164_000, 110487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_insertion() -> Weight { // Proof Size summary in bytes: - // Measured: `3011` + // Measured: `3077` // Estimated: `5477` - // Minimum execution time: 24_043_000 picoseconds. - Weight::from_parts(24_512_000, 5477) + // Minimum execution time: 21_909_000 picoseconds. + Weight::from_parts(22_641_000, 5477) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_slide() -> Weight { // Proof Size summary in bytes: - // Measured: `3011` + // Measured: `3077` // Estimated: `5477` - // Minimum execution time: 23_588_000 picoseconds. - Weight::from_parts(24_422_000, 5477) + // Minimum execution time: 21_626_000 picoseconds. + Weight::from_parts(22_338_000, 5477) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:0) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:0) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3015` + // Measured: `3081` // Estimated: `5477` - // Minimum execution time: 31_443_000 picoseconds. - Weight::from_parts(32_725_000, 5477) + // Minimum execution time: 29_245_000 picoseconds. + Weight::from_parts(30_147_000, 5477) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:0) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Referenda TrackQueue (r:1 w:1) - /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:0) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Referenda::TrackQueue` (r:1 w:1) + /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3035` + // Measured: `3101` // Estimated: `5477` - // Minimum execution time: 30_319_000 picoseconds. - Weight::from_parts(31_652_000, 5477) + // Minimum execution time: 28_512_000 picoseconds. + Weight::from_parts(29_781_000, 5477) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_no_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `333` + // Measured: `399` // Estimated: `110487` - // Minimum execution time: 23_062_000 picoseconds. - Weight::from_parts(23_614_000, 110487) + // Minimum execution time: 19_208_000 picoseconds. + Weight::from_parts(19_947_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `381` + // Measured: `447` // Estimated: `110487` - // Minimum execution time: 23_537_000 picoseconds. - Weight::from_parts(24_267_000, 110487) + // Minimum execution time: 19_708_000 picoseconds. + Weight::from_parts(20_783_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) fn nudge_referendum_timed_out() -> Weight { // Proof Size summary in bytes: - // Measured: `278` + // Measured: `344` // Estimated: `3831` - // Minimum execution time: 16_388_000 picoseconds. - Weight::from_parts(16_676_000, 3831) + // Minimum execution time: 12_947_000 picoseconds. + Weight::from_parts(13_582_000, 3831) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `381` + // Measured: `447` // Estimated: `110487` - // Minimum execution time: 32_801_000 picoseconds. - Weight::from_parts(34_053_000, 110487) + // Minimum execution time: 26_699_000 picoseconds. + Weight::from_parts(28_048_000, 110487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda DecidingCount (r:1 w:1) - /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::DecidingCount` (r:1 w:1) + /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `381` + // Measured: `447` // Estimated: `110487` - // Minimum execution time: 35_704_000 picoseconds. - Weight::from_parts(36_451_000, 110487) + // Minimum execution time: 28_132_000 picoseconds. + Weight::from_parts(29_520_000, 110487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_begin_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `434` + // Measured: `500` // Estimated: `110487` - // Minimum execution time: 29_151_000 picoseconds. - Weight::from_parts(30_055_000, 110487) + // Minimum execution time: 23_212_000 picoseconds. + Weight::from_parts(24_200_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_end_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `483` // Estimated: `110487` - // Minimum execution time: 29_265_000 picoseconds. - Weight::from_parts(30_213_000, 110487) + // Minimum execution time: 22_807_000 picoseconds. + Weight::from_parts(23_858_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_continue_not_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `434` + // Measured: `500` // Estimated: `110487` - // Minimum execution time: 27_760_000 picoseconds. - Weight::from_parts(28_381_000, 110487) + // Minimum execution time: 22_862_000 picoseconds. + Weight::from_parts(23_627_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_continue_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `438` + // Measured: `504` // Estimated: `110487` - // Minimum execution time: 25_464_000 picoseconds. - Weight::from_parts(26_348_000, 110487) + // Minimum execution time: 21_030_000 picoseconds. + Weight::from_parts(21_710_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:2 w:2) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) - /// Storage: Scheduler Lookup (r:1 w:1) - /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:2 w:2) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Lookup` (r:1 w:1) + /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn nudge_referendum_approved() -> Weight { // Proof Size summary in bytes: - // Measured: `438` + // Measured: `504` // Estimated: `219984` - // Minimum execution time: 42_629_000 picoseconds. - Weight::from_parts(43_732_000, 219984) + // Minimum execution time: 33_031_000 picoseconds. + Weight::from_parts(34_518_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:1) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Scheduler Agenda (r:1 w:1) - /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Agenda` (r:1 w:1) + /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) fn nudge_referendum_rejected() -> Weight { // Proof Size summary in bytes: - // Measured: `434` + // Measured: `500` // Estimated: `110487` - // Minimum execution time: 30_015_000 picoseconds. - Weight::from_parts(30_827_000, 110487) + // Minimum execution time: 23_198_000 picoseconds. + Weight::from_parts(24_238_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:0) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) - /// Storage: Referenda MetadataOf (r:0 w:1) - /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Referenda::MetadataOf` (r:0 w:1) + /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_some_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `422` + // Measured: `555` // Estimated: `3831` - // Minimum execution time: 19_901_000 picoseconds. - Weight::from_parts(20_681_000, 3831) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Minimum execution time: 19_502_000 picoseconds. + Weight::from_parts(20_105_000, 3831) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Referenda ReferendumInfoFor (r:1 w:0) - /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) - /// Storage: Referenda MetadataOf (r:1 w:1) - /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) + /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: `Referenda::MetadataOf` (r:1 w:1) + /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `355` + // Measured: `421` // Estimated: `3831` - // Minimum execution time: 17_323_000 picoseconds. - Weight::from_parts(18_227_000, 3831) + // Minimum execution time: 15_417_000 picoseconds. + Weight::from_parts(15_916_000, 3831) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/remark/src/weights.rs b/substrate/frame/remark/src/weights.rs index 46475db163f..61cca5b7d05 100644 --- a/substrate/frame/remark/src/weights.rs +++ b/substrate/frame/remark/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_remark +//! Autogenerated weights for `pallet_remark` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/remark/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/remark/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,12 +49,12 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_remark. +/// Weight functions needed for `pallet_remark`. pub trait WeightInfo { fn store(l: u32, ) -> Weight; } -/// Weights for pallet_remark using the Substrate node and recommended hardware. +/// Weights for `pallet_remark` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// The range of component `l` is `[1, 1048576]`. @@ -63,23 +62,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_471_000 picoseconds. - Weight::from_parts(8_586_000, 0) + // Minimum execution time: 6_623_000 picoseconds. + Weight::from_parts(6_757_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_359, 0).saturating_mul(l.into())) + .saturating_add(Weight::from_parts(1_368, 0).saturating_mul(l.into())) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { /// The range of component `l` is `[1, 1048576]`. fn store(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_471_000 picoseconds. - Weight::from_parts(8_586_000, 0) + // Minimum execution time: 6_623_000 picoseconds. + Weight::from_parts(6_757_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_359, 0).saturating_mul(l.into())) + .saturating_add(Weight::from_parts(1_368, 0).saturating_mul(l.into())) } } diff --git a/substrate/frame/safe-mode/src/weights.rs b/substrate/frame/safe-mode/src/weights.rs index f72bebcab9a..d326fab0f0f 100644 --- a/substrate/frame/safe-mode/src/weights.rs +++ b/substrate/frame/safe-mode/src/weights.rs @@ -17,27 +17,29 @@ //! Autogenerated weights for `pallet_safe_mode` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-08-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-aahe6cbd-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_safe_mode +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json -// --pallet=pallet_safe_mode -// --chain=dev -// --header=./HEADER-APACHE2 -// --output=./frame/safe-mode/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/safe-mode/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -70,8 +72,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1489` - // Minimum execution time: 2_500_000 picoseconds. - Weight::from_parts(2_594_000, 1489) + // Minimum execution time: 2_216_000 picoseconds. + Weight::from_parts(2_309_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) @@ -80,23 +82,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 8_868_000 picoseconds. - Weight::from_parts(9_415_000, 1489) + // Minimum execution time: 6_124_000 picoseconds. + Weight::from_parts(6_601_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `SafeMode::Deposits` (r:0 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn enter() -> Weight { // Proof Size summary in bytes: // Measured: `142` - // Estimated: `3550` - // Minimum execution time: 50_541_000 picoseconds. - Weight::from_parts(51_558_000, 3550) + // Estimated: `3658` + // Minimum execution time: 44_825_000 picoseconds. + Weight::from_parts(45_845_000, 3658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -106,23 +108,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1489` - // Minimum execution time: 10_489_000 picoseconds. - Weight::from_parts(10_833_000, 1489) + // Minimum execution time: 7_603_000 picoseconds. + Weight::from_parts(7_954_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `SafeMode::Deposits` (r:0 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn extend() -> Weight { // Proof Size summary in bytes: // Measured: `169` - // Estimated: `3550` - // Minimum execution time: 50_818_000 picoseconds. - Weight::from_parts(51_873_000, 3550) + // Estimated: `3658` + // Minimum execution time: 44_716_000 picoseconds. + Weight::from_parts(46_039_000, 3658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -132,8 +134,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 10_843_000 picoseconds. - Weight::from_parts(11_314_000, 1489) + // Minimum execution time: 8_231_000 picoseconds. + Weight::from_parts(8_731_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -143,8 +145,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 10_382_000 picoseconds. - Weight::from_parts(10_814_000, 1489) + // Minimum execution time: 8_015_000 picoseconds. + Weight::from_parts(8_247_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -153,39 +155,39 @@ impl WeightInfo for SubstrateWeight { /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn release_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3550` - // Minimum execution time: 42_828_000 picoseconds. - Weight::from_parts(43_752_000, 3550) + // Estimated: `3658` + // Minimum execution time: 39_149_000 picoseconds. + Weight::from_parts(40_005_000, 3658) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `SafeMode::Deposits` (r:1 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn force_release_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3550` - // Minimum execution time: 40_196_000 picoseconds. - Weight::from_parts(41_298_000, 3550) + // Estimated: `3658` + // Minimum execution time: 37_528_000 picoseconds. + Weight::from_parts(38_473_000, 3658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `SafeMode::Deposits` (r:1 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn force_slash_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3550` - // Minimum execution time: 33_660_000 picoseconds. - Weight::from_parts(34_426_000, 3550) + // Estimated: `3658` + // Minimum execution time: 29_417_000 picoseconds. + Weight::from_parts(30_195_000, 3658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -199,8 +201,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1489` - // Minimum execution time: 2_500_000 picoseconds. - Weight::from_parts(2_594_000, 1489) + // Minimum execution time: 2_216_000 picoseconds. + Weight::from_parts(2_309_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) @@ -209,23 +211,23 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 8_868_000 picoseconds. - Weight::from_parts(9_415_000, 1489) + // Minimum execution time: 6_124_000 picoseconds. + Weight::from_parts(6_601_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `SafeMode::Deposits` (r:0 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn enter() -> Weight { // Proof Size summary in bytes: // Measured: `142` - // Estimated: `3550` - // Minimum execution time: 50_541_000 picoseconds. - Weight::from_parts(51_558_000, 3550) + // Estimated: `3658` + // Minimum execution time: 44_825_000 picoseconds. + Weight::from_parts(45_845_000, 3658) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -235,23 +237,23 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1489` - // Minimum execution time: 10_489_000 picoseconds. - Weight::from_parts(10_833_000, 1489) + // Minimum execution time: 7_603_000 picoseconds. + Weight::from_parts(7_954_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `SafeMode::Deposits` (r:0 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn extend() -> Weight { // Proof Size summary in bytes: // Measured: `169` - // Estimated: `3550` - // Minimum execution time: 50_818_000 picoseconds. - Weight::from_parts(51_873_000, 3550) + // Estimated: `3658` + // Minimum execution time: 44_716_000 picoseconds. + Weight::from_parts(46_039_000, 3658) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -261,8 +263,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 10_843_000 picoseconds. - Weight::from_parts(11_314_000, 1489) + // Minimum execution time: 8_231_000 picoseconds. + Weight::from_parts(8_731_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -272,8 +274,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 10_382_000 picoseconds. - Weight::from_parts(10_814_000, 1489) + // Minimum execution time: 8_015_000 picoseconds. + Weight::from_parts(8_247_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -282,39 +284,39 @@ impl WeightInfo for () { /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn release_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3550` - // Minimum execution time: 42_828_000 picoseconds. - Weight::from_parts(43_752_000, 3550) + // Estimated: `3658` + // Minimum execution time: 39_149_000 picoseconds. + Weight::from_parts(40_005_000, 3658) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `SafeMode::Deposits` (r:1 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn force_release_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3550` - // Minimum execution time: 40_196_000 picoseconds. - Weight::from_parts(41_298_000, 3550) + // Estimated: `3658` + // Minimum execution time: 37_528_000 picoseconds. + Weight::from_parts(38_473_000, 3658) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `SafeMode::Deposits` (r:1 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn force_slash_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3550` - // Minimum execution time: 33_660_000 picoseconds. - Weight::from_parts(34_426_000, 3550) + // Estimated: `3658` + // Minimum execution time: 29_417_000 picoseconds. + Weight::from_parts(30_195_000, 3658) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/salary/src/weights.rs b/substrate/frame/salary/src/weights.rs index 3d3b9e31595..c4f22a027eb 100644 --- a/substrate/frame/salary/src/weights.rs +++ b/substrate/frame/salary/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_salary +//! Autogenerated weights for `pallet_salary` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/salary/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/salary/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_salary. +/// Weight functions needed for `pallet_salary`. pub trait WeightInfo { fn init() -> Weight; fn bump() -> Weight; @@ -61,204 +60,204 @@ pub trait WeightInfo { fn check_payment() -> Weight; } -/// Weights for pallet_salary using the Substrate node and recommended hardware. +/// Weights for `pallet_salary` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) fn init() -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `1541` - // Minimum execution time: 10_778_000 picoseconds. - Weight::from_parts(11_084_000, 1541) + // Minimum execution time: 7_421_000 picoseconds. + Weight::from_parts(7_819_000, 1541) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) fn bump() -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1541` - // Minimum execution time: 12_042_000 picoseconds. - Weight::from_parts(12_645_000, 1541) + // Minimum execution time: 8_651_000 picoseconds. + Weight::from_parts(9_056_000, 1541) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Salary Status (r:1 w:0) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:0) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) fn induct() -> Weight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3543` - // Minimum execution time: 18_374_000 picoseconds. - Weight::from_parts(19_200_000, 3543) + // Minimum execution time: 16_513_000 picoseconds. + Weight::from_parts(17_305_000, 3543) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) fn register() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3543` - // Minimum execution time: 22_696_000 picoseconds. - Weight::from_parts(23_275_000, 3543) + // Minimum execution time: 18_913_000 picoseconds. + Weight::from_parts(19_867_000, 3543) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) fn payout() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3543` - // Minimum execution time: 63_660_000 picoseconds. - Weight::from_parts(65_006_000, 3543) + // Minimum execution time: 53_297_000 picoseconds. + Weight::from_parts(55_144_000, 3543) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn payout_other() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3593` - // Minimum execution time: 64_706_000 picoseconds. - Weight::from_parts(65_763_000, 3593) + // Minimum execution time: 53_638_000 picoseconds. + Weight::from_parts(55_328_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) fn check_payment() -> Weight { // Proof Size summary in bytes: // Measured: `170` // Estimated: `3543` - // Minimum execution time: 11_838_000 picoseconds. - Weight::from_parts(12_323_000, 3543) + // Minimum execution time: 10_557_000 picoseconds. + Weight::from_parts(11_145_000, 3543) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) fn init() -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `1541` - // Minimum execution time: 10_778_000 picoseconds. - Weight::from_parts(11_084_000, 1541) + // Minimum execution time: 7_421_000 picoseconds. + Weight::from_parts(7_819_000, 1541) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) fn bump() -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1541` - // Minimum execution time: 12_042_000 picoseconds. - Weight::from_parts(12_645_000, 1541) + // Minimum execution time: 8_651_000 picoseconds. + Weight::from_parts(9_056_000, 1541) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Salary Status (r:1 w:0) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:0) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) fn induct() -> Weight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3543` - // Minimum execution time: 18_374_000 picoseconds. - Weight::from_parts(19_200_000, 3543) + // Minimum execution time: 16_513_000 picoseconds. + Weight::from_parts(17_305_000, 3543) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) fn register() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3543` - // Minimum execution time: 22_696_000 picoseconds. - Weight::from_parts(23_275_000, 3543) + // Minimum execution time: 18_913_000 picoseconds. + Weight::from_parts(19_867_000, 3543) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) fn payout() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3543` - // Minimum execution time: 63_660_000 picoseconds. - Weight::from_parts(65_006_000, 3543) + // Minimum execution time: 53_297_000 picoseconds. + Weight::from_parts(55_144_000, 3543) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) - /// Storage: RankedCollective Members (r:1 w:0) - /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: `RankedCollective::Members` (r:1 w:0) + /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn payout_other() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3593` - // Minimum execution time: 64_706_000 picoseconds. - Weight::from_parts(65_763_000, 3593) + // Minimum execution time: 53_638_000 picoseconds. + Weight::from_parts(55_328_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Salary Status (r:1 w:1) - /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) - /// Storage: Salary Claimant (r:1 w:1) - /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: `Salary::Status` (r:1 w:1) + /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: `Salary::Claimant` (r:1 w:1) + /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) fn check_payment() -> Weight { // Proof Size summary in bytes: // Measured: `170` // Estimated: `3543` - // Minimum execution time: 11_838_000 picoseconds. - Weight::from_parts(12_323_000, 3543) + // Minimum execution time: 10_557_000 picoseconds. + Weight::from_parts(11_145_000, 3543) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/sassafras/src/mock.rs b/substrate/frame/sassafras/src/mock.rs index 5e5909fcb0d..4c6efaa63a9 100644 --- a/substrate/frame/sassafras/src/mock.rs +++ b/substrate/frame/sassafras/src/mock.rs @@ -34,7 +34,8 @@ use sp_core::{ H256, U256, }; use sp_runtime::{ - testing::{Digest, DigestItem, Header, TestXt}, + generic::UncheckedExtrinsic, + testing::{Digest, DigestItem, Header}, BuildStorage, }; @@ -53,7 +54,7 @@ where RuntimeCall: From, { type OverarchingCall = RuntimeCall; - type Extrinsic = TestXt; + type Extrinsic = UncheckedExtrinsic; } impl pallet_sassafras::Config for Test { diff --git a/substrate/frame/scheduler/src/weights.rs b/substrate/frame/scheduler/src/weights.rs index 9b7e5405a1b..6c98145d266 100644 --- a/substrate/frame/scheduler/src/weights.rs +++ b/substrate/frame/scheduler/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_scheduler` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_scheduler +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_scheduler -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/scheduler/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -77,8 +79,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `31` // Estimated: `1489` - // Minimum execution time: 3_040_000 picoseconds. - Weight::from_parts(3_202_000, 1489) + // Minimum execution time: 3_128_000 picoseconds. + Weight::from_parts(3_372_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -89,10 +91,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 3_462_000 picoseconds. - Weight::from_parts(6_262_125, 110487) - // Standard Error: 536 - .saturating_add(Weight::from_parts(332_570, 0).saturating_mul(s.into())) + // Minimum execution time: 3_560_000 picoseconds. + Weight::from_parts(6_356_795, 110487) + // Standard Error: 493 + .saturating_add(Weight::from_parts(315_098, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -100,8 +102,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_425_000 picoseconds. - Weight::from_parts(3_680_000, 0) + // Minimum execution time: 3_501_000 picoseconds. + Weight::from_parts(3_722_000, 0) } /// Storage: `Preimage::PreimageFor` (r:1 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) @@ -114,10 +116,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `246 + s * (1 ±0)` // Estimated: `3711 + s * (1 ±0)` - // Minimum execution time: 17_564_000 picoseconds. - Weight::from_parts(17_887_000, 3711) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_253, 0).saturating_mul(s.into())) + // Minimum execution time: 17_976_000 picoseconds. + Weight::from_parts(18_137_000, 3711) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_173, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(s.into())) @@ -128,16 +130,16 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_934_000 picoseconds. - Weight::from_parts(5_275_000, 0) + // Minimum execution time: 4_935_000 picoseconds. + Weight::from_parts(5_133_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn service_task_periodic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_348_000 picoseconds. - Weight::from_parts(3_561_000, 0) + // Minimum execution time: 3_467_000 picoseconds. + Weight::from_parts(3_654_000, 0) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -147,16 +149,16 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3997` - // Minimum execution time: 6_395_000 picoseconds. - Weight::from_parts(6_642_000, 3997) + // Minimum execution time: 6_528_000 picoseconds. + Weight::from_parts(6_820_000, 3997) .saturating_add(T::DbWeight::get().reads(2_u64)) } fn execute_dispatch_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_167_000 picoseconds. - Weight::from_parts(2_266_000, 0) + // Minimum execution time: 2_202_000 picoseconds. + Weight::from_parts(2_360_000, 0) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) @@ -165,15 +167,17 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 10_009_000 picoseconds. - Weight::from_parts(13_565_985, 110487) - // Standard Error: 575 - .saturating_add(Weight::from_parts(354_760, 0).saturating_mul(s.into())) + // Minimum execution time: 10_222_000 picoseconds. + Weight::from_parts(13_654_958, 110487) + // Standard Error: 676 + .saturating_add(Weight::from_parts(338_633, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Lookup` (r:0 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. @@ -181,12 +185,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 14_048_000 picoseconds. - Weight::from_parts(15_141_696, 110487) - // Standard Error: 1_082 - .saturating_add(Weight::from_parts(533_390, 0).saturating_mul(s.into())) + // Minimum execution time: 15_517_000 picoseconds. + Weight::from_parts(17_464_075, 110487) + // Standard Error: 952 + .saturating_add(Weight::from_parts(495_806, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Scheduler::Lookup` (r:1 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) @@ -197,10 +201,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `596 + s * (178 ±0)` // Estimated: `110487` - // Minimum execution time: 12_902_000 picoseconds. - Weight::from_parts(18_957_156, 110487) - // Standard Error: 792 - .saturating_add(Weight::from_parts(361_909, 0).saturating_mul(s.into())) + // Minimum execution time: 13_091_000 picoseconds. + Weight::from_parts(19_101_313, 110487) + // Standard Error: 662 + .saturating_add(Weight::from_parts(342_468, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -208,35 +212,35 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. fn cancel_named(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `709 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 15_933_000 picoseconds. - Weight::from_parts(18_091_415, 110487) - // Standard Error: 779 - .saturating_add(Weight::from_parts(534_402, 0).saturating_mul(s.into())) + // Minimum execution time: 17_579_000 picoseconds. + Weight::from_parts(20_561_921, 110487) + // Standard Error: 792 + .saturating_add(Weight::from_parts(500_463, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Scheduler::Retries` (r:1 w:2) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Lookup` (r:0 w:1) - /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. fn schedule_retry(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `159` + // Measured: `118` // Estimated: `110487` - // Minimum execution time: 14_155_000 picoseconds. - Weight::from_parts(16_447_031, 110487) - // Standard Error: 233 - .saturating_add(Weight::from_parts(8_424, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 8_996_000 picoseconds. + Weight::from_parts(11_393_234, 110487) + // Standard Error: 190 + .saturating_add(Weight::from_parts(6_714, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Scheduler::Agenda` (r:1 w:0) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) @@ -244,10 +248,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn set_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `81 + s * (177 ±0)` + // Measured: `90705` // Estimated: `110487` - // Minimum execution time: 8_130_000 picoseconds. - Weight::from_parts(9_047_554, 110487) + // Minimum execution time: 121_505_000 picoseconds. + Weight::from_parts(124_306_000, 110487) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -259,10 +263,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn set_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `647 + s * (178 ±0)` + // Measured: `91747` // Estimated: `110487` - // Minimum execution time: 10_838_000 picoseconds. - Weight::from_parts(12_804_076, 110487) + // Minimum execution time: 128_070_000 picoseconds. + Weight::from_parts(132_683_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -272,10 +276,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `81 + s * (177 ±0)` + // Measured: `90717` // Estimated: `110487` - // Minimum execution time: 8_130_000 picoseconds. - Weight::from_parts(9_047_554, 110487) + // Minimum execution time: 118_260_000 picoseconds. + Weight::from_parts(119_722_000, 110487) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -287,10 +291,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `647 + s * (178 ±0)` + // Measured: `91759` // Estimated: `110487` - // Minimum execution time: 10_838_000 picoseconds. - Weight::from_parts(12_804_076, 110487) + // Minimum execution time: 129_036_000 picoseconds. + Weight::from_parts(133_975_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -304,8 +308,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `31` // Estimated: `1489` - // Minimum execution time: 3_040_000 picoseconds. - Weight::from_parts(3_202_000, 1489) + // Minimum execution time: 3_128_000 picoseconds. + Weight::from_parts(3_372_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -316,10 +320,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 3_462_000 picoseconds. - Weight::from_parts(6_262_125, 110487) - // Standard Error: 536 - .saturating_add(Weight::from_parts(332_570, 0).saturating_mul(s.into())) + // Minimum execution time: 3_560_000 picoseconds. + Weight::from_parts(6_356_795, 110487) + // Standard Error: 493 + .saturating_add(Weight::from_parts(315_098, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -327,8 +331,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_425_000 picoseconds. - Weight::from_parts(3_680_000, 0) + // Minimum execution time: 3_501_000 picoseconds. + Weight::from_parts(3_722_000, 0) } /// Storage: `Preimage::PreimageFor` (r:1 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) @@ -341,10 +345,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `246 + s * (1 ±0)` // Estimated: `3711 + s * (1 ±0)` - // Minimum execution time: 17_564_000 picoseconds. - Weight::from_parts(17_887_000, 3711) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_253, 0).saturating_mul(s.into())) + // Minimum execution time: 17_976_000 picoseconds. + Weight::from_parts(18_137_000, 3711) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_173, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(s.into())) @@ -355,16 +359,16 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_934_000 picoseconds. - Weight::from_parts(5_275_000, 0) + // Minimum execution time: 4_935_000 picoseconds. + Weight::from_parts(5_133_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn service_task_periodic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_348_000 picoseconds. - Weight::from_parts(3_561_000, 0) + // Minimum execution time: 3_467_000 picoseconds. + Weight::from_parts(3_654_000, 0) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -374,16 +378,16 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3997` - // Minimum execution time: 6_395_000 picoseconds. - Weight::from_parts(6_642_000, 3997) + // Minimum execution time: 6_528_000 picoseconds. + Weight::from_parts(6_820_000, 3997) .saturating_add(RocksDbWeight::get().reads(2_u64)) } fn execute_dispatch_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_167_000 picoseconds. - Weight::from_parts(2_266_000, 0) + // Minimum execution time: 2_202_000 picoseconds. + Weight::from_parts(2_360_000, 0) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) @@ -392,15 +396,17 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 10_009_000 picoseconds. - Weight::from_parts(13_565_985, 110487) - // Standard Error: 575 - .saturating_add(Weight::from_parts(354_760, 0).saturating_mul(s.into())) + // Minimum execution time: 10_222_000 picoseconds. + Weight::from_parts(13_654_958, 110487) + // Standard Error: 676 + .saturating_add(Weight::from_parts(338_633, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Lookup` (r:0 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. @@ -408,12 +414,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 14_048_000 picoseconds. - Weight::from_parts(15_141_696, 110487) - // Standard Error: 1_082 - .saturating_add(Weight::from_parts(533_390, 0).saturating_mul(s.into())) + // Minimum execution time: 15_517_000 picoseconds. + Weight::from_parts(17_464_075, 110487) + // Standard Error: 952 + .saturating_add(Weight::from_parts(495_806, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Scheduler::Lookup` (r:1 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) @@ -424,10 +430,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `596 + s * (178 ±0)` // Estimated: `110487` - // Minimum execution time: 12_902_000 picoseconds. - Weight::from_parts(18_957_156, 110487) - // Standard Error: 792 - .saturating_add(Weight::from_parts(361_909, 0).saturating_mul(s.into())) + // Minimum execution time: 13_091_000 picoseconds. + Weight::from_parts(19_101_313, 110487) + // Standard Error: 662 + .saturating_add(Weight::from_parts(342_468, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -435,35 +441,35 @@ impl WeightInfo for () { /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. fn cancel_named(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `709 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 15_933_000 picoseconds. - Weight::from_parts(18_091_415, 110487) - // Standard Error: 779 - .saturating_add(Weight::from_parts(534_402, 0).saturating_mul(s.into())) + // Minimum execution time: 17_579_000 picoseconds. + Weight::from_parts(20_561_921, 110487) + // Standard Error: 792 + .saturating_add(Weight::from_parts(500_463, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Scheduler::Retries` (r:1 w:2) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Lookup` (r:0 w:1) - /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Retries` (r:0 w:1) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. fn schedule_retry(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `159` + // Measured: `118` // Estimated: `110487` - // Minimum execution time: 14_155_000 picoseconds. - Weight::from_parts(16_447_031, 110487) - // Standard Error: 233 - .saturating_add(Weight::from_parts(8_424, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 8_996_000 picoseconds. + Weight::from_parts(11_393_234, 110487) + // Standard Error: 190 + .saturating_add(Weight::from_parts(6_714, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Scheduler::Agenda` (r:1 w:0) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) @@ -471,10 +477,10 @@ impl WeightInfo for () { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn set_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `81 + s * (177 ±0)` + // Measured: `90705` // Estimated: `110487` - // Minimum execution time: 8_130_000 picoseconds. - Weight::from_parts(9_047_554, 110487) + // Minimum execution time: 121_505_000 picoseconds. + Weight::from_parts(124_306_000, 110487) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -486,10 +492,10 @@ impl WeightInfo for () { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn set_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `647 + s * (178 ±0)` + // Measured: `91747` // Estimated: `110487` - // Minimum execution time: 10_838_000 picoseconds. - Weight::from_parts(12_804_076, 110487) + // Minimum execution time: 128_070_000 picoseconds. + Weight::from_parts(132_683_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -499,10 +505,10 @@ impl WeightInfo for () { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `81 + s * (177 ±0)` + // Measured: `90717` // Estimated: `110487` - // Minimum execution time: 8_130_000 picoseconds. - Weight::from_parts(9_047_554, 110487) + // Minimum execution time: 118_260_000 picoseconds. + Weight::from_parts(119_722_000, 110487) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -514,10 +520,10 @@ impl WeightInfo for () { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `647 + s * (178 ±0)` + // Measured: `91759` // Estimated: `110487` - // Minimum execution time: 10_838_000 picoseconds. - Weight::from_parts(12_804_076, 110487) + // Minimum execution time: 129_036_000 picoseconds. + Weight::from_parts(133_975_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/session/src/weights.rs b/substrate/frame/session/src/weights.rs index dd9848fd2c1..09eb665ff3d 100644 --- a/substrate/frame/session/src/weights.rs +++ b/substrate/frame/session/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_session +//! Autogenerated weights for `pallet_session` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/session/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/session/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,77 +49,77 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_session. +/// Weight functions needed for `pallet_session`. pub trait WeightInfo { fn set_keys() -> Weight; fn purge_keys() -> Weight; } -/// Weights for pallet_session using the Substrate node and recommended hardware. +/// Weights for `pallet_session` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Session NextKeys (r:1 w:1) - /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: Session KeyOwner (r:4 w:4) - /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:6 w:6) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_keys() -> Weight { // Proof Size summary in bytes: - // Measured: `1924` - // Estimated: `12814` - // Minimum execution time: 55_459_000 picoseconds. - Weight::from_parts(56_180_000, 12814) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Measured: `1919` + // Estimated: `17759` + // Minimum execution time: 57_921_000 picoseconds. + Weight::from_parts(58_960_000, 17759) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Session NextKeys (r:1 w:1) - /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: Session KeyOwner (r:0 w:4) - /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:0 w:6) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) fn purge_keys() -> Weight { // Proof Size summary in bytes: - // Measured: `1791` - // Estimated: `5256` - // Minimum execution time: 40_194_000 picoseconds. - Weight::from_parts(41_313_000, 5256) + // Measured: `1817` + // Estimated: `5282` + // Minimum execution time: 40_983_000 picoseconds. + Weight::from_parts(42_700_000, 5282) .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Session NextKeys (r:1 w:1) - /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: Session KeyOwner (r:4 w:4) - /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:6 w:6) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_keys() -> Weight { // Proof Size summary in bytes: - // Measured: `1924` - // Estimated: `12814` - // Minimum execution time: 55_459_000 picoseconds. - Weight::from_parts(56_180_000, 12814) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Measured: `1919` + // Estimated: `17759` + // Minimum execution time: 57_921_000 picoseconds. + Weight::from_parts(58_960_000, 17759) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } - /// Storage: Staking Ledger (r:1 w:0) - /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) - /// Storage: Session NextKeys (r:1 w:1) - /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: Session KeyOwner (r:0 w:4) - /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) + /// Storage: `Staking::Ledger` (r:1 w:0) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:0 w:6) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) fn purge_keys() -> Weight { // Proof Size summary in bytes: - // Measured: `1791` - // Estimated: `5256` - // Minimum execution time: 40_194_000 picoseconds. - Weight::from_parts(41_313_000, 5256) + // Measured: `1817` + // Estimated: `5282` + // Minimum execution time: 40_983_000 picoseconds. + Weight::from_parts(42_700_000, 5282) .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } } diff --git a/substrate/frame/society/src/weights.rs b/substrate/frame/society/src/weights.rs index c32c2383ac9..1245f762972 100644 --- a/substrate/frame/society/src/weights.rs +++ b/substrate/frame/society/src/weights.rs @@ -7,7 +7,7 @@ // 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 +// 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, @@ -15,35 +15,41 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_society +//! Autogenerated weights for `pallet_society` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-09-13, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev // --steps=50 // --repeat=20 // --pallet=pallet_society +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --template=./.maintain/frame-weight-template.hbs -// --header=./HEADER-APACHE2 -// --output=./frame/society/src/weights.rs +// --heap-pages=4096 +// --output=./substrate/frame/society/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_society. +/// Weight functions needed for `pallet_society`. pub trait WeightInfo { fn bid() -> Weight; fn unbid() -> Weight; @@ -67,309 +73,739 @@ pub trait WeightInfo { fn cleanup_challenge() -> Weight; } -/// Weights for pallet_society using the Substrate node and recommended hardware. +/// Weights for `pallet_society` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - // Storage: Society Bids (r:1 w:1) - // Storage: Society Candidates (r:1 w:0) - // Storage: Society Members (r:1 w:0) - // Storage: Society SuspendedMembers (r:1 w:0) - // Storage: Society Parameters (r:1 w:0) + /// Storage: `Society::Bids` (r:1 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:1 w:0) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:0) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::SuspendedMembers` (r:1 w:0) + /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:1 w:0) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn bid() -> Weight { - Weight::zero() - } - // Storage: Society Bids (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `444` + // Estimated: `3909` + // Minimum execution time: 29_905_000 picoseconds. + Weight::from_parts(31_031_000, 3909) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Society::Bids` (r:1 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn unbid() -> Weight { - Weight::zero() - } - // Storage: Society Bids (r:1 w:1) - // Storage: Society Candidates (r:1 w:0) - // Storage: Society Members (r:2 w:1) - // Storage: Society SuspendedMembers (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `461` + // Estimated: `1946` + // Minimum execution time: 23_038_000 picoseconds. + Weight::from_parts(23_904_000, 1946) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Society::Bids` (r:1 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:1 w:0) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:2 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::SuspendedMembers` (r:1 w:0) + /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn vouch() -> Weight { - Weight::zero() - } - // Storage: Society Bids (r:1 w:1) - // Storage: Society Members (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `481` + // Estimated: `6421` + // Minimum execution time: 21_197_000 picoseconds. + Weight::from_parts(22_043_000, 6421) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Bids` (r:1 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) fn unvouch() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society Members (r:1 w:0) - // Storage: Society Votes (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `535` + // Estimated: `4000` + // Minimum execution time: 14_402_000 picoseconds. + Weight::from_parts(15_171_000, 4000) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:0) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Votes` (r:1 w:1) + /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) fn vote() -> Weight { - Weight::zero() - } - // Storage: Society Defending (r:1 w:1) - // Storage: Society Members (r:1 w:0) - // Storage: Society ChallengeRoundCount (r:1 w:0) - // Storage: Society DefenderVotes (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `569` + // Estimated: `4034` + // Minimum execution time: 21_930_000 picoseconds. + Weight::from_parts(22_666_000, 4034) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Defending` (r:1 w:1) + /// Proof: `Society::Defending` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:0) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::ChallengeRoundCount` (r:1 w:0) + /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::DefenderVotes` (r:1 w:1) + /// Proof: `Society::DefenderVotes` (`max_values`: None, `max_size`: None, mode: `Measured`) fn defender_vote() -> Weight { - Weight::zero() - } - // Storage: Society Members (r:1 w:0) - // Storage: Society Payouts (r:1 w:1) - // Storage: System Account (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `561` + // Estimated: `4026` + // Minimum execution time: 18_821_000 picoseconds. + Weight::from_parts(19_633_000, 4026) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Members` (r:1 w:0) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Payouts` (r:1 w:1) + /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn payout() -> Weight { - Weight::zero() - } - // Storage: Society Members (r:1 w:1) - // Storage: Society Payouts (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `650` + // Estimated: `4115` + // Minimum execution time: 47_262_000 picoseconds. + Weight::from_parts(48_313_000, 4115) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Members` (r:1 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Payouts` (r:1 w:1) + /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) fn waive_repay() -> Weight { - Weight::zero() - } - // Storage: Society Head (r:1 w:1) - // Storage: Society MemberCount (r:1 w:1) - // Storage: Society MemberByIndex (r:0 w:1) - // Storage: Society Founder (r:0 w:1) - // Storage: Society Rules (r:0 w:1) - // Storage: Society Members (r:0 w:1) - // Storage: Society Parameters (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `547` + // Estimated: `4012` + // Minimum execution time: 18_189_000 picoseconds. + Weight::from_parts(19_038_000, 4012) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Head` (r:1 w:1) + /// Proof: `Society::Head` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:1) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberByIndex` (r:0 w:1) + /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Founder` (r:0 w:1) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Rules` (r:0 w:1) + /// Proof: `Society::Rules` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:0 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:0 w:1) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn found_society() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:1) - // Storage: Society MemberCount (r:1 w:1) - // Storage: Society Head (r:0 w:1) - // Storage: Society Defending (r:0 w:1) - // Storage: Society ChallengeRoundCount (r:0 w:1) - // Storage: Society MemberByIndex (r:0 w:5) - // Storage: Society Skeptic (r:0 w:1) - // Storage: Society Candidates (r:0 w:4) - // Storage: Society Pot (r:0 w:1) - // Storage: Society Rules (r:0 w:1) - // Storage: Society Votes (r:0 w:4) - // Storage: Society Members (r:0 w:5) - // Storage: Society RoundCount (r:0 w:1) - // Storage: Society Bids (r:0 w:1) - // Storage: Society Parameters (r:0 w:1) - // Storage: Society NextHead (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `1665` + // Minimum execution time: 14_815_000 picoseconds. + Weight::from_parts(15_426_000, 1665) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Society::Founder` (r:1 w:1) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:1) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:5 w:5) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberByIndex` (r:5 w:5) + /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Votes` (r:4 w:4) + /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:4 w:4) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Head` (r:0 w:1) + /// Proof: `Society::Head` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Defending` (r:0 w:1) + /// Proof: `Society::Defending` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::ChallengeRoundCount` (r:0 w:1) + /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Skeptic` (r:0 w:1) + /// Proof: `Society::Skeptic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Pot` (r:0 w:1) + /// Proof: `Society::Pot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Rules` (r:0 w:1) + /// Proof: `Society::Rules` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:0 w:1) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Bids` (r:0 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:0 w:1) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::NextHead` (r:0 w:1) + /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn dissolve() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:0) - // Storage: Society SuspendedMembers (r:1 w:1) - // Storage: Society Payouts (r:1 w:0) - // Storage: Society Pot (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `1654` + // Estimated: `15019` + // Minimum execution time: 57_787_000 picoseconds. + Weight::from_parts(59_489_000, 15019) + .saturating_add(T::DbWeight::get().reads(20_u64)) + .saturating_add(T::DbWeight::get().writes(30_u64)) + } + /// Storage: `Society::Founder` (r:1 w:0) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::SuspendedMembers` (r:1 w:1) + /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Payouts` (r:1 w:0) + /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Pot` (r:1 w:1) + /// Proof: `Society::Pot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn judge_suspended_member() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:0) - // Storage: Society MemberCount (r:1 w:0) - // Storage: Society Parameters (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `505` + // Estimated: `3970` + // Minimum execution time: 19_262_000 picoseconds. + Weight::from_parts(19_752_000, 3970) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Founder` (r:1 w:0) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:0) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:0 w:1) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn set_parameters() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) - // Storage: Society Skeptic (r:1 w:0) - // Storage: Society Votes (r:1 w:0) - // Storage: Society Members (r:1 w:1) - // Storage: Society Parameters (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `387` + // Estimated: `1872` + // Minimum execution time: 10_656_000 picoseconds. + Weight::from_parts(11_063_000, 1872) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Skeptic` (r:1 w:0) + /// Proof: `Society::Skeptic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Votes` (r:1 w:0) + /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:1 w:0) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn punish_skeptic() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) - // Storage: Society Parameters (r:1 w:0) - // Storage: Society MemberCount (r:1 w:1) - // Storage: Society NextHead (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Society MemberByIndex (r:0 w:1) - // Storage: Society Members (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `636` + // Estimated: `4101` + // Minimum execution time: 22_837_000 picoseconds. + Weight::from_parts(23_738_000, 4101) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:1 w:0) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:1) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::NextHead` (r:1 w:1) + /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Society::MemberByIndex` (r:0 w:1) + /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:0 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) fn claim_membership() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:0) - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) - // Storage: Society Parameters (r:1 w:0) - // Storage: Society MemberCount (r:1 w:1) - // Storage: Society NextHead (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Society MemberByIndex (r:0 w:1) - // Storage: Society Members (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `632` + // Estimated: `4097` + // Minimum execution time: 35_142_000 picoseconds. + Weight::from_parts(36_811_000, 4097) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Society::Founder` (r:1 w:0) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:1 w:0) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:1) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::NextHead` (r:1 w:1) + /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Society::MemberByIndex` (r:0 w:1) + /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:0 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) fn bestow_membership() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:0) - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `650` + // Estimated: `4115` + // Minimum execution time: 37_133_000 picoseconds. + Weight::from_parts(38_366_000, 4115) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Society::Founder` (r:1 w:0) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn kick_candidate() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `776` + // Estimated: `6196` + // Minimum execution time: 37_033_000 picoseconds. + Weight::from_parts(38_293_000, 6196) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn resign_candidacy() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `746` + // Estimated: `6196` + // Minimum execution time: 35_203_000 picoseconds. + Weight::from_parts(36_252_000, 6196) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_candidate() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:0) - // Storage: Society VoteClearCursor (r:1 w:0) - // Storage: Society Votes (r:0 w:2) + // Proof Size summary in bytes: + // Measured: `758` + // Estimated: `6196` + // Minimum execution time: 35_518_000 picoseconds. + Weight::from_parts(36_508_000, 6196) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:0) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::VoteClearCursor` (r:1 w:0) + /// Proof: `Society::VoteClearCursor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Votes` (r:2 w:2) + /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) fn cleanup_candidacy() -> Weight { - Weight::zero() - } - // Storage: Society ChallengeRoundCount (r:1 w:0) - // Storage: Society DefenderVotes (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `552` + // Estimated: `6492` + // Minimum execution time: 17_001_000 picoseconds. + Weight::from_parts(17_845_000, 6492) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Society::ChallengeRoundCount` (r:1 w:0) + /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::DefenderVotes` (r:1 w:1) + /// Proof: `Society::DefenderVotes` (`max_values`: None, `max_size`: None, mode: `Measured`) fn cleanup_challenge() -> Weight { - Weight::zero() + // Proof Size summary in bytes: + // Measured: `510` + // Estimated: `3975` + // Minimum execution time: 11_583_000 picoseconds. + Weight::from_parts(12_134_000, 3975) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - // Storage: Society Bids (r:1 w:1) - // Storage: Society Candidates (r:1 w:0) - // Storage: Society Members (r:1 w:0) - // Storage: Society SuspendedMembers (r:1 w:0) - // Storage: Society Parameters (r:1 w:0) + /// Storage: `Society::Bids` (r:1 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:1 w:0) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:0) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::SuspendedMembers` (r:1 w:0) + /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:1 w:0) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn bid() -> Weight { - Weight::zero() - } - // Storage: Society Bids (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `444` + // Estimated: `3909` + // Minimum execution time: 29_905_000 picoseconds. + Weight::from_parts(31_031_000, 3909) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Society::Bids` (r:1 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn unbid() -> Weight { - Weight::zero() - } - // Storage: Society Bids (r:1 w:1) - // Storage: Society Candidates (r:1 w:0) - // Storage: Society Members (r:2 w:1) - // Storage: Society SuspendedMembers (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `461` + // Estimated: `1946` + // Minimum execution time: 23_038_000 picoseconds. + Weight::from_parts(23_904_000, 1946) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Society::Bids` (r:1 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:1 w:0) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:2 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::SuspendedMembers` (r:1 w:0) + /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn vouch() -> Weight { - Weight::zero() - } - // Storage: Society Bids (r:1 w:1) - // Storage: Society Members (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `481` + // Estimated: `6421` + // Minimum execution time: 21_197_000 picoseconds. + Weight::from_parts(22_043_000, 6421) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Bids` (r:1 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) fn unvouch() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society Members (r:1 w:0) - // Storage: Society Votes (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `535` + // Estimated: `4000` + // Minimum execution time: 14_402_000 picoseconds. + Weight::from_parts(15_171_000, 4000) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:0) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Votes` (r:1 w:1) + /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) fn vote() -> Weight { - Weight::zero() - } - // Storage: Society Defending (r:1 w:1) - // Storage: Society Members (r:1 w:0) - // Storage: Society ChallengeRoundCount (r:1 w:0) - // Storage: Society DefenderVotes (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `569` + // Estimated: `4034` + // Minimum execution time: 21_930_000 picoseconds. + Weight::from_parts(22_666_000, 4034) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Defending` (r:1 w:1) + /// Proof: `Society::Defending` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:0) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::ChallengeRoundCount` (r:1 w:0) + /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::DefenderVotes` (r:1 w:1) + /// Proof: `Society::DefenderVotes` (`max_values`: None, `max_size`: None, mode: `Measured`) fn defender_vote() -> Weight { - Weight::zero() - } - // Storage: Society Members (r:1 w:0) - // Storage: Society Payouts (r:1 w:1) - // Storage: System Account (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `561` + // Estimated: `4026` + // Minimum execution time: 18_821_000 picoseconds. + Weight::from_parts(19_633_000, 4026) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Members` (r:1 w:0) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Payouts` (r:1 w:1) + /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn payout() -> Weight { - Weight::zero() - } - // Storage: Society Members (r:1 w:1) - // Storage: Society Payouts (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `650` + // Estimated: `4115` + // Minimum execution time: 47_262_000 picoseconds. + Weight::from_parts(48_313_000, 4115) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Members` (r:1 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Payouts` (r:1 w:1) + /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) fn waive_repay() -> Weight { - Weight::zero() - } - // Storage: Society Head (r:1 w:1) - // Storage: Society MemberCount (r:1 w:1) - // Storage: Society MemberByIndex (r:0 w:1) - // Storage: Society Founder (r:0 w:1) - // Storage: Society Rules (r:0 w:1) - // Storage: Society Members (r:0 w:1) - // Storage: Society Parameters (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `547` + // Estimated: `4012` + // Minimum execution time: 18_189_000 picoseconds. + Weight::from_parts(19_038_000, 4012) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Head` (r:1 w:1) + /// Proof: `Society::Head` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:1) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberByIndex` (r:0 w:1) + /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Founder` (r:0 w:1) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Rules` (r:0 w:1) + /// Proof: `Society::Rules` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:0 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:0 w:1) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn found_society() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:1) - // Storage: Society MemberCount (r:1 w:1) - // Storage: Society Head (r:0 w:1) - // Storage: Society Defending (r:0 w:1) - // Storage: Society ChallengeRoundCount (r:0 w:1) - // Storage: Society MemberByIndex (r:0 w:5) - // Storage: Society Skeptic (r:0 w:1) - // Storage: Society Candidates (r:0 w:4) - // Storage: Society Pot (r:0 w:1) - // Storage: Society Rules (r:0 w:1) - // Storage: Society Votes (r:0 w:4) - // Storage: Society Members (r:0 w:5) - // Storage: Society RoundCount (r:0 w:1) - // Storage: Society Bids (r:0 w:1) - // Storage: Society Parameters (r:0 w:1) - // Storage: Society NextHead (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `1665` + // Minimum execution time: 14_815_000 picoseconds. + Weight::from_parts(15_426_000, 1665) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + } + /// Storage: `Society::Founder` (r:1 w:1) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:1) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:5 w:5) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberByIndex` (r:5 w:5) + /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Votes` (r:4 w:4) + /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:4 w:4) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Head` (r:0 w:1) + /// Proof: `Society::Head` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Defending` (r:0 w:1) + /// Proof: `Society::Defending` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::ChallengeRoundCount` (r:0 w:1) + /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Skeptic` (r:0 w:1) + /// Proof: `Society::Skeptic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Pot` (r:0 w:1) + /// Proof: `Society::Pot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Rules` (r:0 w:1) + /// Proof: `Society::Rules` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:0 w:1) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Bids` (r:0 w:1) + /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:0 w:1) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::NextHead` (r:0 w:1) + /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn dissolve() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:0) - // Storage: Society SuspendedMembers (r:1 w:1) - // Storage: Society Payouts (r:1 w:0) - // Storage: Society Pot (r:1 w:1) + // Proof Size summary in bytes: + // Measured: `1654` + // Estimated: `15019` + // Minimum execution time: 57_787_000 picoseconds. + Weight::from_parts(59_489_000, 15019) + .saturating_add(RocksDbWeight::get().reads(20_u64)) + .saturating_add(RocksDbWeight::get().writes(30_u64)) + } + /// Storage: `Society::Founder` (r:1 w:0) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::SuspendedMembers` (r:1 w:1) + /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Payouts` (r:1 w:0) + /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Pot` (r:1 w:1) + /// Proof: `Society::Pot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn judge_suspended_member() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:0) - // Storage: Society MemberCount (r:1 w:0) - // Storage: Society Parameters (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `505` + // Estimated: `3970` + // Minimum execution time: 19_262_000 picoseconds. + Weight::from_parts(19_752_000, 3970) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Founder` (r:1 w:0) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:0) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:0 w:1) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn set_parameters() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) - // Storage: Society Skeptic (r:1 w:0) - // Storage: Society Votes (r:1 w:0) - // Storage: Society Members (r:1 w:1) - // Storage: Society Parameters (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `387` + // Estimated: `1872` + // Minimum execution time: 10_656_000 picoseconds. + Weight::from_parts(11_063_000, 1872) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Skeptic` (r:1 w:0) + /// Proof: `Society::Skeptic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Votes` (r:1 w:0) + /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:1 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:1 w:0) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn punish_skeptic() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) - // Storage: Society Parameters (r:1 w:0) - // Storage: Society MemberCount (r:1 w:1) - // Storage: Society NextHead (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Society MemberByIndex (r:0 w:1) - // Storage: Society Members (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `636` + // Estimated: `4101` + // Minimum execution time: 22_837_000 picoseconds. + Weight::from_parts(23_738_000, 4101) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:1 w:0) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:1) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::NextHead` (r:1 w:1) + /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Society::MemberByIndex` (r:0 w:1) + /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:0 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) fn claim_membership() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:0) - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) - // Storage: Society Parameters (r:1 w:0) - // Storage: Society MemberCount (r:1 w:1) - // Storage: Society NextHead (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Society MemberByIndex (r:0 w:1) - // Storage: Society Members (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `632` + // Estimated: `4097` + // Minimum execution time: 35_142_000 picoseconds. + Weight::from_parts(36_811_000, 4097) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + } + /// Storage: `Society::Founder` (r:1 w:0) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Parameters` (r:1 w:0) + /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::MemberCount` (r:1 w:1) + /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::NextHead` (r:1 w:1) + /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Society::MemberByIndex` (r:0 w:1) + /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Members` (r:0 w:1) + /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) fn bestow_membership() -> Weight { - Weight::zero() - } - // Storage: Society Founder (r:1 w:0) - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `650` + // Estimated: `4115` + // Minimum execution time: 37_133_000 picoseconds. + Weight::from_parts(38_366_000, 4115) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) + } + /// Storage: `Society::Founder` (r:1 w:0) + /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn kick_candidate() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `776` + // Estimated: `6196` + // Minimum execution time: 37_033_000 picoseconds. + Weight::from_parts(38_293_000, 6196) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn resign_candidacy() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:1) - // Storage: Society RoundCount (r:1 w:0) + // Proof Size summary in bytes: + // Measured: `746` + // Estimated: `6196` + // Minimum execution time: 35_203_000 picoseconds. + Weight::from_parts(36_252_000, 6196) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:1) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::RoundCount` (r:1 w:0) + /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_candidate() -> Weight { - Weight::zero() - } - // Storage: Society Candidates (r:1 w:0) - // Storage: Society VoteClearCursor (r:1 w:0) - // Storage: Society Votes (r:0 w:2) + // Proof Size summary in bytes: + // Measured: `758` + // Estimated: `6196` + // Minimum execution time: 35_518_000 picoseconds. + Weight::from_parts(36_508_000, 6196) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `Society::Candidates` (r:1 w:0) + /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::VoteClearCursor` (r:1 w:0) + /// Proof: `Society::VoteClearCursor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Society::Votes` (r:2 w:2) + /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) fn cleanup_candidacy() -> Weight { - Weight::zero() - } - // Storage: Society ChallengeRoundCount (r:1 w:0) - // Storage: Society DefenderVotes (r:0 w:1) + // Proof Size summary in bytes: + // Measured: `552` + // Estimated: `6492` + // Minimum execution time: 17_001_000 picoseconds. + Weight::from_parts(17_845_000, 6492) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Society::ChallengeRoundCount` (r:1 w:0) + /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Society::DefenderVotes` (r:1 w:1) + /// Proof: `Society::DefenderVotes` (`max_values`: None, `max_size`: None, mode: `Measured`) fn cleanup_challenge() -> Weight { - Weight::zero() + // Proof Size summary in bytes: + // Measured: `510` + // Estimated: `3975` + // Minimum execution time: 11_583_000 picoseconds. + Weight::from_parts(12_134_000, 3975) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs index 52db7c34bfd..549e177491d 100644 --- a/substrate/frame/src/lib.rs +++ b/substrate/frame/src/lib.rs @@ -249,8 +249,8 @@ pub mod runtime { /// The block type, which should be fed into [`frame_system::Config`]. /// - /// Should be parameterized with `T: frame_system::Config` and a tuple of `SignedExtension`. - /// When in doubt, use [`SystemSignedExtensionsOf`]. + /// Should be parameterized with `T: frame_system::Config` and a tuple of + /// `TransactionExtension`. When in doubt, use [`SystemTransactionExtensionsOf`]. // Note that this cannot be dependent on `T` for block-number because it would lead to a // circular dependency (self-referential generics). pub type BlockOf = generic::Block>; @@ -264,7 +264,7 @@ pub mod runtime { /// Default set of signed extensions exposed from the `frame_system`. /// /// crucially, this does NOT contain any tx-payment extension. - pub type SystemSignedExtensionsOf = ( + pub type SystemTransactionExtensionsOf = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/substrate/frame/staking/src/weights.rs b/substrate/frame/staking/src/weights.rs index 6f729e08ba5..8288591a787 100644 --- a/substrate/frame/staking/src/weights.rs +++ b/substrate/frame/staking/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_staking` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-q7z7ruxr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_staking +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_staking -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/staking/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -99,8 +101,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `927` // Estimated: `4764` - // Minimum execution time: 42_042_000 picoseconds. - Weight::from_parts(43_292_000, 4764) + // Minimum execution time: 41_318_000 picoseconds. + Weight::from_parts(43_268_000, 4764) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -120,8 +122,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1990` // Estimated: `8877` - // Minimum execution time: 85_050_000 picoseconds. - Weight::from_parts(87_567_000, 8877) + // Minimum execution time: 85_666_000 picoseconds. + Weight::from_parts(88_749_000, 8877) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -147,8 +149,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2195` // Estimated: `8877` - // Minimum execution time: 89_076_000 picoseconds. - Weight::from_parts(92_715_000, 8877) + // Minimum execution time: 90_282_000 picoseconds. + Weight::from_parts(92_332_000, 8877) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -162,16 +164,18 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1115` + // Measured: `1297` // Estimated: `4764` - // Minimum execution time: 42_067_000 picoseconds. - Weight::from_parts(43_239_807, 4764) - // Standard Error: 831 - .saturating_add(Weight::from_parts(46_257, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Minimum execution time: 44_626_000 picoseconds. + Weight::from_parts(47_254_657, 4764) + // Standard Error: 1_179 + .saturating_add(Weight::from_parts(57_657, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Staking::Ledger` (r:1 w:1) @@ -207,10 +211,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 86_490_000 picoseconds. - Weight::from_parts(95_358_751, 6248) - // Standard Error: 3_952 - .saturating_add(Weight::from_parts(1_294_907, 0).saturating_mul(s.into())) + // Minimum execution time: 86_769_000 picoseconds. + Weight::from_parts(95_212_867, 6248) + // Standard Error: 3_706 + .saturating_add(Weight::from_parts(1_320_752, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(11_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -242,8 +246,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1372` // Estimated: `4556` - // Minimum execution time: 50_326_000 picoseconds. - Weight::from_parts(52_253_000, 4556) + // Minimum execution time: 50_410_000 picoseconds. + Weight::from_parts(52_576_000, 4556) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -256,10 +260,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1280 + k * (569 ±0)` // Estimated: `4556 + k * (3033 ±0)` - // Minimum execution time: 29_305_000 picoseconds. - Weight::from_parts(32_199_604, 4556) - // Standard Error: 7_150 - .saturating_add(Weight::from_parts(6_437_124, 0).saturating_mul(k.into())) + // Minimum execution time: 29_017_000 picoseconds. + Weight::from_parts(33_019_206, 4556) + // Standard Error: 6_368 + .saturating_add(Weight::from_parts(6_158_681, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -292,10 +296,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1866 + n * (102 ±0)` // Estimated: `6248 + n * (2520 ±0)` - // Minimum execution time: 63_267_000 picoseconds. - Weight::from_parts(61_741_404, 6248) - // Standard Error: 12_955 - .saturating_add(Weight::from_parts(3_811_743, 0).saturating_mul(n.into())) + // Minimum execution time: 63_452_000 picoseconds. + Weight::from_parts(60_924_066, 6248) + // Standard Error: 14_416 + .saturating_add(Weight::from_parts(3_921_589, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) @@ -319,8 +323,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1650` // Estimated: `6248` - // Minimum execution time: 52_862_000 picoseconds. - Weight::from_parts(54_108_000, 6248) + // Minimum execution time: 54_253_000 picoseconds. + Weight::from_parts(55_286_000, 6248) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -334,8 +338,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `902` // Estimated: `4556` - // Minimum execution time: 16_350_000 picoseconds. - Weight::from_parts(16_802_000, 4556) + // Minimum execution time: 16_812_000 picoseconds. + Weight::from_parts(17_380_000, 4556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -349,8 +353,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `969` // Estimated: `4556` - // Minimum execution time: 19_981_000 picoseconds. - Weight::from_parts(20_539_000, 4556) + // Minimum execution time: 20_590_000 picoseconds. + Weight::from_parts(21_096_000, 4556) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -362,8 +366,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `902` // Estimated: `4556` - // Minimum execution time: 19_304_000 picoseconds. - Weight::from_parts(20_000_000, 4556) + // Minimum execution time: 19_923_000 picoseconds. + Weight::from_parts(20_880_000, 4556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -373,8 +377,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_568_000 picoseconds. - Weight::from_parts(2_708_000, 0) + // Minimum execution time: 2_599_000 picoseconds. + Weight::from_parts(2_751_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -383,8 +387,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_950_000 picoseconds. - Weight::from_parts(8_348_000, 0) + // Minimum execution time: 6_941_000 picoseconds. + Weight::from_parts(7_288_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -393,8 +397,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_967_000 picoseconds. - Weight::from_parts(8_222_000, 0) + // Minimum execution time: 6_757_000 picoseconds. + Weight::from_parts(7_200_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -403,8 +407,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_006_000 picoseconds. - Weight::from_parts(8_440_000, 0) + // Minimum execution time: 7_028_000 picoseconds. + Weight::from_parts(7_366_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::Invulnerables` (r:0 w:1) @@ -414,10 +418,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_524_000 picoseconds. - Weight::from_parts(3_123_608, 0) - // Standard Error: 59 - .saturating_add(Weight::from_parts(11_596, 0).saturating_mul(v.into())) + // Minimum execution time: 2_741_000 picoseconds. + Weight::from_parts(3_212_598, 0) + // Standard Error: 68 + .saturating_add(Weight::from_parts(11_695, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::Ledger` (r:5900 w:11800) @@ -431,10 +435,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1356 + i * (151 ±0)` // Estimated: `990 + i * (3566 ±0)` - // Minimum execution time: 2_092_000 picoseconds. - Weight::from_parts(2_258_000, 990) - // Standard Error: 32_695 - .saturating_add(Weight::from_parts(16_669_219, 0).saturating_mul(i.into())) + // Minimum execution time: 2_132_000 picoseconds. + Weight::from_parts(2_289_000, 990) + // Standard Error: 34_227 + .saturating_add(Weight::from_parts(17_006_583, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3566).saturating_mul(i.into())) @@ -472,10 +476,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 84_275_000 picoseconds. - Weight::from_parts(92_512_416, 6248) - // Standard Error: 3_633 - .saturating_add(Weight::from_parts(1_315_923, 0).saturating_mul(s.into())) + // Minimum execution time: 85_308_000 picoseconds. + Weight::from_parts(93_689_468, 6248) + // Standard Error: 5_425 + .saturating_add(Weight::from_parts(1_307_604, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(12_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -488,10 +492,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `66672` // Estimated: `70137` - // Minimum execution time: 101_707_000 picoseconds. - Weight::from_parts(912_819_462, 70137) - // Standard Error: 57_547 - .saturating_add(Weight::from_parts(4_856_799, 0).saturating_mul(s.into())) + // Minimum execution time: 103_242_000 picoseconds. + Weight::from_parts(1_162_296_080, 70137) + // Standard Error: 76_741 + .saturating_add(Weight::from_parts(6_487_522, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -528,10 +532,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `33297 + n * (377 ±0)` // Estimated: `30944 + n * (3774 ±0)` - // Minimum execution time: 138_657_000 picoseconds. - Weight::from_parts(167_173_445, 30944) - // Standard Error: 25_130 - .saturating_add(Weight::from_parts(44_566_012, 0).saturating_mul(n.into())) + // Minimum execution time: 140_740_000 picoseconds. + Weight::from_parts(182_886_963, 30944) + // Standard Error: 39_852 + .saturating_add(Weight::from_parts(43_140_752, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -555,10 +559,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1991 + l * (7 ±0)` // Estimated: `8877` - // Minimum execution time: 80_061_000 picoseconds. - Weight::from_parts(82_836_434, 8877) - // Standard Error: 4_348 - .saturating_add(Weight::from_parts(75_744, 0).saturating_mul(l.into())) + // Minimum execution time: 80_372_000 picoseconds. + Weight::from_parts(83_335_027, 8877) + // Standard Error: 4_780 + .saturating_add(Weight::from_parts(72_180, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -593,10 +597,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 92_560_000 picoseconds. - Weight::from_parts(97_684_741, 6248) - // Standard Error: 3_361 - .saturating_add(Weight::from_parts(1_292_732, 0).saturating_mul(s.into())) + // Minimum execution time: 93_920_000 picoseconds. + Weight::from_parts(98_022_911, 6248) + // Standard Error: 4_096 + .saturating_add(Weight::from_parts(1_287_745, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(11_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -642,12 +646,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + n * (720 ±0) + v * (3598 ±0)` // Estimated: `512390 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 564_963_000 picoseconds. - Weight::from_parts(569_206_000, 512390) - // Standard Error: 2_033_235 - .saturating_add(Weight::from_parts(68_025_841, 0).saturating_mul(v.into())) - // Standard Error: 202_600 - .saturating_add(Weight::from_parts(17_916_770, 0).saturating_mul(n.into())) + // Minimum execution time: 556_012_000 picoseconds. + Weight::from_parts(560_339_000, 512390) + // Standard Error: 2_115_076 + .saturating_add(Weight::from_parts(69_456_497, 0).saturating_mul(v.into())) + // Standard Error: 210_755 + .saturating_add(Weight::from_parts(17_974_873, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(206_u64)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -678,12 +682,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3175 + n * (911 ±0) + v * (395 ±0)` // Estimated: `512390 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 32_196_540_000 picoseconds. - Weight::from_parts(32_341_871_000, 512390) - // Standard Error: 354_657 - .saturating_add(Weight::from_parts(5_143_440, 0).saturating_mul(v.into())) - // Standard Error: 354_657 - .saturating_add(Weight::from_parts(3_328_189, 0).saturating_mul(n.into())) + // Minimum execution time: 32_792_819_000 picoseconds. + Weight::from_parts(32_986_606_000, 512390) + // Standard Error: 360_905 + .saturating_add(Weight::from_parts(5_260_151, 0).saturating_mul(v.into())) + // Standard Error: 360_905 + .saturating_add(Weight::from_parts(3_599_219, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(201_u64)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -700,10 +704,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `979 + v * (50 ±0)` // Estimated: `3510 + v * (2520 ±0)` - // Minimum execution time: 2_381_903_000 picoseconds. - Weight::from_parts(32_693_059, 3510) - // Standard Error: 10_000 - .saturating_add(Weight::from_parts(4_736_173, 0).saturating_mul(v.into())) + // Minimum execution time: 2_434_755_000 picoseconds. + Weight::from_parts(38_574_764, 3510) + // Standard Error: 14_467 + .saturating_add(Weight::from_parts(4_821_702, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(v.into())) @@ -714,6 +718,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::MinValidatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxValidatorsCount` (r:0 w:1) /// Proof: `Staking::MaxValidatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::MaxStakedRewards` (r:0 w:1) + /// Proof: `Staking::MaxStakedRewards` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::ChillThreshold` (r:0 w:1) /// Proof: `Staking::ChillThreshold` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:0 w:1) @@ -724,9 +730,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_434_000 picoseconds. - Weight::from_parts(5_742_000, 0) - .saturating_add(T::DbWeight::get().writes(6_u64)) + // Minimum execution time: 5_765_000 picoseconds. + Weight::from_parts(6_140_000, 0) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Staking::MinCommission` (r:0 w:1) /// Proof: `Staking::MinCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -734,6 +740,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::MinValidatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxValidatorsCount` (r:0 w:1) /// Proof: `Staking::MaxValidatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::MaxStakedRewards` (r:0 w:1) + /// Proof: `Staking::MaxStakedRewards` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::ChillThreshold` (r:0 w:1) /// Proof: `Staking::ChillThreshold` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:0 w:1) @@ -744,9 +752,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_588_000 picoseconds. - Weight::from_parts(4_854_000, 0) - .saturating_add(T::DbWeight::get().writes(6_u64)) + // Minimum execution time: 5_025_000 picoseconds. + Weight::from_parts(5_354_000, 0) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) @@ -774,8 +782,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1939` // Estimated: `6248` - // Minimum execution time: 68_780_000 picoseconds. - Weight::from_parts(71_479_000, 6248) + // Minimum execution time: 69_656_000 picoseconds. + Weight::from_parts(71_574_000, 6248) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -787,8 +795,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `691` // Estimated: `3510` - // Minimum execution time: 12_268_000 picoseconds. - Weight::from_parts(12_661_000, 3510) + // Minimum execution time: 12_523_000 picoseconds. + Weight::from_parts(13_315_000, 3510) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -798,8 +806,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_071_000 picoseconds. - Weight::from_parts(3_334_000, 0) + // Minimum execution time: 3_125_000 picoseconds. + Weight::from_parts(3_300_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } @@ -820,8 +828,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `927` // Estimated: `4764` - // Minimum execution time: 42_042_000 picoseconds. - Weight::from_parts(43_292_000, 4764) + // Minimum execution time: 41_318_000 picoseconds. + Weight::from_parts(43_268_000, 4764) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -841,8 +849,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1990` // Estimated: `8877` - // Minimum execution time: 85_050_000 picoseconds. - Weight::from_parts(87_567_000, 8877) + // Minimum execution time: 85_666_000 picoseconds. + Weight::from_parts(88_749_000, 8877) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -868,8 +876,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2195` // Estimated: `8877` - // Minimum execution time: 89_076_000 picoseconds. - Weight::from_parts(92_715_000, 8877) + // Minimum execution time: 90_282_000 picoseconds. + Weight::from_parts(92_332_000, 8877) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -883,16 +891,18 @@ impl WeightInfo for () { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1115` + // Measured: `1297` // Estimated: `4764` - // Minimum execution time: 42_067_000 picoseconds. - Weight::from_parts(43_239_807, 4764) - // Standard Error: 831 - .saturating_add(Weight::from_parts(46_257, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Minimum execution time: 44_626_000 picoseconds. + Weight::from_parts(47_254_657, 4764) + // Standard Error: 1_179 + .saturating_add(Weight::from_parts(57_657, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Staking::Ledger` (r:1 w:1) @@ -928,10 +938,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 86_490_000 picoseconds. - Weight::from_parts(95_358_751, 6248) - // Standard Error: 3_952 - .saturating_add(Weight::from_parts(1_294_907, 0).saturating_mul(s.into())) + // Minimum execution time: 86_769_000 picoseconds. + Weight::from_parts(95_212_867, 6248) + // Standard Error: 3_706 + .saturating_add(Weight::from_parts(1_320_752, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(11_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -963,8 +973,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1372` // Estimated: `4556` - // Minimum execution time: 50_326_000 picoseconds. - Weight::from_parts(52_253_000, 4556) + // Minimum execution time: 50_410_000 picoseconds. + Weight::from_parts(52_576_000, 4556) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -977,10 +987,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1280 + k * (569 ±0)` // Estimated: `4556 + k * (3033 ±0)` - // Minimum execution time: 29_305_000 picoseconds. - Weight::from_parts(32_199_604, 4556) - // Standard Error: 7_150 - .saturating_add(Weight::from_parts(6_437_124, 0).saturating_mul(k.into())) + // Minimum execution time: 29_017_000 picoseconds. + Weight::from_parts(33_019_206, 4556) + // Standard Error: 6_368 + .saturating_add(Weight::from_parts(6_158_681, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -1013,10 +1023,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1866 + n * (102 ±0)` // Estimated: `6248 + n * (2520 ±0)` - // Minimum execution time: 63_267_000 picoseconds. - Weight::from_parts(61_741_404, 6248) - // Standard Error: 12_955 - .saturating_add(Weight::from_parts(3_811_743, 0).saturating_mul(n.into())) + // Minimum execution time: 63_452_000 picoseconds. + Weight::from_parts(60_924_066, 6248) + // Standard Error: 14_416 + .saturating_add(Weight::from_parts(3_921_589, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) @@ -1040,8 +1050,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1650` // Estimated: `6248` - // Minimum execution time: 52_862_000 picoseconds. - Weight::from_parts(54_108_000, 6248) + // Minimum execution time: 54_253_000 picoseconds. + Weight::from_parts(55_286_000, 6248) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -1055,8 +1065,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `902` // Estimated: `4556` - // Minimum execution time: 16_350_000 picoseconds. - Weight::from_parts(16_802_000, 4556) + // Minimum execution time: 16_812_000 picoseconds. + Weight::from_parts(17_380_000, 4556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1070,8 +1080,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `969` // Estimated: `4556` - // Minimum execution time: 19_981_000 picoseconds. - Weight::from_parts(20_539_000, 4556) + // Minimum execution time: 20_590_000 picoseconds. + Weight::from_parts(21_096_000, 4556) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1083,8 +1093,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `902` // Estimated: `4556` - // Minimum execution time: 19_304_000 picoseconds. - Weight::from_parts(20_000_000, 4556) + // Minimum execution time: 19_923_000 picoseconds. + Weight::from_parts(20_880_000, 4556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1094,8 +1104,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_568_000 picoseconds. - Weight::from_parts(2_708_000, 0) + // Minimum execution time: 2_599_000 picoseconds. + Weight::from_parts(2_751_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -1104,8 +1114,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_950_000 picoseconds. - Weight::from_parts(8_348_000, 0) + // Minimum execution time: 6_941_000 picoseconds. + Weight::from_parts(7_288_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -1114,8 +1124,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_967_000 picoseconds. - Weight::from_parts(8_222_000, 0) + // Minimum execution time: 6_757_000 picoseconds. + Weight::from_parts(7_200_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -1124,8 +1134,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_006_000 picoseconds. - Weight::from_parts(8_440_000, 0) + // Minimum execution time: 7_028_000 picoseconds. + Weight::from_parts(7_366_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::Invulnerables` (r:0 w:1) @@ -1135,10 +1145,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_524_000 picoseconds. - Weight::from_parts(3_123_608, 0) - // Standard Error: 59 - .saturating_add(Weight::from_parts(11_596, 0).saturating_mul(v.into())) + // Minimum execution time: 2_741_000 picoseconds. + Weight::from_parts(3_212_598, 0) + // Standard Error: 68 + .saturating_add(Weight::from_parts(11_695, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::Ledger` (r:5900 w:11800) @@ -1152,10 +1162,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1356 + i * (151 ±0)` // Estimated: `990 + i * (3566 ±0)` - // Minimum execution time: 2_092_000 picoseconds. - Weight::from_parts(2_258_000, 990) - // Standard Error: 32_695 - .saturating_add(Weight::from_parts(16_669_219, 0).saturating_mul(i.into())) + // Minimum execution time: 2_132_000 picoseconds. + Weight::from_parts(2_289_000, 990) + // Standard Error: 34_227 + .saturating_add(Weight::from_parts(17_006_583, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3566).saturating_mul(i.into())) @@ -1193,10 +1203,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 84_275_000 picoseconds. - Weight::from_parts(92_512_416, 6248) - // Standard Error: 3_633 - .saturating_add(Weight::from_parts(1_315_923, 0).saturating_mul(s.into())) + // Minimum execution time: 85_308_000 picoseconds. + Weight::from_parts(93_689_468, 6248) + // Standard Error: 5_425 + .saturating_add(Weight::from_parts(1_307_604, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(12_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -1209,10 +1219,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `66672` // Estimated: `70137` - // Minimum execution time: 101_707_000 picoseconds. - Weight::from_parts(912_819_462, 70137) - // Standard Error: 57_547 - .saturating_add(Weight::from_parts(4_856_799, 0).saturating_mul(s.into())) + // Minimum execution time: 103_242_000 picoseconds. + Weight::from_parts(1_162_296_080, 70137) + // Standard Error: 76_741 + .saturating_add(Weight::from_parts(6_487_522, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1249,10 +1259,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `33297 + n * (377 ±0)` // Estimated: `30944 + n * (3774 ±0)` - // Minimum execution time: 138_657_000 picoseconds. - Weight::from_parts(167_173_445, 30944) - // Standard Error: 25_130 - .saturating_add(Weight::from_parts(44_566_012, 0).saturating_mul(n.into())) + // Minimum execution time: 140_740_000 picoseconds. + Weight::from_parts(182_886_963, 30944) + // Standard Error: 39_852 + .saturating_add(Weight::from_parts(43_140_752, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().reads((6_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) @@ -1276,10 +1286,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1991 + l * (7 ±0)` // Estimated: `8877` - // Minimum execution time: 80_061_000 picoseconds. - Weight::from_parts(82_836_434, 8877) - // Standard Error: 4_348 - .saturating_add(Weight::from_parts(75_744, 0).saturating_mul(l.into())) + // Minimum execution time: 80_372_000 picoseconds. + Weight::from_parts(83_335_027, 8877) + // Standard Error: 4_780 + .saturating_add(Weight::from_parts(72_180, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -1314,10 +1324,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 92_560_000 picoseconds. - Weight::from_parts(97_684_741, 6248) - // Standard Error: 3_361 - .saturating_add(Weight::from_parts(1_292_732, 0).saturating_mul(s.into())) + // Minimum execution time: 93_920_000 picoseconds. + Weight::from_parts(98_022_911, 6248) + // Standard Error: 4_096 + .saturating_add(Weight::from_parts(1_287_745, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(11_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -1363,12 +1373,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + n * (720 ±0) + v * (3598 ±0)` // Estimated: `512390 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 564_963_000 picoseconds. - Weight::from_parts(569_206_000, 512390) - // Standard Error: 2_033_235 - .saturating_add(Weight::from_parts(68_025_841, 0).saturating_mul(v.into())) - // Standard Error: 202_600 - .saturating_add(Weight::from_parts(17_916_770, 0).saturating_mul(n.into())) + // Minimum execution time: 556_012_000 picoseconds. + Weight::from_parts(560_339_000, 512390) + // Standard Error: 2_115_076 + .saturating_add(Weight::from_parts(69_456_497, 0).saturating_mul(v.into())) + // Standard Error: 210_755 + .saturating_add(Weight::from_parts(17_974_873, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(206_u64)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -1399,12 +1409,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3175 + n * (911 ±0) + v * (395 ±0)` // Estimated: `512390 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 32_196_540_000 picoseconds. - Weight::from_parts(32_341_871_000, 512390) - // Standard Error: 354_657 - .saturating_add(Weight::from_parts(5_143_440, 0).saturating_mul(v.into())) - // Standard Error: 354_657 - .saturating_add(Weight::from_parts(3_328_189, 0).saturating_mul(n.into())) + // Minimum execution time: 32_792_819_000 picoseconds. + Weight::from_parts(32_986_606_000, 512390) + // Standard Error: 360_905 + .saturating_add(Weight::from_parts(5_260_151, 0).saturating_mul(v.into())) + // Standard Error: 360_905 + .saturating_add(Weight::from_parts(3_599_219, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(201_u64)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -1421,10 +1431,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `979 + v * (50 ±0)` // Estimated: `3510 + v * (2520 ±0)` - // Minimum execution time: 2_381_903_000 picoseconds. - Weight::from_parts(32_693_059, 3510) - // Standard Error: 10_000 - .saturating_add(Weight::from_parts(4_736_173, 0).saturating_mul(v.into())) + // Minimum execution time: 2_434_755_000 picoseconds. + Weight::from_parts(38_574_764, 3510) + // Standard Error: 14_467 + .saturating_add(Weight::from_parts(4_821_702, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(v.into())) @@ -1435,6 +1445,8 @@ impl WeightInfo for () { /// Proof: `Staking::MinValidatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxValidatorsCount` (r:0 w:1) /// Proof: `Staking::MaxValidatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::MaxStakedRewards` (r:0 w:1) + /// Proof: `Staking::MaxStakedRewards` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::ChillThreshold` (r:0 w:1) /// Proof: `Staking::ChillThreshold` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:0 w:1) @@ -1445,9 +1457,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_434_000 picoseconds. - Weight::from_parts(5_742_000, 0) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + // Minimum execution time: 5_765_000 picoseconds. + Weight::from_parts(6_140_000, 0) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Staking::MinCommission` (r:0 w:1) /// Proof: `Staking::MinCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -1455,6 +1467,8 @@ impl WeightInfo for () { /// Proof: `Staking::MinValidatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxValidatorsCount` (r:0 w:1) /// Proof: `Staking::MaxValidatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::MaxStakedRewards` (r:0 w:1) + /// Proof: `Staking::MaxStakedRewards` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::ChillThreshold` (r:0 w:1) /// Proof: `Staking::ChillThreshold` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:0 w:1) @@ -1465,9 +1479,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_588_000 picoseconds. - Weight::from_parts(4_854_000, 0) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + // Minimum execution time: 5_025_000 picoseconds. + Weight::from_parts(5_354_000, 0) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) @@ -1495,8 +1509,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1939` // Estimated: `6248` - // Minimum execution time: 68_780_000 picoseconds. - Weight::from_parts(71_479_000, 6248) + // Minimum execution time: 69_656_000 picoseconds. + Weight::from_parts(71_574_000, 6248) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -1508,8 +1522,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `691` // Estimated: `3510` - // Minimum execution time: 12_268_000 picoseconds. - Weight::from_parts(12_661_000, 3510) + // Minimum execution time: 12_523_000 picoseconds. + Weight::from_parts(13_315_000, 3510) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1519,8 +1533,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_071_000 picoseconds. - Weight::from_parts(3_334_000, 0) + // Minimum execution time: 3_125_000 picoseconds. + Weight::from_parts(3_300_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/state-trie-migration/src/lib.rs b/substrate/frame/state-trie-migration/src/lib.rs index 6b3aa9934e0..b89159ef3ec 100644 --- a/substrate/frame/state-trie-migration/src/lib.rs +++ b/substrate/frame/state-trie-migration/src/lib.rs @@ -1801,7 +1801,7 @@ mod remote_tests_local { use std::env::var as env_var; // we only use the hash type from this, so using the mock should be fine. - type Extrinsic = sp_runtime::testing::TestXt; + type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; type Block = sp_runtime::testing::Block; #[tokio::test] diff --git a/substrate/frame/state-trie-migration/src/weights.rs b/substrate/frame/state-trie-migration/src/weights.rs index 8fa80b38957..23dad9e3380 100644 --- a/substrate/frame/state-trie-migration/src/weights.rs +++ b/substrate/frame/state-trie-migration/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_state_trie_migration` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_state_trie_migration +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_state_trie_migration -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/state-trie-migration/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -64,15 +66,15 @@ impl WeightInfo for SubstrateWeight { /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `StateTrieMigration::MigrationProcess` (r:1 w:1) /// Proof: `StateTrieMigration::MigrationProcess` (`max_values`: Some(1), `max_size`: Some(1042), added: 1537, mode: `MaxEncodedLen`) fn continue_migrate() -> Weight { // Proof Size summary in bytes: // Measured: `108` - // Estimated: `3640` - // Minimum execution time: 18_520_000 picoseconds. - Weight::from_parts(19_171_000, 3640) + // Estimated: `3658` + // Minimum execution time: 17_661_000 picoseconds. + Weight::from_parts(18_077_000, 3658) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -82,53 +84,53 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1493` - // Minimum execution time: 3_786_000 picoseconds. - Weight::from_parts(4_038_000, 1493) + // Minimum execution time: 4_036_000 picoseconds. + Weight::from_parts(4_267_000, 1493) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn migrate_custom_top_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3640` - // Minimum execution time: 11_144_000 picoseconds. - Weight::from_parts(11_556_000, 3640) + // Estimated: `3658` + // Minimum execution time: 11_348_000 picoseconds. + Weight::from_parts(11_899_000, 3658) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_top_fail() -> Weight { // Proof Size summary in bytes: // Measured: `113` - // Estimated: `3640` - // Minimum execution time: 59_288_000 picoseconds. - Weight::from_parts(60_276_000, 3640) + // Estimated: `3658` + // Minimum execution time: 59_819_000 picoseconds. + Weight::from_parts(61_066_000, 3658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn migrate_custom_child_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3640` - // Minimum execution time: 11_258_000 picoseconds. - Weight::from_parts(11_626_000, 3640) + // Estimated: `3658` + // Minimum execution time: 11_424_000 picoseconds. + Weight::from_parts(11_765_000, 3658) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_child_fail() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `3640` - // Minimum execution time: 61_575_000 picoseconds. - Weight::from_parts(63_454_000, 3640) + // Estimated: `3658` + // Minimum execution time: 61_086_000 picoseconds. + Weight::from_parts(62_546_000, 3658) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -139,10 +141,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `197 + v * (1 ±0)` // Estimated: `3662 + v * (1 ±0)` - // Minimum execution time: 5_259_000 picoseconds. - Weight::from_parts(5_433_000, 3662) + // Minimum execution time: 5_375_000 picoseconds. + Weight::from_parts(5_552_000, 3662) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_159, 0).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(1_146, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(v.into())) @@ -154,15 +156,15 @@ impl WeightInfo for () { /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: `StateTrieMigration::MigrationProcess` (r:1 w:1) /// Proof: `StateTrieMigration::MigrationProcess` (`max_values`: Some(1), `max_size`: Some(1042), added: 1537, mode: `MaxEncodedLen`) fn continue_migrate() -> Weight { // Proof Size summary in bytes: // Measured: `108` - // Estimated: `3640` - // Minimum execution time: 18_520_000 picoseconds. - Weight::from_parts(19_171_000, 3640) + // Estimated: `3658` + // Minimum execution time: 17_661_000 picoseconds. + Weight::from_parts(18_077_000, 3658) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -172,53 +174,53 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1493` - // Minimum execution time: 3_786_000 picoseconds. - Weight::from_parts(4_038_000, 1493) + // Minimum execution time: 4_036_000 picoseconds. + Weight::from_parts(4_267_000, 1493) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn migrate_custom_top_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3640` - // Minimum execution time: 11_144_000 picoseconds. - Weight::from_parts(11_556_000, 3640) + // Estimated: `3658` + // Minimum execution time: 11_348_000 picoseconds. + Weight::from_parts(11_899_000, 3658) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_top_fail() -> Weight { // Proof Size summary in bytes: // Measured: `113` - // Estimated: `3640` - // Minimum execution time: 59_288_000 picoseconds. - Weight::from_parts(60_276_000, 3640) + // Estimated: `3658` + // Minimum execution time: 59_819_000 picoseconds. + Weight::from_parts(61_066_000, 3658) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) fn migrate_custom_child_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3640` - // Minimum execution time: 11_258_000 picoseconds. - Weight::from_parts(11_626_000, 3640) + // Estimated: `3658` + // Minimum execution time: 11_424_000 picoseconds. + Weight::from_parts(11_765_000, 3658) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_child_fail() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `3640` - // Minimum execution time: 61_575_000 picoseconds. - Weight::from_parts(63_454_000, 3640) + // Estimated: `3658` + // Minimum execution time: 61_086_000 picoseconds. + Weight::from_parts(62_546_000, 3658) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -229,10 +231,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `197 + v * (1 ±0)` // Estimated: `3662 + v * (1 ±0)` - // Minimum execution time: 5_259_000 picoseconds. - Weight::from_parts(5_433_000, 3662) + // Minimum execution time: 5_375_000 picoseconds. + Weight::from_parts(5_552_000, 3662) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_159, 0).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(1_146, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(v.into())) diff --git a/substrate/frame/sudo/src/benchmarking.rs b/substrate/frame/sudo/src/benchmarking.rs index e64233fe748..cdd7d707600 100644 --- a/substrate/frame/sudo/src/benchmarking.rs +++ b/substrate/frame/sudo/src/benchmarking.rs @@ -20,14 +20,23 @@ use super::*; use crate::Pallet; use frame_benchmarking::v2::*; +use frame_support::dispatch::DispatchInfo; use frame_system::RawOrigin; +use sp_runtime::traits::{AsSystemOriginSigner, DispatchTransaction, Dispatchable}; fn assert_last_event(generic_event: crate::Event) { let re: ::RuntimeEvent = generic_event.into(); frame_system::Pallet::::assert_last_event(re.into()); } -#[benchmarks(where ::RuntimeCall: From>)] +#[benchmarks(where + T: Send + Sync, + ::RuntimeCall: From>, + ::RuntimeCall: Dispatchable, + <::RuntimeCall as Dispatchable>::PostInfo: From<()>, + <::RuntimeCall as Dispatchable>::RuntimeOrigin: + AsSystemOriginSigner + Clone, +)] mod benchmarks { use super::*; @@ -85,5 +94,23 @@ mod benchmarks { assert_last_event::(Event::KeyRemoved {}); } + #[benchmark] + fn check_only_sudo_account() { + let caller: T::AccountId = whitelisted_caller(); + Key::::put(&caller); + + let call = frame_system::Call::remark { remark: vec![] }.into(); + let info = DispatchInfo { ..Default::default() }; + let ext = CheckOnlySudoAccount::::new(); + + #[block] + { + assert!(ext + .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(().into())) + .unwrap() + .is_ok()); + } + } + impl_benchmark_test_suite!(Pallet, crate::mock::new_bench_ext(), crate::mock::Test); } diff --git a/substrate/frame/sudo/src/extension.rs b/substrate/frame/sudo/src/extension.rs index e90286e5a7c..2cd8f945edd 100644 --- a/substrate/frame/sudo/src/extension.rs +++ b/substrate/frame/sudo/src/extension.rs @@ -20,10 +20,14 @@ use codec::{Decode, Encode}; use frame_support::{dispatch::DispatchInfo, ensure}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, SignedExtension}, + impl_tx_ext_default, + traits::{ + AsSystemOriginSigner, DispatchInfoOf, Dispatchable, TransactionExtension, + TransactionExtensionBase, + }, transaction_validity::{ - InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError, - UnknownTransaction, ValidTransaction, + InvalidTransaction, TransactionPriority, TransactionValidityError, UnknownTransaction, + ValidTransaction, }, }; use sp_std::{fmt, marker::PhantomData}; @@ -59,49 +63,61 @@ impl fmt::Debug for CheckOnlySudoAccount { } impl CheckOnlySudoAccount { - /// Creates new `SignedExtension` to check sudo key. + /// Creates new `TransactionExtension` to check sudo key. pub fn new() -> Self { Self::default() } } -impl SignedExtension for CheckOnlySudoAccount -where - ::RuntimeCall: Dispatchable, -{ +impl TransactionExtensionBase for CheckOnlySudoAccount { const IDENTIFIER: &'static str = "CheckOnlySudoAccount"; - type AccountId = T::AccountId; - type Call = ::RuntimeCall; - type AdditionalSigned = (); - type Pre = (); + type Implicit = (); - fn additional_signed(&self) -> Result { - Ok(()) + fn weight(&self) -> frame_support::weights::Weight { + use crate::weights::WeightInfo; + T::WeightInfo::check_only_sudo_account() } +} +impl + TransactionExtension<::RuntimeCall, Context> for CheckOnlySudoAccount +where + ::RuntimeCall: Dispatchable, + <::RuntimeCall as Dispatchable>::RuntimeOrigin: + AsSystemOriginSigner + Clone, +{ + type Pre = (); + type Val = (); fn validate( &self, - who: &Self::AccountId, - _call: &Self::Call, - info: &DispatchInfoOf, + origin: <::RuntimeCall as Dispatchable>::RuntimeOrigin, + _call: &::RuntimeCall, + info: &DispatchInfoOf<::RuntimeCall>, _len: usize, - ) -> TransactionValidity { + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> Result< + ( + ValidTransaction, + Self::Val, + <::RuntimeCall as Dispatchable>::RuntimeOrigin, + ), + TransactionValidityError, + > { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; let sudo_key: T::AccountId = Key::::get().ok_or(UnknownTransaction::CannotLookup)?; ensure!(*who == sudo_key, InvalidTransaction::BadSigner); - Ok(ValidTransaction { - priority: info.weight.ref_time() as TransactionPriority, - ..Default::default() - }) + Ok(( + ValidTransaction { + priority: info.weight.ref_time() as TransactionPriority, + ..Default::default() + }, + (), + origin, + )) } - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) - } + impl_tx_ext_default!(::RuntimeCall; Context; prepare); } diff --git a/substrate/frame/sudo/src/lib.rs b/substrate/frame/sudo/src/lib.rs index 2ebe4cb0157..2c953368b22 100644 --- a/substrate/frame/sudo/src/lib.rs +++ b/substrate/frame/sudo/src/lib.rs @@ -85,8 +85,8 @@ //! meant to be used by constructing runtime calls from outside the runtime. //! //! -//! This pallet also defines a [`SignedExtension`](sp_runtime::traits::SignedExtension) called -//! [`CheckOnlySudoAccount`] to ensure that only signed transactions by the sudo account are +//! This pallet also defines a [`TransactionExtension`](sp_runtime::traits::TransactionExtension) +//! called [`CheckOnlySudoAccount`] to ensure that only signed transactions by the sudo account are //! accepted by the transaction pool. The intended use of this signed extension is to prevent other //! accounts from spamming the transaction pool for the initial phase of a chain, during which //! developers may only want a sudo account to be able to make transactions. diff --git a/substrate/frame/sudo/src/weights.rs b/substrate/frame/sudo/src/weights.rs index 10d1a9f7a51..aa8f69fd4e6 100644 --- a/substrate/frame/sudo/src/weights.rs +++ b/substrate/frame/sudo/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_sudo` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-11-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_sudo +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_sudo -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/sudo/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -53,6 +55,7 @@ pub trait WeightInfo { fn sudo() -> Weight; fn sudo_as() -> Weight; fn remove_key() -> Weight; + fn check_only_sudo_account() -> Weight; } /// Weights for `pallet_sudo` using the Substrate node and recommended hardware. @@ -64,8 +67,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 9_600_000 picoseconds. - Weight::from_parts(10_076_000, 1517) + // Minimum execution time: 9_590_000 picoseconds. + Weight::from_parts(9_924_000, 1517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -75,8 +78,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 10_453_000 picoseconds. - Weight::from_parts(10_931_000, 1517) + // Minimum execution time: 9_825_000 picoseconds. + Weight::from_parts(10_373_000, 1517) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Sudo::Key` (r:1 w:0) @@ -85,8 +88,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 10_202_000 picoseconds. - Weight::from_parts(10_800_000, 1517) + // Minimum execution time: 10_140_000 picoseconds. + Weight::from_parts(10_382_000, 1517) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Sudo::Key` (r:1 w:1) @@ -95,11 +98,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 8_555_000 picoseconds. - Weight::from_parts(8_846_000, 1517) + // Minimum execution time: 8_610_000 picoseconds. + Weight::from_parts(8_975_000, 1517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: `Sudo::Key` (r:1 w:0) + /// Proof: `Sudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + fn check_only_sudo_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `165` + // Estimated: `1517` + // Minimum execution time: 3_416_000 picoseconds. + Weight::from_parts(3_645_000, 1517) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } } // For backwards compatibility and tests. @@ -110,8 +123,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 9_600_000 picoseconds. - Weight::from_parts(10_076_000, 1517) + // Minimum execution time: 9_590_000 picoseconds. + Weight::from_parts(9_924_000, 1517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -121,8 +134,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 10_453_000 picoseconds. - Weight::from_parts(10_931_000, 1517) + // Minimum execution time: 9_825_000 picoseconds. + Weight::from_parts(10_373_000, 1517) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Sudo::Key` (r:1 w:0) @@ -131,8 +144,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 10_202_000 picoseconds. - Weight::from_parts(10_800_000, 1517) + // Minimum execution time: 10_140_000 picoseconds. + Weight::from_parts(10_382_000, 1517) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Sudo::Key` (r:1 w:1) @@ -141,9 +154,19 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 8_555_000 picoseconds. - Weight::from_parts(8_846_000, 1517) + // Minimum execution time: 8_610_000 picoseconds. + Weight::from_parts(8_975_000, 1517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + /// Storage: `Sudo::Key` (r:1 w:0) + /// Proof: `Sudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + fn check_only_sudo_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `165` + // Estimated: `1517` + // Minimum execution time: 3_416_000 picoseconds. + Weight::from_parts(3_645_000, 1517) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } } diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml index fb9cb3d4511..113af41751e 100644 --- a/substrate/frame/support/Cargo.toml +++ b/substrate/frame/support/Cargo.toml @@ -95,9 +95,9 @@ std = [ "sp-staking/std", "sp-state-machine/std", "sp-std/std", + "sp-timestamp/std", "sp-tracing/std", "sp-weights/std", - "sp-timestamp/std" ] runtime-benchmarks = [ "frame-system/runtime-benchmarks", diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs index da483fa6cf0..d21cfef4a92 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -73,11 +73,9 @@ pub fn expand_outer_inherent( #( #pallet_attrs if let Some(inherent) = #pallet_names::create_inherent(self) { - let inherent = <#unchecked_extrinsic as #scrate::sp_runtime::traits::Extrinsic>::new( + let inherent = <#unchecked_extrinsic as #scrate::sp_runtime::traits::Extrinsic>::new_inherent( inherent.into(), - None, - ).expect("Runtime UncheckedExtrinsic is not Opaque, so it has to return \ - `Some`; qed"); + ); inherents.push(inherent); } @@ -123,7 +121,7 @@ pub fn expand_outer_inherent( for xt in block.extrinsics() { // Inherents are before any other extrinsics. // And signed extrinsics are not inherents. - if #scrate::sp_runtime::traits::Extrinsic::is_signed(xt).unwrap_or(false) { + if !(#scrate::sp_runtime::traits::Extrinsic::is_bare(xt)) { break } @@ -161,10 +159,9 @@ pub fn expand_outer_inherent( match #pallet_names::is_inherent_required(self) { Ok(Some(e)) => { let found = block.extrinsics().iter().any(|xt| { - let is_signed = #scrate::sp_runtime::traits::Extrinsic::is_signed(xt) - .unwrap_or(false); + let is_bare = #scrate::sp_runtime::traits::Extrinsic::is_bare(xt); - if !is_signed { + if is_bare { let call = < #unchecked_extrinsic as ExtrinsicCall >::call(xt); @@ -209,8 +206,9 @@ pub fn expand_outer_inherent( use #scrate::inherent::ProvideInherent; use #scrate::traits::{IsSubType, ExtrinsicCall}; - if #scrate::sp_runtime::traits::Extrinsic::is_signed(ext).unwrap_or(false) { - // Signed extrinsics are never inherents. + let is_bare = #scrate::sp_runtime::traits::Extrinsic::is_bare(ext); + if !is_bare { + // Signed extrinsics are not inherents. return false } diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs index 0e76f9a9246..f55ca677d89 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs @@ -119,13 +119,13 @@ pub fn expand_runtime_metadata( call_ty, signature_ty, extra_ty, - signed_extensions: < + extensions: < < #extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata - >::SignedExtensions as #scrate::sp_runtime::traits::SignedExtension + >::Extra as #scrate::sp_runtime::traits::TransactionExtensionBase >::metadata() .into_iter() - .map(|meta| #scrate::__private::metadata_ir::SignedExtensionMetadataIR { + .map(|meta| #scrate::__private::metadata_ir::TransactionExtensionMetadataIR { identifier: meta.identifier, ty: meta.ty, additional_signed: meta.additional_signed, diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs index 83049919d01..341621deb09 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -153,6 +153,10 @@ pub fn expand_outer_origin( self.filter = #scrate::__private::sp_std::rc::Rc::new(Box::new(filter)); } + fn set_caller(&mut self, caller: OriginCaller) { + self.caller = caller; + } + fn set_caller_from(&mut self, other: impl Into) { self.caller = other.into().caller; } @@ -301,6 +305,16 @@ pub fn expand_outer_origin( } } + impl #scrate::__private::AsSystemOriginSigner<<#runtime as #system_path::Config>::AccountId> for RuntimeOrigin { + fn as_system_origin_signer(&self) -> Option<&<#runtime as #system_path::Config>::AccountId> { + if let OriginCaller::system(#system_path::Origin::<#runtime>::Signed(ref signed)) = &self.caller { + Some(signed) + } else { + None + } + } + } + #pallet_conversions }) } diff --git a/substrate/frame/support/src/dispatch.rs b/substrate/frame/support/src/dispatch.rs index 4a313551aca..61787a74012 100644 --- a/substrate/frame/support/src/dispatch.rs +++ b/substrate/frame/support/src/dispatch.rs @@ -25,7 +25,7 @@ use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; use sp_runtime::{ generic::{CheckedExtrinsic, UncheckedExtrinsic}, - traits::SignedExtension, + traits::Dispatchable, DispatchError, RuntimeDebug, }; use sp_std::fmt; @@ -268,7 +268,8 @@ pub fn extract_actual_weight(result: &DispatchResultWithPostInfo, info: &Dispatc .calc_actual_weight(info) } -/// Extract the actual pays_fee from a dispatch result if any or fall back to the default weight. +/// Extract the actual pays_fee from a dispatch result if any or fall back to the default +/// weight. pub fn extract_actual_pays_fee(result: &DispatchResultWithPostInfo, info: &DispatchInfo) -> Pays { match result { Ok(post_info) => post_info, @@ -368,11 +369,10 @@ where } /// Implementation for unchecked extrinsic. -impl GetDispatchInfo - for UncheckedExtrinsic +impl GetDispatchInfo + for UncheckedExtrinsic where - Call: GetDispatchInfo, - Extra: SignedExtension, + Call: GetDispatchInfo + Dispatchable, { fn get_dispatch_info(&self) -> DispatchInfo { self.function.get_dispatch_info() @@ -380,7 +380,7 @@ where } /// Implementation for checked extrinsic. -impl GetDispatchInfo for CheckedExtrinsic +impl GetDispatchInfo for CheckedExtrinsic where Call: GetDispatchInfo, { @@ -389,21 +389,6 @@ where } } -/// Implementation for test extrinsic. -#[cfg(feature = "std")] -impl GetDispatchInfo - for sp_runtime::testing::TestXt -{ - fn get_dispatch_info(&self) -> DispatchInfo { - // for testing: weight == size. - DispatchInfo { - weight: Weight::from_parts(self.encode().len() as _, 0), - pays_fee: Pays::Yes, - class: self.call.get_dispatch_info().class, - } - } -} - /// A struct holding value for each `DispatchClass`. #[derive(Clone, Eq, PartialEq, Default, Debug, Encode, Decode, TypeInfo, MaxEncodedLen)] pub struct PerDispatchClass { diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index caf9457d666..b5b1ac09c60 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -54,7 +54,8 @@ pub mod __private { #[cfg(feature = "std")] pub use sp_runtime::{bounded_btree_map, bounded_vec}; pub use sp_runtime::{ - traits::Dispatchable, DispatchError, RuntimeDebug, StateVersion, TransactionOutcome, + traits::{AsSystemOriginSigner, Dispatchable}, + DispatchError, RuntimeDebug, StateVersion, TransactionOutcome, }; #[cfg(feature = "std")] pub use sp_state_machine::BasicExternalities; @@ -75,6 +76,7 @@ pub mod storage; #[cfg(test)] mod tests; pub mod traits; +pub mod transaction_extensions; pub mod weights; #[doc(hidden)] pub mod unsigned { @@ -1602,8 +1604,8 @@ pub mod pallet_macros { /// [`ValidateUnsigned`](frame_support::pallet_prelude::ValidateUnsigned) for /// type `Pallet`, and some optional where clause. /// - /// NOTE: There is also the [`sp_runtime::traits::SignedExtension`] trait that can be used - /// to add some specific logic for transaction validation. + /// NOTE: There is also the [`sp_runtime::traits::TransactionExtension`] trait that can be + /// used to add some specific logic for transaction validation. /// /// ## Macro expansion /// diff --git a/substrate/frame/support/src/traits/dispatch.rs b/substrate/frame/support/src/traits/dispatch.rs index de50ce7a26c..212c3080352 100644 --- a/substrate/frame/support/src/traits/dispatch.rs +++ b/substrate/frame/support/src/traits/dispatch.rs @@ -482,7 +482,7 @@ pub trait OriginTrait: Sized { type Call; /// The caller origin, overarching type of all pallets origins. - type PalletsOrigin: Into + CallerTrait + MaxEncodedLen; + type PalletsOrigin: Send + Sync + Into + CallerTrait + MaxEncodedLen; /// The AccountId used across the system. type AccountId; @@ -496,6 +496,14 @@ pub trait OriginTrait: Sized { /// Replace the caller with caller from the other origin fn set_caller_from(&mut self, other: impl Into); + /// Replace the caller with caller from the other origin + fn set_caller(&mut self, caller: Self::PalletsOrigin); + + /// Replace the caller with caller from the other origin + fn set_caller_from_signed(&mut self, caller_account: Self::AccountId) { + self.set_caller(Self::PalletsOrigin::from(RawOrigin::Signed(caller_account))) + } + /// Filter the call if caller is not root, if false is returned then the call must be filtered /// out. /// @@ -544,6 +552,17 @@ pub trait OriginTrait: Sized { fn as_system_ref(&self) -> Option<&RawOrigin> { self.caller().as_system_ref() } + + /// Extract a reference to the sytsem signer, if that's what the caller is. + fn as_system_signer(&self) -> Option<&Self::AccountId> { + self.caller().as_system_ref().and_then(|s| { + if let RawOrigin::Signed(ref who) = s { + Some(who) + } else { + None + } + }) + } } #[cfg(test)] diff --git a/substrate/frame/support/src/traits/misc.rs b/substrate/frame/support/src/traits/misc.rs index 1f634a64282..fba546ce21b 100644 --- a/substrate/frame/support/src/traits/misc.rs +++ b/substrate/frame/support/src/traits/misc.rs @@ -919,24 +919,13 @@ pub trait ExtrinsicCall: sp_runtime::traits::Extrinsic { fn call(&self) -> &Self::Call; } -#[cfg(feature = "std")] -impl ExtrinsicCall for sp_runtime::testing::TestXt -where - Call: codec::Codec + Sync + Send + TypeInfo, - Extra: TypeInfo, -{ - fn call(&self) -> &Self::Call { - &self.call - } -} - impl ExtrinsicCall for sp_runtime::generic::UncheckedExtrinsic where Address: TypeInfo, Call: TypeInfo, Signature: TypeInfo, - Extra: sp_runtime::traits::SignedExtension + TypeInfo, + Extra: TypeInfo, { fn call(&self) -> &Self::Call { &self.function diff --git a/substrate/frame/support/src/transaction_extensions.rs b/substrate/frame/support/src/transaction_extensions.rs new file mode 100644 index 00000000000..98d78b9b4e4 --- /dev/null +++ b/substrate/frame/support/src/transaction_extensions.rs @@ -0,0 +1,89 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Transaction extensions. + +use crate::{CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound}; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_io::hashing::blake2_256; +use sp_runtime::{ + impl_tx_ext_default, + traits::{ + transaction_extension::{TransactionExtensionBase, TransactionExtensionInterior}, + DispatchInfoOf, Dispatchable, IdentifyAccount, TransactionExtension, Verify, + }, + transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction}, +}; + +#[derive( + CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, RuntimeDebugNoBound, TypeInfo, +)] +#[codec(encode_bound())] +#[codec(decode_bound())] +pub struct VerifyMultiSignature +where + V: TransactionExtensionInterior, + ::AccountId: TransactionExtensionInterior, +{ + signature: V, + account: ::AccountId, +} + +impl TransactionExtensionBase for VerifyMultiSignature +where + V: TransactionExtensionInterior, + ::AccountId: TransactionExtensionInterior, +{ + const IDENTIFIER: &'static str = "VerifyMultiSignature"; + type Implicit = (); +} + +impl TransactionExtension + for VerifyMultiSignature +where + V: TransactionExtensionInterior, + ::AccountId: TransactionExtensionInterior, + ::RuntimeOrigin: From::AccountId>>, +{ + type Val = (); + type Pre = (); + impl_tx_ext_default!(Call; Context; prepare); + + fn validate( + &self, + _origin: ::RuntimeOrigin, + _call: &Call, + _info: &DispatchInfoOf, + _len: usize, + _: &mut Context, + _: (), + inherited_implication: &impl Encode, + ) -> Result< + (ValidTransaction, Self::Val, ::RuntimeOrigin), + TransactionValidityError, + > { + let msg = inherited_implication.using_encoded(blake2_256); + + if !self.signature.verify(&msg[..], &self.account) { + Err(InvalidTransaction::BadProof)? + } + // We clobber the original origin. Maybe we shuld check that it's none? + let origin = Some(self.account.clone()).into(); + Ok((ValidTransaction::default(), (), origin)) + } +} diff --git a/substrate/frame/support/src/weights/block_weights.rs b/substrate/frame/support/src/weights/block_weights.rs index 57a68554755..647b6198357 100644 --- a/substrate/frame/support/src/weights/block_weights.rs +++ b/substrate/frame/support/src/weights/block_weights.rs @@ -15,24 +15,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16 (Y/M/D) -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01 (Y/M/D) +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! //! SHORT-NAME: `block`, LONG-NAME: `BlockExecution`, RUNTIME: `Development` //! WARMUPS: `10`, REPEAT: `100` -//! WEIGHT-PATH: `./frame/support/src/weights/` +//! WEIGHT-PATH: `./substrate/frame/support/src/weights/` //! WEIGHT-METRIC: `Average`, WEIGHT-MUL: `1.0`, WEIGHT-ADD: `0` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // overhead // --chain=dev -// --execution=wasm // --wasm-execution=compiled -// --weight-path=./frame/support/src/weights/ -// --header=./HEADER-APACHE2 +// --weight-path=./substrate/frame/support/src/weights/ +// --header=./substrate/HEADER-APACHE2 // --warmup=10 // --repeat=100 @@ -44,17 +43,17 @@ parameter_types! { /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 376_949, 622_462 - /// Average: 390_584 - /// Median: 386_322 - /// Std-Dev: 24792.0 + /// Min, Max: 424_332, 493_017 + /// Average: 437_118 + /// Median: 434_920 + /// Std-Dev: 8798.01 /// /// Percentiles nanoseconds: - /// 99th: 433_299 - /// 95th: 402_688 - /// 75th: 391_645 + /// 99th: 460_074 + /// 95th: 451_580 + /// 75th: 440_307 pub const BlockExecutionWeight: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(390_584), 0); + Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(437_118), 0); } #[cfg(test)] diff --git a/substrate/frame/support/src/weights/extrinsic_weights.rs b/substrate/frame/support/src/weights/extrinsic_weights.rs index a304f089ff7..99b392c4369 100644 --- a/substrate/frame/support/src/weights/extrinsic_weights.rs +++ b/substrate/frame/support/src/weights/extrinsic_weights.rs @@ -15,24 +15,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16 (Y/M/D) -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01 (Y/M/D) +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! //! SHORT-NAME: `extrinsic`, LONG-NAME: `ExtrinsicBase`, RUNTIME: `Development` //! WARMUPS: `10`, REPEAT: `100` -//! WEIGHT-PATH: `./frame/support/src/weights/` +//! WEIGHT-PATH: `./substrate/frame/support/src/weights/` //! WEIGHT-METRIC: `Average`, WEIGHT-MUL: `1.0`, WEIGHT-ADD: `0` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // overhead // --chain=dev -// --execution=wasm // --wasm-execution=compiled -// --weight-path=./frame/support/src/weights/ -// --header=./HEADER-APACHE2 +// --weight-path=./substrate/frame/support/src/weights/ +// --header=./substrate/HEADER-APACHE2 // --warmup=10 // --repeat=100 @@ -44,17 +43,17 @@ parameter_types! { /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 123_875, 128_419 - /// Average: 124_414 - /// Median: 124_332 - /// Std-Dev: 497.74 + /// Min, Max: 106_053, 107_403 + /// Average: 106_446 + /// Median: 106_415 + /// Std-Dev: 216.17 /// /// Percentiles nanoseconds: - /// 99th: 125_245 - /// 95th: 124_989 - /// 75th: 124_498 + /// 99th: 107_042 + /// 95th: 106_841 + /// 75th: 106_544 pub const ExtrinsicBaseWeight: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(124_414), 0); + Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(106_446), 0); } #[cfg(test)] diff --git a/substrate/frame/support/test/tests/construct_runtime.rs b/substrate/frame/support/test/tests/construct_runtime.rs index b7698681886..83691451ccd 100644 --- a/substrate/frame/support/test/tests/construct_runtime.rs +++ b/substrate/frame/support/test/tests/construct_runtime.rs @@ -815,7 +815,7 @@ fn test_metadata() { ty: meta_type::(), version: 4, signed_extensions: vec![SignedExtensionMetadata { - identifier: "UnitSignedExtension", + identifier: "UnitTransactionExtension", ty: meta_type::<()>(), additional_signed: meta_type::<()>(), }], diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr index 61cfc07caed..9dd460da75a 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr @@ -477,7 +477,7 @@ note: required because it appears within the type `RuntimeCall` | ||_- in this macro invocation ... | note: required by a bound in `frame_support::sp_runtime::traits::Dispatchable::Config` - --> $WORKSPACE/substrate/primitives/runtime/src/traits.rs + --> $WORKSPACE/substrate/primitives/runtime/src/traits/mod.rs | | type Config; | ^^^^^^^^^^^^ required by this bound in `Dispatchable::Config` @@ -510,7 +510,7 @@ note: required because it appears within the type `RuntimeCall` | ||_- in this macro invocation ... | note: required by a bound in `frame_support::pallet_prelude::ValidateUnsigned::Call` - --> $WORKSPACE/substrate/primitives/runtime/src/traits.rs + --> $WORKSPACE/substrate/primitives/runtime/src/traits/mod.rs | | type Call; | ^^^^^^^^^^ required by this bound in `ValidateUnsigned::Call` diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 607f54ccc13..4d2737d411e 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -743,10 +743,40 @@ impl pallet5::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; } +#[derive(Clone, Debug, codec::Encode, codec::Decode, PartialEq, Eq, scale_info::TypeInfo)] +pub struct AccountU64(u64); +impl sp_runtime::traits::IdentifyAccount for AccountU64 { + type AccountId = u64; + fn into_account(self) -> u64 { + self.0 + } +} + +impl sp_runtime::traits::Verify for AccountU64 { + type Signer = AccountU64; + fn verify>( + &self, + _msg: L, + _signer: &::AccountId, + ) -> bool { + true + } +} + +impl From for AccountU64 { + fn from(value: u64) -> Self { + Self(value) + } +} + pub type Header = sp_runtime::generic::Header; pub type Block = sp_runtime::generic::Block; -pub type UncheckedExtrinsic = - sp_runtime::testing::TestXt>; +pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic< + u64, + RuntimeCall, + AccountU64, + frame_system::CheckNonZeroSender, +>; frame_support::construct_runtime!( pub struct Runtime { @@ -896,10 +926,8 @@ fn inherent_expand() { let inherents = InherentData::new().create_extrinsics(); - let expected = vec![UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), - signature: None, - }]; + let expected = + vec![UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {}))]; assert_eq!(expected, inherents); let block = Block::new( @@ -911,14 +939,11 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), - signature: None, - }, - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 0 }), - signature: None, - }, + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {})), + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { + foo: 1, + bar: 0, + })), ], ); @@ -933,14 +958,11 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), - signature: None, - }, - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo { foo: 0, bar: 0 }), - signature: None, - }, + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {})), + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { + foo: 0, + bar: 0, + })), ], ); @@ -954,10 +976,9 @@ fn inherent_expand() { BlakeTwo256::hash(b"test"), Digest::default(), ), - vec![UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_storage_layer { foo: 0 }), - signature: None, - }], + vec![UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_storage_layer { + foo: 0, + }))], ); let mut inherent = InherentData::new(); @@ -972,10 +993,12 @@ fn inherent_expand() { BlakeTwo256::hash(b"test"), Digest::default(), ), - vec![UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), - signature: Some((1, Default::default())), - }], + vec![UncheckedExtrinsic::new_signed( + RuntimeCall::Example(pallet::Call::foo_no_post_info {}), + 1, + 1.into(), + Default::default(), + )], ); let mut inherent = InherentData::new(); @@ -991,14 +1014,13 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 1 }), - signature: None, - }, - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_storage_layer { foo: 0 }), - signature: None, - }, + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { + foo: 1, + bar: 1, + })), + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_storage_layer { + foo: 0, + })), ], ); @@ -1013,18 +1035,14 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 1 }), - signature: None, - }, - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_storage_layer { foo: 0 }), - signature: None, - }, - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), - signature: None, - }, + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { + foo: 1, + bar: 1, + })), + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_storage_layer { + foo: 0, + })), + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {})), ], ); @@ -1039,18 +1057,17 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 1 }), - signature: None, - }, - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 0 }), - signature: Some((1, Default::default())), - }, - UncheckedExtrinsic { - call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), - signature: None, - }, + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { + foo: 1, + bar: 1, + })), + UncheckedExtrinsic::new_signed( + RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 0 }), + 1, + 1.into(), + Default::default(), + ), + UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {})), ], ); @@ -1933,7 +1950,7 @@ fn extrinsic_metadata_ir_types() { >(), ir.signature_ty ); - assert_eq!(meta_type::<()>(), ir.signature_ty); + assert_eq!(meta_type::(), ir.signature_ty); assert_eq!(meta_type::<<::SignaturePayload as SignaturePayloadT>::SignatureExtra>(), ir.extra_ty); assert_eq!(meta_type::>(), ir.extra_ty); diff --git a/substrate/frame/support/test/tests/pallet_instance.rs b/substrate/frame/support/test/tests/pallet_instance.rs index f8cc97623b8..505400a7c21 100644 --- a/substrate/frame/support/test/tests/pallet_instance.rs +++ b/substrate/frame/support/test/tests/pallet_instance.rs @@ -943,7 +943,7 @@ fn metadata() { ty: scale_info::meta_type::(), version: 4, signed_extensions: vec![SignedExtensionMetadata { - identifier: "UnitSignedExtension", + identifier: "UnitTransactionExtension", ty: scale_info::meta_type::<()>(), additional_signed: scale_info::meta_type::<()>(), }], diff --git a/substrate/frame/system/benchmarking/src/extensions.rs b/substrate/frame/system/benchmarking/src/extensions.rs new file mode 100644 index 00000000000..1721501dead --- /dev/null +++ b/substrate/frame/system/benchmarking/src/extensions.rs @@ -0,0 +1,213 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +// Benchmarks for System Extensions + +#![cfg(feature = "runtime-benchmarks")] + +use frame_benchmarking::{account, impl_benchmark_test_suite, v2::*, BenchmarkError}; +use frame_support::{ + dispatch::{DispatchClass, DispatchInfo, PostDispatchInfo}, + weights::Weight, +}; +use frame_system::{ + pallet_prelude::*, CheckGenesis, CheckMortality, CheckNonZeroSender, CheckNonce, + CheckSpecVersion, CheckTxVersion, CheckWeight, Config, Pallet as System, RawOrigin, +}; +use sp_runtime::{ + generic::Era, + traits::{AsSystemOriginSigner, DispatchTransaction, Dispatchable, Get}, +}; +use sp_std::prelude::*; + +pub struct Pallet(System); + +#[benchmarks(where + T: Send + Sync, + T::RuntimeCall: Dispatchable, + ::RuntimeOrigin: AsSystemOriginSigner + Clone) +] +mod benchmarks { + use super::*; + + #[benchmark] + fn check_genesis() -> Result<(), BenchmarkError> { + let len = 0_usize; + let caller = account("caller", 0, 0); + let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; + let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + + #[block] + { + CheckGenesis::::new() + .test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) + .unwrap() + .unwrap(); + } + + Ok(()) + } + + #[benchmark] + fn check_mortality() -> Result<(), BenchmarkError> { + let len = 0_usize; + let ext = CheckMortality::::from(Era::mortal(16, 256)); + let block_number: BlockNumberFor = 17u32.into(); + System::::set_block_number(block_number); + let prev_block: BlockNumberFor = 16u32.into(); + let default_hash: T::Hash = Default::default(); + frame_system::BlockHash::::insert(prev_block, default_hash); + let caller = account("caller", 0, 0); + let info = DispatchInfo { + weight: Weight::from_parts(100, 0), + class: DispatchClass::Normal, + ..Default::default() + }; + let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + + #[block] + { + ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) + .unwrap() + .unwrap(); + } + Ok(()) + } + + #[benchmark] + fn check_non_zero_sender() -> Result<(), BenchmarkError> { + let len = 0_usize; + let ext = CheckNonZeroSender::::new(); + let caller = account("caller", 0, 0); + let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; + let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + + #[block] + { + ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) + .unwrap() + .unwrap(); + } + Ok(()) + } + + #[benchmark] + fn check_nonce() -> Result<(), BenchmarkError> { + let caller: T::AccountId = account("caller", 0, 0); + let mut info = frame_system::AccountInfo::default(); + info.nonce = 1u32.into(); + info.providers = 1; + let expected_nonce = info.nonce + 1u32.into(); + frame_system::Account::::insert(caller.clone(), info); + let len = 0_usize; + let ext = CheckNonce::::from(1u32.into()); + let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; + let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + + #[block] + { + ext.test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, len, |_| { + Ok(().into()) + }) + .unwrap() + .unwrap(); + } + + let updated_info = frame_system::Account::::get(caller.clone()); + assert_eq!(updated_info.nonce, expected_nonce); + Ok(()) + } + + #[benchmark] + fn check_spec_version() -> Result<(), BenchmarkError> { + let len = 0_usize; + let caller = account("caller", 0, 0); + let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; + let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + + #[block] + { + CheckSpecVersion::::new() + .test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) + .unwrap() + .unwrap(); + } + Ok(()) + } + + #[benchmark] + fn check_tx_version() -> Result<(), BenchmarkError> { + let len = 0_usize; + let caller = account("caller", 0, 0); + let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; + let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + + #[block] + { + CheckTxVersion::::new() + .test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) + .unwrap() + .unwrap(); + } + Ok(()) + } + + #[benchmark] + fn check_weight() -> Result<(), BenchmarkError> { + let caller = account("caller", 0, 0); + let base_extrinsic = ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let info = DispatchInfo { + weight: Weight::from_parts(base_extrinsic.ref_time() * 5, 0), + class: DispatchClass::Normal, + ..Default::default() + }; + let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(base_extrinsic.ref_time() * 2, 0)), + pays_fee: Default::default(), + }; + let len = 0_usize; + let base_extrinsic = ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + + let ext = CheckWeight::::new(); + + let initial_block_weight = Weight::from_parts(base_extrinsic.ref_time() * 2, 0); + frame_system::BlockWeight::::mutate(|current_weight| { + current_weight.set(Weight::zero(), DispatchClass::Mandatory); + current_weight.set(initial_block_weight, DispatchClass::Normal); + }); + + #[block] + { + ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(post_info)) + .unwrap() + .unwrap(); + } + + assert_eq!( + System::::block_weight().total(), + initial_block_weight + base_extrinsic + post_info.actual_weight.unwrap(), + ); + Ok(()) + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test,); +} diff --git a/substrate/frame/system/benchmarking/src/lib.rs b/substrate/frame/system/benchmarking/src/lib.rs index 18bfb85f52d..ebd16275bcb 100644 --- a/substrate/frame/system/benchmarking/src/lib.rs +++ b/substrate/frame/system/benchmarking/src/lib.rs @@ -28,6 +28,7 @@ use sp_core::storage::well_known_keys; use sp_runtime::traits::Hash; use sp_std::{prelude::*, vec}; +pub mod extensions; mod mock; pub struct Pallet(System); diff --git a/substrate/frame/system/benchmarking/src/mock.rs b/substrate/frame/system/benchmarking/src/mock.rs index edbf74a9a51..1f84dd53004 100644 --- a/substrate/frame/system/benchmarking/src/mock.rs +++ b/substrate/frame/system/benchmarking/src/mock.rs @@ -57,6 +57,7 @@ impl frame_system::Config for Test { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); + type ExtensionsWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; diff --git a/substrate/frame/system/src/extensions/check_genesis.rs b/substrate/frame/system/src/extensions/check_genesis.rs index 76a711a823e..3f11f745cd9 100644 --- a/substrate/frame/system/src/extensions/check_genesis.rs +++ b/substrate/frame/system/src/extensions/check_genesis.rs @@ -19,7 +19,8 @@ use crate::{pallet_prelude::BlockNumberFor, Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, SignedExtension, Zero}, + impl_tx_ext_default, + traits::{TransactionExtension, TransactionExtensionBase, Zero}, transaction_validity::TransactionValidityError, }; @@ -46,30 +47,26 @@ impl sp_std::fmt::Debug for CheckGenesis { } impl CheckGenesis { - /// Creates new `SignedExtension` to check genesis hash. + /// Creates new `TransactionExtension` to check genesis hash. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl SignedExtension for CheckGenesis { - type AccountId = T::AccountId; - type Call = ::RuntimeCall; - type AdditionalSigned = T::Hash; - type Pre = (); +impl TransactionExtensionBase for CheckGenesis { const IDENTIFIER: &'static str = "CheckGenesis"; - - fn additional_signed(&self) -> Result { + type Implicit = T::Hash; + fn implicit(&self) -> Result { Ok(>::block_hash(BlockNumberFor::::zero())) } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) + fn weight(&self) -> sp_weights::Weight { + ::check_genesis() } } +impl TransactionExtension + for CheckGenesis +{ + type Val = (); + type Pre = (); + impl_tx_ext_default!(T::RuntimeCall; Context; validate prepare); +} diff --git a/substrate/frame/system/src/extensions/check_mortality.rs b/substrate/frame/system/src/extensions/check_mortality.rs index 148dfd4aad4..deb44880d64 100644 --- a/substrate/frame/system/src/extensions/check_mortality.rs +++ b/substrate/frame/system/src/extensions/check_mortality.rs @@ -20,10 +20,12 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ generic::Era, - traits::{DispatchInfoOf, SaturatedConversion, SignedExtension}, - transaction_validity::{ - InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + impl_tx_ext_default, + traits::{ + DispatchInfoOf, SaturatedConversion, TransactionExtension, TransactionExtensionBase, + ValidateResult, }, + transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction}, }; /// Check for transaction mortality. @@ -54,29 +56,11 @@ impl sp_std::fmt::Debug for CheckMortality { } } -impl SignedExtension for CheckMortality { - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = T::Hash; - type Pre = (); +impl TransactionExtensionBase for CheckMortality { const IDENTIFIER: &'static str = "CheckMortality"; + type Implicit = T::Hash; - fn validate( - &self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> TransactionValidity { - let current_u64 = >::block_number().saturated_into::(); - let valid_till = self.0.death(current_u64); - Ok(ValidTransaction { - longevity: valid_till.saturating_sub(current_u64), - ..Default::default() - }) - } - - fn additional_signed(&self) -> Result { + fn implicit(&self) -> Result { let current_u64 = >::block_number().saturated_into::(); let n = self.0.birth(current_u64).saturated_into::>(); if !>::contains_key(n) { @@ -85,16 +69,38 @@ impl SignedExtension for CheckMortality { Ok(>::block_hash(n)) } } + fn weight(&self) -> sp_weights::Weight { + ::check_mortality() + } +} +impl TransactionExtension + for CheckMortality +{ + type Pre = (); + type Val = (); - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) + fn validate( + &self, + origin: ::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, + _len: usize, + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult { + let current_u64 = >::block_number().saturated_into::(); + let valid_till = self.0.death(current_u64); + Ok(( + ValidTransaction { + longevity: valid_till.saturating_sub(current_u64), + ..Default::default() + }, + (), + origin, + )) } + impl_tx_ext_default!(T::RuntimeCall; Context; prepare); } #[cfg(test)] @@ -106,23 +112,21 @@ mod tests { weights::Weight, }; use sp_core::H256; + use sp_runtime::traits::DispatchTransaction; #[test] fn signed_ext_check_era_should_work() { new_test_ext().execute_with(|| { // future assert_eq!( - CheckMortality::::from(Era::mortal(4, 2)) - .additional_signed() - .err() - .unwrap(), + CheckMortality::::from(Era::mortal(4, 2)).implicit().err().unwrap(), InvalidTransaction::AncientBirthBlock.into(), ); // correct System::set_block_number(13); >::insert(12, H256::repeat_byte(1)); - assert!(CheckMortality::::from(Era::mortal(4, 12)).additional_signed().is_ok()); + assert!(CheckMortality::::from(Era::mortal(4, 12)).implicit().is_ok()); }) } @@ -142,7 +146,10 @@ mod tests { System::set_block_number(17); >::insert(16, H256::repeat_byte(1)); - assert_eq!(ext.validate(&1, CALL, &normal, len).unwrap().longevity, 15); + assert_eq!( + ext.validate_only(Some(1).into(), CALL, &normal, len).unwrap().0.longevity, + 15 + ); }) } } diff --git a/substrate/frame/system/src/extensions/check_non_zero_sender.rs b/substrate/frame/system/src/extensions/check_non_zero_sender.rs index 92eed60fc66..115ffac9b03 100644 --- a/substrate/frame/system/src/extensions/check_non_zero_sender.rs +++ b/substrate/frame/system/src/extensions/check_non_zero_sender.rs @@ -17,13 +17,14 @@ use crate::Config; use codec::{Decode, Encode}; -use frame_support::{dispatch::DispatchInfo, DefaultNoBound}; +use frame_support::{traits::OriginTrait, DefaultNoBound}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, SignedExtension}, - transaction_validity::{ - InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + impl_tx_ext_default, + traits::{ + transaction_extension::TransactionExtensionBase, DispatchInfoOf, TransactionExtension, }, + transaction_validity::InvalidTransaction, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -45,66 +46,82 @@ impl sp_std::fmt::Debug for CheckNonZeroSender { } impl CheckNonZeroSender { - /// Create new `SignedExtension` to check runtime version. + /// Create new `TransactionExtension` to check runtime version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl SignedExtension for CheckNonZeroSender -where - T::RuntimeCall: Dispatchable, -{ - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); - type Pre = (); +impl TransactionExtensionBase for CheckNonZeroSender { const IDENTIFIER: &'static str = "CheckNonZeroSender"; - - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) + type Implicit = (); + fn weight(&self) -> sp_weights::Weight { + ::check_non_zero_sender() } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) - } - +} +impl TransactionExtension + for CheckNonZeroSender +{ + type Val = (); + type Pre = (); fn validate( &self, - who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, _len: usize, - ) -> TransactionValidity { - if who.using_encoded(|d| d.iter().all(|x| *x == 0)) { - return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)) + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> sp_runtime::traits::ValidateResult { + if let Some(who) = origin.as_system_signer() { + if who.using_encoded(|d| d.iter().all(|x| *x == 0)) { + return Err(InvalidTransaction::BadSigner.into()) + } } - Ok(ValidTransaction::default()) + Ok((Default::default(), (), origin)) } + impl_tx_ext_default!(T::RuntimeCall; Context; prepare); } #[cfg(test)] mod tests { use super::*; use crate::mock::{new_test_ext, Test, CALL}; - use frame_support::{assert_noop, assert_ok}; + use frame_support::{assert_ok, dispatch::DispatchInfo}; + use sp_runtime::{traits::DispatchTransaction, TransactionValidityError}; #[test] fn zero_account_ban_works() { new_test_ext().execute_with(|| { let info = DispatchInfo::default(); let len = 0_usize; - assert_noop!( - CheckNonZeroSender::::new().validate(&0, CALL, &info, len), - InvalidTransaction::BadSigner + assert_eq!( + CheckNonZeroSender::::new() + .validate_only(Some(0).into(), CALL, &info, len) + .unwrap_err(), + TransactionValidityError::from(InvalidTransaction::BadSigner) ); - assert_ok!(CheckNonZeroSender::::new().validate(&1, CALL, &info, len)); + assert_ok!(CheckNonZeroSender::::new().validate_only( + Some(1).into(), + CALL, + &info, + len + )); + }) + } + + #[test] + fn unsigned_origin_works() { + new_test_ext().execute_with(|| { + let info = DispatchInfo::default(); + let len = 0_usize; + assert_ok!(CheckNonZeroSender::::new().validate_only( + None.into(), + CALL, + &info, + len + )); }) } } diff --git a/substrate/frame/system/src/extensions/check_nonce.rs b/substrate/frame/system/src/extensions/check_nonce.rs index 7504a814aef..ead9d9f7c81 100644 --- a/substrate/frame/system/src/extensions/check_nonce.rs +++ b/substrate/frame/system/src/extensions/check_nonce.rs @@ -15,16 +15,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::Config; +use crate::{AccountInfo, Config}; use codec::{Decode, Encode}; use frame_support::dispatch::DispatchInfo; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, One, SignedExtension, Zero}, + traits::{ + AsSystemOriginSigner, DispatchInfoOf, Dispatchable, One, TransactionExtension, + TransactionExtensionBase, ValidateResult, Zero, + }, transaction_validity::{ - InvalidTransaction, TransactionLongevity, TransactionValidity, TransactionValidityError, - ValidTransaction, + InvalidTransaction, TransactionLongevity, TransactionValidityError, ValidTransaction, }, + Saturating, }; use sp_std::vec; @@ -58,75 +61,78 @@ impl sp_std::fmt::Debug for CheckNonce { } } -impl SignedExtension for CheckNonce +impl TransactionExtensionBase for CheckNonce { + const IDENTIFIER: &'static str = "CheckNonce"; + type Implicit = (); + fn weight(&self) -> sp_weights::Weight { + ::check_nonce() + } +} +impl TransactionExtension for CheckNonce where T::RuntimeCall: Dispatchable, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, { - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); + type Val = Option<(T::AccountId, AccountInfo)>; type Pre = (); - const IDENTIFIER: &'static str = "CheckNonce"; - - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result<(), TransactionValidityError> { - let mut account = crate::Account::::get(who); - if account.providers.is_zero() && account.sufficients.is_zero() { - // Nonce storage not paid for - return Err(InvalidTransaction::Payment.into()) - } - if self.0 != account.nonce { - return Err(if self.0 < account.nonce { - InvalidTransaction::Stale - } else { - InvalidTransaction::Future - } - .into()) - } - account.nonce += T::Nonce::one(); - crate::Account::::insert(who, account); - Ok(()) - } fn validate( &self, - who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, _len: usize, - ) -> TransactionValidity { + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult { + let Some(who) = origin.as_system_origin_signer() else { + return Ok((Default::default(), None, origin)) + }; let account = crate::Account::::get(who); if account.providers.is_zero() && account.sufficients.is_zero() { // Nonce storage not paid for - return InvalidTransaction::Payment.into() + return Err(InvalidTransaction::Payment.into()) } if self.0 < account.nonce { - return InvalidTransaction::Stale.into() + return Err(InvalidTransaction::Stale.into()) } - let provides = vec![Encode::encode(&(who, self.0))]; + let provides = vec![Encode::encode(&(who.clone(), self.0))]; let requires = if account.nonce < self.0 { - vec![Encode::encode(&(who, self.0 - One::one()))] + vec![Encode::encode(&(who.clone(), self.0.saturating_sub(One::one())))] } else { vec![] }; - Ok(ValidTransaction { + let validity = ValidTransaction { priority: 0, requires, provides, longevity: TransactionLongevity::max_value(), propagate: true, - }) + }; + + Ok((validity, Some((who.clone(), account)), origin)) + } + + fn prepare( + self, + val: Self::Val, + _origin: &T::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, + _len: usize, + _context: &Context, + ) -> Result { + let Some((who, mut account)) = val else { return Ok(()) }; + // `self.0 < account.nonce` already checked in `validate`. + if self.0 > account.nonce { + return Err(InvalidTransaction::Future.into()) + } + account.nonce.saturating_inc(); + crate::Account::::insert(who, account); + Ok(()) } } @@ -134,7 +140,8 @@ where mod tests { use super::*; use crate::mock::{new_test_ext, Test, CALL}; - use frame_support::{assert_noop, assert_ok}; + use frame_support::assert_ok; + use sp_runtime::traits::DispatchTransaction; #[test] fn signed_ext_check_nonce_works() { @@ -152,22 +159,33 @@ mod tests { let info = DispatchInfo::default(); let len = 0_usize; // stale - assert_noop!( - CheckNonce::(0).validate(&1, CALL, &info, len), - InvalidTransaction::Stale + assert_eq!( + CheckNonce::(0) + .validate_only(Some(1).into(), CALL, &info, len,) + .unwrap_err(), + TransactionValidityError::Invalid(InvalidTransaction::Stale) ); - assert_noop!( - CheckNonce::(0).pre_dispatch(&1, CALL, &info, len), - InvalidTransaction::Stale + assert_eq!( + CheckNonce::(0) + .validate_and_prepare(Some(1).into(), CALL, &info, len) + .unwrap_err(), + InvalidTransaction::Stale.into() ); // correct - assert_ok!(CheckNonce::(1).validate(&1, CALL, &info, len)); - assert_ok!(CheckNonce::(1).pre_dispatch(&1, CALL, &info, len)); + assert_ok!(CheckNonce::(1).validate_only(Some(1).into(), CALL, &info, len)); + assert_ok!(CheckNonce::(1).validate_and_prepare( + Some(1).into(), + CALL, + &info, + len + )); // future - assert_ok!(CheckNonce::(5).validate(&1, CALL, &info, len)); - assert_noop!( - CheckNonce::(5).pre_dispatch(&1, CALL, &info, len), - InvalidTransaction::Future + assert_ok!(CheckNonce::(5).validate_only(Some(1).into(), CALL, &info, len)); + assert_eq!( + CheckNonce::(5) + .validate_and_prepare(Some(1).into(), CALL, &info, len) + .unwrap_err(), + InvalidTransaction::Future.into() ); }) } @@ -198,20 +216,44 @@ mod tests { let info = DispatchInfo::default(); let len = 0_usize; // Both providers and sufficients zero - assert_noop!( - CheckNonce::(1).validate(&1, CALL, &info, len), - InvalidTransaction::Payment + assert_eq!( + CheckNonce::(1) + .validate_only(Some(1).into(), CALL, &info, len) + .unwrap_err(), + TransactionValidityError::Invalid(InvalidTransaction::Payment) ); - assert_noop!( - CheckNonce::(1).pre_dispatch(&1, CALL, &info, len), - InvalidTransaction::Payment + assert_eq!( + CheckNonce::(1) + .validate_and_prepare(Some(1).into(), CALL, &info, len) + .unwrap_err(), + TransactionValidityError::Invalid(InvalidTransaction::Payment) ); // Non-zero providers - assert_ok!(CheckNonce::(1).validate(&2, CALL, &info, len)); - assert_ok!(CheckNonce::(1).pre_dispatch(&2, CALL, &info, len)); + assert_ok!(CheckNonce::(1).validate_only(Some(2).into(), CALL, &info, len)); + assert_ok!(CheckNonce::(1).validate_and_prepare( + Some(2).into(), + CALL, + &info, + len + )); // Non-zero sufficients - assert_ok!(CheckNonce::(1).validate(&3, CALL, &info, len)); - assert_ok!(CheckNonce::(1).pre_dispatch(&3, CALL, &info, len)); + assert_ok!(CheckNonce::(1).validate_only(Some(3).into(), CALL, &info, len)); + assert_ok!(CheckNonce::(1).validate_and_prepare( + Some(3).into(), + CALL, + &info, + len + )); + }) + } + + #[test] + fn unsigned_check_nonce_works() { + new_test_ext().execute_with(|| { + let info = DispatchInfo::default(); + let len = 0_usize; + assert_ok!(CheckNonce::(1).validate_only(None.into(), CALL, &info, len)); + assert_ok!(CheckNonce::(1).validate_and_prepare(None.into(), CALL, &info, len)); }) } } diff --git a/substrate/frame/system/src/extensions/check_spec_version.rs b/substrate/frame/system/src/extensions/check_spec_version.rs index 24d5ef9cafb..3109708f48e 100644 --- a/substrate/frame/system/src/extensions/check_spec_version.rs +++ b/substrate/frame/system/src/extensions/check_spec_version.rs @@ -19,7 +19,8 @@ use crate::{Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, SignedExtension}, + impl_tx_ext_default, + traits::{transaction_extension::TransactionExtensionBase, TransactionExtension}, transaction_validity::TransactionValidityError, }; @@ -46,30 +47,26 @@ impl sp_std::fmt::Debug for CheckSpecVersion { } impl CheckSpecVersion { - /// Create new `SignedExtension` to check runtime version. + /// Create new `TransactionExtension` to check runtime version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl SignedExtension for CheckSpecVersion { - type AccountId = T::AccountId; - type Call = ::RuntimeCall; - type AdditionalSigned = u32; - type Pre = (); +impl TransactionExtensionBase for CheckSpecVersion { const IDENTIFIER: &'static str = "CheckSpecVersion"; - - fn additional_signed(&self) -> Result { + type Implicit = u32; + fn implicit(&self) -> Result { Ok(>::runtime_version().spec_version) } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) + fn weight(&self) -> sp_weights::Weight { + ::check_spec_version() } } +impl TransactionExtension<::RuntimeCall, Context> + for CheckSpecVersion +{ + type Val = (); + type Pre = (); + impl_tx_ext_default!(::RuntimeCall; Context; validate prepare); +} diff --git a/substrate/frame/system/src/extensions/check_tx_version.rs b/substrate/frame/system/src/extensions/check_tx_version.rs index 3f9d6a1903f..ee1d507e7bc 100644 --- a/substrate/frame/system/src/extensions/check_tx_version.rs +++ b/substrate/frame/system/src/extensions/check_tx_version.rs @@ -19,7 +19,8 @@ use crate::{Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, SignedExtension}, + impl_tx_ext_default, + traits::{transaction_extension::TransactionExtensionBase, TransactionExtension}, transaction_validity::TransactionValidityError, }; @@ -46,29 +47,26 @@ impl sp_std::fmt::Debug for CheckTxVersion { } impl CheckTxVersion { - /// Create new `SignedExtension` to check transaction version. + /// Create new `TransactionExtension` to check transaction version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl SignedExtension for CheckTxVersion { - type AccountId = T::AccountId; - type Call = ::RuntimeCall; - type AdditionalSigned = u32; - type Pre = (); +impl TransactionExtensionBase for CheckTxVersion { const IDENTIFIER: &'static str = "CheckTxVersion"; - - fn additional_signed(&self) -> Result { + type Implicit = u32; + fn implicit(&self) -> Result { Ok(>::runtime_version().transaction_version) } - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) + fn weight(&self) -> sp_weights::Weight { + ::check_tx_version() } } +impl TransactionExtension<::RuntimeCall, Context> + for CheckTxVersion +{ + type Val = (); + type Pre = (); + impl_tx_ext_default!(::RuntimeCall; Context; validate prepare); +} diff --git a/substrate/frame/system/src/extensions/check_weight.rs b/substrate/frame/system/src/extensions/check_weight.rs index 70d1e756332..5c35acfb3f3 100644 --- a/substrate/frame/system/src/extensions/check_weight.rs +++ b/substrate/frame/system/src/extensions/check_weight.rs @@ -23,9 +23,12 @@ use frame_support::{ }; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, - transaction_validity::{InvalidTransaction, TransactionValidity, TransactionValidityError}, - DispatchResult, + traits::{ + DispatchInfoOf, Dispatchable, PostDispatchInfoOf, TransactionExtension, + TransactionExtensionBase, ValidateResult, + }, + transaction_validity::{InvalidTransaction, TransactionValidityError}, + DispatchResult, ValidTransaction, }; use sp_weights::Weight; @@ -100,39 +103,43 @@ where } } - /// Creates new `SignedExtension` to check weight of the extrinsic. + /// Creates new `TransactionExtension` to check weight of the extrinsic. pub fn new() -> Self { Self(Default::default()) } - /// Do the pre-dispatch checks. This can be applied to both signed and unsigned. + /// Do the validate checks. This can be applied to both signed and unsigned. /// - /// It checks and notes the new weight and length. - pub fn do_pre_dispatch( + /// It only checks that the block weight and length limit will not exceed. + /// + /// Returns the transaction validity and the next block length, to be used in `prepare`. + pub fn do_validate( info: &DispatchInfoOf, len: usize, - ) -> Result<(), TransactionValidityError> { + ) -> Result<(ValidTransaction, u32), TransactionValidityError> { + // ignore the next length. If they return `Ok`, then it is below the limit. let next_len = Self::check_block_length(info, len)?; - let next_weight = Self::check_block_weight(info)?; + // during validation we skip block limit check. Since the `validate_transaction` + // call runs on an empty block anyway, by this we prevent `on_initialize` weight + // consumption from causing false negatives. Self::check_extrinsic_weight(info)?; - crate::AllExtrinsicsLen::::put(next_len); - crate::BlockWeight::::put(next_weight); - Ok(()) + Ok((Default::default(), next_len)) } - /// Do the validate checks. This can be applied to both signed and unsigned. + /// Do the pre-dispatch checks. This can be applied to both signed and unsigned. /// - /// It only checks that the block weight and length limit will not exceed. - pub fn do_validate(info: &DispatchInfoOf, len: usize) -> TransactionValidity { - // ignore the next length. If they return `Ok`, then it is below the limit. - let _ = Self::check_block_length(info, len)?; - // during validation we skip block limit check. Since the `validate_transaction` - // call runs on an empty block anyway, by this we prevent `on_initialize` weight - // consumption from causing false negatives. - Self::check_extrinsic_weight(info)?; + /// It checks and notes the new weight and length. + pub fn do_prepare( + info: &DispatchInfoOf, + next_len: u32, + ) -> Result<(), TransactionValidityError> { + let next_weight = Self::check_block_weight(info)?; + // Extrinsic weight already checked in `validate`. - Ok(Default::default()) + crate::AllExtrinsicsLen::::put(next_len); + crate::BlockWeight::::put(next_weight); + Ok(()) } } @@ -201,62 +208,55 @@ where Ok(all_weight) } -impl SignedExtension for CheckWeight +impl TransactionExtensionBase for CheckWeight { + const IDENTIFIER: &'static str = "CheckWeight"; + type Implicit = (); + + fn weight(&self) -> Weight { + ::check_weight() + } +} +impl TransactionExtension + for CheckWeight where T::RuntimeCall: Dispatchable, { - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); type Pre = (); - const IDENTIFIER: &'static str = "CheckWeight"; - - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } - - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result<(), TransactionValidityError> { - Self::do_pre_dispatch(info, len) - } + type Val = u32; /* next block length */ fn validate( &self, - _who: &Self::AccountId, - _call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> TransactionValidity { - Self::do_validate(info, len) - } - - fn pre_dispatch_unsigned( - _call: &Self::Call, - info: &DispatchInfoOf, + origin: T::RuntimeOrigin, + _call: &T::RuntimeCall, + info: &DispatchInfoOf, len: usize, - ) -> Result<(), TransactionValidityError> { - Self::do_pre_dispatch(info, len) + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult { + let (validity, next_len) = Self::do_validate(info, len)?; + Ok((validity, next_len, origin)) } - fn validate_unsigned( - _call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> TransactionValidity { - Self::do_validate(info, len) + fn prepare( + self, + val: Self::Val, + _origin: &T::RuntimeOrigin, + _call: &T::RuntimeCall, + info: &DispatchInfoOf, + _len: usize, + _context: &Context, + ) -> Result { + Self::do_prepare(info, val) } fn post_dispatch( - _pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + _pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, _len: usize, _result: &DispatchResult, + _context: &Context, ) -> Result<(), TransactionValidityError> { let unspent = post_info.calc_unspent(info); if unspent.any_gt(Weight::zero()) { @@ -301,6 +301,7 @@ mod tests { AllExtrinsicsLen, BlockWeight, DispatchClass, }; use frame_support::{assert_err, assert_ok, dispatch::Pays, weights::Weight}; + use sp_runtime::traits::DispatchTransaction; use sp_std::marker::PhantomData; fn block_weights() -> crate::limits::BlockWeights { @@ -338,7 +339,8 @@ mod tests { } check(|max, len| { - assert_ok!(CheckWeight::::do_pre_dispatch(max, len)); + let next_len = CheckWeight::::check_block_length(max, len).unwrap(); + assert_ok!(CheckWeight::::do_prepare(max, next_len)); assert_eq!(System::block_weight().total(), Weight::MAX); assert!(System::block_weight().total().ref_time() > block_weight_limit().ref_time()); }); @@ -419,9 +421,11 @@ mod tests { let len = 0_usize; - assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); + let next_len = CheckWeight::::check_block_length(&max_normal, len).unwrap(); + assert_ok!(CheckWeight::::do_prepare(&max_normal, next_len)); assert_eq!(System::block_weight().total(), Weight::from_parts(768, 0)); - assert_ok!(CheckWeight::::do_pre_dispatch(&rest_operational, len)); + let next_len = CheckWeight::::check_block_length(&rest_operational, len).unwrap(); + assert_ok!(CheckWeight::::do_prepare(&rest_operational, next_len)); assert_eq!(block_weight_limit(), Weight::from_parts(1024, u64::MAX)); assert_eq!(System::block_weight().total(), block_weight_limit().set_proof_size(0)); // Checking single extrinsic should not take current block weight into account. @@ -443,10 +447,12 @@ mod tests { let len = 0_usize; - assert_ok!(CheckWeight::::do_pre_dispatch(&rest_operational, len)); + let next_len = CheckWeight::::check_block_length(&rest_operational, len).unwrap(); + assert_ok!(CheckWeight::::do_prepare(&rest_operational, next_len)); // Extra 20 here from block execution + base extrinsic weight assert_eq!(System::block_weight().total(), Weight::from_parts(266, 0)); - assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); + let next_len = CheckWeight::::check_block_length(&max_normal, len).unwrap(); + assert_ok!(CheckWeight::::do_prepare(&max_normal, next_len)); assert_eq!(block_weight_limit(), Weight::from_parts(1024, u64::MAX)); assert_eq!(System::block_weight().total(), block_weight_limit().set_proof_size(0)); }); @@ -469,16 +475,19 @@ mod tests { }; let len = 0_usize; + let next_len = CheckWeight::::check_block_length(&dispatch_normal, len).unwrap(); assert_err!( - CheckWeight::::do_pre_dispatch(&dispatch_normal, len), + CheckWeight::::do_prepare(&dispatch_normal, next_len), InvalidTransaction::ExhaustsResources ); + let next_len = + CheckWeight::::check_block_length(&dispatch_operational, len).unwrap(); // Thank goodness we can still do an operational transaction to possibly save the // blockchain. - assert_ok!(CheckWeight::::do_pre_dispatch(&dispatch_operational, len)); + assert_ok!(CheckWeight::::do_prepare(&dispatch_operational, next_len)); // Not too much though assert_err!( - CheckWeight::::do_pre_dispatch(&dispatch_operational, len), + CheckWeight::::do_prepare(&dispatch_operational, next_len), InvalidTransaction::ExhaustsResources ); // Even with full block, validity of single transaction should be correct. @@ -503,21 +512,35 @@ mod tests { current_weight.set(normal_limit, DispatchClass::Normal) }); // will not fit. - assert_err!( - CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &normal, len), - InvalidTransaction::ExhaustsResources + assert_eq!( + CheckWeight::(PhantomData) + .validate_and_prepare(Some(1).into(), CALL, &normal, len) + .unwrap_err(), + InvalidTransaction::ExhaustsResources.into() ); // will fit. - assert_ok!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &op, len)); + assert_ok!(CheckWeight::(PhantomData).validate_and_prepare( + Some(1).into(), + CALL, + &op, + len + )); // likewise for length limit. let len = 100_usize; AllExtrinsicsLen::::put(normal_length_limit()); - assert_err!( - CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &normal, len), - InvalidTransaction::ExhaustsResources + assert_eq!( + CheckWeight::(PhantomData) + .validate_and_prepare(Some(1).into(), CALL, &normal, len) + .unwrap_err(), + InvalidTransaction::ExhaustsResources.into() ); - assert_ok!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &op, len)); + assert_ok!(CheckWeight::(PhantomData).validate_and_prepare( + Some(1).into(), + CALL, + &op, + len + )); }) } @@ -528,7 +551,12 @@ mod tests { let normal_limit = normal_weight_limit().ref_time() as usize; let reset_check_weight = |tx, s, f| { AllExtrinsicsLen::::put(0); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, tx, s); + let r = CheckWeight::(PhantomData).validate_and_prepare( + Some(1).into(), + CALL, + tx, + s, + ); if f { assert!(r.is_err()) } else { @@ -571,7 +599,12 @@ mod tests { BlockWeight::::mutate(|current_weight| { current_weight.set(s, DispatchClass::Normal) }); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, i, len); + let r = CheckWeight::(PhantomData).validate_and_prepare( + Some(1).into(), + CALL, + i, + len, + ); if f { assert!(r.is_err()) } else { @@ -604,18 +637,22 @@ mod tests { .set(Weight::from_parts(256, 0) - base_extrinsic, DispatchClass::Normal); }); - let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); + let pre = CheckWeight::(PhantomData) + .validate_and_prepare(Some(1).into(), CALL, &info, len) + .unwrap() + .0; assert_eq!( BlockWeight::::get().total(), info.weight + Weight::from_parts(256, 0) ); assert_ok!(CheckWeight::::post_dispatch( - Some(pre), + pre, &info, &post_info, len, - &Ok(()) + &Ok(()), + &() )); assert_eq!( BlockWeight::::get().total(), @@ -639,7 +676,10 @@ mod tests { current_weight.set(Weight::from_parts(128, 0), DispatchClass::Normal); }); - let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); + let pre = CheckWeight::(PhantomData) + .validate_and_prepare(Some(1).into(), CALL, &info, len) + .unwrap() + .0; assert_eq!( BlockWeight::::get().total(), info.weight + @@ -648,11 +688,12 @@ mod tests { ); assert_ok!(CheckWeight::::post_dispatch( - Some(pre), + pre, &info, &post_info, len, - &Ok(()) + &Ok(()), + &() )); assert_eq!( BlockWeight::::get().total(), @@ -672,7 +713,12 @@ mod tests { // Initial weight from `weights.base_block` assert_eq!(System::block_weight().total(), weights.base_block); - assert_ok!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &free, len)); + assert_ok!(CheckWeight::(PhantomData).validate_and_prepare( + Some(1).into(), + CALL, + &free, + len + )); assert_eq!( System::block_weight().total(), weights.get(DispatchClass::Normal).base_extrinsic + weights.base_block @@ -696,9 +742,11 @@ mod tests { let len = 0_usize; - assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); + let next_len = CheckWeight::::check_block_length(&max_normal, len).unwrap(); + assert_ok!(CheckWeight::::do_prepare(&max_normal, next_len)); assert_eq!(System::block_weight().total(), Weight::from_parts(768, 0)); - assert_ok!(CheckWeight::::do_pre_dispatch(&mandatory, len)); + let next_len = CheckWeight::::check_block_length(&mandatory, len).unwrap(); + assert_ok!(CheckWeight::::do_prepare(&mandatory, next_len)); assert_eq!(block_weight_limit(), Weight::from_parts(1024, u64::MAX)); assert_eq!(System::block_weight().total(), Weight::from_parts(1024 + 768, 0)); assert_eq!(CheckWeight::::check_extrinsic_weight(&mandatory), Ok(())); diff --git a/substrate/frame/system/src/extensions/mod.rs b/substrate/frame/system/src/extensions/mod.rs index a88c9fbf96e..d79104d2240 100644 --- a/substrate/frame/system/src/extensions/mod.rs +++ b/substrate/frame/system/src/extensions/mod.rs @@ -22,3 +22,6 @@ pub mod check_nonce; pub mod check_spec_version; pub mod check_tx_version; pub mod check_weight; +pub mod weights; + +pub use weights::WeightInfo; diff --git a/substrate/frame/system/src/extensions/weights.rs b/substrate/frame/system/src/extensions/weights.rs new file mode 100644 index 00000000000..0d2fcb15ee6 --- /dev/null +++ b/substrate/frame/system/src/extensions/weights.rs @@ -0,0 +1,196 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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 `frame_system_extensions` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/production/substrate-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=frame_system_extensions +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./substrate/frame/system/src/extensions/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `frame_system_extensions`. +pub trait WeightInfo { + fn check_genesis() -> Weight; + fn check_mortality() -> Weight; + fn check_non_zero_sender() -> Weight; + fn check_nonce() -> Weight; + fn check_spec_version() -> Weight; + fn check_tx_version() -> Weight; + fn check_weight() -> Weight; +} + +/// Weights for `frame_system_extensions` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_876_000 picoseconds. + Weight::from_parts(4_160_000, 3509) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 6_296_000 picoseconds. + Weight::from_parts(6_523_000, 3509) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 449_000 picoseconds. + Weight::from_parts(527_000, 0) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `101` + // Estimated: `3593` + // Minimum execution time: 5_689_000 picoseconds. + Weight::from_parts(6_000_000, 3593) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 399_000 picoseconds. + Weight::from_parts(461_000, 0) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 390_000 picoseconds. + Weight::from_parts(439_000, 0) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1489` + // Minimum execution time: 4_375_000 picoseconds. + Weight::from_parts(4_747_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_genesis() -> Weight { + // Proof Size summary in bytes: + // Measured: `54` + // Estimated: `3509` + // Minimum execution time: 3_876_000 picoseconds. + Weight::from_parts(4_160_000, 3509) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `System::BlockHash` (r:1 w:0) + /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + fn check_mortality() -> Weight { + // Proof Size summary in bytes: + // Measured: `92` + // Estimated: `3509` + // Minimum execution time: 6_296_000 picoseconds. + Weight::from_parts(6_523_000, 3509) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + fn check_non_zero_sender() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 449_000 picoseconds. + Weight::from_parts(527_000, 0) + } + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn check_nonce() -> Weight { + // Proof Size summary in bytes: + // Measured: `101` + // Estimated: `3593` + // Minimum execution time: 5_689_000 picoseconds. + Weight::from_parts(6_000_000, 3593) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + fn check_spec_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 399_000 picoseconds. + Weight::from_parts(461_000, 0) + } + fn check_tx_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 390_000 picoseconds. + Weight::from_parts(439_000, 0) + } + /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) + /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn check_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `24` + // Estimated: `1489` + // Minimum execution time: 4_375_000 picoseconds. + Weight::from_parts(4_747_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } +} diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 3b659916379..21393cb3e20 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -166,7 +166,7 @@ pub use extensions::{ check_genesis::CheckGenesis, check_mortality::CheckMortality, check_non_zero_sender::CheckNonZeroSender, check_nonce::CheckNonce, check_spec_version::CheckSpecVersion, check_tx_version::CheckTxVersion, - check_weight::CheckWeight, + check_weight::CheckWeight, WeightInfo as ExtensionsWeightInfo, }; // Backward compatible re-export. pub use extensions::check_mortality::CheckMortality as CheckEra; @@ -284,6 +284,7 @@ pub mod pallet { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); + type ExtensionsWeightInfo = (); type SS58Prefix = (); type Version = (); type BlockWeights = (); @@ -356,6 +357,9 @@ pub mod pallet { /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); + /// Weight information for the extensions of this pallet. + type ExtensionsWeightInfo = (); + /// This is used as an identifier of the chain. type SS58Prefix = (); @@ -563,8 +567,12 @@ pub mod pallet { /// All resources should be cleaned up associated with the given account. type OnKilledAccount: OnKilledAccount; + /// Weight information for the extrinsics of this pallet. type SystemWeightInfo: WeightInfo; + /// Weight information for the transaction extensions of this pallet. + type ExtensionsWeightInfo: extensions::WeightInfo; + /// The designated SS58 prefix of this chain. /// /// This replaces the "ss58Format" property declared in the chain spec. Reason is diff --git a/substrate/frame/system/src/offchain.rs b/substrate/frame/system/src/offchain.rs index a019cfd666e..ee73e33fe31 100644 --- a/substrate/frame/system/src/offchain.rs +++ b/substrate/frame/system/src/offchain.rs @@ -79,6 +79,9 @@ pub struct SubmitTransaction, Overarchi _phantom: sp_std::marker::PhantomData<(T, OverarchingCall)>, } +// TODO [#2415]: Avoid splitting call and the totally opaque `signature`; `CreateTransaction` trait +// should provide something which impls `Encode`, which can be sent onwards to +// `sp_io::offchain::submit_transaction`. There's no great need to split things up as in here. impl SubmitTransaction where T: SendTransactionTypes, @@ -88,6 +91,8 @@ where call: >::OverarchingCall, signature: Option<::SignaturePayload>, ) -> Result<(), ()> { + // TODO: Use regular transaction API instead. + #[allow(deprecated)] let xt = T::Extrinsic::new(call, signature).ok_or(())?; sp_io::offchain::submit_transaction(xt.encode()) } @@ -471,7 +476,7 @@ pub trait SendTransactionTypes { /// /// This trait is meant to be implemented by the runtime and is responsible for constructing /// a payload to be signed and contained within the extrinsic. -/// This will most likely include creation of `SignedExtra` (a set of `SignedExtensions`). +/// This will most likely include creation of `TxExtension` (a tuple of `TransactionExtension`s). /// Note that the result can be altered by inspecting the `Call` (for instance adjusting /// fees, or mortality depending on the `pallet` being called). pub trait CreateSignedTransaction: @@ -621,14 +626,17 @@ mod tests { use crate::mock::{RuntimeCall, Test as TestRuntime, CALL}; use codec::Decode; use sp_core::offchain::{testing, TransactionPoolExt}; - use sp_runtime::testing::{TestSignature, TestXt, UintAuthorityId}; + use sp_runtime::{ + generic::UncheckedExtrinsic, + testing::{TestSignature, UintAuthorityId}, + }; impl SigningTypes for TestRuntime { type Public = UintAuthorityId; type Signature = TestSignature; } - type Extrinsic = TestXt; + type Extrinsic = UncheckedExtrinsic; impl SendTransactionTypes for TestRuntime { type Extrinsic = Extrinsic; @@ -693,7 +701,7 @@ mod tests { let _tx3 = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); - assert_eq!(tx1.signature, None); + assert!(tx1.is_inherent()); }); } @@ -724,7 +732,7 @@ mod tests { let tx1 = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); - assert_eq!(tx1.signature, None); + assert!(tx1.is_inherent()); }); } @@ -758,7 +766,7 @@ mod tests { let _tx2 = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); - assert_eq!(tx1.signature, None); + assert!(tx1.is_inherent()); }); } @@ -790,7 +798,7 @@ mod tests { let tx1 = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); - assert_eq!(tx1.signature, None); + assert!(tx1.is_inherent()); }); } } diff --git a/substrate/frame/system/src/weights.rs b/substrate/frame/system/src/weights.rs index 41807dea1c5..bd64bbf3763 100644 --- a/substrate/frame/system/src/weights.rs +++ b/substrate/frame/system/src/weights.rs @@ -15,30 +15,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for frame_system +//! Autogenerated weights for `frame_system` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-s7kdgajz-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=frame_system +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json -// --pallet=frame-system -// --chain=dev -// --header=./HEADER-APACHE2 -// --output=./frame/system/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/system/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -48,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for frame_system. +/// Weight functions needed for `frame_system`. pub trait WeightInfo { fn remark(b: u32, ) -> Weight; fn remark_with_event(b: u32, ) -> Weight; @@ -61,7 +62,7 @@ pub trait WeightInfo { fn apply_authorized_upgrade() -> Weight; } -/// Weights for frame_system using the Substrate node and recommended hardware. +/// Weights for `frame_system` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// The range of component `b` is `[0, 3932160]`. @@ -69,84 +70,86 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_004_000 picoseconds. - Weight::from_parts(2_119_000, 0) + // Minimum execution time: 2_130_000 picoseconds. + Weight::from_parts(2_976_430, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(390, 0).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(386, 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: 8_032_000 picoseconds. - Weight::from_parts(8_097_000, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_455, 0).saturating_mul(b.into())) + // Minimum execution time: 5_690_000 picoseconds. + Weight::from_parts(15_071_416, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_387, 0).saturating_mul(b.into())) } - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a686561707061676573` (r:0 w:1) - /// Proof Skipped: unknown `0x3a686561707061676573` (r:0 w:1) + /// Storage: `System::Digest` (r:1 w:1) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) fn set_heap_pages() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 4_446_000 picoseconds. - Weight::from_parts(4_782_000, 1485) + // Minimum execution time: 3_822_000 picoseconds. + Weight::from_parts(4_099_000, 1485) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a636f6465` (r:0 w:1) - /// Proof Skipped: unknown `0x3a636f6465` (r:0 w:1) + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:1) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `1485` - // Minimum execution time: 84_000_503_000 picoseconds. - Weight::from_parts(87_586_619_000, 1485) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Measured: `142` + // Estimated: `67035` + // Minimum execution time: 81_512_045_000 picoseconds. + Weight::from_parts(82_321_281_000, 67035) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_086_000 picoseconds. - Weight::from_parts(2_175_000, 0) - // Standard Error: 1_056 - .saturating_add(Weight::from_parts(841_511, 0).saturating_mul(i.into())) + // Minimum execution time: 2_074_000 picoseconds. + Weight::from_parts(2_137_000, 0) + // Standard Error: 879 + .saturating_add(Weight::from_parts(797_224, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_000_000 picoseconds. - Weight::from_parts(2_255_000, 0) - // Standard Error: 1_425 - .saturating_add(Weight::from_parts(662_473, 0).saturating_mul(i.into())) + // Minimum execution time: 2_122_000 picoseconds. + Weight::from_parts(2_208_000, 0) + // Standard Error: 855 + .saturating_add(Weight::from_parts(594_034, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `115 + p * (69 ±0)` - // Estimated: `128 + p * (70 ±0)` - // Minimum execution time: 4_189_000 picoseconds. - Weight::from_parts(4_270_000, 128) - // Standard Error: 2_296 - .saturating_add(Weight::from_parts(1_389_650, 0).saturating_mul(p.into())) + // Measured: `129 + p * (69 ±0)` + // Estimated: `135 + p * (70 ±0)` + // Minimum execution time: 3_992_000 picoseconds. + Weight::from_parts(4_170_000, 135) + // Standard Error: 1_377 + .saturating_add(Weight::from_parts(1_267_892, 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())) @@ -157,114 +160,116 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 33_027_000 picoseconds. - Weight::from_parts(33_027_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) + // Minimum execution time: 8_872_000 picoseconds. + Weight::from_parts(9_513_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `System::AuthorizedUpgrade` (r:1 w:1) /// Proof: `System::AuthorizedUpgrade` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) /// Storage: `System::Digest` (r:1 w:1) /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) fn apply_authorized_upgrade() -> Weight { // Proof Size summary in bytes: - // Measured: `22` - // Estimated: `1518` - // Minimum execution time: 118_101_992_000 picoseconds. - Weight::from_parts(118_101_992_000, 0) - .saturating_add(Weight::from_parts(0, 1518)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `164` + // Estimated: `67035` + // Minimum execution time: 85_037_546_000 picoseconds. + Weight::from_parts(85_819_414_000, 67035) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { /// The range of component `b` is `[0, 3932160]`. fn remark(b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_004_000 picoseconds. - Weight::from_parts(2_119_000, 0) + // Minimum execution time: 2_130_000 picoseconds. + Weight::from_parts(2_976_430, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(390, 0).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(386, 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: 8_032_000 picoseconds. - Weight::from_parts(8_097_000, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_455, 0).saturating_mul(b.into())) + // Minimum execution time: 5_690_000 picoseconds. + Weight::from_parts(15_071_416, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_387, 0).saturating_mul(b.into())) } - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a686561707061676573` (r:0 w:1) - /// Proof Skipped: unknown `0x3a686561707061676573` (r:0 w:1) + /// Storage: `System::Digest` (r:1 w:1) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) fn set_heap_pages() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 4_446_000 picoseconds. - Weight::from_parts(4_782_000, 1485) + // Minimum execution time: 3_822_000 picoseconds. + Weight::from_parts(4_099_000, 1485) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: unknown `0x3a636f6465` (r:0 w:1) - /// Proof Skipped: unknown `0x3a636f6465` (r:0 w:1) + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:1) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) + /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `1485` - // Minimum execution time: 84_000_503_000 picoseconds. - Weight::from_parts(87_586_619_000, 1485) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Measured: `142` + // Estimated: `67035` + // Minimum execution time: 81_512_045_000 picoseconds. + Weight::from_parts(82_321_281_000, 67035) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_086_000 picoseconds. - Weight::from_parts(2_175_000, 0) - // Standard Error: 1_056 - .saturating_add(Weight::from_parts(841_511, 0).saturating_mul(i.into())) + // Minimum execution time: 2_074_000 picoseconds. + Weight::from_parts(2_137_000, 0) + // Standard Error: 879 + .saturating_add(Weight::from_parts(797_224, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_000_000 picoseconds. - Weight::from_parts(2_255_000, 0) - // Standard Error: 1_425 - .saturating_add(Weight::from_parts(662_473, 0).saturating_mul(i.into())) + // Minimum execution time: 2_122_000 picoseconds. + Weight::from_parts(2_208_000, 0) + // Standard Error: 855 + .saturating_add(Weight::from_parts(594_034, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: Skipped Metadata (r:0 w:0) - /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `115 + p * (69 ±0)` - // Estimated: `128 + p * (70 ±0)` - // Minimum execution time: 4_189_000 picoseconds. - Weight::from_parts(4_270_000, 128) - // Standard Error: 2_296 - .saturating_add(Weight::from_parts(1_389_650, 0).saturating_mul(p.into())) + // Measured: `129 + p * (69 ±0)` + // Estimated: `135 + p * (70 ±0)` + // Minimum execution time: 3_992_000 picoseconds. + Weight::from_parts(4_170_000, 135) + // Standard Error: 1_377 + .saturating_add(Weight::from_parts(1_267_892, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 70).saturating_mul(p.into())) @@ -275,25 +280,25 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 33_027_000 picoseconds. - Weight::from_parts(33_027_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(RocksDbWeight::get().writes(1)) + // Minimum execution time: 8_872_000 picoseconds. + Weight::from_parts(9_513_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `System::AuthorizedUpgrade` (r:1 w:1) /// Proof: `System::AuthorizedUpgrade` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) /// Storage: `System::Digest` (r:1 w:1) /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) fn apply_authorized_upgrade() -> Weight { // Proof Size summary in bytes: - // Measured: `22` - // Estimated: `1518` - // Minimum execution time: 118_101_992_000 picoseconds. - Weight::from_parts(118_101_992_000, 0) - .saturating_add(Weight::from_parts(0, 1518)) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(3)) + // Measured: `164` + // Estimated: `67035` + // Minimum execution time: 85_037_546_000 picoseconds. + Weight::from_parts(85_819_414_000, 67035) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } } diff --git a/substrate/frame/timestamp/src/weights.rs b/substrate/frame/timestamp/src/weights.rs index 46c54473486..2df68ba0f1e 100644 --- a/substrate/frame/timestamp/src/weights.rs +++ b/substrate/frame/timestamp/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_timestamp +//! Autogenerated weights for `pallet_timestamp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/timestamp/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/timestamp/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,57 +49,57 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_timestamp. +/// Weight functions needed for `pallet_timestamp`. pub trait WeightInfo { fn set() -> Weight; fn on_finalize() -> Weight; } -/// Weights for pallet_timestamp using the Substrate node and recommended hardware. +/// Weights for `pallet_timestamp` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Timestamp Now (r:1 w:1) - /// Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Babe CurrentSlot (r:1 w:0) - /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Timestamp::Now` (r:1 w:1) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Babe::CurrentSlot` (r:1 w:0) + /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn set() -> Weight { // Proof Size summary in bytes: - // Measured: `312` + // Measured: `345` // Estimated: `1493` - // Minimum execution time: 9_857_000 picoseconds. - Weight::from_parts(10_492_000, 1493) + // Minimum execution time: 8_417_000 picoseconds. + Weight::from_parts(8_932_000, 1493) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn on_finalize() -> Weight { // Proof Size summary in bytes: - // Measured: `161` + // Measured: `194` // Estimated: `0` - // Minimum execution time: 4_175_000 picoseconds. - Weight::from_parts(4_334_000, 0) + // Minimum execution time: 3_911_000 picoseconds. + Weight::from_parts(4_092_000, 0) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Timestamp Now (r:1 w:1) - /// Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: Babe CurrentSlot (r:1 w:0) - /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `Timestamp::Now` (r:1 w:1) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Babe::CurrentSlot` (r:1 w:0) + /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn set() -> Weight { // Proof Size summary in bytes: - // Measured: `312` + // Measured: `345` // Estimated: `1493` - // Minimum execution time: 9_857_000 picoseconds. - Weight::from_parts(10_492_000, 1493) + // Minimum execution time: 8_417_000 picoseconds. + Weight::from_parts(8_932_000, 1493) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn on_finalize() -> Weight { // Proof Size summary in bytes: - // Measured: `161` + // Measured: `194` // Estimated: `0` - // Minimum execution time: 4_175_000 picoseconds. - Weight::from_parts(4_334_000, 0) + // Minimum execution time: 3_911_000 picoseconds. + Weight::from_parts(4_092_000, 0) } } diff --git a/substrate/frame/tips/src/weights.rs b/substrate/frame/tips/src/weights.rs index ec622866715..dbe1ed246ff 100644 --- a/substrate/frame/tips/src/weights.rs +++ b/substrate/frame/tips/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_tips +//! Autogenerated weights for `pallet_tips` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/tips/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/tips/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_tips. +/// Weight functions needed for `pallet_tips`. pub trait WeightInfo { fn report_awesome(r: u32, ) -> Weight; fn retract_tip() -> Weight; @@ -60,220 +59,220 @@ pub trait WeightInfo { fn slash_tip(t: u32, ) -> Weight; } -/// Weights for pallet_tips using the Substrate node and recommended hardware. +/// Weights for `pallet_tips` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Tips Reasons (r:1 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: `Tips::Reasons` (r:1 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `r` is `[0, 300]`. fn report_awesome(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `3469` - // Minimum execution time: 29_576_000 picoseconds. - Weight::from_parts(30_722_650, 3469) - // Standard Error: 192 - .saturating_add(Weight::from_parts(2_601, 0).saturating_mul(r.into())) + // Minimum execution time: 25_145_000 picoseconds. + Weight::from_parts(26_085_800, 3469) + // Standard Error: 216 + .saturating_add(Weight::from_parts(5_121, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) - /// Storage: Tips Reasons (r:0 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Reasons` (r:0 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) fn retract_tip() -> Weight { // Proof Size summary in bytes: // Measured: `221` // Estimated: `3686` - // Minimum execution time: 28_522_000 picoseconds. - Weight::from_parts(29_323_000, 3686) + // Minimum execution time: 25_302_000 picoseconds. + Weight::from_parts(26_229_000, 3686) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Tips Reasons (r:1 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) - /// Storage: Tips Tips (r:0 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Reasons` (r:1 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Tips` (r:0 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `r` is `[0, 300]`. /// The range of component `t` is `[1, 13]`. fn tip_new(r: u32, t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `526 + t * (64 ±0)` // Estimated: `3991 + t * (64 ±0)` - // Minimum execution time: 19_650_000 picoseconds. - Weight::from_parts(19_837_982, 3991) - // Standard Error: 151 - .saturating_add(Weight::from_parts(1_746, 0).saturating_mul(r.into())) - // Standard Error: 3_588 - .saturating_add(Weight::from_parts(102_359, 0).saturating_mul(t.into())) + // Minimum execution time: 16_600_000 picoseconds. + Weight::from_parts(17_071_638, 3991) + // Standard Error: 131 + .saturating_add(Weight::from_parts(1_138, 0).saturating_mul(r.into())) + // Standard Error: 3_125 + .saturating_add(Weight::from_parts(82_996, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(t.into())) } - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[1, 13]`. fn tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `747 + t * (112 ±0)` // Estimated: `4212 + t * (112 ±0)` - // Minimum execution time: 15_641_000 picoseconds. - Weight::from_parts(15_745_460, 4212) - // Standard Error: 5_106 - .saturating_add(Weight::from_parts(229_475, 0).saturating_mul(t.into())) + // Minimum execution time: 13_972_000 picoseconds. + Weight::from_parts(14_269_356, 4212) + // Standard Error: 4_695 + .saturating_add(Weight::from_parts(205_433, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(t.into())) } - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Tips Reasons (r:0 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Tips::Reasons` (r:0 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[1, 13]`. fn close_tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `786 + t * (112 ±0)` // Estimated: `4242 + t * (112 ±0)` - // Minimum execution time: 62_059_000 picoseconds. - Weight::from_parts(64_604_554, 4242) - // Standard Error: 11_818 - .saturating_add(Weight::from_parts(116_297, 0).saturating_mul(t.into())) + // Minimum execution time: 51_878_000 picoseconds. + Weight::from_parts(54_513_477, 4242) + // Standard Error: 12_281 + .saturating_add(Weight::from_parts(126_605, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(t.into())) } - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) - /// Storage: Tips Reasons (r:0 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Reasons` (r:0 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[1, 13]`. fn slash_tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `269` // Estimated: `3734` - // Minimum execution time: 14_133_000 picoseconds. - Weight::from_parts(14_957_547, 3734) - // Standard Error: 2_765 - .saturating_add(Weight::from_parts(22_138, 0).saturating_mul(t.into())) + // Minimum execution time: 11_800_000 picoseconds. + Weight::from_parts(12_520_984, 3734) + // Standard Error: 2_360 + .saturating_add(Weight::from_parts(28_777, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Tips Reasons (r:1 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: `Tips::Reasons` (r:1 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `r` is `[0, 300]`. fn report_awesome(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `3469` - // Minimum execution time: 29_576_000 picoseconds. - Weight::from_parts(30_722_650, 3469) - // Standard Error: 192 - .saturating_add(Weight::from_parts(2_601, 0).saturating_mul(r.into())) + // Minimum execution time: 25_145_000 picoseconds. + Weight::from_parts(26_085_800, 3469) + // Standard Error: 216 + .saturating_add(Weight::from_parts(5_121, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) - /// Storage: Tips Reasons (r:0 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Reasons` (r:0 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) fn retract_tip() -> Weight { // Proof Size summary in bytes: // Measured: `221` // Estimated: `3686` - // Minimum execution time: 28_522_000 picoseconds. - Weight::from_parts(29_323_000, 3686) + // Minimum execution time: 25_302_000 picoseconds. + Weight::from_parts(26_229_000, 3686) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Tips Reasons (r:1 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) - /// Storage: Tips Tips (r:0 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Reasons` (r:1 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Tips` (r:0 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `r` is `[0, 300]`. /// The range of component `t` is `[1, 13]`. fn tip_new(r: u32, t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `526 + t * (64 ±0)` // Estimated: `3991 + t * (64 ±0)` - // Minimum execution time: 19_650_000 picoseconds. - Weight::from_parts(19_837_982, 3991) - // Standard Error: 151 - .saturating_add(Weight::from_parts(1_746, 0).saturating_mul(r.into())) - // Standard Error: 3_588 - .saturating_add(Weight::from_parts(102_359, 0).saturating_mul(t.into())) + // Minimum execution time: 16_600_000 picoseconds. + Weight::from_parts(17_071_638, 3991) + // Standard Error: 131 + .saturating_add(Weight::from_parts(1_138, 0).saturating_mul(r.into())) + // Standard Error: 3_125 + .saturating_add(Weight::from_parts(82_996, 0).saturating_mul(t.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(t.into())) } - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[1, 13]`. fn tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `747 + t * (112 ±0)` // Estimated: `4212 + t * (112 ±0)` - // Minimum execution time: 15_641_000 picoseconds. - Weight::from_parts(15_745_460, 4212) - // Standard Error: 5_106 - .saturating_add(Weight::from_parts(229_475, 0).saturating_mul(t.into())) + // Minimum execution time: 13_972_000 picoseconds. + Weight::from_parts(14_269_356, 4212) + // Standard Error: 4_695 + .saturating_add(Weight::from_parts(205_433, 0).saturating_mul(t.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(t.into())) } - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) - /// Storage: Elections Members (r:1 w:0) - /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Tips Reasons (r:0 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Elections::Members` (r:1 w:0) + /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Tips::Reasons` (r:0 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[1, 13]`. fn close_tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `786 + t * (112 ±0)` // Estimated: `4242 + t * (112 ±0)` - // Minimum execution time: 62_059_000 picoseconds. - Weight::from_parts(64_604_554, 4242) - // Standard Error: 11_818 - .saturating_add(Weight::from_parts(116_297, 0).saturating_mul(t.into())) + // Minimum execution time: 51_878_000 picoseconds. + Weight::from_parts(54_513_477, 4242) + // Standard Error: 12_281 + .saturating_add(Weight::from_parts(126_605, 0).saturating_mul(t.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(t.into())) } - /// Storage: Tips Tips (r:1 w:1) - /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) - /// Storage: Tips Reasons (r:0 w:1) - /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: `Tips::Tips` (r:1 w:1) + /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Tips::Reasons` (r:0 w:1) + /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `t` is `[1, 13]`. fn slash_tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `269` // Estimated: `3734` - // Minimum execution time: 14_133_000 picoseconds. - Weight::from_parts(14_957_547, 3734) - // Standard Error: 2_765 - .saturating_add(Weight::from_parts(22_138, 0).saturating_mul(t.into())) + // Minimum execution time: 11_800_000 picoseconds. + Weight::from_parts(12_520_984, 3734) + // Standard Error: 2_360 + .saturating_add(Weight::from_parts(28_777, 0).saturating_mul(t.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/transaction-payment/Cargo.toml b/substrate/frame/transaction-payment/Cargo.toml index 275e1c01f92..66e0bef1436 100644 --- a/substrate/frame/transaction-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/Cargo.toml @@ -21,6 +21,7 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features = ] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true, default-features = true } +frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } frame-system = { path = "../system", default-features = false } sp-core = { path = "../../primitives/core", default-features = false } @@ -36,6 +37,7 @@ pallet-balances = { path = "../balances" } default = ["std"] std = [ "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "pallet-balances/std", @@ -46,6 +48,13 @@ std = [ "sp-runtime/std", "sp-std/std", ] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml b/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml index 7640cc815e5..528f29e8e4a 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml @@ -19,6 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] # Substrate dependencies sp-runtime = { path = "../../../primitives/runtime", default-features = false } sp-std = { path = "../../../primitives/std", default-features = false } +frame-benchmarking = { path = "../../benchmarking", default-features = false, optional = true } frame-support = { path = "../../support", default-features = false } frame-system = { path = "../../system", default-features = false } pallet-asset-conversion = { path = "../../asset-conversion", default-features = false } @@ -37,6 +38,7 @@ pallet-balances = { path = "../../balances" } default = ["std"] std = [ "codec/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "pallet-asset-conversion/std", @@ -50,6 +52,16 @@ std = [ "sp-std/std", "sp-storage/std", ] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-asset-conversion/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/README.md b/substrate/frame/transaction-payment/asset-conversion-tx-payment/README.md index eccba773673..fcd1527526e 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/README.md +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/README.md @@ -16,6 +16,6 @@ asset. ### Integration This pallet wraps FRAME's transaction payment pallet and functions as a replacement. This means you should include both pallets in your `construct_runtime` macro, but only include this -pallet's [`SignedExtension`] ([`ChargeAssetTxPayment`]). +pallet's [`TransactionExtension`] ([`ChargeAssetTxPayment`]). License: Apache-2.0 diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/benchmarking.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/benchmarking.rs new file mode 100644 index 00000000000..0bffb991e4a --- /dev/null +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/benchmarking.rs @@ -0,0 +1,125 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Benchmarks for Asset Conversion Tx Payment Pallet's transaction extension + +use super::*; +use crate::Pallet; +use frame_benchmarking::v2::*; +use frame_support::{ + dispatch::{DispatchInfo, PostDispatchInfo}, + pallet_prelude::*, +}; +use frame_system::RawOrigin; +use sp_runtime::traits::{AsSystemOriginSigner, DispatchTransaction, Dispatchable}; + +#[benchmarks(where + T::RuntimeCall: Dispatchable, + AssetBalanceOf: Send + Sync, + BalanceOf: Send + + Sync + + From + + Into> + + Into> + + From>, + ChargeAssetIdOf: Send + Sync + Default, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, +)] +mod benchmarks { + use super::*; + + #[benchmark] + fn charge_asset_tx_payment_zero() { + let caller: T::AccountId = whitelisted_caller(); + let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(0u64.into(), None); + let inner = frame_system::Call::remark { remark: vec![] }; + let call = T::RuntimeCall::from(inner); + let info = DispatchInfo { + weight: Weight::zero(), + class: DispatchClass::Normal, + pays_fee: Pays::No, + }; + let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Pays::No }; + #[block] + { + assert!(ext + .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(post_info)) + .unwrap() + .is_ok()); + } + } + + #[benchmark] + fn charge_asset_tx_payment_native() { + let caller: T::AccountId = whitelisted_caller(); + let (fun_asset_id, _) = ::BenchmarkHelper::create_asset_id_parameter(1); + ::BenchmarkHelper::setup_balances_and_pool(fun_asset_id, caller.clone()); + let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(10u64.into(), None); + let inner = frame_system::Call::remark { remark: vec![] }; + let call = T::RuntimeCall::from(inner); + let info = DispatchInfo { + weight: Weight::from_parts(10, 0), + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(10, 0)), + pays_fee: Pays::Yes, + }; + + #[block] + { + assert!(ext + .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(post_info)) + .unwrap() + .is_ok()); + } + } + + #[benchmark] + fn charge_asset_tx_payment_asset() { + let caller: T::AccountId = whitelisted_caller(); + let (fun_asset_id, asset_id) = ::BenchmarkHelper::create_asset_id_parameter(1); + ::BenchmarkHelper::setup_balances_and_pool(fun_asset_id, caller.clone()); + + let tip = 10u64.into(); + let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(tip, Some(asset_id)); + let inner = frame_system::Call::remark { remark: vec![] }; + let call = T::RuntimeCall::from(inner); + let info = DispatchInfo { + weight: Weight::from_parts(10, 0), + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(10, 0)), + pays_fee: Pays::Yes, + }; + + #[block] + { + assert!(ext + .test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 0, |_| Ok( + post_info + )) + .unwrap() + .is_ok()); + } + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime); +} diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs index ed0ed56e6e0..8ef7c2ba38e 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs @@ -20,8 +20,8 @@ //! //! ## Overview //! -//! This pallet provides a `SignedExtension` with an optional `AssetId` that specifies the asset -//! to be used for payment (defaulting to the native token on `None`). It expects an +//! This pallet provides a `TransactionExtension` with an optional `AssetId` that specifies the +//! asset to be used for payment (defaulting to the native token on `None`). It expects an //! [`OnChargeAssetTransaction`] implementation analogous to [`pallet-transaction-payment`]. The //! included [`AssetConversionAdapter`] (implementing [`OnChargeAssetTransaction`]) determines the //! fee amount by converting the fee calculated by [`pallet-transaction-payment`] in the native @@ -31,7 +31,7 @@ //! //! This pallet does not have any dispatchable calls or storage. It wraps FRAME's Transaction //! Payment pallet and functions as a replacement. This means you should include both pallets in -//! your `construct_runtime` macro, but only include this pallet's [`SignedExtension`] +//! your `construct_runtime` macro, but only include this pallet's [`TransactionExtension`] //! ([`ChargeAssetTxPayment`]). //! //! ## Terminology @@ -53,23 +53,29 @@ use frame_support::{ }, DefaultNoBound, }; -use pallet_transaction_payment::OnChargeTransaction; +use pallet_transaction_payment::{ChargeTransactionPayment, OnChargeTransaction}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension, Zero}, - transaction_validity::{ - InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + traits::{ + AsSystemOriginSigner, DispatchInfoOf, Dispatchable, PostDispatchInfoOf, + TransactionExtension, TransactionExtensionBase, ValidateResult, Zero, }, + transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction}, }; #[cfg(test)] mod mock; #[cfg(test)] mod tests; +pub mod weights; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; mod payment; -use frame_support::traits::tokens::AssetId; +use frame_support::{pallet_prelude::Weight, traits::tokens::AssetId}; pub use payment::*; +pub use weights::WeightInfo; /// Type aliases used for interaction with `OnChargeTransaction`. pub(crate) type OnChargeTransactionOf = @@ -125,11 +131,30 @@ pub mod pallet { type Fungibles: Balanced; /// The actual transaction charging logic that charges the fees. type OnChargeAssetTransaction: OnChargeAssetTransaction; + /// The weight information of this pallet. + type WeightInfo: WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + /// Benchmark helper + type BenchmarkHelper: BenchmarkHelperTrait< + Self::AccountId, + <::Fungibles as Inspect>::AssetId, + <::OnChargeAssetTransaction as OnChargeAssetTransaction>::AssetId, + >; } #[pallet::pallet] pub struct Pallet(_); + #[cfg(feature = "runtime-benchmarks")] + /// Helper trait to benchmark the `ChargeAssetTxPayment` transaction extension. + pub trait BenchmarkHelperTrait { + /// Returns the `AssetId` to be used in the liquidity pool by the benchmarking code. + fn create_asset_id_parameter(id: u32) -> (FunAssetIdParameter, AssetIdParameter); + /// Create a liquidity pool for a given asset and sufficiently endow accounts to benchmark + /// the extension. + fn setup_balances_and_pool(asset_id: FunAssetIdParameter, account: AccountId); + } + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -179,9 +204,8 @@ where who: &T::AccountId, call: &T::RuntimeCall, info: &DispatchInfoOf, - len: usize, + fee: BalanceOf, ) -> Result<(BalanceOf, InitialPayment), TransactionValidityError> { - let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); debug_assert!(self.tip <= fee, "tip should be included in the computed fee"); if fee.is_zero() { Ok((fee, InitialPayment::Nothing)) @@ -225,9 +249,8 @@ impl sp_std::fmt::Debug for ChargeAssetTxPayment { } } -impl SignedExtension for ChargeAssetTxPayment +impl TransactionExtensionBase for ChargeAssetTxPayment where - T::RuntimeCall: Dispatchable, AssetBalanceOf: Send + Sync, BalanceOf: Send + Sync @@ -238,109 +261,145 @@ where ChargeAssetIdOf: Send + Sync, { const IDENTIFIER: &'static str = "ChargeAssetTxPayment"; - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); + type Implicit = (); + + fn weight(&self) -> Weight { + if self.asset_id.is_some() { + ::WeightInfo::charge_asset_tx_payment_asset() + } else { + ::WeightInfo::charge_asset_tx_payment_native() + } + } +} + +impl TransactionExtension for ChargeAssetTxPayment +where + T::RuntimeCall: Dispatchable, + AssetBalanceOf: Send + Sync, + BalanceOf: Send + + Sync + + From + + Into> + + Into> + + From>, + ChargeAssetIdOf: Send + Sync, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, +{ + type Val = ( + // tip + BalanceOf, + // who paid the fee + T::AccountId, + // transaction fee + BalanceOf, + ); type Pre = ( // tip BalanceOf, // who paid the fee - Self::AccountId, + T::AccountId, // imbalance resulting from withdrawing the fee InitialPayment, // asset_id for the transaction payment Option>, ); - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } - fn validate( &self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + _call: &T::RuntimeCall, + info: &DispatchInfoOf, len: usize, - ) -> TransactionValidity { - use pallet_transaction_payment::ChargeTransactionPayment; - let (fee, _) = self.withdraw_fee(who, call, info, len)?; + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + // Non-mutating call of `compute_fee` to calculate the fee used in the transaction priority. + let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); let priority = ChargeTransactionPayment::::get_priority(info, len, self.tip, fee); - Ok(ValidTransaction { priority, ..Default::default() }) + let validity = ValidTransaction { priority, ..Default::default() }; + let val = (self.tip, who.clone(), fee); + Ok((validity, val, origin)) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + val: Self::Val, + _origin: &::RuntimeOrigin, + call: &T::RuntimeCall, + info: &DispatchInfoOf, + _len: usize, + _context: &Context, ) -> Result { - let (_fee, initial_payment) = self.withdraw_fee(who, call, info, len)?; - Ok((self.tip, who.clone(), initial_payment, self.asset_id)) + let (tip, who, fee) = val; + // Mutating call of `withdraw_fee` to actually charge for the transaction. + let (_fee, initial_payment) = self.withdraw_fee(&who, call, info, fee)?; + Ok((tip, who, initial_payment, self.asset_id.clone())) } fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, + _context: &Context, ) -> Result<(), TransactionValidityError> { - if let Some((tip, who, initial_payment, asset_id)) = pre { - match initial_payment { - InitialPayment::Native(already_withdrawn) => { - debug_assert!( - asset_id.is_none(), - "For that payment type the `asset_id` should be None" - ); - pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( - Some((tip, who, already_withdrawn)), + let (tip, who, initial_payment, asset_id) = pre; + match initial_payment { + InitialPayment::Native(already_withdrawn) => { + debug_assert!( + asset_id.is_none(), + "For that payment type the `asset_id` should be None" + ); + pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( + (tip, who, already_withdrawn), + info, + post_info, + len, + result, + &(), + )?; + }, + InitialPayment::Asset(already_withdrawn) => { + debug_assert!( + asset_id.is_some(), + "For that payment type the `asset_id` should be set" + ); + let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( + len as u32, info, post_info, tip, + ); + + if let Some(asset_id) = asset_id { + let (used_for_fee, received_exchanged, asset_consumed) = already_withdrawn; + let converted_fee = T::OnChargeAssetTransaction::correct_and_deposit_fee( + &who, info, post_info, - len, - result, + actual_fee.into(), + tip.into(), + used_for_fee.into(), + received_exchanged.into(), + asset_id.clone(), + asset_consumed.into(), )?; - }, - InitialPayment::Asset(already_withdrawn) => { - debug_assert!( - asset_id.is_some(), - "For that payment type the `asset_id` should be set" - ); - let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( - len as u32, info, post_info, tip, - ); - - if let Some(asset_id) = asset_id { - let (used_for_fee, received_exchanged, asset_consumed) = already_withdrawn; - let converted_fee = T::OnChargeAssetTransaction::correct_and_deposit_fee( - &who, - info, - post_info, - actual_fee.into(), - tip.into(), - used_for_fee.into(), - received_exchanged.into(), - asset_id.clone(), - asset_consumed.into(), - )?; - Pallet::::deposit_event(Event::::AssetTxFeePaid { - who, - actual_fee: converted_fee, - tip, - asset_id, - }); - } - }, - InitialPayment::Nothing => { - // `actual_fee` should be zero here for any signed extrinsic. It would be - // non-zero here in case of unsigned extrinsics as they don't pay fees but - // `compute_actual_fee` is not aware of them. In both cases it's fine to just - // move ahead without adjusting the fee, though, so we do nothing. - debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); - }, - } + Pallet::::deposit_event(Event::::AssetTxFeePaid { + who, + actual_fee: converted_fee, + tip, + asset_id, + }); + } + }, + InitialPayment::Nothing => { + // `actual_fee` should be zero here for any signed extrinsic. It would be + // non-zero here in case of unsigned extrinsics as they don't pay fees but + // `compute_actual_fee` is not aware of them. In both cases it's fine to just + // move ahead without adjusting the fee, though, so we do nothing. + debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); + }, } Ok(()) diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs index c8bf2eb8f44..853753d41cf 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs @@ -168,12 +168,12 @@ impl OnUnbalanced> for DealWithFees } } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter; type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; - type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; } @@ -269,4 +269,72 @@ impl Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = Assets; type OnChargeAssetTransaction = AssetConversionAdapter; + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = Helper; +} + +#[cfg(feature = "runtime-benchmarks")] +pub fn new_test_ext() -> sp_io::TestExternalities { + let base_weight = 5; + let balance_factor = 100; + crate::tests::ExtBuilder::default() + .balance_factor(balance_factor) + .base_weight(Weight::from_parts(base_weight, 0)) + .build() +} + +#[cfg(feature = "runtime-benchmarks")] +pub struct Helper; + +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkHelperTrait for Helper { + fn create_asset_id_parameter(id: u32) -> (u32, u32) { + (id, id) + } + + fn setup_balances_and_pool(asset_id: u32, account: u64) { + use frame_support::{assert_ok, traits::fungibles::Mutate}; + use sp_runtime::traits::StaticLookup; + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + 42, /* owner */ + true, /* is_sufficient */ + 1, + )); + + let lp_provider = 12; + assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), lp_provider, u64::MAX / 2)); + let lp_provider_account = ::Lookup::unlookup(lp_provider); + assert_ok!(Assets::mint_into(asset_id.into(), &lp_provider_account, u64::MAX / 2)); + + let token_1 = Box::new(NativeOrWithId::Native); + let token_2 = Box::new(NativeOrWithId::WithId(asset_id)); + assert_ok!(AssetConversion::create_pool( + RuntimeOrigin::signed(lp_provider), + token_1.clone(), + token_2.clone() + )); + + assert_ok!(AssetConversion::add_liquidity( + RuntimeOrigin::signed(lp_provider), + token_1, + token_2, + (u32::MAX / 8).into(), // 1 desired + u32::MAX.into(), // 2 desired + 1, // 1 min + 1, // 2 min + lp_provider_account, + )); + + use frame_support::traits::Currency; + let _ = Balances::deposit_creating(&account, u32::MAX.into()); + + let beneficiary = ::Lookup::unlookup(account); + let balance = 1000; + + assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, account), balance); + } } diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/tests.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/tests.rs index 62faed269d3..619077c0a5e 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/tests.rs @@ -28,7 +28,10 @@ use frame_support::{ use frame_system as system; use mock::{ExtrinsicBaseWeight, *}; use pallet_balances::Call as BalancesCall; -use sp_runtime::{traits::StaticLookup, BuildStorage}; +use sp_runtime::{ + traits::{DispatchTransaction, StaticLookup}, + BuildStorage, +}; const CALL: &::RuntimeCall = &RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 2, value: 69 }); @@ -160,33 +163,35 @@ fn transaction_payment_in_native_possible() { .build() .execute_with(|| { let len = 10; - let pre = ChargeAssetTxPayment::::from(0, None) - .pre_dispatch(&1, CALL, &info_from_weight(WEIGHT_5), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, None) + .validate_and_prepare(Some(1).into(), CALL, &info_from_weight(WEIGHT_5), len) .unwrap(); let initial_balance = 10 * balance_factor; assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(WEIGHT_5), &default_post_info(), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); - let pre = ChargeAssetTxPayment::::from(5 /* tipped */, None) - .pre_dispatch(&2, CALL, &info_from_weight(WEIGHT_100), len) + let (pre, _) = ChargeAssetTxPayment::::from(5 /* tipped */, None) + .validate_and_prepare(Some(2).into(), CALL, &info_from_weight(WEIGHT_100), len) .unwrap(); let initial_balance_for_2 = 20 * balance_factor; assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 100 - 5); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(WEIGHT_100), &post_info_from_weight(WEIGHT_50), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 50 - 5); }); @@ -237,8 +242,8 @@ fn transaction_payment_in_asset_possible() { let fee_in_asset = input_quote.unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(WEIGHT_5), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_5), len) .unwrap(); // assert that native balance is not used assert_eq!(Balances::free_balance(caller), 10 * balance_factor); @@ -247,11 +252,12 @@ fn transaction_payment_in_asset_possible() { assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(WEIGHT_5), // estimated tx weight &default_post_info(), // weight actually used == estimated len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); @@ -289,12 +295,8 @@ fn transaction_payment_in_asset_fails_if_no_pool_for_that_asset() { assert_eq!(Assets::balance(asset_id, caller), balance); let len = 10; - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)).pre_dispatch( - &caller, - CALL, - &info_from_weight(WEIGHT_5), - len, - ); + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_5), len); // As there is no pool in the dex set up for this asset, conversion should fail. assert!(pre.is_err()); @@ -344,8 +346,8 @@ fn transaction_payment_without_fee() { assert_eq!(input_quote, Some(201)); let fee_in_asset = input_quote.unwrap(); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(WEIGHT_5), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_5), len) .unwrap(); // assert that native balance is not used @@ -363,11 +365,12 @@ fn transaction_payment_without_fee() { assert_eq!(refund, 199); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(WEIGHT_5), &post_info_from_pays(Pays::No), len, - &Ok(()) + &Ok(()), + &() )); // caller should get refunded @@ -419,8 +422,8 @@ fn asset_transaction_payment_with_tip_and_refund() { assert_eq!(input_quote, Some(1206)); let fee_in_asset = input_quote.unwrap(); - let pre = ChargeAssetTxPayment::::from(tip, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(WEIGHT_100), len) + let (pre, _) = ChargeAssetTxPayment::::from(tip, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_100), len) .unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); @@ -435,11 +438,12 @@ fn asset_transaction_payment_with_tip_and_refund() { .unwrap(); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(WEIGHT_100), &post_info_from_weight(WEIGHT_50), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(TipUnbalancedAmount::get(), tip); @@ -500,8 +504,8 @@ fn payment_from_account_with_only_assets() { .unwrap(); assert_eq!(fee_in_asset, 301); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(WEIGHT_5), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_5), len) .unwrap(); assert_eq!(Balances::free_balance(caller), ed); // check that fee was charged in the given asset @@ -516,11 +520,12 @@ fn payment_from_account_with_only_assets() { .unwrap(); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(WEIGHT_5), &default_post_info(), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset + refund); assert_eq!(Balances::free_balance(caller), 0); @@ -565,18 +570,19 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() { // there will be no conversion when the fee is zero { - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_pays(Pays::No), len) .unwrap(); // `Pays::No` implies there are no fees assert_eq!(Assets::balance(asset_id, caller), balance); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_pays(Pays::No), &post_info_from_pays(Pays::No), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance); } @@ -591,17 +597,23 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() { ) .unwrap(); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare( + Some(caller).into(), + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len, + ) .unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(Weight::from_parts(weight, 0)), &default_post_info(), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); }); @@ -641,8 +653,8 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { // calculated fee is greater than 0 assert!(fee > 0); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_pays(Pays::No), len) .unwrap(); // `Pays::No` implies no pre-dispatch fees @@ -658,62 +670,12 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the // initial fee) assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_pays(Pays::No), &post_info_from_pays(Pays::Yes), len, - &Ok(()) - )); - assert_eq!(Assets::balance(asset_id, caller), balance); - }); -} - -#[test] -fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() { - let base_weight = 1; - ExtBuilder::default() - .balance_factor(100) - .base_weight(Weight::from_parts(base_weight, 0)) - .build() - .execute_with(|| { - // create the asset - let asset_id = 1; - let min_balance = 100; - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - 42, /* owner */ - true, /* is_sufficient */ - min_balance - )); - - // mint into the caller account - let caller = 333; - let beneficiary = ::Lookup::unlookup(caller); - let balance = 1000; - - assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); - assert_eq!(Assets::balance(asset_id, caller), balance); - - let weight = 1; - let len = 1; - ChargeAssetTxPayment::::pre_dispatch_unsigned( - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len, - ) - .unwrap(); - - assert_eq!(Assets::balance(asset_id, caller), balance); - - // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the - // initial fee) - assert_ok!(ChargeAssetTxPayment::::post_dispatch( - None, - &info_from_weight(Weight::from_parts(weight, 0)), - &post_info_from_pays(Pays::Yes), - len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance); }); diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs new file mode 100644 index 00000000000..f95e49f8073 --- /dev/null +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs @@ -0,0 +1,150 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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_asset_conversion_tx_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/production/substrate-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_asset_conversion_tx_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_asset_conversion_tx_payment`. +pub trait WeightInfo { + fn charge_asset_tx_payment_zero() -> Weight; + fn charge_asset_tx_payment_native() -> Weight; + fn charge_asset_tx_payment_asset() -> Weight; +} + +/// Weights for `pallet_asset_conversion_tx_payment` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn charge_asset_tx_payment_zero() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 628_000 picoseconds. + Weight::from_parts(694_000, 0) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_asset_tx_payment_native() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `1733` + // Minimum execution time: 34_410_000 picoseconds. + Weight::from_parts(35_263_000, 1733) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_asset_tx_payment_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `888` + // Estimated: `6208` + // Minimum execution time: 112_432_000 picoseconds. + Weight::from_parts(113_992_000, 6208) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + fn charge_asset_tx_payment_zero() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 628_000 picoseconds. + Weight::from_parts(694_000, 0) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_asset_tx_payment_native() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `1733` + // Minimum execution time: 34_410_000 picoseconds. + Weight::from_parts(35_263_000, 1733) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_asset_tx_payment_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `888` + // Estimated: `6208` + // Minimum execution time: 112_432_000 picoseconds. + Weight::from_parts(113_992_000, 6208) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) + } +} diff --git a/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml b/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml index 1da3237df08..06d9c30792e 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -66,6 +66,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ diff --git a/substrate/frame/transaction-payment/asset-tx-payment/README.md b/substrate/frame/transaction-payment/asset-tx-payment/README.md index fc860347d85..933ce13b0ee 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/README.md +++ b/substrate/frame/transaction-payment/asset-tx-payment/README.md @@ -16,6 +16,6 @@ asset. ### Integration This pallet wraps FRAME's transaction payment pallet and functions as a replacement. This means you should include both pallets in your `construct_runtime` macro, but only include this -pallet's [`SignedExtension`] ([`ChargeAssetTxPayment`]). +pallet's [`TransactionExtension`] ([`ChargeAssetTxPayment`]). License: Apache-2.0 diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/benchmarking.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/benchmarking.rs new file mode 100644 index 00000000000..17e96e2b025 --- /dev/null +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/benchmarking.rs @@ -0,0 +1,123 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Benchmarks for Asset Tx Payment Pallet's transaction extension + +use super::*; +use crate::Pallet; +use frame_benchmarking::v2::*; +use frame_support::{ + dispatch::{DispatchInfo, PostDispatchInfo}, + pallet_prelude::*, +}; +use frame_system::RawOrigin; +use sp_runtime::traits::{AsSystemOriginSigner, DispatchTransaction, Dispatchable}; + +#[benchmarks(where + T::RuntimeCall: Dispatchable, + AssetBalanceOf: Send + Sync, + BalanceOf: Send + Sync + From + IsType>, + ChargeAssetIdOf: Send + Sync, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + Credit: IsType>, +)] +mod benchmarks { + use super::*; + + #[benchmark] + fn charge_asset_tx_payment_zero() { + let caller: T::AccountId = whitelisted_caller(); + let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(0u32.into(), None); + let inner = frame_system::Call::remark { remark: vec![] }; + let call = T::RuntimeCall::from(inner); + let info = DispatchInfo { + weight: Weight::zero(), + class: DispatchClass::Normal, + pays_fee: Pays::No, + }; + let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Pays::No }; + #[block] + { + assert!(ext + .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(post_info)) + .unwrap() + .is_ok()); + } + } + + #[benchmark] + fn charge_asset_tx_payment_native() { + let caller: T::AccountId = whitelisted_caller(); + let (fun_asset_id, _) = ::BenchmarkHelper::create_asset_id_parameter(1); + ::BenchmarkHelper::setup_balances_and_pool(fun_asset_id, caller.clone()); + let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(10u32.into(), None); + let inner = frame_system::Call::remark { remark: vec![] }; + let call = T::RuntimeCall::from(inner); + let info = DispatchInfo { + weight: Weight::from_parts(10, 0), + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(10, 0)), + pays_fee: Pays::Yes, + }; + + #[block] + { + assert!(ext + .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(post_info)) + .unwrap() + .is_ok()); + } + } + + #[benchmark] + fn charge_asset_tx_payment_asset() { + let caller: T::AccountId = whitelisted_caller(); + let (fun_asset_id, asset_id) = ::BenchmarkHelper::create_asset_id_parameter(1); + ::BenchmarkHelper::setup_balances_and_pool( + fun_asset_id.clone(), + caller.clone(), + ); + let tip = 10u32.into(); + let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(tip, Some(asset_id)); + let inner = frame_system::Call::remark { remark: vec![] }; + let call = T::RuntimeCall::from(inner); + let info = DispatchInfo { + weight: Weight::from_parts(10, 0), + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(10, 0)), + pays_fee: Pays::Yes, + }; + + #[block] + { + assert!(ext + .test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 0, |_| Ok( + post_info + )) + .unwrap() + .is_ok()); + } + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime); +} diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs index 753fae747a3..991b5f31406 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs @@ -31,7 +31,7 @@ //! This pallet wraps FRAME's transaction payment pallet and functions as a replacement. This means //! you should include both pallets in your `construct_runtime` macro, but only include this -//! pallet's [`SignedExtension`] ([`ChargeAssetTxPayment`]). +//! pallet's [`TransactionExtension`] ([`ChargeAssetTxPayment`]). #![cfg_attr(not(feature = "std"), no_std)] @@ -40,6 +40,7 @@ use sp_std::prelude::*; use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchInfo, DispatchResult, PostDispatchInfo}, + pallet_prelude::Weight, traits::{ tokens::{ fungibles::{Balanced, Credit, Inspect}, @@ -52,10 +53,11 @@ use frame_support::{ use pallet_transaction_payment::OnChargeTransaction; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension, Zero}, - transaction_validity::{ - InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + traits::{ + AsSystemOriginSigner, DispatchInfoOf, Dispatchable, PostDispatchInfoOf, + TransactionExtension, TransactionExtensionBase, Zero, }, + transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction}, }; #[cfg(test)] @@ -63,8 +65,14 @@ mod mock; #[cfg(test)] mod tests; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + mod payment; +pub mod weights; + pub use payment::*; +pub use weights::WeightInfo; /// Type aliases used for interaction with `OnChargeTransaction`. pub(crate) type OnChargeTransactionOf = @@ -120,11 +128,30 @@ pub mod pallet { type Fungibles: Balanced; /// The actual transaction charging logic that charges the fees. type OnChargeAssetTransaction: OnChargeAssetTransaction; + /// The weight information of this pallet. + type WeightInfo: WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + /// Benchmark helper + type BenchmarkHelper: BenchmarkHelperTrait< + Self::AccountId, + <::Fungibles as Inspect>::AssetId, + <::OnChargeAssetTransaction as OnChargeAssetTransaction>::AssetId, + >; } #[pallet::pallet] pub struct Pallet(_); + #[cfg(feature = "runtime-benchmarks")] + /// Helper trait to benchmark the `ChargeAssetTxPayment` transaction extension. + pub trait BenchmarkHelperTrait { + /// Returns the `AssetId` to be used in the liquidity pool by the benchmarking code. + fn create_asset_id_parameter(id: u32) -> (FunAssetIdParameter, AssetIdParameter); + /// Create a liquidity pool for a given asset and sufficiently endow accounts to benchmark + /// the extension. + fn setup_balances_and_pool(asset_id: FunAssetIdParameter, account: AccountId); + } + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -172,9 +199,8 @@ where who: &T::AccountId, call: &T::RuntimeCall, info: &DispatchInfoOf, - len: usize, + fee: BalanceOf, ) -> Result<(BalanceOf, InitialPayment), TransactionValidityError> { - let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); debug_assert!(self.tip <= fee, "tip should be included in the computed fee"); if fee.is_zero() { Ok((fee, InitialPayment::Nothing)) @@ -209,104 +235,139 @@ impl sp_std::fmt::Debug for ChargeAssetTxPayment { } } -impl SignedExtension for ChargeAssetTxPayment +impl TransactionExtensionBase for ChargeAssetTxPayment where - T::RuntimeCall: Dispatchable, AssetBalanceOf: Send + Sync, BalanceOf: Send + Sync + From + IsType>, ChargeAssetIdOf: Send + Sync, Credit: IsType>, { const IDENTIFIER: &'static str = "ChargeAssetTxPayment"; - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); + type Implicit = (); + + fn weight(&self) -> Weight { + if self.asset_id.is_some() { + ::WeightInfo::charge_asset_tx_payment_asset() + } else { + ::WeightInfo::charge_asset_tx_payment_native() + } + } +} + +impl TransactionExtension for ChargeAssetTxPayment +where + T::RuntimeCall: Dispatchable, + AssetBalanceOf: Send + Sync, + BalanceOf: Send + Sync + From + IsType>, + ChargeAssetIdOf: Send + Sync, + Credit: IsType>, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, +{ + type Val = ( + // tip + BalanceOf, + // who paid the fee + T::AccountId, + // transaction fee + BalanceOf, + ); type Pre = ( // tip BalanceOf, // who paid the fee - Self::AccountId, + T::AccountId, // imbalance resulting from withdrawing the fee InitialPayment, // asset_id for the transaction payment Option>, ); - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } - fn validate( &self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + _call: &T::RuntimeCall, + info: &DispatchInfoOf, len: usize, - ) -> TransactionValidity { + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> Result< + (ValidTransaction, Self::Val, ::RuntimeOrigin), + TransactionValidityError, + > { use pallet_transaction_payment::ChargeTransactionPayment; - let (fee, _) = self.withdraw_fee(who, call, info, len)?; + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + // Non-mutating call of `compute_fee` to calculate the fee used in the transaction priority. + let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); let priority = ChargeTransactionPayment::::get_priority(info, len, self.tip, fee); - Ok(ValidTransaction { priority, ..Default::default() }) + let val = (self.tip, who.clone(), fee); + let validity = ValidTransaction { priority, ..Default::default() }; + Ok((validity, val, origin)) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + val: Self::Val, + _origin: &::RuntimeOrigin, + call: &T::RuntimeCall, + info: &DispatchInfoOf, + _len: usize, + _context: &Context, ) -> Result { - let (_fee, initial_payment) = self.withdraw_fee(who, call, info, len)?; - Ok((self.tip, who.clone(), initial_payment, self.asset_id)) + let (tip, who, fee) = val; + // Mutating call of `withdraw_fee` to actually charge for the transaction. + let (_fee, initial_payment) = self.withdraw_fee(&who, call, info, fee)?; + Ok((tip, who, initial_payment, self.asset_id)) } fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, + _context: &Context, ) -> Result<(), TransactionValidityError> { - if let Some((tip, who, initial_payment, asset_id)) = pre { - match initial_payment { - InitialPayment::Native(already_withdrawn) => { - pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( - Some((tip, who, already_withdrawn)), + let (tip, who, initial_payment, asset_id) = pre; + match initial_payment { + InitialPayment::Native(already_withdrawn) => { + pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( + (tip, who, already_withdrawn), + info, + post_info, + len, + result, + &(), + )?; + }, + InitialPayment::Asset(already_withdrawn) => { + let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( + len as u32, info, post_info, tip, + ); + + let (converted_fee, converted_tip) = + T::OnChargeAssetTransaction::correct_and_deposit_fee( + &who, info, post_info, - len, - result, + actual_fee.into(), + tip.into(), + already_withdrawn.into(), )?; - }, - InitialPayment::Asset(already_withdrawn) => { - let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( - len as u32, info, post_info, tip, - ); - - let (converted_fee, converted_tip) = - T::OnChargeAssetTransaction::correct_and_deposit_fee( - &who, - info, - post_info, - actual_fee.into(), - tip.into(), - already_withdrawn.into(), - )?; - Pallet::::deposit_event(Event::::AssetTxFeePaid { - who, - actual_fee: converted_fee, - tip: converted_tip, - asset_id, - }); - }, - InitialPayment::Nothing => { - // `actual_fee` should be zero here for any signed extrinsic. It would be - // non-zero here in case of unsigned extrinsics as they don't pay fees but - // `compute_actual_fee` is not aware of them. In both cases it's fine to just - // move ahead without adjusting the fee, though, so we do nothing. - debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); - }, - } + Pallet::::deposit_event(Event::::AssetTxFeePaid { + who, + actual_fee: converted_fee, + tip: converted_tip, + asset_id, + }); + }, + InitialPayment::Nothing => { + // `actual_fee` should be zero here for any signed extrinsic. It would be + // non-zero here in case of unsigned extrinsics as they don't pay fees but + // `compute_actual_fee` is not aware of them. In both cases it's fine to just + // move ahead without adjusting the fee, though, so we do nothing. + debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); + }, } Ok(()) diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs index 1f335b4f6c4..bb484795e82 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs @@ -136,12 +136,12 @@ impl WeightToFeeT for TransactionByteFee { } } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter; type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; - type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; } @@ -205,4 +205,56 @@ impl Config for Runtime { pallet_assets::BalanceToAssetBalance, CreditToBlockAuthor, >; + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = Helper; +} + +#[cfg(feature = "runtime-benchmarks")] +pub fn new_test_ext() -> sp_io::TestExternalities { + let base_weight = 5; + let balance_factor = 100; + crate::tests::ExtBuilder::default() + .balance_factor(balance_factor) + .base_weight(Weight::from_parts(base_weight, 0)) + .build() +} + +#[cfg(feature = "runtime-benchmarks")] +pub struct Helper; + +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkHelperTrait for Helper { + fn create_asset_id_parameter(id: u32) -> (u32, u32) { + (id.into(), id.into()) + } + + fn setup_balances_and_pool(asset_id: u32, account: u64) { + use frame_support::{assert_ok, traits::fungibles::Mutate}; + use sp_runtime::traits::StaticLookup; + let min_balance = 1; + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 2; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 1000; + assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + + use frame_support::traits::Currency; + let _ = Balances::deposit_creating(&account, u32::MAX.into()); + + let beneficiary = ::Lookup::unlookup(account); + let balance = 1000; + + assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, account), balance); + } } diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs index 8df98ceda99..42b8f2cf5fa 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs @@ -25,7 +25,10 @@ use frame_support::{ use frame_system as system; use mock::{ExtrinsicBaseWeight, *}; use pallet_balances::Call as BalancesCall; -use sp_runtime::{traits::StaticLookup, BuildStorage}; +use sp_runtime::{ + traits::{DispatchTransaction, StaticLookup}, + BuildStorage, +}; const CALL: &::RuntimeCall = &RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 2, value: 69 }); @@ -116,33 +119,45 @@ fn transaction_payment_in_native_possible() { .build() .execute_with(|| { let len = 10; - let pre = ChargeAssetTxPayment::::from(0, None) - .pre_dispatch(&1, CALL, &info_from_weight(Weight::from_parts(5, 0)), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, None) + .validate_and_prepare( + Some(1).into(), + CALL, + &info_from_weight(Weight::from_parts(5, 0)), + len, + ) .unwrap(); let initial_balance = 10 * balance_factor; assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(Weight::from_parts(5, 0)), &default_post_info(), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); - let pre = ChargeAssetTxPayment::::from(5 /* tipped */, None) - .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) + let (pre, _) = ChargeAssetTxPayment::::from(5 /* tipped */, None) + .validate_and_prepare( + Some(2).into(), + CALL, + &info_from_weight(Weight::from_parts(100, 0)), + len, + ) .unwrap(); let initial_balance_for_2 = 20 * balance_factor; assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 100 - 5); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(Weight::from_parts(100, 0)), &post_info_from_weight(Weight::from_parts(50, 0)), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 50 - 5); }); @@ -179,8 +194,13 @@ fn transaction_payment_in_asset_possible() { // we convert the from weight to fee based on the ratio between asset min balance and // existential deposit let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare( + Some(caller).into(), + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len, + ) .unwrap(); // assert that native balance is not used assert_eq!(Balances::free_balance(caller), 10 * balance_factor); @@ -189,11 +209,12 @@ fn transaction_payment_in_asset_possible() { assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(Weight::from_parts(weight, 0)), &default_post_info(), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance - fee); // check that the block author gets rewarded @@ -232,8 +253,13 @@ fn transaction_payment_without_fee() { // we convert the from weight to fee based on the ratio between asset min balance and // existential deposit let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare( + Some(caller).into(), + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len, + ) .unwrap(); // assert that native balance is not used assert_eq!(Balances::free_balance(caller), 10 * balance_factor); @@ -242,11 +268,12 @@ fn transaction_payment_without_fee() { assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(Weight::from_parts(weight, 0)), &post_info_from_pays(Pays::No), len, - &Ok(()) + &Ok(()), + &() )); // caller should be refunded assert_eq!(Assets::balance(asset_id, caller), balance); @@ -287,18 +314,24 @@ fn asset_transaction_payment_with_tip_and_refund() { // existential deposit let fee_with_tip = (base_weight + weight + len as u64 + tip) * min_balance / ExistentialDeposit::get(); - let pre = ChargeAssetTxPayment::::from(tip, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) + let (pre, _) = ChargeAssetTxPayment::::from(tip, Some(asset_id)) + .validate_and_prepare( + Some(caller).into(), + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len, + ) .unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance - fee_with_tip); let final_weight = 50; assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(Weight::from_parts(weight, 0)), &post_info_from_weight(Weight::from_parts(final_weight, 0)), len, - &Ok(()) + &Ok(()), + &() )); let final_fee = fee_with_tip - (weight - final_weight) * min_balance / ExistentialDeposit::get(); @@ -339,19 +372,25 @@ fn payment_from_account_with_only_assets() { // we convert the from weight to fee based on the ratio between asset min balance and // existential deposit let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare( + Some(caller).into(), + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len, + ) .unwrap(); assert_eq!(Balances::free_balance(caller), 0); // check that fee was charged in the given asset assert_eq!(Assets::balance(asset_id, caller), balance - fee); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(Weight::from_parts(weight, 0)), &default_post_info(), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance - fee); assert_eq!(Balances::free_balance(caller), 0); @@ -372,7 +411,12 @@ fn payment_only_with_existing_sufficient_asset() { let len = 10; // pre_dispatch fails for non-existent asset assert!(ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) + .validate_and_prepare( + Some(caller).into(), + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len + ) .is_err()); // create the non-sufficient asset @@ -386,7 +430,12 @@ fn payment_only_with_existing_sufficient_asset() { )); // pre_dispatch fails for non-sufficient asset assert!(ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) + .validate_and_prepare( + Some(caller).into(), + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len + ) .is_err()); }); } @@ -424,33 +473,40 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() { // naive fee calculation would round down to zero assert_eq!(fee, 0); { - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_pays(Pays::No), len) .unwrap(); // `Pays::No` still implies no fees assert_eq!(Assets::balance(asset_id, caller), balance); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_pays(Pays::No), &post_info_from_pays(Pays::No), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance); } - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare( + Some(caller).into(), + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len, + ) .unwrap(); // check that at least one coin was charged in the given asset assert_eq!(Assets::balance(asset_id, caller), balance - 1); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_weight(Weight::from_parts(weight, 0)), &default_post_info(), len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance - 1); }); @@ -488,8 +544,8 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); // calculated fee is greater than 0 assert!(fee > 0); - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) + let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .validate_and_prepare(Some(caller).into(), CALL, &info_from_pays(Pays::No), len) .unwrap(); // `Pays::No` implies no pre-dispatch fees assert_eq!(Assets::balance(asset_id, caller), balance); @@ -503,60 +559,12 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the // initial fee) assert_ok!(ChargeAssetTxPayment::::post_dispatch( - Some(pre), + pre, &info_from_pays(Pays::No), &post_info_from_pays(Pays::Yes), len, - &Ok(()) - )); - assert_eq!(Assets::balance(asset_id, caller), balance); - }); -} - -#[test] -fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() { - let base_weight = 1; - ExtBuilder::default() - .balance_factor(100) - .base_weight(Weight::from_parts(base_weight, 0)) - .build() - .execute_with(|| { - // create the asset - let asset_id = 1; - let min_balance = 100; - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - 42, /* owner */ - true, /* is_sufficient */ - min_balance - )); - - // mint into the caller account - let caller = 333; - let beneficiary = ::Lookup::unlookup(caller); - let balance = 100; - assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); - assert_eq!(Assets::balance(asset_id, caller), balance); - let weight = 1; - let len = 1; - ChargeAssetTxPayment::::pre_dispatch_unsigned( - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len, - ) - .unwrap(); - - assert_eq!(Assets::balance(asset_id, caller), balance); - - // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the - // initial fee) - assert_ok!(ChargeAssetTxPayment::::post_dispatch( - None, - &info_from_weight(Weight::from_parts(weight, 0)), - &post_info_from_pays(Pays::Yes), - len, - &Ok(()) + &Ok(()), + &() )); assert_eq!(Assets::balance(asset_id, caller), balance); }); diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs new file mode 100644 index 00000000000..1af1c94177d --- /dev/null +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs @@ -0,0 +1,146 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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_asset_tx_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/production/substrate-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_asset_tx_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_asset_tx_payment`. +pub trait WeightInfo { + fn charge_asset_tx_payment_zero() -> Weight; + fn charge_asset_tx_payment_native() -> Weight; + fn charge_asset_tx_payment_asset() -> Weight; +} + +/// Weights for `pallet_asset_tx_payment` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn charge_asset_tx_payment_zero() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 542_000 picoseconds. + Weight::from_parts(597_000, 0) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_asset_tx_payment_native() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `1733` + // Minimum execution time: 33_162_000 picoseconds. + Weight::from_parts(34_716_000, 1733) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_asset_tx_payment_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `747` + // Estimated: `3675` + // Minimum execution time: 44_230_000 picoseconds. + Weight::from_parts(45_297_000, 3675) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + fn charge_asset_tx_payment_zero() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 542_000 picoseconds. + Weight::from_parts(597_000, 0) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_asset_tx_payment_native() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `1733` + // Minimum execution time: 33_162_000 picoseconds. + Weight::from_parts(34_716_000, 1733) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + } + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, 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:1 w:1) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_asset_tx_payment_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `747` + // Estimated: `3675` + // Minimum execution time: 44_230_000 picoseconds. + Weight::from_parts(45_297_000, 3675) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } +} diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs index 6c34c26ce92..9810ea08c79 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs @@ -21,7 +21,7 @@ //! //! ## Overview //! -//! It does this by wrapping an existing [`SignedExtension`] implementation (e.g. +//! It does this by wrapping an existing [`TransactionExtension`] implementation (e.g. //! [`pallet-transaction-payment`]) and checking if the dispatchable is feeless before applying the //! wrapped extension. If the dispatchable is indeed feeless, the extension is skipped and a custom //! event is emitted instead. Otherwise, the extension is applied as usual. @@ -31,7 +31,8 @@ //! //! This pallet wraps an existing transaction payment pallet. This means you should both pallets //! in your `construct_runtime` macro and include this pallet's -//! [`SignedExtension`] ([`SkipCheckIfFeeless`]) that would accept the existing one as an argument. +//! [`TransactionExtension`] ([`SkipCheckIfFeeless`]) that would accept the existing one as an +//! argument. #![cfg_attr(not(feature = "std"), no_std)] @@ -42,7 +43,10 @@ use frame_support::{ }; use scale_info::{StaticTypeInfo, TypeInfo}; use sp_runtime::{ - traits::{DispatchInfoOf, PostDispatchInfoOf, SignedExtension}, + traits::{ + DispatchInfoOf, OriginOf, PostDispatchInfoOf, TransactionExtension, + TransactionExtensionBase, ValidateResult, + }, transaction_validity::TransactionValidityError, }; @@ -70,11 +74,11 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// A transaction fee was skipped. - FeeSkipped { who: T::AccountId }, + FeeSkipped { origin: ::PalletsOrigin }, } } -/// A [`SignedExtension`] that skips the wrapped extension if the dispatchable is feeless. +/// A [`TransactionExtension`] that skips the wrapped extension if the dispatchable is feeless. #[derive(Encode, Decode, Clone, Eq, PartialEq)] pub struct SkipCheckIfFeeless(pub S, sp_std::marker::PhantomData); @@ -103,53 +107,96 @@ impl From for SkipCheckIfFeeless { } } -impl> SignedExtension +pub enum Intermediate { + /// The wrapped extension should be applied. + Apply(T), + /// The wrapped extension should be skipped. + Skip(O), +} +use Intermediate::*; + +impl TransactionExtensionBase for SkipCheckIfFeeless -where - S::Call: CheckIfFeeless>, { - type AccountId = T::AccountId; - type Call = S::Call; - type AdditionalSigned = S::AdditionalSigned; - type Pre = (Self::AccountId, Option<::Pre>); // From the outside this extension should be "invisible", because it just extends the wrapped // extension with an extra check in `pre_dispatch` and `post_dispatch`. Thus, we should forward // the identifier of the wrapped extension to let wallets see this extension as it would only be // the wrapped extension itself. const IDENTIFIER: &'static str = S::IDENTIFIER; + type Implicit = S::Implicit; + + fn implicit(&self) -> Result { + self.0.implicit() + } - fn additional_signed(&self) -> Result { - self.0.additional_signed() + fn weight(&self) -> frame_support::weights::Weight { + self.0.weight() } +} - fn pre_dispatch( +impl> + TransactionExtension for SkipCheckIfFeeless +where + T::RuntimeCall: CheckIfFeeless>, +{ + type Val = Intermediate as OriginTrait>::PalletsOrigin>; + type Pre = Intermediate as OriginTrait>::PalletsOrigin>; + + fn validate( + &self, + origin: OriginOf, + call: &T::RuntimeCall, + info: &DispatchInfoOf, + len: usize, + context: &mut Context, + self_implicit: S::Implicit, + inherited_implication: &impl Encode, + ) -> ValidateResult { + if call.is_feeless(&origin) { + Ok((Default::default(), Skip(origin.caller().clone()), origin)) + } else { + let (x, y, z) = self.0.validate( + origin, + call, + info, + len, + context, + self_implicit, + inherited_implication, + )?; + Ok((x, Apply(y), z)) + } + } + + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, + val: Self::Val, + origin: &OriginOf, + call: &T::RuntimeCall, + info: &DispatchInfoOf, len: usize, + context: &Context, ) -> Result { - if call.is_feeless(&::RuntimeOrigin::signed(who.clone())) { - Ok((who.clone(), None)) - } else { - Ok((who.clone(), Some(self.0.pre_dispatch(who, call, info, len)?))) + match val { + Apply(val) => self.0.prepare(val, origin, call, info, len, context).map(Apply), + Skip(origin) => Ok(Skip(origin)), } } fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, + context: &Context, ) -> Result<(), TransactionValidityError> { - if let Some(pre) = pre { - if let Some(pre) = pre.1 { - S::post_dispatch(Some(pre), info, post_info, len, result)?; - } else { - Pallet::::deposit_event(Event::::FeeSkipped { who: pre.0 }); - } + match pre { + Apply(pre) => S::post_dispatch(pre, info, post_info, len, result, context), + Skip(origin) => { + Pallet::::deposit_event(Event::::FeeSkipped { origin }); + Ok(()) + }, } - Ok(()) } } diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs index 17c4c773997..06948de4c3c 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs @@ -18,9 +18,12 @@ use crate as pallet_skip_feeless_payment; use frame_support::{derive_impl, parameter_types}; use frame_system as system; +use sp_runtime::{ + impl_tx_ext_default, + traits::{OriginOf, TransactionExtension}, +}; type Block = frame_system::mocking::MockBlock; -type AccountId = u64; #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Runtime { @@ -38,21 +41,22 @@ parameter_types! { #[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)] pub struct DummyExtension; -impl SignedExtension for DummyExtension { - type AccountId = AccountId; - type Call = RuntimeCall; - type AdditionalSigned = (); - type Pre = (); +impl TransactionExtensionBase for DummyExtension { const IDENTIFIER: &'static str = "DummyExtension"; - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } - fn pre_dispatch( + type Implicit = (); +} +impl TransactionExtension for DummyExtension { + type Val = (); + type Pre = (); + impl_tx_ext_default!(RuntimeCall; C; validate); + fn prepare( self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, + _val: Self::Val, + _origin: &OriginOf, + _call: &RuntimeCall, + _info: &DispatchInfoOf, _len: usize, + _context: &C, ) -> Result { PreDispatchCount::mutate(|c| *c += 1); Ok(()) diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs index 4b4dd699741..96b4af7e203 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs @@ -16,18 +16,19 @@ use super::*; use crate::mock::{pallet_dummy::Call, DummyExtension, PreDispatchCount, Runtime, RuntimeCall}; use frame_support::dispatch::DispatchInfo; +use sp_runtime::traits::DispatchTransaction; #[test] fn skip_feeless_payment_works() { let call = RuntimeCall::DummyPallet(Call::::aux { data: 1 }); SkipCheckIfFeeless::::from(DummyExtension) - .pre_dispatch(&0, &call, &DispatchInfo::default(), 0) + .validate_and_prepare(Some(0).into(), &call, &DispatchInfo::default(), 0) .unwrap(); assert_eq!(PreDispatchCount::get(), 1); let call = RuntimeCall::DummyPallet(Call::::aux { data: 0 }); SkipCheckIfFeeless::::from(DummyExtension) - .pre_dispatch(&0, &call, &DispatchInfo::default(), 0) + .validate_and_prepare(Some(0).into(), &call, &DispatchInfo::default(), 0) .unwrap(); assert_eq!(PreDispatchCount::get(), 1); } diff --git a/substrate/frame/transaction-payment/src/benchmarking.rs b/substrate/frame/transaction-payment/src/benchmarking.rs new file mode 100644 index 00000000000..d63c5a7d746 --- /dev/null +++ b/substrate/frame/transaction-payment/src/benchmarking.rs @@ -0,0 +1,81 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Benchmarks for Transaction Payment Pallet's transaction extension + +use super::*; +use crate::Pallet; +use frame_benchmarking::v2::*; +use frame_support::dispatch::{DispatchInfo, PostDispatchInfo}; +use frame_system::{EventRecord, RawOrigin}; +use sp_runtime::traits::{DispatchTransaction, Dispatchable}; + +fn assert_last_event(generic_event: ::RuntimeEvent) { + let events = frame_system::Pallet::::events(); + let system_event: ::RuntimeEvent = generic_event.into(); + // compare to the last event record + let EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); +} + +#[benchmarks(where + T: Config, + T::RuntimeCall: Dispatchable, + BalanceOf: Send + Sync + From, +)] +mod benchmarks { + use super::*; + + #[benchmark] + fn charge_transaction_payment() { + let caller: T::AccountId = whitelisted_caller(); + >::endow_account( + &caller, + >::minimum_balance() * 1000.into(), + ); + let tip = >::minimum_balance(); + let ext: ChargeTransactionPayment = ChargeTransactionPayment::from(tip); + let inner = frame_system::Call::remark { remark: vec![] }; + let call = T::RuntimeCall::from(inner); + let info = DispatchInfo { + weight: Weight::from_parts(100, 0), + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(10, 0)), + pays_fee: Pays::Yes, + }; + + #[block] + { + assert!(ext + .test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 10, |_| Ok( + post_info + )) + .unwrap() + .is_ok()); + } + + let actual_fee = Pallet::::compute_actual_fee(10, &info, &post_info, tip); + assert_last_event::( + Event::::TransactionFeePaid { who: caller, actual_fee, tip }.into(), + ); + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime); +} diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs index efadfd60bdd..6b17616bdc7 100644 --- a/substrate/frame/transaction-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/src/lib.rs @@ -62,23 +62,28 @@ pub use payment::*; use sp_runtime::{ traits::{ Convert, DispatchInfoOf, Dispatchable, One, PostDispatchInfoOf, SaturatedConversion, - Saturating, SignedExtension, Zero, + Saturating, TransactionExtension, TransactionExtensionBase, Zero, }, transaction_validity::{ - TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction, + InvalidTransaction, TransactionPriority, TransactionValidityError, ValidTransaction, }, FixedPointNumber, FixedU128, Perbill, Perquintill, RuntimeDebug, }; use sp_std::prelude::*; pub use types::{FeeDetails, InclusionFee, RuntimeDispatchInfo}; +pub use weights::WeightInfo; #[cfg(test)] mod mock; #[cfg(test)] mod tests; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + mod payment; mod types; +pub mod weights; /// Fee multiplier. pub type Multiplier = FixedU128; @@ -335,6 +340,7 @@ pub mod pallet { type RuntimeEvent = (); type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = (); + type WeightInfo = (); } } @@ -387,6 +393,9 @@ pub mod pallet { /// transactions. #[pallet::constant] type OperationalFeeMultiplier: Get; + + /// The weight information of this pallet. + type WeightInfo: WeightInfo; } #[pallet::type_value] @@ -507,11 +516,11 @@ impl Pallet { // a very very little potential gain in the future. let dispatch_info = ::get_dispatch_info(&unchecked_extrinsic); - let partial_fee = if unchecked_extrinsic.is_signed().unwrap_or(false) { - Self::compute_fee(len, &dispatch_info, 0u32.into()) - } else { - // Unsigned extrinsics have no partial fee. + let partial_fee = if unchecked_extrinsic.is_bare() { + // Bare extrinsics have no partial fee. 0u32.into() + } else { + Self::compute_fee(len, &dispatch_info, 0u32.into()) }; let DispatchInfo { weight, class, .. } = dispatch_info; @@ -531,11 +540,11 @@ impl Pallet { let tip = 0u32.into(); - if unchecked_extrinsic.is_signed().unwrap_or(false) { - Self::compute_fee_details(len, &dispatch_info, tip) - } else { - // Unsigned extrinsics have no inclusion fee. + if unchecked_extrinsic.is_bare() { + // Bare extrinsics have no inclusion fee. FeeDetails { inclusion_fee: None, tip } + } else { + Self::compute_fee_details(len, &dispatch_info, tip) } } @@ -714,7 +723,7 @@ where who: &T::AccountId, call: &T::RuntimeCall, info: &DispatchInfoOf, - len: usize, + fee: BalanceOf, ) -> Result< ( BalanceOf, @@ -723,7 +732,6 @@ where TransactionValidityError, > { let tip = self.0; - let fee = Pallet::::compute_fee(len as u32, info, tip); <::OnChargeTransaction as OnChargeTransaction>::withdraw_fee( who, call, info, fee, tip, @@ -731,6 +739,22 @@ where .map(|i| (fee, i)) } + fn can_withdraw_fee( + &self, + who: &T::AccountId, + call: &T::RuntimeCall, + info: &DispatchInfoOf, + len: usize, + ) -> Result, TransactionValidityError> { + let tip = self.0; + let fee = Pallet::::compute_fee(len as u32, info, tip); + + <::OnChargeTransaction as OnChargeTransaction>::can_withdraw_fee( + who, call, info, fee, tip, + )?; + Ok(fee) + } + /// Get an appropriate priority for a transaction with the given `DispatchInfo`, encoded length /// and user-included tip. /// @@ -817,67 +841,93 @@ impl sp_std::fmt::Debug for ChargeTransactionPayment { } } -impl SignedExtension for ChargeTransactionPayment +impl TransactionExtensionBase for ChargeTransactionPayment { + const IDENTIFIER: &'static str = "ChargeTransactionPayment"; + type Implicit = (); + + fn weight(&self) -> Weight { + T::WeightInfo::charge_transaction_payment() + } +} + +impl TransactionExtension + for ChargeTransactionPayment where BalanceOf: Send + Sync + From, T::RuntimeCall: Dispatchable, { - const IDENTIFIER: &'static str = "ChargeTransactionPayment"; - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); + type Val = ( + // tip + BalanceOf, + // who paid the fee + T::AccountId, + // computed fee + BalanceOf, + ); type Pre = ( // tip BalanceOf, - // who paid the fee - this is an option to allow for a Default impl. - Self::AccountId, + // who paid the fee + T::AccountId, // imbalance resulting from withdrawing the fee <::OnChargeTransaction as OnChargeTransaction>::LiquidityInfo, ); - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } fn validate( &self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + call: &T::RuntimeCall, + info: &DispatchInfoOf, len: usize, - ) -> TransactionValidity { - let (final_fee, _) = self.withdraw_fee(who, call, info, len)?; + _context: &mut Context, + _: (), + _implication: &impl Encode, + ) -> Result< + (ValidTransaction, Self::Val, ::RuntimeOrigin), + TransactionValidityError, + > { + let who = frame_system::ensure_signed(origin.clone()) + .map_err(|_| InvalidTransaction::BadSigner)?; + let final_fee = self.can_withdraw_fee(&who, call, info, len)?; let tip = self.0; - Ok(ValidTransaction { - priority: Self::get_priority(info, len, tip, final_fee), - ..Default::default() - }) + Ok(( + ValidTransaction { + priority: Self::get_priority(info, len, tip, final_fee), + ..Default::default() + }, + (self.0, who, final_fee), + origin, + )) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + val: Self::Val, + _origin: &::RuntimeOrigin, + call: &T::RuntimeCall, + info: &DispatchInfoOf, + _len: usize, + _context: &Context, ) -> Result { - let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?; - Ok((self.0, who.clone(), imbalance)) + let (tip, who, fee) = val; + // Mutating call to `withdraw_fee` to actually charge for the transaction. + let (_final_fee, imbalance) = self.withdraw_fee(&who, call, info, fee)?; + Ok((tip, who, imbalance)) } fn post_dispatch( - maybe_pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + (tip, who, imbalance): Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, _result: &DispatchResult, + _context: &Context, ) -> Result<(), TransactionValidityError> { - if let Some((tip, who, imbalance)) = maybe_pre { - let actual_fee = Pallet::::compute_actual_fee(len as u32, info, post_info, tip); - T::OnChargeTransaction::correct_and_deposit_fee( - &who, info, post_info, actual_fee, tip, imbalance, - )?; - Pallet::::deposit_event(Event::::TransactionFeePaid { who, actual_fee, tip }); - } + let actual_fee = Pallet::::compute_actual_fee(len as u32, info, post_info, tip); + T::OnChargeTransaction::correct_and_deposit_fee( + &who, info, post_info, actual_fee, tip, imbalance, + )?; + Pallet::::deposit_event(Event::::TransactionFeePaid { who, actual_fee, tip }); Ok(()) } } diff --git a/substrate/frame/transaction-payment/src/mock.rs b/substrate/frame/transaction-payment/src/mock.rs index 1ca2e3d7347..eda234ffcae 100644 --- a/substrate/frame/transaction-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/src/mock.rs @@ -157,4 +157,14 @@ impl Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; type FeeMultiplierUpdate = (); + type WeightInfo = (); +} + +#[cfg(feature = "runtime-benchmarks")] +pub fn new_test_ext() -> sp_io::TestExternalities { + crate::tests::ExtBuilder::default() + .base_weight(Weight::from_parts(100, 0)) + .byte_fee(10) + .balance_factor(0) + .build() } diff --git a/substrate/frame/transaction-payment/src/payment.rs b/substrate/frame/transaction-payment/src/payment.rs index 886683f2e0b..a13e73b50b0 100644 --- a/substrate/frame/transaction-payment/src/payment.rs +++ b/substrate/frame/transaction-payment/src/payment.rs @@ -20,7 +20,7 @@ use crate::Config; use core::marker::PhantomData; use sp_runtime::{ - traits::{DispatchInfoOf, PostDispatchInfoOf, Saturating, Zero}, + traits::{CheckedSub, DispatchInfoOf, PostDispatchInfoOf, Saturating, Zero}, transaction_validity::InvalidTransaction, }; @@ -51,6 +51,17 @@ pub trait OnChargeTransaction { tip: Self::Balance, ) -> Result; + /// Check if the predicted fee from the transaction origin can be withdrawn. + /// + /// Note: The `fee` already includes the `tip`. + fn can_withdraw_fee( + who: &T::AccountId, + call: &T::RuntimeCall, + dispatch_info: &DispatchInfoOf, + fee: Self::Balance, + tip: Self::Balance, + ) -> Result<(), TransactionValidityError>; + /// After the transaction was executed the actual fee can be calculated. /// This function should refund any overpaid fees and optionally deposit /// the corrected amount. @@ -64,6 +75,12 @@ pub trait OnChargeTransaction { tip: Self::Balance, already_withdrawn: Self::LiquidityInfo, ) -> Result<(), TransactionValidityError>; + + #[cfg(feature = "runtime-benchmarks")] + fn endow_account(who: &T::AccountId, amount: Self::Balance); + + #[cfg(feature = "runtime-benchmarks")] + fn minimum_balance() -> Self::Balance; } /// Implements the transaction payment for a pallet implementing the `Currency` @@ -121,6 +138,33 @@ where } } + /// Check if the predicted fee from the transaction origin can be withdrawn. + /// + /// Note: The `fee` already includes the `tip`. + fn can_withdraw_fee( + who: &T::AccountId, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, + fee: Self::Balance, + tip: Self::Balance, + ) -> Result<(), TransactionValidityError> { + if fee.is_zero() { + return Ok(()) + } + + let withdraw_reason = if tip.is_zero() { + WithdrawReasons::TRANSACTION_PAYMENT + } else { + WithdrawReasons::TRANSACTION_PAYMENT | WithdrawReasons::TIP + }; + + let new_balance = + C::free_balance(who).checked_sub(&fee).ok_or(InvalidTransaction::Payment)?; + C::ensure_can_withdraw(who, fee, withdraw_reason, new_balance) + .map(|_| ()) + .map_err(|_| InvalidTransaction::Payment.into()) + } + /// Hand the fee and the tip over to the `[OnUnbalanced]` implementation. /// Since the predicted fee might have been too high, parts of the fee may /// be refunded. @@ -153,4 +197,14 @@ where } Ok(()) } + + #[cfg(feature = "runtime-benchmarks")] + fn endow_account(who: &T::AccountId, amount: Self::Balance) { + let _ = C::deposit_creating(who, amount); + } + + #[cfg(feature = "runtime-benchmarks")] + fn minimum_balance() -> Self::Balance { + C::minimum_balance() + } } diff --git a/substrate/frame/transaction-payment/src/tests.rs b/substrate/frame/transaction-payment/src/tests.rs index d3a1721ccb9..7a49f8111e2 100644 --- a/substrate/frame/transaction-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/src/tests.rs @@ -21,11 +21,14 @@ use crate as pallet_transaction_payment; use codec::Encode; use sp_runtime::{ - testing::TestXt, traits::One, transaction_validity::InvalidTransaction, BuildStorage, + generic::UncheckedExtrinsic, + traits::{DispatchTransaction, One}, + transaction_validity::InvalidTransaction, + BuildStorage, }; use frame_support::{ - assert_noop, assert_ok, + assert_ok, dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo}, traits::Currency, weights::Weight, @@ -128,44 +131,37 @@ fn default_post_info() -> PostDispatchInfo { PostDispatchInfo { actual_weight: None, pays_fee: Default::default() } } +type Ext = ChargeTransactionPayment; + #[test] -fn signed_extension_transaction_payment_work() { +fn transaction_extension_transaction_payment_work() { ExtBuilder::default() .balance_factor(10) .base_weight(Weight::from_parts(5, 0)) .build() .execute_with(|| { - let len = 10; - let pre = ChargeTransactionPayment::::from(0) - .pre_dispatch(&1, CALL, &info_from_weight(Weight::from_parts(5, 0)), len) + let info = info_from_weight(Weight::from_parts(5, 0)); + Ext::from(0) + .test_run(Some(1).into(), CALL, &info, 10, |_| { + assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); + Ok(default_post_info()) + }) + .unwrap() .unwrap(); assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); - - assert_ok!(ChargeTransactionPayment::::post_dispatch( - Some(pre), - &info_from_weight(Weight::from_parts(5, 0)), - &default_post_info(), - len, - &Ok(()) - )); - assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); assert_eq!(FeeUnbalancedAmount::get(), 5 + 5 + 10); assert_eq!(TipUnbalancedAmount::get(), 0); FeeUnbalancedAmount::mutate(|a| *a = 0); - let pre = ChargeTransactionPayment::::from(5 /* tipped */) - .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) + let info = info_from_weight(Weight::from_parts(100, 0)); + Ext::from(5 /* tipped */) + .test_run(Some(2).into(), CALL, &info, 10, |_| { + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + Ok(post_info_from_weight(Weight::from_parts(50, 0))) + }) + .unwrap() .unwrap(); - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); - - assert_ok!(ChargeTransactionPayment::::post_dispatch( - Some(pre), - &info_from_weight(Weight::from_parts(100, 0)), - &post_info_from_weight(Weight::from_parts(50, 0)), - len, - &Ok(()) - )); assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 50 - 5); assert_eq!(FeeUnbalancedAmount::get(), 5 + 10 + 50); assert_eq!(TipUnbalancedAmount::get(), 5); @@ -173,43 +169,37 @@ fn signed_extension_transaction_payment_work() { } #[test] -fn signed_extension_transaction_payment_multiplied_refund_works() { +fn transaction_extension_transaction_payment_multiplied_refund_works() { ExtBuilder::default() .balance_factor(10) .base_weight(Weight::from_parts(5, 0)) .build() .execute_with(|| { - let len = 10; >::put(Multiplier::saturating_from_rational(3, 2)); - let pre = ChargeTransactionPayment::::from(5 /* tipped */) - .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) + let len = 10; + let origin = Some(2).into(); + let info = info_from_weight(Weight::from_parts(100, 0)); + Ext::from(5 /* tipped */) + .test_run(origin, CALL, &info, len, |_| { + // 5 base fee, 10 byte fee, 3/2 * 100 weight fee, 5 tip + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 150 - 5); + Ok(post_info_from_weight(Weight::from_parts(50, 0))) + }) + .unwrap() .unwrap(); - // 5 base fee, 10 byte fee, 3/2 * 100 weight fee, 5 tip - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 150 - 5); - - assert_ok!(ChargeTransactionPayment::::post_dispatch( - Some(pre), - &info_from_weight(Weight::from_parts(100, 0)), - &post_info_from_weight(Weight::from_parts(50, 0)), - len, - &Ok(()) - )); + // 75 (3/2 of the returned 50 units of weight) is refunded assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 75 - 5); }); } #[test] -fn signed_extension_transaction_payment_is_bounded() { +fn transaction_extension_transaction_payment_is_bounded() { ExtBuilder::default().balance_factor(1000).byte_fee(0).build().execute_with(|| { // maximum weight possible - assert_ok!(ChargeTransactionPayment::::from(0).pre_dispatch( - &1, - CALL, - &info_from_weight(Weight::MAX), - 10 - )); + let info = info_from_weight(Weight::MAX); + assert_ok!(Ext::from(0).validate_and_prepare(Some(1).into(), CALL, &info, 10)); // fee will be proportional to what is the actual maximum weight in the runtime. assert_eq!( Balances::free_balance(&1), @@ -220,7 +210,7 @@ fn signed_extension_transaction_payment_is_bounded() { } #[test] -fn signed_extension_allows_free_transactions() { +fn transaction_extension_allows_free_transactions() { ExtBuilder::default() .base_weight(Weight::from_parts(100, 0)) .balance_factor(0) @@ -232,38 +222,28 @@ fn signed_extension_allows_free_transactions() { let len = 100; // This is a completely free (and thus wholly insecure/DoS-ridden) transaction. - let operational_transaction = DispatchInfo { + let op_tx = DispatchInfo { weight: Weight::from_parts(0, 0), class: DispatchClass::Operational, pays_fee: Pays::No, }; - assert_ok!(ChargeTransactionPayment::::from(0).validate( - &1, - CALL, - &operational_transaction, - len - )); + assert_ok!(Ext::from(0).validate_only(Some(1).into(), CALL, &op_tx, len)); // like a InsecureFreeNormal - let free_transaction = DispatchInfo { + let free_tx = DispatchInfo { weight: Weight::from_parts(0, 0), class: DispatchClass::Normal, pays_fee: Pays::Yes, }; - assert_noop!( - ChargeTransactionPayment::::from(0).validate( - &1, - CALL, - &free_transaction, - len - ), + assert_eq!( + Ext::from(0).validate_only(Some(1).into(), CALL, &free_tx, len).unwrap_err(), TransactionValidityError::Invalid(InvalidTransaction::Payment), ); }); } #[test] -fn signed_ext_length_fee_is_also_updated_per_congestion() { +fn transaction_ext_length_fee_is_also_updated_per_congestion() { ExtBuilder::default() .base_weight(Weight::from_parts(5, 0)) .balance_factor(10) @@ -272,16 +252,15 @@ fn signed_ext_length_fee_is_also_updated_per_congestion() { // all fees should be x1.5 >::put(Multiplier::saturating_from_rational(3, 2)); let len = 10; - - assert_ok!(ChargeTransactionPayment::::from(10) // tipped - .pre_dispatch(&1, CALL, &info_from_weight(Weight::from_parts(3, 0)), len)); + let info = &info_from_weight(Weight::from_parts(3, 0)); + assert_ok!(Ext::from(10).validate_and_prepare(Some(1).into(), CALL, info, len)); assert_eq!( Balances::free_balance(1), 100 // original - - 10 // tip - - 5 // base - - 10 // len - - (3 * 3 / 2) // adjusted weight + - 10 // tip + - 5 // base + - 10 // len + - (3 * 3 / 2) // adjusted weight ); }) } @@ -291,62 +270,62 @@ fn query_info_and_fee_details_works() { let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 2, value: 69 }); let origin = 111111; let extra = (); - let xt = TestXt::new(call.clone(), Some((origin, extra))); + let xt = UncheckedExtrinsic::new_signed(call.clone(), origin, (), extra); let info = xt.get_dispatch_info(); let ext = xt.encode(); let len = ext.len() as u32; - let unsigned_xt = TestXt::<_, ()>::new(call, None); + let unsigned_xt = UncheckedExtrinsic::::new_bare(call); let unsigned_xt_info = unsigned_xt.get_dispatch_info(); ExtBuilder::default() - .base_weight(Weight::from_parts(5, 0)) - .weight_fee(2) - .build() - .execute_with(|| { - // all fees should be x1.5 - >::put(Multiplier::saturating_from_rational(3, 2)); - - assert_eq!( - TransactionPayment::query_info(xt.clone(), len), - RuntimeDispatchInfo { - weight: info.weight, - class: info.class, - partial_fee: 5 * 2 /* base * weight_fee */ - + len as u64 /* len * 1 */ - + info.weight.min(BlockWeights::get().max_block).ref_time() as u64 * 2 * 3 / 2 /* weight */ - }, - ); - - assert_eq!( - TransactionPayment::query_info(unsigned_xt.clone(), len), - RuntimeDispatchInfo { - weight: unsigned_xt_info.weight, - class: unsigned_xt_info.class, - partial_fee: 0, - }, - ); - - assert_eq!( - TransactionPayment::query_fee_details(xt, len), - FeeDetails { - inclusion_fee: Some(InclusionFee { - base_fee: 5 * 2, - len_fee: len as u64, - adjusted_weight_fee: info - .weight - .min(BlockWeights::get().max_block) - .ref_time() as u64 * 2 * 3 / 2 - }), - tip: 0, - }, - ); - - assert_eq!( - TransactionPayment::query_fee_details(unsigned_xt, len), - FeeDetails { inclusion_fee: None, tip: 0 }, - ); - }); + .base_weight(Weight::from_parts(5, 0)) + .weight_fee(2) + .build() + .execute_with(|| { + // all fees should be x1.5 + >::put(Multiplier::saturating_from_rational(3, 2)); + + assert_eq!( + TransactionPayment::query_info(xt.clone(), len), + RuntimeDispatchInfo { + weight: info.weight, + class: info.class, + partial_fee: 5 * 2 /* base * weight_fee */ + + len as u64 /* len * 1 */ + + info.weight.min(BlockWeights::get().max_block).ref_time() as u64 * 2 * 3 / 2 /* weight */ + }, + ); + + assert_eq!( + TransactionPayment::query_info(unsigned_xt.clone(), len), + RuntimeDispatchInfo { + weight: unsigned_xt_info.weight, + class: unsigned_xt_info.class, + partial_fee: 0, + }, + ); + + assert_eq!( + TransactionPayment::query_fee_details(xt, len), + FeeDetails { + inclusion_fee: Some(InclusionFee { + base_fee: 5 * 2, + len_fee: len as u64, + adjusted_weight_fee: info + .weight + .min(BlockWeights::get().max_block) + .ref_time() as u64 * 2 * 3 / 2 + }), + tip: 0, + }, + ); + + assert_eq!( + TransactionPayment::query_fee_details(unsigned_xt, len), + FeeDetails { inclusion_fee: None, tip: 0 }, + ); + }); } #[test] @@ -357,39 +336,39 @@ fn query_call_info_and_fee_details_works() { let len = encoded_call.len() as u32; ExtBuilder::default() - .base_weight(Weight::from_parts(5, 0)) - .weight_fee(2) - .build() - .execute_with(|| { - // all fees should be x1.5 - >::put(Multiplier::saturating_from_rational(3, 2)); - - assert_eq!( - TransactionPayment::query_call_info(call.clone(), len), - RuntimeDispatchInfo { - weight: info.weight, - class: info.class, - partial_fee: 5 * 2 /* base * weight_fee */ - + len as u64 /* len * 1 */ - + info.weight.min(BlockWeights::get().max_block).ref_time() as u64 * 2 * 3 / 2 /* weight */ - }, - ); - - assert_eq!( - TransactionPayment::query_call_fee_details(call, len), - FeeDetails { - inclusion_fee: Some(InclusionFee { - base_fee: 5 * 2, /* base * weight_fee */ - len_fee: len as u64, /* len * 1 */ - adjusted_weight_fee: info - .weight - .min(BlockWeights::get().max_block) - .ref_time() as u64 * 2 * 3 / 2 /* weight * weight_fee * multipler */ - }), - tip: 0, - }, - ); - }); + .base_weight(Weight::from_parts(5, 0)) + .weight_fee(2) + .build() + .execute_with(|| { + // all fees should be x1.5 + >::put(Multiplier::saturating_from_rational(3, 2)); + + assert_eq!( + TransactionPayment::query_call_info(call.clone(), len), + RuntimeDispatchInfo { + weight: info.weight, + class: info.class, + partial_fee: 5 * 2 /* base * weight_fee */ + + len as u64 /* len * 1 */ + + info.weight.min(BlockWeights::get().max_block).ref_time() as u64 * 2 * 3 / 2 /* weight */ + }, + ); + + assert_eq!( + TransactionPayment::query_call_fee_details(call, len), + FeeDetails { + inclusion_fee: Some(InclusionFee { + base_fee: 5 * 2, /* base * weight_fee */ + len_fee: len as u64, /* len * 1 */ + adjusted_weight_fee: info + .weight + .min(BlockWeights::get().max_block) + .ref_time() as u64 * 2 * 3 / 2 /* weight * weight_fee * multipler */ + }), + tip: 0, + }, + ); + }); } #[test] @@ -526,27 +505,23 @@ fn refund_does_not_recreate_account() { .execute_with(|| { // So events are emitted System::set_block_number(10); - let len = 10; - let pre = ChargeTransactionPayment::::from(5 /* tipped */) - .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) + let info = info_from_weight(Weight::from_parts(100, 0)); + Ext::from(5 /* tipped */) + .test_run(Some(2).into(), CALL, &info, 10, |origin| { + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + + // kill the account between pre and post dispatch + assert_ok!(Balances::transfer_allow_death( + origin, + 3, + Balances::free_balance(2) + )); + assert_eq!(Balances::free_balance(2), 0); + + Ok(post_info_from_weight(Weight::from_parts(50, 0))) + }) + .unwrap() .unwrap(); - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); - - // kill the account between pre and post dispatch - assert_ok!(Balances::transfer_allow_death( - Some(2).into(), - 3, - Balances::free_balance(2) - )); - assert_eq!(Balances::free_balance(2), 0); - - assert_ok!(ChargeTransactionPayment::::post_dispatch( - Some(pre), - &info_from_weight(Weight::from_parts(100, 0)), - &post_info_from_weight(Weight::from_parts(50, 0)), - len, - &Ok(()) - )); assert_eq!(Balances::free_balance(2), 0); // Transfer Event System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Transfer { @@ -568,20 +543,15 @@ fn actual_weight_higher_than_max_refunds_nothing() { .base_weight(Weight::from_parts(5, 0)) .build() .execute_with(|| { - let len = 10; - let pre = ChargeTransactionPayment::::from(5 /* tipped */) - .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) + let info = info_from_weight(Weight::from_parts(100, 0)); + Ext::from(5 /* tipped */) + .test_run(Some(2).into(), CALL, &info, 10, |_| { + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + Ok(post_info_from_weight(Weight::from_parts(101, 0))) + }) + .unwrap() .unwrap(); assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); - - assert_ok!(ChargeTransactionPayment::::post_dispatch( - Some(pre), - &info_from_weight(Weight::from_parts(100, 0)), - &post_info_from_weight(Weight::from_parts(101, 0)), - len, - &Ok(()) - )); - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); }); } @@ -594,25 +564,20 @@ fn zero_transfer_on_free_transaction() { .execute_with(|| { // So events are emitted System::set_block_number(10); - let len = 10; - let dispatch_info = DispatchInfo { + let info = DispatchInfo { weight: Weight::from_parts(100, 0), pays_fee: Pays::No, class: DispatchClass::Normal, }; let user = 69; - let pre = ChargeTransactionPayment::::from(0) - .pre_dispatch(&user, CALL, &dispatch_info, len) + Ext::from(0) + .test_run(Some(user).into(), CALL, &info, 10, |_| { + assert_eq!(Balances::total_balance(&user), 0); + Ok(default_post_info()) + }) + .unwrap() .unwrap(); assert_eq!(Balances::total_balance(&user), 0); - assert_ok!(ChargeTransactionPayment::::post_dispatch( - Some(pre), - &dispatch_info, - &default_post_info(), - len, - &Ok(()) - )); - assert_eq!(Balances::total_balance(&user), 0); // TransactionFeePaid Event System::assert_has_event(RuntimeEvent::TransactionPayment( pallet_transaction_payment::Event::TransactionFeePaid { @@ -639,19 +604,11 @@ fn refund_consistent_with_actual_weight() { >::put(Multiplier::saturating_from_rational(5, 4)); - let pre = ChargeTransactionPayment::::from(tip) - .pre_dispatch(&2, CALL, &info, len) + Ext::from(tip) + .test_run(Some(2).into(), CALL, &info, len, |_| Ok(post_info)) + .unwrap() .unwrap(); - ChargeTransactionPayment::::post_dispatch( - Some(pre), - &info, - &post_info, - len, - &Ok(()), - ) - .unwrap(); - let refund_based_fee = prev_balance - Balances::free_balance(2); let actual_fee = Pallet::::compute_actual_fee(len as u32, &info, &post_info, tip); @@ -673,18 +630,13 @@ fn should_alter_operational_priority() { class: DispatchClass::Normal, pays_fee: Pays::Yes, }; - let priority = ChargeTransactionPayment::(tip) - .validate(&2, CALL, &normal, len) - .unwrap() - .priority; + let ext = Ext::from(tip); + let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; assert_eq!(priority, 60); - let priority = ChargeTransactionPayment::(2 * tip) - .validate(&2, CALL, &normal, len) - .unwrap() - .priority; - + let ext = Ext::from(2 * tip); + let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; assert_eq!(priority, 110); }); @@ -694,16 +646,13 @@ fn should_alter_operational_priority() { class: DispatchClass::Operational, pays_fee: Pays::Yes, }; - let priority = ChargeTransactionPayment::(tip) - .validate(&2, CALL, &op, len) - .unwrap() - .priority; + + let ext = Ext::from(tip); + let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; assert_eq!(priority, 5810); - let priority = ChargeTransactionPayment::(2 * tip) - .validate(&2, CALL, &op, len) - .unwrap() - .priority; + let ext = Ext::from(2 * tip); + let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; assert_eq!(priority, 6110); }); } @@ -719,11 +668,8 @@ fn no_tip_has_some_priority() { class: DispatchClass::Normal, pays_fee: Pays::Yes, }; - let priority = ChargeTransactionPayment::(tip) - .validate(&2, CALL, &normal, len) - .unwrap() - .priority; - + let ext = Ext::from(tip); + let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; assert_eq!(priority, 10); }); @@ -733,10 +679,8 @@ fn no_tip_has_some_priority() { class: DispatchClass::Operational, pays_fee: Pays::Yes, }; - let priority = ChargeTransactionPayment::(tip) - .validate(&2, CALL, &op, len) - .unwrap() - .priority; + let ext = Ext::from(tip); + let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; assert_eq!(priority, 5510); }); } @@ -744,8 +688,8 @@ fn no_tip_has_some_priority() { #[test] fn higher_tip_have_higher_priority() { let get_priorities = |tip: u64| { - let mut priority1 = 0; - let mut priority2 = 0; + let mut pri1 = 0; + let mut pri2 = 0; let len = 10; ExtBuilder::default().balance_factor(100).build().execute_with(|| { let normal = DispatchInfo { @@ -753,10 +697,8 @@ fn higher_tip_have_higher_priority() { class: DispatchClass::Normal, pays_fee: Pays::Yes, }; - priority1 = ChargeTransactionPayment::(tip) - .validate(&2, CALL, &normal, len) - .unwrap() - .priority; + let ext = Ext::from(tip); + pri1 = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; }); ExtBuilder::default().balance_factor(100).build().execute_with(|| { @@ -765,13 +707,11 @@ fn higher_tip_have_higher_priority() { class: DispatchClass::Operational, pays_fee: Pays::Yes, }; - priority2 = ChargeTransactionPayment::(tip) - .validate(&2, CALL, &op, len) - .unwrap() - .priority; + let ext = Ext::from(tip); + pri2 = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; }); - (priority1, priority2) + (pri1, pri2) }; let mut prev_priorities = get_priorities(0); @@ -799,19 +739,11 @@ fn post_info_can_change_pays_fee() { >::put(Multiplier::saturating_from_rational(5, 4)); - let pre = ChargeTransactionPayment::::from(tip) - .pre_dispatch(&2, CALL, &info, len) + let post_info = ChargeTransactionPayment::::from(tip) + .test_run(Some(2).into(), CALL, &info, len, |_| Ok(post_info)) + .unwrap() .unwrap(); - ChargeTransactionPayment::::post_dispatch( - Some(pre), - &info, - &post_info, - len, - &Ok(()), - ) - .unwrap(); - let refund_based_fee = prev_balance - Balances::free_balance(2); let actual_fee = Pallet::::compute_actual_fee(len as u32, &info, &post_info, tip); diff --git a/substrate/frame/transaction-payment/src/types.rs b/substrate/frame/transaction-payment/src/types.rs index 25cecc58a63..bfb3012fef0 100644 --- a/substrate/frame/transaction-payment/src/types.rs +++ b/substrate/frame/transaction-payment/src/types.rs @@ -112,7 +112,7 @@ pub struct RuntimeDispatchInfo /// The inclusion fee of this dispatch. /// /// This does not include a tip or anything else that - /// depends on the signature (i.e. depends on a `SignedExtension`). + /// depends on the signature (i.e. depends on a `TransactionExtension`). #[cfg_attr(feature = "std", serde(with = "serde_balance"))] pub partial_fee: Balance, } diff --git a/substrate/frame/transaction-payment/src/weights.rs b/substrate/frame/transaction-payment/src/weights.rs new file mode 100644 index 00000000000..bcffb2eb331 --- /dev/null +++ b/substrate/frame/transaction-payment/src/weights.rs @@ -0,0 +1,92 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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_transaction_payment` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/production/substrate-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_transaction_payment +// --no-storage-info +// --no-median-slopes +// --no-min-squares +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./substrate/frame/transaction-payment/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_transaction_payment`. +pub trait WeightInfo { + fn charge_transaction_payment() -> Weight; +} + +/// Weights for `pallet_transaction_payment` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `1733` + // Minimum execution time: 40_506_000 picoseconds. + Weight::from_parts(41_647_000, 1733) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) + /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Authorship::Author` (r:1 w:0) + /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `System::Digest` (r:1 w:0) + /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn charge_transaction_payment() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `1733` + // Minimum execution time: 40_506_000 picoseconds. + Weight::from_parts(41_647_000, 1733) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + } +} diff --git a/substrate/frame/transaction-storage/src/weights.rs b/substrate/frame/transaction-storage/src/weights.rs index 519317177c4..bfbed62c5a3 100644 --- a/substrate/frame/transaction-storage/src/weights.rs +++ b/substrate/frame/transaction-storage/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_transaction_storage +//! Autogenerated weights for `pallet_transaction_storage` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/transaction-storage/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/transaction-storage/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,125 +49,133 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_transaction_storage. +/// Weight functions needed for `pallet_transaction_storage`. pub trait WeightInfo { fn store(l: u32, ) -> Weight; fn renew() -> Weight; fn check_proof_max() -> Weight; } -/// Weights for pallet_transaction_storage using the Substrate node and recommended hardware. +/// Weights for `pallet_transaction_storage` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: TransactionStorage ByteFee (r:1 w:0) - /// Proof: TransactionStorage ByteFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: TransactionStorage EntryFee (r:1 w:0) - /// Proof: TransactionStorage EntryFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: TransactionStorage BlockTransactions (r:1 w:1) - /// Proof: TransactionStorage BlockTransactions (max_values: Some(1), max_size: Some(36866), added: 37361, mode: MaxEncodedLen) + /// Storage: `TransactionStorage::ByteFee` (r:1 w:0) + /// Proof: `TransactionStorage::ByteFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::EntryFee` (r:1 w:0) + /// Proof: `TransactionStorage::EntryFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::BlockTransactions` (r:1 w:1) + /// Proof: `TransactionStorage::BlockTransactions` (`max_values`: Some(1), `max_size`: Some(36866), added: 37361, mode: `MaxEncodedLen`) /// The range of component `l` is `[1, 8388608]`. fn store(l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `176` + // Measured: `242` // Estimated: `38351` - // Minimum execution time: 34_844_000 picoseconds. - Weight::from_parts(35_489_000, 38351) + // Minimum execution time: 57_912_000 picoseconds. + Weight::from_parts(58_642_000, 38351) // Standard Error: 11 - .saturating_add(Weight::from_parts(6_912, 0).saturating_mul(l.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(Weight::from_parts(6_778, 0).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: TransactionStorage Transactions (r:1 w:0) - /// Proof: TransactionStorage Transactions (max_values: None, max_size: Some(36886), added: 39361, mode: MaxEncodedLen) - /// Storage: TransactionStorage ByteFee (r:1 w:0) - /// Proof: TransactionStorage ByteFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: TransactionStorage EntryFee (r:1 w:0) - /// Proof: TransactionStorage EntryFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: TransactionStorage BlockTransactions (r:1 w:1) - /// Proof: TransactionStorage BlockTransactions (max_values: Some(1), max_size: Some(36866), added: 37361, mode: MaxEncodedLen) + /// Storage: `TransactionStorage::Transactions` (r:1 w:0) + /// Proof: `TransactionStorage::Transactions` (`max_values`: None, `max_size`: Some(36886), added: 39361, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::ByteFee` (r:1 w:0) + /// Proof: `TransactionStorage::ByteFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::EntryFee` (r:1 w:0) + /// Proof: `TransactionStorage::EntryFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::BlockTransactions` (r:1 w:1) + /// Proof: `TransactionStorage::BlockTransactions` (`max_values`: Some(1), `max_size`: Some(36866), added: 37361, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `326` + // Measured: `430` // Estimated: `40351` - // Minimum execution time: 48_244_000 picoseconds. - Weight::from_parts(50_939_000, 40351) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 72_571_000 picoseconds. + Weight::from_parts(74_832_000, 40351) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: TransactionStorage ProofChecked (r:1 w:1) - /// Proof: TransactionStorage ProofChecked (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: TransactionStorage StoragePeriod (r:1 w:0) - /// Proof: TransactionStorage StoragePeriod (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: TransactionStorage ChunkCount (r:1 w:0) - /// Proof: TransactionStorage ChunkCount (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen) - /// Storage: System ParentHash (r:1 w:0) - /// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TransactionStorage Transactions (r:1 w:0) - /// Proof: TransactionStorage Transactions (max_values: None, max_size: Some(36886), added: 39361, mode: MaxEncodedLen) + /// Storage: `TransactionStorage::ProofChecked` (r:1 w:1) + /// Proof: `TransactionStorage::ProofChecked` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::StoragePeriod` (r:1 w:0) + /// Proof: `TransactionStorage::StoragePeriod` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::ChunkCount` (r:1 w:0) + /// Proof: `TransactionStorage::ChunkCount` (`max_values`: None, `max_size`: Some(24), added: 2499, mode: `MaxEncodedLen`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::Transactions` (r:1 w:0) + /// Proof: `TransactionStorage::Transactions` (`max_values`: None, `max_size`: Some(36886), added: 39361, mode: `MaxEncodedLen`) fn check_proof_max() -> Weight { // Proof Size summary in bytes: - // Measured: `37145` + // Measured: `37211` // Estimated: `40351` - // Minimum execution time: 80_913_000 picoseconds. - Weight::from_parts(84_812_000, 40351) + // Minimum execution time: 65_985_000 picoseconds. + Weight::from_parts(72_960_000, 40351) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: TransactionStorage ByteFee (r:1 w:0) - /// Proof: TransactionStorage ByteFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: TransactionStorage EntryFee (r:1 w:0) - /// Proof: TransactionStorage EntryFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: TransactionStorage BlockTransactions (r:1 w:1) - /// Proof: TransactionStorage BlockTransactions (max_values: Some(1), max_size: Some(36866), added: 37361, mode: MaxEncodedLen) + /// Storage: `TransactionStorage::ByteFee` (r:1 w:0) + /// Proof: `TransactionStorage::ByteFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::EntryFee` (r:1 w:0) + /// Proof: `TransactionStorage::EntryFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::BlockTransactions` (r:1 w:1) + /// Proof: `TransactionStorage::BlockTransactions` (`max_values`: Some(1), `max_size`: Some(36866), added: 37361, mode: `MaxEncodedLen`) /// The range of component `l` is `[1, 8388608]`. fn store(l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `176` + // Measured: `242` // Estimated: `38351` - // Minimum execution time: 34_844_000 picoseconds. - Weight::from_parts(35_489_000, 38351) + // Minimum execution time: 57_912_000 picoseconds. + Weight::from_parts(58_642_000, 38351) // Standard Error: 11 - .saturating_add(Weight::from_parts(6_912, 0).saturating_mul(l.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(Weight::from_parts(6_778, 0).saturating_mul(l.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: TransactionStorage Transactions (r:1 w:0) - /// Proof: TransactionStorage Transactions (max_values: None, max_size: Some(36886), added: 39361, mode: MaxEncodedLen) - /// Storage: TransactionStorage ByteFee (r:1 w:0) - /// Proof: TransactionStorage ByteFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: TransactionStorage EntryFee (r:1 w:0) - /// Proof: TransactionStorage EntryFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: TransactionStorage BlockTransactions (r:1 w:1) - /// Proof: TransactionStorage BlockTransactions (max_values: Some(1), max_size: Some(36866), added: 37361, mode: MaxEncodedLen) + /// Storage: `TransactionStorage::Transactions` (r:1 w:0) + /// Proof: `TransactionStorage::Transactions` (`max_values`: None, `max_size`: Some(36886), added: 39361, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::ByteFee` (r:1 w:0) + /// Proof: `TransactionStorage::ByteFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::EntryFee` (r:1 w:0) + /// Proof: `TransactionStorage::EntryFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::BlockTransactions` (r:1 w:1) + /// Proof: `TransactionStorage::BlockTransactions` (`max_values`: Some(1), `max_size`: Some(36866), added: 37361, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `326` + // Measured: `430` // Estimated: `40351` - // Minimum execution time: 48_244_000 picoseconds. - Weight::from_parts(50_939_000, 40351) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 72_571_000 picoseconds. + Weight::from_parts(74_832_000, 40351) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: TransactionStorage ProofChecked (r:1 w:1) - /// Proof: TransactionStorage ProofChecked (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: TransactionStorage StoragePeriod (r:1 w:0) - /// Proof: TransactionStorage StoragePeriod (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: TransactionStorage ChunkCount (r:1 w:0) - /// Proof: TransactionStorage ChunkCount (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen) - /// Storage: System ParentHash (r:1 w:0) - /// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: TransactionStorage Transactions (r:1 w:0) - /// Proof: TransactionStorage Transactions (max_values: None, max_size: Some(36886), added: 39361, mode: MaxEncodedLen) + /// Storage: `TransactionStorage::ProofChecked` (r:1 w:1) + /// Proof: `TransactionStorage::ProofChecked` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::StoragePeriod` (r:1 w:0) + /// Proof: `TransactionStorage::StoragePeriod` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::ChunkCount` (r:1 w:0) + /// Proof: `TransactionStorage::ChunkCount` (`max_values`: None, `max_size`: Some(24), added: 2499, mode: `MaxEncodedLen`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `TransactionStorage::Transactions` (r:1 w:0) + /// Proof: `TransactionStorage::Transactions` (`max_values`: None, `max_size`: Some(36886), added: 39361, mode: `MaxEncodedLen`) fn check_proof_max() -> Weight { // Proof Size summary in bytes: - // Measured: `37145` + // Measured: `37211` // Estimated: `40351` - // Minimum execution time: 80_913_000 picoseconds. - Weight::from_parts(84_812_000, 40351) + // Minimum execution time: 65_985_000 picoseconds. + Weight::from_parts(72_960_000, 40351) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/treasury/src/weights.rs b/substrate/frame/treasury/src/weights.rs index 030e18980eb..8ef4f89fd65 100644 --- a/substrate/frame/treasury/src/weights.rs +++ b/substrate/frame/treasury/src/weights.rs @@ -15,27 +15,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_treasury +//! Autogenerated weights for `pallet_treasury` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-07, STEPS: `20`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `cob`, CPU: `` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/debug/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev -// --steps=20 -// --repeat=2 -// --pallet=pallet-treasury +// --steps=50 +// --repeat=20 +// --pallet=pallet_treasury +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/treasury/src/._weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/treasury/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -45,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_treasury. +/// Weight functions needed for `pallet_treasury`. pub trait WeightInfo { fn spend_local() -> Weight; fn propose_spend() -> Weight; @@ -59,304 +63,304 @@ pub trait WeightInfo { fn void_spend() -> Weight; } -/// Weights for pallet_treasury using the Substrate node and recommended hardware. +/// Weights for `pallet_treasury` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Treasury ProposalCount (r:1 w:1) - /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:0 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: `Treasury::ProposalCount` (r:1 w:1) + /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:0 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn spend_local() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1887` - // Minimum execution time: 179_000_000 picoseconds. - Weight::from_parts(190_000_000, 1887) + // Minimum execution time: 11_686_000 picoseconds. + Weight::from_parts(12_138_000, 1887) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: Treasury ProposalCount (r:1 w:1) - /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:0 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: `Treasury::ProposalCount` (r:1 w:1) + /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:0 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn propose_spend() -> Weight { // Proof Size summary in bytes: // Measured: `177` // Estimated: `1489` - // Minimum execution time: 349_000_000 picoseconds. - Weight::from_parts(398_000_000, 1489) + // Minimum execution time: 23_773_000 picoseconds. + Weight::from_parts(24_801_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Treasury Proposals (r:1 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Treasury::Proposals` (r:1 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn reject_proposal() -> Weight { // Proof Size summary in bytes: // Measured: `335` // Estimated: `3593` - // Minimum execution time: 367_000_000 picoseconds. - Weight::from_parts(388_000_000, 3593) + // Minimum execution time: 24_533_000 picoseconds. + Weight::from_parts(25_731_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Treasury Proposals (r:1 w:0) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Proposals` (r:1 w:0) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `483 + p * (9 ±0)` + // Measured: `504 + p * (8 ±0)` // Estimated: `3573` - // Minimum execution time: 111_000_000 picoseconds. - Weight::from_parts(108_813_243, 3573) - // Standard Error: 147_887 - .saturating_add(Weight::from_parts(683_216, 0).saturating_mul(p.into())) + // Minimum execution time: 8_245_000 picoseconds. + Weight::from_parts(11_300_222, 3573) + // Standard Error: 1_080 + .saturating_add(Weight::from_parts(71_375, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn remove_approval() -> Weight { // Proof Size summary in bytes: // Measured: `161` // Estimated: `1887` - // Minimum execution time: 71_000_000 picoseconds. - Weight::from_parts(78_000_000, 1887) + // Minimum execution time: 6_231_000 picoseconds. + Weight::from_parts(6_517_000, 1887) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Treasury Deactivated (r:1 w:1) - /// Proof: Treasury Deactivated (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:99 w:99) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: System Account (r:198 w:198) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyApprovals (r:1 w:1) - /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Deactivated` (r:1 w:1) + /// Proof: `Treasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:99 w:99) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:198 w:198) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 99]`. fn on_initialize_proposals(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `427 + p * (251 ±0)` + // Measured: `451 + p * (251 ±0)` // Estimated: `1887 + p * (5206 ±0)` - // Minimum execution time: 614_000_000 picoseconds. - Weight::from_parts(498_501_558, 1887) - // Standard Error: 1_070_260 - .saturating_add(Weight::from_parts(599_011_690, 0).saturating_mul(p.into())) + // Minimum execution time: 30_729_000 picoseconds. + Weight::from_parts(37_861_389, 1887) + // Standard Error: 18_741 + .saturating_add(Weight::from_parts(31_377_118, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(p.into())) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:0) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) - /// Storage: Treasury SpendCount (r:1 w:1) - /// Proof: Treasury SpendCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Spends (r:0 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:0) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Treasury::SpendCount` (r:1 w:1) + /// Proof: `Treasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Spends` (r:0 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn spend() -> Weight { // Proof Size summary in bytes: // Measured: `140` // Estimated: `3501` - // Minimum execution time: 214_000_000 picoseconds. - Weight::from_parts(216_000_000, 3501) + // Minimum execution time: 13_700_000 picoseconds. + Weight::from_parts(14_519_000, 3501) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn payout() -> Weight { // Proof Size summary in bytes: - // Measured: `705` + // Measured: `709` // Estimated: `6208` - // Minimum execution time: 760_000_000 picoseconds. - Weight::from_parts(822_000_000, 6208) + // Minimum execution time: 54_888_000 picoseconds. + Weight::from_parts(55_966_000, 6208) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn check_status() -> Weight { // Proof Size summary in bytes: - // Measured: `194` - // Estimated: `3534` - // Minimum execution time: 153_000_000 picoseconds. - Weight::from_parts(160_000_000, 3534) + // Measured: `198` + // Estimated: `3538` + // Minimum execution time: 11_802_000 picoseconds. + Weight::from_parts(12_421_000, 3538) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn void_spend() -> Weight { // Proof Size summary in bytes: - // Measured: `194` - // Estimated: `3534` - // Minimum execution time: 147_000_000 picoseconds. - Weight::from_parts(181_000_000, 3534) + // Measured: `198` + // Estimated: `3538` + // Minimum execution time: 10_571_000 picoseconds. + Weight::from_parts(11_052_000, 3538) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Treasury ProposalCount (r:1 w:1) - /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:0 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: `Treasury::ProposalCount` (r:1 w:1) + /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:0 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn spend_local() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1887` - // Minimum execution time: 179_000_000 picoseconds. - Weight::from_parts(190_000_000, 1887) + // Minimum execution time: 11_686_000 picoseconds. + Weight::from_parts(12_138_000, 1887) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: Treasury ProposalCount (r:1 w:1) - /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:0 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: `Treasury::ProposalCount` (r:1 w:1) + /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:0 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn propose_spend() -> Weight { // Proof Size summary in bytes: // Measured: `177` // Estimated: `1489` - // Minimum execution time: 349_000_000 picoseconds. - Weight::from_parts(398_000_000, 1489) + // Minimum execution time: 23_773_000 picoseconds. + Weight::from_parts(24_801_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Treasury Proposals (r:1 w:1) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Treasury::Proposals` (r:1 w:1) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn reject_proposal() -> Weight { // Proof Size summary in bytes: // Measured: `335` // Estimated: `3593` - // Minimum execution time: 367_000_000 picoseconds. - Weight::from_parts(388_000_000, 3593) + // Minimum execution time: 24_533_000 picoseconds. + Weight::from_parts(25_731_000, 3593) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Treasury Proposals (r:1 w:0) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Proposals` (r:1 w:0) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `483 + p * (9 ±0)` + // Measured: `504 + p * (8 ±0)` // Estimated: `3573` - // Minimum execution time: 111_000_000 picoseconds. - Weight::from_parts(108_813_243, 3573) - // Standard Error: 147_887 - .saturating_add(Weight::from_parts(683_216, 0).saturating_mul(p.into())) + // Minimum execution time: 8_245_000 picoseconds. + Weight::from_parts(11_300_222, 3573) + // Standard Error: 1_080 + .saturating_add(Weight::from_parts(71_375, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn remove_approval() -> Weight { // Proof Size summary in bytes: // Measured: `161` // Estimated: `1887` - // Minimum execution time: 71_000_000 picoseconds. - Weight::from_parts(78_000_000, 1887) + // Minimum execution time: 6_231_000 picoseconds. + Weight::from_parts(6_517_000, 1887) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Treasury Deactivated (r:1 w:1) - /// Proof: Treasury Deactivated (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) - /// Storage: Treasury Approvals (r:1 w:1) - /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) - /// Storage: Treasury Proposals (r:99 w:99) - /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) - /// Storage: System Account (r:198 w:198) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Bounties BountyApprovals (r:1 w:1) - /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: `Treasury::Deactivated` (r:1 w:1) + /// Proof: `Treasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Approvals` (r:1 w:1) + /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Proposals` (r:99 w:99) + /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:198 w:198) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyApprovals` (r:1 w:1) + /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) /// The range of component `p` is `[0, 99]`. fn on_initialize_proposals(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `427 + p * (251 ±0)` + // Measured: `451 + p * (251 ±0)` // Estimated: `1887 + p * (5206 ±0)` - // Minimum execution time: 614_000_000 picoseconds. - Weight::from_parts(498_501_558, 1887) - // Standard Error: 1_070_260 - .saturating_add(Weight::from_parts(599_011_690, 0).saturating_mul(p.into())) + // Minimum execution time: 30_729_000 picoseconds. + Weight::from_parts(37_861_389, 1887) + // Standard Error: 18_741 + .saturating_add(Weight::from_parts(31_377_118, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(p.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(p.into())) } - /// Storage: AssetRate ConversionRateToNative (r:1 w:0) - /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) - /// Storage: Treasury SpendCount (r:1 w:1) - /// Proof: Treasury SpendCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Treasury Spends (r:0 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:0) + /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Treasury::SpendCount` (r:1 w:1) + /// Proof: `Treasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Treasury::Spends` (r:0 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn spend() -> Weight { // Proof Size summary in bytes: // Measured: `140` // Estimated: `3501` - // Minimum execution time: 214_000_000 picoseconds. - Weight::from_parts(216_000_000, 3501) + // Minimum execution time: 13_700_000 picoseconds. + Weight::from_parts(14_519_000, 3501) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, 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:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, 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:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn payout() -> Weight { // Proof Size summary in bytes: - // Measured: `705` + // Measured: `709` // Estimated: `6208` - // Minimum execution time: 760_000_000 picoseconds. - Weight::from_parts(822_000_000, 6208) + // Minimum execution time: 54_888_000 picoseconds. + Weight::from_parts(55_966_000, 6208) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn check_status() -> Weight { // Proof Size summary in bytes: - // Measured: `194` - // Estimated: `3534` - // Minimum execution time: 153_000_000 picoseconds. - Weight::from_parts(160_000_000, 3534) + // Measured: `198` + // Estimated: `3538` + // Minimum execution time: 11_802_000 picoseconds. + Weight::from_parts(12_421_000, 3538) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Treasury Spends (r:1 w:1) - /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: `Treasury::Spends` (r:1 w:1) + /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn void_spend() -> Weight { // Proof Size summary in bytes: - // Measured: `194` - // Estimated: `3534` - // Minimum execution time: 147_000_000 picoseconds. - Weight::from_parts(181_000_000, 3534) + // Measured: `198` + // Estimated: `3538` + // Minimum execution time: 10_571_000 picoseconds. + Weight::from_parts(11_052_000, 3538) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/tx-pause/src/weights.rs b/substrate/frame/tx-pause/src/weights.rs index b733e64b159..14fead12a8e 100644 --- a/substrate/frame/tx-pause/src/weights.rs +++ b/substrate/frame/tx-pause/src/weights.rs @@ -17,27 +17,29 @@ //! Autogenerated weights for `pallet_tx_pause` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-08-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-aahe6cbd-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_tx_pause +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json -// --pallet=pallet_tx_pause -// --chain=dev -// --header=./HEADER-APACHE2 -// --output=./frame/tx-pause/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/tx-pause/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -62,8 +64,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3` // Estimated: `3997` - // Minimum execution time: 15_096_000 picoseconds. - Weight::from_parts(15_437_000, 3997) + // Minimum execution time: 12_014_000 picoseconds. + Weight::from_parts(12_980_000, 3997) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -73,8 +75,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `565` // Estimated: `3997` - // Minimum execution time: 21_546_000 picoseconds. - Weight::from_parts(22_178_000, 3997) + // Minimum execution time: 17_955_000 picoseconds. + Weight::from_parts(18_348_000, 3997) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -88,8 +90,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3` // Estimated: `3997` - // Minimum execution time: 15_096_000 picoseconds. - Weight::from_parts(15_437_000, 3997) + // Minimum execution time: 12_014_000 picoseconds. + Weight::from_parts(12_980_000, 3997) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -99,8 +101,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `565` // Estimated: `3997` - // Minimum execution time: 21_546_000 picoseconds. - Weight::from_parts(22_178_000, 3997) + // Minimum execution time: 17_955_000 picoseconds. + Weight::from_parts(18_348_000, 3997) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/uniques/src/weights.rs b/substrate/frame/uniques/src/weights.rs index eb80ee550a1..6c7b60b82e5 100644 --- a/substrate/frame/uniques/src/weights.rs +++ b/substrate/frame/uniques/src/weights.rs @@ -17,27 +17,29 @@ //! Autogenerated weights for `pallet_uniques` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-gghbxkbs-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_uniques +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json -// --pallet=pallet_uniques -// --chain=dev -// --header=./HEADER-APACHE2 -// --output=./frame/uniques/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/uniques/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -88,8 +90,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `249` // Estimated: `3643` - // Minimum execution time: 31_393_000 picoseconds. - Weight::from_parts(32_933_000, 3643) + // Minimum execution time: 27_960_000 picoseconds. + Weight::from_parts(28_781_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -101,8 +103,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3643` - // Minimum execution time: 14_827_000 picoseconds. - Weight::from_parts(15_273_000, 3643) + // Minimum execution time: 11_970_000 picoseconds. + Weight::from_parts(12_512_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -111,13 +113,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Uniques::Asset` (r:1001 w:1000) /// Proof: `Uniques::Asset` (`max_values`: None, `max_size`: Some(122), added: 2597, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1000 w:1000) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1000 w:1000) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassAccount` (r:0 w:1) /// Proof: `Uniques::ClassAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:0 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) /// Storage: `Uniques::Account` (r:0 w:1000) /// Proof: `Uniques::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Uniques::CollectionMaxSupply` (r:0 w:1) @@ -128,15 +130,15 @@ impl WeightInfo for SubstrateWeight { fn destroy(n: u32, m: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `418 + a * (107 ±0) + m * (56 ±0) + n * (76 ±0)` - // Estimated: `3643 + a * (2839 ±0) + m * (2583 ±0) + n * (2597 ±0)` - // Minimum execution time: 3_281_673_000 picoseconds. - Weight::from_parts(3_443_387_000, 3643) - // Standard Error: 41_937 - .saturating_add(Weight::from_parts(7_914_842, 0).saturating_mul(n.into())) - // Standard Error: 41_937 - .saturating_add(Weight::from_parts(519_960, 0).saturating_mul(m.into())) - // Standard Error: 41_937 - .saturating_add(Weight::from_parts(462_690, 0).saturating_mul(a.into())) + // Estimated: `3643 + a * (2647 ±0) + m * (2662 ±0) + n * (2597 ±0)` + // Minimum execution time: 2_979_858_000 picoseconds. + Weight::from_parts(3_007_268_000, 3643) + // Standard Error: 29_899 + .saturating_add(Weight::from_parts(6_943_612, 0).saturating_mul(n.into())) + // Standard Error: 29_899 + .saturating_add(Weight::from_parts(398_114, 0).saturating_mul(m.into())) + // Standard Error: 29_899 + .saturating_add(Weight::from_parts(369_941, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) @@ -145,8 +147,8 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) - .saturating_add(Weight::from_parts(0, 2839).saturating_mul(a.into())) - .saturating_add(Weight::from_parts(0, 2583).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 2647).saturating_mul(a.into())) + .saturating_add(Weight::from_parts(0, 2662).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 2597).saturating_mul(n.into())) } /// Storage: `Uniques::Asset` (r:1 w:1) @@ -161,8 +163,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 38_122_000 picoseconds. - Weight::from_parts(38_924_000, 3643) + // Minimum execution time: 32_733_000 picoseconds. + Weight::from_parts(33_487_000, 3643) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -178,8 +180,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 38_835_000 picoseconds. - Weight::from_parts(39_754_000, 3643) + // Minimum execution time: 34_202_000 picoseconds. + Weight::from_parts(35_146_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -195,8 +197,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 27_032_000 picoseconds. - Weight::from_parts(27_793_000, 3643) + // Minimum execution time: 24_285_000 picoseconds. + Weight::from_parts(25_300_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -209,10 +211,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `805 + i * (76 ±0)` // Estimated: `3643 + i * (2597 ±0)` - // Minimum execution time: 14_737_000 picoseconds. - Weight::from_parts(15_070_000, 3643) - // Standard Error: 22_500 - .saturating_add(Weight::from_parts(18_855_468, 0).saturating_mul(i.into())) + // Minimum execution time: 11_641_000 picoseconds. + Weight::from_parts(12_261_000, 3643) + // Standard Error: 18_897 + .saturating_add(Weight::from_parts(15_263_570, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -227,8 +229,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 18_664_000 picoseconds. - Weight::from_parts(19_455_000, 3643) + // Minimum execution time: 16_122_000 picoseconds. + Weight::from_parts(16_627_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -240,8 +242,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 18_247_000 picoseconds. - Weight::from_parts(18_763_000, 3643) + // Minimum execution time: 15_824_000 picoseconds. + Weight::from_parts(16_522_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -251,8 +253,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 13_219_000 picoseconds. - Weight::from_parts(13_923_000, 3643) + // Minimum execution time: 10_802_000 picoseconds. + Weight::from_parts(11_206_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -262,8 +264,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 13_376_000 picoseconds. - Weight::from_parts(13_904_000, 3643) + // Minimum execution time: 10_805_000 picoseconds. + Weight::from_parts(11_340_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -271,16 +273,18 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Uniques::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassAccount` (r:0 w:2) /// Proof: `Uniques::ClassAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `423` + // Measured: `597` // Estimated: `3643` - // Minimum execution time: 22_353_000 picoseconds. - Weight::from_parts(23_222_000, 3643) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 24_213_000 picoseconds. + Weight::from_parts(25_547_000, 3643) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) @@ -288,8 +292,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 14_072_000 picoseconds. - Weight::from_parts(14_619_000, 3643) + // Minimum execution time: 11_256_000 picoseconds. + Weight::from_parts(11_585_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -301,90 +305,90 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 17_081_000 picoseconds. - Weight::from_parts(17_698_000, 3643) + // Minimum execution time: 14_616_000 picoseconds. + Weight::from_parts(15_064_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:0) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1 w:1) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `547` - // Estimated: `3829` - // Minimum execution time: 41_501_000 picoseconds. - Weight::from_parts(43_101_000, 3829) + // Measured: `626` + // Estimated: `3652` + // Minimum execution time: 35_640_000 picoseconds. + Weight::from_parts(37_007_000, 3652) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:0) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1 w:1) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `936` - // Estimated: `3829` - // Minimum execution time: 39_722_000 picoseconds. - Weight::from_parts(40_390_000, 3829) + // Measured: `823` + // Estimated: `3652` + // Minimum execution time: 34_410_000 picoseconds. + Weight::from_parts(35_431_000, 3652) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:1) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `415` - // Estimated: `3643` - // Minimum execution time: 30_726_000 picoseconds. - Weight::from_parts(31_557_000, 3643) + // Estimated: `3652` + // Minimum execution time: 26_187_000 picoseconds. + Weight::from_parts(27_837_000, 3652) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:1) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `547` - // Estimated: `3643` - // Minimum execution time: 31_303_000 picoseconds. - Weight::from_parts(32_389_000, 3643) + // Measured: `626` + // Estimated: `3652` + // Minimum execution time: 26_640_000 picoseconds. + Weight::from_parts(27_688_000, 3652) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:1 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 32_155_000 picoseconds. - Weight::from_parts(32_885_000, 3643) + // Minimum execution time: 26_781_000 picoseconds. + Weight::from_parts(27_628_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:0) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:1 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `461` + // Measured: `540` // Estimated: `3643` - // Minimum execution time: 30_044_000 picoseconds. - Weight::from_parts(31_405_000, 3643) + // Minimum execution time: 26_295_000 picoseconds. + Weight::from_parts(26_903_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -396,8 +400,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 18_904_000 picoseconds. - Weight::from_parts(19_687_000, 3643) + // Minimum execution time: 16_678_000 picoseconds. + Weight::from_parts(17_548_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -409,8 +413,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `528` // Estimated: `3643` - // Minimum execution time: 19_144_000 picoseconds. - Weight::from_parts(19_706_000, 3643) + // Minimum execution time: 16_408_000 picoseconds. + Weight::from_parts(16_957_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -420,8 +424,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3517` - // Minimum execution time: 15_339_000 picoseconds. - Weight::from_parts(15_918_000, 3517) + // Minimum execution time: 12_568_000 picoseconds. + Weight::from_parts(12_960_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -433,8 +437,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 15_387_000 picoseconds. - Weight::from_parts(15_726_000, 3643) + // Minimum execution time: 13_110_000 picoseconds. + Weight::from_parts(13_620_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -446,8 +450,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `326` // Estimated: `3587` - // Minimum execution time: 15_873_000 picoseconds. - Weight::from_parts(16_860_000, 3587) + // Minimum execution time: 13_568_000 picoseconds. + Weight::from_parts(14_211_000, 3587) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -463,8 +467,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `607` // Estimated: `3643` - // Minimum execution time: 37_245_000 picoseconds. - Weight::from_parts(38_383_000, 3643) + // Minimum execution time: 32_660_000 picoseconds. + Weight::from_parts(33_734_000, 3643) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -480,8 +484,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `249` // Estimated: `3643` - // Minimum execution time: 31_393_000 picoseconds. - Weight::from_parts(32_933_000, 3643) + // Minimum execution time: 27_960_000 picoseconds. + Weight::from_parts(28_781_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -493,8 +497,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3643` - // Minimum execution time: 14_827_000 picoseconds. - Weight::from_parts(15_273_000, 3643) + // Minimum execution time: 11_970_000 picoseconds. + Weight::from_parts(12_512_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -503,13 +507,13 @@ impl WeightInfo for () { /// Storage: `Uniques::Asset` (r:1001 w:1000) /// Proof: `Uniques::Asset` (`max_values`: None, `max_size`: Some(122), added: 2597, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1000 w:1000) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1000 w:1000) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassAccount` (r:0 w:1) /// Proof: `Uniques::ClassAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:0 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) /// Storage: `Uniques::Account` (r:0 w:1000) /// Proof: `Uniques::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Uniques::CollectionMaxSupply` (r:0 w:1) @@ -520,15 +524,15 @@ impl WeightInfo for () { fn destroy(n: u32, m: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `418 + a * (107 ±0) + m * (56 ±0) + n * (76 ±0)` - // Estimated: `3643 + a * (2839 ±0) + m * (2583 ±0) + n * (2597 ±0)` - // Minimum execution time: 3_281_673_000 picoseconds. - Weight::from_parts(3_443_387_000, 3643) - // Standard Error: 41_937 - .saturating_add(Weight::from_parts(7_914_842, 0).saturating_mul(n.into())) - // Standard Error: 41_937 - .saturating_add(Weight::from_parts(519_960, 0).saturating_mul(m.into())) - // Standard Error: 41_937 - .saturating_add(Weight::from_parts(462_690, 0).saturating_mul(a.into())) + // Estimated: `3643 + a * (2647 ±0) + m * (2662 ±0) + n * (2597 ±0)` + // Minimum execution time: 2_979_858_000 picoseconds. + Weight::from_parts(3_007_268_000, 3643) + // Standard Error: 29_899 + .saturating_add(Weight::from_parts(6_943_612, 0).saturating_mul(n.into())) + // Standard Error: 29_899 + .saturating_add(Weight::from_parts(398_114, 0).saturating_mul(m.into())) + // Standard Error: 29_899 + .saturating_add(Weight::from_parts(369_941, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) @@ -537,8 +541,8 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(m.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) - .saturating_add(Weight::from_parts(0, 2839).saturating_mul(a.into())) - .saturating_add(Weight::from_parts(0, 2583).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 2647).saturating_mul(a.into())) + .saturating_add(Weight::from_parts(0, 2662).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 2597).saturating_mul(n.into())) } /// Storage: `Uniques::Asset` (r:1 w:1) @@ -553,8 +557,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 38_122_000 picoseconds. - Weight::from_parts(38_924_000, 3643) + // Minimum execution time: 32_733_000 picoseconds. + Weight::from_parts(33_487_000, 3643) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -570,8 +574,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 38_835_000 picoseconds. - Weight::from_parts(39_754_000, 3643) + // Minimum execution time: 34_202_000 picoseconds. + Weight::from_parts(35_146_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -587,8 +591,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 27_032_000 picoseconds. - Weight::from_parts(27_793_000, 3643) + // Minimum execution time: 24_285_000 picoseconds. + Weight::from_parts(25_300_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -601,10 +605,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `805 + i * (76 ±0)` // Estimated: `3643 + i * (2597 ±0)` - // Minimum execution time: 14_737_000 picoseconds. - Weight::from_parts(15_070_000, 3643) - // Standard Error: 22_500 - .saturating_add(Weight::from_parts(18_855_468, 0).saturating_mul(i.into())) + // Minimum execution time: 11_641_000 picoseconds. + Weight::from_parts(12_261_000, 3643) + // Standard Error: 18_897 + .saturating_add(Weight::from_parts(15_263_570, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -619,8 +623,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 18_664_000 picoseconds. - Weight::from_parts(19_455_000, 3643) + // Minimum execution time: 16_122_000 picoseconds. + Weight::from_parts(16_627_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -632,8 +636,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 18_247_000 picoseconds. - Weight::from_parts(18_763_000, 3643) + // Minimum execution time: 15_824_000 picoseconds. + Weight::from_parts(16_522_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -643,8 +647,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 13_219_000 picoseconds. - Weight::from_parts(13_923_000, 3643) + // Minimum execution time: 10_802_000 picoseconds. + Weight::from_parts(11_206_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -654,8 +658,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 13_376_000 picoseconds. - Weight::from_parts(13_904_000, 3643) + // Minimum execution time: 10_805_000 picoseconds. + Weight::from_parts(11_340_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -663,16 +667,18 @@ impl WeightInfo for () { /// Proof: `Uniques::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassAccount` (r:0 w:2) /// Proof: `Uniques::ClassAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `423` + // Measured: `597` // Estimated: `3643` - // Minimum execution time: 22_353_000 picoseconds. - Weight::from_parts(23_222_000, 3643) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 24_213_000 picoseconds. + Weight::from_parts(25_547_000, 3643) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) @@ -680,8 +686,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 14_072_000 picoseconds. - Weight::from_parts(14_619_000, 3643) + // Minimum execution time: 11_256_000 picoseconds. + Weight::from_parts(11_585_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -693,90 +699,90 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 17_081_000 picoseconds. - Weight::from_parts(17_698_000, 3643) + // Minimum execution time: 14_616_000 picoseconds. + Weight::from_parts(15_064_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:0) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1 w:1) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `547` - // Estimated: `3829` - // Minimum execution time: 41_501_000 picoseconds. - Weight::from_parts(43_101_000, 3829) + // Measured: `626` + // Estimated: `3652` + // Minimum execution time: 35_640_000 picoseconds. + Weight::from_parts(37_007_000, 3652) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:0) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1 w:1) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `936` - // Estimated: `3829` - // Minimum execution time: 39_722_000 picoseconds. - Weight::from_parts(40_390_000, 3829) + // Measured: `823` + // Estimated: `3652` + // Minimum execution time: 34_410_000 picoseconds. + Weight::from_parts(35_431_000, 3652) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:1) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `415` - // Estimated: `3643` - // Minimum execution time: 30_726_000 picoseconds. - Weight::from_parts(31_557_000, 3643) + // Estimated: `3652` + // Minimum execution time: 26_187_000 picoseconds. + Weight::from_parts(27_837_000, 3652) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:1) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `547` - // Estimated: `3643` - // Minimum execution time: 31_303_000 picoseconds. - Weight::from_parts(32_389_000, 3643) + // Measured: `626` + // Estimated: `3652` + // Minimum execution time: 26_640_000 picoseconds. + Weight::from_parts(27_688_000, 3652) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:1 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 32_155_000 picoseconds. - Weight::from_parts(32_885_000, 3643) + // Minimum execution time: 26_781_000 picoseconds. + Weight::from_parts(27_628_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:0) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:1 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `461` + // Measured: `540` // Estimated: `3643` - // Minimum execution time: 30_044_000 picoseconds. - Weight::from_parts(31_405_000, 3643) + // Minimum execution time: 26_295_000 picoseconds. + Weight::from_parts(26_903_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -788,8 +794,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 18_904_000 picoseconds. - Weight::from_parts(19_687_000, 3643) + // Minimum execution time: 16_678_000 picoseconds. + Weight::from_parts(17_548_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -801,8 +807,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `528` // Estimated: `3643` - // Minimum execution time: 19_144_000 picoseconds. - Weight::from_parts(19_706_000, 3643) + // Minimum execution time: 16_408_000 picoseconds. + Weight::from_parts(16_957_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -812,8 +818,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3517` - // Minimum execution time: 15_339_000 picoseconds. - Weight::from_parts(15_918_000, 3517) + // Minimum execution time: 12_568_000 picoseconds. + Weight::from_parts(12_960_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -825,8 +831,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 15_387_000 picoseconds. - Weight::from_parts(15_726_000, 3643) + // Minimum execution time: 13_110_000 picoseconds. + Weight::from_parts(13_620_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -838,8 +844,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `326` // Estimated: `3587` - // Minimum execution time: 15_873_000 picoseconds. - Weight::from_parts(16_860_000, 3587) + // Minimum execution time: 13_568_000 picoseconds. + Weight::from_parts(14_211_000, 3587) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -855,8 +861,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `607` // Estimated: `3643` - // Minimum execution time: 37_245_000 picoseconds. - Weight::from_parts(38_383_000, 3643) + // Minimum execution time: 32_660_000 picoseconds. + Weight::from_parts(33_734_000, 3643) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } diff --git a/substrate/frame/utility/src/weights.rs b/substrate/frame/utility/src/weights.rs index 1a3ea6c1f7f..60b1c48f086 100644 --- a/substrate/frame/utility/src/weights.rs +++ b/substrate/frame/utility/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_utility +//! Autogenerated weights for `pallet_utility` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/utility/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/utility/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_utility. +/// Weight functions needed for `pallet_utility`. pub trait WeightInfo { fn batch(c: u32, ) -> Weight; fn as_derivative() -> Weight; @@ -59,99 +58,139 @@ pub trait WeightInfo { fn force_batch(c: u32, ) -> Weight; } -/// Weights for pallet_utility using the Substrate node and recommended hardware. +/// Weights for `pallet_utility` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_763_000 picoseconds. - Weight::from_parts(16_943_157, 0) - // Standard Error: 1_904 - .saturating_add(Weight::from_parts(4_653_855, 0).saturating_mul(c.into())) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 5_143_000 picoseconds. + Weight::from_parts(11_552_299, 3997) + // Standard Error: 2_325 + .saturating_add(Weight::from_parts(4_708_951, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) fn as_derivative() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 5_149_000 picoseconds. - Weight::from_parts(5_268_000, 0) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 9_103_000 picoseconds. + Weight::from_parts(9_549_000, 3997) + .saturating_add(T::DbWeight::get().reads(2_u64)) } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_976_000 picoseconds. - Weight::from_parts(16_448_433, 0) - // Standard Error: 1_834 - .saturating_add(Weight::from_parts(4_796_983, 0).saturating_mul(c.into())) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 5_147_000 picoseconds. + Weight::from_parts(15_698_086, 3997) + // Standard Error: 3_066 + .saturating_add(Weight::from_parts(4_809_412, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) } fn dispatch_as() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_102_000 picoseconds. - Weight::from_parts(9_353_000, 0) + // Minimum execution time: 6_683_000 picoseconds. + Weight::from_parts(7_047_000, 0) } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_840_000 picoseconds. - Weight::from_parts(17_748_474, 0) - // Standard Error: 2_059 - .saturating_add(Weight::from_parts(4_630_079, 0).saturating_mul(c.into())) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 4_982_000 picoseconds. + Weight::from_parts(14_474_780, 3997) + // Standard Error: 2_291 + .saturating_add(Weight::from_parts(4_632_643, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_763_000 picoseconds. - Weight::from_parts(16_943_157, 0) - // Standard Error: 1_904 - .saturating_add(Weight::from_parts(4_653_855, 0).saturating_mul(c.into())) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 5_143_000 picoseconds. + Weight::from_parts(11_552_299, 3997) + // Standard Error: 2_325 + .saturating_add(Weight::from_parts(4_708_951, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) fn as_derivative() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 5_149_000 picoseconds. - Weight::from_parts(5_268_000, 0) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 9_103_000 picoseconds. + Weight::from_parts(9_549_000, 3997) + .saturating_add(RocksDbWeight::get().reads(2_u64)) } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_976_000 picoseconds. - Weight::from_parts(16_448_433, 0) - // Standard Error: 1_834 - .saturating_add(Weight::from_parts(4_796_983, 0).saturating_mul(c.into())) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 5_147_000 picoseconds. + Weight::from_parts(15_698_086, 3997) + // Standard Error: 3_066 + .saturating_add(Weight::from_parts(4_809_412, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) } fn dispatch_as() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_102_000 picoseconds. - Weight::from_parts(9_353_000, 0) + // Minimum execution time: 6_683_000 picoseconds. + Weight::from_parts(7_047_000, 0) } + /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) + /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `TxPause::PausedCalls` (r:1 w:0) + /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_840_000 picoseconds. - Weight::from_parts(17_748_474, 0) - // Standard Error: 2_059 - .saturating_add(Weight::from_parts(4_630_079, 0).saturating_mul(c.into())) + // Measured: `145` + // Estimated: `3997` + // Minimum execution time: 4_982_000 picoseconds. + Weight::from_parts(14_474_780, 3997) + // Standard Error: 2_291 + .saturating_add(Weight::from_parts(4_632_643, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) } } diff --git a/substrate/frame/vesting/src/weights.rs b/substrate/frame/vesting/src/weights.rs index ddc7db8fa61..d91c47ae195 100644 --- a/substrate/frame/vesting/src/weights.rs +++ b/substrate/frame/vesting/src/weights.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_vesting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-vmdtonbz-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/production/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 // --repeat=20 +// --pallet=pallet_vesting +// --no-storage-info +// --no-median-slopes +// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_vesting -// --chain=dev -// --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/vesting/src/weights.rs +// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -75,12 +77,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `381 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 32_846_000 picoseconds. - Weight::from_parts(30_974_459, 4764) - // Standard Error: 1_755 - .saturating_add(Weight::from_parts(73_138, 0).saturating_mul(l.into())) - // Standard Error: 3_123 - .saturating_add(Weight::from_parts(82_417, 0).saturating_mul(s.into())) + // Minimum execution time: 31_890_000 picoseconds. + Weight::from_parts(31_128_476, 4764) + // Standard Error: 1_193 + .saturating_add(Weight::from_parts(63_760, 0).saturating_mul(l.into())) + // Standard Error: 2_124 + .saturating_add(Weight::from_parts(57_247, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -96,12 +98,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `381 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 34_360_000 picoseconds. - Weight::from_parts(34_964_080, 4764) - // Standard Error: 1_996 - .saturating_add(Weight::from_parts(48_024, 0).saturating_mul(l.into())) - // Standard Error: 3_552 - .saturating_add(Weight::from_parts(34_411, 0).saturating_mul(s.into())) + // Minimum execution time: 33_958_000 picoseconds. + Weight::from_parts(33_537_005, 4764) + // Standard Error: 1_354 + .saturating_add(Weight::from_parts(60_604, 0).saturating_mul(l.into())) + // Standard Error: 2_410 + .saturating_add(Weight::from_parts(51_378, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -119,12 +121,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `484 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_859_000 picoseconds. - Weight::from_parts(32_950_681, 4764) - // Standard Error: 1_745 - .saturating_add(Weight::from_parts(69_323, 0).saturating_mul(l.into())) - // Standard Error: 3_105 - .saturating_add(Weight::from_parts(86_370, 0).saturating_mul(s.into())) + // Minimum execution time: 33_243_000 picoseconds. + Weight::from_parts(32_552_805, 4764) + // Standard Error: 1_413 + .saturating_add(Weight::from_parts(67_137, 0).saturating_mul(l.into())) + // Standard Error: 2_515 + .saturating_add(Weight::from_parts(70_000, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -142,12 +144,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `484 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 36_239_000 picoseconds. - Weight::from_parts(36_459_756, 4764) - // Standard Error: 2_051 - .saturating_add(Weight::from_parts(56_670, 0).saturating_mul(l.into())) - // Standard Error: 3_650 - .saturating_add(Weight::from_parts(49_663, 0).saturating_mul(s.into())) + // Minimum execution time: 35_396_000 picoseconds. + Weight::from_parts(35_774_949, 4764) + // Standard Error: 1_404 + .saturating_add(Weight::from_parts(55_349, 0).saturating_mul(l.into())) + // Standard Error: 2_497 + .saturating_add(Weight::from_parts(39_228, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -165,12 +167,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 70_330_000 picoseconds. - Weight::from_parts(71_196_328, 4764) - // Standard Error: 2_923 - .saturating_add(Weight::from_parts(67_238, 0).saturating_mul(l.into())) - // Standard Error: 5_201 - .saturating_add(Weight::from_parts(89_102, 0).saturating_mul(s.into())) + // Minimum execution time: 68_441_000 picoseconds. + Weight::from_parts(68_961_970, 4764) + // Standard Error: 2_509 + .saturating_add(Weight::from_parts(83_345, 0).saturating_mul(l.into())) + // Standard Error: 4_464 + .saturating_add(Weight::from_parts(124_158, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -188,12 +190,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `658 + l * (25 ±0) + s * (36 ±0)` // Estimated: `6196` - // Minimum execution time: 70_235_000 picoseconds. - Weight::from_parts(71_960_020, 6196) - // Standard Error: 2_493 - .saturating_add(Weight::from_parts(64_835, 0).saturating_mul(l.into())) - // Standard Error: 4_436 - .saturating_add(Weight::from_parts(102_159, 0).saturating_mul(s.into())) + // Minimum execution time: 70_190_000 picoseconds. + Weight::from_parts(72_355_984, 6196) + // Standard Error: 2_295 + .saturating_add(Weight::from_parts(59_968, 0).saturating_mul(l.into())) + // Standard Error: 4_084 + .saturating_add(Weight::from_parts(87_090, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -211,12 +213,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `482 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 34_352_000 picoseconds. - Weight::from_parts(33_697_027, 4764) - // Standard Error: 2_008 - .saturating_add(Weight::from_parts(79_270, 0).saturating_mul(l.into())) - // Standard Error: 3_710 - .saturating_add(Weight::from_parts(60_691, 0).saturating_mul(s.into())) + // Minimum execution time: 33_911_000 picoseconds. + Weight::from_parts(33_243_006, 4764) + // Standard Error: 1_199 + .saturating_add(Weight::from_parts(70_586, 0).saturating_mul(l.into())) + // Standard Error: 2_214 + .saturating_add(Weight::from_parts(60_985, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -234,12 +236,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `482 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 37_467_000 picoseconds. - Weight::from_parts(36_866_847, 4764) - // Standard Error: 1_692 - .saturating_add(Weight::from_parts(57_882, 0).saturating_mul(l.into())) - // Standard Error: 3_124 - .saturating_add(Weight::from_parts(80_266, 0).saturating_mul(s.into())) + // Minimum execution time: 36_242_000 picoseconds. + Weight::from_parts(35_812_994, 4764) + // Standard Error: 1_351 + .saturating_add(Weight::from_parts(68_256, 0).saturating_mul(l.into())) + // Standard Error: 2_496 + .saturating_add(Weight::from_parts(66_171, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -257,12 +259,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 41_497_000 picoseconds. - Weight::from_parts(38_763_834, 4764) - // Standard Error: 2_030 - .saturating_add(Weight::from_parts(99_580, 0).saturating_mul(l.into())) - // Standard Error: 3_750 - .saturating_add(Weight::from_parts(132_188, 0).saturating_mul(s.into())) + // Minimum execution time: 37_817_000 picoseconds. + Weight::from_parts(37_397_127, 4764) + // Standard Error: 1_665 + .saturating_add(Weight::from_parts(72_049, 0).saturating_mul(l.into())) + // Standard Error: 3_075 + .saturating_add(Weight::from_parts(60_973, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -282,12 +284,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `381 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 32_846_000 picoseconds. - Weight::from_parts(30_974_459, 4764) - // Standard Error: 1_755 - .saturating_add(Weight::from_parts(73_138, 0).saturating_mul(l.into())) - // Standard Error: 3_123 - .saturating_add(Weight::from_parts(82_417, 0).saturating_mul(s.into())) + // Minimum execution time: 31_890_000 picoseconds. + Weight::from_parts(31_128_476, 4764) + // Standard Error: 1_193 + .saturating_add(Weight::from_parts(63_760, 0).saturating_mul(l.into())) + // Standard Error: 2_124 + .saturating_add(Weight::from_parts(57_247, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -303,12 +305,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `381 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 34_360_000 picoseconds. - Weight::from_parts(34_964_080, 4764) - // Standard Error: 1_996 - .saturating_add(Weight::from_parts(48_024, 0).saturating_mul(l.into())) - // Standard Error: 3_552 - .saturating_add(Weight::from_parts(34_411, 0).saturating_mul(s.into())) + // Minimum execution time: 33_958_000 picoseconds. + Weight::from_parts(33_537_005, 4764) + // Standard Error: 1_354 + .saturating_add(Weight::from_parts(60_604, 0).saturating_mul(l.into())) + // Standard Error: 2_410 + .saturating_add(Weight::from_parts(51_378, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -326,12 +328,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `484 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_859_000 picoseconds. - Weight::from_parts(32_950_681, 4764) - // Standard Error: 1_745 - .saturating_add(Weight::from_parts(69_323, 0).saturating_mul(l.into())) - // Standard Error: 3_105 - .saturating_add(Weight::from_parts(86_370, 0).saturating_mul(s.into())) + // Minimum execution time: 33_243_000 picoseconds. + Weight::from_parts(32_552_805, 4764) + // Standard Error: 1_413 + .saturating_add(Weight::from_parts(67_137, 0).saturating_mul(l.into())) + // Standard Error: 2_515 + .saturating_add(Weight::from_parts(70_000, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -349,12 +351,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `484 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 36_239_000 picoseconds. - Weight::from_parts(36_459_756, 4764) - // Standard Error: 2_051 - .saturating_add(Weight::from_parts(56_670, 0).saturating_mul(l.into())) - // Standard Error: 3_650 - .saturating_add(Weight::from_parts(49_663, 0).saturating_mul(s.into())) + // Minimum execution time: 35_396_000 picoseconds. + Weight::from_parts(35_774_949, 4764) + // Standard Error: 1_404 + .saturating_add(Weight::from_parts(55_349, 0).saturating_mul(l.into())) + // Standard Error: 2_497 + .saturating_add(Weight::from_parts(39_228, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -372,12 +374,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 70_330_000 picoseconds. - Weight::from_parts(71_196_328, 4764) - // Standard Error: 2_923 - .saturating_add(Weight::from_parts(67_238, 0).saturating_mul(l.into())) - // Standard Error: 5_201 - .saturating_add(Weight::from_parts(89_102, 0).saturating_mul(s.into())) + // Minimum execution time: 68_441_000 picoseconds. + Weight::from_parts(68_961_970, 4764) + // Standard Error: 2_509 + .saturating_add(Weight::from_parts(83_345, 0).saturating_mul(l.into())) + // Standard Error: 4_464 + .saturating_add(Weight::from_parts(124_158, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -395,12 +397,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `658 + l * (25 ±0) + s * (36 ±0)` // Estimated: `6196` - // Minimum execution time: 70_235_000 picoseconds. - Weight::from_parts(71_960_020, 6196) - // Standard Error: 2_493 - .saturating_add(Weight::from_parts(64_835, 0).saturating_mul(l.into())) - // Standard Error: 4_436 - .saturating_add(Weight::from_parts(102_159, 0).saturating_mul(s.into())) + // Minimum execution time: 70_190_000 picoseconds. + Weight::from_parts(72_355_984, 6196) + // Standard Error: 2_295 + .saturating_add(Weight::from_parts(59_968, 0).saturating_mul(l.into())) + // Standard Error: 4_084 + .saturating_add(Weight::from_parts(87_090, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -418,12 +420,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `482 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 34_352_000 picoseconds. - Weight::from_parts(33_697_027, 4764) - // Standard Error: 2_008 - .saturating_add(Weight::from_parts(79_270, 0).saturating_mul(l.into())) - // Standard Error: 3_710 - .saturating_add(Weight::from_parts(60_691, 0).saturating_mul(s.into())) + // Minimum execution time: 33_911_000 picoseconds. + Weight::from_parts(33_243_006, 4764) + // Standard Error: 1_199 + .saturating_add(Weight::from_parts(70_586, 0).saturating_mul(l.into())) + // Standard Error: 2_214 + .saturating_add(Weight::from_parts(60_985, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -441,12 +443,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `482 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 37_467_000 picoseconds. - Weight::from_parts(36_866_847, 4764) - // Standard Error: 1_692 - .saturating_add(Weight::from_parts(57_882, 0).saturating_mul(l.into())) - // Standard Error: 3_124 - .saturating_add(Weight::from_parts(80_266, 0).saturating_mul(s.into())) + // Minimum execution time: 36_242_000 picoseconds. + Weight::from_parts(35_812_994, 4764) + // Standard Error: 1_351 + .saturating_add(Weight::from_parts(68_256, 0).saturating_mul(l.into())) + // Standard Error: 2_496 + .saturating_add(Weight::from_parts(66_171, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -464,12 +466,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 41_497_000 picoseconds. - Weight::from_parts(38_763_834, 4764) - // Standard Error: 2_030 - .saturating_add(Weight::from_parts(99_580, 0).saturating_mul(l.into())) - // Standard Error: 3_750 - .saturating_add(Weight::from_parts(132_188, 0).saturating_mul(s.into())) + // Minimum execution time: 37_817_000 picoseconds. + Weight::from_parts(37_397_127, 4764) + // Standard Error: 1_665 + .saturating_add(Weight::from_parts(72_049, 0).saturating_mul(l.into())) + // Standard Error: 3_075 + .saturating_add(Weight::from_parts(60_973, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/substrate/frame/whitelist/src/weights.rs b/substrate/frame/whitelist/src/weights.rs index de42c5a5841..13b653f6ca7 100644 --- a/substrate/frame/whitelist/src/weights.rs +++ b/substrate/frame/whitelist/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_whitelist +//! Autogenerated weights for `pallet_whitelist` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// ./target/production/substrate-node // benchmark // pallet // --chain=dev @@ -35,12 +35,11 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/whitelist/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --output=./substrate/frame/whitelist/src/weights.rs +// --header=./substrate/HEADER-APACHE2 +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_whitelist. +/// Weight functions needed for `pallet_whitelist`. pub trait WeightInfo { fn whitelist_call() -> Weight; fn remove_whitelisted_call() -> Weight; @@ -58,133 +57,149 @@ pub trait WeightInfo { fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight; } -/// Weights for pallet_whitelist using the Substrate node and recommended hardware. +/// Weights for `pallet_whitelist` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Whitelist WhitelistedCall (r:1 w:1) - /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) + /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn whitelist_call() -> Weight { // Proof Size summary in bytes: - // Measured: `217` + // Measured: `317` // Estimated: `3556` - // Minimum execution time: 19_914_000 picoseconds. - Weight::from_parts(20_892_000, 3556) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 18_503_000 picoseconds. + Weight::from_parts(19_497_000, 3556) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Whitelist WhitelistedCall (r:1 w:1) - /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) + /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn remove_whitelisted_call() -> Weight { // Proof Size summary in bytes: - // Measured: `346` + // Measured: `446` // Estimated: `3556` - // Minimum execution time: 18_142_000 picoseconds. - Weight::from_parts(18_529_000, 3556) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 17_633_000 picoseconds. + Weight::from_parts(18_196_000, 3556) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: Whitelist WhitelistedCall (r:1 w:1) - /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: Preimage PreimageFor (r:1 w:1) - /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: Measured) - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) + /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Preimage::PreimageFor` (r:1 w:1) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 4194294]`. fn dispatch_whitelisted_call(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `422 + n * (1 ±0)` - // Estimated: `3886 + n * (1 ±0)` - // Minimum execution time: 30_671_000 picoseconds. - Weight::from_parts(31_197_000, 3886) + // Measured: `522 + n * (1 ±0)` + // Estimated: `3986 + n * (1 ±0)` + // Minimum execution time: 28_020_000 picoseconds. + Weight::from_parts(28_991_000, 3986) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_163, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(Weight::from_parts(1_171, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } - /// Storage: Whitelist WhitelistedCall (r:1 w:1) - /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) + /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 10000]`. fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `346` + // Measured: `446` // Estimated: `3556` - // Minimum execution time: 22_099_000 picoseconds. - Weight::from_parts(23_145_477, 3556) - // Standard Error: 5 - .saturating_add(Weight::from_parts(1_422, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 21_916_000 picoseconds. + Weight::from_parts(23_082_065, 3556) + // Standard Error: 6 + .saturating_add(Weight::from_parts(1_388, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Whitelist WhitelistedCall (r:1 w:1) - /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) + /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn whitelist_call() -> Weight { // Proof Size summary in bytes: - // Measured: `217` + // Measured: `317` // Estimated: `3556` - // Minimum execution time: 19_914_000 picoseconds. - Weight::from_parts(20_892_000, 3556) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Minimum execution time: 18_503_000 picoseconds. + Weight::from_parts(19_497_000, 3556) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Whitelist WhitelistedCall (r:1 w:1) - /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) + /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn remove_whitelisted_call() -> Weight { // Proof Size summary in bytes: - // Measured: `346` + // Measured: `446` // Estimated: `3556` - // Minimum execution time: 18_142_000 picoseconds. - Weight::from_parts(18_529_000, 3556) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Minimum execution time: 17_633_000 picoseconds. + Weight::from_parts(18_196_000, 3556) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: Whitelist WhitelistedCall (r:1 w:1) - /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: Preimage PreimageFor (r:1 w:1) - /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: Measured) - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) + /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Preimage::PreimageFor` (r:1 w:1) + /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 4194294]`. fn dispatch_whitelisted_call(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `422 + n * (1 ±0)` - // Estimated: `3886 + n * (1 ±0)` - // Minimum execution time: 30_671_000 picoseconds. - Weight::from_parts(31_197_000, 3886) + // Measured: `522 + n * (1 ±0)` + // Estimated: `3986 + n * (1 ±0)` + // Minimum execution time: 28_020_000 picoseconds. + Weight::from_parts(28_991_000, 3986) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_163, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(Weight::from_parts(1_171, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } - /// Storage: Whitelist WhitelistedCall (r:1 w:1) - /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: Preimage StatusFor (r:1 w:1) - /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) + /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 10000]`. fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `346` + // Measured: `446` // Estimated: `3556` - // Minimum execution time: 22_099_000 picoseconds. - Weight::from_parts(23_145_477, 3556) - // Standard Error: 5 - .saturating_add(Weight::from_parts(1_422, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Minimum execution time: 21_916_000 picoseconds. + Weight::from_parts(23_082_065, 3556) + // Standard Error: 6 + .saturating_add(Weight::from_parts(1_388, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/substrate/primitives/inherents/src/lib.rs b/substrate/primitives/inherents/src/lib.rs index dd7c294f1e2..415319a6849 100644 --- a/substrate/primitives/inherents/src/lib.rs +++ b/substrate/primitives/inherents/src/lib.rs @@ -98,10 +98,10 @@ //! and production. //! //! ``` -//! # use sp_runtime::testing::ExtrinsicWrapper; +//! # use sp_runtime::{generic::UncheckedExtrinsic, testing::MockCallU64}; //! # use sp_inherents::{InherentIdentifier, InherentData}; //! # use futures::FutureExt; -//! # type Block = sp_runtime::testing::Block>; +//! # type Block = sp_runtime::testing::Block>; //! # const INHERENT_IDENTIFIER: InherentIdentifier = *b"testinh0"; //! # struct InherentDataProvider; //! # #[async_trait::async_trait] diff --git a/substrate/primitives/metadata-ir/src/lib.rs b/substrate/primitives/metadata-ir/src/lib.rs index edfa58f8618..66aff2c599f 100644 --- a/substrate/primitives/metadata-ir/src/lib.rs +++ b/substrate/primitives/metadata-ir/src/lib.rs @@ -84,7 +84,7 @@ mod test { call_ty: meta_type::<()>(), signature_ty: meta_type::<()>(), extra_ty: meta_type::<()>(), - signed_extensions: vec![], + extensions: vec![], }, ty: meta_type::<()>(), apis: vec![], diff --git a/substrate/primitives/metadata-ir/src/types.rs b/substrate/primitives/metadata-ir/src/types.rs index b107d20a8e2..e60881ed6b8 100644 --- a/substrate/primitives/metadata-ir/src/types.rs +++ b/substrate/primitives/metadata-ir/src/types.rs @@ -166,10 +166,11 @@ pub struct ExtrinsicMetadataIR { pub call_ty: T::Type, /// The type of the extrinsic's signature. pub signature_ty: T::Type, - /// The type of the outermost Extra enum. + /// The type of the outermost Extra/Extensions enum. + // TODO: metadata-v16: rename this to `extension_ty`. pub extra_ty: T::Type, - /// The signed extensions in the order they appear in the extrinsic. - pub signed_extensions: Vec>, + /// The transaction extensions in the order they appear in the extrinsic. + pub extensions: Vec>, } impl IntoPortable for ExtrinsicMetadataIR { @@ -183,27 +184,27 @@ impl IntoPortable for ExtrinsicMetadataIR { call_ty: registry.register_type(&self.call_ty), signature_ty: registry.register_type(&self.signature_ty), extra_ty: registry.register_type(&self.extra_ty), - signed_extensions: registry.map_into_portable(self.signed_extensions), + extensions: registry.map_into_portable(self.extensions), } } } /// Metadata of an extrinsic's signed extension. #[derive(Clone, PartialEq, Eq, Encode, Debug)] -pub struct SignedExtensionMetadataIR { +pub struct TransactionExtensionMetadataIR { /// The unique signed extension identifier, which may be different from the type name. pub identifier: T::String, /// The type of the signed extension, with the data to be included in the extrinsic. pub ty: T::Type, - /// The type of the additional signed data, with the data to be included in the signed payload + /// The type of the additional signed data, with the data to be included in the signed payload. pub additional_signed: T::Type, } -impl IntoPortable for SignedExtensionMetadataIR { - type Output = SignedExtensionMetadataIR; +impl IntoPortable for TransactionExtensionMetadataIR { + type Output = TransactionExtensionMetadataIR; fn into_portable(self, registry: &mut Registry) -> Self::Output { - SignedExtensionMetadataIR { + TransactionExtensionMetadataIR { identifier: self.identifier.into_portable(registry), ty: registry.register_type(&self.ty), additional_signed: registry.register_type(&self.additional_signed), diff --git a/substrate/primitives/metadata-ir/src/v14.rs b/substrate/primitives/metadata-ir/src/v14.rs index e1b7a24f765..ec08de34786 100644 --- a/substrate/primitives/metadata-ir/src/v14.rs +++ b/substrate/primitives/metadata-ir/src/v14.rs @@ -20,8 +20,8 @@ use super::types::{ ExtrinsicMetadataIR, MetadataIR, PalletCallMetadataIR, PalletConstantMetadataIR, PalletErrorMetadataIR, PalletEventMetadataIR, PalletMetadataIR, PalletStorageMetadataIR, - SignedExtensionMetadataIR, StorageEntryMetadataIR, StorageEntryModifierIR, StorageEntryTypeIR, - StorageHasherIR, + StorageEntryMetadataIR, StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR, + TransactionExtensionMetadataIR, }; use frame_metadata::v14::{ @@ -137,8 +137,8 @@ impl From for PalletErrorMetadata { } } -impl From for SignedExtensionMetadata { - fn from(ir: SignedExtensionMetadataIR) -> Self { +impl From for SignedExtensionMetadata { + fn from(ir: TransactionExtensionMetadataIR) -> Self { SignedExtensionMetadata { identifier: ir.identifier, ty: ir.ty, @@ -152,7 +152,7 @@ impl From for ExtrinsicMetadata { ExtrinsicMetadata { ty: ir.ty, version: ir.version, - signed_extensions: ir.signed_extensions.into_iter().map(Into::into).collect(), + signed_extensions: ir.extensions.into_iter().map(Into::into).collect(), } } } diff --git a/substrate/primitives/metadata-ir/src/v15.rs b/substrate/primitives/metadata-ir/src/v15.rs index a942eb73223..dc5ce1c88fd 100644 --- a/substrate/primitives/metadata-ir/src/v15.rs +++ b/substrate/primitives/metadata-ir/src/v15.rs @@ -21,7 +21,7 @@ use crate::OuterEnumsIR; use super::types::{ ExtrinsicMetadataIR, MetadataIR, PalletMetadataIR, RuntimeApiMetadataIR, - RuntimeApiMethodMetadataIR, RuntimeApiMethodParamMetadataIR, SignedExtensionMetadataIR, + RuntimeApiMethodMetadataIR, RuntimeApiMethodParamMetadataIR, TransactionExtensionMetadataIR, }; use frame_metadata::v15::{ @@ -87,8 +87,8 @@ impl From for PalletMetadata { } } -impl From for SignedExtensionMetadata { - fn from(ir: SignedExtensionMetadataIR) -> Self { +impl From for SignedExtensionMetadata { + fn from(ir: TransactionExtensionMetadataIR) -> Self { SignedExtensionMetadata { identifier: ir.identifier, ty: ir.ty, @@ -105,7 +105,7 @@ impl From for ExtrinsicMetadata { call_ty: ir.call_ty, signature_ty: ir.signature_ty, extra_ty: ir.extra_ty, - signed_extensions: ir.signed_extensions.into_iter().map(Into::into).collect(), + signed_extensions: ir.extensions.into_iter().map(Into::into).collect(), } } } diff --git a/substrate/primitives/runtime/Cargo.toml b/substrate/primitives/runtime/Cargo.toml index cacfc059722..758cd8944fd 100644 --- a/substrate/primitives/runtime/Cargo.toml +++ b/substrate/primitives/runtime/Cargo.toml @@ -17,6 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] +tuplex = { version = "0.1.2", default-features = false } codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } either = { version = "1.5", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } @@ -67,6 +68,7 @@ std = [ "sp-std/std", "sp-tracing/std", "sp-weights/std", + "tuplex/std", ] # Serde support without relying on std features. diff --git a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs index 44325920bee..e28c8fe424a 100644 --- a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs @@ -18,81 +18,115 @@ //! Generic implementation of an extrinsic that has passed the verification //! stage. +use codec::Encode; + use crate::{ traits::{ - self, DispatchInfoOf, Dispatchable, MaybeDisplay, Member, PostDispatchInfoOf, - SignedExtension, ValidateUnsigned, + self, transaction_extension::TransactionExtension, DispatchInfoOf, DispatchTransaction, + Dispatchable, MaybeDisplay, Member, PostDispatchInfoOf, ValidateUnsigned, }, transaction_validity::{TransactionSource, TransactionValidity}, }; +/// The kind of extrinsic this is, including any fields required of that kind. This is basically +/// the full extrinsic except the `Call`. +#[derive(PartialEq, Eq, Clone, sp_core::RuntimeDebug)] +pub enum ExtrinsicFormat { + /// Extrinsic is bare; it must pass either the bare forms of `TransactionExtension` or + /// `ValidateUnsigned`, both deprecated, or alternatively a `ProvideInherent`. + Bare, + /// Extrinsic has a default `Origin` of `Signed(AccountId)` and must pass all + /// `TransactionExtension`s regular checks and includes all extension data. + Signed(AccountId, Extension), + /// Extrinsic has a default `Origin` of `None` and must pass all `TransactionExtension`s. + /// regular checks and includes all extension data. + General(Extension), +} + +// TODO: Rename ValidateUnsigned to ValidateInherent +// TODO: Consider changing ValidateInherent API to avoid need for duplicating validate +// code into pre_dispatch (rename that to `prepare`). +// TODO: New extrinsic type corresponding to `ExtrinsicFormat::General`, which is +// unsigned but includes extension data. +// TODO: Move usage of `signed` to `format`: +// - Inherent instead of None. +// - Signed(id, extension) instead of Some((id, extra)). +// - Introduce General(extension) for one without a signature. + /// Definition of something that the external world might want to say; its existence implies that it /// has been checked and is good, particularly with regards to the signature. /// /// This is typically passed into [`traits::Applyable::apply`], which should execute /// [`CheckedExtrinsic::function`], alongside all other bits and bobs. #[derive(PartialEq, Eq, Clone, sp_core::RuntimeDebug)] -pub struct CheckedExtrinsic { +pub struct CheckedExtrinsic { /// Who this purports to be from and the number of extrinsics have come before /// from the same signer, if anyone (note this is not a signature). - pub signed: Option<(AccountId, Extra)>, + pub format: ExtrinsicFormat, /// The function that should be called. pub function: Call, } -impl traits::Applyable - for CheckedExtrinsic +impl traits::Applyable + for CheckedExtrinsic where AccountId: Member + MaybeDisplay, - Call: Member + Dispatchable, - Extra: SignedExtension, + Call: Member + Dispatchable + Encode, + Extension: TransactionExtension, RuntimeOrigin: From>, { type Call = Call; - fn validate>( + fn validate>( &self, - // TODO [#5006;ToDr] should source be passed to `SignedExtension`s? - // Perhaps a change for 2.0 to avoid breaking too much APIs? source: TransactionSource, info: &DispatchInfoOf, len: usize, ) -> TransactionValidity { - if let Some((ref id, ref extra)) = self.signed { - Extra::validate(extra, id, &self.function, info, len) - } else { - let valid = Extra::validate_unsigned(&self.function, info, len)?; - let unsigned_validation = U::validate_unsigned(source, &self.function)?; - Ok(valid.combine_with(unsigned_validation)) + match self.format { + ExtrinsicFormat::Bare => { + let inherent_validation = I::validate_unsigned(source, &self.function)?; + #[allow(deprecated)] + let legacy_validation = Extension::validate_bare_compat(&self.function, info, len)?; + Ok(legacy_validation.combine_with(inherent_validation)) + }, + ExtrinsicFormat::Signed(ref signer, ref extension) => { + let origin = Some(signer.clone()).into(); + extension.validate_only(origin, &self.function, info, len).map(|x| x.0) + }, + ExtrinsicFormat::General(ref extension) => + extension.validate_only(None.into(), &self.function, info, len).map(|x| x.0), } } - fn apply>( + fn apply>( self, info: &DispatchInfoOf, len: usize, ) -> crate::ApplyExtrinsicResultWithInfo> { - let (maybe_who, maybe_pre) = if let Some((id, extra)) = self.signed { - let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?; - (Some(id), Some(pre)) - } else { - Extra::pre_dispatch_unsigned(&self.function, info, len)?; - U::pre_dispatch(&self.function)?; - (None, None) - }; - let res = self.function.dispatch(RuntimeOrigin::from(maybe_who)); - let post_info = match res { - Ok(info) => info, - Err(err) => err.post_info, - }; - Extra::post_dispatch( - maybe_pre, - info, - &post_info, - len, - &res.map(|_| ()).map_err(|e| e.error), - )?; - Ok(res) + match self.format { + ExtrinsicFormat::Bare => { + I::pre_dispatch(&self.function)?; + // TODO: Remove below once `pre_dispatch_unsigned` is removed from `LegacyExtension` + // or `LegacyExtension` is removed. + #[allow(deprecated)] + Extension::validate_bare_compat(&self.function, info, len)?; + #[allow(deprecated)] + Extension::pre_dispatch_bare_compat(&self.function, info, len)?; + let res = self.function.dispatch(None.into()); + let post_info = res.unwrap_or_else(|err| err.post_info); + let pd_res = res.map(|_| ()).map_err(|e| e.error); + // TODO: Remove below once `pre_dispatch_unsigned` is removed from `LegacyExtension` + // or `LegacyExtension` is removed. + #[allow(deprecated)] + Extension::post_dispatch_bare_compat(info, &post_info, len, &pd_res)?; + Ok(res) + }, + ExtrinsicFormat::Signed(signer, extension) => + extension.dispatch_transaction(Some(signer).into(), self.function, info, len), + ExtrinsicFormat::General(extension) => + extension.dispatch_transaction(None.into(), self.function, info, len), + } } } diff --git a/substrate/primitives/runtime/src/generic/mod.rs b/substrate/primitives/runtime/src/generic/mod.rs index 3687f7cdb3b..5713c166b04 100644 --- a/substrate/primitives/runtime/src/generic/mod.rs +++ b/substrate/primitives/runtime/src/generic/mod.rs @@ -29,9 +29,9 @@ mod unchecked_extrinsic; pub use self::{ block::{Block, BlockId, SignedBlock}, - checked_extrinsic::CheckedExtrinsic, + checked_extrinsic::{CheckedExtrinsic, ExtrinsicFormat}, digest::{Digest, DigestItem, DigestItemRef, OpaqueDigestItemId}, era::{Era, Phase}, header::Header, - unchecked_extrinsic::{SignedPayload, UncheckedExtrinsic}, + unchecked_extrinsic::{Preamble, SignedPayload, UncheckedExtrinsic}, }; diff --git a/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs b/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs index 5b54caf597b..44dfda13d94 100644 --- a/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -18,10 +18,11 @@ //! Generic implementation of an unchecked (pre-verification) extrinsic. use crate::{ - generic::CheckedExtrinsic, + generic::{CheckedExtrinsic, ExtrinsicFormat}, traits::{ - self, Checkable, Extrinsic, ExtrinsicMetadata, IdentifyAccount, MaybeDisplay, Member, - SignaturePayload, SignedExtension, + self, transaction_extension::TransactionExtensionBase, Checkable, Dispatchable, Extrinsic, + ExtrinsicMetadata, IdentifyAccount, MaybeDisplay, Member, SignaturePayload, + TransactionExtension, }, transaction_validity::{InvalidTransaction, TransactionValidityError}, OpaqueExtrinsic, @@ -40,8 +41,60 @@ use sp_std::{fmt, prelude::*}; /// the decoding fails. const EXTRINSIC_FORMAT_VERSION: u8 = 4; -/// The `SingaturePayload` of `UncheckedExtrinsic`. -type UncheckedSignaturePayload = (Address, Signature, Extra); +/// The `SignaturePayload` of `UncheckedExtrinsic`. +type UncheckedSignaturePayload = (Address, Signature, Extension); + +impl SignaturePayload + for UncheckedSignaturePayload +{ + type SignatureAddress = Address; + type Signature = Signature; + type SignatureExtra = Extension; +} + +/// A "header" for extrinsics leading up to the call itself. Determines the type of extrinsic and +/// holds any necessary specialized data. +#[derive(Eq, PartialEq, Clone, Encode, Decode)] +pub enum Preamble { + /// An extrinsic without a signature or any extension. This means it's either an inherent or + /// an old-school "Unsigned" (we don't use that terminology any more since it's confusable with + /// the general transaction which is without a signature but does have an extension). + /// + /// NOTE: In the future, once we remove `ValidateUnsigned`, this will only serve Inherent + /// extrinsics and thus can be renamed to `Inherent`. + #[codec(index = 0b00000100)] + Bare, + /// An old-school transaction extrinsic which includes a signature of some hard-coded crypto. + #[codec(index = 0b10000100)] + Signed(Address, Signature, Extension), + /// A new-school transaction extrinsic which does not include a signature. + #[codec(index = 0b01000100)] + General(Extension), +} + +impl Preamble { + /// Returns `Some` if this is a signed extrinsic, together with the relevant inner fields. + pub fn to_signed(self) -> Option<(Address, Signature, Extension)> { + match self { + Self::Signed(a, s, e) => Some((a, s, e)), + _ => None, + } + } +} + +impl fmt::Debug for Preamble +where + Address: fmt::Debug, + Extension: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Bare => write!(f, "Bare"), + Self::Signed(address, _, tx_ext) => write!(f, "Signed({:?}, {:?})", address, tx_ext), + Self::General(tx_ext) => write!(f, "General({:?})", tx_ext), + } + } +} /// An extrinsic right from the external world. This is unchecked and so can contain a signature. /// @@ -65,41 +118,28 @@ type UncheckedSignaturePayload = (Address, Signature, /// This can be checked using [`Checkable`], yielding a [`CheckedExtrinsic`], which is the /// counterpart of this type after its signature (and other non-negotiable validity checks) have /// passed. -#[derive(PartialEq, Eq, Clone)] -pub struct UncheckedExtrinsic -where - Extra: SignedExtension, -{ - /// The signature, address, number of extrinsics have come before from the same signer and an - /// era describing the longevity of this transaction, if this is a signed extrinsic. - /// - /// `None` if it is unsigned or an inherent. - pub signature: Option>, +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct UncheckedExtrinsic { + /// Information regarding the type of extrinsic this is (inherent or transaction) as well as + /// associated extension (`Extension`) data if it's a transaction and a possible signature. + pub preamble: Preamble, /// The function that should be called. pub function: Call, } -impl SignaturePayload - for UncheckedSignaturePayload -{ - type SignatureAddress = Address; - type Signature = Signature; - type SignatureExtra = Extra; -} - /// Manual [`TypeInfo`] implementation because of custom encoding. The data is a valid encoded /// `Vec`, but requires some logic to extract the signature and payload. /// /// See [`UncheckedExtrinsic::encode`] and [`UncheckedExtrinsic::decode`]. -impl TypeInfo - for UncheckedExtrinsic +impl TypeInfo + for UncheckedExtrinsic where Address: StaticTypeInfo, Call: StaticTypeInfo, Signature: StaticTypeInfo, - Extra: SignedExtension + StaticTypeInfo, + Extension: StaticTypeInfo, { - type Identity = UncheckedExtrinsic; + type Identity = UncheckedExtrinsic; fn type_info() -> Type { Type::builder() @@ -111,7 +151,7 @@ where TypeParameter::new("Address", Some(meta_type::
())), TypeParameter::new("Call", Some(meta_type::())), TypeParameter::new("Signature", Some(meta_type::())), - TypeParameter::new("Extra", Some(meta_type::())), + TypeParameter::new("Extra", Some(meta_type::())), ]) .docs(&["UncheckedExtrinsic raw bytes, requires custom decoding routine"]) // Because of the custom encoding, we can only accurately describe the encoding as an @@ -121,66 +161,113 @@ where } } -impl - UncheckedExtrinsic -{ - /// New instance of a signed extrinsic aka "transaction". - pub fn new_signed(function: Call, signed: Address, signature: Signature, extra: Extra) -> Self { - Self { signature: Some((signed, signature, extra)), function } +impl UncheckedExtrinsic { + /// New instance of a bare (ne unsigned) extrinsic. This could be used for an inherent or an + /// old-school "unsigned transaction" (which are new being deprecated in favour of general + /// transactions). + #[deprecated = "Use new_bare instead"] + pub fn new_unsigned(function: Call) -> Self { + Self::new_bare(function) } - /// New instance of an unsigned extrinsic aka "inherent". - pub fn new_unsigned(function: Call) -> Self { - Self { signature: None, function } + /// Returns `true` if this extrinsic instance is an inherent, `false`` otherwise. + pub fn is_inherent(&self) -> bool { + matches!(self.preamble, Preamble::Bare) + } + + /// Returns `true` if this extrinsic instance is an old-school signed transaction, `false` + /// otherwise. + pub fn is_signed(&self) -> bool { + matches!(self.preamble, Preamble::Signed(..)) + } + + /// Create an `UncheckedExtrinsic` from a `Preamble` and the actual `Call`. + pub fn from_parts(function: Call, preamble: Preamble) -> Self { + Self { preamble, function } + } + + /// New instance of a bare (ne unsigned) extrinsic. + pub fn new_bare(function: Call) -> Self { + Self { preamble: Preamble::Bare, function } + } + + /// New instance of an old-school signed transaction. + pub fn new_signed( + function: Call, + signed: Address, + signature: Signature, + tx_ext: Extension, + ) -> Self { + Self { preamble: Preamble::Signed(signed, signature, tx_ext), function } + } + + /// New instance of an new-school unsigned transaction. + pub fn new_transaction(function: Call, tx_ext: Extension) -> Self { + Self { preamble: Preamble::General(tx_ext), function } } } -impl - Extrinsic for UncheckedExtrinsic +// TODO: We can get rid of this trait and just use UncheckedExtrinsic directly. + +impl Extrinsic + for UncheckedExtrinsic { type Call = Call; - type SignaturePayload = UncheckedSignaturePayload; + type SignaturePayload = UncheckedSignaturePayload; + + fn is_bare(&self) -> bool { + matches!(self.preamble, Preamble::Bare) + } fn is_signed(&self) -> Option { - Some(self.signature.is_some()) + Some(matches!(self.preamble, Preamble::Signed(..))) } fn new(function: Call, signed_data: Option) -> Option { Some(if let Some((address, signature, extra)) = signed_data { Self::new_signed(function, address, signature, extra) } else { - Self::new_unsigned(function) + Self::new_bare(function) }) } + + fn new_inherent(function: Call) -> Self { + Self::new_bare(function) + } } -impl Checkable - for UncheckedExtrinsic +impl Checkable + for UncheckedExtrinsic where LookupSource: Member + MaybeDisplay, - Call: Encode + Member, + Call: Encode + Member + Dispatchable, Signature: Member + traits::Verify, ::Signer: IdentifyAccount, - Extra: SignedExtension, + Extension: Encode + TransactionExtension, AccountId: Member + MaybeDisplay, Lookup: traits::Lookup, { - type Checked = CheckedExtrinsic; + type Checked = CheckedExtrinsic; fn check(self, lookup: &Lookup) -> Result { - Ok(match self.signature { - Some((signed, signature, extra)) => { + Ok(match self.preamble { + Preamble::Signed(signed, signature, tx_ext) => { let signed = lookup.lookup(signed)?; - let raw_payload = SignedPayload::new(self.function, extra)?; + // CHECK! Should this not contain implicit? + let raw_payload = SignedPayload::new(self.function, tx_ext)?; if !raw_payload.using_encoded(|payload| signature.verify(payload, &signed)) { return Err(InvalidTransaction::BadProof.into()) } - - let (function, extra, _) = raw_payload.deconstruct(); - CheckedExtrinsic { signed: Some((signed, extra)), function } + let (function, tx_ext, _) = raw_payload.deconstruct(); + CheckedExtrinsic { format: ExtrinsicFormat::Signed(signed, tx_ext), function } + }, + Preamble::General(tx_ext) => CheckedExtrinsic { + format: ExtrinsicFormat::General(tx_ext), + function: self.function, }, - None => CheckedExtrinsic { signed: None, function: self.function }, + Preamble::Bare => + CheckedExtrinsic { format: ExtrinsicFormat::Bare, function: self.function }, }) } @@ -189,91 +276,38 @@ where self, lookup: &Lookup, ) -> Result { - Ok(match self.signature { - Some((signed, _, extra)) => { + Ok(match self.preamble { + Preamble::Signed(signed, _, extra) => { let signed = lookup.lookup(signed)?; - let raw_payload = SignedPayload::new(self.function, extra)?; - let (function, extra, _) = raw_payload.deconstruct(); - CheckedExtrinsic { signed: Some((signed, extra)), function } + CheckedExtrinsic { + format: ExtrinsicFormat::Signed(signed, extra), + function: self.function, + } }, - None => CheckedExtrinsic { signed: None, function: self.function }, + Preamble::General(extra) => CheckedExtrinsic { + format: ExtrinsicFormat::General(extra), + function: self.function, + }, + Preamble::Bare => + CheckedExtrinsic { format: ExtrinsicFormat::Bare, function: self.function }, }) } } -impl ExtrinsicMetadata - for UncheckedExtrinsic -where - Extra: SignedExtension, +impl> + ExtrinsicMetadata for UncheckedExtrinsic { const VERSION: u8 = EXTRINSIC_FORMAT_VERSION; - type SignedExtensions = Extra; -} - -/// A payload that has been signed for an unchecked extrinsics. -/// -/// Note that the payload that we sign to produce unchecked extrinsic signature -/// is going to be different than the `SignaturePayload` - so the thing the extrinsic -/// actually contains. -pub struct SignedPayload((Call, Extra, Extra::AdditionalSigned)); - -impl SignedPayload -where - Call: Encode, - Extra: SignedExtension, -{ - /// Create new `SignedPayload`. - /// - /// This function may fail if `additional_signed` of `Extra` is not available. - pub fn new(call: Call, extra: Extra) -> Result { - let additional_signed = extra.additional_signed()?; - let raw_payload = (call, extra, additional_signed); - Ok(Self(raw_payload)) - } - - /// Create new `SignedPayload` from raw components. - pub fn from_raw(call: Call, extra: Extra, additional_signed: Extra::AdditionalSigned) -> Self { - Self((call, extra, additional_signed)) - } - - /// Deconstruct the payload into it's components. - pub fn deconstruct(self) -> (Call, Extra, Extra::AdditionalSigned) { - self.0 - } + type Extra = Extension; } -impl Encode for SignedPayload -where - Call: Encode, - Extra: SignedExtension, -{ - /// Get an encoded version of this payload. - /// - /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. - fn using_encoded R>(&self, f: F) -> R { - self.0.using_encoded(|payload| { - if payload.len() > 256 { - f(&blake2_256(payload)[..]) - } else { - f(payload) - } - }) - } -} - -impl EncodeLike for SignedPayload -where - Call: Encode, - Extra: SignedExtension, -{ -} - -impl Decode for UncheckedExtrinsic +impl Decode + for UncheckedExtrinsic where Address: Decode, Signature: Decode, Call: Decode, - Extra: SignedExtension, + Extension: Decode, { fn decode(input: &mut I) -> Result { // This is a little more complicated than usual since the binary format must be compatible @@ -282,15 +316,7 @@ where let expected_length: Compact = Decode::decode(input)?; let before_length = input.remaining_len()?; - let version = input.read_byte()?; - - let is_signed = version & 0b1000_0000 != 0; - let version = version & 0b0111_1111; - if version != EXTRINSIC_FORMAT_VERSION { - return Err("Invalid transaction version".into()) - } - - let signature = is_signed.then(|| Decode::decode(input)).transpose()?; + let preamble = Decode::decode(input)?; let function = Decode::decode(input)?; if let Some((before_length, after_length)) = @@ -303,31 +329,20 @@ where } } - Ok(Self { signature, function }) + Ok(Self { preamble, function }) } } #[docify::export(unchecked_extrinsic_encode_impl)] -impl Encode for UncheckedExtrinsic +impl Encode + for UncheckedExtrinsic where - Address: Encode, - Signature: Encode, + Preamble: Encode, Call: Encode, - Extra: SignedExtension, + Extension: Encode, { fn encode(&self) -> Vec { - let mut tmp = Vec::with_capacity(sp_std::mem::size_of::()); - - // 1 byte version id. - match self.signature.as_ref() { - Some(s) => { - tmp.push(EXTRINSIC_FORMAT_VERSION | 0b1000_0000); - s.encode_to(&mut tmp); - }, - None => { - tmp.push(EXTRINSIC_FORMAT_VERSION & 0b0111_1111); - }, - } + let mut tmp = self.preamble.encode(); self.function.encode_to(&mut tmp); let compact_len = codec::Compact::(tmp.len() as u32); @@ -342,19 +357,19 @@ where } } -impl EncodeLike - for UncheckedExtrinsic +impl EncodeLike + for UncheckedExtrinsic where Address: Encode, Signature: Encode, - Call: Encode, - Extra: SignedExtension, + Call: Encode + Dispatchable, + Extension: TransactionExtension, { } #[cfg(feature = "serde")] -impl serde::Serialize - for UncheckedExtrinsic +impl serde::Serialize + for UncheckedExtrinsic { fn serialize(&self, seq: S) -> Result where @@ -365,45 +380,88 @@ impl s } #[cfg(feature = "serde")] -impl<'a, Address: Decode, Signature: Decode, Call: Decode, Extra: SignedExtension> - serde::Deserialize<'a> for UncheckedExtrinsic +impl<'a, Address: Decode, Signature: Decode, Call: Decode, Extension: Decode> serde::Deserialize<'a> + for UncheckedExtrinsic { fn deserialize(de: D) -> Result where D: serde::Deserializer<'a>, { let r = sp_core::bytes::deserialize(de)?; - Decode::decode(&mut &r[..]) + Self::decode(&mut &r[..]) .map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e))) } } -impl fmt::Debug - for UncheckedExtrinsic +/// A payload that has been signed for an unchecked extrinsics. +/// +/// Note that the payload that we sign to produce unchecked extrinsic signature +/// is going to be different than the `SignaturePayload` - so the thing the extrinsic +/// actually contains. +pub struct SignedPayload( + (Call, Extension, Extension::Implicit), +); + +impl SignedPayload where - Address: fmt::Debug, - Call: fmt::Debug, - Extra: SignedExtension, + Call: Encode + Dispatchable, + Extension: TransactionExtensionBase, { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "UncheckedExtrinsic({:?}, {:?})", - self.signature.as_ref().map(|x| (&x.0, &x.2)), - self.function, - ) + /// Create new `SignedPayload`. + /// + /// This function may fail if `implicit` of `Extension` is not available. + pub fn new(call: Call, tx_ext: Extension) -> Result { + let implicit = Extension::implicit(&tx_ext)?; + let raw_payload = (call, tx_ext, implicit); + Ok(Self(raw_payload)) + } + + /// Create new `SignedPayload` from raw components. + pub fn from_raw(call: Call, tx_ext: Extension, implicit: Extension::Implicit) -> Self { + Self((call, tx_ext, implicit)) + } + + /// Deconstruct the payload into it's components. + pub fn deconstruct(self) -> (Call, Extension, Extension::Implicit) { + self.0 } } -impl From> - for OpaqueExtrinsic +impl Encode for SignedPayload +where + Call: Encode + Dispatchable, + Extension: TransactionExtensionBase, +{ + /// Get an encoded version of this payload. + /// + /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. + fn using_encoded R>(&self, f: F) -> R { + self.0.using_encoded(|payload| { + if payload.len() > 256 { + f(&blake2_256(payload)[..]) + } else { + f(payload) + } + }) + } +} + +impl EncodeLike for SignedPayload +where + Call: Encode + Dispatchable, + Extension: TransactionExtensionBase, +{ +} + +impl + From> for OpaqueExtrinsic where Address: Encode, Signature: Encode, Call: Encode, - Extra: SignedExtension, + Extension: Encode, { - fn from(extrinsic: UncheckedExtrinsic) -> Self { + fn from(extrinsic: UncheckedExtrinsic) -> Self { Self::from_bytes(extrinsic.encode().as_slice()).expect( "both OpaqueExtrinsic and UncheckedExtrinsic have encoding that is compatible with \ raw Vec encoding; qed", @@ -411,60 +469,198 @@ where } } +#[cfg(test)] +mod legacy { + use codec::{Compact, Decode, Encode, EncodeLike, Error, Input}; + use scale_info::{ + build::Fields, meta_type, Path, StaticTypeInfo, Type, TypeInfo, TypeParameter, + }; + + pub type OldUncheckedSignaturePayload = (Address, Signature, Extra); + + #[derive(PartialEq, Eq, Clone, Debug)] + pub struct OldUncheckedExtrinsic { + pub signature: Option>, + pub function: Call, + } + + impl TypeInfo + for OldUncheckedExtrinsic + where + Address: StaticTypeInfo, + Call: StaticTypeInfo, + Signature: StaticTypeInfo, + Extra: StaticTypeInfo, + { + type Identity = OldUncheckedExtrinsic; + + fn type_info() -> Type { + Type::builder() + .path(Path::new("UncheckedExtrinsic", module_path!())) + // Include the type parameter types, even though they are not used directly in any + // of the described fields. These type definitions can be used by downstream + // consumers to help construct the custom decoding from the opaque bytes (see + // below). + .type_params(vec![ + TypeParameter::new("Address", Some(meta_type::
())), + TypeParameter::new("Call", Some(meta_type::())), + TypeParameter::new("Signature", Some(meta_type::())), + TypeParameter::new("Extra", Some(meta_type::())), + ]) + .docs(&["OldUncheckedExtrinsic raw bytes, requires custom decoding routine"]) + // Because of the custom encoding, we can only accurately describe the encoding as + // an opaque `Vec`. Downstream consumers will need to manually implement the + // codec to encode/decode the `signature` and `function` fields. + .composite(Fields::unnamed().field(|f| f.ty::>())) + } + } + + impl OldUncheckedExtrinsic { + pub fn new_signed( + function: Call, + signed: Address, + signature: Signature, + extra: Extra, + ) -> Self { + Self { signature: Some((signed, signature, extra)), function } + } + + pub fn new_unsigned(function: Call) -> Self { + Self { signature: None, function } + } + } + + impl Decode + for OldUncheckedExtrinsic + where + Address: Decode, + Signature: Decode, + Call: Decode, + Extra: Decode, + { + fn decode(input: &mut I) -> Result { + // This is a little more complicated than usual since the binary format must be + // compatible with SCALE's generic `Vec` type. Basically this just means accepting + // that there will be a prefix of vector length. + let expected_length: Compact = Decode::decode(input)?; + let before_length = input.remaining_len()?; + + let version = input.read_byte()?; + + let is_signed = version & 0b1000_0000 != 0; + let version = version & 0b0111_1111; + if version != 4u8 { + return Err("Invalid transaction version".into()) + } + + let signature = is_signed.then(|| Decode::decode(input)).transpose()?; + let function = Decode::decode(input)?; + + if let Some((before_length, after_length)) = + input.remaining_len()?.and_then(|a| before_length.map(|b| (b, a))) + { + let length = before_length.saturating_sub(after_length); + + if length != expected_length.0 as usize { + return Err("Invalid length prefix".into()) + } + } + + Ok(Self { signature, function }) + } + } + + #[docify::export(unchecked_extrinsic_encode_impl)] + impl Encode + for OldUncheckedExtrinsic + where + Address: Encode, + Signature: Encode, + Call: Encode, + Extra: Encode, + { + fn encode(&self) -> Vec { + let mut tmp = Vec::with_capacity(sp_std::mem::size_of::()); + + // 1 byte version id. + match self.signature.as_ref() { + Some(s) => { + tmp.push(4u8 | 0b1000_0000); + s.encode_to(&mut tmp); + }, + None => { + tmp.push(4u8 & 0b0111_1111); + }, + } + self.function.encode_to(&mut tmp); + + let compact_len = codec::Compact::(tmp.len() as u32); + + // Allocate the output buffer with the correct length + let mut output = Vec::with_capacity(compact_len.size_hint() + tmp.len()); + + compact_len.encode_to(&mut output); + output.extend(tmp); + + output + } + } + + impl EncodeLike + for OldUncheckedExtrinsic + where + Address: Encode, + Signature: Encode, + Call: Encode, + Extra: Encode, + { + } +} + #[cfg(test)] mod tests { - use super::*; + use super::{legacy::OldUncheckedExtrinsic, *}; use crate::{ codec::{Decode, Encode}, + impl_tx_ext_default, testing::TestSignature as TestSig, - traits::{DispatchInfoOf, IdentityLookup, SignedExtension}, + traits::{FakeDispatchable, IdentityLookup, TransactionExtension}, }; use sp_io::hashing::blake2_256; type TestContext = IdentityLookup; type TestAccountId = u64; - type TestCall = Vec; + type TestCall = FakeDispatchable>; const TEST_ACCOUNT: TestAccountId = 0; // NOTE: this is demonstration. One can simply use `()` for testing. #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, TypeInfo)] - struct TestExtra; - impl SignedExtension for TestExtra { - const IDENTIFIER: &'static str = "TestExtra"; - type AccountId = u64; - type Call = (); - type AdditionalSigned = (); + struct DummyExtension; + impl TransactionExtensionBase for DummyExtension { + const IDENTIFIER: &'static str = "DummyExtension"; + type Implicit = (); + } + impl TransactionExtension for DummyExtension { + type Val = (); type Pre = (); - - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) - } + impl_tx_ext_default!(TestCall; Context; validate prepare); } - type Ex = UncheckedExtrinsic; - type CEx = CheckedExtrinsic; + type Ex = UncheckedExtrinsic; + type CEx = CheckedExtrinsic; #[test] fn unsigned_codec_should_work() { - let ux = Ex::new_unsigned(vec![0u8; 0]); + let call: TestCall = vec![0u8; 0].into(); + let ux = Ex::new_inherent(call); let encoded = ux.encode(); assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); } #[test] fn invalid_length_prefix_is_detected() { - let ux = Ex::new_unsigned(vec![0u8; 0]); + let ux = Ex::new_inherent(vec![0u8; 0].into()); let mut encoded = ux.encode(); let length = Compact::::decode(&mut &encoded[..]).unwrap(); @@ -473,13 +669,20 @@ mod tests { assert_eq!(Ex::decode(&mut &encoded[..]), Err("Invalid length prefix".into())); } + #[test] + fn transaction_codec_should_work() { + let ux = Ex::new_transaction(vec![0u8; 0].into(), DummyExtension); + let encoded = ux.encode(); + assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); + } + #[test] fn signed_codec_should_work() { let ux = Ex::new_signed( - vec![0u8; 0], + vec![0u8; 0].into(), TEST_ACCOUNT, - TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()), - TestExtra, + TestSig(TEST_ACCOUNT, (vec![0u8; 0], DummyExtension).encode()), + DummyExtension, ); let encoded = ux.encode(); assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); @@ -488,13 +691,13 @@ mod tests { #[test] fn large_signed_codec_should_work() { let ux = Ex::new_signed( - vec![0u8; 0], + vec![0u8; 0].into(), TEST_ACCOUNT, TestSig( TEST_ACCOUNT, - (vec![0u8; 257], TestExtra).using_encoded(blake2_256)[..].to_owned(), + (vec![0u8; 257], DummyExtension).using_encoded(blake2_256)[..].to_owned(), ), - TestExtra, + DummyExtension, ); let encoded = ux.encode(); assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); @@ -502,44 +705,63 @@ mod tests { #[test] fn unsigned_check_should_work() { - let ux = Ex::new_unsigned(vec![0u8; 0]); - assert!(!ux.is_signed().unwrap_or(false)); - assert!(>::check(ux, &Default::default()).is_ok()); + let ux = Ex::new_inherent(vec![0u8; 0].into()); + assert!(ux.is_inherent()); + assert_eq!( + >::check(ux, &Default::default()), + Ok(CEx { format: ExtrinsicFormat::Bare, function: vec![0u8; 0].into() }), + ); } #[test] fn badly_signed_check_should_fail() { let ux = Ex::new_signed( - vec![0u8; 0], + vec![0u8; 0].into(), TEST_ACCOUNT, - TestSig(TEST_ACCOUNT, vec![0u8; 0]), - TestExtra, + TestSig(TEST_ACCOUNT, vec![0u8; 0].into()), + DummyExtension, ); - assert!(ux.is_signed().unwrap_or(false)); + assert!(!ux.is_inherent()); assert_eq!( >::check(ux, &Default::default()), Err(InvalidTransaction::BadProof.into()), ); } + #[test] + fn transaction_check_should_work() { + let ux = Ex::new_transaction(vec![0u8; 0].into(), DummyExtension); + assert!(!ux.is_inherent()); + assert_eq!( + >::check(ux, &Default::default()), + Ok(CEx { + format: ExtrinsicFormat::General(DummyExtension), + function: vec![0u8; 0].into() + }), + ); + } + #[test] fn signed_check_should_work() { let ux = Ex::new_signed( - vec![0u8; 0], + vec![0u8; 0].into(), TEST_ACCOUNT, - TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()), - TestExtra, + TestSig(TEST_ACCOUNT, (vec![0u8; 0], DummyExtension).encode()), + DummyExtension, ); - assert!(ux.is_signed().unwrap_or(false)); + assert!(!ux.is_inherent()); assert_eq!( >::check(ux, &Default::default()), - Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }), + Ok(CEx { + format: ExtrinsicFormat::Signed(TEST_ACCOUNT, DummyExtension), + function: vec![0u8; 0].into() + }), ); } #[test] fn encoding_matches_vec() { - let ex = Ex::new_unsigned(vec![0u8; 0]); + let ex = Ex::new_inherent(vec![0u8; 0].into()); let encoded = ex.encode(); let decoded = Ex::decode(&mut encoded.as_slice()).unwrap(); assert_eq!(decoded, ex); @@ -549,7 +771,7 @@ mod tests { #[test] fn conversion_to_opaque() { - let ux = Ex::new_unsigned(vec![0u8; 0]); + let ux = Ex::new_inherent(vec![0u8; 0].into()); let encoded = ux.encode(); let opaque: OpaqueExtrinsic = ux.into(); let opaque_encoded = opaque.encode(); @@ -558,10 +780,62 @@ mod tests { #[test] fn large_bad_prefix_should_work() { - let encoded = Compact::::from(u32::MAX).encode(); - assert_eq!( - Ex::decode(&mut &encoded[..]), - Err(Error::from("Not enough data to fill buffer")) - ); + let encoded = (Compact::::from(u32::MAX), Preamble::<(), (), ()>::Bare).encode(); + assert!(Ex::decode(&mut &encoded[..]).is_err()); + } + + #[test] + fn legacy_signed_encode_decode() { + let call: TestCall = vec![0u8; 0].into(); + let signed = TEST_ACCOUNT; + let signature = TestSig(TEST_ACCOUNT, (vec![0u8; 0], DummyExtension).encode()); + let extension = DummyExtension; + + let new_ux = Ex::new_signed(call.clone(), signed, signature.clone(), extension.clone()); + let old_ux = + OldUncheckedExtrinsic::::new_signed( + call, signed, signature, extension, + ); + + let encoded_new_ux = new_ux.encode(); + let encoded_old_ux = old_ux.encode(); + + assert_eq!(encoded_new_ux, encoded_old_ux); + + let decoded_new_ux = Ex::decode(&mut &encoded_new_ux[..]).unwrap(); + let decoded_old_ux = + OldUncheckedExtrinsic::::decode( + &mut &encoded_old_ux[..], + ) + .unwrap(); + + assert_eq!(new_ux, decoded_new_ux); + assert_eq!(old_ux, decoded_old_ux); + } + + #[test] + fn legacy_unsigned_encode_decode() { + let call: TestCall = vec![0u8; 0].into(); + + let new_ux = Ex::new_bare(call.clone()); + let old_ux = + OldUncheckedExtrinsic::::new_unsigned( + call, + ); + + let encoded_new_ux = new_ux.encode(); + let encoded_old_ux = old_ux.encode(); + + assert_eq!(encoded_new_ux, encoded_old_ux); + + let decoded_new_ux = Ex::decode(&mut &encoded_new_ux[..]).unwrap(); + let decoded_old_ux = + OldUncheckedExtrinsic::::decode( + &mut &encoded_old_ux[..], + ) + .unwrap(); + + assert_eq!(new_ux, decoded_new_ux); + assert_eq!(old_ux, decoded_old_ux); } } diff --git a/substrate/primitives/runtime/src/lib.rs b/substrate/primitives/runtime/src/lib.rs index 44bf3c969e5..70605970b4e 100644 --- a/substrate/primitives/runtime/src/lib.rs +++ b/substrate/primitives/runtime/src/lib.rs @@ -125,6 +125,11 @@ pub use sp_arithmetic::{ Perquintill, Rational128, Rounding, UpperOf, }; +pub use transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidityError, UnknownTransaction, + ValidTransaction, +}; + pub use either::Either; /// The number of bytes of the module-specific `error` field defined in [`ModuleError`]. @@ -443,21 +448,21 @@ impl std::fmt::Display for MultiSigner { impl Verify for MultiSignature { type Signer = MultiSigner; fn verify>(&self, mut msg: L, signer: &AccountId32) -> bool { - match (self, signer) { - (Self::Ed25519(ref sig), who) => match ed25519::Public::from_slice(who.as_ref()) { + match self { + Self::Ed25519(ref sig) => match ed25519::Public::from_slice(signer.as_ref()) { Ok(signer) => sig.verify(msg, &signer), Err(()) => false, }, - (Self::Sr25519(ref sig), who) => match sr25519::Public::from_slice(who.as_ref()) { + Self::Sr25519(ref sig) => match sr25519::Public::from_slice(signer.as_ref()) { Ok(signer) => sig.verify(msg, &signer), Err(()) => false, }, - (Self::Ecdsa(ref sig), who) => { + Self::Ecdsa(ref sig) => { let m = sp_io::hashing::blake2_256(msg.get()); match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { Ok(pubkey) => &sp_io::hashing::blake2_256(pubkey.as_ref()) == - >::as_ref(who), + >::as_ref(signer), _ => false, } }, @@ -944,9 +949,13 @@ impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic { } } +// TODO: OpaqueExtrinsics cannot act like regular extrinsics, right?! impl traits::Extrinsic for OpaqueExtrinsic { type Call = (); type SignaturePayload = (); + fn is_bare(&self) -> bool { + false + } } /// Print something that implements `Printable` from the runtime. diff --git a/substrate/primitives/runtime/src/testing.rs b/substrate/primitives/runtime/src/testing.rs index 5f94c834a8f..3d6e0b5ab8b 100644 --- a/substrate/primitives/runtime/src/testing.rs +++ b/substrate/primitives/runtime/src/testing.rs @@ -21,24 +21,16 @@ use crate::{ codec::{Codec, Decode, Encode, MaxEncodedLen}, generic, scale_info::TypeInfo, - traits::{ - self, Applyable, BlakeTwo256, Checkable, DispatchInfoOf, Dispatchable, OpaqueKeys, - PostDispatchInfoOf, SignaturePayload, SignedExtension, ValidateUnsigned, - }, - transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, - ApplyExtrinsicResultWithInfo, KeyTypeId, + traits::{self, BlakeTwo256, Dispatchable, OpaqueKeys}, + DispatchResultWithInfo, KeyTypeId, }; -use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize}; use sp_core::{ crypto::{key_types, ByteArray, CryptoType, Dummy}, U256, }; pub use sp_core::{sr25519, H256}; -use std::{ - cell::RefCell, - fmt::{self, Debug}, - ops::Deref, -}; +use std::{cell::RefCell, fmt::Debug}; /// A dummy type which can be used instead of regular cryptographic primitives. /// @@ -198,42 +190,6 @@ impl Header { } } -/// An opaque extrinsic wrapper type. -#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] -pub struct ExtrinsicWrapper(Xt); - -impl traits::Extrinsic for ExtrinsicWrapper { - type Call = (); - type SignaturePayload = (); - - fn is_signed(&self) -> Option { - None - } -} - -impl serde::Serialize for ExtrinsicWrapper { - fn serialize(&self, seq: S) -> Result - where - S: ::serde::Serializer, - { - self.using_encoded(|bytes| seq.serialize_bytes(bytes)) - } -} - -impl From for ExtrinsicWrapper { - fn from(xt: Xt) -> Self { - ExtrinsicWrapper(xt) - } -} - -impl Deref for ExtrinsicWrapper { - type Target = Xt; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - /// Testing block #[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode, TypeInfo)] pub struct Block { @@ -283,139 +239,22 @@ where } } -/// The signature payload of a `TestXt`. -type TxSingaturePayload = (u64, Extra); - -impl SignaturePayload for TxSingaturePayload { - type SignatureAddress = u64; - type Signature = (); - type SignatureExtra = Extra; -} - -/// Test transaction, tuple of (sender, call, signed_extra) -/// with index only used if sender is some. -/// -/// If sender is some then the transaction is signed otherwise it is unsigned. -#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] -pub struct TestXt { - /// Signature of the extrinsic. - pub signature: Option>, - /// Call of the extrinsic. - pub call: Call, -} - -impl TestXt { - /// Create a new `TextXt`. - pub fn new(call: Call, signature: Option<(u64, Extra)>) -> Self { - Self { call, signature } - } -} - -impl Serialize for TestXt -where - TestXt: Encode, -{ - fn serialize(&self, seq: S) -> Result - where - S: Serializer, - { - self.using_encoded(|bytes| seq.serialize_bytes(bytes)) - } -} +/// Wrapper over a `u64` that can be used as a `RuntimeCall`. +#[derive(PartialEq, Eq, Debug, Clone, Encode, Decode, TypeInfo)] +pub struct MockCallU64(pub u64); -impl Debug for TestXt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TestXt({:?}, ...)", self.signature.as_ref().map(|x| &x.0)) +impl Dispatchable for MockCallU64 { + type RuntimeOrigin = u64; + type Config = (); + type Info = (); + type PostInfo = (); + fn dispatch(self, _origin: Self::RuntimeOrigin) -> DispatchResultWithInfo { + Ok(()) } } -impl Checkable for TestXt { - type Checked = Self; - fn check(self, _: &Context) -> Result { - Ok(self) - } - - #[cfg(feature = "try-runtime")] - fn unchecked_into_checked_i_know_what_i_am_doing( - self, - _: &Context, - ) -> Result { - unreachable!() - } -} - -impl traits::Extrinsic - for TestXt -{ - type Call = Call; - type SignaturePayload = TxSingaturePayload; - - fn is_signed(&self) -> Option { - Some(self.signature.is_some()) - } - - fn new(c: Call, sig: Option) -> Option { - Some(TestXt { signature: sig, call: c }) - } -} - -impl traits::ExtrinsicMetadata for TestXt -where - Call: Codec + Sync + Send, - Extra: SignedExtension, -{ - type SignedExtensions = Extra; - const VERSION: u8 = 0u8; -} - -impl Applyable for TestXt -where - Call: 'static - + Sized - + Send - + Sync - + Clone - + Eq - + Codec - + Debug - + Dispatchable, - Extra: SignedExtension, - Origin: From>, -{ - type Call = Call; - - /// Checks to see if this is a valid *transaction*. It returns information on it if so. - fn validate>( - &self, - source: TransactionSource, - info: &DispatchInfoOf, - len: usize, - ) -> TransactionValidity { - if let Some((ref id, ref extra)) = self.signature { - Extra::validate(extra, id, &self.call, info, len) - } else { - let valid = Extra::validate_unsigned(&self.call, info, len)?; - let unsigned_validation = U::validate_unsigned(source, &self.call)?; - Ok(valid.combine_with(unsigned_validation)) - } - } - - /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, - /// index and sender. - fn apply>( - self, - info: &DispatchInfoOf, - len: usize, - ) -> ApplyExtrinsicResultWithInfo> { - let maybe_who = if let Some((who, extra)) = self.signature { - Extra::pre_dispatch(extra, &who, &self.call, info, len)?; - Some(who) - } else { - Extra::pre_dispatch_unsigned(&self.call, info, len)?; - U::pre_dispatch(&self.call)?; - None - }; - - Ok(self.call.dispatch(maybe_who.into())) +impl From for MockCallU64 { + fn from(value: u64) -> Self { + Self(value) } } diff --git a/substrate/primitives/runtime/src/traits.rs b/substrate/primitives/runtime/src/traits/mod.rs similarity index 94% rename from substrate/primitives/runtime/src/traits.rs rename to substrate/primitives/runtime/src/traits/mod.rs index caede5e2b59..b217166d8de 100644 --- a/substrate/primitives/runtime/src/traits.rs +++ b/substrate/primitives/runtime/src/traits/mod.rs @@ -19,7 +19,7 @@ use crate::{ generic::Digest, - scale_info::{MetaType, StaticTypeInfo, TypeInfo}, + scale_info::{StaticTypeInfo, TypeInfo}, transaction_validity::{ TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction, ValidTransaction, @@ -52,6 +52,12 @@ use std::fmt::Display; #[cfg(feature = "std")] use std::str::FromStr; +pub mod transaction_extension; +pub use transaction_extension::{ + DispatchTransaction, TransactionExtension, TransactionExtensionBase, + TransactionExtensionInterior, TransactionExtensionMetadata, ValidateResult, +}; + /// A lazy value. pub trait Lazy { /// Get a reference to the underlying value. @@ -1253,7 +1259,7 @@ pub trait Header: // that is then used to define `UncheckedExtrinsic`. // ```ignore // pub type UncheckedExtrinsic = -// generic::UncheckedExtrinsic; +// generic::UncheckedExtrinsic; // ``` // This `UncheckedExtrinsic` is supplied to the `Block`. // ```ignore @@ -1323,19 +1329,31 @@ pub trait Extrinsic: Sized { /// Is this `Extrinsic` signed? /// If no information are available about signed/unsigned, `None` should be returned. + #[deprecated = "Use and implement `!is_bare()` instead"] fn is_signed(&self) -> Option { None } - /// Create new instance of the extrinsic. - /// - /// Extrinsics can be split into: - /// 1. Inherents (no signature; created by validators during block production) - /// 2. Unsigned Transactions (no signature; represent "system calls" or other special kinds of - /// calls) 3. Signed Transactions (with signature; a regular transactions with known origin) + /// Returns `true` if this `Extrinsic` is bare. + fn is_bare(&self) -> bool { + #[allow(deprecated)] + !self + .is_signed() + .expect("`is_signed` must return `Some` on production extrinsics; qed") + } + + /// Create a new old-school extrinsic, either a bare extrinsic if `_signed_data` is `None` or + /// a signed transaction is it is `Some`. + #[deprecated = "Use `new_inherent` or the `CreateTransaction` trait instead"] fn new(_call: Self::Call, _signed_data: Option) -> Option { None } + + /// Create a new inherent extrinsic. + fn new_inherent(function: Self::Call) -> Self { + #[allow(deprecated)] + Self::new(function, None).expect("Extrinsic must provide inherents; qed") + } } /// Something that acts like a [`SignaturePayload`](Extrinsic::SignaturePayload) of an @@ -1371,7 +1389,8 @@ pub trait ExtrinsicMetadata { const VERSION: u8; /// Signed extensions attached to this `Extrinsic`. - type SignedExtensions: SignedExtension; + // TODO: metadata-v16: rename to `Extension`. + type Extra; } /// Extract the hashing type for a block. @@ -1456,6 +1475,8 @@ pub trait Dispatchable { -> crate::DispatchResultWithInfo; } +/// Shortcut to reference the `Origin` type of a `Dispatchable`. +pub type OriginOf = ::RuntimeOrigin; /// Shortcut to reference the `Info` type of a `Dispatchable`. pub type DispatchInfoOf = ::Info; /// Shortcut to reference the `PostInfo` type of a `Dispatchable`. @@ -1474,8 +1495,49 @@ impl Dispatchable for () { } } +/// Dispatchable impl containing an arbitrary value which panics if it actually is dispatched. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct FakeDispatchable(pub Inner); +impl From for FakeDispatchable { + fn from(inner: Inner) -> Self { + Self(inner) + } +} +impl FakeDispatchable { + /// Take `self` and return the underlying inner value. + pub fn deconstruct(self) -> Inner { + self.0 + } +} +impl AsRef for FakeDispatchable { + fn as_ref(&self) -> &Inner { + &self.0 + } +} + +impl Dispatchable for FakeDispatchable { + type RuntimeOrigin = (); + type Config = (); + type Info = (); + type PostInfo = (); + fn dispatch( + self, + _origin: Self::RuntimeOrigin, + ) -> crate::DispatchResultWithInfo { + panic!("This implementation should not be used for actual dispatch."); + } +} + +/// Runtime Origin which includes a System Origin variant whose `AccountId` is the parameter. +pub trait AsSystemOriginSigner { + /// Extract a reference of the inner value of the System `Origin::Signed` variant, if self has + /// that variant. + fn as_system_origin_signer(&self) -> Option<&AccountId>; +} + /// Means by which a transaction may be extended. This type embodies both the data and the logic /// that should be additionally associated with the transaction. It should be plain old data. +#[deprecated = "Use `TransactionExtension` instead."] pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo { @@ -1493,7 +1555,7 @@ pub trait SignedExtension: /// Any additional data that will go into the signed payload. This may be created dynamically /// from the transaction using the `additional_signed` function. - type AdditionalSigned: Encode + TypeInfo; + type AdditionalSigned: Codec + TypeInfo; /// The type that encodes information that can be passed from pre_dispatch to post-dispatch. type Pre; @@ -1532,38 +1594,6 @@ pub trait SignedExtension: len: usize, ) -> Result; - /// Validate an unsigned transaction for the transaction queue. - /// - /// This function can be called frequently by the transaction queue - /// to obtain transaction validity against current state. - /// It should perform all checks that determine a valid unsigned transaction, - /// and quickly eliminate ones that are stale or incorrect. - /// - /// Make sure to perform the same checks in `pre_dispatch_unsigned` function. - fn validate_unsigned( - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> TransactionValidity { - Ok(ValidTransaction::default()) - } - - /// Do any pre-flight stuff for a unsigned transaction. - /// - /// Note this function by default delegates to `validate_unsigned`, so that - /// all checks performed for the transaction queue are also performed during - /// the dispatch phase (applying the extrinsic). - /// - /// If you ever override this function, you need to make sure to always - /// perform the same validation as in `validate_unsigned`. - fn pre_dispatch_unsigned( - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result<(), TransactionValidityError> { - Self::validate_unsigned(call, info, len).map(|_| ()).map_err(Into::into) - } - /// Do any post-flight stuff for an extrinsic. /// /// If the transaction is signed, then `_pre` will contain the output of `pre_dispatch`, @@ -1594,126 +1624,47 @@ pub trait SignedExtension: /// /// As a [`SignedExtension`] can be a tuple of [`SignedExtension`]s we need to return a `Vec` /// that holds the metadata of each one. Each individual `SignedExtension` must return - /// *exactly* one [`SignedExtensionMetadata`]. + /// *exactly* one [`TransactionExtensionMetadata`]. /// /// This method provides a default implementation that returns a vec containing a single - /// [`SignedExtensionMetadata`]. - fn metadata() -> Vec { - sp_std::vec![SignedExtensionMetadata { + /// [`TransactionExtensionMetadata`]. + fn metadata() -> Vec { + sp_std::vec![TransactionExtensionMetadata { identifier: Self::IDENTIFIER, ty: scale_info::meta_type::(), additional_signed: scale_info::meta_type::() }] } -} - -/// Information about a [`SignedExtension`] for the runtime metadata. -pub struct SignedExtensionMetadata { - /// The unique identifier of the [`SignedExtension`]. - pub identifier: &'static str, - /// The type of the [`SignedExtension`]. - pub ty: MetaType, - /// The type of the [`SignedExtension`] additional signed data for the payload. - pub additional_signed: MetaType, -} - -#[impl_for_tuples(1, 12)] -impl SignedExtension for Tuple { - for_tuples!( where #( Tuple: SignedExtension )* ); - type AccountId = AccountId; - type Call = Call; - const IDENTIFIER: &'static str = "You should call `identifier()`!"; - for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); - for_tuples!( type Pre = ( #( Tuple::Pre ),* ); ); - - fn additional_signed(&self) -> Result { - Ok(for_tuples!( ( #( Tuple.additional_signed()? ),* ) )) - } - - fn validate( - &self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> TransactionValidity { - let valid = ValidTransaction::default(); - for_tuples!( #( let valid = valid.combine_with(Tuple.validate(who, call, info, len)?); )* ); - Ok(valid) - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - Ok(for_tuples!( ( #( Tuple.pre_dispatch(who, call, info, len)? ),* ) )) - } + /// Validate an unsigned transaction for the transaction queue. + /// + /// This function can be called frequently by the transaction queue + /// to obtain transaction validity against current state. + /// It should perform all checks that determine a valid unsigned transaction, + /// and quickly eliminate ones that are stale or incorrect. fn validate_unsigned( - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, ) -> TransactionValidity { - let valid = ValidTransaction::default(); - for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info, len)?); )* ); - Ok(valid) + Ok(ValidTransaction::default()) } + /// Do any pre-flight stuff for an unsigned transaction. + /// + /// Note this function by default delegates to `validate_unsigned`, so that + /// all checks performed for the transaction queue are also performed during + /// the dispatch phase (applying the extrinsic). + /// + /// If you ever override this function, you need not perform the same validation as in + /// `validate_unsigned`. fn pre_dispatch_unsigned( - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, ) -> Result<(), TransactionValidityError> { - for_tuples!( #( Tuple::pre_dispatch_unsigned(call, info, len)?; )* ); Ok(()) } - - fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, - len: usize, - result: &DispatchResult, - ) -> Result<(), TransactionValidityError> { - match pre { - Some(x) => { - for_tuples!( #( Tuple::post_dispatch(Some(x.Tuple), info, post_info, len, result)?; )* ); - }, - None => { - for_tuples!( #( Tuple::post_dispatch(None, info, post_info, len, result)?; )* ); - }, - } - Ok(()) - } - - fn metadata() -> Vec { - let mut ids = Vec::new(); - for_tuples!( #( ids.extend(Tuple::metadata()); )* ); - ids - } -} - -impl SignedExtension for () { - type AccountId = u64; - type AdditionalSigned = (); - type Call = (); - type Pre = (); - const IDENTIFIER: &'static str = "UnitSignedExtension"; - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) - } - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| ()) - } } /// An "executable" piece of information, used by the standard Substrate Executive in order to @@ -1762,6 +1713,7 @@ pub trait GetNodeBlockType { /// function is called right before dispatching the call wrapped by an unsigned extrinsic. The /// [`validate_unsigned`](Self::validate_unsigned) function is mainly being used in the context of /// the transaction pool to check the validity of the call wrapped by an unsigned extrinsic. +// TODO: Rename to ValidateBareTransaction (or just remove). pub trait ValidateUnsigned { /// The call to validate type Call; diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs b/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs new file mode 100644 index 00000000000..a834e88c0b4 --- /dev/null +++ b/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs @@ -0,0 +1,133 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! The [AsTransactionExtension] adapter struct for adapting [SignedExtension]s to +//! [TransactionExtension]s. + +#![allow(deprecated)] + +use scale_info::TypeInfo; +use sp_core::RuntimeDebug; + +use crate::{ + traits::{AsSystemOriginSigner, SignedExtension, ValidateResult}, + InvalidTransaction, +}; + +use super::*; + +/// Adapter to use a `SignedExtension` in the place of a `TransactionExtension`. +#[derive(TypeInfo, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[deprecated = "Convert your SignedExtension to a TransactionExtension."] +pub struct AsTransactionExtension(pub SE); + +impl Default for AsTransactionExtension { + fn default() -> Self { + Self(SE::default()) + } +} + +impl From for AsTransactionExtension { + fn from(value: SE) -> Self { + Self(value) + } +} + +impl TransactionExtensionBase for AsTransactionExtension { + const IDENTIFIER: &'static str = SE::IDENTIFIER; + type Implicit = SE::AdditionalSigned; + + fn implicit(&self) -> Result { + self.0.additional_signed() + } + fn metadata() -> Vec { + SE::metadata() + } +} + +impl TransactionExtension + for AsTransactionExtension +where + ::RuntimeOrigin: AsSystemOriginSigner + Clone, +{ + type Val = (); + type Pre = SE::Pre; + + fn validate( + &self, + origin: ::RuntimeOrigin, + call: &SE::Call, + info: &DispatchInfoOf, + len: usize, + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + let r = self.0.validate(who, call, info, len)?; + Ok((r, (), origin)) + } + + fn prepare( + self, + _: (), + origin: &::RuntimeOrigin, + call: &SE::Call, + info: &DispatchInfoOf, + len: usize, + _context: &Context, + ) -> Result { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + self.0.pre_dispatch(who, call, info, len) + } + + fn post_dispatch( + pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + result: &DispatchResult, + _context: &Context, + ) -> Result<(), TransactionValidityError> { + SE::post_dispatch(Some(pre), info, post_info, len, result) + } + + fn validate_bare_compat( + call: &SE::Call, + info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + SE::validate_unsigned(call, info, len) + } + + fn pre_dispatch_bare_compat( + call: &SE::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(), TransactionValidityError> { + SE::pre_dispatch_unsigned(call, info, len) + } + + fn post_dispatch_bare_compat( + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + SE::post_dispatch(None, info, post_info, len, result) + } +} diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs new file mode 100644 index 00000000000..8efa586aa0e --- /dev/null +++ b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs @@ -0,0 +1,141 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! The [DispatchTransaction] trait. + +use super::*; + +/// Single-function utility trait with a blanket impl over [TransactionExtension] in order to +/// provide transaction dispatching functionality. We avoid implementing this directly on the trait +/// since we never want it to be overriden by the trait implementation. +pub trait DispatchTransaction { + /// The origin type of the transaction. + type Origin; + /// The info type. + type Info; + /// The resultant type. + type Result; + /// The `Val` of the extension. + type Val; + /// The `Pre` of the extension. + type Pre; + /// Just validate a transaction. + /// + /// The is basically the same as [validate](TransactionExtension::validate), except that there + /// is no need to supply the bond data. + fn validate_only( + &self, + origin: Self::Origin, + call: &Call, + info: &Self::Info, + len: usize, + ) -> Result<(ValidTransaction, Self::Val, Self::Origin), TransactionValidityError>; + /// Prepare and validate a transaction, ready for dispatch. + fn validate_and_prepare( + self, + origin: Self::Origin, + call: &Call, + info: &Self::Info, + len: usize, + ) -> Result<(Self::Pre, Self::Origin), TransactionValidityError>; + /// Dispatch a transaction with the given base origin and call. + fn dispatch_transaction( + self, + origin: Self::Origin, + call: Call, + info: &Self::Info, + len: usize, + ) -> Self::Result; + /// Do everything which would be done in a [dispatch_transaction](Self::dispatch_transaction), + /// but instead of executing the call, execute `substitute` instead. Since this doesn't actually + /// dispatch the call, it doesn't need to consume it and so `call` can be passed as a reference. + fn test_run( + self, + origin: Self::Origin, + call: &Call, + info: &Self::Info, + len: usize, + substitute: impl FnOnce( + Self::Origin, + ) -> crate::DispatchResultWithInfo<::PostInfo>, + ) -> Self::Result; +} + +impl, Call: Dispatchable + Encode> DispatchTransaction + for T +{ + type Origin = ::RuntimeOrigin; + type Info = DispatchInfoOf; + type Result = crate::ApplyExtrinsicResultWithInfo>; + type Val = T::Val; + type Pre = T::Pre; + + fn validate_only( + &self, + origin: Self::Origin, + call: &Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(ValidTransaction, T::Val, Self::Origin), TransactionValidityError> { + self.validate(origin, call, info, len, &mut (), self.implicit()?, call) + } + fn validate_and_prepare( + self, + origin: Self::Origin, + call: &Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(T::Pre, Self::Origin), TransactionValidityError> { + let (_, val, origin) = self.validate_only(origin, call, info, len)?; + let pre = self.prepare(val, &origin, &call, info, len, &())?; + Ok((pre, origin)) + } + fn dispatch_transaction( + self, + origin: ::RuntimeOrigin, + call: Call, + info: &DispatchInfoOf, + len: usize, + ) -> Self::Result { + let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?; + let res = call.dispatch(origin); + let post_info = res.unwrap_or_else(|err| err.post_info); + let pd_res = res.map(|_| ()).map_err(|e| e.error); + T::post_dispatch(pre, info, &post_info, len, &pd_res, &())?; + Ok(res) + } + fn test_run( + self, + origin: Self::Origin, + call: &Call, + info: &Self::Info, + len: usize, + substitute: impl FnOnce( + Self::Origin, + ) -> crate::DispatchResultWithInfo<::PostInfo>, + ) -> Self::Result { + let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?; + let res = substitute(origin); + let post_info = match res { + Ok(info) => info, + Err(err) => err.post_info, + }; + let pd_res = res.map(|_| ()).map_err(|e| e.error); + T::post_dispatch(pre, info, &post_info, len, &pd_res, &())?; + Ok(res) + } +} diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs new file mode 100644 index 00000000000..69a0ba18adb --- /dev/null +++ b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs @@ -0,0 +1,526 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! The transaction extension trait. + +use crate::{ + scale_info::{MetaType, StaticTypeInfo}, + transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction}, + DispatchResult, +}; +use codec::{Codec, Decode, Encode}; +use impl_trait_for_tuples::impl_for_tuples; +#[doc(hidden)] +pub use sp_std::marker::PhantomData; +use sp_std::{self, fmt::Debug, prelude::*}; +use sp_weights::Weight; +use tuplex::{PopFront, PushBack}; + +use super::{DispatchInfoOf, Dispatchable, OriginOf, PostDispatchInfoOf}; + +mod as_transaction_extension; +mod dispatch_transaction; +#[allow(deprecated)] +pub use as_transaction_extension::AsTransactionExtension; +pub use dispatch_transaction::DispatchTransaction; + +/// Shortcut for the result value of the `validate` function. +pub type ValidateResult = + Result<(ValidTransaction, Val, OriginOf), TransactionValidityError>; + +/// Simple blanket implementation trait to denote the bounds of a type which can be contained within +/// a [`TransactionExtension`]. +pub trait TransactionExtensionInterior: + Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo +{ +} +impl + TransactionExtensionInterior for T +{ +} + +/// Base for [TransactionExtension]s; this contains the associated types and does not require any +/// generic parameterization. +pub trait TransactionExtensionBase: TransactionExtensionInterior { + /// Unique identifier of this signed extension. + /// + /// This will be exposed in the metadata to identify the signed extension used in an extrinsic. + const IDENTIFIER: &'static str; + + /// Any additional data which was known at the time of transaction construction and can be + /// useful in authenticating the transaction. This is determined dynamically in part from the + /// on-chain environment using the `implicit` function and not directly contained in the + /// transaction itself and therefore is considered "implicit". + type Implicit: Codec + StaticTypeInfo; + + /// Determine any additional data which was known at the time of transaction construction and + /// can be useful in authenticating the transaction. The expected usage of this is to include in + /// any data which is signed and verified as part of transactiob validation. Also perform any + /// pre-signature-verification checks and return an error if needed. + fn implicit(&self) -> Result { + use crate::InvalidTransaction::IndeterminateImplicit; + Ok(Self::Implicit::decode(&mut &[][..]).map_err(|_| IndeterminateImplicit)?) + } + + /// The weight consumed by executing this extension instance fully during transaction dispatch. + fn weight(&self) -> Weight { + Weight::zero() + } + + /// Returns the metadata for this extension. + /// + /// As a [`TransactionExtension`] can be a tuple of [`TransactionExtension`]s we need to return + /// a `Vec` that holds the metadata of each one. Each individual `TransactionExtension` must + /// return *exactly* one [`TransactionExtensionMetadata`]. + /// + /// This method provides a default implementation that returns a vec containing a single + /// [`TransactionExtensionMetadata`]. + fn metadata() -> Vec { + sp_std::vec![TransactionExtensionMetadata { + identifier: Self::IDENTIFIER, + ty: scale_info::meta_type::(), + // TODO: Metadata-v16: Rename to "implicit" + additional_signed: scale_info::meta_type::() + }] + } +} + +/// Means by which a transaction may be extended. This type embodies both the data and the logic +/// that should be additionally associated with the transaction. It should be plain old data. +/// +/// The simplest transaction extension would be the Unit type (and empty pipeline) `()`. This +/// executes no additional logic and implies a dispatch of the transaction's call using the +/// inherited origin (either `None` or `Signed`, depending on whether this is a signed or general +/// transaction). +/// +/// Transaction extensions are capable of altering certain associated semantics: +/// +/// - They may define the origin with which the transaction's call should be dispatched. +/// - They may define various parameters used by the transction queue to determine under what +/// conditions the transaction should be retained and introduced on-chain. +/// - They may define whether this transaction is acceptable for introduction on-chain at all. +/// +/// Each of these semantics are defined by the `validate` function. +/// +/// **NOTE: Transaction extensions cannot under any circumctances alter the call itself.** +/// +/// Transaction extensions are capable of defining logic which is executed additionally to the +/// dispatch of the call: +/// +/// - They may define logic which must be executed prior to the dispatch of the call. +/// - They may also define logic which must be executed after the dispatch of the call. +/// +/// Each of these semantics are defined by the `prepare` and `post_dispatch` functions respectively. +/// +/// Finally, transaction extensions may define additional data to help define the implications of +/// the logic they introduce. This additional data may be explicitly defined by the transaction +/// author (in which case it is included as part of the transaction body), or it may be implicitly +/// defined by the transaction extension based around the on-chain state (which the transaction +/// author is assumed to know). This data may be utilized by the above logic to alter how a node's +/// transaction queue treats this transaction. +/// +/// ## Default implementations +/// +/// Of the 5 functions in this trait, 3 of them must return a value of an associated type on +/// success, and none of these types implement [Default] or anything like it. This means that +/// default implementations cannot be provided for these functions. However, a macro is provided +/// [impl_tx_ext_default](crate::impl_tx_ext_default) which is capable of generating default +/// implementations for each of these 3 functions. If you do not wish to introduce additional logic +/// into the transaction pipeline, then it is recommended that you use this macro to implement these +/// functions. +/// +/// ## Pipelines, Inherited Implications, and Authorized Origins +/// +/// Requiring a single transaction extension to define all of the above semantics would be +/// cumbersome and would lead to a lot of boilerplate. Instead, transaction extensions are +/// aggregated into pipelines, which are tuples of transaction extensions. Each extension in the +/// pipeline is executed in order, and the output of each extension is aggregated and/or relayed as +/// the input to the next extension in the pipeline. +/// +/// This ordered composition happens with all datatypes ([Val](TransactionExtension::Val), +/// [Pre](TransactionExtension::Pre) and [Implicit](TransactionExtensionBase::Implicit)) as well as +/// all functions. There are important consequences stemming from how the composition affects the +/// meaning of the `origin` and `implication` parameters as well as the results. Whereas the +/// [prepare](TransactionExtension::prepare) and +/// [post_dispatch](TransactionExtension::post_dispatch) functions are clear in their meaning, the +/// [validate](TransactionExtension::validate) function is fairly sophisticated and warrants +/// further explanation. +/// +/// Firstly, the `origin` parameter. The `origin` passed into the first item in a pipeline is simply +/// that passed into the tuple itself. It represents an authority who has authorized the implication +/// of the transaction, as of the extension it has been passed into *and any further extensions it +/// may pass though, all the way to, and including, the transaction's dispatch call itself. Each +/// following item in the pipeline is passed the origin which the previous item returned. The origin +/// returned from the final item in the pipeline is the origin which is returned by the tuple +/// itself. +/// +/// This means that if a constituent extension returns a different origin to the one it was called +/// with, then (assuming no other extension changes it further) *this new origin will be used for +/// all extensions following it in the pipeline, and will be returned from the pipeline to be used +/// as the origin for the call's dispatch*. The call itself as well as all these extensions +/// following may each imply consequence for this origin. We call this the *inherited implication*. +/// +/// The *inherited implication* is the cumulated on-chain effects born by whatever origin is +/// returned. It is expressed to the [validate](TransactionExtension::validate) function only as the +/// `implication` argument which implements the [Encode] trait. A transaction extension may define +/// its own implications through its own fields and the +/// [implicit](TransactionExtensionBase::implicit) function. This is only utilized by extensions +/// which preceed it in a pipeline or, if the transaction is an old-school signed trasnaction, the +/// underlying transaction verification logic. +/// +/// **The inherited implication passed as the `implication` parameter to +/// [validate](TransactionExtension::validate) does not include the extension's inner data itself +/// nor does it include the result of the extension's `implicit` function.** If you both provide an +/// implication and rely on the implication, then you need to manually aggregate your extensions +/// implication with the aggregated implication passed in. +pub trait TransactionExtension: TransactionExtensionBase { + /// The type that encodes information that can be passed from validate to prepare. + type Val; + + /// The type that encodes information that can be passed from prepare to post-dispatch. + type Pre; + + /// Validate a transaction for the transaction queue. + /// + /// This function can be called frequently by the transaction queue to obtain transaction + /// validity against current state. It should perform all checks that determine a valid + /// transaction, that can pay for its execution and quickly eliminate ones that are stale or + /// incorrect. + /// + /// Parameters: + /// - `origin`: The origin of the transaction which this extension inherited; coming from an + /// "old-school" *signed transaction*, this will be a system `RawOrigin::Signed` value. If the + /// transaction is a "new-school" *General Transaction*, then this will be a system + /// `RawOrigin::None` value. If this extension is an item in a composite, then it could be + /// anything which was previously returned as an `origin` value in the result of a `validate` + /// call. + /// - `call`: The `Call` wrapped by this extension. + /// - `info`: Information concerning, and inherent to, the transaction's call. + /// - `len`: The total length of the encoded transaction. + /// - `inherited_implication`: The *implication* which this extension inherits. This is a tuple + /// of the transaction's call and some additional opaque-but-encodable data. Coming directly + /// from a transaction, the latter is [()]. However, if this extension is expressed as part of + /// a composite type, then the latter component is equal to any further implications to which + /// the returned `origin` could potentially apply. See Pipelines, Inherited Implications, and + /// Authorized Origins for more information. + /// - `context`: Some opaque mutable context, as yet unused. + /// + /// Returns a [ValidateResult], which is a [Result] whose success type is a tuple of + /// [ValidTransaction] (defining useful metadata for the transaction queue), the [Self::Val] + /// token of this transaction, which gets passed into [prepare](TransactionExtension::prepare), + /// and the origin of the transaction, which gets passed into + /// [prepare](TransactionExtension::prepare) and is ultimately used for dispatch. + fn validate( + &self, + origin: OriginOf, + call: &Call, + info: &DispatchInfoOf, + len: usize, + context: &mut Context, + self_implicit: Self::Implicit, + inherited_implication: &impl Encode, + ) -> ValidateResult; + + /// Do any pre-flight stuff for a transaction after validation. + /// + /// This is for actions which do not happen in the transaction queue but only immediately prior + /// to the point of dispatch on-chain. This should not return an error, since errors should + /// already have been identified during the [validate](TransactionExtension::validate) call. If + /// an error is returned, the transaction will be considered invalid but no state changes will + /// happen and therefore work done in [validate](TransactionExtension::validate) will not be + /// paid for. + /// + /// Unlike `validate`, this function may consume `self`. + /// + /// Parameters: + /// - `val`: `Self::Val` returned by the result of the `validate` call. + /// - `origin`: The origin returned by the result of the `validate` call. + /// - `call`: The `Call` wrapped by this extension. + /// - `info`: Information concerning, and inherent to, the transaction's call. + /// - `len`: The total length of the encoded transaction. + /// - `context`: Some opaque mutable context, as yet unused. + /// + /// Returns a [Self::Pre] value on success, which gets passed into + /// [post_dispatch](TransactionExtension::post_dispatch) and after the call is dispatched. + /// + /// IMPORTANT: **Checks made in validation need not be repeated here.** + fn prepare( + self, + val: Self::Val, + origin: &OriginOf, + call: &Call, + info: &DispatchInfoOf, + len: usize, + context: &Context, + ) -> Result; + + /// Do any post-flight stuff for an extrinsic. + /// + /// `_pre` contains the output of `prepare`. + /// + /// This gets given the `DispatchResult` `_result` from the extrinsic and can, if desired, + /// introduce a `TransactionValidityError`, causing the block to become invalid for including + /// it. + /// + /// Parameters: + /// - `pre`: `Self::Pre` returned by the result of the `prepare` call prior to dispatch. + /// - `info`: Information concerning, and inherent to, the transaction's call. + /// - `post_info`: Information concerning the dispatch of the transaction's call. + /// - `len`: The total length of the encoded transaction. + /// - `result`: The result of the dispatch. + /// - `context`: Some opaque mutable context, as yet unused. + /// + /// WARNING: It is dangerous to return an error here. To do so will fundamentally invalidate the + /// transaction and any block that it is included in, causing the block author to not be + /// compensated for their work in validating the transaction or producing the block so far. It + /// can only be used safely when you *know* that the transaction is one that would only be + /// introduced by the current block author. + fn post_dispatch( + _pre: Self::Pre, + _info: &DispatchInfoOf, + _post_info: &PostDispatchInfoOf, + _len: usize, + _result: &DispatchResult, + _context: &Context, + ) -> Result<(), TransactionValidityError> { + Ok(()) + } + + /// Compatibility function for supporting the `SignedExtension::validate_unsigned` function. + /// + /// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME! + #[deprecated = "Only for compatibility. DO NOT USE."] + fn validate_bare_compat( + _call: &Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + Ok(ValidTransaction::default()) + } + + /// Compatibility function for supporting the `SignedExtension::pre_dispatch_unsigned` function. + /// + /// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME! + #[deprecated = "Only for compatibility. DO NOT USE."] + fn pre_dispatch_bare_compat( + _call: &Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result<(), TransactionValidityError> { + Ok(()) + } + + /// Compatibility function for supporting the `SignedExtension::post_dispatch` function where + /// `pre` is `None`. + /// + /// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME! + #[deprecated = "Only for compatibility. DO NOT USE."] + fn post_dispatch_bare_compat( + _info: &DispatchInfoOf, + _post_info: &PostDispatchInfoOf, + _len: usize, + _result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + Ok(()) + } +} + +/// Implict +#[macro_export] +macro_rules! impl_tx_ext_default { + ($call:ty ; $context:ty ; , $( $rest:tt )*) => { + impl_tx_ext_default!{$call ; $context ; $( $rest )*} + }; + ($call:ty ; $context:ty ; validate $( $rest:tt )*) => { + fn validate( + &self, + origin: $crate::traits::OriginOf<$call>, + _call: &$call, + _info: &$crate::traits::DispatchInfoOf<$call>, + _len: usize, + _context: &mut $context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl $crate::codec::Encode, + ) -> $crate::traits::ValidateResult { + Ok((Default::default(), Default::default(), origin)) + } + impl_tx_ext_default!{$call ; $context ; $( $rest )*} + }; + ($call:ty ; $context:ty ; prepare $( $rest:tt )*) => { + fn prepare( + self, + _val: Self::Val, + _origin: &$crate::traits::OriginOf<$call>, + _call: &$call, + _info: &$crate::traits::DispatchInfoOf<$call>, + _len: usize, + _context: & $context, + ) -> Result { + Ok(Default::default()) + } + impl_tx_ext_default!{$call ; $context ; $( $rest )*} + }; + ($call:ty ; $context:ty ;) => {}; +} + +/// Information about a [`TransactionExtension`] for the runtime metadata. +pub struct TransactionExtensionMetadata { + /// The unique identifier of the [`TransactionExtension`]. + pub identifier: &'static str, + /// The type of the [`TransactionExtension`]. + pub ty: MetaType, + /// The type of the [`TransactionExtension`] additional signed data for the payload. + // TODO: Rename "implicit" + pub additional_signed: MetaType, +} + +#[impl_for_tuples(1, 12)] +impl TransactionExtensionBase for Tuple { + for_tuples!( where #( Tuple: TransactionExtensionBase )* ); + const IDENTIFIER: &'static str = "Use `metadata()`!"; + for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); ); + fn implicit(&self) -> Result { + Ok(for_tuples!( ( #( Tuple.implicit()? ),* ) )) + } + fn weight(&self) -> Weight { + let mut weight = Weight::zero(); + for_tuples!( #( weight += Tuple.weight(); )* ); + weight + } + fn metadata() -> Vec { + let mut ids = Vec::new(); + for_tuples!( #( ids.extend(Tuple::metadata()); )* ); + ids + } +} + +#[impl_for_tuples(1, 12)] +impl TransactionExtension for Tuple { + for_tuples!( where #( Tuple: TransactionExtension )* ); + for_tuples!( type Val = ( #( Tuple::Val ),* ); ); + for_tuples!( type Pre = ( #( Tuple::Pre ),* ); ); + + fn validate( + &self, + origin: ::RuntimeOrigin, + call: &Call, + info: &DispatchInfoOf, + len: usize, + context: &mut Context, + self_implicit: Self::Implicit, + inherited_implication: &impl Encode, + ) -> Result< + (ValidTransaction, Self::Val, ::RuntimeOrigin), + TransactionValidityError, + > { + let valid = ValidTransaction::default(); + let val = (); + let following_explicit_implications = for_tuples!( ( #( &self.Tuple ),* ) ); + let following_implicit_implications = self_implicit; + + for_tuples!(#( + // Implication of this pipeline element not relevant for later items, so we pop it. + let (_item, following_explicit_implications) = following_explicit_implications.pop_front(); + let (item_implicit, following_implicit_implications) = following_implicit_implications.pop_front(); + let (item_valid, item_val, origin) = { + let implications = ( + // The first is the implications born of the fact we return the mutated + // origin. + inherited_implication, + // This is the explicitly made implication born of the fact the new origin is + // passed into the next items in this pipeline-tuple. + &following_explicit_implications, + // This is the implicitly made implication born of the fact the new origin is + // passed into the next items in this pipeline-tuple. + &following_implicit_implications, + ); + Tuple.validate(origin, call, info, len, context, item_implicit, &implications)? + }; + let valid = valid.combine_with(item_valid); + let val = val.push_back(item_val); + )* ); + Ok((valid, val, origin)) + } + + fn prepare( + self, + val: Self::Val, + origin: &::RuntimeOrigin, + call: &Call, + info: &DispatchInfoOf, + len: usize, + context: &Context, + ) -> Result { + Ok(for_tuples!( ( #( + Tuple::prepare(self.Tuple, val.Tuple, origin, call, info, len, context)? + ),* ) )) + } + + fn post_dispatch( + pre: Self::Pre, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + result: &DispatchResult, + context: &Context, + ) -> Result<(), TransactionValidityError> { + for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info, post_info, len, result, context)?; )* ); + Ok(()) + } +} + +impl TransactionExtensionBase for () { + const IDENTIFIER: &'static str = "UnitTransactionExtension"; + type Implicit = (); + fn implicit(&self) -> sp_std::result::Result { + Ok(()) + } + fn weight(&self) -> Weight { + Weight::zero() + } +} + +impl TransactionExtension for () { + type Val = (); + type Pre = (); + fn validate( + &self, + origin: ::RuntimeOrigin, + _call: &Call, + _info: &DispatchInfoOf, + _len: usize, + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> Result< + (ValidTransaction, (), ::RuntimeOrigin), + TransactionValidityError, + > { + Ok((ValidTransaction::default(), (), origin)) + } + fn prepare( + self, + _val: (), + _origin: &::RuntimeOrigin, + _call: &Call, + _info: &DispatchInfoOf, + _len: usize, + _context: &Context, + ) -> Result<(), TransactionValidityError> { + Ok(()) + } +} diff --git a/substrate/primitives/runtime/src/transaction_validity.rs b/substrate/primitives/runtime/src/transaction_validity.rs index 83694849382..24124128083 100644 --- a/substrate/primitives/runtime/src/transaction_validity.rs +++ b/substrate/primitives/runtime/src/transaction_validity.rs @@ -82,6 +82,8 @@ pub enum InvalidTransaction { MandatoryValidation, /// The sending address is disabled or known to be invalid. BadSigner, + /// The implicit data was unable to be calculated. + IndeterminateImplicit, } impl InvalidTransaction { @@ -113,6 +115,8 @@ impl From for &'static str { "Transaction dispatch is mandatory; transactions must not be validated.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", InvalidTransaction::BadSigner => "Invalid signing address", + InvalidTransaction::IndeterminateImplicit => + "The implicit data was unable to be calculated", } } } @@ -338,7 +342,7 @@ pub struct ValidTransactionBuilder { impl ValidTransactionBuilder { /// Set the priority of a transaction. /// - /// Note that the final priority for `FRAME` is combined from all `SignedExtension`s. + /// Note that the final priority for `FRAME` is combined from all `TransactionExtension`s. /// Most likely for unsigned transactions you want the priority to be higher /// than for regular transactions. We recommend exposing a base priority for unsigned /// transactions as a runtime module parameter, so that the runtime can tune inter-module diff --git a/substrate/scripts/run_all_benchmarks.sh b/substrate/scripts/run_all_benchmarks.sh index 6dd7cede319..fe5f89a5b56 100755 --- a/substrate/scripts/run_all_benchmarks.sh +++ b/substrate/scripts/run_all_benchmarks.sh @@ -107,6 +107,19 @@ for PALLET in "${PALLETS[@]}"; do FOLDER="$(echo "${PALLET#*_}" | tr '_' '-')"; WEIGHT_FILE="./frame/${FOLDER}/src/weights.rs" + + # Special handling of custom weight paths. + if [ "$PALLET" == "frame_system_extensions" ] || [ "$PALLET" == "frame-system-extensions" ] + then + WEIGHT_FILE="./frame/system/src/extensions/weights.rs" + elif [ "$PALLET" == "pallet_asset_conversion_tx_payment" ] || [ "$PALLET" == "pallet-asset-conversion-tx-payment" ] + then + WEIGHT_FILE="./frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs" + elif [ "$PALLET" == "pallet_asset_tx_payment" ] || [ "$PALLET" == "pallet-asset-tx-payment" ] + then + WEIGHT_FILE="./frame/transaction-payment/asset-tx-payment/src/weights.rs" + fi + echo "[+] Benchmarking $PALLET with weight file $WEIGHT_FILE"; OUTPUT=$( diff --git a/substrate/test-utils/runtime/src/extrinsic.rs b/substrate/test-utils/runtime/src/extrinsic.rs index 05ffb7db5d5..7eb1839e97b 100644 --- a/substrate/test-utils/runtime/src/extrinsic.rs +++ b/substrate/test-utils/runtime/src/extrinsic.rs @@ -25,7 +25,7 @@ use codec::Encode; use frame_system::{CheckNonce, CheckWeight}; use sp_core::crypto::Pair as TraitPair; use sp_keyring::AccountKeyring; -use sp_runtime::{transaction_validity::TransactionPriority, Perbill}; +use sp_runtime::{generic::Preamble, transaction_validity::TransactionPriority, Perbill}; use sp_std::prelude::*; /// Transfer used in test substrate pallet. Extrinsic is created and signed using this data. @@ -66,11 +66,11 @@ impl TryFrom<&Extrinsic> for TransferData { match uxt { Extrinsic { function: RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }), - signature: Some((from, _, (CheckNonce(nonce), ..))), + preamble: Preamble::Signed(from, _, ((CheckNonce(nonce), ..), ..)), } => Ok(TransferData { from: *from, to: *dest, amount: *value, nonce: *nonce }), Extrinsic { function: RuntimeCall::SubstrateTest(PalletCall::bench_call { transfer }), - signature: None, + preamble: Preamble::Bare, } => Ok(transfer.clone()), _ => Err(()), } @@ -190,18 +190,17 @@ impl ExtrinsicBuilder { /// Build `Extrinsic` using embedded parameters pub fn build(self) -> Extrinsic { if let Some(signer) = self.signer { - let extra = ( - CheckNonce::from(self.nonce.unwrap_or(0)), - CheckWeight::new(), + let tx_ext = ( + (CheckNonce::from(self.nonce.unwrap_or(0)), CheckWeight::new()), CheckSubstrateCall {}, ); let raw_payload = - SignedPayload::from_raw(self.function.clone(), extra.clone(), ((), (), ())); + SignedPayload::from_raw(self.function.clone(), tx_ext.clone(), (((), ()), ())); let signature = raw_payload.using_encoded(|e| signer.sign(e)); - Extrinsic::new_signed(self.function, signer.public(), signature, extra) + Extrinsic::new_signed(self.function, signer.public(), signature, tx_ext) } else { - Extrinsic::new_unsigned(self.function) + Extrinsic::new_bare(self.function) } } } diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index 63e0aa6e137..7ec5f6722c4 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -58,9 +58,11 @@ use sp_api::{decl_runtime_apis, impl_runtime_apis}; pub use sp_core::hash::H256; use sp_inherents::{CheckInherentsResult, InherentData}; use sp_runtime::{ - create_runtime_str, impl_opaque_keys, - traits::{BlakeTwo256, Block as BlockT, DispatchInfoOf, NumberFor, Verify}, - transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, + create_runtime_str, impl_opaque_keys, impl_tx_ext_default, + traits::{BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, NumberFor, Verify}, + transaction_validity::{ + TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, + }, ApplyExtrinsicResult, ExtrinsicInclusionMode, Perbill, }; #[cfg(any(feature = "std", test))] @@ -142,13 +144,14 @@ pub type Signature = sr25519::Signature; #[cfg(feature = "std")] pub type Pair = sp_core::sr25519::Pair; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = (CheckNonce, CheckWeight, CheckSubstrateCall); +// TODO: Remove after the Checks are migrated to TxExtension. +/// The extension to the basic transaction logic. +pub type TxExtension = ((CheckNonce, CheckWeight), CheckSubstrateCall); /// The payload being signed in transactions. -pub type SignedPayload = sp_runtime::generic::SignedPayload; +pub type SignedPayload = sp_runtime::generic::SignedPayload; /// Unchecked extrinsic type as expected by this runtime. pub type Extrinsic = - sp_runtime::generic::UncheckedExtrinsic; + sp_runtime::generic::UncheckedExtrinsic; /// An identifier for an account on this system. pub type AccountId = ::Signer; @@ -243,7 +246,7 @@ impl sp_runtime::traits::Printable for CheckSubstrateCall { } impl sp_runtime::traits::Dispatchable for CheckSubstrateCall { - type RuntimeOrigin = CheckSubstrateCall; + type RuntimeOrigin = RuntimeOrigin; type Config = CheckSubstrateCall; type Info = CheckSubstrateCall; type PostInfo = CheckSubstrateCall; @@ -256,42 +259,37 @@ impl sp_runtime::traits::Dispatchable for CheckSubstrateCall { } } -impl sp_runtime::traits::SignedExtension for CheckSubstrateCall { - type AccountId = AccountId; - type Call = RuntimeCall; - type AdditionalSigned = (); - type Pre = (); +impl sp_runtime::traits::TransactionExtensionBase for CheckSubstrateCall { const IDENTIFIER: &'static str = "CheckSubstrateCall"; - - fn additional_signed( - &self, - ) -> sp_std::result::Result { - Ok(()) - } + type Implicit = (); +} +impl sp_runtime::traits::TransactionExtension + for CheckSubstrateCall +{ + type Pre = (); + type Val = (); + impl_tx_ext_default!(RuntimeCall; Context; prepare); fn validate( &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, + origin: ::RuntimeOrigin, + call: &RuntimeCall, + _info: &DispatchInfoOf, _len: usize, - ) -> TransactionValidity { + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> Result< + (ValidTransaction, Self::Val, ::RuntimeOrigin), + TransactionValidityError, + > { log::trace!(target: LOG_TARGET, "validate"); - match call { + let v = match call { RuntimeCall::SubstrateTest(ref substrate_test_call) => - substrate_test_pallet::validate_runtime_call(substrate_test_call), - _ => Ok(Default::default()), - } - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &sp_runtime::traits::DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(drop) + substrate_test_pallet::validate_runtime_call(substrate_test_call)?, + _ => Default::default(), + }; + Ok((v, (), origin)) } } @@ -364,6 +362,7 @@ impl frame_system::pallet::Config for Runtime { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); + type ExtensionsWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; @@ -672,7 +671,7 @@ impl_runtime_apis! { impl sp_offchain::OffchainWorkerApi for Runtime { fn offchain_worker(header: &::Header) { - let ext = Extrinsic::new_unsigned( + let ext = Extrinsic::new_bare( substrate_test_pallet::pallet::Call::storage_change{ key:b"some_key".encode(), value:Some(header.number.encode()) @@ -1025,7 +1024,7 @@ mod tests { use sp_core::{storage::well_known_keys::HEAP_PAGES, traits::CallContext}; use sp_keyring::AccountKeyring; use sp_runtime::{ - traits::{Hash as _, SignedExtension}, + traits::{DispatchTransaction, Hash as _}, transaction_validity::{InvalidTransaction, ValidTransaction}, }; use substrate_test_runtime_client::{ @@ -1174,31 +1173,33 @@ mod tests { fn check_substrate_check_signed_extension_works() { sp_tracing::try_init_simple(); new_test_ext().execute_with(|| { - let x = sp_keyring::AccountKeyring::Alice.into(); + let x: AccountId = sp_keyring::AccountKeyring::Alice.into(); let info = DispatchInfo::default(); let len = 0_usize; assert_eq!( CheckSubstrateCall {} - .validate( - &x, + .validate_only( + Some(x).into(), &ExtrinsicBuilder::new_call_with_priority(16).build().function, &info, - len + len, ) .unwrap() + .0 .priority, 16 ); assert_eq!( CheckSubstrateCall {} - .validate( - &x, + .validate_only( + Some(x).into(), &ExtrinsicBuilder::new_call_do_not_propagate().build().function, &info, - len + len, ) .unwrap() + .0 .propagate, false ); diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/template.hbs b/substrate/utils/frame/benchmarking-cli/src/pallet/template.hbs index 1e5e294acba..a044049a0d6 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/template.hbs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/template.hbs @@ -22,7 +22,11 @@ use core::marker::PhantomData; /// Weight functions for `{{pallet}}`. pub struct WeightInfo(PhantomData); +{{#if (eq pallet "frame_system_extensions")}} +impl frame_system::ExtensionsWeightInfo for WeightInfo { +{{else}} impl {{pallet}}::WeightInfo for WeightInfo { +{{/if}} {{#each benchmarks as |benchmark|}} {{#each benchmark.comments as |comment|}} /// {{comment}} diff --git a/substrate/utils/frame/remote-externalities/src/lib.rs b/substrate/utils/frame/remote-externalities/src/lib.rs index c7399468da9..d49479d9cda 100644 --- a/substrate/utils/frame/remote-externalities/src/lib.rs +++ b/substrate/utils/frame/remote-externalities/src/lib.rs @@ -1204,8 +1204,9 @@ where #[cfg(test)] mod test_prelude { pub(crate) use super::*; - pub(crate) use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, H256 as Hash}; - pub(crate) type Block = RawBlock>; + pub(crate) use sp_runtime::testing::{Block as RawBlock, MockCallU64}; + pub(crate) type UncheckedXt = sp_runtime::generic::UncheckedExtrinsic; + pub(crate) type Block = RawBlock; pub(crate) fn init_logger() { sp_tracing::try_init_simple(); diff --git a/substrate/utils/frame/rpc/client/src/lib.rs b/substrate/utils/frame/rpc/client/src/lib.rs index 221f260b156..4f4f4bbef56 100644 --- a/substrate/utils/frame/rpc/client/src/lib.rs +++ b/substrate/utils/frame/rpc/client/src/lib.rs @@ -199,11 +199,15 @@ where #[cfg(test)] mod tests { use super::*; - use sp_runtime::testing::{Block as TBlock, ExtrinsicWrapper, Header, H256}; + use sp_runtime::{ + generic::UncheckedExtrinsic, + testing::{Block as TBlock, Header, MockCallU64, H256}, + }; use std::sync::Arc; use tokio::sync::Mutex; - type Block = TBlock>; + type UncheckedXt = UncheckedExtrinsic; + type Block = TBlock; type BlockNumber = u64; type Hash = H256; -- GitLab From 0708cf382daec9996c890ab494122196a2c23d4d Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Mon, 4 Mar 2024 21:32:03 +0100 Subject: [PATCH 063/188] Contracts: Fix typo (#3563) --- substrate/frame/contracts/uapi/src/host.rs | 2 +- substrate/frame/contracts/uapi/src/host/riscv32.rs | 2 +- substrate/frame/contracts/uapi/src/host/wasm32.rs | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/substrate/frame/contracts/uapi/src/host.rs b/substrate/frame/contracts/uapi/src/host.rs index c25be4479ce..04f58895ab4 100644 --- a/substrate/frame/contracts/uapi/src/host.rs +++ b/substrate/frame/contracts/uapi/src/host.rs @@ -180,7 +180,7 @@ pub trait HostFn { flags: CallFlags, callee: &[u8], ref_time_limit: u64, - proof_time_limit: u64, + proof_size_limit: u64, deposit: Option<&[u8]>, value: &[u8], input_data: &[u8], diff --git a/substrate/frame/contracts/uapi/src/host/riscv32.rs b/substrate/frame/contracts/uapi/src/host/riscv32.rs index dbd5abc4240..561ab28747d 100644 --- a/substrate/frame/contracts/uapi/src/host/riscv32.rs +++ b/substrate/frame/contracts/uapi/src/host/riscv32.rs @@ -130,7 +130,7 @@ impl HostFn for HostFnImpl { flags: CallFlags, callee: &[u8], ref_time_limit: u64, - proof_time_limit: u64, + proof_size_limit: u64, deposit: Option<&[u8]>, value: &[u8], input_data: &[u8], diff --git a/substrate/frame/contracts/uapi/src/host/wasm32.rs b/substrate/frame/contracts/uapi/src/host/wasm32.rs index 9651aa73d6f..17c0fd341b5 100644 --- a/substrate/frame/contracts/uapi/src/host/wasm32.rs +++ b/substrate/frame/contracts/uapi/src/host/wasm32.rs @@ -223,7 +223,7 @@ mod sys { pub fn weight_to_fee( ref_time_limit: u64, - proof_time_limit: u64, + proof_size_limit: u64, output_ptr: *mut u8, output_len_ptr: *mut u32, ); @@ -239,7 +239,7 @@ mod sys { flags: u32, callee_ptr: *const u8, ref_time_limit: u64, - proof_time_limit: u64, + proof_size_limit: u64, deposit_ptr: *const u8, transferred_value_ptr: *const u8, input_data_ptr: *const u8, @@ -251,7 +251,7 @@ mod sys { pub fn instantiate( code_hash_ptr: *const u8, ref_time_limit: u64, - proof_time_limit: u64, + proof_size_limit: u64, deposit_ptr: *const u8, value_ptr: *const u8, input_ptr: *const u8, @@ -487,7 +487,7 @@ impl HostFn for HostFnImpl { flags: CallFlags, callee: &[u8], ref_time_limit: u64, - proof_time_limit: u64, + proof_size_limit: u64, deposit: Option<&[u8]>, value: &[u8], input_data: &[u8], @@ -501,7 +501,7 @@ impl HostFn for HostFnImpl { flags.bits(), callee.as_ptr(), ref_time_limit, - proof_time_limit, + proof_size_limit, deposit_ptr, value.as_ptr(), input_data.as_ptr(), -- GitLab From ec30d2f5da839a7fb3f34778013c63e5afc9e90f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 22:41:26 +0000 Subject: [PATCH 064/188] Bump mio from 0.8.8 to 0.8.11 (#3569) Bumps [mio](https://github.com/tokio-rs/mio) from 0.8.8 to 0.8.11.
Changelog

Sourced from mio's changelog.

0.8.11

0.8.10

Added

0.8.9

Added

Fixed

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mio&package-manager=cargo&previous-version=0.8.8&new-version=0.8.11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/paritytech/polkadot-sdk/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81881984378..9ee48f33074 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8234,9 +8234,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", -- GitLab From c34ad77d0524add1ef7cec3de72df7874c67f8a9 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Tue, 5 Mar 2024 09:47:10 +0200 Subject: [PATCH 065/188] Remove useless Result import (#3534) Latest Rust nightly complains with `the item `Result` is imported redundantly` Co-authored-by: Sebastian Kunert Co-authored-by: Liam Aharon --- substrate/primitives/consensus/babe/src/inherents.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/substrate/primitives/consensus/babe/src/inherents.rs b/substrate/primitives/consensus/babe/src/inherents.rs index 909769f3031..54b7b644016 100644 --- a/substrate/primitives/consensus/babe/src/inherents.rs +++ b/substrate/primitives/consensus/babe/src/inherents.rs @@ -17,7 +17,6 @@ //! Inherents for BABE -use core::result::Result; use sp_inherents::{Error, InherentData, InherentIdentifier}; /// The BABE inherent identifier. -- GitLab From 0eda0b3f175338a22e263489320fe2280875711b Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Tue, 5 Mar 2024 10:47:42 +0100 Subject: [PATCH 066/188] Contracts call extract_from_slice in macro (#3566) --- substrate/frame/contracts/uapi/src/host/wasm32.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/frame/contracts/uapi/src/host/wasm32.rs b/substrate/frame/contracts/uapi/src/host/wasm32.rs index 17c0fd341b5..bc697238061 100644 --- a/substrate/frame/contracts/uapi/src/host/wasm32.rs +++ b/substrate/frame/contracts/uapi/src/host/wasm32.rs @@ -301,6 +301,7 @@ macro_rules! impl_wrapper_for { unsafe { $( $mod )::*::$name(output.as_mut_ptr(), &mut output_len); } + extract_from_slice(output, output_len as usize) } } }; -- GitLab From efcea0edab085f036b1e0033781f5f39a73b7904 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Tue, 5 Mar 2024 10:50:57 +0100 Subject: [PATCH 067/188] rpc server: add prometheus label `is_rate_limited` (#3504) After some discussion with @kogeler after the we added the rate-limit middleware it may slow down the rpc call timings metrics significantly because it works as follows: 1. The rate limit guard is checked when the call comes and if a slot is available -> process the call 2. If no free spot is available then the call will be sleeping `jitter_delay + min_time_rate_guard` then woken up and checked at most ten times 3. If no spot is available after 10 iterations -> the call is rejected (this may take tens of seconds) Thus, this PR adds a label "is_rate_limited" to filter those out on the metrics "substrate_rpc_calls_time" and "substrate_rpc_calls_finished". I had to merge two middleware layers Metrics and RateLimit to avoid shared state in a hacky way. --------- Co-authored-by: James Wilson --- Cargo.lock | 1 - prdoc/pr_3504.prdoc | 13 ++ substrate/client/rpc-servers/Cargo.toml | 1 - substrate/client/rpc-servers/src/lib.rs | 25 ++- .../rpc-servers/src/middleware/metrics.rs | 196 +++++++----------- .../client/rpc-servers/src/middleware/mod.rs | 129 +++++++++++- .../rpc-servers/src/middleware/rate_limit.rs | 86 ++------ 7 files changed, 239 insertions(+), 212 deletions(-) create mode 100644 prdoc/pr_3504.prdoc diff --git a/Cargo.lock b/Cargo.lock index 9ee48f33074..d262c1795a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16745,7 +16745,6 @@ dependencies = [ "hyper", "jsonrpsee", "log", - "pin-project", "serde_json", "substrate-prometheus-endpoint", "tokio", diff --git a/prdoc/pr_3504.prdoc b/prdoc/pr_3504.prdoc new file mode 100644 index 00000000000..90a8ddd38b8 --- /dev/null +++ b/prdoc/pr_3504.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: add prometheus label "is_rate_limited" to rpc calls + +doc: + - audience: Node Operator + description: | + This PR adds a label "is_rate_limited" to the prometheus metrics "substrate_rpc_calls_time" and "substrate_rpc_calls_finished" + than can be used to distinguish rate-limited RPC calls from other RPC calls. Because rate-limited RPC calls may take + tens of seconds. + +crates: [ ] diff --git a/substrate/client/rpc-servers/Cargo.toml b/substrate/client/rpc-servers/Cargo.toml index 7f7a86799e0..3adc81c57d5 100644 --- a/substrate/client/rpc-servers/Cargo.toml +++ b/substrate/client/rpc-servers/Cargo.toml @@ -26,5 +26,4 @@ tower = { version = "0.4.13", features = ["util"] } http = "0.2.8" hyper = "0.14.27" futures = "0.3.29" -pin-project = "1.1.3" governor = "0.6.0" diff --git a/substrate/client/rpc-servers/src/lib.rs b/substrate/client/rpc-servers/src/lib.rs index e65d954bed5..ad4b444c7ff 100644 --- a/substrate/client/rpc-servers/src/lib.rs +++ b/substrate/client/rpc-servers/src/lib.rs @@ -49,7 +49,7 @@ pub use jsonrpsee::{ }, server::{middleware::rpc::RpcServiceBuilder, BatchRequestConfig}, }; -pub use middleware::{MetricsLayer, RateLimitLayer, RpcMetrics}; +pub use middleware::{Metrics, MiddlewareLayer, RpcMetrics}; const MEGABYTE: u32 = 1024 * 1024; @@ -173,13 +173,22 @@ where let is_websocket = ws::is_upgrade_request(&req); let transport_label = if is_websocket { "ws" } else { "http" }; - let metrics = metrics.map(|m| MetricsLayer::new(m, transport_label)); - let rate_limit = rate_limit.map(|r| RateLimitLayer::per_minute(r)); + let middleware_layer = match (metrics, rate_limit) { + (None, None) => None, + (Some(metrics), None) => Some( + MiddlewareLayer::new().with_metrics(Metrics::new(metrics, transport_label)), + ), + (None, Some(rate_limit)) => + Some(MiddlewareLayer::new().with_rate_limit_per_minute(rate_limit)), + (Some(metrics), Some(rate_limit)) => Some( + MiddlewareLayer::new() + .with_metrics(Metrics::new(metrics, transport_label)) + .with_rate_limit_per_minute(rate_limit), + ), + }; - // NOTE: The metrics needs to run first to include rate-limited calls in the - // metrics. let rpc_middleware = - RpcServiceBuilder::new().option_layer(metrics.clone()).option_layer(rate_limit); + RpcServiceBuilder::new().option_layer(middleware_layer.clone()); let mut svc = service_builder.set_rpc_middleware(rpc_middleware).build(methods, stop_handle); @@ -191,9 +200,9 @@ where // Spawn a task to handle when the connection is closed. tokio_handle.spawn(async move { let now = std::time::Instant::now(); - metrics.as_ref().map(|m| m.ws_connect()); + middleware_layer.as_ref().map(|m| m.ws_connect()); on_disconnect.await; - metrics.as_ref().map(|m| m.ws_disconnect(now)); + middleware_layer.as_ref().map(|m| m.ws_disconnect(now)); }); } diff --git a/substrate/client/rpc-servers/src/middleware/metrics.rs b/substrate/client/rpc-servers/src/middleware/metrics.rs index c2d1956c3b3..17849dc0c44 100644 --- a/substrate/client/rpc-servers/src/middleware/metrics.rs +++ b/substrate/client/rpc-servers/src/middleware/metrics.rs @@ -18,15 +18,9 @@ //! RPC middleware to collect prometheus metrics on RPC calls. -use std::{ - future::Future, - pin::Pin, - task::{Context, Poll}, - time::Instant, -}; +use std::time::Instant; -use jsonrpsee::{server::middleware::rpc::RpcServiceT, types::Request, MethodResponse}; -use pin_project::pin_project; +use jsonrpsee::{types::Request, MethodResponse}; use prometheus_endpoint::{ register, Counter, CounterVec, HistogramOpts, HistogramVec, Opts, PrometheusError, Registry, U64, @@ -77,7 +71,7 @@ impl RpcMetrics { "Total time [μs] of processed RPC calls", ) .buckets(HISTOGRAM_BUCKETS.to_vec()), - &["protocol", "method"], + &["protocol", "method", "is_rate_limited"], )?, metrics_registry, )?, @@ -97,7 +91,7 @@ impl RpcMetrics { "substrate_rpc_calls_finished", "Number of processed RPC calls (unique un-batched requests)", ), - &["protocol", "method", "is_error"], + &["protocol", "method", "is_error", "is_rate_limited"], )?, metrics_registry, )?, @@ -144,138 +138,90 @@ impl RpcMetrics { self.ws_sessions_closed.as_ref().map(|counter| counter.inc()); self.ws_sessions_time.with_label_values(&["ws"]).observe(micros as _); } -} - -/// Metrics layer. -#[derive(Clone)] -pub struct MetricsLayer { - inner: RpcMetrics, - transport_label: &'static str, -} - -impl MetricsLayer { - /// Create a new [`MetricsLayer`]. - pub fn new(metrics: RpcMetrics, transport_label: &'static str) -> Self { - Self { inner: metrics, transport_label } - } - - pub(crate) fn ws_connect(&self) { - self.inner.ws_connect(); - } - - pub(crate) fn ws_disconnect(&self, now: Instant) { - self.inner.ws_disconnect(now) - } -} - -impl tower::Layer for MetricsLayer { - type Service = Metrics; - - fn layer(&self, inner: S) -> Self::Service { - Metrics::new(inner, self.inner.clone(), self.transport_label) - } -} - -/// Metrics middleware. -#[derive(Clone)] -pub struct Metrics { - service: S, - metrics: RpcMetrics, - transport_label: &'static str, -} - -impl Metrics { - /// Create a new metrics middleware. - pub fn new(service: S, metrics: RpcMetrics, transport_label: &'static str) -> Metrics { - Metrics { service, metrics, transport_label } - } -} - -impl<'a, S> RpcServiceT<'a> for Metrics -where - S: Send + Sync + RpcServiceT<'a>, -{ - type Future = ResponseFuture<'a, S::Future>; - - fn call(&self, req: Request<'a>) -> Self::Future { - let now = Instant::now(); + pub(crate) fn on_call(&self, req: &Request, transport_label: &'static str) { log::trace!( target: "rpc_metrics", - "[{}] on_call name={} params={:?}", - self.transport_label, + "[{transport_label}] on_call name={} params={:?}", req.method_name(), req.params(), ); - self.metrics - .calls_started - .with_label_values(&[self.transport_label, req.method_name()]) + + self.calls_started + .with_label_values(&[transport_label, req.method_name()]) .inc(); + } - ResponseFuture { - fut: self.service.call(req.clone()), - metrics: self.metrics.clone(), - req, - now, - transport_label: self.transport_label, - } + pub(crate) fn on_response( + &self, + req: &Request, + rp: &MethodResponse, + is_rate_limited: bool, + transport_label: &'static str, + now: Instant, + ) { + log::trace!(target: "rpc_metrics", "[{transport_label}] on_response started_at={:?}", now); + log::trace!(target: "rpc_metrics::extra", "[{transport_label}] result={}", rp.as_result()); + + let micros = now.elapsed().as_micros(); + log::debug!( + target: "rpc_metrics", + "[{transport_label}] {} call took {} μs", + req.method_name(), + micros, + ); + self.calls_time + .with_label_values(&[ + transport_label, + req.method_name(), + if is_rate_limited { "true" } else { "false" }, + ]) + .observe(micros as _); + self.calls_finished + .with_label_values(&[ + transport_label, + req.method_name(), + // the label "is_error", so `success` should be regarded as false + // and vice-versa to be registrered correctly. + if rp.is_success() { "false" } else { "true" }, + if is_rate_limited { "true" } else { "false" }, + ]) + .inc(); } } -/// Response future for metrics. -#[pin_project] -pub struct ResponseFuture<'a, F> { - #[pin] - fut: F, - metrics: RpcMetrics, - req: Request<'a>, - now: Instant, - transport_label: &'static str, +/// Metrics with transport label. +#[derive(Clone, Debug)] +pub struct Metrics { + pub(crate) inner: RpcMetrics, + pub(crate) transport_label: &'static str, } -impl<'a, F> std::fmt::Debug for ResponseFuture<'a, F> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("ResponseFuture") +impl Metrics { + /// Create a new [`Metrics`]. + pub fn new(metrics: RpcMetrics, transport_label: &'static str) -> Self { + Self { inner: metrics, transport_label } } -} -impl<'a, F: Future> Future for ResponseFuture<'a, F> { - type Output = F::Output; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.project(); + pub(crate) fn ws_connect(&self) { + self.inner.ws_connect(); + } - let res = this.fut.poll(cx); - if let Poll::Ready(rp) = &res { - let method_name = this.req.method_name(); - let transport_label = &this.transport_label; - let now = this.now; - let metrics = &this.metrics; + pub(crate) fn ws_disconnect(&self, now: Instant) { + self.inner.ws_disconnect(now) + } - log::trace!(target: "rpc_metrics", "[{transport_label}] on_response started_at={:?}", now); - log::trace!(target: "rpc_metrics::extra", "[{transport_label}] result={:?}", rp); + pub(crate) fn on_call(&self, req: &Request) { + self.inner.on_call(req, self.transport_label) + } - let micros = now.elapsed().as_micros(); - log::debug!( - target: "rpc_metrics", - "[{transport_label}] {method_name} call took {} μs", - micros, - ); - metrics - .calls_time - .with_label_values(&[transport_label, method_name]) - .observe(micros as _); - metrics - .calls_finished - .with_label_values(&[ - transport_label, - method_name, - // the label "is_error", so `success` should be regarded as false - // and vice-versa to be registrered correctly. - if rp.is_success() { "false" } else { "true" }, - ]) - .inc(); - } - res + pub(crate) fn on_response( + &self, + req: &Request, + rp: &MethodResponse, + is_rate_limited: bool, + now: Instant, + ) { + self.inner.on_response(req, rp, is_rate_limited, self.transport_label, now) } } diff --git a/substrate/client/rpc-servers/src/middleware/mod.rs b/substrate/client/rpc-servers/src/middleware/mod.rs index cac516913d3..88ed8b2f433 100644 --- a/substrate/client/rpc-servers/src/middleware/mod.rs +++ b/substrate/client/rpc-servers/src/middleware/mod.rs @@ -18,10 +18,131 @@ //! JSON-RPC specific middleware. -/// Grafana metrics middleware. -pub mod metrics; -/// Rate limit middleware. -pub mod rate_limit; +use std::{ + num::NonZeroU32, + time::{Duration, Instant}, +}; + +use futures::future::{BoxFuture, FutureExt}; +use governor::{clock::Clock, Jitter}; +use jsonrpsee::{ + server::middleware::rpc::RpcServiceT, + types::{ErrorObject, Id, Request}, + MethodResponse, +}; + +mod metrics; +mod rate_limit; pub use metrics::*; pub use rate_limit::*; + +const MAX_JITTER: Duration = Duration::from_millis(50); +const MAX_RETRIES: usize = 10; + +/// JSON-RPC middleware layer. +#[derive(Debug, Clone, Default)] +pub struct MiddlewareLayer { + rate_limit: Option, + metrics: Option, +} + +impl MiddlewareLayer { + /// Create an empty MiddlewareLayer. + pub fn new() -> Self { + Self::default() + } + + /// Enable new rate limit middleware enforced per minute. + pub fn with_rate_limit_per_minute(self, n: NonZeroU32) -> Self { + Self { rate_limit: Some(RateLimit::per_minute(n)), metrics: self.metrics } + } + + /// Enable metrics middleware. + pub fn with_metrics(self, metrics: Metrics) -> Self { + Self { rate_limit: self.rate_limit, metrics: Some(metrics) } + } + + /// Register a new websocket connection. + pub fn ws_connect(&self) { + self.metrics.as_ref().map(|m| m.ws_connect()); + } + + /// Register that a websocket connection was closed. + pub fn ws_disconnect(&self, now: Instant) { + self.metrics.as_ref().map(|m| m.ws_disconnect(now)); + } +} + +impl tower::Layer for MiddlewareLayer { + type Service = Middleware; + + fn layer(&self, service: S) -> Self::Service { + Middleware { service, rate_limit: self.rate_limit.clone(), metrics: self.metrics.clone() } + } +} + +/// JSON-RPC middleware that handles metrics +/// and rate-limiting. +/// +/// These are part of the same middleware +/// because the metrics needs to know whether +/// a call was rate-limited or not because +/// it will impact the roundtrip for a call. +pub struct Middleware { + service: S, + rate_limit: Option, + metrics: Option, +} + +impl<'a, S> RpcServiceT<'a> for Middleware +where + S: Send + Sync + RpcServiceT<'a> + Clone + 'static, +{ + type Future = BoxFuture<'a, MethodResponse>; + + fn call(&self, req: Request<'a>) -> Self::Future { + let now = Instant::now(); + + self.metrics.as_ref().map(|m| m.on_call(&req)); + + let service = self.service.clone(); + let rate_limit = self.rate_limit.clone(); + let metrics = self.metrics.clone(); + + async move { + let mut is_rate_limited = false; + + if let Some(limit) = rate_limit.as_ref() { + let mut attempts = 0; + let jitter = Jitter::up_to(MAX_JITTER); + + loop { + if attempts >= MAX_RETRIES { + return reject_too_many_calls(req.id); + } + + if let Err(rejected) = limit.inner.check() { + tokio::time::sleep(jitter + rejected.wait_time_from(limit.clock.now())) + .await; + } else { + break; + } + + is_rate_limited = true; + attempts += 1; + } + } + + let rp = service.call(req.clone()).await; + metrics.as_ref().map(|m| m.on_response(&req, &rp, is_rate_limited, now)); + + rp + } + .boxed() + } +} + +fn reject_too_many_calls(id: Id) -> MethodResponse { + MethodResponse::error(id, ErrorObject::owned(-32999, "RPC rate limit exceeded", None::<()>)) +} diff --git a/substrate/client/rpc-servers/src/middleware/rate_limit.rs b/substrate/client/rpc-servers/src/middleware/rate_limit.rs index cdcc3ebf66f..23335eb3768 100644 --- a/substrate/client/rpc-servers/src/middleware/rate_limit.rs +++ b/substrate/client/rpc-servers/src/middleware/rate_limit.rs @@ -16,92 +16,32 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! RPC rate limiting middleware. +//! RPC rate limit. -use std::{num::NonZeroU32, sync::Arc, time::Duration}; - -use futures::future::{BoxFuture, FutureExt}; use governor::{ - clock::{Clock, DefaultClock, QuantaClock}, + clock::{DefaultClock, QuantaClock}, middleware::NoOpMiddleware, state::{InMemoryState, NotKeyed}, - Jitter, -}; -use jsonrpsee::{ - server::middleware::rpc::RpcServiceT, - types::{ErrorObject, Id, Request}, - MethodResponse, + Quota, }; +use std::{num::NonZeroU32, sync::Arc}; type RateLimitInner = governor::RateLimiter; -const MAX_JITTER: Duration = Duration::from_millis(50); -const MAX_RETRIES: usize = 10; - -/// JSON-RPC rate limit middleware layer. +/// Rate limit. #[derive(Debug, Clone)] -pub struct RateLimitLayer(governor::Quota); - -impl RateLimitLayer { - /// Create new rate limit enforced per minute. - pub fn per_minute(n: NonZeroU32) -> Self { - Self(governor::Quota::per_minute(n)) - } +pub struct RateLimit { + pub(crate) inner: Arc, + pub(crate) clock: QuantaClock, } -/// JSON-RPC rate limit middleware -pub struct RateLimit { - service: S, - rate_limit: Arc, - clock: QuantaClock, -} - -impl tower::Layer for RateLimitLayer { - type Service = RateLimit; - - fn layer(&self, service: S) -> Self::Service { +impl RateLimit { + /// Create a new `RateLimit` per minute. + pub fn per_minute(n: NonZeroU32) -> Self { let clock = QuantaClock::default(); - RateLimit { - service, - rate_limit: Arc::new(RateLimitInner::direct_with_clock(self.0, &clock)), + Self { + inner: Arc::new(RateLimitInner::direct_with_clock(Quota::per_minute(n), &clock)), clock, } } } - -impl<'a, S> RpcServiceT<'a> for RateLimit -where - S: Send + Sync + RpcServiceT<'a> + Clone + 'static, -{ - type Future = BoxFuture<'a, MethodResponse>; - - fn call(&self, req: Request<'a>) -> Self::Future { - let service = self.service.clone(); - let rate_limit = self.rate_limit.clone(); - let clock = self.clock.clone(); - - async move { - let mut attempts = 0; - let jitter = Jitter::up_to(MAX_JITTER); - - loop { - if attempts >= MAX_RETRIES { - break reject_too_many_calls(req.id); - } - - if let Err(rejected) = rate_limit.check() { - tokio::time::sleep(jitter + rejected.wait_time_from(clock.now())).await; - } else { - break service.call(req).await; - } - - attempts += 1; - } - } - .boxed() - } -} - -fn reject_too_many_calls(id: Id) -> MethodResponse { - MethodResponse::error(id, ErrorObject::owned(-32999, "RPC rate limit exceeded", None::<()>)) -} -- GitLab From 601b77d9986d551ecfb2c09de9e75384f055cda4 Mon Sep 17 00:00:00 2001 From: philoniare Date: Tue, 5 Mar 2024 18:46:56 +0800 Subject: [PATCH 068/188] [Documentation] Delete unused outdated `polkadot/testing.md` (#3559) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description *Deletes `testing.md` file in accordance with the discussion on issue #2527.* Old references to Gurke or simnet have been removed. Fixes #2527 --------- Co-authored-by: Bastian Köcher --- polkadot/doc/testing.md | 302 ---------------------------------------- 1 file changed, 302 deletions(-) delete mode 100644 polkadot/doc/testing.md diff --git a/polkadot/doc/testing.md b/polkadot/doc/testing.md deleted file mode 100644 index 76703b1b439..00000000000 --- a/polkadot/doc/testing.md +++ /dev/null @@ -1,302 +0,0 @@ -# Testing - -Testing is an essential tool to assure correctness. This document describes how we test the Polkadot code, whether -locally, at scale, and/or automatically in CI. - -## Scopes - -The testing strategy for Polkadot is 4-fold: - -### Unit testing (1) - -Boring, small scale correctness tests of individual functions. It is usually -enough to run `cargo test` in the crate you are testing. - -For full coverage you may have to pass some additional features. For example: - -```sh -cargo test --features ci-only-tests -``` - -### Integration tests - -There are the following variants of integration tests: - -#### Subsystem tests (2) - -One particular subsystem (subsystem under test) interacts with a mocked overseer that is made to assert incoming and -outgoing messages of the subsystem under test. See e.g. the `statement-distribution` tests. - -#### Behavior tests (3) - -Launching small scale networks, with multiple adversarial nodes. This should include tests around the thresholds in -order to evaluate the error handling once certain assumed invariants fail. - -Currently, we commonly use **zombienet** to run mini test-networks, whether locally or in CI. To run on your machine: - -- First, make sure you have [zombienet][zombienet] installed. - -- Now, all the required binaries must be installed in your $PATH. You must run the following from the `polkadot/` -directory in order to test your changes. (Not `zombienet setup`, or you will get the released binaries without your -local changes!) - -```sh -cargo install --path . --locked -``` - -- You will also need to install whatever binaries are required for your specific tests. For example, to install -`undying-collator`, from `polkadot/`, run: - -```sh -cargo install --path ./parachain/test-parachains/undying/collator --locked -``` - -- Finally, run the zombienet test from the `polkadot` directory: - -```sh -RUST_LOG=parachain::pvf=trace zombienet --provider=native spawn zombienet_tests/functional/0001-parachains-pvf.toml -``` - -- You can pick a validator node like `alice` from the output and view its logs -(`tail -f `) or metrics. Make sure there is nothing funny in the logs -(try `grep WARN `). - -#### Testing at scale (4) - -Launching many nodes with configurable network speed and node features in a cluster of nodes. At this scale the -[Simnet][simnet] comes into play which launches a full cluster of nodes. The scale is handled by spawning a kubernetes -cluster and the meta description is covered by [Gurke][Gurke]. Asserts are made using Grafana rules, based on the -existing prometheus metrics. This can be extended by adding an additional service translating `jaeger` spans into -addition prometheus avoiding additional Polkadot source changes. - -_Behavior tests_ and _testing at scale_ have naturally soft boundary. The most significant difference is the presence of -a real network and the number of nodes, since a single host often not capable to run multiple nodes at once. - -## Observing Logs - -To verify expected behavior it's often useful to observe logs. To avoid too many -logs at once, you can run one test at a time: - -1. Add `sp_tracing::try_init_simple();` to the beginning of a test -2. Specify `RUST_LOG=::=trace` before the cargo command. - -For example: - -```sh -RUST_LOG=parachain::pvf=trace cargo test execute_can_run_serially -``` - -For more info on how our logs work, check [the docs][logs]. - -## Coverage - -Coverage gives a _hint_ of the actually covered source lines by tests and test applications. - -The state of the art is currently tarpaulin which unfortunately yields a lot of false negatives. Lines that -are in fact covered, marked as uncovered due to a mere linebreak in a statement can cause these artifacts. This leads to -lower coverage percentages than there actually is. - -Since late 2020 rust has gained [MIR based coverage tooling]( -https://blog.rust-lang.org/inside-rust/2020/11/12/source-based-code-coverage.html). - -```sh -# setup -rustup component add llvm-tools-preview -cargo install grcov miniserve - -export CARGO_INCREMENTAL=0 -# wasm is not happy with the instrumentation -export SKIP_BUILD_WASM=true -export BUILD_DUMMY_WASM_BINARY=true -# the actully collected coverage data -export LLVM_PROFILE_FILE="llvmcoveragedata-%p-%m.profraw" -# build wasm without instrumentation -export WASM_TARGET_DIRECTORY=/tmp/wasm -cargo +nightly build -# required rust flags -export RUSTFLAGS="-Zinstrument-coverage" -# assure target dir is clean -rm -r target/{debug,tests} -# run tests to get coverage data -cargo +nightly test --all - -# create the *html* report out of all the test binaries -# mostly useful for local inspection -grcov . --binary-path ./target/debug -s . -t html --branch --ignore-not-existing -o ./coverage/ -miniserve -r ./coverage - -# create a *codecov* compatible report -grcov . --binary-path ./target/debug/ -s . -t lcov --branch --ignore-not-existing --ignore "/*" -o lcov.info -``` - -The test coverage in `lcov` can the be published to . - -```sh -bash <(curl -s https://codecov.io/bash) -f lcov.info -``` - -or just printed as part of the PR using a github action i.e. -[`jest-lcov-reporter`](https://github.com/marketplace/actions/jest-lcov-reporter). - -For full examples on how to use [`grcov` /w Polkadot specifics see the github -repo](https://github.com/mozilla/grcov#coverallscodecov-output). - -## Fuzzing - -Fuzzing is an approach to verify correctness against arbitrary or partially structured inputs. - -Currently implemented fuzzing targets: - -- `erasure-coding` - -The tooling of choice here is `honggfuzz-rs` as it allows _fastest_ coverage according to "some paper" which is a -positive feature when run as part of PRs. - -Fuzzing is generally not applicable for data secured by cryptographic hashes or signatures. Either the input has to be -specifically crafted, such that the discarded input percentage stays in an acceptable range. System level fuzzing is -hence simply not feasible due to the amount of state that is required. - -Other candidates to implement fuzzing are: - -- `rpc` -- ... - -## Performance metrics - -There are various ways of performance metrics. - -- timing with `criterion` -- cache hits/misses w/ `iai` harness or `criterion-perf` -- `coz` a performance based compiler - -Most of them are standard tools to aid in the creation of statistical tests regarding change in time of certain unit -tests. - -`coz` is meant for runtime. In our case, the system is far too large to yield a sufficient number of measurements in -finite time. An alternative approach could be to record incoming package streams per subsystem and store dumps of them, -which in return could be replayed repeatedly at an accelerated speed, with which enough metrics could be obtained to -yield information on which areas would improve the metrics. This unfortunately will not yield much information, since -most if not all of the subsystem code is linear based on the input to generate one or multiple output messages, it is -unlikely to get any useful metrics without mocking a sufficiently large part of the other subsystem which overlaps with -[#Integration tests] which is unfortunately not repeatable as of now. As such the effort gain seems low and this is not -pursued at the current time. - -## Writing small scope integration tests with preconfigured workers - -Requirements: - -- spawn nodes with preconfigured behaviors -- allow multiple types of configuration to be specified -- allow extendability via external crates -- ... - ---- - -## Implementation of different behavior strain nodes - -### Goals - -The main goals are is to allow creating a test node which exhibits a certain behavior by utilizing a subset of _wrapped_ -or _replaced_ subsystems easily. The runtime must not matter at all for these tests and should be simplistic. The -execution must be fast, this mostly means to assure a close to zero network latency as well as shorting the block time -and epoch times down to a few `100ms` and a few dozend blocks per epoch. - -### Approach - -#### MVP - -A simple small scale builder pattern would suffice for stage one implementation of allowing to replace individual -subsystems. An alternative would be to harness the existing `AllSubsystems` type and replace the subsystems as needed. - -#### Full `proc-macro` implementation - -`Overseer` is a common pattern. It could be extracted as `proc` macro and generative `proc-macro`. This would replace -the `AllSubsystems` type as well as implicitly create the `AllMessages` enum as `AllSubsystemsGen` does today. - -The implementation is yet to be completed, see the [implementation PR](https://github.com/paritytech/polkadot/pull/2962) -for details. - -##### Declare an overseer implementation - -```rust -struct BehaveMaleficient; - -impl OverseerGen for BehaveMaleficient { - fn generate<'a, Spawner, RuntimeClient>( - &self, - args: OverseerGenArgs<'a, Spawner, RuntimeClient>, - ) -> Result<(Overseer>, OverseerHandler), Error> - where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + overseer::gen::Spawner + Clone + Unpin, - { - let spawner = args.spawner.clone(); - let leaves = args.leaves.clone(); - let runtime_client = args.runtime_client.clone(); - let registry = args.registry.clone(); - let candidate_validation_config = args.candidate_validation_config.clone(); - // modify the subsystem(s) as needed: - let all_subsystems = create_default_subsystems(args)?. - // or spawn an entirely new set - - replace_candidate_validation( - // create the filtered subsystem - FilteredSubsystem::new( - CandidateValidationSubsystem::with_config( - candidate_validation_config, - Metrics::register(registry)?, - ), - // an implementation of - Skippy::default(), - ), - ); - - Overseer::new(leaves, all_subsystems, registry, runtime_client, spawner) - .map_err(|e| e.into()) - - // A builder pattern will simplify this further - // WIP https://github.com/paritytech/polkadot/pull/2962 - } -} - -fn main() -> eyre::Result<()> { - color_eyre::install()?; - let cli = Cli::from_args(); - assert_matches::assert_matches!(cli.subcommand, None); - polkadot_cli::run_node(cli, BehaveMaleficient)?; - Ok(()) -} -``` - -[`variant-a`](../node/malus/src/variant-a.rs) is a fully working example. - -#### Simnet - -Spawn a kubernetes cluster based on a meta description using [Gurke] with the [Simnet] scripts. - -Coordinated attacks of multiple nodes or subsystems must be made possible via a side-channel, that is out of scope for -this document. - -The individual node configurations are done as targets with a particular builder configuration. - -#### Behavior tests w/o Simnet - -Commonly this will require multiple nodes, and most machines are limited to running two or three nodes concurrently. -Hence, this is not the common case and is just an implementation _idea_. - -```rust -behavior_testcase!{ -"TestRuntime" => -"Alice": , -"Bob": , -"Charles": Default, -"David": "Charles", -"Eve": "Bob", -} -``` - -[zombienet]: https://github.com/paritytech/zombienet -[Gurke]: https://github.com/paritytech/gurke -[simnet]: https://github.com/paritytech/simnet_scripts -[logs]: https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/node/gum/src/lib.rs -- GitLab From 3ff78a7888b859af7b4c5ea7247b3ddd0895728d Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 5 Mar 2024 12:04:05 +0100 Subject: [PATCH 069/188] Increase 0002-validators-warp-sync timeout (#3575) Fixes failures like: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5436619#L3319 --- .../0002-validators-warp-sync/test-validators-warp-sync.zndsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/zombienet/0002-validators-warp-sync/test-validators-warp-sync.zndsl b/substrate/zombienet/0002-validators-warp-sync/test-validators-warp-sync.zndsl index ea0f15e5d8a..b68bce508c0 100644 --- a/substrate/zombienet/0002-validators-warp-sync/test-validators-warp-sync.zndsl +++ b/substrate/zombienet/0002-validators-warp-sync/test-validators-warp-sync.zndsl @@ -34,8 +34,8 @@ bob: reports block height is at least {{DB_BLOCK_HEIGHT}} within 10 seconds alice: reports substrate_beefy_best_block is at least {{DB_BLOCK_HEIGHT}} within 180 seconds bob: reports substrate_beefy_best_block is at least {{DB_BLOCK_HEIGHT}} within 180 seconds -alice: reports substrate_beefy_best_block is greater than {{DB_BLOCK_HEIGHT}} within 60 seconds -bob: reports substrate_beefy_best_block is greater than {{DB_BLOCK_HEIGHT}} within 60 seconds +alice: reports substrate_beefy_best_block is greater than {{DB_BLOCK_HEIGHT}} within 180 seconds +bob: reports substrate_beefy_best_block is greater than {{DB_BLOCK_HEIGHT}} within 180 seconds alice: count of log lines containing "error" is 0 within 10 seconds bob: count of log lines containing "verification failed" is 0 within 10 seconds -- GitLab From a71f018c7a6a7374d929e54b3466f1bd9bdd9de8 Mon Sep 17 00:00:00 2001 From: Matteo Muraca <56828990+muraca@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:04:11 +0100 Subject: [PATCH 070/188] Removed `pallet::getter` usage from `pallet-collective` (#3456) Part of #3326 This one is easier as all the storage items are public. @ggwpez @kianenigma @shawntabrizi --------- Signed-off-by: Matteo Muraca Co-authored-by: Liam Aharon Co-authored-by: command-bot <> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- .../collectives-westend/src/impls.rs | 2 +- prdoc/pr_3456.prdoc | 15 ++++ substrate/bin/node/runtime/src/impls.rs | 8 +-- substrate/frame/alliance/src/mock.rs | 2 +- substrate/frame/alliance/src/tests.rs | 4 +- .../frame/collective/src/benchmarking.rs | 32 ++++----- substrate/frame/collective/src/lib.rs | 72 +++++++++---------- substrate/frame/collective/src/tests.rs | 44 ++++++------ 8 files changed, 94 insertions(+), 85 deletions(-) create mode 100644 prdoc/pr_3456.prdoc diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/impls.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/impls.rs index caf0cddec66..e5b176fc778 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/impls.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/impls.rs @@ -81,7 +81,7 @@ where } fn proposal_of(proposal_hash: HashOf) -> Option> { - pallet_collective::Pallet::::proposal_of(proposal_hash) + pallet_collective::ProposalOf::::get(proposal_hash) } } diff --git a/prdoc/pr_3456.prdoc b/prdoc/pr_3456.prdoc new file mode 100644 index 00000000000..c7327e17e57 --- /dev/null +++ b/prdoc/pr_3456.prdoc @@ -0,0 +1,15 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Removed `pallet::getter` usage from `pallet-collective` + +doc: + - audience: Runtime Dev + description: | + This PR removes `pallet::getter` usage from `pallet-collective`, and updates dependant code accordingly. + The syntax `StorageItem::::get()` should be used instead. + +crates: + - name: pallet-collective + - name: kitchensink-runtime + - name: collectives-westend-runtime diff --git a/substrate/bin/node/runtime/src/impls.rs b/substrate/bin/node/runtime/src/impls.rs index 7ff52a758b3..34f043b33a4 100644 --- a/substrate/bin/node/runtime/src/impls.rs +++ b/substrate/bin/node/runtime/src/impls.rs @@ -30,8 +30,8 @@ use pallet_identity::legacy::IdentityField; use sp_std::prelude::*; use crate::{ - AccountId, AllianceMotion, Assets, Authorship, Balances, Hash, NegativeImbalance, Runtime, - RuntimeCall, + AccountId, AllianceCollective, AllianceMotion, Assets, Authorship, Balances, Hash, + NegativeImbalance, Runtime, RuntimeCall, }; pub struct Author; @@ -107,7 +107,7 @@ impl ProposalProvider for AllianceProposalProvider } fn proposal_of(proposal_hash: Hash) -> Option { - AllianceMotion::proposal_of(proposal_hash) + pallet_collective::ProposalOf::::get(proposal_hash) } } @@ -276,7 +276,7 @@ mod multiplier_tests { let next = runtime_multiplier_update(fm); fm = next; if fm == min_multiplier() { - break + break; } iterations += 1; } diff --git a/substrate/frame/alliance/src/mock.rs b/substrate/frame/alliance/src/mock.rs index 4a65485ed8f..fd44d33ef93 100644 --- a/substrate/frame/alliance/src/mock.rs +++ b/substrate/frame/alliance/src/mock.rs @@ -208,7 +208,7 @@ impl ProposalProvider for AllianceProposalProvider } fn proposal_of(proposal_hash: H256) -> Option { - AllianceMotion::proposal_of(proposal_hash) + pallet_collective::ProposalOf::::get(proposal_hash) } } diff --git a/substrate/frame/alliance/src/tests.rs b/substrate/frame/alliance/src/tests.rs index 8011627b237..710de5a54bc 100644 --- a/substrate/frame/alliance/src/tests.rs +++ b/substrate/frame/alliance/src/tests.rs @@ -187,8 +187,8 @@ fn propose_works() { Box::new(proposal.clone()), proposal_len )); - assert_eq!(*AllianceMotion::proposals(), vec![hash]); - assert_eq!(AllianceMotion::proposal_of(&hash), Some(proposal)); + assert_eq!(*pallet_collective::Proposals::::get(), vec![hash]); + assert_eq!(pallet_collective::ProposalOf::::get(&hash), Some(proposal)); assert_eq!( System::events(), vec![EventRecord { diff --git a/substrate/frame/collective/src/benchmarking.rs b/substrate/frame/collective/src/benchmarking.rs index af10eae5b67..7b5df17b60a 100644 --- a/substrate/frame/collective/src/benchmarking.rs +++ b/substrate/frame/collective/src/benchmarking.rs @@ -105,7 +105,7 @@ benchmarks_instance_pallet! { }: _(SystemOrigin::Root, new_members.clone(), new_members.last().cloned(), T::MaxMembers::get()) verify { new_members.sort(); - assert_eq!(Collective::::members(), new_members); + assert_eq!(Members::::get(), new_members); } execute { @@ -199,14 +199,14 @@ benchmarks_instance_pallet! { )?; } - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_eq!(Proposals::::get().len(), (p - 1) as usize); let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(p, b as usize) }.into(); }: propose(SystemOrigin::Signed(caller.clone()), threshold, Box::new(proposal.clone()), bytes_in_storage) verify { // New proposal is recorded - assert_eq!(Collective::::proposals().len(), p as usize); + assert_eq!(Proposals::::get().len(), p as usize); let proposal_hash = T::Hashing::hash_of(&proposal); assert_last_event::(Event::Proposed { account: caller, proposal_index: p - 1, proposal_hash, threshold }.into()); } @@ -269,7 +269,7 @@ benchmarks_instance_pallet! { approve, )?; - assert_eq!(Collective::::proposals().len(), p as usize); + assert_eq!(Proposals::::get().len(), p as usize); // Voter switches vote to nay, but does not kill the vote, just updates + inserts let approve = false; @@ -280,8 +280,8 @@ benchmarks_instance_pallet! { }: _(SystemOrigin::Signed(voter), last_hash, index, approve) verify { // All proposals exist and the last proposal has just been updated. - assert_eq!(Collective::::proposals().len(), p as usize); - let voting = Collective::::voting(&last_hash).ok_or("Proposal Missing")?; + assert_eq!(Proposals::::get().len(), p as usize); + let voting = Voting::::get(&last_hash).ok_or("Proposal Missing")?; assert_eq!(voting.ayes.len(), (m - 3) as usize); assert_eq!(voting.nays.len(), 1); } @@ -344,7 +344,7 @@ benchmarks_instance_pallet! { approve, )?; - assert_eq!(Collective::::proposals().len(), p as usize); + assert_eq!(Proposals::::get().len(), p as usize); // Voter switches vote to nay, which kills the vote let approve = false; @@ -361,7 +361,7 @@ benchmarks_instance_pallet! { }: close(SystemOrigin::Signed(voter), last_hash, index, Weight::MAX, bytes_in_storage) verify { // The last proposal is removed. - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_eq!(Proposals::::get().len(), (p - 1) as usize); assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); } @@ -428,7 +428,7 @@ benchmarks_instance_pallet! { true, )?; - assert_eq!(Collective::::proposals().len(), p as usize); + assert_eq!(Proposals::::get().len(), p as usize); // Caller switches vote to aye, which passes the vote let index = p - 1; @@ -442,7 +442,7 @@ benchmarks_instance_pallet! { }: close(SystemOrigin::Signed(caller), last_hash, index, Weight::MAX, bytes_in_storage) verify { // The last proposal is removed. - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_eq!(Proposals::::get().len(), (p - 1) as usize); assert_last_event::(Event::Executed { proposal_hash: last_hash, result: Ok(()) }.into()); } @@ -519,12 +519,12 @@ benchmarks_instance_pallet! { )?; System::::set_block_number(BlockNumberFor::::max_value()); - assert_eq!(Collective::::proposals().len(), p as usize); + assert_eq!(Proposals::::get().len(), p as usize); // Prime nay will close it as disapproved }: close(SystemOrigin::Signed(caller), last_hash, index, Weight::MAX, bytes_in_storage) verify { - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_eq!(Proposals::::get().len(), (p - 1) as usize); assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); } @@ -591,12 +591,12 @@ benchmarks_instance_pallet! { // caller is prime, prime already votes aye by creating the proposal System::::set_block_number(BlockNumberFor::::max_value()); - assert_eq!(Collective::::proposals().len(), p as usize); + assert_eq!(Proposals::::get().len(), p as usize); // Prime aye will close it as approved }: close(SystemOrigin::Signed(caller), last_hash, p - 1, Weight::MAX, bytes_in_storage) verify { - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_eq!(Proposals::::get().len(), (p - 1) as usize); assert_last_event::(Event::Executed { proposal_hash: last_hash, result: Ok(()) }.into()); } @@ -640,11 +640,11 @@ benchmarks_instance_pallet! { } System::::set_block_number(BlockNumberFor::::max_value()); - assert_eq!(Collective::::proposals().len(), p as usize); + assert_eq!(Proposals::::get().len(), p as usize); }: _(SystemOrigin::Root, last_hash) verify { - assert_eq!(Collective::::proposals().len(), (p - 1) as usize); + assert_eq!(Proposals::::get().len(), (p - 1) as usize); assert_last_event::(Event::Disapproved { proposal_hash: last_hash }.into()); } diff --git a/substrate/frame/collective/src/lib.rs b/substrate/frame/collective/src/lib.rs index dd481b53681..882e99a6d00 100644 --- a/substrate/frame/collective/src/lib.rs +++ b/substrate/frame/collective/src/lib.rs @@ -261,36 +261,30 @@ pub mod pallet { /// The hashes of the active proposals. #[pallet::storage] - #[pallet::getter(fn proposals)] pub type Proposals, I: 'static = ()> = StorageValue<_, BoundedVec, ValueQuery>; /// Actual proposal for a given hash, if it's current. #[pallet::storage] - #[pallet::getter(fn proposal_of)] pub type ProposalOf, I: 'static = ()> = StorageMap<_, Identity, T::Hash, >::Proposal, OptionQuery>; /// Votes on a given proposal, if it is ongoing. #[pallet::storage] - #[pallet::getter(fn voting)] pub type Voting, I: 'static = ()> = StorageMap<_, Identity, T::Hash, Votes>, OptionQuery>; /// Proposals so far. #[pallet::storage] - #[pallet::getter(fn proposal_count)] pub type ProposalCount, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; /// The current members of the collective. This is stored sorted (just by value). #[pallet::storage] - #[pallet::getter(fn members)] pub type Members, I: 'static = ()> = StorageValue<_, Vec, ValueQuery>; /// The prime member that helps determine the default vote behavior in case of absentations. #[pallet::storage] - #[pallet::getter(fn prime)] pub type Prime, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; #[pallet::event] @@ -459,7 +453,7 @@ pub mod pallet { #[pallet::compact] length_bound: u32, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - let members = Self::members(); + let members = Members::::get(); ensure!(members.contains(&who), Error::::NotMember); let proposal_len = proposal.encoded_size(); ensure!(proposal_len <= length_bound as usize, Error::::WrongProposalLength); @@ -519,7 +513,7 @@ pub mod pallet { #[pallet::compact] length_bound: u32, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - let members = Self::members(); + let members = Members::::get(); ensure!(members.contains(&who), Error::::NotMember); if threshold < 2 { @@ -565,7 +559,7 @@ pub mod pallet { approve: bool, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - let members = Self::members(); + let members = Members::::get(); ensure!(members.contains(&who), Error::::NotMember); // Detects first vote of the member in the motion @@ -669,7 +663,7 @@ impl, I: 'static> Pallet { pub fn is_member(who: &T::AccountId) -> bool { // Note: The dispatchables *do not* use this to check membership so make sure // to update those if this is changed. - Self::members().contains(who) + Members::::get().contains(who) } /// Execute immediately when adding a new proposal. @@ -688,7 +682,7 @@ impl, I: 'static> Pallet { let proposal_hash = T::Hashing::hash_of(&proposal); ensure!(!>::contains_key(proposal_hash), Error::::DuplicateProposal); - let seats = Self::members().len() as MemberCount; + let seats = Members::::get().len() as MemberCount; let result = proposal.dispatch(RawOrigin::Members(1, seats).into()); Self::deposit_event(Event::Executed { proposal_hash, @@ -721,7 +715,7 @@ impl, I: 'static> Pallet { Ok(proposals.len()) })?; - let index = Self::proposal_count(); + let index = ProposalCount::::get(); >::mutate(|i| *i += 1); >::insert(proposal_hash, proposal); let votes = { @@ -747,7 +741,7 @@ impl, I: 'static> Pallet { index: ProposalIndex, approve: bool, ) -> Result { - let mut voting = Self::voting(&proposal).ok_or(Error::::ProposalMissing)?; + let mut voting = Voting::::get(&proposal).ok_or(Error::::ProposalMissing)?; ensure!(voting.index == index, Error::::WrongIndex); let position_yes = voting.ayes.iter().position(|a| a == &who); @@ -798,12 +792,12 @@ impl, I: 'static> Pallet { proposal_weight_bound: Weight, length_bound: u32, ) -> DispatchResultWithPostInfo { - let voting = Self::voting(&proposal_hash).ok_or(Error::::ProposalMissing)?; + let voting = Voting::::get(&proposal_hash).ok_or(Error::::ProposalMissing)?; ensure!(voting.index == index, Error::::WrongIndex); let mut no_votes = voting.nays.len() as MemberCount; let mut yes_votes = voting.ayes.len() as MemberCount; - let seats = Self::members().len() as MemberCount; + let seats = Members::::get().len() as MemberCount; let approved = yes_votes >= voting.threshold; let disapproved = seats.saturating_sub(no_votes) < voting.threshold; // Allow (dis-)approving the proposal as soon as there are enough votes. @@ -837,7 +831,7 @@ impl, I: 'static> Pallet { // Only allow actual closing of the proposal after the voting period has ended. ensure!(frame_system::Pallet::::block_number() >= voting.end, Error::::TooEarly); - let prime_vote = Self::prime().map(|who| voting.ayes.iter().any(|a| a == &who)); + let prime_vote = Prime::::get().map(|who| voting.ayes.iter().any(|a| a == &who)); // default voting strategy. let default = T::DefaultVote::default_vote(prime_vote, yes_votes, no_votes, seats); @@ -978,29 +972,28 @@ impl, I: 'static> Pallet { /// * The prime account must be a member of the collective. #[cfg(any(feature = "try-runtime", test))] fn do_try_state() -> Result<(), TryRuntimeError> { - Self::proposals() - .into_iter() - .try_for_each(|proposal| -> Result<(), TryRuntimeError> { + Proposals::::get().into_iter().try_for_each( + |proposal| -> Result<(), TryRuntimeError> { ensure!( - Self::proposal_of(proposal).is_some(), + ProposalOf::::get(proposal).is_some(), "Proposal hash from `Proposals` is not found inside the `ProposalOf` mapping." ); Ok(()) - })?; + }, + )?; ensure!( - Self::proposals().into_iter().count() <= Self::proposal_count() as usize, + Proposals::::get().into_iter().count() <= ProposalCount::::get() as usize, "The actual number of proposals is greater than `ProposalCount`" ); ensure!( - Self::proposals().into_iter().count() == >::iter_keys().count(), + Proposals::::get().into_iter().count() == >::iter_keys().count(), "Proposal count inside `Proposals` is not equal to the proposal count in `ProposalOf`" ); - Self::proposals() - .into_iter() - .try_for_each(|proposal| -> Result<(), TryRuntimeError> { - if let Some(votes) = Self::voting(proposal) { + Proposals::::get().into_iter().try_for_each( + |proposal| -> Result<(), TryRuntimeError> { + if let Some(votes) = Voting::::get(proposal) { let ayes = votes.ayes.len(); let nays = votes.nays.len(); @@ -1010,13 +1003,13 @@ impl, I: 'static> Pallet { ); } Ok(()) - })?; + }, + )?; let mut proposal_indices = vec![]; - Self::proposals() - .into_iter() - .try_for_each(|proposal| -> Result<(), TryRuntimeError> { - if let Some(votes) = Self::voting(proposal) { + Proposals::::get().into_iter().try_for_each( + |proposal| -> Result<(), TryRuntimeError> { + if let Some(votes) = Voting::::get(proposal) { let proposal_index = votes.index; ensure!( !proposal_indices.contains(&proposal_index), @@ -1025,12 +1018,13 @@ impl, I: 'static> Pallet { proposal_indices.push(proposal_index); } Ok(()) - })?; + }, + )?; >::iter_keys().try_for_each( |proposal_hash| -> Result<(), TryRuntimeError> { ensure!( - Self::proposals().contains(&proposal_hash), + Proposals::::get().contains(&proposal_hash), "`Proposals` doesn't contain the proposal hash from the `Voting` storage map." ); Ok(()) @@ -1038,17 +1032,17 @@ impl, I: 'static> Pallet { )?; ensure!( - Self::members().len() <= T::MaxMembers::get() as usize, + Members::::get().len() <= T::MaxMembers::get() as usize, "The member count is greater than `MaxMembers`." ); ensure!( - Self::members().windows(2).all(|members| members[0] <= members[1]), + Members::::get().windows(2).all(|members| members[0] <= members[1]), "The members are not sorted by value." ); - if let Some(prime) = Self::prime() { - ensure!(Self::members().contains(&prime), "Prime account is not a member."); + if let Some(prime) = Prime::::get() { + ensure!(Members::::get().contains(&prime), "Prime account is not a member."); } Ok(()) @@ -1082,7 +1076,7 @@ impl, I: 'static> ChangeMembers for Pallet { // remove accounts from all current voting in motions. let mut outgoing = outgoing.to_vec(); outgoing.sort(); - for h in Self::proposals().into_iter() { + for h in Proposals::::get().into_iter() { >::mutate(h, |v| { if let Some(mut votes) = v.take() { votes.ayes = votes diff --git a/substrate/frame/collective/src/tests.rs b/substrate/frame/collective/src/tests.rs index ac5797c638c..92418794c5f 100644 --- a/substrate/frame/collective/src/tests.rs +++ b/substrate/frame/collective/src/tests.rs @@ -193,8 +193,8 @@ fn default_max_proposal_weight() -> Weight { #[test] fn motions_basic_environment_works() { ExtBuilder::default().build_and_execute(|| { - assert_eq!(Collective::members(), vec![1, 2, 3]); - assert_eq!(*Collective::proposals(), Vec::::new()); + assert_eq!(Members::::get(), vec![1, 2, 3]); + assert_eq!(*Proposals::::get(), Vec::::new()); }); } @@ -205,7 +205,7 @@ fn initialize_members_sorts_members() { ExtBuilder::default() .set_collective_members(unsorted_members) .build_and_execute(|| { - assert_eq!(Collective::members(), expected_members); + assert_eq!(Members::::get(), expected_members); }); } @@ -219,8 +219,8 @@ fn set_members_with_prime_works() { Some(3), MaxMembers::get() )); - assert_eq!(Collective::members(), members.clone()); - assert_eq!(Collective::prime(), Some(3)); + assert_eq!(Members::::get(), members.clone()); + assert_eq!(Prime::::get(), Some(3)); assert_noop!( Collective::set_members(RuntimeOrigin::root(), members, Some(4), MaxMembers::get()), Error::::PrimeAccountNotMember @@ -632,12 +632,12 @@ fn removal_of_old_voters_votes_works() { assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, true)); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![], end }) ); Collective::change_members_sorted(&[4], &[1], &[2, 3, 4]); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![], end }) ); @@ -653,12 +653,12 @@ fn removal_of_old_voters_votes_works() { assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 1, true)); assert_ok!(Collective::vote(RuntimeOrigin::signed(3), hash, 1, false)); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3], end }) ); Collective::change_members_sorted(&[], &[3], &[2, 4]); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![], end }) ); }); @@ -680,7 +680,7 @@ fn removal_of_old_voters_votes_works_with_set_members() { assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 0, true)); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![], end }) ); assert_ok!(Collective::set_members( @@ -690,7 +690,7 @@ fn removal_of_old_voters_votes_works_with_set_members() { MaxMembers::get() )); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![], end }) ); @@ -706,7 +706,7 @@ fn removal_of_old_voters_votes_works_with_set_members() { assert_ok!(Collective::vote(RuntimeOrigin::signed(2), hash, 1, true)); assert_ok!(Collective::vote(RuntimeOrigin::signed(3), hash, 1, false)); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3], end }) ); assert_ok!(Collective::set_members( @@ -716,7 +716,7 @@ fn removal_of_old_voters_votes_works_with_set_members() { MaxMembers::get() )); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![], end }) ); }); @@ -735,10 +735,10 @@ fn propose_works() { Box::new(proposal.clone()), proposal_len )); - assert_eq!(*Collective::proposals(), vec![hash]); - assert_eq!(Collective::proposal_of(&hash), Some(proposal)); + assert_eq!(*Proposals::::get(), vec![hash]); + assert_eq!(ProposalOf::::get(&hash), Some(proposal)); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![], nays: vec![], end }) ); @@ -898,13 +898,13 @@ fn motions_vote_after_works() { )); // Initially there a no votes when the motion is proposed. assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 2, ayes: vec![], nays: vec![], end }) ); // Cast first aye vote. assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, true)); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 2, ayes: vec![1], nays: vec![], end }) ); // Try to cast a duplicate aye vote. @@ -915,7 +915,7 @@ fn motions_vote_after_works() { // Cast a nay vote. assert_ok!(Collective::vote(RuntimeOrigin::signed(1), hash, 0, false)); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 2, ayes: vec![], nays: vec![1], end }) ); // Try to cast a duplicate nay vote. @@ -966,7 +966,7 @@ fn motions_all_first_vote_free_works() { proposal_len, )); assert_eq!( - Collective::voting(&hash), + Voting::::get(&hash), Some(Votes { index: 0, threshold: 2, ayes: vec![], nays: vec![], end }) ); @@ -1031,14 +1031,14 @@ fn motions_reproposing_disapproved_works() { proposal_weight, proposal_len )); - assert_eq!(*Collective::proposals(), vec![]); + assert_eq!(*Proposals::::get(), vec![]); assert_ok!(Collective::propose( RuntimeOrigin::signed(1), 2, Box::new(proposal.clone()), proposal_len )); - assert_eq!(*Collective::proposals(), vec![hash]); + assert_eq!(*Proposals::::get(), vec![hash]); }); } -- GitLab From 4c810609d6c72b48bd748398165da5c27a604778 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:40:37 +0000 Subject: [PATCH 071/188] Repot all templates into a single directory (#3460) The first step towards https://github.com/paritytech/polkadot-sdk/issues/3155 Brings all templates under the following structure ``` templates | parachain | | polkadot-launch | | runtime --> parachain-template-runtime | | pallets --> pallet-parachain-template | | node --> parachain-template-node | minimal | | runtime --> minimal-template-runtime | | pallets --> pallet-minimal-template | | node --> minimal-template-node | solochain | | runtime --> solochain-template-runtime | | pallets --> pallet-template (the naming is not consistent here) | | node --> solochain-template-node ``` The only note-worthy changes in this PR are: - More `Cargo.toml` fields are forwarded to use the one from the workspace. - parachain template now has weights and benchmarks - adds a shell pallet to the minimal template - remove a few unused deps A list of possible follow-ups: - [ ] Unify READMEs, create a parent README for all - [ ] remove references to `docs.substrate.io` in templates - [ ] make all templates use `#[derive_impl]` - [ ] update and unify all licenses - [ ] Remove polkadot launch, use https://github.com/paritytech/polkadot-sdk/blob/35349df993ea2e7c4769914ef5d199e787b23d4c/cumulus/zombienet/examples/small_network.toml instead. --- .github/scripts/check-workspace.py | 22 +- .github/workflows/check-licenses.yml | 1 - .gitlab/pipeline/build.yml | 2 +- Cargo.lock | 195 +++++++++--------- Cargo.toml | 21 +- .../pallets/template/README.md | 1 - .../pallets/template/src/benchmarking.rs | 20 -- prdoc/pr_3460.prdoc | 26 +++ substrate/bin/minimal/node/Cargo.toml | 60 ------ substrate/bin/minimal/runtime/Cargo.toml | 50 ----- substrate/bin/node-template/.editorconfig | 16 -- substrate/bin/node-template/env-setup/.envrc | 1 - substrate/bin/node-template/node/Cargo.toml | 93 --------- .../bin/node-template/runtime/Cargo.toml | 126 ----------- substrate/frame/Cargo.toml | 13 +- .../frame/examples/default-config/src/lib.rs | 2 +- substrate/frame/system/src/lib.rs | 2 +- templates/minimal/README.md | 0 templates/minimal/node/Cargo.toml | 62 ++++++ .../bin => templates}/minimal/node/build.rs | 0 .../minimal/node/src/chain_spec.rs | 0 .../bin => templates}/minimal/node/src/cli.rs | 0 .../minimal/node/src/command.rs | 0 .../bin => templates}/minimal/node/src/lib.rs | 2 +- .../minimal/node/src/main.rs | 0 .../bin => templates}/minimal/node/src/rpc.rs | 0 .../minimal/node/src/service.rs | 0 templates/minimal/pallets/template/Cargo.toml | 33 +++ templates/minimal/pallets/template/src/lib.rs | 19 ++ templates/minimal/runtime/Cargo.toml | 59 ++++++ .../minimal/runtime/build.rs | 0 .../minimal/runtime/src/lib.rs | 15 +- .../parachain}/LICENSE | 0 .../parachain}/README.md | 0 .../parachain}/node/Cargo.toml | 33 +-- .../parachain}/node/build.rs | 0 .../parachain}/node/src/chain_spec.rs | 13 +- .../parachain}/node/src/cli.rs | 0 .../parachain}/node/src/command.rs | 0 .../parachain}/node/src/main.rs | 0 .../parachain}/node/src/rpc.rs | 0 .../parachain}/node/src/service.rs | 0 .../parachain}/pallets/template/Cargo.toml | 30 +-- .../parachain}/pallets/template/README.md | 0 .../pallets/template/src/benchmarking.rs | 0 .../parachain}/pallets/template/src/lib.rs | 4 + .../parachain}/pallets/template/src/mock.rs | 1 + .../parachain}/pallets/template/src/tests.rs | 0 .../pallets/template/src/weights.rs | 0 .../parachain}/polkadot-launch/config.json | 0 .../parachain}/runtime/Cargo.toml | 49 +++-- .../parachain}/runtime/build.rs | 0 .../parachain}/runtime/src/lib.rs | 5 +- .../runtime/src/weights/block_weights.rs | 0 .../runtime/src/weights/extrinsic_weights.rs | 0 .../parachain}/runtime/src/weights/mod.rs | 0 .../runtime/src/weights/paritydb_weights.rs | 0 .../runtime/src/weights/rocksdb_weights.rs | 0 .../parachain}/runtime/src/xcm_config.rs | 0 .../solochain}/LICENSE | 0 .../solochain}/README.md | 0 .../solochain}/docs/rust-setup.md | 0 .../solochain}/env-setup/README.md | 0 .../solochain}/env-setup/flake.lock | 0 .../solochain}/env-setup/flake.nix | 0 .../solochain}/env-setup/rust-toolchain.toml | 0 templates/solochain/node/Cargo.toml | 92 +++++++++ .../solochain}/node/build.rs | 0 .../solochain}/node/src/benchmarking.rs | 2 +- .../solochain}/node/src/chain_spec.rs | 2 +- .../solochain}/node/src/cli.rs | 0 .../solochain}/node/src/command.rs | 2 +- .../solochain}/node/src/main.rs | 0 .../solochain}/node/src/rpc.rs | 2 +- .../solochain}/node/src/service.rs | 2 +- .../solochain}/pallets/template/Cargo.toml | 30 +-- .../solochain/pallets/template/README.md | 1 + .../pallets/template/src/benchmarking.rs | 35 ++++ .../solochain}/pallets/template/src/lib.rs | 0 .../solochain}/pallets/template/src/mock.rs | 0 .../solochain}/pallets/template/src/tests.rs | 0 .../solochain/pallets/template/src/weights.rs | 90 ++++++++ templates/solochain/runtime/Cargo.toml | 152 ++++++++++++++ .../solochain}/runtime/build.rs | 0 .../solochain}/runtime/src/lib.rs | 9 +- 85 files changed, 819 insertions(+), 576 deletions(-) delete mode 100644 cumulus/parachain-template/pallets/template/README.md delete mode 100644 cumulus/parachain-template/pallets/template/src/benchmarking.rs create mode 100644 prdoc/pr_3460.prdoc delete mode 100644 substrate/bin/minimal/node/Cargo.toml delete mode 100644 substrate/bin/minimal/runtime/Cargo.toml delete mode 100644 substrate/bin/node-template/.editorconfig delete mode 100644 substrate/bin/node-template/env-setup/.envrc delete mode 100644 substrate/bin/node-template/node/Cargo.toml delete mode 100644 substrate/bin/node-template/runtime/Cargo.toml create mode 100644 templates/minimal/README.md create mode 100644 templates/minimal/node/Cargo.toml rename {substrate/bin => templates}/minimal/node/build.rs (100%) rename {substrate/bin => templates}/minimal/node/src/chain_spec.rs (100%) rename {substrate/bin => templates}/minimal/node/src/cli.rs (100%) rename {substrate/bin => templates}/minimal/node/src/command.rs (100%) rename {substrate/bin => templates}/minimal/node/src/lib.rs (94%) rename {substrate/bin => templates}/minimal/node/src/main.rs (100%) rename {substrate/bin => templates}/minimal/node/src/rpc.rs (100%) rename {substrate/bin => templates}/minimal/node/src/service.rs (100%) create mode 100644 templates/minimal/pallets/template/Cargo.toml create mode 100644 templates/minimal/pallets/template/src/lib.rs create mode 100644 templates/minimal/runtime/Cargo.toml rename {substrate/bin => templates}/minimal/runtime/build.rs (100%) rename {substrate/bin => templates}/minimal/runtime/src/lib.rs (95%) rename {cumulus/parachain-template => templates/parachain}/LICENSE (100%) rename {cumulus/parachain-template => templates/parachain}/README.md (100%) rename {cumulus/parachain-template => templates/parachain}/node/Cargo.toml (78%) rename {cumulus/parachain-template => templates/parachain}/node/build.rs (100%) rename {cumulus/parachain-template => templates/parachain}/node/src/chain_spec.rs (93%) rename {cumulus/parachain-template => templates/parachain}/node/src/cli.rs (100%) rename {cumulus/parachain-template => templates/parachain}/node/src/command.rs (100%) rename {cumulus/parachain-template => templates/parachain}/node/src/main.rs (100%) rename {cumulus/parachain-template => templates/parachain}/node/src/rpc.rs (100%) rename {cumulus/parachain-template => templates/parachain}/node/src/service.rs (100%) rename {cumulus/parachain-template => templates/parachain}/pallets/template/Cargo.toml (68%) rename {substrate/bin/node-template => templates/parachain}/pallets/template/README.md (100%) rename {substrate/bin/node-template => templates/parachain}/pallets/template/src/benchmarking.rs (100%) rename {cumulus/parachain-template => templates/parachain}/pallets/template/src/lib.rs (96%) rename {cumulus/parachain-template => templates/parachain}/pallets/template/src/mock.rs (98%) rename {cumulus/parachain-template => templates/parachain}/pallets/template/src/tests.rs (100%) rename {substrate/bin/node-template => templates/parachain}/pallets/template/src/weights.rs (100%) rename {cumulus/parachain-template => templates/parachain}/polkadot-launch/config.json (100%) rename {cumulus/parachain-template => templates/parachain}/runtime/Cargo.toml (82%) rename {cumulus/parachain-template => templates/parachain}/runtime/build.rs (100%) rename {cumulus/parachain-template => templates/parachain}/runtime/src/lib.rs (99%) rename {cumulus/parachain-template => templates/parachain}/runtime/src/weights/block_weights.rs (100%) rename {cumulus/parachain-template => templates/parachain}/runtime/src/weights/extrinsic_weights.rs (100%) rename {cumulus/parachain-template => templates/parachain}/runtime/src/weights/mod.rs (100%) rename {cumulus/parachain-template => templates/parachain}/runtime/src/weights/paritydb_weights.rs (100%) rename {cumulus/parachain-template => templates/parachain}/runtime/src/weights/rocksdb_weights.rs (100%) rename {cumulus/parachain-template => templates/parachain}/runtime/src/xcm_config.rs (100%) rename {substrate/bin/node-template => templates/solochain}/LICENSE (100%) rename {substrate/bin/node-template => templates/solochain}/README.md (100%) rename {substrate/bin/node-template => templates/solochain}/docs/rust-setup.md (100%) rename {substrate/bin/node-template => templates/solochain}/env-setup/README.md (100%) rename {substrate/bin/node-template => templates/solochain}/env-setup/flake.lock (100%) rename {substrate/bin/node-template => templates/solochain}/env-setup/flake.nix (100%) rename {substrate/bin/node-template => templates/solochain}/env-setup/rust-toolchain.toml (100%) create mode 100644 templates/solochain/node/Cargo.toml rename {substrate/bin/node-template => templates/solochain}/node/build.rs (100%) rename {substrate/bin/node-template => templates/solochain}/node/src/benchmarking.rs (99%) rename {substrate/bin/node-template => templates/solochain}/node/src/chain_spec.rs (97%) rename {substrate/bin/node-template => templates/solochain}/node/src/cli.rs (100%) rename {substrate/bin/node-template => templates/solochain}/node/src/command.rs (98%) rename {substrate/bin/node-template => templates/solochain}/node/src/main.rs (100%) rename {substrate/bin/node-template => templates/solochain}/node/src/rpc.rs (96%) rename {substrate/bin/node-template => templates/solochain}/node/src/service.rs (99%) rename {substrate/bin/node-template => templates/solochain}/pallets/template/Cargo.toml (55%) create mode 100644 templates/solochain/pallets/template/README.md create mode 100644 templates/solochain/pallets/template/src/benchmarking.rs rename {substrate/bin/node-template => templates/solochain}/pallets/template/src/lib.rs (100%) rename {substrate/bin/node-template => templates/solochain}/pallets/template/src/mock.rs (100%) rename {substrate/bin/node-template => templates/solochain}/pallets/template/src/tests.rs (100%) create mode 100644 templates/solochain/pallets/template/src/weights.rs create mode 100644 templates/solochain/runtime/Cargo.toml rename {substrate/bin/node-template => templates/solochain}/runtime/build.rs (100%) rename {substrate/bin/node-template => templates/solochain}/runtime/src/lib.rs (98%) diff --git a/.github/scripts/check-workspace.py b/.github/scripts/check-workspace.py index d200122fee9..1f8f103e4e1 100644 --- a/.github/scripts/check-workspace.py +++ b/.github/scripts/check-workspace.py @@ -18,7 +18,7 @@ def parse_args(): parser.add_argument('workspace_dir', help='The directory to check', metavar='workspace_dir', type=str, nargs=1) parser.add_argument('--exclude', help='Exclude crate paths from the check', metavar='exclude', type=str, nargs='*', default=[]) - + args = parser.parse_args() return (args.workspace_dir[0], args.exclude) @@ -26,7 +26,7 @@ def main(root, exclude): workspace_crates = get_members(root, exclude) all_crates = get_crates(root, exclude) print(f'📦 Found {len(all_crates)} crates in total') - + check_duplicates(workspace_crates) check_missing(workspace_crates, all_crates) check_links(all_crates) @@ -48,14 +48,14 @@ def get_members(workspace_dir, exclude): if not 'members' in root_manifest['workspace']: return [] - + members = [] for member in root_manifest['workspace']['members']: if member in exclude: print(f'❌ Excluded member should not appear in the workspace {member}') sys.exit(1) members.append(member) - + return members # List all members of the workspace. @@ -74,12 +74,12 @@ def get_crates(workspace_dir, exclude_crates) -> dict: with open(path, "r") as f: content = f.read() manifest = toml.loads(content) - + if 'workspace' in manifest: if root != workspace_dir: print("⏩ Excluded recursive workspace at %s" % path) continue - + # Cut off the root path and the trailing /Cargo.toml. path = path[len(workspace_dir)+1:-11] name = manifest['package']['name'] @@ -87,7 +87,7 @@ def get_crates(workspace_dir, exclude_crates) -> dict: print("⏩ Excluded crate %s at %s" % (name, path)) continue crates[name] = (path, manifest) - + return crates # Check that there are no duplicate entries in the workspace. @@ -138,23 +138,23 @@ def check_links(all_crates): if not 'path' in deps[dep]: broken.append((name, dep_name, "crate must be linked via `path`")) return - + def check_crate(deps): to_checks = ['dependencies', 'dev-dependencies', 'build-dependencies'] for to_check in to_checks: if to_check in deps: check_deps(deps[to_check]) - + # There could possibly target dependant deps: if 'target' in manifest: # Target dependant deps can only have one level of nesting: for _, target in manifest['target'].items(): check_crate(target) - + check_crate(manifest) - + links.sort() broken.sort() diff --git a/.github/workflows/check-licenses.yml b/.github/workflows/check-licenses.yml index e1e92d288ce..c32b6fcf89e 100644 --- a/.github/workflows/check-licenses.yml +++ b/.github/workflows/check-licenses.yml @@ -42,5 +42,4 @@ jobs: shopt -s globstar npx @paritytech/license-scanner scan \ --ensure-licenses ${{ env.LICENSES }} \ - --exclude ./substrate/bin/node-template \ -- ./substrate/**/*.rs diff --git a/.gitlab/pipeline/build.yml b/.gitlab/pipeline/build.yml index 423587c1fb5..f8de6135572 100644 --- a/.gitlab/pipeline/build.yml +++ b/.gitlab/pipeline/build.yml @@ -337,7 +337,7 @@ build-runtimes-polkavm: - .common-refs - .run-immediately script: - - SUBSTRATE_RUNTIME_TARGET=riscv cargo check -p minimal-runtime + - SUBSTRATE_RUNTIME_TARGET=riscv cargo check -p minimal-template-runtime - SUBSTRATE_RUNTIME_TARGET=riscv cargo check -p westend-runtime - SUBSTRATE_RUNTIME_TARGET=riscv cargo check -p rococo-runtime - SUBSTRATE_RUNTIME_TARGET=riscv cargo check -p polkadot-test-runtime diff --git a/Cargo.lock b/Cargo.lock index d262c1795a6..26e134448ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8172,15 +8172,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] -name = "minimal-node" -version = "4.0.0-dev" +name = "minimal-template-node" +version = "0.0.0" dependencies = [ "clap 4.5.1", "frame", "futures", "futures-timer", "jsonrpsee", - "minimal-runtime", + "minimal-template-runtime", "sc-basic-authorship", "sc-cli", "sc-client-api", @@ -8207,12 +8207,12 @@ dependencies = [ ] [[package]] -name = "minimal-runtime" -version = "0.1.0" +name = "minimal-template-runtime" +version = "0.0.0" dependencies = [ "frame", - "frame-support", "pallet-balances", + "pallet-minimal-template", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", @@ -8726,50 +8726,6 @@ dependencies = [ "kitchensink-runtime", ] -[[package]] -name = "node-template" -version = "4.0.0-dev" -dependencies = [ - "clap 4.5.1", - "frame-benchmarking", - "frame-benchmarking-cli", - "frame-system", - "futures", - "jsonrpsee", - "node-template-runtime", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc", - "sc-basic-authorship", - "sc-cli", - "sc-client-api", - "sc-consensus", - "sc-consensus-aura", - "sc-consensus-grandpa", - "sc-executor", - "sc-network", - "sc-offchain", - "sc-rpc-api", - "sc-service", - "sc-telemetry", - "sc-transaction-pool", - "sc-transaction-pool-api", - "serde_json", - "sp-api", - "sp-block-builder", - "sp-blockchain", - "sp-consensus-aura", - "sp-consensus-grandpa", - "sp-core", - "sp-inherents", - "sp-io", - "sp-keyring", - "sp-runtime", - "sp-timestamp", - "substrate-build-script-utils", - "substrate-frame-rpc-system", - "try-runtime-cli", -] - [[package]] name = "node-template-release" version = "3.0.0" @@ -8784,45 +8740,6 @@ dependencies = [ "toml_edit 0.19.15", ] -[[package]] -name = "node-template-runtime" -version = "4.0.0-dev" -dependencies = [ - "frame-benchmarking", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "frame-try-runtime", - "pallet-aura", - "pallet-balances", - "pallet-grandpa", - "pallet-sudo", - "pallet-template", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "parity-scale-codec", - "scale-info", - "serde_json", - "sp-api", - "sp-block-builder", - "sp-consensus-aura", - "sp-consensus-grandpa", - "sp-core", - "sp-genesis-builder", - "sp-inherents", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std 14.0.0", - "sp-storage 19.0.0", - "sp-transaction-pool", - "sp-version", - "substrate-wasm-builder", -] - [[package]] name = "node-testing" version = "3.0.0-dev" @@ -10302,6 +10219,15 @@ dependencies = [ "sp-version", ] +[[package]] +name = "pallet-minimal-template" +version = "0.0.0" +dependencies = [ + "frame", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "pallet-mixnet" version = "0.4.0" @@ -10603,14 +10529,13 @@ dependencies = [ [[package]] name = "pallet-parachain-template" -version = "0.7.0" +version = "0.0.0" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", "scale-info", - "serde", "sp-core", "sp-io", "sp-runtime", @@ -11065,7 +10990,7 @@ dependencies = [ [[package]] name = "pallet-template" -version = "4.0.0-dev" +version = "0.0.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -11075,7 +11000,6 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -11389,7 +11313,7 @@ dependencies = [ [[package]] name = "parachain-template-node" -version = "0.1.0" +version = "0.0.0" dependencies = [ "clap 4.5.1", "color-print", @@ -11447,7 +11371,7 @@ dependencies = [ [[package]] name = "parachain-template-runtime" -version = "0.7.0" +version = "0.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", @@ -18356,6 +18280,87 @@ dependencies = [ "sha-1 0.9.8", ] +[[package]] +name = "solochain-template-node" +version = "0.0.0" +dependencies = [ + "clap 4.5.1", + "frame-benchmarking-cli", + "frame-system", + "futures", + "jsonrpsee", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc", + "sc-basic-authorship", + "sc-cli", + "sc-client-api", + "sc-consensus", + "sc-consensus-aura", + "sc-consensus-grandpa", + "sc-executor", + "sc-network", + "sc-offchain", + "sc-rpc-api", + "sc-service", + "sc-telemetry", + "sc-transaction-pool", + "sc-transaction-pool-api", + "serde_json", + "solochain-template-runtime", + "sp-api", + "sp-block-builder", + "sp-blockchain", + "sp-consensus-aura", + "sp-consensus-grandpa", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keyring", + "sp-runtime", + "sp-timestamp", + "substrate-build-script-utils", + "substrate-frame-rpc-system", + "try-runtime-cli", +] + +[[package]] +name = "solochain-template-runtime" +version = "0.0.0" +dependencies = [ + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "pallet-aura", + "pallet-balances", + "pallet-grandpa", + "pallet-sudo", + "pallet-template", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-consensus-grandpa", + "sp-core", + "sp-genesis-builder", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std 14.0.0", + "sp-storage 19.0.0", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", +] + [[package]] name = "sp-api" version = "26.0.0" diff --git a/Cargo.toml b/Cargo.toml index 48aa25f5c5a..a2e22e0b927 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ authors = ["Parity Technologies "] edition = "2021" repository = "https://github.com/paritytech/polkadot-sdk.git" license = "GPL-3.0-only" +homepage = "https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/index.html" [workspace] resolver = "2" @@ -74,9 +75,6 @@ members = [ "cumulus/pallets/solo-to-para", "cumulus/pallets/xcm", "cumulus/pallets/xcmp-queue", - "cumulus/parachain-template/node", - "cumulus/parachain-template/pallets/template", - "cumulus/parachain-template/runtime", "cumulus/parachains/common", "cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo", "cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend", @@ -219,11 +217,6 @@ members = [ "polkadot/xcm/xcm-simulator", "polkadot/xcm/xcm-simulator/example", "polkadot/xcm/xcm-simulator/fuzzer", - "substrate/bin/minimal/node", - "substrate/bin/minimal/runtime", - "substrate/bin/node-template/node", - "substrate/bin/node-template/pallets/template", - "substrate/bin/node-template/runtime", "substrate/bin/node/bench", "substrate/bin/node/cli", "substrate/bin/node/inspect", @@ -504,6 +497,18 @@ members = [ "substrate/utils/frame/try-runtime/cli", "substrate/utils/prometheus", "substrate/utils/wasm-builder", + + "templates/minimal/node", + "templates/minimal/pallets/template", + "templates/minimal/runtime", + + "templates/solochain/node", + "templates/solochain/pallets/template", + "templates/solochain/runtime", + + "templates/parachain/node", + "templates/parachain/pallets/template", + "templates/parachain/runtime", ] default-members = ["polkadot", "substrate/bin/node/cli"] diff --git a/cumulus/parachain-template/pallets/template/README.md b/cumulus/parachain-template/pallets/template/README.md deleted file mode 100644 index 5a646123346..00000000000 --- a/cumulus/parachain-template/pallets/template/README.md +++ /dev/null @@ -1 +0,0 @@ -License: Unlicense diff --git a/cumulus/parachain-template/pallets/template/src/benchmarking.rs b/cumulus/parachain-template/pallets/template/src/benchmarking.rs deleted file mode 100644 index 8bba2a09867..00000000000 --- a/cumulus/parachain-template/pallets/template/src/benchmarking.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Benchmarking setup for pallet-parachain-template - -use super::*; - -#[allow(unused)] -use crate::Pallet as Template; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; -use frame_system::RawOrigin; - -benchmarks! { - do_something { - let s in 0 .. 100; - let caller: T::AccountId = whitelisted_caller(); - }: _(RawOrigin::Signed(caller), s) - verify { - assert_eq!(Something::::get(), Some(s)); - } -} - -impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test,); diff --git a/prdoc/pr_3460.prdoc b/prdoc/pr_3460.prdoc new file mode 100644 index 00000000000..1f16fe08908 --- /dev/null +++ b/prdoc/pr_3460.prdoc @@ -0,0 +1,26 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Repot all templates + +doc: + - audience: Runtime Dev + description: | + This PR moves all templates into a single folder in the polkadot-sdk repo (`/templates`) and + unifies their crate names as well. Most notably, the crate name for what was formerly known + as `node-template` is no `solochain-template-node`. The other two crates in the template are + consequently called: `solochain-runtime-template` and `pallet-solochain-template`. + The other two template crate names follow a similar patter, just replacing `solochain` with + `parachain` or `minimal`. + + This PR is part of a bigger step toward automating the template repositories, see the + following: https://github.com/paritytech/polkadot-sdk/issues/3155 + +# the following crates are removed and renamed, although none are released. +crates: + - name: minimal-template-runtime # formerly called minimal-runtime + - name: minimal-template-node # formerly called minimal-node + - name: solochain-template-node # formerly called node-template + - name: solochain-template-runtime # formerly called node-template-runtime + - name: parachain-template-runtime # formerly called parachain-runtime + - name: parachain-template-runtime # formerly called parachain-node diff --git a/substrate/bin/minimal/node/Cargo.toml b/substrate/bin/minimal/node/Cargo.toml deleted file mode 100644 index 65644861c9a..00000000000 --- a/substrate/bin/minimal/node/Cargo.toml +++ /dev/null @@ -1,60 +0,0 @@ -[package] -name = "minimal-node" -version = "4.0.0-dev" -description = "A fresh FRAME-based Substrate node, ready for hacking." -authors = ["Substrate DevHub "] -homepage = "https://substrate.io/" -edition = "2021" -license = "MIT-0" -publish = false -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" -build = "build.rs" - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[[bin]] -name = "minimal-node" - -[dependencies] -clap = { version = "4.5.1", features = ["derive"] } -futures = { version = "0.3.21", features = ["thread-pool"] } -futures-timer = "3.0.1" -jsonrpsee = { version = "0.22", features = ["server"] } -serde_json = { workspace = true, default-features = true } - -sc-cli = { path = "../../../client/cli" } -sc-executor = { path = "../../../client/executor" } -sc-network = { path = "../../../client/network" } -sc-service = { path = "../../../client/service" } -sc-telemetry = { path = "../../../client/telemetry" } -sc-transaction-pool = { path = "../../../client/transaction-pool" } -sc-transaction-pool-api = { path = "../../../client/transaction-pool/api" } -sc-consensus = { path = "../../../client/consensus/common" } -sc-consensus-manual-seal = { path = "../../../client/consensus/manual-seal" } -sc-rpc-api = { path = "../../../client/rpc-api" } -sc-basic-authorship = { path = "../../../client/basic-authorship" } -sc-offchain = { path = "../../../client/offchain" } -sc-client-api = { path = "../../../client/api" } - -sp-timestamp = { path = "../../../primitives/timestamp" } -sp-keyring = { path = "../../../primitives/keyring" } -sp-api = { path = "../../../primitives/api" } -sp-blockchain = { path = "../../../primitives/blockchain" } -sp-block-builder = { path = "../../../primitives/block-builder" } -sp-io = { path = "../../../primitives/io" } -sp-runtime = { path = "../../../primitives/runtime" } - -substrate-frame-rpc-system = { path = "../../../utils/frame/rpc/system" } - -frame = { path = "../../../frame", features = ["experimental", "runtime"] } -runtime = { package = "minimal-runtime", path = "../runtime" } - -[build-dependencies] -substrate-build-script-utils = { path = "../../../utils/build-script-utils" } - -[features] -default = [] diff --git a/substrate/bin/minimal/runtime/Cargo.toml b/substrate/bin/minimal/runtime/Cargo.toml deleted file mode 100644 index 296106544bb..00000000000 --- a/substrate/bin/minimal/runtime/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -[package] -name = "minimal-runtime" -version = "0.1.0" -authors.workspace = true -description = "A minimal Substrate example runtime" -edition.workspace = true -repository.workspace = true -license.workspace = true -publish = false - -[lints] -workspace = true - -[dependencies] -parity-scale-codec = { version = "3.0.0", default-features = false } -scale-info = { version = "2.6.0", default-features = false } - -# this is a frame-based runtime, thus importing `frame` with runtime feature enabled. -frame = { path = "../../../frame", default-features = false, features = ["experimental", "runtime"] } -frame-support = { path = "../../../frame/support", default-features = false } - -# pallets that we want to use -pallet-balances = { path = "../../../frame/balances", default-features = false } -pallet-sudo = { path = "../../../frame/sudo", default-features = false } -pallet-timestamp = { path = "../../../frame/timestamp", default-features = false } -pallet-transaction-payment = { path = "../../../frame/transaction-payment", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { path = "../../../frame/transaction-payment/rpc/runtime-api", default-features = false } - -# genesis builder that allows us to interacto with runtime genesis config -sp-genesis-builder = { path = "../../../primitives/genesis-builder", default-features = false } - - -[build-dependencies] -substrate-wasm-builder = { path = "../../../utils/wasm-builder", optional = true } - -[features] -default = ["std"] -std = [ - "frame-support/std", - "frame/std", - "pallet-balances/std", - "pallet-sudo/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "parity-scale-codec/std", - "scale-info/std", - "sp-genesis-builder/std", - "substrate-wasm-builder", -] diff --git a/substrate/bin/node-template/.editorconfig b/substrate/bin/node-template/.editorconfig deleted file mode 100644 index 5adac74ca24..00000000000 --- a/substrate/bin/node-template/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -root = true - -[*] -indent_style=space -indent_size=2 -tab_width=2 -end_of_line=lf -charset=utf-8 -trim_trailing_whitespace=true -insert_final_newline = true - -[*.{rs,toml}] -indent_style=tab -indent_size=tab -tab_width=4 -max_line_length=100 diff --git a/substrate/bin/node-template/env-setup/.envrc b/substrate/bin/node-template/env-setup/.envrc deleted file mode 100644 index 3550a30f2de..00000000000 --- a/substrate/bin/node-template/env-setup/.envrc +++ /dev/null @@ -1 +0,0 @@ -use flake diff --git a/substrate/bin/node-template/node/Cargo.toml b/substrate/bin/node-template/node/Cargo.toml deleted file mode 100644 index 2f31947e492..00000000000 --- a/substrate/bin/node-template/node/Cargo.toml +++ /dev/null @@ -1,93 +0,0 @@ -[package] -name = "node-template" -version = "4.0.0-dev" -description = "A fresh FRAME-based Substrate node, ready for hacking." -authors = ["Substrate DevHub "] -homepage = "https://substrate.io/" -edition.workspace = true -license = "MIT-0" -publish = false -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" -build = "build.rs" - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[[bin]] -name = "node-template" - -[dependencies] -clap = { version = "4.5.1", features = ["derive"] } -futures = { version = "0.3.21", features = ["thread-pool"] } -serde_json = { workspace = true, default-features = true } - -sc-cli = { path = "../../../client/cli" } -sp-core = { path = "../../../primitives/core" } -sc-executor = { path = "../../../client/executor" } -sc-network = { path = "../../../client/network" } -sc-service = { path = "../../../client/service" } -sc-telemetry = { path = "../../../client/telemetry" } -sc-transaction-pool = { path = "../../../client/transaction-pool" } -sc-transaction-pool-api = { path = "../../../client/transaction-pool/api" } -sc-offchain = { path = "../../../client/offchain" } -sc-consensus-aura = { path = "../../../client/consensus/aura" } -sp-consensus-aura = { path = "../../../primitives/consensus/aura" } -sc-consensus = { path = "../../../client/consensus/common" } -sc-consensus-grandpa = { path = "../../../client/consensus/grandpa" } -sp-consensus-grandpa = { path = "../../../primitives/consensus/grandpa" } -sc-client-api = { path = "../../../client/api" } -sp-runtime = { path = "../../../primitives/runtime" } -sp-io = { path = "../../../primitives/io" } -sp-timestamp = { path = "../../../primitives/timestamp" } -sp-inherents = { path = "../../../primitives/inherents" } -sp-keyring = { path = "../../../primitives/keyring" } -frame-system = { path = "../../../frame/system" } -pallet-transaction-payment = { path = "../../../frame/transaction-payment", default-features = false } - -# These dependencies are used for the node template's RPCs -jsonrpsee = { version = "0.22", features = ["server"] } -sp-api = { path = "../../../primitives/api" } -sc-rpc-api = { path = "../../../client/rpc-api" } -sp-blockchain = { path = "../../../primitives/blockchain" } -sp-block-builder = { path = "../../../primitives/block-builder" } -sc-basic-authorship = { path = "../../../client/basic-authorship" } -substrate-frame-rpc-system = { path = "../../../utils/frame/rpc/system" } -pallet-transaction-payment-rpc = { path = "../../../frame/transaction-payment/rpc" } - -# These dependencies are used for runtime benchmarking -frame-benchmarking = { path = "../../../frame/benchmarking" } -frame-benchmarking-cli = { path = "../../../utils/frame/benchmarking-cli" } - -# Local Dependencies -node-template-runtime = { path = "../runtime" } - -# CLI-specific dependencies -try-runtime-cli = { path = "../../../utils/frame/try-runtime/cli", optional = true } - -[build-dependencies] -substrate-build-script-utils = { path = "../../../utils/build-script-utils" } - -[features] -default = [] -# Dependencies that are only required if runtime benchmarking should be build. -runtime-benchmarks = [ - "frame-benchmarking-cli/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "node-template-runtime/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", - "sc-service/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] -# Enable features that allow the runtime to be tried and debugged. Name might be subject to change -# in the near future. -try-runtime = [ - "frame-system/try-runtime", - "node-template-runtime/try-runtime", - "pallet-transaction-payment/try-runtime", - "sp-runtime/try-runtime", - "try-runtime-cli/try-runtime", -] diff --git a/substrate/bin/node-template/runtime/Cargo.toml b/substrate/bin/node-template/runtime/Cargo.toml deleted file mode 100644 index c7cffa568db..00000000000 --- a/substrate/bin/node-template/runtime/Cargo.toml +++ /dev/null @@ -1,126 +0,0 @@ -[package] -name = "node-template-runtime" -version = "4.0.0-dev" -description = "A fresh FRAME-based Substrate node, ready for hacking." -authors = ["Substrate DevHub "] -homepage = "https://substrate.io/" -edition.workspace = true -license = "MIT-0" -publish = false -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive", "serde"] } - -pallet-aura = { path = "../../../frame/aura", default-features = false } -pallet-balances = { path = "../../../frame/balances", default-features = false } -frame-support = { path = "../../../frame/support", default-features = false } -pallet-grandpa = { path = "../../../frame/grandpa", default-features = false } -pallet-sudo = { path = "../../../frame/sudo", default-features = false } -frame-system = { path = "../../../frame/system", default-features = false } -frame-try-runtime = { path = "../../../frame/try-runtime", default-features = false, optional = true } -pallet-timestamp = { path = "../../../frame/timestamp", default-features = false } -pallet-transaction-payment = { path = "../../../frame/transaction-payment", default-features = false } -frame-executive = { path = "../../../frame/executive", default-features = false } -sp-api = { path = "../../../primitives/api", default-features = false } -sp-block-builder = { path = "../../../primitives/block-builder", default-features = false } -sp-consensus-aura = { path = "../../../primitives/consensus/aura", default-features = false, features = ["serde"] } -sp-consensus-grandpa = { path = "../../../primitives/consensus/grandpa", default-features = false, features = ["serde"] } -sp-core = { path = "../../../primitives/core", default-features = false, features = ["serde"] } -sp-inherents = { path = "../../../primitives/inherents", default-features = false } -sp-offchain = { path = "../../../primitives/offchain", default-features = false } -sp-runtime = { path = "../../../primitives/runtime", default-features = false, features = ["serde"] } -sp-session = { path = "../../../primitives/session", default-features = false } -sp-std = { path = "../../../primitives/std", default-features = false } -sp-storage = { path = "../../../primitives/storage", default-features = false } -sp-transaction-pool = { path = "../../../primitives/transaction-pool", default-features = false } -sp-version = { path = "../../../primitives/version", default-features = false, features = ["serde"] } -serde_json = { features = ["alloc"], workspace = true } -sp-genesis-builder = { default-features = false, path = "../../../primitives/genesis-builder" } - -# Used for the node template's RPCs -frame-system-rpc-runtime-api = { path = "../../../frame/system/rpc/runtime-api", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { path = "../../../frame/transaction-payment/rpc/runtime-api", default-features = false } - -# Used for runtime benchmarking -frame-benchmarking = { path = "../../../frame/benchmarking", default-features = false, optional = true } -frame-system-benchmarking = { path = "../../../frame/system/benchmarking", default-features = false, optional = true } - -# Local Dependencies -pallet-template = { path = "../pallets/template", default-features = false } - -[build-dependencies] -substrate-wasm-builder = { path = "../../../utils/wasm-builder", optional = true } - -[features] -default = ["std"] -std = [ - "codec/std", - "frame-benchmarking?/std", - "frame-executive/std", - "frame-support/std", - "frame-system-benchmarking?/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "frame-try-runtime?/std", - "pallet-aura/std", - "pallet-balances/std", - "pallet-grandpa/std", - "pallet-sudo/std", - "pallet-template/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "scale-info/std", - "serde_json/std", - "sp-api/std", - "sp-block-builder/std", - "sp-consensus-aura/std", - "sp-consensus-grandpa/std", - "sp-core/std", - "sp-genesis-builder/std", - "sp-inherents/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", -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-grandpa/runtime-benchmarks", - "pallet-sudo/runtime-benchmarks", - "pallet-template/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] -try-runtime = [ - "frame-executive/try-runtime", - "frame-support/try-runtime", - "frame-system/try-runtime", - "frame-try-runtime/try-runtime", - "pallet-aura/try-runtime", - "pallet-balances/try-runtime", - "pallet-grandpa/try-runtime", - "pallet-sudo/try-runtime", - "pallet-template/try-runtime", - "pallet-timestamp/try-runtime", - "pallet-transaction-payment/try-runtime", - "sp-runtime/try-runtime", -] -experimental = ["pallet-aura/experimental"] diff --git a/substrate/frame/Cargo.toml b/substrate/frame/Cargo.toml index 3f148bf4c83..6746723e72f 100644 --- a/substrate/frame/Cargo.toml +++ b/substrate/frame/Cargo.toml @@ -19,8 +19,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # external deps -parity-scale-codec = { version = "3.2.2", default-features = false, features = ["derive"] } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.2.2", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.6.0", default-features = false, features = [ + "derive", +] } # primitive deps, used for developing FRAME pallets. sp-runtime = { default-features = false, path = "../primitives/runtime" } @@ -57,8 +61,6 @@ pallet-examples = { path = "./examples" } default = ["runtime", "std"] experimental = ["frame-support/experimental"] runtime = [ - "frame-executive", - "frame-system-rpc-runtime-api", "sp-api", "sp-block-builder", "sp-consensus-aura", @@ -68,6 +70,9 @@ runtime = [ "sp-session", "sp-transaction-pool", "sp-version", + + "frame-executive", + "frame-system-rpc-runtime-api", ] std = [ "frame-executive?/std", diff --git a/substrate/frame/examples/default-config/src/lib.rs b/substrate/frame/examples/default-config/src/lib.rs index 69eca055965..224faf9dfd4 100644 --- a/substrate/frame/examples/default-config/src/lib.rs +++ b/substrate/frame/examples/default-config/src/lib.rs @@ -108,7 +108,7 @@ pub mod pallet { } /// A type providing default configurations for this pallet in another environment. Examples - /// could be a parachain, or a solo-chain. + /// could be a parachain, or a solochain. /// /// Appropriate derive for `frame_system::DefaultConfig` needs to be provided. In this /// example, we simple derive `frame_system::config_preludes::TestDefaultConfig` again. diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 21393cb3e20..0318f77342e 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -310,7 +310,7 @@ pub mod pallet { type PostTransactions = (); } - /// Default configurations of this pallet in a solo-chain environment. + /// Default configurations of this pallet in a solochain environment. /// /// ## Considerations: /// diff --git a/templates/minimal/README.md b/templates/minimal/README.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/templates/minimal/node/Cargo.toml b/templates/minimal/node/Cargo.toml new file mode 100644 index 00000000000..410cfc9f6c3 --- /dev/null +++ b/templates/minimal/node/Cargo.toml @@ -0,0 +1,62 @@ +[package] +name = "minimal-template-node" +description = "A miniaml Substrate-based Substrate node, ready for hacking." +version = "0.0.0" +license = "MIT-0" +authors.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true +publish = false +build = "build.rs" + +[lints] +workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +clap = { version = "4.5.1", features = ["derive"] } +futures = { version = "0.3.21", features = ["thread-pool"] } +futures-timer = "3.0.1" +jsonrpsee = { version = "0.22", features = ["server"] } +serde_json = { workspace = true, default-features = true } + +sc-cli = { path = "../../../substrate/client/cli" } +sc-executor = { path = "../../../substrate/client/executor" } +sc-network = { path = "../../../substrate/client/network" } +sc-service = { path = "../../../substrate/client/service" } +sc-telemetry = { path = "../../../substrate/client/telemetry" } +sc-transaction-pool = { path = "../../../substrate/client/transaction-pool" } +sc-transaction-pool-api = { path = "../../../substrate/client/transaction-pool/api" } +sc-consensus = { path = "../../../substrate/client/consensus/common" } +sc-consensus-manual-seal = { path = "../../../substrate/client/consensus/manual-seal" } +sc-rpc-api = { path = "../../../substrate/client/rpc-api" } +sc-basic-authorship = { path = "../../../substrate/client/basic-authorship" } +sc-offchain = { path = "../../../substrate/client/offchain" } +sc-client-api = { path = "../../../substrate/client/api" } + +sp-timestamp = { path = "../../../substrate/primitives/timestamp" } +sp-keyring = { path = "../../../substrate/primitives/keyring" } +sp-api = { path = "../../../substrate/primitives/api" } +sp-blockchain = { path = "../../../substrate/primitives/blockchain" } +sp-block-builder = { path = "../../../substrate/primitives/block-builder" } +sp-io = { path = "../../../substrate/primitives/io" } +sp-runtime = { path = "../../../substrate/primitives/runtime" } + +substrate-frame-rpc-system = { path = "../../../substrate/utils/frame/rpc/system" } + +# Once the native runtime is gone, there should be little to no dependency on FRAME here, and +# certainly no dependency on the runtime. +frame = { path = "../../../substrate/frame", features = [ + "experimental", + "runtime", +] } +runtime = { package = "minimal-template-runtime", path = "../runtime" } + +[build-dependencies] +substrate-build-script-utils = { path = "../../../substrate/utils/build-script-utils" } + +[features] +default = [] diff --git a/substrate/bin/minimal/node/build.rs b/templates/minimal/node/build.rs similarity index 100% rename from substrate/bin/minimal/node/build.rs rename to templates/minimal/node/build.rs diff --git a/substrate/bin/minimal/node/src/chain_spec.rs b/templates/minimal/node/src/chain_spec.rs similarity index 100% rename from substrate/bin/minimal/node/src/chain_spec.rs rename to templates/minimal/node/src/chain_spec.rs diff --git a/substrate/bin/minimal/node/src/cli.rs b/templates/minimal/node/src/cli.rs similarity index 100% rename from substrate/bin/minimal/node/src/cli.rs rename to templates/minimal/node/src/cli.rs diff --git a/substrate/bin/minimal/node/src/command.rs b/templates/minimal/node/src/command.rs similarity index 100% rename from substrate/bin/minimal/node/src/command.rs rename to templates/minimal/node/src/command.rs diff --git a/substrate/bin/minimal/node/src/lib.rs b/templates/minimal/node/src/lib.rs similarity index 94% rename from substrate/bin/minimal/node/src/lib.rs rename to templates/minimal/node/src/lib.rs index c2065def736..cb8ed3bd209 100644 --- a/substrate/bin/minimal/node/src/lib.rs +++ b/templates/minimal/node/src/lib.rs @@ -1,4 +1,4 @@ -// This file is part of Substrate. +// This file is part of Polkadot Sdk. // Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 diff --git a/substrate/bin/minimal/node/src/main.rs b/templates/minimal/node/src/main.rs similarity index 100% rename from substrate/bin/minimal/node/src/main.rs rename to templates/minimal/node/src/main.rs diff --git a/substrate/bin/minimal/node/src/rpc.rs b/templates/minimal/node/src/rpc.rs similarity index 100% rename from substrate/bin/minimal/node/src/rpc.rs rename to templates/minimal/node/src/rpc.rs diff --git a/substrate/bin/minimal/node/src/service.rs b/templates/minimal/node/src/service.rs similarity index 100% rename from substrate/bin/minimal/node/src/service.rs rename to templates/minimal/node/src/service.rs diff --git a/templates/minimal/pallets/template/Cargo.toml b/templates/minimal/pallets/template/Cargo.toml new file mode 100644 index 00000000000..9982e5ea53b --- /dev/null +++ b/templates/minimal/pallets/template/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "pallet-minimal-template" +description = "A minimal pallet built with FRAME, part of Polkadot Sdk." +version = "0.0.0" +license = "MIT-0" +authors.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true +publish = false + +[lints] +workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", features = [ + "derive", +], default-features = false } +scale-info = { version = "2.10.0", default-features = false, features = [ + "derive", +] } +frame = { path = "../../../../substrate/frame", default-features = false, features = [ + "experimental", + "runtime", +] } + + +[features] +default = ["std"] +std = ["codec/std", "frame/std", "scale-info/std"] diff --git a/templates/minimal/pallets/template/src/lib.rs b/templates/minimal/pallets/template/src/lib.rs new file mode 100644 index 00000000000..713f014bbe6 --- /dev/null +++ b/templates/minimal/pallets/template/src/lib.rs @@ -0,0 +1,19 @@ +//! A shell pallet built with [`frame`]. + +#![cfg_attr(not(feature = "std"), no_std)] + +use frame::prelude::*; + +// Re-export all pallet parts, this is needed to properly import the pallet into the runtime. +pub use pallet::*; + +#[frame::pallet] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); +} diff --git a/templates/minimal/runtime/Cargo.toml b/templates/minimal/runtime/Cargo.toml new file mode 100644 index 00000000000..20ffb706eb4 --- /dev/null +++ b/templates/minimal/runtime/Cargo.toml @@ -0,0 +1,59 @@ +[package] +name = "minimal-template-runtime" +description = "A solochain runtime template built with Substrate, part of Polkadot Sdk." +version = "0.0.0" +license = "MIT-0" +authors.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true +publish = false + +[lints] +workspace = true + +[dependencies] +parity-scale-codec = { version = "3.0.0", default-features = false } +scale-info = { version = "2.6.0", default-features = false } + +# this is a frame-based runtime, thus importing `frame` with runtime feature enabled. +frame = { path = "../../../substrate/frame", default-features = false, features = [ + "experimental", + "runtime", +] } + +# pallets that we want to use +pallet-balances = { path = "../../../substrate/frame/balances", default-features = false } +pallet-sudo = { path = "../../../substrate/frame/sudo", default-features = false } +pallet-timestamp = { path = "../../../substrate/frame/timestamp", default-features = false } +pallet-transaction-payment = { path = "../../../substrate/frame/transaction-payment", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { path = "../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false } + +# genesis builder that allows us to interacto with runtime genesis config +sp-genesis-builder = { path = "../../../substrate/primitives/genesis-builder", default-features = false } + +# local pallet templates +pallet-minimal-template = { path = "../pallets/template", default-features = false } + +[build-dependencies] +substrate-wasm-builder = { path = "../../../substrate/utils/wasm-builder", optional = true } + +[features] +default = ["std"] +std = [ + "parity-scale-codec/std", + "scale-info/std", + + "frame/std", + + "pallet-balances/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + + "pallet-minimal-template/std", + + "sp-genesis-builder/std", + "substrate-wasm-builder", +] diff --git a/substrate/bin/minimal/runtime/build.rs b/templates/minimal/runtime/build.rs similarity index 100% rename from substrate/bin/minimal/runtime/build.rs rename to templates/minimal/runtime/build.rs diff --git a/substrate/bin/minimal/runtime/src/lib.rs b/templates/minimal/runtime/src/lib.rs similarity index 95% rename from substrate/bin/minimal/runtime/src/lib.rs rename to templates/minimal/runtime/src/lib.rs index d3e8a2e8ec0..6920511e276 100644 --- a/substrate/bin/minimal/runtime/src/lib.rs +++ b/templates/minimal/runtime/src/lib.rs @@ -22,7 +22,10 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); use frame::{ - deps::frame_support::weights::{FixedFee, NoFee}, + deps::frame_support::{ + genesis_builder_helper::{build_config, create_default_config}, + weights::{FixedFee, NoFee}, + }, prelude::*, runtime::{ apis::{ @@ -32,12 +35,11 @@ use frame::{ prelude::*, }, }; -use frame_support::genesis_builder_helper::{build_config, create_default_config}; #[runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("minimal-runtime"), - impl_name: create_runtime_str!("minimal-runtime"), + spec_name: create_runtime_str!("minimal-template-runtime"), + impl_name: create_runtime_str!("minimal-template-runtime"), authoring_version: 1, spec_version: 0, impl_version: 1, @@ -71,6 +73,9 @@ construct_runtime!( Balances: pallet_balances, Sudo: pallet_sudo, TransactionPayment: pallet_transaction_payment, + + // our local pallet + Template: pallet_minimal_template, } ); @@ -104,6 +109,8 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = FixedFee<1, ::Balance>; } +impl pallet_minimal_template::Config for Runtime {} + type Block = frame::runtime::types_common::BlockOf; type Header = HeaderFor; diff --git a/cumulus/parachain-template/LICENSE b/templates/parachain/LICENSE similarity index 100% rename from cumulus/parachain-template/LICENSE rename to templates/parachain/LICENSE diff --git a/cumulus/parachain-template/README.md b/templates/parachain/README.md similarity index 100% rename from cumulus/parachain-template/README.md rename to templates/parachain/README.md diff --git a/cumulus/parachain-template/node/Cargo.toml b/templates/parachain/node/Cargo.toml similarity index 78% rename from cumulus/parachain-template/node/Cargo.toml rename to templates/parachain/node/Cargo.toml index 0ef678c4cba..b4f3a504a4d 100644 --- a/cumulus/parachain-template/node/Cargo.toml +++ b/templates/parachain/node/Cargo.toml @@ -1,18 +1,21 @@ [package] name = "parachain-template-node" -version = "0.1.0" -authors = ["Anonymous"] -description = "A new Cumulus FRAME-based Substrate Node, ready for hacking together a parachain." -license = "Unlicense" -homepage = "https://substrate.io" +description = "A parachain node template built with Substrate and Cumulus, part of Polkadot Sdk." +version = "0.0.0" +license = "MIT-0" +authors.workspace = true +homepage.workspace = true repository.workspace = true edition.workspace = true -build = "build.rs" publish = false +build = "build.rs" [lints] workspace = true +# [[bin]] +# name = "parachain-template-node" + [dependencies] clap = { version = "4.5.1", features = ["derive"] } log = { workspace = true, default-features = true } @@ -63,15 +66,15 @@ polkadot-primitives = { path = "../../../polkadot/primitives" } xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false } # Cumulus -cumulus-client-cli = { path = "../../client/cli" } -cumulus-client-collator = { path = "../../client/collator" } -cumulus-client-consensus-aura = { path = "../../client/consensus/aura" } -cumulus-client-consensus-common = { path = "../../client/consensus/common" } -cumulus-client-consensus-proposer = { path = "../../client/consensus/proposer" } -cumulus-client-service = { path = "../../client/service" } -cumulus-primitives-core = { path = "../../primitives/core" } -cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent" } -cumulus-relay-chain-interface = { path = "../../client/relay-chain-interface" } +cumulus-client-cli = { path = "../../../cumulus/client/cli" } +cumulus-client-collator = { path = "../../../cumulus/client/collator" } +cumulus-client-consensus-aura = { path = "../../../cumulus/client/consensus/aura" } +cumulus-client-consensus-common = { path = "../../../cumulus/client/consensus/common" } +cumulus-client-consensus-proposer = { path = "../../../cumulus/client/consensus/proposer" } +cumulus-client-service = { path = "../../../cumulus/client/service" } +cumulus-primitives-core = { path = "../../../cumulus/primitives/core" } +cumulus-primitives-parachain-inherent = { path = "../../../cumulus/primitives/parachain-inherent" } +cumulus-relay-chain-interface = { path = "../../../cumulus/client/relay-chain-interface" } color-print = "0.3.4" [build-dependencies] diff --git a/cumulus/parachain-template/node/build.rs b/templates/parachain/node/build.rs similarity index 100% rename from cumulus/parachain-template/node/build.rs rename to templates/parachain/node/build.rs diff --git a/cumulus/parachain-template/node/src/chain_spec.rs b/templates/parachain/node/src/chain_spec.rs similarity index 93% rename from cumulus/parachain-template/node/src/chain_spec.rs rename to templates/parachain/node/src/chain_spec.rs index a79c78699c0..16c91865cdb 100644 --- a/cumulus/parachain-template/node/src/chain_spec.rs +++ b/templates/parachain/node/src/chain_spec.rs @@ -1,5 +1,6 @@ use cumulus_primitives_core::ParaId; -use parachain_template_runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT}; +use parachain_template_runtime as runtime; +use runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT}; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; @@ -56,8 +57,8 @@ where /// Generate the session keys from individual elements. /// /// The input must be a tuple of individual keys (a single arg for now since we have just one key). -pub fn template_session_keys(keys: AuraId) -> parachain_template_runtime::SessionKeys { - parachain_template_runtime::SessionKeys { aura: keys } +pub fn template_session_keys(keys: AuraId) -> runtime::SessionKeys { + runtime::SessionKeys { aura: keys } } pub fn development_config() -> ChainSpec { @@ -68,8 +69,7 @@ pub fn development_config() -> ChainSpec { properties.insert("ss58Format".into(), 42.into()); ChainSpec::builder( - parachain_template_runtime::WASM_BINARY - .expect("WASM binary was not built, please build it!"), + runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"), Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! @@ -120,8 +120,7 @@ pub fn local_testnet_config() -> ChainSpec { #[allow(deprecated)] ChainSpec::builder( - parachain_template_runtime::WASM_BINARY - .expect("WASM binary was not built, please build it!"), + runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"), Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! diff --git a/cumulus/parachain-template/node/src/cli.rs b/templates/parachain/node/src/cli.rs similarity index 100% rename from cumulus/parachain-template/node/src/cli.rs rename to templates/parachain/node/src/cli.rs diff --git a/cumulus/parachain-template/node/src/command.rs b/templates/parachain/node/src/command.rs similarity index 100% rename from cumulus/parachain-template/node/src/command.rs rename to templates/parachain/node/src/command.rs diff --git a/cumulus/parachain-template/node/src/main.rs b/templates/parachain/node/src/main.rs similarity index 100% rename from cumulus/parachain-template/node/src/main.rs rename to templates/parachain/node/src/main.rs diff --git a/cumulus/parachain-template/node/src/rpc.rs b/templates/parachain/node/src/rpc.rs similarity index 100% rename from cumulus/parachain-template/node/src/rpc.rs rename to templates/parachain/node/src/rpc.rs diff --git a/cumulus/parachain-template/node/src/service.rs b/templates/parachain/node/src/service.rs similarity index 100% rename from cumulus/parachain-template/node/src/service.rs rename to templates/parachain/node/src/service.rs diff --git a/cumulus/parachain-template/pallets/template/Cargo.toml b/templates/parachain/pallets/template/Cargo.toml similarity index 68% rename from cumulus/parachain-template/pallets/template/Cargo.toml rename to templates/parachain/pallets/template/Cargo.toml index 04858a161fa..89eb9d51716 100644 --- a/cumulus/parachain-template/pallets/template/Cargo.toml +++ b/templates/parachain/pallets/template/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "pallet-parachain-template" -authors = ["Anonymous"] description = "FRAME pallet template for defining custom runtime logic." -version = "0.7.0" -license = "Unlicense" -homepage = "https://substrate.io" +version = "0.0.0" +license = "MIT-0" +authors.workspace = true +homepage.workspace = true repository.workspace = true edition.workspace = true +publish = false [lints] workspace = true @@ -15,21 +16,22 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"], default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.10.0", default-features = false, features = [ + "derive", +] } -# Substrate +# frame deps frame-benchmarking = { path = "../../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-support = { path = "../../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../../substrate/frame/system", default-features = false } [dev-dependencies] -serde = { workspace = true, default-features = true } - -# Substrate -sp-core = { path = "../../../../substrate/primitives/core", default-features = false } -sp-io = { path = "../../../../substrate/primitives/io", default-features = false } -sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false } +sp-core = { path = "../../../../substrate/primitives/core" } +sp-io = { path = "../../../../substrate/primitives/io" } +sp-runtime = { path = "../../../../substrate/primitives/runtime" } [features] default = ["std"] @@ -41,7 +43,7 @@ runtime-benchmarks = [ ] std = [ "codec/std", - "frame-benchmarking/std", + "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "scale-info/std", diff --git a/substrate/bin/node-template/pallets/template/README.md b/templates/parachain/pallets/template/README.md similarity index 100% rename from substrate/bin/node-template/pallets/template/README.md rename to templates/parachain/pallets/template/README.md diff --git a/substrate/bin/node-template/pallets/template/src/benchmarking.rs b/templates/parachain/pallets/template/src/benchmarking.rs similarity index 100% rename from substrate/bin/node-template/pallets/template/src/benchmarking.rs rename to templates/parachain/pallets/template/src/benchmarking.rs diff --git a/cumulus/parachain-template/pallets/template/src/lib.rs b/templates/parachain/pallets/template/src/lib.rs similarity index 96% rename from cumulus/parachain-template/pallets/template/src/lib.rs rename to templates/parachain/pallets/template/src/lib.rs index 24226d6cf40..11587d1df42 100644 --- a/cumulus/parachain-template/pallets/template/src/lib.rs +++ b/templates/parachain/pallets/template/src/lib.rs @@ -11,6 +11,8 @@ mod mock; #[cfg(test)] mod tests; +pub mod weights; + #[cfg(feature = "runtime-benchmarks")] mod benchmarking; @@ -24,6 +26,8 @@ pub mod pallet { pub trait Config: frame_system::Config { /// Because this pallet emits events, it depends on the runtime's definition of an event. type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// A type representing the weights required by the dispatchables of this pallet. + type WeightInfo: crate::weights::WeightInfo; } #[pallet::pallet] diff --git a/cumulus/parachain-template/pallets/template/src/mock.rs b/templates/parachain/pallets/template/src/mock.rs similarity index 98% rename from cumulus/parachain-template/pallets/template/src/mock.rs rename to templates/parachain/pallets/template/src/mock.rs index 411a16b116c..f510a8b773a 100644 --- a/cumulus/parachain-template/pallets/template/src/mock.rs +++ b/templates/parachain/pallets/template/src/mock.rs @@ -51,6 +51,7 @@ impl system::Config for Test { impl crate::Config for Test { type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } // Build genesis storage according to the mock runtime. diff --git a/cumulus/parachain-template/pallets/template/src/tests.rs b/templates/parachain/pallets/template/src/tests.rs similarity index 100% rename from cumulus/parachain-template/pallets/template/src/tests.rs rename to templates/parachain/pallets/template/src/tests.rs diff --git a/substrate/bin/node-template/pallets/template/src/weights.rs b/templates/parachain/pallets/template/src/weights.rs similarity index 100% rename from substrate/bin/node-template/pallets/template/src/weights.rs rename to templates/parachain/pallets/template/src/weights.rs diff --git a/cumulus/parachain-template/polkadot-launch/config.json b/templates/parachain/polkadot-launch/config.json similarity index 100% rename from cumulus/parachain-template/polkadot-launch/config.json rename to templates/parachain/polkadot-launch/config.json diff --git a/cumulus/parachain-template/runtime/Cargo.toml b/templates/parachain/runtime/Cargo.toml similarity index 82% rename from cumulus/parachain-template/runtime/Cargo.toml rename to templates/parachain/runtime/Cargo.toml index 60d8d6f5136..44e9341b568 100644 --- a/cumulus/parachain-template/runtime/Cargo.toml +++ b/templates/parachain/runtime/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "parachain-template-runtime" -version = "0.7.0" -authors = ["Anonymous"] -description = "A new Cumulus FRAME-based Substrate Runtime, ready for hacking together a parachain." -license = "Unlicense" -homepage = "https://substrate.io" +description = "A parachain runtime template built with Substrate and Cumulus, part of Polkadot Sdk." +version = "0.0.0" +license = "MIT-0" +authors.workspace = true +homepage.workspace = true repository.workspace = true edition.workspace = true +publish = false [lints] workspace = true @@ -18,16 +19,20 @@ targets = ["x86_64-unknown-linux-gnu"] substrate-wasm-builder = { path = "../../../substrate/utils/wasm-builder", optional = true } [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ + "derive", +] } hex-literal = { version = "0.4.1", optional = true } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = [ + "derive", +] } smallvec = "1.11.0" # Local pallet-parachain-template = { path = "../pallets/template", default-features = false } -# Substrate +# Substrate / FRAME frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-executive = { path = "../../../substrate/frame/executive", default-features = false } frame-support = { path = "../../../substrate/frame/support", default-features = false } @@ -35,6 +40,8 @@ frame-system = { path = "../../../substrate/frame/system", default-features = fa frame-system-benchmarking = { path = "../../../substrate/frame/system/benchmarking", default-features = false, optional = true } frame-system-rpc-runtime-api = { path = "../../../substrate/frame/system/rpc/runtime-api", default-features = false } frame-try-runtime = { path = "../../../substrate/frame/try-runtime", default-features = false, optional = true } + +# FRAME Pallets pallet-aura = { path = "../../../substrate/frame/aura", default-features = false } pallet-authorship = { path = "../../../substrate/frame/authorship", default-features = false } pallet-balances = { path = "../../../substrate/frame/balances", default-features = false } @@ -44,6 +51,8 @@ pallet-sudo = { path = "../../../substrate/frame/sudo", default-features = false pallet-timestamp = { path = "../../../substrate/frame/timestamp", default-features = false } pallet-transaction-payment = { path = "../../../substrate/frame/transaction-payment", default-features = false } pallet-transaction-payment-rpc-runtime-api = { path = "../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false } + +# Substrate Primitives sp-api = { path = "../../../substrate/primitives/api", default-features = false } sp-block-builder = { path = "../../../substrate/primitives/block-builder", default-features = false } sp-consensus-aura = { path = "../../../substrate/primitives/consensus/aura", default-features = false } @@ -66,17 +75,19 @@ xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/x xcm-executor = { package = "staging-xcm-executor", path = "../../../polkadot/xcm/xcm-executor", default-features = false } # Cumulus -cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false } -cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } -cumulus-pallet-session-benchmarking = { path = "../../pallets/session-benchmarking", default-features = false } -cumulus-pallet-xcm = { path = "../../pallets/xcm", default-features = false } -cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue", default-features = false } -cumulus-primitives-core = { path = "../../primitives/core", default-features = false } -cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false } -cumulus-primitives-storage-weight-reclaim = { path = "../../primitives/storage-weight-reclaim", default-features = false } -pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false } -parachains-common = { path = "../../parachains/common", default-features = false } -parachain-info = { package = "staging-parachain-info", path = "../../parachains/pallets/parachain-info", default-features = false } +cumulus-pallet-aura-ext = { path = "../../../cumulus/pallets/aura-ext", default-features = false } +cumulus-pallet-parachain-system = { path = "../../../cumulus/pallets/parachain-system", default-features = false, features = [ + "parameterized-consensus-hook", +] } +cumulus-pallet-session-benchmarking = { path = "../../../cumulus/pallets/session-benchmarking", default-features = false } +cumulus-pallet-xcm = { path = "../../../cumulus/pallets/xcm", default-features = false } +cumulus-pallet-xcmp-queue = { path = "../../../cumulus/pallets/xcmp-queue", default-features = false } +cumulus-primitives-core = { path = "../../../cumulus/primitives/core", default-features = false } +cumulus-primitives-utility = { path = "../../../cumulus/primitives/utility", default-features = false } +cumulus-primitives-storage-weight-reclaim = { path = "../../../cumulus/primitives/storage-weight-reclaim", default-features = false } +pallet-collator-selection = { path = "../../../cumulus/pallets/collator-selection", default-features = false } +parachains-common = { path = "../../../cumulus/parachains/common", default-features = false } +parachain-info = { package = "staging-parachain-info", path = "../../../cumulus/parachains/pallets/parachain-info", default-features = false } [features] default = ["std"] diff --git a/cumulus/parachain-template/runtime/build.rs b/templates/parachain/runtime/build.rs similarity index 100% rename from cumulus/parachain-template/runtime/build.rs rename to templates/parachain/runtime/build.rs diff --git a/cumulus/parachain-template/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs similarity index 99% rename from cumulus/parachain-template/runtime/src/lib.rs rename to templates/parachain/runtime/src/lib.rs index f7754e594e6..74ecd751f67 100644 --- a/cumulus/parachain-template/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -180,8 +180,8 @@ impl_opaque_keys! { #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("template-parachain"), - impl_name: create_runtime_str!("template-parachain"), + spec_name: create_runtime_str!("parachain-template-runtime"), + impl_name: create_runtime_str!("parachain-template-runtime"), authoring_version: 1, spec_version: 1, impl_version: 0, @@ -490,6 +490,7 @@ impl pallet_collator_selection::Config for Runtime { /// Configure the pallet template in pallets/template. impl pallet_parachain_template::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_parachain_template::weights::SubstrateWeight; } // Create the runtime by composing the FRAME pallets that were previously configured. diff --git a/cumulus/parachain-template/runtime/src/weights/block_weights.rs b/templates/parachain/runtime/src/weights/block_weights.rs similarity index 100% rename from cumulus/parachain-template/runtime/src/weights/block_weights.rs rename to templates/parachain/runtime/src/weights/block_weights.rs diff --git a/cumulus/parachain-template/runtime/src/weights/extrinsic_weights.rs b/templates/parachain/runtime/src/weights/extrinsic_weights.rs similarity index 100% rename from cumulus/parachain-template/runtime/src/weights/extrinsic_weights.rs rename to templates/parachain/runtime/src/weights/extrinsic_weights.rs diff --git a/cumulus/parachain-template/runtime/src/weights/mod.rs b/templates/parachain/runtime/src/weights/mod.rs similarity index 100% rename from cumulus/parachain-template/runtime/src/weights/mod.rs rename to templates/parachain/runtime/src/weights/mod.rs diff --git a/cumulus/parachain-template/runtime/src/weights/paritydb_weights.rs b/templates/parachain/runtime/src/weights/paritydb_weights.rs similarity index 100% rename from cumulus/parachain-template/runtime/src/weights/paritydb_weights.rs rename to templates/parachain/runtime/src/weights/paritydb_weights.rs diff --git a/cumulus/parachain-template/runtime/src/weights/rocksdb_weights.rs b/templates/parachain/runtime/src/weights/rocksdb_weights.rs similarity index 100% rename from cumulus/parachain-template/runtime/src/weights/rocksdb_weights.rs rename to templates/parachain/runtime/src/weights/rocksdb_weights.rs diff --git a/cumulus/parachain-template/runtime/src/xcm_config.rs b/templates/parachain/runtime/src/xcm_config.rs similarity index 100% rename from cumulus/parachain-template/runtime/src/xcm_config.rs rename to templates/parachain/runtime/src/xcm_config.rs diff --git a/substrate/bin/node-template/LICENSE b/templates/solochain/LICENSE similarity index 100% rename from substrate/bin/node-template/LICENSE rename to templates/solochain/LICENSE diff --git a/substrate/bin/node-template/README.md b/templates/solochain/README.md similarity index 100% rename from substrate/bin/node-template/README.md rename to templates/solochain/README.md diff --git a/substrate/bin/node-template/docs/rust-setup.md b/templates/solochain/docs/rust-setup.md similarity index 100% rename from substrate/bin/node-template/docs/rust-setup.md rename to templates/solochain/docs/rust-setup.md diff --git a/substrate/bin/node-template/env-setup/README.md b/templates/solochain/env-setup/README.md similarity index 100% rename from substrate/bin/node-template/env-setup/README.md rename to templates/solochain/env-setup/README.md diff --git a/substrate/bin/node-template/env-setup/flake.lock b/templates/solochain/env-setup/flake.lock similarity index 100% rename from substrate/bin/node-template/env-setup/flake.lock rename to templates/solochain/env-setup/flake.lock diff --git a/substrate/bin/node-template/env-setup/flake.nix b/templates/solochain/env-setup/flake.nix similarity index 100% rename from substrate/bin/node-template/env-setup/flake.nix rename to templates/solochain/env-setup/flake.nix diff --git a/substrate/bin/node-template/env-setup/rust-toolchain.toml b/templates/solochain/env-setup/rust-toolchain.toml similarity index 100% rename from substrate/bin/node-template/env-setup/rust-toolchain.toml rename to templates/solochain/env-setup/rust-toolchain.toml diff --git a/templates/solochain/node/Cargo.toml b/templates/solochain/node/Cargo.toml new file mode 100644 index 00000000000..5e50e6106c1 --- /dev/null +++ b/templates/solochain/node/Cargo.toml @@ -0,0 +1,92 @@ +[package] +name = "solochain-template-node" +description = "A solochain node template built with Substrate, part of Polkadot Sdk." +version = "0.0.0" +license = "MIT-0" +authors.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true +publish = false + +build = "build.rs" + +[lints] +workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +clap = { version = "4.5.1", features = ["derive"] } +futures = { version = "0.3.21", features = ["thread-pool"] } +serde_json = { workspace = true, default-features = true } +jsonrpsee = { version = "0.22", features = ["server"] } + +# substrate client +sc-cli = { path = "../../../substrate/client/cli" } +sp-core = { path = "../../../substrate/primitives/core" } +sc-executor = { path = "../../../substrate/client/executor" } +sc-network = { path = "../../../substrate/client/network" } +sc-service = { path = "../../../substrate/client/service" } +sc-telemetry = { path = "../../../substrate/client/telemetry" } +sc-transaction-pool = { path = "../../../substrate/client/transaction-pool" } +sc-transaction-pool-api = { path = "../../../substrate/client/transaction-pool/api" } +sc-offchain = { path = "../../../substrate/client/offchain" } +sc-consensus-aura = { path = "../../../substrate/client/consensus/aura" } +sp-consensus-aura = { path = "../../../substrate/primitives/consensus/aura" } +sc-consensus = { path = "../../../substrate/client/consensus/common" } +sc-consensus-grandpa = { path = "../../../substrate/client/consensus/grandpa" } +sp-consensus-grandpa = { path = "../../../substrate/primitives/consensus/grandpa" } +sc-client-api = { path = "../../../substrate/client/api" } +sc-rpc-api = { path = "../../../substrate/client/rpc-api" } +sc-basic-authorship = { path = "../../../substrate/client/basic-authorship" } + +# substrate primitives +sp-runtime = { path = "../../../substrate/primitives/runtime" } +sp-io = { path = "../../../substrate/primitives/io" } +sp-timestamp = { path = "../../../substrate/primitives/timestamp" } +sp-inherents = { path = "../../../substrate/primitives/inherents" } +sp-keyring = { path = "../../../substrate/primitives/keyring" } +sp-api = { path = "../../../substrate/primitives/api" } +sp-blockchain = { path = "../../../substrate/primitives/blockchain" } +sp-block-builder = { path = "../../../substrate/primitives/block-builder" } + +# frame and pallets +frame-system = { path = "../../../substrate/frame/system" } +pallet-transaction-payment = { path = "../../../substrate/frame/transaction-payment", default-features = false } +pallet-transaction-payment-rpc = { path = "../../../substrate/frame/transaction-payment/rpc" } +substrate-frame-rpc-system = { path = "../../../substrate/utils/frame/rpc/system" } + +# These dependencies are used for runtime benchmarking +frame-benchmarking-cli = { path = "../../../substrate/utils/frame/benchmarking-cli" } + +# Local Dependencies +solochain-template-runtime = { path = "../runtime" } + +# CLI-specific dependencies +try-runtime-cli = { path = "../../../substrate/utils/frame/try-runtime/cli", optional = true } + +[build-dependencies] +substrate-build-script-utils = { path = "../../../substrate/utils/build-script-utils" } + +[features] +default = [] +# Dependencies that are only required if runtime benchmarking should be build. +runtime-benchmarks = [ + "frame-benchmarking-cli/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", + "sc-service/runtime-benchmarks", + "solochain-template-runtime/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +# Enable features that allow the runtime to be tried and debugged. Name might be subject to change +# in the near future. +try-runtime = [ + "frame-system/try-runtime", + "pallet-transaction-payment/try-runtime", + "solochain-template-runtime/try-runtime", + "sp-runtime/try-runtime", + "try-runtime-cli/try-runtime", +] diff --git a/substrate/bin/node-template/node/build.rs b/templates/solochain/node/build.rs similarity index 100% rename from substrate/bin/node-template/node/build.rs rename to templates/solochain/node/build.rs diff --git a/substrate/bin/node-template/node/src/benchmarking.rs b/templates/solochain/node/src/benchmarking.rs similarity index 99% rename from substrate/bin/node-template/node/src/benchmarking.rs rename to templates/solochain/node/src/benchmarking.rs index eacc367669c..8710f303e1f 100644 --- a/substrate/bin/node-template/node/src/benchmarking.rs +++ b/templates/solochain/node/src/benchmarking.rs @@ -4,10 +4,10 @@ use crate::service::FullClient; -use node_template_runtime as runtime; use runtime::{AccountId, Balance, BalancesCall, SystemCall}; use sc_cli::Result; use sc_client_api::BlockBackend; +use solochain_template_runtime as runtime; use sp_core::{Encode, Pair}; use sp_inherents::{InherentData, InherentDataProvider}; use sp_keyring::Sr25519Keyring; diff --git a/substrate/bin/node-template/node/src/chain_spec.rs b/templates/solochain/node/src/chain_spec.rs similarity index 97% rename from substrate/bin/node-template/node/src/chain_spec.rs rename to templates/solochain/node/src/chain_spec.rs index 6e0d78f647a..be49f2c1fc7 100644 --- a/substrate/bin/node-template/node/src/chain_spec.rs +++ b/templates/solochain/node/src/chain_spec.rs @@ -1,5 +1,5 @@ -use node_template_runtime::{AccountId, RuntimeGenesisConfig, Signature, WASM_BINARY}; use sc_service::ChainType; +use solochain_template_runtime::{AccountId, RuntimeGenesisConfig, Signature, WASM_BINARY}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{sr25519, Pair, Public}; diff --git a/substrate/bin/node-template/node/src/cli.rs b/templates/solochain/node/src/cli.rs similarity index 100% rename from substrate/bin/node-template/node/src/cli.rs rename to templates/solochain/node/src/cli.rs diff --git a/substrate/bin/node-template/node/src/command.rs b/templates/solochain/node/src/command.rs similarity index 98% rename from substrate/bin/node-template/node/src/command.rs rename to templates/solochain/node/src/command.rs index 3778df66422..42d1477f22f 100644 --- a/substrate/bin/node-template/node/src/command.rs +++ b/templates/solochain/node/src/command.rs @@ -5,9 +5,9 @@ use crate::{ service, }; use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE}; -use node_template_runtime::{Block, EXISTENTIAL_DEPOSIT}; use sc_cli::SubstrateCli; use sc_service::PartialComponents; +use solochain_template_runtime::{Block, EXISTENTIAL_DEPOSIT}; use sp_keyring::Sr25519Keyring; impl SubstrateCli for Cli { diff --git a/substrate/bin/node-template/node/src/main.rs b/templates/solochain/node/src/main.rs similarity index 100% rename from substrate/bin/node-template/node/src/main.rs rename to templates/solochain/node/src/main.rs diff --git a/substrate/bin/node-template/node/src/rpc.rs b/templates/solochain/node/src/rpc.rs similarity index 96% rename from substrate/bin/node-template/node/src/rpc.rs rename to templates/solochain/node/src/rpc.rs index 246391adcbb..fe2b6ca72ed 100644 --- a/substrate/bin/node-template/node/src/rpc.rs +++ b/templates/solochain/node/src/rpc.rs @@ -8,8 +8,8 @@ use std::sync::Arc; use jsonrpsee::RpcModule; -use node_template_runtime::{opaque::Block, AccountId, Balance, Nonce}; use sc_transaction_pool_api::TransactionPool; +use solochain_template_runtime::{opaque::Block, AccountId, Balance, Nonce}; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; diff --git a/substrate/bin/node-template/node/src/service.rs b/templates/solochain/node/src/service.rs similarity index 99% rename from substrate/bin/node-template/node/src/service.rs rename to templates/solochain/node/src/service.rs index 125cca13927..dc25f757912 100644 --- a/substrate/bin/node-template/node/src/service.rs +++ b/templates/solochain/node/src/service.rs @@ -1,13 +1,13 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use futures::FutureExt; -use node_template_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{Backend, BlockBackend}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; use sc_consensus_grandpa::SharedVoterState; use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sc_transaction_pool_api::OffchainTransactionPoolFactory; +use solochain_template_runtime::{self, opaque::Block, RuntimeApi}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; diff --git a/substrate/bin/node-template/pallets/template/Cargo.toml b/templates/solochain/pallets/template/Cargo.toml similarity index 55% rename from substrate/bin/node-template/pallets/template/Cargo.toml rename to templates/solochain/pallets/template/Cargo.toml index 51410a71c7b..bd234715198 100644 --- a/substrate/bin/node-template/pallets/template/Cargo.toml +++ b/templates/solochain/pallets/template/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "pallet-template" -version = "4.0.0-dev" description = "FRAME pallet template for defining custom runtime logic." -authors = ["Substrate DevHub "] -homepage = "https://substrate.io" -edition.workspace = true +version = "0.0.0" license = "MIT-0" +authors.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true publish = false -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" [lints] workspace = true @@ -19,16 +19,19 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ "derive", ] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -frame-benchmarking = { path = "../../../../frame/benchmarking", default-features = false, optional = true } -frame-support = { path = "../../../../frame/support", default-features = false } -frame-system = { path = "../../../../frame/system", default-features = false } -sp-std = { path = "../../../../primitives/std", default-features = false } +scale-info = { version = "2.10.0", default-features = false, features = [ + "derive", +] } + +# frame deps +frame-benchmarking = { path = "../../../../substrate/frame/benchmarking", default-features = false, optional = true } +frame-support = { path = "../../../../substrate/frame/support", default-features = false } +frame-system = { path = "../../../../substrate/frame/system", default-features = false } [dev-dependencies] -sp-core = { path = "../../../../primitives/core" } -sp-io = { path = "../../../../primitives/io" } -sp-runtime = { path = "../../../../primitives/runtime" } +sp-core = { path = "../../../../substrate/primitives/core" } +sp-io = { path = "../../../../substrate/primitives/io" } +sp-runtime = { path = "../../../../substrate/primitives/runtime" } [features] default = ["std"] @@ -41,7 +44,6 @@ std = [ "sp-core/std", "sp-io/std", "sp-runtime/std", - "sp-std/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/templates/solochain/pallets/template/README.md b/templates/solochain/pallets/template/README.md new file mode 100644 index 00000000000..9e4dc55267d --- /dev/null +++ b/templates/solochain/pallets/template/README.md @@ -0,0 +1 @@ +License: MIT-0 diff --git a/templates/solochain/pallets/template/src/benchmarking.rs b/templates/solochain/pallets/template/src/benchmarking.rs new file mode 100644 index 00000000000..5a262417629 --- /dev/null +++ b/templates/solochain/pallets/template/src/benchmarking.rs @@ -0,0 +1,35 @@ +//! Benchmarking setup for pallet-template +#![cfg(feature = "runtime-benchmarks")] +use super::*; + +#[allow(unused)] +use crate::Pallet as Template; +use frame_benchmarking::v2::*; +use frame_system::RawOrigin; + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn do_something() { + let value = 100u32.into(); + let caller: T::AccountId = whitelisted_caller(); + #[extrinsic_call] + do_something(RawOrigin::Signed(caller), value); + + assert_eq!(Something::::get(), Some(value)); + } + + #[benchmark] + fn cause_error() { + Something::::put(100u32); + let caller: T::AccountId = whitelisted_caller(); + #[extrinsic_call] + cause_error(RawOrigin::Signed(caller)); + + assert_eq!(Something::::get(), Some(101u32)); + } + + impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/substrate/bin/node-template/pallets/template/src/lib.rs b/templates/solochain/pallets/template/src/lib.rs similarity index 100% rename from substrate/bin/node-template/pallets/template/src/lib.rs rename to templates/solochain/pallets/template/src/lib.rs diff --git a/substrate/bin/node-template/pallets/template/src/mock.rs b/templates/solochain/pallets/template/src/mock.rs similarity index 100% rename from substrate/bin/node-template/pallets/template/src/mock.rs rename to templates/solochain/pallets/template/src/mock.rs diff --git a/substrate/bin/node-template/pallets/template/src/tests.rs b/templates/solochain/pallets/template/src/tests.rs similarity index 100% rename from substrate/bin/node-template/pallets/template/src/tests.rs rename to templates/solochain/pallets/template/src/tests.rs diff --git a/templates/solochain/pallets/template/src/weights.rs b/templates/solochain/pallets/template/src/weights.rs new file mode 100644 index 00000000000..7c42936e09f --- /dev/null +++ b/templates/solochain/pallets/template/src/weights.rs @@ -0,0 +1,90 @@ + +//! Autogenerated weights for pallet_template +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-04-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `Alexs-MacBook-Pro-2.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ../../target/release/node-template +// benchmark +// pallet +// --chain +// dev +// --pallet +// pallet_template +// --extrinsic +// * +// --steps=50 +// --repeat=20 +// --wasm-execution=compiled +// --output +// pallets/template/src/weights.rs +// --template +// ../../.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for pallet_template. +pub trait WeightInfo { + fn do_something() -> Weight; + fn cause_error() -> Weight; +} + +/// Weights for pallet_template using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: TemplateModule Something (r:0 w:1) + /// Proof: TemplateModule Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn do_something() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 8_000_000 picoseconds. + Weight::from_parts(9_000_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: TemplateModule Something (r:1 w:1) + /// Proof: TemplateModule Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn cause_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `32` + // Estimated: `1489` + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(6_000_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + /// Storage: TemplateModule Something (r:0 w:1) + /// Proof: TemplateModule Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn do_something() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 8_000_000 picoseconds. + Weight::from_parts(9_000_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: TemplateModule Something (r:1 w:1) + /// Proof: TemplateModule Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn cause_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `32` + // Estimated: `1489` + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(6_000_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } +} diff --git a/templates/solochain/runtime/Cargo.toml b/templates/solochain/runtime/Cargo.toml new file mode 100644 index 00000000000..4f22e7ff6a3 --- /dev/null +++ b/templates/solochain/runtime/Cargo.toml @@ -0,0 +1,152 @@ +[package] +name = "solochain-template-runtime" +description = "A solochain runtime template built with Substrate, part of Polkadot Sdk." +version = "0.0.0" +license = "MIT-0" +authors.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true +publish = false + +[lints] +workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.10.0", default-features = false, features = [ + "derive", + "serde", +] } + +# frame +frame-support = { path = "../../../substrate/frame/support", default-features = false } +frame-system = { path = "../../../substrate/frame/system", default-features = false } +frame-try-runtime = { path = "../../../substrate/frame/try-runtime", default-features = false, optional = true } +frame-executive = { path = "../../../substrate/frame/executive", default-features = false } + +# frame pallets +pallet-aura = { path = "../../../substrate/frame/aura", default-features = false } +pallet-balances = { path = "../../../substrate/frame/balances", default-features = false } +pallet-grandpa = { path = "../../../substrate/frame/grandpa", default-features = false } +pallet-sudo = { path = "../../../substrate/frame/sudo", default-features = false } +pallet-timestamp = { path = "../../../substrate/frame/timestamp", default-features = false } +pallet-transaction-payment = { path = "../../../substrate/frame/transaction-payment", default-features = false } + +# primitives +sp-api = { path = "../../../substrate/primitives/api", default-features = false } +sp-block-builder = { path = "../../../substrate/primitives/block-builder", default-features = false } +sp-consensus-aura = { path = "../../../substrate/primitives/consensus/aura", default-features = false, features = [ + "serde", +] } +sp-consensus-grandpa = { path = "../../../substrate/primitives/consensus/grandpa", default-features = false, features = [ + "serde", +] } +sp-core = { path = "../../../substrate/primitives/core", default-features = false, features = [ + "serde", +] } +sp-inherents = { path = "../../../substrate/primitives/inherents", default-features = false } +sp-offchain = { path = "../../../substrate/primitives/offchain", default-features = false } +sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false, features = [ + "serde", +] } +sp-session = { path = "../../../substrate/primitives/session", default-features = false } +sp-std = { path = "../../../substrate/primitives/std", default-features = false } +sp-storage = { path = "../../../substrate/primitives/storage", default-features = false } +sp-transaction-pool = { path = "../../../substrate/primitives/transaction-pool", default-features = false } +sp-version = { path = "../../../substrate/primitives/version", default-features = false, features = [ + "serde", +] } +sp-genesis-builder = { default-features = false, path = "../../../substrate/primitives/genesis-builder" } + +# RPC related +frame-system-rpc-runtime-api = { path = "../../../substrate/frame/system/rpc/runtime-api", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { path = "../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false } + +# Used for runtime benchmarking +frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } +frame-system-benchmarking = { path = "../../../substrate/frame/system/benchmarking", default-features = false, optional = true } + +# The pallet in this template. +pallet-template = { path = "../pallets/template", default-features = false } + +[build-dependencies] +substrate-wasm-builder = { path = "../../../substrate/utils/wasm-builder", optional = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + + "frame-executive/std", + "frame-support/std", + "frame-system-benchmarking?/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + + "frame-benchmarking?/std", + "frame-try-runtime?/std", + + "pallet-aura/std", + "pallet-balances/std", + "pallet-grandpa/std", + "pallet-sudo/std", + "pallet-template/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-consensus-grandpa/std", + "sp-core/std", + "sp-genesis-builder/std", + "sp-inherents/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", +] + +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-grandpa/runtime-benchmarks", + "pallet-sudo/runtime-benchmarks", + "pallet-template/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] + +try-runtime = [ + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-aura/try-runtime", + "pallet-balances/try-runtime", + "pallet-grandpa/try-runtime", + "pallet-sudo/try-runtime", + "pallet-template/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-transaction-payment/try-runtime", + "sp-runtime/try-runtime", +] + +experimental = ["pallet-aura/experimental"] diff --git a/substrate/bin/node-template/runtime/build.rs b/templates/solochain/runtime/build.rs similarity index 100% rename from substrate/bin/node-template/runtime/build.rs rename to templates/solochain/runtime/build.rs diff --git a/substrate/bin/node-template/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs similarity index 98% rename from substrate/bin/node-template/runtime/src/lib.rs rename to templates/solochain/runtime/src/lib.rs index ee622a691b4..409b639f021 100644 --- a/substrate/bin/node-template/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -1,8 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] -// Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); @@ -22,7 +19,6 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use frame_support::genesis_builder_helper::{build_config, create_default_config}; -// A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, derive_impl, parameter_types, traits::{ @@ -95,8 +91,8 @@ pub mod opaque { // https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("node-template"), - impl_name: create_runtime_str!("node-template"), + spec_name: create_runtime_str!("solochain-template-runtime"), + impl_name: create_runtime_str!("solochain-template-runtime"), authoring_version: 1, // The version of the runtime specification. A full node will not attempt to use its native // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, @@ -266,6 +262,7 @@ construct_runtime!( Balances: pallet_balances, TransactionPayment: pallet_transaction_payment, Sudo: pallet_sudo, + // Include the custom logic from the pallet-template in the runtime. TemplateModule: pallet_template, } -- GitLab From c367ac2488db23a68e1cdf446cece58c66ea93d5 Mon Sep 17 00:00:00 2001 From: Rodrigo Quelhas <22591718+RomarQ@users.noreply.github.com> Date: Tue, 5 Mar 2024 14:05:04 +0000 Subject: [PATCH 072/188] remove deprecated type 'GenesisConfig' (#3378) # Description Removed deprecated type `GenesisConfig` from the codebase. Closes https://github.com/paritytech/polkadot-sdk/issues/175 # Checklist - [x] My PR includes a detailed description as outlined in the "Description" section above - [x] My PR follows the [labeling requirements](CONTRIBUTING.md#Process) of this project (at minimum one label for `T` required) - [x] I have made corresponding changes to the documentation (if applicable) --------- Co-authored-by: Liam Aharon Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> --- prdoc/pr_3378.prdoc | 13 +++++++++ .../chain-spec/src/genesis_config_builder.rs | 24 ++++++++------- .../src/construct_runtime/expand/config.rs | 4 --- .../deprecated_where_block.stderr | 2 +- .../primitives/genesis-builder/Cargo.toml | 2 +- .../primitives/genesis-builder/src/lib.rs | 29 ++++++++++--------- 6 files changed, 43 insertions(+), 31 deletions(-) create mode 100644 prdoc/pr_3378.prdoc diff --git a/prdoc/pr_3378.prdoc b/prdoc/pr_3378.prdoc new file mode 100644 index 00000000000..2470fc15851 --- /dev/null +++ b/prdoc/pr_3378.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Remove deprecated GenesisConfig + +doc: + - audience: Runtime Dev + description: | + Removes deprecated type `GenesisConfig`, it was replaced by `RuntimeGenesisConfig` on May 24 of 2023. + The type `GenesisConfig` was deprecated on May 24 of 2023 [#14210](https://github.com/paritytech/substrate/pull/14210) + +crates: + - name: frame-support-procedural \ No newline at end of file diff --git a/substrate/client/chain-spec/src/genesis_config_builder.rs b/substrate/client/chain-spec/src/genesis_config_builder.rs index 6b956316203..c8b54f66be6 100644 --- a/substrate/client/chain-spec/src/genesis_config_builder.rs +++ b/substrate/client/chain-spec/src/genesis_config_builder.rs @@ -81,7 +81,8 @@ where .0 } - /// Returns the default `GenesisConfig` provided by the `runtime`. + /// Returns a json representation of the default `RuntimeGenesisConfig` provided by the + /// `runtime`. /// /// Calls [`GenesisBuilder::create_default_config`](sp_genesis_builder::GenesisBuilder::create_default_config) in the `runtime`. pub fn get_default_config(&self) -> core::result::Result { @@ -94,7 +95,7 @@ where Ok(from_slice(&default_config[..]).expect("returned value is json. qed.")) } - /// Build the given `GenesisConfig` and returns the genesis state. + /// Builds `RuntimeGenesisConfig` from given json blob and returns the genesis state. /// /// Calls [`GenesisBuilder::build_config`](sp_genesis_builder::GenesisBuilder::build_config) /// provided by the `runtime`. @@ -111,25 +112,26 @@ where Ok(ext.into_storages()) } - /// Creates the genesis state by patching the default `GenesisConfig` and applying it. + /// Creates the genesis state by patching the default `RuntimeGenesisConfig`. /// - /// This function generates the `GenesisConfig` for the runtime by applying a provided JSON - /// patch. The patch modifies the default `GenesisConfig` allowing customization of the specific - /// keys. The resulting `GenesisConfig` is then deserialized from the patched JSON - /// representation and stored in the storage. + /// This function generates the `RuntimeGenesisConfig` for the runtime by applying a provided + /// JSON patch. The patch modifies the default `RuntimeGenesisConfig` allowing customization of + /// the specific keys. The resulting `RuntimeGenesisConfig` is then deserialized from the + /// patched JSON representation and stored in the storage. /// /// If the provided JSON patch is incorrect or the deserialization fails the error will be /// returned. /// - /// The patching process modifies the default `GenesisConfig` according to the following rules: + /// The patching process modifies the default `RuntimeGenesisConfig` according to the following + /// rules: /// 1. Existing keys in the default configuration will be overridden by the corresponding values /// in the patch. /// 2. If a key exists in the patch but not in the default configuration, it will be added to - /// the resulting `GenesisConfig`. + /// the resulting `RuntimeGenesisConfig`. /// 3. Keys in the default configuration that have null values in the patch will be removed from - /// the resulting `GenesisConfig`. This is helpful for changing enum variant value. + /// the resulting `RuntimeGenesisConfig`. This is helpful for changing enum variant value. /// - /// Please note that the patch may contain full `GenesisConfig`. + /// Please note that the patch may contain full `RuntimeGenesisConfig`. pub fn get_storage_for_patch(&self, patch: Value) -> core::result::Result { let mut config = self.get_default_config()?; crate::json_patch::merge(&mut config, patch); diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs index 5613047359a..dbbe6ba6e6c 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs @@ -76,10 +76,6 @@ pub fn expand_outer_config( #fields } - #[cfg(any(feature = "std", test))] - #[deprecated(note = "GenesisConfig is planned to be removed in December 2023. Use `RuntimeGenesisConfig` instead.")] - pub type GenesisConfig = RuntimeGenesisConfig; - #[cfg(any(feature = "std", test))] impl #scrate::sp_runtime::BuildStorage for RuntimeGenesisConfig { fn assimilate_storage( diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr index 9dd460da75a..c677ddcd672 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr @@ -347,7 +347,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied 26 | System: frame_system::{Pallet, Call, Storage, Config, Event}, | ^^^^^^ the trait `Config` is not implemented for `Runtime` | -note: required by a bound in `frame_system::GenesisConfig` +note: required by a bound in `GenesisConfig` --> $WORKSPACE/substrate/frame/system/src/lib.rs | | pub struct GenesisConfig { diff --git a/substrate/primitives/genesis-builder/Cargo.toml b/substrate/primitives/genesis-builder/Cargo.toml index bf12433c5f4..15440b4811e 100644 --- a/substrate/primitives/genesis-builder/Cargo.toml +++ b/substrate/primitives/genesis-builder/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true license = "Apache-2.0" homepage = "https://substrate.io" repository.workspace = true -description = "Substrate GenesisConfig builder API" +description = "Substrate RuntimeGenesisConfig builder API" readme = "README.md" [lints] diff --git a/substrate/primitives/genesis-builder/src/lib.rs b/substrate/primitives/genesis-builder/src/lib.rs index e002cd3aa6f..bb1a2a35248 100644 --- a/substrate/primitives/genesis-builder/src/lib.rs +++ b/substrate/primitives/genesis-builder/src/lib.rs @@ -19,36 +19,37 @@ //! Substrate genesis config builder //! -//! This Runtime API allows to construct `GenesisConfig`, in particular: -//! - serialize the runtime default `GenesisConfig` struct into json format, -//! - put the GenesisConfig struct into the storage. Internally this operation calls +//! This Runtime API allows to construct `RuntimeGenesisConfig`, in particular: +//! - serialize the runtime default `RuntimeGenesisConfig` struct into json format, +//! - put the RuntimeGenesisConfig struct into the storage. Internally this operation calls //! `GenesisBuild::build` function for all runtime pallets, which is typically provided by //! pallet's author. -//! - deserialize the `GenesisConfig` from given json blob and put `GenesisConfig` into the state -//! storage. Allows to build customized configuration. +//! - deserialize the `RuntimeGenesisConfig` from given json blob and put `RuntimeGenesisConfig` +//! into the state storage. Allows to build customized configuration. //! -//! Providing externalities with empty storage and putting `GenesisConfig` into storage allows to -//! catch and build the raw storage of `GenesisConfig` which is the foundation for genesis block. +//! Providing externalities with empty storage and putting `RuntimeGenesisConfig` into storage +//! allows to catch and build the raw storage of `RuntimeGenesisConfig` which is the foundation for +//! genesis block. /// The result type alias, used in build methods. `Err` contains formatted error message. pub type Result = core::result::Result<(), sp_runtime::RuntimeString>; sp_api::decl_runtime_apis! { - /// API to interact with GenesisConfig for the runtime + /// API to interact with RuntimeGenesisConfig for the runtime pub trait GenesisBuilder { - /// Creates the default `GenesisConfig` and returns it as a JSON blob. + /// Creates the default `RuntimeGenesisConfig` and returns it as a JSON blob. /// - /// This function instantiates the default `GenesisConfig` struct for the runtime and serializes it into a JSON - /// blob. It returns a `Vec` containing the JSON representation of the default `GenesisConfig`. + /// This function instantiates the default `RuntimeGenesisConfig` struct for the runtime and serializes it into a JSON + /// blob. It returns a `Vec` containing the JSON representation of the default `RuntimeGenesisConfig`. fn create_default_config() -> sp_std::vec::Vec; - /// Build `GenesisConfig` from a JSON blob not using any defaults and store it in the storage. + /// Build `RuntimeGenesisConfig` from a JSON blob not using any defaults and store it in the storage. /// - /// This function deserializes the full `GenesisConfig` from the given JSON blob and puts it into the storage. + /// This function deserializes the full `RuntimeGenesisConfig` from the given JSON blob and puts it into the storage. /// If the provided JSON blob is incorrect or incomplete or the deserialization fails, an error is returned. /// It is recommended to log any errors encountered during the process. /// - /// Please note that provided json blob must contain all `GenesisConfig` fields, no defaults will be used. + /// Please note that provided json blob must contain all `RuntimeGenesisConfig` fields, no defaults will be used. fn build_config(json: sp_std::vec::Vec) -> Result; } } -- GitLab From 329c07723614836a05b1d9158e1a8fdea6fb6508 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 5 Mar 2024 18:16:24 +0100 Subject: [PATCH 073/188] [FRAME] Use 'ready' pages in XCMP suspend logic (#2393) Changes: - `QueueFootprint` gets a new field; `ready_pages` that contains the non-overweight and not yet processed pages. - `XCMP` queue pallet is change to use the `ready_pages` instead of `pages` to calculate the channel suspension thresholds. This should give the XCMP queue pallet a more correct view of when to suspend channels. --------- Signed-off-by: Oliver Tale-Yazdi --- cumulus/pallets/xcmp-queue/src/lib.rs | 6 +++--- cumulus/pallets/xcmp-queue/src/mock.rs | 1 + prdoc/pr_2393.prdoc | 16 ++++++++++++++++ .../frame/message-queue/src/integration_test.rs | 5 +++++ substrate/frame/message-queue/src/lib.rs | 9 +++++++-- substrate/frame/message-queue/src/mock.rs | 4 ++-- substrate/frame/message-queue/src/tests.rs | 13 +++++++++---- substrate/frame/support/src/traits/messages.rs | 2 ++ 8 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 prdoc/pr_2393.prdoc diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index 5b900769622..e92169be16b 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -600,7 +600,7 @@ impl Pallet { let QueueConfigData { drop_threshold, .. } = >::get(); let fp = T::XcmpQueue::footprint(sender); // Assume that it will not fit into the current page: - let new_pages = fp.pages.saturating_add(1); + let new_pages = fp.ready_pages.saturating_add(1); if new_pages > drop_threshold { // This should not happen since the channel should have been suspended in // [`on_queue_changed`]. @@ -663,12 +663,12 @@ impl OnQueueChanged for Pallet { let mut suspended_channels = >::get(); let suspended = suspended_channels.contains(¶); - if suspended && fp.pages <= resume_threshold { + if suspended && fp.ready_pages <= resume_threshold { Self::send_signal(para, ChannelSignal::Resume); suspended_channels.remove(¶); >::put(suspended_channels); - } else if !suspended && fp.pages >= suspend_threshold { + } else if !suspended && fp.ready_pages >= suspend_threshold { log::warn!("XCMP queue for sibling {:?} is full; suspending channel.", para); Self::send_signal(para, ChannelSignal::Suspend); diff --git a/cumulus/pallets/xcmp-queue/src/mock.rs b/cumulus/pallets/xcmp-queue/src/mock.rs index 08ab58ce816..1fb88cafd93 100644 --- a/cumulus/pallets/xcmp-queue/src/mock.rs +++ b/cumulus/pallets/xcmp-queue/src/mock.rs @@ -247,6 +247,7 @@ impl> EnqueueMessage for EnqueueToLocalStorage } } footprint.pages = footprint.storage.size as u32 / 16; // Number does not matter + footprint.ready_pages = footprint.pages; footprint } } diff --git a/prdoc/pr_2393.prdoc b/prdoc/pr_2393.prdoc new file mode 100644 index 00000000000..708d017fafd --- /dev/null +++ b/prdoc/pr_2393.prdoc @@ -0,0 +1,16 @@ +title: "[XCMP] Use the number of 'ready' pages in XCMP suspend logic" + +doc: + - audience: Runtime Dev + description: | + Semantics of the suspension logic in the XCMP queue pallet change from using the number of + total pages to the number of 'ready' pages. The number of ready pages is now also exposed by + the `MessageQueue` pallet to downstream via the queue `footprint`. + +crates: + - name: cumulus-pallet-xcmp-queue + bump: patch + - name: pallet-message-queue + bump: patch + - name: frame-support + bump: major diff --git a/substrate/frame/message-queue/src/integration_test.rs b/substrate/frame/message-queue/src/integration_test.rs index cc3da6ebdc6..ce8eb80805a 100644 --- a/substrate/frame/message-queue/src/integration_test.rs +++ b/substrate/frame/message-queue/src/integration_test.rs @@ -330,6 +330,11 @@ fn process_some_messages(num_msgs: u32) { ServiceWeight::set(Some(weight)); let consumed = next_block(); + for origin in BookStateFor::::iter_keys() { + let fp = MessageQueue::footprint(origin); + assert_eq!(fp.pages, fp.ready_pages); + } + assert_eq!(consumed, weight, "\n{}", MessageQueue::debug_info()); assert_eq!(NumMessagesProcessed::take(), num_msgs as usize); } diff --git a/substrate/frame/message-queue/src/lib.rs b/substrate/frame/message-queue/src/lib.rs index 07eb0041985..61028057394 100644 --- a/substrate/frame/message-queue/src/lib.rs +++ b/substrate/frame/message-queue/src/lib.rs @@ -208,8 +208,9 @@ use frame_support::{ defensive, pallet_prelude::*, traits::{ - Defensive, DefensiveTruncateFrom, EnqueueMessage, ExecuteOverweightError, Footprint, - ProcessMessage, ProcessMessageError, QueueFootprint, QueuePausedQuery, ServiceQueues, + Defensive, DefensiveSaturating, DefensiveTruncateFrom, EnqueueMessage, + ExecuteOverweightError, Footprint, ProcessMessage, ProcessMessageError, QueueFootprint, + QueuePausedQuery, ServiceQueues, }, BoundedSlice, CloneNoBound, DefaultNoBound, }; @@ -442,6 +443,7 @@ impl From> for QueueFootprint { fn from(book: BookState) -> Self { QueueFootprint { pages: book.count, + ready_pages: book.end.defensive_saturating_sub(book.begin), storage: Footprint { count: book.message_count, size: book.size }, } } @@ -1281,6 +1283,9 @@ impl Pallet { ensure!(book.message_count < 1 << 30, "Likely overflow or corruption"); ensure!(book.size < 1 << 30, "Likely overflow or corruption"); ensure!(book.count < 1 << 30, "Likely overflow or corruption"); + + let fp: QueueFootprint = book.into(); + ensure!(fp.ready_pages <= fp.pages, "There cannot be more ready than total pages"); } //loop around this origin diff --git a/substrate/frame/message-queue/src/mock.rs b/substrate/frame/message-queue/src/mock.rs index a46fa31df3e..d176a981ca8 100644 --- a/substrate/frame/message-queue/src/mock.rs +++ b/substrate/frame/message-queue/src/mock.rs @@ -355,8 +355,8 @@ pub fn num_overweight_enqueued_events() -> u32 { .count() as u32 } -pub fn fp(pages: u32, count: u64, size: u64) -> QueueFootprint { - QueueFootprint { storage: Footprint { count, size }, pages } +pub fn fp(pages: u32, ready_pages: u32, count: u64, size: u64) -> QueueFootprint { + QueueFootprint { storage: Footprint { count, size }, pages, ready_pages } } /// A random seed that can be overwritten with `MQ_SEED`. diff --git a/substrate/frame/message-queue/src/tests.rs b/substrate/frame/message-queue/src/tests.rs index 86a8b79fe8b..dbef94b3b10 100644 --- a/substrate/frame/message-queue/src/tests.rs +++ b/substrate/frame/message-queue/src/tests.rs @@ -1064,13 +1064,13 @@ fn footprint_num_pages_works() { MessageQueue::enqueue_message(msg("weight=2"), Here); MessageQueue::enqueue_message(msg("weight=3"), Here); - assert_eq!(MessageQueue::footprint(Here), fp(2, 2, 16)); + assert_eq!(MessageQueue::footprint(Here), fp(2, 2, 2, 16)); // Mark the messages as overweight. assert_eq!(MessageQueue::service_queues(1.into_weight()), 0.into_weight()); assert_eq!(System::events().len(), 2); - // Overweight does not change the footprint. - assert_eq!(MessageQueue::footprint(Here), fp(2, 2, 16)); + // `ready_pages` decreases but `page` count does not. + assert_eq!(MessageQueue::footprint(Here), fp(2, 0, 2, 16)); // Now execute the second message. assert_eq!( @@ -1078,7 +1078,7 @@ fn footprint_num_pages_works() { .unwrap(), 3.into_weight() ); - assert_eq!(MessageQueue::footprint(Here), fp(1, 1, 8)); + assert_eq!(MessageQueue::footprint(Here), fp(1, 0, 1, 8)); // And the first one: assert_eq!( ::execute_overweight(2.into_weight(), (Here, 0, 0)) @@ -1086,6 +1086,11 @@ fn footprint_num_pages_works() { 2.into_weight() ); assert_eq!(MessageQueue::footprint(Here), Default::default()); + assert_eq!(MessageQueue::footprint(Here), fp(0, 0, 0, 0)); + + // `ready_pages` and normal `pages` increases again: + MessageQueue::enqueue_message(msg("weight=3"), Here); + assert_eq!(MessageQueue::footprint(Here), fp(1, 1, 1, 8)); }) } diff --git a/substrate/frame/support/src/traits/messages.rs b/substrate/frame/support/src/traits/messages.rs index 995ac4f7179..f3d893bcc1d 100644 --- a/substrate/frame/support/src/traits/messages.rs +++ b/substrate/frame/support/src/traits/messages.rs @@ -123,6 +123,8 @@ impl ServiceQueues for NoopServiceQueues { pub struct QueueFootprint { /// The number of pages in the queue (including overweight pages). pub pages: u32, + /// The number of pages that are ready (not yet processed and also not overweight). + pub ready_pages: u32, /// The storage footprint of the queue (including overweight messages). pub storage: Footprint, } -- GitLab From 8f8297e9debe79139e3a41be8b54a5fcd603f783 Mon Sep 17 00:00:00 2001 From: Sergej Sakac <73715684+Szegoo@users.noreply.github.com> Date: Wed, 6 Mar 2024 01:49:18 +0100 Subject: [PATCH 074/188] Permissioned contract deployment (#3377) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes: #3196 --------- Co-authored-by: Alexander Theißen Co-authored-by: PG Herveou --- .../contracts-rococo/src/contracts.rs | 3 + prdoc/pr_3377.prdoc | 14 ++ substrate/bin/node/runtime/src/lib.rs | 2 + .../src/parachain/contracts_config.rs | 4 +- substrate/frame/contracts/src/lib.rs | 35 ++++- substrate/frame/contracts/src/tests.rs | 131 +++++++++++++++++- 6 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 prdoc/pr_3377.prdoc diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs index 681b95ce6a5..171ac6a9528 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/contracts.rs @@ -21,6 +21,7 @@ use frame_support::{ parameter_types, traits::{ConstBool, ConstU32, Nothing}, }; +use frame_system::EnsureSigned; use pallet_contracts::{ weights::SubstrateWeight, Config, DebugInfo, DefaultAddressGenerator, Frame, Schedule, }; @@ -65,6 +66,8 @@ impl Config for Runtime { type MaxCodeLen = ConstU32<{ 123 * 1024 }>; type MaxStorageKeyLen = ConstU32<128>; type UnsafeUnstableInterface = ConstBool; + type UploadOrigin = EnsureSigned; + type InstantiateOrigin = EnsureSigned; type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; type MaxDelegateDependencies = ConstU32<32>; type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; diff --git a/prdoc/pr_3377.prdoc b/prdoc/pr_3377.prdoc new file mode 100644 index 00000000000..8e5b3935512 --- /dev/null +++ b/prdoc/pr_3377.prdoc @@ -0,0 +1,14 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Permissioned contract deployment + +doc: + - audience: Runtime Dev + description: | + This PR introduces two new config types that specify the origins allowed to + upload and instantiate contract code. However, this check is not enforced when + a contract instantiates another contract. + +crates: +- name: pallet-contracts diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index f4615802515..18ce13cff80 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1365,6 +1365,8 @@ impl pallet_contracts::Config for Runtime { type MaxCodeLen = ConstU32<{ 123 * 1024 }>; type MaxStorageKeyLen = ConstU32<128>; type UnsafeUnstableInterface = ConstBool; + type UploadOrigin = EnsureSigned; + type InstantiateOrigin = EnsureSigned; type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; type RuntimeHoldReason = RuntimeHoldReason; #[cfg(not(feature = "runtime-benchmarks"))] diff --git a/substrate/frame/contracts/mock-network/src/parachain/contracts_config.rs b/substrate/frame/contracts/mock-network/src/parachain/contracts_config.rs index 3f26c6f372e..3c06131dd60 100644 --- a/substrate/frame/contracts/mock-network/src/parachain/contracts_config.rs +++ b/substrate/frame/contracts/mock-network/src/parachain/contracts_config.rs @@ -25,7 +25,7 @@ use frame_support::{ traits::{ConstBool, ConstU32, Contains, Randomness}, weights::Weight, }; -use frame_system::pallet_prelude::BlockNumberFor; +use frame_system::{pallet_prelude::BlockNumberFor, EnsureSigned}; use pallet_xcm::BalanceOf; use sp_runtime::{traits::Convert, Perbill}; @@ -90,6 +90,8 @@ impl pallet_contracts::Config for Runtime { type Schedule = Schedule; type Time = super::Timestamp; type UnsafeUnstableInterface = ConstBool; + type UploadOrigin = EnsureSigned; + type InstantiateOrigin = EnsureSigned; type WeightInfo = (); type WeightPrice = Self; type Debug = (); diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs index 32d789a458f..f941f152ffe 100644 --- a/substrate/frame/contracts/src/lib.rs +++ b/substrate/frame/contracts/src/lib.rs @@ -379,6 +379,24 @@ pub mod pallet { #[pallet::constant] type MaxDebugBufferLen: Get; + /// Origin allowed to upload code. + /// + /// By default, it is safe to set this to `EnsureSigned`, allowing anyone to upload contract + /// code. + type UploadOrigin: EnsureOrigin; + + /// Origin allowed to instantiate code. + /// + /// # Note + /// + /// This is not enforced when a contract instantiates another contract. The + /// [`Self::UploadOrigin`] should make sure that no code is deployed that does unwanted + /// instantiations. + /// + /// By default, it is safe to set this to `EnsureSigned`, allowing anyone to instantiate + /// contract code. + type InstantiateOrigin: EnsureOrigin; + /// Overarching hold reason. type RuntimeHoldReason: From; @@ -636,7 +654,7 @@ pub mod pallet { determinism: Determinism, ) -> DispatchResult { Migration::::ensure_migrated()?; - let origin = ensure_signed(origin)?; + let origin = T::UploadOrigin::ensure_origin(origin)?; Self::bare_upload_code(origin, code, storage_deposit_limit.map(Into::into), determinism) .map(|_| ()) } @@ -785,11 +803,17 @@ pub mod pallet { salt: Vec, ) -> DispatchResultWithPostInfo { Migration::::ensure_migrated()?; - let origin = ensure_signed(origin)?; + + // These two origins will usually be the same; however, we treat them as separate since + // it is possible for the `Success` value of `UploadOrigin` and `InstantiateOrigin` to + // differ. + let upload_origin = T::UploadOrigin::ensure_origin(origin.clone())?; + let instantiate_origin = T::InstantiateOrigin::ensure_origin(origin)?; + let code_len = code.len() as u32; let (module, upload_deposit) = Self::try_upload_code( - origin.clone(), + upload_origin, code, storage_deposit_limit.clone().map(Into::into), Determinism::Enforced, @@ -803,7 +827,7 @@ pub mod pallet { let data_len = data.len() as u32; let salt_len = salt.len() as u32; let common = CommonInput { - origin: Origin::from_account_id(origin), + origin: Origin::from_account_id(instantiate_origin), value, data, gas_limit, @@ -844,10 +868,11 @@ pub mod pallet { salt: Vec, ) -> DispatchResultWithPostInfo { Migration::::ensure_migrated()?; + let origin = T::InstantiateOrigin::ensure_origin(origin)?; let data_len = data.len() as u32; let salt_len = salt.len() as u32; let common = CommonInput { - origin: Origin::from_runtime_origin(origin)?, + origin: Origin::from_account_id(origin), value, data, gas_limit, diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index 2d1c5b315a3..2f8f6d4a437 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -45,6 +45,7 @@ use frame_support::{ assert_err, assert_err_ignore_postinfo, assert_err_with_weight, assert_noop, assert_ok, derive_impl, dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo}, + pallet_prelude::EnsureOrigin, parameter_types, storage::child, traits::{ @@ -434,6 +435,33 @@ impl Contains for TestFilter { } } +parameter_types! { + pub static UploadAccount: Option<::AccountId> = None; + pub static InstantiateAccount: Option<::AccountId> = None; +} + +pub struct EnsureAccount(sp_std::marker::PhantomData<(T, A)>); +impl>>> + EnsureOrigin<::RuntimeOrigin> for EnsureAccount +where + ::AccountId: From, +{ + type Success = T::AccountId; + + fn try_origin(o: T::RuntimeOrigin) -> Result { + let who = as EnsureOrigin<_>>::try_origin(o.clone())?; + if matches!(A::get(), Some(a) if who != a) { + return Err(o) + } + + Ok(who) + } + + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + Err(()) + } +} parameter_types! { pub static UnstableInterface: bool = true; } @@ -458,6 +486,8 @@ impl Config for Test { type MaxCodeLen = ConstU32<{ 123 * 1024 }>; type MaxStorageKeyLen = ConstU32<128>; type UnsafeUnstableInterface = UnstableInterface; + type UploadOrigin = EnsureAccount; + type InstantiateOrigin = EnsureAccount; type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; type RuntimeHoldReason = RuntimeHoldReason; type Migrations = crate::migration::codegen::BenchMigrations; @@ -5924,7 +5954,106 @@ fn root_cannot_instantiate() { vec![], vec![], ), - DispatchError::RootNotAllowed + DispatchError::BadOrigin + ); + }); +} + +#[test] +fn only_upload_origin_can_upload() { + let (wasm, _) = compile_module::("dummy").unwrap(); + UploadAccount::set(Some(ALICE)); + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::set_balance(&ALICE, 1_000_000); + let _ = Balances::set_balance(&BOB, 1_000_000); + + assert_err!( + Contracts::upload_code( + RuntimeOrigin::root(), + wasm.clone(), + None, + Determinism::Enforced, + ), + DispatchError::BadOrigin + ); + + assert_err!( + Contracts::upload_code( + RuntimeOrigin::signed(BOB), + wasm.clone(), + None, + Determinism::Enforced, + ), + DispatchError::BadOrigin + ); + + // Only alice is allowed to upload contract code. + assert_ok!(Contracts::upload_code( + RuntimeOrigin::signed(ALICE), + wasm.clone(), + None, + Determinism::Enforced, + )); + }); +} + +#[test] +fn only_instantiation_origin_can_instantiate() { + let (code, code_hash) = compile_module::("dummy").unwrap(); + InstantiateAccount::set(Some(ALICE)); + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::set_balance(&ALICE, 1_000_000); + let _ = Balances::set_balance(&BOB, 1_000_000); + + assert_err_ignore_postinfo!( + Contracts::instantiate_with_code( + RuntimeOrigin::root(), + 0, + GAS_LIMIT, + None, + code.clone(), + vec![], + vec![], + ), + DispatchError::BadOrigin + ); + + assert_err_ignore_postinfo!( + Contracts::instantiate_with_code( + RuntimeOrigin::signed(BOB), + 0, + GAS_LIMIT, + None, + code.clone(), + vec![], + vec![], + ), + DispatchError::BadOrigin + ); + + // Only Alice can instantiate + assert_ok!(Contracts::instantiate_with_code( + RuntimeOrigin::signed(ALICE), + 0, + GAS_LIMIT, + None, + code, + vec![], + vec![], + ),); + + // Bob cannot instantiate with either `instantiate_with_code` or `instantiate`. + assert_err_ignore_postinfo!( + Contracts::instantiate( + RuntimeOrigin::signed(BOB), + 0, + GAS_LIMIT, + None, + code_hash, + vec![], + vec![], + ), + DispatchError::BadOrigin ); }); } -- GitLab From 475e7a147676a4e7a9d255ddc7969dd35ea22882 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Wed, 6 Mar 2024 07:47:33 +0100 Subject: [PATCH 075/188] Contracts: Charge min amount when processing deletion queue (#2934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Theißen --- substrate/frame/contracts/src/storage.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substrate/frame/contracts/src/storage.rs b/substrate/frame/contracts/src/storage.rs index 3304166607d..52c5150ca21 100644 --- a/substrate/frame/contracts/src/storage.rs +++ b/substrate/frame/contracts/src/storage.rs @@ -322,7 +322,8 @@ impl ContractInfo { KillStorageResult::SomeRemaining(_) => return weight_limit, KillStorageResult::AllRemoved(keys_removed) => { entry.remove(); - remaining_key_budget = remaining_key_budget.saturating_sub(keys_removed); + // charge at least one key even if none were removed. + remaining_key_budget = remaining_key_budget.saturating_sub(keys_removed.max(1)); }, }; } -- GitLab From f5bf4654e0b9cd089d1ca38ff3d692543ed555d3 Mon Sep 17 00:00:00 2001 From: Usama Ali Date: Wed, 6 Mar 2024 18:18:56 +0500 Subject: [PATCH 076/188] FIX: Make `sc-network-sync` types Public (#3586) This PR makes `sc-network-sync` types public following [this](https://github.com/paritytech/polkadot-sdk/issues/3556) issue. Fixes #3556 --- substrate/client/network/sync/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/client/network/sync/src/lib.rs b/substrate/client/network/sync/src/lib.rs index e23a23e735d..9f6c0f45d08 100644 --- a/substrate/client/network/sync/src/lib.rs +++ b/substrate/client/network/sync/src/lib.rs @@ -28,7 +28,7 @@ mod justification_requests; mod pending_responses; mod request_metrics; mod schema; -mod types; +pub mod types; pub mod block_relay_protocol; pub mod block_request_handler; -- GitLab From adce09057dc3853a62af8b399fe046c60a2777ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Wed, 6 Mar 2024 14:54:36 +0000 Subject: [PATCH 077/188] sc-manual-seal: don't spawn threads in tests (#3595) Hopefully helps with test flakiness. --- .../client/consensus/manual-seal/src/lib.rs | 68 ++++++++----------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/substrate/client/consensus/manual-seal/src/lib.rs b/substrate/client/consensus/manual-seal/src/lib.rs index e3608f6716c..f04c0d42d60 100644 --- a/substrate/client/consensus/manual-seal/src/lib.rs +++ b/substrate/client/consensus/manual-seal/src/lib.rs @@ -429,7 +429,9 @@ mod tests { sender, } }); - let future = run_manual_seal(ManualSealParams { + + // spawn the background authorship task + tokio::spawn(run_manual_seal(ManualSealParams { block_import: client.clone(), env, client: client.clone(), @@ -438,12 +440,8 @@ mod tests { select_chain, create_inherent_data_providers: |_, _| async { Ok(()) }, consensus_data_provider: None, - }); - std::thread::spawn(|| { - let rt = tokio::runtime::Runtime::new().unwrap(); - // spawn the background authorship task - rt.block_on(future); - }); + })); + // submit a transaction to pool. let result = pool.submit_one(genesis_hash, SOURCE, uxt(Alice, 0)).await; // assert that it was successfully imported @@ -507,7 +505,8 @@ mod tests { } }); - let future_instant_seal = run_manual_seal(ManualSealParams { + // spawn the background authorship task + tokio::spawn(run_manual_seal(ManualSealParams { block_import: client.clone(), commands_stream, env, @@ -516,24 +515,16 @@ mod tests { select_chain, create_inherent_data_providers: |_, _| async { Ok(()) }, consensus_data_provider: None, - }); - std::thread::spawn(|| { - let rt = tokio::runtime::Runtime::new().unwrap(); - // spawn the background authorship task - rt.block_on(future_instant_seal); - }); + })); let delay_sec = 5; - let future_delayed_finalize = run_delayed_finalize(DelayedFinalizeParams { + + // spawn the background finality task + tokio::spawn(run_delayed_finalize(DelayedFinalizeParams { client: client.clone(), delay_sec, spawn_handle: spawner, - }); - std::thread::spawn(|| { - let rt = tokio::runtime::Runtime::new().unwrap(); - // spawn the background authorship task - rt.block_on(future_delayed_finalize); - }); + })); let mut finality_stream = client.finality_notification_stream(); // submit a transaction to pool. @@ -589,7 +580,9 @@ mod tests { // this test checks that blocks are created as soon as an engine command is sent over the // stream. let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024); - let future = run_manual_seal(ManualSealParams { + + // spawn the background authorship task + tokio::spawn(run_manual_seal(ManualSealParams { block_import: client.clone(), env, client: client.clone(), @@ -598,12 +591,8 @@ mod tests { select_chain, consensus_data_provider: None, create_inherent_data_providers: |_, _| async { Ok(()) }, - }); - std::thread::spawn(|| { - let rt = tokio::runtime::Runtime::new().unwrap(); - // spawn the background authorship task - rt.block_on(future); - }); + })); + // submit a transaction to pool. let result = pool.submit_one(genesis_hash, SOURCE, uxt(Alice, 0)).await; // assert that it was successfully imported @@ -675,7 +664,9 @@ mod tests { // this test checks that blocks are created as soon as an engine command is sent over the // stream. let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024); - let future = run_manual_seal(ManualSealParams { + + // spawn the background authorship task + tokio::spawn(run_manual_seal(ManualSealParams { block_import: client.clone(), env, client: client.clone(), @@ -684,12 +675,8 @@ mod tests { select_chain, consensus_data_provider: None, create_inherent_data_providers: |_, _| async { Ok(()) }, - }); - std::thread::spawn(|| { - let rt = tokio::runtime::Runtime::new().unwrap(); - // spawn the background authorship task - rt.block_on(future); - }); + })); + // submit a transaction to pool. let result = pool.submit_one(genesis_hash, SOURCE, uxt(Alice, 0)).await; // assert that it was successfully imported @@ -781,7 +768,9 @@ mod tests { let env = ProposerFactory::new(spawner.clone(), client.clone(), pool.clone(), None, None); let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024); - let future = run_manual_seal(ManualSealParams { + + // spawn the background authorship task + tokio::spawn(run_manual_seal(ManualSealParams { block_import: client.clone(), env, client: client.clone(), @@ -791,11 +780,8 @@ mod tests { // use a provider that pushes some post digest data consensus_data_provider: Some(Box::new(TestDigestProvider { _client: client.clone() })), create_inherent_data_providers: |_, _| async { Ok(()) }, - }); - std::thread::spawn(|| { - let rt = tokio::runtime::Runtime::new().unwrap(); - rt.block_on(future); - }); + })); + let (tx, rx) = futures::channel::oneshot::channel(); sink.send(EngineCommand::SealNewBlock { parent_hash: None, -- GitLab From f2f4b154d7641ef3c237a0d7df4b77280b5a81d0 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Wed, 6 Mar 2024 17:52:30 +0200 Subject: [PATCH 078/188] chainHead/follow: Provide multiple block hashes to the initialized event (#3445) This PR extends the Initialized event of the chainHead_follow subscription. Now, the event provides multiple finalized block hashes. This information allows clients that are disconnected, and that want to reconnect, to not lose information about the state of the chain. At the moment, the spec encourages servers to provide at least 1 minute of finalized blocks (~10 blocks). The users are responsible for unpinning these blocks at a later time. This PR tries to report at least 1 finalized block and at most 16 blocks, if they are available. Closes: https://github.com/paritytech/polkadot-sdk/issues/3432 cc @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile Co-authored-by: Niklas Adolfsson --- .../src/chain_head/chain_head_follow.rs | 63 +++++++++++++++---- .../rpc-spec-v2/src/chain_head/event.rs | 16 ++--- .../rpc-spec-v2/src/chain_head/tests.rs | 22 ++++--- 3 files changed, 73 insertions(+), 28 deletions(-) diff --git a/substrate/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs b/substrate/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs index e94374aebd9..afa99f3aa16 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/chain_head_follow.rs @@ -42,7 +42,14 @@ use sp_blockchain::{ Backend as BlockChainBackend, Error as BlockChainError, HeaderBackend, HeaderMetadata, Info, }; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use std::{collections::HashSet, sync::Arc}; +use std::{ + collections::{HashSet, VecDeque}, + sync::Arc, +}; + +/// The maximum number of finalized blocks provided by the +/// `Initialized` event. +const MAX_FINALIZED_BLOCKS: usize = 16; use super::subscription::InsertedSubscriptionData; @@ -95,6 +102,8 @@ struct InitialBlocks { /// /// It is a tuple of (block hash, parent hash). finalized_block_descendants: Vec<(Block::Hash, Block::Hash)>, + /// Hashes of the last finalized blocks + finalized_block_hashes: VecDeque, /// Blocks that should not be reported as pruned by the `Finalized` event. /// /// Substrate database will perform the pruning of height N at @@ -178,13 +187,14 @@ where } /// Get the in-memory blocks of the client, starting from the provided finalized hash. + /// + /// The reported blocks are pinned by this function. fn get_init_blocks_with_forks( &self, - startup_point: &StartupPoint, + finalized: Block::Hash, ) -> Result, SubscriptionManagementError> { let blockchain = self.backend.blockchain(); let leaves = blockchain.leaves()?; - let finalized = startup_point.finalized_hash; let mut pruned_forks = HashSet::new(); let mut finalized_block_descendants = Vec::new(); let mut unique_descendants = HashSet::new(); @@ -198,17 +208,47 @@ where // Ensure a `NewBlock` event is generated for all children of the // finalized block. Describe the tree route as (child_node, parent_node) // Note: the order of elements matters here. - let parents = std::iter::once(finalized).chain(blocks.clone()); + let mut parent = finalized; + for child in blocks { + let pair = (child, parent); - for pair in blocks.zip(parents) { if unique_descendants.insert(pair) { + // The finalized block is pinned below. + self.sub_handle.pin_block(&self.sub_id, child)?; finalized_block_descendants.push(pair); } + + parent = child; } } } - Ok(InitialBlocks { finalized_block_descendants, pruned_forks }) + let mut current_block = finalized; + // The header of the finalized block must not be pruned. + let Some(header) = blockchain.header(current_block)? else { + return Err(SubscriptionManagementError::BlockHeaderAbsent); + }; + + // Report at most `MAX_FINALIZED_BLOCKS`. Note: The node might not have that many blocks. + let mut finalized_block_hashes = VecDeque::with_capacity(MAX_FINALIZED_BLOCKS); + + // Pin the finalized block. + self.sub_handle.pin_block(&self.sub_id, current_block)?; + finalized_block_hashes.push_front(current_block); + current_block = *header.parent_hash(); + + for _ in 0..MAX_FINALIZED_BLOCKS - 1 { + let Ok(Some(header)) = blockchain.header(current_block) else { break }; + // Block cannot be reported if pinning fails. + if self.sub_handle.pin_block(&self.sub_id, current_block).is_err() { + break + }; + + finalized_block_hashes.push_front(current_block); + current_block = *header.parent_hash(); + } + + Ok(InitialBlocks { finalized_block_descendants, finalized_block_hashes, pruned_forks }) } /// Generate the initial events reported by the RPC `follow` method. @@ -220,18 +260,17 @@ where startup_point: &StartupPoint, ) -> Result<(Vec>, HashSet), SubscriptionManagementError> { - let init = self.get_init_blocks_with_forks(startup_point)?; + let init = self.get_init_blocks_with_forks(startup_point.finalized_hash)?; + // The initialized event is the first one sent. let initial_blocks = init.finalized_block_descendants; + let finalized_block_hashes = init.finalized_block_hashes; - // The initialized event is the first one sent. let finalized_block_hash = startup_point.finalized_hash; - self.sub_handle.pin_block(&self.sub_id, finalized_block_hash)?; - let finalized_block_runtime = self.generate_runtime_event(finalized_block_hash, None); let initialized_event = FollowEvent::Initialized(Initialized { - finalized_block_hash, + finalized_block_hashes: finalized_block_hashes.into(), finalized_block_runtime, with_runtime: self.with_runtime, }); @@ -240,8 +279,6 @@ where finalized_block_descendants.push(initialized_event); for (child, parent) in initial_blocks.into_iter() { - self.sub_handle.pin_block(&self.sub_id, child)?; - let new_runtime = self.generate_runtime_event(child, Some(parent)); let event = FollowEvent::NewBlock(NewBlock { diff --git a/substrate/client/rpc-spec-v2/src/chain_head/event.rs b/substrate/client/rpc-spec-v2/src/chain_head/event.rs index 560ab87eab4..e0c804d16eb 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/event.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/event.rs @@ -111,8 +111,8 @@ impl From for RuntimeEvent { #[derive(Debug, Clone, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Initialized { - /// The hash of the latest finalized block. - pub finalized_block_hash: Hash, + /// The hash of the lastest finalized blocks. + pub finalized_block_hashes: Vec, /// The runtime version of the finalized block. /// /// # Note @@ -135,12 +135,12 @@ impl Serialize for Initialized { { if self.with_runtime { let mut state = serializer.serialize_struct("Initialized", 2)?; - state.serialize_field("finalizedBlockHash", &self.finalized_block_hash)?; + state.serialize_field("finalizedBlockHashes", &self.finalized_block_hashes)?; state.serialize_field("finalizedBlockRuntime", &self.finalized_block_runtime)?; state.end() } else { let mut state = serializer.serialize_struct("Initialized", 1)?; - state.serialize_field("finalizedBlockHash", &self.finalized_block_hash)?; + state.serialize_field("finalizedBlockHashes", &self.finalized_block_hashes)?; state.end() } } @@ -348,13 +348,13 @@ mod tests { fn follow_initialized_event_no_updates() { // Runtime flag is false. let event: FollowEvent = FollowEvent::Initialized(Initialized { - finalized_block_hash: "0x1".into(), + finalized_block_hashes: vec!["0x1".into()], finalized_block_runtime: None, with_runtime: false, }); let ser = serde_json::to_string(&event).unwrap(); - let exp = r#"{"event":"initialized","finalizedBlockHash":"0x1"}"#; + let exp = r#"{"event":"initialized","finalizedBlockHashes":["0x1"]}"#; assert_eq!(ser, exp); let event_dec: FollowEvent = serde_json::from_str(exp).unwrap(); @@ -373,7 +373,7 @@ mod tests { let runtime_event = RuntimeEvent::Valid(RuntimeVersionEvent { spec: runtime.into() }); let mut initialized = Initialized { - finalized_block_hash: "0x1".into(), + finalized_block_hashes: vec!["0x1".into()], finalized_block_runtime: Some(runtime_event), with_runtime: true, }; @@ -381,7 +381,7 @@ mod tests { let ser = serde_json::to_string(&event).unwrap(); let exp = concat!( - r#"{"event":"initialized","finalizedBlockHash":"0x1","#, + r#"{"event":"initialized","finalizedBlockHashes":["0x1"],"#, r#""finalizedBlockRuntime":{"type":"valid","spec":{"specName":"ABC","implName":"Impl","#, r#""specVersion":1,"implVersion":0,"apis":{},"transactionVersion":0}}}"#, ); diff --git a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs index 89d8c4ce271..4d9dfb24e0a 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs @@ -173,7 +173,7 @@ async fn follow_subscription_produces_blocks() { // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Initialized(Initialized { - finalized_block_hash: format!("{:?}", finalized_hash), + finalized_block_hashes: vec![format!("{:?}", finalized_hash)], finalized_block_runtime: None, with_runtime: false, }); @@ -255,7 +255,7 @@ async fn follow_with_runtime() { Some(RuntimeEvent::Valid(RuntimeVersionEvent { spec: runtime.clone().into() })); // Runtime must always be reported with the first event. let expected = FollowEvent::Initialized(Initialized { - finalized_block_hash: format!("{:?}", finalized_hash), + finalized_block_hashes: vec![format!("{:?}", finalized_hash)], finalized_block_runtime, with_runtime: false, }); @@ -1344,7 +1344,7 @@ async fn follow_generates_initial_blocks() { // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Initialized(Initialized { - finalized_block_hash: format!("{:?}", finalized_hash), + finalized_block_hashes: vec![format!("{:?}", finalized_hash)], finalized_block_runtime: None, with_runtime: false, }); @@ -1896,7 +1896,7 @@ async fn follow_prune_best_block() { // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Initialized(Initialized { - finalized_block_hash: format!("{:?}", finalized_hash), + finalized_block_hashes: vec![format!("{:?}", finalized_hash)], finalized_block_runtime: None, with_runtime: false, }); @@ -2081,6 +2081,7 @@ async fn follow_forks_pruned_block() { // ^^^ finalized // -> block 1 -> block 2_f -> block 3_f // + let finalized_hash = client.info().finalized_hash; let block_1 = BlockBuilderBuilder::new(&*client) .on_parent_block(client.chain_info().genesis_hash) @@ -2090,6 +2091,7 @@ async fn follow_forks_pruned_block() { .build() .unwrap() .block; + let block_1_hash = block_1.header.hash(); client.import(BlockOrigin::Own, block_1.clone()).await.unwrap(); let block_2 = BlockBuilderBuilder::new(&*client) @@ -2100,6 +2102,7 @@ async fn follow_forks_pruned_block() { .build() .unwrap() .block; + let block_2_hash = block_2.header.hash(); client.import(BlockOrigin::Own, block_2.clone()).await.unwrap(); let block_3 = BlockBuilderBuilder::new(&*client) @@ -2156,7 +2159,12 @@ async fn follow_forks_pruned_block() { // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Initialized(Initialized { - finalized_block_hash: format!("{:?}", block_3_hash), + finalized_block_hashes: vec![ + format!("{:?}", finalized_hash), + format!("{:?}", block_1_hash), + format!("{:?}", block_2_hash), + format!("{:?}", block_3_hash), + ], finalized_block_runtime: None, with_runtime: false, }); @@ -2310,7 +2318,7 @@ async fn follow_report_multiple_pruned_block() { // Initialized must always be reported first. let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Initialized(Initialized { - finalized_block_hash: format!("{:?}", finalized_hash), + finalized_block_hashes: vec![format!("{:?}", finalized_hash)], finalized_block_runtime: None, with_runtime: false, }); @@ -2632,7 +2640,7 @@ async fn follow_finalized_before_new_block() { let finalized_hash = client.info().finalized_hash; let event: FollowEvent = get_next_event(&mut sub).await; let expected = FollowEvent::Initialized(Initialized { - finalized_block_hash: format!("{:?}", finalized_hash), + finalized_block_hashes: vec![format!("{:?}", finalized_hash)], finalized_block_runtime: None, with_runtime: false, }); -- GitLab From 9952786e1b688109b1571248042d71b82bbe2256 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Wed, 6 Mar 2024 17:35:55 +0100 Subject: [PATCH 079/188] Contracts upload with Determinism::Enforced when possible (#3540) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cyrill Leutwiler Co-authored-by: command-bot <> Co-authored-by: Alexander Theißen --- prdoc/pr_3540.prdoc | 10 + .../frame/contracts/src/benchmarking/code.rs | 19 +- .../frame/contracts/src/benchmarking/mod.rs | 27 +- substrate/frame/contracts/src/lib.rs | 11 +- substrate/frame/contracts/src/tests.rs | 20 + substrate/frame/contracts/src/wasm/mod.rs | 5 + substrate/frame/contracts/src/wasm/prepare.rs | 25 +- substrate/frame/contracts/src/weights.rs | 1275 +++++++++-------- 8 files changed, 756 insertions(+), 636 deletions(-) create mode 100644 prdoc/pr_3540.prdoc diff --git a/prdoc/pr_3540.prdoc b/prdoc/pr_3540.prdoc new file mode 100644 index 00000000000..d0a91882b6b --- /dev/null +++ b/prdoc/pr_3540.prdoc @@ -0,0 +1,10 @@ +title: "[pallet-contracts] Only allow non-deterministic code to be uploaded with Determinism::Relaxed" + +doc: + - audience: Runtime Dev + description: | + The `upload_code` extrinsic, will now only allow non-deterministic code to be uploaded with the `Determinism::Relaxed` flag. + This prevent an attacker from uploading "deterministic" code with the `Determinism::Relaxed` flag, preventing the code to be instantiated for on-chain execution. + +crates: + - name: pallet-contracts diff --git a/substrate/frame/contracts/src/benchmarking/code.rs b/substrate/frame/contracts/src/benchmarking/code.rs index 644c2abf0a8..96ce11f8c41 100644 --- a/substrate/frame/contracts/src/benchmarking/code.rs +++ b/substrate/frame/contracts/src/benchmarking/code.rs @@ -26,7 +26,7 @@ use crate::Config; use frame_support::traits::Get; -use sp_runtime::traits::Hash; +use sp_runtime::{traits::Hash, Saturating}; use sp_std::{borrow::ToOwned, prelude::*}; use wasm_instrument::parity_wasm::{ builder, @@ -262,22 +262,25 @@ impl WasmModule { /// `instantiate_with_code` for different sizes of wasm modules. The generated module maximizes /// instrumentation runtime by nesting blocks as deeply as possible given the byte budget. /// `code_location`: Whether to place the code into `deploy` or `call`. - pub fn sized(target_bytes: u32, code_location: Location) -> Self { + pub fn sized(target_bytes: u32, code_location: Location, use_float: bool) -> Self { use self::elements::Instruction::{End, GetLocal, If, Return}; // Base size of a contract is 63 bytes and each expansion adds 6 bytes. // We do one expansion less to account for the code section and function body // size fields inside the binary wasm module representation which are leb128 encoded // and therefore grow in size when the contract grows. We are not allowed to overshoot // because of the maximum code size that is enforced by `instantiate_with_code`. - let expansions = (target_bytes.saturating_sub(63) / 6).saturating_sub(1); + let mut expansions = (target_bytes.saturating_sub(63) / 6).saturating_sub(1); const EXPANSION: [Instruction; 4] = [GetLocal(0), If(BlockType::NoResult), Return, End]; + let mut locals = vec![Local::new(1, ValueType::I32)]; + if use_float { + locals.push(Local::new(1, ValueType::F32)); + locals.push(Local::new(2, ValueType::F32)); + locals.push(Local::new(3, ValueType::F32)); + expansions.saturating_dec(); + } let mut module = ModuleDefinition { memory: Some(ImportedMemory::max::()), ..Default::default() }; - let body = Some(body::repeated_with_locals( - &[Local::new(1, ValueType::I32)], - expansions, - &EXPANSION, - )); + let body = Some(body::repeated_with_locals(&locals, expansions, &EXPANSION)); match code_location { Location::Call => module.call_body = body, Location::Deploy => module.deploy_body = body, diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 4b6ff63c6f5..2ecd56b412d 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -362,7 +362,7 @@ benchmarks! { call_with_code_per_byte { let c in 0 .. T::MaxCodeLen::get(); let instance = Contract::::with_caller( - whitelisted_caller(), WasmModule::sized(c, Location::Deploy), vec![], + whitelisted_caller(), WasmModule::sized(c, Location::Deploy, false), vec![], )?; let value = Pallet::::min_balance(); let origin = RawOrigin::Signed(instance.caller.clone()); @@ -389,7 +389,7 @@ benchmarks! { let value = Pallet::::min_balance(); let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); - let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call); + let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call, false); let origin = RawOrigin::Signed(caller.clone()); let addr = Contracts::::contract_address(&caller, &hash, &input, &salt); }: _(origin, value, Weight::MAX, None, code, input, salt) @@ -468,19 +468,36 @@ benchmarks! { // It creates a maximum number of metering blocks per byte. // `c`: Size of the code in bytes. #[pov_mode = Measured] - upload_code { + upload_code_determinism_enforced { let c in 0 .. T::MaxCodeLen::get(); let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); - let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call); + let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call, false); let origin = RawOrigin::Signed(caller.clone()); - }: _(origin, code, None, Determinism::Enforced) + }: upload_code(origin, code, None, Determinism::Enforced) verify { // uploading the code reserves some balance in the callers account assert!(T::Currency::total_balance_on_hold(&caller) > 0u32.into()); assert!(>::code_exists(&hash)); } + // Uploading code with [`Determinism::Relaxed`] should be more expensive than uploading code with [`Determinism::Enforced`], + // as we always try to save the code with [`Determinism::Enforced`] first. + #[pov_mode = Measured] + upload_code_determinism_relaxed { + let c in 0 .. T::MaxCodeLen::get(); + let caller = whitelisted_caller(); + T::Currency::set_balance(&caller, caller_funding::()); + let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call, true); + let origin = RawOrigin::Signed(caller.clone()); + }: upload_code(origin, code, None, Determinism::Relaxed) + verify { + assert!(T::Currency::total_balance_on_hold(&caller) > 0u32.into()); + assert!(>::code_exists(&hash)); + // Ensure that the benchmark follows the most expensive path, i.e., the code is saved with [`Determinism::Relaxed`] after trying to save it with [`Determinism::Enforced`]. + assert_eq!(CodeInfoOf::::get(&hash).unwrap().determinism(), Determinism::Relaxed); + } + // Removing code does not depend on the size of the contract because all the information // needed to verify the removal claim (refcount, owner) is stored in a separate storage // item (`CodeInfoOf`). diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs index f941f152ffe..0511bcf7f3f 100644 --- a/substrate/frame/contracts/src/lib.rs +++ b/substrate/frame/contracts/src/lib.rs @@ -645,8 +645,17 @@ pub mod pallet { /// To avoid this situation a constructor could employ access control so that it can /// only be instantiated by permissioned entities. The same is true when uploading /// through [`Self::instantiate_with_code`]. + /// + /// Use [`Determinism::Relaxed`] exclusively for non-deterministic code. If the uploaded + /// code is deterministic, specifying [`Determinism::Relaxed`] will be disregarded and + /// result in higher gas costs. #[pallet::call_index(3)] - #[pallet::weight(T::WeightInfo::upload_code(code.len() as u32))] + #[pallet::weight( + match determinism { + Determinism::Enforced => T::WeightInfo::upload_code_determinism_enforced(code.len() as u32), + Determinism::Relaxed => T::WeightInfo::upload_code_determinism_relaxed(code.len() as u32), + } + )] pub fn upload_code( origin: OriginFor, code: Vec, diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index 2f8f6d4a437..011b2b25b2b 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -5185,6 +5185,26 @@ fn deposit_limit_honors_min_leftover() { }); } +#[test] +fn upload_should_enforce_deterministic_mode_when_possible() { + let upload = |fixture, determinism| { + let (wasm, code_hash) = compile_module::(fixture).unwrap(); + ExtBuilder::default() + .build() + .execute_with(|| -> Result { + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + Contracts::bare_upload_code(ALICE, wasm, None, determinism)?; + let info = CodeInfoOf::::get(code_hash).unwrap(); + Ok(info.determinism()) + }) + }; + + assert_eq!(upload("dummy", Determinism::Enforced), Ok(Determinism::Enforced)); + assert_eq!(upload("dummy", Determinism::Relaxed), Ok(Determinism::Enforced)); + assert_eq!(upload("float_instruction", Determinism::Relaxed), Ok(Determinism::Relaxed)); + assert!(upload("float_instruction", Determinism::Enforced).is_err()); +} + #[test] fn cannot_instantiate_indeterministic_code() { let (wasm, code_hash) = compile_module::("float_instruction").unwrap(); diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs index 34b45cba5d2..87e92cd72e8 100644 --- a/substrate/frame/contracts/src/wasm/mod.rs +++ b/substrate/frame/contracts/src/wasm/mod.rs @@ -313,6 +313,11 @@ impl CodeInfo { } } + /// Returns the determinism of the module. + pub fn determinism(&self) -> Determinism { + self.determinism + } + /// Returns reference count of the module. pub fn refcount(&self) -> u64 { self.refcount diff --git a/substrate/frame/contracts/src/wasm/prepare.rs b/substrate/frame/contracts/src/wasm/prepare.rs index 5cdf5600fcd..5efea8c3a23 100644 --- a/substrate/frame/contracts/src/wasm/prepare.rs +++ b/substrate/frame/contracts/src/wasm/prepare.rs @@ -79,7 +79,10 @@ impl LoadedModule { } let engine = Engine::new(&config); - let module = Module::new(&engine, code).map_err(|_| "Can't load the module into wasmi!")?; + let module = Module::new(&engine, code).map_err(|err| { + log::debug!(target: LOG_TARGET, "Module creation failed: {:?}", err); + "Can't load the module into wasmi!" + })?; // Return a `LoadedModule` instance with // __valid__ module. @@ -220,7 +223,7 @@ impl LoadedModule { fn validate( code: &[u8], schedule: &Schedule, - determinism: Determinism, + determinism: &mut Determinism, ) -> Result<(), (DispatchError, &'static str)> where E: Environment<()>, @@ -229,7 +232,17 @@ where (|| { // We check that the module is generally valid, // and does not have restricted WebAssembly features, here. - let contract_module = LoadedModule::new::(code, determinism, None)?; + let contract_module = match *determinism { + Determinism::Relaxed => + if let Ok(module) = LoadedModule::new::(code, Determinism::Enforced, None) { + *determinism = Determinism::Enforced; + module + } else { + LoadedModule::new::(code, Determinism::Relaxed, None)? + }, + Determinism::Enforced => LoadedModule::new::(code, Determinism::Enforced, None)?, + }; + // The we check that module satisfies constraints the pallet puts on contracts. contract_module.scan_exports()?; contract_module.scan_imports::(schedule)?; @@ -252,7 +265,7 @@ where &code, (), schedule, - determinism, + *determinism, stack_limits, AllowDeprecatedInterface::No, ) @@ -276,13 +289,13 @@ pub fn prepare( code: CodeVec, schedule: &Schedule, owner: AccountIdOf, - determinism: Determinism, + mut determinism: Determinism, ) -> Result, (DispatchError, &'static str)> where E: Environment<()>, T: Config, { - validate::(code.as_ref(), schedule, determinism)?; + validate::(code.as_ref(), schedule, &mut determinism)?; // Calculate deposit for storing contract code and `code_info` in two different storage items. let code_len = code.len() as u32; diff --git a/substrate/frame/contracts/src/weights.rs b/substrate/frame/contracts/src/weights.rs index 47ca17c7d80..6e09120c141 100644 --- a/substrate/frame/contracts/src/weights.rs +++ b/substrate/frame/contracts/src/weights.rs @@ -18,27 +18,25 @@ //! Autogenerated weights for `pallet_contracts` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-p5qp1txx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_contracts -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/contracts/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_contracts +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/contracts/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -69,7 +67,8 @@ pub trait WeightInfo { fn instantiate_with_code(c: u32, i: u32, s: u32, ) -> Weight; fn instantiate(i: u32, s: u32, ) -> Weight; fn call() -> Weight; - fn upload_code(c: u32, ) -> Weight; + fn upload_code_determinism_enforced(c: u32, ) -> Weight; + fn upload_code_determinism_relaxed(c: u32, ) -> Weight; fn remove_code() -> Weight; fn set_code() -> Weight; fn seal_caller(r: u32, ) -> Weight; @@ -143,8 +142,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_103_000 picoseconds. - Weight::from_parts(2_260_000, 1627) + // Minimum execution time: 2_054_000 picoseconds. + Weight::from_parts(2_178_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -154,10 +153,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `452 + k * (69 ±0)` // Estimated: `442 + k * (70 ±0)` - // Minimum execution time: 12_173_000 picoseconds. - Weight::from_parts(12_515_000, 442) - // Standard Error: 1_033 - .saturating_add(Weight::from_parts(1_075_765, 0).saturating_mul(k.into())) + // Minimum execution time: 12_119_000 picoseconds. + Weight::from_parts(12_536_000, 442) + // Standard Error: 1_254 + .saturating_add(Weight::from_parts(1_161_885, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -171,10 +170,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_054_000 picoseconds. - Weight::from_parts(8_503_485, 6149) + // Minimum execution time: 8_146_000 picoseconds. + Weight::from_parts(8_560_745, 6149) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_184, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_182, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -187,8 +186,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 16_966_000 picoseconds. - Weight::from_parts(17_445_000, 6450) + // Minimum execution time: 16_183_000 picoseconds. + Weight::from_parts(16_825_000, 6450) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -201,10 +200,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_643_000 picoseconds. - Weight::from_parts(3_714_000, 3635) - // Standard Error: 1_056 - .saturating_add(Weight::from_parts(1_089_042, 0).saturating_mul(k.into())) + // Minimum execution time: 3_645_000 picoseconds. + Weight::from_parts(604_365, 3635) + // Standard Error: 1_013 + .saturating_add(Weight::from_parts(1_100_277, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -225,10 +224,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `328 + c * (1 ±0)` // Estimated: `6266 + c * (1 ±0)` - // Minimum execution time: 19_891_000 picoseconds. - Weight::from_parts(19_961_608, 6266) + // Minimum execution time: 19_500_000 picoseconds. + Weight::from_parts(20_074_895, 6266) // Standard Error: 1 - .saturating_add(Weight::from_parts(429, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(422, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -239,8 +238,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 12_483_000 picoseconds. - Weight::from_parts(13_205_000, 6380) + // Minimum execution time: 12_530_000 picoseconds. + Weight::from_parts(13_362_000, 6380) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -254,8 +253,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `6292` - // Minimum execution time: 42_443_000 picoseconds. - Weight::from_parts(43_420_000, 6292) + // Minimum execution time: 44_275_000 picoseconds. + Weight::from_parts(45_718_000, 6292) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -267,8 +266,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 52_282_000 picoseconds. - Weight::from_parts(54_110_000, 6534) + // Minimum execution time: 55_095_000 picoseconds. + Weight::from_parts(58_009_000, 6534) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -278,8 +277,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_539_000 picoseconds. - Weight::from_parts(2_644_000, 1627) + // Minimum execution time: 2_455_000 picoseconds. + Weight::from_parts(2_608_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -291,8 +290,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 9_473_000 picoseconds. - Weight::from_parts(9_907_000, 3631) + // Minimum execution time: 11_207_000 picoseconds. + Weight::from_parts(11_802_000, 3631) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -302,8 +301,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 3_532_000 picoseconds. - Weight::from_parts(3_768_000, 3607) + // Minimum execution time: 4_581_000 picoseconds. + Weight::from_parts(4_781_000, 3607) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -314,8 +313,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 5_036_000 picoseconds. - Weight::from_parts(5_208_000, 3632) + // Minimum execution time: 5_887_000 picoseconds. + Weight::from_parts(6_393_000, 3632) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -326,8 +325,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 4_881_000 picoseconds. - Weight::from_parts(5_149_000, 3607) + // Minimum execution time: 6_025_000 picoseconds. + Weight::from_parts(6_298_000, 3607) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -352,10 +351,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `804 + c * (1 ±0)` // Estimated: `9217 + c * (1 ±0)` - // Minimum execution time: 280_047_000 picoseconds. - Weight::from_parts(270_065_882, 9217) - // Standard Error: 86 - .saturating_add(Weight::from_parts(34_361, 0).saturating_mul(c.into())) + // Minimum execution time: 294_976_000 picoseconds. + Weight::from_parts(277_235_948, 9217) + // Standard Error: 65 + .saturating_add(Weight::from_parts(34_445, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -387,14 +386,14 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `326` // Estimated: `8740` - // Minimum execution time: 3_776_071_000 picoseconds. - Weight::from_parts(706_212_213, 8740) - // Standard Error: 149 - .saturating_add(Weight::from_parts(98_798, 0).saturating_mul(c.into())) - // Standard Error: 17 - .saturating_add(Weight::from_parts(1_560, 0).saturating_mul(i.into())) - // Standard Error: 17 - .saturating_add(Weight::from_parts(1_476, 0).saturating_mul(s.into())) + // Minimum execution time: 3_864_558_000 picoseconds. + Weight::from_parts(421_676_889, 8740) + // Standard Error: 188 + .saturating_add(Weight::from_parts(103_788, 0).saturating_mul(c.into())) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_715, 0).saturating_mul(i.into())) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_774, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } @@ -424,12 +423,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `563` // Estimated: `8982` - // Minimum execution time: 1_966_301_000 picoseconds. - Weight::from_parts(376_287_434, 8982) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_643, 0).saturating_mul(i.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_667, 0).saturating_mul(s.into())) + // Minimum execution time: 2_069_276_000 picoseconds. + Weight::from_parts(377_210_279, 8982) + // Standard Error: 9 + .saturating_add(Weight::from_parts(1_719, 0).saturating_mul(i.into())) + // Standard Error: 9 + .saturating_add(Weight::from_parts(1_728, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -453,8 +452,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `829` // Estimated: `9244` - // Minimum execution time: 197_571_000 picoseconds. - Weight::from_parts(206_612_000, 9244) + // Minimum execution time: 199_037_000 picoseconds. + Weight::from_parts(213_931_000, 9244) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -471,14 +470,38 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Contracts::PristineCode` (r:0 w:1) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) /// The range of component `c` is `[0, 125952]`. - fn upload_code(c: u32, ) -> Weight { + fn upload_code_determinism_enforced(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `145` // Estimated: `6085` - // Minimum execution time: 266_006_000 picoseconds. - Weight::from_parts(287_700_788, 6085) - // Standard Error: 67 - .saturating_add(Weight::from_parts(63_196, 0).saturating_mul(c.into())) + // Minimum execution time: 278_482_000 picoseconds. + Weight::from_parts(262_753_879, 6085) + // Standard Error: 112 + .saturating_add(Weight::from_parts(66_129, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) + /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) + /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) + /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Storage: `System::EventTopics` (r:1 w:1) + /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Contracts::PristineCode` (r:0 w:1) + /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) + /// The range of component `c` is `[0, 125952]`. + fn upload_code_determinism_relaxed(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `6085` + // Minimum execution time: 286_902_000 picoseconds. + Weight::from_parts(269_003_959, 6085) + // Standard Error: 123 + .saturating_add(Weight::from_parts(66_629, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -496,8 +519,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 42_714_000 picoseconds. - Weight::from_parts(44_713_000, 3780) + // Minimum execution time: 44_128_000 picoseconds. + Weight::from_parts(46_044_000, 3780) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -513,8 +536,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `552` // Estimated: `8967` - // Minimum execution time: 33_516_000 picoseconds. - Weight::from_parts(34_823_000, 8967) + // Minimum execution time: 33_567_000 picoseconds. + Weight::from_parts(35_057_000, 8967) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -539,10 +562,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `869 + r * (6 ±0)` // Estimated: `9284 + r * (6 ±0)` - // Minimum execution time: 246_563_000 picoseconds. - Weight::from_parts(274_999_814, 9284) - // Standard Error: 628 - .saturating_add(Weight::from_parts(347_395, 0).saturating_mul(r.into())) + // Minimum execution time: 272_376_000 picoseconds. + Weight::from_parts(284_162_161, 9284) + // Standard Error: 501 + .saturating_add(Weight::from_parts(341_575, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -568,10 +591,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `925 + r * (209 ±0)` // Estimated: `9304 + r * (2684 ±0)` - // Minimum execution time: 252_236_000 picoseconds. - Weight::from_parts(121_390_081, 9304) - // Standard Error: 6_206 - .saturating_add(Weight::from_parts(3_558_718, 0).saturating_mul(r.into())) + // Minimum execution time: 256_990_000 picoseconds. + Weight::from_parts(107_167_044, 9304) + // Standard Error: 7_545 + .saturating_add(Weight::from_parts(3_628_112, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -598,10 +621,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `924 + r * (213 ±0)` // Estimated: `9308 + r * (2688 ±0)` - // Minimum execution time: 269_427_000 picoseconds. - Weight::from_parts(134_879_389, 9308) - // Standard Error: 6_711 - .saturating_add(Weight::from_parts(4_408_658, 0).saturating_mul(r.into())) + // Minimum execution time: 272_889_000 picoseconds. + Weight::from_parts(110_341_799, 9308) + // Standard Error: 7_881 + .saturating_add(Weight::from_parts(4_427_043, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -628,10 +651,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `876 + r * (6 ±0)` // Estimated: `9293 + r * (6 ±0)` - // Minimum execution time: 249_382_000 picoseconds. - Weight::from_parts(266_305_110, 9293) - // Standard Error: 1_592 - .saturating_add(Weight::from_parts(460_001, 0).saturating_mul(r.into())) + // Minimum execution time: 275_027_000 picoseconds. + Weight::from_parts(283_302_223, 9293) + // Standard Error: 1_179 + .saturating_add(Weight::from_parts(436_023, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -657,10 +680,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866 + r * (3 ±0)` // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 252_145_000 picoseconds. - Weight::from_parts(277_211_668, 9282) - // Standard Error: 371 - .saturating_add(Weight::from_parts(174_394, 0).saturating_mul(r.into())) + // Minimum execution time: 270_137_000 picoseconds. + Weight::from_parts(282_756_362, 9282) + // Standard Error: 384 + .saturating_add(Weight::from_parts(171_660, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -684,10 +707,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `756 + r * (3 ±0)` // Estimated: `9171 + r * (3 ±0)` - // Minimum execution time: 251_595_000 picoseconds. - Weight::from_parts(268_102_575, 9171) - // Standard Error: 334 - .saturating_add(Weight::from_parts(154_836, 0).saturating_mul(r.into())) + // Minimum execution time: 255_131_000 picoseconds. + Weight::from_parts(269_207_006, 9171) + // Standard Error: 542 + .saturating_add(Weight::from_parts(161_597, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -713,10 +736,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `870 + r * (6 ±0)` // Estimated: `9285 + r * (6 ±0)` - // Minimum execution time: 251_404_000 picoseconds. - Weight::from_parts(278_747_574, 9285) - // Standard Error: 782 - .saturating_add(Weight::from_parts(341_598, 0).saturating_mul(r.into())) + // Minimum execution time: 272_172_000 picoseconds. + Weight::from_parts(283_747_134, 9285) + // Standard Error: 885 + .saturating_add(Weight::from_parts(343_968, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -742,10 +765,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866 + r * (6 ±0)` // Estimated: `9284 + r * (6 ±0)` - // Minimum execution time: 255_649_000 picoseconds. - Weight::from_parts(276_509_641, 9284) - // Standard Error: 1_262 - .saturating_add(Weight::from_parts(380_225, 0).saturating_mul(r.into())) + // Minimum execution time: 263_220_000 picoseconds. + Weight::from_parts(277_062_382, 9284) + // Standard Error: 1_783 + .saturating_add(Weight::from_parts(399_631, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -771,10 +794,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1010 + r * (6 ±0)` // Estimated: `9409 + r * (6 ±0)` - // Minimum execution time: 267_143_000 picoseconds. - Weight::from_parts(298_166_116, 9409) - // Standard Error: 3_765 - .saturating_add(Weight::from_parts(1_620_886, 0).saturating_mul(r.into())) + // Minimum execution time: 253_218_000 picoseconds. + Weight::from_parts(282_251_452, 9409) + // Standard Error: 2_367 + .saturating_add(Weight::from_parts(1_604_060, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -800,10 +823,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `880 + r * (6 ±0)` // Estimated: `9301 + r * (6 ±0)` - // Minimum execution time: 250_013_000 picoseconds. - Weight::from_parts(281_469_583, 9301) - // Standard Error: 730 - .saturating_add(Weight::from_parts(339_260, 0).saturating_mul(r.into())) + // Minimum execution time: 271_797_000 picoseconds. + Weight::from_parts(288_594_393, 9301) + // Standard Error: 846 + .saturating_add(Weight::from_parts(335_063, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -829,10 +852,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `878 + r * (6 ±0)` // Estimated: `9294 + r * (6 ±0)` - // Minimum execution time: 256_219_000 picoseconds. - Weight::from_parts(275_309_266, 9294) - // Standard Error: 1_199 - .saturating_add(Weight::from_parts(350_824, 0).saturating_mul(r.into())) + // Minimum execution time: 254_997_000 picoseconds. + Weight::from_parts(284_331_894, 9294) + // Standard Error: 885 + .saturating_add(Weight::from_parts(337_073, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -858,10 +881,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `875 + r * (6 ±0)` // Estimated: `9297 + r * (6 ±0)` - // Minimum execution time: 264_644_000 picoseconds. - Weight::from_parts(283_856_744, 9297) - // Standard Error: 623 - .saturating_add(Weight::from_parts(334_175, 0).saturating_mul(r.into())) + // Minimum execution time: 273_845_000 picoseconds. + Weight::from_parts(285_291_242, 9297) + // Standard Error: 690 + .saturating_add(Weight::from_parts(332_783, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -887,10 +910,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866 + r * (6 ±0)` // Estimated: `9282 + r * (6 ±0)` - // Minimum execution time: 263_364_000 picoseconds. - Weight::from_parts(281_379_508, 9282) - // Standard Error: 639 - .saturating_add(Weight::from_parts(338_021, 0).saturating_mul(r.into())) + // Minimum execution time: 268_302_000 picoseconds. + Weight::from_parts(280_463_257, 9282) + // Standard Error: 1_035 + .saturating_add(Weight::from_parts(345_811, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -918,10 +941,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `940 + r * (14 ±0)` // Estimated: `9350 + r * (14 ±0)` - // Minimum execution time: 269_667_000 picoseconds. - Weight::from_parts(284_662_802, 9350) - // Standard Error: 691 - .saturating_add(Weight::from_parts(799_249, 0).saturating_mul(r.into())) + // Minimum execution time: 263_433_000 picoseconds. + Weight::from_parts(290_098_370, 9350) + // Standard Error: 1_905 + .saturating_add(Weight::from_parts(805_299, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 14).saturating_mul(r.into())) @@ -947,10 +970,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `868 + r * (6 ±0)` // Estimated: `9285 + r * (6 ±0)` - // Minimum execution time: 267_018_000 picoseconds. - Weight::from_parts(281_842_630, 9285) - // Standard Error: 453 - .saturating_add(Weight::from_parts(255_373, 0).saturating_mul(r.into())) + // Minimum execution time: 273_588_000 picoseconds. + Weight::from_parts(287_133_565, 9285) + // Standard Error: 799 + .saturating_add(Weight::from_parts(254_114, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -976,10 +999,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `872` // Estimated: `9287` - // Minimum execution time: 258_208_000 picoseconds. - Weight::from_parts(227_686_792, 9287) - // Standard Error: 23 - .saturating_add(Weight::from_parts(989, 0).saturating_mul(n.into())) + // Minimum execution time: 257_843_000 picoseconds. + Weight::from_parts(228_177_495, 9287) + // Standard Error: 24 + .saturating_add(Weight::from_parts(985, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1004,8 +1027,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `856 + r * (45 ±0)` // Estimated: `9271 + r * (45 ±0)` - // Minimum execution time: 245_714_000 picoseconds. - Weight::from_parts(272_527_059, 9271) + // Minimum execution time: 248_332_000 picoseconds. + Weight::from_parts(274_998_906, 9271) + // Standard Error: 949_561 + .saturating_add(Weight::from_parts(5_570_693, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 45).saturating_mul(r.into())) @@ -1031,10 +1056,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866` // Estimated: `9288` - // Minimum execution time: 256_060_000 picoseconds. - Weight::from_parts(276_710_811, 9288) - // Standard Error: 0 - .saturating_add(Weight::from_parts(312, 0).saturating_mul(n.into())) + // Minimum execution time: 272_055_000 picoseconds. + Weight::from_parts(282_280_090, 9288) + // Standard Error: 1 + .saturating_add(Weight::from_parts(330, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1065,10 +1090,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2902 + r * (529 ±0)` // Estimated: `11317 + r * (5479 ±0)` - // Minimum execution time: 270_479_000 picoseconds. - Weight::from_parts(296_706_989, 11317) - // Standard Error: 813_407 - .saturating_add(Weight::from_parts(109_236_910, 0).saturating_mul(r.into())) + // Minimum execution time: 274_842_000 picoseconds. + Weight::from_parts(299_824_497, 11317) + // Standard Error: 902_686 + .saturating_add(Weight::from_parts(106_562_902, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1098,10 +1123,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `947 + r * (10 ±0)` // Estimated: `9363 + r * (10 ±0)` - // Minimum execution time: 251_787_000 picoseconds. - Weight::from_parts(284_036_313, 9363) - // Standard Error: 2_560 - .saturating_add(Weight::from_parts(1_238_301, 0).saturating_mul(r.into())) + // Minimum execution time: 255_393_000 picoseconds. + Weight::from_parts(309_814_338, 9363) + // Standard Error: 2_978 + .saturating_add(Weight::from_parts(1_203_507, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -1127,10 +1152,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866 + r * (10 ±0)` // Estimated: `9283 + r * (10 ±0)` - // Minimum execution time: 250_566_000 picoseconds. - Weight::from_parts(275_402_784, 9283) - // Standard Error: 3_939 - .saturating_add(Weight::from_parts(1_941_995, 0).saturating_mul(r.into())) + // Minimum execution time: 250_378_000 picoseconds. + Weight::from_parts(287_003_144, 9283) + // Standard Error: 2_726 + .saturating_add(Weight::from_parts(1_850_967, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -1157,12 +1182,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `883 + t * (32 ±0)` // Estimated: `9303 + t * (2508 ±0)` - // Minimum execution time: 267_544_000 picoseconds. - Weight::from_parts(280_117_825, 9303) - // Standard Error: 102_111 - .saturating_add(Weight::from_parts(3_253_038, 0).saturating_mul(t.into())) - // Standard Error: 28 - .saturating_add(Weight::from_parts(668, 0).saturating_mul(n.into())) + // Minimum execution time: 266_787_000 picoseconds. + Weight::from_parts(284_368_661, 9303) + // Standard Error: 121_315 + .saturating_add(Weight::from_parts(2_690_211, 0).saturating_mul(t.into())) + // Standard Error: 33 + .saturating_add(Weight::from_parts(789, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1190,10 +1215,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `865 + r * (7 ±0)` // Estimated: `9285 + r * (7 ±0)` - // Minimum execution time: 157_769_000 picoseconds. - Weight::from_parts(173_026_565, 9285) - // Standard Error: 405 - .saturating_add(Weight::from_parts(219_727, 0).saturating_mul(r.into())) + // Minimum execution time: 166_804_000 picoseconds. + Weight::from_parts(175_118_291, 9285) + // Standard Error: 398 + .saturating_add(Weight::from_parts(220_961, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) @@ -1219,10 +1244,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `125816` // Estimated: `131758` - // Minimum execution time: 403_961_000 picoseconds. - Weight::from_parts(376_480_872, 131758) + // Minimum execution time: 398_436_000 picoseconds. + Weight::from_parts(385_003_285, 131758) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_041, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(1_038, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1233,10 +1258,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `927 + r * (292 ±0)` // Estimated: `929 + r * (293 ±0)` - // Minimum execution time: 256_272_000 picoseconds. - Weight::from_parts(181_058_379, 929) - // Standard Error: 9_838 - .saturating_add(Weight::from_parts(6_316_677, 0).saturating_mul(r.into())) + // Minimum execution time: 274_099_000 picoseconds. + Weight::from_parts(174_282_817, 929) + // Standard Error: 10_547 + .saturating_add(Weight::from_parts(6_262_173, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1250,10 +1275,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1450` // Estimated: `1433` - // Minimum execution time: 268_713_000 picoseconds. - Weight::from_parts(328_329_131, 1433) + // Minimum execution time: 274_061_000 picoseconds. + Weight::from_parts(334_755_333, 1433) // Standard Error: 66 - .saturating_add(Weight::from_parts(962, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(771, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -1264,10 +1289,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1256 + n * (1 ±0)` // Estimated: `1256 + n * (1 ±0)` - // Minimum execution time: 265_683_000 picoseconds. - Weight::from_parts(293_784_477, 1256) - // Standard Error: 31 - .saturating_add(Weight::from_parts(377, 0).saturating_mul(n.into())) + // Minimum execution time: 272_657_000 picoseconds. + Weight::from_parts(299_061_594, 1256) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1279,10 +1302,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `924 + r * (288 ±0)` // Estimated: `930 + r * (289 ±0)` - // Minimum execution time: 269_959_000 picoseconds. - Weight::from_parts(186_065_911, 930) - // Standard Error: 9_679 - .saturating_add(Weight::from_parts(6_286_855, 0).saturating_mul(r.into())) + // Minimum execution time: 270_524_000 picoseconds. + Weight::from_parts(177_959_667, 930) + // Standard Error: 10_397 + .saturating_add(Weight::from_parts(6_270_181, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1296,8 +1319,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1252 + n * (1 ±0)` // Estimated: `1252 + n * (1 ±0)` - // Minimum execution time: 265_805_000 picoseconds. - Weight::from_parts(294_633_695, 1252) + // Minimum execution time: 270_757_000 picoseconds. + Weight::from_parts(298_627_896, 1252) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1309,10 +1332,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `924 + r * (296 ±0)` // Estimated: `926 + r * (297 ±0)` - // Minimum execution time: 264_592_000 picoseconds. - Weight::from_parts(204_670_461, 926) - // Standard Error: 6_869 - .saturating_add(Weight::from_parts(5_137_920, 0).saturating_mul(r.into())) + // Minimum execution time: 268_082_000 picoseconds. + Weight::from_parts(202_583_730, 926) + // Standard Error: 9_029 + .saturating_add(Weight::from_parts(5_028_517, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1325,10 +1348,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1268 + n * (1 ±0)` // Estimated: `1268 + n * (1 ±0)` - // Minimum execution time: 273_165_000 picoseconds. - Weight::from_parts(297_883_669, 1268) - // Standard Error: 37 - .saturating_add(Weight::from_parts(576, 0).saturating_mul(n.into())) + // Minimum execution time: 274_100_000 picoseconds. + Weight::from_parts(296_981_515, 1268) + // Standard Error: 34 + .saturating_add(Weight::from_parts(578, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1340,10 +1363,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `935 + r * (288 ±0)` // Estimated: `932 + r * (289 ±0)` - // Minimum execution time: 252_257_000 picoseconds. - Weight::from_parts(205_018_595, 932) - // Standard Error: 7_605 - .saturating_add(Weight::from_parts(4_933_378, 0).saturating_mul(r.into())) + // Minimum execution time: 269_697_000 picoseconds. + Weight::from_parts(198_346_516, 932) + // Standard Error: 8_623 + .saturating_add(Weight::from_parts(4_964_116, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1356,10 +1379,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1255 + n * (1 ±0)` // Estimated: `1255 + n * (1 ±0)` - // Minimum execution time: 266_839_000 picoseconds. - Weight::from_parts(292_064_487, 1255) - // Standard Error: 34 - .saturating_add(Weight::from_parts(194, 0).saturating_mul(n.into())) + // Minimum execution time: 264_210_000 picoseconds. + Weight::from_parts(291_387_652, 1255) + // Standard Error: 36 + .saturating_add(Weight::from_parts(524, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1371,10 +1394,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `917 + r * (296 ±0)` // Estimated: `922 + r * (297 ±0)` - // Minimum execution time: 266_072_000 picoseconds. - Weight::from_parts(189_018_352, 922) - // Standard Error: 9_530 - .saturating_add(Weight::from_parts(6_481_011, 0).saturating_mul(r.into())) + // Minimum execution time: 267_219_000 picoseconds. + Weight::from_parts(175_866_982, 922) + // Standard Error: 11_275 + .saturating_add(Weight::from_parts(6_424_755, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1388,10 +1411,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1269 + n * (1 ±0)` // Estimated: `1269 + n * (1 ±0)` - // Minimum execution time: 270_703_000 picoseconds. - Weight::from_parts(292_867_105, 1269) - // Standard Error: 30 - .saturating_add(Weight::from_parts(800, 0).saturating_mul(n.into())) + // Minimum execution time: 274_634_000 picoseconds. + Weight::from_parts(294_272_009, 1269) + // Standard Error: 36 + .saturating_add(Weight::from_parts(1_219, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1417,10 +1440,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1418 + r * (45 ±0)` // Estimated: `9785 + r * (2520 ±0)` - // Minimum execution time: 251_843_000 picoseconds. - Weight::from_parts(181_026_888, 9785) - // Standard Error: 38_221 - .saturating_add(Weight::from_parts(30_626_681, 0).saturating_mul(r.into())) + // Minimum execution time: 266_833_000 picoseconds. + Weight::from_parts(186_049_741, 9785) + // Standard Error: 40_311 + .saturating_add(Weight::from_parts(31_365_585, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -1448,10 +1471,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1263 + r * (245 ±0)` // Estimated: `9635 + r * (2721 ±0)` - // Minimum execution time: 254_881_000 picoseconds. - Weight::from_parts(272_871_000, 9635) - // Standard Error: 94_527 - .saturating_add(Weight::from_parts(233_379_497, 0).saturating_mul(r.into())) + // Minimum execution time: 272_140_000 picoseconds. + Weight::from_parts(275_009_000, 9635) + // Standard Error: 99_187 + .saturating_add(Weight::from_parts(240_702_479, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -1478,11 +1501,11 @@ impl WeightInfo for SubstrateWeight { fn seal_delegate_call(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (576 ±0)` - // Estimated: `9290 + r * (2637 ±3)` - // Minimum execution time: 266_704_000 picoseconds. - Weight::from_parts(273_165_000, 9290) - // Standard Error: 141_486 - .saturating_add(Weight::from_parts(232_947_049, 0).saturating_mul(r.into())) + // Estimated: `9290 + r * (2637 ±10)` + // Minimum execution time: 263_664_000 picoseconds. + Weight::from_parts(277_240_000, 9290) + // Standard Error: 169_147 + .saturating_add(Weight::from_parts(240_084_929, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1511,12 +1534,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1310 + t * (277 ±0)` // Estimated: `12200 + t * (5227 ±0)` - // Minimum execution time: 446_451_000 picoseconds. - Weight::from_parts(68_175_222, 12200) - // Standard Error: 11_619_250 - .saturating_add(Weight::from_parts(354_237_260, 0).saturating_mul(t.into())) + // Minimum execution time: 464_644_000 picoseconds. + Weight::from_parts(40_377_313, 12200) + // Standard Error: 12_060_226 + .saturating_add(Weight::from_parts(380_635_982, 0).saturating_mul(t.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(987, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_014, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(16_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) @@ -1548,10 +1571,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1281 + r * (255 ±0)` // Estimated: `9623 + r * (2731 ±0)` - // Minimum execution time: 628_156_000 picoseconds. - Weight::from_parts(642_052_000, 9623) - // Standard Error: 223_957 - .saturating_add(Weight::from_parts(348_660_264, 0).saturating_mul(r.into())) + // Minimum execution time: 641_845_000 picoseconds. + Weight::from_parts(649_908_000, 9623) + // Standard Error: 278_514 + .saturating_add(Weight::from_parts(361_164_598, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(7_u64)) @@ -1585,14 +1608,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1306 + t * (104 ±0)` // Estimated: `12214 + t * (2549 ±1)` - // Minimum execution time: 2_106_379_000 picoseconds. - Weight::from_parts(1_098_227_098, 12214) - // Standard Error: 12_549_729 - .saturating_add(Weight::from_parts(21_628_382, 0).saturating_mul(t.into())) - // Standard Error: 19 - .saturating_add(Weight::from_parts(1_059, 0).saturating_mul(i.into())) - // Standard Error: 19 - .saturating_add(Weight::from_parts(1_220, 0).saturating_mul(s.into())) + // Minimum execution time: 2_111_632_000 picoseconds. + Weight::from_parts(1_213_125_745, 12214) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_055, 0).saturating_mul(i.into())) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_192, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(19_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(11_u64)) @@ -1620,10 +1641,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `865 + r * (8 ±0)` // Estimated: `9279 + r * (8 ±0)` - // Minimum execution time: 257_102_000 picoseconds. - Weight::from_parts(278_920_692, 9279) - // Standard Error: 464 - .saturating_add(Weight::from_parts(374_120, 0).saturating_mul(r.into())) + // Minimum execution time: 264_227_000 picoseconds. + Weight::from_parts(281_015_995, 9279) + // Standard Error: 710 + .saturating_add(Weight::from_parts(365_734, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1649,10 +1670,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `873` // Estimated: `9286` - // Minimum execution time: 266_609_000 picoseconds. - Weight::from_parts(263_034_132, 9286) + // Minimum execution time: 270_709_000 picoseconds. + Weight::from_parts(268_416_051, 9286) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_082, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_080, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1677,10 +1698,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9284 + r * (8 ±0)` - // Minimum execution time: 246_275_000 picoseconds. - Weight::from_parts(279_091_594, 9284) - // Standard Error: 887 - .saturating_add(Weight::from_parts(810_394, 0).saturating_mul(r.into())) + // Minimum execution time: 267_283_000 picoseconds. + Weight::from_parts(280_706_659, 9284) + // Standard Error: 540 + .saturating_add(Weight::from_parts(790_312, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1706,10 +1727,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9292` - // Minimum execution time: 249_254_000 picoseconds. - Weight::from_parts(270_833_823, 9292) - // Standard Error: 0 - .saturating_add(Weight::from_parts(3_347, 0).saturating_mul(n.into())) + // Minimum execution time: 262_010_000 picoseconds. + Weight::from_parts(273_278_744, 9292) + // Standard Error: 1 + .saturating_add(Weight::from_parts(3_362, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1734,10 +1755,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9286 + r * (8 ±0)` - // Minimum execution time: 259_131_000 picoseconds. - Weight::from_parts(272_665_020, 9286) - // Standard Error: 862 - .saturating_add(Weight::from_parts(451_247, 0).saturating_mul(r.into())) + // Minimum execution time: 268_698_000 picoseconds. + Weight::from_parts(282_890_578, 9286) + // Standard Error: 622 + .saturating_add(Weight::from_parts(441_131, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1763,10 +1784,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9291` - // Minimum execution time: 276_465_000 picoseconds. - Weight::from_parts(269_450_297, 9291) + // Minimum execution time: 252_846_000 picoseconds. + Weight::from_parts(267_657_561, 9291) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_190, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_208, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1791,10 +1812,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9283 + r * (8 ±0)` - // Minimum execution time: 248_349_000 picoseconds. - Weight::from_parts(273_660_686, 9283) - // Standard Error: 656 - .saturating_add(Weight::from_parts(444_293, 0).saturating_mul(r.into())) + // Minimum execution time: 266_899_000 picoseconds. + Weight::from_parts(276_862_067, 9283) + // Standard Error: 1_249 + .saturating_add(Weight::from_parts(443_970, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1820,10 +1841,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9289` - // Minimum execution time: 252_107_000 picoseconds. - Weight::from_parts(267_427_726, 9289) + // Minimum execution time: 265_413_000 picoseconds. + Weight::from_parts(265_600_840, 9289) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_199, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_203, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1848,10 +1869,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1000 + n * (1 ±0)` // Estimated: `9412 + n * (1 ±0)` - // Minimum execution time: 311_252_000 picoseconds. - Weight::from_parts(333_250_773, 9412) - // Standard Error: 12 - .saturating_add(Weight::from_parts(5_668, 0).saturating_mul(n.into())) + // Minimum execution time: 328_341_000 picoseconds. + Weight::from_parts(341_038_581, 9412) + // Standard Error: 10 + .saturating_add(Weight::from_parts(5_863, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1875,12 +1896,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 160]`. fn seal_sr25519_verify(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `810 + r * (112 ±0)` + // Measured: `808 + r * (112 ±0)` // Estimated: `9226 + r * (112 ±0)` - // Minimum execution time: 267_431_000 picoseconds. - Weight::from_parts(300_733_048, 9226) - // Standard Error: 8_806 - .saturating_add(Weight::from_parts(42_169_197, 0).saturating_mul(r.into())) + // Minimum execution time: 272_730_000 picoseconds. + Weight::from_parts(339_349_232, 9226) + // Standard Error: 13_004 + .saturating_add(Weight::from_parts(41_649_026, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(r.into())) @@ -1906,10 +1927,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `910 + r * (76 ±0)` // Estimated: `9279 + r * (77 ±0)` - // Minimum execution time: 265_905_000 picoseconds. - Weight::from_parts(305_381_951, 9279) - // Standard Error: 9_863 - .saturating_add(Weight::from_parts(45_771_182, 0).saturating_mul(r.into())) + // Minimum execution time: 273_892_000 picoseconds. + Weight::from_parts(352_853_960, 9279) + // Standard Error: 16_745 + .saturating_add(Weight::from_parts(45_853_294, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 77).saturating_mul(r.into())) @@ -1935,10 +1956,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `880 + r * (42 ±0)` // Estimated: `9294 + r * (42 ±0)` - // Minimum execution time: 266_701_000 picoseconds. - Weight::from_parts(292_407_888, 9294) - // Standard Error: 5_394 - .saturating_add(Weight::from_parts(11_896_065, 0).saturating_mul(r.into())) + // Minimum execution time: 268_431_000 picoseconds. + Weight::from_parts(319_727_796, 9294) + // Standard Error: 10_276 + .saturating_add(Weight::from_parts(11_928_882, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(r.into())) @@ -1964,10 +1985,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + r * (965 ±0)` // Estimated: `9285 + r * (3090 ±7)` - // Minimum execution time: 268_755_000 picoseconds. - Weight::from_parts(272_300_000, 9285) - // Standard Error: 43_747 - .saturating_add(Weight::from_parts(25_001_889, 0).saturating_mul(r.into())) + // Minimum execution time: 275_482_000 picoseconds. + Weight::from_parts(279_155_000, 9285) + // Standard Error: 65_388 + .saturating_add(Weight::from_parts(26_634_187, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1995,10 +2016,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `937 + r * (131 ±0)` // Estimated: `9346 + r * (2607 ±0)` - // Minimum execution time: 255_190_000 picoseconds. - Weight::from_parts(285_643_922, 9346) - // Standard Error: 23_582 - .saturating_add(Weight::from_parts(6_289_940, 0).saturating_mul(r.into())) + // Minimum execution time: 270_001_000 picoseconds. + Weight::from_parts(286_792_689, 9346) + // Standard Error: 21_074 + .saturating_add(Weight::from_parts(6_465_885, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -2026,10 +2047,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `972 + r * (184 ±0)` // Estimated: `129453 + r * (2568 ±0)` - // Minimum execution time: 260_061_000 picoseconds. - Weight::from_parts(286_849_343, 129453) - // Standard Error: 22_406 - .saturating_add(Weight::from_parts(5_661_459, 0).saturating_mul(r.into())) + // Minimum execution time: 270_652_000 picoseconds. + Weight::from_parts(293_369_452, 129453) + // Standard Error: 24_321 + .saturating_add(Weight::from_parts(5_575_600, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -2057,10 +2078,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `861 + r * (3 ±0)` // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 250_922_000 picoseconds. - Weight::from_parts(277_294_913, 9282) - // Standard Error: 391 - .saturating_add(Weight::from_parts(169_457, 0).saturating_mul(r.into())) + // Minimum execution time: 267_749_000 picoseconds. + Weight::from_parts(280_373_341, 9282) + // Standard Error: 464 + .saturating_add(Weight::from_parts(170_398, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2086,10 +2107,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2112 + r * (39 ±0)` // Estimated: `10377 + r * (40 ±0)` - // Minimum execution time: 267_293_000 picoseconds. - Weight::from_parts(309_125_635, 10377) - // Standard Error: 637 - .saturating_add(Weight::from_parts(245_508, 0).saturating_mul(r.into())) + // Minimum execution time: 270_260_000 picoseconds. + Weight::from_parts(337_969_172, 10377) + // Standard Error: 1_557 + .saturating_add(Weight::from_parts(305_735, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 40).saturating_mul(r.into())) @@ -2117,10 +2138,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `864 + r * (3 ±0)` // Estimated: `9279 + r * (3 ±0)` - // Minimum execution time: 256_057_000 picoseconds. - Weight::from_parts(278_068_870, 9279) - // Standard Error: 335 - .saturating_add(Weight::from_parts(152_083, 0).saturating_mul(r.into())) + // Minimum execution time: 265_607_000 picoseconds. + Weight::from_parts(283_396_630, 9279) + // Standard Error: 449 + .saturating_add(Weight::from_parts(149_018, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2130,10 +2151,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_846_000 picoseconds. - Weight::from_parts(1_808_029, 0) - // Standard Error: 9 - .saturating_add(Weight::from_parts(14_937, 0).saturating_mul(r.into())) + // Minimum execution time: 1_813_000 picoseconds. + Weight::from_parts(1_264_945, 0) + // Standard Error: 19 + .saturating_add(Weight::from_parts(15_098, 0).saturating_mul(r.into())) } } @@ -2145,8 +2166,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_103_000 picoseconds. - Weight::from_parts(2_260_000, 1627) + // Minimum execution time: 2_054_000 picoseconds. + Weight::from_parts(2_178_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -2156,10 +2177,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `452 + k * (69 ±0)` // Estimated: `442 + k * (70 ±0)` - // Minimum execution time: 12_173_000 picoseconds. - Weight::from_parts(12_515_000, 442) - // Standard Error: 1_033 - .saturating_add(Weight::from_parts(1_075_765, 0).saturating_mul(k.into())) + // Minimum execution time: 12_119_000 picoseconds. + Weight::from_parts(12_536_000, 442) + // Standard Error: 1_254 + .saturating_add(Weight::from_parts(1_161_885, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -2173,10 +2194,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_054_000 picoseconds. - Weight::from_parts(8_503_485, 6149) + // Minimum execution time: 8_146_000 picoseconds. + Weight::from_parts(8_560_745, 6149) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_184, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_182, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -2189,8 +2210,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 16_966_000 picoseconds. - Weight::from_parts(17_445_000, 6450) + // Minimum execution time: 16_183_000 picoseconds. + Weight::from_parts(16_825_000, 6450) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2203,10 +2224,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_643_000 picoseconds. - Weight::from_parts(3_714_000, 3635) - // Standard Error: 1_056 - .saturating_add(Weight::from_parts(1_089_042, 0).saturating_mul(k.into())) + // Minimum execution time: 3_645_000 picoseconds. + Weight::from_parts(604_365, 3635) + // Standard Error: 1_013 + .saturating_add(Weight::from_parts(1_100_277, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -2227,10 +2248,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `328 + c * (1 ±0)` // Estimated: `6266 + c * (1 ±0)` - // Minimum execution time: 19_891_000 picoseconds. - Weight::from_parts(19_961_608, 6266) + // Minimum execution time: 19_500_000 picoseconds. + Weight::from_parts(20_074_895, 6266) // Standard Error: 1 - .saturating_add(Weight::from_parts(429, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(422, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -2241,8 +2262,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 12_483_000 picoseconds. - Weight::from_parts(13_205_000, 6380) + // Minimum execution time: 12_530_000 picoseconds. + Weight::from_parts(13_362_000, 6380) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2256,8 +2277,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `352` // Estimated: `6292` - // Minimum execution time: 42_443_000 picoseconds. - Weight::from_parts(43_420_000, 6292) + // Minimum execution time: 44_275_000 picoseconds. + Weight::from_parts(45_718_000, 6292) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2269,8 +2290,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 52_282_000 picoseconds. - Weight::from_parts(54_110_000, 6534) + // Minimum execution time: 55_095_000 picoseconds. + Weight::from_parts(58_009_000, 6534) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2280,8 +2301,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_539_000 picoseconds. - Weight::from_parts(2_644_000, 1627) + // Minimum execution time: 2_455_000 picoseconds. + Weight::from_parts(2_608_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2293,8 +2314,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 9_473_000 picoseconds. - Weight::from_parts(9_907_000, 3631) + // Minimum execution time: 11_207_000 picoseconds. + Weight::from_parts(11_802_000, 3631) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2304,8 +2325,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 3_532_000 picoseconds. - Weight::from_parts(3_768_000, 3607) + // Minimum execution time: 4_581_000 picoseconds. + Weight::from_parts(4_781_000, 3607) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -2316,8 +2337,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 5_036_000 picoseconds. - Weight::from_parts(5_208_000, 3632) + // Minimum execution time: 5_887_000 picoseconds. + Weight::from_parts(6_393_000, 3632) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -2328,8 +2349,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 4_881_000 picoseconds. - Weight::from_parts(5_149_000, 3607) + // Minimum execution time: 6_025_000 picoseconds. + Weight::from_parts(6_298_000, 3607) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2354,10 +2375,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `804 + c * (1 ±0)` // Estimated: `9217 + c * (1 ±0)` - // Minimum execution time: 280_047_000 picoseconds. - Weight::from_parts(270_065_882, 9217) - // Standard Error: 86 - .saturating_add(Weight::from_parts(34_361, 0).saturating_mul(c.into())) + // Minimum execution time: 294_976_000 picoseconds. + Weight::from_parts(277_235_948, 9217) + // Standard Error: 65 + .saturating_add(Weight::from_parts(34_445, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -2389,14 +2410,14 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `326` // Estimated: `8740` - // Minimum execution time: 3_776_071_000 picoseconds. - Weight::from_parts(706_212_213, 8740) - // Standard Error: 149 - .saturating_add(Weight::from_parts(98_798, 0).saturating_mul(c.into())) - // Standard Error: 17 - .saturating_add(Weight::from_parts(1_560, 0).saturating_mul(i.into())) - // Standard Error: 17 - .saturating_add(Weight::from_parts(1_476, 0).saturating_mul(s.into())) + // Minimum execution time: 3_864_558_000 picoseconds. + Weight::from_parts(421_676_889, 8740) + // Standard Error: 188 + .saturating_add(Weight::from_parts(103_788, 0).saturating_mul(c.into())) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_715, 0).saturating_mul(i.into())) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_774, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } @@ -2426,12 +2447,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `563` // Estimated: `8982` - // Minimum execution time: 1_966_301_000 picoseconds. - Weight::from_parts(376_287_434, 8982) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_643, 0).saturating_mul(i.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_667, 0).saturating_mul(s.into())) + // Minimum execution time: 2_069_276_000 picoseconds. + Weight::from_parts(377_210_279, 8982) + // Standard Error: 9 + .saturating_add(Weight::from_parts(1_719, 0).saturating_mul(i.into())) + // Standard Error: 9 + .saturating_add(Weight::from_parts(1_728, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -2455,8 +2476,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `829` // Estimated: `9244` - // Minimum execution time: 197_571_000 picoseconds. - Weight::from_parts(206_612_000, 9244) + // Minimum execution time: 199_037_000 picoseconds. + Weight::from_parts(213_931_000, 9244) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2473,14 +2494,38 @@ impl WeightInfo for () { /// Storage: `Contracts::PristineCode` (r:0 w:1) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) /// The range of component `c` is `[0, 125952]`. - fn upload_code(c: u32, ) -> Weight { + fn upload_code_determinism_enforced(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `145` // Estimated: `6085` - // Minimum execution time: 266_006_000 picoseconds. - Weight::from_parts(287_700_788, 6085) - // Standard Error: 67 - .saturating_add(Weight::from_parts(63_196, 0).saturating_mul(c.into())) + // Minimum execution time: 278_482_000 picoseconds. + Weight::from_parts(262_753_879, 6085) + // Standard Error: 112 + .saturating_add(Weight::from_parts(66_129, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) + } + /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) + /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) + /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) + /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Storage: `System::EventTopics` (r:1 w:1) + /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Contracts::PristineCode` (r:0 w:1) + /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) + /// The range of component `c` is `[0, 125952]`. + fn upload_code_determinism_relaxed(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `6085` + // Minimum execution time: 286_902_000 picoseconds. + Weight::from_parts(269_003_959, 6085) + // Standard Error: 123 + .saturating_add(Weight::from_parts(66_629, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2498,8 +2543,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 42_714_000 picoseconds. - Weight::from_parts(44_713_000, 3780) + // Minimum execution time: 44_128_000 picoseconds. + Weight::from_parts(46_044_000, 3780) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2515,8 +2560,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `552` // Estimated: `8967` - // Minimum execution time: 33_516_000 picoseconds. - Weight::from_parts(34_823_000, 8967) + // Minimum execution time: 33_567_000 picoseconds. + Weight::from_parts(35_057_000, 8967) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -2541,10 +2586,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `869 + r * (6 ±0)` // Estimated: `9284 + r * (6 ±0)` - // Minimum execution time: 246_563_000 picoseconds. - Weight::from_parts(274_999_814, 9284) - // Standard Error: 628 - .saturating_add(Weight::from_parts(347_395, 0).saturating_mul(r.into())) + // Minimum execution time: 272_376_000 picoseconds. + Weight::from_parts(284_162_161, 9284) + // Standard Error: 501 + .saturating_add(Weight::from_parts(341_575, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2570,10 +2615,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `925 + r * (209 ±0)` // Estimated: `9304 + r * (2684 ±0)` - // Minimum execution time: 252_236_000 picoseconds. - Weight::from_parts(121_390_081, 9304) - // Standard Error: 6_206 - .saturating_add(Weight::from_parts(3_558_718, 0).saturating_mul(r.into())) + // Minimum execution time: 256_990_000 picoseconds. + Weight::from_parts(107_167_044, 9304) + // Standard Error: 7_545 + .saturating_add(Weight::from_parts(3_628_112, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -2600,10 +2645,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `924 + r * (213 ±0)` // Estimated: `9308 + r * (2688 ±0)` - // Minimum execution time: 269_427_000 picoseconds. - Weight::from_parts(134_879_389, 9308) - // Standard Error: 6_711 - .saturating_add(Weight::from_parts(4_408_658, 0).saturating_mul(r.into())) + // Minimum execution time: 272_889_000 picoseconds. + Weight::from_parts(110_341_799, 9308) + // Standard Error: 7_881 + .saturating_add(Weight::from_parts(4_427_043, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -2630,10 +2675,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `876 + r * (6 ±0)` // Estimated: `9293 + r * (6 ±0)` - // Minimum execution time: 249_382_000 picoseconds. - Weight::from_parts(266_305_110, 9293) - // Standard Error: 1_592 - .saturating_add(Weight::from_parts(460_001, 0).saturating_mul(r.into())) + // Minimum execution time: 275_027_000 picoseconds. + Weight::from_parts(283_302_223, 9293) + // Standard Error: 1_179 + .saturating_add(Weight::from_parts(436_023, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2659,10 +2704,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866 + r * (3 ±0)` // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 252_145_000 picoseconds. - Weight::from_parts(277_211_668, 9282) - // Standard Error: 371 - .saturating_add(Weight::from_parts(174_394, 0).saturating_mul(r.into())) + // Minimum execution time: 270_137_000 picoseconds. + Weight::from_parts(282_756_362, 9282) + // Standard Error: 384 + .saturating_add(Weight::from_parts(171_660, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2686,10 +2731,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `756 + r * (3 ±0)` // Estimated: `9171 + r * (3 ±0)` - // Minimum execution time: 251_595_000 picoseconds. - Weight::from_parts(268_102_575, 9171) - // Standard Error: 334 - .saturating_add(Weight::from_parts(154_836, 0).saturating_mul(r.into())) + // Minimum execution time: 255_131_000 picoseconds. + Weight::from_parts(269_207_006, 9171) + // Standard Error: 542 + .saturating_add(Weight::from_parts(161_597, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(10_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2715,10 +2760,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `870 + r * (6 ±0)` // Estimated: `9285 + r * (6 ±0)` - // Minimum execution time: 251_404_000 picoseconds. - Weight::from_parts(278_747_574, 9285) - // Standard Error: 782 - .saturating_add(Weight::from_parts(341_598, 0).saturating_mul(r.into())) + // Minimum execution time: 272_172_000 picoseconds. + Weight::from_parts(283_747_134, 9285) + // Standard Error: 885 + .saturating_add(Weight::from_parts(343_968, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2744,10 +2789,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866 + r * (6 ±0)` // Estimated: `9284 + r * (6 ±0)` - // Minimum execution time: 255_649_000 picoseconds. - Weight::from_parts(276_509_641, 9284) - // Standard Error: 1_262 - .saturating_add(Weight::from_parts(380_225, 0).saturating_mul(r.into())) + // Minimum execution time: 263_220_000 picoseconds. + Weight::from_parts(277_062_382, 9284) + // Standard Error: 1_783 + .saturating_add(Weight::from_parts(399_631, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2773,10 +2818,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1010 + r * (6 ±0)` // Estimated: `9409 + r * (6 ±0)` - // Minimum execution time: 267_143_000 picoseconds. - Weight::from_parts(298_166_116, 9409) - // Standard Error: 3_765 - .saturating_add(Weight::from_parts(1_620_886, 0).saturating_mul(r.into())) + // Minimum execution time: 253_218_000 picoseconds. + Weight::from_parts(282_251_452, 9409) + // Standard Error: 2_367 + .saturating_add(Weight::from_parts(1_604_060, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2802,10 +2847,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `880 + r * (6 ±0)` // Estimated: `9301 + r * (6 ±0)` - // Minimum execution time: 250_013_000 picoseconds. - Weight::from_parts(281_469_583, 9301) - // Standard Error: 730 - .saturating_add(Weight::from_parts(339_260, 0).saturating_mul(r.into())) + // Minimum execution time: 271_797_000 picoseconds. + Weight::from_parts(288_594_393, 9301) + // Standard Error: 846 + .saturating_add(Weight::from_parts(335_063, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2831,10 +2876,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `878 + r * (6 ±0)` // Estimated: `9294 + r * (6 ±0)` - // Minimum execution time: 256_219_000 picoseconds. - Weight::from_parts(275_309_266, 9294) - // Standard Error: 1_199 - .saturating_add(Weight::from_parts(350_824, 0).saturating_mul(r.into())) + // Minimum execution time: 254_997_000 picoseconds. + Weight::from_parts(284_331_894, 9294) + // Standard Error: 885 + .saturating_add(Weight::from_parts(337_073, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2860,10 +2905,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `875 + r * (6 ±0)` // Estimated: `9297 + r * (6 ±0)` - // Minimum execution time: 264_644_000 picoseconds. - Weight::from_parts(283_856_744, 9297) - // Standard Error: 623 - .saturating_add(Weight::from_parts(334_175, 0).saturating_mul(r.into())) + // Minimum execution time: 273_845_000 picoseconds. + Weight::from_parts(285_291_242, 9297) + // Standard Error: 690 + .saturating_add(Weight::from_parts(332_783, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2889,10 +2934,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866 + r * (6 ±0)` // Estimated: `9282 + r * (6 ±0)` - // Minimum execution time: 263_364_000 picoseconds. - Weight::from_parts(281_379_508, 9282) - // Standard Error: 639 - .saturating_add(Weight::from_parts(338_021, 0).saturating_mul(r.into())) + // Minimum execution time: 268_302_000 picoseconds. + Weight::from_parts(280_463_257, 9282) + // Standard Error: 1_035 + .saturating_add(Weight::from_parts(345_811, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2920,10 +2965,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `940 + r * (14 ±0)` // Estimated: `9350 + r * (14 ±0)` - // Minimum execution time: 269_667_000 picoseconds. - Weight::from_parts(284_662_802, 9350) - // Standard Error: 691 - .saturating_add(Weight::from_parts(799_249, 0).saturating_mul(r.into())) + // Minimum execution time: 263_433_000 picoseconds. + Weight::from_parts(290_098_370, 9350) + // Standard Error: 1_905 + .saturating_add(Weight::from_parts(805_299, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 14).saturating_mul(r.into())) @@ -2949,10 +2994,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `868 + r * (6 ±0)` // Estimated: `9285 + r * (6 ±0)` - // Minimum execution time: 267_018_000 picoseconds. - Weight::from_parts(281_842_630, 9285) - // Standard Error: 453 - .saturating_add(Weight::from_parts(255_373, 0).saturating_mul(r.into())) + // Minimum execution time: 273_588_000 picoseconds. + Weight::from_parts(287_133_565, 9285) + // Standard Error: 799 + .saturating_add(Weight::from_parts(254_114, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2978,10 +3023,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `872` // Estimated: `9287` - // Minimum execution time: 258_208_000 picoseconds. - Weight::from_parts(227_686_792, 9287) - // Standard Error: 23 - .saturating_add(Weight::from_parts(989, 0).saturating_mul(n.into())) + // Minimum execution time: 257_843_000 picoseconds. + Weight::from_parts(228_177_495, 9287) + // Standard Error: 24 + .saturating_add(Weight::from_parts(985, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3006,8 +3051,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `856 + r * (45 ±0)` // Estimated: `9271 + r * (45 ±0)` - // Minimum execution time: 245_714_000 picoseconds. - Weight::from_parts(272_527_059, 9271) + // Minimum execution time: 248_332_000 picoseconds. + Weight::from_parts(274_998_906, 9271) + // Standard Error: 949_561 + .saturating_add(Weight::from_parts(5_570_693, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 45).saturating_mul(r.into())) @@ -3033,10 +3080,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866` // Estimated: `9288` - // Minimum execution time: 256_060_000 picoseconds. - Weight::from_parts(276_710_811, 9288) - // Standard Error: 0 - .saturating_add(Weight::from_parts(312, 0).saturating_mul(n.into())) + // Minimum execution time: 272_055_000 picoseconds. + Weight::from_parts(282_280_090, 9288) + // Standard Error: 1 + .saturating_add(Weight::from_parts(330, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3067,10 +3114,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2902 + r * (529 ±0)` // Estimated: `11317 + r * (5479 ±0)` - // Minimum execution time: 270_479_000 picoseconds. - Weight::from_parts(296_706_989, 11317) - // Standard Error: 813_407 - .saturating_add(Weight::from_parts(109_236_910, 0).saturating_mul(r.into())) + // Minimum execution time: 274_842_000 picoseconds. + Weight::from_parts(299_824_497, 11317) + // Standard Error: 902_686 + .saturating_add(Weight::from_parts(106_562_902, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3100,10 +3147,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `947 + r * (10 ±0)` // Estimated: `9363 + r * (10 ±0)` - // Minimum execution time: 251_787_000 picoseconds. - Weight::from_parts(284_036_313, 9363) - // Standard Error: 2_560 - .saturating_add(Weight::from_parts(1_238_301, 0).saturating_mul(r.into())) + // Minimum execution time: 255_393_000 picoseconds. + Weight::from_parts(309_814_338, 9363) + // Standard Error: 2_978 + .saturating_add(Weight::from_parts(1_203_507, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -3129,10 +3176,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866 + r * (10 ±0)` // Estimated: `9283 + r * (10 ±0)` - // Minimum execution time: 250_566_000 picoseconds. - Weight::from_parts(275_402_784, 9283) - // Standard Error: 3_939 - .saturating_add(Weight::from_parts(1_941_995, 0).saturating_mul(r.into())) + // Minimum execution time: 250_378_000 picoseconds. + Weight::from_parts(287_003_144, 9283) + // Standard Error: 2_726 + .saturating_add(Weight::from_parts(1_850_967, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -3159,12 +3206,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `883 + t * (32 ±0)` // Estimated: `9303 + t * (2508 ±0)` - // Minimum execution time: 267_544_000 picoseconds. - Weight::from_parts(280_117_825, 9303) - // Standard Error: 102_111 - .saturating_add(Weight::from_parts(3_253_038, 0).saturating_mul(t.into())) - // Standard Error: 28 - .saturating_add(Weight::from_parts(668, 0).saturating_mul(n.into())) + // Minimum execution time: 266_787_000 picoseconds. + Weight::from_parts(284_368_661, 9303) + // Standard Error: 121_315 + .saturating_add(Weight::from_parts(2_690_211, 0).saturating_mul(t.into())) + // Standard Error: 33 + .saturating_add(Weight::from_parts(789, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3192,10 +3239,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `865 + r * (7 ±0)` // Estimated: `9285 + r * (7 ±0)` - // Minimum execution time: 157_769_000 picoseconds. - Weight::from_parts(173_026_565, 9285) - // Standard Error: 405 - .saturating_add(Weight::from_parts(219_727, 0).saturating_mul(r.into())) + // Minimum execution time: 166_804_000 picoseconds. + Weight::from_parts(175_118_291, 9285) + // Standard Error: 398 + .saturating_add(Weight::from_parts(220_961, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) @@ -3221,10 +3268,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `125816` // Estimated: `131758` - // Minimum execution time: 403_961_000 picoseconds. - Weight::from_parts(376_480_872, 131758) + // Minimum execution time: 398_436_000 picoseconds. + Weight::from_parts(385_003_285, 131758) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_041, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(1_038, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3235,10 +3282,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `927 + r * (292 ±0)` // Estimated: `929 + r * (293 ±0)` - // Minimum execution time: 256_272_000 picoseconds. - Weight::from_parts(181_058_379, 929) - // Standard Error: 9_838 - .saturating_add(Weight::from_parts(6_316_677, 0).saturating_mul(r.into())) + // Minimum execution time: 274_099_000 picoseconds. + Weight::from_parts(174_282_817, 929) + // Standard Error: 10_547 + .saturating_add(Weight::from_parts(6_262_173, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3252,10 +3299,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1450` // Estimated: `1433` - // Minimum execution time: 268_713_000 picoseconds. - Weight::from_parts(328_329_131, 1433) + // Minimum execution time: 274_061_000 picoseconds. + Weight::from_parts(334_755_333, 1433) // Standard Error: 66 - .saturating_add(Weight::from_parts(962, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(771, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(15_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } @@ -3266,10 +3313,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1256 + n * (1 ±0)` // Estimated: `1256 + n * (1 ±0)` - // Minimum execution time: 265_683_000 picoseconds. - Weight::from_parts(293_784_477, 1256) - // Standard Error: 31 - .saturating_add(Weight::from_parts(377, 0).saturating_mul(n.into())) + // Minimum execution time: 272_657_000 picoseconds. + Weight::from_parts(299_061_594, 1256) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3281,10 +3326,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `924 + r * (288 ±0)` // Estimated: `930 + r * (289 ±0)` - // Minimum execution time: 269_959_000 picoseconds. - Weight::from_parts(186_065_911, 930) - // Standard Error: 9_679 - .saturating_add(Weight::from_parts(6_286_855, 0).saturating_mul(r.into())) + // Minimum execution time: 270_524_000 picoseconds. + Weight::from_parts(177_959_667, 930) + // Standard Error: 10_397 + .saturating_add(Weight::from_parts(6_270_181, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3298,8 +3343,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1252 + n * (1 ±0)` // Estimated: `1252 + n * (1 ±0)` - // Minimum execution time: 265_805_000 picoseconds. - Weight::from_parts(294_633_695, 1252) + // Minimum execution time: 270_757_000 picoseconds. + Weight::from_parts(298_627_896, 1252) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3311,10 +3356,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `924 + r * (296 ±0)` // Estimated: `926 + r * (297 ±0)` - // Minimum execution time: 264_592_000 picoseconds. - Weight::from_parts(204_670_461, 926) - // Standard Error: 6_869 - .saturating_add(Weight::from_parts(5_137_920, 0).saturating_mul(r.into())) + // Minimum execution time: 268_082_000 picoseconds. + Weight::from_parts(202_583_730, 926) + // Standard Error: 9_029 + .saturating_add(Weight::from_parts(5_028_517, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3327,10 +3372,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1268 + n * (1 ±0)` // Estimated: `1268 + n * (1 ±0)` - // Minimum execution time: 273_165_000 picoseconds. - Weight::from_parts(297_883_669, 1268) - // Standard Error: 37 - .saturating_add(Weight::from_parts(576, 0).saturating_mul(n.into())) + // Minimum execution time: 274_100_000 picoseconds. + Weight::from_parts(296_981_515, 1268) + // Standard Error: 34 + .saturating_add(Weight::from_parts(578, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3342,10 +3387,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `935 + r * (288 ±0)` // Estimated: `932 + r * (289 ±0)` - // Minimum execution time: 252_257_000 picoseconds. - Weight::from_parts(205_018_595, 932) - // Standard Error: 7_605 - .saturating_add(Weight::from_parts(4_933_378, 0).saturating_mul(r.into())) + // Minimum execution time: 269_697_000 picoseconds. + Weight::from_parts(198_346_516, 932) + // Standard Error: 8_623 + .saturating_add(Weight::from_parts(4_964_116, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3358,10 +3403,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1255 + n * (1 ±0)` // Estimated: `1255 + n * (1 ±0)` - // Minimum execution time: 266_839_000 picoseconds. - Weight::from_parts(292_064_487, 1255) - // Standard Error: 34 - .saturating_add(Weight::from_parts(194, 0).saturating_mul(n.into())) + // Minimum execution time: 264_210_000 picoseconds. + Weight::from_parts(291_387_652, 1255) + // Standard Error: 36 + .saturating_add(Weight::from_parts(524, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3373,10 +3418,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `917 + r * (296 ±0)` // Estimated: `922 + r * (297 ±0)` - // Minimum execution time: 266_072_000 picoseconds. - Weight::from_parts(189_018_352, 922) - // Standard Error: 9_530 - .saturating_add(Weight::from_parts(6_481_011, 0).saturating_mul(r.into())) + // Minimum execution time: 267_219_000 picoseconds. + Weight::from_parts(175_866_982, 922) + // Standard Error: 11_275 + .saturating_add(Weight::from_parts(6_424_755, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3390,10 +3435,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1269 + n * (1 ±0)` // Estimated: `1269 + n * (1 ±0)` - // Minimum execution time: 270_703_000 picoseconds. - Weight::from_parts(292_867_105, 1269) - // Standard Error: 30 - .saturating_add(Weight::from_parts(800, 0).saturating_mul(n.into())) + // Minimum execution time: 274_634_000 picoseconds. + Weight::from_parts(294_272_009, 1269) + // Standard Error: 36 + .saturating_add(Weight::from_parts(1_219, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3419,10 +3464,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1418 + r * (45 ±0)` // Estimated: `9785 + r * (2520 ±0)` - // Minimum execution time: 251_843_000 picoseconds. - Weight::from_parts(181_026_888, 9785) - // Standard Error: 38_221 - .saturating_add(Weight::from_parts(30_626_681, 0).saturating_mul(r.into())) + // Minimum execution time: 266_833_000 picoseconds. + Weight::from_parts(186_049_741, 9785) + // Standard Error: 40_311 + .saturating_add(Weight::from_parts(31_365_585, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) @@ -3450,10 +3495,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1263 + r * (245 ±0)` // Estimated: `9635 + r * (2721 ±0)` - // Minimum execution time: 254_881_000 picoseconds. - Weight::from_parts(272_871_000, 9635) - // Standard Error: 94_527 - .saturating_add(Weight::from_parts(233_379_497, 0).saturating_mul(r.into())) + // Minimum execution time: 272_140_000 picoseconds. + Weight::from_parts(275_009_000, 9635) + // Standard Error: 99_187 + .saturating_add(Weight::from_parts(240_702_479, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) @@ -3480,11 +3525,11 @@ impl WeightInfo for () { fn seal_delegate_call(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + r * (576 ±0)` - // Estimated: `9290 + r * (2637 ±3)` - // Minimum execution time: 266_704_000 picoseconds. - Weight::from_parts(273_165_000, 9290) - // Standard Error: 141_486 - .saturating_add(Weight::from_parts(232_947_049, 0).saturating_mul(r.into())) + // Estimated: `9290 + r * (2637 ±10)` + // Minimum execution time: 263_664_000 picoseconds. + Weight::from_parts(277_240_000, 9290) + // Standard Error: 169_147 + .saturating_add(Weight::from_parts(240_084_929, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3513,12 +3558,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1310 + t * (277 ±0)` // Estimated: `12200 + t * (5227 ±0)` - // Minimum execution time: 446_451_000 picoseconds. - Weight::from_parts(68_175_222, 12200) - // Standard Error: 11_619_250 - .saturating_add(Weight::from_parts(354_237_260, 0).saturating_mul(t.into())) + // Minimum execution time: 464_644_000 picoseconds. + Weight::from_parts(40_377_313, 12200) + // Standard Error: 12_060_226 + .saturating_add(Weight::from_parts(380_635_982, 0).saturating_mul(t.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(987, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_014, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(16_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) @@ -3550,10 +3595,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1281 + r * (255 ±0)` // Estimated: `9623 + r * (2731 ±0)` - // Minimum execution time: 628_156_000 picoseconds. - Weight::from_parts(642_052_000, 9623) - // Standard Error: 223_957 - .saturating_add(Weight::from_parts(348_660_264, 0).saturating_mul(r.into())) + // Minimum execution time: 641_845_000 picoseconds. + Weight::from_parts(649_908_000, 9623) + // Standard Error: 278_514 + .saturating_add(Weight::from_parts(361_164_598, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().reads((6_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(7_u64)) @@ -3587,14 +3632,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1306 + t * (104 ±0)` // Estimated: `12214 + t * (2549 ±1)` - // Minimum execution time: 2_106_379_000 picoseconds. - Weight::from_parts(1_098_227_098, 12214) - // Standard Error: 12_549_729 - .saturating_add(Weight::from_parts(21_628_382, 0).saturating_mul(t.into())) - // Standard Error: 19 - .saturating_add(Weight::from_parts(1_059, 0).saturating_mul(i.into())) - // Standard Error: 19 - .saturating_add(Weight::from_parts(1_220, 0).saturating_mul(s.into())) + // Minimum execution time: 2_111_632_000 picoseconds. + Weight::from_parts(1_213_125_745, 12214) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_055, 0).saturating_mul(i.into())) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_192, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(19_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(11_u64)) @@ -3622,10 +3665,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `865 + r * (8 ±0)` // Estimated: `9279 + r * (8 ±0)` - // Minimum execution time: 257_102_000 picoseconds. - Weight::from_parts(278_920_692, 9279) - // Standard Error: 464 - .saturating_add(Weight::from_parts(374_120, 0).saturating_mul(r.into())) + // Minimum execution time: 264_227_000 picoseconds. + Weight::from_parts(281_015_995, 9279) + // Standard Error: 710 + .saturating_add(Weight::from_parts(365_734, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3651,10 +3694,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `873` // Estimated: `9286` - // Minimum execution time: 266_609_000 picoseconds. - Weight::from_parts(263_034_132, 9286) + // Minimum execution time: 270_709_000 picoseconds. + Weight::from_parts(268_416_051, 9286) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_082, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_080, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3679,10 +3722,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9284 + r * (8 ±0)` - // Minimum execution time: 246_275_000 picoseconds. - Weight::from_parts(279_091_594, 9284) - // Standard Error: 887 - .saturating_add(Weight::from_parts(810_394, 0).saturating_mul(r.into())) + // Minimum execution time: 267_283_000 picoseconds. + Weight::from_parts(280_706_659, 9284) + // Standard Error: 540 + .saturating_add(Weight::from_parts(790_312, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3708,10 +3751,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9292` - // Minimum execution time: 249_254_000 picoseconds. - Weight::from_parts(270_833_823, 9292) - // Standard Error: 0 - .saturating_add(Weight::from_parts(3_347, 0).saturating_mul(n.into())) + // Minimum execution time: 262_010_000 picoseconds. + Weight::from_parts(273_278_744, 9292) + // Standard Error: 1 + .saturating_add(Weight::from_parts(3_362, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3736,10 +3779,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9286 + r * (8 ±0)` - // Minimum execution time: 259_131_000 picoseconds. - Weight::from_parts(272_665_020, 9286) - // Standard Error: 862 - .saturating_add(Weight::from_parts(451_247, 0).saturating_mul(r.into())) + // Minimum execution time: 268_698_000 picoseconds. + Weight::from_parts(282_890_578, 9286) + // Standard Error: 622 + .saturating_add(Weight::from_parts(441_131, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3765,10 +3808,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9291` - // Minimum execution time: 276_465_000 picoseconds. - Weight::from_parts(269_450_297, 9291) + // Minimum execution time: 252_846_000 picoseconds. + Weight::from_parts(267_657_561, 9291) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_190, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_208, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3793,10 +3836,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9283 + r * (8 ±0)` - // Minimum execution time: 248_349_000 picoseconds. - Weight::from_parts(273_660_686, 9283) - // Standard Error: 656 - .saturating_add(Weight::from_parts(444_293, 0).saturating_mul(r.into())) + // Minimum execution time: 266_899_000 picoseconds. + Weight::from_parts(276_862_067, 9283) + // Standard Error: 1_249 + .saturating_add(Weight::from_parts(443_970, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3822,10 +3865,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9289` - // Minimum execution time: 252_107_000 picoseconds. - Weight::from_parts(267_427_726, 9289) + // Minimum execution time: 265_413_000 picoseconds. + Weight::from_parts(265_600_840, 9289) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_199, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_203, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3850,10 +3893,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1000 + n * (1 ±0)` // Estimated: `9412 + n * (1 ±0)` - // Minimum execution time: 311_252_000 picoseconds. - Weight::from_parts(333_250_773, 9412) - // Standard Error: 12 - .saturating_add(Weight::from_parts(5_668, 0).saturating_mul(n.into())) + // Minimum execution time: 328_341_000 picoseconds. + Weight::from_parts(341_038_581, 9412) + // Standard Error: 10 + .saturating_add(Weight::from_parts(5_863, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3877,12 +3920,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 160]`. fn seal_sr25519_verify(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `810 + r * (112 ±0)` + // Measured: `808 + r * (112 ±0)` // Estimated: `9226 + r * (112 ±0)` - // Minimum execution time: 267_431_000 picoseconds. - Weight::from_parts(300_733_048, 9226) - // Standard Error: 8_806 - .saturating_add(Weight::from_parts(42_169_197, 0).saturating_mul(r.into())) + // Minimum execution time: 272_730_000 picoseconds. + Weight::from_parts(339_349_232, 9226) + // Standard Error: 13_004 + .saturating_add(Weight::from_parts(41_649_026, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(r.into())) @@ -3908,10 +3951,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `910 + r * (76 ±0)` // Estimated: `9279 + r * (77 ±0)` - // Minimum execution time: 265_905_000 picoseconds. - Weight::from_parts(305_381_951, 9279) - // Standard Error: 9_863 - .saturating_add(Weight::from_parts(45_771_182, 0).saturating_mul(r.into())) + // Minimum execution time: 273_892_000 picoseconds. + Weight::from_parts(352_853_960, 9279) + // Standard Error: 16_745 + .saturating_add(Weight::from_parts(45_853_294, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 77).saturating_mul(r.into())) @@ -3937,10 +3980,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `880 + r * (42 ±0)` // Estimated: `9294 + r * (42 ±0)` - // Minimum execution time: 266_701_000 picoseconds. - Weight::from_parts(292_407_888, 9294) - // Standard Error: 5_394 - .saturating_add(Weight::from_parts(11_896_065, 0).saturating_mul(r.into())) + // Minimum execution time: 268_431_000 picoseconds. + Weight::from_parts(319_727_796, 9294) + // Standard Error: 10_276 + .saturating_add(Weight::from_parts(11_928_882, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(r.into())) @@ -3966,10 +4009,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + r * (965 ±0)` // Estimated: `9285 + r * (3090 ±7)` - // Minimum execution time: 268_755_000 picoseconds. - Weight::from_parts(272_300_000, 9285) - // Standard Error: 43_747 - .saturating_add(Weight::from_parts(25_001_889, 0).saturating_mul(r.into())) + // Minimum execution time: 275_482_000 picoseconds. + Weight::from_parts(279_155_000, 9285) + // Standard Error: 65_388 + .saturating_add(Weight::from_parts(26_634_187, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3997,10 +4040,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `937 + r * (131 ±0)` // Estimated: `9346 + r * (2607 ±0)` - // Minimum execution time: 255_190_000 picoseconds. - Weight::from_parts(285_643_922, 9346) - // Standard Error: 23_582 - .saturating_add(Weight::from_parts(6_289_940, 0).saturating_mul(r.into())) + // Minimum execution time: 270_001_000 picoseconds. + Weight::from_parts(286_792_689, 9346) + // Standard Error: 21_074 + .saturating_add(Weight::from_parts(6_465_885, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -4028,10 +4071,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `972 + r * (184 ±0)` // Estimated: `129453 + r * (2568 ±0)` - // Minimum execution time: 260_061_000 picoseconds. - Weight::from_parts(286_849_343, 129453) - // Standard Error: 22_406 - .saturating_add(Weight::from_parts(5_661_459, 0).saturating_mul(r.into())) + // Minimum execution time: 270_652_000 picoseconds. + Weight::from_parts(293_369_452, 129453) + // Standard Error: 24_321 + .saturating_add(Weight::from_parts(5_575_600, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -4059,10 +4102,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `861 + r * (3 ±0)` // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 250_922_000 picoseconds. - Weight::from_parts(277_294_913, 9282) - // Standard Error: 391 - .saturating_add(Weight::from_parts(169_457, 0).saturating_mul(r.into())) + // Minimum execution time: 267_749_000 picoseconds. + Weight::from_parts(280_373_341, 9282) + // Standard Error: 464 + .saturating_add(Weight::from_parts(170_398, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -4088,10 +4131,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2112 + r * (39 ±0)` // Estimated: `10377 + r * (40 ±0)` - // Minimum execution time: 267_293_000 picoseconds. - Weight::from_parts(309_125_635, 10377) - // Standard Error: 637 - .saturating_add(Weight::from_parts(245_508, 0).saturating_mul(r.into())) + // Minimum execution time: 270_260_000 picoseconds. + Weight::from_parts(337_969_172, 10377) + // Standard Error: 1_557 + .saturating_add(Weight::from_parts(305_735, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 40).saturating_mul(r.into())) @@ -4119,10 +4162,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `864 + r * (3 ±0)` // Estimated: `9279 + r * (3 ±0)` - // Minimum execution time: 256_057_000 picoseconds. - Weight::from_parts(278_068_870, 9279) - // Standard Error: 335 - .saturating_add(Weight::from_parts(152_083, 0).saturating_mul(r.into())) + // Minimum execution time: 265_607_000 picoseconds. + Weight::from_parts(283_396_630, 9279) + // Standard Error: 449 + .saturating_add(Weight::from_parts(149_018, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -4132,9 +4175,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_846_000 picoseconds. - Weight::from_parts(1_808_029, 0) - // Standard Error: 9 - .saturating_add(Weight::from_parts(14_937, 0).saturating_mul(r.into())) + // Minimum execution time: 1_813_000 picoseconds. + Weight::from_parts(1_264_945, 0) + // Standard Error: 19 + .saturating_add(Weight::from_parts(15_098, 0).saturating_mul(r.into())) } } -- GitLab From 117a9433dac88d5ac00c058c9b39c511d47749d2 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 6 Mar 2024 22:44:03 +0100 Subject: [PATCH 080/188] Make `penpal-runtime`'s `TrustedReserves` more connfigurable (#3564) The current `penpal` runtime utilizes the `EthereumLocation` parameter, which is employed for XCM emulated integration tests concerning the Rococo <> ETH bridge. It includes a hard-coded chainId for the Ethereum testnet utilized in Rococo. The `EthereumLocation` serves the purpose of aligning with the `TrustedReserves`. However, due to this hard-coded configuration, reusing `penpal` for testing various environments such as Kusama/Polkadot versus Ethereum bridge becomes unfeasible. This PR introduces the capability to easily customize the asset location for `TrustedReserves` without needing to know anything about Ethereum. ## TODO - [x] fix integration tests with `System::set_storage(CustomizableAssetFromSystemAssetHub::key(), )` @claravanstaden - [ ] ~~maybe add some helper function/macro to support `set_storage` for other runtimes (that we could reuse)~~ - [ ] Release patch for: `penpal-runtime` + emulated crate with `set_storage` support (if needed) - [ ] backport to 1.7.0 - [ ] backport to 1.8.0 --------- Co-authored-by: Clara van Staden --- Cargo.lock | 1 - .../chains/parachains/testing/penpal/src/lib.rs | 3 ++- .../bridge-hub-rococo/src/tests/snowbridge.rs | 11 +++++++++++ .../parachains/runtimes/testing/penpal/Cargo.toml | 2 -- .../runtimes/testing/penpal/src/xcm_config.rs | 15 ++++++++++----- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26e134448ff..fbd347c5fde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11754,7 +11754,6 @@ dependencies = [ "staging-xcm-builder", "staging-xcm-executor", "substrate-wasm-builder", - "testnet-parachains-constants", ] [[package]] diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs index 8f586a46a75..c1e03046655 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs @@ -16,7 +16,8 @@ mod genesis; pub use genesis::{genesis, ED, PARA_ID_A, PARA_ID_B}; pub use penpal_runtime::xcm_config::{ - LocalTeleportableToAssetHub, LocalTeleportableToAssetHubV3, XcmConfig, + CustomizableAssetFromSystemAssetHub, LocalTeleportableToAssetHub, + LocalTeleportableToAssetHubV3, XcmConfig, }; // Substrate diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index a5957ee3393..ff069e2d344 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -18,6 +18,7 @@ use codec::{Decode, Encode}; use emulated_integration_tests_common::xcm_emulator::ConvertLocation; use frame_support::pallet_prelude::TypeInfo; use hex_literal::hex; +use rococo_system_emulated_network::penpal_emulated_chain::CustomizableAssetFromSystemAssetHub; use rococo_westend_system_emulated_network::BridgeHubRococoParaSender as BridgeHubRococoSender; use snowbridge_core::outbound::OperatingMode; use snowbridge_pallet_inbound_queue_fixtures::{ @@ -253,6 +254,16 @@ fn send_token_from_ethereum_to_penpal() { (PenpalASender::get(), INITIAL_FUND), ]); + PenpalA::execute_with(|| { + assert_ok!(::System::set_storage( + ::RuntimeOrigin::root(), + vec![( + CustomizableAssetFromSystemAssetHub::key().to_vec(), + Location::new(2, [GlobalConsensus(Ethereum { chain_id: CHAIN_ID })]).encode(), + )], + )); + }); + // The Weth asset location, identified by the contract address on Ethereum let weth_asset_location: Location = (Parent, Parent, EthereumNetwork::get(), AccountKey20 { network: None, key: WETH }).into(); diff --git a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml index bca6aca051f..5a8b15740e4 100644 --- a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml @@ -77,7 +77,6 @@ cumulus-primitives-utility = { path = "../../../../primitives/utility", default- pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false } parachain-info = { package = "staging-parachain-info", path = "../../../pallets/parachain-info", default-features = false } parachains-common = { path = "../../../common", default-features = false } -testnet-parachains-constants = { path = "../../constants", default-features = false, features = ["rococo"] } assets-common = { path = "../../assets/common", default-features = false } [features] @@ -133,7 +132,6 @@ std = [ "sp-transaction-pool/std", "sp-version/std", "substrate-wasm-builder", - "testnet-parachains-constants/std", "xcm-builder/std", "xcm-executor/std", "xcm/std", diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index ef4f466d484..84b8fd9bb0a 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -43,7 +43,6 @@ use pallet_xcm::XcmPassthrough; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; -use testnet_parachains_constants::rococo::snowbridge::EthereumNetwork; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, @@ -295,7 +294,13 @@ parameter_types! { 0, [xcm::v3::Junction::PalletInstance(50), xcm::v3::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into())] ); - pub EthereumLocation: Location = Location::new(2, [GlobalConsensus(EthereumNetwork::get())]); + + /// The Penpal runtime is utilized for testing with various environment setups. + /// This storage item provides the opportunity to customize testing scenarios + /// by configuring the trusted asset from the `SystemAssetHub`. + /// + /// By default, it is configured as a `SystemAssetHubLocation` and can be modified using `System::set_storage`. + pub storage CustomizableAssetFromSystemAssetHub: Location = SystemAssetHubLocation::get(); } /// Accepts asset with ID `AssetLocation` and is coming from `Origin` chain. @@ -310,11 +315,11 @@ impl, Origin: Get> ContainsPair, NativeAssetFrom, - AssetPrefixFrom, + AssetPrefixFrom, ); pub type TrustedTeleporters = (AssetFromChain,); @@ -326,7 +331,7 @@ impl xcm_executor::Config for XcmConfig { // How to withdraw and deposit an asset. type AssetTransactor = AssetTransactors; type OriginConverter = XcmOriginToTransactDispatchOrigin; - type IsReserve = Reserves; + type IsReserve = TrustedReserves; // no teleport trust established with other chains type IsTeleporter = TrustedTeleporters; type UniversalLocation = UniversalLocation; -- GitLab From 4ae7398818c4c49bec9b4185943cf01cbfb00144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Thu, 7 Mar 2024 09:05:04 +0800 Subject: [PATCH 081/188] contracts: Remove wat support from test fixtures (#3588) In order to prepare for PolkaVM support I removed the wat support from our test fixture crate. - Removed redundant tests (invalid module checks are already inside the prepare module where they belong - Converted the gas_sync tests to Rust - Moved the start function test to the `wasm` module --- Cargo.lock | 1 - substrate/frame/contracts/fixtures/Cargo.toml | 1 - ...tract_no_call.rs => caller_is_origin_n.rs} | 17 +- .../data/invalid_contract_no_memory.wat | 5 - .../fixtures/data/invalid_module.wat | 8 - .../fixtures/data/run_out_of_gas_start_fn.wat | 10 -- .../fixtures/data/seal_input_noop.wat | 14 -- .../fixtures/data/seal_input_once.wat | 22 --- .../fixtures/data/seal_input_twice.wat | 28 --- substrate/frame/contracts/fixtures/src/lib.rs | 41 +---- substrate/frame/contracts/src/tests.rs | 167 ++---------------- substrate/frame/contracts/src/wasm/mod.rs | 18 ++ 12 files changed, 49 insertions(+), 283 deletions(-) rename substrate/frame/contracts/fixtures/contracts/{invalid_contract_no_call.rs => caller_is_origin_n.rs} (74%) delete mode 100644 substrate/frame/contracts/fixtures/data/invalid_contract_no_memory.wat delete mode 100644 substrate/frame/contracts/fixtures/data/invalid_module.wat delete mode 100644 substrate/frame/contracts/fixtures/data/run_out_of_gas_start_fn.wat delete mode 100644 substrate/frame/contracts/fixtures/data/seal_input_noop.wat delete mode 100644 substrate/frame/contracts/fixtures/data/seal_input_once.wat delete mode 100644 substrate/frame/contracts/fixtures/data/seal_input_twice.wat diff --git a/Cargo.lock b/Cargo.lock index fbd347c5fde..177d76b8706 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9634,7 +9634,6 @@ dependencies = [ "tempfile", "toml 0.8.8", "twox-hash", - "wat", ] [[package]] diff --git a/substrate/frame/contracts/fixtures/Cargo.toml b/substrate/frame/contracts/fixtures/Cargo.toml index 7fdf56a91fc..9ca9e404c31 100644 --- a/substrate/frame/contracts/fixtures/Cargo.toml +++ b/substrate/frame/contracts/fixtures/Cargo.toml @@ -11,7 +11,6 @@ description = "Fixtures for testing contracts pallet." workspace = true [dependencies] -wat = "1" frame-system = { path = "../../system" } sp-runtime = { path = "../../../primitives/runtime" } anyhow = "1.0.0" diff --git a/substrate/frame/contracts/fixtures/contracts/invalid_contract_no_call.rs b/substrate/frame/contracts/fixtures/contracts/caller_is_origin_n.rs similarity index 74% rename from substrate/frame/contracts/fixtures/contracts/invalid_contract_no_call.rs rename to substrate/frame/contracts/fixtures/contracts/caller_is_origin_n.rs index 13af3eb22b1..fd6f59802fa 100644 --- a/substrate/frame/contracts/fixtures/contracts/invalid_contract_no_call.rs +++ b/substrate/frame/contracts/fixtures/contracts/caller_is_origin_n.rs @@ -14,12 +14,25 @@ // 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. -//! Valid module but missing the call function + +//! This fixture calls caller_is_origin `n` times. + #![no_std] #![no_main] -extern crate common; +use common::input; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + input!(n: u32, ); + + for _ in 0..n { + let _ = api::caller_is_origin(); + } +} diff --git a/substrate/frame/contracts/fixtures/data/invalid_contract_no_memory.wat b/substrate/frame/contracts/fixtures/data/invalid_contract_no_memory.wat deleted file mode 100644 index 0aeefbcb7eb..00000000000 --- a/substrate/frame/contracts/fixtures/data/invalid_contract_no_memory.wat +++ /dev/null @@ -1,5 +0,0 @@ -;; A valid contract which does nothing at all -(module - (func (export "deploy")) - (func (export "call")) -) diff --git a/substrate/frame/contracts/fixtures/data/invalid_module.wat b/substrate/frame/contracts/fixtures/data/invalid_module.wat deleted file mode 100644 index e4a72f74273..00000000000 --- a/substrate/frame/contracts/fixtures/data/invalid_module.wat +++ /dev/null @@ -1,8 +0,0 @@ -;; An invalid module -(module - (func (export "deploy")) - (func (export "call") - ;; imbalanced stack - (i32.const 7) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/run_out_of_gas_start_fn.wat b/substrate/frame/contracts/fixtures/data/run_out_of_gas_start_fn.wat deleted file mode 100644 index 6591d7ede78..00000000000 --- a/substrate/frame/contracts/fixtures/data/run_out_of_gas_start_fn.wat +++ /dev/null @@ -1,10 +0,0 @@ -(module - (import "env" "memory" (memory 1 1)) - (start $start) - (func $start - (loop $inf (br $inf)) ;; just run out of gas - (unreachable) - ) - (func (export "call")) - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/seal_input_noop.wat b/substrate/frame/contracts/fixtures/data/seal_input_noop.wat deleted file mode 100644 index 7b5a1e32af4..00000000000 --- a/substrate/frame/contracts/fixtures/data/seal_input_noop.wat +++ /dev/null @@ -1,14 +0,0 @@ -;; Everything prepared for the host function call, but no call is performed. -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) buffer to write input - - ;; [8, 12) size of the input buffer - (data (i32.const 8) "\04") - - (func (export "call")) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/seal_input_once.wat b/substrate/frame/contracts/fixtures/data/seal_input_once.wat deleted file mode 100644 index 919a03a9b69..00000000000 --- a/substrate/frame/contracts/fixtures/data/seal_input_once.wat +++ /dev/null @@ -1,22 +0,0 @@ -;; Stores a value of the passed size. The host function is called once. -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) buffer to write input - - ;; [8, 12) size of the input buffer - (data (i32.const 8) "\04") - - (func (export "call") - ;; instructions to consume engine fuel - (drop - (i32.const 42) - ) - - (call $seal_input (i32.const 0) (i32.const 8)) - - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/seal_input_twice.wat b/substrate/frame/contracts/fixtures/data/seal_input_twice.wat deleted file mode 100644 index 3a8be814efb..00000000000 --- a/substrate/frame/contracts/fixtures/data/seal_input_twice.wat +++ /dev/null @@ -1,28 +0,0 @@ -;; Stores a value of the passed size. The host function is called twice. -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) buffer to write input - - ;; [8, 12) size of the input buffer - (data (i32.const 8) "\04") - - (func (export "call") - ;; instructions to consume engine fuel - (drop - (i32.const 42) - ) - - (call $seal_input (i32.const 0) (i32.const 8)) - - ;; instructions to consume engine fuel - (drop - (i32.const 42) - ) - - (call $seal_input (i32.const 0) (i32.const 8)) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/src/lib.rs b/substrate/frame/contracts/fixtures/src/lib.rs index e0d9d4f8bd5..56a8e2321c5 100644 --- a/substrate/frame/contracts/fixtures/src/lib.rs +++ b/substrate/frame/contracts/fixtures/src/lib.rs @@ -16,34 +16,7 @@ // limitations under the License. use sp_runtime::traits::Hash; -use std::{env::var, fs, path::PathBuf}; - -fn wat_root_dir() -> PathBuf { - match (var("CARGO_MANIFEST_DIR"), var("CARGO_PKG_NAME")) { - // When `CARGO_MANIFEST_DIR` is not set, Rust resolves relative paths from the root folder - (Err(_), _) => "substrate/frame/contracts/fixtures/data".into(), - (Ok(path), Ok(s)) if s == "pallet-contracts" => PathBuf::from(path).join("fixtures/data"), - (Ok(path), Ok(s)) if s == "pallet-contracts-mock-network" => - PathBuf::from(path).parent().unwrap().join("fixtures/data"), - (Ok(_), pkg_name) => panic!("Failed to resolve fixture dir for tests from {pkg_name:?}."), - } -} - -/// Load a given wasm module represented by a .wat file and returns a wasm binary contents along -/// with it's hash. -/// -/// The fixture files are located under the `fixtures/` directory. -fn legacy_compile_module( - fixture_name: &str, -) -> anyhow::Result<(Vec, ::Output)> -where - T: frame_system::Config, -{ - let fixture_path = wat_root_dir().join(format!("{fixture_name}.wat")); - let wasm_binary = wat::parse_file(fixture_path)?; - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) -} +use std::{fs, path::PathBuf}; /// Load a given wasm module and returns a wasm binary contents along with it's hash. /// Use the legacy compile_module as fallback, if the rust fixture does not exist yet. @@ -53,15 +26,11 @@ pub fn compile_module( where T: frame_system::Config, { - let out_dir: std::path::PathBuf = env!("OUT_DIR").into(); + let out_dir: PathBuf = env!("OUT_DIR").into(); let fixture_path = out_dir.join(format!("{fixture_name}.wasm")); - match fs::read(fixture_path) { - Ok(wasm_binary) => { - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) - }, - Err(_) => legacy_compile_module::(fixture_name), - } + let binary = fs::read(fixture_path)?; + let code_hash = T::Hashing::hash(&binary); + Ok((binary, code_hash)) } #[cfg(test)] diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index 011b2b25b2b..4c1f65e28d5 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -852,27 +852,6 @@ fn deposit_event_max_value_limit() { }); } -// Fail out of fuel (ref_time weight) inside the start function. -#[test] -fn run_out_of_fuel_start_fun() { - let (wasm, _code_hash) = compile_module::("run_out_of_gas_start_fn").unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let _ = ::Currency::set_balance(&ALICE, 1_000_000); - assert_err_ignore_postinfo!( - Contracts::instantiate_with_code( - RuntimeOrigin::signed(ALICE), - 0, - Weight::from_parts(1_000_000_000_000, u64::MAX), - None, - wasm, - vec![], - vec![], - ), - Error::::OutOfGas, - ); - }); -} - // Fail out of fuel (ref_time weight) in the engine. #[test] fn run_out_of_fuel_engine() { @@ -956,50 +935,15 @@ fn run_out_of_fuel_host() { #[test] fn gas_syncs_work() { - let (wasm0, _code_hash) = compile_module::("seal_input_noop").unwrap(); - let (wasm1, _code_hash) = compile_module::("seal_input_once").unwrap(); - let (wasm2, _code_hash) = compile_module::("seal_input_twice").unwrap(); + let (code, _code_hash) = compile_module::("caller_is_origin_n").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 1_000_000); - // Instantiate noop contract. - let addr0 = Contracts::bare_instantiate( - ALICE, - 0, - GAS_LIMIT, - None, - Code::Upload(wasm0), - vec![], - vec![], - DebugInfo::Skip, - CollectEvents::Skip, - ) - .result - .unwrap() - .account_id; - - // Instantiate 1st contract. - let addr1 = Contracts::bare_instantiate( - ALICE, - 0, - GAS_LIMIT, - None, - Code::Upload(wasm1), - vec![], - vec![], - DebugInfo::Skip, - CollectEvents::Skip, - ) - .result - .unwrap() - .account_id; - - // Instantiate 2nd contract. - let addr2 = Contracts::bare_instantiate( + let addr = Contracts::bare_instantiate( ALICE, 0, GAS_LIMIT, None, - Code::Upload(wasm2), + Code::Upload(code), vec![], vec![], DebugInfo::Skip, @@ -1011,11 +955,11 @@ fn gas_syncs_work() { let result = Contracts::bare_call( ALICE, - addr0, + addr.clone(), 0, GAS_LIMIT, None, - 1u8.to_le_bytes().to_vec(), + 0u32.encode(), DebugInfo::Skip, CollectEvents::Skip, Determinism::Enforced, @@ -1025,27 +969,28 @@ fn gas_syncs_work() { let result = Contracts::bare_call( ALICE, - addr1, + addr.clone(), 0, GAS_LIMIT, None, - 1u8.to_le_bytes().to_vec(), + 1u32.encode(), DebugInfo::Skip, CollectEvents::Skip, Determinism::Enforced, ); assert_ok!(result.result); let gas_consumed_once = result.gas_consumed.ref_time(); - let host_consumed_once = ::Schedule::get().host_fn_weights.input.ref_time(); + let host_consumed_once = + ::Schedule::get().host_fn_weights.caller_is_origin.ref_time(); let engine_consumed_once = gas_consumed_once - host_consumed_once - engine_consumed_noop; let result = Contracts::bare_call( ALICE, - addr2, + addr, 0, GAS_LIMIT, None, - 1u8.to_le_bytes().to_vec(), + 2u32.encode(), DebugInfo::Skip, CollectEvents::Skip, Determinism::Enforced, @@ -4453,96 +4398,6 @@ fn contract_reverted() { }); } -#[test] -fn code_rejected_error_works() { - ExtBuilder::default().existential_deposit(200).build().execute_with(|| { - let _ = ::Currency::set_balance(&ALICE, 1_000_000); - - let (wasm, _) = compile_module::("invalid_module").unwrap(); - assert_noop!( - Contracts::upload_code( - RuntimeOrigin::signed(ALICE), - wasm.clone(), - None, - Determinism::Enforced - ), - >::CodeRejected, - ); - let result = Contracts::bare_instantiate( - ALICE, - 0, - GAS_LIMIT, - None, - Code::Upload(wasm), - vec![], - vec![], - DebugInfo::UnsafeDebug, - CollectEvents::Skip, - ); - assert_err!(result.result, >::CodeRejected); - assert_eq!( - std::str::from_utf8(&result.debug_message).unwrap(), - "Can't load the module into wasmi!" - ); - - let (wasm, _) = compile_module::("invalid_contract_no_call").unwrap(); - assert_noop!( - Contracts::upload_code( - RuntimeOrigin::signed(ALICE), - wasm.clone(), - None, - Determinism::Enforced - ), - >::CodeRejected, - ); - - let result = Contracts::bare_instantiate( - ALICE, - 0, - GAS_LIMIT, - None, - Code::Upload(wasm), - vec![], - vec![], - DebugInfo::UnsafeDebug, - CollectEvents::Skip, - ); - assert_err!(result.result, >::CodeRejected); - assert_eq!( - std::str::from_utf8(&result.debug_message).unwrap(), - "call function isn't exported" - ); - - let (wasm, _) = compile_module::("invalid_contract_no_memory").unwrap(); - assert_noop!( - Contracts::upload_code( - RuntimeOrigin::signed(ALICE), - wasm.clone(), - None, - Determinism::Enforced - ), - >::CodeRejected, - ); - - let result = Contracts::bare_instantiate( - ALICE, - 0, - GAS_LIMIT, - None, - Code::Upload(wasm), - vec![], - vec![], - DebugInfo::UnsafeDebug, - CollectEvents::Skip, - ); - assert_err!(result.result, >::CodeRejected); - assert_eq!( - std::str::from_utf8(&result.debug_message).unwrap(), - "No memory import found in the module" - ); - }); -} - #[test] fn set_code_hash() { let (wasm, code_hash) = compile_module::("set_code_hash").unwrap(); diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs index 87e92cd72e8..23363780b14 100644 --- a/substrate/frame/contracts/src/wasm/mod.rs +++ b/substrate/frame/contracts/src/wasm/mod.rs @@ -3442,4 +3442,22 @@ mod tests { runtime.read_sandbox_memory_as(&memory, 0u32).unwrap(); assert_eq!(decoded.into_inner(), data); } + + #[test] + fn run_out_of_gas_in_start_fn() { + const CODE: &str = r#" +(module + (import "env" "memory" (memory 1 1)) + (start $start) + (func $start + (loop $inf (br $inf)) ;; just run out of gas + (unreachable) + ) + (func (export "call")) + (func (export "deploy")) +) +"#; + let mut mock_ext = MockExt::default(); + assert_err!(execute(&CODE, vec![], &mut mock_ext), >::OutOfGas); + } } -- GitLab From c16fcc47bc427dd01ed3d1c17d6483bd388bc92f Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Thu, 7 Mar 2024 11:11:43 +0200 Subject: [PATCH 082/188] ParaInherent create: update `apply_weight_limit` wrt elastic scaling (#3573) Changes the way we perform the random selection of backed candidates when there isn't enough room for all of them. Instead of picking individual backed candidates `apply_weight` now operates on chains of candidates. This is fully backwards compatible and relies on the node side (provisioner/prospective parachains) doing the heavy lifting and providing the candidates in the order they form a chain. The same approach can be implemented for bitfields random selection once https://github.com/paritytech/polkadot-sdk/pull/3479 is merged. The approach taken in this PR aims for reduced additional complexity at the cost of being less fair wrt how many backed candidates from each chain are picked. It favors elastic scaling parachains vs parachains not using elastic scaling, but from my perspective it should be fine as this should happen under exceptional circumstances like dispute storms. Note: to make things more fair we can consider specializing `random_sel` such that it will try to pick candidates one by one in the order provided by the provisioner such that non elastic scaling parachains have the same chance of getting a candidate backed. --------- Signed-off-by: Andrei Sandu --- .../parachains/src/paras_inherent/mod.rs | 64 +++++++-- .../parachains/src/paras_inherent/tests.rs | 125 +++++++++++++++++- 2 files changed, 174 insertions(+), 15 deletions(-) diff --git a/polkadot/runtime/parachains/src/paras_inherent/mod.rs b/polkadot/runtime/parachains/src/paras_inherent/mod.rs index cebf858c24a..723a15bdba7 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/mod.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/mod.rs @@ -788,7 +788,7 @@ fn random_sel Weight>( /// Assumes disputes are already filtered by the time this is called. /// /// Returns the total weight consumed by `bitfields` and `candidates`. -fn apply_weight_limit( +pub(crate) fn apply_weight_limit( candidates: &mut Vec::Hash>>, bitfields: &mut UncheckedSignedAvailabilityBitfields, max_consumable_weight: Weight, @@ -805,35 +805,71 @@ fn apply_weight_limit( return total } - // Prefer code upgrades, they tend to be large and hence stand no chance to be picked - // late while maintaining the weight bounds. - let preferred_indices = candidates + // Invariant: block author provides candidate in the order in which they form a chain + // wrt elastic scaling. If the invariant is broken, we'd fail later when filtering candidates + // which are unchained. + + let mut chained_candidates: Vec> = Vec::new(); + let mut current_para_id = None; + + for candidate in sp_std::mem::take(candidates).into_iter() { + let candidate_para_id = candidate.descriptor().para_id; + if Some(candidate_para_id) == current_para_id { + let chain = chained_candidates + .last_mut() + .expect("if the current_para_id is Some, then vec is not empty; qed"); + chain.push(candidate); + } else { + current_para_id = Some(candidate_para_id); + chained_candidates.push(vec![candidate]); + } + } + + // Elastic scaling: we prefer chains that have a code upgrade among the candidates, + // as the candidates containing the upgrade tend to be large and hence stand no chance to + // be picked late while maintaining the weight bounds. + // + // Limitations: For simplicity if total weight of a chain of candidates is larger than + // the remaining weight, the chain will still not be included while it could still be possible + // to include part of that chain. + let preferred_chain_indices = chained_candidates .iter() .enumerate() - .filter_map(|(idx, candidate)| { - candidate.candidate().commitments.new_validation_code.as_ref().map(|_code| idx) + .filter_map(|(idx, candidates)| { + // Check if any of the candidate in chain contains a code upgrade. + if candidates + .iter() + .any(|candidate| candidate.candidate().commitments.new_validation_code.is_some()) + { + Some(idx) + } else { + None + } }) .collect::>(); - // There is weight remaining to be consumed by a subset of candidates + // There is weight remaining to be consumed by a subset of chained candidates // which are going to be picked now. if let Some(max_consumable_by_candidates) = max_consumable_weight.checked_sub(&total_bitfields_weight) { - let (acc_candidate_weight, indices) = - random_sel::::Hash>, _>( + let (acc_candidate_weight, chained_indices) = + random_sel::::Hash>>, _>( rng, - &candidates, - preferred_indices, - |c| backed_candidate_weight::(c), + &chained_candidates, + preferred_chain_indices, + |candidates| backed_candidates_weight::(&candidates), max_consumable_by_candidates, ); - log::debug!(target: LOG_TARGET, "Indices Candidates: {:?}, size: {}", indices, candidates.len()); - candidates.indexed_retain(|idx, _backed_candidate| indices.binary_search(&idx).is_ok()); + log::debug!(target: LOG_TARGET, "Indices Candidates: {:?}, size: {}", chained_indices, candidates.len()); + chained_candidates + .indexed_retain(|idx, _backed_candidates| chained_indices.binary_search(&idx).is_ok()); // pick all bitfields, and // fill the remaining space with candidates let total_consumed = acc_candidate_weight.saturating_add(total_bitfields_weight); + *candidates = chained_candidates.into_iter().flatten().collect::>(); + return total_consumed } diff --git a/polkadot/runtime/parachains/src/paras_inherent/tests.rs b/polkadot/runtime/parachains/src/paras_inherent/tests.rs index b7285ec884a..fb4d1bd2226 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/tests.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/tests.rs @@ -22,7 +22,7 @@ use super::*; #[cfg(not(feature = "runtime-benchmarks"))] mod enter { - use super::*; + use super::{inclusion::tests::TestCandidateBuilder, *}; use crate::{ builder::{Bench, BenchBuilder}, mock::{mock_assigner, new_test_ext, BlockLength, BlockWeights, MockGenesisConfig, Test}, @@ -925,6 +925,129 @@ mod enter { }); } + // Helper fn that builds chained dummy candidates for elastic scaling tests + fn build_backed_candidate_chain( + para_id: ParaId, + len: usize, + start_core_index: usize, + code_upgrade_index: Option, + ) -> Vec { + if let Some(code_upgrade_index) = code_upgrade_index { + assert!(code_upgrade_index < len, "Code upgrade index out of bounds"); + } + + (0..len) + .into_iter() + .map(|idx| { + let mut builder = TestCandidateBuilder::default(); + builder.para_id = para_id; + let mut ccr = builder.build(); + + if Some(idx) == code_upgrade_index { + ccr.commitments.new_validation_code = Some(vec![1, 2, 3, 4].into()); + } + + ccr.commitments.processed_downward_messages = idx as u32; + let core_index = start_core_index + idx; + + BackedCandidate::new( + ccr.into(), + Default::default(), + Default::default(), + Some(CoreIndex(core_index as u32)), + ) + }) + .collect::>() + } + + // Ensure that overweight parachain inherents are always rejected by the runtime. + // Runtime should panic and return `InherentOverweight` error. + #[test] + fn test_backed_candidates_apply_weight_works_for_elastic_scaling() { + new_test_ext(MockGenesisConfig::default()).execute_with(|| { + let seed = [ + 1, 0, 52, 0, 0, 0, 0, 0, 1, 0, 10, 0, 22, 32, 0, 0, 2, 0, 55, 49, 0, 11, 0, 0, 3, + 0, 0, 0, 0, 0, 2, 92, + ]; + let mut rng = rand_chacha::ChaChaRng::from_seed(seed); + + // Create an overweight inherent and oversized block + let mut backed_and_concluding = BTreeMap::new(); + + for i in 0..30 { + backed_and_concluding.insert(i, i); + } + + let scenario = make_inherent_data(TestConfig { + dispute_statements: Default::default(), + dispute_sessions: vec![], // 3 cores with disputes + backed_and_concluding, + num_validators_per_core: 5, + code_upgrade: None, + fill_claimqueue: false, + }); + + let mut para_inherent_data = scenario.data.clone(); + + // Check the para inherent data is as expected: + // * 1 bitfield per validator (5 validators per core, 30 backed candidates, 0 disputes + // => 5*30 = 150) + assert_eq!(para_inherent_data.bitfields.len(), 150); + // * 30 backed candidates + assert_eq!(para_inherent_data.backed_candidates.len(), 30); + + let mut input_candidates = + build_backed_candidate_chain(ParaId::from(1000), 3, 0, Some(1)); + let chained_candidates_weight = backed_candidates_weight::(&input_candidates); + + input_candidates.append(&mut para_inherent_data.backed_candidates); + let input_bitfields = para_inherent_data.bitfields; + + // Test if weight insufficient even for 1 candidate (which doesn't contain a code + // upgrade). + let max_weight = backed_candidate_weight::(&input_candidates[0]) + + signed_bitfields_weight::(&input_bitfields); + let mut backed_candidates = input_candidates.clone(); + let mut bitfields = input_bitfields.clone(); + apply_weight_limit::( + &mut backed_candidates, + &mut bitfields, + max_weight, + &mut rng, + ); + + // The chained candidates are not picked, instead a single other candidate is picked + assert_eq!(backed_candidates.len(), 1); + assert_ne!(backed_candidates[0].descriptor().para_id, ParaId::from(1000)); + + // All bitfields are kept. + assert_eq!(bitfields.len(), 150); + + // Test if para_id 1000 chained candidates make it if there is enough room for its 3 + // candidates. + let max_weight = + chained_candidates_weight + signed_bitfields_weight::(&input_bitfields); + let mut backed_candidates = input_candidates.clone(); + let mut bitfields = input_bitfields.clone(); + apply_weight_limit::( + &mut backed_candidates, + &mut bitfields, + max_weight, + &mut rng, + ); + + // Only the chained candidates should pass filter. + assert_eq!(backed_candidates.len(), 3); + // Check the actual candidates + assert_eq!(backed_candidates[0].descriptor().para_id, ParaId::from(1000)); + assert_eq!(backed_candidates[1].descriptor().para_id, ParaId::from(1000)); + assert_eq!(backed_candidates[2].descriptor().para_id, ParaId::from(1000)); + + // All bitfields are kept. + assert_eq!(bitfields.len(), 150); + }); + } + // Ensure that overweight parachain inherents are always rejected by the runtime. // Runtime should panic and return `InherentOverweight` error. #[test] -- GitLab From 11831df8e709061e9c6b3292facb5d7d9709f151 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Thu, 7 Mar 2024 11:36:30 +0100 Subject: [PATCH 083/188] `nomination-pools`: add permissionless condition to `chill` (#3453) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, pool member funds cannot be unbonded if the depositor's stake is less than `MinNominatorBond`. This usually happens after `T::MinNominatorBond` is increased. To fix this, the above mentioned condition is added as a case for permissionless dispatch of `chill`. After pool is chilled, pool members can unbond their funds since pool won't be nominating anymore. Consequently, same check is added to `nominate` call, i.e pool can not start nominating if it's depositor does not have `MinNominatorBond` cc @Ank4n @kianenigma closes #2350 Polkadot address: 16FqwPZ8GRC5U5D4Fu7W33nA55ZXzXGWHwmbnE1eT6pxuqcT --------- Co-authored-by: Ankan <10196091+Ank4n@users.noreply.github.com> Co-authored-by: Gonçalo Pestana Co-authored-by: command-bot <> --- prdoc/pr_3453.prdoc | 13 + substrate/frame/nomination-pools/src/lib.rs | 39 ++- substrate/frame/nomination-pools/src/tests.rs | 42 +++ .../frame/nomination-pools/src/weights.rs | 268 ++++++++++-------- .../nomination-pools/test-staking/src/lib.rs | 133 ++++++++- 5 files changed, 367 insertions(+), 128 deletions(-) create mode 100644 prdoc/pr_3453.prdoc diff --git a/prdoc/pr_3453.prdoc b/prdoc/pr_3453.prdoc new file mode 100644 index 00000000000..1f01440f722 --- /dev/null +++ b/prdoc/pr_3453.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "[pallet-nomination-pools]: `chill` is permissionless if depositor's stake is less than `min_nominator_bond`" + +doc: + - audience: Runtime Dev + description: | + Nomination pools currently have an issue whereby member funds cannot be unbonded if the depositor bonded amount is less than `MinNominatorBond`. + This PR makes the `chill` function permissionless if this condition is met. + Consequently, `nominate` function also checks for `depositor` to have at least `MinNominatorBond`, and returns `MinimumBondNotMet` error if not. +crates: + - name: pallet-nomination-pools diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index c64db9ed692..a0dbdb3aaa4 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -2401,6 +2401,11 @@ pub mod pallet { /// /// This directly forward the call to the staking pallet, on behalf of the pool bonded /// account. + /// + /// # Note + /// + /// In addition to a `root` or `nominator` role of `origin`, pool's depositor needs to have + /// at least `depositor_min_bond` in the pool to start nominating. #[pallet::call_index(8)] #[pallet::weight(T::WeightInfo::nominate(validators.len() as u32))] pub fn nominate( @@ -2411,6 +2416,16 @@ pub mod pallet { let who = ensure_signed(origin)?; let bonded_pool = BondedPool::::get(pool_id).ok_or(Error::::PoolNotFound)?; ensure!(bonded_pool.can_nominate(&who), Error::::NotNominator); + + let depositor_points = PoolMembers::::get(&bonded_pool.roles.depositor) + .ok_or(Error::::PoolMemberNotFound)? + .active_points(); + + ensure!( + bonded_pool.points_to_balance(depositor_points) >= Self::depositor_min_bond(), + Error::::MinimumBondNotMet + ); + T::Staking::nominate(&bonded_pool.bonded_account(), validators) } @@ -2573,17 +2588,37 @@ pub mod pallet { /// Chill on behalf of the pool. /// - /// The dispatch origin of this call must be signed by the pool nominator or the pool + /// The dispatch origin of this call can be signed by the pool nominator or the pool /// root role, same as [`Pallet::nominate`]. /// + /// Under certain conditions, this call can be dispatched permissionlessly (i.e. by any + /// account). + /// + /// # Conditions for a permissionless dispatch: + /// * When pool depositor has less than `MinNominatorBond` staked, otherwise pool members + /// are unable to unbond. + /// + /// # Conditions for permissioned dispatch: + /// * The caller has a nominator or root role of the pool. /// This directly forward the call to the staking pallet, on behalf of the pool bonded /// account. #[pallet::call_index(13)] #[pallet::weight(T::WeightInfo::chill())] pub fn chill(origin: OriginFor, pool_id: PoolId) -> DispatchResult { let who = ensure_signed(origin)?; + let bonded_pool = BondedPool::::get(pool_id).ok_or(Error::::PoolNotFound)?; - ensure!(bonded_pool.can_nominate(&who), Error::::NotNominator); + + let depositor_points = PoolMembers::::get(&bonded_pool.roles.depositor) + .ok_or(Error::::PoolMemberNotFound)? + .active_points(); + + if bonded_pool.points_to_balance(depositor_points) >= + T::Staking::minimum_nominator_bond() + { + ensure!(bonded_pool.can_nominate(&who), Error::::NotNominator); + } + T::Staking::chill(&bonded_pool.bonded_account()) } diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index 13298fa64f5..8fb2b41b88a 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -4848,6 +4848,18 @@ mod nominate { Error::::NotNominator ); + // if `depositor` stake is less than the `MinimumNominatorBond`, they can't nominate + StakingMinBond::set(20); + + // Can't nominate if depositor's stake is less than the `MinimumNominatorBond` + assert_noop!( + Pools::nominate(RuntimeOrigin::signed(900), 1, vec![21]), + Error::::MinimumBondNotMet + ); + + // restore `MinimumNominatorBond` + StakingMinBond::set(10); + // Root can nominate assert_ok!(Pools::nominate(RuntimeOrigin::signed(900), 1, vec![21])); assert_eq!(Nominations::get().unwrap(), vec![21]); @@ -7338,3 +7350,33 @@ mod slash { }); } } + +mod chill { + use super::*; + + #[test] + fn chill_works() { + ExtBuilder::default().build_and_execute(|| { + // only nominator or root can chill + assert_noop!( + Pools::chill(RuntimeOrigin::signed(10), 1), + Error::::NotNominator + ); + + // root can chill and re-nominate + assert_ok!(Pools::chill(RuntimeOrigin::signed(900), 1)); + assert_ok!(Pools::nominate(RuntimeOrigin::signed(900), 1, vec![31])); + + // nominator can chill and re-nominate + assert_ok!(Pools::chill(RuntimeOrigin::signed(901), 1)); + assert_ok!(Pools::nominate(RuntimeOrigin::signed(901), 1, vec![31])); + + // if `depositor` stake is less than the `MinimumNominatorBond`, then this call + // becomes permissionless; + StakingMinBond::set(20); + + // any account can chill + assert_ok!(Pools::chill(RuntimeOrigin::signed(10), 1)); + }) + } +} diff --git a/substrate/frame/nomination-pools/src/weights.rs b/substrate/frame/nomination-pools/src/weights.rs index 2749af7937f..987ddd71703 100644 --- a/substrate/frame/nomination-pools/src/weights.rs +++ b/substrate/frame/nomination-pools/src/weights.rs @@ -18,27 +18,25 @@ //! Autogenerated weights for `pallet_nomination_pools` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-p5qp1txx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_nomination_pools -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/nomination-pools/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_nomination_pools +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/nomination-pools/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -114,8 +112,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3425` // Estimated: `8877` - // Minimum execution time: 181_861_000 picoseconds. - Weight::from_parts(186_375_000, 8877) + // Minimum execution time: 182_643_000 picoseconds. + Weight::from_parts(186_106_000, 8877) .saturating_add(T::DbWeight::get().reads(20_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } @@ -147,8 +145,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3435` // Estimated: `8877` - // Minimum execution time: 182_273_000 picoseconds. - Weight::from_parts(186_635_000, 8877) + // Minimum execution time: 181_464_000 picoseconds. + Weight::from_parts(184_672_000, 8877) .saturating_add(T::DbWeight::get().reads(17_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } @@ -182,8 +180,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3500` // Estimated: `8877` - // Minimum execution time: 217_878_000 picoseconds. - Weight::from_parts(221_493_000, 8877) + // Minimum execution time: 216_182_000 picoseconds. + Weight::from_parts(218_448_000, 8877) .saturating_add(T::DbWeight::get().reads(18_u64)) .saturating_add(T::DbWeight::get().writes(14_u64)) } @@ -203,8 +201,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1172` // Estimated: `3719` - // Minimum execution time: 74_509_000 picoseconds. - Weight::from_parts(76_683_000, 3719) + // Minimum execution time: 73_830_000 picoseconds. + Weight::from_parts(75_271_000, 3719) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -244,8 +242,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3622` // Estimated: `27847` - // Minimum execution time: 166_424_000 picoseconds. - Weight::from_parts(169_698_000, 27847) + // Minimum execution time: 166_099_000 picoseconds. + Weight::from_parts(170_355_000, 27847) .saturating_add(T::DbWeight::get().reads(20_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } @@ -270,10 +268,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1848` // Estimated: `4764` - // Minimum execution time: 66_110_000 picoseconds. - Weight::from_parts(68_620_141, 4764) - // Standard Error: 1_379 - .saturating_add(Weight::from_parts(54_961, 0).saturating_mul(s.into())) + // Minimum execution time: 64_787_000 picoseconds. + Weight::from_parts(67_920_914, 4764) + // Standard Error: 1_482 + .saturating_add(Weight::from_parts(43_264, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -308,10 +306,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2238` // Estimated: `27847` - // Minimum execution time: 125_669_000 picoseconds. - Weight::from_parts(130_907_641, 27847) - // Standard Error: 2_490 - .saturating_add(Weight::from_parts(75_219, 0).saturating_mul(s.into())) + // Minimum execution time: 124_990_000 picoseconds. + Weight::from_parts(129_041_398, 27847) + // Standard Error: 2_335 + .saturating_add(Weight::from_parts(67_889, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } @@ -362,12 +360,14 @@ impl WeightInfo for SubstrateWeight { /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. - fn withdraw_unbonded_kill(_s: u32, ) -> Weight { + fn withdraw_unbonded_kill(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `2525` // Estimated: `27847` - // Minimum execution time: 225_700_000 picoseconds. - Weight::from_parts(234_390_990, 27847) + // Minimum execution time: 221_955_000 picoseconds. + Weight::from_parts(230_244_437, 27847) + // Standard Error: 4_059 + .saturating_add(Weight::from_parts(7_522, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(24_u64)) .saturating_add(T::DbWeight::get().writes(20_u64)) } @@ -419,19 +419,25 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1169` // Estimated: `8538` - // Minimum execution time: 167_171_000 picoseconds. - Weight::from_parts(170_531_000, 8538) + // Minimum execution time: 165_358_000 picoseconds. + Weight::from_parts(169_683_000, 8538) .saturating_add(T::DbWeight::get().reads(23_u64)) .saturating_add(T::DbWeight::get().writes(17_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:0) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::MinNominatorBond` (r:1 w:0) /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:1 w:0) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:1) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:1 w:0) @@ -451,13 +457,13 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1808` + // Measured: `1976` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 63_785_000 picoseconds. - Weight::from_parts(64_592_302, 4556) - // Standard Error: 9_416 - .saturating_add(Weight::from_parts(1_524_398, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(12_u64)) + // Minimum execution time: 74_483_000 picoseconds. + Weight::from_parts(76_611_288, 4556) + // Standard Error: 9_013 + .saturating_add(Weight::from_parts(1_475_128, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(n.into())) @@ -472,8 +478,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1434` // Estimated: `4556` - // Minimum execution time: 32_096_000 picoseconds. - Weight::from_parts(33_533_000, 4556) + // Minimum execution time: 32_598_000 picoseconds. + Weight::from_parts(33_350_000, 4556) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -488,10 +494,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3735` - // Minimum execution time: 13_914_000 picoseconds. - Weight::from_parts(14_800_402, 3735) - // Standard Error: 146 - .saturating_add(Weight::from_parts(940, 0).saturating_mul(n.into())) + // Minimum execution time: 13_705_000 picoseconds. + Weight::from_parts(14_594_211, 3735) + // Standard Error: 141 + .saturating_add(Weight::from_parts(2_119, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -511,8 +517,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_373_000 picoseconds. - Weight::from_parts(4_592_000, 0) + // Minimum execution time: 4_222_000 picoseconds. + Weight::from_parts(4_527_000, 0) .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -521,17 +527,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_662_000 picoseconds. - Weight::from_parts(17_531_000, 3719) + // Minimum execution time: 16_106_000 picoseconds. + Weight::from_parts(17_365_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:0) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::Validators` (r:1 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:1) @@ -546,11 +556,11 @@ impl WeightInfo for SubstrateWeight { /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: - // Measured: `1971` + // Measured: `2143` // Estimated: `4556` - // Minimum execution time: 61_348_000 picoseconds. - Weight::from_parts(63_712_000, 4556) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Minimum execution time: 71_301_000 picoseconds. + Weight::from_parts(73_626_000, 4556) + .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -565,8 +575,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `804` // Estimated: `3719` - // Minimum execution time: 32_232_000 picoseconds. - Weight::from_parts(33_433_000, 3719) + // Minimum execution time: 32_363_000 picoseconds. + Weight::from_parts(33_400_000, 3719) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -578,8 +588,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `572` // Estimated: `3719` - // Minimum execution time: 16_774_000 picoseconds. - Weight::from_parts(17_671_000, 3719) + // Minimum execution time: 16_686_000 picoseconds. + Weight::from_parts(17_294_000, 3719) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -589,8 +599,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_724_000 picoseconds. - Weight::from_parts(17_181_000, 3719) + // Minimum execution time: 16_417_000 picoseconds. + Weight::from_parts(17_028_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -600,8 +610,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_362_000 picoseconds. - Weight::from_parts(17_135_000, 3719) + // Minimum execution time: 16_350_000 picoseconds. + Weight::from_parts(16_905_000, 3719) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -613,8 +623,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `542` // Estimated: `3702` - // Minimum execution time: 14_125_000 picoseconds. - Weight::from_parts(14_705_000, 3702) + // Minimum execution time: 14_081_000 picoseconds. + Weight::from_parts(14_608_000, 3702) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -630,8 +640,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1002` // Estimated: `3719` - // Minimum execution time: 61_699_000 picoseconds. - Weight::from_parts(63_605_000, 3719) + // Minimum execution time: 62_178_000 picoseconds. + Weight::from_parts(64_039_000, 3719) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -647,8 +657,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `901` // Estimated: `4764` - // Minimum execution time: 64_930_000 picoseconds. - Weight::from_parts(66_068_000, 4764) + // Minimum execution time: 64_880_000 picoseconds. + Weight::from_parts(66_541_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -692,8 +702,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3425` // Estimated: `8877` - // Minimum execution time: 181_861_000 picoseconds. - Weight::from_parts(186_375_000, 8877) + // Minimum execution time: 182_643_000 picoseconds. + Weight::from_parts(186_106_000, 8877) .saturating_add(RocksDbWeight::get().reads(20_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } @@ -725,8 +735,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3435` // Estimated: `8877` - // Minimum execution time: 182_273_000 picoseconds. - Weight::from_parts(186_635_000, 8877) + // Minimum execution time: 181_464_000 picoseconds. + Weight::from_parts(184_672_000, 8877) .saturating_add(RocksDbWeight::get().reads(17_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } @@ -760,8 +770,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3500` // Estimated: `8877` - // Minimum execution time: 217_878_000 picoseconds. - Weight::from_parts(221_493_000, 8877) + // Minimum execution time: 216_182_000 picoseconds. + Weight::from_parts(218_448_000, 8877) .saturating_add(RocksDbWeight::get().reads(18_u64)) .saturating_add(RocksDbWeight::get().writes(14_u64)) } @@ -781,8 +791,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1172` // Estimated: `3719` - // Minimum execution time: 74_509_000 picoseconds. - Weight::from_parts(76_683_000, 3719) + // Minimum execution time: 73_830_000 picoseconds. + Weight::from_parts(75_271_000, 3719) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -822,8 +832,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3622` // Estimated: `27847` - // Minimum execution time: 166_424_000 picoseconds. - Weight::from_parts(169_698_000, 27847) + // Minimum execution time: 166_099_000 picoseconds. + Weight::from_parts(170_355_000, 27847) .saturating_add(RocksDbWeight::get().reads(20_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } @@ -848,10 +858,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1848` // Estimated: `4764` - // Minimum execution time: 66_110_000 picoseconds. - Weight::from_parts(68_620_141, 4764) - // Standard Error: 1_379 - .saturating_add(Weight::from_parts(54_961, 0).saturating_mul(s.into())) + // Minimum execution time: 64_787_000 picoseconds. + Weight::from_parts(67_920_914, 4764) + // Standard Error: 1_482 + .saturating_add(Weight::from_parts(43_264, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -886,10 +896,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2238` // Estimated: `27847` - // Minimum execution time: 125_669_000 picoseconds. - Weight::from_parts(130_907_641, 27847) - // Standard Error: 2_490 - .saturating_add(Weight::from_parts(75_219, 0).saturating_mul(s.into())) + // Minimum execution time: 124_990_000 picoseconds. + Weight::from_parts(129_041_398, 27847) + // Standard Error: 2_335 + .saturating_add(Weight::from_parts(67_889, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(9_u64)) } @@ -940,12 +950,14 @@ impl WeightInfo for () { /// Storage: `NominationPools::ClaimPermissions` (r:0 w:1) /// Proof: `NominationPools::ClaimPermissions` (`max_values`: None, `max_size`: Some(41), added: 2516, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. - fn withdraw_unbonded_kill(_s: u32, ) -> Weight { + fn withdraw_unbonded_kill(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `2525` // Estimated: `27847` - // Minimum execution time: 225_700_000 picoseconds. - Weight::from_parts(234_390_990, 27847) + // Minimum execution time: 221_955_000 picoseconds. + Weight::from_parts(230_244_437, 27847) + // Standard Error: 4_059 + .saturating_add(Weight::from_parts(7_522, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(24_u64)) .saturating_add(RocksDbWeight::get().writes(20_u64)) } @@ -997,19 +1009,25 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1169` // Estimated: `8538` - // Minimum execution time: 167_171_000 picoseconds. - Weight::from_parts(170_531_000, 8538) + // Minimum execution time: 165_358_000 picoseconds. + Weight::from_parts(169_683_000, 8538) .saturating_add(RocksDbWeight::get().reads(23_u64)) .saturating_add(RocksDbWeight::get().writes(17_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:0) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::MinNominatorBond` (r:1 w:0) /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinCreateBond` (r:1 w:0) + /// Proof: `NominationPools::MinCreateBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::MinJoinBond` (r:1 w:0) + /// Proof: `NominationPools::MinJoinBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:1) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:1 w:0) @@ -1029,13 +1047,13 @@ impl WeightInfo for () { /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1808` + // Measured: `1976` // Estimated: `4556 + n * (2520 ±0)` - // Minimum execution time: 63_785_000 picoseconds. - Weight::from_parts(64_592_302, 4556) - // Standard Error: 9_416 - .saturating_add(Weight::from_parts(1_524_398, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(12_u64)) + // Minimum execution time: 74_483_000 picoseconds. + Weight::from_parts(76_611_288, 4556) + // Standard Error: 9_013 + .saturating_add(Weight::from_parts(1_475_128, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(15_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(n.into())) @@ -1050,8 +1068,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1434` // Estimated: `4556` - // Minimum execution time: 32_096_000 picoseconds. - Weight::from_parts(33_533_000, 4556) + // Minimum execution time: 32_598_000 picoseconds. + Weight::from_parts(33_350_000, 4556) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1066,10 +1084,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3735` - // Minimum execution time: 13_914_000 picoseconds. - Weight::from_parts(14_800_402, 3735) - // Standard Error: 146 - .saturating_add(Weight::from_parts(940, 0).saturating_mul(n.into())) + // Minimum execution time: 13_705_000 picoseconds. + Weight::from_parts(14_594_211, 3735) + // Standard Error: 141 + .saturating_add(Weight::from_parts(2_119, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1089,8 +1107,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_373_000 picoseconds. - Weight::from_parts(4_592_000, 0) + // Minimum execution time: 4_222_000 picoseconds. + Weight::from_parts(4_527_000, 0) .saturating_add(RocksDbWeight::get().writes(6_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -1099,17 +1117,21 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_662_000 picoseconds. - Weight::from_parts(17_531_000, 3719) + // Minimum execution time: 16_106_000 picoseconds. + Weight::from_parts(17_365_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:0) /// Proof: `NominationPools::BondedPools` (`max_values`: None, `max_size`: Some(254), added: 2729, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::PoolMembers` (r:1 w:0) + /// Proof: `NominationPools::PoolMembers` (`max_values`: None, `max_size`: Some(237), added: 2712, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:0) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::Validators` (r:1 w:0) /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:1) @@ -1124,11 +1146,11 @@ impl WeightInfo for () { /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: - // Measured: `1971` + // Measured: `2143` // Estimated: `4556` - // Minimum execution time: 61_348_000 picoseconds. - Weight::from_parts(63_712_000, 4556) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Minimum execution time: 71_301_000 picoseconds. + Weight::from_parts(73_626_000, 4556) + .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `NominationPools::BondedPools` (r:1 w:1) @@ -1143,8 +1165,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `804` // Estimated: `3719` - // Minimum execution time: 32_232_000 picoseconds. - Weight::from_parts(33_433_000, 3719) + // Minimum execution time: 32_363_000 picoseconds. + Weight::from_parts(33_400_000, 3719) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1156,8 +1178,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `572` // Estimated: `3719` - // Minimum execution time: 16_774_000 picoseconds. - Weight::from_parts(17_671_000, 3719) + // Minimum execution time: 16_686_000 picoseconds. + Weight::from_parts(17_294_000, 3719) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1167,8 +1189,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_724_000 picoseconds. - Weight::from_parts(17_181_000, 3719) + // Minimum execution time: 16_417_000 picoseconds. + Weight::from_parts(17_028_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1178,8 +1200,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `532` // Estimated: `3719` - // Minimum execution time: 16_362_000 picoseconds. - Weight::from_parts(17_135_000, 3719) + // Minimum execution time: 16_350_000 picoseconds. + Weight::from_parts(16_905_000, 3719) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1191,8 +1213,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `542` // Estimated: `3702` - // Minimum execution time: 14_125_000 picoseconds. - Weight::from_parts(14_705_000, 3702) + // Minimum execution time: 14_081_000 picoseconds. + Weight::from_parts(14_608_000, 3702) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1208,8 +1230,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1002` // Estimated: `3719` - // Minimum execution time: 61_699_000 picoseconds. - Weight::from_parts(63_605_000, 3719) + // Minimum execution time: 62_178_000 picoseconds. + Weight::from_parts(64_039_000, 3719) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1225,8 +1247,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `901` // Estimated: `4764` - // Minimum execution time: 64_930_000 picoseconds. - Weight::from_parts(66_068_000, 4764) + // Minimum execution time: 64_880_000 picoseconds. + Weight::from_parts(66_541_000, 4764) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/nomination-pools/test-staking/src/lib.rs b/substrate/frame/nomination-pools/test-staking/src/lib.rs index 865b7a71e68..98bff537c90 100644 --- a/substrate/frame/nomination-pools/test-staking/src/lib.rs +++ b/substrate/frame/nomination-pools/test-staking/src/lib.rs @@ -22,10 +22,12 @@ mod mock; use frame_support::{assert_noop, assert_ok, traits::Currency}; use mock::*; use pallet_nomination_pools::{ - BondedPools, Error as PoolsError, Event as PoolsEvent, LastPoolId, PoolMember, PoolMembers, - PoolState, + BondExtra, BondedPools, Error as PoolsError, Event as PoolsEvent, LastPoolId, PoolMember, + PoolMembers, PoolState, +}; +use pallet_staking::{ + CurrentEra, Error as StakingError, Event as StakingEvent, Payee, RewardDestination, }; -use pallet_staking::{CurrentEra, Event as StakingEvent, Payee, RewardDestination}; use sp_runtime::{bounded_btree_map, traits::Zero}; #[test] @@ -191,6 +193,131 @@ fn pool_lifecycle_e2e() { }) } +#[test] +fn pool_chill_e2e() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::minimum_balance(), 5); + assert_eq!(Staking::current_era(), None); + + // create the pool, we know this has id 1. + assert_ok!(Pools::create(RuntimeOrigin::signed(10), 50, 10, 10, 10)); + assert_eq!(LastPoolId::::get(), 1); + + // have the pool nominate. + assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3])); + + assert_eq!( + staking_events_since_last_call(), + vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 50 }] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Created { depositor: 10, pool_id: 1 }, + PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + ] + ); + + // have two members join + assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1)); + assert_ok!(Pools::join(RuntimeOrigin::signed(21), 10, 1)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, + ] + ); + assert_eq!( + pool_events_since_last_call(), + vec![ + PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true }, + PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: 10, joined: true }, + ] + ); + + // in case depositor does not have more than `MinNominatorBond` staked, we can end up in + // situation where a member unbonding would cause pool balance to drop below + // `MinNominatorBond` and hence not allowed. This can happen if the `MinNominatorBond` is + // increased after the pool is created. + assert_ok!(Staking::set_staking_configs( + RuntimeOrigin::root(), + pallet_staking::ConfigOp::Set(55), // minimum nominator bond + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + pallet_staking::ConfigOp::Noop, + )); + + // members can unbond as long as total stake of the pool is above min nominator bond + assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10),); + assert_eq!(PoolMembers::::get(20).unwrap().unbonding_eras.len(), 1); + assert_eq!(PoolMembers::::get(20).unwrap().points, 0); + + // this member cannot unbond since it will cause `pool stake < MinNominatorBond` + assert_noop!( + Pools::unbond(RuntimeOrigin::signed(21), 21, 10), + StakingError::::InsufficientBond, + ); + + // members can call `chill` permissionlessly now + assert_ok!(Pools::chill(RuntimeOrigin::signed(20), 1)); + + // now another member can unbond. + assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10)); + assert_eq!(PoolMembers::::get(21).unwrap().unbonding_eras.len(), 1); + assert_eq!(PoolMembers::::get(21).unwrap().points, 0); + + // nominator can not resume nomination until depositor have enough stake + assert_noop!( + Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]), + PoolsError::::MinimumBondNotMet, + ); + + // other members joining pool does not affect the depositor's ability to resume nomination + assert_ok!(Pools::join(RuntimeOrigin::signed(22), 10, 1)); + + assert_noop!( + Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]), + PoolsError::::MinimumBondNotMet, + ); + + // depositor can bond extra stake + assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(10), BondExtra::FreeBalance(10))); + + // `chill` can not be called permissionlessly anymore + assert_noop!( + Pools::chill(RuntimeOrigin::signed(20), 1), + PoolsError::::NotNominator, + ); + + // now nominator can resume nomination + assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3])); + + // skip to make the unbonding period end. + CurrentEra::::set(Some(BondingDuration::get())); + + // members can now withdraw. + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0)); + assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 0)); + + assert_eq!( + staking_events_since_last_call(), + vec![ + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Chilled { stash: POOL1_BONDED }, + StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }, + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, // other member bonding + StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, // depositor bond extra + StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 20 }, + ] + ); + }) +} + #[test] fn pool_slash_e2e() { new_test_ext().execute_with(|| { -- GitLab From 30c32e3d8456984e19a7edf9e851b0db6135f376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:45:56 +0000 Subject: [PATCH 084/188] move substrate-bip39 into polkadot-sdk (#3579) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves [substrate-bip39](https://github.com/paritytech/substrate-bip39) into substrate. All git history is preserved. Dependencies have been updated to use the same version as the rest of the repo. Fixes https://github.com/paritytech/polkadot-sdk/issues/1934. --------- Co-authored-by: Maciej Hirsz Co-authored-by: Maciej Hirsz <1096222+maciejhirsz@users.noreply.github.com> Co-authored-by: Gav Wood Co-authored-by: Stanislav Tkach Co-authored-by: Robert Habermeier Co-authored-by: Pierre Krieger Co-authored-by: Demi M. Obenour Co-authored-by: Bastian Köcher Co-authored-by: NikVolf Co-authored-by: Bastian Köcher Co-authored-by: Benjamin Kampmann Co-authored-by: Maciej Hirsz Co-authored-by: cheme Co-authored-by: adoerr <0xad@gmx.net> Co-authored-by: Jun Jiang Co-authored-by: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> --- Cargo.lock | 172 +++---------- Cargo.toml | 1 + polkadot/node/core/approval-voting/Cargo.toml | 2 +- polkadot/node/subsystem-bench/Cargo.toml | 5 +- substrate/primitives/core/Cargo.toml | 4 +- substrate/utils/substrate-bip39/Cargo.toml | 31 +++ substrate/utils/substrate-bip39/README.md | 55 +++++ substrate/utils/substrate-bip39/src/lib.rs | 232 ++++++++++++++++++ 8 files changed, 359 insertions(+), 143 deletions(-) create mode 100644 substrate/utils/substrate-bip39/Cargo.toml create mode 100644 substrate/utils/substrate-bip39/README.md create mode 100644 substrate/utils/substrate-bip39/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 177d76b8706..4815e976b5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -744,12 +744,6 @@ dependencies = [ "nodrop", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arrayvec" version = "0.7.4" @@ -1334,7 +1328,7 @@ dependencies = [ "ark-std 0.4.0", "dleq_vrf", "fflonk", - "merlin 3.0.0", + "merlin", "rand_chacha 0.3.1", "rand_core 0.6.4", "ring 0.1.0", @@ -1559,18 +1553,6 @@ dependencies = [ "constant_time_eq 0.3.0", ] -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.9.0" @@ -1589,15 +1571,6 @@ dependencies = [ "generic-array 0.14.7", ] -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - [[package]] name = "blocking" version = "1.3.1" @@ -2634,9 +2607,9 @@ dependencies = [ [[package]] name = "clap-num" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488557e97528174edaa2ee268b23a809e0c598213a4bbcb4f34575a46fda147e" +checksum = "0e063d263364859dc54fb064cedb7c122740cd4733644b14b176c097f51e8ab7" dependencies = [ "num-traits", ] @@ -2854,11 +2827,10 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "colored" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", "lazy_static", "windows-sys 0.48.0", ] @@ -2886,7 +2858,7 @@ dependencies = [ "ark-std 0.4.0", "fflonk", "getrandom_or_panic", - "merlin 3.0.0", + "merlin", "rand_chacha 0.3.1", ] @@ -3526,16 +3498,6 @@ dependencies = [ "subtle 2.5.0", ] -[[package]] -name = "crypto-mac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" -dependencies = [ - "generic-array 0.14.7", - "subtle 2.5.0", -] - [[package]] name = "ctr" version = "0.7.0" @@ -4396,19 +4358,6 @@ dependencies = [ "url", ] -[[package]] -name = "curve25519-dalek" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" -dependencies = [ - "byteorder", - "digest 0.8.1", - "rand_core 0.5.1", - "subtle 2.5.0", - "zeroize", -] - [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -5238,12 +5187,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fallible-iterator" version = "0.2.0" @@ -5353,7 +5296,7 @@ dependencies = [ "ark-poly", "ark-serialize 0.4.2", "ark-std 0.4.0", - "merlin 3.0.0", + "merlin", ] [[package]] @@ -6428,16 +6371,6 @@ dependencies = [ "digest 0.9.0", ] -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac 0.11.0", - "digest 0.9.0", -] - [[package]] name = "hmac" version = "0.12.1" @@ -8124,18 +8057,6 @@ dependencies = [ "hash-db", ] -[[package]] -name = "merlin" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" -dependencies = [ - "byteorder", - "keccak", - "rand_core 0.5.1", - "zeroize", -] - [[package]] name = "merlin" version = "3.0.0" @@ -11642,19 +11563,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7924d1d0ad836f665c9065e26d016c673ece3993f30d340068b16f282afc1156" [[package]] -name = "paste" -version = "1.0.14" +name = "password-hash" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle 2.5.0", +] [[package]] -name = "pbkdf2" -version = "0.8.0" +name = "paste" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" -dependencies = [ - "crypto-mac 0.11.0", -] +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pbkdf2" @@ -11663,6 +11586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", + "password-hash", ] [[package]] @@ -12454,7 +12378,7 @@ dependencies = [ "kvdb", "kvdb-memorydb", "log", - "merlin 3.0.0", + "merlin", "parity-scale-codec", "parking_lot 0.12.1", "polkadot-node-jaeger", @@ -13672,7 +13596,7 @@ dependencies = [ "sc-keystore", "sc-network", "sc-service", - "schnorrkel 0.9.1", + "schnorrkel 0.11.4", "serde", "serde_yaml", "sha1", @@ -14921,7 +14845,7 @@ dependencies = [ "blake2 0.10.6", "common", "fflonk", - "merlin 3.0.0", + "merlin", ] [[package]] @@ -17103,22 +17027,6 @@ dependencies = [ "hashbrown 0.13.2", ] -[[package]] -name = "schnorrkel" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "curve25519-dalek 2.1.3", - "merlin 2.0.1", - "rand_core 0.5.1", - "sha2 0.8.2", - "subtle 2.5.0", - "zeroize", -] - [[package]] name = "schnorrkel" version = "0.10.2" @@ -17128,7 +17036,7 @@ dependencies = [ "arrayref", "arrayvec 0.7.4", "curve25519-dalek-ng", - "merlin 3.0.0", + "merlin", "rand_core 0.6.4", "sha2 0.9.9", "subtle-ng", @@ -17146,7 +17054,7 @@ dependencies = [ "arrayvec 0.7.4", "curve25519-dalek 4.1.2", "getrandom_or_panic", - "merlin 3.0.0", + "merlin", "rand_core 0.6.4", "serde_bytes", "sha2 0.10.7", @@ -17510,18 +17418,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha2" version = "0.9.9" @@ -17756,13 +17652,13 @@ dependencies = [ "hmac 0.12.1", "itertools 0.11.0", "libsecp256k1", - "merlin 3.0.0", + "merlin", "no-std-net", "nom", "num-bigint", "num-rational", "num-traits", - "pbkdf2 0.12.2", + "pbkdf2", "pin-project", "poly1305 0.8.0", "rand", @@ -18673,7 +18569,7 @@ dependencies = [ "lazy_static", "libsecp256k1", "log", - "merlin 3.0.0", + "merlin", "parity-scale-codec", "parking_lot 0.12.1", "paste", @@ -19829,14 +19725,14 @@ dependencies = [ [[package]] name = "substrate-bip39" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e620c7098893ba667438b47169c00aacdd9e7c10e042250ce2b60b087ec97328" +version = "0.4.7" dependencies = [ - "hmac 0.11.0", - "pbkdf2 0.8.0", - "schnorrkel 0.9.1", - "sha2 0.9.9", + "bip39", + "hmac 0.12.1", + "pbkdf2", + "rustc-hex", + "schnorrkel 0.11.4", + "sha2 0.10.7", "zeroize", ] diff --git a/Cargo.toml b/Cargo.toml index a2e22e0b927..80068596685 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -496,6 +496,7 @@ members = [ "substrate/utils/frame/rpc/system", "substrate/utils/frame/try-runtime/cli", "substrate/utils/prometheus", + "substrate/utils/substrate-bip39", "substrate/utils/wasm-builder", "templates/minimal/node", diff --git a/polkadot/node/core/approval-voting/Cargo.toml b/polkadot/node/core/approval-voting/Cargo.toml index f6d89dbc152..2a5b6198b9a 100644 --- a/polkadot/node/core/approval-voting/Cargo.toml +++ b/polkadot/node/core/approval-voting/Cargo.toml @@ -35,7 +35,7 @@ sp-consensus = { path = "../../../../substrate/primitives/consensus/common", def sp-consensus-slots = { path = "../../../../substrate/primitives/consensus/slots", default-features = false } sp-application-crypto = { path = "../../../../substrate/primitives/application-crypto", default-features = false, features = ["full_crypto"] } sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false } -# should match schnorrkel +# rand_core should match schnorrkel rand_core = "0.6.2" rand_chacha = { version = "0.3.1" } rand = "0.8.5" diff --git a/polkadot/node/subsystem-bench/Cargo.toml b/polkadot/node/subsystem-bench/Cargo.toml index 726e7de4587..7c60ff48269 100644 --- a/polkadot/node/subsystem-bench/Cargo.toml +++ b/polkadot/node/subsystem-bench/Cargo.toml @@ -78,8 +78,9 @@ sp-consensus-babe = { path = "../../../substrate/primitives/consensus/babe" } sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } sp-timestamp = { path = "../../../substrate/primitives/timestamp" } -schnorrkel = { version = "0.9.1", default-features = false } -rand_core = "0.6.2" # should match schnorrkel +schnorrkel = { version = "0.11.4", default-features = false } +# rand_core should match schnorrkel +rand_core = "0.6.2" rand_chacha = { version = "0.3.1" } paste = "1.0.14" orchestra = { version = "0.3.5", default-features = false, features = ["futures_channel"] } diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml index 8fcabfeb238..70ca7be6a2d 100644 --- a/substrate/primitives/core/Cargo.toml +++ b/substrate/primitives/core/Cargo.toml @@ -27,7 +27,7 @@ hash-db = { version = "0.16.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } bs58 = { version = "0.5.0", default-features = false, optional = true } rand = { version = "0.8.5", features = ["small_rng"], optional = true } -substrate-bip39 = { version = "0.4.5", optional = true } +substrate-bip39 = { path = "../../utils/substrate-bip39", optional = true } bip39 = { version = "2.0.0", default-features = false } zeroize = { version = "1.4.3", default-features = false } secrecy = { version = "0.8.0", default-features = false } @@ -116,7 +116,7 @@ std = [ "sp-std/std", "sp-storage/std", "ss58-registry/std", - "substrate-bip39", + "substrate-bip39/std", "thiserror", "tracing", "w3f-bls?/std", diff --git a/substrate/utils/substrate-bip39/Cargo.toml b/substrate/utils/substrate-bip39/Cargo.toml new file mode 100644 index 00000000000..a46f81ee24d --- /dev/null +++ b/substrate/utils/substrate-bip39/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "substrate-bip39" +version = "0.4.7" +license = "Apache-2.0" +description = "Converting BIP39 entropy to valid Substrate (sr25519) SecretKeys" +documentation = "https://docs.rs/substrate-bip39" +authors.workspace = true +edition.workspace = true +repository.workspace = true + +[dependencies] +hmac = "0.12.1" +pbkdf2 = { version = "0.12.2", default-features = false } +schnorrkel = { version = "0.11.4", default-features = false } +sha2 = { version = "0.10.7", default-features = false } +zeroize = { version = "1.4.3", default-features = false } + +[dev-dependencies] +bip39 = "2.0.0" +rustc-hex = "2.1.0" + +[features] +default = ["std"] +std = [ + "hmac/std", + "pbkdf2/std", + "schnorrkel/std", + "sha2/std", + "zeroize/alloc", + "zeroize/std", +] diff --git a/substrate/utils/substrate-bip39/README.md b/substrate/utils/substrate-bip39/README.md new file mode 100644 index 00000000000..368d18f406b --- /dev/null +++ b/substrate/utils/substrate-bip39/README.md @@ -0,0 +1,55 @@ +# Substrate BIP39 + +This is a crate for deriving secret keys for Ristretto compressed Ed25519 (should be compatible with Ed25519 at this +time) from BIP39 phrases. + +## Why? + +The natural approach here would be to use the 64-byte seed generated from the BIP39 phrase, and use that to construct +the key. This approach, while reasonable and fairly straight forward to implement, also means we would have to inherit +all the characteristics of seed generation. Since we are breaking compatibility with both BIP32 and BIP44 anyway (which +we are free to do as we are no longer using the Secp256k1 curve), there is also no reason why we should adhere to BIP39 +seed generation from the mnemonic. + +BIP39 seed generation was designed to be compatible with user supplied brain wallet phrases as well as being extensible +to wallets providing their own dictionaries and checksum mechanism. Issues with those two points: + +1. Brain wallets are a horrible idea, simply because humans are bad entropy generators. It's next to impossible to + educate users on how to use that feature in a secure manner. The 2048 rounds of PBKDF2 is a mere inconvenience that + offers no real protection against dictionary attacks for anyone equipped with modern consumer hardware. Brain wallets + have given users false sense of security. _People have lost money_ this way and wallet providers today tend to stick + to CSPRNG supplied dictionary phrases. + +2. Providing own dictionaries felt into the _you ain't gonna need it_ anti-pattern category on day 1. Wallet providers + (be it hardware or software) typically want their products to be compatibile with other wallets so that users can + migrate to their product without having to migrate all their assets. + +To achieve the above phrases have to be precisely encoded in _The One True Canonical Encoding_, for which UTF-8 NFKD was +chosen. This is largely irrelevant (and even ignored) for English phrases, as they encode to basically just ASCII in +virtualy every character encoding known to mankind, but immedietly becomes a problem for dictionaries that do use +non-ASCII characters. Even if the right encoding is used and implemented correctly, there are still [other caveats +present for some non-english dictionaries](https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md), +such as normalizing spaces to a canonical form, or making some latin based characters equivalent to their base in +dictionary lookups (eg. Spanish `ñ` and `n` are meant to be interchangeable). Thinking about all of this gives me a +headache, and opens doors for disagreements between buggy implementations, breaking compatibility. + +BIP39 does already provide a form of the mnemonic that is free from all of these issues: the entropy byte array. Since +veryfing the checksum requires that we recover the entropy from which the phrase was generated, no extra work is +actually needed here. Wallet implementators can encode the dictionaries in whatever encoding they find convenient (as +long as they are the standard BIP39 dictionaries), no harm in using UTF-16 string primitives that Java and JavaScript +provide. Since the dictionary is fixed and known, and the checksum is done on the entropy itself, the exact character +encoding used becomes irrelevant, as are the precise codepoints and amount of whitespace around the words. It is thus +much harder to create a buggy implementation. + +PBKDF2 was kept in place, along with the password. Using 24 words (with its 256 bits entropy) makes the extra hashing +redundant (if you could brute force 256 bit entropy, you can also just brute force secret keys), however some users +might be still using 12 word phrases from other applications. There is no good reason to prohibit users from recovering +their old wallets using 12 words that I can see, in which case the extra hashing does provide _some_ protection. +Passwords are also a feature that some power users find useful - particularly for creating a decoy address with a small +balance with empty password, while the funds proper are stored on an address that requires a password to be entered. + +## Why not ditch BIP39 altogether? + +Because there are hardware wallets that use a single phrase for the entire device, and operate multiple accounts on +multiple networks using that. A completely different wordlist would make their life much harder when it comes to +providing future Substrate support. diff --git a/substrate/utils/substrate-bip39/src/lib.rs b/substrate/utils/substrate-bip39/src/lib.rs new file mode 100644 index 00000000000..3673d20faed --- /dev/null +++ b/substrate/utils/substrate-bip39/src/lib.rs @@ -0,0 +1,232 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate alloc; +#[cfg(not(feature = "std"))] +use alloc::string::String; + +use hmac::Hmac; +use pbkdf2::pbkdf2; +use schnorrkel::keys::MiniSecretKey; +use sha2::Sha512; +use zeroize::Zeroize; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Error { + InvalidEntropy, +} + +/// `entropy` should be a byte array from a correctly recovered and checksumed BIP39. +/// +/// This function accepts slices of different length for different word lengths: +/// +/// + 16 bytes for 12 words. +/// + 20 bytes for 15 words. +/// + 24 bytes for 18 words. +/// + 28 bytes for 21 words. +/// + 32 bytes for 24 words. +/// +/// Any other length will return an error. +/// +/// `password` is analog to BIP39 seed generation itself, with an empty string being defalt. +pub fn mini_secret_from_entropy(entropy: &[u8], password: &str) -> Result { + let seed = seed_from_entropy(entropy, password)?; + Ok(MiniSecretKey::from_bytes(&seed[..32]).expect("Length is always correct; qed")) +} + +/// Similar to `mini_secret_from_entropy`, except that it provides the 64-byte seed directly. +pub fn seed_from_entropy(entropy: &[u8], password: &str) -> Result<[u8; 64], Error> { + if entropy.len() < 16 || entropy.len() > 32 || entropy.len() % 4 != 0 { + return Err(Error::InvalidEntropy); + } + + let mut salt = String::with_capacity(8 + password.len()); + salt.push_str("mnemonic"); + salt.push_str(password); + + let mut seed = [0u8; 64]; + + pbkdf2::>(entropy, salt.as_bytes(), 2048, &mut seed) + .map_err(|_| Error::InvalidEntropy)?; + + salt.zeroize(); + + Ok(seed) +} + +#[cfg(test)] +mod test { + use super::*; + + #[cfg(not(feature = "std"))] + use alloc::vec::Vec; + + use bip39::{Language, Mnemonic}; + use rustc_hex::FromHex; + + // phrase, entropy, seed, expanded secret_key + // + // ALL SEEDS GENERATED USING "Substrate" PASSWORD! + static VECTORS: &[[&str; 3]] = &[ + [ + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", + "00000000000000000000000000000000", + "44e9d125f037ac1d51f0a7d3649689d422c2af8b1ec8e00d71db4d7bf6d127e33f50c3d5c84fa3e5399c72d6cbbbbc4a49bf76f76d952f479d74655a2ef2d453", + ], + [ + "legal winner thank year wave sausage worth useful legal winner thank yellow", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "4313249608fe8ac10fd5886c92c4579007272cb77c21551ee5b8d60b780416850f1e26c1f4b8d88ece681cb058ab66d6182bc2ce5a03181f7b74c27576b5c8bf", + ], + [ + "letter advice cage absurd amount doctor acoustic avoid letter advice cage above", + "80808080808080808080808080808080", + "27f3eb595928c60d5bc91a4d747da40ed236328183046892ed6cd5aa9ae38122acd1183adf09a89839acb1e6eaa7fb563cc958a3f9161248d5a036e0d0af533d", + ], + [ + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", + "ffffffffffffffffffffffffffffffff", + "227d6256fd4f9ccaf06c45eaa4b2345969640462bbb00c5f51f43cb43418c7a753265f9b1e0c0822c155a9cabc769413ecc14553e135fe140fc50b6722c6b9df", + ], + [ + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent", + "000000000000000000000000000000000000000000000000", + "44e9d125f037ac1d51f0a7d3649689d422c2af8b1ec8e00d71db4d7bf6d127e33f50c3d5c84fa3e5399c72d6cbbbbc4a49bf76f76d952f479d74655a2ef2d453", + ], + [ + "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "cb1d50e14101024a88905a098feb1553d4306d072d7460e167a60ccb3439a6817a0afc59060f45d999ddebc05308714733c9e1e84f30feccddd4ad6f95c8a445", + ], + [ + "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", + "808080808080808080808080808080808080808080808080", + "9ddecf32ce6bee77f867f3c4bb842d1f0151826a145cb4489598fe71ac29e3551b724f01052d1bc3f6d9514d6df6aa6d0291cfdf997a5afdb7b6a614c88ab36a", + ], + [ + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when", + "ffffffffffffffffffffffffffffffffffffffffffffffff", + "8971cb290e7117c64b63379c97ed3b5c6da488841bd9f95cdc2a5651ac89571e2c64d391d46e2475e8b043911885457cd23e99a28b5a18535fe53294dc8e1693", + ], + [ + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", + "0000000000000000000000000000000000000000000000000000000000000000", + "44e9d125f037ac1d51f0a7d3649689d422c2af8b1ec8e00d71db4d7bf6d127e33f50c3d5c84fa3e5399c72d6cbbbbc4a49bf76f76d952f479d74655a2ef2d453", + ], + [ + "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", + "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", + "3037276a5d05fcd7edf51869eb841bdde27c574dae01ac8cfb1ea476f6bea6ef57ab9afe14aea1df8a48f97ae25b37d7c8326e49289efb25af92ba5a25d09ed3", + ], + [ + "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", + "8080808080808080808080808080808080808080808080808080808080808080", + "2c9c6144a06ae5a855453d98c3dea470e2a8ffb78179c2e9eb15208ccca7d831c97ddafe844ab933131e6eb895f675ede2f4e39837bb5769d4e2bc11df58ac42", + ], + [ + "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "047e89ef7739cbfe30da0ad32eb1720d8f62441dd4f139b981b8e2d0bd412ed4eb14b89b5098c49db2301d4e7df4e89c21e53f345138e56a5e7d63fae21c5939", + ], + [ + "ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic", + "9e885d952ad362caeb4efe34a8e91bd2", + "f4956be6960bc145cdab782e649a5056598fd07cd3f32ceb73421c3da27833241324dc2c8b0a4d847eee457e6d4c5429f5e625ece22abaa6a976e82f1ec5531d", + ], + [ + "gravity machine north sort system female filter attitude volume fold club stay feature office ecology stable narrow fog", + "6610b25967cdcca9d59875f5cb50b0ea75433311869e930b", + "fbcc5229ade0c0ff018cb7a329c5459f91876e4dde2a97ddf03c832eab7f26124366a543f1485479c31a9db0d421bda82d7e1fe562e57f3533cb1733b001d84d", + ], + [ + "hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay length", + "68a79eaca2324873eacc50cb9c6eca8cc68ea5d936f98787c60c7ebc74e6ce7c", + "7c60c555126c297deddddd59f8cdcdc9e3608944455824dd604897984b5cc369cad749803bb36eb8b786b570c9cdc8db275dbe841486676a6adf389f3be3f076", + ], + [ + "scheme spot photo card baby mountain device kick cradle pact join borrow", + "c0ba5a8e914111210f2bd131f3d5e08d", + "c12157bf2506526c4bd1b79a056453b071361538e9e2c19c28ba2cfa39b5f23034b974e0164a1e8acd30f5b4c4de7d424fdb52c0116bfc6a965ba8205e6cc121", + ], + [ + "horn tenant knee talent sponsor spell gate clip pulse soap slush warm silver nephew swap uncle crack brave", + "6d9be1ee6ebd27a258115aad99b7317b9c8d28b6d76431c3", + "23766723e970e6b79dec4d5e4fdd627fd27d1ee026eb898feb9f653af01ad22080c6f306d1061656d01c4fe9a14c05f991d2c7d8af8730780de4f94cd99bd819", + ], + [ + "panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed nation flash devote level hobby quick inner drive ghost inside", + "9f6a2878b2520799a44ef18bc7df394e7061a224d2c33cd015b157d746869863", + "f4c83c86617cb014d35cd87d38b5ef1c5d5c3d58a73ab779114438a7b358f457e0462c92bddab5a406fe0e6b97c71905cf19f925f356bc673ceb0e49792f4340", + ], + [ + "cat swing flag economy stadium alone churn speed unique patch report train", + "23db8160a31d3e0dca3688ed941adbf3", + "719d4d4de0638a1705bf5237262458983da76933e718b2d64eb592c470f3c5d222e345cc795337bb3da393b94375ff4a56cfcd68d5ea25b577ee9384d35f4246", + ], + [ + "light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain crack supply proud access", + "8197a4a47f0425faeaa69deebc05ca29c0a5b5cc76ceacc0", + "7ae1291db32d16457c248567f2b101e62c5549d2a64cd2b7605d503ec876d58707a8d663641e99663bc4f6cc9746f4852e75e7e54de5bc1bd3c299c9a113409e", + ], + [ + "all hour make first leader extend hole alien behind guard gospel lava path output census museum junior mass reopen famous sing advance salt reform", + "066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad", + "a911a5f4db0940b17ecb79c4dcf9392bf47dd18acaebdd4ef48799909ebb49672947cc15f4ef7e8ef47103a1a91a6732b821bda2c667e5b1d491c54788c69391", + ], + [ + "vessel ladder alter error federal sibling chat ability sun glass valve picture", + "f30f8c1da665478f49b001d94c5fc452", + "4e2314ca7d9eebac6fe5a05a5a8d3546bc891785414d82207ac987926380411e559c885190d641ff7e686ace8c57db6f6e4333c1081e3d88d7141a74cf339c8f", + ], + [ + "scissors invite lock maple supreme raw rapid void congress muscle digital elegant little brisk hair mango congress clump", + "c10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05", + "7a83851102849edc5d2a3ca9d8044d0d4f00e5c4a292753ed3952e40808593251b0af1dd3c9ed9932d46e8608eb0b928216a6160bd4fc775a6e6fbd493d7c6b2", + ], + [ + "void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold", + "f585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f", + "938ba18c3f521f19bd4a399c8425b02c716844325b1a65106b9d1593fbafe5e0b85448f523f91c48e331995ff24ae406757cff47d11f240847352b348ff436ed", + ] + ]; + + #[test] + fn vectors_are_correct() { + for vector in VECTORS { + let phrase = vector[0]; + + let expected_entropy: Vec = vector[1].from_hex().unwrap(); + let expected_seed: Vec = vector[2].from_hex().unwrap(); + + let mnemonic = Mnemonic::parse_in(Language::English, phrase).unwrap(); + let seed = seed_from_entropy(&mnemonic.to_entropy(), "Substrate").unwrap(); + let secret = mini_secret_from_entropy(&mnemonic.to_entropy(), "Substrate") + .unwrap() + .to_bytes(); + + assert_eq!( + mnemonic.to_entropy(), + &expected_entropy[..], + "Entropy is incorrect for {}", + phrase + ); + assert_eq!(&seed[..], &expected_seed[..], "Seed is incorrect for {}", phrase); + assert_eq!(&secret[..], &expected_seed[..32], "Secret is incorrect for {}", phrase); + } + } +} -- GitLab From 50cc1c2f7efa0e61ac773b8e89171c9640315475 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Thu, 7 Mar 2024 11:40:30 +0000 Subject: [PATCH 085/188] Add documentation around pallet coupling (#3542) substrate.io deprecation companion: https://github.com/substrate-developer-hub/substrate-docs/pull/2139 pba-content companion: https://github.com/Polkadot-Blockchain-Academy/pba-content/pull/978 partially inspired by: https://github.com/paritytech/polkadot-sdk/issues/3535 --------- Co-authored-by: Ankan <10196091+Ank4n@users.noreply.github.com> --- Cargo.lock | 1 + docs/sdk/Cargo.toml | 1 + docs/sdk/src/polkadot_sdk/frame_runtime.rs | 144 +++++---- .../reference_docs/frame_pallet_coupling.rs | 296 ++++++++++++++++++ docs/sdk/src/reference_docs/mod.rs | 4 + substrate/frame/support/src/lib.rs | 5 +- 6 files changed, 374 insertions(+), 77 deletions(-) create mode 100644 docs/sdk/src/reference_docs/frame_pallet_coupling.rs diff --git a/Cargo.lock b/Cargo.lock index 4815e976b5d..e38f09db4d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13332,6 +13332,7 @@ dependencies = [ "frame-support", "frame-system", "kitchensink-runtime", + "pallet-assets", "pallet-aura", "pallet-authorship", "pallet-balances", diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index 735b3d7df61..8b498d407c0 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -65,6 +65,7 @@ pallet-aura = { path = "../../substrate/frame/aura", default-features = false } # Pallets and FRAME internals pallet-timestamp = { path = "../../substrate/frame/timestamp" } pallet-balances = { path = "../../substrate/frame/balances" } +pallet-assets = { path = "../../substrate/frame/assets" } pallet-transaction-payment = { path = "../../substrate/frame/transaction-payment" } pallet-utility = { path = "../../substrate/frame/utility" } pallet-multisig = { path = "../../substrate/frame/multisig" } diff --git a/docs/sdk/src/polkadot_sdk/frame_runtime.rs b/docs/sdk/src/polkadot_sdk/frame_runtime.rs index c9eba7d64bd..f178fc82bf4 100644 --- a/docs/sdk/src/polkadot_sdk/frame_runtime.rs +++ b/docs/sdk/src/polkadot_sdk/frame_runtime.rs @@ -87,93 +87,89 @@ //! * writing a runtime in pure Rust, as done in [this template](https://github.com/JoshOrndorff/frameless-node-template). //! * writing a runtime in AssemblyScript,as explored in [this project](https://github.com/LimeChain/subsembly). -#[cfg(test)] -mod tests { - use frame::prelude::*; +use frame::prelude::*; - /// A FRAME based pallet. This `mod` is the entry point for everything else. All - /// `#[pallet::xxx]` macros must be defined in this `mod`. Although, frame also provides an - /// experimental feature to break these parts into different `mod`s. See [`pallet_examples`] for - /// more. - #[docify::export] - #[frame::pallet(dev_mode)] - pub mod pallet { - use super::*; +/// A FRAME based pallet. This `mod` is the entry point for everything else. All +/// `#[pallet::xxx]` macros must be defined in this `mod`. Although, frame also provides an +/// experimental feature to break these parts into different `mod`s. See [`pallet_examples`] for +/// more. +#[docify::export] +#[frame::pallet(dev_mode)] +pub mod pallet { + use super::*; - /// The configuration trait of a pallet. Mandatory. Allows a pallet to receive types at a - /// later point from the runtime that wishes to contain it. It allows the pallet to be - /// parameterized over both types and values. - #[pallet::config] - pub trait Config: frame_system::Config { - /// A type that is not known now, but the runtime that will contain this pallet will - /// know it later, therefore we define it here as an associated type. - type RuntimeEvent: IsType<::RuntimeEvent> - + From>; + /// The configuration trait of a pallet. Mandatory. Allows a pallet to receive types at a + /// later point from the runtime that wishes to contain it. It allows the pallet to be + /// parameterized over both types and values. + #[pallet::config] + pub trait Config: frame_system::Config { + /// A type that is not known now, but the runtime that will contain this pallet will + /// know it later, therefore we define it here as an associated type. + type RuntimeEvent: IsType<::RuntimeEvent> + From>; - /// A parameterize-able value that we receive later via the `Get<_>` trait. - type ValueParameter: Get; + /// A parameterize-able value that we receive later via the `Get<_>` trait. + type ValueParameter: Get; - /// Similar to [`Config::ValueParameter`], but using `const`. Both are functionally - /// equal, but offer different tradeoffs. - const ANOTHER_VALUE_PARAMETER: u32; - } + /// Similar to [`Config::ValueParameter`], but using `const`. Both are functionally + /// equal, but offer different tradeoffs. + const ANOTHER_VALUE_PARAMETER: u32; + } - /// A mandatory struct in each pallet. All functions callable by external users (aka. - /// transactions) must be attached to this type (see [`frame::pallet_macros::call`]). For - /// convenience, internal (private) functions can also be attached to this type. - #[pallet::pallet] - pub struct Pallet(PhantomData); + /// A mandatory struct in each pallet. All functions callable by external users (aka. + /// transactions) must be attached to this type (see [`frame::pallet_macros::call`]). For + /// convenience, internal (private) functions can also be attached to this type. + #[pallet::pallet] + pub struct Pallet(PhantomData); - /// The events tha this pallet can emit. - #[pallet::event] - pub enum Event {} + /// The events tha this pallet can emit. + #[pallet::event] + pub enum Event {} - /// A storage item that this pallet contains. This will be part of the state root trie/root - /// of the blockchain. - #[pallet::storage] - pub type Value = StorageValue; + /// A storage item that this pallet contains. This will be part of the state root trie/root + /// of the blockchain. + #[pallet::storage] + pub type Value = StorageValue; - /// All *dispatchable* call functions (aka. transactions) are attached to `Pallet` in a - /// `impl` block. - #[pallet::call] - impl Pallet { - /// This will be callable by external users, and has two u32s as a parameter. - pub fn some_dispatchable( - _origin: OriginFor, - _param: u32, - _other_para: u32, - ) -> DispatchResult { - Ok(()) - } + /// All *dispatchable* call functions (aka. transactions) are attached to `Pallet` in a + /// `impl` block. + #[pallet::call] + impl Pallet { + /// This will be callable by external users, and has two u32s as a parameter. + pub fn some_dispatchable( + _origin: OriginFor, + _param: u32, + _other_para: u32, + ) -> DispatchResult { + Ok(()) } } +} - /// A simple runtime that contains the above pallet and `frame_system`, the mandatory pallet of - /// all runtimes. This runtime is for testing, but it shares a lot of similarities with a *real* - /// runtime. - #[docify::export] - pub mod runtime { - use super::pallet as pallet_example; - use frame::{prelude::*, testing_prelude::*}; - - // The major macro that amalgamates pallets into `enum Runtime` - construct_runtime!( - pub enum Runtime { - System: frame_system, - Example: pallet_example, - } - ); +/// A simple runtime that contains the above pallet and `frame_system`, the mandatory pallet of +/// all runtimes. This runtime is for testing, but it shares a lot of similarities with a *real* +/// runtime. +#[docify::export] +pub mod runtime { + use super::pallet as pallet_example; + use frame::{prelude::*, testing_prelude::*}; - // These `impl` blocks specify the parameters of each pallet's `trait Config`. - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] - impl frame_system::Config for Runtime { - type Block = MockBlock; + // The major macro that amalgamates pallets into `enum Runtime` + construct_runtime!( + pub enum Runtime { + System: frame_system, + Example: pallet_example, } + ); - impl pallet_example::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ValueParameter = ConstU32<42>; - const ANOTHER_VALUE_PARAMETER: u32 = 42; - } + // These `impl` blocks specify the parameters of each pallet's `trait Config`. + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Runtime { + type Block = MockBlock; + } + + impl pallet_example::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ValueParameter = ConstU32<42>; + const ANOTHER_VALUE_PARAMETER: u32 = 42; } } diff --git a/docs/sdk/src/reference_docs/frame_pallet_coupling.rs b/docs/sdk/src/reference_docs/frame_pallet_coupling.rs new file mode 100644 index 00000000000..942717ecfb2 --- /dev/null +++ b/docs/sdk/src/reference_docs/frame_pallet_coupling.rs @@ -0,0 +1,296 @@ +//! # FRAME Pallet Coupling +//! +//! This reference document explains how FRAME pallets can be combined to interact together. +//! +//! It is suggested to re-read [`crate::polkadot_sdk::frame_runtime`], notably the information +//! around [`frame::pallet_macros::config`]. Recall that: +//! +//! > Configuration trait of a pallet: It allows a pallet to receive types at a later +//! > point from the runtime that wishes to contain it. It allows the pallet to be parameterized +//! > over both types and values. +//! +//! ## Context, Background +//! +//! FRAME pallets, as per described in [`crate::polkadot_sdk::frame_runtime`] are: +//! +//! > A pallet is a unit of encapsulated logic. It has a clearly defined responsibility and can be +//! linked to other pallets. +//! +//! That is to say: +//! +//! * *encapsulated*: Ideally, a FRAME pallet contains encapsulated logic which has clear +//! boundaries. It is generally a bad idea to build a single monolithic pallet that does multiple +//! things, such as handling currencies, identities and staking all at the same time. +//! * *linked to other pallets*: But, adhering extensively to the above also hinders the ability to +//! write useful applications. Pallets often need to work with each other, communicate and use +//! each other's functionalities. +//! +//! The broad principle that allows pallets to be linked together is the same way through which a +//! pallet uses its `Config` trait to receive types and values from the runtime that contains it. +//! +//! There are generally two ways to achieve this: +//! +//! 1. Tight coupling pallets +//! 2. Loose coupling pallets +//! +//! To explain the difference between the two, consider two pallets, `A` and `B`. In both cases, `A` +//! wants to use some functionality exposed by `B`. +//! +//! When tightly coupling pallets, `A` can only exist in a runtime if `B` is also present in the +//! same runtime. That is, `A` is expressing that can only work if `B` is present. +//! +//! This translates to the following Rust code: +//! +//! ``` +//! trait Pallet_B_Config {} +//! trait Pallet_A_Config: Pallet_B_Config {} +//! ``` +//! +//! Contrary, when pallets are loosely coupled, `A` expresses that some functionality, expressed via +//! a trait `F`, needs to be fulfilled. This trait is then implemented by `B`, and the two pallets +//! are linked together at the runtime level. This means that `A` only relies on the implementation +//! of `F`, which may be `B`, or another implementation of `F`. +//! +//! This translates to the following Rust code: +//! +//! ``` +//! trait F {} +//! trait Pallet_A_Config { +//! type F: F; +//! } +//! // Pallet_B will implement and fulfill `F`. +//! ``` +//! +//! ## Example +//! +//! Consider the following example, in which `pallet-foo` needs another pallet to provide the block +//! author to it, and `pallet-author` which has access to this information. +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", pallet_foo)] +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", pallet_author)] +//! +//! ### Tight Coupling Pallets +//! +//! To tightly couple `pallet-foo` and `pallet-author`, we use Rust's supertrait system. When a +//! pallet makes its own `trait Config` be bounded by another pallet's `trait Config`, it is +//! expressing two things: +//! +//! 1. that it can only exist in a runtime if the other pallet is also present. +//! 2. that it can use the other pallet's functionality. +//! +//! `pallet-foo`'s `Config` would then look like: +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", tight_config)] +//! +//! And `pallet-foo` can use the method exposed by `pallet_author::Pallet` directly: +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", tight_usage)] +//! +//! +//! ### Loosely Coupling Pallets +//! +//! If `pallet-foo` wants to *not* rely on `pallet-author` directly, it can leverage its +//! `Config`'s associated types. First, we need a trait to express the functionality that +//! `pallet-foo` wants to obtain: +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", AuthorProvider)] +//! +//! > We sometimes refer to such traits that help two pallets interact as "glue traits". +//! +//! Next, `pallet-foo` states that it needs this trait to be provided to it, at the runtime level, +//! via an associated type: +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", loose_config)] +//! +//! Then, `pallet-foo` can use this trait to obtain the block author, without knowing where it comes +//! from: +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", loose_usage)] +//! +//! Then, if `pallet-author` implements this glue-trait: +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", pallet_author_provider)] +//! +//! And upon the creation of the runtime, the two pallets are linked together as such: +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", runtime_author_provider)] +//! +//! Crucially, when using loose coupling, we gain the flexibility of providing different +//! implementations of `AuthorProvider`, such that different users of a `pallet-foo` can use +//! different ones, without any code change being needed. For example, in the code snippets of this +//! module, you can fund [`OtherAuthorProvider`] which is an alternative implementation of +//! [`AuthorProvider`]. +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", other_author_provider)] +//! +//! A common pattern in polkadot-sdk is to provide an implementation of such glu traits for the unit +//! type as a "default/test behavior". +#![doc = docify::embed!("./src/reference_docs/frame_pallet_coupling.rs", unit_author_provider)] +//! +//! ## Frame System +//! +//! With the above information in context, we can conclude that **`frame_system` is a special pallet +//! that is tightly coupled with every other pallet**. This is because it provides the fundamental +//! system functionality that every pallet needs, such as some types like +//! [`frame::prelude::frame_system::Config::AccountId`], +//! [`frame::prelude::frame_system::Config::Hash`], and some functionality such as block number, +//! etc. +//! +//! ## Recap +//! +//! To recap, consider the following rules of thumb: +//! +//! * In all cases, try and break down big pallets apart with clear boundaries of responsibility. In +//! general, it is easier to argue about multiple pallet if they only communicate together via a +//! known trait, rather than having access to all of each others public items, such as storage and +//! dispatchables. +//! * If a group of pallets are meant to work together, and but are not foreseen to be generalized, +//! or used by others, consider tightly coupling pallets, *if it simplifies the development*. +//! * If a pallet needs a functionality provided by another pallet, but multiple implementations can +//! be foreseen, consider loosely coupling pallets. +//! +//! For example, all pallets in `polkadot-sdk` that needed to work with currencies could have been +//! tightly coupled with [`pallet_balances`]. But, `polkadot-sdk` also provides [`pallet_assets`] +//! (and more implementations by the community), therefore all pallets use traits to loosely couple +//! with balances or assets pallet. More on this in [`crate::reference_docs::frame_currency`]. +//! +//! ## Further References +//! +//! - +//! - +//! +//! [`AuthorProvider`]: crate::reference_docs::frame_pallet_coupling::AuthorProvider +//! [`OtherAuthorProvider`]: crate::reference_docs::frame_pallet_coupling::OtherAuthorProvider + +#![allow(unused)] + +use frame::prelude::*; + +#[docify::export] +#[frame::pallet] +pub mod pallet_foo { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + impl Pallet { + fn do_stuff_with_author() { + // needs block author here + } + } +} + +#[docify::export] +#[frame::pallet] +pub mod pallet_author { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + impl Pallet { + pub fn author() -> T::AccountId { + todo!("somehow has access to the block author and can return it here") + } + } +} + +#[frame::pallet] +pub mod pallet_foo_tight { + use super::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[docify::export(tight_config)] + /// This pallet can only live in a runtime that has both `frame_system` and `pallet_author`. + #[pallet::config] + pub trait Config: frame_system::Config + pallet_author::Config {} + + #[docify::export(tight_usage)] + impl Pallet { + // anywhere in `pallet-foo`, we can call into `pallet-author` directly, namely because + // `T: pallet_author::Config` + fn do_stuff_with_author() { + let _ = pallet_author::Pallet::::author(); + } + } +} + +#[docify::export] +/// Abstraction over "something that can provide the block author". +pub trait AuthorProvider { + fn author() -> AccountId; +} + +#[frame::pallet] +pub mod pallet_foo_loose { + use super::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[docify::export(loose_config)] + #[pallet::config] + pub trait Config: frame_system::Config { + /// This pallet relies on the existence of something that implements [`AuthorProvider`], + /// which may or may not be `pallet-author`. + type AuthorProvider: AuthorProvider; + } + + #[docify::export(loose_usage)] + impl Pallet { + fn do_stuff_with_author() { + let _ = T::AuthorProvider::author(); + } + } +} + +#[docify::export(pallet_author_provider)] +impl AuthorProvider for pallet_author::Pallet { + fn author() -> T::AccountId { + pallet_author::Pallet::::author() + } +} + +pub struct OtherAuthorProvider; + +#[docify::export(other_author_provider)] +impl AuthorProvider for OtherAuthorProvider { + fn author() -> AccountId { + todo!("somehow get the block author here") + } +} + +#[docify::export(unit_author_provider)] +impl AuthorProvider for () { + fn author() -> AccountId { + todo!("somehow get the block author here") + } +} + +pub mod runtime { + use super::*; + use cumulus_pallet_aura_ext::pallet; + use frame::{runtime::prelude::*, testing_prelude::*}; + + construct_runtime!( + pub struct Runtime { + System: frame_system, + PalletFoo: pallet_foo_loose, + PalletAuthor: pallet_author, + } + ); + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + impl frame_system::Config for Runtime { + type Block = MockBlock; + } + + impl pallet_author::Config for Runtime {} + + #[docify::export(runtime_author_provider)] + impl pallet_foo_loose::Config for Runtime { + type AuthorProvider = pallet_author::Pallet; + // which is also equivalent to + // type AuthorProvider = PalletAuthor; + } +} diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index 3fd815d2a15..f4b52208e2f 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -103,3 +103,7 @@ pub mod light_nodes; /// Learn about the offchain workers, how they function, and how to use them, as provided by the /// [`frame`] APIs. pub mod frame_offchain_workers; + +/// Learn about the different ways through which multiple [`frame`] pallets can be combined to work +/// together. +pub mod frame_pallet_coupling; diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index b5b1ac09c60..6ea7fa33e77 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -1531,9 +1531,8 @@ pub mod pallet_macros { /// The attribute currently only supports enum definitions, and identifiers that are named /// `FreezeReason`, `HoldReason`, `LockId` or `SlashReason`. Arbitrary identifiers for the /// enum are not supported. The aggregate enum generated by - /// [`frame_support::construct_runtime`](frame_support::construct_runtime) will have the - /// name of `RuntimeFreezeReason`, `RuntimeHoldReason`, `RuntimeLockId` and - /// `RuntimeSlashReason` respectively. + /// [`frame_support::construct_runtime`] will have the name of `RuntimeFreezeReason`, + /// `RuntimeHoldReason`, `RuntimeLockId` and `RuntimeSlashReason` respectively. /// /// NOTE: The aggregate enum generated by `construct_runtime` generates a conversion /// function from the pallet enum to the aggregate enum, and automatically derives the -- GitLab From c89b3997df47408a324e8870693e80ddc4a42b7d Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Thu, 7 Mar 2024 12:47:30 +0100 Subject: [PATCH 086/188] Contracts: Remove changelog (#3605) This is not maintained, and we should be able to get information from the release changelog --- substrate/frame/contracts/CHANGELOG.md | 116 ------------------------- 1 file changed, 116 deletions(-) delete mode 100644 substrate/frame/contracts/CHANGELOG.md diff --git a/substrate/frame/contracts/CHANGELOG.md b/substrate/frame/contracts/CHANGELOG.md deleted file mode 100644 index aca94e5b149..00000000000 --- a/substrate/frame/contracts/CHANGELOG.md +++ /dev/null @@ -1,116 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -The semantic versioning guarantees cover the interface to the Substrate runtime which -includes this pallet as a dependency. This module will also add storage migrations whenever -changes require it. Stability with regard to offchain tooling is explicitly excluded from -this guarantee: For example adding a new field to an in-storage data structure will require -changes to frontends to properly display it. However, those changes will still be regarded -as a minor version bump. - -The interface provided to smart contracts will adhere to semver with one exception: Even -major version bumps will be backwards compatible with regard to already deployed contracts. -In other words: Upgrading this pallet will not break pre-existing contracts. - -## [Unreleased] - -### Added - -- Forbid calling back to contracts after switching to runtime -[#13443](https://github.com/paritytech/substrate/pull/13443) - -- Allow contracts to dispatch calls into the runtime (**unstable**) -[#9276](https://github.com/paritytech/substrate/pull/9276) - -- New version of `seal_call` that offers more features. -[#8909](https://github.com/paritytech/substrate/pull/8909) - -- New `instantiate` RPC that allows clients to dry-run contract instantiation. -[#8451](https://github.com/paritytech/substrate/pull/8451) - -- New version of `seal_random` which exposes additional information. -[#8329](https://github.com/paritytech/substrate/pull/8329) - -### Changed - -- Replaced storage rent with automatic storage deposits -[#9669](https://github.com/paritytech/substrate/pull/9669) -[#10082](https://github.com/paritytech/substrate/pull/10082) - -- Replaced `seal_println` with the `seal_debug_message` API which allows outputting debug -messages to the console and RPC clients. -[#8773](https://github.com/paritytech/substrate/pull/8773) -[#9550](https://github.com/paritytech/substrate/pull/9550) - -- Make storage and fields of `Schedule` private to the crate. -[#8359](https://github.com/paritytech/substrate/pull/8359) - -### Fixed - -- Remove pre-charging which caused wrongly estimated weights -[#8976](https://github.com/paritytech/substrate/pull/8976) - -## [v3.0.0] 2021-02-25 - -This version constitutes the first release that brings any stability guarantees (see above). - -### Added - -- Emit an event when a contract terminates (self-destructs). -[#8014](https://github.com/paritytech/substrate/pull/8014) - -- Charge rent for code stored on the chain in addition to the already existing -rent that is paid for data storage. -[#7935](https://github.com/paritytech/substrate/pull/7935) - -- Allow the runtime to configure per storage item costs in addition -to the already existing per byte costs. -[#7819](https://github.com/paritytech/substrate/pull/7819) - -- Contracts are now deleted lazily so that the user who removes a contract -does not need to pay for the deletion of the contract storage. -[#7740](https://github.com/paritytech/substrate/pull/7740) - -- Allow runtime authors to define chain extensions in order to provide custom -functionality to contracts. -[#7548](https://github.com/paritytech/substrate/pull/7548) -[#8003](https://github.com/paritytech/substrate/pull/8003) - -- Proper weights which are fully automated by benchmarking. -[#6715](https://github.com/paritytech/substrate/pull/6715) -[#7017](https://github.com/paritytech/substrate/pull/7017) -[#7361](https://github.com/paritytech/substrate/pull/7361) - -### Changed - -- Collect the rent for one block during instantiation. -[#7847](https://github.com/paritytech/substrate/pull/7847) - -- Instantiation takes a `salt` argument to allow for easier instantion of the -same code by the same sender. -[#7482](https://github.com/paritytech/substrate/pull/7482) - -- Improve the information returned by the `contracts_call` RPC. -[#7468](https://github.com/paritytech/substrate/pull/7468) - -- Simplify the node configuration necessary to add this module. -[#7409](https://github.com/paritytech/substrate/pull/7409) - -### Fixed - -- Consider the code size of a contract in the weight that is charged for -loading a contract from storage. -[#8086](https://github.com/paritytech/substrate/pull/8086) - -- Fix possible overflow in storage size calculation -[#7885](https://github.com/paritytech/substrate/pull/7885) - -- Cap the surcharge reward that can be claimed. -[#7870](https://github.com/paritytech/substrate/pull/7870) - -- Fix a possible DoS vector where contracts could allocate too large buffers. -[#7818](https://github.com/paritytech/substrate/pull/7818) -- GitLab From 6792d4b5b84e80ab771aa32666ce08dbcca39b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Thu, 7 Mar 2024 20:10:12 +0800 Subject: [PATCH 087/188] Disable flaky test (#3602) Unfortunately, the flakiness wasn't fixed by https://github.com/paritytech/polkadot-sdk/pull/3595. Let's disable the test in the meanwhile since it is hanging on the CI a lot. --------- Co-authored-by: Liam Aharon --- substrate/client/consensus/manual-seal/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/substrate/client/consensus/manual-seal/src/lib.rs b/substrate/client/consensus/manual-seal/src/lib.rs index f04c0d42d60..c3d360f0719 100644 --- a/substrate/client/consensus/manual-seal/src/lib.rs +++ b/substrate/client/consensus/manual-seal/src/lib.rs @@ -467,7 +467,10 @@ mod tests { assert_eq!(client.header(created_block.hash).unwrap().unwrap().number, 1) } - #[tokio::test] + // TODO: enable once the flakiness is fixed + // See https://github.com/paritytech/polkadot-sdk/issues/3603 + //#[tokio::test] + #[allow(unused)] async fn instant_seal_delayed_finalize() { let builder = TestClientBuilder::new(); let (client, select_chain) = builder.build_with_longest_chain(); -- GitLab From de9411aa4c29a28cb2c964cce8153bdaa1bdc7ea Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Thu, 7 Mar 2024 13:39:39 +0100 Subject: [PATCH 088/188] Contracts: Remove unstable on lock/unlock_delegate_dependency host fns (#3606) Oversight from PR https://github.com/paritytech/polkadot-sdk/pull/3384. These 2 functions should have been tagged as stable --- prdoc/pr_3606.prdoc | 9 +++++++++ substrate/frame/contracts/src/wasm/runtime.rs | 2 -- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 prdoc/pr_3606.prdoc diff --git a/prdoc/pr_3606.prdoc b/prdoc/pr_3606.prdoc new file mode 100644 index 00000000000..18b71de9477 --- /dev/null +++ b/prdoc/pr_3606.prdoc @@ -0,0 +1,9 @@ +title: "[pallet_contracts] mark lock/unlock_delegate_dependency as stable" + +doc: + - audience: Runtime Dev + description: | + Lock and unlock delegate dependency are stable now, so we can mark them as such. + +crates: + - name: pallet-contracts diff --git a/substrate/frame/contracts/src/wasm/runtime.rs b/substrate/frame/contracts/src/wasm/runtime.rs index f440c818166..402ff78dcde 100644 --- a/substrate/frame/contracts/src/wasm/runtime.rs +++ b/substrate/frame/contracts/src/wasm/runtime.rs @@ -2305,7 +2305,6 @@ pub mod env { /// Adds a new delegate dependency to the contract. /// See [`pallet_contracts_uapi::HostFn::lock_delegate_dependency`]. - #[unstable] fn lock_delegate_dependency(ctx: _, memory: _, code_hash_ptr: u32) -> Result<(), TrapReason> { ctx.charge_gas(RuntimeCosts::LockDelegateDependency)?; let code_hash = ctx.read_sandbox_memory_as(memory, code_hash_ptr)?; @@ -2315,7 +2314,6 @@ pub mod env { /// Removes the delegate dependency from the contract. /// see [`pallet_contracts_uapi::HostFn::unlock_delegate_dependency`]. - #[unstable] fn unlock_delegate_dependency(ctx: _, memory: _, code_hash_ptr: u32) -> Result<(), TrapReason> { ctx.charge_gas(RuntimeCosts::UnlockDelegateDependency)?; let code_hash = ctx.read_sandbox_memory_as(memory, code_hash_ptr)?; -- GitLab From 629506ce061db76d31d4f7a81f4a497752b27259 Mon Sep 17 00:00:00 2001 From: Muharem Date: Thu, 7 Mar 2024 16:13:17 +0100 Subject: [PATCH 089/188] Deprecate xcm::body::TREASURER_INDEX constant, use standard Treasury varian instead (#3608) Deprecate the `xcm::body::TREASURER_INDEX` constant and use the standard Treasury variant from the `xcm::BodyId` type instead. To align with the production runtimes: https://github.com/polkadot-fellows/runtimes/pull/149 --- .../collectives/collectives-westend/src/xcm_config.rs | 2 +- polkadot/runtime/westend/constants/src/lib.rs | 2 ++ polkadot/runtime/westend/src/xcm_config.rs | 6 ++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs index cc25cbda0a4..87f637d5b59 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs @@ -59,7 +59,7 @@ parameter_types! { pub const GovernanceLocation: Location = Location::parent(); pub const FellowshipAdminBodyId: BodyId = BodyId::Index(xcm_constants::body::FELLOWSHIP_ADMIN_INDEX); pub AssetHub: Location = (Parent, Parachain(1000)).into(); - pub const TreasurerBodyId: BodyId = BodyId::Index(xcm_constants::body::TREASURER_INDEX); + pub const TreasurerBodyId: BodyId = BodyId::Treasury; pub AssetHubUsdtId: AssetId = (PalletInstance(50), GeneralIndex(1984)).into(); pub UsdtAssetHub: LocatableAssetId = LocatableAssetId { location: AssetHub::get(), diff --git a/polkadot/runtime/westend/constants/src/lib.rs b/polkadot/runtime/westend/constants/src/lib.rs index 3bc27177d7a..c98f4b114fd 100644 --- a/polkadot/runtime/westend/constants/src/lib.rs +++ b/polkadot/runtime/westend/constants/src/lib.rs @@ -130,6 +130,8 @@ pub mod xcm { const ROOT_INDEX: u32 = 0; // The bodies corresponding to the Polkadot OpenGov Origins. pub const FELLOWSHIP_ADMIN_INDEX: u32 = 1; + #[deprecated = "Will be removed after August 2024; Use `xcm::latest::BodyId::Treasury` \ + instead"] pub const TREASURER_INDEX: u32 = 2; } } diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index c3aa75a86a4..c57af987ca7 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -34,9 +34,7 @@ use runtime_common::{ }; use sp_core::ConstU32; use westend_runtime_constants::{ - currency::CENTS, - system_parachain::*, - xcm::body::{FELLOWSHIP_ADMIN_INDEX, TREASURER_INDEX}, + currency::CENTS, system_parachain::*, xcm::body::FELLOWSHIP_ADMIN_INDEX, }; use xcm::latest::prelude::*; use xcm_builder::{ @@ -231,7 +229,7 @@ parameter_types! { // FellowshipAdmin pluralistic body. pub const FellowshipAdminBodyId: BodyId = BodyId::Index(FELLOWSHIP_ADMIN_INDEX); // `Treasurer` pluralistic body. - pub const TreasurerBodyId: BodyId = BodyId::Index(TREASURER_INDEX); + pub const TreasurerBodyId: BodyId = BodyId::Treasury; } /// Type to convert the `GeneralAdmin` origin to a Plurality `Location` value. -- GitLab From f4fbddec420384e3550703ea7c9db3ea923f66e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Thu, 7 Mar 2024 18:19:52 -0500 Subject: [PATCH 090/188] fix(pallet-benchmarking): split test functions in v2 (#3574) Closes #376 --------- Co-authored-by: command-bot <> --- .../collator-selection/src/benchmarking.rs | 4 +- .../collective-content/src/benchmarking.rs | 2 +- .../runtime/common/src/identity_migrator.rs | 2 +- .../parachains/src/hrmp/benchmarking.rs | 2 +- prdoc/pr_3574.prdoc | 23 +++++++++++ substrate/frame/alliance/src/benchmarking.rs | 2 +- substrate/frame/identity/src/benchmarking.rs | 4 +- substrate/frame/lottery/src/benchmarking.rs | 1 - .../frame/support/procedural/src/benchmark.rs | 38 ++++++++++++++++++- .../system/benchmarking/src/extensions.rs | 2 +- .../frame/system/benchmarking/src/lib.rs | 2 +- 11 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 prdoc/pr_3574.prdoc diff --git a/cumulus/pallets/collator-selection/src/benchmarking.rs b/cumulus/pallets/collator-selection/src/benchmarking.rs index 2c40f4dd0ea..e2af74a6e60 100644 --- a/cumulus/pallets/collator-selection/src/benchmarking.rs +++ b/cumulus/pallets/collator-selection/src/benchmarking.rs @@ -22,9 +22,7 @@ use super::*; #[allow(unused)] use crate::Pallet as CollatorSelection; use codec::Decode; -use frame_benchmarking::{ - account, impl_benchmark_test_suite, v2::*, whitelisted_caller, BenchmarkError, -}; +use frame_benchmarking::{account, v2::*, whitelisted_caller, BenchmarkError}; use frame_support::traits::{Currency, EnsureOrigin, Get, ReservableCurrency}; use frame_system::{pallet_prelude::BlockNumberFor, EventRecord, RawOrigin}; use pallet_authorship::EventHandler; diff --git a/cumulus/parachains/pallets/collective-content/src/benchmarking.rs b/cumulus/parachains/pallets/collective-content/src/benchmarking.rs index 943386a8427..3d6bf073778 100644 --- a/cumulus/parachains/pallets/collective-content/src/benchmarking.rs +++ b/cumulus/parachains/pallets/collective-content/src/benchmarking.rs @@ -16,7 +16,7 @@ //! The pallet benchmarks. use super::{Pallet as CollectiveContent, *}; -use frame_benchmarking::{impl_benchmark_test_suite, v2::*}; +use frame_benchmarking::v2::*; use frame_support::traits::EnsureOrigin; fn assert_last_event, I: 'static>(generic_event: >::RuntimeEvent) { diff --git a/polkadot/runtime/common/src/identity_migrator.rs b/polkadot/runtime/common/src/identity_migrator.rs index 0dfb03b06ba..bf334a63e95 100644 --- a/polkadot/runtime/common/src/identity_migrator.rs +++ b/polkadot/runtime/common/src/identity_migrator.rs @@ -31,7 +31,7 @@ use pallet_identity; use sp_core::Get; #[cfg(feature = "runtime-benchmarks")] -use frame_benchmarking::{account, impl_benchmark_test_suite, v2::*, BenchmarkError}; +use frame_benchmarking::{account, v2::*, BenchmarkError}; pub trait WeightInfo { fn reap_identity(r: u32, s: u32) -> Weight; diff --git a/polkadot/runtime/parachains/src/hrmp/benchmarking.rs b/polkadot/runtime/parachains/src/hrmp/benchmarking.rs index 2cb49c88d43..c6baf2f30cf 100644 --- a/polkadot/runtime/parachains/src/hrmp/benchmarking.rs +++ b/polkadot/runtime/parachains/src/hrmp/benchmarking.rs @@ -22,7 +22,7 @@ use crate::{ paras::{Pallet as Paras, ParaKind, ParachainsCache}, shared::Pallet as Shared, }; -use frame_benchmarking::{impl_benchmark_test_suite, v2::*, whitelisted_caller}; +use frame_benchmarking::{v2::*, whitelisted_caller}; use frame_support::{assert_ok, traits::Currency}; type BalanceOf = diff --git a/prdoc/pr_3574.prdoc b/prdoc/pr_3574.prdoc new file mode 100644 index 00000000000..99868ea8a13 --- /dev/null +++ b/prdoc/pr_3574.prdoc @@ -0,0 +1,23 @@ +title: Generate test functions for each benchmark with benchmarking v2 + +doc: + - audience: Runtime Dev + description: | + This PR fixes an issue where using `impl_benchmark_test_suite` macro + within modules that use the benchmarking v2 macros (`#[benchmarks]` + and `#[instance_benchmarks]`) always produced a single test called + `test_benchmarks` instead of a separate benchmark test for every + benchmark (noted with the `#[benchmark]` macro). + + By using this macro from now on, new tests will be created named + `test_benchmark_{name}` where `name` is the name of the benchmark + function. Those tests will be nested inside the module intended for + benchmark functions. + + Also, when using `impl_benchmark_test_suite` inside the module, + the import of such marco will not be necessary, so any explicit + import of it will be marked as unused, the same way it works for + v1 macros so far. + +crates: + - name: frame-support-procedural diff --git a/substrate/frame/alliance/src/benchmarking.rs b/substrate/frame/alliance/src/benchmarking.rs index 9fe0e29b42c..4ccd0fc08f6 100644 --- a/substrate/frame/alliance/src/benchmarking.rs +++ b/substrate/frame/alliance/src/benchmarking.rs @@ -26,7 +26,7 @@ use core::{ }; use sp_runtime::traits::{Bounded, Hash, StaticLookup}; -use frame_benchmarking::{account, impl_benchmark_test_suite, v2::*, BenchmarkError}; +use frame_benchmarking::{account, v2::*, BenchmarkError}; use frame_support::traits::{EnsureOrigin, Get, UnfilteredDispatchable}; use frame_system::{pallet_prelude::BlockNumberFor, Pallet as System, RawOrigin as SystemOrigin}; diff --git a/substrate/frame/identity/src/benchmarking.rs b/substrate/frame/identity/src/benchmarking.rs index fe2fb0b0489..e0b45eeecd1 100644 --- a/substrate/frame/identity/src/benchmarking.rs +++ b/substrate/frame/identity/src/benchmarking.rs @@ -23,9 +23,7 @@ use super::*; use crate::Pallet as Identity; use codec::Encode; -use frame_benchmarking::{ - account, impl_benchmark_test_suite, v2::*, whitelisted_caller, BenchmarkError, -}; +use frame_benchmarking::{account, v2::*, whitelisted_caller, BenchmarkError}; use frame_support::{ assert_ok, ensure, traits::{EnsureOrigin, Get, OnFinalize, OnInitialize}, diff --git a/substrate/frame/lottery/src/benchmarking.rs b/substrate/frame/lottery/src/benchmarking.rs index 1510d250dbe..123b425b976 100644 --- a/substrate/frame/lottery/src/benchmarking.rs +++ b/substrate/frame/lottery/src/benchmarking.rs @@ -23,7 +23,6 @@ use super::*; use crate::Pallet as Lottery; use frame_benchmarking::{ - impl_benchmark_test_suite, v1::{account, whitelisted_caller, BenchmarkError}, v2::*, }; diff --git a/substrate/frame/support/procedural/src/benchmark.rs b/substrate/frame/support/procedural/src/benchmark.rs index 6ded82d91aa..d16ad2aaa51 100644 --- a/substrate/frame/support/procedural/src/benchmark.rs +++ b/substrate/frame/support/procedural/src/benchmark.rs @@ -431,7 +431,7 @@ pub fn benchmarks( let mut benchmarks_by_name_mappings: Vec = Vec::new(); let test_idents: Vec = benchmark_names_str .iter() - .map(|n| Ident::new(format!("test_{}", n).as_str(), Span::call_site())) + .map(|n| Ident::new(format!("test_benchmark_{}", n).as_str(), Span::call_site())) .collect(); for i in 0..benchmark_names.len() { let name_ident = &benchmark_names[i]; @@ -441,6 +441,37 @@ pub fn benchmarks( benchmarks_by_name_mappings.push(quote!(#name_str => Self::#test_ident())) } + let impl_test_function = content + .iter_mut() + .find_map(|item| { + let Item::Macro(item_macro) = item else { + return None; + }; + + if !item_macro + .mac + .path + .segments + .iter() + .any(|s| s.ident == "impl_benchmark_test_suite") + { + return None; + } + + let tokens = item_macro.mac.tokens.clone(); + *item = Item::Verbatim(quote! {}); + + Some(quote! { + impl_test_function!( + (#( {} #benchmark_names )*) + (#( #extra_benchmark_names )*) + (#( #skip_meta_benchmark_names )*) + #tokens + ); + }) + }) + .unwrap_or(quote! {}); + // emit final quoted tokens let res = quote! { #(#mod_attrs) @@ -676,6 +707,8 @@ pub fn benchmarks( } } } + + #impl_test_function } #mod_vis use #mod_name::*; }; @@ -733,7 +766,8 @@ fn expand_benchmark( let setup_stmts = benchmark_def.setup_stmts; let verify_stmts = benchmark_def.verify_stmts; let last_stmt = benchmark_def.last_stmt; - let test_ident = Ident::new(format!("test_{}", name.to_string()).as_str(), Span::call_site()); + let test_ident = + Ident::new(format!("test_benchmark_{}", name.to_string()).as_str(), Span::call_site()); // unroll params (prepare for quoting) let unrolled = UnrolledParams::from(&benchmark_def.params); diff --git a/substrate/frame/system/benchmarking/src/extensions.rs b/substrate/frame/system/benchmarking/src/extensions.rs index 1721501dead..bfc3b4343a6 100644 --- a/substrate/frame/system/benchmarking/src/extensions.rs +++ b/substrate/frame/system/benchmarking/src/extensions.rs @@ -19,7 +19,7 @@ #![cfg(feature = "runtime-benchmarks")] -use frame_benchmarking::{account, impl_benchmark_test_suite, v2::*, BenchmarkError}; +use frame_benchmarking::{account, v2::*, BenchmarkError}; use frame_support::{ dispatch::{DispatchClass, DispatchInfo, PostDispatchInfo}, weights::Weight, diff --git a/substrate/frame/system/benchmarking/src/lib.rs b/substrate/frame/system/benchmarking/src/lib.rs index ebd16275bcb..c9f0869d3bc 100644 --- a/substrate/frame/system/benchmarking/src/lib.rs +++ b/substrate/frame/system/benchmarking/src/lib.rs @@ -21,7 +21,7 @@ #![cfg(feature = "runtime-benchmarks")] use codec::Encode; -use frame_benchmarking::{impl_benchmark_test_suite, v2::*}; +use frame_benchmarking::v2::*; use frame_support::{dispatch::DispatchClass, storage, traits::Get}; use frame_system::{Call, Pallet as System, RawOrigin}; use sp_core::storage::well_known_keys; -- GitLab From 2aa006e094e248110af14a742d4e2f56b7931959 Mon Sep 17 00:00:00 2001 From: Sebastian Kunert Date: Fri, 8 Mar 2024 00:31:59 +0100 Subject: [PATCH 091/188] Refactor polkadot-parachain service for more code reuse (#3511) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a refactoring, no changes to the logic are included (if you find some, report :D). ## Change Overview In https://github.com/paritytech/polkadot-sdk/issues/2455, dependency on actual runtimes was removed for the system parachains. This means that the trait bounds we have on various `start_node_xy` do not check anything anymore, since they all point to the same runtime. Exception is asset-hub-polkadot which uses a different key type. This PR unifies the different nodes as much as possible. `start_node_impl` is doing the heavy lifting and has been made a bit more flexible to support the rpc extension instantiation that was there before. The generics for `Runtime` and `AuraId` have been removed where possible. The fake runtime is imported as `FakeRuntime` to make it very clear to readers that it is not the generic parameter. Multiple nodes where using the same import queue/start_consensus closure, they have been unified. --------- Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Francisco Aguirre Co-authored-by: Adrian Catangiu Co-authored-by: Egor_P Co-authored-by: Dmitry Markin Co-authored-by: Xiliang Chen Co-authored-by: Andrei Eres Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Co-authored-by: Alin Dima Co-authored-by: gupnik Co-authored-by: Liam Aharon Co-authored-by: Dónal Murray --- cumulus/polkadot-parachain/src/command.rs | 84 +- cumulus/polkadot-parachain/src/service.rs | 2329 ++++++--------------- 2 files changed, 717 insertions(+), 1696 deletions(-) diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index 4d44879af51..9ba7b7876b3 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -399,7 +399,7 @@ macro_rules! construct_partials { Runtime::AssetHubPolkadot => { let $partials = new_partial::( &$config, - crate::service::aura_build_import_queue::<_, AssetHubPolkadotAuraId>, + crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, )?; $code }, @@ -413,28 +413,21 @@ macro_rules! construct_partials { Runtime::People(_) => { let $partials = new_partial::( &$config, - crate::service::aura_build_import_queue::<_, AuraId>, + crate::service::build_relay_to_aura_import_queue::<_, AuraId>, )?; $code }, Runtime::GluttonWestend | Runtime::Glutton | Runtime::Shell | Runtime::Seedling => { let $partials = new_partial::( &$config, - crate::service::shell_build_import_queue, + crate::service::build_shell_import_queue, )?; $code }, - Runtime::ContractsRococo => { + Runtime::ContractsRococo | Runtime::Penpal(_) | Runtime::Default => { let $partials = new_partial::( &$config, - crate::service::contracts_rococo_build_import_queue, - )?; - $code - }, - Runtime::Penpal(_) | Runtime::Default => { - let $partials = new_partial::( - &$config, - crate::service::rococo_parachain_build_import_queue, + crate::service::build_aura_import_queue, )?; $code }, @@ -450,7 +443,7 @@ macro_rules! construct_async_run { runner.async_run(|$config| { let $components = new_partial::( &$config, - crate::service::aura_build_import_queue::<_, AssetHubPolkadotAuraId>, + crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, )?; let task_manager = $components.task_manager; { $( $code )* }.map(|v| (v, task_manager)) @@ -467,7 +460,7 @@ macro_rules! construct_async_run { runner.async_run(|$config| { let $components = new_partial::( &$config, - crate::service::aura_build_import_queue::<_, AuraId>, + crate::service::build_relay_to_aura_import_queue::<_, AuraId>, )?; let task_manager = $components.task_manager; { $( $code )* }.map(|v| (v, task_manager)) @@ -480,30 +473,20 @@ macro_rules! construct_async_run { runner.async_run(|$config| { let $components = new_partial::( &$config, - crate::service::shell_build_import_queue, + crate::service::build_shell_import_queue, )?; let task_manager = $components.task_manager; { $( $code )* }.map(|v| (v, task_manager)) }) } - Runtime::ContractsRococo => { - runner.async_run(|$config| { - let $components = new_partial::( - &$config, - crate::service::contracts_rococo_build_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Runtime::Penpal(_) | Runtime::Default => { + Runtime::ContractsRococo | Runtime::Penpal(_) | Runtime::Default => { runner.async_run(|$config| { let $components = new_partial::< RuntimeApi, _, >( &$config, - crate::service::rococo_parachain_build_import_queue, + crate::service::build_aura_import_queue, )?; let task_manager = $components.task_manager; { $( $code )* }.map(|v| (v, task_manager)) @@ -715,25 +698,19 @@ pub fn run() -> Result<()> { .map_err(Into::into), CollectivesPolkadot => - crate::service::start_generic_aura_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_generic_aura_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0) .map_err(Into::into), CollectivesWestend => - crate::service::start_generic_aura_lookahead_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_generic_aura_lookahead_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0) .map_err(Into::into), Seedling | Shell => - crate::service::start_shell_node::( + crate::service::start_shell_node( config, polkadot_config, collator_options, @@ -758,36 +735,24 @@ pub fn run() -> Result<()> { BridgeHub(bridge_hub_runtime_type) => match bridge_hub_runtime_type { chain_spec::bridge_hubs::BridgeHubRuntimeType::Polkadot | chain_spec::bridge_hubs::BridgeHubRuntimeType::PolkadotLocal => - crate::service::start_generic_aura_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_generic_aura_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0), chain_spec::bridge_hubs::BridgeHubRuntimeType::Kusama | chain_spec::bridge_hubs::BridgeHubRuntimeType::KusamaLocal => - crate::service::start_generic_aura_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_generic_aura_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0), chain_spec::bridge_hubs::BridgeHubRuntimeType::Westend | chain_spec::bridge_hubs::BridgeHubRuntimeType::WestendLocal | chain_spec::bridge_hubs::BridgeHubRuntimeType::WestendDevelopment => - crate::service::start_generic_aura_lookahead_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_generic_aura_lookahead_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0), chain_spec::bridge_hubs::BridgeHubRuntimeType::Rococo | chain_spec::bridge_hubs::BridgeHubRuntimeType::RococoLocal | chain_spec::bridge_hubs::BridgeHubRuntimeType::RococoDevelopment => - crate::service::start_generic_aura_lookahead_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_generic_aura_lookahead_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0), } @@ -800,10 +765,7 @@ pub fn run() -> Result<()> { chain_spec::coretime::CoretimeRuntimeType::Westend | chain_spec::coretime::CoretimeRuntimeType::WestendLocal | chain_spec::coretime::CoretimeRuntimeType::WestendDevelopment => - crate::service::start_generic_aura_lookahead_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_generic_aura_lookahead_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0), } @@ -822,10 +784,7 @@ pub fn run() -> Result<()> { .map_err(Into::into), Glutton | GluttonWestend => - crate::service::start_basic_lookahead_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_basic_lookahead_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0) .map_err(Into::into), @@ -837,10 +796,7 @@ pub fn run() -> Result<()> { chain_spec::people::PeopleRuntimeType::Westend | chain_spec::people::PeopleRuntimeType::WestendLocal | chain_spec::people::PeopleRuntimeType::WestendDevelopment => - crate::service::start_generic_aura_lookahead_node::< - RuntimeApi, - AuraId, - >(config, polkadot_config, collator_options, id, hwbench) + crate::service::start_generic_aura_lookahead_node(config, polkadot_config, collator_options, id, hwbench) .await .map(|r| r.0), } diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index 386551102e4..ddf595ca70c 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -36,12 +36,13 @@ use cumulus_primitives_core::{ ParaId, }; use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; +use sc_rpc::DenyUnsafe; use sp_core::Pair; use jsonrpsee::RpcModule; -use crate::{fake_runtime_api::aura::RuntimeApi, rpc}; -pub use parachains_common::{AccountId, Balance, Block, Hash, Header, Nonce}; +use crate::{fake_runtime_api::aura::RuntimeApi as FakeRuntimeApi, rpc}; +pub use parachains_common::{AccountId, AuraId, Balance, Block, Hash, Header, Nonce}; use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier; use futures::{lock::Mutex, prelude::*}; @@ -85,141 +86,6 @@ type ParachainBackend = TFullBackend; type ParachainBlockImport = TParachainBlockImport>, ParachainBackend>; -/// Native executor instance. -pub struct ShellRuntimeExecutor; - -impl sc_executor::NativeExecutionDispatch for ShellRuntimeExecutor { - type ExtendHostFunctions = (); - - fn dispatch(method: &str, data: &[u8]) -> Option> { - shell_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - shell_runtime::native_version() - } -} - -/// Native Asset Hub Westend (Westmint) executor instance. -pub struct AssetHubWestendExecutor; -impl sc_executor::NativeExecutionDispatch for AssetHubWestendExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - asset_hub_westend_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - asset_hub_westend_runtime::native_version() - } -} - -/// Native Westend Collectives executor instance. -pub struct CollectivesWestendRuntimeExecutor; - -impl sc_executor::NativeExecutionDispatch for CollectivesWestendRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - collectives_westend_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - collectives_westend_runtime::native_version() - } -} - -/// Native BridgeHubRococo executor instance. -pub struct BridgeHubRococoRuntimeExecutor; -impl sc_executor::NativeExecutionDispatch for BridgeHubRococoRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - bridge_hub_rococo_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - bridge_hub_rococo_runtime::native_version() - } -} - -/// Native `CoretimeRococo` executor instance. -pub struct CoretimeRococoRuntimeExecutor; -impl sc_executor::NativeExecutionDispatch for CoretimeRococoRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - fn dispatch(method: &str, data: &[u8]) -> Option> { - coretime_rococo_runtime::api::dispatch(method, data) - } - fn native_version() -> sc_executor::NativeVersion { - coretime_rococo_runtime::native_version() - } -} - -/// Native `CoretimeWestend` executor instance. -pub struct CoretimeWestendRuntimeExecutor; -impl sc_executor::NativeExecutionDispatch for CoretimeWestendRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - fn dispatch(method: &str, data: &[u8]) -> Option> { - coretime_westend_runtime::api::dispatch(method, data) - } - fn native_version() -> sc_executor::NativeVersion { - coretime_westend_runtime::native_version() - } -} - -/// Native contracts executor instance. -pub struct ContractsRococoRuntimeExecutor; -impl sc_executor::NativeExecutionDispatch for ContractsRococoRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - contracts_rococo_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - contracts_rococo_runtime::native_version() - } -} - -/// Native Westend Glutton executor instance. -pub struct GluttonWestendRuntimeExecutor; - -impl sc_executor::NativeExecutionDispatch for GluttonWestendRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - glutton_westend_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - glutton_westend_runtime::native_version() - } -} - -/// Native `PeopleWestend` executor instance. -pub struct PeopleWestendRuntimeExecutor; -impl sc_executor::NativeExecutionDispatch for PeopleWestendRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - fn dispatch(method: &str, data: &[u8]) -> Option> { - people_westend_runtime::api::dispatch(method, data) - } - fn native_version() -> sc_executor::NativeVersion { - people_westend_runtime::native_version() - } -} - -/// Native `PeopleRococo` executor instance. -pub struct PeopleRococoRuntimeExecutor; -impl sc_executor::NativeExecutionDispatch for PeopleRococoRuntimeExecutor { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - fn dispatch(method: &str, data: &[u8]) -> Option> { - people_rococo_runtime::api::dispatch(method, data) - } - fn native_version() -> sc_executor::NativeVersion { - people_rococo_runtime::native_version() - } -} - /// Assembly of PartialComponents (enough to run chain ops subcommands) pub type Service = PartialComponents< ParachainClient, @@ -323,12 +189,11 @@ where }) } -/// Start a shell node with the given parachain `Configuration` and relay chain `Configuration`. +/// Start a node with the given parachain `Configuration` and relay chain `Configuration`. /// -/// This is the actual implementation that is abstract over the executor and the runtime api for -/// shell nodes. +/// This is the actual implementation that is abstract over the executor and the runtime api. #[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_shell_node_impl( +async fn start_node_impl( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, @@ -347,8 +212,15 @@ where + sp_api::ApiExt + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo, - RB: Fn(Arc>) -> Result, sc_service::Error> + + cumulus_primitives_core::CollectCollationInfo + + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + + frame_rpc_system::AccountNonceApi, + RB: Fn( + DenyUnsafe, + Arc>, + Arc, + Arc>>, + ) -> Result, sc_service::Error> + 'static, BIQ: FnOnce( Arc>, @@ -372,6 +244,7 @@ where CollatorPair, OverseerHandle, Arc>) + Send + Sync>, + Arc, ) -> Result<(), sc_service::Error>, { let parachain_config = prepare_node_config(parachain_config); @@ -383,7 +256,6 @@ where let backend = params.backend.clone(); let mut task_manager = params.task_manager; - let (relay_chain_interface, collator_key) = build_relay_chain_interface( polkadot_config, ¶chain_config, @@ -415,8 +287,20 @@ where }) .await?; - let rpc_client = client.clone(); - let rpc_builder = Box::new(move |_, _| rpc_ext_builder(rpc_client.clone())); + let rpc_builder = { + let client = client.clone(); + let transaction_pool = transaction_pool.clone(); + let backend_for_rpc = backend.clone(); + + Box::new(move |deny_unsafe, _| { + rpc_ext_builder( + deny_unsafe, + client.clone(), + backend_for_rpc.clone(), + transaction_pool.clone(), + ) + }) + }; sc_service::spawn_tasks(sc_service::SpawnTasksParams { rpc_builder, @@ -493,6 +377,7 @@ where collator_key.expect("Command line arguments do not allow this. qed"), overseer_handle, announce_block, + backend.clone(), )?; } @@ -501,676 +386,179 @@ where Ok((task_manager, client)) } -/// Start a node with the given parachain `Configuration` and relay chain `Configuration`. -/// -/// This is the actual implementation that is abstract over the executor and the runtime api. -#[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_node_impl( +/// Build the import queue for Aura-based runtimes. +pub fn build_aura_import_queue( + client: Arc>, + block_import: ParachainBlockImport, + config: &Configuration, + telemetry: Option, + task_manager: &TaskManager, +) -> Result, sc_service::Error> { + let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; + + cumulus_client_consensus_aura::import_queue::< + sp_consensus_aura::sr25519::AuthorityPair, + _, + _, + _, + _, + _, + >(cumulus_client_consensus_aura::ImportQueueParams { + block_import, + client, + create_inherent_data_providers: move |_, _| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + registry: config.prometheus_registry(), + spawner: &task_manager.spawn_essential_handle(), + telemetry, + }) + .map_err(Into::into) +} + +/// Start a rococo parachain node. +pub async fn start_rococo_parachain_node( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, - sybil_resistance_level: CollatorSybilResistance, para_id: ParaId, - _rpc_ext_builder: RB, - build_import_queue: BIQ, - start_consensus: SC, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> +) -> sc_service::error::Result<(TaskManager, Arc>)> { + start_node_impl::( + parachain_config, + polkadot_config, + collator_options, + CollatorSybilResistance::Resistant, // Aura + para_id, + build_parachain_rpc_extensions::, + build_aura_import_queue, + start_lookahead_aura_consensus, + hwbench, + ) + .await +} + +/// Build the import queue for the shell runtime. +pub fn build_shell_import_queue( + client: Arc>, + block_import: ParachainBlockImport, + config: &Configuration, + _: Option, + task_manager: &TaskManager, +) -> Result, sc_service::Error> { + cumulus_client_consensus_relay_chain::import_queue( + client, + block_import, + |_, _| async { Ok(()) }, + &task_manager.spawn_essential_handle(), + config.prometheus_registry(), + ) + .map_err(Into::into) +} + +fn build_parachain_rpc_extensions( + deny_unsafe: sc_rpc::DenyUnsafe, + client: Arc>, + backend: Arc, + pool: Arc>>, +) -> Result, sc_service::Error> where RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + frame_rpc_system::AccountNonceApi, - RB: Fn(Arc>) -> Result, sc_service::Error>, - BIQ: FnOnce( - Arc>, - ParachainBlockImport, - &Configuration, - Option, - &TaskManager, - ) -> Result, sc_service::Error>, - SC: FnOnce( - Arc>, - ParachainBlockImport, - Option<&Registry>, - Option, - &TaskManager, - Arc, - Arc>>, - Arc>, - KeystorePtr, - Duration, - ParaId, - CollatorPair, - OverseerHandle, - Arc>) + Send + Sync>, - Arc, - ) -> Result<(), sc_service::Error>, { - let parachain_config = prepare_node_config(parachain_config); + let deps = rpc::FullDeps { client, pool, deny_unsafe }; - let params = new_partial::(¶chain_config, build_import_queue)?; - let (block_import, mut telemetry, telemetry_worker_handle) = params.other; + rpc::create_full(deps, backend).map_err(Into::into) +} - let client = params.client.clone(); - let backend = params.backend.clone(); +fn build_contracts_rpc_extensions( + deny_unsafe: sc_rpc::DenyUnsafe, + client: Arc>, + _backend: Arc, + pool: Arc>>, +) -> Result, sc_service::Error> { + let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; - let mut task_manager = params.task_manager; - let (relay_chain_interface, collator_key) = build_relay_chain_interface( + crate::rpc::create_contracts_rococo(deps).map_err(Into::into) +} + +/// Start a polkadot-shell parachain node. +pub async fn start_shell_node( + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, +) -> sc_service::error::Result<(TaskManager, Arc>)> { + start_node_impl::( + parachain_config, polkadot_config, - ¶chain_config, - telemetry_worker_handle, - &mut task_manager, - collator_options.clone(), - hwbench.clone(), + collator_options, + CollatorSybilResistance::Unresistant, // free-for-all consensus + para_id, + |_, _, _, _| Ok(RpcModule::new(())), + build_shell_import_queue, + start_relay_chain_consensus, + hwbench, ) .await - .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; - - let validator = parachain_config.role.is_authority(); - let prometheus_registry = parachain_config.prometheus_registry().cloned(); - let transaction_pool = params.transaction_pool.clone(); - let import_queue_service = params.import_queue.service(); - let net_config = FullNetworkConfiguration::new(¶chain_config.network); - - let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = - build_network(BuildNetworkParams { - parachain_config: ¶chain_config, - net_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - para_id, - spawn_handle: task_manager.spawn_handle(), - relay_chain_interface: relay_chain_interface.clone(), - import_queue: params.import_queue, - sybil_resistance_level, - }) - .await?; +} - let rpc_builder = { - let client = client.clone(); - let transaction_pool = transaction_pool.clone(); +enum BuildOnAccess { + Uninitialized(Option R + Send + Sync>>), + Initialized(R), +} - let backend_for_rpc = backend.clone(); - Box::new(move |deny_unsafe, _| { - let deps = rpc::FullDeps { - client: client.clone(), - pool: transaction_pool.clone(), - deny_unsafe, - }; +impl BuildOnAccess { + fn get_mut(&mut self) -> &mut R { + loop { + match self { + Self::Uninitialized(f) => { + *self = Self::Initialized((f.take().unwrap())()); + }, + Self::Initialized(ref mut r) => return r, + } + } + } +} - rpc::create_full(deps, backend_for_rpc.clone()).map_err(Into::into) - }) - }; +/// Special [`ParachainConsensus`] implementation that waits for the upgrade from +/// shell to a parachain runtime that implements Aura. +struct WaitForAuraConsensus { + client: Arc, + aura_consensus: Arc>>>>, + relay_chain_consensus: Arc>>>, + _phantom: PhantomData, +} - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - rpc_builder, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - task_manager: &mut task_manager, - config: parachain_config, - keystore: params.keystore_container.keystore(), - backend: backend.clone(), - network: network.clone(), - sync_service: sync_service.clone(), - system_rpc_tx, - tx_handler_controller, - telemetry: telemetry.as_mut(), - })?; - - if let Some(hwbench) = hwbench { - sc_sysinfo::print_hwbench(&hwbench); - if validator { - warn_if_slow_hardware(&hwbench); - } - - if let Some(ref mut telemetry) = telemetry { - let telemetry_handle = telemetry.handle(); - task_manager.spawn_handle().spawn( - "telemetry_hwbench", - None, - sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench), - ); +impl Clone for WaitForAuraConsensus { + fn clone(&self) -> Self { + Self { + client: self.client.clone(), + aura_consensus: self.aura_consensus.clone(), + relay_chain_consensus: self.relay_chain_consensus.clone(), + _phantom: PhantomData, } } - - let announce_block = { - let sync_service = sync_service.clone(); - Arc::new(move |hash, data| sync_service.announce_block(hash, data)) - }; - - let relay_chain_slot_duration = Duration::from_secs(6); - - let overseer_handle = relay_chain_interface - .overseer_handle() - .map_err(|e| sc_service::Error::Application(Box::new(e)))?; - - start_relay_chain_tasks(StartRelayChainTasksParams { - client: client.clone(), - announce_block: announce_block.clone(), - para_id, - relay_chain_interface: relay_chain_interface.clone(), - task_manager: &mut task_manager, - da_recovery_profile: if validator { - DARecoveryProfile::Collator - } else { - DARecoveryProfile::FullNode - }, - import_queue: import_queue_service, - relay_chain_slot_duration, - recovery_handle: Box::new(overseer_handle.clone()), - sync_service: sync_service.clone(), - })?; - - if validator { - start_consensus( - client.clone(), - block_import, - prometheus_registry.as_ref(), - telemetry.as_ref().map(|t| t.handle()), - &task_manager, - relay_chain_interface.clone(), - transaction_pool, - sync_service.clone(), - params.keystore_container.keystore(), - relay_chain_slot_duration, - para_id, - collator_key.expect("Command line arguments do not allow this. qed"), - overseer_handle, - announce_block, - backend.clone(), - )?; - } - - start_network.start_network(); - - Ok((task_manager, client)) } -/// Start a node with the given parachain `Configuration` and relay chain `Configuration`. -/// -/// This is the actual implementation that is abstract over the executor and the runtime api. -/// -/// This node is basic in the sense that it doesn't support functionality like transaction -/// payment. Intended to replace start_shell_node in use for glutton, shell, and seedling. -#[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_basic_lookahead_node_impl( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - sybil_resistance_level: CollatorSybilResistance, - para_id: ParaId, - rpc_ext_builder: RB, - build_import_queue: BIQ, - start_consensus: SC, - hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> +#[async_trait::async_trait] +impl ParachainConsensus for WaitForAuraConsensus where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo - + frame_rpc_system::AccountNonceApi, - RB: Fn(Arc>) -> Result, sc_service::Error> - + 'static, - BIQ: FnOnce( - Arc>, - ParachainBlockImport, - &Configuration, - Option, - &TaskManager, - ) -> Result, sc_service::Error>, - SC: FnOnce( - Arc>, - ParachainBlockImport, - Option<&Registry>, - Option, - &TaskManager, - Arc, - Arc>>, - Arc>, - KeystorePtr, - Duration, - ParaId, - CollatorPair, - OverseerHandle, - Arc>) + Send + Sync>, - Arc, - ) -> Result<(), sc_service::Error>, -{ - let parachain_config = prepare_node_config(parachain_config); - - let params = new_partial::(¶chain_config, build_import_queue)?; - let (block_import, mut telemetry, telemetry_worker_handle) = params.other; - - let client = params.client.clone(); - let backend = params.backend.clone(); - - let mut task_manager = params.task_manager; - let (relay_chain_interface, collator_key) = build_relay_chain_interface( - polkadot_config, - ¶chain_config, - telemetry_worker_handle, - &mut task_manager, - collator_options.clone(), - hwbench.clone(), - ) - .await - .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; - - let validator = parachain_config.role.is_authority(); - let prometheus_registry = parachain_config.prometheus_registry().cloned(); - let transaction_pool = params.transaction_pool.clone(); - let import_queue_service = params.import_queue.service(); - let net_config = FullNetworkConfiguration::new(¶chain_config.network); - - let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = - build_network(BuildNetworkParams { - parachain_config: ¶chain_config, - net_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - para_id, - spawn_handle: task_manager.spawn_handle(), - relay_chain_interface: relay_chain_interface.clone(), - import_queue: params.import_queue, - sybil_resistance_level, - }) - .await?; - - let rpc_client = client.clone(); - let rpc_builder = Box::new(move |_, _| rpc_ext_builder(rpc_client.clone())); - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - rpc_builder, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - task_manager: &mut task_manager, - config: parachain_config, - keystore: params.keystore_container.keystore(), - backend: backend.clone(), - network: network.clone(), - sync_service: sync_service.clone(), - system_rpc_tx, - tx_handler_controller, - telemetry: telemetry.as_mut(), - })?; - - if let Some(hwbench) = hwbench { - sc_sysinfo::print_hwbench(&hwbench); - if validator { - warn_if_slow_hardware(&hwbench); - } - - if let Some(ref mut telemetry) = telemetry { - let telemetry_handle = telemetry.handle(); - task_manager.spawn_handle().spawn( - "telemetry_hwbench", - None, - sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench), - ); - } - } - - let announce_block = { - let sync_service = sync_service.clone(); - Arc::new(move |hash, data| sync_service.announce_block(hash, data)) - }; - - let relay_chain_slot_duration = Duration::from_secs(6); - - let overseer_handle = relay_chain_interface - .overseer_handle() - .map_err(|e| sc_service::Error::Application(Box::new(e)))?; - - start_relay_chain_tasks(StartRelayChainTasksParams { - client: client.clone(), - announce_block: announce_block.clone(), - para_id, - relay_chain_interface: relay_chain_interface.clone(), - task_manager: &mut task_manager, - da_recovery_profile: if validator { - DARecoveryProfile::Collator - } else { - DARecoveryProfile::FullNode - }, - import_queue: import_queue_service, - relay_chain_slot_duration, - recovery_handle: Box::new(overseer_handle.clone()), - sync_service: sync_service.clone(), - })?; - - if validator { - start_consensus( - client.clone(), - block_import, - prometheus_registry.as_ref(), - telemetry.as_ref().map(|t| t.handle()), - &task_manager, - relay_chain_interface.clone(), - transaction_pool, - sync_service.clone(), - params.keystore_container.keystore(), - relay_chain_slot_duration, - para_id, - collator_key.expect("Command line arguments do not allow this. qed"), - overseer_handle, - announce_block, - backend.clone(), - )?; - } - - start_network.start_network(); - - Ok((task_manager, client)) -} - -/// Build the import queue for the rococo parachain runtime. -pub fn rococo_parachain_build_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - telemetry: Option, - task_manager: &TaskManager, -) -> Result, sc_service::Error> { - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - - cumulus_client_consensus_aura::import_queue::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - >(cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry, - }) - .map_err(Into::into) -} - -/// Start a rococo parachain node. -pub async fn start_rococo_parachain_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - |_| Ok(RpcModule::new(())), - rococo_parachain_build_import_queue, - |client, - block_import, - prometheus_registry, - telemetry, - task_manager, - relay_chain_interface, - transaction_pool, - sync_oracle, - keystore, - relay_chain_slot_duration, - para_id, - collator_key, - overseer_handle, - announce_block, - backend| { - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); - let proposer = Proposer::new(proposer_factory); - - let collator_service = CollatorService::new( - client.clone(), - Arc::new(task_manager.spawn_handle()), - announce_block, - client.clone(), - ); - - let params = AuraParams { - create_inherent_data_providers: move |_, ()| async move { Ok(()) }, - block_import, - para_client: client.clone(), - para_backend: backend.clone(), - relay_client: relay_chain_interface, - code_hash_provider: move |block_hash| { - client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) - }, - sync_oracle, - keystore, - collator_key, - para_id, - overseer_handle, - relay_chain_slot_duration, - proposer, - collator_service, - authoring_duration: Duration::from_millis(1500), - reinitialize: false, - }; - - let fut = aura::run::< - Block, - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - _, - _, - _, - _, - >(params); - task_manager.spawn_essential_handle().spawn("aura", None, fut); - - Ok(()) - }, - hwbench, - ) - .await -} - -/// Build the import queue for the shell runtime. -pub fn shell_build_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - _: Option, - task_manager: &TaskManager, -) -> Result, sc_service::Error> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder, -{ - cumulus_client_consensus_relay_chain::import_queue( - client, - block_import, - |_, _| async { Ok(()) }, - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - ) - .map_err(Into::into) -} - -/// Start a polkadot-shell parachain node. -pub async fn start_shell_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo, -{ - start_shell_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Unresistant, // free-for-all consensus - para_id, - |_| Ok(RpcModule::new(())), - shell_build_import_queue, - |client, - block_import, - prometheus_registry, - telemetry, - task_manager, - relay_chain_interface, - transaction_pool, - _sync_oracle, - _keystore, - _relay_chain_slot_duration, - para_id, - collator_key, - overseer_handle, - announce_block| { - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry, - telemetry, - ); - - let free_for_all = cumulus_client_consensus_relay_chain::build_relay_chain_consensus( - cumulus_client_consensus_relay_chain::BuildRelayChainConsensusParams { - para_id, - proposer_factory, - block_import, - relay_chain_interface: relay_chain_interface.clone(), - create_inherent_data_providers: move |_, (relay_parent, validation_data)| { - let relay_chain_interface = relay_chain_interface.clone(); - async move { - let parachain_inherent = - cumulus_client_parachain_inherent::ParachainInherentDataProvider::create_at( - relay_parent, - &relay_chain_interface, - &validation_data, - para_id, - ).await; - let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from( - "Failed to create parachain inherent", - ) - })?; - Ok(parachain_inherent) - } - }, - }, - ); - - let spawner = task_manager.spawn_handle(); - - // Required for free-for-all consensus - #[allow(deprecated)] - old_consensus::start_collator_sync(old_consensus::StartCollatorParams { - para_id, - block_status: client.clone(), - announce_block, - overseer_handle, - spawner, - key: collator_key, - parachain_consensus: free_for_all, - runtime_api: client.clone(), - }); - - Ok(()) - }, - hwbench, - ) - .await -} - -enum BuildOnAccess { - Uninitialized(Option R + Send + Sync>>), - Initialized(R), -} - -impl BuildOnAccess { - fn get_mut(&mut self) -> &mut R { - loop { - match self { - Self::Uninitialized(f) => { - *self = Self::Initialized((f.take().unwrap())()); - }, - Self::Initialized(ref mut r) => return r, - } - } - } -} - -/// Special [`ParachainConsensus`] implementation that waits for the upgrade from -/// shell to a parachain runtime that implements Aura. -struct WaitForAuraConsensus { - client: Arc, - aura_consensus: Arc>>>>, - relay_chain_consensus: Arc>>>, - _phantom: PhantomData, -} - -impl Clone for WaitForAuraConsensus { - fn clone(&self) -> Self { - Self { - client: self.client.clone(), - aura_consensus: self.aura_consensus.clone(), - relay_chain_consensus: self.relay_chain_consensus.clone(), - _phantom: PhantomData, - } - } -} - -#[async_trait::async_trait] -impl ParachainConsensus for WaitForAuraConsensus -where - Client: sp_api::ProvideRuntimeApi + Send + Sync, - Client::Api: AuraApi, - AuraId: Send + Codec + Sync, + Client: sp_api::ProvideRuntimeApi + Send + Sync, + Client::Api: AuraApi, + AuraId: Send + Codec + Sync, { async fn produce_candidate( &mut self, @@ -1190,464 +578,56 @@ where .get_mut() .produce_candidate(parent, relay_parent, validation_data) .await - } else { - self.relay_chain_consensus - .lock() - .await - .produce_candidate(parent, relay_parent, validation_data) - .await - } - } -} - -struct Verifier { - client: Arc, - aura_verifier: BuildOnAccess>>, - relay_chain_verifier: Box>, - _phantom: PhantomData, -} - -#[async_trait::async_trait] -impl VerifierT for Verifier -where - Client: sp_api::ProvideRuntimeApi + Send + Sync, - Client::Api: AuraApi, - AuraId: Send + Sync + Codec, -{ - async fn verify( - &mut self, - block_import: BlockImportParams, - ) -> Result, String> { - if self - .client - .runtime_api() - .has_api::>(*block_import.header.parent_hash()) - .unwrap_or(false) - { - self.aura_verifier.get_mut().verify(block_import).await - } else { - self.relay_chain_verifier.verify(block_import).await - } - } -} - -/// Build the import queue for Aura-based runtimes. -pub fn aura_build_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - telemetry_handle: Option, - task_manager: &TaskManager, -) -> Result, sc_service::Error> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder - + sp_consensus_aura::AuraApi::Pair as Pair>::Public>, - <::Pair as Pair>::Signature: - TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, -{ - let verifier_client = client.clone(); - - let aura_verifier = move || { - Box::new(cumulus_client_consensus_aura::build_verifier::< - ::Pair, - _, - _, - _, - >(cumulus_client_consensus_aura::BuildVerifierParams { - client: verifier_client.clone(), - create_inherent_data_providers: move |parent_hash, _| { - let cidp_client = verifier_client.clone(); - async move { - let slot_duration = cumulus_client_consensus_aura::slot_duration_at( - &*cidp_client, - parent_hash, - )?; - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - } - }, - telemetry: telemetry_handle, - })) as Box<_> - }; - - let relay_chain_verifier = - Box::new(RelayChainVerifier::new(client.clone(), |_, _| async { Ok(()) })) as Box<_>; - - let verifier = Verifier { - client, - relay_chain_verifier, - aura_verifier: BuildOnAccess::Uninitialized(Some(Box::new(aura_verifier))), - _phantom: PhantomData, - }; - - let registry = config.prometheus_registry(); - let spawner = task_manager.spawn_essential_handle(); - - Ok(BasicQueue::new(verifier, Box::new(block_import), None, &spawner, registry)) -} - -/// Start an aura powered parachain node. Some system chains use this. -pub async fn start_generic_aura_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo - + sp_consensus_aura::AuraApi::Pair as Pair>::Public> - + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi - + frame_rpc_system::AccountNonceApi, - <::Pair as Pair>::Signature: - TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, -{ - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - |_| Ok(RpcModule::new(())), - aura_build_import_queue::<_, AuraId>, - |client, - block_import, - prometheus_registry, - telemetry, - task_manager, - relay_chain_interface, - transaction_pool, - sync_oracle, - keystore, - relay_chain_slot_duration, - para_id, - collator_key, - overseer_handle, - announce_block, - _backend| { - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); - let proposer = Proposer::new(proposer_factory); - - let collator_service = CollatorService::new( - client.clone(), - Arc::new(task_manager.spawn_handle()), - announce_block, - client.clone(), - ); - - let params = BasicAuraParams { - create_inherent_data_providers: move |_, ()| async move { Ok(()) }, - block_import, - para_client: client, - relay_client: relay_chain_interface, - sync_oracle, - keystore, - collator_key, - para_id, - overseer_handle, - slot_duration, - relay_chain_slot_duration, - proposer, - collator_service, - // Very limited proposal time. - authoring_duration: Duration::from_millis(500), - collation_request_receiver: None, - }; - - let fut = - basic_aura::run::::Pair, _, _, _, _, _, _, _>(params); - task_manager.spawn_essential_handle().spawn("aura", None, fut); - - Ok(()) - }, - hwbench, - ) - .await -} - -/// Uses the lookahead collator to support async backing. -/// -/// Start an aura powered parachain node. Some system chains use this. -pub async fn start_generic_aura_lookahead_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo - + sp_consensus_aura::AuraApi::Pair as Pair>::Public> - + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi - + frame_rpc_system::AccountNonceApi - + cumulus_primitives_aura::AuraUnincludedSegmentApi, - <::Pair as Pair>::Signature: - TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, -{ - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - |_| Ok(RpcModule::new(())), - aura_build_import_queue::<_, AuraId>, - |client, - block_import, - prometheus_registry, - telemetry, - task_manager, - relay_chain_interface, - transaction_pool, - sync_oracle, - keystore, - relay_chain_slot_duration, - para_id, - collator_key, - overseer_handle, - announce_block, - backend| { - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); - let proposer = Proposer::new(proposer_factory); - - let collator_service = CollatorService::new( - client.clone(), - Arc::new(task_manager.spawn_handle()), - announce_block, - client.clone(), - ); - - let params = AuraParams { - create_inherent_data_providers: move |_, ()| async move { Ok(()) }, - block_import, - para_client: client.clone(), - para_backend: backend, - relay_client: relay_chain_interface, - code_hash_provider: move |block_hash| { - client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) - }, - sync_oracle, - keystore, - collator_key, - para_id, - overseer_handle, - relay_chain_slot_duration, - proposer, - collator_service, - authoring_duration: Duration::from_millis(1500), - reinitialize: false, - }; - - let fut = - aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params); - task_manager.spawn_essential_handle().spawn("aura", None, fut); - - Ok(()) - }, - hwbench, - ) - .await -} - -/// Start a shell node which should later transition into an Aura powered parachain node. Asset Hub -/// uses this because at genesis, Asset Hub was on the `shell` runtime which didn't have Aura and -/// needs to sync and upgrade before it can run `AuraApi` functions. -pub async fn start_asset_hub_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo - + sp_consensus_aura::AuraApi::Pair as Pair>::Public> - + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi - + frame_rpc_system::AccountNonceApi, - <::Pair as Pair>::Signature: - TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, -{ - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - |_| Ok(RpcModule::new(())), - aura_build_import_queue::<_, AuraId>, - |client, - block_import, - prometheus_registry, - telemetry, - task_manager, - relay_chain_interface, - transaction_pool, - sync_oracle, - keystore, - relay_chain_slot_duration, - para_id, - collator_key, - overseer_handle, - announce_block, - _backend| { - let relay_chain_interface2 = relay_chain_interface.clone(); - - let collator_service = CollatorService::new( - client.clone(), - Arc::new(task_manager.spawn_handle()), - announce_block, - client.clone(), - ); - - let spawner = task_manager.spawn_handle(); - - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - spawner, - client.clone(), - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); - - let collation_future = Box::pin(async move { - // Start collating with the `shell` runtime while waiting for an upgrade to an Aura - // compatible runtime. - let mut request_stream = cumulus_client_collator::relay_chain_driven::init( - collator_key.clone(), - para_id, - overseer_handle.clone(), - ) - .await; - while let Some(request) = request_stream.next().await { - let pvd = request.persisted_validation_data().clone(); - let last_head_hash = - match ::Header::decode(&mut &pvd.parent_head.0[..]) { - Ok(header) => header.hash(), - Err(e) => { - log::error!("Could not decode the head data: {e}"); - request.complete(None); - continue - }, - }; - - // Check if we have upgraded to an Aura compatible runtime and transition if - // necessary. - if client - .runtime_api() - .has_api::>(last_head_hash) - .unwrap_or(false) - { - // Respond to this request before transitioning to Aura. - request.complete(None); - break - } - } - - // Move to Aura consensus. - let slot_duration = match cumulus_client_consensus_aura::slot_duration(&*client) { - Ok(d) => d, - Err(e) => { - log::error!("Could not get Aura slot duration: {e}"); - return - }, - }; - - let proposer = Proposer::new(proposer_factory); - - let params = BasicAuraParams { - create_inherent_data_providers: move |_, ()| async move { Ok(()) }, - block_import, - para_client: client, - relay_client: relay_chain_interface2, - sync_oracle, - keystore, - collator_key, - para_id, - overseer_handle, - slot_duration, - relay_chain_slot_duration, - proposer, - collator_service, - // Very limited proposal time. - authoring_duration: Duration::from_millis(500), - collation_request_receiver: Some(request_stream), - }; - - basic_aura::run::::Pair, _, _, _, _, _, _, _>(params) - .await - }); + } else { + self.relay_chain_consensus + .lock() + .await + .produce_candidate(parent, relay_parent, validation_data) + .await + } + } +} - let spawner = task_manager.spawn_essential_handle(); - spawner.spawn_essential("cumulus-asset-hub-collator", None, collation_future); +struct Verifier { + client: Arc, + aura_verifier: BuildOnAccess>>, + relay_chain_verifier: Box>, + _phantom: PhantomData, +} - Ok(()) - }, - hwbench, - ) - .await +#[async_trait::async_trait] +impl VerifierT for Verifier +where + Client: sp_api::ProvideRuntimeApi + Send + Sync, + Client::Api: AuraApi, + AuraId: Send + Sync + Codec, +{ + async fn verify( + &mut self, + block_import: BlockImportParams, + ) -> Result, String> { + if self + .client + .runtime_api() + .has_api::>(*block_import.header.parent_hash()) + .unwrap_or(false) + { + self.aura_verifier.get_mut().verify(block_import).await + } else { + self.relay_chain_verifier.verify(block_import).await + } + } } -/// Start a shell node which should later transition into an Aura powered parachain node. Asset Hub -/// uses this because at genesis, Asset Hub was on the `shell` runtime which didn't have Aura and -/// needs to sync and upgrade before it can run `AuraApi` functions. -/// -/// Uses the lookahead collator to support async backing. -#[sc_tracing::logging::prefix_logs_with("Parachain")] -pub async fn start_asset_hub_lookahead_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> +/// Build the import queue for parachain runtimes that started with relay chain consensus and +/// switched to aura. +pub fn build_relay_to_aura_import_queue( + client: Arc>, + block_import: ParachainBlockImport, + config: &Configuration, + telemetry_handle: Option, + task_manager: &TaskManager, +) -> Result, sc_service::Error> where RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue @@ -1656,162 +636,74 @@ where + sp_api::ApiExt + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo - + sp_consensus_aura::AuraApi::Pair as Pair>::Public> - + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi - + frame_rpc_system::AccountNonceApi - + cumulus_primitives_aura::AuraUnincludedSegmentApi, + + sp_consensus_aura::AuraApi::Pair as Pair>::Public>, <::Pair as Pair>::Signature: TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - |_| Ok(RpcModule::new(())), - aura_build_import_queue::<_, AuraId>, - |client, - block_import, - prometheus_registry, - telemetry, - task_manager, - relay_chain_interface, - transaction_pool, - sync_oracle, - keystore, - relay_chain_slot_duration, - para_id, - collator_key, - overseer_handle, - announce_block, - backend| { - let relay_chain_interface2 = relay_chain_interface.clone(); - - let collator_service = CollatorService::new( - client.clone(), - Arc::new(task_manager.spawn_handle()), - announce_block, - client.clone(), - ); - - let spawner = task_manager.spawn_handle(); + let verifier_client = client.clone(); - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - spawner, - client.clone(), - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); + let aura_verifier = move || { + Box::new(cumulus_client_consensus_aura::build_verifier::< + ::Pair, + _, + _, + _, + >(cumulus_client_consensus_aura::BuildVerifierParams { + client: verifier_client.clone(), + create_inherent_data_providers: move |parent_hash, _| { + let cidp_client = verifier_client.clone(); + async move { + let slot_duration = cumulus_client_consensus_aura::slot_duration_at( + &*cidp_client, + parent_hash, + )?; + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let collation_future = Box::pin(async move { - // Start collating with the `shell` runtime while waiting for an upgrade to an Aura - // compatible runtime. - let mut request_stream = cumulus_client_collator::relay_chain_driven::init( - collator_key.clone(), - para_id, - overseer_handle.clone(), - ) - .await; - while let Some(request) = request_stream.next().await { - let pvd = request.persisted_validation_data().clone(); - let last_head_hash = - match ::Header::decode(&mut &pvd.parent_head.0[..]) { - Ok(header) => header.hash(), - Err(e) => { - log::error!("Could not decode the head data: {e}"); - request.complete(None); - continue - }, - }; + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); - // Check if we have upgraded to an Aura compatible runtime and transition if - // necessary. - if client - .runtime_api() - .has_api::>(last_head_hash) - .unwrap_or(false) - { - // Respond to this request before transitioning to Aura. - request.complete(None); - break - } + Ok((slot, timestamp)) } + }, + telemetry: telemetry_handle, + })) as Box<_> + }; - // Move to Aura consensus. - let proposer = Proposer::new(proposer_factory); - - let params = AuraParams { - create_inherent_data_providers: move |_, ()| async move { Ok(()) }, - block_import, - para_client: client.clone(), - para_backend: backend, - relay_client: relay_chain_interface2, - code_hash_provider: move |block_hash| { - client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) - }, - sync_oracle, - keystore, - collator_key, - para_id, - overseer_handle, - relay_chain_slot_duration, - proposer, - collator_service, - authoring_duration: Duration::from_millis(1500), - reinitialize: true, /* we need to always re-initialize for asset-hub moving - * to aura */ - }; + let relay_chain_verifier = + Box::new(RelayChainVerifier::new(client.clone(), |_, _| async { Ok(()) })) as Box<_>; - aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params) - .await - }); + let verifier = Verifier { + client, + relay_chain_verifier, + aura_verifier: BuildOnAccess::Uninitialized(Some(Box::new(aura_verifier))), + _phantom: PhantomData, + }; - let spawner = task_manager.spawn_essential_handle(); - spawner.spawn_essential("cumulus-asset-hub-collator", None, collation_future); + let registry = config.prometheus_registry(); + let spawner = task_manager.spawn_essential_handle(); - Ok(()) - }, - hwbench, - ) - .await + Ok(BasicQueue::new(verifier, Box::new(block_import), None, &spawner, registry)) } -/// Start an aura powered parachain node which uses the lookahead collator to support async backing. -/// This node is basic in the sense that its runtime api doesn't include common contents such as -/// transaction payment. Used for aura glutton. -pub async fn start_basic_lookahead_node( +/// Start an aura powered parachain node. Some system chains use this. +pub async fn start_generic_aura_node( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo - + sp_consensus_aura::AuraApi::Pair as Pair>::Public> - + frame_rpc_system::AccountNonceApi - + cumulus_primitives_aura::AuraUnincludedSegmentApi, - <::Pair as Pair>::Signature: - TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, -{ - start_basic_lookahead_node_impl::( +) -> sc_service::error::Result<(TaskManager, Arc>)> { + start_node_impl::( parachain_config, polkadot_config, collator_options, CollatorSybilResistance::Resistant, // Aura para_id, - |_| Ok(RpcModule::new(())), - aura_build_import_queue::<_, AuraId>, + build_parachain_rpc_extensions::, + build_relay_to_aura_import_queue::<_, AuraId>, |client, block_import, prometheus_registry, @@ -1826,7 +718,9 @@ where collator_key, overseer_handle, announce_block, - backend| { + _backend| { + let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( task_manager.spawn_handle(), client.clone(), @@ -1843,29 +737,27 @@ where client.clone(), ); - let params = AuraParams { + let params = BasicAuraParams { create_inherent_data_providers: move |_, ()| async move { Ok(()) }, block_import, - para_client: client.clone(), - para_backend: backend.clone(), + para_client: client, relay_client: relay_chain_interface, - code_hash_provider: move |block_hash| { - client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) - }, sync_oracle, keystore, collator_key, para_id, overseer_handle, + slot_duration, relay_chain_slot_duration, proposer, collator_service, - authoring_duration: Duration::from_millis(1500), - reinitialize: false, + // Very limited proposal time. + authoring_duration: Duration::from_millis(500), + collation_request_receiver: None, }; let fut = - aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params); + basic_aura::run::::Pair, _, _, _, _, _, _, _>(params); task_manager.spawn_essential_handle().spawn("aura", None, fut); Ok(()) @@ -1875,16 +767,38 @@ where .await } -#[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_contracts_rococo_node_impl( +/// Uses the lookahead collator to support async backing. +/// +/// Start an aura powered parachain node. Some system chains use this. +pub async fn start_generic_aura_lookahead_node( + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, +) -> sc_service::error::Result<(TaskManager, Arc>)> { + start_node_impl::( + parachain_config, + polkadot_config, + collator_options, + CollatorSybilResistance::Resistant, // Aura + para_id, + build_parachain_rpc_extensions::, + build_relay_to_aura_import_queue::<_, AuraId>, + start_lookahead_aura_consensus, + hwbench, + ) + .await +} + +/// Start a shell node which should later transition into an Aura powered parachain node. Asset Hub +/// uses this because at genesis, Asset Hub was on the `shell` runtime which didn't have Aura and +/// needs to sync and upgrade before it can run `AuraApi` functions. +pub async fn start_asset_hub_node( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, - sybil_resistance_level: CollatorSybilResistance, para_id: ParaId, - _rpc_ext_builder: RB, - build_import_queue: BIQ, - start_consensus: SC, hwbench: Option, ) -> sc_service::error::Result<(TaskManager, Arc>)> where @@ -1896,228 +810,169 @@ where + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder + cumulus_primitives_core::CollectCollationInfo + + sp_consensus_aura::AuraApi::Pair as Pair>::Public> + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi - + frame_rpc_system::AccountNonceApi - + cumulus_primitives_aura::AuraUnincludedSegmentApi, - RB: Fn(Arc>) -> Result, sc_service::Error>, - BIQ: FnOnce( - Arc>, - ParachainBlockImport, - &Configuration, - Option, - &TaskManager, - ) -> Result, sc_service::Error>, - SC: FnOnce( - Arc>, - ParachainBlockImport, - Option<&Registry>, - Option, - &TaskManager, - Arc, - Arc>>, - Arc>, - KeystorePtr, - Duration, - ParaId, - CollatorPair, - OverseerHandle, - Arc>) + Send + Sync>, - Arc, - ) -> Result<(), sc_service::Error>, + + frame_rpc_system::AccountNonceApi, + <::Pair as Pair>::Signature: + TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, { - let parachain_config = prepare_node_config(parachain_config); - - let params = new_partial::(¶chain_config, build_import_queue)?; - let (block_import, mut telemetry, telemetry_worker_handle) = params.other; - - let client = params.client.clone(); - let backend = params.backend.clone(); - let mut task_manager = params.task_manager; - - let (relay_chain_interface, collator_key) = build_relay_chain_interface( + start_node_impl::( + parachain_config, polkadot_config, - ¶chain_config, - telemetry_worker_handle, - &mut task_manager, - collator_options.clone(), - hwbench.clone(), - ) - .await - .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; - - let validator = parachain_config.role.is_authority(); - let prometheus_registry = parachain_config.prometheus_registry().cloned(); - let transaction_pool = params.transaction_pool.clone(); - let import_queue_service = params.import_queue.service(); - let net_config = FullNetworkConfiguration::new(¶chain_config.network); - - let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = - build_network(BuildNetworkParams { - parachain_config: ¶chain_config, - net_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - para_id, - spawn_handle: task_manager.spawn_handle(), - relay_chain_interface: relay_chain_interface.clone(), - import_queue: params.import_queue, - sybil_resistance_level, - }) - .await?; - - let rpc_builder = { - let client = client.clone(); - let transaction_pool = transaction_pool.clone(); - - Box::new(move |deny_unsafe, _| { - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: transaction_pool.clone(), - deny_unsafe, - }; - - crate::rpc::create_contracts_rococo(deps).map_err(Into::into) - }) - }; - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - rpc_builder, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - task_manager: &mut task_manager, - config: parachain_config, - keystore: params.keystore_container.keystore(), - backend: backend.clone(), - network: network.clone(), - sync_service: sync_service.clone(), - system_rpc_tx, - tx_handler_controller, - telemetry: telemetry.as_mut(), - })?; - - if let Some(hwbench) = hwbench { - sc_sysinfo::print_hwbench(&hwbench); - if validator { - warn_if_slow_hardware(&hwbench); - } - - if let Some(ref mut telemetry) = telemetry { - let telemetry_handle = telemetry.handle(); - task_manager.spawn_handle().spawn( - "telemetry_hwbench", - None, - sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench), - ); - } - } - - let announce_block = { - let sync_service = sync_service.clone(); - Arc::new(move |hash, data| sync_service.announce_block(hash, data)) - }; - - let relay_chain_slot_duration = Duration::from_secs(6); - - let overseer_handle = relay_chain_interface - .overseer_handle() - .map_err(|e| sc_service::Error::Application(Box::new(e)))?; - - start_relay_chain_tasks(StartRelayChainTasksParams { - client: client.clone(), - announce_block: announce_block.clone(), + collator_options, + CollatorSybilResistance::Resistant, // Aura para_id, - relay_chain_interface: relay_chain_interface.clone(), - task_manager: &mut task_manager, - da_recovery_profile: if validator { - DARecoveryProfile::Collator - } else { - DARecoveryProfile::FullNode - }, - import_queue: import_queue_service, - relay_chain_slot_duration, - recovery_handle: Box::new(overseer_handle.clone()), - sync_service: sync_service.clone(), - })?; + build_parachain_rpc_extensions::, + build_relay_to_aura_import_queue::<_, AuraId>, + |client, + block_import, + prometheus_registry, + telemetry, + task_manager, + relay_chain_interface, + transaction_pool, + sync_oracle, + keystore, + relay_chain_slot_duration, + para_id, + collator_key, + overseer_handle, + announce_block, + _backend| { + let relay_chain_interface2 = relay_chain_interface.clone(); - if validator { - start_consensus( - client.clone(), - block_import, - prometheus_registry.as_ref(), - telemetry.as_ref().map(|t| t.handle()), - &task_manager, - relay_chain_interface.clone(), - transaction_pool, - sync_service.clone(), - params.keystore_container.keystore(), - relay_chain_slot_duration, - para_id, - collator_key.expect("Command line arguments do not allow this. qed"), - overseer_handle, - announce_block, - backend.clone(), - )?; - } + let collator_service = CollatorService::new( + client.clone(), + Arc::new(task_manager.spawn_handle()), + announce_block, + client.clone(), + ); - start_network.start_network(); + let spawner = task_manager.spawn_handle(); - Ok((task_manager, client)) -} + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + spawner, + client.clone(), + transaction_pool, + prometheus_registry, + telemetry.clone(), + ); -#[allow(clippy::type_complexity)] -pub fn contracts_rococo_build_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - telemetry: Option, - task_manager: &TaskManager, -) -> Result, sc_service::Error> { - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; + let collation_future = Box::pin(async move { + // Start collating with the `shell` runtime while waiting for an upgrade to an Aura + // compatible runtime. + let mut request_stream = cumulus_client_collator::relay_chain_driven::init( + collator_key.clone(), + para_id, + overseer_handle.clone(), + ) + .await; + while let Some(request) = request_stream.next().await { + let pvd = request.persisted_validation_data().clone(); + let last_head_hash = + match ::Header::decode(&mut &pvd.parent_head.0[..]) { + Ok(header) => header.hash(), + Err(e) => { + log::error!("Could not decode the head data: {e}"); + request.complete(None); + continue + }, + }; - cumulus_client_consensus_aura::import_queue::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - >(cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + // Check if we have upgraded to an Aura compatible runtime and transition if + // necessary. + if client + .runtime_api() + .has_api::>(last_head_hash) + .unwrap_or(false) + { + // Respond to this request before transitioning to Aura. + request.complete(None); + break + } + } - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, + // Move to Aura consensus. + let slot_duration = match cumulus_client_consensus_aura::slot_duration(&*client) { + Ok(d) => d, + Err(e) => { + log::error!("Could not get Aura slot duration: {e}"); + return + }, + }; + + let proposer = Proposer::new(proposer_factory); + + let params = BasicAuraParams { + create_inherent_data_providers: move |_, ()| async move { Ok(()) }, + block_import, + para_client: client, + relay_client: relay_chain_interface2, + sync_oracle, + keystore, + collator_key, + para_id, + overseer_handle, slot_duration, - ); + relay_chain_slot_duration, + proposer, + collator_service, + // Very limited proposal time. + authoring_duration: Duration::from_millis(500), + collation_request_receiver: Some(request_stream), + }; - Ok((slot, timestamp)) + basic_aura::run::::Pair, _, _, _, _, _, _, _>(params) + .await + }); + + let spawner = task_manager.spawn_essential_handle(); + spawner.spawn_essential("cumulus-asset-hub-collator", None, collation_future); + + Ok(()) }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry, - }) - .map_err(Into::into) + hwbench, + ) + .await } -/// Start a parachain node. -pub async fn start_contracts_rococo_node( +/// Start a shell node which should later transition into an Aura powered parachain node. Asset Hub +/// uses this because at genesis, Asset Hub was on the `shell` runtime which didn't have Aura and +/// needs to sync and upgrade before it can run `AuraApi` functions. +/// +/// Uses the lookahead collator to support async backing. +#[sc_tracing::logging::prefix_logs_with("Parachain")] +pub async fn start_asset_hub_lookahead_node( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> { - start_contracts_rococo_node_impl::( +) -> sc_service::error::Result<(TaskManager, Arc>)> +where + RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, + RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_api::Metadata + + sp_session::SessionKeys + + sp_api::ApiExt + + sp_offchain::OffchainWorkerApi + + sp_block_builder::BlockBuilder + + cumulus_primitives_core::CollectCollationInfo + + sp_consensus_aura::AuraApi::Pair as Pair>::Public> + + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + + frame_rpc_system::AccountNonceApi + + cumulus_primitives_aura::AuraUnincludedSegmentApi, + <::Pair as Pair>::Signature: + TryFrom> + std::hash::Hash + sp_runtime::traits::Member + Codec, +{ + start_node_impl::( parachain_config, polkadot_config, collator_options, CollatorSybilResistance::Resistant, // Aura para_id, - |_| Ok(RpcModule::new(())), - contracts_rococo_build_import_queue, + build_parachain_rpc_extensions::, + build_relay_to_aura_import_queue::<_, AuraId>, |client, block_import, prometheus_registry, @@ -2133,14 +988,7 @@ pub async fn start_contracts_rococo_node( overseer_handle, announce_block, backend| { - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); - let proposer = Proposer::new(proposer_factory); + let relay_chain_interface2 = relay_chain_interface.clone(); let collator_service = CollatorService::new( client.clone(), @@ -2149,42 +997,81 @@ pub async fn start_contracts_rococo_node( client.clone(), ); - let params = AuraParams { - create_inherent_data_providers: move |_, ()| async move { Ok(()) }, - block_import, - para_client: client.clone(), - para_backend: backend.clone(), - relay_client: relay_chain_interface, - code_hash_provider: move |block_hash| { - client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) - }, - sync_oracle, - keystore, - collator_key, - para_id, - overseer_handle, - relay_chain_slot_duration, - proposer, - collator_service, - // Very limited proposal time. - authoring_duration: Duration::from_millis(1500), - reinitialize: false, - }; + let spawner = task_manager.spawn_handle(); - let fut = aura::run::< - Block, - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - _, - _, - _, - _, - >(params); - task_manager.spawn_essential_handle().spawn("aura", None, fut); + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + spawner, + client.clone(), + transaction_pool, + prometheus_registry, + telemetry.clone(), + ); + + let collation_future = Box::pin(async move { + // Start collating with the `shell` runtime while waiting for an upgrade to an Aura + // compatible runtime. + let mut request_stream = cumulus_client_collator::relay_chain_driven::init( + collator_key.clone(), + para_id, + overseer_handle.clone(), + ) + .await; + while let Some(request) = request_stream.next().await { + let pvd = request.persisted_validation_data().clone(); + let last_head_hash = + match ::Header::decode(&mut &pvd.parent_head.0[..]) { + Ok(header) => header.hash(), + Err(e) => { + log::error!("Could not decode the head data: {e}"); + request.complete(None); + continue + }, + }; + + // Check if we have upgraded to an Aura compatible runtime and transition if + // necessary. + if client + .runtime_api() + .has_api::>(last_head_hash) + .unwrap_or(false) + { + // Respond to this request before transitioning to Aura. + request.complete(None); + break + } + } + + // Move to Aura consensus. + let proposer = Proposer::new(proposer_factory); + + let params = AuraParams { + create_inherent_data_providers: move |_, ()| async move { Ok(()) }, + block_import, + para_client: client.clone(), + para_backend: backend, + relay_client: relay_chain_interface2, + code_hash_provider: move |block_hash| { + client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) + }, + sync_oracle, + keystore, + collator_key, + para_id, + overseer_handle, + relay_chain_slot_duration, + proposer, + collator_service, + authoring_duration: Duration::from_millis(1500), + reinitialize: true, /* we need to always re-initialize for asset-hub moving + * to aura */ + }; + + aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params) + .await + }); + + let spawner = task_manager.spawn_essential_handle(); + spawner.spawn_essential("cumulus-asset-hub-collator", None, collation_future); Ok(()) }, @@ -2193,6 +1080,184 @@ pub async fn start_contracts_rococo_node( .await } +/// Start relay-chain consensus that is free for all. Everyone can submit a block, the relay-chain +/// decides what is backed and included. +fn start_relay_chain_consensus( + client: Arc>, + block_import: ParachainBlockImport, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, + relay_chain_interface: Arc, + transaction_pool: Arc>>, + _sync_oracle: Arc>, + _keystore: KeystorePtr, + _relay_chain_slot_duration: Duration, + para_id: ParaId, + collator_key: CollatorPair, + overseer_handle: OverseerHandle, + announce_block: Arc>) + Send + Sync>, + _backend: Arc, +) -> Result<(), sc_service::Error> { + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + task_manager.spawn_handle(), + client.clone(), + transaction_pool, + prometheus_registry, + telemetry, + ); + + let free_for_all = cumulus_client_consensus_relay_chain::build_relay_chain_consensus( + cumulus_client_consensus_relay_chain::BuildRelayChainConsensusParams { + para_id, + proposer_factory, + block_import, + relay_chain_interface: relay_chain_interface.clone(), + create_inherent_data_providers: move |_, (relay_parent, validation_data)| { + let relay_chain_interface = relay_chain_interface.clone(); + async move { + let parachain_inherent = + cumulus_client_parachain_inherent::ParachainInherentDataProvider::create_at( + relay_parent, + &relay_chain_interface, + &validation_data, + para_id, + ).await; + let parachain_inherent = parachain_inherent.ok_or_else(|| { + Box::::from( + "Failed to create parachain inherent", + ) + })?; + Ok(parachain_inherent) + } + }, + }, + ); + + let spawner = task_manager.spawn_handle(); + + // Required for free-for-all consensus + #[allow(deprecated)] + old_consensus::start_collator_sync(old_consensus::StartCollatorParams { + para_id, + block_status: client.clone(), + announce_block, + overseer_handle, + spawner, + key: collator_key, + parachain_consensus: free_for_all, + runtime_api: client.clone(), + }); + + Ok(()) +} + +/// Start consensus using the lookahead aura collator. +fn start_lookahead_aura_consensus( + client: Arc>, + block_import: ParachainBlockImport, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, + relay_chain_interface: Arc, + transaction_pool: Arc>>, + sync_oracle: Arc>, + keystore: KeystorePtr, + relay_chain_slot_duration: Duration, + para_id: ParaId, + collator_key: CollatorPair, + overseer_handle: OverseerHandle, + announce_block: Arc>) + Send + Sync>, + backend: Arc, +) -> Result<(), sc_service::Error> { + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + task_manager.spawn_handle(), + client.clone(), + transaction_pool, + prometheus_registry, + telemetry.clone(), + ); + + let collator_service = CollatorService::new( + client.clone(), + Arc::new(task_manager.spawn_handle()), + announce_block, + client.clone(), + ); + + let params = AuraParams { + create_inherent_data_providers: move |_, ()| async move { Ok(()) }, + block_import, + para_client: client.clone(), + para_backend: backend, + relay_client: relay_chain_interface, + code_hash_provider: move |block_hash| { + client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) + }, + sync_oracle, + keystore, + collator_key, + para_id, + overseer_handle, + relay_chain_slot_duration, + proposer: Proposer::new(proposer_factory), + collator_service, + authoring_duration: Duration::from_millis(1500), + reinitialize: false, + }; + + let fut = aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params); + task_manager.spawn_essential_handle().spawn("aura", None, fut); + + Ok(()) +} + +/// Start an aura powered parachain node which uses the lookahead collator to support async backing. +/// This node is basic in the sense that its runtime api doesn't include common contents such as +/// transaction payment. Used for aura glutton. +pub async fn start_basic_lookahead_node( + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, +) -> sc_service::error::Result<(TaskManager, Arc>)> { + start_node_impl::( + parachain_config, + polkadot_config, + collator_options, + CollatorSybilResistance::Resistant, // Aura + para_id, + |_, _, _, _| Ok(RpcModule::new(())), + build_relay_to_aura_import_queue::<_, AuraId>, + start_lookahead_aura_consensus, + hwbench, + ) + .await +} + +/// Start a parachain node for Rococo Contracts. +pub async fn start_contracts_rococo_node( + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, +) -> sc_service::error::Result<(TaskManager, Arc>)> { + start_node_impl::( + parachain_config, + polkadot_config, + collator_options, + CollatorSybilResistance::Resistant, // Aura + para_id, + build_contracts_rpc_extensions, + build_aura_import_queue, + start_lookahead_aura_consensus, + hwbench, + ) + .await +} + /// Checks that the hardware meets the requirements and print a warning otherwise. fn warn_if_slow_hardware(hwbench: &sc_sysinfo::HwBench) { // Polkadot para-chains should generally use these requirements to ensure that the relay-chain -- GitLab From f977c211573e65b9f89886e7211e9b3148ce7e05 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Fri, 8 Mar 2024 10:48:55 +0100 Subject: [PATCH 092/188] Contracts Bump ApiVersion and add test (#3619) ApiVersion should have been bumped with https://github.com/paritytech/polkadot-sdk/pull/3606 this does that and add a test so we don't forget to do that everytime --- substrate/frame/contracts/proc-macro/src/lib.rs | 5 +++++ substrate/frame/contracts/src/lib.rs | 11 ++++++++++- substrate/frame/contracts/src/wasm/mod.rs | 3 +++ substrate/frame/contracts/src/wasm/runtime.rs | 1 - 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/substrate/frame/contracts/proc-macro/src/lib.rs b/substrate/frame/contracts/proc-macro/src/lib.rs index de961776c32..1794d09d5ad 100644 --- a/substrate/frame/contracts/proc-macro/src/lib.rs +++ b/substrate/frame/contracts/proc-macro/src/lib.rs @@ -497,9 +497,14 @@ fn expand_docs(def: &EnvDef) -> TokenStream2 { fn expand_env(def: &EnvDef, docs: bool) -> TokenStream2 { let impls = expand_impls(def); let docs = docs.then_some(expand_docs(def)).unwrap_or(TokenStream2::new()); + let stable_api_count = def.host_funcs.iter().filter(|f| f.is_stable).count(); quote! { pub struct Env; + + #[cfg(test)] + pub const STABLE_API_COUNT: usize = #stable_api_count; + #impls /// Documentation of the API (host functions) available to contracts. /// diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs index 0511bcf7f3f..de84d5220c5 100644 --- a/substrate/frame/contracts/src/lib.rs +++ b/substrate/frame/contracts/src/lib.rs @@ -222,10 +222,19 @@ pub struct Environment { pub struct ApiVersion(u16); impl Default for ApiVersion { fn default() -> Self { - Self(1) + Self(2) } } +#[test] +fn api_version_is_up_to_date() { + assert_eq!( + 109, + crate::wasm::STABLE_API_COUNT, + "Stable API count has changed. Bump the returned value of ApiVersion::default() and update the test." + ); +} + #[frame_support::pallet] pub mod pallet { use super::*; diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs index 23363780b14..af287a6f2df 100644 --- a/substrate/frame/contracts/src/wasm/mod.rs +++ b/substrate/frame/contracts/src/wasm/mod.rs @@ -21,6 +21,9 @@ mod prepare; mod runtime; +#[cfg(test)] +pub use runtime::STABLE_API_COUNT; + #[cfg(doc)] pub use crate::wasm::runtime::api_doc; diff --git a/substrate/frame/contracts/src/wasm/runtime.rs b/substrate/frame/contracts/src/wasm/runtime.rs index 402ff78dcde..7d43d30ba58 100644 --- a/substrate/frame/contracts/src/wasm/runtime.rs +++ b/substrate/frame/contracts/src/wasm/runtime.rs @@ -987,7 +987,6 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { // for every function. #[define_env(doc)] pub mod env { - /// Set the value at the given key in the contract storage. /// See [`pallet_contracts_uapi::HostFn::set_storage`] #[prefixed_alias] -- GitLab From 6f3caac0517278f0fdd614545c9ef620200bc02f Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Date: Fri, 8 Mar 2024 14:10:47 +0200 Subject: [PATCH 093/188] collator-protocol: Always stay connected to validators in backing group (#3544) Looking at rococo-asset-hub https://github.com/paritytech/polkadot-sdk/issues/3519 there seems to be a lot of instances where collator did not advertise their collations, while there are multiple problems there, one of it is that we are connecting and disconnecting to our assigned validators every block, because on reconnect_timeout every 4s we call connect_to_validators and that will produce 0 validators when all went well, so set_reseverd_peers called from validator discovery will disconnect all our peers. More details here: https://github.com/paritytech/polkadot-sdk/issues/3519#issuecomment-1972667343 Now, this shouldn't be a problem, but it stacks with an existing bug in our network stack where if disconnect from a peer the peer might not notice it, so it won't detect the reconnect either and it won't send us the necessary view updates, so we won't advertise the collation to it more details here: https://github.com/paritytech/polkadot-sdk/issues/3519#issuecomment-1972958276 To avoid hitting this condition that often, let's keep the peers in the reserved set for the entire duration we are allocated to a backing group. Backing group sizes(1 rococo, 3 kusama, 5 polkadot) are really small, so this shouldn't lead to that many connections. Additionally, the validators would disconnect us any way if we don't advertise anything for 4 blocks. ## TODO - [x] More testing. - [x] Confirm on rococo that this is improving the situation. (It doesn't but just because other things are going wrong there). --------- Signed-off-by: Alexandru Gheorghe --- .../src/collator_side/validators_buffer.rs | 38 +++++++++++++++---- .../src/validator_side/mod.rs | 2 +- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/polkadot/node/network/collator-protocol/src/collator_side/validators_buffer.rs b/polkadot/node/network/collator-protocol/src/collator_side/validators_buffer.rs index 5b88efc99d8..1533f2eda5a 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/validators_buffer.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/validators_buffer.rs @@ -90,8 +90,7 @@ impl ValidatorGroupsBuffer { } } - /// Returns discovery ids of validators we have at least one advertised-but-not-fetched - /// collation for. + /// Returns discovery ids of validators we are assigned to in this backing group window. pub fn validators_to_connect(&self) -> Vec { let validators_num = self.validators.len(); let bits = self @@ -99,11 +98,22 @@ impl ValidatorGroupsBuffer { .values() .fold(bitvec![0; validators_num], |acc, next| acc | next); - self.validators + let mut should_be_connected: Vec = self + .validators .iter() .enumerate() .filter_map(|(idx, authority_id)| bits[idx].then_some(authority_id.clone())) - .collect() + .collect(); + + if let Some(last_group) = self.group_infos.iter().last() { + for validator in self.validators.iter().rev().take(last_group.len) { + if !should_be_connected.contains(validator) { + should_be_connected.push(validator.clone()); + } + } + } + + should_be_connected } /// Note a new advertisement, marking that we want to be connected to validators @@ -279,7 +289,7 @@ mod tests { assert_eq!(buf.validators_to_connect(), validators[..2].to_vec()); buf.reset_validator_interest(hash_a, &validators[1]); - assert_eq!(buf.validators_to_connect(), vec![validators[0].clone()]); + assert_eq!(buf.validators_to_connect(), validators[0..2].to_vec()); buf.note_collation_advertised(hash_b, 0, GroupIndex(1), &validators[2..]); assert_eq!(buf.validators_to_connect(), validators[2..].to_vec()); @@ -287,7 +297,11 @@ mod tests { for validator in &validators[2..] { buf.reset_validator_interest(hash_b, validator); } - assert!(buf.validators_to_connect().is_empty()); + let mut expected = validators[2..].to_vec(); + expected.sort(); + let mut result = buf.validators_to_connect(); + result.sort(); + assert_eq!(result, expected); } #[test] @@ -320,10 +334,18 @@ mod tests { } buf.reset_validator_interest(hashes[1], &validators[0]); - assert_eq!(buf.validators_to_connect(), validators[..2].to_vec()); + let mut expected: Vec<_> = validators[..4].iter().cloned().collect(); + let mut result = buf.validators_to_connect(); + expected.sort(); + result.sort(); + assert_eq!(result, expected); buf.reset_validator_interest(hashes[0], &validators[0]); - assert_eq!(buf.validators_to_connect(), vec![validators[1].clone()]); + let mut expected: Vec<_> = validators[1..4].iter().cloned().collect(); + expected.sort(); + let mut result = buf.validators_to_connect(); + result.sort(); + assert_eq!(result, expected); buf.note_collation_advertised(hashes[3], 0, GroupIndex(1), &validators[2..4]); buf.note_collation_advertised( diff --git a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs index 48ad3c711a6..a1b93fff348 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs @@ -1883,7 +1883,7 @@ async fn disconnect_inactive_peers( ) { for (peer, peer_data) in peers { if peer_data.is_inactive(&eviction_policy) { - gum::trace!(target: LOG_TARGET, "Disconnecting inactive peer"); + gum::trace!(target: LOG_TARGET, ?peer, "Disconnecting inactive peer"); disconnect_peer(sender, *peer).await; } } -- GitLab From a0c9a3d65adb63d83afdf5b29d2e555dea0fa35e Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Fri, 8 Mar 2024 17:36:09 +0100 Subject: [PATCH 094/188] benchmark: allow range trailing comma in RangeArgs (#3598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rustfmt will add a trailing comma for longer expression, this change will make sure that the Range parameters can still be parsed. --------- Co-authored-by: command-bot <> Co-authored-by: Alexander Theißen --- substrate/frame/support/procedural/src/benchmark.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/frame/support/procedural/src/benchmark.rs b/substrate/frame/support/procedural/src/benchmark.rs index d16ad2aaa51..27c75a7f054 100644 --- a/substrate/frame/support/procedural/src/benchmark.rs +++ b/substrate/frame/support/procedural/src/benchmark.rs @@ -65,6 +65,7 @@ struct RangeArgs { start: syn::GenericArgument, _comma: Comma, end: syn::GenericArgument, + _trailing_comma: Option, _gt_token: Gt, } -- GitLab From 1fe3c5f23b9c057a2ff1926daf4ecfd5b022da45 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Fri, 8 Mar 2024 19:13:31 +0100 Subject: [PATCH 095/188] Contracts: Fix terminate benchmark (#3558) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Theißen Co-authored-by: command-bot <> --- substrate/frame/contracts/src/benchmarking/mod.rs | 3 ++- substrate/frame/contracts/src/storage.rs | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 2ecd56b412d..794777ef05c 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -927,7 +927,7 @@ benchmarks! { value: code_hashes_bytes, }, ], - deploy_body: Some(body::repeated_dyn(r, vec![ + deploy_body: Some(body::repeated_dyn(T::MaxDelegateDependencies::get(), vec![ Counter(beneficiary_len as u32, code_hash_len as u32), // code_hash_ptr Regular(Instruction::Call(1)), ])), @@ -943,6 +943,7 @@ benchmarks! { assert_eq!(T::Currency::total_balance(&beneficiary), 0u32.into()); assert_eq!(T::Currency::balance(&instance.account_id), Pallet::::min_balance() * 2u32.into()); assert_ne!(T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &instance.account_id), 0u32.into()); + assert_eq!(ContractInfoOf::::get(&instance.account_id).unwrap().delegate_dependencies_count() as u32, T::MaxDelegateDependencies::get()); }: call(origin, instance.addr.clone(), 0u32.into(), Weight::MAX, None, vec![]) verify { if r > 0 { diff --git a/substrate/frame/contracts/src/storage.rs b/substrate/frame/contracts/src/storage.rs index 52c5150ca21..e99afd5d42e 100644 --- a/substrate/frame/contracts/src/storage.rs +++ b/substrate/frame/contracts/src/storage.rs @@ -108,6 +108,11 @@ impl ContractInfo { Ok(contract) } + /// Returns the number of locked delegate dependencies. + pub fn delegate_dependencies_count(&self) -> usize { + self.delegate_dependencies.len() + } + /// Associated child trie unique id is built from the hash part of the trie id. pub fn child_trie_info(&self) -> ChildInfo { ChildInfo::new_default(self.trie_id.as_ref()) -- GitLab From ea458d0b95d819d31683a8a09ca7973ae10b49be Mon Sep 17 00:00:00 2001 From: cuinix <65650185+cuinix@users.noreply.github.com> Date: Sat, 9 Mar 2024 05:28:04 +0800 Subject: [PATCH 096/188] fix some typos (#3587) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: cuinix <915115094@qq.com> Co-authored-by: Bastian Köcher --- bridges/primitives/test-utils/src/lib.rs | 2 +- cumulus/client/parachain-inherent/src/lib.rs | 4 ++-- .../parachains/integration-tests/emulated/common/src/impls.rs | 2 +- .../runtimes/coretime/coretime-rococo/src/xcm_config.rs | 2 +- .../runtimes/coretime/coretime-westend/src/xcm_config.rs | 2 +- .../runtimes/people/people-rococo/src/xcm_config.rs | 2 +- .../runtimes/people/people-westend/src/xcm_config.rs | 2 +- polkadot/cli/src/cli.rs | 2 +- polkadot/node/core/dispute-coordinator/src/initialized.rs | 2 +- polkadot/node/core/pvf-checker/src/lib.rs | 4 ++-- polkadot/node/subsystem-bench/README.md | 4 ++-- polkadot/node/subsystem-bench/src/lib/availability/mod.rs | 2 +- polkadot/node/subsystem-bench/src/lib/mock/av_store.rs | 2 +- polkadot/node/subsystem-bench/src/lib/network.rs | 4 ++-- polkadot/primitives/src/v6/slashing.rs | 2 +- polkadot/runtime/parachains/src/paras/mod.rs | 2 +- substrate/bin/node/cli/src/cli.rs | 2 +- templates/parachain/node/src/cli.rs | 2 +- templates/solochain/node/src/cli.rs | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/bridges/primitives/test-utils/src/lib.rs b/bridges/primitives/test-utils/src/lib.rs index f23ddd1a10d..1d80890779b 100644 --- a/bridges/primitives/test-utils/src/lib.rs +++ b/bridges/primitives/test-utils/src/lib.rs @@ -129,7 +129,7 @@ pub fn make_justification_for_header( votes_ancestries.push(child.clone()); } - // The header we need to use when pre-commiting is the one at the highest height + // The header we need to use when pre-committing is the one at the highest height // on our chain. let precommit_candidate = chain.last().map(|h| (h.hash(), *h.number())).unwrap(); unsigned_precommits.push(precommit_candidate); diff --git a/cumulus/client/parachain-inherent/src/lib.rs b/cumulus/client/parachain-inherent/src/lib.rs index 57353638e19..051eb6764c8 100644 --- a/cumulus/client/parachain-inherent/src/lib.rs +++ b/cumulus/client/parachain-inherent/src/lib.rs @@ -159,7 +159,7 @@ impl ParachainInherentDataProvider { target: LOG_TARGET, relay_parent = ?relay_parent, error = ?e, - "An error occured during requesting the downward messages.", + "An error occurred during requesting the downward messages.", ); }) .ok()?; @@ -171,7 +171,7 @@ impl ParachainInherentDataProvider { target: LOG_TARGET, relay_parent = ?relay_parent, error = ?e, - "An error occured during requesting the inbound HRMP messages.", + "An error occurred during requesting the inbound HRMP messages.", ); }) .ok()?; diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs index 4bbb4701e43..c93484829fe 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -265,7 +265,7 @@ macro_rules! impl_assert_events_helpers_for_relay_chain { $crate::impls::assert_expected_events!( Self, vec![ - // XCM is succesfully received and proccessed + // XCM is successfully received and proccessed [<$chain RuntimeEvent>]::::MessageQueue($crate::impls::pallet_message_queue::Event::Processed { origin: $crate::impls::AggregateMessageOrigin::Ump($crate::impls::UmpQueueId::Para(id)), weight_used, diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs index 37bb8809dab..1722e1fcb31 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs @@ -192,7 +192,7 @@ pub type Barrier = TrailingSetTopicAsId< AllowKnownQueryResponses, WithComputedOrigin< ( - // If the message is one that immediately attemps to pay for execution, then + // If the message is one that immediately attempts to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, // Parent and its pluralities (i.e. governance bodies) get free execution. diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs index 44049adf027..b03c7748fe0 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs @@ -198,7 +198,7 @@ pub type Barrier = TrailingSetTopicAsId< AllowKnownQueryResponses, WithComputedOrigin< ( - // If the message is one that immediately attemps to pay for execution, then + // If the message is one that immediately attempts to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, // Parent, its pluralities (i.e. governance bodies), and the Fellows plurality diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs index 311128a17ca..534d6519086 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs @@ -207,7 +207,7 @@ pub type Barrier = TrailingSetTopicAsId< AllowKnownQueryResponses, WithComputedOrigin< ( - // If the message is one that immediately attemps to pay for execution, then + // If the message is one that immediately attempts to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, // Parent and its pluralities (i.e. governance bodies) get free execution. diff --git a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs index 4b7da91c17e..6353a581352 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs @@ -214,7 +214,7 @@ pub type Barrier = TrailingSetTopicAsId< AllowKnownQueryResponses, WithComputedOrigin< ( - // If the message is one that immediately attemps to pay for execution, then + // If the message is one that immediately attempts to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, // Parent, its pluralities (i.e. governance bodies), and the Fellows plurality diff --git a/polkadot/cli/src/cli.rs b/polkadot/cli/src/cli.rs index 30f35ebcb6f..e1bc2309a94 100644 --- a/polkadot/cli/src/cli.rs +++ b/polkadot/cli/src/cli.rs @@ -52,7 +52,7 @@ pub enum Subcommand { /// Try-runtime has migrated to a standalone CLI /// (). The subcommand exists as a stub and - /// deprecation notice. It will be removed entirely some time after Janurary 2024. + /// deprecation notice. It will be removed entirely some time after January 2024. TryRuntime, /// Key management CLI utilities diff --git a/polkadot/node/core/dispute-coordinator/src/initialized.rs b/polkadot/node/core/dispute-coordinator/src/initialized.rs index 54e0410268f..5f86da87f21 100644 --- a/polkadot/node/core/dispute-coordinator/src/initialized.rs +++ b/polkadot/node/core/dispute-coordinator/src/initialized.rs @@ -99,7 +99,7 @@ pub(crate) struct Initialized { /// This is the highest `SessionIndex` seen via `ActiveLeavesUpdate`. It doesn't matter if it /// was cached successfully or not. It is used to detect ancient disputes. highest_session_seen: SessionIndex, - /// Will be set to `true` if an error occured during the last caching attempt + /// Will be set to `true` if an error occurred during the last caching attempt gaps_in_cache: bool, spam_slots: SpamSlots, participation: Participation, diff --git a/polkadot/node/core/pvf-checker/src/lib.rs b/polkadot/node/core/pvf-checker/src/lib.rs index ae0fae6b4f9..c00ec0d952f 100644 --- a/polkadot/node/core/pvf-checker/src/lib.rs +++ b/polkadot/node/core/pvf-checker/src/lib.rs @@ -415,7 +415,7 @@ async fn check_signing_credentials( gum::warn!( target: LOG_TARGET, relay_parent = ?leaf, - "error occured during requesting validators: {:?}", + "error occurred during requesting validators: {:?}", e ); return None @@ -508,7 +508,7 @@ async fn sign_and_submit_pvf_check_statement( target: LOG_TARGET, ?relay_parent, ?validation_code_hash, - "error occured during submitting a vote: {:?}", + "error occurred during submitting a vote: {:?}", e, ); }, diff --git a/polkadot/node/subsystem-bench/README.md b/polkadot/node/subsystem-bench/README.md index 3aac2810ad5..94a449ed0bb 100644 --- a/polkadot/node/subsystem-bench/README.md +++ b/polkadot/node/subsystem-bench/README.md @@ -45,7 +45,7 @@ docker compose up Please follow the [official installation guide](https://prometheus.io/docs/prometheus/latest/installation/) for your platform/OS. -After succesfully installing and starting up Prometheus, we need to alter it's configuration such that it +After successfully installing and starting up Prometheus, we need to alter it's configuration such that it will scrape the benchmark prometheus endpoint `127.0.0.1:9999`. Please check the prometheus official documentation regarding the location of `prometheus.yml`. On MacOS for example the full path `/opt/homebrew/etc/prometheus.yml` @@ -211,7 +211,7 @@ You can select log target, subtarget and verbosity just like with Polkadot node ### View test metrics -Assuming the Grafana/Prometheus stack installation steps completed succesfully, you should be able to +Assuming the Grafana/Prometheus stack installation steps completed successfully, you should be able to view the test progress in real time by accessing [this link](http://localhost:3000/goto/SM5B8pNSR?orgId=1). Now run diff --git a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs index f012a5a907e..dc4e1e40310 100644 --- a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs @@ -598,7 +598,7 @@ pub async fn benchmark_availability_write( gum::info!(target: LOG_TARGET, "Waiting for all emulated peers to receive their chunk from us ..."); for receiver in receivers.into_iter() { - let response = receiver.await.expect("Chunk is always served succesfully"); + let response = receiver.await.expect("Chunk is always served successfully"); // TODO: check if chunk is the one the peer expects to receive. assert!(response.result.is_ok()); } diff --git a/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs index 41c4fe2cbad..9064f17940f 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs @@ -97,7 +97,7 @@ impl HandleNetworkMessage for NetworkAvailabilityState { outgoing_request .pending_response .send(response) - .expect("Response is always sent succesfully"); + .expect("Response is always sent successfully"); None }, _ => Some(NetworkMessage::RequestFromNode(peer, request)), diff --git a/polkadot/node/subsystem-bench/src/lib/network.rs b/polkadot/node/subsystem-bench/src/lib/network.rs index 1e09441792d..1bc35a014ff 100644 --- a/polkadot/node/subsystem-bench/src/lib/network.rs +++ b/polkadot/node/subsystem-bench/src/lib/network.rs @@ -219,7 +219,7 @@ impl Future for ProxiedRequest { Poll::Ready(response) => Poll::Ready(ProxiedResponse { sender: self.sender.take().expect("sender already used"), result: response - .expect("Response is always succesfully received.") + .expect("Response is always successfully received.") .result .map_err(|_| RequestFailure::Refused), }), @@ -761,7 +761,7 @@ pub fn new_network( gum::info!(target: LOG_TARGET, "{}",format!("connectivity {}%, latency {:?}", config.connectivity, config.latency).bright_black()); let metrics = - Metrics::new(&dependencies.registry).expect("Metrics always register succesfully"); + Metrics::new(&dependencies.registry).expect("Metrics always register successfully"); let mut validator_authority_id_mapping = HashMap::new(); // Create the channel from `peer` to `NetworkInterface` . diff --git a/polkadot/primitives/src/v6/slashing.rs b/polkadot/primitives/src/v6/slashing.rs index efffb932cdc..bcd7d0c2fc4 100644 --- a/polkadot/primitives/src/v6/slashing.rs +++ b/polkadot/primitives/src/v6/slashing.rs @@ -54,7 +54,7 @@ impl DisputesTimeSlot { /// is required to identify and verify it. #[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug)] pub struct DisputeProof { - /// Time slot when the dispute occured. + /// Time slot when the dispute occurred. pub time_slot: DisputesTimeSlot, /// The dispute outcome. pub kind: SlashingOffenceKind, diff --git a/polkadot/runtime/parachains/src/paras/mod.rs b/polkadot/runtime/parachains/src/paras/mod.rs index 39371391b1f..5acdb9683bb 100644 --- a/polkadot/runtime/parachains/src/paras/mod.rs +++ b/polkadot/runtime/parachains/src/paras/mod.rs @@ -1374,7 +1374,7 @@ impl Pallet { outgoing } - // note replacement of the code of para with given `id`, which occured in the + // note replacement of the code of para with given `id`, which occurred in the // context of the given relay-chain block number. provide the replaced code. // // `at` for para-triggered replacement is the block number of the relay-chain diff --git a/substrate/bin/node/cli/src/cli.rs b/substrate/bin/node/cli/src/cli.rs index f3c0435fd32..3345afae4fd 100644 --- a/substrate/bin/node/cli/src/cli.rs +++ b/substrate/bin/node/cli/src/cli.rs @@ -63,7 +63,7 @@ pub enum Subcommand { /// Try-runtime has migrated to a standalone CLI /// (). The subcommand exists as a stub and - /// deprecation notice. It will be removed entirely some time after Janurary 2024. + /// deprecation notice. It will be removed entirely some time after January 2024. TryRuntime, /// Key management cli utilities diff --git a/templates/parachain/node/src/cli.rs b/templates/parachain/node/src/cli.rs index 73ef996b750..a5c55b8118a 100644 --- a/templates/parachain/node/src/cli.rs +++ b/templates/parachain/node/src/cli.rs @@ -40,7 +40,7 @@ pub enum Subcommand { /// Try-runtime has migrated to a standalone /// [CLI](). The subcommand exists as a stub and - /// deprecation notice. It will be removed entirely some time after Janurary 2024. + /// deprecation notice. It will be removed entirely some time after January 2024. TryRuntime, } diff --git a/templates/solochain/node/src/cli.rs b/templates/solochain/node/src/cli.rs index 98037eb886a..7f1b67b3696 100644 --- a/templates/solochain/node/src/cli.rs +++ b/templates/solochain/node/src/cli.rs @@ -43,7 +43,7 @@ pub enum Subcommand { /// Try-runtime has migrated to a standalone CLI /// (). The subcommand exists as a stub and - /// deprecation notice. It will be removed entirely some time after Janurary 2024. + /// deprecation notice. It will be removed entirely some time after January 2024. TryRuntime, /// Db meta columns information. -- GitLab From 9f5d9fa96f88007292c2d59810b7c3c855da58a7 Mon Sep 17 00:00:00 2001 From: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Date: Sat, 9 Mar 2024 11:14:06 +0100 Subject: [PATCH 097/188] core: replace secp256k with k256 in crypto::ecdsa (#3525) This PR replaces the usage of [secp256k](https://crates.io/crates/secp256k1) crate with [k256](https://crates.io/crates/k256) in `core::crypto::ecdsa` for `non-std` environments as outcome of discussion in #3448. `secp256k1` is used in `std`, meaning that we should not affect host performance with this PR. `k256` is enabled in runtimes (`no-std`), and is required to proceed with #2044. If desirable, in future we can switch to `k256` also for `std`. That would require some performance evaluation (e.g. for EVM chains as per https://github.com/paritytech/polkadot-sdk/issues/3448#issuecomment-1976780391). Closes https://github.com/paritytech/polkadot-sdk/issues/3448 --------- Co-authored-by: command-bot <> Co-authored-by: Davide Galassi --- Cargo.lock | 27 ++++- substrate/primitives/core/Cargo.toml | 9 +- substrate/primitives/core/src/ecdsa.rs | 145 +++++++++++++++++-------- 3 files changed, 129 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e38f09db4d3..0b7ea71a536 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4815,6 +4815,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", + "serdect", "signature", "spki", ] @@ -4881,9 +4882,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", @@ -4894,6 +4895,7 @@ dependencies = [ "pkcs8", "rand_core 0.6.4", "sec1", + "serdect", "subtle 2.5.0", "zeroize", ] @@ -6971,14 +6973,15 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", "once_cell", + "serdect", "sha2 0.10.7", ] @@ -17101,6 +17104,7 @@ dependencies = [ "der", "generic-array 0.14.7", "pkcs8", + "serdect", "subtle 2.5.0", "zeroize", ] @@ -17359,6 +17363,16 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "serial_test" version = "2.0.0" @@ -18567,6 +18581,7 @@ dependencies = [ "hash256-std-hasher", "impl-serde", "itertools 0.10.5", + "k256", "lazy_static", "libsecp256k1", "log", @@ -22553,9 +22568,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml index 70ca7be6a2d..f7cc2b4fcf7 100644 --- a/substrate/primitives/core/Cargo.toml +++ b/substrate/primitives/core/Cargo.toml @@ -52,9 +52,12 @@ blake2 = { version = "0.10.4", default-features = false, optional = true } libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context"], optional = true } schnorrkel = { version = "0.11.4", features = ["preaudit_deprecated"], default-features = false } merlin = { version = "3.0", default-features = false } -secp256k1 = { version = "0.28.0", default-features = false, features = ["alloc", "recovery"], optional = true } sp-crypto-hashing = { path = "../crypto/hashing", default-features = false, optional = true } sp-runtime-interface = { path = "../runtime-interface", default-features = false } +# k256 crate, better portability, intended to be used in substrate-runtimes (no-std) +k256 = { version = "0.13.3", features = ["alloc", "ecdsa"], default-features = false } +# secp256k1 crate, better performance, intended to be used on host side (std) +secp256k1 = { version = "0.28.0", default-features = false, features = ["alloc", "recovery"], optional = true } # bls crypto w3f-bls = { version = "0.1.3", default-features = false, optional = true } @@ -76,6 +79,7 @@ bench = false [features] default = ["std"] + std = [ "array-bytes", "bandersnatch_vrfs?/std", @@ -94,6 +98,7 @@ std = [ "hash256-std-hasher/std", "impl-serde/std", "itertools", + "k256/std", "libsecp256k1/std", "log/std", "merlin/std", @@ -132,6 +137,7 @@ serde = [ "bs58/alloc", "dep:serde", "impl-serde", + "k256/serde", "primitive-types/serde_no_std", "scale-info/serde", "secrecy/alloc", @@ -147,7 +153,6 @@ full_crypto = [ "blake2", "ed25519-zebra", "libsecp256k1", - "secp256k1", "sp-crypto-hashing", "sp-runtime-interface/disable_target_static_assertions", ] diff --git a/substrate/primitives/core/src/ecdsa.rs b/substrate/primitives/core/src/ecdsa.rs index f172b3a7d02..e6bd2c7eb57 100644 --- a/substrate/primitives/core/src/ecdsa.rs +++ b/substrate/primitives/core/src/ecdsa.rs @@ -28,14 +28,15 @@ use crate::crypto::{ }; #[cfg(feature = "full_crypto")] use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; -#[cfg(all(feature = "full_crypto", not(feature = "std")))] -use secp256k1::Secp256k1; -#[cfg(feature = "std")] -use secp256k1::SECP256K1; -#[cfg(feature = "full_crypto")] + +#[cfg(all(not(feature = "std"), feature = "full_crypto"))] +use k256::ecdsa::SigningKey as SecretKey; +#[cfg(not(feature = "std"))] +use k256::ecdsa::VerifyingKey; +#[cfg(all(feature = "std", feature = "full_crypto"))] use secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, - Message, PublicKey, SecretKey, + Message, PublicKey, SecretKey, SECP256K1, }; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -53,9 +54,9 @@ pub const PUBLIC_KEY_SERIALIZED_SIZE: usize = 33; /// The byte length of signature pub const SIGNATURE_SERIALIZED_SIZE: usize = 65; -/// A secret seed (which is bytewise essentially equivalent to a SecretKey). +/// The secret seed. /// -/// We need it as a different type because `Seed` is expected to be AsRef<[u8]>. +/// The raw secret seed, which can be used to create the `Pair`. #[cfg(feature = "full_crypto")] type Seed = [u8; 32]; @@ -96,18 +97,21 @@ impl Public { /// Create a new instance from the given full public key. /// /// This will convert the full public key into the compressed format. - #[cfg(feature = "std")] pub fn from_full(full: &[u8]) -> Result { - let pubkey = if full.len() == 64 { + let mut tagged_full = [0u8; 65]; + let full = if full.len() == 64 { // Tag it as uncompressed public key. - let mut tagged_full = [0u8; 65]; tagged_full[0] = 0x04; tagged_full[1..].copy_from_slice(full); - secp256k1::PublicKey::from_slice(&tagged_full) + &tagged_full } else { - secp256k1::PublicKey::from_slice(full) + full }; - pubkey.map(|k| Self(k.serialize())).map_err(|_| ()) + #[cfg(feature = "std")] + let pubkey = PublicKey::from_slice(&full); + #[cfg(not(feature = "std"))] + let pubkey = VerifyingKey::from_sec1_bytes(&full); + pubkey.map(|k| k.into()).map_err(|_| ()) } } @@ -131,6 +135,24 @@ impl AsMut<[u8]> for Public { } } +#[cfg(feature = "std")] +impl From for Public { + fn from(pubkey: PublicKey) -> Self { + Self(pubkey.serialize()) + } +} + +#[cfg(not(feature = "std"))] +impl From for Public { + fn from(pubkey: VerifyingKey) -> Self { + Self::unchecked_from( + pubkey.to_sec1_bytes()[..] + .try_into() + .expect("valid key is serializable to [u8,33]. qed."), + ) + } +} + impl TryFrom<&[u8]> for Public { type Error = (); @@ -331,23 +353,34 @@ impl Signature { /// Recover the public key from this signature and a pre-hashed message. #[cfg(feature = "full_crypto")] pub fn recover_prehashed(&self, message: &[u8; 32]) -> Option { - let rid = RecoveryId::from_i32(self.0[64] as i32).ok()?; - let sig = RecoverableSignature::from_compact(&self.0[..64], rid).ok()?; - let message = Message::from_digest_slice(message).expect("Message is 32 bytes; qed"); - #[cfg(feature = "std")] - let context = SECP256K1; + { + let rid = RecoveryId::from_i32(self.0[64] as i32).ok()?; + let sig = RecoverableSignature::from_compact(&self.0[..64], rid).ok()?; + let message = Message::from_digest_slice(message).expect("Message is 32 bytes; qed"); + SECP256K1.recover_ecdsa(&message, &sig).ok().map(Public::from) + } + #[cfg(not(feature = "std"))] - let context = Secp256k1::verification_only(); + { + let rid = k256::ecdsa::RecoveryId::from_byte(self.0[64])?; + let sig = k256::ecdsa::Signature::from_bytes((&self.0[..64]).into()).ok()?; + VerifyingKey::recover_from_prehash(message, &sig, rid).map(Public::from).ok() + } + } +} - context - .recover_ecdsa(&message, &sig) - .ok() - .map(|pubkey| Public(pubkey.serialize())) +#[cfg(not(feature = "std"))] +impl From<(k256::ecdsa::Signature, k256::ecdsa::RecoveryId)> for Signature { + fn from(recsig: (k256::ecdsa::Signature, k256::ecdsa::RecoveryId)) -> Signature { + let mut r = Self::default(); + r.0[..64].copy_from_slice(&recsig.0.to_bytes()); + r.0[64] = recsig.1.to_byte(); + r } } -#[cfg(feature = "full_crypto")] +#[cfg(all(feature = "std", feature = "full_crypto"))] impl From for Signature { fn from(recsig: RecoverableSignature) -> Signature { let mut r = Self::default(); @@ -384,17 +417,19 @@ impl TraitPair for Pair { /// /// You should never need to use this; generate(), generate_with_phrase fn from_seed_slice(seed_slice: &[u8]) -> Result { - let secret = - SecretKey::from_slice(seed_slice).map_err(|_| SecretStringError::InvalidSeedLength)?; - #[cfg(feature = "std")] - let context = SECP256K1; - #[cfg(not(feature = "std"))] - let context = Secp256k1::signing_only(); + { + let secret = SecretKey::from_slice(seed_slice) + .map_err(|_| SecretStringError::InvalidSeedLength)?; + Ok(Pair { public: PublicKey::from_secret_key(&SECP256K1, &secret).into(), secret }) + } - let public = PublicKey::from_secret_key(&context, &secret); - let public = Public(public.serialize()); - Ok(Pair { public, secret }) + #[cfg(not(feature = "std"))] + { + let secret = SecretKey::from_slice(seed_slice) + .map_err(|_| SecretStringError::InvalidSeedLength)?; + Ok(Pair { public: VerifyingKey::from(&secret).into(), secret }) + } } /// Derive a child key from a series of given junctions. @@ -438,7 +473,14 @@ impl TraitPair for Pair { impl Pair { /// Get the seed for this key. pub fn seed(&self) -> Seed { - self.secret.secret_bytes() + #[cfg(feature = "std")] + { + self.secret.secret_bytes() + } + #[cfg(not(feature = "std"))] + { + self.secret.to_bytes().into() + } } /// Exactly as `from_string` except that if no matches are found then, the the first 32 @@ -455,14 +497,19 @@ impl Pair { /// Sign a pre-hashed message pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature { - let message = Message::from_digest_slice(message).expect("Message is 32 bytes; qed"); - #[cfg(feature = "std")] - let context = SECP256K1; - #[cfg(not(feature = "std"))] - let context = Secp256k1::signing_only(); + { + let message = Message::from_digest_slice(message).expect("Message is 32 bytes; qed"); + SECP256K1.sign_ecdsa_recoverable(&message, &self.secret).into() + } - context.sign_ecdsa_recoverable(&message, &self.secret).into() + #[cfg(not(feature = "std"))] + { + self.secret + .sign_prehash_recoverable(message) + .expect("signing may not fail (???). qed.") + .into() + } } /// Verify a signature on a pre-hashed message. Return `true` if the signature is valid @@ -503,7 +550,7 @@ impl Pair { // NOTE: this solution is not effective when `Pair` is moved around memory. // The very same problem affects other cryptographic backends that are just using // `zeroize`for their secrets. -#[cfg(feature = "full_crypto")] +#[cfg(all(feature = "std", feature = "full_crypto"))] impl Drop for Pair { fn drop(&mut self) { self.secret.non_secure_erase() @@ -770,8 +817,18 @@ mod test { let msg = [0u8; 32]; let sig1 = pair.sign_prehashed(&msg); let sig2: Signature = { - let message = Message::from_digest_slice(&msg).unwrap(); - SECP256K1.sign_ecdsa_recoverable(&message, &pair.secret).into() + #[cfg(feature = "std")] + { + let message = Message::from_digest_slice(&msg).unwrap(); + SECP256K1.sign_ecdsa_recoverable(&message, &pair.secret).into() + } + #[cfg(not(feature = "std"))] + { + pair.secret + .sign_prehash_recoverable(&msg) + .expect("signing may not fail (???). qed.") + .into() + } }; assert_eq!(sig1, sig2); -- GitLab From 1c435e91c117b877c803427a91c0ccd18c527382 Mon Sep 17 00:00:00 2001 From: Viki Val Date: Sat, 9 Mar 2024 07:32:53 -0800 Subject: [PATCH 098/188] :bug: Depositing PalletAttributeSet on incorrect nft (#2740) ## Context Implementing `HolderOf(collection_id)` we have observed a fancy glitch where pallet deposits event with incorrect values ### Test case [Observe following extrinsic](https://assethub-polkadot.subscan.io/extrinsic/0xdc72321b7674aa209c2f194ed49bd6bd12708af103f98b5b9196e0132dcba777) To mint in collection `51` user needs to be `HolderOf(50)`. Therefore current user is owner of item `394` `witness_data { owned_item: 394 }` All checking is done correctly, storage is updated correctly ![photo_2023-12-18 16 07 11](https://github.com/paritytech/polkadot-sdk/assets/22471030/ca991272-156d-4db1-97b2-1a2873fc5d3f) However the event which is emitted does not make semantic sense as we updated storage for `50-394` not for `51-114` ![photo_2023-12-18 16 07 17](https://github.com/paritytech/polkadot-sdk/assets/22471030/c998a92c-e306-4433-aad8-103078140e23) ## The fix This PR fixes that depositing `PalletAttributeSet` emits correct values. --------- Co-authored-by: Jegor Sidorenko Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> --- substrate/frame/nfts/src/lib.rs | 4 ++-- substrate/frame/nfts/src/tests.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/substrate/frame/nfts/src/lib.rs b/substrate/frame/nfts/src/lib.rs index 7cf7cdc61a7..615720268fe 100644 --- a/substrate/frame/nfts/src/lib.rs +++ b/substrate/frame/nfts/src/lib.rs @@ -874,8 +874,8 @@ pub mod pallet { ), ); Self::deposit_event(Event::PalletAttributeSet { - collection, - item: Some(item), + collection: collection_id, + item: Some(owned_item), attribute: pallet_attribute, value: attribute_value, }); diff --git a/substrate/frame/nfts/src/tests.rs b/substrate/frame/nfts/src/tests.rs index 9e521537534..6bf9427f4e6 100644 --- a/substrate/frame/nfts/src/tests.rs +++ b/substrate/frame/nfts/src/tests.rs @@ -440,6 +440,12 @@ fn mint_should_work() { account(2), Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); + assert!(events().contains(&Event::::PalletAttributeSet { + collection: 0, + item: Some(43), + attribute: PalletAttributes::<::CollectionId>::UsedToClaim(1), + value: Nfts::construct_attribute_value(vec![]).unwrap(), + })); // can't mint twice assert_noop!( -- GitLab From bbaa5a3bb5451fc0c51fd42fd91d765f5589c033 Mon Sep 17 00:00:00 2001 From: Muharem Date: Sun, 10 Mar 2024 22:24:41 +0100 Subject: [PATCH 099/188] Asset Conversion: doc guide to address incorrect exchange rate for non-withdrawable pool (#3275) This documentation guide to address an incorrect exchange rate for a non-withdrawable pool. --- substrate/frame/asset-conversion/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/substrate/frame/asset-conversion/src/lib.rs b/substrate/frame/asset-conversion/src/lib.rs index f13d40d3e7e..c9725f9d39d 100644 --- a/substrate/frame/asset-conversion/src/lib.rs +++ b/substrate/frame/asset-conversion/src/lib.rs @@ -413,6 +413,11 @@ pub mod pallet { /// Params `amount1_min`/`amount2_min` represent that. /// `mint_to` will be sent the liquidity tokens that represent this share of the pool. /// + /// NOTE: when encountering an incorrect exchange rate and non-withdrawable pool liquidity, + /// batch an atomic call with [`Pallet::add_liquidity`] and + /// [`Pallet::swap_exact_tokens_for_tokens`] or [`Pallet::swap_tokens_for_exact_tokens`] + /// calls to render the liquidity withdrawable and rectify the exchange rate. + /// /// Once liquidity is added, someone may successfully call /// [`Pallet::swap_exact_tokens_for_tokens`] successfully. #[pallet::call_index(1)] -- GitLab From a6713c55fd5082d333518c3ca13f2a4294726fcc Mon Sep 17 00:00:00 2001 From: Egor_P Date: Mon, 11 Mar 2024 16:37:22 +0700 Subject: [PATCH 100/188] Fix release docker image GHA (#3547) This PR add extra checks for the input fields in the GHA which does the docker image build and publishing. --- .github/scripts/common/lib.sh | 96 ++++++++++++++++++- .../workflows/release-50_publish-docker.yml | 16 +++- .../workflows/release-99_notif-published.yml | 10 +- 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/.github/scripts/common/lib.sh b/.github/scripts/common/lib.sh index bd12d9c6e6f..29dc269ffd2 100755 --- a/.github/scripts/common/lib.sh +++ b/.github/scripts/common/lib.sh @@ -237,6 +237,61 @@ fetch_release_artifacts() { popd > /dev/null } +# Fetch the release artifacts like binary and sigantures from S3. Assumes the ENV are set: +# - RELEASE_ID +# - GITHUB_TOKEN +# - REPO in the form paritytech/polkadot +fetch_release_artifacts_from_s3() { + echo "Version : $VERSION" + echo "Repo : $REPO" + echo "Binary : $BINARY" + OUTPUT_DIR=${OUTPUT_DIR:-"./release-artifacts/${BINARY}"} + echo "OUTPUT_DIR : $OUTPUT_DIR" + + URL_BASE=$(get_s3_url_base $BINARY) + echo "URL_BASE=$URL_BASE" + + URL_BINARY=$URL_BASE/$VERSION/$BINARY + URL_SHA=$URL_BASE/$VERSION/$BINARY.sha256 + URL_ASC=$URL_BASE/$VERSION/$BINARY.asc + + # Fetch artifacts + mkdir -p "$OUTPUT_DIR" + pushd "$OUTPUT_DIR" > /dev/null + + echo "Fetching artifacts..." + for URL in $URL_BINARY $URL_SHA $URL_ASC; do + echo "Fetching %s" "$URL" + curl --progress-bar -LO "$URL" || echo "Missing $URL" + done + + pwd + ls -al --color + popd > /dev/null + +} + +# Pass the name of the binary as input, it will +# return the s3 base url +function get_s3_url_base() { + name=$1 + case $name in + polkadot | polkadot-execute-worker | polkadot-prepare-worker | staking-miner) + printf "https://releases.parity.io/polkadot" + ;; + + polkadot-parachain) + printf "https://releases.parity.io/cumulus" + ;; + + *) + printf "UNSUPPORTED BINARY $name" + exit 1 + ;; + esac +} + + # Check the checksum for a given binary function check_sha256() { echo "Checking SHA256 for $1" @@ -248,13 +303,11 @@ function check_sha256() { function import_gpg_keys() { GPG_KEYSERVER=${GPG_KEYSERVER:-"keyserver.ubuntu.com"} SEC="9D4B2B6EB8F97156D19669A9FF0812D491B96798" - WILL="2835EAF92072BC01D188AF2C4A092B93E97CE1E2" EGOR="E6FC4D4782EB0FA64A4903CCDB7D3555DD3932D3" - MARA="533C920F40E73A21EEB7E9EBF27AEA7E7594C9CF" MORGAN="2E92A9D8B15D7891363D1AE8AF9E6C43F7F8C4CF" echo "Importing GPG keys from $GPG_KEYSERVER in parallel" - for key in $SEC $WILL $EGOR $MARA $MORGAN; do + for key in $SEC $EGOR $MORGAN; do ( echo "Importing GPG key $key" gpg --no-tty --quiet --keyserver $GPG_KEYSERVER --recv-keys $key @@ -344,3 +397,40 @@ function find_runtimes() { done echo $JSON } + +# Filter the version matches the particular pattern and return it. +# input: version (v1.8.0 or v1.8.0-rc1) +# output: none +filter_version_from_input() { + version=$1 + regex="(^v[0-9]+\.[0-9]+\.[0-9]+)$|(^v[0-9]+\.[0-9]+\.[0-9]+-rc[0-9]+)$" + + if [[ $version =~ $regex ]]; then + if [ -n "${BASH_REMATCH[1]}" ]; then + echo "${BASH_REMATCH[1]}" + elif [ -n "${BASH_REMATCH[2]}" ]; then + echo "${BASH_REMATCH[2]}" + fi + else + echo "Invalid version: $version" + exit 1 + fi + +} + +# Check if the release_id is valid number +# input: release_id +# output: release_id or exit 1 +check_release_id() { + input=$1 + + release_id=$(echo "$input" | sed 's/[^0-9]//g') + + if [[ $release_id =~ ^[0-9]+$ ]]; then + echo "$release_id" + else + echo "Invalid release_id from input: $input" + exit 1 + fi + +} diff --git a/.github/workflows/release-50_publish-docker.yml b/.github/workflows/release-50_publish-docker.yml index ecbac01cd3a..67e93ee9657 100644 --- a/.github/workflows/release-50_publish-docker.yml +++ b/.github/workflows/release-50_publish-docker.yml @@ -36,7 +36,7 @@ on: -H "Authorization: Bearer ${GITHUB_TOKEN}" https://api.github.com/repos/$OWNER/$REPO/releases | \ jq '.[] | { name: .name, id: .id }' required: true - type: string + type: number registry: description: Container registry @@ -61,7 +61,6 @@ permissions: contents: write env: - RELEASE_ID: ${{ inputs.release_id }} ENGINE: docker REGISTRY: ${{ inputs.registry }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -71,6 +70,7 @@ env: # EVENT_ACTION: ${{ github.event.action }} EVENT_NAME: ${{ github.event_name }} IMAGE_TYPE: ${{ inputs.image_type }} + VERSION: ${{ inputs.version }} jobs: fetch-artifacts: # this job will be triggered for the polkadot-parachain rc and release or polkadot rc image build @@ -95,13 +95,16 @@ jobs: # chmod a+x $BINARY # ls -al - - name: Fetch rc artifacts or release artifacts based on release id + - name: Fetch rc artifacts or release artifacts from s3 based on version #this step runs only if the workflow is triggered manually if: ${{ env.EVENT_NAME == 'workflow_dispatch' }} run: | . ./.github/scripts/common/lib.sh - fetch_release_artifacts + VERSION=$(filter_version_from_input "${{ inputs.version }}") + echo "VERSION=${VERSION}" >> $GITHUB_ENV + + fetch_release_artifacts_from_s3 - name: Cache the artifacts uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 @@ -147,7 +150,10 @@ jobs: if: ${{ env.IMAGE_TYPE == 'rc' }} id: fetch_rc_refs run: | - release=release-${{ inputs.release_id }} && \ + . ./.github/scripts/common/lib.sh + + RELEASE_ID=$(check_release_id "${{ inputs.release_id }}") + release=release-$RELEASE_ID && \ echo "release=${release}" >> $GITHUB_OUTPUT commit=$(git rev-parse --short HEAD) && \ diff --git a/.github/workflows/release-99_notif-published.yml b/.github/workflows/release-99_notif-published.yml index 732db15d9c0..05c9d6a47f5 100644 --- a/.github/workflows/release-99_notif-published.yml +++ b/.github/workflows/release-99_notif-published.yml @@ -16,12 +16,6 @@ jobs: - name: "RelEng: Polkadot Release Coordination" room: '!cqAmzdIcbOFwrdrubV:parity.io' pre-release: true - - name: 'General: Rust, Polkadot, Substrate' - room: '!aJymqQYtCjjqImFLSb:parity.io' - pre-release: false - - name: 'Team: DevOps' - room: '!lUslSijLMgNcEKcAiE:parity.io' - pre-release: true # External - name: 'Ledger <> Polkadot Coordination' @@ -48,7 +42,9 @@ jobs: access_token: ${{ secrets.RELEASENOTES_MATRIX_V2_ACCESS_TOKEN }} server: m.parity.io message: | - A (pre)release has been ${{github.event.action}} in **${{github.event.repository.full_name}}:**
+ @room + + A new node release has been ${{github.event.action}} in **${{github.event.repository.full_name}}:**
Release version: [${{github.event.release.tag_name}}](${{github.event.release.html_url}}) ----- -- GitLab From 8dc6048d5eb20886f5d0781d54e073441d3bd86c Mon Sep 17 00:00:00 2001 From: eskimor Date: Mon, 11 Mar 2024 15:11:55 +0100 Subject: [PATCH 101/188] Remove unused FullCandidateReceipt (#3641) Currently redesigning candidate data structures, noticed that this one seems dead. Co-authored-by: eskimor --- polkadot/primitives/src/v6/mod.rs | 12 --------- .../implementers-guide/src/types/README.md | 11 -------- .../implementers-guide/src/types/candidate.md | 26 ++----------------- 3 files changed, 2 insertions(+), 47 deletions(-) diff --git a/polkadot/primitives/src/v6/mod.rs b/polkadot/primitives/src/v6/mod.rs index 89431f7801f..cab34deeb50 100644 --- a/polkadot/primitives/src/v6/mod.rs +++ b/polkadot/primitives/src/v6/mod.rs @@ -533,18 +533,6 @@ impl CandidateReceipt { } } -/// All data pertaining to the execution of a para candidate. -#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -pub struct FullCandidateReceipt { - /// The inner candidate receipt. - pub inner: CandidateReceipt, - /// The validation data derived from the relay-chain state at that - /// point. The hash of the persisted validation data should - /// match the `persisted_validation_data_hash` in the descriptor - /// of the receipt. - pub validation_data: PersistedValidationData, -} - /// A candidate-receipt with commitments directly included. #[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Hash))] diff --git a/polkadot/roadmap/implementers-guide/src/types/README.md b/polkadot/roadmap/implementers-guide/src/types/README.md index 87092bf3a00..5fd3050f949 100644 --- a/polkadot/roadmap/implementers-guide/src/types/README.md +++ b/polkadot/roadmap/implementers-guide/src/types/README.md @@ -55,17 +55,6 @@ digraph { CandidateCommitmentsHash [label = "Hash", shape="doublecircle", fill="gray90"] CandidateCommitmentsHash -> CandidateCommitments:name - FullCandidateReceipt [label = < - - - - -
FullCandidateReceipt<H = Hash, N = BlockNumber>
innerCandidateReceipt<H>
validation_dataValidationData<N>
- >] - - FullCandidateReceipt:inner -> CandidateReceipt:name - FullCandidateReceipt:validation_data -> ValidationData:name - CommittedCandidateReceipt [label = < diff --git a/polkadot/roadmap/implementers-guide/src/types/candidate.md b/polkadot/roadmap/implementers-guide/src/types/candidate.md index 00176229e5a..399d7854ac4 100644 --- a/polkadot/roadmap/implementers-guide/src/types/candidate.md +++ b/polkadot/roadmap/implementers-guide/src/types/candidate.md @@ -20,12 +20,8 @@ struct ParaId(u32); ## Candidate Receipt -Much info in a [`FullCandidateReceipt`](#full-candidate-receipt) is duplicated from the relay-chain state. When the -corresponding relay-chain state is considered widely available, the Candidate Receipt should be favored over the -`FullCandidateReceipt`. - -Examples of situations where the state is readily available includes within the scope of work done by subsystems working -on a given relay-parent, or within the logic of the runtime importing a backed candidate. +Compact representation of the result of a validation. This is what validators +receive from collators, together with the PoV. ```rust /// A candidate-receipt. @@ -37,24 +33,6 @@ struct CandidateReceipt { } ``` -## Full Candidate Receipt - -This is the full receipt type. The `PersistedValidationData` are technically redundant with the `inner.relay_parent`, -which uniquely describes the block in the blockchain from whose state these values are derived. The -[`CandidateReceipt`](#candidate-receipt) variant is often used instead for this reason. - -However, the Full Candidate Receipt type is useful as a means of avoiding the implicit dependency on availability of old -blockchain state. In situations such as availability and approval, having the full description of the candidate within a -self-contained struct is convenient. - -```rust -/// All data pertaining to the execution of a para candidate. -struct FullCandidateReceipt { - inner: CandidateReceipt, - validation_data: PeristedValidationData, -} -``` - ## Committed Candidate Receipt This is a variant of the candidate receipt which includes the commitments of the candidate receipt alongside the -- GitLab From aa35328371d967e6af20c03e86db0b6e5c11cdf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=B3nal=20Murray?= Date: Mon, 11 Mar 2024 21:12:27 +0700 Subject: [PATCH 102/188] [pallet_broker] Fix `adapt_price` behaviour at zero (#3636) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the behaviour of `Linear` which is the default implementation of the `AdaptPrice` trait in the broker pallet. Previously if cores were offered but not sold in only one sale, the price would be set to zero and due to the logic being purely multiplicative, the price would stay at 0 indefinitely. This could be further paired with a configurable minimum in the broker pallet itself, which will be a future PR. This affects the Rococo and Westend Coretime chains, but Kusama has a different implementation so this isn't required for the Kusama launch. I actually thought I opened this a while ago. --------- Co-authored-by: Bastian Köcher --- prdoc/pr_3636.prdoc | 15 +++++++++ substrate/frame/broker/src/adapt_price.rs | 38 ++++++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 prdoc/pr_3636.prdoc diff --git a/prdoc/pr_3636.prdoc b/prdoc/pr_3636.prdoc new file mode 100644 index 00000000000..934158ac102 --- /dev/null +++ b/prdoc/pr_3636.prdoc @@ -0,0 +1,15 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "[pallet_broker] Fix `Linear::adapt_price` behavior at zero" + +doc: + - audience: Runtime Dev + description: | + This fixes the behaviour of `Linear` which is the default implementation of the `AdaptPrice` + trait in the broker pallet. Previously if cores were offered but not sold in only one sale, + the price would be set to zero and due to the logic being purely multiplicative, the price + would stay at 0 indefinitely. + +crates: + - name: pallet-broker diff --git a/substrate/frame/broker/src/adapt_price.rs b/substrate/frame/broker/src/adapt_price.rs index 8266625687a..fbcd7afdf0d 100644 --- a/substrate/frame/broker/src/adapt_price.rs +++ b/substrate/frame/broker/src/adapt_price.rs @@ -19,6 +19,7 @@ use crate::CoreIndex; use sp_arithmetic::{traits::One, FixedU64}; +use sp_runtime::Saturating; /// Type for determining how to set price. pub trait AdaptPrice { @@ -49,14 +50,24 @@ impl AdaptPrice for () { pub struct Linear; impl AdaptPrice for Linear { fn leadin_factor_at(when: FixedU64) -> FixedU64 { - FixedU64::from(2) - when + FixedU64::from(2).saturating_sub(when) } fn adapt_price(sold: CoreIndex, target: CoreIndex, limit: CoreIndex) -> FixedU64 { if sold <= target { - FixedU64::from_rational(sold.into(), target.into()) + // Range of [0.5, 1.0]. + FixedU64::from_rational(1, 2).saturating_add(FixedU64::from_rational( + sold.into(), + target.saturating_mul(2).into(), + )) } else { - FixedU64::one() + - FixedU64::from_rational((sold - target).into(), (limit - target).into()) + // Range of (1.0, 2]. + + // Unchecked math: In this branch we know that sold > target. The limit must be >= sold + // by construction, and thus target must be < limit. + FixedU64::one().saturating_add(FixedU64::from_rational( + (sold - target).into(), + (limit - target).into(), + )) } } } @@ -81,4 +92,23 @@ mod tests { } } } + + #[test] + fn linear_bound_check() { + // Using constraints from pallet implementation i.e. `limit >= sold`. + // Check extremes + let limit = 10; + let target = 5; + + // Maximally sold: `sold == limit` + assert_eq!(Linear::adapt_price(limit, target, limit), FixedU64::from_float(2.0)); + // Ideally sold: `sold == target` + assert_eq!(Linear::adapt_price(target, target, limit), FixedU64::one()); + // Minimally sold: `sold == 0` + assert_eq!(Linear::adapt_price(0, target, limit), FixedU64::from_float(0.5)); + // Optimistic target: `target == limit` + assert_eq!(Linear::adapt_price(limit, limit, limit), FixedU64::one()); + // Pessimistic target: `target == 0` + assert_eq!(Linear::adapt_price(limit, 0, limit), FixedU64::from_float(2.0)); + } } -- GitLab From 4249a3d6cbca1da2ee15237c05691005973502e9 Mon Sep 17 00:00:00 2001 From: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:38:44 +0100 Subject: [PATCH 103/188] Remove getters from `im-online` pallet (#3589) As I've been dancing around this pallet for quite some time anyway, I decided to remove getters at once. There were only a few leftovers in tests. Related: #3326 CC @muraca --- prdoc/pr_3589.prdoc | 10 ++++++++++ substrate/frame/im-online/src/lib.rs | 12 ++++-------- substrate/frame/im-online/src/tests.rs | 9 +++------ 3 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 prdoc/pr_3589.prdoc diff --git a/prdoc/pr_3589.prdoc b/prdoc/pr_3589.prdoc new file mode 100644 index 00000000000..98b9b1039ab --- /dev/null +++ b/prdoc/pr_3589.prdoc @@ -0,0 +1,10 @@ +title: Removed `pallet::getter` usage from `pallet-im-online` + +doc: + - audience: Runtime Dev + description: | + This PR removes `pallet::getter` usage from `pallet-im-online`, and updates dependant code accordingly. + The syntax `StorageItem::::get()` should be used instead. + +crates: + - name: pallet-im-online diff --git a/substrate/frame/im-online/src/lib.rs b/substrate/frame/im-online/src/lib.rs index f14093aa09a..239b47834d1 100644 --- a/substrate/frame/im-online/src/lib.rs +++ b/substrate/frame/im-online/src/lib.rs @@ -338,26 +338,22 @@ pub mod pallet { /// progress estimate from `NextSessionRotation`, as those estimates should be /// more accurate then the value we calculate for `HeartbeatAfter`. #[pallet::storage] - #[pallet::getter(fn heartbeat_after)] - pub(super) type HeartbeatAfter = StorageValue<_, BlockNumberFor, ValueQuery>; + pub type HeartbeatAfter = StorageValue<_, BlockNumberFor, ValueQuery>; /// The current set of keys that may issue a heartbeat. #[pallet::storage] - #[pallet::getter(fn keys)] - pub(super) type Keys = + pub type Keys = StorageValue<_, WeakBoundedVec, ValueQuery>; /// For each session index, we keep a mapping of `SessionIndex` and `AuthIndex`. #[pallet::storage] - #[pallet::getter(fn received_heartbeats)] - pub(super) type ReceivedHeartbeats = + pub type ReceivedHeartbeats = StorageDoubleMap<_, Twox64Concat, SessionIndex, Twox64Concat, AuthIndex, bool>; /// For each session index, we keep a mapping of `ValidatorId` to the /// number of blocks authored by the given authority. #[pallet::storage] - #[pallet::getter(fn authored_blocks)] - pub(super) type AuthoredBlocks = StorageDoubleMap< + pub type AuthoredBlocks = StorageDoubleMap< _, Twox64Concat, SessionIndex, diff --git a/substrate/frame/im-online/src/tests.rs b/substrate/frame/im-online/src/tests.rs index 7efca926eb0..6f5a14d7e7f 100644 --- a/substrate/frame/im-online/src/tests.rs +++ b/substrate/frame/im-online/src/tests.rs @@ -26,10 +26,7 @@ use sp_core::offchain::{ testing::{TestOffchainExt, TestTransactionPoolExt}, OffchainDbExt, OffchainWorkerExt, TransactionPoolExt, }; -use sp_runtime::{ - testing::UintAuthorityId, - transaction_validity::{InvalidTransaction, TransactionValidityError}, -}; +use sp_runtime::testing::UintAuthorityId; #[test] fn test_unresponsiveness_slash_fraction() { @@ -267,14 +264,14 @@ fn should_cleanup_received_heartbeats_on_session_end() { let _ = heartbeat(1, 2, 0, 1.into(), Session::validators()).unwrap(); // the heartbeat is stored - assert!(!ImOnline::received_heartbeats(&2, &0).is_none()); + assert!(!super::pallet::ReceivedHeartbeats::::get(2, 0).is_none()); advance_session(); // after the session has ended we have already processed the heartbeat // message, so any messages received on the previous session should have // been pruned. - assert!(ImOnline::received_heartbeats(&2, &0).is_none()); + assert!(super::pallet::ReceivedHeartbeats::::get(2, 0).is_none()); }); } -- GitLab From 02f1f2c47609483be04097e27fc52c06883a6540 Mon Sep 17 00:00:00 2001 From: Tsvetomir Dimitrov Date: Mon, 11 Mar 2024 18:00:52 +0200 Subject: [PATCH 104/188] Small fixes in para-scheduler pallet (#3524) Fixes some typos, outdated comments and test asserts. Also uses safe math and `defensive` for arithmetic operations. --- polkadot/runtime/parachains/src/scheduler.rs | 23 ++++++++++++------- .../runtime/parachains/src/scheduler/tests.rs | 11 +++++---- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/polkadot/runtime/parachains/src/scheduler.rs b/polkadot/runtime/parachains/src/scheduler.rs index 61ab36dbe96..f231864a85e 100644 --- a/polkadot/runtime/parachains/src/scheduler.rs +++ b/polkadot/runtime/parachains/src/scheduler.rs @@ -37,7 +37,7 @@ //! availability cores over time. use crate::{configuration, initializer::SessionChangeNotification, paras}; -use frame_support::pallet_prelude::*; +use frame_support::{pallet_prelude::*, traits::Defensive}; use frame_system::pallet_prelude::BlockNumberFor; pub use polkadot_core_primitives::v2::BlockNumber; use primitives::{ @@ -59,6 +59,7 @@ pub use pallet::*; mod tests; const LOG_TARGET: &str = "runtime::parachains::scheduler"; + pub mod migration; #[frame_support::pallet] @@ -88,10 +89,8 @@ pub mod pallet { #[pallet::getter(fn validator_groups)] pub(crate) type ValidatorGroups = StorageValue<_, Vec>, ValueQuery>; - /// One entry for each availability core. Entries are `None` if the core is not currently - /// occupied. Can be temporarily `Some` if scheduled but not occupied. - /// The i'th parachain belongs to the i'th core, with the remaining cores all being - /// parathread-multiplexers. + /// One entry for each availability core. The i'th parachain belongs to the i'th core, with the + /// remaining cores all being on demand parachain multiplexers. /// /// Bounded by the maximum of either of these two values: /// * The number of parachains and parathread multiplexers @@ -146,7 +145,7 @@ pub mod pallet { /// One entry for each availability core. The `VecDeque` represents the assignments to be /// scheduled on that core. The value contained here will not be valid after the end of - /// a block. Runtime APIs should be used to determine scheduled cores/ for the upcoming block. + /// a block. Runtime APIs should be used to determine scheduled cores for the upcoming block. #[pallet::storage] #[pallet::getter(fn claimqueue)] pub(crate) type ClaimQueue = @@ -236,8 +235,16 @@ impl Pallet { if n_cores == 0 || validators.is_empty() { ValidatorGroups::::set(Vec::new()); } else { - let group_base_size = validators.len() / n_cores as usize; - let n_larger_groups = validators.len() % n_cores as usize; + let group_base_size = validators + .len() + .checked_div(n_cores as usize) + .defensive_proof("n_cores should not be 0") + .unwrap_or(0); + let n_larger_groups = validators + .len() + .checked_rem(n_cores as usize) + .defensive_proof("n_cores should not be 0") + .unwrap_or(0); // Groups contain indices into the validators from the session change notification, // which are already shuffled. diff --git a/polkadot/runtime/parachains/src/scheduler/tests.rs b/polkadot/runtime/parachains/src/scheduler/tests.rs index 28b3a6b4f5d..e6a1e66b3a5 100644 --- a/polkadot/runtime/parachains/src/scheduler/tests.rs +++ b/polkadot/runtime/parachains/src/scheduler/tests.rs @@ -213,6 +213,7 @@ fn claimqueue_ttl_drop_fn_works() { // Drop expired claim. Scheduler::drop_expired_claims_from_claimqueue(); + assert!(!claimqueue_contains_para_ids::(vec![para_id])); // Add a claim on core 0 with a ttl == now (17) let paras_entry_non_expired = ParasEntry::new(Assignment::Bulk(para_id), now); @@ -222,7 +223,7 @@ fn claimqueue_ttl_drop_fn_works() { Scheduler::add_to_claimqueue(core_idx, paras_entry_expired.clone()); Scheduler::add_to_claimqueue(core_idx, paras_entry_non_expired.clone()); let cq = Scheduler::claimqueue(); - assert!(cq.get(&core_idx).unwrap().len() == 3); + assert_eq!(cq.get(&core_idx).unwrap().len(), 3); // Add a claim to the test assignment provider. let assignment = Assignment::Bulk(para_id); @@ -234,8 +235,9 @@ fn claimqueue_ttl_drop_fn_works() { let cq = Scheduler::claimqueue(); let cqc = cq.get(&core_idx).unwrap(); - // Same number of claims - assert!(cqc.len() == 3); + // Same number of claims, because a new claim is popped from `MockAssigner` instead of the + // expired one + assert_eq!(cqc.len(), 3); // The first 2 claims in the queue should have a ttl of 17, // being the ones set up prior in this test as claims 1 and 3. @@ -355,14 +357,13 @@ fn fill_claimqueue_fills() { schedule_blank_para(para_b); schedule_blank_para(para_c); - // start a new session to activate, 3 validators for 3 cores. + // start a new session to activate, 2 validators for 2 cores. run_to_block(1, |number| match number { 1 => Some(SessionChangeNotification { new_config: default_config(), validators: vec![ ValidatorId::from(Sr25519Keyring::Alice.public()), ValidatorId::from(Sr25519Keyring::Bob.public()), - ValidatorId::from(Sr25519Keyring::Charlie.public()), ], ..Default::default() }), -- GitLab From 05381afcb2e2015fe7f379ddba7522d595a5e8cc Mon Sep 17 00:00:00 2001 From: Andrei Eres Date: Mon, 11 Mar 2024 17:17:45 +0100 Subject: [PATCH 105/188] subsystem-bench: adjust test config to Kusama (#3583) Fixes https://github.com/paritytech/polkadot-sdk/issues/3528 ```rust latency: mean_latency_ms = 30 // common sense std_dev = 2.0 // common sense n_validators = 300 // max number of validators, from chain config n_cores = 60 // 300/5 max_validators_per_core = 5 // default min_pov_size = 5120 // max max_pov_size = 5120 // max peer_bandwidth = 44040192 // from the Parity's kusama validators bandwidth = 44040192 // from the Parity's kusama validators connectivity = 90 // we need to be connected to 90-95% of peers ``` --- ...ilability-distribution-regression-bench.rs | 19 +++------- .../availability-recovery-regression-bench.rs | 13 +------ .../subsystem-bench/src/lib/configuration.rs | 38 ++++++++++++++----- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs b/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs index f2872f3c72b..7a490d5e47f 100644 --- a/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs +++ b/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs @@ -16,7 +16,7 @@ //! availability-read regression tests //! -//! TODO: Explain the test case after configuration adjusted to Kusama +//! Availability read benchmark based on Kusama parameters and scale. //! //! Subsystems involved: //! - availability-distribution @@ -25,28 +25,19 @@ use polkadot_subsystem_bench::{ availability::{benchmark_availability_write, prepare_test, TestDataAvailability, TestState}, - configuration::{PeerLatency, TestConfiguration}, + configuration::TestConfiguration, usage::BenchmarkUsage, }; const BENCH_COUNT: usize = 3; -const WARM_UP_COUNT: usize = 20; +const WARM_UP_COUNT: usize = 30; const WARM_UP_PRECISION: f64 = 0.01; fn main() -> Result<(), String> { let mut messages = vec![]; - - // TODO: Adjust the test configurations to Kusama values let mut config = TestConfiguration::default(); - config.latency = Some(PeerLatency { mean_latency_ms: 30, std_dev: 2.0 }); - config.n_validators = 1000; - config.n_cores = 200; - config.max_validators_per_core = 5; - config.min_pov_size = 5120; - config.max_pov_size = 5120; - config.peer_bandwidth = 52428800; - config.bandwidth = 52428800; - config.connectivity = 75; + // A single node effort roughly n_cores * needed_approvals / n_validators = 60 * 30 / 300 + config.n_cores = 6; config.num_blocks = 3; config.generate_pov_sizes(); diff --git a/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs b/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs index beb063e7ae0..30cc4d47ecc 100644 --- a/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs +++ b/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs @@ -16,7 +16,7 @@ //! availability-write regression tests //! -//! TODO: Explain the test case after configuration adjusted to Kusama +//! Availability write benchmark based on Kusama parameters and scale. //! //! Subsystems involved: //! - availability-recovery @@ -26,7 +26,7 @@ use polkadot_subsystem_bench::{ benchmark_availability_read, prepare_test, DataAvailabilityReadOptions, TestDataAvailability, TestState, }, - configuration::{PeerLatency, TestConfiguration}, + configuration::TestConfiguration, usage::BenchmarkUsage, }; @@ -37,18 +37,9 @@ const WARM_UP_PRECISION: f64 = 0.01; fn main() -> Result<(), String> { let mut messages = vec![]; - // TODO: Adjust the test configurations to Kusama values let options = DataAvailabilityReadOptions { fetch_from_backers: true }; let mut config = TestConfiguration::default(); - config.latency = Some(PeerLatency { mean_latency_ms: 100, std_dev: 1.0 }); - config.n_validators = 300; - config.n_cores = 20; - config.min_pov_size = 5120; - config.max_pov_size = 5120; - config.peer_bandwidth = 52428800; - config.bandwidth = 52428800; config.num_blocks = 3; - config.connectivity = 90; config.generate_pov_sizes(); warm_up(config.clone(), options.clone())?; diff --git a/polkadot/node/subsystem-bench/src/lib/configuration.rs b/polkadot/node/subsystem-bench/src/lib/configuration.rs index c7693308527..17c81c4fd35 100644 --- a/polkadot/node/subsystem-bench/src/lib/configuration.rs +++ b/polkadot/node/subsystem-bench/src/lib/configuration.rs @@ -35,19 +35,34 @@ pub struct PeerLatency { pub std_dev: f64, } +// Based on Kusama `max_validators` +fn default_n_validators() -> usize { + 300 +} + +// Based on Kusama cores +fn default_n_cores() -> usize { + 60 +} + // Default PoV size in KiB. fn default_pov_size() -> usize { - 5120 + 5 * 1024 } -// Default bandwidth in bytes +// Default bandwidth in bytes, based stats from Kusama validators fn default_bandwidth() -> usize { - 52428800 + 42 * 1024 * 1024 +} + +// Default peer latency +fn default_peer_latency() -> Option { + Some(PeerLatency { mean_latency_ms: 30, std_dev: 2.0 }) } // Default connectivity percentage fn default_connectivity() -> usize { - 100 + 90 } // Default backing group size @@ -63,6 +78,7 @@ fn default_needed_approvals() -> usize { fn default_zeroth_delay_tranche_width() -> usize { 0 } + fn default_relay_vrf_modulo_samples() -> usize { 6 } @@ -78,8 +94,10 @@ fn default_no_show_slots() -> usize { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct TestConfiguration { /// Number of validators + #[serde(default = "default_n_validators")] pub n_validators: usize, /// Number of cores + #[serde(default = "default_n_cores")] pub n_cores: usize, /// The number of needed votes to approve a candidate. #[serde(default = "default_needed_approvals")] @@ -111,10 +129,10 @@ pub struct TestConfiguration { #[serde(default = "default_bandwidth")] pub bandwidth: usize, /// Optional peer emulation latency (round trip time) wrt node under test - #[serde(default)] + #[serde(default = "default_peer_latency")] pub latency: Option, - /// Connectivity ratio, the percentage of peers we are not connected to, but ar part of - /// the topology. + /// Connectivity ratio, the percentage of peers we are connected to, but as part of the + /// topology. #[serde(default = "default_connectivity")] pub connectivity: usize, /// Number of blocks to run the test for @@ -124,8 +142,8 @@ pub struct TestConfiguration { impl Default for TestConfiguration { fn default() -> Self { Self { - n_validators: Default::default(), - n_cores: Default::default(), + n_validators: default_n_validators(), + n_cores: default_n_cores(), needed_approvals: default_needed_approvals(), zeroth_delay_tranche_width: default_zeroth_delay_tranche_width(), relay_vrf_modulo_samples: default_relay_vrf_modulo_samples(), @@ -137,7 +155,7 @@ impl Default for TestConfiguration { pov_sizes: Default::default(), peer_bandwidth: default_bandwidth(), bandwidth: default_bandwidth(), - latency: Default::default(), + latency: default_peer_latency(), connectivity: default_connectivity(), num_blocks: Default::default(), } -- GitLab From d3f81056ad1054731e711f2761673ef72686697f Mon Sep 17 00:00:00 2001 From: philoniare Date: Tue, 12 Mar 2024 04:39:21 +0800 Subject: [PATCH 106/188] [Deprecation] Remove the deprecated Store trait (#3532) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description *Removes the deprecated `trait Store` feature from the code base* Fixes #222 --------- Co-authored-by: Dónal Murray --- prdoc/pr_3532.prdoc | 15 +++++ substrate/frame/support/procedural/src/lib.rs | 10 --- .../procedural/src/pallet/expand/mod.rs | 3 - .../src/pallet/expand/store_trait.rs | 67 ------------------- .../procedural/src/pallet/parse/mod.rs | 2 - .../src/pallet/parse/pallet_struct.rs | 26 +------ substrate/frame/support/src/lib.rs | 24 +------ .../tests/pallet_ui/deprecated_store_attr.rs | 28 -------- .../pallet_ui/deprecated_store_attr.stderr | 10 --- .../tests/pallet_ui/duplicate_store_attr.rs | 42 ------------ .../pallet_ui/duplicate_store_attr.stderr | 5 -- .../pallet_struct_invalid_attr.stderr | 2 +- .../pallet_ui/store_trait_leak_private.rs | 42 ------------ .../pallet_ui/store_trait_leak_private.stderr | 19 ------ .../support/test/tests/storage_transaction.rs | 1 - 15 files changed, 20 insertions(+), 276 deletions(-) create mode 100644 prdoc/pr_3532.prdoc delete mode 100644 substrate/frame/support/procedural/src/pallet/expand/store_trait.rs delete mode 100644 substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.rs delete mode 100644 substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.stderr delete mode 100644 substrate/frame/support/test/tests/pallet_ui/duplicate_store_attr.rs delete mode 100644 substrate/frame/support/test/tests/pallet_ui/duplicate_store_attr.stderr delete mode 100644 substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.rs delete mode 100644 substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.stderr diff --git a/prdoc/pr_3532.prdoc b/prdoc/pr_3532.prdoc new file mode 100644 index 00000000000..d47c8d1d491 --- /dev/null +++ b/prdoc/pr_3532.prdoc @@ -0,0 +1,15 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Remove deprecated `trait Store` + +doc: + - audience: Runtime Dev + description: | + The deprecated `trait Store` feature has been removed from the codebase. Please remove usages of `generate_store` + macro from your pallets and access the storage through generics. For example, + `::StoredRange::mutate` will need to be updated to `StoredRange::::mutate`. + +crates: + - name: frame-support + - name: frame \ No newline at end of file diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 036da52a7ba..89e39a5c9bb 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -858,16 +858,6 @@ pub fn disable_frame_system_supertrait_check(_: TokenStream, _: TokenStream) -> pallet_macro_stub() } -/// -/// --- -/// -/// Rust-Analyzer Users: Documentation for this macro can be found at -/// `frame_support::pallet_macros::generate_store`. -#[proc_macro_attribute] -pub fn generate_store(_: TokenStream, _: TokenStream) -> TokenStream { - pallet_macro_stub() -} - /// /// --- /// diff --git a/substrate/frame/support/procedural/src/pallet/expand/mod.rs b/substrate/frame/support/procedural/src/pallet/expand/mod.rs index 3da7d9293c7..067839c2846 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/mod.rs @@ -31,7 +31,6 @@ mod instances; mod origin; mod pallet_struct; mod storage; -mod store_trait; mod tasks; mod tt_default_parts; mod type_value; @@ -68,7 +67,6 @@ pub fn expand(mut def: Def) -> proc_macro2::TokenStream { let storages = storage::expand_storages(&mut def); let inherents = inherent::expand_inherents(&mut def); let instances = instances::expand_instances(&mut def); - let store_trait = store_trait::expand_store_trait(&mut def); let hooks = hooks::expand_hooks(&mut def); let genesis_build = genesis_build::expand_genesis_build(&mut def); let genesis_config = genesis_config::expand_genesis_config(&mut def); @@ -110,7 +108,6 @@ storage item. Otherwise, all storage items are listed among [*Type Definitions*] #storages #inherents #instances - #store_trait #hooks #genesis_build #genesis_config diff --git a/substrate/frame/support/procedural/src/pallet/expand/store_trait.rs b/substrate/frame/support/procedural/src/pallet/expand/store_trait.rs deleted file mode 100644 index 6635adc9881..00000000000 --- a/substrate/frame/support/procedural/src/pallet/expand/store_trait.rs +++ /dev/null @@ -1,67 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -use crate::pallet::Def; -use syn::spanned::Spanned; - -/// If attribute `#[pallet::generate_store(..)]` is defined then: -/// * generate Store trait with all storages, -/// * implement Store trait for Pallet. -pub fn expand_store_trait(def: &mut Def) -> proc_macro2::TokenStream { - let (trait_vis, trait_store, attribute_span) = - if let Some(store) = &def.pallet_struct.store { store } else { return Default::default() }; - - let type_impl_gen = &def.type_impl_generics(trait_store.span()); - let type_use_gen = &def.type_use_generics(trait_store.span()); - let pallet_ident = &def.pallet_struct.pallet; - - let mut where_clauses = vec![&def.config.where_clause]; - where_clauses.extend(def.storages.iter().map(|storage| &storage.where_clause)); - let completed_where_clause = super::merge_where_clauses(&where_clauses); - - let storage_names = &def.storages.iter().map(|storage| &storage.ident).collect::>(); - let storage_cfg_attrs = - &def.storages.iter().map(|storage| &storage.cfg_attrs).collect::>(); - let warnig_struct_name = syn::Ident::new("Store", *attribute_span); - let warning: syn::ItemStruct = syn::parse_quote!( - #[deprecated(note = r" - Use of `#[pallet::generate_store(pub(super) trait Store)]` will be removed after July 2023. - Check https://github.com/paritytech/substrate/pull/13535 for more details.")] - struct #warnig_struct_name; - ); - - quote::quote_spanned!(trait_store.span() => - const _:() = { - #warning - const _: Option<#warnig_struct_name> = None; - }; - #trait_vis trait #trait_store { - #( - #(#storage_cfg_attrs)* - type #storage_names; - )* - } - impl<#type_impl_gen> #trait_store for #pallet_ident<#type_use_gen> - #completed_where_clause - { - #( - #(#storage_cfg_attrs)* - type #storage_names = #storage_names<#type_use_gen>; - )* - } - ) -} diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index e1efdbcc202..b55f130a93a 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -558,8 +558,6 @@ mod keyword { syn::custom_keyword!(validate_unsigned); syn::custom_keyword!(type_value); syn::custom_keyword!(pallet); - syn::custom_keyword!(generate_store); - syn::custom_keyword!(Store); syn::custom_keyword!(extra_constants); syn::custom_keyword!(composite_enum); } diff --git a/substrate/frame/support/procedural/src/pallet/parse/pallet_struct.rs b/substrate/frame/support/procedural/src/pallet/parse/pallet_struct.rs index c2855ae38ef..b645760998f 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/pallet_struct.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/pallet_struct.rs @@ -23,10 +23,8 @@ use syn::spanned::Spanned; mod keyword { syn::custom_keyword!(pallet); syn::custom_keyword!(Pallet); - syn::custom_keyword!(generate_store); syn::custom_keyword!(without_storage_info); syn::custom_keyword!(storage_version); - syn::custom_keyword!(Store); } /// Definition of the pallet pallet. @@ -37,8 +35,6 @@ pub struct PalletStructDef { pub instances: Vec, /// The keyword Pallet used (contains span). pub pallet: keyword::Pallet, - /// Whether the trait `Store` must be generated. - pub store: Option<(syn::Visibility, keyword::Store, proc_macro2::Span)>, /// The span of the pallet::pallet attribute. pub attr_span: proc_macro2::Span, /// Whether to specify the storages max encoded len when implementing `StorageInfoTrait`. @@ -49,11 +45,9 @@ pub struct PalletStructDef { } /// Parse for one variant of: -/// * `#[pallet::generate_store($vis trait Store)]` /// * `#[pallet::without_storage_info]` /// * `#[pallet::storage_version(STORAGE_VERSION)]` pub enum PalletStructAttr { - GenerateStore { span: proc_macro2::Span, vis: syn::Visibility, keyword: keyword::Store }, WithoutStorageInfoTrait(proc_macro2::Span), StorageVersion { storage_version: syn::Path, span: proc_macro2::Span }, } @@ -61,9 +55,7 @@ pub enum PalletStructAttr { impl PalletStructAttr { fn span(&self) -> proc_macro2::Span { match self { - Self::GenerateStore { span, .. } | - Self::WithoutStorageInfoTrait(span) | - Self::StorageVersion { span, .. } => *span, + Self::WithoutStorageInfoTrait(span) | Self::StorageVersion { span, .. } => *span, } } } @@ -77,16 +69,7 @@ impl syn::parse::Parse for PalletStructAttr { content.parse::()?; let lookahead = content.lookahead1(); - if lookahead.peek(keyword::generate_store) { - content.parse::()?; - let generate_content; - syn::parenthesized!(generate_content in content); - let vis = generate_content.parse::()?; - generate_content.parse::()?; - let keyword = generate_content.parse::()?; - let span = content.span(); - Ok(Self::GenerateStore { vis, keyword, span }) - } else if lookahead.peek(keyword::without_storage_info) { + if lookahead.peek(keyword::without_storage_info) { let span = content.parse::()?.span(); Ok(Self::WithoutStorageInfoTrait(span)) } else if lookahead.peek(keyword::storage_version) { @@ -116,16 +99,12 @@ impl PalletStructDef { return Err(syn::Error::new(item.span(), msg)) }; - let mut store = None; let mut without_storage_info = None; let mut storage_version_found = None; let struct_attrs: Vec = helper::take_item_pallet_attrs(&mut item.attrs)?; for attr in struct_attrs { match attr { - PalletStructAttr::GenerateStore { vis, keyword, span } if store.is_none() => { - store = Some((vis, keyword, span)); - }, PalletStructAttr::WithoutStorageInfoTrait(span) if without_storage_info.is_none() => { @@ -162,7 +141,6 @@ impl PalletStructDef { index, instances, pallet, - store, attr_span, without_storage_info, storage_version: storage_version_found, diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 6ea7fa33e77..07560abd935 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -702,7 +702,7 @@ pub use frame_support_procedural::crate_to_crate_version; #[macro_export] macro_rules! fail { ( $y:expr ) => {{ - return Err($y.into()) + return Err($y.into()); }}; } @@ -949,7 +949,7 @@ pub mod pallet_prelude { /// pub trait Config: frame_system::Config {} /// } /// ``` -/// +// /// I.e. a regular struct definition named `Pallet`, with generic T and no where clause. /// /// ## Macro expansion: @@ -1341,26 +1341,6 @@ pub mod pallet_macros { /// See [`pallet::storage`](`frame_support::pallet_macros::storage`) for more info. pub use frame_support_procedural::getter; - /// Allows generating the `Store` trait for all storages. - /// - /// DEPRECATED: Will be removed, do not use. - /// See for more details. - /// - /// To generate a `Store` trait associating all storages, annotate your `Pallet` struct - /// with the attribute `#[pallet::generate_store($vis trait Store)]`, e.g.: - /// - /// ```ignore - /// #[pallet::pallet] - /// #[pallet::generate_store(pub(super) trait Store)] - /// pub struct Pallet(_); - /// ``` - /// More precisely, the `Store` trait contains an associated type for each storage. It is - /// implemented for `Pallet` allowing access to the storage from pallet struct. - /// - /// Thus when defining a storage named `Foo`, it can later be accessed from `Pallet` using - /// `::Foo`. - pub use frame_support_procedural::generate_store; - /// Defines constants that are added to the constant field of /// [`PalletMetadata`](frame_metadata::v15::PalletMetadata) struct for this pallet. /// diff --git a/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.rs b/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.rs deleted file mode 100644 index 72ad7896dfe..00000000000 --- a/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.rs +++ /dev/null @@ -1,28 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -#[frame_support::pallet] -mod pallet { - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::pallet] - #[pallet::generate_store(trait Store)] - pub struct Pallet(core::marker::PhantomData); -} - -fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.stderr b/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.stderr deleted file mode 100644 index e227033d364..00000000000 --- a/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: use of deprecated struct `pallet::_::Store`: - Use of `#[pallet::generate_store(pub(super) trait Store)]` will be removed after July 2023. - Check https://github.com/paritytech/substrate/pull/13535 for more details. - --> tests/pallet_ui/deprecated_store_attr.rs:24:3 - | -24 | #[pallet::generate_store(trait Store)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D deprecated` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(deprecated)]` diff --git a/substrate/frame/support/test/tests/pallet_ui/duplicate_store_attr.rs b/substrate/frame/support/test/tests/pallet_ui/duplicate_store_attr.rs deleted file mode 100644 index 334fd8a46af..00000000000 --- a/substrate/frame/support/test/tests/pallet_ui/duplicate_store_attr.rs +++ /dev/null @@ -1,42 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -#[frame_support::pallet] -mod pallet { - use frame_support::pallet_prelude::Hooks; - use frame_system::pallet_prelude::BlockNumberFor; - use frame_support::pallet_prelude::StorageValue; - - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::pallet] - #[pallet::generate_store(trait Store)] - #[pallet::generate_store(trait Store)] - pub struct Pallet(core::marker::PhantomData); - - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::call] - impl Pallet {} - - #[pallet::storage] - type Foo = StorageValue<_, u8>; -} - -fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/duplicate_store_attr.stderr b/substrate/frame/support/test/tests/pallet_ui/duplicate_store_attr.stderr deleted file mode 100644 index 864b399326e..00000000000 --- a/substrate/frame/support/test/tests/pallet_ui/duplicate_store_attr.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: Unexpected duplicated attribute - --> tests/pallet_ui/duplicate_store_attr.rs:29:3 - | -29 | #[pallet::generate_store(trait Store)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/substrate/frame/support/test/tests/pallet_ui/pallet_struct_invalid_attr.stderr b/substrate/frame/support/test/tests/pallet_ui/pallet_struct_invalid_attr.stderr index 33a2d1da786..6f7f5617f7e 100644 --- a/substrate/frame/support/test/tests/pallet_ui/pallet_struct_invalid_attr.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/pallet_struct_invalid_attr.stderr @@ -1,4 +1,4 @@ -error: expected one of: `generate_store`, `without_storage_info`, `storage_version` +error: expected `without_storage_info` or `storage_version` --> tests/pallet_ui/pallet_struct_invalid_attr.rs:24:12 | 24 | #[pallet::generate_storage_info] // invalid diff --git a/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.rs b/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.rs deleted file mode 100644 index 55dd315fb29..00000000000 --- a/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.rs +++ /dev/null @@ -1,42 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -#[frame_support::pallet] -mod pallet { - use frame_support::pallet_prelude::Hooks; - use frame_system::pallet_prelude::BlockNumberFor; - use frame_support::pallet_prelude::StorageValue; - - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::pallet] - #[pallet::generate_store(pub trait Store)] - pub struct Pallet(core::marker::PhantomData); - - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::call] - impl Pallet {} - - #[pallet::storage] - type Foo = StorageValue<_, u8>; -} - -fn main() { -} diff --git a/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.stderr b/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.stderr deleted file mode 100644 index ccb55122e81..00000000000 --- a/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: use of deprecated struct `pallet::_::Store`: - Use of `#[pallet::generate_store(pub(super) trait Store)]` will be removed after July 2023. - Check https://github.com/paritytech/substrate/pull/13535 for more details. - --> tests/pallet_ui/store_trait_leak_private.rs:28:3 - | -28 | #[pallet::generate_store(pub trait Store)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D deprecated` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(deprecated)]` - -error[E0446]: private type `_GeneratedPrefixForStorageFoo` in public interface - --> tests/pallet_ui/store_trait_leak_private.rs:28:37 - | -28 | #[pallet::generate_store(pub trait Store)] - | ^^^^^ can't leak private type -... -37 | #[pallet::storage] - | ------- `_GeneratedPrefixForStorageFoo` declared as private diff --git a/substrate/frame/support/test/tests/storage_transaction.rs b/substrate/frame/support/test/tests/storage_transaction.rs index c4774330860..f1489a8b0a6 100644 --- a/substrate/frame/support/test/tests/storage_transaction.rs +++ b/substrate/frame/support/test/tests/storage_transaction.rs @@ -41,7 +41,6 @@ pub mod pallet { use frame_system::pallet_prelude::*; #[pallet::pallet] - #[pallet::generate_store(pub (super) trait Store)] pub struct Pallet(_); #[pallet::config] -- GitLab From 7839400f1203b1c1de2ff84db5f5ffcf31e20d87 Mon Sep 17 00:00:00 2001 From: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com> Date: Tue, 12 Mar 2024 00:12:58 +0200 Subject: [PATCH 107/188] [Collator Selection] Fix weight refund for `set_candidacy_bond` (#3643) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #3642 This PR implements the weight refund of `pallet_collator_selection::set_candidacy_bond` to account for no iterations when the bond is decreased. --------- Signed-off-by: georgepisaltu Co-authored-by: Bastian Köcher --- cumulus/pallets/collator-selection/src/lib.rs | 6 +++++- prdoc/pr_3643.prdoc | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 prdoc/pr_3643.prdoc diff --git a/cumulus/pallets/collator-selection/src/lib.rs b/cumulus/pallets/collator-selection/src/lib.rs index fb4c4a445df..62c00737f91 100644 --- a/cumulus/pallets/collator-selection/src/lib.rs +++ b/cumulus/pallets/collator-selection/src/lib.rs @@ -495,7 +495,11 @@ pub mod pallet { }) .unwrap_or_default(); Self::deposit_event(Event::NewCandidacyBond { bond_amount: bond }); - Ok(Some(T::WeightInfo::set_candidacy_bond(initial_len as u32, kicked as u32)).into()) + Ok(Some(T::WeightInfo::set_candidacy_bond( + bond_increased.then(|| initial_len as u32).unwrap_or_default(), + kicked as u32, + )) + .into()) } /// Register this account as a collator candidate. The account must (a) already have diff --git a/prdoc/pr_3643.prdoc b/prdoc/pr_3643.prdoc new file mode 100644 index 00000000000..6e85af8d99a --- /dev/null +++ b/prdoc/pr_3643.prdoc @@ -0,0 +1,12 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Fix weight refund for `pallet_collator_selection::set_candidacy_bond` + +doc: + - audience: Runtime Dev + description: | + This PR implements the weight refund of `pallet_collator_selection::set_candidacy_bond` to + account for no iterations over the candidate list when the candidacy bond is decreased. +crates: + - name: pallet-collator-selection -- GitLab From 7a644fa082f09b557a8a198ed56412f02062bbcf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 23:20:48 +0100 Subject: [PATCH 108/188] Bump handlebars from 4.3.7 to 5.1.0 (#3248) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [handlebars](https://github.com/sunng87/handlebars-rust) from 4.3.7 to 5.1.0.
Release notes

Sourced from handlebars's releases.

v5.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/sunng87/handlebars-rust/compare/v5.0.0...v5.1.0

v5.0.0

5.0.0

A semver major release that introduces some API breaking changes.

Highlights

  • RenderError has been rewritten for typed error reason. In previous versions we use string message for RenderError which is impossible to handle with code. This version introduces RenderErrorReason so you can use match to deal various error reasons.
  • Lifetime in Helper trait has been simplified.

Changes compared to 4.3

  • [Added] public mutable access to local variables in BlockContext #533
  • [Changed] Simplified lifetime specifiers for Helper, ScopedJson and some other related types and functions. #532
  • [Changed] Updated TemplateError to reduce its size. Direct field access is removed in favor of access methods
  • [Changed] Introducing RenderErrorReason for typed render error
  • [Changed] Changed register_template_directory api for more customizations #[610]
  • [Changed] Updated rust-embed to 8.0

Collaboration Wanted

I'm looking for collaborations to join the development with me on this project. Contact via email if your are interested in.

Auto-generated changelog

... (truncated)

Changelog

Sourced from handlebars's changelog.

5.1.0 - 2024-01-17

  • [Added] Chained else if block support #629

5.0.0 - 2023-12-31

  • [Added] public mutable access to local variables in BlockContext #533
  • [Changed] Simplified lifetime specifiers for Helper, ScopedJson and some other related types and functions. #532
  • [Changed] Updated TemplateError to reduce its size. Direct field access is removed in favor of access methods
  • [Changed] Introducing RenderErrorReason for typed render error
  • [Changed] Changed register_template_directory api for more customizations #[610]
  • [Changed] Updated rust-embed to 8.0

4.3.4 - 2022-09-11

  • [Added] New write_fmt function for Output #522
  • [Added] reason() method for TemplateError to access underlying reason, this replaces original direct .reason access.
  • [Changed] Direct access to TemplateError's reason field is depreacted will be removed in future.

4.3.3 - 2022-07-20

  • [Fixed] Disable partial expression indentation with {{~> partial}} to bring behavior closer in line with original javascript version. #518
  • [Fixed] Support for using partial context together with partial parameters #520

4.3.2 - 2022-07-14

  • [Added] Render functions that reuse Context for custom std::io::Write: render_with_context_to_write and render_template_with_context_to_write

4.3.1 - 2022-06-09

  • [Added] Added support for {{~{variable}~}} syntax #509

4.3.0 - 2022-05-18

  • [Changed] update MSRV to 1.57 as rhai requires
  • [Fixed] Reimplemented indent support for partial expression {{> partial}}, which is introduced in 4.2.0. The new implementation is aligned with original javascript version, that every text line generated from partial are indented as {{> partial}} does. prevent_indent will turn-off this feature. #505
  • [Changed] changed error support library from quick_error to thiserror

... (truncated)

Commits
  • d8d9a78 chore: Release handlebars version 5.1.0
  • 137bce5 chore: minor cleanup for chained else support in #629
  • e30d8ab Merge pull request #629 from progmboy/else_chain
  • 8f16353 format code
  • 786d132 add else chain support
  • 23672e8 Merge pull request #628 from sunng87/dependabot/npm_and_yarn/playground/www/f...
  • b849efd chore(deps-dev): bump follow-redirects in /playground/www
  • 7071c9d test: add test for error reason
  • 4664a34 (cargo-release) version 5.0.0
  • ca27748 Merge pull request #625 from sunng87/refactor/render-error-reason-2
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=handlebars&package-manager=cargo&previous-version=4.3.7&new-version=5.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bastian Köcher --- Cargo.lock | 4 ++-- substrate/utils/frame/benchmarking-cli/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b7ea71a536..7eaf3e44a1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6256,9 +6256,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "handlebars" -version = "4.3.7" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c3372087601b532857d332f5957cbae686da52bb7810bf038c3e3c3cc2fa0d" +checksum = "ab283476b99e66691dee3f1640fea91487a8d81f50fb5ecc75538f8f8879a1e4" dependencies = [ "log", "pest", diff --git a/substrate/utils/frame/benchmarking-cli/Cargo.toml b/substrate/utils/frame/benchmarking-cli/Cargo.toml index a2db83052c5..a25ab3a8f5b 100644 --- a/substrate/utils/frame/benchmarking-cli/Cargo.toml +++ b/substrate/utils/frame/benchmarking-cli/Cargo.toml @@ -21,7 +21,7 @@ chrono = "0.4" clap = { version = "4.5.1", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.6.1" } comfy-table = { version = "7.1.0", default-features = false } -handlebars = "4.2.2" +handlebars = "5.1.0" Inflector = "0.11.4" itertools = "0.10.3" lazy_static = "1.4.0" -- GitLab From 7315a9b8fdc18848025a83f18c643573d9be9e1e Mon Sep 17 00:00:00 2001 From: gupnik Date: Tue, 12 Mar 2024 10:12:58 +0530 Subject: [PATCH 109/188] Adds default config for assets pallet (#3637) Step in https://github.com/paritytech/polkadot-sdk/issues/171 --- substrate/frame/assets/src/lib.rs | 43 +++++++++++++++++++++++++++++- substrate/frame/assets/src/mock.rs | 16 +---------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs index 60316f8cdcf..09d59ae1b8b 100644 --- a/substrate/frame/assets/src/lib.rs +++ b/substrate/frame/assets/src/lib.rs @@ -226,10 +226,42 @@ pub mod pallet { } } - #[pallet::config] + /// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`]. + pub mod config_preludes { + use super::*; + use frame_support::{derive_impl, traits::ConstU64}; + pub struct TestDefaultConfig; + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + impl frame_system::DefaultConfig for TestDefaultConfig {} + + #[frame_support::register_default_impl(TestDefaultConfig)] + impl DefaultConfig for TestDefaultConfig { + #[inject_runtime_type] + type RuntimeEvent = (); + type Balance = u64; + type RemoveItemsLimit = ConstU32<5>; + type AssetId = u32; + type AssetIdParameter = u32; + type AssetDeposit = ConstU64<1>; + type AssetAccountDeposit = ConstU64<10>; + type MetadataDepositBase = ConstU64<1>; + type MetadataDepositPerByte = ConstU64<1>; + type ApprovalDeposit = ConstU64<1>; + type StringLimit = ConstU32<50>; + type Extra = (); + type CallbackHandle = (); + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + } + } + + #[pallet::config(with_default)] /// The module configuration trait. pub trait Config: frame_system::Config { /// The overarching event type. + #[pallet::no_default_bounds] type RuntimeEvent: From> + IsType<::RuntimeEvent>; @@ -262,10 +294,12 @@ pub mod pallet { type AssetIdParameter: Parameter + From + Into + MaxEncodedLen; /// The currency mechanism. + #[pallet::no_default] type Currency: ReservableCurrency; /// Standard asset class creation is only allowed if the origin attempting it and the /// asset class are in this set. + #[pallet::no_default] type CreateOrigin: EnsureOriginWithArg< Self::RuntimeOrigin, Self::AssetId, @@ -274,28 +308,34 @@ pub mod pallet { /// The origin which may forcibly create or destroy an asset or otherwise alter privileged /// attributes. + #[pallet::no_default] type ForceOrigin: EnsureOrigin; /// The basic amount of funds that must be reserved for an asset. #[pallet::constant] + #[pallet::no_default_bounds] type AssetDeposit: Get>; /// The amount of funds that must be reserved for a non-provider asset account to be /// maintained. #[pallet::constant] + #[pallet::no_default_bounds] type AssetAccountDeposit: Get>; /// The basic amount of funds that must be reserved when adding metadata to your asset. #[pallet::constant] + #[pallet::no_default_bounds] type MetadataDepositBase: Get>; /// The additional funds that must be reserved for the number of bytes you store in your /// metadata. #[pallet::constant] + #[pallet::no_default_bounds] type MetadataDepositPerByte: Get>; /// The amount of funds that must be reserved when creating a new approval. #[pallet::constant] + #[pallet::no_default_bounds] type ApprovalDeposit: Get>; /// The maximum length of a name or symbol stored on-chain. @@ -304,6 +344,7 @@ pub mod pallet { /// A hook to allow a per-asset, per-account minimum balance to be enforced. This must be /// respected in all permissionless operations. + #[pallet::no_default] type Freezer: FrozenBalance; /// Additional data to be stored with an account's asset balance. diff --git a/substrate/frame/assets/src/mock.rs b/substrate/frame/assets/src/mock.rs index e1722200c35..906febb0214 100644 --- a/substrate/frame/assets/src/mock.rs +++ b/substrate/frame/assets/src/mock.rs @@ -108,27 +108,13 @@ impl AssetsCallbackHandle { } } +#[derive_impl(crate::config_preludes::TestDefaultConfig)] impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type Balance = u64; - type AssetId = u32; - type AssetIdParameter = u32; type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; - type AssetDeposit = ConstU64<1>; - type AssetAccountDeposit = ConstU64<10>; - type MetadataDepositBase = ConstU64<1>; - type MetadataDepositPerByte = ConstU64<1>; - type ApprovalDeposit = ConstU64<1>; - type StringLimit = ConstU32<50>; type Freezer = TestFreezer; - type WeightInfo = (); type CallbackHandle = AssetsCallbackHandle; - type Extra = (); - type RemoveItemsLimit = ConstU32<5>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } use std::collections::HashMap; -- GitLab From b0f34e4b2953f814254f92c8d151f22ffcf9c034 Mon Sep 17 00:00:00 2001 From: Koute Date: Tue, 12 Mar 2024 14:23:06 +0900 Subject: [PATCH 110/188] Add a PolkaVM-based executor (#3458) This PR adds a new PolkaVM-based executor to Substrate. - The executor can now be used to actually run a PolkaVM-based runtime, and successfully produces blocks. - The executor is always compiled-in, but is disabled by default. - The `SUBSTRATE_ENABLE_POLKAVM` environment variable must be set to `1` to enable the executor, in which case the node will accept both WASM and PolkaVM program blobs (otherwise it'll default to WASM-only). This is deliberately undocumented and not explicitly exposed anywhere (e.g. in the command line arguments, or in the API) to disincentivize anyone from enabling it in production. If/when we'll move this into production usage I'll remove the environment variable and do it "properly". - I did not use our legacy runtime allocator for the PolkaVM executor, so currently every allocation inside of the runtime will leak guest memory until that particular instance is destroyed. The idea here is that I will work on the https://github.com/polkadot-fellows/RFCs/pull/4 which will remove the need for the legacy allocator under WASM, and that will also allow us to use a proper non-leaking allocator under PolkaVM. - I also did some minor cleanups of the WASM executor and deleted some dead code. No prdocs included since this is not intended to be an end-user feature, but an unofficial experiment, and shouldn't affect any current production user. Once this is production-ready a full Polkadot Fellowship RFC will be necessary anyway. --- Cargo.lock | 74 ++++- Cargo.toml | 6 +- .../core/pvf/common/src/executor_interface.rs | 4 +- substrate/client/executor/Cargo.toml | 1 + substrate/client/executor/common/Cargo.toml | 1 + substrate/client/executor/common/src/error.rs | 18 ++ substrate/client/executor/common/src/lib.rs | 4 + .../common/src/runtime_blob/runtime_blob.rs | 153 +++++----- .../executor/common/src/wasm_runtime.rs | 50 +--- substrate/client/executor/polkavm/Cargo.toml | 23 ++ substrate/client/executor/polkavm/README.md | 1 + substrate/client/executor/polkavm/src/lib.rs | 261 ++++++++++++++++++ substrate/client/executor/src/wasm_runtime.rs | 4 + .../executor/wasmtime/src/instance_wrapper.rs | 148 ++-------- .../client/executor/wasmtime/src/runtime.rs | 19 +- substrate/primitives/io/Cargo.toml | 3 + .../primitives/io/src/global_alloc_riscv.rs | 19 ++ .../primitives/io/src/global_alloc_wasm.rs | 34 +++ substrate/primitives/io/src/lib.rs | 34 +-- .../utils/wasm-builder/src/wasm_project.rs | 2 +- 20 files changed, 559 insertions(+), 300 deletions(-) create mode 100644 substrate/client/executor/polkavm/Cargo.toml create mode 100644 substrate/client/executor/polkavm/README.md create mode 100644 substrate/client/executor/polkavm/src/lib.rs create mode 100644 substrate/primitives/io/src/global_alloc_riscv.rs create mode 100644 substrate/primitives/io/src/global_alloc_wasm.rs diff --git a/Cargo.lock b/Cargo.lock index 7eaf3e44a1b..5eab3cf7c24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13805,6 +13805,28 @@ dependencies = [ "westend-runtime", ] +[[package]] +name = "polkavm" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3693e5efdb2bf74e449cd25fd777a28bd7ed87e41f5d5da75eb31b4de48b94" +dependencies = [ + "libc", + "log", + "polkavm-assembler", + "polkavm-common 0.9.0", + "polkavm-linux-raw", +] + +[[package]] +name = "polkavm-assembler" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa96d6d868243acc12de813dd48e756cbadcc8e13964c70d272753266deadc1" +dependencies = [ + "log", +] + [[package]] name = "polkavm-common" version = "0.5.0" @@ -13813,9 +13835,12 @@ checksum = "88b4e215c80fe876147f3d58158d5dfeae7dabdd6047e175af77095b78d0035c" [[package]] name = "polkavm-common" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92c99f7eee94e7be43ba37eef65ad0ee8cbaf89b7c00001c3f6d2be985cb1817" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" +dependencies = [ + "log", +] [[package]] name = "polkavm-derive" @@ -13829,9 +13854,9 @@ dependencies = [ [[package]] name = "polkavm-derive" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79fa916f7962348bd1bb1a65a83401675e6fc86c51a0fdbcf92a3108e58e6125" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" dependencies = [ "polkavm-derive-impl-macro", ] @@ -13850,11 +13875,11 @@ dependencies = [ [[package]] name = "polkavm-derive-impl" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c10b2654a8a10a83c260bfb93e97b262cf0017494ab94a65d389e0eda6de6c9c" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" dependencies = [ - "polkavm-common 0.8.0", + "polkavm-common 0.9.0", "proc-macro2", "quote", "syn 2.0.50", @@ -13862,11 +13887,11 @@ dependencies = [ [[package]] name = "polkavm-derive-impl-macro" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e85319a0d5129dc9f021c62607e0804f5fb777a05cdda44d750ac0732def66" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" dependencies = [ - "polkavm-derive-impl 0.8.0", + "polkavm-derive-impl 0.9.0", "syn 2.0.50", ] @@ -13887,19 +13912,25 @@ dependencies = [ [[package]] name = "polkavm-linker" -version = "0.8.2" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdec1451cb18261d5d01de82acc15305e417fb59588cdcb3127d3dcc9672b925" +checksum = "9c7be503e60cf56c0eb785f90aaba4b583b36bff00e93997d93fef97f9553c39" dependencies = [ "gimli 0.28.0", "hashbrown 0.14.3", "log", "object 0.32.2", - "polkavm-common 0.8.0", + "polkavm-common 0.9.0", "regalloc2 0.9.3", "rustc-demangle", ] +[[package]] +name = "polkavm-linux-raw" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26e85d3456948e650dff0cfc85603915847faf893ed1e66b020bb82ef4557120" + [[package]] name = "polling" version = "2.8.0" @@ -16112,6 +16143,7 @@ dependencies = [ "paste", "regex", "sc-executor-common", + "sc-executor-polkavm", "sc-executor-wasmtime", "sc-runtime-test", "sc-tracing", @@ -16141,6 +16173,7 @@ dependencies = [ name = "sc-executor-common" version = "0.29.0" dependencies = [ + "polkavm", "sc-allocator", "sp-maybe-compressed-blob", "sp-wasm-interface 20.0.0", @@ -16148,6 +16181,16 @@ dependencies = [ "wasm-instrument", ] +[[package]] +name = "sc-executor-polkavm" +version = "0.29.0" +dependencies = [ + "log", + "polkavm", + "sc-executor-common", + "sp-wasm-interface 20.0.0", +] + [[package]] name = "sc-executor-wasmtime" version = "0.29.0" @@ -18781,6 +18824,7 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", + "polkavm-derive 0.9.1", "rustversion", "secp256k1", "sp-core", @@ -18973,7 +19017,7 @@ dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive 0.8.0", + "polkavm-derive 0.9.1", "primitive-types", "rustversion", "sp-core", @@ -19995,7 +20039,7 @@ dependencies = [ "console", "filetime", "parity-wasm", - "polkavm-linker 0.8.2", + "polkavm-linker 0.9.2", "sp-maybe-compressed-blob", "strum 0.24.1", "tempfile", diff --git a/Cargo.toml b/Cargo.toml index 80068596685..f256d02808a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -249,6 +249,7 @@ members = [ "substrate/client/db", "substrate/client/executor", "substrate/client/executor/common", + "substrate/client/executor/polkavm", "substrate/client/executor/runtime-test", "substrate/client/executor/wasmtime", "substrate/client/informant", @@ -543,8 +544,9 @@ extra-unused-type-parameters = { level = "allow", priority = 2 } # stylistic default_constructed_unit_structs = { level = "allow", priority = 2 } # stylistic [workspace.dependencies] -polkavm-linker = "0.8.2" -polkavm-derive = "0.8.0" +polkavm = "0.9.3" +polkavm-linker = "0.9.2" +polkavm-derive = "0.9.1" log = { version = "0.4.20", default-features = false } quote = { version = "1.0.33" } serde = { version = "1.0.197", default-features = false } diff --git a/polkadot/node/core/pvf/common/src/executor_interface.rs b/polkadot/node/core/pvf/common/src/executor_interface.rs index b69a87890f6..252e611db8a 100644 --- a/polkadot/node/core/pvf/common/src/executor_interface.rs +++ b/polkadot/node/core/pvf/common/src/executor_interface.rs @@ -24,7 +24,7 @@ use polkadot_primitives::{ use sc_executor_common::{ error::WasmError, runtime_blob::RuntimeBlob, - wasm_runtime::{HeapAllocStrategy, InvokeMethod, WasmModule as _}, + wasm_runtime::{HeapAllocStrategy, WasmModule as _}, }; use sc_executor_wasmtime::{Config, DeterministicStackLimit, Semantics, WasmtimeRuntime}; use sp_core::storage::{ChildInfo, TrackedStorageKey}; @@ -119,7 +119,7 @@ pub unsafe fn execute_artifact( match sc_executor::with_externalities_safe(&mut ext, || { let runtime = create_runtime_from_artifact_bytes(compiled_artifact_blob, executor_params)?; - runtime.new_instance()?.call(InvokeMethod::Export("validate_block"), params) + runtime.new_instance()?.call("validate_block", params) }) { Ok(Ok(ok)) => Ok(ok), Ok(Err(err)) | Err(err) => Err(err), diff --git a/substrate/client/executor/Cargo.toml b/substrate/client/executor/Cargo.toml index 4e36de3c4f4..7fad7e3a2a0 100644 --- a/substrate/client/executor/Cargo.toml +++ b/substrate/client/executor/Cargo.toml @@ -23,6 +23,7 @@ tracing = "0.1.29" codec = { package = "parity-scale-codec", version = "3.6.1" } sc-executor-common = { path = "common" } +sc-executor-polkavm = { path = "polkavm" } sc-executor-wasmtime = { path = "wasmtime" } sp-api = { path = "../../primitives/api" } sp-core = { path = "../../primitives/core" } diff --git a/substrate/client/executor/common/Cargo.toml b/substrate/client/executor/common/Cargo.toml index bfd1fa6b740..8ff34c3709a 100644 --- a/substrate/client/executor/common/Cargo.toml +++ b/substrate/client/executor/common/Cargo.toml @@ -22,6 +22,7 @@ wasm-instrument = "0.4" sc-allocator = { path = "../../allocator" } sp-maybe-compressed-blob = { path = "../../../primitives/maybe-compressed-blob" } sp-wasm-interface = { path = "../../../primitives/wasm-interface" } +polkavm = { workspace = true } [features] default = [] diff --git a/substrate/client/executor/common/src/error.rs b/substrate/client/executor/common/src/error.rs index 2a0dc364b41..b7c7e2b7019 100644 --- a/substrate/client/executor/common/src/error.rs +++ b/substrate/client/executor/common/src/error.rs @@ -150,6 +150,24 @@ pub enum WasmError { Other(String), } +impl From for WasmError { + fn from(error: polkavm::ProgramParseError) -> Self { + WasmError::Other(error.to_string()) + } +} + +impl From for WasmError { + fn from(error: polkavm::Error) -> Self { + WasmError::Other(error.to_string()) + } +} + +impl From for Error { + fn from(error: polkavm::Error) -> Self { + Error::Other(error.to_string()) + } +} + /// An error message with an attached backtrace. #[derive(Debug)] pub struct MessageWithBacktrace { diff --git a/substrate/client/executor/common/src/lib.rs b/substrate/client/executor/common/src/lib.rs index 751801fb30d..ff9fab2c888 100644 --- a/substrate/client/executor/common/src/lib.rs +++ b/substrate/client/executor/common/src/lib.rs @@ -25,3 +25,7 @@ pub mod error; pub mod runtime_blob; pub mod util; pub mod wasm_runtime; + +pub(crate) fn is_polkavm_enabled() -> bool { + std::env::var_os("SUBSTRATE_ENABLE_POLKAVM").map_or(false, |value| value == "1") +} diff --git a/substrate/client/executor/common/src/runtime_blob/runtime_blob.rs b/substrate/client/executor/common/src/runtime_blob/runtime_blob.rs index becf9e219b0..d689083b2f8 100644 --- a/substrate/client/executor/common/src/runtime_blob/runtime_blob.rs +++ b/substrate/client/executor/common/src/runtime_blob/runtime_blob.rs @@ -17,23 +17,23 @@ // along with this program. If not, see . use crate::{error::WasmError, wasm_runtime::HeapAllocStrategy}; -use wasm_instrument::{ - export_mutable_globals, - parity_wasm::elements::{ - deserialize_buffer, serialize, ExportEntry, External, Internal, MemorySection, MemoryType, - Module, Section, - }, +use wasm_instrument::parity_wasm::elements::{ + deserialize_buffer, serialize, ExportEntry, External, Internal, MemorySection, MemoryType, + Module, Section, }; -/// A bunch of information collected from a WebAssembly module. +/// A program blob containing a Substrate runtime. #[derive(Clone)] -pub struct RuntimeBlob { - raw_module: Module, +pub struct RuntimeBlob(BlobKind); + +#[derive(Clone)] +enum BlobKind { + WebAssembly(Module), + PolkaVM(polkavm::ProgramBlob<'static>), } impl RuntimeBlob { - /// Create `RuntimeBlob` from the given wasm code. Will attempt to decompress the code before - /// deserializing it. + /// Create `RuntimeBlob` from the given WASM or PolkaVM compressed program blob. /// /// See [`sp_maybe_compressed_blob`] for details about decompression. pub fn uncompress_if_needed(wasm_code: &[u8]) -> Result { @@ -43,31 +43,26 @@ impl RuntimeBlob { Self::new(&wasm_code) } - /// Create `RuntimeBlob` from the given wasm code. + /// Create `RuntimeBlob` from the given WASM or PolkaVM program blob. /// - /// Returns `Err` if the wasm code cannot be deserialized. - pub fn new(wasm_code: &[u8]) -> Result { - let raw_module: Module = deserialize_buffer(wasm_code) - .map_err(|e| WasmError::Other(format!("cannot deserialize module: {:?}", e)))?; - Ok(Self { raw_module }) - } - - /// The number of globals defined in locally in this module. - pub fn declared_globals_count(&self) -> u32 { - self.raw_module - .global_section() - .map(|gs| gs.entries().len() as u32) - .unwrap_or(0) - } - - /// The number of imports of globals. - pub fn imported_globals_count(&self) -> u32 { - self.raw_module.import_section().map(|is| is.globals() as u32).unwrap_or(0) - } + /// Returns `Err` if the blob cannot be deserialized. + /// + /// Will only accept a PolkaVM program if the `SUBSTRATE_ENABLE_POLKAVM` environment + /// variable is set to `1`. + pub fn new(raw_blob: &[u8]) -> Result { + if raw_blob.starts_with(b"PVM\0") { + if crate::is_polkavm_enabled() { + return Ok(Self(BlobKind::PolkaVM( + polkavm::ProgramBlob::parse(raw_blob)?.into_owned(), + ))); + } else { + return Err(WasmError::Other("expected a WASM runtime blob, found a PolkaVM runtime blob; set the 'SUBSTRATE_ENABLE_POLKAVM' environment variable to enable the experimental PolkaVM-based executor".to_string())); + } + } - /// Perform an instrumentation that makes sure that the mutable globals are exported. - pub fn expose_mutable_globals(&mut self) { - export_mutable_globals(&mut self.raw_module, "exported_internal_global"); + let raw_module: Module = deserialize_buffer(raw_blob) + .map_err(|e| WasmError::Other(format!("cannot deserialize module: {:?}", e)))?; + Ok(Self(BlobKind::WebAssembly(raw_module))) } /// Run a pass that instrument this module so as to introduce a deterministic stack height @@ -80,26 +75,16 @@ impl RuntimeBlob { /// /// The stack cost of a function is computed based on how much locals there are and the maximum /// depth of the wasm operand stack. + /// + /// Only valid for WASM programs; will return an error if the blob is a PolkaVM program. pub fn inject_stack_depth_metering(self, stack_depth_limit: u32) -> Result { let injected_module = - wasm_instrument::inject_stack_limiter(self.raw_module, stack_depth_limit).map_err( - |e| WasmError::Other(format!("cannot inject the stack limiter: {:?}", e)), - )?; - - Ok(Self { raw_module: injected_module }) - } + wasm_instrument::inject_stack_limiter(self.into_webassembly_blob()?, stack_depth_limit) + .map_err(|e| { + WasmError::Other(format!("cannot inject the stack limiter: {:?}", e)) + })?; - /// Perform an instrumentation that makes sure that a specific function `entry_point` is - /// exported - pub fn entry_point_exists(&self, entry_point: &str) -> bool { - self.raw_module - .export_section() - .map(|e| { - e.entries().iter().any(|e| { - matches!(e.internal(), Internal::Function(_)) && e.field() == entry_point - }) - }) - .unwrap_or_default() + Ok(Self(BlobKind::WebAssembly(injected_module))) } /// Converts a WASM memory import into a memory section and exports it. @@ -107,8 +92,11 @@ impl RuntimeBlob { /// Does nothing if there's no memory import. /// /// May return an error in case the WASM module is invalid. + /// + /// Only valid for WASM programs; will return an error if the blob is a PolkaVM program. pub fn convert_memory_import_into_export(&mut self) -> Result<(), WasmError> { - let import_section = match self.raw_module.import_section_mut() { + let raw_module = self.as_webassembly_blob_mut()?; + let import_section = match raw_module.import_section_mut() { Some(import_section) => import_section, None => return Ok(()), }; @@ -124,7 +112,7 @@ impl RuntimeBlob { let memory_name = entry.field().to_owned(); import_entries.remove(index); - self.raw_module + raw_module .insert_section(Section::Memory(MemorySection::with_entries(vec![memory_ty]))) .map_err(|error| { WasmError::Other(format!( @@ -133,14 +121,14 @@ impl RuntimeBlob { )) })?; - if self.raw_module.export_section_mut().is_none() { + if raw_module.export_section_mut().is_none() { // A module without an export section is somewhat unrealistic, but let's do this // just in case to cover all of our bases. - self.raw_module + raw_module .insert_section(Section::Export(Default::default())) .expect("an export section can be always inserted if it doesn't exist; qed"); } - self.raw_module + raw_module .export_section_mut() .expect("export section already existed or we just added it above, so it always exists; qed") .entries_mut() @@ -156,12 +144,14 @@ impl RuntimeBlob { /// /// Will return an error in case there is no memory section present, /// or if the memory section is empty. + /// + /// Only valid for WASM programs; will return an error if the blob is a PolkaVM program. pub fn setup_memory_according_to_heap_alloc_strategy( &mut self, heap_alloc_strategy: HeapAllocStrategy, ) -> Result<(), WasmError> { - let memory_section = self - .raw_module + let raw_module = self.as_webassembly_blob_mut()?; + let memory_section = raw_module .memory_section_mut() .ok_or_else(|| WasmError::Other("no memory section found".into()))?; @@ -187,8 +177,11 @@ impl RuntimeBlob { /// Scans the wasm blob for the first section with the name that matches the given. Returns the /// contents of the custom section if found or `None` otherwise. + /// + /// Only valid for WASM programs; will return an error if the blob is a PolkaVM program. pub fn custom_section_contents(&self, section_name: &str) -> Option<&[u8]> { - self.raw_module + self.as_webassembly_blob() + .ok()? .custom_sections() .find(|cs| cs.name() == section_name) .map(|cs| cs.payload()) @@ -196,11 +189,45 @@ impl RuntimeBlob { /// Consumes this runtime blob and serializes it. pub fn serialize(self) -> Vec { - serialize(self.raw_module).expect("serializing into a vec should succeed; qed") + match self.0 { + BlobKind::WebAssembly(raw_module) => + serialize(raw_module).expect("serializing into a vec should succeed; qed"), + BlobKind::PolkaVM(ref blob) => blob.as_bytes().to_vec(), + } + } + + fn as_webassembly_blob(&self) -> Result<&Module, WasmError> { + match self.0 { + BlobKind::WebAssembly(ref raw_module) => Ok(raw_module), + BlobKind::PolkaVM(..) => Err(WasmError::Other( + "expected a WebAssembly program; found a PolkaVM program blob".into(), + )), + } } - /// Destructure this structure into the underlying parity-wasm Module. - pub fn into_inner(self) -> Module { - self.raw_module + fn as_webassembly_blob_mut(&mut self) -> Result<&mut Module, WasmError> { + match self.0 { + BlobKind::WebAssembly(ref mut raw_module) => Ok(raw_module), + BlobKind::PolkaVM(..) => Err(WasmError::Other( + "expected a WebAssembly program; found a PolkaVM program blob".into(), + )), + } + } + + fn into_webassembly_blob(self) -> Result { + match self.0 { + BlobKind::WebAssembly(raw_module) => Ok(raw_module), + BlobKind::PolkaVM(..) => Err(WasmError::Other( + "expected a WebAssembly program; found a PolkaVM program blob".into(), + )), + } + } + + /// Gets a reference to the inner PolkaVM program blob, if this is a PolkaVM program. + pub fn as_polkavm_blob(&self) -> Option<&polkavm::ProgramBlob> { + match self.0 { + BlobKind::WebAssembly(..) => None, + BlobKind::PolkaVM(ref blob) => Some(blob), + } } } diff --git a/substrate/client/executor/common/src/wasm_runtime.rs b/substrate/client/executor/common/src/wasm_runtime.rs index d8e142b9d55..e8f429a3dbb 100644 --- a/substrate/client/executor/common/src/wasm_runtime.rs +++ b/substrate/client/executor/common/src/wasm_runtime.rs @@ -19,7 +19,6 @@ //! Definitions for a wasm runtime. use crate::error::Error; -use sp_wasm_interface::Value; pub use sc_allocator::AllocationStats; @@ -30,46 +29,6 @@ pub const DEFAULT_HEAP_ALLOC_STRATEGY: HeapAllocStrategy = /// Default heap allocation pages. pub const DEFAULT_HEAP_ALLOC_PAGES: u32 = 2048; -/// A method to be used to find the entrypoint when calling into the runtime -/// -/// Contains variants on how to resolve wasm function that will be invoked. -pub enum InvokeMethod<'a> { - /// Call function exported with this name. - /// - /// Located function should have (u32, u32) -> u64 signature. - Export(&'a str), - /// Call a function found in the exported table found under the given index. - /// - /// Located function should have (u32, u32) -> u64 signature. - Table(u32), - /// Call function by reference from table through a wrapper. - /// - /// Invoked function (`dispatcher_ref`) function - /// should have (u32, u32, u32) -> u64 signature. - /// - /// `func` will be passed to the invoked function as a first argument. - TableWithWrapper { - /// Wrapper for the call. - /// - /// Function pointer, index into runtime exported table. - dispatcher_ref: u32, - /// Extra argument for dispatch. - /// - /// Common usage would be to use it as an actual wasm function pointer - /// that should be invoked, but can be used as any extra argument on the - /// callee side. - /// - /// This is typically generated and invoked by the runtime itself. - func: u32, - }, -} - -impl<'a> From<&'a str> for InvokeMethod<'a> { - fn from(val: &'a str) -> InvokeMethod<'a> { - InvokeMethod::Export(val) - } -} - /// A trait that defines an abstract WASM runtime module. /// /// This can be implemented by an execution engine. @@ -87,7 +46,7 @@ pub trait WasmInstance: Send { /// Before execution, instance is reset. /// /// Returns the encoded result on success. - fn call(&mut self, method: InvokeMethod, data: &[u8]) -> Result, Error> { + fn call(&mut self, method: &str, data: &[u8]) -> Result, Error> { self.call_with_allocation_stats(method, data).0 } @@ -98,7 +57,7 @@ pub trait WasmInstance: Send { /// Returns the encoded result on success. fn call_with_allocation_stats( &mut self, - method: InvokeMethod, + method: &str, data: &[u8], ) -> (Result, Error>, Option); @@ -110,11 +69,6 @@ pub trait WasmInstance: Send { fn call_export(&mut self, method: &str, data: &[u8]) -> Result, Error> { self.call(method.into(), data) } - - /// Get the value from a global with the given `name`. - /// - /// This method is only suitable for getting immutable globals. - fn get_global_const(&mut self, name: &str) -> Result, Error>; } /// Defines the heap pages allocation strategy the wasm runtime should use. diff --git a/substrate/client/executor/polkavm/Cargo.toml b/substrate/client/executor/polkavm/Cargo.toml new file mode 100644 index 00000000000..9d0eb8ccf0e --- /dev/null +++ b/substrate/client/executor/polkavm/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sc-executor-polkavm" +version = "0.29.0" +authors.workspace = true +edition.workspace = true +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +homepage = "https://substrate.io" +repository.workspace = true +description = "PolkaVM executor for Substrate" +readme = "README.md" + +[lints] +workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +log = { workspace = true } +polkavm = { workspace = true } + +sc-executor-common = { path = "../common" } +sp-wasm-interface = { path = "../../../primitives/wasm-interface" } diff --git a/substrate/client/executor/polkavm/README.md b/substrate/client/executor/polkavm/README.md new file mode 100644 index 00000000000..64fc2fa0c28 --- /dev/null +++ b/substrate/client/executor/polkavm/README.md @@ -0,0 +1 @@ +License: GPL-3.0-or-later WITH Classpath-exception-2.0 diff --git a/substrate/client/executor/polkavm/src/lib.rs b/substrate/client/executor/polkavm/src/lib.rs new file mode 100644 index 00000000000..1bd72eb33d3 --- /dev/null +++ b/substrate/client/executor/polkavm/src/lib.rs @@ -0,0 +1,261 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +use polkavm::{Caller, Reg}; +use sc_executor_common::{ + error::{Error, WasmError}, + wasm_runtime::{AllocationStats, WasmInstance, WasmModule}, +}; +use sp_wasm_interface::{ + Function, FunctionContext, HostFunctions, Pointer, Value, ValueType, WordSize, +}; + +#[repr(transparent)] +pub struct InstancePre(polkavm::InstancePre<()>); + +#[repr(transparent)] +pub struct Instance(polkavm::Instance<()>); + +impl WasmModule for InstancePre { + fn new_instance(&self) -> Result, Error> { + Ok(Box::new(Instance(self.0.instantiate()?))) + } +} + +impl WasmInstance for Instance { + fn call_with_allocation_stats( + &mut self, + name: &str, + raw_data: &[u8], + ) -> (Result, Error>, Option) { + let Some(method_index) = self.0.module().lookup_export(name) else { + return ( + Err(format!("cannot call into the runtime: export not found: '{name}'").into()), + None, + ); + }; + + let Ok(raw_data_length) = u32::try_from(raw_data.len()) else { + return ( + Err(format!("cannot call runtime method '{name}': input payload is too big").into()), + None, + ); + }; + + // TODO: This will leak guest memory; find a better solution. + let mut state_args = polkavm::StateArgs::new(); + + // Make sure the memory is cleared... + state_args.reset_memory(true); + // ...and allocate space for the input payload. + state_args.sbrk(raw_data_length); + + match self.0.update_state(state_args) { + Ok(()) => {}, + Err(polkavm::ExecutionError::Trap(trap)) => { + return (Err(format!("call into the runtime method '{name}' failed: failed to prepare the guest's memory: {trap}").into()), None); + }, + Err(polkavm::ExecutionError::Error(error)) => { + return (Err(format!("call into the runtime method '{name}' failed: failed to prepare the guest's memory: {error}").into()), None); + }, + Err(polkavm::ExecutionError::OutOfGas) => unreachable!("gas metering is never enabled"), + } + + // Grab the address of where the guest's heap starts; that's where we've just allocated + // the memory for the input payload. + let data_pointer = self.0.module().memory_map().heap_base(); + + if let Err(error) = self.0.write_memory(data_pointer, raw_data) { + return (Err(format!("call into the runtime method '{name}': failed to write the input payload into guest memory: {error}").into()), None); + } + + let mut state = (); + let mut call_args = polkavm::CallArgs::new(&mut state, method_index); + call_args.args_untyped(&[data_pointer, raw_data_length]); + + match self.0.call(Default::default(), call_args) { + Ok(()) => {}, + Err(polkavm::ExecutionError::Trap(trap)) => { + return ( + Err(format!("call into the runtime method '{name}' failed: {trap}").into()), + None, + ); + }, + Err(polkavm::ExecutionError::Error(error)) => { + return ( + Err(format!("call into the runtime method '{name}' failed: {error}").into()), + None, + ); + }, + Err(polkavm::ExecutionError::OutOfGas) => unreachable!("gas metering is never enabled"), + } + + let result_pointer = self.0.get_reg(Reg::A0); + let result_length = self.0.get_reg(Reg::A1); + let output = match self.0.read_memory_into_vec(result_pointer, result_length) { + Ok(output) => output, + Err(error) => { + return (Err(format!("call into the runtime method '{name}' failed: failed to read the return payload: {error}").into()), None) + }, + }; + + (Ok(output), None) + } +} + +struct Context<'r, 'a>(&'r mut polkavm::Caller<'a, ()>); + +impl<'r, 'a> FunctionContext for Context<'r, 'a> { + fn read_memory_into( + &self, + address: Pointer, + dest: &mut [u8], + ) -> sp_wasm_interface::Result<()> { + self.0 + .read_memory_into_slice(u32::from(address), dest) + .map_err(|error| error.to_string()) + .map(|_| ()) + } + + fn write_memory(&mut self, address: Pointer, data: &[u8]) -> sp_wasm_interface::Result<()> { + self.0.write_memory(u32::from(address), data).map_err(|error| error.to_string()) + } + + fn allocate_memory(&mut self, size: WordSize) -> sp_wasm_interface::Result> { + let pointer = self.0.sbrk(0).expect("fetching the current heap pointer never fails"); + + // TODO: This will leak guest memory; find a better solution. + self.0.sbrk(size).ok_or_else(|| String::from("allocation failed"))?; + + Ok(Pointer::new(pointer)) + } + + fn deallocate_memory(&mut self, _ptr: Pointer) -> sp_wasm_interface::Result<()> { + // This is only used by the allocator host function, which is unused under PolkaVM. + unimplemented!("'deallocate_memory' is never used when running under PolkaVM"); + } + + fn register_panic_error_message(&mut self, _message: &str) { + unimplemented!("'register_panic_error_message' is never used when running under PolkaVM"); + } +} + +fn call_host_function( + caller: &mut Caller<()>, + function: &dyn Function, +) -> Result<(), polkavm::Trap> { + let mut args = [Value::I64(0); Reg::ARG_REGS.len()]; + let mut nth_reg = 0; + for (nth_arg, kind) in function.signature().args.iter().enumerate() { + match kind { + ValueType::I32 => { + args[nth_arg] = Value::I32(caller.get_reg(Reg::ARG_REGS[nth_reg]) as i32); + nth_reg += 1; + }, + ValueType::F32 => { + args[nth_arg] = Value::F32(caller.get_reg(Reg::ARG_REGS[nth_reg])); + nth_reg += 1; + }, + ValueType::I64 => { + let value_lo = caller.get_reg(Reg::ARG_REGS[nth_reg]); + nth_reg += 1; + + let value_hi = caller.get_reg(Reg::ARG_REGS[nth_reg]); + nth_reg += 1; + + args[nth_arg] = + Value::I64((u64::from(value_lo) | (u64::from(value_hi) << 32)) as i64); + }, + ValueType::F64 => { + let value_lo = caller.get_reg(Reg::ARG_REGS[nth_reg]); + nth_reg += 1; + + let value_hi = caller.get_reg(Reg::ARG_REGS[nth_reg]); + nth_reg += 1; + + args[nth_arg] = Value::F64(u64::from(value_lo) | (u64::from(value_hi) << 32)); + }, + } + } + + log::trace!( + "Calling host function: '{}', args = {:?}", + function.name(), + &args[..function.signature().args.len()] + ); + + let value = match function + .execute(&mut Context(caller), &mut args.into_iter().take(function.signature().args.len())) + { + Ok(value) => value, + Err(error) => { + log::warn!("Call into the host function '{}' failed: {error}", function.name()); + return Err(polkavm::Trap::default()); + }, + }; + + if let Some(value) = value { + match value { + Value::I32(value) => { + caller.set_reg(Reg::A0, value as u32); + }, + Value::F32(value) => { + caller.set_reg(Reg::A0, value); + }, + Value::I64(value) => { + caller.set_reg(Reg::A0, value as u32); + caller.set_reg(Reg::A1, (value >> 32) as u32); + }, + Value::F64(value) => { + caller.set_reg(Reg::A0, value as u32); + caller.set_reg(Reg::A1, (value >> 32) as u32); + }, + } + } + + Ok(()) +} + +pub fn create_runtime(blob: &polkavm::ProgramBlob) -> Result, WasmError> +where + H: HostFunctions, +{ + static ENGINE: std::sync::OnceLock> = + std::sync::OnceLock::new(); + + let engine = ENGINE.get_or_init(|| { + let config = polkavm::Config::from_env()?; + polkavm::Engine::new(&config) + }); + + let engine = match engine { + Ok(ref engine) => engine, + Err(ref error) => { + return Err(WasmError::Other(error.to_string())); + }, + }; + + let module = polkavm::Module::from_blob(&engine, &polkavm::ModuleConfig::default(), blob)?; + let mut linker = polkavm::Linker::new(&engine); + for function in H::host_functions() { + linker.func_new(function.name(), |mut caller| call_host_function(&mut caller, function))?; + } + + let instance_pre = linker.instantiate_pre(&module)?; + Ok(Box::new(InstancePre(instance_pre))) +} diff --git a/substrate/client/executor/src/wasm_runtime.rs b/substrate/client/executor/src/wasm_runtime.rs index 501279a312c..be8344ba79b 100644 --- a/substrate/client/executor/src/wasm_runtime.rs +++ b/substrate/client/executor/src/wasm_runtime.rs @@ -297,6 +297,10 @@ pub fn create_wasm_runtime_with_code( where H: HostFunctions, { + if let Some(blob) = blob.as_polkavm_blob() { + return sc_executor_polkavm::create_runtime::(blob); + } + match wasm_method { WasmExecutionMethod::Compiled { instantiation_strategy } => sc_executor_wasmtime::create_runtime::( diff --git a/substrate/client/executor/wasmtime/src/instance_wrapper.rs b/substrate/client/executor/wasmtime/src/instance_wrapper.rs index 8852532adbc..4f67d1df9c5 100644 --- a/substrate/client/executor/wasmtime/src/instance_wrapper.rs +++ b/substrate/client/executor/wasmtime/src/instance_wrapper.rs @@ -22,36 +22,12 @@ use std::sync::Arc; use crate::runtime::{InstanceCounter, ReleaseInstanceHandle, Store, StoreData}; -use sc_executor_common::{ - error::{Backtrace, Error, MessageWithBacktrace, Result, WasmError}, - wasm_runtime::InvokeMethod, -}; -use sp_wasm_interface::{Pointer, Value, WordSize}; -use wasmtime::{ - AsContext, AsContextMut, Engine, Extern, Instance, InstancePre, Memory, Table, Val, -}; - -/// Invoked entrypoint format. -pub enum EntryPointType { - /// Direct call. - /// - /// Call is made by providing only payload reference and length. - Direct { entrypoint: wasmtime::TypedFunc<(u32, u32), u64> }, - /// Indirect call. - /// - /// Call is made by providing payload reference and length, and extra argument - /// for advanced routing. - Wrapped { - /// The extra argument passed to the runtime. It is typically a wasm function pointer. - func: u32, - dispatcher: wasmtime::TypedFunc<(u32, u32, u32), u64>, - }, -} +use sc_executor_common::error::{Backtrace, Error, MessageWithBacktrace, Result, WasmError}; +use sp_wasm_interface::{Pointer, WordSize}; +use wasmtime::{AsContext, AsContextMut, Engine, Instance, InstancePre, Memory}; /// Wasm blob entry point. -pub struct EntryPoint { - call_type: EntryPointType, -} +pub struct EntryPoint(wasmtime::TypedFunc<(u32, u32), u64>); impl EntryPoint { /// Call this entry point. @@ -64,13 +40,7 @@ impl EntryPoint { let data_ptr = u32::from(data_ptr); let data_len = u32::from(data_len); - match self.call_type { - EntryPointType::Direct { ref entrypoint } => - entrypoint.call(&mut *store, (data_ptr, data_len)), - EntryPointType::Wrapped { func, ref dispatcher } => - dispatcher.call(&mut *store, (func, data_ptr, data_len)), - } - .map_err(|trap| { + self.0.call(&mut *store, (data_ptr, data_len)).map_err(|trap| { let host_state = store .data_mut() .host_state @@ -99,18 +69,7 @@ impl EntryPoint { let entrypoint = func .typed::<(u32, u32), u64>(ctx) .map_err(|_| "Invalid signature for direct entry point")?; - Ok(Self { call_type: EntryPointType::Direct { entrypoint } }) - } - - pub fn wrapped( - dispatcher: wasmtime::Func, - func: u32, - ctx: impl AsContext, - ) -> std::result::Result { - let dispatcher = dispatcher - .typed::<(u32, u32, u32), u64>(ctx) - .map_err(|_| "Invalid signature for wrapped entry point")?; - Ok(Self { call_type: EntryPointType::Wrapped { func, dispatcher } }) + Ok(Self(entrypoint)) } } @@ -178,10 +137,8 @@ impl InstanceWrapper { })?; let memory = get_linear_memory(&instance, &mut store)?; - let table = get_table(&instance, &mut store); store.data_mut().memory = Some(memory); - store.data_mut().table = table; Ok(InstanceWrapper { instance, store, _release_instance_handle }) } @@ -190,61 +147,17 @@ impl InstanceWrapper { /// /// An entrypoint must have a signature `(i32, i32) -> i64`, otherwise this function will return /// an error. - pub fn resolve_entrypoint(&mut self, method: InvokeMethod) -> Result { - Ok(match method { - InvokeMethod::Export(method) => { - // Resolve the requested method and verify that it has a proper signature. - let export = - self.instance.get_export(&mut self.store, method).ok_or_else(|| { - Error::from(format!("Exported method {} is not found", method)) - })?; - let func = export - .into_func() - .ok_or_else(|| Error::from(format!("Export {} is not a function", method)))?; - EntryPoint::direct(func, &self.store).map_err(|_| { - Error::from(format!("Exported function '{}' has invalid signature.", method)) - })? - }, - InvokeMethod::Table(func_ref) => { - let table = self - .instance - .get_table(&mut self.store, "__indirect_function_table") - .ok_or(Error::NoTable)?; - let val = table - .get(&mut self.store, func_ref) - .ok_or(Error::NoTableEntryWithIndex(func_ref))?; - let func = val - .funcref() - .ok_or(Error::TableElementIsNotAFunction(func_ref))? - .ok_or(Error::FunctionRefIsNull(func_ref))?; - - EntryPoint::direct(*func, &self.store).map_err(|_| { - Error::from(format!( - "Function @{} in exported table has invalid signature for direct call.", - func_ref, - )) - })? - }, - InvokeMethod::TableWithWrapper { dispatcher_ref, func } => { - let table = self - .instance - .get_table(&mut self.store, "__indirect_function_table") - .ok_or(Error::NoTable)?; - let val = table - .get(&mut self.store, dispatcher_ref) - .ok_or(Error::NoTableEntryWithIndex(dispatcher_ref))?; - let dispatcher = val - .funcref() - .ok_or(Error::TableElementIsNotAFunction(dispatcher_ref))? - .ok_or(Error::FunctionRefIsNull(dispatcher_ref))?; - - EntryPoint::wrapped(*dispatcher, func, &self.store).map_err(|_| { - Error::from(format!( - "Function @{} in exported table has invalid signature for wrapped call.", - dispatcher_ref, - )) - })? - }, + pub fn resolve_entrypoint(&mut self, method: &str) -> Result { + // Resolve the requested method and verify that it has a proper signature. + let export = self + .instance + .get_export(&mut self.store, method) + .ok_or_else(|| Error::from(format!("Exported method {} is not found", method)))?; + let func = export + .into_func() + .ok_or_else(|| Error::from(format!("Export {} is not a function", method)))?; + EntryPoint::direct(func, &self.store).map_err(|_| { + Error::from(format!("Exported function '{}' has invalid signature.", method)) }) } @@ -268,24 +181,6 @@ impl InstanceWrapper { Ok(heap_base as u32) } - - /// Get the value from a global with the given `name`. - pub fn get_global_val(&mut self, name: &str) -> Result> { - let global = match self.instance.get_export(&mut self.store, name) { - Some(global) => global, - None => return Ok(None), - }; - - let global = global.into_global().ok_or_else(|| format!("`{}` is not a global", name))?; - - match global.get(&mut self.store) { - Val::I32(val) => Ok(Some(Value::I32(val))), - Val::I64(val) => Ok(Some(Value::I64(val))), - Val::F32(val) => Ok(Some(Value::F32(val))), - Val::F64(val) => Ok(Some(Value::F64(val))), - _ => Err("Unknown value type".into()), - } - } } /// Extract linear memory instance from the given instance. @@ -301,15 +196,6 @@ fn get_linear_memory(instance: &Instance, ctx: impl AsContextMut) -> Result Option
CommittedCandidateReceipt<H = Hash>
{ - instance - .get_export(ctx, "__indirect_function_table") - .as_ref() - .cloned() - .and_then(Extern::into_table) -} - /// Functions related to memory. impl InstanceWrapper { pub(crate) fn store(&self) -> &Store { diff --git a/substrate/client/executor/wasmtime/src/runtime.rs b/substrate/client/executor/wasmtime/src/runtime.rs index ac88663f4e7..595cc503272 100644 --- a/substrate/client/executor/wasmtime/src/runtime.rs +++ b/substrate/client/executor/wasmtime/src/runtime.rs @@ -30,10 +30,10 @@ use sc_executor_common::{ error::{Error, Result, WasmError}, runtime_blob::RuntimeBlob, util::checked_range, - wasm_runtime::{HeapAllocStrategy, InvokeMethod, WasmInstance, WasmModule}, + wasm_runtime::{HeapAllocStrategy, WasmInstance, WasmModule}, }; use sp_runtime_interface::unpack_ptr_and_len; -use sp_wasm_interface::{HostFunctions, Pointer, Value, WordSize}; +use sp_wasm_interface::{HostFunctions, Pointer, WordSize}; use std::{ path::{Path, PathBuf}, sync::{ @@ -41,7 +41,7 @@ use std::{ Arc, }, }; -use wasmtime::{AsContext, Engine, Memory, Table}; +use wasmtime::{AsContext, Engine, Memory}; const MAX_INSTANCE_COUNT: u32 = 64; @@ -51,8 +51,6 @@ pub(crate) struct StoreData { pub(crate) host_state: Option, /// This will be always set once the store is initialized. pub(crate) memory: Option, - /// This will be set only if the runtime actually contains a table. - pub(crate) table: Option
, } impl StoreData { @@ -164,7 +162,7 @@ pub struct WasmtimeInstance { impl WasmtimeInstance { fn call_impl( &mut self, - method: InvokeMethod, + method: &str, data: &[u8], allocation_stats: &mut Option, ) -> Result> { @@ -184,20 +182,13 @@ impl WasmtimeInstance { impl WasmInstance for WasmtimeInstance { fn call_with_allocation_stats( &mut self, - method: InvokeMethod, + method: &str, data: &[u8], ) -> (Result>, Option) { let mut allocation_stats = None; let result = self.call_impl(method, data, &mut allocation_stats); (result, allocation_stats) } - - fn get_global_const(&mut self, name: &str) -> Result> { - match &mut self.strategy { - Strategy::RecreateInstance(ref mut instance_creator) => - instance_creator.instantiate()?.get_global_val(name), - } - } } /// Prepare a directory structure and a config file to enable wasmtime caching. diff --git a/substrate/primitives/io/Cargo.toml b/substrate/primitives/io/Cargo.toml index c78def9bf44..e47775d56d9 100644 --- a/substrate/primitives/io/Cargo.toml +++ b/substrate/primitives/io/Cargo.toml @@ -38,6 +38,9 @@ tracing-core = { version = "0.1.32", default-features = false } # Required for backwards compatibility reason, but only used for verifying when `UseDalekExt` is set. ed25519-dalek = { version = "2.1", default-features = false, optional = true } +[target.'cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), substrate_runtime))'.dependencies] +polkavm-derive = { workspace = true } + [build-dependencies] rustversion = "1.0.6" diff --git a/substrate/primitives/io/src/global_alloc_riscv.rs b/substrate/primitives/io/src/global_alloc_riscv.rs new file mode 100644 index 00000000000..8d7c69c2094 --- /dev/null +++ b/substrate/primitives/io/src/global_alloc_riscv.rs @@ -0,0 +1,19 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[global_allocator] +static ALLOCATOR: polkavm_derive::LeakingAllocator = polkavm_derive::LeakingAllocator; diff --git a/substrate/primitives/io/src/global_alloc_wasm.rs b/substrate/primitives/io/src/global_alloc_wasm.rs new file mode 100644 index 00000000000..cf19a6e21a2 --- /dev/null +++ b/substrate/primitives/io/src/global_alloc_wasm.rs @@ -0,0 +1,34 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use core::alloc::{GlobalAlloc, Layout}; + +/// Allocator used by Substrate from within the runtime. +struct RuntimeAllocator; + +#[global_allocator] +static ALLOCATOR: RuntimeAllocator = RuntimeAllocator; + +unsafe impl GlobalAlloc for RuntimeAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + crate::allocator::malloc(layout.size() as u32) + } + + unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { + crate::allocator::free(ptr) + } +} diff --git a/substrate/primitives/io/src/lib.rs b/substrate/primitives/io/src/lib.rs index 6d34199416a..684854ea5c8 100644 --- a/substrate/primitives/io/src/lib.rs +++ b/substrate/primitives/io/src/lib.rs @@ -129,6 +129,16 @@ use sp_externalities::{Externalities, ExternalitiesExt}; pub use sp_externalities::MultiRemovalResults; +#[cfg(all(not(feature = "disable_allocator"), substrate_runtime, target_family = "wasm"))] +mod global_alloc_wasm; + +#[cfg(all( + not(feature = "disable_allocator"), + substrate_runtime, + any(target_arch = "riscv32", target_arch = "riscv64") +))] +mod global_alloc_riscv; + #[cfg(feature = "std")] const LOG_TARGET: &str = "runtime::io"; @@ -1737,30 +1747,6 @@ mod tracing_setup { pub use tracing_setup::init_tracing; -/// Allocator used by Substrate from within the runtime. -#[cfg(substrate_runtime)] -struct RuntimeAllocator; - -#[cfg(all(not(feature = "disable_allocator"), substrate_runtime))] -#[global_allocator] -static ALLOCATOR: RuntimeAllocator = RuntimeAllocator; - -#[cfg(substrate_runtime)] -mod allocator_impl { - use super::*; - use core::alloc::{GlobalAlloc, Layout}; - - unsafe impl GlobalAlloc for RuntimeAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - allocator::malloc(layout.size() as u32) - } - - unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { - allocator::free(ptr) - } - } -} - /// Crashes the execution of the program. /// /// Equivalent to the WASM `unreachable` instruction, RISC-V `unimp` instruction, diff --git a/substrate/utils/wasm-builder/src/wasm_project.rs b/substrate/utils/wasm-builder/src/wasm_project.rs index 9ffb5c72fd9..13db9fce431 100644 --- a/substrate/utils/wasm-builder/src/wasm_project.rs +++ b/substrate/utils/wasm-builder/src/wasm_project.rs @@ -855,7 +855,7 @@ fn build_bloaty_blob( println!("{} {}", colorize_info_message("Using rustc version:"), cargo_cmd.rustc_version()); // Use `process::exit(1)` to have a clean error output. - if !matches!(build_cmd.status().map(|s| s.success()), Ok(true)) { + if !build_cmd.status().map_or(false, |s| s.success()) { process::exit(1); } -- GitLab From 1ead59773e2dab336d2b54295419bbc3fe7c687f Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Date: Tue, 12 Mar 2024 10:33:54 +0200 Subject: [PATCH 111/188] Add api-name in `cannot query the runtime API version` warning (#3653) Sometimes we see nodes printing this warning: ``` cannot query the runtime API version: Api called for an unknown Block: State already discarded for ``` The log is harmless, but let's print the api we got this for, so that we can track its call site and truly confirm it is harmless or fix it. Signed-off-by: Alexandru Gheorghe --- polkadot/node/core/runtime-api/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/polkadot/node/core/runtime-api/src/lib.rs b/polkadot/node/core/runtime-api/src/lib.rs index 4bedfd82734..3ff1a35d068 100644 --- a/polkadot/node/core/runtime-api/src/lib.rs +++ b/polkadot/node/core/runtime-api/src/lib.rs @@ -433,6 +433,7 @@ where .unwrap_or_else(|e| { gum::warn!( target: LOG_TARGET, + api = ?stringify!($api_name), "cannot query the runtime API version: {}", e, ); -- GitLab From a756baf3b211efc57ca4a0089b7ceba4c20b9f12 Mon Sep 17 00:00:00 2001 From: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Date: Tue, 12 Mar 2024 12:43:31 +0100 Subject: [PATCH 112/188] Support for `keyring` in runtimes (#2044) This functionality is required for #1984. This PR enables [`sp-keyring`](https://github.com/paritytech/polkadot-sdk/blob/21d36b7b4229c4d5225944f197918cde23fda4ea/substrate/primitives/keyring/src/sr25519.rs#L31-L40) in `no-std` environments, allowing to generate the public key (e.g. `AccountKeyring::Alice.public().to_ss58check()`), which can be later used in the any of built-in [_runtime-genesis-config_ variant](https://github.com/paritytech/polkadot-sdk/blob/21d36b7b4229c4d5225944f197918cde23fda4ea/polkadot/node/service/src/chain_spec.rs#L1066-L1073). The proposal is as follows: - expose [`core::Pair` trait](https://github.com/paritytech/polkadot-sdk/blob/d6f15306282e3de848a09c9aa9cba6f95a7811f0/substrate/primitives/core/src/crypto.rs#L832) in `no-std`, - `full_crypto` feature enables `sign` method, - `std` feature enables `generate_with_phrase` and `generate` methods (randomness is required), - All other functionality, currently gated by `full_crypto` will be available unconditionally (`no-std`): -- `from_string` -- `from_string_with_seed` -- `from seed` -- `from_seed_slice` -- `from_phrase` -- `derive` -- `verify` --- Depends on https://github.com/rust-bitcoin/rust-bip39/pull/57 --------- Co-authored-by: command-bot <> Co-authored-by: Davide Galassi --- .gitlab/pipeline/check.yml | 16 +++++ Cargo.lock | 43 ++++++++++++-- substrate/client/cli/Cargo.toml | 3 +- substrate/client/cli/src/commands/generate.rs | 2 +- .../check-features-variants.sh | 12 ++++ .../application-crypto/src/bls377.rs | 5 +- .../application-crypto/src/ecdsa.rs | 4 +- .../application-crypto/src/ecdsa_bls377.rs | 1 + .../application-crypto/src/ed25519.rs | 4 +- .../primitives/application-crypto/src/lib.rs | 59 +++++++++++++------ .../application-crypto/src/sr25519.rs | 4 +- .../application-crypto/src/traits.rs | 14 +---- substrate/primitives/core/Cargo.toml | 24 +++----- .../core/check-features-variants.sh | 13 ++++ substrate/primitives/core/src/address_uri.rs | 2 +- substrate/primitives/core/src/bandersnatch.rs | 28 ++++----- substrate/primitives/core/src/bls.rs | 31 +++------- substrate/primitives/core/src/crypto.rs | 24 +------- substrate/primitives/core/src/ecdsa.rs | 34 ++++------- substrate/primitives/core/src/ed25519.rs | 21 ++----- substrate/primitives/core/src/lib.rs | 3 - .../primitives/core/src/paired_crypto.rs | 27 +++------ substrate/primitives/core/src/sr25519.rs | 30 +++------- substrate/primitives/keyring/Cargo.toml | 7 ++- .../keyring/check-features-variants.sh | 8 +++ .../primitives/keyring/src/bandersnatch.rs | 20 +++++-- substrate/primitives/keyring/src/ed25519.rs | 12 +++- substrate/primitives/keyring/src/lib.rs | 2 + substrate/primitives/keyring/src/sr25519.rs | 20 +++++-- substrate/test-utils/runtime/Cargo.toml | 6 +- 30 files changed, 247 insertions(+), 232 deletions(-) create mode 100755 substrate/primitives/application-crypto/check-features-variants.sh create mode 100755 substrate/primitives/core/check-features-variants.sh create mode 100755 substrate/primitives/keyring/check-features-variants.sh diff --git a/.gitlab/pipeline/check.yml b/.gitlab/pipeline/check.yml index 4d71a473372..52da3355050 100644 --- a/.gitlab/pipeline/check.yml +++ b/.gitlab/pipeline/check.yml @@ -259,3 +259,19 @@ find-fail-ci-phrase: echo "No $ASSERT_REGEX was found, exiting with 0"; exit 0; fi + +check-core-crypto-features: + stage: check + extends: + - .docker-env + - .common-refs + script: + - pushd substrate/primitives/core + - ./check-features-variants.sh + - popd + - pushd substrate/primitives/application-crypto + - ./check-features-variants.sh + - popd + - pushd substrate/primitives/keyring + - ./check-features-variants.sh + - popd diff --git a/Cargo.lock b/Cargo.lock index 5eab3cf7c24..37c5a5177c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1434,9 +1434,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ - "bitcoin_hashes", - "rand", - "rand_core 0.6.4", + "bitcoin_hashes 0.11.0", "serde", "unicode-normalization", ] @@ -1456,12 +1454,28 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + [[package]] name = "bitcoin_hashes" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -6348,6 +6362,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" + [[package]] name = "hex-literal" version = "0.4.1" @@ -11411,6 +11431,19 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "parity-bip39" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" +dependencies = [ + "bitcoin_hashes 0.13.0", + "rand", + "rand_core 0.6.4", + "serde", + "unicode-normalization", +] + [[package]] name = "parity-bytes" version = "0.1.2" @@ -15662,7 +15695,6 @@ name = "sc-cli" version = "0.36.0" dependencies = [ "array-bytes 6.1.0", - "bip39", "chrono", "clap 4.5.1", "fdlimit", @@ -15672,6 +15704,7 @@ dependencies = [ "libp2p-identity", "log", "names", + "parity-bip39", "parity-scale-codec", "rand", "regex", @@ -18611,7 +18644,6 @@ version = "28.0.0" dependencies = [ "array-bytes 6.1.0", "bandersnatch_vrfs", - "bip39", "bitflags 1.3.2", "blake2 0.10.6", "bounded-collections", @@ -18629,6 +18661,7 @@ dependencies = [ "libsecp256k1", "log", "merlin", + "parity-bip39", "parity-scale-codec", "parking_lot 0.12.1", "paste", diff --git a/substrate/client/cli/Cargo.toml b/substrate/client/cli/Cargo.toml index 0582018283c..c70a0893c72 100644 --- a/substrate/client/cli/Cargo.toml +++ b/substrate/client/cli/Cargo.toml @@ -32,7 +32,8 @@ rpassword = "7.0.0" serde = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } thiserror = { workspace = true } -bip39 = "2.0.0" +# personal fork here as workaround for: https://github.com/rust-bitcoin/rust-bip39/pull/64 +bip39 = { package = "parity-bip39", version = "2.0.1", features = ["rand"] } tokio = { version = "1.22.0", features = ["parking_lot", "rt-multi-thread", "signal"] } sc-client-api = { path = "../api" } sc-client-db = { path = "../db", default-features = false } diff --git a/substrate/client/cli/src/commands/generate.rs b/substrate/client/cli/src/commands/generate.rs index c465bcc85a4..94769279e21 100644 --- a/substrate/client/cli/src/commands/generate.rs +++ b/substrate/client/cli/src/commands/generate.rs @@ -64,7 +64,7 @@ impl GenerateCmd { let password = self.keystore_params.read_password()?; let output = self.output_scheme.output_type; - let phrase = mnemonic.word_iter().join(" "); + let phrase = mnemonic.words().join(" "); with_crypto_scheme!( self.crypto_scheme.scheme, diff --git a/substrate/primitives/application-crypto/check-features-variants.sh b/substrate/primitives/application-crypto/check-features-variants.sh new file mode 100755 index 00000000000..dd45a212bae --- /dev/null +++ b/substrate/primitives/application-crypto/check-features-variants.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env -S bash -eux + +export RUSTFLAGS="-Cdebug-assertions=y -Dwarnings" +T=wasm32-unknown-unknown +cargo check --release +cargo check --release --target=$T --no-default-features +cargo check --release --target=$T --no-default-features --features="full_crypto" +cargo check --release --target=$T --no-default-features --features="serde" +cargo check --release --target=$T --no-default-features --features="serde,full_crypto" +cargo check --release --target=$T --no-default-features --features="bandersnatch-experimental" +cargo check --release --target=$T --no-default-features --features="bls-experimental" +cargo check --release --target=$T --no-default-features --features="bls-experimental,full_crypto" diff --git a/substrate/primitives/application-crypto/src/bls377.rs b/substrate/primitives/application-crypto/src/bls377.rs index ee17060564f..3bd01de139c 100644 --- a/substrate/primitives/application-crypto/src/bls377.rs +++ b/substrate/primitives/application-crypto/src/bls377.rs @@ -19,14 +19,13 @@ use crate::{KeyTypeId, RuntimePublic}; pub use sp_core::bls::bls377::*; +use sp_std::vec::Vec; mod app { crate::app_crypto!(super, sp_core::testing::BLS377); } -#[cfg(feature = "full_crypto")] -pub use app::Pair as AppPair; -pub use app::{Public as AppPublic, Signature as AppSignature}; +pub use app::{Pair as AppPair, Public as AppPublic, Signature as AppSignature}; impl RuntimePublic for Public { type Signature = Signature; diff --git a/substrate/primitives/application-crypto/src/ecdsa.rs b/substrate/primitives/application-crypto/src/ecdsa.rs index 27ffe12579f..439b51dc604 100644 --- a/substrate/primitives/application-crypto/src/ecdsa.rs +++ b/substrate/primitives/application-crypto/src/ecdsa.rs @@ -27,9 +27,7 @@ mod app { crate::app_crypto!(super, sp_core::testing::ECDSA); } -#[cfg(feature = "full_crypto")] -pub use app::Pair as AppPair; -pub use app::{Public as AppPublic, Signature as AppSignature}; +pub use app::{Pair as AppPair, Public as AppPublic, Signature as AppSignature}; impl RuntimePublic for Public { type Signature = Signature; diff --git a/substrate/primitives/application-crypto/src/ecdsa_bls377.rs b/substrate/primitives/application-crypto/src/ecdsa_bls377.rs index 70940587ced..8dee73095fb 100644 --- a/substrate/primitives/application-crypto/src/ecdsa_bls377.rs +++ b/substrate/primitives/application-crypto/src/ecdsa_bls377.rs @@ -18,6 +18,7 @@ //! ECDSA and BLS12-377 paired crypto applications. use crate::{KeyTypeId, RuntimePublic}; +use sp_std::vec::Vec; pub use sp_core::paired_crypto::ecdsa_bls377::*; diff --git a/substrate/primitives/application-crypto/src/ed25519.rs b/substrate/primitives/application-crypto/src/ed25519.rs index bc05018370e..addefe7daf6 100644 --- a/substrate/primitives/application-crypto/src/ed25519.rs +++ b/substrate/primitives/application-crypto/src/ed25519.rs @@ -27,9 +27,7 @@ mod app { crate::app_crypto!(super, sp_core::testing::ED25519); } -#[cfg(feature = "full_crypto")] -pub use app::Pair as AppPair; -pub use app::{Public as AppPublic, Signature as AppSignature}; +pub use app::{Pair as AppPair, Public as AppPublic, Signature as AppSignature}; impl RuntimePublic for Public { type Signature = Signature; diff --git a/substrate/primitives/application-crypto/src/lib.rs b/substrate/primitives/application-crypto/src/lib.rs index 686b486f335..ea2e5a83127 100644 --- a/substrate/primitives/application-crypto/src/lib.rs +++ b/substrate/primitives/application-crypto/src/lib.rs @@ -20,12 +20,9 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -pub use sp_core::crypto::{key_types, CryptoTypeId, KeyTypeId}; +pub use sp_core::crypto::{key_types, CryptoTypeId, DeriveJunction, KeyTypeId, Ss58Codec}; #[doc(hidden)] -#[cfg(feature = "full_crypto")] pub use sp_core::crypto::{DeriveError, Pair, SecretStringError}; -#[cfg(any(feature = "full_crypto", feature = "serde"))] -pub use sp_core::crypto::{DeriveJunction, Ss58Codec}; #[doc(hidden)] pub use sp_core::{ self, @@ -85,7 +82,7 @@ macro_rules! app_crypto { $module::CRYPTO_ID ); $crate::app_crypto_signature_common!($module::Signature, $key_type); - $crate::app_crypto_pair!($module::Pair, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_pair_common!($module::Pair, $key_type, $module::CRYPTO_ID); }; } @@ -116,13 +113,15 @@ macro_rules! app_crypto { $module::CRYPTO_ID ); $crate::app_crypto_signature_common!($module::Signature, $key_type); + $crate::app_crypto_pair_common!($module::Pair, $key_type, $module::CRYPTO_ID); }; } /// Declares `Pair` type which is functionally equivalent to `$pair`, but is /// new application-specific type whose identifier is `$key_type`. +/// It is a common part shared between full_crypto and non full_crypto environments. #[macro_export] -macro_rules! app_crypto_pair { +macro_rules! app_crypto_pair_common { ($pair:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap! { /// A generic `AppPublic` wrapper type over $pair crypto; this has no specific App. @@ -140,7 +139,14 @@ macro_rules! app_crypto_pair { type Signature = Signature; $crate::app_crypto_pair_functions_if_std!($pair); + $crate::app_crypto_pair_functions_if_full_crypto!($pair); + fn from_phrase( + phrase: &str, + password: Option<&str>, + ) -> Result<(Self, Self::Seed), $crate::SecretStringError> { + <$pair>::from_phrase(phrase, password).map(|r| (Self(r.0), r.1)) + } fn derive>( &self, path: Iter, @@ -154,9 +160,6 @@ macro_rules! app_crypto_pair { fn from_seed_slice(seed: &[u8]) -> Result { <$pair>::from_seed_slice(seed).map(Self) } - fn sign(&self, msg: &[u8]) -> Self::Signature { - Signature(self.0.sign(msg)) - } fn verify>( sig: &Self::Signature, message: M, @@ -203,13 +206,6 @@ macro_rules! app_crypto_pair_functions_if_std { let r = <$pair>::generate_with_phrase(password); (Self(r.0), r.1, r.2) } - - fn from_phrase( - phrase: &str, - password: Option<&str>, - ) -> Result<(Self, Self::Seed), $crate::SecretStringError> { - <$pair>::from_phrase(phrase, password).map(|r| (Self(r.0), r.1)) - } }; } @@ -220,6 +216,25 @@ macro_rules! app_crypto_pair_functions_if_std { ($pair:ty) => {}; } +/// Implements functions for the `Pair` trait when `feature = "full_crypto"` is enabled. +#[doc(hidden)] +#[cfg(feature = "full_crypto")] +#[macro_export] +macro_rules! app_crypto_pair_functions_if_full_crypto { + ($pair:ty) => { + fn sign(&self, msg: &[u8]) -> Self::Signature { + Signature(self.0.sign(msg)) + } + }; +} + +#[doc(hidden)] +#[cfg(not(feature = "full_crypto"))] +#[macro_export] +macro_rules! app_crypto_pair_functions_if_full_crypto { + ($pair:ty) => {}; +} + /// Declares `Public` type which is functionally equivalent to `$public` but is /// new application-specific type whose identifier is `$key_type`. /// For full functionality, `app_crypto_public_common!` must be called too. @@ -267,7 +282,7 @@ macro_rules! app_crypto_public_not_full_crypto { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( - Clone, Eq, PartialEq, Ord, PartialOrd, + Clone, Eq, Hash, PartialEq, Ord, PartialOrd, $crate::codec::Encode, $crate::codec::Decode, $crate::RuntimeDebug, @@ -277,10 +292,13 @@ macro_rules! app_crypto_public_not_full_crypto { pub struct Public($public); } - impl $crate::CryptoType for Public {} + impl $crate::CryptoType for Public { + type Pair = Pair; + } impl $crate::AppCrypto for Public { type Public = Public; + type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; @@ -452,10 +470,13 @@ macro_rules! app_crypto_signature_not_full_crypto { pub struct Signature($sig); } - impl $crate::CryptoType for Signature {} + impl $crate::CryptoType for Signature { + type Pair = Pair; + } impl $crate::AppCrypto for Signature { type Public = Public; + type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; diff --git a/substrate/primitives/application-crypto/src/sr25519.rs b/substrate/primitives/application-crypto/src/sr25519.rs index 7c91bfa7bb5..d411cc253c0 100644 --- a/substrate/primitives/application-crypto/src/sr25519.rs +++ b/substrate/primitives/application-crypto/src/sr25519.rs @@ -27,9 +27,7 @@ mod app { crate::app_crypto!(super, sp_core::testing::SR25519); } -#[cfg(feature = "full_crypto")] -pub use app::Pair as AppPair; -pub use app::{Public as AppPublic, Signature as AppSignature}; +pub use app::{Pair as AppPair, Public as AppPublic, Signature as AppSignature}; impl RuntimePublic for Public { type Signature = Signature; diff --git a/substrate/primitives/application-crypto/src/traits.rs b/substrate/primitives/application-crypto/src/traits.rs index e9b1080f63d..0b59abf272d 100644 --- a/substrate/primitives/application-crypto/src/traits.rs +++ b/substrate/primitives/application-crypto/src/traits.rs @@ -18,9 +18,7 @@ use codec::Codec; use scale_info::TypeInfo; -#[cfg(feature = "full_crypto")] -use sp_core::crypto::Pair; -use sp_core::crypto::{CryptoType, CryptoTypeId, IsWrappedBy, KeyTypeId, Public}; +use sp_core::crypto::{CryptoType, CryptoTypeId, IsWrappedBy, KeyTypeId, Pair, Public}; use sp_std::{fmt::Debug, vec::Vec}; /// Application-specific cryptographic object. @@ -45,24 +43,14 @@ pub trait AppCrypto: 'static + Sized + CryptoType { type Signature: AppSignature; /// The corresponding key pair type in this application scheme. - #[cfg(feature = "full_crypto")] type Pair: AppPair; } /// Type which implements Hash in std, not when no-std (std variant). -#[cfg(any(feature = "std", feature = "full_crypto"))] pub trait MaybeHash: sp_std::hash::Hash {} -#[cfg(any(feature = "std", feature = "full_crypto"))] impl MaybeHash for T {} -/// Type which implements Hash in std, not when no-std (no-std variant). -#[cfg(all(not(feature = "std"), not(feature = "full_crypto")))] -pub trait MaybeHash {} -#[cfg(all(not(feature = "std"), not(feature = "full_crypto")))] -impl MaybeHash for T {} - /// Application-specific key pair. -#[cfg(feature = "full_crypto")] pub trait AppPair: AppCrypto + Pair::Public, Signature = ::Signature> { diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml index f7cc2b4fcf7..908f2498de5 100644 --- a/substrate/primitives/core/Cargo.toml +++ b/substrate/primitives/core/Cargo.toml @@ -27,10 +27,11 @@ hash-db = { version = "0.16.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } bs58 = { version = "0.5.0", default-features = false, optional = true } rand = { version = "0.8.5", features = ["small_rng"], optional = true } -substrate-bip39 = { path = "../../utils/substrate-bip39", optional = true } -bip39 = { version = "2.0.0", default-features = false } +substrate-bip39 = { path = "../../utils/substrate-bip39", default-features = false } +# personal fork here as workaround for: https://github.com/rust-bitcoin/rust-bip39/pull/64 +bip39 = { package = "parity-bip39", version = "2.0.1", default-features = false, features = ["alloc"] } zeroize = { version = "1.4.3", default-features = false } -secrecy = { version = "0.8.0", default-features = false } +secrecy = { version = "0.8.0", default-features = false, features = ["alloc"] } parking_lot = { version = "0.12.1", optional = true } ss58-registry = { version = "1.34.0", default-features = false } sp-std = { path = "../std", default-features = false } @@ -46,13 +47,13 @@ paste = "1.0.7" itertools = { version = "0.10.3", optional = true } # full crypto -array-bytes = { version = "6.1", optional = true } -ed25519-zebra = { version = "3.1.0", default-features = false, optional = true } +array-bytes = { version = "6.1" } +ed25519-zebra = { version = "3.1.0", default-features = false } blake2 = { version = "0.10.4", default-features = false, optional = true } -libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context"], optional = true } +libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context"] } schnorrkel = { version = "0.11.4", features = ["preaudit_deprecated"], default-features = false } merlin = { version = "3.0", default-features = false } -sp-crypto-hashing = { path = "../crypto/hashing", default-features = false, optional = true } +sp-crypto-hashing = { path = "../crypto/hashing", default-features = false } sp-runtime-interface = { path = "../runtime-interface", default-features = false } # k256 crate, better portability, intended to be used in substrate-runtimes (no-std) k256 = { version = "0.13.3", features = ["alloc", "ecdsa"], default-features = false } @@ -81,7 +82,6 @@ bench = false default = ["std"] std = [ - "array-bytes", "bandersnatch_vrfs?/std", "bip39/rand", "bip39/std", @@ -112,7 +112,6 @@ std = [ "schnorrkel/std", "secp256k1/global-context", "secp256k1/std", - "secrecy/alloc", "serde/std", "sp-crypto-hashing/std", "sp-debug-derive/std", @@ -131,7 +130,6 @@ std = [ # Serde support without relying on std features. serde = [ - "array-bytes", "blake2", "bounded-collections/serde", "bs58/alloc", @@ -140,8 +138,6 @@ serde = [ "k256/serde", "primitive-types/serde_no_std", "scale-info/serde", - "secrecy/alloc", - "sp-crypto-hashing", "sp-storage/serde", ] @@ -149,11 +145,7 @@ serde = [ # or Intel SGX. # For the regular wasm runtime builds this should not be used. full_crypto = [ - "array-bytes", "blake2", - "ed25519-zebra", - "libsecp256k1", - "sp-crypto-hashing", "sp-runtime-interface/disable_target_static_assertions", ] diff --git a/substrate/primitives/core/check-features-variants.sh b/substrate/primitives/core/check-features-variants.sh new file mode 100755 index 00000000000..6d28212065a --- /dev/null +++ b/substrate/primitives/core/check-features-variants.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env -S bash -eux + +export RUSTFLAGS="-Cdebug-assertions=y -Dwarnings" +T=wasm32-unknown-unknown + +cargo check --target=$T --release --no-default-features --features="bls-experimental" +cargo check --target=$T --release --no-default-features --features="full_crypto,bls-experimental" +cargo check --target=$T --release --no-default-features --features="bandersnatch-experimental" +cargo check --target=$T --release --no-default-features --features="full_crypto,serde,bandersnatch-experimental" +cargo check --target=$T --release --no-default-features --features="full_crypto,serde" +cargo check --target=$T --release --no-default-features --features="full_crypto" +cargo check --target=$T --release --no-default-features --features="serde" +cargo check --target=$T --release --no-default-features diff --git a/substrate/primitives/core/src/address_uri.rs b/substrate/primitives/core/src/address_uri.rs index 211d47c0093..2e32d0cd86d 100644 --- a/substrate/primitives/core/src/address_uri.rs +++ b/substrate/primitives/core/src/address_uri.rs @@ -17,7 +17,7 @@ //! Little util for parsing an address URI. Replaces regular expressions. -#[cfg(all(not(feature = "std"), any(feature = "serde", feature = "full_crypto")))] +#[cfg(not(feature = "std"))] use sp_std::{ alloc::string::{String, ToString}, vec::Vec, diff --git a/substrate/primitives/core/src/bandersnatch.rs b/substrate/primitives/core/src/bandersnatch.rs index 61e7162544a..5cae6047f16 100644 --- a/substrate/primitives/core/src/bandersnatch.rs +++ b/substrate/primitives/core/src/bandersnatch.rs @@ -22,19 +22,18 @@ #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; +#[cfg(feature = "full_crypto")] +use crate::crypto::VrfSecret; use crate::crypto::{ - ByteArray, CryptoType, CryptoTypeId, Derive, Public as TraitPublic, UncheckedFrom, VrfPublic, + ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, + Public as TraitPublic, SecretStringError, UncheckedFrom, VrfPublic, }; -#[cfg(feature = "full_crypto")] -use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError, VrfSecret}; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; -use bandersnatch_vrfs::CanonicalSerialize; -#[cfg(feature = "full_crypto")] -use bandersnatch_vrfs::SecretKey; +use bandersnatch_vrfs::{CanonicalSerialize, SecretKey}; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; use scale_info::TypeInfo; @@ -45,10 +44,8 @@ use sp_std::{vec, vec::Vec}; pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"band"); /// Context used to produce a plain signature without any VRF input/output. -#[cfg(feature = "full_crypto")] pub const SIGNING_CTX: &[u8] = b"BandersnatchSigningContext"; -#[cfg(feature = "full_crypto")] const SEED_SERIALIZED_SIZE: usize = 32; const PUBLIC_SERIALIZED_SIZE: usize = 33; @@ -56,7 +53,6 @@ const SIGNATURE_SERIALIZED_SIZE: usize = 65; const PREOUT_SERIALIZED_SIZE: usize = 33; /// Bandersnatch public key. -#[cfg_attr(feature = "full_crypto", derive(Hash))] #[derive( Clone, Copy, @@ -69,6 +65,7 @@ const PREOUT_SERIALIZED_SIZE: usize = 33; PassByInner, MaxEncodedLen, TypeInfo, + Hash, )] pub struct Public(pub [u8; PUBLIC_SERIALIZED_SIZE]); @@ -116,7 +113,6 @@ impl ByteArray for Public { impl TraitPublic for Public {} impl CryptoType for Public { - #[cfg(feature = "full_crypto")] type Pair = Pair; } @@ -154,8 +150,9 @@ impl<'de> Deserialize<'de> for Public { /// /// The signature is created via the [`VrfSecret::vrf_sign`] using [`SIGNING_CTX`] as transcript /// `label`. -#[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo)] +#[derive( + Clone, Copy, PartialEq, Eq, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo, Hash, +)] pub struct Signature([u8; SIGNATURE_SERIALIZED_SIZE]); impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { @@ -194,7 +191,6 @@ impl ByteArray for Signature { } impl CryptoType for Signature { - #[cfg(feature = "full_crypto")] type Pair = Pair; } @@ -211,18 +207,15 @@ impl sp_std::fmt::Debug for Signature { } /// The raw secret seed, which can be used to reconstruct the secret [`Pair`]. -#[cfg(feature = "full_crypto")] type Seed = [u8; SEED_SERIALIZED_SIZE]; /// Bandersnatch secret key. -#[cfg(feature = "full_crypto")] #[derive(Clone)] pub struct Pair { secret: SecretKey, seed: Seed, } -#[cfg(feature = "full_crypto")] impl Pair { /// Get the key seed. pub fn seed(&self) -> Seed { @@ -230,7 +223,6 @@ impl Pair { } } -#[cfg(feature = "full_crypto")] impl TraitPair for Pair { type Seed = Seed; type Public = Public; @@ -287,6 +279,7 @@ impl TraitPair for Pair { /// the constant label [`SIGNING_CTX`] and `data` without any additional data. /// /// See [`vrf::VrfSignData`] for additional details. + #[cfg(feature = "full_crypto")] fn sign(&self, data: &[u8]) -> Signature { let data = vrf::VrfSignData::new_unchecked(SIGNING_CTX, &[data], None); self.vrf_sign(&data).signature @@ -305,7 +298,6 @@ impl TraitPair for Pair { } } -#[cfg(feature = "full_crypto")] impl CryptoType for Pair { type Pair = Pair; } diff --git a/substrate/primitives/core/src/bls.rs b/substrate/primitives/core/src/bls.rs index 0c84d0ba8e6..2256e4cd823 100644 --- a/substrate/primitives/core/src/bls.rs +++ b/substrate/primitives/core/src/bls.rs @@ -25,11 +25,11 @@ #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; -use crate::crypto::{ByteArray, CryptoType, Derive, Public as TraitPublic, UncheckedFrom}; -#[cfg(feature = "full_crypto")] -use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; +use crate::crypto::{ + ByteArray, CryptoType, Derive, DeriveError, DeriveJunction, Pair as TraitPair, + Public as TraitPublic, SecretStringError, UncheckedFrom, +}; -#[cfg(feature = "full_crypto")] use sp_std::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; @@ -40,9 +40,10 @@ use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; -use w3f_bls::{DoublePublicKey, DoubleSignature, EngineBLS, SerializableToBytes, TinyBLS381}; -#[cfg(feature = "full_crypto")] -use w3f_bls::{DoublePublicKeyScheme, Keypair, Message, SecretKey}; +use w3f_bls::{ + DoublePublicKey, DoublePublicKeyScheme, DoubleSignature, EngineBLS, Keypair, Message, + SecretKey, SerializableToBytes, TinyBLS381, +}; use sp_runtime_interface::pass_by::{self, PassBy, PassByInner}; use sp_std::{convert::TryFrom, marker::PhantomData, ops::Deref}; @@ -57,7 +58,6 @@ pub mod bls377 { pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"bls7"); /// BLS12-377 key pair. - #[cfg(feature = "full_crypto")] pub type Pair = super::Pair; /// BLS12-377 public key. pub type Public = super::Public; @@ -79,7 +79,6 @@ pub mod bls381 { pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"bls8"); /// BLS12-381 key pair. - #[cfg(feature = "full_crypto")] pub type Pair = super::Pair; /// BLS12-381 public key. pub type Public = super::Public; @@ -96,7 +95,6 @@ trait BlsBound: EngineBLS + HardJunctionId + Send + Sync + 'static {} impl BlsBound for T {} /// Secret key serialized size -#[cfg(feature = "full_crypto")] const SECRET_KEY_SERIALIZED_SIZE: usize = as SerializableToBytes>::SERIALIZED_BYTES_SIZE; @@ -113,7 +111,6 @@ pub const SIGNATURE_SERIALIZED_SIZE: usize = /// It's not called a "secret key" because ring doesn't expose the secret keys /// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we /// will need it later (such as for HDKD). -#[cfg(feature = "full_crypto")] type Seed = [u8; SECRET_KEY_SERIALIZED_SIZE]; /// A public key. @@ -150,7 +147,6 @@ impl Ord for Public { } } -#[cfg(feature = "full_crypto")] impl sp_std::hash::Hash for Public { fn hash(&self, state: &mut H) { self.inner.hash(state) @@ -226,7 +222,6 @@ impl From> for [u8; PUBLIC_KEY_SERIALIZED_SIZE] { } } -#[cfg(feature = "full_crypto")] impl From> for Public { fn from(x: Pair) -> Self { x.public() @@ -296,7 +291,6 @@ impl TraitPublic for Public {} impl Derive for Public {} impl CryptoType for Public { - #[cfg(feature = "full_crypto")] type Pair = Pair; } @@ -322,7 +316,6 @@ impl PartialEq for Signature { impl Eq for Signature {} -#[cfg(feature = "full_crypto")] impl sp_std::hash::Hash for Signature { fn hash(&self, state: &mut H) { self.inner.hash(state) @@ -412,15 +405,12 @@ impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { } impl CryptoType for Signature { - #[cfg(feature = "full_crypto")] type Pair = Pair; } /// A key pair. -#[cfg(feature = "full_crypto")] pub struct Pair(Keypair); -#[cfg(feature = "full_crypto")] impl Clone for Pair { fn clone(&self) -> Self { Pair(self.0.clone()) @@ -432,15 +422,12 @@ trait HardJunctionId { } /// Derive a single hard junction. -#[cfg(feature = "full_crypto")] fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { (T::ID, secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } -#[cfg(feature = "full_crypto")] impl Pair {} -#[cfg(feature = "full_crypto")] impl TraitPair for Pair { type Seed = Seed; type Public = Public; @@ -480,6 +467,7 @@ impl TraitPair for Pair { Self::Public::unchecked_from(raw) } + #[cfg(feature = "full_crypto")] fn sign(&self, message: &[u8]) -> Self::Signature { let mut mutable_self = self.clone(); let r: [u8; SIGNATURE_SERIALIZED_SIZE] = @@ -523,7 +511,6 @@ impl TraitPair for Pair { } } -#[cfg(feature = "full_crypto")] impl CryptoType for Pair { type Pair = Pair; } diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs index 2a8be2a2ba8..fab865d8c1f 100644 --- a/substrate/primitives/core/src/crypto.rs +++ b/substrate/primitives/core/src/crypto.rs @@ -18,7 +18,6 @@ //! Cryptographic utilities. use crate::{ed25519, sr25519}; -#[cfg(feature = "std")] use bip39::{Language, Mnemonic}; use codec::{Decode, Encode, MaxEncodedLen}; #[cfg(feature = "std")] @@ -26,7 +25,6 @@ use itertools::Itertools; #[cfg(feature = "std")] use rand::{rngs::OsRng, RngCore}; use scale_info::TypeInfo; -#[cfg(feature = "std")] pub use secrecy::{ExposeSecret, SecretString}; use sp_runtime_interface::pass_by::PassByInner; #[doc(hidden)] @@ -41,10 +39,7 @@ pub use ss58_registry::{from_known_address_format, Ss58AddressFormat, Ss58Addres /// Trait to zeroize a memory buffer. pub use zeroize::Zeroize; -#[cfg(feature = "std")] -pub use crate::address_uri::AddressUri; -#[cfg(any(feature = "std", feature = "full_crypto"))] -pub use crate::address_uri::Error as AddressUriError; +pub use crate::address_uri::{AddressUri, Error as AddressUriError}; /// The root phrase for our publicly known keys. pub const DEV_PHRASE: &str = @@ -82,7 +77,6 @@ impl> UncheckedInto for S { /// An error with the interpretation of a secret. #[cfg_attr(feature = "std", derive(thiserror::Error))] #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg(feature = "full_crypto")] pub enum SecretStringError { /// The overall format was invalid (e.g. the seed phrase contained symbols). #[cfg_attr(feature = "std", error("Invalid format {0}"))] @@ -104,7 +98,6 @@ pub enum SecretStringError { InvalidPath, } -#[cfg(any(feature = "std", feature = "full_crypto"))] impl From for SecretStringError { fn from(e: AddressUriError) -> Self { Self::InvalidFormat(e) @@ -114,7 +107,6 @@ impl From for SecretStringError { /// An error when deriving a key. #[cfg_attr(feature = "std", derive(thiserror::Error))] #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg(feature = "full_crypto")] pub enum DeriveError { /// A soft key was found in the path (and is unsupported). #[cfg_attr(feature = "std", error("Soft key in path"))] @@ -125,7 +117,6 @@ pub enum DeriveError { /// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex` /// a new public key from an existing public key. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)] -#[cfg(any(feature = "full_crypto", feature = "serde"))] pub enum DeriveJunction { /// Soft (vanilla) derivation. Public keys have a correspondent derivation. Soft([u8; JUNCTION_ID_LEN]), @@ -133,7 +124,6 @@ pub enum DeriveJunction { Hard([u8; JUNCTION_ID_LEN]), } -#[cfg(any(feature = "full_crypto", feature = "serde"))] impl DeriveJunction { /// Consume self to return a soft derive junction with the same chain code. pub fn soften(self) -> Self { @@ -192,7 +182,6 @@ impl DeriveJunction { } } -#[cfg(any(feature = "full_crypto", feature = "serde"))] impl> From for DeriveJunction { fn from(j: T) -> DeriveJunction { let j = j.as_ref(); @@ -812,7 +801,6 @@ mod dummy { /// assert_eq!("0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a", suri.phrase.expose_secret()); /// assert!(suri.password.is_none()); /// ``` -#[cfg(feature = "std")] pub struct SecretUri { /// The phrase to derive the private key. /// @@ -824,7 +812,6 @@ pub struct SecretUri { pub junctions: Vec, } -#[cfg(feature = "std")] impl sp_std::str::FromStr for SecretUri { type Err = SecretStringError; @@ -845,7 +832,6 @@ impl sp_std::str::FromStr for SecretUri { /// Trait suitable for typical cryptographic PKI key pair type. /// /// For now it just specifies how to create a key from a phrase and derivation path. -#[cfg(feature = "full_crypto")] pub trait Pair: CryptoType + Sized { /// The type which is used to encode a public key. type Public: Public + Hash; @@ -878,21 +864,19 @@ pub trait Pair: CryptoType + Sized { #[cfg(feature = "std")] fn generate_with_phrase(password: Option<&str>) -> (Self, String, Self::Seed) { let mnemonic = Mnemonic::generate(12).expect("Mnemonic generation always works; qed"); - let phrase = mnemonic.word_iter().join(" "); + let phrase = mnemonic.words().join(" "); let (pair, seed) = Self::from_phrase(&phrase, password) .expect("All phrases generated by Mnemonic are valid; qed"); (pair, phrase.to_owned(), seed) } /// Returns the KeyPair from the English BIP39 seed `phrase`, or an error if it's invalid. - #[cfg(feature = "std")] fn from_phrase( phrase: &str, password: Option<&str>, ) -> Result<(Self, Self::Seed), SecretStringError> { let mnemonic = Mnemonic::parse_in(Language::English, phrase) .map_err(|_| SecretStringError::InvalidPhrase)?; - let (entropy, entropy_len) = mnemonic.to_entropy_array(); let big_seed = substrate_bip39::seed_from_entropy(&entropy[0..entropy_len], password.unwrap_or("")) @@ -928,6 +912,7 @@ pub trait Pair: CryptoType + Sized { fn from_seed_slice(seed: &[u8]) -> Result; /// Sign a message. + #[cfg(feature = "full_crypto")] fn sign(&self, message: &[u8]) -> Self::Signature; /// Verify a signature on a message. Returns true if the signature is good. @@ -962,7 +947,6 @@ pub trait Pair: CryptoType + Sized { /// Notably, integer junction indices may be legally prefixed with arbitrary number of zeros. /// Similarly an empty password (ending the SURI with `///`) is perfectly valid and will /// generally be equivalent to no password at all. - #[cfg(feature = "std")] fn from_string_with_seed( s: &str, password_override: Option<&str>, @@ -996,7 +980,6 @@ pub trait Pair: CryptoType + Sized { /// Interprets the string `s` in order to generate a key pair. /// /// See [`from_string_with_seed`](Pair::from_string_with_seed) for more extensive documentation. - #[cfg(feature = "std")] fn from_string(s: &str, password_override: Option<&str>) -> Result { Self::from_string_with_seed(s, password_override).map(|x| x.0) } @@ -1054,7 +1037,6 @@ where /// Type which has a particular kind of crypto associated with it. pub trait CryptoType { /// The pair key type of this crypto. - #[cfg(feature = "full_crypto")] type Pair: Pair; } diff --git a/substrate/primitives/core/src/ecdsa.rs b/substrate/primitives/core/src/ecdsa.rs index e6bd2c7eb57..fa071e1b03f 100644 --- a/substrate/primitives/core/src/ecdsa.rs +++ b/substrate/primitives/core/src/ecdsa.rs @@ -24,16 +24,13 @@ use sp_runtime_interface::pass_by::PassByInner; #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ - ByteArray, CryptoType, CryptoTypeId, Derive, Public as TraitPublic, UncheckedFrom, + ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, + Public as TraitPublic, SecretStringError, UncheckedFrom, }; -#[cfg(feature = "full_crypto")] -use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; -#[cfg(all(not(feature = "std"), feature = "full_crypto"))] -use k256::ecdsa::SigningKey as SecretKey; #[cfg(not(feature = "std"))] -use k256::ecdsa::VerifyingKey; -#[cfg(all(feature = "std", feature = "full_crypto"))] +use k256::ecdsa::{SigningKey as SecretKey, VerifyingKey}; +#[cfg(feature = "std")] use secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, Message, PublicKey, SecretKey, SECP256K1, @@ -42,7 +39,7 @@ use secp256k1::{ use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; -#[cfg(feature = "full_crypto")] +#[cfg(not(feature = "std"))] use sp_std::vec::Vec; /// An identifier used to match public keys against ecdsa keys @@ -57,11 +54,9 @@ pub const SIGNATURE_SERIALIZED_SIZE: usize = 65; /// The secret seed. /// /// The raw secret seed, which can be used to create the `Pair`. -#[cfg(feature = "full_crypto")] type Seed = [u8; 32]; /// The ECDSA compressed public key. -#[cfg_attr(feature = "full_crypto", derive(Hash))] #[derive( Clone, Copy, @@ -74,6 +69,7 @@ type Seed = [u8; 32]; PartialEq, PartialOrd, Ord, + Hash, )] pub struct Public(pub [u8; PUBLIC_KEY_SERIALIZED_SIZE]); @@ -221,8 +217,7 @@ impl<'de> Deserialize<'de> for Public { } /// A signature (a 512-bit value, plus 8 bits for recovery ID). -#[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] +#[derive(Hash, Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] pub struct Signature(pub [u8; SIGNATURE_SERIALIZED_SIZE]); impl ByteArray for Signature { @@ -345,13 +340,11 @@ impl Signature { } /// Recover the public key from this signature and a message. - #[cfg(feature = "full_crypto")] pub fn recover>(&self, message: M) -> Option { self.recover_prehashed(&sp_crypto_hashing::blake2_256(message.as_ref())) } /// Recover the public key from this signature and a pre-hashed message. - #[cfg(feature = "full_crypto")] pub fn recover_prehashed(&self, message: &[u8; 32]) -> Option { #[cfg(feature = "std")] { @@ -380,7 +373,7 @@ impl From<(k256::ecdsa::Signature, k256::ecdsa::RecoveryId)> for Signature { } } -#[cfg(all(feature = "std", feature = "full_crypto"))] +#[cfg(feature = "std")] impl From for Signature { fn from(recsig: RecoverableSignature) -> Signature { let mut r = Self::default(); @@ -393,20 +386,17 @@ impl From for Signature { } /// Derive a single hard junction. -#[cfg(feature = "full_crypto")] fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { ("Secp256k1HDKD", secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } /// A key pair. -#[cfg(feature = "full_crypto")] #[derive(Clone)] pub struct Pair { public: Public, secret: SecretKey, } -#[cfg(feature = "full_crypto")] impl TraitPair for Pair { type Public = Public; type Seed = Seed; @@ -454,6 +444,7 @@ impl TraitPair for Pair { } /// Sign a message. + #[cfg(feature = "full_crypto")] fn sign(&self, message: &[u8]) -> Signature { self.sign_prehashed(&sp_crypto_hashing::blake2_256(message)) } @@ -469,7 +460,6 @@ impl TraitPair for Pair { } } -#[cfg(feature = "full_crypto")] impl Pair { /// Get the seed for this key. pub fn seed(&self) -> Seed { @@ -496,6 +486,7 @@ impl Pair { } /// Sign a pre-hashed message + #[cfg(feature = "full_crypto")] pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature { #[cfg(feature = "std")] { @@ -550,7 +541,7 @@ impl Pair { // NOTE: this solution is not effective when `Pair` is moved around memory. // The very same problem affects other cryptographic backends that are just using // `zeroize`for their secrets. -#[cfg(all(feature = "std", feature = "full_crypto"))] +#[cfg(feature = "std")] impl Drop for Pair { fn drop(&mut self) { self.secret.non_secure_erase() @@ -558,16 +549,13 @@ impl Drop for Pair { } impl CryptoType for Public { - #[cfg(feature = "full_crypto")] type Pair = Pair; } impl CryptoType for Signature { - #[cfg(feature = "full_crypto")] type Pair = Pair; } -#[cfg(feature = "full_crypto")] impl CryptoType for Pair { type Pair = Pair; } diff --git a/substrate/primitives/core/src/ed25519.rs b/substrate/primitives/core/src/ed25519.rs index 60ebd93e12d..9f42b36dc8b 100644 --- a/substrate/primitives/core/src/ed25519.rs +++ b/substrate/primitives/core/src/ed25519.rs @@ -19,7 +19,6 @@ //! Simple Ed25519 API. // end::description[] -#[cfg(feature = "full_crypto")] use sp_std::vec::Vec; use crate::{ @@ -32,13 +31,11 @@ use scale_info::TypeInfo; #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ - CryptoType, CryptoTypeId, Derive, FromEntropy, Public as TraitPublic, UncheckedFrom, + CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, FromEntropy, Pair as TraitPair, + Public as TraitPublic, SecretStringError, UncheckedFrom, }; #[cfg(feature = "full_crypto")] -use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; -#[cfg(feature = "full_crypto")] use core::convert::TryFrom; -#[cfg(feature = "full_crypto")] use ed25519_zebra::{SigningKey, VerificationKey}; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -53,11 +50,9 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ed25"); /// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys /// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we /// will need it later (such as for HDKD). -#[cfg(feature = "full_crypto")] type Seed = [u8; 32]; /// A public key. -#[cfg_attr(feature = "full_crypto", derive(Hash))] #[derive( PartialEq, Eq, @@ -70,11 +65,11 @@ type Seed = [u8; 32]; PassByInner, MaxEncodedLen, TypeInfo, + Hash, )] pub struct Public(pub [u8; 32]); /// A key pair. -#[cfg(feature = "full_crypto")] #[derive(Copy, Clone)] pub struct Pair { public: VerificationKey, @@ -210,8 +205,7 @@ impl<'de> Deserialize<'de> for Public { } /// A signature (a 512-bit value). -#[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] +#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq, Hash)] pub struct Signature(pub [u8; 64]); impl TryFrom<&[u8]> for Signature { @@ -370,12 +364,10 @@ impl TraitPublic for Public {} impl Derive for Public {} /// Derive a single hard junction. -#[cfg(feature = "full_crypto")] fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { ("Ed25519HDKD", secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } -#[cfg(feature = "full_crypto")] impl TraitPair for Pair { type Public = Public; type Seed = Seed; @@ -414,6 +406,7 @@ impl TraitPair for Pair { } /// Sign a message. + #[cfg(feature = "full_crypto")] fn sign(&self, message: &[u8]) -> Signature { Signature::from_raw(self.secret.sign(message).into()) } @@ -433,7 +426,6 @@ impl TraitPair for Pair { } } -#[cfg(feature = "full_crypto")] impl Pair { /// Get the seed for this key. pub fn seed(&self) -> Seed { @@ -454,16 +446,13 @@ impl Pair { } impl CryptoType for Public { - #[cfg(feature = "full_crypto")] type Pair = Pair; } impl CryptoType for Signature { - #[cfg(feature = "full_crypto")] type Pair = Pair; } -#[cfg(feature = "full_crypto")] impl CryptoType for Pair { type Pair = Pair; } diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs index 0d43eea9962..c0b41234460 100644 --- a/substrate/primitives/core/src/lib.rs +++ b/substrate/primitives/core/src/lib.rs @@ -46,7 +46,6 @@ pub use sp_debug_derive::RuntimeDebug; #[cfg(feature = "serde")] pub use impl_serde::serialize as bytes; -#[cfg(feature = "full_crypto")] #[deprecated( since = "27.0.0", note = "`sp-crypto-hashing` re-exports will be removed after June 2024. Use `sp-crypto-hashing` instead." @@ -58,7 +57,6 @@ pub mod crypto; pub mod hexdisplay; pub use paste; -#[cfg(any(feature = "full_crypto", feature = "std"))] mod address_uri; #[cfg(feature = "bandersnatch-experimental")] pub mod bandersnatch; @@ -87,7 +85,6 @@ pub use self::{ hash::{convert_hash, H160, H256, H512}, uint::{U256, U512}, }; -#[cfg(feature = "full_crypto")] pub use crypto::{ByteArray, DeriveJunction, Pair, Public}; #[cfg(feature = "std")] diff --git a/substrate/primitives/core/src/paired_crypto.rs b/substrate/primitives/core/src/paired_crypto.rs index 20b32c339bd..6d2e6ddf334 100644 --- a/substrate/primitives/core/src/paired_crypto.rs +++ b/substrate/primitives/core/src/paired_crypto.rs @@ -19,11 +19,11 @@ #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; -use crate::crypto::{ByteArray, CryptoType, Derive, Public as PublicT, UncheckedFrom}; -#[cfg(feature = "full_crypto")] -use crate::crypto::{DeriveError, DeriveJunction, Pair as PairT, SecretStringError}; +use crate::crypto::{ + ByteArray, CryptoType, Derive, DeriveError, DeriveJunction, Pair as PairT, Public as PublicT, + SecretStringError, UncheckedFrom, +}; -#[cfg(feature = "full_crypto")] use sp_std::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; @@ -39,12 +39,11 @@ use sp_std::convert::TryFrom; /// ECDSA and BLS12-377 paired crypto scheme #[cfg(feature = "bls-experimental")] pub mod ecdsa_bls377 { + use crate::{bls377, crypto::CryptoTypeId, ecdsa}; #[cfg(feature = "full_crypto")] - use crate::Hasher; use crate::{ - bls377, - crypto::{CryptoTypeId, Pair as PairT, UncheckedFrom}, - ecdsa, + crypto::{Pair as PairT, UncheckedFrom}, + Hasher, }; /// An identifier used to match public keys against BLS12-377 keys @@ -56,7 +55,6 @@ pub mod ecdsa_bls377 { ecdsa::SIGNATURE_SERIALIZED_SIZE + bls377::SIGNATURE_SERIALIZED_SIZE; /// (ECDSA,BLS12-377) key-pair pair. - #[cfg(feature = "full_crypto")] pub type Pair = super::Pair; /// (ECDSA,BLS12-377) public key pair. pub type Public = super::Public; @@ -64,16 +62,13 @@ pub mod ecdsa_bls377 { pub type Signature = super::Signature; impl super::CryptoType for Public { - #[cfg(feature = "full_crypto")] type Pair = Pair; } impl super::CryptoType for Signature { - #[cfg(feature = "full_crypto")] type Pair = Pair; } - #[cfg(feature = "full_crypto")] impl super::CryptoType for Pair { type Pair = Pair; } @@ -136,7 +131,6 @@ pub mod ecdsa_bls377 { /// Secure seed length. /// /// Currently only supporting sub-schemes whose seed is a 32-bytes array. -#[cfg(feature = "full_crypto")] const SECURE_SEED_LEN: usize = 32; /// A secret seed. @@ -144,14 +138,12 @@ const SECURE_SEED_LEN: usize = 32; /// It's not called a "secret key" because ring doesn't expose the secret keys /// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we /// will need it later (such as for HDKD). -#[cfg(feature = "full_crypto")] type Seed = [u8; SECURE_SEED_LEN]; /// A public key. #[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, PartialOrd, Ord)] pub struct Public([u8; LEFT_PLUS_RIGHT_LEN]); -#[cfg(feature = "full_crypto")] impl sp_std::hash::Hash for Public { fn hash(&self, state: &mut H) { self.0.hash(state); @@ -215,7 +207,6 @@ impl PassBy for Public { type PassBy = pass_by::Inner; } -#[cfg(feature = "full_crypto")] impl< LeftPair: PairT, RightPair: PairT, @@ -311,7 +302,6 @@ impl SignatureBound for T {} #[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq)] pub struct Signature([u8; LEFT_PLUS_RIGHT_LEN]); -#[cfg(feature = "full_crypto")] impl sp_std::hash::Hash for Signature { fn hash(&self, state: &mut H) { self.0.hash(state); @@ -411,7 +401,6 @@ impl UncheckedFrom<[u8; LEFT_PLUS_RIGHT_LEN]> } /// A key pair. -#[cfg(feature = "full_crypto")] #[derive(Clone)] pub struct Pair< LeftPair: PairT, @@ -423,7 +412,6 @@ pub struct Pair< right: RightPair, } -#[cfg(feature = "full_crypto")] impl< LeftPair: PairT, RightPair: PairT, @@ -483,6 +471,7 @@ where Self::Public::unchecked_from(raw) } + #[cfg(feature = "full_crypto")] fn sign(&self, message: &[u8]) -> Self::Signature { let mut raw: [u8; SIGNATURE_LEN] = [0u8; SIGNATURE_LEN]; raw[..LeftPair::Signature::LEN].copy_from_slice(self.left.sign(message).as_ref()); diff --git a/substrate/primitives/core/src/sr25519.rs b/substrate/primitives/core/src/sr25519.rs index 7c02afc3cd5..6c04eb8def1 100644 --- a/substrate/primitives/core/src/sr25519.rs +++ b/substrate/primitives/core/src/sr25519.rs @@ -19,20 +19,14 @@ //! //! Note: `CHAIN_CODE_LENGTH` must be equal to `crate::crypto::JUNCTION_ID_LEN` //! for this to work. -#[cfg(any(feature = "full_crypto", feature = "serde"))] -use crate::crypto::DeriveJunction; #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; +use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; #[cfg(feature = "full_crypto")] -use crate::crypto::{DeriveError, Pair as TraitPair, SecretStringError}; -#[cfg(feature = "full_crypto")] -use schnorrkel::{ - derive::CHAIN_CODE_LENGTH, signing_context, ExpansionMode, Keypair, MiniSecretKey, SecretKey, -}; -#[cfg(any(feature = "full_crypto", feature = "serde"))] +use schnorrkel::signing_context; use schnorrkel::{ - derive::{ChainCode, Derivation}, - PublicKey, + derive::{ChainCode, Derivation, CHAIN_CODE_LENGTH}, + ExpansionMode, Keypair, MiniSecretKey, PublicKey, SecretKey, }; use sp_std::vec::Vec; @@ -47,7 +41,6 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_std::ops::Deref; -#[cfg(feature = "full_crypto")] use schnorrkel::keys::{MINI_SECRET_KEY_LENGTH, SECRET_KEY_LENGTH}; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -56,14 +49,12 @@ use sp_runtime_interface::pass_by::PassByInner; use sp_std::alloc::{format, string::String}; // signing context -#[cfg(feature = "full_crypto")] const SIGNING_CTX: &[u8] = b"substrate"; /// An identifier used to match public keys against sr25519 keys pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"sr25"); /// An Schnorrkel/Ristretto x25519 ("sr25519") public key. -#[cfg_attr(feature = "full_crypto", derive(Hash))] #[derive( PartialEq, Eq, @@ -76,14 +67,13 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"sr25"); PassByInner, MaxEncodedLen, TypeInfo, + Hash, )] pub struct Public(pub [u8; 32]); /// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. -#[cfg(feature = "full_crypto")] pub struct Pair(Keypair); -#[cfg(feature = "full_crypto")] impl Clone for Pair { fn clone(&self) -> Self { Pair(schnorrkel::Keypair { @@ -216,8 +206,7 @@ impl<'de> Deserialize<'de> for Public { } /// An Schnorrkel/Ristretto x25519 ("sr25519") signature. -#[cfg_attr(feature = "full_crypto", derive(Hash))] -#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] +#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq, Hash)] pub struct Signature(pub [u8; 64]); impl TryFrom<&[u8]> for Signature { @@ -435,16 +424,13 @@ impl AsRef for Pair { } /// Derive a single hard junction. -#[cfg(feature = "full_crypto")] fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> MiniSecretKey { secret.hard_derive_mini_secret_key(Some(ChainCode(*cc)), b"").0 } /// The raw secret seed, which can be used to recreate the `Pair`. -#[cfg(feature = "full_crypto")] type Seed = [u8; MINI_SECRET_KEY_LENGTH]; -#[cfg(feature = "full_crypto")] impl TraitPair for Pair { type Public = Public; type Seed = Seed; @@ -499,6 +485,7 @@ impl TraitPair for Pair { Ok((Self(result.into()), seed.map(|s| MiniSecretKey::to_bytes(&s)))) } + #[cfg(feature = "full_crypto")] fn sign(&self, message: &[u8]) -> Signature { let context = signing_context(SIGNING_CTX); self.0.sign(context.bytes(message)).into() @@ -533,16 +520,13 @@ impl Pair { } impl CryptoType for Public { - #[cfg(feature = "full_crypto")] type Pair = Pair; } impl CryptoType for Signature { - #[cfg(feature = "full_crypto")] type Pair = Pair; } -#[cfg(feature = "full_crypto")] impl CryptoType for Pair { type Pair = Pair; } diff --git a/substrate/primitives/keyring/Cargo.toml b/substrate/primitives/keyring/Cargo.toml index 1c936b6685b..940fe90916d 100644 --- a/substrate/primitives/keyring/Cargo.toml +++ b/substrate/primitives/keyring/Cargo.toml @@ -18,10 +18,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] strum = { version = "0.24.1", features = ["derive"], default-features = false } -sp-core = { path = "../core" } -sp-runtime = { path = "../runtime" } +sp-core = { path = "../core", default-features = false } +sp-runtime = { path = "../runtime", default-features = false } [features] +default = ["std"] +std = ["sp-core/std", "sp-runtime/std", "strum/std"] + # This feature adds Bandersnatch crypto primitives. # It should not be used in production since the implementation and interface may still # be subject to significant changes. diff --git a/substrate/primitives/keyring/check-features-variants.sh b/substrate/primitives/keyring/check-features-variants.sh new file mode 100755 index 00000000000..9c28d835894 --- /dev/null +++ b/substrate/primitives/keyring/check-features-variants.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env -S bash -eux + +export RUSTFLAGS="-Cdebug-assertions=y -Dwarnings" +T=wasm32-unknown-unknown + +cargo check --release +cargo check --release --features="bandersnatch-experimental" +cargo check --release --target=$T --no-default-features diff --git a/substrate/primitives/keyring/src/bandersnatch.rs b/substrate/primitives/keyring/src/bandersnatch.rs index eb60f856327..67fc5c47df6 100644 --- a/substrate/primitives/keyring/src/bandersnatch.rs +++ b/substrate/primitives/keyring/src/bandersnatch.rs @@ -18,14 +18,21 @@ //! A set of well-known keys used for testing. pub use sp_core::bandersnatch; +#[cfg(feature = "std")] +use sp_core::bandersnatch::Signature; use sp_core::{ - bandersnatch::{Pair, Public, Signature}, + bandersnatch::{Pair, Public}, crypto::UncheckedFrom, hex2array, ByteArray, Pair as PairT, }; +extern crate alloc; +use alloc::{fmt, format, str::FromStr, string::String, vec::Vec}; + /// Set of test accounts. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter)] +#[derive( + Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter, Ord, PartialOrd, +)] pub enum Keyring { Alice, Bob, @@ -56,6 +63,7 @@ impl Keyring { Public::from(self).to_raw_vec() } + #[cfg(feature = "std")] pub fn sign(self, msg: &[u8]) -> Signature { Pair::from(self).sign(msg) } @@ -102,16 +110,16 @@ impl From for &'static str { #[derive(Debug)] pub struct ParseKeyringError; -impl std::fmt::Display for ParseKeyringError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for ParseKeyringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ParseKeyringError") } } -impl std::str::FromStr for Keyring { +impl FromStr for Keyring { type Err = ParseKeyringError; - fn from_str(s: &str) -> Result::Err> { + fn from_str(s: &str) -> Result::Err> { match s { "Alice" => Ok(Keyring::Alice), "Bob" => Ok(Keyring::Bob), diff --git a/substrate/primitives/keyring/src/ed25519.rs b/substrate/primitives/keyring/src/ed25519.rs index ade42b29494..98ca368e53c 100644 --- a/substrate/primitives/keyring/src/ed25519.rs +++ b/substrate/primitives/keyring/src/ed25519.rs @@ -18,14 +18,21 @@ //! Support code for the runtime. A set of test accounts. pub use sp_core::ed25519; +#[cfg(feature = "std")] +use sp_core::ed25519::Signature; use sp_core::{ - ed25519::{Pair, Public, Signature}, + ed25519::{Pair, Public}, hex2array, ByteArray, Pair as PairT, H256, }; use sp_runtime::AccountId32; +extern crate alloc; +use alloc::{format, string::String, vec::Vec}; + /// Set of test accounts. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter)] +#[derive( + Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter, Ord, PartialOrd, +)] pub enum Keyring { Alice, Bob, @@ -76,6 +83,7 @@ impl Keyring { self.to_raw_public().into() } + #[cfg(feature = "std")] pub fn sign(self, msg: &[u8]) -> Signature { Pair::from(self).sign(msg) } diff --git a/substrate/primitives/keyring/src/lib.rs b/substrate/primitives/keyring/src/lib.rs index ee7fd56ba11..f753bf4b0dd 100644 --- a/substrate/primitives/keyring/src/lib.rs +++ b/substrate/primitives/keyring/src/lib.rs @@ -17,6 +17,8 @@ //! Support code for the runtime. A set of test accounts. +#![cfg_attr(not(feature = "std"), no_std)] + /// Test account crypto for sr25519. pub mod sr25519; diff --git a/substrate/primitives/keyring/src/sr25519.rs b/substrate/primitives/keyring/src/sr25519.rs index 1c2a2526efb..a3a506152d7 100644 --- a/substrate/primitives/keyring/src/sr25519.rs +++ b/substrate/primitives/keyring/src/sr25519.rs @@ -18,15 +18,22 @@ //! Support code for the runtime. A set of test accounts. pub use sp_core::sr25519; +#[cfg(feature = "std")] +use sp_core::sr25519::Signature; use sp_core::{ hex2array, - sr25519::{Pair, Public, Signature}, + sr25519::{Pair, Public}, ByteArray, Pair as PairT, H256, }; use sp_runtime::AccountId32; +extern crate alloc; +use alloc::{fmt, format, str::FromStr, string::String, vec::Vec}; + /// Set of test accounts. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter)] +#[derive( + Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter, Ord, PartialOrd, +)] pub enum Keyring { Alice, Bob, @@ -77,6 +84,7 @@ impl Keyring { self.to_raw_public().into() } + #[cfg(feature = "std")] pub fn sign(self, msg: &[u8]) -> Signature { Pair::from(self).sign(msg) } @@ -140,16 +148,16 @@ impl From for sp_runtime::MultiSigner { #[derive(Debug)] pub struct ParseKeyringError; -impl std::fmt::Display for ParseKeyringError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for ParseKeyringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ParseKeyringError") } } -impl std::str::FromStr for Keyring { +impl FromStr for Keyring { type Err = ParseKeyringError; - fn from_str(s: &str) -> Result::Err> { + fn from_str(s: &str) -> Result::Err> { match s { "alice" => Ok(Keyring::Alice), "bob" => Ok(Keyring::Bob), diff --git a/substrate/test-utils/runtime/Cargo.toml b/substrate/test-utils/runtime/Cargo.toml index 3bba5cd5bf0..b6e6346e801 100644 --- a/substrate/test-utils/runtime/Cargo.toml +++ b/substrate/test-utils/runtime/Cargo.toml @@ -24,9 +24,9 @@ sp-block-builder = { path = "../../primitives/block-builder", default-features = codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } sp-inherents = { path = "../../primitives/inherents", default-features = false } -sp-keyring = { path = "../../primitives/keyring", optional = true } +sp-keyring = { path = "../../primitives/keyring", default-features = false } sp-offchain = { path = "../../primitives/offchain", default-features = false } -sp-core = { path = "../../primitives/core", default-features = false } +sp-core = { path = "../../primitives/core", default-features = false, features = ["serde"] } sp-crypto-hashing = { path = "../../primitives/crypto/hashing", default-features = false } sp-std = { path = "../../primitives/std", default-features = false } sp-io = { path = "../../primitives/io", default-features = false } @@ -99,7 +99,7 @@ std = [ "sp-genesis-builder/std", "sp-inherents/std", "sp-io/std", - "sp-keyring", + "sp-keyring/std", "sp-offchain/std", "sp-runtime/std", "sp-session/std", -- GitLab From 82f3c3e2e81d3ea4b9bc35a14432d3ab93fb5b52 Mon Sep 17 00:00:00 2001 From: gupnik Date: Wed, 13 Mar 2024 12:31:01 +0530 Subject: [PATCH 113/188] Construct Runtime v2 (#1378) Moved from https://github.com/paritytech/substrate/pull/14788 ---- Fixes https://github.com/paritytech/polkadot-sdk/issues/232 This PR introduces outer-macro approach for `construct_runtime` as discussed in the linked issue. It looks like the following: ```rust #[frame_support::runtime] mod runtime { #[runtime::runtime] #[runtime::derive( RuntimeCall, RuntimeEvent, RuntimeError, RuntimeOrigin, RuntimeFreezeReason, RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, RuntimeTask, )] pub struct Runtime; #[runtime::pallet_index(0)] pub type System = frame_system; #[runtime::pallet_index(1)] pub type Timestamp = pallet_timestamp; #[runtime::pallet_index(2)] pub type Aura = pallet_aura; #[runtime::pallet_index(3)] pub type Grandpa = pallet_grandpa; #[runtime::pallet_index(4)] pub type Balances = pallet_balances; #[runtime::pallet_index(5)] pub type TransactionPayment = pallet_transaction_payment; #[runtime::pallet_index(6)] pub type Sudo = pallet_sudo; // Include the custom logic from the pallet-template in the runtime. #[runtime::pallet_index(7)] pub type TemplateModule = pallet_template; } ``` ## Features - `#[runtime::runtime]` attached to a struct defines the main runtime - `#[runtime::derive]` attached to this struct defines the types generated by runtime - `#[runtime::pallet_index]` must be attached to a pallet to define its index - `#[runtime::disable_call]` can be optionally attached to a pallet to disable its calls - `#[runtime::disable_unsigned]` can be optionally attached to a pallet to disable unsigned calls - A pallet instance can be defined as `TemplateModule: pallet_template` - An optional attribute can be defined as `#[frame_support::runtime(legacy_ordering)]` to ensure that the order of hooks is same as the order of pallets (and not based on the pallet_index). This is to support legacy runtimes and should be avoided for new ones. ## Todo - [x] Update the latest syntax in kitchensink and tests - [x] Update UI tests - [x] Docs ## Extension - Abstract away the Executive similar to https://github.com/paritytech/substrate/pull/14742 - Optionally avoid the need to specify all runtime types (TBD) --------- Co-authored-by: Francisco Aguirre Co-authored-by: Nikhil Gupta <> --- prdoc/pr_1378.prdoc | 27 + substrate/bin/node/runtime/Cargo.toml | 2 +- substrate/bin/node/runtime/src/lib.rs | 342 ++++-- substrate/frame/support/Cargo.toml | 4 +- substrate/frame/support/procedural/Cargo.toml | 1 + .../procedural/src/construct_runtime/mod.rs | 15 +- substrate/frame/support/procedural/src/lib.rs | 68 ++ .../src/pallet/expand/tt_default_parts.rs | 74 ++ .../procedural/src/pallet/parse/helper.rs | 6 + .../procedural/src/runtime/expand/mod.rs | 320 ++++++ .../support/procedural/src/runtime/mod.rs | 236 +++++ .../procedural/src/runtime/parse/helper.rs | 37 + .../procedural/src/runtime/parse/mod.rs | 266 +++++ .../procedural/src/runtime/parse/pallet.rs | 99 ++ .../src/runtime/parse/pallet_decl.rs | 60 ++ .../src/runtime/parse/runtime_struct.rs | 35 + .../src/runtime/parse/runtime_types.rs | 76 ++ substrate/frame/support/src/lib.rs | 3 + substrate/frame/support/test/Cargo.toml | 2 +- .../{construct_runtime.rs => runtime.rs} | 282 +++-- .../test/tests/runtime_legacy_ordering.rs | 993 ++++++++++++++++++ .../frame/support/test/tests/runtime_ui.rs | 36 + .../runtime_ui/can_only_be_attached_to_mod.rs | 21 + .../can_only_be_attached_to_mod.stderr | 5 + .../runtime_ui/conflicting_pallet_index.rs | 43 + .../conflicting_pallet_index.stderr | 11 + .../runtime_ui/conflicting_pallet_name.rs | 43 + .../runtime_ui/conflicting_pallet_name.stderr | 11 + .../tests/runtime_ui/invalid_attribute.rs | 23 + .../tests/runtime_ui/invalid_attribute.stderr | 5 + .../tests/runtime_ui/invalid_pallet_index.rs | 28 + .../runtime_ui/invalid_pallet_index.stderr | 5 + .../runtime_ui/invalid_runtime_type_derive.rs | 25 + .../invalid_runtime_type_derive.stderr | 5 + .../test/tests/runtime_ui/missing_runtime.rs | 21 + .../tests/runtime_ui/missing_runtime.stderr | 5 + .../missing_runtime_types_derive.rs | 24 + .../missing_runtime_types_derive.stderr | 5 + .../tests/runtime_ui/missing_system_pallet.rs | 25 + .../runtime_ui/missing_system_pallet.stderr | 5 + .../test/tests/runtime_ui/pass/basic.rs | 37 + .../test/tests/runtime_ui/runtime_struct.rs | 24 + .../tests/runtime_ui/runtime_struct.stderr | 5 + templates/solochain/runtime/Cargo.toml | 2 +- templates/solochain/runtime/src/lib.rs | 55 +- 45 files changed, 3212 insertions(+), 205 deletions(-) create mode 100644 prdoc/pr_1378.prdoc create mode 100644 substrate/frame/support/procedural/src/runtime/expand/mod.rs create mode 100644 substrate/frame/support/procedural/src/runtime/mod.rs create mode 100644 substrate/frame/support/procedural/src/runtime/parse/helper.rs create mode 100644 substrate/frame/support/procedural/src/runtime/parse/mod.rs create mode 100644 substrate/frame/support/procedural/src/runtime/parse/pallet.rs create mode 100644 substrate/frame/support/procedural/src/runtime/parse/pallet_decl.rs create mode 100644 substrate/frame/support/procedural/src/runtime/parse/runtime_struct.rs create mode 100644 substrate/frame/support/procedural/src/runtime/parse/runtime_types.rs rename substrate/frame/support/test/tests/{construct_runtime.rs => runtime.rs} (89%) create mode 100644 substrate/frame/support/test/tests/runtime_legacy_ordering.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/can_only_be_attached_to_mod.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/can_only_be_attached_to_mod.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_index.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_index.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_name.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_name.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/invalid_attribute.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/invalid_attribute.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/invalid_pallet_index.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/invalid_pallet_index.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/missing_runtime.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/missing_runtime.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/missing_runtime_types_derive.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/missing_runtime_types_derive.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/missing_system_pallet.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/missing_system_pallet.stderr create mode 100644 substrate/frame/support/test/tests/runtime_ui/pass/basic.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/runtime_struct.rs create mode 100644 substrate/frame/support/test/tests/runtime_ui/runtime_struct.stderr diff --git a/prdoc/pr_1378.prdoc b/prdoc/pr_1378.prdoc new file mode 100644 index 00000000000..6533dcb6630 --- /dev/null +++ b/prdoc/pr_1378.prdoc @@ -0,0 +1,27 @@ +title: Construct Runtime V2 - An outer macro approach to define the runtime + +doc: + - audience: Runtime Dev + description: | + Introduces `#[frame_support::runtime]` that can be attached to a mod to define a runtime. The items + in this mod can be attached to the following attributes to define the key components of the runtime. + 1. `#[runtime::runtime]` attached to a struct defines the main runtime + 2. `#[runtime::derive]` attached to the runtime struct defines the types generated by the runtime + 3. `#[runtime::pallet_index]` must be attached to a pallet to define its index + 4. `#[runtime::disable_call]` can be optionally attached to a pallet to disable its calls + 5. `#[runtime::disable_unsigned]` can be optionally attached to a pallet to disable unsigned calls + 6. A pallet instance can be defined as `TemplateModule: pallet_template` + An optional attribute can be defined as `#[frame_support::runtime(legacy_ordering)]` to ensure that + the order of hooks is same as the order of pallets (and not based on the pallet_index). This is to support + legacy runtimes and should be avoided for new ones. + +migrations: + db: [] + + runtime: [] + +crates: + - name: frame-support + - name: frame-support-procedural + +host_functions: [] diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml index bdef42474d0..09c8fb4ed3d 100644 --- a/substrate/bin/node/runtime/Cargo.toml +++ b/substrate/bin/node/runtime/Cargo.toml @@ -58,7 +58,7 @@ sp-io = { path = "../../../primitives/io", default-features = false } frame-executive = { path = "../../../frame/executive", default-features = false } frame-benchmarking = { path = "../../../frame/benchmarking", default-features = false } frame-benchmarking-pallet-pov = { path = "../../../frame/benchmarking/pov", default-features = false } -frame-support = { path = "../../../frame/support", default-features = false, features = ["tuples-96"] } +frame-support = { path = "../../../frame/support", default-features = false, features = ["experimental", "tuples-96"] } frame-system = { path = "../../../frame/system", default-features = false } frame-system-benchmarking = { path = "../../../frame/system/benchmarking", default-features = false, optional = true } frame-election-provider-support = { path = "../../../frame/election-provider-support", default-features = false } diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 18ce13cff80..96611f5a144 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -28,7 +28,7 @@ use frame_election_provider_support::{ onchain, BalancingConfig, ElectionDataProvider, SequentialPhragmen, VoteWeight, }; use frame_support::{ - construct_runtime, derive_impl, + derive_impl, dispatch::DispatchClass, dynamic_params::{dynamic_pallet_params, dynamic_params}, genesis_builder_helper::{build_config, create_default_config}, @@ -2196,92 +2196,260 @@ impl pallet_parameters::Config for Runtime { type WeightInfo = (); } -construct_runtime!( - pub enum Runtime { - System: frame_system, - Utility: pallet_utility, - Babe: pallet_babe, - Timestamp: pallet_timestamp, - // Authorship must be before session in order to note author in the correct session and era - // for im-online and staking. - Authorship: pallet_authorship, - Indices: pallet_indices, - Balances: pallet_balances, - TransactionPayment: pallet_transaction_payment, - AssetTxPayment: pallet_asset_tx_payment, - AssetConversionTxPayment: pallet_asset_conversion_tx_payment, - ElectionProviderMultiPhase: pallet_election_provider_multi_phase, - Staking: pallet_staking, - Session: pallet_session, - Democracy: pallet_democracy, - Council: pallet_collective::, - TechnicalCommittee: pallet_collective::, - Elections: pallet_elections_phragmen, - TechnicalMembership: pallet_membership::, - Grandpa: pallet_grandpa, - Treasury: pallet_treasury, - AssetRate: pallet_asset_rate, - Contracts: pallet_contracts, - Sudo: pallet_sudo, - ImOnline: pallet_im_online, - AuthorityDiscovery: pallet_authority_discovery, - Offences: pallet_offences, - Historical: pallet_session_historical, - RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip, - Identity: pallet_identity, - Society: pallet_society, - Recovery: pallet_recovery, - Vesting: pallet_vesting, - Scheduler: pallet_scheduler, - Glutton: pallet_glutton, - Preimage: pallet_preimage, - Proxy: pallet_proxy, - Multisig: pallet_multisig, - Bounties: pallet_bounties, - Tips: pallet_tips, - Assets: pallet_assets::, - PoolAssets: pallet_assets::, - Beefy: pallet_beefy, - // MMR leaf construction must be after session in order to have a leaf's next_auth_set - // refer to block. See issue polkadot-fellows/runtimes#160 for details. - Mmr: pallet_mmr, - MmrLeaf: pallet_beefy_mmr, - Lottery: pallet_lottery, - Nis: pallet_nis, - Uniques: pallet_uniques, - Nfts: pallet_nfts, - NftFractionalization: pallet_nft_fractionalization, - Salary: pallet_salary, - CoreFellowship: pallet_core_fellowship, - TransactionStorage: pallet_transaction_storage, - VoterList: pallet_bags_list::, - StateTrieMigration: pallet_state_trie_migration, - ChildBounties: pallet_child_bounties, - Referenda: pallet_referenda, - Remark: pallet_remark, - RootTesting: pallet_root_testing, - ConvictionVoting: pallet_conviction_voting, - Whitelist: pallet_whitelist, - AllianceMotion: pallet_collective::, - Alliance: pallet_alliance, - NominationPools: pallet_nomination_pools, - RankedPolls: pallet_referenda::, - RankedCollective: pallet_ranked_collective, - AssetConversion: pallet_asset_conversion, - FastUnstake: pallet_fast_unstake, - MessageQueue: pallet_message_queue, - Pov: frame_benchmarking_pallet_pov, - TxPause: pallet_tx_pause, - SafeMode: pallet_safe_mode, - Statement: pallet_statement, - MultiBlockMigrations: pallet_migrations, - Broker: pallet_broker, - TasksExample: pallet_example_tasks, - Mixnet: pallet_mixnet, - Parameters: pallet_parameters, - SkipFeelessPayment: pallet_skip_feeless_payment, - } -); +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + #[runtime::pallet_index(0)] + pub type System = frame_system; + + #[runtime::pallet_index(1)] + pub type Utility = pallet_utility; + + #[runtime::pallet_index(2)] + pub type Babe = pallet_babe; + + #[runtime::pallet_index(3)] + pub type Timestamp = pallet_timestamp; + + // Authorship must be before session in order to note author in the correct session and era + // for im-online and staking. + #[runtime::pallet_index(4)] + pub type Authorship = pallet_authorship; + + #[runtime::pallet_index(5)] + pub type Indices = pallet_indices; + + #[runtime::pallet_index(6)] + pub type Balances = pallet_balances; + + #[runtime::pallet_index(7)] + pub type TransactionPayment = pallet_transaction_payment; + + #[runtime::pallet_index(8)] + pub type AssetTxPayment = pallet_asset_tx_payment; + + #[runtime::pallet_index(9)] + pub type AssetConversionTxPayment = pallet_asset_conversion_tx_payment; + + #[runtime::pallet_index(10)] + pub type ElectionProviderMultiPhase = pallet_election_provider_multi_phase; + + #[runtime::pallet_index(11)] + pub type Staking = pallet_staking; + + #[runtime::pallet_index(12)] + pub type Session = pallet_session; + + #[runtime::pallet_index(13)] + pub type Democracy = pallet_democracy; + + #[runtime::pallet_index(14)] + pub type Council = pallet_collective; + + #[runtime::pallet_index(15)] + pub type TechnicalCommittee = pallet_collective; + + #[runtime::pallet_index(16)] + pub type Elections = pallet_elections_phragmen; + + #[runtime::pallet_index(17)] + pub type TechnicalMembership = pallet_membership; + + #[runtime::pallet_index(18)] + pub type Grandpa = pallet_grandpa; + + #[runtime::pallet_index(19)] + pub type Treasury = pallet_treasury; + + #[runtime::pallet_index(20)] + pub type AssetRate = pallet_asset_rate; + + #[runtime::pallet_index(21)] + pub type Contracts = pallet_contracts; + + #[runtime::pallet_index(22)] + pub type Sudo = pallet_sudo; + + #[runtime::pallet_index(23)] + pub type ImOnline = pallet_im_online; + + #[runtime::pallet_index(24)] + pub type AuthorityDiscovery = pallet_authority_discovery; + + #[runtime::pallet_index(25)] + pub type Offences = pallet_offences; + + #[runtime::pallet_index(26)] + pub type Historical = pallet_session_historical; + + #[runtime::pallet_index(27)] + pub type RandomnessCollectiveFlip = pallet_insecure_randomness_collective_flip; + + #[runtime::pallet_index(28)] + pub type Identity = pallet_identity; + + #[runtime::pallet_index(29)] + pub type Society = pallet_society; + + #[runtime::pallet_index(30)] + pub type Recovery = pallet_recovery; + + #[runtime::pallet_index(31)] + pub type Vesting = pallet_vesting; + + #[runtime::pallet_index(32)] + pub type Scheduler = pallet_scheduler; + + #[runtime::pallet_index(33)] + pub type Glutton = pallet_glutton; + + #[runtime::pallet_index(34)] + pub type Preimage = pallet_preimage; + + #[runtime::pallet_index(35)] + pub type Proxy = pallet_proxy; + + #[runtime::pallet_index(36)] + pub type Multisig = pallet_multisig; + + #[runtime::pallet_index(37)] + pub type Bounties = pallet_bounties; + + #[runtime::pallet_index(38)] + pub type Tips = pallet_tips; + + #[runtime::pallet_index(39)] + pub type Assets = pallet_assets; + + #[runtime::pallet_index(40)] + pub type PoolAssets = pallet_assets; + + #[runtime::pallet_index(41)] + pub type Beefy = pallet_beefy; + + // MMR leaf construction must be after session in order to have a leaf's next_auth_set + // refer to block. See issue polkadot-fellows/runtimes#160 for details. + #[runtime::pallet_index(42)] + pub type Mmr = pallet_mmr; + + #[runtime::pallet_index(43)] + pub type MmrLeaf = pallet_beefy_mmr; + + #[runtime::pallet_index(44)] + pub type Lottery = pallet_lottery; + + #[runtime::pallet_index(45)] + pub type Nis = pallet_nis; + + #[runtime::pallet_index(46)] + pub type Uniques = pallet_uniques; + + #[runtime::pallet_index(47)] + pub type Nfts = pallet_nfts; + + #[runtime::pallet_index(48)] + pub type NftFractionalization = pallet_nft_fractionalization; + + #[runtime::pallet_index(49)] + pub type Salary = pallet_salary; + + #[runtime::pallet_index(50)] + pub type CoreFellowship = pallet_core_fellowship; + + #[runtime::pallet_index(51)] + pub type TransactionStorage = pallet_transaction_storage; + + #[runtime::pallet_index(52)] + pub type VoterList = pallet_bags_list; + + #[runtime::pallet_index(53)] + pub type StateTrieMigration = pallet_state_trie_migration; + + #[runtime::pallet_index(54)] + pub type ChildBounties = pallet_child_bounties; + + #[runtime::pallet_index(55)] + pub type Referenda = pallet_referenda; + + #[runtime::pallet_index(56)] + pub type Remark = pallet_remark; + + #[runtime::pallet_index(57)] + pub type RootTesting = pallet_root_testing; + + #[runtime::pallet_index(58)] + pub type ConvictionVoting = pallet_conviction_voting; + + #[runtime::pallet_index(59)] + pub type Whitelist = pallet_whitelist; + + #[runtime::pallet_index(60)] + pub type AllianceMotion = pallet_collective; + + #[runtime::pallet_index(61)] + pub type Alliance = pallet_alliance; + + #[runtime::pallet_index(62)] + pub type NominationPools = pallet_nomination_pools; + + #[runtime::pallet_index(63)] + pub type RankedPolls = pallet_referenda; + + #[runtime::pallet_index(64)] + pub type RankedCollective = pallet_ranked_collective; + + #[runtime::pallet_index(65)] + pub type AssetConversion = pallet_asset_conversion; + + #[runtime::pallet_index(66)] + pub type FastUnstake = pallet_fast_unstake; + + #[runtime::pallet_index(67)] + pub type MessageQueue = pallet_message_queue; + + #[runtime::pallet_index(68)] + pub type Pov = frame_benchmarking_pallet_pov; + + #[runtime::pallet_index(69)] + pub type TxPause = pallet_tx_pause; + + #[runtime::pallet_index(70)] + pub type SafeMode = pallet_safe_mode; + + #[runtime::pallet_index(71)] + pub type Statement = pallet_statement; + + #[runtime::pallet_index(72)] + pub type MultiBlockMigrations = pallet_migrations; + + #[runtime::pallet_index(73)] + pub type Broker = pallet_broker; + + #[runtime::pallet_index(74)] + pub type TasksExample = pallet_example_tasks; + + #[runtime::pallet_index(75)] + pub type Mixnet = pallet_mixnet; + + #[runtime::pallet_index(76)] + pub type Parameters = pallet_parameters; + + #[runtime::pallet_index(77)] + pub type SkipFeelessPayment = pallet_skip_feeless_payment; +} /// The address format for describing accounts. pub type Address = sp_runtime::MultiAddress; diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml index 113af41751e..be60068f122 100644 --- a/substrate/frame/support/Cargo.toml +++ b/substrate/frame/support/Cargo.toml @@ -109,7 +109,9 @@ try-runtime = [ "sp-debug-derive/force-debug", "sp-runtime/try-runtime", ] -experimental = [] +experimental = [ + "frame-support-procedural/experimental", +] # By default some types have documentation, `no-metadata-docs` allows to reduce the documentation # in the metadata. no-metadata-docs = [ diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index 85947503802..dd0688f2ad0 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -38,6 +38,7 @@ regex = "1" default = ["std"] std = ["sp-crypto-hashing/std"] no-metadata-docs = [] +experimental = [] # Generate impl-trait for tuples with the given number of tuples. Will be needed as the number of # pallets in a runtime grows. Does increase the compile time! tuples-96 = [] diff --git a/substrate/frame/support/procedural/src/construct_runtime/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/mod.rs index 6e95fdf116a..1937dfa9ca4 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/mod.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/mod.rs @@ -208,8 +208,8 @@ //! This macro returns the ` :: expanded { Error }` list of additional parts we would like to //! expose. -mod expand; -mod parse; +pub(crate) mod expand; +pub(crate) mod parse; use crate::pallet::parse::helper::two128_str; use cfg_expr::Predicate; @@ -515,7 +515,7 @@ fn construct_runtime_final_expansion( Ok(res) } -fn decl_all_pallets<'a>( +pub(crate) fn decl_all_pallets<'a>( runtime: &'a Ident, pallet_declarations: impl Iterator, features: &HashSet<&str>, @@ -624,7 +624,8 @@ fn decl_all_pallets<'a>( #( #all_pallets_without_system )* ) } -fn decl_pallet_runtime_setup( + +pub(crate) fn decl_pallet_runtime_setup( runtime: &Ident, pallet_declarations: &[Pallet], scrate: &TokenStream2, @@ -730,7 +731,7 @@ fn decl_pallet_runtime_setup( ) } -fn decl_integrity_test(scrate: &TokenStream2) -> TokenStream2 { +pub(crate) fn decl_integrity_test(scrate: &TokenStream2) -> TokenStream2 { quote!( #[cfg(test)] mod __construct_runtime_integrity_test { @@ -745,7 +746,7 @@ fn decl_integrity_test(scrate: &TokenStream2) -> TokenStream2 { ) } -fn decl_static_assertions( +pub(crate) fn decl_static_assertions( runtime: &Ident, pallet_decls: &[Pallet], scrate: &TokenStream2, @@ -776,7 +777,7 @@ fn decl_static_assertions( } } -fn check_pallet_number(input: TokenStream2, pallet_num: usize) -> Result<()> { +pub(crate) fn check_pallet_number(input: TokenStream2, pallet_num: usize) -> Result<()> { let max_pallet_num = { if cfg!(feature = "tuples-96") { 96 diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 89e39a5c9bb..dee6d522d25 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -31,6 +31,7 @@ mod match_and_insert; mod no_bound; mod pallet; mod pallet_error; +mod runtime; mod storage_alias; mod transactional; mod tt_macro; @@ -1220,6 +1221,73 @@ pub fn import_section(attr: TokenStream, tokens: TokenStream) -> TokenStream { .into() } +/// Construct a runtime, with the given name and the given pallets. +/// +/// # Example: +/// +/// ```ignore +/// #[frame_support::runtime] +/// mod runtime { +/// // The main runtime +/// #[runtime::runtime] +/// // Runtime Types to be generated +/// #[runtime::derive( +/// RuntimeCall, +/// RuntimeEvent, +/// RuntimeError, +/// RuntimeOrigin, +/// RuntimeFreezeReason, +/// RuntimeHoldReason, +/// RuntimeSlashReason, +/// RuntimeLockId, +/// RuntimeTask, +/// )] +/// pub struct Runtime; +/// +/// #[runtime::pallet_index(0)] +/// pub type System = frame_system; +/// +/// #[runtime::pallet_index(1)] +/// pub type Test = path::to::test; +/// +/// // Pallet with instance. +/// #[runtime::pallet_index(2)] +/// pub type Test2_Instance1 = test2; +/// +/// // Pallet with calls disabled. +/// #[runtime::pallet_index(3)] +/// #[runtime::disable_call] +/// pub type Test3 = test3; +/// +/// // Pallet with unsigned extrinsics disabled. +/// #[runtime::pallet_index(4)] +/// #[runtime::disable_unsigned] +/// pub type Test4 = test4; +/// } +/// ``` +/// +/// # Legacy Ordering +/// +/// An optional attribute can be defined as #[frame_support::runtime(legacy_ordering)] to +/// ensure that the order of hooks is same as the order of pallets (and not based on the +/// pallet_index). This is to support legacy runtimes and should be avoided for new ones. +/// +/// # Note +/// +/// The population of the genesis storage depends on the order of pallets. So, if one of your +/// pallets depends on another pallet, the pallet that is depended upon needs to come before +/// the pallet depending on it. +/// +/// # Type definitions +/// +/// * The macro generates a type alias for each pallet to their `Pallet`. E.g. `type System = +/// frame_system::Pallet` +#[cfg(feature = "experimental")] +#[proc_macro_attribute] +pub fn runtime(attr: TokenStream, item: TokenStream) -> TokenStream { + runtime::runtime(attr, item) +} + /// Mark a module that contains dynamic parameters. /// /// See the `pallet_parameters` for a full example. diff --git a/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs b/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs index 7cc1415dfdd..99364aaa96c 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs @@ -28,6 +28,8 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { syn::Ident::new(&format!("__tt_default_parts_{}", count), def.item.span()); let extra_parts_unique_id = syn::Ident::new(&format!("__tt_extra_parts_{}", count), def.item.span()); + let default_parts_unique_id_v2 = + syn::Ident::new(&format!("__tt_default_parts_v2_{}", count), def.item.span()); let call_part = def.call.as_ref().map(|_| quote::quote!(Call,)); @@ -81,6 +83,58 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { .any(|c| matches!(c.composite_keyword, CompositeKeyword::SlashReason(_))) .then_some(quote::quote!(SlashReason,)); + let call_part_v2 = def.call.as_ref().map(|_| quote::quote!(+ Call)); + + let task_part_v2 = def.task_enum.as_ref().map(|_| quote::quote!(+ Task)); + + let storage_part_v2 = (!def.storages.is_empty()).then(|| quote::quote!(+ Storage)); + + let event_part_v2 = def.event.as_ref().map(|event| { + let gen = event.gen_kind.is_generic().then(|| quote::quote!()); + quote::quote!(+ Event #gen) + }); + + let error_part_v2 = def.error.as_ref().map(|_| quote::quote!(+ Error)); + + let origin_part_v2 = def.origin.as_ref().map(|origin| { + let gen = origin.is_generic.then(|| quote::quote!()); + quote::quote!(+ Origin #gen) + }); + + let config_part_v2 = def.genesis_config.as_ref().map(|genesis_config| { + let gen = genesis_config.gen_kind.is_generic().then(|| quote::quote!()); + quote::quote!(+ Config #gen) + }); + + let inherent_part_v2 = def.inherent.as_ref().map(|_| quote::quote!(+ Inherent)); + + let validate_unsigned_part_v2 = + def.validate_unsigned.as_ref().map(|_| quote::quote!(+ ValidateUnsigned)); + + let freeze_reason_part_v2 = def + .composites + .iter() + .any(|c| matches!(c.composite_keyword, CompositeKeyword::FreezeReason(_))) + .then_some(quote::quote!(+ FreezeReason)); + + let hold_reason_part_v2 = def + .composites + .iter() + .any(|c| matches!(c.composite_keyword, CompositeKeyword::HoldReason(_))) + .then_some(quote::quote!(+ HoldReason)); + + let lock_id_part_v2 = def + .composites + .iter() + .any(|c| matches!(c.composite_keyword, CompositeKeyword::LockId(_))) + .then_some(quote::quote!(+ LockId)); + + let slash_reason_part_v2 = def + .composites + .iter() + .any(|c| matches!(c.composite_keyword, CompositeKeyword::SlashReason(_))) + .then_some(quote::quote!(+ SlashReason)); + quote::quote!( // This macro follows the conventions as laid out by the `tt-call` crate. It does not // accept any arguments and simply returns the pallet parts, separated by commas, then @@ -138,5 +192,25 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { } pub use #extra_parts_unique_id as tt_extra_parts; + + #[macro_export] + #[doc(hidden)] + macro_rules! #default_parts_unique_id_v2 { + { + $caller:tt + frame_support = [{ $($frame_support:ident)::* }] + } => { + $($frame_support)*::__private::tt_return! { + $caller + tokens = [{ + + Pallet #call_part_v2 #storage_part_v2 #event_part_v2 #error_part_v2 #origin_part_v2 #config_part_v2 + #inherent_part_v2 #validate_unsigned_part_v2 #freeze_reason_part_v2 #task_part_v2 + #hold_reason_part_v2 #lock_id_part_v2 #slash_reason_part_v2 + }] + } + }; + } + + pub use #default_parts_unique_id_v2 as tt_default_parts_v2; ) } diff --git a/substrate/frame/support/procedural/src/pallet/parse/helper.rs b/substrate/frame/support/procedural/src/pallet/parse/helper.rs index 538226a8745..3187c9139c8 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/helper.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/helper.rs @@ -148,6 +148,12 @@ impl MutItemAttrs for syn::ImplItemFn { } } +impl MutItemAttrs for syn::ItemType { + fn mut_item_attrs(&mut self) -> Option<&mut Vec> { + Some(&mut self.attrs) + } +} + /// Parse for `()` struct Unit; impl syn::parse::Parse for Unit { diff --git a/substrate/frame/support/procedural/src/runtime/expand/mod.rs b/substrate/frame/support/procedural/src/runtime/expand/mod.rs new file mode 100644 index 00000000000..93c88fce94b --- /dev/null +++ b/substrate/frame/support/procedural/src/runtime/expand/mod.rs @@ -0,0 +1,320 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use super::parse::runtime_types::RuntimeType; +use crate::{ + construct_runtime::{ + check_pallet_number, decl_all_pallets, decl_integrity_test, decl_pallet_runtime_setup, + decl_static_assertions, expand, + }, + runtime::{ + parse::{ + AllPalletsDeclaration, ExplicitAllPalletsDeclaration, ImplicitAllPalletsDeclaration, + }, + Def, + }, +}; +use cfg_expr::Predicate; +use frame_support_procedural_tools::{ + generate_access_from_frame_or_crate, generate_crate_access, generate_hidden_includes, +}; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use std::collections::HashSet; +use syn::{Ident, Result}; + +/// The fixed name of the system pallet. +const SYSTEM_PALLET_NAME: &str = "System"; + +pub fn expand(def: Def, legacy_ordering: bool) -> TokenStream2 { + let input = def.input; + + let (check_pallet_number_res, res) = match def.pallets { + AllPalletsDeclaration::Implicit(ref decl) => ( + check_pallet_number(input.clone(), decl.pallet_count), + construct_runtime_implicit_to_explicit(input.into(), decl.clone(), legacy_ordering), + ), + AllPalletsDeclaration::Explicit(ref decl) => ( + check_pallet_number(input, decl.pallets.len()), + construct_runtime_final_expansion( + def.runtime_struct.ident.clone(), + decl.clone(), + def.runtime_types.clone(), + legacy_ordering, + ), + ), + }; + + let res = res.unwrap_or_else(|e| e.to_compile_error()); + + // We want to provide better error messages to the user and thus, handle the error here + // separately. If there is an error, we print the error and still generate all of the code to + // get in overall less errors for the user. + let res = if let Err(error) = check_pallet_number_res { + let error = error.to_compile_error(); + + quote! { + #error + + #res + } + } else { + res + }; + + let res = expander::Expander::new("construct_runtime") + .dry(std::env::var("FRAME_EXPAND").is_err()) + .verbose(true) + .write_to_out_dir(res) + .expect("Does not fail because of IO in OUT_DIR; qed"); + + res.into() +} + +fn construct_runtime_implicit_to_explicit( + input: TokenStream2, + definition: ImplicitAllPalletsDeclaration, + legacy_ordering: bool, +) -> Result { + let frame_support = generate_access_from_frame_or_crate("frame-support")?; + let attr = if legacy_ordering { quote!((legacy_ordering)) } else { quote!() }; + let mut expansion = quote::quote!( + #[frame_support::runtime #attr] + #input + ); + for pallet in definition.pallet_decls.iter() { + let pallet_path = &pallet.path; + let pallet_name = &pallet.name; + let pallet_instance = pallet.instance.as_ref().map(|instance| quote::quote!(<#instance>)); + expansion = quote::quote!( + #frame_support::__private::tt_call! { + macro = [{ #pallet_path::tt_default_parts_v2 }] + frame_support = [{ #frame_support }] + ~~> #frame_support::match_and_insert! { + target = [{ #expansion }] + pattern = [{ #pallet_name = #pallet_path #pallet_instance }] + } + } + ); + } + + Ok(expansion) +} + +fn construct_runtime_final_expansion( + name: Ident, + definition: ExplicitAllPalletsDeclaration, + runtime_types: Vec, + legacy_ordering: bool, +) -> Result { + let ExplicitAllPalletsDeclaration { mut pallets, name: pallets_name } = definition; + + if !legacy_ordering { + // Ensure that order of hooks is based on the pallet index + pallets.sort_by_key(|p| p.index); + } + + let system_pallet = + pallets.iter().find(|decl| decl.name == SYSTEM_PALLET_NAME).ok_or_else(|| { + syn::Error::new( + pallets_name.span(), + "`System` pallet declaration is missing. \ + Please add this line: `pub type System = frame_system;`", + ) + })?; + if !system_pallet.cfg_pattern.is_empty() { + return Err(syn::Error::new( + system_pallet.name.span(), + "`System` pallet declaration is feature gated, please remove any `#[cfg]` attributes", + )) + } + + let features = pallets + .iter() + .filter_map(|decl| { + (!decl.cfg_pattern.is_empty()).then(|| { + decl.cfg_pattern.iter().flat_map(|attr| { + attr.predicates().filter_map(|pred| match pred { + Predicate::Feature(feat) => Some(feat), + Predicate::Test => Some("test"), + _ => None, + }) + }) + }) + }) + .flatten() + .collect::>(); + + let hidden_crate_name = "construct_runtime"; + let scrate = generate_crate_access(hidden_crate_name, "frame-support"); + let scrate_decl = generate_hidden_includes(hidden_crate_name, "frame-support"); + + let frame_system = generate_access_from_frame_or_crate("frame-system")?; + let block = quote!(<#name as #frame_system::Config>::Block); + let unchecked_extrinsic = quote!(<#block as #scrate::sp_runtime::traits::Block>::Extrinsic); + + let mut dispatch = None; + let mut outer_event = None; + let mut outer_error = None; + let mut outer_origin = None; + let mut freeze_reason = None; + let mut hold_reason = None; + let mut slash_reason = None; + let mut lock_id = None; + let mut task = None; + + for runtime_type in runtime_types.iter() { + match runtime_type { + RuntimeType::RuntimeCall(_) => { + dispatch = + Some(expand::expand_outer_dispatch(&name, system_pallet, &pallets, &scrate)); + }, + RuntimeType::RuntimeEvent(_) => { + outer_event = Some(expand::expand_outer_enum( + &name, + &pallets, + &scrate, + expand::OuterEnumType::Event, + )?); + }, + RuntimeType::RuntimeError(_) => { + outer_error = Some(expand::expand_outer_enum( + &name, + &pallets, + &scrate, + expand::OuterEnumType::Error, + )?); + }, + RuntimeType::RuntimeOrigin(_) => { + outer_origin = + Some(expand::expand_outer_origin(&name, system_pallet, &pallets, &scrate)?); + }, + RuntimeType::RuntimeFreezeReason(_) => { + freeze_reason = Some(expand::expand_outer_freeze_reason(&pallets, &scrate)); + }, + RuntimeType::RuntimeHoldReason(_) => { + hold_reason = Some(expand::expand_outer_hold_reason(&pallets, &scrate)); + }, + RuntimeType::RuntimeSlashReason(_) => { + slash_reason = Some(expand::expand_outer_slash_reason(&pallets, &scrate)); + }, + RuntimeType::RuntimeLockId(_) => { + lock_id = Some(expand::expand_outer_lock_id(&pallets, &scrate)); + }, + RuntimeType::RuntimeTask(_) => { + task = Some(expand::expand_outer_task(&name, &pallets, &scrate)); + }, + } + } + + let all_pallets = decl_all_pallets(&name, pallets.iter(), &features); + let pallet_to_index = decl_pallet_runtime_setup(&name, &pallets, &scrate); + + let metadata = expand::expand_runtime_metadata( + &name, + &pallets, + &scrate, + &unchecked_extrinsic, + &system_pallet.path, + ); + let outer_config = expand::expand_outer_config(&name, &pallets, &scrate); + let inherent = + expand::expand_outer_inherent(&name, &block, &unchecked_extrinsic, &pallets, &scrate); + let validate_unsigned = expand::expand_outer_validate_unsigned(&name, &pallets, &scrate); + let integrity_test = decl_integrity_test(&scrate); + let static_assertions = decl_static_assertions(&name, &pallets, &scrate); + + let res = quote!( + #scrate_decl + + // Prevent UncheckedExtrinsic to print unused warning. + const _: () = { + #[allow(unused)] + type __hidden_use_of_unchecked_extrinsic = #unchecked_extrinsic; + }; + + #[derive( + Clone, Copy, PartialEq, Eq, #scrate::sp_runtime::RuntimeDebug, + #scrate::__private::scale_info::TypeInfo + )] + pub struct #name; + impl #scrate::sp_runtime::traits::GetRuntimeBlockType for #name { + type RuntimeBlock = #block; + } + + // Each runtime must expose the `runtime_metadata()` to fetch the runtime API metadata. + // The function is implemented by calling `impl_runtime_apis!`. + // + // However, the `runtime` may be used without calling `impl_runtime_apis!`. + // Rely on the `Deref` trait to differentiate between a runtime that implements + // APIs (by macro impl_runtime_apis!) and a runtime that is simply created (by macro runtime). + // + // Both `InternalConstructRuntime` and `InternalImplRuntimeApis` expose a `runtime_metadata()` function. + // `InternalConstructRuntime` is implemented by the `runtime` for Runtime references (`& Runtime`), + // while `InternalImplRuntimeApis` is implemented by the `impl_runtime_apis!` for Runtime (`Runtime`). + // + // Therefore, the `Deref` trait will resolve the `runtime_metadata` from `impl_runtime_apis!` + // when both macros are called; and will resolve an empty `runtime_metadata` when only the `runtime` + // is used. + + #[doc(hidden)] + trait InternalConstructRuntime { + #[inline(always)] + fn runtime_metadata(&self) -> #scrate::__private::sp_std::vec::Vec<#scrate::__private::metadata_ir::RuntimeApiMetadataIR> { + Default::default() + } + } + #[doc(hidden)] + impl InternalConstructRuntime for &#name {} + + #outer_event + + #outer_error + + #outer_origin + + #all_pallets + + #pallet_to_index + + #dispatch + + #task + + #metadata + + #outer_config + + #inherent + + #validate_unsigned + + #freeze_reason + + #hold_reason + + #lock_id + + #slash_reason + + #integrity_test + + #static_assertions + ); + + Ok(res) +} diff --git a/substrate/frame/support/procedural/src/runtime/mod.rs b/substrate/frame/support/procedural/src/runtime/mod.rs new file mode 100644 index 00000000000..aaae579eb08 --- /dev/null +++ b/substrate/frame/support/procedural/src/runtime/mod.rs @@ -0,0 +1,236 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Implementation of `runtime`. +//! +//! `runtime` implementation is recursive and can generate code which will call itself +//! in order to get all the pallet parts for each pallet. +//! +//! Pallets can define their parts: +//! - Implicitly: `pub type System = frame_system;` +//! - Explicitly: `pub type System = frame_system + Pallet + Call;` +//! +//! The `runtime` transitions from the implicit definition to the explicit one. +//! From the explicit state, Substrate expands the pallets with additional information +//! that is to be included in the runtime metadata. +//! +//! Pallets must provide the `tt_default_parts_v2` macro for these transitions. +//! These are automatically implemented by the `#[pallet::pallet]` macro. +//! +//! This macro also generates the following enums for ease of decoding if the respective type +//! is defined inside `#[runtime::derive]`: +//! - `enum RuntimeCall`: This type contains the information needed to decode extrinsics. +//! - `enum RuntimeEvent`: This type contains the information needed to decode events. +//! - `enum RuntimeError`: While this cannot be used directly to decode `sp_runtime::DispatchError` +//! from the chain, it contains the information needed to decode the +//! `sp_runtime::DispatchError::Module`. +//! +//! # State Transitions +//! +//! ```ignore +//! +----------+ +//! | Implicit | +//! +----------+ +//! | +//! v +//! +----------+ +//! | Explicit | +//! +----------+ +//! ``` +//! +//! The `runtime` macro transforms the implicit declaration of each pallet +//! `System: frame_system` to an explicit one `System: frame_system + Pallet + Call` using the +//! `tt_default_parts_v2` macro. +//! +//! The `tt_default_parts_v2` macro exposes a plus separated list of pallet parts. For example, the +//! `Event` part is exposed only if the pallet implements an event via `#[pallet::event]` macro. +//! The tokens generated by this macro are `+ Pallet + Call` for our example. +//! +//! The `match_and_insert` macro takes in 3 arguments: +//! - target: This is the `TokenStream` that contains the `runtime` macro. +//! - pattern: The pattern to match against in the target stream. +//! - tokens: The tokens to added after the pattern match. +//! +//! The `runtime` macro uses the `tt_call` to get the default pallet parts via +//! the `tt_default_parts_v2` macro defined by each pallet. The pallet parts are then returned as +//! input to the `match_and_replace` macro. +//! The `match_and_replace` then will modify the `runtime` to expand the implicit +//! definition to the explicit one. +//! +//! For example, +//! +//! ```ignore +//! #[frame_support::runtime] +//! mod runtime { +//! //... +//! +//! #[runtime::pallet_index(0)] +//! pub type System = frame_system; // Implicit definition of parts +//! +//! #[runtime::pallet_index(1)] +//! pub type Balances = pallet_balances; // Implicit definition of parts +//! } +//! ``` +//! This call has some implicit pallet parts, thus it will expand to: +//! ```ignore +//! frame_support::__private::tt_call! { +//! macro = [{ pallet_balances::tt_default_parts_v2 }] +//! ~~> frame_support::match_and_insert! { +//! target = [{ +//! frame_support::__private::tt_call! { +//! macro = [{ frame_system::tt_default_parts_v2 }] +//! ~~> frame_support::match_and_insert! { +//! target = [{ +//! #[frame_support::runtime] +//! mod runtime { +//! //... +//! +//! #[runtime::pallet_index(0)] +//! pub type System = frame_system; +//! +//! #[runtime::pallet_index(1)] +//! pub type Balances = pallet_balances; +//! } +//! }] +//! pattern = [{ System = frame_system }] +//! } +//! } +//! }] +//! pattern = [{ Balances = pallet_balances }] +//! } +//! } +//! ``` +//! `tt_default_parts_v2` must be defined. It returns the pallet parts inside some tokens, and +//! then `tt_call` will pipe the returned pallet parts into the input of `match_and_insert`. +//! Thus `match_and_insert` will initially receive the following inputs: +//! ```ignore +//! frame_support::match_and_insert! { +//! target = [{ +//! frame_support::match_and_insert! { +//! target = [{ +//! #[frame_support::runtime] +//! mod runtime { +//! //... +//! +//! #[runtime::pallet_index(0)] +//! pub type System = frame_system; +//! +//! #[runtime::pallet_index(1)] +//! pub type Balances = pallet_balances; +//! } +//! }] +//! pattern = [{ System = frame_system }] +//! tokens = [{ ::{+ Pallet + Call} }] +//! } +//! }] +//! pattern = [{ Balances = pallet_balances }] +//! tokens = [{ ::{+ Pallet + Call} }] +//! } +//! ``` +//! After dealing with `pallet_balances`, the inner `match_and_insert` will expand to: +//! ```ignore +//! frame_support::match_and_insert! { +//! target = [{ +//! #[frame_support::runtime] +//! mod runtime { +//! //... +//! +//! #[runtime::pallet_index(0)] +//! pub type System = frame_system; // Implicit definition of parts +//! +//! #[runtime::pallet_index(1)] +//! pub type Balances = pallet_balances + Pallet + Call; // Explicit definition of parts +//! } +//! }] +//! pattern = [{ System = frame_system }] +//! tokens = [{ ::{+ Pallet + Call} }] +//! } +//! ``` +//! +//! Which will then finally expand to the following: +//! ```ignore +//! #[frame_support::runtime] +//! mod runtime { +//! //... +//! +//! #[runtime::pallet_index(0)] +//! pub type System = frame_system + Pallet + Call; +//! +//! #[runtime::pallet_index(1)] +//! pub type Balances = pallet_balances + Pallet + Call; +//! } +//! ``` +//! +//! This call has no implicit pallet parts, thus it will expand to the runtime construction: +//! ```ignore +//! pub struct Runtime { ... } +//! pub struct Call { ... } +//! impl Call ... +//! pub enum Origin { ... } +//! ... +//! ``` +//! +//! Visualizing the entire flow of `#[frame_support::runtime]`, it would look like the following: +//! +//! ```ignore +//! +----------------------+ +------------------------+ +-------------------+ +//! | | | (defined in pallet) | | | +//! | runtime | --> | tt_default_parts_v2! | --> | match_and_insert! | +//! | w/ no pallet parts | | | | | +//! +----------------------+ +------------------------+ +-------------------+ +//! +//! +----------------------+ +//! | | +//! --> | runtime | +//! | w/ pallet parts | +//! +----------------------+ +//! ``` + +#![cfg(feature = "experimental")] + +pub use parse::Def; +use proc_macro::TokenStream; +use syn::spanned::Spanned; + +mod expand; +mod parse; + +mod keyword { + syn::custom_keyword!(legacy_ordering); +} + +pub fn runtime(attr: TokenStream, tokens: TokenStream) -> TokenStream { + let mut legacy_ordering = false; + if !attr.is_empty() { + if let Ok(_) = syn::parse::(attr.clone()) { + legacy_ordering = true; + } else { + let msg = "Invalid runtime macro call: unexpected attribute. Macro call must be \ + bare, such as `#[frame_support::runtime]` or `#[runtime]`, or must specify the \ + `legacy_ordering` attribute, such as `#[frame_support::runtime(legacy_ordering)]` or \ + #[runtime(legacy_ordering)]."; + let span = proc_macro2::TokenStream::from(attr).span(); + return syn::Error::new(span, msg).to_compile_error().into() + } + } + + let item = syn::parse_macro_input!(tokens as syn::ItemMod); + match parse::Def::try_from(item) { + Ok(def) => expand::expand(def, legacy_ordering).into(), + Err(e) => e.to_compile_error().into(), + } +} diff --git a/substrate/frame/support/procedural/src/runtime/parse/helper.rs b/substrate/frame/support/procedural/src/runtime/parse/helper.rs new file mode 100644 index 00000000000..f05395f9b7a --- /dev/null +++ b/substrate/frame/support/procedural/src/runtime/parse/helper.rs @@ -0,0 +1,37 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use crate::pallet::parse::helper::MutItemAttrs; +use quote::ToTokens; + +pub(crate) fn take_first_item_runtime_attr( + item: &mut impl MutItemAttrs, +) -> syn::Result> +where + Attr: syn::parse::Parse, +{ + let attrs = if let Some(attrs) = item.mut_item_attrs() { attrs } else { return Ok(None) }; + + if let Some(index) = attrs.iter().position(|attr| { + attr.path().segments.first().map_or(false, |segment| segment.ident == "runtime") + }) { + let runtime_attr = attrs.remove(index); + Ok(Some(syn::parse2(runtime_attr.into_token_stream())?)) + } else { + Ok(None) + } +} diff --git a/substrate/frame/support/procedural/src/runtime/parse/mod.rs b/substrate/frame/support/procedural/src/runtime/parse/mod.rs new file mode 100644 index 00000000000..893cb4726e2 --- /dev/null +++ b/substrate/frame/support/procedural/src/runtime/parse/mod.rs @@ -0,0 +1,266 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +pub mod helper; +pub mod pallet; +pub mod pallet_decl; +pub mod runtime_struct; +pub mod runtime_types; + +use crate::construct_runtime::parse::Pallet; +use pallet_decl::PalletDeclaration; +use proc_macro2::TokenStream as TokenStream2; +use quote::ToTokens; +use std::collections::HashMap; +use syn::{spanned::Spanned, Ident, Token}; + +use frame_support_procedural_tools::syn_ext as ext; +use runtime_types::RuntimeType; + +mod keyword { + use syn::custom_keyword; + + custom_keyword!(runtime); + custom_keyword!(derive); + custom_keyword!(pallet_index); + custom_keyword!(disable_call); + custom_keyword!(disable_unsigned); +} + +enum RuntimeAttr { + Runtime(proc_macro2::Span), + Derive(proc_macro2::Span, Vec), + PalletIndex(proc_macro2::Span, u8), + DisableCall(proc_macro2::Span), + DisableUnsigned(proc_macro2::Span), +} + +impl RuntimeAttr { + fn span(&self) -> proc_macro2::Span { + match self { + Self::Runtime(span) => *span, + Self::Derive(span, _) => *span, + Self::PalletIndex(span, _) => *span, + Self::DisableCall(span) => *span, + Self::DisableUnsigned(span) => *span, + } + } +} + +impl syn::parse::Parse for RuntimeAttr { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + input.parse::()?; + let content; + syn::bracketed!(content in input); + content.parse::()?; + content.parse::()?; + + let lookahead = content.lookahead1(); + if lookahead.peek(keyword::runtime) { + Ok(RuntimeAttr::Runtime(content.parse::()?.span())) + } else if lookahead.peek(keyword::derive) { + let _ = content.parse::(); + let derive_content; + syn::parenthesized!(derive_content in content); + let runtime_types = + derive_content.parse::>()?; + let runtime_types = runtime_types.inner.into_iter().collect(); + Ok(RuntimeAttr::Derive(derive_content.span(), runtime_types)) + } else if lookahead.peek(keyword::pallet_index) { + let _ = content.parse::(); + let pallet_index_content; + syn::parenthesized!(pallet_index_content in content); + let pallet_index = pallet_index_content.parse::()?; + if !pallet_index.suffix().is_empty() { + let msg = "Number literal must not have a suffix"; + return Err(syn::Error::new(pallet_index.span(), msg)) + } + Ok(RuntimeAttr::PalletIndex(pallet_index.span(), pallet_index.base10_parse()?)) + } else if lookahead.peek(keyword::disable_call) { + Ok(RuntimeAttr::DisableCall(content.parse::()?.span())) + } else if lookahead.peek(keyword::disable_unsigned) { + Ok(RuntimeAttr::DisableUnsigned(content.parse::()?.span())) + } else { + Err(lookahead.error()) + } + } +} + +#[derive(Debug, Clone)] +pub enum AllPalletsDeclaration { + Implicit(ImplicitAllPalletsDeclaration), + Explicit(ExplicitAllPalletsDeclaration), +} + +/// Declaration of a runtime with some pallet with implicit declaration of parts. +#[derive(Debug, Clone)] +pub struct ImplicitAllPalletsDeclaration { + pub name: Ident, + pub pallet_decls: Vec, + pub pallet_count: usize, +} + +/// Declaration of a runtime with all pallet having explicit declaration of parts. +#[derive(Debug, Clone)] +pub struct ExplicitAllPalletsDeclaration { + pub name: Ident, + pub pallets: Vec, +} + +pub struct Def { + pub input: TokenStream2, + pub item: syn::ItemMod, + pub runtime_struct: runtime_struct::RuntimeStructDef, + pub pallets: AllPalletsDeclaration, + pub runtime_types: Vec, +} + +impl Def { + pub fn try_from(mut item: syn::ItemMod) -> syn::Result { + let input: TokenStream2 = item.to_token_stream().into(); + let item_span = item.span(); + let items = &mut item + .content + .as_mut() + .ok_or_else(|| { + let msg = "Invalid runtime definition, expected mod to be inlined."; + syn::Error::new(item_span, msg) + })? + .1; + + let mut runtime_struct = None; + let mut runtime_types = None; + + let mut indices = HashMap::new(); + let mut names = HashMap::new(); + + let mut pallet_decls = vec![]; + let mut pallets = vec![]; + + for item in items.iter_mut() { + let mut pallet_item = None; + let mut pallet_index = 0; + + let mut disable_call = false; + let mut disable_unsigned = false; + + while let Some(runtime_attr) = + helper::take_first_item_runtime_attr::(item)? + { + match runtime_attr { + RuntimeAttr::Runtime(span) if runtime_struct.is_none() => { + let p = runtime_struct::RuntimeStructDef::try_from(span, item)?; + runtime_struct = Some(p); + }, + RuntimeAttr::Derive(_, types) if runtime_types.is_none() => { + runtime_types = Some(types); + }, + RuntimeAttr::PalletIndex(span, index) => { + pallet_index = index; + pallet_item = if let syn::Item::Type(item) = item { + Some(item.clone()) + } else { + let msg = "Invalid runtime::pallet_index, expected type definition"; + return Err(syn::Error::new(span, msg)) + }; + }, + RuntimeAttr::DisableCall(_) => disable_call = true, + RuntimeAttr::DisableUnsigned(_) => disable_unsigned = true, + attr => { + let msg = "Invalid duplicated attribute"; + return Err(syn::Error::new(attr.span(), msg)) + }, + } + } + + if let Some(pallet_item) = pallet_item { + match *pallet_item.ty.clone() { + syn::Type::Path(ref path) => { + let pallet_decl = + PalletDeclaration::try_from(item.span(), &pallet_item, path)?; + + if let Some(used_pallet) = + names.insert(pallet_decl.name.clone(), pallet_decl.name.span()) + { + let msg = "Two pallets with the same name!"; + + let mut err = syn::Error::new(used_pallet, &msg); + err.combine(syn::Error::new(pallet_decl.name.span(), &msg)); + return Err(err) + } + + pallet_decls.push(pallet_decl); + }, + syn::Type::TraitObject(syn::TypeTraitObject { bounds, .. }) => { + let pallet = Pallet::try_from( + item.span(), + &pallet_item, + pallet_index, + disable_call, + disable_unsigned, + &bounds, + )?; + + if let Some(used_pallet) = indices.insert(pallet.index, pallet.name.clone()) + { + let msg = format!( + "Pallet indices are conflicting: Both pallets {} and {} are at index {}", + used_pallet, pallet.name, pallet.index, + ); + let mut err = syn::Error::new(used_pallet.span(), &msg); + err.combine(syn::Error::new(pallet.name.span(), msg)); + return Err(err) + } + + pallets.push(pallet); + }, + _ => continue, + } + } + } + + let name = item.ident.clone(); + let decl_count = pallet_decls.len(); + let pallets = if decl_count > 0 { + AllPalletsDeclaration::Implicit(ImplicitAllPalletsDeclaration { + name, + pallet_decls, + pallet_count: decl_count.saturating_add(pallets.len()), + }) + } else { + AllPalletsDeclaration::Explicit(ExplicitAllPalletsDeclaration { name, pallets }) + }; + + let def = Def { + input, + item, + runtime_struct: runtime_struct.ok_or_else(|| { + syn::Error::new(item_span, + "Missing Runtime. Please add a struct inside the module and annotate it with `#[runtime::runtime]`" + ) + })?, + pallets, + runtime_types: runtime_types.ok_or_else(|| { + syn::Error::new(item_span, + "Missing Runtime Types. Please annotate the runtime struct with `#[runtime::derive]`" + ) + })?, + }; + + Ok(def) + } +} diff --git a/substrate/frame/support/procedural/src/runtime/parse/pallet.rs b/substrate/frame/support/procedural/src/runtime/parse/pallet.rs new file mode 100644 index 00000000000..d2f1857fb2b --- /dev/null +++ b/substrate/frame/support/procedural/src/runtime/parse/pallet.rs @@ -0,0 +1,99 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use crate::construct_runtime::parse::{Pallet, PalletPart, PalletPartKeyword, PalletPath}; +use quote::ToTokens; +use syn::{punctuated::Punctuated, spanned::Spanned, token, Error, Ident, PathArguments}; + +impl Pallet { + pub fn try_from( + attr_span: proc_macro2::Span, + item: &syn::ItemType, + pallet_index: u8, + disable_call: bool, + disable_unsigned: bool, + bounds: &Punctuated, + ) -> syn::Result { + let name = item.ident.clone(); + + let mut pallet_path = None; + let mut pallet_parts = vec![]; + + for (index, bound) in bounds.into_iter().enumerate() { + if let syn::TypeParamBound::Trait(syn::TraitBound { path, .. }) = bound { + if index == 0 { + pallet_path = Some(PalletPath { inner: path.clone() }); + } else { + let pallet_part = syn::parse2::(bound.into_token_stream())?; + pallet_parts.push(pallet_part); + } + } else { + return Err(Error::new( + attr_span, + "Invalid pallet declaration, expected a path or a trait object", + )) + }; + } + + let mut path = pallet_path.ok_or(Error::new( + attr_span, + "Invalid pallet declaration, expected a path or a trait object", + ))?; + + let mut instance = None; + if let Some(segment) = path.inner.segments.iter_mut().find(|seg| !seg.arguments.is_empty()) + { + if let PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { + args, .. + }) = segment.arguments.clone() + { + if let Some(syn::GenericArgument::Type(syn::Type::Path(arg_path))) = args.first() { + instance = + Some(Ident::new(&arg_path.to_token_stream().to_string(), arg_path.span())); + segment.arguments = PathArguments::None; + } + } + } + + pallet_parts = pallet_parts + .into_iter() + .filter(|part| { + if let (true, &PalletPartKeyword::Call(_)) = (disable_call, &part.keyword) { + false + } else if let (true, &PalletPartKeyword::ValidateUnsigned(_)) = + (disable_unsigned, &part.keyword) + { + false + } else { + true + } + }) + .collect(); + + let cfg_pattern = vec![]; + + Ok(Pallet { + is_expanded: true, + name, + index: pallet_index, + path, + instance, + cfg_pattern, + pallet_parts, + }) + } +} diff --git a/substrate/frame/support/procedural/src/runtime/parse/pallet_decl.rs b/substrate/frame/support/procedural/src/runtime/parse/pallet_decl.rs new file mode 100644 index 00000000000..437a163cfbc --- /dev/null +++ b/substrate/frame/support/procedural/src/runtime/parse/pallet_decl.rs @@ -0,0 +1,60 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use quote::ToTokens; +use syn::{spanned::Spanned, Attribute, Ident, PathArguments}; + +/// The declaration of a pallet. +#[derive(Debug, Clone)] +pub struct PalletDeclaration { + /// The name of the pallet, e.g.`System` in `System: frame_system`. + pub name: Ident, + /// Optional attributes tagged right above a pallet declaration. + pub attrs: Vec, + /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. + pub path: syn::Path, + /// The instance of the pallet, e.g. `Instance1` in `Council: pallet_collective::`. + pub instance: Option, +} + +impl PalletDeclaration { + pub fn try_from( + _attr_span: proc_macro2::Span, + item: &syn::ItemType, + path: &syn::TypePath, + ) -> syn::Result { + let name = item.ident.clone(); + + let mut path = path.path.clone(); + + let mut instance = None; + if let Some(segment) = path.segments.iter_mut().find(|seg| !seg.arguments.is_empty()) { + if let PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { + args, .. + }) = segment.arguments.clone() + { + if let Some(syn::GenericArgument::Type(syn::Type::Path(arg_path))) = args.first() { + instance = + Some(Ident::new(&arg_path.to_token_stream().to_string(), arg_path.span())); + segment.arguments = PathArguments::None; + } + } + } + + Ok(Self { name, path, instance, attrs: item.attrs.clone() }) + } +} diff --git a/substrate/frame/support/procedural/src/runtime/parse/runtime_struct.rs b/substrate/frame/support/procedural/src/runtime/parse/runtime_struct.rs new file mode 100644 index 00000000000..8fa746ee807 --- /dev/null +++ b/substrate/frame/support/procedural/src/runtime/parse/runtime_struct.rs @@ -0,0 +1,35 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use syn::spanned::Spanned; +pub struct RuntimeStructDef { + pub ident: syn::Ident, + pub attr_span: proc_macro2::Span, +} + +impl RuntimeStructDef { + pub fn try_from(attr_span: proc_macro2::Span, item: &mut syn::Item) -> syn::Result { + let item = if let syn::Item::Struct(item) = item { + item + } else { + let msg = "Invalid runtime::runtime, expected struct definition"; + return Err(syn::Error::new(item.span(), msg)) + }; + + Ok(Self { ident: item.ident.clone(), attr_span }) + } +} diff --git a/substrate/frame/support/procedural/src/runtime/parse/runtime_types.rs b/substrate/frame/support/procedural/src/runtime/parse/runtime_types.rs new file mode 100644 index 00000000000..a4480e2a1fd --- /dev/null +++ b/substrate/frame/support/procedural/src/runtime/parse/runtime_types.rs @@ -0,0 +1,76 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use syn::{ + parse::{Parse, ParseStream}, + Result, +}; + +mod keyword { + use syn::custom_keyword; + + custom_keyword!(RuntimeCall); + custom_keyword!(RuntimeEvent); + custom_keyword!(RuntimeError); + custom_keyword!(RuntimeOrigin); + custom_keyword!(RuntimeFreezeReason); + custom_keyword!(RuntimeHoldReason); + custom_keyword!(RuntimeSlashReason); + custom_keyword!(RuntimeLockId); + custom_keyword!(RuntimeTask); +} + +#[derive(Debug, Clone, PartialEq)] +pub enum RuntimeType { + RuntimeCall(keyword::RuntimeCall), + RuntimeEvent(keyword::RuntimeEvent), + RuntimeError(keyword::RuntimeError), + RuntimeOrigin(keyword::RuntimeOrigin), + RuntimeFreezeReason(keyword::RuntimeFreezeReason), + RuntimeHoldReason(keyword::RuntimeHoldReason), + RuntimeSlashReason(keyword::RuntimeSlashReason), + RuntimeLockId(keyword::RuntimeLockId), + RuntimeTask(keyword::RuntimeTask), +} + +impl Parse for RuntimeType { + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + + if lookahead.peek(keyword::RuntimeCall) { + Ok(Self::RuntimeCall(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeEvent) { + Ok(Self::RuntimeEvent(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeError) { + Ok(Self::RuntimeError(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeOrigin) { + Ok(Self::RuntimeOrigin(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeFreezeReason) { + Ok(Self::RuntimeFreezeReason(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeHoldReason) { + Ok(Self::RuntimeHoldReason(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeSlashReason) { + Ok(Self::RuntimeSlashReason(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeLockId) { + Ok(Self::RuntimeLockId(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeTask) { + Ok(Self::RuntimeTask(input.parse()?)) + } else { + Err(lookahead.error()) + } + } +} diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 07560abd935..af8449c9697 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -510,6 +510,9 @@ pub use frame_support_procedural::{ construct_runtime, match_and_insert, transactional, PalletError, RuntimeDebugNoBound, }; +#[cfg(feature = "experimental")] +pub use frame_support_procedural::runtime; + #[doc(hidden)] pub use frame_support_procedural::{__create_tt_macro, __generate_dummy_part_checker}; diff --git a/substrate/frame/support/test/Cargo.toml b/substrate/frame/support/test/Cargo.toml index ae2c56a531f..2f12cc00ed9 100644 --- a/substrate/frame/support/test/Cargo.toml +++ b/substrate/frame/support/test/Cargo.toml @@ -24,7 +24,7 @@ sp-api = { path = "../../../primitives/api", default-features = false } sp-arithmetic = { path = "../../../primitives/arithmetic", default-features = false } sp-io = { path = "../../../primitives/io", default-features = false } sp-state-machine = { path = "../../../primitives/state-machine", optional = true } -frame-support = { path = "..", default-features = false } +frame-support = { path = "..", default-features = false, features = ["experimental"] } frame-benchmarking = { path = "../../benchmarking", default-features = false } sp-runtime = { path = "../../../primitives/runtime", default-features = false } sp-core = { path = "../../../primitives/core", default-features = false } diff --git a/substrate/frame/support/test/tests/construct_runtime.rs b/substrate/frame/support/test/tests/runtime.rs similarity index 89% rename from substrate/frame/support/test/tests/construct_runtime.rs rename to substrate/frame/support/test/tests/runtime.rs index 83691451ccd..7e33ee46458 100644 --- a/substrate/frame/support/test/tests/construct_runtime.rs +++ b/substrate/frame/support/test/tests/runtime.rs @@ -30,7 +30,7 @@ use scale_info::TypeInfo; use sp_core::{sr25519, ConstU64}; use sp_runtime::{ generic, - traits::{BlakeTwo256, Verify}, + traits::{BlakeTwo256, ValidateUnsigned, Verify}, DispatchError, ModuleError, }; use sp_version::RuntimeVersion; @@ -176,6 +176,17 @@ mod nested { impl BuildGenesisConfig for GenesisConfig { fn build(&self) {} } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + fn validate_unsigned( + _source: TransactionSource, + _call: &Self::Call, + ) -> TransactionValidity { + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + } + } } } @@ -247,6 +258,20 @@ pub mod module3 { impl BuildGenesisConfig for GenesisConfig { fn build(&self) {} } + + #[pallet::storage] + pub type Storage = StorageValue<_, u32>; + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + fn validate_unsigned( + _source: TransactionSource, + _call: &Self::Call, + ) -> TransactionValidity { + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + } + } } pub type BlockNumber = u64; @@ -256,24 +281,64 @@ pub type Header = generic::Header; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; pub type Block = generic::Block; -frame_support::construct_runtime!( - pub struct Runtime - { - System: frame_system::{Pallet, Call, Event, Origin} = 30, - Module1_1: module1::::{Pallet, Call, Storage, Event, Origin}, - Module2: module2::{Pallet, Call, Storage, Event, Origin}, - Module1_2: module1::::{Pallet, Call, Storage, Event, Origin}, - NestedModule3: nested::module3::{Pallet, Call, Config, Storage, Event, Origin}, - Module3: self::module3::{Pallet, Call, Config, Storage, Event, Origin}, - Module1_3: module1::::{Pallet, Storage, Event } = 6, - Module1_4: module1::::{Pallet, Call, Event } = 3, - Module1_5: module1::::{Pallet, Event}, - Module1_6: module1::::{Pallet, Call, Storage, Event, Origin} = 1, - Module1_7: module1::::{Pallet, Call, Storage, Event, Origin}, - Module1_8: module1::::{Pallet, Call, Storage, Event, Origin} = 12, - Module1_9: module1::::{Pallet, Call, Storage, Event, Origin}, - } -); +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + #[runtime::pallet_index(30)] + pub type System = frame_system + Pallet + Call + Event + Origin; + + #[runtime::pallet_index(31)] + pub type Module1_1 = module1; + + #[runtime::pallet_index(32)] + pub type Module2 = module2; + + #[runtime::pallet_index(33)] + pub type Module1_2 = module1; + + #[runtime::pallet_index(34)] + pub type NestedModule3 = nested::module3; + + #[runtime::pallet_index(35)] + #[runtime::disable_unsigned] + pub type Module3 = self::module3; + + #[runtime::pallet_index(6)] + #[runtime::disable_call] + pub type Module1_3 = module1; + + #[runtime::pallet_index(3)] + pub type Module1_4 = module1; + + #[runtime::pallet_index(4)] + #[runtime::disable_call] + pub type Module1_5 = module1; + + #[runtime::pallet_index(1)] + pub type Module1_6 = module1; + + #[runtime::pallet_index(2)] + pub type Module1_7 = module1; + + #[runtime::pallet_index(12)] + pub type Module1_8 = module1; + + #[runtime::pallet_index(13)] + pub type Module1_9 = module1; +} #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Runtime { @@ -605,17 +670,17 @@ fn get_module_names() { let module_names = RuntimeCall::get_module_names(); assert_eq!( [ + "Module1_6", + "Module1_7", + "Module1_4", + "Module1_8", + "Module1_9", "System", "Module1_1", "Module2", "Module1_2", "NestedModule3", "Module3", - "Module1_4", - "Module1_6", - "Module1_7", - "Module1_8", - "Module1_9", ], module_names ); @@ -636,9 +701,13 @@ fn call_subtype_conversion() { #[test] fn test_metadata() { - use frame_metadata::{v14::*, *}; + use frame_metadata::{ + v14::{StorageEntryType::Plain, *}, + *, + }; use scale_info::meta_type; use sp_core::Encode; + use sp_metadata_ir::StorageEntryModifierIR::Optional; fn maybe_docs(doc: Vec<&'static str>) -> Vec<&'static str> { if cfg!(feature = "no-metadata-docs") { @@ -649,6 +718,69 @@ fn test_metadata() { } let pallets = vec![ + PalletMetadata { + name: "Module1_6", + storage:None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 1, + }, + PalletMetadata { + name: "Module1_7", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 2, + }, + PalletMetadata { + name: "Module1_4", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 3, + }, + PalletMetadata { + name: "Module1_5", + storage: None, + calls: None, + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 4, + }, + PalletMetadata { + name: "Module1_3", + storage: None, + calls: None, + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 6, + }, + PalletMetadata { + name: "Module1_8", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 12, + }, + PalletMetadata { + name: "Module1_9", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 13, + }, PalletMetadata { name: "System", storage: None, @@ -703,7 +835,7 @@ fn test_metadata() { }, PalletMetadata { name: "Module1_1", - storage: Some(PalletStorageMetadata { prefix: "Module1_1", entries: vec![] }), + storage: None, calls: Some(meta_type::>().into()), event: Some(meta_type::>().into()), constants: vec![], @@ -712,7 +844,7 @@ fn test_metadata() { }, PalletMetadata { name: "Module2", - storage: Some(PalletStorageMetadata { prefix: "Module2", entries: vec![] }), + storage: None, calls: Some(meta_type::>().into()), event: Some(meta_type::>().into()), constants: vec![], @@ -721,7 +853,7 @@ fn test_metadata() { }, PalletMetadata { name: "Module1_2", - storage: Some(PalletStorageMetadata { prefix: "Module1_2", entries: vec![] }), + storage: None, calls: Some(meta_type::>().into()), event: Some(meta_type::>().into()), constants: vec![], @@ -730,7 +862,7 @@ fn test_metadata() { }, PalletMetadata { name: "NestedModule3", - storage: Some(PalletStorageMetadata { prefix: "NestedModule3", entries: vec![] }), + storage: None, calls: Some(meta_type::>().into()), event: Some(meta_type::>().into()), constants: vec![], @@ -739,76 +871,24 @@ fn test_metadata() { }, PalletMetadata { name: "Module3", - storage: Some(PalletStorageMetadata { prefix: "Module3", entries: vec![] }), + storage: Some(PalletStorageMetadata { + prefix: "Module3", + entries: vec![ + StorageEntryMetadata { + name: "Storage", + modifier: Optional.into(), + ty: Plain(meta_type::().into()), + default: vec![0], + docs: vec![], + }, + ] + }), calls: Some(meta_type::>().into()), event: Some(meta_type::>().into()), constants: vec![], error: Some(meta_type::>().into()), index: 35, }, - PalletMetadata { - name: "Module1_3", - storage: Some(PalletStorageMetadata { prefix: "Module1_3", entries: vec![] }), - calls: None, - event: Some(meta_type::>().into()), - constants: vec![], - error: Some(meta_type::>().into()), - index: 6, - }, - PalletMetadata { - name: "Module1_4", - storage: None, - calls: Some(meta_type::>().into()), - event: Some(meta_type::>().into()), - constants: vec![], - error: Some(meta_type::>().into()), - index: 3, - }, - PalletMetadata { - name: "Module1_5", - storage: None, - calls: None, - event: Some(meta_type::>().into()), - constants: vec![], - error: Some(meta_type::>().into()), - index: 4, - }, - PalletMetadata { - name: "Module1_6", - storage: Some(PalletStorageMetadata { prefix: "Module1_6", entries: vec![] }), - calls: Some(meta_type::>().into()), - event: Some(meta_type::>().into()), - constants: vec![], - error: Some(meta_type::>().into()), - index: 1, - }, - PalletMetadata { - name: "Module1_7", - storage: Some(PalletStorageMetadata { prefix: "Module1_7", entries: vec![] }), - calls: Some(meta_type::>().into()), - event: Some(meta_type::>().into()), - constants: vec![], - error: Some(meta_type::>().into()), - index: 2, - }, - PalletMetadata { - name: "Module1_8", - storage: Some(PalletStorageMetadata { prefix: "Module1_8", entries: vec![] }), - calls: Some(meta_type::>().into()), - event: Some(meta_type::>().into()), - constants: vec![], - error: Some(meta_type::>().into()), - index: 12, - }, - PalletMetadata { - name: "Module1_9", - storage: Some(PalletStorageMetadata { prefix: "Module1_9", entries: vec![] }), - calls: Some(meta_type::>().into()), - event: Some(meta_type::>().into()), - constants: vec![], - error: Some(meta_type::>().into()), - index: 13, - }, ]; let extrinsic = ExtrinsicMetadata { @@ -895,3 +975,19 @@ fn pallet_in_runtime_is_correct() { assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); assert!(PalletInfo::crate_version::().is_some()); } + +#[test] +fn test_validate_unsigned() { + use frame_support::pallet_prelude::*; + + let call = RuntimeCall::NestedModule3(nested::module3::Call::fail {}); + let validity = Runtime::validate_unsigned(TransactionSource::Local, &call).unwrap_err(); + assert_eq!(validity, TransactionValidityError::Invalid(InvalidTransaction::Call)); + + let call = RuntimeCall::Module3(module3::Call::fail {}); + let validity = Runtime::validate_unsigned(TransactionSource::Local, &call).unwrap_err(); + assert_eq!( + validity, + TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator) + ); +} diff --git a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs new file mode 100644 index 00000000000..38875517018 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs @@ -0,0 +1,993 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! General tests for construct_runtime macro, test for: +//! * error declared with decl_error works +//! * integrity test is generated + +#![recursion_limit = "128"] + +use codec::MaxEncodedLen; +use frame_support::{ + derive_impl, parameter_types, traits::PalletInfo as _, weights::RuntimeDbWeight, +}; +use frame_system::limits::{BlockLength, BlockWeights}; +use scale_info::TypeInfo; +use sp_core::{sr25519, ConstU64}; +use sp_runtime::{ + generic, + traits::{BlakeTwo256, ValidateUnsigned, Verify}, + DispatchError, ModuleError, +}; +use sp_version::RuntimeVersion; + +parameter_types! { + pub static IntegrityTestExec: u32 = 0; +} + +#[frame_support::pallet(dev_mode)] +mod module1 { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + + IsType<::RuntimeEvent>; + } + + #[pallet::call] + impl, I: 'static> Pallet { + pub fn fail(_origin: OriginFor) -> DispatchResult { + Err(Error::::Something.into()) + } + } + + #[pallet::origin] + #[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)] + #[scale_info(skip_type_params(I))] + pub struct Origin(pub PhantomData<(T, I)>); + + #[pallet::event] + pub enum Event, I: 'static = ()> { + A(::AccountId), + } + + #[pallet::error] + pub enum Error { + Something, + } +} + +#[frame_support::pallet(dev_mode)] +mod module2 { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + IntegrityTestExec::mutate(|i| *i += 1); + } + } + + #[pallet::call] + impl Pallet { + pub fn fail(_origin: OriginFor) -> DispatchResult { + Err(Error::::Something.into()) + } + } + + #[pallet::origin] + #[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)] + pub struct Origin; + + #[pallet::event] + pub enum Event { + A, + } + + #[pallet::error] + pub enum Error { + Something, + } +} + +mod nested { + use super::*; + + #[frame_support::pallet(dev_mode)] + pub mod module3 { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + + IsType<::RuntimeEvent>; + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + IntegrityTestExec::mutate(|i| *i += 1); + } + } + + #[pallet::call] + impl Pallet { + pub fn fail(_origin: OriginFor) -> DispatchResult { + Err(Error::::Something.into()) + } + } + + #[pallet::origin] + #[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)] + pub struct Origin; + + #[pallet::event] + pub enum Event { + A, + } + + #[pallet::error] + pub enum Error { + Something, + } + + #[pallet::genesis_config] + #[derive(frame_support::DefaultNoBound)] + pub struct GenesisConfig { + #[serde(skip)] + pub _config: sp_std::marker::PhantomData, + } + + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) {} + } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + fn validate_unsigned( + _source: TransactionSource, + _call: &Self::Call, + ) -> TransactionValidity { + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + } + } + } +} + +#[frame_support::pallet(dev_mode)] +pub mod module3 { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::call] + impl Pallet { + pub fn fail(_origin: OriginFor) -> DispatchResult { + Err(Error::::Something.into()) + } + pub fn aux_1(_origin: OriginFor, #[pallet::compact] _data: u32) -> DispatchResult { + unreachable!() + } + pub fn aux_2( + _origin: OriginFor, + _data: i32, + #[pallet::compact] _data2: u32, + ) -> DispatchResult { + unreachable!() + } + #[pallet::weight(0)] + pub fn aux_3(_origin: OriginFor, _data: i32, _data2: String) -> DispatchResult { + unreachable!() + } + #[pallet::weight(3)] + pub fn aux_4(_origin: OriginFor) -> DispatchResult { + unreachable!() + } + #[pallet::weight((5, DispatchClass::Operational))] + pub fn operational(_origin: OriginFor) -> DispatchResult { + unreachable!() + } + } + + #[pallet::origin] + #[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)] + pub struct Origin(pub PhantomData); + + #[pallet::event] + pub enum Event { + A, + } + + #[pallet::error] + pub enum Error { + Something, + } + + #[pallet::genesis_config] + #[derive(frame_support::DefaultNoBound)] + pub struct GenesisConfig { + #[serde(skip)] + pub _config: sp_std::marker::PhantomData, + } + + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) {} + } + + #[pallet::storage] + pub type Storage = StorageValue<_, u32>; + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + fn validate_unsigned( + _source: TransactionSource, + _call: &Self::Call, + ) -> TransactionValidity { + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + } + } +} + +pub type BlockNumber = u64; +pub type Signature = sr25519::Signature; +pub type AccountId = ::Signer; +pub type Header = generic::Header; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type Block = generic::Block; + +#[frame_support::runtime(legacy_ordering)] +mod runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + #[runtime::pallet_index(30)] + pub type System = frame_system + Pallet + Call + Event + Origin; + + #[runtime::pallet_index(31)] + pub type Module1_1 = module1; + + #[runtime::pallet_index(32)] + pub type Module2 = module2; + + #[runtime::pallet_index(33)] + pub type Module1_2 = module1; + + #[runtime::pallet_index(34)] + pub type NestedModule3 = nested::module3; + + #[runtime::pallet_index(35)] + #[runtime::disable_unsigned] + pub type Module3 = self::module3; + + #[runtime::pallet_index(6)] + #[runtime::disable_call] + pub type Module1_3 = module1; + + #[runtime::pallet_index(3)] + pub type Module1_4 = module1; + + #[runtime::pallet_index(4)] + #[runtime::disable_call] + pub type Module1_5 = module1; + + #[runtime::pallet_index(1)] + pub type Module1_6 = module1; + + #[runtime::pallet_index(2)] + pub type Module1_7 = module1; + + #[runtime::pallet_index(12)] + pub type Module1_8 = module1; + + #[runtime::pallet_index(13)] + pub type Module1_9 = module1; +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Runtime { + type AccountId = AccountId; + type Lookup = sp_runtime::traits::IdentityLookup; + type BaseCallFilter = frame_support::traits::Everything; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type PalletInfo = PalletInfo; + type OnSetCode = (); + type Block = Block; + type BlockHashCount = ConstU64<10>; +} + +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module1::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module2::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl nested::module3::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} +impl module3::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + +fn test_pub() -> AccountId { + AccountId::from_raw([0; 32]) +} + +#[test] +fn check_modules_error_type() { + sp_io::TestExternalities::default().execute_with(|| { + assert_eq!( + Module1_1::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 31, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module2::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 32, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module1_2::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 33, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + NestedModule3::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 34, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module1_3::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 6, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module1_4::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 3, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module1_5::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 4, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module1_6::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 1, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module1_7::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 2, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module1_8::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 12, + error: [0; 4], + message: Some("Something") + })), + ); + assert_eq!( + Module1_9::fail(frame_system::Origin::::Root.into()), + Err(DispatchError::Module(ModuleError { + index: 13, + error: [0; 4], + message: Some("Something") + })), + ); + }) +} + +#[test] +fn integrity_test_works() { + __construct_runtime_integrity_test::runtime_integrity_tests(); + assert_eq!(IntegrityTestExec::get(), 2); +} + +#[test] +fn origin_codec() { + use codec::Encode; + + let origin = OriginCaller::system(frame_system::RawOrigin::None); + assert_eq!(origin.encode()[0], 30); + + let origin = OriginCaller::Module1_1(module1::Origin(Default::default())); + assert_eq!(origin.encode()[0], 31); + + let origin = OriginCaller::Module2(module2::Origin); + assert_eq!(origin.encode()[0], 32); + + let origin = OriginCaller::Module1_2(module1::Origin(Default::default())); + assert_eq!(origin.encode()[0], 33); + + let origin = OriginCaller::NestedModule3(nested::module3::Origin); + assert_eq!(origin.encode()[0], 34); + + let origin = OriginCaller::Module3(module3::Origin(Default::default())); + assert_eq!(origin.encode()[0], 35); + + let origin = OriginCaller::Module1_6(module1::Origin(Default::default())); + assert_eq!(origin.encode()[0], 1); + + let origin = OriginCaller::Module1_7(module1::Origin(Default::default())); + assert_eq!(origin.encode()[0], 2); + + let origin = OriginCaller::Module1_8(module1::Origin(Default::default())); + assert_eq!(origin.encode()[0], 12); + + let origin = OriginCaller::Module1_9(module1::Origin(Default::default())); + assert_eq!(origin.encode()[0], 13); +} + +#[test] +fn event_codec() { + use codec::Encode; + + let event = + frame_system::Event::::ExtrinsicSuccess { dispatch_info: Default::default() }; + assert_eq!(RuntimeEvent::from(event).encode()[0], 30); + + let event = module1::Event::::A(test_pub()); + assert_eq!(RuntimeEvent::from(event).encode()[0], 31); + + let event = module2::Event::A; + assert_eq!(RuntimeEvent::from(event).encode()[0], 32); + + let event = module1::Event::::A(test_pub()); + assert_eq!(RuntimeEvent::from(event).encode()[0], 33); + + let event = nested::module3::Event::A; + assert_eq!(RuntimeEvent::from(event).encode()[0], 34); + + let event = module3::Event::A; + assert_eq!(RuntimeEvent::from(event).encode()[0], 35); + + let event = module1::Event::::A(test_pub()); + assert_eq!(RuntimeEvent::from(event).encode()[0], 4); + + let event = module1::Event::::A(test_pub()); + assert_eq!(RuntimeEvent::from(event).encode()[0], 1); + + let event = module1::Event::::A(test_pub()); + assert_eq!(RuntimeEvent::from(event).encode()[0], 2); + + let event = module1::Event::::A(test_pub()); + assert_eq!(RuntimeEvent::from(event).encode()[0], 12); + + let event = module1::Event::::A(test_pub()); + assert_eq!(RuntimeEvent::from(event).encode()[0], 13); +} + +#[test] +fn call_codec() { + use codec::Encode; + assert_eq!(RuntimeCall::System(frame_system::Call::remark { remark: vec![1] }).encode()[0], 30); + assert_eq!(RuntimeCall::Module1_1(module1::Call::fail {}).encode()[0], 31); + assert_eq!(RuntimeCall::Module2(module2::Call::fail {}).encode()[0], 32); + assert_eq!(RuntimeCall::Module1_2(module1::Call::fail {}).encode()[0], 33); + assert_eq!(RuntimeCall::NestedModule3(nested::module3::Call::fail {}).encode()[0], 34); + assert_eq!(RuntimeCall::Module3(module3::Call::fail {}).encode()[0], 35); + assert_eq!(RuntimeCall::Module1_4(module1::Call::fail {}).encode()[0], 3); + assert_eq!(RuntimeCall::Module1_6(module1::Call::fail {}).encode()[0], 1); + assert_eq!(RuntimeCall::Module1_7(module1::Call::fail {}).encode()[0], 2); + assert_eq!(RuntimeCall::Module1_8(module1::Call::fail {}).encode()[0], 12); + assert_eq!(RuntimeCall::Module1_9(module1::Call::fail {}).encode()[0], 13); +} + +#[test] +fn call_compact_attr() { + use codec::Encode; + let call: module3::Call = module3::Call::aux_1 { data: 1 }; + let encoded = call.encode(); + assert_eq!(2, encoded.len()); + assert_eq!(vec![1, 4], encoded); + + let call: module3::Call = module3::Call::aux_2 { data: 1, data2: 2 }; + let encoded = call.encode(); + assert_eq!(6, encoded.len()); + assert_eq!(vec![2, 1, 0, 0, 0, 8], encoded); +} + +#[test] +fn call_encode_is_correct_and_decode_works() { + use codec::{Decode, Encode}; + let call: module3::Call = module3::Call::fail {}; + let encoded = call.encode(); + assert_eq!(vec![0], encoded); + let decoded = module3::Call::::decode(&mut &encoded[..]).unwrap(); + assert_eq!(decoded, call); + + let call: module3::Call = module3::Call::aux_3 { data: 32, data2: "hello".into() }; + let encoded = call.encode(); + assert_eq!(vec![3, 32, 0, 0, 0, 20, 104, 101, 108, 108, 111], encoded); + let decoded = module3::Call::::decode(&mut &encoded[..]).unwrap(); + assert_eq!(decoded, call); +} + +#[test] +fn call_weight_should_attach_to_call_enum() { + use frame_support::{ + dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}, + weights::Weight, + }; + // operational. + assert_eq!( + module3::Call::::operational {}.get_dispatch_info(), + DispatchInfo { + weight: Weight::from_parts(5, 0), + class: DispatchClass::Operational, + pays_fee: Pays::Yes + }, + ); + // custom basic + assert_eq!( + module3::Call::::aux_4 {}.get_dispatch_info(), + DispatchInfo { + weight: Weight::from_parts(3, 0), + class: DispatchClass::Normal, + pays_fee: Pays::Yes + }, + ); +} + +#[test] +fn call_name() { + use frame_support::traits::GetCallName; + let name = module3::Call::::aux_4 {}.get_call_name(); + assert_eq!("aux_4", name); +} + +#[test] +fn call_metadata() { + use frame_support::traits::{CallMetadata, GetCallMetadata}; + let call = RuntimeCall::Module3(module3::Call::::aux_4 {}); + let metadata = call.get_call_metadata(); + let expected = CallMetadata { function_name: "aux_4".into(), pallet_name: "Module3".into() }; + assert_eq!(metadata, expected); +} + +#[test] +fn get_call_names() { + use frame_support::traits::GetCallName; + let call_names = module3::Call::::get_call_names(); + assert_eq!(["fail", "aux_1", "aux_2", "aux_3", "aux_4", "operational"], call_names); +} + +#[test] +fn get_module_names() { + use frame_support::traits::GetCallMetadata; + let module_names = RuntimeCall::get_module_names(); + assert_eq!( + [ + "System", + "Module1_1", + "Module2", + "Module1_2", + "NestedModule3", + "Module3", + "Module1_4", + "Module1_6", + "Module1_7", + "Module1_8", + "Module1_9", + ], + module_names + ); +} + +#[test] +fn call_subtype_conversion() { + use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; + let call = RuntimeCall::Module3(module3::Call::::fail {}); + let subcall: Option<&CallableCallFor> = call.is_sub_type(); + let subcall_none: Option<&CallableCallFor> = call.is_sub_type(); + assert_eq!(Some(&module3::Call::::fail {}), subcall); + assert_eq!(None, subcall_none); + + let from = RuntimeCall::from(subcall.unwrap().clone()); + assert_eq!(from, call); +} + +#[test] +fn test_metadata() { + use frame_metadata::{ + v14::{StorageEntryType::Plain, *}, + *, + }; + use scale_info::meta_type; + use sp_core::Encode; + use sp_metadata_ir::StorageEntryModifierIR::Optional; + + fn maybe_docs(doc: Vec<&'static str>) -> Vec<&'static str> { + if cfg!(feature = "no-metadata-docs") { + vec![] + } else { + doc + } + } + + let pallets = vec![ + PalletMetadata { + name: "System", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![ + PalletConstantMetadata { + name: "BlockWeights", + ty: meta_type::(), + value: BlockWeights::default().encode(), + docs: maybe_docs(vec![" Block & extrinsics weights: base values and limits."]), + }, + PalletConstantMetadata { + name: "BlockLength", + ty: meta_type::(), + value: BlockLength::default().encode(), + docs: maybe_docs(vec![" The maximum length of a block (in bytes)."]), + }, + PalletConstantMetadata { + name: "BlockHashCount", + ty: meta_type::(), + value: 10u64.encode(), + docs: maybe_docs(vec![" Maximum number of block number to block hash mappings to keep (oldest pruned first)."]), + }, + PalletConstantMetadata { + name: "DbWeight", + ty: meta_type::(), + value: RuntimeDbWeight::default().encode(), + docs: maybe_docs(vec![" The weight of runtime database operations the runtime can invoke.",]), + }, + PalletConstantMetadata { + name: "Version", + ty: meta_type::(), + value: RuntimeVersion::default().encode(), + docs: maybe_docs(vec![ " Get the chain's current version."]), + }, + PalletConstantMetadata { + name: "SS58Prefix", + ty: meta_type::(), + value: 0u16.encode(), + docs: maybe_docs(vec![ + " The designated SS58 prefix of this chain.", + "", + " This replaces the \"ss58Format\" property declared in the chain spec. Reason is", + " that the runtime should know about the prefix in order to make use of it as", + " an identifier of the chain.", + ]), + }, + ], + error: Some(meta_type::>().into()), + index: 30, + }, + PalletMetadata { + name: "Module1_1", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 31, + }, + PalletMetadata { + name: "Module2", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 32, + }, + PalletMetadata { + name: "Module1_2", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 33, + }, + PalletMetadata { + name: "NestedModule3", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 34, + }, + PalletMetadata { + name: "Module3", + storage: Some(PalletStorageMetadata { + prefix: "Module3", + entries: vec![ + StorageEntryMetadata { + name: "Storage", + modifier: Optional.into(), + ty: Plain(meta_type::().into()), + default: vec![0], + docs: vec![], + }, + ] + }), + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 35, + }, + PalletMetadata { + name: "Module1_3", + storage: None, + calls: None, + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 6, + }, + PalletMetadata { + name: "Module1_4", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 3, + }, + PalletMetadata { + name: "Module1_5", + storage: None, + calls: None, + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 4, + }, + PalletMetadata { + name: "Module1_6", + storage:None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 1, + }, + PalletMetadata { + name: "Module1_7", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 2, + }, + PalletMetadata { + name: "Module1_8", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 12, + }, + PalletMetadata { + name: "Module1_9", + storage: None, + calls: Some(meta_type::>().into()), + event: Some(meta_type::>().into()), + constants: vec![], + error: Some(meta_type::>().into()), + index: 13, + }, + ]; + + let extrinsic = ExtrinsicMetadata { + ty: meta_type::(), + version: 4, + signed_extensions: vec![SignedExtensionMetadata { + identifier: "UnitTransactionExtension", + ty: meta_type::<()>(), + additional_signed: meta_type::<()>(), + }], + }; + + let expected_metadata: RuntimeMetadataPrefixed = + RuntimeMetadataLastVersion::new(pallets, extrinsic, meta_type::()).into(); + let actual_metadata = Runtime::metadata(); + + pretty_assertions::assert_eq!(actual_metadata, expected_metadata); +} + +#[test] +fn pallet_in_runtime_is_correct() { + assert_eq!(PalletInfo::index::().unwrap(), 30); + assert_eq!(PalletInfo::name::().unwrap(), "System"); + assert_eq!(PalletInfo::module_name::().unwrap(), "frame_system"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 31); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_1"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 32); + assert_eq!(PalletInfo::name::().unwrap(), "Module2"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module2"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 33); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_2"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 34); + assert_eq!(PalletInfo::name::().unwrap(), "NestedModule3"); + assert_eq!(PalletInfo::module_name::().unwrap(), "nested::module3"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 35); + assert_eq!(PalletInfo::name::().unwrap(), "Module3"); + assert_eq!(PalletInfo::module_name::().unwrap(), "self::module3"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 6); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_3"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 3); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_4"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 4); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_5"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 1); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_6"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 2); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_7"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 12); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_8"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); + + assert_eq!(PalletInfo::index::().unwrap(), 13); + assert_eq!(PalletInfo::name::().unwrap(), "Module1_9"); + assert_eq!(PalletInfo::module_name::().unwrap(), "module1"); + assert!(PalletInfo::crate_version::().is_some()); +} + +#[test] +fn test_validate_unsigned() { + use frame_support::pallet_prelude::*; + + let call = RuntimeCall::NestedModule3(nested::module3::Call::fail {}); + let validity = Runtime::validate_unsigned(TransactionSource::Local, &call).unwrap_err(); + assert_eq!(validity, TransactionValidityError::Invalid(InvalidTransaction::Call)); + + let call = RuntimeCall::Module3(module3::Call::fail {}); + let validity = Runtime::validate_unsigned(TransactionSource::Local, &call).unwrap_err(); + assert_eq!( + validity, + TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator) + ); +} diff --git a/substrate/frame/support/test/tests/runtime_ui.rs b/substrate/frame/support/test/tests/runtime_ui.rs new file mode 100644 index 00000000000..dbe150f38ed --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui.rs @@ -0,0 +1,36 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[rustversion::attr(not(stable), ignore)] +#[cfg(not(feature = "disable-ui-tests"))] +#[test] +fn ui() { + // Only run the ui tests when `RUN_UI_TESTS` is set. + if std::env::var("RUN_UI_TESTS").is_err() { + return + } + + // As trybuild is using `cargo check`, we don't need the real WASM binaries. + std::env::set_var("SKIP_WASM_BUILD", "1"); + + // Deny all warnings since we emit warnings as part of a Runtime's UI. + std::env::set_var("RUSTFLAGS", "--deny warnings"); + + let t = trybuild::TestCases::new(); + t.compile_fail("tests/runtime_ui/*.rs"); + t.pass("tests/runtime_ui/pass/*.rs"); +} diff --git a/substrate/frame/support/test/tests/runtime_ui/can_only_be_attached_to_mod.rs b/substrate/frame/support/test/tests/runtime_ui/can_only_be_attached_to_mod.rs new file mode 100644 index 00000000000..eb586809041 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/can_only_be_attached_to_mod.rs @@ -0,0 +1,21 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::runtime] +fn construct_runtime() {} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/can_only_be_attached_to_mod.stderr b/substrate/frame/support/test/tests/runtime_ui/can_only_be_attached_to_mod.stderr new file mode 100644 index 00000000000..7c2f0d1f169 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/can_only_be_attached_to_mod.stderr @@ -0,0 +1,5 @@ +error: expected `mod` + --> tests/runtime_ui/can_only_be_attached_to_mod.rs:19:1 + | +19 | fn construct_runtime() {} + | ^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_index.rs b/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_index.rs new file mode 100644 index 00000000000..648812b52c4 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_index.rs @@ -0,0 +1,43 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::pallet] +mod pallet { + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call] + impl Pallet {} +} + +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive(RuntimeCall)] + pub struct Runtime; + + #[runtime::pallet_index(0)] + pub type System = frame_system; + + #[runtime::pallet_index(0)] + pub type Pallet = pallet; +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_index.stderr b/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_index.stderr new file mode 100644 index 00000000000..8963c5d3f26 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_index.stderr @@ -0,0 +1,11 @@ +error: Pallet indices are conflicting: Both pallets System and Pallet are at index 0 + --> tests/runtime_ui/conflicting_pallet_index.rs:37:14 + | +37 | pub type System = frame_system; + | ^^^^^^ + +error: Pallet indices are conflicting: Both pallets System and Pallet are at index 0 + --> tests/runtime_ui/conflicting_pallet_index.rs:40:14 + | +40 | pub type Pallet = pallet; + | ^^^^^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_name.rs b/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_name.rs new file mode 100644 index 00000000000..c68f9a8082b --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_name.rs @@ -0,0 +1,43 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::pallet] +mod pallet { + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call] + impl Pallet {} +} + +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive(RuntimeCall)] + pub struct Runtime; + + #[runtime::pallet_index(0)] + pub type System = frame_system; + + #[runtime::pallet_index(1)] + pub type System = pallet; +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_name.stderr b/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_name.stderr new file mode 100644 index 00000000000..c250c24e3e7 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/conflicting_pallet_name.stderr @@ -0,0 +1,11 @@ +error: Two pallets with the same name! + --> tests/runtime_ui/conflicting_pallet_name.rs:37:14 + | +37 | pub type System = frame_system; + | ^^^^^^ + +error: Two pallets with the same name! + --> tests/runtime_ui/conflicting_pallet_name.rs:40:14 + | +40 | pub type System = pallet; + | ^^^^^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/invalid_attribute.rs b/substrate/frame/support/test/tests/runtime_ui/invalid_attribute.rs new file mode 100644 index 00000000000..5df2491cb24 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/invalid_attribute.rs @@ -0,0 +1,23 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::runtime(dummy)] +mod runtime { + +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/invalid_attribute.stderr b/substrate/frame/support/test/tests/runtime_ui/invalid_attribute.stderr new file mode 100644 index 00000000000..e13552413c0 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/invalid_attribute.stderr @@ -0,0 +1,5 @@ +error: Invalid runtime macro call: unexpected attribute. Macro call must be bare, such as `#[frame_support::runtime]` or `#[runtime]`, or must specify the `legacy_ordering` attribute, such as `#[frame_support::runtime(legacy_ordering)]` or #[runtime(legacy_ordering)]. + --> tests/runtime_ui/invalid_attribute.rs:18:26 + | +18 | #[frame_support::runtime(dummy)] + | ^^^^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/invalid_pallet_index.rs b/substrate/frame/support/test/tests/runtime_ui/invalid_pallet_index.rs new file mode 100644 index 00000000000..de89bb60224 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/invalid_pallet_index.rs @@ -0,0 +1,28 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive(RuntimeCall)] + pub struct Runtime; + + #[runtime::pallet_index("0")] + pub type System = frame_system; +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/invalid_pallet_index.stderr b/substrate/frame/support/test/tests/runtime_ui/invalid_pallet_index.stderr new file mode 100644 index 00000000000..1fbd086ddbe --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/invalid_pallet_index.stderr @@ -0,0 +1,5 @@ +error: expected integer literal + --> tests/runtime_ui/invalid_pallet_index.rs:24:29 + | +24 | #[runtime::pallet_index("0")] + | ^^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.rs b/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.rs new file mode 100644 index 00000000000..89ba2f23bb1 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.rs @@ -0,0 +1,25 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive(RuntimeInfo)] + pub struct Runtime; +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.stderr b/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.stderr new file mode 100644 index 00000000000..0b128c3dd45 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.stderr @@ -0,0 +1,5 @@ +error: expected one of: `RuntimeCall`, `RuntimeEvent`, `RuntimeError`, `RuntimeOrigin`, `RuntimeFreezeReason`, `RuntimeHoldReason`, `RuntimeSlashReason`, `RuntimeLockId`, `RuntimeTask` + --> tests/runtime_ui/invalid_runtime_type_derive.rs:21:23 + | +21 | #[runtime::derive(RuntimeInfo)] + | ^^^^^^^^^^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/missing_runtime.rs b/substrate/frame/support/test/tests/runtime_ui/missing_runtime.rs new file mode 100644 index 00000000000..c5febbe5287 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/missing_runtime.rs @@ -0,0 +1,21 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::runtime] +mod runtime {} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/missing_runtime.stderr b/substrate/frame/support/test/tests/runtime_ui/missing_runtime.stderr new file mode 100644 index 00000000000..9790c5dbc1a --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/missing_runtime.stderr @@ -0,0 +1,5 @@ +error: Missing Runtime. Please add a struct inside the module and annotate it with `#[runtime::runtime]` + --> tests/runtime_ui/missing_runtime.rs:19:1 + | +19 | mod runtime {} + | ^^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/missing_runtime_types_derive.rs b/substrate/frame/support/test/tests/runtime_ui/missing_runtime_types_derive.rs new file mode 100644 index 00000000000..c3fb0fd454f --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/missing_runtime_types_derive.rs @@ -0,0 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + pub struct Runtime; +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/missing_runtime_types_derive.stderr b/substrate/frame/support/test/tests/runtime_ui/missing_runtime_types_derive.stderr new file mode 100644 index 00000000000..1a8deebe549 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/missing_runtime_types_derive.stderr @@ -0,0 +1,5 @@ +error: Missing Runtime Types. Please annotate the runtime struct with `#[runtime::derive]` + --> tests/runtime_ui/missing_runtime_types_derive.rs:19:1 + | +19 | mod runtime { + | ^^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/missing_system_pallet.rs b/substrate/frame/support/test/tests/runtime_ui/missing_system_pallet.rs new file mode 100644 index 00000000000..f9a15fcf992 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/missing_system_pallet.rs @@ -0,0 +1,25 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive(RuntimeCall)] + pub struct Runtime; +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/missing_system_pallet.stderr b/substrate/frame/support/test/tests/runtime_ui/missing_system_pallet.stderr new file mode 100644 index 00000000000..dc3ac4cd5d5 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/missing_system_pallet.stderr @@ -0,0 +1,5 @@ +error: `System` pallet declaration is missing. Please add this line: `pub type System = frame_system;` + --> tests/runtime_ui/missing_system_pallet.rs:19:5 + | +19 | mod runtime { + | ^^^^^^^ diff --git a/substrate/frame/support/test/tests/runtime_ui/pass/basic.rs b/substrate/frame/support/test/tests/runtime_ui/pass/basic.rs new file mode 100644 index 00000000000..514f1501801 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/pass/basic.rs @@ -0,0 +1,37 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use frame_support::derive_impl; + +pub type Block = frame_system::mocking::MockBlock; + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for Runtime { + type Block = Block; +} + +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive(RuntimeCall, RuntimeEvent, RuntimeOrigin, RuntimeError, RuntimeTask)] + pub struct Runtime; + + #[runtime::pallet_index(0)] + pub type System = frame_system; +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/runtime_struct.rs b/substrate/frame/support/test/tests/runtime_ui/runtime_struct.rs new file mode 100644 index 00000000000..bfa2fb75f04 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/runtime_struct.rs @@ -0,0 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + pub enum Runtime {} +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/runtime_ui/runtime_struct.stderr b/substrate/frame/support/test/tests/runtime_ui/runtime_struct.stderr new file mode 100644 index 00000000000..04192bcf7f1 --- /dev/null +++ b/substrate/frame/support/test/tests/runtime_ui/runtime_struct.stderr @@ -0,0 +1,5 @@ +error: Invalid runtime::runtime, expected struct definition + --> tests/runtime_ui/runtime_struct.rs:21:5 + | +21 | pub enum Runtime {} + | ^^^ diff --git a/templates/solochain/runtime/Cargo.toml b/templates/solochain/runtime/Cargo.toml index 4f22e7ff6a3..706ea863d0f 100644 --- a/templates/solochain/runtime/Cargo.toml +++ b/templates/solochain/runtime/Cargo.toml @@ -25,7 +25,7 @@ scale-info = { version = "2.10.0", default-features = false, features = [ ] } # frame -frame-support = { path = "../../../substrate/frame/support", default-features = false } +frame-support = { path = "../../../substrate/frame/support", default-features = false, features = ["experimental"] } frame-system = { path = "../../../substrate/frame/system", default-features = false } frame-try-runtime = { path = "../../../substrate/frame/try-runtime", default-features = false, optional = true } frame-executive = { path = "../../../substrate/frame/executive", default-features = false } diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs index 409b639f021..303122da564 100644 --- a/templates/solochain/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -253,20 +253,47 @@ impl pallet_template::Config for Runtime { } // Create the runtime by composing the FRAME pallets that were previously configured. -construct_runtime!( - pub enum Runtime { - System: frame_system, - Timestamp: pallet_timestamp, - Aura: pallet_aura, - Grandpa: pallet_grandpa, - Balances: pallet_balances, - TransactionPayment: pallet_transaction_payment, - Sudo: pallet_sudo, - - // Include the custom logic from the pallet-template in the runtime. - TemplateModule: pallet_template, - } -); +#[frame_support::runtime] +mod runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + #[runtime::pallet_index(0)] + pub type System = frame_system; + + #[runtime::pallet_index(1)] + pub type Timestamp = pallet_timestamp; + + #[runtime::pallet_index(2)] + pub type Aura = pallet_aura; + + #[runtime::pallet_index(3)] + pub type Grandpa = pallet_grandpa; + + #[runtime::pallet_index(4)] + pub type Balances = pallet_balances; + + #[runtime::pallet_index(5)] + pub type TransactionPayment = pallet_transaction_payment; + + #[runtime::pallet_index(6)] + pub type Sudo = pallet_sudo; + + // Include the custom logic from the pallet-template in the runtime. + #[runtime::pallet_index(7)] + pub type TemplateModule = pallet_template; +} /// The address format for describing accounts. pub type Address = sp_runtime::MultiAddress; -- GitLab From 60ac5a723c6c0eeef0e35a0788792378c8200ec5 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Wed, 13 Mar 2024 13:33:27 +0200 Subject: [PATCH 114/188] authority-discovery: Add log for debugging DHT authority records (#3668) This PR adds a debug log for displaying all the public addresses that will later be advertised in the DHT record of the authority. The Authority DHT record will contain the address ++ `/p2p/peerID` (if not already present). This log enables us to check if different nodes will advertise in the DHT record of the authority the same IP address, however with different peer IDs. Signed-off-by: Alexandru Vasile --- .../client/authority-discovery/src/worker.rs | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/substrate/client/authority-discovery/src/worker.rs b/substrate/client/authority-discovery/src/worker.rs index 6db25416dee..9bccb96ff37 100644 --- a/substrate/client/authority-discovery/src/worker.rs +++ b/substrate/client/authority-discovery/src/worker.rs @@ -306,29 +306,30 @@ where fn addresses_to_publish(&self) -> impl Iterator { let peer_id: Multihash = self.network.local_peer_id().into(); let publish_non_global_ips = self.publish_non_global_ips; - self.network - .external_addresses() - .into_iter() - .filter(move |a| { - if publish_non_global_ips { - return true - } + let addresses = self.network.external_addresses().into_iter().filter(move |a| { + if publish_non_global_ips { + return true + } - a.iter().all(|p| match p { - // The `ip_network` library is used because its `is_global()` method is stable, - // while `is_global()` in the standard library currently isn't. - multiaddr::Protocol::Ip4(ip) if !IpNetwork::from(ip).is_global() => false, - multiaddr::Protocol::Ip6(ip) if !IpNetwork::from(ip).is_global() => false, - _ => true, - }) - }) - .map(move |a| { - if a.iter().any(|p| matches!(p, multiaddr::Protocol::P2p(_))) { - a - } else { - a.with(multiaddr::Protocol::P2p(peer_id)) - } + a.iter().all(|p| match p { + // The `ip_network` library is used because its `is_global()` method is stable, + // while `is_global()` in the standard library currently isn't. + multiaddr::Protocol::Ip4(ip) if !IpNetwork::from(ip).is_global() => false, + multiaddr::Protocol::Ip6(ip) if !IpNetwork::from(ip).is_global() => false, + _ => true, }) + }); + + debug!(target: LOG_TARGET, "Authority DHT record peer_id='{:?}' addresses='{:?}'", peer_id, addresses.clone().collect::>()); + + // The address must include the peer id if not already set. + addresses.map(move |a| { + if a.iter().any(|p| matches!(p, multiaddr::Protocol::P2p(_))) { + a + } else { + a.with(multiaddr::Protocol::P2p(peer_id)) + } + }) } /// Publish own public addresses. -- GitLab From bbd51ce867967f71657b901f1a956ad4f75d352e Mon Sep 17 00:00:00 2001 From: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:10:59 +0200 Subject: [PATCH 115/188] Revert "FRAME: Create `TransactionExtension` as a replacement for `SignedExtension` (#2280)" (#3665) This PR reverts #2280 which introduced `TransactionExtension` to replace `SignedExtension`. As a result of the discussion [here](https://github.com/paritytech/polkadot-sdk/pull/3623#issuecomment-1986789700), the changes will be reverted for now with plans to reintroduce the concept in the future. --------- Signed-off-by: georgepisaltu --- Cargo.lock | 35 +- bridges/bin/runtime-common/Cargo.toml | 1 - bridges/bin/runtime-common/src/lib.rs | 72 +- bridges/bin/runtime-common/src/mock.rs | 2 +- .../runtime-common/src/priority_calculator.rs | 11 +- .../src/refund_relayer_extension.rs | 154 +- .../chain-bridge-hub-cumulus/src/lib.rs | 4 +- .../chain-bridge-hub-rococo/src/lib.rs | 2 +- bridges/primitives/chain-kusama/src/lib.rs | 4 +- .../chain-polkadot-bulletin/src/lib.rs | 51 +- bridges/primitives/chain-polkadot/src/lib.rs | 4 +- bridges/primitives/chain-rococo/src/lib.rs | 4 +- bridges/primitives/chain-westend/src/lib.rs | 4 +- bridges/primitives/polkadot-core/src/lib.rs | 37 +- bridges/primitives/runtime/src/extensions.rs | 135 +- .../snowbridge/runtime/test-common/Cargo.toml | 1 - .../assets/asset-hub-rococo/Cargo.toml | 2 - .../assets/asset-hub-rococo/src/lib.rs | 77 +- .../src/weights/frame_system_extensions.rs | 121 -- .../asset-hub-rococo/src/weights/mod.rs | 3 - .../pallet_asset_conversion_tx_payment.rs | 92 - .../src/weights/pallet_transaction_payment.rs | 67 - .../assets/asset-hub-westend/Cargo.toml | 2 - .../assets/asset-hub-westend/src/lib.rs | 77 +- .../src/weights/frame_system_extensions.rs | 121 -- .../asset-hub-westend/src/weights/mod.rs | 3 - .../pallet_asset_conversion_tx_payment.rs | 92 - .../src/weights/pallet_transaction_payment.rs | 67 - .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 1 - .../src/bridge_to_bulletin_config.rs | 4 +- .../src/bridge_to_westend_config.rs | 4 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 27 +- .../src/weights/frame_system_extensions.rs | 121 -- .../bridge-hub-rococo/src/weights/mod.rs | 2 - .../src/weights/pallet_transaction_payment.rs | 67 - .../bridge-hub-rococo/tests/snowbridge.rs | 8 +- .../bridge-hub-rococo/tests/tests.rs | 11 +- .../bridge-hubs/bridge-hub-westend/Cargo.toml | 1 - .../src/bridge_to_rococo_config.rs | 4 +- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 25 +- .../src/weights/frame_system_extensions.rs | 121 -- .../bridge-hub-westend/src/weights/mod.rs | 2 - .../src/weights/pallet_transaction_payment.rs | 67 - .../bridge-hub-westend/tests/tests.rs | 11 +- .../collectives-westend/Cargo.toml | 1 - .../collectives-westend/src/lib.rs | 12 +- .../src/weights/frame_system_extensions.rs | 121 -- .../collectives-westend/src/weights/mod.rs | 2 - .../src/weights/pallet_transaction_payment.rs | 67 - .../contracts/contracts-rococo/Cargo.toml | 1 - .../contracts/contracts-rococo/src/lib.rs | 10 +- .../coretime/coretime-rococo/Cargo.toml | 1 - .../coretime/coretime-rococo/src/lib.rs | 9 +- .../src/weights/frame_system_extensions.rs | 121 -- .../coretime-rococo/src/weights/mod.rs | 2 - .../src/weights/pallet_transaction_payment.rs | 67 - .../coretime/coretime-westend/Cargo.toml | 1 - .../coretime/coretime-westend/src/lib.rs | 9 +- .../src/weights/frame_system_extensions.rs | 121 -- .../coretime-westend/src/weights/mod.rs | 2 - .../src/weights/pallet_transaction_payment.rs | 67 - .../glutton/glutton-westend/src/lib.rs | 9 +- .../src/weights/frame_system_extensions.rs | 119 -- .../runtimes/people/people-rococo/Cargo.toml | 1 - .../runtimes/people/people-rococo/src/lib.rs | 9 +- .../src/weights/frame_system_extensions.rs | 121 -- .../people/people-rococo/src/weights/mod.rs | 2 - .../src/weights/pallet_transaction_payment.rs | 67 - .../runtimes/people/people-westend/Cargo.toml | 1 - .../runtimes/people/people-westend/src/lib.rs | 8 +- .../src/weights/frame_system_extensions.rs | 121 -- .../people/people-westend/src/weights/mod.rs | 2 - .../src/weights/pallet_transaction_payment.rs | 67 - .../runtimes/starters/seedling/src/lib.rs | 6 +- .../runtimes/starters/shell/src/lib.rs | 64 +- .../runtimes/testing/penpal/Cargo.toml | 1 - .../runtimes/testing/penpal/src/lib.rs | 26 +- .../testing/rococo-parachain/Cargo.toml | 1 - .../testing/rococo-parachain/src/lib.rs | 7 +- cumulus/polkadot-parachain/Cargo.toml | 1 - .../storage-weight-reclaim/Cargo.toml | 13 +- .../src/benchmarking.rs | 70 - .../storage-weight-reclaim/src/lib.rs | 522 ++++- .../storage-weight-reclaim/src/tests.rs | 484 ----- cumulus/test/client/Cargo.toml | 2 - cumulus/test/client/src/lib.rs | 13 +- cumulus/test/runtime/src/lib.rs | 9 +- cumulus/test/service/Cargo.toml | 2 - cumulus/test/service/src/bench_utils.rs | 4 +- cumulus/test/service/src/lib.rs | 9 +- .../src/reference_docs/extrinsic_encoding.rs | 101 +- .../src/reference_docs/frame_runtime_types.rs | 2 +- docs/sdk/src/reference_docs/mod.rs | 4 +- .../src/reference_docs/signed_extensions.rs | 79 + .../reference_docs/transaction_extensions.rs | 57 - polkadot/node/service/Cargo.toml | 1 - polkadot/node/service/src/benchmarking.rs | 18 +- polkadot/node/test/service/Cargo.toml | 1 - polkadot/node/test/service/src/lib.rs | 11 +- polkadot/runtime/common/Cargo.toml | 1 - polkadot/runtime/common/src/claims.rs | 150 +- polkadot/runtime/rococo/Cargo.toml | 1 - .../constants/src/weights/block_weights.rs | 29 +- .../src/weights/extrinsic_weights.rs | 29 +- polkadot/runtime/rococo/src/lib.rs | 45 +- .../weights/frame_benchmarking_baseline.rs | 43 +- .../rococo/src/weights/frame_system.rs | 103 +- .../src/weights/frame_system_extensions.rs | 123 -- polkadot/runtime/rococo/src/weights/mod.rs | 2 - .../rococo/src/weights/pallet_asset_rate.rs | 63 +- .../src/weights/pallet_balances_balances.rs | 58 +- ...allet_balances_nis_counterpart_balances.rs | 58 +- .../rococo/src/weights/pallet_bounties.rs | 218 +-- .../src/weights/pallet_child_bounties.rs | 181 +- .../src/weights/pallet_conviction_voting.rs | 196 +- .../rococo/src/weights/pallet_identity.rs | 409 ++-- .../rococo/src/weights/pallet_indices.rs | 73 +- .../src/weights/pallet_message_queue.rs | 168 +- .../rococo/src/weights/pallet_multisig.rs | 123 +- .../runtime/rococo/src/weights/pallet_nis.rs | 243 +-- .../rococo/src/weights/pallet_preimage.rs | 252 ++- .../rococo/src/weights/pallet_proxy.rs | 195 +- .../src/weights/pallet_ranked_collective.rs | 66 +- .../rococo/src/weights/pallet_recovery.rs | 186 -- .../pallet_referenda_fellowship_referenda.rs | 235 ++- .../src/weights/pallet_referenda_referenda.rs | 283 +-- .../rococo/src/weights/pallet_scheduler.rs | 146 +- .../runtime/rococo/src/weights/pallet_sudo.rs | 45 +- .../rococo/src/weights/pallet_timestamp.rs | 35 +- .../src/weights/pallet_transaction_payment.rs | 68 - .../rococo/src/weights/pallet_treasury.rs | 233 +-- .../rococo/src/weights/pallet_utility.rs | 47 +- .../rococo/src/weights/pallet_vesting.rs | 254 ++- .../rococo/src/weights/pallet_whitelist.rs | 68 +- .../runtime/rococo/src/weights/pallet_xcm.rs | 90 +- .../weights/pallet_xcm_benchmarks_fungible.rs | 191 -- .../weights/pallet_xcm_benchmarks_generic.rs | 347 ---- .../weights/runtime_common_assigned_slots.rs | 70 +- .../src/weights/runtime_common_auctions.rs | 137 +- .../src/weights/runtime_common_claims.rs | 180 +- .../src/weights/runtime_common_coretime.rs | 86 - .../src/weights/runtime_common_crowdloan.rs | 239 +-- .../runtime_common_identity_migrator.rs | 83 +- .../weights/runtime_common_paras_registrar.rs | 281 +-- .../src/weights/runtime_common_slots.rs | 127 +- .../runtime_parachains_assigner_on_demand.rs | 50 +- .../runtime_parachains_configuration.rs | 48 +- .../weights/runtime_parachains_disputes.rs | 23 +- .../src/weights/runtime_parachains_hrmp.rs | 389 ++-- .../weights/runtime_parachains_inclusion.rs | 45 +- .../weights/runtime_parachains_initializer.rs | 27 +- .../src/weights/runtime_parachains_paras.rs | 368 ++-- .../runtime_parachains_paras_inherent.rs | 429 ++--- polkadot/runtime/test-runtime/Cargo.toml | 1 - polkadot/runtime/test-runtime/src/lib.rs | 40 +- polkadot/runtime/westend/Cargo.toml | 1 - polkadot/runtime/westend/src/lib.rs | 25 +- .../src/weights/frame_system_extensions.rs | 116 -- polkadot/runtime/westend/src/weights/mod.rs | 2 - .../westend/src/weights/pallet_sudo.rs | 11 - .../src/weights/pallet_transaction_payment.rs | 65 - polkadot/xcm/xcm-builder/Cargo.toml | 1 - .../xcm/xcm-builder/src/tests/pay/mock.rs | 12 +- .../xcm/xcm-simulator/fuzzer/src/parachain.rs | 4 +- .../xcm-simulator/fuzzer/src/relay_chain.rs | 4 +- prdoc/pr_2280.prdoc | 144 -- prdoc/pr_3665.prdoc | 11 + substrate/.maintain/frame-weight-template.hbs | 2 +- substrate/bin/node/cli/Cargo.toml | 2 - .../bin/node/cli/benches/block_production.rs | 2 +- substrate/bin/node/cli/benches/executor.rs | 6 +- substrate/bin/node/cli/src/service.rs | 77 +- substrate/bin/node/cli/tests/basic.rs | 26 +- substrate/bin/node/cli/tests/fees.rs | 24 +- .../bin/node/cli/tests/submit_transaction.rs | 10 +- substrate/bin/node/runtime/Cargo.toml | 2 - substrate/bin/node/runtime/src/lib.rs | 165 +- substrate/bin/node/testing/src/bench.rs | 26 +- substrate/bin/node/testing/src/keyring.rs | 44 +- .../client/api/src/notifications/tests.rs | 7 +- substrate/client/db/benches/state_access.rs | 5 +- substrate/client/db/src/lib.rs | 262 +-- substrate/client/db/src/utils.rs | 11 +- .../network-gossip/src/state_machine.rs | 5 +- substrate/client/network/sync/src/blocks.rs | 7 +- substrate/client/transaction-pool/src/lib.rs | 9 +- substrate/frame/alliance/src/weights.rs | 1033 +++++----- .../frame/asset-conversion/src/weights.rs | 126 +- substrate/frame/asset-rate/src/weights.rs | 73 +- substrate/frame/assets/src/weights.rs | 841 ++++---- substrate/frame/babe/src/mock.rs | 5 +- substrate/frame/bags-list/src/weights.rs | 165 +- substrate/frame/balances/Cargo.toml | 1 - .../balances/src/tests/currency_tests.rs | 17 +- substrate/frame/balances/src/tests/mod.rs | 4 +- substrate/frame/balances/src/weights.rs | 98 +- substrate/frame/beefy/src/mock.rs | 6 +- substrate/frame/benchmarking/src/weights.rs | 81 +- substrate/frame/bounties/src/weights.rs | 405 ++-- substrate/frame/broker/src/weights.rs | 357 ++-- substrate/frame/child-bounties/src/weights.rs | 381 ++-- substrate/frame/collective/src/tests.rs | 2 +- substrate/frame/collective/src/weights.rs | 677 ++++--- substrate/frame/contracts/src/weights.rs | 265 +-- .../frame/conviction-voting/src/weights.rs | 405 ++-- .../frame/core-fellowship/src/weights.rs | 429 ++--- substrate/frame/democracy/src/weights.rs | 1093 ++++++----- .../election-provider-multi-phase/src/mock.rs | 2 +- .../src/unsigned.rs | 4 +- .../src/weights.rs | 517 +++-- .../test-staking-e2e/src/mock.rs | 4 +- substrate/frame/elections-phragmen/src/lib.rs | 2 +- .../frame/elections-phragmen/src/weights.rs | 655 ++++--- substrate/frame/examples/basic/src/lib.rs | 76 +- substrate/frame/examples/basic/src/tests.rs | 9 +- .../examples/offchain-worker/src/tests.rs | 22 +- substrate/frame/examples/tasks/src/weights.rs | 78 +- substrate/frame/executive/src/tests.rs | 225 +-- substrate/frame/fast-unstake/src/weights.rs | 473 +++-- substrate/frame/glutton/src/weights.rs | 249 +-- substrate/frame/grandpa/src/mock.rs | 9 +- substrate/frame/identity/src/weights.rs | 825 ++++---- substrate/frame/im-online/src/mock.rs | 4 +- substrate/frame/im-online/src/tests.rs | 4 +- substrate/frame/im-online/src/weights.rs | 85 +- substrate/frame/indices/src/weights.rs | 121 +- substrate/frame/lottery/src/weights.rs | 301 ++- substrate/frame/membership/src/weights.rs | 385 ++-- substrate/frame/message-queue/src/weights.rs | 247 ++- substrate/frame/migrations/src/weights.rs | 183 +- substrate/frame/multisig/src/weights.rs | 243 ++- .../nft-fractionalization/src/weights.rs | 209 +- substrate/frame/nfts/src/weights.rs | 1692 ++++++++--------- substrate/frame/nis/src/weights.rs | 429 ++--- .../frame/nomination-pools/src/weights.rs | 29 +- .../frame/offences/benchmarking/src/mock.rs | 2 +- substrate/frame/parameters/src/weights.rs | 38 +- substrate/frame/preimage/src/weights.rs | 332 ++-- substrate/frame/proxy/src/weights.rs | 377 ++-- .../frame/ranked-collective/src/weights.rs | 353 ++-- substrate/frame/recovery/src/weights.rs | 305 ++- substrate/frame/referenda/src/weights.rs | 1037 +++++----- substrate/frame/remark/src/weights.rs | 37 +- substrate/frame/safe-mode/src/weights.rs | 142 +- substrate/frame/salary/src/weights.rs | 217 +-- substrate/frame/sassafras/src/mock.rs | 5 +- substrate/frame/scheduler/src/weights.rs | 266 ++- substrate/frame/session/src/weights.rs | 117 +- substrate/frame/society/src/weights.rs | 974 +++------- substrate/frame/src/lib.rs | 6 +- substrate/frame/staking/src/weights.rs | 422 ++-- .../frame/state-trie-migration/src/lib.rs | 2 +- .../frame/state-trie-migration/src/weights.rs | 118 +- substrate/frame/sudo/src/benchmarking.rs | 29 +- substrate/frame/sudo/src/extension.rs | 78 +- substrate/frame/sudo/src/lib.rs | 4 +- substrate/frame/sudo/src/weights.rs | 71 +- .../src/construct_runtime/expand/inherent.rs | 18 +- .../src/construct_runtime/expand/metadata.rs | 6 +- .../src/construct_runtime/expand/origin.rs | 14 - substrate/frame/support/src/dispatch.rs | 29 +- substrate/frame/support/src/lib.rs | 8 +- .../frame/support/src/traits/dispatch.rs | 21 +- substrate/frame/support/src/traits/misc.rs | 13 +- .../support/src/transaction_extensions.rs | 89 - .../support/src/weights/block_weights.rs | 31 +- .../support/src/weights/extrinsic_weights.rs | 31 +- .../deprecated_where_block.stderr | 4 +- substrate/frame/support/test/tests/pallet.rs | 143 +- .../support/test/tests/pallet_instance.rs | 2 +- substrate/frame/support/test/tests/runtime.rs | 2 +- .../test/tests/runtime_legacy_ordering.rs | 4 +- .../system/benchmarking/src/extensions.rs | 213 --- .../frame/system/benchmarking/src/lib.rs | 1 - .../frame/system/benchmarking/src/mock.rs | 1 - .../system/src/extensions/check_genesis.rs | 33 +- .../system/src/extensions/check_mortality.rs | 83 +- .../src/extensions/check_non_zero_sender.rs | 95 +- .../system/src/extensions/check_nonce.rs | 184 +- .../src/extensions/check_spec_version.rs | 33 +- .../system/src/extensions/check_tx_version.rs | 32 +- .../system/src/extensions/check_weight.rs | 228 +-- substrate/frame/system/src/extensions/mod.rs | 3 - .../frame/system/src/extensions/weights.rs | 196 -- substrate/frame/system/src/lib.rs | 10 +- substrate/frame/system/src/offchain.rs | 22 +- substrate/frame/system/src/weights.rs | 249 ++- substrate/frame/timestamp/src/weights.rs | 65 +- substrate/frame/tips/src/weights.rs | 241 +-- .../frame/transaction-payment/Cargo.toml | 9 - .../asset-conversion-tx-payment/Cargo.toml | 12 - .../asset-conversion-tx-payment/README.md | 2 +- .../src/benchmarking.rs | 125 -- .../asset-conversion-tx-payment/src/lib.rs | 233 +-- .../asset-conversion-tx-payment/src/mock.rs | 70 +- .../asset-conversion-tx-payment/src/tests.rs | 150 +- .../src/weights.rs | 150 -- .../asset-tx-payment/Cargo.toml | 1 - .../asset-tx-payment/README.md | 2 +- .../asset-tx-payment/src/benchmarking.rs | 123 -- .../asset-tx-payment/src/lib.rs | 199 +- .../asset-tx-payment/src/mock.rs | 54 +- .../asset-tx-payment/src/tests.rs | 184 +- .../asset-tx-payment/src/weights.rs | 146 -- .../skip-feeless-payment/src/lib.rs | 111 +- .../skip-feeless-payment/src/mock.rs | 30 +- .../skip-feeless-payment/src/tests.rs | 5 +- .../transaction-payment/src/benchmarking.rs | 81 - .../frame/transaction-payment/src/lib.rs | 146 +- .../frame/transaction-payment/src/mock.rs | 10 - .../frame/transaction-payment/src/payment.rs | 56 +- .../frame/transaction-payment/src/tests.rs | 444 +++-- .../frame/transaction-payment/src/types.rs | 2 +- .../frame/transaction-payment/src/weights.rs | 92 - .../frame/transaction-storage/src/weights.rs | 185 +- substrate/frame/treasury/src/weights.rs | 348 ++-- substrate/frame/tx-pause/src/weights.rs | 38 +- substrate/frame/uniques/src/weights.rs | 368 ++-- substrate/frame/utility/src/weights.rs | 161 +- substrate/frame/vesting/src/weights.rs | 234 ++- substrate/frame/whitelist/src/weights.rs | 193 +- substrate/primitives/inherents/src/lib.rs | 4 +- substrate/primitives/metadata-ir/src/lib.rs | 2 +- substrate/primitives/metadata-ir/src/types.rs | 19 +- substrate/primitives/metadata-ir/src/v14.rs | 10 +- substrate/primitives/metadata-ir/src/v15.rs | 8 +- substrate/primitives/runtime/Cargo.toml | 2 - .../runtime/src/generic/checked_extrinsic.rs | 112 +- .../primitives/runtime/src/generic/mod.rs | 4 +- .../src/generic/unchecked_extrinsic.rs | 730 +++---- substrate/primitives/runtime/src/lib.rs | 19 +- substrate/primitives/runtime/src/testing.rs | 195 +- .../runtime/src/{traits/mod.rs => traits.rs} | 244 ++- .../as_transaction_extension.rs | 133 -- .../dispatch_transaction.rs | 141 -- .../src/traits/transaction_extension/mod.rs | 526 ----- .../runtime/src/transaction_validity.rs | 6 +- substrate/scripts/run_all_benchmarks.sh | 13 - substrate/test-utils/runtime/src/extrinsic.rs | 17 +- substrate/test-utils/runtime/src/lib.rs | 93 +- .../benchmarking-cli/src/pallet/template.hbs | 4 - .../frame/remote-externalities/src/lib.rs | 5 +- substrate/utils/frame/rpc/client/src/lib.rs | 8 +- templates/minimal/runtime/src/lib.rs | 4 +- templates/parachain/runtime/Cargo.toml | 2 - templates/parachain/runtime/src/lib.rs | 10 +- templates/solochain/node/Cargo.toml | 1 - templates/solochain/node/src/benchmarking.rs | 9 +- templates/solochain/runtime/Cargo.toml | 1 - templates/solochain/runtime/src/lib.rs | 12 +- 350 files changed, 15770 insertions(+), 24248 deletions(-) delete mode 100644 cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_conversion_tx_payment.rs delete mode 100644 cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_conversion_tx_payment.rs delete mode 100644 cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs delete mode 100644 cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_transaction_payment.rs delete mode 100644 cumulus/primitives/storage-weight-reclaim/src/benchmarking.rs delete mode 100644 cumulus/primitives/storage-weight-reclaim/src/tests.rs create mode 100644 docs/sdk/src/reference_docs/signed_extensions.rs delete mode 100644 docs/sdk/src/reference_docs/transaction_extensions.rs delete mode 100644 polkadot/runtime/rococo/src/weights/frame_system_extensions.rs delete mode 100644 polkadot/runtime/rococo/src/weights/pallet_recovery.rs delete mode 100644 polkadot/runtime/rococo/src/weights/pallet_transaction_payment.rs delete mode 100644 polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs delete mode 100644 polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs delete mode 100644 polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs delete mode 100644 polkadot/runtime/westend/src/weights/frame_system_extensions.rs delete mode 100644 polkadot/runtime/westend/src/weights/pallet_transaction_payment.rs delete mode 100644 prdoc/pr_2280.prdoc create mode 100644 prdoc/pr_3665.prdoc delete mode 100644 substrate/frame/support/src/transaction_extensions.rs delete mode 100644 substrate/frame/system/benchmarking/src/extensions.rs delete mode 100644 substrate/frame/system/src/extensions/weights.rs delete mode 100644 substrate/frame/transaction-payment/asset-conversion-tx-payment/src/benchmarking.rs delete mode 100644 substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs delete mode 100644 substrate/frame/transaction-payment/asset-tx-payment/src/benchmarking.rs delete mode 100644 substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs delete mode 100644 substrate/frame/transaction-payment/src/benchmarking.rs delete mode 100644 substrate/frame/transaction-payment/src/weights.rs rename substrate/primitives/runtime/src/{traits/mod.rs => traits.rs} (94%) delete mode 100644 substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs delete mode 100644 substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs delete mode 100644 substrate/primitives/runtime/src/traits/transaction_extension/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 37c5a5177c0..8cbbbce209a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4046,13 +4046,11 @@ dependencies = [ "cumulus-primitives-proof-size-hostfunction", "cumulus-test-runtime", "docify 0.2.7", - "frame-benchmarking", "frame-support", "frame-system", "log", "parity-scale-codec", "scale-info", - "sp-core", "sp-io", "sp-runtime", "sp-std 14.0.0", @@ -5899,7 +5897,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f9df8a11882c4e3335eb2d18a0137c505d9ca927470b0cac9c6f0ae07d28f7" dependencies = [ - "rustix 0.38.25", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -6784,7 +6782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.2", - "rustix 0.38.25", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -7792,9 +7790,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lioness" @@ -9040,7 +9038,6 @@ dependencies = [ name = "pallet-asset-conversion-tx-payment" version = "10.0.0" dependencies = [ - "frame-benchmarking", "frame-support", "frame-system", "pallet-asset-conversion", @@ -10989,7 +10986,6 @@ dependencies = [ name = "pallet-transaction-payment" version = "28.0.0" dependencies = [ - "frame-benchmarking", "frame-support", "frame-system", "pallet-balances", @@ -14251,7 +14247,7 @@ dependencies = [ "hex", "lazy_static", "procfs-core", - "rustix 0.38.25", + "rustix 0.38.21", ] [[package]] @@ -15376,14 +15372,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.11", + "linux-raw-sys 0.4.10", "windows-sys 0.48.0", ] @@ -18715,7 +18711,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.4.1" -source = "git+https://github.com/paritytech/polkadot-sdk#838a534da874cf6071fba1df07643c6c5b033ae0" +source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf590a34fca09b72dc5f" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -19021,7 +19017,6 @@ dependencies = [ "sp-tracing 16.0.0", "sp-weights", "substrate-test-runtime-client", - "tuplex", "zstd 0.12.4", ] @@ -19070,7 +19065,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#838a534da874cf6071fba1df07643c6c5b033ae0" +source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf590a34fca09b72dc5f" dependencies = [ "Inflector", "proc-macro-crate 1.3.1", @@ -20289,7 +20284,7 @@ dependencies = [ "cfg-if", "fastrand 2.0.0", "redox_syscall 0.4.1", - "rustix 0.38.25", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -20308,7 +20303,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.38.25", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -21154,12 +21149,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "tuplex" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "676ac81d5454c4dcf37955d34fa8626ede3490f744b86ca14a7b90168d2a08aa" - [[package]] name = "twox-hash" version = "1.6.3" diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml index ee54f15f38b..fac88b20ca5 100644 --- a/bridges/bin/runtime-common/Cargo.toml +++ b/bridges/bin/runtime-common/Cargo.toml @@ -93,7 +93,6 @@ runtime-benchmarks = [ "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bridges/bin/runtime-common/src/lib.rs b/bridges/bin/runtime-common/src/lib.rs index 035077408c4..2722f6f1c6d 100644 --- a/bridges/bin/runtime-common/src/lib.rs +++ b/bridges/bin/runtime-common/src/lib.rs @@ -105,48 +105,43 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { ($call:ty, $account_id:ty, $($filter_call:ty),*) => { #[derive(Clone, codec::Decode, Default, codec::Encode, Eq, PartialEq, sp_runtime::RuntimeDebug, scale_info::TypeInfo)] pub struct BridgeRejectObsoleteHeadersAndMessages; - impl sp_runtime::traits::TransactionExtensionBase for BridgeRejectObsoleteHeadersAndMessages { + impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages { const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages"; - type Implicit = (); - } - impl sp_runtime::traits::TransactionExtension<$call, Context> for BridgeRejectObsoleteHeadersAndMessages { + type AccountId = $account_id; + type Call = $call; + type AdditionalSigned = (); type Pre = (); - type Val = (); + + fn additional_signed(&self) -> sp_std::result::Result< + (), + sp_runtime::transaction_validity::TransactionValidityError, + > { + Ok(()) + } fn validate( &self, - origin: <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, - call: &$call, - _info: &sp_runtime::traits::DispatchInfoOf<$call>, + _who: &Self::AccountId, + call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl codec::Encode, - ) -> Result< - ( - sp_runtime::transaction_validity::ValidTransaction, - Self::Val, - <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, - ), sp_runtime::transaction_validity::TransactionValidityError - > { - let tx_validity = sp_runtime::transaction_validity::ValidTransaction::default(); + ) -> sp_runtime::transaction_validity::TransactionValidity { + let valid = sp_runtime::transaction_validity::ValidTransaction::default(); $( - let call_filter_validity = <$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?; - let tx_validity = tx_validity.combine_with(call_filter_validity); + let valid = valid + .combine_with(<$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?); )* - Ok((tx_validity, (), origin)) + Ok(valid) } - fn prepare( + fn pre_dispatch( self, - _val: Self::Val, - _origin: &<$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, - _call: &$call, - _info: &sp_runtime::traits::DispatchInfoOf<$call>, - _len: usize, - _context: &Context, + who: &Self::AccountId, + call: &Self::Call, + info: &sp_runtime::traits::DispatchInfoOf, + len: usize, ) -> Result { - Ok(()) + self.validate(who, call, info, len).map(drop) } } }; @@ -155,14 +150,12 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { #[cfg(test)] mod tests { use crate::BridgeRuntimeFilterCall; - use codec::Encode; - use frame_support::assert_err; + use frame_support::{assert_err, assert_ok}; use sp_runtime::{ - traits::DispatchTransaction, + traits::SignedExtension, transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, }; - #[derive(Encode)] pub struct MockCall { data: u32, } @@ -213,20 +206,17 @@ mod tests { ); assert_err!( - BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 1 }, &(), 0), + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 1 }, &(), 0), InvalidTransaction::Custom(1) ); assert_err!( - BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 2 }, &(), 0), + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 2 }, &(), 0), InvalidTransaction::Custom(2) ); - assert_eq!( - BridgeRejectObsoleteHeadersAndMessages - .validate_only((), &MockCall { data: 3 }, &(), 0) - .unwrap() - .0, + assert_ok!( + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 3 }, &(), 0), ValidTransaction { priority: 3, ..Default::default() } ) } diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs index f147f1404f0..8877a4fd95c 100644 --- a/bridges/bin/runtime-common/src/mock.rs +++ b/bridges/bin/runtime-common/src/mock.rs @@ -164,7 +164,6 @@ impl pallet_balances::Config for TestRuntime { type AccountStore = System; } -#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for TestRuntime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; @@ -177,6 +176,7 @@ impl pallet_transaction_payment::Config for TestRuntime { MinimumMultiplier, MaximumMultiplier, >; + type RuntimeEvent = RuntimeEvent; } impl pallet_bridge_grandpa::Config for TestRuntime { diff --git a/bridges/bin/runtime-common/src/priority_calculator.rs b/bridges/bin/runtime-common/src/priority_calculator.rs index 0c53018330e..a597fb9e2f4 100644 --- a/bridges/bin/runtime-common/src/priority_calculator.rs +++ b/bridges/bin/runtime-common/src/priority_calculator.rs @@ -169,15 +169,12 @@ mod integrity_tests { // nodes to the proof (x0.5 because we expect some nodes to be reused) let estimated_message_size = 512; // let's say all our messages have the same dispatch weight - let estimated_message_dispatch_weight = >::WeightInfo::message_dispatch_weight( - estimated_message_size - ); + let estimated_message_dispatch_weight = + Runtime::WeightInfo::message_dispatch_weight(estimated_message_size); // messages proof argument size is (for every message) messages size + some additional // trie nodes. Some of them are reused by different messages, so let's take 2/3 of default // "overhead" constant - let messages_proof_size = >::WeightInfo::expected_extra_storage_proof_size() + let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size() .saturating_mul(2) .saturating_div(3) .saturating_add(estimated_message_size) @@ -185,7 +182,7 @@ mod integrity_tests { // finally we are able to estimate transaction size and weight let transaction_size = base_tx_size.saturating_add(messages_proof_size); - let transaction_weight = >::WeightInfo::receive_messages_proof_weight( + let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight( &PreComputedSize(transaction_size as _), messages as _, estimated_message_dispatch_weight.saturating_mul(messages), diff --git a/bridges/bin/runtime-common/src/refund_relayer_extension.rs b/bridges/bin/runtime-common/src/refund_relayer_extension.rs index b912f8445ac..bfcb82ad166 100644 --- a/bridges/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bridges/bin/runtime-common/src/refund_relayer_extension.rs @@ -48,12 +48,9 @@ use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTra use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{ - AsSystemOriginSigner, DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, - TransactionExtension, TransactionExtensionBase, ValidateResult, Zero, - }, + traits::{DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, SignedExtension, Zero}, transaction_validity::{ - InvalidTransaction, TransactionPriority, TransactionValidityError, ValidTransactionBuilder, + TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransactionBuilder, }, DispatchResult, FixedPointOperand, RuntimeDebug, }; @@ -242,8 +239,8 @@ pub enum RelayerAccountAction { Slash(AccountId, RewardsAccountParams), } -/// Everything common among our refund transaction extensions. -pub trait RefundTransactionExtension: +/// Everything common among our refund signed extensions. +pub trait RefundSignedExtension: 'static + Clone + Codec + sp_std::fmt::Debug + Default + Eq + PartialEq + Send + Sync + TypeInfo where >::BridgedChain: @@ -459,8 +456,8 @@ where } } -/// Adapter that allow implementing `sp_runtime::traits::TransactionExtension` for any -/// `RefundTransactionExtension`. +/// Adapter that allow implementing `sp_runtime::traits::SignedExtension` for any +/// `RefundSignedExtension`. #[derive( DefaultNoBound, CloneNoBound, @@ -471,13 +468,12 @@ where RuntimeDebugNoBound, TypeInfo, )] -pub struct RefundTransactionExtensionAdapter(T) +pub struct RefundSignedExtensionAdapter(T) where >::BridgedChain: Chain; -impl TransactionExtensionBase - for RefundTransactionExtensionAdapter +impl SignedExtension for RefundSignedExtensionAdapter where >::BridgedChain: Chain, @@ -487,35 +483,22 @@ where + MessagesCallSubType::Instance>, { const IDENTIFIER: &'static str = T::Id::STR; - type Implicit = (); -} - -impl TransactionExtension, Context> - for RefundTransactionExtensionAdapter -where - >::BridgedChain: - Chain, - CallOf: Dispatchable - + IsSubType, T::Runtime>> - + GrandpaCallSubType - + MessagesCallSubType::Instance>, - as Dispatchable>::RuntimeOrigin: - AsSystemOriginSigner> + Clone, -{ + type AccountId = AccountIdOf; + type Call = CallOf; + type AdditionalSigned = (); type Pre = Option>>; - type Val = Option; + + fn additional_signed(&self) -> Result<(), TransactionValidityError> { + Ok(()) + } fn validate( &self, - origin: as Dispatchable>::RuntimeOrigin, - call: &CallOf, - _info: &DispatchInfoOf>, + who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult> { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + ) -> TransactionValidity { // this is the only relevant line of code for the `pre_dispatch` // // we're not calling `validate` from `pre_dispatch` directly because of performance @@ -528,12 +511,12 @@ where // we only boost priority of presumably correct message delivery transactions let bundled_messages = match T::bundled_messages_for_priority_boost(parsed_call.as_ref()) { Some(bundled_messages) => bundled_messages, - None => return Ok((Default::default(), parsed_call, origin)), + None => return Ok(Default::default()), }; // we only boost priority if relayer has staked required balance if !RelayersPallet::::is_registration_active(who) { - return Ok((Default::default(), parsed_call, origin)) + return Ok(Default::default()) } // compute priority boost @@ -552,21 +535,20 @@ where priority_boost, ); - let validity = valid_transaction.build()?; - Ok((validity, parsed_call, origin)) + valid_transaction.build() } - fn prepare( + fn pre_dispatch( self, - val: Self::Val, - origin: & as Dispatchable>::RuntimeOrigin, - _call: &CallOf, - _info: &DispatchInfoOf>, + who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &Context, ) -> Result { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; - Ok(val.map(|call_info| { + // this is a relevant piece of `validate` that we need here (in `pre_dispatch`) + let parsed_call = T::parse_and_check_for_obsolete_call(call)?; + + Ok(parsed_call.map(|call_info| { log::trace!( target: "runtime::bridge", "{} via {:?} parsed bridge transaction in pre-dispatch: {:?}", @@ -579,14 +561,13 @@ where } fn post_dispatch( - pre: Self::Pre, - info: &DispatchInfoOf>, - post_info: &PostDispatchInfoOf>, + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, - _context: &Context, ) -> Result<(), TransactionValidityError> { - let call_result = T::analyze_call_result(Some(pre), info, post_info, len, result); + let call_result = T::analyze_call_result(pre, info, post_info, len, result); match call_result { RelayerAccountAction::None => (), @@ -614,7 +595,7 @@ where } } -/// Transaction extension that refunds a relayer for new messages coming from a parachain. +/// Signed extension that refunds a relayer for new messages coming from a parachain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and @@ -655,7 +636,7 @@ pub struct RefundBridgedParachainMessages, ); -impl RefundTransactionExtension +impl RefundSignedExtension for RefundBridgedParachainMessages where Self: 'static + Send + Sync, @@ -749,13 +730,13 @@ where } } -/// Transaction extension that refunds a relayer for new messages coming from a standalone (GRANDPA) +/// Signed extension that refunds a relayer for new messages coming from a standalone (GRANDPA) /// chain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and -/// parachain head, or just parachain head. Corresponding headers must be used in messages proof -/// verification. +/// parachain head, or just parachain head. Corresponding headers must be used in messages +/// proof verification. /// /// Extension does not refund transaction tip due to security reasons. #[derive( @@ -790,7 +771,7 @@ pub struct RefundBridgedGrandpaMessages, ); -impl RefundTransactionExtension +impl RefundSignedExtension for RefundBridgedGrandpaMessages where Self: 'static + Send + Sync, @@ -888,8 +869,8 @@ mod tests { Call as ParachainsCall, Pallet as ParachainsPallet, RelayBlockHash, }; use sp_runtime::{ - traits::{ConstU64, DispatchTransaction, Header as HeaderT}, - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + traits::{ConstU64, Header as HeaderT}, + transaction_validity::{InvalidTransaction, ValidTransaction}, DispatchError, }; @@ -918,7 +899,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; - type TestGrandpaExtension = RefundTransactionExtensionAdapter; + type TestGrandpaExtension = RefundSignedExtensionAdapter; type TestExtensionProvider = RefundBridgedParachainMessages< TestRuntime, DefaultRefundableParachainId<(), TestParachain>, @@ -927,7 +908,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; - type TestExtension = RefundTransactionExtensionAdapter; + type TestExtension = RefundSignedExtensionAdapter; fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance { let test_stake: ThisChainBalance = TestStake::get(); @@ -1426,28 +1407,14 @@ mod tests { fn run_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestExtension = - RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); - extension - .validate_only( - Some(relayer_account_at_this_chain()).into(), - &call, - &DispatchInfo::default(), - 0, - ) - .map(|res| res.0) + RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn run_grandpa_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestGrandpaExtension = - RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); - extension - .validate_only( - Some(relayer_account_at_this_chain()).into(), - &call, - &DispatchInfo::default(), - 0, - ) - .map(|res| res.0) + RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); + extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn run_validate_ignore_priority(call: RuntimeCall) -> TransactionValidity { @@ -1461,30 +1428,16 @@ mod tests { call: RuntimeCall, ) -> Result>, TransactionValidityError> { let extension: TestExtension = - RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); - extension - .validate_and_prepare( - Some(relayer_account_at_this_chain()).into(), - &call, - &DispatchInfo::default(), - 0, - ) - .map(|(pre, _)| pre) + RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn run_grandpa_pre_dispatch( call: RuntimeCall, ) -> Result>, TransactionValidityError> { let extension: TestGrandpaExtension = - RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); - extension - .validate_and_prepare( - Some(relayer_account_at_this_chain()).into(), - &call, - &DispatchInfo::default(), - 0, - ) - .map(|(pre, _)| pre) + RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); + extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn dispatch_info() -> DispatchInfo { @@ -1507,12 +1460,11 @@ mod tests { dispatch_result: DispatchResult, ) { let post_dispatch_result = TestExtension::post_dispatch( - pre_dispatch_data, + Some(pre_dispatch_data), &dispatch_info(), &post_dispatch_info(), 1024, &dispatch_result, - &(), ); assert_eq!(post_dispatch_result, Ok(())); } diff --git a/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs b/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs index f186f6427ae..c49aa4b8563 100644 --- a/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -26,7 +26,7 @@ pub use bp_polkadot_core::{ }; use bp_messages::*; -use bp_polkadot_core::SuffixedCommonTransactionExtension; +use bp_polkadot_core::SuffixedCommonSignedExtension; use bp_runtime::extensions::{ BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, }; @@ -164,7 +164,7 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// Signed extension that is used by all bridge hubs. -pub type TransactionExtension = SuffixedCommonTransactionExtension<( +pub type SignedExtension = SuffixedCommonSignedExtension<( BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, )>; diff --git a/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs b/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs index 992ef1bd7a1..c4e697fbe95 100644 --- a/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -107,5 +107,5 @@ frame_support::parameter_types! { /// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation. /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_904_835; + pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_829_647; } diff --git a/bridges/primitives/chain-kusama/src/lib.rs b/bridges/primitives/chain-kusama/src/lib.rs index 253a1010e83..e3b4d0520f6 100644 --- a/bridges/primitives/chain-kusama/src/lib.rs +++ b/bridges/primitives/chain-kusama/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Kusama { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The TransactionExtension used by Kusama. -pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; +// The SignedExtension used by Kusama. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; /// Name of the parachains pallet in the Kusama runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/bridges/primitives/chain-polkadot-bulletin/src/lib.rs b/bridges/primitives/chain-polkadot-bulletin/src/lib.rs index 73dd122bd15..f2eebf93124 100644 --- a/bridges/primitives/chain-polkadot-bulletin/src/lib.rs +++ b/bridges/primitives/chain-polkadot-bulletin/src/lib.rs @@ -25,7 +25,7 @@ use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, extensions::{ CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion, - CheckWeight, GenericTransactionExtension, GenericTransactionExtensionSchema, + CheckWeight, GenericSignedExtension, GenericSignedExtensionSchema, }, Chain, ChainId, TransactionEra, }; @@ -37,12 +37,7 @@ use frame_support::{ }; use frame_system::limits; use scale_info::TypeInfo; -use sp_runtime::{ - impl_tx_ext_default, - traits::{Dispatchable, TransactionExtensionBase}, - transaction_validity::TransactionValidityError, - Perbill, -}; +use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidityError, Perbill}; // This chain reuses most of Polkadot primitives. pub use bp_polkadot_core::{ @@ -76,10 +71,10 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// This signed extension is used to ensure that the chain transactions are signed by proper -pub type ValidateSigned = GenericTransactionExtensionSchema<(), ()>; +pub type ValidateSigned = GenericSignedExtensionSchema<(), ()>; /// Signed extension schema, used by Polkadot Bulletin. -pub type TransactionExtensionSchema = GenericTransactionExtension<( +pub type SignedExtensionSchema = GenericSignedExtension<( ( CheckNonZeroSender, CheckSpecVersion, @@ -92,30 +87,34 @@ pub type TransactionExtensionSchema = GenericTransactionExtension<( ValidateSigned, )>; -/// Transaction extension, used by Polkadot Bulletin. +/// Signed extension, used by Polkadot Bulletin. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct TransactionExtension(TransactionExtensionSchema); +pub struct SignedExtension(SignedExtensionSchema); -impl TransactionExtensionBase for TransactionExtension { +impl sp_runtime::traits::SignedExtension for SignedExtension { const IDENTIFIER: &'static str = "Not needed."; - type Implicit = ::Implicit; + type AccountId = (); + type Call = (); + type AdditionalSigned = + ::AdditionalSigned; + type Pre = (); - fn implicit(&self) -> Result { - ::implicit(&self.0) + fn additional_signed(&self) -> Result { + self.0.additional_signed() } -} -impl sp_runtime::traits::TransactionExtension for TransactionExtension -where - C: Dispatchable, -{ - type Pre = (); - type Val = (); - - impl_tx_ext_default!(C; Context; validate prepare); + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } } -impl TransactionExtension { +impl SignedExtension { /// Create signed extension from its components. pub fn from_params( spec_version: u32, @@ -124,7 +123,7 @@ impl TransactionExtension { genesis_hash: Hash, nonce: Nonce, ) -> Self { - Self(GenericTransactionExtension::new( + Self(GenericSignedExtension::new( ( ( (), // non-zero sender diff --git a/bridges/primitives/chain-polkadot/src/lib.rs b/bridges/primitives/chain-polkadot/src/lib.rs index e5e2e7c3a04..fc5e10308a8 100644 --- a/bridges/primitives/chain-polkadot/src/lib.rs +++ b/bridges/primitives/chain-polkadot/src/lib.rs @@ -61,8 +61,8 @@ impl ChainWithGrandpa for Polkadot { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -/// The TransactionExtension used by Polkadot. -pub type TransactionExtension = SuffixedCommonTransactionExtension; +/// The SignedExtension used by Polkadot. +pub type SignedExtension = SuffixedCommonSignedExtension; /// Name of the parachains pallet in the Polkadot runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/bridges/primitives/chain-rococo/src/lib.rs b/bridges/primitives/chain-rococo/src/lib.rs index 267c6b2b1f0..f1b256f0f09 100644 --- a/bridges/primitives/chain-rococo/src/lib.rs +++ b/bridges/primitives/chain-rococo/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Rococo { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The TransactionExtension used by Rococo. -pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; +// The SignedExtension used by Rococo. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/bridges/primitives/chain-westend/src/lib.rs b/bridges/primitives/chain-westend/src/lib.rs index afa02e8ee54..f03fd2160a7 100644 --- a/bridges/primitives/chain-westend/src/lib.rs +++ b/bridges/primitives/chain-westend/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Westend { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The TransactionExtension used by Westend. -pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; +// The SignedExtension used by Westend. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/bridges/primitives/polkadot-core/src/lib.rs b/bridges/primitives/polkadot-core/src/lib.rs index d59b99db4b5..df2836495bb 100644 --- a/bridges/primitives/polkadot-core/src/lib.rs +++ b/bridges/primitives/polkadot-core/src/lib.rs @@ -24,8 +24,8 @@ use bp_runtime::{ self, extensions::{ ChargeTransactionPayment, CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, - CheckSpecVersion, CheckTxVersion, CheckWeight, GenericTransactionExtension, - TransactionExtensionSchema, + CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension, + SignedExtensionSchema, }, EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra, }; @@ -229,12 +229,8 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< - AccountAddress, - EncodedOrDecodedCall, - Signature, - TransactionExt, ->; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic, Signature, SignedExt>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; @@ -279,7 +275,7 @@ impl AccountInfoStorageMapKeyProvider { } /// Extra signed extension data that is used by most chains. -pub type CommonTransactionExtra = ( +pub type CommonSignedExtra = ( CheckNonZeroSender, CheckSpecVersion, CheckTxVersion, @@ -290,12 +286,12 @@ pub type CommonTransactionExtra = ( ChargeTransactionPayment, ); -/// Extra transaction extension data that starts with `CommonTransactionExtra`. -pub type SuffixedCommonTransactionExtension = - GenericTransactionExtension<(CommonTransactionExtra, Suffix)>; +/// Extra signed extension data that starts with `CommonSignedExtra`. +pub type SuffixedCommonSignedExtension = + GenericSignedExtension<(CommonSignedExtra, Suffix)>; -/// Helper trait to define some extra methods on `SuffixedCommonTransactionExtension`. -pub trait SuffixedCommonTransactionExtensionExt { +/// Helper trait to define some extra methods on `SuffixedCommonSignedExtension`. +pub trait SuffixedCommonSignedExtensionExt { /// Create signed extension from its components. fn from_params( spec_version: u32, @@ -304,7 +300,7 @@ pub trait SuffixedCommonTransactionExtensionExt Self; /// Return transaction nonce. @@ -314,10 +310,9 @@ pub trait SuffixedCommonTransactionExtensionExt Balance; } -impl SuffixedCommonTransactionExtensionExt - for SuffixedCommonTransactionExtension +impl SuffixedCommonSignedExtensionExt for SuffixedCommonSignedExtension where - Suffix: TransactionExtensionSchema, + Suffix: SignedExtensionSchema, { fn from_params( spec_version: u32, @@ -326,9 +321,9 @@ where genesis_hash: Hash, nonce: Nonce, tip: Balance, - extra: (Suffix::Payload, Suffix::Implicit), + extra: (Suffix::Payload, Suffix::AdditionalSigned), ) -> Self { - GenericTransactionExtension::new( + GenericSignedExtension::new( ( ( (), // non-zero sender @@ -370,7 +365,7 @@ where } /// Signed extension that is used by most chains. -pub type CommonTransactionExtension = SuffixedCommonTransactionExtension<()>; +pub type CommonSignedExtension = SuffixedCommonSignedExtension<()>; #[cfg(test)] mod tests { diff --git a/bridges/primitives/runtime/src/extensions.rs b/bridges/primitives/runtime/src/extensions.rs index a31e7b5bb47..d896bc92eff 100644 --- a/bridges/primitives/runtime/src/extensions.rs +++ b/bridges/primitives/runtime/src/extensions.rs @@ -20,138 +20,135 @@ use codec::{Compact, Decode, Encode}; use impl_trait_for_tuples::impl_for_tuples; use scale_info::{StaticTypeInfo, TypeInfo}; use sp_runtime::{ - impl_tx_ext_default, - traits::{Dispatchable, TransactionExtension, TransactionExtensionBase}, + traits::{DispatchInfoOf, SignedExtension}, transaction_validity::TransactionValidityError, }; use sp_std::{fmt::Debug, marker::PhantomData}; -/// Trait that describes some properties of a `TransactionExtension` that are needed in order to -/// send a transaction to the chain. -pub trait TransactionExtensionSchema: - Encode + Decode + Debug + Eq + Clone + StaticTypeInfo -{ +/// Trait that describes some properties of a `SignedExtension` that are needed in order to send a +/// transaction to the chain. +pub trait SignedExtensionSchema: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo { /// A type of the data encoded as part of the transaction. type Payload: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; /// Parameters which are part of the payload used to produce transaction signature, /// but don't end up in the transaction itself (i.e. inherent part of the runtime). - type Implicit: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; + type AdditionalSigned: Encode + Debug + Eq + Clone + StaticTypeInfo; } -impl TransactionExtensionSchema for () { +impl SignedExtensionSchema for () { type Payload = (); - type Implicit = (); + type AdditionalSigned = (); } -/// An implementation of `TransactionExtensionSchema` using generic params. +/// An implementation of `SignedExtensionSchema` using generic params. #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)] -pub struct GenericTransactionExtensionSchema(PhantomData<(P, S)>); +pub struct GenericSignedExtensionSchema(PhantomData<(P, S)>); -impl TransactionExtensionSchema for GenericTransactionExtensionSchema +impl SignedExtensionSchema for GenericSignedExtensionSchema where P: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, - S: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, + S: Encode + Debug + Eq + Clone + StaticTypeInfo, { type Payload = P; - type Implicit = S; + type AdditionalSigned = S; } -/// The `TransactionExtensionSchema` for `frame_system::CheckNonZeroSender`. -pub type CheckNonZeroSender = GenericTransactionExtensionSchema<(), ()>; +/// The `SignedExtensionSchema` for `frame_system::CheckNonZeroSender`. +pub type CheckNonZeroSender = GenericSignedExtensionSchema<(), ()>; -/// The `TransactionExtensionSchema` for `frame_system::CheckSpecVersion`. -pub type CheckSpecVersion = GenericTransactionExtensionSchema<(), u32>; +/// The `SignedExtensionSchema` for `frame_system::CheckSpecVersion`. +pub type CheckSpecVersion = GenericSignedExtensionSchema<(), u32>; -/// The `TransactionExtensionSchema` for `frame_system::CheckTxVersion`. -pub type CheckTxVersion = GenericTransactionExtensionSchema<(), u32>; +/// The `SignedExtensionSchema` for `frame_system::CheckTxVersion`. +pub type CheckTxVersion = GenericSignedExtensionSchema<(), u32>; -/// The `TransactionExtensionSchema` for `frame_system::CheckGenesis`. -pub type CheckGenesis = GenericTransactionExtensionSchema<(), Hash>; +/// The `SignedExtensionSchema` for `frame_system::CheckGenesis`. +pub type CheckGenesis = GenericSignedExtensionSchema<(), Hash>; -/// The `TransactionExtensionSchema` for `frame_system::CheckEra`. -pub type CheckEra = GenericTransactionExtensionSchema; +/// The `SignedExtensionSchema` for `frame_system::CheckEra`. +pub type CheckEra = GenericSignedExtensionSchema; -/// The `TransactionExtensionSchema` for `frame_system::CheckNonce`. -pub type CheckNonce = GenericTransactionExtensionSchema, ()>; +/// The `SignedExtensionSchema` for `frame_system::CheckNonce`. +pub type CheckNonce = GenericSignedExtensionSchema, ()>; -/// The `TransactionExtensionSchema` for `frame_system::CheckWeight`. -pub type CheckWeight = GenericTransactionExtensionSchema<(), ()>; +/// The `SignedExtensionSchema` for `frame_system::CheckWeight`. +pub type CheckWeight = GenericSignedExtensionSchema<(), ()>; -/// The `TransactionExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. -pub type ChargeTransactionPayment = - GenericTransactionExtensionSchema, ()>; +/// The `SignedExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. +pub type ChargeTransactionPayment = GenericSignedExtensionSchema, ()>; -/// The `TransactionExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. -pub type PrevalidateAttests = GenericTransactionExtensionSchema<(), ()>; +/// The `SignedExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. +pub type PrevalidateAttests = GenericSignedExtensionSchema<(), ()>; -/// The `TransactionExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. -pub type BridgeRejectObsoleteHeadersAndMessages = GenericTransactionExtensionSchema<(), ()>; +/// The `SignedExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. +pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<(), ()>; -/// The `TransactionExtensionSchema` for `RefundBridgedParachainMessages`. +/// The `SignedExtensionSchema` for `RefundBridgedParachainMessages`. /// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as /// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (), /// ())` is the same. So runtime can contains any kind of tuple: /// `(BridgeRefundBridgeHubRococoMessages)` /// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWestendMessages)` /// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)` -pub type RefundBridgedParachainMessagesSchema = GenericTransactionExtensionSchema<(), ()>; +pub type RefundBridgedParachainMessagesSchema = GenericSignedExtensionSchema<(), ()>; #[impl_for_tuples(1, 12)] -impl TransactionExtensionSchema for Tuple { +impl SignedExtensionSchema for Tuple { for_tuples!( type Payload = ( #( Tuple::Payload ),* ); ); - for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); ); + for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); } /// A simplified version of signed extensions meant for producing signed transactions /// and signed payloads in the client code. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct GenericTransactionExtension { +pub struct GenericSignedExtension { /// A payload that is included in the transaction. pub payload: S::Payload, #[codec(skip)] // It may be set to `None` if extensions are decoded. We are never reconstructing transactions - // (and it makes no sense to do that) => decoded version of `TransactionExtensions` is only - // used to read fields of the `payload`. And when resigning transaction, we're reconstructing - // `TransactionExtensions` from scratch. - implicit: Option, + // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to + // read fields of the `payload`. And when resigning transaction, we're reconstructing + // `SignedExtensions` from scratch. + additional_signed: Option, } -impl GenericTransactionExtension { - /// Create new `GenericTransactionExtension` object. - pub fn new(payload: S::Payload, implicit: Option) -> Self { - Self { payload, implicit } +impl GenericSignedExtension { + /// Create new `GenericSignedExtension` object. + pub fn new(payload: S::Payload, additional_signed: Option) -> Self { + Self { payload, additional_signed } } } -impl TransactionExtensionBase for GenericTransactionExtension +impl SignedExtension for GenericSignedExtension where - S: TransactionExtensionSchema, + S: SignedExtensionSchema, S::Payload: Send + Sync, - S::Implicit: Send + Sync, + S::AdditionalSigned: Send + Sync, { const IDENTIFIER: &'static str = "Not needed."; - type Implicit = S::Implicit; + type AccountId = (); + type Call = (); + type AdditionalSigned = S::AdditionalSigned; + type Pre = (); - fn implicit(&self) -> Result { + fn additional_signed(&self) -> Result { // we shall not ever see this error in relay, because we are never signing decoded // transactions. Instead we're constructing and signing new transactions. So the error code // is kinda random here - self.implicit - .clone() - .ok_or(frame_support::unsigned::TransactionValidityError::Unknown( + self.additional_signed.clone().ok_or( + frame_support::unsigned::TransactionValidityError::Unknown( frame_support::unsigned::UnknownTransaction::Custom(0xFF), - )) + ), + ) } -} -impl TransactionExtension for GenericTransactionExtension -where - C: Dispatchable, - S: TransactionExtensionSchema, - S::Payload: Send + Sync, - S::Implicit: Send + Sync, -{ - type Pre = (); - type Val = (); - impl_tx_ext_default!(C; Context; validate prepare); + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } } diff --git a/bridges/snowbridge/runtime/test-common/Cargo.toml b/bridges/snowbridge/runtime/test-common/Cargo.toml index 5f169e82f49..4e8b311cb97 100644 --- a/bridges/snowbridge/runtime/test-common/Cargo.toml +++ b/bridges/snowbridge/runtime/test-common/Cargo.toml @@ -181,7 +181,6 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index 3eb63a24b74..05936e93993 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -119,7 +119,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-asset-conversion-tx-payment/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -131,7 +130,6 @@ runtime-benchmarks = [ "pallet-proxy/runtime-benchmarks", "pallet-state-trie-migration/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 32966ab6341..17a12dd2f6f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -178,7 +178,6 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; @@ -235,7 +234,6 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -763,9 +761,6 @@ impl pallet_asset_conversion_tx_payment::Config for Runtime { type Fungibles = LocalAndForeignAssets; type OnChargeAssetTransaction = AssetConversionAdapter; - type WeightInfo = weights::pallet_asset_conversion_tx_payment::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = AssetConversionTxHelper; } parameter_types! { @@ -953,8 +948,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -966,7 +961,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( pallet_collator_selection::migration::v1::MigrateToV1, @@ -1039,77 +1034,14 @@ pub type Executive = frame_executive::Executive< Migrations, >; -#[cfg(feature = "runtime-benchmarks")] -pub struct AssetConversionTxHelper; - -#[cfg(feature = "runtime-benchmarks")] -impl - pallet_asset_conversion_tx_payment::BenchmarkHelperTrait< - AccountId, - xcm::v3::MultiLocation, - xcm::v3::MultiLocation, - > for AssetConversionTxHelper -{ - fn create_asset_id_parameter(seed: u32) -> (xcm::v3::MultiLocation, xcm::v3::MultiLocation) { - // Use a different parachain' foreign assets pallet so that the asset is indeed foreign. - let asset_id = xcm::v3::MultiLocation::new( - 1, - xcm::v3::Junctions::X3( - xcm::v3::Junction::Parachain(3000), - xcm::v3::Junction::PalletInstance(53), - xcm::v3::Junction::GeneralIndex(seed.into()), - ), - ); - (asset_id, asset_id) - } - - fn setup_balances_and_pool(asset_id: xcm::v3::MultiLocation, account: AccountId) { - use frame_support::{assert_ok, traits::fungibles::Mutate}; - assert_ok!(ForeignAssets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - account.clone().into(), /* owner */ - true, /* is_sufficient */ - 1, - )); - - let lp_provider = account.clone(); - use frame_support::traits::Currency; - let _ = Balances::deposit_creating(&lp_provider, u64::MAX.into()); - assert_ok!(ForeignAssets::mint_into(asset_id.into(), &lp_provider, u64::MAX.into())); - - let token_native = Box::new(TokenLocationV3::get()); - let token_second = Box::new(asset_id); - - assert_ok!(AssetConversion::create_pool( - RuntimeOrigin::signed(lp_provider.clone()), - token_native.clone(), - token_second.clone() - )); - - assert_ok!(AssetConversion::add_liquidity( - RuntimeOrigin::signed(lp_provider.clone()), - token_native, - token_second, - (u32::MAX / 8).into(), // 1 desired - u32::MAX.into(), // 2 desired - 1, // 1 min - 1, // 2 min - lp_provider, - )); - } -} - #[cfg(feature = "runtime-benchmarks")] mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_assets, Local] [pallet_assets, Foreign] [pallet_assets, Pool] [pallet_asset_conversion, AssetConversion] - [pallet_asset_conversion_tx_payment, AssetTxPayment] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] @@ -1120,7 +1052,6 @@ mod benches { [pallet_uniques, Uniques] [pallet_utility, Utility] [pallet_timestamp, Timestamp] - [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -1371,7 +1302,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; @@ -1406,7 +1336,6 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs deleted file mode 100644 index ed2c5f3056e..00000000000 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/ -// --chain=asset-hub-rococo-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_637_000 picoseconds. - Weight::from_parts(6_382_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_841_000 picoseconds. - Weight::from_parts(8_776_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 561_000 picoseconds. - Weight::from_parts(2_705_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_316_000 picoseconds. - Weight::from_parts(5_771_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 511_000 picoseconds. - Weight::from_parts(2_575_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 501_000 picoseconds. - Weight::from_parts(2_595_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_687_000 picoseconds. - Weight::from_parts(6_192_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs index 134b5341a40..fa9e86102c6 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs @@ -19,9 +19,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_asset_conversion; -pub mod pallet_asset_conversion_tx_payment; pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; @@ -34,7 +32,6 @@ pub mod pallet_nfts; pub mod pallet_proxy; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_conversion_tx_payment.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_conversion_tx_payment.rs deleted file mode 100644 index 0a639b368af..00000000000 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_conversion_tx_payment.rs +++ /dev/null @@ -1,92 +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 . - -//! Autogenerated weights for `pallet_asset_conversion_tx_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-04, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `Georges-MacBook-Pro.local`, CPU: `` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/debug/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_asset_conversion_tx_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/ -// --chain=asset-hub-rococo-dev - -#![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_asset_conversion_tx_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_asset_conversion_tx_payment::WeightInfo for WeightInfo { - fn charge_asset_tx_payment_zero() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 7_000_000 picoseconds. - Weight::from_parts(10_000_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_asset_tx_payment_native() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 209_000_000 picoseconds. - Weight::from_parts(212_000_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Asset` (r:1 w:1) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Account` (r:2 w:2) - /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_asset_tx_payment_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `631` - // Estimated: `7404` - // Minimum execution time: 1_228_000_000 picoseconds. - Weight::from_parts(1_268_000_000, 0) - .saturating_add(Weight::from_parts(0, 7404)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(4)) - } -} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 035f9a6dbe5..00000000000 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/ -// --chain=asset-hub-rococo-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 33_363_000 picoseconds. - Weight::from_parts(38_793_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index c10e02bd8a6..78c48507a7a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -110,7 +110,6 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "hex-literal", - "pallet-asset-conversion-tx-payment/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -121,7 +120,6 @@ runtime-benchmarks = [ "pallet-nfts/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 5246828da31..1ead2897855 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -162,7 +162,6 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; @@ -219,7 +218,6 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -737,9 +735,6 @@ impl pallet_asset_conversion_tx_payment::Config for Runtime { type Fungibles = LocalAndForeignAssets; type OnChargeAssetTransaction = AssetConversionAdapter; - type WeightInfo = weights::pallet_asset_conversion_tx_payment::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = AssetConversionTxHelper; } parameter_types! { @@ -925,8 +920,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -938,7 +933,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -1070,77 +1065,14 @@ pub type Executive = frame_executive::Executive< Migrations, >; -#[cfg(feature = "runtime-benchmarks")] -pub struct AssetConversionTxHelper; - -#[cfg(feature = "runtime-benchmarks")] -impl - pallet_asset_conversion_tx_payment::BenchmarkHelperTrait< - AccountId, - xcm::v3::MultiLocation, - xcm::v3::MultiLocation, - > for AssetConversionTxHelper -{ - fn create_asset_id_parameter(seed: u32) -> (xcm::v3::MultiLocation, xcm::v3::MultiLocation) { - // Use a different parachain' foreign assets pallet so that the asset is indeed foreign. - let asset_id = xcm::v3::MultiLocation::new( - 1, - xcm::v3::Junctions::X3( - xcm::v3::Junction::Parachain(3000), - xcm::v3::Junction::PalletInstance(53), - xcm::v3::Junction::GeneralIndex(seed.into()), - ), - ); - (asset_id, asset_id) - } - - fn setup_balances_and_pool(asset_id: xcm::v3::MultiLocation, account: AccountId) { - use frame_support::{assert_ok, traits::fungibles::Mutate}; - assert_ok!(ForeignAssets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - account.clone().into(), /* owner */ - true, /* is_sufficient */ - 1, - )); - - let lp_provider = account.clone(); - use frame_support::traits::Currency; - let _ = Balances::deposit_creating(&lp_provider, u64::MAX.into()); - assert_ok!(ForeignAssets::mint_into(asset_id.into(), &lp_provider, u64::MAX.into())); - - let token_native = Box::new(xcm::v3::MultiLocation::new(1, xcm::v3::Junctions::Here)); - let token_second = Box::new(asset_id); - - assert_ok!(AssetConversion::create_pool( - RuntimeOrigin::signed(lp_provider.clone()), - token_native.clone(), - token_second.clone() - )); - - assert_ok!(AssetConversion::add_liquidity( - RuntimeOrigin::signed(lp_provider.clone()), - token_native, - token_second, - (u32::MAX / 2).into(), // 1 desired - u32::MAX.into(), // 2 desired - 1, // 1 min - 1, // 2 min - lp_provider, - )); - } -} - #[cfg(feature = "runtime-benchmarks")] mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_assets, Local] [pallet_assets, Foreign] [pallet_assets, Pool] [pallet_asset_conversion, AssetConversion] - [pallet_asset_conversion_tx_payment, AssetTxPayment] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] @@ -1151,7 +1083,6 @@ mod benches { [pallet_uniques, Uniques] [pallet_utility, Utility] [pallet_timestamp, Timestamp] - [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -1448,7 +1379,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; @@ -1483,7 +1413,6 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs deleted file mode 100644 index 46f4f2bfd96..00000000000 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/ -// --chain=asset-hub-westend-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_206_000 picoseconds. - Weight::from_parts(6_212_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_851_000 picoseconds. - Weight::from_parts(8_847_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 631_000 picoseconds. - Weight::from_parts(3_086_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_446_000 picoseconds. - Weight::from_parts(5_911_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 481_000 picoseconds. - Weight::from_parts(2_916_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 501_000 picoseconds. - Weight::from_parts(2_595_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_927_000 picoseconds. - Weight::from_parts(6_613_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs index 691ed2e5730..2f1fcfb05f3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs @@ -18,9 +18,7 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_asset_conversion; -pub mod pallet_asset_conversion_tx_payment; pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; @@ -33,7 +31,6 @@ pub mod pallet_nfts; pub mod pallet_proxy; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_conversion_tx_payment.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_conversion_tx_payment.rs deleted file mode 100644 index 8fe302630fb..00000000000 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_conversion_tx_payment.rs +++ /dev/null @@ -1,92 +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 . - -//! Autogenerated weights for `pallet_asset_conversion_tx_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-04, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `Georges-MacBook-Pro.local`, CPU: `` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/debug/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_asset_conversion_tx_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/ -// --chain=asset-hub-westend-dev - -#![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_asset_conversion_tx_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_asset_conversion_tx_payment::WeightInfo for WeightInfo { - fn charge_asset_tx_payment_zero() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 8_000_000 picoseconds. - Weight::from_parts(9_000_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_asset_tx_payment_native() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 214_000_000 picoseconds. - Weight::from_parts(219_000_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Asset` (r:1 w:1) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Account` (r:2 w:2) - /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_asset_tx_payment_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `631` - // Estimated: `7404` - // Minimum execution time: 1_211_000_000 picoseconds. - Weight::from_parts(1_243_000_000, 0) - .saturating_add(Weight::from_parts(0, 7404)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(4)) - } -} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index b4c78a78b48..00000000000 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/ -// --chain=asset-hub-westend-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 40_847_000 picoseconds. - Weight::from_parts(49_674_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 242627815d3..7a1951fd24b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -242,7 +242,6 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-bridge-hub/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs index 323e6ed65e6..6dbf96edc2a 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_bulletin_config.rs @@ -40,7 +40,7 @@ use bridge_runtime_common::{ XcmBlobMessageDispatch, XcmVersionOfDestAndRemoteBridge, }, refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedGrandpaMessages, RefundTransactionExtensionAdapter, + ActualFeeRefund, RefundBridgedGrandpaMessages, RefundSignedExtensionAdapter, RefundableMessagesLane, }, }; @@ -168,7 +168,7 @@ impl messages::BridgedChainWithMessages for RococoBulletin {} /// Signed extension that refunds relayers that are delivering messages from the Rococo Bulletin /// chain. -pub type OnBridgeHubRococoRefundRococoBulletinMessages = RefundTransactionExtensionAdapter< +pub type OnBridgeHubRococoRefundRococoBulletinMessages = RefundSignedExtensionAdapter< RefundBridgedGrandpaMessages< Runtime, BridgeGrandpaRococoBulletinInstance, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs index 05d1aa188d2..5d55d7afbac 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_westend_config.rs @@ -39,7 +39,7 @@ use bridge_runtime_common::{ XcmBlobMessageDispatch, XcmVersionOfDestAndRemoteBridge, }, refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedParachainMessages, RefundTransactionExtensionAdapter, + ActualFeeRefund, RefundBridgedParachainMessages, RefundSignedExtensionAdapter, RefundableMessagesLane, RefundableParachain, }, }; @@ -173,7 +173,7 @@ impl UnderlyingChainProvider for BridgeHubWestend { impl messages::BridgedChainWithMessages for BridgeHubWestend {} /// Signed extension that refunds relayers that are delivering messages from the Westend parachain. -pub type OnBridgeHubRococoRefundBridgeHubWestendMessages = RefundTransactionExtensionAdapter< +pub type OnBridgeHubRococoRefundBridgeHubWestendMessages = RefundSignedExtensionAdapter< RefundBridgedParachainMessages< Runtime, RefundableParachain< diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 16e3b2e8600..0b48d1717fa 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -115,8 +115,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The TransactionExtension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -134,7 +134,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -262,8 +262,6 @@ impl frame_system::Config for Runtime { type DbWeight = RocksDbWeight; /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = weights::frame_system::WeightInfo; - /// Weight information for the extensions of this pallet. - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; /// Block & extrinsics weights: base values and limits. type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). @@ -326,7 +324,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -762,14 +759,12 @@ bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] - [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -1070,7 +1065,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -1101,7 +1095,6 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); @@ -1485,16 +1478,16 @@ mod tests { use codec::Encode; use sp_runtime::{ generic::Era, - traits::{TransactionExtensionBase, Zero}, + traits::{SignedExtension, Zero}, }; #[test] fn ensure_signed_extension_definition_is_compatible_with_relay() { - use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; + use bp_polkadot_core::SuffixedCommonSignedExtensionExt; sp_io::TestExternalities::default().execute_with(|| { frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); - let payload: TxExtension = ( + let payload: SignedExtra = ( frame_system::CheckNonZeroSender::new(), frame_system::CheckSpecVersion::new(), frame_system::CheckTxVersion::new(), @@ -1508,11 +1501,11 @@ mod tests { bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(), bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages::default(), ) - ).into(); + ); // for BridgeHubRococo { - let bhr_indirect_payload = bp_bridge_hub_rococo::TransactionExtension::from_params( + let bhr_indirect_payload = bp_bridge_hub_rococo::SignedExtension::from_params( VERSION.spec_version, VERSION.transaction_version, bp_runtime::TransactionEra::Immortal, @@ -1523,8 +1516,8 @@ mod tests { ); assert_eq!(payload.encode(), bhr_indirect_payload.encode()); assert_eq!( - payload.implicit().unwrap().encode(), - bhr_indirect_payload.implicit().unwrap().encode() + payload.additional_signed().unwrap().encode(), + bhr_indirect_payload.additional_signed().unwrap().encode() ) } }); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs deleted file mode 100644 index 99e3d6aeba0..00000000000 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/ -// --chain=bridge-hub-rococo-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_136_000 picoseconds. - Weight::from_parts(5_842_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_771_000 picoseconds. - Weight::from_parts(8_857_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 732_000 picoseconds. - Weight::from_parts(2_875_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_627_000 picoseconds. - Weight::from_parts(6_322_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 471_000 picoseconds. - Weight::from_parts(2_455_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 491_000 picoseconds. - Weight::from_parts(2_916_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_798_000 picoseconds. - Weight::from_parts(6_272_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs index d97a30db954..aac39a4564f 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs @@ -25,7 +25,6 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_bridge_grandpa; pub mod pallet_bridge_messages_rococo_to_rococo_bulletin; @@ -37,7 +36,6 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 71d17e7259f..00000000000 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/ -// --chain=bridge-hub-rococo-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `3` - // Estimated: `3593` - // Minimum execution time: 34_956_000 picoseconds. - Weight::from_parts(40_788_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs index 46c5df18a15..239bd946e75 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs @@ -22,7 +22,7 @@ use bridge_hub_rococo_runtime::{ bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages, xcm_config::XcmConfig, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, MessageQueueServiceWeight, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, - TxExtension, UncheckedExtrinsic, + SignedExtra, UncheckedExtrinsic, }; use codec::{Decode, Encode}; use cumulus_primitives_core::XcmError::{FailedToTransactAsset, NotHoldingFees}; @@ -171,7 +171,7 @@ fn construct_extrinsic( call: RuntimeCall, ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); - let tx_ext: TxExtension = ( + let extra: SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -188,13 +188,13 @@ fn construct_extrinsic( OnBridgeHubRococoRefundRococoBulletinMessages::default(), ), ); - let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); + 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()), - tx_ext, + extra, ) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index 565343c55a5..f11954cf165 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -22,7 +22,7 @@ use bridge_hub_rococo_runtime::{ xcm_config::{RelayNetwork, TokenLocation, XcmConfig}, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, EthereumGatewayAddress, Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, - RuntimeEvent, RuntimeOrigin, SessionKeys, TransactionPayment, TxExtension, UncheckedExtrinsic, + RuntimeEvent, RuntimeOrigin, SessionKeys, SignedExtra, TransactionPayment, UncheckedExtrinsic, }; use bridge_hub_test_utils::SlotDurations; use codec::{Decode, Encode}; @@ -48,7 +48,7 @@ fn construct_extrinsic( call: RuntimeCall, ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); - let tx_ext: TxExtension = ( + let extra: SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -64,15 +64,14 @@ fn construct_extrinsic( bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(), bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages::default(), ), - ) - .into(); - let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); + ); + 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()), - tx_ext, + extra, ) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml index b5fe093b8be..8623f7cb366 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml @@ -204,7 +204,6 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-bridge-hub/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs index 934dce5c2c4..bce722aa5f8 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs @@ -36,7 +36,7 @@ use bridge_runtime_common::{ XcmBlobMessageDispatch, XcmVersionOfDestAndRemoteBridge, }, refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedParachainMessages, RefundTransactionExtensionAdapter, + ActualFeeRefund, RefundBridgedParachainMessages, RefundSignedExtensionAdapter, RefundableMessagesLane, RefundableParachain, }, }; @@ -190,7 +190,7 @@ impl ThisChainWithMessages for BridgeHubWestend { } /// Signed extension that refunds relayers that are delivering messages from the Rococo parachain. -pub type OnBridgeHubWestendRefundBridgeHubRococoMessages = RefundTransactionExtensionAdapter< +pub type OnBridgeHubWestendRefundBridgeHubRococoMessages = RefundSignedExtensionAdapter< RefundBridgedParachainMessages< Runtime, RefundableParachain, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 86ed8b2f488..e1344fce63d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -97,8 +97,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The TransactionExtension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -113,7 +113,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -298,7 +298,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -516,14 +515,12 @@ bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] - [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -764,7 +761,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -794,7 +790,6 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); @@ -1140,16 +1135,16 @@ mod tests { use codec::Encode; use sp_runtime::{ generic::Era, - traits::{TransactionExtensionBase, Zero}, + traits::{SignedExtension, Zero}, }; #[test] fn ensure_signed_extension_definition_is_compatible_with_relay() { - use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; + use bp_polkadot_core::SuffixedCommonSignedExtensionExt; sp_io::TestExternalities::default().execute_with(|| { frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); - let payload: TxExtension = ( + let payload: SignedExtra = ( frame_system::CheckNonZeroSender::new(), frame_system::CheckSpecVersion::new(), frame_system::CheckTxVersion::new(), @@ -1162,10 +1157,10 @@ mod tests { ( bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages::default(), ), - ).into(); + ); { - let bh_indirect_payload = bp_bridge_hub_westend::TransactionExtension::from_params( + let bh_indirect_payload = bp_bridge_hub_westend::SignedExtension::from_params( VERSION.spec_version, VERSION.transaction_version, bp_runtime::TransactionEra::Immortal, @@ -1176,8 +1171,8 @@ mod tests { ); assert_eq!(payload.encode(), bh_indirect_payload.encode()); assert_eq!( - payload.implicit().unwrap().encode(), - bh_indirect_payload.implicit().unwrap().encode() + payload.additional_signed().unwrap().encode(), + bh_indirect_payload.additional_signed().unwrap().encode() ) } }); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs deleted file mode 100644 index 06f1114b4de..00000000000 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/ -// --chain=bridge-hub-westend-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_166_000 picoseconds. - Weight::from_parts(6_021_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_651_000 picoseconds. - Weight::from_parts(9_177_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 601_000 picoseconds. - Weight::from_parts(2_805_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_727_000 picoseconds. - Weight::from_parts(6_051_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 471_000 picoseconds. - Weight::from_parts(2_494_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 521_000 picoseconds. - Weight::from_parts(2_655_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_808_000 picoseconds. - Weight::from_parts(6_402_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs index e23033e0dfd..a65ee31d3e5 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/mod.rs @@ -25,7 +25,6 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_bridge_grandpa; pub mod pallet_bridge_messages; @@ -36,7 +35,6 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 92c53b91879..00000000000 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/ -// --chain=bridge-hub-westend-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `3` - // Estimated: `3593` - // Minimum execution time: 40_286_000 picoseconds. - Weight::from_parts(45_816_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs index 7ea22befe95..149a3bbeb75 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs @@ -24,7 +24,7 @@ use bridge_hub_westend_runtime::{ xcm_config::{RelayNetwork, WestendLocation, XcmConfig}, AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, - TransactionPayment, TxExtension, UncheckedExtrinsic, + SignedExtra, TransactionPayment, UncheckedExtrinsic, }; use bridge_to_rococo_config::{ BridgeGrandpaRococoInstance, BridgeHubRococoChainId, BridgeHubRococoLocation, @@ -65,7 +65,7 @@ fn construct_extrinsic( call: RuntimeCall, ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); - let tx_ext: TxExtension = ( + let extra: SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -78,15 +78,14 @@ fn construct_extrinsic( pallet_transaction_payment::ChargeTransactionPayment::::from(0), BridgeRejectObsoleteHeadersAndMessages::default(), (bridge_to_rococo_config::OnBridgeHubWestendRefundBridgeHubRococoMessages::default(),), - ) - .into(); - let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); + ); + 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()), - tx_ext, + extra, ) } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml index 32d7e97bc45..ed264f28c26 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml @@ -117,7 +117,6 @@ runtime-benchmarks = [ "pallet-salary/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 3887a1d74ec..6bcf98c428f 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -175,7 +175,6 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = ConstU16<0>; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; @@ -232,7 +231,6 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -709,8 +707,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -721,7 +719,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// All migrations executed on runtime upgrade as a nested tuple of types implementing /// `OnRuntimeUpgrade`. Included migrations must be idempotent. type Migrations = ( @@ -747,7 +745,6 @@ pub type Executive = frame_executive::Executive< mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] @@ -755,7 +752,6 @@ mod benches { [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] - [pallet_transaction_payment, TransactionPayment] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] @@ -959,7 +955,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -977,7 +972,6 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs deleted file mode 100644 index f3030cc4f6a..00000000000 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/ -// --chain=collectives-westend-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_497_000 picoseconds. - Weight::from_parts(5_961_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_240_000 picoseconds. - Weight::from_parts(8_175_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 671_000 picoseconds. - Weight::from_parts(3_005_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_426_000 picoseconds. - Weight::from_parts(6_131_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 501_000 picoseconds. - Weight::from_parts(2_715_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 491_000 picoseconds. - Weight::from_parts(2_635_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_958_000 picoseconds. - Weight::from_parts(6_753_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs index 00b3bd92d5e..a9a298e547e 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/mod.rs @@ -18,7 +18,6 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_alliance; pub mod pallet_asset_rate; pub mod pallet_balances; @@ -40,7 +39,6 @@ pub mod pallet_salary_fellowship_salary; pub mod pallet_scheduler; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_treasury; pub mod pallet_utility; pub mod pallet_xcm; diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 5d077b89d56..00000000000 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/ -// --chain=collectives-westend-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 39_815_000 picoseconds. - Weight::from_parts(46_067_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml index 747f75cf2e2..dcc6c4e853a 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml @@ -158,7 +158,6 @@ runtime-benchmarks = [ "pallet-multisig/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 8ce46ccd34f..0668b9a4c7d 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -80,8 +80,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -93,7 +93,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -240,7 +240,6 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; - type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } parameter_types! { @@ -424,7 +423,6 @@ construct_runtime!( mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] @@ -688,7 +686,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -706,7 +703,6 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml index 70a6a81bdcf..0bc3b510ed5 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml @@ -156,7 +156,6 @@ runtime-benchmarks = [ "pallet-multisig/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 9913e47a93a..cdff371c505 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -89,8 +89,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The TransactionExtension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -103,7 +103,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -192,8 +192,6 @@ impl frame_system::Config for Runtime { type DbWeight = RocksDbWeight; /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = weights::frame_system::WeightInfo; - /// Weight information for the extensions of this pallet. - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; /// Block & extrinsics weights: base values and limits. type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). @@ -253,7 +251,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs deleted file mode 100644 index aac73680ad1..00000000000 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/ -// --chain=coretime-rococo-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_637_000 picoseconds. - Weight::from_parts(6_382_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_841_000 picoseconds. - Weight::from_parts(8_776_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 561_000 picoseconds. - Weight::from_parts(2_705_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_316_000 picoseconds. - Weight::from_parts(5_771_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 511_000 picoseconds. - Weight::from_parts(2_575_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 501_000 picoseconds. - Weight::from_parts(2_595_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_687_000 picoseconds. - Weight::from_parts(6_192_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs index 7b6ab611e6f..f1050b3ae63 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/mod.rs @@ -22,7 +22,6 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_broker; pub mod pallet_collator_selection; @@ -30,7 +29,6 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 29d48abab89..00000000000 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/ -// --chain=coretime-rococo-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 33_363_000 picoseconds. - Weight::from_parts(38_793_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml index 549ef7ce4d7..a7d52dfd784 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml @@ -153,7 +153,6 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 1a330821d3f..7fa70647992 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -89,8 +89,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The TransactionExtension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -103,7 +103,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -192,8 +192,6 @@ impl frame_system::Config for Runtime { type DbWeight = RocksDbWeight; /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = weights::frame_system::WeightInfo; - /// Weight information for the extensions of this pallet. - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; /// Block & extrinsics weights: base values and limits. type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). @@ -253,7 +251,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs deleted file mode 100644 index 0683158a01a..00000000000 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/ -// --chain=coretime-westend-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_637_000 picoseconds. - Weight::from_parts(6_382_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_841_000 picoseconds. - Weight::from_parts(8_776_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 561_000 picoseconds. - Weight::from_parts(2_705_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_316_000 picoseconds. - Weight::from_parts(5_771_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 511_000 picoseconds. - Weight::from_parts(2_575_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 501_000 picoseconds. - Weight::from_parts(2_595_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_687_000 picoseconds. - Weight::from_parts(6_192_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs index 7b6ab611e6f..f1050b3ae63 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/mod.rs @@ -22,7 +22,6 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_broker; pub mod pallet_collator_selection; @@ -30,7 +29,6 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index f159f877afe..00000000000 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/ -// --chain=coretime-westend-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 33_363_000 picoseconds. - Weight::from_parts(38_793_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index 199057c3764..232a82115a8 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -289,8 +289,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( pallet_sudo::CheckOnlySudoAccount, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, @@ -301,7 +301,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -316,7 +316,6 @@ mod benches { frame_benchmarking::define_benchmarks!( [cumulus_pallet_parachain_system, ParachainSystem] [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_glutton, Glutton] [pallet_message_queue, MessageQueue] [pallet_timestamp, Timestamp] @@ -440,7 +439,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -457,7 +455,6 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs deleted file mode 100644 index e6efa762308..00000000000 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,119 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("glutton-westend-dev-1300")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/glutton/glutton-westend/src/weights/ -// --chain=glutton-westend-dev-1300 - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_908_000 picoseconds. - Weight::from_parts(4_007_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_510_000 picoseconds. - Weight::from_parts(6_332_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 651_000 picoseconds. - Weight::from_parts(851_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_387_000 picoseconds. - Weight::from_parts(3_646_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 491_000 picoseconds. - Weight::from_parts(651_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 451_000 picoseconds. - Weight::from_parts(662_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1489` - // Minimum execution time: 3_537_000 picoseconds. - Weight::from_parts(4_208_000, 0) - .saturating_add(Weight::from_parts(0, 1489)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml index c9781639c3e..c0b8fb7636b 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml @@ -152,7 +152,6 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index c5e420785de..2b8cc32f67c 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -83,8 +83,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The TransactionExtension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -97,7 +97,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -178,7 +178,6 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = ConstU32<16>; @@ -233,7 +232,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -455,7 +453,6 @@ mod benches { [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] - [pallet_transaction_payment, TransactionPayment] // Polkadot [polkadot_runtime_common::identity_migrator, IdentityMigrator] // Cumulus diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs deleted file mode 100644 index 1ba2010991f..00000000000 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights/ -// --chain=people-rococo-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_637_000 picoseconds. - Weight::from_parts(6_382_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_841_000 picoseconds. - Weight::from_parts(8_776_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 561_000 picoseconds. - Weight::from_parts(2_705_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_316_000 picoseconds. - Weight::from_parts(5_771_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 511_000 picoseconds. - Weight::from_parts(2_575_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 501_000 picoseconds. - Weight::from_parts(2_595_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_687_000 picoseconds. - Weight::from_parts(6_192_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs index c4cea99ee5a..3396a8caea0 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/mod.rs @@ -20,7 +20,6 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_collator_selection; pub mod pallet_identity; @@ -28,7 +27,6 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 555fd5a32fa..00000000000 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights/ -// --chain=people-rococo-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 33_363_000 picoseconds. - Weight::from_parts(38_793_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml index 8d8421332c1..e87e825a34e 100644 --- a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml @@ -152,7 +152,6 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index dea079a4a98..2dc2d06a66b 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -83,8 +83,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The transactionExtension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -97,7 +97,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Migrations to apply on runtime upgrade. pub type Migrations = ( @@ -178,7 +178,6 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = ConstU32<16>; @@ -233,7 +232,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs deleted file mode 100644 index 7130a62ab6a..00000000000 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,121 +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 . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights/ -// --chain=people-westend-dev - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_637_000 picoseconds. - Weight::from_parts(6_382_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_841_000 picoseconds. - Weight::from_parts(8_776_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 561_000 picoseconds. - Weight::from_parts(2_705_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_316_000 picoseconds. - Weight::from_parts(5_771_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 511_000 picoseconds. - Weight::from_parts(2_575_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 501_000 picoseconds. - Weight::from_parts(2_595_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::BlockWeight` (r:1 w:1) - /// Proof: `System::BlockWeight` (`max_values`: Some(1), `max_size`: Some(48), added: 543, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1533` - // Minimum execution time: 3_687_000 picoseconds. - Weight::from_parts(6_192_000, 0) - .saturating_add(Weight::from_parts(0, 1533)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs index c4cea99ee5a..3396a8caea0 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/mod.rs @@ -20,7 +20,6 @@ pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_balances; pub mod pallet_collator_selection; pub mod pallet_identity; @@ -28,7 +27,6 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_session; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_transaction_payment.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 30e4524e586..00000000000 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,67 +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 . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot-parachain -// benchmark -// pallet -// --wasm-execution=compiled -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --steps=2 -// --repeat=2 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights/ -// --chain=people-westend-dev - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `3593` - // Minimum execution time: 33_363_000 picoseconds. - Weight::from_parts(38_793_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs index 023c9978302..4cc0a81ef49 100644 --- a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs @@ -258,8 +258,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, @@ -269,7 +269,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< diff --git a/cumulus/parachains/runtimes/starters/shell/src/lib.rs b/cumulus/parachains/runtimes/starters/shell/src/lib.rs index fedac36e48d..829754731a4 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/lib.rs @@ -34,19 +34,15 @@ pub mod xcm_config; use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use cumulus_primitives_core::AggregateMessageOrigin; +use frame_support::unsigned::TransactionValidityError; use scale_info::TypeInfo; use sp_api::impl_runtime_apis; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, OriginOf, - TransactionExtension, TransactionExtensionBase, ValidateResult, - }, - transaction_validity::{ - InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, - }, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf}, + transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, }; use sp_std::prelude::*; @@ -279,37 +275,35 @@ construct_runtime! { /// Simple implementation which fails any transaction which is signed. #[derive(Eq, PartialEq, Clone, Default, sp_core::RuntimeDebug, Encode, Decode, TypeInfo)] pub struct DisallowSigned; - -impl TransactionExtensionBase for DisallowSigned { +impl sp_runtime::traits::SignedExtension for DisallowSigned { const IDENTIFIER: &'static str = "DisallowSigned"; - type Implicit = (); -} - -impl TransactionExtension for DisallowSigned { - type Val = (); + type AccountId = AccountId; + type Call = RuntimeCall; + type AdditionalSigned = (); type Pre = (); - fn validate( + fn additional_signed( &self, - _origin: OriginOf, - _call: &RuntimeCall, - _info: &DispatchInfoOf, - _len: usize, - _context: &mut C, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult { - Err(InvalidTransaction::BadProof.into()) + ) -> sp_std::result::Result<(), sp_runtime::transaction_validity::TransactionValidityError> { + Ok(()) } - fn prepare( + fn pre_dispatch( self, - _val: Self::Val, - _origin: &OriginOf, - _call: &RuntimeCall, - _info: &DispatchInfoOf, - _len: usize, - _context: &C, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, ) -> Result { - Err(InvalidTransaction::BadProof.into()) + self.validate(who, call, info, len).map(|_| ()) + } + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + let i = sp_runtime::transaction_validity::InvalidTransaction::BadProof; + Err(sp_runtime::transaction_validity::TransactionValidityError::Invalid(i)) } } @@ -329,11 +323,11 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = DisallowSigned; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = DisallowSigned; /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, diff --git a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml index 5a8b15740e4..7f3e898d923 100644 --- a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml @@ -156,7 +156,6 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 62065619e42..0030287edb3 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -114,8 +114,8 @@ pub type BlockId = generic::BlockId; // Id used for identifying assets. pub type AssetId = u32; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -128,7 +128,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; pub type Migrations = ( pallet_balances::migration::MigrateToTrackInactive, @@ -419,7 +419,6 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; - type WeightInfo = (); } parameter_types! { @@ -609,19 +608,6 @@ impl pallet_collator_selection::Config for Runtime { type WeightInfo = (); } -#[cfg(feature = "runtime-benchmarks")] -pub struct AssetTxHelper; - -#[cfg(feature = "runtime-benchmarks")] -impl pallet_asset_tx_payment::BenchmarkHelperTrait for AssetTxHelper { - fn create_asset_id_parameter(_id: u32) -> (u32, u32) { - unimplemented!("Penpal uses default weights"); - } - fn setup_balances_and_pool(_asset_id: u32, _account: AccountId) { - unimplemented!("Penpal uses default weights"); - } -} - impl pallet_asset_tx_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = Assets; @@ -634,9 +620,6 @@ impl pallet_asset_tx_payment::Config for Runtime { >, AssetsToBlockAuthor, >; - type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = AssetTxHelper; } impl pallet_sudo::Config for Runtime { @@ -685,7 +668,6 @@ construct_runtime!( mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_session, SessionBench::] @@ -869,7 +851,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; let mut list = Vec::::new(); @@ -886,7 +867,6 @@ impl_runtime_apis! { use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime {} use cumulus_pallet_session_benchmarking::Pallet as SessionBench; diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml index 2023d9abf5d..42169e8949f 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml @@ -126,7 +126,6 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 469f06a1aa6..2b21a12c3ca 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -267,7 +267,6 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; - type WeightInfo = (); } impl pallet_sudo::Config for Runtime { @@ -645,8 +644,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -658,7 +657,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index a92e8a4c12a..84a232e954f 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -136,7 +136,6 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "glutton-westend-runtime/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "parachains-common/runtime-benchmarks", "penpal-runtime/runtime-benchmarks", "people-rococo-runtime/runtime-benchmarks", diff --git a/cumulus/primitives/storage-weight-reclaim/Cargo.toml b/cumulus/primitives/storage-weight-reclaim/Cargo.toml index 9e8f60783d4..4835fb5192b 100644 --- a/cumulus/primitives/storage-weight-reclaim/Cargo.toml +++ b/cumulus/primitives/storage-weight-reclaim/Cargo.toml @@ -14,12 +14,9 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-support = { path = "../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../substrate/frame/system", default-features = false } -sp-core = { path = "../../../substrate/primitives/core", default-features = false } -sp-io = { path = "../../../substrate/primitives/io", default-features = false } sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } sp-std = { path = "../../../substrate/primitives/std", default-features = false } @@ -29,27 +26,19 @@ docify = "0.2.7" [dev-dependencies] sp-trie = { path = "../../../substrate/primitives/trie", default-features = false } +sp-io = { path = "../../../substrate/primitives/io", default-features = false } cumulus-test-runtime = { path = "../../test/runtime" } [features] default = ["std"] -runtime-benchmarks = [ - "cumulus-primitives-core/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] std = [ "codec/std", "cumulus-primitives-core/std", "cumulus-primitives-proof-size-hostfunction/std", - "frame-benchmarking/std", "frame-support/std", "frame-system/std", "log/std", "scale-info/std", - "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", diff --git a/cumulus/primitives/storage-weight-reclaim/src/benchmarking.rs b/cumulus/primitives/storage-weight-reclaim/src/benchmarking.rs deleted file mode 100644 index 2980d08271a..00000000000 --- a/cumulus/primitives/storage-weight-reclaim/src/benchmarking.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -//! Benchmarking setup for cumulus-primitives-storage-weight-reclaim - -#![cfg(feature = "runtime-benchmarks")] - -use super::*; - -use frame_benchmarking::{account, v2::*, BenchmarkError}; -use frame_support::pallet_prelude::DispatchClass; -use frame_system::{BlockWeight, RawOrigin}; -use sp_runtime::traits::{DispatchTransaction, Get}; -use sp_std::{ - marker::{Send, Sync}, - prelude::*, -}; - -/// Pallet we're benchmarking here. -pub struct Pallet(frame_system::Pallet); - -#[benchmarks(where - T: Send + Sync, - T::RuntimeCall: Dispatchable -)] -mod benchmarks { - use super::*; - - #[benchmark] - fn storage_weight_reclaim() -> Result<(), BenchmarkError> { - let caller = account("caller", 0, 0); - BlockWeight::::mutate(|current_weight| { - current_weight.set(Weight::from_parts(0, 1000), DispatchClass::Normal); - }); - let base_extrinsic = ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(0, 200)), - pays_fee: Default::default(), - }; - let len = 0_usize; - let ext = StorageWeightReclaim::::new(); - - #[block] - { - ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(post_info)) - .unwrap() - .unwrap(); - } - - assert_eq!(BlockWeight::::get().total().proof_size(), 700 + base_extrinsic.proof_size()); - - Ok(()) - } -} diff --git a/cumulus/primitives/storage-weight-reclaim/src/lib.rs b/cumulus/primitives/storage-weight-reclaim/src/lib.rs index 4bb40176b78..5dddc92e395 100644 --- a/cumulus/primitives/storage-weight-reclaim/src/lib.rs +++ b/cumulus/primitives/storage-weight-reclaim/src/lib.rs @@ -29,22 +29,12 @@ use frame_support::{ use frame_system::Config; use scale_info::TypeInfo; use sp_runtime::{ - impl_tx_ext_default, - traits::{ - DispatchInfoOf, Dispatchable, PostDispatchInfoOf, TransactionExtension, - TransactionExtensionBase, - }, + traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, transaction_validity::TransactionValidityError, DispatchResult, }; use sp_std::marker::PhantomData; -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - const LOG_TARGET: &'static str = "runtime::storage_reclaim"; /// `StorageWeightReclaimer` is a mechanism for manually reclaiming storage weight. @@ -53,7 +43,7 @@ const LOG_TARGET: &'static str = "runtime::storage_reclaim"; /// reclaim it computes the real consumed storage weight and refunds excess weight. /// /// # Example -#[doc = docify::embed!("src/tests.rs", simple_reclaimer_example)] +#[doc = docify::embed!("src/lib.rs", simple_reclaimer_example)] pub struct StorageWeightReclaimer { previous_remaining_proof_size: u64, previous_reported_proof_size: Option, @@ -129,40 +119,42 @@ impl core::fmt::Debug for StorageWeightReclaim { } } -impl TransactionExtensionBase for StorageWeightReclaim { - const IDENTIFIER: &'static str = "StorageWeightReclaim"; - type Implicit = (); -} - -impl TransactionExtension - for StorageWeightReclaim +impl SignedExtension for StorageWeightReclaim where T::RuntimeCall: Dispatchable, { - type Val = (); + const IDENTIFIER: &'static str = "StorageWeightReclaim"; + + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = (); type Pre = Option; - fn prepare( + fn additional_signed( + &self, + ) -> Result + { + Ok(()) + } + + fn pre_dispatch( self, - _val: Self::Val, - _origin: &T::RuntimeOrigin, - _call: &T::RuntimeCall, - _info: &DispatchInfoOf, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, _len: usize, - _context: &Context, - ) -> Result { + ) -> Result { Ok(get_proof_size()) } fn post_dispatch( - pre: Self::Pre, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, _len: usize, _result: &DispatchResult, - _context: &Context, ) -> Result<(), TransactionValidityError> { - let Some(pre_dispatch_proof_size) = pre else { + let Some(Some(pre_dispatch_proof_size)) = pre else { return Ok(()); }; @@ -202,6 +194,470 @@ where }); Ok(()) } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::{ + assert_ok, + dispatch::DispatchClass, + weights::{Weight, WeightMeter}, + }; + use frame_system::{BlockWeight, CheckWeight}; + use sp_runtime::{AccountId32, BuildStorage}; + use sp_std::marker::PhantomData; + use sp_trie::proof_size_extension::ProofSizeExt; + + type Test = cumulus_test_runtime::Runtime; + const CALL: &::RuntimeCall = + &cumulus_test_runtime::RuntimeCall::System(frame_system::Call::set_heap_pages { + pages: 0u64, + }); + const ALICE: AccountId32 = AccountId32::new([1u8; 32]); + const LEN: usize = 0; + + pub fn new_test_ext() -> sp_io::TestExternalities { + let ext: sp_io::TestExternalities = cumulus_test_runtime::RuntimeGenesisConfig::default() + .build_storage() + .unwrap() + .into(); + ext + } + + struct TestRecorder { + return_values: Box<[usize]>, + counter: std::sync::atomic::AtomicUsize, + } + + impl TestRecorder { + fn new(values: &[usize]) -> Self { + TestRecorder { return_values: values.into(), counter: Default::default() } + } + } + + impl sp_trie::ProofSizeProvider for TestRecorder { + fn estimate_encoded_size(&self) -> usize { + let counter = self.counter.fetch_add(1, core::sync::atomic::Ordering::Relaxed); + self.return_values[counter] + } + } + + fn setup_test_externalities(proof_values: &[usize]) -> sp_io::TestExternalities { + let mut test_ext = new_test_ext(); + let test_recorder = TestRecorder::new(proof_values); + test_ext.register_extension(ProofSizeExt::new(test_recorder)); + test_ext + } + + fn set_current_storage_weight(new_weight: u64) { + BlockWeight::::mutate(|current_weight| { + current_weight.set(Weight::from_parts(0, new_weight), DispatchClass::Normal); + }); + } + + #[test] + fn basic_refund() { + // The real cost will be 100 bytes of storage size + let mut test_ext = setup_test_externalities(&[0, 100]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 500 + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(0)); + + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + // We expect a refund of 400 + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 600); + }) + } + + #[test] + fn does_nothing_without_extension() { + let mut test_ext = new_test_ext(); + + // Proof size extension not registered + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 500 + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, None); + + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1000); + }) + } + + #[test] + fn negative_refund_is_added_to_weight() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 100 + let info = DispatchInfo { weight: Weight::from_parts(0, 100), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // We expect no refund + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1100); + }) + } + + #[test] + fn test_zero_proof_size() { + let mut test_ext = setup_test_externalities(&[0, 0]); + + test_ext.execute_with(|| { + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(0)); + + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 0); + }); + } + + #[test] + fn test_larger_pre_dispatch_proof_size() { + let mut test_ext = setup_test_externalities(&[300, 100]); + + test_ext.execute_with(|| { + set_current_storage_weight(1300); + + let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; + let post_info = PostDispatchInfo::default(); + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(300)); + + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 800); + }); + } + + #[test] + fn test_incorporates_check_weight_unspent_weight() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 300 + let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; + + // Actual weight is 50 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 250)), + pays_fee: Default::default(), + }; + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 900); + }) + } + + #[test] + fn test_incorporates_check_weight_unspent_weight_on_negative() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 50 + let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; + + // Actual weight is 25 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 25)), + pays_fee: Default::default(), + }; + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1150); + }) + } + + #[test] + fn test_incorporates_check_weight_unspent_weight_reverse_order() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + + // Benchmarked storage weight: 300 + let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; + + // Actual weight is 50 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 250)), + pays_fee: Default::default(), + }; + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + // `CheckWeight` gets called after `StorageWeightReclaim` this time. + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + + assert_eq!(BlockWeight::::get().total().proof_size(), 900); + }) + } + + #[test] + fn test_incorporates_check_weight_unspent_weight_on_negative_reverse_order() { + let mut test_ext = setup_test_externalities(&[100, 300]); + + test_ext.execute_with(|| { + set_current_storage_weight(1000); + // Benchmarked storage weight: 50 + let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; - impl_tx_ext_default!(T::RuntimeCall; Context; validate); + // Actual weight is 25 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 25)), + pays_fee: Default::default(), + }; + + let pre = StorageWeightReclaim::(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + assert_eq!(pre, Some(100)); + + assert_ok!(StorageWeightReclaim::::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + // `CheckWeight` gets called after `StorageWeightReclaim` this time. + // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + + assert_eq!(BlockWeight::::get().total().proof_size(), 1150); + }) + } + + #[test] + fn storage_size_reported_correctly() { + let mut test_ext = setup_test_externalities(&[1000]); + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), Some(1000)); + }); + + let mut test_ext = new_test_ext(); + + let test_recorder = TestRecorder::new(&[0]); + + test_ext.register_extension(ProofSizeExt::new(test_recorder)); + + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), Some(0)); + }); + } + + #[test] + fn storage_size_disabled_reported_correctly() { + let mut test_ext = setup_test_externalities(&[PROOF_RECORDING_DISABLED as usize]); + + test_ext.execute_with(|| { + assert_eq!(get_proof_size(), None); + }); + } + + #[test] + fn test_reclaim_helper() { + let mut test_ext = setup_test_externalities(&[1000, 1300, 1800]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 2000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + remaining_weight_meter.consume(Weight::from_parts(0, 500)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 200))); + + remaining_weight_meter.consume(Weight::from_parts(0, 800)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + assert_eq!(reclaimed, Some(Weight::from_parts(0, 300))); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1200)); + }); + } + + #[test] + fn test_reclaim_helper_does_not_reclaim_negative() { + // Benchmarked weight does not change at all + let mut test_ext = setup_test_externalities(&[1000, 1300]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1000)); + }); + + // Benchmarked weight increases less than storage proof consumes + let mut test_ext = setup_test_externalities(&[1000, 1300]); + + test_ext.execute_with(|| { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + remaining_weight_meter.consume(Weight::from_parts(0, 0)); + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); + }); + } + + /// Just here for doc purposes + fn get_benched_weight() -> Weight { + Weight::from_parts(0, 5) + } + + /// Just here for doc purposes + fn do_work() {} + + #[docify::export_content(simple_reclaimer_example)] + fn reclaim_with_weight_meter() { + let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(10, 10)); + + let benched_weight = get_benched_weight(); + + // It is important to instantiate the `StorageWeightReclaimer` before we consume the weight + // for a piece of work from the weight meter. + let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); + + if remaining_weight_meter.try_consume(benched_weight).is_ok() { + // Perform some work that takes has `benched_weight` storage weight. + do_work(); + + // Reclaimer will detect that we only consumed 2 bytes, so 3 bytes are reclaimed. + let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); + + // We reclaimed 3 bytes of storage size! + assert_eq!(reclaimed, Some(Weight::from_parts(0, 3))); + assert_eq!(BlockWeight::::get().total().proof_size(), 10); + assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(10, 8)); + } + } + + #[test] + fn test_reclaim_helper_works_with_meter() { + // The node will report 12 - 10 = 2 consumed storage size between the calls. + let mut test_ext = setup_test_externalities(&[10, 12]); + + test_ext.execute_with(|| { + // Initial storage size is 10. + set_current_storage_weight(10); + reclaim_with_weight_meter(); + }); + } } diff --git a/cumulus/primitives/storage-weight-reclaim/src/tests.rs b/cumulus/primitives/storage-weight-reclaim/src/tests.rs deleted file mode 100644 index 631827cf442..00000000000 --- a/cumulus/primitives/storage-weight-reclaim/src/tests.rs +++ /dev/null @@ -1,484 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -use super::*; -use frame_support::{ - assert_ok, - dispatch::DispatchClass, - weights::{Weight, WeightMeter}, -}; -use frame_system::{BlockWeight, CheckWeight}; -use sp_runtime::{traits::DispatchTransaction, AccountId32, BuildStorage}; -use sp_std::marker::PhantomData; -use sp_trie::proof_size_extension::ProofSizeExt; - -type Test = cumulus_test_runtime::Runtime; -const CALL: &::RuntimeCall = - &cumulus_test_runtime::RuntimeCall::System(frame_system::Call::set_heap_pages { pages: 0u64 }); -const ALICE: AccountId32 = AccountId32::new([1u8; 32]); -const LEN: usize = 0; - -fn new_test_ext() -> sp_io::TestExternalities { - let ext: sp_io::TestExternalities = cumulus_test_runtime::RuntimeGenesisConfig::default() - .build_storage() - .unwrap() - .into(); - ext -} - -struct TestRecorder { - return_values: Box<[usize]>, - counter: std::sync::atomic::AtomicUsize, -} - -impl TestRecorder { - fn new(values: &[usize]) -> Self { - TestRecorder { return_values: values.into(), counter: Default::default() } - } -} - -impl sp_trie::ProofSizeProvider for TestRecorder { - fn estimate_encoded_size(&self) -> usize { - let counter = self.counter.fetch_add(1, core::sync::atomic::Ordering::Relaxed); - self.return_values[counter] - } -} - -fn setup_test_externalities(proof_values: &[usize]) -> sp_io::TestExternalities { - let mut test_ext = new_test_ext(); - let test_recorder = TestRecorder::new(proof_values); - test_ext.register_extension(ProofSizeExt::new(test_recorder)); - test_ext -} - -fn set_current_storage_weight(new_weight: u64) { - BlockWeight::::mutate(|current_weight| { - current_weight.set(Weight::from_parts(0, new_weight), DispatchClass::Normal); - }); -} - -#[test] -fn basic_refund() { - // The real cost will be 100 bytes of storage size - let mut test_ext = setup_test_externalities(&[0, 100]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - - // Benchmarked storage weight: 500 - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(0)); - - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - // We expect a refund of 400 - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 600); - }) -} - -#[test] -fn does_nothing_without_extension() { - let mut test_ext = new_test_ext(); - - // Proof size extension not registered - test_ext.execute_with(|| { - set_current_storage_weight(1000); - - // Benchmarked storage weight: 500 - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, None); - - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 1000); - }) -} - -#[test] -fn negative_refund_is_added_to_weight() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - // Benchmarked storage weight: 100 - let info = DispatchInfo { weight: Weight::from_parts(0, 100), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - // We expect no refund - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 1100); - }) -} - -#[test] -fn test_zero_proof_size() { - let mut test_ext = setup_test_externalities(&[0, 0]); - - test_ext.execute_with(|| { - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(0)); - - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 0); - }); -} - -#[test] -fn test_larger_pre_dispatch_proof_size() { - let mut test_ext = setup_test_externalities(&[300, 100]); - - test_ext.execute_with(|| { - set_current_storage_weight(1300); - - let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; - let post_info = PostDispatchInfo::default(); - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(300)); - - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 800); - }); -} - -#[test] -fn test_incorporates_check_weight_unspent_weight() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - - // Benchmarked storage weight: 300 - let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; - - // Actual weight is 50 - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(50, 250)), - pays_fee: Default::default(), - }; - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` - // we always need to call `post_dispatch` to verify that they interoperate correctly. - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 900); - }) -} - -#[test] -fn test_incorporates_check_weight_unspent_weight_on_negative() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - // Benchmarked storage weight: 50 - let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; - - // Actual weight is 25 - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(50, 25)), - pays_fee: Default::default(), - }; - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` - // we always need to call `post_dispatch` to verify that they interoperate correctly. - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - - assert_eq!(BlockWeight::::get().total().proof_size(), 1150); - }) -} - -#[test] -fn test_incorporates_check_weight_unspent_weight_reverse_order() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - - // Benchmarked storage weight: 300 - let info = DispatchInfo { weight: Weight::from_parts(100, 300), ..Default::default() }; - - // Actual weight is 50 - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(50, 250)), - pays_fee: Default::default(), - }; - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - // `CheckWeight` gets called after `StorageWeightReclaim` this time. - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` - // we always need to call `post_dispatch` to verify that they interoperate correctly. - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - - assert_eq!(BlockWeight::::get().total().proof_size(), 900); - }) -} - -#[test] -fn test_incorporates_check_weight_unspent_weight_on_negative_reverse_order() { - let mut test_ext = setup_test_externalities(&[100, 300]); - - test_ext.execute_with(|| { - set_current_storage_weight(1000); - // Benchmarked storage weight: 50 - let info = DispatchInfo { weight: Weight::from_parts(100, 50), ..Default::default() }; - - // Actual weight is 25 - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(50, 25)), - pays_fee: Default::default(), - }; - - let (pre, _) = StorageWeightReclaim::(PhantomData) - .validate_and_prepare(Some(ALICE.clone()).into(), CALL, &info, LEN) - .unwrap(); - assert_eq!(pre, Some(100)); - - assert_ok!(StorageWeightReclaim::::post_dispatch( - pre, - &info, - &post_info, - LEN, - &Ok(()), - &() - )); - // `CheckWeight` gets called after `StorageWeightReclaim` this time. - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` - // we always need to call `post_dispatch` to verify that they interoperate correctly. - assert_ok!(CheckWeight::::post_dispatch((), &info, &post_info, 0, &Ok(()), &())); - - assert_eq!(BlockWeight::::get().total().proof_size(), 1150); - }) -} - -#[test] -fn storage_size_reported_correctly() { - let mut test_ext = setup_test_externalities(&[1000]); - test_ext.execute_with(|| { - assert_eq!(get_proof_size(), Some(1000)); - }); - - let mut test_ext = new_test_ext(); - - let test_recorder = TestRecorder::new(&[0]); - - test_ext.register_extension(ProofSizeExt::new(test_recorder)); - - test_ext.execute_with(|| { - assert_eq!(get_proof_size(), Some(0)); - }); -} - -#[test] -fn storage_size_disabled_reported_correctly() { - let mut test_ext = setup_test_externalities(&[PROOF_RECORDING_DISABLED as usize]); - - test_ext.execute_with(|| { - assert_eq!(get_proof_size(), None); - }); -} - -#[test] -fn test_reclaim_helper() { - let mut test_ext = setup_test_externalities(&[1000, 1300, 1800]); - - test_ext.execute_with(|| { - let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 2000)); - let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); - remaining_weight_meter.consume(Weight::from_parts(0, 500)); - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - - assert_eq!(reclaimed, Some(Weight::from_parts(0, 200))); - - remaining_weight_meter.consume(Weight::from_parts(0, 800)); - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - assert_eq!(reclaimed, Some(Weight::from_parts(0, 300))); - assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1200)); - }); -} - -#[test] -fn test_reclaim_helper_does_not_reclaim_negative() { - // Benchmarked weight does not change at all - let mut test_ext = setup_test_externalities(&[1000, 1300]); - - test_ext.execute_with(|| { - let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); - let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - - assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); - assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(0, 1000)); - }); - - // Benchmarked weight increases less than storage proof consumes - let mut test_ext = setup_test_externalities(&[1000, 1300]); - - test_ext.execute_with(|| { - let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(0, 1000)); - let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); - remaining_weight_meter.consume(Weight::from_parts(0, 0)); - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - - assert_eq!(reclaimed, Some(Weight::from_parts(0, 0))); - }); -} - -/// Just here for doc purposes -fn get_benched_weight() -> Weight { - Weight::from_parts(0, 5) -} - -/// Just here for doc purposes -fn do_work() {} - -#[docify::export_content(simple_reclaimer_example)] -fn reclaim_with_weight_meter() { - let mut remaining_weight_meter = WeightMeter::with_limit(Weight::from_parts(10, 10)); - - let benched_weight = get_benched_weight(); - - // It is important to instantiate the `StorageWeightReclaimer` before we consume the weight - // for a piece of work from the weight meter. - let mut reclaim_helper = StorageWeightReclaimer::new(&remaining_weight_meter); - - if remaining_weight_meter.try_consume(benched_weight).is_ok() { - // Perform some work that takes has `benched_weight` storage weight. - do_work(); - - // Reclaimer will detect that we only consumed 2 bytes, so 3 bytes are reclaimed. - let reclaimed = reclaim_helper.reclaim_with_meter(&mut remaining_weight_meter); - - // We reclaimed 3 bytes of storage size! - assert_eq!(reclaimed, Some(Weight::from_parts(0, 3))); - assert_eq!(BlockWeight::::get().total().proof_size(), 10); - assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(10, 8)); - } -} - -#[test] -fn test_reclaim_helper_works_with_meter() { - // The node will report 12 - 10 = 2 consumed storage size between the calls. - let mut test_ext = setup_test_externalities(&[10, 12]); - - test_ext.execute_with(|| { - // Initial storage size is 10. - set_current_storage_weight(10); - reclaim_with_weight_meter(); - }); -} diff --git a/cumulus/test/client/Cargo.toml b/cumulus/test/client/Cargo.toml index 9dfa6ecb351..028733ce235 100644 --- a/cumulus/test/client/Cargo.toml +++ b/cumulus/test/client/Cargo.toml @@ -46,11 +46,9 @@ cumulus-primitives-storage-weight-reclaim = { path = "../../primitives/storage-w [features] runtime-benchmarks = [ "cumulus-primitives-core/runtime-benchmarks", - "cumulus-primitives-storage-weight-reclaim/runtime-benchmarks", "cumulus-test-service/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", "sc-service/runtime-benchmarks", diff --git a/cumulus/test/client/src/lib.rs b/cumulus/test/client/src/lib.rs index 9239ff0f23e..c46f4da7f67 100644 --- a/cumulus/test/client/src/lib.rs +++ b/cumulus/test/client/src/lib.rs @@ -19,7 +19,7 @@ mod block_builder; use codec::{Decode, Encode}; use runtime::{ - Balance, Block, BlockHashCount, Runtime, RuntimeCall, Signature, SignedPayload, TxExtension, + Balance, Block, BlockHashCount, Runtime, RuntimeCall, Signature, SignedExtra, SignedPayload, UncheckedExtrinsic, VERSION, }; use sc_executor::HeapAllocStrategy; @@ -125,7 +125,7 @@ impl DefaultTestClientBuilderExt for TestClientBuilder { /// Create an unsigned extrinsic from a runtime call. pub fn generate_unsigned(function: impl Into) -> UncheckedExtrinsic { - UncheckedExtrinsic::new_bare(function.into()) + UncheckedExtrinsic::new_unsigned(function.into()) } /// Create a signed extrinsic from a runtime call and sign @@ -143,7 +143,7 @@ pub fn generate_extrinsic_with_pair( let period = BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; let tip = 0; - let tx_ext: TxExtension = ( + let extra: SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckGenesis::::new(), @@ -152,14 +152,13 @@ pub fn generate_extrinsic_with_pair( frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::::new(), - ) - .into(); + ); let function = function.into(); let raw_payload = SignedPayload::from_raw( function.clone(), - tx_ext.clone(), + extra.clone(), ((), VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|e| origin.sign(e)); @@ -168,7 +167,7 @@ pub fn generate_extrinsic_with_pair( function, origin.public().into(), Signature::Sr25519(signature), - tx_ext, + extra, ) } diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index 154948a24b4..5ccec8983e9 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -246,7 +246,6 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; - type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } impl pallet_sudo::Config for Runtime { @@ -323,8 +322,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckGenesis, @@ -336,7 +335,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -347,7 +346,7 @@ pub type Executive = frame_executive::Executive< TestOnRuntimeUpgrade, >; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; pub struct TestOnRuntimeUpgrade; diff --git a/cumulus/test/service/Cargo.toml b/cumulus/test/service/Cargo.toml index 39e8aeba433..27273f4e0a8 100644 --- a/cumulus/test/service/Cargo.toml +++ b/cumulus/test/service/Cargo.toml @@ -104,12 +104,10 @@ substrate-test-utils = { path = "../../../substrate/test-utils" } runtime-benchmarks = [ "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-primitives-core/runtime-benchmarks", - "cumulus-primitives-storage-weight-reclaim/runtime-benchmarks", "cumulus-test-client/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-cli/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", diff --git a/cumulus/test/service/src/bench_utils.rs b/cumulus/test/service/src/bench_utils.rs index 15128b23787..4ace894b392 100644 --- a/cumulus/test/service/src/bench_utils.rs +++ b/cumulus/test/service/src/bench_utils.rs @@ -69,7 +69,7 @@ pub fn extrinsic_set_time(client: &TestClient) -> OpaqueExtrinsic { let timestamp = best_number as u64 * cumulus_test_runtime::MinimumPeriod::get(); cumulus_test_runtime::UncheckedExtrinsic { - preamble: sp_runtime::generic::Preamble::Bare, + signature: None, function: cumulus_test_runtime::RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: timestamp, }), @@ -102,7 +102,7 @@ pub fn extrinsic_set_validation_data( }; cumulus_test_runtime::UncheckedExtrinsic { - preamble: sp_runtime::generic::Preamble::Bare, + signature: None, function: cumulus_test_runtime::RuntimeCall::ParachainSystem( cumulus_pallet_parachain_system::Call::set_validation_data { data }, ), diff --git a/cumulus/test/service/src/lib.rs b/cumulus/test/service/src/lib.rs index f05dc5f180f..3554a383f21 100644 --- a/cumulus/test/service/src/lib.rs +++ b/cumulus/test/service/src/lib.rs @@ -883,7 +883,7 @@ pub fn construct_extrinsic( .map(|c| c / 2) .unwrap_or(2) as u64; let tip = 0; - let tx_ext: runtime::TxExtension = ( + let extra: runtime::SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckGenesis::::new(), @@ -895,11 +895,10 @@ pub fn construct_extrinsic( frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim::::new(), - ) - .into(); + ); let raw_payload = runtime::SignedPayload::from_raw( function.clone(), - tx_ext.clone(), + extra.clone(), ((), runtime::VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|e| caller.sign(e)); @@ -907,7 +906,7 @@ pub fn construct_extrinsic( function, caller.public().into(), runtime::Signature::Sr25519(signature), - tx_ext, + extra, ) } diff --git a/docs/sdk/src/reference_docs/extrinsic_encoding.rs b/docs/sdk/src/reference_docs/extrinsic_encoding.rs index be1af500038..8c8568a228f 100644 --- a/docs/sdk/src/reference_docs/extrinsic_encoding.rs +++ b/docs/sdk/src/reference_docs/extrinsic_encoding.rs @@ -56,7 +56,7 @@ //! version_and_signed, //! from_address, //! signature, -//! transaction_extensions_extra, +//! signed_extensions_extra, //! ) //! ``` //! @@ -90,31 +90,31 @@ //! The signature type used on the Polkadot relay chain is [`sp_runtime::MultiSignature`]; the //! variants there are the types of signature that can be provided. //! -//! ### transaction_extensions_extra +//! ### signed_extensions_extra //! //! This is the concatenation of the [SCALE encoded][frame::deps::codec] bytes representing each of -//! the [_transaction extensions_][sp_runtime::traits::TransactionExtension], and are configured by -//! the fourth generic parameter of [`sp_runtime::generic::UncheckedExtrinsic`]. Learn more about -//! transaction extensions [here][crate::reference_docs::transaction_extensions]. +//! the [_signed extensions_][sp_runtime::traits::SignedExtension], and are configured by the +//! fourth generic parameter of [`sp_runtime::generic::UncheckedExtrinsic`]. Learn more about +//! signed extensions [here][crate::reference_docs::signed_extensions]. //! -//! When it comes to constructing an extrinsic, each transaction extension has two things that we -//! are interested in here: +//! When it comes to constructing an extrinsic, each signed extension has two things that we are +//! interested in here: //! -//! - The actual SCALE encoding of the transaction extension type itself; this is what will form our -//! `transaction_extensions_extra` bytes. -//! - An `Implicit` type. This is SCALE encoded into the `transaction_extensions_implicit` data of -//! the _signed payload_ (see below). +//! - The actual SCALE encoding of the signed extension type itself; this is what will form our +//! `signed_extensions_extra` bytes. +//! - An `AdditionalSigned` type. This is SCALE encoded into the `signed_extensions_additional` data +//! of the _signed payload_ (see below). //! //! Either (or both) of these can encode to zero bytes. //! -//! Each chain configures the set of transaction extensions that it uses in its runtime -//! configuration. At the time of writing, Polkadot configures them +//! Each chain configures the set of signed extensions that it uses in its runtime configuration. +//! At the time of writing, Polkadot configures them //! [here](https://github.com/polkadot-fellows/runtimes/blob/1dc04eb954eadf8aadb5d83990b89662dbb5a074/relay/polkadot/src/lib.rs#L1432C25-L1432C25). -//! Some of the common transaction extensions are defined -//! [here][frame::deps::frame_system#transaction-extensions]. +//! Some of the common signed extensions are defined +//! [here][frame::deps::frame_system#signed-extensions]. //! -//! Information about exactly which transaction extensions are present on a chain and in what order -//! is also a part of the metadata for the chain. For V15 metadata, it can be +//! Information about exactly which signed extensions are present on a chain and in what order is +//! also a part of the metadata for the chain. For V15 metadata, it can be //! [found here][frame::deps::frame_support::__private::metadata::v15::ExtrinsicMetadata]. //! //! ## call_data @@ -163,8 +163,8 @@ //! ```text //! signed_payload = concat( //! call_data, -//! transaction_extensions_extra, -//! transaction_extensions_implicit, +//! signed_extensions_extra, +//! signed_extensions_additional, //! ) //! //! if length(signed_payload) > 256 { @@ -172,16 +172,16 @@ //! } //! ``` //! -//! The bytes representing `call_data` and `transaction_extensions_extra` can be obtained as -//! descibed above. `transaction_extensions_implicit` is constructed by SCALE encoding the -//! ["implicit" data][sp_runtime::traits::TransactionExtensionBase::Implicit] for each -//! transaction extension that the chain is using, in order. +//! The bytes representing `call_data` and `signed_extensions_extra` can be obtained as described +//! above. `signed_extensions_additional` is constructed by SCALE encoding the +//! ["additional signed" data][sp_runtime::traits::SignedExtension::AdditionalSigned] for each +//! signed extension that the chain is using, in order. //! //! Once we've concatenated those together, we hash the result if it's greater than 256 bytes in //! length using a Blake2 256bit hasher. //! //! The [`sp_runtime::generic::SignedPayload`] type takes care of assembling the correct payload -//! for us, given `call_data` and a tuple of transaction extensions. +//! for us, given `call_data` and a tuple of signed extensions. //! //! # Example Encoding //! @@ -192,12 +192,11 @@ #[docify::export] pub mod call_data { use parity_scale_codec::{Decode, Encode}; - use sp_runtime::{traits::Dispatchable, DispatchResultWithInfo}; // The outer enum composes calls within // different pallets together. We have two // pallets, "PalletA" and "PalletB". - #[derive(Encode, Decode, Clone)] + #[derive(Encode, Decode)] pub enum Call { #[codec(index = 0)] PalletA(PalletACall), @@ -208,33 +207,23 @@ pub mod call_data { // An inner enum represents the calls within // a specific pallet. "PalletA" has one call, // "Foo". - #[derive(Encode, Decode, Clone)] + #[derive(Encode, Decode)] pub enum PalletACall { #[codec(index = 0)] Foo(String), } - #[derive(Encode, Decode, Clone)] + #[derive(Encode, Decode)] pub enum PalletBCall { #[codec(index = 0)] Bar(String), } - - impl Dispatchable for Call { - type RuntimeOrigin = (); - type Config = (); - type Info = (); - type PostInfo = (); - fn dispatch(self, _origin: Self::RuntimeOrigin) -> DispatchResultWithInfo { - Ok(()) - } - } } #[docify::export] pub mod encoding_example { use super::call_data::{Call, PalletACall}; - use crate::reference_docs::transaction_extensions::transaction_extensions_example; + use crate::reference_docs::signed_extensions::signed_extensions_example; use parity_scale_codec::Encode; use sp_core::crypto::AccountId32; use sp_keyring::sr25519::Keyring; @@ -243,40 +232,34 @@ pub mod encoding_example { MultiAddress, MultiSignature, }; - // Define some transaction extensions to use. We'll use a couple of examples - // from the transaction extensions reference doc. - type TransactionExtensions = ( - transaction_extensions_example::AddToPayload, - transaction_extensions_example::AddToSignaturePayload, - ); + // Define some signed extensions to use. We'll use a couple of examples + // from the signed extensions reference doc. + type SignedExtensions = + (signed_extensions_example::AddToPayload, signed_extensions_example::AddToSignaturePayload); // We'll use `UncheckedExtrinsic` to encode our extrinsic for us. We set // the address and signature type to those used on Polkadot, use our custom - // `Call` type, and use our custom set of `TransactionExtensions`. - type Extrinsic = UncheckedExtrinsic< - MultiAddress, - Call, - MultiSignature, - TransactionExtensions, - >; + // `Call` type, and use our custom set of `SignedExtensions`. + type Extrinsic = + UncheckedExtrinsic, Call, MultiSignature, SignedExtensions>; pub fn encode_demo_extrinsic() -> Vec { // The "from" address will be our Alice dev account. let from_address = MultiAddress::::Id(Keyring::Alice.to_account_id()); - // We provide some values for our expected transaction extensions. - let transaction_extensions = ( - transaction_extensions_example::AddToPayload(1), - transaction_extensions_example::AddToSignaturePayload, + // We provide some values for our expected signed extensions. + let signed_extensions = ( + signed_extensions_example::AddToPayload(1), + signed_extensions_example::AddToSignaturePayload, ); // Construct our call data: let call_data = Call::PalletA(PalletACall::Foo("Hello".to_string())); // The signed payload. This takes care of encoding the call_data, - // transaction_extensions_extra and transaction_extensions_implicit, and hashing + // signed_extensions_extra and signed_extensions_additional, and hashing // the result if it's > 256 bytes: - let signed_payload = SignedPayload::new(call_data.clone(), transaction_extensions.clone()); + let signed_payload = SignedPayload::new(&call_data, signed_extensions.clone()); // Sign the signed payload with our Alice dev account's private key, // and wrap the signature into the expected type: @@ -286,7 +269,7 @@ pub mod encoding_example { }; // Now, we can build and encode our extrinsic: - let ext = Extrinsic::new_signed(call_data, from_address, signature, transaction_extensions); + let ext = Extrinsic::new_signed(call_data, from_address, signature, signed_extensions); let encoded_ext = ext.encode(); encoded_ext diff --git a/docs/sdk/src/reference_docs/frame_runtime_types.rs b/docs/sdk/src/reference_docs/frame_runtime_types.rs index 883892729d1..b5838b79e51 100644 --- a/docs/sdk/src/reference_docs/frame_runtime_types.rs +++ b/docs/sdk/src/reference_docs/frame_runtime_types.rs @@ -130,7 +130,7 @@ //! * [`crate::reference_docs::frame_origin`] explores further details about the usage of //! `RuntimeOrigin`. //! * [`RuntimeCall`] is a particularly interesting composite enum as it dictates the encoding of an -//! extrinsic. See [`crate::reference_docs::transaction_extensions`] for more information. +//! extrinsic. See [`crate::reference_docs::signed_extensions`] for more information. //! * See the documentation of [`construct_runtime`]. //! * See the corresponding lecture in the [pba-book](https://polkadot-blockchain-academy.github.io/pba-book/frame/outer-enum/page.html). //! diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index f4b52208e2f..de0b012bb12 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -39,9 +39,9 @@ pub mod runtime_vs_smart_contract; /// Learn about how extrinsics are encoded to be transmitted to a node and stored in blocks. pub mod extrinsic_encoding; -/// Learn about the transaction extensions that form a part of extrinsics. +/// Learn about the signed extensions that form a part of extrinsics. // TODO: @jsdw https://github.com/paritytech/polkadot-sdk-docs/issues/42 -pub mod transaction_extensions; +pub mod signed_extensions; /// Learn about *Origins*, a topic in FRAME that enables complex account abstractions to be built. pub mod frame_origin; diff --git a/docs/sdk/src/reference_docs/signed_extensions.rs b/docs/sdk/src/reference_docs/signed_extensions.rs new file mode 100644 index 00000000000..28b1426536b --- /dev/null +++ b/docs/sdk/src/reference_docs/signed_extensions.rs @@ -0,0 +1,79 @@ +//! Signed extensions are, briefly, a means for different chains to extend the "basic" extrinsic +//! format with custom data that can be checked by the runtime. +//! +//! # Example +//! +//! Defining a couple of very simple signed extensions looks like the following: +#![doc = docify::embed!("./src/reference_docs/signed_extensions.rs", signed_extensions_example)] + +#[docify::export] +pub mod signed_extensions_example { + use parity_scale_codec::{Decode, Encode}; + use scale_info::TypeInfo; + use sp_runtime::traits::SignedExtension; + + // This doesn't actually check anything, but simply allows + // some arbitrary `u32` to be added to the extrinsic payload + #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] + pub struct AddToPayload(pub u32); + + impl SignedExtension for AddToPayload { + const IDENTIFIER: &'static str = "AddToPayload"; + type AccountId = (); + type Call = (); + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed( + &self, + ) -> Result< + Self::AdditionalSigned, + sp_runtime::transaction_validity::TransactionValidityError, + > { + Ok(()) + } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } + } + + // This is the opposite; nothing will be added to the extrinsic payload, + // but the AdditionalSigned type (`1234u32`) will be added to the + // payload to be signed. + #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] + pub struct AddToSignaturePayload; + + impl SignedExtension for AddToSignaturePayload { + const IDENTIFIER: &'static str = "AddToSignaturePayload"; + type AccountId = (); + type Call = (); + type AdditionalSigned = u32; + type Pre = (); + + fn additional_signed( + &self, + ) -> Result< + Self::AdditionalSigned, + sp_runtime::transaction_validity::TransactionValidityError, + > { + Ok(1234) + } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } + } +} diff --git a/docs/sdk/src/reference_docs/transaction_extensions.rs b/docs/sdk/src/reference_docs/transaction_extensions.rs deleted file mode 100644 index 4f96d665d9b..00000000000 --- a/docs/sdk/src/reference_docs/transaction_extensions.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! Transaction extensions are, briefly, a means for different chains to extend the "basic" -//! extrinsic format with custom data that can be checked by the runtime. -//! -//! # Example -//! -//! Defining a couple of very simple transaction extensions looks like the following: -#![doc = docify::embed!("./src/reference_docs/transaction_extensions.rs", transaction_extensions_example)] - -#[docify::export] -pub mod transaction_extensions_example { - use parity_scale_codec::{Decode, Encode}; - use scale_info::TypeInfo; - use sp_runtime::{ - impl_tx_ext_default, - traits::{Dispatchable, TransactionExtension, TransactionExtensionBase}, - TransactionValidityError, - }; - - // This doesn't actually check anything, but simply allows - // some arbitrary `u32` to be added to the extrinsic payload - #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] - pub struct AddToPayload(pub u32); - - impl TransactionExtensionBase for AddToPayload { - const IDENTIFIER: &'static str = "AddToPayload"; - type Implicit = (); - } - - impl TransactionExtension for AddToPayload { - type Pre = (); - type Val = (); - - impl_tx_ext_default!(Call; (); validate prepare); - } - - // This is the opposite; nothing will be added to the extrinsic payload, - // but the Implicit type (`1234u32`) will be added to the - // payload to be signed. - #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] - pub struct AddToSignaturePayload; - - impl TransactionExtensionBase for AddToSignaturePayload { - const IDENTIFIER: &'static str = "AddToSignaturePayload"; - type Implicit = u32; - - fn implicit(&self) -> Result { - Ok(1234) - } - } - - impl TransactionExtension for AddToSignaturePayload { - type Pre = (); - type Val = (); - - impl_tx_ext_default!(Call; (); validate prepare); - } -} diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml index 180de70ad6c..734dcbdeb44 100644 --- a/polkadot/node/service/Cargo.toml +++ b/polkadot/node/service/Cargo.toml @@ -196,7 +196,6 @@ runtime-benchmarks = [ "pallet-babe/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", "pallet-staking/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", "polkadot-runtime-parachains/runtime-benchmarks", diff --git a/polkadot/node/service/src/benchmarking.rs b/polkadot/node/service/src/benchmarking.rs index 29acc5c3ca8..400daf1aee3 100644 --- a/polkadot/node/service/src/benchmarking.rs +++ b/polkadot/node/service/src/benchmarking.rs @@ -189,7 +189,7 @@ fn westend_sign_call( use sp_core::Pair; use westend_runtime as runtime; - let tx_ext: runtime::TxExtension = ( + let extra: runtime::SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -201,12 +201,11 @@ fn westend_sign_call( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ) - .into(); + ); let payload = runtime::SignedPayload::from_raw( call.clone(), - tx_ext.clone(), + extra.clone(), ( (), runtime::VERSION.spec_version, @@ -224,7 +223,7 @@ fn westend_sign_call( call, sp_runtime::AccountId32::from(acc.public()).into(), polkadot_core_primitives::Signature::Sr25519(signature.clone()), - tx_ext, + extra, ) .into() } @@ -242,7 +241,7 @@ fn rococo_sign_call( use rococo_runtime as runtime; use sp_core::Pair; - let tx_ext: runtime::TxExtension = ( + let extra: runtime::SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -254,12 +253,11 @@ fn rococo_sign_call( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ) - .into(); + ); let payload = runtime::SignedPayload::from_raw( call.clone(), - tx_ext.clone(), + extra.clone(), ( (), runtime::VERSION.spec_version, @@ -277,7 +275,7 @@ fn rococo_sign_call( call, sp_runtime::AccountId32::from(acc.public()).into(), polkadot_core_primitives::Signature::Sr25519(signature.clone()), - tx_ext, + extra, ) .into() } diff --git a/polkadot/node/test/service/Cargo.toml b/polkadot/node/test/service/Cargo.toml index 02b227e6f34..e7892abcd87 100644 --- a/polkadot/node/test/service/Cargo.toml +++ b/polkadot/node/test/service/Cargo.toml @@ -71,7 +71,6 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-staking/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", "polkadot-runtime-common/runtime-benchmarks", diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs index 1876595c7b4..ca904bae28d 100644 --- a/polkadot/node/test/service/src/lib.rs +++ b/polkadot/node/test/service/src/lib.rs @@ -32,7 +32,7 @@ use polkadot_service::{ Error, FullClient, IsParachainNode, NewFull, OverseerGen, PrometheusConfig, }; use polkadot_test_runtime::{ - ParasCall, ParasSudoWrapperCall, Runtime, SignedPayload, SudoCall, TxExtension, + ParasCall, ParasSudoWrapperCall, Runtime, SignedExtra, SignedPayload, SudoCall, UncheckedExtrinsic, VERSION, }; @@ -382,7 +382,7 @@ pub fn construct_extrinsic( let period = BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; let tip = 0; - let tx_ext: TxExtension = ( + let extra: SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -391,11 +391,10 @@ pub fn construct_extrinsic( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ) - .into(); + ); let raw_payload = SignedPayload::from_raw( function.clone(), - tx_ext.clone(), + extra.clone(), ( (), VERSION.spec_version, @@ -412,7 +411,7 @@ pub fn construct_extrinsic( function.clone(), polkadot_test_runtime::Address::Id(caller.public().into()), polkadot_primitives::Signature::Sr25519(signature.clone()), - tx_ext.clone(), + extra.clone(), ) } diff --git a/polkadot/runtime/common/Cargo.toml b/polkadot/runtime/common/Cargo.toml index c2205938295..eae5d4fb2ef 100644 --- a/polkadot/runtime/common/Cargo.toml +++ b/polkadot/runtime/common/Cargo.toml @@ -132,7 +132,6 @@ runtime-benchmarks = [ "pallet-identity/runtime-benchmarks", "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", "primitives/runtime-benchmarks", diff --git a/polkadot/runtime/common/src/claims.rs b/polkadot/runtime/common/src/claims.rs index 57a95b22af3..68f42914e44 100644 --- a/polkadot/runtime/common/src/claims.rs +++ b/polkadot/runtime/common/src/claims.rs @@ -29,11 +29,7 @@ use scale_info::TypeInfo; use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; use sp_io::{crypto::secp256k1_ecdsa_recover, hashing::keccak_256}; use sp_runtime::{ - impl_tx_ext_default, - traits::{ - AsSystemOriginSigner, CheckedSub, DispatchInfoOf, Dispatchable, TransactionExtension, - TransactionExtensionBase, Zero, - }, + traits::{CheckedSub, DispatchInfoOf, SignedExtension, Zero}, transaction_validity::{ InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, }, @@ -54,7 +50,6 @@ pub trait WeightInfo { fn claim_attest() -> Weight; fn attest() -> Weight; fn move_claim() -> Weight; - fn prevalidate_attests() -> Weight; } pub struct TestWeightInfo; @@ -74,9 +69,6 @@ impl WeightInfo for TestWeightInfo { fn move_claim() -> Weight { Weight::zero() } - fn prevalidate_attests() -> Weight { - Weight::zero() - } } /// The kind of statement an account needs to make for a claim to be valid. @@ -92,7 +84,7 @@ pub enum StatementKind { impl StatementKind { /// Convert this to the (English) statement it represents. - pub fn to_text(self) -> &'static [u8] { + fn to_text(self) -> &'static [u8] { match self { StatementKind::Regular => &b"I hereby agree to the terms of the statement whose SHA-256 multihash is \ @@ -174,13 +166,6 @@ pub mod pallet { #[pallet::without_storage_info] pub struct Pallet(_); - #[cfg(feature = "runtime-benchmarks")] - /// Helper trait to benchmark the `PrevalidateAttests` transaction extension. - pub trait BenchmarkHelperTrait { - /// `Call` to be used when benchmarking the transaction extension. - fn default_call_and_info() -> (RuntimeCall, DispatchInfo); - } - /// Configuration trait. #[pallet::config] pub trait Config: frame_system::Config { @@ -191,12 +176,6 @@ pub mod pallet { type Prefix: Get<&'static [u8]>; type MoveClaimOrigin: EnsureOrigin; type WeightInfo: WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - /// Benchmark helper - type BenchmarkHelper: BenchmarkHelperTrait< - Self::RuntimeCall, - DispatchInfoOf, - >; } #[pallet::event] @@ -423,7 +402,7 @@ pub mod pallet { /// Attest to a statement, needed to finalize the claims process. /// /// WARNING: Insecure unless your chain includes `PrevalidateAttests` as a - /// `TransactionExtension`. + /// `SignedExtension`. /// /// Unsigned Validation: /// A call to attest is deemed valid if the sender has a `Preclaim` registered @@ -633,46 +612,46 @@ impl PrevalidateAttests where ::RuntimeCall: IsSubType>, { - /// Create new `TransactionExtension` to check runtime version. + /// Create new `SignedExtension` to check runtime version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl TransactionExtensionBase for PrevalidateAttests +impl SignedExtension for PrevalidateAttests where ::RuntimeCall: IsSubType>, { + type AccountId = T::AccountId; + type Call = ::RuntimeCall; + type AdditionalSigned = (); + type Pre = (); const IDENTIFIER: &'static str = "PrevalidateAttests"; - type Implicit = (); -} -impl TransactionExtension for PrevalidateAttests -where - ::RuntimeCall: IsSubType>, - <::RuntimeCall as Dispatchable>::RuntimeOrigin: - AsSystemOriginSigner + Clone, -{ - type Pre = (); - type Val = (); + fn additional_signed(&self) -> Result { + Ok(()) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) + } // // The weight of this logic is included in the `attest` dispatchable. // fn validate( &self, - origin: ::RuntimeOrigin, - call: &T::RuntimeCall, - _info: &DispatchInfoOf, + who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> Result< - (ValidTransaction, Self::Val, ::RuntimeOrigin), - TransactionValidityError, - > { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + ) -> TransactionValidity { if let Some(local_call) = call.is_sub_type() { if let Call::attest { statement: attested_statement } = local_call { let signer = Preclaims::::get(who) @@ -683,9 +662,8 @@ where } } } - Ok((ValidTransaction::default(), (), origin)) + Ok(ValidTransaction::default()) } - impl_tx_ext_default!(T::RuntimeCall; Context; prepare); } #[cfg(any(test, feature = "runtime-benchmarks"))] @@ -718,7 +696,7 @@ mod secp_utils { } #[cfg(test)] -pub(super) mod tests { +mod tests { use super::*; use hex_literal::hex; use secp_utils::*; @@ -736,11 +714,8 @@ pub(super) mod tests { }; use pallet_balances; use sp_runtime::{ - traits::{DispatchTransaction, Identity}, - transaction_validity::TransactionLongevity, - BuildStorage, - DispatchError::BadOrigin, - TokenError, + traits::Identity, transaction_validity::TransactionLongevity, BuildStorage, + DispatchError::BadOrigin, TokenError, }; type Block = frame_system::mocking::MockBlock; @@ -815,19 +790,6 @@ pub(super) mod tests { type Prefix = Prefix; type MoveClaimOrigin = frame_system::EnsureSignedBy; type WeightInfo = TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - } - - #[cfg(feature = "runtime-benchmarks")] - impl BenchmarkHelperTrait> for () { - fn default_call_and_info() -> (RuntimeCall, DispatchInfoOf) { - let call = RuntimeCall::Claims(crate::claims::Call::attest { - statement: StatementKind::Regular.to_text().to_vec(), - }); - let info = call.get_dispatch_info(); - (call, info) - } } fn alice() -> libsecp256k1::SecretKey { @@ -1109,8 +1071,8 @@ pub(super) mod tests { }); let di = c.get_dispatch_info(); assert_eq!(di.pays_fee, Pays::No); - let r = p.validate_only(Some(42).into(), &c, &di, 20); - assert_eq!(r.unwrap().0, ValidTransaction::default()); + let r = p.validate(&42, &c, &di, 20); + assert_eq!(r, TransactionValidity::Ok(ValidTransaction::default())); }); } @@ -1122,13 +1084,13 @@ pub(super) mod tests { statement: StatementKind::Regular.to_text().to_vec(), }); let di = c.get_dispatch_info(); - let r = p.validate_only(Some(42).into(), &c, &di, 20); + let r = p.validate(&42, &c, &di, 20); assert!(r.is_err()); let c = RuntimeCall::Claims(ClaimsCall::attest { statement: StatementKind::Saft.to_text().to_vec(), }); let di = c.get_dispatch_info(); - let r = p.validate_only(Some(69).into(), &c, &di, 20); + let r = p.validate(&69, &c, &di, 20); assert!(r.is_err()); }); } @@ -1482,17 +1444,14 @@ pub(super) mod tests { } #[cfg(feature = "runtime-benchmarks")] -pub(super) mod benchmarking { +mod benchmarking { use super::*; use crate::claims::Call; use frame_benchmarking::{account, benchmarks}; use frame_support::traits::UnfilteredDispatchable; use frame_system::RawOrigin; use secp_utils::*; - use sp_runtime::{ - traits::{DispatchTransaction, ValidateUnsigned}, - DispatchResult, - }; + use sp_runtime::{traits::ValidateUnsigned, DispatchResult}; const SEED: u32 = 0; @@ -1528,11 +1487,6 @@ pub(super) mod benchmarking { } benchmarks! { - where_clause { where ::RuntimeCall: IsSubType>, - <::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner + Clone, - <::RuntimeCall as Dispatchable>::PostInfo: Default, - } - // Benchmark `claim` including `validate_unsigned` logic. claim { let c = MAX_CLAIMS; @@ -1711,38 +1665,6 @@ pub(super) mod benchmarking { } } - prevalidate_attests { - let c = MAX_CLAIMS; - - for i in 0 .. c / 2 { - create_claim::(c)?; - create_claim_attest::(u32::MAX - c)?; - } - - let ext = PrevalidateAttests::::new(); - let (call, info) = T::BenchmarkHelper::default_call_and_info(); - let attest_c = u32::MAX - c; - let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&attest_c.encode())).unwrap(); - let eth_address = eth(&secret_key); - let account: T::AccountId = account("user", c, SEED); - let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into())); - let statement = StatementKind::Regular; - let signature = sig::(&secret_key, &account.encode(), statement.to_text()); - super::Pallet::::mint_claim(RawOrigin::Root.into(), eth_address, VALUE.into(), vesting, Some(statement))?; - Preclaims::::insert(&account, eth_address); - assert_eq!(Claims::::get(eth_address), Some(VALUE.into())); - }: { - assert!(ext.test_run( - RawOrigin::Signed(account).into(), - &call, - &info, - 0, - |_| { - Ok(Default::default()) - } - ).unwrap().is_ok()); - } - impl_benchmark_test_suite!( Pallet, crate::claims::tests::new_test_ext(), diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index 61ca1635ac9..3dc59cc1728 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -246,7 +246,6 @@ runtime-benchmarks = [ "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-tips/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", diff --git a/polkadot/runtime/rococo/constants/src/weights/block_weights.rs b/polkadot/runtime/rococo/constants/src/weights/block_weights.rs index f7dc2f19316..e2aa4a6cab7 100644 --- a/polkadot/runtime/rococo/constants/src/weights/block_weights.rs +++ b/polkadot/runtime/rococo/constants/src/weights/block_weights.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29 (Y/M/D) -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26 (Y/M/D) +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `block`, LONG-NAME: `BlockExecution`, RUNTIME: `Development` //! WARMUPS: `10`, REPEAT: `100` -//! WEIGHT-PATH: `./polkadot/runtime/rococo/constants/src/weights/` +//! WEIGHT-PATH: `runtime/rococo/constants/src/weights/` //! WEIGHT-METRIC: `Average`, WEIGHT-MUL: `1.0`, WEIGHT-ADD: `0` // Executed Command: @@ -28,11 +28,12 @@ // benchmark // overhead // --chain=rococo-dev +// --execution=wasm // --wasm-execution=compiled -// --weight-path=./polkadot/runtime/rococo/constants/src/weights/ +// --weight-path=runtime/rococo/constants/src/weights/ // --warmup=10 // --repeat=100 -// --header=./polkadot/file_header.txt +// --header=./file_header.txt use sp_core::parameter_types; use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; @@ -42,17 +43,17 @@ parameter_types! { /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 440_142, 476_907 - /// Average: 450_240 - /// Median: 448_633 - /// Std-Dev: 7301.18 + /// Min, Max: 408_659, 450_716 + /// Average: 417_412 + /// Median: 411_177 + /// Std-Dev: 12242.31 /// /// Percentiles nanoseconds: - /// 99th: 470_733 - /// 95th: 465_082 - /// 75th: 452_536 + /// 99th: 445_142 + /// 95th: 442_275 + /// 75th: 414_217 pub const BlockExecutionWeight: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(450_240), 0); + Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(417_412), 0); } #[cfg(test)] diff --git a/polkadot/runtime/rococo/constants/src/weights/extrinsic_weights.rs b/polkadot/runtime/rococo/constants/src/weights/extrinsic_weights.rs index 000cee8a237..adce840ebbc 100644 --- a/polkadot/runtime/rococo/constants/src/weights/extrinsic_weights.rs +++ b/polkadot/runtime/rococo/constants/src/weights/extrinsic_weights.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29 (Y/M/D) -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26 (Y/M/D) +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `extrinsic`, LONG-NAME: `ExtrinsicBase`, RUNTIME: `Development` //! WARMUPS: `10`, REPEAT: `100` -//! WEIGHT-PATH: `./polkadot/runtime/rococo/constants/src/weights/` +//! WEIGHT-PATH: `runtime/rococo/constants/src/weights/` //! WEIGHT-METRIC: `Average`, WEIGHT-MUL: `1.0`, WEIGHT-ADD: `0` // Executed Command: @@ -28,11 +28,12 @@ // benchmark // overhead // --chain=rococo-dev +// --execution=wasm // --wasm-execution=compiled -// --weight-path=./polkadot/runtime/rococo/constants/src/weights/ +// --weight-path=runtime/rococo/constants/src/weights/ // --warmup=10 // --repeat=100 -// --header=./polkadot/file_header.txt +// --header=./file_header.txt use sp_core::parameter_types; use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; @@ -42,17 +43,17 @@ parameter_types! { /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 92_961, 94_143 - /// Average: 93_369 - /// Median: 93_331 - /// Std-Dev: 217.39 + /// Min, Max: 97_574, 100_119 + /// Average: 98_236 + /// Median: 98_179 + /// Std-Dev: 394.9 /// /// Percentiles nanoseconds: - /// 99th: 93_848 - /// 95th: 93_691 - /// 75th: 93_514 + /// 99th: 99_893 + /// 95th: 98_850 + /// 75th: 98_318 pub const ExtrinsicBaseWeight: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(93_369), 0); + Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(98_236), 0); } #[cfg(test)] diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index ff54c777670..96e8c4e0979 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -199,7 +199,6 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type MaxConsumers = frame_support::traits::ConstU32<16>; } @@ -330,7 +329,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -593,7 +591,7 @@ where // so the actual block number is `n`. .saturating_sub(1); let tip = 0; - let tx_ext: TxExtension = ( + let extra: SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -605,17 +603,16 @@ where frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ) - .into(); - let raw_payload = SignedPayload::new(call, tx_ext) + ); + let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; - let (call, tx_ext, _) = raw_payload.deconstruct(); + let (call, extra, _) = raw_payload.deconstruct(); let address = ::Lookup::unlookup(account); - Some((call, (address, signature, tx_ext))) + Some((call, (address, signature, extra))) } } @@ -636,32 +633,12 @@ parameter_types! { pub Prefix: &'static [u8] = b"Pay ROCs to the Rococo account:"; } -#[cfg(feature = "runtime-benchmarks")] -pub struct ClaimsHelper; - -#[cfg(feature = "runtime-benchmarks")] -use frame_support::dispatch::DispatchInfo; - -#[cfg(feature = "runtime-benchmarks")] -impl claims::BenchmarkHelperTrait for ClaimsHelper { - fn default_call_and_info() -> (RuntimeCall, DispatchInfo) { - use frame_support::dispatch::GetDispatchInfo; - let call = RuntimeCall::Claims(claims::Call::attest { - statement: claims::StatementKind::Regular.to_text().to_vec(), - }); - let info = call.get_dispatch_info(); - (call, info) - } -} - impl claims::Config for Runtime { type RuntimeEvent = RuntimeEvent; type VestingSchedule = Vesting; type Prefix = Prefix; type MoveClaimOrigin = EnsureRoot; type WeightInfo = weights::runtime_common_claims::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = ClaimsHelper; } parameter_types! { @@ -1470,8 +1447,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// `BlockId` type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The `SignedExtension` to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -1484,7 +1461,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// All migrations that will run on the next runtime upgrade. /// @@ -1698,7 +1675,7 @@ pub type Executive = frame_executive::Executive< Migrations, >; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; parameter_types! { // The deposit configuration for the singed migration. Specially if you want to allow any signed account to do the migration (see `SignedFilter`, these deposits should be high) @@ -1769,9 +1746,7 @@ mod benches { [pallet_scheduler, Scheduler] [pallet_sudo, Sudo] [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_timestamp, Timestamp] - [pallet_transaction_payment, TransactionPayment] [pallet_treasury, Treasury] [pallet_utility, Utility] [pallet_vesting, Vesting] @@ -2265,7 +2240,6 @@ sp_api::impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use frame_benchmarking::baseline::Pallet as Baseline; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; @@ -2286,7 +2260,6 @@ sp_api::impl_runtime_apis! { use frame_support::traits::WhitelistedStorageKeys; use frame_benchmarking::{Benchmarking, BenchmarkBatch, BenchmarkError}; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use frame_benchmarking::baseline::Pallet as Baseline; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use sp_storage::TrackedStorageKey; diff --git a/polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs b/polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs index 0f68a5c6fb3..dfba0cfc4aa 100644 --- a/polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs +++ b/polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `frame_benchmarking::baseline` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=frame_benchmarking::baseline // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/frame_benchmarking_baseline.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/frame_benchmarking_baseline.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,8 +52,8 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 172_000 picoseconds. - Weight::from_parts(199_481, 0) + // Minimum execution time: 157_000 picoseconds. + Weight::from_parts(175_233, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `i` is `[0, 1000000]`. @@ -64,8 +61,8 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 171_000 picoseconds. - Weight::from_parts(197_821, 0) + // Minimum execution time: 149_000 picoseconds. + Weight::from_parts(183_285, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `i` is `[0, 1000000]`. @@ -73,8 +70,8 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 172_000 picoseconds. - Weight::from_parts(200_942, 0) + // Minimum execution time: 158_000 picoseconds. + Weight::from_parts(184_720, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `i` is `[0, 1000000]`. @@ -82,16 +79,16 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 170_000 picoseconds. - Weight::from_parts(196_906, 0) + // Minimum execution time: 152_000 picoseconds. + Weight::from_parts(177_496, 0) .saturating_add(Weight::from_parts(0, 0)) } fn hashing() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 23_346_876_000 picoseconds. - Weight::from_parts(23_363_744_000, 0) + // Minimum execution time: 19_907_376_000 picoseconds. + Weight::from_parts(19_988_727_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `i` is `[0, 100]`. @@ -99,10 +96,10 @@ impl frame_benchmarking::baseline::WeightInfo for Weigh // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 201_000 picoseconds. - Weight::from_parts(219_000, 0) + // Minimum execution time: 198_000 picoseconds. + Weight::from_parts(228_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 14_372 - .saturating_add(Weight::from_parts(45_375_800, 0).saturating_mul(i.into())) + // Standard Error: 20_467 + .saturating_add(Weight::from_parts(47_443_635, 0).saturating_mul(i.into())) } } diff --git a/polkadot/runtime/rococo/src/weights/frame_system.rs b/polkadot/runtime/rococo/src/weights/frame_system.rs index 1742a761ca7..2e49483dcc6 100644 --- a/polkadot/runtime/rococo/src/weights/frame_system.rs +++ b/polkadot/runtime/rococo/src/weights/frame_system.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `frame_system` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=frame_system // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,91 +52,91 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_541_000 picoseconds. - Weight::from_parts(2_581_470, 0) + // Minimum execution time: 2_283_000 picoseconds. + Weight::from_parts(2_305_000, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(387, 0).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(366, 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: 5_060_000 picoseconds. - Weight::from_parts(5_167_000, 0) + // Minimum execution time: 7_435_000 picoseconds. + Weight::from_parts(7_581_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_696, 0).saturating_mul(b.into())) + // Standard Error: 0 + .saturating_add(Weight::from_parts(1_408, 0).saturating_mul(b.into())) } - /// Storage: `System::Digest` (r:1 w:1) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a686561707061676573` (r:0 w:1) + /// Proof Skipped: unknown `0x3a686561707061676573` (r:0 w:1) fn set_heap_pages() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 2_649_000 picoseconds. - Weight::from_parts(2_909_000, 0) + // Minimum execution time: 4_010_000 picoseconds. + Weight::from_parts(4_112_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `System::Digest` (r:1 w:1) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a636f6465` (r:0 w:1) + /// Proof Skipped: unknown `0x3a636f6465` (r:0 w:1) fn set_code() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 88_417_540_000 picoseconds. - Weight::from_parts(91_809_291_000, 0) + // Minimum execution time: 80_405_511_000 picoseconds. + Weight::from_parts(83_066_478_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_538_000 picoseconds. - Weight::from_parts(1_589_000, 0) + // Minimum execution time: 2_210_000 picoseconds. + Weight::from_parts(2_247_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 1_740 - .saturating_add(Weight::from_parts(730_941, 0).saturating_mul(i.into())) + // Standard Error: 2_058 + .saturating_add(Weight::from_parts(673_943, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_567_000 picoseconds. - Weight::from_parts(1_750_000, 0) + // Minimum execution time: 2_125_000 picoseconds. + Weight::from_parts(2_154_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 835 - .saturating_add(Weight::from_parts(543_218, 0).saturating_mul(i.into())) + // Standard Error: 816 + .saturating_add(Weight::from_parts(491_194, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `80 + p * (69 ±0)` - // Estimated: `83 + p * (70 ±0)` - // Minimum execution time: 3_412_000 picoseconds. - Weight::from_parts(3_448_000, 0) - .saturating_add(Weight::from_parts(0, 83)) - // Standard Error: 1_395 - .saturating_add(Weight::from_parts(1_142_347, 0).saturating_mul(p.into())) + // Measured: `129 + p * (69 ±0)` + // Estimated: `125 + p * (70 ±0)` + // Minimum execution time: 4_002_000 picoseconds. + Weight::from_parts(4_145_000, 0) + .saturating_add(Weight::from_parts(0, 125)) + // Standard Error: 1_108 + .saturating_add(Weight::from_parts(1_014_971, 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())) @@ -150,8 +147,8 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_178_000 picoseconds. - Weight::from_parts(9_780_000, 0) + // Minimum execution time: 33_027_000 picoseconds. + Weight::from_parts(33_027_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -165,8 +162,8 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `22` // Estimated: `1518` - // Minimum execution time: 94_523_563_000 picoseconds. - Weight::from_parts(96_983_131_000, 0) + // Minimum execution time: 118_101_992_000 picoseconds. + Weight::from_parts(118_101_992_000, 0) .saturating_add(Weight::from_parts(0, 1518)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs b/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs deleted file mode 100644 index 40520591f53..00000000000 --- a/polkadot/runtime/rococo/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=rococo-dev -// --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=frame_system_extensions -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ - -#![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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_262_000 picoseconds. - Weight::from_parts(3_497_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_416_000 picoseconds. - Weight::from_parts(5_690_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 471_000 picoseconds. - Weight::from_parts(552_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `101` - // Estimated: `3593` - // Minimum execution time: 4_847_000 picoseconds. - Weight::from_parts(5_091_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 388_000 picoseconds. - Weight::from_parts(421_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 378_000 picoseconds. - Weight::from_parts(440_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1489` - // Minimum execution time: 3_402_000 picoseconds. - Weight::from_parts(3_627_000, 0) - .saturating_add(Weight::from_parts(0, 1489)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/polkadot/runtime/rococo/src/weights/mod.rs b/polkadot/runtime/rococo/src/weights/mod.rs index 128a3083a9c..7328dca9393 100644 --- a/polkadot/runtime/rococo/src/weights/mod.rs +++ b/polkadot/runtime/rococo/src/weights/mod.rs @@ -16,7 +16,6 @@ //! A list of the different weight modules for our runtime. pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_asset_rate; pub mod pallet_balances_balances; pub mod pallet_balances_nis_counterpart_balances; @@ -37,7 +36,6 @@ pub mod pallet_scheduler; pub mod pallet_session; pub mod pallet_sudo; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_treasury; pub mod pallet_utility; pub mod pallet_vesting; diff --git a/polkadot/runtime/rococo/src/weights/pallet_asset_rate.rs b/polkadot/runtime/rococo/src/weights/pallet_asset_rate.rs index 56b1e2cbc57..da2d1958cef 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_asset_rate.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_asset_rate.rs @@ -16,28 +16,25 @@ //! Autogenerated weights for `pallet_asset_rate` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-07-03, STEPS: `50`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `cob`, CPU: `` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// ./target/debug/polkadot // benchmark // pallet // --chain=rococo-dev // --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares +// --repeat=2 // --pallet=pallet_asset_rate // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --heap-pages=4096 +// --output=./runtime/rococo/src/weights/ +// --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,39 +47,39 @@ use core::marker::PhantomData; /// Weight functions for `pallet_asset_rate`. pub struct WeightInfo(PhantomData); impl pallet_asset_rate::WeightInfo for WeightInfo { - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(1237), added: 3712, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `4703` - // Minimum execution time: 10_277_000 picoseconds. - Weight::from_parts(10_487_000, 0) - .saturating_add(Weight::from_parts(0, 4703)) + // Measured: `42` + // Estimated: `4702` + // Minimum execution time: 143_000_000 picoseconds. + Weight::from_parts(155_000_000, 0) + .saturating_add(Weight::from_parts(0, 4702)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(1237), added: 3712, mode: MaxEncodedLen) fn update() -> Weight { // Proof Size summary in bytes: - // Measured: `210` - // Estimated: `4703` - // Minimum execution time: 10_917_000 picoseconds. - Weight::from_parts(11_249_000, 0) - .saturating_add(Weight::from_parts(0, 4703)) + // Measured: `110` + // Estimated: `4702` + // Minimum execution time: 156_000_000 picoseconds. + Weight::from_parts(172_000_000, 0) + .saturating_add(Weight::from_parts(0, 4702)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(1237), added: 3712, mode: MaxEncodedLen) fn remove() -> Weight { // Proof Size summary in bytes: - // Measured: `210` - // Estimated: `4703` - // Minimum execution time: 11_332_000 picoseconds. - Weight::from_parts(11_866_000, 0) - .saturating_add(Weight::from_parts(0, 4703)) + // Measured: `110` + // Estimated: `4702` + // Minimum execution time: 150_000_000 picoseconds. + Weight::from_parts(160_000_000, 0) + .saturating_add(Weight::from_parts(0, 4702)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs b/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs index 3fa54f2c369..1b0ae1eeece 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_balances_balances.rs @@ -16,26 +16,24 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_balances // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_balances +// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -56,8 +54,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 45_336_000 picoseconds. - Weight::from_parts(46_189_000, 0) + // Minimum execution time: 44_127_000 picoseconds. + Weight::from_parts(45_099_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -68,8 +66,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 34_880_000 picoseconds. - Weight::from_parts(35_770_000, 0) + // Minimum execution time: 34_265_000 picoseconds. + Weight::from_parts(35_083_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -80,8 +78,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 12_904_000 picoseconds. - Weight::from_parts(13_260_000, 0) + // Minimum execution time: 12_189_000 picoseconds. + Weight::from_parts(12_655_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -92,8 +90,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 17_669_000 picoseconds. - Weight::from_parts(18_228_000, 0) + // Minimum execution time: 16_910_000 picoseconds. + Weight::from_parts(17_474_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -104,8 +102,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 46_492_000 picoseconds. - Weight::from_parts(47_639_000, 0) + // Minimum execution time: 45_212_000 picoseconds. + Weight::from_parts(46_320_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -116,8 +114,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 44_342_000 picoseconds. - Weight::from_parts(45_144_000, 0) + // Minimum execution time: 42_500_000 picoseconds. + Weight::from_parts(43_991_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -128,8 +126,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 15_260_000 picoseconds. - Weight::from_parts(15_775_000, 0) + // Minimum execution time: 15_197_000 picoseconds. + Weight::from_parts(15_749_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -142,11 +140,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_703_000 picoseconds. - Weight::from_parts(14_950_000, 0) + // Minimum execution time: 14_414_000 picoseconds. + Weight::from_parts(14_685_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 7_665 - .saturating_add(Weight::from_parts(13_335_803, 0).saturating_mul(u.into())) + // Standard Error: 7_918 + .saturating_add(Weight::from_parts(13_095_420, 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())) @@ -155,8 +153,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_506_000 picoseconds. - Weight::from_parts(5_753_000, 0) + // Minimum execution time: 5_239_000 picoseconds. + Weight::from_parts(5_617_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs b/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs index 1852ba6c2c4..6cca9b9320a 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs @@ -16,26 +16,24 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_balances // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_balances +// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -58,8 +56,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 42_443_000 picoseconds. - Weight::from_parts(43_250_000, 0) + // Minimum execution time: 41_978_000 picoseconds. + Weight::from_parts(42_989_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -72,8 +70,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 32_417_000 picoseconds. - Weight::from_parts(33_247_000, 0) + // Minimum execution time: 32_250_000 picoseconds. + Weight::from_parts(33_074_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -84,8 +82,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3577` - // Minimum execution time: 10_091_000 picoseconds. - Weight::from_parts(10_426_000, 0) + // Minimum execution time: 9_906_000 picoseconds. + Weight::from_parts(10_397_000, 0) .saturating_add(Weight::from_parts(0, 3577)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -98,8 +96,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `277` // Estimated: `3593` - // Minimum execution time: 16_546_000 picoseconds. - Weight::from_parts(17_259_000, 0) + // Minimum execution time: 16_298_000 picoseconds. + Weight::from_parts(17_115_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -112,8 +110,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `206` // Estimated: `6196` - // Minimum execution time: 44_322_000 picoseconds. - Weight::from_parts(45_319_000, 0) + // Minimum execution time: 43_283_000 picoseconds. + Weight::from_parts(44_033_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(4)) @@ -126,8 +124,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6164` - // Minimum execution time: 40_852_000 picoseconds. - Weight::from_parts(42_205_000, 0) + // Minimum execution time: 40_564_000 picoseconds. + Weight::from_parts(41_597_000, 0) .saturating_add(Weight::from_parts(0, 6164)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -140,8 +138,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `277` // Estimated: `3593` - // Minimum execution time: 15_050_000 picoseconds. - Weight::from_parts(15_813_000, 0) + // Minimum execution time: 15_018_000 picoseconds. + Weight::from_parts(15_532_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -156,11 +154,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (256 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_830_000 picoseconds. - Weight::from_parts(15_061_000, 0) + // Minimum execution time: 14_470_000 picoseconds. + Weight::from_parts(14_828_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 16_072 - .saturating_add(Weight::from_parts(14_981_430, 0).saturating_mul(u.into())) + // Standard Error: 15_515 + .saturating_add(Weight::from_parts(14_505_553, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -169,8 +167,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_344_000 picoseconds. - Weight::from_parts(5_735_000, 0) + // Minimum execution time: 5_277_000 picoseconds. + Weight::from_parts(5_628_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_bounties.rs b/polkadot/runtime/rococo/src/weights/pallet_bounties.rs index 8f8be5f2386..38d3645316f 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_bounties.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_bounties.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_bounties` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_bounties // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,181 +47,118 @@ use core::marker::PhantomData; /// Weight functions for `pallet_bounties`. pub struct WeightInfo(PhantomData); impl pallet_bounties::WeightInfo for WeightInfo { - /// Storage: `Bounties::BountyCount` (r:1 w:1) - /// Proof: `Bounties::BountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:0 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: Bounties BountyCount (r:1 w:1) + /// Proof: Bounties BountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(16400), added: 18875, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:0 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) /// The range of component `d` is `[0, 16384]`. fn propose_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `210` // Estimated: `3593` - // Minimum execution time: 21_772_000 picoseconds. - Weight::from_parts(22_861_341, 0) + // Minimum execution time: 28_907_000 picoseconds. + Weight::from_parts(31_356_074, 0) .saturating_add(Weight::from_parts(0, 3593)) - // Standard Error: 3 - .saturating_add(Weight::from_parts(721, 0).saturating_mul(d.into())) + // Standard Error: 18 + .saturating_add(Weight::from_parts(606, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn approve_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `302` - // Estimated: `3642` - // Minimum execution time: 11_218_000 picoseconds. - Weight::from_parts(11_796_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `322` - // Estimated: `3642` - // Minimum execution time: 10_959_000 picoseconds. - Weight::from_parts(11_658_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `498` - // Estimated: `3642` - // Minimum execution time: 37_419_000 picoseconds. - Weight::from_parts(38_362_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `494` - // Estimated: `3642` - // Minimum execution time: 27_328_000 picoseconds. - Weight::from_parts(27_661_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn award_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `400` - // Estimated: `3642` - // Minimum execution time: 16_067_000 picoseconds. - Weight::from_parts(16_865_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn claim_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `764` - // Estimated: `8799` - // Minimum execution time: 101_153_000 picoseconds. - Weight::from_parts(102_480_000, 0) - .saturating_add(Weight::from_parts(0, 8799)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(6)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:0) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(16400), added: 18875, mode: MaxEncodedLen) fn close_bounty_proposed() -> Weight { // Proof Size summary in bytes: - // Measured: `444` + // Measured: `482` // Estimated: `3642` - // Minimum execution time: 38_838_000 picoseconds. - Weight::from_parts(39_549_000, 0) + // Minimum execution time: 46_020_000 picoseconds. + Weight::from_parts(46_711_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn close_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `680` - // Estimated: `6196` - // Minimum execution time: 68_592_000 picoseconds. - Weight::from_parts(70_727_000, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn extend_bounty_expiry() -> Weight { // Proof Size summary in bytes: - // Measured: `358` - // Estimated: `3642` - // Minimum execution time: 11_272_000 picoseconds. - Weight::from_parts(11_592_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:100 w:100) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:200 w:200) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties BountyApprovals (r:1 w:1) + /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) /// The range of component `b` is `[0, 100]`. - fn spend_funds(b: u32, ) -> Weight { + fn spend_funds(_b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + b * (297 ±0)` - // Estimated: `1887 + b * (5206 ±0)` - // Minimum execution time: 2_844_000 picoseconds. - Weight::from_parts(2_900_000, 0) + // Measured: `0` + // Estimated: `1887` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(2_405_233, 0) .saturating_add(Weight::from_parts(0, 1887)) - // Standard Error: 9_467 - .saturating_add(Weight::from_parts(32_326_595, 0).saturating_mul(b.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(b.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(b.into()))) - .saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into())) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_child_bounties.rs b/polkadot/runtime/rococo/src/weights/pallet_child_bounties.rs index 47ae3a5c90d..e8c798d45e7 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_child_bounties.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_child_bounties.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_child_bounties` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_child_bounties // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,153 +47,69 @@ use core::marker::PhantomData; /// Weight functions for `pallet_child_bounties`. pub struct WeightInfo(PhantomData); impl pallet_child_bounties::WeightInfo for WeightInfo { - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyCount` (r:1 w:1) - /// Proof: `ChildBounties::ChildBountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:0 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) /// The range of component `d` is `[0, 16384]`. - fn add_child_bounty(d: u32, ) -> Weight { + fn add_child_bounty(_d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `540` - // Estimated: `6196` - // Minimum execution time: 57_964_000 picoseconds. - Weight::from_parts(59_559_565, 0) - .saturating_add(Weight::from_parts(0, 6196)) - // Standard Error: 11 - .saturating_add(Weight::from_parts(697, 0).saturating_mul(d.into())) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(6)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `594` - // Estimated: `3642` - // Minimum execution time: 17_527_000 picoseconds. - Weight::from_parts(18_257_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `740` - // Estimated: `3642` - // Minimum execution time: 29_354_000 picoseconds. - Weight::from_parts(30_629_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `740` - // Estimated: `3642` - // Minimum execution time: 40_643_000 picoseconds. - Weight::from_parts(42_072_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) fn award_child_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `637` - // Estimated: `3642` - // Minimum execution time: 18_616_000 picoseconds. - Weight::from_parts(19_316_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn claim_child_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `576` - // Estimated: `8799` - // Minimum execution time: 96_376_000 picoseconds. - Weight::from_parts(98_476_000, 0) - .saturating_add(Weight::from_parts(0, 8799)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(6)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn close_child_bounty_added() -> Weight { // Proof Size summary in bytes: - // Measured: `840` - // Estimated: `6196` - // Minimum execution time: 64_640_000 picoseconds. - Weight::from_parts(66_174_000, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(6)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) fn close_child_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `1027` - // Estimated: `8799` - // Minimum execution time: 78_159_000 picoseconds. - Weight::from_parts(79_820_000, 0) - .saturating_add(Weight::from_parts(0, 8799)) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(7)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_conviction_voting.rs b/polkadot/runtime/rococo/src/weights/pallet_conviction_voting.rs index 5d92c158df4..ba505737f1b 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_conviction_voting.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_conviction_voting.rs @@ -16,17 +16,17 @@ //! Autogenerated weights for `pallet_conviction_voting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `runner-e8ezs4ez-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot // benchmark // pallet -// --chain=rococo-dev +// --chain=kusama-dev // --steps=50 // --repeat=20 // --no-storage-info @@ -36,8 +36,8 @@ // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/kusama/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,152 +50,144 @@ use core::marker::PhantomData; /// Weight functions for `pallet_conviction_voting`. pub struct WeightInfo(PhantomData); impl pallet_conviction_voting::WeightInfo for WeightInfo { - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(311), added: 2786, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(311), added: 2786, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `13407` + // Measured: `13445` // Estimated: `42428` - // Minimum execution time: 128_378_000 picoseconds. - Weight::from_parts(131_028_000, 0) + // Minimum execution time: 151_077_000 picoseconds. + Weight::from_parts(165_283_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(311), added: 2786, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(311), added: 2786, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `14128` + // Measured: `14166` // Estimated: `83866` - // Minimum execution time: 155_379_000 picoseconds. - Weight::from_parts(161_597_000, 0) + // Minimum execution time: 232_420_000 picoseconds. + Weight::from_parts(244_439_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(7)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) fn remove_vote() -> Weight { // Proof Size summary in bytes: // Measured: `13918` // Estimated: `83866` - // Minimum execution time: 130_885_000 picoseconds. - Weight::from_parts(138_080_000, 0) + // Minimum execution time: 205_017_000 picoseconds. + Weight::from_parts(216_594_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) fn remove_other_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `13005` + // Measured: `13004` // Estimated: `30706` - // Minimum execution time: 71_743_000 picoseconds. - Weight::from_parts(75_170_000, 0) + // Minimum execution time: 84_226_000 picoseconds. + Weight::from_parts(91_255_000, 0) .saturating_add(Weight::from_parts(0, 30706)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:512 w:512) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(311), added: 2786, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:50) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:512 w:512) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(311), added: 2786, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `r` is `[0, 512]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `29602 + r * (365 ±0)` + // Measured: `29640 + r * (365 ±0)` // Estimated: `83866 + r * (3411 ±0)` - // Minimum execution time: 58_504_000 picoseconds. - Weight::from_parts(814_301_018, 0) + // Minimum execution time: 78_708_000 picoseconds. + Weight::from_parts(2_053_488_615, 0) .saturating_add(Weight::from_parts(0, 83866)) - // Standard Error: 59_961 - .saturating_add(Weight::from_parts(20_002_833, 0).saturating_mul(r.into())) + // Standard Error: 179_271 + .saturating_add(Weight::from_parts(47_806_482, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(45)) + .saturating_add(T::DbWeight::get().writes(6)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 3411).saturating_mul(r.into())) } - /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:512 w:512) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:50) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:512 w:512) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(936), added: 3411, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) /// The range of component `r` is `[0, 512]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `29555 + r * (365 ±0)` // Estimated: `83866 + r * (3411 ±0)` - // Minimum execution time: 34_970_000 picoseconds. - Weight::from_parts(771_155_804, 0) + // Minimum execution time: 45_232_000 picoseconds. + Weight::from_parts(2_045_021_014, 0) .saturating_add(Weight::from_parts(0, 83866)) - // Standard Error: 57_795 - .saturating_add(Weight::from_parts(19_781_645, 0).saturating_mul(r.into())) + // Standard Error: 185_130 + .saturating_add(Weight::from_parts(47_896_011, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(43)) + .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 3411).saturating_mul(r.into())) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(311), added: 2786, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(311), added: 2786, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn unlock() -> Weight { // Proof Size summary in bytes: - // Measured: `12180` + // Measured: `12218` // Estimated: `30706` - // Minimum execution time: 89_648_000 picoseconds. - Weight::from_parts(97_144_000, 0) + // Minimum execution time: 116_446_000 picoseconds. + Weight::from_parts(124_043_000, 0) .saturating_add(Weight::from_parts(0, 30706)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_identity.rs b/polkadot/runtime/rococo/src/weights/pallet_identity.rs index 6df16351f2c..b334e21ea03 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_identity.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_identity.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_identity` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_identity // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,291 +47,290 @@ use core::marker::PhantomData; /// Weight functions for `pallet_identity`. pub struct WeightInfo(PhantomData); impl pallet_identity::WeightInfo for WeightInfo { - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `32 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 7_673_000 picoseconds. - Weight::from_parts(8_351_866, 0) + // Minimum execution time: 12_290_000 picoseconds. + Weight::from_parts(12_664_362, 0) .saturating_add(Weight::from_parts(0, 2626)) - // Standard Error: 1_302 - .saturating_add(Weight::from_parts(79_198, 0).saturating_mul(r.into())) + // Standard Error: 1_347 + .saturating_add(Weight::from_parts(88_179, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. fn set_identity(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6978 + r * (5 ±0)` - // Estimated: `11037` - // Minimum execution time: 111_646_000 picoseconds. - Weight::from_parts(113_254_991, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 6_611 - .saturating_add(Weight::from_parts(162_119, 0).saturating_mul(r.into())) + // Measured: `442 + r * (5 ±0)` + // Estimated: `11003` + // Minimum execution time: 31_373_000 picoseconds. + Weight::from_parts(30_435_545, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 2_307 + .saturating_add(Weight::from_parts(92_753, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:100 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:100 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `101` - // Estimated: `11037 + s * (2589 ±0)` - // Minimum execution time: 8_010_000 picoseconds. - Weight::from_parts(19_868_412, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 5_018 - .saturating_add(Weight::from_parts(3_115_007, 0).saturating_mul(s.into())) + // Estimated: `11003 + s * (2589 ±0)` + // Minimum execution time: 9_251_000 picoseconds. + Weight::from_parts(22_039_210, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 40_779 + .saturating_add(Weight::from_parts(2_898_525, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 2589).saturating_mul(s.into())) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `194 + p * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 8_111_000 picoseconds. - Weight::from_parts(19_482_392, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 3_156 - .saturating_add(Weight::from_parts(1_305_890, 0).saturating_mul(p.into())) + // Estimated: `11003` + // Minimum execution time: 9_329_000 picoseconds. + Weight::from_parts(24_055_061, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 3_428 + .saturating_add(Weight::from_parts(1_130_604, 0).saturating_mul(p.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(p.into()))) } - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. - fn clear_identity(r: u32, s: u32, ) -> Weight { + fn clear_identity(_r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7070 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 54_107_000 picoseconds. - Weight::from_parts(56_347_715, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 10_944 - .saturating_add(Weight::from_parts(191_321, 0).saturating_mul(r.into())) - // Standard Error: 2_135 - .saturating_add(Weight::from_parts(1_295_872, 0).saturating_mul(s.into())) + // Measured: `469 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 53_365_000 picoseconds. + Weight::from_parts(35_391_422, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 1_353 + .saturating_add(Weight::from_parts(1_074_019, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: `Identity::Registrars` (r:1 w:0) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:0) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. fn request_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6968 + r * (57 ±0)` - // Estimated: `11037` - // Minimum execution time: 75_780_000 picoseconds. - Weight::from_parts(76_869_773, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 5_456 - .saturating_add(Weight::from_parts(135_316, 0).saturating_mul(r.into())) + // Measured: `367 + r * (57 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 32_509_000 picoseconds. + Weight::from_parts(31_745_585, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 2_214 + .saturating_add(Weight::from_parts(83_822, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. fn cancel_request(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6999` - // Estimated: `11037` - // Minimum execution time: 75_769_000 picoseconds. - Weight::from_parts(76_805_143, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 3_598 - .saturating_add(Weight::from_parts(84_593, 0).saturating_mul(r.into())) + // Measured: `398 + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 29_609_000 picoseconds. + Weight::from_parts(28_572_602, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 2_528 + .saturating_add(Weight::from_parts(85_593, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 5_357_000 picoseconds. - Weight::from_parts(5_732_132, 0) + // Minimum execution time: 7_793_000 picoseconds. + Weight::from_parts(8_173_888, 0) .saturating_add(Weight::from_parts(0, 2626)) - // Standard Error: 927 - .saturating_add(Weight::from_parts(70_832, 0).saturating_mul(r.into())) + // Standard Error: 1_569 + .saturating_add(Weight::from_parts(72_367, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 5_484_000 picoseconds. - Weight::from_parts(5_892_704, 0) + // Minimum execution time: 7_708_000 picoseconds. + Weight::from_parts(8_091_149, 0) .saturating_add(Weight::from_parts(0, 2626)) - // Standard Error: 947 - .saturating_add(Weight::from_parts(71_231, 0).saturating_mul(r.into())) + // Standard Error: 869 + .saturating_add(Weight::from_parts(87_993, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 5_310_000 picoseconds. - Weight::from_parts(5_766_651, 0) + // Minimum execution time: 7_601_000 picoseconds. + Weight::from_parts(8_038_414, 0) .saturating_add(Weight::from_parts(0, 2626)) - // Standard Error: 916 - .saturating_add(Weight::from_parts(74_776, 0).saturating_mul(r.into())) + // Standard Error: 1_041 + .saturating_add(Weight::from_parts(82_588, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::Registrars` (r:1 w:0) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:0) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn provide_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7046 + r * (57 ±0)` - // Estimated: `11037` - // Minimum execution time: 98_200_000 picoseconds. - Weight::from_parts(100_105_482, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 6_152 - .saturating_add(Weight::from_parts(58_906, 0).saturating_mul(r.into())) + // Measured: `445 + r * (57 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 23_114_000 picoseconds. + Weight::from_parts(22_076_548, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 2_881 + .saturating_add(Weight::from_parts(109_812, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. fn kill_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7277 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 64_647_000 picoseconds. - Weight::from_parts(68_877_027, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 9_965 - .saturating_add(Weight::from_parts(135_044, 0).saturating_mul(r.into())) - // Standard Error: 1_944 - .saturating_add(Weight::from_parts(1_388_151, 0).saturating_mul(s.into())) + // Measured: `676 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 70_007_000 picoseconds. + Weight::from_parts(50_186_495, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 6_533 + .saturating_add(Weight::from_parts(15_486, 0).saturating_mul(r.into())) + // Standard Error: 1_275 + .saturating_add(Weight::from_parts(1_085_117, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `475 + s * (36 ±0)` - // Estimated: `11037` - // Minimum execution time: 23_550_000 picoseconds. - Weight::from_parts(29_439_842, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 1_453 - .saturating_add(Weight::from_parts(96_324, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 28_453_000 picoseconds. + Weight::from_parts(33_165_934, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 1_217 + .saturating_add(Weight::from_parts(65_401, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `591 + s * (3 ±0)` - // Estimated: `11037` - // Minimum execution time: 13_704_000 picoseconds. - Weight::from_parts(15_241_441, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 498 - .saturating_add(Weight::from_parts(40_973, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 12_846_000 picoseconds. + Weight::from_parts(14_710_284, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 496 + .saturating_add(Weight::from_parts(19_539, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `638 + s * (35 ±0)` - // Estimated: `11037` - // Minimum execution time: 29_310_000 picoseconds. - Weight::from_parts(31_712_666, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 967 - .saturating_add(Weight::from_parts(81_250, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 32_183_000 picoseconds. + Weight::from_parts(35_296_731, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 854 + .saturating_add(Weight::from_parts(52_028, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `704 + s * (37 ±0)` // Estimated: `6723` - // Minimum execution time: 22_906_000 picoseconds. - Weight::from_parts(24_638_729, 0) + // Minimum execution time: 24_941_000 picoseconds. + Weight::from_parts(27_433_059, 0) .saturating_add(Weight::from_parts(0, 6723)) - // Standard Error: 645 - .saturating_add(Weight::from_parts(75_121, 0).saturating_mul(s.into())) + // Standard Error: 856 + .saturating_add(Weight::from_parts(57_463, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -344,93 +340,90 @@ impl pallet_identity::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_056_000 picoseconds. - Weight::from_parts(6_349_000, 0) + // Minimum execution time: 13_873_000 picoseconds. + Weight::from_parts(13_873_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) + /// Storage: `Identity::UsernameAuthorities` (r:0 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn remove_username_authority() -> Weight { // Proof Size summary in bytes: - // Measured: `80` - // Estimated: `3517` - // Minimum execution time: 9_003_000 picoseconds. - Weight::from_parts(9_276_000, 0) - .saturating_add(Weight::from_parts(0, 3517)) - .saturating_add(T::DbWeight::get().reads(1)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_653_000 picoseconds. + Weight::from_parts(10_653_000, 0) + .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Identity::PendingUsernames` (r:1 w:0) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_username_for() -> Weight { // Proof Size summary in bytes: // Measured: `80` // Estimated: `11037` - // Minimum execution time: 64_724_000 picoseconds. - Weight::from_parts(66_597_000, 0) + // Minimum execution time: 75_928_000 picoseconds. + Weight::from_parts(75_928_000, 0) .saturating_add(Weight::from_parts(0, 11037)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:0 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn accept_username() -> Weight { // Proof Size summary in bytes: - // Measured: `115` + // Measured: `106` // Estimated: `11037` - // Minimum execution time: 19_538_000 picoseconds. - Weight::from_parts(20_204_000, 0) + // Minimum execution time: 38_157_000 picoseconds. + Weight::from_parts(38_157_000, 0) .saturating_add(Weight::from_parts(0, 11037)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) fn remove_expired_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `115` - // Estimated: `3550` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(19_354_000, 0) - .saturating_add(Weight::from_parts(0, 3550)) + // Measured: `106` + // Estimated: `3542` + // Minimum execution time: 46_821_000 picoseconds. + Weight::from_parts(46_821_000, 0) + .saturating_add(Weight::from_parts(0, 3542)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:0) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_primary_username() -> Weight { // Proof Size summary in bytes: - // Measured: `257` + // Measured: `247` // Estimated: `11037` - // Minimum execution time: 15_298_000 picoseconds. - Weight::from_parts(15_760_000, 0) + // Minimum execution time: 22_515_000 picoseconds. + Weight::from_parts(22_515_000, 0) .saturating_add(Weight::from_parts(0, 11037)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:0) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn remove_dangling_username() -> Weight { // Proof Size summary in bytes: - // Measured: `98` + // Measured: `126` // Estimated: `11037` - // Minimum execution time: 10_829_000 picoseconds. - Weight::from_parts(11_113_000, 0) + // Minimum execution time: 15_997_000 picoseconds. + Weight::from_parts(15_997_000, 0) .saturating_add(Weight::from_parts(0, 11037)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_indices.rs b/polkadot/runtime/rococo/src/weights/pallet_indices.rs index 434db97d4a7..99ffd3210ed 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_indices.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_indices.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_indices` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_indices // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,66 +47,66 @@ use core::marker::PhantomData; /// Weight functions for `pallet_indices`. pub struct WeightInfo(PhantomData); impl pallet_indices::WeightInfo for WeightInfo { - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn claim() -> Weight { // Proof Size summary in bytes: - // Measured: `4` + // Measured: `142` // Estimated: `3534` - // Minimum execution time: 18_092_000 picoseconds. - Weight::from_parts(18_533_000, 0) + // Minimum execution time: 25_107_000 picoseconds. + Weight::from_parts(25_655_000, 0) .saturating_add(Weight::from_parts(0, 3534)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `203` + // Measured: `341` // Estimated: `3593` - // Minimum execution time: 31_616_000 picoseconds. - Weight::from_parts(32_556_000, 0) + // Minimum execution time: 36_208_000 picoseconds. + Weight::from_parts(36_521_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn free() -> Weight { // Proof Size summary in bytes: - // Measured: `100` + // Measured: `238` // Estimated: `3534` - // Minimum execution time: 19_593_000 picoseconds. - Weight::from_parts(20_100_000, 0) + // Minimum execution time: 25_915_000 picoseconds. + Weight::from_parts(26_220_000, 0) .saturating_add(Weight::from_parts(0, 3534)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn force_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `203` + // Measured: `341` // Estimated: `3593` - // Minimum execution time: 21_429_000 picoseconds. - Weight::from_parts(22_146_000, 0) + // Minimum execution time: 28_232_000 picoseconds. + Weight::from_parts(28_845_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn freeze() -> Weight { // Proof Size summary in bytes: - // Measured: `100` + // Measured: `238` // Estimated: `3534` - // Minimum execution time: 20_425_000 picoseconds. - Weight::from_parts(21_023_000, 0) + // Minimum execution time: 27_282_000 picoseconds. + Weight::from_parts(27_754_000, 0) .saturating_add(Weight::from_parts(0, 3534)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_message_queue.rs b/polkadot/runtime/rococo/src/weights/pallet_message_queue.rs index 6ebfcd060b6..e1e360d374a 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_message_queue.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_message_queue.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_message_queue` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_message_queue // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,149 +47,150 @@ use core::marker::PhantomData; /// Weight functions for `pallet_message_queue`. pub struct WeightInfo(PhantomData); impl pallet_message_queue::WeightInfo for WeightInfo { - /// Storage: `MessageQueue::ServiceHead` (r:1 w:0) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(6), added: 501, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(6), added: 501, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) fn ready_ring_knit() -> Weight { // Proof Size summary in bytes: - // Measured: `281` + // Measured: `248` // Estimated: `6050` - // Minimum execution time: 12_830_000 picoseconds. - Weight::from_parts(13_476_000, 0) + // Minimum execution time: 12_106_000 picoseconds. + Weight::from_parts(12_387_000, 0) .saturating_add(Weight::from_parts(0, 6050)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(6), added: 501, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(6), added: 501, mode: MaxEncodedLen) fn ready_ring_unknit() -> Weight { // Proof Size summary in bytes: - // Measured: `281` + // Measured: `248` // Estimated: `6050` - // Minimum execution time: 11_583_000 picoseconds. - Weight::from_parts(11_902_000, 0) + // Minimum execution time: 11_227_000 picoseconds. + Weight::from_parts(11_616_000, 0) .saturating_add(Weight::from_parts(0, 6050)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) fn service_queue_base() -> Weight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3520` - // Minimum execution time: 3_801_000 picoseconds. - Weight::from_parts(3_943_000, 0) + // Minimum execution time: 5_052_000 picoseconds. + Weight::from_parts(5_216_000, 0) .saturating_add(Weight::from_parts(0, 3520)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) fn service_page_base_completion() -> Weight { // Proof Size summary in bytes: // Measured: `115` // Estimated: `36283` - // Minimum execution time: 5_517_000 picoseconds. - Weight::from_parts(5_861_000, 0) + // Minimum execution time: 6_522_000 picoseconds. + Weight::from_parts(6_794_000, 0) .saturating_add(Weight::from_parts(0, 36283)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) fn service_page_base_no_completion() -> Weight { // Proof Size summary in bytes: // Measured: `115` // Estimated: `36283` - // Minimum execution time: 5_870_000 picoseconds. - Weight::from_parts(6_028_000, 0) + // Minimum execution time: 6_918_000 picoseconds. + Weight::from_parts(7_083_000, 0) .saturating_add(Weight::from_parts(0, 36283)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `MessageQueue::BookStateFor` (r:0 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:0 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) fn service_page_item() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 80_681_000 picoseconds. - Weight::from_parts(81_818_000, 0) + // Minimum execution time: 28_445_000 picoseconds. + Weight::from_parts(28_659_000, 0) .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(6), added: 501, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(6), added: 501, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:0) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) fn bump_service_head() -> Weight { // Proof Size summary in bytes: - // Measured: `220` + // Measured: `149` // Estimated: `3520` - // Minimum execution time: 8_641_000 picoseconds. - Weight::from_parts(8_995_000, 0) + // Minimum execution time: 7_224_000 picoseconds. + Weight::from_parts(7_441_000, 0) .saturating_add(Weight::from_parts(0, 3520)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Storage: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) - /// Proof: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Proof Skipped: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Storage: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Proof Skipped: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) fn reap_page() -> Weight { // Proof Size summary in bytes: - // Measured: `32945` + // Measured: `33232` // Estimated: `36283` - // Minimum execution time: 38_473_000 picoseconds. - Weight::from_parts(39_831_000, 0) + // Minimum execution time: 45_211_000 picoseconds. + Weight::from_parts(45_505_000, 0) .saturating_add(Weight::from_parts(0, 36283)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Storage: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) - /// Proof: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Proof Skipped: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Storage: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Proof Skipped: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) fn execute_overweight_page_removed() -> Weight { // Proof Size summary in bytes: - // Measured: `32945` + // Measured: `33232` // Estimated: `36283` - // Minimum execution time: 48_717_000 picoseconds. - Weight::from_parts(49_724_000, 0) + // Minimum execution time: 52_346_000 picoseconds. + Weight::from_parts(52_745_000, 0) .saturating_add(Weight::from_parts(0, 36283)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Storage: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) - /// Proof: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Proof Skipped: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Storage: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Proof Skipped: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) fn execute_overweight_page_updated() -> Weight { // Proof Size summary in bytes: - // Measured: `32945` + // Measured: `33232` // Estimated: `36283` - // Minimum execution time: 72_718_000 picoseconds. - Weight::from_parts(74_081_000, 0) + // Minimum execution time: 72_567_000 picoseconds. + Weight::from_parts(73_300_000, 0) .saturating_add(Weight::from_parts(0, 36283)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(4)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_multisig.rs b/polkadot/runtime/rococo/src/weights/pallet_multisig.rs index f1b81759ece..a4f33fe198c 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_multisig.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_multisig.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_multisig // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,110 +52,110 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_023_000 picoseconds. - Weight::from_parts(12_643_116, 0) + // Minimum execution time: 11_475_000 picoseconds. + Weight::from_parts(11_904_745, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 3 - .saturating_add(Weight::from_parts(582, 0).saturating_mul(z.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(492, 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`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `229 + s * (2 ±0)` + // Measured: `193 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 39_339_000 picoseconds. - Weight::from_parts(27_243_033, 0) + // Minimum execution time: 38_857_000 picoseconds. + Weight::from_parts(33_611_791, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_319 - .saturating_add(Weight::from_parts(142_212, 0).saturating_mul(s.into())) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_592, 0).saturating_mul(z.into())) + // Standard Error: 400 + .saturating_add(Weight::from_parts(59_263, 0).saturating_mul(s.into())) + // Standard Error: 3 + .saturating_add(Weight::from_parts(1_211, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248` + // Measured: `211` // Estimated: `6811` - // Minimum execution time: 27_647_000 picoseconds. - Weight::from_parts(15_828_725, 0) + // Minimum execution time: 25_715_000 picoseconds. + Weight::from_parts(20_607_294, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 908 - .saturating_add(Weight::from_parts(130_880, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_532, 0).saturating_mul(z.into())) + // Standard Error: 285 + .saturating_add(Weight::from_parts(58_225, 0).saturating_mul(s.into())) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_160, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `354 + s * (33 ±0)` + // Measured: `317 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 46_971_000 picoseconds. - Weight::from_parts(32_150_393, 0) + // Minimum execution time: 43_751_000 picoseconds. + Weight::from_parts(37_398_513, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_129 - .saturating_add(Weight::from_parts(154_796, 0).saturating_mul(s.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(1_603, 0).saturating_mul(z.into())) + // Standard Error: 426 + .saturating_add(Weight::from_parts(70_904, 0).saturating_mul(s.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(1_235, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `229 + s * (2 ±0)` + // Measured: `193 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 24_947_000 picoseconds. - Weight::from_parts(26_497_183, 0) + // Minimum execution time: 31_278_000 picoseconds. + Weight::from_parts(32_075_573, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_615 - .saturating_add(Weight::from_parts(147_071, 0).saturating_mul(s.into())) + // Standard Error: 452 + .saturating_add(Weight::from_parts(62_018, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248` + // Measured: `211` // Estimated: `6811` - // Minimum execution time: 13_897_000 picoseconds. - Weight::from_parts(14_828_339, 0) + // Minimum execution time: 18_178_000 picoseconds. + Weight::from_parts(18_649_867, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_136 - .saturating_add(Weight::from_parts(133_925, 0).saturating_mul(s.into())) + // Standard Error: 293 + .saturating_add(Weight::from_parts(56_475, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `420 + s * (1 ±0)` + // Measured: `383 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 28_984_000 picoseconds. - Weight::from_parts(29_853_232, 0) + // Minimum execution time: 32_265_000 picoseconds. + Weight::from_parts(32_984_014, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 650 - .saturating_add(Weight::from_parts(113_440, 0).saturating_mul(s.into())) + // Standard Error: 452 + .saturating_add(Weight::from_parts(59_934, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_nis.rs b/polkadot/runtime/rococo/src/weights/pallet_nis.rs index 38b41f3a8e2..35dad482129 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_nis.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_nis.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_nis` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_nis // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,186 +47,202 @@ use core::marker::PhantomData; /// Weight functions for `pallet_nis`. pub struct WeightInfo(PhantomData); impl pallet_nis::WeightInfo for WeightInfo { - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) /// The range of component `l` is `[0, 999]`. fn place_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6209 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 39_592_000 picoseconds. - Weight::from_parts(38_234_037, 0) + // Minimum execution time: 44_704_000 picoseconds. + Weight::from_parts(44_933_886, 0) .saturating_add(Weight::from_parts(0, 51487)) - // Standard Error: 1_237 - .saturating_add(Weight::from_parts(88_816, 0).saturating_mul(l.into())) + // Standard Error: 712 + .saturating_add(Weight::from_parts(71_570, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) fn place_bid_max() -> Weight { // Proof Size summary in bytes: // Measured: `54211` // Estimated: `51487` - // Minimum execution time: 134_847_000 picoseconds. - Weight::from_parts(139_510_000, 0) + // Minimum execution time: 126_544_000 picoseconds. + Weight::from_parts(128_271_000, 0) .saturating_add(Weight::from_parts(0, 51487)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) /// The range of component `l` is `[1, 1000]`. fn retract_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6209 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 43_330_000 picoseconds. - Weight::from_parts(35_097_881, 0) + // Minimum execution time: 47_640_000 picoseconds. + Weight::from_parts(42_214_261, 0) .saturating_add(Weight::from_parts(0, 51487)) - // Standard Error: 1_119 - .saturating_add(Weight::from_parts(73_640, 0).saturating_mul(l.into())) + // Standard Error: 732 + .saturating_add(Weight::from_parts(87_277, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Nis::Summary` (r:1 w:0) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Nis Summary (r:1 w:0) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: Balances InactiveIssuance (r:1 w:0) + /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn fund_deficit() -> Weight { // Proof Size summary in bytes: // Measured: `225` // Estimated: `3593` - // Minimum execution time: 29_989_000 picoseconds. - Weight::from_parts(30_865_000, 0) + // Minimum execution time: 38_031_000 picoseconds. + Weight::from_parts(38_441_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `NisCounterpartBalances::Account` (r:1 w:1) - /// Proof: `NisCounterpartBalances::Account` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + /// Proof: NisCounterpartBalances TotalIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: NisCounterpartBalances Account (r:1 w:1) + /// Proof: NisCounterpartBalances Account (max_values: None, max_size: Some(112), added: 2587, mode: MaxEncodedLen) fn communify() -> Weight { // Proof Size summary in bytes: - // Measured: `387` + // Measured: `469` // Estimated: `3593` - // Minimum execution time: 58_114_000 picoseconds. - Weight::from_parts(59_540_000, 0) + // Minimum execution time: 69_269_000 picoseconds. + Weight::from_parts(70_000_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `NisCounterpartBalances::Account` (r:1 w:1) - /// Proof: `NisCounterpartBalances::Account` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: Balances InactiveIssuance (r:1 w:0) + /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: NisCounterpartBalances Account (r:1 w:1) + /// Proof: NisCounterpartBalances Account (max_values: None, max_size: Some(112), added: 2587, mode: MaxEncodedLen) + /// Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + /// Proof: NisCounterpartBalances TotalIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) fn privatize() -> Weight { // Proof Size summary in bytes: - // Measured: `543` + // Measured: `659` // Estimated: `3593` - // Minimum execution time: 75_780_000 picoseconds. - Weight::from_parts(77_097_000, 0) + // Minimum execution time: 85_763_000 picoseconds. + Weight::from_parts(86_707_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: Balances InactiveIssuance (r:1 w:0) + /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(67), added: 2542, mode: MaxEncodedLen) fn thaw_private() -> Weight { // Proof Size summary in bytes: // Measured: `387` // Estimated: `3593` - // Minimum execution time: 46_133_000 picoseconds. - Weight::from_parts(47_250_000, 0) + // Minimum execution time: 47_336_000 picoseconds. + Weight::from_parts(47_623_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `NisCounterpartBalances::Account` (r:1 w:1) - /// Proof: `NisCounterpartBalances::Account` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: NisCounterpartBalances Account (r:1 w:1) + /// Proof: NisCounterpartBalances Account (max_values: None, max_size: Some(112), added: 2587, mode: MaxEncodedLen) + /// Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + /// Proof: NisCounterpartBalances TotalIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Balances InactiveIssuance (r:1 w:0) + /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn thaw_communal() -> Weight { // Proof Size summary in bytes: - // Measured: `488` + // Measured: `604` // Estimated: `3593` - // Minimum execution time: 77_916_000 picoseconds. - Weight::from_parts(79_427_000, 0) + // Minimum execution time: 90_972_000 picoseconds. + Weight::from_parts(92_074_000, 0) .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: Balances InactiveIssuance (r:1 w:0) + /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) fn process_queues() -> Weight { // Proof Size summary in bytes: // Measured: `6658` // Estimated: `7487` - // Minimum execution time: 22_992_000 picoseconds. - Weight::from_parts(24_112_000, 0) + // Minimum execution time: 21_469_000 picoseconds. + Weight::from_parts(21_983_000, 0) .saturating_add(Weight::from_parts(0, 7487)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) fn process_queue() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `51487` - // Minimum execution time: 3_856_000 picoseconds. - Weight::from_parts(4_125_000, 0) + // Minimum execution time: 4_912_000 picoseconds. + Weight::from_parts(5_013_000, 0) .saturating_add(Weight::from_parts(0, 51487)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Nis::Receipts` (r:0 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:0 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) fn process_bid() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_344_000 picoseconds. - Weight::from_parts(4_545_000, 0) + // Minimum execution time: 7_048_000 picoseconds. + Weight::from_parts(7_278_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_preimage.rs b/polkadot/runtime/rococo/src/weights/pallet_preimage.rs index 7a2b77b84d8..e051ebd5bba 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_preimage.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_preimage.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_preimage` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_preimage // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,219 +47,184 @@ use core::marker::PhantomData; /// Weight functions for `pallet_preimage`. pub struct WeightInfo(PhantomData); impl pallet_preimage::WeightInfo for WeightInfo { - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) - /// Storage: `Preimage::PreimageFor` (r:0 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) + fn ensure_updated(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `193 + n * (91 ±0)` + // Estimated: `3593 + n * (2566 ±0)` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3593) + // Standard Error: 13_720 + .saturating_add(Weight::from_parts(17_309_199, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2566).saturating_mul(n.into())) + } + + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `114` - // Estimated: `3568` - // Minimum execution time: 40_363_000 picoseconds. - Weight::from_parts(41_052_000, 0) - .saturating_add(Weight::from_parts(0, 3568)) - // Standard Error: 6 - .saturating_add(Weight::from_parts(2_298, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `215` + // Estimated: `3556` + // Minimum execution time: 31_040_000 picoseconds. + Weight::from_parts(31_236_000, 0) + .saturating_add(Weight::from_parts(0, 3556)) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_974, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::PreimageFor` (r:0 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 14_570_000 picoseconds. - Weight::from_parts(14_890_000, 0) + // Minimum execution time: 18_025_000 picoseconds. + Weight::from_parts(18_264_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(2_364, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_974, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::PreimageFor` (r:0 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 13_933_000 picoseconds. - Weight::from_parts(14_290_000, 0) + // Minimum execution time: 17_122_000 picoseconds. + Weight::from_parts(17_332_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(2_349, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_968, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) - /// Storage: `Preimage::PreimageFor` (r:0 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) fn unnote_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `315` - // Estimated: `3568` - // Minimum execution time: 54_373_000 picoseconds. - Weight::from_parts(58_205_000, 0) - .saturating_add(Weight::from_parts(0, 3568)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `361` + // Estimated: `3556` + // Minimum execution time: 38_218_000 picoseconds. + Weight::from_parts(39_841_000, 0) + .saturating_add(Weight::from_parts(0, 3556)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::PreimageFor` (r:0 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) fn unnote_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3556` - // Minimum execution time: 24_267_000 picoseconds. - Weight::from_parts(27_063_000, 0) + // Minimum execution time: 23_217_000 picoseconds. + Weight::from_parts(24_246_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn request_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `260` // Estimated: `3556` - // Minimum execution time: 25_569_000 picoseconds. - Weight::from_parts(27_895_000, 0) + // Minimum execution time: 21_032_000 picoseconds. + Weight::from_parts(21_844_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn request_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3556` - // Minimum execution time: 14_182_000 picoseconds. - Weight::from_parts(16_098_000, 0) + // Minimum execution time: 13_954_000 picoseconds. + Weight::from_parts(14_501_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn request_unnoted_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `114` // Estimated: `3556` - // Minimum execution time: 14_681_000 picoseconds. - Weight::from_parts(15_549_000, 0) + // Minimum execution time: 14_874_000 picoseconds. + Weight::from_parts(15_380_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn request_requested_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 9_577_000 picoseconds. - Weight::from_parts(10_146_000, 0) + // Minimum execution time: 10_199_000 picoseconds. + Weight::from_parts(10_493_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::PreimageFor` (r:0 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) fn unrequest_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3556` - // Minimum execution time: 21_003_000 picoseconds. - Weight::from_parts(23_549_000, 0) + // Minimum execution time: 21_772_000 picoseconds. + Weight::from_parts(22_554_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn unrequest_unnoted_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 9_507_000 picoseconds. - Weight::from_parts(10_013_000, 0) + // Minimum execution time: 10_115_000 picoseconds. + Weight::from_parts(10_452_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn unrequest_multi_referenced_preimage() -> Weight { // Proof Size summary in bytes: // Measured: `178` // Estimated: `3556` - // Minimum execution time: 9_293_000 picoseconds. - Weight::from_parts(10_055_000, 0) + // Minimum execution time: 10_031_000 picoseconds. + Weight::from_parts(10_310_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Preimage::StatusFor` (r:1023 w:1023) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1023 w:1023) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1023 w:1023) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:0 w:1023) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// The range of component `n` is `[1, 1024]`. - fn ensure_updated(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + n * (227 ±0)` - // Estimated: `990 + n * (2603 ±0)` - // Minimum execution time: 48_846_000 picoseconds. - Weight::from_parts(49_378_000, 0) - .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 38_493 - .saturating_add(Weight::from_parts(47_418_285, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2603).saturating_mul(n.into())) - } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_proxy.rs b/polkadot/runtime/rococo/src/weights/pallet_proxy.rs index c9202593095..d9737a85c05 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_proxy.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_proxy.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_proxy` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_proxy // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,176 +47,172 @@ use core::marker::PhantomData; /// Weight functions for `pallet_proxy`. pub struct WeightInfo(PhantomData); impl pallet_proxy::WeightInfo for WeightInfo { - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `89 + p * (37 ±0)` + // Measured: `227 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 11_267_000 picoseconds. - Weight::from_parts(11_798_007, 0) + // Minimum execution time: 15_956_000 picoseconds. + Weight::from_parts(16_300_358, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 858 - .saturating_add(Weight::from_parts(43_735, 0).saturating_mul(p.into())) + // Standard Error: 652 + .saturating_add(Weight::from_parts(30_807, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) } - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `416 + a * (68 ±0) + p * (37 ±0)` + // Measured: `554 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 32_791_000 picoseconds. - Weight::from_parts(32_776_904, 0) + // Minimum execution time: 37_584_000 picoseconds. + Weight::from_parts(37_858_207, 0) .saturating_add(Weight::from_parts(0, 5698)) - // Standard Error: 2_382 - .saturating_add(Weight::from_parts(143_857, 0).saturating_mul(a.into())) - // Standard Error: 2_461 - .saturating_add(Weight::from_parts(40_024, 0).saturating_mul(p.into())) + // Standard Error: 1_868 + .saturating_add(Weight::from_parts(148_967, 0).saturating_mul(a.into())) + // Standard Error: 1_930 + .saturating_add(Weight::from_parts(13_017, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. - fn remove_announcement(a: u32, p: u32, ) -> Weight { + fn remove_announcement(a: u32, _p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `331 + a * (68 ±0)` + // Measured: `469 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 21_831_000 picoseconds. - Weight::from_parts(22_479_938, 0) + // Minimum execution time: 24_642_000 picoseconds. + Weight::from_parts(25_526_588, 0) .saturating_add(Weight::from_parts(0, 5698)) - // Standard Error: 1_738 - .saturating_add(Weight::from_parts(146_532, 0).saturating_mul(a.into())) - // Standard Error: 1_796 - .saturating_add(Weight::from_parts(7_499, 0).saturating_mul(p.into())) + // Standard Error: 1_138 + .saturating_add(Weight::from_parts(131_157, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. - fn reject_announcement(a: u32, p: u32, ) -> Weight { + fn reject_announcement(a: u32, _p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `331 + a * (68 ±0)` + // Measured: `469 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 21_776_000 picoseconds. - Weight::from_parts(22_762_843, 0) + // Minimum execution time: 24_377_000 picoseconds. + Weight::from_parts(25_464_033, 0) .saturating_add(Weight::from_parts(0, 5698)) - // Standard Error: 1_402 - .saturating_add(Weight::from_parts(137_512, 0).saturating_mul(a.into())) - // Standard Error: 1_449 - .saturating_add(Weight::from_parts(3_645, 0).saturating_mul(p.into())) + // Standard Error: 1_116 + .saturating_add(Weight::from_parts(130_722, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `348 + a * (68 ±0) + p * (37 ±0)` + // Measured: `486 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 29_108_000 picoseconds. - Weight::from_parts(29_508_910, 0) + // Minimum execution time: 34_202_000 picoseconds. + Weight::from_parts(34_610_079, 0) .saturating_add(Weight::from_parts(0, 5698)) - // Standard Error: 2_268 - .saturating_add(Weight::from_parts(144_770, 0).saturating_mul(a.into())) - // Standard Error: 2_343 - .saturating_add(Weight::from_parts(25_851, 0).saturating_mul(p.into())) + // Standard Error: 1_234 + .saturating_add(Weight::from_parts(134_197, 0).saturating_mul(a.into())) + // Standard Error: 1_275 + .saturating_add(Weight::from_parts(15_970, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `89 + p * (37 ±0)` + // Measured: `227 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 18_942_000 picoseconds. - Weight::from_parts(19_518_812, 0) + // Minimum execution time: 25_492_000 picoseconds. + Weight::from_parts(25_984_867, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 1_078 - .saturating_add(Weight::from_parts(46_147, 0).saturating_mul(p.into())) + // Standard Error: 893 + .saturating_add(Weight::from_parts(51_868, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `89 + p * (37 ±0)` + // Measured: `227 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 18_993_000 picoseconds. - Weight::from_parts(19_871_741, 0) + // Minimum execution time: 25_492_000 picoseconds. + Weight::from_parts(26_283_445, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 1_883 - .saturating_add(Weight::from_parts(46_033, 0).saturating_mul(p.into())) + // Standard Error: 1_442 + .saturating_add(Weight::from_parts(53_504, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `89 + p * (37 ±0)` + // Measured: `227 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 17_849_000 picoseconds. - Weight::from_parts(18_776_170, 0) + // Minimum execution time: 22_083_000 picoseconds. + Weight::from_parts(22_688_835, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 1_239 - .saturating_add(Weight::from_parts(27_960, 0).saturating_mul(p.into())) + // Standard Error: 994 + .saturating_add(Weight::from_parts(32_994, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `101` + // Measured: `239` // Estimated: `4706` - // Minimum execution time: 20_049_000 picoseconds. - Weight::from_parts(20_881_515, 0) + // Minimum execution time: 27_042_000 picoseconds. + Weight::from_parts(27_624_587, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 952 - .saturating_add(Weight::from_parts(5_970, 0).saturating_mul(p.into())) + // Standard Error: 671 + .saturating_add(Weight::from_parts(5_888, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `126 + p * (37 ±0)` + // Measured: `264 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 18_528_000 picoseconds. - Weight::from_parts(19_384_189, 0) + // Minimum execution time: 23_396_000 picoseconds. + Weight::from_parts(24_003_080, 0) .saturating_add(Weight::from_parts(0, 4706)) - // Standard Error: 1_106 - .saturating_add(Weight::from_parts(35_698, 0).saturating_mul(p.into())) + // Standard Error: 684 + .saturating_add(Weight::from_parts(29_878, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_ranked_collective.rs b/polkadot/runtime/rococo/src/weights/pallet_ranked_collective.rs index fa2decb1671..ce9d5fcc0c7 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_ranked_collective.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_ranked_collective.rs @@ -16,26 +16,24 @@ //! Autogenerated weights for `pallet_ranked_collective` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_ranked_collective // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_ranked_collective +// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -62,8 +60,8 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `42` // Estimated: `3507` - // Minimum execution time: 13_428_000 picoseconds. - Weight::from_parts(14_019_000, 0) + // Minimum execution time: 13_480_000 picoseconds. + Weight::from_parts(13_786_000, 0) .saturating_add(Weight::from_parts(0, 3507)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) @@ -81,11 +79,11 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `516 + r * (281 ±0)` // Estimated: `3519 + r * (2529 ±0)` - // Minimum execution time: 28_566_000 picoseconds. - Weight::from_parts(29_346_952, 0) + // Minimum execution time: 28_771_000 picoseconds. + Weight::from_parts(29_256_825, 0) .saturating_add(Weight::from_parts(0, 3519)) - // Standard Error: 21_068 - .saturating_add(Weight::from_parts(14_471_237, 0).saturating_mul(r.into())) + // Standard Error: 21_594 + .saturating_add(Weight::from_parts(14_649_527, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(6)) @@ -105,11 +103,11 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `214 + r * (17 ±0)` // Estimated: `3507` - // Minimum execution time: 16_161_000 picoseconds. - Weight::from_parts(16_981_334, 0) + // Minimum execution time: 16_117_000 picoseconds. + Weight::from_parts(16_978_453, 0) .saturating_add(Weight::from_parts(0, 3507)) - // Standard Error: 4_596 - .saturating_add(Weight::from_parts(313_386, 0).saturating_mul(r.into())) + // Standard Error: 4_511 + .saturating_add(Weight::from_parts(324_261, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -126,11 +124,11 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `532 + r * (72 ±0)` // Estimated: `3519` - // Minimum execution time: 28_406_000 picoseconds. - Weight::from_parts(31_178_557, 0) + // Minimum execution time: 28_995_000 picoseconds. + Weight::from_parts(31_343_215, 0) .saturating_add(Weight::from_parts(0, 3519)) - // Standard Error: 17_737 - .saturating_add(Weight::from_parts(627_757, 0).saturating_mul(r.into())) + // Standard Error: 16_438 + .saturating_add(Weight::from_parts(637_462, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(6)) } @@ -142,17 +140,15 @@ impl pallet_ranked_collective::WeightInfo for WeightInf /// Proof: `FellowshipCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn vote() -> Weight { // Proof Size summary in bytes: // Measured: `603` // Estimated: `83866` - // Minimum execution time: 41_164_000 picoseconds. - Weight::from_parts(42_163_000, 0) + // Minimum execution time: 38_820_000 picoseconds. + Weight::from_parts(40_240_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:0) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -165,11 +161,11 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `400 + n * (50 ±0)` // Estimated: `4365 + n * (2540 ±0)` - // Minimum execution time: 13_183_000 picoseconds. - Weight::from_parts(15_604_064, 0) + // Minimum execution time: 12_972_000 picoseconds. + Weight::from_parts(15_829_333, 0) .saturating_add(Weight::from_parts(0, 4365)) - // Standard Error: 2_018 - .saturating_add(Weight::from_parts(1_101_088, 0).saturating_mul(n.into())) + // Standard Error: 1_754 + .saturating_add(Weight::from_parts(1_116_520, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -187,8 +183,8 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Proof Size summary in bytes: // Measured: `337` // Estimated: `6048` - // Minimum execution time: 43_603_000 picoseconds. - Weight::from_parts(44_809_000, 0) + // Minimum execution time: 44_601_000 picoseconds. + Weight::from_parts(45_714_000, 0) .saturating_add(Weight::from_parts(0, 6048)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(10)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_recovery.rs b/polkadot/runtime/rococo/src/weights/pallet_recovery.rs deleted file mode 100644 index ed79aa2b1f1..00000000000 --- a/polkadot/runtime/rococo/src/weights/pallet_recovery.rs +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Autogenerated weights for `pallet_recovery` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=rococo-dev -// --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_recovery -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ - -#![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_recovery`. -pub struct WeightInfo(PhantomData); -impl pallet_recovery::WeightInfo for WeightInfo { - /// Storage: `Recovery::Proxy` (r:1 w:0) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) - fn as_recovered() -> Weight { - // Proof Size summary in bytes: - // Measured: `215` - // Estimated: `3545` - // Minimum execution time: 7_899_000 picoseconds. - Weight::from_parts(8_205_000, 0) - .saturating_add(Weight::from_parts(0, 3545)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `Recovery::Proxy` (r:0 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) - fn set_recovered() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_258_000 picoseconds. - Weight::from_parts(6_494_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `Recovery::Recoverable` (r:1 w:1) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// The range of component `n` is `[1, 9]`. - fn create_recovery(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `3816` - // Minimum execution time: 19_369_000 picoseconds. - Weight::from_parts(20_185_132, 0) - .saturating_add(Weight::from_parts(0, 3816)) - // Standard Error: 4_275 - .saturating_add(Weight::from_parts(78_024, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - fn initiate_recovery() -> Weight { - // Proof Size summary in bytes: - // Measured: `206` - // Estimated: `3854` - // Minimum execution time: 22_425_000 picoseconds. - Weight::from_parts(23_171_000, 0) - .saturating_add(Weight::from_parts(0, 3854)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// The range of component `n` is `[1, 9]`. - fn vouch_recovery(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `294 + n * (64 ±0)` - // Estimated: `3854` - // Minimum execution time: 17_308_000 picoseconds. - Weight::from_parts(18_118_782, 0) - .saturating_add(Weight::from_parts(0, 3854)) - // Standard Error: 4_309 - .saturating_add(Weight::from_parts(126_278, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `Recovery::Proxy` (r:1 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) - /// The range of component `n` is `[1, 9]`. - fn claim_recovery(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `326 + n * (64 ±0)` - // Estimated: `3854` - // Minimum execution time: 20_755_000 picoseconds. - Weight::from_parts(21_821_713, 0) - .saturating_add(Weight::from_parts(0, 3854)) - // Standard Error: 4_550 - .saturating_add(Weight::from_parts(101_916, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// The range of component `n` is `[1, 9]`. - fn close_recovery(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `447 + n * (32 ±0)` - // Estimated: `3854` - // Minimum execution time: 29_957_000 picoseconds. - Weight::from_parts(31_010_309, 0) - .saturating_add(Weight::from_parts(0, 3854)) - // Standard Error: 5_913 - .saturating_add(Weight::from_parts(110_070, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `Recovery::Recoverable` (r:1 w:1) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// The range of component `n` is `[1, 9]`. - fn remove_recovery(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `204 + n * (32 ±0)` - // Estimated: `3854` - // Minimum execution time: 24_430_000 picoseconds. - Weight::from_parts(24_462_856, 0) - .saturating_add(Weight::from_parts(0, 3854)) - // Standard Error: 13_646 - .saturating_add(Weight::from_parts(507_715, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `Recovery::Proxy` (r:1 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) - fn cancel_recovered() -> Weight { - // Proof Size summary in bytes: - // Measured: `215` - // Estimated: `3545` - // Minimum execution time: 9_686_000 picoseconds. - Weight::from_parts(10_071_000, 0) - .saturating_add(Weight::from_parts(0, 3545)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/polkadot/runtime/rococo/src/weights/pallet_referenda_fellowship_referenda.rs b/polkadot/runtime/rococo/src/weights/pallet_referenda_fellowship_referenda.rs index 6dfcea2b832..96f172230e1 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_referenda_fellowship_referenda.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_referenda_fellowship_referenda.rs @@ -16,28 +16,27 @@ //! Autogenerated weights for `pallet_referenda` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-07-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `runner-xerhrdyb-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: `Some(Wasm)`, WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_referenda // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json +// --pallet=pallet_referenda +// --chain=rococo-dev +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -60,10 +59,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) fn submit() -> Weight { // Proof Size summary in bytes: - // Measured: `292` + // Measured: `327` // Estimated: `42428` - // Minimum execution time: 24_053_000 picoseconds. - Weight::from_parts(25_121_000, 0) + // Minimum execution time: 29_909_000 picoseconds. + Weight::from_parts(30_645_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -72,17 +71,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `403` + // Measured: `438` // Estimated: `83866` - // Minimum execution time: 45_064_000 picoseconds. - Weight::from_parts(46_112_000, 0) + // Minimum execution time: 54_405_000 picoseconds. + Weight::from_parts(55_583_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -92,17 +89,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `2041` + // Measured: `2076` // Estimated: `42428` - // Minimum execution time: 94_146_000 picoseconds. - Weight::from_parts(98_587_000, 0) + // Minimum execution time: 110_477_000 picoseconds. + Weight::from_parts(119_187_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -112,17 +107,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `2082` + // Measured: `2117` // Estimated: `42428` - // Minimum execution time: 93_002_000 picoseconds. - Weight::from_parts(96_924_000, 0) + // Minimum execution time: 111_467_000 picoseconds. + Weight::from_parts(117_758_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -132,17 +125,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `739` + // Measured: `774` // Estimated: `83866` - // Minimum execution time: 160_918_000 picoseconds. - Weight::from_parts(175_603_000, 0) + // Minimum execution time: 191_135_000 picoseconds. + Weight::from_parts(210_535_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -152,26 +143,24 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `604` + // Measured: `639` // Estimated: `83866` - // Minimum execution time: 55_253_000 picoseconds. - Weight::from_parts(56_488_000, 0) + // Minimum execution time: 67_168_000 picoseconds. + Weight::from_parts(68_895_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) fn refund_decision_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `317` + // Measured: `351` // Estimated: `4365` - // Minimum execution time: 24_497_000 picoseconds. - Weight::from_parts(25_280_000, 0) + // Minimum execution time: 31_298_000 picoseconds. + Weight::from_parts(32_570_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -180,10 +169,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) fn refund_submission_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `167` + // Measured: `201` // Estimated: `4365` - // Minimum execution time: 11_374_000 picoseconds. - Weight::from_parts(11_817_000, 0) + // Minimum execution time: 15_674_000 picoseconds. + Weight::from_parts(16_190_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -192,17 +181,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `348` + // Measured: `383` // Estimated: `83866` - // Minimum execution time: 31_805_000 picoseconds. - Weight::from_parts(32_622_000, 0) + // Minimum execution time: 38_927_000 picoseconds. + Weight::from_parts(40_545_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) @@ -210,17 +197,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `FellowshipReferenda::MetadataOf` (r:1 w:0) /// Proof: `FellowshipReferenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn kill() -> Weight { // Proof Size summary in bytes: - // Measured: `449` + // Measured: `484` // Estimated: `83866` - // Minimum execution time: 62_364_000 picoseconds. - Weight::from_parts(63_798_000, 0) + // Minimum execution time: 80_209_000 picoseconds. + Weight::from_parts(82_084_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `FellowshipReferenda::TrackQueue` (r:1 w:0) /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) @@ -228,10 +213,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) fn one_fewer_deciding_queue_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `140` + // Measured: `174` // Estimated: `4277` - // Minimum execution time: 8_811_000 picoseconds. - Weight::from_parts(9_224_000, 0) + // Minimum execution time: 9_520_000 picoseconds. + Weight::from_parts(10_088_000, 0) .saturating_add(Weight::from_parts(0, 4277)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -246,10 +231,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `2341` + // Measured: `2376` // Estimated: `42428` - // Minimum execution time: 83_292_000 picoseconds. - Weight::from_parts(89_114_000, 0) + // Minimum execution time: 93_893_000 picoseconds. + Weight::from_parts(101_065_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -264,10 +249,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `2327` + // Measured: `2362` // Estimated: `42428` - // Minimum execution time: 84_648_000 picoseconds. - Weight::from_parts(89_332_000, 0) + // Minimum execution time: 98_811_000 picoseconds. + Weight::from_parts(103_590_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -278,10 +263,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_insertion() -> Weight { // Proof Size summary in bytes: - // Measured: `1807` + // Measured: `1841` // Estimated: `4365` - // Minimum execution time: 40_529_000 picoseconds. - Weight::from_parts(45_217_000, 0) + // Minimum execution time: 43_230_000 picoseconds. + Weight::from_parts(46_120_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -292,10 +277,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_slide() -> Weight { // Proof Size summary in bytes: - // Measured: `1774` + // Measured: `1808` // Estimated: `4365` - // Minimum execution time: 40_894_000 picoseconds. - Weight::from_parts(45_726_000, 0) + // Minimum execution time: 43_092_000 picoseconds. + Weight::from_parts(46_018_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -308,10 +293,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) fn nudge_referendum_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `1790` + // Measured: `1824` // Estimated: `4365` - // Minimum execution time: 48_187_000 picoseconds. - Weight::from_parts(52_655_000, 0) + // Minimum execution time: 49_697_000 picoseconds. + Weight::from_parts(53_795_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -324,10 +309,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::TrackQueue` (`max_values`: None, `max_size`: Some(812), added: 3287, mode: `MaxEncodedLen`) fn nudge_referendum_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `1831` + // Measured: `1865` // Estimated: `4365` - // Minimum execution time: 47_548_000 picoseconds. - Weight::from_parts(51_547_000, 0) + // Minimum execution time: 50_417_000 picoseconds. + Weight::from_parts(53_214_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -338,10 +323,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_no_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `300` + // Measured: `335` // Estimated: `42428` - // Minimum execution time: 20_959_000 picoseconds. - Weight::from_parts(21_837_000, 0) + // Minimum execution time: 25_688_000 picoseconds. + Weight::from_parts(26_575_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -352,10 +337,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `348` + // Measured: `383` // Estimated: `42428` - // Minimum execution time: 21_628_000 picoseconds. - Weight::from_parts(22_192_000, 0) + // Minimum execution time: 26_230_000 picoseconds. + Weight::from_parts(27_235_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -364,10 +349,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) fn nudge_referendum_timed_out() -> Weight { // Proof Size summary in bytes: - // Measured: `208` + // Measured: `242` // Estimated: `4365` - // Minimum execution time: 12_309_000 picoseconds. - Weight::from_parts(12_644_000, 0) + // Minimum execution time: 17_585_000 picoseconds. + Weight::from_parts(18_225_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -382,10 +367,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `549` + // Measured: `584` // Estimated: `42428` - // Minimum execution time: 31_871_000 picoseconds. - Weight::from_parts(33_123_000, 0) + // Minimum execution time: 38_243_000 picoseconds. + Weight::from_parts(39_959_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -400,10 +385,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `684` + // Measured: `719` // Estimated: `42428` - // Minimum execution time: 73_715_000 picoseconds. - Weight::from_parts(79_980_000, 0) + // Minimum execution time: 88_424_000 picoseconds. + Weight::from_parts(92_969_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -416,10 +401,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `735` + // Measured: `770` // Estimated: `42428` - // Minimum execution time: 128_564_000 picoseconds. - Weight::from_parts(138_536_000, 0) + // Minimum execution time: 138_207_000 picoseconds. + Weight::from_parts(151_726_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -432,10 +417,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_end_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `720` + // Measured: `755` // Estimated: `42428` - // Minimum execution time: 129_775_000 picoseconds. - Weight::from_parts(139_001_000, 0) + // Minimum execution time: 131_001_000 picoseconds. + Weight::from_parts(148_651_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -448,10 +433,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_continue_not_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `735` + // Measured: `770` // Estimated: `42428` - // Minimum execution time: 128_233_000 picoseconds. - Weight::from_parts(135_796_000, 0) + // Minimum execution time: 109_612_000 picoseconds. + Weight::from_parts(143_626_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -464,10 +449,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_continue_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `741` + // Measured: `776` // Estimated: `42428` - // Minimum execution time: 66_995_000 picoseconds. - Weight::from_parts(72_678_000, 0) + // Minimum execution time: 71_754_000 picoseconds. + Weight::from_parts(77_329_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -482,10 +467,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn nudge_referendum_approved() -> Weight { // Proof Size summary in bytes: - // Measured: `741` + // Measured: `776` // Estimated: `83866` - // Minimum execution time: 137_764_000 picoseconds. - Weight::from_parts(152_260_000, 0) + // Minimum execution time: 153_244_000 picoseconds. + Weight::from_parts(169_961_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -498,10 +483,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_rejected() -> Weight { // Proof Size summary in bytes: - // Measured: `737` + // Measured: `772` // Estimated: `42428` - // Minimum execution time: 119_992_000 picoseconds. - Weight::from_parts(134_805_000, 0) + // Minimum execution time: 137_997_000 picoseconds. + Weight::from_parts(157_862_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -510,18 +495,16 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(900), added: 3375, mode: `MaxEncodedLen`) /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `FellowshipReferenda::MetadataOf` (r:0 w:1) /// Proof: `FellowshipReferenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_some_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `424` + // Measured: `458` // Estimated: `4365` - // Minimum execution time: 20_927_000 picoseconds. - Weight::from_parts(21_802_000, 0) + // Minimum execution time: 21_794_000 picoseconds. + Weight::from_parts(22_341_000, 0) .saturating_add(Weight::from_parts(0, 4365)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `FellowshipReferenda::ReferendumInfoFor` (r:1 w:0) @@ -530,10 +513,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `FellowshipReferenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `285` + // Measured: `319` // Estimated: `4365` - // Minimum execution time: 14_253_000 picoseconds. - Weight::from_parts(15_031_000, 0) + // Minimum execution time: 18_458_000 picoseconds. + Weight::from_parts(19_097_000, 0) .saturating_add(Weight::from_parts(0, 4365)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_referenda_referenda.rs b/polkadot/runtime/rococo/src/weights/pallet_referenda_referenda.rs index c35925198f9..b7cc5df28b9 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_referenda_referenda.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_referenda_referenda.rs @@ -16,28 +16,27 @@ //! Autogenerated weights for `pallet_referenda` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-07-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `runner-xerhrdyb-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: `Some(Wasm)`, WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_referenda // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json +// --pallet=pallet_referenda +// --chain=rococo-dev +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -58,10 +57,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn submit() -> Weight { // Proof Size summary in bytes: - // Measured: `185` + // Measured: `324` // Estimated: `42428` - // Minimum execution time: 28_612_000 picoseconds. - Weight::from_parts(30_060_000, 0) + // Minimum execution time: 39_852_000 picoseconds. + Weight::from_parts(41_610_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) @@ -70,17 +69,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `438` + // Measured: `577` // Estimated: `83866` - // Minimum execution time: 42_827_000 picoseconds. - Weight::from_parts(44_072_000, 0) + // Minimum execution time: 52_588_000 picoseconds. + Weight::from_parts(54_154_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) @@ -90,17 +87,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3225` + // Measured: `3334` // Estimated: `42428` - // Minimum execution time: 56_475_000 picoseconds. - Weight::from_parts(58_888_000, 0) + // Minimum execution time: 70_483_000 picoseconds. + Weight::from_parts(72_731_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) @@ -110,62 +105,60 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3245` + // Measured: `3354` // Estimated: `42428` - // Minimum execution time: 56_542_000 picoseconds. - Weight::from_parts(58_616_000, 0) + // Minimum execution time: 68_099_000 picoseconds. + Weight::from_parts(71_560_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Referenda::DecidingCount` (r:1 w:1) /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `438` + // Measured: `577` // Estimated: `83866` - // Minimum execution time: 51_218_000 picoseconds. - Weight::from_parts(53_148_000, 0) + // Minimum execution time: 64_357_000 picoseconds. + Weight::from_parts(66_081_000, 0) .saturating_add(Weight::from_parts(0, 83866)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Referenda::DecidingCount` (r:1 w:1) /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn place_decision_deposit_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `438` + // Measured: `577` // Estimated: `83866` - // Minimum execution time: 49_097_000 picoseconds. - Weight::from_parts(50_796_000, 0) + // Minimum execution time: 62_709_000 picoseconds. + Weight::from_parts(64_534_000, 0) .saturating_add(Weight::from_parts(0, 83866)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn refund_decision_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `279` + // Measured: `417` // Estimated: `4401` - // Minimum execution time: 23_720_000 picoseconds. - Weight::from_parts(24_327_000, 0) + // Minimum execution time: 31_296_000 picoseconds. + Weight::from_parts(32_221_000, 0) .saturating_add(Weight::from_parts(0, 4401)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -174,10 +167,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn refund_submission_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `269` + // Measured: `407` // Estimated: `4401` - // Minimum execution time: 24_089_000 picoseconds. - Weight::from_parts(24_556_000, 0) + // Minimum execution time: 31_209_000 picoseconds. + Weight::from_parts(32_168_000, 0) .saturating_add(Weight::from_parts(0, 4401)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -186,17 +179,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `346` + // Measured: `485` // Estimated: `83866` - // Minimum execution time: 29_022_000 picoseconds. - Weight::from_parts(29_590_000, 0) + // Minimum execution time: 38_887_000 picoseconds. + Weight::from_parts(40_193_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) @@ -204,17 +195,15 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Referenda::MetadataOf` (r:1 w:0) /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn kill() -> Weight { // Proof Size summary in bytes: - // Measured: `587` + // Measured: `726` // Estimated: `83866` - // Minimum execution time: 81_920_000 picoseconds. - Weight::from_parts(84_492_000, 0) + // Minimum execution time: 106_054_000 picoseconds. + Weight::from_parts(108_318_000, 0) .saturating_add(Weight::from_parts(0, 83866)) .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::TrackQueue` (r:1 w:0) /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) @@ -222,10 +211,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) fn one_fewer_deciding_queue_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `102` + // Measured: `240` // Estimated: `5477` - // Minimum execution time: 8_134_000 picoseconds. - Weight::from_parts(8_574_000, 0) + // Minimum execution time: 9_263_000 picoseconds. + Weight::from_parts(9_763_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -234,32 +223,36 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `3115` + // Measured: `3254` // Estimated: `42428` - // Minimum execution time: 39_932_000 picoseconds. - Weight::from_parts(42_086_000, 0) + // Minimum execution time: 50_080_000 picoseconds. + Weight::from_parts(51_858_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::TrackQueue` (r:1 w:1) /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `3115` + // Measured: `3254` // Estimated: `42428` - // Minimum execution time: 42_727_000 picoseconds. - Weight::from_parts(44_280_000, 0) + // Minimum execution time: 53_889_000 picoseconds. + Weight::from_parts(55_959_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) @@ -268,10 +261,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_insertion() -> Weight { // Proof Size summary in bytes: - // Measured: `2939` + // Measured: `3077` // Estimated: `5477` - // Minimum execution time: 20_918_000 picoseconds. - Weight::from_parts(22_180_000, 0) + // Minimum execution time: 23_266_000 picoseconds. + Weight::from_parts(24_624_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -282,10 +275,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_requeued_slide() -> Weight { // Proof Size summary in bytes: - // Measured: `2939` + // Measured: `3077` // Estimated: `5477` - // Minimum execution time: 20_943_000 picoseconds. - Weight::from_parts(21_932_000, 0) + // Minimum execution time: 22_846_000 picoseconds. + Weight::from_parts(24_793_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -298,10 +291,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `2943` + // Measured: `3081` // Estimated: `5477` - // Minimum execution time: 25_197_000 picoseconds. - Weight::from_parts(26_083_000, 0) + // Minimum execution time: 28_284_000 picoseconds. + Weight::from_parts(29_940_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -314,10 +307,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) fn nudge_referendum_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `2963` + // Measured: `3101` // Estimated: `5477` - // Minimum execution time: 24_969_000 picoseconds. - Weight::from_parts(26_096_000, 0) + // Minimum execution time: 28_133_000 picoseconds. + Weight::from_parts(29_638_000, 0) .saturating_add(Weight::from_parts(0, 5477)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -328,10 +321,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_no_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `298` + // Measured: `437` // Estimated: `42428` - // Minimum execution time: 18_050_000 picoseconds. - Weight::from_parts(18_790_000, 0) + // Minimum execution time: 25_710_000 picoseconds. + Weight::from_parts(26_500_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -342,10 +335,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `346` + // Measured: `485` // Estimated: `42428` - // Minimum execution time: 18_357_000 picoseconds. - Weight::from_parts(18_957_000, 0) + // Minimum execution time: 25_935_000 picoseconds. + Weight::from_parts(26_803_000, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -354,10 +347,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) fn nudge_referendum_timed_out() -> Weight { // Proof Size summary in bytes: - // Measured: `206` + // Measured: `344` // Estimated: `4401` - // Minimum execution time: 11_479_000 picoseconds. - Weight::from_parts(11_968_000, 0) + // Minimum execution time: 17_390_000 picoseconds. + Weight::from_parts(18_042_000, 0) .saturating_add(Weight::from_parts(0, 4401)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -366,136 +359,150 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Referenda::DecidingCount` (r:1 w:1) /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `346` + // Measured: `485` // Estimated: `42428` - // Minimum execution time: 24_471_000 picoseconds. - Weight::from_parts(25_440_000, 0) + // Minimum execution time: 35_141_000 picoseconds. + Weight::from_parts(36_318_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Referenda::DecidingCount` (r:1 w:1) /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `346` + // Measured: `485` // Estimated: `42428` - // Minimum execution time: 26_580_000 picoseconds. - Weight::from_parts(27_570_000, 0) + // Minimum execution time: 37_815_000 picoseconds. + Weight::from_parts(39_243_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_begin_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `399` + // Measured: `538` // Estimated: `42428` - // Minimum execution time: 24_331_000 picoseconds. - Weight::from_parts(25_291_000, 0) + // Minimum execution time: 30_779_000 picoseconds. + Weight::from_parts(31_845_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_end_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `521` // Estimated: `42428` - // Minimum execution time: 24_768_000 picoseconds. - Weight::from_parts(25_746_000, 0) + // Minimum execution time: 31_908_000 picoseconds. + Weight::from_parts(33_253_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_continue_not_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `399` + // Measured: `538` // Estimated: `42428` - // Minimum execution time: 23_171_000 picoseconds. - Weight::from_parts(24_161_000, 0) + // Minimum execution time: 28_951_000 picoseconds. + Weight::from_parts(30_004_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_continue_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `403` + // Measured: `542` // Estimated: `42428` - // Minimum execution time: 22_263_000 picoseconds. - Weight::from_parts(23_062_000, 0) + // Minimum execution time: 27_750_000 picoseconds. + Weight::from_parts(28_588_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:2 w:2) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Lookup` (r:1 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn nudge_referendum_approved() -> Weight { // Proof Size summary in bytes: - // Measured: `403` + // Measured: `542` // Estimated: `83866` - // Minimum execution time: 33_710_000 picoseconds. - Weight::from_parts(34_871_000, 0) + // Minimum execution time: 43_950_000 picoseconds. + Weight::from_parts(46_164_000, 0) .saturating_add(Weight::from_parts(0, 83866)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) + /// Storage: `Balances::InactiveIssuance` (r:1 w:0) + /// Proof: `Balances::InactiveIssuance` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) fn nudge_referendum_rejected() -> Weight { // Proof Size summary in bytes: - // Measured: `399` + // Measured: `538` // Estimated: `42428` - // Minimum execution time: 24_260_000 picoseconds. - Weight::from_parts(25_104_000, 0) + // Minimum execution time: 31_050_000 picoseconds. + Weight::from_parts(32_169_000, 0) .saturating_add(Weight::from_parts(0, 42428)) - .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(936), added: 3411, mode: `MaxEncodedLen`) /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Referenda::MetadataOf` (r:0 w:1) /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_some_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `422` + // Measured: `560` // Estimated: `4401` - // Minimum execution time: 19_821_000 picoseconds. - Weight::from_parts(20_641_000, 0) + // Minimum execution time: 21_193_000 picoseconds. + Weight::from_parts(22_116_000, 0) .saturating_add(Weight::from_parts(0, 4401)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) @@ -504,10 +511,10 @@ impl pallet_referenda::WeightInfo for WeightInfo { /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `283` + // Measured: `421` // Estimated: `4401` - // Minimum execution time: 13_411_000 picoseconds. - Weight::from_parts(14_070_000, 0) + // Minimum execution time: 18_065_000 picoseconds. + Weight::from_parts(18_781_000, 0) .saturating_add(Weight::from_parts(0, 4401)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_scheduler.rs b/polkadot/runtime/rococo/src/weights/pallet_scheduler.rs index 5f6b41d2b54..0f36dbd384d 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_scheduler.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_scheduler.rs @@ -16,26 +16,24 @@ //! Autogenerated weights for `pallet_scheduler` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_scheduler // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_scheduler +// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -56,8 +54,8 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `68` // Estimated: `1489` - // Minimum execution time: 3_114_000 picoseconds. - Weight::from_parts(3_245_000, 0) + // Minimum execution time: 2_869_000 picoseconds. + Weight::from_parts(3_109_000, 0) .saturating_add(Weight::from_parts(0, 1489)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -69,11 +67,11 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `115 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 3_430_000 picoseconds. - Weight::from_parts(6_250_920, 0) + // Minimum execution time: 3_326_000 picoseconds. + Weight::from_parts(5_818_563, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 1_350 - .saturating_add(Weight::from_parts(333_245, 0).saturating_mul(s.into())) + // Standard Error: 1_261 + .saturating_add(Weight::from_parts(336_446, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -81,8 +79,8 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_166_000 picoseconds. - Weight::from_parts(3_295_000, 0) + // Minimum execution time: 3_007_000 picoseconds. + Weight::from_parts(3_197_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Preimage::PreimageFor` (r:1 w:1) @@ -96,11 +94,11 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `251 + s * (1 ±0)` // Estimated: `3716 + s * (1 ±0)` - // Minimum execution time: 17_072_000 picoseconds. - Weight::from_parts(17_393_000, 0) + // Minimum execution time: 16_590_000 picoseconds. + Weight::from_parts(16_869_000, 0) .saturating_add(Weight::from_parts(0, 3716)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_204, 0).saturating_mul(s.into())) + // Standard Error: 9 + .saturating_add(Weight::from_parts(1_308, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(s.into())) @@ -111,8 +109,8 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_566_000 picoseconds. - Weight::from_parts(4_775_000, 0) + // Minimum execution time: 4_320_000 picoseconds. + Weight::from_parts(4_594_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -120,24 +118,24 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_180_000 picoseconds. - Weight::from_parts(3_339_000, 0) + // Minimum execution time: 2_956_000 picoseconds. + Weight::from_parts(3_216_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn execute_dispatch_signed() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_656_000 picoseconds. - Weight::from_parts(1_829_000, 0) + // Minimum execution time: 1_824_000 picoseconds. + Weight::from_parts(1_929_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn execute_dispatch_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_628_000 picoseconds. - Weight::from_parts(1_840_000, 0) + // Minimum execution time: 1_749_000 picoseconds. + Weight::from_parts(1_916_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Scheduler::Agenda` (r:1 w:1) @@ -147,18 +145,16 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `115 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 9_523_000 picoseconds. - Weight::from_parts(12_482_434, 0) + // Minimum execution time: 9_086_000 picoseconds. + Weight::from_parts(11_733_696, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 1_663 - .saturating_add(Weight::from_parts(370_122, 0).saturating_mul(s.into())) + // Standard Error: 1_362 + .saturating_add(Weight::from_parts(375_266, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Lookup` (r:0 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 50]`. @@ -166,13 +162,13 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `115 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 14_649_000 picoseconds. - Weight::from_parts(14_705_132, 0) + // Minimum execution time: 12_716_000 picoseconds. + Weight::from_parts(12_529_180, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 1_126 - .saturating_add(Weight::from_parts(547_438, 0).saturating_mul(s.into())) + // Standard Error: 867 + .saturating_add(Weight::from_parts(548_188, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Scheduler::Lookup` (r:1 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) @@ -183,11 +179,11 @@ impl pallet_scheduler::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `292 + s * (185 ±0)` // Estimated: `42428` - // Minimum execution time: 12_335_000 picoseconds. - Weight::from_parts(16_144_217, 0) + // Minimum execution time: 12_053_000 picoseconds. + Weight::from_parts(15_358_056, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 3_533 - .saturating_add(Weight::from_parts(413_823, 0).saturating_mul(s.into())) + // Standard Error: 3_176 + .saturating_add(Weight::from_parts(421_589, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -195,48 +191,49 @@ impl pallet_scheduler::WeightInfo for WeightInfo { /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 50]`. fn cancel_named(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `318 + s * (185 ±0)` // Estimated: `42428` - // Minimum execution time: 16_906_000 picoseconds. - Weight::from_parts(17_846_662, 0) + // Minimum execution time: 14_803_000 picoseconds. + Weight::from_parts(15_805_714, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 2_687 - .saturating_add(Weight::from_parts(613_356, 0).saturating_mul(s.into())) + // Standard Error: 2_597 + .saturating_add(Weight::from_parts(611_053, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `Scheduler::Retries` (r:1 w:2) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Lookup` (r:0 w:1) + /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 50]`. fn schedule_retry(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `155` + // Measured: `196` // Estimated: `42428` - // Minimum execution time: 8_988_000 picoseconds. - Weight::from_parts(9_527_838, 0) + // Minimum execution time: 13_156_000 picoseconds. + Weight::from_parts(13_801_287, 0) .saturating_add(Weight::from_parts(0, 42428)) - // Standard Error: 523 - .saturating_add(Weight::from_parts(25_453, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(2)) + // Standard Error: 568 + .saturating_add(Weight::from_parts(35_441, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Scheduler::Agenda` (r:1 w:0) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Retries` (r:0 w:1) /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// The range of component `s` is `[1, 50]`. fn set_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `8965` + // Measured: `115 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 23_337_000 picoseconds. - Weight::from_parts(24_255_000, 0) + // Minimum execution time: 7_912_000 picoseconds. + Weight::from_parts(8_081_460, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -247,12 +244,13 @@ impl pallet_scheduler::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Retries` (r:0 w:1) /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// The range of component `s` is `[1, 50]`. fn set_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `9643` + // Measured: `324 + s * (185 ±0)` // Estimated: `42428` - // Minimum execution time: 30_704_000 picoseconds. - Weight::from_parts(31_646_000, 0) + // Minimum execution time: 10_673_000 picoseconds. + Weight::from_parts(12_212_185, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -261,12 +259,13 @@ impl pallet_scheduler::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Retries` (r:0 w:1) /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// The range of component `s` is `[1, 50]`. fn cancel_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `8977` + // Measured: `115 + s * (177 ±0)` // Estimated: `42428` - // Minimum execution time: 22_279_000 picoseconds. - Weight::from_parts(23_106_000, 0) + // Minimum execution time: 7_912_000 picoseconds. + Weight::from_parts(8_081_460, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -277,12 +276,13 @@ impl pallet_scheduler::WeightInfo for WeightInfo { /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(38963), added: 41438, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Retries` (r:0 w:1) /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// The range of component `s` is `[1, 50]`. fn cancel_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `9655` + // Measured: `324 + s * (185 ±0)` // Estimated: `42428` - // Minimum execution time: 29_649_000 picoseconds. - Weight::from_parts(30_472_000, 0) + // Minimum execution time: 10_673_000 picoseconds. + Weight::from_parts(12_212_185, 0) .saturating_add(Weight::from_parts(0, 42428)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_sudo.rs b/polkadot/runtime/rococo/src/weights/pallet_sudo.rs index ecc31dc3fa9..694174954fc 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_sudo.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_sudo.rs @@ -16,26 +16,24 @@ //! Autogenerated weights for `pallet_sudo` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_sudo // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_sudo +// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -56,8 +54,8 @@ impl pallet_sudo::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `132` // Estimated: `1517` - // Minimum execution time: 8_336_000 picoseconds. - Weight::from_parts(8_569_000, 0) + // Minimum execution time: 8_432_000 picoseconds. + Weight::from_parts(8_757_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -68,8 +66,8 @@ impl pallet_sudo::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `132` // Estimated: `1517` - // Minimum execution time: 8_858_000 picoseconds. - Weight::from_parts(9_238_000, 0) + // Minimum execution time: 9_167_000 picoseconds. + Weight::from_parts(9_397_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -79,8 +77,8 @@ impl pallet_sudo::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `132` // Estimated: `1517` - // Minimum execution time: 8_921_000 picoseconds. - Weight::from_parts(9_324_000, 0) + // Minimum execution time: 9_133_000 picoseconds. + Weight::from_parts(9_573_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -90,21 +88,10 @@ impl pallet_sudo::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `132` // Estimated: `1517` - // Minimum execution time: 7_398_000 picoseconds. - Weight::from_parts(7_869_000, 0) + // Minimum execution time: 7_374_000 picoseconds. + Weight::from_parts(7_702_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Sudo::Key` (r:1 w:0) - /// Proof: `Sudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - fn check_only_sudo_account() -> Weight { - // Proof Size summary in bytes: - // Measured: `132` - // Estimated: `1517` - // Minimum execution time: 3_146_000 picoseconds. - Weight::from_parts(3_314_000, 0) - .saturating_add(Weight::from_parts(0, 1517)) - .saturating_add(T::DbWeight::get().reads(1)) - } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_timestamp.rs b/polkadot/runtime/rococo/src/weights/pallet_timestamp.rs index 7d79621b9e6..1bb2e227ab7 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_timestamp.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_timestamp.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_timestamp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_timestamp // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,26 +47,26 @@ use core::marker::PhantomData; /// Weight functions for `pallet_timestamp`. pub struct WeightInfo(PhantomData); impl pallet_timestamp::WeightInfo for WeightInfo { - /// Storage: `Timestamp::Now` (r:1 w:1) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Babe::CurrentSlot` (r:1 w:0) - /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Timestamp Now (r:1 w:1) + /// Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Babe CurrentSlot (r:1 w:0) + /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn set() -> Weight { // Proof Size summary in bytes: - // Measured: `137` + // Measured: `311` // Estimated: `1493` - // Minimum execution time: 5_596_000 picoseconds. - Weight::from_parts(5_823_000, 0) + // Minimum execution time: 10_103_000 picoseconds. + Weight::from_parts(10_597_000, 0) .saturating_add(Weight::from_parts(0, 1493)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } fn on_finalize() -> Weight { // Proof Size summary in bytes: - // Measured: `57` + // Measured: `94` // Estimated: `0` - // Minimum execution time: 2_777_000 picoseconds. - Weight::from_parts(2_900_000, 0) + // Minimum execution time: 4_718_000 picoseconds. + Weight::from_parts(4_839_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_transaction_payment.rs b/polkadot/runtime/rococo/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 44dfab289fb..00000000000 --- a/polkadot/runtime/rococo/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=rococo-dev -// --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_transaction_payment -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ - -#![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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `252` - // Estimated: `1737` - // Minimum execution time: 33_070_000 picoseconds. - Weight::from_parts(33_730_000, 0) - .saturating_add(Weight::from_parts(0, 1737)) - .saturating_add(T::DbWeight::get().reads(3)) - } -} diff --git a/polkadot/runtime/rococo/src/weights/pallet_treasury.rs b/polkadot/runtime/rococo/src/weights/pallet_treasury.rs index acf09989afc..144e9d5b872 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_treasury.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_treasury.rs @@ -16,28 +16,25 @@ //! Autogenerated weights for `pallet_treasury` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-07-07, STEPS: `50`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `cob`, CPU: `` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// ./target/debug/polkadot // benchmark // pallet // --chain=rococo-dev // --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares +// --repeat=2 // --pallet=pallet_treasury // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --heap-pages=4096 +// --output=./runtime/rococo/src/weights/ +// --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,168 +47,176 @@ use core::marker::PhantomData; /// Weight functions for `pallet_treasury`. pub struct WeightInfo(PhantomData); impl pallet_treasury::WeightInfo for WeightInfo { - /// Storage: `Treasury::ProposalCount` (r:1 w:1) - /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:0 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: Treasury ProposalCount (r:1 w:1) + /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:0 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) fn spend_local() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `42` // Estimated: `1887` - // Minimum execution time: 9_928_000 picoseconds. - Weight::from_parts(10_560_000, 0) + // Minimum execution time: 177_000_000 picoseconds. + Weight::from_parts(191_000_000, 0) .saturating_add(Weight::from_parts(0, 1887)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Treasury::ProposalCount` (r:1 w:1) - /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:0 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: Treasury ProposalCount (r:1 w:1) + /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:0 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) fn propose_spend() -> Weight { // Proof Size summary in bytes: - // Measured: `243` + // Measured: `143` // Estimated: `1489` - // Minimum execution time: 20_714_000 picoseconds. - Weight::from_parts(21_137_000, 0) + // Minimum execution time: 354_000_000 picoseconds. + Weight::from_parts(376_000_000, 0) .saturating_add(Weight::from_parts(0, 1489)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Treasury::Proposals` (r:1 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Treasury Proposals (r:1 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn reject_proposal() -> Weight { // Proof Size summary in bytes: - // Measured: `401` + // Measured: `301` // Estimated: `3593` - // Minimum execution time: 31_665_000 picoseconds. - Weight::from_parts(32_442_000, 0) + // Minimum execution time: 547_000_000 picoseconds. + Weight::from_parts(550_000_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Treasury::Proposals` (r:1 w:0) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Proposals (r:1 w:0) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `570 + p * (8 ±0)` + // Measured: `470 + p * (8 ±0)` // Estimated: `3573` - // Minimum execution time: 6_988_000 picoseconds. - Weight::from_parts(11_464_972, 0) + // Minimum execution time: 104_000_000 picoseconds. + Weight::from_parts(121_184_402, 0) .saturating_add(Weight::from_parts(0, 3573)) - // Standard Error: 1_722 - .saturating_add(Weight::from_parts(84_536, 0).saturating_mul(p.into())) + // Standard Error: 42_854 + .saturating_add(Weight::from_parts(153_112, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) fn remove_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `227` + // Measured: `127` // Estimated: `1887` - // Minimum execution time: 5_386_000 picoseconds. - Weight::from_parts(5_585_000, 0) + // Minimum execution time: 80_000_000 picoseconds. + Weight::from_parts(82_000_000, 0) .saturating_add(Weight::from_parts(0, 1887)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Treasury::Deactivated` (r:1 w:1) - /// Proof: `Treasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:99 w:99) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:199 w:199) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Deactivated (r:1 w:1) + /// Proof: Treasury Deactivated (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Balances InactiveIssuance (r:1 w:1) + /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:99 w:99) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: System Account (r:199 w:199) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyApprovals (r:1 w:1) + /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) /// The range of component `p` is `[0, 99]`. fn on_initialize_proposals(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `431 + p * (251 ±0)` + // Measured: `331 + p * (251 ±0)` // Estimated: `3593 + p * (5206 ±0)` - // Minimum execution time: 43_737_000 picoseconds. - Weight::from_parts(39_883_021, 0) + // Minimum execution time: 887_000_000 picoseconds. + Weight::from_parts(828_616_021, 0) .saturating_add(Weight::from_parts(0, 3593)) - // Standard Error: 12_917 - .saturating_add(Weight::from_parts(31_796_205, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(4)) + // Standard Error: 695_351 + .saturating_add(Weight::from_parts(566_114_524, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(p.into()))) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(5)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(p.into())) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:0) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(1238), added: 3713, mode: `MaxEncodedLen`) - /// Storage: `Treasury::SpendCount` (r:1 w:1) - /// Proof: `Treasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Spends` (r:0 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:0) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(1237), added: 3712, mode: MaxEncodedLen) + /// Storage: Treasury SpendCount (r:1 w:1) + /// Proof: Treasury SpendCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Spends (r:0 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(1848), added: 4323, mode: MaxEncodedLen) fn spend() -> Weight { // Proof Size summary in bytes: - // Measured: `215` - // Estimated: `4703` - // Minimum execution time: 16_829_000 picoseconds. - Weight::from_parts(17_251_000, 0) - .saturating_add(Weight::from_parts(0, 4703)) + // Measured: `114` + // Estimated: `4702` + // Minimum execution time: 208_000_000 picoseconds. + Weight::from_parts(222_000_000, 0) + .saturating_add(Weight::from_parts(0, 4702)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`) - /// Storage: `XcmPallet::QueryCounter` (r:1 w:1) - /// Proof: `XcmPallet::QueryCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::Queries` (r:0 w:1) - /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(1848), added: 4323, mode: MaxEncodedLen) + /// Storage: XcmPallet QueryCounter (r:1 w:1) + /// Proof Skipped: XcmPallet QueryCounter (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Dmp DeliveryFeeFactor (r:1 w:0) + /// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmPallet SupportedVersion (r:1 w:0) + /// Proof Skipped: XcmPallet SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: XcmPallet VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmPallet SafeXcmVersion (r:1 w:0) + /// Proof Skipped: XcmPallet SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueues (r:1 w:1) + /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmPallet Queries (r:0 w:1) + /// Proof Skipped: XcmPallet Queries (max_values: None, max_size: None, mode: Measured) fn payout() -> Weight { // Proof Size summary in bytes: - // Measured: `458` - // Estimated: `5318` - // Minimum execution time: 41_554_000 picoseconds. - Weight::from_parts(42_451_000, 0) - .saturating_add(Weight::from_parts(0, 5318)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(5)) + // Measured: `737` + // Estimated: `5313` + // Minimum execution time: 551_000_000 picoseconds. + Weight::from_parts(569_000_000, 0) + .saturating_add(Weight::from_parts(0, 5313)) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`) - /// Storage: `XcmPallet::Queries` (r:1 w:1) - /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(1848), added: 4323, mode: MaxEncodedLen) + /// Storage: XcmPallet Queries (r:1 w:1) + /// Proof Skipped: XcmPallet Queries (max_values: None, max_size: None, mode: Measured) fn check_status() -> Weight { // Proof Size summary in bytes: - // Measured: `306` - // Estimated: `5318` - // Minimum execution time: 22_546_000 picoseconds. - Weight::from_parts(23_151_000, 0) - .saturating_add(Weight::from_parts(0, 5318)) + // Measured: `442` + // Estimated: `5313` + // Minimum execution time: 245_000_000 picoseconds. + Weight::from_parts(281_000_000, 0) + .saturating_add(Weight::from_parts(0, 5313)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(1853), added: 4328, mode: `MaxEncodedLen`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(1848), added: 4323, mode: MaxEncodedLen) fn void_spend() -> Weight { // Proof Size summary in bytes: - // Measured: `278` - // Estimated: `5318` - // Minimum execution time: 12_169_000 picoseconds. - Weight::from_parts(12_484_000, 0) - .saturating_add(Weight::from_parts(0, 5318)) + // Measured: `172` + // Estimated: `5313` + // Minimum execution time: 147_000_000 picoseconds. + Weight::from_parts(160_000_000, 0) + .saturating_add(Weight::from_parts(0, 5313)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_utility.rs b/polkadot/runtime/rococo/src/weights/pallet_utility.rs index 6f2a374247f..f50f60eaad7 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_utility.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_utility.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_utility` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_utility // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,18 +52,18 @@ impl pallet_utility::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_041_000 picoseconds. - Weight::from_parts(5_685_496, 0) + // Minimum execution time: 6_738_000 picoseconds. + Weight::from_parts(2_704_821, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 810 - .saturating_add(Weight::from_parts(3_177_197, 0).saturating_mul(c.into())) + // Standard Error: 2_999 + .saturating_add(Weight::from_parts(4_627_278, 0).saturating_mul(c.into())) } fn as_derivative() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_667_000 picoseconds. - Weight::from_parts(3_871_000, 0) + // Minimum execution time: 5_294_000 picoseconds. + Weight::from_parts(5_467_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `c` is `[0, 1000]`. @@ -74,18 +71,18 @@ impl pallet_utility::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_116_000 picoseconds. - Weight::from_parts(6_453_932, 0) + // Minimum execution time: 6_828_000 picoseconds. + Weight::from_parts(4_650_678, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 825 - .saturating_add(Weight::from_parts(3_366_112, 0).saturating_mul(c.into())) + // Standard Error: 2_789 + .saturating_add(Weight::from_parts(4_885_004, 0).saturating_mul(c.into())) } fn dispatch_as() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_630_000 picoseconds. - Weight::from_parts(5_956_000, 0) + // Minimum execution time: 9_020_000 picoseconds. + Weight::from_parts(9_205_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `c` is `[0, 1000]`. @@ -93,10 +90,10 @@ impl pallet_utility::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_165_000 picoseconds. - Weight::from_parts(5_442_561, 0) + // Minimum execution time: 6_852_000 picoseconds. + Weight::from_parts(20_703_134, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 460 - .saturating_add(Weight::from_parts(3_173_577, 0).saturating_mul(c.into())) + // Standard Error: 3_924 + .saturating_add(Weight::from_parts(4_604_529, 0).saturating_mul(c.into())) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_vesting.rs b/polkadot/runtime/rococo/src/weights/pallet_vesting.rs index c21ab087774..2596207d583 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_vesting.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_vesting.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `pallet_vesting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=pallet_vesting // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,143 +47,143 @@ use core::marker::PhantomData; /// Weight functions for `pallet_vesting`. pub struct WeightInfo(PhantomData); impl pallet_vesting::WeightInfo for WeightInfo { - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_locked(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `277 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 29_288_000 picoseconds. - Weight::from_parts(29_095_507, 0) + // Minimum execution time: 32_820_000 picoseconds. + Weight::from_parts(31_640_992, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_679 - .saturating_add(Weight::from_parts(33_164, 0).saturating_mul(l.into())) - // Standard Error: 2_988 - .saturating_add(Weight::from_parts(67_092, 0).saturating_mul(s.into())) + // Standard Error: 449 + .saturating_add(Weight::from_parts(45_254, 0).saturating_mul(l.into())) + // Standard Error: 800 + .saturating_add(Weight::from_parts(72_178, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_unlocked(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `277 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 31_003_000 picoseconds. - Weight::from_parts(30_528_438, 0) + // Minimum execution time: 36_054_000 picoseconds. + Weight::from_parts(35_825_428, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_586 - .saturating_add(Weight::from_parts(35_429, 0).saturating_mul(l.into())) - // Standard Error: 2_823 - .saturating_add(Weight::from_parts(76_505, 0).saturating_mul(s.into())) + // Standard Error: 749 + .saturating_add(Weight::from_parts(31_738, 0).saturating_mul(l.into())) + // Standard Error: 1_333 + .saturating_add(Weight::from_parts(40_580, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_other_locked(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `380 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 31_269_000 picoseconds. - Weight::from_parts(30_661_898, 0) + // Minimum execution time: 35_440_000 picoseconds. + Weight::from_parts(34_652_647, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_394 - .saturating_add(Weight::from_parts(39_300, 0).saturating_mul(l.into())) - // Standard Error: 2_480 - .saturating_add(Weight::from_parts(78_849, 0).saturating_mul(s.into())) + // Standard Error: 517 + .saturating_add(Weight::from_parts(41_942, 0).saturating_mul(l.into())) + // Standard Error: 920 + .saturating_add(Weight::from_parts(66_074, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_other_unlocked(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `380 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_040_000 picoseconds. - Weight::from_parts(32_469_674, 0) + // Minimum execution time: 38_880_000 picoseconds. + Weight::from_parts(39_625_819, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_418 - .saturating_add(Weight::from_parts(44_206, 0).saturating_mul(l.into())) - // Standard Error: 2_523 - .saturating_add(Weight::from_parts(74_224, 0).saturating_mul(s.into())) + // Standard Error: 1_032 + .saturating_add(Weight::from_parts(29_856, 0).saturating_mul(l.into())) + // Standard Error: 1_837 + .saturating_add(Weight::from_parts(6_210, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[0, 27]`. fn vested_transfer(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `451 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 62_032_000 picoseconds. - Weight::from_parts(63_305_621, 0) + // Minimum execution time: 68_294_000 picoseconds. + Weight::from_parts(68_313_394, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 2_277 - .saturating_add(Weight::from_parts(42_767, 0).saturating_mul(l.into())) - // Standard Error: 4_051 - .saturating_add(Weight::from_parts(65_487, 0).saturating_mul(s.into())) + // Standard Error: 983 + .saturating_add(Weight::from_parts(48_156, 0).saturating_mul(l.into())) + // Standard Error: 1_750 + .saturating_add(Weight::from_parts(87_719, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[0, 27]`. fn force_vested_transfer(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `554 + l * (25 ±0) + s * (36 ±0)` // Estimated: `6196` - // Minimum execution time: 63_303_000 picoseconds. - Weight::from_parts(65_180_847, 0) + // Minimum execution time: 70_529_000 picoseconds. + Weight::from_parts(70_619_962, 0) .saturating_add(Weight::from_parts(0, 6196)) - // Standard Error: 2_220 - .saturating_add(Weight::from_parts(28_829, 0).saturating_mul(l.into())) - // Standard Error: 3_951 - .saturating_add(Weight::from_parts(84_970, 0).saturating_mul(s.into())) + // Standard Error: 1_259 + .saturating_add(Weight::from_parts(50_685, 0).saturating_mul(l.into())) + // Standard Error: 2_241 + .saturating_add(Weight::from_parts(91_444, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -195,70 +192,59 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[2, 28]`. - fn not_unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { + fn force_remove_vesting_schedule(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `378 + l * (25 ±0) + s * (36 ±0)` + // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 31_440_000 picoseconds. - Weight::from_parts(30_773_053, 0) - .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_474 - .saturating_add(Weight::from_parts(43_019, 0).saturating_mul(l.into())) - // Standard Error: 2_723 - .saturating_add(Weight::from_parts(73_360, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) + // Minimum execution time: 41_497_000 picoseconds. + Weight::from_parts(38_763_834, 4764) + // Standard Error: 2_030 + .saturating_add(Weight::from_parts(99_580, 0).saturating_mul(l.into())) + // Standard Error: 3_750 + .saturating_add(Weight::from_parts(132_188, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// The range of component `l` is `[0, 49]`. - /// The range of component `s` is `[2, 28]`. - fn unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { + fn not_unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `378 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 34_221_000 picoseconds. - Weight::from_parts(33_201_125, 0) + // Minimum execution time: 36_428_000 picoseconds. + Weight::from_parts(35_604_430, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_751 - .saturating_add(Weight::from_parts(44_088, 0).saturating_mul(l.into())) - // Standard Error: 3_234 - .saturating_add(Weight::from_parts(86_228, 0).saturating_mul(s.into())) + // Standard Error: 504 + .saturating_add(Weight::from_parts(43_191, 0).saturating_mul(l.into())) + // Standard Error: 931 + .saturating_add(Weight::from_parts(66_795, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[2, 28]`. - fn force_remove_vesting_schedule(l: u32, s: u32, ) -> Weight { + fn unlocking_merge_schedules(l: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `451 + l * (25 ±0) + s * (36 ±0)` + // Measured: `378 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 35_553_000 picoseconds. - Weight::from_parts(34_974_083, 0) + // Minimum execution time: 40_696_000 picoseconds. + Weight::from_parts(39_741_284, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 1_560 - .saturating_add(Weight::from_parts(34_615, 0).saturating_mul(l.into())) - // Standard Error: 2_882 - .saturating_add(Weight::from_parts(83_419, 0).saturating_mul(s.into())) + // Standard Error: 478 + .saturating_add(Weight::from_parts(43_792, 0).saturating_mul(l.into())) + // Standard Error: 883 + .saturating_add(Weight::from_parts(66_540, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_whitelist.rs b/polkadot/runtime/rococo/src/weights/pallet_whitelist.rs index ec67268d144..7c307deec4c 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_whitelist.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_whitelist.rs @@ -16,28 +16,26 @@ //! Autogenerated weights for `pallet_whitelist` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-aahe6cbd-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_whitelist // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json +// --pallet=pallet_whitelist +// --chain=rococo-dev +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -52,75 +50,67 @@ pub struct WeightInfo(PhantomData); impl pallet_whitelist::WeightInfo for WeightInfo { /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Storage: `Preimage::StatusFor` (r:1 w:1) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn whitelist_call() -> Weight { // Proof Size summary in bytes: // Measured: `223` // Estimated: `3556` - // Minimum execution time: 16_686_000 picoseconds. - Weight::from_parts(17_042_000, 0) + // Minimum execution time: 20_035_000 picoseconds. + Weight::from_parts(20_452_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Storage: `Preimage::StatusFor` (r:1 w:1) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) fn remove_whitelisted_call() -> Weight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `3556` - // Minimum execution time: 18_250_000 picoseconds. - Weight::from_parts(19_026_000, 0) + // Minimum execution time: 20_247_000 picoseconds. + Weight::from_parts(20_808_000, 0) .saturating_add(Weight::from_parts(0, 3556)) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:1 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Storage: `Preimage::StatusFor` (r:1 w:1) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 4194294]`. fn dispatch_whitelisted_call(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `428 + n * (1 ±0)` // Estimated: `3892 + n * (1 ±0)` - // Minimum execution time: 28_741_000 picoseconds. - Weight::from_parts(29_024_000, 0) + // Minimum execution time: 32_633_000 picoseconds. + Weight::from_parts(32_855_000, 0) .saturating_add(Weight::from_parts(0, 3892)) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_305, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(4)) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_223, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) + /// Storage: `Preimage::StatusFor` (r:1 w:1) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// The range of component `n` is `[1, 10000]`. fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `3556` - // Minimum execution time: 21_670_000 picoseconds. - Weight::from_parts(22_561_364, 0) + // Minimum execution time: 23_833_000 picoseconds. + Weight::from_parts(24_698_994, 0) .saturating_add(Weight::from_parts(0, 3556)) // Standard Error: 4 - .saturating_add(Weight::from_parts(1_468, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(Weight::from_parts(1_454, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs index d5cf33515e6..5544ca44658 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs @@ -17,25 +17,23 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_xcm // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm +// --chain=rococo-dev // --header=./polkadot/file_header.txt // --output=./polkadot/runtime/rococo/src/weights/ @@ -62,8 +60,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 25_521_000 picoseconds. - Weight::from_parts(25_922_000, 0) + // Minimum execution time: 25_043_000 picoseconds. + Weight::from_parts(25_682_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) @@ -82,8 +80,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 112_185_000 picoseconds. - Weight::from_parts(115_991_000, 0) + // Minimum execution time: 107_570_000 picoseconds. + Weight::from_parts(109_878_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -102,8 +100,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `232` // Estimated: `3697` - // Minimum execution time: 108_693_000 picoseconds. - Weight::from_parts(111_853_000, 0) + // Minimum execution time: 106_341_000 picoseconds. + Weight::from_parts(109_135_000, 0) .saturating_add(Weight::from_parts(0, 3697)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -122,8 +120,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 113_040_000 picoseconds. - Weight::from_parts(115_635_000, 0) + // Minimum execution time: 108_372_000 picoseconds. + Weight::from_parts(112_890_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -132,8 +130,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_979_000 picoseconds. - Weight::from_parts(7_342_000, 0) + // Minimum execution time: 6_957_000 picoseconds. + Weight::from_parts(7_417_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::SupportedVersion` (r:0 w:1) @@ -142,8 +140,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_144_000 picoseconds. - Weight::from_parts(7_297_000, 0) + // Minimum execution time: 7_053_000 picoseconds. + Weight::from_parts(7_462_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -151,8 +149,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_886_000 picoseconds. - Weight::from_parts(1_995_000, 0) + // Minimum execution time: 1_918_000 picoseconds. + Weight::from_parts(2_037_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::VersionNotifiers` (r:1 w:1) @@ -173,8 +171,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 31_238_000 picoseconds. - Weight::from_parts(31_955_000, 0) + // Minimum execution time: 30_417_000 picoseconds. + Weight::from_parts(31_191_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) @@ -195,8 +193,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `360` // Estimated: `3825` - // Minimum execution time: 37_237_000 picoseconds. - Weight::from_parts(38_569_000, 0) + // Minimum execution time: 36_666_000 picoseconds. + Weight::from_parts(37_779_000, 0) .saturating_add(Weight::from_parts(0, 3825)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -207,8 +205,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_884_000 picoseconds. - Weight::from_parts(2_028_000, 0) + // Minimum execution time: 1_869_000 picoseconds. + Weight::from_parts(2_003_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -218,8 +216,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `22` // Estimated: `13387` - // Minimum execution time: 16_048_000 picoseconds. - Weight::from_parts(16_617_000, 0) + // Minimum execution time: 16_188_000 picoseconds. + Weight::from_parts(16_435_000, 0) .saturating_add(Weight::from_parts(0, 13387)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -230,8 +228,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `26` // Estimated: `13391` - // Minimum execution time: 16_073_000 picoseconds. - Weight::from_parts(16_672_000, 0) + // Minimum execution time: 16_431_000 picoseconds. + Weight::from_parts(16_935_000, 0) .saturating_add(Weight::from_parts(0, 13391)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -242,8 +240,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `40` // Estimated: `15880` - // Minimum execution time: 18_422_000 picoseconds. - Weight::from_parts(18_900_000, 0) + // Minimum execution time: 18_460_000 picoseconds. + Weight::from_parts(18_885_000, 0) .saturating_add(Weight::from_parts(0, 15880)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -261,8 +259,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `216` // Estimated: `6156` - // Minimum execution time: 30_373_000 picoseconds. - Weight::from_parts(30_972_000, 0) + // Minimum execution time: 29_623_000 picoseconds. + Weight::from_parts(30_661_000, 0) .saturating_add(Weight::from_parts(0, 6156)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) @@ -273,8 +271,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `69` // Estimated: `10959` - // Minimum execution time: 11_863_000 picoseconds. - Weight::from_parts(12_270_000, 0) + // Minimum execution time: 12_043_000 picoseconds. + Weight::from_parts(12_360_000, 0) .saturating_add(Weight::from_parts(0, 10959)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -284,8 +282,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `33` // Estimated: `13398` - // Minimum execution time: 16_733_000 picoseconds. - Weight::from_parts(17_094_000, 0) + // Minimum execution time: 16_511_000 picoseconds. + Weight::from_parts(17_011_000, 0) .saturating_add(Weight::from_parts(0, 13398)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -304,8 +302,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `216` // Estimated: `13581` - // Minimum execution time: 39_236_000 picoseconds. - Weight::from_parts(40_587_000, 0) + // Minimum execution time: 39_041_000 picoseconds. + Weight::from_parts(39_883_000, 0) .saturating_add(Weight::from_parts(0, 13581)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(4)) @@ -318,8 +316,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 2_145_000 picoseconds. - Weight::from_parts(2_255_000, 0) + // Minimum execution time: 2_030_000 picoseconds. + Weight::from_parts(2_150_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -330,8 +328,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7576` // Estimated: `11041` - // Minimum execution time: 22_518_000 picoseconds. - Weight::from_parts(22_926_000, 0) + // Minimum execution time: 22_615_000 picoseconds. + Weight::from_parts(23_008_000, 0) .saturating_add(Weight::from_parts(0, 11041)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs deleted file mode 100644 index dc5e5d8ca4b..00000000000 --- a/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Autogenerated weights for `pallet_xcm_benchmarks::fungible` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=rococo-dev -// --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_xcm_benchmarks::fungible -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_fungible.rs - -#![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_xcm_benchmarks::fungible`. -pub struct WeightInfo(PhantomData); -impl pallet_xcm_benchmarks::fungible::WeightInfo for WeightInfo { - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn withdraw_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `101` - // Estimated: `3593` - // Minimum execution time: 27_223_000 picoseconds. - Weight::from_parts(27_947_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn transfer_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `101` - // Estimated: `6196` - // Minimum execution time: 36_502_000 picoseconds. - Weight::from_parts(37_023_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:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn transfer_reserve_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `281` - // Estimated: `6196` - // Minimum execution time: 85_152_000 picoseconds. - Weight::from_parts(86_442_000, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(4)) - } - /// Storage: `Benchmark::Override` (r:0 w:0) - /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn reserve_asset_deposited() -> 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)) - } - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn initiate_reserve_withdraw() -> Weight { - // Proof Size summary in bytes: - // Measured: `281` - // Estimated: `3746` - // Minimum execution time: 56_571_000 picoseconds. - Weight::from_parts(58_163_000, 0) - .saturating_add(Weight::from_parts(0, 3746)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn receive_teleported_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `103` - // Estimated: `3593` - // Minimum execution time: 27_411_000 picoseconds. - Weight::from_parts(27_953_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn deposit_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `3593` - // Minimum execution time: 20_776_000 picoseconds. - Weight::from_parts(21_145_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn deposit_reserve_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `180` - // Estimated: `3645` - // Minimum execution time: 51_738_000 picoseconds. - Weight::from_parts(53_251_000, 0) - .saturating_add(Weight::from_parts(0, 3645)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn initiate_teleport() -> Weight { - // Proof Size summary in bytes: - // Measured: `180` - // Estimated: `3645` - // Minimum execution time: 39_333_000 picoseconds. - Weight::from_parts(40_515_000, 0) - .saturating_add(Weight::from_parts(0, 3645)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } -} diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs deleted file mode 100644 index b62f36172ba..00000000000 --- a/polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Autogenerated weights for `pallet_xcm_benchmarks::generic` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=rococo-dev -// --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=pallet_xcm_benchmarks::generic -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/pallet_xcm_benchmarks_generic.rs - -#![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_xcm_benchmarks::generic`. -pub struct WeightInfo(PhantomData); -impl pallet_xcm_benchmarks::generic::WeightInfo for WeightInfo { - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn report_holding() -> Weight { - // Proof Size summary in bytes: - // Measured: `281` - // Estimated: `3746` - // Minimum execution time: 55_210_000 picoseconds. - Weight::from_parts(56_613_000, 0) - .saturating_add(Weight::from_parts(0, 3746)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - fn buy_execution() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_246_000 picoseconds. - Weight::from_parts(1_339_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `XcmPallet::Queries` (r:1 w:0) - /// Proof: `XcmPallet::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn query_response() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `3465` - // Minimum execution time: 5_377_000 picoseconds. - Weight::from_parts(5_549_000, 0) - .saturating_add(Weight::from_parts(0, 3465)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn transact() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 7_008_000 picoseconds. - Weight::from_parts(7_361_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn refund_surplus() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_700_000 picoseconds. - Weight::from_parts(1_848_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn set_error_handler() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_198_000 picoseconds. - Weight::from_parts(1_265_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn set_appendix() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_197_000 picoseconds. - Weight::from_parts(1_267_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn clear_error() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_193_000 picoseconds. - Weight::from_parts(1_258_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn descend_origin() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_268_000 picoseconds. - Weight::from_parts(1_342_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn clear_origin() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_173_000 picoseconds. - Weight::from_parts(1_248_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn report_error() -> Weight { - // Proof Size summary in bytes: - // Measured: `281` - // Estimated: `3746` - // Minimum execution time: 53_715_000 picoseconds. - Weight::from_parts(54_860_000, 0) - .saturating_add(Weight::from_parts(0, 3746)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: `XcmPallet::AssetTraps` (r:1 w:1) - /// Proof: `XcmPallet::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn claim_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `23` - // Estimated: `3488` - // Minimum execution time: 8_621_000 picoseconds. - Weight::from_parts(8_903_000, 0) - .saturating_add(Weight::from_parts(0, 3488)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - fn trap() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_211_000 picoseconds. - Weight::from_parts(1_281_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:1 w:1) - /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn subscribe_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `180` - // Estimated: `3645` - // Minimum execution time: 26_448_000 picoseconds. - Weight::from_parts(27_057_000, 0) - .saturating_add(Weight::from_parts(0, 3645)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: `XcmPallet::VersionNotifyTargets` (r:0 w:1) - /// Proof: `XcmPallet::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn unsubscribe_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_498_000 picoseconds. - Weight::from_parts(3_614_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) - } - fn burn_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_575_000 picoseconds. - Weight::from_parts(1_698_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn expect_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_334_000 picoseconds. - Weight::from_parts(1_435_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn expect_origin() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_244_000 picoseconds. - Weight::from_parts(1_337_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn expect_error() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_244_000 picoseconds. - Weight::from_parts(1_331_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn expect_transact_status() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_407_000 picoseconds. - Weight::from_parts(1_522_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn query_pallet() -> Weight { - // Proof Size summary in bytes: - // Measured: `281` - // Estimated: `3746` - // Minimum execution time: 62_963_000 picoseconds. - Weight::from_parts(64_556_000, 0) - .saturating_add(Weight::from_parts(0, 3746)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - fn expect_pallet() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 8_458_000 picoseconds. - Weight::from_parts(8_741_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) - /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn report_transact_status() -> Weight { - // Proof Size summary in bytes: - // Measured: `281` - // Estimated: `3746` - // Minimum execution time: 54_068_000 picoseconds. - Weight::from_parts(55_665_000, 0) - .saturating_add(Weight::from_parts(0, 3746)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - fn clear_transact_status() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_290_000 picoseconds. - Weight::from_parts(1_348_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn set_topic() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_189_000 picoseconds. - Weight::from_parts(1_268_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn clear_topic() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_197_000 picoseconds. - Weight::from_parts(1_276_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn set_fees_mode() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_197_000 picoseconds. - Weight::from_parts(1_253_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn unpaid_execution() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 1_250_000 picoseconds. - Weight::from_parts(1_354_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } -} diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs b/polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs index f41a5d4ebf8..a6beeded428 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs @@ -16,28 +16,26 @@ //! Autogenerated weights for `runtime_common::assigned_slots` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `runner-ynta1nyy-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=runtime_common::assigned_slots // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_common_assigned_slots.rs +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json +// --pallet=runtime_common::assigned_slots +// --chain=rococo-dev +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +48,7 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::assigned_slots`. pub struct WeightInfo(PhantomData); impl runtime_common::assigned_slots::WeightInfo for WeightInfo { - /// Storage: `Registrar::Paras` (r:1 w:0) + /// Storage: `Registrar::Paras` (r:1 w:1) /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Paras::ParaLifecycles` (r:1 w:1) /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -70,15 +68,15 @@ impl runtime_common::assigned_slots::WeightInfo for Wei /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) fn assign_perm_parachain_slot() -> Weight { // Proof Size summary in bytes: - // Measured: `730` - // Estimated: `4195` - // Minimum execution time: 71_337_000 picoseconds. - Weight::from_parts(80_807_000, 0) - .saturating_add(Weight::from_parts(0, 4195)) + // Measured: `673` + // Estimated: `4138` + // Minimum execution time: 84_646_000 picoseconds. + Weight::from_parts(91_791_000, 0) + .saturating_add(Weight::from_parts(0, 4138)) .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: `Registrar::Paras` (r:1 w:0) + /// Storage: `Registrar::Paras` (r:1 w:1) /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Paras::ParaLifecycles` (r:1 w:1) /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -100,13 +98,13 @@ impl runtime_common::assigned_slots::WeightInfo for Wei /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) fn assign_temp_parachain_slot() -> Weight { // Proof Size summary in bytes: - // Measured: `730` - // Estimated: `4195` - // Minimum execution time: 60_188_000 picoseconds. - Weight::from_parts(63_932_000, 0) - .saturating_add(Weight::from_parts(0, 4195)) + // Measured: `673` + // Estimated: `4138` + // Minimum execution time: 68_091_000 picoseconds. + Weight::from_parts(77_310_000, 0) + .saturating_add(Weight::from_parts(0, 4138)) .saturating_add(T::DbWeight::get().reads(10)) - .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes(7)) } /// Storage: `AssignedSlots::PermanentSlots` (r:1 w:0) /// Proof: `AssignedSlots::PermanentSlots` (`max_values`: None, `max_size`: Some(20), added: 2495, mode: `MaxEncodedLen`) @@ -120,11 +118,11 @@ impl runtime_common::assigned_slots::WeightInfo for Wei /// Proof: `AssignedSlots::TemporarySlotCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn unassign_parachain_slot() -> Weight { // Proof Size summary in bytes: - // Measured: `856` - // Estimated: `4321` - // Minimum execution time: 35_764_000 picoseconds. - Weight::from_parts(38_355_000, 0) - .saturating_add(Weight::from_parts(0, 4321)) + // Measured: `823` + // Estimated: `4288` + // Minimum execution time: 38_081_000 picoseconds. + Weight::from_parts(40_987_000, 0) + .saturating_add(Weight::from_parts(0, 4288)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -134,8 +132,8 @@ impl runtime_common::assigned_slots::WeightInfo for Wei // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_634_000 picoseconds. - Weight::from_parts(4_852_000, 0) + // Minimum execution time: 7_182_000 picoseconds. + Weight::from_parts(7_437_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -145,8 +143,8 @@ impl runtime_common::assigned_slots::WeightInfo for Wei // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_563_000 picoseconds. - Weight::from_parts(4_829_000, 0) + // Minimum execution time: 7_153_000 picoseconds. + Weight::from_parts(7_456_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs b/polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs index 2b756802289..3cd7c7a47e9 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::auctions` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_common::auctions // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_common_auctions.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_common_auctions.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,90 +47,92 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::auctions`. pub struct WeightInfo(PhantomData); impl runtime_common::auctions::WeightInfo for WeightInfo { - /// Storage: `Auctions::AuctionInfo` (r:1 w:1) - /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Auctions::AuctionCounter` (r:1 w:1) - /// Proof: `Auctions::AuctionCounter` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: Auctions AuctionInfo (r:1 w:1) + /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Auctions AuctionCounter (r:1 w:1) + /// Proof: Auctions AuctionCounter (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn new_auction() -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `1493` - // Minimum execution time: 7_307_000 picoseconds. - Weight::from_parts(7_680_000, 0) + // Minimum execution time: 12_805_000 picoseconds. + Weight::from_parts(13_153_000, 0) .saturating_add(Weight::from_parts(0, 1493)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Auctions::AuctionCounter` (r:1 w:0) - /// Proof: `Auctions::AuctionCounter` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Auctions::AuctionInfo` (r:1 w:0) - /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Slots::Leases` (r:1 w:0) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Auctions::Winning` (r:1 w:1) - /// Proof: `Auctions::Winning` (`max_values`: None, `max_size`: Some(1920), added: 4395, mode: `MaxEncodedLen`) - /// Storage: `Auctions::ReservedAmounts` (r:2 w:2) - /// Proof: `Auctions::ReservedAmounts` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Paras ParaLifecycles (r:1 w:0) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Auctions AuctionCounter (r:1 w:0) + /// Proof: Auctions AuctionCounter (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Auctions AuctionInfo (r:1 w:0) + /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Slots Leases (r:1 w:0) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: Auctions Winning (r:1 w:1) + /// Proof: Auctions Winning (max_values: None, max_size: Some(1920), added: 4395, mode: MaxEncodedLen) + /// Storage: Auctions ReservedAmounts (r:2 w:2) + /// Proof: Auctions ReservedAmounts (max_values: None, max_size: Some(60), added: 2535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn bid() -> Weight { // Proof Size summary in bytes: - // Measured: `761` + // Measured: `728` // Estimated: `6060` - // Minimum execution time: 75_448_000 picoseconds. - Weight::from_parts(78_716_000, 0) + // Minimum execution time: 77_380_000 picoseconds. + Weight::from_parts(80_503_000, 0) .saturating_add(Weight::from_parts(0, 6060)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `Auctions::AuctionInfo` (r:1 w:1) - /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Babe::NextRandomness` (r:1 w:0) - /// Proof: `Babe::NextRandomness` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `Babe::EpochStart` (r:1 w:0) - /// Proof: `Babe::EpochStart` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Auctions::AuctionCounter` (r:1 w:0) - /// Proof: `Auctions::AuctionCounter` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Auctions::Winning` (r:3600 w:3600) - /// Proof: `Auctions::Winning` (`max_values`: None, `max_size`: Some(1920), added: 4395, mode: `MaxEncodedLen`) - /// Storage: `Auctions::ReservedAmounts` (r:37 w:36) - /// Proof: `Auctions::ReservedAmounts` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:36 w:36) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Slots::Leases` (r:2 w:2) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:1) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ActionsQueue` (r:1 w:1) - /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Auctions AuctionInfo (r:1 w:1) + /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Babe NextRandomness (r:1 w:0) + /// Proof: Babe NextRandomness (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: Babe EpochStart (r:1 w:0) + /// Proof: Babe EpochStart (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Auctions AuctionCounter (r:1 w:0) + /// Proof: Auctions AuctionCounter (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Auctions Winning (r:3600 w:3600) + /// Proof: Auctions Winning (max_values: None, max_size: Some(1920), added: 4395, mode: MaxEncodedLen) + /// Storage: Auctions ReservedAmounts (r:37 w:36) + /// Proof: Auctions ReservedAmounts (max_values: None, max_size: Some(60), added: 2535, mode: MaxEncodedLen) + /// Storage: System Account (r:36 w:36) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Slots Leases (r:2 w:2) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:1 w:1) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ActionsQueue (r:1 w:1) + /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) + /// Storage: Registrar Paras (r:1 w:1) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) fn on_initialize() -> Weight { // Proof Size summary in bytes: - // Measured: `6947017` + // Measured: `6947789` // Estimated: `15822990` - // Minimum execution time: 7_120_207_000 picoseconds. - Weight::from_parts(7_273_496_000, 0) + // Minimum execution time: 6_311_055_000 picoseconds. + Weight::from_parts(6_409_142_000, 0) .saturating_add(Weight::from_parts(0, 15822990)) - .saturating_add(T::DbWeight::get().reads(3682)) - .saturating_add(T::DbWeight::get().writes(3677)) + .saturating_add(T::DbWeight::get().reads(3683)) + .saturating_add(T::DbWeight::get().writes(3678)) } - /// Storage: `Auctions::ReservedAmounts` (r:37 w:36) - /// Proof: `Auctions::ReservedAmounts` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:36 w:36) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Auctions::Winning` (r:3600 w:3600) - /// Proof: `Auctions::Winning` (`max_values`: None, `max_size`: Some(1920), added: 4395, mode: `MaxEncodedLen`) - /// Storage: `Auctions::AuctionInfo` (r:0 w:1) - /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Auctions ReservedAmounts (r:37 w:36) + /// Proof: Auctions ReservedAmounts (max_values: None, max_size: Some(60), added: 2535, mode: MaxEncodedLen) + /// Storage: System Account (r:36 w:36) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Auctions Winning (r:3600 w:3600) + /// Proof: Auctions Winning (max_values: None, max_size: Some(1920), added: 4395, mode: MaxEncodedLen) + /// Storage: Auctions AuctionInfo (r:0 w:1) + /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn cancel_auction() -> Weight { // Proof Size summary in bytes: // Measured: `177732` // Estimated: `15822990` - // Minimum execution time: 5_536_281_000 picoseconds. - Weight::from_parts(5_675_163_000, 0) + // Minimum execution time: 4_849_561_000 picoseconds. + Weight::from_parts(4_955_226_000, 0) .saturating_add(Weight::from_parts(0, 15822990)) .saturating_add(T::DbWeight::get().reads(3673)) .saturating_add(T::DbWeight::get().writes(3673)) diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_claims.rs b/polkadot/runtime/rococo/src/weights/runtime_common_claims.rs index de2bb71933b..52e0dd24afa 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_claims.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_claims.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::claims` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_common::claims // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_common_claims.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_common_claims.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,133 +47,120 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::claims`. pub struct WeightInfo(PhantomData); impl runtime_common::claims::WeightInfo for WeightInfo { - /// Storage: `Claims::Claims` (r:1 w:1) - /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Signing` (r:1 w:1) - /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Total` (r:1 w:1) - /// Proof: `Claims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Vesting` (r:1 w:1) - /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: Claims Claims (r:1 w:1) + /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Signing (r:1 w:1) + /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Total (r:1 w:1) + /// Proof Skipped: Claims Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Claims Vesting (r:1 w:1) + /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) fn claim() -> Weight { // Proof Size summary in bytes: // Measured: `558` // Estimated: `4764` - // Minimum execution time: 181_028_000 picoseconds. - Weight::from_parts(194_590_000, 0) + // Minimum execution time: 144_931_000 picoseconds. + Weight::from_parts(156_550_000, 0) .saturating_add(Weight::from_parts(0, 4764)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: `Claims::Total` (r:1 w:1) - /// Proof: `Claims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Vesting` (r:0 w:1) - /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Claims` (r:0 w:1) - /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Signing` (r:0 w:1) - /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Claims Total (r:1 w:1) + /// Proof Skipped: Claims Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Claims Vesting (r:0 w:1) + /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Claims (r:0 w:1) + /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Signing (r:0 w:1) + /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) fn mint_claim() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `1701` - // Minimum execution time: 11_224_000 picoseconds. - Weight::from_parts(13_342_000, 0) + // Minimum execution time: 11_300_000 picoseconds. + Weight::from_parts(11_642_000, 0) .saturating_add(Weight::from_parts(0, 1701)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `Claims::Claims` (r:1 w:1) - /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Signing` (r:1 w:1) - /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Total` (r:1 w:1) - /// Proof: `Claims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Vesting` (r:1 w:1) - /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: Claims Claims (r:1 w:1) + /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Signing (r:1 w:1) + /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Total (r:1 w:1) + /// Proof Skipped: Claims Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Claims Vesting (r:1 w:1) + /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) fn claim_attest() -> Weight { // Proof Size summary in bytes: // Measured: `558` // Estimated: `4764` - // Minimum execution time: 187_964_000 picoseconds. - Weight::from_parts(202_553_000, 0) + // Minimum execution time: 149_112_000 picoseconds. + Weight::from_parts(153_872_000, 0) .saturating_add(Weight::from_parts(0, 4764)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: `Claims::Preclaims` (r:1 w:1) - /// Proof: `Claims::Preclaims` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Signing` (r:1 w:1) - /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Claims` (r:1 w:1) - /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Total` (r:1 w:1) - /// Proof: `Claims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Vesting` (r:1 w:1) - /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Vesting::Vesting` (r:1 w:1) - /// Proof: `Vesting::Vesting` (`max_values`: None, `max_size`: Some(1057), added: 3532, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: Claims Preclaims (r:1 w:1) + /// Proof Skipped: Claims Preclaims (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Signing (r:1 w:1) + /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Claims (r:1 w:1) + /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Total (r:1 w:1) + /// Proof Skipped: Claims Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Claims Vesting (r:1 w:1) + /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) + /// Storage: Vesting Vesting (r:1 w:1) + /// Proof: Vesting Vesting (max_values: None, max_size: Some(1057), added: 3532, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) fn attest() -> Weight { // Proof Size summary in bytes: // Measured: `632` // Estimated: `4764` - // Minimum execution time: 78_210_000 picoseconds. - Weight::from_parts(84_581_000, 0) + // Minimum execution time: 69_619_000 picoseconds. + Weight::from_parts(79_242_000, 0) .saturating_add(Weight::from_parts(0, 4764)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: `Claims::Claims` (r:1 w:2) - /// Proof: `Claims::Claims` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Vesting` (r:1 w:2) - /// Proof: `Claims::Vesting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Signing` (r:1 w:2) - /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Preclaims` (r:1 w:1) - /// Proof: `Claims::Preclaims` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Claims Claims (r:1 w:2) + /// Proof Skipped: Claims Claims (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Vesting (r:1 w:2) + /// Proof Skipped: Claims Vesting (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Signing (r:1 w:2) + /// Proof Skipped: Claims Signing (max_values: None, max_size: None, mode: Measured) + /// Storage: Claims Preclaims (r:1 w:1) + /// Proof Skipped: Claims Preclaims (max_values: None, max_size: None, mode: Measured) fn move_claim() -> Weight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `3905` - // Minimum execution time: 33_940_000 picoseconds. - Weight::from_parts(48_438_000, 0) + // Minimum execution time: 22_066_000 picoseconds. + Weight::from_parts(22_483_000, 0) .saturating_add(Weight::from_parts(0, 3905)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: `Claims::Preclaims` (r:1 w:0) - /// Proof: `Claims::Preclaims` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Claims::Signing` (r:1 w:0) - /// Proof: `Claims::Signing` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn prevalidate_attests() -> Weight { - // Proof Size summary in bytes: - // Measured: `296` - // Estimated: `3761` - // Minimum execution time: 9_025_000 picoseconds. - Weight::from_parts(10_563_000, 0) - .saturating_add(Weight::from_parts(0, 3761)) - .saturating_add(T::DbWeight::get().reads(2)) - } } diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs b/polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs deleted file mode 100644 index d068f07e759..00000000000 --- a/polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Autogenerated weights for `runtime_common::coretime` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=rococo-dev -// --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=runtime_common::coretime -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_common_coretime.rs - -#![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 `runtime_common::coretime`. -pub struct WeightInfo(PhantomData); -impl runtime_common::coretime::WeightInfo for WeightInfo { - /// Storage: `Configuration::PendingConfigs` (r:1 w:1) - /// Proof: `Configuration::PendingConfigs` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Configuration::BypassConsistencyCheck` (r:1 w:0) - /// Proof: `Configuration::BypassConsistencyCheck` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn request_core_count() -> Weight { - // Proof Size summary in bytes: - // Measured: `151` - // Estimated: `1636` - // Minimum execution time: 7_543_000 picoseconds. - Weight::from_parts(7_745_000, 0) - .saturating_add(Weight::from_parts(0, 1636)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) - /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `CoretimeAssignmentProvider::CoreSchedules` (r:0 w:1) - /// Proof: `CoretimeAssignmentProvider::CoreSchedules` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `s` is `[1, 100]`. - fn assign_core(s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `180` - // Estimated: `3645` - // Minimum execution time: 9_367_000 picoseconds. - Weight::from_parts(9_932_305, 0) - .saturating_add(Weight::from_parts(0, 3645)) - // Standard Error: 231 - .saturating_add(Weight::from_parts(12_947, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs b/polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs index 8ebab3d551e..0e7420cba2e 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::crowdloan` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_common::crowdloan // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_common_crowdloan.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_common_crowdloan.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,168 +47,172 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::crowdloan`. pub struct WeightInfo(PhantomData); impl runtime_common::crowdloan::WeightInfo for WeightInfo { - /// Storage: `Crowdloan::Funds` (r:1 w:1) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Registrar::Paras` (r:1 w:0) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Crowdloan::NextFundIndex` (r:1 w:1) - /// Proof: `Crowdloan::NextFundIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Crowdloan Funds (r:1 w:1) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: Registrar Paras (r:1 w:1) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:1 w:0) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Crowdloan NextFundIndex (r:1 w:1) + /// Proof Skipped: Crowdloan NextFundIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `438` // Estimated: `3903` - // Minimum execution time: 46_095_000 picoseconds. - Weight::from_parts(48_111_000, 0) + // Minimum execution time: 50_399_000 picoseconds. + Weight::from_parts(51_641_000, 0) .saturating_add(Weight::from_parts(0, 3903)) .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `Crowdloan::Funds` (r:1 w:1) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Slots::Leases` (r:1 w:0) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Auctions::AuctionInfo` (r:1 w:0) - /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Crowdloan::EndingsCount` (r:1 w:0) - /// Proof: `Crowdloan::EndingsCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Crowdloan::NewRaise` (r:1 w:1) - /// Proof: `Crowdloan::NewRaise` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) - /// Proof: UNKNOWN KEY `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) + /// Storage: Crowdloan Funds (r:1 w:1) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: Slots Leases (r:1 w:0) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: Auctions AuctionInfo (r:1 w:0) + /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances InactiveIssuance (r:1 w:1) + /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Crowdloan EndingsCount (r:1 w:0) + /// Proof Skipped: Crowdloan EndingsCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Crowdloan NewRaise (r:1 w:1) + /// Proof Skipped: Crowdloan NewRaise (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) + /// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) fn contribute() -> Weight { // Proof Size summary in bytes: - // Measured: `563` - // Estimated: `4028` - // Minimum execution time: 133_059_000 picoseconds. - Weight::from_parts(136_515_000, 0) - .saturating_add(Weight::from_parts(0, 4028)) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(4)) + // Measured: `530` + // Estimated: `3995` + // Minimum execution time: 128_898_000 picoseconds. + Weight::from_parts(130_277_000, 0) + .saturating_add(Weight::from_parts(0, 3995)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: `Crowdloan::Funds` (r:1 w:1) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0` (r:1 w:1) - /// Proof: UNKNOWN KEY `0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0` (r:1 w:1) + /// Storage: Crowdloan Funds (r:1 w:1) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances InactiveIssuance (r:1 w:1) + /// Proof: Balances InactiveIssuance (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: unknown `0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0` (r:1 w:1) + /// Proof Skipped: unknown `0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0` (r:1 w:1) fn withdraw() -> Weight { // Proof Size summary in bytes: - // Measured: `687` + // Measured: `689` // Estimated: `6196` - // Minimum execution time: 71_733_000 picoseconds. - Weight::from_parts(74_034_000, 0) + // Minimum execution time: 69_543_000 picoseconds. + Weight::from_parts(71_522_000, 0) .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `k` is `[0, 1000]`. fn refund(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `125 + k * (189 ±0)` - // Estimated: `138 + k * (189 ±0)` - // Minimum execution time: 46_016_000 picoseconds. - Weight::from_parts(48_260_000, 0) - .saturating_add(Weight::from_parts(0, 138)) - // Standard Error: 21_140 - .saturating_add(Weight::from_parts(39_141_925, 0).saturating_mul(k.into())) - .saturating_add(T::DbWeight::get().reads(3)) + // Measured: `127 + k * (189 ±0)` + // Estimated: `140 + k * (189 ±0)` + // Minimum execution time: 50_735_000 picoseconds. + Weight::from_parts(52_282_000, 0) + .saturating_add(Weight::from_parts(0, 140)) + // Standard Error: 21_607 + .saturating_add(Weight::from_parts(38_955_985, 0).saturating_mul(k.into())) + .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(k.into()))) - .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(k.into()))) .saturating_add(Weight::from_parts(0, 189).saturating_mul(k.into())) } - /// Storage: `Crowdloan::Funds` (r:1 w:1) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Crowdloan Funds (r:1 w:1) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn dissolve() -> Weight { // Proof Size summary in bytes: - // Measured: `514` + // Measured: `515` // Estimated: `6196` - // Minimum execution time: 44_724_000 picoseconds. - Weight::from_parts(47_931_000, 0) + // Minimum execution time: 43_100_000 picoseconds. + Weight::from_parts(44_272_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Crowdloan::Funds` (r:1 w:1) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Crowdloan Funds (r:1 w:1) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) fn edit() -> Weight { // Proof Size summary in bytes: - // Measured: `234` - // Estimated: `3699` - // Minimum execution time: 19_512_000 picoseconds. - Weight::from_parts(21_129_000, 0) - .saturating_add(Weight::from_parts(0, 3699)) + // Measured: `235` + // Estimated: `3700` + // Minimum execution time: 18_702_000 picoseconds. + Weight::from_parts(19_408_000, 0) + .saturating_add(Weight::from_parts(0, 3700)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Crowdloan::Funds` (r:1 w:0) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: UNKNOWN KEY `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) - /// Proof: UNKNOWN KEY `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) + /// Storage: Crowdloan Funds (r:1 w:0) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) + /// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1) fn add_memo() -> Weight { // Proof Size summary in bytes: // Measured: `412` // Estimated: `3877` - // Minimum execution time: 33_529_000 picoseconds. - Weight::from_parts(37_082_000, 0) + // Minimum execution time: 25_568_000 picoseconds. + Weight::from_parts(26_203_000, 0) .saturating_add(Weight::from_parts(0, 3877)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Crowdloan::Funds` (r:1 w:0) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Crowdloan::NewRaise` (r:1 w:1) - /// Proof: `Crowdloan::NewRaise` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Crowdloan Funds (r:1 w:0) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: Crowdloan NewRaise (r:1 w:1) + /// Proof Skipped: Crowdloan NewRaise (max_values: Some(1), max_size: None, mode: Measured) fn poke() -> Weight { // Proof Size summary in bytes: - // Measured: `238` - // Estimated: `3703` - // Minimum execution time: 23_153_000 picoseconds. - Weight::from_parts(24_181_000, 0) - .saturating_add(Weight::from_parts(0, 3703)) + // Measured: `239` + // Estimated: `3704` + // Minimum execution time: 17_832_000 picoseconds. + Weight::from_parts(18_769_000, 0) + .saturating_add(Weight::from_parts(0, 3704)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Auctions::AuctionInfo` (r:1 w:0) - /// Proof: `Auctions::AuctionInfo` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Crowdloan::EndingsCount` (r:1 w:1) - /// Proof: `Crowdloan::EndingsCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Crowdloan::NewRaise` (r:1 w:1) - /// Proof: `Crowdloan::NewRaise` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Crowdloan::Funds` (r:100 w:0) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Auctions::AuctionCounter` (r:1 w:0) - /// Proof: `Auctions::AuctionCounter` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Paras::ParaLifecycles` (r:100 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Slots::Leases` (r:100 w:0) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Auctions::Winning` (r:1 w:1) - /// Proof: `Auctions::Winning` (`max_values`: None, `max_size`: Some(1920), added: 4395, mode: `MaxEncodedLen`) - /// Storage: `Auctions::ReservedAmounts` (r:100 w:100) - /// Proof: `Auctions::ReservedAmounts` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:100 w:100) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Auctions AuctionInfo (r:1 w:0) + /// Proof: Auctions AuctionInfo (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Crowdloan EndingsCount (r:1 w:1) + /// Proof Skipped: Crowdloan EndingsCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Crowdloan NewRaise (r:1 w:1) + /// Proof Skipped: Crowdloan NewRaise (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Crowdloan Funds (r:100 w:0) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: Auctions AuctionCounter (r:1 w:0) + /// Proof: Auctions AuctionCounter (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Paras ParaLifecycles (r:100 w:0) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Slots Leases (r:100 w:0) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: Auctions Winning (r:1 w:1) + /// Proof: Auctions Winning (max_values: None, max_size: Some(1920), added: 4395, mode: MaxEncodedLen) + /// Storage: Auctions ReservedAmounts (r:100 w:100) + /// Proof: Auctions ReservedAmounts (max_values: None, max_size: Some(60), added: 2535, mode: MaxEncodedLen) + /// Storage: System Account (r:100 w:100) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[2, 100]`. fn on_initialize(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `229 + n * (356 ±0)` + // Measured: `197 + n * (356 ±0)` // Estimated: `5385 + n * (2832 ±0)` - // Minimum execution time: 120_164_000 picoseconds. - Weight::from_parts(3_390_119, 0) + // Minimum execution time: 128_319_000 picoseconds. + Weight::from_parts(130_877_000, 0) .saturating_add(Weight::from_parts(0, 5385)) - // Standard Error: 41_727 - .saturating_add(Weight::from_parts(54_453_016, 0).saturating_mul(n.into())) + // Standard Error: 61_381 + .saturating_add(Weight::from_parts(60_209_202, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs b/polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs index 9b0cb98e6c0..cec357453b6 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs @@ -1,43 +1,36 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// SPDX-License-Identifier: Apache-2.0 -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . +// 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 `runtime_common::identity_migrator` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-07, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `sbtb`, CPU: `13th Gen Intel(R) Core(TM) i7-1365U` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// ./target/release/polkadot // benchmark // pallet // --chain=rococo-dev -// --steps=50 -// --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares +// --steps=2 +// --repeat=1 // --pallet=runtime_common::identity_migrator // --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_common_identity_migrator.rs +// --output=./migrator-release.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -51,7 +44,7 @@ use core::marker::PhantomData; pub struct WeightInfo(PhantomData); impl runtime_common::identity_migrator::WeightInfo for WeightInfo { /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `Identity::SubsOf` (r:1 w:1) /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:2 w:2) @@ -70,34 +63,34 @@ impl runtime_common::identity_migrator::WeightInfo for /// The range of component `s` is `[0, 100]`. fn reap_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7457 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037 + r * (7 ±0) + s * (32 ±0)` - // Minimum execution time: 157_343_000 picoseconds. - Weight::from_parts(159_289_236, 0) - .saturating_add(Weight::from_parts(0, 11037)) - // Standard Error: 16_439 - .saturating_add(Weight::from_parts(224_293, 0).saturating_mul(r.into())) - // Standard Error: 3_367 - .saturating_add(Weight::from_parts(1_383_637, 0).saturating_mul(s.into())) + // Measured: `7292 + r * (8 ±0) + s * (32 ±0)` + // Estimated: `11003 + r * (8 ±0) + s * (33 ±0)` + // Minimum execution time: 163_756_000 picoseconds. + Weight::from_parts(158_982_500, 0) + .saturating_add(Weight::from_parts(0, 11003)) + // Standard Error: 1_143_629 + .saturating_add(Weight::from_parts(238_675, 0).saturating_mul(r.into())) + // Standard Error: 228_725 + .saturating_add(Weight::from_parts(1_529_645, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes(5)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) - .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) - .saturating_add(Weight::from_parts(0, 32).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 33).saturating_mul(s.into())) } /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7538), added: 10013, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Identity::SubsOf` (r:1 w:1) /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) fn poke_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `7242` - // Estimated: `11037` - // Minimum execution time: 114_384_000 picoseconds. - Weight::from_parts(115_741_000, 0) - .saturating_add(Weight::from_parts(0, 11037)) + // Measured: `7229` + // Estimated: `11003` + // Minimum execution time: 137_570_000 picoseconds. + Weight::from_parts(137_570_000, 0) + .saturating_add(Weight::from_parts(0, 11003)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs b/polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs index e066106e134..0a56562a1a9 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::paras_registrar` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_common::paras_registrar // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_common_paras_registrar.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_common_paras_registrar.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,169 +47,175 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::paras_registrar`. pub struct WeightInfo(PhantomData); impl runtime_common::paras_registrar::WeightInfo for WeightInfo { - /// Storage: `Registrar::NextFreeParaId` (r:1 w:1) - /// Proof: `Registrar::NextFreeParaId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Registrar::Paras` (r:1 w:1) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Registrar NextFreeParaId (r:1 w:1) + /// Proof Skipped: Registrar NextFreeParaId (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Registrar Paras (r:1 w:1) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:1 w:0) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) fn reserve() -> Weight { // Proof Size summary in bytes: - // Measured: `96` - // Estimated: `3561` - // Minimum execution time: 24_109_000 picoseconds. - Weight::from_parts(24_922_000, 0) - .saturating_add(Weight::from_parts(0, 3561)) + // Measured: `97` + // Estimated: `3562` + // Minimum execution time: 29_948_000 picoseconds. + Weight::from_parts(30_433_000, 0) + .saturating_add(Weight::from_parts(0, 3562)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Registrar::Paras` (r:1 w:1) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:1) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHash` (r:1 w:1) - /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) - /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CurrentCodeHash` (r:0 w:1) - /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpcomingParasGenesis` (r:0 w:1) - /// Proof: `Paras::UpcomingParasGenesis` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Registrar Paras (r:1 w:1) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:1 w:1) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CodeByHash (r:1 w:1) + /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteList (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras CodeByHashRefs (r:1 w:1) + /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CurrentCodeHash (r:0 w:1) + /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras UpcomingParasGenesis (r:0 w:1) + /// Proof Skipped: Paras UpcomingParasGenesis (max_values: None, max_size: None, mode: Measured) fn register() -> Weight { // Proof Size summary in bytes: - // Measured: `352` - // Estimated: `3817` - // Minimum execution time: 7_207_580_000 picoseconds. - Weight::from_parts(7_298_567_000, 0) - .saturating_add(Weight::from_parts(0, 3817)) - .saturating_add(T::DbWeight::get().reads(7)) + // Measured: `616` + // Estimated: `4081` + // Minimum execution time: 6_332_113_000 picoseconds. + Weight::from_parts(6_407_158_000, 0) + .saturating_add(Weight::from_parts(0, 4081)) + .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(8)) } - /// Storage: `Registrar::Paras` (r:1 w:1) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:1) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHash` (r:1 w:1) - /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) - /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CurrentCodeHash` (r:0 w:1) - /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpcomingParasGenesis` (r:0 w:1) - /// Proof: `Paras::UpcomingParasGenesis` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Registrar Paras (r:1 w:1) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:1 w:1) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CodeByHash (r:1 w:1) + /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteList (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras CodeByHashRefs (r:1 w:1) + /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CurrentCodeHash (r:0 w:1) + /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras UpcomingParasGenesis (r:0 w:1) + /// Proof Skipped: Paras UpcomingParasGenesis (max_values: None, max_size: None, mode: Measured) fn force_register() -> Weight { // Proof Size summary in bytes: - // Measured: `269` - // Estimated: `3734` - // Minimum execution time: 7_196_460_000 picoseconds. - Weight::from_parts(7_385_729_000, 0) - .saturating_add(Weight::from_parts(0, 3734)) - .saturating_add(T::DbWeight::get().reads(7)) + // Measured: `533` + // Estimated: `3998` + // Minimum execution time: 6_245_403_000 picoseconds. + Weight::from_parts(6_289_575_000, 0) + .saturating_add(Weight::from_parts(0, 3998)) + .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(8)) } - /// Storage: `Registrar::Paras` (r:1 w:1) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:1) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::FutureCodeHash` (r:1 w:0) - /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ActionsQueue` (r:1 w:1) - /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `Registrar::PendingSwap` (r:0 w:1) - /// Proof: `Registrar::PendingSwap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Registrar Paras (r:1 w:1) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:1 w:1) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras FutureCodeHash (r:1 w:0) + /// Proof Skipped: Paras FutureCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ActionsQueue (r:1 w:1) + /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) + /// Storage: MessageQueue BookStateFor (r:1 w:0) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: Registrar PendingSwap (r:0 w:1) + /// Proof Skipped: Registrar PendingSwap (max_values: None, max_size: None, mode: Measured) fn deregister() -> Weight { // Proof Size summary in bytes: - // Measured: `499` - // Estimated: `3964` - // Minimum execution time: 54_761_000 picoseconds. - Weight::from_parts(57_931_000, 0) - .saturating_add(Weight::from_parts(0, 3964)) + // Measured: `476` + // Estimated: `3941` + // Minimum execution time: 49_822_000 picoseconds. + Weight::from_parts(50_604_000, 0) + .saturating_add(Weight::from_parts(0, 3941)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `Registrar::Paras` (r:1 w:0) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:2 w:2) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Registrar::PendingSwap` (r:1 w:1) - /// Proof: `Registrar::PendingSwap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ActionsQueue` (r:1 w:1) - /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Crowdloan::Funds` (r:2 w:2) - /// Proof: `Crowdloan::Funds` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Slots::Leases` (r:2 w:2) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Registrar Paras (r:1 w:0) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:2 w:2) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Registrar PendingSwap (r:1 w:1) + /// Proof Skipped: Registrar PendingSwap (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ActionsQueue (r:1 w:1) + /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) + /// Storage: Crowdloan Funds (r:2 w:2) + /// Proof Skipped: Crowdloan Funds (max_values: None, max_size: None, mode: Measured) + /// Storage: Slots Leases (r:2 w:2) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) fn swap() -> Weight { // Proof Size summary in bytes: - // Measured: `837` - // Estimated: `6777` - // Minimum execution time: 59_564_000 picoseconds. - Weight::from_parts(62_910_000, 0) - .saturating_add(Weight::from_parts(0, 6777)) + // Measured: `780` + // Estimated: `6720` + // Minimum execution time: 55_166_000 picoseconds. + Weight::from_parts(56_913_000, 0) + .saturating_add(Weight::from_parts(0, 6720)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(8)) } - /// Storage: `Paras::FutureCodeHash` (r:1 w:1) - /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeRestrictionSignal` (r:1 w:1) - /// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) - /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeCooldowns` (r:1 w:1) - /// Proof: `Paras::UpgradeCooldowns` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHash` (r:1 w:1) - /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) - /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `b` is `[9, 3145728]`. + /// Storage: Paras FutureCodeHash (r:1 w:1) + /// Proof Skipped: Paras FutureCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras UpgradeRestrictionSignal (r:1 w:1) + /// Proof Skipped: Paras UpgradeRestrictionSignal (max_values: None, max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras CurrentCodeHash (r:1 w:0) + /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras UpgradeCooldowns (r:1 w:1) + /// Proof Skipped: Paras UpgradeCooldowns (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CodeByHash (r:1 w:1) + /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteList (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras CodeByHashRefs (r:1 w:1) + /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) + /// The range of component `b` is `[1, 3145728]`. fn schedule_code_upgrade(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `201` - // Estimated: `3666` - // Minimum execution time: 33_106_000 picoseconds. - Weight::from_parts(33_526_000, 0) - .saturating_add(Weight::from_parts(0, 3666)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(2_334, 0).saturating_mul(b.into())) - .saturating_add(T::DbWeight::get().reads(9)) + // Measured: `464` + // Estimated: `3929` + // Minimum execution time: 43_650_000 picoseconds. + Weight::from_parts(43_918_000, 0) + .saturating_add(Weight::from_parts(0, 3929)) + // Standard Error: 6 + .saturating_add(Weight::from_parts(2_041, 0).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: `Paras::Heads` (r:0 w:1) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Paras Heads (r:0 w:1) + /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[1, 1048576]`. fn set_current_head(b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_992_000 picoseconds. - Weight::from_parts(12_059_689, 0) + // Minimum execution time: 8_666_000 picoseconds. + Weight::from_parts(8_893_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 0 - .saturating_add(Weight::from_parts(959, 0).saturating_mul(b.into())) + // Standard Error: 2 + .saturating_add(Weight::from_parts(855, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/polkadot/runtime/rococo/src/weights/runtime_common_slots.rs b/polkadot/runtime/rococo/src/weights/runtime_common_slots.rs index dd10dbbf1f1..23ab1ed3ee0 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_common_slots.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_common_slots.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_common::slots` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_common::slots // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_common_slots.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_common_slots.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,82 +47,86 @@ use core::marker::PhantomData; /// Weight functions for `runtime_common::slots`. pub struct WeightInfo(PhantomData); impl runtime_common::slots::WeightInfo for WeightInfo { - /// Storage: `Slots::Leases` (r:1 w:1) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Slots Leases (r:1 w:1) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn force_lease() -> Weight { // Proof Size summary in bytes: - // Measured: `320` - // Estimated: `3785` - // Minimum execution time: 26_570_000 picoseconds. - Weight::from_parts(27_619_000, 0) - .saturating_add(Weight::from_parts(0, 3785)) + // Measured: `287` + // Estimated: `3752` + // Minimum execution time: 29_932_000 picoseconds. + Weight::from_parts(30_334_000, 0) + .saturating_add(Weight::from_parts(0, 3752)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `Paras::Parachains` (r:1 w:0) - /// Proof: `Paras::Parachains` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Slots::Leases` (r:101 w:100) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:200 w:200) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ActionsQueue` (r:1 w:1) - /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Paras Parachains (r:1 w:0) + /// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Slots Leases (r:101 w:100) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:200 w:200) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ActionsQueue (r:1 w:1) + /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) + /// Storage: Registrar Paras (r:100 w:100) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) /// The range of component `c` is `[0, 100]`. /// The range of component `t` is `[0, 100]`. fn manage_lease_period_start(c: u32, t: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `594 + c * (20 ±0) + t * (234 ±0)` - // Estimated: `4065 + c * (2496 ±0) + t * (2709 ±0)` - // Minimum execution time: 729_793_000 picoseconds. - Weight::from_parts(740_820_000, 0) - .saturating_add(Weight::from_parts(0, 4065)) - // Standard Error: 88_206 - .saturating_add(Weight::from_parts(2_793_142, 0).saturating_mul(c.into())) - // Standard Error: 88_206 - .saturating_add(Weight::from_parts(8_933_065, 0).saturating_mul(t.into())) + // Measured: `26 + c * (47 ±0) + t * (308 ±0)` + // Estimated: `2800 + c * (2526 ±0) + t * (2789 ±0)` + // Minimum execution time: 634_547_000 picoseconds. + Weight::from_parts(643_045_000, 0) + .saturating_add(Weight::from_parts(0, 2800)) + // Standard Error: 81_521 + .saturating_add(Weight::from_parts(2_705_219, 0).saturating_mul(c.into())) + // Standard Error: 81_521 + .saturating_add(Weight::from_parts(11_464_132, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) - .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(t.into()))) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(t.into()))) - .saturating_add(Weight::from_parts(0, 2496).saturating_mul(c.into())) - .saturating_add(Weight::from_parts(0, 2709).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(t.into()))) + .saturating_add(Weight::from_parts(0, 2526).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(0, 2789).saturating_mul(t.into())) } - /// Storage: `Slots::Leases` (r:1 w:1) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:8 w:8) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Slots Leases (r:1 w:1) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:8 w:8) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn clear_all_leases() -> Weight { // Proof Size summary in bytes: - // Measured: `2792` + // Measured: `2759` // Estimated: `21814` - // Minimum execution time: 123_888_000 picoseconds. - Weight::from_parts(131_245_000, 0) + // Minimum execution time: 129_756_000 picoseconds. + Weight::from_parts(131_810_000, 0) .saturating_add(Weight::from_parts(0, 21814)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(9)) } - /// Storage: `Slots::Leases` (r:1 w:0) - /// Proof: `Slots::Leases` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:1) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ActionsQueue` (r:1 w:1) - /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Slots Leases (r:1 w:0) + /// Proof Skipped: Slots Leases (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:1 w:1) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ActionsQueue (r:1 w:1) + /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) + /// Storage: Registrar Paras (r:1 w:1) + /// Proof Skipped: Registrar Paras (max_values: None, max_size: None, mode: Measured) fn trigger_onboard() -> Weight { // Proof Size summary in bytes: - // Measured: `612` - // Estimated: `4077` - // Minimum execution time: 27_341_000 picoseconds. - Weight::from_parts(28_697_000, 0) - .saturating_add(Weight::from_parts(0, 4077)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `707` + // Estimated: `4172` + // Minimum execution time: 29_527_000 picoseconds. + Weight::from_parts(30_055_000, 0) + .saturating_add(Weight::from_parts(0, 4172)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs index 653e1009f31..ac0f05301b4 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs @@ -16,28 +16,26 @@ //! Autogenerated weights for `runtime_parachains::assigner_on_demand` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-fljshgub-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=runtime_parachains::assigner_on_demand // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json +// --pallet=runtime_parachains::assigner_on_demand +// --chain=rococo-dev +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -59,13 +57,13 @@ impl runtime_parachains::assigner_on_demand::WeightInfo /// The range of component `s` is `[1, 9999]`. fn place_order_keep_alive(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `363 + s * (4 ±0)` - // Estimated: `3828 + s * (4 ±0)` - // Minimum execution time: 25_298_000 picoseconds. - Weight::from_parts(21_486_098, 0) - .saturating_add(Weight::from_parts(0, 3828)) - // Standard Error: 136 - .saturating_add(Weight::from_parts(13_943, 0).saturating_mul(s.into())) + // Measured: `297 + s * (4 ±0)` + // Estimated: `3762 + s * (4 ±0)` + // Minimum execution time: 33_522_000 picoseconds. + Weight::from_parts(35_436_835, 0) + .saturating_add(Weight::from_parts(0, 3762)) + // Standard Error: 129 + .saturating_add(Weight::from_parts(14_041, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) @@ -79,13 +77,13 @@ impl runtime_parachains::assigner_on_demand::WeightInfo /// The range of component `s` is `[1, 9999]`. fn place_order_allow_death(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `363 + s * (4 ±0)` - // Estimated: `3828 + s * (4 ±0)` - // Minimum execution time: 25_421_000 picoseconds. - Weight::from_parts(21_828_043, 0) - .saturating_add(Weight::from_parts(0, 3828)) - // Standard Error: 133 - .saturating_add(Weight::from_parts(13_831, 0).saturating_mul(s.into())) + // Measured: `297 + s * (4 ±0)` + // Estimated: `3762 + s * (4 ±0)` + // Minimum execution time: 33_488_000 picoseconds. + Weight::from_parts(34_848_934, 0) + .saturating_add(Weight::from_parts(0, 3762)) + // Standard Error: 143 + .saturating_add(Weight::from_parts(14_215, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs index caad090ae15..ca0575cb1b6 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs @@ -17,27 +17,25 @@ //! Autogenerated weights for `runtime_parachains::configuration` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet -// --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --pallet=runtime_parachains::configuration // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=runtime_parachains::configuration +// --chain=rococo-dev // --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_configuration.rs +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -60,8 +58,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_689_000 picoseconds. - Weight::from_parts(8_089_000, 0) + // Minimum execution time: 7_789_000 picoseconds. + Weight::from_parts(8_269_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -76,8 +74,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_735_000 picoseconds. - Weight::from_parts(8_150_000, 0) + // Minimum execution time: 7_851_000 picoseconds. + Weight::from_parts(8_152_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -92,8 +90,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_902_000 picoseconds. - Weight::from_parts(8_196_000, 0) + // Minimum execution time: 7_960_000 picoseconds. + Weight::from_parts(8_276_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -118,8 +116,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_634_000 picoseconds. - Weight::from_parts(7_983_000, 0) + // Minimum execution time: 7_912_000 picoseconds. + Weight::from_parts(8_164_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -134,8 +132,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 9_580_000 picoseconds. - Weight::from_parts(9_989_000, 0) + // Minimum execution time: 9_782_000 picoseconds. + Weight::from_parts(10_373_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -150,8 +148,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_787_000 picoseconds. - Weight::from_parts(8_008_000, 0) + // Minimum execution time: 7_870_000 picoseconds. + Weight::from_parts(8_274_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -166,8 +164,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 9_557_000 picoseconds. - Weight::from_parts(9_994_000, 0) + // Minimum execution time: 9_960_000 picoseconds. + Weight::from_parts(10_514_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -182,8 +180,8 @@ impl runtime_parachains::configuration::WeightInfo for // Proof Size summary in bytes: // Measured: `151` // Estimated: `1636` - // Minimum execution time: 7_775_000 picoseconds. - Weight::from_parts(7_989_000, 0) + // Minimum execution time: 7_913_000 picoseconds. + Weight::from_parts(8_338_000, 0) .saturating_add(Weight::from_parts(0, 1636)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs index cf1aa36e10e..63a8c3addc7 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::disputes` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_parachains::disputes // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_disputes.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_parachains_disputes.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,14 +47,14 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::disputes`. pub struct WeightInfo(PhantomData); impl runtime_parachains::disputes::WeightInfo for WeightInfo { - /// Storage: `ParasDisputes::Frozen` (r:0 w:1) - /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ParasDisputes Frozen (r:0 w:1) + /// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured) fn force_unfreeze() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_855_000 picoseconds. - Weight::from_parts(2_015_000, 0) + // Minimum execution time: 2_937_000 picoseconds. + Weight::from_parts(3_082_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs index a3b912491e5..417820e6627 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::hrmp` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_parachains::hrmp // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_hrmp.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_parachains_hrmp.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,97 +47,105 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::hrmp`. pub struct WeightInfo(PhantomData); impl runtime_parachains::hrmp::WeightInfo for WeightInfo { - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) - /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:1 w:0) - /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Paras ParaLifecycles (r:2 w:0) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpChannels (r:1 w:0) + /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) + /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueues (r:1 w:1) + /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) fn hrmp_init_open_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `488` - // Estimated: `3953` - // Minimum execution time: 34_911_000 picoseconds. - Weight::from_parts(35_762_000, 0) - .saturating_add(Weight::from_parts(0, 3953)) - .saturating_add(T::DbWeight::get().reads(8)) + // Measured: `704` + // Estimated: `6644` + // Minimum execution time: 41_564_000 picoseconds. + Weight::from_parts(42_048_000, 0) + .saturating_add(Weight::from_parts(0, 6644)) + .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(5)) } - /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:1 w:0) - /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:1 w:1) - /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:1 w:0) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) + /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) + /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueues (r:1 w:1) + /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) fn hrmp_accept_open_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `478` - // Estimated: `3943` - // Minimum execution time: 31_483_000 picoseconds. - Weight::from_parts(32_230_000, 0) - .saturating_add(Weight::from_parts(0, 3943)) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `936` + // Estimated: `4401` + // Minimum execution time: 43_570_000 picoseconds. + Weight::from_parts(44_089_000, 0) + .saturating_add(Weight::from_parts(0, 4401)) + .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) - /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpCloseChannelRequests` (r:1 w:1) - /// Proof: `Hrmp::HrmpCloseChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpCloseChannelRequestsList` (r:1 w:1) - /// Proof: `Hrmp::HrmpCloseChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Hrmp HrmpChannels (r:1 w:0) + /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) + /// Proof Skipped: Hrmp HrmpCloseChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) + /// Proof Skipped: Hrmp HrmpCloseChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueues (r:1 w:1) + /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) fn hrmp_close_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `591` - // Estimated: `4056` - // Minimum execution time: 32_153_000 picoseconds. - Weight::from_parts(32_982_000, 0) - .saturating_add(Weight::from_parts(0, 4056)) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `807` + // Estimated: `4272` + // Minimum execution time: 36_594_000 picoseconds. + Weight::from_parts(37_090_000, 0) + .saturating_add(Weight::from_parts(0, 4272)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) - /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) - /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannels` (r:254 w:254) - /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:0 w:1) - /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannelContents` (r:0 w:254) - /// Proof: `Hrmp::HrmpChannelContents` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:0 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) + /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) + /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpChannels (r:254 w:254) + /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1) + /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpChannelContents (r:0 w:254) + /// Proof Skipped: Hrmp HrmpChannelContents (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) /// The range of component `i` is `[0, 127]`. /// The range of component `e` is `[0, 127]`. fn force_clean_hrmp(i: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `297 + e * (100 ±0) + i * (100 ±0)` - // Estimated: `3759 + e * (2575 ±0) + i * (2575 ±0)` - // Minimum execution time: 1_240_769_000 picoseconds. - Weight::from_parts(1_249_285_000, 0) - .saturating_add(Weight::from_parts(0, 3759)) - // Standard Error: 112_346 - .saturating_add(Weight::from_parts(3_449_114, 0).saturating_mul(i.into())) - // Standard Error: 112_346 - .saturating_add(Weight::from_parts(3_569_184, 0).saturating_mul(e.into())) + // Measured: `264 + e * (100 ±0) + i * (100 ±0)` + // Estimated: `3726 + e * (2575 ±0) + i * (2575 ±0)` + // Minimum execution time: 1_085_140_000 picoseconds. + Weight::from_parts(1_100_901_000, 0) + .saturating_add(Weight::from_parts(0, 3726)) + // Standard Error: 98_982 + .saturating_add(Weight::from_parts(3_229_112, 0).saturating_mul(i.into())) + // Standard Error: 98_982 + .saturating_add(Weight::from_parts(3_210_944, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(e.into()))) @@ -150,139 +155,139 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf .saturating_add(Weight::from_parts(0, 2575).saturating_mul(e.into())) .saturating_add(Weight::from_parts(0, 2575).saturating_mul(i.into())) } - /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:128 w:128) - /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:256 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) - /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) - /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:128 w:128) - /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:128 w:128) - /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannels` (r:0 w:128) - /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequests (r:128 w:128) + /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras ParaLifecycles (r:256 w:0) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) + /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) + /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequestCount (r:128 w:128) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:128 w:128) + /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpChannels (r:0 w:128) + /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_open(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `525 + c * (136 ±0)` - // Estimated: `1980 + c * (5086 ±0)` - // Minimum execution time: 6_026_000 picoseconds. - Weight::from_parts(6_257_000, 0) - .saturating_add(Weight::from_parts(0, 1980)) - // Standard Error: 9_732 - .saturating_add(Weight::from_parts(21_049_890, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(1)) + // Measured: `779 + c * (136 ±0)` + // Estimated: `2234 + c * (5086 ±0)` + // Minimum execution time: 10_497_000 picoseconds. + Weight::from_parts(6_987_455, 0) + .saturating_add(Weight::from_parts(0, 2234)) + // Standard Error: 18_540 + .saturating_add(Weight::from_parts(18_788_534, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((6_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 5086).saturating_mul(c.into())) } - /// Storage: `Hrmp::HrmpCloseChannelRequestsList` (r:1 w:1) - /// Proof: `Hrmp::HrmpCloseChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannels` (r:128 w:128) - /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:128 w:128) - /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:128 w:128) - /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpCloseChannelRequests` (r:0 w:128) - /// Proof: `Hrmp::HrmpCloseChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannelContents` (r:0 w:128) - /// Proof: `Hrmp::HrmpChannelContents` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) + /// Proof Skipped: Hrmp HrmpCloseChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Hrmp HrmpChannels (r:128 w:128) + /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpEgressChannelsIndex (r:128 w:128) + /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:128) + /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpCloseChannelRequests (r:0 w:128) + /// Proof Skipped: Hrmp HrmpCloseChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpChannelContents (r:0 w:128) + /// Proof Skipped: Hrmp HrmpChannelContents (max_values: None, max_size: None, mode: Measured) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_close(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `368 + c * (124 ±0)` - // Estimated: `1828 + c * (2600 ±0)` - // Minimum execution time: 4_991_000 picoseconds. - Weight::from_parts(984_758, 0) - .saturating_add(Weight::from_parts(0, 1828)) - // Standard Error: 11_918 - .saturating_add(Weight::from_parts(13_018_813, 0).saturating_mul(c.into())) + // Measured: `335 + c * (124 ±0)` + // Estimated: `1795 + c * (2600 ±0)` + // Minimum execution time: 6_575_000 picoseconds. + Weight::from_parts(1_228_642, 0) + .saturating_add(Weight::from_parts(0, 1795)) + // Standard Error: 14_826 + .saturating_add(Weight::from_parts(11_604_038, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2600).saturating_mul(c.into())) } - /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) /// The range of component `c` is `[0, 128]`. fn hrmp_cancel_open_request(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1059 + c * (13 ±0)` - // Estimated: `4328 + c * (15 ±0)` - // Minimum execution time: 17_299_000 picoseconds. - Weight::from_parts(27_621_478, 0) - .saturating_add(Weight::from_parts(0, 4328)) - // Standard Error: 2_527 - .saturating_add(Weight::from_parts(121_149, 0).saturating_mul(c.into())) + // Measured: `1026 + c * (13 ±0)` + // Estimated: `4295 + c * (15 ±0)` + // Minimum execution time: 22_301_000 picoseconds. + Weight::from_parts(26_131_473, 0) + .saturating_add(Weight::from_parts(0, 4295)) + // Standard Error: 830 + .saturating_add(Weight::from_parts(49_448, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(Weight::from_parts(0, 15).saturating_mul(c.into())) } - /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:128 w:128) - /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequests (r:128 w:128) + /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) /// The range of component `c` is `[0, 128]`. fn clean_open_channel_requests(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `276 + c * (63 ±0)` - // Estimated: `1755 + c * (2538 ±0)` - // Minimum execution time: 3_764_000 picoseconds. - Weight::from_parts(5_935_301, 0) - .saturating_add(Weight::from_parts(0, 1755)) - // Standard Error: 3_761 - .saturating_add(Weight::from_parts(3_290_277, 0).saturating_mul(c.into())) + // Measured: `243 + c * (63 ±0)` + // Estimated: `1722 + c * (2538 ±0)` + // Minimum execution time: 5_234_000 picoseconds. + Weight::from_parts(7_350_270, 0) + .saturating_add(Weight::from_parts(0, 1722)) + // Standard Error: 3_105 + .saturating_add(Weight::from_parts(2_981_935, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2538).saturating_mul(c.into())) } - /// Storage: `Hrmp::HrmpOpenChannelRequests` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequestsList` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestsList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpOpenChannelRequestCount` (r:1 w:1) - /// Proof: `Hrmp::HrmpOpenChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannels` (r:1 w:0) - /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpEgressChannelsIndex` (r:1 w:0) - /// Proof: `Hrmp::HrmpEgressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:2 w:2) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueueHeads` (r:2 w:2) - /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpIngressChannelsIndex` (r:1 w:0) - /// Proof: `Hrmp::HrmpIngressChannelsIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpAcceptedChannelRequestCount` (r:1 w:1) - /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `c` is `[0, 1]`. - fn force_open_hrmp_channel(c: u32, ) -> Weight { + /// Storage: Paras ParaLifecycles (r:2 w:0) + /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpChannels (r:1 w:0) + /// Proof Skipped: Hrmp HrmpChannels (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) + /// Proof Skipped: Hrmp HrmpEgressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestCount (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) + /// Proof Skipped: Hrmp HrmpOpenChannelRequestsList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueues (r:2 w:2) + /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) + /// Storage: Dmp DownwardMessageQueueHeads (r:2 w:2) + /// Proof Skipped: Dmp DownwardMessageQueueHeads (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) + /// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured) + /// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) + /// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured) + fn force_open_hrmp_channel(_c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `488 + c * (235 ±0)` - // Estimated: `6428 + c * (235 ±0)` - // Minimum execution time: 49_506_000 picoseconds. - Weight::from_parts(51_253_075, 0) - .saturating_add(Weight::from_parts(0, 6428)) - // Standard Error: 144_082 - .saturating_add(Weight::from_parts(12_862_224, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(12)) + // Measured: `704` + // Estimated: `6644` + // Minimum execution time: 55_611_000 picoseconds. + Weight::from_parts(56_488_000, 0) + .saturating_add(Weight::from_parts(0, 6644)) + .saturating_add(T::DbWeight::get().reads(14)) .saturating_add(T::DbWeight::get().writes(8)) - .saturating_add(Weight::from_parts(0, 235).saturating_mul(c.into())) } /// Storage: `Paras::ParaLifecycles` (r:1 w:0) /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -306,11 +311,11 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// Proof: `Hrmp::HrmpAcceptedChannelRequestCount` (`max_values`: None, `max_size`: None, mode: `Measured`) fn establish_system_channel() -> Weight { // Proof Size summary in bytes: - // Measured: `488` - // Estimated: `6428` - // Minimum execution time: 50_016_000 picoseconds. - Weight::from_parts(50_933_000, 0) - .saturating_add(Weight::from_parts(0, 6428)) + // Measured: `417` + // Estimated: `6357` + // Minimum execution time: 629_674_000 picoseconds. + Weight::from_parts(640_174_000, 0) + .saturating_add(Weight::from_parts(0, 6357)) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(8)) } @@ -318,11 +323,11 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// Proof: `Hrmp::HrmpChannels` (`max_values`: None, `max_size`: None, mode: `Measured`) fn poke_channel_deposits() -> Weight { // Proof Size summary in bytes: - // Measured: `296` - // Estimated: `3761` - // Minimum execution time: 12_280_000 picoseconds. - Weight::from_parts(12_863_000, 0) - .saturating_add(Weight::from_parts(0, 3761)) + // Measured: `263` + // Estimated: `3728` + // Minimum execution time: 173_371_000 picoseconds. + Weight::from_parts(175_860_000, 0) + .saturating_add(Weight::from_parts(0, 3728)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs index b9ec7565bd5..a121ad774ce 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::inclusion` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_parachains::inclusion // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_inclusion.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_parachains_inclusion.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,25 +47,27 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::inclusion`. pub struct WeightInfo(PhantomData); impl runtime_parachains::inclusion::WeightInfo for WeightInfo { - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:999) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(32818), added: 35293, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) - /// Storage: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) - /// Proof: UNKNOWN KEY `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:999) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(32818), added: 35293, mode: MaxEncodedLen) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Proof Skipped: unknown `0x3a72656c61795f64697370617463685f71756575655f72656d61696e696e675f` (r:0 w:1) + /// Storage: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) + /// Proof Skipped: unknown `0xf5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e` (r:0 w:1) /// The range of component `i` is `[1, 1000]`. fn receive_upward_messages(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32993` + // Measured: `33280` // Estimated: `36283` - // Minimum execution time: 72_675_000 picoseconds. - Weight::from_parts(73_290_000, 0) + // Minimum execution time: 71_094_000 picoseconds. + Weight::from_parts(71_436_000, 0) .saturating_add(Weight::from_parts(0, 36283)) - // Standard Error: 16_067 - .saturating_add(Weight::from_parts(57_735_739, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(2)) + // Standard Error: 22_149 + .saturating_add(Weight::from_parts(51_495_472, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs index e8c554610c9..5c627507dfb 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::initializer` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_parachains::initializer // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_initializer.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_parachains_initializer.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,18 +47,18 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::initializer`. pub struct WeightInfo(PhantomData); impl runtime_parachains::initializer::WeightInfo for WeightInfo { - /// Storage: `System::Digest` (r:1 w:1) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `d` is `[0, 65536]`. fn force_approve(d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + d * (11 ±0)` // Estimated: `1480 + d * (11 ±0)` - // Minimum execution time: 2_634_000 picoseconds. - Weight::from_parts(2_728_000, 0) + // Minimum execution time: 3_771_000 picoseconds. + Weight::from_parts(6_491_437, 0) .saturating_add(Weight::from_parts(0, 1480)) - // Standard Error: 19 - .saturating_add(Weight::from_parts(2_499, 0).saturating_mul(d.into())) + // Standard Error: 9 + .saturating_add(Weight::from_parts(1_356, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 11).saturating_mul(d.into())) diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs index af26bfc9ae9..dfd95006dc7 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::paras` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 1024 // Executed Command: // ./target/production/polkadot @@ -29,15 +29,12 @@ // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_parachains::paras // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_paras.rs +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/runtime_parachains_paras.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,248 +47,247 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::paras`. pub struct WeightInfo(PhantomData); impl runtime_parachains::paras::WeightInfo for WeightInfo { - /// Storage: `Paras::CurrentCodeHash` (r:1 w:1) - /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) - /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PastCodeMeta` (r:1 w:1) - /// Proof: `Paras::PastCodeMeta` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PastCodePruning` (r:1 w:1) - /// Proof: `Paras::PastCodePruning` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PastCodeHash` (r:0 w:1) - /// Proof: `Paras::PastCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHash` (r:0 w:1) - /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Paras CurrentCodeHash (r:1 w:1) + /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CodeByHashRefs (r:1 w:1) + /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras PastCodeMeta (r:1 w:1) + /// Proof Skipped: Paras PastCodeMeta (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras PastCodePruning (r:1 w:1) + /// Proof Skipped: Paras PastCodePruning (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PastCodeHash (r:0 w:1) + /// Proof Skipped: Paras PastCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CodeByHash (r:0 w:1) + /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) /// The range of component `c` is `[1, 3145728]`. fn force_set_current_code(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `8309` // Estimated: `11774` - // Minimum execution time: 27_488_000 picoseconds. - Weight::from_parts(27_810_000, 0) + // Minimum execution time: 31_941_000 picoseconds. + Weight::from_parts(32_139_000, 0) .saturating_add(Weight::from_parts(0, 11774)) - // Standard Error: 8 - .saturating_add(Weight::from_parts(2_189, 0).saturating_mul(c.into())) + // Standard Error: 5 + .saturating_add(Weight::from_parts(2_011, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(6)) } - /// Storage: `Paras::Heads` (r:0 w:1) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Paras Heads (r:0 w:1) + /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) /// The range of component `s` is `[1, 1048576]`. fn force_set_current_head(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_793_000 picoseconds. - Weight::from_parts(7_987_606, 0) + // Minimum execution time: 8_275_000 picoseconds. + Weight::from_parts(8_321_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(971, 0).saturating_mul(s.into())) + // Standard Error: 2 + .saturating_add(Weight::from_parts(858, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Paras::MostRecentContext` (r:0 w:1) - /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) + // Storage: Paras Heads (r:0 w:1) fn force_set_most_recent_context() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_733_000 picoseconds. - Weight::from_parts(2_954_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_parts(10_155_000, 0) + // Standard Error: 0 + .saturating_add(T::DbWeight::get().writes(1 as u64)) } - /// Storage: `Paras::FutureCodeHash` (r:1 w:1) - /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) - /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeCooldowns` (r:1 w:1) - /// Proof: `Paras::UpgradeCooldowns` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHash` (r:1 w:1) - /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHashRefs` (r:1 w:1) - /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeRestrictionSignal` (r:0 w:1) - /// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras FutureCodeHash (r:1 w:1) + /// Proof Skipped: Paras FutureCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CurrentCodeHash (r:1 w:0) + /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras UpgradeCooldowns (r:1 w:1) + /// Proof Skipped: Paras UpgradeCooldowns (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CodeByHash (r:1 w:1) + /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteList (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras CodeByHashRefs (r:1 w:1) + /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras UpgradeRestrictionSignal (r:0 w:1) + /// Proof Skipped: Paras UpgradeRestrictionSignal (max_values: None, max_size: None, mode: Measured) /// The range of component `c` is `[1, 3145728]`. fn force_schedule_code_upgrade(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `8452` - // Estimated: `11917` - // Minimum execution time: 6_072_000 picoseconds. - Weight::from_parts(6_128_000, 0) - .saturating_add(Weight::from_parts(0, 11917)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(2_334, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(6)) + // Measured: `8715` + // Estimated: `12180` + // Minimum execution time: 49_923_000 picoseconds. + Weight::from_parts(50_688_000, 0) + .saturating_add(Weight::from_parts(0, 12180)) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_976, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) - /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Registrar::Paras` (r:1 w:0) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::Heads` (r:0 w:1) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) - /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::MostRecentContext` (r:0 w:1) - /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Paras FutureCodeUpgrades (r:1 w:0) + /// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras Heads (r:0 w:1) + /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras UpgradeGoAheadSignal (r:0 w:1) + /// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured) /// The range of component `s` is `[1, 1048576]`. fn force_note_new_head(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `163` - // Estimated: `3628` - // Minimum execution time: 15_166_000 picoseconds. - Weight::from_parts(21_398_053, 0) - .saturating_add(Weight::from_parts(0, 3628)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(976, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `95` + // Estimated: `3560` + // Minimum execution time: 14_408_000 picoseconds. + Weight::from_parts(14_647_000, 0) + .saturating_add(Weight::from_parts(0, 3560)) + // Standard Error: 2 + .saturating_add(Weight::from_parts(858, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ActionsQueue` (r:1 w:1) - /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ActionsQueue (r:1 w:1) + /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) fn force_queue_action() -> Weight { // Proof Size summary in bytes: - // Measured: `4312` - // Estimated: `7777` - // Minimum execution time: 16_345_000 picoseconds. - Weight::from_parts(16_712_000, 0) - .saturating_add(Weight::from_parts(0, 7777)) + // Measured: `4288` + // Estimated: `7753` + // Minimum execution time: 20_009_000 picoseconds. + Weight::from_parts(20_518_000, 0) + .saturating_add(Weight::from_parts(0, 7753)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ActionsQueue` (r:1 w:1) - /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteList (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ActionsQueue (r:1 w:1) + /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) /// The range of component `c` is `[1, 3145728]`. fn add_trusted_validation_code(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `683` - // Estimated: `4148` - // Minimum execution time: 78_076_000 picoseconds. - Weight::from_parts(123_193_814, 0) - .saturating_add(Weight::from_parts(0, 4148)) - // Standard Error: 5 - .saturating_add(Weight::from_parts(1_770, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(4)) + // Measured: `946` + // Estimated: `4411` + // Minimum execution time: 80_626_000 picoseconds. + Weight::from_parts(52_721_755, 0) + .saturating_add(Weight::from_parts(0, 4411)) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_443, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Paras::CodeByHashRefs` (r:1 w:0) - /// Proof: `Paras::CodeByHashRefs` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CodeByHash` (r:0 w:1) - /// Proof: `Paras::CodeByHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Paras CodeByHashRefs (r:1 w:0) + /// Proof Skipped: Paras CodeByHashRefs (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras CodeByHash (r:0 w:1) + /// Proof Skipped: Paras CodeByHash (max_values: None, max_size: None, mode: Measured) fn poke_unused_validation_code() -> Weight { // Proof Size summary in bytes: // Measured: `28` // Estimated: `3493` - // Minimum execution time: 5_184_000 picoseconds. - Weight::from_parts(5_430_000, 0) + // Minimum execution time: 6_692_000 picoseconds. + Weight::from_parts(7_009_000, 0) .saturating_add(Weight::from_parts(0, 3493)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) fn include_pvf_check_statement() -> Weight { // Proof Size summary in bytes: - // Measured: `26706` - // Estimated: `30171` - // Minimum execution time: 102_995_000 picoseconds. - Weight::from_parts(108_977_000, 0) - .saturating_add(Weight::from_parts(0, 30171)) + // Measured: `26682` + // Estimated: `30147` + // Minimum execution time: 87_994_000 picoseconds. + Weight::from_parts(89_933_000, 0) + .saturating_add(Weight::from_parts(0, 30147)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpcomingUpgrades` (r:1 w:1) - /// Proof: `Paras::UpcomingUpgrades` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Digest` (r:1 w:1) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::FutureCodeUpgrades` (r:0 w:100) - /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteList (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras UpcomingUpgrades (r:1 w:1) + /// Proof Skipped: Paras UpcomingUpgrades (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras FutureCodeUpgrades (r:0 w:100) + /// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured) fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { // Proof Size summary in bytes: - // Measured: `27360` - // Estimated: `30825` - // Minimum execution time: 709_433_000 picoseconds. - Weight::from_parts(725_074_000, 0) - .saturating_add(Weight::from_parts(0, 30825)) - .saturating_add(T::DbWeight::get().reads(6)) + // Measured: `27523` + // Estimated: `30988` + // Minimum execution time: 783_222_000 picoseconds. + Weight::from_parts(794_959_000, 0) + .saturating_add(Weight::from_parts(0, 30988)) + .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(104)) } - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { // Proof Size summary in bytes: - // Measured: `27338` - // Estimated: `30803` - // Minimum execution time: 98_973_000 picoseconds. - Weight::from_parts(104_715_000, 0) - .saturating_add(Weight::from_parts(0, 30803)) + // Measured: `27214` + // Estimated: `30679` + // Minimum execution time: 87_424_000 picoseconds. + Weight::from_parts(88_737_000, 0) + .saturating_add(Weight::from_parts(0, 30679)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteList` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteList` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ActionsQueue` (r:1 w:1) - /// Proof: `Paras::ActionsQueue` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteList (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteList (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Configuration ActiveConfig (r:1 w:0) + /// Proof Skipped: Configuration ActiveConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras ActionsQueue (r:1 w:1) + /// Proof Skipped: Paras ActionsQueue (max_values: None, max_size: None, mode: Measured) fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { // Proof Size summary in bytes: - // Measured: `26728` - // Estimated: `30193` - // Minimum execution time: 550_958_000 picoseconds. - Weight::from_parts(564_497_000, 0) - .saturating_add(Weight::from_parts(0, 30193)) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `26991` + // Estimated: `30456` + // Minimum execution time: 612_485_000 picoseconds. + Weight::from_parts(621_670_000, 0) + .saturating_add(Weight::from_parts(0, 30456)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::PvfActiveVoteMap` (r:1 w:1) - /// Proof: `Paras::PvfActiveVoteMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) + /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Paras PvfActiveVoteMap (r:1 w:1) + /// Proof Skipped: Paras PvfActiveVoteMap (max_values: None, max_size: None, mode: Measured) fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { // Proof Size summary in bytes: - // Measured: `26706` - // Estimated: `30171` - // Minimum execution time: 97_088_000 picoseconds. - Weight::from_parts(103_617_000, 0) - .saturating_add(Weight::from_parts(0, 30171)) + // Measured: `26682` + // Estimated: `30147` + // Minimum execution time: 86_673_000 picoseconds. + Weight::from_parts(87_424_000, 0) + .saturating_add(Weight::from_parts(0, 30147)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs index 374927f8470..a102d1903b2 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs @@ -13,334 +13,161 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . - //! Autogenerated weights for `runtime_parachains::paras_inherent` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-11-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 128 // Executed Command: -// ./target/production/polkadot +// target/release/polkadot // benchmark -// pallet // --chain=rococo-dev // --steps=50 // --repeat=20 -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --pallet=runtime_parachains::paras_inherent // --extrinsic=* // --execution=wasm // --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs +// --heap-pages=4096 +// --output=./runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs +// --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; +use sp_std::marker::PhantomData; /// Weight functions for `runtime_parachains::paras_inherent`. pub struct WeightInfo(PhantomData); impl runtime_parachains::paras_inherent::WeightInfo for WeightInfo { - /// Storage: `ParaInherent::Included` (r:1 w:1) - /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::ParentHash` (r:1 w:0) - /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) - /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) - /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) - /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) - /// Storage: `ParaSessionInfo::Sessions` (r:1 w:0) - /// Proof: `ParaSessionInfo::Sessions` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Disputes` (r:1 w:1) - /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::BackersOnDisputes` (r:1 w:1) - /// Proof: `ParasDisputes::BackersOnDisputes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Included` (r:1 w:1) - /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) - /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Frozen` (r:1 w:0) - /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::PendingAvailability` (r:2 w:1) - /// Proof: `ParaInclusion::PendingAvailability` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::PendingAvailabilityCommitments` (r:1 w:1) - /// Proof: `ParaInclusion::PendingAvailabilityCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) - /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) - /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Registrar::Paras` (r:1 w:0) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) - /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) - /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) - /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) - /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Session::DisabledValidators` (r:1 w:0) - /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) - /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::Heads` (r:0 w:1) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) - /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::MostRecentContext` (r:0 w:1) - /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `v` is `[10, 200]`. + // Storage: ParaInherent Included (r:1 w:1) + // Storage: System ParentHash (r:1 w:0) + // Storage: ParaScheduler AvailabilityCores (r:1 w:1) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParaSessionInfo Sessions (r:1 w:0) + // Storage: ParasDisputes Disputes (r:1 w:1) + // Storage: ParasDisputes Included (r:1 w:1) + // Storage: ParasDisputes SpamSlots (r:1 w:1) + // Storage: ParasDisputes Frozen (r:1 w:0) + // Storage: ParaInclusion PendingAvailability (r:2 w:1) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: Paras Parachains (r:1 w:0) + // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + // Storage: Hrmp HrmpChannelDigests (r:1 w:1) + // Storage: Paras FutureCodeUpgrades (r:1 w:0) + // Storage: ParaScheduler SessionStartBlock (r:1 w:0) + // Storage: ParaScheduler ParathreadQueue (r:1 w:1) + // Storage: ParaScheduler Scheduled (r:1 w:1) + // Storage: ParaScheduler ValidatorGroups (r:1 w:0) + // Storage: Ump NeedsDispatch (r:1 w:1) + // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) + // Storage: ParaInherent OnChainVotes (r:0 w:1) + // Storage: Hrmp HrmpWatermarks (r:0 w:1) + // Storage: Paras Heads (r:0 w:1) fn enter_variable_disputes(v: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `67819` - // Estimated: `73759 + v * (23 ±0)` - // Minimum execution time: 874_229_000 picoseconds. - Weight::from_parts(486_359_072, 0) - .saturating_add(Weight::from_parts(0, 73759)) - // Standard Error: 19_197 - .saturating_add(Weight::from_parts(41_842_161, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(26)) - .saturating_add(T::DbWeight::get().writes(16)) - .saturating_add(Weight::from_parts(0, 23).saturating_mul(v.into())) + Weight::from_parts(352_590_000 as u64, 0) + // Standard Error: 13_000 + .saturating_add(Weight::from_parts(49_254_000 as u64, 0).saturating_mul(v as u64)) + .saturating_add(T::DbWeight::get().reads(24 as u64)) + .saturating_add(T::DbWeight::get().writes(16 as u64)) } - /// Storage: `ParaInherent::Included` (r:1 w:1) - /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::ParentHash` (r:1 w:0) - /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) - /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) - /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) - /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) - /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) - /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Frozen` (r:1 w:0) - /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::PendingAvailability` (r:2 w:1) - /// Proof: `ParaInclusion::PendingAvailability` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::PendingAvailabilityCommitments` (r:1 w:1) - /// Proof: `ParaInclusion::PendingAvailabilityCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) - /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) - /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Registrar::Paras` (r:1 w:0) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Disputes` (r:1 w:0) - /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) - /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) - /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) - /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) - /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Session::DisabledValidators` (r:1 w:0) - /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::AvailabilityBitfields` (r:0 w:1) - /// Proof: `ParaInclusion::AvailabilityBitfields` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Included` (r:0 w:1) - /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) - /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::Heads` (r:0 w:1) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) - /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::MostRecentContext` (r:0 w:1) - /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) + // Storage: ParaInherent Included (r:1 w:1) + // Storage: System ParentHash (r:1 w:0) + // Storage: ParaScheduler AvailabilityCores (r:1 w:1) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParasDisputes Frozen (r:1 w:0) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: Paras Parachains (r:1 w:0) + // Storage: ParaInclusion PendingAvailability (r:2 w:1) + // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + // Storage: Hrmp HrmpChannelDigests (r:1 w:1) + // Storage: Paras FutureCodeUpgrades (r:1 w:0) + // Storage: ParasDisputes Disputes (r:1 w:0) + // Storage: ParaScheduler SessionStartBlock (r:1 w:0) + // Storage: ParaScheduler ParathreadQueue (r:1 w:1) + // Storage: ParaScheduler Scheduled (r:1 w:1) + // Storage: ParaScheduler ValidatorGroups (r:1 w:0) + // Storage: Ump NeedsDispatch (r:1 w:1) + // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) + // Storage: ParaInclusion AvailabilityBitfields (r:0 w:1) + // Storage: ParaInherent OnChainVotes (r:0 w:1) + // Storage: ParasDisputes Included (r:0 w:1) + // Storage: Hrmp HrmpWatermarks (r:0 w:1) + // Storage: Paras Heads (r:0 w:1) fn enter_bitfields() -> Weight { - // Proof Size summary in bytes: - // Measured: `42791` - // Estimated: `48731` - // Minimum execution time: 428_757_000 picoseconds. - Weight::from_parts(449_681_000, 0) - .saturating_add(Weight::from_parts(0, 48731)) - .saturating_add(T::DbWeight::get().reads(24)) - .saturating_add(T::DbWeight::get().writes(17)) + Weight::from_parts(299_878_000 as u64, 0) + .saturating_add(T::DbWeight::get().reads(21 as u64)) + .saturating_add(T::DbWeight::get().writes(15 as u64)) } - /// Storage: `ParaInherent::Included` (r:1 w:1) - /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::ParentHash` (r:1 w:0) - /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) - /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) - /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) - /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) - /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) - /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Frozen` (r:1 w:0) - /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::PendingAvailability` (r:2 w:1) - /// Proof: `ParaInclusion::PendingAvailability` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::PendingAvailabilityCommitments` (r:1 w:1) - /// Proof: `ParaInclusion::PendingAvailabilityCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) - /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) - /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Registrar::Paras` (r:1 w:0) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Disputes` (r:1 w:0) - /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) - /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) - /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) - /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) - /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) - /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Session::DisabledValidators` (r:1 w:0) - /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Included` (r:0 w:1) - /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) - /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::Heads` (r:0 w:1) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) - /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::MostRecentContext` (r:0 w:1) - /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `v` is `[101, 200]`. - fn enter_backed_candidates_variable(v: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `42863` - // Estimated: `48803` - // Minimum execution time: 1_276_079_000 picoseconds. - Weight::from_parts(1_313_585_212, 0) - .saturating_add(Weight::from_parts(0, 48803)) - // Standard Error: 18_279 - .saturating_add(Weight::from_parts(43_528, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(27)) - .saturating_add(T::DbWeight::get().writes(16)) + // Storage: ParaInherent Included (r:1 w:1) + // Storage: System ParentHash (r:1 w:0) + // Storage: ParaScheduler AvailabilityCores (r:1 w:1) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParasDisputes Frozen (r:1 w:0) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: Paras Parachains (r:1 w:0) + // Storage: ParaInclusion PendingAvailability (r:2 w:1) + // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + // Storage: Hrmp HrmpChannelDigests (r:1 w:1) + // Storage: Paras FutureCodeUpgrades (r:1 w:0) + // Storage: ParasDisputes Disputes (r:2 w:0) + // Storage: ParaScheduler SessionStartBlock (r:1 w:0) + // Storage: ParaScheduler ParathreadQueue (r:1 w:1) + // Storage: ParaScheduler Scheduled (r:1 w:1) + // Storage: ParaScheduler ValidatorGroups (r:1 w:0) + // Storage: Paras PastCodeMeta (r:1 w:0) + // Storage: Paras CurrentCodeHash (r:1 w:0) + // Storage: Ump RelayDispatchQueueSize (r:1 w:0) + // Storage: Ump NeedsDispatch (r:1 w:1) + // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) + // Storage: ParaInherent OnChainVotes (r:0 w:1) + // Storage: ParasDisputes Included (r:0 w:1) + // Storage: Hrmp HrmpWatermarks (r:0 w:1) + // Storage: Paras Heads (r:0 w:1) + fn enter_backed_candidates_variable(_v: u32) -> Weight { + Weight::from_parts(442_472_000 as u64, 0) + .saturating_add(T::DbWeight::get().reads(25 as u64)) + .saturating_add(T::DbWeight::get().writes(14 as u64)) } - /// Storage: `ParaInherent::Included` (r:1 w:1) - /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::ParentHash` (r:1 w:0) - /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) - /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) - /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) - /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) - /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) - /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) - /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Frozen` (r:1 w:0) - /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::PendingAvailability` (r:2 w:1) - /// Proof: `ParaInclusion::PendingAvailability` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaInclusion::PendingAvailabilityCommitments` (r:1 w:1) - /// Proof: `ParaInclusion::PendingAvailabilityCommitments` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) - /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) - /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) - /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) - /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Registrar::Paras` (r:1 w:0) - /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Disputes` (r:1 w:0) - /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) - /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) - /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) - /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) - /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) - /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::FutureCodeHash` (r:1 w:0) - /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeRestrictionSignal` (r:1 w:0) - /// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) - /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) - /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Session::DisabledValidators` (r:1 w:0) - /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParasDisputes::Included` (r:0 w:1) - /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) - /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::Heads` (r:0 w:1) - /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) - /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Paras::MostRecentContext` (r:0 w:1) - /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) + // Storage: ParaInherent Included (r:1 w:1) + // Storage: System ParentHash (r:1 w:0) + // Storage: ParaScheduler AvailabilityCores (r:1 w:1) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParasDisputes Frozen (r:1 w:0) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: Paras Parachains (r:1 w:0) + // Storage: ParaInclusion PendingAvailability (r:2 w:1) + // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + // Storage: Hrmp HrmpChannelDigests (r:1 w:1) + // Storage: Paras FutureCodeUpgrades (r:1 w:0) + // Storage: ParasDisputes Disputes (r:2 w:0) + // Storage: ParaScheduler SessionStartBlock (r:1 w:0) + // Storage: ParaScheduler ParathreadQueue (r:1 w:1) + // Storage: ParaScheduler Scheduled (r:1 w:1) + // Storage: ParaScheduler ValidatorGroups (r:1 w:0) + // Storage: Paras PastCodeMeta (r:1 w:0) + // Storage: Paras CurrentCodeHash (r:1 w:0) + // Storage: Ump RelayDispatchQueueSize (r:1 w:0) + // Storage: Ump NeedsDispatch (r:1 w:1) + // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) + // Storage: ParaInherent OnChainVotes (r:0 w:1) + // Storage: ParasDisputes Included (r:0 w:1) + // Storage: Hrmp HrmpWatermarks (r:0 w:1) + // Storage: Paras Heads (r:0 w:1) fn enter_backed_candidate_code_upgrade() -> Weight { - // Proof Size summary in bytes: - // Measured: `42876` - // Estimated: `48816` - // Minimum execution time: 34_352_245_000 picoseconds. - Weight::from_parts(34_587_559_000, 0) - .saturating_add(Weight::from_parts(0, 48816)) - .saturating_add(T::DbWeight::get().reads(29)) - .saturating_add(T::DbWeight::get().writes(16)) + Weight::from_parts(36_903_411_000 as u64, 0) + .saturating_add(T::DbWeight::get().reads(25 as u64)) + .saturating_add(T::DbWeight::get().writes(14 as u64)) } } diff --git a/polkadot/runtime/test-runtime/Cargo.toml b/polkadot/runtime/test-runtime/Cargo.toml index bdf68864605..9753a409304 100644 --- a/polkadot/runtime/test-runtime/Cargo.toml +++ b/polkadot/runtime/test-runtime/Cargo.toml @@ -155,7 +155,6 @@ runtime-benchmarks = [ "pallet-staking/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index a0617b3108f..6c899c52701 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -238,7 +238,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = frame_support::weights::ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = (); } parameter_types! { @@ -394,7 +393,7 @@ where let current_block = System::block_number().saturated_into::().saturating_sub(1); let tip = 0; - let tx_ext: TxExtension = ( + let extra: SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -406,17 +405,16 @@ where frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ) - .into(); - let raw_payload = SignedPayload::new(call, tx_ext) + ); + let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; - let (call, tx_ext, _) = raw_payload.deconstruct(); + let (call, extra, _) = raw_payload.deconstruct(); let address = Indices::unlookup(account); - Some((call, (address, signature, tx_ext))) + Some((call, (address, signature, extra))) } } @@ -444,32 +442,12 @@ parameter_types! { pub Prefix: &'static [u8] = b"Pay KSMs to the Kusama account:"; } -#[cfg(feature = "runtime-benchmarks")] -pub struct ClaimsHelper; - -#[cfg(feature = "runtime-benchmarks")] -use frame_support::dispatch::DispatchInfo; - -#[cfg(feature = "runtime-benchmarks")] -impl claims::BenchmarkHelperTrait for ClaimsHelper { - fn default_call_and_info() -> (RuntimeCall, DispatchInfo) { - use frame_support::dispatch::GetDispatchInfo; - let call = RuntimeCall::Claims(claims::Call::attest { - statement: claims::StatementKind::Regular.to_text().to_vec(), - }); - let info = call.get_dispatch_info(); - (call, info) - } -} - impl claims::Config for Runtime { type RuntimeEvent = RuntimeEvent; type VestingSchedule = Vesting; type Prefix = Prefix; type MoveClaimOrigin = frame_system::EnsureRoot; type WeightInfo = claims::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = ClaimsHelper; } parameter_types! { @@ -750,8 +728,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// `BlockId` type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The `SignedExtension` to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -763,7 +741,7 @@ pub type TxExtension = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -774,7 +752,7 @@ pub type Executive = frame_executive::Executive< AllPalletsWithSystem, >; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; pub type Hash = ::Hash; pub type Extrinsic = ::Extrinsic; diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml index 6899edeeaeb..4180828bcfb 100644 --- a/polkadot/runtime/westend/Cargo.toml +++ b/polkadot/runtime/westend/Cargo.toml @@ -270,7 +270,6 @@ runtime-benchmarks = [ "pallet-state-trie-migration/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 45bbd0260e5..b55d68ee0f6 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -200,7 +200,6 @@ impl frame_system::Config for Runtime { type Version = Version; type AccountData = pallet_balances::AccountData; type SystemWeightInfo = weights::frame_system::WeightInfo; - type ExtensionsWeightInfo = weights::frame_system_extensions::WeightInfo; type SS58Prefix = SS58Prefix; type MaxConsumers = frame_support::traits::ConstU32<16>; } @@ -386,7 +385,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type WeightInfo = weights::pallet_transaction_payment::WeightInfo; } parameter_types! { @@ -822,7 +820,7 @@ where // so the actual block number is `n`. .saturating_sub(1); let tip = 0; - let tx_ext: TxExtension = ( + let extra: SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -834,17 +832,16 @@ where frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ) - .into(); - let raw_payload = SignedPayload::new(call, tx_ext) + ); + let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; - let (call, tx_ext, _) = raw_payload.deconstruct(); + let (call, extra, _) = raw_payload.deconstruct(); let address = ::Lookup::unlookup(account); - Some((call, (address, signature, tx_ext))) + Some((call, (address, signature, extra))) } } @@ -1551,8 +1548,8 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// `BlockId` type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The `SignedExtension` to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -1716,7 +1713,7 @@ pub mod migrations { /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -1727,7 +1724,7 @@ pub type Executive = frame_executive::Executive< Migrations, >; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; #[cfg(feature = "runtime-benchmarks")] mod benches { @@ -1773,9 +1770,7 @@ mod benches { [pallet_staking, Staking] [pallet_sudo, Sudo] [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_timestamp, Timestamp] - [pallet_transaction_payment, TransactionPayment] [pallet_treasury, Treasury] [pallet_utility, Utility] [pallet_vesting, Vesting] @@ -2317,7 +2312,6 @@ sp_api::impl_runtime_apis! { use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; @@ -2346,7 +2340,6 @@ sp_api::impl_runtime_apis! { use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; impl pallet_session_benchmarking::Config for Runtime {} diff --git a/polkadot/runtime/westend/src/weights/frame_system_extensions.rs b/polkadot/runtime/westend/src/weights/frame_system_extensions.rs deleted file mode 100644 index e4e1a799ec6..00000000000 --- a/polkadot/runtime/westend/src/weights/frame_system_extensions.rs +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Autogenerated weights for `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-20, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot -// benchmark -// pallet -// --steps=2 -// --repeat=2 -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --pallet=frame-system-extensions -// --chain=westend-dev -// --output=./polkadot/runtime/westend/src/weights/ -// --header=./polkadot/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 `frame_system_extensions`. -pub struct WeightInfo(PhantomData); -impl frame_system::ExtensionsWeightInfo for WeightInfo { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_356_000 picoseconds. - Weight::from_parts(7_805_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 5_510_000 picoseconds. - Weight::from_parts(10_009_000, 0) - .saturating_add(Weight::from_parts(0, 3509)) - .saturating_add(T::DbWeight::get().reads(1)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 761_000 picoseconds. - Weight::from_parts(4_308_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_396_000 picoseconds. - Weight::from_parts(7_585_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 521_000 picoseconds. - Weight::from_parts(4_168_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 541_000 picoseconds. - Weight::from_parts(4_228_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1489` - // Minimum execution time: 3_807_000 picoseconds. - Weight::from_parts(8_025_000, 0) - .saturating_add(Weight::from_parts(0, 1489)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/polkadot/runtime/westend/src/weights/mod.rs b/polkadot/runtime/westend/src/weights/mod.rs index 8aeb4216550..f6a9008d718 100644 --- a/polkadot/runtime/westend/src/weights/mod.rs +++ b/polkadot/runtime/westend/src/weights/mod.rs @@ -17,7 +17,6 @@ pub mod frame_election_provider_support; pub mod frame_system; -pub mod frame_system_extensions; pub mod pallet_asset_rate; pub mod pallet_bags_list; pub mod pallet_balances; @@ -38,7 +37,6 @@ pub mod pallet_session; pub mod pallet_staking; pub mod pallet_sudo; pub mod pallet_timestamp; -pub mod pallet_transaction_payment; pub mod pallet_treasury; pub mod pallet_utility; pub mod pallet_vesting; diff --git a/polkadot/runtime/westend/src/weights/pallet_sudo.rs b/polkadot/runtime/westend/src/weights/pallet_sudo.rs index 649c43e031d..e9ab3ad37a4 100644 --- a/polkadot/runtime/westend/src/weights/pallet_sudo.rs +++ b/polkadot/runtime/westend/src/weights/pallet_sudo.rs @@ -94,15 +94,4 @@ impl pallet_sudo::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Sudo::Key` (r:1 w:0) - /// Proof: `Sudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - fn check_only_sudo_account() -> Weight { - // Proof Size summary in bytes: - // Measured: `132` - // Estimated: `1517` - // Minimum execution time: 2_875_000 picoseconds. - Weight::from_parts(6_803_000, 0) - .saturating_add(Weight::from_parts(0, 1517)) - .saturating_add(T::DbWeight::get().reads(1)) - } } diff --git a/polkadot/runtime/westend/src/weights/pallet_transaction_payment.rs b/polkadot/runtime/westend/src/weights/pallet_transaction_payment.rs deleted file mode 100644 index 001a09f103d..00000000000 --- a/polkadot/runtime/westend/src/weights/pallet_transaction_payment.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Autogenerated weights for `pallet_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-21, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gleipnir`, CPU: `AMD Ryzen 9 7900X 12-Core Processor` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 - -// Executed Command: -// ./target/release/polkadot -// benchmark -// pallet -// --steps=2 -// --repeat=2 -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --pallet=pallet_transaction_payment -// --chain=westend-dev -// --output=./polkadot/runtime/westend/src/weights/ -// --header=./polkadot/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_transaction_payment`. -pub struct WeightInfo(PhantomData); -impl pallet_transaction_payment::WeightInfo for WeightInfo { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `156` - // Estimated: `1641` - // Minimum execution time: 30_888_000 picoseconds. - Weight::from_parts(41_308_000, 0) - .saturating_add(Weight::from_parts(0, 1641)) - .saturating_add(T::DbWeight::get().reads(3)) - } -} diff --git a/polkadot/xcm/xcm-builder/Cargo.toml b/polkadot/xcm/xcm-builder/Cargo.toml index 660a30605e5..10726b0f511 100644 --- a/polkadot/xcm/xcm-builder/Cargo.toml +++ b/polkadot/xcm/xcm-builder/Cargo.toml @@ -47,7 +47,6 @@ runtime-benchmarks = [ "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-salary/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-runtime-parachains/runtime-benchmarks", diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 3bd2fa4b4f5..9892c500f2e 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -25,22 +25,14 @@ use frame_support::{ traits::{ConstU32, Everything}, }; use frame_system::{EnsureRoot, EnsureSigned}; +use polkadot_test_runtime::SignedExtra; use primitives::{AccountIndex, BlakeTwo256, Signature}; use sp_runtime::{generic, traits::MaybeEquivalence, AccountId32, BuildStorage}; use xcm_executor::{traits::ConvertLocation, XcmExecutor}; -pub type TxExtension = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckMortality, - frame_system::CheckNonce, - frame_system::CheckWeight, -); pub type Address = sp_runtime::MultiAddress; pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; pub type Header = generic::Header; pub type Block = generic::Block; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index f953e54111c..a20390b64f9 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -46,13 +46,13 @@ use xcm_builder::{ }; use xcm_executor::{Config, XcmExecutor}; -pub type TxExtension = (frame_system::CheckNonZeroSender,); +pub type SignedExtra = (frame_system::CheckNonZeroSender,); pub type BlockNumber = u64; pub type Address = MultiAddress; pub type Header = generic::Header; pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; pub type Block = generic::Block; pub type Signature = MultiSignature; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index a11e535492c..5bf65fa9f9a 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -45,13 +45,13 @@ use xcm_builder::{ }; use xcm_executor::{Config, XcmExecutor}; -pub type TxExtension = (frame_system::CheckNonZeroSender,); +pub type SignedExtra = (frame_system::CheckNonZeroSender,); pub type BlockNumber = u64; pub type Address = MultiAddress; pub type Header = generic::Header; pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; pub type Block = generic::Block; pub type Signature = MultiSignature; diff --git a/prdoc/pr_2280.prdoc b/prdoc/pr_2280.prdoc deleted file mode 100644 index 3026dc254e6..00000000000 --- a/prdoc/pr_2280.prdoc +++ /dev/null @@ -1,144 +0,0 @@ -# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 -# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json - -title: FRAME Create `TransactionExtension` as a replacement for `SignedExtension` - -doc: - - audience: Runtime User - description: | - Introduces a new trait `TransactionExtension` to replace `SignedExtension`. Introduce the - idea of transactions which obey the runtime's extensions and have according Extension data - (né Extra data) yet do not have hard-coded signatures. - - Deprecate the terminology of "Unsigned" when used for transactions/extrinsics owing to there - now being "proper" unsigned transactions which obey the extension framework and "old-style" - unsigned which do not. Instead we have `General` for the former and `Bare` for the latter. - Unsigned will be phased out as a type of transaction, and `Bare` will only be used for - Inherents. - - Types of extrinsic are now therefore - - Bare (no hardcoded signature, no Extra data; used to be known as "Unsigned") - - Bare transactions (deprecated) - Gossiped, validated with `ValidateUnsigned` - (deprecated) and the `_bare_compat` bits of `TransactionExtension` (deprecated). - - Inherents - Not gossiped, validated with `ProvideInherent`. - - Extended (Extra data) - Gossiped, validated via `TransactionExtension`. - - Signed transactions (with a hardcoded signature). - - General transactions (without a hardcoded signature). - - Notable information on `TransactionExtension` and the differences from `SignedExtension` - - `AdditionalSigned`/`additional_signed` is renamed to `Implicit`/`implicit`. It is encoded - for the entire transaction and passed in to each extension as a new argument to validate. - - `pre_dispatch` is renamed to `prepare`. - - `validate` runs transaction validation logic both off-chain and on-chain, and is - non-mutating. - - `prepare` runs on-chain pre-execution logic using information extracted during validation - and is mutating. - - `validate` and `prepare` are now passed an `Origin` rather than an `AccountId`. If the - extension logic presumes an `AccountId`, consider using the trait function - `AsSystemOriginSigner::as_system_origin_signer`. - - A signature on the underlying transaction may validly not be present. - - The origin may be altered during validation. - - Validation functionality present in `validate` should not be repeated in `prepare`. - Useful information obtained during `validate` should now be passsed in to `prepare` using - the new user-specifiable type `Val`. - - Unsigned logic should be migrated from the old `*_unsigned` functions into the regular - versions of the new functions where the `Origin` is `None`. - - The `Call` type defining the runtime call is now a type parameter. - - `TransactionExtension` now takes a `Context` type parameter. This defines some arbitrary - contextual data that is injected into the transaction extension logic. It is unused in - instances migrated from `SignedExtension`. - - Extensions now track the weight they consume during valdiation, preparation and - post-dispatch through the `TransactionExtensionBase::weight` function. - - `TestXt` was removed and its usage in tests was replaced with `UncheckedExtrinsic` - instances. - - To fix the build issues introduced by this change, use the `AsTransactionExtension` adapter - to wrap existing `SignedExtension`s by converting them using the `From` - generic implementation for `AsTransactionExtension`. More details on migrating existing - `SignedExtension` implementations to `TransactionExtension` in the PR description. - -crates: - - name: bridge-runtime-common - - name: bp-bridge-hub-cumulus - - name: bp-kusama - - name: bp-polkadot-bulletin - - name: bp-polkadot - - name: bp-rococo - - name: bp-westend - - name: bp-polkadot-core - - name: bp-runtime - - name: snowbridge-pallet-inbound-queue - - name: snowbridge-pallet-outbound-queue - - name: snowbridge-pallet-system - - name: snowbridge-runtime-test-common - - name: parachain-template-runtime - - name: asset-hub-rococo-runtime - - name: asset-hub-westend-runtime - - name: bridge-hub-rococo-runtime - - name: bridge-hub-westend-runtime - - name: collectives-westend-runtime - - name: contracts-rococo-runtime - - name: coretime-rococo-runtime - - name: coretime-westend-runtime - - name: glutton-westend-runtime - - name: people-rococo-runtime - - name: people-westend-runtime - - name: seedling-runtime - - name: shell-runtime - - name: penpal-runtime - - name: rococo-parachain-runtime - - name: polkadot-parachain-bin - - name: cumulus-primitives-storage-weight-reclaim - - name: cumulus-test-client - - name: cumulus-test-runtime - - name: cumulus-test-service - - name: polkadot-sdk-docs - - name: polkadot-service - - name: polkadot-test-service - - name: polkadot-runtime-common - - name: rococo-runtime - - name: polkadot-test-runtime - - name: westend-runtime - - name: staging-xcm-builder - - name: minimal-runtime - - name: node-template - - name: node-template-runtime - - name: staging-node-cli - - name: kitchensink-runtime - - name: node-testing - - name: sc-client-api - - name: sc-client-db - - name: sc-network-gossip - - name: sc-network-sync - - name: sc-transaction-pool - - name: frame - - name: pallet-babe - - name: pallet-balances - - name: pallet-beefy - - name: pallet-collective - - name: pallet-election-provider-multi-phase - - name: pallet-elections-phragmen - - name: pallet-example-basic - - name: pallet-example-offchain-worker - - name: frame-executive - - name: pallet-grandpa - - name: pallet-im-online - - name: pallet-offences - - name: pallet-sassafras - - name: pallet-state-trie-migration - - name: pallet-sudo - - name: frame-support-procedural - - name: frame-support - - name: frame-system - - name: frame-system-benchmarking - - name: pallet-transaction-payment - - name: pallet-asset-conversion-tx-payment - - name: pallet-asset-tx-payment - - name: pallet-skip-feeless-payment - - name: sp-inherents - - name: sp-metadata-ir - - name: sp-runtime - - name: substrate-test-runtime - - name: frame-benchmarking-cli - - name: frame-remote-externalities - - name: substrate-rpc-client diff --git a/prdoc/pr_3665.prdoc b/prdoc/pr_3665.prdoc new file mode 100644 index 00000000000..67725d24d18 --- /dev/null +++ b/prdoc/pr_3665.prdoc @@ -0,0 +1,11 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Revert "FRAME Create TransactionExtension as a replacement for SignedExtension (#2280)" + +doc: + - audience: Runtime Dev + description: | + This PR reverts the PR which introduced `TransactionExtension` to replace `SignedExtension`. + +crates: [ ] diff --git a/substrate/.maintain/frame-weight-template.hbs b/substrate/.maintain/frame-weight-template.hbs index ec9eee205ce..ecd384a5145 100644 --- a/substrate/.maintain/frame-weight-template.hbs +++ b/substrate/.maintain/frame-weight-template.hbs @@ -33,7 +33,7 @@ pub trait WeightInfo { /// Weights for `{{pallet}}` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); -{{#if (or (eq pallet "frame_system") (eq pallet "frame_system_extensions"))}} +{{#if (eq pallet "frame_system")}} impl WeightInfo for SubstrateWeight { {{else}} impl WeightInfo for SubstrateWeight { diff --git a/substrate/bin/node/cli/Cargo.toml b/substrate/bin/node/cli/Cargo.toml index c91a83e6d6e..abe284c41da 100644 --- a/substrate/bin/node/cli/Cargo.toml +++ b/substrate/bin/node/cli/Cargo.toml @@ -196,7 +196,6 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "kitchensink-runtime/runtime-benchmarks", "node-inspect?/runtime-benchmarks", - "pallet-asset-conversion-tx-payment/runtime-benchmarks", "pallet-asset-tx-payment/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -206,7 +205,6 @@ runtime-benchmarks = [ "pallet-skip-feeless-payment/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "sc-client-db/runtime-benchmarks", "sc-service/runtime-benchmarks", diff --git a/substrate/bin/node/cli/benches/block_production.rs b/substrate/bin/node/cli/benches/block_production.rs index b98a321c338..23a62cc0bd2 100644 --- a/substrate/bin/node/cli/benches/block_production.rs +++ b/substrate/bin/node/cli/benches/block_production.rs @@ -110,7 +110,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { fn extrinsic_set_time(now: u64) -> OpaqueExtrinsic { kitchensink_runtime::UncheckedExtrinsic { - preamble: sp_runtime::generic::Preamble::Bare, + signature: None, function: kitchensink_runtime::RuntimeCall::Timestamp(pallet_timestamp::Call::set { now }), } .into() diff --git a/substrate/bin/node/cli/benches/executor.rs b/substrate/bin/node/cli/benches/executor.rs index e13d34f9657..a326e1a79ea 100644 --- a/substrate/bin/node/cli/benches/executor.rs +++ b/substrate/bin/node/cli/benches/executor.rs @@ -29,7 +29,7 @@ use sp_core::{ storage::well_known_keys, traits::{CallContext, CodeExecutor, RuntimeCode}, }; -use sp_runtime::{generic::ExtrinsicFormat, traits::BlakeTwo256}; +use sp_runtime::traits::BlakeTwo256; use sp_state_machine::TestExternalities as CoreTestExternalities; use staging_node_cli::service::RuntimeExecutor; @@ -144,11 +144,11 @@ fn test_blocks( ) -> Vec<(Vec, Hash)> { let mut test_ext = new_test_ext(genesis_config); let mut block1_extrinsics = vec![CheckedExtrinsic { - format: ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: 0 }), }]; block1_extrinsics.extend((0..20).map(|i| CheckedExtrinsic { - format: ExtrinsicFormat::Signed(alice(), tx_ext(i, 0)), + signed: Some((alice(), signed_extra(i, 0))), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 1 * DOLLARS, diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index 157f278fb53..8f2aba6b44c 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -107,21 +107,18 @@ pub fn create_extrinsic( .map(|c| c / 2) .unwrap_or(2) as u64; let tip = 0; - let tx_ext: kitchensink_runtime::TxExtension = + let extra: kitchensink_runtime::SignedExtra = ( - ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(generic::Era::mortal( - period, - best_block.saturated_into(), - )), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), - ) - .into(), + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal( + period, + best_block.saturated_into(), + )), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::< kitchensink_runtime::Runtime, @@ -131,17 +128,15 @@ pub fn create_extrinsic( let raw_payload = kitchensink_runtime::SignedPayload::from_raw( function.clone(), - tx_ext.clone(), + extra.clone(), ( - ( - (), - kitchensink_runtime::VERSION.spec_version, - kitchensink_runtime::VERSION.transaction_version, - genesis_hash, - best_hash, - (), - (), - ), + (), + kitchensink_runtime::VERSION.spec_version, + kitchensink_runtime::VERSION.transaction_version, + genesis_hash, + best_hash, + (), + (), (), ), ); @@ -151,7 +146,7 @@ pub fn create_extrinsic( function, sp_runtime::AccountId32::from(sender.public()).into(), kitchensink_runtime::Signature::Sr25519(signature), - tx_ext, + extra, ) } @@ -796,7 +791,7 @@ mod tests { use codec::Encode; use kitchensink_runtime::{ constants::{currency::CENTS, time::SLOT_DURATION}, - Address, BalancesCall, RuntimeCall, TxExtension, UncheckedExtrinsic, + Address, BalancesCall, RuntimeCall, UncheckedExtrinsic, }; use node_primitives::{Block, DigestItem, Signature}; use sc_client_api::BlockBackend; @@ -998,31 +993,25 @@ mod tests { let tx_payment = pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::from(0, None), ); - let tx_ext: TxExtension = ( - ( - check_non_zero_sender, - check_spec_version, - check_tx_version, - check_genesis, - check_era, - check_nonce, - check_weight, - ) - .into(), + let extra = ( + check_non_zero_sender, + check_spec_version, + check_tx_version, + check_genesis, + check_era, + check_nonce, + check_weight, tx_payment, ); let raw_payload = SignedPayload::from_raw( function, - tx_ext, - ( - ((), spec_version, transaction_version, genesis_hash, genesis_hash, (), ()), - (), - ), + extra, + ((), spec_version, transaction_version, genesis_hash, genesis_hash, (), (), ()), ); let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let (function, tx_ext, _) = raw_payload.deconstruct(); + let (function, extra, _) = raw_payload.deconstruct(); index += 1; - UncheckedExtrinsic::new_signed(function, from.into(), signature.into(), tx_ext) + UncheckedExtrinsic::new_signed(function, from.into(), signature.into(), extra) .into() }, ); diff --git a/substrate/bin/node/cli/tests/basic.rs b/substrate/bin/node/cli/tests/basic.rs index 5fcb2295ef0..525ab2e39c1 100644 --- a/substrate/bin/node/cli/tests/basic.rs +++ b/substrate/bin/node/cli/tests/basic.rs @@ -67,7 +67,7 @@ fn transfer_fee(extrinsic: &E) -> Balance { fn xt() -> UncheckedExtrinsic { sign(CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(0, 0)), + signed: Some((alice(), signed_extra(0, 0))), function: RuntimeCall::Balances(default_transfer_call()), }) } @@ -84,11 +84,11 @@ fn changes_trie_block() -> (Vec, Hash) { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(0, 0)), + signed: Some((alice(), signed_extra(0, 0))), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 69 * DOLLARS, @@ -111,11 +111,11 @@ fn blocks() -> ((Vec, Hash), (Vec, Hash)) { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time1 }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(0, 0)), + signed: Some((alice(), signed_extra(0, 0))), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 69 * DOLLARS, @@ -131,18 +131,18 @@ fn blocks() -> ((Vec, Hash), (Vec, Hash)) { block1.1, vec![ CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time2 }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(bob(), tx_ext(0, 0)), + signed: Some((bob(), signed_extra(0, 0))), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: alice().into(), value: 5 * DOLLARS, }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(1, 0)), + signed: Some((alice(), signed_extra(1, 0))), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 15 * DOLLARS, @@ -166,11 +166,11 @@ fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec, Hash) { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time * 1000 }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(nonce, 0)), + signed: Some((alice(), signed_extra(nonce, 0))), function: RuntimeCall::System(frame_system::Call::remark { remark: vec![0; size] }), }, ], @@ -677,11 +677,11 @@ fn deploying_wasm_contract_should_work() { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(charlie(), tx_ext(0, 0)), + signed: Some((charlie(), signed_extra(0, 0))), function: RuntimeCall::Contracts(pallet_contracts::Call::instantiate_with_code::< Runtime, > { @@ -694,7 +694,7 @@ fn deploying_wasm_contract_should_work() { }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(charlie(), tx_ext(1, 0)), + signed: Some((charlie(), signed_extra(1, 0))), function: RuntimeCall::Contracts(pallet_contracts::Call::call:: { dest: sp_runtime::MultiAddress::Id(addr.clone()), value: 10, diff --git a/substrate/bin/node/cli/tests/fees.rs b/substrate/bin/node/cli/tests/fees.rs index 9d6407067a3..8c7b3c87315 100644 --- a/substrate/bin/node/cli/tests/fees.rs +++ b/substrate/bin/node/cli/tests/fees.rs @@ -54,11 +54,11 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() { GENESIS_HASH.into(), vec![ CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time1 }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(charlie(), tx_ext(0, 0)), + signed: Some((charlie(), signed_extra(0, 0))), function: RuntimeCall::Sudo(pallet_sudo::Call::sudo { call: Box::new(RuntimeCall::RootTesting( pallet_root_testing::Call::fill_block { ratio: Perbill::from_percent(60) }, @@ -77,11 +77,11 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() { block1.1, vec![ CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time2 }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(charlie(), tx_ext(1, 0)), + signed: Some((charlie(), signed_extra(1, 0))), function: RuntimeCall::System(frame_system::Call::remark { remark: vec![0; 1] }), }, ], @@ -147,7 +147,7 @@ fn transaction_fee_is_correct() { let tip = 1_000_000; let xt = sign(CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed(alice(), tx_ext(0, tip)), + signed: Some((alice(), signed_extra(0, tip))), function: RuntimeCall::Balances(default_transfer_call()), }); @@ -211,10 +211,7 @@ fn block_weight_capacity_report() { let num_transfers = block_number * factor; let mut xts = (0..num_transfers) .map(|i| CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed( - charlie(), - tx_ext(nonce + i as Nonce, 0), - ), + signed: Some((charlie(), signed_extra(nonce + i as Nonce, 0))), function: RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest: bob().into(), value: 0, @@ -225,7 +222,7 @@ fn block_weight_capacity_report() { xts.insert( 0, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time * 1000 }), }, ); @@ -288,16 +285,13 @@ fn block_length_capacity_report() { previous_hash, vec![ CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Bare, + signed: None, function: RuntimeCall::Timestamp(pallet_timestamp::Call::set { now: time * 1000, }), }, CheckedExtrinsic { - format: sp_runtime::generic::ExtrinsicFormat::Signed( - charlie(), - tx_ext(nonce, 0), - ), + signed: Some((charlie(), signed_extra(nonce, 0))), function: RuntimeCall::System(frame_system::Call::remark { remark: vec![0u8; (block_number * factor) as usize], }), diff --git a/substrate/bin/node/cli/tests/submit_transaction.rs b/substrate/bin/node/cli/tests/submit_transaction.rs index f3a5bac8fb5..5cbb0103d47 100644 --- a/substrate/bin/node/cli/tests/submit_transaction.rs +++ b/substrate/bin/node/cli/tests/submit_transaction.rs @@ -130,8 +130,8 @@ fn should_submit_signed_twice_from_the_same_account() { // now check that the transaction nonces are not equal let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { - let extra = tx.preamble.to_signed().unwrap().2; - (extra.0).5 + let extra = tx.signature.unwrap().2; + extra.5 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -179,8 +179,8 @@ fn should_submit_signed_twice_from_all_accounts() { // now check that the transaction nonces are not equal let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { - let extra = tx.preamble.to_signed().unwrap().2; - (extra.0).5 + let extra = tx.signature.unwrap().2; + extra.5 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -236,7 +236,7 @@ fn submitted_transaction_should_be_valid() { let source = TransactionSource::External; let extrinsic = UncheckedExtrinsic::decode(&mut &*tx0).unwrap(); // add balance to the account - let author = extrinsic.preamble.clone().to_signed().clone().unwrap().0; + let author = extrinsic.signature.clone().unwrap().0; let address = Indices::lookup(author).unwrap(); let data = pallet_balances::AccountData { free: 5_000_000_000_000, ..Default::default() }; let account = frame_system::AccountInfo { providers: 1, data, ..Default::default() }; diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml index 09c8fb4ed3d..4d342ceb460 100644 --- a/substrate/bin/node/runtime/Cargo.toml +++ b/substrate/bin/node/runtime/Cargo.toml @@ -276,7 +276,6 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-alliance/runtime-benchmarks", - "pallet-asset-conversion-tx-payment/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-asset-rate/runtime-benchmarks", "pallet-asset-tx-payment/runtime-benchmarks", @@ -334,7 +333,6 @@ runtime-benchmarks = [ "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-tips/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-transaction-storage/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-tx-pause/runtime-benchmarks", diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 96611f5a144..437f76c9d5f 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -560,7 +560,6 @@ impl pallet_transaction_payment::Config for Runtime { MinimumMultiplier, MaximumMultiplier, >; - type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } impl pallet_asset_tx_payment::Config for Runtime { @@ -570,9 +569,6 @@ impl pallet_asset_tx_payment::Config for Runtime { pallet_assets::BalanceToAssetBalance, CreditToBlockAuthor, >; - type WeightInfo = pallet_asset_tx_payment::weights::SubstrateWeight; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = AssetTxHelper; } impl pallet_asset_conversion_tx_payment::Config for Runtime { @@ -583,9 +579,6 @@ impl pallet_asset_conversion_tx_payment::Config for Runtime { AssetConversion, Native, >; - type WeightInfo = pallet_asset_conversion_tx_payment::weights::SubstrateWeight; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = AssetConversionTxHelper; } impl pallet_skip_feeless_payment::Config for Runtime { @@ -1416,33 +1409,29 @@ where // so the actual block number is `n`. .saturating_sub(1); let era = Era::mortal(period, current_block); - let tx_ext: TxExtension = ( - ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(era), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), - ) - .into(), + let extra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(era), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::::from( tip, None, ), ), ); - - let raw_payload = SignedPayload::new(call, tx_ext) + let raw_payload = SignedPayload::new(call, extra) .map_err(|e| { log::warn!("Unable to create signed payload: {:?}", e); }) .ok()?; let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; let address = Indices::unlookup(account); - let (call, tx_ext, _) = raw_payload.deconstruct(); - Some((call, (address, signature, tx_ext))) + let (call, extra, _) = raw_payload.deconstruct(); + Some((call, (address, signature, extra))) } } @@ -2461,21 +2450,19 @@ pub type Block = generic::Block; pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The TransactionExtension to the basic transaction logic. +/// The SignedExtension to the basic transaction logic. /// /// When you change this, you **MUST** modify [`sign`] in `bin/node/testing/src/keyring.rs`! /// /// [`sign`]: <../../testing/src/keyring.rs.html> -pub type TxExtension = ( - ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - ), +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_skip_feeless_payment::SkipCheckIfFeeless< Runtime, pallet_asset_conversion_tx_payment::ChargeAssetTxPayment, @@ -2484,11 +2471,11 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; /// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; +pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -2543,106 +2530,6 @@ mod mmr { pub type Hashing = ::Hashing; } -#[cfg(feature = "runtime-benchmarks")] -pub struct AssetConversionTxHelper; - -#[cfg(feature = "runtime-benchmarks")] -impl pallet_asset_conversion_tx_payment::BenchmarkHelperTrait - for AssetConversionTxHelper -{ - fn create_asset_id_parameter(seed: u32) -> (u32, u32) { - (seed, seed) - } - - fn setup_balances_and_pool(asset_id: u32, account: AccountId) { - use frame_support::{assert_ok, traits::fungibles::Mutate}; - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - account.clone().into(), /* owner */ - true, /* is_sufficient */ - 1, - )); - - let lp_provider = account.clone(); - let _ = Balances::deposit_creating(&lp_provider, ((u64::MAX as u128) * 100).into()); - assert_ok!(Assets::mint_into( - asset_id.into(), - &lp_provider, - ((u64::MAX as u128) * 100).into() - )); - - let token_native = Box::new(NativeOrWithId::Native); - let token_second = Box::new(NativeOrWithId::WithId(asset_id)); - - assert_ok!(AssetConversion::create_pool( - RuntimeOrigin::signed(lp_provider.clone()), - token_native.clone(), - token_second.clone() - )); - - assert_ok!(AssetConversion::add_liquidity( - RuntimeOrigin::signed(lp_provider.clone()), - token_native, - token_second, - u64::MAX.into(), // 1 desired - u64::MAX.into(), // 2 desired - 1, // 1 min - 1, // 2 min - lp_provider, - )); - } -} - -#[cfg(feature = "runtime-benchmarks")] -pub struct AssetTxHelper; - -#[cfg(feature = "runtime-benchmarks")] -impl pallet_asset_tx_payment::BenchmarkHelperTrait for AssetTxHelper { - fn create_asset_id_parameter(seed: u32) -> (u32, u32) { - (seed, seed) - } - - fn setup_balances_and_pool(asset_id: u32, account: AccountId) { - use frame_support::{assert_ok, traits::fungibles::Mutate}; - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - account.clone().into(), /* owner */ - true, /* is_sufficient */ - 1, - )); - - let lp_provider = account.clone(); - let _ = Balances::deposit_creating(&lp_provider, ((u64::MAX as u128) * 100).into()); - assert_ok!(Assets::mint_into( - asset_id.into(), - &lp_provider, - ((u64::MAX as u128) * 100).into() - )); - - let token_native = Box::new(NativeOrWithId::Native); - let token_second = Box::new(NativeOrWithId::WithId(asset_id)); - - assert_ok!(AssetConversion::create_pool( - RuntimeOrigin::signed(lp_provider.clone()), - token_native.clone(), - token_second.clone() - )); - - assert_ok!(AssetConversion::add_liquidity( - RuntimeOrigin::signed(lp_provider.clone()), - token_native, - token_second, - u64::MAX.into(), // 1 desired - u64::MAX.into(), // 2 desired - 1, // 1 min - 1, // 2 min - lp_provider, - )); - } -} - #[cfg(feature = "runtime-benchmarks")] mod benches { frame_benchmarking::define_benchmarks!( @@ -2663,9 +2550,6 @@ mod benches { [tasks_example, TasksExample] [pallet_democracy, Democracy] [pallet_asset_conversion, AssetConversion] - [pallet_asset_conversion_tx_payment, AssetConversionTxPayment] - [pallet_asset_tx_payment, AssetTxPayment] - [pallet_transaction_payment, TransactionPayment] [pallet_election_provider_multi_phase, ElectionProviderMultiPhase] [pallet_election_provider_support_benchmarking, EPSBench::] [pallet_elections_phragmen, Elections] @@ -2699,7 +2583,6 @@ mod benches { [pallet_state_trie_migration, StateTrieMigration] [pallet_sudo, Sudo] [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_timestamp, Timestamp] [pallet_tips, Tips] [pallet_transaction_storage, TransactionStorage] @@ -3247,7 +3130,6 @@ impl_runtime_apis! { use pallet_offences_benchmarking::Pallet as OffencesBench; use pallet_election_provider_support_benchmarking::Pallet as EPSBench; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use baseline::Pallet as BaselineBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; @@ -3272,7 +3154,6 @@ impl_runtime_apis! { use pallet_offences_benchmarking::Pallet as OffencesBench; use pallet_election_provider_support_benchmarking::Pallet as EPSBench; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use baseline::Pallet as BaselineBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; diff --git a/substrate/bin/node/testing/src/bench.rs b/substrate/bin/node/testing/src/bench.rs index ccf79eed884..df302a6453b 100644 --- a/substrate/bin/node/testing/src/bench.rs +++ b/substrate/bin/node/testing/src/bench.rs @@ -51,7 +51,6 @@ use sp_core::{ed25519, sr25519, traits::SpawnNamed, Pair, Public}; use sp_crypto_hashing::blake2_256; use sp_inherents::InherentData; use sp_runtime::{ - generic::{ExtrinsicFormat, Preamble}, traits::{Block as BlockT, IdentifyAccount, Verify}, OpaqueExtrinsic, }; @@ -296,10 +295,10 @@ impl<'a> Iterator for BlockContentIterator<'a> { let signed = self.keyring.sign( CheckedExtrinsic { - format: ExtrinsicFormat::Signed( + signed: Some(( sender, - tx_ext(0, kitchensink_runtime::ExistentialDeposit::get() + 1), - ), + signed_extra(0, kitchensink_runtime::ExistentialDeposit::get() + 1), + )), function: match self.content.block_type { BlockType::RandomTransfersKeepAlive => RuntimeCall::Balances(BalancesCall::transfer_keep_alive { @@ -563,11 +562,11 @@ impl BenchKeyring { tx_version: u32, genesis_hash: [u8; 32], ) -> UncheckedExtrinsic { - match xt.format { - ExtrinsicFormat::Signed(signed, tx_ext) => { + match xt.signed { + Some((signed, extra)) => { let payload = ( xt.function, - tx_ext.clone(), + extra.clone(), spec_version, tx_version, genesis_hash, @@ -582,20 +581,11 @@ impl BenchKeyring { } }); UncheckedExtrinsic { - preamble: Preamble::Signed( - sp_runtime::MultiAddress::Id(signed), - signature, - tx_ext, - ), + signature: Some((sp_runtime::MultiAddress::Id(signed), signature, extra)), function: payload.0, } }, - ExtrinsicFormat::Bare => - UncheckedExtrinsic { preamble: Preamble::Bare, function: xt.function }, - ExtrinsicFormat::General(tx_ext) => UncheckedExtrinsic { - preamble: sp_runtime::generic::Preamble::General(tx_ext), - function: xt.function, - }, + None => UncheckedExtrinsic { signature: None, function: xt.function }, } } diff --git a/substrate/bin/node/testing/src/keyring.rs b/substrate/bin/node/testing/src/keyring.rs index 13daf915325..f712191bed6 100644 --- a/substrate/bin/node/testing/src/keyring.rs +++ b/substrate/bin/node/testing/src/keyring.rs @@ -19,13 +19,13 @@ //! Test accounts. use codec::Encode; -use kitchensink_runtime::{CheckedExtrinsic, SessionKeys, TxExtension, UncheckedExtrinsic}; +use kitchensink_runtime::{CheckedExtrinsic, SessionKeys, SignedExtra, UncheckedExtrinsic}; use node_cli::chain_spec::get_from_seed; use node_primitives::{AccountId, Balance, Nonce}; use sp_core::{ecdsa, ed25519, sr25519}; use sp_crypto_hashing::blake2_256; use sp_keyring::AccountKeyring; -use sp_runtime::generic::{Era, ExtrinsicFormat}; +use sp_runtime::generic::Era; /// Alice's account id. pub fn alice() -> AccountId { @@ -70,18 +70,15 @@ pub fn session_keys_from_seed(seed: &str) -> SessionKeys { } /// Returns transaction extra. -pub fn tx_ext(nonce: Nonce, extra_fee: Balance) -> TxExtension { +pub fn signed_extra(nonce: Nonce, extra_fee: Balance) -> SignedExtra { ( - ( - frame_system::CheckNonZeroSender::new(), - frame_system::CheckSpecVersion::new(), - frame_system::CheckTxVersion::new(), - frame_system::CheckGenesis::new(), - frame_system::CheckEra::from(Era::mortal(256, 0)), - frame_system::CheckNonce::from(nonce), - frame_system::CheckWeight::new(), - ) - .into(), + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::mortal(256, 0)), + frame_system::CheckNonce::from(nonce), + frame_system::CheckWeight::new(), pallet_skip_feeless_payment::SkipCheckIfFeeless::from( pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::from(extra_fee, None), ), @@ -95,10 +92,10 @@ pub fn sign( tx_version: u32, genesis_hash: [u8; 32], ) -> UncheckedExtrinsic { - match xt.format { - ExtrinsicFormat::Signed(signed, tx_ext) => { + match xt.signed { + Some((signed, extra)) => { let payload = - (xt.function, tx_ext.clone(), spec_version, tx_version, genesis_hash, genesis_hash); + (xt.function, extra.clone(), spec_version, tx_version, genesis_hash, genesis_hash); let key = AccountKeyring::from_account_id(&signed).unwrap(); let signature = payload @@ -111,21 +108,10 @@ pub fn sign( }) .into(); UncheckedExtrinsic { - preamble: sp_runtime::generic::Preamble::Signed( - sp_runtime::MultiAddress::Id(signed), - signature, - tx_ext, - ), + signature: Some((sp_runtime::MultiAddress::Id(signed), signature, extra)), function: payload.0, } }, - ExtrinsicFormat::Bare => UncheckedExtrinsic { - preamble: sp_runtime::generic::Preamble::Bare, - function: xt.function, - }, - ExtrinsicFormat::General(tx_ext) => UncheckedExtrinsic { - preamble: sp_runtime::generic::Preamble::General(tx_ext), - function: xt.function, - }, + None => UncheckedExtrinsic { signature: None, function: xt.function }, } } diff --git a/substrate/client/api/src/notifications/tests.rs b/substrate/client/api/src/notifications/tests.rs index 7afdcbd9543..fba829b1cf9 100644 --- a/substrate/client/api/src/notifications/tests.rs +++ b/substrate/client/api/src/notifications/tests.rs @@ -18,10 +18,7 @@ use super::*; -use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{Block as RawBlock, H256 as Hash}, -}; +use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, H256 as Hash}; use std::iter::{empty, Empty}; type TestChangeSet = ( @@ -53,7 +50,7 @@ impl PartialEq for StorageChangeSet { } } -type Block = RawBlock>; +type Block = RawBlock>; #[test] fn triggering_change_should_notify_wildcard_listeners() { diff --git a/substrate/client/db/benches/state_access.rs b/substrate/client/db/benches/state_access.rs index 9f3b8ca77c2..e47559e710d 100644 --- a/substrate/client/db/benches/state_access.rs +++ b/substrate/client/db/benches/state_access.rs @@ -22,13 +22,12 @@ use sc_client_api::{Backend as _, BlockImportOperation, NewBlockState, StateBack use sc_client_db::{Backend, BlocksPruning, DatabaseSettings, DatabaseSource, PruningMode}; use sp_core::H256; use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{Block as RawBlock, Header, MockCallU64}, + testing::{Block as RawBlock, ExtrinsicWrapper, Header}, StateVersion, Storage, }; use tempfile::TempDir; -pub(crate) type Block = RawBlock>; +pub(crate) type Block = RawBlock>; fn insert_blocks(db: &Backend, storage: Vec<(Vec, Vec)>) -> H256 { let mut op = db.begin_operation().unwrap(); diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index f22022ef29a..0faa90dfc4f 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/client/db/src/lib.rs @@ -2573,8 +2573,7 @@ pub(crate) mod tests { use sp_blockchain::{lowest_common_ancestor, tree_route}; use sp_core::H256; use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{Block as RawBlock, Header, MockCallU64}, + testing::{Block as RawBlock, ExtrinsicWrapper, Header}, traits::{BlakeTwo256, Hash}, ConsensusEngineId, StateVersion, }; @@ -2582,8 +2581,7 @@ pub(crate) mod tests { const CONS0_ENGINE_ID: ConsensusEngineId = *b"CON0"; const CONS1_ENGINE_ID: ConsensusEngineId = *b"CON1"; - type UncheckedXt = UncheckedExtrinsic; - pub(crate) type Block = RawBlock; + pub(crate) type Block = RawBlock>; pub fn insert_header( backend: &Backend, @@ -2602,7 +2600,7 @@ pub(crate) mod tests { parent_hash: H256, _changes: Option, Vec)>>, extrinsics_root: H256, - body: Vec, + body: Vec>, transaction_index: Option>, ) -> Result { use sp_runtime::testing::Digest; @@ -3416,7 +3414,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![UncheckedXt::new_transaction(i.into(), ())], + vec![i.into()], None, ) .unwrap(); @@ -3438,20 +3436,11 @@ pub(crate) mod tests { assert_eq!(None, bc.body(blocks[0]).unwrap()); assert_eq!(None, bc.body(blocks[1]).unwrap()); assert_eq!(None, bc.body(blocks[2]).unwrap()); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(3.into(), ())]), - bc.body(blocks[3]).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(4.into(), ())]), - bc.body(blocks[4]).unwrap() - ); + assert_eq!(Some(vec![3.into()]), bc.body(blocks[3]).unwrap()); + assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); } else { for i in 0..5 { - assert_eq!( - Some(vec![UncheckedXt::new_transaction((i as u64).into(), ())]), - bc.body(blocks[i]).unwrap() - ); + assert_eq!(Some(vec![(i as u64).into()]), bc.body(blocks[i]).unwrap()); } } } @@ -3475,7 +3464,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![UncheckedXt::new_transaction(i.into(), ())], + vec![i.into()], None, ) .unwrap(); @@ -3484,26 +3473,16 @@ pub(crate) mod tests { } // insert a fork at block 2 - let fork_hash_root = insert_block( - &backend, - 2, - blocks[1], - None, - H256::random(), - vec![UncheckedXt::new_transaction(2.into(), ())], - None, - ) - .unwrap(); + let fork_hash_root = + insert_block(&backend, 2, blocks[1], None, H256::random(), vec![2.into()], None) + .unwrap(); insert_block( &backend, 3, fork_hash_root, None, H256::random(), - vec![ - UncheckedXt::new_transaction(3.into(), ()), - UncheckedXt::new_transaction(11.into(), ()), - ], + vec![3.into(), 11.into()], None, ) .unwrap(); @@ -3513,10 +3492,7 @@ pub(crate) mod tests { backend.commit_operation(op).unwrap(); let bc = backend.blockchain(); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(2.into(), ())]), - bc.body(fork_hash_root).unwrap() - ); + assert_eq!(Some(vec![2.into()]), bc.body(fork_hash_root).unwrap()); for i in 1..5 { let mut op = backend.begin_operation().unwrap(); @@ -3530,28 +3506,16 @@ pub(crate) mod tests { assert_eq!(None, bc.body(blocks[1]).unwrap()); assert_eq!(None, bc.body(blocks[2]).unwrap()); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(3.into(), ())]), - bc.body(blocks[3]).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(4.into(), ())]), - bc.body(blocks[4]).unwrap() - ); + assert_eq!(Some(vec![3.into()]), bc.body(blocks[3]).unwrap()); + assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); } else { for i in 0..5 { - assert_eq!( - Some(vec![UncheckedXt::new_transaction((i as u64).into(), ())]), - bc.body(blocks[i]).unwrap() - ); + assert_eq!(Some(vec![(i as u64).into()]), bc.body(blocks[i]).unwrap()); } } if matches!(pruning, BlocksPruning::KeepAll) { - assert_eq!( - Some(vec![UncheckedXt::new_transaction(2.into(), ())]), - bc.body(fork_hash_root).unwrap() - ); + assert_eq!(Some(vec![2.into()]), bc.body(fork_hash_root).unwrap()); } else { assert_eq!(None, bc.body(fork_hash_root).unwrap()); } @@ -3572,16 +3536,8 @@ pub(crate) mod tests { let backend = Backend::::new_test_with_tx_storage(BlocksPruning::Some(10), 10); let make_block = |index, parent, val: u64| { - insert_block( - &backend, - index, - parent, - None, - H256::random(), - vec![UncheckedXt::new_transaction(val.into(), ())], - None, - ) - .unwrap() + insert_block(&backend, index, parent, None, H256::random(), vec![val.into()], None) + .unwrap() }; let block_0 = make_block(0, Default::default(), 0x00); @@ -3609,30 +3565,18 @@ pub(crate) mod tests { let bc = backend.blockchain(); assert_eq!(None, bc.body(block_1b).unwrap()); assert_eq!(None, bc.body(block_2b).unwrap()); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(0x00.into(), ())]), - bc.body(block_0).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(0x1a.into(), ())]), - bc.body(block_1a).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(0x2a.into(), ())]), - bc.body(block_2a).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(0x3a.into(), ())]), - bc.body(block_3a).unwrap() - ); + assert_eq!(Some(vec![0x00.into()]), bc.body(block_0).unwrap()); + assert_eq!(Some(vec![0x1a.into()]), bc.body(block_1a).unwrap()); + assert_eq!(Some(vec![0x2a.into()]), bc.body(block_2a).unwrap()); + assert_eq!(Some(vec![0x3a.into()]), bc.body(block_3a).unwrap()); } #[test] fn indexed_data_block_body() { let backend = Backend::::new_test_with_tx_storage(BlocksPruning::Some(1), 10); - let x0 = UncheckedXt::new_transaction(0.into(), ()).encode(); - let x1 = UncheckedXt::new_transaction(1.into(), ()).encode(); + let x0 = ExtrinsicWrapper::from(0u64).encode(); + let x1 = ExtrinsicWrapper::from(1u64).encode(); let x0_hash = as sp_core::Hasher>::hash(&x0[1..]); let x1_hash = as sp_core::Hasher>::hash(&x1[1..]); let index = vec![ @@ -3653,10 +3597,7 @@ pub(crate) mod tests { Default::default(), None, Default::default(), - vec![ - UncheckedXt::new_transaction(0.into(), ()), - UncheckedXt::new_transaction(1.into(), ()), - ], + vec![0u64.into(), 1u64.into()], Some(index), ) .unwrap(); @@ -3678,9 +3619,8 @@ pub(crate) mod tests { fn index_invalid_size() { let backend = Backend::::new_test_with_tx_storage(BlocksPruning::Some(1), 10); - let x0 = UncheckedXt::new_transaction(0.into(), ()).encode(); - let x1 = UncheckedXt::new_transaction(1.into(), ()).encode(); - + let x0 = ExtrinsicWrapper::from(0u64).encode(); + let x1 = ExtrinsicWrapper::from(1u64).encode(); let x0_hash = as sp_core::Hasher>::hash(&x0[..]); let x1_hash = as sp_core::Hasher>::hash(&x1[..]); let index = vec![ @@ -3701,10 +3641,7 @@ pub(crate) mod tests { Default::default(), None, Default::default(), - vec![ - UncheckedXt::new_transaction(0.into(), ()), - UncheckedXt::new_transaction(1.into(), ()), - ], + vec![0u64.into(), 1u64.into()], Some(index), ) .unwrap(); @@ -3718,7 +3655,7 @@ pub(crate) mod tests { let backend = Backend::::new_test_with_tx_storage(BlocksPruning::Some(2), 10); let mut blocks = Vec::new(); let mut prev_hash = Default::default(); - let x1 = UncheckedXt::new_transaction(0.into(), ()).encode(); + let x1 = ExtrinsicWrapper::from(0u64).encode(); let x1_hash = as sp_core::Hasher>::hash(&x1[1..]); for i in 0..10 { let mut index = Vec::new(); @@ -3738,7 +3675,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![UncheckedXt::new_transaction(i.into(), ())], + vec![i.into()], Some(index), ) .unwrap(); @@ -3772,7 +3709,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![UncheckedXt::new_transaction(i.into(), ())], + vec![i.into()], None, ) .unwrap(); @@ -3787,7 +3724,7 @@ pub(crate) mod tests { blocks[1], None, sp_core::H256::random(), - vec![UncheckedXt::new_transaction(i.into(), ())], + vec![i.into()], None, ) .unwrap(); @@ -3801,7 +3738,7 @@ pub(crate) mod tests { blocks[0], None, sp_core::H256::random(), - vec![UncheckedXt::new_transaction(42.into(), ())], + vec![42.into()], None, ) .unwrap(); @@ -4274,7 +4211,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![UncheckedXt::new_transaction(i.into(), ())], + vec![i.into()], None, ) .unwrap(); @@ -4289,10 +4226,7 @@ pub(crate) mod tests { // Check that we can properly access values when there is reference count // but no value. - assert_eq!( - Some(vec![UncheckedXt::new_transaction(1.into(), ())]), - bc.body(blocks[1]).unwrap() - ); + assert_eq!(Some(vec![1.into()]), bc.body(blocks[1]).unwrap()); // Block 1 gets pinned three times backend.pin_block(blocks[1]).unwrap(); @@ -4309,42 +4243,27 @@ pub(crate) mod tests { // Block 0, 1, 2, 3 are pinned, so all values should be cached. // Block 4 is inside the pruning window, its value is in db. - assert_eq!( - Some(vec![UncheckedXt::new_transaction(0.into(), ())]), - bc.body(blocks[0]).unwrap() - ); + assert_eq!(Some(vec![0.into()]), bc.body(blocks[0]).unwrap()); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(1.into(), ())]), - bc.body(blocks[1]).unwrap() - ); + assert_eq!(Some(vec![1.into()]), bc.body(blocks[1]).unwrap()); assert_eq!( Some(Justifications::from(build_justification(1))), bc.justifications(blocks[1]).unwrap() ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(2.into(), ())]), - bc.body(blocks[2]).unwrap() - ); + assert_eq!(Some(vec![2.into()]), bc.body(blocks[2]).unwrap()); assert_eq!( Some(Justifications::from(build_justification(2))), bc.justifications(blocks[2]).unwrap() ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(3.into(), ())]), - bc.body(blocks[3]).unwrap() - ); + assert_eq!(Some(vec![3.into()]), bc.body(blocks[3]).unwrap()); assert_eq!( Some(Justifications::from(build_justification(3))), bc.justifications(blocks[3]).unwrap() ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(4.into(), ())]), - bc.body(blocks[4]).unwrap() - ); + assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); assert_eq!( Some(Justifications::from(build_justification(4))), bc.justifications(blocks[4]).unwrap() @@ -4375,10 +4294,7 @@ pub(crate) mod tests { assert!(bc.justifications(blocks[1]).unwrap().is_none()); // Block 4 is inside the pruning window and still kept - assert_eq!( - Some(vec![UncheckedXt::new_transaction(4.into(), ())]), - bc.body(blocks[4]).unwrap() - ); + assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); assert_eq!( Some(Justifications::from(build_justification(4))), bc.justifications(blocks[4]).unwrap() @@ -4386,16 +4302,9 @@ pub(crate) mod tests { // Block tree: // 0 -> 1 -> 2 -> 3 -> 4 -> 5 - let hash = insert_block( - &backend, - 5, - prev_hash, - None, - Default::default(), - vec![UncheckedXt::new_transaction(5.into(), ())], - None, - ) - .unwrap(); + let hash = + insert_block(&backend, 5, prev_hash, None, Default::default(), vec![5.into()], None) + .unwrap(); blocks.push(hash); backend.pin_block(blocks[4]).unwrap(); @@ -4410,18 +4319,12 @@ pub(crate) mod tests { assert!(bc.body(blocks[2]).unwrap().is_none()); assert!(bc.body(blocks[3]).unwrap().is_none()); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(4.into(), ())]), - bc.body(blocks[4]).unwrap() - ); + assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); assert_eq!( Some(Justifications::from(build_justification(4))), bc.justifications(blocks[4]).unwrap() ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(5.into(), ())]), - bc.body(blocks[5]).unwrap() - ); + assert_eq!(Some(vec![5.into()]), bc.body(blocks[5]).unwrap()); assert!(bc.header(blocks[5]).ok().flatten().is_some()); backend.unpin_block(blocks[4]); @@ -4431,16 +4334,9 @@ pub(crate) mod tests { // Append a justification to block 5. backend.append_justification(blocks[5], ([0, 0, 0, 1], vec![42])).unwrap(); - let hash = insert_block( - &backend, - 6, - blocks[5], - None, - Default::default(), - vec![UncheckedXt::new_transaction(6.into(), ())], - None, - ) - .unwrap(); + let hash = + insert_block(&backend, 6, blocks[5], None, Default::default(), vec![6.into()], None) + .unwrap(); blocks.push(hash); // Pin block 5 so it gets loaded into the cache on prune @@ -4453,10 +4349,7 @@ pub(crate) mod tests { op.mark_finalized(blocks[6], None).unwrap(); backend.commit_operation(op).unwrap(); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(5.into(), ())]), - bc.body(blocks[5]).unwrap() - ); + assert_eq!(Some(vec![5.into()]), bc.body(blocks[5]).unwrap()); assert!(bc.header(blocks[5]).ok().flatten().is_some()); let mut expected = Justifications::from(build_justification(5)); expected.append(([0, 0, 0, 1], vec![42])); @@ -4478,7 +4371,7 @@ pub(crate) mod tests { prev_hash, None, Default::default(), - vec![UncheckedXt::new_transaction(i.into(), ())], + vec![i.into()], None, ) .unwrap(); @@ -4494,26 +4387,16 @@ pub(crate) mod tests { // Block tree: // 0 -> 1 -> 2 -> 3 -> 4 // \ -> 2 -> 3 - let fork_hash_root = insert_block( - &backend, - 2, - blocks[1], - None, - H256::random(), - vec![UncheckedXt::new_transaction(2.into(), ())], - None, - ) - .unwrap(); + let fork_hash_root = + insert_block(&backend, 2, blocks[1], None, H256::random(), vec![2.into()], None) + .unwrap(); let fork_hash_3 = insert_block( &backend, 3, fork_hash_root, None, H256::random(), - vec![ - UncheckedXt::new_transaction(3.into(), ()), - UncheckedXt::new_transaction(11.into(), ()), - ], + vec![3.into(), 11.into()], None, ) .unwrap(); @@ -4534,35 +4417,14 @@ pub(crate) mod tests { } let bc = backend.blockchain(); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(0.into(), ())]), - bc.body(blocks[0]).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(1.into(), ())]), - bc.body(blocks[1]).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(2.into(), ())]), - bc.body(blocks[2]).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(3.into(), ())]), - bc.body(blocks[3]).unwrap() - ); - assert_eq!( - Some(vec![UncheckedXt::new_transaction(4.into(), ())]), - bc.body(blocks[4]).unwrap() - ); + assert_eq!(Some(vec![0.into()]), bc.body(blocks[0]).unwrap()); + assert_eq!(Some(vec![1.into()]), bc.body(blocks[1]).unwrap()); + assert_eq!(Some(vec![2.into()]), bc.body(blocks[2]).unwrap()); + assert_eq!(Some(vec![3.into()]), bc.body(blocks[3]).unwrap()); + assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap()); // Check the fork hashes. assert_eq!(None, bc.body(fork_hash_root).unwrap()); - assert_eq!( - Some(vec![ - UncheckedXt::new_transaction(3.into(), ()), - UncheckedXt::new_transaction(11.into(), ()) - ]), - bc.body(fork_hash_3).unwrap() - ); + assert_eq!(Some(vec![3.into(), 11.into()]), bc.body(fork_hash_3).unwrap()); // Unpin all blocks, except the forked one. for block in &blocks { diff --git a/substrate/client/db/src/utils.rs b/substrate/client/db/src/utils.rs index d2a5f7e718a..abf9c4629ce 100644 --- a/substrate/client/db/src/utils.rs +++ b/substrate/client/db/src/utils.rs @@ -582,19 +582,14 @@ impl<'a, 'b> codec::Input for JoinInput<'a, 'b> { mod tests { use super::*; use codec::Input; - use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{Block as RawBlock, MockCallU64}, - }; - - pub type UncheckedXt = UncheckedExtrinsic; - type Block = RawBlock; + use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper}; + type Block = RawBlock>; #[cfg(feature = "rocksdb")] #[test] fn database_type_subdir_migration() { use std::path::PathBuf; - type Block = RawBlock; + type Block = RawBlock>; fn check_dir_for_db_type( db_type: DatabaseType, diff --git a/substrate/client/network-gossip/src/state_machine.rs b/substrate/client/network-gossip/src/state_machine.rs index f1c830341ea..069d7cdba16 100644 --- a/substrate/client/network-gossip/src/state_machine.rs +++ b/substrate/client/network-gossip/src/state_machine.rs @@ -550,8 +550,7 @@ mod tests { NotificationSenderError, NotificationSenderT as NotificationSender, ReputationChange, }; use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{Block as RawBlock, MockCallU64, H256}, + testing::{Block as RawBlock, ExtrinsicWrapper, H256}, traits::NumberFor, }; use std::{ @@ -560,7 +559,7 @@ mod tests { sync::{Arc, Mutex}, }; - type Block = RawBlock>; + type Block = RawBlock>; macro_rules! push_msg { ($consensus:expr, $topic:expr, $hash: expr, $m:expr) => { diff --git a/substrate/client/network/sync/src/blocks.rs b/substrate/client/network/sync/src/blocks.rs index a115ee94767..4988045a478 100644 --- a/substrate/client/network/sync/src/blocks.rs +++ b/substrate/client/network/sync/src/blocks.rs @@ -265,12 +265,9 @@ mod test { use libp2p::PeerId; use sc_network_common::sync::message; use sp_core::H256; - use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{Block as RawBlock, MockCallU64}, - }; + use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper}; - type Block = RawBlock>; + type Block = RawBlock>; fn is_empty(bc: &BlockCollection) -> bool { bc.blocks.is_empty() && bc.peer_requests.is_empty() diff --git a/substrate/client/transaction-pool/src/lib.rs b/substrate/client/transaction-pool/src/lib.rs index 730cfe36712..64b301e6bf3 100644 --- a/substrate/client/transaction-pool/src/lib.rs +++ b/substrate/client/transaction-pool/src/lib.rs @@ -659,13 +659,8 @@ where }) .unwrap_or_default() .into_iter() - // TODO [#2415]: This isn't really what we mean - we really want a - // `tx.is_transaction`, since bare transactions may be gossipped as in the case - // of Frontier txs or claims. This will be sorted once we dispense with the - // concept of bare transactions and make inherents the only possible type of - // extrinsics which are bare. At this point we can change this to - // `tx.is_transaction()`. - .filter(|tx| !tx.is_bare()); + .filter(|tx| tx.is_signed().unwrap_or(true)); + let mut resubmitted_to_report = 0; resubmit_transactions.extend(block_transactions.into_iter().filter(|tx| { diff --git a/substrate/frame/alliance/src/weights.rs b/substrate/frame/alliance/src/weights.rs index 0b2d1fca43c..b5bb5095720 100644 --- a/substrate/frame/alliance/src/weights.rs +++ b/substrate/frame/alliance/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_alliance` +//! Autogenerated weights for pallet_alliance //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/alliance/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/alliance/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_alliance`. +/// Weight functions needed for pallet_alliance. pub trait WeightInfo { fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight; fn vote(m: u32, ) -> Weight; @@ -73,209 +74,205 @@ pub trait WeightInfo { fn abdicate_fellow_status() -> Weight; } -/// Weights for `pallet_alliance` using the Substrate node and recommended hardware. +/// Weights for pallet_alliance using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::ProposalOf` (r:1 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalCount` (r:1 w:1) - /// Proof: `AllianceMotion::ProposalCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Voting` (r:0 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion ProposalOf (r:1 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalCount (r:1 w:1) + /// Proof Skipped: AllianceMotion ProposalCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Voting (r:0 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `654 + m * (32 ±0) + p * (36 ±0)` + // Measured: `653 + m * (32 ±0) + p * (35 ±0)` // Estimated: `6676 + m * (32 ±0) + p * (36 ±0)` - // Minimum execution time: 30_801_000 picoseconds. - Weight::from_parts(32_942_969, 6676) - // Standard Error: 112 - .saturating_add(Weight::from_parts(614, 0).saturating_mul(b.into())) - // Standard Error: 1_177 - .saturating_add(Weight::from_parts(45_758, 0).saturating_mul(m.into())) - // Standard Error: 1_162 - .saturating_add(Weight::from_parts(136_600, 0).saturating_mul(p.into())) + // Minimum execution time: 36_908_000 picoseconds. + Weight::from_parts(39_040_304, 6676) + // Standard Error: 131 + .saturating_add(Weight::from_parts(781, 0).saturating_mul(b.into())) + // Standard Error: 1_375 + .saturating_add(Weight::from_parts(48_745, 0).saturating_mul(m.into())) + // Standard Error: 1_358 + .saturating_add(Weight::from_parts(148_047, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1113 + m * (64 ±0)` + // Measured: `1042 + m * (64 ±0)` // Estimated: `6676 + m * (64 ±0)` - // Minimum execution time: 29_705_000 picoseconds. - Weight::from_parts(30_274_070, 6676) - // Standard Error: 884 - .saturating_add(Weight::from_parts(71_178, 0).saturating_mul(m.into())) + // Minimum execution time: 30_166_000 picoseconds. + Weight::from_parts(32_798_454, 6676) + // Standard Error: 1_432 + .saturating_add(Weight::from_parts(83_001, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:1 w:0) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:1 w:0) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalOf (r:0 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `640 + m * (96 ±0) + p * (36 ±0)` + // Measured: `576 + m * (96 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 38_596_000 picoseconds. - Weight::from_parts(36_445_536, 6676) - // Standard Error: 1_217 - .saturating_add(Weight::from_parts(69_976, 0).saturating_mul(m.into())) - // Standard Error: 1_187 - .saturating_add(Weight::from_parts(149_706, 0).saturating_mul(p.into())) + // Minimum execution time: 45_173_000 picoseconds. + Weight::from_parts(42_192_020, 6676) + // Standard Error: 1_456 + .saturating_add(Weight::from_parts(66_751, 0).saturating_mul(m.into())) + // Standard Error: 1_420 + .saturating_add(Weight::from_parts(158_161, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:1 w:0) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalOf` (r:1 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:1 w:0) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalOf (r:1 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1220 + m * (96 ±0) + p * (39 ±0)` + // Measured: `1087 + m * (96 ±0) + p * (39 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (40 ±0)` - // Minimum execution time: 57_602_000 picoseconds. - Weight::from_parts(55_147_214, 6676) - // Standard Error: 127 - .saturating_add(Weight::from_parts(1_650, 0).saturating_mul(b.into())) - // Standard Error: 1_346 - .saturating_add(Weight::from_parts(56_056, 0).saturating_mul(m.into())) - // Standard Error: 1_312 - .saturating_add(Weight::from_parts(168_247, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Minimum execution time: 58_290_000 picoseconds. + Weight::from_parts(54_924_919, 6676) + // Standard Error: 157 + .saturating_add(Weight::from_parts(464, 0).saturating_mul(b.into())) + // Standard Error: 1_665 + .saturating_add(Weight::from_parts(73_183, 0).saturating_mul(m.into())) + // Standard Error: 1_623 + .saturating_add(Weight::from_parts(168_318, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:1 w:0) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:1 w:0) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:1 w:0) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:1 w:0) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalOf (r:0 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `641 + m * (96 ±0) + p * (36 ±0)` + // Measured: `577 + m * (96 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 40_755_000 picoseconds. - Weight::from_parts(36_953_935, 6676) - // Standard Error: 1_177 - .saturating_add(Weight::from_parts(73_240, 0).saturating_mul(m.into())) - // Standard Error: 1_162 - .saturating_add(Weight::from_parts(149_412, 0).saturating_mul(p.into())) + // Minimum execution time: 46_794_000 picoseconds. + Weight::from_parts(43_092_958, 6676) + // Standard Error: 1_273 + .saturating_add(Weight::from_parts(71_054, 0).saturating_mul(m.into())) + // Standard Error: 1_257 + .saturating_add(Weight::from_parts(152_820, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:1 w:0) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:1 w:0) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:1 w:0) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:1 w:0) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalOf (r:0 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[5, 100]`. /// The range of component `p` is `[1, 100]`. fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `694 + m * (96 ±0) + p * (35 ±0)` + // Measured: `684 + m * (96 ±0) + p * (35 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 41_113_000 picoseconds. - Weight::from_parts(36_610_116, 6676) - // Standard Error: 92 - .saturating_add(Weight::from_parts(1_157, 0).saturating_mul(b.into())) - // Standard Error: 984 - .saturating_add(Weight::from_parts(63_050, 0).saturating_mul(m.into())) - // Standard Error: 949 - .saturating_add(Weight::from_parts(150_420, 0).saturating_mul(p.into())) + // Minimum execution time: 47_338_000 picoseconds. + Weight::from_parts(41_257_479, 6676) + // Standard Error: 119 + .saturating_add(Weight::from_parts(1_019, 0).saturating_mul(b.into())) + // Standard Error: 1_277 + .saturating_add(Weight::from_parts(78_453, 0).saturating_mul(m.into())) + // Standard Error: 1_231 + .saturating_add(Weight::from_parts(150_991, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:2 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Members` (r:1 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:2 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Members (r:1 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. /// The range of component `z` is `[0, 100]`. fn init_members(m: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `250` + // Measured: `217` // Estimated: `12362` - // Minimum execution time: 30_249_000 picoseconds. - Weight::from_parts(21_364_868, 12362) - // Standard Error: 887 - .saturating_add(Weight::from_parts(131_624, 0).saturating_mul(m.into())) - // Standard Error: 877 - .saturating_add(Weight::from_parts(105_379, 0).saturating_mul(z.into())) + // Minimum execution time: 35_012_000 picoseconds. + Weight::from_parts(24_288_079, 12362) + // Standard Error: 878 + .saturating_add(Weight::from_parts(153_615, 0).saturating_mul(m.into())) + // Standard Error: 867 + .saturating_add(Weight::from_parts(129_307, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Alliance::Members` (r:2 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Alliance::DepositOf` (r:200 w:50) - /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:50 w:50) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:2 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Alliance DepositOf (r:200 w:50) + /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) + /// Storage: System Account (r:50 w:50) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `x` is `[1, 100]`. /// The range of component `y` is `[0, 100]`. /// The range of component `z` is `[0, 50]`. @@ -283,14 +280,14 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + x * (50 ±0) + y * (51 ±0) + z * (251 ±0)` // Estimated: `12362 + x * (2539 ±0) + y * (2539 ±0) + z * (2603 ±1)` - // Minimum execution time: 307_414_000 picoseconds. - Weight::from_parts(309_960_000, 12362) - // Standard Error: 29_278 - .saturating_add(Weight::from_parts(588_774, 0).saturating_mul(x.into())) - // Standard Error: 29_137 - .saturating_add(Weight::from_parts(563_245, 0).saturating_mul(y.into())) - // Standard Error: 58_221 - .saturating_add(Weight::from_parts(13_947_604, 0).saturating_mul(z.into())) + // Minimum execution time: 309_235_000 picoseconds. + Weight::from_parts(311_279_000, 12362) + // Standard Error: 26_510 + .saturating_add(Weight::from_parts(543_475, 0).saturating_mul(x.into())) + // Standard Error: 26_382 + .saturating_add(Weight::from_parts(603_169, 0).saturating_mul(y.into())) + // Standard Error: 52_716 + .saturating_add(Weight::from_parts(16_264_836, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y.into()))) @@ -301,401 +298,397 @@ impl WeightInfo for SubstrateWeight { .saturating_add(Weight::from_parts(0, 2539).saturating_mul(y.into())) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(z.into())) } - /// Storage: `Alliance::Rule` (r:0 w:1) - /// Proof: `Alliance::Rule` (`max_values`: Some(1), `max_size`: Some(87), added: 582, mode: `MaxEncodedLen`) + /// Storage: Alliance Rule (r:0 w:1) + /// Proof: Alliance Rule (max_values: Some(1), max_size: Some(87), added: 582, mode: MaxEncodedLen) fn set_rule() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_156_000 picoseconds. - Weight::from_parts(6_560_000, 0) + // Minimum execution time: 8_833_000 picoseconds. + Weight::from_parts(9_313_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Alliance::Announcements` (r:1 w:1) - /// Proof: `Alliance::Announcements` (`max_values`: Some(1), `max_size`: Some(8702), added: 9197, mode: `MaxEncodedLen`) + /// Storage: Alliance Announcements (r:1 w:1) + /// Proof: Alliance Announcements (max_values: Some(1), max_size: Some(8702), added: 9197, mode: MaxEncodedLen) fn announce() -> Weight { // Proof Size summary in bytes: - // Measured: `279` + // Measured: `246` // Estimated: `10187` - // Minimum execution time: 8_988_000 picoseconds. - Weight::from_parts(9_476_000, 10187) + // Minimum execution time: 12_231_000 picoseconds. + Weight::from_parts(12_761_000, 10187) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Alliance::Announcements` (r:1 w:1) - /// Proof: `Alliance::Announcements` (`max_values`: Some(1), `max_size`: Some(8702), added: 9197, mode: `MaxEncodedLen`) + /// Storage: Alliance Announcements (r:1 w:1) + /// Proof: Alliance Announcements (max_values: Some(1), max_size: Some(8702), added: 9197, mode: MaxEncodedLen) fn remove_announcement() -> Weight { // Proof Size summary in bytes: - // Measured: `352` + // Measured: `319` // Estimated: `10187` - // Minimum execution time: 10_126_000 picoseconds. - Weight::from_parts(10_755_000, 10187) + // Minimum execution time: 13_079_000 picoseconds. + Weight::from_parts(13_612_000, 10187) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Alliance::Members` (r:3 w:1) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:0) - /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Alliance::DepositOf` (r:0 w:1) - /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: Alliance Members (r:3 w:1) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: Alliance UnscrupulousAccounts (r:1 w:0) + /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Alliance DepositOf (r:0 w:1) + /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) fn join_alliance() -> Weight { // Proof Size summary in bytes: - // Measured: `501` + // Measured: `468` // Estimated: `18048` - // Minimum execution time: 38_878_000 picoseconds. - Weight::from_parts(40_493_000, 18048) + // Minimum execution time: 44_574_000 picoseconds. + Weight::from_parts(46_157_000, 18048) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Alliance::Members` (r:3 w:1) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:0) - /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: Alliance Members (r:3 w:1) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: Alliance UnscrupulousAccounts (r:1 w:0) + /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) fn nominate_ally() -> Weight { // Proof Size summary in bytes: - // Measured: `400` + // Measured: `367` // Estimated: `18048` - // Minimum execution time: 23_265_000 picoseconds. - Weight::from_parts(24_703_000, 18048) + // Minimum execution time: 26_114_000 picoseconds. + Weight::from_parts(27_069_000, 18048) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Alliance::Members` (r:2 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:2 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) fn elevate_ally() -> Weight { // Proof Size summary in bytes: - // Measured: `476` + // Measured: `443` // Estimated: `12362` - // Minimum execution time: 23_049_000 picoseconds. - Weight::from_parts(23_875_000, 12362) + // Minimum execution time: 25_882_000 picoseconds. + Weight::from_parts(26_923_000, 12362) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Alliance::Members` (r:4 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Alliance::RetiringMembers` (r:0 w:1) - /// Proof: `Alliance::RetiringMembers` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: Alliance Members (r:4 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Alliance RetiringMembers (r:0 w:1) + /// Proof: Alliance RetiringMembers (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn give_retirement_notice() -> Weight { // Proof Size summary in bytes: - // Measured: `476` + // Measured: `443` // Estimated: `23734` - // Minimum execution time: 29_124_000 picoseconds. - Weight::from_parts(30_369_000, 23734) + // Minimum execution time: 34_112_000 picoseconds. + Weight::from_parts(35_499_000, 23734) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Alliance::RetiringMembers` (r:1 w:1) - /// Proof: `Alliance::RetiringMembers` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Alliance::Members` (r:1 w:1) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `Alliance::DepositOf` (r:1 w:1) - /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Alliance RetiringMembers (r:1 w:1) + /// Proof: Alliance RetiringMembers (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: Alliance Members (r:1 w:1) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: Alliance DepositOf (r:1 w:1) + /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn retire() -> Weight { // Proof Size summary in bytes: - // Measured: `720` + // Measured: `687` // Estimated: `6676` - // Minimum execution time: 36_376_000 picoseconds. - Weight::from_parts(38_221_000, 6676) + // Minimum execution time: 41_239_000 picoseconds. + Weight::from_parts(42_764_000, 6676) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Alliance::Members` (r:3 w:1) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Alliance::DepositOf` (r:1 w:1) - /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:3 w:1) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Alliance DepositOf (r:1 w:1) + /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) fn kick_member() -> Weight { // Proof Size summary in bytes: - // Measured: `740` + // Measured: `707` // Estimated: `18048` - // Minimum execution time: 56_560_000 picoseconds. - Weight::from_parts(58_621_000, 18048) + // Minimum execution time: 68_071_000 picoseconds. + Weight::from_parts(71_808_000, 18048) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:1) - /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `Alliance::UnscrupulousWebsites` (r:1 w:1) - /// Proof: `Alliance::UnscrupulousWebsites` (`max_values`: Some(1), `max_size`: Some(25702), added: 26197, mode: `MaxEncodedLen`) + /// Storage: Alliance UnscrupulousAccounts (r:1 w:1) + /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: Alliance UnscrupulousWebsites (r:1 w:1) + /// Proof: Alliance UnscrupulousWebsites (max_values: Some(1), max_size: Some(25702), added: 26197, mode: MaxEncodedLen) /// The range of component `n` is `[0, 100]`. /// The range of component `l` is `[0, 255]`. fn add_unscrupulous_items(n: u32, l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `279` + // Measured: `246` // Estimated: `27187` - // Minimum execution time: 5_191_000 picoseconds. - Weight::from_parts(5_410_000, 27187) - // Standard Error: 3_215 - .saturating_add(Weight::from_parts(1_018_569, 0).saturating_mul(n.into())) - // Standard Error: 1_259 - .saturating_add(Weight::from_parts(68_712, 0).saturating_mul(l.into())) + // Minimum execution time: 7_006_000 picoseconds. + Weight::from_parts(7_253_000, 27187) + // Standard Error: 3_403 + .saturating_add(Weight::from_parts(1_680_082, 0).saturating_mul(n.into())) + // Standard Error: 1_333 + .saturating_add(Weight::from_parts(72_943, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:1) - /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `Alliance::UnscrupulousWebsites` (r:1 w:1) - /// Proof: `Alliance::UnscrupulousWebsites` (`max_values`: Some(1), `max_size`: Some(25702), added: 26197, mode: `MaxEncodedLen`) + /// Storage: Alliance UnscrupulousAccounts (r:1 w:1) + /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: Alliance UnscrupulousWebsites (r:1 w:1) + /// Proof: Alliance UnscrupulousWebsites (max_values: Some(1), max_size: Some(25702), added: 26197, mode: MaxEncodedLen) /// The range of component `n` is `[0, 100]`. /// The range of component `l` is `[0, 255]`. fn remove_unscrupulous_items(n: u32, l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + l * (100 ±0) + n * (289 ±0)` // Estimated: `27187` - // Minimum execution time: 5_361_000 picoseconds. - Weight::from_parts(5_494_000, 27187) - // Standard Error: 181_133 - .saturating_add(Weight::from_parts(16_322_982, 0).saturating_mul(n.into())) - // Standard Error: 70_940 - .saturating_add(Weight::from_parts(343_581, 0).saturating_mul(l.into())) + // Minimum execution time: 7_292_000 picoseconds. + Weight::from_parts(7_629_000, 27187) + // Standard Error: 176_225 + .saturating_add(Weight::from_parts(16_646_429, 0).saturating_mul(n.into())) + // Standard Error: 69_017 + .saturating_add(Weight::from_parts(310_978, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Alliance::Members` (r:3 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:3 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) fn abdicate_fellow_status() -> Weight { // Proof Size summary in bytes: - // Measured: `476` + // Measured: `443` // Estimated: `18048` - // Minimum execution time: 28_856_000 picoseconds. - Weight::from_parts(29_875_000, 18048) + // Minimum execution time: 31_798_000 picoseconds. + Weight::from_parts(33_463_000, 18048) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::ProposalOf` (r:1 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalCount` (r:1 w:1) - /// Proof: `AllianceMotion::ProposalCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Voting` (r:0 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion ProposalOf (r:1 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalCount (r:1 w:1) + /// Proof Skipped: AllianceMotion ProposalCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Voting (r:0 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `654 + m * (32 ±0) + p * (36 ±0)` + // Measured: `653 + m * (32 ±0) + p * (35 ±0)` // Estimated: `6676 + m * (32 ±0) + p * (36 ±0)` - // Minimum execution time: 30_801_000 picoseconds. - Weight::from_parts(32_942_969, 6676) - // Standard Error: 112 - .saturating_add(Weight::from_parts(614, 0).saturating_mul(b.into())) - // Standard Error: 1_177 - .saturating_add(Weight::from_parts(45_758, 0).saturating_mul(m.into())) - // Standard Error: 1_162 - .saturating_add(Weight::from_parts(136_600, 0).saturating_mul(p.into())) + // Minimum execution time: 36_908_000 picoseconds. + Weight::from_parts(39_040_304, 6676) + // Standard Error: 131 + .saturating_add(Weight::from_parts(781, 0).saturating_mul(b.into())) + // Standard Error: 1_375 + .saturating_add(Weight::from_parts(48_745, 0).saturating_mul(m.into())) + // Standard Error: 1_358 + .saturating_add(Weight::from_parts(148_047, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1113 + m * (64 ±0)` + // Measured: `1042 + m * (64 ±0)` // Estimated: `6676 + m * (64 ±0)` - // Minimum execution time: 29_705_000 picoseconds. - Weight::from_parts(30_274_070, 6676) - // Standard Error: 884 - .saturating_add(Weight::from_parts(71_178, 0).saturating_mul(m.into())) + // Minimum execution time: 30_166_000 picoseconds. + Weight::from_parts(32_798_454, 6676) + // Standard Error: 1_432 + .saturating_add(Weight::from_parts(83_001, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:1 w:0) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:1 w:0) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalOf (r:0 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `640 + m * (96 ±0) + p * (36 ±0)` + // Measured: `576 + m * (96 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 38_596_000 picoseconds. - Weight::from_parts(36_445_536, 6676) - // Standard Error: 1_217 - .saturating_add(Weight::from_parts(69_976, 0).saturating_mul(m.into())) - // Standard Error: 1_187 - .saturating_add(Weight::from_parts(149_706, 0).saturating_mul(p.into())) + // Minimum execution time: 45_173_000 picoseconds. + Weight::from_parts(42_192_020, 6676) + // Standard Error: 1_456 + .saturating_add(Weight::from_parts(66_751, 0).saturating_mul(m.into())) + // Standard Error: 1_420 + .saturating_add(Weight::from_parts(158_161, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:1 w:0) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalOf` (r:1 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:1 w:0) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalOf (r:1 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1220 + m * (96 ±0) + p * (39 ±0)` + // Measured: `1087 + m * (96 ±0) + p * (39 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (40 ±0)` - // Minimum execution time: 57_602_000 picoseconds. - Weight::from_parts(55_147_214, 6676) - // Standard Error: 127 - .saturating_add(Weight::from_parts(1_650, 0).saturating_mul(b.into())) - // Standard Error: 1_346 - .saturating_add(Weight::from_parts(56_056, 0).saturating_mul(m.into())) - // Standard Error: 1_312 - .saturating_add(Weight::from_parts(168_247, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(7_u64)) + // Minimum execution time: 58_290_000 picoseconds. + Weight::from_parts(54_924_919, 6676) + // Standard Error: 157 + .saturating_add(Weight::from_parts(464, 0).saturating_mul(b.into())) + // Standard Error: 1_665 + .saturating_add(Weight::from_parts(73_183, 0).saturating_mul(m.into())) + // Standard Error: 1_623 + .saturating_add(Weight::from_parts(168_318, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:1 w:0) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:1 w:0) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:1 w:0) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:1 w:0) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalOf (r:0 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `641 + m * (96 ±0) + p * (36 ±0)` + // Measured: `577 + m * (96 ±0) + p * (36 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 40_755_000 picoseconds. - Weight::from_parts(36_953_935, 6676) - // Standard Error: 1_177 - .saturating_add(Weight::from_parts(73_240, 0).saturating_mul(m.into())) - // Standard Error: 1_162 - .saturating_add(Weight::from_parts(149_412, 0).saturating_mul(p.into())) + // Minimum execution time: 46_794_000 picoseconds. + Weight::from_parts(43_092_958, 6676) + // Standard Error: 1_273 + .saturating_add(Weight::from_parts(71_054, 0).saturating_mul(m.into())) + // Standard Error: 1_257 + .saturating_add(Weight::from_parts(152_820, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:1 w:0) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Voting` (r:1 w:1) - /// Proof: `AllianceMotion::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:1 w:0) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:1 w:0) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:1) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::ProposalOf` (r:0 w:1) - /// Proof: `AllianceMotion::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:1 w:0) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Voting (r:1 w:1) + /// Proof Skipped: AllianceMotion Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:1 w:0) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:1 w:0) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Proposals (r:1 w:1) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion ProposalOf (r:0 w:1) + /// Proof Skipped: AllianceMotion ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[1, 1024]`. /// The range of component `m` is `[5, 100]`. /// The range of component `p` is `[1, 100]`. fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `694 + m * (96 ±0) + p * (35 ±0)` + // Measured: `684 + m * (96 ±0) + p * (35 ±0)` // Estimated: `6676 + m * (97 ±0) + p * (36 ±0)` - // Minimum execution time: 41_113_000 picoseconds. - Weight::from_parts(36_610_116, 6676) - // Standard Error: 92 - .saturating_add(Weight::from_parts(1_157, 0).saturating_mul(b.into())) - // Standard Error: 984 - .saturating_add(Weight::from_parts(63_050, 0).saturating_mul(m.into())) - // Standard Error: 949 - .saturating_add(Weight::from_parts(150_420, 0).saturating_mul(p.into())) + // Minimum execution time: 47_338_000 picoseconds. + Weight::from_parts(41_257_479, 6676) + // Standard Error: 119 + .saturating_add(Weight::from_parts(1_019, 0).saturating_mul(b.into())) + // Standard Error: 1_277 + .saturating_add(Weight::from_parts(78_453, 0).saturating_mul(m.into())) + // Standard Error: 1_231 + .saturating_add(Weight::from_parts(150_991, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 97).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Alliance::Members` (r:2 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Members` (r:1 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:2 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Members (r:1 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. /// The range of component `z` is `[0, 100]`. fn init_members(m: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `250` + // Measured: `217` // Estimated: `12362` - // Minimum execution time: 30_249_000 picoseconds. - Weight::from_parts(21_364_868, 12362) - // Standard Error: 887 - .saturating_add(Weight::from_parts(131_624, 0).saturating_mul(m.into())) - // Standard Error: 877 - .saturating_add(Weight::from_parts(105_379, 0).saturating_mul(z.into())) + // Minimum execution time: 35_012_000 picoseconds. + Weight::from_parts(24_288_079, 12362) + // Standard Error: 878 + .saturating_add(Weight::from_parts(153_615, 0).saturating_mul(m.into())) + // Standard Error: 867 + .saturating_add(Weight::from_parts(129_307, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Alliance::Members` (r:2 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Alliance::DepositOf` (r:200 w:50) - /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:50 w:50) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:2 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Alliance DepositOf (r:200 w:50) + /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) + /// Storage: System Account (r:50 w:50) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `x` is `[1, 100]`. /// The range of component `y` is `[0, 100]`. /// The range of component `z` is `[0, 50]`. @@ -703,14 +696,14 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + x * (50 ±0) + y * (51 ±0) + z * (251 ±0)` // Estimated: `12362 + x * (2539 ±0) + y * (2539 ±0) + z * (2603 ±1)` - // Minimum execution time: 307_414_000 picoseconds. - Weight::from_parts(309_960_000, 12362) - // Standard Error: 29_278 - .saturating_add(Weight::from_parts(588_774, 0).saturating_mul(x.into())) - // Standard Error: 29_137 - .saturating_add(Weight::from_parts(563_245, 0).saturating_mul(y.into())) - // Standard Error: 58_221 - .saturating_add(Weight::from_parts(13_947_604, 0).saturating_mul(z.into())) + // Minimum execution time: 309_235_000 picoseconds. + Weight::from_parts(311_279_000, 12362) + // Standard Error: 26_510 + .saturating_add(Weight::from_parts(543_475, 0).saturating_mul(x.into())) + // Standard Error: 26_382 + .saturating_add(Weight::from_parts(603_169, 0).saturating_mul(y.into())) + // Standard Error: 52_716 + .saturating_add(Weight::from_parts(16_264_836, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(y.into()))) @@ -721,194 +714,194 @@ impl WeightInfo for () { .saturating_add(Weight::from_parts(0, 2539).saturating_mul(y.into())) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(z.into())) } - /// Storage: `Alliance::Rule` (r:0 w:1) - /// Proof: `Alliance::Rule` (`max_values`: Some(1), `max_size`: Some(87), added: 582, mode: `MaxEncodedLen`) + /// Storage: Alliance Rule (r:0 w:1) + /// Proof: Alliance Rule (max_values: Some(1), max_size: Some(87), added: 582, mode: MaxEncodedLen) fn set_rule() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_156_000 picoseconds. - Weight::from_parts(6_560_000, 0) + // Minimum execution time: 8_833_000 picoseconds. + Weight::from_parts(9_313_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Alliance::Announcements` (r:1 w:1) - /// Proof: `Alliance::Announcements` (`max_values`: Some(1), `max_size`: Some(8702), added: 9197, mode: `MaxEncodedLen`) + /// Storage: Alliance Announcements (r:1 w:1) + /// Proof: Alliance Announcements (max_values: Some(1), max_size: Some(8702), added: 9197, mode: MaxEncodedLen) fn announce() -> Weight { // Proof Size summary in bytes: - // Measured: `279` + // Measured: `246` // Estimated: `10187` - // Minimum execution time: 8_988_000 picoseconds. - Weight::from_parts(9_476_000, 10187) + // Minimum execution time: 12_231_000 picoseconds. + Weight::from_parts(12_761_000, 10187) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Alliance::Announcements` (r:1 w:1) - /// Proof: `Alliance::Announcements` (`max_values`: Some(1), `max_size`: Some(8702), added: 9197, mode: `MaxEncodedLen`) + /// Storage: Alliance Announcements (r:1 w:1) + /// Proof: Alliance Announcements (max_values: Some(1), max_size: Some(8702), added: 9197, mode: MaxEncodedLen) fn remove_announcement() -> Weight { // Proof Size summary in bytes: - // Measured: `352` + // Measured: `319` // Estimated: `10187` - // Minimum execution time: 10_126_000 picoseconds. - Weight::from_parts(10_755_000, 10187) + // Minimum execution time: 13_079_000 picoseconds. + Weight::from_parts(13_612_000, 10187) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Alliance::Members` (r:3 w:1) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:0) - /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Alliance::DepositOf` (r:0 w:1) - /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: Alliance Members (r:3 w:1) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: Alliance UnscrupulousAccounts (r:1 w:0) + /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Alliance DepositOf (r:0 w:1) + /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) fn join_alliance() -> Weight { // Proof Size summary in bytes: - // Measured: `501` + // Measured: `468` // Estimated: `18048` - // Minimum execution time: 38_878_000 picoseconds. - Weight::from_parts(40_493_000, 18048) + // Minimum execution time: 44_574_000 picoseconds. + Weight::from_parts(46_157_000, 18048) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Alliance::Members` (r:3 w:1) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:0) - /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: Alliance Members (r:3 w:1) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: Alliance UnscrupulousAccounts (r:1 w:0) + /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) fn nominate_ally() -> Weight { // Proof Size summary in bytes: - // Measured: `400` + // Measured: `367` // Estimated: `18048` - // Minimum execution time: 23_265_000 picoseconds. - Weight::from_parts(24_703_000, 18048) + // Minimum execution time: 26_114_000 picoseconds. + Weight::from_parts(27_069_000, 18048) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Alliance::Members` (r:2 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:2 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) fn elevate_ally() -> Weight { // Proof Size summary in bytes: - // Measured: `476` + // Measured: `443` // Estimated: `12362` - // Minimum execution time: 23_049_000 picoseconds. - Weight::from_parts(23_875_000, 12362) + // Minimum execution time: 25_882_000 picoseconds. + Weight::from_parts(26_923_000, 12362) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Alliance::Members` (r:4 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Alliance::RetiringMembers` (r:0 w:1) - /// Proof: `Alliance::RetiringMembers` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: Alliance Members (r:4 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Alliance RetiringMembers (r:0 w:1) + /// Proof: Alliance RetiringMembers (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn give_retirement_notice() -> Weight { // Proof Size summary in bytes: - // Measured: `476` + // Measured: `443` // Estimated: `23734` - // Minimum execution time: 29_124_000 picoseconds. - Weight::from_parts(30_369_000, 23734) + // Minimum execution time: 34_112_000 picoseconds. + Weight::from_parts(35_499_000, 23734) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Alliance::RetiringMembers` (r:1 w:1) - /// Proof: `Alliance::RetiringMembers` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Alliance::Members` (r:1 w:1) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `Alliance::DepositOf` (r:1 w:1) - /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Alliance RetiringMembers (r:1 w:1) + /// Proof: Alliance RetiringMembers (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: Alliance Members (r:1 w:1) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: Alliance DepositOf (r:1 w:1) + /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn retire() -> Weight { // Proof Size summary in bytes: - // Measured: `720` + // Measured: `687` // Estimated: `6676` - // Minimum execution time: 36_376_000 picoseconds. - Weight::from_parts(38_221_000, 6676) + // Minimum execution time: 41_239_000 picoseconds. + Weight::from_parts(42_764_000, 6676) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Alliance::Members` (r:3 w:1) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Alliance::DepositOf` (r:1 w:1) - /// Proof: `Alliance::DepositOf` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:3 w:1) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Alliance DepositOf (r:1 w:1) + /// Proof: Alliance DepositOf (max_values: None, max_size: Some(64), added: 2539, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) fn kick_member() -> Weight { // Proof Size summary in bytes: - // Measured: `740` + // Measured: `707` // Estimated: `18048` - // Minimum execution time: 56_560_000 picoseconds. - Weight::from_parts(58_621_000, 18048) + // Minimum execution time: 68_071_000 picoseconds. + Weight::from_parts(71_808_000, 18048) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:1) - /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `Alliance::UnscrupulousWebsites` (r:1 w:1) - /// Proof: `Alliance::UnscrupulousWebsites` (`max_values`: Some(1), `max_size`: Some(25702), added: 26197, mode: `MaxEncodedLen`) + /// Storage: Alliance UnscrupulousAccounts (r:1 w:1) + /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: Alliance UnscrupulousWebsites (r:1 w:1) + /// Proof: Alliance UnscrupulousWebsites (max_values: Some(1), max_size: Some(25702), added: 26197, mode: MaxEncodedLen) /// The range of component `n` is `[0, 100]`. /// The range of component `l` is `[0, 255]`. fn add_unscrupulous_items(n: u32, l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `279` + // Measured: `246` // Estimated: `27187` - // Minimum execution time: 5_191_000 picoseconds. - Weight::from_parts(5_410_000, 27187) - // Standard Error: 3_215 - .saturating_add(Weight::from_parts(1_018_569, 0).saturating_mul(n.into())) - // Standard Error: 1_259 - .saturating_add(Weight::from_parts(68_712, 0).saturating_mul(l.into())) + // Minimum execution time: 7_006_000 picoseconds. + Weight::from_parts(7_253_000, 27187) + // Standard Error: 3_403 + .saturating_add(Weight::from_parts(1_680_082, 0).saturating_mul(n.into())) + // Standard Error: 1_333 + .saturating_add(Weight::from_parts(72_943, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Alliance::UnscrupulousAccounts` (r:1 w:1) - /// Proof: `Alliance::UnscrupulousAccounts` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `Alliance::UnscrupulousWebsites` (r:1 w:1) - /// Proof: `Alliance::UnscrupulousWebsites` (`max_values`: Some(1), `max_size`: Some(25702), added: 26197, mode: `MaxEncodedLen`) + /// Storage: Alliance UnscrupulousAccounts (r:1 w:1) + /// Proof: Alliance UnscrupulousAccounts (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: Alliance UnscrupulousWebsites (r:1 w:1) + /// Proof: Alliance UnscrupulousWebsites (max_values: Some(1), max_size: Some(25702), added: 26197, mode: MaxEncodedLen) /// The range of component `n` is `[0, 100]`. /// The range of component `l` is `[0, 255]`. fn remove_unscrupulous_items(n: u32, l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + l * (100 ±0) + n * (289 ±0)` // Estimated: `27187` - // Minimum execution time: 5_361_000 picoseconds. - Weight::from_parts(5_494_000, 27187) - // Standard Error: 181_133 - .saturating_add(Weight::from_parts(16_322_982, 0).saturating_mul(n.into())) - // Standard Error: 70_940 - .saturating_add(Weight::from_parts(343_581, 0).saturating_mul(l.into())) + // Minimum execution time: 7_292_000 picoseconds. + Weight::from_parts(7_629_000, 27187) + // Standard Error: 176_225 + .saturating_add(Weight::from_parts(16_646_429, 0).saturating_mul(n.into())) + // Standard Error: 69_017 + .saturating_add(Weight::from_parts(310_978, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Alliance::Members` (r:3 w:2) - /// Proof: `Alliance::Members` (`max_values`: None, `max_size`: Some(3211), added: 5686, mode: `MaxEncodedLen`) - /// Storage: `AllianceMotion::Proposals` (r:1 w:0) - /// Proof: `AllianceMotion::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Members` (r:0 w:1) - /// Proof: `AllianceMotion::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `AllianceMotion::Prime` (r:0 w:1) - /// Proof: `AllianceMotion::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Alliance Members (r:3 w:2) + /// Proof: Alliance Members (max_values: None, max_size: Some(3211), added: 5686, mode: MaxEncodedLen) + /// Storage: AllianceMotion Proposals (r:1 w:0) + /// Proof Skipped: AllianceMotion Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Members (r:0 w:1) + /// Proof Skipped: AllianceMotion Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AllianceMotion Prime (r:0 w:1) + /// Proof Skipped: AllianceMotion Prime (max_values: Some(1), max_size: None, mode: Measured) fn abdicate_fellow_status() -> Weight { // Proof Size summary in bytes: - // Measured: `476` + // Measured: `443` // Estimated: `18048` - // Minimum execution time: 28_856_000 picoseconds. - Weight::from_parts(29_875_000, 18048) + // Minimum execution time: 31_798_000 picoseconds. + Weight::from_parts(33_463_000, 18048) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } diff --git a/substrate/frame/asset-conversion/src/weights.rs b/substrate/frame/asset-conversion/src/weights.rs index 4eaa115c694..a0e687f7a41 100644 --- a/substrate/frame/asset-conversion/src/weights.rs +++ b/substrate/frame/asset-conversion/src/weights.rs @@ -17,28 +17,24 @@ //! Autogenerated weights for `pallet_asset_conversion` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-30, STEPS: `5`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `cob`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// ./target/debug/substrate-node // benchmark // pallet // --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_asset_conversion -// --no-storage-info -// --no-median-slopes -// --no-min-squares +// --steps=5 +// --repeat=2 +// --pallet=pallet-asset-conversion // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 // --output=./substrate/frame/asset-conversion/src/weights.rs -// --header=./substrate/HEADER-APACHE2 // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -63,9 +59,11 @@ pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// Storage: `AssetConversion::Pools` (r:1 w:1) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:2 w:0) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:2 w:2) /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetConversion::NextPoolAssetId` (r:1 w:1) /// Proof: `AssetConversion::NextPoolAssetId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -75,12 +73,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `910` + // Measured: `1081` // Estimated: `6360` - // Minimum execution time: 82_941_000 picoseconds. - Weight::from_parts(85_526_000, 6360) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Minimum execution time: 1_576_000_000 picoseconds. + Weight::from_parts(1_668_000_000, 6360) + .saturating_add(T::DbWeight::get().reads(10_u64)) + .saturating_add(T::DbWeight::get().writes(10_u64)) } /// Storage: `AssetConversion::Pools` (r:1 w:0) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) @@ -88,20 +86,18 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `Assets::Account` (r:4 w:4) /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `PoolAssets::Asset` (r:1 w:1) /// Proof: `PoolAssets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `PoolAssets::Account` (r:2 w:2) /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn add_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `1507` + // Measured: `1761` // Estimated: `11426` - // Minimum execution time: 138_424_000 picoseconds. - Weight::from_parts(142_083_000, 11426) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(10_u64)) + // Minimum execution time: 1_636_000_000 picoseconds. + Weight::from_parts(1_894_000_000, 11426) + .saturating_add(T::DbWeight::get().reads(10_u64)) + .saturating_add(T::DbWeight::get().writes(9_u64)) } /// Storage: `AssetConversion::Pools` (r:1 w:0) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) @@ -115,10 +111,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn remove_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `1650` + // Measured: `1750` // Estimated: `11426` - // Minimum execution time: 122_132_000 picoseconds. - Weight::from_parts(125_143_000, 11426) + // Minimum execution time: 1_507_000_000 picoseconds. + Weight::from_parts(1_524_000_000, 11426) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -129,12 +125,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[2, 4]`. fn swap_exact_tokens_for_tokens(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `89 + n * (419 ±0)` + // Measured: `0 + n * (522 ±0)` // Estimated: `990 + n * (5218 ±0)` - // Minimum execution time: 77_183_000 picoseconds. - Weight::from_parts(78_581_000, 990) - // Standard Error: 306_918 - .saturating_add(Weight::from_parts(10_581_054, 0).saturating_mul(n.into())) + // Minimum execution time: 937_000_000 picoseconds. + Weight::from_parts(941_000_000, 990) + // Standard Error: 40_863_477 + .saturating_add(Weight::from_parts(205_862_068, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 5218).saturating_mul(n.into())) @@ -146,12 +142,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[2, 4]`. fn swap_tokens_for_exact_tokens(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `89 + n * (419 ±0)` + // Measured: `0 + n * (522 ±0)` // Estimated: `990 + n * (5218 ±0)` - // Minimum execution time: 76_962_000 picoseconds. - Weight::from_parts(78_315_000, 990) - // Standard Error: 311_204 - .saturating_add(Weight::from_parts(10_702_400, 0).saturating_mul(n.into())) + // Minimum execution time: 935_000_000 picoseconds. + Weight::from_parts(947_000_000, 990) + // Standard Error: 46_904_620 + .saturating_add(Weight::from_parts(218_275_862, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 5218).saturating_mul(n.into())) @@ -162,9 +158,11 @@ impl WeightInfo for SubstrateWeight { impl WeightInfo for () { /// Storage: `AssetConversion::Pools` (r:1 w:1) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:2 w:0) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:2 w:2) /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetConversion::NextPoolAssetId` (r:1 w:1) /// Proof: `AssetConversion::NextPoolAssetId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -174,12 +172,12 @@ impl WeightInfo for () { /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `910` + // Measured: `1081` // Estimated: `6360` - // Minimum execution time: 82_941_000 picoseconds. - Weight::from_parts(85_526_000, 6360) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Minimum execution time: 1_576_000_000 picoseconds. + Weight::from_parts(1_668_000_000, 6360) + .saturating_add(RocksDbWeight::get().reads(10_u64)) + .saturating_add(RocksDbWeight::get().writes(10_u64)) } /// Storage: `AssetConversion::Pools` (r:1 w:0) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) @@ -187,20 +185,18 @@ impl WeightInfo for () { /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `Assets::Account` (r:4 w:4) /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `PoolAssets::Asset` (r:1 w:1) /// Proof: `PoolAssets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `PoolAssets::Account` (r:2 w:2) /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn add_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `1507` + // Measured: `1761` // Estimated: `11426` - // Minimum execution time: 138_424_000 picoseconds. - Weight::from_parts(142_083_000, 11426) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(10_u64)) + // Minimum execution time: 1_636_000_000 picoseconds. + Weight::from_parts(1_894_000_000, 11426) + .saturating_add(RocksDbWeight::get().reads(10_u64)) + .saturating_add(RocksDbWeight::get().writes(9_u64)) } /// Storage: `AssetConversion::Pools` (r:1 w:0) /// Proof: `AssetConversion::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) @@ -214,10 +210,10 @@ impl WeightInfo for () { /// Proof: `PoolAssets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn remove_liquidity() -> Weight { // Proof Size summary in bytes: - // Measured: `1650` + // Measured: `1750` // Estimated: `11426` - // Minimum execution time: 122_132_000 picoseconds. - Weight::from_parts(125_143_000, 11426) + // Minimum execution time: 1_507_000_000 picoseconds. + Weight::from_parts(1_524_000_000, 11426) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } @@ -228,12 +224,12 @@ impl WeightInfo for () { /// The range of component `n` is `[2, 4]`. fn swap_exact_tokens_for_tokens(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `89 + n * (419 ±0)` + // Measured: `0 + n * (522 ±0)` // Estimated: `990 + n * (5218 ±0)` - // Minimum execution time: 77_183_000 picoseconds. - Weight::from_parts(78_581_000, 990) - // Standard Error: 306_918 - .saturating_add(Weight::from_parts(10_581_054, 0).saturating_mul(n.into())) + // Minimum execution time: 937_000_000 picoseconds. + Weight::from_parts(941_000_000, 990) + // Standard Error: 40_863_477 + .saturating_add(Weight::from_parts(205_862_068, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 5218).saturating_mul(n.into())) @@ -245,12 +241,12 @@ impl WeightInfo for () { /// The range of component `n` is `[2, 4]`. fn swap_tokens_for_exact_tokens(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `89 + n * (419 ±0)` + // Measured: `0 + n * (522 ±0)` // Estimated: `990 + n * (5218 ±0)` - // Minimum execution time: 76_962_000 picoseconds. - Weight::from_parts(78_315_000, 990) - // Standard Error: 311_204 - .saturating_add(Weight::from_parts(10_702_400, 0).saturating_mul(n.into())) + // Minimum execution time: 935_000_000 picoseconds. + Weight::from_parts(947_000_000, 990) + // Standard Error: 46_904_620 + .saturating_add(Weight::from_parts(218_275_862, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 5218).saturating_mul(n.into())) diff --git a/substrate/frame/asset-rate/src/weights.rs b/substrate/frame/asset-rate/src/weights.rs index b8723ee3bed..582e20e56d7 100644 --- a/substrate/frame/asset-rate/src/weights.rs +++ b/substrate/frame/asset-rate/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_asset_rate` +//! Autogenerated weights for pallet_asset_rate //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/asset-rate/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/asset-rate/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,83 +50,83 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_asset_rate`. +/// Weight functions needed for pallet_asset_rate. pub trait WeightInfo { fn create() -> Weight; fn update() -> Weight; fn remove() -> Weight; } -/// Weights for `pallet_asset_rate` using the Substrate node and recommended hardware. +/// Weights for pallet_asset_rate using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3501` - // Minimum execution time: 9_447_000 picoseconds. - Weight::from_parts(10_078_000, 3501) + // Minimum execution time: 11_700_000 picoseconds. + Weight::from_parts(12_158_000, 3501) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn update() -> Weight { // Proof Size summary in bytes: // Measured: `137` // Estimated: `3501` - // Minimum execution time: 9_844_000 picoseconds. - Weight::from_parts(10_240_000, 3501) + // Minimum execution time: 12_119_000 picoseconds. + Weight::from_parts(12_548_000, 3501) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn remove() -> Weight { // Proof Size summary in bytes: // Measured: `137` // Estimated: `3501` - // Minimum execution time: 10_411_000 picoseconds. - Weight::from_parts(10_686_000, 3501) + // Minimum execution time: 12_541_000 picoseconds. + Weight::from_parts(12_956_000, 3501) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3501` - // Minimum execution time: 9_447_000 picoseconds. - Weight::from_parts(10_078_000, 3501) + // Minimum execution time: 11_700_000 picoseconds. + Weight::from_parts(12_158_000, 3501) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn update() -> Weight { // Proof Size summary in bytes: // Measured: `137` // Estimated: `3501` - // Minimum execution time: 9_844_000 picoseconds. - Weight::from_parts(10_240_000, 3501) + // Minimum execution time: 12_119_000 picoseconds. + Weight::from_parts(12_548_000, 3501) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:1) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn remove() -> Weight { // Proof Size summary in bytes: // Measured: `137` // Estimated: `3501` - // Minimum execution time: 10_411_000 picoseconds. - Weight::from_parts(10_686_000, 3501) + // Minimum execution time: 12_541_000 picoseconds. + Weight::from_parts(12_956_000, 3501) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/assets/src/weights.rs b/substrate/frame/assets/src/weights.rs index f5199105fe3..f20f7e317cf 100644 --- a/substrate/frame/assets/src/weights.rs +++ b/substrate/frame/assets/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_assets` +//! Autogenerated weights for pallet_assets //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/assets/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/assets/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_assets`. +/// Weight functions needed for pallet_assets. pub trait WeightInfo { fn create() -> Weight; fn force_create() -> Weight; @@ -85,890 +86,882 @@ pub trait WeightInfo { fn block() -> Weight; } -/// Weights for `pallet_assets` using the Substrate node and recommended hardware. +/// Weights for pallet_assets using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `293` // Estimated: `3675` - // Minimum execution time: 24_690_000 picoseconds. - Weight::from_parts(25_878_000, 3675) + // Minimum execution time: 31_340_000 picoseconds. + Weight::from_parts(31_977_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `153` // Estimated: `3675` - // Minimum execution time: 10_997_000 picoseconds. - Weight::from_parts(11_369_000, 3675) + // Minimum execution time: 13_342_000 picoseconds. + Weight::from_parts(13_782_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn start_destroy() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 11_536_000 picoseconds. - Weight::from_parts(12_309_000, 3675) + // Minimum execution time: 14_437_000 picoseconds. + Weight::from_parts(14_833_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// 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:1001 w:1000) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1000 w:1000) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1001 w:1000) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: System Account (r:1000 w:1000) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `c` is `[0, 1000]`. fn destroy_accounts(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + c * (208 ±0)` // Estimated: `3675 + c * (2609 ±0)` - // Minimum execution time: 15_798_000 picoseconds. - Weight::from_parts(16_005_000, 3675) - // Standard Error: 7_818 - .saturating_add(Weight::from_parts(12_826_278, 0).saturating_mul(c.into())) + // Minimum execution time: 18_728_000 picoseconds. + Weight::from_parts(18_982_000, 3675) + // Standard Error: 11_708 + .saturating_add(Weight::from_parts(14_363_570, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2609).saturating_mul(c.into())) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1001 w:1000) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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 Approvals (r:1001 w:1000) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, mode: MaxEncodedLen) /// The range of component `a` is `[0, 1000]`. fn destroy_approvals(a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `522 + a * (86 ±0)` // Estimated: `3675 + a * (2623 ±0)` - // Minimum execution time: 16_334_000 picoseconds. - Weight::from_parts(16_616_000, 3675) - // Standard Error: 6_402 - .saturating_add(Weight::from_parts(13_502_238, 0).saturating_mul(a.into())) + // Minimum execution time: 18_611_000 picoseconds. + Weight::from_parts(18_970_000, 3675) + // Standard Error: 13_224 + .saturating_add(Weight::from_parts(16_397_299, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) .saturating_add(Weight::from_parts(0, 2623).saturating_mul(a.into())) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:0) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, 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 Metadata (r:1 w:0) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn finish_destroy() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 12_278_000 picoseconds. - Weight::from_parts(12_834_000, 3675) + // Minimum execution time: 14_504_000 picoseconds. + Weight::from_parts(14_906_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn mint() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 21_793_000 picoseconds. - Weight::from_parts(22_284_000, 3675) + // Minimum execution time: 26_653_000 picoseconds. + Weight::from_parts(27_260_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn burn() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 28_712_000 picoseconds. - Weight::from_parts(29_710_000, 3675) + // Minimum execution time: 33_625_000 picoseconds. + Weight::from_parts(34_474_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 41_331_000 picoseconds. - Weight::from_parts(42_362_000, 6208) + // Minimum execution time: 47_609_000 picoseconds. + Weight::from_parts(48_476_000, 6208) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer_keep_alive() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 37_316_000 picoseconds. - Weight::from_parts(38_200_000, 6208) + // Minimum execution time: 41_625_000 picoseconds. + Weight::from_parts(43_030_000, 6208) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 41_347_000 picoseconds. - Weight::from_parts(42_625_000, 6208) + // Minimum execution time: 47_661_000 picoseconds. + Weight::from_parts(48_469_000, 6208) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn freeze() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 15_072_000 picoseconds. - Weight::from_parts(15_925_000, 3675) + // Minimum execution time: 17_727_000 picoseconds. + Weight::from_parts(18_384_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn thaw() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 14_991_000 picoseconds. - Weight::from_parts(15_987_000, 3675) + // Minimum execution time: 17_657_000 picoseconds. + Weight::from_parts(18_282_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn freeze_asset() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 11_296_000 picoseconds. - Weight::from_parts(12_052_000, 3675) + // Minimum execution time: 13_743_000 picoseconds. + Weight::from_parts(14_193_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn thaw_asset() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 11_446_000 picoseconds. - Weight::from_parts(11_791_000, 3675) + // Minimum execution time: 13_653_000 picoseconds. + Weight::from_parts(14_263_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:0) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, 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 Metadata (r:1 w:0) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 13_134_000 picoseconds. - Weight::from_parts(13_401_000, 3675) + // Minimum execution time: 15_328_000 picoseconds. + Weight::from_parts(16_042_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn set_team() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 11_395_000 picoseconds. - Weight::from_parts(11_718_000, 3675) + // Minimum execution time: 14_097_000 picoseconds. + Weight::from_parts(14_641_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) /// The range of component `n` is `[0, 50]`. /// The range of component `s` is `[0, 50]`. - fn set_metadata(n: u32, _s: u32, ) -> Weight { + fn set_metadata(_n: u32, _s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 25_147_000 picoseconds. - Weight::from_parts(26_614_272, 3675) - // Standard Error: 959 - .saturating_add(Weight::from_parts(2_300, 0).saturating_mul(n.into())) + // Minimum execution time: 29_535_000 picoseconds. + Weight::from_parts(31_456_892, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn clear_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `515` // Estimated: `3675` - // Minimum execution time: 26_094_000 picoseconds. - Weight::from_parts(27_199_000, 3675) + // Minimum execution time: 30_680_000 picoseconds. + Weight::from_parts(31_930_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) /// The range of component `n` is `[0, 50]`. /// The range of component `s` is `[0, 50]`. - fn force_set_metadata(n: u32, s: u32, ) -> Weight { + fn force_set_metadata(_n: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `190` // Estimated: `3675` - // Minimum execution time: 11_977_000 picoseconds. - Weight::from_parts(12_719_933, 3675) - // Standard Error: 429 - .saturating_add(Weight::from_parts(3_239, 0).saturating_mul(n.into())) - // Standard Error: 429 - .saturating_add(Weight::from_parts(3_941, 0).saturating_mul(s.into())) + // Minimum execution time: 14_660_000 picoseconds. + Weight::from_parts(15_718_387, 3675) + // Standard Error: 622 + .saturating_add(Weight::from_parts(2_640, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn force_clear_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `515` // Estimated: `3675` - // Minimum execution time: 25_859_000 picoseconds. - Weight::from_parts(26_654_000, 3675) + // Minimum execution time: 30_853_000 picoseconds. + Weight::from_parts(31_483_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn force_asset_status() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 10_965_000 picoseconds. - Weight::from_parts(11_595_000, 3675) + // Minimum execution time: 13_632_000 picoseconds. + Weight::from_parts(14_077_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1 w:1) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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 Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, mode: MaxEncodedLen) fn approve_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 28_427_000 picoseconds. - Weight::from_parts(29_150_000, 3675) + // Minimum execution time: 33_780_000 picoseconds. + Weight::from_parts(34_533_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1 w:1) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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 Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer_approved() -> Weight { // Proof Size summary in bytes: // Measured: `668` // Estimated: `6208` - // Minimum execution time: 60_227_000 picoseconds. - Weight::from_parts(61_839_000, 6208) + // Minimum execution time: 67_712_000 picoseconds. + Weight::from_parts(69_946_000, 6208) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1 w:1) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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 Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, mode: MaxEncodedLen) fn cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `555` // Estimated: `3675` - // Minimum execution time: 30_738_000 picoseconds. - Weight::from_parts(31_988_000, 3675) + // Minimum execution time: 36_668_000 picoseconds. + Weight::from_parts(37_637_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1 w:1) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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 Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, mode: MaxEncodedLen) fn force_cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `555` // Estimated: `3675` - // Minimum execution time: 31_444_000 picoseconds. - Weight::from_parts(32_126_000, 3675) + // Minimum execution time: 36_685_000 picoseconds. + Weight::from_parts(37_950_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn set_min_balance() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 11_890_000 picoseconds. - Weight::from_parts(12_462_000, 3675) + // Minimum execution time: 14_466_000 picoseconds. + Weight::from_parts(14_924_000, 3675) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn touch() -> Weight { // Proof Size summary in bytes: // Measured: `453` // Estimated: `3675` - // Minimum execution time: 30_675_000 picoseconds. - Weight::from_parts(31_749_000, 3675) + // Minimum execution time: 34_874_000 picoseconds. + Weight::from_parts(36_330_000, 3675) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn touch_other() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 28_290_000 picoseconds. - Weight::from_parts(29_405_000, 3675) + // Minimum execution time: 33_278_000 picoseconds. + Weight::from_parts(34_104_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn refund() -> Weight { // Proof Size summary in bytes: // Measured: `579` // Estimated: `3675` - // Minimum execution time: 30_195_000 picoseconds. - Weight::from_parts(31_105_000, 3675) + // Minimum execution time: 32_898_000 picoseconds. + Weight::from_parts(33_489_000, 3675) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn refund_other() -> Weight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `3675` - // Minimum execution time: 27_785_000 picoseconds. - Weight::from_parts(28_783_000, 3675) + // Minimum execution time: 31_243_000 picoseconds. + Weight::from_parts(31_909_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn block() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 15_318_000 picoseconds. - Weight::from_parts(16_113_000, 3675) + // Minimum execution time: 17_692_000 picoseconds. + Weight::from_parts(18_253_000, 3675) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `293` // Estimated: `3675` - // Minimum execution time: 24_690_000 picoseconds. - Weight::from_parts(25_878_000, 3675) + // Minimum execution time: 31_340_000 picoseconds. + Weight::from_parts(31_977_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `153` // Estimated: `3675` - // Minimum execution time: 10_997_000 picoseconds. - Weight::from_parts(11_369_000, 3675) + // Minimum execution time: 13_342_000 picoseconds. + Weight::from_parts(13_782_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn start_destroy() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 11_536_000 picoseconds. - Weight::from_parts(12_309_000, 3675) + // Minimum execution time: 14_437_000 picoseconds. + Weight::from_parts(14_833_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// 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:1001 w:1000) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1000 w:1000) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1001 w:1000) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: System Account (r:1000 w:1000) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `c` is `[0, 1000]`. fn destroy_accounts(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + c * (208 ±0)` // Estimated: `3675 + c * (2609 ±0)` - // Minimum execution time: 15_798_000 picoseconds. - Weight::from_parts(16_005_000, 3675) - // Standard Error: 7_818 - .saturating_add(Weight::from_parts(12_826_278, 0).saturating_mul(c.into())) + // Minimum execution time: 18_728_000 picoseconds. + Weight::from_parts(18_982_000, 3675) + // Standard Error: 11_708 + .saturating_add(Weight::from_parts(14_363_570, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(c.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(c.into()))) .saturating_add(Weight::from_parts(0, 2609).saturating_mul(c.into())) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1001 w:1000) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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 Approvals (r:1001 w:1000) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, mode: MaxEncodedLen) /// The range of component `a` is `[0, 1000]`. fn destroy_approvals(a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `522 + a * (86 ±0)` // Estimated: `3675 + a * (2623 ±0)` - // Minimum execution time: 16_334_000 picoseconds. - Weight::from_parts(16_616_000, 3675) - // Standard Error: 6_402 - .saturating_add(Weight::from_parts(13_502_238, 0).saturating_mul(a.into())) + // Minimum execution time: 18_611_000 picoseconds. + Weight::from_parts(18_970_000, 3675) + // Standard Error: 13_224 + .saturating_add(Weight::from_parts(16_397_299, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) .saturating_add(Weight::from_parts(0, 2623).saturating_mul(a.into())) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:0) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, 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 Metadata (r:1 w:0) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn finish_destroy() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 12_278_000 picoseconds. - Weight::from_parts(12_834_000, 3675) + // Minimum execution time: 14_504_000 picoseconds. + Weight::from_parts(14_906_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn mint() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 21_793_000 picoseconds. - Weight::from_parts(22_284_000, 3675) + // Minimum execution time: 26_653_000 picoseconds. + Weight::from_parts(27_260_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn burn() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 28_712_000 picoseconds. - Weight::from_parts(29_710_000, 3675) + // Minimum execution time: 33_625_000 picoseconds. + Weight::from_parts(34_474_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 41_331_000 picoseconds. - Weight::from_parts(42_362_000, 6208) + // Minimum execution time: 47_609_000 picoseconds. + Weight::from_parts(48_476_000, 6208) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer_keep_alive() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 37_316_000 picoseconds. - Weight::from_parts(38_200_000, 6208) + // Minimum execution time: 41_625_000 picoseconds. + Weight::from_parts(43_030_000, 6208) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6208` - // Minimum execution time: 41_347_000 picoseconds. - Weight::from_parts(42_625_000, 6208) + // Minimum execution time: 47_661_000 picoseconds. + Weight::from_parts(48_469_000, 6208) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn freeze() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 15_072_000 picoseconds. - Weight::from_parts(15_925_000, 3675) + // Minimum execution time: 17_727_000 picoseconds. + Weight::from_parts(18_384_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn thaw() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 14_991_000 picoseconds. - Weight::from_parts(15_987_000, 3675) + // Minimum execution time: 17_657_000 picoseconds. + Weight::from_parts(18_282_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn freeze_asset() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 11_296_000 picoseconds. - Weight::from_parts(12_052_000, 3675) + // Minimum execution time: 13_743_000 picoseconds. + Weight::from_parts(14_193_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn thaw_asset() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 11_446_000 picoseconds. - Weight::from_parts(11_791_000, 3675) + // Minimum execution time: 13_653_000 picoseconds. + Weight::from_parts(14_263_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:0) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, 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 Metadata (r:1 w:0) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 13_134_000 picoseconds. - Weight::from_parts(13_401_000, 3675) + // Minimum execution time: 15_328_000 picoseconds. + Weight::from_parts(16_042_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn set_team() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 11_395_000 picoseconds. - Weight::from_parts(11_718_000, 3675) + // Minimum execution time: 14_097_000 picoseconds. + Weight::from_parts(14_641_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) /// The range of component `n` is `[0, 50]`. /// The range of component `s` is `[0, 50]`. - fn set_metadata(n: u32, _s: u32, ) -> Weight { + fn set_metadata(_n: u32, _s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 25_147_000 picoseconds. - Weight::from_parts(26_614_272, 3675) - // Standard Error: 959 - .saturating_add(Weight::from_parts(2_300, 0).saturating_mul(n.into())) + // Minimum execution time: 29_535_000 picoseconds. + Weight::from_parts(31_456_892, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn clear_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `515` // Estimated: `3675` - // Minimum execution time: 26_094_000 picoseconds. - Weight::from_parts(27_199_000, 3675) + // Minimum execution time: 30_680_000 picoseconds. + Weight::from_parts(31_930_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) /// The range of component `n` is `[0, 50]`. /// The range of component `s` is `[0, 50]`. - fn force_set_metadata(n: u32, s: u32, ) -> Weight { + fn force_set_metadata(_n: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `190` // Estimated: `3675` - // Minimum execution time: 11_977_000 picoseconds. - Weight::from_parts(12_719_933, 3675) - // Standard Error: 429 - .saturating_add(Weight::from_parts(3_239, 0).saturating_mul(n.into())) - // Standard Error: 429 - .saturating_add(Weight::from_parts(3_941, 0).saturating_mul(s.into())) + // Minimum execution time: 14_660_000 picoseconds. + Weight::from_parts(15_718_387, 3675) + // Standard Error: 622 + .saturating_add(Weight::from_parts(2_640, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn force_clear_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `515` // Estimated: `3675` - // Minimum execution time: 25_859_000 picoseconds. - Weight::from_parts(26_654_000, 3675) + // Minimum execution time: 30_853_000 picoseconds. + Weight::from_parts(31_483_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn force_asset_status() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 10_965_000 picoseconds. - Weight::from_parts(11_595_000, 3675) + // Minimum execution time: 13_632_000 picoseconds. + Weight::from_parts(14_077_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1 w:1) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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 Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, mode: MaxEncodedLen) fn approve_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3675` - // Minimum execution time: 28_427_000 picoseconds. - Weight::from_parts(29_150_000, 3675) + // Minimum execution time: 33_780_000 picoseconds. + Weight::from_parts(34_533_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1 w:1) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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 Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer_approved() -> Weight { // Proof Size summary in bytes: // Measured: `668` // Estimated: `6208` - // Minimum execution time: 60_227_000 picoseconds. - Weight::from_parts(61_839_000, 6208) + // Minimum execution time: 67_712_000 picoseconds. + Weight::from_parts(69_946_000, 6208) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1 w:1) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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 Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, mode: MaxEncodedLen) fn cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `555` // Estimated: `3675` - // Minimum execution time: 30_738_000 picoseconds. - Weight::from_parts(31_988_000, 3675) + // Minimum execution time: 36_668_000 picoseconds. + Weight::from_parts(37_637_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Approvals` (r:1 w:1) - /// Proof: `Assets::Approvals` (`max_values`: None, `max_size`: Some(148), added: 2623, 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 Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(148), added: 2623, mode: MaxEncodedLen) fn force_cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `555` // Estimated: `3675` - // Minimum execution time: 31_444_000 picoseconds. - Weight::from_parts(32_126_000, 3675) + // Minimum execution time: 36_685_000 picoseconds. + Weight::from_parts(37_950_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn set_min_balance() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 11_890_000 picoseconds. - Weight::from_parts(12_462_000, 3675) + // Minimum execution time: 14_466_000 picoseconds. + Weight::from_parts(14_924_000, 3675) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn touch() -> Weight { // Proof Size summary in bytes: // Measured: `453` // Estimated: `3675` - // Minimum execution time: 30_675_000 picoseconds. - Weight::from_parts(31_749_000, 3675) + // Minimum execution time: 34_874_000 picoseconds. + Weight::from_parts(36_330_000, 3675) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn touch_other() -> Weight { // Proof Size summary in bytes: // Measured: `351` // Estimated: `3675` - // Minimum execution time: 28_290_000 picoseconds. - Weight::from_parts(29_405_000, 3675) + // Minimum execution time: 33_278_000 picoseconds. + Weight::from_parts(34_104_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn refund() -> Weight { // Proof Size summary in bytes: // Measured: `579` // Estimated: `3675` - // Minimum execution time: 30_195_000 picoseconds. - Weight::from_parts(31_105_000, 3675) + // Minimum execution time: 32_898_000 picoseconds. + Weight::from_parts(33_489_000, 3675) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) fn refund_other() -> Weight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `3675` - // Minimum execution time: 27_785_000 picoseconds. - Weight::from_parts(28_783_000, 3675) + // Minimum execution time: 31_243_000 picoseconds. + Weight::from_parts(31_909_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn block() -> Weight { // Proof Size summary in bytes: // Measured: `459` // Estimated: `3675` - // Minimum execution time: 15_318_000 picoseconds. - Weight::from_parts(16_113_000, 3675) + // Minimum execution time: 17_692_000 picoseconds. + Weight::from_parts(18_253_000, 3675) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/babe/src/mock.rs b/substrate/frame/babe/src/mock.rs index 1ba0cdd0cc1..b693f4fce9b 100644 --- a/substrate/frame/babe/src/mock.rs +++ b/substrate/frame/babe/src/mock.rs @@ -37,9 +37,8 @@ use sp_core::{ use sp_io; use sp_runtime::{ curve::PiecewiseLinear, - generic::UncheckedExtrinsic, impl_opaque_keys, - testing::{Digest, DigestItem, Header}, + testing::{Digest, DigestItem, Header, TestXt}, traits::{Header as _, OpaqueKeys}, BuildStorage, Perbill, }; @@ -75,7 +74,7 @@ where RuntimeCall: From, { type OverarchingCall = RuntimeCall; - type Extrinsic = UncheckedExtrinsic; + type Extrinsic = TestXt; } impl_opaque_keys! { diff --git a/substrate/frame/bags-list/src/weights.rs b/substrate/frame/bags-list/src/weights.rs index 804b702cc9a..d929c6bb959 100644 --- a/substrate/frame/bags-list/src/weights.rs +++ b/substrate/frame/bags-list/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_bags_list` +//! Autogenerated weights for pallet_bags_list //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/bags-list/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/bags-list/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,123 +50,123 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_bags_list`. +/// Weight functions needed for pallet_bags_list. pub trait WeightInfo { fn rebag_non_terminal() -> Weight; fn rebag_terminal() -> Weight; fn put_in_front_of() -> Weight; } -/// Weights for `pallet_bags_list` using the Substrate node and recommended hardware. +/// Weights for pallet_bags_list using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:4 w:4) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:4 w:4) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn rebag_non_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1719` + // Measured: `1724` // Estimated: `11506` - // Minimum execution time: 55_856_000 picoseconds. - Weight::from_parts(59_022_000, 11506) + // Minimum execution time: 62_137_000 picoseconds. + Weight::from_parts(64_050_000, 11506) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:3 w:3) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:2 w:2) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:3 w:3) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:2 w:2) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn rebag_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1613` + // Measured: `1618` // Estimated: `8877` - // Minimum execution time: 55_418_000 picoseconds. - Weight::from_parts(57_352_000, 8877) + // Minimum execution time: 60_880_000 picoseconds. + Weight::from_parts(62_078_000, 8877) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `VoterList::ListNodes` (r:4 w:4) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:2 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:2 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: VoterList ListNodes (r:4 w:4) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:2 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:2 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn put_in_front_of() -> Weight { // Proof Size summary in bytes: - // Measured: `1925` + // Measured: `1930` // Estimated: `11506` - // Minimum execution time: 63_820_000 picoseconds. - Weight::from_parts(65_530_000, 11506) + // Minimum execution time: 68_911_000 picoseconds. + Weight::from_parts(70_592_000, 11506) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:4 w:4) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:4 w:4) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn rebag_non_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1719` + // Measured: `1724` // Estimated: `11506` - // Minimum execution time: 55_856_000 picoseconds. - Weight::from_parts(59_022_000, 11506) + // Minimum execution time: 62_137_000 picoseconds. + Weight::from_parts(64_050_000, 11506) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:3 w:3) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:2 w:2) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:3 w:3) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:2 w:2) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn rebag_terminal() -> Weight { // Proof Size summary in bytes: - // Measured: `1613` + // Measured: `1618` // Estimated: `8877` - // Minimum execution time: 55_418_000 picoseconds. - Weight::from_parts(57_352_000, 8877) + // Minimum execution time: 60_880_000 picoseconds. + Weight::from_parts(62_078_000, 8877) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `VoterList::ListNodes` (r:4 w:4) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:2 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:2 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: VoterList ListNodes (r:4 w:4) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:2 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:2 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) fn put_in_front_of() -> Weight { // Proof Size summary in bytes: - // Measured: `1925` + // Measured: `1930` // Estimated: `11506` - // Minimum execution time: 63_820_000 picoseconds. - Weight::from_parts(65_530_000, 11506) + // Minimum execution time: 68_911_000 picoseconds. + Weight::from_parts(70_592_000, 11506) .saturating_add(RocksDbWeight::get().reads(10_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } diff --git a/substrate/frame/balances/Cargo.toml b/substrate/frame/balances/Cargo.toml index db114290ed8..64ae90c6757 100644 --- a/substrate/frame/balances/Cargo.toml +++ b/substrate/frame/balances/Cargo.toml @@ -53,7 +53,6 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ diff --git a/substrate/frame/balances/src/tests/currency_tests.rs b/substrate/frame/balances/src/tests/currency_tests.rs index 10bb79901f8..46a4c4caefc 100644 --- a/substrate/frame/balances/src/tests/currency_tests.rs +++ b/substrate/frame/balances/src/tests/currency_tests.rs @@ -30,7 +30,6 @@ use frame_support::{ StorageNoopGuard, }; use frame_system::Event as SysEvent; -use sp_runtime::traits::DispatchTransaction; const ID_1: LockIdentifier = *b"1 "; const ID_2: LockIdentifier = *b"2 "; @@ -241,17 +240,17 @@ fn lock_should_work_reserve() { TokenError::Frozen ); assert_noop!(Balances::reserve(&1, 1), Error::::LiquidityRestrictions,); - assert!(ChargeTransactionPayment::::validate_and_prepare( + assert!( as SignedExtension>::pre_dispatch( ChargeTransactionPayment::from(1), - Some(1).into(), + &1, CALL, &info_from_weight(Weight::from_parts(1, 0)), 1, ) .is_err()); - assert!(ChargeTransactionPayment::::validate_and_prepare( + assert!( as SignedExtension>::pre_dispatch( ChargeTransactionPayment::from(0), - Some(1).into(), + &1, CALL, &info_from_weight(Weight::from_parts(1, 0)), 1, @@ -272,17 +271,17 @@ fn lock_should_work_tx_fee() { TokenError::Frozen ); assert_noop!(Balances::reserve(&1, 1), Error::::LiquidityRestrictions,); - assert!(ChargeTransactionPayment::::validate_and_prepare( + assert!( as SignedExtension>::pre_dispatch( ChargeTransactionPayment::from(1), - Some(1).into(), + &1, CALL, &info_from_weight(Weight::from_parts(1, 0)), 1, ) .is_err()); - assert!(ChargeTransactionPayment::::validate_and_prepare( + assert!( as SignedExtension>::pre_dispatch( ChargeTransactionPayment::from(0), - Some(1).into(), + &1, CALL, &info_from_weight(Weight::from_parts(1, 0)), 1, diff --git a/substrate/frame/balances/src/tests/mod.rs b/substrate/frame/balances/src/tests/mod.rs index ee076a10fd1..599909fa943 100644 --- a/substrate/frame/balances/src/tests/mod.rs +++ b/substrate/frame/balances/src/tests/mod.rs @@ -37,7 +37,7 @@ use scale_info::TypeInfo; use sp_core::hexdisplay::HexDisplay; use sp_io; use sp_runtime::{ - traits::{BadOrigin, Zero}, + traits::{BadOrigin, SignedExtension, Zero}, ArithmeticError, BuildStorage, DispatchError, DispatchResult, FixedPointNumber, RuntimeDebug, TokenError, }; @@ -96,13 +96,13 @@ impl frame_system::Config for Test { type AccountData = super::AccountData; } -#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for Test { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter, ()>; type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; + type FeeMultiplierUpdate = (); } pub(crate) type Balance = u64; diff --git a/substrate/frame/balances/src/weights.rs b/substrate/frame/balances/src/weights.rs index 6bcfe050af7..f875ea189ba 100644 --- a/substrate/frame/balances/src/weights.rs +++ b/substrate/frame/balances/src/weights.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_balances` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_balances -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/balances/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_balances +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/balances/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -71,8 +69,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 46_407_000 picoseconds. - Weight::from_parts(47_561_000, 3593) + // Minimum execution time: 46_329_000 picoseconds. + Weight::from_parts(47_297_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -82,8 +80,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 36_574_000 picoseconds. - Weight::from_parts(37_682_000, 3593) + // Minimum execution time: 36_187_000 picoseconds. + Weight::from_parts(36_900_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -93,8 +91,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 13_990_000 picoseconds. - Weight::from_parts(14_568_000, 3593) + // Minimum execution time: 13_498_000 picoseconds. + Weight::from_parts(14_143_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -104,8 +102,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 19_594_000 picoseconds. - Weight::from_parts(20_148_000, 3593) + // Minimum execution time: 18_756_000 picoseconds. + Weight::from_parts(19_553_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -115,8 +113,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 47_945_000 picoseconds. - Weight::from_parts(49_363_000, 6196) + // Minimum execution time: 47_826_000 picoseconds. + Weight::from_parts(48_834_000, 6196) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -126,8 +124,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 45_205_000 picoseconds. - Weight::from_parts(45_952_000, 3593) + // Minimum execution time: 44_621_000 picoseconds. + Weight::from_parts(45_151_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -137,8 +135,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_593_000 picoseconds. - Weight::from_parts(17_123_000, 3593) + // Minimum execution time: 16_194_000 picoseconds. + Weight::from_parts(16_945_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -149,10 +147,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 16_182_000 picoseconds. - Weight::from_parts(16_412_000, 990) - // Standard Error: 10_148 - .saturating_add(Weight::from_parts(13_382_459, 0).saturating_mul(u.into())) + // Minimum execution time: 15_782_000 picoseconds. + Weight::from_parts(16_118_000, 990) + // Standard Error: 10_499 + .saturating_add(Weight::from_parts(13_327_660, 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())) @@ -161,8 +159,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_478_000 picoseconds. - Weight::from_parts(6_830_000, 0) + // Minimum execution time: 6_157_000 picoseconds. + Weight::from_parts(6_507_000, 0) } } @@ -174,8 +172,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 46_407_000 picoseconds. - Weight::from_parts(47_561_000, 3593) + // Minimum execution time: 46_329_000 picoseconds. + Weight::from_parts(47_297_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -185,8 +183,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 36_574_000 picoseconds. - Weight::from_parts(37_682_000, 3593) + // Minimum execution time: 36_187_000 picoseconds. + Weight::from_parts(36_900_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -196,8 +194,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 13_990_000 picoseconds. - Weight::from_parts(14_568_000, 3593) + // Minimum execution time: 13_498_000 picoseconds. + Weight::from_parts(14_143_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -207,8 +205,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 19_594_000 picoseconds. - Weight::from_parts(20_148_000, 3593) + // Minimum execution time: 18_756_000 picoseconds. + Weight::from_parts(19_553_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -218,8 +216,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 47_945_000 picoseconds. - Weight::from_parts(49_363_000, 6196) + // Minimum execution time: 47_826_000 picoseconds. + Weight::from_parts(48_834_000, 6196) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -229,8 +227,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 45_205_000 picoseconds. - Weight::from_parts(45_952_000, 3593) + // Minimum execution time: 44_621_000 picoseconds. + Weight::from_parts(45_151_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -240,8 +238,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_593_000 picoseconds. - Weight::from_parts(17_123_000, 3593) + // Minimum execution time: 16_194_000 picoseconds. + Weight::from_parts(16_945_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -252,10 +250,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + u * (135 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 16_182_000 picoseconds. - Weight::from_parts(16_412_000, 990) - // Standard Error: 10_148 - .saturating_add(Weight::from_parts(13_382_459, 0).saturating_mul(u.into())) + // Minimum execution time: 15_782_000 picoseconds. + Weight::from_parts(16_118_000, 990) + // Standard Error: 10_499 + .saturating_add(Weight::from_parts(13_327_660, 0).saturating_mul(u.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -264,7 +262,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_478_000 picoseconds. - Weight::from_parts(6_830_000, 0) + // Minimum execution time: 6_157_000 picoseconds. + Weight::from_parts(6_507_000, 0) } } diff --git a/substrate/frame/beefy/src/mock.rs b/substrate/frame/beefy/src/mock.rs index 5d963d309a4..9cce479890a 100644 --- a/substrate/frame/beefy/src/mock.rs +++ b/substrate/frame/beefy/src/mock.rs @@ -29,8 +29,8 @@ use pallet_session::historical as pallet_session_historical; use sp_core::{crypto::KeyTypeId, ConstU128}; use sp_io::TestExternalities; use sp_runtime::{ - app_crypto::ecdsa::Public, curve::PiecewiseLinear, generic::UncheckedExtrinsic, - impl_opaque_keys, traits::OpaqueKeys, BuildStorage, Perbill, + app_crypto::ecdsa::Public, curve::PiecewiseLinear, impl_opaque_keys, testing::TestXt, + traits::OpaqueKeys, BuildStorage, Perbill, }; use sp_staking::{EraIndex, SessionIndex}; use sp_state_machine::BasicExternalities; @@ -73,7 +73,7 @@ where RuntimeCall: From, { type OverarchingCall = RuntimeCall; - type Extrinsic = UncheckedExtrinsic; + type Extrinsic = TestXt; } parameter_types! { diff --git a/substrate/frame/benchmarking/src/weights.rs b/substrate/frame/benchmarking/src/weights.rs index 76f9a3fe52b..13d73e420cc 100644 --- a/substrate/frame/benchmarking/src/weights.rs +++ b/substrate/frame/benchmarking/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `frame_benchmarking` +//! Autogenerated weights for frame_benchmarking //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/benchmarking/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/benchmarking/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `frame_benchmarking`. +/// Weight functions needed for frame_benchmarking. pub trait WeightInfo { fn addition(i: u32, ) -> Weight; fn subtraction(i: u32, ) -> Weight; @@ -59,7 +60,7 @@ pub trait WeightInfo { fn sr25519_verification(i: u32, ) -> Weight; } -/// Weights for `frame_benchmarking` using the Substrate node and recommended hardware. +/// Weights for frame_benchmarking using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 1000000]`. @@ -67,101 +68,101 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 150_000 picoseconds. - Weight::from_parts(190_440, 0) + // Minimum execution time: 147_000 picoseconds. + Weight::from_parts(185_656, 0) } /// The range of component `i` is `[0, 1000000]`. fn subtraction(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 151_000 picoseconds. - Weight::from_parts(201_397, 0) + // Minimum execution time: 146_000 picoseconds. + Weight::from_parts(189_816, 0) } /// The range of component `i` is `[0, 1000000]`. fn multiplication(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 152_000 picoseconds. - Weight::from_parts(187_862, 0) + // Minimum execution time: 148_000 picoseconds. + Weight::from_parts(202_367, 0) } /// The range of component `i` is `[0, 1000000]`. fn division(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 146_000 picoseconds. - Weight::from_parts(215_191, 0) + // Minimum execution time: 143_000 picoseconds. + Weight::from_parts(189_693, 0) } fn hashing() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 25_432_823_000 picoseconds. - Weight::from_parts(25_568_846_000, 0) + // Minimum execution time: 24_167_071_000 picoseconds. + Weight::from_parts(24_391_749_000, 0) } /// The range of component `i` is `[0, 100]`. fn sr25519_verification(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 193_000 picoseconds. - Weight::from_parts(3_846_690, 0) - // Standard Error: 6_694 - .saturating_add(Weight::from_parts(40_647_582, 0).saturating_mul(i.into())) + // Minimum execution time: 231_000 picoseconds. + Weight::from_parts(2_998_013, 0) + // Standard Error: 6_256 + .saturating_add(Weight::from_parts(55_456_705, 0).saturating_mul(i.into())) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { /// The range of component `i` is `[0, 1000000]`. fn addition(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 150_000 picoseconds. - Weight::from_parts(190_440, 0) + // Minimum execution time: 147_000 picoseconds. + Weight::from_parts(185_656, 0) } /// The range of component `i` is `[0, 1000000]`. fn subtraction(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 151_000 picoseconds. - Weight::from_parts(201_397, 0) + // Minimum execution time: 146_000 picoseconds. + Weight::from_parts(189_816, 0) } /// The range of component `i` is `[0, 1000000]`. fn multiplication(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 152_000 picoseconds. - Weight::from_parts(187_862, 0) + // Minimum execution time: 148_000 picoseconds. + Weight::from_parts(202_367, 0) } /// The range of component `i` is `[0, 1000000]`. fn division(_i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 146_000 picoseconds. - Weight::from_parts(215_191, 0) + // Minimum execution time: 143_000 picoseconds. + Weight::from_parts(189_693, 0) } fn hashing() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 25_432_823_000 picoseconds. - Weight::from_parts(25_568_846_000, 0) + // Minimum execution time: 24_167_071_000 picoseconds. + Weight::from_parts(24_391_749_000, 0) } /// The range of component `i` is `[0, 100]`. fn sr25519_verification(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 193_000 picoseconds. - Weight::from_parts(3_846_690, 0) - // Standard Error: 6_694 - .saturating_add(Weight::from_parts(40_647_582, 0).saturating_mul(i.into())) + // Minimum execution time: 231_000 picoseconds. + Weight::from_parts(2_998_013, 0) + // Standard Error: 6_256 + .saturating_add(Weight::from_parts(55_456_705, 0).saturating_mul(i.into())) } } diff --git a/substrate/frame/bounties/src/weights.rs b/substrate/frame/bounties/src/weights.rs index 1f0e38b6702..a172d15b56c 100644 --- a/substrate/frame/bounties/src/weights.rs +++ b/substrate/frame/bounties/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_bounties` +//! Autogenerated weights for pallet_bounties //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/bounties/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/bounties/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_bounties`. +/// Weight functions needed for pallet_bounties. pub trait WeightInfo { fn propose_bounty(d: u32, ) -> Weight; fn approve_bounty() -> Weight; @@ -64,169 +65,169 @@ pub trait WeightInfo { fn spend_funds(b: u32, ) -> Weight; } -/// Weights for `pallet_bounties` using the Substrate node and recommended hardware. +/// Weights for pallet_bounties using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Bounties::BountyCount` (r:1 w:1) - /// Proof: `Bounties::BountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:0 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: Bounties BountyCount (r:1 w:1) + /// Proof: Bounties BountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:0 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) /// The range of component `d` is `[0, 300]`. fn propose_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `309` + // Measured: `276` // Estimated: `3593` - // Minimum execution time: 24_286_000 picoseconds. - Weight::from_parts(25_657_314, 3593) - // Standard Error: 215 - .saturating_add(Weight::from_parts(1_116, 0).saturating_mul(d.into())) + // Minimum execution time: 29_384_000 picoseconds. + Weight::from_parts(30_820_018, 3593) + // Standard Error: 298 + .saturating_add(Weight::from_parts(2_920, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: Bounties BountyApprovals (r:1 w:1) + /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) fn approve_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `401` + // Measured: `368` // Estimated: `3642` - // Minimum execution time: 12_526_000 picoseconds. - Weight::from_parts(13_373_000, 3642) + // Minimum execution time: 10_873_000 picoseconds. + Weight::from_parts(11_421_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `421` + // Measured: `388` // Estimated: `3642` - // Minimum execution time: 11_807_000 picoseconds. - Weight::from_parts(12_340_000, 3642) + // Minimum execution time: 9_181_000 picoseconds. + Weight::from_parts(9_726_000, 3642) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `597` + // Measured: `564` // Estimated: `3642` - // Minimum execution time: 27_183_000 picoseconds. - Weight::from_parts(28_250_000, 3642) + // Minimum execution time: 30_257_000 picoseconds. + Weight::from_parts(30_751_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `593` + // Measured: `560` // Estimated: `3642` - // Minimum execution time: 26_775_000 picoseconds. - Weight::from_parts(27_667_000, 3642) + // Minimum execution time: 27_850_000 picoseconds. + Weight::from_parts(28_821_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:0) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) fn award_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `605` + // Measured: `572` // Estimated: `3642` - // Minimum execution time: 16_089_000 picoseconds. - Weight::from_parts(16_909_000, 3642) + // Minimum execution time: 19_164_000 picoseconds. + Weight::from_parts(20_136_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:3 w:3) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn claim_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `969` + // Measured: `936` // Estimated: `8799` - // Minimum execution time: 104_973_000 picoseconds. - Weight::from_parts(107_696_000, 8799) + // Minimum execution time: 120_235_000 picoseconds. + Weight::from_parts(121_673_000, 8799) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:0) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn close_bounty_proposed() -> Weight { // Proof Size summary in bytes: - // Measured: `649` + // Measured: `616` // Estimated: `3642` - // Minimum execution time: 30_702_000 picoseconds. - Weight::from_parts(32_615_000, 3642) + // Minimum execution time: 35_713_000 picoseconds. + Weight::from_parts(37_174_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:0) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn close_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `885` + // Measured: `852` // Estimated: `6196` - // Minimum execution time: 72_055_000 picoseconds. - Weight::from_parts(73_900_000, 6196) + // Minimum execution time: 81_037_000 picoseconds. + Weight::from_parts(83_294_000, 6196) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) fn extend_bounty_expiry() -> Weight { // Proof Size summary in bytes: - // Measured: `457` + // Measured: `424` // Estimated: `3642` - // Minimum execution time: 12_057_000 picoseconds. - Weight::from_parts(12_744_000, 3642) + // Minimum execution time: 15_348_000 picoseconds. + Weight::from_parts(15_776_000, 3642) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:100 w:100) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:200 w:200) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties BountyApprovals (r:1 w:1) + /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:100 w:100) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:200 w:200) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `b` is `[0, 100]`. fn spend_funds(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `37 + b * (297 ±0)` + // Measured: `4 + b * (297 ±0)` // Estimated: `1887 + b * (5206 ±0)` - // Minimum execution time: 3_489_000 picoseconds. - Weight::from_parts(8_384_129, 1887) - // Standard Error: 18_066 - .saturating_add(Weight::from_parts(31_612_331, 0).saturating_mul(b.into())) + // Minimum execution time: 5_082_000 picoseconds. + Weight::from_parts(5_126_000, 1887) + // Standard Error: 21_949 + .saturating_add(Weight::from_parts(42_635_308, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -235,168 +236,168 @@ impl WeightInfo for SubstrateWeight { } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Bounties::BountyCount` (r:1 w:1) - /// Proof: `Bounties::BountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:0 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: Bounties BountyCount (r:1 w:1) + /// Proof: Bounties BountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:0 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) /// The range of component `d` is `[0, 300]`. fn propose_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `309` + // Measured: `276` // Estimated: `3593` - // Minimum execution time: 24_286_000 picoseconds. - Weight::from_parts(25_657_314, 3593) - // Standard Error: 215 - .saturating_add(Weight::from_parts(1_116, 0).saturating_mul(d.into())) + // Minimum execution time: 29_384_000 picoseconds. + Weight::from_parts(30_820_018, 3593) + // Standard Error: 298 + .saturating_add(Weight::from_parts(2_920, 0).saturating_mul(d.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: Bounties BountyApprovals (r:1 w:1) + /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) fn approve_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `401` + // Measured: `368` // Estimated: `3642` - // Minimum execution time: 12_526_000 picoseconds. - Weight::from_parts(13_373_000, 3642) + // Minimum execution time: 10_873_000 picoseconds. + Weight::from_parts(11_421_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `421` + // Measured: `388` // Estimated: `3642` - // Minimum execution time: 11_807_000 picoseconds. - Weight::from_parts(12_340_000, 3642) + // Minimum execution time: 9_181_000 picoseconds. + Weight::from_parts(9_726_000, 3642) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `597` + // Measured: `564` // Estimated: `3642` - // Minimum execution time: 27_183_000 picoseconds. - Weight::from_parts(28_250_000, 3642) + // Minimum execution time: 30_257_000 picoseconds. + Weight::from_parts(30_751_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `593` + // Measured: `560` // Estimated: `3642` - // Minimum execution time: 26_775_000 picoseconds. - Weight::from_parts(27_667_000, 3642) + // Minimum execution time: 27_850_000 picoseconds. + Weight::from_parts(28_821_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:0) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) fn award_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `605` + // Measured: `572` // Estimated: `3642` - // Minimum execution time: 16_089_000 picoseconds. - Weight::from_parts(16_909_000, 3642) + // Minimum execution time: 19_164_000 picoseconds. + Weight::from_parts(20_136_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:3 w:3) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn claim_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `969` + // Measured: `936` // Estimated: `8799` - // Minimum execution time: 104_973_000 picoseconds. - Weight::from_parts(107_696_000, 8799) + // Minimum execution time: 120_235_000 picoseconds. + Weight::from_parts(121_673_000, 8799) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:0) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn close_bounty_proposed() -> Weight { // Proof Size summary in bytes: - // Measured: `649` + // Measured: `616` // Estimated: `3642` - // Minimum execution time: 30_702_000 picoseconds. - Weight::from_parts(32_615_000, 3642) + // Minimum execution time: 35_713_000 picoseconds. + Weight::from_parts(37_174_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:0) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyDescriptions` (r:0 w:1) - /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:0) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyDescriptions (r:0 w:1) + /// Proof: Bounties BountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn close_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `885` + // Measured: `852` // Estimated: `6196` - // Minimum execution time: 72_055_000 picoseconds. - Weight::from_parts(73_900_000, 6196) + // Minimum execution time: 81_037_000 picoseconds. + Weight::from_parts(83_294_000, 6196) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:1) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:1) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) fn extend_bounty_expiry() -> Weight { // Proof Size summary in bytes: - // Measured: `457` + // Measured: `424` // Estimated: `3642` - // Minimum execution time: 12_057_000 picoseconds. - Weight::from_parts(12_744_000, 3642) + // Minimum execution time: 15_348_000 picoseconds. + Weight::from_parts(15_776_000, 3642) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:100 w:100) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:200 w:200) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties BountyApprovals (r:1 w:1) + /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:100 w:100) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:200 w:200) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `b` is `[0, 100]`. fn spend_funds(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `37 + b * (297 ±0)` + // Measured: `4 + b * (297 ±0)` // Estimated: `1887 + b * (5206 ±0)` - // Minimum execution time: 3_489_000 picoseconds. - Weight::from_parts(8_384_129, 1887) - // Standard Error: 18_066 - .saturating_add(Weight::from_parts(31_612_331, 0).saturating_mul(b.into())) + // Minimum execution time: 5_082_000 picoseconds. + Weight::from_parts(5_126_000, 1887) + // Standard Error: 21_949 + .saturating_add(Weight::from_parts(42_635_308, 0).saturating_mul(b.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(b.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) diff --git a/substrate/frame/broker/src/weights.rs b/substrate/frame/broker/src/weights.rs index 133ea63e35f..a8f50eeee6e 100644 --- a/substrate/frame/broker/src/weights.rs +++ b/substrate/frame/broker/src/weights.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_broker` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-09-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-pzhd7p6z-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_broker -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/broker/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_broker +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/broker/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -89,8 +87,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_701_000 picoseconds. - Weight::from_parts(2_902_000, 0) + // Minimum execution time: 3_040_000 picoseconds. + Weight::from_parts(3_344_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -99,8 +97,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 18_056_000 picoseconds. - Weight::from_parts(19_093_000, 7496) + // Minimum execution time: 21_259_000 picoseconds. + Weight::from_parts(22_110_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -110,8 +108,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 17_233_000 picoseconds. - Weight::from_parts(17_788_000, 7496) + // Minimum execution time: 20_330_000 picoseconds. + Weight::from_parts(20_826_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -121,8 +119,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 9_740_000 picoseconds. - Weight::from_parts(10_504_000, 1526) + // Minimum execution time: 13_411_000 picoseconds. + Weight::from_parts(13_960_000, 1526) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -141,12 +139,14 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(_n: u32, ) -> Weight { + fn start_sales(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 49_728_000 picoseconds. - Weight::from_parts(52_765_861, 8499) + // Minimum execution time: 57_770_000 picoseconds. + Weight::from_parts(61_047_512, 8499) + // Standard Error: 165 + .saturating_add(Weight::from_parts(3, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(16_u64)) } @@ -162,10 +162,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn purchase() -> Weight { // Proof Size summary in bytes: - // Measured: `635` - // Estimated: `2120` - // Minimum execution time: 41_986_000 picoseconds. - Weight::from_parts(43_465_000, 2120) + // Measured: `568` + // Estimated: `2053` + // Minimum execution time: 51_196_000 picoseconds. + Weight::from_parts(52_382_000, 2053) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -185,10 +185,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `753` + // Measured: `686` // Estimated: `4698` - // Minimum execution time: 61_779_000 picoseconds. - Weight::from_parts(62_563_000, 4698) + // Minimum execution time: 71_636_000 picoseconds. + Weight::from_parts(73_679_000, 4698) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -198,8 +198,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 16_962_000 picoseconds. - Weight::from_parts(17_733_000, 3550) + // Minimum execution time: 19_182_000 picoseconds. + Weight::from_parts(19_775_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -209,21 +209,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 18_380_000 picoseconds. - Weight::from_parts(19_105_000, 3550) + // Minimum execution time: 20_688_000 picoseconds. + Weight::from_parts(21_557_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Broker::Regions` (r:1 w:3) + /// Storage: `Broker::Regions` (r:1 w:2) /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn interlace() -> Weight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 20_115_000 picoseconds. - Weight::from_parts(20_741_000, 3550) + // Minimum execution time: 21_190_000 picoseconds. + Weight::from_parts(22_215_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) @@ -237,8 +237,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `740` // Estimated: `4681` - // Minimum execution time: 31_339_000 picoseconds. - Weight::from_parts(32_639_000, 4681) + // Minimum execution time: 34_591_000 picoseconds. + Weight::from_parts(36_227_000, 4681) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -256,8 +256,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `775` // Estimated: `5996` - // Minimum execution time: 37_542_000 picoseconds. - Weight::from_parts(38_521_000, 5996) + // Minimum execution time: 40_346_000 picoseconds. + Weight::from_parts(41_951_000, 5996) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -272,10 +272,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 66_176_000 picoseconds. - Weight::from_parts(68_356_745, 6196) - // Standard Error: 68_008 - .saturating_add(Weight::from_parts(1_558_419, 0).saturating_mul(m.into())) + // Minimum execution time: 75_734_000 picoseconds. + Weight::from_parts(78_168_395, 6196) + // Standard Error: 63_180 + .saturating_add(Weight::from_parts(1_076_259, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) @@ -287,8 +287,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 41_130_000 picoseconds. - Weight::from_parts(41_914_000, 3593) + // Minimum execution time: 46_383_000 picoseconds. + Weight::from_parts(47_405_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -300,8 +300,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `603` // Estimated: `3550` - // Minimum execution time: 31_042_000 picoseconds. - Weight::from_parts(34_087_000, 3550) + // Minimum execution time: 30_994_000 picoseconds. + Weight::from_parts(31_979_000, 3550) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -315,8 +315,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 39_116_000 picoseconds. - Weight::from_parts(39_990_000, 3533) + // Minimum execution time: 37_584_000 picoseconds. + Weight::from_parts(44_010_000, 3533) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -330,10 +330,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_history() -> Weight { // Proof Size summary in bytes: - // Measured: `995` + // Measured: `830` // Estimated: `3593` - // Minimum execution time: 47_547_000 picoseconds. - Weight::from_parts(50_274_000, 3593) + // Minimum execution time: 45_266_000 picoseconds. + Weight::from_parts(48_000_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -343,32 +343,34 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: - // Measured: `661` + // Measured: `525` // Estimated: `4698` - // Minimum execution time: 26_707_000 picoseconds. - Weight::from_parts(27_217_000, 4698) + // Minimum execution time: 25_365_000 picoseconds. + Weight::from_parts(26_920_000, 4698) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// The range of component `n` is `[0, 1000]`. - fn request_core_count(_n: u32, ) -> Weight { + fn request_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_651_000 picoseconds. - Weight::from_parts(5_231_385, 0) + // Minimum execution time: 6_519_000 picoseconds. + Weight::from_parts(7_098_698, 0) + // Standard Error: 20 + .saturating_add(Weight::from_parts(8, 0).saturating_mul(n.into())) } - /// Storage: `Broker::CoreCountInbox` (r:1 w:1) - /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) /// The range of component `n` is `[0, 1000]`. fn process_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `404` - // Estimated: `1487` - // Minimum execution time: 6_806_000 picoseconds. - Weight::from_parts(7_264_002, 1487) - // Standard Error: 21 - .saturating_add(Weight::from_parts(31, 0).saturating_mul(n.into())) + // Measured: `98` + // Estimated: `3563` + // Minimum execution time: 7_608_000 picoseconds. + Weight::from_parts(8_157_815, 3563) + // Standard Error: 26 + .saturating_add(Weight::from_parts(48, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -384,10 +386,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn process_revenue() -> Weight { // Proof Size summary in bytes: - // Measured: `972` - // Estimated: `4437` - // Minimum execution time: 48_297_000 picoseconds. - Weight::from_parts(49_613_000, 4437) + // Measured: `905` + // Estimated: `4370` + // Minimum execution time: 59_993_000 picoseconds. + Weight::from_parts(61_752_000, 4370) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -406,10 +408,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 36_715_000 picoseconds. - Weight::from_parts(38_580_380, 8499) - // Standard Error: 91 - .saturating_add(Weight::from_parts(1_163, 0).saturating_mul(n.into())) + // Minimum execution time: 41_863_000 picoseconds. + Weight::from_parts(44_033_031, 8499) + // Standard Error: 116 + .saturating_add(Weight::from_parts(764, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)) } @@ -421,8 +423,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 7_564_000 picoseconds. - Weight::from_parts(7_932_000, 3493) + // Minimum execution time: 9_588_000 picoseconds. + Weight::from_parts(9_925_000, 3493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -434,8 +436,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 17_082_000 picoseconds. - Weight::from_parts(17_662_000, 4681) + // Minimum execution time: 19_308_000 picoseconds. + Weight::from_parts(20_482_000, 4681) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -443,35 +445,28 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 175_000 picoseconds. - Weight::from_parts(223_000, 0) + // Minimum execution time: 147_000 picoseconds. + Weight::from_parts(184_000, 0) } - /// Storage: `Broker::CoreCountInbox` (r:0 w:1) - /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) fn notify_core_count() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_432_000 picoseconds. - Weight::from_parts(2_536_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + T::DbWeight::get().reads_writes(1, 1) } /// Storage: `Broker::Status` (r:1 w:1) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) - /// Storage: `Broker::CoreCountInbox` (r:1 w:0) - /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) fn do_tick_base() -> Weight { // Proof Size summary in bytes: - // Measured: `603` - // Estimated: `4068` - // Minimum execution time: 13_080_000 picoseconds. - Weight::from_parts(13_937_000, 4068) + // Measured: `699` + // Estimated: `4164` + // Minimum execution time: 19_824_000 picoseconds. + Weight::from_parts(20_983_000, 4164) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } } @@ -483,8 +478,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_701_000 picoseconds. - Weight::from_parts(2_902_000, 0) + // Minimum execution time: 3_040_000 picoseconds. + Weight::from_parts(3_344_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -493,8 +488,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 18_056_000 picoseconds. - Weight::from_parts(19_093_000, 7496) + // Minimum execution time: 21_259_000 picoseconds. + Weight::from_parts(22_110_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -504,8 +499,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 17_233_000 picoseconds. - Weight::from_parts(17_788_000, 7496) + // Minimum execution time: 20_330_000 picoseconds. + Weight::from_parts(20_826_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -515,8 +510,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 9_740_000 picoseconds. - Weight::from_parts(10_504_000, 1526) + // Minimum execution time: 13_411_000 picoseconds. + Weight::from_parts(13_960_000, 1526) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -535,12 +530,14 @@ impl WeightInfo for () { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(_n: u32, ) -> Weight { + fn start_sales(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 49_728_000 picoseconds. - Weight::from_parts(52_765_861, 8499) + // Minimum execution time: 57_770_000 picoseconds. + Weight::from_parts(61_047_512, 8499) + // Standard Error: 165 + .saturating_add(Weight::from_parts(3, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(16_u64)) } @@ -556,10 +553,10 @@ impl WeightInfo for () { /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn purchase() -> Weight { // Proof Size summary in bytes: - // Measured: `635` - // Estimated: `2120` - // Minimum execution time: 41_986_000 picoseconds. - Weight::from_parts(43_465_000, 2120) + // Measured: `568` + // Estimated: `2053` + // Minimum execution time: 51_196_000 picoseconds. + Weight::from_parts(52_382_000, 2053) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -579,10 +576,10 @@ impl WeightInfo for () { /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `753` + // Measured: `686` // Estimated: `4698` - // Minimum execution time: 61_779_000 picoseconds. - Weight::from_parts(62_563_000, 4698) + // Minimum execution time: 71_636_000 picoseconds. + Weight::from_parts(73_679_000, 4698) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -592,8 +589,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 16_962_000 picoseconds. - Weight::from_parts(17_733_000, 3550) + // Minimum execution time: 19_182_000 picoseconds. + Weight::from_parts(19_775_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -603,21 +600,21 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 18_380_000 picoseconds. - Weight::from_parts(19_105_000, 3550) + // Minimum execution time: 20_688_000 picoseconds. + Weight::from_parts(21_557_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Broker::Regions` (r:1 w:3) + /// Storage: `Broker::Regions` (r:1 w:2) /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn interlace() -> Weight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 20_115_000 picoseconds. - Weight::from_parts(20_741_000, 3550) + // Minimum execution time: 21_190_000 picoseconds. + Weight::from_parts(22_215_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) @@ -631,8 +628,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `740` // Estimated: `4681` - // Minimum execution time: 31_339_000 picoseconds. - Weight::from_parts(32_639_000, 4681) + // Minimum execution time: 34_591_000 picoseconds. + Weight::from_parts(36_227_000, 4681) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -650,8 +647,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `775` // Estimated: `5996` - // Minimum execution time: 37_542_000 picoseconds. - Weight::from_parts(38_521_000, 5996) + // Minimum execution time: 40_346_000 picoseconds. + Weight::from_parts(41_951_000, 5996) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -666,10 +663,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 66_176_000 picoseconds. - Weight::from_parts(68_356_745, 6196) - // Standard Error: 68_008 - .saturating_add(Weight::from_parts(1_558_419, 0).saturating_mul(m.into())) + // Minimum execution time: 75_734_000 picoseconds. + Weight::from_parts(78_168_395, 6196) + // Standard Error: 63_180 + .saturating_add(Weight::from_parts(1_076_259, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(RocksDbWeight::get().writes(5_u64)) @@ -681,8 +678,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 41_130_000 picoseconds. - Weight::from_parts(41_914_000, 3593) + // Minimum execution time: 46_383_000 picoseconds. + Weight::from_parts(47_405_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -694,8 +691,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `603` // Estimated: `3550` - // Minimum execution time: 31_042_000 picoseconds. - Weight::from_parts(34_087_000, 3550) + // Minimum execution time: 30_994_000 picoseconds. + Weight::from_parts(31_979_000, 3550) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -709,8 +706,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 39_116_000 picoseconds. - Weight::from_parts(39_990_000, 3533) + // Minimum execution time: 37_584_000 picoseconds. + Weight::from_parts(44_010_000, 3533) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -724,10 +721,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_history() -> Weight { // Proof Size summary in bytes: - // Measured: `995` + // Measured: `830` // Estimated: `3593` - // Minimum execution time: 47_547_000 picoseconds. - Weight::from_parts(50_274_000, 3593) + // Minimum execution time: 45_266_000 picoseconds. + Weight::from_parts(48_000_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -737,32 +734,34 @@ impl WeightInfo for () { /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: - // Measured: `661` + // Measured: `525` // Estimated: `4698` - // Minimum execution time: 26_707_000 picoseconds. - Weight::from_parts(27_217_000, 4698) + // Minimum execution time: 25_365_000 picoseconds. + Weight::from_parts(26_920_000, 4698) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// The range of component `n` is `[0, 1000]`. - fn request_core_count(_n: u32, ) -> Weight { + fn request_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_651_000 picoseconds. - Weight::from_parts(5_231_385, 0) + // Minimum execution time: 6_519_000 picoseconds. + Weight::from_parts(7_098_698, 0) + // Standard Error: 20 + .saturating_add(Weight::from_parts(8, 0).saturating_mul(n.into())) } - /// Storage: `Broker::CoreCountInbox` (r:1 w:1) - /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) /// The range of component `n` is `[0, 1000]`. fn process_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `404` - // Estimated: `1487` - // Minimum execution time: 6_806_000 picoseconds. - Weight::from_parts(7_264_002, 1487) - // Standard Error: 21 - .saturating_add(Weight::from_parts(31, 0).saturating_mul(n.into())) + // Measured: `98` + // Estimated: `3563` + // Minimum execution time: 7_608_000 picoseconds. + Weight::from_parts(8_157_815, 3563) + // Standard Error: 26 + .saturating_add(Weight::from_parts(48, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -778,10 +777,10 @@ impl WeightInfo for () { /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn process_revenue() -> Weight { // Proof Size summary in bytes: - // Measured: `972` - // Estimated: `4437` - // Minimum execution time: 48_297_000 picoseconds. - Weight::from_parts(49_613_000, 4437) + // Measured: `905` + // Estimated: `4370` + // Minimum execution time: 59_993_000 picoseconds. + Weight::from_parts(61_752_000, 4370) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -800,10 +799,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 36_715_000 picoseconds. - Weight::from_parts(38_580_380, 8499) - // Standard Error: 91 - .saturating_add(Weight::from_parts(1_163, 0).saturating_mul(n.into())) + // Minimum execution time: 41_863_000 picoseconds. + Weight::from_parts(44_033_031, 8499) + // Standard Error: 116 + .saturating_add(Weight::from_parts(764, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(15_u64)) } @@ -815,8 +814,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 7_564_000 picoseconds. - Weight::from_parts(7_932_000, 3493) + // Minimum execution time: 9_588_000 picoseconds. + Weight::from_parts(9_925_000, 3493) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -828,8 +827,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 17_082_000 picoseconds. - Weight::from_parts(17_662_000, 4681) + // Minimum execution time: 19_308_000 picoseconds. + Weight::from_parts(20_482_000, 4681) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -837,34 +836,28 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 175_000 picoseconds. - Weight::from_parts(223_000, 0) + // Minimum execution time: 147_000 picoseconds. + Weight::from_parts(184_000, 0) } - /// Storage: `Broker::CoreCountInbox` (r:0 w:1) - /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) fn notify_core_count() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_432_000 picoseconds. - Weight::from_parts(2_536_000, 0) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + RocksDbWeight::get().reads(1) + .saturating_add(RocksDbWeight::get().writes(1)) } /// Storage: `Broker::Status` (r:1 w:1) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) - /// Storage: `Broker::CoreCountInbox` (r:1 w:0) - /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) fn do_tick_base() -> Weight { // Proof Size summary in bytes: - // Measured: `603` - // Estimated: `4068` - // Minimum execution time: 13_080_000 picoseconds. - Weight::from_parts(13_937_000, 4068) + // Measured: `699` + // Estimated: `4164` + // Minimum execution time: 19_824_000 picoseconds. + Weight::from_parts(20_983_000, 4164) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } } diff --git a/substrate/frame/child-bounties/src/weights.rs b/substrate/frame/child-bounties/src/weights.rs index 6427517b45b..e4c1f238e88 100644 --- a/substrate/frame/child-bounties/src/weights.rs +++ b/substrate/frame/child-bounties/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_child_bounties` +//! Autogenerated weights for pallet_child_bounties //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/child-bounties/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/child-bounties/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_child_bounties`. +/// Weight functions needed for pallet_child_bounties. pub trait WeightInfo { fn add_child_bounty(d: u32, ) -> Weight; fn propose_curator() -> Weight; @@ -61,288 +62,288 @@ pub trait WeightInfo { fn close_child_bounty_active() -> Weight; } -/// Weights for `pallet_child_bounties` using the Substrate node and recommended hardware. +/// Weights for pallet_child_bounties using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyCount` (r:1 w:1) - /// Proof: `ChildBounties::ChildBountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:0 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: ChildBounties ParentChildBounties (r:1 w:1) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyCount (r:1 w:1) + /// Proof: ChildBounties ChildBountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:0 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) /// The range of component `d` is `[0, 300]`. fn add_child_bounty(_d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `745` + // Measured: `712` // Estimated: `6196` - // Minimum execution time: 60_674_000 picoseconds. - Weight::from_parts(63_477_428, 6196) + // Minimum execution time: 69_805_000 picoseconds. + Weight::from_parts(73_216_717, 6196) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `799` + // Measured: `766` // Estimated: `3642` - // Minimum execution time: 17_754_000 picoseconds. - Weight::from_parts(18_655_000, 3642) + // Minimum execution time: 18_190_000 picoseconds. + Weight::from_parts(18_932_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `945` + // Measured: `912` // Estimated: `3642` - // Minimum execution time: 31_580_000 picoseconds. - Weight::from_parts(32_499_000, 3642) + // Minimum execution time: 35_035_000 picoseconds. + Weight::from_parts(35_975_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `945` + // Measured: `912` // Estimated: `3642` - // Minimum execution time: 33_536_000 picoseconds. - Weight::from_parts(34_102_000, 3642) + // Minimum execution time: 37_636_000 picoseconds. + Weight::from_parts(38_610_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) fn award_child_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `842` + // Measured: `809` // Estimated: `3642` - // Minimum execution time: 18_295_000 picoseconds. - Weight::from_parts(19_496_000, 3642) + // Minimum execution time: 22_457_000 picoseconds. + Weight::from_parts(23_691_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: System Account (r:3 w:3) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:1) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn claim_child_bounty() -> Weight { // Proof Size summary in bytes: // Measured: `682` // Estimated: `8799` - // Minimum execution time: 102_367_000 picoseconds. - Weight::from_parts(104_352_000, 8799) + // Minimum execution time: 118_272_000 picoseconds. + Weight::from_parts(121_646_000, 8799) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:1) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn close_child_bounty_added() -> Weight { // Proof Size summary in bytes: - // Measured: `1045` + // Measured: `1012` // Estimated: `6196` - // Minimum execution time: 69_051_000 picoseconds. - Weight::from_parts(71_297_000, 6196) + // Minimum execution time: 75_717_000 picoseconds. + Weight::from_parts(77_837_000, 6196) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: System Account (r:3 w:3) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:1) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn close_child_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `1232` + // Measured: `1199` // Estimated: `8799` - // Minimum execution time: 84_053_000 picoseconds. - Weight::from_parts(86_072_000, 8799) + // Minimum execution time: 94_215_000 picoseconds. + Weight::from_parts(97_017_000, 8799) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyCount` (r:1 w:1) - /// Proof: `ChildBounties::ChildBountyCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:0 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: ChildBounties ParentChildBounties (r:1 w:1) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyCount (r:1 w:1) + /// Proof: ChildBounties ChildBountyCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:0 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) /// The range of component `d` is `[0, 300]`. fn add_child_bounty(_d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `745` + // Measured: `712` // Estimated: `6196` - // Minimum execution time: 60_674_000 picoseconds. - Weight::from_parts(63_477_428, 6196) + // Minimum execution time: 69_805_000 picoseconds. + Weight::from_parts(73_216_717, 6196) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `799` + // Measured: `766` // Estimated: `3642` - // Minimum execution time: 17_754_000 picoseconds. - Weight::from_parts(18_655_000, 3642) + // Minimum execution time: 18_190_000 picoseconds. + Weight::from_parts(18_932_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `945` + // Measured: `912` // Estimated: `3642` - // Minimum execution time: 31_580_000 picoseconds. - Weight::from_parts(32_499_000, 3642) + // Minimum execution time: 35_035_000 picoseconds. + Weight::from_parts(35_975_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `945` + // Measured: `912` // Estimated: `3642` - // Minimum execution time: 33_536_000 picoseconds. - Weight::from_parts(34_102_000, 3642) + // Minimum execution time: 37_636_000 picoseconds. + Weight::from_parts(38_610_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) fn award_child_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `842` + // Measured: `809` // Estimated: `3642` - // Minimum execution time: 18_295_000 picoseconds. - Weight::from_parts(19_496_000, 3642) + // Minimum execution time: 22_457_000 picoseconds. + Weight::from_parts(23_691_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: System Account (r:3 w:3) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:1) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn claim_child_bounty() -> Weight { // Proof Size summary in bytes: // Measured: `682` // Estimated: `8799` - // Minimum execution time: 102_367_000 picoseconds. - Weight::from_parts(104_352_000, 8799) + // Minimum execution time: 118_272_000 picoseconds. + Weight::from_parts(121_646_000, 8799) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:1) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn close_child_bounty_added() -> Weight { // Proof Size summary in bytes: - // Measured: `1045` + // Measured: `1012` // Estimated: `6196` - // Minimum execution time: 69_051_000 picoseconds. - Weight::from_parts(71_297_000, 6196) + // Minimum execution time: 75_717_000 picoseconds. + Weight::from_parts(77_837_000, 6196) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `Bounties::Bounties` (r:1 w:0) - /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ChildBounties` (`max_values`: None, `max_size`: Some(145), added: 2620, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:3 w:3) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildrenCuratorFees` (r:1 w:1) - /// Proof: `ChildBounties::ChildrenCuratorFees` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ParentChildBounties` (r:1 w:1) - /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `ChildBounties::ChildBountyDescriptions` (r:0 w:1) - /// Proof: `ChildBounties::ChildBountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: Bounties Bounties (r:1 w:0) + /// Proof: Bounties Bounties (max_values: None, max_size: Some(177), added: 2652, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBounties (r:1 w:1) + /// Proof: ChildBounties ChildBounties (max_values: None, max_size: Some(145), added: 2620, mode: MaxEncodedLen) + /// Storage: System Account (r:3 w:3) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) + /// Proof: ChildBounties ChildrenCuratorFees (max_values: None, max_size: Some(28), added: 2503, mode: MaxEncodedLen) + /// Storage: ChildBounties ParentChildBounties (r:1 w:1) + /// Proof: ChildBounties ParentChildBounties (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) + /// Proof: ChildBounties ChildBountyDescriptions (max_values: None, max_size: Some(314), added: 2789, mode: MaxEncodedLen) fn close_child_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `1232` + // Measured: `1199` // Estimated: `8799` - // Minimum execution time: 84_053_000 picoseconds. - Weight::from_parts(86_072_000, 8799) + // Minimum execution time: 94_215_000 picoseconds. + Weight::from_parts(97_017_000, 8799) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } diff --git a/substrate/frame/collective/src/tests.rs b/substrate/frame/collective/src/tests.rs index 92418794c5f..02c3377515c 100644 --- a/substrate/frame/collective/src/tests.rs +++ b/substrate/frame/collective/src/tests.rs @@ -29,7 +29,7 @@ use sp_core::H256; use sp_runtime::{testing::Header, traits::BlakeTwo256, BuildStorage}; pub type Block = sp_runtime::generic::Block; -pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; frame_support::construct_runtime!( pub enum Test diff --git a/substrate/frame/collective/src/weights.rs b/substrate/frame/collective/src/weights.rs index 85744b4de9d..eece6a006b8 100644 --- a/substrate/frame/collective/src/weights.rs +++ b/substrate/frame/collective/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_collective` +//! Autogenerated weights for pallet_collective //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/collective/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/collective/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_collective`. +/// Weight functions needed for pallet_collective. pub trait WeightInfo { fn set_members(m: u32, n: u32, p: u32, ) -> Weight; fn execute(b: u32, m: u32, ) -> Weight; @@ -63,30 +64,30 @@ pub trait WeightInfo { fn disapprove_proposal(p: u32, ) -> Weight; } -/// Weights for `pallet_collective` using the Substrate node and recommended hardware. +/// Weights for pallet_collective using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Council::Members` (r:1 w:1) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:0) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Voting` (r:100 w:100) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:0 w:1) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Council Members (r:1 w:1) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:0) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Voting (r:100 w:100) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Prime (r:0 w:1) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[0, 100]`. /// The range of component `n` is `[0, 100]`. /// The range of component `p` is `[0, 100]`. fn set_members(m: u32, _n: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + m * (3232 ±0) + p * (3190 ±0)` - // Estimated: `15894 + m * (1967 ±23) + p * (4332 ±23)` - // Minimum execution time: 15_559_000 picoseconds. - Weight::from_parts(15_870_000, 15894) - // Standard Error: 54_310 - .saturating_add(Weight::from_parts(4_117_753, 0).saturating_mul(m.into())) - // Standard Error: 54_310 - .saturating_add(Weight::from_parts(7_677_627, 0).saturating_mul(p.into())) + // Estimated: `15861 + m * (1967 ±24) + p * (4332 ±24)` + // Minimum execution time: 17_506_000 picoseconds. + Weight::from_parts(17_767_000, 15861) + // Standard Error: 60_220 + .saturating_add(Weight::from_parts(4_374_805, 0).saturating_mul(m.into())) + // Standard Error: 60_220 + .saturating_add(Weight::from_parts(8_398_316, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -94,261 +95,245 @@ impl WeightInfo for SubstrateWeight { .saturating_add(Weight::from_parts(0, 1967).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 4332).saturating_mul(p.into())) } - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `380 + m * (32 ±0)` - // Estimated: `3997 + m * (32 ±0)` - // Minimum execution time: 19_024_000 picoseconds. - Weight::from_parts(18_153_872, 3997) - // Standard Error: 46 - .saturating_add(Weight::from_parts(1_933, 0).saturating_mul(b.into())) - // Standard Error: 478 - .saturating_add(Weight::from_parts(18_872, 0).saturating_mul(m.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Measured: `202 + m * (32 ±0)` + // Estimated: `1688 + m * (32 ±0)` + // Minimum execution time: 16_203_000 picoseconds. + Weight::from_parts(15_348_267, 1688) + // Standard Error: 37 + .saturating_add(Weight::from_parts(1_766, 0).saturating_mul(b.into())) + // Standard Error: 382 + .saturating_add(Weight::from_parts(15_765, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:1 w:0) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:1 w:0) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `380 + m * (32 ±0)` - // Estimated: `3997 + m * (32 ±0)` - // Minimum execution time: 20_895_000 picoseconds. - Weight::from_parts(20_081_761, 3997) - // Standard Error: 57 - .saturating_add(Weight::from_parts(1_982, 0).saturating_mul(b.into())) - // Standard Error: 594 - .saturating_add(Weight::from_parts(32_085, 0).saturating_mul(m.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Measured: `202 + m * (32 ±0)` + // Estimated: `3668 + m * (32 ±0)` + // Minimum execution time: 18_642_000 picoseconds. + Weight::from_parts(17_708_609, 3668) + // Standard Error: 58 + .saturating_add(Weight::from_parts(2_285, 0).saturating_mul(b.into())) + // Standard Error: 598 + .saturating_add(Weight::from_parts(30_454, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:1 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalCount` (r:1 w:1) - /// Proof: `Council::ProposalCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Voting` (r:0 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:1 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalCount (r:1 w:1) + /// Proof Skipped: Council ProposalCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Voting (r:0 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `525 + m * (32 ±0) + p * (36 ±0)` - // Estimated: `3917 + m * (33 ±0) + p * (36 ±0)` - // Minimum execution time: 22_068_000 picoseconds. - Weight::from_parts(19_639_088, 3917) - // Standard Error: 104 - .saturating_add(Weight::from_parts(3_896, 0).saturating_mul(b.into())) - // Standard Error: 1_095 - .saturating_add(Weight::from_parts(31_634, 0).saturating_mul(m.into())) - // Standard Error: 1_081 - .saturating_add(Weight::from_parts(178_702, 0).saturating_mul(p.into())) + // Measured: `492 + m * (32 ±0) + p * (36 ±0)` + // Estimated: `3884 + m * (33 ±0) + p * (36 ±0)` + // Minimum execution time: 27_067_000 picoseconds. + Weight::from_parts(25_456_964, 3884) + // Standard Error: 112 + .saturating_add(Weight::from_parts(3_773, 0).saturating_mul(b.into())) + // Standard Error: 1_177 + .saturating_add(Weight::from_parts(32_783, 0).saturating_mul(m.into())) + // Standard Error: 1_162 + .saturating_add(Weight::from_parts(194_388, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 33).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `974 + m * (64 ±0)` - // Estimated: `4438 + m * (64 ±0)` - // Minimum execution time: 22_395_000 picoseconds. - Weight::from_parts(23_025_217, 4438) - // Standard Error: 842 - .saturating_add(Weight::from_parts(58_102, 0).saturating_mul(m.into())) + // Measured: `941 + m * (64 ±0)` + // Estimated: `4405 + m * (64 ±0)` + // Minimum execution time: 26_055_000 picoseconds. + Weight::from_parts(27_251_907, 4405) + // Standard Error: 1_008 + .saturating_add(Weight::from_parts(65_947, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:0 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:0 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `563 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `4008 + m * (65 ±0) + p * (36 ±0)` - // Minimum execution time: 24_179_000 picoseconds. - Weight::from_parts(23_846_394, 4008) - // Standard Error: 1_052 - .saturating_add(Weight::from_parts(40_418, 0).saturating_mul(m.into())) - // Standard Error: 1_026 - .saturating_add(Weight::from_parts(171_653, 0).saturating_mul(p.into())) + // Measured: `530 + m * (64 ±0) + p * (36 ±0)` + // Estimated: `3975 + m * (65 ±0) + p * (36 ±0)` + // Minimum execution time: 28_363_000 picoseconds. + Weight::from_parts(28_733_464, 3975) + // Standard Error: 1_275 + .saturating_add(Weight::from_parts(43_236, 0).saturating_mul(m.into())) + // Standard Error: 1_244 + .saturating_add(Weight::from_parts(180_187, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 65).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:1 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:1 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1010 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `4327 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` - // Minimum execution time: 42_129_000 picoseconds. - Weight::from_parts(40_808_957, 4327) - // Standard Error: 134 - .saturating_add(Weight::from_parts(3_579, 0).saturating_mul(b.into())) - // Standard Error: 1_425 - .saturating_add(Weight::from_parts(37_166, 0).saturating_mul(m.into())) - // Standard Error: 1_389 - .saturating_add(Weight::from_parts(200_986, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) + // Measured: `832 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` + // Estimated: `4149 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` + // Minimum execution time: 40_391_000 picoseconds. + Weight::from_parts(42_695_215, 4149) + // Standard Error: 167 + .saturating_add(Weight::from_parts(3_622, 0).saturating_mul(b.into())) + // Standard Error: 1_772 + .saturating_add(Weight::from_parts(33_830, 0).saturating_mul(m.into())) + // Standard Error: 1_727 + .saturating_add(Weight::from_parts(205_374, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) .saturating_add(Weight::from_parts(0, 66).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:1 w:0) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:0 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:1 w:0) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:0 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `583 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `4028 + m * (65 ±0) + p * (36 ±0)` - // Minimum execution time: 26_385_000 picoseconds. - Weight::from_parts(25_713_839, 4028) - // Standard Error: 1_254 - .saturating_add(Weight::from_parts(36_206, 0).saturating_mul(m.into())) - // Standard Error: 1_223 - .saturating_add(Weight::from_parts(195_114, 0).saturating_mul(p.into())) + // Measured: `550 + m * (64 ±0) + p * (36 ±0)` + // Estimated: `3995 + m * (65 ±0) + p * (36 ±0)` + // Minimum execution time: 31_368_000 picoseconds. + Weight::from_parts(32_141_835, 3995) + // Standard Error: 1_451 + .saturating_add(Weight::from_parts(36_372, 0).saturating_mul(m.into())) + // Standard Error: 1_415 + .saturating_add(Weight::from_parts(210_635, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 65).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:1 w:0) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:1 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:1 w:0) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:1 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1030 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `4347 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` - // Minimum execution time: 42_903_000 picoseconds. - Weight::from_parts(43_152_907, 4347) - // Standard Error: 146 - .saturating_add(Weight::from_parts(3_459, 0).saturating_mul(b.into())) - // Standard Error: 1_548 - .saturating_add(Weight::from_parts(35_321, 0).saturating_mul(m.into())) - // Standard Error: 1_509 - .saturating_add(Weight::from_parts(202_541, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(7_u64)) + // Measured: `852 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` + // Estimated: `4169 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` + // Minimum execution time: 43_271_000 picoseconds. + Weight::from_parts(45_495_648, 4169) + // Standard Error: 174 + .saturating_add(Weight::from_parts(3_034, 0).saturating_mul(b.into())) + // Standard Error: 1_840 + .saturating_add(Weight::from_parts(42_209, 0).saturating_mul(m.into())) + // Standard Error: 1_793 + .saturating_add(Weight::from_parts(207_525, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) .saturating_add(Weight::from_parts(0, 66).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Voting` (r:0 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:0 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Voting (r:0 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:0 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `392 + p * (32 ±0)` - // Estimated: `1877 + p * (32 ±0)` - // Minimum execution time: 12_656_000 picoseconds. - Weight::from_parts(14_032_951, 1877) - // Standard Error: 1_025 - .saturating_add(Weight::from_parts(159_143, 0).saturating_mul(p.into())) + // Measured: `359 + p * (32 ±0)` + // Estimated: `1844 + p * (32 ±0)` + // Minimum execution time: 15_170_000 picoseconds. + Weight::from_parts(17_567_243, 1844) + // Standard Error: 1_430 + .saturating_add(Weight::from_parts(169_040, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(p.into())) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Council::Members` (r:1 w:1) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:0) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Voting` (r:100 w:100) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:0 w:1) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Council Members (r:1 w:1) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:0) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Voting (r:100 w:100) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Prime (r:0 w:1) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[0, 100]`. /// The range of component `n` is `[0, 100]`. /// The range of component `p` is `[0, 100]`. fn set_members(m: u32, _n: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + m * (3232 ±0) + p * (3190 ±0)` - // Estimated: `15894 + m * (1967 ±23) + p * (4332 ±23)` - // Minimum execution time: 15_559_000 picoseconds. - Weight::from_parts(15_870_000, 15894) - // Standard Error: 54_310 - .saturating_add(Weight::from_parts(4_117_753, 0).saturating_mul(m.into())) - // Standard Error: 54_310 - .saturating_add(Weight::from_parts(7_677_627, 0).saturating_mul(p.into())) + // Estimated: `15861 + m * (1967 ±24) + p * (4332 ±24)` + // Minimum execution time: 17_506_000 picoseconds. + Weight::from_parts(17_767_000, 15861) + // Standard Error: 60_220 + .saturating_add(Weight::from_parts(4_374_805, 0).saturating_mul(m.into())) + // Standard Error: 60_220 + .saturating_add(Weight::from_parts(8_398_316, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -356,232 +341,216 @@ impl WeightInfo for () { .saturating_add(Weight::from_parts(0, 1967).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 4332).saturating_mul(p.into())) } - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `380 + m * (32 ±0)` - // Estimated: `3997 + m * (32 ±0)` - // Minimum execution time: 19_024_000 picoseconds. - Weight::from_parts(18_153_872, 3997) - // Standard Error: 46 - .saturating_add(Weight::from_parts(1_933, 0).saturating_mul(b.into())) - // Standard Error: 478 - .saturating_add(Weight::from_parts(18_872, 0).saturating_mul(m.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Measured: `202 + m * (32 ±0)` + // Estimated: `1688 + m * (32 ±0)` + // Minimum execution time: 16_203_000 picoseconds. + Weight::from_parts(15_348_267, 1688) + // Standard Error: 37 + .saturating_add(Weight::from_parts(1_766, 0).saturating_mul(b.into())) + // Standard Error: 382 + .saturating_add(Weight::from_parts(15_765, 0).saturating_mul(m.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:1 w:0) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:1 w:0) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `380 + m * (32 ±0)` - // Estimated: `3997 + m * (32 ±0)` - // Minimum execution time: 20_895_000 picoseconds. - Weight::from_parts(20_081_761, 3997) - // Standard Error: 57 - .saturating_add(Weight::from_parts(1_982, 0).saturating_mul(b.into())) - // Standard Error: 594 - .saturating_add(Weight::from_parts(32_085, 0).saturating_mul(m.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + // Measured: `202 + m * (32 ±0)` + // Estimated: `3668 + m * (32 ±0)` + // Minimum execution time: 18_642_000 picoseconds. + Weight::from_parts(17_708_609, 3668) + // Standard Error: 58 + .saturating_add(Weight::from_parts(2_285, 0).saturating_mul(b.into())) + // Standard Error: 598 + .saturating_add(Weight::from_parts(30_454, 0).saturating_mul(m.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:1 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalCount` (r:1 w:1) - /// Proof: `Council::ProposalCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Voting` (r:0 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:1 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalCount (r:1 w:1) + /// Proof Skipped: Council ProposalCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Voting (r:0 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `525 + m * (32 ±0) + p * (36 ±0)` - // Estimated: `3917 + m * (33 ±0) + p * (36 ±0)` - // Minimum execution time: 22_068_000 picoseconds. - Weight::from_parts(19_639_088, 3917) - // Standard Error: 104 - .saturating_add(Weight::from_parts(3_896, 0).saturating_mul(b.into())) - // Standard Error: 1_095 - .saturating_add(Weight::from_parts(31_634, 0).saturating_mul(m.into())) - // Standard Error: 1_081 - .saturating_add(Weight::from_parts(178_702, 0).saturating_mul(p.into())) + // Measured: `492 + m * (32 ±0) + p * (36 ±0)` + // Estimated: `3884 + m * (33 ±0) + p * (36 ±0)` + // Minimum execution time: 27_067_000 picoseconds. + Weight::from_parts(25_456_964, 3884) + // Standard Error: 112 + .saturating_add(Weight::from_parts(3_773, 0).saturating_mul(b.into())) + // Standard Error: 1_177 + .saturating_add(Weight::from_parts(32_783, 0).saturating_mul(m.into())) + // Standard Error: 1_162 + .saturating_add(Weight::from_parts(194_388, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 33).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `974 + m * (64 ±0)` - // Estimated: `4438 + m * (64 ±0)` - // Minimum execution time: 22_395_000 picoseconds. - Weight::from_parts(23_025_217, 4438) - // Standard Error: 842 - .saturating_add(Weight::from_parts(58_102, 0).saturating_mul(m.into())) + // Measured: `941 + m * (64 ±0)` + // Estimated: `4405 + m * (64 ±0)` + // Minimum execution time: 26_055_000 picoseconds. + Weight::from_parts(27_251_907, 4405) + // Standard Error: 1_008 + .saturating_add(Weight::from_parts(65_947, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:0 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:0 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `563 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `4008 + m * (65 ±0) + p * (36 ±0)` - // Minimum execution time: 24_179_000 picoseconds. - Weight::from_parts(23_846_394, 4008) - // Standard Error: 1_052 - .saturating_add(Weight::from_parts(40_418, 0).saturating_mul(m.into())) - // Standard Error: 1_026 - .saturating_add(Weight::from_parts(171_653, 0).saturating_mul(p.into())) + // Measured: `530 + m * (64 ±0) + p * (36 ±0)` + // Estimated: `3975 + m * (65 ±0) + p * (36 ±0)` + // Minimum execution time: 28_363_000 picoseconds. + Weight::from_parts(28_733_464, 3975) + // Standard Error: 1_275 + .saturating_add(Weight::from_parts(43_236, 0).saturating_mul(m.into())) + // Standard Error: 1_244 + .saturating_add(Weight::from_parts(180_187, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 65).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:1 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:1 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1010 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `4327 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` - // Minimum execution time: 42_129_000 picoseconds. - Weight::from_parts(40_808_957, 4327) - // Standard Error: 134 - .saturating_add(Weight::from_parts(3_579, 0).saturating_mul(b.into())) - // Standard Error: 1_425 - .saturating_add(Weight::from_parts(37_166, 0).saturating_mul(m.into())) - // Standard Error: 1_389 - .saturating_add(Weight::from_parts(200_986, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) + // Measured: `832 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` + // Estimated: `4149 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` + // Minimum execution time: 40_391_000 picoseconds. + Weight::from_parts(42_695_215, 4149) + // Standard Error: 167 + .saturating_add(Weight::from_parts(3_622, 0).saturating_mul(b.into())) + // Standard Error: 1_772 + .saturating_add(Weight::from_parts(33_830, 0).saturating_mul(m.into())) + // Standard Error: 1_727 + .saturating_add(Weight::from_parts(205_374, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) .saturating_add(Weight::from_parts(0, 66).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:1 w:0) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:0 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:1 w:0) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:0 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `583 + m * (64 ±0) + p * (36 ±0)` - // Estimated: `4028 + m * (65 ±0) + p * (36 ±0)` - // Minimum execution time: 26_385_000 picoseconds. - Weight::from_parts(25_713_839, 4028) - // Standard Error: 1_254 - .saturating_add(Weight::from_parts(36_206, 0).saturating_mul(m.into())) - // Standard Error: 1_223 - .saturating_add(Weight::from_parts(195_114, 0).saturating_mul(p.into())) + // Measured: `550 + m * (64 ±0) + p * (36 ±0)` + // Estimated: `3995 + m * (65 ±0) + p * (36 ±0)` + // Minimum execution time: 31_368_000 picoseconds. + Weight::from_parts(32_141_835, 3995) + // Standard Error: 1_451 + .saturating_add(Weight::from_parts(36_372, 0).saturating_mul(m.into())) + // Standard Error: 1_415 + .saturating_add(Weight::from_parts(210_635, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 65).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) } - /// Storage: `Council::Voting` (r:1 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:1 w:0) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:1 w:0) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:1 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Council Voting (r:1 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Members (r:1 w:0) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:1 w:0) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:1 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1030 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` - // Estimated: `4347 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` - // Minimum execution time: 42_903_000 picoseconds. - Weight::from_parts(43_152_907, 4347) - // Standard Error: 146 - .saturating_add(Weight::from_parts(3_459, 0).saturating_mul(b.into())) - // Standard Error: 1_548 - .saturating_add(Weight::from_parts(35_321, 0).saturating_mul(m.into())) - // Standard Error: 1_509 - .saturating_add(Weight::from_parts(202_541, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(7_u64)) + // Measured: `852 + b * (1 ±0) + m * (64 ±0) + p * (40 ±0)` + // Estimated: `4169 + b * (1 ±0) + m * (66 ±0) + p * (40 ±0)` + // Minimum execution time: 43_271_000 picoseconds. + Weight::from_parts(45_495_648, 4169) + // Standard Error: 174 + .saturating_add(Weight::from_parts(3_034, 0).saturating_mul(b.into())) + // Standard Error: 1_840 + .saturating_add(Weight::from_parts(42_209, 0).saturating_mul(m.into())) + // Standard Error: 1_793 + .saturating_add(Weight::from_parts(207_525, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) .saturating_add(Weight::from_parts(0, 66).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) } - /// Storage: `Council::Proposals` (r:1 w:1) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Voting` (r:0 w:1) - /// Proof: `Council::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::ProposalOf` (r:0 w:1) - /// Proof: `Council::ProposalOf` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Council Proposals (r:1 w:1) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Voting (r:0 w:1) + /// Proof Skipped: Council Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council ProposalOf (r:0 w:1) + /// Proof Skipped: Council ProposalOf (max_values: None, max_size: None, mode: Measured) /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `392 + p * (32 ±0)` - // Estimated: `1877 + p * (32 ±0)` - // Minimum execution time: 12_656_000 picoseconds. - Weight::from_parts(14_032_951, 1877) - // Standard Error: 1_025 - .saturating_add(Weight::from_parts(159_143, 0).saturating_mul(p.into())) + // Measured: `359 + p * (32 ±0)` + // Estimated: `1844 + p * (32 ±0)` + // Minimum execution time: 15_170_000 picoseconds. + Weight::from_parts(17_567_243, 1844) + // Standard Error: 1_430 + .saturating_add(Weight::from_parts(169_040, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(p.into())) diff --git a/substrate/frame/contracts/src/weights.rs b/substrate/frame/contracts/src/weights.rs index 6e09120c141..99bc4d8d3eb 100644 --- a/substrate/frame/contracts/src/weights.rs +++ b/substrate/frame/contracts/src/weights.rs @@ -25,6 +25,7 @@ // Executed Command: // target/production/substrate-node +// target/production/substrate-node // benchmark // pallet // --steps=50 @@ -35,8 +36,12 @@ // --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json // --pallet=pallet_contracts // --chain=dev +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_contracts +// --chain=dev // --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/contracts/src/weights.rs +// --output=./substrate/frame/contracts/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -213,8 +218,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553053f13fd319a03c211337c76e0fe776df` (r:2 w:0) /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:0 w:1) @@ -248,7 +251,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) fn v14_migration_step() -> Weight { // Proof Size summary in bytes: // Measured: `352` @@ -332,8 +335,6 @@ impl WeightInfo for SubstrateWeight { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -361,12 +362,10 @@ impl WeightInfo for SubstrateWeight { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// Storage: `System::EventTopics` (r:3 w:3) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) @@ -403,8 +402,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -416,7 +413,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:2 w:2) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { @@ -434,8 +431,6 @@ impl WeightInfo for SubstrateWeight { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -459,12 +454,10 @@ impl WeightInfo for SubstrateWeight { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -510,7 +503,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -545,8 +538,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -574,8 +565,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -604,8 +593,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -634,8 +621,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -663,8 +648,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -690,8 +673,6 @@ impl WeightInfo for SubstrateWeight { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -719,8 +700,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -748,8 +727,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -777,8 +754,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:2 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -806,8 +781,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -835,8 +808,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -864,8 +835,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -893,8 +862,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -922,8 +889,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -953,8 +918,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -982,8 +945,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1010,8 +971,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1039,8 +998,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1067,8 +1024,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:1 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:2) @@ -1082,7 +1037,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// Storage: `Contracts::DeletionQueue` (r:0 w:1) /// Proof: `Contracts::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) /// The range of component `r` is `[0, 1]`. @@ -1098,14 +1053,12 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((10_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 5479).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 5266).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1135,8 +1088,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1164,8 +1115,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1198,8 +1147,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1227,8 +1174,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1423,8 +1368,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1602 w:1601) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1454,8 +1397,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -1485,8 +1426,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:736 w:0) @@ -1516,8 +1455,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -1550,8 +1487,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:802 w:802) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:801 w:800) @@ -1565,7 +1500,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:803 w:803) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:800 w:800) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// The range of component `r` is `[1, 800]`. fn seal_instantiate(r: u32, ) -> Weight { // Proof Size summary in bytes: @@ -1585,8 +1520,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:1) @@ -1600,7 +1533,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. @@ -1624,8 +1557,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1653,8 +1584,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1681,8 +1610,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1710,8 +1637,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1738,8 +1663,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1767,8 +1690,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1795,8 +1716,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1824,8 +1743,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1852,8 +1769,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1881,8 +1796,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1910,8 +1823,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1939,8 +1850,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1968,8 +1877,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536) @@ -1999,8 +1906,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -2024,14 +1929,12 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2607).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 2606).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -2045,7 +1948,7 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 32]`. fn unlock_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `972 + r * (184 ±0)` + // Measured: `969 + r * (183 ±0)` // Estimated: `129453 + r * (2568 ±0)` // Minimum execution time: 270_652_000 picoseconds. Weight::from_parts(293_369_452, 129453) @@ -2061,8 +1964,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2090,8 +1991,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2119,8 +2018,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2237,8 +2134,6 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553053f13fd319a03c211337c76e0fe776df` (r:2 w:0) /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:0 w:1) @@ -2272,7 +2167,7 @@ impl WeightInfo for () { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) fn v14_migration_step() -> Weight { // Proof Size summary in bytes: // Measured: `352` @@ -2356,8 +2251,6 @@ impl WeightInfo for () { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2385,12 +2278,10 @@ impl WeightInfo for () { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// Storage: `System::EventTopics` (r:3 w:3) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) @@ -2427,8 +2318,6 @@ impl WeightInfo for () { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -2440,7 +2329,7 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:2 w:2) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { @@ -2458,8 +2347,6 @@ impl WeightInfo for () { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2483,12 +2370,10 @@ impl WeightInfo for () { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -2534,7 +2419,7 @@ impl WeightInfo for () { /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -2569,8 +2454,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2598,8 +2481,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2628,8 +2509,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2658,8 +2537,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2687,8 +2564,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2714,8 +2589,6 @@ impl WeightInfo for () { } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2743,8 +2616,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2772,8 +2643,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2801,8 +2670,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:2 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2830,8 +2697,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2859,8 +2724,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2888,8 +2751,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2917,8 +2778,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2946,8 +2805,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2977,8 +2834,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3006,8 +2861,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3034,8 +2887,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3063,8 +2914,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3091,8 +2940,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:1 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:2) @@ -3106,7 +2953,7 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// Storage: `Contracts::DeletionQueue` (r:0 w:1) /// Proof: `Contracts::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) /// The range of component `r` is `[0, 1]`. @@ -3122,14 +2969,12 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((10_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 5479).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 5266).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3159,8 +3004,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3188,8 +3031,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3222,8 +3063,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3251,8 +3090,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3447,8 +3284,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1602 w:1601) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3478,8 +3313,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -3509,8 +3342,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:736 w:0) @@ -3540,8 +3371,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -3574,8 +3403,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:802 w:802) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:801 w:800) @@ -3589,7 +3416,7 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:803 w:803) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:800 w:800) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// The range of component `r` is `[1, 800]`. fn seal_instantiate(r: u32, ) -> Weight { // Proof Size summary in bytes: @@ -3609,8 +3436,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:1) @@ -3624,7 +3449,7 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. @@ -3648,8 +3473,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3677,8 +3500,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3705,8 +3526,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3734,8 +3553,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3762,8 +3579,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3791,8 +3606,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3819,8 +3632,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3848,8 +3659,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3876,8 +3685,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3905,8 +3712,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3934,8 +3739,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3963,8 +3766,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3992,8 +3793,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536) @@ -4023,8 +3822,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -4048,14 +3845,12 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2607).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 2606).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -4069,7 +3864,7 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 32]`. fn unlock_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `972 + r * (184 ±0)` + // Measured: `969 + r * (183 ±0)` // Estimated: `129453 + r * (2568 ±0)` // Minimum execution time: 270_652_000 picoseconds. Weight::from_parts(293_369_452, 129453) @@ -4085,8 +3880,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -4114,8 +3907,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -4143,8 +3934,6 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) - /// Storage: `Parameters::Parameters` (r:3 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) diff --git a/substrate/frame/conviction-voting/src/weights.rs b/substrate/frame/conviction-voting/src/weights.rs index 75d9e8499ed..225f5c2cadd 100644 --- a/substrate/frame/conviction-voting/src/weights.rs +++ b/substrate/frame/conviction-voting/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_conviction_voting` +//! Autogenerated weights for pallet_conviction_voting //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/conviction-voting/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/conviction-voting/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_conviction_voting`. +/// Weight functions needed for pallet_conviction_voting. pub trait WeightInfo { fn vote_new() -> Weight; fn vote_existing() -> Weight; @@ -60,300 +61,280 @@ pub trait WeightInfo { fn unlock() -> Weight; } -/// Weights for `pallet_conviction_voting` using the Substrate node and recommended hardware. +/// Weights for pallet_conviction_voting using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `13141` + // Measured: `13074` // Estimated: `219984` - // Minimum execution time: 102_539_000 picoseconds. - Weight::from_parts(105_873_000, 219984) + // Minimum execution time: 112_936_000 picoseconds. + Weight::from_parts(116_972_000, 219984) .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `20283` + // Measured: `20216` // Estimated: `219984` - // Minimum execution time: 275_424_000 picoseconds. - Weight::from_parts(283_690_000, 219984) + // Minimum execution time: 291_971_000 picoseconds. + Weight::from_parts(301_738_000, 219984) .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn remove_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `20035` + // Measured: `19968` // Estimated: `219984` - // Minimum execution time: 275_109_000 picoseconds. - Weight::from_parts(281_315_000, 219984) + // Minimum execution time: 262_582_000 picoseconds. + Weight::from_parts(270_955_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn remove_other_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `12742` + // Measured: `12675` // Estimated: `30706` - // Minimum execution time: 49_629_000 picoseconds. - Weight::from_parts(51_300_000, 30706) + // Minimum execution time: 52_909_000 picoseconds. + Weight::from_parts(56_365_000, 30706) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `r` is `[0, 1]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `306 + r * (1628 ±0)` + // Measured: `240 + r * (1627 ±0)` // Estimated: `109992 + r * (109992 ±0)` - // Minimum execution time: 45_776_000 picoseconds. - Weight::from_parts(47_917_822, 109992) - // Standard Error: 124_174 - .saturating_add(Weight::from_parts(43_171_077, 0).saturating_mul(r.into())) + // Minimum execution time: 54_640_000 picoseconds. + Weight::from_parts(57_185_281, 109992) + // Standard Error: 193_362 + .saturating_add(Weight::from_parts(44_897_418, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 109992).saturating_mul(r.into())) } - /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) /// The range of component `r` is `[0, 1]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `472 + r * (1377 ±0)` + // Measured: `406 + r * (1376 ±0)` // Estimated: `109992 + r * (109992 ±0)` - // Minimum execution time: 23_600_000 picoseconds. - Weight::from_parts(25_001_426, 109992) - // Standard Error: 72_034 - .saturating_add(Weight::from_parts(37_851_873, 0).saturating_mul(r.into())) + // Minimum execution time: 26_514_000 picoseconds. + Weight::from_parts(28_083_732, 109992) + // Standard Error: 104_905 + .saturating_add(Weight::from_parts(40_722_467, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 109992).saturating_mul(r.into())) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn unlock() -> Weight { // Proof Size summary in bytes: - // Measured: `11800` + // Measured: `11734` // Estimated: `30706` - // Minimum execution time: 66_247_000 picoseconds. - Weight::from_parts(67_552_000, 30706) + // Minimum execution time: 71_140_000 picoseconds. + Weight::from_parts(77_388_000, 30706) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `13141` + // Measured: `13074` // Estimated: `219984` - // Minimum execution time: 102_539_000 picoseconds. - Weight::from_parts(105_873_000, 219984) + // Minimum execution time: 112_936_000 picoseconds. + Weight::from_parts(116_972_000, 219984) .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `20283` + // Measured: `20216` // Estimated: `219984` - // Minimum execution time: 275_424_000 picoseconds. - Weight::from_parts(283_690_000, 219984) + // Minimum execution time: 291_971_000 picoseconds. + Weight::from_parts(301_738_000, 219984) .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn remove_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `20035` + // Measured: `19968` // Estimated: `219984` - // Minimum execution time: 275_109_000 picoseconds. - Weight::from_parts(281_315_000, 219984) + // Minimum execution time: 262_582_000 picoseconds. + Weight::from_parts(270_955_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn remove_other_vote() -> Weight { // Proof Size summary in bytes: - // Measured: `12742` + // Measured: `12675` // Estimated: `30706` - // Minimum execution time: 49_629_000 picoseconds. - Weight::from_parts(51_300_000, 30706) + // Minimum execution time: 52_909_000 picoseconds. + Weight::from_parts(56_365_000, 30706) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `r` is `[0, 1]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `306 + r * (1628 ±0)` + // Measured: `240 + r * (1627 ±0)` // Estimated: `109992 + r * (109992 ±0)` - // Minimum execution time: 45_776_000 picoseconds. - Weight::from_parts(47_917_822, 109992) - // Standard Error: 124_174 - .saturating_add(Weight::from_parts(43_171_077, 0).saturating_mul(r.into())) + // Minimum execution time: 54_640_000 picoseconds. + Weight::from_parts(57_185_281, 109992) + // Standard Error: 193_362 + .saturating_add(Weight::from_parts(44_897_418, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(r.into()))) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 109992).saturating_mul(r.into())) } - /// Storage: `ConvictionVoting::VotingFor` (r:2 w:2) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) /// The range of component `r` is `[0, 1]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `472 + r * (1377 ±0)` + // Measured: `406 + r * (1376 ±0)` // Estimated: `109992 + r * (109992 ±0)` - // Minimum execution time: 23_600_000 picoseconds. - Weight::from_parts(25_001_426, 109992) - // Standard Error: 72_034 - .saturating_add(Weight::from_parts(37_851_873, 0).saturating_mul(r.into())) + // Minimum execution time: 26_514_000 picoseconds. + Weight::from_parts(28_083_732, 109992) + // Standard Error: 104_905 + .saturating_add(Weight::from_parts(40_722_467, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(r.into()))) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 109992).saturating_mul(r.into())) } - /// Storage: `ConvictionVoting::VotingFor` (r:1 w:1) - /// Proof: `ConvictionVoting::VotingFor` (`max_values`: None, `max_size`: Some(27241), added: 29716, mode: `MaxEncodedLen`) - /// Storage: `ConvictionVoting::ClassLocksFor` (r:1 w:1) - /// Proof: `ConvictionVoting::ClassLocksFor` (`max_values`: None, `max_size`: Some(59), added: 2534, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27241), added: 29716, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(59), added: 2534, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn unlock() -> Weight { // Proof Size summary in bytes: - // Measured: `11800` + // Measured: `11734` // Estimated: `30706` - // Minimum execution time: 66_247_000 picoseconds. - Weight::from_parts(67_552_000, 30706) + // Minimum execution time: 71_140_000 picoseconds. + Weight::from_parts(77_388_000, 30706) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/substrate/frame/core-fellowship/src/weights.rs b/substrate/frame/core-fellowship/src/weights.rs index fce1d3747a8..8bbfd1a4dd8 100644 --- a/substrate/frame/core-fellowship/src/weights.rs +++ b/substrate/frame/core-fellowship/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_core_fellowship` +//! Autogenerated weights for pallet_core_fellowship //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/core-fellowship/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/core-fellowship/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_core_fellowship`. +/// Weight functions needed for pallet_core_fellowship. pub trait WeightInfo { fn set_params() -> Weight; fn bump_offboard() -> Weight; @@ -63,344 +64,336 @@ pub trait WeightInfo { fn submit_evidence() -> Weight; } -/// Weights for `pallet_core_fellowship` using the Substrate node and recommended hardware. +/// Weights for pallet_core_fellowship using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `CoreFellowship::Params` (r:0 w:1) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Params (r:0 w:1) + /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) fn set_params() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_146_000 picoseconds. - Weight::from_parts(7_426_000, 0) + // Minimum execution time: 9_454_000 picoseconds. + Weight::from_parts(9_804_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Params (r:1 w:0) + /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:1 w:0) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn bump_offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `17274` + // Measured: `16887` // Estimated: `19894` - // Minimum execution time: 54_511_000 picoseconds. - Weight::from_parts(56_995_000, 19894) + // Minimum execution time: 58_489_000 picoseconds. + Weight::from_parts(60_202_000, 19894) .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Params (r:1 w:0) + /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:1 w:0) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn bump_demote() -> Weight { // Proof Size summary in bytes: - // Measured: `17384` + // Measured: `16997` // Estimated: `19894` - // Minimum execution time: 56_453_000 picoseconds. - Weight::from_parts(59_030_000, 19894) + // Minimum execution time: 60_605_000 picoseconds. + Weight::from_parts(63_957_000, 19894) .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn set_active() -> Weight { // Proof Size summary in bytes: // Measured: `388` // Estimated: `3514` - // Minimum execution time: 15_940_000 picoseconds. - Weight::from_parts(16_381_000, 3514) + // Minimum execution time: 17_816_000 picoseconds. + Weight::from_parts(18_524_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:0 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:0 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) fn induct() -> Weight { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3514` - // Minimum execution time: 24_193_000 picoseconds. - Weight::from_parts(24_963_000, 3514) + // Minimum execution time: 27_249_000 picoseconds. + Weight::from_parts(28_049_000, 3514) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: CoreFellowship Params (r:1 w:0) + /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:0 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:0 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) fn promote() -> Weight { // Proof Size summary in bytes: // Measured: `16865` // Estimated: `19894` - // Minimum execution time: 48_138_000 picoseconds. - Weight::from_parts(50_007_000, 19894) + // Minimum execution time: 56_642_000 picoseconds. + Weight::from_parts(59_353_000, 19894) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:0 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:0 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `293` + // Measured: `359` // Estimated: `3514` - // Minimum execution time: 15_225_000 picoseconds. - Weight::from_parts(15_730_000, 3514) + // Minimum execution time: 17_459_000 picoseconds. + Weight::from_parts(18_033_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) fn import() -> Weight { // Proof Size summary in bytes: // Measured: `313` // Estimated: `3514` - // Minimum execution time: 14_507_000 picoseconds. - Weight::from_parts(14_935_000, 3514) + // Minimum execution time: 16_728_000 picoseconds. + Weight::from_parts(17_263_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn approve() -> Weight { // Proof Size summary in bytes: // Measured: `16843` // Estimated: `19894` - // Minimum execution time: 34_050_000 picoseconds. - Weight::from_parts(36_323_000, 19894) + // Minimum execution time: 41_487_000 picoseconds. + Weight::from_parts(43_459_000, 19894) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:0) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:0) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn submit_evidence() -> Weight { // Proof Size summary in bytes: // Measured: `79` // Estimated: `19894` - // Minimum execution time: 24_016_000 picoseconds. - Weight::from_parts(24_607_000, 19894) + // Minimum execution time: 26_033_000 picoseconds. + Weight::from_parts(26_612_000, 19894) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `CoreFellowship::Params` (r:0 w:1) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Params (r:0 w:1) + /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) fn set_params() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_146_000 picoseconds. - Weight::from_parts(7_426_000, 0) + // Minimum execution time: 9_454_000 picoseconds. + Weight::from_parts(9_804_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Params (r:1 w:0) + /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:1 w:0) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn bump_offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `17274` + // Measured: `16887` // Estimated: `19894` - // Minimum execution time: 54_511_000 picoseconds. - Weight::from_parts(56_995_000, 19894) + // Minimum execution time: 58_489_000 picoseconds. + Weight::from_parts(60_202_000, 19894) .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:1 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Params (r:1 w:0) + /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:1 w:0) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn bump_demote() -> Weight { // Proof Size summary in bytes: - // Measured: `17384` + // Measured: `16997` // Estimated: `19894` - // Minimum execution time: 56_453_000 picoseconds. - Weight::from_parts(59_030_000, 19894) + // Minimum execution time: 60_605_000 picoseconds. + Weight::from_parts(63_957_000, 19894) .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn set_active() -> Weight { // Proof Size summary in bytes: // Measured: `388` // Estimated: `3514` - // Minimum execution time: 15_940_000 picoseconds. - Weight::from_parts(16_381_000, 3514) + // Minimum execution time: 17_816_000 picoseconds. + Weight::from_parts(18_524_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:0 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:0 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) fn induct() -> Weight { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3514` - // Minimum execution time: 24_193_000 picoseconds. - Weight::from_parts(24_963_000, 3514) + // Minimum execution time: 27_249_000 picoseconds. + Weight::from_parts(28_049_000, 3514) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Params` (r:1 w:0) - /// Proof: `CoreFellowship::Params` (`max_values`: Some(1), `max_size`: Some(364), added: 859, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: CoreFellowship Params (r:1 w:0) + /// Proof: CoreFellowship Params (max_values: Some(1), max_size: Some(364), added: 859, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:0 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:0 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) fn promote() -> Weight { // Proof Size summary in bytes: // Measured: `16865` // Estimated: `19894` - // Minimum execution time: 48_138_000 picoseconds. - Weight::from_parts(50_007_000, 19894) + // Minimum execution time: 56_642_000 picoseconds. + Weight::from_parts(59_353_000, 19894) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:0 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:0 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn offboard() -> Weight { // Proof Size summary in bytes: - // Measured: `293` + // Measured: `359` // Estimated: `3514` - // Minimum execution time: 15_225_000 picoseconds. - Weight::from_parts(15_730_000, 3514) + // Minimum execution time: 17_459_000 picoseconds. + Weight::from_parts(18_033_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) fn import() -> Weight { // Proof Size summary in bytes: // Measured: `313` // Estimated: `3514` - // Minimum execution time: 14_507_000 picoseconds. - Weight::from_parts(14_935_000, 3514) + // Minimum execution time: 16_728_000 picoseconds. + Weight::from_parts(17_263_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:1 w:1) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: CoreFellowship Member (r:1 w:1) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn approve() -> Weight { // Proof Size summary in bytes: // Measured: `16843` // Estimated: `19894` - // Minimum execution time: 34_050_000 picoseconds. - Weight::from_parts(36_323_000, 19894) + // Minimum execution time: 41_487_000 picoseconds. + Weight::from_parts(43_459_000, 19894) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `CoreFellowship::Member` (r:1 w:0) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:1) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) + /// Storage: CoreFellowship Member (r:1 w:0) + /// Proof: CoreFellowship Member (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: CoreFellowship MemberEvidence (r:1 w:1) + /// Proof: CoreFellowship MemberEvidence (max_values: None, max_size: Some(16429), added: 18904, mode: MaxEncodedLen) fn submit_evidence() -> Weight { // Proof Size summary in bytes: // Measured: `79` // Estimated: `19894` - // Minimum execution time: 24_016_000 picoseconds. - Weight::from_parts(24_607_000, 19894) + // Minimum execution time: 26_033_000 picoseconds. + Weight::from_parts(26_612_000, 19894) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/democracy/src/weights.rs b/substrate/frame/democracy/src/weights.rs index d6097922a82..241f6c3cb38 100644 --- a/substrate/frame/democracy/src/weights.rs +++ b/substrate/frame/democracy/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_democracy` +//! Autogenerated weights for pallet_democracy //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/democracy/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/democracy/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_democracy`. +/// Weight functions needed for pallet_democracy. pub trait WeightInfo { fn propose() -> Weight; fn second() -> Weight; @@ -81,916 +82,904 @@ pub trait WeightInfo { fn clear_referendum_metadata() -> Weight; } -/// Weights for `pallet_democracy` using the Substrate node and recommended hardware. +/// Weights for pallet_democracy using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Democracy::PublicPropCount` (r:1 w:1) - /// Proof: `Democracy::PublicPropCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::PublicProps` (r:1 w:1) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Blacklist` (r:1 w:0) - /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) - /// Storage: `Democracy::DepositOf` (r:0 w:1) - /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicPropCount (r:1 w:1) + /// Proof: Democracy PublicPropCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:0) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:0 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) fn propose() -> Weight { // Proof Size summary in bytes: - // Measured: `4834` + // Measured: `4801` // Estimated: `18187` - // Minimum execution time: 39_930_000 picoseconds. - Weight::from_parts(41_746_000, 18187) + // Minimum execution time: 49_339_000 picoseconds. + Weight::from_parts(50_942_000, 18187) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::DepositOf` (r:1 w:1) - /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) fn second() -> Weight { // Proof Size summary in bytes: - // Measured: `3589` + // Measured: `3556` // Estimated: `6695` - // Minimum execution time: 36_490_000 picoseconds. - Weight::from_parts(37_615_000, 6695) + // Minimum execution time: 43_291_000 picoseconds. + Weight::from_parts(44_856_000, 6695) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `3503` + // Measured: `3470` // Estimated: `7260` - // Minimum execution time: 54_257_000 picoseconds. - Weight::from_parts(55_912_000, 7260) + // Minimum execution time: 61_890_000 picoseconds. + Weight::from_parts(63_626_000, 7260) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `3525` + // Measured: `3492` // Estimated: `7260` - // Minimum execution time: 56_878_000 picoseconds. - Weight::from_parts(58_796_000, 7260) + // Minimum execution time: 67_802_000 picoseconds. + Weight::from_parts(69_132_000, 7260) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Cancellations` (r:1 w:1) - /// Proof: `Democracy::Cancellations` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy Cancellations (r:1 w:1) + /// Proof: Democracy Cancellations (max_values: None, max_size: Some(33), added: 2508, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn emergency_cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `399` + // Measured: `366` // Estimated: `3666` - // Minimum execution time: 22_700_000 picoseconds. - Weight::from_parts(23_539_000, 3666) + // Minimum execution time: 25_757_000 picoseconds. + Weight::from_parts(27_226_000, 3666) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::PublicProps` (r:1 w:1) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::DepositOf` (r:1 w:1) - /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:3 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) - /// Storage: `Democracy::NextExternal` (r:1 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Blacklist` (r:0 w:1) - /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:3 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:0 w:1) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) fn blacklist() -> Weight { // Proof Size summary in bytes: - // Measured: `5943` + // Measured: `5910` // Estimated: `18187` - // Minimum execution time: 95_398_000 picoseconds. - Weight::from_parts(97_261_000, 18187) + // Minimum execution time: 113_060_000 picoseconds. + Weight::from_parts(114_813_000, 18187) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Blacklist` (r:1 w:0) - /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:0) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) fn external_propose() -> Weight { // Proof Size summary in bytes: - // Measured: `3449` + // Measured: `3416` // Estimated: `6703` - // Minimum execution time: 11_745_000 picoseconds. - Weight::from_parts(12_304_000, 6703) + // Minimum execution time: 13_413_000 picoseconds. + Weight::from_parts(13_794_000, 6703) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::NextExternal` (r:0 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:0 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) fn external_propose_majority() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_710_000 picoseconds. - Weight::from_parts(2_918_000, 0) + // Minimum execution time: 3_213_000 picoseconds. + Weight::from_parts(3_429_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::NextExternal` (r:0 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:0 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) fn external_propose_default() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_664_000 picoseconds. - Weight::from_parts(2_776_000, 0) + // Minimum execution time: 3_280_000 picoseconds. + Weight::from_parts(3_389_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumCount` (r:1 w:1) - /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:2) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:0 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:1) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:2) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:0 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) fn fast_track() -> Weight { // Proof Size summary in bytes: - // Measured: `319` + // Measured: `286` // Estimated: `3518` - // Minimum execution time: 22_585_000 picoseconds. - Weight::from_parts(23_689_000, 3518) + // Minimum execution time: 28_142_000 picoseconds. + Weight::from_parts(28_862_000, 3518) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Blacklist` (r:1 w:1) - /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:1) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn veto_external() -> Weight { // Proof Size summary in bytes: - // Measured: `3552` + // Measured: `3519` // Estimated: `6703` - // Minimum execution time: 26_391_000 picoseconds. - Weight::from_parts(27_141_000, 6703) + // Minimum execution time: 32_395_000 picoseconds. + Weight::from_parts(33_617_000, 6703) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::PublicProps` (r:1 w:1) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::DepositOf` (r:1 w:1) - /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn cancel_proposal() -> Weight { // Proof Size summary in bytes: - // Measured: `5854` + // Measured: `5821` // Estimated: `18187` - // Minimum execution time: 77_905_000 picoseconds. - Weight::from_parts(79_628_000, 18187) + // Minimum execution time: 92_255_000 picoseconds. + Weight::from_parts(93_704_000, 18187) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:0 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:0 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) fn cancel_referendum() -> Weight { // Proof Size summary in bytes: - // Measured: `304` + // Measured: `271` // Estimated: `3518` - // Minimum execution time: 15_735_000 picoseconds. - Weight::from_parts(16_525_000, 3518) + // Minimum execution time: 19_623_000 picoseconds. + Weight::from_parts(20_545_000, 3518) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Democracy::LowestUnbaked` (r:1 w:1) - /// Proof: `Democracy::LowestUnbaked` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumCount` (r:1 w:0) - /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:0) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy LowestUnbaked (r:1 w:1) + /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:0) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn on_initialize_base(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `277 + r * (86 ±0)` + // Measured: `244 + r * (86 ±0)` // Estimated: `1489 + r * (2676 ±0)` - // Minimum execution time: 5_274_000 picoseconds. - Weight::from_parts(6_162_399, 1489) - // Standard Error: 6_924 - .saturating_add(Weight::from_parts(3_186_702, 0).saturating_mul(r.into())) + // Minimum execution time: 7_032_000 picoseconds. + Weight::from_parts(7_931_421, 1489) + // Standard Error: 7_395 + .saturating_add(Weight::from_parts(3_236_964, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: `Democracy::LowestUnbaked` (r:1 w:1) - /// Proof: `Democracy::LowestUnbaked` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumCount` (r:1 w:0) - /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::LastTabledWasExternal` (r:1 w:0) - /// Proof: `Democracy::LastTabledWasExternal` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `Democracy::NextExternal` (r:1 w:0) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::PublicProps` (r:1 w:0) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:0) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy LowestUnbaked (r:1 w:1) + /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:0) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy LastTabledWasExternal (r:1 w:0) + /// Proof: Democracy LastTabledWasExternal (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `277 + r * (86 ±0)` + // Measured: `244 + r * (86 ±0)` // Estimated: `18187 + r * (2676 ±0)` - // Minimum execution time: 7_950_000 picoseconds. - Weight::from_parts(7_381_228, 18187) - // Standard Error: 6_650 - .saturating_add(Weight::from_parts(3_198_515, 0).saturating_mul(r.into())) + // Minimum execution time: 10_524_000 picoseconds. + Weight::from_parts(10_369_064, 18187) + // Standard Error: 8_385 + .saturating_add(Weight::from_parts(3_242_334, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: `Democracy::VotingOf` (r:3 w:3) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:99) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Democracy VotingOf (r:3 w:3) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:99) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (108 ±0)` + // Measured: `830 + r * (108 ±0)` // Estimated: `19800 + r * (2676 ±0)` - // Minimum execution time: 40_109_000 picoseconds. - Weight::from_parts(43_164_384, 19800) - // Standard Error: 7_267 - .saturating_add(Weight::from_parts(4_161_526, 0).saturating_mul(r.into())) + // Minimum execution time: 46_106_000 picoseconds. + Weight::from_parts(48_936_654, 19800) + // Standard Error: 8_879 + .saturating_add(Weight::from_parts(4_708_141, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: `Democracy::VotingOf` (r:2 w:2) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:99) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy VotingOf (r:2 w:2) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:99) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `526 + r * (108 ±0)` + // Measured: `493 + r * (108 ±0)` // Estimated: `13530 + r * (2676 ±0)` - // Minimum execution time: 17_466_000 picoseconds. - Weight::from_parts(18_004_456, 13530) - // Standard Error: 6_327 - .saturating_add(Weight::from_parts(4_194_583, 0).saturating_mul(r.into())) + // Minimum execution time: 21_078_000 picoseconds. + Weight::from_parts(22_732_737, 13530) + // Standard Error: 7_969 + .saturating_add(Weight::from_parts(4_626_458, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: `Democracy::PublicProps` (r:0 w:1) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:0 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) fn clear_public_proposals() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_824_000 picoseconds. - Weight::from_parts(2_948_000, 0) + // Minimum execution time: 3_229_000 picoseconds. + Weight::from_parts(3_415_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn unlock_remove(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `596` + // Measured: `563` // Estimated: `7260` - // Minimum execution time: 23_373_000 picoseconds. - Weight::from_parts(34_306_582, 7260) - // Standard Error: 2_849 - .saturating_add(Weight::from_parts(85_027, 0).saturating_mul(r.into())) + // Minimum execution time: 25_735_000 picoseconds. + Weight::from_parts(41_341_468, 7260) + // Standard Error: 3_727 + .saturating_add(Weight::from_parts(94_755, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn unlock_set(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `597 + r * (22 ±0)` + // Measured: `564 + r * (22 ±0)` // Estimated: `7260` - // Minimum execution time: 31_574_000 picoseconds. - Weight::from_parts(33_906_658, 7260) - // Standard Error: 1_514 - .saturating_add(Weight::from_parts(124_471, 0).saturating_mul(r.into())) + // Minimum execution time: 36_233_000 picoseconds. + Weight::from_parts(39_836_017, 7260) + // Standard Error: 1_791 + .saturating_add(Weight::from_parts(132_158, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) /// The range of component `r` is `[1, 100]`. fn remove_vote(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `761 + r * (26 ±0)` + // Measured: `728 + r * (26 ±0)` // Estimated: `7260` - // Minimum execution time: 15_204_000 picoseconds. - Weight::from_parts(18_405_879, 7260) - // Standard Error: 1_851 - .saturating_add(Weight::from_parts(119_018, 0).saturating_mul(r.into())) + // Minimum execution time: 16_081_000 picoseconds. + Weight::from_parts(19_624_101, 7260) + // Standard Error: 1_639 + .saturating_add(Weight::from_parts(133_630, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) /// The range of component `r` is `[1, 100]`. fn remove_other_vote(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `761 + r * (26 ±0)` + // Measured: `728 + r * (26 ±0)` // Estimated: `7260` - // Minimum execution time: 15_120_000 picoseconds. - Weight::from_parts(18_282_222, 7260) - // Standard Error: 1_669 - .saturating_add(Weight::from_parts(127_649, 0).saturating_mul(r.into())) + // Minimum execution time: 15_634_000 picoseconds. + Weight::from_parts(19_573_407, 7260) + // Standard Error: 1_790 + .saturating_add(Weight::from_parts(139_707, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:0) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:0 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn set_external_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `456` + // Measured: `356` // Estimated: `3556` - // Minimum execution time: 17_351_000 picoseconds. - Weight::from_parts(17_964_000, 3556) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 18_344_000 picoseconds. + Weight::from_parts(18_727_000, 3556) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:0) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn clear_external_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `319` + // Measured: `286` // Estimated: `3518` - // Minimum execution time: 13_669_000 picoseconds. - Weight::from_parts(14_410_000, 3518) + // Minimum execution time: 16_497_000 picoseconds. + Weight::from_parts(16_892_000, 3518) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::PublicProps` (r:1 w:0) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:0 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn set_proposal_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `4988` + // Measured: `4888` // Estimated: `18187` - // Minimum execution time: 39_162_000 picoseconds. - Weight::from_parts(40_109_000, 18187) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 39_517_000 picoseconds. + Weight::from_parts(40_632_000, 18187) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::PublicProps` (r:1 w:0) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn clear_proposal_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `4855` + // Measured: `4822` // Estimated: `18187` - // Minimum execution time: 34_141_000 picoseconds. - Weight::from_parts(34_732_000, 18187) + // Minimum execution time: 37_108_000 picoseconds. + Weight::from_parts(37_599_000, 18187) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:0 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn set_referendum_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `144` // Estimated: `3556` - // Minimum execution time: 13_413_000 picoseconds. - Weight::from_parts(14_039_000, 3556) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 13_997_000 picoseconds. + Weight::from_parts(14_298_000, 3556) + .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:0) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn clear_referendum_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `335` + // Measured: `302` // Estimated: `3666` - // Minimum execution time: 16_010_000 picoseconds. - Weight::from_parts(16_474_000, 3666) + // Minimum execution time: 18_122_000 picoseconds. + Weight::from_parts(18_655_000, 3666) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Democracy::PublicPropCount` (r:1 w:1) - /// Proof: `Democracy::PublicPropCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::PublicProps` (r:1 w:1) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Blacklist` (r:1 w:0) - /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) - /// Storage: `Democracy::DepositOf` (r:0 w:1) - /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicPropCount (r:1 w:1) + /// Proof: Democracy PublicPropCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:0) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:0 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) fn propose() -> Weight { // Proof Size summary in bytes: - // Measured: `4834` + // Measured: `4801` // Estimated: `18187` - // Minimum execution time: 39_930_000 picoseconds. - Weight::from_parts(41_746_000, 18187) + // Minimum execution time: 49_339_000 picoseconds. + Weight::from_parts(50_942_000, 18187) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::DepositOf` (r:1 w:1) - /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) fn second() -> Weight { // Proof Size summary in bytes: - // Measured: `3589` + // Measured: `3556` // Estimated: `6695` - // Minimum execution time: 36_490_000 picoseconds. - Weight::from_parts(37_615_000, 6695) + // Minimum execution time: 43_291_000 picoseconds. + Weight::from_parts(44_856_000, 6695) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn vote_new() -> Weight { // Proof Size summary in bytes: - // Measured: `3503` + // Measured: `3470` // Estimated: `7260` - // Minimum execution time: 54_257_000 picoseconds. - Weight::from_parts(55_912_000, 7260) + // Minimum execution time: 61_890_000 picoseconds. + Weight::from_parts(63_626_000, 7260) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn vote_existing() -> Weight { // Proof Size summary in bytes: - // Measured: `3525` + // Measured: `3492` // Estimated: `7260` - // Minimum execution time: 56_878_000 picoseconds. - Weight::from_parts(58_796_000, 7260) + // Minimum execution time: 67_802_000 picoseconds. + Weight::from_parts(69_132_000, 7260) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Cancellations` (r:1 w:1) - /// Proof: `Democracy::Cancellations` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy Cancellations (r:1 w:1) + /// Proof: Democracy Cancellations (max_values: None, max_size: Some(33), added: 2508, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn emergency_cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `399` + // Measured: `366` // Estimated: `3666` - // Minimum execution time: 22_700_000 picoseconds. - Weight::from_parts(23_539_000, 3666) + // Minimum execution time: 25_757_000 picoseconds. + Weight::from_parts(27_226_000, 3666) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::PublicProps` (r:1 w:1) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::DepositOf` (r:1 w:1) - /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:3 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) - /// Storage: `Democracy::NextExternal` (r:1 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Blacklist` (r:0 w:1) - /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:3 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:0 w:1) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) fn blacklist() -> Weight { // Proof Size summary in bytes: - // Measured: `5943` + // Measured: `5910` // Estimated: `18187` - // Minimum execution time: 95_398_000 picoseconds. - Weight::from_parts(97_261_000, 18187) + // Minimum execution time: 113_060_000 picoseconds. + Weight::from_parts(114_813_000, 18187) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Blacklist` (r:1 w:0) - /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:0) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) fn external_propose() -> Weight { // Proof Size summary in bytes: - // Measured: `3449` + // Measured: `3416` // Estimated: `6703` - // Minimum execution time: 11_745_000 picoseconds. - Weight::from_parts(12_304_000, 6703) + // Minimum execution time: 13_413_000 picoseconds. + Weight::from_parts(13_794_000, 6703) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::NextExternal` (r:0 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:0 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) fn external_propose_majority() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_710_000 picoseconds. - Weight::from_parts(2_918_000, 0) + // Minimum execution time: 3_213_000 picoseconds. + Weight::from_parts(3_429_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::NextExternal` (r:0 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:0 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) fn external_propose_default() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_664_000 picoseconds. - Weight::from_parts(2_776_000, 0) + // Minimum execution time: 3_280_000 picoseconds. + Weight::from_parts(3_389_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumCount` (r:1 w:1) - /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:2) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:0 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:1) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:2) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:0 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) fn fast_track() -> Weight { // Proof Size summary in bytes: - // Measured: `319` + // Measured: `286` // Estimated: `3518` - // Minimum execution time: 22_585_000 picoseconds. - Weight::from_parts(23_689_000, 3518) + // Minimum execution time: 28_142_000 picoseconds. + Weight::from_parts(28_862_000, 3518) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:1) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::Blacklist` (r:1 w:1) - /// Proof: `Democracy::Blacklist` (`max_values`: None, `max_size`: Some(3238), added: 5713, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:1) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(3238), added: 5713, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn veto_external() -> Weight { // Proof Size summary in bytes: - // Measured: `3552` + // Measured: `3519` // Estimated: `6703` - // Minimum execution time: 26_391_000 picoseconds. - Weight::from_parts(27_141_000, 6703) + // Minimum execution time: 32_395_000 picoseconds. + Weight::from_parts(33_617_000, 6703) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::PublicProps` (r:1 w:1) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::DepositOf` (r:1 w:1) - /// Proof: `Democracy::DepositOf` (`max_values`: None, `max_size`: Some(3230), added: 5705, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(3230), added: 5705, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn cancel_proposal() -> Weight { // Proof Size summary in bytes: - // Measured: `5854` + // Measured: `5821` // Estimated: `18187` - // Minimum execution time: 77_905_000 picoseconds. - Weight::from_parts(79_628_000, 18187) + // Minimum execution time: 92_255_000 picoseconds. + Weight::from_parts(93_704_000, 18187) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:0 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:0 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) fn cancel_referendum() -> Weight { // Proof Size summary in bytes: - // Measured: `304` + // Measured: `271` // Estimated: `3518` - // Minimum execution time: 15_735_000 picoseconds. - Weight::from_parts(16_525_000, 3518) + // Minimum execution time: 19_623_000 picoseconds. + Weight::from_parts(20_545_000, 3518) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Democracy::LowestUnbaked` (r:1 w:1) - /// Proof: `Democracy::LowestUnbaked` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumCount` (r:1 w:0) - /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:0) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy LowestUnbaked (r:1 w:1) + /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:0) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn on_initialize_base(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `277 + r * (86 ±0)` + // Measured: `244 + r * (86 ±0)` // Estimated: `1489 + r * (2676 ±0)` - // Minimum execution time: 5_274_000 picoseconds. - Weight::from_parts(6_162_399, 1489) - // Standard Error: 6_924 - .saturating_add(Weight::from_parts(3_186_702, 0).saturating_mul(r.into())) + // Minimum execution time: 7_032_000 picoseconds. + Weight::from_parts(7_931_421, 1489) + // Standard Error: 7_395 + .saturating_add(Weight::from_parts(3_236_964, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: `Democracy::LowestUnbaked` (r:1 w:1) - /// Proof: `Democracy::LowestUnbaked` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumCount` (r:1 w:0) - /// Proof: `Democracy::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Democracy::LastTabledWasExternal` (r:1 w:0) - /// Proof: `Democracy::LastTabledWasExternal` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `Democracy::NextExternal` (r:1 w:0) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::PublicProps` (r:1 w:0) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:0) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy LowestUnbaked (r:1 w:1) + /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:0) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy LastTabledWasExternal (r:1 w:0) + /// Proof: Democracy LastTabledWasExternal (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `277 + r * (86 ±0)` + // Measured: `244 + r * (86 ±0)` // Estimated: `18187 + r * (2676 ±0)` - // Minimum execution time: 7_950_000 picoseconds. - Weight::from_parts(7_381_228, 18187) - // Standard Error: 6_650 - .saturating_add(Weight::from_parts(3_198_515, 0).saturating_mul(r.into())) + // Minimum execution time: 10_524_000 picoseconds. + Weight::from_parts(10_369_064, 18187) + // Standard Error: 8_385 + .saturating_add(Weight::from_parts(3_242_334, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: `Democracy::VotingOf` (r:3 w:3) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:99) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Democracy VotingOf (r:3 w:3) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:99) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn delegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `863 + r * (108 ±0)` + // Measured: `830 + r * (108 ±0)` // Estimated: `19800 + r * (2676 ±0)` - // Minimum execution time: 40_109_000 picoseconds. - Weight::from_parts(43_164_384, 19800) - // Standard Error: 7_267 - .saturating_add(Weight::from_parts(4_161_526, 0).saturating_mul(r.into())) + // Minimum execution time: 46_106_000 picoseconds. + Weight::from_parts(48_936_654, 19800) + // Standard Error: 8_879 + .saturating_add(Weight::from_parts(4_708_141, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: `Democracy::VotingOf` (r:2 w:2) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Democracy::ReferendumInfoOf` (r:99 w:99) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) + /// Storage: Democracy VotingOf (r:2 w:2) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:99) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn undelegate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `526 + r * (108 ±0)` + // Measured: `493 + r * (108 ±0)` // Estimated: `13530 + r * (2676 ±0)` - // Minimum execution time: 17_466_000 picoseconds. - Weight::from_parts(18_004_456, 13530) - // Standard Error: 6_327 - .saturating_add(Weight::from_parts(4_194_583, 0).saturating_mul(r.into())) + // Minimum execution time: 21_078_000 picoseconds. + Weight::from_parts(22_732_737, 13530) + // Standard Error: 7_969 + .saturating_add(Weight::from_parts(4_626_458, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) } - /// Storage: `Democracy::PublicProps` (r:0 w:1) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:0 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) fn clear_public_proposals() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_824_000 picoseconds. - Weight::from_parts(2_948_000, 0) + // Minimum execution time: 3_229_000 picoseconds. + Weight::from_parts(3_415_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn unlock_remove(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `596` + // Measured: `563` // Estimated: `7260` - // Minimum execution time: 23_373_000 picoseconds. - Weight::from_parts(34_306_582, 7260) - // Standard Error: 2_849 - .saturating_add(Weight::from_parts(85_027, 0).saturating_mul(r.into())) + // Minimum execution time: 25_735_000 picoseconds. + Weight::from_parts(41_341_468, 7260) + // Standard Error: 3_727 + .saturating_add(Weight::from_parts(94_755, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `r` is `[0, 99]`. fn unlock_set(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `597 + r * (22 ±0)` + // Measured: `564 + r * (22 ±0)` // Estimated: `7260` - // Minimum execution time: 31_574_000 picoseconds. - Weight::from_parts(33_906_658, 7260) - // Standard Error: 1_514 - .saturating_add(Weight::from_parts(124_471, 0).saturating_mul(r.into())) + // Minimum execution time: 36_233_000 picoseconds. + Weight::from_parts(39_836_017, 7260) + // Standard Error: 1_791 + .saturating_add(Weight::from_parts(132_158, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) /// The range of component `r` is `[1, 100]`. fn remove_vote(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `761 + r * (26 ±0)` + // Measured: `728 + r * (26 ±0)` // Estimated: `7260` - // Minimum execution time: 15_204_000 picoseconds. - Weight::from_parts(18_405_879, 7260) - // Standard Error: 1_851 - .saturating_add(Weight::from_parts(119_018, 0).saturating_mul(r.into())) + // Minimum execution time: 16_081_000 picoseconds. + Weight::from_parts(19_624_101, 7260) + // Standard Error: 1_639 + .saturating_add(Weight::from_parts(133_630, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:1) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::VotingOf` (r:1 w:1) - /// Proof: `Democracy::VotingOf` (`max_values`: None, `max_size`: Some(3795), added: 6270, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3795), added: 6270, mode: MaxEncodedLen) /// The range of component `r` is `[1, 100]`. fn remove_other_vote(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `761 + r * (26 ±0)` + // Measured: `728 + r * (26 ±0)` // Estimated: `7260` - // Minimum execution time: 15_120_000 picoseconds. - Weight::from_parts(18_282_222, 7260) - // Standard Error: 1_669 - .saturating_add(Weight::from_parts(127_649, 0).saturating_mul(r.into())) + // Minimum execution time: 15_634_000 picoseconds. + Weight::from_parts(19_573_407, 7260) + // Standard Error: 1_790 + .saturating_add(Weight::from_parts(139_707, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:0) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:0 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn set_external_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `456` + // Measured: `356` // Estimated: `3556` - // Minimum execution time: 17_351_000 picoseconds. - Weight::from_parts(17_964_000, 3556) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Minimum execution time: 18_344_000 picoseconds. + Weight::from_parts(18_727_000, 3556) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::NextExternal` (r:1 w:0) - /// Proof: `Democracy::NextExternal` (`max_values`: Some(1), `max_size`: Some(132), added: 627, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn clear_external_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `319` + // Measured: `286` // Estimated: `3518` - // Minimum execution time: 13_669_000 picoseconds. - Weight::from_parts(14_410_000, 3518) + // Minimum execution time: 16_497_000 picoseconds. + Weight::from_parts(16_892_000, 3518) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::PublicProps` (r:1 w:0) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:0 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn set_proposal_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `4988` + // Measured: `4888` // Estimated: `18187` - // Minimum execution time: 39_162_000 picoseconds. - Weight::from_parts(40_109_000, 18187) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Minimum execution time: 39_517_000 picoseconds. + Weight::from_parts(40_632_000, 18187) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::PublicProps` (r:1 w:0) - /// Proof: `Democracy::PublicProps` (`max_values`: Some(1), `max_size`: Some(16702), added: 17197, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(16702), added: 17197, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn clear_proposal_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `4855` + // Measured: `4822` // Estimated: `18187` - // Minimum execution time: 34_141_000 picoseconds. - Weight::from_parts(34_732_000, 18187) + // Minimum execution time: 37_108_000 picoseconds. + Weight::from_parts(37_599_000, 18187) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:0 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn set_referendum_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `144` // Estimated: `3556` - // Minimum execution time: 13_413_000 picoseconds. - Weight::from_parts(14_039_000, 3556) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Minimum execution time: 13_997_000 picoseconds. + Weight::from_parts(14_298_000, 3556) + .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Democracy::ReferendumInfoOf` (r:1 w:0) - /// Proof: `Democracy::ReferendumInfoOf` (`max_values`: None, `max_size`: Some(201), added: 2676, mode: `MaxEncodedLen`) - /// Storage: `Democracy::MetadataOf` (r:1 w:1) - /// Proof: `Democracy::MetadataOf` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + /// Storage: Democracy ReferendumInfoOf (r:1 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) fn clear_referendum_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `335` + // Measured: `302` // Estimated: `3666` - // Minimum execution time: 16_010_000 picoseconds. - Weight::from_parts(16_474_000, 3666) + // Minimum execution time: 18_122_000 picoseconds. + Weight::from_parts(18_655_000, 3666) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/election-provider-multi-phase/src/mock.rs b/substrate/frame/election-provider-multi-phase/src/mock.rs index 312dc557090..18dcd7061c1 100644 --- a/substrate/frame/election-provider-multi-phase/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/src/mock.rs @@ -441,7 +441,7 @@ where type Extrinsic = Extrinsic; } -pub type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; +pub type Extrinsic = sp_runtime::testing::TestXt; parameter_types! { pub MaxNominations: u32 = ::LIMIT as u32; diff --git a/substrate/frame/election-provider-multi-phase/src/unsigned.rs b/substrate/frame/election-provider-multi-phase/src/unsigned.rs index 94cfd059b6c..94348181334 100644 --- a/substrate/frame/election-provider-multi-phase/src/unsigned.rs +++ b/substrate/frame/election-provider-multi-phase/src/unsigned.rs @@ -1813,7 +1813,7 @@ mod tests { let encoded = pool.read().transactions[0].clone(); let extrinsic: Extrinsic = codec::Decode::decode(&mut &*encoded).unwrap(); - let call = extrinsic.function; + let call = extrinsic.call; assert!(matches!(call, RuntimeCall::MultiPhase(Call::submit_unsigned { .. }))); }) } @@ -1830,7 +1830,7 @@ mod tests { let encoded = pool.read().transactions[0].clone(); let extrinsic = Extrinsic::decode(&mut &*encoded).unwrap(); - let call = match extrinsic.function { + let call = match extrinsic.call { RuntimeCall::MultiPhase(call @ Call::submit_unsigned { .. }) => call, _ => panic!("bad call: unexpected submission"), }; diff --git a/substrate/frame/election-provider-multi-phase/src/weights.rs b/substrate/frame/election-provider-multi-phase/src/weights.rs index ed3e942716e..be578fac8c4 100644 --- a/substrate/frame/election-provider-multi-phase/src/weights.rs +++ b/substrate/frame/election-provider-multi-phase/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_election_provider_multi_phase` +//! Autogenerated weights for pallet_election_provider_multi_phase //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/election-provider-multi-phase/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/election-provider-multi-phase/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_election_provider_multi_phase`. +/// Weight functions needed for pallet_election_provider_multi_phase. pub trait WeightInfo { fn on_initialize_nothing() -> Weight; fn on_initialize_open_signed() -> Weight; @@ -63,171 +64,169 @@ pub trait WeightInfo { fn feasibility_check(v: u32, t: u32, a: u32, d: u32, ) -> Weight; } -/// Weights for `pallet_election_provider_multi_phase` using the Substrate node and recommended hardware. +/// Weights for pallet_election_provider_multi_phase using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::CurrentPlannedSession` (r:1 w:0) - /// Proof: `Staking::CurrentPlannedSession` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::ErasStartSessionIndex` (r:1 w:0) - /// Proof: `Staking::ErasStartSessionIndex` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `Babe::EpochIndex` (r:1 w:0) - /// Proof: `Babe::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Babe::GenesisSlot` (r:1 w:0) - /// Proof: `Babe::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Babe::CurrentSlot` (r:1 w:0) - /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Staking::ForceEra` (r:1 w:0) - /// Proof: `Staking::ForceEra` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CurrentPlannedSession (r:1 w:0) + /// Proof: Staking CurrentPlannedSession (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ErasStartSessionIndex (r:1 w:0) + /// Proof: Staking ErasStartSessionIndex (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: Babe EpochIndex (r:1 w:0) + /// Proof: Babe EpochIndex (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Babe GenesisSlot (r:1 w:0) + /// Proof: Babe GenesisSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Babe CurrentSlot (r:1 w:0) + /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Staking ForceEra (r:1 w:0) + /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) fn on_initialize_nothing() -> Weight { // Proof Size summary in bytes: - // Measured: `1061` + // Measured: `1028` // Estimated: `3481` - // Minimum execution time: 19_340_000 picoseconds. - Weight::from_parts(19_886_000, 3481) + // Minimum execution time: 22_089_000 picoseconds. + Weight::from_parts(22_677_000, 3481) .saturating_add(T::DbWeight::get().reads(8_u64)) } - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) fn on_initialize_open_signed() -> Weight { // Proof Size summary in bytes: // Measured: `148` // Estimated: `1633` - // Minimum execution time: 8_067_000 picoseconds. - Weight::from_parts(8_508_000, 1633) + // Minimum execution time: 11_986_000 picoseconds. + Weight::from_parts(12_445_000, 1633) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) fn on_initialize_open_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `148` // Estimated: `1633` - // Minimum execution time: 8_810_000 picoseconds. - Weight::from_parts(9_061_000, 1633) + // Minimum execution time: 12_988_000 picoseconds. + Weight::from_parts(13_281_000, 1633) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) fn finalize_signed_phase_accept_solution() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 24_339_000 picoseconds. - Weight::from_parts(25_322_000, 3593) + // Minimum execution time: 32_659_000 picoseconds. + Weight::from_parts(33_281_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn finalize_signed_phase_reject_solution() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_635_000 picoseconds. - Weight::from_parts(17_497_000, 3593) + // Minimum execution time: 22_471_000 picoseconds. + Weight::from_parts(23_046_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. fn create_snapshot_internal(v: u32, _t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 170_730_000 picoseconds. - Weight::from_parts(175_009_000, 0) - // Standard Error: 2_010 - .saturating_add(Weight::from_parts(224_974, 0).saturating_mul(v.into())) + // Minimum execution time: 262_360_000 picoseconds. + Weight::from_parts(279_313_000, 0) + // Standard Error: 2_384 + .saturating_add(Weight::from_parts(176_415, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionIndices` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionsMap` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionsMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionIndices (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionNextIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionsMap (max_values: None, max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase QueuedSolution (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn elect_queued(a: u32, d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `371 + a * (768 ±0) + d * (48 ±0)` // Estimated: `3923 + a * (768 ±0) + d * (49 ±0)` - // Minimum execution time: 280_705_000 picoseconds. - Weight::from_parts(303_018_000, 3923) - // Standard Error: 4_633 - .saturating_add(Weight::from_parts(307_274, 0).saturating_mul(a.into())) + // Minimum execution time: 301_283_000 picoseconds. + Weight::from_parts(324_586_000, 3923) + // Standard Error: 4_763 + .saturating_add(Weight::from_parts(279_812, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) .saturating_add(Weight::from_parts(0, 768).saturating_mul(a.into())) .saturating_add(Weight::from_parts(0, 49).saturating_mul(d.into())) } - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionIndices` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionsMap` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionsMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) + /// Proof: TransactionPayment NextFeeMultiplier (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionIndices (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionNextIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionsMap (max_values: None, max_size: None, mode: Measured) fn submit() -> Weight { // Proof Size summary in bytes: // Measured: `927` // Estimated: `2412` - // Minimum execution time: 43_405_000 picoseconds. - Weight::from_parts(45_734_000, 2412) - .saturating_add(T::DbWeight::get().reads(6_u64)) + // Minimum execution time: 52_276_000 picoseconds. + Weight::from_parts(53_846_000, 2412) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::MinimumUntrustedScore` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::MinimumUntrustedScore` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase QueuedSolution (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase MinimumUntrustedScore (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `a` is `[500, 800]`. @@ -236,25 +235,25 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `253 + t * (32 ±0) + v * (553 ±0)` // Estimated: `1738 + t * (32 ±0) + v * (553 ±0)` - // Minimum execution time: 5_059_092_000 picoseconds. - Weight::from_parts(5_263_076_000, 1738) - // Standard Error: 17_317 - .saturating_add(Weight::from_parts(384_051, 0).saturating_mul(v.into())) - // Standard Error: 51_319 - .saturating_add(Weight::from_parts(4_095_128, 0).saturating_mul(a.into())) + // Minimum execution time: 5_448_459_000 picoseconds. + Weight::from_parts(5_525_622_000, 1738) + // Standard Error: 21_478 + .saturating_add(Weight::from_parts(256_345, 0).saturating_mul(v.into())) + // Standard Error: 63_648 + .saturating_add(Weight::from_parts(5_103_224, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(t.into())) .saturating_add(Weight::from_parts(0, 553).saturating_mul(v.into())) } - /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::MinimumUntrustedScore` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::MinimumUntrustedScore` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase MinimumUntrustedScore (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `a` is `[500, 800]`. @@ -263,182 +262,180 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `228 + t * (32 ±0) + v * (553 ±0)` // Estimated: `1713 + t * (32 ±0) + v * (553 ±0)` - // Minimum execution time: 4_426_416_000 picoseconds. - Weight::from_parts(4_466_923_000, 1713) - // Standard Error: 15_415 - .saturating_add(Weight::from_parts(334_047, 0).saturating_mul(v.into())) - // Standard Error: 45_682 - .saturating_add(Weight::from_parts(3_097_318, 0).saturating_mul(a.into())) + // Minimum execution time: 4_724_399_000 picoseconds. + Weight::from_parts(4_886_472_000, 1713) + // Standard Error: 15_220 + .saturating_add(Weight::from_parts(365_569, 0).saturating_mul(v.into())) + // Standard Error: 45_104 + .saturating_add(Weight::from_parts(3_176_675, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(t.into())) .saturating_add(Weight::from_parts(0, 553).saturating_mul(v.into())) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::CurrentPlannedSession` (r:1 w:0) - /// Proof: `Staking::CurrentPlannedSession` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::ErasStartSessionIndex` (r:1 w:0) - /// Proof: `Staking::ErasStartSessionIndex` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) - /// Storage: `Babe::EpochIndex` (r:1 w:0) - /// Proof: `Babe::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Babe::GenesisSlot` (r:1 w:0) - /// Proof: `Babe::GenesisSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Babe::CurrentSlot` (r:1 w:0) - /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Staking::ForceEra` (r:1 w:0) - /// Proof: `Staking::ForceEra` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CurrentPlannedSession (r:1 w:0) + /// Proof: Staking CurrentPlannedSession (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ErasStartSessionIndex (r:1 w:0) + /// Proof: Staking ErasStartSessionIndex (max_values: None, max_size: Some(16), added: 2491, mode: MaxEncodedLen) + /// Storage: Babe EpochIndex (r:1 w:0) + /// Proof: Babe EpochIndex (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Babe GenesisSlot (r:1 w:0) + /// Proof: Babe GenesisSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Babe CurrentSlot (r:1 w:0) + /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Staking ForceEra (r:1 w:0) + /// Proof: Staking ForceEra (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) fn on_initialize_nothing() -> Weight { // Proof Size summary in bytes: - // Measured: `1061` + // Measured: `1028` // Estimated: `3481` - // Minimum execution time: 19_340_000 picoseconds. - Weight::from_parts(19_886_000, 3481) + // Minimum execution time: 22_089_000 picoseconds. + Weight::from_parts(22_677_000, 3481) .saturating_add(RocksDbWeight::get().reads(8_u64)) } - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) fn on_initialize_open_signed() -> Weight { // Proof Size summary in bytes: // Measured: `148` // Estimated: `1633` - // Minimum execution time: 8_067_000 picoseconds. - Weight::from_parts(8_508_000, 1633) + // Minimum execution time: 11_986_000 picoseconds. + Weight::from_parts(12_445_000, 1633) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) fn on_initialize_open_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `148` // Estimated: `1633` - // Minimum execution time: 8_810_000 picoseconds. - Weight::from_parts(9_061_000, 1633) + // Minimum execution time: 12_988_000 picoseconds. + Weight::from_parts(13_281_000, 1633) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) fn finalize_signed_phase_accept_solution() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 24_339_000 picoseconds. - Weight::from_parts(25_322_000, 3593) + // Minimum execution time: 32_659_000 picoseconds. + Weight::from_parts(33_281_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn finalize_signed_phase_reject_solution() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 16_635_000 picoseconds. - Weight::from_parts(17_497_000, 3593) + // Minimum execution time: 22_471_000 picoseconds. + Weight::from_parts(23_046_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. fn create_snapshot_internal(v: u32, _t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 170_730_000 picoseconds. - Weight::from_parts(175_009_000, 0) - // Standard Error: 2_010 - .saturating_add(Weight::from_parts(224_974, 0).saturating_mul(v.into())) + // Minimum execution time: 262_360_000 picoseconds. + Weight::from_parts(279_313_000, 0) + // Standard Error: 2_384 + .saturating_add(Weight::from_parts(176_415, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionIndices` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionsMap` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionsMap` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionIndices (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionNextIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionsMap (max_values: None, max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase QueuedSolution (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn elect_queued(a: u32, d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `371 + a * (768 ±0) + d * (48 ±0)` // Estimated: `3923 + a * (768 ±0) + d * (49 ±0)` - // Minimum execution time: 280_705_000 picoseconds. - Weight::from_parts(303_018_000, 3923) - // Standard Error: 4_633 - .saturating_add(Weight::from_parts(307_274, 0).saturating_mul(a.into())) + // Minimum execution time: 301_283_000 picoseconds. + Weight::from_parts(324_586_000, 3923) + // Standard Error: 4_763 + .saturating_add(Weight::from_parts(279_812, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) .saturating_add(Weight::from_parts(0, 768).saturating_mul(a.into())) .saturating_add(Weight::from_parts(0, 49).saturating_mul(d.into())) } - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionIndices` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionNextIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::SignedSubmissionsMap` (r:0 w:1) - /// Proof: `ElectionProviderMultiPhase::SignedSubmissionsMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) + /// Proof: TransactionPayment NextFeeMultiplier (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionIndices (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionNextIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) + /// Proof Skipped: ElectionProviderMultiPhase SignedSubmissionsMap (max_values: None, max_size: None, mode: Measured) fn submit() -> Weight { // Proof Size summary in bytes: // Measured: `927` // Estimated: `2412` - // Minimum execution time: 43_405_000 picoseconds. - Weight::from_parts(45_734_000, 2412) - .saturating_add(RocksDbWeight::get().reads(6_u64)) + // Minimum execution time: 52_276_000 picoseconds. + Weight::from_parts(53_846_000, 2412) + .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::QueuedSolution` (r:1 w:1) - /// Proof: `ElectionProviderMultiPhase::QueuedSolution` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::SnapshotMetadata` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::SnapshotMetadata` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::MinimumUntrustedScore` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::MinimumUntrustedScore` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase QueuedSolution (r:1 w:1) + /// Proof Skipped: ElectionProviderMultiPhase QueuedSolution (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase SnapshotMetadata (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase MinimumUntrustedScore (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `a` is `[500, 800]`. @@ -447,25 +444,25 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `253 + t * (32 ±0) + v * (553 ±0)` // Estimated: `1738 + t * (32 ±0) + v * (553 ±0)` - // Minimum execution time: 5_059_092_000 picoseconds. - Weight::from_parts(5_263_076_000, 1738) - // Standard Error: 17_317 - .saturating_add(Weight::from_parts(384_051, 0).saturating_mul(v.into())) - // Standard Error: 51_319 - .saturating_add(Weight::from_parts(4_095_128, 0).saturating_mul(a.into())) + // Minimum execution time: 5_448_459_000 picoseconds. + Weight::from_parts(5_525_622_000, 1738) + // Standard Error: 21_478 + .saturating_add(Weight::from_parts(256_345, 0).saturating_mul(v.into())) + // Standard Error: 63_648 + .saturating_add(Weight::from_parts(5_103_224, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(t.into())) .saturating_add(Weight::from_parts(0, 553).saturating_mul(v.into())) } - /// Storage: `ElectionProviderMultiPhase::DesiredTargets` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::DesiredTargets` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Snapshot` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Snapshot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::Round` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::Round` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ElectionProviderMultiPhase::MinimumUntrustedScore` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::MinimumUntrustedScore` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase DesiredTargets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Snapshot (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Snapshot (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase Round (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase Round (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ElectionProviderMultiPhase MinimumUntrustedScore (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase MinimumUntrustedScore (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `a` is `[500, 800]`. @@ -474,12 +471,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `228 + t * (32 ±0) + v * (553 ±0)` // Estimated: `1713 + t * (32 ±0) + v * (553 ±0)` - // Minimum execution time: 4_426_416_000 picoseconds. - Weight::from_parts(4_466_923_000, 1713) - // Standard Error: 15_415 - .saturating_add(Weight::from_parts(334_047, 0).saturating_mul(v.into())) - // Standard Error: 45_682 - .saturating_add(Weight::from_parts(3_097_318, 0).saturating_mul(a.into())) + // Minimum execution time: 4_724_399_000 picoseconds. + Weight::from_parts(4_886_472_000, 1713) + // Standard Error: 15_220 + .saturating_add(Weight::from_parts(365_569, 0).saturating_mul(v.into())) + // Standard Error: 45_104 + .saturating_add(Weight::from_parts(3_176_675, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(t.into())) .saturating_add(Weight::from_parts(0, 553).saturating_mul(v.into())) diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs index 7fade251e6d..882b894bb22 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs @@ -62,7 +62,7 @@ pub const INIT_TIMESTAMP: BlockNumber = 30_000; pub const BLOCK_TIME: BlockNumber = 1000; type Block = frame_system::mocking::MockBlockU32; -type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; +type Extrinsic = testing::TestXt; frame_support::construct_runtime!( pub enum Runtime { @@ -699,7 +699,7 @@ pub fn roll_to_with_ocw(n: BlockNumber, pool: Arc>, delay_solu for encoded in &pool.read().transactions { let extrinsic = Extrinsic::decode(&mut &encoded[..]).unwrap(); - let _ = match extrinsic.function { + let _ = match extrinsic.call { RuntimeCall::ElectionProviderMultiPhase( call @ Call::submit_unsigned { .. }, ) => { diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs index e08412a6e87..308f2cdc1aa 100644 --- a/substrate/frame/elections-phragmen/src/lib.rs +++ b/substrate/frame/elections-phragmen/src/lib.rs @@ -1422,7 +1422,7 @@ mod tests { pub type Block = sp_runtime::generic::Block; pub type UncheckedExtrinsic = - sp_runtime::generic::UncheckedExtrinsic; + sp_runtime::generic::UncheckedExtrinsic; frame_support::construct_runtime!( pub enum Test diff --git a/substrate/frame/elections-phragmen/src/weights.rs b/substrate/frame/elections-phragmen/src/weights.rs index cd67918e85b..b7ed13dae9f 100644 --- a/substrate/frame/elections-phragmen/src/weights.rs +++ b/substrate/frame/elections-phragmen/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_elections_phragmen` +//! Autogenerated weights for pallet_elections_phragmen //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/elections-phragmen/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/elections-phragmen/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_elections_phragmen`. +/// Weight functions needed for pallet_elections_phragmen. pub trait WeightInfo { fn vote_equal(v: u32, ) -> Weight; fn vote_more(v: u32, ) -> Weight; @@ -65,165 +66,165 @@ pub trait WeightInfo { fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight; } -/// Weights for `pallet_elections_phragmen` using the Substrate node and recommended hardware. +/// Weights for pallet_elections_phragmen using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Elections::Candidates` (r:1 w:0) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Voting` (r:1 w:1) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Elections Candidates (r:1 w:0) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Voting (r:1 w:1) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `v` is `[1, 16]`. fn vote_equal(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 29_390_000 picoseconds. - Weight::from_parts(30_525_476, 4764) - // Standard Error: 3_185 - .saturating_add(Weight::from_parts(143_073, 0).saturating_mul(v.into())) + // Minimum execution time: 33_028_000 picoseconds. + Weight::from_parts(34_073_914, 4764) + // Standard Error: 3_474 + .saturating_add(Weight::from_parts(205_252, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: `Elections::Candidates` (r:1 w:0) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Voting` (r:1 w:1) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Elections Candidates (r:1 w:0) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Voting (r:1 w:1) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `v` is `[2, 16]`. fn vote_more(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `371 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 39_765_000 picoseconds. - Weight::from_parts(41_374_102, 4764) - // Standard Error: 4_310 - .saturating_add(Weight::from_parts(153_015, 0).saturating_mul(v.into())) + // Minimum execution time: 45_725_000 picoseconds. + Weight::from_parts(47_169_586, 4764) + // Standard Error: 5_148 + .saturating_add(Weight::from_parts(213_742, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: `Elections::Candidates` (r:1 w:0) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Voting` (r:1 w:1) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Elections Candidates (r:1 w:0) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Voting (r:1 w:1) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `v` is `[2, 16]`. fn vote_less(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 39_647_000 picoseconds. - Weight::from_parts(41_474_523, 4764) - // Standard Error: 5_503 - .saturating_add(Weight::from_parts(149_029, 0).saturating_mul(v.into())) + // Minimum execution time: 45_519_000 picoseconds. + Weight::from_parts(47_339_108, 4764) + // Standard Error: 5_501 + .saturating_add(Weight::from_parts(195_247, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: `Elections::Voting` (r:1 w:1) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Elections Voting (r:1 w:1) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn remove_voter() -> Weight { // Proof Size summary in bytes: // Measured: `925` // Estimated: `4764` - // Minimum execution time: 41_882_000 picoseconds. - Weight::from_parts(42_794_000, 4764) + // Minimum execution time: 50_386_000 picoseconds. + Weight::from_parts(51_378_000, 4764) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Elections::Candidates` (r:1 w:1) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Candidates (r:1 w:1) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `c` is `[1, 64]`. fn submit_candidacy(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1570 + c * (48 ±0)` // Estimated: `3055 + c * (48 ±0)` - // Minimum execution time: 33_719_000 picoseconds. - Weight::from_parts(35_017_073, 3055) - // Standard Error: 1_587 - .saturating_add(Weight::from_parts(121_130, 0).saturating_mul(c.into())) + // Minimum execution time: 38_987_000 picoseconds. + Weight::from_parts(41_302_276, 3055) + // Standard Error: 2_047 + .saturating_add(Weight::from_parts(125_200, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into())) } - /// Storage: `Elections::Candidates` (r:1 w:1) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Candidates (r:1 w:1) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `c` is `[1, 64]`. fn renounce_candidacy_candidate(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `285 + c * (48 ±0)` // Estimated: `1770 + c * (48 ±0)` - // Minimum execution time: 27_263_000 picoseconds. - Weight::from_parts(28_215_666, 1770) - // Standard Error: 1_196 - .saturating_add(Weight::from_parts(86_804, 0).saturating_mul(c.into())) + // Minimum execution time: 33_510_000 picoseconds. + Weight::from_parts(34_947_760, 1770) + // Standard Error: 1_781 + .saturating_add(Weight::from_parts(78_851, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into())) } - /// Storage: `Elections::Members` (r:1 w:1) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:1) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:1 w:1) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:0) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:0 w:1) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Members (r:1 w:1) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:1) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:1 w:1) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:0) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Members (r:0 w:1) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) fn renounce_candidacy_members() -> Weight { // Proof Size summary in bytes: - // Measured: `1933` - // Estimated: `3418` - // Minimum execution time: 41_531_000 picoseconds. - Weight::from_parts(42_937_000, 3418) + // Measured: `1900` + // Estimated: `3385` + // Minimum execution time: 50_603_000 picoseconds. + Weight::from_parts(51_715_000, 3385) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Elections::RunnersUp` (r:1 w:1) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections RunnersUp (r:1 w:1) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) fn renounce_candidacy_runners_up() -> Weight { // Proof Size summary in bytes: // Measured: `880` // Estimated: `2365` - // Minimum execution time: 27_680_000 picoseconds. - Weight::from_parts(28_810_000, 2365) + // Minimum execution time: 33_441_000 picoseconds. + Weight::from_parts(34_812_000, 2365) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Benchmark::Override` (r:0 w:0) - /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) fn remove_member_without_replacement() -> Weight { // Proof Size summary in bytes: // Measured: `0` @@ -231,90 +232,87 @@ impl WeightInfo for SubstrateWeight { // Minimum execution time: 2_000_000_000_000 picoseconds. Weight::from_parts(2_000_000_000_000, 0) } - /// Storage: `Elections::Members` (r:1 w:1) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Elections::RunnersUp` (r:1 w:1) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:1 w:1) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:0) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:0 w:1) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Members (r:1 w:1) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Elections RunnersUp (r:1 w:1) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:1 w:1) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:0) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Members (r:0 w:1) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) fn remove_member_with_replacement() -> Weight { // Proof Size summary in bytes: - // Measured: `1933` + // Measured: `1900` // Estimated: `3593` - // Minimum execution time: 45_333_000 picoseconds. - Weight::from_parts(46_523_000, 3593) + // Minimum execution time: 57_289_000 picoseconds. + Weight::from_parts(58_328_000, 3593) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Elections::Voting` (r:257 w:256) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Candidates` (r:1 w:0) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:256 w:256) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:256 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:256 w:256) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Elections Voting (r:513 w:512) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Candidates (r:1 w:0) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:512 w:512) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:512 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: System Account (r:512 w:512) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `v` is `[256, 512]`. /// The range of component `d` is `[0, 256]`. - fn clean_defunct_voters(v: u32, d: u32, ) -> Weight { + fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + d * (818 ±0) + v * (57 ±0)` - // Estimated: `24906 + d * (3774 ±1) + v * (24 ±0)` - // Minimum execution time: 5_620_000 picoseconds. - Weight::from_parts(5_817_000, 24906) - // Standard Error: 18_357 - .saturating_add(Weight::from_parts(106_164, 0).saturating_mul(v.into())) - // Standard Error: 39_980 - .saturating_add(Weight::from_parts(52_456_337, 0).saturating_mul(d.into())) + // Measured: `1149 + v * (811 ±0)` + // Estimated: `4621 + v * (3774 ±0)` + // Minimum execution time: 18_774_231_000 picoseconds. + Weight::from_parts(18_933_040_000, 4621) + // Standard Error: 301_534 + .saturating_add(Weight::from_parts(44_306_903, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(d.into()))) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(d.into()))) - .saturating_add(Weight::from_parts(0, 3774).saturating_mul(d.into())) - .saturating_add(Weight::from_parts(0, 24).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) + .saturating_add(Weight::from_parts(0, 3774).saturating_mul(v.into())) } - /// Storage: `Elections::Candidates` (r:1 w:1) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:1) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:1) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Voting` (r:513 w:0) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:0) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:44 w:44) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Elections::ElectionRounds` (r:1 w:1) - /// Proof: `Elections::ElectionRounds` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:0 w:1) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:0 w:1) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Candidates (r:1 w:1) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:1) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:1) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Voting (r:513 w:0) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:0) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:44 w:44) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Elections ElectionRounds (r:1 w:1) + /// Proof Skipped: Elections ElectionRounds (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Members (r:0 w:1) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:0 w:1) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `c` is `[1, 64]`. /// The range of component `v` is `[1, 512]`. /// The range of component `e` is `[512, 8192]`. fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + e * (28 ±0) + v * (606 ±0)` - // Estimated: `178920 + c * (2135 ±7) + e * (12 ±0) + v * (2653 ±6)` - // Minimum execution time: 1_082_582_000 picoseconds. - Weight::from_parts(1_084_730_000, 178920) - // Standard Error: 594_096 - .saturating_add(Weight::from_parts(19_096_288, 0).saturating_mul(v.into())) - // Standard Error: 38_118 - .saturating_add(Weight::from_parts(792_945, 0).saturating_mul(e.into())) + // Estimated: `178887 + c * (2135 ±7) + e * (12 ±0) + v * (2653 ±6)` + // Minimum execution time: 1_281_877_000 picoseconds. + Weight::from_parts(1_288_147_000, 178887) + // Standard Error: 528_851 + .saturating_add(Weight::from_parts(17_761_407, 0).saturating_mul(v.into())) + // Standard Error: 33_932 + .saturating_add(Weight::from_parts(698_277, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(21_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) @@ -326,164 +324,164 @@ impl WeightInfo for SubstrateWeight { } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Elections::Candidates` (r:1 w:0) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Voting` (r:1 w:1) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Elections Candidates (r:1 w:0) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Voting (r:1 w:1) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `v` is `[1, 16]`. fn vote_equal(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 29_390_000 picoseconds. - Weight::from_parts(30_525_476, 4764) - // Standard Error: 3_185 - .saturating_add(Weight::from_parts(143_073, 0).saturating_mul(v.into())) + // Minimum execution time: 33_028_000 picoseconds. + Weight::from_parts(34_073_914, 4764) + // Standard Error: 3_474 + .saturating_add(Weight::from_parts(205_252, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: `Elections::Candidates` (r:1 w:0) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Voting` (r:1 w:1) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Elections Candidates (r:1 w:0) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Voting (r:1 w:1) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `v` is `[2, 16]`. fn vote_more(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `371 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 39_765_000 picoseconds. - Weight::from_parts(41_374_102, 4764) - // Standard Error: 4_310 - .saturating_add(Weight::from_parts(153_015, 0).saturating_mul(v.into())) + // Minimum execution time: 45_725_000 picoseconds. + Weight::from_parts(47_169_586, 4764) + // Standard Error: 5_148 + .saturating_add(Weight::from_parts(213_742, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: `Elections::Candidates` (r:1 w:0) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Voting` (r:1 w:1) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Elections Candidates (r:1 w:0) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Voting (r:1 w:1) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) /// The range of component `v` is `[2, 16]`. fn vote_less(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + v * (80 ±0)` // Estimated: `4764 + v * (80 ±0)` - // Minimum execution time: 39_647_000 picoseconds. - Weight::from_parts(41_474_523, 4764) - // Standard Error: 5_503 - .saturating_add(Weight::from_parts(149_029, 0).saturating_mul(v.into())) + // Minimum execution time: 45_519_000 picoseconds. + Weight::from_parts(47_339_108, 4764) + // Standard Error: 5_501 + .saturating_add(Weight::from_parts(195_247, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 80).saturating_mul(v.into())) } - /// Storage: `Elections::Voting` (r:1 w:1) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + /// Storage: Elections Voting (r:1 w:1) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn remove_voter() -> Weight { // Proof Size summary in bytes: // Measured: `925` // Estimated: `4764` - // Minimum execution time: 41_882_000 picoseconds. - Weight::from_parts(42_794_000, 4764) + // Minimum execution time: 50_386_000 picoseconds. + Weight::from_parts(51_378_000, 4764) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Elections::Candidates` (r:1 w:1) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Candidates (r:1 w:1) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `c` is `[1, 64]`. fn submit_candidacy(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1570 + c * (48 ±0)` // Estimated: `3055 + c * (48 ±0)` - // Minimum execution time: 33_719_000 picoseconds. - Weight::from_parts(35_017_073, 3055) - // Standard Error: 1_587 - .saturating_add(Weight::from_parts(121_130, 0).saturating_mul(c.into())) + // Minimum execution time: 38_987_000 picoseconds. + Weight::from_parts(41_302_276, 3055) + // Standard Error: 2_047 + .saturating_add(Weight::from_parts(125_200, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into())) } - /// Storage: `Elections::Candidates` (r:1 w:1) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Candidates (r:1 w:1) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `c` is `[1, 64]`. fn renounce_candidacy_candidate(c: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `285 + c * (48 ±0)` // Estimated: `1770 + c * (48 ±0)` - // Minimum execution time: 27_263_000 picoseconds. - Weight::from_parts(28_215_666, 1770) - // Standard Error: 1_196 - .saturating_add(Weight::from_parts(86_804, 0).saturating_mul(c.into())) + // Minimum execution time: 33_510_000 picoseconds. + Weight::from_parts(34_947_760, 1770) + // Standard Error: 1_781 + .saturating_add(Weight::from_parts(78_851, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 48).saturating_mul(c.into())) } - /// Storage: `Elections::Members` (r:1 w:1) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:1) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:1 w:1) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:0) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:0 w:1) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Members (r:1 w:1) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:1) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:1 w:1) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:0) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Members (r:0 w:1) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) fn renounce_candidacy_members() -> Weight { // Proof Size summary in bytes: - // Measured: `1933` - // Estimated: `3418` - // Minimum execution time: 41_531_000 picoseconds. - Weight::from_parts(42_937_000, 3418) + // Measured: `1900` + // Estimated: `3385` + // Minimum execution time: 50_603_000 picoseconds. + Weight::from_parts(51_715_000, 3385) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Elections::RunnersUp` (r:1 w:1) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections RunnersUp (r:1 w:1) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) fn renounce_candidacy_runners_up() -> Weight { // Proof Size summary in bytes: // Measured: `880` // Estimated: `2365` - // Minimum execution time: 27_680_000 picoseconds. - Weight::from_parts(28_810_000, 2365) + // Minimum execution time: 33_441_000 picoseconds. + Weight::from_parts(34_812_000, 2365) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Benchmark::Override` (r:0 w:0) - /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) fn remove_member_without_replacement() -> Weight { // Proof Size summary in bytes: // Measured: `0` @@ -491,90 +489,87 @@ impl WeightInfo for () { // Minimum execution time: 2_000_000_000_000 picoseconds. Weight::from_parts(2_000_000_000_000, 0) } - /// Storage: `Elections::Members` (r:1 w:1) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Elections::RunnersUp` (r:1 w:1) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:1 w:1) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:0) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:0 w:1) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Members (r:1 w:1) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Elections RunnersUp (r:1 w:1) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:1 w:1) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:0) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Members (r:0 w:1) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) fn remove_member_with_replacement() -> Weight { // Proof Size summary in bytes: - // Measured: `1933` + // Measured: `1900` // Estimated: `3593` - // Minimum execution time: 45_333_000 picoseconds. - Weight::from_parts(46_523_000, 3593) + // Minimum execution time: 57_289_000 picoseconds. + Weight::from_parts(58_328_000, 3593) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Elections::Voting` (r:257 w:256) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:0) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Candidates` (r:1 w:0) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Balances::Locks` (r:256 w:256) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:256 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:256 w:256) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Elections Voting (r:513 w:512) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:0) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Candidates (r:1 w:0) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:512 w:512) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:512 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: System Account (r:512 w:512) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `v` is `[256, 512]`. /// The range of component `d` is `[0, 256]`. - fn clean_defunct_voters(v: u32, d: u32, ) -> Weight { + fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + d * (818 ±0) + v * (57 ±0)` - // Estimated: `24906 + d * (3774 ±1) + v * (24 ±0)` - // Minimum execution time: 5_620_000 picoseconds. - Weight::from_parts(5_817_000, 24906) - // Standard Error: 18_357 - .saturating_add(Weight::from_parts(106_164, 0).saturating_mul(v.into())) - // Standard Error: 39_980 - .saturating_add(Weight::from_parts(52_456_337, 0).saturating_mul(d.into())) + // Measured: `1149 + v * (811 ±0)` + // Estimated: `4621 + v * (3774 ±0)` + // Minimum execution time: 18_774_231_000 picoseconds. + Weight::from_parts(18_933_040_000, 4621) + // Standard Error: 301_534 + .saturating_add(Weight::from_parts(44_306_903, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(d.into()))) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(d.into()))) - .saturating_add(Weight::from_parts(0, 3774).saturating_mul(d.into())) - .saturating_add(Weight::from_parts(0, 24).saturating_mul(v.into())) + .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(v.into()))) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(v.into()))) + .saturating_add(Weight::from_parts(0, 3774).saturating_mul(v.into())) } - /// Storage: `Elections::Candidates` (r:1 w:1) - /// Proof: `Elections::Candidates` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:1) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::RunnersUp` (r:1 w:1) - /// Proof: `Elections::RunnersUp` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Voting` (r:513 w:0) - /// Proof: `Elections::Voting` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Council::Proposals` (r:1 w:0) - /// Proof: `Council::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:44 w:44) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Elections::ElectionRounds` (r:1 w:1) - /// Proof: `Elections::ElectionRounds` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Members` (r:0 w:1) - /// Proof: `Council::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Council::Prime` (r:0 w:1) - /// Proof: `Council::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Elections Candidates (r:1 w:1) + /// Proof Skipped: Elections Candidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:1) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections RunnersUp (r:1 w:1) + /// Proof Skipped: Elections RunnersUp (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Elections Voting (r:513 w:0) + /// Proof Skipped: Elections Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: Council Proposals (r:1 w:0) + /// Proof Skipped: Council Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:44 w:44) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Elections ElectionRounds (r:1 w:1) + /// Proof Skipped: Elections ElectionRounds (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Members (r:0 w:1) + /// Proof Skipped: Council Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Council Prime (r:0 w:1) + /// Proof Skipped: Council Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `c` is `[1, 64]`. /// The range of component `v` is `[1, 512]`. /// The range of component `e` is `[512, 8192]`. fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + e * (28 ±0) + v * (606 ±0)` - // Estimated: `178920 + c * (2135 ±7) + e * (12 ±0) + v * (2653 ±6)` - // Minimum execution time: 1_082_582_000 picoseconds. - Weight::from_parts(1_084_730_000, 178920) - // Standard Error: 594_096 - .saturating_add(Weight::from_parts(19_096_288, 0).saturating_mul(v.into())) - // Standard Error: 38_118 - .saturating_add(Weight::from_parts(792_945, 0).saturating_mul(e.into())) + // Estimated: `178887 + c * (2135 ±7) + e * (12 ±0) + v * (2653 ±6)` + // Minimum execution time: 1_281_877_000 picoseconds. + Weight::from_parts(1_288_147_000, 178887) + // Standard Error: 528_851 + .saturating_add(Weight::from_parts(17_761_407, 0).saturating_mul(v.into())) + // Standard Error: 33_932 + .saturating_add(Weight::from_parts(698_277, 0).saturating_mul(e.into())) .saturating_add(RocksDbWeight::get().reads(21_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) diff --git a/substrate/frame/examples/basic/src/lib.rs b/substrate/frame/examples/basic/src/lib.rs index 94b2f276e00..12cadc969fd 100644 --- a/substrate/frame/examples/basic/src/lib.rs +++ b/substrate/frame/examples/basic/src/lib.rs @@ -46,10 +46,9 @@ //! use the [`Config::WeightInfo`] trait to calculate call weights. This can also be overridden, //! as demonstrated by [`Call::set_dummy`]. //! - A private function that performs a storage update. -//! - A simple transaction extension implementation (see: -//! [`sp_runtime::traits::TransactionExtension`]) which increases the priority of the -//! [`Call::set_dummy`] if it's present and drops any transaction with an encoded length higher -//! than 200 bytes. +//! - A simple signed extension implementation (see: [`sp_runtime::traits::SignedExtension`]) which +//! increases the priority of the [`Call::set_dummy`] if it's present and drops any transaction +//! with an encoded length higher than 200 bytes. // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] @@ -65,12 +64,10 @@ use frame_system::ensure_signed; use log::info; use scale_info::TypeInfo; use sp_runtime::{ - impl_tx_ext_default, - traits::{ - Bounded, DispatchInfoOf, OriginOf, SaturatedConversion, Saturating, TransactionExtension, - TransactionExtensionBase, ValidateResult, + traits::{Bounded, DispatchInfoOf, SaturatedConversion, Saturating, SignedExtension}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, }, - transaction_validity::{InvalidTransaction, ValidTransaction}, }; use sp_std::vec::Vec; @@ -443,8 +440,8 @@ impl Pallet { // Similar to other FRAME pallets, your pallet can also define a signed extension and perform some // checks and [pre/post]processing [before/after] the transaction. A signed extension can be any -// decodable type that implements `TransactionExtension`. See the trait definition for the full list -// of bounds. As a convention, you can follow this approach to create an extension for your pallet: +// decodable type that implements `SignedExtension`. See the trait definition for the full list of +// bounds. As a convention, you can follow this approach to create an extension for your pallet: // - If the extension does not carry any data, then use a tuple struct with just a `marker` // (needed for the compiler to accept `T: Config`) will suffice. // - Otherwise, create a tuple struct which contains the external data. Of course, for the entire @@ -458,18 +455,18 @@ impl Pallet { // // Using the extension, you can add some hooks to the life cycle of each transaction. Note that by // default, an extension is applied to all `Call` functions (i.e. all transactions). the `Call` enum -// variant is given to each function of `TransactionExtension`. Hence, you can filter based on -// pallet or a particular call if needed. +// variant is given to each function of `SignedExtension`. Hence, you can filter based on pallet or +// a particular call if needed. // // Some extra information, such as encoded length, some static dispatch info like weight and the // sender of the transaction (if signed) are also provided. // // The full list of hooks that can be added to a signed extension can be found -// [here](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.TransactionExtension.html). +// [here](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html). // // The signed extensions are aggregated in the runtime file of a substrate chain. All extensions // should be aggregated in a tuple and passed to the `CheckedExtrinsic` and `UncheckedExtrinsic` -// types defined in the runtime. Lookup `pub type TxExtension = (...)` in `node/runtime` and +// types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and // `node-template` for an example of this. /// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the @@ -487,45 +484,52 @@ impl core::fmt::Debug for WatchDummy { } } -impl TransactionExtensionBase for WatchDummy { - const IDENTIFIER: &'static str = "WatchDummy"; - type Implicit = (); -} -impl - TransactionExtension<::RuntimeCall, Context> for WatchDummy +impl SignedExtension for WatchDummy where ::RuntimeCall: IsSubType>, { + const IDENTIFIER: &'static str = "WatchDummy"; + type AccountId = T::AccountId; + type Call = ::RuntimeCall; + type AdditionalSigned = (); type Pre = (); - type Val = (); + + fn additional_signed(&self) -> core::result::Result<(), TransactionValidityError> { + Ok(()) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) + } fn validate( &self, - origin: OriginOf<::RuntimeCall>, - call: &::RuntimeCall, - _info: &DispatchInfoOf<::RuntimeCall>, + _who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult::RuntimeCall> { + ) -> TransactionValidity { // if the transaction is too big, just drop it. if len > 200 { - return Err(InvalidTransaction::ExhaustsResources.into()) + return InvalidTransaction::ExhaustsResources.into() } // check for `set_dummy` - let validity = match call.is_sub_type() { + match call.is_sub_type() { Some(Call::set_dummy { .. }) => { sp_runtime::print("set_dummy was received."); let valid_tx = ValidTransaction { priority: Bounded::max_value(), ..Default::default() }; - valid_tx + Ok(valid_tx) }, - _ => Default::default(), - }; - Ok((validity, (), origin)) + _ => Ok(Default::default()), + } } - impl_tx_ext_default!(::RuntimeCall; Context; prepare); } diff --git a/substrate/frame/examples/basic/src/tests.rs b/substrate/frame/examples/basic/src/tests.rs index e460ad0992f..207e46e428d 100644 --- a/substrate/frame/examples/basic/src/tests.rs +++ b/substrate/frame/examples/basic/src/tests.rs @@ -27,7 +27,7 @@ use sp_core::H256; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{ - traits::{BlakeTwo256, DispatchTransaction, IdentityLookup}, + traits::{BlakeTwo256, IdentityLookup}, BuildStorage, }; // Reexport crate as its pallet name for construct_runtime. @@ -158,16 +158,13 @@ fn signed_ext_watch_dummy_works() { assert_eq!( WatchDummy::(PhantomData) - .validate_only(Some(1).into(), &call, &info, 150) + .validate(&1, &call, &info, 150) .unwrap() - .0 .priority, u64::MAX, ); assert_eq!( - WatchDummy::(PhantomData) - .validate_only(Some(1).into(), &call, &info, 250) - .unwrap_err(), + WatchDummy::(PhantomData).validate(&1, &call, &info, 250), InvalidTransaction::ExhaustsResources.into(), ); }) diff --git a/substrate/frame/examples/offchain-worker/src/tests.rs b/substrate/frame/examples/offchain-worker/src/tests.rs index 81f2a40840b..ea37a2da493 100644 --- a/substrate/frame/examples/offchain-worker/src/tests.rs +++ b/substrate/frame/examples/offchain-worker/src/tests.rs @@ -30,7 +30,7 @@ use sp_core::{ use sp_keystore::{testing::MemoryKeystore, Keystore, KeystoreExt}; use sp_runtime::{ - generic::UncheckedExtrinsic, + testing::TestXt, traits::{BlakeTwo256, Extrinsic as ExtrinsicT, IdentifyAccount, IdentityLookup, Verify}, RuntimeAppPublic, }; @@ -73,7 +73,7 @@ impl frame_system::Config for Test { type MaxConsumers = ConstU32<16>; } -type Extrinsic = UncheckedExtrinsic; +type Extrinsic = TestXt; type AccountId = <::Signer as IdentifyAccount>::AccountId; impl frame_system::offchain::SigningTypes for Test { @@ -99,7 +99,7 @@ where _account: AccountId, nonce: u64, ) -> Option<(RuntimeCall, ::SignaturePayload)> { - Some((call, (nonce, (), ()))) + Some((call, (nonce, ()))) } } @@ -219,8 +219,8 @@ fn should_submit_signed_transaction_on_chain() { let tx = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx = Extrinsic::decode(&mut &*tx).unwrap(); - assert!(matches!(tx.preamble, sp_runtime::generic::Preamble::Signed(0, (), ()))); - assert_eq!(tx.function, RuntimeCall::Example(crate::Call::submit_price { price: 15523 })); + assert_eq!(tx.signature.unwrap().0, 0); + assert_eq!(tx.call, RuntimeCall::Example(crate::Call::submit_price { price: 15523 })); }); } @@ -259,11 +259,11 @@ fn should_submit_unsigned_transaction_on_chain_for_any_account() { // then let tx = pool_state.write().transactions.pop().unwrap(); let tx = Extrinsic::decode(&mut &*tx).unwrap(); - assert!(tx.is_inherent()); + assert_eq!(tx.signature, None); if let RuntimeCall::Example(crate::Call::submit_price_unsigned_with_signed_payload { price_payload: body, signature, - }) = tx.function + }) = tx.call { assert_eq!(body, price_payload); @@ -313,11 +313,11 @@ fn should_submit_unsigned_transaction_on_chain_for_all_accounts() { // then let tx = pool_state.write().transactions.pop().unwrap(); let tx = Extrinsic::decode(&mut &*tx).unwrap(); - assert!(tx.is_inherent()); + assert_eq!(tx.signature, None); if let RuntimeCall::Example(crate::Call::submit_price_unsigned_with_signed_payload { price_payload: body, signature, - }) = tx.function + }) = tx.call { assert_eq!(body, price_payload); @@ -353,9 +353,9 @@ fn should_submit_raw_unsigned_transaction_on_chain() { let tx = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx = Extrinsic::decode(&mut &*tx).unwrap(); - assert!(tx.is_inherent()); + assert_eq!(tx.signature, None); assert_eq!( - tx.function, + tx.call, RuntimeCall::Example(crate::Call::submit_price_unsigned { block_number: 1, price: 15523 diff --git a/substrate/frame/examples/tasks/src/weights.rs b/substrate/frame/examples/tasks/src/weights.rs index c9ddea6f9a8..793af6e9622 100644 --- a/substrate/frame/examples/tasks/src/weights.rs +++ b/substrate/frame/examples/tasks/src/weights.rs @@ -15,31 +15,30 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `tasks_example` +//! Autogenerated weights for `pallet_example_tasks` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-02, STEPS: `20`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `MacBook.local`, CPU: `` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/release/node-template // benchmark // pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=tasks_example -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/examples/tasks/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --chain +// dev +// --pallet +// pallet_example_tasks +// --extrinsic +// * +// --steps +// 20 +// --repeat +// 10 +// --output +// frame/examples/tasks/src/weights.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,42 +48,37 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `tasks_example`. +/// Weight functions needed for pallet_template. pub trait WeightInfo { fn add_number_into_total() -> Weight; } -/// Weights for `tasks_example` using the Substrate node and recommended hardware. +/// Weight functions for `pallet_example_kitchensink`. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `TasksExample::Numbers` (r:1 w:1) - /// Proof: `TasksExample::Numbers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `TasksExample::Total` (r:1 w:1) - /// Proof: `TasksExample::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Kitchensink OtherFoo (r:0 w:1) + /// Proof Skipped: Kitchensink OtherFoo (max_values: Some(1), max_size: None, mode: Measured) fn add_number_into_total() -> Weight { // Proof Size summary in bytes: - // Measured: `149` - // Estimated: `3614` - // Minimum execution time: 5_776_000 picoseconds. - Weight::from_parts(6_178_000, 3614) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } } -// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: `TasksExample::Numbers` (r:1 w:1) - /// Proof: `TasksExample::Numbers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `TasksExample::Total` (r:1 w:1) - /// Proof: `TasksExample::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: Kitchensink OtherFoo (r:0 w:1) + /// Proof Skipped: Kitchensink OtherFoo (max_values: Some(1), max_size: None, mode: Measured) fn add_number_into_total() -> Weight { // Proof Size summary in bytes: - // Measured: `149` - // Estimated: `3614` - // Minimum execution time: 5_776_000 picoseconds. - Weight::from_parts(6_178_000, 3614) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(RocksDbWeight::get().writes(1)) } } diff --git a/substrate/frame/executive/src/tests.rs b/substrate/frame/executive/src/tests.rs index a3f70a9fc3c..70b55f6e855 100644 --- a/substrate/frame/executive/src/tests.rs +++ b/substrate/frame/executive/src/tests.rs @@ -327,42 +327,10 @@ impl frame_system::Config for Runtime { type Balance = u64; -pub struct BalancesWeights; -impl pallet_balances::WeightInfo for BalancesWeights { - fn transfer_allow_death() -> Weight { - Weight::from_parts(25, 0) - } - fn transfer_keep_alive() -> Weight { - Weight::zero() - } - fn force_set_balance_creating() -> Weight { - Weight::zero() - } - fn force_set_balance_killing() -> Weight { - Weight::zero() - } - fn force_transfer() -> Weight { - Weight::zero() - } - fn transfer_all() -> Weight { - Weight::zero() - } - fn force_unreserve() -> Weight { - Weight::zero() - } - fn upgrade_accounts(_u: u32) -> Weight { - Weight::zero() - } - fn force_adjust_total_issuance() -> Weight { - Weight::zero() - } -} - #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for Runtime { type Balance = Balance; type AccountStore = System; - type WeightInfo = BalancesWeights; } parameter_types! { @@ -375,7 +343,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = IdentityFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = (); - type WeightInfo = (); } impl custom::Config for Runtime {} @@ -388,46 +355,19 @@ impl frame_support::traits::Get for RuntimeVersion { } } -#[derive(Clone, Debug, Encode, codec::Decode, PartialEq, Eq, scale_info::TypeInfo)] -pub struct AccountU64(u64); -impl sp_runtime::traits::IdentifyAccount for AccountU64 { - type AccountId = u64; - fn into_account(self) -> u64 { - self.0 - } -} - -impl sp_runtime::traits::Verify for AccountU64 { - type Signer = AccountU64; - fn verify>( - &self, - _msg: L, - _signer: &::AccountId, - ) -> bool { - true - } -} - -impl From for AccountU64 { - fn from(value: u64) -> Self { - Self(value) - } -} - parameter_types! { pub static RuntimeVersionTestValues: sp_version::RuntimeVersion = Default::default(); } -type TxExtension = ( +type SignedExtra = ( frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, ); -type UncheckedXt = - sp_runtime::generic::UncheckedExtrinsic; -type TestBlock = Block; +type TestXt = sp_runtime::testing::TestXt; +type TestBlock = Block; // Will contain `true` when the custom runtime logic was called. const CUSTOM_ON_RUNTIME_KEY: &[u8] = b":custom:on_runtime"; @@ -447,7 +387,7 @@ impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { type Executive = super::Executive< Runtime, - Block, + Block, ChainContext, Runtime, AllPalletsWithSystem, @@ -522,14 +462,17 @@ impl MultiStepMigrator for MockedModeGetter { } } -fn tx_ext(nonce: u64, fee: Balance) -> TxExtension { +fn extra(nonce: u64, fee: Balance) -> SignedExtra { ( frame_system::CheckEra::from(Era::Immortal), frame_system::CheckNonce::from(nonce), frame_system::CheckWeight::new(), pallet_transaction_payment::ChargeTransactionPayment::from(fee), ) - .into() +} + +fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { + Some((who, extra(nonce, fee))) } fn call_transfer(dest: u64, value: u64) -> RuntimeCall { @@ -542,7 +485,7 @@ fn balance_transfer_dispatch_works() { pallet_balances::GenesisConfig:: { balances: vec![(1, 211)] } .assimilate_storage(&mut t) .unwrap(); - let xt = UncheckedXt::new_signed(call_transfer(2, 69), 1, 1.into(), tx_ext(0, 0)); + let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0)); let weight = xt.get_dispatch_info().weight + ::BlockWeights::get() .get(DispatchClass::Normal) @@ -653,7 +596,7 @@ fn block_import_of_bad_extrinsic_root_fails() { fn bad_extrinsic_not_inserted() { let mut t = new_test_ext(1); // bad nonce check! - let xt = UncheckedXt::new_signed(call_transfer(33, 69), 1, 1.into(), tx_ext(30, 0)); + let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0)); t.execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); assert_err!( @@ -667,24 +610,27 @@ fn bad_extrinsic_not_inserted() { #[test] fn block_weight_limit_enforced() { let mut t = new_test_ext(10000); - let transfer_weight = - <::WeightInfo as pallet_balances::WeightInfo>::transfer_allow_death(); + // given: TestXt uses the encoded len as fixed Len: + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let encoded = xt.encode(); + let encoded_len = encoded.len() as u64; // on_initialize weight + base block execution weight let block_weights = ::BlockWeights::get(); let base_block_weight = Weight::from_parts(175, 0) + block_weights.base_block; let limit = block_weights.get(DispatchClass::Normal).max_total.unwrap() - base_block_weight; - let num_to_exhaust_block = limit.ref_time() / (transfer_weight.ref_time() + 5); + let num_to_exhaust_block = limit.ref_time() / (encoded_len + 5); t.execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); // Base block execution weight + `on_initialize` weight from the custom module. assert_eq!(>::block_weight().total(), base_block_weight); for nonce in 0..=num_to_exhaust_block { - let xt = UncheckedXt::new_signed( + let xt = TestXt::new( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - 1, - 1.into(), - tx_ext(nonce.into(), 0), + sign_extra(1, nonce.into(), 0), ); let res = Executive::apply_extrinsic(xt); if nonce != num_to_exhaust_block { @@ -692,8 +638,7 @@ fn block_weight_limit_enforced() { assert_eq!( >::block_weight().total(), //--------------------- on_initialize + block_execution + extrinsic_base weight - Weight::from_parts((transfer_weight.ref_time() + 5) * (nonce + 1), 0) + - base_block_weight, + Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, ); assert_eq!( >::extrinsic_index(), @@ -708,26 +653,19 @@ fn block_weight_limit_enforced() { #[test] fn block_weight_and_size_is_stored_per_tx() { - let xt = UncheckedXt::new_signed( + let xt = TestXt::new( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - 1, - 1.into(), - tx_ext(0, 0), + sign_extra(1, 0, 0), ); - let x1 = UncheckedXt::new_signed( + let x1 = TestXt::new( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - 1, - 1.into(), - tx_ext(1, 0), + sign_extra(1, 1, 0), ); - let x2 = UncheckedXt::new_signed( + let x2 = TestXt::new( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - 1, - 1.into(), - tx_ext(2, 0), + sign_extra(1, 2, 0), ); let len = xt.clone().encode().len() as u32; - let transfer_weight = <::WeightInfo as pallet_balances::WeightInfo>::transfer_allow_death(); let mut t = new_test_ext(1); t.execute_with(|| { // Block execution weight + on_initialize weight from custom module @@ -743,7 +681,8 @@ fn block_weight_and_size_is_stored_per_tx() { assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); - let extrinsic_weight = transfer_weight + + // default weight for `TestXt` == encoded length. + let extrinsic_weight = Weight::from_parts(len as u64, 0) + ::BlockWeights::get() .get(DispatchClass::Normal) .base_extrinsic; @@ -768,8 +707,8 @@ fn block_weight_and_size_is_stored_per_tx() { #[test] fn validate_unsigned() { - let valid = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::allowed_unsigned {})); - let invalid = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::unallowed_unsigned {})); + let valid = TestXt::new(RuntimeCall::Custom(custom::Call::allowed_unsigned {}), None); + let invalid = TestXt::new(RuntimeCall::Custom(custom::Call::unallowed_unsigned {}), None); let mut t = new_test_ext(1); t.execute_with(|| { @@ -806,11 +745,9 @@ fn can_not_pay_for_tx_fee_on_full_lock() { t.execute_with(|| { as fungible::MutateFreeze>::set_freeze(&(), &1, 110) .unwrap(); - let xt = UncheckedXt::new_signed( + let xt = TestXt::new( RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), - 1, - 1.into(), - tx_ext(0, 0), + sign_extra(1, 0, 0), ); Executive::initialize_block(&Header::new_from_number(1)); @@ -935,11 +872,9 @@ fn event_from_runtime_upgrade_is_included() { /// used through the `ExecuteBlock` trait. #[test] fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { - let xt = UncheckedXt::new_signed( + let xt = TestXt::new( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - 1, - 1.into(), - tx_ext(0, 0), + sign_extra(1, 0, 0), ); let header = new_test_ext(1).execute_with(|| { @@ -967,10 +902,7 @@ fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } }); - >>::execute_block(Block::new( - header, - vec![xt], - )); + >>::execute_block(Block::new(header, vec![xt])); assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); @@ -1036,7 +968,7 @@ fn offchain_worker_works_as_expected() { #[test] fn calculating_storage_root_twice_works() { let call = RuntimeCall::Custom(custom::Call::calculate_storage_root {}); - let xt = UncheckedXt::new_signed(call, 1, 1.into(), tx_ext(0, 0)); + let xt = TestXt::new(call, sign_extra(1, 0, 0)); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1055,13 +987,11 @@ fn calculating_storage_root_twice_works() { #[test] #[should_panic(expected = "Invalid inherent position for extrinsic at index 1")] fn invalid_inherent_position_fail() { - let xt1 = UncheckedXt::new_signed( + let xt1 = TestXt::new( RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - 1, - 1.into(), - tx_ext(0, 0), + sign_extra(1, 0, 0), ); - let xt2 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let xt2 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1080,8 +1010,8 @@ fn invalid_inherent_position_fail() { #[test] fn valid_inherents_position_works() { - let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); - let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1101,12 +1031,7 @@ fn valid_inherents_position_works() { #[test] #[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] fn invalid_inherents_fail_block_execution() { - let xt1 = UncheckedXt::new_signed( - RuntimeCall::Custom(custom::Call::inherent {}), - 1, - 1.into(), - tx_ext(0, 0), - ); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), sign_extra(1, 0, 0)); new_test_ext(1).execute_with(|| { Executive::execute_block(Block::new( @@ -1119,7 +1044,7 @@ fn invalid_inherents_fail_block_execution() { // Inherents are created by the runtime and don't need to be validated. #[test] fn inherents_fail_validate_block() { - let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); new_test_ext(1).execute_with(|| { assert_eq!( @@ -1133,7 +1058,7 @@ fn inherents_fail_validate_block() { /// Inherents still work while `initialize_block` forbids transactions. #[test] fn inherents_ok_while_exts_forbidden_works() { - let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); @@ -1153,8 +1078,8 @@ fn inherents_ok_while_exts_forbidden_works() { #[test] #[should_panic = "Only inherents are allowed in this block"] fn transactions_in_only_inherents_block_errors() { - let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); - let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); @@ -1174,8 +1099,8 @@ fn transactions_in_only_inherents_block_errors() { /// Same as above but no error. #[test] fn transactions_in_normal_block_works() { - let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); - let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); @@ -1195,8 +1120,8 @@ fn transactions_in_normal_block_works() { #[test] #[cfg(feature = "try-runtime")] fn try_execute_block_works() { - let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); - let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new_from_number(1)); @@ -1223,8 +1148,8 @@ fn try_execute_block_works() { #[cfg(feature = "try-runtime")] #[should_panic = "Only inherents allowed"] fn try_execute_tx_forbidden_errors() { - let xt1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); - let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1251,9 +1176,9 @@ fn try_execute_tx_forbidden_errors() { /// Check that `ensure_inherents_are_first` reports the correct indices. #[test] fn ensure_inherents_are_first_works() { - let in1 = UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})); - let in2 = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::inherent {})); - let xt2 = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); + let in1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None); + let in2 = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); // Mocked empty header: let header = new_test_ext(1).execute_with(|| { @@ -1331,20 +1256,18 @@ fn callbacks_in_block_execution_works_inner(mbms_active: bool) { for i in 0..n_in { let xt = if i % 2 == 0 { - UncheckedXt::new_bare(RuntimeCall::Custom(custom::Call::inherent {})) + TestXt::new(RuntimeCall::Custom(custom::Call::inherent {}), None) } else { - UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::optional_inherent {})) + TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None) }; Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); extrinsics.push(xt); } for t in 0..n_tx { - let xt = UncheckedXt::new_signed( + let xt = TestXt::new( RuntimeCall::Custom2(custom2::Call::some_call {}), - 1, - 1.into(), - tx_ext(t as u64, 0), + sign_extra(1, t as u64, 0), ); // Extrinsics can be applied even when MBMs are active. Only the `execute_block` // will reject it. @@ -1384,13 +1307,8 @@ fn callbacks_in_block_execution_works_inner(mbms_active: bool) { #[test] fn post_inherent_called_after_all_inherents() { - let in1 = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::inherent {})); - let xt1 = UncheckedXt::new_signed( - RuntimeCall::Custom2(custom2::Call::some_call {}), - 1, - 1.into(), - tx_ext(0, 0), - ); + let in1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); + let xt1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::some_call {}), sign_extra(1, 0, 0)); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1424,13 +1342,8 @@ fn post_inherent_called_after_all_inherents() { /// Regression test for AppSec finding #40. #[test] fn post_inherent_called_after_all_optional_inherents() { - let in1 = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::optional_inherent {})); - let xt1 = UncheckedXt::new_signed( - RuntimeCall::Custom2(custom2::Call::some_call {}), - 1, - 1.into(), - tx_ext(0, 0), - ); + let in1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None); + let xt1 = TestXt::new(RuntimeCall::Custom2(custom2::Call::some_call {}), sign_extra(1, 0, 0)); let header = new_test_ext(1).execute_with(|| { // Let's build some fake block. @@ -1463,14 +1376,14 @@ fn post_inherent_called_after_all_optional_inherents() { #[test] fn is_inherent_works() { - let ext = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::inherent {})); + let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::inherent {}), None); assert!(Runtime::is_inherent(&ext)); - let ext = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::optional_inherent {})); + let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::optional_inherent {}), None); assert!(Runtime::is_inherent(&ext)); - let ext = UncheckedXt::new_signed(call_transfer(33, 0), 1, 1.into(), tx_ext(0, 0)); + let ext = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); assert!(!Runtime::is_inherent(&ext)); - let ext = UncheckedXt::new_bare(RuntimeCall::Custom2(custom2::Call::allowed_unsigned {})); + let ext = TestXt::new(RuntimeCall::Custom2(custom2::Call::allowed_unsigned {}), None); assert!(!Runtime::is_inherent(&ext), "Unsigned ext are not automatically inherents"); } diff --git a/substrate/frame/fast-unstake/src/weights.rs b/substrate/frame/fast-unstake/src/weights.rs index d783ba921bf..9c25a409f74 100644 --- a/substrate/frame/fast-unstake/src/weights.rs +++ b/substrate/frame/fast-unstake/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_fast_unstake` +//! Autogenerated weights for pallet_fast_unstake //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/fast-unstake/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/fast-unstake/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_fast_unstake`. +/// Weight functions needed for pallet_fast_unstake. pub trait WeightInfo { fn on_idle_unstake(b: u32, ) -> Weight; fn on_idle_check(v: u32, b: u32, ) -> Weight; @@ -58,305 +59,301 @@ pub trait WeightInfo { fn control() -> Weight; } -/// Weights for `pallet_fast_unstake` using the Substrate node and recommended hardware. +/// Weights for pallet_fast_unstake using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::ValidatorCount` (r:1 w:0) - /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Head` (r:1 w:1) - /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::CounterForQueue` (r:1 w:0) - /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::SlashingSpans` (r:64 w:0) - /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Staking::Bonded` (r:64 w:64) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:64 w:64) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:64 w:64) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:64 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:64 w:64) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Staking::Validators` (r:64 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `Staking::Nominators` (r:64 w:0) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `Staking::Payee` (r:0 w:64) - /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ValidatorCount (r:1 w:0) + /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: FastUnstake Head (r:1 w:1) + /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) + /// Storage: FastUnstake CounterForQueue (r:1 w:0) + /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking SlashingSpans (r:64 w:0) + /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking Bonded (r:64 w:64) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:64 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:64 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: System Account (r:64 w:64) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:64 w:64) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:64 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:0 w:64) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:64) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) /// The range of component `b` is `[1, 64]`. fn on_idle_unstake(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1475 + b * (452 ±0)` + // Measured: `1378 + b * (343 ±0)` // Estimated: `7253 + b * (3774 ±0)` - // Minimum execution time: 89_005_000 picoseconds. - Weight::from_parts(50_257_055, 7253) - // Standard Error: 68_836 - .saturating_add(Weight::from_parts(57_329_950, 0).saturating_mul(b.into())) + // Minimum execution time: 92_847_000 picoseconds. + Weight::from_parts(42_300_813, 7253) + // Standard Error: 40_514 + .saturating_add(Weight::from_parts(58_412_402, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().reads((8_u64).saturating_mul(b.into()))) + .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 3774).saturating_mul(b.into())) } - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::ValidatorCount` (r:1 w:0) - /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Head` (r:1 w:1) - /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::CounterForQueue` (r:1 w:0) - /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::ErasStakers` (r:1 w:0) - /// Proof: `Staking::ErasStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Staking::ErasStakersPaged` (r:257 w:0) - /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ValidatorCount (r:1 w:0) + /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: FastUnstake Head (r:1 w:1) + /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) + /// Storage: FastUnstake CounterForQueue (r:1 w:0) + /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ErasStakers (r:257 w:0) + /// Proof Skipped: Staking ErasStakers (max_values: None, max_size: None, mode: Measured) /// The range of component `v` is `[1, 256]`. /// The range of component `b` is `[1, 64]`. fn on_idle_check(v: u32, b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1879 + b * (55 ±0) + v * (10055 ±0)` - // Estimated: `7253 + b * (56 ±0) + v * (12531 ±0)` - // Minimum execution time: 1_737_131_000 picoseconds. - Weight::from_parts(1_746_770_000, 7253) - // Standard Error: 13_401_143 - .saturating_add(Weight::from_parts(426_946_450, 0).saturating_mul(v.into())) - // Standard Error: 53_619_501 - .saturating_add(Weight::from_parts(1_664_681_508, 0).saturating_mul(b.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `1546 + b * (48 ±0) + v * (10037 ±0)` + // Estimated: `7253 + b * (49 ±0) + v * (12513 ±0)` + // Minimum execution time: 1_685_784_000 picoseconds. + Weight::from_parts(1_693_370_000, 7253) + // Standard Error: 13_295_842 + .saturating_add(Weight::from_parts(425_349_148, 0).saturating_mul(v.into())) + // Standard Error: 53_198_180 + .saturating_add(Weight::from_parts(1_673_328_444, 0).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 56).saturating_mul(b.into())) - .saturating_add(Weight::from_parts(0, 12531).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(0, 49).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(0, 12513).saturating_mul(v.into())) } - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:1 w:1) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Queue` (r:1 w:1) - /// Proof: `FastUnstake::Queue` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Head` (r:1 w:0) - /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Validators` (r:1 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `Staking::Nominators` (r:1 w:1) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `Staking::CounterForNominators` (r:1 w:1) - /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:1 w:1) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::CounterForQueue` (r:1 w:1) - /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: FastUnstake Queue (r:1 w:1) + /// Proof: FastUnstake Queue (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) + /// Storage: FastUnstake Head (r:1 w:0) + /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:1 w:1) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: FastUnstake CounterForQueue (r:1 w:1) + /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn register_fast_unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `1955` + // Measured: `1964` // Estimated: `7253` - // Minimum execution time: 112_632_000 picoseconds. - Weight::from_parts(117_267_000, 7253) + // Minimum execution time: 125_512_000 picoseconds. + Weight::from_parts(129_562_000, 7253) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Queue` (r:1 w:1) - /// Proof: `FastUnstake::Queue` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Head` (r:1 w:0) - /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::CounterForQueue` (r:1 w:1) - /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: FastUnstake Queue (r:1 w:1) + /// Proof: FastUnstake Queue (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) + /// Storage: FastUnstake Head (r:1 w:0) + /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) + /// Storage: FastUnstake CounterForQueue (r:1 w:1) + /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn deregister() -> Weight { // Proof Size summary in bytes: - // Measured: `1251` + // Measured: `1223` // Estimated: `7253` - // Minimum execution time: 39_253_000 picoseconds. - Weight::from_parts(40_053_000, 7253) + // Minimum execution time: 43_943_000 picoseconds. + Weight::from_parts(45_842_000, 7253) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:0 w:1) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn control() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_386_000 picoseconds. - Weight::from_parts(2_508_000, 0) + // Minimum execution time: 2_677_000 picoseconds. + Weight::from_parts(2_849_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::ValidatorCount` (r:1 w:0) - /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Head` (r:1 w:1) - /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::CounterForQueue` (r:1 w:0) - /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::SlashingSpans` (r:64 w:0) - /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Staking::Bonded` (r:64 w:64) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:64 w:64) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:64 w:64) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:64 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:64 w:64) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Staking::Validators` (r:64 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `Staking::Nominators` (r:64 w:0) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `Staking::Payee` (r:0 w:64) - /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ValidatorCount (r:1 w:0) + /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: FastUnstake Head (r:1 w:1) + /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) + /// Storage: FastUnstake CounterForQueue (r:1 w:0) + /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking SlashingSpans (r:64 w:0) + /// Proof Skipped: Staking SlashingSpans (max_values: None, max_size: None, mode: Measured) + /// Storage: Staking Bonded (r:64 w:64) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:64 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:64 w:0) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: System Account (r:64 w:64) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:64 w:64) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:64 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:0 w:64) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Staking Payee (r:0 w:64) + /// Proof: Staking Payee (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) /// The range of component `b` is `[1, 64]`. fn on_idle_unstake(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1475 + b * (452 ±0)` + // Measured: `1378 + b * (343 ±0)` // Estimated: `7253 + b * (3774 ±0)` - // Minimum execution time: 89_005_000 picoseconds. - Weight::from_parts(50_257_055, 7253) - // Standard Error: 68_836 - .saturating_add(Weight::from_parts(57_329_950, 0).saturating_mul(b.into())) + // Minimum execution time: 92_847_000 picoseconds. + Weight::from_parts(42_300_813, 7253) + // Standard Error: 40_514 + .saturating_add(Weight::from_parts(58_412_402, 0).saturating_mul(b.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().reads((8_u64).saturating_mul(b.into()))) + .saturating_add(RocksDbWeight::get().reads((7_u64).saturating_mul(b.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((5_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 3774).saturating_mul(b.into())) } - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::ValidatorCount` (r:1 w:0) - /// Proof: `Staking::ValidatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Head` (r:1 w:1) - /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::CounterForQueue` (r:1 w:0) - /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `ElectionProviderMultiPhase::CurrentPhase` (r:1 w:0) - /// Proof: `ElectionProviderMultiPhase::CurrentPhase` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::ErasStakers` (r:1 w:0) - /// Proof: `Staking::ErasStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Staking::ErasStakersPaged` (r:257 w:0) - /// Proof: `Staking::ErasStakersPaged` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ValidatorCount (r:1 w:0) + /// Proof: Staking ValidatorCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: FastUnstake Head (r:1 w:1) + /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) + /// Storage: FastUnstake CounterForQueue (r:1 w:0) + /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) + /// Proof Skipped: ElectionProviderMultiPhase CurrentPhase (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking ErasStakers (r:257 w:0) + /// Proof Skipped: Staking ErasStakers (max_values: None, max_size: None, mode: Measured) /// The range of component `v` is `[1, 256]`. /// The range of component `b` is `[1, 64]`. fn on_idle_check(v: u32, b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1879 + b * (55 ±0) + v * (10055 ±0)` - // Estimated: `7253 + b * (56 ±0) + v * (12531 ±0)` - // Minimum execution time: 1_737_131_000 picoseconds. - Weight::from_parts(1_746_770_000, 7253) - // Standard Error: 13_401_143 - .saturating_add(Weight::from_parts(426_946_450, 0).saturating_mul(v.into())) - // Standard Error: 53_619_501 - .saturating_add(Weight::from_parts(1_664_681_508, 0).saturating_mul(b.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `1546 + b * (48 ±0) + v * (10037 ±0)` + // Estimated: `7253 + b * (49 ±0) + v * (12513 ±0)` + // Minimum execution time: 1_685_784_000 picoseconds. + Weight::from_parts(1_693_370_000, 7253) + // Standard Error: 13_295_842 + .saturating_add(Weight::from_parts(425_349_148, 0).saturating_mul(v.into())) + // Standard Error: 53_198_180 + .saturating_add(Weight::from_parts(1_673_328_444, 0).saturating_mul(b.into())) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 56).saturating_mul(b.into())) - .saturating_add(Weight::from_parts(0, 12531).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(0, 49).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(0, 12513).saturating_mul(v.into())) } - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:1 w:1) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Queue` (r:1 w:1) - /// Proof: `FastUnstake::Queue` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Head` (r:1 w:0) - /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Validators` (r:1 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `Staking::Nominators` (r:1 w:1) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `Staking::CounterForNominators` (r:1 w:1) - /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:1 w:1) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::CounterForQueue` (r:1 w:1) - /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:1) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: FastUnstake Queue (r:1 w:1) + /// Proof: FastUnstake Queue (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) + /// Storage: FastUnstake Head (r:1 w:0) + /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) + /// Storage: Staking Bonded (r:1 w:0) + /// Proof: Staking Bonded (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: Staking Validators (r:1 w:0) + /// Proof: Staking Validators (max_values: None, max_size: Some(45), added: 2520, mode: MaxEncodedLen) + /// Storage: Staking Nominators (r:1 w:1) + /// Proof: Staking Nominators (max_values: None, max_size: Some(558), added: 3033, mode: MaxEncodedLen) + /// Storage: Staking CounterForNominators (r:1 w:1) + /// Proof: Staking CounterForNominators (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: VoterList ListNodes (r:1 w:1) + /// Proof: VoterList ListNodes (max_values: None, max_size: Some(154), added: 2629, mode: MaxEncodedLen) + /// Storage: VoterList ListBags (r:1 w:1) + /// Proof: VoterList ListBags (max_values: None, max_size: Some(82), added: 2557, mode: MaxEncodedLen) + /// Storage: VoterList CounterForListNodes (r:1 w:1) + /// Proof: VoterList CounterForListNodes (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking CurrentEra (r:1 w:0) + /// Proof: Staking CurrentEra (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: FastUnstake CounterForQueue (r:1 w:1) + /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn register_fast_unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `1955` + // Measured: `1964` // Estimated: `7253` - // Minimum execution time: 112_632_000 picoseconds. - Weight::from_parts(117_267_000, 7253) + // Minimum execution time: 125_512_000 picoseconds. + Weight::from_parts(129_562_000, 7253) .saturating_add(RocksDbWeight::get().reads(15_u64)) .saturating_add(RocksDbWeight::get().writes(9_u64)) } - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:1 w:0) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Queue` (r:1 w:1) - /// Proof: `FastUnstake::Queue` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::Head` (r:1 w:0) - /// Proof: `FastUnstake::Head` (`max_values`: Some(1), `max_size`: Some(5768), added: 6263, mode: `MaxEncodedLen`) - /// Storage: `FastUnstake::CounterForQueue` (r:1 w:1) - /// Proof: `FastUnstake::CounterForQueue` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: FastUnstake Queue (r:1 w:1) + /// Proof: FastUnstake Queue (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) + /// Storage: FastUnstake Head (r:1 w:0) + /// Proof: FastUnstake Head (max_values: Some(1), max_size: Some(5768), added: 6263, mode: MaxEncodedLen) + /// Storage: FastUnstake CounterForQueue (r:1 w:1) + /// Proof: FastUnstake CounterForQueue (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn deregister() -> Weight { // Proof Size summary in bytes: - // Measured: `1251` + // Measured: `1223` // Estimated: `7253` - // Minimum execution time: 39_253_000 picoseconds. - Weight::from_parts(40_053_000, 7253) + // Minimum execution time: 43_943_000 picoseconds. + Weight::from_parts(45_842_000, 7253) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `FastUnstake::ErasToCheckPerBlock` (r:0 w:1) - /// Proof: `FastUnstake::ErasToCheckPerBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) + /// Proof: FastUnstake ErasToCheckPerBlock (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn control() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_386_000 picoseconds. - Weight::from_parts(2_508_000, 0) + // Minimum execution time: 2_677_000 picoseconds. + Weight::from_parts(2_849_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/glutton/src/weights.rs b/substrate/frame/glutton/src/weights.rs index b2e28dc488a..cbc0fb022f5 100644 --- a/substrate/frame/glutton/src/weights.rs +++ b/substrate/frame/glutton/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_glutton` +//! Autogenerated weights for pallet_glutton //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/glutton/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/glutton/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_glutton`. +/// Weight functions needed for pallet_glutton. pub trait WeightInfo { fn initialize_pallet_grow(n: u32, ) -> Weight; fn initialize_pallet_shrink(n: u32, ) -> Weight; @@ -62,39 +63,39 @@ pub trait WeightInfo { fn set_storage() -> Weight; } -/// Weights for `pallet_glutton` using the Substrate node and recommended hardware. +/// Weights for pallet_glutton using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Glutton::TrashDataCount` (r:1 w:1) - /// Proof: `Glutton::TrashDataCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Glutton::TrashData` (r:0 w:1000) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton TrashDataCount (r:1 w:1) + /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:0 w:1000) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) /// The range of component `n` is `[0, 1000]`. fn initialize_pallet_grow(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1489` - // Minimum execution time: 8_443_000 picoseconds. - Weight::from_parts(103_698_651, 1489) - // Standard Error: 21_777 - .saturating_add(Weight::from_parts(9_529_476, 0).saturating_mul(n.into())) + // Minimum execution time: 11_488_000 picoseconds. + Weight::from_parts(93_073_710, 1489) + // Standard Error: 22_390 + .saturating_add(Weight::from_parts(9_572_012, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) } - /// Storage: `Glutton::TrashDataCount` (r:1 w:1) - /// Proof: `Glutton::TrashDataCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Glutton::TrashData` (r:0 w:1000) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton TrashDataCount (r:1 w:1) + /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:0 w:1000) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) /// The range of component `n` is `[0, 1000]`. fn initialize_pallet_shrink(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `119` // Estimated: `1489` - // Minimum execution time: 8_343_000 picoseconds. - Weight::from_parts(304_498, 1489) - // Standard Error: 1_568 - .saturating_add(Weight::from_parts(1_146_553, 0).saturating_mul(n.into())) + // Minimum execution time: 11_378_000 picoseconds. + Weight::from_parts(5_591_508, 1489) + // Standard Error: 1_592 + .saturating_add(Weight::from_parts(1_163_758, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -104,119 +105,119 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 656_000 picoseconds. - Weight::from_parts(1_875_128, 0) - // Standard Error: 8 - .saturating_add(Weight::from_parts(103_381, 0).saturating_mul(i.into())) + // Minimum execution time: 669_000 picoseconds. + Weight::from_parts(990_745, 0) + // Standard Error: 10 + .saturating_add(Weight::from_parts(105_224, 0).saturating_mul(i.into())) } - /// Storage: `Glutton::TrashData` (r:5000 w:0) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton TrashData (r:5000 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) /// The range of component `i` is `[0, 5000]`. fn waste_proof_size_some(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `119114 + i * (1022 ±0)` // Estimated: `990 + i * (3016 ±0)` - // Minimum execution time: 454_000 picoseconds. - Weight::from_parts(521_000, 990) - // Standard Error: 1_940 - .saturating_add(Weight::from_parts(5_729_831, 0).saturating_mul(i.into())) + // Minimum execution time: 435_000 picoseconds. + Weight::from_parts(66_547_542, 990) + // Standard Error: 4_557 + .saturating_add(Weight::from_parts(5_851_324, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3016).saturating_mul(i.into())) } - /// Storage: `Glutton::Storage` (r:1 w:0) - /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::Compute` (r:1 w:0) - /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::TrashData` (r:1737 w:0) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:1737 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) fn on_idle_high_proof_waste() -> Weight { // Proof Size summary in bytes: // Measured: `1900497` // Estimated: `5239782` - // Minimum execution time: 55_403_909_000 picoseconds. - Weight::from_parts(55_472_412_000, 5239782) + // Minimum execution time: 67_699_845_000 picoseconds. + Weight::from_parts(67_893_204_000, 5239782) .saturating_add(T::DbWeight::get().reads(1739_u64)) } - /// Storage: `Glutton::Storage` (r:1 w:0) - /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::Compute` (r:1 w:0) - /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::TrashData` (r:5 w:0) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:5 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) fn on_idle_low_proof_waste() -> Weight { // Proof Size summary in bytes: // Measured: `9547` // Estimated: `16070` - // Minimum execution time: 97_959_007_000 picoseconds. - Weight::from_parts(98_030_476_000, 16070) + // Minimum execution time: 122_297_527_000 picoseconds. + Weight::from_parts(122_394_818_000, 16070) .saturating_add(T::DbWeight::get().reads(7_u64)) } - /// Storage: `Glutton::Storage` (r:1 w:0) - /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::Compute` (r:1 w:0) - /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn empty_on_idle() -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1493` - // Minimum execution time: 5_011_000 picoseconds. - Weight::from_parts(5_183_000, 1493) + // Minimum execution time: 5_882_000 picoseconds. + Weight::from_parts(6_138_000, 1493) .saturating_add(T::DbWeight::get().reads(2_u64)) } - /// Storage: `Glutton::Compute` (r:0 w:1) - /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Glutton Compute (r:0 w:1) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn set_compute() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_591_000 picoseconds. - Weight::from_parts(5_970_000, 0) + // Minimum execution time: 7_830_000 picoseconds. + Weight::from_parts(8_366_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Glutton::Storage` (r:0 w:1) - /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Glutton Storage (r:0 w:1) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn set_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_689_000 picoseconds. - Weight::from_parts(6_038_000, 0) + // Minimum execution time: 7_933_000 picoseconds. + Weight::from_parts(8_213_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Glutton::TrashDataCount` (r:1 w:1) - /// Proof: `Glutton::TrashDataCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Glutton::TrashData` (r:0 w:1000) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton TrashDataCount (r:1 w:1) + /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:0 w:1000) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) /// The range of component `n` is `[0, 1000]`. fn initialize_pallet_grow(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1489` - // Minimum execution time: 8_443_000 picoseconds. - Weight::from_parts(103_698_651, 1489) - // Standard Error: 21_777 - .saturating_add(Weight::from_parts(9_529_476, 0).saturating_mul(n.into())) + // Minimum execution time: 11_488_000 picoseconds. + Weight::from_parts(93_073_710, 1489) + // Standard Error: 22_390 + .saturating_add(Weight::from_parts(9_572_012, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) } - /// Storage: `Glutton::TrashDataCount` (r:1 w:1) - /// Proof: `Glutton::TrashDataCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Glutton::TrashData` (r:0 w:1000) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton TrashDataCount (r:1 w:1) + /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:0 w:1000) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) /// The range of component `n` is `[0, 1000]`. fn initialize_pallet_shrink(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `119` // Estimated: `1489` - // Minimum execution time: 8_343_000 picoseconds. - Weight::from_parts(304_498, 1489) - // Standard Error: 1_568 - .saturating_add(Weight::from_parts(1_146_553, 0).saturating_mul(n.into())) + // Minimum execution time: 11_378_000 picoseconds. + Weight::from_parts(5_591_508, 1489) + // Standard Error: 1_592 + .saturating_add(Weight::from_parts(1_163_758, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -226,83 +227,83 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 656_000 picoseconds. - Weight::from_parts(1_875_128, 0) - // Standard Error: 8 - .saturating_add(Weight::from_parts(103_381, 0).saturating_mul(i.into())) + // Minimum execution time: 669_000 picoseconds. + Weight::from_parts(990_745, 0) + // Standard Error: 10 + .saturating_add(Weight::from_parts(105_224, 0).saturating_mul(i.into())) } - /// Storage: `Glutton::TrashData` (r:5000 w:0) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton TrashData (r:5000 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) /// The range of component `i` is `[0, 5000]`. fn waste_proof_size_some(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `119114 + i * (1022 ±0)` // Estimated: `990 + i * (3016 ±0)` - // Minimum execution time: 454_000 picoseconds. - Weight::from_parts(521_000, 990) - // Standard Error: 1_940 - .saturating_add(Weight::from_parts(5_729_831, 0).saturating_mul(i.into())) + // Minimum execution time: 435_000 picoseconds. + Weight::from_parts(66_547_542, 990) + // Standard Error: 4_557 + .saturating_add(Weight::from_parts(5_851_324, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3016).saturating_mul(i.into())) } - /// Storage: `Glutton::Storage` (r:1 w:0) - /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::Compute` (r:1 w:0) - /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::TrashData` (r:1737 w:0) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:1737 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) fn on_idle_high_proof_waste() -> Weight { // Proof Size summary in bytes: // Measured: `1900497` // Estimated: `5239782` - // Minimum execution time: 55_403_909_000 picoseconds. - Weight::from_parts(55_472_412_000, 5239782) + // Minimum execution time: 67_699_845_000 picoseconds. + Weight::from_parts(67_893_204_000, 5239782) .saturating_add(RocksDbWeight::get().reads(1739_u64)) } - /// Storage: `Glutton::Storage` (r:1 w:0) - /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::Compute` (r:1 w:0) - /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::TrashData` (r:5 w:0) - /// Proof: `Glutton::TrashData` (`max_values`: Some(65000), `max_size`: Some(1036), added: 3016, mode: `MaxEncodedLen`) + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:5 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) fn on_idle_low_proof_waste() -> Weight { // Proof Size summary in bytes: // Measured: `9547` // Estimated: `16070` - // Minimum execution time: 97_959_007_000 picoseconds. - Weight::from_parts(98_030_476_000, 16070) + // Minimum execution time: 122_297_527_000 picoseconds. + Weight::from_parts(122_394_818_000, 16070) .saturating_add(RocksDbWeight::get().reads(7_u64)) } - /// Storage: `Glutton::Storage` (r:1 w:0) - /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Glutton::Compute` (r:1 w:0) - /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn empty_on_idle() -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1493` - // Minimum execution time: 5_011_000 picoseconds. - Weight::from_parts(5_183_000, 1493) + // Minimum execution time: 5_882_000 picoseconds. + Weight::from_parts(6_138_000, 1493) .saturating_add(RocksDbWeight::get().reads(2_u64)) } - /// Storage: `Glutton::Compute` (r:0 w:1) - /// Proof: `Glutton::Compute` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Glutton Compute (r:0 w:1) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn set_compute() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_591_000 picoseconds. - Weight::from_parts(5_970_000, 0) + // Minimum execution time: 7_830_000 picoseconds. + Weight::from_parts(8_366_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Glutton::Storage` (r:0 w:1) - /// Proof: `Glutton::Storage` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Glutton Storage (r:0 w:1) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn set_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_689_000 picoseconds. - Weight::from_parts(6_038_000, 0) + // Minimum execution time: 7_933_000 picoseconds. + Weight::from_parts(8_213_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/grandpa/src/mock.rs b/substrate/frame/grandpa/src/mock.rs index e1be487dbb7..5d48f974c31 100644 --- a/substrate/frame/grandpa/src/mock.rs +++ b/substrate/frame/grandpa/src/mock.rs @@ -35,8 +35,11 @@ use sp_consensus_grandpa::{RoundNumber, SetId, GRANDPA_ENGINE_ID}; use sp_core::{crypto::KeyTypeId, H256}; use sp_keyring::Ed25519Keyring; use sp_runtime::{ - curve::PiecewiseLinear, generic::UncheckedExtrinsic, impl_opaque_keys, - testing::UintAuthorityId, traits::OpaqueKeys, BuildStorage, DigestItem, Perbill, + curve::PiecewiseLinear, + impl_opaque_keys, + testing::{TestXt, UintAuthorityId}, + traits::OpaqueKeys, + BuildStorage, DigestItem, Perbill, }; use sp_staking::{EraIndex, SessionIndex}; @@ -74,7 +77,7 @@ where RuntimeCall: From, { type OverarchingCall = RuntimeCall; - type Extrinsic = UncheckedExtrinsic; + type Extrinsic = TestXt; } parameter_types! { diff --git a/substrate/frame/identity/src/weights.rs b/substrate/frame/identity/src/weights.rs index 81de520d7f2..1feb8252c84 100644 --- a/substrate/frame/identity/src/weights.rs +++ b/substrate/frame/identity/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_identity` +//! Autogenerated weights for pallet_identity //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/identity/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/identity/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_identity`. +/// Weight functions needed for pallet_identity. pub trait WeightInfo { fn add_registrar(r: u32, ) -> Weight; fn set_identity(r: u32, ) -> Weight; @@ -76,274 +77,278 @@ pub trait WeightInfo { fn remove_dangling_username() -> Weight; } -/// Weights for `pallet_identity` using the Substrate node and recommended hardware. +/// Weights for pallet_identity using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `32 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 8_857_000 picoseconds. - Weight::from_parts(9_331_464, 2626) - // Standard Error: 1_745 - .saturating_add(Weight::from_parts(94_096, 0).saturating_mul(r.into())) + // Minimum execution time: 11_683_000 picoseconds. + Weight::from_parts(12_515_830, 2626) + // Standard Error: 2_154 + .saturating_add(Weight::from_parts(147_919, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. - fn set_identity(_r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `6978 + r * (5 ±0)` - // Estimated: `11037` - // Minimum execution time: 96_522_000 picoseconds. - Weight::from_parts(102_738_605, 11037) + fn set_identity(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `442 + r * (5 ±0)` + // Estimated: `11003` + // Minimum execution time: 32_949_000 picoseconds. + Weight::from_parts(31_329_634, 11003) + // Standard Error: 4_496 + .saturating_add(Weight::from_parts(203_570, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:100 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:100 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `101` - // Estimated: `11037 + s * (2589 ±0)` - // Minimum execution time: 9_112_000 picoseconds. - Weight::from_parts(22_676_873, 11037) - // Standard Error: 6_494 - .saturating_add(Weight::from_parts(3_279_196, 0).saturating_mul(s.into())) + // Estimated: `11003 + s * (2589 ±0)` + // Minimum execution time: 9_157_000 picoseconds. + Weight::from_parts(24_917_444, 11003) + // Standard Error: 4_554 + .saturating_add(Weight::from_parts(3_279_868, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 2589).saturating_mul(s.into())) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `194 + p * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 8_902_000 picoseconds. - Weight::from_parts(21_168_031, 11037) - // Standard Error: 3_576 - .saturating_add(Weight::from_parts(1_431_542, 0).saturating_mul(p.into())) + // Estimated: `11003` + // Minimum execution time: 9_240_000 picoseconds. + Weight::from_parts(23_326_035, 11003) + // Standard Error: 3_664 + .saturating_add(Weight::from_parts(1_439_873, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. - fn clear_identity(_r: u32, s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `7070 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 52_468_000 picoseconds. - Weight::from_parts(56_065_452, 11037) - // Standard Error: 2_274 - .saturating_add(Weight::from_parts(1_399_051, 0).saturating_mul(s.into())) + fn clear_identity(r: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `469 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 55_687_000 picoseconds. + Weight::from_parts(30_695_182, 11003) + // Standard Error: 9_921 + .saturating_add(Weight::from_parts(162_357, 0).saturating_mul(r.into())) + // Standard Error: 1_937 + .saturating_add(Weight::from_parts(1_427_998, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: `Identity::Registrars` (r:1 w:0) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:0) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. fn request_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6968 + r * (57 ±0)` - // Estimated: `11037` - // Minimum execution time: 67_951_000 picoseconds. - Weight::from_parts(69_591_058, 11037) - // Standard Error: 4_420 - .saturating_add(Weight::from_parts(209_239, 0).saturating_mul(r.into())) + // Measured: `367 + r * (57 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 34_876_000 picoseconds. + Weight::from_parts(32_207_018, 11003) + // Standard Error: 5_247 + .saturating_add(Weight::from_parts(249_156, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. fn cancel_request(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6999` - // Estimated: `11037` - // Minimum execution time: 67_818_000 picoseconds. - Weight::from_parts(70_356_319, 11037) - // Standard Error: 5_116 - .saturating_add(Weight::from_parts(4_264, 0).saturating_mul(r.into())) + // Measured: `398 + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 30_689_000 picoseconds. + Weight::from_parts(31_967_170, 11003) + // Standard Error: 5_387 + .saturating_add(Weight::from_parts(42_676, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 6_096_000 picoseconds. - Weight::from_parts(6_470_752, 2626) - // Standard Error: 1_328 - .saturating_add(Weight::from_parts(94_764, 0).saturating_mul(r.into())) + // Minimum execution time: 7_357_000 picoseconds. + Weight::from_parts(7_932_950, 2626) + // Standard Error: 1_804 + .saturating_add(Weight::from_parts(132_653, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 6_278_000 picoseconds. - Weight::from_parts(6_678_997, 2626) - // Standard Error: 1_396 - .saturating_add(Weight::from_parts(87_207, 0).saturating_mul(r.into())) + // Minimum execution time: 7_437_000 picoseconds. + Weight::from_parts(8_051_889, 2626) + // Standard Error: 1_997 + .saturating_add(Weight::from_parts(129_592, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 6_130_000 picoseconds. - Weight::from_parts(6_516_146, 2626) - // Standard Error: 1_356 - .saturating_add(Weight::from_parts(88_455, 0).saturating_mul(r.into())) + // Minimum execution time: 7_385_000 picoseconds. + Weight::from_parts(7_911_589, 2626) + // Standard Error: 1_791 + .saturating_add(Weight::from_parts(125_788, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::Registrars` (r:1 w:0) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:0) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn provide_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7046 + r * (57 ±0)` - // Estimated: `11037` - // Minimum execution time: 87_100_000 picoseconds. - Weight::from_parts(87_601_945, 11037) - // Standard Error: 22_724 - .saturating_add(Weight::from_parts(458_296, 0).saturating_mul(r.into())) + // Measured: `445 + r * (57 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 24_073_000 picoseconds. + Weight::from_parts(17_817_684, 11003) + // Standard Error: 8_612 + .saturating_add(Weight::from_parts(406_251, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. fn kill_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7277 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 65_925_000 picoseconds. - Weight::from_parts(70_786_250, 11037) - // Standard Error: 19_680 - .saturating_add(Weight::from_parts(29_782, 0).saturating_mul(r.into())) - // Standard Error: 3_839 - .saturating_add(Weight::from_parts(1_377_604, 0).saturating_mul(s.into())) + // Measured: `676 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 73_981_000 picoseconds. + Weight::from_parts(51_684_057, 11003) + // Standard Error: 12_662 + .saturating_add(Weight::from_parts(145_285, 0).saturating_mul(r.into())) + // Standard Error: 2_472 + .saturating_add(Weight::from_parts(1_421_039, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `475 + s * (36 ±0)` - // Estimated: `11037` - // Minimum execution time: 25_916_000 picoseconds. - Weight::from_parts(29_781_270, 11037) - // Standard Error: 1_326 - .saturating_add(Weight::from_parts(101_515, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 29_367_000 picoseconds. + Weight::from_parts(34_214_998, 11003) + // Standard Error: 1_522 + .saturating_add(Weight::from_parts(114_551, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `591 + s * (3 ±0)` - // Estimated: `11037` - // Minimum execution time: 12_142_000 picoseconds. - Weight::from_parts(14_179_741, 11037) - // Standard Error: 538 - .saturating_add(Weight::from_parts(38_847, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 12_384_000 picoseconds. + Weight::from_parts(14_417_903, 11003) + // Standard Error: 539 + .saturating_add(Weight::from_parts(38_371, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `638 + s * (35 ±0)` - // Estimated: `11037` - // Minimum execution time: 29_327_000 picoseconds. - Weight::from_parts(32_163_402, 11037) - // Standard Error: 1_047 - .saturating_add(Weight::from_parts(87_159, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 33_327_000 picoseconds. + Weight::from_parts(36_208_941, 11003) + // Standard Error: 1_240 + .saturating_add(Weight::from_parts(105_805, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `704 + s * (37 ±0)` // Estimated: `6723` - // Minimum execution time: 22_380_000 picoseconds. - Weight::from_parts(24_557_574, 6723) - // Standard Error: 1_131 - .saturating_add(Weight::from_parts(86_358, 0).saturating_mul(s.into())) + // Minimum execution time: 23_764_000 picoseconds. + Weight::from_parts(26_407_731, 6723) + // Standard Error: 1_025 + .saturating_add(Weight::from_parts(101_112, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -353,359 +358,367 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_791_000 picoseconds. - Weight::from_parts(7_126_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 13_873_000 picoseconds. + Weight::from_parts(13_873_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) + /// Storage: `Identity::UsernameAuthorities` (r:0 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn remove_username_authority() -> Weight { // Proof Size summary in bytes: - // Measured: `80` - // Estimated: `3517` - // Minimum execution time: 9_657_000 picoseconds. - Weight::from_parts(9_922_000, 3517) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_653_000 picoseconds. + Weight::from_parts(10_653_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Identity::PendingUsernames` (r:1 w:0) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_username_for() -> Weight { // Proof Size summary in bytes: // Measured: `80` // Estimated: `11037` - // Minimum execution time: 67_928_000 picoseconds. - Weight::from_parts(69_993_000, 11037) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Minimum execution time: 75_928_000 picoseconds. + Weight::from_parts(75_928_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:0 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn accept_username() -> Weight { // Proof Size summary in bytes: - // Measured: `115` + // Measured: `106` // Estimated: `11037` - // Minimum execution time: 20_496_000 picoseconds. - Weight::from_parts(20_971_000, 11037) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Minimum execution time: 38_157_000 picoseconds. + Weight::from_parts(38_157_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) fn remove_expired_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `115` - // Estimated: `3550` - // Minimum execution time: 13_845_000 picoseconds. - Weight::from_parts(16_201_000, 3550) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `106` + // Estimated: `3542` + // Minimum execution time: 46_821_000 picoseconds. + Weight::from_parts(46_821_000, 0) + .saturating_add(Weight::from_parts(0, 3542)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:0) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_primary_username() -> Weight { // Proof Size summary in bytes: - // Measured: `257` + // Measured: `247` // Estimated: `11037` - // Minimum execution time: 15_900_000 picoseconds. - Weight::from_parts(16_716_000, 11037) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 22_515_000 picoseconds. + Weight::from_parts(22_515_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:0) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn remove_dangling_username() -> Weight { // Proof Size summary in bytes: - // Measured: `98` + // Measured: `126` // Estimated: `11037` - // Minimum execution time: 11_538_000 picoseconds. - Weight::from_parts(11_898_000, 11037) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 15_997_000 picoseconds. + Weight::from_parts(15_997_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `32 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 8_857_000 picoseconds. - Weight::from_parts(9_331_464, 2626) - // Standard Error: 1_745 - .saturating_add(Weight::from_parts(94_096, 0).saturating_mul(r.into())) + // Minimum execution time: 11_683_000 picoseconds. + Weight::from_parts(12_515_830, 2626) + // Standard Error: 2_154 + .saturating_add(Weight::from_parts(147_919, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. - fn set_identity(_r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `6978 + r * (5 ±0)` - // Estimated: `11037` - // Minimum execution time: 96_522_000 picoseconds. - Weight::from_parts(102_738_605, 11037) + fn set_identity(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `442 + r * (5 ±0)` + // Estimated: `11003` + // Minimum execution time: 32_949_000 picoseconds. + Weight::from_parts(31_329_634, 11003) + // Standard Error: 4_496 + .saturating_add(Weight::from_parts(203_570, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:100 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:100 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `101` - // Estimated: `11037 + s * (2589 ±0)` - // Minimum execution time: 9_112_000 picoseconds. - Weight::from_parts(22_676_873, 11037) - // Standard Error: 6_494 - .saturating_add(Weight::from_parts(3_279_196, 0).saturating_mul(s.into())) + // Estimated: `11003 + s * (2589 ±0)` + // Minimum execution time: 9_157_000 picoseconds. + Weight::from_parts(24_917_444, 11003) + // Standard Error: 4_554 + .saturating_add(Weight::from_parts(3_279_868, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(s.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 2589).saturating_mul(s.into())) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `194 + p * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 8_902_000 picoseconds. - Weight::from_parts(21_168_031, 11037) - // Standard Error: 3_576 - .saturating_add(Weight::from_parts(1_431_542, 0).saturating_mul(p.into())) + // Estimated: `11003` + // Minimum execution time: 9_240_000 picoseconds. + Weight::from_parts(23_326_035, 11003) + // Standard Error: 3_664 + .saturating_add(Weight::from_parts(1_439_873, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(p.into()))) } - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. - fn clear_identity(_r: u32, s: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `7070 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 52_468_000 picoseconds. - Weight::from_parts(56_065_452, 11037) - // Standard Error: 2_274 - .saturating_add(Weight::from_parts(1_399_051, 0).saturating_mul(s.into())) + fn clear_identity(r: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `469 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 55_687_000 picoseconds. + Weight::from_parts(30_695_182, 11003) + // Standard Error: 9_921 + .saturating_add(Weight::from_parts(162_357, 0).saturating_mul(r.into())) + // Standard Error: 1_937 + .saturating_add(Weight::from_parts(1_427_998, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: `Identity::Registrars` (r:1 w:0) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:0) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. fn request_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6968 + r * (57 ±0)` - // Estimated: `11037` - // Minimum execution time: 67_951_000 picoseconds. - Weight::from_parts(69_591_058, 11037) - // Standard Error: 4_420 - .saturating_add(Weight::from_parts(209_239, 0).saturating_mul(r.into())) + // Measured: `367 + r * (57 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 34_876_000 picoseconds. + Weight::from_parts(32_207_018, 11003) + // Standard Error: 5_247 + .saturating_add(Weight::from_parts(249_156, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. fn cancel_request(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6999` - // Estimated: `11037` - // Minimum execution time: 67_818_000 picoseconds. - Weight::from_parts(70_356_319, 11037) - // Standard Error: 5_116 - .saturating_add(Weight::from_parts(4_264, 0).saturating_mul(r.into())) + // Measured: `398 + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 30_689_000 picoseconds. + Weight::from_parts(31_967_170, 11003) + // Standard Error: 5_387 + .saturating_add(Weight::from_parts(42_676, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 6_096_000 picoseconds. - Weight::from_parts(6_470_752, 2626) - // Standard Error: 1_328 - .saturating_add(Weight::from_parts(94_764, 0).saturating_mul(r.into())) + // Minimum execution time: 7_357_000 picoseconds. + Weight::from_parts(7_932_950, 2626) + // Standard Error: 1_804 + .saturating_add(Weight::from_parts(132_653, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 6_278_000 picoseconds. - Weight::from_parts(6_678_997, 2626) - // Standard Error: 1_396 - .saturating_add(Weight::from_parts(87_207, 0).saturating_mul(r.into())) + // Minimum execution time: 7_437_000 picoseconds. + Weight::from_parts(8_051_889, 2626) + // Standard Error: 1_997 + .saturating_add(Weight::from_parts(129_592, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::Registrars` (r:1 w:1) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `89 + r * (57 ±0)` // Estimated: `2626` - // Minimum execution time: 6_130_000 picoseconds. - Weight::from_parts(6_516_146, 2626) - // Standard Error: 1_356 - .saturating_add(Weight::from_parts(88_455, 0).saturating_mul(r.into())) + // Minimum execution time: 7_385_000 picoseconds. + Weight::from_parts(7_911_589, 2626) + // Standard Error: 1_791 + .saturating_add(Weight::from_parts(125_788, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::Registrars` (r:1 w:0) - /// Proof: `Identity::Registrars` (`max_values`: Some(1), `max_size`: Some(1141), added: 1636, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) + /// Storage: Identity Registrars (r:1 w:0) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(1141), added: 1636, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) /// The range of component `r` is `[1, 19]`. fn provide_judgement(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7046 + r * (57 ±0)` - // Estimated: `11037` - // Minimum execution time: 87_100_000 picoseconds. - Weight::from_parts(87_601_945, 11037) - // Standard Error: 22_724 - .saturating_add(Weight::from_parts(458_296, 0).saturating_mul(r.into())) + // Measured: `445 + r * (57 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 24_073_000 picoseconds. + Weight::from_parts(17_817_684, 11003) + // Standard Error: 8_612 + .saturating_add(Weight::from_parts(406_251, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `Identity::IdentityOf` (r:1 w:1) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:0 w:100) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `r` is `[1, 20]`. /// The range of component `s` is `[0, 100]`. fn kill_identity(r: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `7277 + r * (5 ±0) + s * (32 ±0)` - // Estimated: `11037` - // Minimum execution time: 65_925_000 picoseconds. - Weight::from_parts(70_786_250, 11037) - // Standard Error: 19_680 - .saturating_add(Weight::from_parts(29_782, 0).saturating_mul(r.into())) - // Standard Error: 3_839 - .saturating_add(Weight::from_parts(1_377_604, 0).saturating_mul(s.into())) + // Measured: `676 + r * (5 ±0) + s * (32 ±0) + x * (66 ±0)` + // Estimated: `11003` + // Minimum execution time: 73_981_000 picoseconds. + Weight::from_parts(51_684_057, 11003) + // Standard Error: 12_662 + .saturating_add(Weight::from_parts(145_285, 0).saturating_mul(r.into())) + // Standard Error: 2_472 + .saturating_add(Weight::from_parts(1_421_039, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `475 + s * (36 ±0)` - // Estimated: `11037` - // Minimum execution time: 25_916_000 picoseconds. - Weight::from_parts(29_781_270, 11037) - // Standard Error: 1_326 - .saturating_add(Weight::from_parts(101_515, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 29_367_000 picoseconds. + Weight::from_parts(34_214_998, 11003) + // Standard Error: 1_522 + .saturating_add(Weight::from_parts(114_551, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `591 + s * (3 ±0)` - // Estimated: `11037` - // Minimum execution time: 12_142_000 picoseconds. - Weight::from_parts(14_179_741, 11037) - // Standard Error: 538 - .saturating_add(Weight::from_parts(38_847, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 12_384_000 picoseconds. + Weight::from_parts(14_417_903, 11003) + // Standard Error: 539 + .saturating_add(Weight::from_parts(38_371, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Identity::IdentityOf` (r:1 w:0) - /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7538), added: 10013, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `638 + s * (35 ±0)` - // Estimated: `11037` - // Minimum execution time: 29_327_000 picoseconds. - Weight::from_parts(32_163_402, 11037) - // Standard Error: 1_047 - .saturating_add(Weight::from_parts(87_159, 0).saturating_mul(s.into())) + // Estimated: `11003` + // Minimum execution time: 33_327_000 picoseconds. + Weight::from_parts(36_208_941, 11003) + // Standard Error: 1_240 + .saturating_add(Weight::from_parts(105_805, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Identity::SuperOf` (r:1 w:1) - /// Proof: `Identity::SuperOf` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Identity::SubsOf` (r:1 w:1) - /// Proof: `Identity::SubsOf` (`max_values`: None, `max_size`: Some(3258), added: 5733, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(3258), added: 5733, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `704 + s * (37 ±0)` // Estimated: `6723` - // Minimum execution time: 22_380_000 picoseconds. - Weight::from_parts(24_557_574, 6723) - // Standard Error: 1_131 - .saturating_add(Weight::from_parts(86_358, 0).saturating_mul(s.into())) + // Minimum execution time: 23_764_000 picoseconds. + Weight::from_parts(26_407_731, 6723) + // Standard Error: 1_025 + .saturating_add(Weight::from_parts(101_112, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -715,88 +728,92 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_791_000 picoseconds. - Weight::from_parts(7_126_000, 0) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 13_873_000 picoseconds. + Weight::from_parts(13_873_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(RocksDbWeight::get().writes(1)) } - /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) + /// Storage: `Identity::UsernameAuthorities` (r:0 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn remove_username_authority() -> Weight { // Proof Size summary in bytes: - // Measured: `80` - // Estimated: `3517` - // Minimum execution time: 9_657_000 picoseconds. - Weight::from_parts(9_922_000, 3517) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 10_653_000 picoseconds. + Weight::from_parts(10_653_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(RocksDbWeight::get().writes(1)) } /// Storage: `Identity::UsernameAuthorities` (r:1 w:1) /// Proof: `Identity::UsernameAuthorities` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Identity::PendingUsernames` (r:1 w:0) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_username_for() -> Weight { // Proof Size summary in bytes: // Measured: `80` // Estimated: `11037` - // Minimum execution time: 67_928_000 picoseconds. - Weight::from_parts(69_993_000, 11037) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Minimum execution time: 75_928_000 picoseconds. + Weight::from_parts(75_928_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(3)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) /// Storage: `Identity::AccountOfUsername` (r:0 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn accept_username() -> Weight { // Proof Size summary in bytes: - // Measured: `115` + // Measured: `106` // Estimated: `11037` - // Minimum execution time: 20_496_000 picoseconds. - Weight::from_parts(20_971_000, 11037) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Minimum execution time: 38_157_000 picoseconds. + Weight::from_parts(38_157_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) + .saturating_add(RocksDbWeight::get().reads(2)) + .saturating_add(RocksDbWeight::get().writes(3)) } /// Storage: `Identity::PendingUsernames` (r:1 w:1) - /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Proof: `Identity::PendingUsernames` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) fn remove_expired_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `115` - // Estimated: `3550` - // Minimum execution time: 13_845_000 picoseconds. - Weight::from_parts(16_201_000, 3550) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Measured: `106` + // Estimated: `3542` + // Minimum execution time: 46_821_000 picoseconds. + Weight::from_parts(46_821_000, 0) + .saturating_add(Weight::from_parts(0, 3542)) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(1)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:0) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:1) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn set_primary_username() -> Weight { // Proof Size summary in bytes: - // Measured: `257` + // Measured: `247` // Estimated: `11037` - // Minimum execution time: 15_900_000 picoseconds. - Weight::from_parts(16_716_000, 11037) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 22_515_000 picoseconds. + Weight::from_parts(22_515_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) + .saturating_add(RocksDbWeight::get().reads(2)) + .saturating_add(RocksDbWeight::get().writes(1)) } /// Storage: `Identity::AccountOfUsername` (r:1 w:1) - /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Proof: `Identity::AccountOfUsername` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Identity::IdentityOf` (r:1 w:0) /// Proof: `Identity::IdentityOf` (`max_values`: None, `max_size`: Some(7572), added: 10047, mode: `MaxEncodedLen`) fn remove_dangling_username() -> Weight { // Proof Size summary in bytes: - // Measured: `98` + // Measured: `126` // Estimated: `11037` - // Minimum execution time: 11_538_000 picoseconds. - Weight::from_parts(11_898_000, 11037) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 15_997_000 picoseconds. + Weight::from_parts(15_997_000, 0) + .saturating_add(Weight::from_parts(0, 11037)) + .saturating_add(RocksDbWeight::get().reads(2)) + .saturating_add(RocksDbWeight::get().writes(1)) } } diff --git a/substrate/frame/im-online/src/mock.rs b/substrate/frame/im-online/src/mock.rs index c0ba9143e13..9dad148b10f 100644 --- a/substrate/frame/im-online/src/mock.rs +++ b/substrate/frame/im-online/src/mock.rs @@ -27,7 +27,7 @@ use frame_support::{ use pallet_session::historical as pallet_session_historical; use sp_core::H256; use sp_runtime::{ - testing::UintAuthorityId, + testing::{TestXt, UintAuthorityId}, traits::{BlakeTwo256, ConvertInto, IdentityLookup}, BuildStorage, Permill, }; @@ -78,7 +78,7 @@ impl pallet_session::historical::SessionManager for TestSessionManager } /// An extrinsic type used for tests. -pub type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; +pub type Extrinsic = TestXt; type IdentificationTuple = (u64, u64); type Offence = crate::UnresponsivenessOffence; diff --git a/substrate/frame/im-online/src/tests.rs b/substrate/frame/im-online/src/tests.rs index 6f5a14d7e7f..5e5212e1d56 100644 --- a/substrate/frame/im-online/src/tests.rs +++ b/substrate/frame/im-online/src/tests.rs @@ -228,7 +228,7 @@ fn should_generate_heartbeats() { // check stuff about the transaction. let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); - let heartbeat = match ex.function { + let heartbeat = match ex.call { crate::mock::RuntimeCall::ImOnline(crate::Call::heartbeat { heartbeat, .. }) => heartbeat, e => panic!("Unexpected call: {:?}", e), @@ -342,7 +342,7 @@ fn should_not_send_a_report_if_already_online() { assert_eq!(pool_state.read().transactions.len(), 0); // check stuff about the transaction. let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); - let heartbeat = match ex.function { + let heartbeat = match ex.call { crate::mock::RuntimeCall::ImOnline(crate::Call::heartbeat { heartbeat, .. }) => heartbeat, e => panic!("Unexpected call: {:?}", e), diff --git a/substrate/frame/im-online/src/weights.rs b/substrate/frame/im-online/src/weights.rs index 11357b1e7b7..c3db02af257 100644 --- a/substrate/frame/im-online/src/weights.rs +++ b/substrate/frame/im-online/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_im_online` +//! Autogenerated weights for pallet_im_online //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/im-online/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/im-online/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,60 +50,60 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_im_online`. +/// Weight functions needed for pallet_im_online. pub trait WeightInfo { fn validate_unsigned_and_then_heartbeat(k: u32, ) -> Weight; } -/// Weights for `pallet_im_online` using the Substrate node and recommended hardware. +/// Weights for pallet_im_online using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Session::Validators` (r:1 w:0) - /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Session::CurrentIndex` (r:1 w:0) - /// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ImOnline::Keys` (r:1 w:0) - /// Proof: `ImOnline::Keys` (`max_values`: Some(1), `max_size`: Some(320002), added: 320497, mode: `MaxEncodedLen`) - /// Storage: `ImOnline::ReceivedHeartbeats` (r:1 w:1) - /// Proof: `ImOnline::ReceivedHeartbeats` (`max_values`: None, `max_size`: Some(25), added: 2500, mode: `MaxEncodedLen`) - /// Storage: `ImOnline::AuthoredBlocks` (r:1 w:0) - /// Proof: `ImOnline::AuthoredBlocks` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: Session Validators (r:1 w:0) + /// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Session CurrentIndex (r:1 w:0) + /// Proof Skipped: Session CurrentIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ImOnline Keys (r:1 w:0) + /// Proof: ImOnline Keys (max_values: Some(1), max_size: Some(320002), added: 320497, mode: MaxEncodedLen) + /// Storage: ImOnline ReceivedHeartbeats (r:1 w:1) + /// Proof: ImOnline ReceivedHeartbeats (max_values: None, max_size: Some(25), added: 2500, mode: MaxEncodedLen) + /// Storage: ImOnline AuthoredBlocks (r:1 w:0) + /// Proof: ImOnline AuthoredBlocks (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) /// The range of component `k` is `[1, 1000]`. fn validate_unsigned_and_then_heartbeat(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `327 + k * (32 ±0)` + // Measured: `295 + k * (32 ±0)` // Estimated: `321487 + k * (1761 ±0)` - // Minimum execution time: 65_515_000 picoseconds. - Weight::from_parts(74_765_329, 321487) - // Standard Error: 500 - .saturating_add(Weight::from_parts(39_171, 0).saturating_mul(k.into())) + // Minimum execution time: 80_568_000 picoseconds. + Weight::from_parts(95_175_595, 321487) + // Standard Error: 627 + .saturating_add(Weight::from_parts(39_094, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1761).saturating_mul(k.into())) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Session::Validators` (r:1 w:0) - /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Session::CurrentIndex` (r:1 w:0) - /// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ImOnline::Keys` (r:1 w:0) - /// Proof: `ImOnline::Keys` (`max_values`: Some(1), `max_size`: Some(320002), added: 320497, mode: `MaxEncodedLen`) - /// Storage: `ImOnline::ReceivedHeartbeats` (r:1 w:1) - /// Proof: `ImOnline::ReceivedHeartbeats` (`max_values`: None, `max_size`: Some(25), added: 2500, mode: `MaxEncodedLen`) - /// Storage: `ImOnline::AuthoredBlocks` (r:1 w:0) - /// Proof: `ImOnline::AuthoredBlocks` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: Session Validators (r:1 w:0) + /// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Session CurrentIndex (r:1 w:0) + /// Proof Skipped: Session CurrentIndex (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ImOnline Keys (r:1 w:0) + /// Proof: ImOnline Keys (max_values: Some(1), max_size: Some(320002), added: 320497, mode: MaxEncodedLen) + /// Storage: ImOnline ReceivedHeartbeats (r:1 w:1) + /// Proof: ImOnline ReceivedHeartbeats (max_values: None, max_size: Some(25), added: 2500, mode: MaxEncodedLen) + /// Storage: ImOnline AuthoredBlocks (r:1 w:0) + /// Proof: ImOnline AuthoredBlocks (max_values: None, max_size: Some(56), added: 2531, mode: MaxEncodedLen) /// The range of component `k` is `[1, 1000]`. fn validate_unsigned_and_then_heartbeat(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `327 + k * (32 ±0)` + // Measured: `295 + k * (32 ±0)` // Estimated: `321487 + k * (1761 ±0)` - // Minimum execution time: 65_515_000 picoseconds. - Weight::from_parts(74_765_329, 321487) - // Standard Error: 500 - .saturating_add(Weight::from_parts(39_171, 0).saturating_mul(k.into())) + // Minimum execution time: 80_568_000 picoseconds. + Weight::from_parts(95_175_595, 321487) + // Standard Error: 627 + .saturating_add(Weight::from_parts(39_094, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1761).saturating_mul(k.into())) diff --git a/substrate/frame/indices/src/weights.rs b/substrate/frame/indices/src/weights.rs index 6b571164eb6..d081cc738b1 100644 --- a/substrate/frame/indices/src/weights.rs +++ b/substrate/frame/indices/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_indices` +//! Autogenerated weights for pallet_indices //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/indices/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/indices/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_indices`. +/// Weight functions needed for pallet_indices. pub trait WeightInfo { fn claim() -> Weight; fn transfer() -> Weight; @@ -58,128 +59,128 @@ pub trait WeightInfo { fn freeze() -> Weight; } -/// Weights for `pallet_indices` using the Substrate node and recommended hardware. +/// Weights for pallet_indices using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn claim() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3534` - // Minimum execution time: 20_825_000 picoseconds. - Weight::from_parts(21_507_000, 3534) + // Minimum execution time: 25_491_000 picoseconds. + Weight::from_parts(26_456_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `3593` - // Minimum execution time: 31_091_000 picoseconds. - Weight::from_parts(31_923_000, 3593) + // Minimum execution time: 38_027_000 picoseconds. + Weight::from_parts(38_749_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn free() -> Weight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `3534` - // Minimum execution time: 21_832_000 picoseconds. - Weight::from_parts(22_436_000, 3534) + // Minimum execution time: 26_652_000 picoseconds. + Weight::from_parts(27_273_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `3593` - // Minimum execution time: 23_876_000 picoseconds. - Weight::from_parts(24_954_000, 3593) + // Minimum execution time: 29_464_000 picoseconds. + Weight::from_parts(30_959_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn freeze() -> Weight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `3534` - // Minimum execution time: 22_954_000 picoseconds. - Weight::from_parts(23_792_000, 3534) + // Minimum execution time: 29_015_000 picoseconds. + Weight::from_parts(29_714_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn claim() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3534` - // Minimum execution time: 20_825_000 picoseconds. - Weight::from_parts(21_507_000, 3534) + // Minimum execution time: 25_491_000 picoseconds. + Weight::from_parts(26_456_000, 3534) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `3593` - // Minimum execution time: 31_091_000 picoseconds. - Weight::from_parts(31_923_000, 3593) + // Minimum execution time: 38_027_000 picoseconds. + Weight::from_parts(38_749_000, 3593) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn free() -> Weight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `3534` - // Minimum execution time: 21_832_000 picoseconds. - Weight::from_parts(22_436_000, 3534) + // Minimum execution time: 26_652_000 picoseconds. + Weight::from_parts(27_273_000, 3534) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn force_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `3593` - // Minimum execution time: 23_876_000 picoseconds. - Weight::from_parts(24_954_000, 3593) + // Minimum execution time: 29_464_000 picoseconds. + Weight::from_parts(30_959_000, 3593) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Indices::Accounts` (r:1 w:1) - /// Proof: `Indices::Accounts` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Indices Accounts (r:1 w:1) + /// Proof: Indices Accounts (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn freeze() -> Weight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `3534` - // Minimum execution time: 22_954_000 picoseconds. - Weight::from_parts(23_792_000, 3534) + // Minimum execution time: 29_015_000 picoseconds. + Weight::from_parts(29_714_000, 3534) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/lottery/src/weights.rs b/substrate/frame/lottery/src/weights.rs index 7e56cdf90db..3b4e5623753 100644 --- a/substrate/frame/lottery/src/weights.rs +++ b/substrate/frame/lottery/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_lottery` +//! Autogenerated weights for pallet_lottery //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/lottery/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/lottery/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_lottery`. +/// Weight functions needed for pallet_lottery. pub trait WeightInfo { fn buy_ticket() -> Weight; fn set_calls(n: u32, ) -> Weight; @@ -59,222 +60,214 @@ pub trait WeightInfo { fn on_initialize_repeat() -> Weight; } -/// Weights for `pallet_lottery` using the Substrate node and recommended hardware. +/// Weights for pallet_lottery using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Lottery` (r:1 w:0) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) - /// Storage: `Lottery::CallIndices` (r:1 w:0) - /// Proof: `Lottery::CallIndices` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) - /// Storage: `Lottery::TicketsCount` (r:1 w:1) - /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Participants` (r:1 w:1) - /// Proof: `Lottery::Participants` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `Lottery::LotteryIndex` (r:1 w:0) - /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Tickets` (r:0 w:1) - /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: Lottery Lottery (r:1 w:0) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: Lottery CallIndices (r:1 w:0) + /// Proof: Lottery CallIndices (max_values: Some(1), max_size: Some(21), added: 516, mode: MaxEncodedLen) + /// Storage: Lottery TicketsCount (r:1 w:1) + /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Lottery Participants (r:1 w:1) + /// Proof: Lottery Participants (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: Lottery LotteryIndex (r:1 w:0) + /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Lottery Tickets (r:0 w:1) + /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) fn buy_ticket() -> Weight { // Proof Size summary in bytes: - // Measured: `492` - // Estimated: `3997` - // Minimum execution time: 57_891_000 picoseconds. - Weight::from_parts(59_508_000, 3997) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Measured: `452` + // Estimated: `3593` + // Minimum execution time: 60_298_000 picoseconds. + Weight::from_parts(62_058_000, 3593) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Lottery::CallIndices` (r:0 w:1) - /// Proof: `Lottery::CallIndices` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) + /// Storage: Lottery CallIndices (r:0 w:1) + /// Proof: Lottery CallIndices (max_values: Some(1), max_size: Some(21), added: 516, mode: MaxEncodedLen) /// The range of component `n` is `[0, 10]`. fn set_calls(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_026_000 picoseconds. - Weight::from_parts(5_854_666, 0) - // Standard Error: 3_233 - .saturating_add(Weight::from_parts(334_818, 0).saturating_mul(n.into())) + // Minimum execution time: 7_291_000 picoseconds. + Weight::from_parts(8_178_186, 0) + // Standard Error: 3_048 + .saturating_add(Weight::from_parts(330_871, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Lottery::Lottery` (r:1 w:1) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) - /// Storage: `Lottery::LotteryIndex` (r:1 w:1) - /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Lottery Lottery (r:1 w:1) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: Lottery LotteryIndex (r:1 w:1) + /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn start_lottery() -> Weight { // Proof Size summary in bytes: - // Measured: `194` + // Measured: `161` // Estimated: `3593` - // Minimum execution time: 26_216_000 picoseconds. - Weight::from_parts(27_216_000, 3593) + // Minimum execution time: 36_741_000 picoseconds. + Weight::from_parts(38_288_000, 3593) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Lottery::Lottery` (r:1 w:1) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: Lottery Lottery (r:1 w:1) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) fn stop_repeat() -> Weight { // Proof Size summary in bytes: - // Measured: `252` + // Measured: `219` // Estimated: `1514` - // Minimum execution time: 6_208_000 picoseconds. - Weight::from_parts(6_427_000, 1514) + // Minimum execution time: 7_270_000 picoseconds. + Weight::from_parts(7_578_000, 1514) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) - /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Lottery` (r:1 w:1) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Lottery::TicketsCount` (r:1 w:1) - /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Tickets` (r:1 w:0) - /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Lottery Lottery (r:1 w:1) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Lottery TicketsCount (r:1 w:1) + /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Lottery Tickets (r:1 w:0) + /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) fn on_initialize_end() -> Weight { // Proof Size summary in bytes: - // Measured: `591` + // Measured: `558` // Estimated: `6196` - // Minimum execution time: 58_660_000 picoseconds. - Weight::from_parts(59_358_000, 6196) + // Minimum execution time: 76_611_000 picoseconds. + Weight::from_parts(78_107_000, 6196) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) - /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Lottery` (r:1 w:1) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Lottery::TicketsCount` (r:1 w:1) - /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Tickets` (r:1 w:0) - /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - /// Storage: `Lottery::LotteryIndex` (r:1 w:1) - /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Lottery Lottery (r:1 w:1) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Lottery TicketsCount (r:1 w:1) + /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Lottery Tickets (r:1 w:0) + /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) + /// Storage: Lottery LotteryIndex (r:1 w:1) + /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn on_initialize_repeat() -> Weight { // Proof Size summary in bytes: - // Measured: `591` + // Measured: `558` // Estimated: `6196` - // Minimum execution time: 59_376_000 picoseconds. - Weight::from_parts(60_598_000, 6196) + // Minimum execution time: 78_731_000 picoseconds. + Weight::from_parts(80_248_000, 6196) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Lottery` (r:1 w:0) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) - /// Storage: `Lottery::CallIndices` (r:1 w:0) - /// Proof: `Lottery::CallIndices` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) - /// Storage: `Lottery::TicketsCount` (r:1 w:1) - /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Participants` (r:1 w:1) - /// Proof: `Lottery::Participants` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `Lottery::LotteryIndex` (r:1 w:0) - /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Tickets` (r:0 w:1) - /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: Lottery Lottery (r:1 w:0) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: Lottery CallIndices (r:1 w:0) + /// Proof: Lottery CallIndices (max_values: Some(1), max_size: Some(21), added: 516, mode: MaxEncodedLen) + /// Storage: Lottery TicketsCount (r:1 w:1) + /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Lottery Participants (r:1 w:1) + /// Proof: Lottery Participants (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: Lottery LotteryIndex (r:1 w:0) + /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Lottery Tickets (r:0 w:1) + /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) fn buy_ticket() -> Weight { // Proof Size summary in bytes: - // Measured: `492` - // Estimated: `3997` - // Minimum execution time: 57_891_000 picoseconds. - Weight::from_parts(59_508_000, 3997) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Measured: `452` + // Estimated: `3593` + // Minimum execution time: 60_298_000 picoseconds. + Weight::from_parts(62_058_000, 3593) + .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Lottery::CallIndices` (r:0 w:1) - /// Proof: `Lottery::CallIndices` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) + /// Storage: Lottery CallIndices (r:0 w:1) + /// Proof: Lottery CallIndices (max_values: Some(1), max_size: Some(21), added: 516, mode: MaxEncodedLen) /// The range of component `n` is `[0, 10]`. fn set_calls(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_026_000 picoseconds. - Weight::from_parts(5_854_666, 0) - // Standard Error: 3_233 - .saturating_add(Weight::from_parts(334_818, 0).saturating_mul(n.into())) + // Minimum execution time: 7_291_000 picoseconds. + Weight::from_parts(8_178_186, 0) + // Standard Error: 3_048 + .saturating_add(Weight::from_parts(330_871, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Lottery::Lottery` (r:1 w:1) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) - /// Storage: `Lottery::LotteryIndex` (r:1 w:1) - /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Lottery Lottery (r:1 w:1) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: Lottery LotteryIndex (r:1 w:1) + /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn start_lottery() -> Weight { // Proof Size summary in bytes: - // Measured: `194` + // Measured: `161` // Estimated: `3593` - // Minimum execution time: 26_216_000 picoseconds. - Weight::from_parts(27_216_000, 3593) + // Minimum execution time: 36_741_000 picoseconds. + Weight::from_parts(38_288_000, 3593) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Lottery::Lottery` (r:1 w:1) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) + /// Storage: Lottery Lottery (r:1 w:1) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) fn stop_repeat() -> Weight { // Proof Size summary in bytes: - // Measured: `252` + // Measured: `219` // Estimated: `1514` - // Minimum execution time: 6_208_000 picoseconds. - Weight::from_parts(6_427_000, 1514) + // Minimum execution time: 7_270_000 picoseconds. + Weight::from_parts(7_578_000, 1514) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) - /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Lottery` (r:1 w:1) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Lottery::TicketsCount` (r:1 w:1) - /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Tickets` (r:1 w:0) - /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Lottery Lottery (r:1 w:1) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Lottery TicketsCount (r:1 w:1) + /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Lottery Tickets (r:1 w:0) + /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) fn on_initialize_end() -> Weight { // Proof Size summary in bytes: - // Measured: `591` + // Measured: `558` // Estimated: `6196` - // Minimum execution time: 58_660_000 picoseconds. - Weight::from_parts(59_358_000, 6196) + // Minimum execution time: 76_611_000 picoseconds. + Weight::from_parts(78_107_000, 6196) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `RandomnessCollectiveFlip::RandomMaterial` (r:1 w:0) - /// Proof: `RandomnessCollectiveFlip::RandomMaterial` (`max_values`: Some(1), `max_size`: Some(2594), added: 3089, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Lottery` (r:1 w:1) - /// Proof: `Lottery::Lottery` (`max_values`: Some(1), `max_size`: Some(29), added: 524, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Lottery::TicketsCount` (r:1 w:1) - /// Proof: `Lottery::TicketsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Lottery::Tickets` (r:1 w:0) - /// Proof: `Lottery::Tickets` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - /// Storage: `Lottery::LotteryIndex` (r:1 w:1) - /// Proof: `Lottery::LotteryIndex` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: RandomnessCollectiveFlip RandomMaterial (r:1 w:0) + /// Proof: RandomnessCollectiveFlip RandomMaterial (max_values: Some(1), max_size: Some(2594), added: 3089, mode: MaxEncodedLen) + /// Storage: Lottery Lottery (r:1 w:1) + /// Proof: Lottery Lottery (max_values: Some(1), max_size: Some(29), added: 524, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Lottery TicketsCount (r:1 w:1) + /// Proof: Lottery TicketsCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Lottery Tickets (r:1 w:0) + /// Proof: Lottery Tickets (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen) + /// Storage: Lottery LotteryIndex (r:1 w:1) + /// Proof: Lottery LotteryIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn on_initialize_repeat() -> Weight { // Proof Size summary in bytes: - // Measured: `591` + // Measured: `558` // Estimated: `6196` - // Minimum execution time: 59_376_000 picoseconds. - Weight::from_parts(60_598_000, 6196) + // Minimum execution time: 78_731_000 picoseconds. + Weight::from_parts(80_248_000, 6196) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } diff --git a/substrate/frame/membership/src/weights.rs b/substrate/frame/membership/src/weights.rs index f21867d6870..2d18848b89a 100644 --- a/substrate/frame/membership/src/weights.rs +++ b/substrate/frame/membership/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_membership` +//! Autogenerated weights for pallet_membership //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/membership/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/membership/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_membership`. +/// Weight functions needed for pallet_membership. pub trait WeightInfo { fn add_member(m: u32, ) -> Weight; fn remove_member(m: u32, ) -> Weight; @@ -60,299 +61,299 @@ pub trait WeightInfo { fn clear_prime() -> Weight; } -/// Weights for `pallet_membership` using the Substrate node and recommended hardware. +/// Weights for pallet_membership using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 99]`. fn add_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `207 + m * (64 ±0)` + // Measured: `208 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 12_126_000 picoseconds. - Weight::from_parts(13_085_583, 4687) - // Standard Error: 659 - .saturating_add(Weight::from_parts(36_103, 0).saturating_mul(m.into())) + // Minimum execution time: 17_040_000 picoseconds. + Weight::from_parts(18_344_571, 4687) + // Standard Error: 847 + .saturating_add(Weight::from_parts(50_842, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalMembership::Prime` (r:1 w:0) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalMembership Prime (r:1 w:0) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[2, 100]`. fn remove_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `311 + m * (64 ±0)` + // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 14_571_000 picoseconds. - Weight::from_parts(15_532_232, 4687) - // Standard Error: 531 - .saturating_add(Weight::from_parts(35_757, 0).saturating_mul(m.into())) + // Minimum execution time: 20_088_000 picoseconds. + Weight::from_parts(21_271_384, 4687) + // Standard Error: 786 + .saturating_add(Weight::from_parts(44_806, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalMembership::Prime` (r:1 w:0) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalMembership Prime (r:1 w:0) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[2, 100]`. fn swap_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `311 + m * (64 ±0)` + // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 14_833_000 picoseconds. - Weight::from_parts(15_657_084, 4687) - // Standard Error: 650 - .saturating_add(Weight::from_parts(44_467, 0).saturating_mul(m.into())) + // Minimum execution time: 20_308_000 picoseconds. + Weight::from_parts(21_469_843, 4687) + // Standard Error: 782 + .saturating_add(Weight::from_parts(56_893, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalMembership::Prime` (r:1 w:0) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalMembership Prime (r:1 w:0) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. fn reset_members(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `311 + m * (64 ±0)` + // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 14_629_000 picoseconds. - Weight::from_parts(15_578_203, 4687) - // Standard Error: 910 - .saturating_add(Weight::from_parts(145_101, 0).saturating_mul(m.into())) + // Minimum execution time: 19_464_000 picoseconds. + Weight::from_parts(21_223_702, 4687) + // Standard Error: 1_068 + .saturating_add(Weight::from_parts(165_438, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalMembership::Prime` (r:1 w:1) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalMembership Prime (r:1 w:1) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. fn change_key(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `311 + m * (64 ±0)` + // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 15_218_000 picoseconds. - Weight::from_parts(16_388_690, 4687) - // Standard Error: 626 - .saturating_add(Weight::from_parts(46_204, 0).saturating_mul(m.into())) + // Minimum execution time: 20_965_000 picoseconds. + Weight::from_parts(22_551_007, 4687) + // Standard Error: 860 + .saturating_add(Weight::from_parts(52_397, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:0) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalMembership::Prime` (r:0 w:1) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:0) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalMembership Prime (r:0 w:1) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. fn set_prime(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `31 + m * (32 ±0)` + // Measured: `32 + m * (32 ±0)` // Estimated: `4687 + m * (32 ±0)` - // Minimum execution time: 5_954_000 picoseconds. - Weight::from_parts(6_544_638, 4687) - // Standard Error: 346 - .saturating_add(Weight::from_parts(17_638, 0).saturating_mul(m.into())) + // Minimum execution time: 7_481_000 picoseconds. + Weight::from_parts(7_959_053, 4687) + // Standard Error: 364 + .saturating_add(Weight::from_parts(18_653, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Prime` (r:0 w:1) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Prime (r:0 w:1) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) fn clear_prime() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_569_000 picoseconds. - Weight::from_parts(2_776_000, 0) + // Minimum execution time: 3_373_000 picoseconds. + Weight::from_parts(3_750_452, 0) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 99]`. fn add_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `207 + m * (64 ±0)` + // Measured: `208 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 12_126_000 picoseconds. - Weight::from_parts(13_085_583, 4687) - // Standard Error: 659 - .saturating_add(Weight::from_parts(36_103, 0).saturating_mul(m.into())) + // Minimum execution time: 17_040_000 picoseconds. + Weight::from_parts(18_344_571, 4687) + // Standard Error: 847 + .saturating_add(Weight::from_parts(50_842, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalMembership::Prime` (r:1 w:0) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalMembership Prime (r:1 w:0) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[2, 100]`. fn remove_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `311 + m * (64 ±0)` + // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 14_571_000 picoseconds. - Weight::from_parts(15_532_232, 4687) - // Standard Error: 531 - .saturating_add(Weight::from_parts(35_757, 0).saturating_mul(m.into())) + // Minimum execution time: 20_088_000 picoseconds. + Weight::from_parts(21_271_384, 4687) + // Standard Error: 786 + .saturating_add(Weight::from_parts(44_806, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalMembership::Prime` (r:1 w:0) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalMembership Prime (r:1 w:0) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[2, 100]`. fn swap_member(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `311 + m * (64 ±0)` + // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 14_833_000 picoseconds. - Weight::from_parts(15_657_084, 4687) - // Standard Error: 650 - .saturating_add(Weight::from_parts(44_467, 0).saturating_mul(m.into())) + // Minimum execution time: 20_308_000 picoseconds. + Weight::from_parts(21_469_843, 4687) + // Standard Error: 782 + .saturating_add(Weight::from_parts(56_893, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalMembership::Prime` (r:1 w:0) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalMembership Prime (r:1 w:0) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. fn reset_members(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `311 + m * (64 ±0)` + // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 14_629_000 picoseconds. - Weight::from_parts(15_578_203, 4687) - // Standard Error: 910 - .saturating_add(Weight::from_parts(145_101, 0).saturating_mul(m.into())) + // Minimum execution time: 19_464_000 picoseconds. + Weight::from_parts(21_223_702, 4687) + // Standard Error: 1_068 + .saturating_add(Weight::from_parts(165_438, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:1) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Proposals` (r:1 w:0) - /// Proof: `TechnicalCommittee::Proposals` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalMembership::Prime` (r:1 w:1) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Members` (r:0 w:1) - /// Proof: `TechnicalCommittee::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:1) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Proposals (r:1 w:0) + /// Proof Skipped: TechnicalCommittee Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalMembership Prime (r:1 w:1) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Members (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. fn change_key(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `311 + m * (64 ±0)` + // Measured: `312 + m * (64 ±0)` // Estimated: `4687 + m * (64 ±0)` - // Minimum execution time: 15_218_000 picoseconds. - Weight::from_parts(16_388_690, 4687) - // Standard Error: 626 - .saturating_add(Weight::from_parts(46_204, 0).saturating_mul(m.into())) + // Minimum execution time: 20_965_000 picoseconds. + Weight::from_parts(22_551_007, 4687) + // Standard Error: 860 + .saturating_add(Weight::from_parts(52_397, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Members` (r:1 w:0) - /// Proof: `TechnicalMembership::Members` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) - /// Storage: `TechnicalMembership::Prime` (r:0 w:1) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Members (r:1 w:0) + /// Proof: TechnicalMembership Members (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen) + /// Storage: TechnicalMembership Prime (r:0 w:1) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) /// The range of component `m` is `[1, 100]`. fn set_prime(m: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `31 + m * (32 ±0)` + // Measured: `32 + m * (32 ±0)` // Estimated: `4687 + m * (32 ±0)` - // Minimum execution time: 5_954_000 picoseconds. - Weight::from_parts(6_544_638, 4687) - // Standard Error: 346 - .saturating_add(Weight::from_parts(17_638, 0).saturating_mul(m.into())) + // Minimum execution time: 7_481_000 picoseconds. + Weight::from_parts(7_959_053, 4687) + // Standard Error: 364 + .saturating_add(Weight::from_parts(18_653, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 32).saturating_mul(m.into())) } - /// Storage: `TechnicalMembership::Prime` (r:0 w:1) - /// Proof: `TechnicalMembership::Prime` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TechnicalCommittee::Prime` (r:0 w:1) - /// Proof: `TechnicalCommittee::Prime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: TechnicalMembership Prime (r:0 w:1) + /// Proof: TechnicalMembership Prime (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TechnicalCommittee Prime (r:0 w:1) + /// Proof Skipped: TechnicalCommittee Prime (max_values: Some(1), max_size: None, mode: Measured) fn clear_prime() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_569_000 picoseconds. - Weight::from_parts(2_776_000, 0) + // Minimum execution time: 3_373_000 picoseconds. + Weight::from_parts(3_750_452, 0) .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/substrate/frame/message-queue/src/weights.rs b/substrate/frame/message-queue/src/weights.rs index 001e2834e1c..e86f23e274f 100644 --- a/substrate/frame/message-queue/src/weights.rs +++ b/substrate/frame/message-queue/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_message_queue` +//! Autogenerated weights for pallet_message_queue //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/message-queue/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/message-queue/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_message_queue`. +/// Weight functions needed for pallet_message_queue. pub trait WeightInfo { fn ready_ring_knit() -> Weight; fn ready_ring_unknit() -> Weight; @@ -63,256 +64,246 @@ pub trait WeightInfo { fn execute_overweight_page_updated() -> Weight; } -/// Weights for `pallet_message_queue` using the Substrate node and recommended hardware. +/// Weights for pallet_message_queue using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `MessageQueue::ServiceHead` (r:1 w:0) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn ready_ring_knit() -> Weight { // Proof Size summary in bytes: - // Measured: `301` + // Measured: `267` // Estimated: `6038` - // Minimum execution time: 11_563_000 picoseconds. - Weight::from_parts(11_956_000, 6038) + // Minimum execution time: 12_025_000 picoseconds. + Weight::from_parts(12_597_000, 6038) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn ready_ring_unknit() -> Weight { // Proof Size summary in bytes: - // Measured: `301` + // Measured: `267` // Estimated: `6038` - // Minimum execution time: 10_263_000 picoseconds. - Weight::from_parts(10_638_000, 6038) + // Minimum execution time: 11_563_000 picoseconds. + Weight::from_parts(11_785_000, 6038) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn service_queue_base() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3514` - // Minimum execution time: 4_335_000 picoseconds. - Weight::from_parts(4_552_000, 3514) + // Minimum execution time: 4_467_000 picoseconds. + Weight::from_parts(4_655_000, 3514) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn service_page_base_completion() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `69049` - // Minimum execution time: 6_016_000 picoseconds. - Weight::from_parts(6_224_000, 69049) + // Minimum execution time: 6_103_000 picoseconds. + Weight::from_parts(6_254_000, 69049) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn service_page_base_no_completion() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `69049` - // Minimum execution time: 6_183_000 picoseconds. - Weight::from_parts(6_348_000, 69049) + // Minimum execution time: 6_320_000 picoseconds. + Weight::from_parts(6_565_000, 69049) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:0 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:0 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn service_page_item() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 112_864_000 picoseconds. - Weight::from_parts(114_269_000, 0) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Minimum execution time: 66_062_000 picoseconds. + Weight::from_parts(66_371_000, 0) } - /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:0) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn bump_service_head() -> Weight { // Proof Size summary in bytes: - // Measured: `246` + // Measured: `174` // Estimated: `3514` - // Minimum execution time: 6_665_000 picoseconds. - Weight::from_parts(7_108_000, 3514) + // Minimum execution time: 6_788_000 picoseconds. + Weight::from_parts(7_176_000, 3514) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn reap_page() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 51_420_000 picoseconds. - Weight::from_parts(52_252_000, 69049) + // Minimum execution time: 52_865_000 picoseconds. + Weight::from_parts(54_398_000, 69049) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn execute_overweight_page_removed() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 71_195_000 picoseconds. - Weight::from_parts(72_981_000, 69049) + // Minimum execution time: 69_168_000 picoseconds. + Weight::from_parts(70_560_000, 69049) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn execute_overweight_page_updated() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 83_238_000 picoseconds. - Weight::from_parts(84_422_000, 69049) + // Minimum execution time: 80_947_000 picoseconds. + Weight::from_parts(82_715_000, 69049) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `MessageQueue::ServiceHead` (r:1 w:0) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn ready_ring_knit() -> Weight { // Proof Size summary in bytes: - // Measured: `301` + // Measured: `267` // Estimated: `6038` - // Minimum execution time: 11_563_000 picoseconds. - Weight::from_parts(11_956_000, 6038) + // Minimum execution time: 12_025_000 picoseconds. + Weight::from_parts(12_597_000, 6038) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:2 w:2) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) fn ready_ring_unknit() -> Weight { // Proof Size summary in bytes: - // Measured: `301` + // Measured: `267` // Estimated: `6038` - // Minimum execution time: 10_263_000 picoseconds. - Weight::from_parts(10_638_000, 6038) + // Minimum execution time: 11_563_000 picoseconds. + Weight::from_parts(11_785_000, 6038) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn service_queue_base() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3514` - // Minimum execution time: 4_335_000 picoseconds. - Weight::from_parts(4_552_000, 3514) + // Minimum execution time: 4_467_000 picoseconds. + Weight::from_parts(4_655_000, 3514) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn service_page_base_completion() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `69049` - // Minimum execution time: 6_016_000 picoseconds. - Weight::from_parts(6_224_000, 69049) + // Minimum execution time: 6_103_000 picoseconds. + Weight::from_parts(6_254_000, 69049) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn service_page_base_no_completion() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `69049` - // Minimum execution time: 6_183_000 picoseconds. - Weight::from_parts(6_348_000, 69049) + // Minimum execution time: 6_320_000 picoseconds. + Weight::from_parts(6_565_000, 69049) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:0 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:0 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) fn service_page_item() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 112_864_000 picoseconds. - Weight::from_parts(114_269_000, 0) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Minimum execution time: 66_062_000 picoseconds. + Weight::from_parts(66_371_000, 0) } - /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:0) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) fn bump_service_head() -> Weight { // Proof Size summary in bytes: - // Measured: `246` + // Measured: `174` // Estimated: `3514` - // Minimum execution time: 6_665_000 picoseconds. - Weight::from_parts(7_108_000, 3514) + // Minimum execution time: 6_788_000 picoseconds. + Weight::from_parts(7_176_000, 3514) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn reap_page() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 51_420_000 picoseconds. - Weight::from_parts(52_252_000, 69049) + // Minimum execution time: 52_865_000 picoseconds. + Weight::from_parts(54_398_000, 69049) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn execute_overweight_page_removed() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 71_195_000 picoseconds. - Weight::from_parts(72_981_000, 69049) + // Minimum execution time: 69_168_000 picoseconds. + Weight::from_parts(70_560_000, 69049) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::Pages` (r:1 w:1) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65584), added: 68059, mode: `MaxEncodedLen`) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(49), added: 2524, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65584), added: 68059, mode: MaxEncodedLen) fn execute_overweight_page_updated() -> Weight { // Proof Size summary in bytes: // Measured: `65744` // Estimated: `69049` - // Minimum execution time: 83_238_000 picoseconds. - Weight::from_parts(84_422_000, 69049) + // Minimum execution time: 80_947_000 picoseconds. + Weight::from_parts(82_715_000, 69049) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/migrations/src/weights.rs b/substrate/frame/migrations/src/weights.rs index 9eca48ac3fd..c9b63258c44 100644 --- a/substrate/frame/migrations/src/weights.rs +++ b/substrate/frame/migrations/src/weights.rs @@ -17,29 +17,26 @@ //! Autogenerated weights for `pallet_migrations` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-12-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `loud1`, CPU: `AMD EPYC 7282 16-Core Processor` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/release/substrate-node // benchmark // pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_migrations -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/migrations/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --chain +// dev +// --pallet +// pallet-migrations +// --extrinsic +// +// --output +// weight.rs +// --template +// ../../polkadot-sdk/substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -74,10 +71,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `243` // Estimated: `67035` - // Minimum execution time: 7_932_000 picoseconds. - Weight::from_parts(8_428_000, 67035) + // Minimum execution time: 13_980_000 picoseconds. + Weight::from_parts(14_290_000, 67035) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -85,10 +82,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `109` // Estimated: `67035` - // Minimum execution time: 2_229_000 picoseconds. - Weight::from_parts(2_329_000, 67035) + // Minimum execution time: 3_770_000 picoseconds. + Weight::from_parts(4_001_000, 67035) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -99,8 +96,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `134` // Estimated: `3599` - // Minimum execution time: 6_051_000 picoseconds. - Weight::from_parts(6_483_000, 3599) + // Minimum execution time: 10_900_000 picoseconds. + Weight::from_parts(11_251_000, 3599) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -110,10 +107,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `330` - // Estimated: `3795` - // Minimum execution time: 10_066_000 picoseconds. - Weight::from_parts(10_713_000, 3795) + // Measured: `297` + // Estimated: `3762` + // Minimum execution time: 17_891_000 picoseconds. + Weight::from_parts(18_501_000, 3762) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -122,10 +119,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 10_026_000 picoseconds. - Weight::from_parts(10_379_000, 3741) + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 18_271_000 picoseconds. + Weight::from_parts(18_740_000, 3731) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -134,10 +131,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 11_680_000 picoseconds. - Weight::from_parts(12_184_000, 3741) + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 21_241_000 picoseconds. + Weight::from_parts(21_911_000, 3731) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -149,10 +146,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 12_334_000 picoseconds. - Weight::from_parts(12_899_000, 3741) + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 22_740_000 picoseconds. + Weight::from_parts(23_231_000, 3731) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -160,8 +157,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 187_000 picoseconds. - Weight::from_parts(209_000, 0) + // Minimum execution time: 440_000 picoseconds. + Weight::from_parts(500_000, 0) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -169,8 +166,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_688_000 picoseconds. - Weight::from_parts(2_874_000, 0) + // Minimum execution time: 5_751_000 picoseconds. + Weight::from_parts(5_950_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) @@ -179,8 +176,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_108_000 picoseconds. - Weight::from_parts(3_263_000, 0) + // Minimum execution time: 6_350_000 picoseconds. + Weight::from_parts(6_560_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) @@ -189,10 +186,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `251` + // Measured: `218` // Estimated: `67035` - // Minimum execution time: 5_993_000 picoseconds. - Weight::from_parts(6_359_000, 67035) + // Minimum execution time: 11_121_000 picoseconds. + Weight::from_parts(11_530_000, 67035) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) @@ -200,12 +197,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1122 + n * (271 ±0)` + // Measured: `1089 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 16_003_000 picoseconds. - Weight::from_parts(14_453_014, 3834) - // Standard Error: 3_305 - .saturating_add(Weight::from_parts(1_325_026, 0).saturating_mul(n.into())) + // Minimum execution time: 21_891_000 picoseconds. + Weight::from_parts(18_572_306, 3834) + // Standard Error: 3_236 + .saturating_add(Weight::from_parts(1_648_429, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -221,10 +218,10 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `243` // Estimated: `67035` - // Minimum execution time: 7_932_000 picoseconds. - Weight::from_parts(8_428_000, 67035) + // Minimum execution time: 13_980_000 picoseconds. + Weight::from_parts(14_290_000, 67035) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -232,10 +229,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `109` // Estimated: `67035` - // Minimum execution time: 2_229_000 picoseconds. - Weight::from_parts(2_329_000, 67035) + // Minimum execution time: 3_770_000 picoseconds. + Weight::from_parts(4_001_000, 67035) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -246,8 +243,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `134` // Estimated: `3599` - // Minimum execution time: 6_051_000 picoseconds. - Weight::from_parts(6_483_000, 3599) + // Minimum execution time: 10_900_000 picoseconds. + Weight::from_parts(11_251_000, 3599) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -257,10 +254,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `330` - // Estimated: `3795` - // Minimum execution time: 10_066_000 picoseconds. - Weight::from_parts(10_713_000, 3795) + // Measured: `297` + // Estimated: `3762` + // Minimum execution time: 17_891_000 picoseconds. + Weight::from_parts(18_501_000, 3762) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -269,10 +266,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 10_026_000 picoseconds. - Weight::from_parts(10_379_000, 3741) + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 18_271_000 picoseconds. + Weight::from_parts(18_740_000, 3731) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -281,10 +278,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 11_680_000 picoseconds. - Weight::from_parts(12_184_000, 3741) + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 21_241_000 picoseconds. + Weight::from_parts(21_911_000, 3731) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -296,10 +293,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 12_334_000 picoseconds. - Weight::from_parts(12_899_000, 3741) + // Measured: `243` + // Estimated: `3731` + // Minimum execution time: 22_740_000 picoseconds. + Weight::from_parts(23_231_000, 3731) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -307,8 +304,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 187_000 picoseconds. - Weight::from_parts(209_000, 0) + // Minimum execution time: 440_000 picoseconds. + Weight::from_parts(500_000, 0) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -316,8 +313,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_688_000 picoseconds. - Weight::from_parts(2_874_000, 0) + // Minimum execution time: 5_751_000 picoseconds. + Weight::from_parts(5_950_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) @@ -326,8 +323,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_108_000 picoseconds. - Weight::from_parts(3_263_000, 0) + // Minimum execution time: 6_350_000 picoseconds. + Weight::from_parts(6_560_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) @@ -336,10 +333,10 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `251` + // Measured: `218` // Estimated: `67035` - // Minimum execution time: 5_993_000 picoseconds. - Weight::from_parts(6_359_000, 67035) + // Minimum execution time: 11_121_000 picoseconds. + Weight::from_parts(11_530_000, 67035) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) @@ -347,12 +344,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1122 + n * (271 ±0)` + // Measured: `1089 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 16_003_000 picoseconds. - Weight::from_parts(14_453_014, 3834) - // Standard Error: 3_305 - .saturating_add(Weight::from_parts(1_325_026, 0).saturating_mul(n.into())) + // Minimum execution time: 21_891_000 picoseconds. + Weight::from_parts(18_572_306, 3834) + // Standard Error: 3_236 + .saturating_add(Weight::from_parts(1_648_429, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) diff --git a/substrate/frame/multisig/src/weights.rs b/substrate/frame/multisig/src/weights.rs index 4cbe7bb03b7..7b87d258d38 100644 --- a/substrate/frame/multisig/src/weights.rs +++ b/substrate/frame/multisig/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_multisig` +//! Autogenerated weights for pallet_multisig //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/multisig/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/multisig/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_multisig`. +/// Weight functions needed for pallet_multisig. pub trait WeightInfo { fn as_multi_threshold_1(z: u32, ) -> Weight; fn as_multi_create(s: u32, z: u32, ) -> Weight; @@ -60,238 +61,220 @@ pub trait WeightInfo { fn cancel_as_multi(s: u32, ) -> Weight; } -/// Weights for `pallet_multisig` using the Substrate node and recommended hardware. +/// Weights for pallet_multisig using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 18_893_000 picoseconds. - Weight::from_parts(20_278_307, 3997) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 13_452_000 picoseconds. + Weight::from_parts(14_425_869, 0) // Standard Error: 4 - .saturating_add(Weight::from_parts(488, 0).saturating_mul(z.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(Weight::from_parts(493, 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`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `301 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 39_478_000 picoseconds. - Weight::from_parts(29_195_487, 6811) - // Standard Error: 739 - .saturating_add(Weight::from_parts(118_766, 0).saturating_mul(s.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_511, 0).saturating_mul(z.into())) + // Minimum execution time: 46_012_000 picoseconds. + Weight::from_parts(34_797_344, 6811) + // Standard Error: 833 + .saturating_add(Weight::from_parts(127_671, 0).saturating_mul(s.into())) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_498, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `320` // Estimated: `6811` - // Minimum execution time: 26_401_000 picoseconds. - Weight::from_parts(17_277_296, 6811) - // Standard Error: 492 - .saturating_add(Weight::from_parts(101_763, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_486, 0).saturating_mul(z.into())) + // Minimum execution time: 29_834_000 picoseconds. + Weight::from_parts(20_189_154, 6811) + // Standard Error: 637 + .saturating_add(Weight::from_parts(110_080, 0).saturating_mul(s.into())) + // Standard Error: 6 + .saturating_add(Weight::from_parts(1_483, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `571 + s * (33 ±0)` + // Measured: `426 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 52_430_000 picoseconds. - Weight::from_parts(40_585_478, 6811) - // Standard Error: 1_240 - .saturating_add(Weight::from_parts(161_405, 0).saturating_mul(s.into())) + // Minimum execution time: 51_464_000 picoseconds. + Weight::from_parts(39_246_644, 6811) + // Standard Error: 1_251 + .saturating_add(Weight::from_parts(143_313, 0).saturating_mul(s.into())) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_547, 0).saturating_mul(z.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(Weight::from_parts(1_523, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `301 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 27_797_000 picoseconds. - Weight::from_parts(29_064_584, 6811) - // Standard Error: 817 - .saturating_add(Weight::from_parts(108_179, 0).saturating_mul(s.into())) + // Minimum execution time: 33_275_000 picoseconds. + Weight::from_parts(34_073_221, 6811) + // Standard Error: 1_163 + .saturating_add(Weight::from_parts(124_815, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `320` // Estimated: `6811` - // Minimum execution time: 15_236_000 picoseconds. - Weight::from_parts(16_360_247, 6811) - // Standard Error: 584 - .saturating_add(Weight::from_parts(94_917, 0).saturating_mul(s.into())) + // Minimum execution time: 18_411_000 picoseconds. + Weight::from_parts(19_431_787, 6811) + // Standard Error: 694 + .saturating_add(Weight::from_parts(107_220, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `492 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 28_730_000 picoseconds. - Weight::from_parts(30_056_661, 6811) - // Standard Error: 792 - .saturating_add(Weight::from_parts(108_212, 0).saturating_mul(s.into())) + // Minimum execution time: 33_985_000 picoseconds. + Weight::from_parts(35_547_970, 6811) + // Standard Error: 1_135 + .saturating_add(Weight::from_parts(116_537, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 18_893_000 picoseconds. - Weight::from_parts(20_278_307, 3997) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 13_452_000 picoseconds. + Weight::from_parts(14_425_869, 0) // Standard Error: 4 - .saturating_add(Weight::from_parts(488, 0).saturating_mul(z.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(Weight::from_parts(493, 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`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `301 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 39_478_000 picoseconds. - Weight::from_parts(29_195_487, 6811) - // Standard Error: 739 - .saturating_add(Weight::from_parts(118_766, 0).saturating_mul(s.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_511, 0).saturating_mul(z.into())) + // Minimum execution time: 46_012_000 picoseconds. + Weight::from_parts(34_797_344, 6811) + // Standard Error: 833 + .saturating_add(Weight::from_parts(127_671, 0).saturating_mul(s.into())) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_498, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `320` // Estimated: `6811` - // Minimum execution time: 26_401_000 picoseconds. - Weight::from_parts(17_277_296, 6811) - // Standard Error: 492 - .saturating_add(Weight::from_parts(101_763, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_486, 0).saturating_mul(z.into())) + // Minimum execution time: 29_834_000 picoseconds. + Weight::from_parts(20_189_154, 6811) + // Standard Error: 637 + .saturating_add(Weight::from_parts(110_080, 0).saturating_mul(s.into())) + // Standard Error: 6 + .saturating_add(Weight::from_parts(1_483, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `571 + s * (33 ±0)` + // Measured: `426 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 52_430_000 picoseconds. - Weight::from_parts(40_585_478, 6811) - // Standard Error: 1_240 - .saturating_add(Weight::from_parts(161_405, 0).saturating_mul(s.into())) + // Minimum execution time: 51_464_000 picoseconds. + Weight::from_parts(39_246_644, 6811) + // Standard Error: 1_251 + .saturating_add(Weight::from_parts(143_313, 0).saturating_mul(s.into())) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_547, 0).saturating_mul(z.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(Weight::from_parts(1_523, 0).saturating_mul(z.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `301 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 27_797_000 picoseconds. - Weight::from_parts(29_064_584, 6811) - // Standard Error: 817 - .saturating_add(Weight::from_parts(108_179, 0).saturating_mul(s.into())) + // Minimum execution time: 33_275_000 picoseconds. + Weight::from_parts(34_073_221, 6811) + // Standard Error: 1_163 + .saturating_add(Weight::from_parts(124_815, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `320` // Estimated: `6811` - // Minimum execution time: 15_236_000 picoseconds. - Weight::from_parts(16_360_247, 6811) - // Standard Error: 584 - .saturating_add(Weight::from_parts(94_917, 0).saturating_mul(s.into())) + // Minimum execution time: 18_411_000 picoseconds. + Weight::from_parts(19_431_787, 6811) + // Standard Error: 694 + .saturating_add(Weight::from_parts(107_220, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Multisig::Multisigs` (r:1 w:1) - /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `492 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 28_730_000 picoseconds. - Weight::from_parts(30_056_661, 6811) - // Standard Error: 792 - .saturating_add(Weight::from_parts(108_212, 0).saturating_mul(s.into())) + // Minimum execution time: 33_985_000 picoseconds. + Weight::from_parts(35_547_970, 6811) + // Standard Error: 1_135 + .saturating_add(Weight::from_parts(116_537, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/nft-fractionalization/src/weights.rs b/substrate/frame/nft-fractionalization/src/weights.rs index 07872ebaea9..ebb4aa0fbcf 100644 --- a/substrate/frame/nft-fractionalization/src/weights.rs +++ b/substrate/frame/nft-fractionalization/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_nft_fractionalization` +//! Autogenerated weights for pallet_nft_fractionalization //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/nft-fractionalization/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/nft-fractionalization/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,136 +50,136 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_nft_fractionalization`. +/// Weight functions needed for pallet_nft_fractionalization. pub trait WeightInfo { fn fractionalize() -> Weight; fn unify() -> Weight; } -/// Weights for `pallet_nft_fractionalization` using the Substrate node and recommended hardware. +/// Weights for pallet_nft_fractionalization using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) - /// Storage: `NftFractionalization::NftToAsset` (r:0 w:1) - /// Proof: `NftFractionalization::NftToAsset` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: NftFractionalization NftToAsset (r:0 w:1) + /// Proof: NftFractionalization NftToAsset (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) fn fractionalize() -> Weight { // Proof Size summary in bytes: // Measured: `609` // Estimated: `4326` - // Minimum execution time: 164_764_000 picoseconds. - Weight::from_parts(168_243_000, 4326) + // Minimum execution time: 187_416_000 picoseconds. + Weight::from_parts(191_131_000, 4326) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } - /// Storage: `NftFractionalization::NftToAsset` (r:1 w:1) - /// Proof: `NftFractionalization::NftToAsset` (`max_values`: None, `max_size`: Some(92), added: 2567, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: NftFractionalization NftToAsset (r:1 w:1) + /// Proof: NftFractionalization NftToAsset (max_values: None, max_size: Some(92), added: 2567, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn unify() -> Weight { // Proof Size summary in bytes: // Measured: `1422` // Estimated: `4326` - // Minimum execution time: 120_036_000 picoseconds. - Weight::from_parts(123_550_000, 4326) + // Minimum execution time: 134_159_000 picoseconds. + Weight::from_parts(136_621_000, 4326) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Assets::Metadata` (r:1 w:1) - /// Proof: `Assets::Metadata` (`max_values`: None, `max_size`: Some(140), added: 2615, mode: `MaxEncodedLen`) - /// Storage: `NftFractionalization::NftToAsset` (r:0 w:1) - /// Proof: `NftFractionalization::NftToAsset` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: NftFractionalization NftToAsset (r:0 w:1) + /// Proof: NftFractionalization NftToAsset (max_values: None, max_size: Some(92), added: 2567, mode: MaxEncodedLen) fn fractionalize() -> Weight { // Proof Size summary in bytes: // Measured: `609` // Estimated: `4326` - // Minimum execution time: 164_764_000 picoseconds. - Weight::from_parts(168_243_000, 4326) + // Minimum execution time: 187_416_000 picoseconds. + Weight::from_parts(191_131_000, 4326) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } - /// Storage: `NftFractionalization::NftToAsset` (r:1 w:1) - /// Proof: `NftFractionalization::NftToAsset` (`max_values`: None, `max_size`: Some(92), added: 2567, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: NftFractionalization NftToAsset (r:1 w:1) + /// Proof: NftFractionalization NftToAsset (max_values: None, max_size: Some(92), added: 2567, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn unify() -> Weight { // Proof Size summary in bytes: // Measured: `1422` // Estimated: `4326` - // Minimum execution time: 120_036_000 picoseconds. - Weight::from_parts(123_550_000, 4326) + // Minimum execution time: 134_159_000 picoseconds. + Weight::from_parts(136_621_000, 4326) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } diff --git a/substrate/frame/nfts/src/weights.rs b/substrate/frame/nfts/src/weights.rs index 4fcc1e601f4..6b8c577bb12 100644 --- a/substrate/frame/nfts/src/weights.rs +++ b/substrate/frame/nfts/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_nfts` +//! Autogenerated weights for pallet_nfts //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -37,9 +37,9 @@ // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/nfts/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/nfts/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +49,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_nfts`. +/// Weight functions needed for pallet_nfts. pub trait WeightInfo { fn create() -> Weight; fn force_create() -> Weight; @@ -92,568 +92,564 @@ pub trait WeightInfo { fn set_attributes_pre_signed(n: u32, ) -> Weight; } -/// Weights for `pallet_nfts` using the Substrate node and recommended hardware. +/// Weights for pallet_nfts using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Nfts::NextCollectionId` (r:1 w:1) - /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:1) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts NextCollectionId (r:1 w:1) + /// Proof: Nfts NextCollectionId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:0 w:1) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:0 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:1) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3549` - // Minimum execution time: 34_035_000 picoseconds. - Weight::from_parts(35_228_000, 3549) + // Minimum execution time: 40_489_000 picoseconds. + Weight::from_parts(41_320_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Nfts::NextCollectionId` (r:1 w:1) - /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:1) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts NextCollectionId (r:1 w:1) + /// Proof: Nfts NextCollectionId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:0 w:1) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:0 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:1) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3549` - // Minimum execution time: 19_430_000 picoseconds. - Weight::from_parts(20_054_000, 3549) + // Minimum execution time: 23_257_000 picoseconds. + Weight::from_parts(23_770_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1001 w:1000) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) - /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:1) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:0) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:1 w:1) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1001 w:1000) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1000 w:1000) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts CollectionMetadataOf (r:0 w:1) + /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:0 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:1) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32204 + a * (366 ±0)` - // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 1_249_733_000 picoseconds. - Weight::from_parts(1_293_703_849, 2523990) - // Standard Error: 4_764 - .saturating_add(Weight::from_parts(6_433_523, 0).saturating_mul(a.into())) + // Measured: `32220 + a * (332 ±0)` + // Estimated: `2523990 + a * (2921 ±0)` + // Minimum execution time: 1_310_198_000 picoseconds. + Weight::from_parts(1_479_261_043, 2523990) + // Standard Error: 4_415 + .saturating_add(Weight::from_parts(6_016_212, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1004_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) - .saturating_add(Weight::from_parts(0, 2954).saturating_mul(a.into())) - } - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + .saturating_add(Weight::from_parts(0, 2921).saturating_mul(a.into())) + } + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) fn mint() -> Weight { // Proof Size summary in bytes: // Measured: `455` // Estimated: `4326` - // Minimum execution time: 48_645_000 picoseconds. - Weight::from_parts(50_287_000, 4326) + // Minimum execution time: 51_910_000 picoseconds. + Weight::from_parts(53_441_000, 4326) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) fn force_mint() -> Weight { // Proof Size summary in bytes: // Measured: `455` // Estimated: `4326` - // Minimum execution time: 46_688_000 picoseconds. - Weight::from_parts(47_680_000, 4326) + // Minimum execution time: 50_168_000 picoseconds. + Weight::from_parts(51_380_000, 4326) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Nfts::Attribute` (r:1 w:0) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:0) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: Nfts ItemAttributesApprovalsOf (r:0 w:1) + /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn burn() -> Weight { // Proof Size summary in bytes: // Measured: `564` // Estimated: `4326` - // Minimum execution time: 51_771_000 picoseconds. - Weight::from_parts(53_492_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Minimum execution time: 50_738_000 picoseconds. + Weight::from_parts(51_850_000, 4326) + .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:0) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:2) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:0) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:2) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `593` // Estimated: `4326` - // Minimum execution time: 39_166_000 picoseconds. - Weight::from_parts(40_128_000, 4326) + // Minimum execution time: 41_055_000 picoseconds. + Weight::from_parts(42_336_000, 4326) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:5000 w:5000) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:5000 w:5000) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `763 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 13_804_000 picoseconds. - Weight::from_parts(14_159_000, 3549) - // Standard Error: 13_812 - .saturating_add(Weight::from_parts(14_661_284, 0).saturating_mul(i.into())) + // Minimum execution time: 15_688_000 picoseconds. + Weight::from_parts(15_921_000, 3549) + // Standard Error: 14_827 + .saturating_add(Weight::from_parts(17_105_395, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3336).saturating_mul(i.into())) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 17_485_000 picoseconds. - Weight::from_parts(18_412_000, 3534) + // Minimum execution time: 19_981_000 picoseconds. + Weight::from_parts(20_676_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 17_335_000 picoseconds. - Weight::from_parts(18_543_000, 3534) + // Minimum execution time: 19_911_000 picoseconds. + Weight::from_parts(20_612_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn lock_collection() -> Weight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3549` - // Minimum execution time: 14_608_000 picoseconds. - Weight::from_parts(15_696_000, 3549) + // Minimum execution time: 16_441_000 picoseconds. + Weight::from_parts(16_890_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) - /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:2) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts OwnershipAcceptance (r:1 w:1) + /// Proof: Nfts OwnershipAcceptance (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:2) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `562` - // Estimated: `3593` - // Minimum execution time: 25_686_000 picoseconds. - Weight::from_parts(26_433_000, 3593) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Measured: `388` + // Estimated: `3549` + // Minimum execution time: 22_610_000 picoseconds. + Weight::from_parts(23_422_000, 3549) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:2 w:4) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn set_team() -> Weight { // Proof Size summary in bytes: // Measured: `369` // Estimated: `6078` - // Minimum execution time: 37_192_000 picoseconds. - Weight::from_parts(38_561_000, 6078) + // Minimum execution time: 39_739_000 picoseconds. + Weight::from_parts(41_306_000, 6078) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:2) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:2) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: // Measured: `311` // Estimated: `3549` - // Minimum execution time: 15_401_000 picoseconds. - Weight::from_parts(15_826_000, 3549) + // Minimum execution time: 17_685_000 picoseconds. + Weight::from_parts(18_258_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:0 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `276` // Estimated: `3549` - // Minimum execution time: 11_683_000 picoseconds. - Weight::from_parts(12_255_000, 3549) + // Minimum execution time: 13_734_000 picoseconds. + Weight::from_parts(14_337_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 16_899_000 picoseconds. - Weight::from_parts(17_404_000, 3534) + // Minimum execution time: 19_269_000 picoseconds. + Weight::from_parts(19_859_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) fn set_attribute() -> Weight { // Proof Size summary in bytes: // Measured: `539` - // Estimated: `3944` - // Minimum execution time: 46_768_000 picoseconds. - Weight::from_parts(47_834_000, 3944) + // Estimated: `3911` + // Minimum execution time: 51_540_000 picoseconds. + Weight::from_parts(52_663_000, 3911) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: // Measured: `344` - // Estimated: `3944` - // Minimum execution time: 23_356_000 picoseconds. - Weight::from_parts(24_528_000, 3944) + // Estimated: `3911` + // Minimum execution time: 26_529_000 picoseconds. + Weight::from_parts(27_305_000, 3911) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `983` - // Estimated: `3944` - // Minimum execution time: 43_061_000 picoseconds. - Weight::from_parts(44_024_000, 3944) + // Measured: `950` + // Estimated: `3911` + // Minimum execution time: 46_951_000 picoseconds. + Weight::from_parts(48_481_000, 3911) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) + /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: // Measured: `381` // Estimated: `4326` - // Minimum execution time: 14_929_000 picoseconds. - Weight::from_parts(15_344_000, 4326) + // Minimum execution time: 17_222_000 picoseconds. + Weight::from_parts(17_819_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1001 w:1000) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) + /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1001 w:1000) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + n * (398 ±0)` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 23_707_000 picoseconds. - Weight::from_parts(24_688_000, 4326) - // Standard Error: 3_813 - .saturating_add(Weight::from_parts(6_422_256, 0).saturating_mul(n.into())) + // Measured: `837 + n * (364 ±0)` + // Estimated: `4326 + n * (2921 ±0)` + // Minimum execution time: 26_185_000 picoseconds. + Weight::from_parts(27_038_000, 4326) + // Standard Error: 2_378 + .saturating_add(Weight::from_parts(6_067_888, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) - } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) + } + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:1) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn set_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `539` - // Estimated: `3812` - // Minimum execution time: 37_882_000 picoseconds. - Weight::from_parts(39_222_000, 3812) + // Estimated: `3605` + // Minimum execution time: 42_120_000 picoseconds. + Weight::from_parts(43_627_000, 3605) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:1) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `849` - // Estimated: `3812` - // Minimum execution time: 36_629_000 picoseconds. - Weight::from_parts(37_351_000, 3812) + // Measured: `642` + // Estimated: `3605` + // Minimum execution time: 40_732_000 picoseconds. + Weight::from_parts(42_760_000, 3605) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) - /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionMetadataOf (r:1 w:1) + /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `398` - // Estimated: `3759` - // Minimum execution time: 34_853_000 picoseconds. - Weight::from_parts(35_914_000, 3759) + // Estimated: `3552` + // Minimum execution time: 39_443_000 picoseconds. + Weight::from_parts(40_482_000, 3552) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) - /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts CollectionMetadataOf (r:1 w:1) + /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `716` - // Estimated: `3759` - // Minimum execution time: 33_759_000 picoseconds. - Weight::from_parts(34_729_000, 3759) + // Measured: `509` + // Estimated: `3552` + // Minimum execution time: 37_676_000 picoseconds. + Weight::from_parts(39_527_000, 3552) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn approve_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `410` // Estimated: `4326` - // Minimum execution time: 17_583_000 picoseconds. - Weight::from_parts(18_675_000, 4326) + // Minimum execution time: 20_787_000 picoseconds. + Weight::from_parts(21_315_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) fn cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `4326` - // Minimum execution time: 15_036_000 picoseconds. - Weight::from_parts(15_995_000, 4326) + // Minimum execution time: 18_200_000 picoseconds. + Weight::from_parts(19_064_000, 4326) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `4326` - // Minimum execution time: 14_666_000 picoseconds. - Weight::from_parts(15_152_000, 4326) + // Minimum execution time: 17_128_000 picoseconds. + Weight::from_parts(17_952_000, 4326) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) - /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: Nfts OwnershipAcceptance (r:1 w:1) + /// Proof: Nfts OwnershipAcceptance (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3517` - // Minimum execution time: 12_393_000 picoseconds. - Weight::from_parts(12_895_000, 3517) + // Minimum execution time: 14_667_000 picoseconds. + Weight::from_parts(15_262_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionConfigOf (r:1 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3549` - // Minimum execution time: 16_034_000 picoseconds. - Weight::from_parts(16_617_000, 3549) + // Minimum execution time: 18_435_000 picoseconds. + Weight::from_parts(18_775_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: // Measured: `323` // Estimated: `3538` - // Minimum execution time: 15_812_000 picoseconds. - Weight::from_parts(16_644_000, 3538) + // Minimum execution time: 18_125_000 picoseconds. + Weight::from_parts(18_415_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) fn set_price() -> Weight { // Proof Size summary in bytes: // Measured: `518` // Estimated: `4326` - // Minimum execution time: 21_650_000 picoseconds. - Weight::from_parts(22_443_000, 4326) + // Minimum execution time: 23_237_000 picoseconds. + Weight::from_parts(24_128_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:0) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:2) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:1 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:0) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:2) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn buy_item() -> Weight { // Proof Size summary in bytes: // Measured: `705` // Estimated: `4326` - // Minimum execution time: 49_463_000 picoseconds. - Weight::from_parts(50_937_000, 4326) + // Minimum execution time: 53_291_000 picoseconds. + Weight::from_parts(54_614_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -662,685 +658,681 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_029_000 picoseconds. - Weight::from_parts(3_749_829, 0) - // Standard Error: 8_497 - .saturating_add(Weight::from_parts(1_913_514, 0).saturating_mul(n.into())) - } - /// Storage: `Nfts::Item` (r:2 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + // Minimum execution time: 2_192_000 picoseconds. + Weight::from_parts(4_039_901, 0) + // Standard Error: 10_309 + .saturating_add(Weight::from_parts(3_934_017, 0).saturating_mul(n.into())) + } + /// Storage: Nfts Item (r:2 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn create_swap() -> Weight { // Proof Size summary in bytes: // Measured: `494` // Estimated: `7662` - // Minimum execution time: 18_181_000 picoseconds. - Weight::from_parts(18_698_000, 7662) + // Minimum execution time: 21_011_000 picoseconds. + Weight::from_parts(22_065_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::PendingSwapOf` (r:1 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: Nfts PendingSwapOf (r:1 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) fn cancel_swap() -> Weight { // Proof Size summary in bytes: // Measured: `513` // Estimated: `4326` - // Minimum execution time: 18_228_000 picoseconds. - Weight::from_parts(18_940_000, 4326) + // Minimum execution time: 21_423_000 picoseconds. + Weight::from_parts(21_743_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:2 w:2) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:2 w:0) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:4) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:2 w:2) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:1 w:2) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:2 w:0) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:2 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:4) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:2) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) fn claim_swap() -> Weight { // Proof Size summary in bytes: // Measured: `834` // Estimated: `7662` - // Minimum execution time: 77_983_000 picoseconds. - Weight::from_parts(79_887_000, 7662) + // Minimum execution time: 86_059_000 picoseconds. + Weight::from_parts(88_401_000, 7662) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:10 w:10) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:2 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:10 w:10) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:1) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `629` - // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 126_998_000 picoseconds. - Weight::from_parts(134_149_389, 6078) - // Standard Error: 33_180 - .saturating_add(Weight::from_parts(30_711_206, 0).saturating_mul(n.into())) + // Estimated: `6078 + n * (2921 ±0)` + // Minimum execution time: 146_746_000 picoseconds. + Weight::from_parts(152_885_862, 6078) + // Standard Error: 40_442 + .saturating_add(Weight::from_parts(32_887_800, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) - } - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:10 w:10) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) + } + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) + /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:10 w:10) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `659` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 66_213_000 picoseconds. - Weight::from_parts(81_661_819, 4326) - // Standard Error: 87_003 - .saturating_add(Weight::from_parts(29_550_476, 0).saturating_mul(n.into())) + // Estimated: `4326 + n * (2921 ±0)` + // Minimum execution time: 83_960_000 picoseconds. + Weight::from_parts(98_609_885, 4326) + // Standard Error: 85_991 + .saturating_add(Weight::from_parts(32_633_495, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Nfts::NextCollectionId` (r:1 w:1) - /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:1) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts NextCollectionId (r:1 w:1) + /// Proof: Nfts NextCollectionId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:0 w:1) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:0 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:1) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `216` // Estimated: `3549` - // Minimum execution time: 34_035_000 picoseconds. - Weight::from_parts(35_228_000, 3549) + // Minimum execution time: 40_489_000 picoseconds. + Weight::from_parts(41_320_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Nfts::NextCollectionId` (r:1 w:1) - /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:1) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts NextCollectionId (r:1 w:1) + /// Proof: Nfts NextCollectionId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:0 w:1) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:0 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:1) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3549` - // Minimum execution time: 19_430_000 picoseconds. - Weight::from_parts(20_054_000, 3549) + // Minimum execution time: 23_257_000 picoseconds. + Weight::from_parts(23_770_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1001 w:1000) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) - /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:1) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:0) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:1 w:1) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1001 w:1000) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1000 w:1000) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts CollectionMetadataOf (r:0 w:1) + /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:0 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:1) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32204 + a * (366 ±0)` - // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 1_249_733_000 picoseconds. - Weight::from_parts(1_293_703_849, 2523990) - // Standard Error: 4_764 - .saturating_add(Weight::from_parts(6_433_523, 0).saturating_mul(a.into())) + // Measured: `32220 + a * (332 ±0)` + // Estimated: `2523990 + a * (2921 ±0)` + // Minimum execution time: 1_310_198_000 picoseconds. + Weight::from_parts(1_479_261_043, 2523990) + // Standard Error: 4_415 + .saturating_add(Weight::from_parts(6_016_212, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(1004_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) - .saturating_add(Weight::from_parts(0, 2954).saturating_mul(a.into())) - } - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + .saturating_add(Weight::from_parts(0, 2921).saturating_mul(a.into())) + } + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) fn mint() -> Weight { // Proof Size summary in bytes: // Measured: `455` // Estimated: `4326` - // Minimum execution time: 48_645_000 picoseconds. - Weight::from_parts(50_287_000, 4326) + // Minimum execution time: 51_910_000 picoseconds. + Weight::from_parts(53_441_000, 4326) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) fn force_mint() -> Weight { // Proof Size summary in bytes: // Measured: `455` // Estimated: `4326` - // Minimum execution time: 46_688_000 picoseconds. - Weight::from_parts(47_680_000, 4326) + // Minimum execution time: 50_168_000 picoseconds. + Weight::from_parts(51_380_000, 4326) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Nfts::Attribute` (r:1 w:0) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:0) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: Nfts ItemAttributesApprovalsOf (r:0 w:1) + /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn burn() -> Weight { // Proof Size summary in bytes: // Measured: `564` // Estimated: `4326` - // Minimum execution time: 51_771_000 picoseconds. - Weight::from_parts(53_492_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Minimum execution time: 50_738_000 picoseconds. + Weight::from_parts(51_850_000, 4326) + .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:0) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:2) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:0) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:2) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn transfer() -> Weight { // Proof Size summary in bytes: // Measured: `593` // Estimated: `4326` - // Minimum execution time: 39_166_000 picoseconds. - Weight::from_parts(40_128_000, 4326) + // Minimum execution time: 41_055_000 picoseconds. + Weight::from_parts(42_336_000, 4326) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:5000 w:5000) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:5000 w:5000) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `763 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 13_804_000 picoseconds. - Weight::from_parts(14_159_000, 3549) - // Standard Error: 13_812 - .saturating_add(Weight::from_parts(14_661_284, 0).saturating_mul(i.into())) + // Minimum execution time: 15_688_000 picoseconds. + Weight::from_parts(15_921_000, 3549) + // Standard Error: 14_827 + .saturating_add(Weight::from_parts(17_105_395, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3336).saturating_mul(i.into())) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 17_485_000 picoseconds. - Weight::from_parts(18_412_000, 3534) + // Minimum execution time: 19_981_000 picoseconds. + Weight::from_parts(20_676_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 17_335_000 picoseconds. - Weight::from_parts(18_543_000, 3534) + // Minimum execution time: 19_911_000 picoseconds. + Weight::from_parts(20_612_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn lock_collection() -> Weight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3549` - // Minimum execution time: 14_608_000 picoseconds. - Weight::from_parts(15_696_000, 3549) + // Minimum execution time: 16_441_000 picoseconds. + Weight::from_parts(16_890_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) - /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:2) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts OwnershipAcceptance (r:1 w:1) + /// Proof: Nfts OwnershipAcceptance (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:2) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `562` - // Estimated: `3593` - // Minimum execution time: 25_686_000 picoseconds. - Weight::from_parts(26_433_000, 3593) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Measured: `388` + // Estimated: `3549` + // Minimum execution time: 22_610_000 picoseconds. + Weight::from_parts(23_422_000, 3549) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:2 w:4) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn set_team() -> Weight { // Proof Size summary in bytes: // Measured: `369` // Estimated: `6078` - // Minimum execution time: 37_192_000 picoseconds. - Weight::from_parts(38_561_000, 6078) + // Minimum execution time: 39_739_000 picoseconds. + Weight::from_parts(41_306_000, 6078) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionAccount` (r:0 w:2) - /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionAccount (r:0 w:2) + /// Proof: Nfts CollectionAccount (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: // Measured: `311` // Estimated: `3549` - // Minimum execution time: 15_401_000 picoseconds. - Weight::from_parts(15_826_000, 3549) + // Minimum execution time: 17_685_000 picoseconds. + Weight::from_parts(18_258_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:0 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `276` // Estimated: `3549` - // Minimum execution time: 11_683_000 picoseconds. - Weight::from_parts(12_255_000, 3549) + // Minimum execution time: 13_734_000 picoseconds. + Weight::from_parts(14_337_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: // Measured: `435` // Estimated: `3534` - // Minimum execution time: 16_899_000 picoseconds. - Weight::from_parts(17_404_000, 3534) + // Minimum execution time: 19_269_000 picoseconds. + Weight::from_parts(19_859_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) fn set_attribute() -> Weight { // Proof Size summary in bytes: // Measured: `539` - // Estimated: `3944` - // Minimum execution time: 46_768_000 picoseconds. - Weight::from_parts(47_834_000, 3944) + // Estimated: `3911` + // Minimum execution time: 51_540_000 picoseconds. + Weight::from_parts(52_663_000, 3911) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: // Measured: `344` - // Estimated: `3944` - // Minimum execution time: 23_356_000 picoseconds. - Weight::from_parts(24_528_000, 3944) + // Estimated: `3911` + // Minimum execution time: 26_529_000 picoseconds. + Weight::from_parts(27_305_000, 3911) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::Attribute` (r:1 w:1) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: Nfts Attribute (r:1 w:1) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `983` - // Estimated: `3944` - // Minimum execution time: 43_061_000 picoseconds. - Weight::from_parts(44_024_000, 3944) + // Measured: `950` + // Estimated: `3911` + // Minimum execution time: 46_951_000 picoseconds. + Weight::from_parts(48_481_000, 3911) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) + /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: // Measured: `381` // Estimated: `4326` - // Minimum execution time: 14_929_000 picoseconds. - Weight::from_parts(15_344_000, 4326) + // Minimum execution time: 17_222_000 picoseconds. + Weight::from_parts(17_819_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1001 w:1000) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) + /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1001 w:1000) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + n * (398 ±0)` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 23_707_000 picoseconds. - Weight::from_parts(24_688_000, 4326) - // Standard Error: 3_813 - .saturating_add(Weight::from_parts(6_422_256, 0).saturating_mul(n.into())) + // Measured: `837 + n * (364 ±0)` + // Estimated: `4326 + n * (2921 ±0)` + // Minimum execution time: 26_185_000 picoseconds. + Weight::from_parts(27_038_000, 4326) + // Standard Error: 2_378 + .saturating_add(Weight::from_parts(6_067_888, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) - } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) + } + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:1) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) fn set_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `539` - // Estimated: `3812` - // Minimum execution time: 37_882_000 picoseconds. - Weight::from_parts(39_222_000, 3812) + // Estimated: `3605` + // Minimum execution time: 42_120_000 picoseconds. + Weight::from_parts(43_627_000, 3605) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:1) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `849` - // Estimated: `3812` - // Minimum execution time: 36_629_000 picoseconds. - Weight::from_parts(37_351_000, 3812) + // Measured: `642` + // Estimated: `3605` + // Minimum execution time: 40_732_000 picoseconds. + Weight::from_parts(42_760_000, 3605) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) - /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionMetadataOf (r:1 w:1) + /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `398` - // Estimated: `3759` - // Minimum execution time: 34_853_000 picoseconds. - Weight::from_parts(35_914_000, 3759) + // Estimated: `3552` + // Minimum execution time: 39_443_000 picoseconds. + Weight::from_parts(40_482_000, 3552) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) - /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts CollectionMetadataOf (r:1 w:1) + /// Proof: Nfts CollectionMetadataOf (max_values: None, max_size: Some(87), added: 2562, mode: MaxEncodedLen) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `716` - // Estimated: `3759` - // Minimum execution time: 33_759_000 picoseconds. - Weight::from_parts(34_729_000, 3759) + // Measured: `509` + // Estimated: `3552` + // Minimum execution time: 37_676_000 picoseconds. + Weight::from_parts(39_527_000, 3552) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn approve_transfer() -> Weight { // Proof Size summary in bytes: // Measured: `410` // Estimated: `4326` - // Minimum execution time: 17_583_000 picoseconds. - Weight::from_parts(18_675_000, 4326) + // Minimum execution time: 20_787_000 picoseconds. + Weight::from_parts(21_315_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) fn cancel_approval() -> Weight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `4326` - // Minimum execution time: 15_036_000 picoseconds. - Weight::from_parts(15_995_000, 4326) + // Minimum execution time: 18_200_000 picoseconds. + Weight::from_parts(19_064_000, 4326) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `4326` - // Minimum execution time: 14_666_000 picoseconds. - Weight::from_parts(15_152_000, 4326) + // Minimum execution time: 17_128_000 picoseconds. + Weight::from_parts(17_952_000, 4326) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) - /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: Nfts OwnershipAcceptance (r:1 w:1) + /// Proof: Nfts OwnershipAcceptance (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `3517` - // Minimum execution time: 12_393_000 picoseconds. - Weight::from_parts(12_895_000, 3517) + // Minimum execution time: 14_667_000 picoseconds. + Weight::from_parts(15_262_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionConfigOf (r:1 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3549` - // Minimum execution time: 16_034_000 picoseconds. - Weight::from_parts(16_617_000, 3549) + // Minimum execution time: 18_435_000 picoseconds. + Weight::from_parts(18_775_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:1 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:1) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: // Measured: `323` // Estimated: `3538` - // Minimum execution time: 15_812_000 picoseconds. - Weight::from_parts(16_644_000, 3538) + // Minimum execution time: 18_125_000 picoseconds. + Weight::from_parts(18_415_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) fn set_price() -> Weight { // Proof Size summary in bytes: // Measured: `518` // Estimated: `4326` - // Minimum execution time: 21_650_000 picoseconds. - Weight::from_parts(22_443_000, 4326) + // Minimum execution time: 23_237_000 picoseconds. + Weight::from_parts(24_128_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:1 w:0) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:2) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:1 w:1) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:1 w:0) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:2) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn buy_item() -> Weight { // Proof Size summary in bytes: // Measured: `705` // Estimated: `4326` - // Minimum execution time: 49_463_000 picoseconds. - Weight::from_parts(50_937_000, 4326) + // Minimum execution time: 53_291_000 picoseconds. + Weight::from_parts(54_614_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1349,120 +1341,120 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_029_000 picoseconds. - Weight::from_parts(3_749_829, 0) - // Standard Error: 8_497 - .saturating_add(Weight::from_parts(1_913_514, 0).saturating_mul(n.into())) - } - /// Storage: `Nfts::Item` (r:2 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + // Minimum execution time: 2_192_000 picoseconds. + Weight::from_parts(4_039_901, 0) + // Standard Error: 10_309 + .saturating_add(Weight::from_parts(3_934_017, 0).saturating_mul(n.into())) + } + /// Storage: Nfts Item (r:2 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:0 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) fn create_swap() -> Weight { // Proof Size summary in bytes: // Measured: `494` // Estimated: `7662` - // Minimum execution time: 18_181_000 picoseconds. - Weight::from_parts(18_698_000, 7662) + // Minimum execution time: 21_011_000 picoseconds. + Weight::from_parts(22_065_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::PendingSwapOf` (r:1 w:1) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: Nfts PendingSwapOf (r:1 w:1) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) fn cancel_swap() -> Weight { // Proof Size summary in bytes: // Measured: `513` // Estimated: `4326` - // Minimum execution time: 18_228_000 picoseconds. - Weight::from_parts(18_940_000, 4326) + // Minimum execution time: 21_423_000 picoseconds. + Weight::from_parts(21_743_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nfts::Item` (r:2 w:2) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) - /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:2 w:0) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:4) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) - /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) + /// Storage: Nfts Item (r:2 w:2) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts PendingSwapOf (r:1 w:2) + /// Proof: Nfts PendingSwapOf (max_values: None, max_size: Some(71), added: 2546, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:0) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:2 w:0) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:2 w:0) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:4) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + /// Storage: Nfts ItemPriceOf (r:0 w:2) + /// Proof: Nfts ItemPriceOf (max_values: None, max_size: Some(89), added: 2564, mode: MaxEncodedLen) fn claim_swap() -> Weight { // Proof Size summary in bytes: // Measured: `834` // Estimated: `7662` - // Minimum execution time: 77_983_000 picoseconds. - Weight::from_parts(79_887_000, 7662) + // Minimum execution time: 86_059_000 picoseconds. + Weight::from_parts(88_401_000, 7662) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } - /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) - /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Item` (r:1 w:1) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:10 w:10) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) - /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Account` (r:0 w:1) - /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) + /// Storage: Nfts CollectionRoleOf (r:2 w:0) + /// Proof: Nfts CollectionRoleOf (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Item (r:1 w:1) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts ItemConfigOf (r:1 w:1) + /// Proof: Nfts ItemConfigOf (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:10 w:10) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: Nfts ItemMetadataOf (r:1 w:1) + /// Proof: Nfts ItemMetadataOf (max_values: None, max_size: Some(140), added: 2615, mode: MaxEncodedLen) + /// Storage: Nfts Account (r:0 w:1) + /// Proof: Nfts Account (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `629` - // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 126_998_000 picoseconds. - Weight::from_parts(134_149_389, 6078) - // Standard Error: 33_180 - .saturating_add(Weight::from_parts(30_711_206, 0).saturating_mul(n.into())) + // Estimated: `6078 + n * (2921 ±0)` + // Minimum execution time: 146_746_000 picoseconds. + Weight::from_parts(152_885_862, 6078) + // Standard Error: 40_442 + .saturating_add(Weight::from_parts(32_887_800, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) - } - /// Storage: `Nfts::Item` (r:1 w:0) - /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) - /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) - /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Attribute` (r:10 w:10) - /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) + } + /// Storage: Nfts Item (r:1 w:0) + /// Proof: Nfts Item (max_values: None, max_size: Some(861), added: 3336, mode: MaxEncodedLen) + /// Storage: Nfts ItemAttributesApprovalsOf (r:1 w:1) + /// Proof: Nfts ItemAttributesApprovalsOf (max_values: None, max_size: Some(681), added: 3156, mode: MaxEncodedLen) + /// Storage: Nfts CollectionConfigOf (r:1 w:0) + /// Proof: Nfts CollectionConfigOf (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: Nfts Collection (r:1 w:1) + /// Proof: Nfts Collection (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Nfts Attribute (r:10 w:10) + /// Proof: Nfts Attribute (max_values: None, max_size: Some(446), added: 2921, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `659` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 66_213_000 picoseconds. - Weight::from_parts(81_661_819, 4326) - // Standard Error: 87_003 - .saturating_add(Weight::from_parts(29_550_476, 0).saturating_mul(n.into())) + // Estimated: `4326 + n * (2921 ±0)` + // Minimum execution time: 83_960_000 picoseconds. + Weight::from_parts(98_609_885, 4326) + // Standard Error: 85_991 + .saturating_add(Weight::from_parts(32_633_495, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(0, 2921).saturating_mul(n.into())) } } diff --git a/substrate/frame/nis/src/weights.rs b/substrate/frame/nis/src/weights.rs index 63908271391..cba2f004905 100644 --- a/substrate/frame/nis/src/weights.rs +++ b/substrate/frame/nis/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_nis` +//! Autogenerated weights for pallet_nis //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/nis/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/nis/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_nis`. +/// Weight functions needed for pallet_nis. pub trait WeightInfo { fn place_bid(l: u32, ) -> Weight; fn place_bid_max() -> Weight; @@ -64,367 +65,367 @@ pub trait WeightInfo { fn process_bid() -> Weight; } -/// Weights for `pallet_nis` using the Substrate node and recommended hardware. +/// Weights for pallet_nis using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) /// The range of component `l` is `[0, 999]`. fn place_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6176 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 47_908_000 picoseconds. - Weight::from_parts(50_096_676, 51487) - // Standard Error: 208 - .saturating_add(Weight::from_parts(41_318, 0).saturating_mul(l.into())) + // Minimum execution time: 49_410_000 picoseconds. + Weight::from_parts(57_832_282, 51487) + // Standard Error: 288 + .saturating_add(Weight::from_parts(51_621, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) fn place_bid_max() -> Weight { // Proof Size summary in bytes: // Measured: `54178` // Estimated: `51487` - // Minimum execution time: 100_836_000 picoseconds. - Weight::from_parts(102_497_000, 51487) + // Minimum execution time: 119_696_000 picoseconds. + Weight::from_parts(121_838_000, 51487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) /// The range of component `l` is `[1, 1000]`. fn retract_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6176 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 45_830_000 picoseconds. - Weight::from_parts(46_667_676, 51487) - // Standard Error: 130 - .saturating_add(Weight::from_parts(33_007, 0).saturating_mul(l.into())) + // Minimum execution time: 50_843_000 picoseconds. + Weight::from_parts(54_237_365, 51487) + // Standard Error: 243 + .saturating_add(Weight::from_parts(67_732, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Nis::Summary` (r:1 w:0) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Nis Summary (r:1 w:0) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn fund_deficit() -> Weight { // Proof Size summary in bytes: // Measured: `191` // Estimated: `3593` - // Minimum execution time: 30_440_000 picoseconds. - Weight::from_parts(31_240_000, 3593) + // Minimum execution time: 40_752_000 picoseconds. + Weight::from_parts(41_899_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn communify() -> Weight { // Proof Size summary in bytes: // Measured: `668` // Estimated: `3675` - // Minimum execution time: 71_017_000 picoseconds. - Weight::from_parts(72_504_000, 3675) + // Minimum execution time: 79_779_000 picoseconds. + Weight::from_parts(82_478_000, 3675) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) fn privatize() -> Weight { // Proof Size summary in bytes: // Measured: `829` // Estimated: `3675` - // Minimum execution time: 89_138_000 picoseconds. - Weight::from_parts(91_290_000, 3675) + // Minimum execution time: 99_588_000 picoseconds. + Weight::from_parts(102_340_000, 3675) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) fn thaw_private() -> Weight { // Proof Size summary in bytes: // Measured: `354` - // Estimated: `3658` - // Minimum execution time: 47_917_000 picoseconds. - Weight::from_parts(49_121_000, 3658) + // Estimated: `3593` + // Minimum execution time: 53_094_000 picoseconds. + Weight::from_parts(54_543_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn thaw_communal() -> Weight { // Proof Size summary in bytes: // Measured: `773` // Estimated: `3675` - // Minimum execution time: 91_320_000 picoseconds. - Weight::from_parts(93_080_000, 3675) + // Minimum execution time: 107_248_000 picoseconds. + Weight::from_parts(109_923_000, 3675) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) fn process_queues() -> Weight { // Proof Size summary in bytes: // Measured: `6624` // Estimated: `7487` - // Minimum execution time: 20_117_000 picoseconds. - Weight::from_parts(20_829_000, 7487) + // Minimum execution time: 27_169_000 picoseconds. + Weight::from_parts(29_201_000, 7487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) fn process_queue() -> Weight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `51487` - // Minimum execution time: 4_460_000 picoseconds. - Weight::from_parts(4_797_000, 51487) + // Minimum execution time: 4_540_000 picoseconds. + Weight::from_parts(4_699_000, 51487) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Nis::Receipts` (r:0 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:0 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) fn process_bid() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_609_000 picoseconds. - Weight::from_parts(4_834_000, 0) + // Minimum execution time: 7_085_000 picoseconds. + Weight::from_parts(7_336_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) /// The range of component `l` is `[0, 999]`. fn place_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6176 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 47_908_000 picoseconds. - Weight::from_parts(50_096_676, 51487) - // Standard Error: 208 - .saturating_add(Weight::from_parts(41_318, 0).saturating_mul(l.into())) + // Minimum execution time: 49_410_000 picoseconds. + Weight::from_parts(57_832_282, 51487) + // Standard Error: 288 + .saturating_add(Weight::from_parts(51_621, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) fn place_bid_max() -> Weight { // Proof Size summary in bytes: // Measured: `54178` // Estimated: `51487` - // Minimum execution time: 100_836_000 picoseconds. - Weight::from_parts(102_497_000, 51487) + // Minimum execution time: 119_696_000 picoseconds. + Weight::from_parts(121_838_000, 51487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) /// The range of component `l` is `[1, 1000]`. fn retract_bid(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6176 + l * (48 ±0)` // Estimated: `51487` - // Minimum execution time: 45_830_000 picoseconds. - Weight::from_parts(46_667_676, 51487) - // Standard Error: 130 - .saturating_add(Weight::from_parts(33_007, 0).saturating_mul(l.into())) + // Minimum execution time: 50_843_000 picoseconds. + Weight::from_parts(54_237_365, 51487) + // Standard Error: 243 + .saturating_add(Weight::from_parts(67_732, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Nis::Summary` (r:1 w:0) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Nis Summary (r:1 w:0) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn fund_deficit() -> Weight { // Proof Size summary in bytes: // Measured: `191` // Estimated: `3593` - // Minimum execution time: 30_440_000 picoseconds. - Weight::from_parts(31_240_000, 3593) + // Minimum execution time: 40_752_000 picoseconds. + Weight::from_parts(41_899_000, 3593) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) fn communify() -> Weight { // Proof Size summary in bytes: // Measured: `668` // Estimated: `3675` - // Minimum execution time: 71_017_000 picoseconds. - Weight::from_parts(72_504_000, 3675) + // Minimum execution time: 79_779_000 picoseconds. + Weight::from_parts(82_478_000, 3675) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) fn privatize() -> Weight { // Proof Size summary in bytes: // Measured: `829` // Estimated: `3675` - // Minimum execution time: 89_138_000 picoseconds. - Weight::from_parts(91_290_000, 3675) + // Minimum execution time: 99_588_000 picoseconds. + Weight::from_parts(102_340_000, 3675) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Balances Holds (r:1 w:1) + /// Proof: Balances Holds (max_values: None, max_size: Some(85), added: 2560, mode: MaxEncodedLen) fn thaw_private() -> Weight { // Proof Size summary in bytes: // Measured: `354` - // Estimated: `3658` - // Minimum execution time: 47_917_000 picoseconds. - Weight::from_parts(49_121_000, 3658) + // Estimated: `3593` + // Minimum execution time: 53_094_000 picoseconds. + Weight::from_parts(54_543_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Nis::Receipts` (r:1 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:1 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, 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:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(134), added: 2609, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn thaw_communal() -> Weight { // Proof Size summary in bytes: // Measured: `773` // Estimated: `3675` - // Minimum execution time: 91_320_000 picoseconds. - Weight::from_parts(93_080_000, 3675) + // Minimum execution time: 107_248_000 picoseconds. + Weight::from_parts(109_923_000, 3675) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Nis::Summary` (r:1 w:1) - /// Proof: `Nis::Summary` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Nis::QueueTotals` (r:1 w:1) - /// Proof: `Nis::QueueTotals` (`max_values`: Some(1), `max_size`: Some(6002), added: 6497, mode: `MaxEncodedLen`) + /// Storage: Nis Summary (r:1 w:1) + /// Proof: Nis Summary (max_values: Some(1), max_size: Some(40), added: 535, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Nis QueueTotals (r:1 w:1) + /// Proof: Nis QueueTotals (max_values: Some(1), max_size: Some(6002), added: 6497, mode: MaxEncodedLen) fn process_queues() -> Weight { // Proof Size summary in bytes: // Measured: `6624` // Estimated: `7487` - // Minimum execution time: 20_117_000 picoseconds. - Weight::from_parts(20_829_000, 7487) + // Minimum execution time: 27_169_000 picoseconds. + Weight::from_parts(29_201_000, 7487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Nis::Queues` (r:1 w:1) - /// Proof: `Nis::Queues` (`max_values`: None, `max_size`: Some(48022), added: 50497, mode: `MaxEncodedLen`) + /// Storage: Nis Queues (r:1 w:1) + /// Proof: Nis Queues (max_values: None, max_size: Some(48022), added: 50497, mode: MaxEncodedLen) fn process_queue() -> Weight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `51487` - // Minimum execution time: 4_460_000 picoseconds. - Weight::from_parts(4_797_000, 51487) + // Minimum execution time: 4_540_000 picoseconds. + Weight::from_parts(4_699_000, 51487) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Nis::Receipts` (r:0 w:1) - /// Proof: `Nis::Receipts` (`max_values`: None, `max_size`: Some(81), added: 2556, mode: `MaxEncodedLen`) + /// Storage: Nis Receipts (r:0 w:1) + /// Proof: Nis Receipts (max_values: None, max_size: Some(81), added: 2556, mode: MaxEncodedLen) fn process_bid() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_609_000 picoseconds. - Weight::from_parts(4_834_000, 0) + // Minimum execution time: 7_085_000 picoseconds. + Weight::from_parts(7_336_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/nomination-pools/src/weights.rs b/substrate/frame/nomination-pools/src/weights.rs index 987ddd71703..0b8c1d22fa1 100644 --- a/substrate/frame/nomination-pools/src/weights.rs +++ b/substrate/frame/nomination-pools/src/weights.rs @@ -25,6 +25,7 @@ // Executed Command: // target/production/substrate-node +// target/production/substrate-node // benchmark // pallet // --steps=50 @@ -35,8 +36,12 @@ // --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json // --pallet=pallet_nomination_pools // --chain=dev +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_nomination_pools +// --chain=dev // --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/nomination-pools/src/weights.rs +// --output=./substrate/frame/nomination-pools/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -259,14 +264,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1848` + // Measured: `1817` // Estimated: `4764` // Minimum execution time: 64_787_000 picoseconds. Weight::from_parts(67_920_914, 4764) @@ -293,8 +296,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) @@ -304,7 +305,7 @@ impl WeightInfo for SubstrateWeight { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2238` + // Measured: `2207` // Estimated: `27847` // Minimum execution time: 124_990_000 picoseconds. Weight::from_parts(129_041_398, 27847) @@ -337,12 +338,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:0) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::RewardPools` (r:1 w:1) @@ -849,14 +850,12 @@ impl WeightInfo for () { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1848` + // Measured: `1817` // Estimated: `4764` // Minimum execution time: 64_787_000 picoseconds. Weight::from_parts(67_920_914, 4764) @@ -883,8 +882,6 @@ impl WeightInfo for () { /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) @@ -894,7 +891,7 @@ impl WeightInfo for () { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2238` + // Measured: `2207` // Estimated: `27847` // Minimum execution time: 124_990_000 picoseconds. Weight::from_parts(129_041_398, 27847) @@ -927,12 +924,12 @@ impl WeightInfo for () { /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) /// Storage: `Staking::Nominators` (r:1 w:0) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::TotalValueLocked` (r:1 w:1) /// Proof: `NominationPools::TotalValueLocked` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForPoolMembers` (r:1 w:1) /// Proof: `NominationPools::CounterForPoolMembers` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:1) + /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// Storage: `NominationPools::CounterForReversePoolIdLookup` (r:1 w:1) /// Proof: `NominationPools::CounterForReversePoolIdLookup` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `NominationPools::RewardPools` (r:1 w:1) diff --git a/substrate/frame/offences/benchmarking/src/mock.rs b/substrate/frame/offences/benchmarking/src/mock.rs index b3260f0841f..01ad8d64f10 100644 --- a/substrate/frame/offences/benchmarking/src/mock.rs +++ b/substrate/frame/offences/benchmarking/src/mock.rs @@ -148,7 +148,7 @@ parameter_types! { pub static ElectionsBounds: ElectionBounds = ElectionBoundsBuilder::default().build(); } -pub type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; +pub type Extrinsic = sp_runtime::testing::TestXt; pub struct OnChainSeqPhragmen; impl onchain::Config for OnChainSeqPhragmen { diff --git a/substrate/frame/parameters/src/weights.rs b/substrate/frame/parameters/src/weights.rs index 340eb9e31b7..6746960b1b7 100644 --- a/substrate/frame/parameters/src/weights.rs +++ b/substrate/frame/parameters/src/weights.rs @@ -18,27 +18,25 @@ //! Autogenerated weights for `pallet_parameters` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-02-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_parameters -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/parameters/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_parameters +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/parameters/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -57,30 +55,22 @@ pub trait WeightInfo { /// Weights for `pallet_parameters` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Parameters::Parameters` (r:1 w:1) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn set_parameter() -> Weight { // Proof Size summary in bytes: - // Measured: `3` - // Estimated: `3501` - // Minimum execution time: 8_400_000 picoseconds. - Weight::from_parts(8_682_000, 3501) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) } } // For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: `Parameters::Parameters` (r:1 w:1) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) fn set_parameter() -> Weight { // Proof Size summary in bytes: - // Measured: `3` - // Estimated: `3501` - // Minimum execution time: 8_400_000 picoseconds. - Weight::from_parts(8_682_000, 3501) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) } } diff --git a/substrate/frame/preimage/src/weights.rs b/substrate/frame/preimage/src/weights.rs index 6167cd53029..c11ab74c1e5 100644 --- a/substrate/frame/preimage/src/weights.rs +++ b/substrate/frame/preimage/src/weights.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_preimage` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-09-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-mia4uyug-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_preimage -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/preimage/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_preimage +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/preimage/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -72,209 +70,200 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `112` - // Estimated: `6012` - // Minimum execution time: 48_893_000 picoseconds. - Weight::from_parts(44_072_327, 6012) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_684, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Measured: `42` + // Estimated: `3556` + // Minimum execution time: 15_936_000 picoseconds. + Weight::from_parts(16_271_000, 3556) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_916, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 15_675_000 picoseconds. - Weight::from_parts(4_564_145, 3556) + // Minimum execution time: 16_468_000 picoseconds. + Weight::from_parts(17_031_000, 3556) // Standard Error: 2 - .saturating_add(Weight::from_parts(1_678, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_948, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 14_959_000 picoseconds. - Weight::from_parts(15_335_000, 3556) + // Minimum execution time: 16_342_000 picoseconds. + Weight::from_parts(16_535_000, 3556) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_687, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_906, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `311` - // Estimated: `3658` - // Minimum execution time: 47_378_000 picoseconds. - Weight::from_parts(48_776_000, 3658) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Measured: `172` + // Estimated: `3556` + // Minimum execution time: 31_047_000 picoseconds. + Weight::from_parts(34_099_000, 3556) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `144` // Estimated: `3556` - // Minimum execution time: 20_939_000 picoseconds. - Weight::from_parts(21_577_000, 3556) + // Minimum execution time: 32_559_000 picoseconds. + Weight::from_parts(36_677_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn request_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `255` + // Measured: `172` // Estimated: `3556` - // Minimum execution time: 17_945_000 picoseconds. - Weight::from_parts(18_448_000, 3556) + // Minimum execution time: 27_887_000 picoseconds. + Weight::from_parts(30_303_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn request_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `144` // Estimated: `3556` - // Minimum execution time: 12_132_000 picoseconds. - Weight::from_parts(12_710_000, 3556) + // Minimum execution time: 17_256_000 picoseconds. + Weight::from_parts(19_481_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn request_unnoted_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `109` + // Measured: `42` // Estimated: `3556` - // Minimum execution time: 13_014_000 picoseconds. - Weight::from_parts(13_726_000, 3556) + // Minimum execution time: 22_344_000 picoseconds. + Weight::from_parts(23_868_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn request_requested_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 9_785_000 picoseconds. - Weight::from_parts(10_266_000, 3556) + // Minimum execution time: 10_542_000 picoseconds. + Weight::from_parts(11_571_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unrequest_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `144` // Estimated: `3556` - // Minimum execution time: 18_764_000 picoseconds. - Weight::from_parts(19_635_000, 3556) + // Minimum execution time: 29_054_000 picoseconds. + Weight::from_parts(32_996_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn unrequest_unnoted_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 9_624_000 picoseconds. - Weight::from_parts(10_044_000, 3556) + // Minimum execution time: 10_775_000 picoseconds. + Weight::from_parts(11_937_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn unrequest_multi_referenced_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 9_432_000 picoseconds. - Weight::from_parts(9_991_000, 3556) + // Minimum execution time: 10_696_000 picoseconds. + Weight::from_parts(11_717_000, 3556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Preimage::StatusFor` (r:1023 w:1023) + /// Storage: `Preimage::StatusFor` (r:1024 w:1024) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1023 w:1023) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1023 w:1023) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:0 w:1023) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// The range of component `n` is `[1, 1024]`. + /// Storage: `Preimage::RequestStatusFor` (r:0 w:1024) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1024]`. fn ensure_updated(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + n * (227 ±0)` - // Estimated: `6012 + n * (2668 ±0)` - // Minimum execution time: 54_056_000 picoseconds. - Weight::from_parts(54_912_000, 6012) - // Standard Error: 42_469 - .saturating_add(Weight::from_parts(50_710_258, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2668).saturating_mul(n.into())) + // Measured: `193 + n * (91 ±0)` + // Estimated: `3593 + n * (2566 ±0)` + // Minimum execution time: 2_452_000 picoseconds. + Weight::from_parts(2_641_000, 3593) + // Standard Error: 19_797 + .saturating_add(Weight::from_parts(15_620_946, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2566).saturating_mul(n.into())) } } @@ -283,208 +272,199 @@ impl WeightInfo for () { /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `112` - // Estimated: `6012` - // Minimum execution time: 48_893_000 picoseconds. - Weight::from_parts(44_072_327, 6012) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_684, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Measured: `42` + // Estimated: `3556` + // Minimum execution time: 15_936_000 picoseconds. + Weight::from_parts(16_271_000, 3556) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_916, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 15_675_000 picoseconds. - Weight::from_parts(4_564_145, 3556) + // Minimum execution time: 16_468_000 picoseconds. + Weight::from_parts(17_031_000, 3556) // Standard Error: 2 - .saturating_add(Weight::from_parts(1_678, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_948, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 14_959_000 picoseconds. - Weight::from_parts(15_335_000, 3556) + // Minimum execution time: 16_342_000 picoseconds. + Weight::from_parts(16_535_000, 3556) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_687, 0).saturating_mul(s.into())) + .saturating_add(Weight::from_parts(1_906, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `311` - // Estimated: `3658` - // Minimum execution time: 47_378_000 picoseconds. - Weight::from_parts(48_776_000, 3658) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Measured: `172` + // Estimated: `3556` + // Minimum execution time: 31_047_000 picoseconds. + Weight::from_parts(34_099_000, 3556) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unnote_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `144` // Estimated: `3556` - // Minimum execution time: 20_939_000 picoseconds. - Weight::from_parts(21_577_000, 3556) + // Minimum execution time: 32_559_000 picoseconds. + Weight::from_parts(36_677_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn request_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `255` + // Measured: `172` // Estimated: `3556` - // Minimum execution time: 17_945_000 picoseconds. - Weight::from_parts(18_448_000, 3556) + // Minimum execution time: 27_887_000 picoseconds. + Weight::from_parts(30_303_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn request_no_deposit_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `144` // Estimated: `3556` - // Minimum execution time: 12_132_000 picoseconds. - Weight::from_parts(12_710_000, 3556) + // Minimum execution time: 17_256_000 picoseconds. + Weight::from_parts(19_481_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn request_unnoted_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `109` + // Measured: `42` // Estimated: `3556` - // Minimum execution time: 13_014_000 picoseconds. - Weight::from_parts(13_726_000, 3556) + // Minimum execution time: 22_344_000 picoseconds. + Weight::from_parts(23_868_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn request_requested_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 9_785_000 picoseconds. - Weight::from_parts(10_266_000, 3556) + // Minimum execution time: 10_542_000 picoseconds. + Weight::from_parts(11_571_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) /// Storage: `Preimage::PreimageFor` (r:0 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `MaxEncodedLen`) fn unrequest_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `211` + // Measured: `144` // Estimated: `3556` - // Minimum execution time: 18_764_000 picoseconds. - Weight::from_parts(19_635_000, 3556) + // Minimum execution time: 29_054_000 picoseconds. + Weight::from_parts(32_996_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn unrequest_unnoted_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 9_624_000 picoseconds. - Weight::from_parts(10_044_000, 3556) + // Minimum execution time: 10_775_000 picoseconds. + Weight::from_parts(11_937_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Preimage::StatusFor` (r:1 w:0) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) fn unrequest_multi_referenced_preimage() -> Weight { // Proof Size summary in bytes: - // Measured: `173` + // Measured: `106` // Estimated: `3556` - // Minimum execution time: 9_432_000 picoseconds. - Weight::from_parts(9_991_000, 3556) + // Minimum execution time: 10_696_000 picoseconds. + Weight::from_parts(11_717_000, 3556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Preimage::StatusFor` (r:1023 w:1023) + /// Storage: `Preimage::StatusFor` (r:1024 w:1024) /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1023 w:1023) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Parameters::Parameters` (r:2 w:0) - /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1023 w:1023) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:0 w:1023) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// The range of component `n` is `[1, 1024]`. + /// Storage: `Preimage::RequestStatusFor` (r:0 w:1024) + /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(75), added: 2550, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1024]`. fn ensure_updated(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + n * (227 ±0)` - // Estimated: `6012 + n * (2668 ±0)` - // Minimum execution time: 54_056_000 picoseconds. - Weight::from_parts(54_912_000, 6012) - // Standard Error: 42_469 - .saturating_add(Weight::from_parts(50_710_258, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes((4_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2668).saturating_mul(n.into())) + // Measured: `193 + n * (91 ±0)` + // Estimated: `3593 + n * (2566 ±0)` + // Minimum execution time: 2_452_000 picoseconds. + Weight::from_parts(2_641_000, 3593) + // Standard Error: 19_797 + .saturating_add(Weight::from_parts(15_620_946, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2566).saturating_mul(n.into())) } } diff --git a/substrate/frame/proxy/src/weights.rs b/substrate/frame/proxy/src/weights.rs index 3c37c91d500..f30fe73d27a 100644 --- a/substrate/frame/proxy/src/weights.rs +++ b/substrate/frame/proxy/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_proxy` +//! Autogenerated weights for pallet_proxy //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/proxy/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/proxy/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_proxy`. +/// Weight functions needed for pallet_proxy. pub trait WeightInfo { fn proxy(p: u32, ) -> Weight; fn proxy_announced(a: u32, p: u32, ) -> Weight; @@ -63,352 +64,336 @@ pub trait WeightInfo { fn kill_pure(p: u32, ) -> Weight; } -/// Weights for `pallet_proxy` using the Substrate node and recommended hardware. +/// Weights for pallet_proxy using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `306 + p * (37 ±0)` + // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 18_437_000 picoseconds. - Weight::from_parts(19_610_577, 4706) - // Standard Error: 2_531 - .saturating_add(Weight::from_parts(26_001, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 15_182_000 picoseconds. + Weight::from_parts(15_919_146, 4706) + // Standard Error: 1_586 + .saturating_add(Weight::from_parts(31_768, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `633 + a * (68 ±0) + p * (37 ±0)` + // Measured: `488 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 40_426_000 picoseconds. - Weight::from_parts(40_200_295, 5698) - // Standard Error: 2_922 - .saturating_add(Weight::from_parts(161_885, 0).saturating_mul(a.into())) - // Standard Error: 3_019 - .saturating_add(Weight::from_parts(69_710, 0).saturating_mul(p.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Minimum execution time: 40_256_000 picoseconds. + Weight::from_parts(40_373_648, 5698) + // Standard Error: 3_978 + .saturating_add(Weight::from_parts(166_936, 0).saturating_mul(a.into())) + // Standard Error: 4_110 + .saturating_add(Weight::from_parts(54_329, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn remove_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 21_905_000 picoseconds. - Weight::from_parts(22_717_430, 5698) - // Standard Error: 2_004 - .saturating_add(Weight::from_parts(153_390, 0).saturating_mul(a.into())) - // Standard Error: 2_071 - .saturating_add(Weight::from_parts(5_676, 0).saturating_mul(p.into())) + // Minimum execution time: 25_040_000 picoseconds. + Weight::from_parts(25_112_188, 5698) + // Standard Error: 2_143 + .saturating_add(Weight::from_parts(189_027, 0).saturating_mul(a.into())) + // Standard Error: 2_214 + .saturating_add(Weight::from_parts(26_683, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn reject_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 21_974_000 picoseconds. - Weight::from_parts(22_484_324, 5698) - // Standard Error: 1_846 - .saturating_add(Weight::from_parts(153_904, 0).saturating_mul(a.into())) - // Standard Error: 1_907 - .saturating_add(Weight::from_parts(9_616, 0).saturating_mul(p.into())) + // Minimum execution time: 24_884_000 picoseconds. + Weight::from_parts(25_359_291, 5698) + // Standard Error: 2_019 + .saturating_add(Weight::from_parts(181_470, 0).saturating_mul(a.into())) + // Standard Error: 2_086 + .saturating_add(Weight::from_parts(17_725, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `420 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 30_454_000 picoseconds. - Weight::from_parts(32_128_158, 5698) - // Standard Error: 3_778 - .saturating_add(Weight::from_parts(137_366, 0).saturating_mul(a.into())) - // Standard Error: 3_904 - .saturating_add(Weight::from_parts(53_040, 0).saturating_mul(p.into())) + // Minimum execution time: 35_039_000 picoseconds. + Weight::from_parts(36_727_868, 5698) + // Standard Error: 4_463 + .saturating_add(Weight::from_parts(167_060, 0).saturating_mul(a.into())) + // Standard Error: 4_611 + .saturating_add(Weight::from_parts(59_836, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 21_391_000 picoseconds. - Weight::from_parts(22_202_614, 4706) - // Standard Error: 1_750 - .saturating_add(Weight::from_parts(49_639, 0).saturating_mul(p.into())) + // Minimum execution time: 25_697_000 picoseconds. + Weight::from_parts(26_611_090, 4706) + // Standard Error: 2_306 + .saturating_add(Weight::from_parts(85_165, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 21_375_000 picoseconds. - Weight::from_parts(22_392_601, 4706) - // Standard Error: 2_415 - .saturating_add(Weight::from_parts(40_345, 0).saturating_mul(p.into())) + // Minimum execution time: 25_638_000 picoseconds. + Weight::from_parts(26_904_510, 4706) + // Standard Error: 2_669 + .saturating_add(Weight::from_parts(61_668, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 19_833_000 picoseconds. - Weight::from_parts(20_839_747, 4706) - // Standard Error: 1_742 - .saturating_add(Weight::from_parts(40_874, 0).saturating_mul(p.into())) + // Minimum execution time: 22_737_000 picoseconds. + Weight::from_parts(23_618_441, 4706) + // Standard Error: 1_729 + .saturating_add(Weight::from_parts(44_009, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `173` // Estimated: `4706` - // Minimum execution time: 22_231_000 picoseconds. - Weight::from_parts(23_370_995, 4706) - // Standard Error: 1_521 - .saturating_add(Weight::from_parts(4_892, 0).saturating_mul(p.into())) + // Minimum execution time: 27_364_000 picoseconds. + Weight::from_parts(28_632_271, 4706) + // Standard Error: 1_613 + .saturating_add(Weight::from_parts(2_453, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `198 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 20_614_000 picoseconds. - Weight::from_parts(21_845_970, 4706) - // Standard Error: 1_636 - .saturating_add(Weight::from_parts(34_480, 0).saturating_mul(p.into())) + // Minimum execution time: 23_552_000 picoseconds. + Weight::from_parts(24_874_553, 4706) + // Standard Error: 1_919 + .saturating_add(Weight::from_parts(38_799, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `306 + p * (37 ±0)` + // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 18_437_000 picoseconds. - Weight::from_parts(19_610_577, 4706) - // Standard Error: 2_531 - .saturating_add(Weight::from_parts(26_001, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Minimum execution time: 15_182_000 picoseconds. + Weight::from_parts(15_919_146, 4706) + // Standard Error: 1_586 + .saturating_add(Weight::from_parts(31_768, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `633 + a * (68 ±0) + p * (37 ±0)` + // Measured: `488 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 40_426_000 picoseconds. - Weight::from_parts(40_200_295, 5698) - // Standard Error: 2_922 - .saturating_add(Weight::from_parts(161_885, 0).saturating_mul(a.into())) - // Standard Error: 3_019 - .saturating_add(Weight::from_parts(69_710, 0).saturating_mul(p.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Minimum execution time: 40_256_000 picoseconds. + Weight::from_parts(40_373_648, 5698) + // Standard Error: 3_978 + .saturating_add(Weight::from_parts(166_936, 0).saturating_mul(a.into())) + // Standard Error: 4_110 + .saturating_add(Weight::from_parts(54_329, 0).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn remove_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 21_905_000 picoseconds. - Weight::from_parts(22_717_430, 5698) - // Standard Error: 2_004 - .saturating_add(Weight::from_parts(153_390, 0).saturating_mul(a.into())) - // Standard Error: 2_071 - .saturating_add(Weight::from_parts(5_676, 0).saturating_mul(p.into())) + // Minimum execution time: 25_040_000 picoseconds. + Weight::from_parts(25_112_188, 5698) + // Standard Error: 2_143 + .saturating_add(Weight::from_parts(189_027, 0).saturating_mul(a.into())) + // Standard Error: 2_214 + .saturating_add(Weight::from_parts(26_683, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn reject_announcement(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `403 + a * (68 ±0)` // Estimated: `5698` - // Minimum execution time: 21_974_000 picoseconds. - Weight::from_parts(22_484_324, 5698) - // Standard Error: 1_846 - .saturating_add(Weight::from_parts(153_904, 0).saturating_mul(a.into())) - // Standard Error: 1_907 - .saturating_add(Weight::from_parts(9_616, 0).saturating_mul(p.into())) + // Minimum execution time: 24_884_000 picoseconds. + Weight::from_parts(25_359_291, 5698) + // Standard Error: 2_019 + .saturating_add(Weight::from_parts(181_470, 0).saturating_mul(a.into())) + // Standard Error: 2_086 + .saturating_add(Weight::from_parts(17_725, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:0) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) - /// Storage: `Proxy::Announcements` (r:1 w:1) - /// Proof: `Proxy::Announcements` (`max_values`: None, `max_size`: Some(2233), added: 4708, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(2233), added: 4708, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `420 + a * (68 ±0) + p * (37 ±0)` // Estimated: `5698` - // Minimum execution time: 30_454_000 picoseconds. - Weight::from_parts(32_128_158, 5698) - // Standard Error: 3_778 - .saturating_add(Weight::from_parts(137_366, 0).saturating_mul(a.into())) - // Standard Error: 3_904 - .saturating_add(Weight::from_parts(53_040, 0).saturating_mul(p.into())) + // Minimum execution time: 35_039_000 picoseconds. + Weight::from_parts(36_727_868, 5698) + // Standard Error: 4_463 + .saturating_add(Weight::from_parts(167_060, 0).saturating_mul(a.into())) + // Standard Error: 4_611 + .saturating_add(Weight::from_parts(59_836, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 21_391_000 picoseconds. - Weight::from_parts(22_202_614, 4706) - // Standard Error: 1_750 - .saturating_add(Weight::from_parts(49_639, 0).saturating_mul(p.into())) + // Minimum execution time: 25_697_000 picoseconds. + Weight::from_parts(26_611_090, 4706) + // Standard Error: 2_306 + .saturating_add(Weight::from_parts(85_165, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 21_375_000 picoseconds. - Weight::from_parts(22_392_601, 4706) - // Standard Error: 2_415 - .saturating_add(Weight::from_parts(40_345, 0).saturating_mul(p.into())) + // Minimum execution time: 25_638_000 picoseconds. + Weight::from_parts(26_904_510, 4706) + // Standard Error: 2_669 + .saturating_add(Weight::from_parts(61_668, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `161 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 19_833_000 picoseconds. - Weight::from_parts(20_839_747, 4706) - // Standard Error: 1_742 - .saturating_add(Weight::from_parts(40_874, 0).saturating_mul(p.into())) + // Minimum execution time: 22_737_000 picoseconds. + Weight::from_parts(23_618_441, 4706) + // Standard Error: 1_729 + .saturating_add(Weight::from_parts(44_009, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `173` // Estimated: `4706` - // Minimum execution time: 22_231_000 picoseconds. - Weight::from_parts(23_370_995, 4706) - // Standard Error: 1_521 - .saturating_add(Weight::from_parts(4_892, 0).saturating_mul(p.into())) + // Minimum execution time: 27_364_000 picoseconds. + Weight::from_parts(28_632_271, 4706) + // Standard Error: 1_613 + .saturating_add(Weight::from_parts(2_453, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Proxy::Proxies` (r:1 w:1) - /// Proof: `Proxy::Proxies` (`max_values`: None, `max_size`: Some(1241), added: 3716, mode: `MaxEncodedLen`) + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(1241), added: 3716, mode: MaxEncodedLen) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `198 + p * (37 ±0)` // Estimated: `4706` - // Minimum execution time: 20_614_000 picoseconds. - Weight::from_parts(21_845_970, 4706) - // Standard Error: 1_636 - .saturating_add(Weight::from_parts(34_480, 0).saturating_mul(p.into())) + // Minimum execution time: 23_552_000 picoseconds. + Weight::from_parts(24_874_553, 4706) + // Standard Error: 1_919 + .saturating_add(Weight::from_parts(38_799, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/ranked-collective/src/weights.rs b/substrate/frame/ranked-collective/src/weights.rs index 5721858f7e2..4ff0c3337d5 100644 --- a/substrate/frame/ranked-collective/src/weights.rs +++ b/substrate/frame/ranked-collective/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_ranked_collective` +//! Autogenerated weights for pallet_ranked_collective //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/ranked-collective/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/ranked-collective/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_ranked_collective`. +/// Weight functions needed for pallet_ranked_collective. pub trait WeightInfo { fn add_member() -> Weight; fn remove_member(r: u32, ) -> Weight; @@ -60,295 +61,283 @@ pub trait WeightInfo { fn exchange_member() -> Weight; } -/// Weights for `pallet_ranked_collective` using the Substrate node and recommended hardware. +/// Weights for pallet_ranked_collective using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:0 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:0 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) fn add_member() -> Weight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3507` - // Minimum execution time: 15_389_000 picoseconds. - Weight::from_parts(15_901_000, 3507) + // Minimum execution time: 17_245_000 picoseconds. + Weight::from_parts(17_930_000, 3507) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:11 w:11) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:11 w:22) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:11 w:22) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:11 w:11) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:11 w:11) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:11 w:11) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) /// The range of component `r` is `[0, 10]`. fn remove_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `616 + r * (281 ±0)` // Estimated: `3519 + r * (2529 ±0)` - // Minimum execution time: 29_541_000 picoseconds. - Weight::from_parts(32_239_358, 3519) - // Standard Error: 23_406 - .saturating_add(Weight::from_parts(16_030_191, 0).saturating_mul(r.into())) + // Minimum execution time: 29_534_000 picoseconds. + Weight::from_parts(32_847_495, 3519) + // Standard Error: 24_211 + .saturating_add(Weight::from_parts(13_949_639, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) - .saturating_add(T::DbWeight::get().writes(6_u64)) - .saturating_add(T::DbWeight::get().writes((5_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2529).saturating_mul(r.into())) } - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:0 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:0 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) /// The range of component `r` is `[0, 10]`. fn promote_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `314 + r * (17 ±0)` // Estimated: `3507` - // Minimum execution time: 17_939_000 picoseconds. - Weight::from_parts(19_290_416, 3507) - // Standard Error: 5_710 - .saturating_add(Weight::from_parts(374_399, 0).saturating_mul(r.into())) + // Minimum execution time: 20_333_000 picoseconds. + Weight::from_parts(21_592_224, 3507) + // Standard Error: 6_423 + .saturating_add(Weight::from_parts(321_314, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:1 w:2) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:1 w:2) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:1 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:1 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) /// The range of component `r` is `[0, 10]`. fn demote_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `632 + r * (72 ±0)` // Estimated: `3519` - // Minimum execution time: 29_609_000 picoseconds. - Weight::from_parts(32_686_167, 3519) - // Standard Error: 27_588 - .saturating_add(Weight::from_parts(789_212, 0).saturating_mul(r.into())) + // Minimum execution time: 29_446_000 picoseconds. + Weight::from_parts(32_447_715, 3519) + // Standard Error: 28_791 + .saturating_add(Weight::from_parts(822_890, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedPolls::ReferendumInfoFor` (r:1 w:1) - /// Proof: `RankedPolls::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(330), added: 2805, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Voting` (r:1 w:1) - /// Proof: `RankedCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedPolls ReferendumInfoFor (r:1 w:1) + /// Proof: RankedPolls ReferendumInfoFor (max_values: None, max_size: Some(330), added: 2805, mode: MaxEncodedLen) + /// Storage: RankedCollective Voting (r:1 w:1) + /// Proof: RankedCollective Voting (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn vote() -> Weight { // Proof Size summary in bytes: // Measured: `628` // Estimated: `219984` - // Minimum execution time: 41_151_000 picoseconds. - Weight::from_parts(42_435_000, 219984) + // Minimum execution time: 45_474_000 picoseconds. + Weight::from_parts(47_228_000, 219984) .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `RankedPolls::ReferendumInfoFor` (r:1 w:0) - /// Proof: `RankedPolls::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(330), added: 2805, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::VotingCleanup` (r:1 w:0) - /// Proof: `RankedCollective::VotingCleanup` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Voting` (r:100 w:100) - /// Proof: `RankedCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: RankedPolls ReferendumInfoFor (r:1 w:0) + /// Proof: RankedPolls ReferendumInfoFor (max_values: None, max_size: Some(330), added: 2805, mode: MaxEncodedLen) + /// Storage: RankedCollective VotingCleanup (r:1 w:0) + /// Proof: RankedCollective VotingCleanup (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: RankedCollective Voting (r:100 w:100) + /// Proof: RankedCollective Voting (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) /// The range of component `n` is `[0, 100]`. fn cleanup_poll(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `462 + n * (50 ±0)` // Estimated: `3795 + n * (2540 ±0)` - // Minimum execution time: 13_563_000 picoseconds. - Weight::from_parts(17_495_215, 3795) - // Standard Error: 2_294 - .saturating_add(Weight::from_parts(1_207_393, 0).saturating_mul(n.into())) + // Minimum execution time: 13_903_000 picoseconds. + Weight::from_parts(18_209_102, 3795) + // Standard Error: 2_556 + .saturating_add(Weight::from_parts(1_237_454, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2540).saturating_mul(n.into())) } + /// Storage: `RankedCollective::Members` (r:2 w:2) /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:2 w:2) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:2 w:4) + /// Storage: `RankedCollective::IdToIndex` (r:2 w:2) /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:2 w:2) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:0) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:2 w:2) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::IndexToId` (r:0 w:2) /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn exchange_member() -> Weight { // Proof Size summary in bytes: - // Measured: `625` - // Estimated: `19894` - // Minimum execution time: 70_713_000 picoseconds. - Weight::from_parts(72_831_000, 19894) - .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(14_u64)) + // Measured: `437` + // Estimated: `6048` + // Minimum execution time: 138_000_000 picoseconds. + Weight::from_parts(141_000_000, 0) + .saturating_add(Weight::from_parts(0, 6048)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(8)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:0 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:0 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) fn add_member() -> Weight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3507` - // Minimum execution time: 15_389_000 picoseconds. - Weight::from_parts(15_901_000, 3507) + // Minimum execution time: 17_245_000 picoseconds. + Weight::from_parts(17_930_000, 3507) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:11 w:11) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:11 w:22) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:11 w:22) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:11 w:11) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:11 w:11) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:11 w:11) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) /// The range of component `r` is `[0, 10]`. fn remove_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `616 + r * (281 ±0)` // Estimated: `3519 + r * (2529 ±0)` - // Minimum execution time: 29_541_000 picoseconds. - Weight::from_parts(32_239_358, 3519) - // Standard Error: 23_406 - .saturating_add(Weight::from_parts(16_030_191, 0).saturating_mul(r.into())) + // Minimum execution time: 29_534_000 picoseconds. + Weight::from_parts(32_847_495, 3519) + // Standard Error: 24_211 + .saturating_add(Weight::from_parts(13_949_639, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) - .saturating_add(RocksDbWeight::get().writes(6_u64)) - .saturating_add(RocksDbWeight::get().writes((5_u64).saturating_mul(r.into()))) + .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(r.into()))) .saturating_add(Weight::from_parts(0, 2529).saturating_mul(r.into())) } - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:0 w:1) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:0 w:1) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:0 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:0 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) /// The range of component `r` is `[0, 10]`. fn promote_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `314 + r * (17 ±0)` // Estimated: `3507` - // Minimum execution time: 17_939_000 picoseconds. - Weight::from_parts(19_290_416, 3507) - // Standard Error: 5_710 - .saturating_add(Weight::from_parts(374_399, 0).saturating_mul(r.into())) + // Minimum execution time: 20_333_000 picoseconds. + Weight::from_parts(21_592_224, 3507) + // Standard Error: 6_423 + .saturating_add(Weight::from_parts(321_314, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:1) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::MemberCount` (r:1 w:1) - /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:1 w:2) - /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IndexToId` (r:1 w:2) - /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:1) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedCollective MemberCount (r:1 w:1) + /// Proof: RankedCollective MemberCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: RankedCollective IdToIndex (r:1 w:1) + /// Proof: RankedCollective IdToIndex (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) + /// Storage: RankedCollective IndexToId (r:1 w:1) + /// Proof: RankedCollective IndexToId (max_values: None, max_size: Some(54), added: 2529, mode: MaxEncodedLen) /// The range of component `r` is `[0, 10]`. fn demote_member(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `632 + r * (72 ±0)` // Estimated: `3519` - // Minimum execution time: 29_609_000 picoseconds. - Weight::from_parts(32_686_167, 3519) - // Standard Error: 27_588 - .saturating_add(Weight::from_parts(789_212, 0).saturating_mul(r.into())) + // Minimum execution time: 29_446_000 picoseconds. + Weight::from_parts(32_447_715, 3519) + // Standard Error: 28_791 + .saturating_add(Weight::from_parts(822_890, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `RankedPolls::ReferendumInfoFor` (r:1 w:1) - /// Proof: `RankedPolls::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(330), added: 2805, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Voting` (r:1 w:1) - /// Proof: `RankedCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: RankedPolls ReferendumInfoFor (r:1 w:1) + /// Proof: RankedPolls ReferendumInfoFor (max_values: None, max_size: Some(330), added: 2805, mode: MaxEncodedLen) + /// Storage: RankedCollective Voting (r:1 w:1) + /// Proof: RankedCollective Voting (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn vote() -> Weight { // Proof Size summary in bytes: // Measured: `628` // Estimated: `219984` - // Minimum execution time: 41_151_000 picoseconds. - Weight::from_parts(42_435_000, 219984) + // Minimum execution time: 45_474_000 picoseconds. + Weight::from_parts(47_228_000, 219984) .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `RankedPolls::ReferendumInfoFor` (r:1 w:0) - /// Proof: `RankedPolls::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(330), added: 2805, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::VotingCleanup` (r:1 w:0) - /// Proof: `RankedCollective::VotingCleanup` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Voting` (r:100 w:100) - /// Proof: `RankedCollective::Voting` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + /// Storage: RankedPolls ReferendumInfoFor (r:1 w:0) + /// Proof: RankedPolls ReferendumInfoFor (max_values: None, max_size: Some(330), added: 2805, mode: MaxEncodedLen) + /// Storage: RankedCollective VotingCleanup (r:1 w:0) + /// Proof: RankedCollective VotingCleanup (max_values: None, max_size: Some(114), added: 2589, mode: MaxEncodedLen) + /// Storage: RankedCollective Voting (r:100 w:100) + /// Proof: RankedCollective Voting (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) /// The range of component `n` is `[0, 100]`. fn cleanup_poll(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `462 + n * (50 ±0)` // Estimated: `3795 + n * (2540 ±0)` - // Minimum execution time: 13_563_000 picoseconds. - Weight::from_parts(17_495_215, 3795) - // Standard Error: 2_294 - .saturating_add(Weight::from_parts(1_207_393, 0).saturating_mul(n.into())) + // Minimum execution time: 13_903_000 picoseconds. + Weight::from_parts(18_209_102, 3795) + // Standard Error: 2_556 + .saturating_add(Weight::from_parts(1_237_454, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2540).saturating_mul(n.into())) } + /// Storage: `RankedCollective::Members` (r:2 w:2) /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::MemberCount` (r:2 w:2) /// Proof: `RankedCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::IdToIndex` (r:2 w:4) + /// Storage: `RankedCollective::IdToIndex` (r:2 w:2) /// Proof: `RankedCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::Member` (r:2 w:2) - /// Proof: `CoreFellowship::Member` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) - /// Storage: `CoreFellowship::MemberEvidence` (r:1 w:0) - /// Proof: `CoreFellowship::MemberEvidence` (`max_values`: None, `max_size`: Some(16429), added: 18904, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:2 w:2) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) /// Storage: `RankedCollective::IndexToId` (r:0 w:2) /// Proof: `RankedCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) fn exchange_member() -> Weight { // Proof Size summary in bytes: - // Measured: `625` - // Estimated: `19894` - // Minimum execution time: 70_713_000 picoseconds. - Weight::from_parts(72_831_000, 19894) - .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(14_u64)) + // Measured: `437` + // Estimated: `6048` + // Minimum execution time: 138_000_000 picoseconds. + Weight::from_parts(141_000_000, 0) + .saturating_add(Weight::from_parts(0, 6048)) + .saturating_add(RocksDbWeight::get().reads(6)) + .saturating_add(RocksDbWeight::get().writes(8)) } } diff --git a/substrate/frame/recovery/src/weights.rs b/substrate/frame/recovery/src/weights.rs index fe5dbcfc222..84b19ae694e 100644 --- a/substrate/frame/recovery/src/weights.rs +++ b/substrate/frame/recovery/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_recovery` +//! Autogenerated weights for pallet_recovery //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/recovery/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/recovery/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_recovery`. +/// Weight functions needed for pallet_recovery. pub trait WeightInfo { fn as_recovered() -> Weight; fn set_recovered() -> Weight; @@ -62,266 +63,258 @@ pub trait WeightInfo { fn cancel_recovered() -> Weight; } -/// Weights for `pallet_recovery` using the Substrate node and recommended hardware. +/// Weights for pallet_recovery using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Recovery::Proxy` (r:1 w:0) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Recovery Proxy (r:1 w:0) + /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) fn as_recovered() -> Weight { // Proof Size summary in bytes: - // Measured: `497` - // Estimated: `3997` - // Minimum execution time: 14_898_000 picoseconds. - Weight::from_parts(15_464_000, 3997) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Measured: `281` + // Estimated: `3545` + // Minimum execution time: 9_360_000 picoseconds. + Weight::from_parts(9_773_000, 3545) + .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: `Recovery::Proxy` (r:0 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// Storage: Recovery Proxy (r:0 w:1) + /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) fn set_recovered() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_424_000 picoseconds. - Weight::from_parts(7_830_000, 0) + // Minimum execution time: 9_146_000 picoseconds. + Weight::from_parts(9_507_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Recoverable` (r:1 w:1) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: Recovery Recoverable (r:1 w:1) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn create_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `246` + // Measured: `175` // Estimated: `3816` - // Minimum execution time: 21_968_000 picoseconds. - Weight::from_parts(23_594_232, 3816) - // Standard Error: 5_848 - .saturating_add(Weight::from_parts(24_843, 0).saturating_mul(n.into())) + // Minimum execution time: 26_472_000 picoseconds. + Weight::from_parts(27_917_651, 3816) + // Standard Error: 7_129 + .saturating_add(Weight::from_parts(59_239, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: Recovery Recoverable (r:1 w:0) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: Recovery ActiveRecoveries (r:1 w:1) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) fn initiate_recovery() -> Weight { // Proof Size summary in bytes: - // Measured: `343` + // Measured: `272` // Estimated: `3854` - // Minimum execution time: 25_494_000 picoseconds. - Weight::from_parts(26_290_000, 3854) + // Minimum execution time: 29_618_000 picoseconds. + Weight::from_parts(30_192_000, 3854) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: Recovery Recoverable (r:1 w:0) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: Recovery ActiveRecoveries (r:1 w:1) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn vouch_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `431 + n * (64 ±0)` + // Measured: `360 + n * (64 ±0)` // Estimated: `3854` - // Minimum execution time: 17_044_000 picoseconds. - Weight::from_parts(18_299_617, 3854) - // Standard Error: 5_580 - .saturating_add(Weight::from_parts(187_568, 0).saturating_mul(n.into())) + // Minimum execution time: 19_464_000 picoseconds. + Weight::from_parts(20_642_522, 3854) + // Standard Error: 5_974 + .saturating_add(Weight::from_parts(142_308, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `Recovery::Proxy` (r:1 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// Storage: Recovery Recoverable (r:1 w:0) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: Recovery ActiveRecoveries (r:1 w:0) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: Recovery Proxy (r:1 w:1) + /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn claim_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `463 + n * (64 ±0)` + // Measured: `392 + n * (64 ±0)` // Estimated: `3854` - // Minimum execution time: 22_186_000 picoseconds. - Weight::from_parts(23_476_807, 3854) - // Standard Error: 6_392 - .saturating_add(Weight::from_parts(89_770, 0).saturating_mul(n.into())) + // Minimum execution time: 23_656_000 picoseconds. + Weight::from_parts(24_903_269, 3854) + // Standard Error: 5_771 + .saturating_add(Weight::from_parts(117_343, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Recovery ActiveRecoveries (r:1 w:1) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn close_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `584 + n * (32 ±0)` + // Measured: `513 + n * (32 ±0)` // Estimated: `3854` - // Minimum execution time: 31_045_000 picoseconds. - Weight::from_parts(32_623_578, 3854) - // Standard Error: 7_203 - .saturating_add(Weight::from_parts(61_466, 0).saturating_mul(n.into())) + // Minimum execution time: 34_866_000 picoseconds. + Weight::from_parts(36_368_748, 3854) + // Standard Error: 6_600 + .saturating_add(Weight::from_parts(118_610, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `Recovery::Recoverable` (r:1 w:1) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: Recovery ActiveRecoveries (r:1 w:0) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: Recovery Recoverable (r:1 w:1) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn remove_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `341 + n * (32 ±0)` + // Measured: `270 + n * (32 ±0)` // Estimated: `3854` - // Minimum execution time: 27_925_000 picoseconds. - Weight::from_parts(29_258_264, 3854) - // Standard Error: 8_192 - .saturating_add(Weight::from_parts(128_124, 0).saturating_mul(n.into())) + // Minimum execution time: 31_405_000 picoseconds. + Weight::from_parts(32_552_838, 3854) + // Standard Error: 8_043 + .saturating_add(Weight::from_parts(171_605, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Proxy` (r:1 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// Storage: Recovery Proxy (r:1 w:1) + /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) fn cancel_recovered() -> Weight { // Proof Size summary in bytes: - // Measured: `352` + // Measured: `281` // Estimated: `3545` - // Minimum execution time: 11_623_000 picoseconds. - Weight::from_parts(12_043_000, 3545) + // Minimum execution time: 11_530_000 picoseconds. + Weight::from_parts(11_851_000, 3545) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Recovery::Proxy` (r:1 w:0) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) + /// Storage: Recovery Proxy (r:1 w:0) + /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) fn as_recovered() -> Weight { // Proof Size summary in bytes: - // Measured: `497` - // Estimated: `3997` - // Minimum execution time: 14_898_000 picoseconds. - Weight::from_parts(15_464_000, 3997) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Measured: `281` + // Estimated: `3545` + // Minimum execution time: 9_360_000 picoseconds. + Weight::from_parts(9_773_000, 3545) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: `Recovery::Proxy` (r:0 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// Storage: Recovery Proxy (r:0 w:1) + /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) fn set_recovered() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_424_000 picoseconds. - Weight::from_parts(7_830_000, 0) + // Minimum execution time: 9_146_000 picoseconds. + Weight::from_parts(9_507_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Recoverable` (r:1 w:1) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: Recovery Recoverable (r:1 w:1) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn create_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `246` + // Measured: `175` // Estimated: `3816` - // Minimum execution time: 21_968_000 picoseconds. - Weight::from_parts(23_594_232, 3816) - // Standard Error: 5_848 - .saturating_add(Weight::from_parts(24_843, 0).saturating_mul(n.into())) + // Minimum execution time: 26_472_000 picoseconds. + Weight::from_parts(27_917_651, 3816) + // Standard Error: 7_129 + .saturating_add(Weight::from_parts(59_239, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: Recovery Recoverable (r:1 w:0) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: Recovery ActiveRecoveries (r:1 w:1) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) fn initiate_recovery() -> Weight { // Proof Size summary in bytes: - // Measured: `343` + // Measured: `272` // Estimated: `3854` - // Minimum execution time: 25_494_000 picoseconds. - Weight::from_parts(26_290_000, 3854) + // Minimum execution time: 29_618_000 picoseconds. + Weight::from_parts(30_192_000, 3854) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) + /// Storage: Recovery Recoverable (r:1 w:0) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: Recovery ActiveRecoveries (r:1 w:1) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn vouch_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `431 + n * (64 ±0)` + // Measured: `360 + n * (64 ±0)` // Estimated: `3854` - // Minimum execution time: 17_044_000 picoseconds. - Weight::from_parts(18_299_617, 3854) - // Standard Error: 5_580 - .saturating_add(Weight::from_parts(187_568, 0).saturating_mul(n.into())) + // Minimum execution time: 19_464_000 picoseconds. + Weight::from_parts(20_642_522, 3854) + // Standard Error: 5_974 + .saturating_add(Weight::from_parts(142_308, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Recoverable` (r:1 w:0) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `Recovery::Proxy` (r:1 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// Storage: Recovery Recoverable (r:1 w:0) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) + /// Storage: Recovery ActiveRecoveries (r:1 w:0) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: Recovery Proxy (r:1 w:1) + /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn claim_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `463 + n * (64 ±0)` + // Measured: `392 + n * (64 ±0)` // Estimated: `3854` - // Minimum execution time: 22_186_000 picoseconds. - Weight::from_parts(23_476_807, 3854) - // Standard Error: 6_392 - .saturating_add(Weight::from_parts(89_770, 0).saturating_mul(n.into())) + // Minimum execution time: 23_656_000 picoseconds. + Weight::from_parts(24_903_269, 3854) + // Standard Error: 5_771 + .saturating_add(Weight::from_parts(117_343, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:1) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Recovery ActiveRecoveries (r:1 w:1) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn close_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `584 + n * (32 ±0)` + // Measured: `513 + n * (32 ±0)` // Estimated: `3854` - // Minimum execution time: 31_045_000 picoseconds. - Weight::from_parts(32_623_578, 3854) - // Standard Error: 7_203 - .saturating_add(Weight::from_parts(61_466, 0).saturating_mul(n.into())) + // Minimum execution time: 34_866_000 picoseconds. + Weight::from_parts(36_368_748, 3854) + // Standard Error: 6_600 + .saturating_add(Weight::from_parts(118_610, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Recovery::ActiveRecoveries` (r:1 w:0) - /// Proof: `Recovery::ActiveRecoveries` (`max_values`: None, `max_size`: Some(389), added: 2864, mode: `MaxEncodedLen`) - /// Storage: `Recovery::Recoverable` (r:1 w:1) - /// Proof: `Recovery::Recoverable` (`max_values`: None, `max_size`: Some(351), added: 2826, mode: `MaxEncodedLen`) + /// Storage: Recovery ActiveRecoveries (r:1 w:0) + /// Proof: Recovery ActiveRecoveries (max_values: None, max_size: Some(389), added: 2864, mode: MaxEncodedLen) + /// Storage: Recovery Recoverable (r:1 w:1) + /// Proof: Recovery Recoverable (max_values: None, max_size: Some(351), added: 2826, mode: MaxEncodedLen) /// The range of component `n` is `[1, 9]`. fn remove_recovery(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `341 + n * (32 ±0)` + // Measured: `270 + n * (32 ±0)` // Estimated: `3854` - // Minimum execution time: 27_925_000 picoseconds. - Weight::from_parts(29_258_264, 3854) - // Standard Error: 8_192 - .saturating_add(Weight::from_parts(128_124, 0).saturating_mul(n.into())) + // Minimum execution time: 31_405_000 picoseconds. + Weight::from_parts(32_552_838, 3854) + // Standard Error: 8_043 + .saturating_add(Weight::from_parts(171_605, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Recovery::Proxy` (r:1 w:1) - /// Proof: `Recovery::Proxy` (`max_values`: None, `max_size`: Some(80), added: 2555, mode: `MaxEncodedLen`) + /// Storage: Recovery Proxy (r:1 w:1) + /// Proof: Recovery Proxy (max_values: None, max_size: Some(80), added: 2555, mode: MaxEncodedLen) fn cancel_recovered() -> Weight { // Proof Size summary in bytes: - // Measured: `352` + // Measured: `281` // Estimated: `3545` - // Minimum execution time: 11_623_000 picoseconds. - Weight::from_parts(12_043_000, 3545) + // Minimum execution time: 11_530_000 picoseconds. + Weight::from_parts(11_851_000, 3545) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/referenda/src/weights.rs b/substrate/frame/referenda/src/weights.rs index 1f1b69873eb..4b89379b311 100644 --- a/substrate/frame/referenda/src/weights.rs +++ b/substrate/frame/referenda/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_referenda` +//! Autogenerated weights for pallet_referenda //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/referenda/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/referenda/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_referenda`. +/// Weight functions needed for pallet_referenda. pub trait WeightInfo { fn submit() -> Weight; fn place_decision_deposit_preparing() -> Weight; @@ -83,874 +84,842 @@ pub trait WeightInfo { fn clear_metadata() -> Weight; } -/// Weights for `pallet_referenda` using the Substrate node and recommended hardware. +/// Weights for pallet_referenda using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Referenda::ReferendumCount` (r:1 w:1) - /// Proof: `Referenda::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:0 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumCount (r:1 w:1) + /// Proof: Referenda ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:0 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn submit() -> Weight { // Proof Size summary in bytes: - // Measured: `286` + // Measured: `220` // Estimated: `110487` - // Minimum execution time: 31_536_000 picoseconds. - Weight::from_parts(32_797_000, 110487) + // Minimum execution time: 40_175_000 picoseconds. + Weight::from_parts(41_107_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `473` // Estimated: `219984` - // Minimum execution time: 42_579_000 picoseconds. - Weight::from_parts(43_877_000, 219984) + // Minimum execution time: 50_922_000 picoseconds. + Weight::from_parts(52_179_000, 219984) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:0) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3326` + // Measured: `3260` // Estimated: `110487` - // Minimum execution time: 61_439_000 picoseconds. - Weight::from_parts(63_681_000, 110487) + // Minimum execution time: 69_559_000 picoseconds. + Weight::from_parts(72_143_000, 110487) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:0) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3346` + // Measured: `3280` // Estimated: `110487` - // Minimum execution time: 60_136_000 picoseconds. - Weight::from_parts(61_841_000, 110487) + // Minimum execution time: 68_833_000 picoseconds. + Weight::from_parts(70_987_000, 110487) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `473` // Estimated: `219984` - // Minimum execution time: 49_865_000 picoseconds. - Weight::from_parts(51_347_000, 219984) + // Minimum execution time: 61_794_000 picoseconds. + Weight::from_parts(62_846_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) - } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `473` // Estimated: `219984` - // Minimum execution time: 47_887_000 picoseconds. - Weight::from_parts(49_927_000, 219984) + // Minimum execution time: 58_664_000 picoseconds. + Weight::from_parts(60_195_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn refund_decision_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `351` // Estimated: `3831` - // Minimum execution time: 25_721_000 picoseconds. - Weight::from_parts(26_922_000, 3831) + // Minimum execution time: 30_850_000 picoseconds. + Weight::from_parts(32_130_000, 3831) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn refund_submission_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `407` + // Measured: `341` // Estimated: `3831` - // Minimum execution time: 25_840_000 picoseconds. - Weight::from_parts(26_498_000, 3831) + // Minimum execution time: 30_747_000 picoseconds. + Weight::from_parts(32_196_000, 3831) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `447` + // Measured: `381` // Estimated: `219984` - // Minimum execution time: 30_530_000 picoseconds. - Weight::from_parts(31_547_000, 219984) + // Minimum execution time: 36_139_000 picoseconds. + Weight::from_parts(37_252_000, 219984) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Referenda::MetadataOf` (r:1 w:0) - /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:1 w:0) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn kill() -> Weight { // Proof Size summary in bytes: - // Measured: `688` + // Measured: `622` // Estimated: `219984` - // Minimum execution time: 64_011_000 picoseconds. - Weight::from_parts(65_240_000, 219984) + // Minimum execution time: 80_862_000 picoseconds. + Weight::from_parts(83_045_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::TrackQueue` (r:1 w:0) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: Referenda TrackQueue (r:1 w:0) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) fn one_fewer_deciding_queue_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `240` + // Measured: `174` // Estimated: `5477` - // Minimum execution time: 9_568_000 picoseconds. - Weight::from_parts(10_004_000, 5477) + // Minimum execution time: 10_136_000 picoseconds. + Weight::from_parts(10_638_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `3216` + // Measured: `3150` // Estimated: `110487` - // Minimum execution time: 43_325_000 picoseconds. - Weight::from_parts(45_335_000, 110487) + // Minimum execution time: 52_022_000 picoseconds. + Weight::from_parts(53_910_000, 110487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `3216` + // Measured: `3150` // Estimated: `110487` - // Minimum execution time: 44_287_000 picoseconds. - Weight::from_parts(45_164_000, 110487) + // Minimum execution time: 53_683_000 picoseconds. + Weight::from_parts(55_707_000, 110487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) fn nudge_referendum_requeued_insertion() -> Weight { // Proof Size summary in bytes: - // Measured: `3077` + // Measured: `3011` // Estimated: `5477` - // Minimum execution time: 21_909_000 picoseconds. - Weight::from_parts(22_641_000, 5477) + // Minimum execution time: 24_043_000 picoseconds. + Weight::from_parts(24_512_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) fn nudge_referendum_requeued_slide() -> Weight { // Proof Size summary in bytes: - // Measured: `3077` + // Measured: `3011` // Estimated: `5477` - // Minimum execution time: 21_626_000 picoseconds. - Weight::from_parts(22_338_000, 5477) + // Minimum execution time: 23_588_000 picoseconds. + Weight::from_parts(24_422_000, 5477) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:0) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) fn nudge_referendum_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3081` + // Measured: `3015` // Estimated: `5477` - // Minimum execution time: 29_245_000 picoseconds. - Weight::from_parts(30_147_000, 5477) + // Minimum execution time: 31_443_000 picoseconds. + Weight::from_parts(32_725_000, 5477) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:0) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) fn nudge_referendum_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3101` + // Measured: `3035` // Estimated: `5477` - // Minimum execution time: 28_512_000 picoseconds. - Weight::from_parts(29_781_000, 5477) + // Minimum execution time: 30_319_000 picoseconds. + Weight::from_parts(31_652_000, 5477) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_no_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `399` + // Measured: `333` // Estimated: `110487` - // Minimum execution time: 19_208_000 picoseconds. - Weight::from_parts(19_947_000, 110487) + // Minimum execution time: 23_062_000 picoseconds. + Weight::from_parts(23_614_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `447` + // Measured: `381` // Estimated: `110487` - // Minimum execution time: 19_708_000 picoseconds. - Weight::from_parts(20_783_000, 110487) + // Minimum execution time: 23_537_000 picoseconds. + Weight::from_parts(24_267_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn nudge_referendum_timed_out() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `278` // Estimated: `3831` - // Minimum execution time: 12_947_000 picoseconds. - Weight::from_parts(13_582_000, 3831) + // Minimum execution time: 16_388_000 picoseconds. + Weight::from_parts(16_676_000, 3831) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_begin_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `447` + // Measured: `381` // Estimated: `110487` - // Minimum execution time: 26_699_000 picoseconds. - Weight::from_parts(28_048_000, 110487) + // Minimum execution time: 32_801_000 picoseconds. + Weight::from_parts(34_053_000, 110487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_begin_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `447` + // Measured: `381` // Estimated: `110487` - // Minimum execution time: 28_132_000 picoseconds. - Weight::from_parts(29_520_000, 110487) + // Minimum execution time: 35_704_000 picoseconds. + Weight::from_parts(36_451_000, 110487) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_begin_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `500` + // Measured: `434` // Estimated: `110487` - // Minimum execution time: 23_212_000 picoseconds. - Weight::from_parts(24_200_000, 110487) + // Minimum execution time: 29_151_000 picoseconds. + Weight::from_parts(30_055_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_end_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `483` + // Measured: `417` // Estimated: `110487` - // Minimum execution time: 22_807_000 picoseconds. - Weight::from_parts(23_858_000, 110487) + // Minimum execution time: 29_265_000 picoseconds. + Weight::from_parts(30_213_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_continue_not_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `500` + // Measured: `434` // Estimated: `110487` - // Minimum execution time: 22_862_000 picoseconds. - Weight::from_parts(23_627_000, 110487) + // Minimum execution time: 27_760_000 picoseconds. + Weight::from_parts(28_381_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_continue_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `504` + // Measured: `438` // Estimated: `110487` - // Minimum execution time: 21_030_000 picoseconds. - Weight::from_parts(21_710_000, 110487) + // Minimum execution time: 25_464_000 picoseconds. + Weight::from_parts(26_348_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Lookup` (r:1 w:1) - /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: Scheduler Lookup (r:1 w:1) + /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn nudge_referendum_approved() -> Weight { // Proof Size summary in bytes: - // Measured: `504` + // Measured: `438` // Estimated: `219984` - // Minimum execution time: 33_031_000 picoseconds. - Weight::from_parts(34_518_000, 219984) + // Minimum execution time: 42_629_000 picoseconds. + Weight::from_parts(43_732_000, 219984) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_rejected() -> Weight { // Proof Size summary in bytes: - // Measured: `500` + // Measured: `434` // Estimated: `110487` - // Minimum execution time: 23_198_000 picoseconds. - Weight::from_parts(24_238_000, 110487) + // Minimum execution time: 30_015_000 picoseconds. + Weight::from_parts(30_827_000, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Referenda::MetadataOf` (r:0 w:1) - /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:0 w:1) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn set_some_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `555` + // Measured: `422` // Estimated: `3831` - // Minimum execution time: 19_502_000 picoseconds. - Weight::from_parts(20_105_000, 3831) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 19_901_000 picoseconds. + Weight::from_parts(20_681_000, 3831) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::MetadataOf` (r:1 w:1) - /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:1 w:1) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `421` + // Measured: `355` // Estimated: `3831` - // Minimum execution time: 15_417_000 picoseconds. - Weight::from_parts(15_916_000, 3831) + // Minimum execution time: 17_323_000 picoseconds. + Weight::from_parts(18_227_000, 3831) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Referenda::ReferendumCount` (r:1 w:1) - /// Proof: `Referenda::ReferendumCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:0 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumCount (r:1 w:1) + /// Proof: Referenda ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:0 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn submit() -> Weight { // Proof Size summary in bytes: - // Measured: `286` + // Measured: `220` // Estimated: `110487` - // Minimum execution time: 31_536_000 picoseconds. - Weight::from_parts(32_797_000, 110487) + // Minimum execution time: 40_175_000 picoseconds. + Weight::from_parts(41_107_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `473` // Estimated: `219984` - // Minimum execution time: 42_579_000 picoseconds. - Weight::from_parts(43_877_000, 219984) + // Minimum execution time: 50_922_000 picoseconds. + Weight::from_parts(52_179_000, 219984) .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:0) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3326` + // Measured: `3260` // Estimated: `110487` - // Minimum execution time: 61_439_000 picoseconds. - Weight::from_parts(63_681_000, 110487) + // Minimum execution time: 69_559_000 picoseconds. + Weight::from_parts(72_143_000, 110487) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:0) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3346` + // Measured: `3280` // Estimated: `110487` - // Minimum execution time: 60_136_000 picoseconds. - Weight::from_parts(61_841_000, 110487) + // Minimum execution time: 68_833_000 picoseconds. + Weight::from_parts(70_987_000, 110487) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `473` // Estimated: `219984` - // Minimum execution time: 49_865_000 picoseconds. - Weight::from_parts(51_347_000, 219984) + // Minimum execution time: 61_794_000 picoseconds. + Weight::from_parts(62_846_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + .saturating_add(RocksDbWeight::get().writes(4_u64)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn place_decision_deposit_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `473` // Estimated: `219984` - // Minimum execution time: 47_887_000 picoseconds. - Weight::from_parts(49_927_000, 219984) + // Minimum execution time: 58_664_000 picoseconds. + Weight::from_parts(60_195_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn refund_decision_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `351` // Estimated: `3831` - // Minimum execution time: 25_721_000 picoseconds. - Weight::from_parts(26_922_000, 3831) + // Minimum execution time: 30_850_000 picoseconds. + Weight::from_parts(32_130_000, 3831) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn refund_submission_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `407` + // Measured: `341` // Estimated: `3831` - // Minimum execution time: 25_840_000 picoseconds. - Weight::from_parts(26_498_000, 3831) + // Minimum execution time: 30_747_000 picoseconds. + Weight::from_parts(32_196_000, 3831) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn cancel() -> Weight { // Proof Size summary in bytes: - // Measured: `447` + // Measured: `381` // Estimated: `219984` - // Minimum execution time: 30_530_000 picoseconds. - Weight::from_parts(31_547_000, 219984) + // Minimum execution time: 36_139_000 picoseconds. + Weight::from_parts(37_252_000, 219984) .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Referenda::MetadataOf` (r:1 w:0) - /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:1 w:0) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn kill() -> Weight { // Proof Size summary in bytes: - // Measured: `688` + // Measured: `622` // Estimated: `219984` - // Minimum execution time: 64_011_000 picoseconds. - Weight::from_parts(65_240_000, 219984) + // Minimum execution time: 80_862_000 picoseconds. + Weight::from_parts(83_045_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::TrackQueue` (r:1 w:0) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) + /// Storage: Referenda TrackQueue (r:1 w:0) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) fn one_fewer_deciding_queue_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `240` + // Measured: `174` // Estimated: `5477` - // Minimum execution time: 9_568_000 picoseconds. - Weight::from_parts(10_004_000, 5477) + // Minimum execution time: 10_136_000 picoseconds. + Weight::from_parts(10_638_000, 5477) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn one_fewer_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `3216` + // Measured: `3150` // Estimated: `110487` - // Minimum execution time: 43_325_000 picoseconds. - Weight::from_parts(45_335_000, 110487) + // Minimum execution time: 52_022_000 picoseconds. + Weight::from_parts(53_910_000, 110487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn one_fewer_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `3216` + // Measured: `3150` // Estimated: `110487` - // Minimum execution time: 44_287_000 picoseconds. - Weight::from_parts(45_164_000, 110487) + // Minimum execution time: 53_683_000 picoseconds. + Weight::from_parts(55_707_000, 110487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) fn nudge_referendum_requeued_insertion() -> Weight { // Proof Size summary in bytes: - // Measured: `3077` + // Measured: `3011` // Estimated: `5477` - // Minimum execution time: 21_909_000 picoseconds. - Weight::from_parts(22_641_000, 5477) + // Minimum execution time: 24_043_000 picoseconds. + Weight::from_parts(24_512_000, 5477) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) fn nudge_referendum_requeued_slide() -> Weight { // Proof Size summary in bytes: - // Measured: `3077` + // Measured: `3011` // Estimated: `5477` - // Minimum execution time: 21_626_000 picoseconds. - Weight::from_parts(22_338_000, 5477) + // Minimum execution time: 23_588_000 picoseconds. + Weight::from_parts(24_422_000, 5477) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:0) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) fn nudge_referendum_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3081` + // Measured: `3015` // Estimated: `5477` - // Minimum execution time: 29_245_000 picoseconds. - Weight::from_parts(30_147_000, 5477) + // Minimum execution time: 31_443_000 picoseconds. + Weight::from_parts(32_725_000, 5477) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:0) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Referenda::TrackQueue` (r:1 w:1) - /// Proof: `Referenda::TrackQueue` (`max_values`: None, `max_size`: Some(2012), added: 4487, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) fn nudge_referendum_not_queued() -> Weight { // Proof Size summary in bytes: - // Measured: `3101` + // Measured: `3035` // Estimated: `5477` - // Minimum execution time: 28_512_000 picoseconds. - Weight::from_parts(29_781_000, 5477) + // Minimum execution time: 30_319_000 picoseconds. + Weight::from_parts(31_652_000, 5477) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_no_deposit() -> Weight { // Proof Size summary in bytes: - // Measured: `399` + // Measured: `333` // Estimated: `110487` - // Minimum execution time: 19_208_000 picoseconds. - Weight::from_parts(19_947_000, 110487) + // Minimum execution time: 23_062_000 picoseconds. + Weight::from_parts(23_614_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_preparing() -> Weight { // Proof Size summary in bytes: - // Measured: `447` + // Measured: `381` // Estimated: `110487` - // Minimum execution time: 19_708_000 picoseconds. - Weight::from_parts(20_783_000, 110487) + // Minimum execution time: 23_537_000 picoseconds. + Weight::from_parts(24_267_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) fn nudge_referendum_timed_out() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `278` // Estimated: `3831` - // Minimum execution time: 12_947_000 picoseconds. - Weight::from_parts(13_582_000, 3831) + // Minimum execution time: 16_388_000 picoseconds. + Weight::from_parts(16_676_000, 3831) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_begin_deciding_failing() -> Weight { // Proof Size summary in bytes: - // Measured: `447` + // Measured: `381` // Estimated: `110487` - // Minimum execution time: 26_699_000 picoseconds. - Weight::from_parts(28_048_000, 110487) + // Minimum execution time: 32_801_000 picoseconds. + Weight::from_parts(34_053_000, 110487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::DecidingCount` (r:1 w:1) - /// Proof: `Referenda::DecidingCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_begin_deciding_passing() -> Weight { // Proof Size summary in bytes: - // Measured: `447` + // Measured: `381` // Estimated: `110487` - // Minimum execution time: 28_132_000 picoseconds. - Weight::from_parts(29_520_000, 110487) + // Minimum execution time: 35_704_000 picoseconds. + Weight::from_parts(36_451_000, 110487) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_begin_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `500` + // Measured: `434` // Estimated: `110487` - // Minimum execution time: 23_212_000 picoseconds. - Weight::from_parts(24_200_000, 110487) + // Minimum execution time: 29_151_000 picoseconds. + Weight::from_parts(30_055_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_end_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `483` + // Measured: `417` // Estimated: `110487` - // Minimum execution time: 22_807_000 picoseconds. - Weight::from_parts(23_858_000, 110487) + // Minimum execution time: 29_265_000 picoseconds. + Weight::from_parts(30_213_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_continue_not_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `500` + // Measured: `434` // Estimated: `110487` - // Minimum execution time: 22_862_000 picoseconds. - Weight::from_parts(23_627_000, 110487) + // Minimum execution time: 27_760_000 picoseconds. + Weight::from_parts(28_381_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_continue_confirming() -> Weight { // Proof Size summary in bytes: - // Measured: `504` + // Measured: `438` // Estimated: `110487` - // Minimum execution time: 21_030_000 picoseconds. - Weight::from_parts(21_710_000, 110487) + // Minimum execution time: 25_464_000 picoseconds. + Weight::from_parts(26_348_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:2 w:2) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Lookup` (r:1 w:1) - /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) + /// Storage: Scheduler Lookup (r:1 w:1) + /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) fn nudge_referendum_approved() -> Weight { // Proof Size summary in bytes: - // Measured: `504` + // Measured: `438` // Estimated: `219984` - // Minimum execution time: 33_031_000 picoseconds. - Weight::from_parts(34_518_000, 219984) + // Minimum execution time: 42_629_000 picoseconds. + Weight::from_parts(43_732_000, 219984) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:1) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Agenda` (r:1 w:1) - /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(107022), added: 109497, mode: MaxEncodedLen) fn nudge_referendum_rejected() -> Weight { // Proof Size summary in bytes: - // Measured: `500` + // Measured: `434` // Estimated: `110487` - // Minimum execution time: 23_198_000 picoseconds. - Weight::from_parts(24_238_000, 110487) + // Minimum execution time: 30_015_000 picoseconds. + Weight::from_parts(30_827_000, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:0) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Referenda::MetadataOf` (r:0 w:1) - /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:0 w:1) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn set_some_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `555` + // Measured: `422` // Estimated: `3831` - // Minimum execution time: 19_502_000 picoseconds. - Weight::from_parts(20_105_000, 3831) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Minimum execution time: 19_901_000 picoseconds. + Weight::from_parts(20_681_000, 3831) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Referenda::ReferendumInfoFor` (r:1 w:0) - /// Proof: `Referenda::ReferendumInfoFor` (`max_values`: None, `max_size`: Some(366), added: 2841, mode: `MaxEncodedLen`) - /// Storage: `Referenda::MetadataOf` (r:1 w:1) - /// Proof: `Referenda::MetadataOf` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(366), added: 2841, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:1 w:1) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `421` + // Measured: `355` // Estimated: `3831` - // Minimum execution time: 15_417_000 picoseconds. - Weight::from_parts(15_916_000, 3831) + // Minimum execution time: 17_323_000 picoseconds. + Weight::from_parts(18_227_000, 3831) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/remark/src/weights.rs b/substrate/frame/remark/src/weights.rs index 61cca5b7d05..46475db163f 100644 --- a/substrate/frame/remark/src/weights.rs +++ b/substrate/frame/remark/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_remark` +//! Autogenerated weights for pallet_remark //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/remark/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/remark/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,12 +50,12 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_remark`. +/// Weight functions needed for pallet_remark. pub trait WeightInfo { fn store(l: u32, ) -> Weight; } -/// Weights for `pallet_remark` using the Substrate node and recommended hardware. +/// Weights for pallet_remark using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// The range of component `l` is `[1, 1048576]`. @@ -62,23 +63,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_623_000 picoseconds. - Weight::from_parts(6_757_000, 0) + // Minimum execution time: 8_471_000 picoseconds. + Weight::from_parts(8_586_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_368, 0).saturating_mul(l.into())) + .saturating_add(Weight::from_parts(1_359, 0).saturating_mul(l.into())) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { /// The range of component `l` is `[1, 1048576]`. fn store(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_623_000 picoseconds. - Weight::from_parts(6_757_000, 0) + // Minimum execution time: 8_471_000 picoseconds. + Weight::from_parts(8_586_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_368, 0).saturating_mul(l.into())) + .saturating_add(Weight::from_parts(1_359, 0).saturating_mul(l.into())) } } diff --git a/substrate/frame/safe-mode/src/weights.rs b/substrate/frame/safe-mode/src/weights.rs index d326fab0f0f..f72bebcab9a 100644 --- a/substrate/frame/safe-mode/src/weights.rs +++ b/substrate/frame/safe-mode/src/weights.rs @@ -17,29 +17,27 @@ //! Autogenerated weights for `pallet_safe_mode` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-aahe6cbd-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_safe_mode -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/safe-mode/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_safe_mode +// --chain=dev +// --header=./HEADER-APACHE2 +// --output=./frame/safe-mode/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -72,8 +70,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1489` - // Minimum execution time: 2_216_000 picoseconds. - Weight::from_parts(2_309_000, 1489) + // Minimum execution time: 2_500_000 picoseconds. + Weight::from_parts(2_594_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) @@ -82,23 +80,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 6_124_000 picoseconds. - Weight::from_parts(6_601_000, 1489) + // Minimum execution time: 8_868_000 picoseconds. + Weight::from_parts(9_415_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `SafeMode::Deposits` (r:0 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn enter() -> Weight { // Proof Size summary in bytes: // Measured: `142` - // Estimated: `3658` - // Minimum execution time: 44_825_000 picoseconds. - Weight::from_parts(45_845_000, 3658) + // Estimated: `3550` + // Minimum execution time: 50_541_000 picoseconds. + Weight::from_parts(51_558_000, 3550) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -108,23 +106,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1489` - // Minimum execution time: 7_603_000 picoseconds. - Weight::from_parts(7_954_000, 1489) + // Minimum execution time: 10_489_000 picoseconds. + Weight::from_parts(10_833_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `SafeMode::Deposits` (r:0 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn extend() -> Weight { // Proof Size summary in bytes: // Measured: `169` - // Estimated: `3658` - // Minimum execution time: 44_716_000 picoseconds. - Weight::from_parts(46_039_000, 3658) + // Estimated: `3550` + // Minimum execution time: 50_818_000 picoseconds. + Weight::from_parts(51_873_000, 3550) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -134,8 +132,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 8_231_000 picoseconds. - Weight::from_parts(8_731_000, 1489) + // Minimum execution time: 10_843_000 picoseconds. + Weight::from_parts(11_314_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -145,8 +143,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 8_015_000 picoseconds. - Weight::from_parts(8_247_000, 1489) + // Minimum execution time: 10_382_000 picoseconds. + Weight::from_parts(10_814_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -155,39 +153,39 @@ impl WeightInfo for SubstrateWeight { /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn release_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3658` - // Minimum execution time: 39_149_000 picoseconds. - Weight::from_parts(40_005_000, 3658) + // Estimated: `3550` + // Minimum execution time: 42_828_000 picoseconds. + Weight::from_parts(43_752_000, 3550) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `SafeMode::Deposits` (r:1 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn force_release_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3658` - // Minimum execution time: 37_528_000 picoseconds. - Weight::from_parts(38_473_000, 3658) + // Estimated: `3550` + // Minimum execution time: 40_196_000 picoseconds. + Weight::from_parts(41_298_000, 3550) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `SafeMode::Deposits` (r:1 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn force_slash_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3658` - // Minimum execution time: 29_417_000 picoseconds. - Weight::from_parts(30_195_000, 3658) + // Estimated: `3550` + // Minimum execution time: 33_660_000 picoseconds. + Weight::from_parts(34_426_000, 3550) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -201,8 +199,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1489` - // Minimum execution time: 2_216_000 picoseconds. - Weight::from_parts(2_309_000, 1489) + // Minimum execution time: 2_500_000 picoseconds. + Weight::from_parts(2_594_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) @@ -211,23 +209,23 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 6_124_000 picoseconds. - Weight::from_parts(6_601_000, 1489) + // Minimum execution time: 8_868_000 picoseconds. + Weight::from_parts(9_415_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `SafeMode::Deposits` (r:0 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn enter() -> Weight { // Proof Size summary in bytes: // Measured: `142` - // Estimated: `3658` - // Minimum execution time: 44_825_000 picoseconds. - Weight::from_parts(45_845_000, 3658) + // Estimated: `3550` + // Minimum execution time: 50_541_000 picoseconds. + Weight::from_parts(51_558_000, 3550) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -237,23 +235,23 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1489` - // Minimum execution time: 7_603_000 picoseconds. - Weight::from_parts(7_954_000, 1489) + // Minimum execution time: 10_489_000 picoseconds. + Weight::from_parts(10_833_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:1) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) /// Storage: `SafeMode::Deposits` (r:0 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn extend() -> Weight { // Proof Size summary in bytes: // Measured: `169` - // Estimated: `3658` - // Minimum execution time: 44_716_000 picoseconds. - Weight::from_parts(46_039_000, 3658) + // Estimated: `3550` + // Minimum execution time: 50_818_000 picoseconds. + Weight::from_parts(51_873_000, 3550) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -263,8 +261,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 8_231_000 picoseconds. - Weight::from_parts(8_731_000, 1489) + // Minimum execution time: 10_843_000 picoseconds. + Weight::from_parts(11_314_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -274,8 +272,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `169` // Estimated: `1489` - // Minimum execution time: 8_015_000 picoseconds. - Weight::from_parts(8_247_000, 1489) + // Minimum execution time: 10_382_000 picoseconds. + Weight::from_parts(10_814_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -284,39 +282,39 @@ impl WeightInfo for () { /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn release_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3658` - // Minimum execution time: 39_149_000 picoseconds. - Weight::from_parts(40_005_000, 3658) + // Estimated: `3550` + // Minimum execution time: 42_828_000 picoseconds. + Weight::from_parts(43_752_000, 3550) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `SafeMode::Deposits` (r:1 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn force_release_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3658` - // Minimum execution time: 37_528_000 picoseconds. - Weight::from_parts(38_473_000, 3658) + // Estimated: `3550` + // Minimum execution time: 40_196_000 picoseconds. + Weight::from_parts(41_298_000, 3550) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `SafeMode::Deposits` (r:1 w:1) /// Proof: `SafeMode::Deposits` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn force_slash_deposit() -> Weight { // Proof Size summary in bytes: // Measured: `292` - // Estimated: `3658` - // Minimum execution time: 29_417_000 picoseconds. - Weight::from_parts(30_195_000, 3658) + // Estimated: `3550` + // Minimum execution time: 33_660_000 picoseconds. + Weight::from_parts(34_426_000, 3550) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/salary/src/weights.rs b/substrate/frame/salary/src/weights.rs index c4f22a027eb..3d3b9e31595 100644 --- a/substrate/frame/salary/src/weights.rs +++ b/substrate/frame/salary/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_salary` +//! Autogenerated weights for pallet_salary //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/salary/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/salary/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_salary`. +/// Weight functions needed for pallet_salary. pub trait WeightInfo { fn init() -> Weight; fn bump() -> Weight; @@ -60,204 +61,204 @@ pub trait WeightInfo { fn check_payment() -> Weight; } -/// Weights for `pallet_salary` using the Substrate node and recommended hardware. +/// Weights for pallet_salary using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) fn init() -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `1541` - // Minimum execution time: 7_421_000 picoseconds. - Weight::from_parts(7_819_000, 1541) + // Minimum execution time: 10_778_000 picoseconds. + Weight::from_parts(11_084_000, 1541) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) fn bump() -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1541` - // Minimum execution time: 8_651_000 picoseconds. - Weight::from_parts(9_056_000, 1541) + // Minimum execution time: 12_042_000 picoseconds. + Weight::from_parts(12_645_000, 1541) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Salary::Status` (r:1 w:0) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:0) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) fn induct() -> Weight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3543` - // Minimum execution time: 16_513_000 picoseconds. - Weight::from_parts(17_305_000, 3543) + // Minimum execution time: 18_374_000 picoseconds. + Weight::from_parts(19_200_000, 3543) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) fn register() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3543` - // Minimum execution time: 18_913_000 picoseconds. - Weight::from_parts(19_867_000, 3543) + // Minimum execution time: 22_696_000 picoseconds. + Weight::from_parts(23_275_000, 3543) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) fn payout() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3543` - // Minimum execution time: 53_297_000 picoseconds. - Weight::from_parts(55_144_000, 3543) + // Minimum execution time: 63_660_000 picoseconds. + Weight::from_parts(65_006_000, 3543) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn payout_other() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3593` - // Minimum execution time: 53_638_000 picoseconds. - Weight::from_parts(55_328_000, 3593) + // Minimum execution time: 64_706_000 picoseconds. + Weight::from_parts(65_763_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) fn check_payment() -> Weight { // Proof Size summary in bytes: // Measured: `170` // Estimated: `3543` - // Minimum execution time: 10_557_000 picoseconds. - Weight::from_parts(11_145_000, 3543) + // Minimum execution time: 11_838_000 picoseconds. + Weight::from_parts(12_323_000, 3543) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) fn init() -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `1541` - // Minimum execution time: 7_421_000 picoseconds. - Weight::from_parts(7_819_000, 1541) + // Minimum execution time: 10_778_000 picoseconds. + Weight::from_parts(11_084_000, 1541) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) fn bump() -> Weight { // Proof Size summary in bytes: // Measured: `86` // Estimated: `1541` - // Minimum execution time: 8_651_000 picoseconds. - Weight::from_parts(9_056_000, 1541) + // Minimum execution time: 12_042_000 picoseconds. + Weight::from_parts(12_645_000, 1541) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Salary::Status` (r:1 w:0) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:0) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) fn induct() -> Weight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3543` - // Minimum execution time: 16_513_000 picoseconds. - Weight::from_parts(17_305_000, 3543) + // Minimum execution time: 18_374_000 picoseconds. + Weight::from_parts(19_200_000, 3543) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) fn register() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3543` - // Minimum execution time: 18_913_000 picoseconds. - Weight::from_parts(19_867_000, 3543) + // Minimum execution time: 22_696_000 picoseconds. + Weight::from_parts(23_275_000, 3543) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) fn payout() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3543` - // Minimum execution time: 53_297_000 picoseconds. - Weight::from_parts(55_144_000, 3543) + // Minimum execution time: 63_660_000 picoseconds. + Weight::from_parts(65_006_000, 3543) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) - /// Storage: `RankedCollective::Members` (r:1 w:0) - /// Proof: `RankedCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) + /// Storage: RankedCollective Members (r:1 w:0) + /// Proof: RankedCollective Members (max_values: None, max_size: Some(42), added: 2517, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn payout_other() -> Weight { // Proof Size summary in bytes: // Measured: `462` // Estimated: `3593` - // Minimum execution time: 53_638_000 picoseconds. - Weight::from_parts(55_328_000, 3593) + // Minimum execution time: 64_706_000 picoseconds. + Weight::from_parts(65_763_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Salary::Status` (r:1 w:1) - /// Proof: `Salary::Status` (`max_values`: Some(1), `max_size`: Some(56), added: 551, mode: `MaxEncodedLen`) - /// Storage: `Salary::Claimant` (r:1 w:1) - /// Proof: `Salary::Claimant` (`max_values`: None, `max_size`: Some(78), added: 2553, mode: `MaxEncodedLen`) + /// Storage: Salary Status (r:1 w:1) + /// Proof: Salary Status (max_values: Some(1), max_size: Some(56), added: 551, mode: MaxEncodedLen) + /// Storage: Salary Claimant (r:1 w:1) + /// Proof: Salary Claimant (max_values: None, max_size: Some(78), added: 2553, mode: MaxEncodedLen) fn check_payment() -> Weight { // Proof Size summary in bytes: // Measured: `170` // Estimated: `3543` - // Minimum execution time: 10_557_000 picoseconds. - Weight::from_parts(11_145_000, 3543) + // Minimum execution time: 11_838_000 picoseconds. + Weight::from_parts(12_323_000, 3543) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/sassafras/src/mock.rs b/substrate/frame/sassafras/src/mock.rs index 4c6efaa63a9..5e5909fcb0d 100644 --- a/substrate/frame/sassafras/src/mock.rs +++ b/substrate/frame/sassafras/src/mock.rs @@ -34,8 +34,7 @@ use sp_core::{ H256, U256, }; use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{Digest, DigestItem, Header}, + testing::{Digest, DigestItem, Header, TestXt}, BuildStorage, }; @@ -54,7 +53,7 @@ where RuntimeCall: From, { type OverarchingCall = RuntimeCall; - type Extrinsic = UncheckedExtrinsic; + type Extrinsic = TestXt; } impl pallet_sassafras::Config for Test { diff --git a/substrate/frame/scheduler/src/weights.rs b/substrate/frame/scheduler/src/weights.rs index 6c98145d266..9b7e5405a1b 100644 --- a/substrate/frame/scheduler/src/weights.rs +++ b/substrate/frame/scheduler/src/weights.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_scheduler` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-25, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_scheduler -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/scheduler/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_scheduler +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/scheduler/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -79,8 +77,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `31` // Estimated: `1489` - // Minimum execution time: 3_128_000 picoseconds. - Weight::from_parts(3_372_000, 1489) + // Minimum execution time: 3_040_000 picoseconds. + Weight::from_parts(3_202_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -91,10 +89,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 3_560_000 picoseconds. - Weight::from_parts(6_356_795, 110487) - // Standard Error: 493 - .saturating_add(Weight::from_parts(315_098, 0).saturating_mul(s.into())) + // Minimum execution time: 3_462_000 picoseconds. + Weight::from_parts(6_262_125, 110487) + // Standard Error: 536 + .saturating_add(Weight::from_parts(332_570, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -102,8 +100,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_501_000 picoseconds. - Weight::from_parts(3_722_000, 0) + // Minimum execution time: 3_425_000 picoseconds. + Weight::from_parts(3_680_000, 0) } /// Storage: `Preimage::PreimageFor` (r:1 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) @@ -116,10 +114,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `246 + s * (1 ±0)` // Estimated: `3711 + s * (1 ±0)` - // Minimum execution time: 17_976_000 picoseconds. - Weight::from_parts(18_137_000, 3711) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1_173, 0).saturating_mul(s.into())) + // Minimum execution time: 17_564_000 picoseconds. + Weight::from_parts(17_887_000, 3711) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_253, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(s.into())) @@ -130,16 +128,16 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_935_000 picoseconds. - Weight::from_parts(5_133_000, 0) + // Minimum execution time: 4_934_000 picoseconds. + Weight::from_parts(5_275_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn service_task_periodic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_467_000 picoseconds. - Weight::from_parts(3_654_000, 0) + // Minimum execution time: 3_348_000 picoseconds. + Weight::from_parts(3_561_000, 0) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -149,16 +147,16 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3997` - // Minimum execution time: 6_528_000 picoseconds. - Weight::from_parts(6_820_000, 3997) + // Minimum execution time: 6_395_000 picoseconds. + Weight::from_parts(6_642_000, 3997) .saturating_add(T::DbWeight::get().reads(2_u64)) } fn execute_dispatch_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_202_000 picoseconds. - Weight::from_parts(2_360_000, 0) + // Minimum execution time: 2_167_000 picoseconds. + Weight::from_parts(2_266_000, 0) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) @@ -167,17 +165,15 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 10_222_000 picoseconds. - Weight::from_parts(13_654_958, 110487) - // Standard Error: 676 - .saturating_add(Weight::from_parts(338_633, 0).saturating_mul(s.into())) + // Minimum execution time: 10_009_000 picoseconds. + Weight::from_parts(13_565_985, 110487) + // Standard Error: 575 + .saturating_add(Weight::from_parts(354_760, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Lookup` (r:0 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. @@ -185,12 +181,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 15_517_000 picoseconds. - Weight::from_parts(17_464_075, 110487) - // Standard Error: 952 - .saturating_add(Weight::from_parts(495_806, 0).saturating_mul(s.into())) + // Minimum execution time: 14_048_000 picoseconds. + Weight::from_parts(15_141_696, 110487) + // Standard Error: 1_082 + .saturating_add(Weight::from_parts(533_390, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Scheduler::Lookup` (r:1 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) @@ -201,10 +197,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `596 + s * (178 ±0)` // Estimated: `110487` - // Minimum execution time: 13_091_000 picoseconds. - Weight::from_parts(19_101_313, 110487) - // Standard Error: 662 - .saturating_add(Weight::from_parts(342_468, 0).saturating_mul(s.into())) + // Minimum execution time: 12_902_000 picoseconds. + Weight::from_parts(18_957_156, 110487) + // Standard Error: 792 + .saturating_add(Weight::from_parts(361_909, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -212,35 +208,35 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. fn cancel_named(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `709 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 17_579_000 picoseconds. - Weight::from_parts(20_561_921, 110487) - // Standard Error: 792 - .saturating_add(Weight::from_parts(500_463, 0).saturating_mul(s.into())) + // Minimum execution time: 15_933_000 picoseconds. + Weight::from_parts(18_091_415, 110487) + // Standard Error: 779 + .saturating_add(Weight::from_parts(534_402, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: `Scheduler::Retries` (r:1 w:2) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Lookup` (r:0 w:1) + /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. fn schedule_retry(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `118` + // Measured: `159` // Estimated: `110487` - // Minimum execution time: 8_996_000 picoseconds. - Weight::from_parts(11_393_234, 110487) - // Standard Error: 190 - .saturating_add(Weight::from_parts(6_714, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Minimum execution time: 14_155_000 picoseconds. + Weight::from_parts(16_447_031, 110487) + // Standard Error: 233 + .saturating_add(Weight::from_parts(8_424, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Scheduler::Agenda` (r:1 w:0) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) @@ -248,10 +244,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn set_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `90705` + // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 121_505_000 picoseconds. - Weight::from_parts(124_306_000, 110487) + // Minimum execution time: 8_130_000 picoseconds. + Weight::from_parts(9_047_554, 110487) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -263,10 +259,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn set_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `91747` + // Measured: `647 + s * (178 ±0)` // Estimated: `110487` - // Minimum execution time: 128_070_000 picoseconds. - Weight::from_parts(132_683_000, 110487) + // Minimum execution time: 10_838_000 picoseconds. + Weight::from_parts(12_804_076, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -276,10 +272,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `90717` + // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 118_260_000 picoseconds. - Weight::from_parts(119_722_000, 110487) + // Minimum execution time: 8_130_000 picoseconds. + Weight::from_parts(9_047_554, 110487) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -291,10 +287,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `91759` + // Measured: `647 + s * (178 ±0)` // Estimated: `110487` - // Minimum execution time: 129_036_000 picoseconds. - Weight::from_parts(133_975_000, 110487) + // Minimum execution time: 10_838_000 picoseconds. + Weight::from_parts(12_804_076, 110487) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -308,8 +304,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `31` // Estimated: `1489` - // Minimum execution time: 3_128_000 picoseconds. - Weight::from_parts(3_372_000, 1489) + // Minimum execution time: 3_040_000 picoseconds. + Weight::from_parts(3_202_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -320,10 +316,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 3_560_000 picoseconds. - Weight::from_parts(6_356_795, 110487) - // Standard Error: 493 - .saturating_add(Weight::from_parts(315_098, 0).saturating_mul(s.into())) + // Minimum execution time: 3_462_000 picoseconds. + Weight::from_parts(6_262_125, 110487) + // Standard Error: 536 + .saturating_add(Weight::from_parts(332_570, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -331,8 +327,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_501_000 picoseconds. - Weight::from_parts(3_722_000, 0) + // Minimum execution time: 3_425_000 picoseconds. + Weight::from_parts(3_680_000, 0) } /// Storage: `Preimage::PreimageFor` (r:1 w:1) /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) @@ -345,10 +341,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `246 + s * (1 ±0)` // Estimated: `3711 + s * (1 ±0)` - // Minimum execution time: 17_976_000 picoseconds. - Weight::from_parts(18_137_000, 3711) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1_173, 0).saturating_mul(s.into())) + // Minimum execution time: 17_564_000 picoseconds. + Weight::from_parts(17_887_000, 3711) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_253, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(s.into())) @@ -359,16 +355,16 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_935_000 picoseconds. - Weight::from_parts(5_133_000, 0) + // Minimum execution time: 4_934_000 picoseconds. + Weight::from_parts(5_275_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn service_task_periodic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_467_000 picoseconds. - Weight::from_parts(3_654_000, 0) + // Minimum execution time: 3_348_000 picoseconds. + Weight::from_parts(3_561_000, 0) } /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -378,16 +374,16 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3997` - // Minimum execution time: 6_528_000 picoseconds. - Weight::from_parts(6_820_000, 3997) + // Minimum execution time: 6_395_000 picoseconds. + Weight::from_parts(6_642_000, 3997) .saturating_add(RocksDbWeight::get().reads(2_u64)) } fn execute_dispatch_unsigned() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_202_000 picoseconds. - Weight::from_parts(2_360_000, 0) + // Minimum execution time: 2_167_000 picoseconds. + Weight::from_parts(2_266_000, 0) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) @@ -396,17 +392,15 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 10_222_000 picoseconds. - Weight::from_parts(13_654_958, 110487) - // Standard Error: 676 - .saturating_add(Weight::from_parts(338_633, 0).saturating_mul(s.into())) + // Minimum execution time: 10_009_000 picoseconds. + Weight::from_parts(13_565_985, 110487) + // Standard Error: 575 + .saturating_add(Weight::from_parts(354_760, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Lookup` (r:0 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. @@ -414,12 +408,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 15_517_000 picoseconds. - Weight::from_parts(17_464_075, 110487) - // Standard Error: 952 - .saturating_add(Weight::from_parts(495_806, 0).saturating_mul(s.into())) + // Minimum execution time: 14_048_000 picoseconds. + Weight::from_parts(15_141_696, 110487) + // Standard Error: 1_082 + .saturating_add(Weight::from_parts(533_390, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Scheduler::Lookup` (r:1 w:1) /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) @@ -430,10 +424,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `596 + s * (178 ±0)` // Estimated: `110487` - // Minimum execution time: 13_091_000 picoseconds. - Weight::from_parts(19_101_313, 110487) - // Standard Error: 662 - .saturating_add(Weight::from_parts(342_468, 0).saturating_mul(s.into())) + // Minimum execution time: 12_902_000 picoseconds. + Weight::from_parts(18_957_156, 110487) + // Standard Error: 792 + .saturating_add(Weight::from_parts(361_909, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -441,35 +435,35 @@ impl WeightInfo for () { /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. fn cancel_named(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `709 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 17_579_000 picoseconds. - Weight::from_parts(20_561_921, 110487) - // Standard Error: 792 - .saturating_add(Weight::from_parts(500_463, 0).saturating_mul(s.into())) + // Minimum execution time: 15_933_000 picoseconds. + Weight::from_parts(18_091_415, 110487) + // Standard Error: 779 + .saturating_add(Weight::from_parts(534_402, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: `Scheduler::Retries` (r:1 w:2) + /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) /// Storage: `Scheduler::Agenda` (r:1 w:1) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) - /// Storage: `Scheduler::Retries` (r:0 w:1) - /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) + /// Storage: `Scheduler::Lookup` (r:0 w:1) + /// Proof: `Scheduler::Lookup` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// The range of component `s` is `[1, 512]`. fn schedule_retry(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `118` + // Measured: `159` // Estimated: `110487` - // Minimum execution time: 8_996_000 picoseconds. - Weight::from_parts(11_393_234, 110487) - // Standard Error: 190 - .saturating_add(Weight::from_parts(6_714, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Minimum execution time: 14_155_000 picoseconds. + Weight::from_parts(16_447_031, 110487) + // Standard Error: 233 + .saturating_add(Weight::from_parts(8_424, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `Scheduler::Agenda` (r:1 w:0) /// Proof: `Scheduler::Agenda` (`max_values`: None, `max_size`: Some(107022), added: 109497, mode: `MaxEncodedLen`) @@ -477,10 +471,10 @@ impl WeightInfo for () { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn set_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `90705` + // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 121_505_000 picoseconds. - Weight::from_parts(124_306_000, 110487) + // Minimum execution time: 8_130_000 picoseconds. + Weight::from_parts(9_047_554, 110487) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -492,10 +486,10 @@ impl WeightInfo for () { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn set_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `91747` + // Measured: `647 + s * (178 ±0)` // Estimated: `110487` - // Minimum execution time: 128_070_000 picoseconds. - Weight::from_parts(132_683_000, 110487) + // Minimum execution time: 10_838_000 picoseconds. + Weight::from_parts(12_804_076, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -505,10 +499,10 @@ impl WeightInfo for () { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel_retry() -> Weight { // Proof Size summary in bytes: - // Measured: `90717` + // Measured: `81 + s * (177 ±0)` // Estimated: `110487` - // Minimum execution time: 118_260_000 picoseconds. - Weight::from_parts(119_722_000, 110487) + // Minimum execution time: 8_130_000 picoseconds. + Weight::from_parts(9_047_554, 110487) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -520,10 +514,10 @@ impl WeightInfo for () { /// Proof: `Scheduler::Retries` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`) fn cancel_retry_named() -> Weight { // Proof Size summary in bytes: - // Measured: `91759` + // Measured: `647 + s * (178 ±0)` // Estimated: `110487` - // Minimum execution time: 129_036_000 picoseconds. - Weight::from_parts(133_975_000, 110487) + // Minimum execution time: 10_838_000 picoseconds. + Weight::from_parts(12_804_076, 110487) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/session/src/weights.rs b/substrate/frame/session/src/weights.rs index 09eb665ff3d..dd9848fd2c1 100644 --- a/substrate/frame/session/src/weights.rs +++ b/substrate/frame/session/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_session` +//! Autogenerated weights for pallet_session //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/session/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/session/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,77 +50,77 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_session`. +/// Weight functions needed for pallet_session. pub trait WeightInfo { fn set_keys() -> Weight; fn purge_keys() -> Weight; } -/// Weights for `pallet_session` using the Substrate node and recommended hardware. +/// Weights for pallet_session using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Session::NextKeys` (r:1 w:1) - /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Session::KeyOwner` (r:6 w:6) - /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Session NextKeys (r:1 w:1) + /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) + /// Storage: Session KeyOwner (r:4 w:4) + /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) fn set_keys() -> Weight { // Proof Size summary in bytes: - // Measured: `1919` - // Estimated: `17759` - // Minimum execution time: 57_921_000 picoseconds. - Weight::from_parts(58_960_000, 17759) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + // Measured: `1924` + // Estimated: `12814` + // Minimum execution time: 55_459_000 picoseconds. + Weight::from_parts(56_180_000, 12814) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Session::NextKeys` (r:1 w:1) - /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Session::KeyOwner` (r:0 w:6) - /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Session NextKeys (r:1 w:1) + /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) + /// Storage: Session KeyOwner (r:0 w:4) + /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) fn purge_keys() -> Weight { // Proof Size summary in bytes: - // Measured: `1817` - // Estimated: `5282` - // Minimum execution time: 40_983_000 picoseconds. - Weight::from_parts(42_700_000, 5282) + // Measured: `1791` + // Estimated: `5256` + // Minimum execution time: 40_194_000 picoseconds. + Weight::from_parts(41_313_000, 5256) .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Session::NextKeys` (r:1 w:1) - /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Session::KeyOwner` (r:6 w:6) - /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Session NextKeys (r:1 w:1) + /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) + /// Storage: Session KeyOwner (r:4 w:4) + /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) fn set_keys() -> Weight { // Proof Size summary in bytes: - // Measured: `1919` - // Estimated: `17759` - // Minimum execution time: 57_921_000 picoseconds. - Weight::from_parts(58_960_000, 17759) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + // Measured: `1924` + // Estimated: `12814` + // Minimum execution time: 55_459_000 picoseconds. + Weight::from_parts(56_180_000, 12814) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Staking::Ledger` (r:1 w:0) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Session::NextKeys` (r:1 w:1) - /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Session::KeyOwner` (r:0 w:6) - /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Staking Ledger (r:1 w:0) + /// Proof: Staking Ledger (max_values: None, max_size: Some(1091), added: 3566, mode: MaxEncodedLen) + /// Storage: Session NextKeys (r:1 w:1) + /// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured) + /// Storage: Session KeyOwner (r:0 w:4) + /// Proof Skipped: Session KeyOwner (max_values: None, max_size: None, mode: Measured) fn purge_keys() -> Weight { // Proof Size summary in bytes: - // Measured: `1817` - // Estimated: `5282` - // Minimum execution time: 40_983_000 picoseconds. - Weight::from_parts(42_700_000, 5282) + // Measured: `1791` + // Estimated: `5256` + // Minimum execution time: 40_194_000 picoseconds. + Weight::from_parts(41_313_000, 5256) .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } } diff --git a/substrate/frame/society/src/weights.rs b/substrate/frame/society/src/weights.rs index 1245f762972..c32c2383ac9 100644 --- a/substrate/frame/society/src/weights.rs +++ b/substrate/frame/society/src/weights.rs @@ -7,7 +7,7 @@ // 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 +// 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, @@ -15,41 +15,35 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_society` +//! Autogenerated weights for pallet_society //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-09-13, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev // --steps=50 // --repeat=20 // --pallet=pallet_society -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/society/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --template=./.maintain/frame-weight-template.hbs +// --header=./HEADER-APACHE2 +// --output=./frame/society/src/weights.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] -#![allow(missing_docs)] use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_society`. +/// Weight functions needed for pallet_society. pub trait WeightInfo { fn bid() -> Weight; fn unbid() -> Weight; @@ -73,739 +67,309 @@ pub trait WeightInfo { fn cleanup_challenge() -> Weight; } -/// Weights for `pallet_society` using the Substrate node and recommended hardware. +/// Weights for pallet_society using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Society::Bids` (r:1 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:1 w:0) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:0) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::SuspendedMembers` (r:1 w:0) - /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:1 w:0) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + // Storage: Society Bids (r:1 w:1) + // Storage: Society Candidates (r:1 w:0) + // Storage: Society Members (r:1 w:0) + // Storage: Society SuspendedMembers (r:1 w:0) + // Storage: Society Parameters (r:1 w:0) fn bid() -> Weight { - // Proof Size summary in bytes: - // Measured: `444` - // Estimated: `3909` - // Minimum execution time: 29_905_000 picoseconds. - Weight::from_parts(31_031_000, 3909) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `Society::Bids` (r:1 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Bids (r:1 w:1) fn unbid() -> Weight { - // Proof Size summary in bytes: - // Measured: `461` - // Estimated: `1946` - // Minimum execution time: 23_038_000 picoseconds. - Weight::from_parts(23_904_000, 1946) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `Society::Bids` (r:1 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:1 w:0) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:2 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::SuspendedMembers` (r:1 w:0) - /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Bids (r:1 w:1) + // Storage: Society Candidates (r:1 w:0) + // Storage: Society Members (r:2 w:1) + // Storage: Society SuspendedMembers (r:1 w:0) fn vouch() -> Weight { - // Proof Size summary in bytes: - // Measured: `481` - // Estimated: `6421` - // Minimum execution time: 21_197_000 picoseconds. - Weight::from_parts(22_043_000, 6421) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Bids` (r:1 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Bids (r:1 w:1) + // Storage: Society Members (r:1 w:1) fn unvouch() -> Weight { - // Proof Size summary in bytes: - // Measured: `535` - // Estimated: `4000` - // Minimum execution time: 14_402_000 picoseconds. - Weight::from_parts(15_171_000, 4000) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:0) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Votes` (r:1 w:1) - /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society Members (r:1 w:0) + // Storage: Society Votes (r:1 w:1) fn vote() -> Weight { - // Proof Size summary in bytes: - // Measured: `569` - // Estimated: `4034` - // Minimum execution time: 21_930_000 picoseconds. - Weight::from_parts(22_666_000, 4034) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Defending` (r:1 w:1) - /// Proof: `Society::Defending` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:0) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::ChallengeRoundCount` (r:1 w:0) - /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::DefenderVotes` (r:1 w:1) - /// Proof: `Society::DefenderVotes` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Defending (r:1 w:1) + // Storage: Society Members (r:1 w:0) + // Storage: Society ChallengeRoundCount (r:1 w:0) + // Storage: Society DefenderVotes (r:1 w:1) fn defender_vote() -> Weight { - // Proof Size summary in bytes: - // Measured: `561` - // Estimated: `4026` - // Minimum execution time: 18_821_000 picoseconds. - Weight::from_parts(19_633_000, 4026) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Members` (r:1 w:0) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Payouts` (r:1 w:1) - /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + Weight::zero() + } + // Storage: Society Members (r:1 w:0) + // Storage: Society Payouts (r:1 w:1) + // Storage: System Account (r:1 w:1) fn payout() -> Weight { - // Proof Size summary in bytes: - // Measured: `650` - // Estimated: `4115` - // Minimum execution time: 47_262_000 picoseconds. - Weight::from_parts(48_313_000, 4115) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Members` (r:1 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Payouts` (r:1 w:1) - /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Members (r:1 w:1) + // Storage: Society Payouts (r:1 w:1) fn waive_repay() -> Weight { - // Proof Size summary in bytes: - // Measured: `547` - // Estimated: `4012` - // Minimum execution time: 18_189_000 picoseconds. - Weight::from_parts(19_038_000, 4012) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Head` (r:1 w:1) - /// Proof: `Society::Head` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:1) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberByIndex` (r:0 w:1) - /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Founder` (r:0 w:1) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Rules` (r:0 w:1) - /// Proof: `Society::Rules` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:0 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:0 w:1) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Head (r:1 w:1) + // Storage: Society MemberCount (r:1 w:1) + // Storage: Society MemberByIndex (r:0 w:1) + // Storage: Society Founder (r:0 w:1) + // Storage: Society Rules (r:0 w:1) + // Storage: Society Members (r:0 w:1) + // Storage: Society Parameters (r:0 w:1) fn found_society() -> Weight { - // Proof Size summary in bytes: - // Measured: `180` - // Estimated: `1665` - // Minimum execution time: 14_815_000 picoseconds. - Weight::from_parts(15_426_000, 1665) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) - } - /// Storage: `Society::Founder` (r:1 w:1) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:1) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:5 w:5) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberByIndex` (r:5 w:5) - /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Votes` (r:4 w:4) - /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:4 w:4) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Head` (r:0 w:1) - /// Proof: `Society::Head` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Defending` (r:0 w:1) - /// Proof: `Society::Defending` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::ChallengeRoundCount` (r:0 w:1) - /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Skeptic` (r:0 w:1) - /// Proof: `Society::Skeptic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Pot` (r:0 w:1) - /// Proof: `Society::Pot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Rules` (r:0 w:1) - /// Proof: `Society::Rules` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:0 w:1) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Bids` (r:0 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:0 w:1) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::NextHead` (r:0 w:1) - /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:1) + // Storage: Society MemberCount (r:1 w:1) + // Storage: Society Head (r:0 w:1) + // Storage: Society Defending (r:0 w:1) + // Storage: Society ChallengeRoundCount (r:0 w:1) + // Storage: Society MemberByIndex (r:0 w:5) + // Storage: Society Skeptic (r:0 w:1) + // Storage: Society Candidates (r:0 w:4) + // Storage: Society Pot (r:0 w:1) + // Storage: Society Rules (r:0 w:1) + // Storage: Society Votes (r:0 w:4) + // Storage: Society Members (r:0 w:5) + // Storage: Society RoundCount (r:0 w:1) + // Storage: Society Bids (r:0 w:1) + // Storage: Society Parameters (r:0 w:1) + // Storage: Society NextHead (r:0 w:1) fn dissolve() -> Weight { - // Proof Size summary in bytes: - // Measured: `1654` - // Estimated: `15019` - // Minimum execution time: 57_787_000 picoseconds. - Weight::from_parts(59_489_000, 15019) - .saturating_add(T::DbWeight::get().reads(20_u64)) - .saturating_add(T::DbWeight::get().writes(30_u64)) - } - /// Storage: `Society::Founder` (r:1 w:0) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::SuspendedMembers` (r:1 w:1) - /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Payouts` (r:1 w:0) - /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Pot` (r:1 w:1) - /// Proof: `Society::Pot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:0) + // Storage: Society SuspendedMembers (r:1 w:1) + // Storage: Society Payouts (r:1 w:0) + // Storage: Society Pot (r:1 w:1) fn judge_suspended_member() -> Weight { - // Proof Size summary in bytes: - // Measured: `505` - // Estimated: `3970` - // Minimum execution time: 19_262_000 picoseconds. - Weight::from_parts(19_752_000, 3970) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Founder` (r:1 w:0) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:0) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:0 w:1) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:0) + // Storage: Society MemberCount (r:1 w:0) + // Storage: Society Parameters (r:0 w:1) fn set_parameters() -> Weight { - // Proof Size summary in bytes: - // Measured: `387` - // Estimated: `1872` - // Minimum execution time: 10_656_000 picoseconds. - Weight::from_parts(11_063_000, 1872) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Skeptic` (r:1 w:0) - /// Proof: `Society::Skeptic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Votes` (r:1 w:0) - /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:1 w:0) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) + // Storage: Society Skeptic (r:1 w:0) + // Storage: Society Votes (r:1 w:0) + // Storage: Society Members (r:1 w:1) + // Storage: Society Parameters (r:1 w:0) fn punish_skeptic() -> Weight { - // Proof Size summary in bytes: - // Measured: `636` - // Estimated: `4101` - // Minimum execution time: 22_837_000 picoseconds. - Weight::from_parts(23_738_000, 4101) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:1 w:0) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:1) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::NextHead` (r:1 w:1) - /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Society::MemberByIndex` (r:0 w:1) - /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:0 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) + // Storage: Society Parameters (r:1 w:0) + // Storage: Society MemberCount (r:1 w:1) + // Storage: Society NextHead (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Society MemberByIndex (r:0 w:1) + // Storage: Society Members (r:0 w:1) fn claim_membership() -> Weight { - // Proof Size summary in bytes: - // Measured: `632` - // Estimated: `4097` - // Minimum execution time: 35_142_000 picoseconds. - Weight::from_parts(36_811_000, 4097) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) - } - /// Storage: `Society::Founder` (r:1 w:0) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:1 w:0) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:1) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::NextHead` (r:1 w:1) - /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Society::MemberByIndex` (r:0 w:1) - /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:0 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:0) + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) + // Storage: Society Parameters (r:1 w:0) + // Storage: Society MemberCount (r:1 w:1) + // Storage: Society NextHead (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Society MemberByIndex (r:0 w:1) + // Storage: Society Members (r:0 w:1) fn bestow_membership() -> Weight { - // Proof Size summary in bytes: - // Measured: `650` - // Estimated: `4115` - // Minimum execution time: 37_133_000 picoseconds. - Weight::from_parts(38_366_000, 4115) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) - } - /// Storage: `Society::Founder` (r:1 w:0) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:0) + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) fn kick_candidate() -> Weight { - // Proof Size summary in bytes: - // Measured: `776` - // Estimated: `6196` - // Minimum execution time: 37_033_000 picoseconds. - Weight::from_parts(38_293_000, 6196) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) fn resign_candidacy() -> Weight { - // Proof Size summary in bytes: - // Measured: `746` - // Estimated: `6196` - // Minimum execution time: 35_203_000 picoseconds. - Weight::from_parts(36_252_000, 6196) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) fn drop_candidate() -> Weight { - // Proof Size summary in bytes: - // Measured: `758` - // Estimated: `6196` - // Minimum execution time: 35_518_000 picoseconds. - Weight::from_parts(36_508_000, 6196) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:0) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::VoteClearCursor` (r:1 w:0) - /// Proof: `Society::VoteClearCursor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Votes` (r:2 w:2) - /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:0) + // Storage: Society VoteClearCursor (r:1 w:0) + // Storage: Society Votes (r:0 w:2) fn cleanup_candidacy() -> Weight { - // Proof Size summary in bytes: - // Measured: `552` - // Estimated: `6492` - // Minimum execution time: 17_001_000 picoseconds. - Weight::from_parts(17_845_000, 6492) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `Society::ChallengeRoundCount` (r:1 w:0) - /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::DefenderVotes` (r:1 w:1) - /// Proof: `Society::DefenderVotes` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society ChallengeRoundCount (r:1 w:0) + // Storage: Society DefenderVotes (r:0 w:1) fn cleanup_challenge() -> Weight { - // Proof Size summary in bytes: - // Measured: `510` - // Estimated: `3975` - // Minimum execution time: 11_583_000 picoseconds. - Weight::from_parts(12_134_000, 3975) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + Weight::zero() } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Society::Bids` (r:1 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:1 w:0) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:0) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::SuspendedMembers` (r:1 w:0) - /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:1 w:0) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + // Storage: Society Bids (r:1 w:1) + // Storage: Society Candidates (r:1 w:0) + // Storage: Society Members (r:1 w:0) + // Storage: Society SuspendedMembers (r:1 w:0) + // Storage: Society Parameters (r:1 w:0) fn bid() -> Weight { - // Proof Size summary in bytes: - // Measured: `444` - // Estimated: `3909` - // Minimum execution time: 29_905_000 picoseconds. - Weight::from_parts(31_031_000, 3909) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `Society::Bids` (r:1 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Bids (r:1 w:1) fn unbid() -> Weight { - // Proof Size summary in bytes: - // Measured: `461` - // Estimated: `1946` - // Minimum execution time: 23_038_000 picoseconds. - Weight::from_parts(23_904_000, 1946) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `Society::Bids` (r:1 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:1 w:0) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:2 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::SuspendedMembers` (r:1 w:0) - /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Bids (r:1 w:1) + // Storage: Society Candidates (r:1 w:0) + // Storage: Society Members (r:2 w:1) + // Storage: Society SuspendedMembers (r:1 w:0) fn vouch() -> Weight { - // Proof Size summary in bytes: - // Measured: `481` - // Estimated: `6421` - // Minimum execution time: 21_197_000 picoseconds. - Weight::from_parts(22_043_000, 6421) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Bids` (r:1 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Bids (r:1 w:1) + // Storage: Society Members (r:1 w:1) fn unvouch() -> Weight { - // Proof Size summary in bytes: - // Measured: `535` - // Estimated: `4000` - // Minimum execution time: 14_402_000 picoseconds. - Weight::from_parts(15_171_000, 4000) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:0) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Votes` (r:1 w:1) - /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society Members (r:1 w:0) + // Storage: Society Votes (r:1 w:1) fn vote() -> Weight { - // Proof Size summary in bytes: - // Measured: `569` - // Estimated: `4034` - // Minimum execution time: 21_930_000 picoseconds. - Weight::from_parts(22_666_000, 4034) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Defending` (r:1 w:1) - /// Proof: `Society::Defending` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:0) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::ChallengeRoundCount` (r:1 w:0) - /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::DefenderVotes` (r:1 w:1) - /// Proof: `Society::DefenderVotes` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Defending (r:1 w:1) + // Storage: Society Members (r:1 w:0) + // Storage: Society ChallengeRoundCount (r:1 w:0) + // Storage: Society DefenderVotes (r:1 w:1) fn defender_vote() -> Weight { - // Proof Size summary in bytes: - // Measured: `561` - // Estimated: `4026` - // Minimum execution time: 18_821_000 picoseconds. - Weight::from_parts(19_633_000, 4026) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Members` (r:1 w:0) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Payouts` (r:1 w:1) - /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + Weight::zero() + } + // Storage: Society Members (r:1 w:0) + // Storage: Society Payouts (r:1 w:1) + // Storage: System Account (r:1 w:1) fn payout() -> Weight { - // Proof Size summary in bytes: - // Measured: `650` - // Estimated: `4115` - // Minimum execution time: 47_262_000 picoseconds. - Weight::from_parts(48_313_000, 4115) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Members` (r:1 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Payouts` (r:1 w:1) - /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Members (r:1 w:1) + // Storage: Society Payouts (r:1 w:1) fn waive_repay() -> Weight { - // Proof Size summary in bytes: - // Measured: `547` - // Estimated: `4012` - // Minimum execution time: 18_189_000 picoseconds. - Weight::from_parts(19_038_000, 4012) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Head` (r:1 w:1) - /// Proof: `Society::Head` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:1) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberByIndex` (r:0 w:1) - /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Founder` (r:0 w:1) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Rules` (r:0 w:1) - /// Proof: `Society::Rules` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:0 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:0 w:1) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Head (r:1 w:1) + // Storage: Society MemberCount (r:1 w:1) + // Storage: Society MemberByIndex (r:0 w:1) + // Storage: Society Founder (r:0 w:1) + // Storage: Society Rules (r:0 w:1) + // Storage: Society Members (r:0 w:1) + // Storage: Society Parameters (r:0 w:1) fn found_society() -> Weight { - // Proof Size summary in bytes: - // Measured: `180` - // Estimated: `1665` - // Minimum execution time: 14_815_000 picoseconds. - Weight::from_parts(15_426_000, 1665) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - } - /// Storage: `Society::Founder` (r:1 w:1) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:1) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:5 w:5) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberByIndex` (r:5 w:5) - /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Votes` (r:4 w:4) - /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:4 w:4) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Head` (r:0 w:1) - /// Proof: `Society::Head` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Defending` (r:0 w:1) - /// Proof: `Society::Defending` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::ChallengeRoundCount` (r:0 w:1) - /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Skeptic` (r:0 w:1) - /// Proof: `Society::Skeptic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Pot` (r:0 w:1) - /// Proof: `Society::Pot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Rules` (r:0 w:1) - /// Proof: `Society::Rules` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:0 w:1) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Bids` (r:0 w:1) - /// Proof: `Society::Bids` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:0 w:1) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::NextHead` (r:0 w:1) - /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:1) + // Storage: Society MemberCount (r:1 w:1) + // Storage: Society Head (r:0 w:1) + // Storage: Society Defending (r:0 w:1) + // Storage: Society ChallengeRoundCount (r:0 w:1) + // Storage: Society MemberByIndex (r:0 w:5) + // Storage: Society Skeptic (r:0 w:1) + // Storage: Society Candidates (r:0 w:4) + // Storage: Society Pot (r:0 w:1) + // Storage: Society Rules (r:0 w:1) + // Storage: Society Votes (r:0 w:4) + // Storage: Society Members (r:0 w:5) + // Storage: Society RoundCount (r:0 w:1) + // Storage: Society Bids (r:0 w:1) + // Storage: Society Parameters (r:0 w:1) + // Storage: Society NextHead (r:0 w:1) fn dissolve() -> Weight { - // Proof Size summary in bytes: - // Measured: `1654` - // Estimated: `15019` - // Minimum execution time: 57_787_000 picoseconds. - Weight::from_parts(59_489_000, 15019) - .saturating_add(RocksDbWeight::get().reads(20_u64)) - .saturating_add(RocksDbWeight::get().writes(30_u64)) - } - /// Storage: `Society::Founder` (r:1 w:0) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::SuspendedMembers` (r:1 w:1) - /// Proof: `Society::SuspendedMembers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Payouts` (r:1 w:0) - /// Proof: `Society::Payouts` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Pot` (r:1 w:1) - /// Proof: `Society::Pot` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:0) + // Storage: Society SuspendedMembers (r:1 w:1) + // Storage: Society Payouts (r:1 w:0) + // Storage: Society Pot (r:1 w:1) fn judge_suspended_member() -> Weight { - // Proof Size summary in bytes: - // Measured: `505` - // Estimated: `3970` - // Minimum execution time: 19_262_000 picoseconds. - Weight::from_parts(19_752_000, 3970) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Founder` (r:1 w:0) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:0) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:0 w:1) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:0) + // Storage: Society MemberCount (r:1 w:0) + // Storage: Society Parameters (r:0 w:1) fn set_parameters() -> Weight { - // Proof Size summary in bytes: - // Measured: `387` - // Estimated: `1872` - // Minimum execution time: 10_656_000 picoseconds. - Weight::from_parts(11_063_000, 1872) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Skeptic` (r:1 w:0) - /// Proof: `Society::Skeptic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Votes` (r:1 w:0) - /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:1 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:1 w:0) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) + // Storage: Society Skeptic (r:1 w:0) + // Storage: Society Votes (r:1 w:0) + // Storage: Society Members (r:1 w:1) + // Storage: Society Parameters (r:1 w:0) fn punish_skeptic() -> Weight { - // Proof Size summary in bytes: - // Measured: `636` - // Estimated: `4101` - // Minimum execution time: 22_837_000 picoseconds. - Weight::from_parts(23_738_000, 4101) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:1 w:0) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:1) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::NextHead` (r:1 w:1) - /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Society::MemberByIndex` (r:0 w:1) - /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:0 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) + // Storage: Society Parameters (r:1 w:0) + // Storage: Society MemberCount (r:1 w:1) + // Storage: Society NextHead (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Society MemberByIndex (r:0 w:1) + // Storage: Society Members (r:0 w:1) fn claim_membership() -> Weight { - // Proof Size summary in bytes: - // Measured: `632` - // Estimated: `4097` - // Minimum execution time: 35_142_000 picoseconds. - Weight::from_parts(36_811_000, 4097) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) - } - /// Storage: `Society::Founder` (r:1 w:0) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Parameters` (r:1 w:0) - /// Proof: `Society::Parameters` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::MemberCount` (r:1 w:1) - /// Proof: `Society::MemberCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::NextHead` (r:1 w:1) - /// Proof: `Society::NextHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Society::MemberByIndex` (r:0 w:1) - /// Proof: `Society::MemberByIndex` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Members` (r:0 w:1) - /// Proof: `Society::Members` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:0) + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) + // Storage: Society Parameters (r:1 w:0) + // Storage: Society MemberCount (r:1 w:1) + // Storage: Society NextHead (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Society MemberByIndex (r:0 w:1) + // Storage: Society Members (r:0 w:1) fn bestow_membership() -> Weight { - // Proof Size summary in bytes: - // Measured: `650` - // Estimated: `4115` - // Minimum execution time: 37_133_000 picoseconds. - Weight::from_parts(38_366_000, 4115) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) - } - /// Storage: `Society::Founder` (r:1 w:0) - /// Proof: `Society::Founder` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + Weight::zero() + } + // Storage: Society Founder (r:1 w:0) + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) fn kick_candidate() -> Weight { - // Proof Size summary in bytes: - // Measured: `776` - // Estimated: `6196` - // Minimum execution time: 37_033_000 picoseconds. - Weight::from_parts(38_293_000, 6196) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) fn resign_candidacy() -> Weight { - // Proof Size summary in bytes: - // Measured: `746` - // Estimated: `6196` - // Minimum execution time: 35_203_000 picoseconds. - Weight::from_parts(36_252_000, 6196) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:1) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::RoundCount` (r:1 w:0) - /// Proof: `Society::RoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:1) + // Storage: Society RoundCount (r:1 w:0) fn drop_candidate() -> Weight { - // Proof Size summary in bytes: - // Measured: `758` - // Estimated: `6196` - // Minimum execution time: 35_518_000 picoseconds. - Weight::from_parts(36_508_000, 6196) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: `Society::Candidates` (r:1 w:0) - /// Proof: `Society::Candidates` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::VoteClearCursor` (r:1 w:0) - /// Proof: `Society::VoteClearCursor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Society::Votes` (r:2 w:2) - /// Proof: `Society::Votes` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society Candidates (r:1 w:0) + // Storage: Society VoteClearCursor (r:1 w:0) + // Storage: Society Votes (r:0 w:2) fn cleanup_candidacy() -> Weight { - // Proof Size summary in bytes: - // Measured: `552` - // Estimated: `6492` - // Minimum execution time: 17_001_000 picoseconds. - Weight::from_parts(17_845_000, 6492) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `Society::ChallengeRoundCount` (r:1 w:0) - /// Proof: `Society::ChallengeRoundCount` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Society::DefenderVotes` (r:1 w:1) - /// Proof: `Society::DefenderVotes` (`max_values`: None, `max_size`: None, mode: `Measured`) + Weight::zero() + } + // Storage: Society ChallengeRoundCount (r:1 w:0) + // Storage: Society DefenderVotes (r:0 w:1) fn cleanup_challenge() -> Weight { - // Proof Size summary in bytes: - // Measured: `510` - // Estimated: `3975` - // Minimum execution time: 11_583_000 picoseconds. - Weight::from_parts(12_134_000, 3975) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + Weight::zero() } } diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs index 549e177491d..52db7c34bfd 100644 --- a/substrate/frame/src/lib.rs +++ b/substrate/frame/src/lib.rs @@ -249,8 +249,8 @@ pub mod runtime { /// The block type, which should be fed into [`frame_system::Config`]. /// - /// Should be parameterized with `T: frame_system::Config` and a tuple of - /// `TransactionExtension`. When in doubt, use [`SystemTransactionExtensionsOf`]. + /// Should be parameterized with `T: frame_system::Config` and a tuple of `SignedExtension`. + /// When in doubt, use [`SystemSignedExtensionsOf`]. // Note that this cannot be dependent on `T` for block-number because it would lead to a // circular dependency (self-referential generics). pub type BlockOf = generic::Block>; @@ -264,7 +264,7 @@ pub mod runtime { /// Default set of signed extensions exposed from the `frame_system`. /// /// crucially, this does NOT contain any tx-payment extension. - pub type SystemTransactionExtensionsOf = ( + pub type SystemSignedExtensionsOf = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/substrate/frame/staking/src/weights.rs b/substrate/frame/staking/src/weights.rs index 8288591a787..6f729e08ba5 100644 --- a/substrate/frame/staking/src/weights.rs +++ b/substrate/frame/staking/src/weights.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_staking` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-q7z7ruxr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_staking -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/staking/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_staking +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/staking/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -101,8 +99,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `927` // Estimated: `4764` - // Minimum execution time: 41_318_000 picoseconds. - Weight::from_parts(43_268_000, 4764) + // Minimum execution time: 42_042_000 picoseconds. + Weight::from_parts(43_292_000, 4764) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -122,8 +120,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1990` // Estimated: `8877` - // Minimum execution time: 85_666_000 picoseconds. - Weight::from_parts(88_749_000, 8877) + // Minimum execution time: 85_050_000 picoseconds. + Weight::from_parts(87_567_000, 8877) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -149,8 +147,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2195` // Estimated: `8877` - // Minimum execution time: 90_282_000 picoseconds. - Weight::from_parts(92_332_000, 8877) + // Minimum execution time: 89_076_000 picoseconds. + Weight::from_parts(92_715_000, 8877) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -164,18 +162,16 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1297` + // Measured: `1115` // Estimated: `4764` - // Minimum execution time: 44_626_000 picoseconds. - Weight::from_parts(47_254_657, 4764) - // Standard Error: 1_179 - .saturating_add(Weight::from_parts(57_657, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) + // Minimum execution time: 42_067_000 picoseconds. + Weight::from_parts(43_239_807, 4764) + // Standard Error: 831 + .saturating_add(Weight::from_parts(46_257, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Staking::Ledger` (r:1 w:1) @@ -211,10 +207,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 86_769_000 picoseconds. - Weight::from_parts(95_212_867, 6248) - // Standard Error: 3_706 - .saturating_add(Weight::from_parts(1_320_752, 0).saturating_mul(s.into())) + // Minimum execution time: 86_490_000 picoseconds. + Weight::from_parts(95_358_751, 6248) + // Standard Error: 3_952 + .saturating_add(Weight::from_parts(1_294_907, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(11_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -246,8 +242,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1372` // Estimated: `4556` - // Minimum execution time: 50_410_000 picoseconds. - Weight::from_parts(52_576_000, 4556) + // Minimum execution time: 50_326_000 picoseconds. + Weight::from_parts(52_253_000, 4556) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -260,10 +256,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1280 + k * (569 ±0)` // Estimated: `4556 + k * (3033 ±0)` - // Minimum execution time: 29_017_000 picoseconds. - Weight::from_parts(33_019_206, 4556) - // Standard Error: 6_368 - .saturating_add(Weight::from_parts(6_158_681, 0).saturating_mul(k.into())) + // Minimum execution time: 29_305_000 picoseconds. + Weight::from_parts(32_199_604, 4556) + // Standard Error: 7_150 + .saturating_add(Weight::from_parts(6_437_124, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -296,10 +292,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1866 + n * (102 ±0)` // Estimated: `6248 + n * (2520 ±0)` - // Minimum execution time: 63_452_000 picoseconds. - Weight::from_parts(60_924_066, 6248) - // Standard Error: 14_416 - .saturating_add(Weight::from_parts(3_921_589, 0).saturating_mul(n.into())) + // Minimum execution time: 63_267_000 picoseconds. + Weight::from_parts(61_741_404, 6248) + // Standard Error: 12_955 + .saturating_add(Weight::from_parts(3_811_743, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) @@ -323,8 +319,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1650` // Estimated: `6248` - // Minimum execution time: 54_253_000 picoseconds. - Weight::from_parts(55_286_000, 6248) + // Minimum execution time: 52_862_000 picoseconds. + Weight::from_parts(54_108_000, 6248) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -338,8 +334,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `902` // Estimated: `4556` - // Minimum execution time: 16_812_000 picoseconds. - Weight::from_parts(17_380_000, 4556) + // Minimum execution time: 16_350_000 picoseconds. + Weight::from_parts(16_802_000, 4556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -353,8 +349,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `969` // Estimated: `4556` - // Minimum execution time: 20_590_000 picoseconds. - Weight::from_parts(21_096_000, 4556) + // Minimum execution time: 19_981_000 picoseconds. + Weight::from_parts(20_539_000, 4556) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -366,8 +362,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `902` // Estimated: `4556` - // Minimum execution time: 19_923_000 picoseconds. - Weight::from_parts(20_880_000, 4556) + // Minimum execution time: 19_304_000 picoseconds. + Weight::from_parts(20_000_000, 4556) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -377,8 +373,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_599_000 picoseconds. - Weight::from_parts(2_751_000, 0) + // Minimum execution time: 2_568_000 picoseconds. + Weight::from_parts(2_708_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -387,8 +383,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_941_000 picoseconds. - Weight::from_parts(7_288_000, 0) + // Minimum execution time: 7_950_000 picoseconds. + Weight::from_parts(8_348_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -397,8 +393,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_757_000 picoseconds. - Weight::from_parts(7_200_000, 0) + // Minimum execution time: 7_967_000 picoseconds. + Weight::from_parts(8_222_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -407,8 +403,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_028_000 picoseconds. - Weight::from_parts(7_366_000, 0) + // Minimum execution time: 8_006_000 picoseconds. + Weight::from_parts(8_440_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::Invulnerables` (r:0 w:1) @@ -418,10 +414,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_741_000 picoseconds. - Weight::from_parts(3_212_598, 0) - // Standard Error: 68 - .saturating_add(Weight::from_parts(11_695, 0).saturating_mul(v.into())) + // Minimum execution time: 2_524_000 picoseconds. + Weight::from_parts(3_123_608, 0) + // Standard Error: 59 + .saturating_add(Weight::from_parts(11_596, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Staking::Ledger` (r:5900 w:11800) @@ -435,10 +431,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1356 + i * (151 ±0)` // Estimated: `990 + i * (3566 ±0)` - // Minimum execution time: 2_132_000 picoseconds. - Weight::from_parts(2_289_000, 990) - // Standard Error: 34_227 - .saturating_add(Weight::from_parts(17_006_583, 0).saturating_mul(i.into())) + // Minimum execution time: 2_092_000 picoseconds. + Weight::from_parts(2_258_000, 990) + // Standard Error: 32_695 + .saturating_add(Weight::from_parts(16_669_219, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3566).saturating_mul(i.into())) @@ -476,10 +472,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 85_308_000 picoseconds. - Weight::from_parts(93_689_468, 6248) - // Standard Error: 5_425 - .saturating_add(Weight::from_parts(1_307_604, 0).saturating_mul(s.into())) + // Minimum execution time: 84_275_000 picoseconds. + Weight::from_parts(92_512_416, 6248) + // Standard Error: 3_633 + .saturating_add(Weight::from_parts(1_315_923, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(12_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -492,10 +488,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `66672` // Estimated: `70137` - // Minimum execution time: 103_242_000 picoseconds. - Weight::from_parts(1_162_296_080, 70137) - // Standard Error: 76_741 - .saturating_add(Weight::from_parts(6_487_522, 0).saturating_mul(s.into())) + // Minimum execution time: 101_707_000 picoseconds. + Weight::from_parts(912_819_462, 70137) + // Standard Error: 57_547 + .saturating_add(Weight::from_parts(4_856_799, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -532,10 +528,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `33297 + n * (377 ±0)` // Estimated: `30944 + n * (3774 ±0)` - // Minimum execution time: 140_740_000 picoseconds. - Weight::from_parts(182_886_963, 30944) - // Standard Error: 39_852 - .saturating_add(Weight::from_parts(43_140_752, 0).saturating_mul(n.into())) + // Minimum execution time: 138_657_000 picoseconds. + Weight::from_parts(167_173_445, 30944) + // Standard Error: 25_130 + .saturating_add(Weight::from_parts(44_566_012, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -559,10 +555,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1991 + l * (7 ±0)` // Estimated: `8877` - // Minimum execution time: 80_372_000 picoseconds. - Weight::from_parts(83_335_027, 8877) - // Standard Error: 4_780 - .saturating_add(Weight::from_parts(72_180, 0).saturating_mul(l.into())) + // Minimum execution time: 80_061_000 picoseconds. + Weight::from_parts(82_836_434, 8877) + // Standard Error: 4_348 + .saturating_add(Weight::from_parts(75_744, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } @@ -597,10 +593,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 93_920_000 picoseconds. - Weight::from_parts(98_022_911, 6248) - // Standard Error: 4_096 - .saturating_add(Weight::from_parts(1_287_745, 0).saturating_mul(s.into())) + // Minimum execution time: 92_560_000 picoseconds. + Weight::from_parts(97_684_741, 6248) + // Standard Error: 3_361 + .saturating_add(Weight::from_parts(1_292_732, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(11_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -646,12 +642,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + n * (720 ±0) + v * (3598 ±0)` // Estimated: `512390 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 556_012_000 picoseconds. - Weight::from_parts(560_339_000, 512390) - // Standard Error: 2_115_076 - .saturating_add(Weight::from_parts(69_456_497, 0).saturating_mul(v.into())) - // Standard Error: 210_755 - .saturating_add(Weight::from_parts(17_974_873, 0).saturating_mul(n.into())) + // Minimum execution time: 564_963_000 picoseconds. + Weight::from_parts(569_206_000, 512390) + // Standard Error: 2_033_235 + .saturating_add(Weight::from_parts(68_025_841, 0).saturating_mul(v.into())) + // Standard Error: 202_600 + .saturating_add(Weight::from_parts(17_916_770, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(206_u64)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -682,12 +678,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3175 + n * (911 ±0) + v * (395 ±0)` // Estimated: `512390 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 32_792_819_000 picoseconds. - Weight::from_parts(32_986_606_000, 512390) - // Standard Error: 360_905 - .saturating_add(Weight::from_parts(5_260_151, 0).saturating_mul(v.into())) - // Standard Error: 360_905 - .saturating_add(Weight::from_parts(3_599_219, 0).saturating_mul(n.into())) + // Minimum execution time: 32_196_540_000 picoseconds. + Weight::from_parts(32_341_871_000, 512390) + // Standard Error: 354_657 + .saturating_add(Weight::from_parts(5_143_440, 0).saturating_mul(v.into())) + // Standard Error: 354_657 + .saturating_add(Weight::from_parts(3_328_189, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(201_u64)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -704,10 +700,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `979 + v * (50 ±0)` // Estimated: `3510 + v * (2520 ±0)` - // Minimum execution time: 2_434_755_000 picoseconds. - Weight::from_parts(38_574_764, 3510) - // Standard Error: 14_467 - .saturating_add(Weight::from_parts(4_821_702, 0).saturating_mul(v.into())) + // Minimum execution time: 2_381_903_000 picoseconds. + Weight::from_parts(32_693_059, 3510) + // Standard Error: 10_000 + .saturating_add(Weight::from_parts(4_736_173, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(v.into())) @@ -718,8 +714,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::MinValidatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxValidatorsCount` (r:0 w:1) /// Proof: `Staking::MaxValidatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::MaxStakedRewards` (r:0 w:1) - /// Proof: `Staking::MaxStakedRewards` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::ChillThreshold` (r:0 w:1) /// Proof: `Staking::ChillThreshold` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:0 w:1) @@ -730,9 +724,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_765_000 picoseconds. - Weight::from_parts(6_140_000, 0) - .saturating_add(T::DbWeight::get().writes(7_u64)) + // Minimum execution time: 5_434_000 picoseconds. + Weight::from_parts(5_742_000, 0) + .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `Staking::MinCommission` (r:0 w:1) /// Proof: `Staking::MinCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -740,8 +734,6 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Staking::MinValidatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxValidatorsCount` (r:0 w:1) /// Proof: `Staking::MaxValidatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::MaxStakedRewards` (r:0 w:1) - /// Proof: `Staking::MaxStakedRewards` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::ChillThreshold` (r:0 w:1) /// Proof: `Staking::ChillThreshold` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:0 w:1) @@ -752,9 +744,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_025_000 picoseconds. - Weight::from_parts(5_354_000, 0) - .saturating_add(T::DbWeight::get().writes(7_u64)) + // Minimum execution time: 4_588_000 picoseconds. + Weight::from_parts(4_854_000, 0) + .saturating_add(T::DbWeight::get().writes(6_u64)) } /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) @@ -782,8 +774,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1939` // Estimated: `6248` - // Minimum execution time: 69_656_000 picoseconds. - Weight::from_parts(71_574_000, 6248) + // Minimum execution time: 68_780_000 picoseconds. + Weight::from_parts(71_479_000, 6248) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -795,8 +787,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `691` // Estimated: `3510` - // Minimum execution time: 12_523_000 picoseconds. - Weight::from_parts(13_315_000, 3510) + // Minimum execution time: 12_268_000 picoseconds. + Weight::from_parts(12_661_000, 3510) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -806,8 +798,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_125_000 picoseconds. - Weight::from_parts(3_300_000, 0) + // Minimum execution time: 3_071_000 picoseconds. + Weight::from_parts(3_334_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } } @@ -828,8 +820,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `927` // Estimated: `4764` - // Minimum execution time: 41_318_000 picoseconds. - Weight::from_parts(43_268_000, 4764) + // Minimum execution time: 42_042_000 picoseconds. + Weight::from_parts(43_292_000, 4764) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -849,8 +841,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1990` // Estimated: `8877` - // Minimum execution time: 85_666_000 picoseconds. - Weight::from_parts(88_749_000, 8877) + // Minimum execution time: 85_050_000 picoseconds. + Weight::from_parts(87_567_000, 8877) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -876,8 +868,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2195` // Estimated: `8877` - // Minimum execution time: 90_282_000 picoseconds. - Weight::from_parts(92_332_000, 8877) + // Minimum execution time: 89_076_000 picoseconds. + Weight::from_parts(92_715_000, 8877) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -891,18 +883,16 @@ impl WeightInfo for () { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) - /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1297` + // Measured: `1115` // Estimated: `4764` - // Minimum execution time: 44_626_000 picoseconds. - Weight::from_parts(47_254_657, 4764) - // Standard Error: 1_179 - .saturating_add(Weight::from_parts(57_657, 0).saturating_mul(s.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) + // Minimum execution time: 42_067_000 picoseconds. + Weight::from_parts(43_239_807, 4764) + // Standard Error: 831 + .saturating_add(Weight::from_parts(46_257, 0).saturating_mul(s.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Staking::Ledger` (r:1 w:1) @@ -938,10 +928,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 86_769_000 picoseconds. - Weight::from_parts(95_212_867, 6248) - // Standard Error: 3_706 - .saturating_add(Weight::from_parts(1_320_752, 0).saturating_mul(s.into())) + // Minimum execution time: 86_490_000 picoseconds. + Weight::from_parts(95_358_751, 6248) + // Standard Error: 3_952 + .saturating_add(Weight::from_parts(1_294_907, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(11_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -973,8 +963,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1372` // Estimated: `4556` - // Minimum execution time: 50_410_000 picoseconds. - Weight::from_parts(52_576_000, 4556) + // Minimum execution time: 50_326_000 picoseconds. + Weight::from_parts(52_253_000, 4556) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -987,10 +977,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1280 + k * (569 ±0)` // Estimated: `4556 + k * (3033 ±0)` - // Minimum execution time: 29_017_000 picoseconds. - Weight::from_parts(33_019_206, 4556) - // Standard Error: 6_368 - .saturating_add(Weight::from_parts(6_158_681, 0).saturating_mul(k.into())) + // Minimum execution time: 29_305_000 picoseconds. + Weight::from_parts(32_199_604, 4556) + // Standard Error: 7_150 + .saturating_add(Weight::from_parts(6_437_124, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -1023,10 +1013,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1866 + n * (102 ±0)` // Estimated: `6248 + n * (2520 ±0)` - // Minimum execution time: 63_452_000 picoseconds. - Weight::from_parts(60_924_066, 6248) - // Standard Error: 14_416 - .saturating_add(Weight::from_parts(3_921_589, 0).saturating_mul(n.into())) + // Minimum execution time: 63_267_000 picoseconds. + Weight::from_parts(61_741_404, 6248) + // Standard Error: 12_955 + .saturating_add(Weight::from_parts(3_811_743, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) @@ -1050,8 +1040,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1650` // Estimated: `6248` - // Minimum execution time: 54_253_000 picoseconds. - Weight::from_parts(55_286_000, 6248) + // Minimum execution time: 52_862_000 picoseconds. + Weight::from_parts(54_108_000, 6248) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -1065,8 +1055,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `902` // Estimated: `4556` - // Minimum execution time: 16_812_000 picoseconds. - Weight::from_parts(17_380_000, 4556) + // Minimum execution time: 16_350_000 picoseconds. + Weight::from_parts(16_802_000, 4556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1080,8 +1070,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `969` // Estimated: `4556` - // Minimum execution time: 20_590_000 picoseconds. - Weight::from_parts(21_096_000, 4556) + // Minimum execution time: 19_981_000 picoseconds. + Weight::from_parts(20_539_000, 4556) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1093,8 +1083,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `902` // Estimated: `4556` - // Minimum execution time: 19_923_000 picoseconds. - Weight::from_parts(20_880_000, 4556) + // Minimum execution time: 19_304_000 picoseconds. + Weight::from_parts(20_000_000, 4556) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1104,8 +1094,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_599_000 picoseconds. - Weight::from_parts(2_751_000, 0) + // Minimum execution time: 2_568_000 picoseconds. + Weight::from_parts(2_708_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -1114,8 +1104,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_941_000 picoseconds. - Weight::from_parts(7_288_000, 0) + // Minimum execution time: 7_950_000 picoseconds. + Weight::from_parts(8_348_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -1124,8 +1114,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_757_000 picoseconds. - Weight::from_parts(7_200_000, 0) + // Minimum execution time: 7_967_000 picoseconds. + Weight::from_parts(8_222_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::ForceEra` (r:0 w:1) @@ -1134,8 +1124,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_028_000 picoseconds. - Weight::from_parts(7_366_000, 0) + // Minimum execution time: 8_006_000 picoseconds. + Weight::from_parts(8_440_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::Invulnerables` (r:0 w:1) @@ -1145,10 +1135,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_741_000 picoseconds. - Weight::from_parts(3_212_598, 0) - // Standard Error: 68 - .saturating_add(Weight::from_parts(11_695, 0).saturating_mul(v.into())) + // Minimum execution time: 2_524_000 picoseconds. + Weight::from_parts(3_123_608, 0) + // Standard Error: 59 + .saturating_add(Weight::from_parts(11_596, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Staking::Ledger` (r:5900 w:11800) @@ -1162,10 +1152,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1356 + i * (151 ±0)` // Estimated: `990 + i * (3566 ±0)` - // Minimum execution time: 2_132_000 picoseconds. - Weight::from_parts(2_289_000, 990) - // Standard Error: 34_227 - .saturating_add(Weight::from_parts(17_006_583, 0).saturating_mul(i.into())) + // Minimum execution time: 2_092_000 picoseconds. + Weight::from_parts(2_258_000, 990) + // Standard Error: 32_695 + .saturating_add(Weight::from_parts(16_669_219, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 3566).saturating_mul(i.into())) @@ -1203,10 +1193,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 85_308_000 picoseconds. - Weight::from_parts(93_689_468, 6248) - // Standard Error: 5_425 - .saturating_add(Weight::from_parts(1_307_604, 0).saturating_mul(s.into())) + // Minimum execution time: 84_275_000 picoseconds. + Weight::from_parts(92_512_416, 6248) + // Standard Error: 3_633 + .saturating_add(Weight::from_parts(1_315_923, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(12_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -1219,10 +1209,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `66672` // Estimated: `70137` - // Minimum execution time: 103_242_000 picoseconds. - Weight::from_parts(1_162_296_080, 70137) - // Standard Error: 76_741 - .saturating_add(Weight::from_parts(6_487_522, 0).saturating_mul(s.into())) + // Minimum execution time: 101_707_000 picoseconds. + Weight::from_parts(912_819_462, 70137) + // Standard Error: 57_547 + .saturating_add(Weight::from_parts(4_856_799, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1259,10 +1249,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `33297 + n * (377 ±0)` // Estimated: `30944 + n * (3774 ±0)` - // Minimum execution time: 140_740_000 picoseconds. - Weight::from_parts(182_886_963, 30944) - // Standard Error: 39_852 - .saturating_add(Weight::from_parts(43_140_752, 0).saturating_mul(n.into())) + // Minimum execution time: 138_657_000 picoseconds. + Weight::from_parts(167_173_445, 30944) + // Standard Error: 25_130 + .saturating_add(Weight::from_parts(44_566_012, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().reads((6_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) @@ -1286,10 +1276,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1991 + l * (7 ±0)` // Estimated: `8877` - // Minimum execution time: 80_372_000 picoseconds. - Weight::from_parts(83_335_027, 8877) - // Standard Error: 4_780 - .saturating_add(Weight::from_parts(72_180, 0).saturating_mul(l.into())) + // Minimum execution time: 80_061_000 picoseconds. + Weight::from_parts(82_836_434, 8877) + // Standard Error: 4_348 + .saturating_add(Weight::from_parts(75_744, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } @@ -1324,10 +1314,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2196 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 93_920_000 picoseconds. - Weight::from_parts(98_022_911, 6248) - // Standard Error: 4_096 - .saturating_add(Weight::from_parts(1_287_745, 0).saturating_mul(s.into())) + // Minimum execution time: 92_560_000 picoseconds. + Weight::from_parts(97_684_741, 6248) + // Standard Error: 3_361 + .saturating_add(Weight::from_parts(1_292_732, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(11_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(s.into()))) @@ -1373,12 +1363,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + n * (720 ±0) + v * (3598 ±0)` // Estimated: `512390 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 556_012_000 picoseconds. - Weight::from_parts(560_339_000, 512390) - // Standard Error: 2_115_076 - .saturating_add(Weight::from_parts(69_456_497, 0).saturating_mul(v.into())) - // Standard Error: 210_755 - .saturating_add(Weight::from_parts(17_974_873, 0).saturating_mul(n.into())) + // Minimum execution time: 564_963_000 picoseconds. + Weight::from_parts(569_206_000, 512390) + // Standard Error: 2_033_235 + .saturating_add(Weight::from_parts(68_025_841, 0).saturating_mul(v.into())) + // Standard Error: 202_600 + .saturating_add(Weight::from_parts(17_916_770, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(206_u64)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -1409,12 +1399,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3175 + n * (911 ±0) + v * (395 ±0)` // Estimated: `512390 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 32_792_819_000 picoseconds. - Weight::from_parts(32_986_606_000, 512390) - // Standard Error: 360_905 - .saturating_add(Weight::from_parts(5_260_151, 0).saturating_mul(v.into())) - // Standard Error: 360_905 - .saturating_add(Weight::from_parts(3_599_219, 0).saturating_mul(n.into())) + // Minimum execution time: 32_196_540_000 picoseconds. + Weight::from_parts(32_341_871_000, 512390) + // Standard Error: 354_657 + .saturating_add(Weight::from_parts(5_143_440, 0).saturating_mul(v.into())) + // Standard Error: 354_657 + .saturating_add(Weight::from_parts(3_328_189, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(201_u64)) .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -1431,10 +1421,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `979 + v * (50 ±0)` // Estimated: `3510 + v * (2520 ±0)` - // Minimum execution time: 2_434_755_000 picoseconds. - Weight::from_parts(38_574_764, 3510) - // Standard Error: 14_467 - .saturating_add(Weight::from_parts(4_821_702, 0).saturating_mul(v.into())) + // Minimum execution time: 2_381_903_000 picoseconds. + Weight::from_parts(32_693_059, 3510) + // Standard Error: 10_000 + .saturating_add(Weight::from_parts(4_736_173, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(v.into())) @@ -1445,8 +1435,6 @@ impl WeightInfo for () { /// Proof: `Staking::MinValidatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxValidatorsCount` (r:0 w:1) /// Proof: `Staking::MaxValidatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::MaxStakedRewards` (r:0 w:1) - /// Proof: `Staking::MaxStakedRewards` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::ChillThreshold` (r:0 w:1) /// Proof: `Staking::ChillThreshold` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:0 w:1) @@ -1457,9 +1445,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_765_000 picoseconds. - Weight::from_parts(6_140_000, 0) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + // Minimum execution time: 5_434_000 picoseconds. + Weight::from_parts(5_742_000, 0) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } /// Storage: `Staking::MinCommission` (r:0 w:1) /// Proof: `Staking::MinCommission` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -1467,8 +1455,6 @@ impl WeightInfo for () { /// Proof: `Staking::MinValidatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxValidatorsCount` (r:0 w:1) /// Proof: `Staking::MaxValidatorsCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::MaxStakedRewards` (r:0 w:1) - /// Proof: `Staking::MaxStakedRewards` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::ChillThreshold` (r:0 w:1) /// Proof: `Staking::ChillThreshold` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `Staking::MaxNominatorsCount` (r:0 w:1) @@ -1479,9 +1465,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_025_000 picoseconds. - Weight::from_parts(5_354_000, 0) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + // Minimum execution time: 4_588_000 picoseconds. + Weight::from_parts(4_854_000, 0) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) @@ -1509,8 +1495,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1939` // Estimated: `6248` - // Minimum execution time: 69_656_000 picoseconds. - Weight::from_parts(71_574_000, 6248) + // Minimum execution time: 68_780_000 picoseconds. + Weight::from_parts(71_479_000, 6248) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -1522,8 +1508,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `691` // Estimated: `3510` - // Minimum execution time: 12_523_000 picoseconds. - Weight::from_parts(13_315_000, 3510) + // Minimum execution time: 12_268_000 picoseconds. + Weight::from_parts(12_661_000, 3510) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1533,8 +1519,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_125_000 picoseconds. - Weight::from_parts(3_300_000, 0) + // Minimum execution time: 3_071_000 picoseconds. + Weight::from_parts(3_334_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/substrate/frame/state-trie-migration/src/lib.rs b/substrate/frame/state-trie-migration/src/lib.rs index b89159ef3ec..6b3aa9934e0 100644 --- a/substrate/frame/state-trie-migration/src/lib.rs +++ b/substrate/frame/state-trie-migration/src/lib.rs @@ -1801,7 +1801,7 @@ mod remote_tests_local { use std::env::var as env_var; // we only use the hash type from this, so using the mock should be fine. - type Extrinsic = sp_runtime::generic::UncheckedExtrinsic; + type Extrinsic = sp_runtime::testing::TestXt; type Block = sp_runtime::testing::Block; #[tokio::test] diff --git a/substrate/frame/state-trie-migration/src/weights.rs b/substrate/frame/state-trie-migration/src/weights.rs index 23dad9e3380..8fa80b38957 100644 --- a/substrate/frame/state-trie-migration/src/weights.rs +++ b/substrate/frame/state-trie-migration/src/weights.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_state_trie_migration` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-01-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_state_trie_migration -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/state-trie-migration/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_state_trie_migration +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/state-trie-migration/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -66,15 +64,15 @@ impl WeightInfo for SubstrateWeight { /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) /// Storage: `StateTrieMigration::MigrationProcess` (r:1 w:1) /// Proof: `StateTrieMigration::MigrationProcess` (`max_values`: Some(1), `max_size`: Some(1042), added: 1537, mode: `MaxEncodedLen`) fn continue_migrate() -> Weight { // Proof Size summary in bytes: // Measured: `108` - // Estimated: `3658` - // Minimum execution time: 17_661_000 picoseconds. - Weight::from_parts(18_077_000, 3658) + // Estimated: `3640` + // Minimum execution time: 18_520_000 picoseconds. + Weight::from_parts(19_171_000, 3640) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -84,53 +82,53 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1493` - // Minimum execution time: 4_036_000 picoseconds. - Weight::from_parts(4_267_000, 1493) + // Minimum execution time: 3_786_000 picoseconds. + Weight::from_parts(4_038_000, 1493) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) fn migrate_custom_top_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3658` - // Minimum execution time: 11_348_000 picoseconds. - Weight::from_parts(11_899_000, 3658) + // Estimated: `3640` + // Minimum execution time: 11_144_000 picoseconds. + Weight::from_parts(11_556_000, 3640) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_top_fail() -> Weight { // Proof Size summary in bytes: // Measured: `113` - // Estimated: `3658` - // Minimum execution time: 59_819_000 picoseconds. - Weight::from_parts(61_066_000, 3658) + // Estimated: `3640` + // Minimum execution time: 59_288_000 picoseconds. + Weight::from_parts(60_276_000, 3640) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) fn migrate_custom_child_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3658` - // Minimum execution time: 11_424_000 picoseconds. - Weight::from_parts(11_765_000, 3658) + // Estimated: `3640` + // Minimum execution time: 11_258_000 picoseconds. + Weight::from_parts(11_626_000, 3640) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_child_fail() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `3658` - // Minimum execution time: 61_086_000 picoseconds. - Weight::from_parts(62_546_000, 3658) + // Estimated: `3640` + // Minimum execution time: 61_575_000 picoseconds. + Weight::from_parts(63_454_000, 3640) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -141,10 +139,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `197 + v * (1 ±0)` // Estimated: `3662 + v * (1 ±0)` - // Minimum execution time: 5_375_000 picoseconds. - Weight::from_parts(5_552_000, 3662) + // Minimum execution time: 5_259_000 picoseconds. + Weight::from_parts(5_433_000, 3662) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_146, 0).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(1_159, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(v.into())) @@ -156,15 +154,15 @@ impl WeightInfo for () { /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) /// Storage: `StateTrieMigration::MigrationProcess` (r:1 w:1) /// Proof: `StateTrieMigration::MigrationProcess` (`max_values`: Some(1), `max_size`: Some(1042), added: 1537, mode: `MaxEncodedLen`) fn continue_migrate() -> Weight { // Proof Size summary in bytes: // Measured: `108` - // Estimated: `3658` - // Minimum execution time: 17_661_000 picoseconds. - Weight::from_parts(18_077_000, 3658) + // Estimated: `3640` + // Minimum execution time: 18_520_000 picoseconds. + Weight::from_parts(19_171_000, 3640) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -174,53 +172,53 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1493` - // Minimum execution time: 4_036_000 picoseconds. - Weight::from_parts(4_267_000, 1493) + // Minimum execution time: 3_786_000 picoseconds. + Weight::from_parts(4_038_000, 1493) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) fn migrate_custom_top_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3658` - // Minimum execution time: 11_348_000 picoseconds. - Weight::from_parts(11_899_000, 3658) + // Estimated: `3640` + // Minimum execution time: 11_144_000 picoseconds. + Weight::from_parts(11_556_000, 3640) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_top_fail() -> Weight { // Proof Size summary in bytes: // Measured: `113` - // Estimated: `3658` - // Minimum execution time: 59_819_000 picoseconds. - Weight::from_parts(61_066_000, 3658) + // Estimated: `3640` + // Minimum execution time: 59_288_000 picoseconds. + Weight::from_parts(60_276_000, 3640) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) fn migrate_custom_child_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `3658` - // Minimum execution time: 11_424_000 picoseconds. - Weight::from_parts(11_765_000, 3658) + // Estimated: `3640` + // Minimum execution time: 11_258_000 picoseconds. + Weight::from_parts(11_626_000, 3640) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_child_fail() -> Weight { // Proof Size summary in bytes: // Measured: `106` - // Estimated: `3658` - // Minimum execution time: 61_086_000 picoseconds. - Weight::from_parts(62_546_000, 3658) + // Estimated: `3640` + // Minimum execution time: 61_575_000 picoseconds. + Weight::from_parts(63_454_000, 3640) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -231,10 +229,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `197 + v * (1 ±0)` // Estimated: `3662 + v * (1 ±0)` - // Minimum execution time: 5_375_000 picoseconds. - Weight::from_parts(5_552_000, 3662) + // Minimum execution time: 5_259_000 picoseconds. + Weight::from_parts(5_433_000, 3662) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_146, 0).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(1_159, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(v.into())) diff --git a/substrate/frame/sudo/src/benchmarking.rs b/substrate/frame/sudo/src/benchmarking.rs index cdd7d707600..e64233fe748 100644 --- a/substrate/frame/sudo/src/benchmarking.rs +++ b/substrate/frame/sudo/src/benchmarking.rs @@ -20,23 +20,14 @@ use super::*; use crate::Pallet; use frame_benchmarking::v2::*; -use frame_support::dispatch::DispatchInfo; use frame_system::RawOrigin; -use sp_runtime::traits::{AsSystemOriginSigner, DispatchTransaction, Dispatchable}; fn assert_last_event(generic_event: crate::Event) { let re: ::RuntimeEvent = generic_event.into(); frame_system::Pallet::::assert_last_event(re.into()); } -#[benchmarks(where - T: Send + Sync, - ::RuntimeCall: From>, - ::RuntimeCall: Dispatchable, - <::RuntimeCall as Dispatchable>::PostInfo: From<()>, - <::RuntimeCall as Dispatchable>::RuntimeOrigin: - AsSystemOriginSigner + Clone, -)] +#[benchmarks(where ::RuntimeCall: From>)] mod benchmarks { use super::*; @@ -94,23 +85,5 @@ mod benchmarks { assert_last_event::(Event::KeyRemoved {}); } - #[benchmark] - fn check_only_sudo_account() { - let caller: T::AccountId = whitelisted_caller(); - Key::::put(&caller); - - let call = frame_system::Call::remark { remark: vec![] }.into(); - let info = DispatchInfo { ..Default::default() }; - let ext = CheckOnlySudoAccount::::new(); - - #[block] - { - assert!(ext - .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(().into())) - .unwrap() - .is_ok()); - } - } - impl_benchmark_test_suite!(Pallet, crate::mock::new_bench_ext(), crate::mock::Test); } diff --git a/substrate/frame/sudo/src/extension.rs b/substrate/frame/sudo/src/extension.rs index 2cd8f945edd..e90286e5a7c 100644 --- a/substrate/frame/sudo/src/extension.rs +++ b/substrate/frame/sudo/src/extension.rs @@ -20,14 +20,10 @@ use codec::{Decode, Encode}; use frame_support::{dispatch::DispatchInfo, ensure}; use scale_info::TypeInfo; use sp_runtime::{ - impl_tx_ext_default, - traits::{ - AsSystemOriginSigner, DispatchInfoOf, Dispatchable, TransactionExtension, - TransactionExtensionBase, - }, + traits::{DispatchInfoOf, Dispatchable, SignedExtension}, transaction_validity::{ - InvalidTransaction, TransactionPriority, TransactionValidityError, UnknownTransaction, - ValidTransaction, + InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError, + UnknownTransaction, ValidTransaction, }, }; use sp_std::{fmt, marker::PhantomData}; @@ -63,61 +59,49 @@ impl fmt::Debug for CheckOnlySudoAccount { } impl CheckOnlySudoAccount { - /// Creates new `TransactionExtension` to check sudo key. + /// Creates new `SignedExtension` to check sudo key. pub fn new() -> Self { Self::default() } } -impl TransactionExtensionBase for CheckOnlySudoAccount { - const IDENTIFIER: &'static str = "CheckOnlySudoAccount"; - type Implicit = (); - - fn weight(&self) -> frame_support::weights::Weight { - use crate::weights::WeightInfo; - T::WeightInfo::check_only_sudo_account() - } -} -impl - TransactionExtension<::RuntimeCall, Context> for CheckOnlySudoAccount +impl SignedExtension for CheckOnlySudoAccount where - ::RuntimeCall: Dispatchable, - <::RuntimeCall as Dispatchable>::RuntimeOrigin: - AsSystemOriginSigner + Clone, + ::RuntimeCall: Dispatchable, { + const IDENTIFIER: &'static str = "CheckOnlySudoAccount"; + type AccountId = T::AccountId; + type Call = ::RuntimeCall; + type AdditionalSigned = (); type Pre = (); - type Val = (); + + fn additional_signed(&self) -> Result { + Ok(()) + } fn validate( &self, - origin: <::RuntimeCall as Dispatchable>::RuntimeOrigin, - _call: &::RuntimeCall, - info: &DispatchInfoOf<::RuntimeCall>, + who: &Self::AccountId, + _call: &Self::Call, + info: &DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> Result< - ( - ValidTransaction, - Self::Val, - <::RuntimeCall as Dispatchable>::RuntimeOrigin, - ), - TransactionValidityError, - > { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + ) -> TransactionValidity { let sudo_key: T::AccountId = Key::::get().ok_or(UnknownTransaction::CannotLookup)?; ensure!(*who == sudo_key, InvalidTransaction::BadSigner); - Ok(( - ValidTransaction { - priority: info.weight.ref_time() as TransactionPriority, - ..Default::default() - }, - (), - origin, - )) + Ok(ValidTransaction { + priority: info.weight.ref_time() as TransactionPriority, + ..Default::default() + }) } - impl_tx_ext_default!(::RuntimeCall; Context; prepare); + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) + } } diff --git a/substrate/frame/sudo/src/lib.rs b/substrate/frame/sudo/src/lib.rs index 2c953368b22..2ebe4cb0157 100644 --- a/substrate/frame/sudo/src/lib.rs +++ b/substrate/frame/sudo/src/lib.rs @@ -85,8 +85,8 @@ //! meant to be used by constructing runtime calls from outside the runtime. //! //! -//! This pallet also defines a [`TransactionExtension`](sp_runtime::traits::TransactionExtension) -//! called [`CheckOnlySudoAccount`] to ensure that only signed transactions by the sudo account are +//! This pallet also defines a [`SignedExtension`](sp_runtime::traits::SignedExtension) called +//! [`CheckOnlySudoAccount`] to ensure that only signed transactions by the sudo account are //! accepted by the transaction pool. The intended use of this signed extension is to prevent other //! accounts from spamming the transaction pool for the initial phase of a chain, during which //! developers may only want a sudo account to be able to make transactions. diff --git a/substrate/frame/sudo/src/weights.rs b/substrate/frame/sudo/src/weights.rs index aa8f69fd4e6..10d1a9f7a51 100644 --- a/substrate/frame/sudo/src/weights.rs +++ b/substrate/frame/sudo/src/weights.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_sudo` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-yprdrvc7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_sudo -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/sudo/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_sudo +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/sudo/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -55,7 +53,6 @@ pub trait WeightInfo { fn sudo() -> Weight; fn sudo_as() -> Weight; fn remove_key() -> Weight; - fn check_only_sudo_account() -> Weight; } /// Weights for `pallet_sudo` using the Substrate node and recommended hardware. @@ -67,8 +64,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 9_590_000 picoseconds. - Weight::from_parts(9_924_000, 1517) + // Minimum execution time: 9_600_000 picoseconds. + Weight::from_parts(10_076_000, 1517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -78,8 +75,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 9_825_000 picoseconds. - Weight::from_parts(10_373_000, 1517) + // Minimum execution time: 10_453_000 picoseconds. + Weight::from_parts(10_931_000, 1517) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Sudo::Key` (r:1 w:0) @@ -88,8 +85,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 10_140_000 picoseconds. - Weight::from_parts(10_382_000, 1517) + // Minimum execution time: 10_202_000 picoseconds. + Weight::from_parts(10_800_000, 1517) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Sudo::Key` (r:1 w:1) @@ -98,21 +95,11 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 8_610_000 picoseconds. - Weight::from_parts(8_975_000, 1517) + // Minimum execution time: 8_555_000 picoseconds. + Weight::from_parts(8_846_000, 1517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Sudo::Key` (r:1 w:0) - /// Proof: `Sudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - fn check_only_sudo_account() -> Weight { - // Proof Size summary in bytes: - // Measured: `165` - // Estimated: `1517` - // Minimum execution time: 3_416_000 picoseconds. - Weight::from_parts(3_645_000, 1517) - .saturating_add(T::DbWeight::get().reads(1_u64)) - } } // For backwards compatibility and tests. @@ -123,8 +110,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 9_590_000 picoseconds. - Weight::from_parts(9_924_000, 1517) + // Minimum execution time: 9_600_000 picoseconds. + Weight::from_parts(10_076_000, 1517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -134,8 +121,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 9_825_000 picoseconds. - Weight::from_parts(10_373_000, 1517) + // Minimum execution time: 10_453_000 picoseconds. + Weight::from_parts(10_931_000, 1517) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Sudo::Key` (r:1 w:0) @@ -144,8 +131,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 10_140_000 picoseconds. - Weight::from_parts(10_382_000, 1517) + // Minimum execution time: 10_202_000 picoseconds. + Weight::from_parts(10_800_000, 1517) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Sudo::Key` (r:1 w:1) @@ -154,19 +141,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `165` // Estimated: `1517` - // Minimum execution time: 8_610_000 picoseconds. - Weight::from_parts(8_975_000, 1517) + // Minimum execution time: 8_555_000 picoseconds. + Weight::from_parts(8_846_000, 1517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Sudo::Key` (r:1 w:0) - /// Proof: `Sudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - fn check_only_sudo_account() -> Weight { - // Proof Size summary in bytes: - // Measured: `165` - // Estimated: `1517` - // Minimum execution time: 3_416_000 picoseconds. - Weight::from_parts(3_645_000, 1517) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - } } diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs index d21cfef4a92..da483fa6cf0 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -73,9 +73,11 @@ pub fn expand_outer_inherent( #( #pallet_attrs if let Some(inherent) = #pallet_names::create_inherent(self) { - let inherent = <#unchecked_extrinsic as #scrate::sp_runtime::traits::Extrinsic>::new_inherent( + let inherent = <#unchecked_extrinsic as #scrate::sp_runtime::traits::Extrinsic>::new( inherent.into(), - ); + None, + ).expect("Runtime UncheckedExtrinsic is not Opaque, so it has to return \ + `Some`; qed"); inherents.push(inherent); } @@ -121,7 +123,7 @@ pub fn expand_outer_inherent( for xt in block.extrinsics() { // Inherents are before any other extrinsics. // And signed extrinsics are not inherents. - if !(#scrate::sp_runtime::traits::Extrinsic::is_bare(xt)) { + if #scrate::sp_runtime::traits::Extrinsic::is_signed(xt).unwrap_or(false) { break } @@ -159,9 +161,10 @@ pub fn expand_outer_inherent( match #pallet_names::is_inherent_required(self) { Ok(Some(e)) => { let found = block.extrinsics().iter().any(|xt| { - let is_bare = #scrate::sp_runtime::traits::Extrinsic::is_bare(xt); + let is_signed = #scrate::sp_runtime::traits::Extrinsic::is_signed(xt) + .unwrap_or(false); - if is_bare { + if !is_signed { let call = < #unchecked_extrinsic as ExtrinsicCall >::call(xt); @@ -206,9 +209,8 @@ pub fn expand_outer_inherent( use #scrate::inherent::ProvideInherent; use #scrate::traits::{IsSubType, ExtrinsicCall}; - let is_bare = #scrate::sp_runtime::traits::Extrinsic::is_bare(ext); - if !is_bare { - // Signed extrinsics are not inherents. + if #scrate::sp_runtime::traits::Extrinsic::is_signed(ext).unwrap_or(false) { + // Signed extrinsics are never inherents. return false } diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs index f55ca677d89..0e76f9a9246 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs @@ -119,13 +119,13 @@ pub fn expand_runtime_metadata( call_ty, signature_ty, extra_ty, - extensions: < + signed_extensions: < < #extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata - >::Extra as #scrate::sp_runtime::traits::TransactionExtensionBase + >::SignedExtensions as #scrate::sp_runtime::traits::SignedExtension >::metadata() .into_iter() - .map(|meta| #scrate::__private::metadata_ir::TransactionExtensionMetadataIR { + .map(|meta| #scrate::__private::metadata_ir::SignedExtensionMetadataIR { identifier: meta.identifier, ty: meta.ty, additional_signed: meta.additional_signed, diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs index 341621deb09..83049919d01 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -153,10 +153,6 @@ pub fn expand_outer_origin( self.filter = #scrate::__private::sp_std::rc::Rc::new(Box::new(filter)); } - fn set_caller(&mut self, caller: OriginCaller) { - self.caller = caller; - } - fn set_caller_from(&mut self, other: impl Into) { self.caller = other.into().caller; } @@ -305,16 +301,6 @@ pub fn expand_outer_origin( } } - impl #scrate::__private::AsSystemOriginSigner<<#runtime as #system_path::Config>::AccountId> for RuntimeOrigin { - fn as_system_origin_signer(&self) -> Option<&<#runtime as #system_path::Config>::AccountId> { - if let OriginCaller::system(#system_path::Origin::<#runtime>::Signed(ref signed)) = &self.caller { - Some(signed) - } else { - None - } - } - } - #pallet_conversions }) } diff --git a/substrate/frame/support/src/dispatch.rs b/substrate/frame/support/src/dispatch.rs index 61787a74012..4a313551aca 100644 --- a/substrate/frame/support/src/dispatch.rs +++ b/substrate/frame/support/src/dispatch.rs @@ -25,7 +25,7 @@ use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; use sp_runtime::{ generic::{CheckedExtrinsic, UncheckedExtrinsic}, - traits::Dispatchable, + traits::SignedExtension, DispatchError, RuntimeDebug, }; use sp_std::fmt; @@ -268,8 +268,7 @@ pub fn extract_actual_weight(result: &DispatchResultWithPostInfo, info: &Dispatc .calc_actual_weight(info) } -/// Extract the actual pays_fee from a dispatch result if any or fall back to the default -/// weight. +/// Extract the actual pays_fee from a dispatch result if any or fall back to the default weight. pub fn extract_actual_pays_fee(result: &DispatchResultWithPostInfo, info: &DispatchInfo) -> Pays { match result { Ok(post_info) => post_info, @@ -369,10 +368,11 @@ where } /// Implementation for unchecked extrinsic. -impl GetDispatchInfo - for UncheckedExtrinsic +impl GetDispatchInfo + for UncheckedExtrinsic where - Call: GetDispatchInfo + Dispatchable, + Call: GetDispatchInfo, + Extra: SignedExtension, { fn get_dispatch_info(&self) -> DispatchInfo { self.function.get_dispatch_info() @@ -380,7 +380,7 @@ where } /// Implementation for checked extrinsic. -impl GetDispatchInfo for CheckedExtrinsic +impl GetDispatchInfo for CheckedExtrinsic where Call: GetDispatchInfo, { @@ -389,6 +389,21 @@ where } } +/// Implementation for test extrinsic. +#[cfg(feature = "std")] +impl GetDispatchInfo + for sp_runtime::testing::TestXt +{ + fn get_dispatch_info(&self) -> DispatchInfo { + // for testing: weight == size. + DispatchInfo { + weight: Weight::from_parts(self.encode().len() as _, 0), + pays_fee: Pays::Yes, + class: self.call.get_dispatch_info().class, + } + } +} + /// A struct holding value for each `DispatchClass`. #[derive(Clone, Eq, PartialEq, Default, Debug, Encode, Decode, TypeInfo, MaxEncodedLen)] pub struct PerDispatchClass { diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index af8449c9697..4eadd85a9e0 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -54,8 +54,7 @@ pub mod __private { #[cfg(feature = "std")] pub use sp_runtime::{bounded_btree_map, bounded_vec}; pub use sp_runtime::{ - traits::{AsSystemOriginSigner, Dispatchable}, - DispatchError, RuntimeDebug, StateVersion, TransactionOutcome, + traits::Dispatchable, DispatchError, RuntimeDebug, StateVersion, TransactionOutcome, }; #[cfg(feature = "std")] pub use sp_state_machine::BasicExternalities; @@ -76,7 +75,6 @@ pub mod storage; #[cfg(test)] mod tests; pub mod traits; -pub mod transaction_extensions; pub mod weights; #[doc(hidden)] pub mod unsigned { @@ -1586,8 +1584,8 @@ pub mod pallet_macros { /// [`ValidateUnsigned`](frame_support::pallet_prelude::ValidateUnsigned) for /// type `Pallet`, and some optional where clause. /// - /// NOTE: There is also the [`sp_runtime::traits::TransactionExtension`] trait that can be - /// used to add some specific logic for transaction validation. + /// NOTE: There is also the [`sp_runtime::traits::SignedExtension`] trait that can be used + /// to add some specific logic for transaction validation. /// /// ## Macro expansion /// diff --git a/substrate/frame/support/src/traits/dispatch.rs b/substrate/frame/support/src/traits/dispatch.rs index 212c3080352..de50ce7a26c 100644 --- a/substrate/frame/support/src/traits/dispatch.rs +++ b/substrate/frame/support/src/traits/dispatch.rs @@ -482,7 +482,7 @@ pub trait OriginTrait: Sized { type Call; /// The caller origin, overarching type of all pallets origins. - type PalletsOrigin: Send + Sync + Into + CallerTrait + MaxEncodedLen; + type PalletsOrigin: Into + CallerTrait + MaxEncodedLen; /// The AccountId used across the system. type AccountId; @@ -496,14 +496,6 @@ pub trait OriginTrait: Sized { /// Replace the caller with caller from the other origin fn set_caller_from(&mut self, other: impl Into); - /// Replace the caller with caller from the other origin - fn set_caller(&mut self, caller: Self::PalletsOrigin); - - /// Replace the caller with caller from the other origin - fn set_caller_from_signed(&mut self, caller_account: Self::AccountId) { - self.set_caller(Self::PalletsOrigin::from(RawOrigin::Signed(caller_account))) - } - /// Filter the call if caller is not root, if false is returned then the call must be filtered /// out. /// @@ -552,17 +544,6 @@ pub trait OriginTrait: Sized { fn as_system_ref(&self) -> Option<&RawOrigin> { self.caller().as_system_ref() } - - /// Extract a reference to the sytsem signer, if that's what the caller is. - fn as_system_signer(&self) -> Option<&Self::AccountId> { - self.caller().as_system_ref().and_then(|s| { - if let RawOrigin::Signed(ref who) = s { - Some(who) - } else { - None - } - }) - } } #[cfg(test)] diff --git a/substrate/frame/support/src/traits/misc.rs b/substrate/frame/support/src/traits/misc.rs index fba546ce21b..1f634a64282 100644 --- a/substrate/frame/support/src/traits/misc.rs +++ b/substrate/frame/support/src/traits/misc.rs @@ -919,13 +919,24 @@ pub trait ExtrinsicCall: sp_runtime::traits::Extrinsic { fn call(&self) -> &Self::Call; } +#[cfg(feature = "std")] +impl ExtrinsicCall for sp_runtime::testing::TestXt +where + Call: codec::Codec + Sync + Send + TypeInfo, + Extra: TypeInfo, +{ + fn call(&self) -> &Self::Call { + &self.call + } +} + impl ExtrinsicCall for sp_runtime::generic::UncheckedExtrinsic where Address: TypeInfo, Call: TypeInfo, Signature: TypeInfo, - Extra: TypeInfo, + Extra: sp_runtime::traits::SignedExtension + TypeInfo, { fn call(&self) -> &Self::Call { &self.function diff --git a/substrate/frame/support/src/transaction_extensions.rs b/substrate/frame/support/src/transaction_extensions.rs deleted file mode 100644 index 98d78b9b4e4..00000000000 --- a/substrate/frame/support/src/transaction_extensions.rs +++ /dev/null @@ -1,89 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -//! Transaction extensions. - -use crate::{CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound}; -use codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_io::hashing::blake2_256; -use sp_runtime::{ - impl_tx_ext_default, - traits::{ - transaction_extension::{TransactionExtensionBase, TransactionExtensionInterior}, - DispatchInfoOf, Dispatchable, IdentifyAccount, TransactionExtension, Verify, - }, - transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction}, -}; - -#[derive( - CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, RuntimeDebugNoBound, TypeInfo, -)] -#[codec(encode_bound())] -#[codec(decode_bound())] -pub struct VerifyMultiSignature -where - V: TransactionExtensionInterior, - ::AccountId: TransactionExtensionInterior, -{ - signature: V, - account: ::AccountId, -} - -impl TransactionExtensionBase for VerifyMultiSignature -where - V: TransactionExtensionInterior, - ::AccountId: TransactionExtensionInterior, -{ - const IDENTIFIER: &'static str = "VerifyMultiSignature"; - type Implicit = (); -} - -impl TransactionExtension - for VerifyMultiSignature -where - V: TransactionExtensionInterior, - ::AccountId: TransactionExtensionInterior, - ::RuntimeOrigin: From::AccountId>>, -{ - type Val = (); - type Pre = (); - impl_tx_ext_default!(Call; Context; prepare); - - fn validate( - &self, - _origin: ::RuntimeOrigin, - _call: &Call, - _info: &DispatchInfoOf, - _len: usize, - _: &mut Context, - _: (), - inherited_implication: &impl Encode, - ) -> Result< - (ValidTransaction, Self::Val, ::RuntimeOrigin), - TransactionValidityError, - > { - let msg = inherited_implication.using_encoded(blake2_256); - - if !self.signature.verify(&msg[..], &self.account) { - Err(InvalidTransaction::BadProof)? - } - // We clobber the original origin. Maybe we shuld check that it's none? - let origin = Some(self.account.clone()).into(); - Ok((ValidTransaction::default(), (), origin)) - } -} diff --git a/substrate/frame/support/src/weights/block_weights.rs b/substrate/frame/support/src/weights/block_weights.rs index 647b6198357..57a68554755 100644 --- a/substrate/frame/support/src/weights/block_weights.rs +++ b/substrate/frame/support/src/weights/block_weights.rs @@ -15,23 +15,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01 (Y/M/D) -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16 (Y/M/D) +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! //! SHORT-NAME: `block`, LONG-NAME: `BlockExecution`, RUNTIME: `Development` //! WARMUPS: `10`, REPEAT: `100` -//! WEIGHT-PATH: `./substrate/frame/support/src/weights/` +//! WEIGHT-PATH: `./frame/support/src/weights/` //! WEIGHT-METRIC: `Average`, WEIGHT-MUL: `1.0`, WEIGHT-ADD: `0` // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // overhead // --chain=dev +// --execution=wasm // --wasm-execution=compiled -// --weight-path=./substrate/frame/support/src/weights/ -// --header=./substrate/HEADER-APACHE2 +// --weight-path=./frame/support/src/weights/ +// --header=./HEADER-APACHE2 // --warmup=10 // --repeat=100 @@ -43,17 +44,17 @@ parameter_types! { /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 424_332, 493_017 - /// Average: 437_118 - /// Median: 434_920 - /// Std-Dev: 8798.01 + /// Min, Max: 376_949, 622_462 + /// Average: 390_584 + /// Median: 386_322 + /// Std-Dev: 24792.0 /// /// Percentiles nanoseconds: - /// 99th: 460_074 - /// 95th: 451_580 - /// 75th: 440_307 + /// 99th: 433_299 + /// 95th: 402_688 + /// 75th: 391_645 pub const BlockExecutionWeight: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(437_118), 0); + Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(390_584), 0); } #[cfg(test)] diff --git a/substrate/frame/support/src/weights/extrinsic_weights.rs b/substrate/frame/support/src/weights/extrinsic_weights.rs index 99b392c4369..a304f089ff7 100644 --- a/substrate/frame/support/src/weights/extrinsic_weights.rs +++ b/substrate/frame/support/src/weights/extrinsic_weights.rs @@ -15,23 +15,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01 (Y/M/D) -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16 (Y/M/D) +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! //! SHORT-NAME: `extrinsic`, LONG-NAME: `ExtrinsicBase`, RUNTIME: `Development` //! WARMUPS: `10`, REPEAT: `100` -//! WEIGHT-PATH: `./substrate/frame/support/src/weights/` +//! WEIGHT-PATH: `./frame/support/src/weights/` //! WEIGHT-METRIC: `Average`, WEIGHT-MUL: `1.0`, WEIGHT-ADD: `0` // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // overhead // --chain=dev +// --execution=wasm // --wasm-execution=compiled -// --weight-path=./substrate/frame/support/src/weights/ -// --header=./substrate/HEADER-APACHE2 +// --weight-path=./frame/support/src/weights/ +// --header=./HEADER-APACHE2 // --warmup=10 // --repeat=100 @@ -43,17 +44,17 @@ parameter_types! { /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 106_053, 107_403 - /// Average: 106_446 - /// Median: 106_415 - /// Std-Dev: 216.17 + /// Min, Max: 123_875, 128_419 + /// Average: 124_414 + /// Median: 124_332 + /// Std-Dev: 497.74 /// /// Percentiles nanoseconds: - /// 99th: 107_042 - /// 95th: 106_841 - /// 75th: 106_544 + /// 99th: 125_245 + /// 95th: 124_989 + /// 75th: 124_498 pub const ExtrinsicBaseWeight: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(106_446), 0); + Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(124_414), 0); } #[cfg(test)] diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr index c677ddcd672..09c4d290ef5 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr @@ -477,7 +477,7 @@ note: required because it appears within the type `RuntimeCall` | ||_- in this macro invocation ... | note: required by a bound in `frame_support::sp_runtime::traits::Dispatchable::Config` - --> $WORKSPACE/substrate/primitives/runtime/src/traits/mod.rs + --> $WORKSPACE/substrate/primitives/runtime/src/traits.rs | | type Config; | ^^^^^^^^^^^^ required by this bound in `Dispatchable::Config` @@ -510,7 +510,7 @@ note: required because it appears within the type `RuntimeCall` | ||_- in this macro invocation ... | note: required by a bound in `frame_support::pallet_prelude::ValidateUnsigned::Call` - --> $WORKSPACE/substrate/primitives/runtime/src/traits/mod.rs + --> $WORKSPACE/substrate/primitives/runtime/src/traits.rs | | type Call; | ^^^^^^^^^^ required by this bound in `ValidateUnsigned::Call` diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 4d2737d411e..607f54ccc13 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -743,40 +743,10 @@ impl pallet5::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; } -#[derive(Clone, Debug, codec::Encode, codec::Decode, PartialEq, Eq, scale_info::TypeInfo)] -pub struct AccountU64(u64); -impl sp_runtime::traits::IdentifyAccount for AccountU64 { - type AccountId = u64; - fn into_account(self) -> u64 { - self.0 - } -} - -impl sp_runtime::traits::Verify for AccountU64 { - type Signer = AccountU64; - fn verify>( - &self, - _msg: L, - _signer: &::AccountId, - ) -> bool { - true - } -} - -impl From for AccountU64 { - fn from(value: u64) -> Self { - Self(value) - } -} - pub type Header = sp_runtime::generic::Header; pub type Block = sp_runtime::generic::Block; -pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic< - u64, - RuntimeCall, - AccountU64, - frame_system::CheckNonZeroSender, ->; +pub type UncheckedExtrinsic = + sp_runtime::testing::TestXt>; frame_support::construct_runtime!( pub struct Runtime { @@ -926,8 +896,10 @@ fn inherent_expand() { let inherents = InherentData::new().create_extrinsics(); - let expected = - vec![UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {}))]; + let expected = vec![UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), + signature: None, + }]; assert_eq!(expected, inherents); let block = Block::new( @@ -939,11 +911,14 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {})), - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { - foo: 1, - bar: 0, - })), + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), + signature: None, + }, + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 0 }), + signature: None, + }, ], ); @@ -958,11 +933,14 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {})), - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { - foo: 0, - bar: 0, - })), + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), + signature: None, + }, + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo { foo: 0, bar: 0 }), + signature: None, + }, ], ); @@ -976,9 +954,10 @@ fn inherent_expand() { BlakeTwo256::hash(b"test"), Digest::default(), ), - vec![UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_storage_layer { - foo: 0, - }))], + vec![UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_storage_layer { foo: 0 }), + signature: None, + }], ); let mut inherent = InherentData::new(); @@ -993,12 +972,10 @@ fn inherent_expand() { BlakeTwo256::hash(b"test"), Digest::default(), ), - vec![UncheckedExtrinsic::new_signed( - RuntimeCall::Example(pallet::Call::foo_no_post_info {}), - 1, - 1.into(), - Default::default(), - )], + vec![UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), + signature: Some((1, Default::default())), + }], ); let mut inherent = InherentData::new(); @@ -1014,13 +991,14 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { - foo: 1, - bar: 1, - })), - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_storage_layer { - foo: 0, - })), + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 1 }), + signature: None, + }, + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_storage_layer { foo: 0 }), + signature: None, + }, ], ); @@ -1035,14 +1013,18 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { - foo: 1, - bar: 1, - })), - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_storage_layer { - foo: 0, - })), - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {})), + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 1 }), + signature: None, + }, + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_storage_layer { foo: 0 }), + signature: None, + }, + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), + signature: None, + }, ], ); @@ -1057,17 +1039,18 @@ fn inherent_expand() { Digest::default(), ), vec![ - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo { - foo: 1, - bar: 1, - })), - UncheckedExtrinsic::new_signed( - RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 0 }), - 1, - 1.into(), - Default::default(), - ), - UncheckedExtrinsic::new_bare(RuntimeCall::Example(pallet::Call::foo_no_post_info {})), + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 1 }), + signature: None, + }, + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo { foo: 1, bar: 0 }), + signature: Some((1, Default::default())), + }, + UncheckedExtrinsic { + call: RuntimeCall::Example(pallet::Call::foo_no_post_info {}), + signature: None, + }, ], ); @@ -1950,7 +1933,7 @@ fn extrinsic_metadata_ir_types() { >(), ir.signature_ty ); - assert_eq!(meta_type::(), ir.signature_ty); + assert_eq!(meta_type::<()>(), ir.signature_ty); assert_eq!(meta_type::<<::SignaturePayload as SignaturePayloadT>::SignatureExtra>(), ir.extra_ty); assert_eq!(meta_type::>(), ir.extra_ty); diff --git a/substrate/frame/support/test/tests/pallet_instance.rs b/substrate/frame/support/test/tests/pallet_instance.rs index 505400a7c21..f8cc97623b8 100644 --- a/substrate/frame/support/test/tests/pallet_instance.rs +++ b/substrate/frame/support/test/tests/pallet_instance.rs @@ -943,7 +943,7 @@ fn metadata() { ty: scale_info::meta_type::(), version: 4, signed_extensions: vec![SignedExtensionMetadata { - identifier: "UnitTransactionExtension", + identifier: "UnitSignedExtension", ty: scale_info::meta_type::<()>(), additional_signed: scale_info::meta_type::<()>(), }], diff --git a/substrate/frame/support/test/tests/runtime.rs b/substrate/frame/support/test/tests/runtime.rs index 7e33ee46458..115e3aa4c8a 100644 --- a/substrate/frame/support/test/tests/runtime.rs +++ b/substrate/frame/support/test/tests/runtime.rs @@ -895,7 +895,7 @@ fn test_metadata() { ty: meta_type::(), version: 4, signed_extensions: vec![SignedExtensionMetadata { - identifier: "UnitTransactionExtension", + identifier: "UnitSignedExtension", ty: meta_type::<()>(), additional_signed: meta_type::<()>(), }], diff --git a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs index 38875517018..4c7012dca14 100644 --- a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs +++ b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs @@ -752,7 +752,7 @@ fn test_metadata() { name: "Version", ty: meta_type::(), value: RuntimeVersion::default().encode(), - docs: maybe_docs(vec![ " Get the chain's current version."]), + docs: maybe_docs(vec![ " Get the chain's in-code version."]), }, PalletConstantMetadata { name: "SS58Prefix", @@ -895,7 +895,7 @@ fn test_metadata() { ty: meta_type::(), version: 4, signed_extensions: vec![SignedExtensionMetadata { - identifier: "UnitTransactionExtension", + identifier: "UnitSignedExtension", ty: meta_type::<()>(), additional_signed: meta_type::<()>(), }], diff --git a/substrate/frame/system/benchmarking/src/extensions.rs b/substrate/frame/system/benchmarking/src/extensions.rs deleted file mode 100644 index bfc3b4343a6..00000000000 --- a/substrate/frame/system/benchmarking/src/extensions.rs +++ /dev/null @@ -1,213 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -// Benchmarks for System Extensions - -#![cfg(feature = "runtime-benchmarks")] - -use frame_benchmarking::{account, v2::*, BenchmarkError}; -use frame_support::{ - dispatch::{DispatchClass, DispatchInfo, PostDispatchInfo}, - weights::Weight, -}; -use frame_system::{ - pallet_prelude::*, CheckGenesis, CheckMortality, CheckNonZeroSender, CheckNonce, - CheckSpecVersion, CheckTxVersion, CheckWeight, Config, Pallet as System, RawOrigin, -}; -use sp_runtime::{ - generic::Era, - traits::{AsSystemOriginSigner, DispatchTransaction, Dispatchable, Get}, -}; -use sp_std::prelude::*; - -pub struct Pallet(System); - -#[benchmarks(where - T: Send + Sync, - T::RuntimeCall: Dispatchable, - ::RuntimeOrigin: AsSystemOriginSigner + Clone) -] -mod benchmarks { - use super::*; - - #[benchmark] - fn check_genesis() -> Result<(), BenchmarkError> { - let len = 0_usize; - let caller = account("caller", 0, 0); - let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; - let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); - - #[block] - { - CheckGenesis::::new() - .test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) - .unwrap() - .unwrap(); - } - - Ok(()) - } - - #[benchmark] - fn check_mortality() -> Result<(), BenchmarkError> { - let len = 0_usize; - let ext = CheckMortality::::from(Era::mortal(16, 256)); - let block_number: BlockNumberFor = 17u32.into(); - System::::set_block_number(block_number); - let prev_block: BlockNumberFor = 16u32.into(); - let default_hash: T::Hash = Default::default(); - frame_system::BlockHash::::insert(prev_block, default_hash); - let caller = account("caller", 0, 0); - let info = DispatchInfo { - weight: Weight::from_parts(100, 0), - class: DispatchClass::Normal, - ..Default::default() - }; - let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); - - #[block] - { - ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) - .unwrap() - .unwrap(); - } - Ok(()) - } - - #[benchmark] - fn check_non_zero_sender() -> Result<(), BenchmarkError> { - let len = 0_usize; - let ext = CheckNonZeroSender::::new(); - let caller = account("caller", 0, 0); - let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; - let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); - - #[block] - { - ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) - .unwrap() - .unwrap(); - } - Ok(()) - } - - #[benchmark] - fn check_nonce() -> Result<(), BenchmarkError> { - let caller: T::AccountId = account("caller", 0, 0); - let mut info = frame_system::AccountInfo::default(); - info.nonce = 1u32.into(); - info.providers = 1; - let expected_nonce = info.nonce + 1u32.into(); - frame_system::Account::::insert(caller.clone(), info); - let len = 0_usize; - let ext = CheckNonce::::from(1u32.into()); - let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; - let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); - - #[block] - { - ext.test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, len, |_| { - Ok(().into()) - }) - .unwrap() - .unwrap(); - } - - let updated_info = frame_system::Account::::get(caller.clone()); - assert_eq!(updated_info.nonce, expected_nonce); - Ok(()) - } - - #[benchmark] - fn check_spec_version() -> Result<(), BenchmarkError> { - let len = 0_usize; - let caller = account("caller", 0, 0); - let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; - let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); - - #[block] - { - CheckSpecVersion::::new() - .test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) - .unwrap() - .unwrap(); - } - Ok(()) - } - - #[benchmark] - fn check_tx_version() -> Result<(), BenchmarkError> { - let len = 0_usize; - let caller = account("caller", 0, 0); - let info = DispatchInfo { weight: Weight::zero(), ..Default::default() }; - let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); - - #[block] - { - CheckTxVersion::::new() - .test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(().into())) - .unwrap() - .unwrap(); - } - Ok(()) - } - - #[benchmark] - fn check_weight() -> Result<(), BenchmarkError> { - let caller = account("caller", 0, 0); - let base_extrinsic = ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - let info = DispatchInfo { - weight: Weight::from_parts(base_extrinsic.ref_time() * 5, 0), - class: DispatchClass::Normal, - ..Default::default() - }; - let call: T::RuntimeCall = frame_system::Call::remark { remark: vec![] }.into(); - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(base_extrinsic.ref_time() * 2, 0)), - pays_fee: Default::default(), - }; - let len = 0_usize; - let base_extrinsic = ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - - let ext = CheckWeight::::new(); - - let initial_block_weight = Weight::from_parts(base_extrinsic.ref_time() * 2, 0); - frame_system::BlockWeight::::mutate(|current_weight| { - current_weight.set(Weight::zero(), DispatchClass::Mandatory); - current_weight.set(initial_block_weight, DispatchClass::Normal); - }); - - #[block] - { - ext.test_run(RawOrigin::Signed(caller).into(), &call, &info, len, |_| Ok(post_info)) - .unwrap() - .unwrap(); - } - - assert_eq!( - System::::block_weight().total(), - initial_block_weight + base_extrinsic + post_info.actual_weight.unwrap(), - ); - Ok(()) - } - - impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test,); -} diff --git a/substrate/frame/system/benchmarking/src/lib.rs b/substrate/frame/system/benchmarking/src/lib.rs index c9f0869d3bc..29100faa751 100644 --- a/substrate/frame/system/benchmarking/src/lib.rs +++ b/substrate/frame/system/benchmarking/src/lib.rs @@ -28,7 +28,6 @@ use sp_core::storage::well_known_keys; use sp_runtime::traits::Hash; use sp_std::{prelude::*, vec}; -pub mod extensions; mod mock; pub struct Pallet(System); diff --git a/substrate/frame/system/benchmarking/src/mock.rs b/substrate/frame/system/benchmarking/src/mock.rs index 1f84dd53004..edbf74a9a51 100644 --- a/substrate/frame/system/benchmarking/src/mock.rs +++ b/substrate/frame/system/benchmarking/src/mock.rs @@ -57,7 +57,6 @@ impl frame_system::Config for Test { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type ExtensionsWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = frame_support::traits::ConstU32<16>; diff --git a/substrate/frame/system/src/extensions/check_genesis.rs b/substrate/frame/system/src/extensions/check_genesis.rs index 3f11f745cd9..76a711a823e 100644 --- a/substrate/frame/system/src/extensions/check_genesis.rs +++ b/substrate/frame/system/src/extensions/check_genesis.rs @@ -19,8 +19,7 @@ use crate::{pallet_prelude::BlockNumberFor, Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ - impl_tx_ext_default, - traits::{TransactionExtension, TransactionExtensionBase, Zero}, + traits::{DispatchInfoOf, SignedExtension, Zero}, transaction_validity::TransactionValidityError, }; @@ -47,26 +46,30 @@ impl sp_std::fmt::Debug for CheckGenesis { } impl CheckGenesis { - /// Creates new `TransactionExtension` to check genesis hash. + /// Creates new `SignedExtension` to check genesis hash. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl TransactionExtensionBase for CheckGenesis { +impl SignedExtension for CheckGenesis { + type AccountId = T::AccountId; + type Call = ::RuntimeCall; + type AdditionalSigned = T::Hash; + type Pre = (); const IDENTIFIER: &'static str = "CheckGenesis"; - type Implicit = T::Hash; - fn implicit(&self) -> Result { + + fn additional_signed(&self) -> Result { Ok(>::block_hash(BlockNumberFor::::zero())) } - fn weight(&self) -> sp_weights::Weight { - ::check_genesis() + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) } } -impl TransactionExtension - for CheckGenesis -{ - type Val = (); - type Pre = (); - impl_tx_ext_default!(T::RuntimeCall; Context; validate prepare); -} diff --git a/substrate/frame/system/src/extensions/check_mortality.rs b/substrate/frame/system/src/extensions/check_mortality.rs index deb44880d64..148dfd4aad4 100644 --- a/substrate/frame/system/src/extensions/check_mortality.rs +++ b/substrate/frame/system/src/extensions/check_mortality.rs @@ -20,12 +20,10 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ generic::Era, - impl_tx_ext_default, - traits::{ - DispatchInfoOf, SaturatedConversion, TransactionExtension, TransactionExtensionBase, - ValidateResult, + traits::{DispatchInfoOf, SaturatedConversion, SignedExtension}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, }, - transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction}, }; /// Check for transaction mortality. @@ -56,11 +54,29 @@ impl sp_std::fmt::Debug for CheckMortality { } } -impl TransactionExtensionBase for CheckMortality { +impl SignedExtension for CheckMortality { + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = T::Hash; + type Pre = (); const IDENTIFIER: &'static str = "CheckMortality"; - type Implicit = T::Hash; - fn implicit(&self) -> Result { + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + let current_u64 = >::block_number().saturated_into::(); + let valid_till = self.0.death(current_u64); + Ok(ValidTransaction { + longevity: valid_till.saturating_sub(current_u64), + ..Default::default() + }) + } + + fn additional_signed(&self) -> Result { let current_u64 = >::block_number().saturated_into::(); let n = self.0.birth(current_u64).saturated_into::>(); if !>::contains_key(n) { @@ -69,38 +85,16 @@ impl TransactionExtensionBase for CheckMortality { Ok(>::block_hash(n)) } } - fn weight(&self) -> sp_weights::Weight { - ::check_mortality() - } -} -impl TransactionExtension - for CheckMortality -{ - type Pre = (); - type Val = (); - fn validate( - &self, - origin: ::RuntimeOrigin, - _call: &T::RuntimeCall, - _info: &DispatchInfoOf, - _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult { - let current_u64 = >::block_number().saturated_into::(); - let valid_till = self.0.death(current_u64); - Ok(( - ValidTransaction { - longevity: valid_till.saturating_sub(current_u64), - ..Default::default() - }, - (), - origin, - )) + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) } - impl_tx_ext_default!(T::RuntimeCall; Context; prepare); } #[cfg(test)] @@ -112,21 +106,23 @@ mod tests { weights::Weight, }; use sp_core::H256; - use sp_runtime::traits::DispatchTransaction; #[test] fn signed_ext_check_era_should_work() { new_test_ext().execute_with(|| { // future assert_eq!( - CheckMortality::::from(Era::mortal(4, 2)).implicit().err().unwrap(), + CheckMortality::::from(Era::mortal(4, 2)) + .additional_signed() + .err() + .unwrap(), InvalidTransaction::AncientBirthBlock.into(), ); // correct System::set_block_number(13); >::insert(12, H256::repeat_byte(1)); - assert!(CheckMortality::::from(Era::mortal(4, 12)).implicit().is_ok()); + assert!(CheckMortality::::from(Era::mortal(4, 12)).additional_signed().is_ok()); }) } @@ -146,10 +142,7 @@ mod tests { System::set_block_number(17); >::insert(16, H256::repeat_byte(1)); - assert_eq!( - ext.validate_only(Some(1).into(), CALL, &normal, len).unwrap().0.longevity, - 15 - ); + assert_eq!(ext.validate(&1, CALL, &normal, len).unwrap().longevity, 15); }) } } diff --git a/substrate/frame/system/src/extensions/check_non_zero_sender.rs b/substrate/frame/system/src/extensions/check_non_zero_sender.rs index 115ffac9b03..92eed60fc66 100644 --- a/substrate/frame/system/src/extensions/check_non_zero_sender.rs +++ b/substrate/frame/system/src/extensions/check_non_zero_sender.rs @@ -17,14 +17,13 @@ use crate::Config; use codec::{Decode, Encode}; -use frame_support::{traits::OriginTrait, DefaultNoBound}; +use frame_support::{dispatch::DispatchInfo, DefaultNoBound}; use scale_info::TypeInfo; use sp_runtime::{ - impl_tx_ext_default, - traits::{ - transaction_extension::TransactionExtensionBase, DispatchInfoOf, TransactionExtension, + traits::{DispatchInfoOf, Dispatchable, SignedExtension}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, }, - transaction_validity::InvalidTransaction, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -46,82 +45,66 @@ impl sp_std::fmt::Debug for CheckNonZeroSender { } impl CheckNonZeroSender { - /// Create new `TransactionExtension` to check runtime version. + /// Create new `SignedExtension` to check runtime version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl TransactionExtensionBase for CheckNonZeroSender { - const IDENTIFIER: &'static str = "CheckNonZeroSender"; - type Implicit = (); - fn weight(&self) -> sp_weights::Weight { - ::check_non_zero_sender() - } -} -impl TransactionExtension - for CheckNonZeroSender +impl SignedExtension for CheckNonZeroSender +where + T::RuntimeCall: Dispatchable, { - type Val = (); + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = (); type Pre = (); + const IDENTIFIER: &'static str = "CheckNonZeroSender"; + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) + } + fn validate( &self, - origin: ::RuntimeOrigin, - _call: &T::RuntimeCall, - _info: &DispatchInfoOf, + who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> sp_runtime::traits::ValidateResult { - if let Some(who) = origin.as_system_signer() { - if who.using_encoded(|d| d.iter().all(|x| *x == 0)) { - return Err(InvalidTransaction::BadSigner.into()) - } + ) -> TransactionValidity { + if who.using_encoded(|d| d.iter().all(|x| *x == 0)) { + return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)) } - Ok((Default::default(), (), origin)) + Ok(ValidTransaction::default()) } - impl_tx_ext_default!(T::RuntimeCall; Context; prepare); } #[cfg(test)] mod tests { use super::*; use crate::mock::{new_test_ext, Test, CALL}; - use frame_support::{assert_ok, dispatch::DispatchInfo}; - use sp_runtime::{traits::DispatchTransaction, TransactionValidityError}; + use frame_support::{assert_noop, assert_ok}; #[test] fn zero_account_ban_works() { new_test_ext().execute_with(|| { let info = DispatchInfo::default(); let len = 0_usize; - assert_eq!( - CheckNonZeroSender::::new() - .validate_only(Some(0).into(), CALL, &info, len) - .unwrap_err(), - TransactionValidityError::from(InvalidTransaction::BadSigner) + assert_noop!( + CheckNonZeroSender::::new().validate(&0, CALL, &info, len), + InvalidTransaction::BadSigner ); - assert_ok!(CheckNonZeroSender::::new().validate_only( - Some(1).into(), - CALL, - &info, - len - )); - }) - } - - #[test] - fn unsigned_origin_works() { - new_test_ext().execute_with(|| { - let info = DispatchInfo::default(); - let len = 0_usize; - assert_ok!(CheckNonZeroSender::::new().validate_only( - None.into(), - CALL, - &info, - len - )); + assert_ok!(CheckNonZeroSender::::new().validate(&1, CALL, &info, len)); }) } } diff --git a/substrate/frame/system/src/extensions/check_nonce.rs b/substrate/frame/system/src/extensions/check_nonce.rs index ead9d9f7c81..7504a814aef 100644 --- a/substrate/frame/system/src/extensions/check_nonce.rs +++ b/substrate/frame/system/src/extensions/check_nonce.rs @@ -15,19 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{AccountInfo, Config}; +use crate::Config; use codec::{Decode, Encode}; use frame_support::dispatch::DispatchInfo; use scale_info::TypeInfo; use sp_runtime::{ - traits::{ - AsSystemOriginSigner, DispatchInfoOf, Dispatchable, One, TransactionExtension, - TransactionExtensionBase, ValidateResult, Zero, - }, + traits::{DispatchInfoOf, Dispatchable, One, SignedExtension, Zero}, transaction_validity::{ - InvalidTransaction, TransactionLongevity, TransactionValidityError, ValidTransaction, + InvalidTransaction, TransactionLongevity, TransactionValidity, TransactionValidityError, + ValidTransaction, }, - Saturating, }; use sp_std::vec; @@ -61,78 +58,75 @@ impl sp_std::fmt::Debug for CheckNonce { } } -impl TransactionExtensionBase for CheckNonce { - const IDENTIFIER: &'static str = "CheckNonce"; - type Implicit = (); - fn weight(&self) -> sp_weights::Weight { - ::check_nonce() - } -} -impl TransactionExtension for CheckNonce +impl SignedExtension for CheckNonce where T::RuntimeCall: Dispatchable, - ::RuntimeOrigin: AsSystemOriginSigner + Clone, { - type Val = Option<(T::AccountId, AccountInfo)>; + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = (); type Pre = (); + const IDENTIFIER: &'static str = "CheckNonce"; + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result<(), TransactionValidityError> { + let mut account = crate::Account::::get(who); + if account.providers.is_zero() && account.sufficients.is_zero() { + // Nonce storage not paid for + return Err(InvalidTransaction::Payment.into()) + } + if self.0 != account.nonce { + return Err(if self.0 < account.nonce { + InvalidTransaction::Stale + } else { + InvalidTransaction::Future + } + .into()) + } + account.nonce += T::Nonce::one(); + crate::Account::::insert(who, account); + Ok(()) + } fn validate( &self, - origin: ::RuntimeOrigin, - _call: &T::RuntimeCall, - _info: &DispatchInfoOf, + who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult { - let Some(who) = origin.as_system_origin_signer() else { - return Ok((Default::default(), None, origin)) - }; + ) -> TransactionValidity { let account = crate::Account::::get(who); if account.providers.is_zero() && account.sufficients.is_zero() { // Nonce storage not paid for - return Err(InvalidTransaction::Payment.into()) + return InvalidTransaction::Payment.into() } if self.0 < account.nonce { - return Err(InvalidTransaction::Stale.into()) + return InvalidTransaction::Stale.into() } - let provides = vec![Encode::encode(&(who.clone(), self.0))]; + let provides = vec![Encode::encode(&(who, self.0))]; let requires = if account.nonce < self.0 { - vec![Encode::encode(&(who.clone(), self.0.saturating_sub(One::one())))] + vec![Encode::encode(&(who, self.0 - One::one()))] } else { vec![] }; - let validity = ValidTransaction { + Ok(ValidTransaction { priority: 0, requires, provides, longevity: TransactionLongevity::max_value(), propagate: true, - }; - - Ok((validity, Some((who.clone(), account)), origin)) - } - - fn prepare( - self, - val: Self::Val, - _origin: &T::RuntimeOrigin, - _call: &T::RuntimeCall, - _info: &DispatchInfoOf, - _len: usize, - _context: &Context, - ) -> Result { - let Some((who, mut account)) = val else { return Ok(()) }; - // `self.0 < account.nonce` already checked in `validate`. - if self.0 > account.nonce { - return Err(InvalidTransaction::Future.into()) - } - account.nonce.saturating_inc(); - crate::Account::::insert(who, account); - Ok(()) + }) } } @@ -140,8 +134,7 @@ where mod tests { use super::*; use crate::mock::{new_test_ext, Test, CALL}; - use frame_support::assert_ok; - use sp_runtime::traits::DispatchTransaction; + use frame_support::{assert_noop, assert_ok}; #[test] fn signed_ext_check_nonce_works() { @@ -159,33 +152,22 @@ mod tests { let info = DispatchInfo::default(); let len = 0_usize; // stale - assert_eq!( - CheckNonce::(0) - .validate_only(Some(1).into(), CALL, &info, len,) - .unwrap_err(), - TransactionValidityError::Invalid(InvalidTransaction::Stale) + assert_noop!( + CheckNonce::(0).validate(&1, CALL, &info, len), + InvalidTransaction::Stale ); - assert_eq!( - CheckNonce::(0) - .validate_and_prepare(Some(1).into(), CALL, &info, len) - .unwrap_err(), - InvalidTransaction::Stale.into() + assert_noop!( + CheckNonce::(0).pre_dispatch(&1, CALL, &info, len), + InvalidTransaction::Stale ); // correct - assert_ok!(CheckNonce::(1).validate_only(Some(1).into(), CALL, &info, len)); - assert_ok!(CheckNonce::(1).validate_and_prepare( - Some(1).into(), - CALL, - &info, - len - )); + assert_ok!(CheckNonce::(1).validate(&1, CALL, &info, len)); + assert_ok!(CheckNonce::(1).pre_dispatch(&1, CALL, &info, len)); // future - assert_ok!(CheckNonce::(5).validate_only(Some(1).into(), CALL, &info, len)); - assert_eq!( - CheckNonce::(5) - .validate_and_prepare(Some(1).into(), CALL, &info, len) - .unwrap_err(), - InvalidTransaction::Future.into() + assert_ok!(CheckNonce::(5).validate(&1, CALL, &info, len)); + assert_noop!( + CheckNonce::(5).pre_dispatch(&1, CALL, &info, len), + InvalidTransaction::Future ); }) } @@ -216,44 +198,20 @@ mod tests { let info = DispatchInfo::default(); let len = 0_usize; // Both providers and sufficients zero - assert_eq!( - CheckNonce::(1) - .validate_only(Some(1).into(), CALL, &info, len) - .unwrap_err(), - TransactionValidityError::Invalid(InvalidTransaction::Payment) + assert_noop!( + CheckNonce::(1).validate(&1, CALL, &info, len), + InvalidTransaction::Payment ); - assert_eq!( - CheckNonce::(1) - .validate_and_prepare(Some(1).into(), CALL, &info, len) - .unwrap_err(), - TransactionValidityError::Invalid(InvalidTransaction::Payment) + assert_noop!( + CheckNonce::(1).pre_dispatch(&1, CALL, &info, len), + InvalidTransaction::Payment ); // Non-zero providers - assert_ok!(CheckNonce::(1).validate_only(Some(2).into(), CALL, &info, len)); - assert_ok!(CheckNonce::(1).validate_and_prepare( - Some(2).into(), - CALL, - &info, - len - )); + assert_ok!(CheckNonce::(1).validate(&2, CALL, &info, len)); + assert_ok!(CheckNonce::(1).pre_dispatch(&2, CALL, &info, len)); // Non-zero sufficients - assert_ok!(CheckNonce::(1).validate_only(Some(3).into(), CALL, &info, len)); - assert_ok!(CheckNonce::(1).validate_and_prepare( - Some(3).into(), - CALL, - &info, - len - )); - }) - } - - #[test] - fn unsigned_check_nonce_works() { - new_test_ext().execute_with(|| { - let info = DispatchInfo::default(); - let len = 0_usize; - assert_ok!(CheckNonce::(1).validate_only(None.into(), CALL, &info, len)); - assert_ok!(CheckNonce::(1).validate_and_prepare(None.into(), CALL, &info, len)); + assert_ok!(CheckNonce::(1).validate(&3, CALL, &info, len)); + assert_ok!(CheckNonce::(1).pre_dispatch(&3, CALL, &info, len)); }) } } diff --git a/substrate/frame/system/src/extensions/check_spec_version.rs b/substrate/frame/system/src/extensions/check_spec_version.rs index 3109708f48e..24d5ef9cafb 100644 --- a/substrate/frame/system/src/extensions/check_spec_version.rs +++ b/substrate/frame/system/src/extensions/check_spec_version.rs @@ -19,8 +19,7 @@ use crate::{Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ - impl_tx_ext_default, - traits::{transaction_extension::TransactionExtensionBase, TransactionExtension}, + traits::{DispatchInfoOf, SignedExtension}, transaction_validity::TransactionValidityError, }; @@ -47,26 +46,30 @@ impl sp_std::fmt::Debug for CheckSpecVersion { } impl CheckSpecVersion { - /// Create new `TransactionExtension` to check runtime version. + /// Create new `SignedExtension` to check runtime version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl TransactionExtensionBase for CheckSpecVersion { +impl SignedExtension for CheckSpecVersion { + type AccountId = T::AccountId; + type Call = ::RuntimeCall; + type AdditionalSigned = u32; + type Pre = (); const IDENTIFIER: &'static str = "CheckSpecVersion"; - type Implicit = u32; - fn implicit(&self) -> Result { + + fn additional_signed(&self) -> Result { Ok(>::runtime_version().spec_version) } - fn weight(&self) -> sp_weights::Weight { - ::check_spec_version() + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) } } -impl TransactionExtension<::RuntimeCall, Context> - for CheckSpecVersion -{ - type Val = (); - type Pre = (); - impl_tx_ext_default!(::RuntimeCall; Context; validate prepare); -} diff --git a/substrate/frame/system/src/extensions/check_tx_version.rs b/substrate/frame/system/src/extensions/check_tx_version.rs index ee1d507e7bc..3f9d6a1903f 100644 --- a/substrate/frame/system/src/extensions/check_tx_version.rs +++ b/substrate/frame/system/src/extensions/check_tx_version.rs @@ -19,8 +19,7 @@ use crate::{Config, Pallet}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::{ - impl_tx_ext_default, - traits::{transaction_extension::TransactionExtensionBase, TransactionExtension}, + traits::{DispatchInfoOf, SignedExtension}, transaction_validity::TransactionValidityError, }; @@ -47,26 +46,29 @@ impl sp_std::fmt::Debug for CheckTxVersion { } impl CheckTxVersion { - /// Create new `TransactionExtension` to check transaction version. + /// Create new `SignedExtension` to check transaction version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl TransactionExtensionBase for CheckTxVersion { +impl SignedExtension for CheckTxVersion { + type AccountId = T::AccountId; + type Call = ::RuntimeCall; + type AdditionalSigned = u32; + type Pre = (); const IDENTIFIER: &'static str = "CheckTxVersion"; - type Implicit = u32; - fn implicit(&self) -> Result { + + fn additional_signed(&self) -> Result { Ok(>::runtime_version().transaction_version) } - fn weight(&self) -> sp_weights::Weight { - ::check_tx_version() + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) } } -impl TransactionExtension<::RuntimeCall, Context> - for CheckTxVersion -{ - type Val = (); - type Pre = (); - impl_tx_ext_default!(::RuntimeCall; Context; validate prepare); -} diff --git a/substrate/frame/system/src/extensions/check_weight.rs b/substrate/frame/system/src/extensions/check_weight.rs index 5c35acfb3f3..70d1e756332 100644 --- a/substrate/frame/system/src/extensions/check_weight.rs +++ b/substrate/frame/system/src/extensions/check_weight.rs @@ -23,12 +23,9 @@ use frame_support::{ }; use scale_info::TypeInfo; use sp_runtime::{ - traits::{ - DispatchInfoOf, Dispatchable, PostDispatchInfoOf, TransactionExtension, - TransactionExtensionBase, ValidateResult, - }, - transaction_validity::{InvalidTransaction, TransactionValidityError}, - DispatchResult, ValidTransaction, + traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, + transaction_validity::{InvalidTransaction, TransactionValidity, TransactionValidityError}, + DispatchResult, }; use sp_weights::Weight; @@ -103,44 +100,40 @@ where } } - /// Creates new `TransactionExtension` to check weight of the extrinsic. + /// Creates new `SignedExtension` to check weight of the extrinsic. pub fn new() -> Self { Self(Default::default()) } - /// Do the validate checks. This can be applied to both signed and unsigned. - /// - /// It only checks that the block weight and length limit will not exceed. - /// - /// Returns the transaction validity and the next block length, to be used in `prepare`. - pub fn do_validate( - info: &DispatchInfoOf, - len: usize, - ) -> Result<(ValidTransaction, u32), TransactionValidityError> { - // ignore the next length. If they return `Ok`, then it is below the limit. - let next_len = Self::check_block_length(info, len)?; - // during validation we skip block limit check. Since the `validate_transaction` - // call runs on an empty block anyway, by this we prevent `on_initialize` weight - // consumption from causing false negatives. - Self::check_extrinsic_weight(info)?; - - Ok((Default::default(), next_len)) - } - /// Do the pre-dispatch checks. This can be applied to both signed and unsigned. /// /// It checks and notes the new weight and length. - pub fn do_prepare( + pub fn do_pre_dispatch( info: &DispatchInfoOf, - next_len: u32, + len: usize, ) -> Result<(), TransactionValidityError> { + let next_len = Self::check_block_length(info, len)?; let next_weight = Self::check_block_weight(info)?; - // Extrinsic weight already checked in `validate`. + Self::check_extrinsic_weight(info)?; crate::AllExtrinsicsLen::::put(next_len); crate::BlockWeight::::put(next_weight); Ok(()) } + + /// Do the validate checks. This can be applied to both signed and unsigned. + /// + /// It only checks that the block weight and length limit will not exceed. + pub fn do_validate(info: &DispatchInfoOf, len: usize) -> TransactionValidity { + // ignore the next length. If they return `Ok`, then it is below the limit. + let _ = Self::check_block_length(info, len)?; + // during validation we skip block limit check. Since the `validate_transaction` + // call runs on an empty block anyway, by this we prevent `on_initialize` weight + // consumption from causing false negatives. + Self::check_extrinsic_weight(info)?; + + Ok(Default::default()) + } } pub fn calculate_consumed_weight( @@ -208,55 +201,62 @@ where Ok(all_weight) } -impl TransactionExtensionBase for CheckWeight { - const IDENTIFIER: &'static str = "CheckWeight"; - type Implicit = (); - - fn weight(&self) -> Weight { - ::check_weight() - } -} -impl TransactionExtension - for CheckWeight +impl SignedExtension for CheckWeight where T::RuntimeCall: Dispatchable, { + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = (); type Pre = (); - type Val = u32; /* next block length */ + const IDENTIFIER: &'static str = "CheckWeight"; + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(), TransactionValidityError> { + Self::do_pre_dispatch(info, len) + } fn validate( &self, - origin: T::RuntimeOrigin, - _call: &T::RuntimeCall, - info: &DispatchInfoOf, + _who: &Self::AccountId, + _call: &Self::Call, + info: &DispatchInfoOf, len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult { - let (validity, next_len) = Self::do_validate(info, len)?; - Ok((validity, next_len, origin)) + ) -> TransactionValidity { + Self::do_validate(info, len) } - fn prepare( - self, - val: Self::Val, - _origin: &T::RuntimeOrigin, - _call: &T::RuntimeCall, - info: &DispatchInfoOf, - _len: usize, - _context: &Context, - ) -> Result { - Self::do_prepare(info, val) + fn pre_dispatch_unsigned( + _call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(), TransactionValidityError> { + Self::do_pre_dispatch(info, len) + } + + fn validate_unsigned( + _call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + Self::do_validate(info, len) } fn post_dispatch( - _pre: Self::Pre, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + _pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, _len: usize, _result: &DispatchResult, - _context: &Context, ) -> Result<(), TransactionValidityError> { let unspent = post_info.calc_unspent(info); if unspent.any_gt(Weight::zero()) { @@ -301,7 +301,6 @@ mod tests { AllExtrinsicsLen, BlockWeight, DispatchClass, }; use frame_support::{assert_err, assert_ok, dispatch::Pays, weights::Weight}; - use sp_runtime::traits::DispatchTransaction; use sp_std::marker::PhantomData; fn block_weights() -> crate::limits::BlockWeights { @@ -339,8 +338,7 @@ mod tests { } check(|max, len| { - let next_len = CheckWeight::::check_block_length(max, len).unwrap(); - assert_ok!(CheckWeight::::do_prepare(max, next_len)); + assert_ok!(CheckWeight::::do_pre_dispatch(max, len)); assert_eq!(System::block_weight().total(), Weight::MAX); assert!(System::block_weight().total().ref_time() > block_weight_limit().ref_time()); }); @@ -421,11 +419,9 @@ mod tests { let len = 0_usize; - let next_len = CheckWeight::::check_block_length(&max_normal, len).unwrap(); - assert_ok!(CheckWeight::::do_prepare(&max_normal, next_len)); + assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); assert_eq!(System::block_weight().total(), Weight::from_parts(768, 0)); - let next_len = CheckWeight::::check_block_length(&rest_operational, len).unwrap(); - assert_ok!(CheckWeight::::do_prepare(&rest_operational, next_len)); + assert_ok!(CheckWeight::::do_pre_dispatch(&rest_operational, len)); assert_eq!(block_weight_limit(), Weight::from_parts(1024, u64::MAX)); assert_eq!(System::block_weight().total(), block_weight_limit().set_proof_size(0)); // Checking single extrinsic should not take current block weight into account. @@ -447,12 +443,10 @@ mod tests { let len = 0_usize; - let next_len = CheckWeight::::check_block_length(&rest_operational, len).unwrap(); - assert_ok!(CheckWeight::::do_prepare(&rest_operational, next_len)); + assert_ok!(CheckWeight::::do_pre_dispatch(&rest_operational, len)); // Extra 20 here from block execution + base extrinsic weight assert_eq!(System::block_weight().total(), Weight::from_parts(266, 0)); - let next_len = CheckWeight::::check_block_length(&max_normal, len).unwrap(); - assert_ok!(CheckWeight::::do_prepare(&max_normal, next_len)); + assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); assert_eq!(block_weight_limit(), Weight::from_parts(1024, u64::MAX)); assert_eq!(System::block_weight().total(), block_weight_limit().set_proof_size(0)); }); @@ -475,19 +469,16 @@ mod tests { }; let len = 0_usize; - let next_len = CheckWeight::::check_block_length(&dispatch_normal, len).unwrap(); assert_err!( - CheckWeight::::do_prepare(&dispatch_normal, next_len), + CheckWeight::::do_pre_dispatch(&dispatch_normal, len), InvalidTransaction::ExhaustsResources ); - let next_len = - CheckWeight::::check_block_length(&dispatch_operational, len).unwrap(); // Thank goodness we can still do an operational transaction to possibly save the // blockchain. - assert_ok!(CheckWeight::::do_prepare(&dispatch_operational, next_len)); + assert_ok!(CheckWeight::::do_pre_dispatch(&dispatch_operational, len)); // Not too much though assert_err!( - CheckWeight::::do_prepare(&dispatch_operational, next_len), + CheckWeight::::do_pre_dispatch(&dispatch_operational, len), InvalidTransaction::ExhaustsResources ); // Even with full block, validity of single transaction should be correct. @@ -512,35 +503,21 @@ mod tests { current_weight.set(normal_limit, DispatchClass::Normal) }); // will not fit. - assert_eq!( - CheckWeight::(PhantomData) - .validate_and_prepare(Some(1).into(), CALL, &normal, len) - .unwrap_err(), - InvalidTransaction::ExhaustsResources.into() + assert_err!( + CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &normal, len), + InvalidTransaction::ExhaustsResources ); // will fit. - assert_ok!(CheckWeight::(PhantomData).validate_and_prepare( - Some(1).into(), - CALL, - &op, - len - )); + assert_ok!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &op, len)); // likewise for length limit. let len = 100_usize; AllExtrinsicsLen::::put(normal_length_limit()); - assert_eq!( - CheckWeight::(PhantomData) - .validate_and_prepare(Some(1).into(), CALL, &normal, len) - .unwrap_err(), - InvalidTransaction::ExhaustsResources.into() + assert_err!( + CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &normal, len), + InvalidTransaction::ExhaustsResources ); - assert_ok!(CheckWeight::(PhantomData).validate_and_prepare( - Some(1).into(), - CALL, - &op, - len - )); + assert_ok!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &op, len)); }) } @@ -551,12 +528,7 @@ mod tests { let normal_limit = normal_weight_limit().ref_time() as usize; let reset_check_weight = |tx, s, f| { AllExtrinsicsLen::::put(0); - let r = CheckWeight::(PhantomData).validate_and_prepare( - Some(1).into(), - CALL, - tx, - s, - ); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, tx, s); if f { assert!(r.is_err()) } else { @@ -599,12 +571,7 @@ mod tests { BlockWeight::::mutate(|current_weight| { current_weight.set(s, DispatchClass::Normal) }); - let r = CheckWeight::(PhantomData).validate_and_prepare( - Some(1).into(), - CALL, - i, - len, - ); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, i, len); if f { assert!(r.is_err()) } else { @@ -637,22 +604,18 @@ mod tests { .set(Weight::from_parts(256, 0) - base_extrinsic, DispatchClass::Normal); }); - let pre = CheckWeight::(PhantomData) - .validate_and_prepare(Some(1).into(), CALL, &info, len) - .unwrap() - .0; + let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); assert_eq!( BlockWeight::::get().total(), info.weight + Weight::from_parts(256, 0) ); assert_ok!(CheckWeight::::post_dispatch( - pre, + Some(pre), &info, &post_info, len, - &Ok(()), - &() + &Ok(()) )); assert_eq!( BlockWeight::::get().total(), @@ -676,10 +639,7 @@ mod tests { current_weight.set(Weight::from_parts(128, 0), DispatchClass::Normal); }); - let pre = CheckWeight::(PhantomData) - .validate_and_prepare(Some(1).into(), CALL, &info, len) - .unwrap() - .0; + let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); assert_eq!( BlockWeight::::get().total(), info.weight + @@ -688,12 +648,11 @@ mod tests { ); assert_ok!(CheckWeight::::post_dispatch( - pre, + Some(pre), &info, &post_info, len, - &Ok(()), - &() + &Ok(()) )); assert_eq!( BlockWeight::::get().total(), @@ -713,12 +672,7 @@ mod tests { // Initial weight from `weights.base_block` assert_eq!(System::block_weight().total(), weights.base_block); - assert_ok!(CheckWeight::(PhantomData).validate_and_prepare( - Some(1).into(), - CALL, - &free, - len - )); + assert_ok!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &free, len)); assert_eq!( System::block_weight().total(), weights.get(DispatchClass::Normal).base_extrinsic + weights.base_block @@ -742,11 +696,9 @@ mod tests { let len = 0_usize; - let next_len = CheckWeight::::check_block_length(&max_normal, len).unwrap(); - assert_ok!(CheckWeight::::do_prepare(&max_normal, next_len)); + assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); assert_eq!(System::block_weight().total(), Weight::from_parts(768, 0)); - let next_len = CheckWeight::::check_block_length(&mandatory, len).unwrap(); - assert_ok!(CheckWeight::::do_prepare(&mandatory, next_len)); + assert_ok!(CheckWeight::::do_pre_dispatch(&mandatory, len)); assert_eq!(block_weight_limit(), Weight::from_parts(1024, u64::MAX)); assert_eq!(System::block_weight().total(), Weight::from_parts(1024 + 768, 0)); assert_eq!(CheckWeight::::check_extrinsic_weight(&mandatory), Ok(())); diff --git a/substrate/frame/system/src/extensions/mod.rs b/substrate/frame/system/src/extensions/mod.rs index d79104d2240..a88c9fbf96e 100644 --- a/substrate/frame/system/src/extensions/mod.rs +++ b/substrate/frame/system/src/extensions/mod.rs @@ -22,6 +22,3 @@ pub mod check_nonce; pub mod check_spec_version; pub mod check_tx_version; pub mod check_weight; -pub mod weights; - -pub use weights::WeightInfo; diff --git a/substrate/frame/system/src/extensions/weights.rs b/substrate/frame/system/src/extensions/weights.rs deleted file mode 100644 index 0d2fcb15ee6..00000000000 --- a/substrate/frame/system/src/extensions/weights.rs +++ /dev/null @@ -1,196 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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 `frame_system_extensions` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` - -// Executed Command: -// ./target/production/substrate-node -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=frame_system_extensions -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/system/src/extensions/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for `frame_system_extensions`. -pub trait WeightInfo { - fn check_genesis() -> Weight; - fn check_mortality() -> Weight; - fn check_non_zero_sender() -> Weight; - fn check_nonce() -> Weight; - fn check_spec_version() -> Weight; - fn check_tx_version() -> Weight; - fn check_weight() -> Weight; -} - -/// Weights for `frame_system_extensions` using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_876_000 picoseconds. - Weight::from_parts(4_160_000, 3509) - .saturating_add(T::DbWeight::get().reads(1_u64)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 6_296_000 picoseconds. - Weight::from_parts(6_523_000, 3509) - .saturating_add(T::DbWeight::get().reads(1_u64)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 449_000 picoseconds. - Weight::from_parts(527_000, 0) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `101` - // Estimated: `3593` - // Minimum execution time: 5_689_000 picoseconds. - Weight::from_parts(6_000_000, 3593) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 399_000 picoseconds. - Weight::from_parts(461_000, 0) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 390_000 picoseconds. - Weight::from_parts(439_000, 0) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1489` - // Minimum execution time: 4_375_000 picoseconds. - Weight::from_parts(4_747_000, 1489) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } -} - -// For backwards compatibility and tests. -impl WeightInfo for () { - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_genesis() -> Weight { - // Proof Size summary in bytes: - // Measured: `54` - // Estimated: `3509` - // Minimum execution time: 3_876_000 picoseconds. - Weight::from_parts(4_160_000, 3509) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - } - /// Storage: `System::BlockHash` (r:1 w:0) - /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) - fn check_mortality() -> Weight { - // Proof Size summary in bytes: - // Measured: `92` - // Estimated: `3509` - // Minimum execution time: 6_296_000 picoseconds. - Weight::from_parts(6_523_000, 3509) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - } - fn check_non_zero_sender() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 449_000 picoseconds. - Weight::from_parts(527_000, 0) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn check_nonce() -> Weight { - // Proof Size summary in bytes: - // Measured: `101` - // Estimated: `3593` - // Minimum execution time: 5_689_000 picoseconds. - Weight::from_parts(6_000_000, 3593) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - fn check_spec_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 399_000 picoseconds. - Weight::from_parts(461_000, 0) - } - fn check_tx_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 390_000 picoseconds. - Weight::from_parts(439_000, 0) - } - /// Storage: `System::AllExtrinsicsLen` (r:1 w:1) - /// Proof: `System::AllExtrinsicsLen` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - fn check_weight() -> Weight { - // Proof Size summary in bytes: - // Measured: `24` - // Estimated: `1489` - // Minimum execution time: 4_375_000 picoseconds. - Weight::from_parts(4_747_000, 1489) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } -} diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 0318f77342e..184f27b61ed 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -166,7 +166,7 @@ pub use extensions::{ check_genesis::CheckGenesis, check_mortality::CheckMortality, check_non_zero_sender::CheckNonZeroSender, check_nonce::CheckNonce, check_spec_version::CheckSpecVersion, check_tx_version::CheckTxVersion, - check_weight::CheckWeight, WeightInfo as ExtensionsWeightInfo, + check_weight::CheckWeight, }; // Backward compatible re-export. pub use extensions::check_mortality::CheckMortality as CheckEra; @@ -284,7 +284,6 @@ pub mod pallet { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type ExtensionsWeightInfo = (); type SS58Prefix = (); type Version = (); type BlockWeights = (); @@ -357,9 +356,6 @@ pub mod pallet { /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); - /// Weight information for the extensions of this pallet. - type ExtensionsWeightInfo = (); - /// This is used as an identifier of the chain. type SS58Prefix = (); @@ -567,12 +563,8 @@ pub mod pallet { /// All resources should be cleaned up associated with the given account. type OnKilledAccount: OnKilledAccount; - /// Weight information for the extrinsics of this pallet. type SystemWeightInfo: WeightInfo; - /// Weight information for the transaction extensions of this pallet. - type ExtensionsWeightInfo: extensions::WeightInfo; - /// The designated SS58 prefix of this chain. /// /// This replaces the "ss58Format" property declared in the chain spec. Reason is diff --git a/substrate/frame/system/src/offchain.rs b/substrate/frame/system/src/offchain.rs index ee73e33fe31..a019cfd666e 100644 --- a/substrate/frame/system/src/offchain.rs +++ b/substrate/frame/system/src/offchain.rs @@ -79,9 +79,6 @@ pub struct SubmitTransaction, Overarchi _phantom: sp_std::marker::PhantomData<(T, OverarchingCall)>, } -// TODO [#2415]: Avoid splitting call and the totally opaque `signature`; `CreateTransaction` trait -// should provide something which impls `Encode`, which can be sent onwards to -// `sp_io::offchain::submit_transaction`. There's no great need to split things up as in here. impl SubmitTransaction where T: SendTransactionTypes, @@ -91,8 +88,6 @@ where call: >::OverarchingCall, signature: Option<::SignaturePayload>, ) -> Result<(), ()> { - // TODO: Use regular transaction API instead. - #[allow(deprecated)] let xt = T::Extrinsic::new(call, signature).ok_or(())?; sp_io::offchain::submit_transaction(xt.encode()) } @@ -476,7 +471,7 @@ pub trait SendTransactionTypes { /// /// This trait is meant to be implemented by the runtime and is responsible for constructing /// a payload to be signed and contained within the extrinsic. -/// This will most likely include creation of `TxExtension` (a tuple of `TransactionExtension`s). +/// This will most likely include creation of `SignedExtra` (a set of `SignedExtensions`). /// Note that the result can be altered by inspecting the `Call` (for instance adjusting /// fees, or mortality depending on the `pallet` being called). pub trait CreateSignedTransaction: @@ -626,17 +621,14 @@ mod tests { use crate::mock::{RuntimeCall, Test as TestRuntime, CALL}; use codec::Decode; use sp_core::offchain::{testing, TransactionPoolExt}; - use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{TestSignature, UintAuthorityId}, - }; + use sp_runtime::testing::{TestSignature, TestXt, UintAuthorityId}; impl SigningTypes for TestRuntime { type Public = UintAuthorityId; type Signature = TestSignature; } - type Extrinsic = UncheckedExtrinsic; + type Extrinsic = TestXt; impl SendTransactionTypes for TestRuntime { type Extrinsic = Extrinsic; @@ -701,7 +693,7 @@ mod tests { let _tx3 = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); - assert!(tx1.is_inherent()); + assert_eq!(tx1.signature, None); }); } @@ -732,7 +724,7 @@ mod tests { let tx1 = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); - assert!(tx1.is_inherent()); + assert_eq!(tx1.signature, None); }); } @@ -766,7 +758,7 @@ mod tests { let _tx2 = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); - assert!(tx1.is_inherent()); + assert_eq!(tx1.signature, None); }); } @@ -798,7 +790,7 @@ mod tests { let tx1 = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx1 = Extrinsic::decode(&mut &*tx1).unwrap(); - assert!(tx1.is_inherent()); + assert_eq!(tx1.signature, None); }); } } diff --git a/substrate/frame/system/src/weights.rs b/substrate/frame/system/src/weights.rs index bd64bbf3763..41807dea1c5 100644 --- a/substrate/frame/system/src/weights.rs +++ b/substrate/frame/system/src/weights.rs @@ -15,31 +15,30 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `frame_system` +//! Autogenerated weights for frame_system //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-s7kdgajz-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// target/production/substrate // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=frame_system -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/system/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=frame-system +// --chain=dev +// --header=./HEADER-APACHE2 +// --output=./frame/system/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +48,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `frame_system`. +/// Weight functions needed for frame_system. pub trait WeightInfo { fn remark(b: u32, ) -> Weight; fn remark_with_event(b: u32, ) -> Weight; @@ -62,7 +61,7 @@ pub trait WeightInfo { fn apply_authorized_upgrade() -> Weight; } -/// Weights for `frame_system` using the Substrate node and recommended hardware. +/// Weights for frame_system using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { /// The range of component `b` is `[0, 3932160]`. @@ -70,86 +69,84 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_130_000 picoseconds. - Weight::from_parts(2_976_430, 0) + // Minimum execution time: 2_004_000 picoseconds. + Weight::from_parts(2_119_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(386, 0).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(390, 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: 5_690_000 picoseconds. - Weight::from_parts(15_071_416, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_387, 0).saturating_mul(b.into())) + // Minimum execution time: 8_032_000 picoseconds. + Weight::from_parts(8_097_000, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_455, 0).saturating_mul(b.into())) } - /// Storage: `System::Digest` (r:1 w:1) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a686561707061676573` (r:0 w:1) + /// Proof Skipped: unknown `0x3a686561707061676573` (r:0 w:1) fn set_heap_pages() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 3_822_000 picoseconds. - Weight::from_parts(4_099_000, 1485) + // Minimum execution time: 4_446_000 picoseconds. + Weight::from_parts(4_782_000, 1485) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) - /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:1) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a636f6465` (r:0 w:1) + /// Proof Skipped: unknown `0x3a636f6465` (r:0 w:1) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `67035` - // Minimum execution time: 81_512_045_000 picoseconds. - Weight::from_parts(82_321_281_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `1485` + // Minimum execution time: 84_000_503_000 picoseconds. + Weight::from_parts(87_586_619_000, 1485) + .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_074_000 picoseconds. - Weight::from_parts(2_137_000, 0) - // Standard Error: 879 - .saturating_add(Weight::from_parts(797_224, 0).saturating_mul(i.into())) + // Minimum execution time: 2_086_000 picoseconds. + Weight::from_parts(2_175_000, 0) + // Standard Error: 1_056 + .saturating_add(Weight::from_parts(841_511, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_122_000 picoseconds. - Weight::from_parts(2_208_000, 0) - // Standard Error: 855 - .saturating_add(Weight::from_parts(594_034, 0).saturating_mul(i.into())) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_255_000, 0) + // Standard Error: 1_425 + .saturating_add(Weight::from_parts(662_473, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `129 + p * (69 ±0)` - // Estimated: `135 + p * (70 ±0)` - // Minimum execution time: 3_992_000 picoseconds. - Weight::from_parts(4_170_000, 135) - // Standard Error: 1_377 - .saturating_add(Weight::from_parts(1_267_892, 0).saturating_mul(p.into())) + // Measured: `115 + p * (69 ±0)` + // Estimated: `128 + p * (70 ±0)` + // Minimum execution time: 4_189_000 picoseconds. + Weight::from_parts(4_270_000, 128) + // Standard Error: 2_296 + .saturating_add(Weight::from_parts(1_389_650, 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())) @@ -160,116 +157,114 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_872_000 picoseconds. - Weight::from_parts(9_513_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 33_027_000 picoseconds. + Weight::from_parts(33_027_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `System::AuthorizedUpgrade` (r:1 w:1) /// Proof: `System::AuthorizedUpgrade` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) - /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) - /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) /// Storage: `System::Digest` (r:1 w:1) /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) fn apply_authorized_upgrade() -> Weight { // Proof Size summary in bytes: - // Measured: `164` - // Estimated: `67035` - // Minimum execution time: 85_037_546_000 picoseconds. - Weight::from_parts(85_819_414_000, 67035) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Measured: `22` + // Estimated: `1518` + // Minimum execution time: 118_101_992_000 picoseconds. + Weight::from_parts(118_101_992_000, 0) + .saturating_add(Weight::from_parts(0, 1518)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { /// The range of component `b` is `[0, 3932160]`. fn remark(b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_130_000 picoseconds. - Weight::from_parts(2_976_430, 0) + // Minimum execution time: 2_004_000 picoseconds. + Weight::from_parts(2_119_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(386, 0).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(390, 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: 5_690_000 picoseconds. - Weight::from_parts(15_071_416, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_387, 0).saturating_mul(b.into())) + // Minimum execution time: 8_032_000 picoseconds. + Weight::from_parts(8_097_000, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_455, 0).saturating_mul(b.into())) } - /// Storage: `System::Digest` (r:1 w:1) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a686561707061676573` (r:0 w:1) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a686561707061676573` (r:0 w:1) + /// Proof Skipped: unknown `0x3a686561707061676573` (r:0 w:1) fn set_heap_pages() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 3_822_000 picoseconds. - Weight::from_parts(4_099_000, 1485) + // Minimum execution time: 4_446_000 picoseconds. + Weight::from_parts(4_782_000, 1485) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) - /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:1) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) - /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: unknown `0x3a636f6465` (r:0 w:1) + /// Proof Skipped: unknown `0x3a636f6465` (r:0 w:1) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `67035` - // Minimum execution time: 81_512_045_000 picoseconds. - Weight::from_parts(82_321_281_000, 67035) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `1485` + // Minimum execution time: 84_000_503_000 picoseconds. + Weight::from_parts(87_586_619_000, 1485) + .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_074_000 picoseconds. - Weight::from_parts(2_137_000, 0) - // Standard Error: 879 - .saturating_add(Weight::from_parts(797_224, 0).saturating_mul(i.into())) + // Minimum execution time: 2_086_000 picoseconds. + Weight::from_parts(2_175_000, 0) + // Standard Error: 1_056 + .saturating_add(Weight::from_parts(841_511, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_122_000 picoseconds. - Weight::from_parts(2_208_000, 0) - // Standard Error: 855 - .saturating_add(Weight::from_parts(594_034, 0).saturating_mul(i.into())) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_255_000, 0) + // Standard Error: 1_425 + .saturating_add(Weight::from_parts(662_473, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) } - /// Storage: `Skipped::Metadata` (r:0 w:0) - /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Skipped Metadata (r:0 w:0) + /// Proof Skipped: Skipped Metadata (max_values: None, max_size: None, mode: Measured) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `129 + p * (69 ±0)` - // Estimated: `135 + p * (70 ±0)` - // Minimum execution time: 3_992_000 picoseconds. - Weight::from_parts(4_170_000, 135) - // Standard Error: 1_377 - .saturating_add(Weight::from_parts(1_267_892, 0).saturating_mul(p.into())) + // Measured: `115 + p * (69 ±0)` + // Estimated: `128 + p * (70 ±0)` + // Minimum execution time: 4_189_000 picoseconds. + Weight::from_parts(4_270_000, 128) + // Standard Error: 2_296 + .saturating_add(Weight::from_parts(1_389_650, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 70).saturating_mul(p.into())) @@ -280,25 +275,25 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_872_000 picoseconds. - Weight::from_parts(9_513_000, 0) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Minimum execution time: 33_027_000 picoseconds. + Weight::from_parts(33_027_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(RocksDbWeight::get().writes(1)) } /// Storage: `System::AuthorizedUpgrade` (r:1 w:1) /// Proof: `System::AuthorizedUpgrade` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) - /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) - /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) /// Storage: `System::Digest` (r:1 w:1) /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) /// Proof: UNKNOWN KEY `0x3a636f6465` (r:0 w:1) fn apply_authorized_upgrade() -> Weight { // Proof Size summary in bytes: - // Measured: `164` - // Estimated: `67035` - // Minimum execution time: 85_037_546_000 picoseconds. - Weight::from_parts(85_819_414_000, 67035) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Measured: `22` + // Estimated: `1518` + // Minimum execution time: 118_101_992_000 picoseconds. + Weight::from_parts(118_101_992_000, 0) + .saturating_add(Weight::from_parts(0, 1518)) + .saturating_add(RocksDbWeight::get().reads(2)) + .saturating_add(RocksDbWeight::get().writes(3)) } } diff --git a/substrate/frame/timestamp/src/weights.rs b/substrate/frame/timestamp/src/weights.rs index 2df68ba0f1e..46c54473486 100644 --- a/substrate/frame/timestamp/src/weights.rs +++ b/substrate/frame/timestamp/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_timestamp` +//! Autogenerated weights for pallet_timestamp //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/timestamp/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/timestamp/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,57 +50,57 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_timestamp`. +/// Weight functions needed for pallet_timestamp. pub trait WeightInfo { fn set() -> Weight; fn on_finalize() -> Weight; } -/// Weights for `pallet_timestamp` using the Substrate node and recommended hardware. +/// Weights for pallet_timestamp using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Timestamp::Now` (r:1 w:1) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Babe::CurrentSlot` (r:1 w:0) - /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Timestamp Now (r:1 w:1) + /// Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Babe CurrentSlot (r:1 w:0) + /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn set() -> Weight { // Proof Size summary in bytes: - // Measured: `345` + // Measured: `312` // Estimated: `1493` - // Minimum execution time: 8_417_000 picoseconds. - Weight::from_parts(8_932_000, 1493) + // Minimum execution time: 9_857_000 picoseconds. + Weight::from_parts(10_492_000, 1493) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn on_finalize() -> Weight { // Proof Size summary in bytes: - // Measured: `194` + // Measured: `161` // Estimated: `0` - // Minimum execution time: 3_911_000 picoseconds. - Weight::from_parts(4_092_000, 0) + // Minimum execution time: 4_175_000 picoseconds. + Weight::from_parts(4_334_000, 0) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Timestamp::Now` (r:1 w:1) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Babe::CurrentSlot` (r:1 w:0) - /// Proof: `Babe::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: Timestamp Now (r:1 w:1) + /// Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: Babe CurrentSlot (r:1 w:0) + /// Proof: Babe CurrentSlot (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) fn set() -> Weight { // Proof Size summary in bytes: - // Measured: `345` + // Measured: `312` // Estimated: `1493` - // Minimum execution time: 8_417_000 picoseconds. - Weight::from_parts(8_932_000, 1493) + // Minimum execution time: 9_857_000 picoseconds. + Weight::from_parts(10_492_000, 1493) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn on_finalize() -> Weight { // Proof Size summary in bytes: - // Measured: `194` + // Measured: `161` // Estimated: `0` - // Minimum execution time: 3_911_000 picoseconds. - Weight::from_parts(4_092_000, 0) + // Minimum execution time: 4_175_000 picoseconds. + Weight::from_parts(4_334_000, 0) } } diff --git a/substrate/frame/tips/src/weights.rs b/substrate/frame/tips/src/weights.rs index dbe1ed246ff..ec622866715 100644 --- a/substrate/frame/tips/src/weights.rs +++ b/substrate/frame/tips/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_tips` +//! Autogenerated weights for pallet_tips //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/tips/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/tips/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_tips`. +/// Weight functions needed for pallet_tips. pub trait WeightInfo { fn report_awesome(r: u32, ) -> Weight; fn retract_tip() -> Weight; @@ -59,220 +60,220 @@ pub trait WeightInfo { fn slash_tip(t: u32, ) -> Weight; } -/// Weights for `pallet_tips` using the Substrate node and recommended hardware. +/// Weights for pallet_tips using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Tips::Reasons` (r:1 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Tips Reasons (r:1 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) /// The range of component `r` is `[0, 300]`. fn report_awesome(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `3469` - // Minimum execution time: 25_145_000 picoseconds. - Weight::from_parts(26_085_800, 3469) - // Standard Error: 216 - .saturating_add(Weight::from_parts(5_121, 0).saturating_mul(r.into())) + // Minimum execution time: 29_576_000 picoseconds. + Weight::from_parts(30_722_650, 3469) + // Standard Error: 192 + .saturating_add(Weight::from_parts(2_601, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Reasons` (r:0 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: Tips Reasons (r:0 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) fn retract_tip() -> Weight { // Proof Size summary in bytes: // Measured: `221` // Estimated: `3686` - // Minimum execution time: 25_302_000 picoseconds. - Weight::from_parts(26_229_000, 3686) + // Minimum execution time: 28_522_000 picoseconds. + Weight::from_parts(29_323_000, 3686) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Reasons` (r:1 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Tips` (r:0 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Tips Reasons (r:1 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: Tips Tips (r:0 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) /// The range of component `r` is `[0, 300]`. /// The range of component `t` is `[1, 13]`. fn tip_new(r: u32, t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `526 + t * (64 ±0)` // Estimated: `3991 + t * (64 ±0)` - // Minimum execution time: 16_600_000 picoseconds. - Weight::from_parts(17_071_638, 3991) - // Standard Error: 131 - .saturating_add(Weight::from_parts(1_138, 0).saturating_mul(r.into())) - // Standard Error: 3_125 - .saturating_add(Weight::from_parts(82_996, 0).saturating_mul(t.into())) + // Minimum execution time: 19_650_000 picoseconds. + Weight::from_parts(19_837_982, 3991) + // Standard Error: 151 + .saturating_add(Weight::from_parts(1_746, 0).saturating_mul(r.into())) + // Standard Error: 3_588 + .saturating_add(Weight::from_parts(102_359, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(t.into())) } - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) /// The range of component `t` is `[1, 13]`. fn tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `747 + t * (112 ±0)` // Estimated: `4212 + t * (112 ±0)` - // Minimum execution time: 13_972_000 picoseconds. - Weight::from_parts(14_269_356, 4212) - // Standard Error: 4_695 - .saturating_add(Weight::from_parts(205_433, 0).saturating_mul(t.into())) + // Minimum execution time: 15_641_000 picoseconds. + Weight::from_parts(15_745_460, 4212) + // Standard Error: 5_106 + .saturating_add(Weight::from_parts(229_475, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(t.into())) } - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Tips::Reasons` (r:0 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Tips Reasons (r:0 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) /// The range of component `t` is `[1, 13]`. fn close_tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `786 + t * (112 ±0)` // Estimated: `4242 + t * (112 ±0)` - // Minimum execution time: 51_878_000 picoseconds. - Weight::from_parts(54_513_477, 4242) - // Standard Error: 12_281 - .saturating_add(Weight::from_parts(126_605, 0).saturating_mul(t.into())) + // Minimum execution time: 62_059_000 picoseconds. + Weight::from_parts(64_604_554, 4242) + // Standard Error: 11_818 + .saturating_add(Weight::from_parts(116_297, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(t.into())) } - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Reasons` (r:0 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: Tips Reasons (r:0 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) /// The range of component `t` is `[1, 13]`. fn slash_tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `269` // Estimated: `3734` - // Minimum execution time: 11_800_000 picoseconds. - Weight::from_parts(12_520_984, 3734) - // Standard Error: 2_360 - .saturating_add(Weight::from_parts(28_777, 0).saturating_mul(t.into())) + // Minimum execution time: 14_133_000 picoseconds. + Weight::from_parts(14_957_547, 3734) + // Standard Error: 2_765 + .saturating_add(Weight::from_parts(22_138, 0).saturating_mul(t.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Tips::Reasons` (r:1 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Tips Reasons (r:1 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) /// The range of component `r` is `[0, 300]`. fn report_awesome(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `4` // Estimated: `3469` - // Minimum execution time: 25_145_000 picoseconds. - Weight::from_parts(26_085_800, 3469) - // Standard Error: 216 - .saturating_add(Weight::from_parts(5_121, 0).saturating_mul(r.into())) + // Minimum execution time: 29_576_000 picoseconds. + Weight::from_parts(30_722_650, 3469) + // Standard Error: 192 + .saturating_add(Weight::from_parts(2_601, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Reasons` (r:0 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: Tips Reasons (r:0 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) fn retract_tip() -> Weight { // Proof Size summary in bytes: // Measured: `221` // Estimated: `3686` - // Minimum execution time: 25_302_000 picoseconds. - Weight::from_parts(26_229_000, 3686) + // Minimum execution time: 28_522_000 picoseconds. + Weight::from_parts(29_323_000, 3686) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Reasons` (r:1 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Tips` (r:0 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Tips Reasons (r:1 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) + /// Storage: Tips Tips (r:0 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) /// The range of component `r` is `[0, 300]`. /// The range of component `t` is `[1, 13]`. fn tip_new(r: u32, t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `526 + t * (64 ±0)` // Estimated: `3991 + t * (64 ±0)` - // Minimum execution time: 16_600_000 picoseconds. - Weight::from_parts(17_071_638, 3991) - // Standard Error: 131 - .saturating_add(Weight::from_parts(1_138, 0).saturating_mul(r.into())) - // Standard Error: 3_125 - .saturating_add(Weight::from_parts(82_996, 0).saturating_mul(t.into())) + // Minimum execution time: 19_650_000 picoseconds. + Weight::from_parts(19_837_982, 3991) + // Standard Error: 151 + .saturating_add(Weight::from_parts(1_746, 0).saturating_mul(r.into())) + // Standard Error: 3_588 + .saturating_add(Weight::from_parts(102_359, 0).saturating_mul(t.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 64).saturating_mul(t.into())) } - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) /// The range of component `t` is `[1, 13]`. fn tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `747 + t * (112 ±0)` // Estimated: `4212 + t * (112 ±0)` - // Minimum execution time: 13_972_000 picoseconds. - Weight::from_parts(14_269_356, 4212) - // Standard Error: 4_695 - .saturating_add(Weight::from_parts(205_433, 0).saturating_mul(t.into())) + // Minimum execution time: 15_641_000 picoseconds. + Weight::from_parts(15_745_460, 4212) + // Standard Error: 5_106 + .saturating_add(Weight::from_parts(229_475, 0).saturating_mul(t.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(t.into())) } - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Elections::Members` (r:1 w:0) - /// Proof: `Elections::Members` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Tips::Reasons` (r:0 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: Elections Members (r:1 w:0) + /// Proof Skipped: Elections Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Tips Reasons (r:0 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) /// The range of component `t` is `[1, 13]`. fn close_tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `786 + t * (112 ±0)` // Estimated: `4242 + t * (112 ±0)` - // Minimum execution time: 51_878_000 picoseconds. - Weight::from_parts(54_513_477, 4242) - // Standard Error: 12_281 - .saturating_add(Weight::from_parts(126_605, 0).saturating_mul(t.into())) + // Minimum execution time: 62_059_000 picoseconds. + Weight::from_parts(64_604_554, 4242) + // Standard Error: 11_818 + .saturating_add(Weight::from_parts(116_297, 0).saturating_mul(t.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(t.into())) } - /// Storage: `Tips::Tips` (r:1 w:1) - /// Proof: `Tips::Tips` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `Tips::Reasons` (r:0 w:1) - /// Proof: `Tips::Reasons` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: Tips Tips (r:1 w:1) + /// Proof Skipped: Tips Tips (max_values: None, max_size: None, mode: Measured) + /// Storage: Tips Reasons (r:0 w:1) + /// Proof Skipped: Tips Reasons (max_values: None, max_size: None, mode: Measured) /// The range of component `t` is `[1, 13]`. fn slash_tip(t: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `269` // Estimated: `3734` - // Minimum execution time: 11_800_000 picoseconds. - Weight::from_parts(12_520_984, 3734) - // Standard Error: 2_360 - .saturating_add(Weight::from_parts(28_777, 0).saturating_mul(t.into())) + // Minimum execution time: 14_133_000 picoseconds. + Weight::from_parts(14_957_547, 3734) + // Standard Error: 2_765 + .saturating_add(Weight::from_parts(22_138, 0).saturating_mul(t.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate/frame/transaction-payment/Cargo.toml b/substrate/frame/transaction-payment/Cargo.toml index 66e0bef1436..275e1c01f92 100644 --- a/substrate/frame/transaction-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/Cargo.toml @@ -21,7 +21,6 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features = ] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true, default-features = true } -frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } frame-support = { path = "../support", default-features = false } frame-system = { path = "../system", default-features = false } sp-core = { path = "../../primitives/core", default-features = false } @@ -37,7 +36,6 @@ pallet-balances = { path = "../balances" } default = ["std"] std = [ "codec/std", - "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "pallet-balances/std", @@ -48,13 +46,6 @@ std = [ "sp-runtime/std", "sp-std/std", ] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml b/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml index 528f29e8e4a..7640cc815e5 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/Cargo.toml @@ -19,7 +19,6 @@ targets = ["x86_64-unknown-linux-gnu"] # Substrate dependencies sp-runtime = { path = "../../../primitives/runtime", default-features = false } sp-std = { path = "../../../primitives/std", default-features = false } -frame-benchmarking = { path = "../../benchmarking", default-features = false, optional = true } frame-support = { path = "../../support", default-features = false } frame-system = { path = "../../system", default-features = false } pallet-asset-conversion = { path = "../../asset-conversion", default-features = false } @@ -38,7 +37,6 @@ pallet-balances = { path = "../../balances" } default = ["std"] std = [ "codec/std", - "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "pallet-asset-conversion/std", @@ -52,16 +50,6 @@ std = [ "sp-std/std", "sp-storage/std", ] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-asset-conversion/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/README.md b/substrate/frame/transaction-payment/asset-conversion-tx-payment/README.md index fcd1527526e..eccba773673 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/README.md +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/README.md @@ -16,6 +16,6 @@ asset. ### Integration This pallet wraps FRAME's transaction payment pallet and functions as a replacement. This means you should include both pallets in your `construct_runtime` macro, but only include this -pallet's [`TransactionExtension`] ([`ChargeAssetTxPayment`]). +pallet's [`SignedExtension`] ([`ChargeAssetTxPayment`]). License: Apache-2.0 diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/benchmarking.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/benchmarking.rs deleted file mode 100644 index 0bffb991e4a..00000000000 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/benchmarking.rs +++ /dev/null @@ -1,125 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -//! Benchmarks for Asset Conversion Tx Payment Pallet's transaction extension - -use super::*; -use crate::Pallet; -use frame_benchmarking::v2::*; -use frame_support::{ - dispatch::{DispatchInfo, PostDispatchInfo}, - pallet_prelude::*, -}; -use frame_system::RawOrigin; -use sp_runtime::traits::{AsSystemOriginSigner, DispatchTransaction, Dispatchable}; - -#[benchmarks(where - T::RuntimeCall: Dispatchable, - AssetBalanceOf: Send + Sync, - BalanceOf: Send - + Sync - + From - + Into> - + Into> - + From>, - ChargeAssetIdOf: Send + Sync + Default, - ::RuntimeOrigin: AsSystemOriginSigner + Clone, -)] -mod benchmarks { - use super::*; - - #[benchmark] - fn charge_asset_tx_payment_zero() { - let caller: T::AccountId = whitelisted_caller(); - let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(0u64.into(), None); - let inner = frame_system::Call::remark { remark: vec![] }; - let call = T::RuntimeCall::from(inner); - let info = DispatchInfo { - weight: Weight::zero(), - class: DispatchClass::Normal, - pays_fee: Pays::No, - }; - let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Pays::No }; - #[block] - { - assert!(ext - .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(post_info)) - .unwrap() - .is_ok()); - } - } - - #[benchmark] - fn charge_asset_tx_payment_native() { - let caller: T::AccountId = whitelisted_caller(); - let (fun_asset_id, _) = ::BenchmarkHelper::create_asset_id_parameter(1); - ::BenchmarkHelper::setup_balances_and_pool(fun_asset_id, caller.clone()); - let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(10u64.into(), None); - let inner = frame_system::Call::remark { remark: vec![] }; - let call = T::RuntimeCall::from(inner); - let info = DispatchInfo { - weight: Weight::from_parts(10, 0), - class: DispatchClass::Operational, - pays_fee: Pays::Yes, - }; - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(10, 0)), - pays_fee: Pays::Yes, - }; - - #[block] - { - assert!(ext - .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(post_info)) - .unwrap() - .is_ok()); - } - } - - #[benchmark] - fn charge_asset_tx_payment_asset() { - let caller: T::AccountId = whitelisted_caller(); - let (fun_asset_id, asset_id) = ::BenchmarkHelper::create_asset_id_parameter(1); - ::BenchmarkHelper::setup_balances_and_pool(fun_asset_id, caller.clone()); - - let tip = 10u64.into(); - let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(tip, Some(asset_id)); - let inner = frame_system::Call::remark { remark: vec![] }; - let call = T::RuntimeCall::from(inner); - let info = DispatchInfo { - weight: Weight::from_parts(10, 0), - class: DispatchClass::Operational, - pays_fee: Pays::Yes, - }; - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(10, 0)), - pays_fee: Pays::Yes, - }; - - #[block] - { - assert!(ext - .test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 0, |_| Ok( - post_info - )) - .unwrap() - .is_ok()); - } - } - - impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime); -} diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs index 8ef7c2ba38e..ed0ed56e6e0 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs @@ -20,8 +20,8 @@ //! //! ## Overview //! -//! This pallet provides a `TransactionExtension` with an optional `AssetId` that specifies the -//! asset to be used for payment (defaulting to the native token on `None`). It expects an +//! This pallet provides a `SignedExtension` with an optional `AssetId` that specifies the asset +//! to be used for payment (defaulting to the native token on `None`). It expects an //! [`OnChargeAssetTransaction`] implementation analogous to [`pallet-transaction-payment`]. The //! included [`AssetConversionAdapter`] (implementing [`OnChargeAssetTransaction`]) determines the //! fee amount by converting the fee calculated by [`pallet-transaction-payment`] in the native @@ -31,7 +31,7 @@ //! //! This pallet does not have any dispatchable calls or storage. It wraps FRAME's Transaction //! Payment pallet and functions as a replacement. This means you should include both pallets in -//! your `construct_runtime` macro, but only include this pallet's [`TransactionExtension`] +//! your `construct_runtime` macro, but only include this pallet's [`SignedExtension`] //! ([`ChargeAssetTxPayment`]). //! //! ## Terminology @@ -53,29 +53,23 @@ use frame_support::{ }, DefaultNoBound, }; -use pallet_transaction_payment::{ChargeTransactionPayment, OnChargeTransaction}; +use pallet_transaction_payment::OnChargeTransaction; use scale_info::TypeInfo; use sp_runtime::{ - traits::{ - AsSystemOriginSigner, DispatchInfoOf, Dispatchable, PostDispatchInfoOf, - TransactionExtension, TransactionExtensionBase, ValidateResult, Zero, + traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension, Zero}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, }, - transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction}, }; #[cfg(test)] mod mock; #[cfg(test)] mod tests; -pub mod weights; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; mod payment; -use frame_support::{pallet_prelude::Weight, traits::tokens::AssetId}; +use frame_support::traits::tokens::AssetId; pub use payment::*; -pub use weights::WeightInfo; /// Type aliases used for interaction with `OnChargeTransaction`. pub(crate) type OnChargeTransactionOf = @@ -131,30 +125,11 @@ pub mod pallet { type Fungibles: Balanced; /// The actual transaction charging logic that charges the fees. type OnChargeAssetTransaction: OnChargeAssetTransaction; - /// The weight information of this pallet. - type WeightInfo: WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - /// Benchmark helper - type BenchmarkHelper: BenchmarkHelperTrait< - Self::AccountId, - <::Fungibles as Inspect>::AssetId, - <::OnChargeAssetTransaction as OnChargeAssetTransaction>::AssetId, - >; } #[pallet::pallet] pub struct Pallet(_); - #[cfg(feature = "runtime-benchmarks")] - /// Helper trait to benchmark the `ChargeAssetTxPayment` transaction extension. - pub trait BenchmarkHelperTrait { - /// Returns the `AssetId` to be used in the liquidity pool by the benchmarking code. - fn create_asset_id_parameter(id: u32) -> (FunAssetIdParameter, AssetIdParameter); - /// Create a liquidity pool for a given asset and sufficiently endow accounts to benchmark - /// the extension. - fn setup_balances_and_pool(asset_id: FunAssetIdParameter, account: AccountId); - } - #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -204,8 +179,9 @@ where who: &T::AccountId, call: &T::RuntimeCall, info: &DispatchInfoOf, - fee: BalanceOf, + len: usize, ) -> Result<(BalanceOf, InitialPayment), TransactionValidityError> { + let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); debug_assert!(self.tip <= fee, "tip should be included in the computed fee"); if fee.is_zero() { Ok((fee, InitialPayment::Nothing)) @@ -249,30 +225,7 @@ impl sp_std::fmt::Debug for ChargeAssetTxPayment { } } -impl TransactionExtensionBase for ChargeAssetTxPayment -where - AssetBalanceOf: Send + Sync, - BalanceOf: Send - + Sync - + From - + Into> - + Into> - + From>, - ChargeAssetIdOf: Send + Sync, -{ - const IDENTIFIER: &'static str = "ChargeAssetTxPayment"; - type Implicit = (); - - fn weight(&self) -> Weight { - if self.asset_id.is_some() { - ::WeightInfo::charge_asset_tx_payment_asset() - } else { - ::WeightInfo::charge_asset_tx_payment_native() - } - } -} - -impl TransactionExtension for ChargeAssetTxPayment +impl SignedExtension for ChargeAssetTxPayment where T::RuntimeCall: Dispatchable, AssetBalanceOf: Send + Sync, @@ -283,123 +236,111 @@ where + Into> + From>, ChargeAssetIdOf: Send + Sync, - ::RuntimeOrigin: AsSystemOriginSigner + Clone, { - type Val = ( - // tip - BalanceOf, - // who paid the fee - T::AccountId, - // transaction fee - BalanceOf, - ); + const IDENTIFIER: &'static str = "ChargeAssetTxPayment"; + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = (); type Pre = ( // tip BalanceOf, // who paid the fee - T::AccountId, + Self::AccountId, // imbalance resulting from withdrawing the fee InitialPayment, // asset_id for the transaction payment Option>, ); + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + fn validate( &self, - origin: ::RuntimeOrigin, - _call: &T::RuntimeCall, - info: &DispatchInfoOf, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; - // Non-mutating call of `compute_fee` to calculate the fee used in the transaction priority. - let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); + ) -> TransactionValidity { + use pallet_transaction_payment::ChargeTransactionPayment; + let (fee, _) = self.withdraw_fee(who, call, info, len)?; let priority = ChargeTransactionPayment::::get_priority(info, len, self.tip, fee); - let validity = ValidTransaction { priority, ..Default::default() }; - let val = (self.tip, who.clone(), fee); - Ok((validity, val, origin)) + Ok(ValidTransaction { priority, ..Default::default() }) } - fn prepare( + fn pre_dispatch( self, - val: Self::Val, - _origin: &::RuntimeOrigin, - call: &T::RuntimeCall, - info: &DispatchInfoOf, - _len: usize, - _context: &Context, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, ) -> Result { - let (tip, who, fee) = val; - // Mutating call of `withdraw_fee` to actually charge for the transaction. - let (_fee, initial_payment) = self.withdraw_fee(&who, call, info, fee)?; - Ok((tip, who, initial_payment, self.asset_id.clone())) + let (_fee, initial_payment) = self.withdraw_fee(who, call, info, len)?; + Ok((self.tip, who.clone(), initial_payment, self.asset_id)) } fn post_dispatch( - pre: Self::Pre, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, - _context: &Context, ) -> Result<(), TransactionValidityError> { - let (tip, who, initial_payment, asset_id) = pre; - match initial_payment { - InitialPayment::Native(already_withdrawn) => { - debug_assert!( - asset_id.is_none(), - "For that payment type the `asset_id` should be None" - ); - pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( - (tip, who, already_withdrawn), - info, - post_info, - len, - result, - &(), - )?; - }, - InitialPayment::Asset(already_withdrawn) => { - debug_assert!( - asset_id.is_some(), - "For that payment type the `asset_id` should be set" - ); - let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( - len as u32, info, post_info, tip, - ); - - if let Some(asset_id) = asset_id { - let (used_for_fee, received_exchanged, asset_consumed) = already_withdrawn; - let converted_fee = T::OnChargeAssetTransaction::correct_and_deposit_fee( - &who, + if let Some((tip, who, initial_payment, asset_id)) = pre { + match initial_payment { + InitialPayment::Native(already_withdrawn) => { + debug_assert!( + asset_id.is_none(), + "For that payment type the `asset_id` should be None" + ); + pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( + Some((tip, who, already_withdrawn)), info, post_info, - actual_fee.into(), - tip.into(), - used_for_fee.into(), - received_exchanged.into(), - asset_id.clone(), - asset_consumed.into(), + len, + result, )?; + }, + InitialPayment::Asset(already_withdrawn) => { + debug_assert!( + asset_id.is_some(), + "For that payment type the `asset_id` should be set" + ); + let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( + len as u32, info, post_info, tip, + ); + + if let Some(asset_id) = asset_id { + let (used_for_fee, received_exchanged, asset_consumed) = already_withdrawn; + let converted_fee = T::OnChargeAssetTransaction::correct_and_deposit_fee( + &who, + info, + post_info, + actual_fee.into(), + tip.into(), + used_for_fee.into(), + received_exchanged.into(), + asset_id.clone(), + asset_consumed.into(), + )?; - Pallet::::deposit_event(Event::::AssetTxFeePaid { - who, - actual_fee: converted_fee, - tip, - asset_id, - }); - } - }, - InitialPayment::Nothing => { - // `actual_fee` should be zero here for any signed extrinsic. It would be - // non-zero here in case of unsigned extrinsics as they don't pay fees but - // `compute_actual_fee` is not aware of them. In both cases it's fine to just - // move ahead without adjusting the fee, though, so we do nothing. - debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); - }, + Pallet::::deposit_event(Event::::AssetTxFeePaid { + who, + actual_fee: converted_fee, + tip, + asset_id, + }); + } + }, + InitialPayment::Nothing => { + // `actual_fee` should be zero here for any signed extrinsic. It would be + // non-zero here in case of unsigned extrinsics as they don't pay fees but + // `compute_actual_fee` is not aware of them. In both cases it's fine to just + // move ahead without adjusting the fee, though, so we do nothing. + debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); + }, + } } Ok(()) diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs index 853753d41cf..c8bf2eb8f44 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs @@ -168,12 +168,12 @@ impl OnUnbalanced> for DealWithFees } } -#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter; type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; + type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; } @@ -269,72 +269,4 @@ impl Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = Assets; type OnChargeAssetTransaction = AssetConversionAdapter; - type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = Helper; -} - -#[cfg(feature = "runtime-benchmarks")] -pub fn new_test_ext() -> sp_io::TestExternalities { - let base_weight = 5; - let balance_factor = 100; - crate::tests::ExtBuilder::default() - .balance_factor(balance_factor) - .base_weight(Weight::from_parts(base_weight, 0)) - .build() -} - -#[cfg(feature = "runtime-benchmarks")] -pub struct Helper; - -#[cfg(feature = "runtime-benchmarks")] -impl BenchmarkHelperTrait for Helper { - fn create_asset_id_parameter(id: u32) -> (u32, u32) { - (id, id) - } - - fn setup_balances_and_pool(asset_id: u32, account: u64) { - use frame_support::{assert_ok, traits::fungibles::Mutate}; - use sp_runtime::traits::StaticLookup; - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - 42, /* owner */ - true, /* is_sufficient */ - 1, - )); - - let lp_provider = 12; - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), lp_provider, u64::MAX / 2)); - let lp_provider_account = ::Lookup::unlookup(lp_provider); - assert_ok!(Assets::mint_into(asset_id.into(), &lp_provider_account, u64::MAX / 2)); - - let token_1 = Box::new(NativeOrWithId::Native); - let token_2 = Box::new(NativeOrWithId::WithId(asset_id)); - assert_ok!(AssetConversion::create_pool( - RuntimeOrigin::signed(lp_provider), - token_1.clone(), - token_2.clone() - )); - - assert_ok!(AssetConversion::add_liquidity( - RuntimeOrigin::signed(lp_provider), - token_1, - token_2, - (u32::MAX / 8).into(), // 1 desired - u32::MAX.into(), // 2 desired - 1, // 1 min - 1, // 2 min - lp_provider_account, - )); - - use frame_support::traits::Currency; - let _ = Balances::deposit_creating(&account, u32::MAX.into()); - - let beneficiary = ::Lookup::unlookup(account); - let balance = 1000; - - assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); - assert_eq!(Assets::balance(asset_id, account), balance); - } } diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/tests.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/tests.rs index 619077c0a5e..62faed269d3 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/tests.rs @@ -28,10 +28,7 @@ use frame_support::{ use frame_system as system; use mock::{ExtrinsicBaseWeight, *}; use pallet_balances::Call as BalancesCall; -use sp_runtime::{ - traits::{DispatchTransaction, StaticLookup}, - BuildStorage, -}; +use sp_runtime::{traits::StaticLookup, BuildStorage}; const CALL: &::RuntimeCall = &RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 2, value: 69 }); @@ -163,35 +160,33 @@ fn transaction_payment_in_native_possible() { .build() .execute_with(|| { let len = 10; - let (pre, _) = ChargeAssetTxPayment::::from(0, None) - .validate_and_prepare(Some(1).into(), CALL, &info_from_weight(WEIGHT_5), len) + let pre = ChargeAssetTxPayment::::from(0, None) + .pre_dispatch(&1, CALL, &info_from_weight(WEIGHT_5), len) .unwrap(); let initial_balance = 10 * balance_factor; assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(WEIGHT_5), &default_post_info(), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); - let (pre, _) = ChargeAssetTxPayment::::from(5 /* tipped */, None) - .validate_and_prepare(Some(2).into(), CALL, &info_from_weight(WEIGHT_100), len) + let pre = ChargeAssetTxPayment::::from(5 /* tipped */, None) + .pre_dispatch(&2, CALL, &info_from_weight(WEIGHT_100), len) .unwrap(); let initial_balance_for_2 = 20 * balance_factor; assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 100 - 5); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(WEIGHT_100), &post_info_from_weight(WEIGHT_50), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 50 - 5); }); @@ -242,8 +237,8 @@ fn transaction_payment_in_asset_possible() { let fee_in_asset = input_quote.unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_5), len) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(WEIGHT_5), len) .unwrap(); // assert that native balance is not used assert_eq!(Balances::free_balance(caller), 10 * balance_factor); @@ -252,12 +247,11 @@ fn transaction_payment_in_asset_possible() { assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(WEIGHT_5), // estimated tx weight &default_post_info(), // weight actually used == estimated len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); @@ -295,8 +289,12 @@ fn transaction_payment_in_asset_fails_if_no_pool_for_that_asset() { assert_eq!(Assets::balance(asset_id, caller), balance); let len = 10; - let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_5), len); + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)).pre_dispatch( + &caller, + CALL, + &info_from_weight(WEIGHT_5), + len, + ); // As there is no pool in the dex set up for this asset, conversion should fail. assert!(pre.is_err()); @@ -346,8 +344,8 @@ fn transaction_payment_without_fee() { assert_eq!(input_quote, Some(201)); let fee_in_asset = input_quote.unwrap(); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_5), len) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(WEIGHT_5), len) .unwrap(); // assert that native balance is not used @@ -365,12 +363,11 @@ fn transaction_payment_without_fee() { assert_eq!(refund, 199); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(WEIGHT_5), &post_info_from_pays(Pays::No), len, - &Ok(()), - &() + &Ok(()) )); // caller should get refunded @@ -422,8 +419,8 @@ fn asset_transaction_payment_with_tip_and_refund() { assert_eq!(input_quote, Some(1206)); let fee_in_asset = input_quote.unwrap(); - let (pre, _) = ChargeAssetTxPayment::::from(tip, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_100), len) + let pre = ChargeAssetTxPayment::::from(tip, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(WEIGHT_100), len) .unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); @@ -438,12 +435,11 @@ fn asset_transaction_payment_with_tip_and_refund() { .unwrap(); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(WEIGHT_100), &post_info_from_weight(WEIGHT_50), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(TipUnbalancedAmount::get(), tip); @@ -504,8 +500,8 @@ fn payment_from_account_with_only_assets() { .unwrap(); assert_eq!(fee_in_asset, 301); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_weight(WEIGHT_5), len) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(WEIGHT_5), len) .unwrap(); assert_eq!(Balances::free_balance(caller), ed); // check that fee was charged in the given asset @@ -520,12 +516,11 @@ fn payment_from_account_with_only_assets() { .unwrap(); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(WEIGHT_5), &default_post_info(), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset + refund); assert_eq!(Balances::free_balance(caller), 0); @@ -570,19 +565,18 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() { // there will be no conversion when the fee is zero { - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_pays(Pays::No), len) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) .unwrap(); // `Pays::No` implies there are no fees assert_eq!(Assets::balance(asset_id, caller), balance); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_pays(Pays::No), &post_info_from_pays(Pays::No), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance); } @@ -597,23 +591,17 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() { ) .unwrap(); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare( - Some(caller).into(), - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len, - ) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) .unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(Weight::from_parts(weight, 0)), &default_post_info(), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance - fee_in_asset); }); @@ -653,8 +641,8 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { // calculated fee is greater than 0 assert!(fee > 0); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_pays(Pays::No), len) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) .unwrap(); // `Pays::No` implies no pre-dispatch fees @@ -670,12 +658,62 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the // initial fee) assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_pays(Pays::No), &post_info_from_pays(Pays::Yes), len, - &Ok(()), - &() + &Ok(()) + )); + assert_eq!(Assets::balance(asset_id, caller), balance); + }); +} + +#[test] +fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() { + let base_weight = 1; + ExtBuilder::default() + .balance_factor(100) + .base_weight(Weight::from_parts(base_weight, 0)) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 100; + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 333; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 1000; + + assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + + let weight = 1; + let len = 1; + ChargeAssetTxPayment::::pre_dispatch_unsigned( + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len, + ) + .unwrap(); + + assert_eq!(Assets::balance(asset_id, caller), balance); + + // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the + // initial fee) + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + None, + &info_from_weight(Weight::from_parts(weight, 0)), + &post_info_from_pays(Pays::Yes), + len, + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance); }); diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs deleted file mode 100644 index f95e49f8073..00000000000 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs +++ /dev/null @@ -1,150 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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_asset_conversion_tx_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` - -// Executed Command: -// ./target/production/substrate-node -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_asset_conversion_tx_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for `pallet_asset_conversion_tx_payment`. -pub trait WeightInfo { - fn charge_asset_tx_payment_zero() -> Weight; - fn charge_asset_tx_payment_native() -> Weight; - fn charge_asset_tx_payment_asset() -> Weight; -} - -/// Weights for `pallet_asset_conversion_tx_payment` using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - fn charge_asset_tx_payment_zero() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 628_000 picoseconds. - Weight::from_parts(694_000, 0) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_asset_tx_payment_native() -> Weight { - // Proof Size summary in bytes: - // Measured: `248` - // Estimated: `1733` - // Minimum execution time: 34_410_000 picoseconds. - Weight::from_parts(35_263_000, 1733) - .saturating_add(T::DbWeight::get().reads(3_u64)) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_asset_tx_payment_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `888` - // Estimated: `6208` - // Minimum execution time: 112_432_000 picoseconds. - Weight::from_parts(113_992_000, 6208) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) - } -} - -// For backwards compatibility and tests. -impl WeightInfo for () { - fn charge_asset_tx_payment_zero() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 628_000 picoseconds. - Weight::from_parts(694_000, 0) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_asset_tx_payment_native() -> Weight { - // Proof Size summary in bytes: - // Measured: `248` - // Estimated: `1733` - // Minimum execution time: 34_410_000 picoseconds. - Weight::from_parts(35_263_000, 1733) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_asset_tx_payment_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `888` - // Estimated: `6208` - // Minimum execution time: 112_432_000 picoseconds. - Weight::from_parts(113_992_000, 6208) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - } -} diff --git a/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml b/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml index 06d9c30792e..1da3237df08 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml +++ b/substrate/frame/transaction-payment/asset-tx-payment/Cargo.toml @@ -66,7 +66,6 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ diff --git a/substrate/frame/transaction-payment/asset-tx-payment/README.md b/substrate/frame/transaction-payment/asset-tx-payment/README.md index 933ce13b0ee..fc860347d85 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/README.md +++ b/substrate/frame/transaction-payment/asset-tx-payment/README.md @@ -16,6 +16,6 @@ asset. ### Integration This pallet wraps FRAME's transaction payment pallet and functions as a replacement. This means you should include both pallets in your `construct_runtime` macro, but only include this -pallet's [`TransactionExtension`] ([`ChargeAssetTxPayment`]). +pallet's [`SignedExtension`] ([`ChargeAssetTxPayment`]). License: Apache-2.0 diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/benchmarking.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/benchmarking.rs deleted file mode 100644 index 17e96e2b025..00000000000 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/benchmarking.rs +++ /dev/null @@ -1,123 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -//! Benchmarks for Asset Tx Payment Pallet's transaction extension - -use super::*; -use crate::Pallet; -use frame_benchmarking::v2::*; -use frame_support::{ - dispatch::{DispatchInfo, PostDispatchInfo}, - pallet_prelude::*, -}; -use frame_system::RawOrigin; -use sp_runtime::traits::{AsSystemOriginSigner, DispatchTransaction, Dispatchable}; - -#[benchmarks(where - T::RuntimeCall: Dispatchable, - AssetBalanceOf: Send + Sync, - BalanceOf: Send + Sync + From + IsType>, - ChargeAssetIdOf: Send + Sync, - ::RuntimeOrigin: AsSystemOriginSigner + Clone, - Credit: IsType>, -)] -mod benchmarks { - use super::*; - - #[benchmark] - fn charge_asset_tx_payment_zero() { - let caller: T::AccountId = whitelisted_caller(); - let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(0u32.into(), None); - let inner = frame_system::Call::remark { remark: vec![] }; - let call = T::RuntimeCall::from(inner); - let info = DispatchInfo { - weight: Weight::zero(), - class: DispatchClass::Normal, - pays_fee: Pays::No, - }; - let post_info = PostDispatchInfo { actual_weight: None, pays_fee: Pays::No }; - #[block] - { - assert!(ext - .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(post_info)) - .unwrap() - .is_ok()); - } - } - - #[benchmark] - fn charge_asset_tx_payment_native() { - let caller: T::AccountId = whitelisted_caller(); - let (fun_asset_id, _) = ::BenchmarkHelper::create_asset_id_parameter(1); - ::BenchmarkHelper::setup_balances_and_pool(fun_asset_id, caller.clone()); - let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(10u32.into(), None); - let inner = frame_system::Call::remark { remark: vec![] }; - let call = T::RuntimeCall::from(inner); - let info = DispatchInfo { - weight: Weight::from_parts(10, 0), - class: DispatchClass::Operational, - pays_fee: Pays::Yes, - }; - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(10, 0)), - pays_fee: Pays::Yes, - }; - - #[block] - { - assert!(ext - .test_run(RawOrigin::Signed(caller).into(), &call, &info, 0, |_| Ok(post_info)) - .unwrap() - .is_ok()); - } - } - - #[benchmark] - fn charge_asset_tx_payment_asset() { - let caller: T::AccountId = whitelisted_caller(); - let (fun_asset_id, asset_id) = ::BenchmarkHelper::create_asset_id_parameter(1); - ::BenchmarkHelper::setup_balances_and_pool( - fun_asset_id.clone(), - caller.clone(), - ); - let tip = 10u32.into(); - let ext: ChargeAssetTxPayment = ChargeAssetTxPayment::from(tip, Some(asset_id)); - let inner = frame_system::Call::remark { remark: vec![] }; - let call = T::RuntimeCall::from(inner); - let info = DispatchInfo { - weight: Weight::from_parts(10, 0), - class: DispatchClass::Operational, - pays_fee: Pays::Yes, - }; - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(10, 0)), - pays_fee: Pays::Yes, - }; - - #[block] - { - assert!(ext - .test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 0, |_| Ok( - post_info - )) - .unwrap() - .is_ok()); - } - } - - impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime); -} diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs index 991b5f31406..753fae747a3 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs @@ -31,7 +31,7 @@ //! This pallet wraps FRAME's transaction payment pallet and functions as a replacement. This means //! you should include both pallets in your `construct_runtime` macro, but only include this -//! pallet's [`TransactionExtension`] ([`ChargeAssetTxPayment`]). +//! pallet's [`SignedExtension`] ([`ChargeAssetTxPayment`]). #![cfg_attr(not(feature = "std"), no_std)] @@ -40,7 +40,6 @@ use sp_std::prelude::*; use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchInfo, DispatchResult, PostDispatchInfo}, - pallet_prelude::Weight, traits::{ tokens::{ fungibles::{Balanced, Credit, Inspect}, @@ -53,11 +52,10 @@ use frame_support::{ use pallet_transaction_payment::OnChargeTransaction; use scale_info::TypeInfo; use sp_runtime::{ - traits::{ - AsSystemOriginSigner, DispatchInfoOf, Dispatchable, PostDispatchInfoOf, - TransactionExtension, TransactionExtensionBase, Zero, + traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension, Zero}, + transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, }, - transaction_validity::{InvalidTransaction, TransactionValidityError, ValidTransaction}, }; #[cfg(test)] @@ -65,14 +63,8 @@ mod mock; #[cfg(test)] mod tests; -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - mod payment; -pub mod weights; - pub use payment::*; -pub use weights::WeightInfo; /// Type aliases used for interaction with `OnChargeTransaction`. pub(crate) type OnChargeTransactionOf = @@ -128,30 +120,11 @@ pub mod pallet { type Fungibles: Balanced; /// The actual transaction charging logic that charges the fees. type OnChargeAssetTransaction: OnChargeAssetTransaction; - /// The weight information of this pallet. - type WeightInfo: WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - /// Benchmark helper - type BenchmarkHelper: BenchmarkHelperTrait< - Self::AccountId, - <::Fungibles as Inspect>::AssetId, - <::OnChargeAssetTransaction as OnChargeAssetTransaction>::AssetId, - >; } #[pallet::pallet] pub struct Pallet(_); - #[cfg(feature = "runtime-benchmarks")] - /// Helper trait to benchmark the `ChargeAssetTxPayment` transaction extension. - pub trait BenchmarkHelperTrait { - /// Returns the `AssetId` to be used in the liquidity pool by the benchmarking code. - fn create_asset_id_parameter(id: u32) -> (FunAssetIdParameter, AssetIdParameter); - /// Create a liquidity pool for a given asset and sufficiently endow accounts to benchmark - /// the extension. - fn setup_balances_and_pool(asset_id: FunAssetIdParameter, account: AccountId); - } - #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -199,8 +172,9 @@ where who: &T::AccountId, call: &T::RuntimeCall, info: &DispatchInfoOf, - fee: BalanceOf, + len: usize, ) -> Result<(BalanceOf, InitialPayment), TransactionValidityError> { + let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); debug_assert!(self.tip <= fee, "tip should be included in the computed fee"); if fee.is_zero() { Ok((fee, InitialPayment::Nothing)) @@ -235,139 +209,104 @@ impl sp_std::fmt::Debug for ChargeAssetTxPayment { } } -impl TransactionExtensionBase for ChargeAssetTxPayment -where - AssetBalanceOf: Send + Sync, - BalanceOf: Send + Sync + From + IsType>, - ChargeAssetIdOf: Send + Sync, - Credit: IsType>, -{ - const IDENTIFIER: &'static str = "ChargeAssetTxPayment"; - type Implicit = (); - - fn weight(&self) -> Weight { - if self.asset_id.is_some() { - ::WeightInfo::charge_asset_tx_payment_asset() - } else { - ::WeightInfo::charge_asset_tx_payment_native() - } - } -} - -impl TransactionExtension for ChargeAssetTxPayment +impl SignedExtension for ChargeAssetTxPayment where T::RuntimeCall: Dispatchable, AssetBalanceOf: Send + Sync, BalanceOf: Send + Sync + From + IsType>, ChargeAssetIdOf: Send + Sync, Credit: IsType>, - ::RuntimeOrigin: AsSystemOriginSigner + Clone, { - type Val = ( - // tip - BalanceOf, - // who paid the fee - T::AccountId, - // transaction fee - BalanceOf, - ); + const IDENTIFIER: &'static str = "ChargeAssetTxPayment"; + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = (); type Pre = ( // tip BalanceOf, // who paid the fee - T::AccountId, + Self::AccountId, // imbalance resulting from withdrawing the fee InitialPayment, // asset_id for the transaction payment Option>, ); + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + fn validate( &self, - origin: ::RuntimeOrigin, - _call: &T::RuntimeCall, - info: &DispatchInfoOf, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> Result< - (ValidTransaction, Self::Val, ::RuntimeOrigin), - TransactionValidityError, - > { + ) -> TransactionValidity { use pallet_transaction_payment::ChargeTransactionPayment; - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; - // Non-mutating call of `compute_fee` to calculate the fee used in the transaction priority. - let fee = pallet_transaction_payment::Pallet::::compute_fee(len as u32, info, self.tip); + let (fee, _) = self.withdraw_fee(who, call, info, len)?; let priority = ChargeTransactionPayment::::get_priority(info, len, self.tip, fee); - let val = (self.tip, who.clone(), fee); - let validity = ValidTransaction { priority, ..Default::default() }; - Ok((validity, val, origin)) + Ok(ValidTransaction { priority, ..Default::default() }) } - fn prepare( + fn pre_dispatch( self, - val: Self::Val, - _origin: &::RuntimeOrigin, - call: &T::RuntimeCall, - info: &DispatchInfoOf, - _len: usize, - _context: &Context, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, ) -> Result { - let (tip, who, fee) = val; - // Mutating call of `withdraw_fee` to actually charge for the transaction. - let (_fee, initial_payment) = self.withdraw_fee(&who, call, info, fee)?; - Ok((tip, who, initial_payment, self.asset_id)) + let (_fee, initial_payment) = self.withdraw_fee(who, call, info, len)?; + Ok((self.tip, who.clone(), initial_payment, self.asset_id)) } fn post_dispatch( - pre: Self::Pre, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, - _context: &Context, ) -> Result<(), TransactionValidityError> { - let (tip, who, initial_payment, asset_id) = pre; - match initial_payment { - InitialPayment::Native(already_withdrawn) => { - pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( - (tip, who, already_withdrawn), - info, - post_info, - len, - result, - &(), - )?; - }, - InitialPayment::Asset(already_withdrawn) => { - let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( - len as u32, info, post_info, tip, - ); - - let (converted_fee, converted_tip) = - T::OnChargeAssetTransaction::correct_and_deposit_fee( - &who, + if let Some((tip, who, initial_payment, asset_id)) = pre { + match initial_payment { + InitialPayment::Native(already_withdrawn) => { + pallet_transaction_payment::ChargeTransactionPayment::::post_dispatch( + Some((tip, who, already_withdrawn)), info, post_info, - actual_fee.into(), - tip.into(), - already_withdrawn.into(), + len, + result, )?; - Pallet::::deposit_event(Event::::AssetTxFeePaid { - who, - actual_fee: converted_fee, - tip: converted_tip, - asset_id, - }); - }, - InitialPayment::Nothing => { - // `actual_fee` should be zero here for any signed extrinsic. It would be - // non-zero here in case of unsigned extrinsics as they don't pay fees but - // `compute_actual_fee` is not aware of them. In both cases it's fine to just - // move ahead without adjusting the fee, though, so we do nothing. - debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); - }, + }, + InitialPayment::Asset(already_withdrawn) => { + let actual_fee = pallet_transaction_payment::Pallet::::compute_actual_fee( + len as u32, info, post_info, tip, + ); + + let (converted_fee, converted_tip) = + T::OnChargeAssetTransaction::correct_and_deposit_fee( + &who, + info, + post_info, + actual_fee.into(), + tip.into(), + already_withdrawn.into(), + )?; + Pallet::::deposit_event(Event::::AssetTxFeePaid { + who, + actual_fee: converted_fee, + tip: converted_tip, + asset_id, + }); + }, + InitialPayment::Nothing => { + // `actual_fee` should be zero here for any signed extrinsic. It would be + // non-zero here in case of unsigned extrinsics as they don't pay fees but + // `compute_actual_fee` is not aware of them. In both cases it's fine to just + // move ahead without adjusting the fee, though, so we do nothing. + debug_assert!(tip.is_zero(), "tip should be zero if initial fee was zero."); + }, + } } Ok(()) diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs index bb484795e82..1f335b4f6c4 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs @@ -136,12 +136,12 @@ impl WeightToFeeT for TransactionByteFee { } } -#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter; type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; + type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = ConstU8<5>; } @@ -205,56 +205,4 @@ impl Config for Runtime { pallet_assets::BalanceToAssetBalance, CreditToBlockAuthor, >; - type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = Helper; -} - -#[cfg(feature = "runtime-benchmarks")] -pub fn new_test_ext() -> sp_io::TestExternalities { - let base_weight = 5; - let balance_factor = 100; - crate::tests::ExtBuilder::default() - .balance_factor(balance_factor) - .base_weight(Weight::from_parts(base_weight, 0)) - .build() -} - -#[cfg(feature = "runtime-benchmarks")] -pub struct Helper; - -#[cfg(feature = "runtime-benchmarks")] -impl BenchmarkHelperTrait for Helper { - fn create_asset_id_parameter(id: u32) -> (u32, u32) { - (id.into(), id.into()) - } - - fn setup_balances_and_pool(asset_id: u32, account: u64) { - use frame_support::{assert_ok, traits::fungibles::Mutate}; - use sp_runtime::traits::StaticLookup; - let min_balance = 1; - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - asset_id.into(), - 42, /* owner */ - true, /* is_sufficient */ - min_balance - )); - - // mint into the caller account - let caller = 2; - let beneficiary = ::Lookup::unlookup(caller); - let balance = 1000; - assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); - assert_eq!(Assets::balance(asset_id, caller), balance); - - use frame_support::traits::Currency; - let _ = Balances::deposit_creating(&account, u32::MAX.into()); - - let beneficiary = ::Lookup::unlookup(account); - let balance = 1000; - - assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); - assert_eq!(Assets::balance(asset_id, account), balance); - } } diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs index 42b8f2cf5fa..8df98ceda99 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/tests.rs @@ -25,10 +25,7 @@ use frame_support::{ use frame_system as system; use mock::{ExtrinsicBaseWeight, *}; use pallet_balances::Call as BalancesCall; -use sp_runtime::{ - traits::{DispatchTransaction, StaticLookup}, - BuildStorage, -}; +use sp_runtime::{traits::StaticLookup, BuildStorage}; const CALL: &::RuntimeCall = &RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 2, value: 69 }); @@ -119,45 +116,33 @@ fn transaction_payment_in_native_possible() { .build() .execute_with(|| { let len = 10; - let (pre, _) = ChargeAssetTxPayment::::from(0, None) - .validate_and_prepare( - Some(1).into(), - CALL, - &info_from_weight(Weight::from_parts(5, 0)), - len, - ) + let pre = ChargeAssetTxPayment::::from(0, None) + .pre_dispatch(&1, CALL, &info_from_weight(Weight::from_parts(5, 0)), len) .unwrap(); let initial_balance = 10 * balance_factor; assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(Weight::from_parts(5, 0)), &default_post_info(), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Balances::free_balance(1), initial_balance - 5 - 5 - 10); - let (pre, _) = ChargeAssetTxPayment::::from(5 /* tipped */, None) - .validate_and_prepare( - Some(2).into(), - CALL, - &info_from_weight(Weight::from_parts(100, 0)), - len, - ) + let pre = ChargeAssetTxPayment::::from(5 /* tipped */, None) + .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) .unwrap(); let initial_balance_for_2 = 20 * balance_factor; assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 100 - 5); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(Weight::from_parts(100, 0)), &post_info_from_weight(Weight::from_parts(50, 0)), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Balances::free_balance(2), initial_balance_for_2 - 5 - 10 - 50 - 5); }); @@ -194,13 +179,8 @@ fn transaction_payment_in_asset_possible() { // we convert the from weight to fee based on the ratio between asset min balance and // existential deposit let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare( - Some(caller).into(), - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len, - ) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) .unwrap(); // assert that native balance is not used assert_eq!(Balances::free_balance(caller), 10 * balance_factor); @@ -209,12 +189,11 @@ fn transaction_payment_in_asset_possible() { assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(Weight::from_parts(weight, 0)), &default_post_info(), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance - fee); // check that the block author gets rewarded @@ -253,13 +232,8 @@ fn transaction_payment_without_fee() { // we convert the from weight to fee based on the ratio between asset min balance and // existential deposit let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare( - Some(caller).into(), - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len, - ) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) .unwrap(); // assert that native balance is not used assert_eq!(Balances::free_balance(caller), 10 * balance_factor); @@ -268,12 +242,11 @@ fn transaction_payment_without_fee() { assert_eq!(Assets::balance(asset_id, BLOCK_AUTHOR), 0); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(Weight::from_parts(weight, 0)), &post_info_from_pays(Pays::No), len, - &Ok(()), - &() + &Ok(()) )); // caller should be refunded assert_eq!(Assets::balance(asset_id, caller), balance); @@ -314,24 +287,18 @@ fn asset_transaction_payment_with_tip_and_refund() { // existential deposit let fee_with_tip = (base_weight + weight + len as u64 + tip) * min_balance / ExistentialDeposit::get(); - let (pre, _) = ChargeAssetTxPayment::::from(tip, Some(asset_id)) - .validate_and_prepare( - Some(caller).into(), - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len, - ) + let pre = ChargeAssetTxPayment::::from(tip, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) .unwrap(); assert_eq!(Assets::balance(asset_id, caller), balance - fee_with_tip); let final_weight = 50; assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(Weight::from_parts(weight, 0)), &post_info_from_weight(Weight::from_parts(final_weight, 0)), len, - &Ok(()), - &() + &Ok(()) )); let final_fee = fee_with_tip - (weight - final_weight) * min_balance / ExistentialDeposit::get(); @@ -372,25 +339,19 @@ fn payment_from_account_with_only_assets() { // we convert the from weight to fee based on the ratio between asset min balance and // existential deposit let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare( - Some(caller).into(), - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len, - ) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) .unwrap(); assert_eq!(Balances::free_balance(caller), 0); // check that fee was charged in the given asset assert_eq!(Assets::balance(asset_id, caller), balance - fee); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(Weight::from_parts(weight, 0)), &default_post_info(), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance - fee); assert_eq!(Balances::free_balance(caller), 0); @@ -411,12 +372,7 @@ fn payment_only_with_existing_sufficient_asset() { let len = 10; // pre_dispatch fails for non-existent asset assert!(ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare( - Some(caller).into(), - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len - ) + .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) .is_err()); // create the non-sufficient asset @@ -430,12 +386,7 @@ fn payment_only_with_existing_sufficient_asset() { )); // pre_dispatch fails for non-sufficient asset assert!(ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare( - Some(caller).into(), - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len - ) + .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) .is_err()); }); } @@ -473,40 +424,33 @@ fn converted_fee_is_never_zero_if_input_fee_is_not() { // naive fee calculation would round down to zero assert_eq!(fee, 0); { - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_pays(Pays::No), len) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) .unwrap(); // `Pays::No` still implies no fees assert_eq!(Assets::balance(asset_id, caller), balance); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_pays(Pays::No), &post_info_from_pays(Pays::No), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance); } - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare( - Some(caller).into(), - CALL, - &info_from_weight(Weight::from_parts(weight, 0)), - len, - ) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_weight(Weight::from_parts(weight, 0)), len) .unwrap(); // check that at least one coin was charged in the given asset assert_eq!(Assets::balance(asset_id, caller), balance - 1); assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_weight(Weight::from_parts(weight, 0)), &default_post_info(), len, - &Ok(()), - &() + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance - 1); }); @@ -544,8 +488,8 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { let fee = (base_weight + weight + len as u64) * min_balance / ExistentialDeposit::get(); // calculated fee is greater than 0 assert!(fee > 0); - let (pre, _) = ChargeAssetTxPayment::::from(0, Some(asset_id)) - .validate_and_prepare(Some(caller).into(), CALL, &info_from_pays(Pays::No), len) + let pre = ChargeAssetTxPayment::::from(0, Some(asset_id)) + .pre_dispatch(&caller, CALL, &info_from_pays(Pays::No), len) .unwrap(); // `Pays::No` implies no pre-dispatch fees assert_eq!(Assets::balance(asset_id, caller), balance); @@ -559,12 +503,60 @@ fn post_dispatch_fee_is_zero_if_pre_dispatch_fee_is_zero() { // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the // initial fee) assert_ok!(ChargeAssetTxPayment::::post_dispatch( - pre, + Some(pre), &info_from_pays(Pays::No), &post_info_from_pays(Pays::Yes), len, - &Ok(()), - &() + &Ok(()) + )); + assert_eq!(Assets::balance(asset_id, caller), balance); + }); +} + +#[test] +fn post_dispatch_fee_is_zero_if_unsigned_pre_dispatch_fee_is_zero() { + let base_weight = 1; + ExtBuilder::default() + .balance_factor(100) + .base_weight(Weight::from_parts(base_weight, 0)) + .build() + .execute_with(|| { + // create the asset + let asset_id = 1; + let min_balance = 100; + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + asset_id.into(), + 42, /* owner */ + true, /* is_sufficient */ + min_balance + )); + + // mint into the caller account + let caller = 333; + let beneficiary = ::Lookup::unlookup(caller); + let balance = 100; + assert_ok!(Assets::mint_into(asset_id.into(), &beneficiary, balance)); + assert_eq!(Assets::balance(asset_id, caller), balance); + let weight = 1; + let len = 1; + ChargeAssetTxPayment::::pre_dispatch_unsigned( + CALL, + &info_from_weight(Weight::from_parts(weight, 0)), + len, + ) + .unwrap(); + + assert_eq!(Assets::balance(asset_id, caller), balance); + + // `Pays::Yes` on post-dispatch does not mean we pay (we never charge more than the + // initial fee) + assert_ok!(ChargeAssetTxPayment::::post_dispatch( + None, + &info_from_weight(Weight::from_parts(weight, 0)), + &post_info_from_pays(Pays::Yes), + len, + &Ok(()) )); assert_eq!(Assets::balance(asset_id, caller), balance); }); diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs deleted file mode 100644 index 1af1c94177d..00000000000 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs +++ /dev/null @@ -1,146 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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_asset_tx_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` - -// Executed Command: -// ./target/production/substrate-node -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_asset_tx_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/transaction-payment/asset-tx-payment/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for `pallet_asset_tx_payment`. -pub trait WeightInfo { - fn charge_asset_tx_payment_zero() -> Weight; - fn charge_asset_tx_payment_native() -> Weight; - fn charge_asset_tx_payment_asset() -> Weight; -} - -/// Weights for `pallet_asset_tx_payment` using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - fn charge_asset_tx_payment_zero() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 542_000 picoseconds. - Weight::from_parts(597_000, 0) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_asset_tx_payment_native() -> Weight { - // Proof Size summary in bytes: - // Measured: `248` - // Estimated: `1733` - // Minimum execution time: 33_162_000 picoseconds. - Weight::from_parts(34_716_000, 1733) - .saturating_add(T::DbWeight::get().reads(3_u64)) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_asset_tx_payment_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `747` - // Estimated: `3675` - // Minimum execution time: 44_230_000 picoseconds. - Weight::from_parts(45_297_000, 3675) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } -} - -// For backwards compatibility and tests. -impl WeightInfo for () { - fn charge_asset_tx_payment_zero() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 542_000 picoseconds. - Weight::from_parts(597_000, 0) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_asset_tx_payment_native() -> Weight { - // Proof Size summary in bytes: - // Measured: `248` - // Estimated: `1733` - // Minimum execution time: 33_162_000 picoseconds. - Weight::from_parts(34_716_000, 1733) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - } - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, 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:1 w:1) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_asset_tx_payment_asset() -> Weight { - // Proof Size summary in bytes: - // Measured: `747` - // Estimated: `3675` - // Minimum execution time: 44_230_000 picoseconds. - Weight::from_parts(45_297_000, 3675) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } -} diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs index 9810ea08c79..6c34c26ce92 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs @@ -21,7 +21,7 @@ //! //! ## Overview //! -//! It does this by wrapping an existing [`TransactionExtension`] implementation (e.g. +//! It does this by wrapping an existing [`SignedExtension`] implementation (e.g. //! [`pallet-transaction-payment`]) and checking if the dispatchable is feeless before applying the //! wrapped extension. If the dispatchable is indeed feeless, the extension is skipped and a custom //! event is emitted instead. Otherwise, the extension is applied as usual. @@ -31,8 +31,7 @@ //! //! This pallet wraps an existing transaction payment pallet. This means you should both pallets //! in your `construct_runtime` macro and include this pallet's -//! [`TransactionExtension`] ([`SkipCheckIfFeeless`]) that would accept the existing one as an -//! argument. +//! [`SignedExtension`] ([`SkipCheckIfFeeless`]) that would accept the existing one as an argument. #![cfg_attr(not(feature = "std"), no_std)] @@ -43,10 +42,7 @@ use frame_support::{ }; use scale_info::{StaticTypeInfo, TypeInfo}; use sp_runtime::{ - traits::{ - DispatchInfoOf, OriginOf, PostDispatchInfoOf, TransactionExtension, - TransactionExtensionBase, ValidateResult, - }, + traits::{DispatchInfoOf, PostDispatchInfoOf, SignedExtension}, transaction_validity::TransactionValidityError, }; @@ -74,11 +70,11 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// A transaction fee was skipped. - FeeSkipped { origin: ::PalletsOrigin }, + FeeSkipped { who: T::AccountId }, } } -/// A [`TransactionExtension`] that skips the wrapped extension if the dispatchable is feeless. +/// A [`SignedExtension`] that skips the wrapped extension if the dispatchable is feeless. #[derive(Encode, Decode, Clone, Eq, PartialEq)] pub struct SkipCheckIfFeeless(pub S, sp_std::marker::PhantomData); @@ -107,96 +103,53 @@ impl From for SkipCheckIfFeeless { } } -pub enum Intermediate { - /// The wrapped extension should be applied. - Apply(T), - /// The wrapped extension should be skipped. - Skip(O), -} -use Intermediate::*; - -impl TransactionExtensionBase +impl> SignedExtension for SkipCheckIfFeeless +where + S::Call: CheckIfFeeless>, { + type AccountId = T::AccountId; + type Call = S::Call; + type AdditionalSigned = S::AdditionalSigned; + type Pre = (Self::AccountId, Option<::Pre>); // From the outside this extension should be "invisible", because it just extends the wrapped // extension with an extra check in `pre_dispatch` and `post_dispatch`. Thus, we should forward // the identifier of the wrapped extension to let wallets see this extension as it would only be // the wrapped extension itself. const IDENTIFIER: &'static str = S::IDENTIFIER; - type Implicit = S::Implicit; - - fn implicit(&self) -> Result { - self.0.implicit() - } - fn weight(&self) -> frame_support::weights::Weight { - self.0.weight() + fn additional_signed(&self) -> Result { + self.0.additional_signed() } -} -impl> - TransactionExtension for SkipCheckIfFeeless -where - T::RuntimeCall: CheckIfFeeless>, -{ - type Val = Intermediate as OriginTrait>::PalletsOrigin>; - type Pre = Intermediate as OriginTrait>::PalletsOrigin>; - - fn validate( - &self, - origin: OriginOf, - call: &T::RuntimeCall, - info: &DispatchInfoOf, - len: usize, - context: &mut Context, - self_implicit: S::Implicit, - inherited_implication: &impl Encode, - ) -> ValidateResult { - if call.is_feeless(&origin) { - Ok((Default::default(), Skip(origin.caller().clone()), origin)) - } else { - let (x, y, z) = self.0.validate( - origin, - call, - info, - len, - context, - self_implicit, - inherited_implication, - )?; - Ok((x, Apply(y), z)) - } - } - - fn prepare( + fn pre_dispatch( self, - val: Self::Val, - origin: &OriginOf, - call: &T::RuntimeCall, - info: &DispatchInfoOf, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, len: usize, - context: &Context, ) -> Result { - match val { - Apply(val) => self.0.prepare(val, origin, call, info, len, context).map(Apply), - Skip(origin) => Ok(Skip(origin)), + if call.is_feeless(&::RuntimeOrigin::signed(who.clone())) { + Ok((who.clone(), None)) + } else { + Ok((who.clone(), Some(self.0.pre_dispatch(who, call, info, len)?))) } } fn post_dispatch( - pre: Self::Pre, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, - context: &Context, ) -> Result<(), TransactionValidityError> { - match pre { - Apply(pre) => S::post_dispatch(pre, info, post_info, len, result, context), - Skip(origin) => { - Pallet::::deposit_event(Event::::FeeSkipped { origin }); - Ok(()) - }, + if let Some(pre) = pre { + if let Some(pre) = pre.1 { + S::post_dispatch(Some(pre), info, post_info, len, result)?; + } else { + Pallet::::deposit_event(Event::::FeeSkipped { who: pre.0 }); + } } + Ok(()) } } diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs index 06948de4c3c..17c4c773997 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs @@ -18,12 +18,9 @@ use crate as pallet_skip_feeless_payment; use frame_support::{derive_impl, parameter_types}; use frame_system as system; -use sp_runtime::{ - impl_tx_ext_default, - traits::{OriginOf, TransactionExtension}, -}; type Block = frame_system::mocking::MockBlock; +type AccountId = u64; #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Runtime { @@ -41,22 +38,21 @@ parameter_types! { #[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)] pub struct DummyExtension; -impl TransactionExtensionBase for DummyExtension { - const IDENTIFIER: &'static str = "DummyExtension"; - type Implicit = (); -} -impl TransactionExtension for DummyExtension { - type Val = (); +impl SignedExtension for DummyExtension { + type AccountId = AccountId; + type Call = RuntimeCall; + type AdditionalSigned = (); type Pre = (); - impl_tx_ext_default!(RuntimeCall; C; validate); - fn prepare( + const IDENTIFIER: &'static str = "DummyExtension"; + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + fn pre_dispatch( self, - _val: Self::Val, - _origin: &OriginOf, - _call: &RuntimeCall, - _info: &DispatchInfoOf, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &C, ) -> Result { PreDispatchCount::mutate(|c| *c += 1); Ok(()) diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs index 96b4af7e203..4b4dd699741 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs @@ -16,19 +16,18 @@ use super::*; use crate::mock::{pallet_dummy::Call, DummyExtension, PreDispatchCount, Runtime, RuntimeCall}; use frame_support::dispatch::DispatchInfo; -use sp_runtime::traits::DispatchTransaction; #[test] fn skip_feeless_payment_works() { let call = RuntimeCall::DummyPallet(Call::::aux { data: 1 }); SkipCheckIfFeeless::::from(DummyExtension) - .validate_and_prepare(Some(0).into(), &call, &DispatchInfo::default(), 0) + .pre_dispatch(&0, &call, &DispatchInfo::default(), 0) .unwrap(); assert_eq!(PreDispatchCount::get(), 1); let call = RuntimeCall::DummyPallet(Call::::aux { data: 0 }); SkipCheckIfFeeless::::from(DummyExtension) - .validate_and_prepare(Some(0).into(), &call, &DispatchInfo::default(), 0) + .pre_dispatch(&0, &call, &DispatchInfo::default(), 0) .unwrap(); assert_eq!(PreDispatchCount::get(), 1); } diff --git a/substrate/frame/transaction-payment/src/benchmarking.rs b/substrate/frame/transaction-payment/src/benchmarking.rs deleted file mode 100644 index d63c5a7d746..00000000000 --- a/substrate/frame/transaction-payment/src/benchmarking.rs +++ /dev/null @@ -1,81 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -//! Benchmarks for Transaction Payment Pallet's transaction extension - -use super::*; -use crate::Pallet; -use frame_benchmarking::v2::*; -use frame_support::dispatch::{DispatchInfo, PostDispatchInfo}; -use frame_system::{EventRecord, RawOrigin}; -use sp_runtime::traits::{DispatchTransaction, Dispatchable}; - -fn assert_last_event(generic_event: ::RuntimeEvent) { - let events = frame_system::Pallet::::events(); - let system_event: ::RuntimeEvent = generic_event.into(); - // compare to the last event record - let EventRecord { event, .. } = &events[events.len() - 1]; - assert_eq!(event, &system_event); -} - -#[benchmarks(where - T: Config, - T::RuntimeCall: Dispatchable, - BalanceOf: Send + Sync + From, -)] -mod benchmarks { - use super::*; - - #[benchmark] - fn charge_transaction_payment() { - let caller: T::AccountId = whitelisted_caller(); - >::endow_account( - &caller, - >::minimum_balance() * 1000.into(), - ); - let tip = >::minimum_balance(); - let ext: ChargeTransactionPayment = ChargeTransactionPayment::from(tip); - let inner = frame_system::Call::remark { remark: vec![] }; - let call = T::RuntimeCall::from(inner); - let info = DispatchInfo { - weight: Weight::from_parts(100, 0), - class: DispatchClass::Operational, - pays_fee: Pays::Yes, - }; - let post_info = PostDispatchInfo { - actual_weight: Some(Weight::from_parts(10, 0)), - pays_fee: Pays::Yes, - }; - - #[block] - { - assert!(ext - .test_run(RawOrigin::Signed(caller.clone()).into(), &call, &info, 10, |_| Ok( - post_info - )) - .unwrap() - .is_ok()); - } - - let actual_fee = Pallet::::compute_actual_fee(10, &info, &post_info, tip); - assert_last_event::( - Event::::TransactionFeePaid { who: caller, actual_fee, tip }.into(), - ); - } - - impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime); -} diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs index 6b17616bdc7..efadfd60bdd 100644 --- a/substrate/frame/transaction-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/src/lib.rs @@ -62,28 +62,23 @@ pub use payment::*; use sp_runtime::{ traits::{ Convert, DispatchInfoOf, Dispatchable, One, PostDispatchInfoOf, SaturatedConversion, - Saturating, TransactionExtension, TransactionExtensionBase, Zero, + Saturating, SignedExtension, Zero, }, transaction_validity::{ - InvalidTransaction, TransactionPriority, TransactionValidityError, ValidTransaction, + TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction, }, FixedPointNumber, FixedU128, Perbill, Perquintill, RuntimeDebug, }; use sp_std::prelude::*; pub use types::{FeeDetails, InclusionFee, RuntimeDispatchInfo}; -pub use weights::WeightInfo; #[cfg(test)] mod mock; #[cfg(test)] mod tests; -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - mod payment; mod types; -pub mod weights; /// Fee multiplier. pub type Multiplier = FixedU128; @@ -340,7 +335,6 @@ pub mod pallet { type RuntimeEvent = (); type FeeMultiplierUpdate = (); type OperationalFeeMultiplier = (); - type WeightInfo = (); } } @@ -393,9 +387,6 @@ pub mod pallet { /// transactions. #[pallet::constant] type OperationalFeeMultiplier: Get; - - /// The weight information of this pallet. - type WeightInfo: WeightInfo; } #[pallet::type_value] @@ -516,11 +507,11 @@ impl Pallet { // a very very little potential gain in the future. let dispatch_info = ::get_dispatch_info(&unchecked_extrinsic); - let partial_fee = if unchecked_extrinsic.is_bare() { - // Bare extrinsics have no partial fee. - 0u32.into() - } else { + let partial_fee = if unchecked_extrinsic.is_signed().unwrap_or(false) { Self::compute_fee(len, &dispatch_info, 0u32.into()) + } else { + // Unsigned extrinsics have no partial fee. + 0u32.into() }; let DispatchInfo { weight, class, .. } = dispatch_info; @@ -540,11 +531,11 @@ impl Pallet { let tip = 0u32.into(); - if unchecked_extrinsic.is_bare() { - // Bare extrinsics have no inclusion fee. - FeeDetails { inclusion_fee: None, tip } - } else { + if unchecked_extrinsic.is_signed().unwrap_or(false) { Self::compute_fee_details(len, &dispatch_info, tip) + } else { + // Unsigned extrinsics have no inclusion fee. + FeeDetails { inclusion_fee: None, tip } } } @@ -723,7 +714,7 @@ where who: &T::AccountId, call: &T::RuntimeCall, info: &DispatchInfoOf, - fee: BalanceOf, + len: usize, ) -> Result< ( BalanceOf, @@ -732,6 +723,7 @@ where TransactionValidityError, > { let tip = self.0; + let fee = Pallet::::compute_fee(len as u32, info, tip); <::OnChargeTransaction as OnChargeTransaction>::withdraw_fee( who, call, info, fee, tip, @@ -739,22 +731,6 @@ where .map(|i| (fee, i)) } - fn can_withdraw_fee( - &self, - who: &T::AccountId, - call: &T::RuntimeCall, - info: &DispatchInfoOf, - len: usize, - ) -> Result, TransactionValidityError> { - let tip = self.0; - let fee = Pallet::::compute_fee(len as u32, info, tip); - - <::OnChargeTransaction as OnChargeTransaction>::can_withdraw_fee( - who, call, info, fee, tip, - )?; - Ok(fee) - } - /// Get an appropriate priority for a transaction with the given `DispatchInfo`, encoded length /// and user-included tip. /// @@ -841,93 +817,67 @@ impl sp_std::fmt::Debug for ChargeTransactionPayment { } } -impl TransactionExtensionBase for ChargeTransactionPayment { - const IDENTIFIER: &'static str = "ChargeTransactionPayment"; - type Implicit = (); - - fn weight(&self) -> Weight { - T::WeightInfo::charge_transaction_payment() - } -} - -impl TransactionExtension - for ChargeTransactionPayment +impl SignedExtension for ChargeTransactionPayment where BalanceOf: Send + Sync + From, T::RuntimeCall: Dispatchable, { - type Val = ( - // tip - BalanceOf, - // who paid the fee - T::AccountId, - // computed fee - BalanceOf, - ); + const IDENTIFIER: &'static str = "ChargeTransactionPayment"; + type AccountId = T::AccountId; + type Call = T::RuntimeCall; + type AdditionalSigned = (); type Pre = ( // tip BalanceOf, - // who paid the fee - T::AccountId, + // who paid the fee - this is an option to allow for a Default impl. + Self::AccountId, // imbalance resulting from withdrawing the fee <::OnChargeTransaction as OnChargeTransaction>::LiquidityInfo, ); + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } fn validate( &self, - origin: ::RuntimeOrigin, - call: &T::RuntimeCall, - info: &DispatchInfoOf, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, len: usize, - _context: &mut Context, - _: (), - _implication: &impl Encode, - ) -> Result< - (ValidTransaction, Self::Val, ::RuntimeOrigin), - TransactionValidityError, - > { - let who = frame_system::ensure_signed(origin.clone()) - .map_err(|_| InvalidTransaction::BadSigner)?; - let final_fee = self.can_withdraw_fee(&who, call, info, len)?; + ) -> TransactionValidity { + let (final_fee, _) = self.withdraw_fee(who, call, info, len)?; let tip = self.0; - Ok(( - ValidTransaction { - priority: Self::get_priority(info, len, tip, final_fee), - ..Default::default() - }, - (self.0, who, final_fee), - origin, - )) + Ok(ValidTransaction { + priority: Self::get_priority(info, len, tip, final_fee), + ..Default::default() + }) } - fn prepare( + fn pre_dispatch( self, - val: Self::Val, - _origin: &::RuntimeOrigin, - call: &T::RuntimeCall, - info: &DispatchInfoOf, - _len: usize, - _context: &Context, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, ) -> Result { - let (tip, who, fee) = val; - // Mutating call to `withdraw_fee` to actually charge for the transaction. - let (_final_fee, imbalance) = self.withdraw_fee(&who, call, info, fee)?; - Ok((tip, who, imbalance)) + let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?; + Ok((self.0, who.clone(), imbalance)) } fn post_dispatch( - (tip, who, imbalance): Self::Pre, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + maybe_pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, _result: &DispatchResult, - _context: &Context, ) -> Result<(), TransactionValidityError> { - let actual_fee = Pallet::::compute_actual_fee(len as u32, info, post_info, tip); - T::OnChargeTransaction::correct_and_deposit_fee( - &who, info, post_info, actual_fee, tip, imbalance, - )?; - Pallet::::deposit_event(Event::::TransactionFeePaid { who, actual_fee, tip }); + if let Some((tip, who, imbalance)) = maybe_pre { + let actual_fee = Pallet::::compute_actual_fee(len as u32, info, post_info, tip); + T::OnChargeTransaction::correct_and_deposit_fee( + &who, info, post_info, actual_fee, tip, imbalance, + )?; + Pallet::::deposit_event(Event::::TransactionFeePaid { who, actual_fee, tip }); + } Ok(()) } } diff --git a/substrate/frame/transaction-payment/src/mock.rs b/substrate/frame/transaction-payment/src/mock.rs index eda234ffcae..1ca2e3d7347 100644 --- a/substrate/frame/transaction-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/src/mock.rs @@ -157,14 +157,4 @@ impl Config for Runtime { type WeightToFee = WeightToFee; type LengthToFee = TransactionByteFee; type FeeMultiplierUpdate = (); - type WeightInfo = (); -} - -#[cfg(feature = "runtime-benchmarks")] -pub fn new_test_ext() -> sp_io::TestExternalities { - crate::tests::ExtBuilder::default() - .base_weight(Weight::from_parts(100, 0)) - .byte_fee(10) - .balance_factor(0) - .build() } diff --git a/substrate/frame/transaction-payment/src/payment.rs b/substrate/frame/transaction-payment/src/payment.rs index a13e73b50b0..886683f2e0b 100644 --- a/substrate/frame/transaction-payment/src/payment.rs +++ b/substrate/frame/transaction-payment/src/payment.rs @@ -20,7 +20,7 @@ use crate::Config; use core::marker::PhantomData; use sp_runtime::{ - traits::{CheckedSub, DispatchInfoOf, PostDispatchInfoOf, Saturating, Zero}, + traits::{DispatchInfoOf, PostDispatchInfoOf, Saturating, Zero}, transaction_validity::InvalidTransaction, }; @@ -51,17 +51,6 @@ pub trait OnChargeTransaction { tip: Self::Balance, ) -> Result; - /// Check if the predicted fee from the transaction origin can be withdrawn. - /// - /// Note: The `fee` already includes the `tip`. - fn can_withdraw_fee( - who: &T::AccountId, - call: &T::RuntimeCall, - dispatch_info: &DispatchInfoOf, - fee: Self::Balance, - tip: Self::Balance, - ) -> Result<(), TransactionValidityError>; - /// After the transaction was executed the actual fee can be calculated. /// This function should refund any overpaid fees and optionally deposit /// the corrected amount. @@ -75,12 +64,6 @@ pub trait OnChargeTransaction { tip: Self::Balance, already_withdrawn: Self::LiquidityInfo, ) -> Result<(), TransactionValidityError>; - - #[cfg(feature = "runtime-benchmarks")] - fn endow_account(who: &T::AccountId, amount: Self::Balance); - - #[cfg(feature = "runtime-benchmarks")] - fn minimum_balance() -> Self::Balance; } /// Implements the transaction payment for a pallet implementing the `Currency` @@ -138,33 +121,6 @@ where } } - /// Check if the predicted fee from the transaction origin can be withdrawn. - /// - /// Note: The `fee` already includes the `tip`. - fn can_withdraw_fee( - who: &T::AccountId, - _call: &T::RuntimeCall, - _info: &DispatchInfoOf, - fee: Self::Balance, - tip: Self::Balance, - ) -> Result<(), TransactionValidityError> { - if fee.is_zero() { - return Ok(()) - } - - let withdraw_reason = if tip.is_zero() { - WithdrawReasons::TRANSACTION_PAYMENT - } else { - WithdrawReasons::TRANSACTION_PAYMENT | WithdrawReasons::TIP - }; - - let new_balance = - C::free_balance(who).checked_sub(&fee).ok_or(InvalidTransaction::Payment)?; - C::ensure_can_withdraw(who, fee, withdraw_reason, new_balance) - .map(|_| ()) - .map_err(|_| InvalidTransaction::Payment.into()) - } - /// Hand the fee and the tip over to the `[OnUnbalanced]` implementation. /// Since the predicted fee might have been too high, parts of the fee may /// be refunded. @@ -197,14 +153,4 @@ where } Ok(()) } - - #[cfg(feature = "runtime-benchmarks")] - fn endow_account(who: &T::AccountId, amount: Self::Balance) { - let _ = C::deposit_creating(who, amount); - } - - #[cfg(feature = "runtime-benchmarks")] - fn minimum_balance() -> Self::Balance { - C::minimum_balance() - } } diff --git a/substrate/frame/transaction-payment/src/tests.rs b/substrate/frame/transaction-payment/src/tests.rs index 7a49f8111e2..d3a1721ccb9 100644 --- a/substrate/frame/transaction-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/src/tests.rs @@ -21,14 +21,11 @@ use crate as pallet_transaction_payment; use codec::Encode; use sp_runtime::{ - generic::UncheckedExtrinsic, - traits::{DispatchTransaction, One}, - transaction_validity::InvalidTransaction, - BuildStorage, + testing::TestXt, traits::One, transaction_validity::InvalidTransaction, BuildStorage, }; use frame_support::{ - assert_ok, + assert_noop, assert_ok, dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo}, traits::Currency, weights::Weight, @@ -131,37 +128,44 @@ fn default_post_info() -> PostDispatchInfo { PostDispatchInfo { actual_weight: None, pays_fee: Default::default() } } -type Ext = ChargeTransactionPayment; - #[test] -fn transaction_extension_transaction_payment_work() { +fn signed_extension_transaction_payment_work() { ExtBuilder::default() .balance_factor(10) .base_weight(Weight::from_parts(5, 0)) .build() .execute_with(|| { - let info = info_from_weight(Weight::from_parts(5, 0)); - Ext::from(0) - .test_run(Some(1).into(), CALL, &info, 10, |_| { - assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); - Ok(default_post_info()) - }) - .unwrap() + let len = 10; + let pre = ChargeTransactionPayment::::from(0) + .pre_dispatch(&1, CALL, &info_from_weight(Weight::from_parts(5, 0)), len) .unwrap(); assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); + + assert_ok!(ChargeTransactionPayment::::post_dispatch( + Some(pre), + &info_from_weight(Weight::from_parts(5, 0)), + &default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10); assert_eq!(FeeUnbalancedAmount::get(), 5 + 5 + 10); assert_eq!(TipUnbalancedAmount::get(), 0); FeeUnbalancedAmount::mutate(|a| *a = 0); - let info = info_from_weight(Weight::from_parts(100, 0)); - Ext::from(5 /* tipped */) - .test_run(Some(2).into(), CALL, &info, 10, |_| { - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); - Ok(post_info_from_weight(Weight::from_parts(50, 0))) - }) - .unwrap() + let pre = ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) .unwrap(); + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + + assert_ok!(ChargeTransactionPayment::::post_dispatch( + Some(pre), + &info_from_weight(Weight::from_parts(100, 0)), + &post_info_from_weight(Weight::from_parts(50, 0)), + len, + &Ok(()) + )); assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 50 - 5); assert_eq!(FeeUnbalancedAmount::get(), 5 + 10 + 50); assert_eq!(TipUnbalancedAmount::get(), 5); @@ -169,37 +173,43 @@ fn transaction_extension_transaction_payment_work() { } #[test] -fn transaction_extension_transaction_payment_multiplied_refund_works() { +fn signed_extension_transaction_payment_multiplied_refund_works() { ExtBuilder::default() .balance_factor(10) .base_weight(Weight::from_parts(5, 0)) .build() .execute_with(|| { + let len = 10; >::put(Multiplier::saturating_from_rational(3, 2)); - let len = 10; - let origin = Some(2).into(); - let info = info_from_weight(Weight::from_parts(100, 0)); - Ext::from(5 /* tipped */) - .test_run(origin, CALL, &info, len, |_| { - // 5 base fee, 10 byte fee, 3/2 * 100 weight fee, 5 tip - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 150 - 5); - Ok(post_info_from_weight(Weight::from_parts(50, 0))) - }) - .unwrap() + let pre = ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) .unwrap(); - + // 5 base fee, 10 byte fee, 3/2 * 100 weight fee, 5 tip + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 150 - 5); + + assert_ok!(ChargeTransactionPayment::::post_dispatch( + Some(pre), + &info_from_weight(Weight::from_parts(100, 0)), + &post_info_from_weight(Weight::from_parts(50, 0)), + len, + &Ok(()) + )); // 75 (3/2 of the returned 50 units of weight) is refunded assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 75 - 5); }); } #[test] -fn transaction_extension_transaction_payment_is_bounded() { +fn signed_extension_transaction_payment_is_bounded() { ExtBuilder::default().balance_factor(1000).byte_fee(0).build().execute_with(|| { // maximum weight possible - let info = info_from_weight(Weight::MAX); - assert_ok!(Ext::from(0).validate_and_prepare(Some(1).into(), CALL, &info, 10)); + assert_ok!(ChargeTransactionPayment::::from(0).pre_dispatch( + &1, + CALL, + &info_from_weight(Weight::MAX), + 10 + )); // fee will be proportional to what is the actual maximum weight in the runtime. assert_eq!( Balances::free_balance(&1), @@ -210,7 +220,7 @@ fn transaction_extension_transaction_payment_is_bounded() { } #[test] -fn transaction_extension_allows_free_transactions() { +fn signed_extension_allows_free_transactions() { ExtBuilder::default() .base_weight(Weight::from_parts(100, 0)) .balance_factor(0) @@ -222,28 +232,38 @@ fn transaction_extension_allows_free_transactions() { let len = 100; // This is a completely free (and thus wholly insecure/DoS-ridden) transaction. - let op_tx = DispatchInfo { + let operational_transaction = DispatchInfo { weight: Weight::from_parts(0, 0), class: DispatchClass::Operational, pays_fee: Pays::No, }; - assert_ok!(Ext::from(0).validate_only(Some(1).into(), CALL, &op_tx, len)); + assert_ok!(ChargeTransactionPayment::::from(0).validate( + &1, + CALL, + &operational_transaction, + len + )); // like a InsecureFreeNormal - let free_tx = DispatchInfo { + let free_transaction = DispatchInfo { weight: Weight::from_parts(0, 0), class: DispatchClass::Normal, pays_fee: Pays::Yes, }; - assert_eq!( - Ext::from(0).validate_only(Some(1).into(), CALL, &free_tx, len).unwrap_err(), + assert_noop!( + ChargeTransactionPayment::::from(0).validate( + &1, + CALL, + &free_transaction, + len + ), TransactionValidityError::Invalid(InvalidTransaction::Payment), ); }); } #[test] -fn transaction_ext_length_fee_is_also_updated_per_congestion() { +fn signed_ext_length_fee_is_also_updated_per_congestion() { ExtBuilder::default() .base_weight(Weight::from_parts(5, 0)) .balance_factor(10) @@ -252,15 +272,16 @@ fn transaction_ext_length_fee_is_also_updated_per_congestion() { // all fees should be x1.5 >::put(Multiplier::saturating_from_rational(3, 2)); let len = 10; - let info = &info_from_weight(Weight::from_parts(3, 0)); - assert_ok!(Ext::from(10).validate_and_prepare(Some(1).into(), CALL, info, len)); + + assert_ok!(ChargeTransactionPayment::::from(10) // tipped + .pre_dispatch(&1, CALL, &info_from_weight(Weight::from_parts(3, 0)), len)); assert_eq!( Balances::free_balance(1), 100 // original - - 10 // tip - - 5 // base - - 10 // len - - (3 * 3 / 2) // adjusted weight + - 10 // tip + - 5 // base + - 10 // len + - (3 * 3 / 2) // adjusted weight ); }) } @@ -270,62 +291,62 @@ fn query_info_and_fee_details_works() { let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 2, value: 69 }); let origin = 111111; let extra = (); - let xt = UncheckedExtrinsic::new_signed(call.clone(), origin, (), extra); + let xt = TestXt::new(call.clone(), Some((origin, extra))); let info = xt.get_dispatch_info(); let ext = xt.encode(); let len = ext.len() as u32; - let unsigned_xt = UncheckedExtrinsic::::new_bare(call); + let unsigned_xt = TestXt::<_, ()>::new(call, None); let unsigned_xt_info = unsigned_xt.get_dispatch_info(); ExtBuilder::default() - .base_weight(Weight::from_parts(5, 0)) - .weight_fee(2) - .build() - .execute_with(|| { - // all fees should be x1.5 - >::put(Multiplier::saturating_from_rational(3, 2)); - - assert_eq!( - TransactionPayment::query_info(xt.clone(), len), - RuntimeDispatchInfo { - weight: info.weight, - class: info.class, - partial_fee: 5 * 2 /* base * weight_fee */ - + len as u64 /* len * 1 */ - + info.weight.min(BlockWeights::get().max_block).ref_time() as u64 * 2 * 3 / 2 /* weight */ - }, - ); - - assert_eq!( - TransactionPayment::query_info(unsigned_xt.clone(), len), - RuntimeDispatchInfo { - weight: unsigned_xt_info.weight, - class: unsigned_xt_info.class, - partial_fee: 0, - }, - ); - - assert_eq!( - TransactionPayment::query_fee_details(xt, len), - FeeDetails { - inclusion_fee: Some(InclusionFee { - base_fee: 5 * 2, - len_fee: len as u64, - adjusted_weight_fee: info - .weight - .min(BlockWeights::get().max_block) - .ref_time() as u64 * 2 * 3 / 2 - }), - tip: 0, - }, - ); - - assert_eq!( - TransactionPayment::query_fee_details(unsigned_xt, len), - FeeDetails { inclusion_fee: None, tip: 0 }, - ); - }); + .base_weight(Weight::from_parts(5, 0)) + .weight_fee(2) + .build() + .execute_with(|| { + // all fees should be x1.5 + >::put(Multiplier::saturating_from_rational(3, 2)); + + assert_eq!( + TransactionPayment::query_info(xt.clone(), len), + RuntimeDispatchInfo { + weight: info.weight, + class: info.class, + partial_fee: 5 * 2 /* base * weight_fee */ + + len as u64 /* len * 1 */ + + info.weight.min(BlockWeights::get().max_block).ref_time() as u64 * 2 * 3 / 2 /* weight */ + }, + ); + + assert_eq!( + TransactionPayment::query_info(unsigned_xt.clone(), len), + RuntimeDispatchInfo { + weight: unsigned_xt_info.weight, + class: unsigned_xt_info.class, + partial_fee: 0, + }, + ); + + assert_eq!( + TransactionPayment::query_fee_details(xt, len), + FeeDetails { + inclusion_fee: Some(InclusionFee { + base_fee: 5 * 2, + len_fee: len as u64, + adjusted_weight_fee: info + .weight + .min(BlockWeights::get().max_block) + .ref_time() as u64 * 2 * 3 / 2 + }), + tip: 0, + }, + ); + + assert_eq!( + TransactionPayment::query_fee_details(unsigned_xt, len), + FeeDetails { inclusion_fee: None, tip: 0 }, + ); + }); } #[test] @@ -336,39 +357,39 @@ fn query_call_info_and_fee_details_works() { let len = encoded_call.len() as u32; ExtBuilder::default() - .base_weight(Weight::from_parts(5, 0)) - .weight_fee(2) - .build() - .execute_with(|| { - // all fees should be x1.5 - >::put(Multiplier::saturating_from_rational(3, 2)); - - assert_eq!( - TransactionPayment::query_call_info(call.clone(), len), - RuntimeDispatchInfo { - weight: info.weight, - class: info.class, - partial_fee: 5 * 2 /* base * weight_fee */ - + len as u64 /* len * 1 */ - + info.weight.min(BlockWeights::get().max_block).ref_time() as u64 * 2 * 3 / 2 /* weight */ - }, - ); - - assert_eq!( - TransactionPayment::query_call_fee_details(call, len), - FeeDetails { - inclusion_fee: Some(InclusionFee { - base_fee: 5 * 2, /* base * weight_fee */ - len_fee: len as u64, /* len * 1 */ - adjusted_weight_fee: info - .weight - .min(BlockWeights::get().max_block) - .ref_time() as u64 * 2 * 3 / 2 /* weight * weight_fee * multipler */ - }), - tip: 0, - }, - ); - }); + .base_weight(Weight::from_parts(5, 0)) + .weight_fee(2) + .build() + .execute_with(|| { + // all fees should be x1.5 + >::put(Multiplier::saturating_from_rational(3, 2)); + + assert_eq!( + TransactionPayment::query_call_info(call.clone(), len), + RuntimeDispatchInfo { + weight: info.weight, + class: info.class, + partial_fee: 5 * 2 /* base * weight_fee */ + + len as u64 /* len * 1 */ + + info.weight.min(BlockWeights::get().max_block).ref_time() as u64 * 2 * 3 / 2 /* weight */ + }, + ); + + assert_eq!( + TransactionPayment::query_call_fee_details(call, len), + FeeDetails { + inclusion_fee: Some(InclusionFee { + base_fee: 5 * 2, /* base * weight_fee */ + len_fee: len as u64, /* len * 1 */ + adjusted_weight_fee: info + .weight + .min(BlockWeights::get().max_block) + .ref_time() as u64 * 2 * 3 / 2 /* weight * weight_fee * multipler */ + }), + tip: 0, + }, + ); + }); } #[test] @@ -505,23 +526,27 @@ fn refund_does_not_recreate_account() { .execute_with(|| { // So events are emitted System::set_block_number(10); - let info = info_from_weight(Weight::from_parts(100, 0)); - Ext::from(5 /* tipped */) - .test_run(Some(2).into(), CALL, &info, 10, |origin| { - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); - - // kill the account between pre and post dispatch - assert_ok!(Balances::transfer_allow_death( - origin, - 3, - Balances::free_balance(2) - )); - assert_eq!(Balances::free_balance(2), 0); - - Ok(post_info_from_weight(Weight::from_parts(50, 0))) - }) - .unwrap() + let len = 10; + let pre = ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) .unwrap(); + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + + // kill the account between pre and post dispatch + assert_ok!(Balances::transfer_allow_death( + Some(2).into(), + 3, + Balances::free_balance(2) + )); + assert_eq!(Balances::free_balance(2), 0); + + assert_ok!(ChargeTransactionPayment::::post_dispatch( + Some(pre), + &info_from_weight(Weight::from_parts(100, 0)), + &post_info_from_weight(Weight::from_parts(50, 0)), + len, + &Ok(()) + )); assert_eq!(Balances::free_balance(2), 0); // Transfer Event System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Transfer { @@ -543,15 +568,20 @@ fn actual_weight_higher_than_max_refunds_nothing() { .base_weight(Weight::from_parts(5, 0)) .build() .execute_with(|| { - let info = info_from_weight(Weight::from_parts(100, 0)); - Ext::from(5 /* tipped */) - .test_run(Some(2).into(), CALL, &info, 10, |_| { - assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); - Ok(post_info_from_weight(Weight::from_parts(101, 0))) - }) - .unwrap() + let len = 10; + let pre = ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, &info_from_weight(Weight::from_parts(100, 0)), len) .unwrap(); assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); + + assert_ok!(ChargeTransactionPayment::::post_dispatch( + Some(pre), + &info_from_weight(Weight::from_parts(100, 0)), + &post_info_from_weight(Weight::from_parts(101, 0)), + len, + &Ok(()) + )); + assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); }); } @@ -564,20 +594,25 @@ fn zero_transfer_on_free_transaction() { .execute_with(|| { // So events are emitted System::set_block_number(10); - let info = DispatchInfo { + let len = 10; + let dispatch_info = DispatchInfo { weight: Weight::from_parts(100, 0), pays_fee: Pays::No, class: DispatchClass::Normal, }; let user = 69; - Ext::from(0) - .test_run(Some(user).into(), CALL, &info, 10, |_| { - assert_eq!(Balances::total_balance(&user), 0); - Ok(default_post_info()) - }) - .unwrap() + let pre = ChargeTransactionPayment::::from(0) + .pre_dispatch(&user, CALL, &dispatch_info, len) .unwrap(); assert_eq!(Balances::total_balance(&user), 0); + assert_ok!(ChargeTransactionPayment::::post_dispatch( + Some(pre), + &dispatch_info, + &default_post_info(), + len, + &Ok(()) + )); + assert_eq!(Balances::total_balance(&user), 0); // TransactionFeePaid Event System::assert_has_event(RuntimeEvent::TransactionPayment( pallet_transaction_payment::Event::TransactionFeePaid { @@ -604,11 +639,19 @@ fn refund_consistent_with_actual_weight() { >::put(Multiplier::saturating_from_rational(5, 4)); - Ext::from(tip) - .test_run(Some(2).into(), CALL, &info, len, |_| Ok(post_info)) - .unwrap() + let pre = ChargeTransactionPayment::::from(tip) + .pre_dispatch(&2, CALL, &info, len) .unwrap(); + ChargeTransactionPayment::::post_dispatch( + Some(pre), + &info, + &post_info, + len, + &Ok(()), + ) + .unwrap(); + let refund_based_fee = prev_balance - Balances::free_balance(2); let actual_fee = Pallet::::compute_actual_fee(len as u32, &info, &post_info, tip); @@ -630,13 +673,18 @@ fn should_alter_operational_priority() { class: DispatchClass::Normal, pays_fee: Pays::Yes, }; + let priority = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &normal, len) + .unwrap() + .priority; - let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; assert_eq!(priority, 60); - let ext = Ext::from(2 * tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; + let priority = ChargeTransactionPayment::(2 * tip) + .validate(&2, CALL, &normal, len) + .unwrap() + .priority; + assert_eq!(priority, 110); }); @@ -646,13 +694,16 @@ fn should_alter_operational_priority() { class: DispatchClass::Operational, pays_fee: Pays::Yes, }; - - let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; + let priority = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &op, len) + .unwrap() + .priority; assert_eq!(priority, 5810); - let ext = Ext::from(2 * tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; + let priority = ChargeTransactionPayment::(2 * tip) + .validate(&2, CALL, &op, len) + .unwrap() + .priority; assert_eq!(priority, 6110); }); } @@ -668,8 +719,11 @@ fn no_tip_has_some_priority() { class: DispatchClass::Normal, pays_fee: Pays::Yes, }; - let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; + let priority = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &normal, len) + .unwrap() + .priority; + assert_eq!(priority, 10); }); @@ -679,8 +733,10 @@ fn no_tip_has_some_priority() { class: DispatchClass::Operational, pays_fee: Pays::Yes, }; - let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; + let priority = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &op, len) + .unwrap() + .priority; assert_eq!(priority, 5510); }); } @@ -688,8 +744,8 @@ fn no_tip_has_some_priority() { #[test] fn higher_tip_have_higher_priority() { let get_priorities = |tip: u64| { - let mut pri1 = 0; - let mut pri2 = 0; + let mut priority1 = 0; + let mut priority2 = 0; let len = 10; ExtBuilder::default().balance_factor(100).build().execute_with(|| { let normal = DispatchInfo { @@ -697,8 +753,10 @@ fn higher_tip_have_higher_priority() { class: DispatchClass::Normal, pays_fee: Pays::Yes, }; - let ext = Ext::from(tip); - pri1 = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; + priority1 = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &normal, len) + .unwrap() + .priority; }); ExtBuilder::default().balance_factor(100).build().execute_with(|| { @@ -707,11 +765,13 @@ fn higher_tip_have_higher_priority() { class: DispatchClass::Operational, pays_fee: Pays::Yes, }; - let ext = Ext::from(tip); - pri2 = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; + priority2 = ChargeTransactionPayment::(tip) + .validate(&2, CALL, &op, len) + .unwrap() + .priority; }); - (pri1, pri2) + (priority1, priority2) }; let mut prev_priorities = get_priorities(0); @@ -739,11 +799,19 @@ fn post_info_can_change_pays_fee() { >::put(Multiplier::saturating_from_rational(5, 4)); - let post_info = ChargeTransactionPayment::::from(tip) - .test_run(Some(2).into(), CALL, &info, len, |_| Ok(post_info)) - .unwrap() + let pre = ChargeTransactionPayment::::from(tip) + .pre_dispatch(&2, CALL, &info, len) .unwrap(); + ChargeTransactionPayment::::post_dispatch( + Some(pre), + &info, + &post_info, + len, + &Ok(()), + ) + .unwrap(); + let refund_based_fee = prev_balance - Balances::free_balance(2); let actual_fee = Pallet::::compute_actual_fee(len as u32, &info, &post_info, tip); diff --git a/substrate/frame/transaction-payment/src/types.rs b/substrate/frame/transaction-payment/src/types.rs index bfb3012fef0..25cecc58a63 100644 --- a/substrate/frame/transaction-payment/src/types.rs +++ b/substrate/frame/transaction-payment/src/types.rs @@ -112,7 +112,7 @@ pub struct RuntimeDispatchInfo /// The inclusion fee of this dispatch. /// /// This does not include a tip or anything else that - /// depends on the signature (i.e. depends on a `TransactionExtension`). + /// depends on the signature (i.e. depends on a `SignedExtension`). #[cfg_attr(feature = "std", serde(with = "serde_balance"))] pub partial_fee: Balance, } diff --git a/substrate/frame/transaction-payment/src/weights.rs b/substrate/frame/transaction-payment/src/weights.rs deleted file mode 100644 index bcffb2eb331..00000000000 --- a/substrate/frame/transaction-payment/src/weights.rs +++ /dev/null @@ -1,92 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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_transaction_payment` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` - -// Executed Command: -// ./target/production/substrate-node -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_transaction_payment -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/transaction-payment/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for `pallet_transaction_payment`. -pub trait WeightInfo { - fn charge_transaction_payment() -> Weight; -} - -/// Weights for `pallet_transaction_payment` using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `248` - // Estimated: `1733` - // Minimum execution time: 40_506_000 picoseconds. - Weight::from_parts(41_647_000, 1733) - .saturating_add(T::DbWeight::get().reads(3_u64)) - } -} - -// For backwards compatibility and tests. -impl WeightInfo for () { - /// Storage: `TransactionPayment::NextFeeMultiplier` (r:1 w:0) - /// Proof: `TransactionPayment::NextFeeMultiplier` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Authorship::Author` (r:1 w:0) - /// Proof: `Authorship::Author` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `System::Digest` (r:1 w:0) - /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - fn charge_transaction_payment() -> Weight { - // Proof Size summary in bytes: - // Measured: `248` - // Estimated: `1733` - // Minimum execution time: 40_506_000 picoseconds. - Weight::from_parts(41_647_000, 1733) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - } -} diff --git a/substrate/frame/transaction-storage/src/weights.rs b/substrate/frame/transaction-storage/src/weights.rs index bfbed62c5a3..519317177c4 100644 --- a/substrate/frame/transaction-storage/src/weights.rs +++ b/substrate/frame/transaction-storage/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_transaction_storage` +//! Autogenerated weights for pallet_transaction_storage //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/transaction-storage/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/transaction-storage/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,133 +50,125 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_transaction_storage`. +/// Weight functions needed for pallet_transaction_storage. pub trait WeightInfo { fn store(l: u32, ) -> Weight; fn renew() -> Weight; fn check_proof_max() -> Weight; } -/// Weights for `pallet_transaction_storage` using the Substrate node and recommended hardware. +/// Weights for pallet_transaction_storage using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `TransactionStorage::ByteFee` (r:1 w:0) - /// Proof: `TransactionStorage::ByteFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::EntryFee` (r:1 w:0) - /// Proof: `TransactionStorage::EntryFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::BlockTransactions` (r:1 w:1) - /// Proof: `TransactionStorage::BlockTransactions` (`max_values`: Some(1), `max_size`: Some(36866), added: 37361, mode: `MaxEncodedLen`) + /// Storage: TransactionStorage ByteFee (r:1 w:0) + /// Proof: TransactionStorage ByteFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: TransactionStorage EntryFee (r:1 w:0) + /// Proof: TransactionStorage EntryFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: TransactionStorage BlockTransactions (r:1 w:1) + /// Proof: TransactionStorage BlockTransactions (max_values: Some(1), max_size: Some(36866), added: 37361, mode: MaxEncodedLen) /// The range of component `l` is `[1, 8388608]`. fn store(l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `242` + // Measured: `176` // Estimated: `38351` - // Minimum execution time: 57_912_000 picoseconds. - Weight::from_parts(58_642_000, 38351) + // Minimum execution time: 34_844_000 picoseconds. + Weight::from_parts(35_489_000, 38351) // Standard Error: 11 - .saturating_add(Weight::from_parts(6_778, 0).saturating_mul(l.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(6_912, 0).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `TransactionStorage::Transactions` (r:1 w:0) - /// Proof: `TransactionStorage::Transactions` (`max_values`: None, `max_size`: Some(36886), added: 39361, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::ByteFee` (r:1 w:0) - /// Proof: `TransactionStorage::ByteFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::EntryFee` (r:1 w:0) - /// Proof: `TransactionStorage::EntryFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::BlockTransactions` (r:1 w:1) - /// Proof: `TransactionStorage::BlockTransactions` (`max_values`: Some(1), `max_size`: Some(36866), added: 37361, mode: `MaxEncodedLen`) + /// Storage: TransactionStorage Transactions (r:1 w:0) + /// Proof: TransactionStorage Transactions (max_values: None, max_size: Some(36886), added: 39361, mode: MaxEncodedLen) + /// Storage: TransactionStorage ByteFee (r:1 w:0) + /// Proof: TransactionStorage ByteFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: TransactionStorage EntryFee (r:1 w:0) + /// Proof: TransactionStorage EntryFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: TransactionStorage BlockTransactions (r:1 w:1) + /// Proof: TransactionStorage BlockTransactions (max_values: Some(1), max_size: Some(36866), added: 37361, mode: MaxEncodedLen) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `430` + // Measured: `326` // Estimated: `40351` - // Minimum execution time: 72_571_000 picoseconds. - Weight::from_parts(74_832_000, 40351) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Minimum execution time: 48_244_000 picoseconds. + Weight::from_parts(50_939_000, 40351) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `TransactionStorage::ProofChecked` (r:1 w:1) - /// Proof: `TransactionStorage::ProofChecked` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::StoragePeriod` (r:1 w:0) - /// Proof: `TransactionStorage::StoragePeriod` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::ChunkCount` (r:1 w:0) - /// Proof: `TransactionStorage::ChunkCount` (`max_values`: None, `max_size`: Some(24), added: 2499, mode: `MaxEncodedLen`) - /// Storage: `System::ParentHash` (r:1 w:0) - /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::Transactions` (r:1 w:0) - /// Proof: `TransactionStorage::Transactions` (`max_values`: None, `max_size`: Some(36886), added: 39361, mode: `MaxEncodedLen`) + /// Storage: TransactionStorage ProofChecked (r:1 w:1) + /// Proof: TransactionStorage ProofChecked (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: TransactionStorage StoragePeriod (r:1 w:0) + /// Proof: TransactionStorage StoragePeriod (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: TransactionStorage ChunkCount (r:1 w:0) + /// Proof: TransactionStorage ChunkCount (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen) + /// Storage: System ParentHash (r:1 w:0) + /// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TransactionStorage Transactions (r:1 w:0) + /// Proof: TransactionStorage Transactions (max_values: None, max_size: Some(36886), added: 39361, mode: MaxEncodedLen) fn check_proof_max() -> Weight { // Proof Size summary in bytes: - // Measured: `37211` + // Measured: `37145` // Estimated: `40351` - // Minimum execution time: 65_985_000 picoseconds. - Weight::from_parts(72_960_000, 40351) + // Minimum execution time: 80_913_000 picoseconds. + Weight::from_parts(84_812_000, 40351) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `TransactionStorage::ByteFee` (r:1 w:0) - /// Proof: `TransactionStorage::ByteFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::EntryFee` (r:1 w:0) - /// Proof: `TransactionStorage::EntryFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::BlockTransactions` (r:1 w:1) - /// Proof: `TransactionStorage::BlockTransactions` (`max_values`: Some(1), `max_size`: Some(36866), added: 37361, mode: `MaxEncodedLen`) + /// Storage: TransactionStorage ByteFee (r:1 w:0) + /// Proof: TransactionStorage ByteFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: TransactionStorage EntryFee (r:1 w:0) + /// Proof: TransactionStorage EntryFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: TransactionStorage BlockTransactions (r:1 w:1) + /// Proof: TransactionStorage BlockTransactions (max_values: Some(1), max_size: Some(36866), added: 37361, mode: MaxEncodedLen) /// The range of component `l` is `[1, 8388608]`. fn store(l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `242` + // Measured: `176` // Estimated: `38351` - // Minimum execution time: 57_912_000 picoseconds. - Weight::from_parts(58_642_000, 38351) + // Minimum execution time: 34_844_000 picoseconds. + Weight::from_parts(35_489_000, 38351) // Standard Error: 11 - .saturating_add(Weight::from_parts(6_778, 0).saturating_mul(l.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(6_912, 0).saturating_mul(l.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `TransactionStorage::Transactions` (r:1 w:0) - /// Proof: `TransactionStorage::Transactions` (`max_values`: None, `max_size`: Some(36886), added: 39361, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::ByteFee` (r:1 w:0) - /// Proof: `TransactionStorage::ByteFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::EntryFee` (r:1 w:0) - /// Proof: `TransactionStorage::EntryFee` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::BlockTransactions` (r:1 w:1) - /// Proof: `TransactionStorage::BlockTransactions` (`max_values`: Some(1), `max_size`: Some(36866), added: 37361, mode: `MaxEncodedLen`) + /// Storage: TransactionStorage Transactions (r:1 w:0) + /// Proof: TransactionStorage Transactions (max_values: None, max_size: Some(36886), added: 39361, mode: MaxEncodedLen) + /// Storage: TransactionStorage ByteFee (r:1 w:0) + /// Proof: TransactionStorage ByteFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: TransactionStorage EntryFee (r:1 w:0) + /// Proof: TransactionStorage EntryFee (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: TransactionStorage BlockTransactions (r:1 w:1) + /// Proof: TransactionStorage BlockTransactions (max_values: Some(1), max_size: Some(36866), added: 37361, mode: MaxEncodedLen) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `430` + // Measured: `326` // Estimated: `40351` - // Minimum execution time: 72_571_000 picoseconds. - Weight::from_parts(74_832_000, 40351) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Minimum execution time: 48_244_000 picoseconds. + Weight::from_parts(50_939_000, 40351) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `TransactionStorage::ProofChecked` (r:1 w:1) - /// Proof: `TransactionStorage::ProofChecked` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::StoragePeriod` (r:1 w:0) - /// Proof: `TransactionStorage::StoragePeriod` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::ChunkCount` (r:1 w:0) - /// Proof: `TransactionStorage::ChunkCount` (`max_values`: None, `max_size`: Some(24), added: 2499, mode: `MaxEncodedLen`) - /// Storage: `System::ParentHash` (r:1 w:0) - /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `TransactionStorage::Transactions` (r:1 w:0) - /// Proof: `TransactionStorage::Transactions` (`max_values`: None, `max_size`: Some(36886), added: 39361, mode: `MaxEncodedLen`) + /// Storage: TransactionStorage ProofChecked (r:1 w:1) + /// Proof: TransactionStorage ProofChecked (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: TransactionStorage StoragePeriod (r:1 w:0) + /// Proof: TransactionStorage StoragePeriod (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: TransactionStorage ChunkCount (r:1 w:0) + /// Proof: TransactionStorage ChunkCount (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen) + /// Storage: System ParentHash (r:1 w:0) + /// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: TransactionStorage Transactions (r:1 w:0) + /// Proof: TransactionStorage Transactions (max_values: None, max_size: Some(36886), added: 39361, mode: MaxEncodedLen) fn check_proof_max() -> Weight { // Proof Size summary in bytes: - // Measured: `37211` + // Measured: `37145` // Estimated: `40351` - // Minimum execution time: 65_985_000 picoseconds. - Weight::from_parts(72_960_000, 40351) + // Minimum execution time: 80_913_000 picoseconds. + Weight::from_parts(84_812_000, 40351) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/treasury/src/weights.rs b/substrate/frame/treasury/src/weights.rs index 8ef4f89fd65..030e18980eb 100644 --- a/substrate/frame/treasury/src/weights.rs +++ b/substrate/frame/treasury/src/weights.rs @@ -15,31 +15,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_treasury` +//! Autogenerated weights for pallet_treasury //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-07-07, STEPS: `20`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `cob`, CPU: `` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/debug/substrate // benchmark // pallet // --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_treasury -// --no-storage-info -// --no-median-slopes -// --no-min-squares +// --steps=20 +// --repeat=2 +// --pallet=pallet-treasury // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/treasury/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/treasury/src/._weights.rs +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +45,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_treasury`. +/// Weight functions needed for pallet_treasury. pub trait WeightInfo { fn spend_local() -> Weight; fn propose_spend() -> Weight; @@ -63,304 +59,304 @@ pub trait WeightInfo { fn void_spend() -> Weight; } -/// Weights for `pallet_treasury` using the Substrate node and recommended hardware. +/// Weights for pallet_treasury using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Treasury::ProposalCount` (r:1 w:1) - /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:0 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: Treasury ProposalCount (r:1 w:1) + /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:0 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) fn spend_local() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1887` - // Minimum execution time: 11_686_000 picoseconds. - Weight::from_parts(12_138_000, 1887) + // Minimum execution time: 179_000_000 picoseconds. + Weight::from_parts(190_000_000, 1887) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `Treasury::ProposalCount` (r:1 w:1) - /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:0 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: Treasury ProposalCount (r:1 w:1) + /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:0 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) fn propose_spend() -> Weight { // Proof Size summary in bytes: // Measured: `177` // Estimated: `1489` - // Minimum execution time: 23_773_000 picoseconds. - Weight::from_parts(24_801_000, 1489) + // Minimum execution time: 349_000_000 picoseconds. + Weight::from_parts(398_000_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Treasury::Proposals` (r:1 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Treasury Proposals (r:1 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn reject_proposal() -> Weight { // Proof Size summary in bytes: // Measured: `335` // Estimated: `3593` - // Minimum execution time: 24_533_000 picoseconds. - Weight::from_parts(25_731_000, 3593) + // Minimum execution time: 367_000_000 picoseconds. + Weight::from_parts(388_000_000, 3593) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Treasury::Proposals` (r:1 w:0) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Proposals (r:1 w:0) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `504 + p * (8 ±0)` + // Measured: `483 + p * (9 ±0)` // Estimated: `3573` - // Minimum execution time: 8_245_000 picoseconds. - Weight::from_parts(11_300_222, 3573) - // Standard Error: 1_080 - .saturating_add(Weight::from_parts(71_375, 0).saturating_mul(p.into())) + // Minimum execution time: 111_000_000 picoseconds. + Weight::from_parts(108_813_243, 3573) + // Standard Error: 147_887 + .saturating_add(Weight::from_parts(683_216, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) fn remove_approval() -> Weight { // Proof Size summary in bytes: // Measured: `161` // Estimated: `1887` - // Minimum execution time: 6_231_000 picoseconds. - Weight::from_parts(6_517_000, 1887) + // Minimum execution time: 71_000_000 picoseconds. + Weight::from_parts(78_000_000, 1887) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Treasury::Deactivated` (r:1 w:1) - /// Proof: `Treasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:99 w:99) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:198 w:198) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Deactivated (r:1 w:1) + /// Proof: Treasury Deactivated (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:99 w:99) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: System Account (r:198 w:198) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyApprovals (r:1 w:1) + /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) /// The range of component `p` is `[0, 99]`. fn on_initialize_proposals(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `451 + p * (251 ±0)` + // Measured: `427 + p * (251 ±0)` // Estimated: `1887 + p * (5206 ±0)` - // Minimum execution time: 30_729_000 picoseconds. - Weight::from_parts(37_861_389, 1887) - // Standard Error: 18_741 - .saturating_add(Weight::from_parts(31_377_118, 0).saturating_mul(p.into())) + // Minimum execution time: 614_000_000 picoseconds. + Weight::from_parts(498_501_558, 1887) + // Standard Error: 1_070_260 + .saturating_add(Weight::from_parts(599_011_690, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(p.into())) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:0) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) - /// Storage: `Treasury::SpendCount` (r:1 w:1) - /// Proof: `Treasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Spends` (r:0 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:0) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: Treasury SpendCount (r:1 w:1) + /// Proof: Treasury SpendCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Spends (r:0 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn spend() -> Weight { // Proof Size summary in bytes: // Measured: `140` // Estimated: `3501` - // Minimum execution time: 13_700_000 picoseconds. - Weight::from_parts(14_519_000, 3501) + // Minimum execution time: 214_000_000 picoseconds. + Weight::from_parts(216_000_000, 3501) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn payout() -> Weight { // Proof Size summary in bytes: - // Measured: `709` + // Measured: `705` // Estimated: `6208` - // Minimum execution time: 54_888_000 picoseconds. - Weight::from_parts(55_966_000, 6208) + // Minimum execution time: 760_000_000 picoseconds. + Weight::from_parts(822_000_000, 6208) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn check_status() -> Weight { // Proof Size summary in bytes: - // Measured: `198` - // Estimated: `3538` - // Minimum execution time: 11_802_000 picoseconds. - Weight::from_parts(12_421_000, 3538) + // Measured: `194` + // Estimated: `3534` + // Minimum execution time: 153_000_000 picoseconds. + Weight::from_parts(160_000_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn void_spend() -> Weight { // Proof Size summary in bytes: - // Measured: `198` - // Estimated: `3538` - // Minimum execution time: 10_571_000 picoseconds. - Weight::from_parts(11_052_000, 3538) + // Measured: `194` + // Estimated: `3534` + // Minimum execution time: 147_000_000 picoseconds. + Weight::from_parts(181_000_000, 3534) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Treasury::ProposalCount` (r:1 w:1) - /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:0 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: Treasury ProposalCount (r:1 w:1) + /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:0 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) fn spend_local() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1887` - // Minimum execution time: 11_686_000 picoseconds. - Weight::from_parts(12_138_000, 1887) + // Minimum execution time: 179_000_000 picoseconds. + Weight::from_parts(190_000_000, 1887) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `Treasury::ProposalCount` (r:1 w:1) - /// Proof: `Treasury::ProposalCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:0 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) + /// Storage: Treasury ProposalCount (r:1 w:1) + /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:0 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) fn propose_spend() -> Weight { // Proof Size summary in bytes: // Measured: `177` // Estimated: `1489` - // Minimum execution time: 23_773_000 picoseconds. - Weight::from_parts(24_801_000, 1489) + // Minimum execution time: 349_000_000 picoseconds. + Weight::from_parts(398_000_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Treasury::Proposals` (r:1 w:1) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Treasury Proposals (r:1 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn reject_proposal() -> Weight { // Proof Size summary in bytes: // Measured: `335` // Estimated: `3593` - // Minimum execution time: 24_533_000 picoseconds. - Weight::from_parts(25_731_000, 3593) + // Minimum execution time: 367_000_000 picoseconds. + Weight::from_parts(388_000_000, 3593) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Treasury::Proposals` (r:1 w:0) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Proposals (r:1 w:0) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `504 + p * (8 ±0)` + // Measured: `483 + p * (9 ±0)` // Estimated: `3573` - // Minimum execution time: 8_245_000 picoseconds. - Weight::from_parts(11_300_222, 3573) - // Standard Error: 1_080 - .saturating_add(Weight::from_parts(71_375, 0).saturating_mul(p.into())) + // Minimum execution time: 111_000_000 picoseconds. + Weight::from_parts(108_813_243, 3573) + // Standard Error: 147_887 + .saturating_add(Weight::from_parts(683_216, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) fn remove_approval() -> Weight { // Proof Size summary in bytes: // Measured: `161` // Estimated: `1887` - // Minimum execution time: 6_231_000 picoseconds. - Weight::from_parts(6_517_000, 1887) + // Minimum execution time: 71_000_000 picoseconds. + Weight::from_parts(78_000_000, 1887) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Treasury::Deactivated` (r:1 w:1) - /// Proof: `Treasury::Deactivated` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Approvals` (r:1 w:1) - /// Proof: `Treasury::Approvals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Proposals` (r:99 w:99) - /// Proof: `Treasury::Proposals` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:198 w:198) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// Storage: `Bounties::BountyApprovals` (r:1 w:1) - /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) + /// Storage: Treasury Deactivated (r:1 w:1) + /// Proof: Treasury Deactivated (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:99 w:99) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(108), added: 2583, mode: MaxEncodedLen) + /// Storage: System Account (r:198 w:198) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: Bounties BountyApprovals (r:1 w:1) + /// Proof: Bounties BountyApprovals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) /// The range of component `p` is `[0, 99]`. fn on_initialize_proposals(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `451 + p * (251 ±0)` + // Measured: `427 + p * (251 ±0)` // Estimated: `1887 + p * (5206 ±0)` - // Minimum execution time: 30_729_000 picoseconds. - Weight::from_parts(37_861_389, 1887) - // Standard Error: 18_741 - .saturating_add(Weight::from_parts(31_377_118, 0).saturating_mul(p.into())) + // Minimum execution time: 614_000_000 picoseconds. + Weight::from_parts(498_501_558, 1887) + // Standard Error: 1_070_260 + .saturating_add(Weight::from_parts(599_011_690, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(p.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(p.into())) } - /// Storage: `AssetRate::ConversionRateToNative` (r:1 w:0) - /// Proof: `AssetRate::ConversionRateToNative` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) - /// Storage: `Treasury::SpendCount` (r:1 w:1) - /// Proof: `Treasury::SpendCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Treasury::Spends` (r:0 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: AssetRate ConversionRateToNative (r:1 w:0) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: Treasury SpendCount (r:1 w:1) + /// Proof: Treasury SpendCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Spends (r:0 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn spend() -> Weight { // Proof Size summary in bytes: // Measured: `140` // Estimated: `3501` - // Minimum execution time: 13_700_000 picoseconds. - Weight::from_parts(14_519_000, 3501) + // Minimum execution time: 214_000_000 picoseconds. + Weight::from_parts(216_000_000, 3501) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, 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:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, 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:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) fn payout() -> Weight { // Proof Size summary in bytes: - // Measured: `709` + // Measured: `705` // Estimated: `6208` - // Minimum execution time: 54_888_000 picoseconds. - Weight::from_parts(55_966_000, 6208) + // Minimum execution time: 760_000_000 picoseconds. + Weight::from_parts(822_000_000, 6208) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn check_status() -> Weight { // Proof Size summary in bytes: - // Measured: `198` - // Estimated: `3538` - // Minimum execution time: 11_802_000 picoseconds. - Weight::from_parts(12_421_000, 3538) + // Measured: `194` + // Estimated: `3534` + // Minimum execution time: 153_000_000 picoseconds. + Weight::from_parts(160_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: `Treasury::Spends` (r:1 w:1) - /// Proof: `Treasury::Spends` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: Treasury Spends (r:1 w:1) + /// Proof: Treasury Spends (max_values: None, max_size: Some(69), added: 2544, mode: MaxEncodedLen) fn void_spend() -> Weight { // Proof Size summary in bytes: - // Measured: `198` - // Estimated: `3538` - // Minimum execution time: 10_571_000 picoseconds. - Weight::from_parts(11_052_000, 3538) + // Measured: `194` + // Estimated: `3534` + // Minimum execution time: 147_000_000 picoseconds. + Weight::from_parts(181_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/tx-pause/src/weights.rs b/substrate/frame/tx-pause/src/weights.rs index 14fead12a8e..b733e64b159 100644 --- a/substrate/frame/tx-pause/src/weights.rs +++ b/substrate/frame/tx-pause/src/weights.rs @@ -17,29 +17,27 @@ //! Autogenerated weights for `pallet_tx_pause` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-aahe6cbd-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_tx_pause -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/tx-pause/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_tx_pause +// --chain=dev +// --header=./HEADER-APACHE2 +// --output=./frame/tx-pause/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -64,8 +62,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3` // Estimated: `3997` - // Minimum execution time: 12_014_000 picoseconds. - Weight::from_parts(12_980_000, 3997) + // Minimum execution time: 15_096_000 picoseconds. + Weight::from_parts(15_437_000, 3997) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -75,8 +73,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `565` // Estimated: `3997` - // Minimum execution time: 17_955_000 picoseconds. - Weight::from_parts(18_348_000, 3997) + // Minimum execution time: 21_546_000 picoseconds. + Weight::from_parts(22_178_000, 3997) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -90,8 +88,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3` // Estimated: `3997` - // Minimum execution time: 12_014_000 picoseconds. - Weight::from_parts(12_980_000, 3997) + // Minimum execution time: 15_096_000 picoseconds. + Weight::from_parts(15_437_000, 3997) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -101,8 +99,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `565` // Estimated: `3997` - // Minimum execution time: 17_955_000 picoseconds. - Weight::from_parts(18_348_000, 3997) + // Minimum execution time: 21_546_000 picoseconds. + Weight::from_parts(22_178_000, 3997) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate/frame/uniques/src/weights.rs b/substrate/frame/uniques/src/weights.rs index 6c7b60b82e5..eb80ee550a1 100644 --- a/substrate/frame/uniques/src/weights.rs +++ b/substrate/frame/uniques/src/weights.rs @@ -17,29 +17,27 @@ //! Autogenerated weights for `pallet_uniques` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-07-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-gghbxkbs-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_uniques -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/uniques/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_uniques +// --chain=dev +// --header=./HEADER-APACHE2 +// --output=./frame/uniques/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -90,8 +88,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `249` // Estimated: `3643` - // Minimum execution time: 27_960_000 picoseconds. - Weight::from_parts(28_781_000, 3643) + // Minimum execution time: 31_393_000 picoseconds. + Weight::from_parts(32_933_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -103,8 +101,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3643` - // Minimum execution time: 11_970_000 picoseconds. - Weight::from_parts(12_512_000, 3643) + // Minimum execution time: 14_827_000 picoseconds. + Weight::from_parts(15_273_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -113,13 +111,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Uniques::Asset` (r:1001 w:1000) /// Proof: `Uniques::Asset` (`max_values`: None, `max_size`: Some(122), added: 2597, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1000 w:1000) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1000 w:1000) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassAccount` (r:0 w:1) /// Proof: `Uniques::ClassAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:0 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Uniques::Account` (r:0 w:1000) /// Proof: `Uniques::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Uniques::CollectionMaxSupply` (r:0 w:1) @@ -130,15 +128,15 @@ impl WeightInfo for SubstrateWeight { fn destroy(n: u32, m: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `418 + a * (107 ±0) + m * (56 ±0) + n * (76 ±0)` - // Estimated: `3643 + a * (2647 ±0) + m * (2662 ±0) + n * (2597 ±0)` - // Minimum execution time: 2_979_858_000 picoseconds. - Weight::from_parts(3_007_268_000, 3643) - // Standard Error: 29_899 - .saturating_add(Weight::from_parts(6_943_612, 0).saturating_mul(n.into())) - // Standard Error: 29_899 - .saturating_add(Weight::from_parts(398_114, 0).saturating_mul(m.into())) - // Standard Error: 29_899 - .saturating_add(Weight::from_parts(369_941, 0).saturating_mul(a.into())) + // Estimated: `3643 + a * (2839 ±0) + m * (2583 ±0) + n * (2597 ±0)` + // Minimum execution time: 3_281_673_000 picoseconds. + Weight::from_parts(3_443_387_000, 3643) + // Standard Error: 41_937 + .saturating_add(Weight::from_parts(7_914_842, 0).saturating_mul(n.into())) + // Standard Error: 41_937 + .saturating_add(Weight::from_parts(519_960, 0).saturating_mul(m.into())) + // Standard Error: 41_937 + .saturating_add(Weight::from_parts(462_690, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) @@ -147,8 +145,8 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) - .saturating_add(Weight::from_parts(0, 2647).saturating_mul(a.into())) - .saturating_add(Weight::from_parts(0, 2662).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 2839).saturating_mul(a.into())) + .saturating_add(Weight::from_parts(0, 2583).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 2597).saturating_mul(n.into())) } /// Storage: `Uniques::Asset` (r:1 w:1) @@ -163,8 +161,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 32_733_000 picoseconds. - Weight::from_parts(33_487_000, 3643) + // Minimum execution time: 38_122_000 picoseconds. + Weight::from_parts(38_924_000, 3643) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -180,8 +178,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 34_202_000 picoseconds. - Weight::from_parts(35_146_000, 3643) + // Minimum execution time: 38_835_000 picoseconds. + Weight::from_parts(39_754_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -197,8 +195,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 24_285_000 picoseconds. - Weight::from_parts(25_300_000, 3643) + // Minimum execution time: 27_032_000 picoseconds. + Weight::from_parts(27_793_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -211,10 +209,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `805 + i * (76 ±0)` // Estimated: `3643 + i * (2597 ±0)` - // Minimum execution time: 11_641_000 picoseconds. - Weight::from_parts(12_261_000, 3643) - // Standard Error: 18_897 - .saturating_add(Weight::from_parts(15_263_570, 0).saturating_mul(i.into())) + // Minimum execution time: 14_737_000 picoseconds. + Weight::from_parts(15_070_000, 3643) + // Standard Error: 22_500 + .saturating_add(Weight::from_parts(18_855_468, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -229,8 +227,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 16_122_000 picoseconds. - Weight::from_parts(16_627_000, 3643) + // Minimum execution time: 18_664_000 picoseconds. + Weight::from_parts(19_455_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -242,8 +240,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 15_824_000 picoseconds. - Weight::from_parts(16_522_000, 3643) + // Minimum execution time: 18_247_000 picoseconds. + Weight::from_parts(18_763_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -253,8 +251,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 10_802_000 picoseconds. - Weight::from_parts(11_206_000, 3643) + // Minimum execution time: 13_219_000 picoseconds. + Weight::from_parts(13_923_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -264,8 +262,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 10_805_000 picoseconds. - Weight::from_parts(11_340_000, 3643) + // Minimum execution time: 13_376_000 picoseconds. + Weight::from_parts(13_904_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -273,18 +271,16 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Uniques::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassAccount` (r:0 w:2) /// Proof: `Uniques::ClassAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `597` + // Measured: `423` // Estimated: `3643` - // Minimum execution time: 24_213_000 picoseconds. - Weight::from_parts(25_547_000, 3643) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Minimum execution time: 22_353_000 picoseconds. + Weight::from_parts(23_222_000, 3643) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) @@ -292,8 +288,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 11_256_000 picoseconds. - Weight::from_parts(11_585_000, 3643) + // Minimum execution time: 14_072_000 picoseconds. + Weight::from_parts(14_619_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -305,90 +301,90 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 14_616_000 picoseconds. - Weight::from_parts(15_064_000, 3643) + // Minimum execution time: 17_081_000 picoseconds. + Weight::from_parts(17_698_000, 3643) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:0) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1 w:1) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `626` - // Estimated: `3652` - // Minimum execution time: 35_640_000 picoseconds. - Weight::from_parts(37_007_000, 3652) + // Measured: `547` + // Estimated: `3829` + // Minimum execution time: 41_501_000 picoseconds. + Weight::from_parts(43_101_000, 3829) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:0) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1 w:1) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `823` - // Estimated: `3652` - // Minimum execution time: 34_410_000 picoseconds. - Weight::from_parts(35_431_000, 3652) + // Measured: `936` + // Estimated: `3829` + // Minimum execution time: 39_722_000 picoseconds. + Weight::from_parts(40_390_000, 3829) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:1) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `415` - // Estimated: `3652` - // Minimum execution time: 26_187_000 picoseconds. - Weight::from_parts(27_837_000, 3652) + // Estimated: `3643` + // Minimum execution time: 30_726_000 picoseconds. + Weight::from_parts(31_557_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:1) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `626` - // Estimated: `3652` - // Minimum execution time: 26_640_000 picoseconds. - Weight::from_parts(27_688_000, 3652) + // Measured: `547` + // Estimated: `3643` + // Minimum execution time: 31_303_000 picoseconds. + Weight::from_parts(32_389_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:1 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 26_781_000 picoseconds. - Weight::from_parts(27_628_000, 3643) + // Minimum execution time: 32_155_000 picoseconds. + Weight::from_parts(32_885_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:0) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:1 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `540` + // Measured: `461` // Estimated: `3643` - // Minimum execution time: 26_295_000 picoseconds. - Weight::from_parts(26_903_000, 3643) + // Minimum execution time: 30_044_000 picoseconds. + Weight::from_parts(31_405_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -400,8 +396,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 16_678_000 picoseconds. - Weight::from_parts(17_548_000, 3643) + // Minimum execution time: 18_904_000 picoseconds. + Weight::from_parts(19_687_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -413,8 +409,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `528` // Estimated: `3643` - // Minimum execution time: 16_408_000 picoseconds. - Weight::from_parts(16_957_000, 3643) + // Minimum execution time: 19_144_000 picoseconds. + Weight::from_parts(19_706_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -424,8 +420,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3517` - // Minimum execution time: 12_568_000 picoseconds. - Weight::from_parts(12_960_000, 3517) + // Minimum execution time: 15_339_000 picoseconds. + Weight::from_parts(15_918_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -437,8 +433,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 13_110_000 picoseconds. - Weight::from_parts(13_620_000, 3643) + // Minimum execution time: 15_387_000 picoseconds. + Weight::from_parts(15_726_000, 3643) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -450,8 +446,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `326` // Estimated: `3587` - // Minimum execution time: 13_568_000 picoseconds. - Weight::from_parts(14_211_000, 3587) + // Minimum execution time: 15_873_000 picoseconds. + Weight::from_parts(16_860_000, 3587) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -467,8 +463,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `607` // Estimated: `3643` - // Minimum execution time: 32_660_000 picoseconds. - Weight::from_parts(33_734_000, 3643) + // Minimum execution time: 37_245_000 picoseconds. + Weight::from_parts(38_383_000, 3643) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -484,8 +480,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `249` // Estimated: `3643` - // Minimum execution time: 27_960_000 picoseconds. - Weight::from_parts(28_781_000, 3643) + // Minimum execution time: 31_393_000 picoseconds. + Weight::from_parts(32_933_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -497,8 +493,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3643` - // Minimum execution time: 11_970_000 picoseconds. - Weight::from_parts(12_512_000, 3643) + // Minimum execution time: 14_827_000 picoseconds. + Weight::from_parts(15_273_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -507,13 +503,13 @@ impl WeightInfo for () { /// Storage: `Uniques::Asset` (r:1001 w:1000) /// Proof: `Uniques::Asset` (`max_values`: None, `max_size`: Some(122), added: 2597, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1000 w:1000) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1000 w:1000) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassAccount` (r:0 w:1) /// Proof: `Uniques::ClassAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:0 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Uniques::Account` (r:0 w:1000) /// Proof: `Uniques::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Uniques::CollectionMaxSupply` (r:0 w:1) @@ -524,15 +520,15 @@ impl WeightInfo for () { fn destroy(n: u32, m: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `418 + a * (107 ±0) + m * (56 ±0) + n * (76 ±0)` - // Estimated: `3643 + a * (2647 ±0) + m * (2662 ±0) + n * (2597 ±0)` - // Minimum execution time: 2_979_858_000 picoseconds. - Weight::from_parts(3_007_268_000, 3643) - // Standard Error: 29_899 - .saturating_add(Weight::from_parts(6_943_612, 0).saturating_mul(n.into())) - // Standard Error: 29_899 - .saturating_add(Weight::from_parts(398_114, 0).saturating_mul(m.into())) - // Standard Error: 29_899 - .saturating_add(Weight::from_parts(369_941, 0).saturating_mul(a.into())) + // Estimated: `3643 + a * (2839 ±0) + m * (2583 ±0) + n * (2597 ±0)` + // Minimum execution time: 3_281_673_000 picoseconds. + Weight::from_parts(3_443_387_000, 3643) + // Standard Error: 41_937 + .saturating_add(Weight::from_parts(7_914_842, 0).saturating_mul(n.into())) + // Standard Error: 41_937 + .saturating_add(Weight::from_parts(519_960, 0).saturating_mul(m.into())) + // Standard Error: 41_937 + .saturating_add(Weight::from_parts(462_690, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) @@ -541,8 +537,8 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(m.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) - .saturating_add(Weight::from_parts(0, 2647).saturating_mul(a.into())) - .saturating_add(Weight::from_parts(0, 2662).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 2839).saturating_mul(a.into())) + .saturating_add(Weight::from_parts(0, 2583).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 2597).saturating_mul(n.into())) } /// Storage: `Uniques::Asset` (r:1 w:1) @@ -557,8 +553,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 32_733_000 picoseconds. - Weight::from_parts(33_487_000, 3643) + // Minimum execution time: 38_122_000 picoseconds. + Weight::from_parts(38_924_000, 3643) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -574,8 +570,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 34_202_000 picoseconds. - Weight::from_parts(35_146_000, 3643) + // Minimum execution time: 38_835_000 picoseconds. + Weight::from_parts(39_754_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -591,8 +587,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 24_285_000 picoseconds. - Weight::from_parts(25_300_000, 3643) + // Minimum execution time: 27_032_000 picoseconds. + Weight::from_parts(27_793_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -605,10 +601,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `805 + i * (76 ±0)` // Estimated: `3643 + i * (2597 ±0)` - // Minimum execution time: 11_641_000 picoseconds. - Weight::from_parts(12_261_000, 3643) - // Standard Error: 18_897 - .saturating_add(Weight::from_parts(15_263_570, 0).saturating_mul(i.into())) + // Minimum execution time: 14_737_000 picoseconds. + Weight::from_parts(15_070_000, 3643) + // Standard Error: 22_500 + .saturating_add(Weight::from_parts(18_855_468, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -623,8 +619,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 16_122_000 picoseconds. - Weight::from_parts(16_627_000, 3643) + // Minimum execution time: 18_664_000 picoseconds. + Weight::from_parts(19_455_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -636,8 +632,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 15_824_000 picoseconds. - Weight::from_parts(16_522_000, 3643) + // Minimum execution time: 18_247_000 picoseconds. + Weight::from_parts(18_763_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -647,8 +643,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 10_802_000 picoseconds. - Weight::from_parts(11_206_000, 3643) + // Minimum execution time: 13_219_000 picoseconds. + Weight::from_parts(13_923_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -658,8 +654,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 10_805_000 picoseconds. - Weight::from_parts(11_340_000, 3643) + // Minimum execution time: 13_376_000 picoseconds. + Weight::from_parts(13_904_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -667,18 +663,16 @@ impl WeightInfo for () { /// Proof: `Uniques::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassAccount` (r:0 w:2) /// Proof: `Uniques::ClassAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `597` + // Measured: `423` // Estimated: `3643` - // Minimum execution time: 24_213_000 picoseconds. - Weight::from_parts(25_547_000, 3643) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Minimum execution time: 22_353_000 picoseconds. + Weight::from_parts(23_222_000, 3643) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) @@ -686,8 +680,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 11_256_000 picoseconds. - Weight::from_parts(11_585_000, 3643) + // Minimum execution time: 14_072_000 picoseconds. + Weight::from_parts(14_619_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -699,90 +693,90 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 14_616_000 picoseconds. - Weight::from_parts(15_064_000, 3643) + // Minimum execution time: 17_081_000 picoseconds. + Weight::from_parts(17_698_000, 3643) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:0) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1 w:1) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `626` - // Estimated: `3652` - // Minimum execution time: 35_640_000 picoseconds. - Weight::from_parts(37_007_000, 3652) + // Measured: `547` + // Estimated: `3829` + // Minimum execution time: 41_501_000 picoseconds. + Weight::from_parts(43_101_000, 3829) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:0) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) /// Storage: `Uniques::Attribute` (r:1 w:1) - /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(172), added: 2647, mode: `MaxEncodedLen`) + /// Proof: `Uniques::Attribute` (`max_values`: None, `max_size`: Some(364), added: 2839, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `823` - // Estimated: `3652` - // Minimum execution time: 34_410_000 picoseconds. - Weight::from_parts(35_431_000, 3652) + // Measured: `936` + // Estimated: `3829` + // Minimum execution time: 39_722_000 picoseconds. + Weight::from_parts(40_390_000, 3829) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:1) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `415` - // Estimated: `3652` - // Minimum execution time: 26_187_000 picoseconds. - Weight::from_parts(27_837_000, 3652) + // Estimated: `3643` + // Minimum execution time: 30_726_000 picoseconds. + Weight::from_parts(31_557_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::InstanceMetadataOf` (r:1 w:1) - /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(187), added: 2662, mode: `MaxEncodedLen`) + /// Proof: `Uniques::InstanceMetadataOf` (`max_values`: None, `max_size`: Some(108), added: 2583, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `626` - // Estimated: `3652` - // Minimum execution time: 26_640_000 picoseconds. - Weight::from_parts(27_688_000, 3652) + // Measured: `547` + // Estimated: `3643` + // Minimum execution time: 31_303_000 picoseconds. + Weight::from_parts(32_389_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:1) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:1 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 26_781_000 picoseconds. - Weight::from_parts(27_628_000, 3643) + // Minimum execution time: 32_155_000 picoseconds. + Weight::from_parts(32_885_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Uniques::Class` (r:1 w:0) /// Proof: `Uniques::Class` (`max_values`: None, `max_size`: Some(178), added: 2653, mode: `MaxEncodedLen`) /// Storage: `Uniques::ClassMetadataOf` (r:1 w:1) - /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(167), added: 2642, mode: `MaxEncodedLen`) + /// Proof: `Uniques::ClassMetadataOf` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `540` + // Measured: `461` // Estimated: `3643` - // Minimum execution time: 26_295_000 picoseconds. - Weight::from_parts(26_903_000, 3643) + // Minimum execution time: 30_044_000 picoseconds. + Weight::from_parts(31_405_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -794,8 +788,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3643` - // Minimum execution time: 16_678_000 picoseconds. - Weight::from_parts(17_548_000, 3643) + // Minimum execution time: 18_904_000 picoseconds. + Weight::from_parts(19_687_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -807,8 +801,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `528` // Estimated: `3643` - // Minimum execution time: 16_408_000 picoseconds. - Weight::from_parts(16_957_000, 3643) + // Minimum execution time: 19_144_000 picoseconds. + Weight::from_parts(19_706_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -818,8 +812,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `3517` - // Minimum execution time: 12_568_000 picoseconds. - Weight::from_parts(12_960_000, 3517) + // Minimum execution time: 15_339_000 picoseconds. + Weight::from_parts(15_918_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -831,8 +825,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `349` // Estimated: `3643` - // Minimum execution time: 13_110_000 picoseconds. - Weight::from_parts(13_620_000, 3643) + // Minimum execution time: 15_387_000 picoseconds. + Weight::from_parts(15_726_000, 3643) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -844,8 +838,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `326` // Estimated: `3587` - // Minimum execution time: 13_568_000 picoseconds. - Weight::from_parts(14_211_000, 3587) + // Minimum execution time: 15_873_000 picoseconds. + Weight::from_parts(16_860_000, 3587) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -861,8 +855,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `607` // Estimated: `3643` - // Minimum execution time: 32_660_000 picoseconds. - Weight::from_parts(33_734_000, 3643) + // Minimum execution time: 37_245_000 picoseconds. + Weight::from_parts(38_383_000, 3643) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } diff --git a/substrate/frame/utility/src/weights.rs b/substrate/frame/utility/src/weights.rs index 60b1c48f086..1a3ea6c1f7f 100644 --- a/substrate/frame/utility/src/weights.rs +++ b/substrate/frame/utility/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_utility` +//! Autogenerated weights for pallet_utility //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/utility/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/utility/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_utility`. +/// Weight functions needed for pallet_utility. pub trait WeightInfo { fn batch(c: u32, ) -> Weight; fn as_derivative() -> Weight; @@ -58,139 +59,99 @@ pub trait WeightInfo { fn force_batch(c: u32, ) -> Weight; } -/// Weights for `pallet_utility` using the Substrate node and recommended hardware. +/// Weights for pallet_utility using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 5_143_000 picoseconds. - Weight::from_parts(11_552_299, 3997) - // Standard Error: 2_325 - .saturating_add(Weight::from_parts(4_708_951, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_763_000 picoseconds. + Weight::from_parts(16_943_157, 0) + // Standard Error: 1_904 + .saturating_add(Weight::from_parts(4_653_855, 0).saturating_mul(c.into())) } - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) fn as_derivative() -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 9_103_000 picoseconds. - Weight::from_parts(9_549_000, 3997) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 5_149_000 picoseconds. + Weight::from_parts(5_268_000, 0) } - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 5_147_000 picoseconds. - Weight::from_parts(15_698_086, 3997) - // Standard Error: 3_066 - .saturating_add(Weight::from_parts(4_809_412, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_976_000 picoseconds. + Weight::from_parts(16_448_433, 0) + // Standard Error: 1_834 + .saturating_add(Weight::from_parts(4_796_983, 0).saturating_mul(c.into())) } fn dispatch_as() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_683_000 picoseconds. - Weight::from_parts(7_047_000, 0) + // Minimum execution time: 9_102_000 picoseconds. + Weight::from_parts(9_353_000, 0) } - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 4_982_000 picoseconds. - Weight::from_parts(14_474_780, 3997) - // Standard Error: 2_291 - .saturating_add(Weight::from_parts(4_632_643, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_840_000 picoseconds. + Weight::from_parts(17_748_474, 0) + // Standard Error: 2_059 + .saturating_add(Weight::from_parts(4_630_079, 0).saturating_mul(c.into())) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 5_143_000 picoseconds. - Weight::from_parts(11_552_299, 3997) - // Standard Error: 2_325 - .saturating_add(Weight::from_parts(4_708_951, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_763_000 picoseconds. + Weight::from_parts(16_943_157, 0) + // Standard Error: 1_904 + .saturating_add(Weight::from_parts(4_653_855, 0).saturating_mul(c.into())) } - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) fn as_derivative() -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 9_103_000 picoseconds. - Weight::from_parts(9_549_000, 3997) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 5_149_000 picoseconds. + Weight::from_parts(5_268_000, 0) } - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 5_147_000 picoseconds. - Weight::from_parts(15_698_086, 3997) - // Standard Error: 3_066 - .saturating_add(Weight::from_parts(4_809_412, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_976_000 picoseconds. + Weight::from_parts(16_448_433, 0) + // Standard Error: 1_834 + .saturating_add(Weight::from_parts(4_796_983, 0).saturating_mul(c.into())) } fn dispatch_as() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_683_000 picoseconds. - Weight::from_parts(7_047_000, 0) + // Minimum execution time: 9_102_000 picoseconds. + Weight::from_parts(9_353_000, 0) } - /// Storage: `SafeMode::EnteredUntil` (r:1 w:0) - /// Proof: `SafeMode::EnteredUntil` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `TxPause::PausedCalls` (r:1 w:0) - /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `MaxEncodedLen`) /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3997` - // Minimum execution time: 4_982_000 picoseconds. - Weight::from_parts(14_474_780, 3997) - // Standard Error: 2_291 - .saturating_add(Weight::from_parts(4_632_643, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_840_000 picoseconds. + Weight::from_parts(17_748_474, 0) + // Standard Error: 2_059 + .saturating_add(Weight::from_parts(4_630_079, 0).saturating_mul(c.into())) } } diff --git a/substrate/frame/vesting/src/weights.rs b/substrate/frame/vesting/src/weights.rs index d91c47ae195..ddc7db8fa61 100644 --- a/substrate/frame/vesting/src/weights.rs +++ b/substrate/frame/vesting/src/weights.rs @@ -17,28 +17,26 @@ //! Autogenerated weights for `pallet_vesting` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-vmdtonbz-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_vesting -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/vesting/src/weights.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_vesting +// --chain=dev // --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/vesting/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -77,12 +75,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `381 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 31_890_000 picoseconds. - Weight::from_parts(31_128_476, 4764) - // Standard Error: 1_193 - .saturating_add(Weight::from_parts(63_760, 0).saturating_mul(l.into())) - // Standard Error: 2_124 - .saturating_add(Weight::from_parts(57_247, 0).saturating_mul(s.into())) + // Minimum execution time: 32_846_000 picoseconds. + Weight::from_parts(30_974_459, 4764) + // Standard Error: 1_755 + .saturating_add(Weight::from_parts(73_138, 0).saturating_mul(l.into())) + // Standard Error: 3_123 + .saturating_add(Weight::from_parts(82_417, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -98,12 +96,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `381 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_958_000 picoseconds. - Weight::from_parts(33_537_005, 4764) - // Standard Error: 1_354 - .saturating_add(Weight::from_parts(60_604, 0).saturating_mul(l.into())) - // Standard Error: 2_410 - .saturating_add(Weight::from_parts(51_378, 0).saturating_mul(s.into())) + // Minimum execution time: 34_360_000 picoseconds. + Weight::from_parts(34_964_080, 4764) + // Standard Error: 1_996 + .saturating_add(Weight::from_parts(48_024, 0).saturating_mul(l.into())) + // Standard Error: 3_552 + .saturating_add(Weight::from_parts(34_411, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -121,12 +119,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `484 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_243_000 picoseconds. - Weight::from_parts(32_552_805, 4764) - // Standard Error: 1_413 - .saturating_add(Weight::from_parts(67_137, 0).saturating_mul(l.into())) - // Standard Error: 2_515 - .saturating_add(Weight::from_parts(70_000, 0).saturating_mul(s.into())) + // Minimum execution time: 33_859_000 picoseconds. + Weight::from_parts(32_950_681, 4764) + // Standard Error: 1_745 + .saturating_add(Weight::from_parts(69_323, 0).saturating_mul(l.into())) + // Standard Error: 3_105 + .saturating_add(Weight::from_parts(86_370, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -144,12 +142,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `484 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 35_396_000 picoseconds. - Weight::from_parts(35_774_949, 4764) - // Standard Error: 1_404 - .saturating_add(Weight::from_parts(55_349, 0).saturating_mul(l.into())) - // Standard Error: 2_497 - .saturating_add(Weight::from_parts(39_228, 0).saturating_mul(s.into())) + // Minimum execution time: 36_239_000 picoseconds. + Weight::from_parts(36_459_756, 4764) + // Standard Error: 2_051 + .saturating_add(Weight::from_parts(56_670, 0).saturating_mul(l.into())) + // Standard Error: 3_650 + .saturating_add(Weight::from_parts(49_663, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -167,12 +165,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 68_441_000 picoseconds. - Weight::from_parts(68_961_970, 4764) - // Standard Error: 2_509 - .saturating_add(Weight::from_parts(83_345, 0).saturating_mul(l.into())) - // Standard Error: 4_464 - .saturating_add(Weight::from_parts(124_158, 0).saturating_mul(s.into())) + // Minimum execution time: 70_330_000 picoseconds. + Weight::from_parts(71_196_328, 4764) + // Standard Error: 2_923 + .saturating_add(Weight::from_parts(67_238, 0).saturating_mul(l.into())) + // Standard Error: 5_201 + .saturating_add(Weight::from_parts(89_102, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -190,12 +188,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `658 + l * (25 ±0) + s * (36 ±0)` // Estimated: `6196` - // Minimum execution time: 70_190_000 picoseconds. - Weight::from_parts(72_355_984, 6196) - // Standard Error: 2_295 - .saturating_add(Weight::from_parts(59_968, 0).saturating_mul(l.into())) - // Standard Error: 4_084 - .saturating_add(Weight::from_parts(87_090, 0).saturating_mul(s.into())) + // Minimum execution time: 70_235_000 picoseconds. + Weight::from_parts(71_960_020, 6196) + // Standard Error: 2_493 + .saturating_add(Weight::from_parts(64_835, 0).saturating_mul(l.into())) + // Standard Error: 4_436 + .saturating_add(Weight::from_parts(102_159, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -213,12 +211,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `482 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_911_000 picoseconds. - Weight::from_parts(33_243_006, 4764) - // Standard Error: 1_199 - .saturating_add(Weight::from_parts(70_586, 0).saturating_mul(l.into())) - // Standard Error: 2_214 - .saturating_add(Weight::from_parts(60_985, 0).saturating_mul(s.into())) + // Minimum execution time: 34_352_000 picoseconds. + Weight::from_parts(33_697_027, 4764) + // Standard Error: 2_008 + .saturating_add(Weight::from_parts(79_270, 0).saturating_mul(l.into())) + // Standard Error: 3_710 + .saturating_add(Weight::from_parts(60_691, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -236,12 +234,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `482 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 36_242_000 picoseconds. - Weight::from_parts(35_812_994, 4764) - // Standard Error: 1_351 - .saturating_add(Weight::from_parts(68_256, 0).saturating_mul(l.into())) - // Standard Error: 2_496 - .saturating_add(Weight::from_parts(66_171, 0).saturating_mul(s.into())) + // Minimum execution time: 37_467_000 picoseconds. + Weight::from_parts(36_866_847, 4764) + // Standard Error: 1_692 + .saturating_add(Weight::from_parts(57_882, 0).saturating_mul(l.into())) + // Standard Error: 3_124 + .saturating_add(Weight::from_parts(80_266, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -259,12 +257,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 37_817_000 picoseconds. - Weight::from_parts(37_397_127, 4764) - // Standard Error: 1_665 - .saturating_add(Weight::from_parts(72_049, 0).saturating_mul(l.into())) - // Standard Error: 3_075 - .saturating_add(Weight::from_parts(60_973, 0).saturating_mul(s.into())) + // Minimum execution time: 41_497_000 picoseconds. + Weight::from_parts(38_763_834, 4764) + // Standard Error: 2_030 + .saturating_add(Weight::from_parts(99_580, 0).saturating_mul(l.into())) + // Standard Error: 3_750 + .saturating_add(Weight::from_parts(132_188, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -284,12 +282,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `381 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 31_890_000 picoseconds. - Weight::from_parts(31_128_476, 4764) - // Standard Error: 1_193 - .saturating_add(Weight::from_parts(63_760, 0).saturating_mul(l.into())) - // Standard Error: 2_124 - .saturating_add(Weight::from_parts(57_247, 0).saturating_mul(s.into())) + // Minimum execution time: 32_846_000 picoseconds. + Weight::from_parts(30_974_459, 4764) + // Standard Error: 1_755 + .saturating_add(Weight::from_parts(73_138, 0).saturating_mul(l.into())) + // Standard Error: 3_123 + .saturating_add(Weight::from_parts(82_417, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -305,12 +303,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `381 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_958_000 picoseconds. - Weight::from_parts(33_537_005, 4764) - // Standard Error: 1_354 - .saturating_add(Weight::from_parts(60_604, 0).saturating_mul(l.into())) - // Standard Error: 2_410 - .saturating_add(Weight::from_parts(51_378, 0).saturating_mul(s.into())) + // Minimum execution time: 34_360_000 picoseconds. + Weight::from_parts(34_964_080, 4764) + // Standard Error: 1_996 + .saturating_add(Weight::from_parts(48_024, 0).saturating_mul(l.into())) + // Standard Error: 3_552 + .saturating_add(Weight::from_parts(34_411, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -328,12 +326,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `484 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_243_000 picoseconds. - Weight::from_parts(32_552_805, 4764) - // Standard Error: 1_413 - .saturating_add(Weight::from_parts(67_137, 0).saturating_mul(l.into())) - // Standard Error: 2_515 - .saturating_add(Weight::from_parts(70_000, 0).saturating_mul(s.into())) + // Minimum execution time: 33_859_000 picoseconds. + Weight::from_parts(32_950_681, 4764) + // Standard Error: 1_745 + .saturating_add(Weight::from_parts(69_323, 0).saturating_mul(l.into())) + // Standard Error: 3_105 + .saturating_add(Weight::from_parts(86_370, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -351,12 +349,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `484 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 35_396_000 picoseconds. - Weight::from_parts(35_774_949, 4764) - // Standard Error: 1_404 - .saturating_add(Weight::from_parts(55_349, 0).saturating_mul(l.into())) - // Standard Error: 2_497 - .saturating_add(Weight::from_parts(39_228, 0).saturating_mul(s.into())) + // Minimum execution time: 36_239_000 picoseconds. + Weight::from_parts(36_459_756, 4764) + // Standard Error: 2_051 + .saturating_add(Weight::from_parts(56_670, 0).saturating_mul(l.into())) + // Standard Error: 3_650 + .saturating_add(Weight::from_parts(49_663, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -374,12 +372,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 68_441_000 picoseconds. - Weight::from_parts(68_961_970, 4764) - // Standard Error: 2_509 - .saturating_add(Weight::from_parts(83_345, 0).saturating_mul(l.into())) - // Standard Error: 4_464 - .saturating_add(Weight::from_parts(124_158, 0).saturating_mul(s.into())) + // Minimum execution time: 70_330_000 picoseconds. + Weight::from_parts(71_196_328, 4764) + // Standard Error: 2_923 + .saturating_add(Weight::from_parts(67_238, 0).saturating_mul(l.into())) + // Standard Error: 5_201 + .saturating_add(Weight::from_parts(89_102, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -397,12 +395,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `658 + l * (25 ±0) + s * (36 ±0)` // Estimated: `6196` - // Minimum execution time: 70_190_000 picoseconds. - Weight::from_parts(72_355_984, 6196) - // Standard Error: 2_295 - .saturating_add(Weight::from_parts(59_968, 0).saturating_mul(l.into())) - // Standard Error: 4_084 - .saturating_add(Weight::from_parts(87_090, 0).saturating_mul(s.into())) + // Minimum execution time: 70_235_000 picoseconds. + Weight::from_parts(71_960_020, 6196) + // Standard Error: 2_493 + .saturating_add(Weight::from_parts(64_835, 0).saturating_mul(l.into())) + // Standard Error: 4_436 + .saturating_add(Weight::from_parts(102_159, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -420,12 +418,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `482 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 33_911_000 picoseconds. - Weight::from_parts(33_243_006, 4764) - // Standard Error: 1_199 - .saturating_add(Weight::from_parts(70_586, 0).saturating_mul(l.into())) - // Standard Error: 2_214 - .saturating_add(Weight::from_parts(60_985, 0).saturating_mul(s.into())) + // Minimum execution time: 34_352_000 picoseconds. + Weight::from_parts(33_697_027, 4764) + // Standard Error: 2_008 + .saturating_add(Weight::from_parts(79_270, 0).saturating_mul(l.into())) + // Standard Error: 3_710 + .saturating_add(Weight::from_parts(60_691, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -443,12 +441,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `482 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 36_242_000 picoseconds. - Weight::from_parts(35_812_994, 4764) - // Standard Error: 1_351 - .saturating_add(Weight::from_parts(68_256, 0).saturating_mul(l.into())) - // Standard Error: 2_496 - .saturating_add(Weight::from_parts(66_171, 0).saturating_mul(s.into())) + // Minimum execution time: 37_467_000 picoseconds. + Weight::from_parts(36_866_847, 4764) + // Standard Error: 1_692 + .saturating_add(Weight::from_parts(57_882, 0).saturating_mul(l.into())) + // Standard Error: 3_124 + .saturating_add(Weight::from_parts(80_266, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -466,12 +464,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `555 + l * (25 ±0) + s * (36 ±0)` // Estimated: `4764` - // Minimum execution time: 37_817_000 picoseconds. - Weight::from_parts(37_397_127, 4764) - // Standard Error: 1_665 - .saturating_add(Weight::from_parts(72_049, 0).saturating_mul(l.into())) - // Standard Error: 3_075 - .saturating_add(Weight::from_parts(60_973, 0).saturating_mul(s.into())) + // Minimum execution time: 41_497_000 picoseconds. + Weight::from_parts(38_763_834, 4764) + // Standard Error: 2_030 + .saturating_add(Weight::from_parts(99_580, 0).saturating_mul(l.into())) + // Standard Error: 3_750 + .saturating_add(Weight::from_parts(132_188, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/substrate/frame/whitelist/src/weights.rs b/substrate/frame/whitelist/src/weights.rs index 13b653f6ca7..de42c5a5841 100644 --- a/substrate/frame/whitelist/src/weights.rs +++ b/substrate/frame/whitelist/src/weights.rs @@ -15,16 +15,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for `pallet_whitelist` +//! Autogenerated weights for pallet_whitelist //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/production/substrate-node +// ./target/production/substrate // benchmark // pallet // --chain=dev @@ -35,11 +35,12 @@ // --no-median-slopes // --no-min-squares // --extrinsic=* +// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/whitelist/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./frame/whitelist/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,7 +50,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for `pallet_whitelist`. +/// Weight functions needed for pallet_whitelist. pub trait WeightInfo { fn whitelist_call() -> Weight; fn remove_whitelisted_call() -> Weight; @@ -57,149 +58,133 @@ pub trait WeightInfo { fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight; } -/// Weights for `pallet_whitelist` using the Substrate node and recommended hardware. +/// Weights for pallet_whitelist using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) - /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn whitelist_call() -> Weight { // Proof Size summary in bytes: - // Measured: `317` + // Measured: `217` // Estimated: `3556` - // Minimum execution time: 18_503_000 picoseconds. - Weight::from_parts(19_497_000, 3556) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 19_914_000 picoseconds. + Weight::from_parts(20_892_000, 3556) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) - /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn remove_whitelisted_call() -> Weight { // Proof Size summary in bytes: - // Measured: `446` + // Measured: `346` // Estimated: `3556` - // Minimum execution time: 17_633_000 picoseconds. - Weight::from_parts(18_196_000, 3556) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 18_142_000 picoseconds. + Weight::from_parts(18_529_000, 3556) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) - /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::PreimageFor` (r:1 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:1 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: Measured) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) /// The range of component `n` is `[1, 4194294]`. fn dispatch_whitelisted_call(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `522 + n * (1 ±0)` - // Estimated: `3986 + n * (1 ±0)` - // Minimum execution time: 28_020_000 picoseconds. - Weight::from_parts(28_991_000, 3986) + // Measured: `422 + n * (1 ±0)` + // Estimated: `3886 + n * (1 ±0)` + // Minimum execution time: 30_671_000 picoseconds. + Weight::from_parts(31_197_000, 3886) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_171, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(Weight::from_parts(1_163, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } - /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) - /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) /// The range of component `n` is `[1, 10000]`. fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `446` + // Measured: `346` // Estimated: `3556` - // Minimum execution time: 21_916_000 picoseconds. - Weight::from_parts(23_082_065, 3556) - // Standard Error: 6 - .saturating_add(Weight::from_parts(1_388, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Minimum execution time: 22_099_000 picoseconds. + Weight::from_parts(23_145_477, 3556) + // Standard Error: 5 + .saturating_add(Weight::from_parts(1_422, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } } -// For backwards compatibility and tests. +// For backwards compatibility and tests impl WeightInfo for () { - /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) - /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn whitelist_call() -> Weight { // Proof Size summary in bytes: - // Measured: `317` + // Measured: `217` // Estimated: `3556` - // Minimum execution time: 18_503_000 picoseconds. - Weight::from_parts(19_497_000, 3556) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Minimum execution time: 19_914_000 picoseconds. + Weight::from_parts(20_892_000, 3556) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) - /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) fn remove_whitelisted_call() -> Weight { // Proof Size summary in bytes: - // Measured: `446` + // Measured: `346` // Estimated: `3556` - // Minimum execution time: 17_633_000 picoseconds. - Weight::from_parts(18_196_000, 3556) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Minimum execution time: 18_142_000 picoseconds. + Weight::from_parts(18_529_000, 3556) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) - /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::PreimageFor` (r:1 w:1) - /// Proof: `Preimage::PreimageFor` (`max_values`: None, `max_size`: Some(4194344), added: 4196819, mode: `Measured`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:1 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: Measured) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) /// The range of component `n` is `[1, 4194294]`. fn dispatch_whitelisted_call(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `522 + n * (1 ±0)` - // Estimated: `3986 + n * (1 ±0)` - // Minimum execution time: 28_020_000 picoseconds. - Weight::from_parts(28_991_000, 3986) + // Measured: `422 + n * (1 ±0)` + // Estimated: `3886 + n * (1 ±0)` + // Minimum execution time: 30_671_000 picoseconds. + Weight::from_parts(31_197_000, 3886) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_171, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(Weight::from_parts(1_163, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } - /// Storage: `Whitelist::WhitelistedCall` (r:1 w:1) - /// Proof: `Whitelist::WhitelistedCall` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `Preimage::StatusFor` (r:1 w:0) - /// Proof: `Preimage::StatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) - /// Storage: `Preimage::RequestStatusFor` (r:1 w:1) - /// Proof: `Preimage::RequestStatusFor` (`max_values`: None, `max_size`: Some(91), added: 2566, mode: `MaxEncodedLen`) + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(91), added: 2566, mode: MaxEncodedLen) /// The range of component `n` is `[1, 10000]`. fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `446` + // Measured: `346` // Estimated: `3556` - // Minimum execution time: 21_916_000 picoseconds. - Weight::from_parts(23_082_065, 3556) - // Standard Error: 6 - .saturating_add(Weight::from_parts(1_388, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Minimum execution time: 22_099_000 picoseconds. + Weight::from_parts(23_145_477, 3556) + // Standard Error: 5 + .saturating_add(Weight::from_parts(1_422, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/substrate/primitives/inherents/src/lib.rs b/substrate/primitives/inherents/src/lib.rs index 415319a6849..dd7c294f1e2 100644 --- a/substrate/primitives/inherents/src/lib.rs +++ b/substrate/primitives/inherents/src/lib.rs @@ -98,10 +98,10 @@ //! and production. //! //! ``` -//! # use sp_runtime::{generic::UncheckedExtrinsic, testing::MockCallU64}; +//! # use sp_runtime::testing::ExtrinsicWrapper; //! # use sp_inherents::{InherentIdentifier, InherentData}; //! # use futures::FutureExt; -//! # type Block = sp_runtime::testing::Block>; +//! # type Block = sp_runtime::testing::Block>; //! # const INHERENT_IDENTIFIER: InherentIdentifier = *b"testinh0"; //! # struct InherentDataProvider; //! # #[async_trait::async_trait] diff --git a/substrate/primitives/metadata-ir/src/lib.rs b/substrate/primitives/metadata-ir/src/lib.rs index 66aff2c599f..edfa58f8618 100644 --- a/substrate/primitives/metadata-ir/src/lib.rs +++ b/substrate/primitives/metadata-ir/src/lib.rs @@ -84,7 +84,7 @@ mod test { call_ty: meta_type::<()>(), signature_ty: meta_type::<()>(), extra_ty: meta_type::<()>(), - extensions: vec![], + signed_extensions: vec![], }, ty: meta_type::<()>(), apis: vec![], diff --git a/substrate/primitives/metadata-ir/src/types.rs b/substrate/primitives/metadata-ir/src/types.rs index e60881ed6b8..b107d20a8e2 100644 --- a/substrate/primitives/metadata-ir/src/types.rs +++ b/substrate/primitives/metadata-ir/src/types.rs @@ -166,11 +166,10 @@ pub struct ExtrinsicMetadataIR { pub call_ty: T::Type, /// The type of the extrinsic's signature. pub signature_ty: T::Type, - /// The type of the outermost Extra/Extensions enum. - // TODO: metadata-v16: rename this to `extension_ty`. + /// The type of the outermost Extra enum. pub extra_ty: T::Type, - /// The transaction extensions in the order they appear in the extrinsic. - pub extensions: Vec>, + /// The signed extensions in the order they appear in the extrinsic. + pub signed_extensions: Vec>, } impl IntoPortable for ExtrinsicMetadataIR { @@ -184,27 +183,27 @@ impl IntoPortable for ExtrinsicMetadataIR { call_ty: registry.register_type(&self.call_ty), signature_ty: registry.register_type(&self.signature_ty), extra_ty: registry.register_type(&self.extra_ty), - extensions: registry.map_into_portable(self.extensions), + signed_extensions: registry.map_into_portable(self.signed_extensions), } } } /// Metadata of an extrinsic's signed extension. #[derive(Clone, PartialEq, Eq, Encode, Debug)] -pub struct TransactionExtensionMetadataIR { +pub struct SignedExtensionMetadataIR { /// The unique signed extension identifier, which may be different from the type name. pub identifier: T::String, /// The type of the signed extension, with the data to be included in the extrinsic. pub ty: T::Type, - /// The type of the additional signed data, with the data to be included in the signed payload. + /// The type of the additional signed data, with the data to be included in the signed payload pub additional_signed: T::Type, } -impl IntoPortable for TransactionExtensionMetadataIR { - type Output = TransactionExtensionMetadataIR; +impl IntoPortable for SignedExtensionMetadataIR { + type Output = SignedExtensionMetadataIR; fn into_portable(self, registry: &mut Registry) -> Self::Output { - TransactionExtensionMetadataIR { + SignedExtensionMetadataIR { identifier: self.identifier.into_portable(registry), ty: registry.register_type(&self.ty), additional_signed: registry.register_type(&self.additional_signed), diff --git a/substrate/primitives/metadata-ir/src/v14.rs b/substrate/primitives/metadata-ir/src/v14.rs index ec08de34786..e1b7a24f765 100644 --- a/substrate/primitives/metadata-ir/src/v14.rs +++ b/substrate/primitives/metadata-ir/src/v14.rs @@ -20,8 +20,8 @@ use super::types::{ ExtrinsicMetadataIR, MetadataIR, PalletCallMetadataIR, PalletConstantMetadataIR, PalletErrorMetadataIR, PalletEventMetadataIR, PalletMetadataIR, PalletStorageMetadataIR, - StorageEntryMetadataIR, StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR, - TransactionExtensionMetadataIR, + SignedExtensionMetadataIR, StorageEntryMetadataIR, StorageEntryModifierIR, StorageEntryTypeIR, + StorageHasherIR, }; use frame_metadata::v14::{ @@ -137,8 +137,8 @@ impl From for PalletErrorMetadata { } } -impl From for SignedExtensionMetadata { - fn from(ir: TransactionExtensionMetadataIR) -> Self { +impl From for SignedExtensionMetadata { + fn from(ir: SignedExtensionMetadataIR) -> Self { SignedExtensionMetadata { identifier: ir.identifier, ty: ir.ty, @@ -152,7 +152,7 @@ impl From for ExtrinsicMetadata { ExtrinsicMetadata { ty: ir.ty, version: ir.version, - signed_extensions: ir.extensions.into_iter().map(Into::into).collect(), + signed_extensions: ir.signed_extensions.into_iter().map(Into::into).collect(), } } } diff --git a/substrate/primitives/metadata-ir/src/v15.rs b/substrate/primitives/metadata-ir/src/v15.rs index dc5ce1c88fd..a942eb73223 100644 --- a/substrate/primitives/metadata-ir/src/v15.rs +++ b/substrate/primitives/metadata-ir/src/v15.rs @@ -21,7 +21,7 @@ use crate::OuterEnumsIR; use super::types::{ ExtrinsicMetadataIR, MetadataIR, PalletMetadataIR, RuntimeApiMetadataIR, - RuntimeApiMethodMetadataIR, RuntimeApiMethodParamMetadataIR, TransactionExtensionMetadataIR, + RuntimeApiMethodMetadataIR, RuntimeApiMethodParamMetadataIR, SignedExtensionMetadataIR, }; use frame_metadata::v15::{ @@ -87,8 +87,8 @@ impl From for PalletMetadata { } } -impl From for SignedExtensionMetadata { - fn from(ir: TransactionExtensionMetadataIR) -> Self { +impl From for SignedExtensionMetadata { + fn from(ir: SignedExtensionMetadataIR) -> Self { SignedExtensionMetadata { identifier: ir.identifier, ty: ir.ty, @@ -105,7 +105,7 @@ impl From for ExtrinsicMetadata { call_ty: ir.call_ty, signature_ty: ir.signature_ty, extra_ty: ir.extra_ty, - signed_extensions: ir.extensions.into_iter().map(Into::into).collect(), + signed_extensions: ir.signed_extensions.into_iter().map(Into::into).collect(), } } } diff --git a/substrate/primitives/runtime/Cargo.toml b/substrate/primitives/runtime/Cargo.toml index 758cd8944fd..cacfc059722 100644 --- a/substrate/primitives/runtime/Cargo.toml +++ b/substrate/primitives/runtime/Cargo.toml @@ -17,7 +17,6 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -tuplex = { version = "0.1.2", default-features = false } codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } either = { version = "1.5", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } @@ -68,7 +67,6 @@ std = [ "sp-std/std", "sp-tracing/std", "sp-weights/std", - "tuplex/std", ] # Serde support without relying on std features. diff --git a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs index e28c8fe424a..44325920bee 100644 --- a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs @@ -18,115 +18,81 @@ //! Generic implementation of an extrinsic that has passed the verification //! stage. -use codec::Encode; - use crate::{ traits::{ - self, transaction_extension::TransactionExtension, DispatchInfoOf, DispatchTransaction, - Dispatchable, MaybeDisplay, Member, PostDispatchInfoOf, ValidateUnsigned, + self, DispatchInfoOf, Dispatchable, MaybeDisplay, Member, PostDispatchInfoOf, + SignedExtension, ValidateUnsigned, }, transaction_validity::{TransactionSource, TransactionValidity}, }; -/// The kind of extrinsic this is, including any fields required of that kind. This is basically -/// the full extrinsic except the `Call`. -#[derive(PartialEq, Eq, Clone, sp_core::RuntimeDebug)] -pub enum ExtrinsicFormat { - /// Extrinsic is bare; it must pass either the bare forms of `TransactionExtension` or - /// `ValidateUnsigned`, both deprecated, or alternatively a `ProvideInherent`. - Bare, - /// Extrinsic has a default `Origin` of `Signed(AccountId)` and must pass all - /// `TransactionExtension`s regular checks and includes all extension data. - Signed(AccountId, Extension), - /// Extrinsic has a default `Origin` of `None` and must pass all `TransactionExtension`s. - /// regular checks and includes all extension data. - General(Extension), -} - -// TODO: Rename ValidateUnsigned to ValidateInherent -// TODO: Consider changing ValidateInherent API to avoid need for duplicating validate -// code into pre_dispatch (rename that to `prepare`). -// TODO: New extrinsic type corresponding to `ExtrinsicFormat::General`, which is -// unsigned but includes extension data. -// TODO: Move usage of `signed` to `format`: -// - Inherent instead of None. -// - Signed(id, extension) instead of Some((id, extra)). -// - Introduce General(extension) for one without a signature. - /// Definition of something that the external world might want to say; its existence implies that it /// has been checked and is good, particularly with regards to the signature. /// /// This is typically passed into [`traits::Applyable::apply`], which should execute /// [`CheckedExtrinsic::function`], alongside all other bits and bobs. #[derive(PartialEq, Eq, Clone, sp_core::RuntimeDebug)] -pub struct CheckedExtrinsic { +pub struct CheckedExtrinsic { /// Who this purports to be from and the number of extrinsics have come before /// from the same signer, if anyone (note this is not a signature). - pub format: ExtrinsicFormat, + pub signed: Option<(AccountId, Extra)>, /// The function that should be called. pub function: Call, } -impl traits::Applyable - for CheckedExtrinsic +impl traits::Applyable + for CheckedExtrinsic where AccountId: Member + MaybeDisplay, - Call: Member + Dispatchable + Encode, - Extension: TransactionExtension, + Call: Member + Dispatchable, + Extra: SignedExtension, RuntimeOrigin: From>, { type Call = Call; - fn validate>( + fn validate>( &self, + // TODO [#5006;ToDr] should source be passed to `SignedExtension`s? + // Perhaps a change for 2.0 to avoid breaking too much APIs? source: TransactionSource, info: &DispatchInfoOf, len: usize, ) -> TransactionValidity { - match self.format { - ExtrinsicFormat::Bare => { - let inherent_validation = I::validate_unsigned(source, &self.function)?; - #[allow(deprecated)] - let legacy_validation = Extension::validate_bare_compat(&self.function, info, len)?; - Ok(legacy_validation.combine_with(inherent_validation)) - }, - ExtrinsicFormat::Signed(ref signer, ref extension) => { - let origin = Some(signer.clone()).into(); - extension.validate_only(origin, &self.function, info, len).map(|x| x.0) - }, - ExtrinsicFormat::General(ref extension) => - extension.validate_only(None.into(), &self.function, info, len).map(|x| x.0), + if let Some((ref id, ref extra)) = self.signed { + Extra::validate(extra, id, &self.function, info, len) + } else { + let valid = Extra::validate_unsigned(&self.function, info, len)?; + let unsigned_validation = U::validate_unsigned(source, &self.function)?; + Ok(valid.combine_with(unsigned_validation)) } } - fn apply>( + fn apply>( self, info: &DispatchInfoOf, len: usize, ) -> crate::ApplyExtrinsicResultWithInfo> { - match self.format { - ExtrinsicFormat::Bare => { - I::pre_dispatch(&self.function)?; - // TODO: Remove below once `pre_dispatch_unsigned` is removed from `LegacyExtension` - // or `LegacyExtension` is removed. - #[allow(deprecated)] - Extension::validate_bare_compat(&self.function, info, len)?; - #[allow(deprecated)] - Extension::pre_dispatch_bare_compat(&self.function, info, len)?; - let res = self.function.dispatch(None.into()); - let post_info = res.unwrap_or_else(|err| err.post_info); - let pd_res = res.map(|_| ()).map_err(|e| e.error); - // TODO: Remove below once `pre_dispatch_unsigned` is removed from `LegacyExtension` - // or `LegacyExtension` is removed. - #[allow(deprecated)] - Extension::post_dispatch_bare_compat(info, &post_info, len, &pd_res)?; - Ok(res) - }, - ExtrinsicFormat::Signed(signer, extension) => - extension.dispatch_transaction(Some(signer).into(), self.function, info, len), - ExtrinsicFormat::General(extension) => - extension.dispatch_transaction(None.into(), self.function, info, len), - } + let (maybe_who, maybe_pre) = if let Some((id, extra)) = self.signed { + let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?; + (Some(id), Some(pre)) + } else { + Extra::pre_dispatch_unsigned(&self.function, info, len)?; + U::pre_dispatch(&self.function)?; + (None, None) + }; + let res = self.function.dispatch(RuntimeOrigin::from(maybe_who)); + let post_info = match res { + Ok(info) => info, + Err(err) => err.post_info, + }; + Extra::post_dispatch( + maybe_pre, + info, + &post_info, + len, + &res.map(|_| ()).map_err(|e| e.error), + )?; + Ok(res) } } diff --git a/substrate/primitives/runtime/src/generic/mod.rs b/substrate/primitives/runtime/src/generic/mod.rs index 5713c166b04..3687f7cdb3b 100644 --- a/substrate/primitives/runtime/src/generic/mod.rs +++ b/substrate/primitives/runtime/src/generic/mod.rs @@ -29,9 +29,9 @@ mod unchecked_extrinsic; pub use self::{ block::{Block, BlockId, SignedBlock}, - checked_extrinsic::{CheckedExtrinsic, ExtrinsicFormat}, + checked_extrinsic::CheckedExtrinsic, digest::{Digest, DigestItem, DigestItemRef, OpaqueDigestItemId}, era::{Era, Phase}, header::Header, - unchecked_extrinsic::{Preamble, SignedPayload, UncheckedExtrinsic}, + unchecked_extrinsic::{SignedPayload, UncheckedExtrinsic}, }; diff --git a/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs b/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs index 44dfda13d94..5b54caf597b 100644 --- a/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -18,11 +18,10 @@ //! Generic implementation of an unchecked (pre-verification) extrinsic. use crate::{ - generic::{CheckedExtrinsic, ExtrinsicFormat}, + generic::CheckedExtrinsic, traits::{ - self, transaction_extension::TransactionExtensionBase, Checkable, Dispatchable, Extrinsic, - ExtrinsicMetadata, IdentifyAccount, MaybeDisplay, Member, SignaturePayload, - TransactionExtension, + self, Checkable, Extrinsic, ExtrinsicMetadata, IdentifyAccount, MaybeDisplay, Member, + SignaturePayload, SignedExtension, }, transaction_validity::{InvalidTransaction, TransactionValidityError}, OpaqueExtrinsic, @@ -41,60 +40,8 @@ use sp_std::{fmt, prelude::*}; /// the decoding fails. const EXTRINSIC_FORMAT_VERSION: u8 = 4; -/// The `SignaturePayload` of `UncheckedExtrinsic`. -type UncheckedSignaturePayload = (Address, Signature, Extension); - -impl SignaturePayload - for UncheckedSignaturePayload -{ - type SignatureAddress = Address; - type Signature = Signature; - type SignatureExtra = Extension; -} - -/// A "header" for extrinsics leading up to the call itself. Determines the type of extrinsic and -/// holds any necessary specialized data. -#[derive(Eq, PartialEq, Clone, Encode, Decode)] -pub enum Preamble { - /// An extrinsic without a signature or any extension. This means it's either an inherent or - /// an old-school "Unsigned" (we don't use that terminology any more since it's confusable with - /// the general transaction which is without a signature but does have an extension). - /// - /// NOTE: In the future, once we remove `ValidateUnsigned`, this will only serve Inherent - /// extrinsics and thus can be renamed to `Inherent`. - #[codec(index = 0b00000100)] - Bare, - /// An old-school transaction extrinsic which includes a signature of some hard-coded crypto. - #[codec(index = 0b10000100)] - Signed(Address, Signature, Extension), - /// A new-school transaction extrinsic which does not include a signature. - #[codec(index = 0b01000100)] - General(Extension), -} - -impl Preamble { - /// Returns `Some` if this is a signed extrinsic, together with the relevant inner fields. - pub fn to_signed(self) -> Option<(Address, Signature, Extension)> { - match self { - Self::Signed(a, s, e) => Some((a, s, e)), - _ => None, - } - } -} - -impl fmt::Debug for Preamble -where - Address: fmt::Debug, - Extension: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Self::Bare => write!(f, "Bare"), - Self::Signed(address, _, tx_ext) => write!(f, "Signed({:?}, {:?})", address, tx_ext), - Self::General(tx_ext) => write!(f, "General({:?})", tx_ext), - } - } -} +/// The `SingaturePayload` of `UncheckedExtrinsic`. +type UncheckedSignaturePayload = (Address, Signature, Extra); /// An extrinsic right from the external world. This is unchecked and so can contain a signature. /// @@ -118,28 +65,41 @@ where /// This can be checked using [`Checkable`], yielding a [`CheckedExtrinsic`], which is the /// counterpart of this type after its signature (and other non-negotiable validity checks) have /// passed. -#[derive(PartialEq, Eq, Clone, Debug)] -pub struct UncheckedExtrinsic { - /// Information regarding the type of extrinsic this is (inherent or transaction) as well as - /// associated extension (`Extension`) data if it's a transaction and a possible signature. - pub preamble: Preamble, +#[derive(PartialEq, Eq, Clone)] +pub struct UncheckedExtrinsic +where + Extra: SignedExtension, +{ + /// The signature, address, number of extrinsics have come before from the same signer and an + /// era describing the longevity of this transaction, if this is a signed extrinsic. + /// + /// `None` if it is unsigned or an inherent. + pub signature: Option>, /// The function that should be called. pub function: Call, } +impl SignaturePayload + for UncheckedSignaturePayload +{ + type SignatureAddress = Address; + type Signature = Signature; + type SignatureExtra = Extra; +} + /// Manual [`TypeInfo`] implementation because of custom encoding. The data is a valid encoded /// `Vec`, but requires some logic to extract the signature and payload. /// /// See [`UncheckedExtrinsic::encode`] and [`UncheckedExtrinsic::decode`]. -impl TypeInfo - for UncheckedExtrinsic +impl TypeInfo + for UncheckedExtrinsic where Address: StaticTypeInfo, Call: StaticTypeInfo, Signature: StaticTypeInfo, - Extension: StaticTypeInfo, + Extra: SignedExtension + StaticTypeInfo, { - type Identity = UncheckedExtrinsic; + type Identity = UncheckedExtrinsic; fn type_info() -> Type { Type::builder() @@ -151,7 +111,7 @@ where TypeParameter::new("Address", Some(meta_type::
())), TypeParameter::new("Call", Some(meta_type::())), TypeParameter::new("Signature", Some(meta_type::())), - TypeParameter::new("Extra", Some(meta_type::())), + TypeParameter::new("Extra", Some(meta_type::())), ]) .docs(&["UncheckedExtrinsic raw bytes, requires custom decoding routine"]) // Because of the custom encoding, we can only accurately describe the encoding as an @@ -161,113 +121,66 @@ where } } -impl UncheckedExtrinsic { - /// New instance of a bare (ne unsigned) extrinsic. This could be used for an inherent or an - /// old-school "unsigned transaction" (which are new being deprecated in favour of general - /// transactions). - #[deprecated = "Use new_bare instead"] - pub fn new_unsigned(function: Call) -> Self { - Self::new_bare(function) - } - - /// Returns `true` if this extrinsic instance is an inherent, `false`` otherwise. - pub fn is_inherent(&self) -> bool { - matches!(self.preamble, Preamble::Bare) - } - - /// Returns `true` if this extrinsic instance is an old-school signed transaction, `false` - /// otherwise. - pub fn is_signed(&self) -> bool { - matches!(self.preamble, Preamble::Signed(..)) - } - - /// Create an `UncheckedExtrinsic` from a `Preamble` and the actual `Call`. - pub fn from_parts(function: Call, preamble: Preamble) -> Self { - Self { preamble, function } - } - - /// New instance of a bare (ne unsigned) extrinsic. - pub fn new_bare(function: Call) -> Self { - Self { preamble: Preamble::Bare, function } - } - - /// New instance of an old-school signed transaction. - pub fn new_signed( - function: Call, - signed: Address, - signature: Signature, - tx_ext: Extension, - ) -> Self { - Self { preamble: Preamble::Signed(signed, signature, tx_ext), function } +impl + UncheckedExtrinsic +{ + /// New instance of a signed extrinsic aka "transaction". + pub fn new_signed(function: Call, signed: Address, signature: Signature, extra: Extra) -> Self { + Self { signature: Some((signed, signature, extra)), function } } - /// New instance of an new-school unsigned transaction. - pub fn new_transaction(function: Call, tx_ext: Extension) -> Self { - Self { preamble: Preamble::General(tx_ext), function } + /// New instance of an unsigned extrinsic aka "inherent". + pub fn new_unsigned(function: Call) -> Self { + Self { signature: None, function } } } -// TODO: We can get rid of this trait and just use UncheckedExtrinsic directly. - -impl Extrinsic - for UncheckedExtrinsic +impl + Extrinsic for UncheckedExtrinsic { type Call = Call; - type SignaturePayload = UncheckedSignaturePayload; - - fn is_bare(&self) -> bool { - matches!(self.preamble, Preamble::Bare) - } + type SignaturePayload = UncheckedSignaturePayload; fn is_signed(&self) -> Option { - Some(matches!(self.preamble, Preamble::Signed(..))) + Some(self.signature.is_some()) } fn new(function: Call, signed_data: Option) -> Option { Some(if let Some((address, signature, extra)) = signed_data { Self::new_signed(function, address, signature, extra) } else { - Self::new_bare(function) + Self::new_unsigned(function) }) } - - fn new_inherent(function: Call) -> Self { - Self::new_bare(function) - } } -impl Checkable - for UncheckedExtrinsic +impl Checkable + for UncheckedExtrinsic where LookupSource: Member + MaybeDisplay, - Call: Encode + Member + Dispatchable, + Call: Encode + Member, Signature: Member + traits::Verify, ::Signer: IdentifyAccount, - Extension: Encode + TransactionExtension, + Extra: SignedExtension, AccountId: Member + MaybeDisplay, Lookup: traits::Lookup, { - type Checked = CheckedExtrinsic; + type Checked = CheckedExtrinsic; fn check(self, lookup: &Lookup) -> Result { - Ok(match self.preamble { - Preamble::Signed(signed, signature, tx_ext) => { + Ok(match self.signature { + Some((signed, signature, extra)) => { let signed = lookup.lookup(signed)?; - // CHECK! Should this not contain implicit? - let raw_payload = SignedPayload::new(self.function, tx_ext)?; + let raw_payload = SignedPayload::new(self.function, extra)?; if !raw_payload.using_encoded(|payload| signature.verify(payload, &signed)) { return Err(InvalidTransaction::BadProof.into()) } - let (function, tx_ext, _) = raw_payload.deconstruct(); - CheckedExtrinsic { format: ExtrinsicFormat::Signed(signed, tx_ext), function } - }, - Preamble::General(tx_ext) => CheckedExtrinsic { - format: ExtrinsicFormat::General(tx_ext), - function: self.function, + + let (function, extra, _) = raw_payload.deconstruct(); + CheckedExtrinsic { signed: Some((signed, extra)), function } }, - Preamble::Bare => - CheckedExtrinsic { format: ExtrinsicFormat::Bare, function: self.function }, + None => CheckedExtrinsic { signed: None, function: self.function }, }) } @@ -276,38 +189,91 @@ where self, lookup: &Lookup, ) -> Result { - Ok(match self.preamble { - Preamble::Signed(signed, _, extra) => { + Ok(match self.signature { + Some((signed, _, extra)) => { let signed = lookup.lookup(signed)?; - CheckedExtrinsic { - format: ExtrinsicFormat::Signed(signed, extra), - function: self.function, - } + let raw_payload = SignedPayload::new(self.function, extra)?; + let (function, extra, _) = raw_payload.deconstruct(); + CheckedExtrinsic { signed: Some((signed, extra)), function } }, - Preamble::General(extra) => CheckedExtrinsic { - format: ExtrinsicFormat::General(extra), - function: self.function, - }, - Preamble::Bare => - CheckedExtrinsic { format: ExtrinsicFormat::Bare, function: self.function }, + None => CheckedExtrinsic { signed: None, function: self.function }, }) } } -impl> - ExtrinsicMetadata for UncheckedExtrinsic +impl ExtrinsicMetadata + for UncheckedExtrinsic +where + Extra: SignedExtension, { const VERSION: u8 = EXTRINSIC_FORMAT_VERSION; - type Extra = Extension; + type SignedExtensions = Extra; +} + +/// A payload that has been signed for an unchecked extrinsics. +/// +/// Note that the payload that we sign to produce unchecked extrinsic signature +/// is going to be different than the `SignaturePayload` - so the thing the extrinsic +/// actually contains. +pub struct SignedPayload((Call, Extra, Extra::AdditionalSigned)); + +impl SignedPayload +where + Call: Encode, + Extra: SignedExtension, +{ + /// Create new `SignedPayload`. + /// + /// This function may fail if `additional_signed` of `Extra` is not available. + pub fn new(call: Call, extra: Extra) -> Result { + let additional_signed = extra.additional_signed()?; + let raw_payload = (call, extra, additional_signed); + Ok(Self(raw_payload)) + } + + /// Create new `SignedPayload` from raw components. + pub fn from_raw(call: Call, extra: Extra, additional_signed: Extra::AdditionalSigned) -> Self { + Self((call, extra, additional_signed)) + } + + /// Deconstruct the payload into it's components. + pub fn deconstruct(self) -> (Call, Extra, Extra::AdditionalSigned) { + self.0 + } } -impl Decode - for UncheckedExtrinsic +impl Encode for SignedPayload +where + Call: Encode, + Extra: SignedExtension, +{ + /// Get an encoded version of this payload. + /// + /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. + fn using_encoded R>(&self, f: F) -> R { + self.0.using_encoded(|payload| { + if payload.len() > 256 { + f(&blake2_256(payload)[..]) + } else { + f(payload) + } + }) + } +} + +impl EncodeLike for SignedPayload +where + Call: Encode, + Extra: SignedExtension, +{ +} + +impl Decode for UncheckedExtrinsic where Address: Decode, Signature: Decode, Call: Decode, - Extension: Decode, + Extra: SignedExtension, { fn decode(input: &mut I) -> Result { // This is a little more complicated than usual since the binary format must be compatible @@ -316,7 +282,15 @@ where let expected_length: Compact = Decode::decode(input)?; let before_length = input.remaining_len()?; - let preamble = Decode::decode(input)?; + let version = input.read_byte()?; + + let is_signed = version & 0b1000_0000 != 0; + let version = version & 0b0111_1111; + if version != EXTRINSIC_FORMAT_VERSION { + return Err("Invalid transaction version".into()) + } + + let signature = is_signed.then(|| Decode::decode(input)).transpose()?; let function = Decode::decode(input)?; if let Some((before_length, after_length)) = @@ -329,20 +303,31 @@ where } } - Ok(Self { preamble, function }) + Ok(Self { signature, function }) } } #[docify::export(unchecked_extrinsic_encode_impl)] -impl Encode - for UncheckedExtrinsic +impl Encode for UncheckedExtrinsic where - Preamble: Encode, + Address: Encode, + Signature: Encode, Call: Encode, - Extension: Encode, + Extra: SignedExtension, { fn encode(&self) -> Vec { - let mut tmp = self.preamble.encode(); + let mut tmp = Vec::with_capacity(sp_std::mem::size_of::()); + + // 1 byte version id. + match self.signature.as_ref() { + Some(s) => { + tmp.push(EXTRINSIC_FORMAT_VERSION | 0b1000_0000); + s.encode_to(&mut tmp); + }, + None => { + tmp.push(EXTRINSIC_FORMAT_VERSION & 0b0111_1111); + }, + } self.function.encode_to(&mut tmp); let compact_len = codec::Compact::(tmp.len() as u32); @@ -357,19 +342,19 @@ where } } -impl EncodeLike - for UncheckedExtrinsic +impl EncodeLike + for UncheckedExtrinsic where Address: Encode, Signature: Encode, - Call: Encode + Dispatchable, - Extension: TransactionExtension, + Call: Encode, + Extra: SignedExtension, { } #[cfg(feature = "serde")] -impl serde::Serialize - for UncheckedExtrinsic +impl serde::Serialize + for UncheckedExtrinsic { fn serialize(&self, seq: S) -> Result where @@ -380,88 +365,45 @@ impl serde: } #[cfg(feature = "serde")] -impl<'a, Address: Decode, Signature: Decode, Call: Decode, Extension: Decode> serde::Deserialize<'a> - for UncheckedExtrinsic +impl<'a, Address: Decode, Signature: Decode, Call: Decode, Extra: SignedExtension> + serde::Deserialize<'a> for UncheckedExtrinsic { fn deserialize(de: D) -> Result where D: serde::Deserializer<'a>, { let r = sp_core::bytes::deserialize(de)?; - Self::decode(&mut &r[..]) + Decode::decode(&mut &r[..]) .map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e))) } } -/// A payload that has been signed for an unchecked extrinsics. -/// -/// Note that the payload that we sign to produce unchecked extrinsic signature -/// is going to be different than the `SignaturePayload` - so the thing the extrinsic -/// actually contains. -pub struct SignedPayload( - (Call, Extension, Extension::Implicit), -); - -impl SignedPayload -where - Call: Encode + Dispatchable, - Extension: TransactionExtensionBase, -{ - /// Create new `SignedPayload`. - /// - /// This function may fail if `implicit` of `Extension` is not available. - pub fn new(call: Call, tx_ext: Extension) -> Result { - let implicit = Extension::implicit(&tx_ext)?; - let raw_payload = (call, tx_ext, implicit); - Ok(Self(raw_payload)) - } - - /// Create new `SignedPayload` from raw components. - pub fn from_raw(call: Call, tx_ext: Extension, implicit: Extension::Implicit) -> Self { - Self((call, tx_ext, implicit)) - } - - /// Deconstruct the payload into it's components. - pub fn deconstruct(self) -> (Call, Extension, Extension::Implicit) { - self.0 - } -} - -impl Encode for SignedPayload +impl fmt::Debug + for UncheckedExtrinsic where - Call: Encode + Dispatchable, - Extension: TransactionExtensionBase, + Address: fmt::Debug, + Call: fmt::Debug, + Extra: SignedExtension, { - /// Get an encoded version of this payload. - /// - /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. - fn using_encoded R>(&self, f: F) -> R { - self.0.using_encoded(|payload| { - if payload.len() > 256 { - f(&blake2_256(payload)[..]) - } else { - f(payload) - } - }) + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "UncheckedExtrinsic({:?}, {:?})", + self.signature.as_ref().map(|x| (&x.0, &x.2)), + self.function, + ) } } -impl EncodeLike for SignedPayload -where - Call: Encode + Dispatchable, - Extension: TransactionExtensionBase, -{ -} - -impl - From> for OpaqueExtrinsic +impl From> + for OpaqueExtrinsic where Address: Encode, Signature: Encode, Call: Encode, - Extension: Encode, + Extra: SignedExtension, { - fn from(extrinsic: UncheckedExtrinsic) -> Self { + fn from(extrinsic: UncheckedExtrinsic) -> Self { Self::from_bytes(extrinsic.encode().as_slice()).expect( "both OpaqueExtrinsic and UncheckedExtrinsic have encoding that is compatible with \ raw Vec encoding; qed", @@ -469,198 +411,60 @@ where } } -#[cfg(test)] -mod legacy { - use codec::{Compact, Decode, Encode, EncodeLike, Error, Input}; - use scale_info::{ - build::Fields, meta_type, Path, StaticTypeInfo, Type, TypeInfo, TypeParameter, - }; - - pub type OldUncheckedSignaturePayload = (Address, Signature, Extra); - - #[derive(PartialEq, Eq, Clone, Debug)] - pub struct OldUncheckedExtrinsic { - pub signature: Option>, - pub function: Call, - } - - impl TypeInfo - for OldUncheckedExtrinsic - where - Address: StaticTypeInfo, - Call: StaticTypeInfo, - Signature: StaticTypeInfo, - Extra: StaticTypeInfo, - { - type Identity = OldUncheckedExtrinsic; - - fn type_info() -> Type { - Type::builder() - .path(Path::new("UncheckedExtrinsic", module_path!())) - // Include the type parameter types, even though they are not used directly in any - // of the described fields. These type definitions can be used by downstream - // consumers to help construct the custom decoding from the opaque bytes (see - // below). - .type_params(vec![ - TypeParameter::new("Address", Some(meta_type::
())), - TypeParameter::new("Call", Some(meta_type::())), - TypeParameter::new("Signature", Some(meta_type::())), - TypeParameter::new("Extra", Some(meta_type::())), - ]) - .docs(&["OldUncheckedExtrinsic raw bytes, requires custom decoding routine"]) - // Because of the custom encoding, we can only accurately describe the encoding as - // an opaque `Vec`. Downstream consumers will need to manually implement the - // codec to encode/decode the `signature` and `function` fields. - .composite(Fields::unnamed().field(|f| f.ty::>())) - } - } - - impl OldUncheckedExtrinsic { - pub fn new_signed( - function: Call, - signed: Address, - signature: Signature, - extra: Extra, - ) -> Self { - Self { signature: Some((signed, signature, extra)), function } - } - - pub fn new_unsigned(function: Call) -> Self { - Self { signature: None, function } - } - } - - impl Decode - for OldUncheckedExtrinsic - where - Address: Decode, - Signature: Decode, - Call: Decode, - Extra: Decode, - { - fn decode(input: &mut I) -> Result { - // This is a little more complicated than usual since the binary format must be - // compatible with SCALE's generic `Vec` type. Basically this just means accepting - // that there will be a prefix of vector length. - let expected_length: Compact = Decode::decode(input)?; - let before_length = input.remaining_len()?; - - let version = input.read_byte()?; - - let is_signed = version & 0b1000_0000 != 0; - let version = version & 0b0111_1111; - if version != 4u8 { - return Err("Invalid transaction version".into()) - } - - let signature = is_signed.then(|| Decode::decode(input)).transpose()?; - let function = Decode::decode(input)?; - - if let Some((before_length, after_length)) = - input.remaining_len()?.and_then(|a| before_length.map(|b| (b, a))) - { - let length = before_length.saturating_sub(after_length); - - if length != expected_length.0 as usize { - return Err("Invalid length prefix".into()) - } - } - - Ok(Self { signature, function }) - } - } - - #[docify::export(unchecked_extrinsic_encode_impl)] - impl Encode - for OldUncheckedExtrinsic - where - Address: Encode, - Signature: Encode, - Call: Encode, - Extra: Encode, - { - fn encode(&self) -> Vec { - let mut tmp = Vec::with_capacity(sp_std::mem::size_of::()); - - // 1 byte version id. - match self.signature.as_ref() { - Some(s) => { - tmp.push(4u8 | 0b1000_0000); - s.encode_to(&mut tmp); - }, - None => { - tmp.push(4u8 & 0b0111_1111); - }, - } - self.function.encode_to(&mut tmp); - - let compact_len = codec::Compact::(tmp.len() as u32); - - // Allocate the output buffer with the correct length - let mut output = Vec::with_capacity(compact_len.size_hint() + tmp.len()); - - compact_len.encode_to(&mut output); - output.extend(tmp); - - output - } - } - - impl EncodeLike - for OldUncheckedExtrinsic - where - Address: Encode, - Signature: Encode, - Call: Encode, - Extra: Encode, - { - } -} - #[cfg(test)] mod tests { - use super::{legacy::OldUncheckedExtrinsic, *}; + use super::*; use crate::{ codec::{Decode, Encode}, - impl_tx_ext_default, testing::TestSignature as TestSig, - traits::{FakeDispatchable, IdentityLookup, TransactionExtension}, + traits::{DispatchInfoOf, IdentityLookup, SignedExtension}, }; use sp_io::hashing::blake2_256; type TestContext = IdentityLookup; type TestAccountId = u64; - type TestCall = FakeDispatchable>; + type TestCall = Vec; const TEST_ACCOUNT: TestAccountId = 0; // NOTE: this is demonstration. One can simply use `()` for testing. #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, TypeInfo)] - struct DummyExtension; - impl TransactionExtensionBase for DummyExtension { - const IDENTIFIER: &'static str = "DummyExtension"; - type Implicit = (); - } - impl TransactionExtension for DummyExtension { - type Val = (); + struct TestExtra; + impl SignedExtension for TestExtra { + const IDENTIFIER: &'static str = "TestExtra"; + type AccountId = u64; + type Call = (); + type AdditionalSigned = (); type Pre = (); - impl_tx_ext_default!(TestCall; Context; validate prepare); + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) + } } - type Ex = UncheckedExtrinsic; - type CEx = CheckedExtrinsic; + type Ex = UncheckedExtrinsic; + type CEx = CheckedExtrinsic; #[test] fn unsigned_codec_should_work() { - let call: TestCall = vec![0u8; 0].into(); - let ux = Ex::new_inherent(call); + let ux = Ex::new_unsigned(vec![0u8; 0]); let encoded = ux.encode(); assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); } #[test] fn invalid_length_prefix_is_detected() { - let ux = Ex::new_inherent(vec![0u8; 0].into()); + let ux = Ex::new_unsigned(vec![0u8; 0]); let mut encoded = ux.encode(); let length = Compact::::decode(&mut &encoded[..]).unwrap(); @@ -669,20 +473,13 @@ mod tests { assert_eq!(Ex::decode(&mut &encoded[..]), Err("Invalid length prefix".into())); } - #[test] - fn transaction_codec_should_work() { - let ux = Ex::new_transaction(vec![0u8; 0].into(), DummyExtension); - let encoded = ux.encode(); - assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); - } - #[test] fn signed_codec_should_work() { let ux = Ex::new_signed( - vec![0u8; 0].into(), + vec![0u8; 0], TEST_ACCOUNT, - TestSig(TEST_ACCOUNT, (vec![0u8; 0], DummyExtension).encode()), - DummyExtension, + TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()), + TestExtra, ); let encoded = ux.encode(); assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); @@ -691,13 +488,13 @@ mod tests { #[test] fn large_signed_codec_should_work() { let ux = Ex::new_signed( - vec![0u8; 0].into(), + vec![0u8; 0], TEST_ACCOUNT, TestSig( TEST_ACCOUNT, - (vec![0u8; 257], DummyExtension).using_encoded(blake2_256)[..].to_owned(), + (vec![0u8; 257], TestExtra).using_encoded(blake2_256)[..].to_owned(), ), - DummyExtension, + TestExtra, ); let encoded = ux.encode(); assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux)); @@ -705,63 +502,44 @@ mod tests { #[test] fn unsigned_check_should_work() { - let ux = Ex::new_inherent(vec![0u8; 0].into()); - assert!(ux.is_inherent()); - assert_eq!( - >::check(ux, &Default::default()), - Ok(CEx { format: ExtrinsicFormat::Bare, function: vec![0u8; 0].into() }), - ); + let ux = Ex::new_unsigned(vec![0u8; 0]); + assert!(!ux.is_signed().unwrap_or(false)); + assert!(>::check(ux, &Default::default()).is_ok()); } #[test] fn badly_signed_check_should_fail() { let ux = Ex::new_signed( - vec![0u8; 0].into(), + vec![0u8; 0], TEST_ACCOUNT, - TestSig(TEST_ACCOUNT, vec![0u8; 0].into()), - DummyExtension, + TestSig(TEST_ACCOUNT, vec![0u8; 0]), + TestExtra, ); - assert!(!ux.is_inherent()); + assert!(ux.is_signed().unwrap_or(false)); assert_eq!( >::check(ux, &Default::default()), Err(InvalidTransaction::BadProof.into()), ); } - #[test] - fn transaction_check_should_work() { - let ux = Ex::new_transaction(vec![0u8; 0].into(), DummyExtension); - assert!(!ux.is_inherent()); - assert_eq!( - >::check(ux, &Default::default()), - Ok(CEx { - format: ExtrinsicFormat::General(DummyExtension), - function: vec![0u8; 0].into() - }), - ); - } - #[test] fn signed_check_should_work() { let ux = Ex::new_signed( - vec![0u8; 0].into(), + vec![0u8; 0], TEST_ACCOUNT, - TestSig(TEST_ACCOUNT, (vec![0u8; 0], DummyExtension).encode()), - DummyExtension, + TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()), + TestExtra, ); - assert!(!ux.is_inherent()); + assert!(ux.is_signed().unwrap_or(false)); assert_eq!( >::check(ux, &Default::default()), - Ok(CEx { - format: ExtrinsicFormat::Signed(TEST_ACCOUNT, DummyExtension), - function: vec![0u8; 0].into() - }), + Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }), ); } #[test] fn encoding_matches_vec() { - let ex = Ex::new_inherent(vec![0u8; 0].into()); + let ex = Ex::new_unsigned(vec![0u8; 0]); let encoded = ex.encode(); let decoded = Ex::decode(&mut encoded.as_slice()).unwrap(); assert_eq!(decoded, ex); @@ -771,7 +549,7 @@ mod tests { #[test] fn conversion_to_opaque() { - let ux = Ex::new_inherent(vec![0u8; 0].into()); + let ux = Ex::new_unsigned(vec![0u8; 0]); let encoded = ux.encode(); let opaque: OpaqueExtrinsic = ux.into(); let opaque_encoded = opaque.encode(); @@ -780,62 +558,10 @@ mod tests { #[test] fn large_bad_prefix_should_work() { - let encoded = (Compact::::from(u32::MAX), Preamble::<(), (), ()>::Bare).encode(); - assert!(Ex::decode(&mut &encoded[..]).is_err()); - } - - #[test] - fn legacy_signed_encode_decode() { - let call: TestCall = vec![0u8; 0].into(); - let signed = TEST_ACCOUNT; - let signature = TestSig(TEST_ACCOUNT, (vec![0u8; 0], DummyExtension).encode()); - let extension = DummyExtension; - - let new_ux = Ex::new_signed(call.clone(), signed, signature.clone(), extension.clone()); - let old_ux = - OldUncheckedExtrinsic::::new_signed( - call, signed, signature, extension, - ); - - let encoded_new_ux = new_ux.encode(); - let encoded_old_ux = old_ux.encode(); - - assert_eq!(encoded_new_ux, encoded_old_ux); - - let decoded_new_ux = Ex::decode(&mut &encoded_new_ux[..]).unwrap(); - let decoded_old_ux = - OldUncheckedExtrinsic::::decode( - &mut &encoded_old_ux[..], - ) - .unwrap(); - - assert_eq!(new_ux, decoded_new_ux); - assert_eq!(old_ux, decoded_old_ux); - } - - #[test] - fn legacy_unsigned_encode_decode() { - let call: TestCall = vec![0u8; 0].into(); - - let new_ux = Ex::new_bare(call.clone()); - let old_ux = - OldUncheckedExtrinsic::::new_unsigned( - call, - ); - - let encoded_new_ux = new_ux.encode(); - let encoded_old_ux = old_ux.encode(); - - assert_eq!(encoded_new_ux, encoded_old_ux); - - let decoded_new_ux = Ex::decode(&mut &encoded_new_ux[..]).unwrap(); - let decoded_old_ux = - OldUncheckedExtrinsic::::decode( - &mut &encoded_old_ux[..], - ) - .unwrap(); - - assert_eq!(new_ux, decoded_new_ux); - assert_eq!(old_ux, decoded_old_ux); + let encoded = Compact::::from(u32::MAX).encode(); + assert_eq!( + Ex::decode(&mut &encoded[..]), + Err(Error::from("Not enough data to fill buffer")) + ); } } diff --git a/substrate/primitives/runtime/src/lib.rs b/substrate/primitives/runtime/src/lib.rs index 70605970b4e..44bf3c969e5 100644 --- a/substrate/primitives/runtime/src/lib.rs +++ b/substrate/primitives/runtime/src/lib.rs @@ -125,11 +125,6 @@ pub use sp_arithmetic::{ Perquintill, Rational128, Rounding, UpperOf, }; -pub use transaction_validity::{ - InvalidTransaction, TransactionSource, TransactionValidityError, UnknownTransaction, - ValidTransaction, -}; - pub use either::Either; /// The number of bytes of the module-specific `error` field defined in [`ModuleError`]. @@ -448,21 +443,21 @@ impl std::fmt::Display for MultiSigner { impl Verify for MultiSignature { type Signer = MultiSigner; fn verify>(&self, mut msg: L, signer: &AccountId32) -> bool { - match self { - Self::Ed25519(ref sig) => match ed25519::Public::from_slice(signer.as_ref()) { + match (self, signer) { + (Self::Ed25519(ref sig), who) => match ed25519::Public::from_slice(who.as_ref()) { Ok(signer) => sig.verify(msg, &signer), Err(()) => false, }, - Self::Sr25519(ref sig) => match sr25519::Public::from_slice(signer.as_ref()) { + (Self::Sr25519(ref sig), who) => match sr25519::Public::from_slice(who.as_ref()) { Ok(signer) => sig.verify(msg, &signer), Err(()) => false, }, - Self::Ecdsa(ref sig) => { + (Self::Ecdsa(ref sig), who) => { let m = sp_io::hashing::blake2_256(msg.get()); match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { Ok(pubkey) => &sp_io::hashing::blake2_256(pubkey.as_ref()) == - >::as_ref(signer), + >::as_ref(who), _ => false, } }, @@ -949,13 +944,9 @@ impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic { } } -// TODO: OpaqueExtrinsics cannot act like regular extrinsics, right?! impl traits::Extrinsic for OpaqueExtrinsic { type Call = (); type SignaturePayload = (); - fn is_bare(&self) -> bool { - false - } } /// Print something that implements `Printable` from the runtime. diff --git a/substrate/primitives/runtime/src/testing.rs b/substrate/primitives/runtime/src/testing.rs index 3d6e0b5ab8b..5f94c834a8f 100644 --- a/substrate/primitives/runtime/src/testing.rs +++ b/substrate/primitives/runtime/src/testing.rs @@ -21,16 +21,24 @@ use crate::{ codec::{Codec, Decode, Encode, MaxEncodedLen}, generic, scale_info::TypeInfo, - traits::{self, BlakeTwo256, Dispatchable, OpaqueKeys}, - DispatchResultWithInfo, KeyTypeId, + traits::{ + self, Applyable, BlakeTwo256, Checkable, DispatchInfoOf, Dispatchable, OpaqueKeys, + PostDispatchInfoOf, SignaturePayload, SignedExtension, ValidateUnsigned, + }, + transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, + ApplyExtrinsicResultWithInfo, KeyTypeId, }; -use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize}; +use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer}; use sp_core::{ crypto::{key_types, ByteArray, CryptoType, Dummy}, U256, }; pub use sp_core::{sr25519, H256}; -use std::{cell::RefCell, fmt::Debug}; +use std::{ + cell::RefCell, + fmt::{self, Debug}, + ops::Deref, +}; /// A dummy type which can be used instead of regular cryptographic primitives. /// @@ -190,6 +198,42 @@ impl Header { } } +/// An opaque extrinsic wrapper type. +#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] +pub struct ExtrinsicWrapper(Xt); + +impl traits::Extrinsic for ExtrinsicWrapper { + type Call = (); + type SignaturePayload = (); + + fn is_signed(&self) -> Option { + None + } +} + +impl serde::Serialize for ExtrinsicWrapper { + fn serialize(&self, seq: S) -> Result + where + S: ::serde::Serializer, + { + self.using_encoded(|bytes| seq.serialize_bytes(bytes)) + } +} + +impl From for ExtrinsicWrapper { + fn from(xt: Xt) -> Self { + ExtrinsicWrapper(xt) + } +} + +impl Deref for ExtrinsicWrapper { + type Target = Xt; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + /// Testing block #[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode, TypeInfo)] pub struct Block { @@ -239,22 +283,139 @@ where } } -/// Wrapper over a `u64` that can be used as a `RuntimeCall`. -#[derive(PartialEq, Eq, Debug, Clone, Encode, Decode, TypeInfo)] -pub struct MockCallU64(pub u64); +/// The signature payload of a `TestXt`. +type TxSingaturePayload = (u64, Extra); + +impl SignaturePayload for TxSingaturePayload { + type SignatureAddress = u64; + type Signature = (); + type SignatureExtra = Extra; +} + +/// Test transaction, tuple of (sender, call, signed_extra) +/// with index only used if sender is some. +/// +/// If sender is some then the transaction is signed otherwise it is unsigned. +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] +pub struct TestXt { + /// Signature of the extrinsic. + pub signature: Option>, + /// Call of the extrinsic. + pub call: Call, +} + +impl TestXt { + /// Create a new `TextXt`. + pub fn new(call: Call, signature: Option<(u64, Extra)>) -> Self { + Self { call, signature } + } +} + +impl Serialize for TestXt +where + TestXt: Encode, +{ + fn serialize(&self, seq: S) -> Result + where + S: Serializer, + { + self.using_encoded(|bytes| seq.serialize_bytes(bytes)) + } +} -impl Dispatchable for MockCallU64 { - type RuntimeOrigin = u64; - type Config = (); - type Info = (); - type PostInfo = (); - fn dispatch(self, _origin: Self::RuntimeOrigin) -> DispatchResultWithInfo { - Ok(()) +impl Debug for TestXt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "TestXt({:?}, ...)", self.signature.as_ref().map(|x| &x.0)) } } -impl From for MockCallU64 { - fn from(value: u64) -> Self { - Self(value) +impl Checkable for TestXt { + type Checked = Self; + fn check(self, _: &Context) -> Result { + Ok(self) + } + + #[cfg(feature = "try-runtime")] + fn unchecked_into_checked_i_know_what_i_am_doing( + self, + _: &Context, + ) -> Result { + unreachable!() + } +} + +impl traits::Extrinsic + for TestXt +{ + type Call = Call; + type SignaturePayload = TxSingaturePayload; + + fn is_signed(&self) -> Option { + Some(self.signature.is_some()) + } + + fn new(c: Call, sig: Option) -> Option { + Some(TestXt { signature: sig, call: c }) + } +} + +impl traits::ExtrinsicMetadata for TestXt +where + Call: Codec + Sync + Send, + Extra: SignedExtension, +{ + type SignedExtensions = Extra; + const VERSION: u8 = 0u8; +} + +impl Applyable for TestXt +where + Call: 'static + + Sized + + Send + + Sync + + Clone + + Eq + + Codec + + Debug + + Dispatchable, + Extra: SignedExtension, + Origin: From>, +{ + type Call = Call; + + /// Checks to see if this is a valid *transaction*. It returns information on it if so. + fn validate>( + &self, + source: TransactionSource, + info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + if let Some((ref id, ref extra)) = self.signature { + Extra::validate(extra, id, &self.call, info, len) + } else { + let valid = Extra::validate_unsigned(&self.call, info, len)?; + let unsigned_validation = U::validate_unsigned(source, &self.call)?; + Ok(valid.combine_with(unsigned_validation)) + } + } + + /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, + /// index and sender. + fn apply>( + self, + info: &DispatchInfoOf, + len: usize, + ) -> ApplyExtrinsicResultWithInfo> { + let maybe_who = if let Some((who, extra)) = self.signature { + Extra::pre_dispatch(extra, &who, &self.call, info, len)?; + Some(who) + } else { + Extra::pre_dispatch_unsigned(&self.call, info, len)?; + U::pre_dispatch(&self.call)?; + None + }; + + Ok(self.call.dispatch(maybe_who.into())) } } diff --git a/substrate/primitives/runtime/src/traits/mod.rs b/substrate/primitives/runtime/src/traits.rs similarity index 94% rename from substrate/primitives/runtime/src/traits/mod.rs rename to substrate/primitives/runtime/src/traits.rs index b217166d8de..caede5e2b59 100644 --- a/substrate/primitives/runtime/src/traits/mod.rs +++ b/substrate/primitives/runtime/src/traits.rs @@ -19,7 +19,7 @@ use crate::{ generic::Digest, - scale_info::{StaticTypeInfo, TypeInfo}, + scale_info::{MetaType, StaticTypeInfo, TypeInfo}, transaction_validity::{ TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction, ValidTransaction, @@ -52,12 +52,6 @@ use std::fmt::Display; #[cfg(feature = "std")] use std::str::FromStr; -pub mod transaction_extension; -pub use transaction_extension::{ - DispatchTransaction, TransactionExtension, TransactionExtensionBase, - TransactionExtensionInterior, TransactionExtensionMetadata, ValidateResult, -}; - /// A lazy value. pub trait Lazy { /// Get a reference to the underlying value. @@ -1259,7 +1253,7 @@ pub trait Header: // that is then used to define `UncheckedExtrinsic`. // ```ignore // pub type UncheckedExtrinsic = -// generic::UncheckedExtrinsic; +// generic::UncheckedExtrinsic; // ``` // This `UncheckedExtrinsic` is supplied to the `Block`. // ```ignore @@ -1329,31 +1323,19 @@ pub trait Extrinsic: Sized { /// Is this `Extrinsic` signed? /// If no information are available about signed/unsigned, `None` should be returned. - #[deprecated = "Use and implement `!is_bare()` instead"] fn is_signed(&self) -> Option { None } - /// Returns `true` if this `Extrinsic` is bare. - fn is_bare(&self) -> bool { - #[allow(deprecated)] - !self - .is_signed() - .expect("`is_signed` must return `Some` on production extrinsics; qed") - } - - /// Create a new old-school extrinsic, either a bare extrinsic if `_signed_data` is `None` or - /// a signed transaction is it is `Some`. - #[deprecated = "Use `new_inherent` or the `CreateTransaction` trait instead"] + /// Create new instance of the extrinsic. + /// + /// Extrinsics can be split into: + /// 1. Inherents (no signature; created by validators during block production) + /// 2. Unsigned Transactions (no signature; represent "system calls" or other special kinds of + /// calls) 3. Signed Transactions (with signature; a regular transactions with known origin) fn new(_call: Self::Call, _signed_data: Option) -> Option { None } - - /// Create a new inherent extrinsic. - fn new_inherent(function: Self::Call) -> Self { - #[allow(deprecated)] - Self::new(function, None).expect("Extrinsic must provide inherents; qed") - } } /// Something that acts like a [`SignaturePayload`](Extrinsic::SignaturePayload) of an @@ -1389,8 +1371,7 @@ pub trait ExtrinsicMetadata { const VERSION: u8; /// Signed extensions attached to this `Extrinsic`. - // TODO: metadata-v16: rename to `Extension`. - type Extra; + type SignedExtensions: SignedExtension; } /// Extract the hashing type for a block. @@ -1475,8 +1456,6 @@ pub trait Dispatchable { -> crate::DispatchResultWithInfo; } -/// Shortcut to reference the `Origin` type of a `Dispatchable`. -pub type OriginOf = ::RuntimeOrigin; /// Shortcut to reference the `Info` type of a `Dispatchable`. pub type DispatchInfoOf = ::Info; /// Shortcut to reference the `PostInfo` type of a `Dispatchable`. @@ -1495,49 +1474,8 @@ impl Dispatchable for () { } } -/// Dispatchable impl containing an arbitrary value which panics if it actually is dispatched. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct FakeDispatchable(pub Inner); -impl From for FakeDispatchable { - fn from(inner: Inner) -> Self { - Self(inner) - } -} -impl FakeDispatchable { - /// Take `self` and return the underlying inner value. - pub fn deconstruct(self) -> Inner { - self.0 - } -} -impl AsRef for FakeDispatchable { - fn as_ref(&self) -> &Inner { - &self.0 - } -} - -impl Dispatchable for FakeDispatchable { - type RuntimeOrigin = (); - type Config = (); - type Info = (); - type PostInfo = (); - fn dispatch( - self, - _origin: Self::RuntimeOrigin, - ) -> crate::DispatchResultWithInfo { - panic!("This implementation should not be used for actual dispatch."); - } -} - -/// Runtime Origin which includes a System Origin variant whose `AccountId` is the parameter. -pub trait AsSystemOriginSigner { - /// Extract a reference of the inner value of the System `Origin::Signed` variant, if self has - /// that variant. - fn as_system_origin_signer(&self) -> Option<&AccountId>; -} - /// Means by which a transaction may be extended. This type embodies both the data and the logic /// that should be additionally associated with the transaction. It should be plain old data. -#[deprecated = "Use `TransactionExtension` instead."] pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo { @@ -1555,7 +1493,7 @@ pub trait SignedExtension: /// Any additional data that will go into the signed payload. This may be created dynamically /// from the transaction using the `additional_signed` function. - type AdditionalSigned: Codec + TypeInfo; + type AdditionalSigned: Encode + TypeInfo; /// The type that encodes information that can be passed from pre_dispatch to post-dispatch. type Pre; @@ -1594,6 +1532,38 @@ pub trait SignedExtension: len: usize, ) -> Result; + /// Validate an unsigned transaction for the transaction queue. + /// + /// This function can be called frequently by the transaction queue + /// to obtain transaction validity against current state. + /// It should perform all checks that determine a valid unsigned transaction, + /// and quickly eliminate ones that are stale or incorrect. + /// + /// Make sure to perform the same checks in `pre_dispatch_unsigned` function. + fn validate_unsigned( + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + Ok(ValidTransaction::default()) + } + + /// Do any pre-flight stuff for a unsigned transaction. + /// + /// Note this function by default delegates to `validate_unsigned`, so that + /// all checks performed for the transaction queue are also performed during + /// the dispatch phase (applying the extrinsic). + /// + /// If you ever override this function, you need to make sure to always + /// perform the same validation as in `validate_unsigned`. + fn pre_dispatch_unsigned( + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result<(), TransactionValidityError> { + Self::validate_unsigned(call, info, len).map(|_| ()).map_err(Into::into) + } + /// Do any post-flight stuff for an extrinsic. /// /// If the transaction is signed, then `_pre` will contain the output of `pre_dispatch`, @@ -1624,47 +1594,126 @@ pub trait SignedExtension: /// /// As a [`SignedExtension`] can be a tuple of [`SignedExtension`]s we need to return a `Vec` /// that holds the metadata of each one. Each individual `SignedExtension` must return - /// *exactly* one [`TransactionExtensionMetadata`]. + /// *exactly* one [`SignedExtensionMetadata`]. /// /// This method provides a default implementation that returns a vec containing a single - /// [`TransactionExtensionMetadata`]. - fn metadata() -> Vec { - sp_std::vec![TransactionExtensionMetadata { + /// [`SignedExtensionMetadata`]. + fn metadata() -> Vec { + sp_std::vec![SignedExtensionMetadata { identifier: Self::IDENTIFIER, ty: scale_info::meta_type::(), additional_signed: scale_info::meta_type::() }] } +} + +/// Information about a [`SignedExtension`] for the runtime metadata. +pub struct SignedExtensionMetadata { + /// The unique identifier of the [`SignedExtension`]. + pub identifier: &'static str, + /// The type of the [`SignedExtension`]. + pub ty: MetaType, + /// The type of the [`SignedExtension`] additional signed data for the payload. + pub additional_signed: MetaType, +} + +#[impl_for_tuples(1, 12)] +impl SignedExtension for Tuple { + for_tuples!( where #( Tuple: SignedExtension )* ); + type AccountId = AccountId; + type Call = Call; + const IDENTIFIER: &'static str = "You should call `identifier()`!"; + for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); + for_tuples!( type Pre = ( #( Tuple::Pre ),* ); ); + + fn additional_signed(&self) -> Result { + Ok(for_tuples!( ( #( Tuple.additional_signed()? ),* ) )) + } + + fn validate( + &self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + let valid = ValidTransaction::default(); + for_tuples!( #( let valid = valid.combine_with(Tuple.validate(who, call, info, len)?); )* ); + Ok(valid) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(for_tuples!( ( #( Tuple.pre_dispatch(who, call, info, len)? ),* ) )) + } - /// Validate an unsigned transaction for the transaction queue. - /// - /// This function can be called frequently by the transaction queue - /// to obtain transaction validity against current state. - /// It should perform all checks that determine a valid unsigned transaction, - /// and quickly eliminate ones that are stale or incorrect. fn validate_unsigned( - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, ) -> TransactionValidity { - Ok(ValidTransaction::default()) + let valid = ValidTransaction::default(); + for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info, len)?); )* ); + Ok(valid) } - /// Do any pre-flight stuff for an unsigned transaction. - /// - /// Note this function by default delegates to `validate_unsigned`, so that - /// all checks performed for the transaction queue are also performed during - /// the dispatch phase (applying the extrinsic). - /// - /// If you ever override this function, you need not perform the same validation as in - /// `validate_unsigned`. fn pre_dispatch_unsigned( - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, ) -> Result<(), TransactionValidityError> { + for_tuples!( #( Tuple::pre_dispatch_unsigned(call, info, len)?; )* ); Ok(()) } + + fn post_dispatch( + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + match pre { + Some(x) => { + for_tuples!( #( Tuple::post_dispatch(Some(x.Tuple), info, post_info, len, result)?; )* ); + }, + None => { + for_tuples!( #( Tuple::post_dispatch(None, info, post_info, len, result)?; )* ); + }, + } + Ok(()) + } + + fn metadata() -> Vec { + let mut ids = Vec::new(); + for_tuples!( #( ids.extend(Tuple::metadata()); )* ); + ids + } +} + +impl SignedExtension for () { + type AccountId = u64; + type AdditionalSigned = (); + type Call = (); + type Pre = (); + const IDENTIFIER: &'static str = "UnitSignedExtension"; + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { + Ok(()) + } + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(|_| ()) + } } /// An "executable" piece of information, used by the standard Substrate Executive in order to @@ -1713,7 +1762,6 @@ pub trait GetNodeBlockType { /// function is called right before dispatching the call wrapped by an unsigned extrinsic. The /// [`validate_unsigned`](Self::validate_unsigned) function is mainly being used in the context of /// the transaction pool to check the validity of the call wrapped by an unsigned extrinsic. -// TODO: Rename to ValidateBareTransaction (or just remove). pub trait ValidateUnsigned { /// The call to validate type Call; diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs b/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs deleted file mode 100644 index a834e88c0b4..00000000000 --- a/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs +++ /dev/null @@ -1,133 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -//! The [AsTransactionExtension] adapter struct for adapting [SignedExtension]s to -//! [TransactionExtension]s. - -#![allow(deprecated)] - -use scale_info::TypeInfo; -use sp_core::RuntimeDebug; - -use crate::{ - traits::{AsSystemOriginSigner, SignedExtension, ValidateResult}, - InvalidTransaction, -}; - -use super::*; - -/// Adapter to use a `SignedExtension` in the place of a `TransactionExtension`. -#[derive(TypeInfo, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -#[deprecated = "Convert your SignedExtension to a TransactionExtension."] -pub struct AsTransactionExtension(pub SE); - -impl Default for AsTransactionExtension { - fn default() -> Self { - Self(SE::default()) - } -} - -impl From for AsTransactionExtension { - fn from(value: SE) -> Self { - Self(value) - } -} - -impl TransactionExtensionBase for AsTransactionExtension { - const IDENTIFIER: &'static str = SE::IDENTIFIER; - type Implicit = SE::AdditionalSigned; - - fn implicit(&self) -> Result { - self.0.additional_signed() - } - fn metadata() -> Vec { - SE::metadata() - } -} - -impl TransactionExtension - for AsTransactionExtension -where - ::RuntimeOrigin: AsSystemOriginSigner + Clone, -{ - type Val = (); - type Pre = SE::Pre; - - fn validate( - &self, - origin: ::RuntimeOrigin, - call: &SE::Call, - info: &DispatchInfoOf, - len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; - let r = self.0.validate(who, call, info, len)?; - Ok((r, (), origin)) - } - - fn prepare( - self, - _: (), - origin: &::RuntimeOrigin, - call: &SE::Call, - info: &DispatchInfoOf, - len: usize, - _context: &Context, - ) -> Result { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; - self.0.pre_dispatch(who, call, info, len) - } - - fn post_dispatch( - pre: Self::Pre, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, - len: usize, - result: &DispatchResult, - _context: &Context, - ) -> Result<(), TransactionValidityError> { - SE::post_dispatch(Some(pre), info, post_info, len, result) - } - - fn validate_bare_compat( - call: &SE::Call, - info: &DispatchInfoOf, - len: usize, - ) -> TransactionValidity { - SE::validate_unsigned(call, info, len) - } - - fn pre_dispatch_bare_compat( - call: &SE::Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result<(), TransactionValidityError> { - SE::pre_dispatch_unsigned(call, info, len) - } - - fn post_dispatch_bare_compat( - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, - len: usize, - result: &DispatchResult, - ) -> Result<(), TransactionValidityError> { - SE::post_dispatch(None, info, post_info, len, result) - } -} diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs deleted file mode 100644 index 8efa586aa0e..00000000000 --- a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs +++ /dev/null @@ -1,141 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -//! The [DispatchTransaction] trait. - -use super::*; - -/// Single-function utility trait with a blanket impl over [TransactionExtension] in order to -/// provide transaction dispatching functionality. We avoid implementing this directly on the trait -/// since we never want it to be overriden by the trait implementation. -pub trait DispatchTransaction { - /// The origin type of the transaction. - type Origin; - /// The info type. - type Info; - /// The resultant type. - type Result; - /// The `Val` of the extension. - type Val; - /// The `Pre` of the extension. - type Pre; - /// Just validate a transaction. - /// - /// The is basically the same as [validate](TransactionExtension::validate), except that there - /// is no need to supply the bond data. - fn validate_only( - &self, - origin: Self::Origin, - call: &Call, - info: &Self::Info, - len: usize, - ) -> Result<(ValidTransaction, Self::Val, Self::Origin), TransactionValidityError>; - /// Prepare and validate a transaction, ready for dispatch. - fn validate_and_prepare( - self, - origin: Self::Origin, - call: &Call, - info: &Self::Info, - len: usize, - ) -> Result<(Self::Pre, Self::Origin), TransactionValidityError>; - /// Dispatch a transaction with the given base origin and call. - fn dispatch_transaction( - self, - origin: Self::Origin, - call: Call, - info: &Self::Info, - len: usize, - ) -> Self::Result; - /// Do everything which would be done in a [dispatch_transaction](Self::dispatch_transaction), - /// but instead of executing the call, execute `substitute` instead. Since this doesn't actually - /// dispatch the call, it doesn't need to consume it and so `call` can be passed as a reference. - fn test_run( - self, - origin: Self::Origin, - call: &Call, - info: &Self::Info, - len: usize, - substitute: impl FnOnce( - Self::Origin, - ) -> crate::DispatchResultWithInfo<::PostInfo>, - ) -> Self::Result; -} - -impl, Call: Dispatchable + Encode> DispatchTransaction - for T -{ - type Origin = ::RuntimeOrigin; - type Info = DispatchInfoOf; - type Result = crate::ApplyExtrinsicResultWithInfo>; - type Val = T::Val; - type Pre = T::Pre; - - fn validate_only( - &self, - origin: Self::Origin, - call: &Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result<(ValidTransaction, T::Val, Self::Origin), TransactionValidityError> { - self.validate(origin, call, info, len, &mut (), self.implicit()?, call) - } - fn validate_and_prepare( - self, - origin: Self::Origin, - call: &Call, - info: &DispatchInfoOf, - len: usize, - ) -> Result<(T::Pre, Self::Origin), TransactionValidityError> { - let (_, val, origin) = self.validate_only(origin, call, info, len)?; - let pre = self.prepare(val, &origin, &call, info, len, &())?; - Ok((pre, origin)) - } - fn dispatch_transaction( - self, - origin: ::RuntimeOrigin, - call: Call, - info: &DispatchInfoOf, - len: usize, - ) -> Self::Result { - let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?; - let res = call.dispatch(origin); - let post_info = res.unwrap_or_else(|err| err.post_info); - let pd_res = res.map(|_| ()).map_err(|e| e.error); - T::post_dispatch(pre, info, &post_info, len, &pd_res, &())?; - Ok(res) - } - fn test_run( - self, - origin: Self::Origin, - call: &Call, - info: &Self::Info, - len: usize, - substitute: impl FnOnce( - Self::Origin, - ) -> crate::DispatchResultWithInfo<::PostInfo>, - ) -> Self::Result { - let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?; - let res = substitute(origin); - let post_info = match res { - Ok(info) => info, - Err(err) => err.post_info, - }; - let pd_res = res.map(|_| ()).map_err(|e| e.error); - T::post_dispatch(pre, info, &post_info, len, &pd_res, &())?; - Ok(res) - } -} diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs deleted file mode 100644 index 69a0ba18adb..00000000000 --- a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs +++ /dev/null @@ -1,526 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// 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. - -//! The transaction extension trait. - -use crate::{ - scale_info::{MetaType, StaticTypeInfo}, - transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction}, - DispatchResult, -}; -use codec::{Codec, Decode, Encode}; -use impl_trait_for_tuples::impl_for_tuples; -#[doc(hidden)] -pub use sp_std::marker::PhantomData; -use sp_std::{self, fmt::Debug, prelude::*}; -use sp_weights::Weight; -use tuplex::{PopFront, PushBack}; - -use super::{DispatchInfoOf, Dispatchable, OriginOf, PostDispatchInfoOf}; - -mod as_transaction_extension; -mod dispatch_transaction; -#[allow(deprecated)] -pub use as_transaction_extension::AsTransactionExtension; -pub use dispatch_transaction::DispatchTransaction; - -/// Shortcut for the result value of the `validate` function. -pub type ValidateResult = - Result<(ValidTransaction, Val, OriginOf), TransactionValidityError>; - -/// Simple blanket implementation trait to denote the bounds of a type which can be contained within -/// a [`TransactionExtension`]. -pub trait TransactionExtensionInterior: - Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo -{ -} -impl - TransactionExtensionInterior for T -{ -} - -/// Base for [TransactionExtension]s; this contains the associated types and does not require any -/// generic parameterization. -pub trait TransactionExtensionBase: TransactionExtensionInterior { - /// Unique identifier of this signed extension. - /// - /// This will be exposed in the metadata to identify the signed extension used in an extrinsic. - const IDENTIFIER: &'static str; - - /// Any additional data which was known at the time of transaction construction and can be - /// useful in authenticating the transaction. This is determined dynamically in part from the - /// on-chain environment using the `implicit` function and not directly contained in the - /// transaction itself and therefore is considered "implicit". - type Implicit: Codec + StaticTypeInfo; - - /// Determine any additional data which was known at the time of transaction construction and - /// can be useful in authenticating the transaction. The expected usage of this is to include in - /// any data which is signed and verified as part of transactiob validation. Also perform any - /// pre-signature-verification checks and return an error if needed. - fn implicit(&self) -> Result { - use crate::InvalidTransaction::IndeterminateImplicit; - Ok(Self::Implicit::decode(&mut &[][..]).map_err(|_| IndeterminateImplicit)?) - } - - /// The weight consumed by executing this extension instance fully during transaction dispatch. - fn weight(&self) -> Weight { - Weight::zero() - } - - /// Returns the metadata for this extension. - /// - /// As a [`TransactionExtension`] can be a tuple of [`TransactionExtension`]s we need to return - /// a `Vec` that holds the metadata of each one. Each individual `TransactionExtension` must - /// return *exactly* one [`TransactionExtensionMetadata`]. - /// - /// This method provides a default implementation that returns a vec containing a single - /// [`TransactionExtensionMetadata`]. - fn metadata() -> Vec { - sp_std::vec![TransactionExtensionMetadata { - identifier: Self::IDENTIFIER, - ty: scale_info::meta_type::(), - // TODO: Metadata-v16: Rename to "implicit" - additional_signed: scale_info::meta_type::() - }] - } -} - -/// Means by which a transaction may be extended. This type embodies both the data and the logic -/// that should be additionally associated with the transaction. It should be plain old data. -/// -/// The simplest transaction extension would be the Unit type (and empty pipeline) `()`. This -/// executes no additional logic and implies a dispatch of the transaction's call using the -/// inherited origin (either `None` or `Signed`, depending on whether this is a signed or general -/// transaction). -/// -/// Transaction extensions are capable of altering certain associated semantics: -/// -/// - They may define the origin with which the transaction's call should be dispatched. -/// - They may define various parameters used by the transction queue to determine under what -/// conditions the transaction should be retained and introduced on-chain. -/// - They may define whether this transaction is acceptable for introduction on-chain at all. -/// -/// Each of these semantics are defined by the `validate` function. -/// -/// **NOTE: Transaction extensions cannot under any circumctances alter the call itself.** -/// -/// Transaction extensions are capable of defining logic which is executed additionally to the -/// dispatch of the call: -/// -/// - They may define logic which must be executed prior to the dispatch of the call. -/// - They may also define logic which must be executed after the dispatch of the call. -/// -/// Each of these semantics are defined by the `prepare` and `post_dispatch` functions respectively. -/// -/// Finally, transaction extensions may define additional data to help define the implications of -/// the logic they introduce. This additional data may be explicitly defined by the transaction -/// author (in which case it is included as part of the transaction body), or it may be implicitly -/// defined by the transaction extension based around the on-chain state (which the transaction -/// author is assumed to know). This data may be utilized by the above logic to alter how a node's -/// transaction queue treats this transaction. -/// -/// ## Default implementations -/// -/// Of the 5 functions in this trait, 3 of them must return a value of an associated type on -/// success, and none of these types implement [Default] or anything like it. This means that -/// default implementations cannot be provided for these functions. However, a macro is provided -/// [impl_tx_ext_default](crate::impl_tx_ext_default) which is capable of generating default -/// implementations for each of these 3 functions. If you do not wish to introduce additional logic -/// into the transaction pipeline, then it is recommended that you use this macro to implement these -/// functions. -/// -/// ## Pipelines, Inherited Implications, and Authorized Origins -/// -/// Requiring a single transaction extension to define all of the above semantics would be -/// cumbersome and would lead to a lot of boilerplate. Instead, transaction extensions are -/// aggregated into pipelines, which are tuples of transaction extensions. Each extension in the -/// pipeline is executed in order, and the output of each extension is aggregated and/or relayed as -/// the input to the next extension in the pipeline. -/// -/// This ordered composition happens with all datatypes ([Val](TransactionExtension::Val), -/// [Pre](TransactionExtension::Pre) and [Implicit](TransactionExtensionBase::Implicit)) as well as -/// all functions. There are important consequences stemming from how the composition affects the -/// meaning of the `origin` and `implication` parameters as well as the results. Whereas the -/// [prepare](TransactionExtension::prepare) and -/// [post_dispatch](TransactionExtension::post_dispatch) functions are clear in their meaning, the -/// [validate](TransactionExtension::validate) function is fairly sophisticated and warrants -/// further explanation. -/// -/// Firstly, the `origin` parameter. The `origin` passed into the first item in a pipeline is simply -/// that passed into the tuple itself. It represents an authority who has authorized the implication -/// of the transaction, as of the extension it has been passed into *and any further extensions it -/// may pass though, all the way to, and including, the transaction's dispatch call itself. Each -/// following item in the pipeline is passed the origin which the previous item returned. The origin -/// returned from the final item in the pipeline is the origin which is returned by the tuple -/// itself. -/// -/// This means that if a constituent extension returns a different origin to the one it was called -/// with, then (assuming no other extension changes it further) *this new origin will be used for -/// all extensions following it in the pipeline, and will be returned from the pipeline to be used -/// as the origin for the call's dispatch*. The call itself as well as all these extensions -/// following may each imply consequence for this origin. We call this the *inherited implication*. -/// -/// The *inherited implication* is the cumulated on-chain effects born by whatever origin is -/// returned. It is expressed to the [validate](TransactionExtension::validate) function only as the -/// `implication` argument which implements the [Encode] trait. A transaction extension may define -/// its own implications through its own fields and the -/// [implicit](TransactionExtensionBase::implicit) function. This is only utilized by extensions -/// which preceed it in a pipeline or, if the transaction is an old-school signed trasnaction, the -/// underlying transaction verification logic. -/// -/// **The inherited implication passed as the `implication` parameter to -/// [validate](TransactionExtension::validate) does not include the extension's inner data itself -/// nor does it include the result of the extension's `implicit` function.** If you both provide an -/// implication and rely on the implication, then you need to manually aggregate your extensions -/// implication with the aggregated implication passed in. -pub trait TransactionExtension: TransactionExtensionBase { - /// The type that encodes information that can be passed from validate to prepare. - type Val; - - /// The type that encodes information that can be passed from prepare to post-dispatch. - type Pre; - - /// Validate a transaction for the transaction queue. - /// - /// This function can be called frequently by the transaction queue to obtain transaction - /// validity against current state. It should perform all checks that determine a valid - /// transaction, that can pay for its execution and quickly eliminate ones that are stale or - /// incorrect. - /// - /// Parameters: - /// - `origin`: The origin of the transaction which this extension inherited; coming from an - /// "old-school" *signed transaction*, this will be a system `RawOrigin::Signed` value. If the - /// transaction is a "new-school" *General Transaction*, then this will be a system - /// `RawOrigin::None` value. If this extension is an item in a composite, then it could be - /// anything which was previously returned as an `origin` value in the result of a `validate` - /// call. - /// - `call`: The `Call` wrapped by this extension. - /// - `info`: Information concerning, and inherent to, the transaction's call. - /// - `len`: The total length of the encoded transaction. - /// - `inherited_implication`: The *implication* which this extension inherits. This is a tuple - /// of the transaction's call and some additional opaque-but-encodable data. Coming directly - /// from a transaction, the latter is [()]. However, if this extension is expressed as part of - /// a composite type, then the latter component is equal to any further implications to which - /// the returned `origin` could potentially apply. See Pipelines, Inherited Implications, and - /// Authorized Origins for more information. - /// - `context`: Some opaque mutable context, as yet unused. - /// - /// Returns a [ValidateResult], which is a [Result] whose success type is a tuple of - /// [ValidTransaction] (defining useful metadata for the transaction queue), the [Self::Val] - /// token of this transaction, which gets passed into [prepare](TransactionExtension::prepare), - /// and the origin of the transaction, which gets passed into - /// [prepare](TransactionExtension::prepare) and is ultimately used for dispatch. - fn validate( - &self, - origin: OriginOf, - call: &Call, - info: &DispatchInfoOf, - len: usize, - context: &mut Context, - self_implicit: Self::Implicit, - inherited_implication: &impl Encode, - ) -> ValidateResult; - - /// Do any pre-flight stuff for a transaction after validation. - /// - /// This is for actions which do not happen in the transaction queue but only immediately prior - /// to the point of dispatch on-chain. This should not return an error, since errors should - /// already have been identified during the [validate](TransactionExtension::validate) call. If - /// an error is returned, the transaction will be considered invalid but no state changes will - /// happen and therefore work done in [validate](TransactionExtension::validate) will not be - /// paid for. - /// - /// Unlike `validate`, this function may consume `self`. - /// - /// Parameters: - /// - `val`: `Self::Val` returned by the result of the `validate` call. - /// - `origin`: The origin returned by the result of the `validate` call. - /// - `call`: The `Call` wrapped by this extension. - /// - `info`: Information concerning, and inherent to, the transaction's call. - /// - `len`: The total length of the encoded transaction. - /// - `context`: Some opaque mutable context, as yet unused. - /// - /// Returns a [Self::Pre] value on success, which gets passed into - /// [post_dispatch](TransactionExtension::post_dispatch) and after the call is dispatched. - /// - /// IMPORTANT: **Checks made in validation need not be repeated here.** - fn prepare( - self, - val: Self::Val, - origin: &OriginOf, - call: &Call, - info: &DispatchInfoOf, - len: usize, - context: &Context, - ) -> Result; - - /// Do any post-flight stuff for an extrinsic. - /// - /// `_pre` contains the output of `prepare`. - /// - /// This gets given the `DispatchResult` `_result` from the extrinsic and can, if desired, - /// introduce a `TransactionValidityError`, causing the block to become invalid for including - /// it. - /// - /// Parameters: - /// - `pre`: `Self::Pre` returned by the result of the `prepare` call prior to dispatch. - /// - `info`: Information concerning, and inherent to, the transaction's call. - /// - `post_info`: Information concerning the dispatch of the transaction's call. - /// - `len`: The total length of the encoded transaction. - /// - `result`: The result of the dispatch. - /// - `context`: Some opaque mutable context, as yet unused. - /// - /// WARNING: It is dangerous to return an error here. To do so will fundamentally invalidate the - /// transaction and any block that it is included in, causing the block author to not be - /// compensated for their work in validating the transaction or producing the block so far. It - /// can only be used safely when you *know* that the transaction is one that would only be - /// introduced by the current block author. - fn post_dispatch( - _pre: Self::Pre, - _info: &DispatchInfoOf, - _post_info: &PostDispatchInfoOf, - _len: usize, - _result: &DispatchResult, - _context: &Context, - ) -> Result<(), TransactionValidityError> { - Ok(()) - } - - /// Compatibility function for supporting the `SignedExtension::validate_unsigned` function. - /// - /// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME! - #[deprecated = "Only for compatibility. DO NOT USE."] - fn validate_bare_compat( - _call: &Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> TransactionValidity { - Ok(ValidTransaction::default()) - } - - /// Compatibility function for supporting the `SignedExtension::pre_dispatch_unsigned` function. - /// - /// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME! - #[deprecated = "Only for compatibility. DO NOT USE."] - fn pre_dispatch_bare_compat( - _call: &Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result<(), TransactionValidityError> { - Ok(()) - } - - /// Compatibility function for supporting the `SignedExtension::post_dispatch` function where - /// `pre` is `None`. - /// - /// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME! - #[deprecated = "Only for compatibility. DO NOT USE."] - fn post_dispatch_bare_compat( - _info: &DispatchInfoOf, - _post_info: &PostDispatchInfoOf, - _len: usize, - _result: &DispatchResult, - ) -> Result<(), TransactionValidityError> { - Ok(()) - } -} - -/// Implict -#[macro_export] -macro_rules! impl_tx_ext_default { - ($call:ty ; $context:ty ; , $( $rest:tt )*) => { - impl_tx_ext_default!{$call ; $context ; $( $rest )*} - }; - ($call:ty ; $context:ty ; validate $( $rest:tt )*) => { - fn validate( - &self, - origin: $crate::traits::OriginOf<$call>, - _call: &$call, - _info: &$crate::traits::DispatchInfoOf<$call>, - _len: usize, - _context: &mut $context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl $crate::codec::Encode, - ) -> $crate::traits::ValidateResult { - Ok((Default::default(), Default::default(), origin)) - } - impl_tx_ext_default!{$call ; $context ; $( $rest )*} - }; - ($call:ty ; $context:ty ; prepare $( $rest:tt )*) => { - fn prepare( - self, - _val: Self::Val, - _origin: &$crate::traits::OriginOf<$call>, - _call: &$call, - _info: &$crate::traits::DispatchInfoOf<$call>, - _len: usize, - _context: & $context, - ) -> Result { - Ok(Default::default()) - } - impl_tx_ext_default!{$call ; $context ; $( $rest )*} - }; - ($call:ty ; $context:ty ;) => {}; -} - -/// Information about a [`TransactionExtension`] for the runtime metadata. -pub struct TransactionExtensionMetadata { - /// The unique identifier of the [`TransactionExtension`]. - pub identifier: &'static str, - /// The type of the [`TransactionExtension`]. - pub ty: MetaType, - /// The type of the [`TransactionExtension`] additional signed data for the payload. - // TODO: Rename "implicit" - pub additional_signed: MetaType, -} - -#[impl_for_tuples(1, 12)] -impl TransactionExtensionBase for Tuple { - for_tuples!( where #( Tuple: TransactionExtensionBase )* ); - const IDENTIFIER: &'static str = "Use `metadata()`!"; - for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); ); - fn implicit(&self) -> Result { - Ok(for_tuples!( ( #( Tuple.implicit()? ),* ) )) - } - fn weight(&self) -> Weight { - let mut weight = Weight::zero(); - for_tuples!( #( weight += Tuple.weight(); )* ); - weight - } - fn metadata() -> Vec { - let mut ids = Vec::new(); - for_tuples!( #( ids.extend(Tuple::metadata()); )* ); - ids - } -} - -#[impl_for_tuples(1, 12)] -impl TransactionExtension for Tuple { - for_tuples!( where #( Tuple: TransactionExtension )* ); - for_tuples!( type Val = ( #( Tuple::Val ),* ); ); - for_tuples!( type Pre = ( #( Tuple::Pre ),* ); ); - - fn validate( - &self, - origin: ::RuntimeOrigin, - call: &Call, - info: &DispatchInfoOf, - len: usize, - context: &mut Context, - self_implicit: Self::Implicit, - inherited_implication: &impl Encode, - ) -> Result< - (ValidTransaction, Self::Val, ::RuntimeOrigin), - TransactionValidityError, - > { - let valid = ValidTransaction::default(); - let val = (); - let following_explicit_implications = for_tuples!( ( #( &self.Tuple ),* ) ); - let following_implicit_implications = self_implicit; - - for_tuples!(#( - // Implication of this pipeline element not relevant for later items, so we pop it. - let (_item, following_explicit_implications) = following_explicit_implications.pop_front(); - let (item_implicit, following_implicit_implications) = following_implicit_implications.pop_front(); - let (item_valid, item_val, origin) = { - let implications = ( - // The first is the implications born of the fact we return the mutated - // origin. - inherited_implication, - // This is the explicitly made implication born of the fact the new origin is - // passed into the next items in this pipeline-tuple. - &following_explicit_implications, - // This is the implicitly made implication born of the fact the new origin is - // passed into the next items in this pipeline-tuple. - &following_implicit_implications, - ); - Tuple.validate(origin, call, info, len, context, item_implicit, &implications)? - }; - let valid = valid.combine_with(item_valid); - let val = val.push_back(item_val); - )* ); - Ok((valid, val, origin)) - } - - fn prepare( - self, - val: Self::Val, - origin: &::RuntimeOrigin, - call: &Call, - info: &DispatchInfoOf, - len: usize, - context: &Context, - ) -> Result { - Ok(for_tuples!( ( #( - Tuple::prepare(self.Tuple, val.Tuple, origin, call, info, len, context)? - ),* ) )) - } - - fn post_dispatch( - pre: Self::Pre, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, - len: usize, - result: &DispatchResult, - context: &Context, - ) -> Result<(), TransactionValidityError> { - for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info, post_info, len, result, context)?; )* ); - Ok(()) - } -} - -impl TransactionExtensionBase for () { - const IDENTIFIER: &'static str = "UnitTransactionExtension"; - type Implicit = (); - fn implicit(&self) -> sp_std::result::Result { - Ok(()) - } - fn weight(&self) -> Weight { - Weight::zero() - } -} - -impl TransactionExtension for () { - type Val = (); - type Pre = (); - fn validate( - &self, - origin: ::RuntimeOrigin, - _call: &Call, - _info: &DispatchInfoOf, - _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> Result< - (ValidTransaction, (), ::RuntimeOrigin), - TransactionValidityError, - > { - Ok((ValidTransaction::default(), (), origin)) - } - fn prepare( - self, - _val: (), - _origin: &::RuntimeOrigin, - _call: &Call, - _info: &DispatchInfoOf, - _len: usize, - _context: &Context, - ) -> Result<(), TransactionValidityError> { - Ok(()) - } -} diff --git a/substrate/primitives/runtime/src/transaction_validity.rs b/substrate/primitives/runtime/src/transaction_validity.rs index 24124128083..83694849382 100644 --- a/substrate/primitives/runtime/src/transaction_validity.rs +++ b/substrate/primitives/runtime/src/transaction_validity.rs @@ -82,8 +82,6 @@ pub enum InvalidTransaction { MandatoryValidation, /// The sending address is disabled or known to be invalid. BadSigner, - /// The implicit data was unable to be calculated. - IndeterminateImplicit, } impl InvalidTransaction { @@ -115,8 +113,6 @@ impl From for &'static str { "Transaction dispatch is mandatory; transactions must not be validated.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", InvalidTransaction::BadSigner => "Invalid signing address", - InvalidTransaction::IndeterminateImplicit => - "The implicit data was unable to be calculated", } } } @@ -342,7 +338,7 @@ pub struct ValidTransactionBuilder { impl ValidTransactionBuilder { /// Set the priority of a transaction. /// - /// Note that the final priority for `FRAME` is combined from all `TransactionExtension`s. + /// Note that the final priority for `FRAME` is combined from all `SignedExtension`s. /// Most likely for unsigned transactions you want the priority to be higher /// than for regular transactions. We recommend exposing a base priority for unsigned /// transactions as a runtime module parameter, so that the runtime can tune inter-module diff --git a/substrate/scripts/run_all_benchmarks.sh b/substrate/scripts/run_all_benchmarks.sh index fe5f89a5b56..6dd7cede319 100755 --- a/substrate/scripts/run_all_benchmarks.sh +++ b/substrate/scripts/run_all_benchmarks.sh @@ -107,19 +107,6 @@ for PALLET in "${PALLETS[@]}"; do FOLDER="$(echo "${PALLET#*_}" | tr '_' '-')"; WEIGHT_FILE="./frame/${FOLDER}/src/weights.rs" - - # Special handling of custom weight paths. - if [ "$PALLET" == "frame_system_extensions" ] || [ "$PALLET" == "frame-system-extensions" ] - then - WEIGHT_FILE="./frame/system/src/extensions/weights.rs" - elif [ "$PALLET" == "pallet_asset_conversion_tx_payment" ] || [ "$PALLET" == "pallet-asset-conversion-tx-payment" ] - then - WEIGHT_FILE="./frame/transaction-payment/asset-conversion-tx-payment/src/weights.rs" - elif [ "$PALLET" == "pallet_asset_tx_payment" ] || [ "$PALLET" == "pallet-asset-tx-payment" ] - then - WEIGHT_FILE="./frame/transaction-payment/asset-tx-payment/src/weights.rs" - fi - echo "[+] Benchmarking $PALLET with weight file $WEIGHT_FILE"; OUTPUT=$( diff --git a/substrate/test-utils/runtime/src/extrinsic.rs b/substrate/test-utils/runtime/src/extrinsic.rs index 7eb1839e97b..05ffb7db5d5 100644 --- a/substrate/test-utils/runtime/src/extrinsic.rs +++ b/substrate/test-utils/runtime/src/extrinsic.rs @@ -25,7 +25,7 @@ use codec::Encode; use frame_system::{CheckNonce, CheckWeight}; use sp_core::crypto::Pair as TraitPair; use sp_keyring::AccountKeyring; -use sp_runtime::{generic::Preamble, transaction_validity::TransactionPriority, Perbill}; +use sp_runtime::{transaction_validity::TransactionPriority, Perbill}; use sp_std::prelude::*; /// Transfer used in test substrate pallet. Extrinsic is created and signed using this data. @@ -66,11 +66,11 @@ impl TryFrom<&Extrinsic> for TransferData { match uxt { Extrinsic { function: RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }), - preamble: Preamble::Signed(from, _, ((CheckNonce(nonce), ..), ..)), + signature: Some((from, _, (CheckNonce(nonce), ..))), } => Ok(TransferData { from: *from, to: *dest, amount: *value, nonce: *nonce }), Extrinsic { function: RuntimeCall::SubstrateTest(PalletCall::bench_call { transfer }), - preamble: Preamble::Bare, + signature: None, } => Ok(transfer.clone()), _ => Err(()), } @@ -190,17 +190,18 @@ impl ExtrinsicBuilder { /// Build `Extrinsic` using embedded parameters pub fn build(self) -> Extrinsic { if let Some(signer) = self.signer { - let tx_ext = ( - (CheckNonce::from(self.nonce.unwrap_or(0)), CheckWeight::new()), + let extra = ( + CheckNonce::from(self.nonce.unwrap_or(0)), + CheckWeight::new(), CheckSubstrateCall {}, ); let raw_payload = - SignedPayload::from_raw(self.function.clone(), tx_ext.clone(), (((), ()), ())); + SignedPayload::from_raw(self.function.clone(), extra.clone(), ((), (), ())); let signature = raw_payload.using_encoded(|e| signer.sign(e)); - Extrinsic::new_signed(self.function, signer.public(), signature, tx_ext) + Extrinsic::new_signed(self.function, signer.public(), signature, extra) } else { - Extrinsic::new_bare(self.function) + Extrinsic::new_unsigned(self.function) } } } diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index 7ec5f6722c4..63e0aa6e137 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -58,11 +58,9 @@ use sp_api::{decl_runtime_apis, impl_runtime_apis}; pub use sp_core::hash::H256; use sp_inherents::{CheckInherentsResult, InherentData}; use sp_runtime::{ - create_runtime_str, impl_opaque_keys, impl_tx_ext_default, - traits::{BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, NumberFor, Verify}, - transaction_validity::{ - TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, - }, + create_runtime_str, impl_opaque_keys, + traits::{BlakeTwo256, Block as BlockT, DispatchInfoOf, NumberFor, Verify}, + transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, ApplyExtrinsicResult, ExtrinsicInclusionMode, Perbill, }; #[cfg(any(feature = "std", test))] @@ -144,14 +142,13 @@ pub type Signature = sr25519::Signature; #[cfg(feature = "std")] pub type Pair = sp_core::sr25519::Pair; -// TODO: Remove after the Checks are migrated to TxExtension. -/// The extension to the basic transaction logic. -pub type TxExtension = ((CheckNonce, CheckWeight), CheckSubstrateCall); +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = (CheckNonce, CheckWeight, CheckSubstrateCall); /// The payload being signed in transactions. -pub type SignedPayload = sp_runtime::generic::SignedPayload; +pub type SignedPayload = sp_runtime::generic::SignedPayload; /// Unchecked extrinsic type as expected by this runtime. pub type Extrinsic = - sp_runtime::generic::UncheckedExtrinsic; + sp_runtime::generic::UncheckedExtrinsic; /// An identifier for an account on this system. pub type AccountId = ::Signer; @@ -246,7 +243,7 @@ impl sp_runtime::traits::Printable for CheckSubstrateCall { } impl sp_runtime::traits::Dispatchable for CheckSubstrateCall { - type RuntimeOrigin = RuntimeOrigin; + type RuntimeOrigin = CheckSubstrateCall; type Config = CheckSubstrateCall; type Info = CheckSubstrateCall; type PostInfo = CheckSubstrateCall; @@ -259,37 +256,42 @@ impl sp_runtime::traits::Dispatchable for CheckSubstrateCall { } } -impl sp_runtime::traits::TransactionExtensionBase for CheckSubstrateCall { - const IDENTIFIER: &'static str = "CheckSubstrateCall"; - type Implicit = (); -} -impl sp_runtime::traits::TransactionExtension - for CheckSubstrateCall -{ +impl sp_runtime::traits::SignedExtension for CheckSubstrateCall { + type AccountId = AccountId; + type Call = RuntimeCall; + type AdditionalSigned = (); type Pre = (); - type Val = (); - impl_tx_ext_default!(RuntimeCall; Context; prepare); + const IDENTIFIER: &'static str = "CheckSubstrateCall"; + + fn additional_signed( + &self, + ) -> sp_std::result::Result { + Ok(()) + } fn validate( &self, - origin: ::RuntimeOrigin, - call: &RuntimeCall, - _info: &DispatchInfoOf, + _who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> Result< - (ValidTransaction, Self::Val, ::RuntimeOrigin), - TransactionValidityError, - > { + ) -> TransactionValidity { log::trace!(target: LOG_TARGET, "validate"); - let v = match call { + match call { RuntimeCall::SubstrateTest(ref substrate_test_call) => - substrate_test_pallet::validate_runtime_call(substrate_test_call)?, - _ => Default::default(), - }; - Ok((v, (), origin)) + substrate_test_pallet::validate_runtime_call(substrate_test_call), + _ => Ok(Default::default()), + } + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &sp_runtime::traits::DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(drop) } } @@ -362,7 +364,6 @@ impl frame_system::pallet::Config for Runtime { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type ExtensionsWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; @@ -671,7 +672,7 @@ impl_runtime_apis! { impl sp_offchain::OffchainWorkerApi for Runtime { fn offchain_worker(header: &::Header) { - let ext = Extrinsic::new_bare( + let ext = Extrinsic::new_unsigned( substrate_test_pallet::pallet::Call::storage_change{ key:b"some_key".encode(), value:Some(header.number.encode()) @@ -1024,7 +1025,7 @@ mod tests { use sp_core::{storage::well_known_keys::HEAP_PAGES, traits::CallContext}; use sp_keyring::AccountKeyring; use sp_runtime::{ - traits::{DispatchTransaction, Hash as _}, + traits::{Hash as _, SignedExtension}, transaction_validity::{InvalidTransaction, ValidTransaction}, }; use substrate_test_runtime_client::{ @@ -1173,33 +1174,31 @@ mod tests { fn check_substrate_check_signed_extension_works() { sp_tracing::try_init_simple(); new_test_ext().execute_with(|| { - let x: AccountId = sp_keyring::AccountKeyring::Alice.into(); + let x = sp_keyring::AccountKeyring::Alice.into(); let info = DispatchInfo::default(); let len = 0_usize; assert_eq!( CheckSubstrateCall {} - .validate_only( - Some(x).into(), + .validate( + &x, &ExtrinsicBuilder::new_call_with_priority(16).build().function, &info, - len, + len ) .unwrap() - .0 .priority, 16 ); assert_eq!( CheckSubstrateCall {} - .validate_only( - Some(x).into(), + .validate( + &x, &ExtrinsicBuilder::new_call_do_not_propagate().build().function, &info, - len, + len ) .unwrap() - .0 .propagate, false ); diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/template.hbs b/substrate/utils/frame/benchmarking-cli/src/pallet/template.hbs index a044049a0d6..1e5e294acba 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/template.hbs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/template.hbs @@ -22,11 +22,7 @@ use core::marker::PhantomData; /// Weight functions for `{{pallet}}`. pub struct WeightInfo(PhantomData); -{{#if (eq pallet "frame_system_extensions")}} -impl frame_system::ExtensionsWeightInfo for WeightInfo { -{{else}} impl {{pallet}}::WeightInfo for WeightInfo { -{{/if}} {{#each benchmarks as |benchmark|}} {{#each benchmark.comments as |comment|}} /// {{comment}} diff --git a/substrate/utils/frame/remote-externalities/src/lib.rs b/substrate/utils/frame/remote-externalities/src/lib.rs index d49479d9cda..c7399468da9 100644 --- a/substrate/utils/frame/remote-externalities/src/lib.rs +++ b/substrate/utils/frame/remote-externalities/src/lib.rs @@ -1204,9 +1204,8 @@ where #[cfg(test)] mod test_prelude { pub(crate) use super::*; - pub(crate) use sp_runtime::testing::{Block as RawBlock, MockCallU64}; - pub(crate) type UncheckedXt = sp_runtime::generic::UncheckedExtrinsic; - pub(crate) type Block = RawBlock; + pub(crate) use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, H256 as Hash}; + pub(crate) type Block = RawBlock>; pub(crate) fn init_logger() { sp_tracing::try_init_simple(); diff --git a/substrate/utils/frame/rpc/client/src/lib.rs b/substrate/utils/frame/rpc/client/src/lib.rs index 4f4f4bbef56..221f260b156 100644 --- a/substrate/utils/frame/rpc/client/src/lib.rs +++ b/substrate/utils/frame/rpc/client/src/lib.rs @@ -199,15 +199,11 @@ where #[cfg(test)] mod tests { use super::*; - use sp_runtime::{ - generic::UncheckedExtrinsic, - testing::{Block as TBlock, Header, MockCallU64, H256}, - }; + use sp_runtime::testing::{Block as TBlock, ExtrinsicWrapper, Header, H256}; use std::sync::Arc; use tokio::sync::Mutex; - type UncheckedXt = UncheckedExtrinsic; - type Block = TBlock; + type Block = TBlock>; type BlockNumber = u64; type Hash = H256; diff --git a/templates/minimal/runtime/src/lib.rs b/templates/minimal/runtime/src/lib.rs index 6920511e276..91859cf4a2f 100644 --- a/templates/minimal/runtime/src/lib.rs +++ b/templates/minimal/runtime/src/lib.rs @@ -54,7 +54,7 @@ pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } -type TxExtension = ( +type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -111,7 +111,7 @@ impl pallet_transaction_payment::Config for Runtime { impl pallet_minimal_template::Config for Runtime {} -type Block = frame::runtime::types_common::BlockOf; +type Block = frame::runtime::types_common::BlockOf; type Header = HeaderFor; type RuntimeExecutive = diff --git a/templates/parachain/runtime/Cargo.toml b/templates/parachain/runtime/Cargo.toml index 44e9341b568..9d9da2b4b97 100644 --- a/templates/parachain/runtime/Cargo.toml +++ b/templates/parachain/runtime/Cargo.toml @@ -149,7 +149,6 @@ runtime-benchmarks = [ "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", "cumulus-primitives-core/runtime-benchmarks", - "cumulus-primitives-storage-weight-reclaim/runtime-benchmarks", "cumulus-primitives-utility/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", @@ -162,7 +161,6 @@ runtime-benchmarks = [ "pallet-parachain-template/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs index 74ecd751f67..89899d286bb 100644 --- a/templates/parachain/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -97,8 +97,8 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -112,7 +112,7 @@ pub type TxExtension = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -353,7 +353,6 @@ impl pallet_transaction_payment::Config for Runtime { type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; type OperationalFeeMultiplier = ConstU8<5>; - type WeightInfo = (); } impl pallet_sudo::Config for Runtime { @@ -531,7 +530,6 @@ construct_runtime!( mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] @@ -715,7 +713,6 @@ impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; let mut list = Vec::::new(); @@ -731,7 +728,6 @@ impl_runtime_apis! { use frame_benchmarking::{BenchmarkError, Benchmarking, BenchmarkBatch}; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; impl frame_system_benchmarking::Config for Runtime { fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); diff --git a/templates/solochain/node/Cargo.toml b/templates/solochain/node/Cargo.toml index 5e50e6106c1..48bb511bfd1 100644 --- a/templates/solochain/node/Cargo.toml +++ b/templates/solochain/node/Cargo.toml @@ -76,7 +76,6 @@ default = [] runtime-benchmarks = [ "frame-benchmarking-cli/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "sc-service/runtime-benchmarks", "solochain-template-runtime/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/templates/solochain/node/src/benchmarking.rs b/templates/solochain/node/src/benchmarking.rs index 8710f303e1f..d1d8c2ccaba 100644 --- a/templates/solochain/node/src/benchmarking.rs +++ b/templates/solochain/node/src/benchmarking.rs @@ -109,7 +109,7 @@ pub fn create_benchmark_extrinsic( .checked_next_power_of_two() .map(|c| c / 2) .unwrap_or(2) as u64; - let tx_ext: runtime::TxExtension = ( + let extra: runtime::SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -121,12 +121,11 @@ pub fn create_benchmark_extrinsic( frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ) - .into(); + ); let raw_payload = runtime::SignedPayload::from_raw( call.clone(), - tx_ext.clone(), + extra.clone(), ( (), runtime::VERSION.spec_version, @@ -144,7 +143,7 @@ pub fn create_benchmark_extrinsic( call, sp_runtime::AccountId32::from(sender.public()).into(), runtime::Signature::Sr25519(signature), - tx_ext, + extra, ) } diff --git a/templates/solochain/runtime/Cargo.toml b/templates/solochain/runtime/Cargo.toml index 706ea863d0f..a7fc0519ba2 100644 --- a/templates/solochain/runtime/Cargo.toml +++ b/templates/solochain/runtime/Cargo.toml @@ -130,7 +130,6 @@ runtime-benchmarks = [ "pallet-sudo/runtime-benchmarks", "pallet-template/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs index 303122da564..a8a5b7857e1 100644 --- a/templates/solochain/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -237,7 +237,6 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; type FeeMultiplierUpdate = ConstFeeMultiplier; - type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } impl pallet_sudo::Config for Runtime { @@ -301,8 +300,8 @@ pub type Address = sp_runtime::MultiAddress; pub type Header = generic::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; -/// The extension to the basic transaction logic. -pub type TxExtension = ( +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -321,9 +320,9 @@ type Migrations = (); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; + generic::UncheckedExtrinsic; /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -339,7 +338,6 @@ mod benches { frame_benchmarking::define_benchmarks!( [frame_benchmarking, BaselineBench::] [frame_system, SystemBench::] - [frame_system_extensions, SystemExtensionsBench::] [pallet_balances, Balances] [pallet_timestamp, Timestamp] [pallet_sudo, Sudo] @@ -524,7 +522,6 @@ impl_runtime_apis! { use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); @@ -541,7 +538,6 @@ impl_runtime_apis! { use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch}; use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; - use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use baseline::Pallet as BaselineBench; impl frame_system_benchmarking::Config for Runtime {} -- GitLab From 878b5dd010d4b4dfc7927018cce249ff51e13f33 Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:28:14 +0200 Subject: [PATCH 116/188] Always print connectivity report (#3677) This is printed every 10 minutes, I see no reason why it shouldn't be in all the logs, it would give us valuable information about what is going on with node connectivity when validators come-back to us to report issues. Signed-off-by: Alexandru Gheorghe --- polkadot/node/network/gossip-support/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/node/network/gossip-support/src/lib.rs b/polkadot/node/network/gossip-support/src/lib.rs index 4dfdd1f7208..9f33cd5d8a3 100644 --- a/polkadot/node/network/gossip-support/src/lib.rs +++ b/polkadot/node/network/gossip-support/src/lib.rs @@ -508,7 +508,7 @@ where ); } let pretty = PrettyAuthorities(unconnected_authorities); - gum::debug!( + gum::info!( target: LOG_TARGET, ?connected_ratio, ?absolute_connected, -- GitLab From 256546b7b9033ea99eb22b92c1d4cdec64c56516 Mon Sep 17 00:00:00 2001 From: Andrei Eres Date: Wed, 13 Mar 2024 17:54:41 +0100 Subject: [PATCH 117/188] Add subsystems regression tests to CI (#3527) Fixes https://github.com/paritytech/polkadot-sdk/issues/3530 --- .gitlab/pipeline/test.yml | 12 +++ ...ilability-distribution-regression-bench.rs | 77 ++++++------------- .../availability-recovery-regression-bench.rs | 63 +++++---------- polkadot/node/subsystem-bench/src/lib/lib.rs | 1 + .../node/subsystem-bench/src/lib/usage.rs | 4 +- .../node/subsystem-bench/src/lib/utils.rs | 76 ++++++++++++++++++ 6 files changed, 134 insertions(+), 99 deletions(-) create mode 100644 polkadot/node/subsystem-bench/src/lib/utils.rs diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index 5c41a3e6e08..26e55e9385f 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -494,3 +494,15 @@ test-syscalls: printf "The x86_64 syscalls used by the worker binaries have changed. Please review if this is expected and update polkadot/scripts/list-syscalls/*-worker-syscalls as needed.\n"; fi allow_failure: false # this rarely triggers in practice + +subsystem-regression-tests: + stage: test + extends: + - .docker-env + - .common-refs + - .run-immediately + script: + - cargo test --profile=testnet -p polkadot-availability-recovery --test availability-recovery-regression-bench --features subsystem-benchmarks + tags: + - benchmark + allow_failure: true diff --git a/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs b/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs index 7a490d5e47f..bdab11298d5 100644 --- a/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs +++ b/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs @@ -26,13 +26,9 @@ use polkadot_subsystem_bench::{ availability::{benchmark_availability_write, prepare_test, TestDataAvailability, TestState}, configuration::TestConfiguration, - usage::BenchmarkUsage, + utils::{warm_up_and_benchmark, WarmUpOptions}, }; -const BENCH_COUNT: usize = 3; -const WARM_UP_COUNT: usize = 30; -const WARM_UP_PRECISION: f64 = 0.01; - fn main() -> Result<(), String> { let mut messages = vec![]; let mut config = TestConfiguration::default(); @@ -41,17 +37,33 @@ fn main() -> Result<(), String> { config.num_blocks = 3; config.generate_pov_sizes(); - warm_up(config.clone())?; - let usage = benchmark(config.clone()); + let usage = warm_up_and_benchmark( + WarmUpOptions::new(&[ + "availability-distribution", + "bitfield-distribution", + "availability-store", + ]), + || { + let mut state = TestState::new(&config); + let (mut env, _protocol_config) = + prepare_test(config.clone(), &mut state, TestDataAvailability::Write, false); + env.runtime().block_on(benchmark_availability_write( + "data_availability_write", + &mut env, + state, + )) + }, + )?; + println!("{}", usage); messages.extend(usage.check_network_usage(&[ - ("Received from peers", 4330.0, 0.05), - ("Sent to peers", 15900.0, 0.05), + ("Received from peers", 443.333, 0.05), + ("Sent to peers", 21818.555, 0.05), ])); messages.extend(usage.check_cpu_usage(&[ - ("availability-distribution", 0.025, 0.05), - ("bitfield-distribution", 0.085, 0.05), - ("availability-store", 0.180, 0.05), + ("availability-distribution", 0.011, 0.05), + ("bitfield-distribution", 0.029, 0.05), + ("availability-store", 0.232, 0.05), ])); if messages.is_empty() { @@ -61,44 +73,3 @@ fn main() -> Result<(), String> { Err("Regressions found".to_string()) } } - -fn warm_up(config: TestConfiguration) -> Result<(), String> { - println!("Warming up..."); - let mut prev_run: Option = None; - for _ in 0..WARM_UP_COUNT { - let curr = run(config.clone()); - if let Some(ref prev) = prev_run { - let av_distr_diff = - curr.cpu_usage_diff(prev, "availability-distribution").expect("Must exist"); - let bitf_distr_diff = - curr.cpu_usage_diff(prev, "bitfield-distribution").expect("Must exist"); - let av_store_diff = - curr.cpu_usage_diff(prev, "availability-store").expect("Must exist"); - if av_distr_diff < WARM_UP_PRECISION && - bitf_distr_diff < WARM_UP_PRECISION && - av_store_diff < WARM_UP_PRECISION - { - return Ok(()) - } - } - prev_run = Some(curr); - } - - Err("Can't warm up".to_string()) -} - -fn benchmark(config: TestConfiguration) -> BenchmarkUsage { - println!("Benchmarking..."); - let usages: Vec = (0..BENCH_COUNT).map(|_| run(config.clone())).collect(); - let usage = BenchmarkUsage::average(&usages); - println!("{}", usage); - usage -} - -fn run(config: TestConfiguration) -> BenchmarkUsage { - let mut state = TestState::new(&config); - let (mut env, _protocol_config) = - prepare_test(config.clone(), &mut state, TestDataAvailability::Write, false); - env.runtime() - .block_on(benchmark_availability_write("data_availability_write", &mut env, state)) -} diff --git a/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs b/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs index 30cc4d47ecc..42b1787e045 100644 --- a/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs +++ b/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs @@ -27,13 +27,9 @@ use polkadot_subsystem_bench::{ TestDataAvailability, TestState, }, configuration::TestConfiguration, - usage::BenchmarkUsage, + utils::{warm_up_and_benchmark, WarmUpOptions}, }; -const BENCH_COUNT: usize = 3; -const WARM_UP_COUNT: usize = 10; -const WARM_UP_PRECISION: f64 = 0.01; - fn main() -> Result<(), String> { let mut messages = vec![]; @@ -42,14 +38,27 @@ fn main() -> Result<(), String> { config.num_blocks = 3; config.generate_pov_sizes(); - warm_up(config.clone(), options.clone())?; - let usage = benchmark(config.clone(), options.clone()); + let usage = warm_up_and_benchmark(WarmUpOptions::new(&["availability-recovery"]), || { + let mut state = TestState::new(&config); + let (mut env, _protocol_config) = prepare_test( + config.clone(), + &mut state, + TestDataAvailability::Read(options.clone()), + false, + ); + env.runtime().block_on(benchmark_availability_read( + "data_availability_read", + &mut env, + state, + )) + })?; + println!("{}", usage); messages.extend(usage.check_network_usage(&[ - ("Received from peers", 102400.000, 0.05), - ("Sent to peers", 0.335, 0.05), + ("Received from peers", 307200.000, 0.05), + ("Sent to peers", 1.667, 0.05), ])); - messages.extend(usage.check_cpu_usage(&[("availability-recovery", 3.850, 0.05)])); + messages.extend(usage.check_cpu_usage(&[("availability-recovery", 11.500, 0.05)])); if messages.is_empty() { Ok(()) @@ -58,37 +67,3 @@ fn main() -> Result<(), String> { Err("Regressions found".to_string()) } } - -fn warm_up(config: TestConfiguration, options: DataAvailabilityReadOptions) -> Result<(), String> { - println!("Warming up..."); - let mut prev_run: Option = None; - for _ in 0..WARM_UP_COUNT { - let curr = run(config.clone(), options.clone()); - if let Some(ref prev) = prev_run { - let diff = curr.cpu_usage_diff(prev, "availability-recovery").expect("Must exist"); - if diff < WARM_UP_PRECISION { - return Ok(()) - } - } - prev_run = Some(curr); - } - - Err("Can't warm up".to_string()) -} - -fn benchmark(config: TestConfiguration, options: DataAvailabilityReadOptions) -> BenchmarkUsage { - println!("Benchmarking..."); - let usages: Vec = - (0..BENCH_COUNT).map(|_| run(config.clone(), options.clone())).collect(); - let usage = BenchmarkUsage::average(&usages); - println!("{}", usage); - usage -} - -fn run(config: TestConfiguration, options: DataAvailabilityReadOptions) -> BenchmarkUsage { - let mut state = TestState::new(&config); - let (mut env, _protocol_config) = - prepare_test(config.clone(), &mut state, TestDataAvailability::Read(options), false); - env.runtime() - .block_on(benchmark_availability_read("data_availability_read", &mut env, state)) -} diff --git a/polkadot/node/subsystem-bench/src/lib/lib.rs b/polkadot/node/subsystem-bench/src/lib/lib.rs index d06f2822a89..ef2724abc98 100644 --- a/polkadot/node/subsystem-bench/src/lib/lib.rs +++ b/polkadot/node/subsystem-bench/src/lib/lib.rs @@ -26,3 +26,4 @@ pub(crate) mod keyring; pub(crate) mod mock; pub(crate) mod network; pub mod usage; +pub mod utils; diff --git a/polkadot/node/subsystem-bench/src/lib/usage.rs b/polkadot/node/subsystem-bench/src/lib/usage.rs index b83ef7d98d9..ef60d67372a 100644 --- a/polkadot/node/subsystem-bench/src/lib/usage.rs +++ b/polkadot/node/subsystem-bench/src/lib/usage.rs @@ -20,7 +20,7 @@ use colored::Colorize; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct BenchmarkUsage { pub benchmark_name: String, pub network_usage: Vec, @@ -110,7 +110,7 @@ fn check_resource_usage( } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct ResourceUsage { pub resource_name: String, pub total: f64, diff --git a/polkadot/node/subsystem-bench/src/lib/utils.rs b/polkadot/node/subsystem-bench/src/lib/utils.rs new file mode 100644 index 00000000000..75b72cc11b9 --- /dev/null +++ b/polkadot/node/subsystem-bench/src/lib/utils.rs @@ -0,0 +1,76 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Test utils + +use crate::usage::BenchmarkUsage; +use std::io::{stdout, Write}; + +pub struct WarmUpOptions<'a> { + /// The maximum number of runs considered for marming up. + pub warm_up: usize, + /// The number of runs considered for benchmarking. + pub bench: usize, + /// The difference in CPU usage between runs considered as normal + pub precision: f64, + /// The subsystems whose CPU usage is checked during warm-up cycles + pub subsystems: &'a [&'a str], +} + +impl<'a> WarmUpOptions<'a> { + pub fn new(subsystems: &'a [&'a str]) -> Self { + Self { warm_up: 100, bench: 3, precision: 0.02, subsystems } + } +} + +pub fn warm_up_and_benchmark( + options: WarmUpOptions, + run: impl Fn() -> BenchmarkUsage, +) -> Result { + println!("Warming up..."); + let mut usages = Vec::with_capacity(options.bench); + + for n in 1..=options.warm_up { + let curr = run(); + if let Some(prev) = usages.last() { + let diffs = options + .subsystems + .iter() + .map(|&v| { + curr.cpu_usage_diff(prev, v) + .ok_or(format!("{} not found in benchmark {:?}", v, prev)) + }) + .collect::, String>>()?; + if !diffs.iter().all(|&v| v < options.precision) { + usages.clear(); + } + } + usages.push(curr); + print!("\r{}%", n * 100 / options.warm_up); + if usages.len() == options.bench { + println!("\rTook {} runs to warm up", n.saturating_sub(options.bench)); + break; + } + stdout().flush().unwrap(); + } + + if usages.len() != options.bench { + println!("Didn't warm up after {} runs", options.warm_up); + return Err("Can't warm up".to_string()) + } + + Ok(BenchmarkUsage::average(&usages)) +} -- GitLab From c4c9257386036a9e27e7ee001fe8eadb80958cc0 Mon Sep 17 00:00:00 2001 From: Javier Viola <363911+pepoviola@users.noreply.github.com> Date: Thu, 14 Mar 2024 04:41:44 -0300 Subject: [PATCH 118/188] Increase timeout for assertions (#3680) Prevents timeouts in ci like https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5516019 --- .../testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl | 2 +- .../testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl | 2 +- .../testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl | 2 +- .../tests/0001-asset-transfer/wwnd-reaches-westend.zndsl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl index a58520ccea6..cdb7d28e940 100644 --- a/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl @@ -6,7 +6,7 @@ Creds: config asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-rococo-local 5000000000000" within 120 seconds # check that //Alice received at least 4.8 ROC on Westend AH -asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Rococo" within 300 seconds +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Rococo" within 600 seconds # check that the relayer //Charlie is rewarded by Westend AH bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726F,ThisChain,0" within 30 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl index fedb78cc210..dbc03864e2b 100644 --- a/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl @@ -6,7 +6,7 @@ Creds: config asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-westend-local 5000000000000" within 120 seconds # check that //Alice received at least 4.8 WND on Rococo AH -asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Westend" within 300 seconds +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Westend" within 600 seconds # check that the relayer //Charlie is rewarded by Rococo AH bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,ThisChain,0" within 30 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl index 68b888b6858..9967732cabe 100644 --- a/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl @@ -7,4 +7,4 @@ asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-as # check that //Alice received at least 2.8 wROC on Rococo AH # (we wait until //Alice account increases here - there are no other transactions that may increase it) -asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 300 seconds +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 600 seconds diff --git a/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl index 1a8a1618195..2037b0baf3c 100644 --- a/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl +++ b/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl @@ -7,4 +7,4 @@ asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-a # check that //Alice received at least 2.8 wWND on Westend AH # (we wait until //Alice account increases here - there are no other transactions that may increase it) -asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 300 seconds +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 600 seconds -- GitLab From d55d4f64b50c858bce6fa1a429f50d486cc67d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Pa=C4=8Dandi?= <3002868+Dinonard@users.noreply.github.com> Date: Thu, 14 Mar 2024 10:16:02 +0100 Subject: [PATCH 119/188] DescribeAllTerminal for HashedDescription (#3349) Make Rococo & Westend XCM's location converter `HashedDescription` more in line with Polkadot/Kusama runtimes. Co-authored-by: Muharem --- polkadot/runtime/rococo/src/xcm_config.rs | 6 +++--- polkadot/runtime/westend/src/xcm_config.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index af8981ddcc1..67f34916fe7 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -39,7 +39,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, - ChildParachainConvertsVia, DescribeBodyTerminal, DescribeFamily, FixedWeightBounds, + ChildParachainConvertsVia, DescribeAllTerminal, DescribeFamily, FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, HashedDescription, IsChildSystemParachain, IsConcrete, MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, @@ -63,8 +63,8 @@ pub type LocationConverter = ( ChildParachainConvertsVia, // We can directly alias an `AccountId32` into a local account. AccountId32Aliases, - // Allow governance body to be used as a sovereign account. - HashedDescription>, + // Foreign locations alias into accounts according to a hash of their standard description. + HashedDescription>, ); /// Our asset transactor. This is what allows us to interest with the runtime facilities from the diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index c57af987ca7..7281007f006 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -40,7 +40,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, - ChildParachainConvertsVia, DescribeBodyTerminal, DescribeFamily, FrameTransactionalProcessor, + ChildParachainConvertsVia, DescribeAllTerminal, DescribeFamily, FrameTransactionalProcessor, FungibleAdapter, HashedDescription, IsConcrete, MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, @@ -67,8 +67,8 @@ pub type LocationConverter = ( ChildParachainConvertsVia, // We can directly alias an `AccountId32` into a local account. AccountId32Aliases, - // Allow governance body to be used as a sovereign account. - HashedDescription>, + // Foreign locations alias into accounts according to a hash of their standard description. + HashedDescription>, ); pub type LocalAssetTransactor = FungibleAdapter< -- GitLab From 606664e1bd70ebe25adbf53b2547d8b10d4803c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Pestana?= Date: Thu, 14 Mar 2024 10:49:46 +0100 Subject: [PATCH 120/188] Staking ledger bonding fixes (#3639) Currently, the staking logic does not prevent a controller from becoming a stash of *another* ledger (introduced by [removing this check](https://github.com/paritytech/polkadot-sdk/pull/1484/files#diff-3aa6ceab5aa4e0ab2ed73a7245e0f5b42e0832d8ca5b1ed85d7b2a52fb196524L850)). Given that the remaining of the code expects that never happens, bonding a ledger with a stash that is a controller of another ledger may lead to data inconsistencies and data losses in bonded ledgers. For more detailed explanation of this issue: https://hackmd.io/@gpestana/HJoBm2tqo/%2FTPdi28H7Qc2mNUqLSMn15w In a nutshell, when fetching a ledger with a given controller, we may be end up getting the wrong ledger which can lead to unexpected ledger states. This PR also ensures that `set_controller` does not lead to data inconsistencies in the staking ledger and bonded storage in the case when a controller of a stash is a stash of *another* ledger. and improves the staking `try-runtime` checks to catch potential issues with the storage preemptively. In summary, there are two important cases here: 1. **"Sane" double bonded ledger** When a controller of a ledger is a stash of *another* ledger. In this case, we have: ``` > Bonded(stash, controller) (A, B) // stash A with controller B (B, C) // B is also a stash of another ledger (C, D) > Ledger(controller) Ledger(B) = L_a (stash = A) Ledger(C) = L_b (stash = B) Ledger(D) = L_c (stash = C) ``` In this case, the ledgers can be mutated and all operations are OK. However, we should not allow `set_controller` to be called if it means it results in a "corrupt" double bonded ledger (see below). 3. **"Corrupt" double bonded ledger** ``` > Bonded(stash, controller) (A, B) // stash A with controller B (B, B) (C, D) ``` In this case, B is a stash and controller AND is corrupted, since B is responsible for 2 ledgers which is not correct and will lead to inconsistent states. Thus, in this case, in this PR we are preventing these ledgers from mutating (i.e. operations like bonding extra etc) until the ledger is brought back to a consistent state. --- **Changes**: - Checks if stash is already a controller when calling `Call::bond` (fixes the regression introduced by [removing this check](https://github.com/paritytech/polkadot-sdk/pull/1484/files#diff-3aa6ceab5aa4e0ab2ed73a7245e0f5b42e0832d8ca5b1ed85d7b2a52fb196524L850)); - Ensures that all fetching ledgers from storage are done through the `StakingLedger` API; - Ensures that -- when fetching a ledger from storage using the `StakingLedger` API --, a `Error::BadState` is returned if the ledger bonding is in a bad state. This prevents bad ledgers from mutating (e.g. `bond_extra`, `set_controller`, etc) its state and avoid further data inconsistencies. - Prevents stashes which are controllers or another ledger from calling `set_controller`, since that may lead to a bad state. - Adds further try-state runtime checks that check if there are ledgers in a bad state based on their bonded metadata. Related to https://github.com/paritytech/polkadot-sdk/issues/3245 --------- Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: kianenigma --- prdoc/pr_3639.prdoc | 19 +++ substrate/frame/staking/src/ledger.rs | 61 +++++++- substrate/frame/staking/src/mock.rs | 51 +++++++ substrate/frame/staking/src/pallet/impls.rs | 84 ++++++++++- substrate/frame/staking/src/pallet/mod.rs | 28 ++-- substrate/frame/staking/src/tests.rs | 159 ++++++++++++++++++++ 6 files changed, 378 insertions(+), 24 deletions(-) create mode 100644 prdoc/pr_3639.prdoc diff --git a/prdoc/pr_3639.prdoc b/prdoc/pr_3639.prdoc new file mode 100644 index 00000000000..46e3f6f4d76 --- /dev/null +++ b/prdoc/pr_3639.prdoc @@ -0,0 +1,19 @@ +title: Prevents staking controllers from becoming stashes of different ledgers; Ensures that no ledger in bad state is mutated. + +doc: + - audience: Runtime User + description: | + This PR introduces a fix to the staking logic which prevents an existing controller from bonding as a stash of another ledger, which + lead to staking ledger inconsistencies down the line. In addition, it adds a few (temporary) gates to prevent ledgers that are already + in a bad state from mutating its state. + + In summary: + * Checks if stash is already a controller when calling `Call::bond` and fails if that's the case; + * Ensures that all fetching ledgers from storage are done through the `StakingLedger` API; + * Ensures that a `Error::BadState` is returned if the ledger bonding is in a bad state. This prevents bad ledgers from mutating (e.g. + `bond_extra`, `set_controller`, etc) its state and avoid further data inconsistencies. + * Prevents stashes which are controllers or another ledger from calling `set_controller`, since that may lead to a bad state. + * Adds further try-state runtime checks that check if there are ledgers in a bad state based on their bonded metadata. + +crates: +- name: pallet-staking diff --git a/substrate/frame/staking/src/ledger.rs b/substrate/frame/staking/src/ledger.rs index 5947adb9028..67be1e15bc6 100644 --- a/substrate/frame/staking/src/ledger.rs +++ b/substrate/frame/staking/src/ledger.rs @@ -32,8 +32,8 @@ //! state consistency. use frame_support::{ - defensive, - traits::{LockableCurrency, WithdrawReasons}, + defensive, ensure, + traits::{Defensive, LockableCurrency, WithdrawReasons}, }; use sp_staking::StakingAccount; use sp_std::prelude::*; @@ -106,18 +106,39 @@ impl StakingLedger { /// This getter can be called with either a controller or stash account, provided that the /// account is properly wrapped in the respective [`StakingAccount`] variant. This is meant to /// abstract the concept of controller/stash accounts from the caller. + /// + /// Returns [`Error::BadState`] when a bond is in "bad state". A bond is in a bad state when a + /// stash has a controller which is bonding a ledger associated with another stash. pub(crate) fn get(account: StakingAccount) -> Result, Error> { - let controller = match account { - StakingAccount::Stash(stash) => >::get(stash).ok_or(Error::::NotStash), - StakingAccount::Controller(controller) => Ok(controller), - }?; + let (stash, controller) = match account.clone() { + StakingAccount::Stash(stash) => + (stash.clone(), >::get(&stash).ok_or(Error::::NotStash)?), + StakingAccount::Controller(controller) => ( + Ledger::::get(&controller) + .map(|l| l.stash) + .ok_or(Error::::NotController)?, + controller, + ), + }; - >::get(&controller) + let ledger = >::get(&controller) .map(|mut ledger| { ledger.controller = Some(controller.clone()); ledger }) - .ok_or(Error::::NotController) + .ok_or(Error::::NotController)?; + + // if ledger bond is in a bad state, return error to prevent applying operations that may + // further spoil the ledger's state. A bond is in bad state when the bonded controller is + // associted with a different ledger (i.e. a ledger with a different stash). + // + // See for more details. + ensure!( + Bonded::::get(&stash) == Some(controller) && ledger.stash == stash, + Error::::BadState + ); + + Ok(ledger) } /// Returns the reward destination of a staking ledger, stored in [`Payee`]. @@ -201,6 +222,30 @@ impl StakingLedger { } } + /// Sets the ledger controller to its stash. + pub(crate) fn set_controller_to_stash(self) -> Result<(), Error> { + let controller = self.controller.as_ref() + .defensive_proof("Ledger's controller field didn't exist. The controller should have been fetched using StakingLedger.") + .ok_or(Error::::NotController)?; + + ensure!(self.stash != *controller, Error::::AlreadyPaired); + + // check if the ledger's stash is a controller of another ledger. + if let Some(bonded_ledger) = Ledger::::get(&self.stash) { + // there is a ledger bonded by the stash. In this case, the stash of the bonded ledger + // should be the same as the ledger's stash. Otherwise fail to prevent data + // inconsistencies. See for more + // details. + ensure!(bonded_ledger.stash == self.stash, Error::::BadState); + } + + >::remove(&controller); + >::insert(&self.stash, &self); + >::insert(&self.stash, &self.stash); + + Ok(()) + } + /// Clears all data related to a staking ledger and its bond in both [`Ledger`] and [`Bonded`] /// storage items and updates the stash staking lock. pub(crate) fn kill(stash: &T::AccountId) -> Result<(), Error> { diff --git a/substrate/frame/staking/src/mock.rs b/substrate/frame/staking/src/mock.rs index 24311cb9e78..65e660f248d 100644 --- a/substrate/frame/staking/src/mock.rs +++ b/substrate/frame/staking/src/mock.rs @@ -786,6 +786,57 @@ pub(crate) fn bond_controller_stash(controller: AccountId, stash: AccountId) -> Ok(()) } +pub(crate) fn setup_double_bonded_ledgers() { + assert_ok!(Staking::bond(RuntimeOrigin::signed(1), 10, RewardDestination::Staked)); + assert_ok!(Staking::bond(RuntimeOrigin::signed(2), 20, RewardDestination::Staked)); + assert_ok!(Staking::bond(RuntimeOrigin::signed(3), 20, RewardDestination::Staked)); + // not relevant to the test case, but ensures try-runtime checks pass. + [1, 2, 3] + .iter() + .for_each(|s| Payee::::insert(s, RewardDestination::Staked)); + + // we want to test the case where a controller can also be a stash of another ledger. + // for that, we change the controller/stash bonding so that: + // * 2 becomes controller of 1. + // * 3 becomes controller of 2. + // * 4 becomes controller of 3. + let ledger_1 = Ledger::::get(1).unwrap(); + let ledger_2 = Ledger::::get(2).unwrap(); + let ledger_3 = Ledger::::get(3).unwrap(); + + // 4 becomes controller of 3. + Bonded::::mutate(3, |controller| *controller = Some(4)); + Ledger::::insert(4, ledger_3); + + // 3 becomes controller of 2. + Bonded::::mutate(2, |controller| *controller = Some(3)); + Ledger::::insert(3, ledger_2); + + // 2 becomes controller of 1 + Bonded::::mutate(1, |controller| *controller = Some(2)); + Ledger::::insert(2, ledger_1); + // 1 is not controller anymore. + Ledger::::remove(1); + + // checks. now we have: + // * 3 ledgers + assert_eq!(Ledger::::iter().count(), 3); + // * stash 1 has controller 2. + assert_eq!(Bonded::::get(1), Some(2)); + assert_eq!(StakingLedger::::paired_account(StakingAccount::Stash(1)), Some(2)); + assert_eq!(Ledger::::get(2).unwrap().stash, 1); + + // * stash 2 has controller 3. + assert_eq!(Bonded::::get(2), Some(3)); + assert_eq!(StakingLedger::::paired_account(StakingAccount::Stash(2)), Some(3)); + assert_eq!(Ledger::::get(3).unwrap().stash, 2); + + // * stash 3 has controller 4. + assert_eq!(Bonded::::get(3), Some(4)); + assert_eq!(StakingLedger::::paired_account(StakingAccount::Stash(3)), Some(4)); + assert_eq!(Ledger::::get(4).unwrap().stash, 3); +} + #[macro_export] macro_rules! assert_session_era { ($session:expr, $era:expr) => { diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 757c46f4faf..d42456e53b1 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -165,7 +165,8 @@ impl Pallet { let controller = Self::bonded(&validator_stash).ok_or_else(|| { Error::::NotStash.with_weight(T::WeightInfo::payout_stakers_alive_staked(0)) })?; - let ledger = >::get(&controller).ok_or(Error::::NotController)?; + + let ledger = Self::ledger(StakingAccount::Controller(controller))?; let page = EraInfo::::get_next_claimable_page(era, &validator_stash, &ledger) .ok_or_else(|| { Error::::AlreadyClaimed @@ -1728,7 +1729,7 @@ impl StakingInterface for Pallet { ) -> Result { let ctrl = Self::bonded(&who).ok_or(Error::::NotStash)?; Self::withdraw_unbonded(RawOrigin::Signed(ctrl.clone()).into(), num_slashing_spans) - .map(|_| !Ledger::::contains_key(&ctrl)) + .map(|_| !StakingLedger::::is_bonded(StakingAccount::Controller(ctrl))) .map_err(|with_post| with_post.error) } @@ -1836,6 +1837,7 @@ impl Pallet { "VoterList contains non-staker" ); + Self::check_bonded_consistency()?; Self::check_payees()?; Self::check_nominators()?; Self::check_exposures()?; @@ -1844,9 +1846,67 @@ impl Pallet { Self::check_count() } + /// Invariants: + /// * A controller should not be associated with more than one ledger. + /// * A bonded (stash, controller) pair should have only one associated ledger. I.e. if the + /// ledger is bonded by stash, the controller account must not bond a different ledger. + /// * A bonded (stash, controller) pair must have an associated ledger. + /// NOTE: these checks result in warnings only. Once + /// is resolved, turn warns into check + /// failures. + fn check_bonded_consistency() -> Result<(), TryRuntimeError> { + use sp_std::collections::btree_set::BTreeSet; + + let mut count_controller_double = 0; + let mut count_double = 0; + let mut count_none = 0; + // sanity check to ensure that each controller in Bonded storage is associated with only one + // ledger. + let mut controllers = BTreeSet::new(); + + for (stash, controller) in >::iter() { + if !controllers.insert(controller.clone()) { + count_controller_double += 1; + } + + match (>::get(&stash), >::get(&controller)) { + (Some(_), Some(_)) => + // if stash == controller, it means that the ledger has migrated to + // post-controller. If no migration happened, we expect that the (stash, + // controller) pair has only one associated ledger. + if stash != controller { + count_double += 1; + }, + (None, None) => { + count_none += 1; + }, + _ => {}, + }; + } + + if count_controller_double != 0 { + log!( + warn, + "a controller is associated with more than one ledger ({} occurrences)", + count_controller_double + ); + }; + + if count_double != 0 { + log!(warn, "single tuple of (stash, controller) pair bonds more than one ledger ({} occurrences)", count_double); + } + + if count_none != 0 { + log!(warn, "inconsistent bonded state: (stash, controller) pair missing associated ledger ({} occurrences)", count_none); + } + + Ok(()) + } + /// Invariants: /// * A bonded ledger should always have an assigned `Payee`. /// * The number of entries in `Payee` and of bonded staking ledgers *must* match. + /// * The stash account in the ledger must match that of the bonded acount. fn check_payees() -> Result<(), TryRuntimeError> { for (stash, _) in Bonded::::iter() { ensure!(Payee::::get(&stash).is_some(), "bonded ledger does not have payee set"); @@ -1861,6 +1921,11 @@ impl Pallet { Ok(()) } + /// Invariants: + /// * Number of voters in `VoterList` match that of the number of Nominators and Validators in + /// the system (validator is both voter and target). + /// * Number of targets in `TargetList` matches the number of validators in the system. + /// * Current validator count is bounded by the election provider's max winners. fn check_count() -> Result<(), TryRuntimeError> { ensure!( ::VoterList::count() == @@ -1879,6 +1944,11 @@ impl Pallet { Ok(()) } + /// Invariants: + /// * `ledger.controller` is not stored in the storage (but populated at retrieval). + /// * Stake consistency: ledger.total == ledger.active + sum(ledger.unlocking). + /// * The controller keyeing the ledger and the ledger stash matches the state of the `Bonded` + /// storage. fn check_ledgers() -> Result<(), TryRuntimeError> { Bonded::::iter() .map(|(stash, ctrl)| { @@ -1896,8 +1966,10 @@ impl Pallet { Ok(()) } + /// Invariants: + /// * For each era exposed validator, check if the exposure total is sane (exposure.total = + /// exposure.own + exposure.own). fn check_exposures() -> Result<(), TryRuntimeError> { - // a check per validator to ensure the exposure struct is always sane. let era = Self::active_era().unwrap().index; ErasStakers::::iter_prefix_values(era) .map(|expo| { @@ -1915,6 +1987,10 @@ impl Pallet { .collect::>() } + /// Invariants: + /// * For each paged era exposed validator, check if the exposure total is sane (exposure.total + /// = exposure.own + exposure.own). + /// * Paged exposures metadata (`ErasStakersOverview`) matches the paged exposures state. fn check_paged_exposures() -> Result<(), TryRuntimeError> { use sp_staking::PagedExposureMetadata; use sp_std::collections::btree_map::BTreeMap; @@ -1979,6 +2055,8 @@ impl Pallet { .collect::>() } + /// Invariants: + /// * Checks that each nominator has its entire stake correctly distributed. fn check_nominators() -> Result<(), TryRuntimeError> { // a check per nominator to ensure their entire stake is correctly distributed. Will only // kick-in if the nomination was submitted before the current era. diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 992a7fe2c9c..1bf8bd8b09c 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -791,6 +791,8 @@ pub mod pallet { SnapshotTargetsSizeExceeded { size: u32 }, /// A new force era mode was set. ForceEra { mode: Forcing }, + /// Report of a controller batch deprecation. + ControllerBatchDeprecated { failures: u32 }, } #[pallet::error] @@ -935,6 +937,11 @@ pub mod pallet { return Err(Error::::AlreadyBonded.into()) } + // An existing controller cannot become a stash. + if StakingLedger::::is_bonded(StakingAccount::Controller(stash.clone())) { + return Err(Error::::AlreadyPaired.into()) + } + // Reject a bond which is considered to be _dust_. if value < T::Currency::minimum_balance() { return Err(Error::::InsufficientBond.into()) @@ -975,7 +982,6 @@ pub mod pallet { #[pallet::compact] max_additional: BalanceOf, ) -> DispatchResult { let stash = ensure_signed(origin)?; - let mut ledger = Self::ledger(StakingAccount::Stash(stash.clone()))?; let stash_balance = T::Currency::free_balance(&stash); @@ -1332,8 +1338,6 @@ pub mod pallet { pub fn set_controller(origin: OriginFor) -> DispatchResult { let stash = ensure_signed(origin)?; - // The bonded map and ledger are mutated directly as this extrinsic is related to a - // (temporary) passive migration. Self::ledger(StakingAccount::Stash(stash.clone())).map(|ledger| { let controller = ledger.controller() .defensive_proof("Ledger's controller field didn't exist. The controller should have been fetched using StakingLedger.") @@ -1343,9 +1347,8 @@ pub mod pallet { // Stash is already its own controller. return Err(Error::::AlreadyPaired.into()) } - >::remove(controller); - >::insert(&stash, &stash); - >::insert(&stash, ledger); + + let _ = ledger.set_controller_to_stash()?; Ok(()) })? } @@ -1960,7 +1963,7 @@ pub mod pallet { }; if ledger.stash != *controller && !payee_deprecated { - Some((controller.clone(), ledger)) + Some(ledger) } else { None } @@ -1969,13 +1972,12 @@ pub mod pallet { .collect(); // Update unique pairs. - for (controller, ledger) in filtered_batch_with_ledger { - let stash = ledger.stash.clone(); - - >::insert(&stash, &stash); - >::remove(controller); - >::insert(stash, ledger); + let mut failures = 0; + for ledger in filtered_batch_with_ledger { + let _ = ledger.clone().set_controller_to_stash().map_err(|_| failures += 1); } + Self::deposit_event(Event::::ControllerBatchDeprecated { failures }); + Ok(Some(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32)).into()) } } diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index 3f4e28b1f6a..3725c9e3c2c 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -1248,6 +1248,23 @@ fn bond_extra_works() { }); } +#[test] +fn bond_extra_controller_bad_state_works() { + ExtBuilder::default().try_state(false).build_and_execute(|| { + assert_eq!(StakingLedger::::get(StakingAccount::Stash(31)).unwrap().stash, 31); + + // simulate ledger in bad state: the controller 41 is associated to the stash 31 and 41. + Bonded::::insert(31, 41); + + // we confirm that the ledger is in bad state: 31 has 41 as controller and when fetching + // the ledger associated with the controler 41, its stash is 41 (and not 31). + assert_eq!(Ledger::::get(41).unwrap().stash, 41); + + // if the ledger is in this bad state, the `bond_extra` should fail. + assert_noop!(Staking::bond_extra(RuntimeOrigin::signed(31), 10), Error::::BadState); + }) +} + #[test] fn bond_extra_and_withdraw_unbonded_works() { // @@ -6910,6 +6927,49 @@ mod ledger { }) } + #[test] + fn get_ledger_bad_state_fails() { + ExtBuilder::default().has_stakers(false).try_state(false).build_and_execute(|| { + setup_double_bonded_ledgers(); + + // Case 1: double bonded but not corrupted: + // stash 2 has controller 3: + assert_eq!(Bonded::::get(2), Some(3)); + assert_eq!(Ledger::::get(3).unwrap().stash, 2); + + // stash 2 is also a controller of 1: + assert_eq!(Bonded::::get(1), Some(2)); + assert_eq!(StakingLedger::::paired_account(StakingAccount::Stash(1)), Some(2)); + assert_eq!(Ledger::::get(2).unwrap().stash, 1); + + // although 2 is double bonded (it is a controller and a stash of different ledgers), + // we can safely retrieve the ledger and mutate it since the correct ledger is + // returned. + let ledger_result = StakingLedger::::get(StakingAccount::Stash(2)); + assert_eq!(ledger_result.unwrap().stash, 2); // correct ledger. + + let ledger_result = StakingLedger::::get(StakingAccount::Controller(2)); + assert_eq!(ledger_result.unwrap().stash, 1); // correct ledger. + + // fetching ledger 1 by its stash works. + let ledger_result = StakingLedger::::get(StakingAccount::Stash(1)); + assert_eq!(ledger_result.unwrap().stash, 1); + + // Case 2: corrupted ledger bonding. + // in this case, we simulate what happens when fetching a ledger by stash returns a + // ledger with a different stash. when this happens, we return an error instead of the + // ledger to prevent ledger mutations. + let mut ledger = Ledger::::get(2).unwrap(); + assert_eq!(ledger.stash, 1); + ledger.stash = 2; + Ledger::::insert(2, ledger); + + // now, we are prevented from fetching the ledger by stash from 1. It's associated + // controller (2) is now bonding a ledger with a different stash (2, not 1). + assert!(StakingLedger::::get(StakingAccount::Stash(1)).is_err()); + }) + } + #[test] fn bond_works() { ExtBuilder::default().build_and_execute(|| { @@ -6933,6 +6993,28 @@ mod ledger { }) } + #[test] + fn bond_controller_cannot_be_stash_works() { + ExtBuilder::default().build_and_execute(|| { + let (stash, controller) = testing_utils::create_unique_stash_controller::( + 0, + 10, + RewardDestination::Staked, + false, + ) + .unwrap(); + + assert_eq!(Bonded::::get(stash), Some(controller)); + assert_eq!(Ledger::::get(controller).map(|l| l.stash), Some(stash)); + + // existing controller should not be able become a stash. + assert_noop!( + Staking::bond(RuntimeOrigin::signed(controller), 10, RewardDestination::Staked), + Error::::AlreadyPaired, + ); + }) + } + #[test] fn is_bonded_works() { ExtBuilder::default().build_and_execute(|| { @@ -7161,4 +7243,81 @@ mod ledger { assert_eq!(ledger_updated.stash, stash); }) } + + #[test] + fn deprecate_controller_batch_with_bad_state_ok() { + ExtBuilder::default().has_stakers(false).nominate(false).build_and_execute(|| { + setup_double_bonded_ledgers(); + + // now let's deprecate all the controllers for all the existing ledgers. + let bounded_controllers: BoundedVec< + _, + ::MaxControllersInDeprecationBatch, + > = BoundedVec::try_from(vec![1, 2, 3, 4]).unwrap(); + + assert_ok!(Staking::deprecate_controller_batch( + RuntimeOrigin::root(), + bounded_controllers + )); + + assert_eq!( + *staking_events().last().unwrap(), + Event::ControllerBatchDeprecated { failures: 0 } + ); + }) + } + + #[test] + fn deprecate_controller_batch_with_bad_state_failures() { + ExtBuilder::default().has_stakers(false).try_state(false).build_and_execute(|| { + setup_double_bonded_ledgers(); + + // now let's deprecate all the controllers for all the existing ledgers. + let bounded_controllers: BoundedVec< + _, + ::MaxControllersInDeprecationBatch, + > = BoundedVec::try_from(vec![4, 3, 2, 1]).unwrap(); + + assert_ok!(Staking::deprecate_controller_batch( + RuntimeOrigin::root(), + bounded_controllers + )); + + assert_eq!( + *staking_events().last().unwrap(), + Event::ControllerBatchDeprecated { failures: 2 } + ); + }) + } + + #[test] + fn set_controller_with_bad_state_ok() { + ExtBuilder::default().has_stakers(false).nominate(false).build_and_execute(|| { + setup_double_bonded_ledgers(); + + // in this case, setting controller works due to the ordering of the calls. + assert_ok!(Staking::set_controller(RuntimeOrigin::signed(1))); + assert_ok!(Staking::set_controller(RuntimeOrigin::signed(2))); + assert_ok!(Staking::set_controller(RuntimeOrigin::signed(3))); + }) + } + + #[test] + fn set_controller_with_bad_state_fails() { + ExtBuilder::default().has_stakers(false).try_state(false).build_and_execute(|| { + setup_double_bonded_ledgers(); + + // setting the controller of ledger associated with stash 3 fails since its stash is a + // controller of another ledger. + assert_noop!( + Staking::set_controller(RuntimeOrigin::signed(3)), + Error::::BadState + ); + assert_noop!( + Staking::set_controller(RuntimeOrigin::signed(2)), + Error::::BadState + ); + assert_ok!(Staking::set_controller(RuntimeOrigin::signed(1))); + }) + } } -- GitLab From cfc4050d6b95619b969a92d32e71a874aa5ef38a Mon Sep 17 00:00:00 2001 From: Ignacio Palacios Date: Thu, 14 Mar 2024 11:29:24 +0100 Subject: [PATCH 121/188] Improve Penpal runtime + emulated tests (#3543) Issues addressed in this PR: - Improve *Penpal* runtime: - Properly handled received assets. Previously, it treated `(1, Here)` as the local native currency, whereas it should be treated as a `ForeignAsset`. This wasn't a great example of standard Parachain behaviour, as no Parachain treats the system asset as the local currency. - Remove `AllowExplicitUnpaidExecutionFrom` the system. Again, this wasn't a great example of standard Parachain behaviour. - Move duplicated `ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger` to `assets_common` crate. - Improve emulated tests: - Update *Penpal* tests to new runtime. - To simplify tests, register the reserve transferred, teleported, and system assets in *Penpal* and *AssetHub* genesis. This saves us from having to create the assets repeatedly for each test - Add missing test case: `reserve_transfer_assets_from_para_to_system_para`. - Cleanup. - Prevent integration tests crates imports from being re-exported, as they were polluting the `polkadot-sdk` docs. There is still a test case missing for reserve transfers: - Reserve transfer of system asset from *Parachain* to *Parachain* trough *AssetHub*. - This is not yet possible with `pallet-xcm` due to the reasons explained in https://github.com/paritytech/polkadot-sdk/pull/3339 --------- Co-authored-by: command-bot <> --- Cargo.lock | 6 +- .../assets/asset-hub-rococo/src/genesis.rs | 29 +- .../assets/asset-hub-rococo/src/lib.rs | 6 +- .../assets/asset-hub-westend/src/genesis.rs | 29 +- .../assets/asset-hub-westend/src/lib.rs | 6 +- .../parachains/testing/penpal/Cargo.toml | 5 +- .../parachains/testing/penpal/src/genesis.rs | 43 +- .../parachains/testing/penpal/src/lib.rs | 11 +- .../emulated/common/Cargo.toml | 1 + .../emulated/common/src/impls.rs | 150 ++- .../emulated/common/src/lib.rs | 23 +- .../emulated/common/src/macros.rs | 111 +-- .../tests/assets/asset-hub-rococo/Cargo.toml | 1 + .../tests/assets/asset-hub-rococo/src/lib.rs | 116 ++- .../assets/asset-hub-rococo/src/tests/mod.rs | 8 - .../src/tests/reserve_transfer.rs | 829 +++++++++++++--- .../assets/asset-hub-rococo/src/tests/send.rs | 129 ++- .../src/tests/set_xcm_versions.rs | 2 +- .../assets/asset-hub-rococo/src/tests/swap.rs | 58 +- .../asset-hub-rococo/src/tests/teleport.rs | 135 ++- .../tests/assets/asset-hub-westend/Cargo.toml | 1 + .../tests/assets/asset-hub-westend/src/lib.rs | 128 +-- .../src/tests/fellowship_treasury.rs | 2 +- .../assets/asset-hub-westend/src/tests/mod.rs | 8 - .../src/tests/reserve_transfer.rs | 903 ++++++++++++++---- .../asset-hub-westend/src/tests/send.rs | 143 ++- .../src/tests/set_xcm_versions.rs | 2 +- .../asset-hub-westend/src/tests/swap.rs | 107 +-- .../asset-hub-westend/src/tests/teleport.rs | 226 +++-- .../asset-hub-westend/src/tests/treasury.rs | 2 +- .../bridges/bridge-hub-rococo/src/lib.rs | 97 +- .../bridge-hub-rococo/src/tests/mod.rs | 2 +- .../bridge-hub-rococo/src/tests/snowbridge.rs | 2 +- .../bridge-hub-rococo/src/tests/teleport.rs | 2 +- .../bridges/bridge-hub-westend/src/lib.rs | 93 +- .../bridge-hub-westend/src/tests/mod.rs | 2 +- .../bridge-hub-westend/src/tests/teleport.rs | 2 +- .../tests/people/people-rococo/src/lib.rs | 73 +- .../people-rococo/src/tests/reap_identity.rs | 2 +- .../people-rococo/src/tests/teleport.rs | 2 +- .../tests/people/people-westend/src/lib.rs | 74 +- .../people-westend/src/tests/reap_identity.rs | 2 +- .../people-westend/src/tests/teleport.rs | 2 +- .../assets/asset-hub-rococo/tests/tests.rs | 8 +- .../assets/asset-hub-westend/tests/tests.rs | 8 +- .../runtimes/testing/penpal/src/lib.rs | 9 +- .../runtimes/testing/penpal/src/xcm_config.rs | 139 ++- 47 files changed, 2560 insertions(+), 1179 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8cbbbce209a..e1bd596a7a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -841,6 +841,7 @@ dependencies = [ "pallet-xcm", "parachains-common", "parity-scale-codec", + "penpal-runtime", "rococo-runtime", "rococo-system-emulated-network", "sp-runtime", @@ -962,6 +963,7 @@ dependencies = [ "pallet-xcm", "parachains-common", "parity-scale-codec", + "penpal-runtime", "polkadot-runtime-common", "sp-runtime", "staging-xcm", @@ -4931,6 +4933,7 @@ dependencies = [ "parachains-common", "parity-scale-codec", "paste", + "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-parachains", "sc-consensus-grandpa", @@ -11645,9 +11648,8 @@ dependencies = [ "frame-support", "parachains-common", "penpal-runtime", - "rococo-emulated-chain", "sp-core", - "westend-emulated-chain", + "staging-xcm", ] [[package]] diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/genesis.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/genesis.rs index 80db5644469..2acccb9649b 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/genesis.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/genesis.rs @@ -14,17 +14,24 @@ // limitations under the License. // Substrate -use sp_core::storage::Storage; +use frame_support::parameter_types; +use sp_core::{sr25519, storage::Storage}; // Cumulus use emulated_integration_tests_common::{ - accounts, build_genesis_storage, collators, SAFE_XCM_VERSION, + accounts, build_genesis_storage, collators, get_account_id_from_seed, + PenpalSiblingSovereigAccount, PenpalTeleportableAssetLocation, RESERVABLE_ASSET_ID, + SAFE_XCM_VERSION, }; -use parachains_common::Balance; +use parachains_common::{AccountId, Balance}; pub const PARA_ID: u32 = 1000; pub const ED: Balance = testnet_parachains_constants::rococo::currency::EXISTENTIAL_DEPOSIT; +parameter_types! { + pub AssetHubRococoAssetOwner: AccountId = get_account_id_from_seed::("Alice"); +} + pub fn genesis() -> Storage { let genesis_config = asset_hub_rococo_runtime::RuntimeGenesisConfig { system: asset_hub_rococo_runtime::SystemConfig::default(), @@ -60,6 +67,22 @@ pub fn genesis() -> Storage { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + assets: asset_hub_rococo_runtime::AssetsConfig { + assets: vec![(RESERVABLE_ASSET_ID, AssetHubRococoAssetOwner::get(), true, ED)], + ..Default::default() + }, + foreign_assets: asset_hub_rococo_runtime::ForeignAssetsConfig { + assets: vec![ + // Penpal's teleportable asset representation + ( + PenpalTeleportableAssetLocation::get(), + PenpalSiblingSovereigAccount::get(), + true, + ED, + ), + ], + ..Default::default() + }, ..Default::default() }; diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs index 00f41256420..f1e972e869d 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs @@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize; // Cumulus use emulated_integration_tests_common::{ impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, - impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain, + impl_assets_helpers_for_parachain, impl_assets_helpers_for_system_parachain, impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains, }; use rococo_emulated_chain::Rococo; @@ -54,6 +54,6 @@ decl_test_parachains! { // AssetHubRococo implementation impl_accounts_helpers_for_parachain!(AssetHubRococo); impl_assert_events_helpers_for_parachain!(AssetHubRococo); -impl_assets_helpers_for_parachain!(AssetHubRococo, Rococo); -impl_foreign_assets_helpers_for_parachain!(AssetHubRococo, Rococo); +impl_assets_helpers_for_system_parachain!(AssetHubRococo, Rococo); +impl_assets_helpers_for_parachain!(AssetHubRococo); impl_xcm_helpers_for_parachain!(AssetHubRococo); diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/genesis.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/genesis.rs index b2e4645ee07..e30529aff42 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/genesis.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/genesis.rs @@ -14,17 +14,24 @@ // limitations under the License. // Substrate -use sp_core::storage::Storage; +use frame_support::parameter_types; +use sp_core::{sr25519, storage::Storage}; // Cumulus use emulated_integration_tests_common::{ - accounts, build_genesis_storage, collators, SAFE_XCM_VERSION, + accounts, build_genesis_storage, collators, get_account_id_from_seed, + PenpalSiblingSovereigAccount, PenpalTeleportableAssetLocation, RESERVABLE_ASSET_ID, + SAFE_XCM_VERSION, }; -use parachains_common::Balance; +use parachains_common::{AccountId, Balance}; pub const PARA_ID: u32 = 1000; pub const ED: Balance = testnet_parachains_constants::westend::currency::EXISTENTIAL_DEPOSIT; +parameter_types! { + pub AssetHubWestendAssetOwner: AccountId = get_account_id_from_seed::("Alice"); +} + pub fn genesis() -> Storage { let genesis_config = asset_hub_westend_runtime::RuntimeGenesisConfig { system: asset_hub_westend_runtime::SystemConfig::default(), @@ -56,6 +63,22 @@ pub fn genesis() -> Storage { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + assets: asset_hub_westend_runtime::AssetsConfig { + assets: vec![(RESERVABLE_ASSET_ID, AssetHubWestendAssetOwner::get(), true, ED)], + ..Default::default() + }, + foreign_assets: asset_hub_westend_runtime::ForeignAssetsConfig { + assets: vec![ + // Penpal's teleportable asset representation + ( + PenpalTeleportableAssetLocation::get(), + PenpalSiblingSovereigAccount::get(), + true, + ED, + ), + ], + ..Default::default() + }, ..Default::default() }; diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs index 25d7c1079b4..7f05eefb4c2 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs @@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize; // Cumulus use emulated_integration_tests_common::{ impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, - impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain, + impl_assets_helpers_for_parachain, impl_assets_helpers_for_system_parachain, impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains, }; use westend_emulated_chain::Westend; @@ -54,6 +54,6 @@ decl_test_parachains! { // AssetHubWestend implementation impl_accounts_helpers_for_parachain!(AssetHubWestend); impl_assert_events_helpers_for_parachain!(AssetHubWestend); -impl_assets_helpers_for_parachain!(AssetHubWestend, Westend); -impl_foreign_assets_helpers_for_parachain!(AssetHubWestend, Westend); +impl_assets_helpers_for_system_parachain!(AssetHubWestend, Westend); +impl_assets_helpers_for_parachain!(AssetHubWestend); impl_xcm_helpers_for_parachain!(AssetHubWestend); diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml index a853825d8ef..f47350b00eb 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml @@ -16,10 +16,11 @@ workspace = true sp-core = { path = "../../../../../../../../substrate/primitives/core", default-features = false } frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } +# Polkadot +xcm = { package = "staging-xcm", path = "../../../../../../../../polkadot/xcm", default-features = false } + # Cumulus parachains-common = { path = "../../../../../../../parachains/common" } cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false } emulated-integration-tests-common = { path = "../../../../common", default-features = false } penpal-runtime = { path = "../../../../../../runtimes/testing/penpal" } -rococo-emulated-chain = { path = "../../../relays/rococo" } -westend-emulated-chain = { path = "../../../relays/westend" } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/genesis.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/genesis.rs index 9ab32a977d7..48901647fd0 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/genesis.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/genesis.rs @@ -14,19 +14,27 @@ // limitations under the License. // Substrate +use frame_support::parameter_types; use sp_core::{sr25519, storage::Storage}; +// Polkadot +use xcm::v3::Location; // Cumulus use emulated_integration_tests_common::{ accounts, build_genesis_storage, collators, get_account_id_from_seed, SAFE_XCM_VERSION, }; -use parachains_common::Balance; - +use parachains_common::{AccountId, Balance}; +use penpal_runtime::xcm_config::{LocalReservableFromAssetHub, RelayLocation}; // Penpal pub const PARA_ID_A: u32 = 2000; pub const PARA_ID_B: u32 = 2001; pub const ED: Balance = penpal_runtime::EXISTENTIAL_DEPOSIT; +parameter_types! { + pub PenpalSudoAcccount: AccountId = get_account_id_from_seed::("Alice"); + pub PenpalAssetOwner: AccountId = PenpalSudoAcccount::get(); +} + pub fn genesis(para_id: u32) -> Storage { let genesis_config = penpal_runtime::RuntimeGenesisConfig { system: penpal_runtime::SystemConfig::default(), @@ -58,8 +66,35 @@ pub fn genesis(para_id: u32) -> Storage { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, - sudo: penpal_runtime::SudoConfig { - key: Some(get_account_id_from_seed::("Alice")), + sudo: penpal_runtime::SudoConfig { key: Some(PenpalSudoAcccount::get()) }, + assets: penpal_runtime::AssetsConfig { + assets: vec![( + penpal_runtime::xcm_config::TELEPORTABLE_ASSET_ID, + PenpalAssetOwner::get(), + false, + ED, + )], + ..Default::default() + }, + foreign_assets: penpal_runtime::ForeignAssetsConfig { + assets: vec![ + // Relay Native asset representation + ( + Location::try_from(RelayLocation::get()).expect("conversion works"), + PenpalAssetOwner::get(), + true, + ED, + ), + // Sufficient AssetHub asset representation + ( + Location::try_from(LocalReservableFromAssetHub::get()) + .expect("conversion works"), + PenpalAssetOwner::get(), + true, + ED, + ), + ], + ..Default::default() }, ..Default::default() }; diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs index c1e03046655..651b3a52306 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs @@ -14,10 +14,9 @@ // limitations under the License. mod genesis; -pub use genesis::{genesis, ED, PARA_ID_A, PARA_ID_B}; +pub use genesis::{genesis, PenpalAssetOwner, PenpalSudoAcccount, ED, PARA_ID_A, PARA_ID_B}; pub use penpal_runtime::xcm_config::{ - CustomizableAssetFromSystemAssetHub, LocalTeleportableToAssetHub, - LocalTeleportableToAssetHubV3, XcmConfig, + CustomizableAssetFromSystemAssetHub, LocalTeleportableToAssetHub, XcmConfig, }; // Substrate @@ -28,8 +27,6 @@ use emulated_integration_tests_common::{ impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, impl_assets_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains, }; -use rococo_emulated_chain::Rococo; -use westend_emulated_chain::Westend; // Penpal Parachain declaration decl_test_parachains! { @@ -76,7 +73,7 @@ decl_test_parachains! { // Penpal implementation impl_accounts_helpers_for_parachain!(PenpalA); impl_accounts_helpers_for_parachain!(PenpalB); -impl_assets_helpers_for_parachain!(PenpalA, Rococo); -impl_assets_helpers_for_parachain!(PenpalB, Westend); impl_assert_events_helpers_for_parachain!(PenpalA); impl_assert_events_helpers_for_parachain!(PenpalB); +impl_assets_helpers_for_parachain!(PenpalA); +impl_assets_helpers_for_parachain!(PenpalB); diff --git a/cumulus/parachains/integration-tests/emulated/common/Cargo.toml b/cumulus/parachains/integration-tests/emulated/common/Cargo.toml index 721c58fd864..8c44cce7d92 100644 --- a/cumulus/parachains/integration-tests/emulated/common/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/common/Cargo.toml @@ -27,6 +27,7 @@ pallet-message-queue = { path = "../../../../../substrate/frame/message-queue" } # Polkadot polkadot-primitives = { path = "../../../../../polkadot/primitives" } +polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain" } polkadot-runtime-parachains = { path = "../../../../../polkadot/runtime/parachains" } xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm" } pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm" } diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs index c93484829fe..5fc08dff32c 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -592,7 +592,7 @@ macro_rules! impl_assert_events_helpers_for_parachain { } #[macro_export] -macro_rules! impl_assets_helpers_for_parachain { +macro_rules! impl_assets_helpers_for_system_parachain { ( $chain:ident, $relay_chain:ident ) => { $crate::impls::paste::paste! { impl $chain { @@ -630,38 +630,6 @@ macro_rules! impl_assets_helpers_for_parachain { $crate::impls::xcm_transact_unpaid_execution(call, origin_kind) } - /// Mint assets making use of the assets pallet - pub fn mint_asset( - signed_origin: ::RuntimeOrigin, - id: u32, - beneficiary: $crate::impls::AccountId, - amount_to_mint: u128, - ) { - ::execute_with(|| { - $crate::impls::assert_ok!(]>::Assets::mint( - signed_origin, - id.clone().into(), - beneficiary.clone().into(), - amount_to_mint - )); - - type RuntimeEvent = <$chain as $crate::impls::Chain>::RuntimeEvent; - - $crate::impls::assert_expected_events!( - Self, - vec![ - RuntimeEvent::::Assets( - $crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount } - ) => { - asset_id: *asset_id == id, - owner: *owner == beneficiary.clone().into(), - amount: *amount == amount_to_mint, - }, - ] - ); - }); - } - /// Force create and mint assets making use of the assets pallet pub fn force_create_and_mint_asset( id: u32, @@ -727,8 +695,8 @@ macro_rules! impl_assets_helpers_for_parachain { } #[macro_export] -macro_rules! impl_foreign_assets_helpers_for_parachain { - ( $chain:ident, $relay_chain:ident ) => { +macro_rules! impl_assets_helpers_for_parachain { + ( $chain:ident) => { $crate::impls::paste::paste! { impl $chain { /// Create foreign assets using sudo `ForeignAssets::force_create()` @@ -803,6 +771,118 @@ macro_rules! impl_foreign_assets_helpers_for_parachain { ); }); } + /// Create assets using sudo `Assets::force_create()` + pub fn force_create_asset( + id: u32, + owner: $crate::impls::AccountId, + is_sufficient: bool, + min_balance: u128, + prefund_accounts: Vec<($crate::impls::AccountId, u128)>, + ) { + use $crate::impls::Inspect; + let sudo_origin = <$chain as $crate::impls::Chain>::RuntimeOrigin::root(); + ::execute_with(|| { + $crate::impls::assert_ok!( + ]>::Assets::force_create( + sudo_origin, + id.clone().into(), + owner.clone().into(), + is_sufficient, + min_balance, + ) + ); + assert!(]>::Assets::asset_exists(id.clone())); + type RuntimeEvent = <$chain as $crate::impls::Chain>::RuntimeEvent; + $crate::impls::assert_expected_events!( + Self, + vec![ + RuntimeEvent::::Assets( + $crate::impls::pallet_assets::Event::ForceCreated { + asset_id, + .. + } + ) => { asset_id: *asset_id == id, }, + ] + ); + }); + for (beneficiary, amount) in prefund_accounts.into_iter() { + let signed_origin = + <$chain as $crate::impls::Chain>::RuntimeOrigin::signed(owner.clone()); + Self::mint_asset(signed_origin, id.clone(), beneficiary, amount); + } + } + + /// Mint assets making use of the assets pallet + pub fn mint_asset( + signed_origin: ::RuntimeOrigin, + id: u32, + beneficiary: $crate::impls::AccountId, + amount_to_mint: u128, + ) { + ::execute_with(|| { + $crate::impls::assert_ok!(]>::Assets::mint( + signed_origin, + id.clone().into(), + beneficiary.clone().into(), + amount_to_mint + )); + + type RuntimeEvent = <$chain as $crate::impls::Chain>::RuntimeEvent; + + $crate::impls::assert_expected_events!( + Self, + vec![ + RuntimeEvent::::Assets( + $crate::impls::pallet_assets::Event::Issued { asset_id, owner, amount } + ) => { + asset_id: *asset_id == id, + owner: *owner == beneficiary.clone().into(), + amount: *amount == amount_to_mint, + }, + ] + ); + }); + } + + /// Returns the encoded call for `create` from the assets pallet + pub fn create_asset_call( + asset_id: u32, + min_balance: $crate::impls::Balance, + admin: $crate::impls::AccountId, + ) -> $crate::impls::DoubleEncoded<()> { + use $crate::impls::{Chain, Encode}; + + ::RuntimeCall::Assets($crate::impls::pallet_assets::Call::< + ::Runtime, + $crate::impls::pallet_assets::Instance1, + >::create { + id: asset_id.into(), + min_balance, + admin: admin.into(), + }) + .encode() + .into() + } + + /// Returns the encoded call for `create` from the foreign assets pallet + pub fn create_foreign_asset_call( + asset_id: $crate::impls::v3::Location, + min_balance: $crate::impls::Balance, + admin: $crate::impls::AccountId, + ) -> $crate::impls::DoubleEncoded<()> { + use $crate::impls::{Chain, Encode}; + + ::RuntimeCall::ForeignAssets($crate::impls::pallet_assets::Call::< + ::Runtime, + $crate::impls::pallet_assets::Instance2, + >::create { + id: asset_id.into(), + min_balance, + admin: admin.into(), + }) + .encode() + .into() + } } } }; diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 1a5cc1f6fea..40204ca297a 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -21,17 +21,19 @@ pub use xcm_emulator; // Substrate use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId; +use frame_support::parameter_types; use grandpa::AuthorityId as GrandpaId; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; use sp_core::{sr25519, storage::Storage, Pair, Public}; use sp_runtime::{ - traits::{IdentifyAccount, Verify}, + traits::{AccountIdConversion, IdentifyAccount, Verify}, BuildStorage, MultiSignature, }; // Polakdot use parachains_common::BlockNumber; +use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_parachains::configuration::HostConfiguration; // Cumulus @@ -49,6 +51,25 @@ pub const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; type AccountPublic = ::Signer; +// This asset is added to AH as Asset and reserved transfer between Parachain and AH +pub const RESERVABLE_ASSET_ID: u32 = 1; +// This asset is added to AH as ForeignAsset and teleported between Penpal and AH +pub const TELEPORTABLE_ASSET_ID: u32 = 2; + +pub const PENPAL_ID: u32 = 2000; +pub const ASSETS_PALLET_ID: u8 = 50; + +parameter_types! { + pub PenpalTeleportableAssetLocation: xcm::v3::Location + = xcm::v3::Location::new(1, [ + xcm::v3::Junction::Parachain(PENPAL_ID), + xcm::v3::Junction::PalletInstance(ASSETS_PALLET_ID), + xcm::v3::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into()), + ] + ); + pub PenpalSiblingSovereigAccount: AccountId = Sibling::from(PENPAL_ID).into_account_truncating(); +} + /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { TPublic::Pair::from_string(&format!("//{}", seed), None) diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index d3bb3238a3b..6951de6faa7 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -16,16 +16,26 @@ pub use paste; // Substrate +pub use frame_support::{pallet_prelude::Weight, weights::WeightToFee}; +pub use pallet_assets; pub use pallet_balances; pub use pallet_message_queue; pub use pallet_xcm; // Polkadot -pub use xcm::prelude::{AccountId32, WeightLimit}; +pub use xcm::{ + prelude::{ + AccountId32, All, Asset, AssetId, BuyExecution, DepositAsset, ExpectTransactStatus, + Fungible, Here, Location, MaybeErrorCode, OriginKind, RefundSurplus, Transact, Unlimited, + VersionedXcm, WeightLimit, WithdrawAsset, Xcm, + }, + v3::Location as V3Location, +}; // Cumulus pub use asset_test_utils; pub use cumulus_pallet_xcmp_queue; +pub use parachains_common::AccountId; pub use xcm_emulator::Chain; #[macro_export] @@ -120,102 +130,3 @@ macro_rules! test_parachain_is_trusted_teleporter { } }; } - -#[macro_export] -macro_rules! include_penpal_create_foreign_asset_on_asset_hub { - ( $penpal:ident, $asset_hub:ident, $relay_ed:expr, $weight_to_fee:expr) => { - $crate::impls::paste::paste! { - pub fn penpal_create_foreign_asset_on_asset_hub( - asset_id_on_penpal: u32, - foreign_asset_at_asset_hub: v3::Location, - ah_as_seen_by_penpal: Location, - is_sufficient: bool, - asset_owner: AccountId, - prefund_amount: u128, - ) { - use frame_support::weights::WeightToFee; - let ah_check_account = $asset_hub::execute_with(|| { - <$asset_hub as [<$asset_hub Pallet>]>::PolkadotXcm::check_account() - }); - let penpal_check_account = - $penpal::execute_with(|| <$penpal as [<$penpal Pallet>]>::PolkadotXcm::check_account()); - let penpal_as_seen_by_ah = $asset_hub::sibling_location_of($penpal::para_id()); - - // prefund SA of Penpal on AssetHub with enough native tokens to pay for creating - // new foreign asset, also prefund CheckingAccount with ED, because teleported asset - // itself might not be sufficient and CheckingAccount cannot be created otherwise - let sov_penpal_on_ah = $asset_hub::sovereign_account_id_of(penpal_as_seen_by_ah.clone()); - $asset_hub::fund_accounts(vec![ - (sov_penpal_on_ah.clone().into(), $relay_ed * 100_000_000_000), - (ah_check_account.clone().into(), $relay_ed * 1000), - ]); - - // prefund SA of AssetHub on Penpal with native asset - let sov_ah_on_penpal = $penpal::sovereign_account_id_of(ah_as_seen_by_penpal.clone()); - $penpal::fund_accounts(vec![ - (sov_ah_on_penpal.into(), $relay_ed * 1_000_000_000), - (penpal_check_account.clone().into(), $relay_ed * 1000), - ]); - - // Force create asset on $penpal and prefund [<$penpal Sender>] - $penpal::force_create_and_mint_asset( - asset_id_on_penpal, - ASSET_MIN_BALANCE, - is_sufficient, - asset_owner, - None, - prefund_amount, - ); - - let require_weight_at_most = Weight::from_parts(1_100_000_000_000, 30_000); - // `OriginKind::Xcm` required by ForeignCreators pallet-assets origin filter - let origin_kind = OriginKind::Xcm; - let call_create_foreign_assets = - <$asset_hub as Chain>::RuntimeCall::ForeignAssets(pallet_assets::Call::< - <$asset_hub as Chain>::Runtime, - pallet_assets::Instance2, - >::create { - id: foreign_asset_at_asset_hub, - min_balance: ASSET_MIN_BALANCE, - admin: sov_penpal_on_ah.into(), - }) - .encode(); - let buy_execution_fee_amount = $weight_to_fee::weight_to_fee( - &Weight::from_parts(10_100_000_000_000, 300_000), - ); - let buy_execution_fee = Asset { - id: AssetId(Location { parents: 1, interior: Here }), - fun: Fungible(buy_execution_fee_amount), - }; - let xcm = VersionedXcm::from(Xcm(vec![ - WithdrawAsset { 0: vec![buy_execution_fee.clone()].into() }, - BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited }, - Transact { require_weight_at_most, origin_kind, call: call_create_foreign_assets.into() }, - ExpectTransactStatus(MaybeErrorCode::Success), - RefundSurplus, - DepositAsset { assets: All.into(), beneficiary: penpal_as_seen_by_ah }, - ])); - // Send XCM message from penpal => asset_hub - let sudo_penpal_origin = <$penpal as Chain>::RuntimeOrigin::root(); - $penpal::execute_with(|| { - assert_ok!(<$penpal as [<$penpal Pallet>]>::PolkadotXcm::send( - sudo_penpal_origin.clone(), - bx!(ah_as_seen_by_penpal.into()), - bx!(xcm), - )); - type RuntimeEvent = <$penpal as Chain>::RuntimeEvent; - assert_expected_events!( - $penpal, - vec![ - RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {}, - ] - ); - }); - $asset_hub::execute_with(|| { - type ForeignAssets = <$asset_hub as [<$asset_hub Pallet>]>::ForeignAssets; - assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub)); - }); - } - } - }; -} diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml index 0a397c2617b..13eb7d8dfc4 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml @@ -34,5 +34,6 @@ parachains-common = { path = "../../../../../../parachains/common" } cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false } testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["rococo"] } asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo" } +penpal-runtime = { path = "../../../../../runtimes/testing/penpal" } emulated-integration-tests-common = { path = "../../../common", default-features = false } rococo-system-emulated-network = { path = "../../../networks/rococo-system" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs index 1cc25cb54a1..21d858f1fe5 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs @@ -13,59 +13,79 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use codec::Encode; +#[cfg(test)] +mod imports { + pub use codec::Encode; + + // Substrate + pub use frame_support::{ + assert_err, assert_ok, + pallet_prelude::Weight, + sp_runtime::{DispatchError, DispatchResult, ModuleError}, + traits::fungibles::Inspect, + }; -// Substrate -pub use frame_support::{ - assert_err, assert_ok, - pallet_prelude::Weight, - sp_runtime::{AccountId32, DispatchError, DispatchResult}, - traits::fungibles::Inspect, -}; + // Polkadot + pub use xcm::{ + prelude::{AccountId32 as AccountId32Junction, *}, + v3, + }; -// Polkadot -pub use xcm::{ - prelude::{AccountId32 as AccountId32Junction, *}, - v3::{self, Error, NetworkId::Rococo as RococoId}, -}; + // Cumulus + pub use asset_test_utils::xcm_helpers; + pub use emulated_integration_tests_common::{ + test_parachain_is_trusted_teleporter, + xcm_emulator::{ + assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, + TestArgs, TestContext, TestExt, + }, + xcm_helpers::{non_fee_asset, xcm_transact_paid_execution}, + ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, XCM_V3, + }; + pub use parachains_common::Balance; + pub use rococo_system_emulated_network::{ + asset_hub_rococo_emulated_chain::{ + genesis::{AssetHubRococoAssetOwner, ED as ASSET_HUB_ROCOCO_ED}, + AssetHubRococoParaPallet as AssetHubRococoPallet, + }, + penpal_emulated_chain::{ + PenpalAParaPallet as PenpalAPallet, PenpalAssetOwner, + PenpalBParaPallet as PenpalBPallet, ED as PENPAL_ED, + }, + rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet}, + AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver, + AssetHubRococoParaSender as AssetHubRococoSender, BridgeHubRococoPara as BridgeHubRococo, + BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, PenpalAPara as PenpalA, + PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender, + PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, RococoRelay as Rococo, + RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender, + }; -// Cumulus -pub use asset_test_utils::xcm_helpers; -pub use emulated_integration_tests_common::{ - test_parachain_is_trusted_teleporter, - xcm_emulator::{ - assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, - RelayChain as Relay, Test, TestArgs, TestContext, TestExt, - }, - xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, - PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, -}; -pub use parachains_common::{AccountId, Balance}; -pub use rococo_system_emulated_network::{ - asset_hub_rococo_emulated_chain::{ - genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, - }, - penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet, - rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet}, - AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver, - AssetHubRococoParaSender as AssetHubRococoSender, BridgeHubRococoPara as BridgeHubRococo, - BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, PenpalAPara as PenpalA, - PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender, - PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, RococoRelay as Rococo, - RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender, -}; + // Runtimes + pub use asset_hub_rococo_runtime::xcm_config::{ + TokenLocation as RelayLocation, UniversalLocation as AssetHubRococoUniversalLocation, + XcmConfig as AssetHubRococoXcmConfig, + }; + pub use penpal_runtime::xcm_config::{ + LocalReservableFromAssetHub as PenpalLocalReservableFromAssetHub, + LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub, + UniversalLocation as PenpalUniversalLocation, XcmConfig as PenpalRococoXcmConfig, + }; + pub use rococo_runtime::xcm_config::{ + UniversalLocation as RococoUniversalLocation, XcmConfig as RococoXcmConfig, + }; -pub const ASSET_ID: u32 = 1; -pub const ASSET_MIN_BALANCE: u128 = 1000; -// `Assets` pallet index -pub const ASSETS_PALLET_ID: u8 = 50; + pub const ASSET_ID: u32 = 3; + pub const ASSET_MIN_BALANCE: u128 = 1000; -pub type RelayToSystemParaTest = Test; -pub type RelayToParaTest = Test; -pub type SystemParaToRelayTest = Test; -pub type SystemParaToParaTest = Test; -pub type ParaToSystemParaTest = Test; -pub type ParaToParaTest = Test; + pub type RelayToSystemParaTest = Test; + pub type RelayToParaTest = Test; + pub type ParaToRelayTest = Test; + pub type SystemParaToRelayTest = Test; + pub type SystemParaToParaTest = Test; + pub type ParaToSystemParaTest = Test; + pub type ParaToParaThroughRelayTest = Test; +} #[cfg(test)] mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs index 21bed234304..b3841af0e6c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs @@ -18,11 +18,3 @@ mod send; mod set_xcm_versions; mod swap; mod teleport; - -use crate::*; -emulated_integration_tests_common::include_penpal_create_foreign_asset_on_asset_hub!( - PenpalA, - AssetHubRococo, - ROCOCO_ED, - testnet_parachains_constants::rococo::fee::WeightToFee -); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index d2c3a323256..705c9613b64 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -13,14 +13,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; -use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig; -use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig; -use rococo_system_emulated_network::penpal_emulated_chain::XcmConfig as PenpalRococoXcmConfig; +use crate::imports::*; fn relay_to_para_sender_assertions(t: RelayToParaTest) { type RuntimeEvent = ::RuntimeEvent; + Rococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799))); + assert_expected_events!( Rococo, vec![ @@ -38,12 +37,32 @@ fn relay_to_para_sender_assertions(t: RelayToParaTest) { ); } +fn para_to_relay_sender_assertions(t: ParaToRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + PenpalA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799))); + assert_expected_events!( + PenpalA, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance, .. } + ) => { + asset_id: *asset_id == v3::Location::try_from(RelayLocation::get()).expect("conversion works"), + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + ] + ); +} + fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; + AssetHubRococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( 864_610_000, 8_799, ))); + assert_expected_events!( AssetHubRococo, vec![ @@ -57,19 +76,29 @@ fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { ), amount: *amount == t.args.amount, }, + // Transport fees are paid + RuntimeEvent::PolkadotXcm( + pallet_xcm::Event::FeesPaid { .. } + ) => {}, ] ); + AssetHubRococo::assert_xcm_pallet_sent(); } -fn para_receiver_assertions(_: Test) { +fn system_para_to_para_receiver_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + PenpalA::assert_xcmp_queue_success(None); + assert_expected_events!( PenpalA, vec![ - RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, - RuntimeEvent::MessageQueue( - pallet_message_queue::Event::Processed { success: true, .. } - ) => {}, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.receiver.account_id, + }, ] ); } @@ -81,12 +110,42 @@ fn para_to_system_para_sender_assertions(t: ParaToSystemParaTest) { PenpalA, vec![ // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance, .. } + ) => { + asset_id: *asset_id == v3::Location::try_from(RelayLocation::get()).expect("conversion works"), + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + ] + ); +} + +fn para_to_relay_receiver_assertions(t: ParaToRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_on_relay = + Rococo::sovereign_account_id_of(Rococo::child_location_of(PenpalA::para_id())); + + Rococo::assert_ump_queue_processed( + true, + Some(PenpalA::para_id()), + Some(Weight::from_parts(306305000, 7_186)), + ); + + assert_expected_events!( + Rococo, + vec![ + // Amount to reserve transfer is withdrawn from Parachain's Sovereign account RuntimeEvent::Balances( pallet_balances::Event::Burned { who, amount } ) => { - who: *who == t.sender.account_id, + who: *who == sov_penpal_on_relay.clone().into(), amount: *amount == t.args.amount, }, + RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, ] ); } @@ -96,6 +155,9 @@ fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) { let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of( AssetHubRococo::sibling_location_of(PenpalA::para_id()), ); + + AssetHubRococo::assert_xcmp_queue_success(None); + assert_expected_events!( AssetHubRococo, vec![ @@ -127,24 +189,124 @@ fn system_para_to_para_assets_sender_assertions(t: SystemParaToParaTest) { RuntimeEvent::Assets( pallet_assets::Event::Transferred { asset_id, from, to, amount } ) => { - asset_id: *asset_id == ASSET_ID, + asset_id: *asset_id == RESERVABLE_ASSET_ID, from: *from == t.sender.account_id, to: *to == AssetHubRococo::sovereign_account_id_of( t.args.dest.clone() ), amount: *amount == t.args.amount, }, + // Native asset to pay for fees is transferred to Parachain's Sovereign account + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { + who: *who == AssetHubRococo::sovereign_account_id_of( + t.args.dest.clone() + ), + }, + // Transport fees are paid + RuntimeEvent::PolkadotXcm( + pallet_xcm::Event::FeesPaid { .. } + ) => {}, ] ); } -fn system_para_to_para_assets_receiver_assertions(_: Test) { +fn para_to_system_para_assets_sender_assertions(t: ParaToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let reservable_asset_location = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); + PenpalA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8799))); assert_expected_events!( PenpalA, vec![ - RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, - RuntimeEvent::Assets(pallet_assets::Event::Issued { .. }) => {}, + // Fees amount to reserve transfer is burned from Parachains's sender account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, .. } + ) => { + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.sender.account_id, + }, + // Amount to reserve transfer is burned from Parachains's sender account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance } + ) => { + asset_id: *asset_id == reservable_asset_location, + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + // Transport fees are paid + RuntimeEvent::PolkadotXcm( + pallet_xcm::Event::FeesPaid { .. } + ) => {}, + ] + ); +} + +fn system_para_to_para_assets_receiver_assertions(t: SystemParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let system_para_asset_location = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); + PenpalA::assert_xcmp_queue_success(None); + assert_expected_events!( + PenpalA, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { + asset_id: *asset_id == v3::Location::try_from(RelayLocation::get()).expect("conversion works"), + owner: *owner == t.receiver.account_id, + }, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, amount }) => { + asset_id: *asset_id == system_para_asset_location, + owner: *owner == t.receiver.account_id, + amount: *amount == t.args.amount, + }, + ] + ); +} + +fn para_to_system_para_assets_receiver_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of( + AssetHubRococo::sibling_location_of(PenpalA::para_id()), + ); + AssetHubRococo::assert_xcmp_queue_success(None); + assert_expected_events!( + AssetHubRococo, + vec![ + // Amount to reserve transfer is burned from Parachain's Sovereign account + RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { + asset_id: *asset_id == RESERVABLE_ASSET_ID, + owner: *owner == sov_penpal_on_ahr, + balance: *balance == t.args.amount, + }, + // Fee amount is burned from Parachain's Sovereign account + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, .. }) => { + who: *who == sov_penpal_on_ahr, + }, + // Amount to reserve transfer is issued for beneficiary + RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, owner, amount }) => { + asset_id: *asset_id == RESERVABLE_ASSET_ID, + owner: *owner == t.receiver.account_id, + amount: *amount == t.args.amount, + }, + // Remaining fee amount is minted for for beneficiary + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { + who: *who == t.receiver.account_id, + }, + ] + ); +} + +fn relay_to_para_assets_receiver_assertions(t: RelayToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + PenpalA, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { + asset_id: *asset_id == v3::Location::try_from(RelayLocation::get()).expect("conversion works"), + owner: *owner == t.receiver.account_id, + }, RuntimeEvent::MessageQueue( pallet_message_queue::Event::Processed { success: true, .. } ) => {}, @@ -152,33 +314,38 @@ fn system_para_to_para_assets_receiver_assertions(_: Test) { ); } -fn para_to_para_sender_assertions(t: ParaToParaTest) { +fn para_to_para_through_relay_sender_assertions(t: ParaToParaThroughRelayTest) { type RuntimeEvent = ::RuntimeEvent; + + let relay_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + PenpalA::assert_xcm_pallet_attempted_complete(None); + // XCM sent to relay reserve + PenpalA::assert_parachain_system_ump_sent(); + assert_expected_events!( PenpalA, vec![ // Amount to reserve transfer is transferred to Parachain's Sovereign account - RuntimeEvent::Balances( - pallet_balances::Event::Burned { who, amount } + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance }, ) => { - who: *who == t.sender.account_id, - amount: *amount == t.args.amount, + asset_id: *asset_id == relay_asset_location, + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, }, - // XCM sent to relay reserve - RuntimeEvent::ParachainSystem( - cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. } - ) => {}, ] ); } -fn para_to_para_relay_hop_assertions(t: ParaToParaTest) { +fn para_to_para_relay_hop_assertions(t: ParaToParaThroughRelayTest) { type RuntimeEvent = ::RuntimeEvent; let sov_penpal_a_on_rococo = Rococo::sovereign_account_id_of(Rococo::child_location_of(PenpalA::para_id())); let sov_penpal_b_on_rococo = Rococo::sovereign_account_id_of(Rococo::child_location_of(PenpalB::para_id())); + assert_expected_events!( Rococo, vec![ @@ -202,15 +369,20 @@ fn para_to_para_relay_hop_assertions(t: ParaToParaTest) { ); } -fn para_to_para_receiver_assertions(_: ParaToParaTest) { +fn para_to_para_through_relay_receiver_assertions(t: ParaToParaThroughRelayTest) { type RuntimeEvent = ::RuntimeEvent; + let relay_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + PenpalB::assert_xcmp_queue_success(None); + assert_expected_events!( PenpalB, vec![ - RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, - RuntimeEvent::MessageQueue( - pallet_message_queue::Event::Processed { success: true, .. } - ) => {}, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { + asset_id: *asset_id == relay_asset_location, + owner: *owner == t.receiver.account_id, + }, ] ); } @@ -226,6 +398,17 @@ fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { ) } +fn para_to_relay_reserve_transfer_assets(t: ParaToRelayTest) -> DispatchResult { + ::PolkadotXcm::limited_reserve_transfer_assets( + t.signed_origin, + bx!(t.args.dest.into()), + bx!(t.args.beneficiary.into()), + bx!(t.args.assets.into()), + t.args.fee_asset_item, + t.args.weight_limit, + ) +} + fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, @@ -248,7 +431,9 @@ fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> Dispa ) } -fn para_to_para_limited_reserve_transfer_assets(t: ParaToParaTest) -> DispatchResult { +fn para_to_para_through_relay_limited_reserve_transfer_assets( + t: ParaToParaThroughRelayTest, +) -> DispatchResult { ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, bx!(t.args.dest.into()), @@ -262,6 +447,7 @@ fn para_to_para_limited_reserve_transfer_assets(t: ParaToParaTest) -> DispatchRe /// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work #[test] fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { + // Init values for Relay Chain let signed_origin = ::RuntimeOrigin::signed(RococoSender::get().into()); let destination = Rococo::child_location_of(AssetHubRococo::para_id()); let beneficiary: Location = @@ -328,135 +514,298 @@ fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { }); } +// ========================================================================= +// ========= Reserve Transfers - Native Asset - Relay<>Parachain =========== +// ========================================================================= /// Reserve Transfers of native asset from Relay to Parachain should work #[test] fn reserve_transfer_native_asset_from_relay_to_para() { // Init values for Relay let destination = Rococo::child_location_of(PenpalA::para_id()); - let beneficiary_id = PenpalAReceiver::get(); + let sender = RococoSender::get(); let amount_to_send: Balance = ROCOCO_ED * 1000; + let assets: Assets = (Here, amount_to_send).into(); + + // Init values fot Parachain + let relay_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let receiver = PenpalAReceiver::get(); + // Init Test let test_args = TestContext { - sender: RococoSender::get(), - receiver: PenpalAReceiver::get(), - args: TestArgs::new_relay(destination, beneficiary_id, amount_to_send), + sender, + receiver: receiver.clone(), + args: TestArgs::new_relay(destination.clone(), receiver.clone(), amount_to_send), }; - let mut test = RelayToParaTest::new(test_args); + // Query initial balances let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; + let receiver_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.into(), &receiver) + }); + // Set assertions and dispatchables test.set_assertion::(relay_to_para_sender_assertions); - test.set_assertion::(para_receiver_assertions); + test.set_assertion::(relay_to_para_assets_receiver_assertions); test.set_dispatchable::(relay_to_para_reserve_transfer_assets); test.assert(); + // Calculate delivery fees let delivery_fees = Rococo::execute_with(|| { + let reanchored_assets = + assets.reanchored(&destination, &RococoUniversalLocation::get()).unwrap(); xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); + // Query final balances let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; + let receiver_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.into(), &receiver) + }); // Sender's balance is reduced assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // Receiver's balance is increased + // Receiver's asset balance is increased + assert!(receiver_assets_after > receiver_assets_before); + // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; + // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but + // should be non-zero + assert!(receiver_assets_after < receiver_assets_before + amount_to_send); +} + +/// Reserve Transfers of native asset from Parachain to Relay should work +#[test] +fn reserve_transfer_native_asset_from_para_to_relay() { + // Init values for Parachain + let destination = PenpalA::parent_location(); + let sender = PenpalASender::get(); + let amount_to_send: Balance = ROCOCO_ED * 1000; + let assets: Assets = (Parent, amount_to_send).into(); + let asset_owner = PenpalAssetOwner::get(); + let relay_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + relay_native_asset_location, + sender.clone(), + amount_to_send, + ); + + // Init values for Relay + let receiver = RococoReceiver::get(); + let penpal_location_as_seen_by_relay = Rococo::child_location_of(PenpalA::para_id()); + let sov_penpal_on_relay = Rococo::sovereign_account_id_of(penpal_location_as_seen_by_relay); + + // fund Parachain's SA on Relay with the native tokens held in reserve + Rococo::fund_accounts(vec![(sov_penpal_on_relay.into(), amount_to_send * 2)]); + + // Init Test + let test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination.clone(), + receiver, + amount_to_send, + assets.clone(), + None, + 0, + ), + }; + let mut test = ParaToRelayTest::new(test_args); + + // Query initial balances + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.into(), &sender) + }); + let receiver_balance_before = test.receiver.balance; + + // Set assertions and dispatchables + test.set_assertion::(para_to_relay_sender_assertions); + test.set_assertion::(para_to_relay_receiver_assertions); + test.set_dispatchable::(para_to_relay_reserve_transfer_assets); + test.assert(); + + // Calculate delivery fees + let delivery_fees = PenpalA::execute_with(|| { + let reanchored_assets = + assets.reanchored(&destination, &PenpalUniversalLocation::get()).unwrap(); + xcm_helpers::transfer_assets_delivery_fees::< + ::XcmSender, + >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Query final balances + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.into(), &sender) + }); + let receiver_balance_after = test.receiver.balance; + + // Sender's balance is reduced + assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); + // Receiver's asset balance is increased assert!(receiver_balance_after > receiver_balance_before); - // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; + // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but // should be non-zero assert!(receiver_balance_after < receiver_balance_before + amount_to_send); } +// ========================================================================= +// ======= Reserve Transfers - Native Asset - AssetHub<>Parachain ========== +// ========================================================================= /// Reserve Transfers of native asset from System Parachain to Parachain should work #[test] fn reserve_transfer_native_asset_from_system_para_to_para() { // Init values for System Parachain let destination = AssetHubRococo::sibling_location_of(PenpalA::para_id()); - let beneficiary_id = PenpalAReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000; - let assets = (Parent, amount_to_send).into(); + let sender = AssetHubRococoSender::get(); + let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 10000; + let assets: Assets = (Parent, amount_to_send).into(); + + // Init values for Parachain + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let receiver = PenpalAReceiver::get(); + // Init Test let test_args = TestContext { - sender: AssetHubRococoSender::get(), - receiver: PenpalAReceiver::get(), - args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), + sender, + receiver: receiver.clone(), + args: TestArgs::new_para( + destination.clone(), + receiver.clone(), + amount_to_send, + assets.clone(), + None, + 0, + ), }; - let mut test = SystemParaToParaTest::new(test_args); + // Query initial balances let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; + let receiver_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location.into(), &receiver) + }); + // Set assertions and dispatchables test.set_assertion::(system_para_to_para_sender_assertions); - test.set_assertion::(para_receiver_assertions); + test.set_assertion::(system_para_to_para_receiver_assertions); test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); test.assert(); - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - + // Calculate delivery fees let delivery_fees = AssetHubRococo::execute_with(|| { + let reanchored_assets = assets + .reanchored(&destination, &AssetHubRococoUniversalLocation::get()) + .unwrap(); xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Query final balances + let sender_balance_after = test.sender.balance; + let receiver_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &receiver) }); // Sender's balance is reduced assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // Receiver's balance is increased - assert!(receiver_balance_after > receiver_balance_before); - // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; + // Receiver's assets is increased + assert!(receiver_assets_after > receiver_assets_before); + // Receiver's assets increased by `amount_to_send - delivery_fees - bought_execution`; // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but // should be non-zero - assert!(receiver_balance_after < receiver_balance_before + amount_to_send); + assert!(receiver_assets_after < receiver_assets_before + amount_to_send); } /// Reserve Transfers of native asset from Parachain to System Parachain should work #[test] fn reserve_transfer_native_asset_from_para_to_system_para() { - // Init values for Penpal Parachain + // Init values for Parachain let destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()); - let beneficiary_id = AssetHubRococoReceiver::get(); + let sender = PenpalASender::get(); let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000; - let assets = (Parent, amount_to_send).into(); + let assets: Assets = (Parent, amount_to_send).into(); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let asset_owner = PenpalAssetOwner::get(); + + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + system_para_native_asset_location, + sender.clone(), + amount_to_send, + ); + // Init values for System Parachain + let receiver = AssetHubRococoReceiver::get(); + let penpal_location_as_seen_by_ahr = AssetHubRococo::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + + // fund Parachain's SA on System Parachain with the native tokens held in reserve + AssetHubRococo::fund_accounts(vec![(sov_penpal_on_ahr.into(), amount_to_send * 2)]); + + // Init Test let test_args = TestContext { - sender: PenpalASender::get(), - receiver: AssetHubRococoReceiver::get(), - args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination.clone(), + receiver.clone(), + amount_to_send, + assets.clone(), + None, + 0, + ), }; - let mut test = ParaToSystemParaTest::new(test_args); - let sender_balance_before = test.sender.balance; + // Query initial balances + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &sender) + }); let receiver_balance_before = test.receiver.balance; - let penpal_location_as_seen_by_ahr = AssetHubRococo::sibling_location_of(PenpalA::para_id()); - let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location_as_seen_by_ahr); - - // fund the Penpal's SA on AHR with the native tokens held in reserve - AssetHubRococo::fund_accounts(vec![(sov_penpal_on_ahr.into(), amount_to_send * 2)]); - + // Set assertions and dispatchables test.set_assertion::(para_to_system_para_sender_assertions); test.set_assertion::(para_to_system_para_receiver_assertions); test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); test.assert(); - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - + // Calculate delivery fees let delivery_fees = PenpalA::execute_with(|| { + let reanchored_assets = + assets.reanchored(&destination, &PenpalUniversalLocation::get()).unwrap(); xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); + // Query final balances + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &sender) + }); + let receiver_balance_after = test.receiver.balance; + // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); // Receiver's balance is increased assert!(receiver_balance_after > receiver_balance_before); // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -465,36 +814,27 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { assert!(receiver_balance_after < receiver_balance_before + amount_to_send); } +// ========================================================================= +// ======= Reserve Transfers - Non-system Asset - AssetHub<>Parachain ====== +// ========================================================================= /// Reserve Transfers of a local asset and native asset from System Parachain to Parachain should /// work #[test] fn reserve_transfer_assets_from_system_para_to_para() { - // Force create asset on AssetHubRococo and PenpalA from Relay Chain - AssetHubRococo::force_create_and_mint_asset( - ASSET_ID, - ASSET_MIN_BALANCE, - false, - AssetHubRococoSender::get(), - Some(Weight::from_parts(1_019_445_000, 200_000)), - ASSET_MIN_BALANCE * 1_000_000, - ); - PenpalA::force_create_and_mint_asset( - ASSET_ID, - ASSET_MIN_BALANCE, - false, - PenpalASender::get(), - None, - 0, - ); - // Init values for System Parachain let destination = AssetHubRococo::sibling_location_of(PenpalA::para_id()); - let beneficiary_id = PenpalAReceiver::get(); - let fee_amount_to_send = ASSET_HUB_ROCOCO_ED * 1000; - let asset_amount_to_send = ASSET_MIN_BALANCE * 1000; + let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(destination.clone()); + let sender = AssetHubRococoSender::get(); + let fee_amount_to_send = ASSET_HUB_ROCOCO_ED * 10000; + let asset_amount_to_send = PENPAL_ED * 10000; + let asset_owner = AssetHubRococoAssetOwner::get(); + let asset_owner_signer = ::RuntimeOrigin::signed(asset_owner.clone()); let assets: Assets = vec![ (Parent, fee_amount_to_send).into(), - ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], asset_amount_to_send) + ( + [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(RESERVABLE_ASSET_ID.into())], + asset_amount_to_send, + ) .into(), ] .into(); @@ -503,49 +843,211 @@ fn reserve_transfer_assets_from_system_para_to_para() { .iter() .position(|r| r == &(Parent, fee_amount_to_send).into()) .unwrap() as u32; + AssetHubRococo::mint_asset( + asset_owner_signer, + RESERVABLE_ASSET_ID, + asset_owner, + asset_amount_to_send * 2, + ); + // Create SA-of-Penpal-on-AHR with ED. + AssetHubRococo::fund_accounts(vec![(sov_penpal_on_ahr.into(), ASSET_HUB_ROCOCO_ED)]); + + // Init values for Parachain + let receiver = PenpalAReceiver::get(); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let system_para_foreign_asset_location = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); + + // Init Test let para_test_args = TestContext { - sender: AssetHubRococoSender::get(), - receiver: PenpalAReceiver::get(), + sender: sender.clone(), + receiver: receiver.clone(), args: TestArgs::new_para( destination, - beneficiary_id, + receiver.clone(), asset_amount_to_send, assets, None, fee_asset_index, ), }; - let mut test = SystemParaToParaTest::new(para_test_args); - // Create SA-of-Penpal-on-AHR with ED. - let penpal_location = AssetHubRococo::sibling_location_of(PenpalA::para_id()); - let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location); - AssetHubRococo::fund_accounts(vec![(sov_penpal_on_ahr.into(), ROCOCO_ED)]); - + // Query initial balances let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - let sender_assets_before = AssetHubRococo::execute_with(|| { type Assets = ::Assets; - >::balance(ASSET_ID, &AssetHubRococoSender::get()) + >::balance(RESERVABLE_ASSET_ID, &sender) }); - let receiver_assets_before = PenpalA::execute_with(|| { - type Assets = ::Assets; - >::balance(ASSET_ID, &PenpalAReceiver::get()) + let receiver_system_native_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &receiver) + }); + let receiver_foreign_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_foreign_asset_location, &receiver) }); + // Set assertions and dispatchables test.set_assertion::(system_para_to_para_assets_sender_assertions); test.set_assertion::(system_para_to_para_assets_receiver_assertions); test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); test.assert(); + // Query final balances let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - + let sender_assets_after = AssetHubRococo::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &sender) + }); + let receiver_system_native_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &receiver) + }); + let receiver_foreign_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_foreign_asset_location, &receiver) + }); // Sender's balance is reduced assert!(sender_balance_after < sender_balance_before); + // Receiver's foreign asset balance is increased + assert!(receiver_foreign_assets_after > receiver_foreign_assets_before); + // Receiver's system asset balance increased by `amount_to_send - delivery_fees - + // bought_execution`; `delivery_fees` might be paid from transfer or JIT, also + // `bought_execution` is unknown but should be non-zero + assert!( + receiver_system_native_assets_after < + receiver_system_native_assets_before + fee_amount_to_send + ); + + // Sender's asset balance is reduced by exact amount + assert_eq!(sender_assets_before - asset_amount_to_send, sender_assets_after); + // Receiver's foreign asset balance is increased by exact amount + assert_eq!( + receiver_foreign_assets_after, + receiver_foreign_assets_before + asset_amount_to_send + ); +} + +/// Reserve Transfers of a foreign asset and native asset from Parachain to System Para should +/// work +#[test] +fn reserve_transfer_assets_from_para_to_system_para() { + // Init values for Parachain + let destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()); + let sender = PenpalASender::get(); + let fee_amount_to_send = ASSET_HUB_ROCOCO_ED * 10000; + let asset_amount_to_send = ASSET_HUB_ROCOCO_ED * 10000; + let penpal_asset_owner = PenpalAssetOwner::get(); + let penpal_asset_owner_signer = ::RuntimeOrigin::signed(penpal_asset_owner); + let asset_location_on_penpal = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); + let asset_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap(); + let system_asset_location_on_penpal = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let assets: Assets = vec![ + (Parent, fee_amount_to_send).into(), + (asset_location_on_penpal_latest, asset_amount_to_send).into(), + ] + .into(); + let fee_asset_index = assets + .inner() + .iter() + .position(|r| r == &(Parent, fee_amount_to_send).into()) + .unwrap() as u32; + // Fund Parachain's sender account with some foreign assets + PenpalA::mint_foreign_asset( + penpal_asset_owner_signer.clone(), + asset_location_on_penpal, + sender.clone(), + asset_amount_to_send * 2, + ); + // Fund Parachain's sender account with some system assets + PenpalA::mint_foreign_asset( + penpal_asset_owner_signer, + system_asset_location_on_penpal, + sender.clone(), + fee_amount_to_send * 2, + ); + + // Init values for System Parachain + let receiver = AssetHubRococoReceiver::get(); + let penpal_location_as_seen_by_ahr = AssetHubRococo::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let system_para_foreign_asset_location = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); + let ah_asset_owner = AssetHubRococoAssetOwner::get(); + let ah_asset_owner_signer = ::RuntimeOrigin::signed(ah_asset_owner); + + // Fund SA-of-Penpal-on-AHR to be able to pay for the fees. + AssetHubRococo::fund_accounts(vec![( + sov_penpal_on_ahr.clone().into(), + ASSET_HUB_ROCOCO_ED * 10000000, + )]); + // Fund SA-of-Penpal-on-AHR to be able to pay for the sent amount. + AssetHubRococo::mint_asset( + ah_asset_owner_signer, + RESERVABLE_ASSET_ID, + sov_penpal_on_ahr, + asset_amount_to_send * 2, + ); + + // Init Test + let para_test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination, + receiver.clone(), + asset_amount_to_send, + assets, + None, + fee_asset_index, + ), + }; + let mut test = ParaToSystemParaTest::new(para_test_args); + + // Query initial balances + let sender_system_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &sender) + }); + let sender_foreign_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_foreign_asset_location, &sender) + }); + let receiver_balance_before = test.receiver.balance; + let receiver_assets_before = AssetHubRococo::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &receiver) + }); + + // Set assertions and dispatchables + test.set_assertion::(para_to_system_para_assets_sender_assertions); + test.set_assertion::(para_to_system_para_assets_receiver_assertions); + test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); + test.assert(); + + // Query final balances + let sender_system_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &sender) + }); + let sender_foreign_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_foreign_asset_location, &sender) + }); + let receiver_balance_after = test.receiver.balance; + let receiver_assets_after = AssetHubRococo::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &receiver) + }); + // Sender's system asset balance is reduced + assert!(sender_system_assets_after < sender_system_assets_before); // Receiver's balance is increased assert!(receiver_balance_after > receiver_balance_before); // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -553,65 +1055,88 @@ fn reserve_transfer_assets_from_system_para_to_para() { // should be non-zero assert!(receiver_balance_after < receiver_balance_before + fee_amount_to_send); - let sender_assets_after = AssetHubRococo::execute_with(|| { - type Assets = ::Assets; - >::balance(ASSET_ID, &AssetHubRococoSender::get()) - }); - let receiver_assets_after = PenpalA::execute_with(|| { - type Assets = ::Assets; - >::balance(ASSET_ID, &PenpalAReceiver::get()) - }); - - // Sender's balance is reduced by exact amount - assert_eq!(sender_assets_before - asset_amount_to_send, sender_assets_after); - // Receiver's balance is increased by exact amount + // Sender's asset balance is reduced by exact amount + assert_eq!(sender_foreign_assets_before - asset_amount_to_send, sender_foreign_assets_after); + // Receiver's foreign asset balance is increased by exact amount assert_eq!(receiver_assets_after, receiver_assets_before + asset_amount_to_send); } +// ========================================================================= +// ===== Reserve Transfers - Native Asset - Parachain<>Relay<>Parachain ==== +// ========================================================================= /// Reserve Transfers of native asset from Parachain to Parachain (through Relay reserve) should /// work #[test] -fn reserve_transfer_native_asset_from_para_to_para() { - // Init values for Penpal Parachain +fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { + // Init values for Parachain Origin let destination = PenpalA::sibling_location_of(PenpalB::para_id()); - let beneficiary_id = PenpalBReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 10000; + let sender = PenpalASender::get(); + let amount_to_send: Balance = ROCOCO_ED * 10000; + let asset_owner = PenpalAssetOwner::get(); let assets = (Parent, amount_to_send).into(); + let relay_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let sender_as_seen_by_relay = Rococo::child_location_of(PenpalA::para_id()); + let sov_of_sender_on_relay = Rococo::sovereign_account_id_of(sender_as_seen_by_relay); - let test_args = TestContext { - sender: PenpalASender::get(), - receiver: PenpalBReceiver::get(), - args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), - }; + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + relay_native_asset_location, + sender.clone(), + amount_to_send, + ); - let mut test = ParaToParaTest::new(test_args); + // fund the Parachain Origin's SA on Relay Chain with the native tokens held in reserve + Rococo::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; + // Init values for Parachain Desitnation + let receiver = PenpalBReceiver::get(); - let sender_as_seen_by_relay = Rococo::child_location_of(PenpalA::para_id()); - let sov_of_sender_on_relay = Rococo::sovereign_account_id_of(sender_as_seen_by_relay); + // Init Test + let test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para(destination, receiver.clone(), amount_to_send, assets, None, 0), + }; + let mut test = ParaToParaThroughRelayTest::new(test_args); - // fund the PenpalA's SA on Rococo with the native tokens held in reserve - Rococo::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); + // Query initial balances + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &sender) + }); + let receiver_assets_before = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &receiver) + }); - test.set_assertion::(para_to_para_sender_assertions); + // Set assertions and dispatchables + test.set_assertion::(para_to_para_through_relay_sender_assertions); test.set_assertion::(para_to_para_relay_hop_assertions); - test.set_assertion::(para_to_para_receiver_assertions); - test.set_dispatchable::(para_to_para_limited_reserve_transfer_assets); + test.set_assertion::(para_to_para_through_relay_receiver_assertions); + test.set_dispatchable::(para_to_para_through_relay_limited_reserve_transfer_assets); test.assert(); - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - + // Calculate delivery fees let delivery_fees = PenpalA::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); + // Query final balances + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &sender) + }); + let receiver_assets_after = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &receiver) + }); + // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); // Receiver's balance is increased - assert!(receiver_balance_after > receiver_balance_before); + assert!(receiver_assets_after > receiver_assets_before); } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs index 3c9e76a34e3..364fbd0d439 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; /// Relay Chain should be able to execute `Transact` instructions in System Parachain /// when `OriginKind::Superuser`. @@ -28,8 +28,95 @@ fn send_transact_as_superuser_from_relay_to_system_para_works() { ) } -/// Parachain should be able to send XCM paying its fee with sufficient asset -/// in the System Parachain +/// We tests two things here: +/// - Parachain should be able to send XCM paying its fee with system asset in the System Parachain +/// - Parachain should be able to create a new Foreign Asset in the System Parachain +#[test] +fn send_xcm_from_para_to_system_para_paying_fee_with_system_assets_works() { + let para_sovereign_account = AssetHubRococo::sovereign_account_id_of( + AssetHubRococo::sibling_location_of(PenpalA::para_id()), + ); + let asset_location_on_penpal = v3::Location::new( + 0, + [ + v3::Junction::PalletInstance(ASSETS_PALLET_ID), + v3::Junction::GeneralIndex(ASSET_ID.into()), + ], + ); + let foreign_asset_at_asset_hub = + v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) + .appended_with(asset_location_on_penpal) + .unwrap(); + + // Encoded `create_asset` call to be executed in AssetHub + let call = AssetHubRococo::create_foreign_asset_call( + foreign_asset_at_asset_hub, + ASSET_MIN_BALANCE, + para_sovereign_account.clone(), + ); + + let origin_kind = OriginKind::Xcm; + let fee_amount = ASSET_HUB_ROCOCO_ED * 1000000; + let system_asset = (Parent, fee_amount).into(); + + let root_origin = ::RuntimeOrigin::root(); + let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into(); + let xcm = xcm_transact_paid_execution( + call, + origin_kind, + system_asset, + para_sovereign_account.clone(), + ); + + // SA-of-Penpal-on-AHR needs to have balance to pay for fees and asset creation deposit + AssetHubRococo::fund_accounts(vec![( + para_sovereign_account.clone().into(), + ASSET_HUB_ROCOCO_ED * 10000000000, + )]); + + PenpalA::execute_with(|| { + assert_ok!(::PolkadotXcm::send( + root_origin, + bx!(system_para_destination), + bx!(xcm), + )); + + PenpalA::assert_xcm_pallet_sent(); + }); + + AssetHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + AssetHubRococo::assert_xcmp_queue_success(Some(Weight::from_parts( + 15_594_564_000, + 562_893, + ))); + + assert_expected_events!( + AssetHubRococo, + vec![ + // Burned the fee + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { + who: *who == para_sovereign_account, + amount: *amount == fee_amount, + }, + // Foreign Asset created + RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { asset_id, creator, owner }) => { + asset_id: *asset_id == foreign_asset_at_asset_hub, + creator: *creator == para_sovereign_account.clone(), + owner: *owner == para_sovereign_account, + }, + ] + ); + + type ForeignAssets = ::ForeignAssets; + assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub)); + }); +} + +/// We tests two things here: +/// - Parachain should be able to send XCM paying its fee with system assets in the System Parachain +/// - Parachain should be able to create a new Asset in the System Parachain #[test] fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { let para_sovereign_account = AssetHubRococo::sovereign_account_id_of( @@ -46,28 +133,30 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { ASSET_MIN_BALANCE * 1000000000, ); - // We just need a call that can pass the `SafeCallFilter` - // Call values are not relevant - let call = AssetHubRococo::force_create_asset_call( - ASSET_ID, - para_sovereign_account.clone(), - true, + // Just a different `asset_id`` that does not exist yet + let new_asset_id = ASSET_ID + 1; + + // Encoded `create_asset` call to be executed in AssetHub + let call = AssetHubRococo::create_asset_call( + new_asset_id, ASSET_MIN_BALANCE, + para_sovereign_account.clone(), ); let origin_kind = OriginKind::SovereignAccount; let fee_amount = ASSET_MIN_BALANCE * 1000000; - let native_asset = + let asset = ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); let root_origin = ::RuntimeOrigin::root(); let system_para_destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()).into(); - let xcm = xcm_transact_paid_execution( - call, - origin_kind, - native_asset, - para_sovereign_account.clone(), - ); + let xcm = xcm_transact_paid_execution(call, origin_kind, asset, para_sovereign_account.clone()); + + // SA-of-Penpal-on-AHR needs to have balance to pay for asset creation deposit + AssetHubRococo::fund_accounts(vec![( + para_sovereign_account.clone().into(), + ASSET_HUB_ROCOCO_ED * 10000000000, + )]); PenpalA::execute_with(|| { assert_ok!(::PolkadotXcm::send( @@ -90,13 +179,17 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { assert_expected_events!( AssetHubRococo, vec![ + // Burned the fee RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { asset_id: *asset_id == ASSET_ID, owner: *owner == para_sovereign_account, balance: *balance == fee_amount, }, - RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => { - asset_id: *asset_id == ASSET_ID, + // Asset created + RuntimeEvent::Assets(pallet_assets::Event::Created { asset_id, creator, owner }) => { + asset_id: *asset_id == new_asset_id, + creator: *creator == para_sovereign_account.clone(), + owner: *owner == para_sovereign_account, }, ] ); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/set_xcm_versions.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/set_xcm_versions.rs index 7d630d36805..5662a78ab67 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/set_xcm_versions.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/set_xcm_versions.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; #[test] fn relay_sets_system_para_xcm_supported_version() { diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs index c6a10b25290..87f0b3d9f90 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs @@ -13,9 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; -use rococo_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3; -use sp_runtime::ModuleError; +use crate::imports::*; #[test] fn swap_locally_on_chain_using_local_assets() { @@ -114,49 +112,39 @@ fn swap_locally_on_chain_using_local_assets() { #[test] fn swap_locally_on_chain_using_foreign_assets() { - let asset_native = Box::new(asset_hub_rococo_runtime::xcm_config::TokenLocationV3::get()); - let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id()); - let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get(); - let asset_id_on_penpal = match asset_location_on_penpal.last() { - Some(v3::Junction::GeneralIndex(id)) => *id as u32, - _ => unreachable!(), - }; - let asset_owner_on_penpal = PenpalASender::get(); + let asset_native = + Box::new(v3::Location::try_from(RelayLocation::get()).expect("conversion works")); + let asset_location_on_penpal = + v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion works"); let foreign_asset_at_asset_hub_rococo = v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) .appended_with(asset_location_on_penpal) .unwrap(); - // 1. Create asset on penpal and, 2. Create foreign asset on asset_hub_rococo - super::penpal_create_foreign_asset_on_asset_hub( - asset_id_on_penpal, - foreign_asset_at_asset_hub_rococo, - ah_as_seen_by_penpal, - true, - asset_owner_on_penpal, - ASSET_MIN_BALANCE * 1_000_000, - ); - let penpal_as_seen_by_ah = AssetHubRococo::sibling_location_of(PenpalA::para_id()); let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_as_seen_by_ah); AssetHubRococo::fund_accounts(vec![ - (AssetHubRococoSender::get().into(), 5_000_000 * ROCOCO_ED), /* An account to swap dot - * for something else. */ + // An account to swap dot for something else. + (AssetHubRococoSender::get().into(), 5_000_000 * ASSET_HUB_ROCOCO_ED), + // Penpal's sovereign account in AH should have some balance + (sov_penpal_on_ahr.clone().into(), 100_000_000 * ASSET_HUB_ROCOCO_ED), ]); AssetHubRococo::execute_with(|| { - // 3: Mint foreign asset on asset_hub_rococo: + // 0: No need to create foreign asset as it exists in genesis. + // + // 1: Mint foreign asset on asset_hub_rococo: // // (While it might be nice to use batch, // currently that's disabled due to safe call filters.) type RuntimeEvent = ::RuntimeEvent; - // 3. Mint foreign asset (in reality this should be a teleport or some such) + // 1. Mint foreign asset (in reality this should be a teleport or some such) assert_ok!(::ForeignAssets::mint( ::RuntimeOrigin::signed(sov_penpal_on_ahr.clone().into()), foreign_asset_at_asset_hub_rococo, sov_penpal_on_ahr.clone().into(), - 3_000_000_000_000, + ASSET_HUB_ROCOCO_ED * 3_000_000_000_000, )); assert_expected_events!( @@ -166,7 +154,7 @@ fn swap_locally_on_chain_using_foreign_assets() { ] ); - // 4. Create pool: + // 2. Create pool: assert_ok!(::AssetConversion::create_pool( ::RuntimeOrigin::signed(AssetHubRococoSender::get()), asset_native.clone(), @@ -180,7 +168,7 @@ fn swap_locally_on_chain_using_foreign_assets() { ] ); - // 5. Add liquidity: + // 3. Add liquidity: assert_ok!(::AssetConversion::add_liquidity( ::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()), asset_native.clone(), @@ -201,15 +189,15 @@ fn swap_locally_on_chain_using_foreign_assets() { ] ); - // 6. Swap! + // 4. Swap! let path = vec![asset_native.clone(), Box::new(foreign_asset_at_asset_hub_rococo)]; assert_ok!( ::AssetConversion::swap_exact_tokens_for_tokens( ::RuntimeOrigin::signed(AssetHubRococoSender::get()), path, - 100000, - 1000, + 100000 * ASSET_HUB_ROCOCO_ED, + 1000 * ASSET_HUB_ROCOCO_ED, AssetHubRococoSender::get().into(), true ) @@ -219,18 +207,18 @@ fn swap_locally_on_chain_using_foreign_assets() { AssetHubRococo, vec![ RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => { - amount_in: *amount_in == 100000, - amount_out: *amount_out == 199399, + amount_in: *amount_in == 333333300000, + amount_out: *amount_out == 498874118173, }, ] ); - // 7. Remove liquidity + // 5. Remove liquidity assert_ok!(::AssetConversion::remove_liquidity( ::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()), asset_native.clone(), Box::new(foreign_asset_at_asset_hub_rococo), - 1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved. + 1414213562273 - ASSET_HUB_ROCOCO_ED * 2, // all but the 2 EDs can't be retrieved. 0, 0, sov_penpal_on_ahr.clone().into(), diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/teleport.rs index dfb5061b55f..0cc5ddb9f64 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/teleport.rs @@ -13,11 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; -use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig; -use emulated_integration_tests_common::xcm_helpers::non_fee_asset; -use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig; -use rococo_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3; +use crate::imports::*; fn relay_origin_assertions(t: RelayToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -114,18 +110,21 @@ fn para_dest_assertions(t: RelayToSystemParaTest) { fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; - PenpalA::assert_xcm_pallet_attempted_complete(None); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); let expected_asset_id = t.args.asset_id.unwrap(); let (_, expected_asset_amount) = non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); + + PenpalA::assert_xcm_pallet_attempted_complete(None); assert_expected_events!( PenpalA, vec![ - RuntimeEvent::Balances( - pallet_balances::Event::Burned { who, amount } + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, .. } ) => { - who: *who == t.sender.account_id, - amount: *amount == t.args.amount, + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.sender.account_id, }, RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { asset_id: *asset_id == expected_asset_id, @@ -144,6 +143,9 @@ fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) { let (expected_foreign_asset_id, expected_foreign_asset_amount) = non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); let expected_foreign_asset_id_v3: v3::Location = expected_foreign_asset_id.try_into().unwrap(); + + AssetHubRococo::assert_xcmp_queue_success(None); + assert_expected_events!( AssetHubRococo, vec![ @@ -163,9 +165,6 @@ fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) { amount: *amount == expected_foreign_asset_amount, }, RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, - RuntimeEvent::MessageQueue( - pallet_message_queue::Event::Processed { success: true, .. } - ) => {}, ] ); } @@ -205,6 +204,11 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) { let (_, expected_asset_amount) = non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); let checking_account = ::PolkadotXcm::check_account(); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + PenpalA::assert_xcmp_queue_success(None); + assert_expected_events!( PenpalA, vec![ @@ -221,12 +225,11 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) { amount: *amount == expected_asset_amount, }, // native asset for fee is deposited to receiver - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { - who: *who == t.receiver.account_id, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, amount }) => { + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.receiver.account_id, + amount: *amount == expected_asset_amount, }, - RuntimeEvent::MessageQueue( - pallet_message_queue::Event::Processed { success: true, .. } - ) => {}, ] ); } @@ -558,30 +561,21 @@ fn teleport_to_other_system_parachains_works() { /// (using native reserve-based transfer for fees) #[test] fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { - let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id()); - let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get(); + // Init values for Parachain + let fee_amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 10000; + let asset_location_on_penpal = + v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion works"); let asset_id_on_penpal = match asset_location_on_penpal.last() { Some(v3::Junction::GeneralIndex(id)) => *id as u32, _ => unreachable!(), }; - let asset_owner_on_penpal = PenpalASender::get(); - let foreign_asset_at_asset_hub_rococo = - v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) - .appended_with(asset_location_on_penpal) - .unwrap(); - super::penpal_create_foreign_asset_on_asset_hub( - asset_id_on_penpal, - foreign_asset_at_asset_hub_rococo, - ah_as_seen_by_penpal.clone(), - false, - asset_owner_on_penpal, - ASSET_MIN_BALANCE * 1_000_000, - ); - let penpal_to_ah_beneficiary_id = AssetHubRococoReceiver::get(); - - let fee_amount_to_send = ASSET_HUB_ROCOCO_ED * 10_000; - let asset_amount_to_send = ASSET_MIN_BALANCE * 1000; - + let asset_amount_to_send = ASSET_HUB_ROCOCO_ED * 1000; + let asset_owner = PenpalAssetOwner::get(); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let sender = PenpalASender::get(); + let penpal_check_account = ::PolkadotXcm::check_account(); + let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubRococo::para_id()); let asset_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap(); let penpal_assets: Assets = vec![ (Parent, fee_amount_to_send).into(), @@ -594,6 +588,38 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { .position(|r| r == &(Parent, fee_amount_to_send).into()) .unwrap() as u32; + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner.clone()), + system_para_native_asset_location, + sender.clone(), + fee_amount_to_send, + ); + // No need to create the asset (only mint) as it exists in genesis. + PenpalA::mint_asset( + ::RuntimeOrigin::signed(asset_owner.clone()), + asset_id_on_penpal, + sender.clone(), + asset_amount_to_send, + ); + // fund Parachain's check account to be able to teleport + PenpalA::fund_accounts(vec![(penpal_check_account.clone().into(), ASSET_HUB_ROCOCO_ED * 1000)]); + + // prefund SA of Penpal on AssetHub with enough native tokens to pay for fees + let penpal_as_seen_by_ah = AssetHubRococo::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ah = AssetHubRococo::sovereign_account_id_of(penpal_as_seen_by_ah); + AssetHubRococo::fund_accounts(vec![( + sov_penpal_on_ah.clone().into(), + ASSET_HUB_ROCOCO_ED * 100_000_000_000, + )]); + + // Init values for System Parachain + let foreign_asset_at_asset_hub_rococo = + v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) + .appended_with(asset_location_on_penpal) + .unwrap(); + let penpal_to_ah_beneficiary_id = AssetHubRococoReceiver::get(); + // Penpal to AH test args let penpal_to_ah_test_args = TestContext { sender: PenpalASender::get(), @@ -608,8 +634,14 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { ), }; let mut penpal_to_ah = ParaToSystemParaTest::new(penpal_to_ah_test_args); + let penpal_sender_balance_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance( + system_para_native_asset_location, + &PenpalASender::get(), + ) + }); - let penpal_sender_balance_before = penpal_to_ah.sender.balance; let ah_receiver_balance_before = penpal_to_ah.receiver.balance; let penpal_sender_assets_before = PenpalA::execute_with(|| { @@ -629,7 +661,14 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { penpal_to_ah.set_dispatchable::(para_to_system_para_transfer_assets); penpal_to_ah.assert(); - let penpal_sender_balance_after = penpal_to_ah.sender.balance; + let penpal_sender_balance_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance( + system_para_native_asset_location, + &PenpalASender::get(), + ) + }); + let ah_receiver_balance_after = penpal_to_ah.receiver.balance; let penpal_sender_assets_after = PenpalA::execute_with(|| { @@ -704,7 +743,13 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { let mut ah_to_penpal = SystemParaToParaTest::new(ah_to_penpal_test_args); let ah_sender_balance_before = ah_to_penpal.sender.balance; - let penpal_receiver_balance_before = ah_to_penpal.receiver.balance; + let penpal_receiver_balance_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance( + system_para_native_asset_location, + &PenpalAReceiver::get(), + ) + }); let ah_sender_assets_before = AssetHubRococo::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -724,7 +769,13 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { ah_to_penpal.assert(); let ah_sender_balance_after = ah_to_penpal.sender.balance; - let penpal_receiver_balance_after = ah_to_penpal.receiver.balance; + let penpal_receiver_balance_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance( + system_para_native_asset_location, + &PenpalAReceiver::get(), + ) + }); let ah_sender_assets_after = AssetHubRococo::execute_with(|| { type ForeignAssets = ::ForeignAssets; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml index 0c920730d0f..8ac8efb5218 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml @@ -33,6 +33,7 @@ westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" } # Cumulus parachains-common = { path = "../../../../../../parachains/common" } testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["westend"] } +penpal-runtime = { path = "../../../../../runtimes/testing/penpal" } asset-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" } asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" } cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs index 409369df7bb..3f899d1dbdb 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs @@ -13,67 +13,83 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use codec::Encode; +#[cfg(test)] +mod imports { + pub use codec::Encode; + + // Substrate + pub use frame_support::{ + assert_err, assert_ok, + pallet_prelude::Weight, + sp_runtime::{DispatchError, DispatchResult, ModuleError}, + traits::fungibles::Inspect, + }; -// Substrate -pub use frame_support::{ - assert_err, assert_ok, - instances::Instance2, - pallet_prelude::Weight, - sp_runtime::{AccountId32, DispatchError, DispatchResult, ModuleError}, - traits::fungibles::Inspect, - BoundedVec, -}; + // Polkadot + pub use xcm::{ + prelude::{AccountId32 as AccountId32Junction, *}, + v3, + }; -// Polkadot -pub use xcm::{ - prelude::{AccountId32 as AccountId32Junction, *}, - v3::{self, Error, NetworkId::Westend as WestendId}, -}; + // Cumulus + pub use asset_test_utils::xcm_helpers; + pub use emulated_integration_tests_common::{ + test_parachain_is_trusted_teleporter, + xcm_emulator::{ + assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, + TestArgs, TestContext, TestExt, + }, + xcm_helpers::{non_fee_asset, xcm_transact_paid_execution}, + ASSETS_PALLET_ID, RESERVABLE_ASSET_ID, XCM_V3, + }; + pub use parachains_common::{AccountId, Balance}; + pub use westend_system_emulated_network::{ + asset_hub_westend_emulated_chain::{ + genesis::{AssetHubWestendAssetOwner, ED as ASSET_HUB_WESTEND_ED}, + AssetHubWestendParaPallet as AssetHubWestendPallet, + }, + collectives_westend_emulated_chain::CollectivesWestendParaPallet as CollectivesWestendPallet, + penpal_emulated_chain::{ + PenpalAParaPallet as PenpalAPallet, PenpalAssetOwner, + PenpalBParaPallet as PenpalBPallet, + }, + westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet}, + AssetHubWestendPara as AssetHubWestend, + AssetHubWestendParaReceiver as AssetHubWestendReceiver, + AssetHubWestendParaSender as AssetHubWestendSender, + BridgeHubWestendPara as BridgeHubWestend, + BridgeHubWestendParaReceiver as BridgeHubWestendReceiver, + CollectivesWestendPara as CollectivesWestend, PenpalAPara as PenpalA, + PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender, + PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, WestendRelay as Westend, + WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender, + }; -// Cumulus -pub use asset_test_utils::xcm_helpers; -pub use emulated_integration_tests_common::{ - test_parachain_is_trusted_teleporter, - xcm_emulator::{ - assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, - RelayChain as Relay, Test, TestArgs, TestContext, TestExt, - }, - xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, - PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, -}; -pub use parachains_common::{AccountId, Balance}; -pub use westend_system_emulated_network::{ - asset_hub_westend_emulated_chain::{ - genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, - }, - collectives_westend_emulated_chain::{ - genesis::ED as COLLECTIVES_WESTEND_ED, - CollectivesWestendParaPallet as CollectivesWestendPallet, - }, - penpal_emulated_chain::PenpalBParaPallet as PenpalBPallet, - westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet}, - AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver, - AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubWestendPara as BridgeHubWestend, - BridgeHubWestendParaReceiver as BridgeHubWestendReceiver, - CollectivesWestendPara as CollectivesWestend, PenpalAPara as PenpalA, - PenpalAParaReceiver as PenpalAReceiver, PenpalBPara as PenpalB, - PenpalBParaReceiver as PenpalBReceiver, PenpalBParaSender as PenpalBSender, - WestendRelay as Westend, WestendRelayReceiver as WestendReceiver, - WestendRelaySender as WestendSender, -}; + // Runtimes + pub use asset_hub_westend_runtime::xcm_config::{ + UniversalLocation as AssetHubWestendUniversalLocation, WestendLocation as RelayLocation, + XcmConfig as AssetHubWestendXcmConfig, + }; + pub use penpal_runtime::xcm_config::{ + LocalReservableFromAssetHub as PenpalLocalReservableFromAssetHub, + LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub, + UniversalLocation as PenpalUniversalLocation, XcmConfig as PenpalWestendXcmConfig, + }; + pub use westend_runtime::xcm_config::{ + UniversalLocation as WestendUniversalLocation, XcmConfig as WestendXcmConfig, + }; -pub const ASSET_ID: u32 = 1; -pub const ASSET_MIN_BALANCE: u128 = 1000; -// `Assets` pallet index -pub const ASSETS_PALLET_ID: u8 = 50; + pub const ASSET_ID: u32 = 3; + pub const ASSET_MIN_BALANCE: u128 = 1000; -pub type RelayToSystemParaTest = Test; -pub type RelayToParaTest = Test; -pub type SystemParaToRelayTest = Test; -pub type SystemParaToParaTest = Test; -pub type ParaToSystemParaTest = Test; -pub type ParaToParaTest = Test; + pub type RelayToSystemParaTest = Test; + pub type RelayToParaTest = Test; + pub type ParaToRelayTest = Test; + pub type SystemParaToRelayTest = Test; + pub type SystemParaToParaTest = Test; + pub type ParaToSystemParaTest = Test; + pub type ParaToParaThroughRelayTest = Test; +} #[cfg(test)] mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/fellowship_treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/fellowship_treasury.rs index 11e1e1762db..2d02e90f47f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/fellowship_treasury.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/fellowship_treasury.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; use emulated_integration_tests_common::accounts::{ALICE, BOB}; use frame_support::traits::fungibles::{Create, Inspect, Mutate}; use polkadot_runtime_common::impls::VersionedLocatableAsset; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs index a56cde8f2a2..3cd7c9c46d6 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs @@ -20,11 +20,3 @@ mod set_xcm_versions; mod swap; mod teleport; mod treasury; - -use crate::*; -emulated_integration_tests_common::include_penpal_create_foreign_asset_on_asset_hub!( - PenpalB, - AssetHubWestend, - WESTEND_ED, - testnet_parachains_constants::westend::fee::WeightToFee -); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs index a29cd10ba83..8c836132b54 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -13,10 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; -use asset_hub_westend_runtime::xcm_config::XcmConfig as AssetHubWestendXcmConfig; -use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig; -use westend_system_emulated_network::penpal_emulated_chain::XcmConfig as PenpalWestendXcmConfig; +use crate::imports::*; fn relay_to_para_sender_assertions(t: RelayToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -40,12 +37,30 @@ fn relay_to_para_sender_assertions(t: RelayToParaTest) { ); } +fn para_to_relay_sender_assertions(t: ParaToRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + PenpalA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799))); + assert_expected_events!( + PenpalA, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance, .. } + ) => { + asset_id: *asset_id == v3::Location::try_from(RelayLocation::get()).expect("conversion works"), + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + ] + ); +} + fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( - 676_119_000, - 6196, + 864_610_000, + 8_799, ))); assert_expected_events!( @@ -61,57 +76,96 @@ fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { ), amount: *amount == t.args.amount, }, + // Transport fees are paid + RuntimeEvent::PolkadotXcm( + pallet_xcm::Event::FeesPaid { .. } + ) => {}, ] ); + AssetHubWestend::assert_xcm_pallet_sent(); } -fn para_receiver_assertions(_: Test) { - type RuntimeEvent = ::RuntimeEvent; +fn system_para_to_para_receiver_assertions(t: SystemParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + PenpalA::assert_xcmp_queue_success(None); + assert_expected_events!( - PenpalB, + PenpalA, vec![ - RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, - RuntimeEvent::MessageQueue( - pallet_message_queue::Event::Processed { success: true, .. } - ) => {}, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.receiver.account_id, + }, ] ); } fn para_to_system_para_sender_assertions(t: ParaToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; + type RuntimeEvent = ::RuntimeEvent; + PenpalA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799))); + assert_expected_events!( + PenpalA, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance, .. } + ) => { + asset_id: *asset_id == v3::Location::try_from(RelayLocation::get()).expect("conversion works"), + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + ] + ); +} + +fn para_to_relay_receiver_assertions(t: ParaToRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_on_relay = + Westend::sovereign_account_id_of(Westend::child_location_of(PenpalA::para_id())); - PenpalB::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799))); + Westend::assert_ump_queue_processed( + true, + Some(PenpalA::para_id()), + Some(Weight::from_parts(306305000, 7_186)), + ); assert_expected_events!( - PenpalB, + Westend, vec![ - // Amount to reserve transfer is transferred to Parachain's Sovereign account + // Amount to reserve transfer is withdrawn from Parachain's Sovereign account RuntimeEvent::Balances( pallet_balances::Event::Burned { who, amount } ) => { - who: *who == t.sender.account_id, + who: *who == sov_penpal_on_relay.clone().into(), amount: *amount == t.args.amount, }, + RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, ] ); } fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; - - let sov_penpal_on_ahw = AssetHubWestend::sovereign_account_id_of( - AssetHubWestend::sibling_location_of(PenpalB::para_id()), + let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of( + AssetHubWestend::sibling_location_of(PenpalA::para_id()), ); + AssetHubWestend::assert_xcmp_queue_success(None); + assert_expected_events!( AssetHubWestend, vec![ - // Amount to reserve transfer is transferred to Parachain's Sovereign account + // Amount to reserve transfer is withdrawn from Parachain's Sovereign account RuntimeEvent::Balances( pallet_balances::Event::Burned { who, amount } ) => { - who: *who == sov_penpal_on_ahw.clone().into(), + who: *who == sov_penpal_on_ahr.clone().into(), amount: *amount == t.args.amount, }, RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, @@ -124,12 +178,10 @@ fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) { fn system_para_to_para_assets_sender_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; - AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( - 676_119_000, - 6196, + 864_610_000, + 8799, ))); - assert_expected_events!( AssetHubWestend, vec![ @@ -137,24 +189,124 @@ fn system_para_to_para_assets_sender_assertions(t: SystemParaToParaTest) { RuntimeEvent::Assets( pallet_assets::Event::Transferred { asset_id, from, to, amount } ) => { - asset_id: *asset_id == ASSET_ID, + asset_id: *asset_id == RESERVABLE_ASSET_ID, from: *from == t.sender.account_id, to: *to == AssetHubWestend::sovereign_account_id_of( t.args.dest.clone() ), amount: *amount == t.args.amount, }, + // Native asset to pay for fees is transferred to Parachain's Sovereign account + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { + who: *who == AssetHubWestend::sovereign_account_id_of( + t.args.dest.clone() + ), + }, + // Transport fees are paid + RuntimeEvent::PolkadotXcm( + pallet_xcm::Event::FeesPaid { .. } + ) => {}, ] ); } -fn system_para_to_para_assets_receiver_assertions(_: Test) { - type RuntimeEvent = ::RuntimeEvent; +fn para_to_system_para_assets_sender_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let reservable_asset_location = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("coversion works"); + PenpalA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8799))); assert_expected_events!( - PenpalB, + PenpalA, vec![ - RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, - RuntimeEvent::Assets(pallet_assets::Event::Issued { .. }) => {}, + // Fees amount to reserve transfer is burned from Parachains's sender account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, .. } + ) => { + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.sender.account_id, + }, + // Amount to reserve transfer is burned from Parachains's sender account + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance } + ) => { + asset_id: *asset_id == reservable_asset_location, + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, + }, + // Transport fees are paid + RuntimeEvent::PolkadotXcm( + pallet_xcm::Event::FeesPaid { .. } + ) => {}, + ] + ); +} + +fn system_para_to_para_assets_receiver_assertions(t: SystemParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let system_para_asset_location = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("coversion works"); + PenpalA::assert_xcmp_queue_success(None); + assert_expected_events!( + PenpalA, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { + asset_id: *asset_id == v3::Location::try_from(RelayLocation::get()).expect("conversion works"), + owner: *owner == t.receiver.account_id, + }, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, amount }) => { + asset_id: *asset_id == system_para_asset_location, + owner: *owner == t.receiver.account_id, + amount: *amount == t.args.amount, + }, + ] + ); +} + +fn para_to_system_para_assets_receiver_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of( + AssetHubWestend::sibling_location_of(PenpalA::para_id()), + ); + AssetHubWestend::assert_xcmp_queue_success(None); + assert_expected_events!( + AssetHubWestend, + vec![ + // Amount to reserve transfer is burned from Parachain's Sovereign account + RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { + asset_id: *asset_id == RESERVABLE_ASSET_ID, + owner: *owner == sov_penpal_on_ahr, + balance: *balance == t.args.amount, + }, + // Fee amount is burned from Parachain's Sovereign account + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, .. }) => { + who: *who == sov_penpal_on_ahr, + }, + // Amount to reserve transfer is issued for beneficiary + RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, owner, amount }) => { + asset_id: *asset_id == RESERVABLE_ASSET_ID, + owner: *owner == t.receiver.account_id, + amount: *amount == t.args.amount, + }, + // Remaining fee amount is minted for for beneficiary + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { + who: *who == t.receiver.account_id, + }, + ] + ); +} + +fn relay_to_para_assets_receiver_assertions(t: RelayToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + PenpalA, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { + asset_id: *asset_id == v3::Location::try_from(RelayLocation::get()).expect("conversion works"), + owner: *owner == t.receiver.account_id, + }, RuntimeEvent::MessageQueue( pallet_message_queue::Event::Processed { success: true, .. } ) => {}, @@ -162,33 +314,38 @@ fn system_para_to_para_assets_receiver_assertions(_: Test) { ); } -fn para_to_para_sender_assertions(t: ParaToParaTest) { - type RuntimeEvent = ::RuntimeEvent; - PenpalB::assert_xcm_pallet_attempted_complete(None); +fn para_to_para_through_relay_sender_assertions(t: ParaToParaThroughRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + + let relay_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + PenpalA::assert_xcm_pallet_attempted_complete(None); + // XCM sent to relay reserve + PenpalA::assert_parachain_system_ump_sent(); + assert_expected_events!( - PenpalB, + PenpalA, vec![ // Amount to reserve transfer is transferred to Parachain's Sovereign account - RuntimeEvent::Balances( - pallet_balances::Event::Burned { who, amount } + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, balance }, ) => { - who: *who == t.sender.account_id, - amount: *amount == t.args.amount, + asset_id: *asset_id == relay_asset_location, + owner: *owner == t.sender.account_id, + balance: *balance == t.args.amount, }, - // XCM sent to relay reserve - RuntimeEvent::ParachainSystem( - cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. } - ) => {}, ] ); } -fn para_to_para_relay_hop_assertions(t: ParaToParaTest) { +fn para_to_para_relay_hop_assertions(t: ParaToParaThroughRelayTest) { type RuntimeEvent = ::RuntimeEvent; - let sov_penpal_b_on_westend = - Westend::sovereign_account_id_of(Westend::child_location_of(PenpalB::para_id())); let sov_penpal_a_on_westend = Westend::sovereign_account_id_of(Westend::child_location_of(PenpalA::para_id())); + let sov_penpal_b_on_westend = + Westend::sovereign_account_id_of(Westend::child_location_of(PenpalB::para_id())); + assert_expected_events!( Westend, vec![ @@ -196,14 +353,14 @@ fn para_to_para_relay_hop_assertions(t: ParaToParaTest) { RuntimeEvent::Balances( pallet_balances::Event::Burned { who, amount } ) => { - who: *who == sov_penpal_b_on_westend, + who: *who == sov_penpal_a_on_westend, amount: *amount == t.args.amount, }, // Deposited to receiver parachain SA RuntimeEvent::Balances( pallet_balances::Event::Minted { who, .. } ) => { - who: *who == sov_penpal_a_on_westend, + who: *who == sov_penpal_b_on_westend, }, RuntimeEvent::MessageQueue( pallet_message_queue::Event::Processed { success: true, .. } @@ -212,15 +369,20 @@ fn para_to_para_relay_hop_assertions(t: ParaToParaTest) { ); } -fn para_to_para_receiver_assertions(_: ParaToParaTest) { - type RuntimeEvent = ::RuntimeEvent; +fn para_to_para_through_relay_receiver_assertions(t: ParaToParaThroughRelayTest) { + type RuntimeEvent = ::RuntimeEvent; + let relay_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + PenpalB::assert_xcmp_queue_success(None); + assert_expected_events!( - PenpalA, + PenpalB, vec![ - RuntimeEvent::Balances(pallet_balances::Event::Minted { .. }) => {}, - RuntimeEvent::MessageQueue( - pallet_message_queue::Event::Processed { success: true, .. } - ) => {}, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, .. }) => { + asset_id: *asset_id == relay_asset_location, + owner: *owner == t.receiver.account_id, + }, ] ); } @@ -236,6 +398,17 @@ fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { ) } +fn para_to_relay_reserve_transfer_assets(t: ParaToRelayTest) -> DispatchResult { + ::PolkadotXcm::limited_reserve_transfer_assets( + t.signed_origin, + bx!(t.args.dest.into()), + bx!(t.args.beneficiary.into()), + bx!(t.args.assets.into()), + t.args.fee_asset_item, + t.args.weight_limit, + ) +} + fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, @@ -248,7 +421,7 @@ fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> Dispa } fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( + ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, bx!(t.args.dest.into()), bx!(t.args.beneficiary.into()), @@ -258,8 +431,10 @@ fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> Dispa ) } -fn para_to_para_limited_reserve_transfer_assets(t: ParaToParaTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( +fn para_to_para_through_relay_limited_reserve_transfer_assets( + t: ParaToParaThroughRelayTest, +) -> DispatchResult { + ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, bx!(t.args.dest.into()), bx!(t.args.beneficiary.into()), @@ -272,6 +447,7 @@ fn para_to_para_limited_reserve_transfer_assets(t: ParaToParaTest) -> DispatchRe /// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work #[test] fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { + // Init values for Relay Chain let signed_origin = ::RuntimeOrigin::signed(WestendSender::get().into()); let destination = Westend::child_location_of(AssetHubWestend::para_id()); let beneficiary: Location = @@ -312,6 +488,7 @@ fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { let beneficiary: Location = AccountId32Junction { network: None, id: beneficiary_id.into() }.into(); let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000; + let assets: Assets = (Parent, amount_to_send).into(); let fee_asset_item = 0; @@ -337,136 +514,299 @@ fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { }); } +// ========================================================================= +// ========= Reserve Transfers - Native Asset - Relay<>Parachain =========== +// ========================================================================= /// Reserve Transfers of native asset from Relay to Parachain should work #[test] fn reserve_transfer_native_asset_from_relay_to_para() { // Init values for Relay - let destination = Westend::child_location_of(PenpalB::para_id()); - let beneficiary_id = PenpalBReceiver::get(); + let destination = Westend::child_location_of(PenpalA::para_id()); + let sender = WestendSender::get(); let amount_to_send: Balance = WESTEND_ED * 1000; + let assets: Assets = (Here, amount_to_send).into(); + // Init values fot Parachain + let relay_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let receiver = PenpalAReceiver::get(); + + // Init Test let test_args = TestContext { - sender: WestendSender::get(), - receiver: PenpalBReceiver::get(), - args: TestArgs::new_relay(destination, beneficiary_id, amount_to_send), + sender, + receiver: receiver.clone(), + args: TestArgs::new_relay(destination.clone(), receiver.clone(), amount_to_send), }; - let mut test = RelayToParaTest::new(test_args); + // Query initial balances let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; + let receiver_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.into(), &receiver) + }); + // Set assertions and dispatchables test.set_assertion::(relay_to_para_sender_assertions); - test.set_assertion::(para_receiver_assertions); + test.set_assertion::(relay_to_para_assets_receiver_assertions); test.set_dispatchable::(relay_to_para_reserve_transfer_assets); test.assert(); + // Calculate delivery fees let delivery_fees = Westend::execute_with(|| { + let reanchored_assets = + assets.reanchored(&destination, &WestendUniversalLocation::get()).unwrap(); xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); + // Query final balances let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; + let receiver_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.into(), &receiver) + }); // Sender's balance is reduced assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // Receiver's balance is increased + // Receiver's asset balance is increased + assert!(receiver_assets_after > receiver_assets_before); + // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; + // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but + // should be non-zero + assert!(receiver_assets_after < receiver_assets_before + amount_to_send); +} + +/// Reserve Transfers of native asset from Parachain to Relay should work +#[test] +fn reserve_transfer_native_asset_from_para_to_relay() { + // Init values for Parachain + let destination = PenpalA::parent_location(); + let sender = PenpalASender::get(); + let amount_to_send: Balance = WESTEND_ED * 1000; + let assets: Assets = (Parent, amount_to_send).into(); + let asset_owner = PenpalAssetOwner::get(); + let relay_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + relay_native_asset_location, + sender.clone(), + amount_to_send, + ); + + // Init values for Relay + let receiver = WestendReceiver::get(); + let penpal_location_as_seen_by_relay = Westend::child_location_of(PenpalA::para_id()); + let sov_penpal_on_relay = Westend::sovereign_account_id_of(penpal_location_as_seen_by_relay); + + // fund Parachain's SA on Relay with the native tokens held in reserve + Westend::fund_accounts(vec![(sov_penpal_on_relay.into(), amount_to_send * 2)]); + + // Init Test + let test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination.clone(), + receiver, + amount_to_send, + assets.clone(), + None, + 0, + ), + }; + let mut test = ParaToRelayTest::new(test_args); + + // Query initial balances + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.into(), &sender) + }); + let receiver_balance_before = test.receiver.balance; + + // Set assertions and dispatchables + test.set_assertion::(para_to_relay_sender_assertions); + test.set_assertion::(para_to_relay_receiver_assertions); + test.set_dispatchable::(para_to_relay_reserve_transfer_assets); + test.assert(); + + // Calculate delivery fees + let delivery_fees = PenpalA::execute_with(|| { + let reanchored_assets = + assets.reanchored(&destination, &PenpalUniversalLocation::get()).unwrap(); + xcm_helpers::transfer_assets_delivery_fees::< + ::XcmSender, + >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Query final balances + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location.into(), &sender) + }); + let receiver_balance_after = test.receiver.balance; + + // Sender's balance is reduced + assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); + // Receiver's asset balance is increased assert!(receiver_balance_after > receiver_balance_before); - // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; + // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but // should be non-zero assert!(receiver_balance_after < receiver_balance_before + amount_to_send); } +// ========================================================================= +// ======= Reserve Transfers - Native Asset - AssetHub<>Parachain ========== +// ========================================================================= /// Reserve Transfers of native asset from System Parachain to Parachain should work #[test] fn reserve_transfer_native_asset_from_system_para_to_para() { // Init values for System Parachain - let destination = AssetHubWestend::sibling_location_of(PenpalB::para_id()); - let beneficiary_id = PenpalBReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000; - let assets = (Parent, amount_to_send).into(); + let destination = AssetHubWestend::sibling_location_of(PenpalA::para_id()); + let sender = AssetHubWestendSender::get(); + let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 2000; + let assets: Assets = (Parent, amount_to_send).into(); + + // Init values for Parachain + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let receiver = PenpalAReceiver::get(); + // Init Test let test_args = TestContext { - sender: AssetHubWestendSender::get(), - receiver: PenpalBReceiver::get(), - args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), + sender, + receiver: receiver.clone(), + args: TestArgs::new_para( + destination.clone(), + receiver.clone(), + amount_to_send, + assets.clone(), + None, + 0, + ), }; - let mut test = SystemParaToParaTest::new(test_args); + // Query initial balances let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; + let receiver_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location.into(), &receiver) + }); + // Set assertions and dispatchables test.set_assertion::(system_para_to_para_sender_assertions); - test.set_assertion::(para_receiver_assertions); + test.set_assertion::(system_para_to_para_receiver_assertions); test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); test.assert(); - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - + // Calculate delivery fees let delivery_fees = AssetHubWestend::execute_with(|| { + let reanchored_assets = assets + .reanchored(&destination, &AssetHubWestendUniversalLocation::get()) + .unwrap(); xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Query final balances + let sender_balance_after = test.sender.balance; + let receiver_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &receiver) }); // Sender's balance is reduced assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // Receiver's balance is increased - assert!(receiver_balance_after > receiver_balance_before); - // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; + // Receiver's assets is increased + assert!(receiver_assets_after > receiver_assets_before); + // Receiver's assets increased by `amount_to_send - delivery_fees - bought_execution`; // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but // should be non-zero - assert!(receiver_balance_after < receiver_balance_before + amount_to_send); + assert!(receiver_assets_after < receiver_assets_before + amount_to_send); } /// Reserve Transfers of native asset from Parachain to System Parachain should work #[test] fn reserve_transfer_native_asset_from_para_to_system_para() { - // Init values for Penpal Parachain - let destination = PenpalB::sibling_location_of(AssetHubWestend::para_id()); - let beneficiary_id = AssetHubWestendReceiver::get(); + // Init values for Parachain + let destination = PenpalA::sibling_location_of(AssetHubWestend::para_id()); + let sender = PenpalASender::get(); let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000; - let assets = (Parent, amount_to_send).into(); + let assets: Assets = (Parent, amount_to_send).into(); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let asset_owner = PenpalAssetOwner::get(); + + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + system_para_native_asset_location, + sender.clone(), + amount_to_send, + ); + + // Init values for System Parachain + let receiver = AssetHubWestendReceiver::get(); + let penpal_location_as_seen_by_ahr = AssetHubWestend::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ahr = + AssetHubWestend::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + // fund Parachain's SA on System Parachain with the native tokens held in reserve + AssetHubWestend::fund_accounts(vec![(sov_penpal_on_ahr.into(), amount_to_send * 2)]); + + // Init Test let test_args = TestContext { - sender: PenpalBSender::get(), - receiver: AssetHubWestendReceiver::get(), - args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination.clone(), + receiver.clone(), + amount_to_send, + assets.clone(), + None, + 0, + ), }; - let mut test = ParaToSystemParaTest::new(test_args); - let sender_balance_before = test.sender.balance; + // Query initial balances + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &sender) + }); let receiver_balance_before = test.receiver.balance; - let penpal_location_as_seen_by_ahw = AssetHubWestend::sibling_location_of(PenpalB::para_id()); - let sov_penpal_on_ahw = - AssetHubWestend::sovereign_account_id_of(penpal_location_as_seen_by_ahw); - - // fund the Penpal's SA on AHW with the native tokens held in reserve - AssetHubWestend::fund_accounts(vec![(sov_penpal_on_ahw.into(), amount_to_send * 2)]); - - test.set_assertion::(para_to_system_para_sender_assertions); + // Set assertions and dispatchables + test.set_assertion::(para_to_system_para_sender_assertions); test.set_assertion::(para_to_system_para_receiver_assertions); - test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); + test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); test.assert(); - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - let delivery_fees = PenpalB::execute_with(|| { + // Calculate delivery fees + let delivery_fees = PenpalA::execute_with(|| { + let reanchored_assets = + assets.reanchored(&destination, &PenpalUniversalLocation::get()).unwrap(); xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Query final balances + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &sender) }); + let receiver_balance_after = test.receiver.balance; // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); // Receiver's balance is increased assert!(receiver_balance_after > receiver_balance_before); // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -475,36 +815,27 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { assert!(receiver_balance_after < receiver_balance_before + amount_to_send); } +// ========================================================================= +// ======= Reserve Transfers - Non-system Asset - AssetHub<>Parachain ====== +// ========================================================================= /// Reserve Transfers of a local asset and native asset from System Parachain to Parachain should /// work #[test] fn reserve_transfer_assets_from_system_para_to_para() { - // Force create asset on AssetHubWestend and PenpalB from Relay Chain - AssetHubWestend::force_create_and_mint_asset( - ASSET_ID, - ASSET_MIN_BALANCE, - true, - AssetHubWestendSender::get(), - Some(Weight::from_parts(1_019_445_000, 200_000)), - ASSET_MIN_BALANCE * 1_000_000, - ); - PenpalB::force_create_and_mint_asset( - ASSET_ID, - ASSET_MIN_BALANCE, - false, - PenpalBSender::get(), - None, - 0, - ); - // Init values for System Parachain - let destination = AssetHubWestend::sibling_location_of(PenpalB::para_id()); - let beneficiary_id = PenpalBReceiver::get(); - let fee_amount_to_send = ASSET_HUB_WESTEND_ED * 1000; - let asset_amount_to_send = ASSET_MIN_BALANCE * 1000; + let destination = AssetHubWestend::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of(destination.clone()); + let sender = AssetHubWestendSender::get(); + let fee_amount_to_send = ASSET_HUB_WESTEND_ED * 100; + let asset_amount_to_send = ASSET_HUB_WESTEND_ED * 100; + let asset_owner = AssetHubWestendAssetOwner::get(); + let asset_owner_signer = ::RuntimeOrigin::signed(asset_owner.clone()); let assets: Assets = vec![ (Parent, fee_amount_to_send).into(), - ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], asset_amount_to_send) + ( + [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(RESERVABLE_ASSET_ID.into())], + asset_amount_to_send, + ) .into(), ] .into(); @@ -513,49 +844,212 @@ fn reserve_transfer_assets_from_system_para_to_para() { .iter() .position(|r| r == &(Parent, fee_amount_to_send).into()) .unwrap() as u32; + AssetHubWestend::mint_asset( + asset_owner_signer, + RESERVABLE_ASSET_ID, + asset_owner, + asset_amount_to_send * 2, + ); + + // Create SA-of-Penpal-on-AHR with ED. + AssetHubWestend::fund_accounts(vec![(sov_penpal_on_ahr.into(), ASSET_HUB_WESTEND_ED)]); + + // Init values for Parachain + let receiver = PenpalAReceiver::get(); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let system_para_foreign_asset_location = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); + // Init Test let para_test_args = TestContext { - sender: AssetHubWestendSender::get(), - receiver: PenpalBReceiver::get(), + sender: sender.clone(), + receiver: receiver.clone(), args: TestArgs::new_para( destination, - beneficiary_id, + receiver.clone(), asset_amount_to_send, assets, None, fee_asset_index, ), }; - let mut test = SystemParaToParaTest::new(para_test_args); - // Create SA-of-Penpal-on-AHW with ED. - let penpal_location = AssetHubWestend::sibling_location_of(PenpalB::para_id()); - let sov_penpal_on_ahw = AssetHubWestend::sovereign_account_id_of(penpal_location); - AssetHubWestend::fund_accounts(vec![(sov_penpal_on_ahw.into(), WESTEND_ED)]); - + // Query initial balances let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - let sender_assets_before = AssetHubWestend::execute_with(|| { type Assets = ::Assets; - >::balance(ASSET_ID, &AssetHubWestendSender::get()) + >::balance(RESERVABLE_ASSET_ID, &sender) }); - let receiver_assets_before = PenpalB::execute_with(|| { - type Assets = ::Assets; - >::balance(ASSET_ID, &PenpalBReceiver::get()) + let receiver_system_native_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &receiver) + }); + let receiver_foreign_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_foreign_asset_location, &receiver) }); + // Set assertions and dispatchables test.set_assertion::(system_para_to_para_assets_sender_assertions); - test.set_assertion::(system_para_to_para_assets_receiver_assertions); + test.set_assertion::(system_para_to_para_assets_receiver_assertions); test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); test.assert(); + // Query final balances let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - + let sender_assets_after = AssetHubWestend::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &sender) + }); + let receiver_system_native_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &receiver) + }); + let receiver_foreign_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_foreign_asset_location, &receiver) + }); // Sender's balance is reduced assert!(sender_balance_after < sender_balance_before); + // Receiver's foreign asset balance is increased + assert!(receiver_foreign_assets_after > receiver_foreign_assets_before); + // Receiver's system asset balance increased by `amount_to_send - delivery_fees - + // bought_execution`; `delivery_fees` might be paid from transfer or JIT, also + // `bought_execution` is unknown but should be non-zero + assert!( + receiver_system_native_assets_after < + receiver_system_native_assets_before + fee_amount_to_send + ); + + // Sender's asset balance is reduced by exact amount + assert_eq!(sender_assets_before - asset_amount_to_send, sender_assets_after); + // Receiver's foreign asset balance is increased by exact amount + assert_eq!( + receiver_foreign_assets_after, + receiver_foreign_assets_before + asset_amount_to_send + ); +} + +/// Reserve Transfers of a foreign asset and native asset from Parachain to System Para should +/// work +#[test] +fn reserve_transfer_assets_from_para_to_system_para() { + // Init values for Parachain + let destination = PenpalA::sibling_location_of(AssetHubWestend::para_id()); + let sender = PenpalASender::get(); + let fee_amount_to_send = ASSET_HUB_WESTEND_ED * 100; + let asset_amount_to_send = ASSET_HUB_WESTEND_ED * 100; + let penpal_asset_owner = PenpalAssetOwner::get(); + let penpal_asset_owner_signer = ::RuntimeOrigin::signed(penpal_asset_owner); + let asset_location_on_penpal = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); + let asset_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap(); + let system_asset_location_on_penpal = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let assets: Assets = vec![ + (Parent, fee_amount_to_send).into(), + (asset_location_on_penpal_latest, asset_amount_to_send).into(), + ] + .into(); + let fee_asset_index = assets + .inner() + .iter() + .position(|r| r == &(Parent, fee_amount_to_send).into()) + .unwrap() as u32; + // Fund Parachain's sender account with some foreign assets + PenpalA::mint_foreign_asset( + penpal_asset_owner_signer.clone(), + asset_location_on_penpal, + sender.clone(), + asset_amount_to_send * 2, + ); + // Fund Parachain's sender account with some system assets + PenpalA::mint_foreign_asset( + penpal_asset_owner_signer, + system_asset_location_on_penpal, + sender.clone(), + fee_amount_to_send * 2, + ); + + // Init values for System Parachain + let receiver = AssetHubWestendReceiver::get(); + let penpal_location_as_seen_by_ahr = AssetHubWestend::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ahr = + AssetHubWestend::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let system_para_foreign_asset_location = + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); + let ah_asset_owner = AssetHubWestendAssetOwner::get(); + let ah_asset_owner_signer = ::RuntimeOrigin::signed(ah_asset_owner); + + // Fund SA-of-Penpal-on-AHR to be able to pay for the fees. + AssetHubWestend::fund_accounts(vec![( + sov_penpal_on_ahr.clone().into(), + ASSET_HUB_WESTEND_ED * 1000, + )]); + // Fund SA-of-Penpal-on-AHR to be able to pay for the sent amount. + AssetHubWestend::mint_asset( + ah_asset_owner_signer, + RESERVABLE_ASSET_ID, + sov_penpal_on_ahr, + asset_amount_to_send * 2, + ); + + // Init Test + let para_test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para( + destination, + receiver.clone(), + asset_amount_to_send, + assets, + None, + fee_asset_index, + ), + }; + let mut test = ParaToSystemParaTest::new(para_test_args); + + // Query initial balances + let sender_system_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &sender) + }); + let sender_foreign_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_foreign_asset_location, &sender) + }); + let receiver_balance_before = test.receiver.balance; + let receiver_assets_before = AssetHubWestend::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &receiver) + }); + + // Set assertions and dispatchables + test.set_assertion::(para_to_system_para_assets_sender_assertions); + test.set_assertion::(para_to_system_para_assets_receiver_assertions); + test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); + test.assert(); + + // Query final balances + let sender_system_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_native_asset_location, &sender) + }); + let sender_foreign_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(system_para_foreign_asset_location, &sender) + }); + let receiver_balance_after = test.receiver.balance; + let receiver_assets_after = AssetHubWestend::execute_with(|| { + type Assets = ::Assets; + >::balance(RESERVABLE_ASSET_ID, &receiver) + }); + // Sender's system asset balance is reduced + assert!(sender_system_assets_after < sender_system_assets_before); // Receiver's balance is increased assert!(receiver_balance_after > receiver_balance_before); // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -563,65 +1057,88 @@ fn reserve_transfer_assets_from_system_para_to_para() { // should be non-zero assert!(receiver_balance_after < receiver_balance_before + fee_amount_to_send); - let sender_assets_after = AssetHubWestend::execute_with(|| { - type Assets = ::Assets; - >::balance(ASSET_ID, &AssetHubWestendSender::get()) - }); - let receiver_assets_after = PenpalB::execute_with(|| { - type Assets = ::Assets; - >::balance(ASSET_ID, &PenpalBReceiver::get()) - }); - - // Sender's balance is reduced by exact amount - assert_eq!(sender_assets_before - asset_amount_to_send, sender_assets_after); - // Receiver's balance is increased by exact amount + // Sender's asset balance is reduced by exact amount + assert_eq!(sender_foreign_assets_before - asset_amount_to_send, sender_foreign_assets_after); + // Receiver's foreign asset balance is increased by exact amount assert_eq!(receiver_assets_after, receiver_assets_before + asset_amount_to_send); } +// ========================================================================= +// ===== Reserve Transfers - Native Asset - Parachain<>Relay<>Parachain ==== +// ========================================================================= /// Reserve Transfers of native asset from Parachain to Parachain (through Relay reserve) should /// work #[test] -fn reserve_transfer_native_asset_from_para_to_para() { - // Init values for Penpal Parachain - let destination = PenpalB::sibling_location_of(PenpalA::para_id()); - let beneficiary_id = PenpalAReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000; +fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { + // Init values for Parachain Origin + let destination = PenpalA::sibling_location_of(PenpalB::para_id()); + let sender = PenpalASender::get(); + let amount_to_send: Balance = WESTEND_ED * 10000; + let asset_owner = PenpalAssetOwner::get(); let assets = (Parent, amount_to_send).into(); + let relay_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let sender_as_seen_by_relay = Westend::child_location_of(PenpalA::para_id()); + let sov_of_sender_on_relay = Westend::sovereign_account_id_of(sender_as_seen_by_relay); - let test_args = TestContext { - sender: PenpalBSender::get(), - receiver: PenpalAReceiver::get(), - args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), - }; + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner), + relay_native_asset_location, + sender.clone(), + amount_to_send, + ); - let mut test = ParaToParaTest::new(test_args); + // fund the Parachain Origin's SA on Relay Chain with the native tokens held in reserve + Westend::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; + // Init values for Parachain Desitnation + let receiver = PenpalBReceiver::get(); - let sender_as_seen_by_relay = Westend::child_location_of(PenpalB::para_id()); - let sov_of_sender_on_relay = Westend::sovereign_account_id_of(sender_as_seen_by_relay); + // Init Test + let test_args = TestContext { + sender: sender.clone(), + receiver: receiver.clone(), + args: TestArgs::new_para(destination, receiver.clone(), amount_to_send, assets, None, 0), + }; + let mut test = ParaToParaThroughRelayTest::new(test_args); - // fund the PenpalB's SA on Westend with the native tokens held in reserve - Westend::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); + // Query initial balances + let sender_assets_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &sender) + }); + let receiver_assets_before = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &receiver) + }); - test.set_assertion::(para_to_para_sender_assertions); + // Set assertions and dispatchables + test.set_assertion::(para_to_para_through_relay_sender_assertions); test.set_assertion::(para_to_para_relay_hop_assertions); - test.set_assertion::(para_to_para_receiver_assertions); - test.set_dispatchable::(para_to_para_limited_reserve_transfer_assets); + test.set_assertion::(para_to_para_through_relay_receiver_assertions); + test.set_dispatchable::(para_to_para_through_relay_limited_reserve_transfer_assets); test.assert(); - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - let delivery_fees = PenpalB::execute_with(|| { + // Calculate delivery fees + let delivery_fees = PenpalA::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); + // Query final balances + let sender_assets_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &sender) + }); + let receiver_assets_after = PenpalB::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance(relay_native_asset_location, &receiver) + }); + // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); // Receiver's balance is increased - assert!(receiver_balance_after > receiver_balance_before); + assert!(receiver_assets_after > receiver_assets_before); } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs index a3cd5c5803e..eb0e985cc0c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; /// Relay Chain should be able to execute `Transact` instructions in System Parachain /// when `OriginKind::Superuser`. @@ -28,12 +28,99 @@ fn send_transact_as_superuser_from_relay_to_system_para_works() { ) } -/// Parachain should be able to send XCM paying its fee with sufficient asset -/// in the System Parachain +/// We tests two things here: +/// - Parachain should be able to send XCM paying its fee with system asset in the System Parachain +/// - Parachain should be able to create a new Foreign Asset in the System Parachain +#[test] +fn send_xcm_from_para_to_system_para_paying_fee_with_system_assets_works() { + let para_sovereign_account = AssetHubWestend::sovereign_account_id_of( + AssetHubWestend::sibling_location_of(PenpalA::para_id()), + ); + let asset_location_on_penpal = v3::Location::new( + 0, + [ + v3::Junction::PalletInstance(ASSETS_PALLET_ID), + v3::Junction::GeneralIndex(ASSET_ID.into()), + ], + ); + let foreign_asset_at_asset_hub = + v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) + .appended_with(asset_location_on_penpal) + .unwrap(); + + // Encoded `create_asset` call to be executed in AssetHub + let call = AssetHubWestend::create_foreign_asset_call( + foreign_asset_at_asset_hub, + ASSET_MIN_BALANCE, + para_sovereign_account.clone(), + ); + + let origin_kind = OriginKind::Xcm; + let fee_amount = ASSET_HUB_WESTEND_ED * 1000000; + let system_asset = (Parent, fee_amount).into(); + + let root_origin = ::RuntimeOrigin::root(); + let system_para_destination = PenpalA::sibling_location_of(AssetHubWestend::para_id()).into(); + let xcm = xcm_transact_paid_execution( + call, + origin_kind, + system_asset, + para_sovereign_account.clone(), + ); + + // SA-of-Penpal-on-AHR needs to have balance to pay for fees and asset creation deposit + AssetHubWestend::fund_accounts(vec![( + para_sovereign_account.clone().into(), + ASSET_HUB_WESTEND_ED * 10000000000, + )]); + + PenpalA::execute_with(|| { + assert_ok!(::PolkadotXcm::send( + root_origin, + bx!(system_para_destination), + bx!(xcm), + )); + + PenpalA::assert_xcm_pallet_sent(); + }); + + AssetHubWestend::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts( + 15_594_564_000, + 562_893, + ))); + + assert_expected_events!( + AssetHubWestend, + vec![ + // Burned the fee + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) => { + who: *who == para_sovereign_account, + amount: *amount == fee_amount, + }, + // Foreign Asset created + RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { asset_id, creator, owner }) => { + asset_id: *asset_id == foreign_asset_at_asset_hub, + creator: *creator == para_sovereign_account.clone(), + owner: *owner == para_sovereign_account, + }, + ] + ); + + type ForeignAssets = ::ForeignAssets; + assert!(ForeignAssets::asset_exists(foreign_asset_at_asset_hub)); + }); +} + +/// We tests two things here: +/// - Parachain should be able to send XCM paying its fee with system assets in the System Parachain +/// - Parachain should be able to create a new Asset in the System Parachain #[test] fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { let para_sovereign_account = AssetHubWestend::sovereign_account_id_of( - AssetHubWestend::sibling_location_of(PenpalB::para_id()), + AssetHubWestend::sibling_location_of(PenpalA::para_id()), ); // Force create and mint assets for Parachain's sovereign account @@ -46,57 +133,63 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { ASSET_MIN_BALANCE * 1000000000, ); - // We just need a call that can pass the `SafeCallFilter` - // Call values are not relevant - let call = AssetHubWestend::force_create_asset_call( - ASSET_ID, - para_sovereign_account.clone(), - true, + // Just a different `asset_id`` that does not exist yet + let new_asset_id = ASSET_ID + 1; + + // Encoded `create_asset` call to be executed in AssetHub + let call = AssetHubWestend::create_asset_call( + new_asset_id, ASSET_MIN_BALANCE, + para_sovereign_account.clone(), ); let origin_kind = OriginKind::SovereignAccount; let fee_amount = ASSET_MIN_BALANCE * 1000000; - let native_asset = + let asset = ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); - let root_origin = ::RuntimeOrigin::root(); - let system_para_destination = PenpalB::sibling_location_of(AssetHubWestend::para_id()).into(); - let xcm = xcm_transact_paid_execution( - call, - origin_kind, - native_asset, - para_sovereign_account.clone(), - ); + let root_origin = ::RuntimeOrigin::root(); + let system_para_destination = PenpalA::sibling_location_of(AssetHubWestend::para_id()).into(); + let xcm = xcm_transact_paid_execution(call, origin_kind, asset, para_sovereign_account.clone()); - PenpalB::execute_with(|| { - assert_ok!(::PolkadotXcm::send( + // SA-of-Penpal-on-AHR needs to have balance to pay for asset creation deposit + AssetHubWestend::fund_accounts(vec![( + para_sovereign_account.clone().into(), + ASSET_HUB_WESTEND_ED * 10000000000, + )]); + + PenpalA::execute_with(|| { + assert_ok!(::PolkadotXcm::send( root_origin, bx!(system_para_destination), bx!(xcm), )); - PenpalB::assert_xcm_pallet_sent(); + PenpalA::assert_xcm_pallet_sent(); }); AssetHubWestend::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; AssetHubWestend::assert_xcmp_queue_success(Some(Weight::from_parts( - 16_290_336_000, + 15_594_564_000, 562_893, ))); assert_expected_events!( AssetHubWestend, vec![ + // Burned the fee RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { asset_id: *asset_id == ASSET_ID, owner: *owner == para_sovereign_account, balance: *balance == fee_amount, }, - RuntimeEvent::Assets(pallet_assets::Event::Issued { asset_id, .. }) => { - asset_id: *asset_id == ASSET_ID, + // Asset created + RuntimeEvent::Assets(pallet_assets::Event::Created { asset_id, creator, owner }) => { + asset_id: *asset_id == new_asset_id, + creator: *creator == para_sovereign_account.clone(), + owner: *owner == para_sovereign_account, }, ] ); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/set_xcm_versions.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/set_xcm_versions.rs index 130454551d2..474e9a86ccc 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/set_xcm_versions.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/set_xcm_versions.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; #[test] fn relay_sets_system_para_xcm_supported_version() { diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs index b39cc2159de..04740d31158 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs @@ -13,8 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; -use westend_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3; +use crate::imports::*; #[test] fn swap_locally_on_chain_using_local_assets() { @@ -112,49 +111,39 @@ fn swap_locally_on_chain_using_local_assets() { #[test] fn swap_locally_on_chain_using_foreign_assets() { - let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocationV3::get()); - let ah_as_seen_by_penpal = PenpalB::sibling_location_of(AssetHubWestend::para_id()); - let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get(); - let asset_id_on_penpal = match asset_location_on_penpal.last() { - Some(v3::Junction::GeneralIndex(id)) => *id as u32, - _ => unreachable!(), - }; - let asset_owner_on_penpal = PenpalBSender::get(); + let asset_native = + Box::new(v3::Location::try_from(RelayLocation::get()).expect("conversion works")); + let asset_location_on_penpal = + v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion_works"); let foreign_asset_at_asset_hub_westend = - v3::Location::new(1, [v3::Junction::Parachain(PenpalB::para_id().into())]) + v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) .appended_with(asset_location_on_penpal) .unwrap(); - // 1. Create asset on penpal and, 2. Create foreign asset on asset_hub_westend - super::penpal_create_foreign_asset_on_asset_hub( - asset_id_on_penpal, - foreign_asset_at_asset_hub_westend, - ah_as_seen_by_penpal, - true, - asset_owner_on_penpal, - ASSET_MIN_BALANCE * 1_000_000, - ); - - let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalB::para_id()); - let sov_penpal_on_ahw = AssetHubWestend::sovereign_account_id_of(penpal_as_seen_by_ah); + let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of(penpal_as_seen_by_ah); AssetHubWestend::fund_accounts(vec![ - (AssetHubWestendSender::get().into(), 5_000_000 * WESTEND_ED), /* An account to swap dot - * for something else. */ + // An account to swap dot for something else. + (AssetHubWestendSender::get().into(), 5_000_000 * ASSET_HUB_WESTEND_ED), + // Penpal's sovereign account in AH should have some balance + (sov_penpal_on_ahr.clone().into(), 100_000_000 * ASSET_HUB_WESTEND_ED), ]); AssetHubWestend::execute_with(|| { - // 3: Mint foreign asset on asset_hub_westend: + // 0: No need to create foreign asset as it exists in genesis. + // + // 1: Mint foreign asset on asset_hub_westend: // // (While it might be nice to use batch, // currently that's disabled due to safe call filters.) type RuntimeEvent = ::RuntimeEvent; - // 3. Mint foreign asset (in reality this should be a teleport or some such) + // 1. Mint foreign asset (in reality this should be a teleport or some such) assert_ok!(::ForeignAssets::mint( - ::RuntimeOrigin::signed(sov_penpal_on_ahw.clone().into()), + ::RuntimeOrigin::signed(sov_penpal_on_ahr.clone().into()), foreign_asset_at_asset_hub_westend, - sov_penpal_on_ahw.clone().into(), - 3_000_000_000_000, + sov_penpal_on_ahr.clone().into(), + ASSET_HUB_WESTEND_ED * 3_000_000_000_000, )); assert_expected_events!( @@ -164,7 +153,7 @@ fn swap_locally_on_chain_using_foreign_assets() { ] ); - // 4. Create pool: + // 2. Create pool: assert_ok!(::AssetConversion::create_pool( ::RuntimeOrigin::signed(AssetHubWestendSender::get()), asset_native.clone(), @@ -178,58 +167,60 @@ fn swap_locally_on_chain_using_foreign_assets() { ] ); - // 5. Add liquidity: + // 3. Add liquidity: assert_ok!(::AssetConversion::add_liquidity( - ::RuntimeOrigin::signed(sov_penpal_on_ahw.clone()), + ::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()), asset_native.clone(), Box::new(foreign_asset_at_asset_hub_westend), - 1_000_000_000_000, - 2_000_000_000_000, + 1_000_000_000_000_000, + 2_000_000_000_000_000, 0, 0, - sov_penpal_on_ahw.clone().into() + sov_penpal_on_ahr.clone().into() )); assert_expected_events!( AssetHubWestend, vec![ RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { - lp_token_minted: *lp_token_minted == 1414213562273, + lp_token_minted: *lp_token_minted == 1414213562372995, }, ] ); - // 6. Swap! + // 4. Swap! let path = vec![asset_native.clone(), Box::new(foreign_asset_at_asset_hub_westend)]; - assert_ok!(::AssetConversion::swap_exact_tokens_for_tokens( - ::RuntimeOrigin::signed(AssetHubWestendSender::get()), - path, - 100000, - 1000, - AssetHubWestendSender::get().into(), - true - )); + assert_ok!( + ::AssetConversion::swap_exact_tokens_for_tokens( + ::RuntimeOrigin::signed(AssetHubWestendSender::get()), + path, + 100000 * ASSET_HUB_WESTEND_ED, + 1000 * ASSET_HUB_WESTEND_ED, + AssetHubWestendSender::get().into(), + true + ) + ); assert_expected_events!( AssetHubWestend, vec![ RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => { - amount_in: *amount_in == 100000, - amount_out: *amount_out == 199399, + amount_in: *amount_in == 100000000000000, + amount_out: *amount_out == 181322178776029, }, ] ); - // 7. Remove liquidity + // 5. Remove liquidity assert_ok!(::AssetConversion::remove_liquidity( - ::RuntimeOrigin::signed(sov_penpal_on_ahw.clone()), + ::RuntimeOrigin::signed(sov_penpal_on_ahr.clone()), asset_native.clone(), Box::new(foreign_asset_at_asset_hub_westend), - 1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved. + 1414213562372995 - ASSET_HUB_WESTEND_ED * 2, // all but the 2 EDs can't be retrieved. 0, 0, - sov_penpal_on_ahw.into(), + sov_penpal_on_ahr.clone().into(), )); }); } @@ -283,7 +274,7 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { .into(), }; let penpal = AssetHubWestend::sovereign_account_id_of(AssetHubWestend::sibling_location_of( - PenpalB::para_id(), + PenpalA::para_id(), )); AssetHubWestend::execute_with(|| { @@ -356,7 +347,7 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { )); }); - PenpalB::execute_with(|| { + PenpalA::execute_with(|| { // send xcm transact from `penpal` account which as only `ASSET_ID` tokens on // `AssetHubWestend` let call = AssetHubWestend::force_create_asset_call( @@ -366,11 +357,11 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { ASSET_MIN_BALANCE, ); - let penpal_root = ::RuntimeOrigin::root(); + let penpal_root = ::RuntimeOrigin::root(); let fee_amount = 4_000_000_000_000u128; let asset_one = ([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into(); - let asset_hub_location = PenpalB::sibling_location_of(AssetHubWestend::para_id()).into(); + let asset_hub_location = PenpalA::sibling_location_of(AssetHubWestend::para_id()).into(); let xcm = xcm_transact_paid_execution( call, OriginKind::SovereignAccount, @@ -378,13 +369,13 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { penpal.clone(), ); - assert_ok!(::PolkadotXcm::send( + assert_ok!(::PolkadotXcm::send( penpal_root, bx!(asset_hub_location), bx!(xcm), )); - PenpalB::assert_xcm_pallet_sent(); + PenpalA::assert_xcm_pallet_sent(); }); AssetHubWestend::execute_with(|| { diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/teleport.rs index 0dd1a1533b5..61f547fe7c5 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/teleport.rs @@ -13,16 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; -use asset_hub_westend_runtime::xcm_config::XcmConfig as AssetHubWestendXcmConfig; -use emulated_integration_tests_common::xcm_helpers::non_fee_asset; -use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig; -use westend_system_emulated_network::penpal_emulated_chain::LocalTeleportableToAssetHubV3 as PenpalLocalTeleportableToAssetHubV3; +use crate::imports::*; fn relay_origin_assertions(t: RelayToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; - Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(632_207_000, 7_186))); + Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(631_531_000, 7_186))); assert_expected_events!( Westend, @@ -47,7 +43,7 @@ fn relay_dest_assertions(t: SystemParaToRelayTest) { Westend::assert_ump_queue_processed( true, Some(AssetHubWestend::para_id()), - Some(Weight::from_parts(308_222_000, 7_186)), + Some(Weight::from_parts(307_225_000, 7_186)), ); assert_expected_events!( @@ -70,7 +66,7 @@ fn relay_dest_assertions_fail(_t: SystemParaToRelayTest) { Westend::assert_ump_queue_processed( false, Some(AssetHubWestend::para_id()), - Some(Weight::from_parts(148_705_000, 3_593)), + Some(Weight::from_parts(157_718_000, 3_593)), ); } @@ -78,8 +74,8 @@ fn para_origin_assertions(t: SystemParaToRelayTest) { type RuntimeEvent = ::RuntimeEvent; AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( - 533_910_000, - 7167, + 720_053_000, + 7_203, ))); AssetHubWestend::assert_parachain_system_ump_sent(); @@ -99,7 +95,7 @@ fn para_origin_assertions(t: SystemParaToRelayTest) { fn para_dest_assertions(t: RelayToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; - AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(164_793_000, 3593))); + AssetHubWestend::assert_dmp_queue_complete(Some(Weight::from_parts(157_718_000, 3593))); assert_expected_events!( AssetHubWestend, @@ -113,19 +109,22 @@ fn para_dest_assertions(t: RelayToSystemParaTest) { } fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; - PenpalB::assert_xcm_pallet_attempted_complete(None); + type RuntimeEvent = ::RuntimeEvent; + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); let expected_asset_id = t.args.asset_id.unwrap(); let (_, expected_asset_amount) = non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); + + PenpalA::assert_xcm_pallet_attempted_complete(None); assert_expected_events!( - PenpalB, + PenpalA, vec![ - RuntimeEvent::Balances( - pallet_balances::Event::Burned { who, amount } + RuntimeEvent::ForeignAssets( + pallet_assets::Event::Burned { asset_id, owner, .. } ) => { - who: *who == t.sender.account_id, - amount: *amount == t.args.amount, + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.sender.account_id, }, RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { asset_id: *asset_id == expected_asset_id, @@ -139,11 +138,14 @@ fn penpal_to_ah_foreign_assets_sender_assertions(t: ParaToSystemParaTest) { fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) { type RuntimeEvent = ::RuntimeEvent; let sov_penpal_on_ahr = AssetHubWestend::sovereign_account_id_of( - AssetHubWestend::sibling_location_of(PenpalB::para_id()), + AssetHubWestend::sibling_location_of(PenpalA::para_id()), ); let (expected_foreign_asset_id, expected_foreign_asset_amount) = non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); let expected_foreign_asset_id_v3: v3::Location = expected_foreign_asset_id.try_into().unwrap(); + + AssetHubWestend::assert_xcmp_queue_success(None); + assert_expected_events!( AssetHubWestend, vec![ @@ -163,9 +165,6 @@ fn penpal_to_ah_foreign_assets_receiver_assertions(t: ParaToSystemParaTest) { amount: *amount == expected_foreign_asset_amount, }, RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, - RuntimeEvent::MessageQueue( - pallet_message_queue::Event::Processed { success: true, .. } - ) => {}, ] ); } @@ -200,13 +199,18 @@ fn ah_to_penpal_foreign_assets_sender_assertions(t: SystemParaToParaTest) { } fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) { - type RuntimeEvent = ::RuntimeEvent; + type RuntimeEvent = ::RuntimeEvent; let expected_asset_id = t.args.asset_id.unwrap(); let (_, expected_asset_amount) = non_fee_asset(&t.args.assets, t.args.fee_asset_item as usize).unwrap(); - let checking_account = ::PolkadotXcm::check_account(); + let checking_account = ::PolkadotXcm::check_account(); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + + PenpalA::assert_xcmp_queue_success(None); + assert_expected_events!( - PenpalB, + PenpalA, vec![ // checking account burns local asset as part of incoming teleport RuntimeEvent::Assets(pallet_assets::Event::Burned { asset_id, owner, balance }) => { @@ -221,12 +225,11 @@ fn ah_to_penpal_foreign_assets_receiver_assertions(t: SystemParaToParaTest) { amount: *amount == expected_asset_amount, }, // native asset for fee is deposited to receiver - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. }) => { - who: *who == t.receiver.account_id, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, owner, amount }) => { + asset_id: *asset_id == system_para_native_asset_location, + owner: *owner == t.receiver.account_id, + amount: *amount == expected_asset_amount, }, - RuntimeEvent::MessageQueue( - pallet_message_queue::Event::Processed { success: true, .. } - ) => {}, ] ); } @@ -273,8 +276,8 @@ fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult { ) } -fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { - ::PolkadotXcm::transfer_assets( +fn para_to_system_para_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult { + ::PolkadotXcm::transfer_assets( t.signed_origin, bx!(t.args.dest.into()), bx!(t.args.beneficiary.into()), @@ -284,8 +287,8 @@ fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResul ) } -fn para_to_system_para_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult { - ::PolkadotXcm::transfer_assets( +fn system_para_to_para_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { + ::PolkadotXcm::transfer_assets( t.signed_origin, bx!(t.args.dest.into()), bx!(t.args.beneficiary.into()), @@ -301,11 +304,11 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { // Init values for Relay Chain let amount_to_send: Balance = WESTEND_ED * 1000; let dest = Westend::child_location_of(AssetHubWestend::para_id()); - let beneficiary = AssetHubWestendReceiver::get(); + let beneficiary_id = AssetHubWestendReceiver::get(); let test_args = TestContext { sender: WestendSender::get(), - receiver: beneficiary.clone(), - args: TestArgs::new_relay(dest, beneficiary, amount_to_send), + receiver: AssetHubWestendReceiver::get(), + args: TestArgs::new_relay(dest, beneficiary_id, amount_to_send), }; let mut test = RelayToSystemParaTest::new(test_args); @@ -424,11 +427,11 @@ fn teleport_native_assets_from_relay_to_system_para_works() { // Init values for Relay Chain let amount_to_send: Balance = WESTEND_ED * 1000; let dest = Westend::child_location_of(AssetHubWestend::para_id()); - let beneficiary = AssetHubWestendReceiver::get(); + let beneficiary_id = AssetHubWestendReceiver::get(); let test_args = TestContext { sender: WestendSender::get(), - receiver: beneficiary.clone(), - args: TestArgs::new_relay(dest, beneficiary, amount_to_send), + receiver: AssetHubWestendReceiver::get(), + args: TestArgs::new_relay(dest, beneficiary_id, amount_to_send), }; let mut test = RelayToSystemParaTest::new(test_args); @@ -485,15 +488,15 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { test.set_dispatchable::(system_para_teleport_assets); test.assert(); + let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; + let delivery_fees = AssetHubWestend::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - // Sender's balance is reduced assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); // Receiver's balance is increased @@ -558,30 +561,21 @@ fn teleport_to_other_system_parachains_works() { /// (using native reserve-based transfer for fees) #[test] fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { - let ah_as_seen_by_penpal = PenpalB::sibling_location_of(AssetHubWestend::para_id()); - let asset_location_on_penpal = PenpalLocalTeleportableToAssetHubV3::get(); + // Init values for Parachain + let fee_amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 100; + let asset_location_on_penpal = + v3::Location::try_from(PenpalLocalTeleportableToAssetHub::get()).expect("conversion works"); let asset_id_on_penpal = match asset_location_on_penpal.last() { Some(v3::Junction::GeneralIndex(id)) => *id as u32, _ => unreachable!(), }; - let asset_owner_on_penpal = PenpalBSender::get(); - let foreign_asset_at_asset_hub_westend = - v3::Location::new(1, [v3::Junction::Parachain(PenpalB::para_id().into())]) - .appended_with(asset_location_on_penpal) - .unwrap(); - super::penpal_create_foreign_asset_on_asset_hub( - asset_id_on_penpal, - foreign_asset_at_asset_hub_westend, - ah_as_seen_by_penpal.clone(), - false, - asset_owner_on_penpal, - ASSET_MIN_BALANCE * 1_000_000, - ); - let penpal_to_ah_beneficiary_id = AssetHubWestendReceiver::get(); - - let fee_amount_to_send = ASSET_HUB_WESTEND_ED * 1000; - let asset_amount_to_send = ASSET_MIN_BALANCE * 1000; - + let asset_amount_to_send = ASSET_HUB_WESTEND_ED * 100; + let asset_owner = PenpalAssetOwner::get(); + let system_para_native_asset_location = + v3::Location::try_from(RelayLocation::get()).expect("conversion works"); + let sender = PenpalASender::get(); + let penpal_check_account = ::PolkadotXcm::check_account(); + let ah_as_seen_by_penpal = PenpalA::sibling_location_of(AssetHubWestend::para_id()); let asset_location_on_penpal_latest: Location = asset_location_on_penpal.try_into().unwrap(); let penpal_assets: Assets = vec![ (Parent, fee_amount_to_send).into(), @@ -594,9 +588,44 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { .position(|r| r == &(Parent, fee_amount_to_send).into()) .unwrap() as u32; + // fund Parachain's sender account + PenpalA::mint_foreign_asset( + ::RuntimeOrigin::signed(asset_owner.clone()), + system_para_native_asset_location, + sender.clone(), + fee_amount_to_send, + ); + // No need to create the asset (only mint) as it exists in genesis. + PenpalA::mint_asset( + ::RuntimeOrigin::signed(asset_owner.clone()), + asset_id_on_penpal, + sender.clone(), + asset_amount_to_send, + ); + // fund Parachain's check account to be able to teleport + PenpalA::fund_accounts(vec![( + penpal_check_account.clone().into(), + ASSET_HUB_WESTEND_ED * 1000, + )]); + + // prefund SA of Penpal on AssetHub with enough native tokens to pay for fees + let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalA::para_id()); + let sov_penpal_on_ah = AssetHubWestend::sovereign_account_id_of(penpal_as_seen_by_ah); + AssetHubWestend::fund_accounts(vec![( + sov_penpal_on_ah.clone().into(), + ASSET_HUB_WESTEND_ED * 100_000_000_000, + )]); + + // Init values for System Parachain + let foreign_asset_at_asset_hub_westend = + v3::Location::new(1, [v3::Junction::Parachain(PenpalA::para_id().into())]) + .appended_with(asset_location_on_penpal) + .unwrap(); + let penpal_to_ah_beneficiary_id = AssetHubWestendReceiver::get(); + // Penpal to AH test args let penpal_to_ah_test_args = TestContext { - sender: PenpalBSender::get(), + sender: PenpalASender::get(), receiver: AssetHubWestendReceiver::get(), args: TestArgs::new_para( ah_as_seen_by_penpal, @@ -608,13 +637,19 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { ), }; let mut penpal_to_ah = ParaToSystemParaTest::new(penpal_to_ah_test_args); + let penpal_sender_balance_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance( + system_para_native_asset_location, + &PenpalASender::get(), + ) + }); - let penpal_sender_balance_before = penpal_to_ah.sender.balance; let ah_receiver_balance_before = penpal_to_ah.receiver.balance; - let penpal_sender_assets_before = PenpalB::execute_with(|| { - type Assets = ::Assets; - >::balance(asset_id_on_penpal, &PenpalBSender::get()) + let penpal_sender_assets_before = PenpalA::execute_with(|| { + type Assets = ::Assets; + >::balance(asset_id_on_penpal, &PenpalASender::get()) }); let ah_receiver_assets_before = AssetHubWestend::execute_with(|| { type Assets = ::ForeignAssets; @@ -624,17 +659,24 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { ) }); - penpal_to_ah.set_assertion::(penpal_to_ah_foreign_assets_sender_assertions); + penpal_to_ah.set_assertion::(penpal_to_ah_foreign_assets_sender_assertions); penpal_to_ah.set_assertion::(penpal_to_ah_foreign_assets_receiver_assertions); - penpal_to_ah.set_dispatchable::(para_to_system_para_transfer_assets); + penpal_to_ah.set_dispatchable::(para_to_system_para_transfer_assets); penpal_to_ah.assert(); - let penpal_sender_balance_after = penpal_to_ah.sender.balance; + let penpal_sender_balance_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance( + system_para_native_asset_location, + &PenpalASender::get(), + ) + }); + let ah_receiver_balance_after = penpal_to_ah.receiver.balance; - let penpal_sender_assets_after = PenpalB::execute_with(|| { - type Assets = ::Assets; - >::balance(asset_id_on_penpal, &PenpalBSender::get()) + let penpal_sender_assets_after = PenpalA::execute_with(|| { + type Assets = ::Assets; + >::balance(asset_id_on_penpal, &PenpalASender::get()) }); let ah_receiver_assets_after = AssetHubWestend::execute_with(|| { type Assets = ::ForeignAssets; @@ -675,8 +717,8 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { let foreign_asset_at_asset_hub_westend_latest: Location = foreign_asset_at_asset_hub_westend.try_into().unwrap(); - let ah_to_penpal_beneficiary_id = PenpalBReceiver::get(); - let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalB::para_id()); + let ah_to_penpal_beneficiary_id = PenpalAReceiver::get(); + let penpal_as_seen_by_ah = AssetHubWestend::sibling_location_of(PenpalA::para_id()); let ah_assets: Assets = vec![ (Parent, fee_amount_to_send).into(), (foreign_asset_at_asset_hub_westend_latest, asset_amount_to_send).into(), @@ -691,7 +733,7 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { // AH to Penpal test args let ah_to_penpal_test_args = TestContext { sender: AssetHubWestendSender::get(), - receiver: PenpalBReceiver::get(), + receiver: PenpalAReceiver::get(), args: TestArgs::new_para( penpal_as_seen_by_ah, ah_to_penpal_beneficiary_id, @@ -704,7 +746,13 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { let mut ah_to_penpal = SystemParaToParaTest::new(ah_to_penpal_test_args); let ah_sender_balance_before = ah_to_penpal.sender.balance; - let penpal_receiver_balance_before = ah_to_penpal.receiver.balance; + let penpal_receiver_balance_before = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance( + system_para_native_asset_location, + &PenpalAReceiver::get(), + ) + }); let ah_sender_assets_before = AssetHubWestend::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -713,18 +761,24 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { &AssetHubWestendSender::get(), ) }); - let penpal_receiver_assets_before = PenpalB::execute_with(|| { - type Assets = ::Assets; - >::balance(asset_id_on_penpal, &PenpalBReceiver::get()) + let penpal_receiver_assets_before = PenpalA::execute_with(|| { + type Assets = ::Assets; + >::balance(asset_id_on_penpal, &PenpalAReceiver::get()) }); ah_to_penpal.set_assertion::(ah_to_penpal_foreign_assets_sender_assertions); - ah_to_penpal.set_assertion::(ah_to_penpal_foreign_assets_receiver_assertions); + ah_to_penpal.set_assertion::(ah_to_penpal_foreign_assets_receiver_assertions); ah_to_penpal.set_dispatchable::(system_para_to_para_transfer_assets); ah_to_penpal.assert(); let ah_sender_balance_after = ah_to_penpal.sender.balance; - let penpal_receiver_balance_after = ah_to_penpal.receiver.balance; + let penpal_receiver_balance_after = PenpalA::execute_with(|| { + type ForeignAssets = ::ForeignAssets; + >::balance( + system_para_native_asset_location, + &PenpalAReceiver::get(), + ) + }); let ah_sender_assets_after = AssetHubWestend::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -733,9 +787,9 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { &AssetHubWestendSender::get(), ) }); - let penpal_receiver_assets_after = PenpalB::execute_with(|| { - type Assets = ::Assets; - >::balance(asset_id_on_penpal, &PenpalBReceiver::get()) + let penpal_receiver_assets_after = PenpalA::execute_with(|| { + type Assets = ::Assets; + >::balance(asset_id_on_penpal, &PenpalAReceiver::get()) }); // Sender's balance is reduced diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury.rs index 8e82059a32d..6d8c0f5e5de 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; use emulated_integration_tests_common::accounts::{ALICE, BOB}; use frame_support::traits::fungibles::{Create, Inspect, Mutate}; use polkadot_runtime_common::impls::VersionedLocatableAsset; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs index 9ce981b074c..b5e19cf3fa3 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs @@ -13,62 +13,53 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Substrate -pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult}; -pub use sp_runtime::DispatchError; - -// Polkadot -pub use xcm::{ - latest::ParentThen, - prelude::{AccountId32 as AccountId32Junction, *}, - v3::{ - self, Error, - NetworkId::{Rococo as RococoId, Westend as WestendId}, - }, -}; +#[cfg(test)] +mod imports { + // Substrate + pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult}; + pub use sp_runtime::DispatchError; -// Bridges -pub use bp_messages::LaneId; + // Polkadot + pub use xcm::{ + latest::ParentThen, + prelude::{AccountId32 as AccountId32Junction, *}, + v3::{self, NetworkId::Westend as WestendId}, + }; -// Cumulus -pub use emulated_integration_tests_common::{ - accounts::ALICE, - impls::Inspect, - test_parachain_is_trusted_teleporter, - xcm_emulator::{ - assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, - RelayChain as Relay, Test, TestArgs, TestContext, TestExt, - }, - xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, - PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, -}; -pub use parachains_common::{AccountId, Balance}; -pub use rococo_westend_system_emulated_network::{ - asset_hub_rococo_emulated_chain::{ - genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, - }, - asset_hub_westend_emulated_chain::{ - genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, - }, - bridge_hub_rococo_emulated_chain::{ - genesis::ED as BRIDGE_HUB_ROCOCO_ED, BridgeHubRococoParaPallet as BridgeHubRococoPallet, - }, - penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet, - rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet}, - AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver, - AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend, - AssetHubWestendParaReceiver as AssetHubWestendReceiver, - AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo, - BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, - BridgeHubRococoParaSender as BridgeHubRococoSender, BridgeHubWestendPara as BridgeHubWestend, - PenpalAPara as PenpalA, PenpalAParaReceiver as PenpalAReceiver, - PenpalAParaSender as PenpalASender, RococoRelay as Rococo, - RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender, -}; + // Cumulus + pub use emulated_integration_tests_common::{ + accounts::ALICE, + impls::Inspect, + test_parachain_is_trusted_teleporter, + xcm_emulator::{ + assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt, + }, + }; + pub use parachains_common::AccountId; + pub use rococo_westend_system_emulated_network::{ + asset_hub_rococo_emulated_chain::{ + genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, + }, + asset_hub_westend_emulated_chain::{ + genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, + }, + bridge_hub_rococo_emulated_chain::{ + genesis::ED as BRIDGE_HUB_ROCOCO_ED, BridgeHubRococoParaPallet as BridgeHubRococoPallet, + }, + penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet, + rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet}, + AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver, + AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend, + AssetHubWestendParaReceiver as AssetHubWestendReceiver, + AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo, + BridgeHubRococoParaSender as BridgeHubRococoSender, + BridgeHubWestendPara as BridgeHubWestend, PenpalAPara as PenpalA, + PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender, + RococoRelay as Rococo, + }; -pub const ASSET_ID: u32 = 1; -pub const ASSET_MIN_BALANCE: u128 = 1000; -pub const ASSETS_PALLET_ID: u8 = 50; + pub const ASSET_MIN_BALANCE: u128 = 1000; +} #[cfg(test)] mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs index 6d7b53c8fdf..88dad06434b 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; mod asset_transfers; mod send_xcm; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index ff069e2d344..1e74d63e1d5 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -12,7 +12,7 @@ // 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. -use crate::*; +use crate::imports::*; use bridge_hub_rococo_runtime::{EthereumBeaconClient, EthereumInboundQueue, RuntimeOrigin}; use codec::{Decode, Encode}; use emulated_integration_tests_common::xcm_emulator::ConvertLocation; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/teleport.rs index 43f8af9244f..8f51f5b1800 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/teleport.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::tests::*; use bridge_hub_rococo_runtime::xcm_config::XcmConfig; #[test] diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs index 223979cc9c9..60c31ce5a4a 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs @@ -13,59 +13,52 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Substrate -pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult}; -pub use sp_runtime::DispatchError; - -// Polkadot -pub use xcm::{ - latest::ParentThen, - prelude::{AccountId32 as AccountId32Junction, *}, - v3, - v4::{ - Error, - NetworkId::{Rococo as RococoId, Westend as WestendId}, - }, -}; +#[cfg(test)] +mod imports { + // Substrate + pub use frame_support::{assert_err, assert_ok, pallet_prelude::DispatchResult}; + pub use sp_runtime::DispatchError; -// Bridges -pub use bp_messages::LaneId; + // Polkadot + pub use xcm::{ + latest::ParentThen, + prelude::{AccountId32 as AccountId32Junction, *}, + v3, + v4::NetworkId::Rococo as RococoId, + }; -// Cumulus -pub use emulated_integration_tests_common::{ - accounts::ALICE, - impls::Inspect, - test_parachain_is_trusted_teleporter, - xcm_emulator::{ - assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, - RelayChain as Relay, Test, TestArgs, TestContext, TestExt, - }, - xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, - PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, -}; -pub use parachains_common::{AccountId, Balance}; -pub use rococo_westend_system_emulated_network::{ - asset_hub_rococo_emulated_chain::{ - genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, - }, - asset_hub_westend_emulated_chain::{ - genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, - }, - bridge_hub_westend_emulated_chain::{ - genesis::ED as BRIDGE_HUB_WESTEND_ED, BridgeHubWestendParaPallet as BridgeHubWestendPallet, - }, - westend_emulated_chain::WestendRelayPallet as WestendPallet, - AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver, - AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend, - AssetHubWestendParaReceiver as AssetHubWestendReceiver, - AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo, - BridgeHubWestendPara as BridgeHubWestend, BridgeHubWestendParaSender as BridgeHubWestendSender, - WestendRelay as Westend, -}; + // Cumulus + pub use emulated_integration_tests_common::{ + accounts::ALICE, + impls::Inspect, + test_parachain_is_trusted_teleporter, + xcm_emulator::{ + assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, TestExt, + }, + }; + pub use parachains_common::AccountId; + pub use rococo_westend_system_emulated_network::{ + asset_hub_rococo_emulated_chain::{ + genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet, + }, + asset_hub_westend_emulated_chain::{ + genesis::ED as ASSET_HUB_WESTEND_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, + }, + bridge_hub_westend_emulated_chain::{ + genesis::ED as BRIDGE_HUB_WESTEND_ED, + BridgeHubWestendParaPallet as BridgeHubWestendPallet, + }, + westend_emulated_chain::WestendRelayPallet as WestendPallet, + AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver, + AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend, + AssetHubWestendParaReceiver as AssetHubWestendReceiver, + AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubRococoPara as BridgeHubRococo, + BridgeHubWestendPara as BridgeHubWestend, + BridgeHubWestendParaSender as BridgeHubWestendSender, WestendRelay as Westend, + }; -pub const ASSET_ID: u32 = 1; -pub const ASSET_MIN_BALANCE: u128 = 1000; -pub const ASSETS_PALLET_ID: u8 = 50; + pub const ASSET_MIN_BALANCE: u128 = 1000; +} #[cfg(test)] mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs index 3074435e8e4..b781d6e987c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; mod asset_transfers; mod send_xcm; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/teleport.rs index edffaf16596..c960233c08b 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/teleport.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::tests::*; use bridge_hub_westend_runtime::xcm_config::XcmConfig; #[test] diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/lib.rs index 6f2f1409135..38ff08b486d 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/lib.rs @@ -13,52 +13,41 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use codec::Encode; +#[cfg(test)] +mod imports { + pub use codec::Encode; -// Substrate -pub use frame_support::{ - assert_err, assert_ok, - pallet_prelude::Weight, - sp_runtime::{AccountId32, DispatchError, DispatchResult}, - traits::fungibles::Inspect, -}; + // Substrate + pub use frame_support::{ + assert_ok, + pallet_prelude::Weight, + sp_runtime::{AccountId32, DispatchResult}, + traits::fungibles::Inspect, + }; -// Polkadot -pub use xcm::{ - prelude::{AccountId32 as AccountId32Junction, *}, - v3::{Error, NetworkId::Rococo as RococoId}, -}; + // Polkadot + pub use xcm::prelude::*; -// Cumulus -pub use asset_test_utils::xcm_helpers; -pub use emulated_integration_tests_common::{ - test_parachain_is_trusted_teleporter, - xcm_emulator::{ - assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, - RelayChain as Relay, Test, TestArgs, TestContext, TestExt, - }, - xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, - PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, -}; -pub use parachains_common::{AccountId, Balance}; -pub use rococo_system_emulated_network::{ - people_rococo_emulated_chain::{ - genesis::ED as PEOPLE_ROCOCO_ED, PeopleRococoParaPallet as PeopleRococoPallet, - }, - rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet}, - PenpalAPara as PenpalA, PeopleRococoPara as PeopleRococo, - PeopleRococoParaReceiver as PeopleRococoReceiver, PeopleRococoParaSender as PeopleRococoSender, - RococoRelay as Rococo, RococoRelayReceiver as RococoReceiver, - RococoRelaySender as RococoSender, -}; + // Cumulus + pub use asset_test_utils::xcm_helpers; + pub use emulated_integration_tests_common::xcm_emulator::{ + assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs, + TestContext, TestExt, + }; + pub use parachains_common::Balance; + pub use rococo_system_emulated_network::{ + people_rococo_emulated_chain::{ + genesis::ED as PEOPLE_ROCOCO_ED, PeopleRococoParaPallet as PeopleRococoPallet, + }, + rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet}, + PeopleRococoPara as PeopleRococo, PeopleRococoParaReceiver as PeopleRococoReceiver, + PeopleRococoParaSender as PeopleRococoSender, RococoRelay as Rococo, + RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender, + }; -// pub const ASSET_ID: u32 = 1; -// pub const ASSET_MIN_BALANCE: u128 = 1000; -pub type RelayToSystemParaTest = Test; -pub type RelayToParaTest = Test; -pub type SystemParaToRelayTest = Test; -pub type SystemParaToParaTest = Test; -pub type ParaToSystemParaTest = Test; + pub type RelayToSystemParaTest = Test; + pub type SystemParaToRelayTest = Test; +} #[cfg(test)] mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/reap_identity.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/reap_identity.rs index 87adb363e02..3f1f8638d6f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/reap_identity.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/reap_identity.rs @@ -38,7 +38,7 @@ //! - The freed deposit from the Relay Chain is sufficient for the parachain deposit; and //! - The account will exist on the parachain. -use crate::*; +use crate::imports::*; use frame_support::BoundedVec; use pallet_balances::Event as BalancesEvent; use pallet_identity::{legacy::IdentityInfo, Data, Event as IdentityEvent}; diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/teleport.rs index 0a12277395d..3abe5c6cf66 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/teleport.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; use people_rococo_runtime::xcm_config::XcmConfig as PeopleRococoXcmConfig; use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig; diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/lib.rs index 59cec36030b..77ac7cfc78c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/lib.rs @@ -13,52 +13,40 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use codec::Encode; - -// Substrate -pub use frame_support::{ - assert_err, assert_ok, - pallet_prelude::Weight, - sp_runtime::{AccountId32, DispatchError, DispatchResult}, - traits::fungibles::Inspect, -}; +#[cfg(test)] +mod imports { + pub use codec::Encode; + // Substrate + pub use frame_support::{ + assert_ok, + pallet_prelude::Weight, + sp_runtime::{AccountId32, DispatchResult}, + traits::fungibles::Inspect, + }; -// Polkadot -pub use xcm::{ - prelude::{AccountId32 as AccountId32Junction, *}, - v3::{Error, NetworkId::Westend as WestendId}, -}; + // Polkadot + pub use xcm::prelude::*; -// Cumulus -pub use asset_test_utils::xcm_helpers; -pub use emulated_integration_tests_common::{ - test_parachain_is_trusted_teleporter, - xcm_emulator::{ - assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, - RelayChain as Relay, Test, TestArgs, TestContext, TestExt, - }, - xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, - PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, -}; -pub use parachains_common::{AccountId, Balance}; -pub use westend_system_emulated_network::{ - people_westend_emulated_chain::{ - genesis::ED as PEOPLE_WESTEND_ED, PeopleWestendParaPallet as PeopleWestendPallet, - }, - westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet}, - PenpalAPara as PenpalA, PeopleWestendPara as PeopleWestend, - PeopleWestendParaReceiver as PeopleWestendReceiver, - PeopleWestendParaSender as PeopleWestendSender, WestendRelay as Westend, - WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender, -}; + // Cumulus + pub use asset_test_utils::xcm_helpers; + pub use emulated_integration_tests_common::xcm_emulator::{ + assert_expected_events, bx, Chain, Parachain as Para, RelayChain as Relay, Test, TestArgs, + TestContext, TestExt, + }; + pub use parachains_common::Balance; + pub use westend_system_emulated_network::{ + people_westend_emulated_chain::{ + genesis::ED as PEOPLE_WESTEND_ED, PeopleWestendParaPallet as PeopleWestendPallet, + }, + westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet}, + PeopleWestendPara as PeopleWestend, PeopleWestendParaReceiver as PeopleWestendReceiver, + PeopleWestendParaSender as PeopleWestendSender, WestendRelay as Westend, + WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender, + }; -// pub const ASSET_ID: u32 = 1; -// pub const ASSET_MIN_BALANCE: u128 = 1000; -pub type RelayToSystemParaTest = Test; -pub type RelayToParaTest = Test; -pub type SystemParaToRelayTest = Test; -pub type SystemParaToParaTest = Test; -pub type ParaToSystemParaTest = Test; + pub type RelayToSystemParaTest = Test; + pub type SystemParaToRelayTest = Test; +} #[cfg(test)] mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/reap_identity.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/reap_identity.rs index 8d63c8ceff6..3ed8592918d 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/reap_identity.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/reap_identity.rs @@ -38,7 +38,7 @@ //! - The freed deposit from the Relay Chain is sufficient for the parachain deposit; and //! - The account will exist on the parachain. -use crate::*; +use crate::imports::*; use frame_support::BoundedVec; use pallet_balances::Event as BalancesEvent; use pallet_identity::{legacy::IdentityInfo, Data, Event as IdentityEvent}; diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/teleport.rs index 345663be99b..eef35a99a83 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/teleport.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::*; +use crate::imports::*; use people_westend_runtime::xcm_config::XcmConfig as PeopleWestendXcmConfig; use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs index 38c118dbb4b..5fa7455ad2a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs @@ -527,12 +527,12 @@ fn test_foreign_asset_xcm_take_first_trader() { let bought = Weight::from_parts(4_000_000_000u64, 0); // Lets calculate amount needed - let asset_amount_needed = - ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles( + let asset_amount_needed + = ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles( foreign_location, - bought, + bought ) - .expect("failed to compute"); + .expect("failed to compute"); // Lets pay with: asset_amount_needed + asset_amount_extra let asset_amount_extra = 100_u128; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index aa8c3cf2f14..3ba9b9587d8 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -527,12 +527,8 @@ fn test_foreign_asset_xcm_take_first_trader() { let bought = Weight::from_parts(4_000_000_000u64, 0); // Lets calculate amount needed - let asset_amount_needed = - ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles( - foreign_location, - bought, - ) - .expect("failed to compute"); + let asset_amount_needed = ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(foreign_location, bought) + .expect("failed to compute"); // Lets pay with: asset_amount_needed + asset_amount_extra let asset_amount_extra = 100_u128; diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 0030287edb3..bea78e14520 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -53,7 +53,10 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, EnsureSigned, }; -use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; +use parachains_common::{ + impls::{AssetsToBlockAuthor, NonZeroIssuance}, + message_queue::{NarrowOriginToSibling, ParaIdToSibling}, +}; use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; use smallvec::smallvec; use sp_api::impl_runtime_apis; @@ -70,7 +73,7 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use xcm_config::{AssetsToBlockAuthor, XcmOriginToTransactDispatchOrigin}; +use xcm_config::XcmOriginToTransactDispatchOrigin; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -618,7 +621,7 @@ impl pallet_asset_tx_payment::Config for Runtime { ConvertInto, pallet_assets::Instance1, >, - AssetsToBlockAuthor, + AssetsToBlockAuthor, >; } diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index 84b8fd9bb0a..bc1aa05a617 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -23,41 +23,39 @@ //! `ReserveAssetTransferDeposited` message but that will but the intension will be to support this //! soon. use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, - ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, - RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Authorship, Balance, + Balances, ForeignAssets, ForeignAssetsInstance, NonZeroIssuance, ParachainInfo, + ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, + XcmpQueue, }; use core::marker::PhantomData; use frame_support::{ parameter_types, - traits::{ - fungibles::{self, Balanced, Credit}, - ConstU32, Contains, ContainsPair, Everything, Get, Nothing, - }, + traits::{ConstU32, Contains, ContainsPair, Everything, EverythingBut, Get, Nothing}, weights::Weight, }; use frame_system::EnsureRoot; -use pallet_asset_tx_payment::HandleCredit; -use pallet_assets::Instance1; use pallet_xcm::XcmPassthrough; +use parachains_common::xcm_config::AssetFeeAsExistentialDepositMultiplier; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; -use sp_runtime::traits::Zero; +use sp_runtime::traits::ConvertInto; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, - AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, - ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, - FungibleAdapter, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, NoChecking, - ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, StartsWith, TakeWeightCredit, TrailingSetTopicAsId, - UsingComponents, WithComputedOrigin, WithUniqueTopic, + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, EnsureXcmOrigin, + FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, IsConcrete, + LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, StartsWith, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::{traits::JustTry, XcmExecutor}; parameter_types! { pub const RelayLocation: Location = Location::parent(); + // Local native currency which is stored in `pallet_balances`` + pub const PenpalNativeCurrency: Location = Location::here(); pub const RelayNetwork: Option = None; pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorLocation = [Parachain(ParachainInfo::parachain_id().into())].into(); @@ -80,7 +78,7 @@ pub type CurrencyTransactor = FungibleAdapter< // Use this currency: Balances, // Use this currency when it is a fungible asset matching the given location or name: - IsConcrete, + 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): @@ -123,9 +121,16 @@ pub type FungiblesTransactor = FungiblesAdapter< CheckingAccount, >; -/// `AssetId/Balance` converter for `TrustBackedAssets` -pub type ForeignAssetsConvertedConcreteId = - assets_common::ForeignAssetsConvertedConcreteId, Balance>; +pub type ForeignAssetsConvertedConcreteId = assets_common::LocationConvertedConcreteId< + EverythingBut<( + // Here we rely on fact that something like this works: + // assert!(Location::new(1, + // [Parachain(100)]).starts_with(&Location::parent())); + // assert!([Parachain(100)].into().starts_with(&Here)); + StartsWith, + )>, + Balance, +>; /// Means for transacting foreign assets from different global consensus. pub type ForeignFungiblesTransactor = FungiblesAdapter< @@ -175,6 +180,7 @@ parameter_types! { pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; + pub XcmAssetFeesReceiver: Option = Authorship::author(); } pub struct ParentOrParentsExecutivePlurality; @@ -184,13 +190,6 @@ impl Contains for ParentOrParentsExecutivePlurality { } } -pub struct CommonGoodAssetsParachain; -impl Contains for CommonGoodAssetsParachain { - fn contains(location: &Location) -> bool { - matches!(location.unpack(), (1, [Parachain(1000)])) - } -} - pub type Barrier = TrailingSetTopicAsId<( TakeWeightCredit, // Expected responses are OK. @@ -201,12 +200,6 @@ pub type Barrier = TrailingSetTopicAsId<( // If the message is one that immediately attempts to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, - // System Assets parachain, parent and its exec plurality get free - // execution - AllowExplicitUnpaidExecutionFrom<( - CommonGoodAssetsParachain, - ParentOrParentsExecutivePlurality, - )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -246,53 +239,30 @@ impl> ContainsPair for NativeAssetFrom { } } -/// Allow checking in assets that have issuance > 0. -pub struct NonZeroIssuance(PhantomData<(AccountId, Assets)>); -impl Contains<>::AssetId> - for NonZeroIssuance -where - Assets: fungibles::Inspect, -{ - fn contains(id: &>::AssetId) -> bool { - !Assets::total_issuance(id.clone()).is_zero() - } -} - -/// A `HandleCredit` implementation that naively transfers the fees to the block author. -/// Will drop and burn the assets in case the transfer fails. -pub struct AssetsToBlockAuthor(PhantomData); -impl HandleCredit, pallet_assets::Pallet> for AssetsToBlockAuthor -where - R: pallet_authorship::Config + pallet_assets::Config, - AccountIdOf: From + Into, -{ - fn handle_credit(credit: Credit, pallet_assets::Pallet>) { - if let Some(author) = pallet_authorship::Pallet::::author() { - // In case of error: Will drop the result triggering the `OnDrop` of the imbalance. - let _ = pallet_assets::Pallet::::resolve(&author, credit); - } - } -} - +// This asset can be added to AH as Asset and reserved transfer between Penpal and AH +pub const RESERVABLE_ASSET_ID: u32 = 1; // This asset can be added to AH as ForeignAsset and teleported between Penpal and AH pub const TELEPORTABLE_ASSET_ID: u32 = 2; + +pub const ASSETS_PALLET_ID: u8 = 50; +pub const ASSET_HUB_ID: u32 = 1000; + parameter_types! { /// The location that this chain recognizes as the Relay network's Asset Hub. - pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(1000)]); - // ALWAYS ensure that the index in PalletInstance stays up-to-date with + pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]); // the Relay Chain's Asset Hub's Assets pallet index pub SystemAssetHubAssetsPalletLocation: Location = - Location::new(1, [Parachain(1000), PalletInstance(50)]); + Location::new(1, [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID)]); pub AssetsPalletLocation: Location = - Location::new(0, [PalletInstance(50)]); + Location::new(0, [PalletInstance(ASSETS_PALLET_ID)]); pub CheckingAccount: AccountId = PolkadotXcm::check_account(); pub LocalTeleportableToAssetHub: Location = Location::new( 0, - [PalletInstance(50), GeneralIndex(TELEPORTABLE_ASSET_ID.into())] + [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(TELEPORTABLE_ASSET_ID.into())] ); - pub LocalTeleportableToAssetHubV3: xcm::v3::Location = xcm::v3::Location::new( - 0, - [xcm::v3::Junction::PalletInstance(50), xcm::v3::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into())] + pub LocalReservableFromAssetHub: Location = Location::new( + 1, + [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID), GeneralIndex(RESERVABLE_ASSET_ID.into())] ); /// The Penpal runtime is utilized for testing with various environment setups. @@ -337,8 +307,22 @@ impl xcm_executor::Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = - UsingComponents>; + type Trader = ( + UsingComponents>, + // This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated + // `pallet_assets` instance - `ForeignAssets`. + cumulus_primitives_utility::TakeFirstAssetTrader< + AccountId, + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, + ForeignAssetsConvertedConcreteId, + ForeignAssets, + cumulus_primitives_utility::XcmFeesTo32ByteAccount< + ForeignFungiblesTransactor, + AccountId, + XcmAssetFeesReceiver, + >, + >, + ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; type AssetClaims = PolkadotXcm; @@ -356,6 +340,15 @@ impl xcm_executor::Config for XcmConfig { type TransactionalProcessor = FrameTransactionalProcessor; } +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. +pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger = + AssetFeeAsExistentialDepositMultiplier< + Runtime, + WeightToFee, + pallet_assets::BalanceToAssetBalance, + ForeignAssetsInstance, + >; + /// No local origins on this chain are allowed to dispatch XCM sends/executions. pub type LocalOriginToLocation = SignedToAccountId32; -- GitLab From 3c6ebd9e9bfda58f199cba6ec3023e0d12d6b506 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 14 Mar 2024 11:44:55 +0100 Subject: [PATCH 122/188] fix(paseo-spec): New Paseo Bootnodes (#3674) This change includes new bootnodes for Paseo. _This is meant to be a silent PR_ --- polkadot/node/service/chain-specs/paseo.json | 287 ++++++++++++++++--- 1 file changed, 240 insertions(+), 47 deletions(-) diff --git a/polkadot/node/service/chain-specs/paseo.json b/polkadot/node/service/chain-specs/paseo.json index 8db75ff137b..2e659716766 100644 --- a/polkadot/node/service/chain-specs/paseo.json +++ b/polkadot/node/service/chain-specs/paseo.json @@ -5,23 +5,20 @@ "bootNodes": [ "/dns/paseo.bootnode.amforc.com/tcp/30333/wss/p2p/12D3KooWFD81HC9memUwuGMLvhDDEfmXjn6jC4n7zyNs3vToXapS", "/dns/paseo.bootnode.amforc.com/tcp/30344/p2p/12D3KooWFD81HC9memUwuGMLvhDDEfmXjn6jC4n7zyNs3vToXapS", - "/dns/paseo-bootnode.radiumblock.com/tcp/30333/p2p/12D3KooWADeayZC8zag4Qrb4GosSn65MmfVZztRPMaBdgZnQqXRo", - "/dns/paseo-bootnode.radiumblock.com/tcp/30335/wss/p2p/12D3KooWADeayZC8zag4Qrb4GosSn65MmfVZztRPMaBdgZnQqXRo", - "/dns/boot.gatotech.network/tcp/33400/p2p/12D3KooWEvz5Ygv3MhCUNTVQbUTVhzhvf4KKcNoe5M5YbVLPBeeW", - "/dns/boot.gatotech.network/tcp/35400/wss/p2p/12D3KooWEvz5Ygv3MhCUNTVQbUTVhzhvf4KKcNoe5M5YbVLPBeeW", + "/dns/boot.stake.plus/tcp/43334/wss/p2p/12D3KooWNhgAC3hjZHxaT52EpPFZohkCL1AHFAijqcN8xB9Rwud2", + "/dns/boot.stake.plus/tcp/43333/p2p/12D3KooWNhgAC3hjZHxaT52EpPFZohkCL1AHFAijqcN8xB9Rwud2", + "/dns/boot.metaspan.io/tcp/36017/wss/p2p/12D3KooWSW6nDfM3SS8rUtjMyjdszivK31bu4a1sRngGa2hFETz7", + "/dns/boot.metaspan.io/tcp/36018/p2p/12D3KooWSW6nDfM3SS8rUtjMyjdszivK31bu4a1sRngGa2hFETz7", + "/dns/paseo.bootnodes.polkadotters.com/tcp/30538/p2p/12D3KooWPbbFy4TefEGTRF5eTYhq8LEzc4VAHdNUVCbY4nAnhqPP", + "/dns/paseo.bootnodes.polkadotters.com/tcp/30540/wss/p2p/12D3KooWPbbFy4TefEGTRF5eTYhq8LEzc4VAHdNUVCbY4nAnhqPP", "/dns/boot-node.helikon.io/tcp/10020/p2p/12D3KooWBetfzZpf6tGihKrqCo5z854Ub4ZNAUUTRT6eYHNh7FYi", "/dns/boot-node.helikon.io/tcp/10022/wss/p2p/12D3KooWBetfzZpf6tGihKrqCo5z854Ub4ZNAUUTRT6eYHNh7FYi", - "/dns/pso16.rotko.net/tcp/33246/p2p/12D3KooWRH8eBMhw8c7bucy6pJfy94q4dKpLkF3pmeGohHmemdRu", - "/dns/pso16.rotko.net/tcp/35246/wss/p2p/12D3KooWRH8eBMhw8c7bucy6pJfy94q4dKpLkF3pmeGohHmemdRu", - "/dns/paseo.bootnodes.polkadotters.com/tcp/30538/p2p/12D3KooWPbbFy4TefEGTRF5eTYhq8LEzc4VAHdNUVCbY4nAnhqPP", - "/dns/paseo.bootnodes.polkadotters.com/tcp/30540/wss/p2p/12D3KooWPbbFy4TefEGTRF5eTYhq8LEzc4VAHdNUVCbY4nAnhqPP" - ], - "telemetryEndpoints": [ - [ - "wss://telemetry.polkadot.io/submit/", - 0 - ] + "/dns/boot.gatotech.network/tcp/33400/p2p/12D3KooWEvz5Ygv3MhCUNTVQbUTVhzhvf4KKcNoe5M5YbVLPBeeW", + "/dns/boot.gatotech.network/tcp/35400/wss/p2p/12D3KooWEvz5Ygv3MhCUNTVQbUTVhzhvf4KKcNoe5M5YbVLPBeeW", + "/dns/paseo-bootnode.turboflakes.io/tcp/30630/p2p/12D3KooWMjCN2CrnN71hAdehn6M2iYKeGdGbZ1A3SKhf4hxrgG9e", + "/dns/paseo-bootnode.turboflakes.io/tcp/30730/wss/p2p/12D3KooWMjCN2CrnN71hAdehn6M2iYKeGdGbZ1A3SKhf4hxrgG9e" ], + "telemetryEndpoints": null, "protocolId": "pas", "properties": { "ss58Format": 42, @@ -36,6 +33,12 @@ "0x06de3d8a54d27e44a9d5ce189618f22d4e7b9012096b41c4eb3aaf947f6ea429": "0x0900", "0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385": "0x0000300000800000080000000000100000c8000005000000050000000200000002000000000000000000000000005000000010000400000000000000000000000000000000000000000000000000000000000000000000000800000000200000040000000000100000b004000000000000000000001027000080b2e60e80c3c9018096980000000000000000000000000005000000140000000400000001000000000006000000640000000200000019000000000000000200000002000000020000000500000002000000", "0x074b65e262fcd5bd9c785caf7f42e00a4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x08c41974a97dbf15cfbec28365bea2da4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x08c41974a97dbf15cfbec28365bea2da5e0621c4869aa60c02be9adcc98a0d1d": "0x380325fc2095902f5fe394f244bce38b0dc3d631cbc05f0b64d5620a71bbf2514f0f03f045328f504c13dac9ddd9b1186098aee7c46cb8d55289dbbf2433bab7a2623903a0af06322d100056125fac1df39d161089b07ae279505aae8731c4d110a54ad703aec8e80ea0375f8669d6e55d7abb6a3117678d7bb851a1bd100a01e52a4fed9003d46c454f9b620603feef8c3a2a5d7098205b8566500fda0fa0b456d6ded54538030e901c390fa37d101ff25d70594acd2df67b4493ee77a73684f25d39313536d702f4f4d0eccb899bf2d611b56e0afec7c740efba404f8d0e82a545f988c45316c402182879ec92e811e2a8cc117f3cde1f61d3cba0093134cfb1ed17a4ef74915d4a03e843f200e30bc5b951c73a96d968db1c0cd05e357d910fce159fc59c40e9d6e20203d51bba2124f480e3507eb1764fc3019ac7abae8ee215683a285078bda7f51d029338ece1c6bc6439dc4d16bfe33f28c9f0af31626bb8142849742b7a624f68070333022898140662dfea847e3cbfe5e989845ac6766e83472f8b0c650d85e77bae03586dafcdab3d4647d4dc68732a9cab8aa34c00c5edd04e65d9dd44c2a1fd21e2029a1eb2e31dcaf468dbb516f9b620fdd7c3f090d58a88e02b51b25255b2182dd1", + "0x08c41974a97dbf15cfbec28365bea2da8f05bccc2f70ec66a32999c5761156be": "0x0000000000000000", + "0x08c41974a97dbf15cfbec28365bea2daaacf00b9b41fda7a9268821c2a2b3e4c": "0x380325fc2095902f5fe394f244bce38b0dc3d631cbc05f0b64d5620a71bbf2514f0f03f045328f504c13dac9ddd9b1186098aee7c46cb8d55289dbbf2433bab7a2623903a0af06322d100056125fac1df39d161089b07ae279505aae8731c4d110a54ad703aec8e80ea0375f8669d6e55d7abb6a3117678d7bb851a1bd100a01e52a4fed9003d46c454f9b620603feef8c3a2a5d7098205b8566500fda0fa0b456d6ded54538030e901c390fa37d101ff25d70594acd2df67b4493ee77a73684f25d39313536d702f4f4d0eccb899bf2d611b56e0afec7c740efba404f8d0e82a545f988c45316c402182879ec92e811e2a8cc117f3cde1f61d3cba0093134cfb1ed17a4ef74915d4a03e843f200e30bc5b951c73a96d968db1c0cd05e357d910fce159fc59c40e9d6e20203d51bba2124f480e3507eb1764fc3019ac7abae8ee215683a285078bda7f51d029338ece1c6bc6439dc4d16bfe33f28c9f0af31626bb8142849742b7a624f68070333022898140662dfea847e3cbfe5e989845ac6766e83472f8b0c650d85e77bae03586dafcdab3d4647d4dc68732a9cab8aa34c00c5edd04e65d9dd44c2a1fd21e2029a1eb2e31dcaf468dbb516f9b620fdd7c3f090d58a88e02b51b25255b2182dd1", + "0x08c41974a97dbf15cfbec28365bea2dac713b7f8b14e2815d297585d3581e774": "0x0101000000", + "0x08c41974a97dbf15cfbec28365bea2dad47cb8f5328af743ddfb361e7180e7fcbb1bdbcacd6ac9340000000000000000": "0x00000000", "0x0f6738a0ee80c8e74cd2c7417c1e25564e7b9012096b41c4eb3aaf947f6ea429": "0x0100", "0x1405f2411d0af5a7ff397e7c9dc68d194e7b9012096b41c4eb3aaf947f6ea429": "0x0100", "0x1405f2411d0af5a7ff397e7c9dc68d196323ae84c43568be0d1394d5d0d522c4": "0x03000000", @@ -43,45 +46,59 @@ "0x196e027349017067f9eb56e2c4d9ded54e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x1a736d37504c2e3fb73dad160c55b2914e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x1cb6f36e027abb2091cfb5110ab5087f4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d": "0x10b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a65010000000000000058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe3233020100000000000000facb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe4440000100000000000000ae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e2455330100000000000000", + "0x1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d": "0x38b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a6501000000000000005440add43e5388a81aef665c9086d386c0be0ce75e4f8a4a3d8168e976ea821f010000000000000074dacbca0cdb5099afef67e622c147614198e669931cebc605629da332632473010000000000000058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe323302010000000000000050412bd7d3f1075e8f8e3b682d05ea20b391c287d8c849a0e49a78f568553e690100000000000000c44b3e8efe854419ccd5801a82ada22d39cfccdbcece382304cdfeac81ebe4020100000000000000b2efe7e70daf44b3466c63ccbf4487f42c6a9f6fbb7050b849691e36ce92e3470100000000000000facb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe444000010000000000000068a9ec74fa35b3425eaf503dd36294ba8e758e7b8084c4d6bfd547f8c6b5827401000000000000007c8348ec95a0faad6a638ef74864761028c53221bde07e9ff7c81a3f427abf3f0100000000000000ae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e245533010000000000000018bd0f67d77f04f1a92400421813d8927fad109b40a8689254a5f0c8b346857c01000000000000006248d87bd2a640ffe26d6b831735887c24e2076a3a0f3a74f7ae7568c276040801000000000000001ab03b1b3277edfedd24ef3d3359b449b64bd95ed82a04e7f9fbaab7b71dc0150100000000000000", "0x1cb6f36e027abb2091cfb5110ab5087f66e8f035c8adbe7f1547b43c51e6f8a4": "0x00000000", - "0x1cb6f36e027abb2091cfb5110ab5087faacf00b9b41fda7a9268821c2a2b3e4c": "0x10b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a65010000000000000058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe3233020100000000000000facb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe4440000100000000000000ae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e2455330100000000000000", + "0x1cb6f36e027abb2091cfb5110ab5087faacf00b9b41fda7a9268821c2a2b3e4c": "0x38b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a6501000000000000005440add43e5388a81aef665c9086d386c0be0ce75e4f8a4a3d8168e976ea821f010000000000000074dacbca0cdb5099afef67e622c147614198e669931cebc605629da332632473010000000000000058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe323302010000000000000050412bd7d3f1075e8f8e3b682d05ea20b391c287d8c849a0e49a78f568553e690100000000000000c44b3e8efe854419ccd5801a82ada22d39cfccdbcece382304cdfeac81ebe4020100000000000000b2efe7e70daf44b3466c63ccbf4487f42c6a9f6fbb7050b849691e36ce92e3470100000000000000facb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe444000010000000000000068a9ec74fa35b3425eaf503dd36294ba8e758e7b8084c4d6bfd547f8c6b5827401000000000000007c8348ec95a0faad6a638ef74864761028c53221bde07e9ff7c81a3f427abf3f0100000000000000ae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e245533010000000000000018bd0f67d77f04f1a92400421813d8927fad109b40a8689254a5f0c8b346857c01000000000000006248d87bd2a640ffe26d6b831735887c24e2076a3a0f3a74f7ae7568c276040801000000000000001ab03b1b3277edfedd24ef3d3359b449b64bd95ed82a04e7f9fbaab7b71dc0150100000000000000", "0x1cb6f36e027abb2091cfb5110ab5087fdc6b171b77304263c292cc3ea5ed31ef": "0x0100000000000000040000000000000002", - "0x2099d7f109d6e535fb000bba623fd4404c014e6bf8b8c2c011e7290b85696bb3": "0x10f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e876892cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a54326e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e", + "0x2099d7f109d6e535fb000bba623fd4404c014e6bf8b8c2c011e7290b85696bb3": "0x38f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e8768cce3ec06252cf7cdad47fe1265047a9bbddb9059ee4bdc6dec83b67249b4a9342ada042fb4bbfd9b6d8c48293ffc4a7722632c843a67e608554c41d06aabc41392cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a5438c15606f4c121376097ff0e96c2a33ea7b024d812b42fe2c741c8b8cee17e63d729053f28155071474b4686323db5f7a318cb3f088b76660cc8ff5e3e11ec32eaa3955187f755708cd6a8104314b962ff5043e36efa3ec5d84df40c58b44222126e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e64ffc83f4f86cc595e607a00b977eeb6641e02a4e6e556c24ab163aecd7d146c7aeb767131602e6612e607a9eb8e26b4ce4fa4765593d032bc923ce8acadda42763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e629f9fd0dd7279c7af7470472d1208a13e33239b484974d47cffce4ad4785644047277f22b9ef92a8b99618f4c86c2412f0e3b08a4f965f842775672043d1e259a86227e204a2d003399c2a3b50c2c869c4380c195a014a02f6d2e7048941237", "0x2099d7f109d6e535fb000bba623fd4404e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x2099d7f109d6e535fb000bba623fd4409f99a2ce711f3a31b2fc05604c93f179": "0x10f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e876892cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a54326e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e", - "0x26aa394eea5630e07c48ae0c9558cef734abf5cb34d6244378cddbf18e849d96": "0x00000000070d8aa99f1452f92000", + "0x2099d7f109d6e535fb000bba623fd4409f99a2ce711f3a31b2fc05604c93f179": "0x38f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e8768cce3ec06252cf7cdad47fe1265047a9bbddb9059ee4bdc6dec83b67249b4a9342ada042fb4bbfd9b6d8c48293ffc4a7722632c843a67e608554c41d06aabc41392cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a5438c15606f4c121376097ff0e96c2a33ea7b024d812b42fe2c741c8b8cee17e63d729053f28155071474b4686323db5f7a318cb3f088b76660cc8ff5e3e11ec32eaa3955187f755708cd6a8104314b962ff5043e36efa3ec5d84df40c58b44222126e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e64ffc83f4f86cc595e607a00b977eeb6641e02a4e6e556c24ab163aecd7d146c7aeb767131602e6612e607a9eb8e26b4ce4fa4765593d032bc923ce8acadda42763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e629f9fd0dd7279c7af7470472d1208a13e33239b484974d47cffce4ad4785644047277f22b9ef92a8b99618f4c86c2412f0e3b08a4f965f842775672043d1e259a86227e204a2d003399c2a3b50c2c869c4380c195a014a02f6d2e7048941237", + "0x26aa394eea5630e07c48ae0c9558cef734abf5cb34d6244378cddbf18e849d96": "0x0000000007def964eb114a412100", "0x26aa394eea5630e07c48ae0c9558cef74e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x26aa394eea5630e07c48ae0c9558cef75684a022a34dd8bfa2baaf44f172b710": "0x01", "0x26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc": "0x4545454545454545454545454545454545454545454545454545454545454545", "0x26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c118746b4def25cfda6ef3a00000000": "0x4545454545454545454545454545454545454545454545454545454545454545", "0x26aa394eea5630e07c48ae0c9558cef7a7fd6c28836b9a28522dc924110cf439": "0x01", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da902d496d20c019d22397accfc42b7635d94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da90ffdb9747f7a8bfa200ea2291eea6bdf9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da911fcf3e922de10898cb04273301735e65270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da915fbc5d9b44885a2dce0fbaa3834ba211e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9279effc2672354478fb5e3f7e65726b668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da92ffe7c0dd7d3d8d8485c403a33fb7adb6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9350ea875b4c0459b3527d475e9825c99d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da94d176c4abc6d2410c43423c2714b909c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9585bd5ccc1af6cf60c19d791bb091b750efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95ecffd7b6c0f78751baa9d281e0bfa3a6d6f646c70792f74727372790000000000000000000000000000000000000000": "0x0000000000000000010000000000000000e40b54020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da965bb58c29c9825c1f6727fe8c41650ac82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da96deaa967a94fa09152be01a253511479d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9829f3f4d6d7c991993e0c044ae97410b043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9a00c6f5358fa04d76ce7cf995bce2eabe21bb02f2a82cb1113ff10693093377672925b23f047624c0cfa7a24a8609841": "0x000000000000000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9ba2db252d1b8c64ec51b04d0f50d7d2b9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9dfc40f350cc4563ad9ddff5ad92944278eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x000000000400000001000000000000000000c16ff28623000000000000000000000000000000000000000000000000000080c6a47e8d0300000000000000000000000000000000000000000000000080", "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9e6fb488a1496189393ed0a95dcf5577e7e939ef17e229e9a29210d95cb0b607e0030d54899c05f791a62d5c6f4557659": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", - "0x26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8": "0x02093d0014706173656f", + "0x26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8": "0xaa183d0014706173656f", "0x2762c81376aaa894b6f64c67e58cc6504e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x2aeddc77fe58c98d50bd37f1b90840f94e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x2b06af9719ac64d755623cda8ddd9b944e7b9012096b41c4eb3aaf947f6ea429": "0x0100", - "0x2b06af9719ac64d755623cda8ddd9b949f99a2ce711f3a31b2fc05604c93f179": "0x100edf2a41cb81178704560b02c35f5e01a5a97a568ebc10c025ade18b6ab2fa1d74bd654c470ed9b94972c1f997593fab7bdd4d6b85e3cf49401265668142584eca3c2703db1633a27eff681d979967988c3a6752c669fd41f1abde10f3b0544606bd8fd81e50cda2bd67bf6893d921d1aae5cb08409ae43e0bff4d54e1830e58", + "0x2b06af9719ac64d755623cda8ddd9b949f99a2ce711f3a31b2fc05604c93f179": "0x380edf2a41cb81178704560b02c35f5e01a5a97a568ebc10c025ade18b6ab2fa1d98aab6f52520022d011a6eba2dca1c6327edbbcd753c170dcf0e9118b5f0f25bb414aa148096a92a1831309f758f944725653363ccbaeb21817b7df5784b8d4674bd654c470ed9b94972c1f997593fab7bdd4d6b85e3cf49401265668142584e94848b8cf2cbc9e6fd72db8d80676591b5be4d1ec68972ada48cf6fd01228712a8a03d86e6c0dbe180cadfc7994121f462b28f7a8cb1be7e0e354147624be734bef47a9e4b47ed57461e1d28cac7da327a52ebcd64d74080d31deb3ac7a7645eca3c2703db1633a27eff681d979967988c3a6752c669fd41f1abde10f3b0544660fcc9d094d21fe17cfb7426501f50cb3d75c4c9395a3140e0f255443f660d3b30c40adee5476157ef3c2a26e10cab95ec7d54b62dd220738f5a474d5f86874e06bd8fd81e50cda2bd67bf6893d921d1aae5cb08409ae43e0bff4d54e1830e58d28145a7cde195a4c834276730d30f074b212a150e770931ee9470e853e7d2247c03ca47a3201455f8f89defda4aa909cb1d25dd9ddb7fd62a940606f79b56632cd12c731d91441f0114b08d314cd3f9a9f7fd0240d467fe54adefbee4d90762", + "0x2ecf93be7260df120a495bd3855c0e600c98535b82c72faf3c64974094af4643": "0x01000000000000000e00000063e7f4c4028d97f9e69689cea528e2d0155ea2b202be0a42381c642ace2e4cf4", + "0x2ecf93be7260df120a495bd3855c0e604e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x2ecf93be7260df120a495bd3855c0e60c52aa943bf0908860a3eea0fad707cdc": "0x00000000000000000e00000063e7f4c4028d97f9e69689cea528e2d0155ea2b202be0a42381c642ace2e4cf4", "0x2f85f1e1378cb2d7b83adbaf0b5869c24e7b9012096b41c4eb3aaf947f6ea429": "0x0100", - "0x2f85f1e1378cb2d7b83adbaf0b5869c298ef7dc060436e4ed803af07632b89b65153cb1f00942ff401000000": "0xcee7559d1a7431ad9a589c49d42b6e5da57d8208d290516347b21415449fbf4c04000000", - "0x2f85f1e1378cb2d7b83adbaf0b5869c298ef7dc060436e4ed803af07632b89b6b4def25cfda6ef3a00000000": "0xcee7559d1a7431ad9a589c49d42b6e5da57d8208d290516347b21415449fbf4c04000000", + "0x2f85f1e1378cb2d7b83adbaf0b5869c298ef7dc060436e4ed803af07632b89b65153cb1f00942ff401000000": "0xe68919a7ceff5bcca24e5051b9ab34b9c9f9e74a925cde4c49570cfed7bf14180e000000", + "0x2f85f1e1378cb2d7b83adbaf0b5869c298ef7dc060436e4ed803af07632b89b6b4def25cfda6ef3a00000000": "0xe68919a7ceff5bcca24e5051b9ab34b9c9f9e74a925cde4c49570cfed7bf14180e000000", "0x2f85f1e1378cb2d7b83adbaf0b5869c2ff3ae12770bea2e48d9bde7385e7a25f": "0x0000000002000000", "0x31a3a2ce3603138b8b352e8f192ca55a4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x3a636f6465": "0x52bc537646db8e0528b52ffd00580c6105dee2866016521030cf2a1d73eebb153057df9bb472cc0a860361c473d10e8f9f75d9071693fda90415453adee41bf641bf24fc4306beefa61e5e18c0cbb36d9bec46d011d098dc9c6d2bd360511bf97b6f42f6de5ba6245368194d145f153c9d801bc50970a58c7bc312c497e3b3cbd8a80c636c54ca9e9d7d081bcd672c609e1dc646fceccb479356fa3cfb8a0bd032c606ed2b7128347d00b7c8b83ea38c7bb361fdf8e5d73f36da9badccaf876c348f9656c27e07006ed2387d7d5be0b2d1dcf9ebe06bd968d9cbefd7291b4d5f0727cf02b488b141fbe05c911de470f76601596460d97e536f9fdea2925977de2c200b1896edb337097638c9f92cb2af48ab12afa8844ef100b567259e7380fb1f1b95ecedeb3c497618d9277355e2da9c4bc0e9fb53fab34ff201e3cd66fb923e3b65a375f66ffaf7f5d1f2ac1c7f7a397ef93dbbff0aa9cd3942b7cf3979b62bf1ec7676eaddddd37b32fbf75c7b98b053e7599765e292e95c4bf6e94aacc4fbd395c97f85d478ce2ec0fd29fdd9c1cd600417695c9695dfb3b7afa8a47d8a1a9860b3d9b07c3bc8e1b2d1f492fefab251fbfa8acb3276256e92b28cfd682cc7679f4e9d1d84b1d13e3b38c3918d9665ebec30369acf1e63a376f61595b42bb11253f24a9087aafdac3d4cbe9ffefdac3d4ca6539f4e6bd4fcaecbb292fefa8a4a662de74f576225de1fae4cfe2ba4d6736e01eeef4f393e3bf8b15139bd7d9d27c90ee3f4327cf6b27d59b60e36f9b16c9d689cdebebe6207d399ba7e2c5ba72c5b57627092fce1263dcddb5fe97e3abbb8494fd3f64e03f8e9ec2087bb49d3cbf665d9fac746e5fcf675b0c98f65eb4363fbfa8a1b5096ad77fd58b6aec4208793a41f6ed2d3cc7a27efafe0fc747671939ea6ed9d06f057c29fce6eb3494fd3f64e03f82bdd4f677f6dd2d3b4bdd3007e3a3bd8e124fbc54d7a9ab6771ac05fe97e3a7bb8494f13cd5f097f3abbcd263d4ddb3b0de0a7b3afd801b5d97eba124f71c968fbe9211bedb3afb864da7eba122bb1122bf192cbb2f5fde1ca34fe0aa9f1e435c06570195c24e3f4f56d21a9833fd0c20aae2431246101490a90e881040f2470202101923790c481e40e2423409207123248be404205121790d480e405243224dd92c4400203921890cc80848624169074414285644b520b48b824a5901443920992ea484241d214198c49a222e904495924e1911446d218495e248191b405922c495720d182448524aca42e92ca40b242920792be482a419215495524199184449298a41990b0904443929924aa0cd264c044064a64f04506502449914112495d3258228330327022898e0c8e48d222894c1216495c2495c9e089242d196065104712144944240991810892de487223294b0623c8c08da4393200230331322823292be90348c020b1010996a42592a2487222498e0cbc4842930482a438924490f444120990a48074061218485f20758184855406e90a242a9064404a026909241a9036808404120f483d206900290c120e483e20fd8054051219242b907440ba42ca01e906242590c0208d412a02e909a40e20058104051211483320d940d4a5888ea23a8a4a506482a2111499513444911045411475a00888220e148529faa1c887a20d14f550c44351154556149129a2a2c889a2268aa62852a3288da2334568149d51d4451117455b1469519445111645658aae28f240511145628a88a041143151b444d19822258a922842a2e88822238acc1495514446d118453814dd50344351068a5e28a2a1a8aaa84b119722ab22188a64209283680ea23a884c400407d11b4423208a830804446a88ec204201d10988c220fa82080ca232888e2082820809a214105d41f4049114445310dd88b420c261480d1116a21486483024c7501b43730c610d5d31c4c51013434a0c093164c5d00d43381c61e3481e432c0cb97024cd912b8eec71248b23681c01c191368e9c397282232138f2c611111c71636885237a1cd1e24899211586aa86b80c6519a21ad232b4e5481947d63862e6089a2363fc8b913b8ce0c16e7811302af80c2328e037a606aa1e312b8c9461640c223378822022c3c80e4379f8e0e1a30696858d169b148aa4a0481945ee2862a6089a221ff02b86ae8672e830806cd0690156850c861f2e300b48e420d246921a4e44d211b132404b00c901c80d449c00028648134498008283634164892176780d18b041240c110e10010288ed87123213f8d8414409227a08b11141027606d01940b4ec906007053c48ecdcc1c3028f179e1676460084ca070f46acd81141bfc10326280515580d3511c487236414c962e78c991b3c43f86061288a9c2c76e2086a8327892010f06c095a63c7044167621ce0e11234c69013b33678c6047921a3baa08bec043e2008a2da39418e16413610a4875816205d7cd6e460c9628871d9b12308882258fca8198262f6c60f167cf6f08165678d217a046de191418786217bc4b0c0000418a0c1400d0cceec7c609666e7cc4c04332966b71919b3286669ccceccd698a9319b022803332b6664664c245161162676c5ec87990fb30de874a958b013c84a20cb92c531244bf682cc4aa605680fa03c80f00052038402a03a804a0094054402a03880e0004a032402a03580d820aa01080d901a41ee08a207ac07d80678b400c221e601201d6262807278cde12900ed102b02e80bd00d312378b6e0e102e80a0808202284c4003484101980c408a101a80821330009212403401e000a42480d42be008501a2828f1bf58c111788b04044059e1c76e0a868f01441c4cb8f16580344b220a245055a783ac033034f161e2d414a50dd702d5504158e223b764240c4852174d430aa173b20e0a1e25921c81e3a566e457d23c8098a80112405414c00c44310140451e359bc0aa88620790081098287db7ccb8b04be826c0659065c059812b024dc05242db80c0e83bf50a4825bf938011ba248999d3d865ad89183c8871f2ffc8041e78b4e0c415408d2a582121cf1020916500f3fac2af85241063823d80b5808182b698f24362ac0c2360021118b0289890c52907303c2e293029f3b6cb010e1425b00d20050123c63141183a70b1e2f7474a8800b101a3f9a187a02e88d1c2980eef8a103e80c902c312d4026c899c28605a035b0334072bc6e365b7eec006407902d406efc946036021b1580da8099817551d7f8e4f183099819156c81810113434808848000e804b00f00d15141085e3bc0d0009aa302157456001ac18e183b5fc0d6f8b104d00772b6105205a407500a8042b003c68b8a236600e1a25326b66516c76b0a205874b0289a63c78c970f455b606e106591404c892261d4361c4b4d03a4444f0e31276250c49e804d019322c604511eb1266249502086dc51cd50332ea60787980fb10d101902c9cc10131c7161878cd80b31ab1d343c61743cc0a343ab21f24264851f46042902c606cc0e58160f0f3f74f82103112b2330f8e861c46a670e2010f0882172044f0a15500d29814e0674b87029c0c8806d3184044350e06476bcd84183c8061d1ca89620297484f0598347033fae606d0cbdf092029606ac8c5e0366056c0c2234302e605a201d11ebc1081a447e9825012443912e5e560461e20799fa058c0ae6015811303130236044c090801d01fb813f000b0303a247075810b00e04b10396c34b8e23627894b0e9b21306ec0a1d1988ec9113460e183d6062591879814815912d33387862e0d940cfd52b8ea23b869c00830c14b9721bd8082433780c03c11dd019036803f388514d9035ce05690c6f82a80c4c8e1e0d38d578c4ab8e318908bc4af0caeab9e145c75016af375e6986d431448df3e04038073c8cffe03ef80686ccb183c74e0a8e8041e405225d76d8e0b94107cc113c8edc6124061e23a612445a401222481d3c553c30341c1d87cd15938b5a066b51e48b222d3644f834e1c3c410962367bc7ae079c1cbd850f1a86093e5081642b4bc7878fda053354405c3a14386102ebc42067a50178e8c11a44383f10389203c10ed4124890a7ca86420f9c253032c052dc705b62369c04af02309202b34968f1d8e8461b3820f1d6061e86800481e485208f940520e5c065115dd848f1e92e0481a41066fbca2c8a0043c030c0d9b119265a70c215886c8bcc8c0b082b0c0d498d1f0da001d434817d81c47d604d921880e41ae74b6e8500d65402705242d8450250d61e4899d12e86881e9b193467f61e345074b911a581a1e2ba22f3a2c2435e155ecd0314443901b908080e161840c9baa991c49587e4620c44b521a19c8c15b6460068897231e602f3f70c0f2c879024855066b9a8b1c366cb6b0e9c2860b1b2f86be04a9222243640d521442561092c2d014478480ad11a202ec8e0bb2f01c21048d8e0b3c38086101884c8fa0282b033a3280e38214605ed0333a579c86c7079d1d605f004981870347be388265c3250332807020a98d234820c1218331846c81c501a48566020647121a1760493a936446100f00d162a80e98088e14c12a00a53154050c043013d02cca048d82de681afa049582be419da070d026e81440476010020cdaa078d03ba81a226390380044066ac7eccb6c06581d3b583a30f06021b282280b1d1b88b020520791087868d0f142f401d90880c000c40a880b4062a8573b667466808d0046079119a2338c98b1b366678c1d35746ed05141e7859d36783c60a4059d1a602480a9e1c9804e0e3b593a5976f480bd0143818e6dc83604c390d5900c47d43862c42bcc11318e1c01e485a12d906e455440588061c1d3a5c84bd10a394d10e901db83a707242f606580ec8081160cb660409583821c353976f8bce133021f38646a6478c8eef8f1c30f0efc0853ada865ea1545c61461a2c812332266625e59bcb6786911c48b205f04c19add007361680898158c0bacea05c64b8c571841e0f871c58f323f6ef891c30f1c8a1051a488226288a041240d22678cc061240e2323a8515429ea4d670f1f369d354134047d09cac08d0c3734dccc60b3e685e565cb39d37be4a4a12387ce1c3a24c8d123674dce1e152451c1980a94a82c54176a0bb3aa990ab32e168cc002392c88a382ab0a76a840070bd4e01258b00699d52120e968326ccab031c3c6cc0f296ceab039818d0980d001c404404a504110231863183e6af0a1011f365430f586aa811baa1b2e375b76f2e0b1edd4c1e302cfd58e1b3b6a786ce0f9c243c44e9a9d37787ee0118267071e20883a7024054331f416445bd01b280e3487a435b48a72e93c908618ba63a8049da6dd681310ad4004a6c7683188f020baa39de824faaa8968311da677e80eb412cd43ebd041b407fa4b83691c7a8846a26fe81fda87d64017d1363410cd81eea18fe81a7a4ce7d01b68235a88211410adc174701ccc06b7c122603518048c86d7e010b01943763019ae6286e129580abe71147c048be130ec0373006907fe8193183a016f807be01a9806fe326402de81abb80bf3403b8054c6cc626a31b7984ccc25a6969965a630b14c9b950640e083f9030833070750214184a50a78b00005342140070940c0010cc0c1061a28a14d27e6182345478c844600d500e7effca1438b7b090a4a059c5881b224c5891370760854969c38710505ed7421b4c345531394284d4d5008b08594a811a82c3569b14b4b2238a912e5244aca0853962c30dbc962a19aa640895a0ac1c9d2920817ec60b15544a032c5c9094f4b2538399962e5a3a82c9170029426be536697a250a942c509942854aa2420ca03d9b922842a51964208b263c5429db0c40475c2121306903b55404d29c0094fee9029daa1e267678a3561890ace8e147b5b2951aa5859ead989629f4a18618a0854aa447132c5ca2f55000a4d67078a0b769e40da71624398e2246a09eaa984283b3b4d2cd4d294a8294f55a4449500c5c9084ea65879285642a002e569830a76985828a8a526203b4be4ec8c5162a3a89450258a1311a02c35e9ec24b14f24904002025e3b4858b073c486b04465842950544a7012a5ca952925382d19ed18b1514b504e3cb05053a04e106169a9024ea658f91344585aa2f9d82962a3a0aa343979aa6265e949cc8a50a5ca93152756a648817a5aa262812a4e4e586222778858a8252950509aa09c84b034a5c98a1528544a08b233c4422d459560056a4a083e768458295050a4d49d2076e9c98a93a5a72925382d3d398112e18a15213b1dd8282a4b242c4541898212e18a15d90e100bb51455e58a132754aaf8ec70604fa8809330504d4b54a8409112c58915129ea43809814a09552a4065ca0f5154aa4471e24442083e2c1409509ea05871f25465035b45049e9d1e162a8acad295251e76290a4a085342a00225ca909d1d7629842a5180ece8b04f5544805a82ba5aa8a812ac44955005682707124a80828262c10e0e0b250a4a084ea8549912c25214d414a8a7252b17ecdcb0504b4f55a23839216a4ad3940a40699a02e50a14df01b350564aa8f23482930a7634b0504f55a2a0aa7000e5094a93d88e0d6b812956fe6989e9a98a033a20776ad8a5a512964a508007212c8d3002140f00b0f365a1445529c1c90914152753acfc0854a63041896280cf4e06b64a94131a76290a15284d502ae0a44a9413a8282a53aafcecccb050213c41b1c0d2939311a84c0981ca92152753ac3c5453952a4da85499120585ca1412aa24a0eec8b0504c5196a4448961a1a2a82c3d2d49a132c57760a03245849e9d1736ca14282a539ea24c5872724293152b509c3c2d85d034a5041a53942a4d349f1dab85e2d97161a138f1d96961497002250a4a0850a2961070b3c3c205a6344199123585ca149d1d2fcb14a54a53059c2c45951065c984259c9d15f6a90a01c29d4b4d15801245a504119c4445597a9a120295294e9cec2c81c9e081a105cd6f0ddc9bcdf6b3d63b1db806b8c6b4323dfaf578cfe75f4fcff77ddfd7bbcc54ecee6e6ef7833bca4cc7edb6b9ebe6eeecdeaeebe672efecbaddae97776eb7bbdd757f1dedba6e7767d7f4ebbaedeeba053d8f76f7d72d7acdcc226fd7f2e8f2ccf5a80f6e71e734479b03993bce6bdeed3aee9a365dba1d04887437a9ef8f8e865e2fb38db74bbb026f9b7638bc61d7d1deae9b9b2eb7d7f570d731d38e763f28bda0a3dd32dd6daec3deee7e703fa0bbfb477773cefd3ceffbe852dae0521b1bda607b1ef53aca0c720882d7dc0ec0a09b3fe80e3b6e224cbd6ec0fa6ec774b9bbee6370bfa58d036eb75e8c7a33c85c0f3aee2006f402767977bbf0dbddde95b1b79333bbeeb8fbb883bac9dbcddd75d3dd21ddfd7a756f0f69cabdb3e3791d8436a5ed75b7473dcff33c4a3da6de647675dd1ed80a601d1d9dd993276dd2ed76c8b3bbfb075b30f67a1e0540f7a4cd1dcc2e01ddbb949bbfba4166d760d39b9b1b6646c0d7cd9383508f7976b72165a6947aaffd983deea9d3cb71dddcea5e6e77b6ba5bdbda566bb7d56a6df74d77377bbbbddddcd2b6e9eeedb6bbebf0e38e59c0b46da82732337f7c00cacc5dd73177dc0c8add819dc71de8713779765de7791ef5769b72bd74297b9477bd8fbb9be93237ef2ea5bdbb5e874cbaebe69cbbe16800ee70c9641a7608807e31dd6eca1caba0b7db6e829cd7bddb2d07dd9eb7dd8b7bceee39a74777b71bc4d9607976cf9d5f476d6c30605148a7016d9edd3173b7bdaed9ec66dd4a9a520ff428a5cccddc71b7bbdd36dd5eda5d1736c7ade59876d3d975ddecb83b2cc0d72debbd809b3673d3a64d9979f2f6f77dccccfb639b0094f9a7797bb7bbebfd68f7c7d4a31defecc066baa1b7bcdccdbccdfdb3db4dd7029ad7b4bbb7db66973d5e5e66ba5cd7cb2d33c37876bb777a3c419edbdb8cd371b7ccb3bdee9a32e5ee3aef6bf6b6692fb8ddafed9e61d38f6977b737bb67f786e118766c0cc39f7d333b3a2773f7722c0c976d7ab9576776d7e20de9584105aff0d51c762f2b51a69e3752cf1b80e779d4f37e3c01785e00c6eeee26a594b97bf2ecbaaeebddee769777777227e99682fbf5ecd9755df7c74cb9bb9b524abb6753eee56e4ab79b6ed751daccb4b997f2d2edb6dbaeeb3adad16ebadb743bcfe3a6db81dbddf6ce9ddd766f37a5db75dfb7dd323377d36ebba674b767ef5266ee8984c7eee6e6eeddedee66cadd761d737777ddcdccdd2575403c8f99bbeef3beae1b27032024203814c81110103ae7ecbe0fa7ebbaafeb7c187545f3fb70e6c7f39b389fd77536ccdc5dd775dd31cfc95dd75fd7ed761c534a41ca94f276dccddddd5cd3afe3ee761b491d4850d03acb273c55216189848ec8088809552c1055011394285196988c8a8e38ec889111a84c910205458a1385b0f4b414c25315274645479c1c596282d25401274b539ea23018ba801c425e701342d31429519c443595004584a51066478e8c30058ad4396189c94994294d1528c18aecc90228a8a5272b24548972e4da234b57aa44597a7202052a84284b4e8c3019151db11265096a881011a63c2d5d1152a3a03c2d51591ac14906468a8a8e84b0e4a44a9495139ea258d06a5abab2d4e4c404282404798d50a5c9c90854a68c304295a69d1b139642a032c52709bb46969e448852a5a9098a0f8f1512a044412d913025ca7d2a5002d4acb5b404e584842a215081f2545f50322332a110a84071b2f404c50a095588769aa044a9d28441ab4a149410a63441b9e2046a8a132a53a0488922820855842c9130258a4a094f35074984a81280905002159f1c1396a43889a232e5c98a93285053487882120575c10dd48ece1ea952e58987290a940a34355579c2a00894a5279e1396989c4499b044a5029fa8a5117660505150534c58f2e1d608952a53a2a24081a202e529ca49d4141248a82223f788095344587ab252739ea02c3545e9b94265a96fd688132a55a6403d2d5d71120295252b56a038591a01ca539528282751262cf95ca1b2d4422f23786b53535fd8a235afc64d4d4df554ed7b529bae27b5393535353555eb5a2d3ea9cd5aeb496dd65e5353cdfd646a4ecda9a9a9599b9aea273b35e5d5a6f8c94e4d6d6d6a0aac7d53535353357e32356bb57eb2b5ee496d4e4d4d4dd5b82753739fec546d3ea9cda9f964a7e693dadca9297eb2b5a9a95aadd675cd7b529b5353dd93a959abf193dadc27b559abd5bac63da9cdadd1275babf193add56afda4366bf3c9d6e69308742cccdd9d244041d9ffb573f77b03c2853a8462335675e6d97d7ef888612c833d692465dd9f6b902fc31840104690fbbdf110c434c2889ead06a8fd3a0a41ac2f4d88ad1b049c43eb6bb34628bde0cbdf5b5598dda452a8c695b496534fbd6c216043e04b7ece9194e4ba882cda576ddb8515f5b2f57d81af08810b5e68827174e4853aa5e4c4f2eb3d9daf96aa8ff679cb3db2eaa379be6439e501db689fb7c82d4834ef0a7dce7b96ccabe7b8aee5544f579b78beefc148fbbaae3abd9eab3f7cb56f57ea69fbcf23bbc631b77004c60c25ab288d7a931e8c34eabbddd5e9f53f504a6ecf9679de50830d1a9845c01cd96066a4db1ad83da37b3be02bf369fb92eb34bf7d7783d6a715b8208cd3cb9065000041a8f9dcaa4cd35b3498f9929fe606711ef5bdd3ae79d057d4207497cb57e4601fac25c43e2af6b3ba949a5be4ea403df4341f7acbc10e995c97b79804b99039f4292e6979286ee039e89304bd45864e45269f4f9f753768965c5b0e9225fff4d695ef9d7a0f5b19359f7d7aad9b3c02ead3a903e069b8facebb090833c4d1b1eee9dc7f644fa4c89086ab00481c1c37e79c9d37072108b12d7300369acfb9101bed6d86239e3eb765ce3ce7cb46b12f978de7ba0eac3cfb4e8fea989cffc3464e73cdd370924feb511d1327cfdeb1ef74aebb43a612a6962b9ca206dd9e831e5962e03b974281bf29d680bd5bb56467fa6ad9be5e765d272ee9dac3a444e1d9f7d9d99d8d986c07273b93d95526d339c6469e73eee3917bab0a33c26e32f4f01dc975cee9b1c71ebfe29a1db2de9173cdaf68db21cbb65f710963e1662b09b04cf2fb72d1d7616ce4f2f5181b81beeee33f6cf4f9ba8c8d3aafbd8b14fd236b20e8025d8943b2e7f3968b6c3c755086a7ee9241cb536f8901eedc61dc5b0c62fc4e1dc6bdc540e6a98b0eb6c28ea40e82b5d99125e761ab4572e00c39703f045fe4d256049da98789e79c7b9ec8843ae89e8dc7e4f33c1b0ff4cfc196cbf75baeaac1e72d6f3171deaaa17fe4fcd614357079cb257640dd5599382fa943d5be734eec00aaf6a133751d50f76ad979585bdc82ae70c5b096521f7a4796f43b7f91cd5b768d4c9a96976fd935d2f9a4297548baa87764fb8b5c1ae80a5fe4d25cfd658d746a26adca243a75d1575492a48651f476256691095d027a574bd1c1da03bae79cafc884ba587bc0cae4f3ae235dcef4799fc7e4f3be562d3b071d6472959d8731d4f1d441073904c932f49e96ef83de913dadaa01e7a083b59cdff93ed8a18b0cbd9c1f82de72b0ee0695a0b7b7ea06952d77b0962eef48d0959a23e777f35de47e6b7e5712fd9649be7022612cbf6e238434356b2e0e7788c14b3bf10443d59cd3bbae73cfeb3acfeb9cdd878d9ee8773ee795cd66c3429bbe22f58e7cfa9ea3cfb9127724577dba39e3b8e029ef06754e7d929e7764399dbd450da67bb59c5f0f93e99e4ff7ea74d74f70c10e39707b929465dcb1776207ae5f776d123b153b00ab6b83d8f3c869fb8e2cbf67c6f2ec5c1d2f18590a707219a783e0ce0dc8f0d329599f9be064f100a133393d24997803f6c9f386716f2ff4f02ecfe35d1f3a087638c50d3e6fb98b2c5bce04bacbe5ec20933d4ba8cdf6a2d3ef5fd199e417bd90ee06bd9c73266dfc45964c450dd86d6a3959d4807d74a51ec91e26ec36ce6e53c91e26ae67773d579e0d6a6feca3a5b533f9721b4fecc0f5a1f36c523b2776d0b341ed61e5b1711b72da7ec50da6ed871b57e2b18f6eeaf6acfdd53913bbcb4b57e203d4a270b99418a422074a3e450da6b333bb12b7b884ddc5e4daa0767083daf6bb413d8191dab0bce8ed600b14ebcb77835a2fb76991653fe836a04d0b74917cb27985aec4afd06d4031f41618d6dd21606db9cb79fa32d9dd7875645957eb731566c3de0ce0e432d2dfdb0b2c4c2e23f77b7ba16a37c80246b2bf5e6c48c24c7691a2bb77d6dd5a9af0cb24543bc72b88a228860eba288aa2e8fb23e60182e0b72414088220e8fb03a2a0d56ab53ef7bcd56ab55abe3fad2ccff3be25a13ccff3e000976476708acc5196713ebf0de27c4928ce3976cee9b7496c80dbda2425ed4b042ed3483d075fedddddddbddd9d83b30357a4b5ac951fe934eecd2acd73ae84761db941e73977e0f57ad9b8e8a183fe7abd5e2f108020e8390882206806dcdd395fdc202fdc20cf27e93476ce95df7bee79b849ec9e8b9bb4ef39935e17e0f6b20b8157b87772fa4ee3157e27fa3e0b0b01dc1d7089e71e75ef5b9d7faec4b4e59f77947e5d0bf4c82bf3297965fef7b9c7be41fb55a6cf3ba708f8bc6bd5b2f62da7dfe74a4dc992fa6c39f8cd39a97f73cee91f65ffe69cff718b3ffed827fb6b9deca14cf650a724074abf3b8486d3f3dc69ae798a0aad2c7962801db2817b64f9391375cf41ea5d9f9c36cb66fb289cffbc3b2afcaf032bdf722576914f4e0378de20ea51ddbbf8a9b7c827974775fff98a4c9c7ccb837ccb5da4d3007e6e10a5adba3b848a1a704e7d8a4aba5ad6be734a7e1f39bd9cbfce91253b7da2f5abb56f7e599a739023f7a7d80e4e7172e4244303fbab65edbf59b2b7e779ee797375925a6f72bfa7934e3d3d77f2f11cfcb8f428cb3cd2f3eab2ecab5ed764d97e65fc266ac3f2e5e74e5e1e58d6fc95ef3f9f64d962a2ce0eba573f32f4bcfc3ecfcbcf9d3e2d2960f9a72bdd4fbfe23d54ed3d9fa212cf95da233bffca287e9777aeea34f378da22a3f8a9d79e25f3f6ec2c2a61efc8597ade399357f8f38ecbce9dbca747bab73e4926f69dd5239bcbf99f7fb59cbeeef992fe12aaf61a2c7d5a99984cefcab4cedb9a1ed5087a80564616adb0bea44f9f8c564626e98759efe4fd151cf135c34d9acefde2952e44f357429be9ec2c76406db69f3ec525a3eda7ed270ac0d792ce3befa6ebf3f5cf57d4a0e5dfe822a7831d79657e39bfe593bc32bfd50279e732b599d537a8235b95e9737064a3ce435f9fa26b3eb8a292ed6e4696b95c48c9ac65ed27d3e7a0cb376986a46fd0fac8464223cbf6fb8ec9e760a52c7b39e7d45b3ec5b9656cafadea13fcc8f2f39683e08aae5ad6dee5932ce7f4962bf524cbe9721074b5beefa7b748afdb21ec1cdd21ec2d5f5103fab34536ef10f6d200b5287eee107603d4a2f8dd21ec2da7fef66d91936a6c1fbff73d32e8d7bf197e64c9f9748fec99d5697e577dc8d86c0f80f76687066caba7de646d64e2fc822fb93abdb06cbf1d9c5ed8689ffad2263d09fd0febb515814fdfad5dd5b22588d679550e6d3af5e9858d604f9d270998b16cfae98565d485be847db96d2860695a3a9faec4526339bd3cf572db78ea52eb63cf4e0046891c941083c666a3754e6993b4d10eb4c0430a3b3c41d3b2258836bd2a87b6ae650bd33caf12006d7a4756098026258407d3a59af48cfac47aea9d4b09e181e75d9552ea1975af4a09e141e7b34a79cfa87755687b567e5feeed36bd5cac4501172c7e90e30c203e00863ff524398c4babcdb0c51338e02085190f9880b6b4f552c803b7d968d30b1b5df0d4f78756a669f52b648a6bccf40a9cea59cfd6570714aabdd6459dd2a96f9f21785ab9b2a3ee552a5d2d3b6fea22b29eab9d97d4a777de24f515996c172e7c577ff840cecba92f39b2e4bca906e63d2adb85d5735e5ee03baf5259369eeba80440cbedb98a15068a22654c514b13ac6eeff37bb3eae1410e39f207a9f5a9d79a356bc0d05a4ebd66cdff6003c2c20664b87ab2e08a8832b6282bcbc6ff602b52c614b62b01d07233c1b65d58d1d6cb0b3c97c2b2416b55dbb2415b2fa59eabe5f4de22e5de5a38f351f37fb0f950a3882c6fd86cb4ad52eb535470d0c10c2c79d86cb4afdab4d86cb4f5921ad15a5a59a7643b8b1f1429438a351fdc7c400d1ff6c8b2660d0df63cc5358e3b215a00f3e36c41869f9361d8da519e544d37697f9d525189182c6cd1751cc7712255d2cc5280ebdf6dd29c62c7227b3e2cf37ebd4d9abf2dce1a58f0f21ef3c2c6b7fbfc7c835d4829d7715d8b012f70c208ae061e569bb3085c2f61640fc1a694e47c4e8fe33a6ff7388e033bd287659cb3386be09057e09c2a719a6b9e7a577d58c6d5a5949c4f99c300a77f9b346bd5190f6359fbb749ed4abe4c926ed0725d967d3de711ebdf2671be0e723dfbf3eebc3b6f27fabaf6eebcbb9df36159e7208794dce794300dd49598a7d8790ff5f9fc3d7486ce39affab0ace3c8f91fc701b2d34d6272c2403769d618de7d36c869aee10df69de61a6e83b6c6737601d739a79bd4f93ab74993146219e7c5ea87b08cf3157b452b43627de4da24dfa0cf3997b1d1c8b2afe59cbbc8e5d9e7de47df8faf8f603cfb9cf38de37f6cd27cce3b1f967dde2c74a47fdebe82998fb1ec9be2e73d9ef7f3f778d569ae79cff7e6a5eaf7e6658587b1ecf3ce897eabfab0ecf3486e83d657a41bb4aec41d397f6ad6386e21c0f9203845252e0f9dba478abe9b043ae720486a50fb1535f0983c5f0fc9d2f3e9e06ca7bf372f5a9e6e90a801c92e929eb7c8f9ecdfe722f9798b9ceb4afc91e5fcade5e7eb20871fc9a0cfcf9518ecf02339ace5fcd0c1d057dc20741748c38f645f7183d04104881ed6f2fbb0e5537432414b0a586cef545a20057aac79a8c50a23830abf0e55fbad1b8221b92f92a5090f2240aca5090f7ab8b59cbf1e3a276ae07a77b952af92b032b93470f95627a92ffb5d0f56a6cfd94596df8a4cd83fa7b9e65baed44adcda27c91a382915e04619a997b1e7bed1d9887322ce63679e731f36e2e7849e8b3de7231bb1730e63a3768ee37c7fb8cab4372de003c61c70bb9b906514d6848d4a1fe3f3e58a419d73efe3fcbdce91d8a88c29b151f971c046e5f8848d3c4fc246b1f71c84156478cf25c046f4bd5e33eff520bde7cb463d5fee16ef71aec43e20939e18138cf79c3f86f59e83cb73dbc669aef91dd9a8dd73181b51f7fc63a3e99e7bbe3f5e65daac0e036ed3b8372b355f7e7be301ccb7efb33777393e7526191ba9702b63319f76dae106bb36e0e432d27dc0e8036cdf9f72b1c874d338f62cc444cfced3440b150a6a506159515da1061bb4ed19d57fe18118b64873871d52d0bebee16af94da4679f4e5d09a94b1ccf9ea4007c3469a5cfceb3fbb011e75cc315670d7f6f5dce3cad3096cdc5ea17c02dd2612cbf9fce1edba4308f67874d2e2365d9baefcd17fbf671ccb77f1178210d4f1f4626e2f7964315cf39fcde6ef0e165bf373064bc83935c129525ebcb9a13dd9725bc60c5afbfa60f634ff17bab41869f647e6f19c0fa21bf371ad44c7103171768dee9c9af6fe0cac2e19da66cbe8c02811ab11cbe8c0a930308822fa3560001f725941948008009ac2fa1c660fd2ef96c367109b5ed9a5f27e7832fffe5198278ae8c9f0ebe9ce6530729c939b8e206b496738a4cdab9963d8c79eaec2c6a407dba5233b9cf9193ec61c295f1d4b932be84aa3d75ce9974da356bd670edd9b931e5b8b71dc03cf9e4831c3219e439922be3a7b8813f3b25afe8cc1ac54cfcd9959809c9c44e1d64b29ccf398b1bcc35ef34d7705d7b964c6fdf607ad728706f3c1cf151fc5c2dd9afcc6faf7d2bb1125392fc26c9494681bf5ee326ab017748f3ae9f0eb26b93925c48761629bf3deae66c939476c06383f6cb45a2b4839a2db2cfb59c3ec50ec09fb59cfa2bfc233ccd9fde82b946300c3ff10ab5d9db0e4ebcd3ebb549abc7b77713c9ee97fc65f7ed200d7793a6cdc9381d9c220546066717cc64a6a8c489da6c8b868ee1ce746cec4432d39cf9759eae8984da7e1df4c21635d833def77d5fc7dfd7f3fb3e4e6633bd5b63f303f87beb02e6613ee0f6d19679a18938de00428a321aa0ad7f7d54ab41032eac81822c2cde9081b6be5528a4dc01dda0aba57fe7df76379465b58cea9feef2918d40f740afd5aa65cb5ddef23c6f0fd9a8e5eda047ce075b64e853dce0c7539685b50cdde51eb91f9251fd2d0727ef6c1b8fdc07c97d578bfc61a3dda0d2e7a7b7c7c69fb5ec9cf376b0e7ecc8fd014cffc828ee61cf5d2d4df8ce972cbf16b7bb01a9b8df4dc8326759bbe73e2c6b5f5189a7c44acd4ec972bed35cb366cd9a2f6bbfde9151fdeb93fc58c63e45255bb93ab28c7df4f961a3fd181bf9b7cb36a9bfdddf35391ec0f5fd29a7edd941b23632b5ef97d3c6bfb716ccfc7c32eead85323f6d4b2696df5a4edb1f2dc8e18a4aa82f7985fe3a25978cbfde6459fbf6dda4927acf12d7d3eaf4faf52de385bedc355fb6f3fe92cbb225a711e3f4f9cb45eb537472a7f1bbfa4c9b1760834d82308a0f18a9735d64789e5f15e66869ec1c0963d92c633f7d45109ece2870195c06c10d6bcdb322b853c6bd557d79eef7c665ccef0d98495d8969fdaa05402663cb5ee064c0b8a2016a4f69adcd59802540260470d25e96979dc375160f507ba6ad4e53bf5eb24f28b880f9bd6dc9836ec17a0a82533c40ed976525fdda77156c5109c7aec4e00c3bce49bac1fcce7b3498df7957bf9fce91f3f787f6e41e4026d399a697ed3cc92438ccb91a2cd2183e7df0c5f563597b3be5ba0dd8d9a84703f6f6ee7c72ced44ebdebfc6323eec2576225aecd39cb80cb80117c7109821ea0f6b151397fd68f65d4a983af25633bbbd3d453a7aec4693ead150097fbd54c26d961a4dd0ece90f612f88524b83fe5debe1dac73faf2fa96302dc4466592246c44bd5bdf5bbe7cf7f8dd927d3bc821a51f1b31b17f2c9b3e7df968ec593bade5f74b6f9665d429cba697e166fd3aa592e16869eb2bb22bf1143560a7f50bd988f7c66480cbe014620e31be4618a79771ce15c621e04619bbbddbbb5b4b1edfdddd4e7ffac98c969b162def6cc44e47362afd270b563f7b197ee94c2bc32f218bd5ef2d05361e00bfb714c63cf8da1fca46b52fd9a733619ab58709fde9f4a79b60b3d96c4ba8732dd9a9afb8a434e1a9d3eac4347dbff4f6a72bd3f82ba4c6736a01f7a714fa6559f9f58c7d1d5ca4b1f3f955c6bda510e6f79682ed877e6f58b67816953c602cc7710cd9889d7dd9e8f3ced93f16957c5de7e00ce78353ec1cecc8a8e9a484b28cfa92f13b9f2207fb9dafa8645956863fb95ad69efb3e57ea8f2ce997d4a3fa3d5f5109e74a0c822b762da5befd234bffcf3bb25c9699f09f97cbb2d2ca7f5e76be2c2ba5fce74adda4579da4bebd23f73fb2f479eae00c3d72bf23f757ec807e73a4537f3b259765d35754d295b2cc9b5d062cbf76e69aec9ec9f9932c4ff8e9e04e669b1203dfe4f41597703f5d899ba4cfe47e2d2d17ea231dd1d9657de4c375433ed920cf4752022cf3fc4582c032cf6d480f58e6b948c658e679482ab1cc73902c00cb3cf7417e3cf35c875c9e6d1f71c0334f037e9747f46513d2770e736b3cfca53613e603ce902c630fd627da14ba389906907ab5449ae3e8257579eb861cca1a416ff9487edef4a6e736def45cf43cf47c2ab50d2992e1fcbed2cb28faed2d7264d9573dee364e9e83e3386e0d8ee3d26db9bbdb1dc7110d390012d2779502317eb1989ff808a2382496ed929111fd8ac182038b2601f62c89a25f7e5e56ee419fd5e7f459cb9e2551f45d3e6bc979c95efb56ed096b493ff4567da2df84f42daf3df8899f8845bac8254312ecc2d0bb708b5f17d922cbaf847d9f7b5fe5603e48690158c6759d73ddce675eee2953ee9e7b5bff8a4bf6f65c27c95f13278705e4e077a6314ea74d48bfbbe34e2ca50d5a18c771dc2881e79c92538d713a6dfa798e0b3f3add18a7734362dd1b43ba18a77f4dbba98c6b4e2c19112c1958932107d304e3f46e427afaa1e17c143bc026496dd02c89f636848f24c0b389a4268eac3aa43c01ee0f8c8f864ca3a1acb1fcbe29c7580ab9f65b3ece461cc7fe79bbaacbe9afd872d5a6f0bf4fe6f39bfc03b848e38dd36f957be6d73de016076cd4f9ee1637056023aed5721bbee5e51192f9658bb4bc2cfafdf952f6365e0e11226ab5bc56abe543672cf31890c9f9ae16bb7ea0ad56cb6bb9b0f4b839e17279cbe718d0f5b1ec6b81b99a414c31df8d57c686b246cf27186314f7d3f90b18ae2dbf2129cbbaceb956eb76d36ab56ebcd56ab55aa3b75a2d9f64d888bde5f3c646d35b37b575f38465ec23fbab8c8d9018fb10249b4ed06ab55a2da46fb9abd59aadd98a6133185d5eca5e6993ac6cd074d8bfbc0c7fdbe785fec6d79d8f62a2dbf8aec7868037e47cfe905c3536c77843ee831dba9a90cc3421c5f8f99279cf4472be8decdbe538de2ed48e437e3d9bfbf591d22441b77b0082ccf3febc91d888bdbd006ce4f27625d0bb09e95dde22932939d05042896fda34ef727086a06b7e6cfc742f8d045886c603e3f46fdff990127664c2cf6f8c8f947ad6f90ea519436fc2320f58d6b9120fbd31967be63b1f3a632ce7972f6ce4cd316ce4657de7b38723d8288eeff68398627ea0aec44cee37e9a358cf3affbeb11c6becbb490e658d9df7d1acea59d7f98ca3ebbc091b85deb90720b05198ee0b18367279e7f38a8d7ae0e9858daad8687a58abbe9b358ad25f91ebcf06b173648c652c6b91435923cf3ac6e965ecbb8ed6b9f7103e5a5ae7714dbdf3fde92ad3bc71536c77bb7b669cbe7c46b7ceadb7971cb7cead3371dbddee2e377b085acbe6dcf3b29bf376ce999a8ceae79c7275418e2c857eddf30de27ac8afefa4be2ce3b8eaf36912e7259d4f7d7224d1066d4929a54d765cc2dfa6900b703f96351e61a5edd44bce979bed9ccf76266ecef2eb4a9dd63dc0fde948ea5afe82df1b11677e8b97fdde88e8e1c588f99ddf9b18191eec90eb815e3518fef29ef75d95e12b5bb1cce3aea41fc525d7287ef6ce7b17ccbb5adae078f9b9d875be7c94e39dc36a1945bf3ecaf15e1f3d875c9ebd1c875c9e8d65543fe8ddabe59c4726d961b4a951f4bd502493ec307e35aadf0b7d39177d8a1b304da7ef55a6b07ab48ca23c497018a3faa78b5e46f514c37dab32b17bee7160e59c2bd374ee5bec80fb59f93de76ac956db2ceb1f96b52c8cbde779e794df7329dff4748fd23ff6a5142ab1a795693aadedb4321132bcffde86a0e1b99bde4d51ece066f5f4c1451af9f6f4411a2e1f75b58ca2ef390dbd9c47fcac252de77be0865c477a5e3ccfd98a8a4abc9b525351c9ecbaceea978daad8cb44b2556cd4c244b24f9dadd8c873ea2c2aa1b7f7c825e96f0720c755e07b955b984592b0acbd89cb5dde5517d9482cdb632cbf6f9f73fa574bd94bbde794ac4bd8eacb287e6e6116a14edd23cbda7b9c533f272ae196d66c7844022c6372534e5492c29844c90da41ca55de7799c472793f1f9e93032c639c718b796b4e368f3f46c4a137e4dad9b9c14e066307e0ebef607e42c63393ec79efac7465de5402f3fa432eab9b2e9b9d20ad628c42c63a4767e1711cbd84de803b06c3e2587fc24cbaf1cc72ef6732c7de9b75afef1d1d872ca46adeef315bb8f73ae4d3126188c01c418cf714e9fab3d9cd7de59367deca3a1acb15c35b2e9268cdf9629b7ab65ecb9557300967196716e570e58c6338f2d33afba3792100d21834548897f7e77a362ef2ca3b2a7ce710e8235a4df2813362c61bf2ce3caeced9158466bd9b458de6c1e401094b18c0e795ace6fd0e59e1253d146b411c96559b8ddf75d2d9b7ede73d095da25d2ddcf3b07c15d727f3eeffc739afafd9ce6af8cab2147cee56c7683a8fbb0cc4796d15a36217df357b3995c1968ee98b669c3c26203cd933cd0604989c0881ad65cf1d090012e1a57cbd73fa794524a5d89859e52417ad02959223552f9f313fcbe394330865eca64e1071b7d623f4fbdf4e7ca214fddc697e8a98b3ca3cebd26e9721bb2943de722590a3d579fe88364c9c173dea212171882b5e9e73b679189d4183a42b0c6739dbb48fa2d729ff448ca322434bf426a36937a015ee19ea973cfbb978b0e7b97afa8242692e57cd1c6575462e34a1c9225d287bea2122506c3a80f43b214fa8f65ae6a4396dfbb6a19c5bd285ee19e8973ea477bb3d96c5a68dff40fbdf4cf731f36b2f97ac622e7375ec6de73d70cc3e532366abd9c5d888d5ace4ec4466513d28fde029d7d24479685de223f9685fe224396857e43c678163a475296856e43c294887559e6a08b2c3f6f7d3fbbca91b4be983ac1399d58ef7d53cdc80e96abe6db29e5c872c97c921dc625f3e5f81f183f07818d5cce75bcab2ecba82bb5e72df289bec77de4c8b2c9d5a62533e502172ae6788efe24f7b78f40a7ce1eb693cb5456cd7395a96bc8b239b15acc654c2fa8734db19fdedfce9151fc4b30180308329a6273fa1910f47670722d2ae9269b9cce93b7805bcbf137ece95c476e609cde39535729cbf018d9c3dace9551f4a7efb402dc2567d568f37b1ba24acd97e1b31071fcf4908d989c318c7b13e28cf87b13a28b9ffef52ce12f4ff80b7c8fcce0ac1a5fbf587a94f909669cceb21d13fa88ae2f159d96cb715db7be9e67e9267d2445eb9649a31ce7619d61cc749d83758a41b365d23c77d53926cd96499b69e62d6b92d30c39b1c85986e346d05d31aee51fe7794739a7be2e6b6242cfa6cd5541109a555f7d82f4eb3bada4f4ac777eb1d2b332b34bd9aa91f5919410a5ce21852e2ab91ce4a08f3e6f75eeb918d66fec2329d025d58a791f49795cbb6a933f26c0fd29f9f6ddec94d6726b29fbe6762cc6725ebd10b62f578d1a3366d0a04993a69c655acac65fde52a18bde522e07bda53e97e2bcf3f61d5f75653db3f152c846acdff6ac440ac13a6ecfcabdb56a8c3d4b77d5cb79c5618d992a018e5aaa64342d5b9084689e6f91d13adf12a36979b9962d1f8dba962da3962cdecde634976bd922a3b55c4b15114dcb16245ae860dd2244036d7ccb109aa8a5ca87a6658bd36efc55b7c468a36ff9a1bdb46c91d182ac91e95a78b668fa16a755b07e43c2b668fa48e6ac91e92f32b643d36dc86f8ba68b64b846a687a4b746a68364b746a6bb48ba46a6b7486e8d4cffc8dda2e91e69b346a677a4b846a673e46b8d4ca7e4cd1a99de24ce1a99cee4b846a64f8d937b003bea5b288d139adc94f3be968bab1ad2dd2dfbd9e11aeb990f900a82d0a693d180fb5372568c2517e6cb485511d1a84bb567a15539b4be55118da1a267d9309eb8434c15118d73a92c5e16eaec5c983ecae265a195cb00685da5a4a4b80cc0e332009a58a56a414cc1a555a54ea062a2aa882c8e584393e232001a57a5a6dc0073c697306662a065f13c8b97c5d3b225a47540fcab82d15a1dd755e02e7a8586fbe11406e35c072b88e360512b5abd459712c203d22b933d0e52bfc59cc73d766b5188fff8f0711f395c05a35131cf9db5e336ecfc53a5441752bd56a991ac524a20e83d558ade78aa148d55a9f6dab71f556a6130d7a95214abb182546a7513735795a215544a81d42d43689fb77c6c7d3e554a080f78bcc7a5c41fce2ebfb972b9d4a7e3ad9e2a253a4f7dd233761f552aa74a0955a92d43689e87558a8ae92c313b95b31c4ba88b893f6a9733ba14bf5c8adda6ad9eadb06c3faa54e73e2a4e95b2d233f69b2a35afaad455cff88ad12c9aac2b0ed6e55429213cb8711c976ab9541511cdc5dd70aa54cb6fea1cabd47c55a96955a5daaa671c56c6b24d311bc613775851b055a5b46c0969ae4aab8868b44ab5ea44d355a98955a5d856f9363b3caab0a30b24b4c032b1e697106cc08d327ec8e24df115471401c31779688046ebcccabab2c2a2376abbf51515d35962b25a4c57b92f68fa0acd155739abb6a25e3296b766cd1e6694918506ac68e5aaf8364940c61921c8a1cc19b4a53518192063092e5cc8415b5a57ce36b39e7d5e314e2f391b87f52b64aad626fb8061a279f6d9be6a16eb77d69274da39e74fd9ede795d3a5b594752d658fc68b9896abf1cfcbc5fabce5a5ecd755f22d0d2c0b87d5e4947d330656f9cbcdc19838bed0f055cf98394ccf580cd6f3989eb1992f67d6623dadb2b2f9125eb9aeb26e46353726a0b9b9b1a5b9a9baa9cabab1bab152337ee9190751f525ad2aa38717349d1bac9b9b1c3339398ee33e7c549d2a631d9dba1cc0603855090727a722e5789671e6dc54a1e9f36a5e95e199e69b685c4e7533cd78be34aa9b89e59148f61867f57c9619613858b38c192caa2ca3df54cff11caa1bcf32c22a0a39f5e6a6ce3450b5e75b99e9e5bc2af3fcaae528d6323682b574572d63ad5acafeaba5b37b24df560d1a35612ca1830d6dd0c183d4c24195c5cc18693c4193e23beaf0c1c6c5c6019a547731460437d8ee688226c565b6c461870a72aca1717093a64a0f27b2acbe501bbda261a89883260322cd97b40acdb3f34d56a68f84b0fa08c94c1f29319a3ee2a067ecb76797ddc4f46cc774b5fc6e5c2dc7323ddba7b58c290581d5b37d31368c03c5edd7a77268377e33060736460cccc5f48c711c965351b8a9f40b0ebd9a586a5e63d5100e9a1dff9126c76f6e2a0a3caee3b057a5caf272aa988fdff88df3d8e3e3f1f0f47cbe7d9453739ca7e5db473b75fad26215859b9c8ac2e82e9f5633745a158a4e6da28db79a9ea9613559dc37eff31ef3b5bcc5b45cde615c2e24d433f6efe334dd68a873dedce8595ea02f8daaeb1c24e99789f5c5cb8935e64bb6650975c0eacbefead9594d1f71989eb17f36b5fc46b196632cac658cab1a066bb96a7e7ac961a62dccaf99b73d87995833ccc49a61a69a325f26d697ab2f5fb2ca3c673d632d561f8d2f33398e134383e33f7ea4b9711f3e1c85d17574bca2f072589582393bfdd24752b1daa467d373aefa48ea87999f8ee3523ed0fcf41b97d249f3d347978265fdf497b30bf5514e95f56c3a8ed04f77d5f2bb41fae9ad5a8ee3eda77f42afba3d2bb7cc4ff784ba5a7e5c2d475acbd897df772dfdcbef6d6a22dfb401ee4f49b39e1ddc3e5293f5eb6926ad5c33bffe9193b6687e17ebcb3643c3f4ccf6558d56b12fbfebd4d6472da667ec7e15fb325a557ddfd8666849b19edb8c18ac3e5a9a193434cd330d2386d16c5657f5115516cea93cf7c2b4c0305760ebea8b5349550dd15a0e7eb1ea23aaceb3705eedaa8a42e75d6dabaee2315ff5ec6d66d17c69c6ac58abe9a32d93e63d636f33568c26cd17ab31cfce567dd4cc5f9ec73613a3b667b682622c5bcc5c9ac7be1cbfa46196366f334d9a8ecb4261dec44c3565c6d8b06e3d63aeea2333657ac652284c343d636fac9e7149c33c7bd9629e69983ee220ac50a30d1b5ac882c64ec5f451cf80471e3f00b1c31434763aa68fe69615cc58a3660d1934767aeb232357d40082355bc8d0d869993e9a4adc1143d50960b0d1f8cbb3975ffa486a5ef551cb993d67ced9adf491d4540e8ddd843e72550ef4f8c2d647addaa467cc3eabfaa882e0ecd3aa8fa4aa86685f45c1ab4f50e0aa949e316f9967256d6683d8dbccb377f76c2f65cfcdfe35ad1b3b5a189bb41caf0a69b19dcdddd9a45ead79a4a3ada446eaa2deb6ef1bdb38dbba530f590c78f3af4ab5edc6b65795fadc43f3cd7997f5edd4a5c22ac5592cc68ad0d8b2b9fafe1c1c5d58df225b7d87236349b195d4c492da69d5448aafc01b46d371556a66f914f3da5bd8b6d68d6db65b28d4ca129325a6e51ea301475f1ae8255f89ae79c57939da78b9e3abba4dfdb0c4b0c6c03ab255ab8e5f8d614de5d0bc4aebaaf76cd6a5d1ba3deb576db28b0b707fca99f5b9e7eb631f75be1eeb23ced7bd8fa8c8b5ac71a45392ba474ae9f8474afdf0a91c9a962d228dba94101e84eeb954077ae75256943a67e3f4f689feb9d4f6ec8a6bb9cba584f060f4d6a2e17ccb7c3987f5edca711d9712c2031ccf41e3ba71974b6d964e95d2b245f4e13fb4540d80a6e35b264d4a080f60aee3523faa948fba65d274da6175da7ad69e53a5269a9eb5e3d42d93e6aa524237d54acfda5b55ea49cfdac7ba65d2b82a35b17ad6feaa2e6553b74cda57a5c43aafa4c2ba65d2ba2ad5a467ed609d563de3b0a8d5772377d5f272de2856e78b46c8db2c9797138d8bf3a5755eeead55a77268d497e6f9e74bfbbc9c62be3db223c79e4de7c858cfa653d27b3627ac36d9c302f7a7f4b2befdeba372a45ec64a2f6548f6189f38ef7cdd65e3dd6ab92a0a22e8ec7281158556e8d4b78fc28a82ebe5d3b78fa842247b8c4ef3bd321bd4be34aad0a5aa8668af8a0268535108bd4e4da7a68fc44a258ab553d3b3f6b05285a1e7b38c574b072b1508cedbac65cc55a95c9ee5732a57dd313d6ba7b51cbfecd4b42a55cbb37c15852c730d4d08ea4ba36ad529a6679e0dc91ee353e7ecf336729832ddde80b8bdb7771dd60c13a68fbe2af589e92371f5c01ad347e177eb23706c79fb2cd347ae564521f655140690456be748247b8cd4c1ade574a28e648f5183dda032a8642fbd32f389713e3196de55a766cdcc30fca557c62bd347334ccfdabf6f1c63b12fbd32df3d2bfdfd6dde9557c6bb5a36beecb03a351dd6912f3b5b17a6b3716238339c18d897140d5745d1b8bea456744c49adb82ffbd669fa4bdf38abbf94c9e22b5b99307ca5264c39d5084d5bf9956b46a8fcbee76d8c629ccf5ece305ed6af90a9afc6b18d1770a7082d4ba3a1413649d5105a96ce83679354511a27a90a7d3649150cc826a9f2a9609354fd7839476859d8c6be65c2364995a7b349aa5e3e3649d58f1f9ba42a486c93545d40eb2ad579d5106d9368a90aa2656935365afb964edc24556cb349aa5caf4d5285336e922a9e9b4d5255713649150634ae529c570d759b444b168f56254463dfd2de26a9e2689da44a6c6d922a1dd726a90242eb245516d0ba4ab5570dcd4d52f5f126a91a7b9354c5689ca4ca6949aa64344ec2558afa540ecdf3b8ebbc1ae3b8ae8e5da5aa8668ed5cfd7a36bd6a88269543a3552a4bafa175dd9e4d9fcaa1550dd1b87a4f7593de8010337b4e71c97083d81b882b206a78a7716f3c78f992fe0231435878b1e546939a9a50a85165a309c13ee52ae30b4d881e266cfc3c5233020d31676c208f2b20e8e05f324e58638f2d779c200d37dea0adef08e0228ddfd3efcaf03bdf8eb2118c8d5adeb96fd27ed775738c5da78406ab67fbadd6f74afc9194655446fba87b638c1ba8c8b0210533df3945d3c6775d11697ce1820d304570f101da18df755fd6b84fddeb588c57009a460d6994f9e2bbbb9ef93c9ac585716f698c4943ccef2d8dabdf346a48230b02a8fc7cf9f3dbcda67ce60b1a3b9ca9a2cb4f1a4fb41207b5fcce205195c61922b6a471260c9734ba336bfcebf77606ab1b438d3cd6b01a1ad56043e7f7a68617b0df9b1a4d10c143f87b53230321f87b53c38b97461e6990e0671a68a4a185cbc64ff8652a903f80244488c60f1a488ef37b43c36ac67e6f67a8217f6f6794d1678cf1f9bd9d01e6a783dc195ec63c3a33e2f8f17b33430ccf0c32427e6f66e4007efe7b33b3e6a783ad30c8efcd0c9a9f0ebac225a346a8716f66b06018777e6f668ef8b9aed607f62c01bfbf6bf9f4dc3380cb9d379be33252e8bac658e6830757020a47930182aaaef3ae23e38c2aa5f91c4706558c655ce531bc9fdf1b1949901104d65704b83fb309d712f6d399722411cba6195b192afc8ab43aa545b422552132c615429ad387e0182bf8bd91c102195d3e5e420c31be40fa82fba8d79b821460f130061466b8bc415b32b07cd769f15de7423e2cc300982e6000a20b174400025ac7550fe373fddec6b0e3c65978cc678c9b185b8c51471630c6c8d202c618726401638c32defbbd8d8145b1e0829b948302848105061a6bfaa70b1378f9e9e20d15681794d230d03ca53f5d503166f8d6ef4d0c2f5f80b36a0ce2d7c570e2b746f1ef0659d060a6f76e50194f8eace7ba9bf26f6cbcf23d5d30c87cf93de7eb312124a53e721ae71c1c6093fa396f02c611cf79f89c6f5fd12817c7739e67f1eb5c992df3e590e9b376bd01cecf2c709e73b0ebbadda0d9d5ae6ed697a6afbe9d070beff7068618df35c90ee3c47a21224650e02478238e12cc0dda00a91d6cc706b52741750d1bd4ce28d8a0e6b84abf6c12fdb25cfc6e906fed2f1b74c588f3fd6522d96f6f1b3669bf198a3176a484856667d348092bcdcaf64b9bef99c4ef9738af8475c6ca2612252c35b6c8fe55d8461e5871fc2cf3ede0ab7dfe404edb7f8b1dcc322f32995774759a6b9c7e7e6af9e9c3cf2fbcfc2cf3e0b215e3debea8e3cbef8b20bef49ebf88c38b3cca4c28c61f36096a6af9f9c306ad2741f9407d785a6693ba96f3a1a8f715df3eb1d8a4727ed7596683d6b1d8a0f599c5264ddfa4ae4edf4fa75dc06d1adbcb6f6f5ec4f194522a055cfe61ea3d5c35e0ffdc73a2f5cec3ce471f19cfd6cb2423cfb6837de7a59743be731739f28cbd457e1ef5e2ccef18bfa2929fae798a005cfea5e0321771fc4af17be3a2030fbec0ed231e20bece81953ea2be3ebe0c1eb97c5d4a1f5de01bc4b7a791fae8e5eb4ffaa8fa8abea4afaf0bf511ccd741e8a31c5f20df1dfff17513fae887af10af31f2a702c089f810f7410aa9543f42dc02c721812ad50cc8656e43d64a4524c87d78489295ca82eaa4b7c80b2a55900f1fe21f19a452c92e700cdc237b2a5525fdc73b1248a5eae9bc499f4a758167a1aaf1905440bcf320d37582b88f77b5cb105a053e9254416a1700d0a86c3c888ff7384852f9d42e3a34aacf7d6a171b9a3b904ac5e3a3ef9054608feb388ca4ead17120fe22a9746a97a651c57c04e22f77bd1c7420b54b108d0ac781384752bd6a9700d0a8420f02d62e3e342ad07dbca77681d1a838eff11c920a00446a971d1a55cb7d3ca876f96854ed3d4e492a1fb50b0e8dca878f436a9749a3d271200e80daa5a351bd3c88ff20a930a85d7a68549df7cc6a971f1ad58e8f0ee4a2ac7679d1a8440fe217d42e48342acf7d1ca87671d1a8721c88df9054423c0b558d6641ed72018d8a7a8fd7da6546a3fae163a5aade65d25cce245516aa1aeda77611008d6af42041dc55a9749c0ae654394e75e3382ea47639a251b9dca756aacea938a7a24ec5deeee364edc234aa1b07e24e52b1f754aa20950a742a9753b59ccaf3cfbb4c5a8f574052c11c48a5ea32693e956a74aa9753d93855e8a2f7542a1ea7da71aa9853f9f01faed43ce40e29ebd97a8c6cd2b3f51fa4093d5bf7b1ae437e3d5b87913924083d5bc759bf591fc9b167eb2f12a967eb36e4939ead8be4acead97ab80e92b19eadbb48a59eadb748293d5bffc869b5de91deb3758ea4a4959ead3739bff46c9df7b605d6977bd3c2eaa3fa99a6c73ef641f35363892596405ae2c727e66b460b4378c1021b19f0e10320647121051fce88414b0e5984414a6185142d2b9470856a7041f42c99627a96302331726524c6f5dad77ed6da83dd7d4529fd32e7729c3357b90a8bae0ba0c401cb26119f0f2d4a29a59436a556acf0945af1e529e5aab0c3c60aaaae4837f175e745470658ae972573de39d8b56847b28b6b247e7086aba48990ccc535d91deb19e720d7a21cc91c757194ecafc9f79cdb33a62bfd3f9ce079eb57f480da6c1e4c9b8de6397bb0379a5739e8d9ba12f37c8a85c55548635d4322072dc69ce9020572fca08019a608e209335cd0a8a38a35ba0a10e80ce0f37a84fddeb068e2c1df1b16626e9c06b83f5cc458ae99ac3e12e23f5eb2159005cece6358d633eef101227376fed24717383b5ff511e9ec1ca68faab3b3983e729f693a2fa715e7e5fc323adf38e338e738c39c7f784c07843e7a39fb933eb27176297d24eef0f870dedb22811790415c4656e0e00c81909326238138908a0250ad1790163800dc410e8190aec4401cbc8084c11c5651f0d1d1c9e989c570c8495b51c90f3f1c875c5a0e2973187981afa8c4e005a4587b3eb8c045172b0a377e41edf9c00700dc878cb4a93d1fc8fc02bfa0a230baacf67cc0e33297551466cee34b5bda8b9c3470863fec7893972bf14c880b71009052427c3049804416361a063e73a929995fe018ccea94ac2e17951cc44f4761ea826aeb332390c146fbf19f3040e4546301c93f644fe83d1fb8fb4fed01bde703d7f19fdae3f29e0fdc87ff5421644f589b90def3815717527bc0dae487f77ce03117527b5cb5c98ef77ce03c2ea456557262f56c3a49ce323d9beee434d3b3e941c879ebd9f40ac839a667d38190534ccfa6fb90334ccfa6f790f3aa67134dcfe6cc1a3bd9f3903b648c34a167d37f90567a36dd07a9434e5bcfa6c34829e4131c128491e4c04654ea23a146ea2035905d5080df3af80af313674510a43c1fbb1b11051c177d695de879e84bbbc1f1a6989b39e6a777f3a6f3c395fce0e3a6c371d1f350f4500c6d26d6741cb6fd74b135cbfcf4cf4c169a344fed62e8398e7bbe34d141e8f900c7733ca7a2d0398e2f2df40df629cc736e1cd6790e082c9b0e237ba8c39ed8a1e63b3d3981f0f2cf4170b98d2bf9a1e54e1f48850efacb3f90127d74106edcf32982d0398e37d1e2390ee89ee3d41ece7fd4eeeaa7df8479ae36f1a1536d30f2cb4fcf217b686d52f5d3ad9abf907cd5b3e920934f4e50f39d9c16b034cf17b0341c7702a1e70397bffc5551a0790e42cf072fefbcab2888fef2a5e1f8067be39d8337be2208a2773c1f87fc6ec81e76cf6b34b017b0342d2e7f798753fc207497b30882e82f6f10407755aeead9f457ed69b77191e4a067d343727bc6563d5d9bb4be2af3c81eae4d847a36bd469bc2a951fe8800979f7082892698b0a28ef79034516669535a953868b2007b850f46b881841c586031070da38c1968e680420d140441a357d0f0945e91c3d39da702784a29a594d2fe01230524a0018b14742083b6a18716476859638d0f1fa0512bec781a3ebd22cbd39ca701784a6937b13e7e6f64c27c1ae0646e8ba38fc644d09f1f4afab0cc8616f88789afc9b4f0ed85d60ee31f262a074190b17d197bca3115753cf77ba3628e2f85e80d091224489ee8f0984b3dea3c4473dd1c19ad987364401907dd751558df557891e4bb5da8964d485c131fe7d15993f840470b7150c1250d99309ea842081f4c2046961c768ca1c20c15653af65200a7cd89214270c3aad2920609a509008d0c7821850b5a6051066d7d97aa38820c1444083105144c3ca1c4ec4010484c0e007104910546e6b922c3ac61ac80fff7e00b4d9329e4c7023461c7a29456252a2a8cf872b19a78158b524a05114f29a53e692d325231c4b3bf122bf10f0fc53176bf372ac2a0a150b4a670828a2f2cc5996729c47866de329642426ce4394f073972fcc8ef85d1e5fbe5f72e6f39272ee1dc554ba666a23e99da3b063951c9d7a2e2016a2bb6bcc5259fb76af931b5833cc5f68f64a23edf2349da91e1c87db7313f3f3250fa4305a90909062a48cb463d419e24388c5d7b187afe393b0ff596835f0ca3e7fbcc7dbf7df4d1be0eaecc9f955ee1beab4cd4b93a99579042ccbfbe8fdc77cfeb9cd6929c7fcbfa0e3f92c178e47eccd56950526f39e730cf5db56749e72defbeae3279cee212cfbf24388c5e65f2c2259e77de2202baea7dd5ab4fac7d003b8fadbb14574f9d93c22a0a331eec18e7b0986b50561f96852cebff58d60bde2c204b1c3556993a67ff1c966487b1f392738e097b5799b8eab5bd2f63dc71de4dbbfbbe6d030a2c3280c5195daea0c20122f8d2431a458461871734ef04de910bad8ea3cd350a32fffddea2f8825e457144143dfcf490c18dd19b0568d1f2dfcd02b238c1b27d9043cade43e9b76ca30f51d64fd84f2c286ef8d29f50f3e590b76022fd34f36592a7cd60f3b36fc0cf20cf651baecc65ccf9bd39b1e69578f21a45fffd7a13a43ea2b45d2e86c0e18529c678a10c3468ab85102f6c91020b72888086c3b81f0b4d605535b185964fc8efad090e340186a338b7d96c511c12b7e0c58fcf183ad8f8e1eedd169899f97beefe25383d6011c34f9f67dc96c06a42062aeae32cd332ba7e6f4da8f06b56f8b162420d971f2b26e6e8f2634583fcde98c0fa9c273c0f7c4a1c14a08b8f0c3a84e44290102748a14c16aa1768d82e7088018b3437ace1001267886ed81021b9f0c5c6df1b13429cb1392021d5a000d342078c480209aa10d48270238b092ca2c0a14c07baf8c8a043482e2c194d9031441d6770d8c20a09b8e1461d37b8616606369ce0a4108f20b920e63d2417bef0f7c6840e2768c5dc87892f5d38e6319f581f2931c1c20a5f6582cb969688c7c75d0c47bbb332c8dca3d81e292de75e261142e697c6d888dba18c7b53e2ea6f7e6f4904f12b72aec47c35c67c3c9f3f5f7a5589838e2c00cbe69a14684a1c14e028363da79c85e6fdc436d65b8978369d2385dc878cf5d10fcfa6330ea312077d346d369bad8a36e76dfad008c6fdbd2991c7fff8bd2d1182a7bfb725d6f8c965801d5cd9bcf958e65e0ee91b18cb7aaabebd87ab1af073beb72e7a78ea4a7dd437760e3c78d2f4e559a88ed7426f5f866f23c4dec6a0f9db1831ffe5a679665ab96a16a0c50cb9002c60c80560b962d9bed0ac7a3622f46558fbae3d4ce6b72f404bed7feb0f9d2bf1f43e1abbba3d1b59c6370bc87266d90a0d08524a414a3b57e7ea5c9dcb455d61975476eeb95273d9de39d8ea662ee753572d6bd92ed579b743d59e3f26d6805d9376994f50cfabe557fabc0763dfa47ecf975a8d9ecfb167d43fa3aec6820b2770a30b1075c861076deca32d811966505185135c8c6983e6f92a91c47befb9b35191f75cd64794e6b950574796516717c6fdb18f3e1aad7e05d8dddd5eb7d7852c5b4e9c5cb75fed76ef5b5d73f2fe9b7acf5954f2d5b03d9023dbc1f6ce39b2ddeb38e7ce3b36a26cc4b909df1cc7b183dd91ec9ea884b24fb1ebcfd988c9ee06b06a4edf65dff649eecfc94d7189f7de926cd5753ef5fbebd35774ce27c95e7e3acfe91c37274f8e9d921f5d4e0360b94e29a594b26c7da71d60397fd38c25fdf9d41e459ff3ad3d4b76d99b96cc539f3b97235ddff2ca30c64db92ee426cff1c6ab8dd18664b1430a72aeaee585637bd731f4f93236e9f7e5c8327efa21cb98d2df350a611ea0d64e9dd6927e57b68dd36bffc3ae36c06523fec2918f465f5a8b64f748eaee52c2ded280f965d37e43fec494fa45da902d4eac2e722437490d63e7ad0d3a675149abcef6bacf458e20255dceadf0878d5cb58ccdb01c9b9ce29a0dd33d7ee81963f9f3ecb202707080a618fb4fcc872343148ca5ec59c646cc5d47969919658c07b87dd47235bbb1dfaf964db2a74e2ecfb8e99ef7757b5e4f35d32f9d73ce7907668b1697501a66118ef326679192caf0ec5354c255a6611661a7fb733a8b4a3866925a99f09c33d9f40bcb6acf75fb8afd5196cde9ceb2e971f78122ce88b93df86a34a698ff3e67f7deb53ef594fb3e6f55ef2339075b9845d6bdbab388e71cc95e9e732a2ad9ca55eef93e25f74df8de632b96714aede43de9d124bc2061fb2972aec474837dea1cc96138521dc05d234a9b91b097cbbfcbbf3e9de9697e127bb9938ce235622fd77777d769dde5b9deb3b9706ab2a444794faf78cfc41a9801822092d037611967869b73ce39e79c6b66d99000cbb8aa013713d759f3662f91f5447e6f47dc1e7ccdce39b28cb1f8b96ca4bcf7b53c977fde22cb980d39bf8f5e0ebec8e59957cbef3db1e55e4f1882ee72d025e53dffb8c997eb4db1b23682dc3e88f19a768c1301f327190e29d8aae35b6e041b0f80df9b115f9ec99cffc36ddca6f4e13b1ee361c271188843e6f80dc9d3718ca87a1c17d578204d7ba0eadb03b6ef06bb70c52539ce5782fc0be638a1e3dcdcbc70701cc773c872f47503f8f02ec421717cc504ccf7e14a8ce3379d88801c87390e594a791cef4404dc387fdfe8e5f838be7cd4133a9710e4c7b227ac06a8fd587b5ece14fae8afd0470feb38fab22caca5941feb4b7998e394a37738ce891cccf7e130b284794e4db2c308ab1df8709ccae4c3c3ca243a8e2bf1483259c26a53ec7dd41bd1d779c8927ecc5b64222e112b65994d75ce716ab953976531a72c8b3102b896f37f20e0c70fb29c1297b0df3878432ee977894c4a1cbf79f2b07621a064c7f19bdaffa396287ca18b649c0aab25e751fd2e2f29cb6e5ca7ea38c7e2127e1d77913ab59cefba71ca46a1dfd4f2c66fc8243b8c51fd2ee7fcc641326abecba7a8e4c665c7f8790f93f9383e1fc7b9daf8ac3dae0ffd08314768610ac525aec7d9d05baec42d12c4215fd35b1e30f32d0f1d5c900b577cd5b2f62f1fc932f6a3c3c852cac360ffc3633737ceb1ea43e6a396e3df78ce8d2f1ff5b80f1fb5fcfea6963a0ef31cef21976739b5fc9e6b29aec3c8ce75c8b229f6382efa8bbc321fc7a9b8841fc7a7c864e278ab96a1e3380ef99aa2016aabc438243f8b1ae0d4723e8ebf7c24739c4998df9065ec6fbc47676287f9c80e7376581d3da7deb852e390fc376429baf72fc721f97b709ce9c6d9716a921ac69e2537ce7e53b9daf8586d96f0bf2a53e8626d8a7d585bbeaed420397a6449544af9f5169570d3f64a6853ecaf4c9d18bf861023ca9300b83f5f944dabc63f72493a0121d09bdddc208e8652f4bb290d3fa3fe7ea66e2ea4fc257d4f023f2568fa79eadd04bf900e4f544243dabd9f8d95318b3efde1dcebbcf43ccfa35dd90ca2f10d7ae27444715774775dd72d772fef8705c65866d69225dd92d2f0e316b0908490907ea472c6b19652c61b980fb2003cd3a95c9765383e2c1be76b7c91b158cc7fb07298de3c2f2a0831efd5c2bc4765d33c93e79f979b66d3203d09e1a5e078d9644500554ef3e16514cc4b1372bc94fa1b5f1d076be9c101402f9bfcbaac8f746a2d3f91fcc187e7c0c8a1acb1e58afdd0113dc79d659eb3e3903487f47191483152f6430867286b0ca4f8a8442a144ba4899e04a153088dd0cc06010dc31460404028168d07240251d5d40714800e9cb64e54a14ae424c8711032c818630c310600008008c0c088b4011baf7c02a02fa1fbe1b4d32f99d7b62afa7fc898fe216df96c1755fda153a462695579f9549042bf752c4cdf1a464bcf8197f6a81e2f02f64c79f312f8f6b33778daf93e9f1525e570f7b648736655a8c5500a32b7c94479e040faf4b24159a64483487f20872d03693850197c8bd432289043476c5404ef57d1af89a2615e4b70bd7ab5a20f3341842816368b8b1adba3fe817f8e13f592d5b9e0c1fb251eadaa7cf96ead5a1ed3fe2061230dba61a80703c0513be8426d6778c535a744b8e2dae994a3195a018ee2da7edc753a170744dd57c4487d7378aec6701581d14c6f1b4af5481745494383a65bb700b770b8de3008c1fe13f3bd73b40a4228de0ac1fb0b029ec83a31b1a022562a5af60580c774a0ba5e183d165e8c8b6eeebf47b58352a943542e8f4ce7567aa111e6a56a5fa17313ab8184f43bd68ecb2e2a2b3851eb84a3084cffe90c135656238de56f5b4da7e5dde85ceffd2357ed623497f49f634218c25bce0ddc478a3f32c5992c25d8ef90350f10757008ba510da1bc3656d52d9cdc20708a953a006810f8a2084f8674832cd98b1aa35d87a3a8c15e4b4c6170b062d3e7425f3263eef65e9a0dbdbc6e61b71e2d87ad16019d1d1db6edcc590bc39eccdceca528aa2a69a8b6d0deaad868162b44c7432db57a93ed6bf94d3c628d032f9d5723c56fbec400a8cadf00dd6b12457c8a6c5fba3195026be1c57c76282c03e0986a83473d40c827baeb3422619c14b5009fd7ef3c2d02443b5cb97e12ff8fd7706ef009b8994fc01bd4c7bffb7322d19f3f3fa8e19d71b09be2770a68e1c10ea417b05f3f8aefb701440aac78792752d7e46f4e72f7db68f6f4040e8065681c6d2c16adf482ac4254a78c59759f2c6ca89de73a5a991252d5e87f86e3448c60aa80b39934c04a24f5debebbc791d45ba714e9233573b9d69749417c471996c178a9ddf1b74ab541d4bf5547d832c24a5d9458d26dfbea58886bd8e0a2a40c1bd4f016577e7fe1dd5645e87e801edc50cec969d834ebc5d1c513ce2db67b15396c7b59dca586d80fc4de8f94b2a13fd22fb17fde9cf5ab55a63c1583fefacca68abf01389f6a236a6aa385fa5f9adc4c3ae28b4eaaab6295d66bd4d71833a564dfd76fff1f9cd46951654d3be5ff9fcca22bc384d8d30858775c75b1accc89d9a9402279dcd0a6ea12ae4c3744eafaf6cb3f4aeeee2f03440eb30217919845b215177db5e8c30f642f484ed0090688382a27e7f7c48a85478904644f79a06833465c8f10baa982f8a4068bfab79a5fe28c38f18de4b041dd5d1d5ae934abef2fe697b54fa2512c874c30e494f9eb3550f64880d9acbff4eb88b4ae27c1064c5cb90dafbe6f9660b2863e8f0463393cabe89d4cc59395a89dbae72c9f7b854b039d0013b5b0c2e643047e26968c3f4ee89803293e6b5f4a24f2b30fbe708bbc2678d55a642c2a5d47a50a1f76fe9e4385a403550622038524edeee8cecf77b1e3bbe80f9541f95b2ec95138819f61a77394a3a727417e468261ba66e6e887b76a9b4343ab9117b9d8a21bf01c898441234329d92eb68eeecdf7fa955e342051e9f72bfe5508fe19f4be0e6eb0196494f65077fc3997232a80f429f2c3f2145fe8a780fddf20dcccb5b4648f4676917ceb2afb60e7947d0d2b0c5792c484a2e8144452259d46753fdcf00d7cc3d56863e399adfa866f04dc0ba07700bd01a2f781c98379d376a2c89b212f1f4bf9e19e84f00c143b2775095549d5599a986eb080a62f7c16b772006fd63d18e2d8a26957648530f3ceb30b785eec719d854b868bb803757a8286d8ef1ed0ffb66b24b7ba60767141007c3788b0504b16c9a28dd9f7adbea23ee54fe8bd15c9fc899681b6ba72d34b9e84012e20e30e32183df021da4fb48e714b6b8d0a9546d226fb2c5878b9fc22cd77e97be8a5d60e5750d72f07262f3e831d8bf19d8594367203c5144f3d07015cd1aa15abafdfc1e694ecaf5516108f59f23f8069cbf5d64b206ddce2322622894838454f8511c4460dd919a62b877987766a50a8cdfa7e976d932de014665d46c53796e6652d1aea77a325473b20ff1c80836a13d56fa16bb47fd7ea0cebf8119207ac18d5500f2f7b01f080f5cb76a79a1f36b0992fabe957f1f500ee113939e61d06c501a8fcf371adef04422891b6f9c7a80bc0f30af3638af7302217e1ee585dc6f352b0c81c449bc49df60a8ac754c1202fb6c1701b21173e9ae400473fd8980a2d3c6b23b1c4d203bd2b3502a2eb9923ac97d346364844dac3c8fd78720d13f70eebb4993d266f99c002c9b0584c960f518e4c18071b67d2bd0eb12af8e0c78736def06c39e71b0adf80da0b68d1ebddd0a706e07f207ad183e167e734b64706c752b9eea98a012732bd87507a414864a71f7e0fcbc3e329e08da9f5c263424b6d06012b46646fa1787413370ef74e7a1f7a7f09835e241858b26ee1914cc4d08b34285aaceeb75737a1a2e2cf7e9960998fe03f9fa2875ce96b2f85e7a6840d2d53ef4760e3e680be703145b0db25bbd8bd3934de5cfbb328e3ae04d5c6e0653b061ff4f7580107c1b5f98289c3d7af68f822aa201f61c03b99aebbc55b730553a5f63d92443b6a41ebf1b935f6c08f23bf3bb0680f711e29f306444ffca262fb740a5059a784426b92f2599f2ed2548204ede3ededdd980f62405f01f4ec935fdcd644c56cfda65d02bf9e87000d4c28138e4ac4540e181b4c19c0b6e5dce1eb9a26731f47b49f957fc3ff79ae72c8be7b66e9c396f8eaa4f49d344afaa00e90a242d730c734649cabb26ab2159580f3728a20c45343361ed152f6892a372771d12c40b6022809a50b032c2447b51ea89cf2094be1b8a4845aea263e9732c8add004aa09113d26a6755c161371cbff143bae25a63af1ef331a0423ac5e17c180d431e457c6dde6f5eb202ead50c4b6a914005f22ddb099e4c23270f2a9a6219453430c2ad048b16d4d87f388e2fec1391351709b62c2c34e0fd2eeb064a6cc37b7829705ab313da5fe80037595e77caf14f6f9d5de8d84b67270634b91528552b4f740331b194a8cbce623fb50394f232cb5ec456dcbfeeb0965fac77d3d823dd7827de0067b6b69202c0695e4db2d6b8d1d100198ca08b073668b98aeb65902b759c66eb30cdf668de06671ee092e6bb67b87a0fda076cf4515663715766714bb5f27d9dd824440acf1c3d37f24d611e1812eda5c2fe77114e149dad5b6a8a19280e4375d7ad4e7a89ac2ea45703150483a85ca69381a511a61330c1bcf1893d55c33ec222e81f0c30ef962d715c746e86eebbcb42473c8e1426381a6d1a6e4582a0de68a49a76a91c39e187ac08bfaf2acea53df28c67ae5b43f61cb05c97f0fde26e6fe19a7c3ed2738b91a542a6eb5185bb35a0deb915f9727a7d81cf9d6593dc2c3f92b72d540588d7691df35895fec4007a3c4d7e37f9a3c955d4eb149adee33d865671a6e3a373a132095d1b79dc04617e88f2330b5b3200c949aa80a7857edaf5678cc5269a2857755159a2ec8bbe02c1d897957a5eed5745669500173de88e7620a20668d5bae6295e763e1d53d62b23112c85dfb116e4386d9b52c203a018e4c6c9dc99c43bb2bd82bf65c4926e0442626e8a0fd60cad45fc94d57cc4a67fdfdb773dfd6cf1928d2e6e5f3b14d2fd795db2c50a35d3192b8b79212454eaa472a6982a88b76b53cd9671bdfe5f3102a31af56c96a292c078ca0c0e42ea7ab32f8d5081e9e8c030ecf3edd201977885ea48ea3ab135a62458b5df9a1a660f49a80f63b1a949edf0d467a7dd7fc63c42c6e532464332f5a45ebe3f7919a17f98cd1e1c4e8afe682250248a81f8dbbcce37b971874807b834f483d4cc5c2ab3b0bfcd627acd5a4d0323268600bd28bd34fa50649ab71904e71a68252cb800795384628c5e11ba9f690a8c042e6588aa0319c6dedd1ee8b9828892ab5d6c8dca33825caec0cea2dd5db37b7a9364da678a704cb7ccfad9cf1cd596a64d44dfb5d9e2dda4836ed27051b2c16814fc7c7f90c6d4bc465c2d52bed066068c6064eb5907380938e0543c781e86c16e9bf55af1dfaaff97c6072d3e9fe57fe73b0c40fc913ae712af8a8f9486154064679f00f46801e259a4a00a0d0873956fb26f4b5164bae6cceede07bd895fb666bbce376e387b3d36e9dc50c7ea4a36268c3e5d087d39e3644310575b0a727042574a57c62ac7cc65b874810f8577b63a513fc4da0a9258881c114fe2842db24749256910d4c99610558a48188f271e1866f700cc6ca0cceff3666dea683b21c6090c29db9203299381956bc68b5198414dbff80985903c3bc0b2838076d8a93bdfe9adaa0d2e9f0da6133cfc62404a9560c75b2c736be45c206bd56a98beb06564f6f77af14e2bae6f009c7371eca13a5bf4114d5450fce119ab3572d6040dc28761a9ab8ca399f67a380a0cc4f78862fd6f81efd5689732a49ce54df24731c462ed9a1855966220d380b32bebb2d53f55d85c98e4b6d46261820f6a4ddf634e9f46e02d66d01a145b6b918746324175159f3eebe5e128c8699ff96c92205cfea63b74476705c13d934aba3bc7cc6bc1cc6262d6ff17f94718c08e2b2767ec6e962450833d4c882d3cd8b8f286c7b1c45bdc74d92a3ce9303a47c4679ec1c8530079eaa354db0909015ada4229ba8a98866da128e95e490d9ff97fcc0c4bca26fda53e5c5d109a6a1103b4640b04f5c7526c98bbb15339de2092f4c6c3db0f29338c562764100491993ea7c6b1f1fd4dbfa304cd1af1be83de83a684e714290f5ca2f7787b003933e8b0e922284e34eee299c651f1d451a359369a7c85578123c198d22e35070abddd6c1156081fd6159519adc90c45f2cbaaae89b56a1188750c9b766a1fdeaf8f1619b53e0af943e93bb8f87ce8892805fd203ffbc2a93aaaef12818436bd5cace61eb43da626fece284452e059dab60ba9c10099d3d324a144c41f5a74e0cad520acb355f7551ee6171276e1ba76ae882f8ca50c23caaf4c2eb312da84c367b0540f4322ebc1f93e8d455dbfaa17e9829346e051066e135cb7d4bf14e697707dd18881a12b370975be93be3142da9219906bbed24a6f18a860560260abf0b22a6ceb71b50239196921643bdee33a3f308c55d282557dcc2983aa44882d1da6597e22aa6e4e865954459dd8873020c6dbc4a65d5da57251bb177f340796bd8da63947c6ee219b58daff93bd53103c57144ecba24fa10d72c7f8df442a84d97fbf44043319f091581e010529b2178920148ddf522c90c99a48aa1625544068c9134bfed707d9152538568a5b2ac296d8a2fd3c90f6e876a02585a2a9d265258cd83c631db8638981ffe150fbaf5b1aeeeb346877d925179dacfea07e7cd3a05cccb311465b66f131fe2ad251f0b4dbed1b87105b0fb46aa16f90a53c294b06acc2cf6d4a34dfc928665261ab77c00be0222362d8baac6dc6a40d7bca78e697390844f779d2c7c81e995ae7eaed4e7bc8cf365458d2a6d60f01c9563e9d48822952ef92223c1b7959e204e95b93e85699aba5083cb8cbf287549c65573280a1abedd45df52f9ac45862b8e1775645d4ab1795f51f7562dac283b58b140743b63783d19a629db97708e889d6f4dd0ffefe56baf939860ff9ed02f33fc2c317da209c0ac21b9ca57c4b7ef67269747dc46a5d9bdf49a291f61f59e02655bd61d2d758277ae74890b4f71e899e450b8a17eca5d642d48496981b5661f94379aac5f51e7420b7a0b621ea4c6687e63cdb8fb89d8002f352125851717137eb5d31e994d3fe3e8d044feefc96787e7d2155548532f92269afcf27efda70545134c0c4529646d45762c697c05a1b06250b68bc8d8ddd5caa031fd4d1fdb1aca5b6043b3d65aa835a3a82cc40d1031c08007c189d837ce74e4c711b0d100049f7ea907c35a396e93d8891a5b18f15ba30ea1ce1336898bc12248ca454d645e3193f1f17080c71782405215ac04ba485daa0ae3a284af7525835e32914aaf22b3673f60629409f1e891032e88c33aa31f4cba1a2d0e8ec67f0a5d3d97ffe6b060e807cf6cb5e516a7b1616431515657b4124fbdf9308b3da1766324fc63c9b62c86d1e80dda3206e78fc8df2431f8ef49f4ae0c3f4aac455ac22527f87ffcf6bd6b7e55a5b53f206c4120f808b37c23470e8299c571bbdb95cb96864bdabebea2930e42120bd8c64b927192b226748e408c181f308bb7667f9384c95ce6e0f0457ff3e1503b05ba4c6653619c012f2419791c0eb5534cd87f7d417fb32fd87703d70bdccff054db10c3df2d5f307f2a11bd5e0ad20e408144b60ed1aee124984c525f40bcb8016430faf36ef2c1fe9dd2392f3d06e9d8cde7dd0bb739a4ad44153e52c9c7033853fdceb77d106151175e2268b26a7b3dc86025c9722cb877538e2a104d54ac215bb1b9f823aeca42a796d1ab9739d09ad0cc1591cf0aed54a5e848e0ffeb6e654b3e08a18b81ee621f28cc05ebf700f525d53beb2bfed0aff83c3cc2de08dc58198cb3c2bf58ce6db1ee5d5ef010a806390455afaad3c9e144eadfcdf7073c04333f147a19a1e90aa913fce2be349183b242ee523cf19713a43f961a7f28bd58b1ad1e688db48c1c16856e3e6377b8a727f71f0c038ad05c201284b19fd012b54274e2c91141a0922154dcc4cc76406b2cb40580600905032db142d7bef036970a3de9ef3c43b2af511b2a69362a15cb4cbe6850d8a7a82c02b8e1b6c4a9d19a6bf22c907fc3e65be6f384ee9cc3cc8d12b338d0522c91de558ae2869d04995846dc69d68beda0b179be7f7b0efa887740c307ce38c2d5beb9990849af8529f2cb99a05c441f322b43f495682372cfee9ff25706e292e4b666e2c0313585d7cfb2c97019cea0949a1355c484ec5708b27539f0d2870be4edfcfd76149ff8bda09b6d555458cce62b7089d48b9fac02384f909658c9937f6694a6b637bf7fd8b66cc1b46d04eb1f610c5069cf747cd04c76139584adfe83a688aa8bc1eee59184b274002ac16c88a31dfd5059827516e1d446107001c5a4efd043565aeba5ecec433ecf7517c63ac965e94d2c684ba45185722f838cbbe7ac9b45491c900ebb3e41097467d1aa3e6388e324ca98b41a61747775c18c6ef35d36a44fa823f25bde957387213d0192a2da7c2c4987a36210baa224d423117432037e6ec3ebdf6427d05f1c1dc8390d40987b2dd60f6fca02544d2ef847d2ec17a1c8ba2fe91f1dacc4411300746ef95f720fe730e26dd37b851a8bc1a6f26bb9e121ca4f980d28922323f5ae7926e6a9b7d2285d43307e843b6d28bda5a1717f663dc9da4a8c675bae683ef53d5b205c17f2267def5f7c53143f9ca230dbc63b07a107fa59a635c2961364486352041e09536b418eb89653e513d0940952c1f508e8a940849d767dfe1d7366b176737977267285bb00e67c519f127eb19a67239dc64d481cf7988f681c43ea2493b27fc412f2037327c30f119cf6119842fb28a3ba6d95415ac83074d41aeadb419a33d945fefd902f6bda3734d1ad524fe3e24513891d2202641ea4f6ca62d2f51ae349597907f44ee910218f0349cea14bc7ef424d73c0dcd77a1dab61e426404bdc28703071c68512b4753c32573c593ee3bc0a0b1af338de17d9a11eefee8a511a4a4c4c47040a44b3743b1ec3b9dac711943b8c272791089566bea429f56322e8604227d66e10fdd96d7f643053c68512b3d00f26a4d95382bf2e919623dcf9cfb6bad386036fd3a5d9c3953e1d03a0d0667447631eeb6e3e6eda4dcb8deec671afddbcdc75bbe961c8d71e4e7957c1f34dc0bea877b7370fef9761d9809d32cdd620abede66e456f32b8f75c15ee88f45472119d1bf7404468d1d920894640d6cdae5217e746d0b67f02b89e76480df1e22e6ab7f0f989e75b3f311c6405a42d0ba45a68d4083f144cec124fa26b22d3152fcd152d3b108a72faea2375748973e21c445edaf9c1fea33e5105ea9a488e353cfdeafe7ff2c0884983858c0af31c34848a6b013ca901fb186903ff36008f90de91c6456f0685022c39ec1400f35904808e934498a6b9eb8898c2a834cc0031332752102a2da97c3779f2eb6453a48008cbccce73b396c941cccaea538df7448cb1125a51fa343156972674d863d182b2fcd24932f26641cd8fac7be568b7967b72b4e8e09b60912ad23a77e30f86fe8c3ddc446f8ea34fa5fc8f3de4f935533f522b694a262368087efb3ead00b41bbc31707738b0a9ffacbd048af586d8360abe11d33df5ad8c767663364a0d6f19eb5144b525d532da304539d7d08f5485ed17cdd0524657addf6f4a89c90d2a8fa24ca7c33ec03f993710f4cb8f4cab643da394a26e966bafea06497c3630c7359aa323b1ab7e359dc74c51494a021cb73433f6f7cf20a35cacdb549a8f9d9a2b92425bc83cf952c6f39c54fee6e133441bec06ab36c161fdb49c0d873c11610c95cd8895761f3ba8e02a7c23ff59888d0050754252421cb43be5641d742477ef4db2e8193dfa1e6c370df547747ee4d718be5a5cd189ce747bb8ad1ade8fab820c46002940e94168b6b986718e2e358da9330f86db5327aaed9803424f6b887f415451f45b7b7101c7c29d3bb4e3e4e5013a1fbc8349bc86cbba571c2dffb583ad39cd469187bfb73dba622612700ef5db9247c02eae2fb0c2bc9b5b9e86a876bcea9e4418a55a3f23b6147aa1bbd06a9b7e71eda11f0c3df93254c6490b5b757d0e58b1518b1ac6e7b6375cc1fbe0cb1b6efe94a087e0acf1d344b3102f06291ba12e072a12275de15adc6b91c101ff71f2903356e87f14113f6a84db524aad5eb6a5dbd1e837f024c3c62ec701b6333ae17e57620f6852bde9d9a94570273254350229afeccd8f5fa13c7cace8665423e825e9b64c6b72201e03e26d631291838bda51bcd58441f79142116b536bc58a046275df4cd03952e6f301e163c03510acb7ac3c41d4a613841b7b5237924bee5d72383bc8b766dfe847dc83cc702013c36552d0913b766f98ef168a37d08f08c56edcd9005f6dfd07c920c4c63be3dd8d764fc1646f0c38c8352dc64dafd77894dd711b836d94bcc6af9aa30111a22e48b210a0ea7db0597ae49ef70d37f90dc76034170686c994c383c3d122e612d6b0c94d97a7e7c8c84df06519c081d89ab3f13e52c81d47e13d9e62c6889a597fba2792e6614851b06d500bb09bf87d24c9c6fb0602b1d074886357a5bd390409878b93169a1a909fe76e96fc2c27bad6395b647d26a0d2f458dda041a1df9d3d35ed519f12c1a421e9483b1a5dffd98a0057cab66c7e4bd8ef53df5aceaca96022d7a29ff31abdbb9945516bf228e21ca59ac18ce8a55ebe6fe722313b1d1465f542f8465f07210518c48190837e4b07ecdace3cf3b58531b2d9ca8bc0face6180cb762a56a1141e5198e264ab4815f1f51ebf66c59199869d2a85f7ee14bef8569145936259e77f47b3df611691d39a2ae844af00ea91bd1c5c3fd8f7147c3e46f6148fb0d7951410030560baafb1d5404ab219e8ec0c44f2815a3ca0cf2862b05918d2b777fa517b07e0e1548dc3b5d7f082321ce9fe86eb199496efa0a5dc3c9553bac8d9937975466862290e7f044856993ae88596df22d1caf2cdd98724e0fe637dd57d43433bd6b010a4cc599930d40e53b0feb6793a28b0ea33bf06809f292f10808f4866b58da8b455865b63edb06ff45f32838a9428a4ae6a79dce62acd946d49f43a52dc583fdf389c5958addacecc847cb13a608678439a85d97c39a6a87a07207ea13b50d128a7629d8b69866e2c9521130194ce6f5c84fa5f60b9441f15cbd4e22029394510f78d842a75010bd87faf40609f16a5f07142272f5c0e197a4a5e9729f93b184b31f12687c2c403143c1aae6daadbca1a202ba251de382a4e02d7d90f2154f40d1692dbdd9a012c9044a67cf1cce746500b98cd2b42b61bea8a40049958aaf58e5d0ab3ae17db0d725677f9283d1c8a2cab632edf3a5deb14ae78b86edf0108a2b7f64dc00faecd93367301957597ba94a24ca0bedcf5d6c36e5af656e078fbc9302d830b764720db1abfb76606710afd2875be909148801ce08dfc7f643799b3aca5b81692168338815d8f6125253f2981f8b9dd693a3e1577060e52c6408b531198835a000bc70b2b502b81b5d274828b23c66eaad03e161679ac5c83cdb77b36b17bbcef540d0a0d851a4e244a05bf8c45de0ad7d9f7afeb9556645d4374efae9f913a839d0f5b1dc8a0e1a0b65a3d8831354be6e336e9ecbd6989644b763ac632d84e739f9682dbde4c6458fc9b430156624e6bf838f2326fa15cc5160b75203d77168461d33dbb20ca0577c1bbd17ea447f9d7e12e2f3645311ca0b70b2a7744394af663df86293463144dca158de1a996f33c018e105b945ac325479e8608ba91b301105204ac08235ed0b1aa7598b69d5edee918791e8ea7d77537a356e4083acaf9dc7aa4128ec8072cdf72a33b0210bfc514f0549f22d335cbe8d0cfd07c06253738bb74c60835c58f8294fe22caae51bec904a7a744b2ae1c50823ee776b918e7294c351ccf110cb47eb765f4f4e0b6f0bd3714bb270f8176bcd88c3b3559b79113c10e36e24e39882081860b5556bccffea4468ad586ad43e32138962ed520393973118011ea72da5cdc10ee56701aacf59b95db19a84b7e24f20094371abbda7acffb6a9cbfbdd8fef07fedc5d7c34892ac2b475ec39053a5df21c8a59007695b25a9f741ea59085c16fb5fee68dde659ee4118df4913a9a47120c581387ac5502661d2a9d5ce8343bb825a7fecd96411da2f63c9765e740f33505f44eb435c984e61b242ac62b822e017e65808cb2828ba65baadce5a2d966fd4b84f212ebaa12267bbb95d197fde2ca7f36d39a1c8eab896e32c2fe381db3b39e9d73fdf85927344a7ff0dc0b9687f2fddf34516cbf4fb2c1bd07f3a300beff2f297652089bf83f232de3d256fa9951a5954d7ea2f653a2fc6e87762d3ea8578f1df64d5866d08d527916c821aa3397e6ee10bf9a5c09ea923c8b2e06dabf1a5ff0f37f80b6a558130d9af1af5c5d259df1b6a13f6d19a17a4fae6c4b79484c26e2e0e8fd6b9353ea84917e060c62b5827c556948d2d9d0bf5b38e10a5b8ff94a63b37ee7c0c3f5900867059ff83c993011164020ae9d40d1080a199fae10275c8860bd8a18a60a29aadcb0576c792cf9d3b42adb02d1702f1e806cda89b77a1a45c6c478812475a3750d84e14f26c4a109ad61ae0ea1dd4eebced3bfa2e54d998cac44eb87e56f8426582aafa8535fcc3415419ff4db51cd4d9019bd92030d49def76e801473763f33b23899d7885a1f0d0d15b0d8ce8d004bb4b5b8a1a5b76bbeadf6b66f01c4623b3e8d20a89b1f13036db2d5c414ff3ab66290511990c1b59e9b8fe4da158bf0eea57098322c0ad0c08cd0991d84c38b1e249257b23c54a2e5ca25876602977b9eb21a5a443403c59c49102cb7492272c6fb678dbc285130d6d9322c6bf57ee5b39899570c1124f5d034705d78046f116944f6d955221792cc43867778022675e92ae111871f503cc6c598c0ba3714a61ae8e046c2a64212addc1f971f308ae2e91f12fb70f8cc14846c19f1d28268ddd324094819620af220875d53b89421fd2025761d7655285a596f32b856031b839a76e3a491f5f2281c3fbaec1b351114e056c50dd0566ed6ba9988061930fe3ec222fc6a8bf4d5c63aec87c959f472e38276c6a54ebc94a60899507951181da3f49d4ad688b6aa1ec2b42bc398664cdfbcb7a44b83e726a3b4e3d4ca1c5fa46cf40ea3b8556561e563a16c2450fd6068a34f712f8943ed60d9666c25e4d296093cfec2922e21228d936a0d1760adf16163bef1f3318906d00147c33cbdb525a274d7883d3394308916445eca5a141cad84cf9d5ef6e6a01fe0b9649e00f517fe94b250e3273b8f7766c2c7f8eeca1c687647d816d9efc640dcf2ed240b6228330e080c1dc28bf85f3399a410efe99c8d1c36ae2f37ca335d3cce4f8b66542971f82bc327e7d3183f38596adef1c6058160073f4ad071034c3dce1bda361608751b76dcb9d5c06816225a7eaf941dd8b9e1de35da3afbe604e13a56a162f6e9fe0afcd6a2adb6121230b4f805abe394d8c122ab03ac24121b1071d33e5bde4e00d14d2d5f133bfbfb5dd2f16bd6ada7821af6948d55206f242bf6b2c0b29832f7965162e537e6e90393785c2232accfae34cc72223ccaca13e8f03b3bed01bdc01a24cddd19220557ca2f35f5bb9fe3faa387450cbd768919bb700d6355613fd0849c7350a02e25bf6821b02a08a0abd53a5f0f55e5c62716e6d0272b63679e334939a2a996d3a8f9f0e5a7efe7401eb40029926d510c66f8ea9214dfa93d9b94532b827fe722f8a242c7ca00d396bfb698a19209ddf157c09a058f11267ff3b63679ec77ff33272612b85f3a22c4891080bd5acaea6612da89eed4961d3d729263f2b1c2a223ca36f2a2abaa25b1b2554f29eba5232617ebb5b667535ec41d6c2ac566417ed9eacc5021126a2ab68e4b42f0e3e03732f3309aa426ee3b735a51c1044f6abd0ea578846a4008acb51f0c9740acb36f193dae9203dccec3845835f3a23f83ff13995b2a1d8b5288642d86c438f7b55290448e027155da101eac9cb3930c921722f757257ac98423a2e416f0f6188fa7cf60de063374a230186ebdf14c8d9748ed0844953d617a51d18afa89f145a5cbee8bf1c3d3971967cdbf1c8fed9565b27c13ef16965f308102f3bd17d6c22dc17e0042523aa25d4156c129a5c08ef8c2e1d7ac3b9f7180ebd1ab507ea46b779a1444067b5366ab8049465866588aa51e86e9509f875e52b0bc14caa2fddf014da58b812621e824664aa22453e71cafd1f8300a51129ab5477c2335c5371c9c0d512bb675ffdf53941b0ea691976dc0655c0f6f22dae7c99459e5b8b4fc2c477a508b942df87e2525f18b0a0bedb1d99192ae452164666f1a6f32e5a1ac5c06db2feaf87b6911da179dbd6a7f1ad28425eb668933c7cc4d8a4581fa5647e3e59fc4e9e3e4ee3374183ed760f24155fd1eadfe4a6333e77338ffdada383a01ef30dd33b9c2eb05b0780732f51c518c652528874b11101ab8055a4d09ce65d951b28f0a4f008aae09998f2cfdc52ec15ca9e53cf745b4a7ae0d43c43e7f5520600addcdfe7359f5ba2e87606c2a5165ac07124b8c1338edc6828c9243acbab14344e46ae8f6c14aa573cfcb76ed122de1023ff1b47b68c5fb1e76bd0d35193342953f22b2f263fab63f185cb32ae9d6501c5b019d03682ecc4ec6408a7ae7eff0064ed68c7241fe8cce7ca2a7f62ec84e8a0683a70f4623682b1cde07c0884a67871981de5c4d1c2d04275eb2154b8113e2bae438bf80aaab5078cae4fc4a883e5c59274c153923b2612b00a4b98fbf91370deee72a8f5cfcca4e2908e56cb2a22f3343cabf28a96aac9d66e783654861fd885ca4504eaea752b8999d40cb7718fb8248abe00300f7064f8c99c316ce225c1835030dbc04cc84e14b51d465e2530241ed554f3d1e7d2c4a6cd26afedc0183ed2ae9a6897063d16b84acd0660604567e9422ae446b72fb5a1a36c3faaca089a1835fa46a9ef8afc79e7be3952a6ca85af2480db54de196ec2d298d0e3c9327ef8413e1fbcb61119b08560f9abb76d2991a5e9f67b65ae674c3d6c7b018620910f2378f44a0ac124f501fcac6e2ebd05ce848ff4c859f6304987669a457c49bc33fd832a7d9e051edcefaddcb69fe6626792a080f4cf48887dcea4920571a5c20d5dd4bb0b8730b29a3e863128e8c1c2c9285af15086b136b7fcf1ae3e92b81a383eaa790482ed94b9a4b206bb6e144fefa62532e613261c4b0b4b90bf963f1931e61fd51e2b160e914a3577c817e8d3b8d43b9d12395b37841d0b0c1abba432917fe56f28cebc2e1cec800e84c30b55a2cbeac96e82e62a9ff5ed034ff3e6d9f24f9accf0c33193c1960d8a3b3c091b73f22cded9b25a0cb6fe2c0c74e8a534b2c1c1ab2f8ebb59600bbf20c6a6a1998ef111ef1e54c3c0c057af7693632ec85e84fc57dc0a6da7510836a032d8329eea382bdfec8aba8e860a8299b91f77cdd9634a3f6ba4e4f2e0d02ee2e9771487a46bc774e004b9bfa5a8f395633d8e0225ac295bebf62da1ff6d1985df0371b7c92c9b2b6d9262ba60c1c6cf442f16777e262a598dfa9936021a21bbc0c00790be5c0106d237bbb9b018786745d498a1826114b0575d75e54a2b0754afd83282f53a3ac8a369e0ccb9486a74c21494c40696e08d2af555409de89d4b8ea5e0ca95fe0428e79e3906f9d61e7443c48e6bcc73c93945df5c161062c2ac426a7e816c333393850d5a6a4a5907cbbbb01f6ac86f1e37ac3175f0f41fbabfae80cad8c05a415ffc48dcc79e64ba5edb3e388261c4ce1bd9337e498769576057da935aa59d180b529882711a4d406d990875023650d1a50ad95ac42b184ac0ce3c641e29ae4d807f07b090d4a6cbee5d6261e922a92c395483f0b5a02c853f1e961e3f4be44fd6289193ab506332c51d69e117eb2ec4519634585bc4d1b8fd79118440a7efae3debfec402eb06e1f45089d03b1c1c339e1f47569b7b494027e96b3e5cd17ada2471c8d59442b213c613ab0dd7a78fdb9f9171d50cac28957d7e0e033477182b0cafde449f6a848a9c9cc0a654211f7a854f5dbde31e18feeb23a3a7c99d89e1a57185875a93ca7783917719dbea5ffc7a910bfe4b795980a54dd4880040278105a54d0ec2e681a5a0a2cea7d536f5c2e3969344c4e8483072809fabfed7b10b7ca023e6c4276aba07f52efdd7f5b6f2d158004922269903b7f761159f42fe8ff0840b66361b1a587ddabb5521123a4866025f02efb1fddf630eb3c20b2cc09c790cc8d2616cfb7329ce27f5272bd24c4c0bcb5e5d1183848bb9b5f116870f818ff4ef63052a8aa17366bb4bcc86ccae389caf37a0a3e351fae2c4e5d87a9641ef791f226692f1b2ae618e57f8f1a7c5105bd173400da6819338fb21c5ed49678c68bfa54a5ffbf90acf970834aaeb34b4fd70be5ce21671f1db6d8b3b232916e44c8efe69290c118729946aa3ad45a076e1e2139c97e4c4b101ae1a40a91cd2062fa323d9eac3468f07589bb5d35eb349b261abbfa0d4dfd3ad2f8b2150f1ce85bb916e05e1ef7970041c6656e730ee282cffb0cc2290361324deb631e8b09986842e28ea120c6e22be2fa9a00c5959a9e43d198f1666d40f26c867c2b9833d3ee8262533571590f8b65c3e1abe20ac665d3de079aa2858088d8adebeef9fd67e7e70474267dbcbb392985d54723562a5d7ae14bbffe730c642a96d752f71e39913ca24e015bf902c0caea90bd16e96ba3a5dcce41c1ac48dfbceb36bbf51b66da90ea66b85e35c4e7694864e8925ce3cabaa580c8f1f0135b50a8b7d50b10e55302c53fb4bfdab70f004d435b4652bac91fb6eb4745fad2b28b458824dd6ab834535acc72f0f0682b5b8e3f1120a1656cdb7f8839e595b620b9aff99704888f746288414abdc93ad24034c4eca3e354cb129713321dc360d1cef032bbf5f5342edc2fbaca6555327c8652123ae728481c08a3d08b4564211a1fcbbab90aa027b88d698ba426ec31bd38d471b41e4414e12708d353f3c216014f991d44288d642adda9ffb7dfbe23810b92c7333c8c3b9536c9dc15fc7599843b3a95bf40242b303234b4bcf5a262a989c719b56aec27ac26f781634796d037a4fcb2695794171b5866cc95820e6433119a5d6d80d1dd9831e6c84936a6491ddd59cc8b5b5ac5be6f3322292754fe8a3184c4e5d9c1d06afbbeae2186e5c2bba68d85d3777a9fb21858d4ba6e3d3d38ce2f8f6286be45b86ac6482606e9aa1ea11e281bf211721f5ee520853aad06ba75105e58cbc87ebc83869a98b53df83cf5efb1c2506d38081ed5f58585b0542587808e57d960f88b00868ef52582c8d0c3ddc9bb00460b808bf0ea502a200d43951875e4f5e30cd374c1e9583275a4246ef945ecc80251407c6db439ead0b4ab15ccca6855a52c95f1956c633a0b4e3d81867363df81c9da8124d84f6605cafae7cc882e5a82316559d7e7eb30aa424a8f2d9d2ace04924cc904b91f09ac7130e4c35593ee207b03274777f0874959977c48be8693dda01a23243d8ecb218500399c2273284e48b8fa48c0da67748d1418d35b92ae87abd8ba873a589b3a3cf4bfcf8a1e2b595b01cef5a87517938950851f7883dc4bfa5459e3be73d4cbcd54bb271103161d2198649922923927c7743928129493ebc139b7948195b9081b95767030e71ce5decb93dd8f374e08bc54db8682a7e05b54bdce51a3130f9d3f3fa2d64d510aa083584d7f689b1ca48d62bf220796d287d0895ec9010f3c435aafc7f08fdae7589e55b2e5fd1bcc0b172263efba217923525856525d7d70acb422192daccbba6628b6966f947f86c9022d7f55e506c67b25f200be291a0b769df303edd8eb26362057a70b20ae76874a513dd9a40b32490b6dd74621b80948c847423fd061cff206746bcf3954415af77b9061c5d8abe6452179e098d24231e9e25067997a5d4ff5705942282f91232b93f19fa27c6ad0370a2cd07d2e5159eaa9bdecfe2067d66675f90d2267efab7e9f9363cacd2d248db60559224025096bbd435de84a48c139e2349af0cea30283608d458a2a385dc43e74fb03c3040fe687a5fd573e9d0192f309a233b0054283e959c41e0c60f538dd0589cc15e5afbd4da26bb88388b9b2a954ff008905871943b115a28a8871478e616125c38e46afc5b8654dab5b5fdcfedd7f0b753b0d5b67b0b940b81edda0867efc61bd15b8c0f929b8a17bcfba94c087302247ad6c617917f26ceff6a74e6ffda3e113ae60e97cc0bc49d9b8ac8503c57985da5cdb5b917acaea8250ec7f3f900f97b7fca882da48c713306c1c4512532fccf326b593a46a05aa9e01b9d30c9c245d71ac4201a064a1e4e7575cf9c900b296389e6698178c4c6a678f4394e50a000ff4f0165b54c21875383cde7435334e0b88d3b763381a213ae2101d04c53ff62f828f91d7337902c52511e0ac0ed1c83694f6330014cfc8d95184c294aba1345806c3667b41ac47ef2b29fdf8d5bce78fa84af518ea7e2cf329dba195f51a89a3612a75930806807bbe0cb80ba6897728ac94eda834124b9720e3443e1d37c991be621c3afffcbd4a9b58688a75f6067be93f0af0d9152c90fe2753da8b8b43d5767ac75da282d6c3fd1b71a1a9489c1bd71711cab4f090e459ecbdcc45cf8007e174ba4c5453fad1a12bc8b58a724c9eecb4e9098691e49c274df2d4b92474bdcafe447728d397aafeb627eba455ec080bf830f95279fc38cd9431755f7050d4cf23491a8122929e31b7bc228d2a2ca273598c48dc13cd941985e1231e2f0ef927e8200934d83fd0ff316409bf94d6c60943ce244d2ce9b8fe652737fd67c53b0099dd10ddb46e0cf2b6c756a75d3baafadbe4a8155fac1ff97c8dd2a312563d25095f254693ce182fadbf93bdbc1d5b54399b0d43b4bce59199683770e5ace855b39a517c35115d6f10863777aa30032b5929ed50955a75cabdcdb081fba7942e929a3af10ae5afbf77c7eb4233c0e08a7369fd2a42023748801dd99d6d9b84414894c8dd42cc2ecd225ec8fe52b13fc092170c3c39be1774137cf614e7d3e117e05e95d648765763b604c143b572c560a741aa96c93cfce9549c875d05e999c34658d54a130cdf863126f24639e08e8d96ba0822b364401fdbac559ee330d81b14a427f3820baa50c145f2efd091cb560d626632730380a63ccf70ef9437092458508394712885d61421d2214da206f9d5f672d206d6d6e3413056d34412eb5a52b0b7c37ffdcd75f3e22fd36825d7897b0b93eb3b554924ac42970eb684e8c1347e98f442a5d044dbb3f56e31e4b1bde268e28f2414882c46c1a0b65a2adea8a5f21d27aa07823bc1aa8c7026b03d56dbb0be649bf2320efcfa21d88d112021f9e262e52c811b1cc61b2d78ffd89382adc9a668cc2510ee53267c95b210a2b6610c6759b9d3c40e90900a4e04987233baf39eb18fbc1513b84d54df85fe28bbda20ae555058f7a6e13ce1519a91f78d24d49f67663e01be2f6b6eba86f93cb2c9f8142fcc1e2aaaad677636af5190574ae9ae7cf4817afe9f2f0b75139b035c70780fa4aa015ce21623559395ab7388e8ecc1763018dc783ce308d1eda0ad44437b4e58fef345608784117675615b8a2db95fb8fcea4ab979d4fbe08a621118af024a1a915246da6c0529c06f92028c553f001c2a03a9f5d0f0bc6eb5cbf712404763a02d5c894742b3601c0c1e93d08adb178de32df03cd95be63343881703955fe50f398c7a72c5548d23a7261927562ad0c212619ea106e8c9613fba38ffebf2684ae42a6d040851b31473bc48efc335cd000a6a15c62f6cdc667b755d0430f768e8b0247f36b2df8610ff969156057b43dc4f6c0bdc910121b659c79265a883b55663155aff06c7a7e5b33e81c157210222a23bae30dd157ae530bd74cc3523b38a582039fe058b53277814cc7ad9bc76e1c65c1932ea76c8d34dcc7584a5cf2ba9e576c22c4e9245a44ba71df510c503ff1005fc9a02d5b4490a5ff94d78226f03ad545a68767cfd4f191e7b1e1a33be873f5a206415200c761da02c066b99298e1714c5178282888bf2d8098fd27ca4bda6a5d3f221e547b75e2bd96652207e9f0740e327e847419a1b241afb3764d6da8b870dd292c4f30d3d454ac0c84e1689941a78c39252cee78cf574a5318eb8706f7cafa373ec469a998b366bfafc91d4174ecb63320689b7f932db380492525070e62612712658908b5c508b9b763a6e61127c8df619e3817eb1073c67da233cd4e870ad97ff2ad43ec007b53f90a0e20d5651e6bd5781169eeb0f6b24263ec4261cdde0c6b6408b458d6139cfd1dd85d4e861844e9dd36f4339bcbb08ccf931abaa74291c715278a53169248d914d6108b91fc8e6196e6ec7f5c2496df3d6955110e420a2a60dd042b80355da97d27978e5902bb5c52e82a049c8f691644b5b78c3d74a85c10a21afcddfd31af244e6d30e14e0cc41f734fcacaf9a091188184693294928adde3b2817c2796db1e05248b1e2ba858eec795817368db7a7c01e18d8208e6197fabbb1443dd6804256dd3ce000fb413aedae5cdcd7c857c78fde2adf47f361bb8bed915aa2d75dfe039ce71c75b559c35c413495c834509930c3a7d1c4567fabee8700de6b9e037c331dd331db5ed94a8b849d0aa7cdea4a167257647ddfee53b1e3e799b164df6b6cf8940e8535f7915fc4941ed328a15049a6bf3b20c6921a6d758ad8a9ab246a184bc9b6b458336656d87739e16b3f7c4395abd36da726028b1800067cc6803e516b8ee0118a4a094b70a9c67ff7178db297af12a60a3cb45c1ca3fe722562b0be942803cc68be0569e4e6690c45f112db041913dd012a50accab971475591b328705e21398d98447eaa288f05c8014128ff10d0cc94252e31a5c0652012457d288220eff51c4b4f37e6cfe624d37c7ef6e9e54c1c21a79c4fe41f4aa1b6b21cbd738e8d29502abb89e5e8f6017b27579a9bf12466c22c41440f700a54dae58d963439f7578ccc4bb2d252ddf22aef1ea7597fb7304eccd43fa02aa91e2bce67b06e7225866fc31cc0dbf6ce18d5ac49eedf32372efd350b368bed7c00668e9102eefdc77efa353ca6c2346931f360315145c5a1814a953dde44b836876d0e115b028f598d0ca5db361615be32ddd2b435d4c7966018872b4b59ce655b07f4b724c7b7e9efc1c36c4c7ce347ce05f22152079ef7800584b9888fe76ca6059aaae34da70216053e2c4e05c31ec1394fc0a5639544bc985f60ef25968136f70035c1060df929fc396bf17a01c36f976c538f5206fbc6e8a4150fc6df0f0bcf3605c7965a96d5478c749f4d0ef8184a429fb6e7e7eda0b2fa7b5b4a610ae09193ad14b7eafd355612116a1a860af494e57f95d4adba5daea4b8600d9955ce2932eab751d155f547f43688d047cb2f52297085c427f63b89a385a61a12442c2acb3c2cf39d39dd5db7492af67ac467c54d945c4b5ede0ed64f6b8bf60769c2210bc2de89f071c4c92584b8dc87229ebd2525c55aecddfea46d4149297410e962527593b096df6539b5022f66fa0dea1d06a2b328efb54f5b77afa866b8a3a08eca964739cbb1993d883b511353cf4c4082484efc2af4473eb49371d4d3e62e4df5440a20104891ec1bf2d59d5d4ef7a28306fa3de97156da72c9560487b3390b2bcb9b0bccbc48059c5fb6606b8e8936fd28c731b2cf4f793b85e44b0035749fc56230db45bf41b1611b891ddb8e74117ca60d078b449b3ecd88e613d8856c6954cf462de8fd809154d0e0e3b58d634a818e91731a6f75749846465110d8ab63ad4b258096a9c9d25a75f42d61a0fef31730fa3001a2c431396413e6c84e94a0af485fb896216e968172c73525fe3effafe00632c6388b94afce032f35813e5790450833d03423f758828bd8ec496c8c4d06c51cec1de474504498927454b3584f02522a8a087a371a8a9167341a849e392febde547ae8f15a186207ba137d7992753789e47960fbd1c644aa5fc1343967830646f4c043faedf2662c0f257198907cee40336ffbe10befec215f367528f082e4f92b9e9435d7313e922a18d581afe5168ceac051a7bf54f0819e5fb3d9ab99103c9c35f4f27f9c08f1b333febe71050d0622340c5e7cdb992b332274245f107267594cbf29c62cc5a51bba591cd1e462d0ce13b51861e710cc9b3d46c3755176f752096852ab8c5da6a4928250f2f0e58a39e31dd0f5ad7a2c15970fa1672f7431c89e6162f81d969d463ed655ed2c91375fc166c1f9560f35485b7972ff2be4855e57dae89a4b5c0f83aa139a6fd2bc4fb41dae61d8b512ed6f84ad6f553836f710a4bd7072fa76de3499ebd8158d559880602ea2959ce154109c60450c861158635a9b713c40ffc259350593ea4d0690c540d37db29bb166b96099104f8b42625f732fe64b4875fe559d2a97cb112aee966edb3c17db99cc8ed3d1cd62b0db7b857fdbc185c9510b7c6e74689abc599d84b7ec3dd3d4543b9288d1a1c92721be961f0355648272c40f04ff2152131a0ca11485933239d5d61d94159c5f8c3426ca579f48e1d7b001c8827fdad92243567900de6c44b9ecb299f3c6d90a8a1468859dca673ae3d4e622df8bdb1a98115e4136ee241ecc9fe5ffa1eb04e13703648d626e6984232be47084d8b8129774aef4be852c475df158b366808a2fe0d809f0a7670bbb2430db6a1333ec375d842c3d04e7a1e9f1fb828fea0edb58e14394eb3735b0ee096b3801371072638558d5e97ea2998720dd3813f1aa2c0cf4fe6267e67405277579c507b6c3d0be72ed44c95a1e0322a7c8e70f97d97e2648cbddb0c11f12edb97c37a52fc7d54a71457b49ebde0cad0e375826ea5e0d563c9b521bf7f1a63e75197724cd5bfc4654983a0aa1b602b3242e6f4887a338896130431a28cbff1a1d6524b5d66dfa219ae426209fa2f2eb24ac563494f148d1c3ee6a5c888543226b399b4f04592222717dcc66083709cf74810b1f75d2acaad3b2ed2f39c2e6a271eff473bb28c710ad80a0c3feec8dcfbc18d5e062a2d89162d15d342aae24ba42e412b1ca5c1e7201a7bb6c9c28c7f4e662f6a3e506e60735732b8ef27def67dbc095336402b7437d97fabbd2aea13907ad5e440340870d272bf00ffa550e65720391695f18048c1ca078765c756b297db6aa02891ec54f923460306639f34464a49cd852669d3934c2e58893972a2714dd96b6ed9cb4ab280c3ed09733ae2f1d10550940577341909caea9fd1017f43953e6af3ba1731822657b9b7e61f7b9cdd6a26e3804e630e68896484a5e63714009cdbdb5201846093048ca86e3aa8c26d0c2fc9c51ec467cc7503508f1f33d1779af8f745bb9d6b21c4825ad7e7c6651587867ac990c2f1d18bacb48d8e971d96c784eeb4e2068d33031e93b40dc5c10e419a2341b988582aad415527199105107436f4e7c36ae33d29cb312cbc2cde6309c0055353d183395898085f6a53756a6d69e012f933df3aebadfff73dfd20c4134ea60cffb8a75dbb3e4f626007020296f63cc545ffbc6b192ef244b38264a0ce542f66f0f923e093843db689ea8819bec1bd0047587f75971b887ac6bf1d72234d7477017b82800a14cb42e599b7c8c00d9179e003b296ab1c42caf089faaa7023a037b0435d3e981e39399a01348b29450f128dc4bf738e01f2fe315d20e9f4f059595f1dccd47e4907093cb017408eeb0dc58e8c880dd0edb56a87c4dc6c2a401041b1920cedcd7046b3470da422c9a0ce7c8e4031255365eb7d4c216c5af1f27414149b64f46e90c1c34de39fcff676dab104356b0245e809ef0991e326e37ce47124141870968c90c9f2c20eb01d313059c927e81f22f0f1e2efde2831944a02136f230424426ae4b89cdddbc3b161f09234fe0b8beb075564a32267cde42d061bcde8a97102a4b4aaca41ad7d56bbe26ca501081577d792dd5b0e73e620cbae45df56d41bd3617ca38a3c4037523e920a2cd434b1f104881fc8cadbb89cf9b7a73f9fc072de521d925df5d352a8e4554c5818d314a9d5dd88893c2a01b7c24fac6760dc9ee024c6eb592c0961611857689184c10c85034c56e82565ec06c84a99d0696fe5156b30b4138aeee8d79163ebd3c569cd3a846fcece037da1a61922347d7d0a96d6e61dfa6c9640142ab6d7cda2a1841af9a2b87eb41187c7d032fe0f0d9aa998d094835063308838fbc5cfd98fa1454695bdd2e7348bb3e789b15f78d9de9c384608a6f2c275d9c2628ea1d973e020bdce13782cfd506197674345a0a820990a6061cd98447580997a1c86aefc511bd34d9369f5a8e1a5d62afaa008ec7a832bb1b416820f11bb16a598bcb44a682696837832159ac0a7b887b56eb2e7d1e4950475e1b9613380509a99a650f80cffd21e6eddd84750288521f8e79dacf4ed14b8e364fec7b9ada27689cb28e9c730d020b1b37c0e4647383cd4e136c202b3c966142606c4903d5d384fba4c4e29951be84a501bea4d941cb1713152b00adf6d216654a2d7cadf3501d631f9aa73c5744eab1b6f9ae6064c9b387c9ce8a90341f5c424a129d6a7515e76eda5a08b71ba25f2ac25e4969be471f8844df1ac48eb29f8390332661357bcd4408063a08ef3544187ba03cfd85d8a13692aa50da61924721f9336a2c2d015ae940e85fed8f4174ac8eda8ac08434bca2881fa47118ddd67930fb014de2894f60f643d30aaef5f0e0087aa44e50113e5af7263e17183193c644a72ba147847cca26f4b944288bcb52c5c0b66cc95f0ac96b768193902108131e838f457fce6d430e3b4bbf3beca269eb0fac9b52719b2f29ea3a2394ea4ce892f937194c1dc846651cecd4acbc3cd5f3604065490896f6142c05e1abbcece1344b5d18b317d996ad4e6e38594db2153b85b28327f5ccf33995dc7808e530dfd9b1e33c68c556bf8f80315e0a102494341c807e67fd8414d335ee2625d82e9dac5a69a22ee289b1479ce74160de59ba31357ab564c270e05753b9394c8958133c7f56de960d64175bacd6bb9928d4c9ebce9db44b51ee4d4613964686eed7ce23c39e351b5d2fd43bfa9c27af7f7ce699859e8819b4c6a847ac791b57cae334efaa152bb62fd67743f57a2bc5b65b0c68358827b206aa5f80aae7176fa170a357afc9ea445cc1b5ff700ec8d7f73eefc97557c54775a518925eea0fb5417c458bc7add07e518dab7bb1660c592eb52461ef555e7de6e5badf06f761433bdb3431f546866cf950e4842944bfb0dfb2b403cf92e282c8d084cae5b3abbaff972fd7f1f3988e6ae66c05daf59d482a3cb776fedac534afe3f5c2cc9eec4792346e69f1ea56fff1de92bddfd481977719619db26ecaaedcec95d58ddd609ddb58865a44b4e687736a1520d2d5337513747b67b7f6ff1cb922d48e77479e536e1b6dd10dac40f62366ca2125be581166205d63aa9dd463f59cef1742e56d58221dfc6ea59d29ce54170d9b3086e40f70fd4836063ea081356a38868694c103031d928449c5f41eca47804534e0fe1dd5b36a5f33ecaff65ffdaa03e6bb4feb5ab77a04d0edae1602e69a3aea3e88039c04aceaad82bff4f79c2782c8bd7917d50eb8d268a7f2069a64552bf2d3c71402081941d12e195ff3ec4b488f34ce1956c0bd4f9b9638ca16bdf10c8f10c6e0a1e96556573b863d4347c798e0617f737bf6db1b1f0552bef43602a81b56511eaf5beb8efff647222f916a74602e6812c2ef4cad15305dd21b0503c4aa3678c5e4232c37a13963ac3a0167942d102e754c6897d97fe910628478f958812f58ada66f147a216f08cb3d4d9d605a0b2d5f0aafa0b5bc9e2c79584d229576994fc4b8cb98ca3cf233b8083ffcef2ec16382c93c5419f8a10f9ca67a15fa517de8a1a87af420aa0d99f3c3851788e9bd76bda0a40429b740b360cc419831c33589b99932a39dacfcee9c1316f6ce4ba7163ca986111efddd2d05c345709b58cadddb963196f5e347cd52c44d00f0a5adeae0504549d543b4c17d4802b1d6155b302a7bd0868da1d7ab8907ed08cef127e991d9205aeeb2f5fad1f13946efd9c0cc2d716da49bb4064f902b7fd25be6d5b5b6b44bc7f7b49b6245ff5101a6ac80f45aed038d2e40ca71783d5e15b7fdc7895122458505f39707a4b48116080202c4ffa659df1d2639a0611d01421462b8d41427d918d39048600a0ea0ca69fd8fc3994316ddb44da49870e5f7ae7b7a674f9615ae2291ba70d05bb59ab01683fab97d5514057acbf8cc2c4d95c7781ace5d7d701f1913f7d13b894055b525ba43e967b74634c302273000fffe80d986ca5758e59e07fba5c5ab6e9e0597b6158eaf059f099f5dac64d2ca2dc6eca1da5056a8f8d7cf1026f1521ce65ade53fed44fdf234880d7364ca0f77aa8426f9334733eb7287d4bbc4c648595946dbbebac8f63be8e928e7a022a346b7fa1cbe472b61a598ca8866f9f9eab70a03f65dd73db75aa4ec3ea5f9dc598b8f28a5e161d94513886722f5a358dd65d20f091d3d84c41cb48dcacdd239802e48453da052154535138f9f63ea8b212c13d5c21e4dcdfb87062162e6665fcdec9ca5c5ccca8a90f57aa03aa32e547570a2ac08f850ba0d48d19eb8129eb9f0c303f60a0f074015890be1fff7ef2e31963a6ca97b75c67a061d22fdf0af0a96af4d9813d1788c9002474ad24cf62c2defbeb305279d632ec9b645e643b20ff3f18617c2e481eac308372de9461c559447bad51babe3206f4831b863b68ccffa767663075236985dfcc74b7c2578891614890caac95d96ea8cec97511a8b422c5da9aaef3a04f2082773f9d312b856e035982e96fe4fd86fe217eb825b13dde4863cebe08505eaa3bc86f84c92702b8ce58308e54ecbdb817fc0561ae6094a50e698da0769f657f68fafaeebe65d3238934d98cd9e3097597a3e8a5295b3a2c39cc92ad5c4b25ad4331f254a7b8f376171cbf4592ba3f6740947284201a11d403fa42ff0fa16377c1059386fb548640c48428cc13591e5f3bc9b3836505ec3eeb09372b227a339c98ae9e3da10d87f0454fc6e0d84386a4648f41dd6f6bb61776376933f40b32568252a870d236d36fd7beb7aa09689317dbf945f6aaaaad5d0965259dc8b3ae16e7011d957d1a09e4c9744b6a49088637c848d4904ff820e6655dbfdca5675e444101d1d84d5b62ae60aae5de4e59853564caf9c5cc5102927bd68f02f86e86036952754b557094881aed786013fd8949e0f533c4221aaeef790b89c06b9856047d287de2f7edfe35fb821003c0941a0b0805f7d7e76eb437ec8b9b5c429815bb7e043b94716b73632ec93c9939986b35aeceef1e8844f27e9bd874dd5ef30a520a4ad32c47d50da8e12217d7cfac93388fff4d8d6e810935ee82c723b258fa32839b5dca28a0916222471285a75a55d23327c58ad2e812918b5828dbea38cb9e437d346f3685e322ec9915011aad59ec14a7d8052e9a8b328faccf983e533b46b40fe37907f2790fce50d27b83bbc0475899f967b07c98145821e714c7c14750c071b3b84299bb66a1127643ae30b8cd096b3b2ff78cb43a951b370b49b39d83a4c94b3157349af264b313090bb0cea754737f1c02f3b6ca0b94581c60805cc21a727f79431d5edca3e0930cd2c293cd2957c38925e11927f0510223dd9f68d1af45c1160f3c964c762408d92436ef4b0ad54a8238165afb1bc55f955c97558d39ba4b1ff78e3f33b436be0bbffbd87359dd1954f65b2ce1091ca2092312f6923fcac1cbcdfacb3f194dabb95f0ee102c1789a58bc0959e9c480aafb76331525b7643e821ff84a8088e610f66c7c3da318b7f79eb70dfd59b18275b42d9de230ff9cd7c2b5db2340e6c97b8c95c7629d943f01d6b6db3a30d575ed40de52139ab1746dfb016fe338ad6be7c3bf9662c276c818a804e65ca4262a2c7dcf20f845c07e5a5e041c1abad7a5d89a1f02ac1b522f88fcb42fc394f3fe799e92a3c90de2a3c9483e23a1d28f48f435df1c0a06141ffe7d1ef8d811226e18816c6e1dc171475f4cea1ac240309ecee067de71f09cc1c4fe8aafe20eb8b38b97fb73af8d54856a052548dc2b3f441b01e9a491474c334440aed0336e33e551a8cddc041cde8fc177b21bbb1eeb998c30fb5bc788103201f2be3ed5b1c5946cfbea1034a925d7918d08b940886a76298a43fe71ac0dad45bd1863160bb3623e31750b14e27a1175cb1241d3eaf2854c353a9394ad861990a8c2484ce3fb3bbd0991d847a615d8de180d0d61122dc1442200796f4035be26547f74f2793b4d139e2162f417dfba9c5acc4fecd4c8a29276784a08abb1c934bebcedf60b1d9bd956232f3f43ffb1e7c92c46fc0e3e2faf928c862dc5e3e9e85a29ca44cf8e1c90b465826245988671f1fa5c1152031632098c3b9fb5276378ab349760fbd1c94684b9bb776bccf5464d380ce0615dfcb6bb7866eeece129168a28ff2a6f42fc617fd3c4d959d2b6d6a5a8c269560a0b26a1c860a17e2493d27e7a955baf48bcabda85474864aa417dbe7878be236f31604a138e0bae5005714e9550810cc00ae8bf2c1e42132d2606ced79b220be67abc2b2ab651d62e0659583d3257a7109f54f2107f72724739182c7a25e2b4e793098f3a8ecd79019a9a4b25827854bd869a1a9d4921edfe85326fa6d21bd120b884ae0547420031ab50679c8fe0d204e36c24328db1c93cb23d4a90a00eeac121cf49ee2d3c72bd6170917b5580cf80030142ac3d208c298d7bd96b9b686a7406d29e74060f5e9cde94ae35f071017665abfde276af7d849148caf77bad0f02e8b0af2914cc2c20c07c6dfa608cc28b7e5e14719f6aebb649a8b8a67c2448f73cd6592ab038970ff7e95d1f0ad52d4244507dfa9afc580e3bd5240ce6f0007b742614824c631b6ab27f16b2774d65dd94cd586729d15b8d3d23d137dcd10f7dc58b0cb26c0c177e5f6f46bff4e041e4830d0b61ccb991094a3c37830e77b0ec9ffc1ba45938f010367a164697b133ddf6b11f0035598760e31d807f2cf257915e3ed334a56ec837c75ee26c3a27876b41ac39f6471d0d38f3ae5de1c5aee64411a62413102d080f267d0a1f48891b89c0dbf15438248dd01f3f20c4b2d071c0cbcbc530562488017c68c587e41354b717828c36fe748611fff3a609333d9034af05706481f8674baf95606cf7cdcf2543f599622df73e85a3e6cedcbce10798e082833b10cbcd26d5ce459b4ecd1abc68744cdfbbc0c0f27b0c307d5b0f132c91f75f08b1eb3d44c256f2563d74f086d4120d189e9a24f4f8d9a94f689f53819e319e987e72ea56f040b23a6cac63ce0ac8f86e6031ccde6b9a8208835812daa944425b58cea11e759172398a153c321d6db503c362d3947032804f9dd44aec42d7f059e190aa922e6520b158d47ed134cdc491fff2482518d688c51c28af6b184b4c2c2ebb456841d02c13a4a2e86d693fd0775c7d5890ab6def00830951908c5a2d84829c5c55f5d5c418a3050ac9ff02551057a38e87a8034068796f76a1cf7a1aded96761b8ee0a81f61df8074a47a1b98587cf9cbe2792be5d903f2fbf94378a20ef84226b146f61d27e9f2476d7971e9ca40e4243871bab6cc465e702b83728c43b0695db5260ebd0e7881ee1064694d3fdbea1ff546c947a100d351abf0a6bbb75131fdd80a1db10d1289665a90375a824e6606d0d3b3822f76be196d087eee472042e46cd323f354d0819cc5a86e0d6002e64bee03c60f8860420466e566b804dabf9a4fe9b14c6b2ed50640abeedb64797c7114a7f4cd3b536539617cf32afa52e3f1a66cd6895fa38226db6abf3f320f089d4941a82003e78f703aadd8a9dabc320fedb729cf5e67e870704b6249a3156863e6b663c7b8567703beb900d81e40d18dd88d0dd7e8dff3d15d28c2912c3a222b6544f1c8218d8a123dd997a0b9785440ae8c2d78653d5513f10dba02d4f8b7c428fc16a196a846003e44c18883b9b3dd03a4426cc4c5062bc6929971146aa1fd27a0292e45085588c7e240d64e51c854a082c9bbcd1e42f701c2a3ac23b309c8700c74b13ac39000077d86b4b1499d09f4c80c7aedc3d29cc140801f4479524955347a24e441897df77cb2d1d7366c07791dc24f78aed86a0c8df944217af9f23aa4fc2c7fea3650794515bf3d1833101e67a30b27de32a451b04f5e4d5f554465a16f6cec0486eadba05c58629af47fdf5c7f3b057bd624dda6cc2a4bd251adecaffe21af3fb5c71703462f10bda32d39c4d9b39788b7be8a16f913d87390a1cc5fc741c17ea0e87f1be1191db8c3e573703b73606c7d1209b5c34773e12c4c397822c1b332805271084d2c0ffe2538a2bfff08ff0284dedd1cd00d11bbdc914ab3210ce003f57204b820e1cf29da35a110a41f4dfb6e161034b53f15b5016ce078cfd74a9242fc71356177c3c73f6a790ff1cfc28a46d113783f39f1a6197b095bb2ba83c35d429cb7155df07665ea65e39c1fc3c39ce3e9f9772354f2f93df8b25a27025abb10f6ab16d9a98da67a44d689e2732cdc2b153c8305124bce193775da12e57f69810fb58acc97f4258adbf7372a37d1e2890a762d0fb9c2a399329d040dc9195a72eb9ae3769f8203f2ff1f445ef84916e460f108cb11e8b4b4fad48a3ea172704225f85b7795f02641168ff9e8c8ae47a2a5486e4195cdc17b0566636ed9dec297c6a2ce9d6c76f55e49151bbfb73cf642ddc5ba81c799e391c2b6c53920aeb1dea6801f206da5eb0e6c5486c4696ca544b006ccb2e5c1b9942c7ed958a0d9f634c58567f219ee4ea7676e57aa9f2dcd187d2e333f2ef2c188190cd2d4e8249667b3e7bc02d7f7d657d965d641f0a07814adf21af807991254f2cf5aa6e5de9ab0cb04b7486474c8e4c537bbb34b96f1f510f8c1ab2392dc69d1f272c0e20aa959d3f321791f6d586fd9f604545a2ad7e5e7a1559104b460beebe964e08fd34cc2c1f0562812234a8156cc7171d929767e96910e555392b02d276321e454d4220b0b29f4536c1a76c54dbd024c1003eac5769459204cd29a0e893213309d6a0407e4ef54cc887b90edfc5ddcb544b64ea506f04f8dd72c20cd06fbfb85d54fcf1a183028f03b83e0f78d15f3dd442157c5b63e1c3b8770897bfc7eaf9734273034d442dade6d4dee2d65923205430ae408c9081946b364fcf58da070cf53a559937bde7eace69ac1ff3a103b9292cf8330330ccb28e9f34655aa4ce67d7d1b2ed5ff6a6765df6ac9fef3405cdfa80aa68e846906b1eff9af431cb11e2bf688a5fd9f8f89a5fdceb1ffb1fff3f767a8e38e1ddc977d6cecc07ecfdb5087fd9e9f2150eceb38abe8fd950105fdf723dfaf6153b2fe7ce720eff91ea09e71f623e2d0839941b80ffbaf962fd0157a3033ac2bbbd107cdb2f7c62bb3d1d6f3623f25896c8ee4d3331a51c17e077b0bf87e69cb4d231670f999da8c92ec178bb96627d6fc3d11a531b113932849fff5f46533aa825bafe4727d1fdaef5dae9af12bb912c5e2ccb00f6a0e45d77fa20f9a5d8f6533dbbdf79f272e75ff75b6b3d7f34173ad5d494481e88b0a4ac7dddd07cdf3dd27c5e170381f340d9d243a44f3ea4c1d3b6b8e0ba8a0a284e88a8a2748aea820e1c815154e49ee60e1a38a12a925aa94e014a5c906ac2b701021ea0b09b2c043c5c3f34275b2738838fd40278c151c1a8e1049d4809b020725a6f090e08ae20d79d121a182a8393be820468e172c7cd20c0922cf111870b0c3039e219f1029ebc37d3d5146c9054a3966a4b9c3252b4a0a239a10010c72a6b400b5244b0bb75a459d5cebdf2aa8c8f5411192ea38d1935407091f6e529db1561184ab8a1b5ad946529d7b072acf72e7eed070270c115d561554c420c6eb3c712634a3b8332577278a5f9db903e50e132abfb366cd144ea4a08273f5da7aaded29acb2b5d6da3676ac68aded5c5d9c3d11bc94b476f0647b870898ed636bad65833b97f74e5135050c5358b9b91caaaa92baaa54077795243b13529c905b02c772e7a470ca65e7d0d4b153bd3a69ea9cc9a58dca85cfbba7e91883446da0dfa3aa8dd6dfd9bd4eb05202f477ddf8236a83be0109e2fdfdeeef88f3c6a8f9dde8efb383faf6dd5fc77c2b7e14f4aebbd2752310d23b03995daf75d35969e704d51262728bdc544be0f2079b2fd236e81b8db6c3fe067db32307b02b164b5b0e2c04fa66c71f33aff595178d92e0997fd07638796d477badb3b2683c3a2babb3b2948cb0d4a8ed5b140d83f18e738e340cbc03da95237fb34fd331c72b760c12b581faf3ed13a031255b6c4a5ec105e9de12a0f441330674eca0df2f25bf19f2c076c445d50f1245d351ff6b5587eb58a82ad827bba4a343c83a30778a28b288c8b9592344ca03f058c1258815b260e5b8743cdc89b34826763535747deb0c15cf64d891dacae0b563ea5e79823852a74c104bb2883a220acf0b35e48172449d17b257e749963fd1b960c6cd24cd392367cd8ceab66cbd6212258d2839bd8a64c3e170436a145172adf53b8992f36d4ae02e436b8d86d62e9d35b4d6b9c4f9fe0c97ee2c7be2054a949c1620224e5494253830e1722b67998e9d4b078bc89439533081927273cb22e98ca523a7d2b9caf5412c72adf59ec1b7da92a268cd9933c7eada3a04700c6038b9385fa6d4385b9ee2b0d024ce932570b0527803274d7ee5cec121e206383824a170683002470627382c50e960bdd9c92913a7eacd1b26eea31225e79b239eb498375e9e38116fb42c7122bc377094bcc1b2370c4124be19014a0f3ac44922829b1e2c0ba8c218918b838788245ab9736fb07816df745dd064acc4b829e341782deffefc9696232d48a902cf9123f75a9dc917966f9e7cefdbd6a011410a0957a8c8dd70bbef605c0ec404b9736f84e42e77ce0aabe25c8c8ff1301e86c8739eebda5811b9f9d2e6481b9c9d65ebed8f2e774acb99bb3a766339ffba3a3be783d094dd03cf1d0efba57defbf9e3dfd552f761f70abd59aad2bb6bac8ebbcaef33afbdd5876e06fbf03ef446b45a6ce55ec3c43cf75bc5d64b3392425f9977b938888fc875a89664744c4c68d111c1b35443a5786842782080ec2e9b21133a44eb1f1810865d3c5c8ac6343432e6d2e183ae7c1bfa1e092ddffdddd7bb8dd151240c38412244da47470c2668606d44055420f6cd4ac3086cd0b2f54b5991d0c682425af5f35ca935228b0a8b12177e8a38d925e308f0748801e953d8832be94880650ee1c9b273638362290805b78dc097752b809f87343b1d4e4b27344d2b89033221c41f10ce148c640f942a728819f40022537d02aa49c890cbee4853b55ae9842ad8042b368d264047f5a73c4c89a2176b23882ad15940a6ced3cb91a22a704ab11d678912a4f8286669dc1a28c3ba1ca6553d13cb8e6ce414126ef707728c46477dfd17947cb879967fe60369b51d2b4d140cc7f2272da683122645a025ce28c65b369a3c18890690930fdf9a598e7d3bfd3467f1121d33fb23fb31d6f4cc1fefef6bb70c9cecffe9ffdc1f9fd5db834f3d7dd2b0f90e7622806563c67b645d0eb1b06e3854f4ff7236bb9c2fb3915a2650dd09a8c0841a20e940d73aeb0304a5125e74411615a786385cbce0b45a4d182854a490a405b6840a10bee0a0d60f0786941b740b9e224a584942c12c80186276d6418038554155d28087ec0e1c81635509e7e682aa1aa08122728389899438597518d179cd58212639c46103215150128a2a8304215284f577780605b4a68d3830d7060582197470d156c84786ae2881d1898e6082d4370c161c509d96091d2040b3a6b9a98a2cbed291daa729042c91238364eb480040c4e767ac06223050f446abc2229264cccc0e608291886c889e2a44505304da2a8e3e5c7822758c860c3130c56cc6460250a33499a844921cf55979997ac1e6e7841891fccf00081293cb91fa8701802083a968514980823b5c3973959a820c40a3924c166072756a2e0410804236200e382972b989062a38a13524c218182133ecce902f699302ea051e34688245a34887a21053934cc412245ce0b099420a284c821024c1a02e04820030a4d9c50e285385d94551b2d261c59f226eb872c459e903283912e60e0f0f01218a2c4942b3dac61738491932655d8a0a509161edec450e3a565353473010b56191c114be0b020c490275688b83387891b183cdc50c31029ea3c5161a504ae0c1b304ad2a8d0c68b8c6ac49815f294b162ca98322db4907067843448b090b0893571830b6a88a062450a1e5a40cd906b824e0f3a5059e3c55d3881fad2831d2d72a40690c4142a52a428c2ce1c28ba886cb2a24832449e144a3083810d3db46113c52a8a1435d3cc972c69aa18d26488150d0891a33a722797e7c9133e63c26831620a8e0857301871c495094caa5068e3a68a871e9f1db494b0029ca9115c683a4ab08c8952020a4820e1c48b11082104578218e0ac51a2853064ae2011a7081fa69af012d46b6498010e9c30504478b2c08c096bdac81993c298345ebe2052d01182053449c440a6863a4c4439e3c50a2c54a0f1227b40922167a0a060bdc9228323ee9c806b0288222630114e12881099c2a9cb1d2b0ab040220a1636dc90c4cb125d5cf814054cc4f044d41b16b2e234a550248d192b155c70424a09efa12a8a1356a6572657bb831ef95f9092348b117af105b1187a1dc976ad55f342b6f62d119964bfb465233b263d11c56b348e9a28f94e25354f7e9f88d6e600e2e07e028927a872f9b91ac5995c9279ae20070c16484a5872c4845bf9486f660053345144144640d981865b9313192482b0e1aaea09226e34d0a4d0640519a078e3c26ddaf2cd1d4e5b0e1345521444335099e6f63ee89f778eb3c96a731d41eeb75d54eb52fbcdc305bc728fddf4e6e207ddffe4f22797f7031f37cfae61dfc72cdbb74f8e54bb665bb8505a28305bfb4e815c7588b3a7dbea41105c76eb944b3bc546a1247d1b6a406fde689fbc465f480eeeb7fe34c42180ce765d37835e3e42f9f03551e9c265fadf3c3275c8fd954b53cd792322972d2d994abdc8736c497511fd1714da45d681e4aede2e3da24ddaef4e04d9bff3c076244ff4db6d0be687798eb38b6edf8d223eb5681b43b238afd18aeb7e362b2daeb3b84c7f9c40f61fc7e948f6d6ff79b6d2d70d991a8adcbd87380490bbffda5bae56ab45835edda8445d383c356891a26186a82c35ccf108775fc1842473ca30a7a31003123060b9f2421417acb4c04215225054545862ce0a2ac471f718a6387122a5c69ca4302d0a78da28787e43c1f3ed133cdf9e80e75b27b715a3a6a5e51abbc8beeb039b1e893630493664c4f7b9d223224a3e256b54f0fcf2c321395f9e4f5de4247c814d8f604c3c4ef2c493a90cc90bd6f66790ec8f416b029e60d32317b9df45a19ea02878be6de2239b89c90a004019cbe407b44f40a02d2108b424cc5a804d8f7cc81c83d202b423b800ed121a6895088136c90bd022813114e270e5b1c810688f3c688d8823d8f4c80563ca18a325cb09515206133188c02693494a8a511081b6880cd0129980022b2486888ac60b39145c47c257aed7666418325c12b44eb50aa8182220132a9801363d9a3630499613124344831c4fc0f3678076080db0e9d10c1a332aa8cd20299840c60ca21833c61933c49f3104e385d00c9a8ba016b319403366ccf891f9cce88961d88c5708cef85cde9a7167789dad7452dcabbbc8fe8cb0738fed4fd8aa7a59ff521253d2bf7680050bb9add4ca3085c452b0ebbe297f16b42289e991f5b7ef210623c836d7b7a18e9a3be8fef3402b8e2025afe00ad2236fbe176630b3f21cc1b05ec1344f1b6ddb82fb34d451f3fd5aa0fdc074daf5e5811775dfbdcfec5155eafb94925cf6b75fb5981eb9fd4ac91083aac3be7d1aeaa0df811df1ad6d41570ae52bdd854f80950a9504454483540e5a6a00d2725d5b57cda7dc1585a29a9d7bb7e5b5aee7148a76eeddee56cda7dc95bb67bdaaf994abb5b475d57cb2ddbb2d775567bf224182e9d34b8fecdf6ca928399f524a2b755c17cd597fd62498beb5df75e37811e27891bdfbceb59c9956bf29d7b1142d580117e00acff7b14a75d17cd71ca7eeeed589d4e94fd467ed6e8b9b977ade556b6b77e7dd5ea557b4a0bb3b2840cc23938e950b3fec30459612663c284fc8a0f0830d4ec0981026a10390ba43022c39986087cd12515646e0ac1015e6e67953489cb2e721a92c18c9d9b16344ca46f53321222733a127a2edb8df9907c5ddbec78ed47a574b3c726ff75da25391a4dbfd23f7f67da3ebafd87a2577892db10303c81d62d06e728f57681bf4adf53f3a770bc1fd10b42a0ec763d27adcd11a6d1db555a68a90c9e59d3ab2e6dea7bc81cf06a5731ef9d70f68f641f395fb5346a6e4f24e197192296d82cf4c11a9aa210f8abbb5be1da9c36e2ce7917b6b795f7fade295d678cb10721dbbebba0e7cd05cc70f78eef7c91d624041eef14a08ee2bd13b7e47eb109dcf84be3ec137f7149123350af6dc53448854afcb3de59465029b14bcd613b02cf79453114a4e248052c5a90528b527f7941393fc937b6a08969af9d342654a5b98239d0925c1d6ce39d2e6cf6cc10ab88e235367fa72aee4d8b9928385a74baecb975c173262b84c4add6bb55eabb55de7dd7aafd3792b68bbcef3ee6d75a0776fabe5727d600541a7136cb95cdf0782a1d5abbe5e4ee7eb8c0bfc40300c5f2f580ef0d5e5f525d387e5605d327d8cc964fa31313db5a7c7e9ece14249faf4892ea14ee8135d42a7d02368aad0aca94223c7eacc949a59e6962935b374c9f42d973cb1604d1cd6749a38acb9641e09810c2d43a6d1f4372975afd576b5eb9cce6e52f75aadedbcea794ea7576dd779debd2d5775b99c4e97775b2d97ebfbc030743a43d7078261f87ac170c5d8e9c4e10b06c33816ebf1a93e3e4ea74f8f8f4cf6f303041434abb399d3398b7d3da08b3e423ea08bb297812e7e507fbe1fd045a0906966b2836a5090d31974ebf8735f341032b5a2247da617b98ae9a229b89c55316dc14fa66fa3b4050d15803b5feb56265eb777d5dada79b747bbaf23d52ffd7ab9037777f7cc2c6955ea4f4ff4c9da576b5eea7957adadd9337da2b9be806b2e632db0be80672e41b02de84cf1adb5bbd65afdc55a6badb5da5a6badb3d65a6bed64329f24afb556af4cbc9d26d57abbbbdddd7d09936b5adbaad5e5f2008d55f9aaedbcdbba2da82b9af3a7aa2a653bef7a17ea8ae6fcc9abaaedbcaea926d415cdf953671bea8ae6aaad16eaaa7aa56239a168d95455497790ab94c5dd79bd7c4d944245e1e2ea757be9eefed4b573af26d8fba5bbbbd72eaadd47ddddee2ecbee933bf0ea4caa143cbf96dddd2d96b319beff43b98396826bbd607deaeef6d68ba6a395fd7fe45b67ea489929235515cad4903b756a9579e46a6a089c4a84686a486e4a0819aba9216d84d422afdc5343ce4c0da1c26fadbd9d6d75df7ab3ceb4b2aab0b5d65a6badbdc22a5b9b35275b6bbfaa509fb2ae6cd69d22726c1622852405892b5430792187874beeba29213ce4ae6301082b4fa0aa48299946f2cc2257d83c93c815b90b82987e150183b9735837e4d2568560c980b5c2082e42ce6d8e742f5691285779f090e079328e8bd786e4b1ca53e5e571210f542e3f27c537ff9b6288e3957dac5d94a9d8392cb6e46f8258d9c58fce7ed174d85c73fd20fbd839ac2fb9ce10645185859cced95a71d873e7f248c9c234772e0f0a958828d322b94cca14872b686083e526874310b71a56704a204788196060e156925d9ae49ea8b02297e5875b69cb4324d3ff280008c2ca095094206705a71bed5c1e26b9b40d61059115495758d1449e1284105591a748152e72e7ae9073c51a21a8f0dad5a805dc8d0095bfd9814dc199905f232a240d2316704966276978192256e070d78892ee3468cd494afa1b59c1ed33b7a0510b787e4fd22d150e8713e16fe4e04195dd7146d9c32a3c57f98cf7193c59dcd639eb788da8e02bcf8a4a243beafb15ac141b51c1017992a23879ea11fb656485cbf9f414658a13da93361a0db269182d994e3d3637b89cb8899b4e343c7b1a24259de62e1ce3d9ec1f8f0d2b048fc61a5cf6550742f8e163367bb2ebf842331978897239a95ef489869dab1efd44c9ea8492f5bfc9d4bd8f2599fdab184aa5057ff25afdbed7777fa1eb63ff8a7d8719b83e0ca64d4ce8236f124a23795d0ba9d4b4014253c6b81b09d6b59e077b7ac29e3a4326cfcaca78549a35ea0efcde482becf158e30d2ebb2ad7af40067a5c801eb5bebe928b6ff1e59d11cd1afe2ef129e92ec6a635ffdab416e42db19c571f542ab97e4c7c89259d92eb7f624965c8f56fd983b45a5381eb6118866118866118866118866118866118866118866118866118866118e6300b9a85e2cf1afe9f0bcddc95dc7e499f7a10a139c3837e55555555559590115cd2aaab923e59c959d3e283bebc42334a862d8228161f968a4c0e1fb15b4828063ceb3a865f625096cb49d542376462f713cd5ca00376cc60c0b2d9e748ef0249d2057ab1d68e279f886cc544109a726cc710e88120181b61cc1af5df9176f4db946af5a79c3fd1b0da9f2655d0d797cd1ae17f22a664183476f87752359a599291ed476c990c06140c1878d608df916663a5b5f06b796b0f190d92e8476c3cc305cb3bd1f8a82f34039a21d054a264adf4ebc01932f97cf8b3d98c18d34cd7ea975ef6a7c1daa79166eeee5e33fe1ef6f89b1ef57c874bb0ef30832f470eb00c6a794f9fbc5663b3f7ef696352cd1af57d2c7b8cd95fc9c51c3160af638ed8cfea4faa690374ffd8b7c692e6725281d0f4b1110c71785656768d3f6b54aa9ef135cebe67e30efffa938a92b5cc0e47a25595560945c1148a1e95b628f4a8fc29f4a83e7542abde468f2a25c3afffb978678dd03e28d6bff561625312ec7cc4b207e840a24dc263a6b9fb1f71669938b38f38735f71e69638b337f36be66fe60fe971dc07c7d98c92b59c9143fc658c1c36e9a2fae52b874f6b245ae5b5fae1c3fae8f5e1fb3452d0870f4e1bfe346bd40f3f0cc3d006030ec371466995234d2aafd5c7e3f7305a95eb7b93d8d7f7a76963c7ffb4e15959d9cb21a4d9c31aa9c5fb7b1ff5bcbfd7482ec2f777217a5d0bbf47f426c36f21c2ba16fe4c0c1f870f0b614fc325d8d894843d0d33081f368294f431ef9836605ff1c7c6927eae8f0d657f4cb3ff4c8475cd1f2676d7f00f12bdaef9bf446fd2fb50ccc041d1fe2796d82596b77e4b2ced52a524ced5a17ce844e28546b6fd143d08423f537a01253ba4ee59d3adc4ef483d2399bbd9f3dd235e406bdd7f0edaba5cbfc564dfd2ac94ed05d94ed18320d975955bdf1ecc2517f8250e5f5f92f84b5beebe9f1228d2e6831ffb50a4f94ba4f948d3e0f53dcfe3f53defdf33fe88f29147f83ee38f9e0fff47ec5fdf74fb449a06e0c79e36471ee0c7683cbeeff9ef7b1e26d2e6fb7cd30d8bb439d234c00f7b1ef8613f1f36fe889a230fd8fb8c3f68f3b1d7ba6fbac1fe076d8e1ff0f079d96fd037a7ebb5ee632f1b7ffc90bdcca7e986bfe9f67debe919fb161bed773798d8b797d8b750ec1b2836dd3eb1e966c5f27d74d9f5345c728d3928d97d4b949105b67fc70b28093403f6a76f73a40b28a844c9ee75c0ae264bef16afb47e49df3bcf9fd51cf0fc9b7fbad075df445ffba4be740305fc4fa27f061c2977cd7fcc5511ad8498adb2ff0c95ba28b68190ff289a30b681902c94eca77f2fc61497ed988392ae245e4049ffb14a3f00dadc80eb2b5d906396dd77aed687c0f5b1fa9d5bdfd1eeb8c3d5b95b6b9c91750bae6369cb2dd592a1022533cb478a3542575090588c09ca22660c224c0d1e3098ee9a0d78be23e01e2097dddd43656ef45157bbd6afb6001f287b92544150a6e428e8880104a54056185803060a300880246404808aa8071c7798e0e78ab1a8098c580a2f5e79847c9470f1f3a6854cc80c8696a0f1c84f6d04990c373e49493904f840d1151c0265a4f9443aadd711de2b0afb624e9da088f6ea2e03c44950a027ae3a3ec1f39d046349ba678d1c452132df9129d907ad60498b8af567b97d72c772cff097bf3a9b0a49416605cd80cb3babe04cea88bcce56ef1200f760042bfba0b95232df1e5373bde077bdeeea68e5f93748cbc9fdf37bc8b20eef61cbf47dfca0e61e3da89decd6da310809cf95923564c0e505c0194cb3f9839a7d7499b6c3fb00e459523a2b404e3a2240feda2b9d4de3616fddd35cce7ca51b7f04b979a3511ebbfce4c1e52d3221260597f585e5c3042eef0f1c5a77511980dc5fcb3d2697b5d9e42ec76419998683e67e9a67ee27f267eb160c8e4949e012d3fa2a9bf2880497b556029661d545e429fb21f7d8d44ec9f925771e0a97eacc6570795f747079bf69e94f16ed4ccc5f753a6bdb57763a6953fb2a9b7277efca316c8e11f298a2e718dd78bd86cfe0f2d270cc9c4b9bc728b8ac65597594b5c7a6fc51b00738c50f6aee31934dd9944d59df57d994f3d7dfa46002194431c851acfd108c17dd4234172d6641403f329f9e1886bd42f073b566bc82d0264b7dc2047533578b0c42530ebf7aef41cd1f7091abb7ee675f301cebf191fd0005cd5ab8a009bd8031f4e277b834be1205bb7c0902ec40286046b6f4972e792a65574e08b11b4535af89a593bae0466ee8c60fad096d9872c34a8ea42f2f9260bc7002bcf29434a328c0080ccd488896e693329d8ce6921d361f5ad85cb460e32a21045bf6461e34c204d198053dd132a1070d3b0f207bf821817ed05c2a1520ad244024c68748e6f3c62b8107119a0afc98d8bb441fb627e6a67bd7bb40b00b97c00ef461a92e2004044c28899230d1d606bb1e7c30e9821c36a370a9f3946457e77d0fa1ec656046e635235fe2d3f2e0b2c72cc946c91eb2ec3d3985e9bbc41eb2ec799ed009b8ec21cbde7b6307f010dfbb441f3587e105c12ffc1a2e7d3e6a0e67e128d6ec03fca1f52eb10798ef75fd9d36eeace175df0a3db19c654f262bc1ec2a6f768163e9fdf72d7bc3fb1e2eb5400c42c0e17043b2174276bd27922abc4bf4e1d927a0c2470fbef7d503bbb73477dff26e06b3eb4b3083ff892ef07bdac8ae2f6b06c7722cbdb79e67f76066f7461f9ebdebbc35895374fafae7b501f71fc015f3cb5995e74faa2bafcd9f3fb1484d2e197024e792e7977d75638427626ef31f5001cac591fae64f7dbbcd4f72a4796b2e74e472a7185b55d550d13cfaf339a8ef23901148140ffffa405e4fc75a7f83bed507d24e6d38dabc762b67afb1c71f3fa2683bfc37e89bc7c2e7a0c3f3248e0a2a88c1e16e4062a392d7bad7d881fe1b54e6886f48a1631d1fd78f7df923ce757bbd8dca8edc5801afd51148140ffbfe403e3602b1e3c479d9f4e748c7f9e4b5aebe77ff1961c1f4e7849a50330735a5625fce1c7dfb11a06f47da2d02f36323cd1b691ad4b7cf417d3b0289e231df1f08fdfa1c38909b12a5ea7e5651bdbe6f55341e218d2d323cb14392a65be8c3330748e138af1c8b23e1e6d524a2c2102b5a5618d201f7192b333d50e10487bb856fbfa438970a979c4beebedb1dca6bdd1b61893d7e3bfe88a269603ff63cecc7c61f515ef7d61b79d8c7e30ffae4b5eeed48a5bcd63d6cecbe74a827fa25859a5f52299a06f5e973e03b9c421108cd79ad7bd71616a0e2c8c982c3dd68963354391a8f1bb7f06fdcc2eebf9748abbcd6fd0d29b86f7872f7f4ca6bdd97b4aaa4571cf49d30718ae06ef695e84b0cafa29220c10e4f38dc2d14a35cf57389e02d318011e18197959585955df75dde57ceec8d9e373a9696e85628d9dd3abca34351b2fb27fc8e732487ea5af7f77a5f629c2bb710608e646f2cb1cd3d75472a970ee5b6c9a330aa8fb6a33ecdb4db45fdcdb0976a1078fe91dc4fdffe15fa1fbd5dd41574ef3b266fbcdd5fe9c62b75a4f1f09bbfdf7cfc11e446c72095522a05c0d55297e7f25caeb1a44fbffb699f7a74f461f350565656b69d1d49224acef9949c2f32c1dfb5f9ddfd2dc4172f998e138b929d7b724f556195cb774d27c174ea94c9abd790a9da5a6d67aded42a6aeebbaceab40e0b24ae5f96595cafdb72acff6277fa2b9abab0935a180c061065e6ef57cd5b1ec20fbd811f9e87fd51632b932657265ef0dbc9bd3dd5f83a4a4eab6b35e95e55a432657c7e4651ae62edc8086b5d65a67df57c8649fd2f176d1eda2d945f3e70e272244a6d845f3c52eba2d4a521c60d954c77a4326b28cb542a6f91fed495f6553f642268c611a78b9fe06ae90a96ce5f965abfe075210044170f67d55a6db45f3eb785d3d5dd4abedbceb7ad9ef463b36d9d90aa2fb59bfacee5f7d94596fe6796fbdd1d301e6fa5fd97dd6ba7f6f00cc752c7d646fec61cb2e22dbaf20c904464c60c4cc6753a13ad703c92cee0c8a6ad5f0725de1523f95eb886cfffbc04e2cbb4ceb5e8cc3257f110469080e21315f200c949d503108d31254a6072c7dc01a31c8400098c173fe80011002081c497083c01f2bee0c2c62d2028ca1505d80af2b2e0df4594208fcb1ba2f2ac8a508c3cabea17693bb4daf81227f3f412e65e4995d8422bb8501c2a8e10e81a391076b2488a08c36776c23628032d0d0c0e4f9830f0df690ab28037c193101f89a7329005f4441821318416b2036732b00814e98018e502a0d30a604631a68c0f0e4bbf7624c3ff744ea599ba32d064cbf8e7716f9be3e53064deef733b4cc1a5af5d42994bbbbbbbbdbaaedbccebbaddb727dedfac0b0c1b06160f7bfacbcb2e47e18166a25f763ba25b7546e0a45c97e3b78ec60e1b1439d705762be9011f3a50c556e467132a744994ea615a8f944d7b8d51a3b571530ba91dbc8f64d4add6bb593bad76a6d576dd779debd2defb65a2ed7f78114a4217dc1422a9697698214d3580ca43db77f808226157d2849451915cbcaf403524cc99e998ee58fec2508798e948a922dd545fd00b0f37ddd1d02568feeced1362322722604b6abf97cf860b229a35e6de7c16ec8d4e59a296d81d8152e4d593b0c0683c1e8173279f97611a51804837b34c24511b8e704bfba440302d39e4d57ce09da49e57e1755b84330988e3fd7ebeccf87e5a573767dcdafffb6aeb219513b4b4ceb76141d5c7a854c14e4db4530188ef524dd303ab3e4534626fbf901ea8080802c50753a811a7c953f2e16632113edb960a593d24cdf710f9df3026bedacfe807b94d129ebdad3a28f2cfca13f3fb3ad0f7ec95a2c7150900705d1a0290b976e5072565f341d359741327dcf6553fe01a2b114349be1162d5cb8304ab2bd78e174b68080828292966636ea6ed1e2024af6bb70d1399a50184cc712a3a93ac3a5cb968e329faeecf4a0ca418388521c2d084cc77262e51e61844b43d7eb6c1df2a1a1a1213afb05bb75ef0a6a410b975c98c1d4826d678d7e1fb0c599acc58f0b1a9d97923f608b25d8e2479b4d5f25907c5d7451b824639ab41083996b0ba1165fb408030fd1a139645f80b410078ca13934d415068611e2f0a17069285c7a1c430ca6a31311115122a249d4b1572902511c63c42022922163820928a080246bb5bee0186312b5bfca20b97e31c018b2d91c693f603ac6087178be4b4421130dafd1da9c205c825130963dc03cdfc57296299d94fadb4ad2c0603a9660ad8219e1128d7009174d0f8697280899687ef00b2e697830b3b27b394790e748d28448f2050c9224875c90640b926c5dafb364753a2b7819c007da44e97f301cad0f70b4f2157f0e5e371f7f84e076610bf07c29d945546c20b20d17e0e51e938e0cc1e52e5c00cd83993fd0ef48ae70d90b1710947b842d7900825c7220e320ca1edcc8edba1e7d951cc8f6bbf77ed7bb5f77ef772ff9ea2fac0ed2eeec0c5baf20b36952aa837badee62e501cf07a9530a7a584326b1b38738ec8fb38bfa3d5c0a32d270f8e4fece3eb9c5ce176c0bea58bb68c8074c9eefac319f29969b92583efa1d1bbf0478be8c92734ef966eefad59f3506da42c9c7920536050a3f5152893abd42c0eae971e555604d8bc7999ba36d463e44a46cf643c90e3f99edc207dfdd43fb60e8c1c42eefe74b47bf7b51592c168bbde2e09252512a7a064d197ae4f3f5956eec4b5cce7a9294daff8e65526b2c6dde58923de36b8c8d78f411cb1bb493592e5bb0d8b0ceb1c1e5cce5c490f9f242887623e985d0c57836fb27499b2d2997f4c9472795054be31b6d7039a5a4b874d9429f485b92918d469faae854ddb00235a563495574a6a8aaaa5203859b2ac755c1a93fa1b064b1224473f1a4914d88e6a2c5a4222715cd55d191139c0aa8642b594b8a9a444aa21100000000c316003028180e8ac4a22489e24cf50314000d7090425e5030164963811c48311407310cc43080106008300818659ca22439f006d235f4e42018eb63110d50aee9340d7f8161cfa29a8831cf1f0fd1bcaba05e1849d4a0a3861c6cdfcb708a891e6d65a05aec2e84ca34c93d9dde9c42ea39d237cb018b75a14debed289c44b19780e090b50e7ca46164d5fe29642fc302c8d86498673fa13c08761fc57d40548f93de19828a3617b2477a7349a10242798c5e20a795394aeb85eea2eb1e074e0b012b8eeb7387bee2dd8eca378670ff03b3817c7008854871f932ec3f11492d0dbe12988f5d782fbb644239cfebeb9bf9d2fc85f3a83ab306f5d31e2f7c9d8818ee152dadbd87e476600397cf40aa5a6be7903c946cceb5a71e3a457833d06909fd0025cab195e8e48f7c1376d82a8f54f010787c73c53abb434984780d3c901b819a9db633229bb178e52b05dafbe815c4ee8a350d6517e9189a6de57768b396f5ffcf09b07d667005a213b986cae91341f3342748272f90237fcf9950cbafd67bc0f3e63224bea686a78051b28f0316675bc16c4c66d864314a809d9f53604fa81befa79a189c6c4be07e78b8cf5969fcfc0ca37550743d5a1bdd4494da23214f9f82d0aba024bce2afa37223fbf16cb6e90c6607e78f4d604eb6f6f55cd7f06e9a615420dd9cf3517afd7a9b90e564427174e4b84b122d140bb1f8628d2a9ba0a6d354ca2e7ef3cd95894938623cb081255be68b4b93dc9511a940e4eac17dc92087d8fc9b75f31dc05bb87b7702f6e74c505dd8d2b58a186f662a90f34f54081cc82a643425059d567ee09c35dc3cc8d712c2cb0bcd12323cdeb48f68e3c576242a0df9bf1721fc29da2ff46c1f362af06a4371e7bc116606fb72e640f63d4d5038bd722e58faa11d95e4607e614c26ab90e0f0a90bf362d6100f1258bcfb041f45653a28f6b8e7cb5ff71c211f90208b22ffcf5853e7ea945ecfca1778c29f0e702d58f0735a1f885d21097d0327da6ccde95548d51a557b8a1cbfba81f6397b4a34b4ae8b71a01c0cfec48f8c10116b24eea14751334fc3e26761e0d900cc817888205a689b65be607a5cbed142dddfae21a39aee34288f82f534887b8a046d55f8bd44dac5620d72ffe76719f468385d8bc69e51077f1e1a6db09036fe1883a483c6f1413db043a9907e1f76bc8f45d171a28dc8d8a5a7261c3cecb707f753495719ed5dd5a714847f71e5deef91012b12adf214fdeba8cbf09a4cccbaf47a918247cb47b3aee35ad5ede689294c582b8e7c9f57bc496fc8d0c277e87bb512c1727771785f73d5e7e25419656641ea970500c7e3e1566485892f86f3ba7b039231c98324676891eec97b4d6f45b416ef8fdf3581b5a47d91951a027e8ea0db6e8df091c242d1eacb0c49e9e4865c9bcc10b3a44196f0bee22f7b9df62245190af2d1c6bdb02690f849622d69407bbf51ca95160d03d6e91660bcc2a9a95693decf7de15d4c3e70d9b8facd39f49a5636f9f5d3e6a2a5383c403412b1548c5b476151bd2221a77670d48aa1c52b42ce2bf0f744b0df0bfafbc24a46d4ac6bc48583d46f3715facb207a1e41c829e9b7a29bffcd1f6eb32b8a4a594fe08dde2779282662df42e8e42424d1dad670803b9f73286b8a2b7edfe20188763f8f0e63d74ee8e8e3d585d5201c4d1abe6cca52de773fcba76413f8b6f07af4aa42f42fb450ea6b3105988b1ec23376b2f52b8780ffb74384b20a0493bfb81edde2040f35e5feab3c648f30a1f3122d62dfd7a425a5924c83f89c40be1c4c8166ba486979809153f11a662d4498821f82b9682fa9d5c285ba4f1013bf81a4d7d0e00f9a60e457af2ca44f9909cd28e7eb8900d84c10777ba55702605bff7cd60234675ff846fdcfabeebf6370788209cc7a581a1b17659857f482cf2665645f4273244ebe81be38209e86fc05e3ff9d831235e0810e7a0319acef41f71f12a0432147e00eaf04ef3799aef4d6ee3387a2b6713067b15a914070f425b3df5c54b0b7c2c4a8e47d84adfaca66f60c89def8c0df2b87d7337ccf5648e87084cdd955edb1b4a5b8e2a302c6ccbd5206872af1affc491aae85f5906ff6f0a5845cb1998f4a9a2283b05dfa7ce2ec5dc6a29f672a58e4e6c2ae4aa2c0d41fc6d1c9f3a5ec5c3a0ec991d82e37ba3dfd12f312534e2039c527f5b082ab52c3f7f8ca8c9fdef8080bbfcdcd1cdf9bd377c8b91284ee3364142bed14a0b4e0cc23d5b75dd268665d74b51f8a74e034bce827f3794342b89370e56ce1127bf3b99822d76e31904f764bdc4dbf0c3bc81be669f6115a6406b74ca88f8ad4d748bc777de62f9fa5fa82cc309914da11537e374087be55cc35ea3ac7148ffda82de4b2e6bc200a322d0d6be9315b424e52126737f22c58a6df52efdb25a4933e9fbf46a57b718e3a97cc2b2a211b41aa20601eaa47eb943e77bb9c0d89db8ee47cd2027e8304454a2d7fd90670cf338dd93836d2d035099956e07a5bd985e3f1ff08b6b0d6026cc5901977c5348e06d9310ebc47f6018e4be32e4c425a1b545b657dd6827353fa39db29c1aa7eeda3ab2d789a5d5aa17be8082990b32435185ca3e0fc9a7aaaa112833ef9607c97e7326ec83c42b3efafbc58e25d56fee2dd98cf884364b473bd956baae15eaf55a4f7e3dbae18ba0719a3c1245eae0943f1351d604b63b612dc36ec436671eba8782af3868e71debb98f6a7fd3d3b51a130a0b0208c643fde81a54f7ebfe9a4505ec4a2a8a68b59558127bc550668ef30ef02041be9b5b6ecf665226e460b48a8df7e135232e237b91243f4f3eeaf8ab6c3468646d54c28f13fc769bf9da78d32e7465b88b4fa8f3f700fbf8003274674cbde63d5ff3fcfc069365adeda0a208a69a4e6c1adbd801163d46b067f41d897d5978ab7107b16a9ae9a049a20ddbf2cf829f211bdd876a07ea2893b6450aa18b75d801d4e6a2100a171706ca6e660c51ccad8a438e366148cedb06f8fb89cd66940153d0e6df161605c280d5ba55aae1e567498b0775a8b5185d1a9474b4cd0feefda6bcfc3a076098a31d2f825a16b635663795a01a6498bcd1d752026fb38fa8b454ba57995cd8f30f736ba1495030c56fc129863727d0c3713521c1501222687c47e6342cee7e8c26b227e7593e6130ef39eeaf5b5743563e7c19d959daab8c28c76365f10015f547974012de4de32909b4777c39353a0d6ce3b7aa41571b2616009090ccfa9588a0ecc4c6330259fc05c33c8cb230cfa1e729447a79c2c8ca5e528cc76aee11c29a74a8c4a96a898488fb3b0ed36b37ea431b04a057e82361e5b0558768d716c8da76cc580c1f5d4e01c4f0f21a78895182d58ad270144d1c824335993fcaae33bbda38e07d1da15484a8cafaa779abd94bde040824afb141338882a28e51c190eabd36c7988d9f72efcaa77b82ed368bc499dedbac06902d3af1d365859724bd9ff6660e54adcbfa8db7148c498697e6c62581cf830cf1a6326c5bd3ce32b73759321f3113b3933ae796cfb3b3da644bbe64871f16e68438ba7e635ce8c65c381705be7760a16da6ddb85d34d6e529632bc6a0aed9cfce162fb77afb18fd5271f061199858ca10336eea4ef52a108ac84863b497564040be246b304958a4cb5e68a54cf3a7cb7942a824d0d571e610d7b8562774c1bb90f0ac5cff493077a6242a498ccdf2182ae9dd64746076a07364806b4c3c6650b6294e4563e0d7541f5708d6416af21319d920aa8906a96ea895a8f4e1368123331037e71eca2e94ba8158d32de5c6d3fa3f6b52f390e04429094182047986c1977fb55b45435894c0e6156c13d94ce3cee803ca838b71fcd71a83e93093c3ac0f207440977b62ab62179041b470f91b4108431f1116bd403f8d967e363874438d9a219e96d84a139d146344855cbf1032153c29caf8ecb994ff4e53a347d16dba473e88d59936a69d69dd13eaf3067c4ec0c0eaceb3ff9908e7baa2794522921ee06280034cb5ccbe34d249c7c3612a5beb1df8a8624b89dcc6b07f394cf9097fe32bc7df3607abdd8c9c3c4bf80b7881bf430bc3b561cf07fe26014ee96d98053bcddb1df79c4d75c7a353f1c94c5c5537906cfaec1bfc2efb147ac407747813873f8e1382e9acf3587f1411a4ba00f02f466cbdf9d6e4d53c2cadabadfc5cd19e7f7540ebf4b3c36488b4ba07624ca774ed7edc3b7d186efc7063a44dcaf5ef846c30c87e9cfd49be0a38f10c6e9cb59f8401b5d132bad5f61978e65a55fece5c8346318c67dd364132e4966fccc9bdf5456ccf5b4f5e3b91e0161e0f282634660ee293c76e8c1a561cb4905a52c4e314531fc772eb056eacf3fd064315ef4d73e1581e0b78b7c2e518003b05de86af9587b746c614e2b836acbd4c17b52f00d7faf55a428a299f937007e4f50dd15de571cc601f842eb9e5b0a9908111314183d8b5ad069ac2f9d28465620d1e098361360f0ff282adb886c4a003fb110edbab70ae0c517687381aa1606d5acbfc88b1fa6c709ae7b740f33c0873bc7b7f962cd6979075286f2e4dd023c92886b4a0456c461ddaadbe545dc2707dfec37f965ae8c396ade30ebbf227e6f87b58bbf5c59ba9e2375552a5a58fbb480a927cf532f04d44e63d273afcc1b3f5adc65d5316bb3dfbeaaa57b8e60dadc23239549c8f25b0fc191cdad6141e72cbb9eada00a91349d7f9932b78e34db3da00f8593fb2e0c7626ba71a80b2497ae139028ab0e2fb97c0a0216e5f6c6c9a2d4bc36392cbb5389d7c6fa37cf66710524f0946d71cfe03ca328632ea35f47a6ff9914959d1b2d0d99d2f0b55cd7e6f4c82ee7b87f14c0bea9388726af93ad52bfabcd13a5b117dfa8011c5062f41ddb3b28c57263b4588b8d1e10ad7ecc98ea25e62aecbd4732952f8e7cb668fdea9fc50251fa5b6793e8cde9d9b84ecf523944493e068b09498e2cc86ff73307df9d5a16dd88db88ffed21d071d9cd7af0d6198ed4ce320bc0582d1e452682405e6368a6429af5064827dac63f649d221b88e2d3e8aba867cd5c4dc6cc1a221251cea2ff846f3601538bd4bd24dff3f3e9b6434e93459bdf4e2e3a516066f221cb6c12998f911c7cb79b4fbfcb45f04990aa545b22a1b40517735d023c20bb0f3a745dbfb2905332ed12e38fe10fed68aa83beffa98343378028c9324c90f4977c10342c23f46759b8996cfe9441aa7741236972951c1a90cf7cbab1fcbf56f02195d0de4f1b451e36de5031f1dc665db007bed532fff4bca1ed199a56d174d67e07824200f42f1c9a96225cee0fe4dd2786d64fb70407ca82bc49fa0c5cd3530ab0705f0ea18972681ebc8998984b900c272647fce1ab2f043e159aaf47b0e9bdbe0d0f246f5ee0e104032af451faae3879dc572346d54ea053a808a919518279aae0f873ccd4231128cba21be6449165bc6e355d310944b3e763a3e2740e7c467d10a60c4a5f86351274171aaee934efec61b6d1f4d39bc97a363b230df64c031fe357eb7e7aa1d4455912945fca038de943f8ce29775b8b48adb30bb60ab5830d770d08d9e375260513f63fb5b7a7626d87afe9be2496e939954e32ecb098d10c926bb02fdb3c8098af60bc883b8ffcb751783a557b7763b4b4b2694e5dd67072fef52102c50724de77991f6c92c87e90ceba5c30bb38ba652c24f3eb7a8debd193b10f4960bc0c3503d8414ff77bc2b518c3224a55b03698da260710e8f9a84fcadfd681bb6019d7ff02097fd23e3b7842ba0334f0e045c8b62d6900088392632267336bd203a2253f4e16b8b1e7ff79f775982c910da9eb0a272eb34149e8a89ba9177328ec6a3656834746222e4b2e668348a8dea5c0daf96e9499217a469a422e90ab1d37caa2975a1b04a11df5c8fb801368fada3b70d2a768d31914a1489be799ba3b11243d06eea310fc43354fb37540f9dbbabacdf2fbe78fdcba568486f9130b3cd8fd5eb6eb59ddca3d49cfce3ed38c13e2f5eb1a91812d40015967c2d7ade9edde1a00f1f40e7e07000a827d860b38e211fe735be6bf018c37c027c00702ea0217e8f7eba78f87222640d0f90a30a14fd7d546b0e6c6c781f08cafb6b85defb75fac0f77cadd5c6e6e008820e1f7c2d6f9e86f1d0b5408cd31d477f77ec936a1fd809950d9eff28361531d6756f2a7844e4c208078fe90204037c1b747182d7699a5afe879e0aea255255d76519d0ad0a70782c802614cbe66e978696bb7bbf7eeefc379a8ba51eef7a1b2f4aedbf074956eef11cab7fc610c11a1eeeb4edff13b443d988e64a041e8a14bc3d9ecad9ec6205074520678417e8581501efb0cb73a8a2ceb1c33e137c4b1027caae9d8ca1f93a381a0e3fefee9b25b51150446dda7db771cbeb514efb8c516583f231cd75b0ff3a6a7e51c2fa53125b0b15a3bc268de007c761855cfb70a92c084557d3fed60c3b43bdf861998bf6d56012b46b7d69e7da8e083e0995ae99f5efc49a08628cceece5bd0be064ca667ef9fbc910993fc76b68335a7695881b1db41b65e765914144869aed2870a874591745cd8497248abfe4c575f18e5a3d0a3a67bc105d316e3b65a06f6bb311544803e5d3e98093e022dc30206364af4cd16b005b99fc89679dcac5bcc8b9bb0b900118b87ffc7620319653b8658960ef38c64bcc5b6d20cbe27a138349435cb2cc5eb40dfb53ad1d0dbe56ac0d0b81f1f6b542a784305731760864ddca1afaad34344d2c4286ad5c4365f869a72ba0351b81035d4bb17738654241a9f6d664d08f2db7d33da1ba2ac9b1a2eb6474bddf62755bbc8b3bd76e28120512ec1c67c26d6b057591382ceace1eaac1393e07c0f9235940935c953110ba1829a88831bbf573e427eedc209d1517a36000004003b87914a12954c47e93cf415ea8ad135eb738ae8069565832e3a7332eec5c41989e26c56e6fc999338c23cd49266a4496cb2721d470232610571806253d8e89c5123014932e3d8c40d49b9f48523834493506634f3c80d5f660ac60fb938c702c8d9ec39b133928a3fb65abdb4595d948e8efed35c4524e3e10a72455e4481704854d1e071c648551392525620c67ddb0bf587fc7d4195021aee2196dc77f4618b96368814653e0e9aeb9c5633ea0722c9814a36dacb854b38c1b871b17ea6b9f780b4e172afd257a4f85e534656a6b64d5a0770d25aa0f4fd180163bb34f0c63528651b0b62e4e603b5c45b4a3f4e8b552a6ceb1b6ba58f24e9634afa2687ef64fa48ad47f0678e1acfd33c1d61de8a89ee3ad2981826a9395149f56f67d20a465a70d5994aa5ae7f4f8a27a5a2bd7f6b0f23a714aff649fe993710a0fb999bd10fb75b3caf368ad6dc7dc186be5c148aeb2248d9b1a7b8f23928f0a2e763e456b3f80936eca387fb646fe0729ceab8901b00628d8569b05339484dd2ab287959a3c95b59448f57341292fac3342e02bca444f72b99d5a6a03fd58958d647d4ee9f2c77a8e70b85fc5182b4d6fcf1d037b1da81e2326315ea3a25c0872e5b490d81422d03f849aa29686f4218afcd1f5cbb5920bb645f60d34e9df122708602e530a8da428ca00f9b535d8a89026359c7a38304fc2570c0e7b121423974553e02391c8b54241505155802bd326f939acf821faa1ca8e98929909c704d715aad6d97f0f1800b9936a51413ff1fecc50864a58f5ecc0c2c22f8c372f42707c3bd3c22e476f7affac852b8398cdb38104da26caa18137ab47389925931a04b353822862f595172ad2d6e3dc3a3f03364140a506d9bb4ab9aeb21f734e1e6cf87442b770ec1d6613894892fc07421409e8e012e3ee23bccfc83d94c5fc0bb5f4ca12af5bf5a7518a23a2ede4041abaf1cc0da1c5a98b3db68ee368a86a96cd45d1181c3fb0dc833f127cc91fe3402f60ac02a16828d0faa937cc9ef1d758088cb16e99eb3932346d53d230c92889fb4b8810862717ff7169ebaf08d46c4dd6943ce5571a866f1f3e61c6e7f21a61a3e170acf439c992ade2db92ed7e6620c5fbd11064551e13a855771f4f98494d8f9e880a02fbdc0a8ff51447b32d454c42ccb26ca90ba7f557a02b8609cf00f673572bde1e7912333835f33544597e89b159c9cab85f0bc022a10c97d30edfae61bcdbb3855e374f786532e4803d5b2e64c2b521f3240cf9a20778d3265efd7f9ec6726cea3170b78c53602ccad0c08a55f77f15111bc625ea2c221f447c7bdbfd303721fc5865d5958026b20cba392d3aebfbb3a0ab416bb579c85c064b624a049a889842f8081b9ebef572751d0a9b2286bdc84c42dc3a48d2d1a32de7d7007f8e953ab534d97028c0aa5780d98449109209409520d0f1bddf860727532dc22d1d5193cb5cc4b28b84804c62588350a9315737adb855c09e7b8938f962cf6764be0ca36a64e8a2a03a0522003d550a8c7d6579fbdce58d90e2a702f47eed847a4e051a9ce5f152536906006a13ac5b692a7b0ee260456a79446f80748874feba1900fed3f4ea2d1cf1a1ea074466a0dc8533c90bdbf2af482b73a840a726cca7437f10a10fcc1bb29f2f7b88a4fa047f739dce1e1064a8f9a1a14c52c62bf5502897986ccf2b7916519c0b45bc27a315ff9e6ed040d33502109d65104b491ca0e397447ab3091ebf684507000ba2f5a00077d5461c7b00e9a21b6a8420099fda630afb240d34079f2f6ae7d0854c36e2d00b6b6aa84bf381dc31d3ff230a8e6a20061b11cd8e9dd757d21560ba5f4ac56d095b132589b83ba19c200d36f7480dc4ca1f68a4249302c06bda4dc68502552038e9e0461fd86aa8a24de716363e1961e8aeddbd8e62d3ce14df49128485e1d493255821681011837dc762a44d2e47f55ee19f22f569a7525d102f19ec3dee9f15e328e7c2ced0f6c753162227e0034933a7fa5051c8362ca196b1fb9c0a16ca2f2be5d17114174cfde8d97065c86478883db8c803d44190b8a11b505f432071a60b4d35403ec245f255a0201c74165fa077bcd535b14a45a9cddd4b610e12801698a611e29d92c921c979520d9fa26d352a24a0d4c2f319f390b5336a2f234cc570e2475c4fdc570566613ab9297c848573fbaa9012148c2c5583aeab27204de3967365a103580b546d8d4c86a5421cfb180bed898da6321741712b0e5ff4c4d82bb68bf95339ab6230a78780f6b50c8508be9a4b69fd09d1c8469bb569d1c71f19a5d54fe9649f585e3b4d492ec3533a58ac7e2ff46155aedfcebb002a310775322ffd5a2a0202a9300f55c243f17ac25d814ff251d6359c5de31d82a0ddfdf0ae6f0a3d3154bc11d7f1351470a81905ff477a084f9780e6d8e9360bbbd89c26182c0ed0973d14698d4b381188312fa005327b1933fbfc2b943af0a058bda70065452b67ed56cb819046114988758dbc437a6c77c4386fef6e5f016760ce1bf7cf97f066edf444d8620e0feb056222130eedc381d0543639cb01054da438790f41684aa14eff21816ded6be5edc6f3b8e3b162fd1949f90d3edc357333f48baf7923418df83f78b0d8398da28f1352ce10f7ef2c1602080c2e7248aa293bcb87d679917e72ee0957e2e09feb786f6aadd6c043451ea5c0d0bce3becbf569c5714e89e8f1e6b841da7454e71af3dbf6088b43cdc765015b6ac5372391b0e0538e4aabcb054cc2510a98eddb9d840f57aca960470198fe31cdcf7d2a39647b58820f3e06ac526a1e2aae91933f79b4f7df9a0731ba71bc9d09aaca51070bc644e77cd97fdc5bad04d4d87a4d482064bde52ca4b3edc60f9dfd53cb6517a975b69da868bac43e46f8c8682da70be1e43bb1d160e52f97c279dc2cbfb430dcc6dd73585b74f692148e3c95da483271db92998bdc01a9cf0cea6531b3de089ff729adcd268030d22bfd9a697cc6338853ad3ae442a2b4ecacc6333f05dcc50ba521962d87069f7628a04fd8d90f3bf618d47d4079d410f60dbbab1f51784c58906d635090805b30ac1b491430ac91c7815c649d51f0bf840d34a4910cef10168732d644f8c8825fc9809cae1cdc4c61ece428424bfbd2ddb36a108ce5bde10cdaea9b495bf3a0f70d54497c96cab80234920287fc822acb426a917237451dd6d74794f00698393b0f82132bd3e7a46d25065c27f56caeef2eed667a51b83c1f1b33f5072067c25bd75abc274eb60e7665f21184d91ee076c6ed067fc020c09e08b79d6f3da97ef13441004508d431a0c246c414419030aa2fc780cacc9f687cc48cca51d86b6eaa02077763ef286c5f9dd036f5096f50c28b5f4b560e5469d9fcb13c20f0e113048dbb727b4968316f62de1159b87eee7fb580e29771891872f7cffc30277ac266463c5b215ace0c5925887782b7b6bbe03c212e10a0cde9ee1d420f1c9559cfda6489cb66d9e9a482dc5b68216a945a145d0566821b515b1b63915e4cd8dd5e8b54d1a732b25137e9d127e50c989d5f9deaa539272608a0359fa5f5afb82a1bdf4de1532c749d23012cc3336df63f63baa579fba82f852a3e5092cae94752a8892620fe8f91a06c394c6fa28f0a6a47622a2d59609c9782e5d216356fc5ec410c041038cc0c2415903b78a99b06c848b4db32ea64318a8501681ab2282a860783b1623d2d65becf7db56f77d3a09a011581020abc05531139d4145cb6f437608801b171ee7b159f338dcda7d796481c505a78a88130768cf76f7f1951d9f8a2a619c9d715d7a953ddad9927c933f0b855a3bbf6096072f24cd643e4d6c9e84ea38880ea513b8705cd0423008e9c831aa4dea9bff9d1b0ce4fba863a147bd32ba48c975916fc31f75219f0a78c9822d8f72c52f44838b10c74cb276ce16ee365bacbfc9e3d84c26d99f312c445ddc2ff6ae51d044e6ddc69580ac247f550bde4172cbc0b0addc2910360c832475b8179b8aafda44e99fef22a47050c36e7566f0fb91c7532e7372a628802eb3b52d3a0f8445dfc48062c2bedee05825fed81e61c9227c648b00461a3705cf833510af2a8be1064465d6c4b91db9d66dde4988acc53cf5144e14afd5193bf1fcba6ce7a298480773967b6fb78157a1c64600fef08524698162e3ee7bd472631c71f08a36ac04ae8a3cc1737443b35637f7850a5a63dc42754834a1612b42a00fa5436b159268452d09e17ecf50364d6c3f2c0aacf5bafc02d5a71b44fe822e9abc0f41a40e7268a05d215ae31fac9e6788c4a12513de736272d3c97c296a883749c6ecdde3664fa0ab722024e1a61eab9dbbb09f6d1311a10ac64ff446c5c7b9aaaafdd6b885ca5b5279b6cf3597fbe09856582368a96d0894a185745522d2c5c172e583c0a3eecb4bab49c5542a940783eefd51e89d6a15950644bd23a0c9aa18b438650e582bda18eb3dfb9173dd13f34206ba59b0fb55905152815f94cab5b7cd9834667883ad4922bcc091f5c09b87f7a565f9f2ab7840504a3886de817e9d38ea9bd67f7681cf1db429e6e094d80056f2fb39200e3bf1638ef29a54ca672ed73f2af5356df709d8e914b5c7c7300743cf76e4b47330279dbb4fcaf11ca1fa89769347814e51555a48950b215bbe86f046a18bd6b1c93a41840199b01b3484ec882f5fab54ea0b370527922f56c0d879b71145e5d7f138ff434512be1e4f3c7d3b5713430ab186d432157378b7d63ae48e513497331efb10e9fa1a75901a3ce08777d631d8239278b27bd215108c225ac80aaddcb75f46cd48f43e606f1a4089c06d69a050d4cf13d97d3edd0b38a85fc002dc045c6a1b4738f1d1a037f5db1acbc410f5a6c2c0650510507f560c9174ce0b72848d22408dadbdd68731bf4ed7bb916e0c88e1e0364cb65b41b5400a606cec5d617dd664631f41ebb152da2fe3323d6e9ee3e42f4cab6bb342e21223856d38a41370f76d20564335544b4bda21a2204ea40d52b1145959311302eccfa4b576eabb4e98690a48a8ce1bf38586e6d431dd2a6994a05e2c8c7dbbe3b4104ce0fd92f916265d3dc733fe85e0f0230bb85fb3252eec7e9f13b622fad64638856dd9e733384ed1297a44d91a355230ece99ef70befc208e43a091d37752d65e16578b61117f5d622b8cef2ea12707a828026078bcac7e4e230223839a3dba09a198711bc98569c4b869f5e736692fcc6f2eb77decb892542816ebc37a5b368ec0af38a7186053266a7075033e4942d95960d50926361149cee5ea33e341ec37d763bc075930d64664fa13602ad289da1697453d278a43b788c61b1a9da66437724486ccc1b4dfe3471cd4e6524a4044e57bce486ed46feeb86cb54bdcc91beb12c214f93924659f81bece4de2e77b1d245deecdbb8f7a88caf01284919866794e05fea807fcbd82303c3836906dd81c09eeda26c7f4dc685b637f3d4c38d35cd32f623080c13172e690bcac49094ae457a51c4df7fb3f3cf07a202868c79f2b01cce4f378c692d25a97eeef7b1ae1bb9df9ad01a7dc76431ed1fc69301e2ca2de0435ab9027553c351f2593768c88ee9998e1752e0f2bb97720a3a711523469bb43d6cf41ec9c4c4e0baf20900f1251c27bfb1f90b565ccf0029497d0796727eb81c25c971b840f6a703d2688ab3854d11ace3f075c510092e7bdb1433b5226725636bdc04cc710a220babacbc1aafba6d03728f078a373487987642d7483719f1809a71bb5a1bba42ef6d5a068e03bcc9c4ca002c02e0206c346ae0e6c384d175cec94c39142c5cbacba931c34fdb90d420e8695d48409701b28b69e1257a023d3c89804272aae3e09d439d908dd1f0f4cf5e8fb439212e6f2d3ece071a445b2218449fb310b752dfb227f2615ecb7446abf0fffb6e7a795bfa032a602da0cf6ec45891ec149346d0c01aaded28d9c087a15cea77a0d9294ab5e48c3f534540ce6714837be81c39701f583f1df2fa369f7111fb67d8f4c5c8d54dd94cfcad498f8e83e2fe2ab1ec857c4f5de33ae4da91a78aa24f305aea033b983b60723ae9bf7b55b0cdd7bd4fe6dd53525a3e353442648c580ba0ba6d46cd20138d0235b2732c0ea59bafafcd4cb28d822b3fadc96b6660c4f5c608608be89d7a5635e13ca3c1c6d91ebb7c2a1f0167a6da16397ec0cebffa0390bf70e48bad90b3fff6f2b42f713ad0bc4591134749986721ce686c8d5fb9e71318b5967e5dd4bce83b94d15ea048dd244cd3e0827be122b09692c0d8072a94f007b933b3c1265a7e61a039ba9fab3ef6481415b57640f76894078cdbeef21a8c068c28705554ea05eda9a0f8be71bacda64ec61c9c2c810f41a7a9696dd65f7accb0e22125cc6e6f168831731ae2110c2d4c5a823ae41e7e518cc84e4802ac93f149490c69f41545fe86afde41b6760450060d80d429a06c812b8285f02011f8378cd4a94d8e02479748e0718d2430182cce2aa7add2456594833453022df6f2736049e4a3cd8100e51a0707588f69da2fe0b109603b0b5b6e6dffe8949564ad1daefc6db6ee5c2978b6e4fd97bdd6868c8cc3d871b922036d478959e58289a11d7be2e0fd4e30fbe030302bc1f0791623a6c82c77ff0f4d16a91f61ff6068632bbbaf5520f0d5f533504cabf152bb9c222e19d5a72b62a688cfaa6e2d54057c2a00a5fe737960dc33726e5494c0cfb1f6553dfe59f29bb33a26aa5b7166701f2ccd0f15cff910fae4b1c755624f887213a2057bdb4ff8c0d6939865a4b7fbabaae3152ee58ede9cf6657dacc74bfc7e690fb5c26e912e5826d53011b3f1a35e7de8e8823c3f1a7546e6048ba49e20fe66e1cc5fc9f30a724841e491e7ebb45250b0529e11010ccbbe2b1537ae289f7555d911b09d23a34577c8fd12dfbce2be68c68a9b750d3d1571bc880907f5ca24602c655c746bc2a5d25bf733e63d47981bc9f5c438ad1e58af68239c67cd79bfb7a72d7cc64c9976146a780581130805aaf099b1d7b0f2e8e45ad58b5a835947e6dbc6c0f46cb3c30f6f3e954fa837ddd0d42a90e09893aa435d40e6c3c4701234f5f6c1436becb6826f2c0d760431744f49357a9091ec68649668fdf4c1b4556894e1f8a97981033a15c84cc5234c810eb0a5efe6f7253cab66dbd24849111069b2d88d5ebb906ae12dcb939a2457f2b2f3aaccfa2a0edd55366887cea29fc58e8c5fb34a5c9ff8f82e6b1ad079f30323e12ac30fdc4992add79c2566a250dc032ec3236427fb90d81b4365403b39e4a71ba26bb9c77aca7546e88199bf07ff0e24cb10efff8a286122b2bdae84016da93a0cf988105e3f57c13d9f90c0684984d58b16df506fb4ddffe1c5921056fe76cee46ba12962652f660504b6940422e578c3d389700c44e90020e1c9a990d90883ad7338023eddb53220fb8cb6fe1784cf3988e439897e1f065bad668f2f33a2cdeb1a3d54455e6d35ce2fe56338f1f01210cb06b41e5c9e3806237d30d2201c19b04d801ab291431a4cf51d6914fa77f8b2712da68ee6f0bb7bb898b720c6786b1fa6dfd9106d8834bf67c6a70d28132a7d707faf862905c79800a27d66793559efb612a6a4a13678d5667a9dfa0cd06ae213e3228037dbec4d9b1a2daeb7aca71478c07efb19fe0607588188f8c4db6688294c5184a96106a8ffca6f944e029b28219aad65b2b431245623baa2c1f83e9cf55cdd3d01eb483f1c16e4c21ad68a9b76f12ae904bfb23d14691a9457e9a6459b25a3e8cd5a12676b5619b7e8b6ab24d59805963a0328387d653765239b861115225fb21d12d156c70285fddb53916eb64912b8e80c6039f195dd348b6c1a0d54887ca96d4844371d0b2c0cf451d0fbc89893f80f0dd7b9eac1a8443818bd72ad9d6fec40644c0733d41791177dea2c1a15dff0e67159c8f3870304191b3a5b90ecff9fa071222b7121d29cf9c853fc0dd01fe14e4a89005d945d3dfb81a3dad0980addb0cb18a49ed538da782457c7fb7f52b03963a1cf6ed3a596041b449acd84107dde660a56c014b738fc54456a7e6487e2d5f955605bbbbb259f13d5a14d4fdc61c04276b714710ca8ddb0644de72f71dfc4c3f8f5413826f5a860cb7bde0b73f866bae86c39d35870ec67c51c43b7fddb165cda23cb93bcf182800a067463cb6cc6406bda7877eb5604ab0656aad275f3906c83fdfa4303b817a02f06506aa9df72a49a3dfca13ba3ac8a0a779bf95b8d0268f21ac262f88f93c8501d5b4b7348aa30e41d9c169b370ec1929117ca3044af96d1ca2a2ee3c8f9810143bf7eb8a2540b44811ef3027d72e263546e2ee2180a5d88b021258b31acf86af95101ed60dff1b0941dd1a991c855a11d6d7a77489831217ae4cade2bac440e4d2fdfec0c5f9634f99d86f684fdb276b2d9bc8a0f55ab7ae8fbb91d63db9fe2782ff669a1a28ac5a18c60c875e3ddcfb46bde2c31aa7f46f264e151270766000f2d0710d6e2203c5a69b624557d6797300f7da3f0d372667e201206f2627c96e99cbd55db0fcaa3f89a2d30d375a70fa00822674351a6b34574038e10f956c5c2c8d2ac6cfff6a459a5f08867a2d0a20bd9efbb042a77e9d0ba248cc21ef690a4a0601325c9f00c1d89ca52c9d95c0c3c057d35992c91d69ad0d66addf42a60a5a8d44be719e3db5e4b7f22ef72154262687dc7fd1bc28bb9111329a396a7227320e7a50af6169416f059dc2608dd2a19d34e17ff0b55a821069b6856392a4529aa4a91fbf1aa60e8f62e4ed6883a254a0e1907004fbff2d3cdf61c14ba666ae3d3fc0458d9d0bd06d1953ccc799dbce98b3095f74ce320e66eb5e8a789296a57af7d458193b1ff821849bb7c0f4135ff4c4e111853211de68285dbc29c881d846bd9bfa182ef19658fccd30107da42b2ac0e82fe0895e976e04089eadbc86e7f7ecda79684f9c5ca51d1e4ab08ef9fe8091ec9eebf9b9f6b45f75f2304ecd595d4ecb636d9fdfad62197b189135e4370ffec550a3db1923f5aaf081c4bc89293ba6ade67ef59c713e0b667c6949dedc0076e8860f5af92e822ce974bf0a5269b9ed8022aa996c5aa0b846901d26a7c7246bed4da1b456759d9d384a96c5c457e8a0ff4970adea44cf2675740dec1d138166b36d7790f6b123c8865d199a6231d8cb7e8fe785a0ec340ea06ca873662863d1d8827e3d04c3f086931c15be6747c89c26664faa7018e7ee9694e40570c85661742b19d2e3c6827b4c827dfa518e80854cca6bc4e31e0b23d12694548ac71d6ee81ec6039b438e57fb3faad22ae4c38dbb58b872a35c0aec4255636f3a96c975f4bc18b07b83edda5dbaeb71d1be6e7c85f50e130b29c474367e0fb95ccf01e45cc9f4c81ffc5cd939a9f6befff658ecc8bb8c45988f935ed5b8bbb60567de857d9419f622c9a3eea06a028b19f75c6d7e367c6e36d448949f9f35eb619b30a015670e5927bf99303a6057c3de22cec8dabb52184c49c3f6159a3f6a067f4e0203aab2f6633b4494390cd8076695986398479cd0cc172a6d3f8ec3a97f8be2d01e940c47d238e21af5da53a752e448f994515a03996798d7a77f8e39c2ed1ffe9c12414fb88438a797dd6bc8df8b6e112ec792f0a3b2fceb2fdc59ac42db9588d10f51b2f0f510a65fe8c1c198593c86947393c7ce68340ef8120e2fe696b5f871a844af54004737fc420f84f5f6041f248cc8000f36ed1afb811e9a75ea823d84712d13e40a0abda53cec532ed77699d660ad90309e41e326cac44814e89accb88e7332552b2bed322dbadf7b651163ade2431d0f07ebf750c62551c60a2aca4ac94897326c30fd42fa3c9a362a46cfabf06237398fb14b9f7af9cd0037bfe8c1f51c818feec37dd3c0f5c1353d1891580a362dbd9bb489833329b68047ba0a6d8c0b6cb7cceeb7b494ce20992329f9272b3e5f665702e74b306592198282cff24d8a8e6aa8cf57c507484f9bb1d390c1dca12d2855c071272309288ad138c8f3c82e618a1b32e6565db5528c5e1ca594695dc596cf0397badde8684ed988de094880ff53931cfba8309d8292cdb5be841f3de82e9eff737c14c2cf3ac5f1fec80fdf9bd231586d99d755aee2c6292b865c6e27f9b648c4136f2e673061720db82dcccb1cb2451d2817ce7395b677ccc5632fd183b433f880cab5ca5a49edf0e0881c58132a1d1ae4232d23386ca5c3830c5da01a3c2609ea41f19e9933cc95becd56b7cecc4308608c4e2989d6b1a52cf9248962be64c6ed8b7e7ffe982fc733b54f92416b81a1ffb5020d01b085a391ed61ca36583fa85cd546dc8d1fc4b1ab3e107583a854dac281b990b046df140b35b23263cb1a6271232f84ed6c16cf5e1cc7d58d978eeb0c2a2fc8a6e0cb1c01f9e447eb5cca109830542ca53fff10c32e8c24d10c7af28830bbd4fecd9e04fb5a5279b3169445e2c7ce095780cae16257171215fa64fb153e9fe24e8efd95050247cfc265a705bf337fb152a50d1ce7ac4c988ac36393b89298cd59aa703c936a881a29862c2e1bddc251b9bb02a3a2744ac1b9e2532cd596856dc8f6a45521f50047e3cabbda5bcc8ef304a82c7c78742e56a218c7a85c0a310ad0e56164a0c91790058cd53c33551614164e7f09e6083242801943b28d271dd7e6b96b08631f553b6e3858c31380d5d9ebc32bb4a0f3e66de48fd861d65284083d5213219a0a47b8203ab2881f2f508293e18da4589e1d2763ef1701f831198ce99761233bcf5b498f22fdbe4d2e4632fb2885c42bc06116b98b64084b42e5543a40f4ac7c88047bac01094201b7ca003d4005ae9d4f44730750269bd7ed36210268bb5b7d958e56a1fa057b9304a2ea6c531485929d6e0561b8d20bc5d08f096429bd6febaf525ab467e964539e8e30083baa8725fd631a13546e333709545739e09ccb845ac3917ab2e5015626d13712a6134c45a9978e369e960252026d4b9a784d40fb09d691fd8e5eb267592054fffacd957e61644fb2ee78beb36362c408dd1298636546d39760dc1b07b48b048b5f6bf0fecd0a5cb12b43fc31ca48bf5cddee43ab8cf845181db0a5cf64f62900239a64ef09137dfb6d69c3c26164ce67b5da10b78744fc684836e491851881014a02c67dcdc9686fe3cd50f8097080897ac274b4c1d0470991f44d19790edf3c33709216ff5dc041e06552b6104719a8f13154068fda512a86a53ae1ffe99eae19190c41468ad3a40d053fcddf96b05efc4cbd01c58e31e0f2a9173c4be95f3427e370f8c1684845147b643687a70d3434acf7fb0b6d32ebb1fb3c3a8941180b090508d677f7b8d642a9b852415f3ec8d0eedde27ff6dc192c961a3d52b1fcb98bf4b937ce41acde6e0b3abc1ae39caec8272f3098af83a77e7d27ad37edc0fd951d52c630181f188e3fc0764990168d181cce8684380dd0492b4bcb1e806a23b9c9eebbc00af3cd89d5f2f00c3981a00eed45a1715da5b506a885da4e047eb0a076ad72c935c6e858dbe9723c35126555a73c5574e0caf19f007177cdf244cc18e8a6a29ed7186cd93568fe1e5950e1e5bacbce62895d3ee762a74a7129a474312062d8a1a1174f7c8cf0a0b4fdddfaef4c1a1cb6cd0349306206cd834b4dde162b54fe552813cc6ec104b68a451b878300221d4741575f216bcb3f1fd2aa0746355dc59a66635c4a5b0a804100c21dc2c34294660f0517c66e21f1e32b64ebccb7ca2b3eb807608ed75ace8ad0be196d6eaaad759b968b431be73afd5e2ef698144c40d894d00944f4558ac62e64a422957d77a40a4b0161b3ad71761028573c7cdc84e1fc6913c5354079d36b06deb03733437d7991c078972e001abb735d3852ef6af57e52c35ca74b0d05a85e6d2ed96d38c511b85a5d9c55b5e7e1f4ffc131520c60fbb4238958001508c59cbf038d34c399e806dbf5a27a244ae5c45b245f1531486f9325bf9142170d79c580c9cd005fb25947dce12a1f92ab8d66e80230a54c773afd1ff22116113950bcf0a884c952282d70a7abb59e5870546acc0256e2229c9fe3da6753f19ab8448de781293b8353c4548c78431858ddd7797be16ce0c3ff0bb6b67b61740032fdcd3e52699b47d663aa46594bf99edd0bfe8a86c8ff12ec4e9aa12fd7efab5db754ca76547548a92af8583f694156182fa06333b3fe34226e100146c4724ed6737723abe574c5367c85cf224b838979b78c0ffd78b058e7fa50e96853f30e4233602902d0a04af42ae5fbef101426af41260b09a244018f2e95d753e392252143c574b9b51227603f5684791ab2b85d932879a050a68e99a05061a162a471a2b477330048363060a5e06c2300294fa23fa9d566a1cc41f8108a7c3a7528c632498746c4a096c2d70528df611fcd02aef9a32ff350b35665329dfc2320533d551057019f3791e6e42b571f04b1211e18f095f0d05514371cc03b71c752e0fa892ec08a11002b76c7280ebc26953e5b01e5fb30b9299f1425c5b72b40acf5c07f2424232d4e4e4663c3b39dc03e32e73a920076aa3c328db0ed1311a71f0326614d0d1c1fedb8365f315e04b3c316c31f7a74517a6849345e7dde0bf0ee4df1b85f33085a6748d1c51fd4dcd7a2ae6a173ec5a3dc69bd9346bb399c19878af728e9891c19786093e86cf3ec4167527aa4345f675ff16ed23da3c648463fe015741c699ecee8fba85902c365580886cd3375800ec80cc04dd6b2c1dacbacde69d5a9cadaa28ab1108150089d7d3c209dbc2201eae15f68ed483bb9b9506ddde585948ad864377acabc830c82ad14296dbef58efb9520c265328d1c3470cf8f0b56b4a88dd2b1340e57942d7b4269388794afb3a452db1ef25b71eb5f643dd05f4288b5dc262d474a67a2e78726e8d0933c99bc8e797d73c1896613e14cef89ab36c771379275e7a00d775a4a7aa085a2a73c4643020273e55d61400adb0a113476537fd8805e4ee2ee46bfee6d7f87434b668904081fa5e0f18701834fa3cb099e5d1f0c90ce5077cb097e9415bdc132f281711a9ed188da63ef84431735a5a7e74750ce9b146dd05e318bd0a3b602c81918892c02856ce6e6a01906a07f4e7b7396aafe005ff9fbdd0b9e2477065820617617abe2c607d75a1a44ab4b4e3b0444dabaee7b583b3695bde2599402533a3b20ef5d5d89264e799be7a89e65eb57dc2214b47036bd99c6c204771a1b453e49333a13de3c5cd21789fd94a0ceac3adac0e8f37e3aaa0d1b81b0b408ba25fc0a21e976f024d6bade56226125831a11ee174653fb68f8eaabfbf02f17a37235329dd73b972b493789197c8ff9a3172e40948c9e057d3ef35f0bec051c269eec734ad0353d532bb81fa0e0710fa54ad85ab317326e86a5543c7cf183587f48fed52ff3f394036d8413bd110b2891e45f681b1b4aa75cec9db3c64ba37259501a31b99efe8192435402a91ef44b0867ee30919fa6dbc4c21b84589d8dc781fa95134fa8eb333e1861cd9e50178d8dbf1d1df7c2688f21530c0d328730130bac02b2a8771b6c0f85e6764595f14407e5b5bf73e9822a0fc71ebdba3e3dbef7c6959ca01ccdb76516c9ecc4462a93c2d01f31f065f7a302ab783cf1c4ae16b35f79a4a98e5195b1d5457521ee49a533f6e93400f772565a59dfda43dcdb09adf099bd207c2cf37148cf1a8e8b1aca1f56745a9882493915cbca373875ef6335b18d271535e3ffb4a0d45818679a5e215b939b243812e8019d32e555c6746c6c5696bac350051d7ec33b3b02c62ac93f3735bc4537c42a262a29c6c876dbd5caa0a28db465575a4b0c1f2cbb0cc65b3b55437983b95ba8383b8caef0fbdad1e9790f644aa5e598d6b17bf55037d641adeada684f36a483821826cb707bb3fbeaf8c72c116fadbd694e6711205b3422abd30dad5bb061bb3e9b6dd2fe1b255395a22b423ea7b4f6783424eab7377ad5e67ebd021797ecf2ec031e91580837c94624c43e404f82b38504625748209c914f41b87b056be5e5fd9dbe4ec29231c923053eb5645b36ce3d5d13194a654a50e0be21a113b2bcb8679f6177b5f15af16c6fccc9d4e0b94d74cf7458e0cc66684aacea0abdf7bb75672825f59b4d4aaab0657f3ec6c96399846b4bfa1b2706a25971aa711b62755d57f0747159037ec30d392a058fbc7f85c193f48980a216a1337928e4988f7f4e31f00c09660dda47f92b5ab673907aa11fb6d762e809c6ce7d3bf837e7217cb9f678ceb6155ca558eb256c415e8ea577553cb4a8eb2a2881574e5a7e256ca0aa772a58815f4ca57e9564a15aeb2528a2a68ca97e25296142ea556883d27b0962b02884a8e95a0c28c1091f70e4af6b7d268d1d4eaf4cc5893fc714b1c6a8378a29428085a74522bc4bb52a240a3950eda82fc5192e0e35bfde6fb87cae9f7f917643c5acfa24f24249718e86f5d4f8ded08b897e2a52de85768a8a058678ab8d6c9ffc6043c8eb1ce63690b0985f501ffa75ffc9fa12b0af24f7c7a857eca9ae257575a0fd267fae72e513ffcd66fff19b446805e14177a439f5287a0ab0e1a0f1a486c51211cddf5f46d261fafaf3580faf4867ea547e34a775a4fa327e867cc57fbfc81487d505b987bd7f34d22e25c1eaba111fe723f09d45c9ce6ccb08a5cfdad5fbc0fcd4efd4cf1a30bade7e933f9f38a38dd17f1af55a3204b545bbffc175a2717c545eb91de13de5208d75d9e71872938ffaa476fe8afaca8e147884eb43c6911b16505faabdb9ee7d032faedf4b8a81bfa951535c4f95ee0ba4c7fb322cc2919d783630d0aa25bbbf8b84523a1f9e1fe004f57195319685d055506d994097cc07b137651605cd8814acab51176a7c68aabb90a91ef5b24fbd5782d0e79e940820f3e26f43906f00a907cc1e9c0d7414c6d28607c7c21352ae5b5c2dd8e6cc8ef7bfd3c4c49ec516c702adb205d1b5a0ccce18c8fda56e418b66972ec0f560f0725f960f70628ea69ef092dff873b66f6579df76d0b119a71f05b6f4dd9f2e1150c372edb745734d6f9f2ee7a973c71b35b5a4dfb4e48d1bd0a6eda3f49ee3444acf1c1261b558713d2526f2b37884f4567ad6caf9b7db7de803c7eb7413154b2a135635b850c4fb2585145cbd935647ad8092f5b7a178436047ece441f11501040c2923a468ffb199af514a9cbf5e765d571a71abd21bc9316e70b0ef541cbd584a547aa549fc7421583fe249432dde7304cf7391898b7dc4043fdf31f3aa14e4ac0dcfeadb5ba8dca6df7de52ee1df510c211aa105dafd9677f91af92df6f92dfafd7eff7f92de87a44c9b225c32adeef159690345eb0c4b0a6e2fd9228c3c46a4957588c78bfcb0c5862a4b13ad3020e47bc5f2c35665c41986a5b56f17e9b52561c61209912622adeaf46912e691475df9bfbece9eeb97deee9644feeb3f7e492bdaedf3d24bf7b477ef77abd1e5990b31460da1881d215ef5ed5979345142346b61c89772ff9d9ca45db0f156f60bec4bbb79481102d36d1aaa91e21e2dd635a3181d166e564c75bbc7bcdcf4de70e28560d1b56e2dd736636bccc8627fccd9b9bcb47aa6fdedbcff1e23e3bef052f4ac9e3f178519e5b9674294bdde74473a239d19c1c1a39515cbf7372727272a25ae6426885f151a726de39cb33272bdeb8b99938c63b8749245d2252f7384d9c264e13070707a7acccecb3e31c71a29abf7194467ee314f98df3fce20345520773ccd59678e3fce4c8a164e1e6e6c957bc71dacef8206bcbf1e20b8d78e32c4b9c388bebd292252cde3841d0844c8d607194638b370e8b2e56584a444c9d88378e33cb4897b28cba77f3d275f352eeb3bb3a3efb76a3945a9f5d379a664797a6eefdf76e4e6e27b79393dba9b57df65d597eca53f948f5bd337bd23e69e9a02db485ca7df6b6ad355b91c695b5250d9a0a34f1de318d634ebe52849541a123debb2591df3badddeff76e37e4dbb956cdabce8ba57b166eb3723e65545e5260deb45011ef367d7344a9c6a2468c2942e2dd7ad98811f684c71ba928f16e971f80d9ba32958666cb8d78b74c0c9c41316122c79b1bcf78b7cd058c3031e3ecf9542325dead73eb77fb1cf2bb15f2bb55b6519fbd3d3e9f9dfbecec312ac86f56a9f59b05f29b7d7e7616ca9ab16a6c9b1cf437ebb6fbcdbe6d386ec900532404da9278b348b3105c6e6c41ba3189379b7c4184068c1b2198c859c59b5d7e964135e479a64cdc5cbcd9b21923c44c88f1a0938a37dbac00444b103837636f5de2cd3a3f57a54b6a55ddcf295755b9aaca755dd71e3dd635bafef8bd2ab5d6a72a624594352da4e06011ef15c9620b9b35415484897989f79a3c41ba34a6ee35081a4ec3c969b5b2fca446e523d5d5286df6d9f5dbfa5b47f9f8ad959f758fdffab9b31cb2e304720e4d8c786ba4037cd09032f38508902ef1d6491488a9522356c28bdc8e78eba605945021c360a12166156fed9440ba44979ed57dce739fddd2729a26f7497549e992ea5ba52bbac115d32f39b8df398ac7efacdcf13bebf89d9f6e9c3da7e5a804a2a6d8980873c2868978676408596a598e5934acb8c43b675131e25942078b3430e29d975bb9a349c694a224de99a9041343c5aacbca5c9378e7265286133146b8acb525e39d9dafce7d8eb76af624807cb4d957b3d720edc0a64baae7a595335ae2c4ccccc450309080a003a3a4cc491c77846a4d9b1c3d8e6cf156995f82275c3fd284d01931136f75c9c30a0b6d69b60549166fd5f931b08478b91961a2b68cb7da64fe569f59bf55ad1cd9d5e3f1b3d3c07513909f829e81fcb4c6d941909dd22f36c916c78d576d7cb6a2b2046d0b6d8c9129713e62e5cacc57979b3566e20dff09ba963ae2aa760c898214238c9b17346b405489a1f453015a34b9546809f3c42dce52ea5e8095613ae98a2f888079c8bc51af3acf1838c806ef5edaab4e5cd30b7bd5896ae0ddd37ad58172f4ae5e75201cf0ee21c57861f0e6455ff52523bcb2577da908bc79cd57fde807bc79c8577d870cde3970af3a052f78e7a4bdea14a0c03bc7f9aa536802ef1ce6ab7e7405ef9ce4ab64448a3cec449975a4fcb4c6ac37b9ecd308f1ce735ee3cec5798d2c54cf14bc71e45e75a012de38d157bd8704bc719eaffa8e1478e368bdea14c0c01b47f9aa038dc11be7f86aef77f0db263bb6be5dfbd65d16df928d697ddb84c78c6fdd7d8dad03b9487bd581aae0ed3a5ff5a51c3d5ef5251cf07695afba121537ea55579a02ef1ddcabcef445ed5567f202efddf3551f1ad97ad5874554f751b39b7ad57de2544f4ad1f6aa27a180770b7dd57dc9b6eb55f7a98077cb7cd575d6b454afba8e1af5a9c6c5af4e1d7e75275a572faeeeaecf346f179ef59d537ab6e35b6fff35ae503e5dd25e751f2ef0669daf3a8f1bb6c7abced306deacf2556791faa9c722c1de650f6e1815f7aa0f45c07b8dbeea4725ca5ef52312f05e9bafba052eeb8d57ddc21678afc9577d2886dbab3e64056f0d7dd52d58d15dafba8534786be6ab2e7c837f4ca8aee3a4ec55d76902efdc7cd5878ec0404e78af0fa404d6716b7bd575bea84efe29196b472aea2758bbab1d7e9d64c4b3189ef5f535b2e9538e5b82057a8c5777d3a7345e5dbfc615ce504efdd483ebc17d521078f75ee5abfe2adf2bd58917971fbed63db89edc908e1eaffa101386a5c051af3a0c857f580c5bc07bfd210bd87784f7faf01b78bbbfe1f8afd6a71546e040cd603fb41ed64004bd86589d063e50c07ed63a5c5d84540b90a863cce6cc8a519510114555c44423a894d83da55a23bf231aa1f53ba211cbdf118da8fa1dd188af332c8846ac389f7e9d31c1cbe2a50e2622ccfd3cdc4991544f85388ff3e96bcc3260f5f7ceab9eeea41c5209f052a2ad56186e10be82abc20dbfca0b40fc193e3001a0d8c112074a1e923a2071c0b0c105a8a327a293d106cfce41ed50d4e4d93bf8a076d090866d759980b3f79a5d01885fb8ba3db8071874222252b109ca4306269ddf4fd0d0b0e8825206270eeb7f60ea80030f1d386c00f5e4b4a1c909ca83da218333b586c0d9df1e5aff0100c2d5edc13dc0a01311918a4d504c459ddf4fd0d0b0e8825206271d0074c041d1c35207250e491b20416178bae074b481d864a4c1b367503b1465f0ec4e6a070b4c1eae6e0081b3ef2c6f00a0030e84abdb837b8041272222159b8a4b3abf9fa0a161d105a50c2c071e96386c00f5e4b4a1494306a56293daa1089554aa80b3c3544a0e3c7410ae6e0fee01069d8888545c52d2f9fd040d0d8b2e28f93a70d840092ae909c909c3860b4d471a88198c983cfb05b54351d1b32b15d50e4b4d9f5d8d9ab282b3ff90531d386c205cdd1edc030c3a1111492949e7f71334342cbad06e0095e4b4a1494306a66211116908834cd4c71470761e1aa8c70da09e84abdb837b804127222621e9fc7e8286864559d8f3e4b401a90983860b198e988845a325cf3e543b142979f622b58385a40f42d00167f701218427a70dc2d5edc13dc0a0132161d0f9fd040d0db370b7a1094306a6e292d2901365f780044c38fb0f0848b0a1498370757b700f30e8182ee8fc7e828684401a32305d281e2d11958c923c7b90daa108c9b30fb9da01c307449f3d0219180167075620031a32300957b707f70083178e747e3f4159e832158f9492907e80c1ec0568c012ce2e21010d602a2e0957b707f7008f883abf9fa025a52422921106cffe533b1479f69e1fb58385a3e067f72000197076a10f0258524a12ae6e0fee211ae9fc7092908c2e1cf514a1a8e0ecc126a824240cc2d5edc146453a3f01c305cfeee6a81d8a889e5dc761b583d1073d9f9d080909671f222261b870245cdd5e514e8ea76a8723cf9ed50e440b4445403f0167a710f423a2917075db7723cfdeaa1d8a2cf454c1d985708f91305597b21709b3ba94dd82705597f270e8697622f2ecabdac182e7e10e210b8b25e09c87ae0561aa2ea5c2550cd6c79f4f27cdc40ac2a1d02908878413841be9b5078542c220e19620dce9f3b503b50369ff11fa68efd1ce23fc09b71ab5d5a91de156afd41baffd15f6b4f3845bed4a9dc062013c80415265eaa735867370861bca99b61bc26df588dcaa721d6e554b6daace57919e4126cccb6bfac35e266acda64e0f50455515aa5bbacb43318496a9e5e1576fa19a3cbcd6379a8030949a54b645a4a6d77a0a89c88b30508f48bf7a4b2472a40f741c11f003a2076e1e248a809abf0ec221b0056833fc41f035f0758fbbaeae57a80f7a5ed300061f0251cf6bf8754f5d3d84dea6c1f732b1f7ba675d8398dec0a9baa47dbb21e887250c61f2210d40fa54d4c3942d3af9500056983a3f08a00009284235115913a2450c163088704df5d002a3498e36b8b9b45d0d109cdd80a291e27a7205490ea499184a3265a4d020d6800162ca5c8b12333a10240cd616313b489435d92d556431733e4db8f0e1230d43420e8e39468683cd12ac74c90c37665654903abca08abc6963458559d447d70c0e9078a21c2283ce0c8c14501271635a48aa2d44763246a06acb02724339630a97a11c1cd8b22e8999f3c7ee4a4ad898b132ab31e6981172a4c92a71d5050c1d0b668c1ad09d0d6162f522461a138cd87ae226e608983735acb28499bd3519a22441868993a926ea15c743c4158c76075ab30c0815254f00c831cbb26ac0a07bba508e10a4ca0a855b11164bc856266457369634718e255fc02348c88511c10389a388973354dc9a785102559e703164a256230574c8893637d2254bd6943bd89c8d5929a3aa8a3b2367a0209330b1e165ea39972684d4982457de50bd2e662254b1a9b80ed32c57565c60390b83c21801479b3151da8030a912126b4f5fc8bdf6353fb5b16ee1ba30b04bd2ed11731645b37265ed4b89279a67cfedf9e2c973f3ecb579f6ac9ebcb9679667ef6d400440082149a5b5958939e7b575737a3af0afe707089789d9dfd7a8c665629a526562f6a19e76d34f39a9d5f2930aa78fb2ab6dffa442c3f293aad5d44f6ab2477e02019aa655a6269d705b50e667cfce1c969dd65c969dd8ecb4c3f1ec192ecf69a4a6ca4e3ecf501fdfd9ccf59dd57234c7777603f29ddf3ee738a0ef2c27c1771af67a2a286b6516d26321dffaeab30b55c13b6bc57df6dc15a67af6bc953b086a6527353ba9aa191dbcf3f27b64a71d427b83474d6303ef7cfc3ce52147e50e8219b9834508096f350a7d836a8bbae954099a83b7ead42a6b0a733edf2d2ae0ad2e7b146f2c993d362978ab47750a292a77103c66271e9e901458a8050cdd1f103f0be971d0793c3b08720741cfee0109b2138f670fe6bc461e21702fe7fd09b384bc884c08e735fa7a54e01e1816660505b9af718757060e027584591224ec5ee3cb0513ed5e176601bd880cd8be465e2f0c466a5f621690179101b1af11470ddc54ccfaf9e1bd813d4065f9f8e8d7c89a81059089d93f64f5788f3087e5a39c9d6f7002de026462f622b2e71167845ff645013bd2038cab1994e443010490828d9896e4338a8cb712e04832828514a713292f72f0bce002000b0d35b27a4891b8d1f5266563828b962b38aab495b9c0b2e3228c87155e43cacbc59a2c176046d8d2f1e6268a6c88153017553a2e6c402553316c44d0805b21638d8811ba4094a09b92c56c0d4b159ce8061531985b43e40a4d6acc589a2125e452a448b37cabaab156e560525340b9c39da75f7e374645a6e97755a08a395c9c20afafa9b77f3ffddad2e2799f7ea5380384e688e1a544e951bb480f5ccffe21bb03e55cd777ea064c83a1e99308c5b2694e814da6d399b314217a74d911963bf68307fe7ab8aa6378699abade39859c739b87bbddb16debecbaaebb765dd9b555d7acb566873e74476855d6cb8eaaaaaaaaaa4cade69245aa495855aac7d50d4ece03fd74d33ee4752516a15cd54feb71754fc0e9675555b55eb3389f073c1e8f209c71da5499acab48f5e881a76e70c39d46d7357d02a1d24d74fd43ea749ce1eafca37ecacef428e7657a941da884934e15e9bac1cb0ffa291fd3a3ec6a34559de95176605a4e9f4028b8b889407837dc70f6d6c98a306ccb686ecb4e6e6e148d0c2f6cbfb37327450606f73b2f5b345e57c0fcce47368c8709b02dbfd5e87aa34533a2edcbaf2b4fe79ce1de1d29abb56b6f9d751aacdeb24311325d57f218afabaf43364d1fb1507da4e6ccb2e1a5449b8dbeea5b3b59f2532793e6a7d14f9d4f1faf932907ed4c93d407e458377316e244fd8481ca9a35ad63ac7a513f8da044751870b06ac2741e637584587535a92af593ced89426c963acbaba54d3321cd0bcd44fb9998f480d4672b8d18a55cfca0c85cab9a5e9a71c0dfa99730d76c79fe9f1a683eec943457c348b8195654bcc1b3171aa9fe02f307e9860e162f926de2954c7b3ee489ef50f4cbc9e8d2165cd1c8e64122c2562960991675de935b2d1a4d708e4fb9f1fed3f3f3f5efcf911f33f6759cf863deb48af913d5bbe760caf51fb85d7f8d3c1fb58997a1f3f7a8d3e55c8bea7c7813d3d4e84949d7adee3c51e874aabf13d1e7a7a3c03704f4f9a9befe9e9e97195aaa7a7a7a7a7a7c7d3ae07c0fb9cf81a7d382ccbb22ccba60d799665dde835b21c3cec699787bde835c2ed267eb143152dafaba4bd760b4fbe8736f73d277a8dbd295832a0359a4a52b869a690239a5b58149692241a9b6fbdc2f035f630795a80781e17be469e249aacdfb913edbcb85b71f53b9d5dceb1f30ae82737deb907f06ec702c4ef787619c7aee7bb9d6fb77395c9e2ccef76377eab4e57cb76bbb4df95e50893453906bd428b772bd2c69c55dc8480897735b68e2ab69c993961b32b71c5668adc0c2127e2ad1e1b00460acd985609a913f156b57e374304da1b2cacb934f1569b2c64fccfd79ffb6bfca51beab5a7458741e135ea28ef13f23e1f7a8d3e2a5c646c754b46f47a36be97467f5c9161e6c708b9b0b8b762c7f77cc26bec053dece98a100f7bf035c26e0a8587157a964db27836197d56c59a675de835b2331041664819189116ceb6c6b7289ec059b9b9aa2a638b5b1564bef5a0d7d8ba84d7b88beeb039f91d07bec69db5bad7d1a1f13aee441d9d2894d7e1d1c94b9dd67574b48e0edb91d7f1e9642c1d5793fac98d755c5566a7f475581d1d77f5130755564bc450a188b2893f9c914aceb59965d1999be286450b246d55749aa8a1359f69b07ce978aae33ace46d99e6559b6132cb0f75a1fbd7658ebb503cdbc9612affda76ddbd65bf7798d6d85dfada9fdce7b5ee38ee735eabc9e26fff5df6b7c753c8f37e379eefac98d794e44ca4eadf3bc089585ec791e783ccf40dac67310b253fab5767c5edcf346fc5691cf7335999d58e7b94ac5bb7a1ecf5dfdc400e6162b492026c68cc43c4ff55304583411336506848813f1869d3c4f772af73cf5f83cb4eff5dcf71a7b566bd844682193e258176ff8595606084c7489ca5813e24ccca6a07bd6e1d7c84af89dd6ef7ce735eec6ac7dbd09f14241e2eab572ee4c0b122e2f5448c49a05d56bd7798ddab38cf8d6dfd7d8be46de6b5c9739c2f70a47b87a015e7fd0384277f8c1bbc411bac3579989aa2bb981f7abecf056a54b6f55dde7a657d9f42a9b5e6553139ab9a618bf9bac7e376518bf9b9a9a9ac6a4d0f0a2448b8d2b2bde4dc81038bc8089127b0316efa6e4afc61ba60e31687472f16e5aee3871d616458e9588771313c5dc0e1d5d6a101111ef261b5658615248668978378dd1304643db6f0d701ae034f4e03468d0a0a12c3fbd516f9406b3cfae21eea841f95bc38bdf1a5cfcd6e05c6362466c2b0795ab786b40028049862bcb91182068c45b43520ab94679a6c6dc58bc352c73e45052e5a51c5226de1a985b9a88c0b116840734de1a2e34a966648995b129e3ade12cc359062ebf33a46548cb909641eeb3674866a8fa9d81ea778616bf3364c890211ae6055b8c2c232b56c43b03528673478e1b544892c43b03b4860c23716c72dc2811ef0c2ad20a44101441a6dec43bc308512db2ce5a18c172a42cde193e60264a9c16882033b4e29dc147bae4a3ee33534f8ba9a7c5d4d3626262622acb4fbdb05e1813d39289c56fa615bf9992bf999e474ed4889c51d13d298b371392a9dc0143a943ae2cde4c492a2b9e6042e8904122de4ccb1a43c8c67278599b8b37530aedf1c479054b0d1434f1664a40f48845049116489ec49ba937a2d81b517cfe2ef690c51eb2d843168bc562597eea5df5ae8ac538ada28adfc514bf8b287e179f3bd06c31c3a54bed4b19efe2545b883219459a5125f12efa940c1b4c80b8a04222dec5dd91a89c192eac2b63f12efebc69a3824794333514f12e761933d6e50ada5bd44bbc8b59d2a52c759f97a24bd1a5e8d2d2d2525cdc92d9675f8a6b2e4dfd5e92fabd74e2f7d2335d2325e42b8a8e124810f15e4a2205240c182a2268e2bd94b43056a48eca11ba286bf15e5a0241d9a4c9128488f249bc97986c8e2b6b64d4e0d060c47ba9698204151738ce9031e2bd44245d2252f75989d754e23595784d252525a5b2fcc42be3952929c53995b289df4a19f95b2997f8adb41c51e3870d363e7254c55b093982b6a418161d0d3722e2ad942cbab1b6848eecc9d58cb7d2726a19834c4d19922ade4a4c658a195c6054b9e226de4a3f5371584c9c69dae6e2adc4a391c4a391b493783792de9e772329eeb32791fdfc4e8a526a2525254593dc7823d225de88bacf483c24120f89c4432221459148fc46527e1ef11b09090929cab5e244931b724faf782321bfea4d324c0a3134af7823253f5f95498226ab8891b3782335bf0ca932a34637264bbc91c6a44b63ea3e63c881c390038721070e038638380c51bf3188f88d412bc46f0c183060887e2983a5cb8b36b078634022717103cb12af3264bc31c420c814158da6d80e2ef1c6e044e5c9c5e549143174f1c6b0e6a3c8549a2a6ff1c640a3485d082155985b6ce28dc17976e1ec0207bf2fa45d48bb907641eeb35f88a3bb70e1c2850b172e44bd8ebc8e3cfc3e721e398f9c47729ffd28cdd45106f1fb281f7f1fd5fd3e3a3a3a7a81922f7225ce9a707589f7919a193e7e640119239622de47c9216b6ef8101345c62dde474b1bd1252e740441ab118df711b34c8db5b0a91d5f67e27dd42c03e39a1195e34a955abc8f9c3938883938881c7e137398c41c2631874924268951442291488ce6a048977250d47d36ca491ae5248d729246464ba337bf8d8c8c8c8c8ca21e9c6e65a6d0b0a26449bc8d9022bc7a64e9814cb122de46c934e9529abacf45724572457245729fbd288d5611ddefa2b9df456e7e173d3f7b11b4a848ada82d65d3723b729961317fc4bb0839033568acbac8526049c6bb2839648b0d29244c191cf12e5a7a9935bb7c509d1d81c4bb8839024c13ad263f966f92f12e62f65881c6ca9a921a51f12eca62218b85a7df16a216a216a2162c10b11065c182050b16a262e99258dd67a227d193e8494404fd4cd4e63711119bdf444444445ec68e3458901d4b9489375154c9151b7260d48644c59b28c9854b8c166acc66803de34dd4a480c646268697b62868bc899c383e2ae0f8a8b0e17705ad0a5a15b42a544813ad20f7bbc29adf15d4fcae50a14285b02029e2d0c4a80a8115ef0ac8205abc346173a5e54a34de159235d80a8bf206e5869a57bc2b2cc73899f1c556b58249bc2b30cb30a7509cb1ea32c54dbc2b342740a7c6c59912501a68f1aee0c4a91ae2540d9b7e0f9543e5503994fbecc33470c334bf874aade170388ca24922069d2a63a2ad19ef211209879613356132c0c2c47b9874e9842e9d50c36f21ce51887314e21c85729f5d7814c6fd162a85687e0b85426154889aaa1a7358626c52c45b88dc9202c609178bb8b5780b9327cc74b1952953232ddec2a609c2d40561f2189366196fa1138c83f10cbf7deef35b7e7bf7cde33ebbab41e1514a2df7b4ec94beab7df674bbbb79a54b5e759f29b84e0aae9382eba440810285b2fce4a6b96914282c79bf299cf94dc1cc6f0a70bf29c46004734df387da1793785318001a29ada794999832de145228556eb6d07dd568e2883705635cdcf32b4a881e63f1a67081341f5f6b5b275a7cc59bc29b12335f669e45c268c49b825b952eb955759f875ce590ab1c72954343434365f9c9edb187cc3efbd071e7f75099df43647e0f8df93df414246e850832cb296ae23dd486eb468e206a90439cc47b28a900265ecb3231559a0489f79007e5982d3367991997780fa9799932e2c344d40733de43cdcf46a2a460296205778cf7d09874694cdde7097013e026c04d98306142597e72a3dca80913b426bcfd9e20e6f78430bf273c776c54ca34bd80e19115ef094804b8e83a61428c8b122be23d21996a512eb18859ab2a0322de13963c14695748d8a0d2844dbc2730b9dc504c1529836623de13a8509993922379046312ef0962e99258dde7e0ee19dc3d83bb6730180c96e5a79dda4e2d18747ef61d04f33be8f63bf8e577f059811a6639c4b06895618b77106900325d6044ab68a90b8b773029c6e6e5edad8a7923dec12509ba9a566d55d01366f10e2ec0ad0b8a1864cd3828f10eae8d01f1d17cc3a2e319efe04e86d04e8650d16fa1dd5268b714da2d85848484caf2d36e6bb72524147d7f0b79f92dd4e5b750db6fa123ca1c595e26927161e22d8464b2044995922c2b76c45b2884922e45ba9c804b33126f21362147404c793177166f21260f279922614f960889b750b3056a39acce54e1911c126fa13441698286bf83e482e482e482828282caf2d36e6a3715140417c4e577d096df416cbf839e1c588226244814971428f10e421ec0cc102e5d6fc4c0a0f10e4a8e00240ecd5493c68eaf13f10e5a4ea152c26a8c978cb7780731353ca7b860d0d8aa3b13efa01b6662c8c94033f18615efa0f68984f68984a1df12a012a012a012244890d0d62641821a3909d1df12b4fc96b0f65bc27304233a78b0117931e58b32de1290259c54a9e0f2450b48bc2524ab9a106163c1e64c46bc252c7f581179ae5d45a9c55b0202e8967ca112236dcd4abc2584797116c6865bb3c996784b70a61d5a1ce9528ba3ee33b065025b26b06502814060597e6abbda2e20f0f8d93730cb6fa0da6f2096dfc0332236dc285d24d15126dec0392597e657162533bce20dfc99a3d14288538b5558bc812100190364aec9991861f106b2a12215034c8fe40e30f10636a17429d2e42b4b49166f204b07c4d201057f03b547a0f608d41e81808080caf2534bd55201012181aefc06b2f21b28ed37d0b3032b3a1a3bb4e4c49c88379013145b536440c8c15d8937d00bbc58980852a7638923de402048aee9e1a5c30dc65bbc81cc90995a9679b1226c45bc819a64c68e37beb8b0498b37100be68705f313f4fb877dfb79fbb79fb8cffe93fca9f2fb07edf7cfd9ef9fe767ff81fefca8fdb4810089d2470b1f43a698c4fb0709050bf40817163a5ac4fb07090b29145ad6403953c6fb676974a644cdc79536376ef1fe612660ee8b9bba1f55d81089f74f33ad42457786d603c7159378ff38592f1fd6cb47c26f1fd6e9c33a7d58a78f8f8f4f597e62d3d8341f9f354a1fb3df3e547efb4cf9edf3a4fa2197a4cad8941f26e2ed83f460cb152f6c516aa492c4db27b905ec899aa4162755bc7daeb6c4b8116469022bde3e5e6bde906186884a1b126f9f17f878cb2a0356e6a64dbc7daad2a5aabacf3dacb28755f6b0ca9e9e9e9eb2fcc4f6607bf4f42cdbdf3d527ef7407ff744f9dd6336a5c89b1c4faeb667bc7b90616d8cb49569f18811ef1e1b6588b0593d81b2d012ef9e0f5ecc48c32204859733f1eeb9e2834d92a935439af1ee693a712cadd848b13113ef1e273b8287ee47d47de69963913c3c729f9d478b07ca6f9e27bf79ca7ef3f0f0f044d768fde671e379938391bc4262854d4c57bc79909fc5cc705ea16b033326de3c3f545964715f6c8841c69b8758a516c7a50d9932ae78f3f4a08bf332048baac99878f33437c0345247e388122360f1e6c9922e65a9fbfc5ba3bfdf1afdfd7ebfb2fcb4c6ad71bfdf1ae7cfc9ef5f93df3fb2dfbf2758d48c1a38a874c4fb87bc3211c7e522c7d59278ff929fa7d2c6d48d7842c42ddebf011cc76449128408579a78ff9e6296cc7066a5507ec5fb976e41f3e58994284a2fc878ff88a44b44ea3efb9abea6afe9f3f97c65653e1fd4f7fced63f2db37f6dbf75443e143080db2113ce2ed438aaded784b9323cc33debee4e7126b492320a6582889b7ef499a176b5cd8ac09b3116f1fd3054d9a44a4acb5e1d2156f1f0a1e4e92b4c09292ac126fdf8a225d5a51d47d86d7240caf491886e1b2fcb4de586fc0f09a282cf61b0efb0d2ff90dd79968e1a6840c1d5d6df1863340f6c3069a32143bc8c41bee809227559c9a123ba0c41b9ea12c31428690326546e20d33e33222736d659623b0e20d373f7b9888a65b911c6586c41b66932eb1a9fb1dbdf3f6733b719f7d678ddbcececececece4e74c7ed49baf4a4eeb30e5407aa03d5d1d1d17173d331fbec3a471db0df3a5fbf759cbf759e1ddcd4b4a93bb1068d9178eb2057d0e5c559a7038c8b10f1d6497ab8422b42e6c856978e78eb2cc7ac884bf214732123de3a4c9c202f629c8d798e51126f9de6e71756702071e3854a2ade3a38d2251c759f5fcd7c35f3d5ccf7557bdb3efb5b969f74573e525d07ce645b52a5b6e62a4a1c8606092b502e6e537171ea6a140aa0de04aee378ea34800108d929bb7dea15c84ef9cba7fe21f5f2a9c3690b3d1e8f445257ddb2535c72ab729f7eada5f17cf5deea3dd9e9f5d581be45ea57a25f8948be9b3e64f9b5b73ed3b25f53330fac34f9b5edd7f56d953b9b53a37e7cab48aa5faf9cacfd7a03c8b7caecf12bd0b7baf5ebeaaa5345965fd53009bed567d9af41ebea6a9409f357b5edd775b9d5b75fd5b895079a5f57e4d4af994ac9acfa35dff895f96b1efaceab672715e5af39ecd7672efb75f574f51c5da6f935b7fdba7aba5a58e57e3d93fad567d5c8a95f3595f257d7cbecb4ea1bbfae3d8c7cebad152dccaf3bab7e96fdbaeab45f5d47af00f955b7fdaadd7e7dfb356ef5f5a8f6f6eb1af5ebba4efd4af5ebd5af9e5afdcf7fbf9f1321652724ff79110bdaff7e7e5c7e3fcfc04fc3eff7fbfd94a89c7ebfdfefb7e4bf5f87dfeff7fbfd7ebfdf4fadc777f00eaece788d1d96969696965c95f11a979cdedec9d5abd7e8e42a292929c5487a0d5874bc0657ad5ea3866030180c0683c160d05518af3138e591ae3c1fc955e56b44d21dd22652d680592be3c5e2cadae504244a10394237824d542cbc12f642575fbc46a18bd7f8b3b2e57dbeb6f7b9cf897cefb3f2f63e9f8f8b4fe8beb4ed7d3e0741842f487575e37d57aedec7e373e273f5999d94dce76a99cf4c557b9f98162259633c94308e3473742989b0f18a7d209aa82092850a13343eb83066c6803979689df97c3e9fa73e57bae2e2959494945cad7a8d4aedd207dd0d5aa1fba0ab54af3128140a8542a1502814badae2350a7507fd3f2b5afef7b3a2f63f5759bcc6df8ad7e83b6af247ae265fe391ebeeee44ee4577d7ddeb1d0d45f17faeaa788d3f9f8f440a47f11add2845da1bb93af51a8d50943d94cf4341b96727a14339119417a152883d140fd41628af40760a3a946700ea070505e5500d10432307168b1949a4a0dc266bc860a559395902953ea170fbdfcf5d38c5ff5c957a8d3f6030c8f641778328d83ee8ea89d71804db414a9b569fbb30dee73096f739d0893e14caf799bdcf5513afd107258cbed05da114f485ae225fa3d04bbc462838b3e0844f4a324b7e92591b15349fe42a89d798e4bc1fd2f24343438e949d7c3ee4c5a1322aa2b4c80203cd8c190f399db860127921862cdeb0db0ff917951aeff3d5e7ea88d7e873a35ee390054f99bc055745bc460b5453cfb26bcfb2ec90b32c559367594f2be0010b42558a67d338645299c4b255679ecd6173169675151a645957a36c905563a1a27c6c4e3eeb59c926b1acd059f6c7b223c454ede87aa202c8593ca58d96175b2aa046d2672ad74c8185220c8796367116185bc8889182438b95a302a30c0f2e6610160b1417744a1a6a2b5896f5dfeff7fbfd7ebfdfeff7fbfd7e3f5743bcc69f10cb6fa8176a35194266449525c878c32f8ca2824d0a33625b421667706c4ae8d4a8110aafbc5068a479c3c48e66142c2ab150e82a88d728ec2d09035be203f335f97c3e1750dee7f3f99456dee7f3592ddf67a5f63e6fc08cf7b97a7c8dbe9e9a820466669c50d68101c266cd5682644aa8a13942c7e62686aa9a7b281fe13542f59c55583e5815e3832ec26b0cc249593ec96bf01a9398dea960bc3b0d5ea30f81f9219fc16b1c92418616c596a41be98bbf9bbe580440b1e82ef4ea8b0e03a1655f7497b2e28b4e9462f6452f2ebfe8501fa658f9a2a751d4bee831788d4528680fc3690fc330ecc5fc94468fc7238918762838092e027b05b253d161cf800f861d0438085781a11c8661380a948775e0340d7663d85568764a1f16c2b0bbb0c3f0541234d132618aa088772a3734c60799256a567e48c19ec26a330af385be66a7a2173a0c5ea3100a9817a455a0a0a0a0a0a0dc05af11cae7f3f97c3e9fcfe7f3f97c3e9fcf5bf01a7d3b6858709cc0214702ca5a0ab320576158c87529b2a94127a58d14311065c5e2d9178b3b44d028b3be82881913178b1ec26b2c32f9ddfbdfff3cddc12848fff35fd992fffd1c78e27f4faafcef0b4a0e2771ff73161457f01a61e10fb3e27ee82a788d431a58dfb666dfb6add0db96c6d9b73a2d95b66d836d6b43c8b73aed94d64705d5b63996dff65a29edcfdbb6d8ae7dfbd34af9ad1e73540bb7703b2777683142a64ec81a15713b25c4878e37487a7445d5681bd2648bcb494c47228d972d3366c0c53b7d6e90e34b045b1b243eb8e29dca8d8023cc0b3a316f8654a1c55b3d6ab5cd2894e41965d3479be24a16091a4eea66c45b85fb168683480f373deca9d6c3309c03eee12c200fbbc34e84bd083b08af116ea3b0d075478e1ecf7a0a8a9eee9e2f7aba836cc5a2c3c82f3af046db17dd7128f9a20d275f7414bcc62291851ea0c798b412636c881511c12a0a139a850b048a0c67baa4a0492365c49adf2f47f99f8db1ff71c045d693311d3bae90887f369cfff313bcc65fefa1a06ab03d548d120fe51fbc462820286fc6a201f73e777d34b8bccf4df01a7d411a591ff4fd1a83ae7039f7422fc16b1492e035b659b9010f2abf818fe0356ec054fb5e0fcaf77abd9ff77a3a5e7cefed3de9f5dc8362afb7b4fa5e52af0753b53d4f7b31a67c2fd82bebf9bcd7637baad6f17894eac17121e391852e7adc8a7b49cac47c5c997863126ff87b2a5c40b37a24e9e1a517c5aa8b738853889c8d5eafb7e6e60bd5962764607a1dc49082d222851b332c7a6c70233ddbe4416ca765a9990bd65d1d3b9e7578c5b30e7c31e5597765d5b34ed401e6592fc678d6a1606479d63ff848bf769c79d61bc083c8b32e82d7c8a6f59cc09041620518166b255ab850aae94a53f339d0e7e2f83e9f8e1beff310bc465f0700f8dd13dc4460bf919abef5f06d7b45e55b192bbe9501fd76c68a6f67a07d8ba5fc16cbcab7572abe7510bcc676a7c96fa814a85d499150c1a2465b08a858585561751d298226434cca8bdb94b61430d9c357c787ddd54f1ba8c275c4871b191a91188e41e661ffc06b848b4c305f740fbcc6a2fb63c6f89f77e035fe3c788dbd28d3989967720ebc46a61e2f5ebb906b2ffe20f11ad64cb40efa4edb400022e4753af65b55d509bed52b550da226e1b72af65b7dea56438fc7e308ed6a744b861af6ba1735e43b4f65e5315fbd8ed2b06bcf5d147ce7b00c2d82cc66d9edb567b82c979dd277df794e238bc4bdd6539a999d7cae5df7106a4fb56b67d3860e5bf25ba7bd761dcd4e43d7aedb2af8d66f1aeeb56b39aea9d71a4cfbaa5c977bbda1c515b76e7d695fa1d9c9826b5fcd8a7caf6a6bf4b5af6e74af7daf6fcedfec11999d8ca688be592a56f9dad9259231f68692df6cf3b5b3ceec74e4dad9b00bbed93216fadad9b42e1daf59b524bf59b8d7cecab5470cbedba816f9dadba417d7eb96caeb5badec84e4dadbad24df6d97f6f69984455bf6ba8dbef6d62db76f4abedbb8dd5189885d54d7ef9df2b5ef963b66764a7fc9f7ae87d66bdf3595b0e9f9bdeb42f27b077dedbbb4ec5474ed3b3526dfbbb69ddb6bdfc13979bcdec51df9ed225fbb9b7495d929fd0cbeddab25d34906e8b7db834bbbfbcc4e1a5cbb5bd6e4db3573d35ebb1b05a3f1da6d6bfe76e55e3bce1107999dd2dfe01b672af9da7194da71ae8c68c769662727d78ed3f5e41b270ce7f9da71a04bdae09815f98de3f6da71e0b213946bc789dbc037cedceb9c2392cae777ce5487df39cbd79ec3ccd1ca4ee973f09db3d57ced394e312eaf73c28868cf8966a70eae3da72dfbce797bede9ce817bed3972d929fd1a3b0bfece997bbdf59b977ced3ca57e7263edbc2507be79375ef398afd78e30b97a16119324d6587e3c71f1c4c613c50835484e6c51231317efd4998a318165c64710ace556bcd3a7049c309e9465c1eaaa11ef542e4b09dd191869d694d4c55b3d86e03924440d2051392bb19499724e45522b196f754d172a296098751d118bb7ea86810857dd0e125959667166e6b41cd549ad7c7d029af5850b982773f1d6cf1e713e44b8c10246ea2cde1a6a850556d890126ea09c88f77a8c3241fce8d21126cb4bbc57a40b204848346db0e1a122de6b338cd408233f54b06589f7ead614f1d6e6879a1821f15ee186b05822055d96692315ef55ee751af2e99c61f675424dbc59e6eb305ba4f8c86ac1c22bdeacd6eb1140c02812044513cb8c59bcd9e86baab52c3ed89a4c25f166dd5e60c6ca121a68d6643c8977ab7c9d62a173322584181a3121ba85be6ed35e47795302a66685ee48bc77c8b43164b6906f66bee2bd4bbef6401632ae8ec4173211f1de395f1f95c815311263c559bc774fa38d19586459456c8488f74e4e0139e0dcd810d1e68954bcdd23d00c4b6bc6992e5da0c4dbd5cac0d75b5813372ed88cc4db6d0a5db46d6933a7264b8a78bb6e43196e4e4ce9a145ea4abc5db8d746545421d364449b2cba4413354da28c399222de38ccd7eea52b2d880da6179278e3a4bdaea18c2239ee28a323de38d1d79eee9ce46bcf51befeb22c52c406599127f1ce79bed6f2724be243069c8a78e74055f022c4da1521483729f1e61d5f57f991b64cb3e2622ede3ca418dd73e02b07be81d7c881ebc1d7ecb4c17bf020b6e33db8065ea3870e1d3a7410d3f11d3c03afb18373f0bbf71c963c0777ab3c8730aae7e018788d1c600a1b6ce0eb06ee62f90d1cde60c98adfc02ff01a3700123d541ef21beaa1945e3190544dbd60c61b7e2819236a44db447cf9ea8a37f1a1be485c9d8181842bc59778171f0a4ac843b99b79a83740ea72405f64d9d126865a12f5506e81d708f5e46b76d2f04f4f49fec92bf01a9f602727073ab9eb0426e49d9c02afd1c97bbfc1d70dee62f90d5f237e834fe0356e8095bec9e9fc2697c06b6c723568d0a0c139e43578045ea386a1cfe044f1191c02af31031393af4c4c4c4a94cfe40f788d4cc062b1582c168bc562d11df01a8b4b4b4b4b4b497afc9237e0352e2929b9929292d794577206bc46259c5f90df50ff9312c5f1a20c9d9325f186ff17570309056ec696977813ff97f565849c15315b28e25dfcdf4feb7f5e64ff7b912cadbcb698412b13ffbcc4fee70b788dbfb1a4a74f4a72b80bcd2775757d922be035260191909090ba8c3c9227e03522953d0624591e8323e03562708dfe0212acbfe007788d175460c5ea4d08972336d8e20dffd111903f72573f3d8099462dcc2bec8d89f808498c3f7203bcc6232722ba569e78e4f8442fc06b24c246464646464e80d76854c485e38b7c00afb1c8b560c18205aeabb7e0c6d768c1899a5f4fe402788d4464bf7b5fc1d70a46ae7c052322be8207e03556180e87c3a1c7af71e8c29e17065f287457e8b0d081c222582ff47f8d42f7f97c3e9fcfe7f3f9fcc36bf4b97b787787cdde8928df1d00afd181624f610bc953f00e5e23057707ff80611172b0b9c84ad2a66d071c00234e1e62a8ae64f101c3f0d6d6c330ec1cbc46b8d7e477cf0f0db92b44cd0f393c84ca0f09b9fa21f7f01a878046bd1d3de2f77abd5e9034dfebf5bcc36bec394929fa4df4ed152d20df3adc3a50abcbb7ee418a7c0be4ec5be7f01a5b628e0f11486efca012c7867601e517a913cb325422a6b0b479a1e4058e303d9e7507e2e40260c49a64c160922644cc02097bd637788d6cba7b3fc127b8cbe527fc70f1131cea354e8077ef834dbf7b3ee86bd0dd361f74d8c7940f7ada83c607fde93506832fc4c3cd0bb9d36b14daf01af5502b4845d80779d36b0c722538508204091224b82b81c84b5021e2d90ccfba86d7c86aadb5f60caf513bd36b9400057422f5402fbe46a0dbf3403c1e08c889801c293b6907f2627e5293c7e3d1440ce4ae7eba3016a38d0dcad88a223190d85514555bda3144bce107f274cd03b995df3d5428fc467a9d6e0f7ff43b0d63c2248809db6b073e8fbc7627937aedc4b5d75e24a37bed1f9a4079ed4baf31732e89a8dd6e37429226488e146903b6034b541b1d65e2c2ea6890858de8d21983414fed4ab8b15560849588eeb400af72fca8d035c85b90940cdab64c388f1972c9edb49412358608312bb9dfed58966505e09616f644eac86979d67b30cbb2ac12e64e0990145d526f5582c0c2ccf0b44b637ace36112dc0e8e2b404b1f294b21e01b26ea802d5e2c3098d2e6efa44fa1c5bb201e6147ab792d9ea12c7e5a50412006ba245dc4819031df134b15bfa68134315617262291b5b56247182c3acac6a4bd79b2899b30672cde59a723552a88d1810146d685d44a07989f2454a0c8dd4d2081117cc88972e718382114c4b8385f1b1abb0eb00892252278c94110135031345c78c317328c6c4f83489319e226ac6a8626e34028999630e2c30423459630548143659dc803d9b3a7ac4ce09521fa52e92ac5d5999b5c7048bfa9daf3d1e753cea847e07e379c25dd500bc51ae3c56603deba0d11a6dacc072dcf8e203069c93301151376ac452bb3db8b0e182ae69f258c058f349133323744e44b869a0f088e80146b965583fa546122ca4a4c19955e530737c963043d7836b8919154bd494d021527775d354188c498cdf2d49a364076908ccc4550021e45816e8e2e00d61ea30ac0cb8134b37faacf7d82f375a0212ac3733b54316138bea4dc1bbdd6eecc8b62ccbb22ccbb26c0082a4a5edb06c58f30bef4d06126277a40b670a4fd8138c85d6eb9127bfd320c652a30ea8988e341649250cdcb66dcbb66ddbb66ddbb66dab7506c70d6fdd8dd560330484492f0028906b7ceca86159966559966559f5637675367d966559d6d825b9ae60da8825e9a2adc51a104ad694e18a37f0c53ccb86d5907b76832b6ebcb2bc89ee90d347b0b0b7ae67bde72cbb26e1dd6eb73b21978fd200481df351fadb857be0155ae076b7e2062cc6cd0a341c315c3ab045b44b0509ebee3c5d3bfb9daf606b56bfeb00a60d401b52cc8c6fdb2542d2be6d1d4e9da86c3cc5c9a54d163336c68e3441116fe03fcf9e6553341c4c2c38a6e0a2b66236d73dcbb253d8748eacd830f6e477675439b2b66ddb3626d3c4c17177ad83c979f9b60dfbb6cd6f5896655996655996650380958683e3ee96609d6159966559984db1e6ebcdb3decb4e3dcfbab32cbbaa10c0d613f8c91d988920f02e8cc80b1e988ab876a9bd1292b5e2c953471b1e4b5e90f520b214e2430b18b2471be683c78feeaa2e1f1173e796ec86383b27d6d5d4dd05204dc9b23842570846c5449a15778ead9df0c655656d859316565232373457d07858cd7d4561b1244a8ce0efb29bdfed763b4f83fe6e073645cdef76eebbddae98a30de3a51d805330115bdfc1a76021d2bcd004863448c0d34a1434d69ec6faa99daf03d258eb217ba52a597d6d5125cc9499e3d1040994ac315c722ad8a47d01a135d5458a18339f890bc534e98209b3231e380d63d9ebf57abd1e0c82eead3db6d7f676bd1d5c0bc7c2ad701a8ef8e96bfc1024e35cb223a859afc849a3544d6da6d1a6074437d1a47a2caa4091e8f7faebcaaeeddaa6b1696b9af6b422d00e58f55d3cae23a8394fb1404694894b5dd1630c84d224203209ea5456aac9649ab4c44cea25900376f1077dc454e6c9cfb0e9f399e8b3a64b8f7a958949491afc7e6210f491dc0c7cea124f950c07bfdc2a2797893e5ee0a23b7170eab1e7084765a093260d0181863de906a4cfd40955243a4eef53fd849374a16a720755932d544db249a89a4ca15b4d36e0480a565dcdd94de5bd87b569af7b5dd7757561f0a1e9f78af47b250aee5cd7757730dc0281acfb4a24fe4ee5762af7c1421bacf5690511da11d4ac9d1c7766aa561ad5f2001a3db61fe4a1462f5d838c20a449d975de60d5770a976300a791887abd5e0f6e4031f8bbf76b8fed655d8416e1b3229c9a330c1e86356bd743f7ddf37bddebeabaa93e721f12567dbb9ad5b50a3975f0fa2958883367d2a5538302c61a2e1e12b0105196fc2e46b178c1315a6bad596f59b66559b76533a4493f5a5fc9128a808eb3eb380f6920422c829ab59bd667e7a956f40514704ed35a6badb576801bc3fa88078d5e77964daf93962605d1ac2cdad1916dcf764040da9dd9c39f87653b97cabaa4c4c599a2779ee0e448c970ce440a68393c68ce3967f7e14cec59c1eb45790f35e0acf61bfe9db3de0b85058af1ea3c71fb0dffce520f9d9d32d7856120d09d482c16617da464650776d232c1c1be26ba58d450503a13875ebe1fd9eee14cf499fbf13ce77892a8787a98b4b13e163d3e63393a743e3f62d975330c671e9eb51fa0301f3140c025c0ef110194009606eba3a1211282be1e7ef8617569782248c8f9958f92424100b830d089458df370265a00139cd0010c0381ee7a68c684210e5cd742748882ce33e5e0a1e766a2f08c4bc13b6437c34038137f4eb890c3007c0fa7493a67c2e106dad5b0066ad7445dd440581f01810d2b403dfc3e0fa7493a7015889e72ce3913279421b2e094a6a9a7fae78585a20dae0bc340a03b71c3c50d7f1ec2286afaf6e110b0514fe7997248af181559202aaa30147a1185a2a1a2a2a2094545c1a2a29fa2b6c8a787a7e8e783778a74de5e91bb2b62d7a222384dca5ef4a69fbe70ca6147ab4213de8514753c6dc1382e4720c880b49ec3274c9cf0d80e940e2854f1d0c3026a076d03d01571c98791d2150b4c668886498a7ce886495543be161374de0479b404f9bc49e889020e6d010da57c8e56f45808c33384d5b3c0c67362736673f63565f33afc917275d076404b5cc70c3b016efd51e60cad549f889c73ce41a12009abeac346228e44da88e8f143508b82b66b9a24a4fed0c5c92a4f9a601a3875e2a743b644b2e7b61be09cd5f4c9b785ad8ff366a60e5df643c8cf4462ea47241c3e8f675dfad180a367fa9da6ece77cce0b21407f76a10164111e6ebffd229350fe0a7955d35667ee43c80f6604f343c89fdde71d804e1a060cdbf3803aabe9ba7efe74b8553096863d3f84fca903539e04ade998c47e88c8700a4ebf56c0fe072974481d4ab5d00ad8ff80f83d6ff4453f24fa2151050b4226f688c9c2f330e4e0e0b8bb1603bbae2b069d5535f5e9a45f7f064e5d8d527e0859e7d321529a24a4a649a9e3fcd1bb69ab93665f149c3a2f1d9a1014220a92506108ef08dddd51b0a0a645455fe1f37027e0759e6952ea597dd5784744e02f78af4c34e024f07627d0b08006ef151e83b7fb2931e590eed8345d739aa669aa0a75760d542dde0a42703f6bbdeabca32d78af9fae60f721b82f3400fda9a7df4b935402e87c3a4c9996f0fb803416b1c3e60aac319b612f78bb7ac212deabc780b3eba7ac44de488576c0bbf7e99a8faf87454d78bb6beee95ddd9be3e7212c066f976d75dbb66d4e853abb069f3f6b8df152a29d86b8525515849bbad3b29c6655d5a990d6d981fa49fd01773c1e4120bdea02c84e29d831ee5555856ea25777703ed2af2dcb0711f5dbc3abcf9cc2d969bb3dd9299379d5d3347502ac9fbaa9abcecb6a4eb54ed69fbfd828ad17342f2b69dc4e30e7e0750a07c58e6d06fc2ecdc4a1d1f1244b1bb12f234d286225945a7859b07bdcb941e6688177492c3c20b0fb64bfe01d9427840796239713ed1909c153924273aec0bd23cf2dd95ac1384b160d76b55a1a30dbdc4181719cbc143970f03ac56bc2ac560e91b629a45d71a35dc2f3e1727173b45fad989d1a1b6dd1ecbe7867ed16db65f782cc140d26bc35f837640bec3edb27bc83ee7c20e179e9f1c049837e487db7fb142cc40d5d22aab638bf817ad5adbb735d015ca199c3d98a3bb6492697ee9538ad1c2f714d1cb438674e142c0366cbc0eb148e17cc5bb66330abe506f7a02c579aa8581a381c37f07b746bc0bce56e06bcf3e9d799e82e0ae3686d81833efd52e3a402bf4ce070e4d4c8f1cc60f698e306bb48d60abc4bb24de09d928705b7cb9c30308e561b8ce3c45902c39f7ead814e59137502bb47164e0e996305ef92386c67b4784560f7c96a8177d09c1e304e340abbc9c1b94a609cdf2914678d4d12bae2401b5001b010567e17a3cef78be96caa51964daddc45eb496c169dda99c6c2a565b8828dd0deb4379aba30d0592dd03689bb03536a31ddb634b7349c2a3d3964d2dad2da7857de7a62afb2d55adf324c1d32de0e9717b95491f098271b5d7d67cfdf1b94478a330dda33e63365fd410304556a318169e49272bf5da58433702d12eeb7ab0cda426c169d504f212c4d285113c9d9f40cc639d3a09ebc096a9a5062f139c4844299968779dbbd0aa3503757395412958bfe769515c4683d7944bd0c57b076a3357dec21b56b7fd37816d8964dad22334c2751d3684913bae623d57bcb1e66508ba889e47cfd7ced3c622fc3156c1406a753401c3ff59e323bedb7ed552db757fd6dcb4efb4d7bd5557fd3de68764a5f1d2a59a57e72d9e50b5774c14b89760bf7da79eb1258f5755d57e0042eb8fded9faa81b79af6ac328d4dba6992500474ccba8ed9210d4488537d945bb89cf395871a309b7c557d13a5b5d63ae79c8112de5d35cbb22dcbb62cbbaeebaaaaaaaa9fd4f448e3689f561d8ba77eba02dd6502144af8547dadb5ce39e7246ecedecb5955553547f152a2bdb3fc9ca6411e6ac0adab9e1dc0c6ad1a076521d6d9380e5ad787d324364de2e006de39ca67cae1e7b3e728530ebccf9e73959d76603efb8e32e590a671eb1f726e27a0aa3b4bab9dacd39c8729f0d377554f63367bd9efde6b1556d1b4fdee3d3cc2aaea1dbcccc4cb2907bc3509bc9375d669d2ab5f02a80318aa6992f6d55756b35aab2f0178decd443dd4aaeae6ea35abebaaa67aeb359c72507d5d5d4de28ab7c326b556573d421af5f09a874336b9aa6a9d1210552802acb76fbcc690310b5c85421158d71848e215adcada325e856b0c2471fa0e20bb97ee192d7d827813a5afdd1aa573d3168b005437953e63c422a85c47626b98f1841c4643e0bdf27af0921eebac1078d403867dc6a22ff7ea3004fd3b3da5216022a01f827e2103e4573dbf6ae54ccce3d7f3253d614a5a3d48602ea05e4f1209236067502fc8e560462c267060851baca070d32a8b3a20ca7815ea6889532649b8b08857a1509a98a77bac306d23030a8d5761d044cc6359372c5a6ef12ae449897943bd543fd14025c1a54c9b5804b58e8e274a945884972d5e8769dee0fa2a74c7c0ebf15921538a28ce7825807e9ef752fd24a47a06cb4236634dc24cce4d48bd50225651ac1ddfba0a3d4f42d4e30ac23bcb9feaa715563bac421ab42082b800738c87594db5ba5405ec18f38a7a124818f5dc09f71c8173dcf0544f895a1076cfab5a6badaa7a755615b2ac5015b240fd23329889fcd4b7e7ad9d7b7c76f513513eca9eb31b9180fdf3d0cd4435af3a7280ae0417af6971eab07eea39b5cee46ef0aa6ff8f3d7ab47e991dacbc42c44d1130a65efb91aeb0885b2bfbec65a28948703d0ef389edfd54f44e2d71322f157adf55047e87a00abef729c15babe7e407cd7b31686a0df0012cabc6cbdebea074409655e86bceb2265628ed07d9efb2e71cb77eefac89acf45a23e521d47089526a9ee5c60ffed12d323d55de2b3c37548e47dfa648c057113797967e4c818f8532855a04483b8e0edafbebdea4ee421ebac737677c3da37d06587eb30859245c56fd720786a9a6637b3cf699f55a803729cea231032514de5d4344d7df50f5aa83269c1d933f42873815070ee4c83be5b848a12b332ed5737eac2b00b7461778144d8d57a46a15c66ea7c37faaebbabcc7797eebaaa50efbefb1b8eefbe5aafba3a22edf02ad325d5d3d7ea55df6a894f533458217260c9525596234e63b810e164c5159522b1baec81b65655e6c493144554340bc60d272fd21f41cc34b172e343199bc18212b704e3034abcd53431690e93e62e29984f3d4da3508015318324da166fff1e1d998be7110dd588382d3ec0459421534a365130e202e8a7a2d75a17241b0cbaa9380da19ea874275b6ca379986256290867040008000318003028180c85591625415072fc1480165aae5a5e589749e47918c330630c00061803000000001802223445350177dcf17c5bd743951ad4b1bdff03051a70ccb0a6308c2d9027f822fb8f7cba32d409d5e4767d4a7dcfe0593c62fd4e903f5514c334ca63a67095d62333a5b1dece423db8274569142c81be022c432ad914ab934fb8264c4481e0c357530bd5f7ea03e64bcdfb97f1339089ff5b4cca43d622985e288dd1d2baeec65b03bc4ccd336f488123d7c1f3245f2ac4e01856003580fa16f27f0309ba1bfa127f73f8bf3503f8b81877069a0b2a1607d93f9731eeff24fba0a8e077a69a92cf54f4ca7cec117839b525330b457909973625d21b145585994c51bbaf496e4948a4527ecb52286ff6c50d172735c4890e32dacd468bc91bc6f53b86708120c963efc48fa0d72ececd0392376e9bfa9f1fceb3fc4aea3f53711671caa89d6ef86bca12776ed48cb43f6539e62e8fbe6f8c4ae19ecc408ec50a5217a35ad941c58f4d8c3e34378f5843e51789b414da345e67619526ab3f1a35577232d37e31f9019739aed261ca68e22ae72c079f556e3d8844e90b715d99b825914de5a4012d774d7e85f05efe16d7a5a09528b047a4c12d5b4c2b0d0265687a9029ebbe2b748415f60c2ec09a07eb341dee168175fd14d715a8c5d6263e7772aaad39875a4d58de7f20bb8cff99adfa939885f5c83ea23ef372dc639dd2b6e46f3428cfb2fef79134adab3d6d2c198fd32cbc54bd3870170f85eb5b252dceecd09819f42c159c6d58669db1d15925ee20622f04b204e5939dfe832455ea8c820dfff4a8c4259bd59a239ed8b49dd7dc84acd4a98b12b635342d71e445b7f4d7c19664ce63eb4c25712feace4d8eb5be0c147229badb11a12a7151f0318978607db308d70adc409e8f2adbdb2c6e2f48689fc77b1dee80a58f1be997ad30969161fa588a9890ee84e46ae1b8928ed67da8ad55ca356b2df35671e6581069f2107aa7aa9a49ecf233b1e1291bd1d0a52b91a38bdd3c08aee2ed6ce3dcaa45fc9385b877497e689ac95b4d145217f4888d41a9c617995b1a3ace0952ea9702c6160d25be345742bf48c422e7622e2fc09db595ba88b900979db93666b6f57f98a9c73a36d459ee15409431540630c8c6f908639ac7ac872667918b09aa3fb7c58c8f0ca429c64250a516a93e05dc62101a930d477d9d725a18f03e23390fc61a8c04f78d92ff3952ff9dbea9771d0e89644edb582195a11d397e132a44103556d0b33065edcbe121733994cfc9b18a02b6429d0ac409a167d9c283bd5669ac0f2d051d7c3dfe2c31ebd3d7d616380834bdb95c0266a8ae9fe6946cd7d34f09d2a122ca594402674d3f7522705a4657747dfb8f611bd4ad48397056165ca80337aee88c6f339172c71ebc6ca575e02df707dd8d4f1c4c035a8029a69aee16b1c7ed9351c622ccea69de4c104f8f635fffb6d6dd08111b4340d846ac6a844faaf1d6e48720098079718863752afa9cde96b90e0b2bf122e5b1724b95c1fca32e665339858522bcbc51e0564441412444447b9e29b972c7f7617952188a5e61d519d3aee6d0fc37dc2ccfd063071353faa85b613890a5db57018ecdc47463ab7fff6de20436911d85f8f8f18e1c290d9857bf890193219980c653a23188851e74e516a0a652a2496b256e2a9cb6bc0b32924c6ad18c78a0a1b91993584ca07d2b7a63ec5725e3a52a7c6f48ed3a4ec3d527e8df30811b583efbae85c4e116cff51d36f8c8126407613a06bffb4ab271236ce0ad3440c93c7afba8a65834704bf2c33a9c407d5e624739332e3ead2c1890312f691805a748febd9edcb39e88eced610202484f4e6c2b80f4ff77649f7d0526a5fbc65d8dc4ccdad7c708d9f5d6094b290f97d6451c4ceabe1fa6e8945baab22ea6383fcdd88e9b81c5a40a59da89d2b5ddd3a0e48668a77be93bff31a2c6912b82c5fd24aead749d183ca348bc4bf7b833edc8f9372881eacaadcda5b56b3ebbf199ecb04185b605462f092bb065b5f42c0a7b3f80dfdafec377d66f6d720cc0224c01f4f7873403b408401b41028d749b61fd7d60f06124329f77d521d8046cc6acaa698289386699298afb82547417d6a0aa2f0cbd28900dd73da97438136078c8fa65df8515ec1ca5ef06108eaab8a92c8857f80395ffdd71a1f34db6b163dfbfcfa21d7e9f7ae8618aeefae6d5833f728a6a63a1fe381dfadaf9902f819d8d6a1fbf49e11c9faea8a6597242bf7a920997ecd97470cd19e12d3a11aca7179056e2d1b5005b339653e13774cad65a083548f2da36c02e352c53a9ecb77917946d1ce8a0278596fd576079510de65efc9f37d2e7c2375a9e42527a45d5bf49d3eb79b9b34373e9f693c5aac7f2e72cc2de4e5f4d7bc123f29634d3b505c5594407481c880acfee7cfcd4e5926ada233da797030873f18d6bb02516a34b96a73be8e9267045084a096121b4d6e67e4ab0d1ff0138c92ec33851e36e3a4baee473bfb98ed3c5c34ad474b0dad543546a7fd119a921054fd0818425dd62e216c478479949aabf09d0229f00ced55bfa4fddda5b6cf1943f33010c30cc658a726e1eb15ad1fcdaec59fb932c5b3b2d1c5c350d03e09d7442e36fc88f1a59faceba0fcc0a916f48ca4cff97a317177a71d493d3e3a4d7627a327a5ab7999b90f53aa6d731bd1c5d8c9ed66de676b9c1582f667a4dd693d15bf4a840bd54e1d0ce423ffcfef3bd0e81cc92f10fadff3f98c86af1ba7f9438dc596d9d881f853988963847539011502b4c7298ba2286913e8e40682bda2ab4cf4252f5ed8931843dd71bcfae3c260e934692f343520251d94eb7bca0ddc7133cd72f6e6417209f45d7787e030c98bc5f2852af834a634b43e02e83a21d69e2ce467f8f0becd5a1ac302b87e4dbfb8a3cdefba1629980b5f6e744aab68ae6a6b751ea2bdb91a06584528ff2a4172ec2aa4b34d5d226d8f67ebd6f4bf5aa86c0c016ef435d431130df076622dc3c267482fbb1f76cbdbd8c15ef0bffcd7b327d7e41fee7ba62f4fff1ee4ff9589a1ddb7cf56138fbf422654fc09b7aab7e95f6fad34099f3014c73c1ceef5090e78f990d1cc7e5cde4e652b36105c60356b3b8ff09e804e6599bc1855bced6839b830653448c39d4a88e36defde487a837833f973e6133e9d3f8c709b72050a4e32c91bcff7ed4fbbfbc5dd8e91502d55186a6ef6d04619160e9b2092ed81bdccf91cbe376c030284ad22cf2adbfa671c88a4eb1bcac379edf4b0cf93b6a824268b94f21e82cfe768bae2a629ab00d7fe7ebd13382be0a1908f6148cacf6a0eb85f42a0574769b91308fbd084e15ed33106ed59eaf875d4fb0633ef3f046c09e88b3c2f58479d7d6662e29a64096f92d0d49dc4770b0be83ab0f4781c78d3391fa54a5149fd6639836f302b433117158e0076ef8b3e1246051db7bdb0238d39b29032b62dbd2e45885bc389a11e151f1b4b18d13d8cebbe061e610176b20b6f91051b7bec15072991db9801f2dfb9699b2b0c608f0f7ae8bc7891d5ccc88d7e85688edc9a6b348042054e9b6f6a45ea51ef772ab071f8e420438fdca9afbf16811ac6fc4be1f3216ddd79078fbc52a362808630ab1515c1bf6b3c3f6e69b8d04a88f30981e43613bf0e7062079eef9a17ac9ff2eccc41080a20c448ff15e055127cb47c6e34e6192acdec2221aa04f930142cdbafc91bd7fe2266ad8b005cd92b9fed089de0d44df92fd9f349affccd1f2f3d3b6315c6910928451a3fd45eef68ace41044e4d5b2e58ee144511a2653eb3094acfdad2a4a63692661e918f5e770d0bddb47003c2db445e4574b12ed763164061b75592ff9dc3a4a71eaef149eb7cc81f56823bd5a18c0c207571f0875478b5fa8810a4238ea2958880b40192f4dfdcff7b5458bfcc620c79ab823dd2bcce6e027d6b67f357ef1ed9892aa5591002939696d595c891b2f01dab3115b92ec63d9c3100057c2a497557a29e2971890283406ccb41e52f71e375d53840e5d2904798bfe69a6043be473c94cbfc4021acdcbc49bf652f60c8e53893ddeca9da77082485f7387ffa464373d3682b56451697b1c1f0f6d9152d5973b834a27673ac4599254ed1b67685347e90bff1a1db1bddee69406eaa021306ae8388fc8c6fc5c0d444564ca0b45566c4b961dc690aa23a47403dd4c8e43f5241a624560d87406b27deb44d3697da14d33ba4b46d066ccf1cb53640488d238623c081b481c8ec246ab57d4c580ca17871501d82402890c3c113d885e188b3a87a500d34364fa4635b8a0ec900999e0e844c97a57bf86fad132b55b71082451366fc20711132ac24cbd7465cbbbb4727213a520fdaa75b2adf0258242e2cab1414992892d8ea8251195542ebb1d4fb038c44f9068f6512eddc1df88b6572e86d61c400a0ecabfe65f624127bb8b0b210006373d6b3225a5c80871ebfa4bc93481b04dc42c627cd724ad69a48fd6f744d494a53a9fc8dbe294849e304bf1dce212b9aa5f657f4a62145f3d4fe88ceb4a44d034ffc629c53ac3543c5dfe94d899466a9fd011d9ab68e1e1e57c21ac79cf476b5b802ab2a9410e46645158bfb1d2c75f5100d101e33475e78c7d3cd118eb1da24f77fe63f2dd69be1f2effcf73416c4253e46e299547c60a6c2e4ed579899ca8a7fbeb4836deb4c533c2675db96effb035bb01f7403c2486ae8dabe3d29d8e3f7794c62146434df6b7437ee77380197d2bd80dae3c192b5f39ff2ca6ddd9836ed03dfd20357384012dc9df5f74df9f6305ed7bad6038023210b5b9f6e712b12402596e30ded09fb872321df858e85f5fbd3f64531c1bac018a302cde70dc5a2034677b024e951e8f673215f705b672a2146f8dba0e490657f72617356389ec33a04eb22b3224b2208dab3bef06ea0ac025f15ecc6fde943a59d8ade6eae3d48a5109720abb9558f0b5b7c6400901e5459e0f41c30d996e05dbf7588b5eda277732d2e365cc18b833c866192da5e73eb0bc193548ff3b87dc4ee0f4f0b14f4010dbdbd1ad8a2fb1c4ae27aa70d2fc8868802b42bbe508dd800a5f90428188dc215d93b704f0302761328207900be35d47f4f194a0d0c42c236585d290636f922e002bd74278660ebe34f2d88a2ef836c7232981d839280033ff0ca6101269e29a0823c0a88ae2a41d9a12b9b0b092cd5f7831afb61eeecf83dc2a2c698400f7f8311a6361d64051155fc014e3dfa6606c2a3882a79c9901b77570a88545c0aa31bc9fa72ee3aff963ba8d4c505d077bd7e67e9b2830ed2fa3b45b706a678192d7e1811c4e923b4ef6992f48b2d33936c081cd3fb5a11543681dd22d45e92fa88f187b61653328ff938f3104e6f999709d9979cc2061aded002086ec38776aabab7df09022864222f09e734da21d387893d6e3c5960edc4405007a22a8e03634584d06cf8d66d219b91a595d40557f26fad2aa6ab6a2653d3c535acc3d86921481316025713b9d793602b0437ba0fd1fad7b9631a46535c182afb7f6932b2850385ee17210bf545d55bba7f0b1d0b4ed75a30f47e28efd29d428d8894eb5f3b499db20f2afe8a2a2259599dc4a79d721ac2891ba68cb4b78477e3970fcfcbe7e072c04b55c18e811162a0cbc10b94824e68b81c3c74afb99d194f559890a5273230cc54a1d86d2693951fe741f6376b7e72a1dd4ccb7055701f072ca1749a2d4474bfd316c2be8ee5c9de48d3a9f2e4b7c9d366f0c0a92b297860cc2179015a1a029946032f2a588d12236079248972106b953d9a556e7aee9d2711b445fecf26e41c225b4e0e936b890facc9666170d04d7666f3214c0b8b32280d6599539251e7dff2546126774d12623795411d820265b407c095a5e7670238aec60e2615b1117635655d8532288d32501ee5a20c4aa30c9447b92883d22803655d0ef49b275ae55c83ff495111a930115917a024f38e249c852635eb6594003e485c6bee8a9b482f71ad791e234d66289f3314c3fe20c3c66ca14049912ccb9602c0936b0d41d9b41634381aa78fa94ddc844676139bc4a33f0be0180e52df5d4ad62e345ce2a90a99c68e5823114d0b50fb19686b2bad9966ea247c03059abe176dd56c9e4280c6eea38ea0f5eda92bd50ecc5c285cff723e3376b66d6dd83468dd9055d0dc80a5323c88bbdd4f6cdf03246d140fcaba2e449b7dd4c55eacab7b8048bb38e009bb3800509b3416d1497b91782245764f94444d0926418dce0d01aad036e855cc6efbc928f12a7edd6b728f7411428d9a7de7d3a1434964005a4f7653f0c00d32704b4a109c7c44b8134e55732741970dbcf6b316ab54b209f7590d1304f6db34f7a102095135af174a2f9c2210cb41576748b881d2f41249820149cd2525f21fe99b0149e20449147bc2f83f1a6351789d4d4cf275e838ce353efa9c680922044a617420702ba443b48ae5189b78696d1e0f3edf86a851e81959a7891f63d2b2778c68cde55632b66ff8c6792e6ba96c0c01dd827ae56c40d32ecee6362aceb8226d03352a73d086c11840237b54b0a05ca88d34a32a7b091e19c7f4b6f46204cb1ccca803fb9b8bab26a9bd0b0193a8000c9215c3279204948abd832105810e65d820e3886c4a28c94610bff0a6c27dce41fcf1a7941454a19d545c42e4a8ede1049f5da1bc4f60d0e08af13bb9ca55c1ceaf10981d6195631809450c2ca322b9d1649431dde5c51f50b7113e2a1ac26009f1034ff086b0f0fcf9e3b50767578023381c70ba861fc7262f53c45f301bef2436060969cc8ff577348079cb3896501595cb19f1473eae97f0f67e8f0876640ef7a24944bc37f1b21537f3ef86964ab51ac2bc56aa30540670ca97bc7b13850e95ee431485d04c568ed3687ad938b5cbf74bf0d1361c51fab353d5e006632e94186ee1238a0f2a58f27c6563c0e276029551fee13e7e61d75a42f61dae5ed52474275940d9078049ee634e45333cb0fd9f1f3ba04ef54906f377acbf80f530b92e97804483de6f37da13a881b67440c3118235c0a478bacc1d9a476e063e43073511af04cf1101dd7fd37fd4e55045e2e828bee4a8c99674c90948c611eec87543d70548e8908468b9f2064e7ce8f01109b9b191c10ad365710fca43ede1f4faa5a22e1f55ec219bb81e8b7cfa8a234f8da3f5358debd7bcf77c3cc7c920c47ed6656f47e3a8bf1a27436e00294169fc6ed427c58bd69ca7dc7bf3a781418ca075cd7db33ad51c135f45a9106bf5b2f62e88947c410aaf9a028d49bb8c9b7415342c1799c57f788c3a463e97df0d89f29abd0918b4a092b73c3f5d88372bcf126068c0092144951b9b86469e38c79429b42501ec29b52b9f5ac55c730405ea972e14b25afd0cd6d1035795c426b5f83bed80f6db52fc11b1aa049ba3613991f9a7fa6cef227759c52cda5a38c95a0cb20cee766c3d6287d4f4fecbc5f92c89b625957a45d686cc42d2833694935cfc0b782b913cbed174f9ed9be4d9e532fc0531581fbe74e23db11aedf77642abaec68530192a0033f2b154b647d0786164ddcca4a77dd4c47c005e3613ccb0a398ba725e37f035e889d249e2e8f1f6a0f15d3af66e6a52530c7340210d7e0ecbd0e88742b47464e038c15d1e1c57ca5752afed88d3c218cd85875d5e58821c455071284eb472f801385a489edc2fa811a1844b500204f6f04a519cb6e507e4631a9cee7ad4ec56884bc42798b98a11e52c74ec3bb8b6a3348ebb6143f49613133cdfb6213bdd96102c25e8352c4eb6e06149a99c5df11d52509decbf6e05944ec5cbea5819d97b75dd462167057c3e900b376c347dee637ecc6a003e9c059b727006f8e61ae62083d48ed3adb154c170817e8dbc52ed1e66ad109b95c1cb5d3b653445191ce20b330d44ca05d259a5a79626db6720f1d40d5a71520f274095381819441c59fd359bd9949b90cf60cd7364a77d58dbb0120fd08c86788174e0702b1d6a9737d343a1ec8ffa4380051bc0c55abe90e48564f32e31f09a4d83f8b622b75b8f48b10c7c710aa023a4d5b87583b186c571c26e7abfdb1030a973d0e285e23e656bd3cbfdc08a627bce527940db9e70c7c08c58431c1b91e008bff1a451c974aec77fa2a19c29ddcf7530e8dbc121755eee11079e9b56c54281bec884ebeab6d651431d37056f9c44248626c07b26bb4b910431f3201374a9a03ca33167fbc1c0282b87b1b96954d408437daf18eab9ddd9d294801dfb815b92381d9aaf765fb998cf75447cf858efe7eaee4375a2b321bda91854e2bc35992573b186c0156f6c375787786c20f346c8cbf8998d2f57e810cd15b492ee6f2fc3f04a8e055eeea40287dbb43c220543253b95199b6b3cf061f94d24e8cfc21244a1605e0857d109efe9bd610dcd499c49200c7fbac96915ed9f5c8155dfc51e64d8f9c23e11ff16ee963f7f530ab309b7d4f6a5b9a825d86a3528ccafd21fdc72ff8aa2a90e402cddd41602505b60bdee89d7e4eaf52174c8ac0227ae8e16caca5d0b4818bc48c1e41fdedb7ca539c483d507cea0e5618bf2bd0d88211227cbe5f269c82575d9ab8b5c807c14811bbd3f7f252d1103e95583c2876271adf0735ca8c031edad056056d2e13635d9ff85a5ccdedcff8f67a00448ea95371cdd9702296431d8f0c660c1088e96a09e6e15767730ff184c1505ac6e391754792af0c10818c8a73cd419b66da285bbd265f8f55d945056ce2b32e2dfe726c9ba471a62637e12ce55317c183390c74d57deea7f94c9d14162c5d9ee6357750de9cd2864a8c3180eba461babd3751e9a7e6fec4226bd6197522a25bf4b6b9e45f8c9853abd8dd4d56e449f38ee12a45b48e15fc17da9bf77b832d8f30d8468c249f6e95984a99988c92de139271a202c3c53a2cc38a45bced1e7377489ff0844f647e096b2eaeec41c336b7ab4b50f9601fe11a43f4f6b4e7d7549c7886ab269b3493cd0fc44e1adc458117e02d7896157f69f23bda7442511a204790eb23b0a37cf06871f04f8891aacf0a3327239655a20950458d541ace8f1015ba15efa9d95172eddf3d576417d10b7de75889402193b311d720436b30bf73a243d824b5b0c2fac95d1048eb833b77f97dfca3ad4286a5a9a10bd0f6b867dccb87d2d0172da6aaf4fb8b7b4db97c5889d3fda8bdabefaba1ff765588def33a07952e89969bf8e4744c5c090feaa167be86c3f0528cc6d643d80cd4831ad0d1515e3d72bb8c42ffd05910788f32ebb206aca16c47ec73c27a6683bf65910427c20cca211975f2d9d0f6e45dbda9c74654b4cbc54d37693d44b6ef3f4b4c7a161a17ac0ba8bd33d136b483cc1a17169d337772ac41d9a435bc0bc02fa0544b4e3c1232a7fe7c7f21e56065592820aebb6b6461ec50856346533e3a0328a0721933ec52447ccf9ef85d4fc6ed719d058d9612fe87c67330fec30aac5a37d1dbb0bde4df5d44121db69030ac3ec9c89520964eaf4a746d69b225cbd6a719ca20c8aa84b905949b26a25f521e23b6f0f84aaecfe2a783971b4f858613c458629933a5fe66a2274ee742d4e715123533cadb83881cdc8ad6bc40ca72ac9e52787ebc9bc7909746001f80ad085e0c65e4daf2b76f207fea6a32c88b7d53ec8e0a99e42d1e84a630fbf5d7de5d9db198b4147bb569eef363872d0bb10aa6e82334293d83b6bde51f1c8e5d91382f28623ac5d7eb91dc484b4e9fd4956324f7f3d6bffe166188126b20b43d4f9806b312ef7f6a96555be4d8ff4495033306e3ce9082b9262acc4c131eb505ce6819704f564633a21a4d7d42a3569b6f0aa7ca0aced32e9d02e97630d987f47314611e3be2260749c8a9f8d8fb1b8155ac2993e928bf72b68cd18fac157cc4b31a2ef25b8b1afb2ba9daaa3f8a6b8b01112e2cd822827fde0ea27611b39ae7d9ddd2983a955bca7e88ebbf049bb8296c3188d9474eec33c9b1505265994e0e5bce6af02474f4cb8d2383b23d39fc87c74ea70ceabdb6d4c3d89c089856e093bf7706fc5fa5a1ce049409d1179866c155acfc12b12a1f41c6e99565a0ef8e709c664acceede5b06b214641103cc0044272620e6c5123f67fdf9e5608c26dafed1267a0a9d55023ea2f6d1c2fc35db80e4b1c8275949a2ac9226ef3c6d99bcfe9ae4df0d2cdb3c663e28a2e58fea753e1b4164556ea6f599a5e08b90b000b7f64a96defa1d78cefe28a18d6f23462d99bc413f5a4914c2bcad00329a3308d84b1c281220b608e57ea8e098d775feb60a3e221b15cf2866f40424b914715d9ddba87e205b0061411fcec3cf92d4dab2311b7638d0af2c49840c64a1da0bc332e7368f6cb0fcdec225cf7c7cf9b6c9c84580ac0a37eafd90c7163859eb6432102c527149799ac441681d27053f4c3a6a37bb16376720a5bdf862a91a79db2160d24c089aa751a76d30870a086a22c44a3a0c639184250aac11d0ef1c9bf6d34fc340419f7521f2a00a0416d88166ce1a86d40ac08d0b117e17b037e8f7de39bb47f6d0a527be6c67a4ec55ac7218725b0a3e874fc29d3c9fec0405ba2284469ab325da9cb1c9d8325e9399c0fcd2affd336638e081b580f7f8aba94e5a038391199d9ec9380df3c73b7f85f3e87a270ac5b39b60bd77c8597f5bd4c393e4826c9e0f5fe2fc07bb0c340147729e16ce4b9862de4454d1f6e811ae3010c41f97b866e4f5eb5f56af9e831802da89ecfb14d7e7437e1305ebfa9095f18a593fd9dc0c246b4a176cdfe452b9000734d7766f10ae766c41c3350a260248e8137a42bd85604c18f86c155fbfc0b5e1340b659663e30c040e978ba7c0101174449610f7cf527078005d0d5831ac22df4cc0ebc65357f15d132701476fb8771145d303fed3acc1a9e1f5f69c4add531fc37d5eea9aa7bc1730bb42b3570942abee35e995f603a81f80d3b92d541fca58d81d1d705b9022b2d0b16ce3f9b70f813a9724ce163ce6b2ae3cf217a2bfa78e755ab66feaa90bb0f2da802acf5d97ab78f3bb0d4ef5e2b72328cb4e948c82b483049a501edff4580ae5ec3a620b7c2a1b4ae8ec7086284928397bbd10c506d8535063fd619b0ec3407bd8b97c9ae0e7d41121457ba8bdfe240d050d687182b3d909c59264df630aa6a53d277c2087935cb97db49d23753c3807ae277f75be59d8f743a7f53a7ce56b0886ac656b082747ff038060411cc6cb57922124fde4e348b692db5ec136346b720c048bb309e4694e886336575382f3a02aaa2cfc3ba889f7e61920f98c0a205882a5659a081a1f743ca7a52a72e1a54b951b0e0f585190912506661f7850c7d60a317be921978e2465f63b8ab06d768ad0aa641960639aa873b112b7d439543b97b41acfb7d13f59f6f90d1645f0b3a1a68b2cce23e374403bfe1f33d1db705561d9a478c1800a41f9aa8ba3386670c3c01aa05560573a6d0c81d1c666a88c0f265c6830daacc930685548c48012db7b92816cfc7439a6a9822280998465778195738c29ad55b6c4fe05a8c9870e206d1739790dbc06b1dd4f1032a9224e295ced223710638a72572f78fa4f7e80a2f436a11b5b7d3b54fd0784fd77098e418e217f244a247634e0c1dda61df72be28c607c2a82b2f0fd2d4c414562f1d3475f089f993aefb0accc919bc6426a77b0ed7c3a01da5aafdb8bc3b0489848eef561572af6cddb232204ceae747c8a7853af688f1b8d0f6fef12623cd82697b442e242982e10cc22add3e55963677dd602589849203b817b9ccffe5440aef1b270552c7cfd2722a7896687cf21325dcd5f43b0e54f1f801d3ae24830224227ae94e2fe1885fa79781bf5799cdeecaf05a53db5022fbb5a6649f24049b0f6fe868bd3a75e7aef1bc721b76e8d5e39dc376481574e2e858b901c729269f829ad16834e02dd084eeee493490216b079373d3d426814a84d57382633231b51e29c7100faca480585ff329b7462a2eb96fce3212e19a478edd276094dac166cfc3ef98cf43dc753234e351b1ee243cae74163085c1271c88f3767d192c6e76604b3578541fd13331aed8c838cc51556df3e61e657754f37f508f1ee95b3d9bdbe205032d82a2bd075278f97ec53cbacdf4abab8049ed3c127324144cc2b1c1eb3cbea1513d7094bcfa4f9ece013d1bc4d4146c326d345c42818f5591fc328e8ded33b88be68f5f225165617f454f91ec0a492bba4610f61cbbd3748a21463484e75a352d9270daf706b43ad225ed68b4d4f7aa5cdad083490e095451a224985cd5b9c063350ef89c3ee0d45ef7301e091033e65452842c101b9cfa8c29d9bb33d63b58f6c408d46cc9ee62bbf635bba2c2caa27be976b38ce9afa1e4d8a627db7cfb3847c16d786f212a8420a2144745eeac357d244abb65d32169da1c78205cd24be470f768f84d1b3a73349ccb5352b903757eadd6784a3a2d2513274882fd744a258d24213040aeb280b63bf13f0c07febba78423e3bfc805d70d6b583a9b23a64670422becbf9d3530ad0501e65d06e94ccac80394e64d9cf8ae88fb06fd236a93d7dfe868f20238b8b1cd89ad62240bf8cd69c322b8777414eeb1bd78406c3b8680933ab19dc1f89d23b376e39f85a92d3880b07457b14e595ec02ce7d909e6565b44bca67b1e925c618347402227ddf76812db54fcacc8a22996d44d92eeae9c61bf8a2593e59eaf21d7ac1c00ee10a290d7cf1648ccff59a51c58c9bde5456ddfb40a9f60342006e3905ec833160fc6ecdf89a83e3a7231ee7c1acba0d2d12e97ecaf437f31786431698d54325cf8b2372f81a362e1dc2c2c9a84168104ceb3db07159e893283e5ebb9a9069b6538a1504d935406d7e2479d7be764943fa2409ec205de93e95057704b4372cdb9c2d6ca0dbe64156a7931990b8c6ef30ef55b44d0c3f3ed9efa4ed91ce3b4ba6756a9790908e35f6edd1de4e63adbc717f8bc4ded451dbb979983f80a4e59a2ff1498efcf1fc17d78d481f1b334816cc5ab521fa86d3a06241c6758f9d13f9a2f34c00bba8a399a60bca38f04ebb762e4c61398bf68c38a63e804690c9fa99e29de1a3c9745b1bccdf4b2e0e783c5ccd7f890905ebc639fedc119a13e2afc3d3d51aefd0d0aab93ad2397f7d442172be0306c90e2e313298abf9f9b1a4fa6aa748bd2f9e3c95c2446f3a6ab32b9f593b0d19e7b8b743aecd1b8caa6c5f971ebccdd18832f4d0f81ec6e3b694cc7afe4267c3d6af2d0fbbecabb8f3503cb04b1359eb74792d8d2569cfca63d471d65806e32297fd27e31a63c02ade72b9dbc6388a0ca7625048168398b186e4fb1c779da27d8c1973a531284572df56b9f8c2ece8f9f4e23a6401d5b664a4c61fdc64cdca96e2815dc87ec5a8808005a7560c6560477d6aa61391707da8aa6c6781b3e9afe8ccb9dfc18090eb7a8c41cadbbc4ff7117e8b6e2a7174f0fcf486c223d32c2361181fe1b642b0b2b7a10cad1233ae1019b0375f49677689125a5735c574446e75bfae7047e56b275ed15db9be11a4f8f2952d4f514d12fdd918b719a697f6156496340d7c97078e8f388f9cfd17c36954f2ca529eff5ffbb4d90ee0d9b794f54702c9fad097c9a6bd6f0dba435a4181c177f733ff3debb7614a81ae1c8279daa58c1e3b1d42eed4b2705fa9858e30253bcab0b8d84242ca22e67ae51e445260aacf5738f89a5a35da961d16d7f652961465a793097234531fabbac357485bfb1037fc61fa5ec78209012096eff061b4880223def9b896d160af185f891b683184b78ce77432c84fd778cb711091ef81528f1495a30815e969f07b78c50892afdf2de5321a388ccb9d9f21b271b3c57e64e746be5695fdf41c8a6631732d4096324a120dc87951f430ffe5eda6ce48a151e2b93d0f83bb5d447294ce12439d191413b7d93434a90a102ff070e01119f41664bd6ad748f3d6736c7ea05b9100d5e4babfac36d1b4f847c62f3da47fa9a71581a890233924bc7432862e7e67265be6c18ae3589fe406756702159319f05c30f85e8f3b8ee75761f96c440142bda0c4a2938aab294469fb9ad8e4cef76bccf02fdea3c51f22faf128caf300290e504754445733be80aec875f5d5cc4bfc2043fa2964400cf294c1b148320dfc1e8f7a741274feaaca78ccd481c6a00022ef4430a11a42cf97af62ea05171ff8adffba679a91c7565ef01e92542a0db0d9d496a61743718e33c8d65345ca0d371c4b70bc302945a78805a08fd75e93f59bede1c95f5be0b1b1349ecbe23b14d3f6288d140b16418e71bd39729ebc82fb9ebdb83b494b5c8bfbfb7088a9425c5a070a3378a67865f7a2ef2eb07eebd257c234cb9ec2c5ece3b970f0cf4c806bb0b7da27dd4b9f9e686a86ab5572446f9fd69047657840bfc5eec0af03c58927df568f863fbef7a6eeee3cb788bf3906cfe4486c4d038c6c1e15747a3c0bcbbab7c2a292bdbfbc4b950db8fb867d71fd611763741586beb7b3c1968d20d5b68eab919bdb73ea5cfcc80e03942033ac093179e370c6d58810a4d92d2b9b0afef0e3650814e4dd093dbcc9e0f01d08fa4aaf65ba0791bfc63614bc6a0e2a60c43c84aae1453e30e7873db027404248a3da76b967cc27c4e9416a1b9f31395006a4e41bfd747f0d8eab36538383daa2125e3fdf33cc3bed766e7c67bdfea30e18fa44d8167c7ce395bc964d1bfd3aa114b0780d83a918c4d3ea2ef33abe4bae88be492c92994cce77c98963d4a9cfe7c9848bd62d88d48f5c59ecfb87886c9bbf114d849b316da6bff12d95ab872a76ef4a4fd2049663ec073fc95b09f71efa2d2cad5121edd631add3779813ab72978b14add0f80de03735beed8c50b05778d203319dd1fe730612f553d57290984a16ac1db12cc82e5c90d10bf00dad3f6013b66afa1c5078106bf4bd6430638542f30cb62199493368804e671d3ec95adc9d80aca10424933171c3054565b61e1674455ed1bfcf35ec1422e430502333a75cec4b73c662fb55d01da2e52e0d88600951cd310bc420a4fd844982a040c344b55b656ec7a8c5025928c7f4ddee5f0504f1af3457f4b833af8f22ae93e79af513e0421f1ba467feeeebed82d76ff3f9ba600ba7bf9d86078f6dc11690846f8ae840e7f03b369600ccc6a7f1430e70c6d7007b0d0796c802718f1556a2d605c71b89e2569207d8573a54b0cbfaaec60ef4cb721e0236422e1bbb6497d5dac28eba29acc9f07fa9969b9484316bc027a0136660cd6960a42ea49a533482ca7daa0e7fcb4a8b4cae21c169a33c7787482c4f24c343041e840dd63df9af1019de8233c1d2806a6e8a4198b42d26073e3b95cf8e66031784ab93e8168c24f4acd0be2adb37b152af9744ac9bc8bf32072ddf1ab63a08fad82e6e414901b6527048070ec7dcb80a83d0f230144ccce32a24233a9dad9068394c99f74f1b5896c32808898f3f57b25042c86ecdd214347bd808a2bf9dfc6ff11ff53f13b43a08ff1afa781f1c2f62dc6a0efd9bd01ebe92e910c6dcb6865e6871ef8bf23e34c0c0c8f39667dc54e0b4cac3c82311dd2cf7227c18e9f9bff5998599351dffde9d9188b83fd1a25fc32dba7658465a1532ad40551fc843c7085f08595844c6e0512107ff2cd702c29c7954097b45b7b327151460670a0fe1a838541f716ef762cb27f38156995bb030d6d97676312f1992a69e01c6785d268a2062f8c424013177d494c5ab8ee1c8679a1ce31e519b27b7d1f6956543f9d6abb66497193abb989b56aa775e53466daa1f71835e524aa3183e67599a26b18cf6fbf21a34f0a3c7087e787454d9f2ae3e3a2b29b4521dbc43a3c4982f74fb36d8bdb104e5189de740048f893451365e3d68f8958523e17b4ca105e568a017fa9389aa2bd915882b2ba8094082613c4a7df77108cc0864c74f0d141fdd24d2fafaac6247077ffda4b14c66bb31e0f146f7ba4ca7725f3403db7b5bed88e3bc02140bae5391b4cad8eac5bd2088a938b498eaa98aebac09cc8d722cc6b83015d57511b83ea0609da006ac86e7f10a51960172a4bd9413726c48063fa93ac9969b48430c313308e4454c3d8930dfe320617f44ad6a6ed62f1054d12953410a50c832e0fff3739b5bddcc4a4c366a52decd84b9e84495277a85e86fd71bd1d62d2c7b262f3f0ef031cbc853a2e4711d7ed0691f0cae477f8681b5ad04b739453cb2f8422a3b8b289d0118a91ea1e859368c3e9f0e42c8bc3bcdee2719eeaf29675d10ef5b083d052d7315052cf7415f8e0a0c1a25f25ae02aeaa801ba102785262190c79e3588e4126ee5024ce82d0f71212a653ee64371d5085490cf810e98595c984ccafef465b90bda1e263e201acb1372c9748e941cd5367aaac1c85246a4280f9897892529d82c48b695a9da753137d703033505132239a7da43bc5c80c99fbb1bbe61424f18040224386304a0fa1f9bff1ef3476abc9f7bb52e67301080ad1f7864ae58969aa0c61f5f83265c0fb77f53777c76fc54956d7b78c8838dcb12e1808438448b3c1dea9e5f3246c13fbc5d56efc612c1435c447db7cbac0b4aa63cd488a355db0d421970b79392472972df2ec0a654c7cb60cc499dd926ac701f5096eda78a4b6bb2a33a19a0b81ea7859a79ca71b390e2f72bd68e824470145a2440d180c9c6250f79125ddacc79b9c18ad199449c9bae23baf0938f69528d54a9764c54db6ae31b8c15f4596a6771c876191e47af9b3e99909a5d2370a53da280ac4a3e29014fed6f1aa4c3a384aef995fba773d517dfab329f4ea8e8a211cae2486ef430de79f33281b855083a014dbce81caa49e7fe6b133f90273b653ec59596dbb0184f2798287ef67b3ae4a7c93c0d49071df0e9ab9a6e53958414a4a7492cb294d53834e40d4088e9f64dd77da05fe93a68538270d5fbf4e852e402f69d261d82cce21604e14a03790044b3d1365637ce6164d8fc9959291434da0be8269bd718363ed6d9b6731760888aec9a055dda0323898765f26e58722945c34907f285777808032e2f25274b9c66f927afe9e86ce310b98f2ce2b6731cbda3938c815d38c72929939425950ced27f16e58a496922d78b128220415402eb30d33f764490df3d086cc04c2e357387062bca6b4945471ab0718d69ad76645abb3f0926105e7b26b601389ecd2b6a7550318dccf6b981aece8feabb165c86db1861331ef118c31821c3b5ba6d570aa8f8166f6e6d3b2415967c2d8bf310ece56c422843300a8a40d4f09612ba63d41a133951f3b9fc7bd72aacb3055bc374e2245959a57fedad0f0a19b487cae13974464f354a824922e51bb2619ac71ae55e009ff4ec739d173f4d8c1bea35a43c03f5f4cbd2bbbbd6be658e9d7f967d83f32c4729524f38d69e06524a4a7fa16f62dba99c5795f172b86e44af762920f5a129b79b279f71ae8b025f6a6258d774c0e7f0b2b72205f55dc7503d96559fbb1c122344a00e1e18fc7c2709854d064347c2d2cd543666ed378de78b0be89fce9b585ead6cb5ca1039504ee88d8a2fa510790b6b65b6d2d31cac0307f918cf9b7351390674004a0968ca9d507574ac02094a31b377a64b3411b0cc188e1f59a420639a8d88fc01342a81239d748851eebc3b10b1a2f9ce7aaacbe2c99df2919696b90bf8879a277180143c9d5ef58d2256d6f67c323d9cd4d512c43b5ca0052e7d1e9b681b85f87c143849ac1a2c4654b4788412c1639c0ed287a1ef3057c7b35845a606926e6412cdec5038d4de2a2147a9da2e91f045a0ee482e518b1a4625d28437ad84f8d14aeeed1eb51d6ff086a1efab35843f4843ce8e6cdcb9e5de33ec1648e7d29bc4687ead6a2a820cbdd6322dac17eebdae4f93828179676e8ea466594e1eca689fbaad4d756690b2446afee138f7f7d29f83c5053aebcaf12f95e57264c1c1e2a8ed32090d99a5c63293725fbe9a3f2d059b7f0ca9a625ea22768ee051397c68def06110cc014c4fd64e2bdd52a108fdfffb138150bf7f554bcea616fab79fb01df2714f5ac076139d9a0ff080b000149bb058f6b5c02b214ad380989ec1fc6d2d7b1c01cdd0efc65a24a2255a445113d4bc1387cb578d355b0c6650bb60ed84c3b49debf91380f4a92dd63fd99a000d300248953a355d2892cb497668220bede1affe787b8d3d4ecf9e9b09e421d7d0e5740119ad50f8750680cb85b4ad67dc82116ac5f7a9ed3d1a6e8e9795394bac582bca50939eaff43fb1e4352081b327984157712be71dd4ee51a5a6ed443471ec058ee94236606b6ff28e83f172d1cc29ed74eac52fd8deec7a7ea5cde9a2a84c380240508995c8ccaf95ae142d753d2848b8886da3bf18fbd7da7fc935b8d087b4c9edafd3de4bf48096c4e02863a50615a5db2525fdba1258d97aa43ca26a2cae12a14c1a69451e57867b4d2d47c3bca4c51973958e887ef19a3772c7ea735064d4aa0cf9346da21f1247bb0895c0115de0b911b5f80f553d75057a4cd25bda9424c2b7c71dfdb103d9c6b9e7cca33dd31a6266f008037a6c418517d22e88f48f6fd1c674205f79eeab54737cdcc32f9221e3244aa29fbf50c250de81e668ca4228e09a2f38ff959f143c69197f852ea7ee8f0ce6ba08d79475e4564ee3dcb77226b1777d0aae77d2ac6208baba59ff05a3333e49d95ff54c26ed6d9a96aca0445a1656a7f2c6c03a9bab65df0b97f1d28d26f1559d1847ce4e672c580271da4d695b7bb7771f4fc7140590fd9feeafc6e13485bc64521d76bcb9247af28da6688742161b71bc0373ecb5092959cab8f743e01216f3605b1378f180cb0dc2f6515b310064734382f2141aa24124cdeee28c5ae0c6fc98713a5ba194da466a326a375886dc06c785972cd7c15fb06d4f72a66d258a37e27bde5e2436905ef5ea5e848b83c05ebb4d107c8c4a3bd70b5e2fa21e9c2d83db1708340e6497e819a1bbb7e241170e08483cb8225064e33816f0302e9f728009b0ccbdf26bb741e741809872234bf82913d6c9b09e6220f88dd9d93eee82e6f5f7bd1736a17ec33784f4e2e08daabe56e4ec0c7dd277088f3d56abf4aefeec04526629b47bd5e6481b63fd46438deb01933ca0e62fc2f651254b62c0c9a4ad91d30500c84c4afd630ae47ce46c604e1f6b5294194d1ff7b96d0307e636d64577c80169868459ecf816099f26953d5d804235ae3c9f43e8bf066525a8d812632fc4c0f10e1b70f2cd63b542dd0e597a9056621f6c20b1c0d49fdd2d58957f427a8044c0c2f5397c1dfd5e60f5a8ed6453755a9397cc5d5fafbe4345309e76c7a1cca63b5b410904b0ff1bae83796367232e45bbe343b5e0c39675c62ddbcc4314a6401c23dd7eaa812ab37c28530cb54161ac35d961a5c0079f848ecebd977cafe7377f8e9f087f772260da84aed11f5f0a3bcfcfda243f11fe3a38023e81e34deb5eab53c64fb9f945fbe0ac3749083a0439c2ee24e24c6572651c8340af25060e20f0c6734f7e326c79ce8d474d7cd1529a561e60e39366854d06404facf1f6b775ca648fd622d88e11cefcbf6f08de744765a3cb7c15ef55f81021eca46175c18201c38dbb961011627051e2bb862cc7625b03b227e33e414889dcc1787c1259ed1918e3e6c12b256b21a362e6da1cc03ac3918296205dafdb1ff2d4849902e6d4b42309d0a3c0fffdedaeda3d6262621798b704a9e56f6b87371e3b7cdfb5fffb1a4fb64154ae76ae77bf665a975117f3160328564959b61e2da34968661d5bc146310e6659dceca2dd0334822dbcf3ec67b7cdefcb3692518683051b6dbb0ab0e7578b98677110ef114730cc1ceb8584adb2a0571d614a019863676eed845e498ca63b489458c0727459b2979824b440bfe8e07101e4ba51d1450a50405268dafb785b4b25728670126a61d550b5ce5279bde96d3cbe1e4fa0e8945f7da6e2abc22f7f9e8ec719f7b628121b60c0248516e0bde1498138b8c429f0110df643838d2c70afc375f21c8d9b845c037623a45562029197f4959d7be1c7bbe18ce814be36aa9fb9dc73db9a3b7e22ba4801ea5881c5380fd81eec921b650cc82cb8e44e5b8fc502f7ee52190267c680f00bd3939566d1a8f5d00e4bb5c1dc197e04ac719820ebd9c3ed92d0432a47c3721c8297a032dbac0a4754c673ff5b01851c99bf2c9c109f02da05be9c3713bba005f0f3351d4ef39cbc7657957990dc8b65832754a2ee0e180b86587edec39de02bbe1a4e54742191c2e097aff9b3694a42a7095af6b7210e36a00d1510f9525e94fdd2020a04fd5c8d07e7d98865f6e99524a395ae872145ade10f30903dae140d0840b6c761dd378ed3b5ddaa47429e8b6a602716e8189060246667c992dd04571b90e17cfdbb7bce9420d1ebb67129f91cf0bd7c23520a4e2987dad66185ee2f9eec6e36d0c9387c5fd312e1aa255eebe27aebb13715a58d75c5b3a0514619000dc4a84a08e6d5a6a80c2606bf2cee6fec5bd3762e38bf1275747d002d83a2dd09a1758d4363ce9f077d450a2040f504066e9ec47f40395c2ae6cfa1f42ec70cd5339b40e28241d9bf9668263b7bdcf795237a30199def28180c952a0247e6c33df6d84c7042cc3af33cb95845d6a48d761e92cefaaa14ddf70f0450da535943b54c9ba5e149ca8f4aab6a9933056afed8356a6c0057d21f258ec1f774c015746e6611e5715b676610e731e3d7e353d386e9edbd5cd76e014bd23528c0dbef0247e751d2f2d8c64e254fa0026f6b4b25030279bb67d19888e5a058855d50d1c93ad67eb08d62abfb1b7179fff214453a9d6425b4da704c4dd08ed428d85ce553615586e81599ba2073bdb02d00e958e55b066a785f1215f2326d84f739eb834bbebce831f69487772b749b500ca4f4b1ef955e58ccad4a084cc9234211811a1045f0b732cc8820238079f1c263e1b475466bc4c383c76bdc6dae3ab111e492a11ed24577382a712c67c3bef4ef99f765382b84da8bbb797ba4a506540e4f2a98e9e74a48a07bb89835a8fa5b9b2e93202d6509a96ed650533d57cb5daa8547385dde388659d3514db4af330ac9b2d88c24d69519e2e13397332ae4262fe2e83dd4dd6e4d3d0b178f0a19533a8012887d011239eba1b35db66424138cc7d120924f9a09e1cfa1886c9555dd0917be4ab892e13b474f3c759eb4b73543885466934591718597800b6b4a61d4cbe8a1b24558f135c18e32c2748f80968b3d4a64c36dcd35dff6dac4e7f4c5aaeaa8308043602c49e925091b0e6561618bb4209e5a049b939ce6acb2d0d1dff767f25e18ec6aca11cea37431e24459a3dbb1c85af414ee5998d77f57468025f45e66c11d4c6bee192c8a8b4955142b56740a084a271a22de41ac424084b159ddb50827d0107bce0736521153d818ace2e7c622c22718049fc0271cd8ccf0c080490b96aa855782ecc0ac07bb33960efcf6677c1dcfefaa3cde667a158145cec7d9464a494808062aa4dcb1bb59de23ad72a4f9c664e53291e9c2aa2516952734c39062d38ecd9783b4d26b3eb3846f2ab3ae29c02e953b52e94d3f5382be3ab232f675bc3be532a1bba5c6303af356d4b1d0c95015d04076738d55c231824643dd2e164ef0488c7b88d68ae8baeb558c1a95d9cb0d6126393f6a0f8730c05278d7f8f2a9d83452cbdd68acd6d20d00fc6e9952573e3ee9da0c2c07a4e8a87dbe460c30c9bb89d22f97d2b9cbd9b38861923861b9fe661825cbf14b5c8d8277ee98602e64191dca3b4a27ba593ad19ba513fd672ed3fccaa48c32cbbfccca5c066594f132cab4cc32b9f72df3d4a0751934601168dbc13c5fd1a14f4265c99f88f2311144c2fd7b3e169a886c620f47169063a103f24f23b31d4d86b3280ecc0df9401d8fd687425980b9862718c1dded008c9930d44c35e4ab4cc818e8bbfde839a6aade99d5702ecad589b5fa922d98c4b177db92aafab6af7f0589f2061fab751a9124da83d5ba11fdaea73bfdec9a878cc85920b67eb2a07c4c4be5bc57b87020d10d17e7df5c1add28301059c96039cddc8ac4a71e5bf286625b3cbcaaa44986912dccc27bcbce313202b307a8fb593d69fb75b1ec1922601599dacc83c0f5f82343fb6b732508d80fff819cb69e656bc565226dff164d7cbf156c7bf06404674dd20884133f21bc46be205c0eab98140daf835a184bc8a828ad794653fd46eaf52a4c1ce7d11fb26af4e71f8ebbfffebd3e4334529174ffc79e702874b3da41f2485adcec2f3f1d896722352a8bc037af540b73c4c82a11fb8a6df69ae2d8ae8cfdb607e4622257814203594267a2e4c9d92cab8c929c110aa8cef720fc752c32fff3c55258677959091c8c7d4c87298d423916ae1b5f97be0e786fb539e6a5e8645d39cec28bbf2ef8d9f813bdb95f578a2e11ef39dc9be87f57b5e8e850945f18e7d71d60d68d877837675e6891bcf4351aa79cb08b748eeadf73a31b8a246ee89e54254a90d6049f7ccca4c8c91a9df5d94944966efb9a5277abfb1567e28109ad5325d1836b6211c9bcd3ec1b8514ed1be34557730a12237bdb7b400e0069f47cccc6f15b1ad6342a7add388cc62cde53e11a39e9a7b25b54ae1b2896305370430328d4f8bf8017df13162065d507862a573f0dae063321c663ea7d54cf3b046fe2f08a0a41333f76e61d8d813e6dbf3101de91aa6cbf118253e7cb7ec515256c6a28a5f2e866af5a18d4c2144b6d851504e2b2d9f4d400f322c528799d8b4767bd0e3504107b892b608e458a477d6f738dfa5eb9893e2d3042738c6a73f284e3cfe4f8d4bd5f62f6b4fb5db66953d9148f857ddbb43ba6f403051e0d00d4a1ea140ce67b2eb4b330dcaad8c11a99fe4876d223b6c82139f0e2a29eee2c3a09ed3a17a5bfe9af52eef3ad617ddbd2d7e73ce0e013d74de47d1e42faf5ef23f221f4eb31f68cd0d848b59d47ca9f638fd6eff2fa12aa8fe2a2090c86f782dd0e7270281472db569d54138f00e24f091673e27d4b8957559c92eb11ab873a0766f5c9f323386de3334d954cc9089f685aa1afaf28fc3b6167917068d2d6928d4eae34285ed0b9474cd7b00124e77df1a14c403fc7ccb21b9a112084c0db73d41c9b018679d6968477a7af3a73ba1ddb51a87cc0a30f52fc152a9a08564c61d463e034847f0a0a0c51d3ea20185f28d0eeda6638d71d936dabdd20a42cfb88034cab0b2c146639ab9cfcc47c019904cf19fd120e9da2e941632922b046768a613abbb1e023974d48b27d17db8c58f0bdc40bbea13dcd017a6141c767e08b7a1a8ab045403d10c94167a96edca6892a9cf4b806e95b2a41af42d28fb2675da7b47f57b20829699f2168bea93172f63944659fb3373c74c091c7d1902409f835ccebbf4e320d3059bd5cb351d9dad000b3ac6258259fdc8ab7665d5dc4fe83d398dcf5cf938106871efb5368b7cca143ddd18d88be5d4cfca439ee7f0f9ecdc185e6a381f95fc7baa5d1464d99b3ca90f455049a8f201119f54df879806c1e43855d22275b6e54f448d485dc9414586c184f7124e3553cfcc1c29df1c51cd461676d98670ef7c79a0292aefe0467d4e20ac2a8b23bc5c27c4da0bef846338f6cde58828cbeb9de547bfb12fda37d29d7b9ed32f09f30d79d70c08b289f189e2ec9a5652098ec95c114822e281b0624f39e6989504c4d22bf885c8a311ba4a271f78b23e41e7430983e03026dddb8450d4295fe6ee74a19e2e69f0938ed6502d7c94e2678bf0c7856c1ca1912d229eb432459dac8edcf0ae23e619cc36e9819cee18aee33a56e0b2070009ecb6968367a7722e55ba87e67852db36fbf3c7f05962a2ea29cce2847a5a41b434b060825a28141c9072eadd5d7ff8c03c5b234cc14192169d24aca042e9481d290103a9cd08617b9f2ae0efa9f974f5c19a36898b6328d70630d62f4eb382e6e384bb98da60a2ad23a9aa33e07543b4856d2d745d2696de951c714517e15569d48d14bbec673d579fe8b3f8bcef923982c3842a2298214044c016af3dc374f50d030d301d4ebbfa2188286a5daa6d0bcac3b085bfc4376adba2cebf55a8164dd35394ca100a2bbdbf407a7a0fa9754c54cb58a0198e77d71350344f476035a08ba547b365412290ed952a6a9880470036003680333c6ff1ed243bd97f23fd36ce3dc964cf2213c73fd9ca8451dcfae5915c67ca049931d9fa351b873d676c094633a21b9169ff1490a5b99b6cad853448a1dc78d733e021ad9991495893b2b0a81974f2a585e6d152acb1f0337511bfcd89effffffffffffc7ccf6ffff4d6a1c94e273219f710c8e73ce4de68f9223d1ae8aab34569573f6629e40ded855ca4c8952d77e8afc3c6ab643f1d3ab70ce79b7b9397c74d75ae41b330759a0261140e5009d06b1477aef233eee980c34ed7b8624a39ab99b870ac0a16e137b41e47a8eb6f3587c670946ef506ba2dc5d7c5f2cae5d2b12be8e17adc6ff3f9216c8e1db068d485c8dff8dffffe74c2544401ba993e6b1ce27d258269d7d18e47acd06cbb28c82616c6c86b59203d3d405ad0803baa9a5cabe41299ff16b452b5fbc47385a819115038320fddd370672f856f0e824f144a365a3c681122c3b408ede31c8f80488d5214dd3341df4a16ea1a24f5ee40721475e18202cd8562ec386e7a49b661266864de6549f61325c9f1ca1e4b46793d71a9ee49cf30e96e3ce9eb2c4896c79e7d472bcb6288b1c019836b1d399a7c444033c29375dc74cf8d25a1ef2081a76a291c209f9c516fe928147e2cc08db9648eae3f20d9b90224b455a2a53596136992d076c19e88f85aed6d69e1865a449c4890a160cba04038ee9a866a041c725ce2e28a9ab75ef1a1552e41c256dad591d3f4de918398c780804fedfbf197a4c6cc598e4f1f5e975c2b9557ac6d54eb98a17102d7f072cc10e4b6747a4e964268b7c22313a31b36553f3ec6d17de7bef0e28c764587492405c449494c8ccd4ac8c45ea9e25889639fcffdf9102faff7fc582626ccc27064030222766d171625e45c8c2595a7dcdac5a6db16f96b498253167d768a5248e68e75b53979f8c33f66c80bd826d02a0ee225be5da6a134768472198a9a5d8de79e1dd1809b3d38aad02f4b0894ae7da66ea6463c0676c83f077afdf1de27e72bd75a1920d945683aa92352088004b50b1a8d20c1923967635aa067918329595da3191a4af2617da7809d053e362c7129b2d7f7bbff7906e890cc0a07c9e9543787498642b255557d979429daad23ba5f7deadac9bc3471f69ecd589dd7befbdf7de9f8773be5d86337b1b5121a45cb79f15075d42c33457ecc8a8181fb637a4b4308b146253a826ac95a6a997c71655a0d0d1ee95937f756ff03d44ba19c428ee1c458640b16f10993c23169b69fe8e26e1f3fffffffffff7a89b6f2f632b2c69482d59c617348a2ad997004ad0297d6d8174dd2c15ffbfceaaf18cefc571ae40080c241a765565167427d63b6115576f945cb6fc831ab37f58b13d1240b6de7b27d7400edfd57b90bd34665fceb02e2f877cec56cf950cc77624ea3198f71e74f975d034b7475d4c5da70d66147befbd43df08256610d32adc3a67aa67218b142964ea4b301f3e5fa6ecbf7ae15735db8b72430c1df4284d223bd1706d878aa4a82749345cc796948bbdf7de7befbdf73e84023dd0686505e6b38cd301d1cd135303365760a08d867f7901f0c06c5c5518a3709c771fb781ac0d98819f1a906af97d58c01b023fb1dfffff1f41ffbf41a1de4f43cf2a96c2ca49a1c23b866db5ecccd0483752df4cd21d067e453388c39b27ddd37bef4666cc7f905eea5d488ac8dac376e58aea4893cc1e132e21fc641fdd09add2bc5cc8a51454d704dad8a24dcb2daeeb8c6225601bcd3260079c3c22e27c1f62b80ec47033e59f276b0db64d090048518acc5c9de3347eb4f8ff288084cd9a3a55291f1fa326341e1460644cc6772e7928da77ffff462fee07c1b84f2ba9344e047e75d008069d7dbdab6973bee2e4eaacc6041461f3f654bc5f5e606a44b039a297b9f7def5e4d69f76cf4e7a42868a84f7f644aee128f2222c13c8c99bcf1e0a4685c4071c497f25941638b54f138f4a8fd294981db90ae14194556b48076ac6c4167afeffffffffff57e9e6f0d1dca75557ddd1cb8ac26c7d59cbb82fb014d5a6d5b883527c1e28d1609d7c0e2b3aa0ca534dceb90457ae8591eec896adc1526922c35a95e13c94f33006c01129e31edf489480689fee069a6981fa47ccb10bbd45d4900998e93af38d426d45a13f71656c7337ddfcf027cf429cdf0772c9f930bc9fcf9f870bd4e741231d42a79e6921802653bb438cdb949cbb901d0844cb6d579876fd2c9d8195d1bd54d03dcb40d5aa6aadc4d9d0ffffff9f996f4cb1ac09c933f1babca824d974ba92c858500c19abe8b87d2c3a50a02acff9ff7ffbffffffff466466c89d14aba0ea3fd196b222395d242d3bc196a110bbe7a970540400aa0000d3d525efdc5de590983863b6ece5d5083119b0798c71d61f336acc247bd251a2a37b29ba3b8b1d4c44b4ecccb2a6dba6bdf35b9166859eaad07a6caf2cee84738e0d66eb5493e28fe498180629fe46541534c5fe03ca029943152c0711e59b25280c42fb34085dc0c7821f8aa97d26bd687ae83515bd9f404d22a139b12e6d01dcd445604ebca89516e811f5cae89e5290a857aee043ec48cd87d08d6e66d5adbd73ceedbd7795a48c6f3d859b7befbc0c88f401c78aa31532f93ac0702500a138cb727457cc2bb81c6c414968e8cd076915b5a78840ef0e83ae558cb88e8c7f6f334b10db13e45896a0cf46fb4119df1fb14b61eb3a319bb1a3e540563813ae6635e0c0179c736ebc6aaf6bbcf7dea59bc39741e4d8655db17fccbda8c8937a20214b3c9737d67b3beb692a59f17a6aeb4878ed25664764f1e82faa4051714222e16a8971a07735c9eb572eba5283f520c4a5c547b6e3cc85883448cccf47cff436fa01ab1e6a1bd5158cc25a5839e7fc275a21fe2003d73b4820b85312d5eafc9a7a598b8188eaf22405f1ee88b3b438ab9e7bdf789f9f1c34ecf3402a671049828e544b3865f589f1058da27428292f0c64888bb594c46b325e69bc2d8302e6b3ad86d0bd100d739b9a6c1da528195b0ac3430afc91e51367f415ef91eb29128b9acab6c4ab8e690db1b4ed28ae40cf925d6c3dae6d6e3d21577e8ffa9539bff8ff2f230b96a505cbc41a9c6fcc4316c70f4bdc3d6b39bf08fb985ae696d955e47ca4bf716d483a02ca3b4a59ddc2e4b7286a5756af6569cc0a14e9fcfb07b9e3e6f0d1526dca4d5fa470ce3955f90a8773cea552a18613dc5e0af59a01886c60ed40e46285449113bf15b900c5f25a33d2995ad950c4ffffffffffff2490c3073da189cb230076d5b9b1fcab9b9577efffff072583c6a013620a8f50058a94feffef086f8341bab7c0933443b9d37bc9097383616ff12528be5ccd9ed0f208c6cbf8d4e2ff7b20da116311493b3a022d9da86d7366e411b6269b4c01d31413217e60b3712bda47a6b2c011ed0f494d0b1a5b00f8f22b81e46643b602b4f098de7bef64d1cde1ebbd77efcf109439e73eb32750efbdcf3dff83b40a5c98744eae9ce534bea0512ca358946b1ec0865c456f9a2d63e3d38c9ed78a8374927cd141465c67435ebe422ee86030b6537968256e2e46399df29c40e1ad250cdeb1190223578120973591693ee0bc6758de6c567869c474359df2c478e9b23ed0750190da018d6747a9332702301ec44e14816b46d5ba835b209d4cc6f83490406b3087bd269559954a565bd776c64e480cac075737f7c12e20df5165fdb718427b1f7a6d70ce39cd916649d38cd9983771c7fc70c84c2f9254f30eac8531135c4d7b0b412aa30ad79ad4b42ed4494145db96b8015d2a8c26d0143bdf18ef8374ef3c7b6a8b38fcffaf667c35b222fc4783322b8d73aa85ad5e4e29593a58d837a14d461d1133e2d7668c8a3237040e40a144c0f93c9ea4f5535928fc172ef03105efff7ff0e6f0d1c227613113b33eaae652006c88de7bef3c61c78fb025f1bfc9854c7e1f3e4b28daff7fc748f3ffff7f9811fdb0ffffff4ba4449bdaa99c28b5b33c37e30b1ac52b8a970fc1fb3161e9322133b219da63ff5fb312f440c11d5aa1fc529e4331563afba6dee35ad0d71ab74e8cf65230ad73b9cb79a9d1336e1375901a065f9a087b1f0f89dbcd9fdb88b67d9a964a1be19b26e9769080897cf8bc20fb4354ec750c48c988a7760994eef79806a09da4f9c28e26f8a707fcba5e00e3184edbd400327f820fa828e79c73ce8d555da71ff2940e9218d26aa5375f216910b4cd961331cac856ccd7240cdf8db3a462aa4bf48e68666b19d5f942697f9bebe3ced097edbec2c8ec8db6b272f1ffff243c4abaf3c9afe36d28304b6ce449c296a08c9ed1126557f9c7e6d9f32265ecfd2a765240d813bbd472abf255d762d76bdedee37c1f65daffdad8534e208947896ba7e295958a49bb385a6ecd96a5b3c262e46062ac13c6484d678c6e85e7a88ccae59be7a5fca23fb87db55add693e85f2da3a56ec7dd8794febd00b35e59588f24bd62d9ae99a20f91c81c4c16d2f19ba6d383b4c21aa34b3b3eb4d98cd943aeef2519b5fb65f4f61eb4a2983f5f596e5827350602121b96d6dae1034df8daa0e92ac9c25bb212c17778b215b4101052edb9ace1c846a1ed78b15b9096c84b2a6c68806acfa757d2b12b1b7245044e0a16403d8b177dc17215ce01e864035c40a385a5ee4d0a1a81e71799335e8d4155d81d790c45b6b8a2135677f1840c977e1232ebd280d40944e44da232c79674de78e29d85aeec3ffffb7d01b8087ed80af6007b53bfb7acf08fa3e73529cc0724dc0a34cc3eb82c9c691a9153b56ef1642a373c9a53257bcf7b969f91362881ca42513e20dab51e8b0ac19cd80e92c6969b6d586d3a286707f9c50af5a72d884c0c357f78c49826424b5ab46dce88d70a320a9b939e7bc5cbf1ce98eb425a0a7b84305925c504a90f5562b03328f89b2a4221324cd90a1543345b8038db8a8446eb8358d01307b040319040001005114c8c24c925c3d14000417ba9ca47c34483038281207426120181006838380000000000381807030180612c3a2d6c03d4c6d7dd0c9832619b11eb0ac4cce745e11bd9739ba2086e0a3e154a9915f26b861dd54573a9e70debe2d88342357061b1b7c670363f9a11b6e0885cb4eb763888f96fd2d9790e77a92094f6d8ded5c52891777879af879094377864c0ca958ab1597730867879c4285593be7831501874836c79f537a00c6a9f7297cc7140c8c5a16499d789bdae48023b1c10246b7bd47de2274afd17abdbd1e1cd8c806fb4af009e14d46f69aa1a76ef1702879c7539c1c83a02c8a83a68b2b0f15ffea10db60183ba696cf8a8c6671275248799099eea6f001636d68078ab302a85a4c456ae28f1f7a66b634ce5232df592e497aac3d13f44e9241496ce8c031f6723a18fc68a6f9174fe69ee029deb47cf5932bd4600b61e85792a5386c2635a9c56b417ca4e0c4559d59a05a3d38508f2320e9917afb08cc594008d3aff5221153a2d39d151da7b8eb36abc3640a1326c35dcbc79add52fd70ddf60ffb74539d43c40c02e57b85803391bf4d777c9699b4ff4bec8479b34f8d5b27e8da782ad465e9cc76c26a30cca5e7962fa97d186c8a82570ea20fb78df4d23195e00ce0396036d64e8e2a12da8b804584a73488d01f1e5df04e32371d8092c9dfbee61c6cc8afe37f773f2b33beff6571d7a618207d0ded80b8ef1ebafa9ffe366dc29bc1ebaba635ee3e121a6ae289943b0292c3d9b536606f680881eaf927ba4ed468d2671dfa692572d2f543d318b4b92794b1e6079dd8dd1be8423d79e2b4a7425fd8c48605e5c66469697d0a1209dc114ca9f721e39c8b5ea1c42566725c2611ec90b6419145e8a4baac6eb62cab81744cb44dd3ec38bfdb0e019570e53aaab3d05d50f953ba02d19c73bb00a242f4cd99f7de9ac084c7226844a6a0d5b71f62a515d02476816bacd56711624bbd92d44a2b8424fe67ca3776bc413f7a28ed21c910a77374018b5b4aa27ccf0ad338da94bfb451b09a2b55ab653b4bd1bbfa45977d00296afc8d224f21e691b1f89de51ce589237b93c5c33a5c02fa75cac43e88b32b660717dd7261f5cb413a251205393be5c25c530a150a42f6375704e673f4a553e603167f23b11c480989eb7a6491375df1265feca7689ba91523aaa5f1851ce5f8523802e6255c8c03813d7458665003abfc64697541851ae05afe5fb474e3471f54c4a39530654d2096b1486c13d460f9b062bb1305696db0343393ff7a088f1da64f66e91e758025f3ddab26e4326c45cda5151ea7759da05f8eaab8ccbd8957cbe8b00460b810007481659eb274ea4f9b6bc6d6a0abd7cae9e316803f526b2f4cb9093140f3736dee1b256933d4a8c729818e9bce7d3c9618284ba6dfb4bc6bd14a783472467d804b422e963c4751aba88922b9835156b90e83a03ee25ba3d1b968d1efb4a0187d0f0cddab30ef45b70aa670b48ffd26df16845d6a896d8aa7026d8c6cb8eae9f9cf2d7dfab847e484562245661d269c3b3c4d26b1085df783e0540997e4634906f92fd4735738438452568023da1e63415ba9f22c49a46aac095bcd2f915e2ee893e20921a4138b4e581485c4bdb456a56c203d7e0eb4045df60b53846477461e3814b938936936ccc06e79b32eb68e0d248be3e2a8bdcdebbd2fc39915530bee6b5d6a9889aa03c18caa7b5fcd270d3ffdfdb7d4da1cee9f1e32a7e0d45ce7ede3e951a6e3a3bde2cf32dde0da38a6854158e99b0804cbac5298880ffce8b50acebb1df4062b1c3a7d053259a00489ef1d337993a3bc95244618ac00419cabdcf265b7ea9aa9a4ef596e71d112a56e150d3cbeb05cb93b39ddd0c6492b6cce805edd24598ef6572edafeea87a6182260c12ac13ed5fbb54e75628fe5feb111d7d1455a9a6277eedae36345e5eb46122428667bbcd06c292f838579d63521ae5ca9bbfd4aa8045d61cc8c3579a5f402cb47094ecb8817ad1f94e0207f58267f648135b11f66b9f4c0223b48633a4d224eeb7ea7f16b1e4d678862cf730b4edf1ab328c282f3d3499556f246dcd3d9f3f245613b30faa91ee1f486b71e608f8169278ade0c3b00ae6b81f5f10a57b7a8f9f69f7bd7c13e01905f5dfdeab382d9c3189473ae77ea94052b1d7d5c7261fe396e02e4b5ee73e13147aaba2ac214a7f9365107808726badb0ed1f514b19cc061ee12ce25dd3c77953f82ffa489902df79d910e0e457915b4b0cb17ce6c8886ef8857e3bb7c234b2c8bb42ee018f998e06fb1a03f6a820a75d0fcd0ccd2cdb87f247e820799c944bbbbacf42bc2964201c9085c33abc18cb1a375abe723e8363a95a132fc02359908e3532ec7aed2cc1a49d5501cb5159ba7e25acb14f05b4f746b89d7f2cd77fcb853b7bc2e3fce3b1f7ae2012899d42660c119557355a88a1a115f85dd078e620bb83e94978f90a2b675afaac669adf6d35d2806db7aabbf534faa981849c18e6bd893682bfb258e10232d171379883c1efbbded23c6f7b808883cfec543bff72adbb4a34e622e0f2aace4fbf0459a36be5555687187bef98305e0b6ef81ae10ae1c65c2a22ca6c9264db164b9d5c2023580cbc0fbbbe10ac6d915707e82553b3a7c02939ba5c0ba3ea0f001b447c0498eca6917bf60a2dc2c3405792eec52f9a79c0f63f9fe026beaf14217db6559389362691eb363f5e00579807fcc0b02eea07934db9b725fc5a6b7c23d2dfe48680455caa5af203178126bee22681afd01c5a8dffed5b493a0fe28541ef10543f876c3e238f7f6a693d93849913564e6fb6a50cb1cdb8693fbbd7d772075d86fc5b846e42f4192c7dcf0f42fe87b20f7b6f5e0249ed00b92b270ebe76e24d4aaa66084249680e1238082aa532eda9efa01517185af981a5c69f2ebe8f8af08d6ba44ecf7dccd58bf20378feed8465448f7abd923c0430b6c95406e1da3f429367beb3f010b4e2f10c80b1104dc343d7de2e3c8006c21ffde51158dea7ec92abd64687c1b56f3f31c5a79bd2889cf8f28a8755c31873dfcc3c094b299f138b8b3cd1d2e3f7504f75ee577adcc4a748f752d32a813c52b5d48a738909afbbc01c9f071a4af8e2eb0f3e178590856a83bc17dc1034a593af0f1b4e8798bfe2488ad83d764baf9e70e0f065731aea5316803ff5012396ebdf0153c9b0fe4c921350bc9d822e6f6184d85d72882a2d740a3ca40ea433dc687bdcfd133328b6500ca833e1ddec88a4434bbea14388c16bbe1763ec95e86b4ace27f6fb333234a7683536d3cb106885c07f0c91ac142cd68ae8f248289734017de9361285392fd6ebadab15ffc1f5b5ee5eb66af05472d4894372a09419986183ae29af9c4c46c89ae4cbb37db360c69f53afa13a0a258fc7df008bb115ca4ca682615b76838c642281440affca1218c068be1a67a8080fa0f2f6fab4ba20c5eae3e5cefd831599eab2b0fe9d52c3ffc52387e6b66651d8b47735b0dbc5b557aca4b4d6163f422d8df39a42d39bf162d98c5bca3e7fd4e6abe1e99821c88b0a5dd90897685654bc2c0a95beba5e9036064f95e5a37d75924c9375a61a147b9a061d4c02deb96adbb9f14a5256e805f6a52d1cacb5256ddfc1a7610f72bee27e63cfbb38c30d9caa1c1aeaa7432b5170cf0aa36e2a406ff8624b778e14c2c4addb2552a31abaa5a1bf4f32b3d9ec51ae32a8099d10d56bd536650394acfeb57a9c02ae08d2b8a7d23aba0f9f35c15510a722a15f046e58b604d96b0f81902eb4b6bb4d58a0aabc77ebb74c13acbca308f9c4b36e71ede7e9e920cd92b1524a24f2e85a9a4c74d6e3566fc9bd7ed8a1f5fa60ebacf0341c556ea4f3aa612365c31ce408f191f03b5e9b203cba76b8287c73412bc120441e6c04a28663e5f61b6a8996a69e6699673fa35ae2d1a4f88e1274a583cea1dd34fff360a34106bca0888b20289d21a512320b24d903c44a00cce4cdd40fe2aafefb1e299257ecba8439a967888b9ee4c81058121fc8d186813947568124c62bb198192e4560e39b22bea132108745416713d10f5890ab7a6844138f5085f39ac98621cf973c8b661ac0bbb69742a25562ec2ba7f15e51ad1f51ef944729ec9f545c310d5dcd642391cb4c57a20c8777917b8fb9e4d432158f222ce86df8973934af3cb3a5a408e87954d771686804b6ef47c3737816403a27155ec9b7a55a8ceacfc338fa25fd5a73a1313c1bd577a217c69cb2af0f1a5ac6b780237d57ac20df625c74f90d4c914aa8bdeaa99998447fb46e4fdcab279ff331a56cc8c6accf81031c810364d6eda58e3a75a7b51d443304fcad926646d447a4d92ef94a8d06945f772e8ebd69c362ddf5886586355ac2bc041260ef41eca233815e50a66a54cce9d4720d9e30134945346926d4f174da076349421bd9e96a05845978c0b8a8d00786230faedbce169a58fb089f1d4d9839b26bd852f945b02858e59fe947216ac00332a44d1643bec6fce9bf6ba63f9e73a89a67141f9d6256f43734c59c0786f59bb321d2ef448e3477617cab081f13dc0eb93b7c96777c854ae5da0dea0a38eab91971e2d84db8d385e57b9af1688b3e5cee60d923b74a5a82dd18765d1e07d1ea5f80a82861a1c60b08c2818ea28898485833306213ee3cb4442c15cb4bbe209a8f165a424577b040c41e9c3f362b52eb3b532051038f98a602e41887dfa902afd43d1563450b1e74dbb3b8c7c8a097d5de2f5946cdc1d17bfe0d5c8feef9c308284cf80be37a4af2e27b714741d6fe1d39fdebd24ceb7d1567976f89788cacccfe48b203fc48ea0cc241902b753fd35eb4354b65e8ba12b495f4d0cd3e2bcad2ad6e91a9a99cb965511fd3f3ac3b95a69fdc57fbd97a84be1ac3bc2693737e01eb2c8c4c2f91681b9b98528b0d376737d356851ef864b8a82b9932adcb3e8e2ab6700fa8b1ed7235b422466b727d2a314175a3224d4fb65e8a0ab937e55685816ca40e067e4bea8288afd77123fe1ae6642f566f70f8b1285979989f8599b7fbc886184a8544901e051dce6b87f8f97cf36e791c5a4c35dde05d20b4b19dd988b024e30f2710e77b3543dd9dc3da34b8b6d2d0746009904b627419f9dae8c9ea0d4cc08f3249b4dae222f94b120e0eff159da29d6fe355a5a2ff4559b7c3834ec2078308d7146ace6988ca0fff6b9936c521956dca6ea4d4ff67dca59e137cf711f33fbbe9aae8d81359416d4a1b978b5e341e85dce83090573107a0b41dc42f6d54358ff1e7b9452141786b5f4a0318f7c4e65b301383999125430065a0d0e6f14245264d51c5798d1ad95234ed01d96cca8e862ed8890413b260468e552e5c79f3a4b336bd18381b55c6a4c1240d460c76c66343082550324f429942a766c7e3648d206ee334cac41afaa3e65c1813c857a7184dbf08b0fdcc015e7aa488d4170c63ec025004e74fb08009c58f0697c377002b9fe96561bc68609d763b541c9f9ced82364b7fab611aa7859aa9752a00a3507bd1c0c1a0d1fbd8d2ebe7acddd03036dcda1500a013b5be6138f15691b96ecdf2968fcc3c9fef6a22fe8448faf1aadf15cc489b091e22400b769647980a29a48822b4deffb2d952f6b5eea062534d7309863340500c312ad505815317bb976b465174bd9c0bfd092e48205816ab8aafe34ae192ac6c8b7104009db05ff50f56f11c159721df017c20a86ffc266ab8605b32c6b3a8a494a5906cb47d66ab856c29c3a257b0d2a7f2fb6eb789f00188b8cede55fb44ad189b402a3759415931084eb34b0dcbf6503d0026083b4b28c1af4ab1823799acb1eadc5a04599784d685797d570a7be4d3037dfed542674b07825caa104a994c03003d826387205e616dd6a2f6bb5f89e9cf31c4205d2010d5e4ed56232880c13ffb31e8689d6cc5558d294eb5980ad3655117a95eddc7fbec7c4049f36895faa0be4c43833c76ce852ca387b9a0eb6dbace9c1393f47c680b9a8ba14c5645b471bb70e3c9b6e33f9845acab7f16279e6edecd9e68f072eb1a0370d46956da19761983f72c8481d62e32775fb1e5dadcb5c423893648838176d048cf6ff5ce3a5df113a10ca7ecbdf600516a3acd66969ff160e42faa192f641c3ec29d0950691d77c98ab92a5ca1403bbedf50fd23c78125c413be12ec5f09613e6bc71e6fd1aef2fa48ba750942ef603a85535c32a59373fa93c8e32d0c5acfcfd1490ae647b546bd8ec96bc03664c68a8659b74b43374d046bb19bdd4b0f2dc4e22fa6338b2a94a53158bca91719936ca3290f3f06033ec3b240cab1d3c27263c0127e98fc35ffd7ec0a0284cb2fd5746604b749c5765dafa607b0f9254fc57706513af645778d2c38b69e6c1cd06f521d1d5df8a1994592b56eb298cb3ae4017e14c19ec873aefb46117024038b81e7b7bc6d3887f134d9c7988fc20c803e2cd8770d5a11c93c17d04a70f1eda600b073e52df54b1af48e6bf7942202257b8e8161d203cf97f42f7cb78297b8ce4c58024fe8edf3f2ebeaf51fee529489079efc5866ef8ccae6b727a3e386c5c07e31544753bf35bbecffcb822da72fd9c0ae72d371aeb487260c1a79a702ad07c184fb12f8c1d2b824bf5be0f9b7fa7b503246d317e767ac91b3dc4fce102ccef703401a29f9a8ba287cb0b05a7874cbd4c54ed41ea786ebe9297c2b5c1d18eca23551f25da20030681222e96b2a93a552cee7fe972d2105d97758d0d2bb0e58e0f29516ed97cb4a5c4b75e06c7775ada7d6061223ee134b014653f76408e07f5b69e0458928e56f58f7200c6ef5da25554911740bacc75ed5b8064bfb4c899e29a7a6af4583a4783d04919f314d9891fba406a43dc60989c48ed82bf0998c8e366ef2a5797003435209fa64fb0ea31ce1a3e6501d3570d7e73087441b9655cd915cf7d391fae9ef7f80d2bcb6382be28bb5afd42258a3db9f9992b9540b7e64f820162b3956d7ed0f9744c2b3a3931723decd0c776f6e46ca4b7389fc64d39fc060caf5d4ae5795a6506140c2844e53985151cab439da4d9c90eb586230b147c3b7a031c3ae0c459441f7ba7fb5860a856f90187ab2b9bfcaafcd697870e03c08d23ed92f84d338c77fabc35885365eba1872a707256945f80143c8d476ff24174830d958331fcea75c990917bad425952772b45e546a01f9ecff29ba76478bb74d896892e9041e4c0fb1d44064a4edda296d5c952328a44c8d4d68e7e55632d4c431e8ca6f4e25b0de82dfa5758850036589b6f94c17dcf3f2e1e33c60e3793d43c46a989718227e2b85a9df20fbd06f2a91531930bdea59f8869cc12260a7af99f03cebadac3562900108920838964e201e702e120a27c84b40dadad6dd396a6e288d8ba626a3309e9bdf13d35940e0fd882a077200adb1902299c83c354e47f7f7f942eb46f286333b9b7e35d6522662f0394e7372503481c71fecc71c07e20fc2c8e59d4fd75e68c322297c9cf7f5c1a2d236fb2ed2098f8ea2477141fa0d9dc46b37f59b0ee1a2860afb44d0d410bee6fec2ad62a5365da0439ee1e5306aaed35aa7af006b103e8ba37ca9d31ab92fbfa63ff918c307caefe405cf847823dbbd10a4577ae11ba1426729751e62cf58260df5ab6b866d8145fd721255351307fd7422f4285d04e3a870728f2803a5b924d7c2a11276685563828fa8a0ddc943bf8b951220480964958049d89f04aaf38726e4a0fd2f9a87aacc47a06111179a7420233153bc96ad7256b165c226a6b576094d8f25e49cc0c4c5e9850b83598c9ecaece40d2fd7ee63042e92c9ec99d7daf4b4ad29480ec3c99795d1b4b00fdb9cf05a7e1f313c50eaf066ccbeaeab4fe642c7b14acad53d3f55e713c6d951d5169eda1325357ae5eb03dbccc56bdfe5221651cdc9e91bcb6d4ec5935add36dba4f7b82f885d6a380ca3467fc96bbf22a7639523c42643cdff1e6e4d0d34ae477f2cfbd7cd8159b3c125ed6d7476e8ccb2132c7f8faa1306464d52f84ef9522e8047158d97f74e67ed8b1745c76dce26c2eec8e7184425ee476bc6452d8cf9b12e3d925e25ab2a14f29348b2942763c54d8dfa02ee06a9a898e32557cd4c2eefd2d960d9928ddae6b1bf94dce39cd8aefaf3952be837d0bab80292177dd34e61867a5e85974b98ccf62eeaeda11aa2399e78bebf1338573170300e87f7a09ca1220228bf7cbcfec8c9c44d77f6b0bea5ba1bfd9ada29131562ec4b23ac038550cde17f3d3977efbf3e973d89b2ad944737c52cbc2c68d30fe806a13c26b76103e182b00b3227956e70f46057623883f90bb20df7e6430afd09e8cbeafa05974a24318c5f68e8e2242d914b2d6ee8e6a24fa079e70e9741199839fbaa2f2921c9d06c548773e6bca2cc9538f0168b2dbc24d96886f807a978c30d4984964a99b51e0a5ec2d12d0113010492e71740c8ddc04df194827236273572872efcbf7851c4a5730b33c2667afe1f8f31a1ea43370438bb76e96c5c6fcafa71468ee3479fab21d24dc2cceb1fdf9ea38da014a5815bf5e837f3c60b53e51470e797f8e8fca1a27e5d082780e290ddbb07f195c4f20e47ffd00cb4be4d0cae9b3d891b8708a9131652a5aa5adf6931c2912978af5c605c2683568fd15d9e64e3379f295ad91929d2ff8b0008b088b5b285f38e8ee6102a54c24961c30f21196f729039d29df4ddadb9975c83c132c7e72a20aa3131e4ad84a2ed88621eda3fcb0cf560ac05228224d39cc6ce0d0c5190d2830e0d39d23bb3138b8b33685e840944c4764e9da232bc54cd8ebf3fab7fd89216565c06d428d15dc001419df1f26cb74e98cf8bdc88ad68d9d01e6e12d56f3c48796073dacff78b7b7c346e35afb731fd18194772989590714e110b80fe45e0cced015f9301c4323c89470418c7ba36ef6d13a809ca495d44518c5ff5e58321b7acbc3d9250a4d0786f4a817c047bbf2c3a155dd79efa7c8b734721234d44971b4483b06975ce2c5f5390b2614848ed57b45e50c5947ffbb400700eede7a54dbfa65091eedeb6dd39bc967147b1254718fd2df7453e88060acbe82cddff371a57df99d7a60b76208d922b755561cf23b99048b5ed4392228917747ceca7e20ecade451ecdda85b27c075bb03e4459e13618e68099ea66969d8616145fc5a056f9813172f8fa43e59b12664a2bab2554ea9f5c19696b4a76981257a92c9507df17f8efad2bab5e9e11d77a354e1566695c256d1b25e05566b643f878123621237f859e9efac70790dc56086c288852d030d2b4de97b74f2711369fcf371d98de184a011b879ec9bd1617548df0cd3eab2f15b348a120715e02344274b9167fa43ed914422432b051f12abe0d628013d514d813e31aed71e998c887a04ccdfe41de2a09f937941a102b1735cb7c23bc4d5fafdb447d77edd1cfd349891ab66f35fddf6bbdd56d20b459107644a2b257a6a7aec6cf814ed6b06c314ea8f84ae95ba14d4d36a5288658c2569d2c02b0bb3589efff41471a5885693a00d57db65f3d45cc0fc7efa7902aaacab591e98b228127a84b29ebe85d773d8d9810d5866d23e13896b54675321a1e1b15742f7580addb55db02d1cb48f919a1d69458c907a24d80269562cd8a5db6c935f72f08e4f44d42d94027a63f0507463e27a92bd31d1c511d4b7a1f6726a44d35f2acd94ab8195faf979d38d785768609ad22f6bd6f5dab81dbb3a60db12008222a60042a0243825aca5ebfc372627bdb065e154098075ed352195248bad0f55c29435a58d84b294dbbf46036127cb76d2bd61d292c7651e8a8cfe917587b3cacd04e8652cf0ca25db392b60f261b1a4a9bbc782cbff92a677a5e907da54317a987ee10b73f78876302eb9e1517163d493f60e96681f6d8ad7ea96f3700d5438a3d7be151741374aa700c0873b711d30e6cb893396f9195c5cfbd8a00b2c20010aad942751600eb1ea545b1497655c847ac9d390f4cc649973f38056c549d550ab64697146a22eeb19d7157ff1c63b28e18d17487e92732ce0d35f800f2c2e8b9909136a49a142fa43a4a7d0b1342dd949a6bdf7de016102610261023278454ae35ad48a660c2f88a6ca48c8857bf245176d76b5d819b66856a0c2ff4b98cba2997b6ad3a2c9b009654596525de3cf755ae1bcfdff0f21b574efd5c3ffddfbdf4d3199b24d96e2103336c64847d0d5f6cd74cd956300d0bcdb594a425bf144e19962d75627c3066374b7aab9bb6fbdd0a0b7cadd6b8fe8da7603939c174ee50c8c3db25c1a4ea1c2ba37f6d385373632715b982e383a5a4f27aee752f8441a1e0045332d714271e16a9f5119644810735a3d63654c9570879977efa01c02c9f519b80c2a5dda3454f4a8b2a2bb77992e0aa05121400c8662ecbd37ca95cc0177a05ceb215c90e50b1cca757befcd9d39e07a6fe1da0276dc9845d4de7b8f1d9788265264c8426fb6f5fd10b5c168765b4dd063e2812ebefeff0d51bb83a542462a061bfaf98f86640ed8e9c6232887149f12f0a5f83ffdff27e2ba91c83b74ba31c2abfb111341e644517c2ccd176a1a2dab9b33a26d67ed49700b435ac81a9b235458727833c176c4a8f905c5313bfbffb932e11c974e22e174859921b59244a6da7c0a8e83564b4de268d1b118b7591b102f1bbddafb4423dbebd5efe2494a77f71967af63063aacd69f62a6e54bb04678884066aa80f0b230cc568ac248a62c732547c092a7e15cb68346322e65745a542a642832e54416ba5387ec6a3099b3c5ff7f64754393cede7befa59b9903aee7f9f3bcb2d285a590293249326542a5a68e0c6d7880a56be2c244337a9bc9841d7755da2704cac141f6de7bb9f7de7b0b37b5fa21c5d2432af2b9f7de59ad9170f6605b564fb8bb7bd27f2348bea9079505e166aa5b673d9aaa620a72a6a29e0235725c2a792b4e248d6d04d3e58723cf568ac5f992a5a7d3210f332ce9a888adc475516ce7ee4cb5145eb803578475d7b01a435d144bf6e173fd12013a9282fac462f99ce998e8115e05e8bac467a76112972c7b1b9adcddc3aa3c3a45df000e89c6a0d33129863c140c5e813e301e578ae71d029733d2518ef595062efd4ac0561c93eead4bc7f4020b56d6cb88a888c9dcbcf7de7b5310e504d7c29a418937af252a09b51a2b570aedebe8482937f7feff89dc7bf5fffffc55f8fffffbf694df0e3e06c464d598fbb4b1ce3d952865b87e51cc80e0cc9ae24cd062537ada9069312975ed583849c0359574b2c59f59c843246226f03548b566922efdffff1b8686e4de89d37b2d6f25e4b6b2f7de1d6e50b73520941bddd6104dce1e274e77f70e30f1b20a835495f04f162a880ee8838ddbe456e96b2a6b5a228494567626d04665bd5a60a5c68c4e6f691e0eeeb0e25a798bbe4163f8246714a85349c0908489fc887005b9b4b1d4dc889d29857d32e6c3cc757747bafb8c5474777777d8badd65f1f1d7f3f77abbbb1f650e185927650eb8b877af06feffbfbbbb6fd04ebd272fc60cb75ce5b985368004abeed17b252245fb8a98788640516d19bf9a33af40c069c9edeceeadd9643d9167ddc1abea2e8b52dcde249862b9f1dc1e122a02ba5f7c67a5ecefe7eebfdf36252e470a33d635e265d2b08bb2f25916c559b94db9c4a8975fb0cd6a6524020f4a2c09d885b2639b92b93962f6826d514c211b05652358dcdc8eb06031981c154e8d66454890adae8bb12ed89921b68ae8d5ac99a1b4d6ec2c0b52dad9eebd9adef252061a2a63a51dcfffbf87f7cabd579f056531b1284db91e56c853935330453b5c33c7b09f6888d512d1d405abf2a345cc90c422c98e60242d7223bce48d6082c6e4189fa63feaa187b9c01a137fab2f1bd5a04b77e14a72fb68d8430e090402b74e5587acdac48bc2eed7a5c77e68ef9f8b7fafbcb2d2aa01e846761f5d826c13b5cbd89984f7c294924a61e1ec5bde08154a9731249c207dfc690022230287a86ba9ec6045d75a0787fcbaa3cee4fd989c73034a4e0c776e8ca65cf30e29848651884eb9e126938943e113b5bddfd76b98640e58eac61a2a0e4eaa86249de07e20c587076f1187c420daad55b07afeff7f669b7730e5862d8e543827492eba2ae30a1c8a631941dcad7d82d9c4fcd8cd458ddfedbbca60f4560831cd97a710e40a170cdd33ae3c9c32ad14cf0874fcff8ffefeff933307dc26f62f1d82ebbde59fdfec43affebdf72693ca1c30d596189a0759db7fa0e1edeeeeffffff1b9f526fdf7befcd362373c0394021d88c363086b34afc51ad85b6425c212f07ade2976ceaffbfd7bd57bff09f05b8e45d7605dbd44e0a2a696e2e53d96cd6956f2a0376177495ffffa1b2c797bb81545c48cd0d717807f4d9acfdff13b50b74b8d128f1f12469aeaf4e4a65cc762a748f4bcfcc70caa336f7e4f8feffff1fb8516ef6de71d211a3b7bc32604262fb5476c71c52485fdbae7209302de706a2428016f4786dd8556ba72420c6c8f7ccf8e661f5441c338f1c8aff0f38b304062dd21f310c983417dba96754d91728ec7e031075e931dfd93ee07321895a0dd59903ae7f183dc36a70bbf7a6d990340428dca4ae20936b9b4e1dcd4e165457b70534e3f9e561ae4bca7155106c2750a49833a677e663e6982545f2b11580170e1131d0cf0ed7e8a4e849c513f5fa34f68343c322482763ee8f0eeb453f70e2b2eabaa9c114fdd0a8aa63cd2cac11bd72edc92a47fac2eed7a5e797c66537d0855223a76bdd5c772fdb40c96f9e504f95894f33048e73b6345561619973d2a68c15adc2c1549a3c52b59d39e09a867bf5ddfffb94f466247083902a41a4ed2dbcc84299587c19f474f3aa1148d9e4ac1da83bd2e28fc904b821d91c7d814076226853fba0c95ab7372a7c291d9aace26cb536a99e804279b5d5245d63ea99dc6df820240b67e2ac6e7d689421d5dd1d2eebeeee3e1fab7244d0e0beb4416975093707dc68bcaa943e7c7a48e893bde5abf94975178235f2ba46b1a25926792d576a923679d2783bce6eb25c16081ea2e114fab3748cc1920447dcd9dd3d28d90b520edddddddddddd6d68b2ec2fa8a18293a508cd9b56a305439897cb8f0817526d9a624897f88496f1cff3c643dd9f6c61e74ff8031fbd258a7b0f3d3e444c4ab840a2bc9c78583ce958a47a3468e45cb3dceeeeee5e348d9db551152356e36e97c5bdb554660ab65887eaa3e413cde686aa8cf4d944c8ff19509ebc723c509bb4320f5aa0b0ca29f960e98c4fc7e4d13409974ae5f556426778dd7deeee0e5cb2d04ee13f93532ea46a0515534c6eeb89b79b40886d2c3925825ea6a886e891019e90f33cb3107a7d557e8d1561cfd4ae8c46ec2598356d94841d13ef8e16f18baf195266461933b39cc126fac5b63001e6d695754687502920228118cd8d5a59af644f2b06e3eb5e25ffffffd92d1b2d69d8881b44faeabb8f9ddea6f0634c2039d276f609c006cdb3ab7e90884a8bdbd22e25618d7c6b1a048023e74c443a9babc6312d759d35d470578c5da8f40ff8443310d08e00a318080400c4401c09e34813cc071400040eb2909c8040302c442c281286c20020180c080ac000000010068341e140280c220745ee615d070d0ca45aeed304d6a2ca8b6926b4d36ee5721865d94b577cba5ada1efe02c85ce3288a7b59c7dec983e6d8038458efbd2a81d9bbc70d717d3ee2d17dd7d19a0a3d2a56dcedf4bef690fb77ecff7b944122dc3d3e2fdab19244208ba2f87369da6f50a230a607fd1f44dde52cf0ccdbbf6f3070f6204b189387cbf681b38bcdf629ea80f8c31aeb38e40bb95c2e3ac4600d00811f0e35762e05816673adb44e0a0cdb4591313b9610e22336d0db4f341a9c8f6c374e0d8b3f39193a068b292f115aa3b9054a51905b96981f2e4365c950e04fae7866db6869aede51568ac2322d54a74f25c7cc1ad94aa70ee18dec76dbcf3cfbf450ff8e32b13530fdba6454a1da5deaaa6fbbde72a9874caa80cb13cf45975d2db86c65a36604ff2795e7b558ba18c3a610d02b48c4170968a89baae10a9b063c583e5543eb4e26e5a8a0c04409a1e1184d2a4b65a895f54a8345d8112e1b3761daaf06f8ab44045fa147d6376c84576da35327abcffa2ea9ad9cb916bc4011a3c9cd17f051ebbf0089d207fcadc924f6ea510efb376d7040ebd5955ca63f118fbfc1191ec4f21169531aa0cec08930420350c4497dc933d7f0de254e04946a942049824699b32b36b3d96d9ec30813d9913d45b349b0e1f3d43db3c77e61b5d58176a6f2f831d1461f3fe6b35d42443d1189712153f40fefd37d3175c19cf01a0b2b699e075c0944690db7860ee59f94c69244989da3857ea3568a48c5537c36478ae6ac14e9f038b4a5aa94a0cd060ab97950b50996b5ab613b57217ba48863fca4e32b39318601e98b29ecb4d34cdfdf24cecb0945ec25c2372043627b53bfd0db58f56d5339126b9858d8c08abda9a77722d78b1c10d50d21d849bb20e05ccece3d28129632e8471c0675975f2ef4dfb810fde6152eaae16ea4c8ebfa42a9fb7ef87e58a268dce9e3dd91c180a3763ceed2def19354ba37c42f9e4a681dd132049390846fb3c50b0235ef219e882b39941e78ed16c5aaea5262bb8f091b865963b75ef6967c3990c1a7c58a665790e132ad267e6b24d56eafaa5e9433ed1ee2cd3efb266a2f61630c94561e5c1bd6231acf0d93ce85c44242a00b41181afe48871d265d79e190f2f4619eecfe76d1a2ad5c6c6f134ac271ef45a26d7783c2f5db4085cb7c1ec0b1e9ac9f0883b45deaf0b711e2452ea5368ba911b25a580976071fe4ff72a6f991e5c11c7df7b9b5f9a31ede42d62aaf6c3f3b51bce751c7542b93d8441c38edd89abd370fbb61eb72321c17b60cb9b92c59eba65e5a1871027db0aebad830b5a498de1775138e0b563860812601e36e4a90b82a9c5a35616710755f28e6cfbf15dd6cda87039cf6095fc070a85390e2243894bba147fd6cfb9c6287952ad7c37d8291b782f24201344c52e0ec0c9c682edf2e8af99ba2252b63f2031f3bc56a8256ce7ccc5f482fe00c9ad987c33ac3eadd9c04218dc7377d4272f7fa1e2270de0e75c3e2ef8991e1ec9e649f6513e9cfebb680e99ec7f447b7ad47242d4819e9bde405922d90ad788e66b7b1f2a51cb4c991a4ec8c3483a9121d104cddb5b84d28263e5ce1bbb3b4f3c2efa879a33e1b8c8370d4e2bd381bae7b7028341fb7d2824360e2dfebf1eb9831a5630d7cab4b09be7d0b531d33907ab625dfcb8aa2f0d5f109ce3631b26e8e0d434c3aa3f0cf6868727f70e7d53fcc21383462cc6d2aef2037c6274d20fdb6ed1c5a48f67f5e445d5273f99475ef12afa4fdfde3a10f7a54b39eb63fe77a4e3dced42c979c744f703f7dfd3be7a01aba782623925cf0601e9d7fd0fb9aed9d0abb02cc5ad0073f2f00acb46298306e89dad930ab3ac59be8c67cf7bd0d1a677eaeddbfd2e8e4c806638407bf094d111016dd5ab1cf86a23a755eba03b1b6569893c308bb65081994c2341db9e61bcaaa5715ce14af4f57650f3b8ae8008098cf48185ebbc8aa89861a05ea8932109feed278e3c896e3ad8aa052f03004b52fe38a71ad66286de852acb2d014aad50a4b73bbc2a780bb455bb415f410d2a5297dcc654855b2db42ba1d3af9a0b8ef4c0b27289a118087cb12d1554edcc9003026d124485f1d24e4951b26a22d6b9c0fb3e778ae03c97075c543c9b5b156b68ce45e5ade585e72c7060ee3dbd640b70e676414e9cd07baf1614665895bbbad08828c563e6f68ecf6a0eb214d687a9a608f0327656971ea64c057edabaeff02aa25ed35e99ea0e8ed029cd6c54fe588576d7400975170499bb848c0a5e4053acdebdfe843023f94d8d133ee34cbf34760b5f9b385f47c005a28cab61d56f1c69e1ee84eb7839b7efd0186e5ffb3adb95d60b44a0b1f19997b97f196932ee0e8422569a740ffd98f249195d7d6fb9039b4b05062f7295dfe3b0705c962947f62d0c60aac5e3dcc7f3cdace496da115287014865c810c28e503ae98594f00ae28788211cde50813b834ec7bb12aca5585e6bec2f264c3087effcf0d1b8e6fb8db8c39b5a2abdfc67934fa39133a16ff3b1bdafe5810999b4d68b45ade46b72d905644ee61171aaf7df4fe6909d5e37e0db9944ecdd496afda1bb7cb26bd88a26043c509598064a422dc151f644583c291fa048641c75065b11139747dda2473c3a378de3d85eb28552861195c3daa1d08b763b762d447e12452d119bf532038079df1fb87594a018c57695215a4e2dcb519e7f989d3ba2c6a33c737f5d7276d41d9ac588523995fcf7beaafb4b51cc623e41988319defff66bd5a4a675f24eaf2602e8deabfed541379ca56ee3e6665866d13f8947755c23b935e52e9c6171c25926a453cd0162d87b66c99a5f1f9263c97a94ddc98783172afa933859264a925b593dbee32062491982416e5caec1c7eae1b6f8c0523e3ec433ca901abff2f4802e1a194f4f02007529a671cf2c9a07523e984e09ecad0078eb5d28dc5da378582242cd59bd2477fc1d1c6e2d5405320f7e668f59635c8a29e717eacd591f8d776bd46c36f36993f253d4bf4a1f5d0a921da07e0504e0c10209be1b596dcbc6401c0615cc18a596558d70e9c03d5b3bb76cbdf72960cb807761771eb8e69916b4c34bec8ac2c013240d517d413184282cf48753ca833d18fd8bbd15a11c7b256e8dbe8f06e9e3984e023228d2337ac19cf6557ddaf4fc72ef50dfd59fa544334b030c2479bad5de6ddf36a8d480c5742c5b2b1bc33d7aa2e80adf978041489aec2eb821ab9ebec98343cb254d6c08a256886a2d5073efe9d6939ae2584dae4c08b2980f5be102c2b2c1e4e834b2a103f8041da1073ffe5ea21341b82503bbc9da30d72ca3cbbf7bb7309c9ae3bc685b3ce9b5dadb372c119caf0918f6047bc190996da57b0e6f2bb92121663b994598790eb5572cae3329251f11a8e372c2947623db33fdd238803853e14c1c8bf9bf7ad3f3e852138b03fd43b0836e59ed68f0b76c37bc5726bd8462f20605681ebf260c501447d89aba12e0728631d5492c2c0a57c564ca626c9776208ab0b5a87d54ee2603ff0199092e1c3be0e05aac5bf457c3d710f612667aa4706bbcac54e12b0adf41bf2c17e8425c0cc3f9337e25c772f957fd5a0889ec20e628812d932b47bc20a756ce96d7f5c1a532a6f45d2146d88b9ccacd64c0d741c2b4444290d12e164e1acfea9fd3b4b6317924f705637034e117df47f5d058cceb8671bd88d29154b4edc1a380ad56abacaea33b1d3f493bedafe67a3305c96fa699fda68435c286585ddb1c8a0581362a32a27f397d9f86c92824ba2fdbbff67ef9ae85009ae55f8a6249541828d4d45da32037f2c7281c001e80b935404781e70bd76f5414397374399174194a82fc9c6562564b5934742ea707671dd39c49080d8c1ba82727c5fc8f240340211034f16d14bca7f45138a15caa7735d6889586d3146890c2b0592480ef2dfd49eace22b9520cd942f6a816ea57cf6eab6290ce6ac91d4f90334c7dd08195081520ea77fc39cb7976d3814e6f8e2ad2a2fa8ef2c54a06a3f891e196c810b0ed6f11d9719eb1072d7abc30698a1d11c0ebc22d6d11d6741e2644ad05c224296ae5899c3e07be59780f4ce68c13a50e240b212a17b0f7a5baa48fc44e936f112295a36bd265968f7b64f48e008cb17b12ec7a7a6ef762be0ceb349f620cb8d79e632c14774e4f636a56d87e9d8ca084e87fbcb68807d1864e35c1eb00745291654eb0e214d1d1727d73bf7ca9c0f90826720824e76f0e6a597771d75b0bc8824bf51e49f639fd10155b26a18daf298666c169e29fb4cafa11631d3cd41d1145ef9723ffee0338b4f47cf0f44f716d375200b67e1f567d222e2709c7f3de272178ee22b60ae7fb711a663a40109960dfa47faa50a59b4903b9c19581a9f2141190d8f40495da44394147e5029a937617dadea3dc03d4662115f393e38173d2e8a0dd151842cb098939f1ab9647c54dfb007477c5f56b5d5e0ed616e6773d5b26bba1ff0fd6c1f1df0974939f13c509980355925580cc7609f98f3232b51b3d19c9685c5ab2ab26015673b3e76aacba37c86c98bdc9e1408d82ca1741ffb92747c27b356c46194c63f4a919a322b52422891f094221d7a9b8a72cfe7b3f4558162233133bee7274e34aac4c8faa867cbe30c9204437731ba53679acac02d8441de30e296994cd2ea0b5f1b476527e3bad1377c103ae6d323bde535ad53aff6649634ba5eb43c044ee914a801c28561730af15c3e991e0a3ad1abfcd108e02e46fb08ce4a118ed5ac9e1520d6747cf8fb6429033a166596f77278137cb66a5b3d4062ee9fc206dd5c5686e928475333356ea6aa86a9c4edf987c78282031943db8b997d7b518a98b0ed56e7e058d1eb846d1987f56d703f3ce4ace613b68dc0145724c011006df741018eb26d3a90e4256be98f876ced0235a25600fd8b4aa3c9fa19b483eb83662651adee001d345e69c6199874979ba9b8e3c12a200b355e0d8825fd6502ebf4c29f0ccaa6a9c5f6a27ac8bfb56436e13f14d9e8801ff3b751c19994eb0753499fa12490d27a3dc8b33b0fb8cb6e1905bf0a140b1b0fd4d62cd58ca2cb7b706eec4ad2bee14454502f46db72d403bc7d9012483f40d78eb3f6364686deef3faef8b8502deda960dce505f87fc8576fab64965c6b41a18622a2f4d0a14d85e221fc1c3c50c0fe334406e56545cc3341756a7be4c1e4ae326cccaf0ddccd599893591b88f841ee2bf5daab39a2412b1ea1a97dad2cc38611531063ae78dfc0b2f823a3f185f1e2a3c0f5e6e2c1155090d73b1105873d803badfb59677b554996c2f0bc1f443fc266a200715184fdb375313f077c5ab4c3b6ba4aab038c2691a3069b2eedaca20ff3d23e286d81b0f134a35d79f5c8c48348a3a57719366a0b237ed724842cc393f674f41a7add14d075951c1d17fabd91cb19c6b2e38d278af2f89f6b63d9ca4d23e15a8dec637e57f5347ee12c1512e0f1557e9ddc3d5a8876ee18120d76f1e8e3c7f1ef8d9a605ed24d02a272de2ae89988b8bb55a12b0a860614b2c1dbcc10b052c0f89d638c88e2278c517db0b05e7c4e8cff1ba0c226882f18598bba1dda5656e286f9d4e152deea4030a7ba3df174f20079493cdc636c458aa84f0cb34640aa41cd1cf39f9aa1a1f06356ed6077a009286102b8b48f46a32cf6ac68864c24aba18b2cba7e61aab172d81fe4c8ca5ee8ce26d2fbbc406e8034482a6b7cb1c4911e45cb5e8113d1728cb38c84fa2c5113244b090f7d56e245e2e4cc216b6c59dd1fc2c0ed89b82ca88ed8d14438c60445c003e238b47cd90ea0c1586498cdb787d1d0fab298b2beed5469cdca5198b93bddd36e479e7966a25c03f065387884e7fb699d3f64b167c2413f5f2730f595ae70f5ea33cb3e83ac97efe5c79e3229e29eb3ad9c111f91de4f4619ccb19213dd4fce36efd4f6c66a3c2616cbb90094cfa705fc96c4b458990ed1aba8af4578368386235899a98dc4d8c2954ea2d497c03f0e1b714c6d842c5643a49e39b1cae22133f6c4e89a38f679b313cef8627fb3c2999b3239ba07c7c3611d9c532f63271cd876c48cf0df6685480d570a5f978f5297d3485dbe2cecd3bab699e6d5db777e46a16cb612eac8fcc1046c422caca3a28553e26ca349cb52ba23b89527cc288f4e06e0231657887a1734a8f430ff9a126d4bc670fc6a1d4325d3222bff9cf029ba18a82db76b42e7b558e8460f5c1c437d2a1a9d287831901a3657e372ed681df847ad4840b47e2f98b23b6ca1a08f48cc0cd2634dd6caf5200c7b4bdf67de499289a96f0108b3293a5f97c394a597a1d59c793a5641f6929fd633b42b201cc1f29a877bb2479c483bb642a55d4a7ca6471338e976b32f1e8bf01001e85835146792c97349c93342c23e0d20aad0a038ded2015b1c2e264dbfd3b5300c9ef2915d87e1caa91b44150e3050439c3d2a19d4242f3db722f7af3a246945c93b4250a5c1d2aaf7a7d5805cd43e873e2a7371735c81fdbf481291e92b3e05d0aa7cbfca57690b35322fd17eb54c58afcab81b411c08d5ad057cd8350d3fe5ee1665f50df4e94073d273e369784d1734359f65be9829bf48d8f9dd9ffcaeb93f8e0833966922158ad741e52c13bf6b202e8db773f13511565fdffcbd9d97f016f87d8b623d0b47a1577f7f16291cf5993b20063d9957277411361a8bcd1d86e20930b1069bfe21016be478f0033e8e04a60ee4cb22e800f049ed078b0406d9d2aa1bbb1d075a556275d61f29c18b93cd98da9e6bf74276c96f8249072c55fbfb6e3af297493a8e36d0226a456e40b6acee6761c0d1eda24c73857dcb5d6dd09b39abf76e12c9414cb5f9bbcd9db12bce75128fd04411c462c801349075c5647339eb1ab30b5bfc3ae3595b3a3af97565d3c717cd7134550ac043016eeafdbc38885f7e2456b7df942bfe65c5d1b7aaecfd8ed19a1046c9e9ecf5cbe50fa74543b3508707b8a55f727f0847e6be9e27823f9b7103767e8e0720ebf67840fce2560008b80c6cd696962994ac076330de23052a75511efe1bf339b33474b93d492f3c94b59de27d438617653fc6d41829e70808aad7a32439019febe8f077191e38b31785f6fabc3e999e97028e0105a6b6f91337034c1df47f14f9c932ef0178d72c3e009556cf7c3d901c0a6ff67023972373718418e07330bcb7870fcc3c96d355795f8ee799a7607ce96ea7aaa3bce9321fccd1d0231ab259a8a9fdcb9072e86e29d6fe0c24d09f7b43d6543f87e4b2d9389d60075b0575ec30d9b5a13a3c78ed0666928439669b01f75a4a1bf7c116a75f8a266ba63139cd72e8d03bffb09ba44129f02ffdb38bb3e9a65d446b0ee6acf3e90d1d613f91d8fde09a7137eef7ead14a6c5887327c603f45c6b47d5dc50966efd7cb1825d8b3c96f46bc9bb8d907aaf9078798b44f5bc35c785da84e389c2afa262429e9b142582ec97038964ccf0268472e526e168179971479c110bd975bc64ccf126ad0c801ba9d6c1f79fb42693ae8103900bb048d188d53cb020037b813e4f13002355a98ff3e7b10b38496dd6268ed6121ab138d62e03e7a1707d5f9643b0fdb6066b4e090b01a95cd9365dfe55c9f77a55983be74a42fec61b7d21aced0e13f31cfa60244015ef5a4d371564056965843b0ef721cc06b0937269bfa5dddfd7738cdc7c7ca422716bdc12b08775668d13c52d1e4c193991e5f7b923fdd0f8ae8e04fe0a7a0ab5de7a0a2e5043148c6451c75c045b2bb5d88a628c42b6f2b8397eb81c8e486af0119d36eee1cc836466741b04de22e42e91c1c79b144f540c3aae95614751c99ac89cd66fb8dd224341af4a237eb34733ea8a087898069f832950d14817ce2019b1381dcf23c0cad45844b4f7be3438796deb015c5878eed36536f69542705263bef8dd9e02559b6ad65db1a1cffe154fc62b22792698aa39b7d4f62abe14d220fc19b7fc4cee3699aa1e101d93a49d3b4d8e7e4dc56cc91fab8e032dca73a09a616613b56215edb1b1a909f4f490c6a60467754366f97bd3722f3caa85d8349f2c8fc71730a3e6682a8ea46e3c33bc32532801f2cc9d18eb0ac41192eb22e47178e33ff75d7db3377f4adbc0cdd82f0100470f5daff73b04786e28b813328d5ab132344b4d003ee5df49828c7f6b88fd2f867851e4a3d4689690393a4882e785e6e562c8f5df0a3ccf52dd76c4d4f6257fb60092a4afad1231cc292e8f084abc90f725eb168e5019fa2a3f0fa20ef383a2d8b9741f081493792529fb6c38d63e4224ed4a3ca65e320bc5c18c44d14c1c404db275fbc55d95084bd8b67808c9901702cd2d3bc23540a2b311b0353d97716a10d9d085879270ca8fc359bb043a2c7831160c35dc09f56a656c8a2525f001b4ca9c759bc02d7f2b39956b2bef296cbfdd9ecc5bd94f47785725cfef1dfdb1c29b41a55d931c21f75997d35c297900dbcbe70fd2cd6f0f62f86cb666d76c4b55c4a418b9b6476a8e134841ee171179a9a19e59ab78b6eaae0ae89a9fa7c8c9dd5e87147f0cfbc51e88af4af929983b3c75f09ae282538f2f211b36eb571c98bd1345c7c28cd602bc2636d54226199ad599509bbba6a572c4bf2f57224a858f55a9215d3ef1bcb5fe25eed5d60d3cefd9153cdf7bde0e82e4cb01568bd9e0c00505c3161f9353aba75d97c3b7b2fc0ec251cbae66867664dc830fac61dc0e0734235e51783443842bb825fe1d61a795af92cc96b13dd2e2e9e9c20c7203b3ab3d4b8899b2290c5c561e017054dd88d5bf0157cce862f98bd4643783854d51be06c4cd4347c5da2c45f6d16f347bcfbff4a4fd674ccd5626c0c0b04d0ead4cabb43507077d7192207e7844758eca5f3ceb8b82d4ec07d30fa66ebe47c0d56ec1d1717b2fe6a7e7b95dd7ac36eb9097c0cd8631116da273b688b21f41fefd29f613953b453311ea97fced2c915f68ef182f4868cb16d2b8b0d566e49d41f941db6c5176a752a5635f70b8a608d2399d393954f93df632f4f9f03b68bed75cf972b3721686d04651f3f0116053fe08b880516fb129e9f79c209833251a401c7faab62758809564c0401027839add4f4447c31a934459904db885bec3c2c76d11ebd43a7245f7d979cde08b69577048bb5ca005184f14c1020a2804e2881015a30b08a9f5dd9572789abc9474545cdee87ba7951725bfa957c31f758a62769b7691ba9936020b7892fb112f453f0e4f50bf7f9180d24c317c726f5c32932176a499752fb5771774cd383849f8262c049e551d4324847eb68878be0accd87edd2afaff8743e4389c89db83f6320ca5b21155ed13c4e6d25828a20553199040e75b874de287414ece8c02ee7cbc7c5e54c3b46d66ee501a4b401ca0905395d408c519b0e8a205e38af5c17d68a17f6bb355aaad015f04ccdc19ce03bc4e11e7015705d4a37404795b8826461d300f8678233c84fed5b9a0e70c0588114fbbb4c623b2a31af02c8dd87e26a1b1902df0b14a18e64b73529654a524a19eb039d0328033c600da1a0a307ab8d53d49420ac1b8268d951a9c192a34241acc834c384648dcc18f960adb539f05e1fe4d0cb12d011e5c4eaa90a8f1254979d08542b84d9aa91c5a8698525b2058403135f950d4c587ea040162e476cc00295b59503017c8874c2097f2ea58880bd176234a71e3634b47489d206033acad4e881ca19a62c5158388acb859c9ce7b33bb7d6dadccea241626709b6a89cb1633123c9069c0e94d020eb2011910a56497a54f899c009905ca192eaa282561b210e82cf8e0b07873012cb07452d92d185b2ab376cac97df18decb8509b4ab327c6ace30e94961fd6068f570e64a8b8fcf2e864944c86e16257956e087f7d21a3fff327578f2f58632c1bcf0dc9a426806e511a164eba525c4745273347237ae5e61700ea7cb231401cb01801aa2260e3d0c96789ad24c2e61915251531154a6b904b21d8054374c21436fac7123bb1c22dec78f0670068959e4952500b3c9bdf776fdf3b8f7aa2952c5a2302526186bad4db2f6286beaec1028da63b646490f26c861c90a2b03266bcc70656101071e416e93cc0caffebcb7cb13c9a6f7e3ffbfcd111c367257b5dd2200deae8c18cbf55736fe47a5f48429d325c5c98a09571215ad204e5b9c87e640604bf06462e1377780cab38b002a04b2b0d2fc08e9116255250743d6128f141ecef070a5b05efe23bc4b6c684591aa31f81ee60670a2390f332505390c095ad343ef5e19916543072818a640f9a2e4304819a9408494102c87d7782f24c0a163071532415236f03285ca490f3c62bcb88f0138a9aaf227854b95b560e8eeffffdf92b05162fe3e60b275effdc9eebdf782f44ae85e25b938eebd37cb2cffc5c94ca25597a629a92524a8a1ca951380bc9063d32385cbc783b03460920ba706504d35784d807c59238124453f45607e80f2d1c4cbbede23440f0d275662b0e2ebf1e3c2e40a0e68aeca6479f282ff6437e14ec4eb7d3f52383f101c08e999485381cbdeee6564f260f7de7b350f5c4567800cf14133c34e8c160f21565a4c6451269c07d5d51c69010bf7de9bab3912efa07e9cd47b435a43a946d38dbd9103e84ad4161a32e820b343325a12c60894a22940840ee03baacc5b93d820c93fadae6691ae2808d680a317688fd4ff3f14100e18880a722f460407890756c10f7884e80945a68a7e7234d07019a3e45463cb162740565ca81cbe0b1ca85efdffffff236007dbe4baf75e211dcd91424138530f9a088153e8def0056373af8309b5aa6653ae2c9997d20cb3890a0910887651a60be50bd0ab53904cd9f9a48bc2c3feeb3093161c973d2589f9c1c29a3339a0352b44598145e920db75ed6ea8b2a4644483ebd8e0e8694696225351b0542c3d8039c150960e304b557c9e43e827fbff7f90cd64baf7de7b3ff3b93e4bff7fedb66b2fae4969b3bead0828bdb6eec8366ddaccf05a71440bfd220a753bf50174daf6706729f59882adba766cfb0ba4e47982b3903109606a9bd55fd034d072a4c5041a6f09a4a9a831de96ff5dbf30bd228ddaaab619e57982efb7628cdf2981c26f975555c93728ab39535b9550a01e53847a4cc078623b09991e67db6b8eab085f7a7405603de21b3dd6eddaf5941d90300df042f6f60d487e4028666aab9a84ab6b2e4b9eac5e7d238e748fd20b8e8923ce395767aeda4e8c26a44b8902535bcd0fb07be6248aaa5fb50c6c80daaa154b38e1439e5a45bdb513e61e6595f842f6b66b1fd102b7a9c6ed9b696fa04155306c45c34ae9dedfbdd7ef5da2d65ac942aba7e58b6951e178121959be78f945916187930bdc30e3888da62527132019724477f49aae4ce065079a22412d4c09f3442a089519178e3c09fa32e4d55a6b6d0fa61ebcbc46aee05599786a33a60368764678d63851218a48d5db19698a72438d23fdff67650de5185680c8f4c02a23464d56578c042e63ae5c18e25b410537c2429d3c3d2a73fc9b52bf8f4ea3c15c929249d92591bd2530314e15e4f7de9bab39f2de7b63cfa493533a6bdb1879ba8002f5663f9e484961e0c4c3a49a4d14ca15ce6ba88b88872847a4230a221222da610140a705a635c7308de9faffffa71131117165fecb6a425522f960373fbe93611374b500ca784025be7f3032e9c198ad1f75ab1f38dc1d61b02331bb485e0f1629179058e9f1b510e573830811b8b4acf87e4192fc1cfdbfce7d9a58f840597baf452202a5c4347a187233e96a0485a12775d7c8ce02aaab415f85d8fc50fdf4183965d9a1378306d696aede0e183030a25d3f6c1753acbe0e97e5c3edd9ac57f253d273a2b404232652140d7269c17b9f5a7d911e2594442a25e60e3fd5f57f6d95ba7fcbf5faf11bbfff7f5ecd9118dc41873435e87260ac2e8e1d429c40c1150f128cc112e5e3bbff7048a727afe6acb5266270e10a0be1c17526c606dd0d8faeb5d65aa42aa42ba4ad2e9edcaf38a2fbc7f7de7b1d8bd644694ea1e0bd5ef8d629494c2094b02c6024840b11263d348ce9f2abb26404c74f942f2ec3ccc807abf7dedb7b0f7ad9efbd61133a15c25318326c928e0cb1e9e04a19ae2d696ee07066c5c53931385e4466fa5485e12ec7f3586badb559319e50b53af86662b207435bb0295914fd7fb863337739803b9d05a08e74e1d2b5e48a56d32f8635638238a541d202e144bd3aeb3520033a43831f5050a6c9488fa5200dfc7035b504074f39e7b1eaa8199f30d3ad6df558654a68341c666aa60a6905a766787cb227791477b36dd70f7b491d59268eb8db2d268e36d7a1dbb74d30e9d85f94f5c260f1d220cc7d3548633b0ed83017c17e3d5ff40a8c406dd5c50658f2d4321443830f97bed8b434e09a74c1964cab1e7dfbf42df14080fda223b1d3e768807ed3b76b920ee3d80defb5ed7b6fb494316c8f99b6d96e371c0e880a60e2a85d549d9928d270448ca58e02ee4b8f1a5b99d5ddd02bf10d2b0f90868f5ef19283d7af0f6cafb1166e5bfc764b634a0e5ecff0c08760fb4f496fa44431dffeb5f7be9e6fdf84706bea7f599d5fb3a2045f7bad9602489e5aee4aa7ef6caae719a15b439c82936d7596b247da7e2d5d3200ebbff7e268981e31a8c74c8be951db6eb812aa0e8e987138d9ed7663b3c5b40e693450ac9252c5b63b0ed856632951e0e9af9a9436d71e0321856ddda902c6e9ef6308b6e3305fd9bb01c2940297bded224ee1d227c3b3f7c6c2cd8a4afe74cc8ff7b79215eb9a53350fabf32e67e998cee9d3b530c4385f8cb338871987c3d196d0709869be3a65e2a7e5bff746be57aba0ffaff7fbbdf36b13ae49dbfdb6b09b76c99456a4ed75687b0542eb0e5a6f50ea03d5a9bc4abbc4dab5ab1e5fd4a4a4ca0bc51183e29869af6ab3edb1f26eb7dab5c7dc25625bb1e63288a1ded855bfd7249a444907ae49b069895c8deb8b55579d98be3ad764b59b9aac39af1b886bb8268332c6612d5f5d41517cfdf2c0be795fed25bcb635b9edbde28b5b88232d47b686b78c9970db2ede5ed47f788e6d2f66b9ec943f4bc72f6608f06145cc6c7bb5f1afff7d66f5ab8635c63a2fed235ebb7ed546bc7e692cd26a4ed5339ebffb8e03dcb76f019dea504debdc533bd52ea60092a996bbeaa947ec7060c48e8f1c90d4a6695524a182ce1e98433abd66f5acc190316d2d8bb4fbd22e8e99da68aec7bc67b4574dc6111f5d63cd01bf1f8ae0daba96bbbaeb162e5ad1a9ed451913402fc682ea1adbc13acf689386db358ded482d475a8e9e4a152841290210d0fd1a1c61bb96246cd7b202fb61c8184f6c0b636eaa2d95188fda828db3fda58373c7559cbf44893de240f86dc52c51548d018f698204530ac298c0012108d33731f15e18f529fc8281e108b89f308f10fec01fecf7fae1dffdd19668341c66772ca06bed557bd5b48a31e8f6aa46ce39e7e7fc185f7bedd33ca385be85c2070a1fded37249a1a8efe90bb98f2069cf1128ede9e3ef780a457b54076b1769d4e783563d12fd5d9b2ca9e40935deaddfd5f177bffbddd474e86ec1826041b0a05dc7dff9aacf8d20df769eb5c183439ce9e3170c74710bb38d768446c361f61b8f9aecb65b02a84e2c86058ac168f896801876f2a8f8600b4c93436aab2158bbb9c85666f796ad826dfb61f665b1b5369dccb1b097c5186f6bdfb65df47a02b73effff61e8e897f8fd02a0493a762a50e27e563df55bd1eaaaa96bea5574a901c89caa471cc3870c405e7d03f0e5fd1da3e04478ffb8090e330ee1ae2ff8929d8eb029186f061814d8d4cd440b13c69360a4f8c07821741377b37d187391625b6db56317315fe8037d36dbed769fa4c0c9411149b1c1e94df08bc4b63ac8eba6c44998a0a26388840f0c48679452ea4e5f5f7d4559f32c2793edd136ab61524a84c32de936a94ae2d13eedaa6dd2119b645b3dda2712fb33189a36690af976d826855b56a86c8966eb9c502fa9f69a446b23dd54c64e06d29e14860c1aa482ca1a8c1a065dccdae76f28cc745b7156058097a71e6795e4c0dddf7f25b822faadc1f98a34d75507d4ae6d27a84e882bd2af6c7506684ecd738ae30b1c7d3da7760f61cf08ece9b24a05bdb7468bbd5802b5551de6c8aea71e65d54ede4e25d7b4cc71db08785bad42c232b63fdf5ac7985a5e5dc006dbe66c5bdbd6826d71b67d6dab2d9108ed8b893a1435288e1a268eb65908eda228e2a4cdb42c3eedab1fcaf6508416f269bb7ed1ab9f5eecf4695b4d633bb22a282a98209fb62ea47649951ce50f5632e0af8a64d78e65981f767d712651542dc391e709bfc77cf5ca926186ab595577415e5b6ddf7738066548f1756b4111f6d25fc2b6faf5bedaedc57eafb59a6a2ba2f07b67f9a463fd35ab69f55fe35a047bdd44d7606dae88d56a39fb75ae1b889037ae61a0e6728235b94262f1e2400c51d18171db454c7fc796d5f48543b01adb5ab63604cf3d5a4ff79c380eb3dbb6dc0550e2aaa6fa45a9dd7dce266e797048cd70c1019182a8048f37d596191904800023170000180804038241d190222749e93e1400093daa90b87c5038228f86e280300c0603c280601884410080410008831880a438c693ad01328aaf397620091664207f82c8ffb94c94ca28f2a22186b8faccc921abb45221e07f36c2b4ae35d6075e817f7cd1d7d5ed3462c30e02f432630371434ed80f71e138ad96722dc99a042cde33cfb032b8df92f685ea1dd8e62dc586836f38f0019b9bcd32db88e44f0e274d264f0d21baa0465e136f67efcb5b2a3a585f3c936e80d5fce88afb44f630c9e488b16f56ac8d6a7037952b640bbea520cb2d677917217ab1f4466f6fc1afbb66719be1519965bbf7aa6fdc1ee0660d8c2c632f97ebcd738946b4fc2bdacd00af9d069c1b36467cb8cc7b563768065360989ce863c19b78899c4cce121cbdf9c4c2f201ed318f087f59d4a61b795d1d1d98a5bccfd4f5d45d04d27dc75a8eb9f7e7ac433184f1a9405d29e22671a93d954c47ee3d7487c12561fa74c0c3b183b408f8db10cd64c56ad8d12ac0ffa52a30064f2bee7185992c4d6645f1f96b048d49f25bd79f47093bbc8932f0bd4ff42955c78e25d5e8ecec10187c5fe22f9f93810eb97201aa55732db3595ecfc6f5c530a0707c1a3fdf7c029c7509fabc611e09f721eb827ecf13102b362fd64985c89ffe03253bd4a8c3064d8c68c81748cf6bcbf3de041d29f779c7f39d35caf1fddd0bdcf625d77f1346f3541a4801d6cb098d212fc7af044b0cd7dfe6bf29f14226299654e33380e9da40743f09aeee05a31f884fb260e0c1703a4cb95db670a050997290410927a38b372aac51b29d2df8ea94daaf3429e68c5b99f496ca53baa8760dce0fb643abf0e80855765b850f43ba013fecc220939941594c7221cd500066b7f5811153f634c79e89a4a73d158da084072923c93eaf0dfe1b0508f90a6d65f10d7232dae76b90f6d3dd288c148863470f32a4810c255908d57669b4014efe425e08b03995304449fcacaacd1ebf3ce9f1635d4dd9035841a5450718d61dc0dee679baf7b18eec316b0944aee2c40c72a59b1e276098225f5fd13bfa26676bfd6df65536e7ddfe83f212a8c8e1b3fc1ea2afe5f4f79daa680e6b30a4401d1ce92300f12e2789e0e7869069633beb3aa9381300ad6f5df8faae2eed5e0256f53d138d67f156a4aa29d1d201fac7db55e5c61e8aae11048034e184f8bf174d3f4c72978969b47175bb9a32484a6a68f6f386041636ac748094e56be01077ff23008e62cf1095e22f52c5cf23f5c63811fc2460863128ce05a1bf80a11d9991fd0428b96d878f1cfbcae64e2eeb770b38033b7c5a57c3e61fb8024798589afb5342f8e1fc235e2b7f9608aef26e53eefc49823ef02690348ca1086f9e2fd48a34f2cce1d866d919b698d801c7fc180915d6eba48d1c623b8251c4951de9c198d4a4fe56dbe0526205427f384fdf44e430f6aa09afa84210a75771a59b7fbf398248240ca5af1c22f6f82fe391f1373dcf50d07fb84540480ea8b8dbf0508814fce04244a9726e6f5664d1132edd91c6272c22e5fe06249ac4746a7c1759a0b7afbadcd1fdd7fb2edb439e30ba1f3dfa80e38f6302e0f3fc4a284e37d9e663d1b28725cad04f9130b144f1563c9498a89b9c2ea81c088295d87199954a988b1dc718228b1cf5044c08428e09abe2d9a5fa9d48be79fa871c430052b268b41383f6c4a31edf76ce800aebb03635ab1c553ad6e35e05cba81a783ad25785a194a733182cd70b76aea02349e3a44e6d9a8ca03da5c80ee8b93bfabf45945d8bbf178461f5ed29644cbe16e1fbbd1da45a509e43992cb14c3cb6208db1059f657bc92c64b0762cc081b5912136885d1f7cf0eca27fb19498f6c7cb9eeab7f0a2f0f99c3c9b96afa3875202f7b7186e443592104dc565c52cba5a0a46f5678ade27f7df7e3608a2051b11f84db4fc74ea16d5228860fe7e63e0f78a06722b004e396441957ce8c41d71479347a710715018002e6c3e52cb15851666b40ec8d663e96ebd02995d54160aea95b415c9751c5e9a381ad742f5014e0037702404fc936a723aa8afe2f8901eaa085c147c8604ad090a228ee88f8ca5ba584ee9418766218dc0dc08e1ca08c285810074e0b528a3eda68820b94e4c3fdfae325973ba9d35890e39a734784399e2acf562822a37918cdd15bbbccccd229d53c22df6cb89597901e7ad88f9d89014dc12cddd35c2364675cf36a0376cba1a19f7f3d451a5a7cc1d9b19d059117f930ae6bed8168ac35d4dcc82c990d882a13ecec1ea30813310fda9f896d00c796827c8f6a8abbce87ad27abbef8415b035cd2d4dafdb47fa28661237ea13133512ab5528158143f2c98d192221fa797a1057c56ae27630585cebb9879c45efd051dc2226798619c0fb5183865ea14ab6b14493ae99c047be64380d4aa93b8d937edd347b49f35a52b29d792bd03aba71acde3f72d8aae259e6ad6802b9c652d488470afe027349fba9c8501b7d145ae0c8060c49a27f6f1e8e469813c9114a05dd5ef2b0f5e819a13bdf7b55cbd09df6de38d44d6b0e65deb1a4a0e4896370c3984bb294948e4c759343cd6721b059239ea8db752511495f6afef090cc6808b968af86e52f32592764e1ece95bef78a2901c2f8087f602a935e51deff865400af364b63ddb96c413cea3a1b0aed04199fe019b95770c407d546a19b37a77f9f892990abb6305a248631dc2aca362f2c1ab7da6090d4ad92eeaedc4fa2efdfa78f1d6f0714c3d7c6a3093758ab9eb66ec764f325993e0f9ac1272935f17fb0596f077b8495a9b69ef61ff877c9218321caae66e370ba96ea88c5bb1d37f41adae41172d190c8d43d743d0a06bac476aa64e89181ab9273d8bdcd7a29b963634e92ddfac13d2f53760f3939b8b70508dadd85b91c2fec4649e471afb7cd8b3231c98794985d6c0c56549b05d31be1111757d4fa778c7e65111720a3ef8f8fa1f6b94c0a62881977f86468a170233d7ed64229276ac57943301c9a89400a791b6a7b1a47e62339f52fc5ef4e7392c50e96af9f2ce54e2e08c7f73386b79cdbcdd41580a797a7221ea46bc3dc6f4c88ab94201d5e363141db5c57882ba095abdf86cfced2218300ad66af020034859221532c665c96a3a1e318e1b491af6a6d15ab43ea92311d3df857b614537553f9c38cbc517122f5945cca1b09816b72012e84489c8267f5347f5c9d25f9e93efbc0e1287f41be474497fac89341c26037655dec10bfd020e7b3d992c91c83a9828ab9c4139f8d4d23db3d44a4b669e3cc1e4c2347ed9c9834aca89f30f07dee019e5049a3bb80fb89746475f10076810ab7c914222a1fa1fc7ecd2c51fa224d8a7e922c4e0857f1f75dc553851ea8fd52912df3b5f853646320ec46907143d320f19b0693f0a24878f515c4f6db0064a5307d908154a97165af06dbb33739f060084f8070611628aaefacc11326cd62040c0311e2132c3cfc43f9888ea5321e01f62f36153afa6424558b831f824aef414b2338baca78c25ba12775ca0258092f7d4ac5e8d7046f98c7fcf8ca6e9dd6339ca97329ce13b8f0c57c54f913149392c07a6fca8a68dedf3275c601ff373f58ef970894cd718731b15cf7695380e2dcc6601d53b8d00fc166620e344efa1aee634efb72b85be6577a2d02745f58170ceeb96bc849647fae47f1bc71bbddc9c6e7432c0c40e24515d943d5a49519d13c879db8a9aa03b2760555830dffdefc5c09e859d9f77fb9a94003ab16fe52b10eb0b68b794279fe6178578489445d71b45fbc4143cc0466e9ba64e906d51cb0534a460f599a043b20986e5d6013355c6f96803510a41b7b23909befc076b68f9717a0e62d1fba28fae413fb963ebc7acf0bb208476d5b2a20ab671e7d14055f73b92da8bc0ff8c1dd2403a7bc17eae46381116b91aacdda11b7b457d4a5d5478337d4c42292642b0f3b60e7fff3c63375784b1b01102876831d9ef60e790baa1ed0428f35983aa4013507302d9918cbed8eec48c6de212e0ea621190385e0616529639548508b4d557753f8b8360f84e46b887f3e9cf9dc79126a4da56db92b521647ce8a5ef2ad93c2c56bd850a18bb1a4bed1e37c2ce4a7350facec3fb3f42dfbd9bcba98a3016de14fe91f8adae815d20b2d3335527e33ccb461d2f5fd269ed883a07760e0c55a97737aaecbf9a80ad7011768fc2bf9a94b9f5fe1eff408e0288463c22a71f5ebf7486b927d392fb14ef2b6d5cb3c48e78070199e4b5eb79bab1791090d7139884155624a5a1f51314b38e3813eb4a230c0382f0aa583dc720705b7b670b4f0038241c509cf94e46254041deb893f890947414600209902fa500b02c1fa82f4a37e471f17cc1def5d60897f4ae7f7b72c4a5de99ba90f6febab6bdeabf1389586144a85a515fcc1e8d4994d59457c6fba34beb541515b1f30f129fcab0ba482b2942a864c5fb101432851099b6072bb88370bd1bda82007214b4c04da8a2408ff33bfa49ae8ffeaadffb6261ddde4303ca44015745a819e2abefac1670e771d607bc0443449ba0603846df818e6e8e4e2621139344ae6950f78f674a0dc51e51ce70ebef4511045ebe0e08818b1cf0f2ed0f4af8c4bc468046ccc440e12843f2cce110ac9f39d6210dbe4367f91217a3f5ab4b29af76bdd114c558dc1cf807ddf70552f17b1458ea929f30aa187c21a6c7991bd0f01e316b03841f800980393197e090b6b966ca3bba3d06d6d6a8164f7a0fb739db04ddbaf3aae9060b445b9f1c108da25448872a6d5d31ea5bb424b0ae9f1a4247d5b93892b1d48740e55d87499c52092a5a13bc3ceb0697b319524a371b795763744be76b6694e075c96120a11b6028d0a068b41d2ac5429da64e47df90f5decac5e0c2d73ceb0986d5a30639e7e8fecc50acbaec856bbdf78156c1c728a82eb89a02b59e8617d1d3ddad0aa91e2fd0a2bdf0f69c6e8b66231a0a7e94174d17c90fe586a1b83b09cbb4fc7410a1c4a559dfede27279f37c8cf9b62182997069b3a030b2c6751e28bfa11d205866ccf9431bd3e893f5d13568f8f91d7447e94032e545db9a8df5f8b6c5bac85948eb4e84acd148f59c58b706fc6d9ea0b25368853eefdb242a81456e813ef93cf6ac76aed1a1193aeefb22823f4f67e82a14c7ceee637152cb30614bb9a36f52226f9033ce608b8d21a800c55926a29d8559ce59d3868f53f9827a01160a30a12fb7947ad05900741251366d18dd31bdd7e0370eca3f65e7c281292701a9ea1cbfa2aa593c6ca9c2795e0eb1146e7fed9535c52545280d2f349700efcf9f9480626ff9df067eef44ca44e28a9bb4435255fbb0678fe9fc1e80edd8ce83fd16446139469f60eb30c4966414cd1c954fddb228f724c1ab993ebccf00422f51f3cf383bd35fe5f3c0324d46b3766a94bde369c0c27c6227662fba5a84511528ff210e0886211dfe777f13a572c24414296978f893144e99c709425dbde890023865f78c02d9683e31526b6efb8b6268a0bd5d3ff042fba895cccf2b4297c32fe725dde910dd9ce4c40e8c78d47b957cb01f2097bc8e3432cf77e62c5f90864c1cb20ba7462d71392f751a9b651c21b3a38d33952236baf851ba88f16707d01a65eb50c6331e6f725194f3170b849eb67c70ae0246be27898362f9bd75bb7aa836fe2d2207a811e83d525be6bb04297644e18b383988e57bd06671d4c887a4a417e611a07204f67be7d7e221408001e2fdbbd802481b3509672c8e1735627694257f342424f833f822cab30d5d0ed2d600812921ab460ad107c57c1d5170053d27121f62423e5451171fb06bb14028e939f5cb8238b2fb03fb5a90f33c7dd406c309c95a450f3a8886df73ed49d2c8e4bc9598a2390054a2830fd4fbede8b9c6493b2ea082a81d41d2b41c96b25504d4a381813ebb623ccebd1041fb34b3799a34348f9696e65e26fc7265f0020ff15990c1f4936b5df656b4d1eb8c82dd111f9347c734c284c68a5f1816e1281ae6142ab2a0433cdd477bdff121181c11d4a902aad3624ed435ba805c98b8ce62f244a5f18f4cd8e39302759aae7f5084621f998a4f3b0323203d01b8b83811341b659e7046f40b496d077b61403a639ae8345f5c2b563d691a150fa3b8372a7afe658cc9ef8fe76a1ee1faaa65b350324606fb939e83be898cd22c2dd9f182d5c83a5023f763f94aa429b0185c535af19b06be46dc8ba93a7a0ffbac931768ce7273ca014b95266c643b42fa81ef81936990549d0b1280d243f95b570570e5105067f18f7c5761351b05f1b45288e7c807e10436a680fe665da6cc9d7c9255a327f0ca2fad39b36fbe7843d1f2d80f3a71543ddfe27dfa1291f6edd60746e18112df0e1ac1260c5da93b9ed2cfc67a47b5f17fe18e0adc8a62880906165d082e0639fec5ff69cf6b8a89eb11371852ff3cde3984acc9f0ff0ded7a281df6dc5dc73f0075c24cad4852ce8b7c44b99e4cc537a2f23589bd2b3653d105214ec010903d60e1f5df8e488e150f036157c58dc7510d6c5ddbafcd65a4741db1283e5c718e3144ff44789c8ec06a6ee293d2c88bfd6cff393cd1a105e40e8e495a0d7d6a8e561b3cd99173958833acc1b626797f81bbd83aa02e3aa19fe313e9bdf534d8c256feb02a3c80c3ce7477bcab7d5059d0cf283c703efb50f171d6a2c0f73b2e1ab0e18dcf694bffa52689e1706e8973852a165ed73cb4427f43cd76c5145287be94df3a2c08fdab864889064f42d6aea1f09d44adff70aab232418839415dca01d18eabfd7a3f108877b9e7bb02973b5991ef3a77410fa86a395289afeedc82ea779453747b5316f2d484f1a4e0200b03e2aa925b5fbf36fafb8db8b9375e1a5b863c3fe7f1109aea1022806d55e5455b041c69b1e5004940fdbbd57f6440ddebe8ecc3060a67f07e8e0f1da83979abe9810e6db6c980785e2a2b480abee610eb3a6610577dde4c5aff87f99953a99a6099fe584c2eb05cca058d42734eb4a0ef4f9e47a5c58179f1c3ce1342550f381941ad50ac12b8dd57ed4d3301c94f2fe085cf9ca03c903fe6515142134dea6740a74d788ee0e0322c86ae99780f55c3e430ad637210f0ec3c045dc5f5121b758cc8344620eb70c7e14d718c1c9032b9ab0a746b424ab814422a64b21c3556b5b8f5e98eae6a482b100d9e9b15b00e22c084a1a07bebb71ec2e3aa80ed8827b54f9d84d1fff19d0a38fb7cb8e892db4f78ff7344074755dd282b0c3433fa93014265f6c86c87215e6e574f717f92eaf513de41a1cf34991defa724c813df3c37a92235872cef766d7d19f30ef901d580b04e63175102ccc105d33fe434345436879eb2a67098cca443209875294482444062672d78ba5c8dbc515f400648ddcc7174eb36115b5fac25d91c1d1c530b163deafc5e8e80b6ef5d4bdb9f2f5132897b3a7f3829d339dd8dd7765d3a61a762486840648e530d893117e3e5afb721220b3007d6966b7c8d5966072bd2a2715e00f39052f41c9d48eb176766ea7fa52883b7d25507a65ab652d763624857916afdc6980acfedbe6ea8bb8c3537b8b87bd966f454659bb33ee31c221742e1eea303d281127693380c08ea0cd422e0613d634f881c83fdf025def8b6bc7d584305d0771c81d919ac971518aa59fec9799966f56a0832161988c67094f481f9f954b5f5e345f29c967520bdaeac58c9530280415c7ead61f2546d696d0af67a7e20c4e3371ad15de84743d7749e65010861ec3155b45bb770df901591c56bed4862dbe5d76ff4a08efabd4e1069b63ccf4f54f549586d86313cbbe1baf95bb2f35dec7dac356d5246fe4261e49f48291195b13d124c751b0c637d8a4923d5c9c0aa231c186e8a8c39a66881059a439dc1978698e53495dcf923f7b7b75ffd0efcb32dfa4780bc3e7720fb4cd0a3beedb1a3f120f5c5f8bdd7ca5377b7dc44db7dc3dd9a411917dccb976aa3b92f6dcc288f38a0fb02a20dd9eeef3b483b97ef0bc8d25597fbafc64d744a569a634db9b81dc081bb535862e80201cc4c1e5cb7555e91f71843fb83428311140cb87461531dc6bfeb3609a34a1236a9620c5414c398caf28475aa1d57c78d3684dd8105ebd9ac96f805ee403b3f26c4ba94a6f01f67a275ccd8ae4898ea2cccabe69a0ae5e495a10804dde43d8630e1342f5c38dd54b8d61059f9a7b6eefc77224e050db996eb53dfda6505fa383b09c9e7493861801aac120cabfe91042b053bf149ceaf37d853b6e58f5b38531aef3e7fc045cf78bc8d5d4f14d1243d37d78738bce0db85618b6c8a6a96dd4800752dc8abb6231202307821af9260036071c764e46d05faf59049224ccef2e20d4250a8b48f347bd2067298f8b8202075d80b37c6fb061fd1bf95caa60d7a53ccc4f9cdb445996cecb01f6e871a1bb138a3a2c386dce9e093adcada350562ccde0f31d5ac40fb541eda1f605e63efa97683650cb65a86ec6f32cb347ba5bf957605dedf0adc6882dc8ecbd158ba4e5541f39e9a49e1ca3c445f08ad9d9e35b9039f7c0714786f3fd0df24c8c221b470cb1d08a395aebc45c1de45e5b293fa7404eccc40ea11b193d692e5bb20ecbd6635d37a461056eaf71bc4c1f4c643d4ad5622509d5b39bf389d8d083d868ecfaa70f26c507a4fae027ebc48432fb0550f0b92a1d189bc6ada460033c66b07caa80d54e34cdd5d34d93a7e7e59c81088beb22378deeed8bb3299b3ff6a1dbb4ce8d3b6799e404f1abb791c0075da5c109a306edbe6c712b48c18a95db7fca39404e38ee4b2d7bcae4d400f88c4ac1eba96aa8796fd6cf22df08491d042711a032b65790298050a42881067d453407bcdff4810edcffef83c83268bdc9a72cda4f46f0b110e20d71f07f06ef64f1168ac700c278f9310b405054f7689e58d74a9dd32d274b4cb0565f2bd6bb27164d11fd9a451003865705ed2273034eaf8d85850728275ff92de70654baa0f30a4945180d26442aca004527b2ff7d86feb0c604ac816996364c454da6467debffe2cf417bdc68b8f8372972df4882e131a5a3b3fd115321af3e28e906053a655f8728f3d49d86c43d0fd1ad74e576dddecaa11d214881f5763a1e66a4e390006606b1bf7f983ec529d67e96356ac56a52cd57794638c711b1cbce65d2e9a151a1599a67e6e03ab0400fd2ff24021ae5a015fb89e70bf92229ddba87043784b53e229cf88b897e8c8cf01c5c56f6d71ccc9135f074dd035349a1ccc51b87d4eaa6cdc6a302336b0b7556bd44df6fbac509b371495f4fb671fdfe29925aacb62243619b45e4c58535949642592261dd8c3552f44d6c5f39f4b8ce03c83b72e90614cced29b0a9811dd6a62468c17eb3951d7ef2609f6b7ea590fbb55d553adc6009d2b905a5923fd192990df7afc4d4c2e3f6924fdf2a414e8bb4c54e76cd1cad86b0dfc3d515e38064fe67f132d40c0b6c51df2df819f8471b592412c0fc16a83012c037bb4229143177258528a297ff35bd72f0ed93910d0f92793a5796f25c9a9440b844dc17a1c2e9795868bf36760b6569ffdbfb86424f86e666b26918df0df129bf1573277a9041fd288106f5ceca00f90f414305dfb2bbff484bf788a2f1511e13cd05cbb8e530b093f7b56c581660fd8e8636b61b37ac97952e9ea318fd7712c76bdaf5b9d02dc75c0b690bac70791587d82aade91de5782ea8d03ca6a01b1a495ff62b3ede97becc5e80916bd9c37bd527743bac64ac2e2b5bacccfc8e1086807722efbbbf1e152cc7e0db00348557c1cce740f3bee8e072f3c6b86e69853c38bd008cf7bb4c7f9b2f75ed1bff79779094484a87c5c279062723334312d8a5940879cbe5a90803bc0ba5cd9349e6351f257268d77d0c541fd446583be874c162e7959a657b05ed630f0869c2acda7d0429e7a795c65b0f70492a9d563c7e38181fce6f33a7f811d5355a8e9605e9e9cbd0530c36dfdf90abdf8da5dcdf86d8ba52582d0d84eaabbf5768d7b16669eadab31a7d13ab1279580cf564b32804ab6d3b61c770510693360f3d6329ed282df407b076856dbe7086dd48bfb4f8728e47fcf21b219a0d06b32048df2f97d7ad8df7da0b969962eff51cb578c115e18a69fa4ef186b6c7a36d1f6b33568f5efe59dff06230dc582113f17deba752f2f398ea453026ec8a454a087126dc72bae4bfede56c940f66c8d83e1e030f069c494af47efb6e5e1ffd7503179cc9655707d100ada4c21fa3182f4bf57584ff02862d350a54a593870627924433eaa1b4e78372a454853bddc14863537d8d5b145ecfb4949fc7b944a163197393a963533bd6d510f6962e7e53481fb18b8979ba0fe1ddced0ca05ab2f05acdab0a3d76c53932505144b0d6034612d1c4c0a4642289f6f325f9c84647bbcbbca6aac76eadc28dcb9ba6cd8dab0d680abae56d5fd9761e4c6e546fe2357f9fda784c1fa513ff007319afc0bea97ef447e0e57b2ea2970f51d26015af89d7a1ebc3e6840aff92b54906de85f83f48435b23da256be2e804170d422de0a2d67850b7eed39096891621c667d05a270cff897452b970aee4e9acebd23eed85d32619338b2062664265bfc5320f116b14f68ccda4f2f4cd0bbfc1e2547d878ba741ec83016a5251b2159215e6491ac41beb36c2889aa52bdc57fde109df7e5840d2841a936ee9b3afa861edc9aff6c87e5295ce1cf062031bfa622a9fcc267e327bc88598b5e6a3d4e262a4c964eeb0b4c085b20fd8c89f0f92e4ce64aaeed3693ba11dc84192433ecf3547cc7f34bed5d2f2133cf5a710f9cee67f50ee4fff45af9c6e824b6a0983d9778d9a9878739a8cfff3e70f8b2105c14209c3f2be88548f55c6c9dbeb2697805378130efa511096b552b37470d1ef41fcdf56042529b721c2653f74b1462849769c14eb20fe400c8e39cddc79383ac8960c5302e0817a90248af05ad1bdec443f604725f0610b401dc316dd3a3aa39e8591d609dc25b39d25addbe3831f5b00297dd7d1664558020adb0b456fc1d6ac833956554305a5abf49e346af2185009587cf47dc41dba855194b96ee005c446a09432548252a29b1fab685cc4a0db2f5818f02f5696db3f68ae3d74a747e17790a7cbc97d32e89700079f488edd6e06e8a19997c80793cc7ff05b51f5907b3045fa1767c7df6f4a9dc3b23ee3b73854474c9b16b2965f42ea24b06ed9eb5d9de3efbfdcb6a44105e26bc5e7da9133e20d710940ad363658138c12ca8c5528e994ed2a4caa3cc156e544848aab42ea5681138266fde494ffdf166286541081f8672c32efafa144051127d71ad6261ba7e4234170c718ef42423585b1603eb046fc5b905c0e899eb0a3537542e50f429f6460324743fcad51eb1fa469bb8c160d3642c8324a393a15321e8ca767a12376c2109736d9e4e35ae5201d8b47a729495c0a52fdc4023e6e1d45390c1a6773ad726f7194e91ef18e03634c1af7d6e6c66425e3a32da2bf847060a4574deb30dcc0037eba8a7ac21cbdb2ff83e56810ea5522de44ea0e7f9f247fe424976643119f0c235a1998880d2f146dbdb8ab6ba3ceb8dbbedf12ec093a22ad98cfac21ae2b530d079db60799b2392169b6a0ad2214f1b0797803363f172a1e53209165163ac5efebc95be47009268d7e2074ef2dcdb9148a7d9f0a0623babe77c8cf940315efa7b7b8b6585d62b1b8d9ca26547b263347ad980d6e3172de7b82fbadf471eda74c347991cd7c16262522d2499d29ff9a60cdc7cfa8f8fd3abe6c2aeb9edfad46c245fc7c527b1fc51da4ac219674c61ef1d95b21ecca8e483cb59f7f066629bdedf2b4c2e6802338872b896dc25438281435bb54800b8a9a46512699b59cc1bcf52f25992fea43c387a47f8e7e862d1895bd0c55d8f213ed5ce9a0607df7f5d2fb4b94122b0263a4ac6a763a84568ce550c9c6adb2aae8bc56ec9bf12a30f0dd9c4b386e150463c7011a183a1e8d3cf528484d5218b89ac08641af049e723651330a46ea6f6b923eacba3d4b4d6f25c6eb32a0ca45eb49ecf318e3657fb8ea65336af723c9bb7b107598c10de2de30a6af0a069710a20e96bc7daf45f2c857ff02784ce6fe249c76998e31269cf748c09b57e87346ce96427c0a82c53004368fa61a84352bfe59a5a77aed67f8de841177b533090be0752fc6b7419a86d1216a22b4b882881677549794bb562de056c3d7bea3589f8462421e15fae46c2da7e8dccb19199f8802a7004a161d1e715f94b8d5ef023009c5928ccf9f82b9a3830dd8929eb85126de4d6d0dcb5594ab1f329eb674ac7d5e2af4e6f3ba179fc4d3080644f9461ac2e48b4eaec28ea752c348bbcc704a54bae61f175ab56452bd78d166ded98b506352e71da23dbc15a5ca4a71b6e0c7c691c28e5434be6c77157ace465b403dc019fb628e33fc3c36a45a0f03b640222b34bca82654890cd6a54028b8b0aa8f1abd612a4afaa5d25a40b4beb86422186df25826c5bf0bb10add2982a45caebc886bd3e4fb3679e2436cf20475d60f14c2dc410e8c0d66b9c0f4c5de74d5c376f8e4fbcf50a57c4ea47f95f4ea0825f8ae8d3770d223f89e1c645d3bad92c3cbaa312ac295d87e54dd0192e55bffd417bca0c3161af5d14418970bae597097a7a6ddcf8ec482c2b67cd25c35ed7e2b1cbd8bd5965367c154b74ee3222f77b7d60d04948acf772f1c37e6df968a67edc617067a2ccb2d7d4069a586e1119b78ac7388acf088bd25788748d199963e704dc8f14e179446be97f7b959721981d93c86f663acf9c5301b16ad54a13b8fb548ec39308020ab1171e421094cd6c54378472b16b0c0b007b0d6f5d346d8fbaa3a931231c6ae07e6e810e595425d232420aad3184c3523fa2365d91968104350d823a4e4a2d855fc204f7cd8a9ac5283be583815588e4e2f55484f6b6bf1f4578f5721b64bb572cebeb04fcdf2e2c4872cb535e2bd55c7d1f97aff3e7652d0803b99449371aff5abf55ad75ee6d2be9dbb062c926c148b168befa8d8ad195157e8b54a6082a3800346eac612e7e49b204b45fa45715f5aafd8f2a34f596398185bce5f998ddb74d1889e351e66de7b52d7d65620d8081c727bda68a0014c34880776ebe917fb7e4fb83d0f44fb3ec0a5910ff352df034ace49dccb53e83ce3e13e636b81e07c41adc5b633f4f64a14680804fc996c0248077b2cd0d05719c9758999aaecfbd95e8b095c239ac0b92e9a4c193bc386840d2b9f626c9a53999a802cc47bfca004867b6dcbfec9b599e26d3e99494551caf9c9d75f46c98d7024b7954eba28bdb9850bca53533dc42741c09f20cc1e2156884f72798e2a72d8ca65ffbfeccf909ae45dd42a74ca7709c0cad3752d8c9caf8c535241984db1e2063d92f9cdbfb681d6830051dd48a7344a57efa028823a98183abd846fb77398cda67900e01b944f05cd511fbc4a015abe8038b62f00e3ec057bb24499d5c7af69f845cb0ac997f4e259fdba66981c3d07df33ae9fad4a2099aaa7dc98193a962388ceb925d62247ef7a954fbd26ce5391b1a80f3d0416d76c5023336ab47479f6a1d117104f0de5f073c116c26102eb895b94448048fd625c516e0be75934924be1b04b3f56122ba47cd518840dc20095b55b623f22114dafebe2ceb523e023b638af0ea6789957f0e7d6ab3574eba68cdecf0bcca22060c20a6851c6fe86dfdf782377755f6ef285bba84e517d7fae02fc7189aa1cca4c6626280351e13a4cf49b75ac9f6ca9a38640a8d8706e6b016c9e9cf571ba54908e4bb52bc459caa9b408df125d2b14ae176584f80c08c7e805cdceebaa55cb265894b9a7d8c0d818d44ecc37191e0ea2e658ecf20310b58c659c72e4b09c26cd8726f4da983ffc913360b9417bb387e928f3c3a0c21572bcfcdd11f05e6bdd81753c38b672c93de6788e0cd9eead776730d09ba4c234db2c3ca0997b973b53d8c97baaa06279b611397b6274e2023426cca5fbb513918992543903e570ce2722e15946ee5f424470b3841b7bcde0767736f6e44337523960dc4c5d9fe4e4c01f8a1dbc5603c30156fb7e0ca1be04cbe183030dcf158da9b668ebc1a6157ff17e380e27d8b370d1279a58043dc9da1c20be56add5e4294f399179f98485e76cf3da29c1074a4361eabcbf732deea27d93a229825c8bafd183cde12fe055f5de88a869f2679c4ad4d1fc3d8c4cb6c88852e9d53bc8ff19393585826fb6c399bb99121cca9abffeea7fd54084351c0a301fa1471c16fc6beb3104a3ee61e11d345aeb42822f004a97412b9db0581e57abe5a7fc33ab469448b6b5670e4389cd4010349555659d41ba9044382f8930e390619af26b42c3d3b5b09bd384186ae104802c3f1220529e79d2009a0de158349bd589dfa5ce390fc59d3b338a52778991b6b7ab6eb38e1867ca6d8ee75b55bf7c36067e5478bc0406ddd1eec63f6ad18e2017c1473a414833dd8292ef8d0361555ffc02902c64f12e4c5bc1fab3d60921a2bdc1328ad279e9161e29b28e61850192ae1328d077c28fbcba10ead32f298ecc373d72b01d58dd2e311d199da0deb58a13a4ba030adeea8556505ad5a4399e04e87e448152e7aa7a3848b0089182a854558b806ce508a24e94086935f219ffa6c1808d32e6158aa3a8a6075d40fa6f17086fdc31678cb07f60d6e177433236f4f6ffbfb5b675a326d444444812d902dd0804081308fd9c7bae3131b88831d61e62ede9ee561b0b8ddd880cc4da64b9d618638c09811d7c7313011020213a1fd6dbbe555b3010e37b188831d7b71880651f00c8b28ff99e880a51597e0b7683ff1c00c439b62836aa3296b0a26807ad1d16ec2d6aadb5f6f0931731bbf7de9bacd6b268ac06bf2258c239e75a6bd79a6bac190fde7b7bce3dc7746837d6302b7c546fe41f1a47b546d7b84e11a69d0f33d68db6b56037f893d59e8369cb0c8b18364ad1dfa5477fd1bb2b82156b33f319df45553cd18c198b6028623baa97551bbdb5d680d8e87df5886a2c5bc177ce3dc4982d3ec33bd71b29b134a6582e3c3d7c06c800961160b95e77f9e818fc952ed9a774c528f2901e2d47d10df728c2b3107cac0cc46cc646f761860a57f4ea04167bf41e8c0cb359364638e25fbdd7b52ccb67218e57c4f5bef3e5c3caeffc57431c11c1ea37b643a47e2dfafbea4a0be163f4433cbc14fd20155962da7cbaebddba522a17d63deae102d4e5a87529a1374f5d8f52d65dba3a00adac57c5ba6bdb8380f61d066159e98d0af1ecab49445958595d3443daf1626d06703e9a732e1273504008217c84706a8173ce39e75c6b1d079a163c1c61b25e6bece958c0632dc289525484127415092cd0294e29b9e7a085e29118fc4163075d6cb4d6dc83aefd4d51609632924c9481772d0a71235363d911b1cc4e88e5a865b0d52aac99010d049c02609d2f7060f1ef5c1201714b6c3fd75e6bb587abb18e91381102eb9e73351b191d4497822524f539e7f51430799a97534053c0ec695ead80d9a6793105cc37c17721aaf8f616feb5808881f511a20ab95b36b291bdae7e2c1b2f218c2c47219a757f56f443c40cd0217eb391bddc42af1f4fd462e42096dd0989f049f2c128a52ac0993733d38810430d7308834b8c202821c66b4e5284a33d463f3c164c56644556448386bd56db571b10cde8ab08c1e2d3169f648d0b907ef3ebb931dd55510222e6c6aa15956322a22357a5176314e188f1acbd17df73f041e86aabf8edc0491a6498d88163cc4be0194f4481cbb4a425592e2e2e2e2e518b3c6307e792830514e02c1440550244320e601d8f68238ccc29a10149b2b5d69a73ceb9186bb09c15b5a8041529962089b1d5a03d25e27b7788221cb426821bb4268376c4452d72149b23293d2865da9df41e7cad4a0d3e2b5cd4e20c1c01cbc4295ac21c40448d9c444b7090819641057b3d18e8285932b1600417c425b6c95801fbb53717dbd9bdcff75a9c1828628ed68ef72267a45f9c2c251089d5feae38fd4eef26603b5d5204a2f671c03a1781debb49f6398e40afbde65c14cd78dc5e4b40d7c4f678506bf155217a1e03143dccc973ceb9f7defb419cac080dcde21623c6dc2cf7ea6b38a0f33050ab2f83354566973108a1b5385944cccccccccc7890e0f1c4c96a48580b9418d681d80072e0e242448c920f11c89d88f60480023e58a03d7a1e78526566dd8f1d8f5957df0e5af341b35105b6b750981d33f33b636667799ce4dce3d91dc6d69a73cdb93a45e139e72c140f335603e6ca0e858af62063118db539b4ee3eeb7e9d9deebafa81ba3b8b7ea077f7b814300be1836d7359577b33dea98ba319eff462d18cf7e96ad18cf779cd909e7d8fd08a4ac4e7286b4798569bac16f9c5c134095a10db6a129d45167603f030d1723483fdd8217df206a010338b2cecf51124886db5f9e80e300b3f5d126d210389d704d359b49e81294370d2c87b41e35cc3223a995273d34544cbe8e96424c2b9cc1031333313b5d84065f0487fd139e7a28f69c2f8a0041f84f039e8dc7bf0819a0a11bfc7de73ef39e7dc7b41f48e44f4e4518b4288a1c28d6009518b4ed8c9d030cd144c632f3fe1278da397b48cbe15fb891516bf9748fdba9774ec27fc84260a43a0601a27d39e88628ef7de638d3596238710ba0a34716aadb5e65a634a641a4707a1a271c8b7da51d404c16abfd14e5690c611754b413a066918a45f102aecf54401815680ac6ca665f43b341eb6e4c11a86c50990c41adb18c83923cc442db6ec789722075927617b6f2e2e916b305689b5260f0482226a3ae0c20fda4ccd4c9118507145cd0eae705295c089931a29ea30859a99d783f75af09084379d210b3c348989375a12555102f71b2d79a2553193823640c85c3841c5d482058b5f0fde6bc143118a48244e886d9f2d5fb05c3424d7d50008b6bd21897e706ff5057142a488c25003dbd60beb6a9301c1e0362038210c053388c0099155cc808ae0f1c4c95201bfd0603f18a88509cd4387289d5cc704876405ee078e0930458aa845878495c004254487443a614d7e90c76a8ffaa0228f019aeaac2e56cb681cc496d1f7c10a331e26034b031d3b5e8f018a92b910c46883385971c8021866e2d422470b197864bcc0e33c71b26682709fbb16a199b1c2098d1022324d9cd0a0c91395203c79e2e4891530e184c6bdf79e73cef1600731718a9624e7449180799385040d0d0d0d0d0d8d47071e4f9cac181978fb2aeb81ec1b807d2ef6cd4f368c104155f55a567deec9f31911d1a2a89d2e1911c8ddc5c5c56586046c3b4b191598354633dc658b40ee8cee884abc47cfd9b0ad3a214a72ea786f51878c8c8c8c0c1106b0f2c41b7c3000dbdee0fe18d3b8d870ce31b35aa00c60f67069624e27608f40ce08fbeee07548194986b585e2796788929c53036cbcb7d8002516102c2b6ad14667891598d8704143d25c40d2608c6d4d0adb185c00c38144cbe8b739510dcc3c8184069a26fe205074d24e8878c184c80ad790401144d0b91358ce3dc61d6058b0509a732e3ae3c8591774ce39f7698f87350612ab991b6b33683d5807273861f483048ae2bdf7de3bbf7a9901cd4a67548868a51ab51d84c12546175c844d02b6b046d10c06b2230b7800eb08609d0ceb2eeb58acdb582759f7e81c454cb8c1caab7a2355af35d5fb592f48aa5c5a51711ce36b6ef1396602654f053172f4ee6f1cd5dd5d6ce4381263f35151ed39f79c7ccdbdd6de7339206b46885e8baaf0c14a447487fc016c23806d326cb3ae0887f51c511525c8d1388a8094f52e2d2b5525a219462c7e11510423072318b5584545022788a10adb188863267e7488ae870706f292aea701683d08a173efc1e7891b4e27077578f8cec5b93657d42cb82a0f8e96bd894c7407a326dd21f95a7994d2d94879dd8e8111734151c958644b0ff4d4cb6c13b1ec2eea65d235738fb177f916c262ec7d67576b26bb08d5bfd329aade2662dfe9a9aed49d2a55a95fcf9b6aaa298ab1686dea87ea68f9bc45108cba948cb1fbe28ffaca75d9aebca23ce41925290e8aca8bea82922ea8a43ec9bbf71076aa45bd9e4f6da95d05a3d702ae06c843ca83bff277b1cbeb9de59aeeb9aac8ae5c73855546f3d8a91eeb2c18290b56ab87507f944d4d2216b188518797d34459a72cfabbf710482b104f5877824f5277511451f542a6b587309a1ed244742c80811cac3dc4b5b0470e50ba27d56794c3724a6cb4ee3392262a9e20b14e1ce39896e1b8f6a66594b01b74474fba832b07e9955f50ca3bbf3926bb36ee458b96535f79ca3b9f134a2965c83a63ccaad750055d9277d5f50d6bbd7d5da7c47277bfebaf3c0fbff03cd4aed5adf72f3bb704e2839d15f63e66ff619bf9ba8e0af6bedf29b1ef308c6aaaa9a62eeb9d2edbb56b67551867690df559c594a42425dfae9d9467d38bdfd8e2d76a79bb247d5dc9f573fd5df670182e3e2c208f4a0e94cfd9f506c1de43b0cbf35d15fcd267d8576461df27bfd9c0770df52d76287f3d96fe5a969ec6380ff57a7878adefa1d97b9094f29093bc0e66b20f5df400e351c7a83c54566b9d4faebe38c875f112d5c54cf42f0761edaae0c1bef9bbfa7cbdff9aaea3d93c0db271320cf4aea365b8c3a837bea837baa8d76a51aff5a9d7d352af87a5de7bea05add40b52a929f5ba5894daa9370787fa85158799998a97e7df8ae392dc984e136bd813cbdee76f75f64b9d85a64b5518672996524aea5615c6b1ac2e09d3e0bc8ae7544172b8801ccbb40c77b7a93787cb3d1e190e52e51f3ca3b15505e209ab72d31fe5513dc495aace3249f8a592a7aa4be2f1384663df6ff4782296a917d6f71b9d8c4be294709025820471499826059463103863e79c57a9cef53e4a85909627ca43bee87086dda03b5ecfe9f29cabffaea9ad252d1dc207a52b44230e45bd4bd2a3389d771905a55ec6d78533f69d992bbdef4dff6a4fef90a77708afb0773a0c0bf17fd877dd0ea2add4fdaedbec740a422bec9d7a88cb38d00afc427dba30ac5e3863a71fbef31b5ec9463f74ded13b4f2b67289daa1f944fef20f86f08fe3b547248057e7987efbd0bc32e9cb1280ffa5743efd42b7a5deef7e93d410a560ae1557a4c6f7aef69a23b660cf2502ebe828681dc81b01e4f0f528107bcfc74b10af5952b052a89a460dddb9cab1548c1ba5b9beb235d3eb2d49a6e31ad216a057e69e9b7473473dfa51a8a87a7987a441f00cf57abb171589fae68d58ff4778a97acc03af877ea02e209ab478ff7f996becf899d8f100af64a967a75c5680645a53c27f61d5a017efa3c5402adc02f919d7f74c78433bc8481dca58baf6020078405adc0349eab211663b1142ab4d0c4de4649ac58b20528ac8b8d9268e10dd60a255600364a92852c2c61c24e963d7ec98c35808d922c2962b9065694840b4fecb4fc1a1b1fe7d1e6739a54561eebe5cb282a84b49136798ecce79a89eee04677b03a67bc66acd4d975ad78192fd959c64b761dcd42d67fd818d11839e54c87a09809bfc8f38c9d21a8daa997591a63656b7d32475943f4d6e36fbcae652304e2e30764f13a3a5ef82b14ff83bd4d529e31768ab1b01746363ac465361e0552879fbfd6a5ac976b3e5d56669d397df224a57cbc2ed33a751e60f1e9e345b97eacc3cbcf19443c0f11cf6724ec863c3bd3f00b9f558a6fcae12fd758f9f9aa86241f5e467653aa4c49a9174652ca233ec4aafc14235f4eba63a22eb6e81519e81d08eb4ce3328d65879447fc3cbcf8ec8247b9a677aeea7da9bc5d2b918d180903c16f38d7477e3eb29bdf0dd3c92666c22f90cf750694747819921e2f27cb4b9cab510fd89ce24bdad48f3c7c3c3c37cbbf30cd52879f4ea7af5857b9a296615d96c2c23fca831fa2e81d1d62b2ccf1f4d3190933e197c84e538d9d57935763a007841519888398365666c234e0b318070b5e20c2dc6198658c7d4188ad61a3245eb88251ec8f2df5e059126ddf7b14f528ea51d4a3a8771dfdfa4d14f5f7fabda99a445ba61e3da2a87b810a5e8082a29cbbd4297a77569d7aa1572f4fefbdce9bb1dec889b15ecf931eab5355be7371aea837977545edec542f102ba58832512cc2e00a273600364a72451512638c85ee7bff477b9fb3b5d93ebb26d1f6b27d0fe8c3db2ce5580fb9f4e9d5752d0bc4c78f6a7ec0f267adaea3abeb3614d5a72b241f59be6edbea110da22dfd9cafaa334b9faa4f7c3b06f64a8761b326d176feb0a1e9b2ba0ec6a7bfd619c659c6ccf5b2595d3a3fe58a9adfe17a615ccb65984d856176ca5fabc2305bd5cb76faa41586d9a946e9ecf2ea214c43aab05e3bfd68402c0669d0052696d0d859b5db45ec65e78b0b351664a3245c90b15e58c216c04649ba30632f576627b6911fb1bb0bc4b28ee650123eac7b649b06d1b69d93681bdd76b9c2b0db4576c027e9828c05808d9274a1889d707a74073c53081f1b07e710d63b7d3ec21aa15c51cbe80a9f72592d0352a730ac3a0ae7da5c51c3bbaa5ed684a23562a0a9c238db32ca3ff7f8a63c2e9090ac17c65d1867790696546198edc75f18c69ad821fc026b88dfb4b587300d56511c908abd19cc7e631b44368231b0eef409ebba58466b6085da590f611ad0620c043b56c723b22dc916ec9083ddb85694640b6fb00c440f611aee4c6f0bb111331a068a8468b6d51ed26d09f313fdc38fec87016cb932cb96d92a9ac18f685427c0d10f5534839d1b30a3e8067b6b1d31f3985184a3d9b9c628623f185bc039e75c51cbe044eb9babc1f4734d34c144134d48134c23c20deb54a199a970d940c66a73c4534cd6cd7dd1477346c618838957a8eaeed88f2a2ca2f014fcc23e53ba5a3947a6c24ece3c63b127b31a8a7d5d0b888ff92657d1714a81048693a9e02968c5efc34358d536dfb37e544e75f7a5988c5dcf1f3ca5b3739e62a5b27e68f67ccf7a57289ee231405d790a96c2ce3e9d5047f7f488536fdc30d74d259deb75b19b6a0ace61d964e9d9abb3384f63db3c4a164f71a9eab7aab7457af76af214b4f2144c039ea78090a9788cf3142e288c7205e69eb18d768c6d312e9c4e8baa6059f404cb1060d90db0f9b551a3067479afc150caa75cf3efeaa87180207bcd0141103390e70f442174e101bd42d27fd89772c6284b0aca1994ae32044a5579cdb2d40bc3208535442ffdb1c309c447e4f29a07f6f67c8c397269287a52c63aa686f4f97a3b66bec2fc4aef0c65ce39278317cbc6460f906a8d77c1fa59797f5613e5a917c6abf7bd472efcf2deeb183bd9f36a5e8996ca52a5fa16582516764ba244d460a7d827f6ce52ab9ef15c352e2518c87de5f2c141a227359846bb5cec3a5ae5daa45cf3289775eaba9ee97a44dc68f52f8c0e6773221a87129c0bc3c3cc752aca6166e6aac735d954e3b6475f8f6bf29c73ce4e8f8bd66b83996b300dce698fcbc657f5dab09cfa9194681ca096e1eef15816fc6d76f6b82cfded71591b767e7345d10cbe754df4a18a1ed43858ba688d8e51c2c713079f0ab790e2454d6cb3113da224632eee4d16d9a393f36d6098bb944e69bd36acfb14e22b3de03197766db0f76a8dc66e3c56a377493d81f8f8a144bc4b8c64e6159afec38af1ef452efcf23e3b67717eb26af04b3c7b9c21ac7a999dcea997d969c376e6a7f926f63759fd4c7797efbdf323171623e7eed7869597e8245fe32d9c0ac32ce7ccbd8738ec4974876c12afab5d4058ec91f27897eedc3797bc75d1ebe8e71eac9a75520d7ea13ef1d2232b04f5592f5baa7ee2dde56bf0cbbba371aa312f2f5fe3d11dd2c6d55eadc1349cc5550ba0fcccd8f889b111cab4d4dc162c20c3969a8f914f0cbb015b42d982c86bf3ee969afea7484794559a621f23fcd212e512e51363b9b96b889eba6c081ffcf0c0de27ffc3729b5a6a3e453e50bc9ee0fdc47c8c4cea13d39fde156efa97829d37ec162c241fcaebaad4e6fa51f97bb7d47c8a40c6eeca27c6363bd51cb95225734fd367e66384690461207795cb2de198e07f8cf0a78885920fa7a3c8ce759be55c2d350c848446e3ad78493f461e37a3c252a7933cfc44272a79921f2390b560c148b0d705b1eecc2d61dd3f46f885f560544cecb6606127d8835161e59f7bd582857dff18f91869a9f918f9c438e7dcc70894e970070e4d896dad888d6942a4642e4877b7a4583721cd895684dd68d9074dea2c299d0d7d3373cb3722dca0b0f40a55510bc65a50d6a2e1ab7e41abbf80ad08d70b53310dcb4a4ad5b2fb75834236ec6e42e81b117ee9d3160309bb39c12f14762b629f7c475e763a524a2969b3aca45495d58f8b3f2460fc9eeb2a1c76834853dae4298a56a7e491681c2eecf388e1f85cf51546bd91c190dd957e72692a2b8c1755e5517bba3981848b0b03f0ca004d73a2a9bede5bcc7fae7baa0971a9375a967aa3653d7701b546439b13b4be8a369aaa8628a5cd09ead238ea5dede1f7f5d7c3c3af15e337da1e2a0b798c1a1d0f35ea5a9b13147c9fa890a6776f4e342720753dd7a24d4873a2154102033434cd891817ac051b8aa44845580d8c1d7971a839e78c87612169d239e37cc52225558f1b5663e36118a5a7f5d2a7fc5a4f992a4cb39b1ae26b511425bdbae635d1b326bc2279585a2ed5cbb35eaea810d24a7c8af2982496580dbb31cf45e80ee99a3ea72451674da4cbde505da18d842249f3d559137e915e312cec9d144a7589fa64ae6aeca45252a6f54985d8ccfad93c9e9224e93ccf9accaaa23ea5549f52aecb143f4abf2a4fa12a104f58d255a930cdcec753164ae52b179532290fe9a1592f4b496289eea045208407c262e726763e521ed23faf78948b9e5d2cefabc55d9eeb6829c6f9aa8ad48cf15ce3355d91e57856067ee13866ddb93ef353f54bddfae55b35242f352bcff91582533ff3f1d6b9ea60ac0cfc223d56a77e1989b52a4cb3cd568fa76f61b11eefb9365fb9a296b1a9d7aa30ed32121b1f2bea9095413ac5caf058cd753508a5cacac034628516e390614696fcf4c852fadb445c57b31bc2d9ddf3dd703633cf331a38afa327bb425414fbba78bfad0e36af83f58ca726a362bfce966e46cdd99f6f76eb8bd1ccb38673b2955fea10c676b01d6c07e74a85bf14fde42946082133c74a3d54ed212e2aecfaa1fe0eb9e164ac5dc0f99eb0ff0ea78b0a279c74ced99452d6d4b58006cc49a7b62c2b247d9e5facf33e3a0f4f299c91ce0963fdccbff345e32f6bf2484108e13c4529a5d3945264e19532c856d245e2511e459fd2d5f9e41697979f7a9923257df5c66e48965da49273ca8bca3a01f151f1ab2ab4f90f2b234b4a5e395bd35975b6be4999ea6576f3141d4cf2a594b2569bca85ac6f2eab8a31c64292624caae4552e4d9736af2aab629537555555959caecb5c532e37b587c8ebaed4cda557524a21d374792e55a7743a555d7a7501f184a4aea7ae30c618af54f57260d21d94928b371610963cbd245de5a29e7271de57cbdbd5e2ee62f9bb3ed7d192b2f40ecaf5994e1f59abf3dbb16a684aee5caf74a99a6a685ebe9a2a799e28d5d47955f99ab73af5335d3a5fd6a553d6376f7155ff5cd55b2e96cb6a195595ced948567557558aa2dee80eaa089d6294356e58470c92bb0adbb889d816598c999395a294c7caa93776434656329a28922425c94592a46b439224e9d22459ac5103657a43608e39e69863ef46c816a5344246584429e37b9452d24829e5e3a3ac714af4559846af8881a6178f380265a20c9ba00d196390b1eeee8e24c6de20846f6287bf304ca2d6a4935167b4a2d75425595126e886eed7dd9c3e84902d07368cad01f1c1e1bc8570ba5d21f78853216cf0ad1ba7dd71381c8e2772cee9ce3912a6a034aab2e00a54b1604a05a94aa17438d651ae8d55517492f50291ea8d96a14c1c26a1204618637c6c8af151b37d1147f1374651616077cb7052e6a5202d83fd469577bdd3217b4ca9ec28f546957aad4ebd9e4dbdafea05512fd84aa742a2bba6d41b3d7133b1dea8c6b25fef3c8a70d4a73c8a70f0f09547118e18677914e1e8e19f47110e1fee221ec67db8e27bb8e2635cf13c5cf58abfae5f512423d60bf30ea3bea837878bdaa25e974f6da917c4523df57ea55e8ff5a454947aad4ebdd15ab59b4ace4e09dfeb90744ea69de3917884695eb05983c4c2bf17fbb5185b6a3e453e3132c658b52716be25562663e1a38ac16bf6d48245f73f463e463e463e46a08b436b365e6bed2eedbd67a36dbcc7f95a8d1a356a3807b9c641c82074b0a6b9a69aa873ae8d35bde71ebb4a919d99301366c24c1a48c5dc179c834c888390098602081d6442a46610fe4e8ff0b15e79ea10d6479b77ab9a32e663779417a6b166674db026d8c4dc15efc5dbafc5185b742f3a2231c6afa8a49cbea74b0d6e22199b7aa34abd91f3cd19eb3c05e5624d389b7a3d96b146d5eea986261bd243e073ada10a9c7bccb1293e235e7beebdf7de83147e9ea2ea6d96d2f775a7d3daaf4eb3de2649523ae288238e30f25eecc7a618e3598ad8a23bb78d4f768c31461bebbdf4d2e3a71c9d4f47b9222663aad7c546ebd41431d0a6de66519d2b6237a27401f184456b9342adfef69055fa75eff860eb8ac240d1df124b52e292180593a9624c84a2c812c684302682b40caeec07815c5c72e4f0782c0be6c52394d678c46234261e8951b01b54d2b6dec2b4bb296b1aa5b02c8576288d31900754875e078b473a3485aac094abc4282cebee9af2dbcdbabbbbbb43d453defcd8e963a7518a2bd4945d312642c12ff432f280693cc25c6f8cc2bec8cdb25936cb66d92c9b65b3ec4bea5962cd70584a29a5e486b45da21cb6536a3c02f3505a183b638f31ec863c7d8482b118058b515879cb4a39ad217a9822adcda30807dbe4b82ea07b66fae742bea9694ccc8b5ae95db4a8d7834437bdfcd49ba3a55e17967a419eda2bacc2302fa5725c128f5c2cc3407c948bab60250cc4f1088b50586afdbd777a9e73dd48e646326cc518067a5505a3ac1e9ffe553cc29c12b6c432eaecd989524ca19495524a73d007708d4798467579dd0a32245a867b11c698c891c3c50504fa3d1ecb8a479c7332efb9189d8c7d47221ee1178e4772e47071a1a77f31261e8951c8542123138fc87c38461384a04016d2d9ccee0e41a9bbcfde94e095fee4d96bf5aaca576ffa957de71f83d26cd6086e08eb11121ad1f00824d88d86f09246445858e90a4d1165cc081436d123268b5a2e16a55e94374bf945b9ca2fbb4aa7d4e917456270ea43a9eb67fafb84d0889e94f2409950aecb965360ad2a7d955a53268a94e88e29e488e96a91c5bede39d7bc7551a7f0f11fcfcb976f9a13c6c647f0cb46fae64a952f3de7773ae74eb01ec134369fe2e608fae92d16756b3a825ff8882368a27684c5e18d0ea28b189f44ab17307e59cdebd97356553567c593635535218d481562893c9e599db14c1791e52e28ae582a6abe94ce863acbace69cf0734e22158b87157c55bdea55afa2aa0abeea55afaaae381fcba43e2c87afaea3fa9c31565f5971115d54cc45355f5c305c4c7488f957bdd752190b753580811e9cf0629f17bce7a2efebc5db0503bef7de93a25455b09a73ceeaf1f38754352b58d58f7ce3f0789c885405e3c515b58caafaab5ef5aae6043c7d13d29c58407ccd8988c6c358c83013672e19632dc6df64b3c2f08b05c3b1f10b85e1f7dafb4c6bad0da0c5b08f5fac5f1866e617398dc57879498a133ff6c82cbef7a299c779ed3133c7c72fcccc2f3ee608c3f1bdf7c7349c551d914d2c245276cbee0e12293b8f36acbb19494bfa1fb623aa9ba1a44ebb512836b9a9d3b784407c48c948a494524a5933c9269d5f4ac1ce34498aa56859fbba2b95aa40c9d85de97424934c386726d34a85819225335161248c29253bb2e786b95e9846498a99c05841499d35f9a6a9c99452844c508a40841911d8646516c1348dd2295dbdd96dcee6d6bb32d652042b82dd88b8096cd691e77346203eba089a6627b1a34f3753f8a1223c7fdef1c39eaeb7c7046f3777777777c366c61e73c21a6545b01b3435947113462183104247298410a6e3c57ef8fc42dbe2f7d9fe752f609c453ffc7d8e7eb8de6f66d217d74f0c96f75004c3b7b430c5efe12ced03eca91bfad0431144580cfa5afede79b8a6d78bf3ebdafc97751897ca5f5cd55d5c296f71a1fc73755aae59044b8dd6adf04ae495c85698b018eb9b7e7b4c374e3544993200b09515865c8178c2524941e177f89ccdc52c9ac1afae16cde07a43d141ee3145c84c8a98a626933101c015c570957958b02231192604461999a0d62636697a7b6317b936e90ec784546f73d7b52c101f3fac7426d80d14486fb51d0c0b51ff61a58823494ca4559335c12fed4c49d2e4489724d5b7f62bb124b51aaa4e5dfa6dce4517037be3d955ce31f1c988c45649d2dd5b8b6fedad35d738b1b50bc39254a5ebc2348a09860237e734adcc532b2cb9af34c9b556ad4d5da1ae7daa9703ac09aa822a9ef7c5f294cb3ae7da5c474b5307853baf21793b4df04b735dc9cfcff93a793e6a1c9244614d7438674d702acbc5b9e70aa7cca8f4ac59e88290211a010000000023160000300c0c854363c140523619a80f14001479a0505e549909c42849619842c618630c000020002202323335090218511a9a6190c0d005f976d64fa643f46448c78dc09721cb735bd15d70ba493802e9209f08266185c54fc783ad271caf1decc996d98606681472b73f4268293f5c25f0c944c8676bea75f29e6cc752db63cfad94a423e4b91180c354eb085efe322e0b165b5e55c42782529ad2b9c68146e711d4c046862517bf8f5967c6cf0a2b4c14bc33439079781fc143ab9d730c35bb555b82cd01befa111e7badede713724706f7cc468d2fd548179b3530c2b40ea815ca7b0b40427de0393feab8d5acb434b6062414b58e19fd1ba789f6e8066808649167af774ec710405407790db4fa615ef49a0219e89b9d95be4bf337af03210b1d4f4e65ff57fe748dc27948fc9a715b9860016739570f69f51d270e7c4b68c36ce3fbcfd7598f2a94e2d7c49c91a80ade82cfa5ea3d3ae72b45559dda173fbe9f46c9277bda2cf2ea3d1483118edf35f8ca9fea998f4ef6027e1aa2b01c9f9e31001a0221c99cf683ca8ae5fb7b16208253ae6785be94e092ac7e042e6ad55a0518a06e5b18fc755ccddf058ba393d128418a2ba55019d722e495a09cab94b94982a82334334592d906c0a6889e3d3fd41e79c3acb8594bc4e72ae212277ab28092f18804f8182a1314e70a437a1baa502820b0a4ba53c0a598f3073e6791cd9bdc983d78ec74a18c7bee5ee00ae01bb313ad51524e588e70fbe0c376d95f3dbeeefd979b33a711ac212c8a48793161a85f1667abb2f929594aa01a103260b361bbbcb0ff30e21bf35c018fff11bcda673c26518d2757403a04643c8d94ea83a11f7db1799ec1a2a3c4296c5f908fa83f695eb09083425d5f1c9f2cb92cf394220b914542420a27243d9687ed96a7d8cb131e8f67af26663b05eb890e4c71a2b36ac868bc7a74a9f214e018114455c042d14fe640cd1a48c43382f6d22a47815d83b54718122183ba2f3d11a423811c3abcaef442655117e748cd8f62d3a814dd103bacdf8e7c18f51976ba1fff99c07495a4c7a35fa2e7cc6772b110b7b82d7da964c219d68fa7d0280a72b5f9892602a6f19d1ae35cbc199ec79bc384ba9a1ae5ae48960367b84ddc9ee3fff7d1396d950f89c2855d1220b942f500ad83fdba281e64e2d2410a0f0f93b416a1710b94ac52be64c360f99a050ef1baf31840222853330d88a3ccd7fbc0728bc072375a0061398daf2dbc1704119530cee8eba4340649363ab660ecf279bc9230421f681cd0be7305789de474d40e9ec7585659b51aef947f57b3112297affaf94fd09b426da3827970d55c1e1bae7d32092ad9bd27d9aa7ee154ee4ad2375cf1f9fab378ecf686762b3a6039727a70dd00e1d630e55842b4633d9d3649fba21dfbe2b373786e35e747fe8c2bbb031581adc6a9a5c32dfde58cae84d218b2e5d3d5cc0043c97cf594935af2342f10df3a13f3bb9aef44e4c1373571b82c7ef92d4d9cd9d166793943430f009e918cf9a1e4e99a39f34b714418cb8810b8a26b268728a9622560a13bc4cc3221f4ca875cfbd10f25766cafdcbeb212b883d3433e12ccdab6852756964844caa229af9eb8b5b1d9e2a8001321142a91780372ae3d5802dae14b7573237715190ce3c4be26ec9d1ca25477dee384451d6ec00b56735105690f15f5c014e6378bc5fbcd349e374f403610b95e6689e574e590198ac6060502493421c78655759b9988a92b92ed3364d6db84212b28398ef817615f4d50c4945d3544ca25bdc80c305bde1f0d48451548a56d0a623a8b451e3aaecae5054d7b8c9842b0faee6f094d72d7cb5962f057ea42a451e7c14cf354333ba09262c03b638bcfe6b5b57745d6573e7b3b5315f6923849b4c390778bca71a57ac5a2de07f6866fc80fcee4f77eb8645871ede33087fd635b7eddeba982bcf1cb8f92178ffa894eee88623116cc967661d116a4100b2ebb01c59a21f50f5ed6891636af5fcc228047c01f77e9ac941cbfe8d744dcc74f41cd711440b58f0f97f55ccadee1d87d8472bb7259665873c053421b7203695f469ba9781104de570348bbabddf78667a862afd612731080bccea59807174f940b6d53b55ffdf640603821db1f18e967ab6a1682786201ac3b718513f50aab6bfb75b61d00004fd6c400a5578718e4d954cdb19e173ddb92928fa42c5afba2a1067d382825d0e825683bf4b1405c4ab51071497720f809f9aa2c569fafd61812a57111cf58e4a46e532c7d283be72018c3fbeab9be2f756fb8a138b58152b2403706d16cc99e52ebb2f114b28aabb7602f93dea23a1fc4334b61469cdcd6e8954e309a8fabf4bb3e95cc22439f592af2402f4a5f377666d1b35a6af9785257fc9e6308b6f97b9cd8652cc73d867fc99323ce6c597e7b6bd1178c879c44a5afa1d01fce4eb28ad03c172c0f5b6d309b23fc939bd3e5f628156a1dde8d2ca71e190d26ceef34bbeaae48cc3297cf0636f37839cf3d7b929b5423287c35f9d15e1d22531f154a28b8d4aa12be688e5127b0782cf9774603edb4af575b102a65da07cc26eac3d27cffd4bdb176ca79fc84fc1fc0d4381e1084445e52a4d9a7140dcac7b9a94c6b4db10255ba1226f01cc9a7a7ea15b8674d841e3b4ba242049212635284550356a40cc11302e669709d7a0417ef0e2c499ae4af6b1cbfbbd445b0f8c91668e02ff0f1f89cc0b031321f146ee6f74648b05607802fb83ee10b40c1f2ed997559503821567c7a8e267bba0242e15684281c3d0a37c081fe03c7a99a856de4310d2c62fefdda7c32110ccb30436beabf36f0a0e905115c66da477e3306d94af57a76166c470702958507dbfa971697572c72a3d3dada52c69b1b052a28b1d820a9c0cb9c1eee836d935a672a09cf5b7da367b6a708c5d0c8a38527b573c37940dc6cd05db9548c0b986c5898129e39a64b3e137a66a2b8b0c987145691c4c0e1c0161d3c7cbe290fd1531794fd3fea1c5b8d59db6ae9b4459f4af1ba97cd9c3dbe90d1201b3c0b17a0a778681e208769f3c383a729e280da5ea983e5436d23fba8b54e24bff617dfb93069e8f365a2756e445612a592b3045f6b6e816fc781449a5401440c7ca4ab2d29949952caf684b4c70721de7bd940d68697a79b1da5d7cc2ce8c5fc889ecda4663e17f3d4b62cd73fe39cb14c497a15e6eda303346a18d23f71a46278b843a8b66f842f4b9509c0e311f12553b8400ff26c234a97caacdd2d7781adb7045d98e9bc3616f1cf4545da9ffb8590c2ac9a892004aae73e7906a2fec470be6258c0b8998e37adaeeb4f993902d06f0621f09dcaecd0c4c8a18e4c9a2c701b27426cb779ccaee851547c74bcbf0941c2c0e9b7802771f26905c4073a13857e745e515565958a552ba6f223e062c4d7c21a05abe3394b08cf95e386c535ce86f37de079ee98132976bcddb50364b48618c20c3309f25570372e8f6c57e188af7640ff760c4c614d208ca7506cfcd38290eb9e630da5d5845b2ce471b57be424e42c36e733c56fedb6a2ab4e946bcc1e7dd0e334694f1ce693f8ba353e74bee3396e64ac2cf0f614483c7c5c76b9483e618c0b8a0d6dd8beb55d6e46e68c755ec0a944c8f7d91b4a311c8e0d6a29ec86a5017b887631a9d47bb04c9a3a41fba032782401575355429464affa480c17ca678d596d5666c4f3de1570acbcb7e0e0faa29b4e28ac616c8c564ac0df5e9dd098ae9ad42610980479d6bd82cc81c643020faddddece8a2886893d79997e23f6eac82f6ed8f33b91e5ba6d521ee276eb395da9371b0fe44857ba887103b22dd5a77cc904c2a94b5e0c0b9b7e17ab6a75cb15ae963aa2364d3d158c21f401b3ec4dd30a9dfe80d896590e13462bbee9c8ed947ca215482613129ae3c1749b0858bee3093c81d2172e4b1c2b01e9097a9b51024393a0676e30eed2b0670b735666ae656dfacbfc8b314dd9cf49c232c9b2b69515877ab4a6bf0338143b450d42eea0c3f334d99d72b926517fe45d3b0a9783b6b5187bbe7ef6c08c22cb906ec86acdb69205ff6a61788c0a7bc8cbbdd5f962ff32fa8b2d5dfff85449d4a88c7ddbc901b611127d13092aa0e6e9324bdb5673219883d69d866ec8c3a6f03453559f5e255cfc173a83dfc9296e3c33aa3243592d1ea4940e54237aa30bbc849aacb07d3c09cbc32b84aa8b4155ff4ab5aa96ea2e28a8564c50a2fe842d68306cfd7dfe1b1c64989807ae60377d6301574ab10211e85c8a2854002f27fba9103efe646db73cc8f86ffc6e2b607368c09c0acb2d64e102c0b5b6c3035665447962a4b8503ffa304ac10907e80521604da9611cea38d5b8a779ee0f3a44f42b81ef0fba45fc0d0b012480e95a7d00886dd291d401a80ae7f35b94896d02c7eb9e3d2239fa60a3e1845a518e022a495c0f1b81959b7a10c6360ca47dda742c1931c11dfe1e5d34588b1578a583db506cfdcb4c507a8af40f7ad1259a16a9ce145af9700d536c7cb99ef94507c3010180be540f6ec562b61cb16453fd6a4c6c610e7de3668e448f3839439f48bb565075c428943313de3a08b04797ac6882ceb3b61f72b7882c1f7416a7cd4baa29cfeac2d0382b2cb47c878acb2a374f3e578e7ec67ca828e436d2936a9cb4fdabae07c042c40813bc4ce99d06d3fe496c7f60a24b5281e0c196188a9bfc228e7682661a9239ec5cfccf6366c94c92f994598f49ba9b99ba46da2b8b95f5a1019a385c98e7a89d4957e56ec1e7b6945acab25a33972872409c816dbd7ff1b0764b0ef8f926c07bc03fab1c1756d36e466bba5229c9753b6e90fd8e546895b43dc942200c662788e168114aef7ba8ee9a48426bb82e874c0f862a3496e4040d8079ae7c25e4d24188a921e2d4b447071d8c4a3fd5ace6cde1885b61cc9290d0ab31ab33cb570e858a0e456b8760540692ebd09087af9618e4dbe06c1219418f40dc7727ec602fbae61eca793a119178a8e657ac73b7a4054559683abaf51c2370a3882435557ac54ea5016bf5081b509f9e8d4acd97f08a0cde7d988cfcc13ec4719984a79adbf1ab2c99902439abf5ac601ab85a6506961c2bff0109321da6bb550152614036403f36b4b201ef3a89ccf7e74fb9c8bdb85dc69c718ffd3819f595f47fb8e52a026643be284bec9f7b094f5500bcb44554235ea8a8660f189200bd26aa8dec22f54c140f185daa8bd4fcb746a75485be4538c789a42235472dcb44f27f90a38803b75ea6d2e823c3e1fc6ac12e502c12490d8a3e81178baca1af6a074618f211f9f666e7d3547e4a1f4ef28592f1a3e0438fc8010c0094dc262707702bd32b0850a09ede8c62fb12f3ef3f54a63bdd3ac71032907d8f0bfbac57a671b0ffc1449b28f79adfa2a4ca14f2831c84cb9c431d9e435872b87971300bdbcf3a766225ffc9281e937f236e3740c39ee985a933c572cf9a9db538c0ba187c34cf74b8ee40ad2252cf34f1e0d354254e286606885105d6d06f77ba52a446c5f6cff014cf14b18ab7e1cb2017d52023e87b011149674c51e7802ff2c353d57481ea848d249ee4783bf0bca1dc87442851697a23430e2d31f6c7f60f2dc3f184df8a9e05fedd344a48574cc16630632ec644831e09c03f76a3d2896004877080244dcd3905cf00aede1110f5817bb2879e660b990b4181c561afeb4cc873164300c89c8874967c947b6d4fa3d6c2d13b193704bc0deb52551d0b82f36049419fa2da62aa63cf6fe23fb00fc8324fd83e350aa867110cb6548455fba19a5353a0c7000b0234dd36c1a8682735b33600329e62e121fd8251a139a7ddc2f0a1ab017f5fb57de9155b76cbee405c96b8303672b8e52aeee5590fe6b2aca66b595ff829e7e909cdd19df4b70d47dedfca51519379a317fb5c13c69ee6b3198536d5c1d2b53f50224d38c9c50efef5d9c8c0e85d09e2507caecbd5865fc7bac70d2611a4355586213079cfe38dbcdfe59898db25f5154a4bd5fd42ff2bdaa896c794928e09501636638aadeb46ac7ceae64668e54aa5dc20aa68202e30520a5c58d382ff82aa4b1160370416537c483ae8a30a3c56d03fc34396d25dee22f1c5443515eeaa15f6a55089239d9d68402a0b264852d1525479484a2a2acca4310a83c622f037122b4dc52c10dcc14d5231cdec4905e394c0bee429340f045271938063703c41f70f9333bc920aed919fbfc521283f307f447ba38a6dc5ba32fc29216c48907cfe8fde0ef38b3b99221b2165c0e9b75a204b5d1d52de90db7cfab3ba2deffd10cc35de271aba1fed4b0a153f99bcf132654d5823153c27eb21abe7f52e2f316c4709891bf948a3c5cd29498a4f1d54e458eda18c1e0dc86163c8147628f154b50ed145f4499934d5bac1510f3f09810b8c42f7f433b7a4d453a7988167f554e8180ccaeb94545fa6b4611673d1669e0d7389bfb55436150c3b31d9fa1175aa757038dbf71c100c7ac97239a7fe36ac45e28b23646b16502c15864b56f54f3c8d784a7725058f6795944df2e9d37cb61627aefbe02d81fdd0302a52dc2563595bde74cc123d27483dbdf39920ebd5f6d7c3e7a766e315314071ea9e0d2103882e666feac3a080ba04c603c61d41b0607f539c9042363745bdfbb7b73d894b746a7310ab5446e51a6e4f29e391957f2dcfdea91d83e194fdbbe01293143f04e2a37d98db9adad7a18bb635b9e9897e091075f5740c39a33f74e38ec7f604e4449785a2532754c6419f4cbade9ecbdb29dd514417da6d75aacc8d6df0c9397505bda70f50035a8d9299e9d759efc1c89990b5ae230a7e29aa37111dd39394022fc55e22e4837c953c569902f8861650ae988d4d453ca4088ec35216f72694f2a85706d81e52be692876acdea7ff72966abeb7dcd6a803862cbd3845da2c2957403c1fc6b37ef828619c754ecf14a55477dd534aca89d4940bfca9895abb8870a18a085c34c240226c4891ffc068d6f5f84985a6a87e4c54986952ae5c18b411ada49542285b411c0780e4110b1871262cfe0324647ca51dc52c1c52c7b863aa72df21fab9f42a3089dfa5b0a4a79d35ca689ff93c03607d36226124882a8fd099f691a991fedf4c4dc3c759b7468669f84df734eb1b0384bdb71d485cb0d8928f8e3b96f55c6aca6755e6fd9dd4583f9aee55b8af8c05c6bc5e52686417383fc6cfe1144b08a9dc0a89ac0f9fd9f3e3684200e5328507314df32622568d94abfc3cebde601df82fc1771f802af3a496c9f2a5b7510df4eaf8b41ccb3f7eda2d0871e4f8c80d4dc137f7fc682e7197de0bb77f96a4ff29090bcd2b278b28f4c44a8dbc6adcfe466528a392f3ae6c07e1b51d1f3df6ed10bdb02e29c545def5577ccb221e89610a29d5575e41e53465f1e527b9377a2aeeef4c31a534b31490d347af3ddaf4230599b461d47c7b82959f6a8a6768fb2a76e2ccd75a3ecb4f38d8bfabb4736ffa52824f8bde209abf35a984555982b5ce7ebcc19bc7e34c04388b905a39becd499dc738aff4522b7e075e0e6d531aea9756b4c6d6f2b3d58f332686cdda9da3eea72e1615f35c6757bb7f034146ccdcae644a0937c64ae6bed9eff678cc9de948dfe75b26771cadd9410775ae0168ac7b603c4f5e12c55708e5cb6ceb4e563f1505ca8851007e16332c49a8570715943b4305e7b5b5a895f3983d1de1eaceefdab7facd635544bdac55131f1a62949ece54d59c8b6c4f6d945d80bd3cd9bf9c29c167abbe84754a65030f8b3c02115a70b70ee2c3ae2763c19751eb2b544ec7aa8263e56932c6dd5c502e815c173f26662c5af4a24b36dd04c9b8965dc0581909851e8d3fa0db16f6fc654bc49386565ee7a343af62fbc823b8c73f0ce838fb204928d2267dbe56dc83244385649cc26ffaa84c4d87f19933dfcc23f47f43fdaa7e38d307219c0d59b8daf7c3d79770584a4eb522c483cfd1e11c52e6b5e78dd6fcc3f3af630774083a91cf91ecd3731d696b57042342d759a6890fb95bf91c1c4c6fd7cf770e3a3e60c7596be0fb83199e469ae3f08802c3aa45c360f4bd4cf1ce5cdb28a0161d85b6162f73f669e67db9216f28b112cb2ad2f53584b5a2e0407db92abe8669b736724571a02f3f64e51ed5ba08ec041cf84bb4843cb1e368dfb729ac6fe8275e9b3a304da1444e26845bfa84411584ce2c97ba7328f32da048d451baec0f6066cd022176312751caee95044625c871524027e57c12c226818ad632560f727e93b4119e1c20210f6ac4a7202f477e6f41873e868409f0a70733ac35d92db66226663fb142972d522222b18e21375add85fa044d3f065eb900fa2f86003a8b70a23a2b8f0ebacbc88493351e3a0b755d706982fe98c0fc5b48766f283d44d62990eea8d0528e3d4311e63a2443c6858c079582accdb071269553a8842ef831085fbf3cf5d640e58f4129c335b36ac650e9ae944bf85021af5159d1c921ff184fd7d46547bf66a268e569454f00ce63c6848338d541554e09bf4d068a0f820f09eed024f81533466297a4560b850528b9f59b4ce9e269332011e2567937a500d7246525539819d0177fc1529620549c2f81e0befe095463dc16119be0095f7847f4ab19d199542538e062851054d956e4c938b65f4875cda6fea1bdaa26291912b561aa3f4cdaf21b1693c3bc574c36d3c394c131ce28d75034f69d4d533e5c9d0b2f171bbe94a4857f181f244c2393d8b093a8b4bedfb1f8543e38b370b63f245c354fa55849cc07a83eb406daa00c5b287adeac9feb24f509df5054bb0dec52032ed198a7dfbabe99b3d1dd10c4154aa18a5f89842297162d0b6204bc6ac6312e4083ad65e91d0aa121c64ecc2a84d04e834f7c2a94dd9cf196c9b869bb637bfce0df787f1bf63582002e3be917fc1ba13f4be59d3c0416ce22a553a44b5c89059c2ec272b35245b163278a48dc1fd8d4ac82b1668a449a493a70e85c05041c559295bb3700f4c7a193f4440848a8961c59a924d6d95d3b5825d3b91f98d48d36d712d698543d910008808a4880e5b6ae91622e2b81402759bf4ce28e13ddcdd255b408a9d04c5ec434dba54820d278c21d603d60f7d1f1e252d23346da826dff78ddc528ae093aa8c06b3f741814b1af9cee7ab8d542c4cc5c93cc1902cfe47d3212bfb61ebea639ae5b94496826753c7c63d3feef80bafc1ca606281efaff42f2f9ce2eabff74aba76aa5c82e6e47bf44fce96c564ec2e5b65babd17181aa0421507e01f5828f31e63874c275c5f99ad1dd284c9cff9af27f28289d056e18b7c06f3f5ea6645ebcc0d717d511ddcd23fa842b009082e6a8ee33419e6894717b2ac3e4a5c9b683d603bb02c51fc4029bbff7f37fa3056731466633ffcc5274518f51fda98e0ef72995b1dde6000054e144cdde2a85d4b456bf29e4a25f4e0257e2b084c262cbc45932bf7bd348c98c41fecf05b6bfdda7d8cb66067004a07486c46293a9ffe4d4a0cc4c7e3a7ee164f6892216567f7b10ae89387c8f9f70714394e796d9df7386c6d36cbb4ea7e2cb0cf447f03ad607bab5cb4445e7257f18b3a90c628333abf48dc789960d49f42461765102d9bcf1b90878b60c1bea8a0dd9cee97ebd39d5f53daf3929eb93c90697bdd038f6c2213b09c80f3fe24a911788868301312b928d5324409e8ddce1188893140f9b999ae83a1e78d903976796ff9a43056da72e4824c7bb256ab8e442ad341a89344731e3d6ddd386d55c62462fb439dd78fa27d50f4a25c9ba22fb69114c2dbbd0b24ef5d9108809d2794040a50654ca48123043d3c207dcaa991365ae1f176b3ff8faecd6f8c66be3227f23c7795c5b2faba518b1c915c9b950d7a678f15559c071f09936be71da62c4199677622b45cad87ca2df5a90e2eb4aa7748a15067432ea56182ca5152d6c6c4732c244d1724fdc33610f7e96161e059399a88732dc3f6766a7c3ee4e54abde105d0ce8c489ea31cefcd0e8494321098496a5a6abac5d743b57748fc71d393bc5db063ac79e9b63c5cae3e7059a25ebe487451a463b45c2859686a9857fdc189e224d32460f359e726fd4f178badc45030737632e359a630a61125b4d78b2ee671c78c2c0980e46499b7d6fdd1df2aa8c975f02c91eaf61d582921e441594fcf1a4c4b26f4876a10517202b332d7afcc1305d39af1af50a134e48a8ec05c80a89a19c5c2280c4c6595c088bec0f6b6d8a2b7773ffff5fa140fb12e9b6ba8c2ba3580528d86da0643d43082a58a379cfcae660ad4f485448290d6b2b8437bc51f824fc24ca064ad78db503d467faaf32ea35662f4aec10a0296bc344c9d59236e2e9330e9ee1c0b9d74709cedd0cbf5a743fd1c766fc9acb19cbec868f72aae868752e4b6c1eb0d8fc874b6fffe0e0426ad3c8858ce845395360ea98b4d0b0367afa289d1f55068037520015c59d90eb4763f766eb21fea8f61ffdbd8c31c69ef023c8ed11c33a715682f2edc551645d4ff44299e44cc2c0d90683c945affb330ef0f0e3996f847fe8b76814f41994b010fd028d1bae8175865e595fc9ae5f2654604e8dec12fa0345a566136c1566b331d942ad8ee005efd59317f3429ab5401d7267a042a82cdf6f47b72db8d2e21e0f9a094ab5a187f688771a6193208c0f254996466277669ee917713af2bc17b88475b73c16c5ab12009c2dd45f459436c3d3c924f63d607ec13310c0d02bf5a740ad2107f3c051585ffe231c4c628d79778137a7d43b98e863d9a39583521924f337b1fdad5d15246cfd1f39129070eb5c4a8e8f4be2e133d9d39dce2d898ee05c8a90c0e0cd6829c592dd3c06639e37813f05807bc82e984a8885706e9b2709af0b3512a031bcf1c360c2875f01be69465ad58e1b542aaae848dbf4c115ae910f805405ad90471ba1b1f0d7f51980af7d1a2333ba0b531226a2e746ab1789c7894f7246fcff9bdd10e0e9cc18cf600810cb91e90f7749a8c806d378f619f6419b5e656a51449821262ab75c7118d8a9e819ea9a78e17dd0e8c8a3e4c321da000448155b2637a04d36848af447508404b44af95069c586081d19ee10edd31e0ee4c4e37108e0b75ef34a503061d95f68f569d06d61596c0af833bd130f9c1b9c9640226e17a8c5966645b694b14ba0415c275448bcfd782ea5b6655ce2402564c6a760226e73e358a5d708c5a209dfa13015662890d3f8d4d0e238c395c97881ab813973f711883fa5ac33b81f968c855e90ba56dbb24655f86f0d6ca644d39e58f1897f7b0a7c529dccc056ec3f7a0e34a9d4b329eed791de6772506b77aeb8f86b16a15d6b60512bb285cf9c2d458e407b7251498b2ab89bc2125002c4a293ce810e6553ac697aae362a25a468d18d43338b63f070b174612c7a59c8876aa9f5f70a4cbb1235abdb33591a120aa31559fe83bdb9cebb2106a135c4d097aa4e356ea82d8ed56977c3c770b7388dd192d3f34fdcda673e710affb86309e29f1e47ced76c0dff9cef1d7af47ed07d6d25e81da59d64fc746e40a3930ed5486af262590e895a353f0c667be24d7b6c58832c7cde9aaf2fac2c90cf4b52841dc240873cd523dff8fa7c627c24bbdcaa8440c3235ccf52acca8966e383e2e12e372f740abc53dddd473fe4962e3169517090ca64fc65723f267cee197cfea497793990bf3d6dcf62a778b3e3b40164a7de8c8e8dabae04e2ea55c36f9e5d77da708d0e69ee7c4c64efd47c1a170e341a574d39211d9bd21188dae24b7d2524aac6df7932a0852766e187ca4c0401281316acedb230c87393b1d62d151783f0107af211f1713aeb145f7243b92d55849ea6a0c2d43c4d6b33ab68a8078a38c3d713b949116fe536c89a384095a5c717ed065265b1854aa17f8fa1b49db1e94f3c65b99be4329df60f783e5c9677bd64a2e1c2ef5600900b2b7faa02fac8cb3ee509c56c8f1d2d1d0ca6f6141781690ec1dcc63cf4a8de6655091d142a9b71aeb18426048535f68a1dfc1b4aadcfb19b5a069fabdded364f387eabad2eff0490e582c0e786496fbdd3ae9820eea2f799b05071d9f8b9dfd817d86e905bd6ca9187e081618c07dabe3122f73bdeebad1983c78aee5010bf4dd2214ea86c59e592874bac96c73a1ad3f61b2ff61be0df5b08c3021a1d46e729106cb6f3be8dac5a828a9c9bd20c597dbd6a5e376de33fa8c6aaff8250a297d91f9355519acdb024f0c06130449c8f3de38aaa0e235995968c282c588dce337c064e1cd0bd10747fb28270d2f736c899393962882e2f0e4709a9cca2d007039537f19c3c7518e6f65f798055821269d8fcb385b93f406dcd91a539c05e43514efb80d3bbbb4e3bb23370ea0ddb746c616f209b4f64e5d13dfa1d519806418bb13d39ade152900d0f9e724cac8253797dbb56655a69ce167239904fde385dcf12b9ddc20da969aef627a6299175a29223de4f8f63ab94eb209c3b1a87d0650a87a838c849a40ce71c904577a5ed97535cce8670cc28149656e7fe0d7ada0ae70d2994685d739747c9ae252eca9ca3747e6623317514f0c766176b15142d32689e18534719ea1550ac0315e9d12db3e2f2e1107224b86b83a5c1c66b9fbcb112ea7e21dbee403a421b0ff5020e25989dff4f89036d85568691ce16ccf7d81fea35e62419929427e01e61704dc2567198151aaceba97ffe523d5953322a281c16c422a6a8ae4aa113b19e0640919a4e5c8f840d750be11abcc73b75cde857e9d7b6429f49f06b11ec94152648ed7cba66dc91326bff046b3f717ac2cb3236d293b21d91e95537f3324f6c22c7c41fe19ae0b90c97aee4a224101a3b8fa85b5c4a2f4f857227fcd59484629625d3246bdbaa1724f6844c9d5f8b61d44a7cf7e9b826931938242b5c42669315512c3252459ba0d6331488fa9debe44c413fe6dc339db773e43002dc066c0281d321e16321fc903955b6857c8b2880deb7b008c8825905a28422f8c8a6f1dc8e848351a2dbf53c38e8fdee63f40ef1d6ffcc2c2956c56624c5e681f955fbc7f95b25da9b3e9e87517c274b88114f96a5f43661f598d62c732e8a8a8515912e45b9e672268ce4c84668ba6fea7a2c91a1639bc6a8dc32fa09daabde84671b2e62cd995022e4c9360194fc027f539b1f4f43133d90d95b343937bca095d0a1d8425c73f187575892bfbdaff52f4818ba6c55c875a758fa987fb2e0e2fce594e4311a02334f6ee3f132dff4d4878a8fcf3a153c71736db6e471a2d7b3eb8a8da0c26495ec92c12e3b031a7ff899d67cddd01856d4d294b0831a2155d4f894086b2c2452ce0172b56272b2be74ae8768448c36b75bea90f76388bc88bd8c7b49c889eba3b3647f53f8a7cdb285ae23a7c62c9b521b0a993a23aac58dd512dc8763805ae49af4b788a62ed96fdb7bc3245ef94f05b66afc5220d5007325f26f31bcd954b9d5727fc4b31d0326af32575e904d715843a550c8928af9b5d3fab8167191150abbc1b9946d46e149f76d5ce5504671601012769f851dd2cd0595d2a420bd3561a3234205bbbb29486f6330de5e1a3db3adfdc4e468d3da807e37de912cb4f22f02eb66fed67e4ab38a14318273539c4e2d0aa6915cdd6e0f4e3b04c760b817bd398ca66bb910f2624ad244fe0bf10dd368708f9f4e4ee4a08fcae279c93ba944b4910002ca472c2c13dda77ed6dbe3583c348f4dc192f919e7ff864e3087b0ac1bae6fe603247f1944153bccfb1fe052250017566a732bd5213531182f94b855e5cfd229480de1ee7373ac14fa6869589e604fd66b0895549fdc508a20c5906b188f6661605f205503e2fea483838b28844f778b226ab931f78c03c4e25e41bc06ba582c535fdf01fd6ef65dfc3064281b90706652000311994fe879d8ed6987e80504f2ff3f557ad521ba37f984b7ddcbeeabbcb12bb6cd80fc4df200aac85c41af952e5690af10b55f64befb343e9509e64410e5a6295d23c4cd4472a407381d1e96bbb9cee5d2cdf391003ab1c3ab7f959b2e13041dab2a1c846d7ebe405fafad0394bc459410379ee2076625bcb68b7c4a32facee6ebb5919820b41365944c6eea9be55c71db9ed74fe988141cfedb96095e7e94943e232d72c76f835cd0ad21a03862f9f8a5d5b9d467f5bcd93d39ebc3528a6272aee74d247acbedc52ed72aff1d4ef7ae4042a7753673d5d609f75c24cbf20e6b2a0a4edad9fa7658cc428705066b02c19a119dfce4e226595df7c546edac7161956110d515e157a556bb4d704709be5d0f20ab00409d57f2497fd6e85b5e12f90e0e287b54d78a5ce68af2ab4bcf23bfa1226856bc66755a38f1ef8bbf9e5c39afa9b26535de6ab412d6a4d88f7586931715d7201e8599afe49203d1aa9904926f1ddf068493b00748db58f19f5aa462b3f0da6534bfc06410e2bc45c9d5fcc2ddc018f1b08290ddc035eefc429f8517a8c2985fc2aa32e49d4bbad6b0d9addbd8aafb1241a6200ef21819896d7f3cb99cb247008ff37db1e353cca148f44cd524f700a3cff3be3820345631c6197808522a91455cc0297d092292fc7d510d16d10f9022ade1d77f29f6941a1e0e49275121212da94731cbfaa6ca657c53cb355ae3440cce71d7cade0e1e8e8e06313fe8afc567660ddc19a94b605bc969d2c1204222cceeb333a7b51eb32d49c05a501a81e7ec5ff684ad5fc6deed8c9ac5e0e5d42890653313eae6a16a6fcf635c318194e7cbdcd00fc657cd938f960735feb27994e7adc419103536d39f53734cc0d4b36c075712cd6e8dc52a52c3c66a1e10807da89e343865c115f313347b6497d17fcba2970b292e6375ee7951ea4a073aaf4fd76a7d1911e6b9cc2f09dbb49950229daa30e082c71e31d152fe953ecf03902f502f7fdec6e4e53f3e212ee31a5e2f5678541eefa7087b22086eb11fad9d805f178b2b98f828ca3856741c03289a01212ba0c741df7c8efa9d57bee12a738eff85f148bbebf47acc32a1f8e7dc9e841b4690b213c438374e76047776b1e03c977a711e98ce737f1913757bc3280798bc4d9f9fe7fc2357f3e44d5822fdac3069d04462f7d0b9aed0a19890e6653e44a4f2b8f999d36ed334a7c44621b04389a0fd82df9b51f140c3fb058f8cce355da744a38c4c04226eb02cb228d41e22f403afec12e958596134c35f231aded03b847a30fba96b310d59dc1adceab44256c8852c5a5533d3b9aa18b774443a9345df18352accdd27808fbcfb1ad1fd8c790a17c9bc32e9b59a59ce541916ceb0973e928da2526524bd7d027a8d1ad4cc643664f27927886a99f62126589219d88227b3573eaad358cc1ab1a622aaa528889b7eac81c1cce785a687a7fbecf163c23103ae76489fb4d75b25c9779b6d2e335243b102b6477494e95bcd87d460bb4db967a66b1697e15b379a694a1c1ae28f88af645a3bb53298ee3d39ebf303cd1a769e1088a33871a6d457e0e55c1b327844ac292240d5e4523db147775c665fb1ccaae3e42caceb9db3394740249787efa7ea80e08a47e9aacaf3e1a663f9f6313a8f398a9cb0d198f37c53b90a13d8dafeb0ccd6c414f4c0c6de4c90f2d1a3bcd9ea45a056d268f1807d97a8ec5313269c03284cda28475838e1cac2e44c0744ee46b7f6ce8b4649f53a27d9c32671393a4d695e438608622b3fecea6e31c22d578e4739e564f2755e8a988ad37412a9897cf14fc00c70b960847b4df075706b82f4f8d01f0ea8969a1948cfd8afd3b74318206de42ca1b228642558fbec668d22b68861dc48938efc39a954741feb783fefb48e0e2d14a66fbb2e6d9253179235da1c17b30f7c09bc6d8a4367c84b7d2c15e2daa9bd18151edd9db4b0fcdbb168cd9b1d7a7625bb20cc550bf2dd65b6800670705846d2f470d1b528371ca8a253d7486538277035b7b1668b9e93244e42316e1e4a35c0ed1c6e918a4c4d9236c95e5c647e46b9db47de5f6775d08c79b5f509e093fad57208ab71a18f5176ebf1d06aedd7acc0b746920adc04c9aaf7e8399e03ebe018c65a2a3ce6815986fc764169139e1944ea727bd000be3b5409ef9155aa6ca95878b4a505013192326367a81560d253f1b1847e5d96ff24eb5690ed9459d23b54e9a0f71e454f270b3a3fc7f82b8a4d1632260b85e2dc388d094606a80864df2dc5e331c0161f7c2a2da08765118c8a94562d6b3e519182cfaa5d04277185794059c3efe6eded4f03995c62b416832dbd3a547fd5eca31aa07e7b2e61630bcbd727393efa90d1bab6cbbbdc475fadfe9a44e7d7425ac1bf5893e781b2966b91fa6b5fda224cdc2020eac23455c354613dea54ea9317d7d129fbf3c9ea28cc93a01fdccd500e0363c3d7be7e1de7188e5ce1fe947e369ae05c9af08dce9e897c38412b306db97f9e9a4d06eddaa0eab77d743fed64f7ae8512489f3886d5470ce8ebd12577b1cb08be33740e599f765d3ab0a0dfa2f05a3f7ca69db9f5af3fc6aa288591d5554d5243b377c2277283d349820eb2bea7a5635e03b2ab86a1f0eb7eadc23b0276369eb092409eb9f63609e66992fc462d2e8d2e4e5e969260e672b70d10dcc83e864f666e6b7932ad3b1856b1f71f475a16b5cede7a24740d1fff06552bdc6518a6b44f1c9a0fea4865913250041e0a598b2ef80f39477fc27ec7494305ce0d0ee8cfcbd86b76ddee0cb76fb6cd40b3204e0fa7ae8222aa102448ce00153da7b2a60566dfb1ea930b661e89c0b0ba22de33e7ff30312960ede84fb1157afd55c87a43026b126f73f94ce991678c2f5c2d0e54e810c01ca41c2a72991003fe76b909a7bb85914d83ed7e07ca1f27bc9b5bf38570e02224fdb93f1efb1c11dda1195e0a18badffd7a40abf83ecd573067e4caa492c5afd0d932d1790d91cc70aa52b221726433c386ab67affb2bce09082e825643c1f9e904228318c1d9330bff6420b86630ed85d695758f9c5d4f1c08be8ee362fcd263e80341e67eb297c1496e34a0f4c2106adf0dcdacbd409032dedc0bbdec19fcc86f9f9b04270a280253a288be38382803ca21bcccc6b99bd0577045e2d4939ba9c9ab7c4f2b9c37d1195a2c82224e13f23f8e020951c80d5a751964b12ee4d66d0017b4700176f03f5e31f3857064f4ac51877354efd462d0eb0350615f9d326337a4f0a00f993e0392426a23f92f466d4f07b30531bfe883d5cc8f91fbc16a74427a22270b24ff8830698a02f22c6a2fc825ed720869bec328599f33f93eeee70c00be57e605d6eff003a31e0d6135b58d61c40534c4587e3b9165262e9fb706e196683b2c3cd1f00e53ce7f880eaa8255798e3ba719ca490bf124a009bf3134aedf6c383cc0cda3edc50eba91d649c603b729a9398fcb12fae2f9c938f9961714dd9943df520caaaf8c28b922075467dcdce22804fd587c1197232299b56be175ad9931297e8007a0c458aff5a7ceaa310b0f87ffa12e487985951c4870504464b3c4c1c2c4027de126d7e48d6d3720d46adc03b4aa40e7f8c6a0930b8b0855e70cd96ea56c115290f68bcd62d86f639aed98f0316426d47aee53710a050aa5ed04d2de5e52c7842013d321282e15cf421d4897bccc64283f7d008bf1a8e6365b039ccf301950d812b618eccf145649a68968e842005b5497efb504a969ebfcc428e6a534bc4aea38d9dc0e0917398384b55f31ec255f8b1a720f8728136d20a213c1bac934fd2c7e1f55456005ca370066aaa62aecde72fa843810f64b475b3d8d4340d7d00cec1cb211c53a82e5194ffe7c9884d09e79bcaf2406e821443d24eb3ed2c4994537e5c0ebf00fdd1dd582d00b1d6089995ddfcfc39bed692b21421a2d4398d6fede843baf9541f0e3e9a0cda0f7af98efd4c85b17b72ab56b5700b3694798c2317c30f38bcb63d52b8d9b41a4108290e52580524a242dd6a9588294ca0f02e1e952b3f3b6da8a136182ea294780a52c288ca74da9c7ea6b6bc19906b0efa74ce8be12d1b45dfec5900e4da2f07392ec26177c22ce4a14f17bb66757dc2130b052c03e9c86e442cb1fd8100fcafb1b09c177cae896b5981a552186c508345200cecb0b4a763a1eccfb6b47aaf3663cbff1fbdf7f396f2e9e962789ed2a516701b516c6c782b97ab42611b035dfd56fa664a5c654739e80351714e766296c51ebbb7ac4a3b449c6f51a5c0a559de16f16885ee81bde4f26f43b89841b2b72ae3b30ecc028395c7f3a9d893303ef854a4782241a55b8d16bce5d85cddd002a0485c85eaacb9c728100d001e30f7fac23757420ccac4e4969650ec32780f9bdbf5be43dec11399cbec60895889b2dd68df548dbdc30fa36f14a2d9c04ea1a3680235a3ed1cf0e9437acf941530b59d5e8483b0192876d598cec48e197e86048f23a3be2a36c08ce90aa30d7abeafb9347a49ee26261372457f4ebb999851a00e2e9ee833fdf97b0b52759a8f7b904c5f0f67ac54a85534f03741c8bceb272c941d39af1d95dab0406a406b771f0346fa7ab9dcc4b99262dea5a9981b669915aa140393da78c4b6cc20ca6f7e8f0b1acb55c3a8b3f814ee7853321a2fc2e112d2b30a878e16d741eda66c7344339ff9e04c6e5c023a0a1350f4a538fc27b3fe2308d72dacf59cdeeadb7fab63d38c12fdd11c6e8f0743759d5cc1452ca3f87f69bcf057f10a3cbdc5cdbf924446bdbd4cb7cbf548e4f52ba40bbb515333d74b8dd649a80209d4f618c03eb615101a5e48be1b40941859646dbc984b720026fa6e5b94303a0052f9c25c9c97ae9fae7f1f631b14710a73013bb73541675921b2875b002e5d498d08163e82a8978f6421f2193042179059a6f8cf9f3dc0a6c94ae674950b75fd733b8de98defb32dd307f9dd595bbe53f347c3df9ee350eb49f5676d1ee28fa17bcd73a543729331d6b9b2ca1128a324d2b257b33a0c44d183e00bd4df37883658395c1907a5a80542fdad5ea9f93bd1dc00ad0f38415054a18ee88a98f2b5256103d8af4c899cbc115289fe9bb4f05868896de610ad166828714ed12f0edce8ae84bb71b32df732b2917137936e6eb5c7b40ed0bbdb68400a4193bb5e0741661b429e63a228366070787fbd0c33cdac548a9c335e31c47cadc5a83c867d25ace75ffce4975ff9fa324bd9c7908405a0067eacd11a4e5acb9ecca70fbb544a24a9f368075e984737f6bb896c1c8969751815b254e23897536a8af2f890e156e914ea713a0b42b0f6ca40b82f2dc83461242700a44f6aac6a8701aa1ec783325d728cc062ab5f9d9e2394adae03759cfb6df5e01fdf32ad9ba3c1ba29694d6b1d8cc5f715922a0f4c5eb9b003f40b419293450b7e92eb064f51ee529f88f0ef22166d8afc76c62285d316979048cbdf68a881e8e57e87c7832ea0b0004ff8f1e1f9a568facc64af15ec08084a425695936d98b6edc8fd7f4c99cce997bc46ca5f59aa1f4a1162fee93838010bdd0bfdcc6ab2e25708cea2f0bc2e6d051f12063cd59474ace729c649112c8e626828185e2d8ae43b824935bc04d74f6f629b25ec667392bec135199e21a2183160ccef3d5545ca90fcc417442f8861d73e5cd2ec51ea8bd42b4addf8db68ea433385ee9f7a8255d2436f38501c30b838e42baa5c4bd892ead63ea69f453e17f1da5e3fdb1b4bc9779558773f6e9cc94caa8acc9ebef189227d48df91b2db96ef07b4070ebdfe76bdde7cbfbd8a2ae2808654c0c2f2c160ba6974f0693f6e7e4daf17cfabd8f2640740a4ca760064f28906b67074e7b07bfec361e3af49bb53ed9d15f40f27704bc5fc3805351e848522ec2fa942507ff92261f751318dc481c86b3db2b562b036ac8030990a9ebab2c7990a36ce435afc5d2c3b40506acac62647726d5293a07dbf4eb1d44dfdc6c8286cd333427806095398c1687d416eccfa2c7f9b04c33ff738205e55dd2aa5363e357075851bc158cda6f1cf2ccccea458e021b70c2ae5c2e0a04815e2130f32fb99e05b666e7ab53d2e6dfaaf36c3771ef4cacf3a135347f99fdfdbd555ab509e8f1b53c6cc24e19f00fdbdd8fcf8bdf537b3a940972a00db31ededad5f8082462ebeb02089c79e5b8dfdaa1b50c3f673fbb44ec12033357e6643fb24506402d29005057f3747fd64dee16c9c8dde565a5ccd310ad9a7efadbf86a8e4accd2139d94af6edb03c1081ee43d47a12ca3d3681e3b447c0ad3391ae947232e8c03ba2e4673c5a4b775adf247f03dbd7471d9041ef25dba3fb5987a29aa1dc75af71f4240a4590c69047d9fcbe7652754b92807f2f9f11dd6920170294d5d972aa31fa57659c621e4d1cde53bd8843e1b8d7b2217807c2eadcad9c504cf785247ede4df6720c487d6cb05599499fd154de7da7ef7cea4a956004f021d22723fa638cca959ca8b21ae02912982c8e8563112c8ab0ce25dccb95b4273568389373be0362ae1e00fd307dc3badfde659af377c5a70ae1f4837798ab369aad198af7a1e6a2312e8328ee21e61b8e2c2ecdfc47839fd91e6b71c9a9dd53de3e3d622a9748fc06cfc26ff671600ebbc79e81ffdb244a2e139d8dc26cbb1d59ca0bfcdb73c48717bb43386c3462dadce036646a870bd95a7e3a2759e6e2dbd0ddfa592f01d1fd5284495f3d4bb1c7c646e6ee590a22c5ad62212e9cba0311fd1fb150d4b13ed272fbd6e21e33165604c5a35c781609342fd2f336941e121dde1c0b925e3934de9d1601b8c23a2c728c557c47171e682f9794aa5d399d38ab5ad73b6ce8b5513658ff126040aa68ae8a37e2740a08fbedffc262378b63d246ef5d904c6d6c784c556cb80f6982001550fc7001cfb2d8991b49003ad37384bde7ba1aa1c281fdc5ab99b9c3a7f9649c3354df226f3e65f6c0c8fa167378b45489865fd703f8768ceee20930f98c4fe5a04c0de50c7fa5492d5545e913a5128c35ddaf037406f7888da3c41a4e2790f6704f3d6fb2392365e5936f98294e134fd434074d925c7a39837df65804c11ba437aeade4c9af1c3a24bc1e59f393d50e5f8481da17c38b5c033f63ac2128640323a3b68c49b1ed2b25a14cbf786e85317d4d7368693ce11361e0b69a150d500d125398b7a623c88fa946422cf092c887c9be2a65b398dd1b400672439d600e9b56d10e32073270257b8f63da75e34d9122902819a3d58bba886529acc8825b166158043b69be595baf2afa33adb4c555e5b06a544a9ba8e06e57d5283fb9ad84534374907cbaa8bfba8daa34f1046a7708cbeb120a132dd12a0670e915fcd4f7e8c71573b27f1d0bd8e4b164ceaeb5c0b1654e909d584e30f6112e8b391f710a0e9fc0da4231096d633338f2885312915db0a3bc47898e950431e921b4d248738dbca4291a3c0225155d84c45103d2c45a1435afae134808799c73354eca043524c77120898b73ec8cd9384f2ea61835c716e63e6d7d885062671fa4d28cd405105797a28c2706c09510122ccc149a6fdcf54aa54de92e509c834fd01a7f82f96eb251f3d3b30d6f6c337f7aef2b012471a0a1d38aee51fd9a96ce8bdf389053d1b8d1e929fd9529983c2d7ac86cbef6d2a832eaeb12a0541bb4c12a547657030b51f0ce4b56da06ebf0fe08d96d27fefe85a4a432d242d71c6779ed54fd3cf31047de2c66088820bd66549c634c7236f908f245dc42a066e360cff7b29af45eab3a947093c839c7ca3b64656beb10f879283de0924e826ded008a914e9422a087ef6216a22313d31c7d2d9f0e48d02e64127adafa843f01c07259541d31b755399eacff38912cf71de7c1e9582f0ca8d9cab14ff09b68fe00c970077dbcc318c87ebb2b1563607d19568eb7e2018cdb233f49c776d3da04d92324811818c933444a8195dfeadd75ac2c2026b9cb561527006cc959f8ac83b114fd52db2b8d34400b4b10bb67b7c13fde387aee6e2f90f0ccca20d9504535b0213daa49b4e11403b168c087ec4597ba8a491183b883f153a4d6de9714cdcb85e8c1dcc13c98362ec8d0549ca2efb4c94224163ce0405195db450c5ee088ca08ddde616fc9c0f63ad7742bc7afe9158be135e043b0217199ed72c913cb823884af44de3208377a8713ba1d9f6f44e93d30930d4c84eb4b45405693268cfd35539a3d541a7ac0adf72037c1a8b450e6bcd1ee330f082c8f9770e392ead87d31e493c53c6e4a1bd51a40e7b0b67ed7b045ba63eb2123c976d9c9386a8ef4872d8c84dec18abab58ca5c565d8ffd3f05f5a1efdc6d5c3491b1e72df4d4eca0482f42c331923371f95d7952e34ec13b99b0aef2340f6e0068e56362700a55469bf293678f16d39dda65c2ba8ab1becbeeb362a5fd222d5aa227f964901d17ac68683d295dc86ab2d0298d71529e6b241916d880567491d82467a7e5e9c0b2856b2b3a4468ddb9bff3f2bb69c614cc6cf3936f9c332c63b63222a70cc90c2babb45d4ace8c661fe1d4e6e4bf6d68d45998ef42cd0abeb4bcc02e8e86319008c7df10df8447a319467c6023e17ecedaff420523089b7d8d1553ba2731cc3a51a2391482f4bc3f85873279fe215c58ead04fbc9c35aa44810c9ef7ee246f70c68d4147a171be602a7365f3920215a3a09048c7fb8d5ee98ac635ddc3bc7847ea776df0353dc50d87fc6912b671ca5aae28a58bd719baf636bbe046f2f188387605556aaeae323ce17f300e56682e1941f3e305d7fb4aa670ef7c33d08cadb5c93d1164801f09d468e44ea6eb41883374c7d18bc6854ab9aee8b9df4836c6c42adb7587b0303e72587691eb9ef0f1a52c002845291070a21cbbdcfa1aeb32376c740efca2614ac9ce8c6220551a66b93932f0f50fa420320846338f479575244a0b07cd1e4ecdc3c0a379aa2db5741a9fb97edc6495e9f2fafa492c94d7af00188c8a09015d8912226b9517870892eb7d29c2495724b28991192b8d507222ada5547dbf42527fd5ae7428311f8124b66b04cfc5bae06707b48a560a9ccb7ea257a2d967d791f35f1a4a2057a35084e5eeb47ea4b77542884fd9e1661da11df80e1fac2aa9c833b1f280add502c2413bdf0289c4dd4fe7784286467aa49e8346f98b4bbff63b5793422eb538cf915dc40e04825c773fff66f296d6a31106076099a414f20e7afd81b14ba6eaf20cc6e4ad4dfbff048cffc219200da9873fa24830934ba8bbfbf83b7186fb13808d800089262457055c6985c7ba9fbde55fd3884453995fe0b2e6b82d9bd60a79d0cd64edebdcdbc6fd929921643cee2664e292cae1211124bc4a84a5e0f64a310f26566a2f52043225bd982562d3911fdda5d6d611032667ba02c5634d206a775a255a53a430a67b792ebf45d26703221275f9123af20abd4fc336996ed3480faf880245f8af185da71550249388d25567ca26bcd50137db2d4b30af51a06dd5c660d4e9fb6d9b492825b1460ddef4e8cf9bc017bb697c8cca2a2460ced55192a78e4bc1dc5da88633ba7f27d6d7b05e4f4aca0880ab27c19d6aee5870eaa5199d31254207892f1e7539b2c519f29503f50c4ece48a2b3a52852686dba76d4f7f1f02a3eeaffae62252aa584284efd5852698f195d5716fbcd20b19584ddfbdf6b61493602c36fa9a87c4ba388b692dea00a06279e01c5865d5075e0cbceffdccd0b1d62fc9c5602b32fec1205c27761c89453ad36321413d523c1ed9fd4425b5103e9c99613148b24643b33ca61cc830c454b874e8905c39c0b46edfbe47c62dd53452f36f0f565a8b66ddb5415d0ea06b37f8483c3a0ffcc1a70966a15f3c34bd5ddaf57242ec70b2c768987449c991f063f1292a16043f63e3dbcc4aa01e4bf4b857f9160243327e10ffc44e10e33ed3123a8cc1c334f409c8acbcda8490d83711619164a4d7219aad006aad41351642c325b0e52d5ef9bf9d202b1e4565ac33cf8a1bb351d7c486af8894b2c849f713d4581db3fd5c1186ffdbfc4532e168ae9cd4854fb53803a278e2efae9e2a4e5dbcafc8b73bb52e515bbf0aef4ae7de8365543137ed9cd508722f8834e59cd8ab5acf40dc7a83fad6b115997bfbbd152c64a7601db022eb3ccf179e7c88ae8033ce53ea12856ce255b871a836c73cd7d288e5d5c39108081aebb0092639c8557ae36845d53c2e96cc792b4c0106b94b9f8f8cbd915eb6fb3dbf82228f4a69d0b0880a5df4248077f0b425afe2de40ee8e997306e0a7041d659ad3b814b2fc3635230c93e221215cd711791e9241b5b544ed9fdd9f9f0fa28b61d84829662c310c1256c150ed652166416f12354652128bafbc8d8ff0c64d5d84154ce31f8d11c5ae5ae921ad6e57441a2e44b595c8d4162a6ffd515e2a7961258537a1be938287e5e6a1169d8e042b8ac02921953d1bc4c7368aef1293699295fddbcfb6771b568e574074ccdf5c6096e758d98e4eee175e1e15dd9135e5452e62e648090fdd498cdf342525719b07ee8d6dc6888cdd7c5053c05c79e9d40456b0bd1b7e9d45d8263d2e73cb11c79356522adfb62ce1d3d10aedcdf36cb17316bcf6ee29d4209b7a24ebb534b775edfc4585d37150cf03606b4211334e74413d01028ac5a214d5aa10b5a0ed7f5baa6bc270402848f930d10d004449f0242fae9734054ca14c22d40d57ed7e92a126050bac5f6bbc4a6d776e662af1e8856ce2760ae9e359da6534fd5132dd45d16c133a746d7569269db3162d37511e889d1497f1af7fca4218ebd173f1aea4ba3b7342ae3c95774c8154c03222250c5838c7651c18e27eb4520bad88139bc4051b0056f388ee66d5c206ffb53f86851eeae417754ce9b57b3cc74c18076632b1985b1b11368e0549dfb221a4ebd131d60bc82245cbcb75731b1c1592a46bce7f328d4de71abed21bd9115c11d633e3080296ad1c5a67308b173d89f9505511202eaa8a2147b742cadf1982824f98823800004aa36b6988b4628c667390f07b8fae18608d8c7dbda44b6969bf0a9aee90e809f1dd4c784ac16d5fd29ddb675bd850a82b6ae96933faaa3a8803bdac984bba1c1d140501757b8c12606b809b0ad45e0bfb6838954486a29e553b816a2c6a9136b7a7578dda8b6172961d348791eac5f8f376c63c155cb13e309f35cf281431507239f30d3cde665938ac48f5a1b4e18a35c88874a823a13c61d1c44024a4b60c04c3ff408d67a602f08df38412d7df634334c3fb42104be47e75a1bb941400c72bc2d8ac728c583c4915235a6d9fc9c574d91ac22585b942cf69bd83fee6c5476bac187b94fdf3fad472f23066356190c7b2e68143c6dcd2132c0851d9752efab0828b9081c8e2e173adf66ee96445b068a30e211e9cd01f104471b6a1751125ac4178cb614487d7a43604e2cd5ceb29fc824cec5251f568de8d17302cabc5cf47a5d0d0cab6bacdcf9d14887a9c9f922c3de357373e83c2178fe976a1a365b594c20ab1ab18f5f0c13b07d2c8be69945291f9220bef3754b55d340649959c3d911d4ef49f5c6f2f85a406aebe6565886c0b6b25e51b4745638553dc00d56b37803ee4113da61857ebd1ad1fc012f3f9fb0e1c676c49f7096dfabb8b1f53d03eae90a0592d881c8d3f8f058661fbb80d10d8669e9a10b30e86c9ae9949bb6aaad71e1fec235b810fe469b65a024e0d6b0b1ac84d11301d3026973e1c7bd173a9cbe7a73d8d669434df02d97894415b4302a323bbe7367d4825c1af1028487004de45b5b75ec77af3f5cfd5fb702a547d53814fabb8e57039c807f2d484bd2022edcb85e374d9eef2736f97e0343960b9f7da0a8de9f6db65d646f2143ec71f042905c702591899c8023c0543dc74164732c549ebab0d25b8da99d26a7bbebe146f2b7ec58df5ab0b4230b5383e4c412d802f37b0fd221dcd491ab8e9ff4a5a153be8c7b3d871c9585b6bb44ab2c3768d207b8886f36636afac441ea46a85715cb573f874e5d4fb47a90ec551323ae07b5265c9748d4e4e95f62bdfe34939d71f8d7597cca5752c7ebbca0ca85e5ff8caf0957db188795e56acb23b566c8fe8aad0bc60250cff5d675b1adb4d6b44332755d010a0bb21594b2fc51d497bd33e4539f859b8b60d1782e457b41270b31e78ce6f13e67e559a3952c93566a90493aacec5b12487c7586cdd0d159ee0ea3776ad50fa5f8cd27e59808872c5161b60487b32cf8bd251c0a0364db211b8ca76b8d8558e102eaaacb8a98d6bb4885f34636ef29ea2416920d969699a02aaed2699e3c3465f18ac2cc151d0ecf405189b6d781e87451bb76aff4102a9332ec022314968b0163e2b08a39a967743dd34579de202cc8b4ddeb442a73afa3935a2d20984c8077f3184f27768cd8cf6da2d67ce1ba91b10a6f14c4acfd8a0183e1ab06175bba9dc70a5d5b4942e6b4510f5107a4d7414e1a4a3b4214c2ba888615b30616d0310c10762b08690d588f3ad0ae92d9ba3a67464a6d8711c4698118514e9f41bb01b4cf94d430d3ff66e6956745e40aca11b4fdfb5474bb4ad2b087549b0ae54ae7f426b5a331f18ef00af89dcd6f5b0cc952c0c8d4b3afb60e2422a1593769220eb36549cec7e43367b51d3f7b36f8af1143253dee3695c69a52402df8bfa2e7f062a3c3871c15ae34edc92ca6cd4996e0a93533730232a953cbbf76a49a111af463425b87d9a057c89042d2a12e796e861bce2a3a64d44f8051484b17a1f84773b72124e368b3442f4bf3f83a5d5bc02ed574e3701a2673cb77d0d96c3de9b6c0106c5e26d7bfaa87c3761f59d7f318ab69110fc933b6104fa2cf127b22f0455622b30462a1a4d6137c347efde6e2a90f94481c275d23544745a75dd46ea84ac8a1460f055ab6dae395379ceb97791cdd09057ed676a07e11bb43f14748669c9a9e9df10b299a68c11286c552f9a9e230a19b5a82b4bf577e6df054f42ad9b52e34e64961efc94491e823bc35ab7c5011a3daa8daa9105554d11b396cffabdb0a64fb6c512481c51a03112dc5c262bb64dfdb9fab188ccfffebf7632f07dec99a15e69a679bc34f8b0ad4b43e46007854c9841df5c3777416583f002fd2138aede64484195195f2d87565ce933483df3ad94f5bfa8033da4f3041a591a09cd91bca84623f38a95b47e3d469bfd98ec70bd72169e65c9621c8db39db3e0c80af6a1de7b45c4c7e5f9501873f831998e2c89264b379ba9e1ae045a6282909d2757e5b75c7f087740db7188dce1ed8f6035372ff8067300692a3febcf001b24be9cf09ca4e70b3df0890deed4ee3ee34e9aa495d7f17812d5d12850764a2df6421f9ce741e968c909b417e05f074b07c16ff86a1a8e7993fecbeba9acf5b506e08089a14fa81144d0c8707a97fa310eeef266d112818820c011b9ea5367fb81bfe4acc5f028e211005895e44773399e0318116a66c2bfba9cdc341ac1b44cba5a44c315bf78b34bec292004e375bccbafa1b4d7d80ef78a3f0041070a6a2c5d7d3f9c3240ca3cd22d6a0f6216309f9a5e580d7333f83f3f3a37c825d6fb977b369e712c3e5a0e3986a92cf0f4f0aba7ce9043f641b042c828446c213e7574b618e3a24c0ad73cc751017264c036c1f2de71e8405bfe50283e9821476457584ef78028106f6cc953598f87090f19411f1bda68f373e373878f4edd96b6987101cc815fdfac6c1a5efce6c398fd853fb25d8ca1f8ac20367ab0c77b2452be15621ffe4ecf74e7953f4fc54ff2e6ef2b866a6d1fecfaf2ed69b6811addb8d5dfda298d64dd005da3bbab197951903c8b5500edea2110aa29b2bc5723f9259a9a98a6ba90f469769e4b8318bf50fa22a59ee107c0052115042cd68761336a96ae7202c046f99cb00f0c4ed8eb686a3a3672bc8deedae60d17462b69a4df2a14be64bc5824c2eaba082eff20eaacb818d826189a5f34b306be4cdb6fa6bd5866b846d6fa326a095e2d9b046f139168a5dab6ee017b8da051f8cc6883f79a1a1472eac7d778f8defaf5f53ca29b17275d7a45b7161f58a3542c96b75707333bac8f50699cc390f56d50dfa9d257e44037d3af148606ee20918860d485eb4220d7d331e235080a646e502f1115c99157c47cdd12ebf1403af57c3c27d4f29d2aac533f291cd1b9738de47005b132fbc343c053d1697ff5b225a4cfed01167e863ca834b1ddc9c8a168b089083edcf66c3ee3545fe0ed23f09f035fc8ac6240ac8eaa3c0465259f8ee8dbcadacfecd009af24f60234492615940e5ff5b2cdb576dc34f5c939e76e373977145bccc809a157eb7ff4f5a9cba62499111b8a759a91b86990a480476f6984ee95db5b0d429c1714f5d9111d1dc8bb54524e3c4f8e60be623065867b9b2d929504b91f8dbc889a887dd3d2bf3789ba524612f7ccbb33036cd5e01defd0a802d82d8348319db2292979ae30043f5e8463303a7566f425b120b160a78fe5e77c19aeeebaf2ad1bf1a7e19a9be460fbeaa2f6525a85e3f75e30eaf62c4dea73e96f268e9770c64db7fd17208c9d83e870f6285969a47e14fc5b53a30570793bb964cf10f3d3275a1206018f266e48e6567ec8d2862e538af0d7587b20c78075d78a17027fb6c12d3b4578ebc63f2bce684c5d88d024d6b4bf44841f4cf41fe0d90638139c3a8c61ffc9bd31cb891a37462381692ad665c012d93b733d6ca3544aa2cfd17d6f74a3679f5fb598732904f7657c313ace9f23dba5cfc0c06112b6b1c9d720c81403fccbb16902e8952c3fda93230428cb8cd4b5a60def33d02c34fa1f01420b58a12a58ed0f2c9f32fd719eaee7df5b395182c558c5dac152a9ed0d0554f19d88b2dbb5e2eea8d9e8af2d221305f105442e1ee4b34152d2345734ee8e700fb30f3cdbab2ada6400f907b428a09b7b86418d2d3cb31171fb395f5b848130cca798e8c46acab4848595ddbff2a0c54667be6c49cd8634b7881034d26e3e7995575033f6785dfb44c9f4e9c2898939800b716001a964aa956560a955148e4173def113bb25c04e4009c1f07b49c9b434b10a7b242c6a52245cc2033226bd911da2ae440236ddeed77cb188657e8cb464f66b5fe76eafe37ae894da4498f034d6dbd749056453a450faaccb80064704d7b1c389320a5ba584a6f24ab3e86716969dfd6707b67b6eabfe2a2ca77616e11e2fe05e35ef925c71f3d349d5dcd7aeee5cac0f1d45b77f72a4246c32884f6432d010d9b3d52333629ff49bc8e55f96a631e10e84815ea31a77b0442c5dcdd4ca47844099631735e757f5fb4991e680239217d732886357bc63d0480816d26989d6eb264c3d016c0714abf5160517448795fd56c1a4789f5e699360abe27d37174882faab4a62cce4fca2872d7fdbbcd7a7a29bf4c9ed5532f024bf1c0636e37517b715bc631f784d283c650c778801ba8b9d34a1b3ed89aed517a56b45166926e1412ea2b38d7861465f28a6e4fc32c402069dfc750c30de29b392c2fdf043e649c2b428bc162537d58aec9a4c0f3921890c01edeacf4f1e65b9f54d148bafc7cdd8338042daed3acd387701a9c824fb04a6ac587e30f846f0de1ba1c59aa2233acc7164536ee79913c2925af85b3a730d407214d81581545aba1025f73418b6492a5c2aea0c07755695e776efe1f46f6c6d0dcdbd0e4fc6cecade3395917b5b280551e39e62f6a8058f39aca927e347d7f9af7dd344d0f77e01118e43583dda1efc749c405ac0b4e4016df13f62883f8387962fd720f3afad76e6d43593d2c2bb1f547d2c98d4eba9e76933c9b90de774c5508de9389940a5dcb79a1b3890b39214087ee77ca3a9af2762c2f1de440ae057b4c036f967e6ea562c8cb9294f8dc9c8b1fa549c8fcca5714d2f46cbce23d012a235597d1055befb6528d8d096369611c11c39a16e698ad5c81b0264698bd838ddd299402370c9954b90a2c15c9cb4076a9a1715bbb9078199b9d2272398c8090cbcd9c6f0d574185670ed99402bcba31574b646bdb495c60a071f3497e5e7c98c013a6e371c5697663852c5caad40638679cb24dcd54e923169b5cb4e2b13b66b72b2baf0991b0fda97bacbce3010ca68e27b169933d46f8d9e10201d4b500c93e946c5671efe9699b2af929f85acde488f1e49dc575f4487d45cc2581c1b4a683b8f9d3a544eaefb73318175db0828ae8bdbcfc78fb8defa48533ecab681ad8a768769f43045ff83b942be006d8bbe95199d1d1b9d7ee14e2623a1e50b60960e94712c164e0a9bc85a3af430633a6722819720913ba6627f5a3fa3dbcea2f2bc0e7ffc9ac44561cf5a24acd7673295ee542ecd9f4c7b9fe5c65ae0d6bb5a8dff9f85d73c197597d7a80c94606c2af76ac991ae9d7c7ed363b80569d378d30b082ba881f18ac081a13743a02283b86eea640e3a03a14bc066dfccbf681d1f3b9cbeb16556c6717a08f892fbf1034db622ae1908cf4dec8574f88135fd9db6c971a6da8d256dacea7b0b6bb4568dbad839ac20ef3f7c463ed786eb54efcbde2fabaf8ca33b1594e474efaf0ffc55d3a79132430aa0edfdf8115a321389ee95a042a1d7c6ae9fe1cb36dd6e8a91ee243c0eedb3d03ea9af87164d77ecd450ef15a92478f76dae2bcb63f98848cd6c2c396df273b0c4431c3fc2d18cd3ce1a420d7417ea3ec13a7a017b87b89c8d310cde0682146271e55b402d7a31832d0cc22fb0f4c9fb0ddd7875734a40769d7ac128f1524021249040f890e35b11e71c0701f88cd818717482c1f4817f32169723376b17977f3be58188121939150421e06ec9a7062e0866be5a5d43e1e2c29bcf585941b5c729ab935a11f4d15e645aee9e13857e2241c9f11c067e7cf7cd2703a9de6ca884d3993bd4886249fcf94a1b03abc9a0113053bcc50e91d290dbf67b9462299f190bdf1c6ccf17b4ca0f7e9afbba143ac3e18ef44d5f1df68d9e2828c73b45554b837ff563364f8ac072e603a19f261fc8e6c08e40800d0a01b6ffa947673f7cf0936cb48692f429c9a241d322bcf94a1cd58af54d607a18e9a3547ac0d451d09d1415bdd5e92d63765a0196e7f2beec9883e9e2603cb83edad73a43cc283742e66bc0798d47c04fe9412d25c2a8c5b9b26f19e08a76bd3edf1264966b74dad7010818eec13919406c76d4ec09a625f516c8882cc81b63128b97e772e343d0b247a041aac8bb85c40981935076dfd727ab99e48c6251f1b4d46f92208e168c94019ca28ab84102988d4f1434ab3151c313221bb1c21055492e60a5adb3b0f28a3c7a7c580551202bfb2596bacb8c4302895d58ec5b6df5a6b2db4b4b449681329539201080b070c460b3b4332a53aa71fa9ce09b01554277b17bedb40d10b3f413c5a18b0d3ff953375c22376fa7b6b3e818fafcd27f061b852fee931f817fc07c1ef7fe14a993ab9705ddc13f8a4ef4e4f6fbdb4a7a7157faa2b40ac63c5d3ef5e81755c57a53a4464b3bb290ea57f5dd7a5514a5da8a30bd115e0498612715d1487e6501c4a04a5171e6b28114d290e2582ead02794886e8ae3c27571e54c6d2e1e5c71f2a9e1ab51356d16d6c8c015a7beae5e51776cdd476a310cff512896be764c97de210d613984556c67eecc9db94343c6c5f7ceacd55a14ea3fdbc92e709da91a0af0b0ea50227c5838cb0fb6896118864d6c661ff7181eadf7acef5efe1d6f77c7ef251e559ef5610d7b96eca6f5de8f19f6e6ac5847f7dff7d7de611d9695618d6157be2c1f64d0c4e6e7fd8d292f0cbb1ec3acebba2886cd39b19f13bbe89cd8959db735f7ddebbddbbf75f6d773b7ffcaee85bf8ff1c6baf72ef7dfedbeebcdee86fa598c639746cd2a9e7876dd45c9366cc5f46df494a66283dab0714bef7957e6cd5eec8e256a5da156e69057b181d5a652b7ef473f4a4dfbd2c546587bebc312a8621e337ff4c33a1c67de67f52fdc536a747457dc53b6ae72f537ac560c6b91b75ab2be6b84442ae5faa24b7aec7a8f893ec6ad8e87d1977e76343c5c3dacb57eccdc2ece5eecb7abfd8671dec57e87d1974497b46db77e7718feae91ad6a2f3b1cb418dfb63b96f2f625ef560fb7275dce535b090892ef33f02292ec651744e7fadf3522fa7a6948ef72a816ff4284ada7fa454d78ac2394c8dcf12199523c733aeefbb1b19b39a7d7ea87614f573cf6a251f4980b17c0cfbe4596b578d3bb30652edef42e9832d367efc2f42d4c0f5e29f1c8c362b162c56ba7d38a9187459fe613d691e193d38e4e21a6d3094f21a29a0ceba0d434854c0cebee98fe9ae434c162b09c2639394dda66c57727d3f652575c99473f56fb232a679fb31b4fcdcf7e7bc94ea6ab2fd3a97ef631b33e8eff5e4ed17bf62b6ee752f638441885da5e5e64ec1f857aad6f66add67adf643ffecbb5c1c35aabb528d4ff587372727272784e6ea282dd6a5141af4c2b3ed419bb9087d485b01609919ea5cb9e85e5b33f5d29531966b9a58bb1a7da578a756c9695ab0e91773a508dd35ea46118765117a25cddeacb4c4dcba5702a2e850be9b8144ec5a570211d97c2a578992e3d666afee4f05837d18642d9d93a33355ffbcd4a989e376caf89aeefbc6f51adaf75376c5fbfc773dfbd9cefbdd4be6217fe34ed658f2bdd44e56da250d662376c8f7dcdb2ac62ee5651045cc8a5b03e1af23ccff35efa10446f481f6ee0f06e78f2060eef7a466e5eb4bf5d377beecadc5d23f6ab65850ecd2a2ed4d9078cc343cf0bbaa1735bdc6f2f5f1b69ae78945fadcfae8547955f0debb0f07f864755d3bf71a36be0b08eecbbefaeb126bbd132e88d96512ba67d8cdf50ffbadccc62a611fbd873b773955cbd01bbd757eeaf3c25674ba81b9d77377472d6156a650e79952c947153f1f0fbbef0d857f6d848fee57d7dd215d5bfaa763faf71d0813dcd1bd6918d54870de3b126c31d03accb92a816b496422076a04a7904a2d434c69be79b0118dd7a4af3f494a692d35368f3f494a692d3539a27c6e987d96bf87a22d8f9b57e53e929419f7f425b73d26933a0d6afd8e94f21b5562153a7a351311ad8d4916f55aae3abfad49a42ae2be8aa780ad97eeb526075606fe5f9500cc92bb27402858d95395f552c6dfdca91ae14b59b65d53b1cbaeaa9faa28bf254fdeadb6bfad12dfd774f2fba2ca1e9256bcfd2239f64edab76577ce9827fbaa867b92c368bd36e7d7b57fce882ff5dd48b2e8b97dd0d1de9b608b25881aaae5def966ef594f62c17e529ed4da7bf217b6d7a46481fe3dd9feef72c5754b2e122e9495756d58c171b3cb4fe9eea0d5f42eabd5e76d785bb1ace3b12588ee3aa58cad1e76edcb01ce70367378eb3df5b6edb3c0f8f32e847d593464f227d292ce1917b121e559d8747f8c68d1b374a7d3931e79ca3e95d231642a0cea8b3a08e86fd65fdf439fa917b165cf55854e15a7bb008b008b008b008ac033fe79c9d3549575743a3759eb5df755e37124d37953ecebee6262ff9e724ecb23e3ae2bafecfd37e0a9942a69029040a77f78d5e94d2efb8cbeaeee6baf720dcfbd5a1711ec771bf65ed35f7319e8ddb97f230cfb6d92f7b1fc287f0217c88ce3121e69cb3b330cb12592f2a6157e98e36d7d0884a2251e9636649fbeeead84a2391e84ba5d2775a271a75255357d2b0cb7ace492311374da5e79c34d25e84fd65fdec91e8f338131e4b4ef2918bdcfae71dae1ee2f1a516a9456a11d993d180ce39a78e117bfa3f2cccdab72cce7aced6d235b3d7ec1d6daea1e12cc7d98f99561b5d1d9bed38eead1dd91f69cd8d18b03da7711f3747ff7dd8393c02c182e68b9ba4d1f6a3c8729df6f3b7db4a5a8696553c5a43dcdd45de595554431324e2beec45df8bb8d12644bdf43ce846ba3c926c9d64947d4fe9293d450beeeed4fb5a43b34995ecf9542dea9a2dede826eaeebd6e6969c9b62f20b2743a5522a79aa4d4273cd6e4d3772552aa479cea915ae4542a9dbe964aa78f99a7d3c9542afde9747a5b427d8c9b4e2816564ffe2e0b75faef2b5d174b372a145d6fa14e2ca6121e512429c2a3cae2fa1fae456a915aa416a945648f06e46b68268e3575587e9c3933c7d6d0605644b2a4b756644da21f4bdfd8ea478d488fc9a6d853162daba3cbf4d991c8623f854c2153c814328598ba1ed1416d857695166aa19e52ba4adfe8fad2e84bdef7fd4812623995462716db493c534fe9293da5a7f4949163506c0d4d27e926562b71fab197f492565243233b09a993643f7e23d18f358faeff4c3fda90bf1f8df0a8cadfd34f74c2168ba9446a25ada495b4128b39c1e27edb30ac86067b12e9411dec4947e8f891b12691bedbc2ea63d645d2eaf55b66758f996a6848df833aa48f99248cf4a6abc3235912097b13e94d98e963dc923ec6dffe58fa0f7b169975bd65fafefb302db3584c2512b6bdf51ed6711b1eb5ac5e1858c485c1225a86e53d9811be1a9a91f4a14a5fa3d175f9f0492aa3b63fcaa0a01b3726e94777b435349ff4e1935548a31169f4a4cbf33e19f4a3ea59de449ff42c7f7ad4951e9ef0f83d8b156193e595da7e1ebe71a3655c376edc3035a633bfaeebba2feb3a55d7d05de38c5c7f9cd1d2d232baefa6fdbeafb3578727fa3e6bbbafe4fdf58944789c913beaf42361d18f44dfb778b7a565742d2d2d35a2be80e08d4674348978a311f5e69091a88e467f8d3e668eee38bfaba31bd9d1e81bfd777df61b95ec8f246a62f97e8b3ab1f4554b789440cd48c2de1432854c2153c814426b448e3d21496e1064e9e4083b793ee82f33f6f27fdbfabaaeef3dc847ffea18b3b764f67df4c2fea2d8cb6e01d66b347363cdf59767ad7d0f627d888e4e64edf5def7ded5d67e8c8bfabbcec3238f697fe4314522ec51cfc3230fdb9146dad3efae0fc1591db6ace111977c889651f2b02d0ef3a159ed24590d4dd649ba0986619da4f6926adf62ef89de72189e5d873117618b8d80e05a4989c3b2506f3c48adf5c683d4ac560f526badb53e8f4ef4e366472edf5fa96bbb5ee451cb4d1fc287a0f4473b3fabf3b3ffec2b910c9359764939e59435c926e56759dd21528f90f231ec7fac47268661daff7569ffc25fd9cf6ceb798c914c231bca0e8fa2d247328d6c97b18c300c63c1be34c25e6431d1db7f6c546241b168f1efc207e01f00ff31fcbfb8ff30dc7f7cffef9532f5787cc105ec028f2f2d308847150bbc028f210a9ff0f82cd8844ba41126b29fd7593db9c4bde01d15dad50eeababb83bab6b275dd5f5750d7752dd4759d8575d68fee7d57b78ab579bdcd26a7dd4e522fdc534a5ce7d80fcd542a952aa333cbb22c0b3858cf9096613dd9bf621850fdb8772a0e0c2f4eb906e58c2728fb63dd0da69cf14061fbc78c87c542616330511e09e342cbbc39b169032f3295410816acd7882ae5133718419676d63a5a1845b0a3f49199991788fdceb27c22073ac8b3b12c9990024fbbbbbf9043d40877e13c2561789022100c60c0ce94fccb27d3dfa89458b0ee65f9ddede0e2cf14456dced103a0668a7e8c8f94602f1c5fd197b1315da06065244c67fa3bf0d02e15e8147d4d6b17d9a9713492725c71292063f490315a78489fa22e9f09834dbed8e4e4662a0456ce54aa7a20b0de3e01ecadeb670264aeabbaee2eb060bdb1023cf48721841dbb0132e59f841b26648f828e0d19c3815c0fd8bec16de3a10c55b48d6be1099b7c214a2412684b69f0811de5131759c35a14eac3f089dcc1c3b1eef8aaee9e3936144437d5344cf343d46cc878488390751e3051c335666a3e0d50b0955a52d8e48be5726fd657d7a9fc6abd4e978e45549fcbfdd8f3204414e9e25cee16509ff3d043fad708fb32459f4a2a25fd279428226754f6d8d05eb210f12004151eca5438d2e45a31ca432ac4ccc29271881f2764200a233af0849a22aeaca0063727200213461045d684ec5cf61953c39dc80f56e0408a2a8d7a77ccdd9faba18938d95470a54e9bccdd515f03298664428022fb4bff4a85d64025022a3b70420a2e20048abff4af338630b142124d90b284921a1c0635647fe95ffd5153babe63ee4db23bf516c47858c31f0797010544488282215670425480952024410a251cc10344447f1925bb37398194ec2cd9a992ecee58f5c73d3109a8a1005f8d9ffdbd053a88a20877275480f2294b1d4471816cb3d4411425c8232a8f28ccaf2768b063258a0e3690852a60c0bf5a2218c10a38508acc400949a612ae60831a08e1491349f84bff4a831386f4c002527652d033033984234ea640450533c0c204a87cc008422cb0842d7cc0ab0c3204aa00240a124c5901139888e3fb57d761842296a0b3030b746003a27b538941cd06a01841859f2638018324a2a4c1146ca258810a186840c8cde6990725650648b84205144b041125144f34d0840c8e38e1048b2532909a029020d1af9438b0b24448f40b2a11e709a2b0c00e15a0b0a181018a2b5441fcb17ac1169e80018af8e3540471628b4a01c5055c20fe08a30871c245040543b002c6cd7b3911a209544420fa955718810ac4ad727ee90a6a20ce4b7319e181186441fc31a3080115a274028c765e1936441c11ddfa40901516883f4225a0608214e7a54909c9a006e28fbe4142e49a9872a5e3e615c0d0077c3c6ede141443e011fd4a71fbb8797b054010018fe8170148889be5e685e161018e28094d8e0c897e5542e2369a4264904304f1c796030b20f183f4e35132c0c447f40b0314712b71f3d2502be0407102f14748832b3e2a2131032e4e4c9d003dda4116763084e8575a4104e2c6c2cd3b8b48c1c647f42b738044dc6ac52eebc4a29fb0840d8444bf310c117f7853276c72ba4c67a20851e088349a124cb0117fc020710429349814f147c905e2c4d209c0440c7e8e88dbe4e6955150208423ca1e08d98290d81dd8800a7a44bfaa24e27659179dded2bab27e230cc1e446f4db6203e20fef6ec17c7007d461210416d1236588af4620ac972d7377ad41c743ea3f68645a838e653d66fdc4b2655c4f6f0d39997e0d381e52ab06225a06c513d760ed4adcabc8bf550cd690b93e0e32575c93b15993698dd50d85943f2dfcc5ccc9c971e99edb327f0e8fa81e2dfba14a8c50023c351f0815e59f207b7272727272729e60fd25add712361cd429ae47ea114a2f6a51eb713ca93ed6932718fd51fa5c14ff703f5f2e1516d6cf365aeb86476b51ff148f2fb5482592e97707cd26b44d2d528b34c1fa4b5abb460982a1b261fdac56948b9d296feb9aa1eac6cccfead090452714a4e3608e83391edb7fab8e471e37e14ccda7d7093e84132c3a31b77cb0c917dbf4562de92599f519a697124a954cd50c4fcd2e0ad64b4a5a4914acbfa4d5e7084116b7753675a60e67c96d7bcba94c211e3485c8fc70db8da1af5df9a4ca145225c852b9bc333cc466507a518b5a957acbf0b7ee85c75665da564bcba0f8059ea516dbd2d232030ad65fd2aa6ac2265f58d943e8f2cbddb25eb3f07861cde31ee3217dfada55cd147dbf33d509d94a694fe90174b73be6986342567ae8d86551cb2d1a6cd9330c078eacde50cdf0c2b8dd14e18d296415cb7b7cd5dec302773c6c4b761e5f8c12b35808616bc7c3f916913c2340b3a3b20b4d065e048be801f44f1a2cc1225a46c7cc20e68f7c8d351613ac7fae168f5503ae6435aa83ceb0205895ca47e5a3f259a2ca2a5f6136c424a086d74afe45b8ea42a9031f6a2951e2097bfdf8e112db3233367ce868d74a7ac9a892990152924476ad6402c1f99086826dd32c0d7034fb010eac8eac25c37eb084d591b5645ccfe832dca2699a1318d5341c50ebc5894dd396d834aab5ccd85a549ad6d22233261b17bad86a61497bac4dc7ea21d85106e1080ab29058659afdaddb66566659aaefce7851f98a7e2fb2c7ca4c2dcb07f6fa51f58284c5f1430e2076f8eafbf93c7af8ead3722ccdca81e3872adaf74d2196e5759a14b28e5a3f4d3467fdd880fb8a6dda73cd5dae6f781e0f3caf096a492a3ca89ed7d9c056cffb1b2da3caa01b5502498fc3be8e16beb1550cd30c0aaa0fbba9d3edd8de2a6725c55640b11da06c0a6cafb4c7368b6edbfb6a7c41cdd62c0fc22ccbba964359995f5436f9a2c5f859725bbd84e0a435ec1242125647c5324fbb2e0f7bec6a1fe2eaacce92f472725d9e733db156bdb2aec392a857d6753e44cbc81ce7ca2e09c587a89ddf7417d6b096e1b14aa086fe6771ae99603e0eecc2f0ac340732639a85e1da978b6283b02b737703aba3be1544c557425da587acf8ea8a76ad979d86555c8bccdeeace8eedf2e8b183470f1f8ae58062583d02f3699b1ebeba81ed7eebb120becab69cad166919593d82655807e5d9403a482dd232dadaea0e8bb6d97afa499eeda3d10bfbb699b55a8b42fd872136315c8bb40cb7e17436f962c482f27cef6922bfc5a655ae32d119664b44b0a30b4d17ebc84ccdafd5855c8889d5a1bd9547eb48b68ef80a3bc2571b8fafba24beca96584af8aabb975db6b110d2305804f61f07f230c87f1cc8575c90a4161332530b2402c5857e3c88896d21afe2436ec5af3815d3062c02dcf1d5681dc9425ec5ad8045b010722117da7eb42cb0081655b0a0ed023cf966e984084182f0c3c9efe5b790878d1b53acbbc6927a93deb2df26e75de3da01c1d68a9a5da7c4e7ed5f84beea7e3e0cd58c173cd6642fbbad352bebc770ccb430774b1785f2954b6a754da865f5773db0d7771e650fca57d9cfef94b0edab7e4b7bcafdc4161e6b6ac4cc4f80af3acfee5e761aa60cb07210b38a2ab2b55d3953978f3cdcc29b6b50f8beeffb3ceffbbeeff36c70e3924118a5524a2a3fcb42f308d14ed242ae536bf59aa7795aa856a1eb9a3f956821da533e4f443b1cbaf7be5e0d97aee9b6e8966226aa74555923bde88ede74495fbaa316ebad73d6176b45d5ef9b1f33bf7f11c26821212121ceb72b6c488c6dd341b0bee91c5f555c7fd69f3a351948a5ddc7784e4e4ece2867341a8d724c2552d7c77a241a8d46a3910b0b0bc631c2230a8ff631131eeb09b360d2736fafcc9e9a3f33edb71719c3e17bd1dbdb5966da276d1a07d5f145bebe6dae9fd7f59788fbcbbee87e72acf34318d755cdf0b07aaadf92fcebc12567b49c41a545d532e352b5cca0542a66c9255a66b478dfcfaf7e9deb36392f7bed3fcdfb6e46cb6731e0b1a2509f09c59fcc1ed38fb3a74da7d9235d33610f7e8e35ec82c964d23493f62e5c543699344d33cd2cfad14da22ac2a6d39baa757afad764729a4c66cf6492d16ed2ef8ec9ec99432b98cc254acc254c7a86e612263d7389127309939e212673099315b76d662a14ab45fdcd0b8eadfb444197e984639b530ce7cdcdcdcd8aef9b1558ce94ec39e79cb387490f931e263d4c7a98b0b8a9083d2d3d2d3d2d3d2d5f774fcbf7bdecfafb66f7d6f774b2470ec1783fce68b12ea6b25a627c65759ff52d96d5f359aa9618abe5fb64c682e8dcdd50bfdfaa1f6645a13e138a3fe92c5538c6bef573fee83fb1aeff75af8d33f2e8fd7cfadbb8fdfcefcec896c558ab5887c48f692ddf626d2db3add73c778743f6d877f7fa0d933130e9ee8d3faeb7707dec6a35ab32464f4b4f4b4f4b4f4b4f8bd71c934dbea8d611f4c824e2012577b1039f3c493776b48e583abeca466b489ed6916c84843922613697ef5fe4fa998647ef31000162c4905f842a1765cfb27b77b99bfdd6d55fbb41746e1c0402be5f76de2d964401fb8ae17ab5a05dbc53f3356d34addb32c63cc2c36935b68ec85085d57c5eb039143b86399430ed2243a7fc3dcc3ecafe52862919c369f5d0c7b087073d02999a2f1b0579764aa6e68beacfd946f2943012e8dc3e2f110f1788e2a1cc3300b1f3df4553d84bc757a3fcb1217f6c4898cef31b206b36ca9f2c444b97b640a7e64f1407f2942d24cf1f4579ce4085bd76b2d0351460c3431f5764e92da5bb548bea3cd33fc8c0e69801886d39e424102dc18ed582e2ab118674e9b2e64afdc543577938ef106bf10c1bb07cc0e63c942f654abe548dd666d9c494dc58aaa44f0c28bd3488b5e88b0aca08d0dc4432c53c684dae992d059f2ce3a5fccd5fa66b50dd1f34ec80093ea20c969d2122322e126f9f7f613e3a432c5f62611d430a6c120be365474386971d8d193ec6fd67dbdee774ff20be2aaad842a6ef39f44f1e7f1cc90fd0617d8c18bf5977ec9fbcc3579e9b65080a421bed82e82a4477d5cd9490b344c421c64f6cad5faf925d5ac92ea9001f48f60e72cac95e7222eedfa49f6428d9a3646fa01f8bcb5ecadea24545c38faa2ce3c7972948dcbd5a1758ef96992e319e9a4f5f0057a6c21b800b801bc36d71150003bed7c6f5c1c3f92f5c1c2e5a5c203c9c0fde1d978787f3575cd46d9bdb40e69b6ee37838bf349f347f747b8887f345b7ed6d227d44f374925ee2a1121ece6ed24f1acafc96fb9e9a4fc355796abe4ac60d9e613cbd303ec6c5e00c303038c3d73cc30c327c15a897e5134a64215b3a1e0ef18ad8cfa3f338cf74a93cb9fa95b23efcfe1f7c15806f007c7f0f7197017cc7f0fd7dc4572fbebf8ff0150cdff8fb3b89afeefff7b712be7ae1fbbbc7572e7c7f37f1958befef27be6af1fd0dc557e0378befef28be5af1fdfd03e4abd3f7b37c9bbe4b557c459a2ede148ef0b1b1b1e9018ed8d26708231ab011fbddc657a3ef7720be127ddbeff720befadefb7ecff155f7fdaee32beefb7d88eff88a88af8e60dff2fd3da60b0ddf740a121bb15fc6cffe2dbc3207e0caacba526cb9529471a548c395620c57e617576618aeccf8ca7cafcc7f657ee1caecc295b9c595199479c595192573eacaece27a1e75b69e4f57e64ce64d66128be7ee76f6aea492bf7b6500dc9a07900a2f0e0ffb03707ff0b01f00b707703b88a7fa63b89dd330dc1ee261ef7848c4c3231e1ee161bf0bd7c56d711fbcad048bdb3d2b50b7a178d87fbaede3613fcbed1f0f8148b7a9886e57b96de5bb7d850ab77120d76f3c0ce2389e735de7e698a97e1a6e8f99ea575d1957ce94cff8e0e1e7b6c9b4b6080a9de04093dc6ec35c523b1e279e04218faf052b798491dbf3f8e2e2287b7c89af787c259de80094dcef497c4591c836c823975b763878762ca3832538c9dd7f7926124bb2636f04fb5d4d59f2c00643d9414a4d41367ed8e1ab99fb697e7263385354218f12c80ed9d8d8d88848a49327c0208f52688aa06e275480ba7198d963dc47007ea39006b87971da70a312e78fa46bb40e307fecb29430467cd370f072105d45b7838bfe21a59a91fad7cd716f2e900cbc8813cb99baa962c5363a1e6e762ce94129f52cc3b586d56c142c0f5f8d75071d424d17f0022f0cee30a7bbbf8fece74b118cc015011ad6cb540cc68e9e4c1f83e121787d0f715ef0c2323b664aac57150e553b5da6c5a18ef16cf2c5fc0b9c18dc617bec7bd0fec23eaed71ec33e90cc5cafbd0f5162d87505a143e77e1ea458bf7db6772753bf6b7b2703645e5fb10bcec73efb1eaeafd847fdeb33ecc34726c51f3ca4f643395398a85d2966578af54a11bb52bcea4cd11c188787ee34c9265f8cd60673174a7ff0f07a7ab759757048982312e6657ef3f4917cb90d7d8f881dfde9fd471974c200f7352206467fc220865958300d120c9b316e61a2e539a6cb88fb1196339563a6ae211c1e11eb0389f53e46cfbd0fd19fbe7f87d1733f33c220f62c169e1161700796a70f627886058f7e3e3853e7c95b81ada70b625895305d034b1ebd2c5fb68baa53971c9d5e8a1b9ee19e8645f452cc6e6d4ebb9eb38b65d9d10065462ff30ccbc7b8ecb6a7a1cffd866746cf8269e68fb2263a81f57388dc052b9691e22d81b521e3ef2baca3b139d71d76ad067277e00e9e37d33d58473fc3fd08d320a94f635930cdf7a3af094287cef5799022cb63d735903b19968f718d05ab1a28c33d0f52e4b00f24f57dd0e7be8711f6315ff4313efa19fa230c6a3f7a29cecc3ffde87b38fd08fb4032337a96f741fad3f7c0f2a637611fa36779296257d340de46178c40103a74c69e07299a3e0234b497313d28437a900729921eec21861d183cb111473ffacc949d9e05c4bef452245d10c3e00ea4377d0fa32f611fa51fbd09fb403253fad1fb303de9a5c8722a99462491e54ad174a558ba52245d298ebee299f9a2c72e9667886e8ea12b36f992a2e84a11c72d817dc12a0faf97a109db3faab89fa1cf61b0be1467e683d74bf17f0afbaaeb477bd52b03a13fdfda6409c30faee67211148b93af03cc972d3c757de807f0bffe5152891eb293710ccad46d7be9bf43c2f4d63aa3ed7690a28de2e6fa1ddf1209f392afefb143390eab66eaaa3153d7cffb326566ea7aede2b015b352d8510ea956d75fbfe37a967c3da5225fd7f5270963fdf52c12c6e2581ad8aeef6bbc9fe1de7beb3d4c83c4c233dd7f9886a6e6c3ff1dd305b4de7b295edf63ba80160677e0fefb1ebaf7b00fefbbffb00f2433de7718a41d95a2d8f4e3ae4b5ea8be2c3cdacbea9fe13e7b17b4dec7f60e36de613ef733f3b9b7de07120bcfcce7de07128a67367f1fdc4bbe5e3cbc2d7a29b0d64bc6c144f0f2ed74e1bcef0beee0ef3d48f18cbf076e7f41fafd18a811ed7717a4ef8f811a91a32ffa1a8ac11db8ef7e86fbeee977980609c533f62d06351a7f8efb1aee7e1e55a036dfc67401350ceee03df73d7cdf611fd807920dcff47fdffbf0f730a8bd14bda7dae7f9a87ca80f7765d39001e2df7f9d6028d377a18414e97727836150c67a7026861d18e8a00af13282bd8dc28ed2e79257b0df6c1436c7749199fea723615e727d4a5133458dd4975d0f2e566c672a9c29fad7b4aeb5556ccff8aa9f850764e7fb3734aba0bdf4dfbe877e0dfbe07c2099f121516f41f9dbd788f3734c1750627087c63448249ee9df300df7bd3d4dbf6390be14fd6bc46a5d39533f857d999adf63e1277420852c31289f4767d0fa99edfdafef0ccaf78184be0fffed7d20b9f08cf6fd3e365062d0c23bf86f3fe3bf61395314cff46bef43c3aae99dc08eaa7c0175eebc49f963b6422553fd624b17eba53866594ad94fe5ca9bcecebcf1478743eb90653a813cbfbb1bb69c43a6fd968d8cd14b4c9c9f4112c6f4ed99b29430fefd321286f4fdbd236146dfdf431246f4fdde2361ecb7258990e75f45f27caca990e7d7f95908f27c8dc680744b3fbaa4df4477f49bbda2dfbe6b7f33ddef37cb6fe94dd7b32eac66dac6d1375def3bcbebc7da8208de058b789705152ae7dd15da8fdec4bba810701ce9c4fd38a7789725773fd21898be66d3972ee9cac818fda3db3b433d1347c6e8f7ee0c92313a05b9a3909d89dc20c89d84dc6ff5531e19c326cbc146ad0bab59a53cd685556ce2045dd885ed0c79cfc4a1d665518b0ed1b913e4eeeed306b57b8cd7ae46368b042b5fbe7c8b04dbffc97eea02202020202020202020202020202020202020202020202020202020202020202020202020d9b9096c97a620458a142952a4489122458a142952a4489122458a142952a4489122458a142952a4489122458a1429f3e5a42620ed935a1756336de33aefb3a211a9646239a156b0005bb0b04105d6b209dab1a13c208b15a8138bbfc9850b2fb498383b964f108ba9441a895e78d07b76268ec87ede4ef6effeb2689c6ba8e3b66b28fb6b17af08d345ce94f5ae694ae625030d64a881ed97b9c60557a41072078388fdc633544e63e500be645087cedc77e6b00d2f1acef00ea8c88efb8adb503184ed91c7e5d7fb3fbda78c5de9031f6c21ffc8964d026816834c3fc6fba78fd498a918f1a7e8b1ee0e1e3d96b0a33ff1950e194f9efe3070ff3c7123309ec2781eee02e3e7ef8011c4396ea09e1d2a8e1c39c27363c387237a8efcdc4c97069a1d8dfef170feff98a8e8f11f1985f5271246cbf34538120626cfdfdcdd9f4c17c94490fb0059c982509e3754e4e94fdc7dc8af4c9bf625798ebdc457208e1f3c9c9fc40df2c84d7f32fd499edd8f83e7ae3f47b20bb97f648cf9344401846828e5e2678be4edc0eab8de3ee9fb4716f5c8197e72abd55a8a75481e5c7475c8b7b445a24fc7f5f2492fbb1d7858593ee94d4174d621df4adb9d65c626d2531a161c7dcd234a2f38925752d3ddbab4034b3dfb11d3bc973fb3dcb897ef12a6c31bbda3abf28025fd68f34b94af748c5efe88f4d6f7148f9fa9bce3936468fdd8224b961572655fa2e4cf2c3b1c4acf72e79faebfbdd3deeb49960c2d1e579c6e6529bd09df30b308a3640c3a7a7a47ffddd1972e900cbca865f5bd47128108f0b0b97b1ea88c3d8f9ab9df40f9328bfebae0f5f6651e5d507ecdf2b7efa505ca97a2ebded060109de94dc2a23cb4fec35606296cbf279fbbdbd5e467320626ff73cd09a5f4433f00b52aa5f4ca324a29cd9e524a2f3a31aa6958e52f32f4b1ab09aa1d43b6d2299b7c31ce9e4cb7967dd33a1749ff901d0f298deb1b8804d488f97e91139b638787de12f685bc7d75f9191ce109228e8001a12988f4af1b433f1be2ab1d2434f3b3b77eda4c970e4f9b99cd9b4c318d7f867d68a6e8d35857beafd0aff54a9527339563a6e8a3504256a8626fe2a10ce8cf00c43ea594d26fd13b819d5f2b751f297ad737f522a1e13efe33531e94e97b4acc2e46c6a0bf45f11ff7e9711f4c8a413ca4ef3f9029fa45089390e98faa4c9d0914c3ee236350995f0adb387de3219dc10576f650d7acd093fbca7e4fa85105c84d43ca45145676f35b60e5469fd20f67c428a09bc827d287fafc727fbfed2ff59c737e12667e4ff931ee220956ce107f8f953ffed743832c8f2f5901646a3e0c27b6a36881ed0db4f04e8c026cf0c0024b60c003219cc8a3f43932b139277595afc600e4f9930742ec6424f264d21e0009e33f3d0c62fb5d24c1f6dbe0b4c705b66d8879f1b2e31719e389f56f984ecdff014a3a219b7881a10a3d0c33251bf71587d3d3df5a5c9a7e8207b2f023b6a06927468af488342ebec5c31882cda145ae5f93fd89af5840f1d5e6e3517ce57ddf60a0e549b09287f5dd66ba740c7ab020d87b8e0ef6bee344b0f723d2c914a864ec9dc712b1b7b2eae3abb1a9c83fd8631886bd6827ec2874092a55ac60df54f80aac9c686747b423dac998a8d65a5ddc1f9d03851243a28b073fc65d5c242c3e5b9655bffbeddbb33a1adb6f1bb771d5fbeeca78a8fdf43c0dbccde2f6f0105b81693c8cc28e6e03c3434cc2dcd827120626d3d084752036bed21e7bbff11516622f5cc7874898eb31ebb36b5ded7198be8e40c82018beda30fdf9d8e8417858192ca12ef8bdcc1e98c3bbe982a5ef5cc26e3303893b2264d1d6e2ca1e4ca1c81531f455fd16d785114b1c11351adbb7b8f2670849f08861a783f5d2c33bf6c87566b03ecdf5b70b56991dc88fdb60492cd91ed4a1fe90ebcb2cbb0c886718f6d708eb37d86d3cc4665881adffc25715b78e8718d7a26f660aeb1bae7e17d5c243ec5f0bf64794dbc814f61d1e2b9661cc895cf168b1972f30ac43d4637291132cb2d024e0f999560c2db0a3fc59400c16b08d258f89c3c3f6c186874046301ed2ef03e44fd6217fe2f1080d3d7674409e78c69c2e158acc4c4905f8b5feba406c735e540e6188523134e7bc68f3d4f05563394a28756234a49449b0eb58b5714f601df712896730c28e337860c4c0c4dae87e95af5ae47e18be8a0107b63fb4622577c700f9d2075bc261c3eee0a28dce393c943f40e4cf0bf9d345e000a20710292891bbdba9c83d65949806512d6c681b3c3edf930d85f298d88b3e786135a60b0c1f191f72f0f0957462e5883ce7bcaaf8c42c8a9a6095996b31bf624ae9e34033bd8195d93b1c3a77d34031b1fef3caa00e7d7dbfcc9bb7377d3a453c586095a513290ce58bfebd4658195c638615d89287610d999a5feb689f50dc38d5071cb0e34b0d5f8dff07c8de3f2601be1a7958d9c8cd8bd9f7a7fc1bbfd0c0cadcff82ad97f9325fa64bebaca4cc961329bc4c218baec619fe335ef8cb4bf616beeabf80b0c917a34832b141962fb66035507ea65d0cd488db775fe3fdccf6decbf7b8ef304de634da6f18f41a914e51fb4c5a2bdc6f76c8c32b26b0f47d7c244c14dbdf3fd385fbcebe5f6a28eea266ea09ed81cd5eb4071d1be146d4142f5eb9ede6b8413eb20765b4d7308d8f1f9890b8fd14b57f861b4b1f1312a5b8611b4c48d430d8436c9b99fa296de139b37c22892764d93edd3353bd64a6c6f6ef287dd341faa77d3c1c3b1bc9be77322c67cace9d8ef10b64c7bdbd7da64b17d163636323c490afacdcdf5400e55e0224b75bc97dc56dfc26f7d32997f86aec21b9bfc1c6e91c0fbbedd074699f2a87f088b243b925ce3c00017a114e754b820d94995f23d2972fda861258d05f8af441ff1641194ab19ca916e7fc162796339ca99e4fff0556fe18c6cc97ee219ff66e1c1c6c600e123472f3e2f7463efc83fe8848fc6b72635087fed958e69a9a0ce670e5f932eb98d87b99bbcf56dea4b74bea8137d03c7f5e0cc8fc04132a88498013567e026ecd66588105b551f6d892edf944124de4896ae16163f8afc73dbbc7734a45fdecbdb33c22673a58cfd55ab96d7beeb31b5e18b57e9914dcdd9fc6ca0b10e953af7cd98baf460925fbfbf70df94a6583027c05da92953edddd313421613cfbcb4c171a39842124b040fcc1f9c00234b0315d684025258c047bcfa17bfbdfcdbe554efa445f3886303cf46f68a6fc459684a78dc2ca48982ffbcfc07c3ff3d9c032df500ed94f3087ecb1cfb20be630aba8a28a2a72cb2aaac8fd19023298c3f7d97f5f93bf21111eadc52a1919c345de73ff711e6e5fa50f8fce1a7751b745103ba2328caeb2ab99f655d3c01cea675f3fab18fc1743d34546a6fc6bf56f287b29cb277a88c8ed3823efa870a568595735535ee3ee2018cafe32a0b0926b0edfe0d9b3aaf04c2b1ce12f478e7b397694fe6971f4ac6e1c1fe5508ecee9e12b50e210c97ec47bdd737e1ead8f145152cc2ac679a32c9f48220a396268c28ed647c2d0f4111088600a3a22cd8fd44f91274496ff3143084f7a209edebf974c179a17569001f107f80491e684817002f8b3e01d4e00ffbe522b104094462418997c32c2242cad94f6b18e86e51961516fbf71dce8b98e86a879248c97fd3bc97745c2c0d4bb7de8d6a7093b2d040513ca3ea70df2d5d838d6c757d2895093ec6fa3f8db1f5f492755a092fd2d90bfa5e22b3a6974cfce8aac68869eafa361593707edb9ff3a06789f434e91f560561dccf00d9e33cf2e9530d44b9470172073a84af6ef26403a9f286c203bcd2e9d340189ecdf3fd209157eb27f0b4d9716fdb36af5f0d528adf0f01558391a5fd124b2ff35a262cd635918c481660b75c119d4b33cea597e87af7678e8288be5add15bf6ad4ff6383c5415b1997f86737848bb1cead7b7be266fd6f7bd6581396c39585fdfc2a07d1e56b65f936bf2f6351967a6fcdd5422d18e861ddd1e1efa8b2ecd0dee36090b6c2fc1cd235b60312853235a1b4a60591e946161017b68f1f42d9ede7b811d1be7bd4694338523ad8569b4006260af8f993113756b44eecafcf58d405f1e9dbddf2a87ba35a2ec7a20c450bebe0112e6075798880213511cc93b7c25819022cb778f8da05e8aa7efde3b1a1dea9e6e8d99f267b9fe53f4bc86350e5f71efff83afbcf7cfc1fdc675d6cbaef3bef33c3087eeadefdec2e0f51d066d641fbee66b847deb335d9aa75acce3939d94e51338f0406e3c5a26aac093c7e6c994b34301a996a8f4cc968541eb14a21901000000003315000038140c078482d17840921435f914800e88aa486a4c96c70325c8410a2983080106184280080014ccd0264101466764bb46cd93d687284a2ef37e74a1bc1a8186a50e8474f974d1092432de9a4f38ea8fc8b22972cd1f109d04601e2b4f4543c2aed26856696e9228eecbf618d0a8caede336ca6bdb2a8a5c4ddd449163593a110e2125f8e778973242add9ea6e207ba386da2bf8dbef8b0784bfec462df371ef1a9f3d85a555a91b9b938aae01c06cbf104aafad4065785fe17e5ae3c08ddde4d43a88b83bac528bcfc67787865186d3bc69e7976439881245cbde72115edb32422b359c06d8beefa6338ee61b17d89b83bc9e20d3dc4cf7a2e1c6183c023a16238eefb858ef1d2c22191664d5c4810cfcca8dc99d932e0280d7a883dae6e817fdf7b09fa6b5a4937988ecc2946c4da956a2a19cad076dd8a0e0233d7068d770eb55353ceb6cd518b10879c09b0fd3376c21a6430db62b4d6ab47340ea47e12a6787554189f7241080a4bd8961e6833d427742a33e23d38b9a76783a8ef34cfde2aa902da4d517e131b9f790580d294ebcf75173ca27c305f0883814d1af6ea0370668f108d62f8017be91f1818ddff5c62557147299fbe60b3c5b4bc9dfdf1862c1d920c812350383c202991b05cc2baf119a9da86cab7ee0e1d2c785e85c7232f66b97880752d9a728aa106ae3549bc791b6e54d0d708e6b5167e8d6e28b6057a377f32a9cb545ab91c8ec704a953118d70404506d172d088c325e5b4eacd090cf988e6fe1c91ad2b0e8c6289a1dc9b84a2b5bcee2b4fb6e92f205fcfddc5bb697c8e6ea490fdcb69f929e76d37965b17d41e3568c9fdd1823831a30c0d1b559dee25b5a33b898f20c7ce724ae4c9e20b8aa2ff93044b2e03898a7dfdff9dc30e943542b1636daa68f04e3476e4bc690d7375f756293eb364ff1a1fb783d89ccd5672e188ecec787ea7fe859896e76cb226e79296e1b6a4590b255b663c5fa17c047ad14279dacd52c9589649003fa0e89257a3c39b0d4a01435149f26d2469ae0a56398205a314011247b05c5d1be76ae42bc582e5ba6cc20e5655edc9030e98347bcbfe08ecab323aa19214475c6431855ca887dc8f0e3fb0670b51077770981044cc9ab67bfb205ff5964c9ce43427c9f6498ad9aaa1401a3251b2519202daa6bacd3b05e6ec21f2a5e575c5babedf2138ba6e03e518c5266bc52818d0f55d9324017ebc1f63e7f74a9223a55304d369546c527cc662310a136cc746b539c44cec78425e8c2cff9fcb8a66a01957636bf60f02853af911435d18823bd3edccb108b8f9c905bef76592b75b10b59f753e7dbf1fee26565d1ce9491a537fb3032d1d24e11ee30a512422e605e268dab88d3c891d192d0d99a29cc0e9d41577e330af7a79cf242d78e081ceb395f2027c02c41b7cdb07f18a1228c196074bc84bf856e928bc0130af2ab345d7f7dfa2836c92a070868cd4d836068e84cab7a6a3784555a7234051c6fe9f7320de149381df0f328557fbe2f075846b5c15dd76e3c1072dfda4675c11e1917b605b25fddda2b04a9457385e6d610574b15044b65888466e5a508e53c4ecf1a5622366cdb91a86a4655d25435624ad5ae8f31fd0cf23d306e78f47e3bd708a8b8899a4bcadb2ce41321101c0c3b4fca486d77327cbba0a913ac893f72b06fc2b86ed3c9c6bbe14b9ea4f92d61a69c782c8797da56fdffb9fa01deb513bbc5023b2016463f0d3f43d93c63af601bb7c93ca6dfa059bc7e5a92ad0d2e56105f8c13f18233afe3f1cfe74b1489fb21c10e9f00ba8a89b07625dfc292eae5a704c4948a315456f9c8145e933692d1624e458f6880d60f18762ac0a127aa9e812d9d4b7c4551c19185e451b9b9712254d3313afb21cfbe5662cd908fdaf9fab6f8ad4bf73a867c57d934ac955f22b1888c325f956c7dc9053431f6e56f2e93f294fa5c28c13b9101c74a47533c47660e2876c8c8e88fee0541482f93646ff2a5227ed53d554a1d2ae117f3481cb343a98683c86ba650c06cb926c55633c2fd8d7ebf38428084e4824b6cd5add16ea73dd35db66524a5c7f0876cd895ae999dd1f04e977b7e745b3abba3f142210df8e7f3b370041e2f074b99ddc870ac24e3e7538c9b1fce2e1f34974d14c190635842cc4ba966355f0178626adf6de43601c7b517e69f983aded515786edaaabd7b65fb38597ce569807b2ca8c3bfe2a3dc4d11dc746758441744d548937d0a22c4cd175efd23ead706d3d4d7a06709be658602d305a0a02e5e454d661aa30162edad7ad23075c4f3ef0e0e5f530eb68ba3ad705bcf925cd8668a1d7deefdf8615579c1f09e6af8bdebadd3ad7d5363f2456ffecd0053aa3237e814b704729edb63c49cced932ab07dd53996a0e0bf6bc44ea089593291b95c924c3dfe2172812ff096c61d971cc2f2a747cea1a318830170703de5442494edd1d87bbd3db809840442fd8c695d12eb008144ac71c840ca6090775a400a498b90e4a6343236c5b79397102293f2325b747a2aac7c1e823d994a81742c2e94128039d816880a344d0e09de4765e2ad430ff0cc2f7414ef688c0a86fc466e4622b0365d00251d666e221601ca19319b065d2c4dfe9c8c360986d956f18c0e7fcbac576db690a45730934cb961635053450578b84cc4b09e0dd669b7234ec5da1bc3db6fbf68231502d5cc2cc6d8fa34f67cb1d6e04f9b0a4458a21fd9c328f8d7c39bc4f2dde2ec10c8f57d253aa746a0de1be137981a181d18066f78ef3a882061067d8cc9968d746cf9f5c85e3a0a66972890f1f4de01cc40c3693dfbd2b583eb5f44458707a02818a100a4addc7a4ae10eada19f5203f891421bc70e746950b572ba1c8fd70ff21d2de941b96c792ea40b884a24359ee3d6bd3a85020a3fd44cb21f66d790499e9d32e6323410ddcfc9898b55ab0655e06e3042981ddab814ce3741b2cfae20f6c8d4f53d0dd8ef8d3bef73d8ad0c91c20ce75c9a429a286b04901d48fe77629311032aef3b5216f60275773ed0a76dfeb2ccca3a58c4faa2463d1518f9d444477504d6b5c93af832fa9532ec6060c7b5747b315331bfe6adb2e54ed0706c9911515937b524df66d01f6bd92d412fd6ff3b888c21efd3ad196acc3732a21b1dc24aef702460b9cd25f1d450e8a5d256b9fcee90d84d07f9b222f10f9bc32430144f0f97d826a5ada873cefa8a67b20b31b4236b915c17cf41336e4ecbcd6c8b94f70598e3076f7d7d30410b7def047e332bec210c32561ecc2d17fca6d0c09e02813379823f7eed085669154a5ee3dc7c4490a2570c5ee3304f1fa30e1146177797ff86ef605dd0366181911c09010e38ccc49a9e98a20936900cdc4045d241833581b7201acd6975a4c6565e14d5646cb037cf8e2934fb987d255b17a286f42f78ac7399d15b25ab85519feea823ffe98d36b43ee7c0550fd0db9fbb1cfd09849d349489bcb11acfe89c3880f5a25b7ca681fba6e1003286591b2fa2be9290df0d2989b5a730d85f44cbc3d1afdd5fd40bf4695d6a06fdca727026932986bbb6c19bfb6e97e8ff86eee1434cf4bd4bf711bc1ce532bd5c00c16bad40ea19d000d73524411f2d8e98a0a626ccdba7caa4973e3ce1e4998abe5a5fbe4cd650f13be17bae456c5f395dd28e82656a130b71cf5572e18685201958de21fabd3072f01dcd9c261cc774c09dcc2697e8c1a4dcb9fe46d6ce1585e726043c35d5de701dea48fbf2832ab6314656b16f3f2c4476eea5e606612c271f80fcb1b124b38e8a608a295b96e0f695a39152c98a0826d1b78779f5abb5bd41662a15dbd08b64ab55bdb9966a6db18b607b69d37b7e73951b22ad299986e2749b43ffc8d1ed7954147f7da1adf4af50f533e5fa9721ad92bb3329a7d5e519d7dc1e65db43cb95e80db3feeada3093bec6debfa88c50dffdd48ca8513fc97bd79391107698c2647837dfd8d0f78f19df4fed5f744bfc7aba6a1b31e19ee5b87ad33e70b9f1b1cc09a0e6e06d4815b6550f8d8577b5efa282ce12d7c5aebd7c468ea723bda1036eac8cb71e62284a3aaad93d45d8ca0313ed512bc734d264391047b6f2372eabc397f575594e4ff32efae17984af237eacdf1ea542f96d752ca2d696b34c82ff24b16c855243e7a0c707e4bec4f699b029f52e6433a4fa83d36f5ade7f323d24fa7d65792316f981f7141180f21d99888d15a016b3c56005c07e8a934b2117a22852fab15a30f9a89a4680b768b93d3c446c742ee477b9f11ff09f0b7c94874e3d7efacfd2c8d8fbdecc3413813a3ae1283548d31e88961aa819ef76f37bc08a82f19491288bf8af4dda12fd3720bcc1a46e92a36efa4e28c0dfc29ac56d0f2290b2bf0af1d80a2e6414df6e6cee8ca5572b18739e6764c869f4beabcd4169d6e5fdda8eca109472928959c133dac274924e5444f21f6f211a5fabae93851ebba1015b737e8d412a8aad23a6ea7a1c662cee6ed665e5722f715192bd1b64aa48a8e55911a52950c16e9619f694fab9a0460bdaf607b1c8f2971fbfec7aea97c1a778845c0e1d42b85a876955044a12834b830bfa806648a9ddcf152b9f871c662aba87f786a41eeb35db92ff6c480e904c536a6719f9d8af510f35dff6d690b5cca05edd30bd46fa775818f7e591065605f8343aade11b37845e81d974357ce3655b5e7d1bc99b3029603de393bb08c419a8ef508520166ef87e3961e385be6a0580d61def567aebc3b6c2e16a4278f5b2732e6d9e13ce4e3926046ca98cbf318d08b8d60ca09e17c0449a236b3774bd75d35c4b64ea7d39dd58da8898d51e61e3fbc55d2eaf1e4cc326f0ceffb603147fcfcf343a5fc92baad91bf5166625907af66012e394e8a4b44e5dcbee8b4ece1b1b5b97dab914fce2800345f0d28669651b34b4e7a4222b76e12a5401a407370459831799abbb0d0137ea975f2d32684ccb098cc113df655c2b2246a4e505a0abe8b92f0fcfbc77b55514323478497ae5fabf1ecc1b558efb28ed39056e10c1cc10dcd861792405c4523ec17f5de3951c09c8fe532bc9521ff179ea81ff0db94281188a3f355f4399a78a5beda7933253a580f735e5f756bd28e8a8b2bc79a0a8ad5d13b78943473d5813332a7914038f15edd1c156133e0c50d632cd57274c00dbfec804587f2f942ec69608840aee96582e1bd38eb14fec7a17cdd23201b177c11b2e05ebcaf51b1e553e6319b3602a4e1fa2a6fbf88ae6ba7ba0f696f1f9c843afa8042eff8ee41ae8e7a210d615c8de1146a1b0feab759ee1ff70f3738cca4ed69f86a4f1b9b1c1cae99f2c1f2d6ef4f0ee79be36fd6fa582af6ec6d98c68b6eafcfb0c5d87b8f600ed4d2dbd7f9835387f1f374361212616e0b18b5d2c8c5a5765095d65e7b3820e803bfbda9cb18923fa569ab127f921f74366b18dc4a486fdcde6e997d70e92b7143c8ca52bf4264d5d7582cf76f3981d2d9cb2b30800786235e68f15812c8a04b5c5e88950362160b613036a4fb1f9d559374ee113c9a405a3bb3fb862f4610cc1657d7603f7a626a777b0d3e083de29311ec164eb114bce1609d0298f66cef86127622fa095a2f3edefb2a6de4ae63ada8642cd1ff1c0428f53120af06c4078858bcbb257f78b006f117de364f3d9ecf591ee37bcbcc8e76471a683957e335e32f73c23fc4d7c9dc03c56450e987abc24447273e088aa7827ab02fab551987109045f16257796c01f0ec2ed087c911718bf17b1ec6c9f35b7b1ef68bb77835e5629fa580183c4c3cdbc4ca5875b50bc34664d97550ca5dfe8a61ed1993f54d2a801e8e1bfce78b34907c8cfbd00389999909584a701dd3e35012537a3eff6cb30e323a338159fa2501d0ba4ba7efafb937f50e7245f7235c99501b3d3320863b0e439df79826822c2168e21c84600950462f70f3e8ac25d8f10f2d1cf669529164dd5977dd65291fbbf3913271d485f529c8dc762babf33a476930f0c8e99634f5b6952b9ba74b1c284b6b27d720336e303dcbc94ae65e6b5700b63539b4b67ff74ac4853836ec5ab59c6ce0db0f2cc8d997600b6b7ce9705f00f3e39d95e449612391071fa0180e7fe082c66bde61c8531a7484a25b90c129fefc9bce817d7afaa6c3623877d78798aff8f718670057b5ba0af8e0829e803bd2a763d71260c3f626d0aed0045027e9e74a23d2adf8614865fe3a163b42274ce48d14361df75167db0d25a9946eef40521760a5ca468f26eb20d2cd132b4ab90328f29e6ca8d03d92aea5ace32329daf7bfba0a8e0f1afa61cfa389b47b279c117c86e256356d3d7781ea3fa504973a0630e9cbf76466934477b69e9ebb475e97dda90a8ef5c104f517b5720d10ce459e760026a4c54fd0529b84840c6baad742e51d3b2f50922595b0ab8fe7ace2798a878a8b03708bc18cf0f8e915793c6d0534f572a87b691d037db79aebb634da695166c4c612654dd7c7c2eb563d459700ba542e688387ef0941e1c18085347d0cabcf44856bf8338207f26441176da54363f163bf2c8865a8f2be95cee5132ba1762bd1715df06959014b72124ffcbfba8093302411795b0c19ece0118835908d934188baf9ece3d8f95d17c09d6cdf98b9e060b570282c8713bf22061491d2060a7599ac7948321f22be1a8bd04694d2becb590536f59ab52ed08b05842754ac3ae5991f60141997a2ab0674343e6860a3ca6dff401e5a4a705665004353f5e9e26ce9117458f6716a4196f2e0c09e64ab3bca824423c3fa6641d60ddd65abcf0678d66ca2eb4625336860cb0dd7dc1b3adcdf79e51018f20b2da0f9c8819f492441633646903a04b9a1dbc07e4591912ebe0aeeaddceb580ac78e95cf1d480edc85b3498f7a362e1e29057f7833703fefdd27af6c340e7c357f3a3010abc06652b15fc7a6ea70e12b2afc3a8af9327d863c363156c8dc7f0c90f419c0157d3057b7a14e874e0f4d1a1cc1a0ae639e43182d613ee64695ed6e2558990f579ad4af02b2145ead04595c8b453b9f25aaa314081cec5ff5dbf0dd1b5a232aceacef17374bd874bf3a275590bca4d5abfd22d89327af0ee16c5ea5a5c1aca7ba420328ec9d02a1096168367386c537f695ebf0917740672763a30c1ffe8f6d888e64bf2b6e4236a196c69d6eaef712e14c753d59ee214e9d7a575c9fecb4f7bc551900110c9e9d305241bf16592e0a0cf12a08b73e7311f72430b931cc0648674d4bc3fe714ca7ebbad81a30e53dcce271cec4a05da78666f271baeb7fbaf1449e8e334f12bc55a7040c573538b6cffbbf206e48425141bff8c05538c4e6bc6fb9c42d9189d530fd0ed612123a86738fe2a19c9c38daf00dd2298c164da64728b9924f9ae175c1ea2a507742b1995f8f8c9c743db20f3fc14a70216220442058f7e9acebdb845536f9ef0ac350b13b397b212461366c89f248b9a52ed105cc9c842b51d11d11fb9d92484fac27e026388e3bbf60d8bfc0c8c774b999813d760a652fbb294341820669a1e5cd16966bd47e290297279c57b5432d1637eb4df7dc6bd85c345800673562a6547c00985274d0e35a58cf5714bac07d3c45d7889dc814e0e4e2309c1a5c896f8b94a73c279dd17eabeb92ccae1517b0e4e6a4519242f06772ced47b6f77e49387a75588bb9084757a21f0c60aab872135903987e48cced77cbd5ae9128ff7a24fa55b7b70cf12186c0e5981b25350fd15f55982c79a4c32906e955a11bb19697080618d1cd7d73407b3738bfca5a88ac84fa28adf2ba635e63d81a5c3df46d6347362f603feaa6889e63330a2800fa12d9fde98377a3dde65d311c5a9e0c771a3b010d475871eff91155fe279f18b7cd0efd78e13efbe8abc79bed67a515ea194d799afb68ae425f57944f30c27833ce3d33c03bbfcc9036022e333ee4e88e208c993615fd5d51d5af5c9826be914debb340466cb63fa07b2abde5425e18708f5b9233f1da16b16d439c44c7128c26d38385bd9aa9d3e7da0a17a3d6f1c2d55024a11fa7e7a602717a06f6a334d4dc50d065aae319ebc50d6eb3ced57aafb59d69456ae6aa085436fe72acc1345e04c35b10911c2ea4fd8da7421709278d59e731958b1db003a08744ab8ce3cbddad3213793d095f09cc4ce2175520b422e3fa7c6094ac816ca540d3f2987ab03021bf7bd02595631245208310348ed2287c47479057d4c2812ca385c62450f21860e9b82842408e7c7e259cb6d9e2a3354312aff42852794f8f16011aca4e823c731ea18a28557e10928622eada728a042e70cd994d4288ff67645f297693152a4c4c57c47ad37b74a2e9c9333ec840d44d1cae978f817d04ee3c481efdc61335fde2b2f4ec1ecb21ffc68e50809c37820407268ae5c2562e5eeb0e12f7d51c29463f8778077863a412026c9b7c2c3c74d70444a2c8c14958295ab18db94e5e1517e40fbb39c29b96c204e1d1cf140fe4fd46144ba279150d54a7a4cb3f8a8e91301f367123faf58f0ef9b5a4feedf30c59187fc021dc60001a015695e0374491f2ed2fa76db7a80956a820a522260eda8d6ea889de5bab74fd56f55a6a17b4ce6aa4bc4867f7090741207d217347570cbd6c98e38ffd0d5f2ce5adc7ab403e7bf60312502a3d29c079fd0b9928ac4032c76785bf85b0293823edb200728940218d11fe9811b10176a6cde956525b9dd188304d2dba36a98a2d4d3e66efc561da5efd3ae8f81cceb9be4f60205ce0c6cad2eff745f732a16015aed1b41415d61edd6a176aab91efaea39a0c116b4c1cb4bf3754ebf3d37e32fe7db2ebc6d012487ce619a388d3bf184278ec31f0d9e16d2e7d850b56e6b9d9e52beaa64fb1ca6a0ae2d5e24e98973eae48b7b4c3c0ad97ed19e7f5ba971651c9edfee51604d77eb313a54d975faa7c519ec1835a28b50bb489f5896f53f3cc667ee456b7f8672b373016caf0575058b9205d368334578ed2b737fd29a118affbc89bc43211a1222ec44465704ff1ed1e9833f2c8ebfe2fb1bd0e40c6f620f77283d330c69fc6f77a2a56343090c25aa6a213852049042adcfac8221d98597cadc495f025a9328c453f53cd007d70265964cdea924f31357e9c48875584c659e01df606d6b2e9ea9be0cbea7a7935aaa08ce0bcb70892c81f6698ac61e2c932fd2b4a4909b9f5f480d66a998cac658589b53d9deae72d9cd80955a38a62f95ee6737973e59a88a49551809df7f96b2581b2061991629f4cfc9ae3fbafa11dac1a9eddda390c419ee7ca6a4db2048fc268a456ac6c1d952d697b048abd8c202ddb3c40216a29388bab851699615982964504917daa1cd586187aca3850faf9109a56ba42da499ab5c1274a62aad6145de2a9d2197a9a1bdb0dc6b555c32a6726e7123e43b345b974d18a161f503d4eb9145d0b01662f1490efd8ca9623519253b51be3168edbd085ee780c3da964719d8903ccb7f9a94d17b4242b5df9026b6aebf338b8122f7d61a3a060856f48ea2a9500e1a05c8a831013d20e3b488cc1debd7976c1802fc4f49edcadaedf3e66d71388a453a990bb5f87553d3fe113f4953ea3f09f10e8a46fbdfc58fd35446b72b44d04fd014788d18dd1ce05bd99c1423bafb56617f77074a28e93587e0aca63180e96426a74b054ae2e1fda44ba37b43718b39ae01f1fb3f25bd077f48d4b6321f602128e1dabe03c1a7fb107e9b8dc43558834974bb14856c7bc3f128630404a7d486ae010ba14edbe6143d6a0c8eb5fcd14bd8ba1b01e45ced6f4609636f2602561f77556dffd6956b0e3b3443618ad4bb311f7992f84fdacbe17b623be32fcf9195284741fb985e6e807173ca97db9ce54ee3b21880988830f2a1d9a385653f00dd51c21ce2fecb1c4ec79ac77e14591643edf49a83d20141a405633a3f480930b9105acee064cbb9dbf087699dc38cf6a366e5aa32edb0c794ca2ed9fbbdc82acc672a0f006c4c0f4f9dfb4aed66d7fead2fc1240712510cc441032172d1a90a42f1e8bb6e3b9ae41165128c07473fc4b34094a42dc549233320c9986ea8bef5e13dc98209bcd504502e47a0b1ecf4d710666fbedfb1ca1940a33c500682fe5598958c2f7ba9e2b67a2898a3ff902c995fe1a47e304800f50719ba5b4876421e6d4740f094e7fa19c4c7ef6456f51bfdbcc770521588edcf6378887e36897f5a92088495b6e2ecb77f878c9efb9383fa738b47fb2945031917576192276d9423b553523a238e413e025f6090bd6988d48787acf1c39680c4026a3207015295f9f025a8042c585eb9edb66786edd15d2e8f12d985bfdd6f2b395b619c6a0bb2806016cec909bd6543c58ea830ce057ebd1ed0a5233d7cd6713cc5b5d1a833dad7b97a395e3a93f812cacb28a57544c3d2ef9df0576d32624457aa70e4ffb951f6b3c9aa5ccb00f9f227c2b5467751d625cc189c49a92aabd31c5cfae567ee3ade5358de40a05e4783865b6d53652beb1f045196b2d63d771a9a2777a039fcc86ef54eb9e1367aa32fbc1f87897aeffee71a941b8e2359d52b2aa5ab39fd370be8f771f6ffe65d40a83e74385db1dafacd6671dfbdd9fe8a30fb02a1f995768f9b02ccccce00dae7c868d381888d5adc7ce7e1cab4ecf0497d73d77f024a3d46a40e66d28b7e3e2daa1cf5ec4ae66e3ee57c197c0b58ea40daa1364666b58c86005ed432f4b697b8cc906662217e274290b57bb66d8131e256e259781a25ae3194ca9655148f24e693531851b323c64af209a0fdb14e5315e5249a5684a913acb44b5d428bf5f4ee61dcb1b2a363bff284fc2d4591d97ddd68d5c48cdb4d5eec61f1515fda6b4023767cb724ac7986e19269b91e6580593db51f30f422d6925548ed0c1f5f9944e031ad63e132e0a7b733952e110e2dd2ae6672971e3520d9bb3bdacb74001fb44f2bb8be75bf2db80045df1e0300ef03c4930bccc66f00de73bb09d4663342eaeb9aefeaa2dd4f5ba1e2d0f64b58bccac8343bcb7ed36009a3ebc972cc390d8a63a141b41d0bd750dec51c64771274f965a1728fea1987c83c8535071132ddff52f0c68c41d9b623397e3b1349818809cff0513a3bcbf57e25979b85ff6e1ec62396de4a0114006b301c33be69d8cb91485a17a514911285fb527860df0b95d3c5c9d60615f131466cf30a00789a09c19b74de3c675294680afb18b543c3d1429dabd7324646c8bc4bc3cd29b6ee8090704a8cdc5a1d6da36605b3fb8143caf554747ea4c9d0bcdab91f9707048f795c700bc152731e1cbe91a9b2677839b089c23a1294ed761358616e3fb8be88fd8d50d0d7e05ae3c732e8c3a57e92a0337717292acb758127409e322998b59b61e07204e9191308d20147895a13f66a2bd0805a586d65e25bdd6a9478aab15712aa8f4ec0978fa52e038aed1d88ddde4bed8b53e2a619817f5230cc9cfaff7c0e9a6b92d903c028de80ec29529f88ec6bbf41944572d302bb0c5ab759c1bf70e16920f227552bbe041f975b6f3f70718be77744b2517f5c48f66b3bf439709396aba5c926c6b814457574aa69e6ba3d213ab3c5f3f26f300a33dac395de19dc3a503e7e13dfff66b99f8f392f2108578f066a724826872ab1016ae8c4dfdd6f90637770bad62ad5f2c813e526aed48f3934b92dcabbe929eefb2a64d9c5577dfcfbfebf596e2949abe6c0d89818af23e65dd8691818090545df910b351065708c2b0abdcd10c662f10b3e13da435fdd35e87accbfffcb678e1a2bde7b4cc569a67158280706d17e12d73c6c9c1e6ea085a3d5b883b759d52c9583c4a992634e9e2c4a1cbe1fa69bb1bff9c853bab0df4d00712aa10c3201d12788568e5d79d807bdd6f2238593b85a7bba88079682372a5045ea5771d4a7af0c6b8871511f02864c9788f925e4fae4a008c610ace3199d2b3a87df1930e2f584fc36771e3291783e63b00ae1706f8f5b02941a66c851c3ad627c4a7ff093b99b963732d003c10b90f61d616212cbf76d307d4b7680edb5770f46ef40cc4efc045759d3404158f1d3b8865b646950916d3cf30e583eb30c0bec8cbc85a6cf5b7ad068cccaee6883cf6b50d4ff6296ea1891f00603e8f5d5ee7509dff530dca53e1ba8f84a37c9cd980fbf899f7f887a37f53d496d40447a472f1f3b3ac29ec7c03c72ea068116a3e5cc12f3233f316eab3bd745d0853ca57d5572fe4369706f0917f476ab161c9bfbd0066927a2ff3833aca1a912185c7edc9856203db0c46e8d5db4290097e858f862bd6168e9e6befc3ce809b10002f053296a9932228719da0fdb7ae6bccdc47c7e1f4899b9358da9316c51b0eea76199ac73a3cc9fc28a35c9b277eb973e87c40226f4928ea52f15a8e708e567a492ab56acfcdb211e2f2894b10766a08e965b15cb51fc81cff37097f5b64e1edd463714cba6ba3fc461e4aa0f019ecdfe0d47888003f26afa671ad8f35e32213bb003b497a98d7ed64fdd1d88507ab2a006c99bac0833c3bdcfd74934bef86f45e8372c99c987eec995f25bcb5cb276326962672e5f2da63128aff497685e8224e8d6fe9bcc9a810377ead40314ee5461bc55fd7160c34904debd186e9da87fd36a7e0db55fa43d9a4309e685f89555bdb8ec25b64a8e23308e127c46dfd27c10b44e07cf27b1fddd97e83d8ab336620413fa77dcd35b066cc4df4e75520ce26ac1dfbe3ef90240b8b783b91477d82f9f6145d1252695260414460883c58f56612d8512b5e980994824f5981b34d3cc10a17fdb0b3d20987cb27f8f6790ff6ad6bec3579bab83877c6de83416b22972e7f0ef7c0fa4df9c36d28ccce516b30d347f59f30c733f15de89ae895064232324bfce797fb80ae84ca20888081312d7bd4d3ed8b2bd35bb5f6c19689b3c0033f5e48ec19b3d91de93bc1dbd9a15feb112ca7fc45b1b1916bdeb521eeed810d81d85d77a196df14bf42b034abe2b251a0efdb6a0a8c08d0a4d36b7f3f22b305c069400af9fbe8ec1989a721c9c4976b522efa6f4364b84e22a2c160f21ff0c2375ba276673adde031e083802b2b0947319023c6f0b629aff4f4a853fa30a1191a30f4cd0d1d958673c0f26b0d03ba2d37b2f232059b4b7e40892a3156463a52b494bd3a14c518b1b549de9af4a61085e54d483ba733d05dbd1191808ef6028fa48e570dbe52fa2d1b0736817be2b980a70b8735f37378b37fdc633a2333e0842c4867f92689847a2e31822d171e4c848a52439b66a55f8f11679f25f7fec595d11816effb64c3bfc25b5362039902a4518967dd140afc013a4e8f59d83aa0eeec8664fc92cb34c5a19012c6edabcaa83550fe2465826d7506a32c8b0065cd458b4aa43841d8630be8035ec5ec6863a32bbca24f46f8ef454f62c3af0e64a99a4321978dfb104d817c89dd394c9637ca6f2a906d4a4c74d99bc5cebf7d11193f42165f2fd6e260339e21518293d14ad4f813eac780065305ac2d08eb60dfa2e6eada4dae64e3ca41f6967b05a0a20496f0276ed4b55aec9739005021fe6936f13df8a6ab3f6358b352cb7864a3f4045c425e368786ce37aef3944bd4d84bcbb833af4a0072da8423d743d78061db4421d7ad083fe035fa10e2de8410f3a86f80f15f44105dd6ccf1bd4b8461b3d6df84683be4d8c94ec4f1ad04c296e2fbbc43d3776957902d1350d015e1a0279f7831ea8a0147a68833af47bf0071db4421d5ad083fe075ea11f2ae8830aba0cf10e25e8410fba6ccf37d6688d1a3ddbf04604fd4d14294512f53c141dfe1314ed9fb924e37672111d15a2578ce39583e9191759ff5c1b6af374500d18781eaa028c9e0eaa01038f437524683f73908700dd898a8e135af1b51f65349e7aa03cf3a82633a8853ab406ea38c224ec9cdfabd2a3952ca4749420da3feafeca7bad38416bb1eb72bb718d8f869c357ab4485e00b49687e81f2d77eed161b94199c9a89729a816f460a187ed9f5deee11b62d6523d9ada286bb28d9f92f33f57d09044a3b6f663e8fef07d0c2759434912aa06f38c68a11fdd9fa1d6fffb4a70d986e90c2ae78b620a94220ecae6ab4ceea7a23aaa010ed8a551b04df8b1e914a9331804cb210c2989add54838ecbf735d7ac39bcebd5ee7e28fb48476394734ad1b36b43c3ff1b0915a02cfb2ff16c0cef27a39b4b00695f683e0256f3d8e2b493771fe9bd6df97ca59c1957481a324d072d8dbd61c6e1f4e4248bd67811fbafc3ad98d6394044eec0ca1e8c3a93f30a1ab25227bace7b7e48cdf8e077e4ba9c2593fe3f544873654064b803b0f79a8d97a038334e714508ec99f760f43dff0d36a531ae5a1982c3bdab360c4713df5ef08b36a258e9ec51da1c0a57fec5109f00257700d4a30df0e19afe570a5a0dd41b1cede76b5c07515bd7888aa06181e41bb101bb7df2b5c8f976eac260183f8a1a1e35d70bafd3c2932d8fc524db2ac502407cdf1511dce2672df32ec0594ecbeb97eda70cd55235e5268a487a85e30a563ccb1c18ccdae759ea41410776d1c4e4f21f5e2363e4da2cbf6ceb4ae8f5d4c3439fe8f8a3f2125fafbadb261b85b2cdc192e1b18a21b0fb6de5872cb3d2efe3399df7d1f62a40abba159b9fafdbcc64e359f72f9da67084c1c42b53b43c51fa063d72a97499d3f9c1e0272e0471de2be375dc8c0d91c1013e99b9e05ca5d28f24d25107426b904cfa86343b46003c5281948ec4f26340a431cb44c65bcb6d532ed45870d29e728a06eb62a08327c914b332cd42e534650512969f4e59002b46bd4644149cacafc3d2ae2c10e0e6db7af6a52d754fb772fc01dd4d99d747f1308c2ab917328ae1fee5332a381ba73fdcd5be3e8490d497136f326f415c8b6bf27d8c62f7fd9711011fdc18c57152b8022be869c1a3d3b245a46c340db7bef7d756fd136e5245443f9d79e8025626920591aa6619de30f02271a2218908345864bb64a15b9935e2f423c3c7976920a8530a4c1a97c6c0359f2f19766cecea9db5cb4520aeff9a853184ee4a158a62b99ec12e3244d30160779662c2a2862666868c362b472996115b281e07d8603f390b78619b80d044d1a693aad5ceadb903f6e8c078ffdc473b4474a06a09b41f8f552c194f7f5cb802f06971eddc3520abe9d2f75e3988e3d03a6afcdfcfceea18c51664b37661603d1f615b2ecdafba0f987246158b694b024ff54a8258ce2136499606cbc06dc478fdf8bf6d1096c0aa56e3fe5b906d19a6335c769e9a047d968788e1973bb1185db4d235d581527918eab13ec3bdd530ca43ce6d7434daf9b36d34ef7f6397ae4c39374d63248e64f8b963037ec7f6d341361ab46bc861ac08dad45bc2cc6c38241573a47f745e039947153746f40fae46c0cb7fc2a83464548cf0675d899d7d284d296830046d1e2fa765d45e7409ec3a6ebcf471152198df6a7ddd7015be6e8aae27f0f532b3975cf27d44a8bff68ff710331ed480675d0abd1868dbfa3d3cb7294e63ddbb9f547dcf45f4ecb5ac608a542ab721acc6d87944421da0d57fcfab45293d23a0f63904a79e976602b5f00119204daf2286ff9cba161c6b12beb8bc0b8d18839b909eddb9cd1d29280f270e8cb21b1cbd04e061b573a432c1f89260aa0b1817fbb82e67c7eee8d2834dfaecf150297bef25c7ca3382028b2bf05367755e2882068d5cc98e9ce92be2cef2ac7f0cc5b7ae8cc3b1d8b74fb81a33e0aa01909525975ea76119f1f02e8b1b2b1515de81188cc6f175cf26d62a34afda8b5616f20df52ca1bf6730b6c91e7477b0f377cab4ddf40e20579ad37ebb024a0af17878c89d9f483dd3002977f45f2c4bb2dccc382c9641791e826c5d6b0ebcb5aa33aaa4437bd7fd7b329c9f3a42c5b97b7c1850d5196d289a096a4324862a05fec814324daa89453b984ae5adac3cbf432b0b812a5669fc48580be63edbcea83160b8058545efc959156f463da638daefb653d1a47a2216b4d326cac2f38de4c345ea76346f41c02662787f8713190f27694b66e00493c07a3ce508f8ca1283807c334f31b22bdbf3977097a30be947c98367270f19016881555b780d02fd6abb2e779e8c8bfdf06efc700bffdb0b9daea44319e5e6cb2ab1c882382033fe654bb90b3c5d38f739f4417e2942a6a2759e104de472b3dd9bd1ff0476d6dd2f0299eff6fd96702df7768d1702fbf254791be5d082d2b14d1c5901f927a6cbc3eb07efb68a82de1de7e09807cad3ee39fe9a89f36ccea290ab67dd1c568c35e2ed8a019de8723b8abac12a918781334eba5abe05536e4dfc1f9176b93d109a941c24c1fc6681482b1f7286e7258cfd139c9764e779f9cdfdaeb3daa45364bb4f7a4b6a90f5ee950b31141e01a47f9e0f8ed82144bbdd6de8edb83b41b2b2342baff7cf452c988d607c449a3d7d8ea3c7470d1a743f7f3617c3dfecf36dc82065652811e6b670de006c6a3d901fd73f00069509e4f468335faca9c98193f7108fb979c8dce97541400e8e723e4c4c34330ec6cc9f3f6dde371336eb598292c0deccf8331e25581d5b553e8c08116feba82a7a89206af918f624645da3a9bd07d122bb1f15f6f0a7e3a5e0488d45fee67eb6fa3c96a88a83a6d7e9f200f7b7c1d83a7f86bc126497598d076eddcded51a5b29cecff4571d24f99fb5515e14c68c78e18e14b00e28a4f1c903e1e19e89e454b19337e1dfdc1fa3b150fb240d4634437a7fa4cbe9ec87b60f3d258014ba4182b2a8f1dca351a5d0661fcb9fa31b208bc060816e4cf4f18d7854ad0ad4cddcb5bf404d2e36b1cd50ec3fd48b8f35fa29d6d7b34bd27f8d076195ca069505d16b7eada2cc36d25ed4f33ece9fa2e4f482ce2631e55d85495cb8744c41632efd9463a687f942138dd577683165e2a0c51dbfa3008951ecb127bdb138aa31cb17d7ed816ba0b8afe6e391b29355e5efd632c9ca4ad760b0b3181f3ec95d4dca46a00aac6c44fdfea341cbd120de2c96652310511a82601f771761489092e248511b33295a5beb41e8ee68a7cbf4a7a9d7fb5635a334e716ea1eb128720c4f512dfc7e4e3eac6202bcc675791b9387b229e36fd96ead5ae9d408f9b85e3e1e619265e8221b2f9952a51310994c92ce278057696dc36071e064856f62d2b15b381e97d26215293f0979ccbf4d55cd262d4fae12e5a32ff98be96b9261e66c9dd8e78f1b6eb1ddb2c32edf6c224e2c2c77f50f135cca7f7c750374d187151fce02abbac8544c467b3b4114bf7dd2934dbce70081263005161fe8f53a28db9d8e6e14eda7e5b41e76f984ad38d2803becf56e7451218a9ff5074566b31faabe2893f4b2b2e299ffd2d617b9c1a0efffaef828840e8728b52f0ab4fd33f4aee92d4e0a5ee426a836c8759fe123c918a5eff3ae217b60ec162cfd2ffe55af2d4614c7248a3f4e7e83519a9ba66b910d08ecf9082e0a4f7ddc30db133339887f2044d648d58e99ae53c36fa4ddb36203636f574162a2f78616edc10cf7bb32d4d3d71a8a9dacac4d01b278afa8ead2df387b6b5936d85781dbd73f9f32197c351ae7b6ec61c35aa53392de31c42c155b0e139184a99c42564c00b796c9dd70ae8eb79e376d08e5f67739e6adf3d5c0af3e0fb777d6c9a1b337096ad0b52190897f1ee10be252120edf1d821bcb13282d46473b81f9ec509be82ff243987fd17c93d038b5a17608fcd875eda8fb0fd471896b918fb1a6b8beeaade32d6dfc1cc5e08f95453746e05dc93238b51e73a785d0393ff2e8c78925016db2425424d8c1122755464b90baf976ab6459e0022747d5d134b29915a485786c9d5b929d61ab0cf283027c042f0057d8b75c97c81607e1d24e5212ecc451e62bbf556a2b3a540842a4b87b8011d5d57a7b2e97c8e0680200588bbd8faaf348d0e33dc71698ac463b7f0150c2048b3d28d8f5825fca182989336b78d0c9d89569d307e0a1fe080d0c4e65318563acf5991c665927f9662b75f4df453d8248da84c79f1dc3784862638cafb14dd282750ae23089974d30534f1a8677274648f37346e1d0c27687da331dcdb703f8ceb9c96687fb1b7a4003e54093f5281e560e26c43a6de9b2a62b89ae0a6b5266e04b187e57ada100515822c6729075d3010a9b52052835b964b0ae44c9d21d6c64abe51a52041c8d4487686a4303b317ecf7adb22543c3a3623912ec21455632701009c0fe618c19a917d37d197f31fb93f227aaa2f3e4aee978ba645e297c30b77a0c00c6f4735d2937c83caebc0df23f98251cb120b07d6544d2b477fe061d54dbc5e70bc0746ed900f383e1d5403c84bd712e1bed50d8a7b88f553d2843121598dcbf105f217e23925a6fd62a9f7e195303754812383294834efef7b7b76b8e7e0eb33d8041d73da6672dc163c420a15a11404020dfe0088075dfe3b838dab84d45c414c441bc7ee092d2c37dd265aaf4750512e3150fefa5e8ca4cbcc76f620ae462a199000aabcdf2c53956c34444ab9accb167d3b47e78173a2be9c15cf247c47b3fe843e176ca73be165166d192ffbdb9229ca43dbcb38b82ca987cbc255f746a517c165aa1199e996118a11ef059247000170cdd3d21d79a075b0dcead8f6b95559765ad05eeaef7d92bcb21bfd5a92e02f1ea3b1409728528e325cc9b7e11d2c00983b41a248af4f621c6f8cb866d7c5c68fdff9dca497be26f9d43a0187cf1962d3b7535b0201ac36a5450b6c4444c884db645066320a8712407660e0169df622056fc242b99816b66214214014fcb38535d76269c2e13d9a71d922ca2ecacf7ab1df6c08db5135f3cd5547b4235d43c92c3ac93b4296e9d22589d54006b416095d6f81273e2bb81a7b760b7bacb2111384ab5ad3eba044a87e1e53f6d4623e926f3f12de2702d113677f49fa9434f00c87017844a99758bcde74de899f25209499da903318f0d060a8a040a1f871b142d6a3de6a0d25f225e9cbc2c9ab9226af32ad4761fca23c76bb5304ffb740b21a1e4e5174eb3080f21a598909e4bf25a8cde03865e1afd258151cb61496e91d5ec4818e1107775cf804868c10c6d2a0f264d0636cc49b007c2dcad491caf4e268fabc2df0a87527cd412157e904a3f168887aba8a31cdfa0d40c8056a1cc5a5e8440891e12a7876c42bb6d89d2d62f43f6992dda3789f217f6c012b5ee95932a88d9610f195f5eb594443868cc696a00a768ee801f10ac419e203015600a5d9f9475097724649e2e3904e845a04708f31cb06a8c00d92625966c8f87282b4af788537312f20a13ba4d5c7294c23742bf87c9acce78f17e18f259a1b07779249f8f7c9b5080199771078a9f7c6656ce1d146234a5658c30d5e140e22f40adaf7f4590a20443b6dfdf516d9570df0ae39c903f6883a0b65bdc07c4102ea90fe218d98981861b0b1eaf9c2ef35b2693b0020b130ca9de08ab2498571010e93d992856fde107689aca698cbe3cbd616a7e5194aa73aa055d58e2a4e3b3cdb63341b567818b08cf4886cafdd0f5f8c8f68059ec3d32b7cb03c96b8b87c362af3cda0ba785701eec71ce8fe0752e33eaeb778f49e27e74febf2ef62cb18edd5a0e6c7cdd9ed15868906b4a026450c4c443327c6380fc7add56c083701ca80ed5214a1104a85903cd77c5f2967d89936d93b420de513297504410258629130d05387d7235aee7a38f9fe92a7fa656f2f4c5eb1fd3e9e599b84eff03e55a2f0026f02d64b72769d116912002768b79f87e78c9676730a5fd93426de7357ba8089d50c9741b2a59fb31f2ba8ad35fcfb920e0623c434ccc17212a65978c1ff6afd41f164e8891dda39f09aa03102c66f86bfbbc1cd6ce1fdd6acf20216ff459c04443ead3ecd31070f83c9b9f8294d62d10d5d340a0537c7367b03d0c53ccee9f4e38bace629354abd6b04e45208cd252f72d5cdcd8b0d97894ec3cf80dca7f0c1302b3b8463d4d79813f36cd5e5f2c1f9209b74b309b2a8bf326c76c33223cb98eb2319d6f309142f9ce757fc332ef8d0c616a2dba00839aa32ffa8192f4039335765d3f8a7cf7bf3f2d79265237060ae7ccc4a4fc13f7eb6558101a35985557cbacd2071a987c42ff286accc24c8ce39513da111361fb9c0e02a59ca73b2c489e62ede6a02ab14cb705099d133ee5b1c21827517adcb3a76724c238d66a9588f9c4e4956c517b194075411c76e5d396b1595a137b04695022303a213d5240d2ed8fc80e9d8306bea3f521344be5b71229d794349f0c7711cf8d5e0a53c3e88bfe15f30b71c8ab7d6bebba05a51dae9780ad7fb018b26aeb58939dd08e692d6bc2c818c2949c729f913803dee9697fa897dc71ce008f768efb87b1d98cde60fb03a75845d0d5dc614eb427f26c11b91558694d7c7199608e27dc2c824f3c9428f11e4d02172c22a82de07ef6925e09076a338111e195a6b40d5180db9ca760ef99f62da2c8eb8fdbc1987ff914bf4540dc66a70cb3d3c23b8696a8b0f7c44e19484c2c13e8bbbd8c88c5919404b5626ab288ec84d74c8e5d7f5377dba80a5eafe078d620097243f740f38a4df43a0e0d9ed3106acd4cb3c737af9775ac9daa50ae75b0e20814573e85926b9e250da7259e7aa10cb4430e62d14f442a057ca53c92d4f3011368ea5df078aa834bc414138b044c1acdd37445361b392e633f04ee69663b1bf1c935a6f0b2b8f8c4cb3f3b4e9e9fa802a9c72c2ebae54b60b8591cbf2072161e5a935fe44177e8c1bedb69c12de7ab258830d84e712988bb5f091b53ffa04eb32171d84e289bd007d197a089c5603c936311224d7c98ac21cacc57fc6638b319130cf9d2329f9917a360a46b872a7211ecc4d3cac77d95311ef3a653c8fbdf8ef187878c93684640e285aefabcf74cd61ed9893ec50215d8373fc7f311c3231fe2d78f4e11155e3382035205c1a50d5010d1881d38fd872f2c74cb30459c783fb439e3e56b99e3547ec60286829e4d7e8d5f86f8124d9182975aaa9bdacfb0a691ead298ac71b7958856386d080885aab164726643be69a759f8d496d60d4bfe9c0d40f5975066c9e3b682f241d717e48ad1379b0887f25de68ff310cc6f9ebe7badd92c3d5c6e4e49833be88186f5be8f214e410d661f66107b29f1dfea1d0e2d1a05c9465f1db5ebc996de9bb391558e165b3ab78c1a4008c5c63dee7bda2ef7c1ad3d4f39edcfe016b66a935c57f91aa05ab9920086ebab1c8e4548780dcef78ef797acab33d1603751394117e86fd8a2cdd369d193dea88152680cdef42fb5a2483714e4a112f47a1b8c4cab9e7c08c870527f0d402c7241d2c0d3ed9602350834f1e151d16d402b863e8bc60643e6aae001727610c22c1a6aee0110851ff4cc9875939c01a27be9d6dd95610c29607ce901918b52863c48bbc54cb74bd05da661babab4000fd0dce768ea7c062eb20624206508960620c1b3ecb035e87669a2a8b15cf06ece5d49bf88197ffecc1dadb129c823aca5d3aa92ee2d3857c5ad80ac568e38e0528d0ad361bea100b7d30113e115254b6d34ec1d74f09aba6146f7aeb7ae5cad210604e4eef493af4ca5bc1dd8cd422ecc9436212a61d19a687f912b6a700e2d78fbc0d58b30b78b5e21fb6a7382bf5165089f8dec33354e36db56c9c629439ff95c6db8e8e0fc48832ee6986fdf18305636202bbe4e0b645174020a72699895a15797b2c9b04f68198b0ec67755ce077107ccfa8537d1e132d9e863ab71fd75e7a7a38ed0db49f0284ba0548d535359d8976d166e55420f45c1e4ada586f4120dc1bf19c0aeeee526f4207e9137ffcdcd7763ccf5859da30150da2616f2c524c5b8b5d4b41d6857a504a5ee1b8a695cf302ccfd3ae8ebc0d2388546f1b404c5098f4b5c05383ecd5560d7bc7d428f4da2e8c1ef0882f8c6dc38d43da0fa5c78420fa55616a9ff9934e0f1a84a4a9689224363e1613a7f73acfea53c41cd025c537b50ef77a29f11f63d25c48c91c6ef1ecee571acef1de45e05e9991cbd5ebdc52d639b617c4640a990ebff0d4af225c902c690ac015bc0296800daa25323d2e5f851ba9f8500b7e82d5a195cac6f11ec746e38a04934bd745c76232e71abf37d04f77dc52164702e029fcf07b00c0823d156ed9284af6d9f00475af39901a14fbb823e5b407fa5c5df8fccda18dcce74f8f9e38ed31d9128f765aee0a0359b54cfbfb8e7684c47049b099369aec9b978bee0086a60f1d2a55a7a4a8b44c44c8b431387579b16692e925417a5aeb91d3d364c36caba1a40acd300a88afd4114da38044b9aa75a7e1b5505c2ea7d23ebdcbbbb6c42d25b9d582619637ddb4c4aba0c365dd62b7e5939a1278f9e350d8a2b4409e0a7fd506600e0e53f76bc7dabb9b416cd57b3290afa9cdde37baf4c5699847105085a17de9035216a6d0f5b4db7f9dc9785ad137379390cac6f508b885425b5297523d56bb78e8a79c1a2b7952dc56fc12ff019b42b88140e33c95cce44a1a9da13b8cb51e0a69e8a266502b35331f27a062281ba7c4a618386e14cdc91e3047885bb070463eb1b46e24a6705ce5d45f4a3dbfa2f013a7efafdd7eb1d948c6cbcdf8fe4fe368377e1a14fc35e586387824533ea453435febc5fcfdc4f6a21864e28e674a5f128f809d95efc4176c730105e04cdddb49da1844cbbad31d0a3183fc8ce79c0c8d036efda089411a5a5602076f5ec8018d9b2764e4df4c4bd04bba52adc743827eb40f1f7a840d447a1bff8a4c615b881a88c93b2f97ec6d79d446212dfea468b0b577c645135d9103660723bafc7001b7ab7977d3340adb4a638ab2731452205471f81b57812fed1ec4dd9f7d84af7a2a8073bc28176470e28a3e43dcae49dd758b7805848d618d01fd509ea28332f0d4a37d8bc5c18f5ed801248e994ea9d2950cdba75960a267f6229a41ca0d614fd881faa80b1348b58b465d3d15810b970682c43fbc37f4561c11cf5e8f761b66b463d23823be6daccada57cf62696ea2e2be6f20250c51fb075cea142150256e8c433144a2f72cd8ac9e4c628bffa7c91824260d12fbc91da1d138d961d729af31973e37297ea147803674c0eb90e87ecd231a3d31003004bffaea8a4ea88de418aadab1168c42b0f25b9357fe320a30736e138593fe629bc29ddeb985ff93a124b5fe7bb7e0fecc7afeb278aa685f12682c901267650790c88cc0ef6c677f278cf2c8881c2e4a93394ce38ffce146afa9d8e7f944476a9328a0b8bd780823080d4a421804dc06c19804c808c4b393388b0ca2fce96f9e9fc8206577ae6cd82e5ad64e0d195371d351617416a2aad6e4a49d3c2cb21d5d01718e3bb25072e485dab0cc20bc7aa554f3a30d1556bb5a05ebdf168ac1f705a605c9513a85a7dae028ee4900ac235c746af527222aaee381a90f024bd5a0d6d3e06a257ad6db6827432ba74c0b5cca1a66119e365befad94a6df23aaff5695ad54a53ef4bac55227f2f9a4a4bed9350da751e39895540e7ed16aca2bd452ae4b920948f36786f62f5f89529c1aa2b56e40b12af1971c3162f667380ff5f36591a13c08403d18bb56393c8d97e910ebf82110bd6b59fcae92c2a9256ed8769808f75cf792a75dc1f8b425dd950266ba06a9aeeda8f589edd84f88a2cd6a01c197b62ba5f9c6075093f2e175a51edf56dc3bc96ec23e501bb03a9f0db7d842a75b2a1a607ebd7cc9328ac1e1e1b71c735733388b12b27d277401689c4d641adbf1787428e60158b5ab71698e3cb386a61edf25d6c60af2fec3acaf004b06d2a00565943aa9fe256bb2047406760ab14632aace205c212c2292172f32b76bfd481be1c6cae84187f8b62d576a871fdab0859941b70d07cea4f9ec0331f4240ad91d7f6979c395b387ce8ebd948ca2ccd876d57a12d1976a68a8274749a9d0d6e8c44a0466b51f2c9dc8720fef7ca2dc9a3740ad013ad0fb1fb6bfad7b8caa0c973ebab88683436a70fad7357c9c7405e4532d3ba6805329f529f4cad5ea7c34cd4167168002121ea8afdebd7344817cd66106cc896ffc50de4d7ca125cff8c79adfd51660b14e996902587b31bd9beb90d898498ad7c7bcaa3eeb2d78240c1629d964f8ac2a8376e763964f39ee0baa4af460f52abc57854479329f65696663a49c25f63d49f4928258d042981e262a4f3a586d0e46bc899ca37d771732de2597f8e27b68af492ae5ed284d04acabf572732d08efaae154c03fbfa097a3e076ed865ec7021225968430e626464af86905680f9cd8de335ad24a66d10089c969213e0eccd56c64e3d620f7628fa6e3b066b6f7fc6550c3d25c038059f208a5bd5814699c09a6c3ace24035016d1e427b3fb5b0d09244ea30c4779a948c4ea47c1d988b66ae21f37ed6f37905706d871ee5ef46c14ae6774e15c6fd198bc4a1929866bbc15276a987fe4169cace3406d609be3655acd13ffe95bf256f7ee6b4516e9eb9ea914e7143941e9ef569f704441e4830a3e4154fcdba4c2c10e15a78028d310909f456a6e6492f91f2fd28549115c06843771a7dc9aaa4f1e416536f6e50c084fcdb51bf73eeda6f5107c8fcba3eac0c7416333ef04bc4966541a8c5cad61469e3a38e5938d15bce683b2ed594689b14c2d3e4d3249d79b6f7f6fc41628404b5918491e29ffab657d1ff80100b14997a56f1f24d3842e2c3c2c06e54700c86679682000f2c0ba15ac79be3d645084caae7408953e297793187989bcee6afa764daca3872e820e10bc78751addf376a54853d55236068ba77a4fcb6926dad08645ed3dd6413af1c2c96f4eb1ad5a7176733301bfebb1369be249c02721bd9247d0b2b1105fb1f9e4b966ef34a016a57a179dcc9c74b6ac32163fbd9bac0ea09f4ee03e711efdeb53232076b3496fbc400db90cf26a04c29017fd5c854dea7872a9ce3047722535c7d652892e375e512e25821988fa45222a5f140943d1c3216a44f6fcb9c445d29ec263b7ff37c44b3454756188cc1335e92c82c63835b837d4d6244c22408c30da5f2858af9886c20817daa100f15cbaa98370a1880acc29d9a57b9a1841eb97c0a5473ea9d31dd8dfa2a8d163749fa226db2085d7bd0ee35e366e01254724d51077225c642b48ede1f839b89919c3653da4b2711ba633a407815a451c2ddad8249f41a78755635403a3af4c48237a730f79ed007084f875a16b36e480c22d7594ad94b110c860ed236114915f0a71f5ab52eec78f53886d6954964229aeb93db8bbdb8d77cd6872e7d21890183a48db4b8313d25e1458e354ba8469cf2579357b5e6ed0a82eb0921bcc8425747b3fd89090eee22023b20086ede1ad0e07e665c1645593ff285b3eb70659db448d793fd56cd52cc8a19c90862d94d7b7c21432d74674c5a7c356c4d54b03e2e211be07a26de4cf0773c052d3b02f97a6fb6da4e002b6091204b8636afd7be726ff342c1a4c126ae6be54904e4332f7a3e34a80dfbebf6665701cab558f93067b1dd653a7a11f2935ca6eaca8e4ac0990c98a60c2c8270cde35cf54797a9983f94f830964d0addadda386be03577d9948bd6d95a7d63a0d16c161aee70b74fc0dd6b21ae7d6578b300b6ce7a97f6c17068db0dda88eb92dea01d5bd8ad7314d774f561ac9abc628d40d31b70fcc38c4da756217389035527fafa3e99600ee7c99481adaab28f1e2987815d08646315851625707f9250d8145435031a486694c85abb009cf863cff97e881c7f628b02f051e49b4ea89e5280c2fd87304515e5495e89633590318043664bd412babdb4ec5486eff84ae3971115f20f2b8de6763a85c873ddf3d38c405467722c341fa3a9fa9edd8d06304ce0ea245f318bfd2d4215f3ce18e350ce28cc3db7b70921c4e33ec12a311cae3f8c8baf360edb9d47242b688b66ec667ebba6a750e495ef04e677f5d8c5bc55acbf1ec47f48e0e9dbbf9eb35ff8e4e6397e19a2a1dc57a68c24fdc6a4a40fec5195ecd431f6a31591e82cb8b268b4234798e055b8361639eef1cc766415d6486f5a9213dd42d68092eebeaced0bc0b82154ce78cbf7626b3027c9bb233473e8769ce269e697b7ce85de93434ab0e00309dd835409554b8a2a5a8145b74e0513b01f7d19ec7573ba0fea14858b84387258ca72d4819bc9b57f8302aa7ac1712b9d0cb7918f3c0ecd4dd752e7dffaa20a990f00807a32e3a3a1c09cb5bd17101f753b0026657b9f05ec879c519b766aecdda8bde285770f5d285f4e8ad82cb932361fbcd3937eb862038796e1c4aa9d243070caacd110beb759a83bc6b7b8b0f639713c2132daf18471638a662f94a3e93aac0a4a71ba9c744d750d7be4eb663650c56e80a1a6080271cae81e46927af419e340a088c2820503592397302e80dd61c1fce888c886880c6d28bdadadfe86d228946dd78338d66f48f3f3b9f7fc991b6ac0089d89b30f5ad9517ece26a4f3d8e8385879d41211bd62394035dcb7336bb96ada44bca76176c52b485a17399a1a69dae17366158c5b81d46cc6deac01437b7497b8b2b18a057ea67743e53e2a4fd55974660507ca6f0a1905ad011bf715d0b1e3561b0a7eca41e5710814732f71b48e18c400d21fa93b0ff69963158068619b2edd3a4f67637b885d9d140249441659f0c308a7f150a6720a0f3abc85f6f62751d87603a3e13d5708689ad584fb080299da7da6cd1177eb024d15b92bf2a80851d6fa6faf334c298dee84e927fbb816f33b5ec2cb93753f793a4ac63cd2a4e58d5c276960add7e3a59ec85911c2757f40e642904a192e2ba9fca8581c4daa2e2df8ef5bcc307438fd6484a3c0823f6630c9ab0f609a36f3de8c13908d00695f113c12d9612fd8edd4c26ded72511d60d9958a19b863461264afcab594a54b24eb6de59ae64ad5ebcfc6e0d5531174beabfa292f98d001b4aefe7664c9e03f9f0ab270d888436558592d1d73cda4ea4d47e4cf485619d377bd458f464f405a8e416287534c868b046f64ba831e5d92eba6502a194145ddaa2d051ef3538c9243a05d585a187033c9d94f3fa2d2da1fdb67e99b2cf56e425ebec831dcd49abf7036258c88fda1ebbd432580771e69fe64470c2f0864776128a1e63c9be1ac2490fb2e37b3919284a2fce388c0d6a9b884c7338d036d08fdf8c7cd44689c38a67e664d2631dec3496e792137edd76b8038d173d5b2e91c9faae2719197d60d4f5bafec375fa7fb969a2ebb4e3165313c2cd3f40c1cddecabf44f0178244baa2657c3942fac38a0fa90eb35fbaad755c91e21765b3d02729b8ab4b58f619220b7466311b69602508ea6aa53a2e3f4ae5dcc7a76ccccbac514af40c3d8952665907e61b51c0a9c6acbf76d2b37e7c7c05c4bce2b70f460b317cffbfbe15e3328dc53013a3fe2707fe39636cf9f75daaf0a987cccc0d247c8ee1e870081a6deafb2d2bffb8f2480845672e05dc923d2c780232d8cdd6e2a95c0450a7286c73247a0cfb7fe4c2dee3da32b940f63c99a371f51337a216ce63e0a6a7dfc7f37a15ac608146749e3999640aab0e81e150fabccd14b26a1266cbeea0b7c01bd0e706b6981bc32ca6ae54023c158c5fa51b115a95958d9d643d88b0388f39af1df55e2dad0edaed1b33db24e60364650594b3f3abb249308ab3a6414b25f336d012ed8fe15af8819adc5063b3eac79e63f7aa508b53837fd2664837a4d31e3b746ad9c86e6fbeda1fa3a82ce0e453b91cec06f8eadacabeb9f1e7fffc68911881dbbf7e2996720f6d17eb8437a7e8201a64ffc9f2b150ba310aede19e206a3e4d958bb3d6c09fdfbbd3abab21262d761a6c95d5086f2f8d8c4d51135d28d96df6573ce887f171ffabf4a72b9eadef3ff15af839b60d51d067ba76464816edcbecacf2f136c9d1b3136574756071771355c530ad139d3857830c131329efb151513d8433c32f9ae3698e65d5d897532fa9ab25297169dd54fbcc2534cda7ccdd135433216ce1453607b361fa26aa21b489a0349feaeabef31e08d38afb4a52850a413d5bf0cd3c2ff1399cec28c537fb565bd6b812f35545039b66070cd7e28f36fa7d5a8439bfb403210258de6c8b07045c1b66b95ed7f503a598191108d9dcdba3089bf6b54fc3396a603c2a8494809da46d558cada91876f846c9e61c7df2288acdc6a4d25279ca84a4b3f7f9f8d867942d87fd8f10815114c12c2382389ed507cd87edf04cb9a0faae56e57b42d6d27f55fc1d271bc3357296d900e5a600949f348abd7bed28b886b933a637d5841aa9d8e7c8508432c8c80ee739c14538c011a487b4935c863c89a18b431b4fa2bfd727a6e8d4307e50d888f3b6d5e6d5920431f215e4279bd123210a2c8a445c1f0912428c18a2dd4430ca78413fa425d34e2ec26d353f8e526edb692e8730f380eb1ce74c2c0f3a429228e7ebcbf48df355efcd37e9458cc1657bdd30735db19044676b7f30fea6158fa11c68945275c2b964592668655f6bf0992e25c7ac55d83c1aff6dccc07ff78ee1fdb8dd6b02f318cad96eb2a0dd9a77f5c08bf24be06ed05b57c51f96855ed8f9a1b32937a0dd23fa9cd23f6e0035398414bef5c0c4282ddbd5fcb7aec0d956f2c4205de5afd9e8c1efbae50c72d542a6ed79c493604eeaef667c301d2e76ad514a65684a4d99c43c9c0711d95744a8f5d11a0f11f4cd675551cdca55fbb4a9b68a904c62bb5c66729390306a3243089a097f8ebfd29f2b7c6dcdff3252a5f540c4faa0fba7bccc56121b502506eb3d621224249dbc2642a88bf836c715bf9f601413c95f2e30cbc18415049f7848fde1ca557719f46cc596495f91f71a4483c76c470729ede72f524f70fdc4a7828feb9a572c77d9e02bebf1ddeab16a183c74faf3688734ff05cb6d3753028de2878c728fca642d84e1dd04192a570d6df6c5ae0718cf77ad82f0d071f49eb4fe7206909e5320d8ca0b6c0ec83bd0d473bc5cb555a3f6200db54a5cc280202a5972552e255678b31d3eeb9e13895b06726c10f36b217677015bd2b05333c5f2dbfd5a60677329ea92ae7aeaae2ae307cee3b377247c6722b1dd692b12dcf32dea678ed9cd14a03e90890cbd255db5900f023cccb23096852f97fcac8a089438cfd14bddc95f965e30d5e84da47ee77d8266d633d72e76e21a5a5592a767daf321b720f7e49b26b3205a958ee49900a1ef148cda890c8730353db45d75ba03f647ae183fe1d13934354bb28175c440a247ba6f9c35e526f3b6995b8164db3351da63bcee9c02c08e22066f4af43b62fe6533b400c96c4a3b62dfe901fca624f65479be2be809289c4624a6eabe524c0c820bf9711012fb2f99afe1bda30f7a888758484c750369ddf24754095101091f221d24f0e6429bf7d2332fa3f2fc992b6b901617b1927304a15871e84856122af7f52f4c3e1bdb1541a72351569719511753bd10d9a2942d071833fbee5f50d926752dec7a2dc424ac6fc402460d0df10283bc057bb7faf85713ef3deb45cc2ad31f4e8b333e0aa02ec1cff6d2baf2f1212d41c29f3c05d79d0159005f29913b5d4c89508088e20239a8e9b5413b7f5ba86af98507235c409086dcaa5bc247c9ca201f62d5df640d6641caa4fab06f11fb9b652105209fed575cf6451f16ad4911c582ff390609137af9ee74e87b056ba173c9103ba8700201ce7d993a2249d08df4b3007819144334e52efa398c5b20ec2ae599a1d024f81c429d6b4859c87d82ead095f193aea7eedf476993e1c1638465c9ef97212f2dda4dadb56c95058ea466670c174a69a1d6113d202fff8d31cc3b0226e081c8b8c1653a9dc96d15394bb9b727ddf0f530144c63e94f16e9bfcd82135244ba8836fa4d46426f1ee6a09852bd9013d969d9ab5d802c523e46b46a5198739ecccbb921be9962c0503970ac939d7bd0edef5f9088e2a835d4a6da5a090058a8db3d161fae3590ee57d6b566a349e5013a6b90733e15ba69adabe1336777ca2b3bb3ba321f09dcb5b83bdc60086e40419a6849b500d129e32d5a655ca195893244ccd664a32bb2e97734bc3846f1f8ca82b4c38cf29e37964a827d5c09774a726f5c49d1ab0e6e332e24b1ab593aae331eecb27e70e2fddfbf9451a59332597705e399cb0985aea0906759d93bce6c7c1080ebe11a708311a68661d05dc049145e4238650bd7a380ff02576dbb96b80b06f95cb905a15f1bee624ac1a96fffe8786af33d1613746d2dd366e36ddbaadf184ce75a24e8188b712a33da9635b98bd8dd46ff2fd7a358975372fb32b50768588481cd85202fdb4ddb76de8871e75eb21fa5cdb615e3300c6068226f8e921a276ccfcd3a63ed69cc0fdc1cc87571e1b8cd88b258b1cae322ca92e4b2c73208ab0b23b9b5b6d7c4480d873746daa462190e997e987ed3192d04d644bc376f483597cf5d6d4d547f2418d8546de3c752ce0357008e46f85df7ff16e16d31f25e159b9e29a35e3915cbfeb0132dd5232e129d2e9a5da1f8719575d07af584eb2eaa872618d4759d6694f291f5c5ac1c10d3b7d57389020b921879f7648bdcd424da99a7e8fc15b8f15bf462484cb846325dcf8686eef4ea13e2e6c2be02770ddc016e338254b510602232b0580e966d819e30c3ce2f2df09858713c0b9e16cb0c95e27c2fa21d0bf5b5e3fce0c4156d36f55d0bce5532dbdea37a4013b4d95938a79bb69fed82c7d8d9f17fd76725744779bb5484d8cea9e9e2761a0f57a5cb1c78079311d6f8bb1abdc54bacbffc4eb8471b96d0b8a6e042d0815dff1cf77cdae33ceb8f10512f70c51390a1e04f1362f6d9bea9705972d1a4f414273b2bc20d912f5aa28a1d7139a8acb859c997f6f70009b6e131bcdd5b54feb3ff5bd9026b9928eaab567063dcdb2b4ca603c091e37a59ba83a3ed758d56a08eab023a583118800e03cd579016423847079d6618d82dcb27f40544140ad77d185828b2c93cfdd5d3a10edba6325f07458e1b40ce1aa2fbb5d1655f916f3961be6b4035ae066bdeff8e85e41c30726c39e6d20e3988aa629913eaf62f68e940a89b2a22cc050175ecd4c71e2030d43fcfb4833f28eac6c9d92ccbcbaf4a04b485b1d293899b9c217ef3fc5a847d49fb877c50faaf378aca8fbe692606ea56db9d53eb2f679600d78e9be10663d80da06622a71269bc1cb525407c178f9c5d75b561c87f6d09734576a21b9772ef6ebc1cb5cd60c7648bf1b5d7b1c6faadb508b1eec8c9efdac68c0ada8f044f3135531cd94a6b480c765e324adefacb991ec818a2514457f4a9efbd7f1a48ad0d6bfc05174cdb25d0a4112750fc3fe469207e81f455e0b06d40c38f63982b8301fd85727a6254a02a49e6ef1538326b9921b59f5d4970e0817c857e2509cac3b5044b8a5ca209463461b1a48e6ecb2d159125a9be0739f52d0ac73d33db97174d6b49b12cac644b320b8004a97d0c286e49275b6e58d1f1c05bd22908f932874e66b0b4db79d2cde84987ba08d73307cc737cb8e94930ece33d10db3c0da72739f53e73d793ac29f6242bed49a6bd42b906c8a0a824d13f2468b1ff1240d35f26ef35e421538fc3947707ff65340989a9f2f0fe61740db8f24cba855982930613730edeb2833c6840f8f479fee185121959413f2722fa77808fdd08380bfd4a3bde3f7e90fda45f27a05ebb0d6c01aa67f6f62b397ff97241f4227da7eb9648e3a037e71d822002578523f1192e788225c804c4b8b340859e44fcfee741909fa89c0cce922615a202498743f7c3ea7360104b42875b10220f661c95258aa361e5061c795341c750a3abcc43dccd099a4f8e14279cc8432e04242265ca587fc10f3c9843d10e72608f34d2cd89f2194f3014ec48b4e3907160a73488bc05681f65311885a9dfff77d18c85ff70b9e9ea6ff8bf1ac9a61cf40186f0fe3b7924187669cb146698572b159afe453e63923f682bc5f94fee3f662d028f25ecde62c9fe4bb3d59cfeb99577fb84dfa641bfa5f619624a8da03929bda4670889e7337bc6806cf0182be1d6c3f0d9ae7c5b102842106d79e1a2a2c00dcf628b66d96f11607b19d5da1f6b95fb972983c45022612e0232d108d6697ee0f17f169ec7c17f07e5d1521f4413f967b42b96fe8ca83a45a94b54c8ccfdab77fec0825f348ccf579377c7d50352b5fb052be38ec8328178bf903b272080e4e00ac55349902443fb0c9e38c7be6378a034af6b22a23cabb4370cb20887f675c21dea3c123fdbb4d141426b5b7cb566b8e6b8bdeb9320a62a2e03dc1874db8388d71bdc85277e9dd220f20ac067d6afe137fd8effc7a31bf2ad3d5ad5c2d2b74df84ebfd9585c1fea13e4857671ca1466d0db62220aed73fe1857daa29980ec522b7fa860ae8c61fde742fa66e989adecd89f7a7e819180c55b260089cbac9eb072605ecb77e556e0c850c88b78c21f4284d0cd47d2a774d863888efe19fe1575d3cfbd6774fbf735b96d2d57654af2022925226e81f78fd2a13eca5efb673c5ab658455c6bed3f6d11796263ca19da1b6d01c57f6cb03f6af99b9be83fd0cfd5f3f347204dbbee04580f1d776421e8d04b8705138c6152101a9156de3631f3e05fd4d3e262f5d460b387a5a9e31a8d3ed9f1b8b4fd805a9efe6413a56664c9d3ac82d94bd3e2b996d3e3ce0173f112d22c7b38753155551773c5546030572f6f6cb6026bf0e662338289ddd6bc50e5b43a98e3999fcba522d6eb09b97f9d12ce40242b5d068fcefa792d8a83c2505c081aeaf122390c0306d1d640e28b53a98c88fbe577df43bb66fc6a7fd1ae3ff61c7a6cedfa808e69b5dc37608afec43102788be13289ff6bc35b745e8b06a6b99aeeb9bc6f35365fea6ed4e2a6aace7e6696a96b0d040d3acfd5be7525fd625e80f344db3957cd5c849e7ed770057de4df5b4ff36761ff78c0f7c0da5d774f6a8447058f8e093a2d198aabfd63ba10cc4476076f96723fb3e202d452dc3efd015d702010d21402c54970b5d55a2058b97af2d655bc57867bf8b9431b98652fbb67aeb639a35c133b2e118bb813ef2a24c1a3d90ddba16dd2f08a4fb519cd91d3013b53e8aabdc2ace5e900da2b604d50986de56e88c64eb6824ecd14cb3662b1193f27ef93860790151565e5425bda90089402d6aaac70692966aae80f77e71ba22395c70ce2ab5783eb87ec5b320834d57c71adaa2079176ade8bc27567e6447c3ba558d72b14f806dfc88981aac1c81b41aad9eba71c1e27106038fe4e13041e1133f82586cfe589af2358ad13421008af3e6f856e84d84d6d912059ae3c3c707114b1262ccc9d7afe6b3e088bca4d65647f5d566e62f0a7a08c38a357c2fe4eecd4822226f8daf157e97c9c223dde3e7850b37bf25497791213986669226df6ddb599bba9381645f8cc49ba2f8599de79e112b709829355e680572a7f4ae4e580eacecdc4a1b5eda6523247fb764a65eed1d2c976bdf79ad63953ef5c4cfc8960c18b74fd485f6a166a4d58362feaeabf753e83d33e4d9374cfac54967a15f3a98dacd2481c747500d6c6cb7b9b9a1090589a10aca54bf6376455d3c15cb933c28b0f12f78ee4814620689f80e078f369e444a9a662bc18d41069de2a1687caf133860a47aec10585af4179e7229287d044d4219236e4c2089a2a483f13022bc3c7230c700526f97859dcd60df1c786a8708a18686df824abcef17a827de670a459d4a964a9a5cdf3b09cad0b9072aa42af77fc7685e03edb9e89ff33bbf06d94b0c2336822a38bd910998844102c11cae683f832b48f0cfcd30f55e07095f140251904eb7ca0fc18d0e60771c1ef94f375003109f373a2eee6da84a736e7e01f38bd26d2a3a18c6a355dc2a8b2ec556643753587bf6345ab1c4d0f222161f3b5bc4fe890bf69ffb52ae17a92620ba9ce9e427b6f139717da5f7f1e4b28b114d9c197b6368fc11485d57efddc76a364b54106dd388f6b40d62c5cee289355a1e4d7c4d5427cbfd4ae8fa8ee06c357db5916cab962a3600dd77789c2839358154acb20d219d6dfca3d1428116044cdc29a8d570192472e948db87fe424da1e0631dda758b3339732fdfb335fcb0c613f3c436726ccf99bce9d2bc8bc6f9987411beebe4cc58d29c37ed2e5b18f638d9666fe5a63ff2c6556e11bbffcb322ee4f2152d24eef8f97a3cbf3824011d6f6f70bac718f9bff6e1bf16ae0d4fbf555517dec383beda7f8718b22867a17390e8ea02d8f9e56411d615557c33d1a52b8a4f14c933eb025112608803270921e56bdf5d5f15591113814daf10d65f9e61e739d338009042b6ebd517ce7a0529ed5260deb8db39618d796776eb186e703ac98c1d02258f985c107b1469b53b5b7931b70c361a3783ad5e9aca8f2a050be6c4d12196d7ea94c42038173ef4ad3ca61992f72830aaf18a1e1566910d3224a37340dda944331cab6fd0d529d184d66ebae41ffd8e8adf9cacbde1cdf4252a49e9ba3fed54ea70ec6214de06ef6c29ae51a6272f3057c78889a05c15631c6f547dedeb75785cd97aa011a385f3214177170ff57428702219d399223bb616ae86f21e196b8ce5aef0a153ec06c554eb82e9fac7e14ed5882bcca36c6fa315c63a40eafb44d8ed214a9e98706ba72650f24df8cc5f664cf0ef70c2b657d91fd46357e3c0f501aeba3f9bf18c016ef60b46c6d7e2ebfb13cdacc2db3d730dbc50eea2cd0ceb0a9daf8862f36d764293da5704057dc888bb9ce102a7ba85e7a827ad762f6a627c8153595e2c1472d46936454d87d4d33cd15f37e4268fc855a940da8dea9e2e060546b5cae25646de0952aea67479da85f77aba1c06b1d5aa79846d4dce3a80b9de95c170e309a7f69040bcf8a2590e383610acbd132459779862d0873a9087a327cd847daa60f27c82ed3b03a3c225760badfa630dcf4ece43cb5242ec3aabb8c9ff7a5bf2fe359bdb58b5317272f6c6121a52e4bb7f90b7c00e270a2de9c8c4338833bd58eb62b5a6e8c724385a18cfcd1dbc28a4f86cdba18798fd708f36b79a9e3766b35b030fcde4b84fa0f0b83e4d2a28460289fa2115c2547db3652ae0dfde90822d202112c6c00218959916e60e5bec90508aef11fb8edbf6712ca1f56996bb9ef533b1341ccf399d2e8ed669a10703d1082a9cfd22311a2080754cd4fee44fdf5bb86dba37a3980ce5b0ab75db2876f5eb060cb6d262d33998190d7dd494d38d5457299606d65231bec064c9303cad752925b30903a4e072dba2dd1c8143fdfb2cda47885c2ef475ff23e0bf105bc262687d568365ec12fe42f59be751dc2524fcd0feee3fb73cb5d9f85013bf37c03c5093883cb17afc39ac5ffd9078f81e5ccba0909697befbde5de32a52465e9081e09e4083f374dd3b45a674f05f00af329fdaeb79f41381f761326b86d13e468ab7ebdf55d4aab86b36852911754c2ce241c5dd8241a285d993483305dae4c9a81923b8ba4f00ef73f5d0522328c9c507cd309e9eae7cf04d39da12909cb3f4a32291004283015183497ec702507980b5b9826b02a2ce56826195161b159d3a87f822b165b40a6d3cbaf63358fd6f3a3794ebfa4b258d61a2de12f01d90b12605d0f57d03e133b7ffa2a1ab682a03ef543ecab4224aab79f52bd7d24a947d1501a615dcabad9775ead055bfef6250c05b63c6c05f11ef543beb72112fbdfa3c2ef91a0de7b09939f01b6f7d06a9a36414d02ac9b85a30ad708ab881672cdaaa136eb6fde09fcd1aefe5a348d8aa651510f0bcdc362dd6e5e120196ece1d3886524753847063baeeeca2e6dacf2420ca43347ffea6f14efb6d50a74b58d13a76a037d5a9bd7bb6a92cd639d755dfbd5ea554f64158a777b554844b68b0bc7bf5b38025ded53a16cd72b49d1cb4dec44b4c0a89fc5fa9c9e122a17960fad7a554a2935d943ca9b672db50f2ac9ed88d9cf85a99405078480a53ea881880273a10613b0545825fb9175030756f52b209eaea941d97c10ea6bc2564d02fbae55315338d6f0146ea1d64b35dfcdac55df7e12980a543dea85a81ef5b5864256ab0f42bdea93c0aab366bf26142df812278d47bd0d59ed12516195ca02a7a05e5e21a830f5346fdfe6ab08a979d4a3506f5f08eaad10d4db84413e614d68847a9b7ad40f493d8ae6edd364a0bc13041d34f2ba5df73456ec582fea0b8b492c369779cbacde876e8fbee4f644bd2ad63ca89063ed1a6a9e55c8432625aceaed07d97ccdab542ad5ab4217544f2344b27a1a6fc320fba8b75c5814c842bbfa576252547aa85dad85b17bc4a22aaca2030a9b7ad6cff8519261cd08e792763d4182c4260caa2264c6dba71122b1d686311bba80645a61fd8c70092b64220640ff8c22206684765a79827a541854659c827ad4a3421790cca59ff1369c38b8d8f94433c22afc354a40d484d3c7934906bc352fbf06d89a3056c5f4554cffe3fd8e98fd46d69513d6d5ef67a394fe09f2d24f721d1cbfc8e5a7a08f1e4e9de432a8813e6d0279cc171f58811c213bf2518fe925ee215015530db1e8812ee4bdd4ae7e15d864dad59f1a733d5857af8a0b3df662f4d0518771feedfd47f7b19b09fcdb6ffe2a819d5f6e370f8f611a7ac8e1c8646e8bcde3432cee25298ef54a197228e7c63bab2ee3314f7fc13da6bfc9f0e0919373e58d77c7bf632f792d1406982630094494d31d9fc6ed68f3e0f418de11c363bc6303efc82d2ec0725b15f31daae8a52d636470c72e33ba900ff9122762d51855ac5f25c43b6e823959fb4c68302ccecf00b28abbf109dacbb06580faf44fa817d8be821b1f85e19d2decef32b0bfacd002dfca2b84145c817f05ede5a5e0c89f85d93bbf668124976ba83d83a31bc0339e32f4b01498e649856ea57ba8bff04e26c5adc0bc1598776cb097a44e7b112c36ab84586cd5902ac6620e2155ec76ea53616b40bafa8358eaa19928fdf490d4691c67a6a45a0c8b8d02d95ab93da697f8073bf2d19201f83d4c52c4f597973f20fc1e3216167ba8879aa7977ac97ba98f545d928f6fc850c30a9a79777777777777e6b4bb9b524ae937edeefa2d5aeb8469da4f9816da76bdf6b57bc0577777d3eea6ddddfd51a712a79b7412a7061576be9c430dc69650e19dc9d30a75167867944997df08bbbbff903dfcd971b02d20d9ae24302993b46ff94f58386159f6139685b65d9fbdd6f3e2312a34cf1c922efe5af947f3d4da1ecea14c876e8afca82d1694cf969f82dfaef90ece2ad3def9414e44fcfcf7fab0123843eacc9752aec04a983be79c72ced93c23e7666661d557c833640ff964280aca2c5db9a58cd2d1955bcad8703532b75f7e95a2c7b0a19bfa2c937a277e76abbab038a6d899d43281af943d2890499d7e3006cb4a9cc30895f2e1a9f3ad639601393664c729d469b3c6b9e8aa542a950f53c0833367cc5caa74c72456420948a5cbe10a357f7af99950c35fe99c737a8e143bca2d63207165a625960322ea19a572af1881996078a725bd0825a860b97d74a7d74985775a7665b98d7952b96206c94c120c94dc4e4ec0ca2d6348b972cb0dbeb0e0ca2d65c8a0eca7bacdabf909d6bc4af53a606bfe8e4f02d301b6e6e77c125847c46233941617c1620bd1f139ef60101d9ff394b118f1152fc357988a9520ec388784a8dcbef96e7dd7f8b6c90183aa702844e7778441afd7f9a0105ec77735c016108fdd1a1d74f20352e33ff8aecbf11d38af8d0f0ed816fa8e1648726fe0781c8ff3e24bde713d082bd0cf9e82dccf1aef6688aebfcbcc10521965ee38633058bafd930c21ef997bfeec4b40f6b4b5519fdee2c2d696130e19211421f4f7c071fb9b2f808d0c01f3da781ff6707e071cd0f5cfbe03cc674aa9b7b6cfc2b1d5a24f64c7e73c91115e84ec391c5bdb8ecff9213bc29c70c808210b975f8490859bbdbc4097dfc7edffc7bc369e0b7d44b1344c808df770051bcf852bb8de8dbc2e0d8dbcae8d50b288e367381a795dd7df3c08e0e857fcfe0c5003882b74167184efc17b38e2849245f19d45f100376e7cf737c0d185db31380f30ba3816b9b49befcf37c21149e67520770798ef210d470fbe85aef1a3b3c839c21cefc1f3cd91231ce7edc2b1f300e4e7ee3d78feb07bfafd707742f8a62d76448db9fd2d03f8cf1084cfc216901a3fbfc6cf70e42ece239d917273ae443253e6ae80f31f7cc71f10eed6f80fde8725ce7ff001d839c835fe03a432c6dc0f1e07688a36decb91f38de386cbbb3173841b0e5728de0847d68b0cc24f7034f2ba1ffc3f7503d4f80ffe8370c47977902711227c7340117e0738c24fb0bf56909c17e187e4bc08e1901d3f4228db41be205ff9b58288f0393f44841084cf0941f82120fc8e100420385fe37d181c6768e47571c20ffee67dbab317bcf90747a07bf3f4fbf120fb7e3a78dd0bcc5b0388bf706b8453e9069c4993cbfcc2624f2a34425638c390110b6719950bec38a9cc89e3073bcea157d83f572f5734341c59a16c97874343d5b25834cd49cd49493f1cfae800254c67fcbbea57552b37d5281bce32edeabf39b2232719a95f4df2cee953e89b734e21b8b093b9b0122781c0e62cd9f9322895dcfe2bf86a57bbdcbe9a271c7b5e2cba0a9542995e5287fff56229f15f8d5e055a26ccebe3b7824c584fbb50b76ba794d24cf32618b6c0b5dbbc0956c06f0bf4765de7d1ebd7e3eb7dde044d9e111c6f9efa9eacb516e5a1be96b429af6542df2975bae9fd1870e6c92190bf3a14dbd5a9522815b7a95455cb5454e59dcacc4c77f7e9ee2ea59452b2bc7bce39a594337420b168a62389adf783f7b028df260acb1f143bdf260a3baf4d1456def95d5397d29daeba339596ea764f800c57b0a1d4a8cdba7394521a9ebcdbf3e4475dfe013a93f77dde35cdce9db3a1b439aaa6a43655a3bbbbd378f293b2060f763e6804e747be0d254ae3bd0d2577772977e48feeee3fbb199ebbbb1cdddd5daa9eb0518583a37825d778a2f3b1a97ba06471669a6f3c659b562cca2ff3c56d81afb32897ae77d8d37db92df0adb582b0712074dcddb4cc9b9ff77d3ff21d1c3fcfc1913a3866d73d29fd64bdc92995277967e5752c2f051c9a2b47b0a3d9cdda636a04e7f677acefa7bfbb47fff636a2e1519b7ac383d16d81af8d2ff2b9868d694c72d9132346a3bfcea3d120eb7a6057e4bf53dd9c661ad7993ccb49392ff73ecc6dbf6df57db8f6a66559c66559d69e83f3527713c83070c2eca94d1dc8b009f33ee93dbbaebb8b8da3e9eebaf6e2a95a5edc393f599b49d1838e707fd7759fc0bddbbb3ba9bb938ebaaebb8bee39fb04ddb26777775d7be9eebaf6e275475ee7e566872959b6cdf529454aa5531af2043ac8badfa9f3be6e54fefb344f8a6f7f403a8c173bbc302f95b3a5b78976f34b80e4e27a61f71b37a5e84f33907dc771a1dcbe1fbef36af4d2acbb8633495b9061dd099cb01438a5cb1f05faa3267033d4cdbe73d6a1defd810ceba6f78113660299bbf45312b86da7e4364998e4bad56c1c0db752a148d7792acf93b2478fd4ed3f7284c5569706a71429f701a1b7bffb50a69327650f7be53bebca23ed02412952101c708437b6371b410880b7ed49c94ad9e3f3ee9462545d0a44a4ecc1090162110a3b693c297b6cb54c37c393b28726cf5c3e22332079bee77016b58b77e68f3386cb2f8b5a6368d05b650f0accdbffa34314a48eaa4b9227aff3ce94227d39bb6b75cfeb75e3f195cdf3fd3785d52e1b5da6e915db865073125dfe113c7244a5c57e536c74b11d7852f6b069d160d9988c3aa67185e6831454b42f0de6035b16123c309b608d593bbacccc9799f9c60bdb572229e1c46519312f71997164f0917559092c1d5cb9e505646ebd12490924a8bc7ff559c44a120677cef98f93f3621e368ac5623bc0e6f7e470279114e89ccfc21577be146368eea0bd9c544660651651b73997a2dc39c5cc32770a752f9928cabd2343b993af60995f036ce43adf4826c932312b57e6985974e733953bbfeffb8cbecfc7f77d25c872bff7ef6b0cf7bbf2c4fdbeff2b55dcef4526f7fb571253dcef7b72b89f09bedc4f8926f77beffbf9fe4bd7751d0962b723c197db8d20cbed9efb7ebaf7d8b6badbcddddeb70d092a7743c28bbb8db9dbd7ef67fbd6adaf7d3f551341d1d53efb7eb49b9b397d69834bdfbf1f9a5dcfe2440ef0fab82d8f067047c965c71de5973e6a125a92314ea19d3b4e1b9ee809e5361129b8dd5fc7b85d0412b78bb0c1ed17ab94e0f6bfaa6871fb7b7c62b8fd3f8cc072fb818c18e3f613010111b74100c6ed67e1c810312b600c89e02285e005b7918e30e2f673d197eb4af79ba718b06c7da2ebd5b2a676e5338f6c30464398e4082860fe72196988125c26e286cb2f3fb0c5e517e1fb61560d1ec042cc1435a8220218bae0418c90098c30223a02c62ca408fb139793b8fc253033f38eef877dbca18205a63bcaa30e585181076af0c00e1e90c19428a840a18203a40f5871fd5fdf8f2b91852684550f295fa4f870f9757c3fcc8ae910e2072f427c71fd75ac4e19637c70fd73be1faf3a7a88122547d5e1c34d1023a85166b8fe38ac545222c1087e90d20412103b3884a0870e5441c31208607e7485737d3fee2284c05cf4e57210335c7e59b481cb2f7e3ffc310042053baeff8defc7ab95609094a86c7c3f6d4978e2f2572080e0800a2e3f08566a89423577703c00775c0d800341fcb0c5e5ff8045e444943ac3efa727bf3cc1e507bf1fae642041e172fdbdfe40c3f57fab63c4fc2760aefb5728315c7f0fbe1fb757eeb8f2e104599e2cb9fe1d7c3fee04c7871aae7f0d110a0a78ee782380d1c791e422bf3821e33a0f517828430402221b5cff574f0f22b8fe3e3f806ebe1fd7f164cc696243074d86b8feac7702c3f5179d1471fd5bdf8fbf7492b8d1a188ebee3a94b9feac1d94aebfcdf7e3af449214600cd1a0c5031dd0220a143cb1c20a182c60d2b5784d193b61f3c7d50d931aece440c4e567e9f0c2e5a791450b4ef660cdd5cd8c25645c7e16132bb8f8612d45354b7af8e10ebc602bb1584c871af79beb38d771ee98739dc7751f2f47c94586f94292a1e38e53689c36cc1d86b25c7ff7af1a00e2fa5b96064670fd3f86eb2f9ee07a0d33b8fe3d1b90e2fafbd830e5faffb80186eb0f44e4862cd7bf880fd79194d4e0fab3706409120e5ecc25abefc7894868020429d9433579482e434a68c872f953ac0e5e304318a8efc75960cc70e5bafd7e9cd5c494c105a7efc7e519289e7c7fc7558fcbfc1649861b2effc752228c947704c5e5ef9ae8c209bd70f937678289adb2daa41892b8fc9a0e0b78dc276ef51864b8fe19cbfb47f30ca1440a3eb1796cdb50b2a3f5c13b634f0f8fc3a6cb1c775c857199915e40bafc16061f2ebfb3a02083a6959062415c7eaed3d62e5140b9fe25f08ee9faff10e2465877b9236fdfb87c668ccbd3e74a4ba749a55e1522099120517d8aa268683e152241927ad54bd8fc7e5af487a45ef543562d1a06517dea87a8c2d4109af0434b432c8b1035c1748b489dfe1c494ed89e2d567e045428c2a2fc4903a43ad245ba53a954f86a57d38040768ced5f1af3f25fb4ac1c6258f9fdf3053248466430992d2fb8c2db92c5109213423bc8ec7994b5d62c913128ca10737bfa0cd704451939e8a1b9a466f45b223571e6d2dc3601a5f44fe04bfb0332c2e5f17bc81ea7cf9e650ffb59f62e7ba0defb917eafddec339405f964fabc0e943d585287fe58df5f05d61468427d8d82b366405ed61b43a5408e567e67b9b048507648f6e8715958923d2a922a4250ff3d12fbde8fd628887def8758d61054d8d3ae7e95fd940dabf073924d50d8153ecb0292e7dbc5924533d955f5deb466c69c41c392ffdfe363998d7c686a56aa148ac6e4237b48ca3a37e8a4949de4b6c249333040cc3c58eb69177777e59fd41f03544aa72f0f7dd832386f7367833a35d93567edee927e0d1e9c7653a636aaa093f6d8a8424a71c3a2856ecf2538d26efa9995524a5aa93b0f072f15e55833c7fe91bebb3b0547a6e018d2e6dadd7fccdcddbda98d2f35936d7778dbddfbc86855ab5acda877a95a46dd8956b59a51ef52b58cba9339994061fa7eea9b4e9956bf6a1975275acfd6967e82611d7179de194aa9e3aeb513ad6a35a3dea56a197527d433ad52cfba38a59e39a91a75275ad56a972e5573a255ad66d4bb542da3eee407e776aa711cd76d454444d5f3beaa64650ec5666c93728e9963a41792877be6c2698506973d0dd8a0232c265993c974ca64b76d9bd2e9fba97ffa4ea03deaf4e64efda5c9036636d8baf366b352ceadb52857b2a2c252112b6dbf1ffa564b35100fae3eeee492c38a959c974b9230b9cc10587b2b49403f68a6c445e939cd4a120b5d1a8e938ca4542aa5e29ee6f95e1a3dd8f3527d3ffeaaef04bebdf22a77ea8e7ff72fa95df956f24ca5764912a695190227bdd839c9b0c85fc1f9058b2c06bb7892305f2043e067a1cbaf4d32bc903afc745a3181de0ee718a9c35fa3899ddfaddc7d49651a5f9ceb408f5dfe2c1e40d775610b28ebdc97644bddfb30e7daf7f80065148ce77723b6eab1ab9fc503e0be37e9dacb7e159ad6dadddd739bb32d775dd823823e20485f3063937d49ad561a59a2269adc79a79726d5cb52a714823a05136e2a2571bb77de9160b678f1a24ad7e2e507119cc7794700977ec5e2044188701d0c0a3e903ea46082cb0e5cbeb8fd6296dbffeac2451432b86cbbb9e5c01ae97ce1125effda82105cbffe5afd401443d7fdb31a050a263aa068e2bad529ea582c1623824deecb9933b4cb2738f9d5f03ba54c2426162d5fb21c5d71fd7b7c7e3cd1c5f52327d75f05168aae1f55b9be8588eb4f6471fd092daeff242ada924405ca7589847483eb48494e5c7f5f028cb559b4e470f979069fb571f9e5175e0d3c42333c2cfba187d5973f250917a877fe055877be277970d8e5edf2f7704af65dabc09439b6b4245beaee1ea08ccae045a19048f8b96f900b91f4532295d36255897b1fce946259c6695cdb7a21543f7ba1edb5e74020229a935162a662143173ff3c00db75f63770fb8e3d065bfc9b3ff743fab7900b915411b27d3f12eefdc5281386397fbe207bd0dfde04470c51430e377b397db899d8aeec297843ea64bf655bd8023a795e0d2c7628e3c21650c771df620e6c71d80ac271db7b5bb83d12d9262e2cf7db7ff4bb49279ba6989ebf2113660a8392c0503fbd5ab4bd0f7733164bb2b548cc4ca6b0670381daa5820f917665cf812cb42bfb0f3c755b5816ca5eb4e166bc85ad20dbfbb7ea77ddf777614b7b5316b66a28647bff2df47efb21dd9b4224dc77bf71614bfb8f7bd30fd9fe0b917cbfbd29445245c8f7db233179d96bd99bb2f7b64cc26033e6d3c3222d6ae6b89881f59f53548dba70a5d1735cd7be827fd6ce711ce75f5fca706c8176fe59f69d7716a47b9f962dfaf5d2e6160de5ada0b4ef58486bfddd699ce5dfa1502105fb6660cb04d467cf2dfbfd345f03b682f4d37ccb8643fa695a43bee6190552609e51c0ea6784b25d353493257564eaa53da1b2a22ef31fbd28b6459fafbcf597740f4a58c7203b6cbbeef5b910097ffd8dbf3e927ead6a1ab76ddacf2f08c3b4df381f967569c992f802e2ba06c9d8512e1589802fcd0f4848687bed85b8afdf01759f8112463950857695019f5856689760fd3503e3651115b4fa30eee64f07aa7f648b2d2df976b1dae5ffea1f600f10cbc6c08e722902459662931d07ed3baf830d58be41b2ef1f42bf3258dba5699aa64932b34ac78024307f322e51f630ddf92632b2474fdd6103107a4edcf9d60576e37e7e4fff7822cdd3fd64895d583497c2881a8f593a89413a2d49296552f3582b75e6fb708e242b5b40dcb7866c6f93e38495608bdd62f34831645e3e7e0839c93077ced92c4f49bc337a272ebce35bee7c66e6ef7db8c57675f6f4e50724545f134a12f397df0224ccdf874f5c64d3e912e6609298d8ae79523a25b188238b953f9e926ef3264627715a40f4bb36083eb19379bed0491cfe1fdccb17c2bdfc7e19065569b971616b4b02ab1c3333739725c0dc0e8d96b88c76c7eaa36acfb8328f259848c1cdc0d8d695484c60f9818928da0b2cea4a242698183121745950c61dd384abb67a7603643a8ccdb4d0c26e57645ea6a85d6c2645455a620925d4e707332192626d84e062603f275a1138743dd87a25d21234d025ac7625d212b1323e25fc4041496933aab6b28c5e5ac6a9eaaa7ab655edaa7a2c82b10116189b33592c99418017a8d03841cd1117963db304139a1c2ce560cc0c7ba6ca92d50c546ace48d180ca4c12cd192729180eaeacce281942c55466ca38b1305c4999d9a2c909658512d3186b464b0e9f9593990ff8e01140a88cc90c0f39743080f9aa990dd8c0c5883c33376c630c7533a83158e1b458a2955161656cac29986449558b127a26a695c0063f53940dd1b031c0d0fafae1866a1966664c6d32345f3d4c0019886add5ecc5bca18baccfcbf85b512208658bbe4ad72a2f83d49d3b88c7abf5e3c7a7cd02b91b01455237106a7da017db92c76f5aeb8d9a609fbdad7d108ceed095f3c546053543427d6e6ca2d2e50d229d9eeca2d2e88216b815591d9c2b0fe8536c6725a6844d82c4c56c69a4e5045606992a858ecaa035c0aba201aa20b1a6a18f61b838362bf187431581a30f48a651955315655656bc29a8018c36e4e382a2c65c2010d6444b65eb9858b17b2261645a69ab1d9955bc4c0e08eb54eb1dc955bc42cd5c0bad1095888da256fb68138ecf22a8bfd4a2425a2a8f588eeeeb6ddf3c4d2344a29a56cb1db3f1c7777af9b764f2fdc66adac4de332f76e94524ae9757777378bed99f8d4deddedee3edddd7ab359af7df61e7606fa777b4b546b06ddb4777a384114ea4eee93bb89d24cdc50345ce5c54e9a699ecc64cdc2b187ba56bd4df670dc44b9ee8e005cf9a0e479fdcbe6bada799ad376dade97d1d7c96fbce912063b9f693b6db72846491edb2efe2ab2ad5fc354d2354a32659af9c77e0fbb93d47982f2b365263529dd59d75d3eab524a69d5a4952ef9eebe4329a5549b9488c9ed34d3eac675de673a59544ae5ad56df0f952fe5cbb72bad48045430c2420b4782666cf592e665cdcb192f5b2f7fca1a2f3b78e9c1cb7f09be94345efebce27af9d3887770bcfc79c43b395ee6bcfcc98577745eea7819c2cb1b2f5f2fff070a40bcc37a2982f022bcfcf12f8f117600f0025f8ae2df006fbe480820eb26023ac0154b051dd01ac9013d167280b5051ce20df1884bbc21de00e1e7db001d049c507e007a2cb24d589fe021451b9b1fe04b8a3c5008c19c1710088a394276409674d93c00409188fd7025451b1b15aed3f020b452b431d201e8b15003ac346c5ab8b17949c3e6480b9452b4a1e1d786463806b154df4f871d68612320453ae652a21ab0484a0c141a300529d2477d407c09242245fa368c141ee00fe9a23f02a804c4c1501101ec912efa3b40295da60fc81515c8e3fb80d89e97c703051498d3bd802c287239426ee36c221113f8db07de48917eedd76e22d081ab8ca5c2eda72b231be879d7f65ab8f548364360540d3a89c352ae2c9a4bccb55acb62fd8be2f8eab9de4fa32ea9fb71163517a954ac95715eb9754ce5984b67e92c9d594a98db3f4d2f640a4724647ce138c540b9ed85e39412660ab940861403451e5d8a85a670fba74869775814e55457ab9bc93c5ebb34a09b855c476bed6ac655b0ebe96171fadce64f12b2f0d27f51b067084b7f7c9dc0a3e7fb09a79c5e2a40c24c216b489f39033b852cf0a062bff7fef4f6ab0841bde94d6150955610d39f5e88897e902914627a1b0699425468fad1c224ecf4bd698857fbcc99ebd33c1e8eacad9f33bd7da1d3a366e5efa77e57ebbc403ac08186a3eb1f7680030d5aae7fd76559969d42efebf749603e5d5f1e9804f681a6ff5e88e9bfe7fe3bbd1706a1b8201bca369daa17b6b820d9402d2e6c05f9de7b21df7b4155b85088f7a630c8fba0fadf2781f9b4b3c830fe1e58069b5f029ce34e4bd5dceb806e7d0e1cedf47e03dfc8eb6a5e28790c694fdf5f5cf6465e7433fab81f7b7e645da0cbfdfceafdf438fa9502413ebc69f75ec10fb82eccf00bdb67ce7018cea11adef963367ff407dc2d09163193df7f76ccb3636fa670b3a0065be05bc1cc636099e538dbcf378233bdbbd514ee96e4ca9dbf65147097610a09b295862d054858125812d88d2eac2082491885d1506cd774ef691e6a3467232d95b9537e716766c5873bcaa322a416b460e82e8d6928ba73c6b0a378272cd64f3a493f4884620323180d5bf3fb0b1332b02009c60e3a2c81b9e03581d1974137586034acc22fdf853907f064cb174b482859db65c9498d2155710377c5aeae445a82618c2cc86459ace94aa42cb488624f572265510516b6bb12298b249f127ea0a0a4c5ea062759c690f9410b983143445accb0c50a25455330d942e5e868a904373c61f4aa82081b8eae54f164c9134b55dca0e4a80c156670d052860a316a4032a202063520c5a858aa618b11156086908aa8501aca52440513391c11bd78f4f8e820879a99d1a2868e072d62340596b3c10602ab819115613f2d341258d4149b17cb21716424518fac76845683942b2dd041062d9081e660cb5219472c85a165494c16463e25fc40414c9628ba6e73ffc9ddcdccccccddddccccccccedee1a8b99997a6566e6aedcddcccccc939999697898dcbeb1d3ac669ca639ed6ed6d3eefecc471aedc8bad18d73ae6bcb7a1f16bde33ceea6ded43dee9bddd49bfac799a4b78f121813d771261fa93367f040439d27cd28cf4ccb786a4126cc65d89342960199338745f97ebb93d3c780d39f6e659f4623f2a8c5435247febc347726b1d095610557f6c4d39a4c3ca589d2300803300f2bd2c924650d1e3e666f25a5ec971d2661bbbba39452ca9ae3b4f28c56932ea5a4610e09ec7c6943897677f728c3f4f0d497527677b79653b38d76dba842c9f6b7c44e1b4a9ec7392598ddf2546b18840198890658a4bf117974250db3eed6b8865b53ca227712dd5833bb698fe1a555865addb8ce0b47161198dbe194ec7d9866ba3f75cfc111bcfe5dd6e32948db5d7bedeedf3481a77ea734a7736ae38beda72c164fdf8f6ceb757f2c4a9d18ecfc946ab5a2a9a95247fec93426b92d212798f6dc1de79da28541188065a16da2890f4d7c68d24427d624a9939a2479497a2f491f48aab09a2727e79d6e725a1d31b96b9c8baedf2ea3f1eab6a2dbb671aaac79523079d35df95bf3f0c15772329d1eb249a43da99d8722f2bcef277bef4b8177bc04e6a95cbe68efe4f28f245cf93ed827009284b9438fa615d1b69048ce998cf98f34cf94b2c32461f62043e047a24c114fa40eff0ef563818c85c921f30c6c0be591db4280d4dba6e631c1240a2cf26fdf0f1639c97e2f51144b60d1c78355def11a588782c9e736c661f19b8783c9ef541bacc81281b1343a506cfff7d3451d4d11d15f71124d22a953c349f3d4c04e262975a66a0b5b9d65afb8e2a900071f617c10238c0c4c58dca0ca42878f938c3cb8a38745d1fd2a1662ac7aeee8ddae638115b723c38621428c7b575b5ded8aab7d15e36a2be8a282272c2f8474082306cbac14571c9960053e58005c11039d8115568c613b1f5eb437189af209199c7851831b50312207499a1c49a1c2490e464aacc0d899c59c74d9893397e5182358cd233a4b7418e3e8beb9fdde5fc1e070fb2d0b4c1229c072fb8558bd508074190535b8fcac67518b67c5133056d0e028e775c7d5172192be78516d66830ae5ca268223b62f4370526c26a56b42c5136d888a26433728a142063a86ddc8e898d8cc063dd88c8c0ed9076c1d534760b5166c536ccacb46c3139c98253224cb5d893485084c4004f7812984a85fa68092651bf5669f127ea030e38adfc27bf584a1641bd37161432db2c2a10007ed4abba4141b285a42820702087165ca0d0490429443ac091874086228064da2944162220b25415c79f1e8f131e38a4f755175426c9183a22d68c085b1f6ca2d5b6c41a5b0a72bb76cf1a504d6bb72cb1649516c3182ed882da66c506ccd955bb660a23db1ab2bb7685146ed99e2c9e519573c15d32511094955d7ad54cc9c4231db6e53777f5ec731f3c662e6aa3187dd3fda25954277cf989929337b873deececccccccc5c2b8bc5ccccccbc52a56870e0a09bdcab76aaa2592ad3509aadb47d361a9bb4d17026a73e4a5782e1baaff33ceaed7ddd67e2a8b7e9b49d6cb5280d95ca7e7c8f51843be2b89ccd951ff20e2c76569b5251d5caa9f78aa669a4924cea09a1bca8344c19ca8a54324422000000001316002020100e8844429128c9635dcdde1400116c94386c56301b4ab328495114838c31c60002002106100380310c1551078a10948e0f99444829cd742afad15fe80b2aa10f01ce4454299dbbdbe806469d6f0b0a81752d89c8dfde2dec4c564189e3c72a048dc0a5a89e4982b0608677d9a18178cd136965fafd769a82efbc0f6077e7a5d1420b656b596d5c84a7e490da23569e0a44e87ef47bce6fe1ebe3e8f44399a4cc9c165ef184acafeeeb1593af250d6a9191f580f4b2fd4ff72d8777b091e0cd1bc4f8656884512c3e2e587419b1e6fc2ed81b2a4feec1d83b490f7aa19bacd9d92c871b7727f53c1e9da3a300f7247574b4c5e21ee2bc6c4d13dd64bd914dac7b890e8c1e990a06b72ee42809780b820296f81c4d41b24a1767b58512c11fb1414322829a3c7caecd1ba07fda2acf6ad964c081ee7449b1f6797cdf9dc62adc73c3a17648ce2d47f238c28964ca0c0dca484999a911bab8135ed93de83d640edd51ec21f2fd81eab0116d5e7394500323daa4fabfefd11bf521a50c87ea3ef28343c12e58e026e7b1c9b5d314203aeb30ab47fd238c5f9efdd73e124f2db56a6bc11a96aa755b2a47245daa9828a19f59d3d6b1a18aa9dbb56608fdce5d4fdaea8eb71b0085f43c5f6931473f8d4b16498a43158be508cbb38161cbe7ad58f0f2403f9dd32c100e9e554d4f55da2ae052785e1b940d95f4b8a8db75e7c3721ad39fbffc6a986c07ac8790f726e817535221e7a19c6722b047fc91ea7328b11e32b936234e0f728e4be1634edc4aff75bb93df6ca4801a7e59db88624ff0053460e7ac53eeb7a239e04946d92f17f02787fee04d596ec642bff49193d8b3ecca8e2b586d3f61fef712db3cd5bc6fbc521f7c9d15843fe5a585faee97ac9e5c02d6a55317e2954706e1c7b5b6413de499cc8ca665786e5e48212f315fc824e5e0bd1ca9e7f1cc6caf84473873c7610b4b8d9cec45198ed011e05f5a13392ef3615b699de33ba7dffdbf8e236705b67022ad77be12ac27c608d21e80d09e41bba957d4bb39965038c202495a7124d42ce8bac451a74258a0327b13c9462470bd0bf75f7863260f396350a03d3e800993cc33f8952803df9660d87aabce274a6ac3034da1e05ddd366ab0fdb7111aee013df75ca43777f764678653ea342934f979339615d7bb5b3c4946627aaffbb5e64ea75abbf6f47460474d52fbe3f45af3cda78f4d9e8be85e3a0b299057c6334bd3d83b9cf1b4e09cedaf92feb60db795292cebe293850ad2e3a39328ca1ce1105905c6ddbd7815b3e27a08404befa98f95175499fbdefcaff7a70b26dce835fe55d6bb2352b3f55ff77e2d609462708b56451953afad8e60cbe205368acce28ad13153f2a6a05fff21b969433cfcc3e6202f4625ccdf9b57f275bf38d1ca425eabfb92ce228a87e709197d259d73fe80c4c0f7ca78c486e50c14f9fc1bd8a1ae2e6afbfd8009f2f6e16611f5d8a1998d4de4c7b9933d780575a64e36b51c712896e3da5793038cb96a82c43fef70a1e6d60363d282881bc157f789fbe76903b987dec8773dfcf2f7dfae12f0b6998f1688e20d786f34540d203c9e5e707d05a1f6bd5c40943970e6b10c75ac0476ed23a219a2dbcfa876f1411e505f706571a83751cd5bf2f9d9de4534fdda40cd30533aab1466034073fabe645c296d07c28bffcb10fff1acac391ec0f01e92ebd2f4e350f0d3ff88e504186ae00e19d66a0ae70772cb05cd543e01813a48262a2c10e8d577e718934e25c520b99237c2569d38d626e75e183e57bf0b0e102ae25b8430b6ba0ea7a43fbae827c37257fb5199644b3dcce83b4bd8102ea3b51282ff23152fdd53606a19d1e946ecafca4f608d0fda44d09828b9914badf764ba6786056201c52f2f2ca30317dd0262e09c646d934120e9418b51d07fc0182bb0949c55f40f45b46e2cfe0e5ab7fa355335ad340291d8dd5e35ea4324e421639e1ccc8d808a1c7fe78a77ed954e09b00df0d544bd6fad9171f08b2690ccf482e667e043ea87e97605b41d4246ae987960881bbc9ec38d4ba23d91241b0e1f24c2250fbca0096db6f5455b9161e0e9182dfc9609fb22f10758ea832761054d3174481087e94308d93397798a870c4cbbce58af2d75329398ae2e5968d4c46c1e9288800846ace2f1db199857803730a92b07b607996c4f7300e518b5ea70c3e4f9584af549ba431050fdf1365510814695d2e011748d28e8d785c4393b5c1424568c8200e474202963f395fb2c97d0b425079ad8ea5260e8ff515a468e1630242dd272fdc8f33ea0db2e2ece0632c063e1d16d46b86028d95f0895573483a81a5dd245294049d61d160952e7f120cbdea7d2ef32023b47a15b5297d5ed22eab258379e23748720ab1f4925d7ba7f3bba4b0ba8a535bcbf7b4e45701656491edf92af0df23216bb7b11ba27ca792d7467d8a48545b997677c017076a899a72fe32846a4c57fe463bc34da69423c8734bc9709d21cd6752d61306185ba24ad625a64f91edeae2605b4d31ffdab7dfbb7578c0d2028ee8f4ac3acf7e69d2e4427b612287bda1d25724b5c7d7b6f31573d17500ec3cbc89b3ca0732752bb1b50c96386a1c1b5c92a72e90a802733d19cb700b0ce9c55157adb29d0614eebfd9d100eb048a506553a05823a24c996d5e26f920431f49f4ecc4623f933d673d63b06ca7fd7f2f40bde05e0a13d13261fa0a5cef00b30281f37c6ffde2b7423b71f8e0a35fa6b7d191f7da2a1eb10b7d5949b6d8cd575e08890759cd7d3fd921ae5ee618373078f521e13ef9b3a4e18a4ebd04d0baf3bd25463227969476fcd3b1f569ebb9d6ef28b67721406eea3b9ead0083f7413ce3aac2abb5e1c4307ac7037aeddb1169c90f9406dc79acb17e9ad26da99f7009ec8bf0e39bb0ccf36d9ce7c0e0126d2037a7301d0d01fac6db10a3ab5e41bd89b4c282a199bc69dbb8c777707c85d7c152a68358ea103c83ce639189c10f63f103431fe3a1c9a68fe3b189c78f63b349c10ee3f109818f73e1c9a68fb1d4ccdf7f575384558b2e7cb72f2f57536e996b7dcd0f8701cc753290bf3c568e1d7d55a1505093f96423fbb2adbf7b784ab8227b1fbd5bb43794e894065bf48cf5568ad7e6d68ef7891e370412bb652deee5ab5b8fe082c3b8a5ca11576ddcce4a76cdca75896702ac5399a28ff760fa3bad7d4ef82bf40b943e042885d20d4dbd19e1d759c9c4ea42ba059756b9e2b23889e822b1d28d957d294fd5737ee6a93c149d90465de92c951ae8b214d12b8718b4caaf886b5aec2cf468f93becda1c32bbd10f25df36f2f96eaf68fd95c8185060df0061979d95be170f71e68ae5bc50b036d1455087ec2817c1d8a856e788ce06ce07d034ed2343185c7074265aac0b48212dbfa067b71f3892ce6c21230b734786a64dac93f4e6cf382078dc5efce7ca59eb12346b502b0b5b20334991b6f7a4def7ec1ec4e29a027e50dda8a99c70217d16d6442f1d7486fa003e9c48331a962c76bb8f50f5210a5907ecbfe72d6e8d9a0e1a80f0e30ea3590a23f8197197a3a60142cb88e3cec3c4bb60966f4e7ca5ef75d8f820e7c9b663cc3f35780e790ce50af06a16d210b2beded0c4a042b226488cc1410268ea804d0196282e3464beda208a42d3036630b5f960a952989c360ee8b76cb82b48af1507822873f50738e28ec301e6cca3f0b43606ff7b621ba4debef83158354b77bd767c99848cf079f835f9faa12409f56c0e7f8c1d29feb0de0cfaeb90a8c6b42814fa21b1536833d2e3f1484d4af80af703c09922e427dcf10c6472ef74e7aef7c17a349539b91bf86163fc5104a6f684d5038ff880a6ac3dacd398a8080dbc4d3191a31e5df57252bd4c69581a11e6a72dde3fd9557995be88f9c996801d6dd2a6d068eeb23757c46cf91f42dc62203bf8bd782a30bdad5e7f93a50b7d7b8b7df66887dcd02f81e8f3debffba76ab67f5e78f181bdf24e7c41df662a48c839e7be7c348754806ba4db59e0b122be1a8a5f74d0e4263c1f765d6af84f96d0df4002ba43a84210b973c612c2846460702f895d091b314e35de0240ebec12ca2ab2a8d212112c755e48ab1812af50ff9c9ca6649d229b30cf68249b694bea19483d048b82bb7ac310206c826aaeb09fac194801690b33a10bac8e56c298aa9a36c67f4bc022c2caac4e88f818ac663585bbe46dbd120b7c01f57241bd946aaa53298600fba73264c3682ebab9985fcfb566d3a6bdb260e230ccf7f656b770bc07cfb7f742abf8a86cd768b6c95f4618474f923524038fc7d6890b2f43dfba0a656cdcbfca0f9f05e5d711d8158423f118084e4a56ff47c19f10438e2972aa2b70dd479f336b33d6c8525da9ff283a8481f40020116647d1908bb4d067a0c5f404f9034e73c4dcc54bbaaba4020b4c147752ba45b4bcf206dabb5fa450aa0efd30fc359c0e1640d8de18d22b5e1d2c9d147b09a212e21ba40b5055a495725619b77bce0e6b434ea9c6406c19eb868c1cec9ca318ebd5167bdc174d7c304751a40dac30bd960890e88022b021d9d2b06c92b1005adf00f6b3b2f226e8478afc23780dc58e754c62b5c613ff6311f30cda76a7a90dece5b0ee25e5195b6fed37e3154fbe48efc228dd23a0003ceb542f6f904c782b0a0bc0882138733207af1da8313ba6ea84c95ddb555afd55b05fd5f9aa3cd50df4eff586f8b3bff3acad164c119280bcd5545aa43c4cf7ed2b3e586f14a6647c07d4357a5b3c278ef53782359e3864ec7a344b022930a6c9ed9b64e11ab33d53e02b18af8cd5c4740a27c52e0cd5bdd0eaa28e8f1bf1fc251afaa289f5ec9755b8469201ec9be6104e656f15910e241501e26fc3b2256ba046bc758b518111f0430bd785054104cdc042ade4d4be2e9ae5548846f2f8108075c720cf655d2bb9ac39122f6fb154295ccd71c134d2c400cda5880b1001bfbe3462ab79a45b915f41559e06454926d86379e00da4e58b66e322a69a000c5cf21bd8bbe5578d916e97dfb95576100bf05fa4cdb842326e84ef6d06c56918973e8e677ce56f642406350db6d8ec23170004aad47c9b851af59b13d6d814f0685a957404f210e052cd0d47d1df90a8806bc7a513de0cd773244b767e0887022ed970250dd39dd9dc999db24f790c356771f693a25d0dfac859ed5f3f3760bf3b6d8fad470fa00589b3df48dd151596c33dd85d69c8e97327805612885234da228cd261fc5b1c24597c23db23bc22c70932b52290da20240777d99db7a6cee49791c8434e0e8001d6b30afa191a889982e7a4822ae33ecabbbb7200625cbb95076cd8334bf68417a06a22fb4a58d89da8a7d5c3315ba1e522ff3da3282bb9e3759e8c8ed3191574950d2bf07db12d270783671ed7456bc0f1c06ff6fafb612e191140d7082a8f9089762f682bf450844522f86bad2fdd51b0c17a8a4211554a5e43ac5b3132678ea11c146cf367265e8beb3e2d083a3b1a48b4e04189839ce5b64f1bd9c88ee443a8b3589731396595095f2c452e997462d0b9a466d37c691ad10d76a670108b7d1c07327bef5c622823bbc1d1b73c1ba1bad6b572ec17c855344d22ad3a85a460e22b2b6deb21575f78104cca8803e56c902e5ebdd468ac78d98bc9a9ce81afec0fdd29cea0602ba929b51a71ab0eea0c64b581598a79869b71fe68ec52d755648abb41150429555e1d629a721956b92dc039babe5adbf4a017790187c33866c23993697206a0fa379dc74aec75527c064df90a1a47538edb7b7b30cd71a0f4d56a70031c3c4b18960c437caf37bc215eb4e29d50cc25f94cea819ece3029455e976b025e3a2a232bc0b1992cfa55da0c199bc0158244812f0a056ece5c68897e9d3f8c4ba9bb189d8b75253c391ad743394bd7b72cfbb192a7425e55084e8f1548b423763790320b2d5d97c9e6c49fb9ad6cc08838218e92f212a3551a6c6f82bce6e06c85c9f67419bceb4c9fb0a7d45c9a844d214dd0ced6aa46d79e666ec3e59fa9e101a76b130e6b7601a9012ff328569b4eb507257778afb8be71e047fe84e5b7b30f8d0ed339136721559e3d39e9fc3eea13b5d3885b1b32fdac5c34a4ef82e85dd781567ebe1d4881c42f0bdba0f689edae266a27ed4502ab45052d66228e949a88dd9a7be4f1a8fd37e214069fc3ee9cdcdec3270b09950b83b6322ca902fee9026adbbb438b06231b18706f15fdf381d62fa99adb7d343fc5d05d1e54e8f72dce4dd69dac34bbbba08357973cf8f7174f6ae115cc0f19aa71980f3f37f7a853710b734a604a5b95c46b5b566e23715e8cee4fa2a79aa885fe37cc49e10be1377b11ff14b262caa3f0cd4a00158e8f8dcc4075aa938b504adec8b1edd40c83dd235b3e25dbec0719b1e43de99cde45070f25df227b884c9556516229879b3186716825774f9aba286e512d85c9d71f436fa34c5613c1e234af4dd8981d2946fadb9691ac8d0f7230f84053f6f5c01ab428e53b0c4609ea5cae1f4db9d7f7bf8f2084de31cf0cfcb816c0c88c2a4a4dd7dfee110c6f0f2e9878ede6a72c026f59ea33ab3e097eebede272d12b7e0cdd0ee6e0e406ff75322a66ac028846b0442f4839ba0da68e8dc52d2057d38f254f5d6ff607645db5a2cdd8e65cb886c406ceb5b1b9074d08ab9516d8b355f69ba03b56d2b7e2516df626c6b9cf29dc5cdf800d728434ddb0a160898367e69ac004c9cfa3bb0e80b4e3226d149a94485c7e024217c29c7f1fd66342055388959721286adf5a5eabaf8a9a10d2dc938e9f6d929d54acd491d9b4b7f44a2fba04593ea07bc4dd073177601dac8da4b3a123a3f099c2ab150f8984c7fd3e14def293ec9f745079900cf201943515248612fad0f4e5d17e0c554ba23630ae261220eba6999fe8fdda4e1bfbfcceb86bfa4f700328a009ba51a0156663865627ca887490839fe833c0ecc2b6b2443100cd17efb7ffbefe6ef6e4a0db8af96a3e1988abff5fde69febbfe9a5e7f0194e2631ec8fbbcca5cac85b89ca974c0400c549f8649ce4ee1e18bf41421227f93058aa140ddcefe69d1aa58125877762a0ffbe3df8b10d63906d57312c9bc5049954007e056256769e8cd1df27a50ce44669d007a0fb3adb9ec7d24aace0ae73cd09af13076f8eb10206e79b4d5e8adc01d02019152151a8e775871992b5937175a6b3597a9e9ec38d8aa943f36fdc16149489bcfa8fc1695ad19b7430a0d91b36d0640f0081026f3cfeccd7c7be2858391c1b1aecccff80aedf080aa891c55dae8c409a37dc6ee84031d8b7b83e5eab37fa91b090566cdcf64dc9a637a99404ff2fddd260ad45c3ce1abb654dd872220f83aa2e0d9d5ae796d96ccba53c0dd237860dea9b001864a0944928260b2868703ecd7c3a19fe31bdaf32b2f979b4610a27c220b071c2b1a4a294b3315b851834e1b026e33a49d08bc06fd3a40175135687b08ff5315d7aa573283147f5d306b5c602a81db46fe4b13a8cdb1c8038b740b5554b0c6900bba9e0b73c0e794372e2399e244f7a939685310294f657a2e0bfdec032c13256ec147d644bc1d6d54da178955a5fd13eb3a1db179882765a5ccaa2bed860cc48e69c58e430fb1c38f7f1a56124be60f403c26d64d7b6c60ddf76b65cdf2c58021c1a9727f0243eeb2a5b3788c9bb4c1929214a6bc7055d087577602aa8d4ce05ddc78a0a64cfb372516a1f73dbefaa0889387b02320149729ee3936e13de4e5c54c76d3c571f61a402085537774213450796e4f5335dead38038cfe4227b2ba14b674444077a4027cc7b397d684c0843dff20c96aa268ba34a30749c8ea0c6326cdab3ef5f4ff5a2ef5be4124467ed7fe27dc9d6813ea0637f1f2ab81558554b70aa0fc974a7a60d7656e673894b551bf6964f1ff14beeb87f6a631af9cc84b90c59be1030b4d0fd7a859056ca2bfd818a24b773ed728a36245e997abd42dc0067440680b38e7d88376fbec5b389803f0e85f8ffadc7d19e51604ccac90a3046f4fb36e97ca61a27071d3c2a11591f1a1d20c7ae4f766f8b4f09827adfafdaee869291ddf769db1cc67e518c0f72fab3f0c6822d4436720a10cddb93299fe7948e905216aa08925f31f882ab759c3a9f84b64f07e5fd721d139f86bdf442e02f504e9bc5e2fec1a2aeae14931f1bcf5ccc86db4aff9057c7ebc990310fbcb45b51a94fbc3a6451471f405c214f1316b03d4ee372115704e473ac3a7b74b95e909388ccc2e0938bd32dd1be506e1c9e9fae391755a1632dd8d6ec31827ed10a8379b1257b4600d2d28602bfab3a66d0220ddbd60ff953f1d562641ae5146110b8d8722e442967513bca4ef8f7217910cbc333408f8769a8b79caa87111fd62ce34d2cec9842f4ca6a1eb41c80347344237d555aca73d6775d3dd7fb1b508c404d528f8e335ea6675580c4062451a6435eaab6ab66829e5e9882f76d2e503d02c0745a6dca87bfe203bf291b2efb93ba5eaca7054b56e2196ed91b5985e6b4a19a26d3393338e13915ee6b3b5b2df21d58291fa504aa1554b370dec6d9d2d2de931539852890f4764bc3264569afa9d8676a9c94d7b370e537a3e699807868c50f52c87245e5e4621125714989de6d97f702b342bfbb0c9eb2559d45f5fff04470a81780bd93cb6e5b609c1de50cbd04c3b51eadf8094d357b8b3ee16d4cbe53e19eb6b354a3df8395f251246023627a0e28f36467ec4b3d28cca2b90a1ba064d29c25b32d39edc28cdc7093831ad1654c8e55a1bee6b3725b07f4ae1dd74d484d4311d3f048dc6caa36df9c10a3c6344c9bac7f0e761b2fce90e18a2c04543810fc964936cb96384201dd82688e137a519df9fdaaa413cda4af51ec3f0c182df3881f424e20b2f6906f2e17e549290d464841e0097244e9ec3518b61504f96516c006b31ba3a79ee10aed9a4c18a940863ca3edc3843f778855077daa7dfab9b8d33b81eec41857265f996c07b43b5fc8357e660c55a04083a7aab9f94b98c674918a8ad4b41592f51ccbf0740add052e8ea66ed2b426c230b16c0365c8010bb1ade97edeb6bdcbfb6a58232d69865ee021db1d51804849606fbc58309e7c5aa6d04e19f3cb50085e92f954000623a5227a84bc2d9631fb2c44eefcdc4ea189b92b75350b3544f3c65be691a0738443b81ed17fe40af5ef69609731a4f3f3ed2627e9c10a4eb908b31973dcd5fc01615d37d7a9f610939c32b02ae044e9dc53404db23cbd13371fca616ef9d9f49bb3027cf4427626ad6ca6de586b69902361fc62a2c54727031e5be76b82d9ae86f905c7498a7b8eadd9ad30fbc2413c4c10cc62f79e967d2d246ca9e8cb6b1e1d9c596594e169abe884d1139d5f833c291e23252a804e59268cda3aa4dd998d1e57f1e031080d2473cc8c2cf50ccc917e574396c7f402849043d0dc1a9d4c3ca4d3209d1f33e2254408164c91f189516b71be5edc3cc64d39e39d35c5d989e9c17d8af7c7f9b406a9446cf4c349294e251a4ce55b166b283fa8784a91109dd24ad88beb40ff21312c653d8e2b114ca2d3f58e7b1e056c7fed90f64b5c35d5b935bbf37b4e9dfcc5f00c316631b36d93262a2342783007ebe6063e7d4e0c4c59782b5c1457266d04c35bf695ea675b32431e01343267a4d28002cc82755b9a19b2b0cd7461843c23e968ca0d70b6f18b35e217f1366e7e9991dcf03603f4c87f4199943f3711f5edf3e8e6850bad2825d6c9cd6e84c24432a08dfc0109bfa62c062b1c983c036d60bfe548c79df0227c982c158ced7562532dca672c859c417f2769543bdbac8fb06e8f891217d14424e24d4660c044e932a0268ed8f01e357038445af89e0c073cd48861f756ace4983653a5f48b1a2074572d298ed6e86f2b04a3181c9bf856c5c94fba9fce17cf1050b6b14577f75b400973622a150208a602c0254f052a5ee036ae0d0a07717450beab0f45c3d9715f6f4879beda465ddfdee5866f92f43ef51ad4638e1758dfe22149f99ab8ec3f9924ed4fa75f325d0b49925e2706b32ae224c908a1a55092e2a1b80e6c98529821272597624fa093492b469e4c8cc68e256731a38d269d12e929e423b8329a5279155716563b20eaae460af04ca89da0ffd2a40a8d3ee1952615287f838b5a26df996cb28da38c36ff104e06940b5b9b3811cb7a9f7b5362a7fce6a0f4a1326059778b24759de1c4c09de8751114caa174a7e5cb80297cbcd70985fec6c0a427a13b1953e49e482eea00d91c5e88a3a4649d56a5c8a83ba36fdec8b24d5cd07f5dba71a3f361169c76d16812fdbdc8ca66590da513115699671830f3ddc5618ea6eb7dc14d45e6a69ad24ddddc4dc9c43b5b1d8cecbd33088cb97df27863eeb3b484831c731099a3cd659e0a32586374704144bb84bee6e3643f2e5863dc69da54668b616698e3b11e181d2d4e702d91123bc5ba5aa98bf79f360a8ea95cc70d216719a37cd35741da68320ad40e03a5aa8d61647d4589062666c683d27d62988c6f77049f4e05d1a89b5356da22846b9be0042452052d25b301e48faee46794576faed8acba8a95c11b4873a451d4adba7526e8cdd5a4a5609deaacf83c6f379d53eaaeb8145f203458ff50a4404692ca85cb85eac49b028fa83a568014d15905fc1980f014f9e242d98449974fcf8e02b8572df55903af94fe9c0def31e1924b858ebb49292ced2a2c73f576c8e9a0f1481a3eaab4185e0251dd2254879a30a52bb373dc743ad0852ae93e573c3a264c4f794f073dadb13ed9d31175040e10bfd26997ddeaaf4411647bb49d2527050ddea00a4c1d4244fe36274e1972e289f10ba7c4aed8d7534d30cc2fce7c3532224894d4e3be91add9b89c5fa1b546bd41e066370fede5bf3737172f1e57ed059eea51d2d14d133637e3e9331510c8676d7ae66609c34121c8084ce820ca462032ce8680979bab5c35263c5ed1d9ee59039dd08d7b3c92f3341ac23006399f277ac65947abe6911b0009034742e2246613254cd14d1459f31f57ae80183c963e6ec2e6f522687f28146a0048fe383b52bdc40ff73011c7c8b6e3fc79b30b27a13396681d02bb813568f4362e26c3fe3ab5ae47c0a5f49d404be790f254bc67530ac2b01095f2d100f80ccf86b4b0739131e3c98a1d8c505272469ddd5abf0b85673bb6723dd255b4119e1f74dc5a18eb07cba9205ccee00a2c03d9845fbc081175166f140de594686cad2ab3755d386073f23ab6240db12801c0b22524eec7ba3a53780cdec306a775964377de465b025bc2a696a7ece334ca51d580aee78af9126a2424319330e4a7001e7b738d901725fd05852eb968e2dd34419cb2c762b02849f2a300791eac804544ae2776216ec1ca9466542147f2ce44bc210f0a937e6291968c0dc932b7f141113ae48b5b69c57fdb42ade8e47d8daa10943d21199ed7b272c9ed247a9234000e2a168047c2140b91c6ac6fa0bd7a5ec42b91481e0817e4f54c9a438c4f52a93a34b5491472acbe1ee056b91b940ad2ecbe7707aae3d33c31ebd749507132e47b0d19600b4407365be9a501fbb40989b3d1487407e92c5fd651cbcc8505277afba17d0911c3ad30e10037bbd1630761763245f55ea9f941f638f58be807bcbe075c2cbac2a56023a2beb680ef03306076e66b63539015a687df70b66d4325aa8a3accf944b39cf4508a61b14c715e4c915d4c34296742548449d87c039640ab5e7a6f2faedfe87bb5aa56b6da15f1df02eb76217ef27e88607aacaf5e52bf4b344ca15ff17d5f87d44117afbecf4510eee9938efd5246792ebb9c9d905aeef03006882342b3253b0665b47848b406d68e81be36dc7e84029e78402544a90424e6bc72c24f0f38d52f5f0a8a9762764e58e3fde0801bc5ded1c915b421c6798fd74fd07a83d6340b58fe1f6c82675890cf5fe30971ef98c070b7abfc7e9acef646d26c798b38cd222064a3725b134466f68f033a992640a7de9a4065d83aaf09b1f7b3a15381ebc010bf284919e08ea7c5a4106860815d87c793bbe0f341f8f03f8147f472bd3b60873209d810b7cf3ed816bc4c02d72881a7aede12a39b4b188a94bb3305a1d574ad693bb8d75be0c99cc10bd21d8b0724b6e49135a7c001bffa6eb60827ee885e99c496dcebed00f5e2b73d2ba8c6b643138d4cdf64531d6fba1fa18b58cdc4f3c99b5a461ae3e5aad88799b80a79747650043ceafdde16cfeec7c4797cf7bdd01126bec8915babddad27c2cda7687e1876e3269acd73090848aade257587574ed8e3e922cf598e7dbf84986032fe17759e4b698258636a0f6ce1333b7eb23e6851d88e9dce44347501bd4ce955dc1b7aa62242506eb6e39527f94b808beecab96fe8dc871730b0e029e24518d65b30deef313dfb4e727589aa207eaf2fea1407bcd223d7a5b4c65d2fdfd6c2757574b75985a05feaa9b2e1a678dbc07c535d98c538f71ccfa45b9f3f5b9281f8969d5b0b5c98d997875cddb321d7356bc38cdc39c6cb1d5067c3ade992c3ad362c510ddf62bb148e5bf36c8106141625fa2cfd7a58d46a9d710190f0da3531bbce6224f0ae81048afc660703d00db4d20eda79946014f7ad5d606d146b41b24dba8b82b5e6238158419f5a086249d1c0a54f41b070e4f6fd3e6f6e893c8521beaa350607eab0caabfdf63c0ae9833336a08d273f443e0c98435a88ff50eab51f89352165ef1ba5fd82e2bc31b3e1bc0075036ebbeb6816e9ae7783013b069a1efde5b72315239bc150ef22032db8c976f3fd4724efb88b7dafb2849f334e27fc3d606d96e76c9b507ccce63a0b0206a681b29ad484466433fe29bb066080cc146e4533528ec0ddcfb47121f22f4531b0abd437cc32642ab47c89fcfe4d5a5de5ef1899326f0fa88c550537f68285adcebf8494144153be88eed54b1adbc77bbf7fb5b8d23d5187cf2c8fc541ee3a8b9af539908396b013ba10565077679f1e290ede354005e7bbb53ef7ea581c1dd21ef2d02196af907069f66e9971e1c0b1a3abff73510bd516d4221fc48fdc795ac99f36aa60aa7a162d296c8597035ee52ed4c8d62ffffba89996855fdf5b7bac6957d7d4bd63e5054f1ab7050b22c1dde53e6454d92c5bf12af95dbb1e622598d345e98c5154a682d9470b4022d89f0c32b57ae16f24828f6eb02cfb8be0f24bd6780a6eca0ee3972c053a3e58de4895796a9d6e49db7b502b52bca8a3470b83d6ae33604742f3e5514852359a183a96a360d6c5a3765a0c03636cbdec769ed81728c5c4011f036fa55e3bb24d254112abb3d19cb0cd155e791983496a0980af5b30bd0e6ccf5ffc79eb8441a35c3c0598101c3e06f3bfa84ba408e31f3d8dc07c35dab31ea34b0070c1a68e8a4305c3dc111cc55f88b78d61c4b6b670fe40b69cdb5fce0b6c897b6c5cbcc3aeca41b0e9ce7080df0c5b7aa5fb8d705f558adf339eff21cdd067e90a7680420ca236535e89a2f086e5d383b6a124625f4c1312de1d0dbdb439519c1c7e406e0737bf492f2346f83a3fc0426d38cab7a8b19b78a7d21ff11867fb5bd62e50bc25df87dcc89552c14a296ca70f67e43581a85f799fcc209196c20590372f57f1389a7068c498ec74610780147278aadaabf3ced9f6bb918f0297983a17dfa1b9926db7e2e632c2535ffd3a9bc53e6ac2a0720d38e8e5246f4fc5d38daeb0a6c5a7dbd196915468791fcd0edbe6caa21f416415587f8766cab28a37d7ccc0e12f22547bc3d11853f28ae65b9c34a85044282ee3c86f8b6fa3ae74eca4c93e35d30839e9e31243ef1ecb1275ced33726d470e98c944045f33d35a372adc60d90f73253e48a9da5b0383058081cd5d3da01ff6627563e8faf92b40d8a16ee0cabd182a093203db9d74695925b7beb8f1735a79a4ec48734f6de27a057672287f8805965aea9d210e25bd1875218cef97ac1aa4fde28b6daa3e81fda4e4b8abc0c05605e23359b6ac768dce9850e53d3e03e1d8a6da4fb75dfb049aace427a33000d96516d94fcb1de021d18d6bc5ad2abf88edb7cdbb674ebf0b168e2dae314a60cb7f5cd24767057386ede3cf2338b15fa2041188f1cbecd2c2d87491918a2774b852b95f924669bef604793e036825ef36f025d06a269c038cf6b412a6e18ee395dd07e5bb549ed753de5817c5e0861d77811cf536328378c2a1ea986b9a4d0b7ac4837f67faaab4547a56a61eeb8a06d69db6e37dab9d2720fb37488b5e3873f46ae2a947b007a55b3bae5f4418d173f7134d7ebb77b9f219d5551739fdefd5354df8dd28a682e6dde5a0da4e21f76ea3125859c469da9c4c047b7d196df5685594d414ef1475b867c34f4edc495ace52a5774770d85da7c6bfa33a4750f232fd9e1a8ed880a48ec32c8adda2179835acc093f57fa2035d1f3e8b0742578d5bc39e8e9daf96fff8480835f94cb8e614a7e68b49cce628e0bc66a5be6fa92bf4ef1dbeae19e7091eb107491c9c0181d9cdf8389032e09b7424264b2f963c52d819d09d37b0c60da58fa3c85497707cd4d5daae8b1b9aceccd79081b5ceca401e61eea2d4da9a1dbc94478aee8d8eafaca5008c59d06ff20bab33a15ad8faac1950bb909d31d626007ff5ab59867a457960001cc5cb94ac40b9c338629c6d3530dfdef8a6aa44a6a1f70d5b398d000c4f4f8412b3ee536319d8d9bd82e16ada13e13d80ec5487e6388fc7105607f22f3eb654520dcb5d5200882138dc170cd0de1aaa4883f82bf230adb66f1409f8119b4fae128901ea315a788d0ab9ea876a6c98d230572903b1fba7be16bd5f12ce50cc0e26566885b5a745fedee0c4cda638ac20432a346ef76e410dc2794ba328f0f862e45c2f61e7cd215d0f5c15f1f1649746a64f770993bfbc50515a1ad063d2a142d83f08b5a1864c3308d21c17c121f98508705537ceef84460425c3a2b13a2304dda5518b959ebeaed924c3d9abe9cd8a7d52020f9bccbbd4f51576e2aff2637e94e50e256fb1a1bf2098b9023fbed6b35f624a3acfbb2b55436bc5da6cd3e7c4826c8e26d142a45dc59f19435c212d5d2cb139a96b55327e00995b55068b8ff0610e05bc907cbd354495254eef76db000758d059887ecf5ad854c389a915a295d7473843fcc73676c612f25f65b5f355339532375e2798ac41069dc847785f5041c71ebd2ee80ddc8d0d926959e1b8db9a0a45a7ad76a6bcf28c33c208b7cb4db20802f374894cfd8f217a62a44574e8bb45bf01f137fba5a7564b2363406ec88ae24191ca81df5b7798af14d50bc216a28902f98d37895026758db8a9e748cc99a154a1b980cb912fb45f3bd506cc0919be9c0aa72acf872b910eba82b457443d4d925abd1fcbed8a651123e0fc6a292e385e01bd93145cf2dc15eb2c5733072a3793b9daf99bc5b8bd91a29abdce2e87e3aaeedf18c760221b631746b1746a7be507376ff262e77b673b2f9932fa14d39deda0a112d8cc4f560d41b50024b0f778cfd234cc78110ee03506efb146698ba56881c20574cd05c2deca1f46b9415860115e012209badf183de2833f7b06a528366e0886d8a310876c56cfbcc53d088ec53cf24e89b5ecb7de3923c055fd3897189bfab354d8e16da4d0013288a6ef577f5d03f57f28d9eb0d969f722dc2ddc719569e9b1a61056629eb57163f2600c38b44ab1f5d89a6bdc4b895cae33cddedf1a1ff6d8bd44a6ec9e49b0fd9cf77c09ba509af6b69cfa955978aa91efeffc95e61cba3b1f36ca9edde872f85b22da1c1267a7183cb873ced78f1dccacab5ec6b087fa37c59138825364dc1edd804fc143ff4ffeef8f334c5839c73fff9a08f5f287fe5e02934a43f30ad99e593e4887781754894a757753378845221950702cbacf010f66fb291c1e7d39a9d1e3e9f6c976c4e3dcc473358f2f070ab9e48eb4eed98f70adf2820db9e456c3ca91ad9875f38c59cb9a1ef365a53ed02c35cd64f8da071e5214a193473ad578368710e1456fd3a4d7f82825672ca2d1d5e83779c4140d8c79e86767776de34d93b551f0932cb515fa8c399e522366e6426934c935a9613f6c99a1662cd5efb0c2174b433115258a1e387fdcdd9e60aa87d375b3346f1ec3c12b597efbe0e04b08975c45e06bd47a290c43dd789d9c40a6542d9e8fece63ad2c0fc9b4973e4c69acd2f1028cd9cf660bf44ed54e67d6fdead6b5390f47104e2d2f6b563ff2055722507574c70f34b1c8a460b1e9d116d2d7b300abb163ff8a2231327c8558affbcfa78a913c3cba6a1ba05dec251543ac86521d346d64b97da7cee1227239255eb83763ecdbad52dcdbda2f60f55fdb8573023765a22817b55a145a8a0aa9a1e5c17fd7dff6a5c961b70b3b97320ff363340d59cb317364da09d009c6f5ae74fb50cf787642d9cfd6b2fe08b09b776c73e184d976edcf00a400a0a3aa118db39010ceb9caf636977212ccb9f520a334c509248e9e5cb055ee08cbc6dd985ec949edfdd72892856921d77a288bce75b3a60daba062177794525ae315b193804c41e9f4880816caae4c07eca2d7cf552df4a906b18cd63243b2cd3a62c71540fecf229c285ddaa8074ba11e667241d4ddc3e6e21e93e148ac46a9cba06601a15c0d41a5ccc70bc0c64d3b4257285b6b29fe479bb7fe85a6a7473d08a7d1db8ffc22cdf58daf242d499677e2038d35d94432c5b7284c4acd0f140d972df1c0ea4ecbf1f27b1bb45520704749c9fb09e76d29d44dcc8bd3a2ef14e19ab46c634c764f7754fecc8d1b11e5e4a0629c715d2ab748f8c078056222736918e25809b2a1e573d0dd4069ec6b1c5195404283e42e3444bfded6a890e40ae55f8095bb6d43a24bdf41bebbb9bdac494f2f796ae17471d9904a6b63d522d6784ffe0711fc4a78e6a8620582879c20194d940bdd0b9e0ed33e5ca7a26d7df0425af50ded27409634be43ab80dcb70b392130423474841473de2286b05fbaaecf008dd8f1671f79b75a1a79067617aecae28b0dceb52a513fa21e0225405c660e91ac37c94f1da8b68b682bd76c603b0d99228796d66dd859e490ddafce681bce62a68c6ec7e8873a7e0f4c0ea28fd399122d17294b9bf39dcb9a9d39b2788f9f3d968b735d350848ca0ca7a528f2179874e09ebd4dc0d6933c78ab5dc79ff89739fc0c6c08854dc0db4b99b6be2d286b123d34555cf8bf5a96e3a46963fbd43f92440bb10e7e95aa64b89535a97f38d734210f88353026f8684b3ac2b57838a6bcd09a0198d24bb267f90a89c236d469d1587894a19bde81b87c13a9328f99f57c8933129e26139202aae7961a47ee80e585e44693f532bc9335362801e1015d698d1baed9f28e707ea8c452135ef7f286b59af3343439323ec5bfc1bfd4554549107b7c995a89eac42e318dae81c31946a866d1f0998e19c39394ce84efd0841f86770db4f08530414bc5753a95acb2004623064088ea106df117fbe3f6600635647662b49a7203d71a4fa45103fe3a8a5e21a0653dd09d1c924dd61fdf0421ee2ac6b7114f186a472d59414eb6eae29ed986baabf692a2b9ddf547c0b31b929563d8ede8485c187d8a879a48e8ea9768ef36cc554f174046de215e12b4e3e41b9ee0654e4129749b1d2e5c8d08b9d7b11499d873d813479727acf863fc7d7cf2ccec54a705fc507942d1a851c202fe4d86f1f2939ba70032a6359bd7ae37f2957df4ec8a5d889d2655df1d60cf17a756a5dc28c515cd7d5c0c44e2279b0b0134f9c6cc61d7ba13db98b8c096b9ab6f1ba0111f5f1d2cd35d0a28fcadcaa0a74c28c67521b90f355dd8bb05258876245a9ab24b7595885bcbdabbb60c862a9241ea2c1adf403ba59da6922ec77e133707ca749ecaaf6ff9a48b00b2dd8e6bd3f0094841d07fa7186b6b2dcefea73ca0a18c0a781370978e8d2d8664659a11cdd2cbc7507bd78a14d92694831eb0c62683e75981d34f73ef6c7ec43f226c346c2e9adc81f81246ca24fa91a046df40a0f25c1fa6020d542a7a8b250299d9d8c261d37bafcc214772c4bd55780cdda0f6ab453e3d43a2d98d1653d4b22d8922be02b5b980a271efb4e4c566c3089a04113c4f63a8cdc1327f7ed891c8ded9bc96d9f6d46db5767a8fcee972827ec1ab44305610d155bf6a7f1dc14c86c05dc776f62f1415638cf3392b54df32fb2ec922a646e4845d9259d526ab03d24b13d50853ddebc6c552c74d96a3ceeedf96b2852ee960d3cb52fc6e0aec9cbacb475075885098dbff45c25c1c86aa44dd1be2e9095528230f9e5c9ca1805e6d9260ec9579f1e4ebccb386b2b55fac6cabc78612f580f27245cab793c1952b77f22d2d06a511712ff2e3d6fb98d9752cea444c0f30b16f60e12eb2aad98441471ffa8a6aaeeed36736e334d2e20b292198bc3f89ea9f4e57c92f2915d28ed6b9658789cd53af1af7b90b429ea89d39655a306231afa13c4c4d0c0f479e746623513905c2315b3b38e0ec47c02156d77070f985219b7f99974673fde193d95c9bd9df3784b1d3e59423654968bfe175cbe5051b2aacb2ffdfd9d4aab133479376aa3170460743620b4e4a465b789d8225af452bb7a7a700954cb4b07c37a8125b0c342fc16faaa51bd0f2be941fd1a52637973f6c985d6f2ca044b570e8a48b83ec74e1eed33ad5779862b0fdca4fddd9cf9e7aadb8a4b83a87f2bf80f17e9de8270aebd09c14b2c35bd5549fa6341ee28f8988cb7457562b3aabc269d2654f112f0e3be84b28686116b34b0122f34e9103fcb5afec3b23cdbbb3984b4498911b0d16d896d72cefea232974208b008293341dd55cf24e0d5e1bee1de8e02a32a8645712149351d3209113fa8ee10c23fe50397835e08bbb1350446d82e12451700a26f1440c42ae91937c3b40b9de510015f9faa4912fd1a0778cf214198d3c24b3053645dc104192d3341c98085094bf2b81d20a7b94e7291f4768785723fb890ccd254d281d2d6fa47a6e39e555f08be0e19a404ed49c8953ccb1798ac125312af23760115fea118a77844a0884e0a83769054d248df1b24fe0ec5c5a1fba2cec68e3817d8cda44b04be83472e90e3844daaea9d2b5e2851f6f12cca67ab24070fd964003175a57ff80ea3e7183cef50d0ba338f206437ac828bccce32e26b1873e21fbcc93cc14ea7a1f32f8d74df66e415387ac58c0ce1b02ef389bbf242978e6ebb5e62362e980934fd9825eca7462232365bf292562e62a6ede277dfe5c0c6a911bc4074190aeac40b3122dd2770dd7a0fee30f5ddc8146431b54b24e770f003db4c1e9f5fe5b821d132902f09151d715f710e4fe8026cdfbdffbf3cfa0b31a3f6ea94a6dc9b6c2317e32278a3908ed7b5978c42d1f3606b9cba01b3eb8c99261fdc4aefbbcf380d082feb3411e942870a1316225b3faf3e52bbabc18047ecd4aeda6cf4a6ed684c44c6f58826d46512d89a6559cfc512314ab6a4f99a3335ae0cd103d566773e8d1a466aa363879e276967332e4138a5d8d9643486726fb2a90454794fc76b27ebf3d9e6b33aaef8a90db9af3cf059784e5e821a5604a669ac7756113efaa2f8759109b265277fc56aee2fe4f8e37fa3f6ab6ffbdd426970afe075adea516a288de9f0b954b0f61ed1263231525cb8c51ad492d6e2daa261b83bb1ecdba97996eec55f8a223f16fdce025f660261b300c54c95025e5762e9b7fefa04227fbeb20543b0e873b933d6a41eaa8a2c90086885866671105cb6a270c24ce2c294bf0870e0ad9f90d42b154039512809d1bc7c369a84df8c63d42798fd6218db5a5795ef79392419a209e9791269b1211f9e36b51a0ee7267dbe95d09b3d12b069abb71ff66cc6076cd4ec0fdd512309ab24e78ae50bc7c36583f89ac67990396056d351b11f3f288c81843308d2217e99c7468df3204e6ac7bfc51cbf5edf28d3815b82d7eaa7c7531a35a76865b63568da58571df210f392c7aad8ce073242c210dc61b19c892d1ca039755607526dd4bd217692119722507cd4d1cc06c9dc6c42e0daf3ceb2c1533f9ae15668273b19dfdad8d8ff9c7cc3d10558de76dbc3202ba216f53ced4e4ce77cb68012dd3dd3ce5d6d7f23e1514e141c1cfed18c9942fe80b5c3f89685b88e413e0550e6ee82d9720766dd8dcefb24ca34d836d0bbd83312059ade8de1b2dad440f4d92fa3348da2830eed3de7a0881ede975b3779eadde393e99b9df869eb7b50722db24032e7e5590c026fc67822d8807ecaad2d0c3e9d93c385adf938c7e4c226a40704f07b9f7270eb7aa856e20dde85b659a0de9392e4b0c10d3f05d0ccb81b6c4f0b5508b140a3511bbec32ff77397e560ad841c4b637e7c3e511e2fe0383fc81bc7c420bf8858ec016c15466a3eae32c56d17ff4a11f4be71e721e14523ec70f9ca173c4e15522ae0c6414885365d15c89cbd5396eaa6dc98b54323f5b164c58f2502604430cd51ec4aedea99bc5bd690bcea12c907c027e92838b35d2c158e9f6616751a164642d3098e2ee0e9f18131305351d75b748eafcee645cd16542c09115dec3f7fb34cf9aa95209a387f262257242a0e31ed46f322ba2814687eff9c2a0f5f5d239bbbdf32b5622636a723f01b434aea6ce1d6818634a68c8de5b415001014ae00a55766b8c84c832b6862319c1dacd160c8e41a8f7434a2db5617492e00552eb2bdb07c607fd82c3e05bf22d888a7358184fe26f4292e74938b24928c7e23d16b5dc99fdea5f01c32adf01ee78c077a70f3c1f8717143760367781037c8a8a8248c825434997af03a81291eb37778c93e32b57616d27d9421a1142b6aa60fd6bd15aed2bad3ded4ed5bbdf5aba25d09d5f93bb255a5e5a3423ba76f059c83f75dca12e3e534c182ec2d75cf5974423397a7d937b5ad0ef4f3c5a17a641f2a762a87fa384e70864e1e6cdc571bb038ad62ac31c1720f32766e25367a1aa64d9c080752e4e41936541d09e83dd9df6d3a860607f7d2294d4654a0250731d228ae7df6d84e93a987a40a4357cc351a65430c9478725c019217f53039489d8c1793312a6681486684975f8e717637e9a566c5cfcc6b787cfae0e5c7d10466589bb74d744ac11c19e9f6d0ea423ed68be3c68ea6c825428c9311bac9fe721a2af4224a7a5b12fcbf02d1fb8cf306b20927a576b49e522b675e5232090422d77cc93cbcc3b97f2a86976436ba85c80f2257f50ea8a3f1a6d4dfb8b46423925a36d493f676655192c20237fa686a82a1cadf2f7ed6177a8637c6055f6e5a26e7bd643593295a491b48e49fabce69ef46ed6b4d6ddad64028ab874fc0bf3bd4b4d54a3552d4e1699e03f45c51a5a1cffeb3f273970e34b6ba5d90d7632491fd7ff86ff11b6c04855f8301cc4b0d532c7e1df4ff06d2a3f564dad47e0b54411953e87e1dd1f08cfffa4a9b5dde7eab0cbcd31522650909a6d415d675adbcc0eb2253fb182ca261177220c34c02552cdc025d4884f1aba848ab03f1a9d994c1b1d0c64aef6ff6616e6398700c557b191772a736a45f1251913ab3ce5608035fb0473694e477193553d8e801e854084a4c6a2342ba882a4d0166096e92d3869b8588132d3b73e4749f5954044cfa188c3d3a7537403e597d8d5a8a4c9b1e36b2953641ab6205b206c8b3150da0045f2f1bb8b030ecd510248df0583922625c891ede367646583288ee0d202ceb35091ef31f8d8fa779c17eac0fc68f3f47402c212cac9cff64d241c9724f5704f28c44fb632cf23a446f7a93110645402f79a3d808000679f4b605b0b4ba518dc73234b0fdc7149b80dea91aa7a0fcfe9edc8c749a4c7a68dfdd6f884f2a327a2d8ca24b16613303ccc8e81fc4b6ed0f31cf92b252c8ff5de749d9ce66941a30487d1995b2ac044935e8df915cbff38995f4dfb45b015ed8decd9e854bdd76d54de12f21c1f95e5795c2b6cb69f0da4d32badd5ad4769305d86ec57ac97a6af585dc2f7bf569b39b78e7accd7657c020d83ecdcd91ea0a379493733eb4f635285e4b36694fe3c6bf589b5db4604f0b6bf41211ca49385929d8ed6edb864f1f69269f6422906ed9c1af51d791ae5a5b2bb8ec5b1775074a24d6948f4b9eaa9efe4fe33e2e513dae4e7d6c8b516a5382a27f72167568e4b54485398b331e2b011916ab56e2399376e92022e58927c9466705703cfe6679f567ff02da3a6219f393c7bc065b2d33f90b71318717ccec1aef7ae0d81c7f42604ccd3be9248a2d7f63d611c69cc37363bb79f65ddb60ed5b0ad824595b04957b97a9deefc7d5c9e06a91a2e4b7d7406054118f481b9ce83da1642a42c1a67d97799681ad30c700be84ae3f0bd7aeebc0072e7d918a7b969eee0ee18100bb16b8d628f460a92692b2c784a9315fbc685719476c43e4fa3556f8db74f866a92169101263d516a107cdfa3ea9194d0261d4c9b711765aeab849d2d00766db8b3eea23f737fa8b17c57ba10768d78ac8866c61369fe980fd3f5520b218975cfc4c967b11c2630d876b473b7a38d4aa75b633b592832d5accad046954c877dedb9ba51e561e41b3e46a75018e3184fd514de7a65549c2888831ac0c59e05262fada64185a7d154de3043354c034a3a35c534a9398bcec1d132d569191c6591de21bc43433e4331215439ba95e242433646a8d37c906d0eff35d43aea7462c8f1df622f69b57e0e6a7aab4d87e587825881618dc083c97c76e32f8231cc8e49c138c5fd31973de56067fb6402c5a7491a66fdff03ce02d4c00994a60e364faebd00a96ddf085b9228c38ee07d0fee8661ffa3bb4c00d75580bdbb4e7eea8786573291f3f616aadca3127792244e0f7422b77eb6d072877d4934eefd2eecc4948c814072d2ea05ddd2ef8d859fa04e4317bf1e23850d6999cc9cc77db7a6287f71c60258884620fb8f64e03d007068418566a453405161d372d81f405b9bc58af62793dceb08e02c8f4b34c8634e19db493cb89b6a4db239032cf517d1e9f83815691d70f778b370bd0260f37cfccf6d72fafa6f3239873e63ef9abb8648eb6199bc8fbe59f15fe214a6224b8627993ff8712e8fd21b2b5b2875e1fccd46daf33961a4458cc22a7a6662473c24258193189771d70916553ea343049eab617729bd569d525188b2e593d16a7426b7f97cc34eaeec2a486aa939b4f0b076f67a618e54ef7372603e8f32d5a7520951769b39147445391776f232253b0cec67b248139eb57c1b21902e0e57c2a97143ed8525854d02ddfb505cef905cd2eb3278b56d2d494df489127cbbb560e5415c5d3fd65213cdd99420eec0635a8ac568cf43cfaf8e7a7595fba1a768f1fa7c9d9ad9760c540cfe4048b6d09a745e346b73f997d2e051d92d950a0b7891cfd3545ca3159d7ea11be4df3988461f7f433d16631a4804a8a111eea96a5b2a64219d01bf239040ed4f0074d33bd4d7be7654caee31944d8ba93e9b88a85abf703589f6bcc8eaf4374f4a889e3c3e080f2e5383ac85a084c184fa2294368a0394a4699a3b5e5567c353ffd921a23370c97d8c2b0d3f26e54d6cf2c28b8527987731494061a4d600a714159e7010af3d88035bcf6898f8a9bcc1a0a20d20e29860c7fabe97a4837b59981610ef4001acd6fb30fa3d4550d590989a85efa05f9466b4b50aaab68227d1586420e1a2c1e03e4c90a2f97a25cea4dbaa5aa19cb34ab2fb1c305ae67521bda4fe7dbc07ac30a7e521bced1d0a0aa19bab03f0ac85a4c3a5fc230ae9bac2f5cb0cb50e8ab4f09da3203e5cb25db72945c241bdb843879019cbd402b0d7b376cfdb62633311df70fb676a3dc4db153ec5a0f8b2553cfae9758ea5865f91c0440f42c105f12b8966a993a89bf1904f7f862b3890b14d5c33b78d8805f20fb0216ebfafb301065d79cf7208ec1d0dccbce2df9470d7f889647aa36bb6340db4536e9f7f231a6cbaee1e35bad223dea274525e81fc799a1baf477250406d51651b7e4e738b74e7e71b5716a20a7fbab9f7272fc510eb140d8dab48ce9c38144536c66228231e885d19809b40937bcdc73f5b8ec02fcfbe55a48ee8843a64f18d41f77031189fb92f390156df1f77364a0d31e80d3196c7e8b059d95dc2b20f245892ae8bb5534286cec741f2227b9739846e122429096b8f2b8eeac4693d50d1f4f5ab2e50442d1ddd4d85d58b053ecc6708f7ea0877a346eb28b13c9b856fb50eb1871b793c0d0e937ccb496dccf3e2157a6a7bf092ed8160179e4d562ad20ff595728d400d088c14d3d67c256d6791d0eee16a88b5a53309eec8393f443d735bc5b5417b0482319a1ed1b45f7648473b150aced4a83e51ec6094fcbb8a800ec5789051418cf731243d8f4388f2a7205ed86008e257fd93fc6132fcc3c8b2e75b8a4d9fea74b19b05148ad7b3b44d6dffb5d34ed9bf62ad77db67063b5e066ba3f43e36d38b35c36d0503ec16a53840a5b4c92f9faafb7a36969a75146b0e72109db0ac39bc6d43eacfdcc603c28c16bd3a26b31d237e31a0088a439b7ba45aa1a3698753d10f0899b065f7dadbe9b663baf7ae1d410f3571f0084030ece21dbe951dd9ece2ef88254a431359cb8c46ed977bdeb6beede03e2c6bf998e1bce35fa77ac05caf784887deb518719c982447e7be3067334c449580d128d5239693ef7f0a499bbe194582168ca950b77e4d2cdcd2e88baaf1993a190443a5d2822f7f6927b0e85e03c755531ef881217d09ce575a1dcd6ffc18b67eee13b891b0738eadfb5404a1808f5d253a663f705e811e1cb6ac85bb3568128d86bddb21a857efe57b3485ac3ad37bca29a055605c862b81cdecd08dd3c7f689744c1ff26974d3602c714bdb2a02f2cbc141c511da248101031c8f44eea64e987164ebfddb31043a4eb8cdd8400ee478cf9d2f2ed80ffa9ab48bc5ed52fbcb0967fcdd1fb0db8c2ade05f65b2f72122852cfa07683b581dc715221ffeda77ba86c59b045b3f2f74010d065cefb149abc65bbf8420035892b6f451e3a3dd93a195913251d04d7cbc82080b80094d5c9a4c9234875c306b4f470c46776c1c094a2991af1b3f13ea09fb2f5d81b51be372240953e0c956e48eee7390aa4ef10c2c2dfdf946d0a7a98c6191009df2c1f024d0636caded4e0b72a6669194695759849afe9db4fe609106fe0b61ab39929f052af5ba8667939c33e53c58fcaef16ee4e520cb116ca711db6b76c753d302b62c282e73eb1d73f1260070f5d38e660698d70638eddbb09641b5a719035a69de266e3c79b73914ed06219a87053b185e61f4f4d2e393def0081331a9f9ecd07b3c360b58d7eb65fc52c3a0d7a67665db20c10ba283cf9782fb3498a0f05619f654c2a32fe81a94b538c5cb64aa5dc3111f6bd2fe776bd0b51df859c9b99e004eb4bbf6997fa525fe662579136df8ed437b8f38ab908242c7322df280be7997cd6b2d42af382ba241d21df5c4a7fdea4a49cf8f43a53746cfc0d0883c79f4cbd418813b9793cf07eac2058caf13c6ae002b286d3ea11e1c787b36a2f851fa751cbdeab6792331d73f1952ab3057f90f9a53ac072375100eb1d678ef8a590357d05e31a69dcb053b195923537ed5c29315558e423e42e93635682a4800d03619debe7d14f98719d02bbeab9c36abc08868f8a7304ceead0a8ad309505c00a522fafa54481d63a6e21b5633a76bbcb7e90c0a77d8e371f78aededc7e5ecd3751b2cc35d7321a848e998564db4c3e088bf53545c65c00247c16975c7dfee483b18a08214a7b7e718c643d0c7a544b4a9a4574246cdc690cf18e38252f002dc40cae4df8d143e846889f4d4436aa9734ebfe0f289ac9c3c2f2366ceb8a5e4fd0349acce7cc8495093d26158c1446518630a3817520cf9b967f581809b16471907fa0879532eb7483280a901564f1c300d79bcb7695c7cad0922593269016021b4787b5fe4ffd591ad025101ea3f1ed44c5168464ee48836a3f68cfb0e79c9ed8aa36748a82aba4c59c558b1889562bd2c710cb4adb284e274212076b27459b14a85c8c58266ad5fb104d5447364e9d1a982afa925dec463268261450e036e185526270f0ac11a9f903d8c0133e94f107cd29d9f426aa13ccde7e3f6321587227b9fc0868b245369c781068281e849aca88134602be08ea4fe1ce27f43f398570994ac88c067cf2dec4744aacd17097e909d54d570737d838308941ebb891f28159cbd4c0c82dfd4e1d07e672658c5e851c3c3afb6ad2079b81629fb8cec94385742b6316c2cd72cec9b2f27c067d63a1ad994b116cddf74e33036bf7da44ae3a68a4a0e508447955ef06de3bfb8c12376f35db2290a638422358a78eb796bc072708bbd54bcdf96b27492f1989720201c2f651421f1013e5b8096a498047762db89380c6e753bc7b5c002e957d245103f8617283340d3c881cc4a074a082517e73f45882c7b89a1f61b1f5f8f85af90b13050afedf89297831e4afc3216fcd6ca61c5d2cf7867d186e2291acf4de9cb788767d4d7ae3d62106b747175322cd6e48a5972427a58fa7e7fb8e9c37e268dcb4f2d50a6e94595154a14a4ecff3b65bec137f663b9329ae24b3c9aa6b3b288fe974bda7ceef38b0d228862ec59981c3c2bfdac0fd62ecf43937038d4b4aba51247068fa5dc8f41e80e799d06a3e33bcc11d111e6d329ed7e1c42804534d309f97408aeb0b1c49b41b518b4eb4f8043a02c79e44b6bae287693e982150a214003591d62dd6df5fc00182c0f73adc88c23b2de3bb1b855e349db1736aa1b5618c988bc940f14f96244d463af73fda80fa108d0e4e104524bf6d2f24364ba431666a4d712b63cce4d0e2a40e939dfa3968d5f3b08400bdbe627a3e374a92e6e0bf5af5c03e3d5797f3b62803a34ec8bcd8749862f6e62be2589ca43424f40c0b7b4c4f466f796768fd7bb0d094c1877f2e8efabc84cb45db7b710d8f400e3840d70147ee5e96896245c80e407c39b2e38bdce29ead73e6280e3d14566f4caef6ce25f0490f9303410937b94d6fd74337d4dff898d6eb2c17aff24c32519733e20a5afa1559064a530b498b843634414d256b51d8f56a99fbd9ea442454daf20be8fe7f78c230974011e0527528cd3a8b32c0b2d389d604c28be9b5e884c69a6e9aa121c7def48e9c388f6b905ccd7de84ea543f41f1b69d856593c7f534bf1a806bcd0ee2d276171c04c3838af43f4c45dbaeebeb0bc48df8c88ea407f7a427949bcba1460cf33d0f6f143ee0454dd95207913d83eee76a086fd5d3df345e8865a55e4e2aebe6e6fc5af04ce150b1cc3b0758d9e46814f11f7a001d930f792c20d6aa8a32902bbd5844658da2f39984f1759ed6c7943f90075aa4fb0fd4cd6f12edaf44030ef2f933a15fb89d12c782ec9f64a88851d0b27910e12d46069fac2693e088ef4e175fd32a6341dec3d9480fb0d559e52b58d0fd6f6b612f80f3f6bcd8f55fd11d02273e06827a3e4c06baf314bb18864c387ab42c403228d3c323483326144ebb5546d59a15d64a6c406e99bee6c7da6117d2f72df00e2741c04b0a43f26fcf7a788856f34a38bacd9bc1ee4ae080aa4e920110da9c6ff0b3a754e8eba07924eab280d2bc02bad23318c83264ad061543e81d03c0a667afcb2d420b39a6184e0bfecd0b8e092b6ad23f2e201aba1d9853a8e4d40c8fe8f9b9d48befe2636bad21c3c20c11f2db695aad06bec4f7cbd5be26eb5a95c728d21b0bac218c40136556dc392af6e60dc6bbbc689ff94aee350134d03ad3e161be99cdc466ded12c08223fbd236ca5210cf8e22cb4aaf9943dcb60a3f57b39923bec1d15b8608d8559ad65f81a0d7a49b5f6401aeaad8685f805595e1806f0bd9216aa3330d1ea7c0c5869fc3643271039f9cee5744e2a085b92df2656fc51e91f2a763bf2d335e860289f879852d2b801a01f572d38bea8eac6d8d9c89d39129cf627119527557f49305ea3830d64325c36e12332b9ac08c1f8dd1809d0b2628e211f1f34c24a676cc3e423244f8dadb212c02d30dc2e73397c651347ba0b993fbddb871526f9e031da6a2e72106a0608f10473b6929144a83ecc4dc219986598d8d1bc880994eefb8e68b1edbbc147cff50227b73d984710f6c8adfff16052113c4ef6d23820c9c4fd1b08d06d15bb5e0f37264de68c80cbf3dd89aafae57799361bfa830bf437048a8f7fb45a30d815271d7ee7a45f5a478caa3b769a5db755f94f13d918d9f5cdee5d442354dfb6a7f6ff9f833ffcfdbff3599b02787c280440f128ce52fd5ba999180c2ad90131175d72689e2ca2be21d0b7d5be5d6209914608217b6fb977ad0b520bee0a78040679c107638733eed178bfc6cd14a33e3b1fe6edbbf34103a41dce00cf02c60e51a71da2c02c244bbcf2c3cab515cd5ef44d7435efa29166ef5db4a25d9ca6d97b232d53918a06aabcaaa8884ec12cd25e2f7a48a485eef558940fd8bb05816c1344f998b79fb71b90ed99b73dfbddbc2b9acfb26f286026925f70e9a39b81c0a3166c6a09c354ea58746c59b065c1a294c75e7d58143bb4262bb207ad358940d247371dbcb15526907b7f74af93bc7347f13cef1998b77b9b7745df62c783ec78f03c50747b479fd65e667ab7b1bd993b26ba771bc74f09dbf9981c18e4056f60f6beccb458bb98e9f6f7c416ed049bd5a1086c6e56af96344c6cc243a6274e0d59b0264c6c1d232d73b3586da4717e3a07a8758262fa26080868dafccc9a5610eb4776fbf48d4fdbb0baa6a795f3a303b4233f593b3a466e58467a6e78a48d4e500e10cecf8d8f4d6e566e16c690d08cd0f9cc286270c4073e34c081028b0c1990200738603981851ffc200a168ca298620903f022053b602c410a2e48c07282203088f18530e8200a5140418ba2496a490c1645866957a5339351582b0cc10a3b50816475770d8a02e7cf0b7684e3155638410eac70044b6b1610412c4008118e577411d4a25e140995c06e610a5d58e19986e3155d4401e7971a18d4200a4a70b71630c0a26a8102032a44358c1083459161da55e9e49121400f06488266a405c4c462f852bdfa3bebce341bd88ae3155d64f16920ab0b2c5299076816c2ae4a594004b10021ba0b1fe0fce19a0328c4985e304d2ca610410d80bea0054f1758b0021d1c49228c9b2337302041080646424a08e178451738f88991ce24ece870ce177a3a315ae2b82c0837bfd880f064f082638c5c08be2db4186bd6355a3426e6e5250cffefeb1d7a583e3c5115df3551159f65af117b583e3273364e879d14158bf1a2d735bf5cca4e33f0f4ba61ca892c9bf3650b8d67461eda6adaa22ddae2993059abd5d362b5aed684c932fb87216dd116ce84c96a6a726a747670ffaa993058ab75d9b4ae9bd665a43561301e9e1f1ea07ee59930180e4e0f0ece84c1aed6b76375b09a93fd58a0ef0aca5a592b6b65ad2ccb329ce3e064389147037398693cb49aac26abc96a5aad568b8787870727b3381d2b563361b41aac06abc16ab41aad46abd16ab41aada65751e3f17cb063be6434eb46603f6996659719a533dbe1e9a93835bb8c89797909c3ef9065df97655996cdcca7f503d4945299655946474984b490a531143d8a8ab021cd1375a20eb4541cf17e030b2f440516da25483d2fc8fbbc37b0f038288ab0c554d658b84f43dc6d2974aeebe6e4e6398ee338d9cd5819eddcb890d6a5c266d2ad6ed22b4fa705b3642fb9edd361374b0acb653a5d6b986055603ad81418126ca7438c074bd2610fa604637588618de5e8000a4c04c519cbc9c172705f63f56c31656f4b72d2eebef2b5e56cb25df3e32cfdbc341ac0b68b460317d6625f74e688b783bbac58b6c1785ae8f12fdd23273bae3bd771de46e311d14537a51d61b90e3ba485407a81a956f55b602fb0648f883e45bfd1936a5518765efa00b274c83536852da6b20808898db98160b266d2a457f512fc7007559fa9ea571f1a96f85426b5d561571f2558f90eead57c2f2182e2dc4199ce8eea3361424b5ad567d26af2e304e8c9436384215688d561dfc38195e774268c88dbc1cd855813469465d67edf1f862f2f5974833bc4c27dee66c27440409c11201ca01ca009d3b158412cae86c5d9b0264ca7a3e3a3d3d2d19930ddcd54f5b31d9e1edce758dbcd84e1b81faec5f97c391607e7cd082b13b130114bc412ddcc9898979730fcbf2f8b6e44749e5220202020168bc5d2d1d1d1e96eba9beea6bbc1fd21ce01cdefe3808eab08c83ec124458784bd4e2f5538bc816d60ecd2124baace39a97763e5bbd460920e12593876286764d329b30e2f5995a001851a042d1b5995efe2a9c293061a00ed59e489943e3ba6d10c9c32f3ca4126931d58f9234c291c81f06460e5299d194062ded3e92737587f811362d015c1c2045814c162c698c9af3cc17221ee5afccb0e8ee3b46da39178e366a557866911e8a61c2b8d84ae5c42cb81e5b21b3d4b48231eb025d9538dc89b2d58969b8f93558b493353dfe3ea8e6626fb6be963f9d65d8945b7c670bb6601ac5d5ed48134ba6c9bf670db429a065e7ab3d99d6c30b6382f5a6bac97b44a0905235e09ac8c316659966559966595eb32e69c73a6269def10c4ae2a6f08a3cb8cc19fc082e8092fa09cd882f6440de909139c1a085b2ce1c2085d388207070b430461a8c20a181c41054fc480f444153409321c78820c8690042e244187081240f891c107b2600227b678420bef892d4448286d618302911d64e1440b142811069b1314410bac248e2843075d24f901fa585ee8428c2b64210a3308810ebea8e9809223c22003082870c2e64ee4e0bee2084d4c011b421264702426d81713e7051fce0e48da0e46385ec1c58e86238252e774bf800aa3304213052f608273c113d210b617844114bb60c2929a31961cd1f345fcc217a8700310e0400ca02cbc408b5292177cc044b5888922d33829444ea2f68398182a4a4740a941131ed066f4b800085f9842167aac2032832ad840490f7a10460d6e78b486f36444b32802d74413d9771c26d0a004f8a8108424216041ab0c1e0514e1044d6a82f063b3842662903561839092264ec0c96eac0525c07d8e84e3155c60e1154126663c502cb12581e205251a2c0945e1a4834c05c72bbae8c011a2f6839818222920c2132536458270051222d012b670e4270a4048e2880b96182571010c6a5023acca48c20c98c08229e458e1c38e912435c042055bf0000b5113be22b4600b5a0b825868a079385ed1e40976322704a49396d42706e66318569a188661d8b10de3b01f260642434ed88e9c62c71969e442df36d141d1153fce6659267a3c62731e29a1905e9562387afc3204e8e9f11fcb23277aca032010640239d86b4b41b0c74da034b22321a4911dc570641f47d6f352a20894d9820077435dc112a0876e061382e5b2d32540abea086ce90616599661599665590f9d8f53191dfb955a73a263fcc0e0b26e2cd258639c36731ac1f11447eb9f06eaa05993c99898979730fcbfcf5a6c076a43690fcba785e5e8ecf05cdd4c635de50fa531a358c52e0c03bb060251159b06142c10ddddfd45ecce00be24290535f6c4b26b5ef3026d8753ebacb1ee9e57adb4e71259af62f7638992963e68bcada47b3a9c734eda2c11e08b07f4999c73621798392c3beb26aa0c54e1c6ae6a23ae3e035313a61da6af1146bb9447c5e822a93c06e64feb1ef0000542c02a9cc29a4e51658cf790b039c33493b2524a834c91e433d24d329973ce39237d965936e5af0ccfe59153cbe608e67a66c134ee88305fce01d3a7a2966197d22458a6675f5a682ac15a5f679db5e79cd4524aa9e4f024829b7ab1cd6b5e5536146aacb17a29b097974caa8c466059af959992524a9b06947e578c1d1ec340db210d494d66f232763392528c088a2b48e714d78eb8c2d705e6ebbaaefb7518ff0169ef466073769d070e5f59965d57100e7fd7955d1a88f2713d0bc2e19a51f044f016349858f9f8fee930e63e9009c420e04c0408787ece6f7db386fb1de670087737c1b14f2ba6fd9bfbb94edc59a63a8c1aceaeef1aceae8ae9ad14b3988633ec5eb4629a584637336995b45fafebbafa327d492c33e9bc9e2b9765199df3d7cd1d05ee67ddcc3c0cb29c18e0c6bae6e99e66d52e426593a0298bf8b47e805af2f4b0a4ed82e002001c3f223c8b7009d806a52d6983b3bb1bcc73ce0cbb404a678d8d498d04496c34de50639c51a38de80280d0b30e3812216681e31270dc02c7cf99045f555479bafd071b80e7ec64f7e3b5f3f128291561a08c2ef594f6051279aeae486c9189cf920e594a7a92f05441c5890a2bbf834487ca981c2870983042e7121dc66f5bec26bd349060e5a9108a670f374814e950937382d6fba62aca1a238ac02e0cbc2ebd402b64024120f08021a6100b984174186fe262b646b3d9dd9d4d3a35307f174e8ece4ead5ad7b40d8ebfe26b1ba1b1e79c738259d3a4a669daa9a6b57e8082a6c6d3c3f2e9ef03bb1b476a9aacc1f1f75e9ab570fc4f3237023431bad81fb1398f011c190018624dd58dd8bb3c6ec867aae823401362459790121518ea89d828bcf77a7b5578519409a650c0b1bb115ed40d903e015327e04d763d324c23cba03e387635bcb40938765675fbc7bbaa4b84772113cf00f17ee3b1fbc10381d467f8c6653aacb737f310310d86551f32b10acc15a4c170f81be0908943b09d7498fad67136bceb668800c0856478c7575f5d1296dd0f948fd0611e3acc63bec98e8798ef808233f5ee8d1d6e967887e370730c02c62154a416e9904da8a6431c2ed39b6481cda11e27bda20ff5c41b62ce739e3355f47fec6274c141b2260c8fd3bb3c4e1802bce571e6380106c003149d763fbad7ee0798cfae470ec7e15b1c2273fc7a55f7ee0d9006c3378e6fbc3418f6c25037a3ba016689bb1e3a9c4696c183005ec39b6fb8ccdce14601dc3c04ec9f0e53d7e1d260d88219e61e4883e1fa1c628e03d84c3a4cdd23824d3d877230fd0d371b816df876f3f6f0366e96d8c60370733ff101e631a9cf8e0718303464e29afaea963000ee8e7b84e8421fca22ce6003f8a9c0d60072335f0b6c967886c70e6978ce360f8954c2e6c864f3381a6f503d84044c9f3b1c433e98621155f4b97a5bd81ceaa13e9149ec50f51baf9706d5cda5f06689c36f2fd7fec615e2c5ce8440bc976efdcbb5d93be9374021c28e07115681a19ee8426fefcb6b68c17244f8b0db4960fc8dcbf4d6f9d88edd63623b7a217ad53e1da664b7281399e1a27a342622a424bad0d368a006cff01994d8d46df4a06c2966aae8a947a9bdcb73f8400a3c4375fa0b49afc21fda8375802e60ce66bc05cc56063007384375bff0b284c186dfd12b1ba70f538fc1917aea16cc5fea1e98fabc71251e7dcb31e0cd2ff7e6f0970859e3661a37779219375b969b230feae6d85ab959d6a8dc2c71be9b254fcacdb275bab94d2a4098966e9e00d64837e620fd243ee9d5751ac4631bd5d0820de14cb1778abbab20d852bdead97904122a300011ec8141ec2551f5118758a80a461c52d221fda5c21641e00210a6cd049e3a1dd2504f87f452847a423da9774861280f9e78db1de60306663d51459f65a11e5ac16c433d2b3502e804e86c3195893cfbaa6d1dd6dd963a9acd796d9bfc9c735e122588db83018018dd0584ae100f80c0bca612f292b39b48b84b80db83012e104174d8548273878253a743198ebc45b7d7eb9697243c55ec20d149c253c5ce44024e9d8d76f737fb450476931cf783b76d9352ca21f0bcbac76e9e7bbd44f0bc422aee38ee66dfaee64447666a9776a8043711b48f63fa4f753f87965ecd3975a6aa3fa7ced48913bc46d2b3628ba99c0284e54f97e9eff528a1995047ba2d91acb5329d897a8b7134baa854839edc969834f1ec9cde679f46565687b2fa70613356af8ca4ccb84aceb0caca6bc8c2e6caaa711a19a9d5abae49afec8f13a05eddcbd72741bdda5e44df64e755d6b42140d6c46709a9f563ba99930ce849104b7a60c6eaa9846459e2c3a4c35693ec2763f520c36a69a9a7d7b8f9346cb0fc8c9b3f969b332758febab90575730b5eb94450ac72f3c60496ff4e5f89498bb524746ddc7bc82d0ce9c3a742fb89c096be1fa54f13ca870904fb0429a6271d05354f51f311934229e5930ee5b4893652dcbe36e94e24a6cdbc0181bdcc84993651253fb2de08c72c9294813b07192bf3c998b43a6cf2e364dbe9db4bc0607f7a4599b0a43aa94cb295b3a7cd54c9db4c988c5565a6854f077083ac9cb1b0fc290f9902a44203acd4216d9a1e3b1e38ecdc56fa388b61114b1a0de05229e2524d8757119425d8f8ee229919e91513bdaabfbc2ca7575892cacac1098bbdbb77efb846eb9b3953759de56349efcac2137b28bf5e32729de4c47a67d2ab2c6462945b5b915850a7c30b090a5877588ed81c84c3a573e7aec4a28c9660afeb7afb7478fdc6c0fe7ad5c9aa8e5775aa0ebe3c9c5e79bf5ea1e895fdf59a6302c33a21aef29079bd6e116fa0c17006e621f37af5893764200d8643e0925e5d95d5e13577264c6545d5f51d7c6961871d76d8e13b649939f3aa210b2bb178c55859132606bb8957bce215afc8c232def8d8b06a7a5a39d815af5f31c6eb25a0d17683e54844422171b72592c974996e1a894d328dc51863bc1c8dc473939ce763433f37ef9f76d22ba0eca6574b6446321e2c5f9974d5a948ea0ee912a557a6cbd79eaaa4b2ea92ead3abeeb936c1f2c7b2a399b9de43622cc699f84d765c8624cbc9a0c8a6c874b29dac8a8c274bd2614f873253d22a79b904736f2991da6a7ab3e950665564507498d3e1141dea20c9763aec0cc70a3bc1306738585e86233673db8d56b3c52da3742e51d24d29a594625d54d993d65ecd896599d64a58180bd67ddfa569217995acada16ee648ddba4749b3ea63ee9f7b4ae7f6a45a91e43fdfb192d6d9928a7492a8c29e70bc428c26e01c794236c82e2e963085cf6699b5359e7081052c99cd380b464eaba2ce0c183b34be275cdca0c250240c48ccb04f94a860050c3e2c4f7860029520d493263e3178569e20718294201d95309ce09cc2e0f9c248c20a4c4140296104a124c6290c1c908074630a03c7042863d894c2284112232052f602061949d8cc669cad99a2470d1214fb92797102ef25e665474c194ccc9401455b309e50021d2b96d80143073740603c6102303a8033e3859e2fb6b0c40c188c7cd104234f6e5430d3859b2fa86062860b3b5f48713343c6cd172b4862260c3f5f78e0043d36c002a2c213335f68015511c54c1835402a7862e6898f8e2fae8a4d23d785553afb65474c0e3a70b4c24908a2c08556d7d362a00077bfbff0c205672e39cd851bdccdd38225ce26108ef12d2b940f357b7dc4281fe8b1d3c730aee25951157db296fd89aa88817802e8f86ac1f406a977023fd644046b73a5b0b789aaf92cbbc06c373a42409122178dab0c3c820a628581475041c85fd7ad210b365b3c6d70ee1afbd5643986cd8401e2099da88a3b31b70d8f91277aa22a62201d54cf060c6cb6980a3ec0d900962fc51b68c0f23528b1f96535e30d8de5770449dcff2abebbbef40ff13419d081bdb40de617ccfac12a769d4d6577d3a96937bac4635a379dddf39a42944d7bf5bf5771d22aab3652c1573ebaf4ffffb4e514fd95059a13f6c2f10a2013b4803a70edc05a1cafd8421846c8b62b50a1c48c173757c831c115545082192bfc5ce1034af878c1052578bce0e2a60b2f94a860860b1f2f729082991f235e1869c14c17412f3b6272681c1e2b4605c216b8c03973c1d18a2bfc64ac2624cd2c7e02d4b516427072c9ab9b99320b210880b6168ce0d60217b8ff6de1481696e0be0e234e664086d5f1440c58a8020e2721c0f4d336810527303da5385811348a269c391e2c8ce00a59e02260afb7bb496096989481c05d9659fb7df9392482d35d0188b4e781281fde4fe7c103e989e06dce8e07efa5cbce87377a8740e04d869a1e47db06e6eef129f794c308b6444da37975b7be7473e8909ef49d6e9df7d82370045a30db2f7f1db78121f08b1d0f419aa5d49714763c1e469fcfec6337e3658947398be1d9a69ebf1b22119883bcdcb8366eeac670c19b87c09e2813c1a3d0bb4ce720b0779939ba127b1b58badbe8cecf1c327a28573b1f8d475ba6726de5333ee32c47d5b0df6eef7d13894a17bd4bf9057b236fe48dbc91e779df4657f4d23d7d93a713e863f4ef2390e5327dbab28788b9933e8ab847d75e9eeee85a992ea5fccb5ce6b0fd4ea5d14db7a543fb94fb5454894e25d1472d1d8a2e33edb5ef6e2ebd5f80db5fa62de89dfedebba3796b4f830c9b68c5155a58eec0d2873b7ae9662070e9b5fbc1fb28cbacfdbe7c5cb2cf212e956427026924a600101a892de8c39ef48845df9a1b5dd1b76b2de9ddcd9c6644b77703334a04168008b68f18881ce40557a006b660ca3bd3513e3b1fa6a35c76a79ca58cbed153463fdd340233105874eeda92112cca43fb2f4c99f6a7d0821908bc957ed95f5d0f12ffdbcda35ff0c76f41203f0a0884c6ed4b37c84ba492a844427d9fc874292c9d02a62d7cbacaaf9bce72db860a2b31e5a191e870d2b43c64e9d564a14975586f2c4290125c6f7d49c483f4be2cf7d1653e76a48b6ece300924827ec5d43728138a8585c5f4aa72539b2e8a544dd474691392746822a2d67a520581d06798f4a62450d6d38c53e9d4046622d81401fa4d745a6b251981ebe91e99f1add4348ed028b1743867e4bbb0d4d37f473de5f943f5f77a514deb5751278252fa150a02f99ee195eb3b6ac807ae804326be4014d8fce127b89bd26ff13b81cdb3064f1b8260b30d4c8ffa7514e9116721159b6eff953e4b4f297da5f4195f0a2caa07c5df7d6800e70ce00f8cd105854ddf48d76636dcc09248263023813e443705893ff19b3535a7cfcf22bd221df5c19876e0958f25a58f859e812d9df4ef32c1f9baa39949790f893f94caca7b488cba4cb70df77d9f299f97467a75fabcc49139281f289036dd74599e0a5b4e7707aa91b81fb07d03b64d0e19d8124802730b102ca9f076f7a5c31c42b36dbe960ed80bacf4fbe8f7e195b6f1b38465003973045b4d60730cb673d2d6c2662e268b3de3b444708c0c0c2637a5a0020b98f9c9811364d7ae85b2a99ac084c91ed240d4f753c17e888ead982e88e66104111ee1c523a7123506d798a9aa8ff4461471123281d3097c406631f5130c84de747a4fa79b4e7fbaf4d7a5f4b18b725641228117ebd775786173ec993ba73b7984e8b02e2008206a0f24148974fa05d4abc656dc5c3e4ceaaf26d7cf845179fdf5a4fe0abac6e855bce20b49703d56d32b89ebb122f5980de9745dd7751e1a5f32321d56167c95388c0273b1a6aafe0aab4c8735c7e42083728760cd672430dbd33d1f3b87b8a6aa9ec014d2af3b733aacdfe52750afaee797acded3a6e870a7661605cce14bfd4622819a4e87f52750cbe9b05e0625b41c5c7f2db97c2ed6119b2f16f72b9f7e7d3bcd9553de7e5df77433e9282512e9a35fa7d3e92730cbccd1a531029f4ec717cdc4a7232bdf36120a3c82022f9fa95ab9576baa6a04682e9fe8722de9b05eac0eebe9a5938ef2eb843222fd7451a352e927d209a57447449c4ea76f271008e919de4ea4a38c3e64e2119849200d864fdfc021139f4e0003f4eaf4fa1e80e855e9f541f40a65f47a217ab5bd76df2877baa66f9be4aeae479fc0dc4f4ca7dd95812930fd9683e94750607a141c4c5f6202d39f326024034b607ad2bdc1b4ebd1f802e315bacafd6a0eae4fe96e8eadd88408ea4d2020a49f6ee8a71bbae89a28681fb3ba4e8fdd7592ef4bbe49570213478c6dd7b65ddbe995406461205bb6f18a2f28c1dd49f4f202f390791a0c979ef2d8fdf0813d74583f64e212573abdb3fbd19df4ede226bddb5b96b039c4f5a257efdce8a6d3af6b3abda7974a27ddeba64b8361d36937733281595e6696480f8d4e2f3a290f99985ef4d1a5c13005b37d0fbde22cbd5dc4d84337bb6a965d2c5caf8a02b2f963e955c459dbc1f555e35931b2f5e0b07c4c79486cd7cea9391326620147a75755f42a2ee955bcc20b504cdaea02193837125cc4c371b283733bc1b995e0c96a9f6ee1f94aa3cd44a25792c312ec9c19b2b0b1c31d1df6ed1838a7733a9c6d63a7b5b15c186c7ccee80d09b698ca590b4e61165cea1eb19f09d3813d46abfa1c07b495b0a0104b0d6e1bdc6007c5cc88043ba8c33e473b88be87945792a01e9c6f4b1f4b87158a9a5371329caba9cfff1b7c051b3b94427af6181dd44f72d4d8f929053ccf52a9162c200a86af2429189830670d5087f3c93b6c2909a1b725db21865d1ff64cc5059b1b68d228e0f98944bc41e29965df57636c4a81260d1cb5587204a6375e6b8ba92c9373c2cca067803d3e0ac15c4604d3ce87794c3e60889c1dd12e4487127b83a80b3c127a4d69d74e55fd3d818de9b0d6cba0034b8f8110e85036ce18c0580f0c63af65e007597b81324461f34bbf3ea62a0824f2006d368241faa1c41e4002e72c9ce245c8c47285525a4121934ef92113cb970d6c3195576a30fd579e602b89447b72342c8574905c97e7813dea3d09b0602015943ba004c1607b8e60e11cca31d2abac02847182a88c3d459898c248cf116360161c7b8e68610fb470ecf1000bdb80638f0798c0a1291aa6c80c3c1d39146f59d6cd7014f41e3e76332a1c5c3dafd6476c6ba80a5f809e74483d3013c92cb85a0bc6baf180f2d1611ebb202c8f19de436298cb34e5a155d01d3a05d56175489768ad0e29939edb9292241dd26b55744871a8d78687c3a5911a8f8dabed8494784ad8102bd4a3eda838c12d2a4e30d580a66a49c867c214e9008f1f711e33f04edfe5f4ca86d37753f46ac7e93b9d5ee170da0280875abd92e1f4fbaca43d51d5f9b0f17a95a05e5510e5838e7a1da0901fad0274753eaee778ed6672809946eaf8f5aba391ad9a9a1aac03bcbccb52031bb1918e5faff70ef31caad1e1e5d0715139aeeb3a74783a88b8aeeb362e1b33d47b3a3e64621d609ee136c02113cf001ee1716d27cbacfdbe873b98da67ec06d37b44b05cd8eea657322cd12b1c8cf4ea62a2c351b9a1f4975743d5aba004ea90ca1f9b1b5e431656000f05f09ce15000cf16870278fe70f8d82a55ab540ff5cc9898979730fcbf6fb6e8f0fce1940ecf16a77478ceb00e4fd1f01b376878b6f8060dcf1fbef17abfcf5a19198cb7e3efb3f6e5e51e13209ad3218b4ed1ab9f9eeaf44ae5f41449af767a95e3f4b48a5e7da7a73cbd429dd24839bdf469399de194e5f4d249af5c4e2fe9e5935ee9385d393d8f2bc3c5e1963abc6ec3fd3abcbe6d5c8e6fdd0cea5b4733f3bd87c4392ed31bcb655ac76337b3a2a3e5d4725b6a9961866e6686cbb48d6ac37badb536be5ee765e39e776db2830163871798596e37e9b03e763d76f8f57a95dbad0eeb73dcfee9b0febbeda4c37ad46da00eeb0cb79475589fd272b90e6b3dcb75b92c1dd6c7e8b8a90eeb576ed83336c0dc4f700547a7bf2e0e56f7e4fea1e1ea70f3ec993f985e0037539b1e1600dcbc1569c12f376f36981edfbce5607a999bb71e4c7fe3e6ed07d3a76ee66c329783e9c39bb91e4c1f804bc48eab5dc3814252141d2455f46a87d0719c5ef2c89e2d0761c1f6389e4ba9c6f6a1cd99570a5b308ed4a5913804865417c7d5803aa413c061b69e05bd0960204228cea457d0bb2f2f540c208c711d62a2c3909111ce1407a1837eba6d0f9407e0a91b80dfb8116f371dd2ba4494692d480b32e2bdbed4ab1a3ec3ab91a9a2f51a50d680307da20575484f030d7fa90f5f5460eb4b88060d254858a19c5e6515273abdca2a41a11c95315482a650828356378fcc6d11ca71808d57744107d7c0f18a2edce087efe9c00f9601c72c923082b738848d5774a166db86c0048e57044181e90ed692504fafe2155d6882e9434a7a2531e591434b30e5b8193a1e6e0891d803730570bc1e87639c753fd40be02a4f7a2580d3ab00a93809d9846c629e7570790640cbb34b8e671b3a9e67c8f06caa11a6deb0c32b986d98b0b588cd0d377698fa0e17eb7ec05cf521f0f163c01c83ef02e617fc163087f839c07c7c1d60fef065a0b8eba1c3f1b76de364c783cc431e6edcbedef0deb54fdd4c71eaaa9b25560d91e9f0d26038cc5962ef3233a5ba0d979938dc900a4788890ee975088f7fc3fba6753d645eb10d6f37b932de3dfa1ab2b0a967c94a9da7e7f4d8a7a79e82939293927aa867c2c44455ea34a61e434c1d7c9ca9df54ea32a43e23751d37dff7a5fe3d7595d48f0a90caeb4d7d25f59ce195d45774be1c9b4a1d85e3f9c32c389e2d66c1f19c6196c77896876a7ae59d3eb48a9e0d1f3b1b8a98d80103d77fb6feab146ff5660ff3c032af219889e0f09ef76aaf3a9829b6b373046274f1c06cafba71698cc0de65dae2f0d24cec1de1f12da6d2660313994c4741b18172329d4c26d34d39ca1d813652c098ba9187ccc43a03cc380bd6f5d0279d7ed3387b4fc7ba03483ce3decda89fc01c9cb028b07b8340669c050412834a4681415af00c9004e6202d3886c78e01acf1fa06f3fd6b7cfbf61aa86fa81a2c47adb01c5583650585a24183c6b74b03d51d8542a1cea1380e6052f7d0bdaeeb48dd26b9d9f5a05d105374922a2a2995d148741a753328301781519799a84b53840f0c03e98e65df6487d28181c90766222d3908cc1262d4fba530856a168cfa52be920aeaad02a6dc54baa89414149851cef2d25325d1572e33576e3ccbbd8e7245ffee904a3b1fdd49df48b26340ea36bed9b86cccb8f72d555554522aa3914a0b26ddfb8c9b8934b68db78dc38248dd46dbe0b0f72d753f55b2fbf1a5ac3ce5a49b2797225da6595858584e04a350df572ecb45bdb4725552bea2024e25e40c29ff6eee164e79ca09a41d8e4a37c760cf070d04d25d661118a4057760e8d1620d6400cb205af010791b1c83623fe23c42d78b9099d9a5d7ae872e6d005c8f19988ba8745e2d99606becb6d96fde5db9bddd754fc9b8528bba7b9ef7bee5be72f38813711d67bb7b1e4af40ecca81fa373dddb07d73de222708fb8eee6ae039b0381a85c040249792764aa74ddb66dfdee5bb76dddb675dbb6795b77db45e9baaeeb8e6dddb6d91aab8542a15028140a85ba51a2f7752f141a755dd6dd9ce16ed475592664666bf1e48860532f3067d9f523d79bd04a45a2c3cb06773f32305f00085fc7ae0ab4ea4dbba0de9081423afd94556e7a49b47251ca7c1629379f45caaddc823948bde12ee23e02ed45a3afdcbc8d54462a236ee5de396efb681b157101a06da4f29591ca4720109577209094df20564504a63cfe2ba59c48a652c95a12e9a193481c47e2442828280f5d144bc6766ddb36cde3bc1c9cb0ddbd9b83d41b118db2fb516f303712e56a83bb7ba011596fbc9c0b00d59b7ac32d81de2c84c54d03f3755dd7754ddb408baf2b0aa95546489d528c61b37fd7b42ee52ae748de479b774d17914eb760a6391eb2824d28f9582412894cdeed2f33bd5c7a7cca51bceb3d7607f0461799aeee07d16d96590ba2502aae400d5cba45010b400497c03c04b68f78083cba57f2523eba7974d328e51e0824e5282010d23d21157bb715a780229023759b0ac769dab72ddb344df3469a48f469e0f75dbb9f1cc34a7b29a5fc107854038b6ad0a03163060b0b0ab5b2a2a2f27d2929a793c9542a91482828a391b59e2712751dc76d5b28a469598661d7552ba573769f9e920266195dac28ba4429bb0210f92bdec0ec43b4b010fa49138fa457a6121b5104cef142fa9212095fb0a150e99be9dbf70ff5949f54bec2dd3bf7d137ee923eba568574dbdd721cbde828a291e824d4c5715784e22e0247a7a41b81b95fdd0fa35b548772d1233622a33ad0078ac80823b03d7799c98950248bba0804827a070251b927a4310a8c1d7e1fa93c7ee5a4f299524e2793e9db4d9b356ddbe81eb78dee99b68cdbb611b759afb481a5d2b75b02b3c49be56e377b6dbbec66eca6795fb05dc8bbbce78542a15048147ae8dc48488b4e22bd7b776a45606e2c7a5604663908ce23b6cafba843b9646012091c224537e2504824a25e26a21d769769eef2a1687186dd5c8411387e52215d13f1c26e0ce52270c51a9c00ce7e15813330d72af10f1eb25f3fea2f4ac19ecd822dc8e6ecccad67233d94b2f2d34ddf5546f7b6d145b9bd5c773fbc8f28606fceb0dd4497fbe6237628baa3d17d742250f4f802acbcbb4c6f2ba36f20f5bc7f28f73ebab9083cfad5fd60ff6dbbdc37793d108890892920b1e8deb90b44c8c42290c6478feedbb98b1ebb1fdd36ba59b4ad1c05e47eac7c0381acbc03817cf72eba42e60a68bfc7ab98bc2fa5f47a0fcc279389e34aa51277ef9b57d2bc90570a7123ef9c4722bd921ebaa17ba79e97853ebb192f943d14643910c876eddd69e763e336ee02d936efe62c178151e75037b6aa3b77f3f551ecdcdd0faef326127117e5dbec7c8cbaf3e1719cb49d8fd0bbf5c0acc3eef21ba8598cddcc1581630d96691aac8c32ca08c242faeb2e8c4dd368671d98a57631cdfe10026bcf3afaefd3b04d7469ff10222504cef141520ff5ccc21323a739eddab99e6d72a10e8572ef28ef6f28f7f496259bcd52ca47a78f7e753fbca3fc30757783a813e8c30492da3ee56694a37c275d1cca7799b6defbf49485c0f657f7437f64519e8f2d0a8832dd0333ea07e928de47604699401fa41116028f6e517ebdd6ae0789bf7bf7bb05817c2781404ab7416ef6c02029fc81a5c7a33a5be256ba8ee338ce7a96b39e4ae8aa7862d84b6ced66af97c228f76e16027b23b06feaeed1a84d2c2c2696d2bd9bce628af7eef5d2cd4152d8be3bc9da4b7b0dccdcadbd9eec7ed8be281fddd9f9e8a380b1436b3b14bdc1548729ad67a6a4fc5469af045bec8de523628bbdd5d8626f372cc182261e53f954c05d022470730cf07064956009892915763ececf8328fa8a354cc138bb035b4ce5520dee77a4af998d8d9dde1cf50d9883a4c2b6f1802dd236a9173c44939e37a41e5b0705e7d6e91bc84eddb641c459a2c336d2e1e49955cc1d1d47a233854d919a31829e502374097a230f45877d90e248ca449316139f25f3b14340e4e9c00ead9a1a40da9aaafebc39fe103182a56ab272880b7533df552e2955ae7bef45cda8918244678a28db06f186d4fbad136f101dc15e6f726320abc8f04c323d2cd82983dc4035beb099b278f03525cfcc94a74fa15fa04c539f18ae182e902ee9b06300290be7b813bcd3f4c5696bc2cc29faa2926219314de30b9c49a24bb390508265c0f1084440c245bc6103f1060a48524edfa4953414ad67d28bfed0160c6c151389ad9b9936b3484d8fd141734e39e56396faec89e11dc34d31bc14c3514eab00dfafc10436d3560ba8d6b024a64d7e9cf4ea49d018bda2e0eca14d6828c1d21f90b63aac21092b3fc1c933773aaca2c39ed771354c5be8676c5ca6657879195d5c543870e4c09103878b4a9583ba7c86db387dcb9d4a5ea8c8b38787a9a4c327a7404059d22634d44987f4e79257e60cd7da84b6723c9c3d53c9646d2a49030d2f34bcbcfcfa0cf4c2412f0a87a43e98366116e9904e2c4462da8a2efde622baf4af0ba4970829e5710099cf300e97cb3b7f4d9006c32ec7010e99d8059c361df675dc0beba8a1d3719976f9a43402f3d771dcf8bcb37304e2751cd70d298f27963aee911abeb95c361cb101a43f53d5b8864b81a6aa2340437fa20b6d82437e3ec7556f79a62dd595e3f2a2ae392f7348d5ef9cf3870902c9f10c8732803e326c23c75517cc39401a0cdb78080e99d806d863a0c0023d91df1276be67f6f40a451f9bd09f5ea128485b11ff4839031bc3c1e7f9c3e2805853d57d290bf73d26f66a1c366ebc87c438be852a99ae94d52b1cefd325bdbaf13ef5e9958d778ef7fb49af540fdff8ba725cfaa3ba34bc14c7a54f2e0dba748c147851a9a9a4c39e2970f67498430636061004730bc67e6ffda54da8934b81e8930efb332e65b9748c5b576eb5a9371df6bf5b97e8b08613db38b74e0a485bd7963a9c3d26b004664b0251c0106d499f0e1be35a85bd31ec4604de74dd934b38774f7ec1b9812a6d112183bcac66afae8b5eb4ce473a1f6b7a55a469abc39e3d1386b6a2aa9f65b307f704b3a5ad52cd4baf763622b08d086cb381c7e6effbbeaf3f6e53d283babc99cf957bed66b26ba6e6acf6be341a305d1a895150b650c759e9a4d5e1920ea74f0d26b0f9c3614ccd0e39067e94411d4e15252795cb744aca6d66f6433dcb6347b382571e314551d447228902a56da8e4ab576b93982a5524020000004315002028140e874362b170340ff45cf60e14000e829e466e4e188ae324c76118669031c61802080000406040866ab801c0f5ca7f2e122ca5ad7fdfd32c7c813cd155c205f4177424226a9f2df5c4c303deaea5b21d67f4ab0614f86ac59d4b8f602307e455c59e16fc7a9f7a3a1e3ec1f19ce62dfbd434c900a800e21db66ba1c1869a2e655fc0001a0b4cff8a32c1ea02e562db2baa4d10fc5818e04f007fe75b62250b23a5757a733a119ca405c28b5ee7cb4b4539b771cb2f478343c55bda17ba29e320e8dacbfb1604d05b94cbb2b3237ab26cbed908b2d33922f3a74413144705750ef692a5536b06dc80a3f27159753bbd41751979ccadf7250fe12191914fde4b5195037248124afde92e654392d41f97e577c3f826646e24d216cad09b16175d9d61fe6d970574623fe28a06cac79db2c249696ad12e65d2c083e569fc16a38eb2004f7781bfdfa44236310678f400614a0b9c5e28ab5f0ed976f94edef951a222e07aa13999c1695fd191796204e6d7cddc057e71adf07caab029f10d59ee8f6715f4a67bb811af7d17cdef6cd6a12d3293ae43a3f1ff33962f4f6bbb6a7275bfcbf0349e3d42061a985f34b9264b90e96907ec20513091061618c89b334d2e829669278fb2175657ddaf8f9418201421104fefe25b55b1ea083fa899a7203528a2396c02e53851d8cad390375bda1b190c312a305e2e0d4c209531d6c3e0ba9c5def659ae755561c277a22a6ce711f369bbd50c03d677f5e4a681764146ed6e885ed922fe86512165b3766b548f1d65db01441ecae1d00094ef2702df2c11da873d8d45f45ef5d3d6ab6cb6997e71a1e57e367231cae28424f1dc02e28f29b9a4f46266657021c3fd64da34a98e2998e88974ccde34e5b83e62b4ffb2e3a79691769ab604c0cdb68526b4893adfb82e4eefbadac55c6569ffc5abdbbba5db475183abcdd685f3dfd4ee03706eacb52c170a943e3c1753373d620f7b28ec5707581edeb2e878205d6254e108d4dee2d3540b94bb73bb38a2bc5c6f7b5798447b20006647a7382b61006d0a59983ea17d8e2fe01e76f7be761945b8ea02871f8887467f179e27e18fac718d4bee627c4a2f2548e920c8421d63276ba4e0056175033daffb5d0df65ac3fd75e1797b79b1b643d6e20787a231ed99579e37dad4ef19ff157f5f1ac44918cb2666f0be911adbaeac7fb2ae82eda0e2e68bc133c19901a37f73851edf419f044f81af353f0cab54d4296c6d9f4a042c020103278c7cfd6d2b223aa4742339c2342f2f95f6bffe1cd91d52fd66e4371c897c520940f8c9bd37b9010c48a001d9f1045c0228c990143029dc05902a2532bd59241c28c598d3346c07085a6cc6471f0ecca01ee20d0407a395867c024731a969ca9c5e1c8c9e6d599912c942c09398f967881648a0fc70d91ac0b78a115f569b8ebcad3e021e336ddc7ca639b07403a07a0f4ba4e8d67e32d5ad818d543f878498b403d0d642ae3d8d30c7e04f54a7051418226aebc5ace063a52efae3e90f49e5fe6728c3368c6cf930046618e923a8b6e6b11f1367563e6a764f3bb748b7acf1b1620c229f442a01a65942eb783cde74a85c868980df634d087a2006aa3e7f31962f8d8f6d5aeec2a4184ea89f16327251042f80b63f7dbc690cff61c0bcfe528ab94a51d39420b3ce531a07e1034858e8126bc2563aa76f42b9a7577c26b454efcac195ce260d2013fd089ba349a83d64bcd2abaf398de7c57e5929ecdc9b868a66062e365e8183744de2394dbb9f4174f350f041535fb4b391386d5f382082257694a6025d01fd897a677c25ddbc0d0d2064e59ed8188a71ec34d32c68eb8a58c2c5b4fc5c17df13087382d846d2672c11dfbb1102e267313f2784b94ae00ccb14a859768fb3918e6f02bb775b1bdab47936d7aef604e2d001fcf4ca0b752bd98584374464ab6d74e221cd74e30930dcf9834d9426de174e88161be3b6c9cda57b077aa71a494aa7189986b44d35efb3f5a1e26b2ef1ba3a77db58f196b96ffc5caaaf6c62eb90638c446c898e48c9a15b74f70486035c1b4129407062092ce0f8328251280f38e801d0f5258fc7f87b366679db9a548d8db35a3b727756fceab3f2a46c2db78e4639f95a4487037be87905a48fb20ec8f6417c13de47720df8b603f92fd487720df07712fa2fdc8ec23b9877817c41d917646b213e91ef27b10ee45b61bc96ea4fb90ef81bc13d16e04f6113c61d1059dc20510945adf9d477ab8460a561824ce9e00bd6c24e217ec6a1ad130e0e7f585945bd061e099bb4c3b10037b05fbd39412ea8f1830afefa993891fc783a99c18c0e4e4eeae8bf8bb782cfc6a0436251934efa093d671157740625cca49fa165f126acc3d76300260f1a6037b87ecd0b4775d3f6e0d51ec6966f6aa9b9c91e2f9bb3d51712f6cf4189e8ad53631294985cfe0f0fb86278f3ad97bb75f15ca0843da4200d78b028cf35e7c020a834b8c1148b03c32824ac6769019989200506d307b1ecba1589b56caa3c1fe31831a31a2ccd5d19ecb0037f086b12185f6ca1d4dc46ce1ffcba7188634b36113bc3824a5c6444c7fd5b84230ff2e756a89389ec3d5e5360919528970f7f99433d2a6ad5c965061f4e08e27e2532ba25ec0b8d11f80f743f87a5a42e38d14aab48990980f0225ea9a256c1247ca192af38ccb201838546c096a9ca5c64b4530283fb35659782dfe05f9b8c513540479943c63689dbab4e8dbecf7b99eb74586d7ab79052b95d6f13a34259b110170714505e049beb37934a8d9a30af31c3166818c58a766a8555dbb384f8303b999f4fada60ffdb7e3ebf6bf862a2804cd070b15e64cef282b912020f5bb9fc8711ec627600012ee8006c34b04b0c96d730f0a2d4092d1aff07153004f9f8fbfe6e5fcabedf3c75117838ef51d0bdc70726760306b45c543e5ba909f04608915af24e16ad04a96d32b8894becb28ae4d93c3c36d22b470352a6587aee717409d6b7ad81a9a8f165541c043cc5f9bd0a7d7edc8aa6171964de998189253fed1cbcf358dada9dc77287a3d911f32d9b212657898df775c310882984cda136c391cd8865aeb59a9e0aaeab512811caf5699a7b4464ed569258d40131aa5f27a1dc29a7036848e27806b25e144b5b32acfe3a37e45e7a408e6d6ab9524610d226573543798b8aa0178913a054f1e00247f1d612b062f53c95ea9ff2dd09e44c6f700d75f3795f339f778a30e4028c34d36b852d991bde826c58de5c1e06955082841eaf02f74b58618da7e555ab6f67339681a5066c7b6db22917ffd934aa1d98c368eb8d9229ac52b85771314dccc04cbb4c8f1362336ae7e85eb1b09ceb656cc6acef46c02150ce25f7ac1c6096969168633f1a7865f7d46ca4d71e1752c75604878b82722b309dcf88f1ae59ef68c4cb4ee5ac47609ff34ccb3aef19bb28da30e38bb73d7f94b90ff3fc5d278d806ec8a2e8e947d9726a667ba52e611dd957aef47eb606d643f612778057c7ab5f82b29199ae0add0f301d32244c63128bdf39db7572aaf47cfa5ec1b963c028abd9a0f4d6282cc176cc21bf5adc243de7234ae2c27cc26add9e41b8e4872b6d2b80547bfea4af3bed414acf3bb079092d1dcb3c9cc540eb59d1ce649b3a2b0b8f0f0b76d65826ddbbc78e8ad88036b72910da362b1fa10b4588bcb0c01009270f8ae89c7f8789cebcc9a6d70d3dd90dc8fa5c416afcd469346f38e7f22f9e88bf92dac787b74347b6d16bfa1f4decca869f94cdcb1ee8646e414ec1768eb25ac69881e564b7c35dd8048cc711ecfa887d432a0c561f0bec9acd93aa2d32d48f45a05bb44b08c34507a7469ecd93d5dc1100c27dda389e768d4535ed904ec6349ad669478cddbcb3629bfe2f55735e7c8e7755de67c56aeb74ac76aa38b0971f6d903b76870c29d1aeb0ae4176979c5ccb1b1543bac86e5508f91df47c3ed8d8481d6ed473b32f0db2fed71cdfe2995c534925191676e2c9bd7ca242efd44bc75dbb557f09e69140d7eed60e7573d95de11131367c6a998ff163b2633eb4c2a47f12bf9b830a2833ea15f89a6296335b0a491afe9a508a45e9b12668ef69771ed24ed2e2d54f97ae473a213fc7ccec257bfb690c4c996c0d1f1040ed42bf323e0380666bb9e3fc27705fcddd313f6f87f344e30f5a2a4580e8552ecbb8a0d99c6e384f2e52977ddd1d34d27446906631d6967f85195a9635a54ddbd4e17514b5a77cdad350579eb44a14a72c11239b76beb06478728b627de0be93a35f5e5c99bfdee672dafcce3732a13e83eea043a779d2ae47a08dd269f01092df749ea8eecfa0dd64929c0ec7987a17b21f8d8015de90f6b40f82f43a05f8f752a36387cf92216070721494ee4894151aae2ed009a420793b88a25fc712e13cbbc9e1a7b26e87c09a31d7a5670bbda4b66def5fbc4075feace7c0968837d0ceaf37a522e9ee5b7c52008a1d49722b54d06faad06d630985f20f713816fee03f98662d3c10473419cc94ade3df299757448cc1d59a623bb08436edffe53cfab331d5c366efbcd081bcb05e0ea3d38c06917f497ab26e6a78b422a49afe68f947188b6404b3929223102cc976618a6a299925194155af0f5d19b9b066e3ebaa3d55b9e48cb85c38210f56c5c363f3a4a47b98bdb4203c3e9c30bd79c4cf8048ff67ee2eca53142c5f391e4c8244af47eb1984c856b9c58be34ba2229a8461a469f377d0a44dcd6dbc56afa6a98989ee66a34040dd73bc857871ec82f34f57266c3a23524b7781fe9f245afe4ddcba4ecd5dd9d4fb7aee84e08f12035868d6af743267f2a5f948599dd0e52c604a53cbc59d109789fcc369f35c8b22b53b3beab3a9c31bbbee082183434120f9d8ad44b1e440ba5597a5a8e73400e6e0e238ffe7bb1407aa08cfa4d8492ab4d76ba91c8967b6f73abb91b3fc7dcc0ef354eda792e5893ded667f8b6411ba8ef968757ba215ff01aa2a1e78e7b123a9753b631ed1fc135425ee4ffffc4992a17385f2023b167e8146910c8b6c7ffdc46e99e99316691bc40e041627f87e05a491c1b629a273bad5fe75a4c7a91415735a3035ab2c316eae2e2f03fe4c496936ed25d3aa188511b9e23a41c8c1ac81a3dc8c001e6aae57cbfcb36375f152e5df74e933f31a8ff86194e8d0649e78acc210c5962c6fa3c379f717ec4550901763a19322e6dbc6d58d8b37d8b7cf7a5d13f7fe16672041e8afaa72f376e9ccdce277f11551b9dfaabfb1b8381f36768e6eb2eb7c20dac143edbee44869c7488f1daab0fea9839a5ee5c265190a9c46f24139f7c246864633cafefc963d98873df41326febdc1037756ad83c5c56f57f494d0990c4db2ec535d401dc78106c468ad4232377138296359b7d5490b7a79049c0468acec984aa6c3d440422cc32e79a8068c631cb462d57901c6495e8e5923790541afc225b1774ec230b5dc533ae7667a9fd5eb02916f0ec978af4f9e861c01b4a8e2a147ceeb04f01ff638f9adcd8db789911afa08e0045081e9e15be708f90548c4a992d8ada3489db3c72ba51435ee2059faaa17f56e360451d499a0bd8ea448e90827b097813cd25f511f78936307cd46e85d44dbacb531e9302e6e12eb7b39428c394435501a37821e506a3e6ec3254a2414c8634a6a2df646238df0bd1ef4b2d2fbdc0e0c1dbb99a0294c2648971db68bbff1d0c63a7a3c2a13421cb1a910fd94cac37a0de4c1751678343f0368c026308c70fc953001ce1e39fcc95ddc34b2dba12d41713ace144289d3c73d821b86670766b93d71346ccfa49f1b35b9bb5a11adadac7413a693b69814c38c12b0948ade791056fabe7e3ab92e68ff4762bdffee4def4bde5ca3c7362b5958c18809eac2d90330ac27e02b5d19b62f2e551cae8d1fa06848d22dcead61773ed3b1eaac22c1baad088938dc12f83bb5390f2a88eddcecb63369e71f86a2a76846ab0ee328a6301db96d2bd716070c20fff56ded9f33911fd66c62ab07dbcd9a0654e6152fe621d97069dd05220320488871cff804ba8fc967f3f9d6608f4ffffdc17a7832b7563618206e11391972afadfad35b7d078461ddd454acd3e9f0b1e2b24b4ab53d98894fdb0911619140f5dc5d7f6a2b68b2d03a6e19dbf843e7d1eccacece6273008c3b00a32a3ef4308a1019a3965e6495ffa5622105e27ce519b8bb8c1d8ae244b5de23dd614ab00972e97416124342e8953ca447d0056844f87b36718265c93ecf85382cd835a67a5c876b2a1435b243e02bbe00e56c03cf065df8b7c08cdd518383125da3c1f78a978c55530e03636c6db4cf79cc067d8f5b21727afc2c14049fbedfbe4242ef64e282495377b874201f057ab0f46c96077c13e0c3b0e9b28943d8daa7fa37bb8fdae924edc5d3b30e12ba6ee970ad417a3a42280095fc865f4ae1f320f39e2050205b2a2c3e03fc50992557ebac488ef62912fe0925e2c86c6a6c3be7c189d2965d4d214069714942560e0df376f2b13b843f4a2fc61ca60802b0fe2cd2044a7ed05672d693a7141c1b38e74f5f33be0fc817760023ce2d0bc0dfff4fe8b729cf8688f2804a6c35e2aa89191b6e01151f031141f8e2364ef515b06d5699ad93ba5f288907c10b33fee0594b1e4d4684692d1b267260eeddd2e3dec7270540a3c459f2179368d2966d8a7426bea6bf5110d97b688ad4034ce99c982bd48eec33ddced5a8a1a3d14ba0316e272d60ef324f5c180aab0aef40c0ece295d6eed4e5f7db0843faaba6eabdbe0e2a5335374cc6391faf86ff86ba52194d3d63021f44fa88283492216b54ca8a6741d2cf24e17e1988b3220d13a2364af08d329b79071e50c178255e1b3241d8427956842e098ae47155a44765438ce653d35c3bb5dfa4978245554c2ebba913d6342038807757cceabf437970662bfd8a440ff7c52e4f4dc795014d30ff8e808a6f2bdbe6846b3b8ed6fcadeb8dc3cdf17092866de1a7686bc254a8f20b0f2bea877382dbeffb3ad895cdc3876bd85839f2dc3a4d629d8c6cce0fa3b153417167a9a1061272d6d3dd9e41be90bf05f9602ee89ac1f5c9d9021ce990431e38d0961673d9afa45dbcd2e189026ed3a82494e76ad6e2c6de1a6624b07bfb20138a4e5501e72ef8c501f819709d193250edd13b8bc2b0277b04c037e8d9bfefe8f24e549f6d194131d8931decb1123d9df2885b768fe041148b3ab640da86d855784c091b97eb09b098c36e08481f10b131ffb877bbd9d311dd3324352b47b24142e7d89863e5f2af87ee24e9f0fed019cb295ebed8c5f6abe437c675b22261a7b661131e1ed51d9b46f80ce6cfb42263bff4c3359c56842bc4b6d1806ccf744c0df6e2c56e93642f76841e4d473f8be23381a60a0942077d8b8d69723ce2307c54d170a7f853a60b9ff49d48c52491083cf65c5a8acd3820281bdda73ab895381bb347b0299eab7936b4217e272f059c0b6e67ee0e1d537ebe5057436a40298599f8f1ebd4113b9a44532c3d9c6de6a4bacdeb67cf0ddc825299f5da0ec73e560b401a8e6cc68aa85bfa067ea5978884495f72af03fe5c2d11347361e0bfb67ff3ca455f0de8fee99fa8ec664363b7f09ec17c237e5dcaa736a6fadfee8a5f18bb95cb00e5bfb6849fddbc324427bd5826c34c7aeef3ce6f00789ca123f87904abdbd456ef7e3731e1df7a59eb43be5af621ec25ae21a98414149e7cb2377e3d345965d59ebe9c34f80caa5d0aa8c64c274b51954ae11b3424623cc7e9e280493866bf5cf2aa6680f77b0e474b82b0e862062098335f0fe9dba13a938e909536c0e27c3d2d82cf7b560d6ea51e84fccc2b105906170a1799280ca198d146c480a5f2925c14943217846a520026128037920004b87154e2c9a9360188c1da478c4f68c7e9400a3b7f5892110b80800a22eba8cf5cc99b13f9516a5613004a9d00e07e02a0c869fc022431a995479676cc2e4bba01953e3a704c48b9f23cf92115a1c4239c920e451478de01719373bc30f5f196ca0007daeed3abb989274e16af293c6e5853cc753d44e3d61a001f8962e931a2b5d7c524ca743c5a38a8de622c73205babd838320205363d5f2b374cbd7a9a55899f45d52ff2264f385b45af2d8edbfef79e78b1b4c94aaa5126298118c600093af69c5b7eaff678ce1b8a7bc94a0c7be2073246e5693bfe9c404891114f6eda4ca8216c291a8c150b7de2e212beb9923c3962cf2c27d9513aeb7065934a88e45a4beb94baac1da449eabd11c6a13229c1a9f52f7b077e4a88fd627e0d9301fffdb087afc9346a19d5bc2419f0fc33fefeaf0ef072906c714d18bcbc81eef184227a8be9858b2f81d1f4f27dadf2f722017d08c0154f577312f129600eb9383027962d3e991088b996f92884e6fd2ffa9c058192ef244e7c7da34f42eb23cc769a87ae9e4e6275e5bdc4b259fef3d6c456e79b0faa26a54e4e8dca1c5e794932bf61aa408b1e08e81ed77310eb9a1f5144a4d62a588ce35506d034ea591b99b651cfa59ad34b52950c8f81bbd02e8c34258787f2d19662e2744d1cc38f50c4aca72deeb75f4dce28c2d94aac551a1333e637ac1773cb02cad20ba2202e5c1610874bc0850f5d79e0544c00440be5786b8473ebfa88ffbfb9a8ff4cbdef76989f509069131725649582e31bda0970cf962f4c956cf42b6c8ffbb2b4831e1040a3555ce15dc7cb648dc9d67c63085b50c3f59e9f978b5be0caaab0dd9663d10d5e157aa76a64ef2a2f6a3c7b5f0dccfa260fd9325bd10644c46e2bcc1c401b2cd3f7597ea0ca22f3d7e097de9fa282912e45891e57e946fe53176dbb0a9841eb5805a9a7c018970997bbdd93312b5314a32b1e7a4d459196ca2a98b3ccd88768e6ca92ea000b8c68d2b84761aaa57c0dbf24beed3a5451622849486520487438caa2db9c1cbf8a93487a7926ff9dc6899b993c935392716e6859ae41e98bf82703fde80fb14c9c8c2ddcbc637b88a19dce185b4bf09e3fa0a01139dcc4a88a0b2f9144d245627445a99492317bf05390e3a7cbf69663dec151b224a44fd5d9395ed114b9ef0697d07a31e17c1cd3777f49b5102bc1b2c5a8b7b57174c51dfc7749a4c2ab945e424bd257f5e094920cf8a72ee86497678db2c3bca32b23e1ab46e19848bff8455ff422cbceb03b7ebc8844d816415dd6655adc71aaefa1c2dd3b0ecb9f411e33936cced3c3f3a7fad0df6fa2f1340f882f029d668231a47154fcf5bc70b31385170c46a7e51720fff3909fb25a754a24e59d10e91804d33070b1daa33bdff39516ea6470acc07ceb7f9ea543b4fd33cd6652eb9ad67349a6e826d0c022de12122b926a3a64b61866b21bd2a04187b3a4a990b3bf9e624005ccb9d1872f614d608b8f0608782ff3bbeb82f1c1be5e28d432a5f38a437edeaf00e5eede4a6a967c22e2e6055d28ce8ac364b45000fe8e34a691777346b51d2b9e42b14c4be9e993a9e414b6681c28291d8be17ab110adf73c94310b67d2672ac02a252ed7540efaa470ec3935da539aabf2d8ada35083aa4932fa1a09174ad2363c3ca405acfc0991f9eac616e3bce00a3efb080ae5be0aba6191ccd7a432730f866fa4a6835cdb4527df4d20b58f149a1c58c814b0093d06104c730ee40b5cd73e404ff1e0156e6f6d76c67bea60dd3416686de30ae5424cfccd5648fc32f567030d4678489786f29a9c3d0b893a96459eca386db3a98898662aad51b07fc215ee0a4d775aca5d0304eb54afaf35235b0d2d67619e620abfff0951337c6daaa07abae0fc6248096441a41f03499426993901592e23b77c25d9dc53d6c329dc20c9f16e5ad07998f994145f41d0581d8044040a6d8cecd85b5799e47a81329dc424633f8bb822ee7e4d8d8885ef35d924e04b8dcfe2e6248717fbf15141cae6fffaa8438cf809bf1d7c15780407ea5339ccdcaa403999ff24fdff6fb01a90f194eeb0fc579ff99315be34d22c05aa09a087ea6763faa391821861558d5066eb597f09e4aacc7e50f0c869441c70d657ff5f5c8abb64d6f64303ea03f0366136243e490dff65dba954deb4dda4f08a015e340ce19839f654d8131db635204994bf698b80f122255a9872da2bf42ffc97e5f7c73d4315c8258db1d11913230135071470abc5daf574af83108f9319abbec6e23e9571d95895e3ab9effc694ef93c735d36d2ef265dede958bf9fefa079e7022d451f3635a6b1bab3c64d11c64d13d6f5cdb963187092f1694c785638540afe51f35b35e27246bedd008f838c0013c865ec548e5bdccc3dedf1a7c8945105d727349ee01cbb5accfc3a018047823a0d316705a29e07909785932133b0cf18c55ac9077bc6b0d6938f6bbd88b0e83aba3794b88fab30f529e5c32c619e62487985a34c81a061179bfe46e79794c5bb2ad882b2582ad55ff8cf71a2e9da75263dcc9ec38c7fd2564754101836ab17af96863dbfd355b7222648e393cb4cc321b6c67ceeb601f53b3ae332bd4fa693a8655e5147e0c1bdaded47b42e02de0514231e909769811b1dcc16bf6a421a2bd4b96ca09aa69b69aec69e83505ef2b26067badef57fd0c96998a4fb8dedefedabbc5b5e6ae7ad58247c381e215a576ddbe15f57f942142093da6a45fcd4d2dbca7848d87e23514ff631f4607d1071adda19b7a078b518508e477558b1a41d8d2288257989b45bdff86f20aff9dcf60f4389ee7c50717015237bd5cfa53fb20db4c7e6dc7c15550a6bdb0f375ac5d12fa37c200a6dc5acd8308a362f8ee90d3f49b39032fa565c07866920eeb37a2e305810d4f8ecb8eb5d9f88a79e7c6bbe04eba3ed526e6fad91aad062e5f98c20eaede60b148cc4eb8319cb1d743ec98f1f142eec9d878c21436b71cad05c65a0ea8b0af47a4109af7e37846ae6cfbb8ee1854279f5de3c9a64e7982995c4b2d524cf98cd367c9feca71d7f164778f20849daa1a263c1317e2a40ab9b9f233eeb68ef7624fb275e127454b19fde6d9236842cf1248b7a7df26c21145a05e9a8554f2099510c18f028d29dc3f72d71a6f94b741085fbc2662cad3a8278c179c050d70c7a3ba8b02884e4c8c0a7cdf43be2d62df57aff75bee538a1669bc31fc8fbbdde691e973ffbe0f1c10e53ac77842bc50021678b1b5f6ad8839ef2cfecb16a475388283c30e5accd3634bf4b6be5e4dd42f46ba9b4b20372a810dd193f0e23953a4f988341b74193fd1996d20583bfdfd024f89dca7d83264518437bfc063dafd9eb73b052f9bd7d0de65b82c9eed302be5698bd4137eabe6c425d961364d8195446d09f2093139c0c73cce8bb77639142de05ca66eb8344fca84e3580c4318988312433de913e5c90866d16fade4106b294c51a83210223ad112382f0bc4b6086b94d5df8f91184a74cd374fe2ba7340d46aa2a03de55d8402ba515a8ffaf9a71e04fa27ae5b7c81eb0c9c7d57fcbc6776b599d1d5777e1623774cee2cf5e7c492653396cce178809decbc3f5e65a0ddd295d700ba2ced0e3b31dcde6e9d49b680b1e9b4dc08d6ade8e4b682437527b7323b1e41a74c761cfe735a61ffba5f0df2b96e54fffb72cb37555153eed474bc2a80b351193051206d8d7fe489978b41f26e7478c6af8b72cce64eefdbbb10b68c1c9669d4ba475d65bda332ea04ffcd3b177ad38c5f5f9d14ad920957d977323587aabdc3aaec13391113e5c9068bfda7c44c450e8bc5edf765b1dccedac352fed1eef7864036bdfea94562cc7a4b48e83350989e0b3f152f033cacf3a5c1d6809c32cc252502b71bd980eb22d9e9f0d5c473d8e9fce10548191e007d54b0b3897a8cc806f51cb59c0d753df3d5ca7def704ad1104ec317e28c55a9ad80055ddd85e59ebe483e06e46e81b3ab2ed68ca1793140e8e9124d79d312b5d890d1df777d8e6b1b91899238a36fc964e3b501ce83b92ac4074d46d957f5d03ad24efb1022815078796d1199f10d5f866431fcd5e58de04632e9223ab54b9b4ce74d7f500d3fabe1660d8abb2b15bfb2bb52df5456941b2762f00b92a9ef8b72e4f83ac78d08c23da01f0111102fa050a743305999dbc76cd0f6b6c3c23cafa735139d6010f3616907920c13961eb038eb673e9284ca4a2bdb8b321b2967caaaafe9b06a1e68a2712298f2dfad3485b62ba5ca69ca792deba5e5aafc0344885586def460d9cc37a101af17fd9a7d0f1f70564a6c367bcfbd147217bf07ff4ade2c77c86c20c38a0ac17a5316669e85821eeaf9971355ed9d587ba7744d2edc8a72f46e4db2de00f2c81570c18640fdc55ae781fc2a7cd9322a795bb0cf51a5f0a7ac4e32f8d3983bb999ba1aa2ad851bc479aafea1b1930c61aab91065400e764be10af6e1a319cd389546ebe246afc03223bbfcc801acc0d3ca77eb1bc00ed74c4fd4a26d2f318cf6c312812bea6067b03200266d9e7fce29c1eb18c5f2bc64fb88de1bdee5a80d1d9e60e34bf0631dceb2ee651c55ee76057ab84715c2e780253d92186584d5190208c8a5003e3a07d749823c1a146561d57f27a1abfe2fb856d9be4efcc8b381d71e93220da9bcfce4edd8e4cd4655528e23987aa292070f65d241d8e80515ef582278df5c9c1a8580eb16330a22fac05bef41932172eafa627d8e8274fecad84b8560bf1939c87cd0bf3fd4fab817ca4bfa6e665d2ffab22d7147d826fb4927a492659f99a34e27cd8113c043d6d7719c34031b23ca43cb7681b2a26a8495289a59dd0d3e5063aad840e696ce42cafacd2810f50127f0f6de701bf265c50ae6601e436719e692ea102824c1c08fcb32731b88abce96d91c337bc0950075c7012050edf529e66cbb0d1c3a88eaaecf1b4cdddfd8667086f60041217465959b4a4598992d270755c83064ca40032ed73b52f0661a6d6f4b24affbbc16e08166f6e86e955d0190ee74daff8239785e33daa1d32bafdeaeb039f1a64ed4aa82c9debea0118ee9045b38599f69ac185e684fa97deea143f968d83dd5fd36bd153df507cfbe3b0b58739ff8f5b89bcf381ca18cd0aa86f2818ca3643ccf06dc15d0a84ffc41844b628e661258190a350046eb3ed79d4536c091946a8d87593a41a208a4a1bc9cab35156a2e5ff745960291b831847b005450d1dfe67dea4f3e92a748946f747a2d30270a01224b6a28c42d7afa4d84421092b2e99060077313615fd99f4b50953c07d81ce36af5a91320959c48407477834739fe44ef9d46ecc0b94cca53ef7a7ef9c532b9cf3f79ebd2d2f388bd85a1dc1d18848e91fd20ae443ef546f3666d4c8f5c63d64013e738fa8f44031f83ee11201b02cd27c69431a4b237061a1f69ea454a636810d4f668101deea7ba499623ff4a6fdd820757ff625c5a228eb432f234bda5d3a069171b0cff0774418edcd5eae4771fc7fb0003fe88e239cad8d67bb6e4f4097d2348a0519bd1ca39eaf5ef10e0a6fa98034ef1b5defc8260e3b1d4286f7572ff5464a90759aff408aac47ecee8437168b62ab4d6c17ebdfb534b373196209467f237348fe4075e73c52484372a7bb16f7ac83d9c535f196c5a01c1dc0f74d564e0f28cfcc0c12a665ccd13c4f0af2e1f40ce56d4c921c87f9041a6a0ddf12486fbdeec3f21e280bab3b9f8ae1e1920e7896485194954606456767d9d008a0db0931546b4bb54b9ff4854bebc91b860111eb029e9c93cde37036d359624a07ffd08133f0d4eabf9c6ccf31d04f9e833f945e90d1d198dd94000629af42deaf0117fa9e5efc85f423b3417ed6f30a5934f6ecf6070d35738378fa9d37d69596557f50709c48ab4ef3d4a9436160935ed1aab49fe27a941df138475f647385a1e76461e2c6a3cd40cbd40d7872c0a186c6a68d53b3da6f5cb1d66537f42e3a4a8701e8b10328b5fb1ed790115268778b7d1be1bb29628f8df22215b89ffbdcb5c1da913ea32279ba172c0dad8092a2147da9ab94d8c51036c5c89cc377c77c5da8f5d0a663504ce5327aa667b4b6ede5d997665ce8f203628b88dcd7ce54a3c6b5ad2771db818feff948044bd9d4166ec446b6d3ace318c13bdb4296eb1ee78a120b56f3412237b987dd3c37b8b906079c7088f2f8421808987c8e425a0c40096f1269724c7ad911b75a2b6f21f7e8192ec76764e975b9a90798f8efb7aa24a2d2cf6e8b389161609866c159d0cbf7769ec6e95570bf493522d2146e4f21b158ba70131a00dd2b64c54ba71f1dc939f00ea1ac28bf3bcba9f0617eea732fc1d4e5d7b2e1f18735270d2730a7bbaa4679ab82afb737e02853ff3a1e07315d088b2da40fb10bffde9d175ff39e429ac33811c702f86a2b17369a0e0646e6d027ca6b10b15dd3a38a0529e17c5f7aa503d342bc39ae860963cc53381c9df1b1b5d4245c1c3b2175141259e4c26c9713745c5ddb7e0adfadc197e1560acb848d60ffd1ea693aa1719a7d53ccf31ae811592777fe48e2fa0581d2cab480cc9015d56b7dd6d7202827558c00a3e472b5f25b75f7b9f473a8b3a549a75cbecbaa6a38cc8a10dbbdb841877de78c898fcbaa3b4dbb959e947184c9d4078bada53aa6e7ad283bf584d276c3bf5866c9e16375d0965035e5deb833208f98a086e0f6e57e2ae300eefb12b1c8aba1aa62271eab3b758e1f1e0fb61f8f354da8be277493cccd0e400acc68dbe2e59f09f308bcbf42dc5d1a9f381e96fa5ae67618c2111a0141f3224b25b33d93ee7f6d03abeef9582f70c274742e8870e6b3230a754356965facebb2716f4438096246bf100246e125ea950b823286bd76a5109ad6e70fbf774e7666f2e570318b3bc3ce662baa2dff33eefa833bff4f267e334a794b0ce7e8b032d9945dca8f822105c6cffeabfe472e3a94b44f8569af925bf9ec202b043e9d0a1cae6103d4a364524bcf38d167133abfbf5205514fb79c63efa1a87f36bbf8f51f94fad2d9f53a92c578d02fc9ffbdcf628df0d0361766886b042f5d92e63dc50c697b394bc2e269499ee64e540e2cccf059a2996d8509c73b3f072429eb1292e41320422db6e06e72b780e0dd7953bf5f4bbc3e9e18ca9e17e14fae000dd3fe1cacf030c2465e8101af4418be70daf26ea224f36bdf5a5251774445f1d25a32fd29f3b8caebeda8a50a2e1fad91ba6e908b777acf45a222b27165875753447485f2636c7129ae5090ee6547fbe362ec2f044e6ff2d93e5e92669dd46ba2b3c81cab9e696f4fd4e934b75707cac5d899a69e615c6c4c3485862ab9e1288950fb172513e34a3cb9e8428b0d985ec4b58a5be6e18a6c41d660ffa4385e2a0fccf8a2752fec5addca34e0374fb951c7d2380926b48535888ad21640ac8a33ac3d972a615c80c0f98f82244baf8f93d09ae0289302d5fb0a54c1ba60838083745250bc3efb98b5e4254b0fc417892a56d6b4fb2e99a2ce03d321edd59238cd2fb806bd84f6ad32de9a69925cfa01f483d4bdeb071134c236b8cd58c2bbf3e33653ac1ac78645de9ea29d6757063b578dd65d56cc191d20a82af95465fc100600a7ed3ef02008196d04f2e73abf9f4a0f2abf83cf6b14a3ae100feb683cbbd81e4f803eb3f5e5709a22002f1322cfc786c2e97a97d1b2be82fdf584e9bb2ca4a3c4d30c6dfbf2fbdaf1a06573b44aaf5961068fd22e556bbd933818cc6f7a478da9774450858923d6393bf250f06fa3745de5a8c2700b2b522acf97b8a4af734fe903de9d4032ae25e55a4082b7801506d1b9ba4e73cbaa91ad7b862587e61bc52afbda8e4d91795094fdf1541e45522e7fd2c4d6ff5884f75fbe31c60240a7c7f1aad09bcb32790f0441d266d4c58d8506bfd82b70460d3b4280b787fc6f9d9b5c3f12abfe358aa780d53c61a458a161863a2a9368144b70ba4f638d22729e8e71033e9ef9c10a195b0a0dcb2a5167fbccc1a53806c2bcd5f9965d02db164b51a7b1364c06508ecb3f4762d53505313bef74b506ed7233f97e3ddd70710e035f32a176c99f1312fbdc92d38eb59fa0e203aae94c55ab81ad94efcae87fc658e92b8d4c8a99fc72c30e1f66c0f78be5621285d85aa3ad8d282b2082c6057b334a799c92db44214cd03074c2943c3f0d59adc462c1b35ea34ff19e9840b8fd36ea47cc21da8ce3da075c802fe9aafb1273ca3f87aeebd4d411973584e26b177ff4aab46e7302629cfc60853a98c98e7cdcbfc15e68f481b0da2a4af40ccd81ec782906c5921929d8d1e2946d3da9205bc6be13786ed729d99c21e002b44b1b766fbc11ea92e9a2970a6754d01a1e392c7e899f6aab2d87c869161f29795bd175ef40e33cc838697bf94bf38aeb7f8c479ff5fd9662602d57820801427986e85ce886cea126d039a8102f40ef692842e51ceee04ff9278d3b027791358000391ef27dc92c87c5aab98febfd52a46895ac525065471947cd80306d29a8ea9687ffdcf6ddc6747376fc04f9fdc5562af83ba28c5e37e76d316b940e7dc6f68c0b61eac852f05fbae74b3c4885fb613aa01bf17ebac5d0c3ed832d322fc9cd0643cfc1ae1fbabd73b57180804c18b1d0078ac4eb3af47b88ebb7735b480d3732c03ed25194b8b56f8d60647628a975e2ebbcbea26105ae82b9f619230b9c31574a22b197fb42900112b6763f5c7df0e3e48c13638ba6e8cc209c8431c0b18863ffb0d05020680539780cfc8583f439474cfb0358fbec74403e73a7311139a62d1932eb46c388de46e5347c9db32bdde6a612b630942695b5434847a977e6ced2adffdd63815baa94862417c50998f6f4699f069088dfa8ea9b656352860c5bbc1517e5f2f0cc0759fdd2e65150a0baca73637863884903ad646a3186f28e14603c9d995e310a903ad6df7336cbb24f80d749ce52a310a732e0167d6640a4ca8b887db74510b4ebf5c8d236453985bc2c10dc84fcd87b6179a6381e2d24ee6e5d8d4f9e26e38297572bd210c8e76d0eb898043319f138b5a23076e50ecfa3f4925bef065e14164b68938be41b1b5cc124aae2bac9f3e9b24672ec25d2e24a7a1bb8ec0ea3bd2a0aba3a8c0ae24b364630ed3996dc9283766b49ca3853d811a5a4f682c11d1b02b8c468c1f4dd0268df91d3eab6027582570072473edbf08440784cca91f9c4c2cdab0a613bd41ddbeecc9a89d695f2f72864a7bcf6de7bd4c6d703864e74f228f90fb4da1a64f99026c4319887d9d8637217442c4346c80c01180044afd149ddaa1bbf2d5e8df08c1beb65386d0f6a4edcc095813c3e9eb2e1f00a731facf779290e44422e6d914a7b9cfb25683ee4dda9667f439cb3045c6a4918917f10986dab227c88647f9a7ec43453903fcac66255f77d6dfcd9a6731278a1c0b63181ea4ab42f0407843740820c9d543738b05e716b0c1843262a8b882df7fef750c6740f05ea6eea0222cda8317af14fef6400851d33d8ddc9c65f251745493d1367c84955c365f220ffd9f6420b9aa231a83e0ccf3f8e084fc55cde59e674a90e9a27362553842574660faf88ec8fe2e14b1ee314a6c280612c63030ef2d98017aec587c0e97ff5777bf3f28c476a33078e47565461b979b6c8c41512ae105480551f6759afade88a5d0f5b40d70aac06d1cb73bb0b1c305938f17664026c1c8ef0ab5d89c4715fbed9a067511cc22bd9f06df429be98e1afb3816bdc8f7eed540ad55987933164e3ec32bc088488d1df785217d1fe9bacbc50511103a1a2b6a78539f0e93050b03e2ae965b9a4fd6293f45ec34789cf826a90576e154ce288cf53c389729f190b3e4b94809c22baffe9e1a9f9745923fb72afaaa14e9769239cba587c4547152875d6f8f60e5cc80c9ceaf6cd28357b588209be16248240b83bab2f823cf882e264063e8632ba739d889f6bdfac1825a4283b5725e8a17d44e0e91ac6035ab411e09ca48897ca70b9f803d33bf160de668dc848c92944c4de6e0d85f45d1933b2bf24e8db821d2efc2556330b9675775f64c86afc9fea81366a74eb387245d96ee6b17ed210dd4b98bd9c17261fe4c3c1ea0920828a3bd12607024543ddf36289946d88b904396f9b49800f8d3f04dc7e7aa8a47873057c3df0561121dd954345089d433130226f6d629f1d7198e81f909adb944325f415fb403ed45812bab9760ddc4c157fe507bd1fdbcafc40813b41a6ebd08b1ba8ff2db9ddfbe055148aa7b0ba67cb6b8ae7af70a3da712a545a28aec420efd19a7cd83722e25dfad82c4038c72b411d5102633290f9cb82bdcf526f20ac28815a832deaf76d029b2da982236efd3c672abcb85c234c0e1d571a1200d7048755d525c033854dd9055a03d5bb8af2a021cf3ab33428df0abb5d497515cac46e1820685a3ad1bff2109eb1e2be81b37cbd47c5d4925c7228a376ea186c2aba4451990dc53264cddd6c447d8a1306e3da3d5c12a08baf5ddfb444ab16aed55a82f76c61a7e0dae44f782d0cd5d972ee7963d31cd69e1f771761d768f4b26cea35db3da2504b10979ddea1e3160ee8b391fe7abb07b5cf2713cf762621d16f93fc82c617eb9cee23df788d1ba5d5c6002d030afe447210fbdcb404c0de3845b8b23f5a94183cfedce3b3467284df4b580c597f4838ee6450fffe804407aa7a0f066dd9fb85c39704bf24c058ec445a97a340d88c4b077b5fa9eaa3c3c297b0b5989a4842e1640282aca569c3abc77ee92af3e2ee84ff1ba59cb31fbbd7727df83786dbb9095dda16d2ff18716d65aa352d709571ce2cdec12008488ba658bce60772fd926615c91ef9b86a1e18372a544ee540e3a308a0ad00c8fa89d9b75bde5b528a3e824cce996cb8bb9945fee6008a37db25726401f75360baf10f2fcc1c6eccdd8e571202ba9049790b6d5b216e868db192c5385fd7e3faf92dbdbb90ed390d1084660d1cbb6a4c957a5507219a59a9790d8387ef07330c5a21ddf8f2824320f72c8a8ea2ffb9b5f86aa38121a57cfa7dafc0eabcb27981f31416131dae218fb70382d7c5fbf2c6631abdf11ad0cca4f6bf64269c1b172a4240de389636c4d1f47e7c34b04ac445b174a485c38d9476ea1fbcc835676198a8ee11b0438e3f7731d42e13782a02e2214d061911f48178ac53cbfec55b86c6bc78ed170a2664037b109523f25812fdb0df09bccb8ea4631a77b2fdc37817da0242804fa8725758eafff248e9139b86026e1ba6dd37e9335139bce7c9c2c7daa35f15d6bc7b7844fa84436c3d6c1cd0b6960ab2898350f74924d63bc842e040f9589251b4ea0057419198e44c5428556029294e5f2ce468dedbb0724815cd4525f4baa4b6650e9bf06f3fb6168ad1411575f1d40d0218caee8a52e11794c58f75dc7f55a72193b7981baf5eed56f3120aaecc5dbf1a0d6c408a186b61d7769c0d269d2225d6d9d18a4a0d21566a4180c66d798acaeee93e7ac937cac3cc876e7325ccdfa7119c2c8e93317734992d7f2bf70ac4d4994f3c601572e61e5c6b49fa17c0c08b646d887daf83d19b485eee50a757baa338aedb805f1c0cebbc1e87ae9c1a86cbdc4a693ce36349933923436f556ac32fc03e03c7d6c10689d3e15a7fe2c7fe82556d963e295daf2f95f1f6ab43dab1b15a945c4d01a21fea7a67f22ccd39edab73d3406c1797ac12301e86f5ff59e5871d78586532d0cb7080f7b62e56e179063cb4e08efb4c865aa897916ed91a1a955b2cd61c1eff37c1576c72d3bc643a5acd2f9068d70f285250de8ddc031404599439607d89dcdfda88ef66760620e0a68825305fc180107570927bae9beb11ba2e605f25362103b2f3016ab168c874dd0126408b3bd7eab77ee106cf5afa08a2a8fcbfaadff685996fad2637f33981eb4500697e286926d2ed06b1b4c357ea0e3afc6e9303495848696de2ef67f9d200724498b9485b4609acf2db8e042990f92d4ce13bc988123cabbbe8a07b9a6eff665107bc6c5e586865d7b501feac95f9f53273fcba6e5c4d6c3c2668f2c9da55d38b7a15106374166b5b1e009995943d4242ce618cc40bafb2486fbc812ea4300452586cb8683f7a315b1c6e20afd263c7d0489ce331a15aa0326af6793ce8a1f1c9834a0d3c0a46ea4cf6998efc5e3167b88e97588ae84aac59690556c488406aac1e1560f45f83ea7511107fa483eea01750425fa94d50a6a61dad2aa3f75fc47e14004cda15a81ba82b13da4354a1f400f94f5b890ece720c14bcfb21c8106bcc0d00f7315fbe2b6b12dc54341ac52644d11144b64e0d4163094e5e6c0ab4901688bfadf5e700faecda2eb0dfe7236ab09625ee89b53bc824b71a84a33a59547b84bd4f21cfaa6ba56236f83dc562e54b8104e6f342aa92bbf5ce28a558530c8096ba058799aff7d7d1eff4b2a291224d39f077f1ed7065c9de85b9803a6db04be0896e6848b531c9bba904dd48fedc9a3f39c638be8f9b39053b117242c737f655b522215674bc60ffc9858957e0d3ff1d8e1605ad8cea2a8399e918e68cd1050bea665b403c9b061cf4350dc34ca0c143021ce32743e0688f97fb1ee3ade0f5121e9ad289da307b68459624d60b07a1bec329a7cc1604d263c0dbee0c4c5b9532b12bc82661a3cd0cbf76306329fe9b116b2f676b767ebbdd065dfa959140d30e1cfdafd596f6c31987c2d8a46b743877f1b4039797b28fe4e247b2b5a81522f8493e52b11d6c1849f0121aa779d625be005a00c758a4d43d282b372bad97c9bd9a026a88080443a9ba1af1db80ce60fbd2fc2fb37dac3f320c26c327a55f48e363ae9a9a297ca4d4d01acbfecfcc0a17f885cfa19fb944ac32986d0128d0a4406eb16dd1396cae2690ecc41b453f87685d861f0546846621bda513299f09a6267b3e1197defcd2d708967b9a37326f4144b42b9bf6801c6efcb275ac33d452916a465d63b5a843b0e301828b6e30eaf36a90eba8851086adc0f09c90c7ff85d040590a23f997255503df4f251e667f3f05e44ae1549511fd7d032c152795f7f8aeec95f5e6b45dced4bed22f92dbaedd09ffa06aba7db67ba928ef4a607480dc872291306ee684541db1c1092660f98e5d9f6c5e25c4fe14c05c710c7a9295dfe238a4523091712528a5110e29fc1ec3bc055bf455bcd7f86b5da1fb6d5fb728334e598c74fdc89036af07141829199ecac213c0e4131939d4dd714cb8f75d64e57e9b4b2678c73c4af838f7f0cad030e86273b23ee5afed676302781e84f5ccae40ddcbc4de25443885347fa874710fe96ecac6fc07dcbb548c3b079d9744c295a16c061aace2bb194ec0ca06e5e959ce01ff1c1d52513b2bb2093be3ad999ce6722957a9fa626f91d5b92d3f24315b115645790a58adf2a18a0188678506b1669419f28f64653844e22fcaa30c63da0b915ba982a4d413acea68bdb9b0a63343a7aecd33ebc3b1598f0916ff9da4767a0dea127971b2afae3231b1cca16512b145db4dfa8338909397fbb7119d70794a9ffd6190dee32fa2b4299fd2c3baf054d21ebfbec24e4417f5e6dfc596d406d28dce86420736032c677d2ce7e0c3302423b9b7fa14f17d90297eb4f1ea7bd1ae7c87369b441e83436a797411a8abe51953d599007c5febfbece57f5c865ddf9a551f8e7284f46421b56d3d0d206154da37d168ec4f0545d274de364f1b1e83a385c28e9710fb3221f33d80417f06528d318ac3474a750740c69696d6a8416e37deb2d42b7d8702ce2c41c1f8aa2bb281ab5f87e62cb77da5ee095a195bbe01b555566803b75c494cb0ab31964dfe934ed4085b308d0db9bd01f2ad81acd26e54c160ee9a45655cbb54af0ff2d9fd62266d4249d6611393f3a44e7926b1128192b945e4c9433da235dd50889c6443abd00d669ed55d21df7b8ef1dc308c73590a5af58ed3383d06daa7aaa74225eede32a6c8b55c6e124411077772bfc28b98235b0e170367641ab6e3d1058d69c29844260ca055ae183789709af52ce04a6b52ec81822a3aea2ac8a1d79afbfe1525eb03330f06ce20dff34194bbea70a0add65ef9f7e03dd40dd78fe1cb1de96578787126a29744edb496cc1bb6847f9de5bdc26cb63a9497610ca290da80d1394a70ada2d79ad0f4e405d0050b7f35f2564f1276d5eee94776ff908786d86d058e334b56018a742cb2e1694b9ac032b4448d27b8bb5becc05f6dd2208dc1ebd6dd13f55fb93fe761b31be5c8a1cd7939bb01931dbd36d65ebc851f58d077187aaf7909b07c556dc5e293db7fd6e32bcc4c73239a80517b878cbe9e78ae28a2e7a2bede1159f54893a5f437df560706549aae3697d6dd2b32724573f638dd9594146c422d71d12c80795d30a06d9a4711342bcd62359c94e6fd6e850430d889aa78b84d11f1e00441f286570688f1aad6eba33a6884a3fd15e8d2caf944a5ca8e36c4fa2511cab2f6c01fd867b94f776dc5c8a739ff1263f7991c8ba12ae7003fc20d3338472afe3537ac061965fc7cc19ff5b0bff4b6b138ec62676dc5fc1d9c27202a48addd2fde03f481628ce7d870648c716a821fbb0591fa930186e0caf56e98733190a12022462ffe84468134c6e5220c61b257e7faf78bb90f0a502908ee1595b6021961b2801576676d1215ba3e8cba39913ee531849fde9f7ab4db3883fa8aa5a4a34e863c717e8b7850c4f72025f6d7c8de826f5f0116ee1a89349002e2c3fdd3aa3dd8472415fecfb8999a75135a5a3cbd6973eab6e4559e8c00c09620284c26c765927da24a201089895c0d2b12c6d3396f2db2e4e756403c08855716296411c265c2fc6c65bb3799803c6c1849f0dc6d4e6d07a75ff3c3268c1c4994755919cbf30c14c597998c71abbf84ba1cf59ada58bffb55d22faacff7fdf9753dd3d8d9278ddaef803d5cbdae4e7a58380a3d8831c697a879de9e165a8a365854ad4861f9d75d516aeb865678db45e24045493c756d57254aef1d8f12048f123c6fe9ae0ba7ffe8e2fedd8d11dd738cd5da24d0340db7f84636d82637723cfb80770d840489e397e45d532ae9c7c1a852529bbdacc6d58f645f7a5655cbff5695eefb4829768ae53c1572163d2b9631e33f672785162193b6771ee46e2616380d690c1a59918176c9be9083e1c507aa163cb2ef2cba004d5cf18089ec9e5d449d2c0925b27ac542f9e5c54f1d09274370146ee9d9f5a7c59239246df7c03ad3ef1f866d051dacc5af20b512ac5f2d1ea310b0af8dcad988a16264c598a4bad474b1a0601300bc708ee9cdbda3cfa3d810dec63bda76d3aa8edddc50ef989e9b5c1eab58a69bf8fa897e19e71344e212701b9f996cf85534fc63a19e5fadaecc853ed19380e4f2f73024f73ba6aedf41bfca9aa96b71c2d413107addd7db19483a8f0d761fb3bcf9c21800c4e709009d84791787ae865ed045e414a4cf3d0a49b1b05bff2e60d552457d7c6959990e8bb9b6480193a05d9708119f80a588881b7d95669f49d1139cb33fa54bfc03c46b7f8c137dfab0447b286c751c69a8a0eddba11f8fdde77517a02a53f67c5b6f9d9d91381646a224b94636afc61fbbfaa579f172b7175e504e144356240ac1cc2dbd31993b92dc396def6adf726795e299bed822de95729672cb1849f56244bb84cfbb11dc394f030859c47d2e74c45e9abdd760f85cccb418a139a6452ff2f462ecd3a38756208d053afe6192e356a4be55df756a838293561fa27e4f44c07ddca8621395840f6583d3765ea755b434d40900df1b9f84a64f42f5bf4941ca013a9be6b994be32f989cad62266dd28efb8465709480829e455054f906779095751d1733354df7e1ac4640ec1324f3f69ece62da99bbd0f471d87167e43c832850cab7e54b182ef02663e55a3d24d2491fbfac944a01ea13bf0d7be025618d4102810dc95e7f0e2c112f58fd554f4aef40120facb8d821489bc951bf408e52868e8907137bae067ac81ddad7341c9e27d55a7691026bd4b80082422a42c15c48023b53c42df4b09d081ebdf02d0ccc663c74e8b565429f8d66b70387dad93145292c04e5628eb42271c377ebe9e87f03b9dcea458776e63f468b4ea491ff568f4c2e708c270f03079ad1d4487f2edfb406110222213f213a4bf815dde300f2fe32f504aae6c6b9b92695200cb68ed91664c36d07e12a16662a21213d0ac4ff3119471399719a2f48a278210737a0bf6154360c94de10d25b06d5486e27c732265a86a1f7a96e7201bd7b7faf9428b528a25042d8d090e1021a4c98874b0ab1f0df8a545264dd53616becdebb9ef5e9eedc8bb6de8720e388cac26f7e4cb09f0e5ef74e5bb00bd7fda283a3bd489c5729458086fe952c05065cc53778d3ebc96f25bda4acbd8e3398ff6ca919f8a91ff185d0e4368f7c57a8ee6267387f1eff887488bca8755a5261955325d2bf1c64b9dd8e272ccb2d1c9a23931c3baaacd4f14f530d8beba24ae2e5e47f645049c703bc2e4f735dae349c62fa526b1dbcf4fa7a646c770085527698d0a747cffe8dd6b2d00abcf63a69f4b4c2486cf4076a9c2e07885f0857b50f0515085af29c8035ea69063c6739dd2924b392ddb4b049e30e0a2516ee2e1a066bd5531f3e376b51531bbcc3887acefb331d3452aba6706f774ef1e486580667cddbbb98c702ae2d2c025449e66e1bc3267b0ddc8b49f9dba2384414d2a6bbcad9bbf6ad6238c5169ec6ef9a87048122d04ade13090bbc206d8d2cdb9d57d37a1a720ed0adde1a50fabc842a71e833c6edb6fa00688d9278c9297b9364ba9b6dae180e5104e0d300002345b90d5610a3701a277a30f9fb4fe76c9966ad32834fb16d2416b83efbf1b039e46cd26fe2642831869fe8188e13d4f36b69069ba2fc1bbf58c3c705f58ba60681900e7ad39d1a8a194589d4c47fa890ad39e4dfad9cfa4c97fe3f8d31131f53674a09eb8e81cee429eee002875a2ec7b0e6fcfff78df1c2b14b2e049b448574f90ec0c031a5822dd7e98f873488bfd1b155a8c1067dc27be19b0ee8d33e21fffd0d300319824d9e61ee702d847738349f980c9b51450d2d153e2116b0f9ca0e68b846e313e20cc1cf103c745ff98d3a48bb387282823c1d51ab155cdca83b022a9a90153d2424f625962893c4a1177f26bff46688aa1b7034cbe1680d6926aa126bc0d90455e82b3e388edfab5a6d74a2e0ad3edc41317fd4c3169dae32737eb3e70423180d101cd1a5fb30b4be4d12cf18a60ac82a07f1522919ad02b13d3d1673e88921851d63faf07e9ea60b4dd6b4398e47fdb2c13da24ee314e6ac9cc11c3607eb3d298f178370a3f3787e26ddd13aa01054814b66aca7a5318d3cb454685bf71bd4a19dfca6268a45a3bb8430c8ed0313a2509b26c3c67b376c76e0b540c761850206b7b2f509a4a1e00d998550f292c0a876c0c03d7b6beefe124843aadd26c9884eb6ee8e7fdefff722c7ad9982b23a86c252f1dfcfc1ac2cfaed0f846581bfaf03df0cc831da735d39514ad96a18d2699ae3c782efe484b72c5ceee2ce6d3331d095ff320a579df15390c1e6b707da8d3c3a46ac7870c48b4734ced92c7b070b911c25f3991ddebe32611b8545ec4b06128e6d067dad56c4a57826e2c2c9e0020c1965372efcf1a30e0b53c263288afc9b49470276ef6dd516cd5d790324a2e890a372736da2e94c8c5d58e4e5fdf56a6c76306cfa239fad43910e75811d9892900eeb8520d2c4b7d7013a2c3c3a249aa04d84eed6c2f6c6e4d7367dd060427d7970323bbabac88c846d9674006fd959cabf90b3ca974f4950e8052766240490304db471993a496f50865c1ae15eeb4a5bb1e8334650f6c70eaf391f85d56645710a7ea478035d809c9f190f386c4cc58a07d857deb704c5fd82208550179c3f63a99a879cf9ef3d7c3d564d7a1a548ff11ef1cec8c0b627744ba837b4e367e0dea567c83f87da8bb74219fb8feffcd8d35a1d0d781008af5163d768c82a5afb484f34fcac31571331f30b82dab193dc71560dfe2e35af54d99ddb078b4f15b9a2356a27da6fea4457694d183a1b4eff3eeed375e6235de683f37fda8cb3002d3bdb310ac4640790f08e2f4bb9677520d44a53cf8e2ce903c384d0d6a3bb435d026304b5b1898cfe612138364ebae973d32037f1832388e785798aac5bbfea5c6d2465ef73400a3e39dbc57230e0e029dca06e466018644c74cee198d63189763f6a024ba3031ef08ac2926274d6bb986077d44b1ed1c98f91a76b19792e2501b4aa6cf6d65b392d1f43cd4fc3647acd7381259688b0c8d7f433f038e6a54a1770ca15c6a633060f65eda07482ec1e6a16aa5fe362d7fc27bd25480397cd43280c5bb6a2467c58e83ea7e2683f03424b44f003dfdd08752ea9f57abf7e4ad693490e0fedbb01411d5d2e884f29bfc5fdd872291412180e09817cda3fe7986d6801defa176b871c6e62f5c5f23f34e09b9b2cd787c98099d46a3282769ad44cf2ae81587bd565dbb57e97f6745595de76bf4e6cd58bc01202e595f6e1bd73be494ace8c49d7faca99ece5126932ec5d52cec87a014551843abd9325d1e92363d27f44460a53647107288f7e7103b7cc297c2058402c87405c340557a65c5e3fb7b37d3070162e4e76518d83c7d67068c79a9ae8a2759b6e14ecda5af980bb1a6fa1b488f17593b70b6338ade329f95ec7cea1ceeee07ac833021a60a4d934d463db4e12a9e486d9c936f0f1f54179f9ba56c6d5689829d99cddb77df2ca2857cc304d2d0b6cb94c565973aeac0b468a4806fb71e89665edbd1e0e47466c4c78b7aef002de4c13c5e42fa5121c09313a2cb3e25498e3a8a7a9f6f85443aadd0c5db94b07c7c7b70e4aa2fe87304acdd636e52be44df0c27d346acc7bc54f531efbb97bd46bff22f33b1363c2c0d2dd05096fa08d83380299ff648ed7a2c43b5323240fa22ee12fd5eee41620ed8e80c9fb9c982f566f1e8ca9dec53a144d5b006bdfefe891afc52ccb51b92b4259c7aeffb2bb060dea31257ff2ded01396a1ee19cbf97dbfcb722cc567cafaf0cde34db1b50015a0ebcfd13f298e88bfb2daa10235aa9d31bdbc42b5a61737137348ecd6d6ebdf43135ecef16d9169bb7b916f0f57842c3981c0d31b7dd41d3921bf2f023b937397019cee808f77c1d8e83d97233a9adcfadf045353d352d92ea645b4723ef058f8983f228083d89d8ccfba79540bef3a714b62a9091d964e3a2eeccd3f5f7b96e7994cb8076b4a896c6fa2d0234cd2ecae4f9726bc5b1e3effb7c2f7dde6cd5fb2b41293e5235c20258a28e279568ca6b475939b9c76b4cd119f9c8bb4febf8be1ea9775ae1b59d3aaae69d7ada4a5bf7d24011850d8ebacf68fbc22fca58f4c2bb8f45d0196cee6a07da2953a544e21cb85ec88a6588fa107d5e70d7c73ac2df3f7caae8158d961d4be16eb847b121ad34a0f73e253b828d1cbe17580da765fb74294092e6ae6f610e57d5bbd5907a50196c66eb61ffcd1800f832a0fd35f1a11cb07b465c8acf4f1d7e35d12cd528b1ee77ad274873fe1e45fd259043b805b20fee025a30058899dda75382a4fc077c9f4056884378ba26a477c28a676550237128296d3d5b7cf1cc4a41b9e863bdb8598b4ce5b1807b34f05c478f5978c68fcd8c66c7e69508e7c6ed5ba41548bf65405e08bf154d28981fd0f8060a8f80ceed2b5b56859c2abcbec437b337189a87730882540a921ae6527e1bbe7d6d7e9b1da252951e248049cf41725a3c7af8e41c09c4c4a26d70f40272f665743fd56a4ed3ab2db507f785c441b38ec1db7d14f6664a715cfdb070bec4cd273a100a19bd71c04775291b0cb3d989e1b07a7f1f064e57769f4c1875d5f867b75928dbe425ef641cc5099246958ff155b9489e16e92cbf3bb2090309546fdaa3e8a6b599261235f04e0c712041ad01c0f9bbffa8854b5b86ae1d3b6610cec81c5cb904bf89eb1713c7ed1e2992da31cf32438ecf424625cd9d40945f26e832e58abd8d8e41e8c0b2392ee1d9302de22cd36bbf79a9c9cdac250d8e59b3d8da62088679b646168c7eb2d9a77300765ee173a89279d6719b2f90c605dc6f5d8c8749de043e5102a74120d9d9f87ce19a253c8e19004d7e319447019f096c2c6708a530eac7b7f3c0291567331af67df9f70b33845fdf09e17d09a73ddeed4317b6bae0b596b2c7a5bc852b966c1815971065053d0088b23eca25e95e2d92c28b4d284733f20222bbe8154a4ce288abad2d0dc151cbc53f75fe41342131afb8f34552c6849672232fa5c8b824d40f0a1a21c78b807f594802805dbe34dc40d2dc1f6363569eb4bbb3c7ce1be08100716571614567d8208a5fb2b718b2309e348aac9ff0158657398f2dad56e88ee00c28f339232f73df08365e00e8041fde1d1af8b397f3b51f03a1bc3a6178c7d090225c197ca961f32c4379309e6cba63259ea29523ee5192284d43b45d9d4dd29782f491f1b2ccf53a328661dfd9288f54e5acbd1b61b920abd7f8519a3f6d54273f158019500dba50b8e345857a22620f13b16b4c9e4a7d23544bf25ef4f6512a93ea9706294d1e87586a771774212c347bbc9a0f5c8278c7e29eb489b2db5f9d13b967c52c0ef36e1c8c364b7a85ba2bacbec593e79b8f4662e2929fdd8a6aa94c467c35f482e21bca9449c6682acb77f0d8a1a484a6b984b9c89d7853b36c2395698f831b30ca0b83569266c0e8fca8752c701cfe7eb10ee6c076ad5d82fcaabc7cf0a377b4c4df4681a9906cecb848f13bf7f94ca67b514655a1a0758e90cf254da72117960fc268e5a541069f5233a7da299acefa2b1702855b499d15a47315e6115d3060e4929ff4aa8e8de7df4e8965a84d5dc3ff5917b9a766a882961defc383e16aa092e1e16566ca2a2189e3ec04ee85c2a373905561d6a887e2aa1f077b116bb4d0ebac643f361accbcabc299a75deff2fba837cfbbad323edcacaea48f6aa84d58583be8a0794229ca0ac1c412662a04fb8bb7ed9813241cc9efb366386c337d068a8b8922cf50211f2e03c5e20e6a8b809858c6edd048b5e8591a7344d9490171d668f0cf6cc9517e2248296ee393348fb88ab8e44d6f872dcc7c7396365acf7fe3cf995d8d340441391e37242f06d92bae11f7bfa352d55202813ec399f5261e65bfa4b65b9669858ec8d4986c59f276540b615ba2a19b92c240b3ed212a7da962da85d6c3455509e08bb8b71d0af42a65b9959b90c1e4bf90368aa0fd97e995e329fc4a860ade464248fa7b61e64e59643ae59a8b7f0199961c82b51d890834084b2ae9608da45824076c8a678de19af6c42602fbbd98ff4905f17f62a38e2e3946cd589077739968c92b504b3561b2fdd98c414c13caf65fcc660ec83423e06079054214b6ad181407d669d4317feb703fa7b6e8bcff29c8d4e80ab5d61d8fbc878c650460788215ac86524e5182755c110c5fbd4af89aec013f2fcb86012571a9206a2cc067ed51a1b711ff1cf34b195ea85e045ee557e92c9802ef264c48376db9bb020b68730bf8911ab54b5884e1e413d9fcb3ab5167853eb92626ea0215888ed878e4662bec0d6e7119bbe3702b15d6a94295c731135d4b86a7a3edc04797484210aeefc85b3f8b4ad4dffbf1a087d760372e75afee45a870f9f33d6fc352a14b48be5970540eee5d9b0bcda085435607a470ed5b52c6f86fd7a8cc2596191644cd2b0e32e042969edf901bdadc68f540cf4700b7534e7344d66b25f922db8ee6c07f3f76bbab3fec710106ecc750969c4c03ffc47afa56f82692d7cfa15cbd98d27fb19a77564d897ba42538f6218b2c49426fbc95704940a0a0bd81d010266feda2d34704e2bf226038544804a6ff6139a4ea76c85c75f44cde949599ae924547ee31869ab0d99e162f6f4f4b6b17851268e2644cc330dbfec988a8ccee1352c95154ca852329e5a8eac03b3b943817d6231419fe40a91a5f3e8515466aae56903f440a9d4cb3c1b64c6f41ba026011eaaa267586e1812fdc18152e3a867502aae77a6246793676bff5ab4a0a688e5a651c7d758dbd88f071c488c2856e8918751c4169741fa21c5692f14ccc5706c931c2601fce671cfb899b2ce82d410fecd97394524fb9fc3fa1d7a7b3192bb297c242108294ed544786dc8aa80c193a47fa1b80cb46292ccecd05c0e0f67c22d62c5b5c24af3569a6acb01e39bb89f52c0fc0d95cbb9557dc2793fd5ae2e57b35f6d5060fac69f3ab340493e9f09082651d6d3c3c9556f87c2a1770b301ecba08a3456828aa1900af812c85c5fbf1a530b9df0a02dcbcf652a38ea57137ba052ec8a641e1044064e9b85c6cc798940abfa7f5449af5f009b96a9445a1895f552ca3cb94a54c14f9166ef8702f912fbe7cdb9aacea30a0c14db8a73fe5aca73d9d6cc4d1400b251c66bd1dd8a072097eae583387e1c63b1dff922cbf09c143e29647c86f51a705f9281832dc92f79f6b4590472e4dea193f6a0ae72e87ffaf3f1a28d5afc441cf5366642c85ce2a643d34b43c6f1391f950577c4548aa1f5d08c3391938de844601cd418cc90d6c7e98a9ad4744579776a540ee80096b8deaad5dd0c2b538dc443f4571ca23a6617553344f907472d83d401ee8398bf5e8b7811789d85d585b2a44835e02f2fca1d39265831f65af37068ca67deba448ce78fc03e64271422e25507fa8d280bb27040307d1703bfd91bd51bfbbffe7ece18b35d5eb68f62e9d799703e225a428370487478ee56f1e4b3feac41f6c067e9065b20ec572d490ee58b596e3c1cd23fb03802497bb9a8dd5984f377c2d5dc5bef7f537ce4f06f176933e760b4100f0550f00fe1bf73f1d03a0bb45f6df71327d60c3714daada11a861002ea4f8095bf39a00165369bfe79f22e7b50ba52194be158348ae7551475af0e2a85961250d65a68ce78d1070ec48f4b526306cd193b71e587e66ac17f1c9bc4bf5e6eb0184486193751817c6dfb131e32b992c99a5c35dbe9939a3346521c42d8ffc2f3792935c738cb1a2ca9b3d8c5df1196914c890dbdaf3c0f0464c53e7daba20cd36af94df9ff7dec457618bcf3a14b80ff95a609098d6717e115d4117e5f36f3df2a1dad58311e4b2aea2eaca251241fb01fcc43e2d0a6c1cca5ae7025e2a06935aa9141a290684086caa9d8e1ecadedcb78616f4a1463cb99433de91b3c6eafbea3e44b340b60e8d6de0af7238beb6a2184d90a33c980ff09a868bb14dcb1fe745ee7c077227883bf1df5d426ab086047fa689a0e06b46c4e0bde395c223b9565024da79176c31bc51b72cca9e9db49b0ca4743326f87990437ab3202a997a106a73c02d58249b7534c75a5a95e4b436b480a04e0c3b37af097d3d7beb02c31a74b45f381815e27b616902695a12acaadc6264fb5530299f3272bbd39ee0b3309f5de4bcd506f07c6760a6f084c3eb3045406d925ba5baadaa1b3436c2789594eab38388a82aaa374252500ee00d5d0094277f6cfd6d4b47da876f392b2d2e8fd48e285a85163ea15fb3d300d1a85ca8d13a22a35f88b41533174eb6b46c79259a65bf5ea91f87285b48fe5b3bd1ee1f7bbb977a8ee38a6a7d120799a08b5debd31ecc8dd9d870ebc4a0d8046293986a4fb168fc5d9e2094da6610032cf06ff9124ab21534c73d2da7cabeb785e1a056ddf282bd8d1e1a24e4098bd6f068da1a48419ca2a29378c9e6dd3752657fe120f0d7cc1eebbea8037c8560f3f7f05c78162b178afeac8a457c79662f56712994f7736488295d8d6aa04dd2b6484418a2b21d0985178254050698d8e447f3f28ee01d81e84480f87ae7f05763f4690ccfcdaefff156d6396e1fd9e124af9c6531cc0049c8ca7344aef8b59678db01310ca1e557da614fa0f18de42ca9802b6894b3a2c481cb71d315dacc474f102b1aff72d8b6d5b562e049eaa38667044e60b59c44132674e5ecda8c93c4e0ab5a0ec98c5f00f01bbf89a4eb27a07f0c4f7707abc115bc54a6c5d31c4d1641d7b91f25f121d5785e17c981154dd91eec55b8cc345f0e02545c49a8f53684021c0e7156a0d5649fe515a331677213943f7c9300205fd633b76ea942956898b49f91b73f1d4c5b61dc68bdc709a634ab3ff051d3511d535a2d1bda6c195b9c948826597ed196bfc89574404225b5596709ef05b44c43a27d870a75776d0efe27bd4ebac5d25f1ae85bce947fee41fe4337fd03983fe05aa0dc16e9bfcb998502ef7f50f37605f575569a18b04f7d4f139a7e51e904a0defc3680376e50df5622bde1f502be042edde97bded22d97ff4199d58634aa651938e189f72208d889f97ae8982a1503ec871936c81f89265ce31ba8ac32d14264a593863162dcea41a91966c438f4f175b337668a07c1d8a761e54efb58d499f68f63428f80b45ed128796271dd7bf24c3c607ea7edc2bcc73d0b49f0d8e262f00f5df12d7c2301dc8db4c972c1d1a5f6aa9f30af0285d5ab3d254f0d42ae5a9f9da2d967bf46e4b20a89ee98ca70689ca3ce5bddc0eb0b66c8dd465166dbc9477fdc09ff01a88810ee94514853b24b8deb3552e8708e1161ca77df1f81161c357eb91ed422fe63af988701159245d8c32498eb608ad692315f4ed03fa49d7a65920161e35633d413fa8453dd6a1d7f588bf21086c2ae5eab775f5f61e5b398a84c51eeb67e9f9e2ac5bd91be6a580090001816010286632f558404b3d993c70a1cf7498b76c1c52adc3fe6fa81b3521a1a5a54d429b4829a50ce609460a8c0aa6cbdc88e9c337f27dcbfc74112aca2230142482760c336d8f11c9c898443132a6d21613532a954a254dd38e650d5fbbbb09bf64d2a3b5bbc75c264b3913a3476be3934a9a74986c77377a27c6cc300638dcd5b54cd374b4ed6ed9d2d3a5b3afdf5027a438780226e45e7a2773d347fa27432232bae8def781a20ffc964711380231f8619d0f04313ea50775744420470a37c88d3412199d30dc5cb8653a9998b0d475611886210c0cccb30c839f0875b6371a7d6118ee0ffcbece0b75c2ad240b1ddad825a55ebed0426bb65f9a5ecba3cbcc2c1b759da4dab32fe8c9f2b2332ddb8258d475da6483f7ee42bc777a6783e0910d5ea39b288f76f635023dcdeb3ad135930ddb4517b25db4b3af0ce671ee231bd3fd6904cc17745cdfb26b99c6aa65e9d0e5007642cb321aa3dda6d2b156caf4612e65ad6e251bb687c7a132c754ee2192d8e1393d0e91c4e6c252095fdc90a9cd084744f04b9a88e874fb41024cc3d8baf4f0dbbbae2bc1c0c068da7798dc85971c908bbb81c6472f65fa8a1b42b56b2b65ed156780b9691ce75124d2210d1a1f692433b84c2fd23a348c4d63d33328a559761c2a2333ba687491cc48241269178944a25fd175025f37d9b0c3d38d865a9839987f1a044f22d130a88de8cf929e3c7ad245f7323d789c0ae6ed9f7598300c436e72446ac83dac303030a5124ce9fb604030775e498f3adba6dc431c9a841e6d6e9ff71d0a82da6403e9e085900eea9d3d1a1dd9a3c378301a01f385efa33cead81f3e69ebf26593b6e402094400e596d1c149ba46d2261b4ea2796cb2e9479994c7235b748d6ea31c7e67871a01f305f060f72f636db1ecedda86488286b195cc16a84909edfe561bebfe806f3dfda053faa1444f20028c61592683b7ee74c3a5cd719bce1181dcf72e8fe027fa4cdff6c3f6303efd7ef861d3cf74bc95f677fa6924a652699b4a22f86153510bdf657094d329954a9bfb38ae44459a18ca5dd16eb5198134b486fb7d0f5ad3fdde7fdb876cec625c2afda248b3b75f4d4b9c2cbb9619f97e1d06a604f327e1f552f624d472c7675f170dd9971eb14b7b2fcf3deedc1e54a4e26665b88461320e3454bca7d9b66b1b78d29f7c0fc1932eeb09bb91ef6178d28d940e136a927e52ba87b136d24737125e44bafb66fa49688de2be7a1cb2ad83facbd7b9a1f9e63a42c321c0db6692b98c8c16b86b5e0ecf65fabb855474ea0999636cf01cc7711c168114d3d050916a586b2334f45f4fde719e63944a18d713c55a3fa1a167604fe47ddc908d8f31c69886666321df699039c6f67410738c219b9a72c07b370901bf2db9eb3fa1f1199f1c688406e8e539c6c81be9f1c878647f1e8dcf00ff848696f524d2e3904d3f430fd9df17924831f446e6a60519195896994cd6f42c9b6a08eccd90b7f05b6df4ab8cd2c516f44823c32413532afda24843a3b3ac3a3794c3210867e34f68fcc62767ca61c66ddc088ddfc8356a68fd27cffadf9941e346a6711b79863723db388d7ce33ad7f8733ecde3cd38840a996370363ee34f6e9c868dcfb8911ba7f15fdf0800eec2b5068096f5f4d1bbe0c3a69c369972d0af71237fbe7e0dfde4cfbac8a636f28d2ceb89d323109e0d3454ecde5deee419aff127349e67bcc68dcc780d2debc9088d67fd7aea9e5fe3466edc46ae217443631b7a88e4a8369972a8717d23f97f0dadb5acdd9f647d7d534fdd77360ea59165ed3ea3bb7733e42628db31d1182ab4ba6557ad74937dd9ca11b9ba09a54660026b9acc683709639c791947046ff7cab20c671eeef4055a1d86614f46067b32187bdec8c3dfb187ef61cc84d77151042e5b72014697d2965c808183ad6599c9945dd665655c10cd035fdd665c4ec5c7638c31c618fb52d1d3df1262adb51ed997f85a6b3d224e113fb07132f8df77b750fceec5b854fabfeffb3ef0c3f89ed7799ef789dfbbe3efc8ee3e1ed9187f5804c51247f270d76ddbf62c6f5dd7755df7017ccf75a6aeeb3a93288aa2281e11693080591610bbfa65f120ebe966da075a4407b80e7c97b74d6fb73a501b3169197d0d831803b1f1863fd365bc6f7a347dda886963b2bd4db3fbfb066a24a524767b5cb76d1bde36bc6d1dc0db86819039f85d26771b0f32d9848dc8dca4653d6d9b8c163923f0ad36400061ed1438702f8661adcbdcb792c9e277dda6c1cda4e16fe30ec4ee6e71386cf73eed186b3a0704e2c35c122b533ab61b5b3b2ac184a4d1280cc330dc44222c8b3870efbdf7de7bc17b2fc69c05626827a99b15b01b71d4c56e06b2e40c1d5222cb382d461381ffbe6b79043feea28ffb34d13739037e9ce671ff3412eea28dcbb22c874a801789f437f369afdbfee54ece8c56ce8c9bc42193ad0b767d5656fdc52a0d744c985c97062e151bd4a31cd57ad8d7b561b34b7a6d7a2c651aa33dd8a86263a3b50ac740e999e822ee32e1bf87611e9d668f1bdd0bc187dec3531c668c690f5e88f1781bded8c3fe30e68e3d1b1b46536ee344a5986d2b954a25eff34a9fe7799ee7791ec640f8eff33ccff3e84d9e67f24ce0f5e9d1c6a6b4fb6863dbb0e125716ff579511fd5a5ae80a8e8f4728c449675dfde75deb61dc6bbc511d9de753aa7bba6bd63ed32591bbb6bddf6aef3b86fda76efd39af7eed33619ed69dcd66d9be76dd7b66df38eb77bdbb66ddbb661243c6fbb2949bd760ba2d16c6cecdac6ddae3bd2594e8f776f37f38e8847449a2f34b8e787761be9322f99b42f87a7998bb95b383a179ebb4544944771d350e77ce7be8c3fcae3f7910e7ea4f008f77ddfa74d22f08848e780dcbf234736f761528849c71a09e9a0461273ac236e7c4edca44ddc31a5980da6548281818181e9baee59ee7af0c5300cc3300cc38edc985f52292485208c1e2ff791e8d33a2286899778893aa2143a22fad0dc7bb3ecdefb99dddf7b2feeeb575ea7a1f9a1c146c83c233d8b19dd7498edd3ba92b45bf84e098d2d7a87c1e37b3dcfa35aa47f3081df1d9f7a0ff308e2d1457884f1a9a8c8f63a4f9b40fc0e8f458a80a37f79c417e9d13d8d647411cdc65a87668ff406538a219960602825919e9d4449daf5de913cdcc9c85099675946eb346c04be9cd76158d79dd212290465bc440a41ad61f488495aa43f3d8abb769791653d75dc69deeedd3ac6369af12ba679a41dd53a343445686852d80976629920a19fa2493fe71fb0b3e9b516f3f196b46f4dd3eca6c95ccb5da795c68fe2d6b40ac3306cfc2e6d96ddf3bc0acbb0ec38cbf2bd97391d5be632b7da2fed22ed21882f6b8c2e6991268d30ec15c783e932aec9a0329ee5d124d217f676ea66ca320cc30b913bfcce16e52b8f3eeceb3883e043d133f0f20ee69d7d61efbecb9cb64636f62c8fdbc6f4b8370e07fa7918ba29a151e0a74ae5665ca3714d5fb7f0fcdb7dee5c16e14c22ddbb566dd806514c4c4c4c0ce5c1a3721bd9dc63f46864c75cb381b98abb0efbb0bd219344e96bdc8dcba26bdae47262ce99ce1df370e3363eeab857541289b4c9a48ddcb88de3dbe8be4c3920df47380135d0d33c0efd2a8d73651376b9efff04198465cba693e2d860049bfede9636c022c6a632689b02059e800008a89a7bcc006501296150407661451528a89bcdd3082f88802557c1842f94506d364f1e31788ab0369b6b9690822e50dab5d95c638526a680d2ee66734d952c154069d8128640851e649bcd72c8053a7882b6d97c2f565cc102db6673938791c5044ca08888210b282c01655f739339c5145044842240592da98f116f9ba5129ca8a20baa66c9832ba0b6d89265d321f06c4a25ee6440228b0b50358759a0aa13a52d8f51f256d6487bedad4db49a85c0626c192f7bc45d94d45db5ec510665d9f33855db1c0496290a68b1ed96290a5cb1876000cb2db7e0f2c53c028f785735cf2d56a30c128748b145bbba8eeab86757353245819f5dbd065a43c517a0c66dd32368338abdb7aee350bbeca6b592527b59e520a6a59976e3b4acabc12ebdac2154a422fda1a3c70d4e0d54bcc1083d55cf0a3c96ea272dd11a5a2d1e4dbedad0dc20659845842165aa083164c04c206dd436957a9ed219e489aad261adb87333c5564b6e54ac97d993425a5b53baac10768f96d6a1d99516e26e1d2ab425152b0e344945ca733fca302e4b1e085a3356977388d68caf97f3a38e22bf818a219f5078a121868f618f8f251f1f651ce03c3edac8e13b3e8a928ad8c71ea48f37301f7fbcf05166a1f928b5c0f0517e4144722922bb841fe51729c64f1fe712cff17142f9ccc7d9840de7f1714271c3777c9c3fff3ece2a177d9c56708c33cb9638a48e8ff38b9ea3849cc738b96c2943be031ffc38c5d8f2f487d2004437b1a81ab413fa437dc813e0f298c7e57f001a2abec88ecbfb40c447bc9462c34b97325284bca429944b192e6f67b8fcfd71011c8786017c945ae07c94a9fd5162e1a9b1f9389ddc7c9c3d0190ddb98f538bede34c6d8965cbf3c84bae1e79475e72d164312fb972e499975c38f2922b061c7200801e331c5cd0230c0e3b78c880030d0e3b76f0d0e30c38c4e043071e3f80bea147925e72b303d9d023a6830f01fcd0e3d481c7817a647a24dd870e07f2711f7ac42eea90f1c881870ccff4928be9313b4c0ed80c7a24c5a0471fe791430c07e221831e6f1c268703657ab4712c07ec4019498f317c8603f9d0238fcb40f31d7ac91577f8e8e1e3403d00f01d2ee0007320928f0ba0c77ffc859c22ba861e2b9abfb083063de2c81169f4a89fe32fe454071aedd0e300725e80c1003b4e44671a0e743d5e03881b678701f413274034341c06031c0886c3a0c77bd100e10543a8975c1a0e74f558e92577007a0c0f835eb2bda04718be432fd95e38d08ed3a0c7fc8bc381ee2b1cee81aa173e8003c1a0c71da741eb71141e28871ec51c071261a081e14034a11e73d438508ee7d0a398333a5008c337cd71ae7f0272836e418f227baad1238e4f2093c6ad5e8245cf01c41ea885931e6b2e0239100e3d9e66f2926b4b2980781bb4c9e640317abcf492bba5146026007ac471a3c75900f140396c5e8003cd14e03bd0cd3573a3975c9b03dd9acfe8251bd0498f3317f592ed7420d1468f57ce4d07cab90e646bf478bacd8166f428bee63134f4d8825e726f0e74717c663ec7cc8172dce85144e340a28bf4f8890ef45d8f330fc081a61e73fce62d9ce621baa25e0338e3542fd93a3dd21a70a0f428e3e06b0df54028ee386aa03af2920bc781e685681cc40a32e33882e808320f8443e6414ac741f4137c20eb7ad43ef5926b4b0162e925578f1548e94095d3e30644f538e3532fd9e881a68c1e4b7a09de32072abda4c70a443f710254bfe9919e3bd00c3dce772fe9380ebde49a81d24bae8c035ded33f4920d48871eb7e3d04b361d07c271197a04f512bc671c083ca847ac97e02da506fd043c10be13238e02d2f4a8e3da81363de2f87619c7a91b67003408e0c70c3204e0c6a6c647d6f11e19c763c8f43cf23c0c59c769328ebf90e977e4f999ac63892d9f23e338659ac49617f39407409e7117b28cdfc832b7914baf91675c6719cf59e6cfa5d3c833b4a4620b598696543465192d1f934b50b6041f8254b69c92ed2e5b4860316484cde5ca4411a926ec2d5f35e8f9810ab6962d2f8ae8228c9d6559c3af20b780bcca526ad04d26aa86db2c25886e425135bc66294074938aaa413b91d407d523fdd9f204d0461c25a98fa9474ac59653531e22be1d14ad11042a9e165b8e5476f50ac59eafaacad249a6452fabba7de58854af96cdb3aa722e89544d244752d13ed3cbaa93cc4d77ac59895091a074d235399fc032c5c3656f2f85a169f657c681f4d2ad4c64e6eb356bc755600c3bae02db6ba7bf9eb7fc6553cef5f94b2399bfbf4eba12ba91c41cbbe6494e765b77b9a796a5f7ce93f734c96d44e47c9fdb7779db5d12b1bb6b79641204c976b93fdc6473dd0376f69c720b8374f72e3712d1e51eb9a9cd3c6aa3768f8252ce8cda25adf9f4a809c1846727a19be384d0adc9e420e60376f6a7b9e3c3607953ce77ed9f46d2a4c9f72e574bbb4e8f399de85f1e81d89ce838d413bdd3e3e4d9a24eb3da96b77ae9363791eb5b0586a1aeaed51d6ebabae44221db2792502b995bbb964df8a26b0fb3095f7b28448eced93eaf7ddce1d99a5642b7a673ae93ad6924f25cccc33c79f6e4d95c26bdf418fdee93b3617be994cb21bd44e4faa769dc4bf95e4b42b96ccad94efa76529614cf127bfebaa65ddbe4888cf6d4482e69370776bf32a7376f9bd7b58343af65efbafc523c4ef67cb79da4c7b949154744eb3429cb7d8d3b9ac68efdca92c87d77ede6792c4bdd9dc354e0793d9bdabf0f09f7ebdaf55d5ece4f8f54cbd77569da3f269e5632bf2c3797c78f7373a6ebe035d3452f9df3dde3ae819ef72e5f077377ec7dd7b2e9d3393037e17f076fc23ae73be85dbe74cfd41d1ffc954de14b99c4715a26c190465a1e3b9d43baa91bbb73978739be289bb88bde5d03f376980c9e9447a3c3e4eda41d29c40c750e7813774ee77c97f7c0cc71bf32be285fcff9cec9716e5dde2e391b60d8f349e6beae659dba2fad84ee790d4f81e7a5855110c4c543a22529685a45245b4de5a47a1352d16b0c2a7b7e57757a735e39671e4810fa7b9c7a8d7667572d2906c2f4f29e15b03da5af6e55746e8d3e678708ada817647ede7acd959573ea2b223c30266c16b4ecf9ead24e3b85989bd67aeb49b86d559984561a892967beaa74109756a2807167cfef6c4b3fa07a926a57fa01d5957cbbd20f984fc2ed4964de6aaa95cc3de9127e31d5d9d7bd18df707b76b17be453b81430dcf6d245dde85ea6dd078674f49d7ae14905d83e3a0e0d71e8611def340c290468e051676330dc4661a8916c1f69245db8f169b8bd4ed4712211c7711c2745f8ef1b799e17def08ee1a6f4babbfb18ee500759965997138c9f2e88bb95c8d8dff6751e77cfa3df2904687005d8d99be6ba1f19992ce3b8cb5d18ba8161024debb6980ffcba8bbeeedbb8afdb38dafdd348ba8bb8ce04941ae172e1c225cbaabb55acc9be19c603a7aff3905dd3b29e66a68b5011bb972e7269950205c7850b972cdb2e4edd72976d9b28dbb60c7260967526f03cb470192650cb8037d282960116a1a255848addad631887451de779187b5070e1c2850b172e20088220f84e4606ecc0c9030f9725bae67ddeab2222530e0116ef0a822b578866b805a532aa28b1e9317da98a0f5a8005087d1646f04ce182225c9003a19d9ed40a94b052821308696182951f68600b9eb0800640e80c10522ce0b1c73358b962a39452ea71406a7843ce90851634acf082ca07a8f8a0091f2a62aca0052ba882152fd8f6dd13ac20c1b6f61c07c45e6bc508aa426f6fc45a6bedc5af5620b1eb350e48c5d6082c2e50ca5460c5a6c730ada162d8e0a2342c68a0010df6f8635b394a2c5530018760db97ec6f826d2fa20009db9e268a6d7f334509db1e0705dba652302404832434ab0a2db3877a61e58a663920f5d2500595296c8a6f0c0161f6482d415f6417688b1b51b4eb1a155f6875abd95a29b56907d96408497da02847640749cd961179ec3ac8635ad6931eeb9554b77225da0802fe9e7fbedb06562ab0ebe50ed2b04b1b9f1c0ff79894179ea7919776ea110b0d31418b2c951a227fa85dea90d41099aa94ea64b2f4129769449c7a9abfd9969882ca96a92d535278d9527cb1a513b64c9d800953ee944159b6f4a19136dbe5af05257daa4d917a9a17aa157341ea662267e6bbdcfa20675e0421cdd6abd268aacd02aab0e776b91fe40c06ba74e1385b2b103a549cd80f3e77c3e00446b877dcf679cce5207f307c7ef0e932bbcc295c13b50156cbd6118093a02d65bbe476b05a50db0edb10dc37add52c002741db395cdab4bc388bf5a4d92a545eabd9b3cfef68134a9b8c64d7aee926560b0eb5d588f64c3731499128ad845da25e696eea8952bb65f2d8303c28d48792708077a5d7a61c2a4a7bb7e750b5a13ef2343f87e65077ee4ce86bdd2ca5c1b4831ec2847da29a4c14be77890ada62d37a6ac2c3240a3c87e66718537eb15e8a528a40117b9e1eb1e7ad127b9efa4cca31913318a016e3fb2a6318add829c54eb16f0cd393e76e2bdf9d652a2fa0c265526dbc4f265791523d99729828eddd37ea537db9526d995dea69f654b9a2aa6659966559b5560fb5cae950519a264d81855c1856ab4eb8edbcb909156765f20226571cf145078b62e2c417265fbe58f9c197100b4249e0d9d20a5b0a7579b283f501cab44376ec981e427b86c22e519333925dd34d4c52242ad392d341a26e3d4dab052551a68badb45ec47aba953437f5347f3068acca5689af60ab81ef96cc540acd947724a458553d54ac5ecd2b2584c4fca287d64c2fa458bd9a7a6aa182b4011617a0f458ca206dba7f9f5b6c60cf9e3c7deaa96eab279417a1e7c6000a58a8580951918a51e091fad01abb81274e8ad8d5e912520649835d9da4045c8f3f873e7feaa9bab8add777f9f5641dcb6e55d32a426fd8d953eb883bbbe56c88c172042b76f62354aceed6e6cfcf4fb591a8db55b9c105bee1013c4a214aefada7eaf4876ab49f0e4e9ccc7be78f3c5540e68e2b7092bb4df33b7ba6b4e9badcf313557d66a9466c5959aded8a3bf3562d6659b962f6549b79459eaae7c0c78b5d5544d8d57da0cc282939531d0333556750954d535460d9f2ca96292a2ab02507a448a79b4c940f374080c7999a58a6d0f7487dbadf6aa7d6e51b58e0cab45dd2ad3a955834d9058f4c4d3134a7a4a6f8b2f9a49ce8c0a49452aa43775311ef9e6e3251264cc57aaabe83c2415ff8506d3acd63b5a04c3b74f7eee9214c4789f554bdd326ee12d55da26ee50a4d3e1834160649ccd4901bb68c936ba062e5536d664a9eaa5713d3239e152d526da84f3d55afacb5160b43f6f566ea43c5ea57a64bd0ea266b7ea6bacc30aacbaa9a59765579d955555993ce1e5a53a57e96d8954cc2ae3e93c8b130f0c4b6348522c309a69fd5a760f4860ab4fa49a3501a14a5dac84cf9c162c527077ba45470291328618fb48a09b44851a19166d9f523b573ce392d078250f2e265eb895e622cb6a25ad8283445b1e460dbef8002b6af7c68cd482b28d546f254552e2ed5b9e5f6b40a0daaf63425246598a928b4eca02cdef692ea1317d81e8756f6d65aeb96da9ba4c0348aad5eaf57b6d6caca7c35eb7c9d75d659679d75d659679df5168bc90478be9ab3ce3aebacb3ce3aebacb3fe9ab3ce3aebdc8440e94f5cd028517ca82841b95b863f4880ab57fd830498f2d4caca2887367db5252868be6a828ab1a716a1ca67a62a9fca27a8fedc380993a87ce612160bad3101a61f6d141d93465a2aa8cd264ff45dba6cd942471ba5dedc84e168a3d8d8a38d6279aacdecd2656888f6c85b965a49b897431beff156d4d5a42970bd16c44a710405b2b0334b290aa1e10dac10bad1022c3af00545f31c7ae2e3044a4041d16c8a02752a44e019811628223c2d76a359c606503537994d0c31310414119814d546b30c420f503537a915684207544011314a01ea5a3a9490440a45c41dc2b5d12c81900554cd4de8145350d00545445804d4959755d96bed0f72669e0b1864d10545f38f24a076261194522542bc517156405a21ce02e35f71f67c230dbed7c3b82b95b85f8f347b14051ee797fa2ff532054514bb82bbeea02aa502553fb5c8a02e73280b4c0f4488209264d97550b13e882473bc1ec4b5b59f8a9992ba35fd5a8370a954c719347e72330a98e6b002631f67dde49cc1f2583cf2f2d4123d0f2a602db858106061440f76fdec526bc7b3e74c5131dfab671018f83be85e1bac1c4bf7f4d4fa2b2b21970d775756ff2067e86994cd094dfaec7929af6451654f9de49ffcd1634445014d7da50c4234798365f6b43eb7fcf86df9571b4fd7d0692cdb92521c65168b89714249c1900b3616dbcac1b6b80945ce58542e1646f54bc67e36515dc774fdf5faebd7b3bcaf5b435fa0c0234f72cbb0a1d02367e41ebf9fd0459ee4c6b42ccf26608033141bbe915ccff46c828ad68c426bae5b986db2b1213646c4c62e774c8f577659bfd6b1d3c0007397d93e50d1ca3d589f4d584b3431430e1250c817e4ce41220979ba321b875e5946935c96651bb07def8375fdc8957da0a2751a2af0d50315ad2c0b41b391e8641bd30dc8f6fdbd7acc7bac8e549b89b2eec35d82943228c19b9e5ede7241496a83456d05a6a9124cb176fd0da6dbb6dc0f2630762924458c2d854e30836d3921d84df6938b3db5d856abb699b70cf06cf91be01c4fe09166571a9a4d93019e1e3739a2e0b164bd3e4666567d3fe2d841cc8e67cb6a53aaa79ae18d692f576e233472a6deca30c899fa2af3903331c8174639835d67c032c072cb54133efb888ea103f8dbd62eae0e36b5f2079ba2e489ca3d5239eeec3b862684fcbdb431d264ba6f4e72f7942fcccb5bcb1edb16a556756f61d7fac4e16d887266c6e04bd733877878783480ead9538ff24bf7118bc071fb4efa5802411d1b041a5de6e3cd06411004c14b2118f072ce901dbcb665519662ea22c574195ff6bc8c6934b4a744855cf6bca8cb9edfbc685bf694f385ed5866e5cae66abd2c252505e6a52ceb6994a923b4ec7952ae0010f313226589c25aec792f8545723a7544d03ea2ca9ed778f67ce664cf6350f6fc6d62cf5f51f6bcf5b3e76dcf9ea90bf8ecd9f55c3b236a7dd1e49c61ce908212c64e3237044a3b49695bcf616a73b372cd1465e55ba9edec514264555f5155ab4c45e8775044a0344a5196be79a2345babad9da5af9c9928ab692582521ac59c17b0c24f151411b2081cd84114d4774aa7e7015a437a9ad72687432dc06577afae5d3d1ad9575bbce13cead8f4029fbbb3b0dba81bd3dc2b4b478749bbdc580df464d26eb796577087e0649f5b4d9102f6d8f4376c80471954f31a865ce2b7d4e9b1e9ab4ff71c05ea92d341a29c64c766b67559d6539528c9012952c2415bd620e2dba9a8b784266d8c98cfaed656d5cd0d438a683d5c9ac4a1a148d68a614ee6b6244d0f6badf54ae620a6767d8161d65655d67aa85893b0f6f6f8c88bd4e6bb04b3eca9555b50b5858a35e3f1040f0fcc9ffb9c536e2f54841285dafc509b4fcae0d30029b4915ca79fb7ae9980ad064821213b537655c9797deaebd29796eb8b06d06c24f6d52dbd655996752599bb01724b8f4db3c79d28bb01349b6a24f3486c906b9c1ac8bce6edd563f5c57339a15202185e3069104da1321f5e2cf414ea9b85de940704fc65de54058fb787c7123d780478bc7cacdf1f2a4201c3c0023c26b1fb3251c03fd74fdd92af2f54ac5ff6909aba7cae2f3050f1a93ebd5fa77abc5fecfb73a998e2051eefcf2e45c1b6bbd78377849bbaf355eebcab8b8e8d3df53504061e6fb6023c5e5a3696af2d25c0539b66769b0415ede57369d9f5f76ab9a57da5523762a5a2f404b63ede54690498c706f065e574023cded4beb474d1aecce92b888afb62d15e7d0badd1b858b982f45505062baaecfa4bf79d72a9a06215ba3fde0f700b5370123a34fbeaa9f4c543c51a64ee9b92a7fa54a9d2b78a2ca62bf078f16834448142059439a134416b2c17945e3e97cfcf12502e1f4f09d81e94610bfdc01713a5533e90d2e3504ae935e50351e81592c0aaaa2ad355c910c54b25ba526d46d5e6fba9aaaa32555736423a78ed5ef7d2004cb11e08325d7add1e5a73f55011caeda1353873ceebd2261becbe2ec4eeab497892bed9c8e89f6e22fa486312e0d18aa09876f80e1ed44384ffb4f5418d37a46c7d28a5d70c42b303424a582047adf49a426bc6faa50a187b68bc56e6d4287764b403495b1f6d79eaa97e942d947ac2a161be5a44f75e3cbbfe2405b6507c9eda33554f75fed42aa6f9b9a7e6634a077cae181288c7051e672a456ba490b5a5da885e6f0d551b89b2b4585dac2fbb529e2df76853f6a79eea45d94ea9a77a30db28a727f06853a97b31d6925559767b042d91258badb26b7db040a936403ed5e6fed45305858af543542e1f28d712b4c63ee1de7ba1d01a918787a788211e1e54bdfda13534888706f1f0ec2ccb6e0c4b2c71b7ec9a55168afbf3d1da02658ac9f2d9b5fede2de371efbd433ff766b9d7cb1dba5fb02dab7e68cd686da182d6d8a1aaaa2a8b038ca5c0b0178b15a2624de5236c4ad3a6928c940dd242f4d14ce1808f97cb47288a969f6a33aab751aa8d4fb5099fbab2c7fbc5976ad3e4d34dbe13815d0182115a5040d745afa16e02ea26e0c38fb4984f53e071a63250f5a953528b6d5333be90d2daaaaaaaaab2f60815ab0f582a9a1ed65af94a9626141a4198eef1619ea8c95db7a914adb9ae8b86613202da14f5510f7e07e5f9e0d1a6be6c32f25d74916e22faf71d944d8972930d0a201bf00045c46f30861628497d8c94cb09aad081104041e154304bd437848a15949cd545ea966a6353b56ea95ca88d44d5ea25dfc0565a0861cf1b2ac0e3c592ba42370bad1969123b55ef531f657e4951d17a9ee2a66eeaa66e6aa6687a703f98c09f5ee6480ad6526dec1579aacfc1f562572d9608bb5e4bb591a88bab4dc9999ab2360b1b5436555536556d7258a12f688db4616cc0caaea31563d7cd6ed935b5abb5959d5f684dbd37b553b4661689426b70e697700ab17bce54b529cd21f506f3e9680f5d68d2670b61e9142ad22954884ea936378268152de81525a8159aa226da45a3f6a7dad0b4000449b000892b590ca1e8b58ad91f1d846e9ba2353fd5c6852d768a159b85cba68fb2e947fbc5a6d514252cb0474b653bf186b070608f251f2f7bb458361547fbb32976a78d426bc6da6543416bac13e69cb376a936f45e8c4ba55f14bbe8405135554ff4180c2cf738a14c11481b8b0239a1541b2bc5b452cc9a2aa64d76fad1b260d35b608f1cb7c7096553a127fa9badd0295e1578ac5d36bd17ad1ec3b00b911bfb0e933d2b2cff60025ff1a9b235ba5db5feca3b7be624755bf555b5549498a5b56e57a8c2f6ec02df6bcb7481ad2dd305aeb64c17d86e992e70dd532894e902d33d3580e7ed1e3fcc851db890030c040c84aa7241484a8f09d6da49abaabaf6558ed5da55cdd56eb757da6b5b36d7add129691d87d02e64995688eba54dbae16a2babe6d8f53576fdac2a7de5cc744107dbdacaca63dd36c7b679acb16d3dddf512bb975571544c114bd286b392f2f0509e4979ee0ea4483f6e3593092705887aa277a1063c3876d8f5cf9464d5e70eac4f9e2a5a4329d5b5529975d6aa95bd9775a5ba52b7bd525da1db5ea9aeecea4ad572f228a980aca95ae70a9562654960d7cfaba9b5d65a9753cee85d358695a60d4ab3d6a9ad754d0d843ae1bd2c5bdd541bec3c343c725a40da501e146c3aa56c8ad5e0b26c55653ea7501e5a6b152a7da43c41b43d854a4410ba32e5a2a324d45a6b96556de3ba8edbb4cc8bcad67b59d5e5be5b747e487511eae1480d3835f5e3267553a5ecaeb4e472ecae2ef08eb098cfca999a89f5150797b3a6684e39060b7542ec5e569565b984b1dccbaa2c2762db4eec5e56e50556eb7647db85d4e852181e9fd168544776146ef1f45c8af982ed489bed9b9e4ecc0f6860d38fd3029b5e2cce29f807787e34dab2e66eb2e67a359233d4db7de51e8e24c087baaf7cc3909411ca1511ba99ee2bffb8e94163abeeea20e6187b017286fe071d0566a2e4eefa09c89aaa93509102b1c5d22969d6557a6e9133740b38faeaadeab367fa60787fdf00339132486dbb092fa647bc7d31f974237fb12d6317bab83159d4985cd3e3cde6bdb854e92d5300b0c7b9654ab58900a594522636a5f741b6ab66f2033c69c704d33a3bda2e6c81474ce40cfdc224a324272ee4a0d65a2bb6d55a6badb5d65a25a6f4f201cd9cb30bebf5f89862eb6a59a6498c450dcb19fa9eecbab29ea80b58f0bcacae8dcacb395f5fcdcbe46e69b3ad69b609706bb3d26d6653ce68a5d6d9764ea523bd4eb8251577c4705b8d56db52aa838a53dbba534d8bc4c74a2ba516b52c8bd62b8fd6a9fd45afeba2746b368f56b5276bc4e4e5680a3c4f4f3b8fa22d3349a7c545d3484078524a01d083e7ad911478debe3a0ebda4945655eb2b6df5b8e3c4a4955ad6754111033279021bb02b95a76c574ab2aaaa9f5665ad652b6b6d554929a5652b6b596e0712b0fd3c0ecda6d0269dd5d67da9cdb5c12e5fa27bea0fdc57033009e473c0ce539eeeaeae25bb1edb555ed36e550504152b8b43e794524a39a7ac5765a5cdbd00b080e5640b617755f58e2e3d96da597db41e582a5842063e4d780015832d4ea0a0828252547881829241179b2157b65c576655b6d2f4b8f94153575c10d4850e30b865ea8a943b0696b165ea0a121812b068cb54eacb90d4502a0ad196292728b0ed96a9d413f7da3bb74822705a66cf083e2d39e852a925b83b841a1f96c7ea141728c04014bbed2adc950c71db8a0628d8150da2b0ab2da8ec6a8b293441dc3184b2b7ce6007bb6ac1c40ca0ec5ab25a5073079bd797a089ed15a74d6dfb792f74e7172ff60614b0d8e8f1430659b6bdb54123d836e805581881c50eb278228b256cfb163820360650f064c8407f65008218e060d39b3011412842ca115e88604415720859460004822e8ef0831fd8266cb1014dca4cecc6608b4daf68c2a68fe180501cb4c52d8d326cd4587181952c5c91c5b6562ab0ed613820569c3d9409185020a394524aba5568e3be8067dbe3173cd9f6a517f860db1f06402e38c1b61f714002a3b3a8744cb7a4514e3245230000000000a315002030140c888462b14816e789a4cb0314800e819848764a188a93240862140421648c32881842089019919119022700b1e93befdce7735ac0c7858f9980a7ec852f010b693b71b19c7c8eb5bcdff64b59fc5a65d9850c0fac9c1dbcd142f73eac89db6747b11f920f66f35b0f22820bb40569b86f23a108f1a3b539885a9d90692c3448e70effbfced2695bf80127bd9c2a2cf50df5428977703634668d2635c33cec33a3a394b6cabdf30b8d4234614d1652e297550e85763a52d2726cb929b9b4531db8c729c67c52cd819c6377df6502140463e15a44974d289ee51d1aae6e79b6479baa79d5afcec7e6ebefe7dbb5fa144cb520d2360e2328fdd40fecf112baf7804ba25fca5e65f611ed3fbbf12745c129074a6b4b536d02e5b6e914be41f9f23656455d39c5830d7df1c550b29c6546b32128f255b1f9ca10bb4a7a9ad94f804b3df4428f06ec246bc57af48aed4e7fa3ff74647ab9188d589ddb52c600c715ec7aeb8677dfa8bd181a30ebab7895f4605ce87378a10659446aa0252bb5c6ae008e8b5fd4b1a53a8e28085dde3027da3ae70f76e1004bd40e66c1f9202f7d6a3e6882b79b87cec0325d2d032e36e587d3e953dea1ab54aaf7e9b92aa3d8d9546c949f1a8e427c3d2b0d5c6664ef578880bdab1386613d350202f07065d6f3824cb0b2d2f62d4c3d93838beba01efbfd8b8767f1f63c6f547c5833a04717e4bb5467ea05842d4d4657fa03164c223517e06858cad5da97bf7787ec8a26a8dfe401af9ed5ba28ae517f759c9313b09b7d22b844e4d2ee521c543cfb8c4188eb1289dba9458a63b3f2329f73266545cb6015bf34d7e95f0a4d900e2d4959c22312c1dfd89349fd3c52662d123ea4ec064cb40f129398bf207c252106ac9cfef2ce200dc92655d57da4be2a943c16159eaa803e322188c60a4bf4a4b4617249e22cfaba51f3a243e5996a3e568e77edf41c2111d0f965a1510052b569f2181804b2b9a12871f40aeacfcc0f0bc3be5b4cee1673c7081dd08f791f7f83a290948b27fe63593c716938ab3b972f7ee3b1f562a3d741e50387cfa4ed57f4fd71f3ef8f4266caddaec3e75f56d346dc61a7377bc0ed6cb550e3fcf77e3c319144b165c114d424e5ffa8ac153e4b98da865b45c4dd58f418a27408423108285f2708b1bb4cf9be5a47bec9ccaab25ba8e0f6f16b55099e6d04ec7bce249038606e514f50213abe16c5407625cf72713fb09812773df9aa98cb8d9f84603f734a877ac2b4ce4048ebd27f767fbb8f5ea6a0074c9dc9c65a89cb276b678cae6e1450c789312330dd94c9ddec4fc90f09ca0400d056f7c20f73573500e730f2b215d1e823361095c337a77a60476a310ff0cd2d10fce12d7f48b3e3ed614649bca0f45da765730958969227eb6663449e889b8f385a3ce2104205a8e038df43f9fb4ab8fbf32552e1f3f4881e23f28665e8208a03354f33571d2ec679cad4baa7f40e42dc59fb8c3bc1202043eee9441d303ef75148921776b90a52dab6d0084cc14875062968af24bc7e9c3c7bb3dce6ec327a7a33a81e85b0f3b7f53f8bef7df42bbd04556293f66ee71e30d1c29b1ee5ede96c765e51695531959e034a431b3b7686c9235330232d450f94b24d3789f3965626af1a14a2134a43087d1f4037181515a6ca40e71a5b87a7329c6fe7afec3b9d5eedd10455de12201c54fd2c8f3b3cc9f7edba38076748f2113938d31020d39d90636def74fc650f9e7c509b21710cd25978e7eae09a87967856cd06ba744080dc68ef37dd274b76a17ec216f8da35f1658c1c238ee0afcb06cca337b18f1e3a16a701b6194fc21cac87c72501b7682acb9c1e464b39369ff050e31df60ccee2b9746149dd7c75825fc97c8d1194bff2b69113e57b59d85cfe5500ef398622416f82421f70283098fd0af3d4d7efc032be96dd41d1135f6e88769284e8e5ca1135a03ab74f649286e564c7cfdf0ec3038c391ebb001234647d4a6ded3b3552b11933bee18ac695568d5c0007deaf31e8f221e2f54082b0f1195453b808515ae8065b705c5b91693a7c0b4b3cc94e381a3381ac88ad2aab0f87124a70de576d1addc97e607d24ab3337fc606a0d57de90fb4ec71d4250fb733bf1cd37e3dd041b55adbc59bc939956e6fe03dfc60c4afb4a27b215aacaf6b0c590c69520dc0614125c8cfa3a4d93836eab6d096727c3e01228fe82da65213c8182b78340b4bd88d3614e00b19a3a3d85e21da9a6774fafe308fe9a958a896b9535b2a308fde57b641b2968593c3894b20c4a4444a88253f4aae32f600d4f0e1387666e1056f9ee136d67496a2b609ac79a53c15c3aa4849d8d4746247090240c0b9b90534d819eef4dd1ef071ec2c1d533b52fb9f0db9df80d1f66e6b199125f9b7ac54152b8a7a4a75ce72bc45c91e1af1ac4ac6d52717895846636b6f2e96c3c47914a840d78af2fb0d4feb2f0f9354a72ccaca58da32400a0f34ee8714543a1351524337f6008834f8cf6cc5ba586f9245e4ddf3a505f2bf86d82683325d52ab09ab7fd878ecea98582c9caa5075d582488bb492e8cea5c1ea00d463e18c738aff79a1029f1e77e4b54962b10febe5fba360c16f83afde3c488977d9ff316bd389b199ab5574a8deefb192cbdd4ba80fc08aa30ec856bdb055d4e8f772d24a9bd2ba577128d5024d8a053a642a33f86b124355396e0bf9ded09ae1ab39b0f198fde0a87442af46f0c8045d2ca4cb2b23b033dc468ff5a7597170c48aa9e867bba8edf99995c3848a6ebec8d1c5afe9a3fb55dca4dec49becfbf531ed4cdce5646ffa04c45b434721d1c85eaad273effba7c9e98abb7aa613fc723904f5adb1a0fe51fbb508e13de8338d499bf56a244276b157dc9e20562621245b81b01089cc757bb934f1d0c94aa60148950c3b3db035d3c656ad0d2a5ae2e63b83fe421eb0fe5c39ed70ef34a2c688cf202befbd13353eca9aacb96f1fe1197f94ad16b8734c3a1a09e44a37164df4b1d4112b38728b71c041ef46afe63bfd297b8fe8d120770fa24bb0e2ca90538aefb6b8b744407f959b06cccf98946d04f4b78153a4eadbd7d41081287d9f5d5f6ff8cca14d2feb19f3c5558409a974654f9b195e2d24287ef3118947d3138edd55cc84caec0e15cc9937a49aa385b4b46568cc918f73cca55f1f71e651d370fe1d4e7360bbd9e85b6f8109a38ce18b36c3a6843d92c3f8835549ee61f081ee2e087a1fb568586c5d0773473e074b3d93d2a45bcf6f8116a4017240617ae4c4f3872a56b1ed41d85a3f80d68161b36500c6e5541965e15d3b0d13e44a347c5d6baeb282baf74a5ad144140b393b4209cbdd157c2a9ac30d83af581e842a54a06113cc689fa5a5d5e3d2161c4a055dbd12b37af967055df4d46025b455ea97988ebe524f6a18aa86b8dd6612aeb45fd2c190eb2eced57710c0ba22191de54d9f13127d46566678b60ee7d05f01df2e544e720a51cc0d312c545d8cd09355894feac135a307e16cd9cda754370f702405772eb22644a088461a7ceb0c6fc51597c52e476c8595223fa2cdc4407354aa599f2243fa4da42b506f74e94b401459b74dae8b72979f8a502a12d40b010ba85574ae57afa47b091ce0ad73ca14b854ba0cc087520d34aece2980494ee8e89b2dbc6c4c2361922c44cf244595b6bd0a2004dcac7245390fa470cfe6f825c646622bd66c68f984c1ebb18465471d3de939123109361a19518464f56149868f311f60cf51034130b0653ec15896200f403d929b764211f798b7ae48f2824ca0439ed01c472bff8e00ae0d71280327a8cc20045093d750802aa69f851ee194fe80ddfda6e99a13d13ab7fd3a4e5fb654d1981c49d9281789b4fe4f9c38b8b0db712d1ad191e682bb7e59ac6e304fb34e51bef5273dc8c37cb9209a960396f1f39cd0807f877fd7dbae5c738ad07adcda930eca9df58ef0b654045b08572a9901537e0001a5512280c195900a8f24aba845bba481ab1a71c59b9b7dc86348eb845b306a83fc7d114138dc0bfe3e9f9098cfa6e304fc663a88e8db8646f43ec1a15e38df68282fa4748b5d0bbac71a1bd7766365fded16fa576fd8d1d9c6c950849eeeb64a771010143c9a9b1ce8ae65041198ea6dbecb9ae37bfe380cfee1611c6fb0d38eb44b756809a3bd083a3506da2e449c5e99fff5b872e04fbba22ea20972d73d086f981e23023952405d8f224d5f19dba5ae13955f336286714790c007c8189c29f7496ccd49f0d16cb372c277dc4c7f948173555c89ba000f94d79d7191c1117dce9ebc5085e7ed8d61eea3beea46e81d10bbce7294c8254b8dfa905536ae3e2e33032cbba79a2cdb3fedcd2cd7d48b8cef5e6eb7bfdf81a0ab014e587b832520aa31f5502fd2008b323a0e89a132903323e9f054df7d833f8cc0e1b645af2025048325087a8762aa86603e68fec1027ba8457a07803c3968a7548c107082aeaa3c1c9eab255e404a54bf12423b4e8a38c5502111292bd7f53b2883448cfe8ac80cff9a9fbdda93d60c0877703e9905e7706fff5a353b24f745c243d1a517d6aed78c3197f758aac094a1db3cf63332d9cb477829e7b5f9cf28f9335f02326f212c645a7ab2e84f22c21c566afda5d63bc9d9940a12bb76b72f1bff0a83fdcf102c3d474e7afd79aa6b8ed7d99c26d16c8090a00e541488ca97c166bd31e3c5611447510e5754cfb70548cf0f85e302717e0092d789592b231d4a3a3158fd54100f55a46903dbf198bc204c4649ea195a42c29795f1e9224f5d01828b2e3404b7e2f0738a0e8a51048956aee5206d530c37c143f781ded15ab1c47fd57aa9a5e3e82025e46a889ae7629c217ada4838219d1fcd0999cbf2027253e97d3c0d1214842b32dafb4bc6d85a49f081ce698268036d546f752d6e7ea2fa10523d61429f03f4e22b9444fe465e6a3846d15f796728feafbc4a35dbecb07289077f5db9d57124b9d7145f606c833a55c8504b7b7a3bbf83a8bc21b6067573c1c874f53db1e2bf82689b23e8b2e6cdcecda6b7fdb5676af5a23065c987d0cda95d75ca56b54e15bed17fac93f2884fda25f3a3cea5df5ef1990174ade03f9d0e706ebc89e689eeb008edb9225177014b511635c4f494962afd6ddab2a8220f790154eb4b7cf9ec0e2985db334b543873a7c8789902dc258b23a4df0b8f275c2b8cce9e6157a59d42f14ef2a22dda1b5ea5c367d7799739e0a251f09aa983309dffab04e52a905ebaebd8a5647013957be1d0baa091d08a627632b54c053125267fba92b60cfd4543036767252f895a63707aea83e948b2528cdb83951734a45e5a8c84112461b35a2699c36f2b5d2455fb466e22d7f3a6a1ee4f8a60c96870b6376c461471cfc408e373ca8bf2d9ccf29fec13c17ce099792be28dc0400f6d973c031387ce1bcc6077e3ae0614ba09cc521c1c9a4c2cf028abb99cde300af93cfbb491d08c723ba28c713a132863d3b9b80da929c3756b3ea16d4c63b5adb9a924a7bea649f3cc812306a626c53d74583e048486a89887a19f8f7257d6b914b7bf23497310126621ab2d09ce43cd856838324c8487e758d4b0b670ea7f59afba5b9fde4a5352290b765b89171caac959f307676e6abfb052266614c4c1fbe24100cb4dbff2d1e5c9d4aa7824a8ce0fbda740e1de3981cf8a4dd7c56beacfe97459a730ca62639e2804370088cd04f10c71d383bef060ac56f5667b8253667dcdcb8ec81d2324742fa36264d55726a4124107bcc82146b0a547cf14a21ede0c0f51917658a50a6d4c4dd1119bc1c66519c288ee9359f3de69a0af283abc32340e70cc04d0ccf07fdb257389cb028f9609c9e601d80007f74e5c652ca60da29a4f8ec5a10e82c518a1372fa77994625f8490b650f14993724432231650f5ee52168e065784382843d2cf01d140a6488ef02ab8411f5154c8493da7d0072e0a63ea001040fc841487c700410a2831cac5efac1d51c42f4e1c04df5e2a0f9869654cf13061a579e32004c780c570bbc1b2a996b255a88151d4454f882ac721834ca734c0f12a49bdf2cc715c8a5832ae09ec305ac64ac963d36b4ab6787de1b8a27586a6e313ad84e8ccb8488f3227263cdbeddbe75cc4d229943b5112dc420a2ddcf18e7fdbfda15198567447ef8bbe53a16b3c5ab35a204753e83cb4e0ffe9819a6c9ac9599f35938c2cff76033d8ec230d39042992418327fca6f3dd383ebf0a1b0b399a1c3b4ffa80ea47e93dfd1535fb619c1d7d5f1d034c89f8a96ebd00a73d4bd0e1442d51907af368631a12c627e61b0b186c3f6ef38f8af1e22b96039eb983970c8c30e60f2424210672194ede810c7246fb7d84ef2152e06e1cd1dd1f15246110fabb1bcc3dbe26cd37e7b96efee321d2e14162bf574a4f51f8d389235c27ee7de7390e061ab4b8b580e2afe09cad1809ebc13f22428e7835e670f246eb429f448f053516e0a7c384754ed011f6ccbbe582d7093db88bd89309d98802c4d70fd6c9010e13bd6a8473007f2289d68d816eb8033c1124280903c8462b23c042c5f53d8525b049d89ec205f5d109593b950504dea5ef57314f519097a4f902336bf82431d358f1de5428bac44e9285d4032c2799c97332ba5c0039846466e4e6511dd6ea3ef768bcd3a5103f072e9ba2c974e72ada1a94b13a14e8fe76115ff822a7cac026a184bdb7700027802f099f79e0a879ef49c1f6fd8aaf767bb153c786df33196cf73eb62c2c8ac5eee13f98cf9cfb3c82a2ad28bbca754232204d10a185f5fbd8c0bc75f42ccf48ac69381a5014473a0b74b9fabf2e9f770461defb2c2392f50d89ec3db1665a0336d6fe2a27c8101c58604a61c3b758c00b6d26c992ad299928afc74b5476ed3edfc374d8d2a42a87e9ee14975494df27ff6f0ce853dcc7408b820986f63e0dd431332994c9c446a7afe563c104b142bf778dee89de7cd68dbc514b6ecee274570dfed845203474bede63c7ede08904b9ae37ad655eddf092d4075cd47172ddf654bc6f5dab0545ac07c28e7ddbef50c19f9f7aa2d0b4ad11b6ce75fe59c17867c35312aa1d1bc34ffd52ea4542ad61ec014732de7fa3ffca212dabd14312004f6c899d114aec3eedff640cddb934813597e71ffcbaa3505e3ad2dcb6de37a05e77421d06dcadfae5cd63c8e0974ff23a31acbe4fd25755c83470c8290d3dd0648962d8f47bcd28e6e16cf442f7cfd793b3366dadc93f1fb53378261a5d1bb4902caec9c5dd391904cd57b4030d1c53600d288a22b8461d4448c09395fd3294e1c470ace2a2581e8bb307d8cb9432a601e1db6e51256c75db8938e5e8eaff2f6a33d0240d150dc40541973fee91f8fe5cca444cf05e8f6173bea857c814e0d87306a943981db0ac77640cf2cb49f414e47c04787784fb2902d587fc415a88844ffab87e6d1875d6ae6a0c2cc0abd5af09f67a03d35cc444c59d10fd2e0061d1a8491035dc1c060f2f003f944958660c02fa3b4be3646be4894228cfe88a7811373a6b344ab8e98532ef8e66cd201c11de1b2b49b138fa4a48e12cdc01f3a1beaad1c408f2372a60670166298e1ee5a9029bf1a832cb8fb5344099b5246142bf2997c9e3ab5d024c549a29d8b8c3fe34ed31f098e5a6c3caceebe564d6ad6b9ced3a5b86381dabc06ae6a8086cbe389e43d2746cea956ebe374bf1e1087e2151137be3b6b42c1312e5addfc2563d33d3ec7335ce7c02133c299d7ba03aa7433b061e9c612a3170a5fcbd07cf75839352fbdceb77dce4d04f2faac3c4b58638d24f97ce8bee207dd2db5fabe81b54bf2ff8c0cf96ea867607e0515c193d4372374ea595dca723bd2bacc7ac642d54dd046dbd60cb44c54089a4fb9300b80f9f93ede815922f3dd3f21852db89ff4647c93e4ef8da44e122d346580e4788ac9c9bdd92c31639d7cc7e790b6886f81cdc1f898200bcdf2938f8831ef6bb3505bbba1f682afd60dd078c841ff9c3cb96d16d7d32e74611fcd35a75ba27e36d0f8f31fd7981882820129c7c540709be084406cc81a2aa279458521e68e409b520eeda833c236d4000ef5b32f5042805385b99dc1694cd973d0d40b461e6fe36db81e59c99b92e1303ee303faff15794803b0bafc0f5afa5ad89d6a01aa337f57b14450fa643ae51805e6fef452387a6dc8421d16be51a5c1e4cf3d60062ff60ed4f957f6253725d49bc019d5854fbab2e9ae9f400c5fe26e25e32725dc7dd70820477c3e0cf717cc466ea739e1cf642c2820de11ec469b182a6c118507efaf8dc8c928eec02f7d2141bb2639d2f40881f559e8dacf2f0f44b44b13839de83e59c40436b9969dfa29810091a3c74671ef76a59d12063b6ff14c6904c44e37cc2f5d3a5ca5124ac60a4cdf6f6791363d709ae05ab60bcb006deef336d47714912edf0ac49d8676ae750e46f1764a2aaec77263143d798f635be1d2dc1595cedbf2a3f08f1aa8571d34cfbe92a7284f8eeb76fc1aeb71f5ccd703d223de5da71b11ac0e5f57950580a122fd2fef8445805a49d4027ef790216a972220b6abc7af8ea8bc72248570e83033ce082a680c4906f01ca205c3f4071a117b0d5e84806c81e4f644aebfdd765b70d37ab4c768a78e1029f63780cbe47571d8dfa2d2562872c2162887c4202b3437594843473a76712493de5712349d28d8a3dda8befb00a22a8f0a1508bd80c0ee298b31575b10cdd19bbca815796b7820320ec578d1ddeed24f3d5443110fe1520a06e614e52faa645d2069a6970e65a38e68dacdaa85e1a3e52bfd4736ec085bae2007996e4195f430a6b827c2e6116ef2af7e9d4565da8ab407558bdc2b7524a5b95c5526fcd38c72850a117e80f1c47b5be8cba9aa46a3e19d07d4a8ab196fe1f917ee798fcb70c65247bf9eeac6070e9208c536463102ae64ec8a4adf9f7f63fa2ba0317091e86264cfed88f74a54216a4458d7e08edc1b65f5caccfe78bc23b51d42436daaf7cbe87e798a6bacbdceec827069cc7e15a509d530b2dfcb10667d11b255aa1122166985d179d60a02c43d615072e52590a8c4d60f080c91159d1c854a02709e36a499199b46f086ae194a3c62e516636ba5ab293a0b3342bd0d03fe4c5183fc5af52d94d6962d8a1ea307a5451d45971520dc01d13355281c42a0bba012f984a1616ee98a232022fb0bce98269d1dcf720061ac9005bc6ecd611b05e395c4d0c7a330a2eb9e3420a20c8de31bf0ad9b31652391a686e70b07f457856a1e416d82e9233aa7be8e31481ef07fec9ea219d367b7d222534eab995c450b49249eefa2ea39e8b2b5e5c6b124659cf1012774756bc7b2cd1b3e2272ba451b9adc2a31116e149b8000d2ebf1eaaab756f76256da48196d09c3796c01374db6e69ea8fb007da9f1255e2b1cb55a6a95e057e770ed5faa6408bc7ab45dde79cdab98f6b83a80a11cc7a92ec100f9b0a7ba0756a9eefcd1d9c9b079591a4e29447e943ef719274816ebec26ad05da374115a01792ca79f524273acde09e5c89e01443352f43a59e18300ba81a8311a465d99125fa99101a1d0c532e25f11cccf8a93151c1048b073a21868a53c25f74ba1d58fe9a324e5e415ea65b076398080be06d4ada2c873b5a92dbd33c0fff3ae0556a962e3ce5458152a3abb107c93352a0ccce9bd4038fa50096ebacc903af7136949814a1de449256cc9acea86ae5005fe93acc2a5d18022fcee71f4be00216f79477590451dfb0a224998825dc6294eb066f54e1272bbdcc358597a084fbb8facaf9f28e85ce09afcf624fbc154d6f9d81e61200c266b351e64048d17b3a57b966506abad6ae5b7c26c7699681332a798e68d390bb7b243346ba1422de20491e16950c3b5ea66f632df32c5dce272b28bab9802c4c94ec85a9640a62e0bf7b34165d725c5e7747950e22449aee0b716614046f633aeff930dbb1454d6a584547e5c7dab821e4d5233022ecdb8702d87fe810a68fb0b96a96e8610a737c725e0766b7182ea961e9457ed8c1a61a589039afa37ce4ac539beb34286f85271eb3f6501c0a7e2749f7cf1b6d27292d0b48280f5604edc4cd7ddd5669ab31ca2e1e4650353046491369545f4b5de64164120369db736ea0dd79616682572a2fcb4b3c74660c5888322a1578a777ad838b1c1fbaa4ae20201a0529e88370e5c6bf97d1a117426e7d383fa48024a720c3040563b0516d772942b6e32ded0fe3d6c107a6e929ff377e665c5413c8f004a27999a7fa50fe8342ab300f0f8838efe441b67e4b96ef0fdbc1fd9b4caed2ca6c930ca796460421d0f1321b8482fec8b60a27cd1549fdf0063f887da879da28416d5963ae92485ff25015d2c752fb9005b47a25daae8069a2837da92cd7578598dd5d491778ef0b6d2d269f082bf28252333022190f01cc482b8a2b8102f15268f109057377fbbb8c57257eb841da8ac5e24856da0c5acea340e517e4aca636e32b6b0daa5021f4a665e3f7b7c78cb78709a09271222f0a1f78ca32c7d48c89844ac6e842fee80baf1b1c341c0c45d00c6989ca5023508b7fb402c996bc36ff7d4981ffb335b79342b17ecb990df542f56f67ee6b8f0901317d9108c84cbb53451b29b2b33120a546f2a17ff5a12068e8fe21e9c1028c0a6b35c29317560b04ff97b3e4973d9540923dc41cbe89f81ef77e7ec73d83c0d87818bd2cd30617223e70f62b313b2323174532a4cd2ae2426d480cde46a89230b7e7121302d19082151ff07c64ac622c0a17a0c2a84128050d220776263d7a097c051a7f9780fa6cf3d2e4ae8427f0c92ca483974150df73b2d1af7620e2dd809340da2d221b18fe3b95cfff54dcc911e2e8b31e1ff5ffd5df8f5e771b5da12e1ccf8f466b7184f4f4b3ceeca4c07b4a644bb442de1089395097b5195affd74bf26e66470c74cf418144186fdf7c5a8c5683889f264a018e58c94941138f00dbc0d783011fc65d3e14ead1e6adf5338971167bf316d849773891fe4f7b76baa9212f44cdf3d4adeb31cd021460aa47b6391c232aec6467d03a1881a07226311d21f38a4a5fa98ba32f397c20e721f460721565864b0285d5979f860e7913a9eb3f8ee4757c6cd67af552a4f1540d9e382a0426b9dfffecb9ed4696ea8a30735775b0cfa2c34c94527dd7069e8a31c1dfc96b325b879b6908191740cea711376edd552ad4ca91cb857700def9e7997122180cd1b5bb1dc6be990182bfb9ae22a7a1ff595826059510ba3b01103faaa5c868ab5eef41deac81b9c6072fa6e8f5d1d8bb5a0e666b07960330594a7a50552dc35abf4b8f4ccef841c48721281098df1b9403266b77dafdab679b32fce61b7777149655592edaf34351fb43d8cf6e9d06faf4ccb745a48a982b9ea08c4af3a9fab2e0730331664a8caa170e53a47371b200048ee3db360cda551744ab7d3b89716534c9e6245a6e39ac6d392a99a370f0b874e46a928c1539e2bbf38ce2a44b27632413336f098f57a694526a304083efcbee8e4afd9d2e4af5737ebf368fa8f18029286e81a94407a3492825ca3ec0b6bfdd5b5ff03dd02b1a680ec269e29e35ceea4ac018bf26def385e2376447eeff477ee9021f48db8315892545a4d203ad6086551eeaaf0e01c2a8fb5cfb9e53259bb13250c5bc0f62c0cce58e37307ad581abeadc0a31dd70c106f0e58c2bd53d3cd29ab7e308c5886bc1a4e5a10afeec2de0204aa7dab9fa960e09b9da507436fff121de78622d267b43874be7b8541f79066e1ebd6cde6c223617d7fc03398b891cf80f46f700902ff0f6400b96fe2dd0cceaaed6bf2c95f3bb66010352b3d3e3c6b99fc97631aae9f11d671b2fed069e1a55f5c58117ab926238bccdc54d6cfe2597301c428ca67c4d07ffde35923ffb44a36c8d607a3cb2db3bf582a9b7dc8fd0bd899a6768b28ad801d3fac38d928e7fc604595a9c89afd43652d81b7a8ee23368a9d88dbb375db83f73bd675a220f96c64a980120aacbd23c81e78402c950b3cd5f379b38c5bd9aaf9e1fd43b4fd63788f438605b7af472774fe9d7f349bf9d7be6d363b718f8628f3aa2c78b6ef25b5536e0993243de5f0ceb62dc1ee60c257e3c40cff3a33005a51dc16c79213242248ce8c7e3565838e38f1183fe8ba47fbb8c61f1486ed6678d74f1a7846d2fa6308d8371fb209622e3a291af983f24b2b183e199872fb863e0c0e2686d4566d0620888a5c194f32b59d59b2b0f0ec795020d7ae4e4400f399e8a49f81959681ba44d99cadb6cb6087c1f6f2680ba5a5bd29e8aa867ee73017996dcc6a93b2c4b2a7e10b468232a20d79ef6728d3c76a0850f799f6baba86b2651e6d75e8febdad71f46f9bf6638fd7d9638617aeeb92dc7866bbb587636f8626f198d5d60c0fa1f88abb0e5ac186cd4c51354c980f1e8ac2c90730d30e585a4252d46f87da5be7bc74501f821144de6700c43e52201027993620f9b04f82bdec153ac1dd4ce126d2cf083415af33403025f6ec391a48c96c2e9251246622c88c80ddda6230ffdd4198d130b8fe4568858824a174571262880e6ce1ff2270bf82f443b1950b7f75d73bde42c10e2dd29889b5e2359250640be1285a041ded2f5ea092850c5988caf4d03bf6be85a7818831df5f18b88f5d088db3cc6d8f8ca48d36de28b960f64261d5e9d7e931f657ef88f29d3285ad63dc789a9dd3a387abc8a0045a38c1aede2f94c1b20c270892d33554ea4cf71ab8ed30096583c9985957042c75161b58f158daaa0b3e135d2f0f3e41c335246418508562509ac6f75ed30e9ccfccfcaa541d6a73308442ec4aac45ae38a89538a81f405be040e5218c683c2f2c72583cebabbc675a0fc37cfd921b5d885361e5f4d29c6b791b234e4007f367e4791d4518bd10e4dce1d2ec8589c78d2319a2c84f3a325ee95a18fbd3ccaf71652e83d2133f940da21addef78c1d6919b0d932c7eae20908fc89262bd48df34e685b3ce73bd71c146af6dd416dfabed0caa170a9ea6c6ce49d0846136f64dc4e5d8f71b4e4f6c42a0c2c75a8c586dd8eec1770189b8d16c1f4abd3c30218ffd66c317f4838ebd1d9112aa367722ba69f79ca1f9b644f1ea5e62984fd44ba8beaa84039f8996bfceb84f21aa8f7585209163002822005131e59c9e3b9e3779c8e2a842a294b20a74330b222ef27e853c1f5982f9ba9c97f653833e55371725875699f882b3fa233d062aa0a100907e1f8890e635e626fc384e63dfb2fdb477fad8dd7fc85fa5078723e899e51944ae0a37533c86e8712877f4185e675428b3d926d5afc78638c9224e0e7efea31fc58353a780d48ee0925f73c6b8e0b46e3d7295dcd4a90d81f480cd922ebc2aaa551ae9367504200dbcf540cea9e603464dad240eda57c823c519b9c04aea8a0ecc62699316ac0ebefe60a6615d9688c34b89e12bd073299030dc37bf99829623a90570f4744adeaf026e523f4b448b85b11f37f185c5aaecb643a5156990f90640249423a1e6818b173bcace20a4713c2da217f3ead1e1fbc834d929bd814b5c6031216d97235372e332c4204f4ff855743880c0f195247692daced14b4ecf2d08fb0d399e74843518e24d1daebd8e89c8d20234f3eb1c74bdf94dafd3d1452072425310ba7c705b6cccfb5643eeb816a401f4da310a1e5d3f95abe3280384fc6ec431a4b5087bb2d3275c9ae770ff83a489675ec672495399ea2899772bba29b48d7e3d5e59989087bbd7a4625d6079e36b5e237bc037b81cf64cd00d44dd07cd8b3103f160dd75ac3ce6a08dc8f9104851d3beee2f02fb012dac64ceab245ed88828b532ee558d2a40074b235534af4b01142a884f8bf376320ad21f31b8b4071e26dc5d9f278d612e3c2d74197be443c1191acaebe6a94dc5a0302c4d001fbe079c548337ca3cf85596f43d5543ab3332324e23aa9a1ac8afb5203d37ef1461a4f3e72df909d073cc8da23df3233fd8decf9867079838b53febf683f7935bddc75b90728361fce4e598348f53e073eb0f60df712637008a104ec368695236e9b0a60c5fd3f877381b8337df30ac046c81de265a04456e1f531376245959c74c8903c64dffb25debb407a5d11438c1042ccd0280c80140acbebb22398f5837962e0c52913ea14b2bc20f7f72c6b03ae82fe3e7e1b21310c0902e7eb6aa50478c99264c9144f8c1e62cadba04fb244f44e6014434aa8ca7a525fc9505d0680451a33b7e0cb556481b3f62f74ec06228dbc48b51381affa25b45582d284c0abf5a5795b9e35e701b5ae622c9daa3263751f29623178048f601f4312d399a9d2391100ad40e4a223c23cd8c48f7965950a8c07eab7534f394ee1131f7720f368c42ed9490a1b75fe22742039d7212fafa1a1f9470f92b0d58d1eeca07a8a3889ac798aa02564f901d6ec48b44cd85a241b9c6bf740261bd8e863fe9bb6d65a0dff1eb678f1ea75620942b3981071348c6347b5568765b410d591dd91f66c0b4fe99140f8134ad9c12e4200bf761b408a7edd5ea3e9647f163aa1e0d441709df5cc80c711244464a094c36da9613a59f011171ff7ca45106dbb73a1f5969aea4045e31b3b117874e28b480c9504bba622fc627fa3ee33438b029527636cd0d585f038533893421457110a32754054f2323ad548bbf092a7b5041771d83b11d765822cb0351aed0e4a171d00b5db14449c89b35596b7806038aa6db001e7910516bd3a0f1468de3c60e56bba6026a25de32fbbc4516da67eaa23fbbe4eddb9f6d94eb9fedc5ed9e2a58a7abbb752055129214bc34d842b725b31a10ff80253df240944dc2fe4a733e727991c589a2ef76c23f22dc9f072ea27b8d6ff4966a08345100b8967ca331a5e963ba194399226b548aecc9a471b8a9cd80069b2e1affb1df323db692953ee1b46822f2c152f359085916783800aa85cc7d09767055eb97106870f50c480c8b9816c5568da5bba37d1d3d6378c944262209c35ff965142b6a9bfae7ef22f680b02b94012528112ab2dbe44126cabf80d8098b111ee38f61d83eee1776524b11483a3a904a87daff01e4f74beb073ec5b9d9838dddf1cce8c23fb634300846fa678af7fa467ce11fd69d3d2d312ace3becbdeeed1a60bb3b25b20273e35bd0471720c36747ea96d18e0769de2b190cde1cf9afa49fb09323ea079ab8422ccdd5f48f510fc1553ec97ac42270afc9f94608e517907ff80910e981b2d5a546364b55bb653246e4caf220984bb9e871aac4485bc6896ff08ad76e6a319665882a8f5886f38d529bc42e67af430f039857fc6c146e66b336e31455d33a0742da43732d82689da4f1b7d66fee033b5966d389b2c1e30877fbc0b3d1c62343cfeede4bf31366ec09e39d484742cd8b0c34e64473384a129cadf9e24148514249333b445c080e1972308571250cb4bebe5a8dadabcd2c038de7d61feda0980e7a5b2d66683324a6d1f93a458c2322a0c2518adfa94e1769b2927abc7b2ba9307891aa8e5257b941d6942765403ca8f101212d0b650db3624a4c285ab4f0c81508143cda1ab87f37240204948425811513d707742781dfd07f8c83f272e3b3141055cff5b0bc2b9af419ee15a4d1c3aa506458aa3eb6d6cc355e33b1d93d34a0f72e81575268ef911dc4bd2be2c8298844d25f1ad7b357782d5429a42f2fa44cca4cd7f4f119a50dcfe361e006276f551cff6a2b10293242011cff32e92e9c344533c2994208f4c869549c96d8ca321cc25efdf00f39ed53eb8612c9768fb6b2f19baa148a5b3d0de40847b742ebf9971266dc64d1cf68fb4eb88a082f7998a48c32baf62a22ab2bdf89a185f5a57660e4c44d7906f75ccc8d21806fd271c8a787ef836ff3c47db033d30fcf46cb97ccd7a53b14e7774c13019d73aba6c2dae52d205f55ad19701112356d1971fb51ffd5da4ab7a53e0db279be7d8548a418b4fde69db21c4c8720a4c4405dc5427eae072110c2e4fe061c5c238ad7ed508006e75f3984b16b03d73c7826aa63d23db5df6635aa556d11217c83bdb22fddcc56f4239a9b77d8f62f51638e05ff0fc6be6e75d28a570aecdde77fd44ca22d22315af2df8281fa533e9fb2a142fa9c5cfc8389a772287af8462368904046ed1e2d0b0dea346a7ffd6bc6f56d09ca5f5b35bb8d7c48ecfe8164dc8b4683a30741ca57bc16586e810033d849a51cf6827396c5190b101351326d6e1a8ba546f17a9cd86c823224e56157fdcc075202c90b6d26e62be12b7318ba828052abf770c5355bbe542783cc39a45039c82179eecf5b0e5373415e9f5f6802c6968d632c2827af3caa110e8981bf8841ff2404ee601bcbfb1319596cd3cb28ce668b7e0be5c1d6225110377604f9efce338bd41398fd0d2e04997e2282dd3778122586b3ceac13ab58bd80ecbc9c6d52d0752233830664018f6220afb2b9a48ccffbaa783e41903d991f1619f43fec4a0f08df0ebd503aee696e60e075c0076e219b6f1f2c299931ec7f41803205bacd81ab6a395e3890ce5abc6feac6e7f2eeb4f2bb55de3478f970e902591b9f87a9d9511ec594ca3959131c1d45ffaa07c8cebc71903d5910c6008267f5bba491e18c9dcdcdd3c13923f7769494d445889cc7b0d6a4c48ff7606e7411bf618444c2f82ffc1ceff38b4d6543615787b0c8e53c6a57a6599ae1dd57aadaca5290e4893d5b87bb7614788497b09887c35e4b14a6ec84099d96b6f5e5793f3380dfe7bdba579b297d5c45e5eb5dc5e2712ec28bcad65c1fa941236ece4babbccd706e7765ef1622f8b5dfb938d9646ae3d949a09f46794634fac2d7d2b0c725801228241db2ef8f73e278af27706cad70640a3ad3d43defb9b0f189a323aa3de5a3b51cd4e63995c9a0cefe8216d6e81bc27f5f96dad6b63d0e25501527eab3c4614e6aee3619cf23c77ec62ffe749f36fe3d7dfa17f5d99c941c521f311f89e8e320aa04cd8d1cd0d76308a5d9a536bceef8343f34645abde4aa7097a4256dcfb0d45b1891f25f35fe592d8b6403926ca5fc72ca4da0d37df004260dc2b2c67aae102cbf61f1cb79d4b507c45f0303f5f84cbb449d1272a36ac36fa48d2526a6201df6be8f736ffdc1aa2a8992a1e5b1508cc337550508db4dc9c06d120731fcaed45d44df3d3c230e06a396d1ab492b3ff3ed012e74ab2df4f71199657b998628a484a2fefbabfd31ad4b7f440a258dbc232dea76568233d63fba01ffd7d130efe6a1b3232aa99b6ed27307eb438525faa8cb84c54644dcff6767e0d0f66e65d9b6a579a905e761e682e9510257b9c265670e54b9805ba3e60dd1453a977c83ef926db342f2b5ecc7de4fd399b8d92065991959b0c0d4a18d6405e180003d38a34595f75ebf18ffcd8c58b87b295797aa96462a14c0187ba326f6c96eee8b8688b54aeebe940622d639c127bc41b8cd70ac9e38da232840f34132d9794604ad852688c2036507260262a56646748226b2737eed5b1c17e7d7fc984ea019a0d889fdd0e84f9e384f233aa342632738724c88e0d7b214b43b1e43be38270b3ae19264d8c2dae4c796ae10ec1a71198afb6b2975fd4d1e4bd42a86c486353ece288bb252451ff4f455162c97f8be79c055116fdd816a65acb922f1a03f1507715d4488768fb2da9c580c10e34bb1fa77291d143433575f3487689c5f3c79bcf4601b2aa84397736341c2617a1cae9df3b8e6fa6f1427bbc7e5ad1e184e02a55fdf14239c77c1287bb331307facd5abccb2c0436654985e8cf98d6083de7643f617ad093241480b6595214766bc04a90aba3902b223477f738c7c3627a6ffcf71621635722cbd8bfc1c89ec45bfc8f66a71d8e031f24b2e8c948e0ad780e040290e99e70aab08dc3fd88745c7510fab53f80678db0889b2dcb4b3604b8b59e8251b328ee077017c1adfd610e27b96ef34deb20a5ed65752ad013986fcd0ce2287312b2003be2a014efbdfb637a85603d2dca46d2cf480e0370e5c8f805c6de6592e2e8cfbf986360e93235632dc1d03e8633c87ec1edb1e06249ad98cc016a7be5080cec72ff002ee0b9ef1981cc9c81d5e414761b218567df65ebe6374dff8c441d142ce4da60db2fda48e4178a3e64e808d194bebb30d16bb75600298e5640f062bd8508ed75eb0bf4601d0d99e08592bd0fe36c1e39f1114e5be04725d0dc9b3052aea8fb144863512b608295dc55a9e9e986bb1606c398c6b8ab129c6383e19d3659cc2848ffba90ea540882badb9641a42ae607f20fa81fe50d928f303854f4e5908b666f9d94579000a6e94d5d199ad28825f4760ecd44c5125ade787454b1bf900ee5403a5e70429a4dfdc4832d63b1058f4793a6fd908b275989806d6b3ecb7370600623ac94019dbea72e493fab941a84a354a75c985aa3fd65f7335e04c6b34d9968e5a2828328c30718705da3a671e89e27afc8a5dd6107c3c1c44e041bf8e223a1391431bbb4354cd3a4029b4362a7c9f6798dc8285ade3480875e6f9eea557bf4be954deebca3b5d81b8f4a25a2bd838c61a6c63ce6cd4b8ad204779e268a065eb6dc25d1075f8752301d3c194d9162d8d90c9e7c483efd974e6283250ce97c02ce22a959d8b092175f81a66cc591a4a2a112c8cd533185f4d54a4e2d0ff12d823906155f832a0cc89b2dce65af25530f6496c5a8bba36c0f69a323179a46dd6c1a5cf73414f1acfae0951512e5bed02148257a18f30e188ad45b68b3cc6115bc26b6326b18126a2e5b113b0514aaaf071b682a94af1fc63cf7605fc9993264a6099adb79e88470444ab2a659d0b635013a0e577326d7e55336cece5d8380437071a36a7bdd33c7469888cd3eee5d308084aee362f5d4f9f7f7571d06c8478d9a2297dd5391f04a969abd778187acbe466daba1a7d96614008420c67794ed6502a3a4aa016032dcc99e2270e0957e90d61f7f3d916e6a441bfe6120f405dfe859f0c0de66dac3a72b71487a482040f8552052a0e44403594b8be1b7460d25cba4727fa8055fc58f179c1193a1130c8a5df010ca201a80f756aefc1b46e6260ec64b178aa39f859408455e18796ba7ef187285df86959813c72c6a71cdbc4e64d7b2ae7b371daf156d9a36c4d26710f9ae0b3b1015c0c8bc870c3b800d9c01f204dcd5389256bb46ae71693a3ea53a91515bc5438a9602d0256170b95f102e9aac8b7f3f442457ada4938c50e7a9a88539ddd12d651a440b4839584d480bd63b7316e68e08f159fd7c38da6ac63b4f2e75ffbed674c3c105d8c770f503964ebc7881b478079a55e2027f41bab89923307a8c12cdd065f9027a952243ca66f1418922e214fc42b496e77d041d84e9696769aee8a6c445913f0a7bdc1146f13b566533ea6bc1894a8b3a78cf35042413b82447b263fe58005dc7cae6b8508276135c8baa7017ed24c3e4762f6cd5fd8f4d303d2d58a5f911b3dd63729dc757dea36d7c2454ee0ff8581aaefc8e39129ca79fdef00a9ac1a731a82dd3e09ee983b7bbfe6353c2951b1c84d546e91d6540eeb818824aa20a4e241969a1a0347e3d917fa1eec699080ad0782ea47acb3a6c23b7a932d086675795a0b78f77c82d72f5487f1669918f254ec49b98128c31b05fc1b974e6bae762298983dfef7ad1ee719ae301749b9bb1903bd1c23ce6ddd077a1728c15028c36bcd2e07ac39159f0053af811eeb81aa41ab89838e59f71bc14c099f60fc4e8823d1c13240816377a0ee988db1ed23c400e6b264ba4d57f3d090d2f6c27a25e261049633ace8a82d0bb53a3c00080547eb29746647e68f6fb6a9aa6d556bc6e6b34610204ca0bbd9d1f29a43f6c089a1a5c595361831c35bd2949d54c1ab1b9ee3f2833519244c0489bae24dbb293be62422d2bc6b4e62eed5c8f93b73397a49e631edbc525aad80f62cb9df656ead23394b3307909ccf71786595207f02405b740f9b55484a5f0ca522aa492c4c2b63909943347ff01c61786361388ee00932e30f3b461d915dceefc01db671e22665bbf423e4d7435b7fe17b2bbe59b05fbe7507bdf4457bfe6ac66d42f5485531b0b88a66d790f80454d1649bab70722ec0b1c6b520bef1ff757e52656f6620c01798335f4210981352a1073ad189035565937a2f3c169f26f00bf694d0ca1c93ecbd771b4714e4640f5f20353ee54dc4096526f057f6de1a1186afdbb85fc55837a8fb3cba6370d1a4d78dafc128c0b2600d3b831cc2fa6ab557ce903c8f22fca76ea26cddc850e05c5c7c3954a0cd0ce0c9c92c277b3c7ec0b4e6411c5e0e14e5588bc75360a9c10cb2a7a29937fddee89f086ed003c5b98c48f9e7b71dbe4f9ffeb8a1f05e7a14b1faf6f36897865ec81d6ae2f9f23cc0bd7be72d0a39e3acc1164028856df7540f9ad90d0df8a90e8ae40f715cc38886239ef994488633423e1a806be7e524cc5670872b5f1a51f9e8a35f71f00f967cf6b2404d01d28414b321418282754330988413cc352f4b7f746351137b88be237d6b69f2c12bd53fa794bbcccfd92b2817207fd300614e95e28c5dd71c8dbf98877abe5d202551a6fc4552a6f797361dadc46bac5f9fe4d7f883167f1e10e5f8852fe05eeddc2e864ce3adf2d434eddcf0b0248d1c205c4e0456573830f12b8b8fa764e88748a0a6481001517ab54c7c6306bbbb0e2e100f924abf219a85ceecffb00c441187935cffbec7ab6a1324f72d206578c691b43b60a552db408a4d8059cc48e81c591a438be7d1c1077d27e356b5a4ede95cf9200a8f56860cb279230c6aaa738992e4dc7f464057e62251ce1a6b09e6db8d8a77646e8b044aff828a765b7f7aba8d33ca61b6c4964901a98b179ede97524b9b2356db59dec6e32a5bdc7fd0d48631150c38699a75190515eb0b68434159d50552c2b8240e6b1b40e1f5e4eb74a279f8035f2ec2ad6417fe2973f1bf7675baee96e652c026e8ecf0fc6e533ac90446461343488e6e733a25786fa60efbef330103b6e5446011ea94134c4fc30b93594c37526df30923e68f071db6b85545b3120669dea1f0eee1f8ae8b54b1a526630b4ff962426628a2b76332ce46c715b4d7dd0a58a482012bff978791849d0a8ebd187ee648e6a72538d658db25c3c20b124f852126844070c38798416971ac3c82324881683dd00614fb268b8d6de1e68d8e7c36ac974ba9391c59c7ed87296b5737aabaaae1faa4aa462f9553b511280e1ef277228cf702831e87f83bfaafba647dedb9b8e9f986f6da25942b108fa82c3b72e0ac09c88c7a838ea4e927a37c5f54c2cc89a6a80c30c1e2abd06b2d87691926415975786d25b1466478d97773b4e9a057a529bb7b756eb9c05e7572cca1b18b5655a2dc55ebf840991a3c1a7cb109e03d084bf3bcd4806fc5e2249ace3d87dfb89b9dcc8f8486a1998ec6852a6ba9c0adf2dc707f0fb7922fd31beb57669e49ccb2600d6193d5883e18ee91681901cfa5329bae859a89f8a5cef03ad434c2cff2dd17afd07dea9751290cdda97301d9e08fa5bec4105b8747b97fe87792958117cf849901578441d3a6f2d02d007983a2855b20cf2c5425a5c79f146474b287c044928f02f97b3d715534dfdf04cf4c861542141ab75f006db962f717f8ec97552c7a99260214356458f74b00a5153b3b261f94e02feaeaa160ade1919dac03e000da5dbcd8bf7232beac63ff651f30da2be8cdfa8c1f2cba58c50ffec48f671f5e486811e4ce9c2e5b1c9a7ef47d20e4a9371e2e8a6d39f4171bdecb58f67fd3acbbfed7188ee1900321bde9661a149d7e5c9d0bdee79150c7e05ff405223469de1911585a7fac2f4a7a48d30fe7fd72febfee60177763b62062ae2a71c30941f82866d66a13240bb34055984fe8ea323f66ffeadc2cb38a980834647eb3575efb531820650f85ff6651dcd5970ddcac1c034ee44661e19263b3173a0e396558abfdc7a3e00db359c4b546f60e5cb0599c66b317f5611721ee163b250f45236339d72c38fc72cb5472ba970c972af30deccf020167ba311721355be605a8e3b05eb4ef72bf9a058fcddfa8563a8ec40fc948562470bc4abc5ea61b7506441b9d435a2c3bc188976f9ceae19078611ce1708ee8596138bc65d25d167127a304f834a172e757b256e76e583bc663f24efaebbe83ce63ff273138950d4aa09adc6ee74b782a92ac64e58097a72fa78b72278d95698967a959ffc13be92b4cc603950cdf5ff43d373d4af9ef7ff8d6c61735bdab3ba9dbdf0a5662426571fb5a7295d4f5c4b63b5dc31e767092b05fe2fc8decf3d1348aa623b11ece9536e86a952e9f3e6609b49f9a40073e22595de5d8369a63c5ded29044f703b2bf7fd1a4e90d0ee59f4941827d89a38ebeab8ca4e1a05a1099818d6fb8fbc2a108909563d11145708eef584f14b2802a92bddc213f590cdcaa3170545d461fbd4073a3de186e1cc33686f9b36c36471b3a1655301b9210fd78920fe303d96c37304711404bf2aa3d9371ff7a3fe880d80416842e66f8411d2d9a6a511ab66d08435489ac87232ffcdd3408cf16bafc8308ec34442eda12c53e681174883cb0259cc98e8abdc02f44eebf220027c98542dacaa867267d518e1ac5a851eb89822df7fc7cce8e2d5ccb11c71ae12939eda1dd3f9f95aa42667751d1b88d2ceb9b3f8d6213fddfe52317c8b4818f66789dea06d69eb76c65ccc0af5e2ca040cd054b39e352264ee8f271e04bb7b6baa8618cb003e163f86d04b6a28768180b75dea0dc12c662de833b30b5f206bd9ab932322bb5f788c9d2a8137ff1779530ff06edbb200a4b05504b51da1ddea099e98aa2658bee0fe8b075fb98bec18dc35d08eea7760784906a469e274989cea2b477404da46d2f16adb563bd5749c127cbe2a1f6cade697f439600b1115ccf825775121c7de1595f618b13ef61dbaaed08c8a7c1225423730ff64b1a8e10ee01f39ff2e18cd5a653efbf112840663eba7fa523108d8846080eb0e6cb0b89077916419910b3e06413b999350b15588a460a0f5f8d95d94578013cd98b35e31f509058d31d2bc55775df4518a98345d59cd4c2bdb46f59b35d9d7ea4c34d9876b1e78345c883e235d6ac39f7d89c99a47ec09a22c979ff4e7b34196677633bd489e6da4b4174b205562b75a467faed264cb023f8747e3669d5df308d620c6b00a98c813ee0578a63c3b47adc87a119576857acce77b0d3771ed63531573564e240d0d578e4b430a6a8612d05747d532ff4abe2e69c9304fc8e30137b16da4d6873fac10157584f6c91707832fd433036afd5ffe34e6beea8fae4dcfa2c372c37ceaf9c66505ce4050039dd1d32beb71df01a37761497d7a58f30884e4cea24e0e528245225e7b36dfe938603a89bceea80d4e26cebaba9e5f170b4a0c7b278b8b4d5dc22026c7b0293245a07229166c5249cecaf4df379e056c0845a90a3a9d3d29a4bae835b760323307bced0ea3a67181846806545a0988f255d9664c18cbd573d0d2200ef4acb352db665829176746a06012a528e41ace6f2fea02070e3b01a5e4b31587b5c70c190ef5fd8d58da6c7ad95fd9dbf4b18ff59a44db63ec458396522afb15fd5d362404072291575a6b8bb86ec6b3a723a95f848d05e95c0adc77510712e550783cc32195787b0edfa5fb04eaeebe838845debf1e1015826beb05388c99bea4d78c46f0add1a297a4b660bd07d221401986345d2b209d01a5aee0184327045c1f8460a5d1c1107003087e551c30c594783175b4733f4e74e6451177b3be047a9228366783b04299ec007fc40e5a4b3219d61f9ec06edac692f70ecb4235f313565aacb72b6bcde4869c9f7a9e29a2695ae85704f333590c5eb93e276020c6f518f9b7857d9181d4487cac1f42c2c4b0ea78c2aa27200d90cf1c76383e11c28dc637bb4088e4412413eb5d89af75f994eedf27b8c80bead0ec3d73ad0d6ad769174596cfce2eaac2fbbf111b8a30d4bf45b393e0ed942d81cf21aa88c3c924b03a115a9dae3dfccdec07fdd05f6de5d24c029e06b256ab1a15192bb7681b0a0d25a1ecedd95c87ccb5feb58f9a400edf05ac7fc1e6911d41f1d57c3f91604a809fca04542527db0a805d08a64cc4bc439824494df694e214e3f6081b4a1d20acaa7adfdeb163f106e5871a844303c6e54778ddcf202d019410b013d1369f211e8174b20e17d5c5849dcfc2a372123e2bd1d83bf628ddf5dde622149991785d031599027ff885b4f0878f600e1e072c7d5e0801d1c949a144f6c04fb23afdf6542618203dc2cb8a412bb3d231fcdd74ff31b8eaacc7603c640c361690e659c69ebe7618bf3104c7eaf2b4c79f38932721db2446ce9214a986ee8e28912f3c2989ad72db6cdf4145121a34e6da2a8aa4e7d31e427883f6391c623593d14edb968d48dd0a0367cd44d66f674caceea3106d3dcb4da63c4770b2201672d9370abcefc85f4ce98fc0ebacffabd30ed67d30fd2b219ceb389ca73ef10bdcbce2cc2a6c09bab486c1e2d1094dc88584bbf3ee655c8ade975a91b97457d9e33eb14c66533a9e2401a00a9d30218434fbbf1abbbd3028d127b0d1038e91e2cb4b985b94a7d0289c9911f3a1e3491db68f37796d60985ea390f3deabc4617f616b70029ef269949f725571b794fb5147a29b4649a8101aca74da9da279e5757b16c4dcf9c7308e05f8d3a798e72b08f94039b0bd803678a68cdaa4842f976e457d5d7f669c2d189e51d7804ad2162c908dc50add289b254924aa562dabaf5c725ed5d9eba736b3a7937d1ac2ec63580156bb17af81b18da30d97d960b141322e47799a767383fc0b23823a9b263187c1fb2ca9cdf4bceff64bf527261e37d60d94e0299e4604bb035a409099dead983d800305dc232b04284efef5f12e4b8625785e23d6304ab6c3d343813dc574b72c01010223e723fe7579501dbebd32324ceee7b451e98304fd46850e13685710046323be119fef7b03821af87fb39a423fb57dfbbd0d2097aa9a9af29b3c21714c8623ea0432352f883180d4b6e893818fc3f4ebcd3dceacde0a39c38eaca919d5aec1aa872cfd6fc0ef5d5c2b9cf84d69359a3918ba38ca914b9bb8076ec2959485c8efad0010e5e4a5a050e32b067aed4d592b051e55c43bbb198b17f476c61d41d8bd032244a457db651f731a1abf3ecaa19df554e2f4a744c835c3c29fc5ce93d20ea3e6e1ffd65c293a307f22159ed9333320884371d0001d90490c99dd625cfe500fb65d5aed53cd63d3f20110b7518362110e1138e2d8492abc9db033823b3db4ce142629838824733ee53f5d0214599facc8c738dab83784197a95ccd40e117c8f8a7118de1d95809113e3fb0c65eb606bec5c6f0f2e6c0355f47c86cf3965dd60e2d5acd1287cfc648b0ba879aaffa2718fc113f7ac4c734a97ab4c66c79af0fcf83f7433e2a263ba802b88daf0c863980ca3f57fe31e61d792c4d857fee4515c74ab21df4f7b0fd06482efafcaeca7d1c8c1a016f8d88d119e1c36ee003271b0da304b0382170e05fa7e2194e73ebd484f1afad100a75435bb50055f32c85e41c39911516d55aaf7018462f75b05e9aeb89427c968ae2ec0621a7ba83fa7ebe63d5edcf1d30437d0583bc730a571ac8e61841cfab5c3d86d566213195fafe288b3af51005b592888ee0ffa0a4c600c4fe446298548b4c1e2d837c5cacc1cd537f348ebd972a0909f4d3e771c5e4c86cbd65d1fcdfc9a17fed57beb38c531967942b79d4fa7d90705408b51422dc07507fde1cc529ebadb97544b86151eb1c6d428758974f06b069c0c6bfe674941a888d7b9100a6bb06a5064fe41b690fd97931d874797b4957eb683cb713a3f9691e679a17a617c8921abba63f151bd00d4ac90696865d048aa010020b2e0fdc77b74357aa81b6d040628374c1ccea44df11194a86e2ec50761762cd6bef8815158899a19fcc2ca53ce043e5b5f58d0a94863b9fc768e1ca2c1b62ccc9251fb4d321678839296d947bdaa482c18ebcaab293d7011d62b3611bfdfc27b699ca0ea8865e117a383bf9d7ef53dda861e75221ffa7ac41391cf9c027e1b6a07a527606fcda2b534fc17fef3bfcda25d8ac5c330601b1d9383e66e10b9f73ec0b70e4f939e2c2b2cc926bcf24896ed827f635721eea82aa7e4d9f8d649b1fe3bc5002ee235c3e7e609bccbcf3347298041b28d0340def87ebfac1251b476c9cd22696ffce80910d546c6fa6f73aee1e6411e4625400b89042d4dace2f18de7434839dde79fcbc38c778a4f3c1e100683b95613b73b4372b6962492f3d16a62ce0046b5816864401894903708275177024e24d18b80670af900227e47a6ac4600da54bb5ce180ea10549b06106118513b185d7c7e5cf8913a421460c570597e5f6c67e4a28f4642040c1d3099dc48d1837ca9f5ed0dbbf60c438d8c8d79b3aa5df6f717646379cf7a8ec0d944bab3a8b5673704ac741a788f4e35a895f3988d009f7a5897bd171b13a25678cf7d235f48967a9379b3214c7373c57a2951ade1639940fbe385ee5641f7b549c4b697878a67d045e12190effed225d3978f73083c93f7e17c87d8323cf4a1fb44cb8ee0d70c10483bb832f4f7bc7643ce373a869ece25dbf8f8d013f4120dd6f7afbd96a809940a02db4b63110c0ae2ca67bd470c33a83b86f13f5d9f6fa1e722b6a9233b934ec8211f8275c88be67afd2b59413b3b00b0af525ae77fe7af1dce9d5241fddec343f78e3c356b210b23f748d5828fae2256f8e9b21a335c0cc8d58ee9bcff0e947cdf9e411dd4dab9a34e13c2cb4bed1fb66d908a22abb990019e2173eea563c50abea0e436487fce137b711ab1fa44d00f57d2ec0fb27c6a29b78c50e775bbe8a2453bb897fe2daec2666102826cf9bad2be062270d8fa642e6f3eef4785dbb2076840f5c9e69d3a12b45a606a93691c3ce3a9509489d238d1f8c04d8e2af97b06c02bc4b780a2c9a35329bc45ec6d05274fd729111ecbf561b21769b6ede33a534c0de0948c00d33ff42a32d5529c817a71a84ba61d117597ef42c962c3b939e457727aaf7aeaf6899f7207831d5a0f7a41f96d44dcd34811bad040b4147b1099bec7fed9b3a18d9bd8801b59243136b81bd68dc31f534f44fe06f7b51b960f9f352cadcb4101bd4855b984f0886022fdc3b0b4f04a1974fb9c568fd3e8e7d90d3945bb12c1ec39501bf8e8fe203bbe8544031428fc416cd390ba2d33c25dde0716c0fd859c4203a53bba999da60e76dc1c0fe6209f28451322c7aa7bff167be868e0f582160e8267ba0b0bf2748d0adf2927b7f8e599bd66750089286d7d45ee1bb94c74e7c2a1eb33e4b49d82fee4cc9c48861db09f180f15a91bfb5b9bbf5a0f2e76b6e69865debf72afbda0119f9731b8256a5ccac66943ff4f6527b117ec9c98c721cbb93e0cba5a4909816f17fa1e4c6257f1fdd9f877a1b96649631107fb47405be1d51e814833b092fc76fc744f96fc81132d1815a7fa367c7490588c7bcd56a0c00b5d38ed994df109fa0282878bc244c07938aff822b93407133a3a0c46a02cb30c81398d11847a260963d85d58f36b13da9d5540457e0b2f22ccfb9cebc91edf97b06ad5262c2295888fd3f54d2f08458274095e25dbde888660b6cc1f5143085ae8c21c9a50319a4318c50933904ba5a0d817d2213b84383367d5ee01f33ab926b85c851178647a10cf9950b4a5e142cd5c1148dacd5d17e511e9d02b7e8c23f1e46bc480acbf276ed952ce7da774e008e2f77727e900f3964eea34abea8c2de9279cacf7c0b4c783f3ffec900fec8e013b8252b7f5bdae59bd1b7db006470f3a40275d431ca29bb39aa2f8c8de39666f916d068c80840dffaf81614d6386188f54c6142c52fe4af5e95c684278543f41740242332a482598f0957bcfa2dc1a07e1016e77ec0aa75dd1563c5554563500e3501ac5a28084342c2d0fa2063bdd7c0adffd4fb8078a70b092d8a7a6962cc2453176a17bac5296f1d764275c49be8f53fc52ac308f5494615c407ca317073534d4ad8559e7b1f14bcc1a8b59291ee886d01eb2143351e4ea76d39a78794a5da0cc6ff91476ce7b19e69f0af2b4fb980c0995fad24d476adae40493ad68381aeb66fa5d24e9d36c0ddba15eb27b73db328ad474a59f615d6be1285d71ce93c8eaf34b0c72276ac3732877eac80b5e16e0225ffabc5e42a4485c18bc10c233d24f84ae8bf31d42c33dc63e8d2b1882711af64492335adc7cc60d0944b72f03ac58ec960c35d8929fff13ee14d06763383d160b8ad18878e8b18da98654b546aacdbb7c60700fc92ce4dd32ba93262026468e2200b3613696b4f22afe282d90d9321374024e8262f6b543d2e512621f34a5c6d3cb28be23f60c4d28711bc12196e1854a84c1ff8ab16038f2ba05c9491676050336492cdea0e8225749e64404249e7c14be3e01a7240810d11dcc5337136b41fad0de1b90db92fa68e18d26c90db0d7932db44e49325c17f68204a9e7f2ae53fff31034284b5ab804b4e0bf3e11745da9954a7518603468dc34066200ded8048acae195818f56336239b232b5a8f5eb401b17e004489824ad81fca0c2d4778c711c05e0564869a5b4d75b33cfcd28c5a3bb85fe5b6d07d98558c4f36621cc1bb576c6481cc73e5b6dcd988ae06b9a22d371996da2fe2c305bea95982304bc5058208b9818de2518bed0cd41a4a22644068ffc8f66079287d1fa5c31ece2ee4cc41dcdd88343adc958738a196937388174d81289487f30b70d837eaa92dbc600bef3946531e92475947f64db586dc5a1fa62f0ec0315e20b13d67cac39eb5801fc2f37ac08700e91c1c31b30902cf2f2be41528873db322b5b83a4905f21c6f4a37e4ae1371c576571383e63179755c052afec5bdef64c87c9b1bfb2bc561bac93a9a4ea8aa86b123be1992f7fce6f953cbbfe8246d5a7a8b19fc3c1177f071a719fb546821ae3bf241d71dacabe6f444b5f7881fbb46d609dd2768cfa69f817f9ec750b819cdacc4f37787f4b0e6f7de671b1ffff1fbf942015a7223d7e9295ea01bb60de6b45dc3bf8c53ee1c2db30d6ce2fff9729de2b356e3a30ab2082121878c82803b0a7cc4f2cffb2fd380e39a84404cd543870af4e4afbc1cefba834d23e18fc79adbe6fbbb4696d83f3f05d714ecccd38cbc8452f9410ac6dfb6e916b8e1b0b60dbef7408e522724a231af251c0894106859d6acb7ad32c350f123f870d7d888319d6b48466b1cfa25d26602f10ba6d2975c8ae02599d3698e51e5a30049ee16a784a3ebb48b02678fdf7d201824dd5a4ca7b2fee7aa6c2874d0d27ade3e3749fc94c511319a95bce8ada2d98d08c1384ee0dba5672a2630d8dfc5ec774243436a415bd2a3fa4f1e5c0d78c6886ef4a6c4ce5a75fecfe87dd2a0b43609cf05667bd1f97e811562d6619c5f20183698e1d2633326b0e12c766463c8c58926d85aa7de649a9c080e092b7313d8946d85e6588505a6abaa39ff443e47438bf2b79ade8077fa0da4c72a03b9ca31d1ac0466c6883dbb5870fb11c1598b20f4c84a2c605ec6d214281756858d18beb86c22c6c041dbca5f4dd96a801734effb389da387ab0245eb5e991f7a8e9dcf292b89a77e9e0d3cc6c7502e594d746c0786f803d22ac529aa0d9f822892d27452247f7b93b021811db34e578e69f8c9887ba62d45d450df93cefcf1fba5d7d013d70e7f694ac47aad1293bf55664a064ba78bdfc1c8a3285d8c816022c0f11db33021465241a9fb7ed46dcc57beff82bed924739832245c62e8ce1435982317808c0c9e2118d73366fa01559b20806bed5a843268f72ad4cccbc9e224d1267358388b1de7c34412c86bb183e9a0af30665df3cb81d3847c7888e7a8871555fc817315510369582420643fe7263e3f0a3344e96a8fa6cb8044772e87c4027c2181e06f0a6500e70b4eb431f91a39a6563b02f6cb1feffe5d434c99a6fea1dbbfbec194e1933f9aa4bac648720afb061211428bfcbccd4b1a4de7e1acd03e1bddb8a23834b4f25a821859be4534508c88873e3b5df2012fd15b98e10023842791573e360ea3717c626eb58f7b503171d1560474dfaaf64fa8503d3b41b9ad6b11237ea36e81329f2f36d717a6c5fb3e94917cc6510b6bd2587f153f796c6e68cec27404794316cd2400db36231bb7151d55136653d4d130664ca495aa25277653d18dd0de94e59e387abb9ea864499d33f312d2257aec96fc0ad7f7a5400537bcc36f9fb2398b14aae52dbeef9322c3e577264607817ce1da5339cd862d9109409bd3ab4b7079234644c060c6560c6da9b22fb53ce330512568527579b3042c74eb726756594dc91b46cb7de1ddc520128e66bbfce6a155539bfcc1a64485ab06706348b52963cce047a83a072b9278f10d1c0104ea14f79d5920da554d0739bce3333337440f35e531849d712302340117173d6e413e8ee3e8956344653f9920159ced9aeb0148583f00da018a8adcf2c1014771999729ec8623e5dfb255cb5e3e6db25c6c1228a4b5bdf7de524a29659232b609df09b4093d72c83b07bded03f97ff1845a6d1994ef7bb9e2a58c4eeebd979bdd68fb15508aa8f7c0afebba4775dfafa03ed7b5b3f7de6bf15fb7a005668d1328fd00a314a2b5863518f58592b2eeae20de32052938fd09a87d0aa81fdfaba343d219bd4e7702e6b8ae7b4ca0d5396e9b7a95c282da4ea5134ec5843267ed705771ed7057b183280ea5629993db30c678e2896b2afbe4b68a718f540e6d543aa53f4d90a6001bcc0ca702a6fe04aeb80af5d3b3393d45a9fc277d85faef59409cefb757813845f2e3a0bee5074de75651c1ff03f52a8fc39bd3af843fbe3fa19efb1b5418de7c386f4e05f4fe04766f1a3d0aa85d9b827252c375d2ecc4652a99429b5228c3954aa6d49b7064d639ffe4882593e94da6ffc1f2a5b0f43962fef955e9673acf667546475f4ab570a7a095ef54c639234202e847e8c77586663fb31158a4fe15fab925d58fb2a8f4dcec546091d2b7944ca56f31994a2a9b1c3a666bf2305d5226cbf6c7da1f2023b22532a19f9892a0990d9ac994c866b43579663c7a3679f0cd215bf3073f52367f7e342dacc14fe3a9faaa6f791630553ff52cafbd66e3315ae86686016f116dfab3ce3dfb837a956f01714acfbd0ac4e1bef42c20f738269c2237dc971ea77bd3573095c3f4ddef283df733468b4ab2a010059ce2c97453c0ed57c0136c4ad9741d972204048bc9826643443f43b39fd989eb04c60703f339cc0763f91c7796f0c7ca4ccdeba0a4b08c6116762b2c2653a5709cb0ac9436930aaae707364e19103c3bbeea8c743118ac33d2b17cca8f32e8034929aa67f992ea378ee35ec5954e6f52d5990dc817dae2c00c6606b3c31e9904a574ba06f29851c3f48f46c2dd5dc37211cc877cb9b686198c9cc94f9f0030399c3b3b398735f6693c7f86f1186dc457b435ded81516daa8eaf7a7d75179d3732ad0e559c0964f8129bf02967e07efd2df0994837b97bfe1eeff4879ee6f78b37d4bf8a3f41bf72ce0f65c05e59ea2296553b22850ff07924a29d5573aa458c1148a6884270683cdaea758a16ab3eb5cdcc54575626149ad702a28dd6742a1508f7279965f71790e64e93a96efdea563f915708a8e53e426f5a8c751fdca7b204eea5134deb9587b59be73d1ec6b61cdfdd0c6c585e54790b3698f1ca6f0ef48f995dfc102a6ecb37c8ee802a66cf8d63ef72d9f23729ad5b4fc113d71042685769d5ab6f565983395a37b97bfe9de25fc51247f4bf84315a6eca7fc0af72ce18f5498c2618e945ff9940d6f527e2575537ad4971ef5dc8f1e057aff81fa554e53a4a0dc26f194735d2ba14b2922cac96fdf8df4d3095362fae992f9f4b87aa468fa51ce4a8ff2270e2cfd06a27c8ec8bd8e1c91e3bec4a1fca95442316ddcdcb8e91acd572a07f7dbdf6cdb8fc21f27bf6dff2365fac669ed72b9be194e97ee714d772f55b7e7e6ddc175c3e9922fd365fffe0d8bb8e12dee29e7b3f58fee29bddc37d44bd5d0867b1d52e47e878bc72567f0a64f8ac91999939e949a6d4ca18ecee8bb22a60d7f715ffa1bee4b29dcdbf0667b94f0c789f69af423efbb227c45b9ce1b9174e7f2e971f55c271d51b5898292e252a77075fb5a4f5feb49ad2ab55467ad951249c1144d6f6b7dee04ec7e03b912caa77c0ffc2412e95148298f02a77802a2fc06a6bcf7c02fc55a6ba6294a67adb5d65a6bad74d65a6badf5fb6a8ffb2398f5bdd64fa995877ca9d3b3fe2e450ccaed8152fc407902a5697a36199cbb447a1338450cce6de9055336282829cf4daf04a6d85a6badb5d65a6bd539d7bd196cafa33d102da2502ba4af8e5a462913894545d334d5a6d2364db5a9b4edf42dd3d39123aa5e478ea80a7fe488aa27fd8d05b09001ed20aac21f16c04206e412472d2c9f7ae9a5340db5c27195e3344eabb5d6ca6ddc73da08b5b26ddbf69b16d2785d7996d7417d8ad36460b495f6daa7696d0373a773c6816efc38c81c66e7b62ddcd19235178802898664b19530c57d0b2a4ce568f9954f71e18e9670e5558ffad40ed5a35e857a1aba8138484e0274e340f716e2b0002d7416f0e453a0fe1530e55120caab9474505e9348a3ffc4142845150fe5e4f529d421fdc83422e9139494d20e4f45c9d93c45094a63323034ef2edb99cdd60394525a85f650e606d0a61a0998914f79ca3d4ff5dc7b214e911bd57361aae2b878e6404df58ffea1adb92359f4b3a63b2c32db26a5faa79c8a09e53ba508e92934775a28c7cdae458aeee9e84096e7c0d4cf14ac7cf729403df70f4e919b5e0e29ea7caff252e4e6cc0766666b449143323befe89f6c830c02646bbe40d3f628b3b393bfe6af61cd7d1ab73d5238f5f655a00ba8b5d0a7ff5ec7f42a3f7d9e1424676436cd3b72266fdaf283a6fa675324e48cf6f4b51064eb03595062535964440b6d902fbe47399483e555cf2365e3e202b6a84022f47cb976f28fd365c351af867bc9f23aa4c812e214c18fb3f25d2ac4413d97cab1f2dddfd4cf43014f34123d3e3f40b0986cee68a09f9d1f994a0e761417fd85963ad024a03d7e1029c863f2c77c4542f285963fb7cb8ecb0e76d971d9d9d3e5886c7b6a06baef7c19a4399264376ea0493d18bc20a844874a5812440a725250386a5290cb8f7d42a63a40b488f240b2d8c31c432ce2aff38211511e8816bb979b7692b64c2699bf0611a09efedc19a218a82188884de641593473b373d3a3bcaaeb506cba0ee5bb3775e18f1c11e555e0143de5cfbd87a91c2a2aa7e7421c963fddb0fce97152d34b69cf23f52acf83253b38b56f3ba7720e6bb8c1c7d4a13ea050ece043738d1961704080ca987f5ffee4cb5725b59fca2815902ff42b688305268b7e27a701c6d11ee53cc028a7b071c84306d5c7ff38acb9f8f108e6b69fcaa18dc984d243871475561ef5292dcc917a95df910a557e074b78caa91caa4ffd8dea53e18f22daff60795578a3fa96f047ea55a1a4ac5c7de52c18cc7b05d48f02499f026efffd09f4de04768f0272fa47af437aef2dc87d498a28508a1f28c5295a50ee94ed4fb41465006ba02cfa9d2c0279c8c0f8ca94839d44034eca18356cd31e3d72d0db3f07d9953ad992a12d1a47983db4f5bdf6a7a7de93266ce4d3e3abd9d364d3b7e97ef6802adffda9880e29eaa4fcc97fa014635c28da320a5bc6be10c24e790d3cf90f9ca20a28450f2481349425b3bd0ef9a3c8cdc96f9ff20571a3711b1dd39f5e7a299b94d721c59450d2935053d609fc1c3a6e30e02cfa1c0d2734cb12dada10697f0fa5f46e689ca3e18496beb2817cb9c1ac51844f22ce1aed1ace1ef9423f06245afaca71b8dfe3be7d1a4ce8fab504b9047a1b91f2dbc9bf5e4c59d24a514089a66c524e9e7a291cda6cbfe304d43aa4a8a3a3f336291365c64a3a3aa3ef5ec77bee39ad859e40b347ce0cc9199914193699c2f9f241593b1ad4427a9cf4abcda31e2dd135ac1b0df59efe28b36f2465b5fca0f1ce4f1abdf7dd731f2e97b8a557e9e6a8bbd399e4fb72961fb8e5bb7f5fce4e29adeeeeeeeeaa21a49452924c4a241ee2a48c39b3a64f5cae775b03b5b4d67aadad54bec8d98b3b17e81ee44767644c0ce60fdb698843c670c0ac563432ee2e04df0f35f7dc35c40178e2ee003c912fbea3e972b9e48cdc3397d37dda1d298a3f6d6863ec4add08df53777bca647bce30bcf5396bfae83d9e84fbe6ef403c6c1ecbc2b5dd611c0bd876ceab17dc612e972b88e822e8d9de64be26103e87f8106df72eecd844e24a669090ed4e83cde2adecacf958aca00363bb11866c610925409cc0828f384a2700418c2e1021c80b3f4944395dab9810465880831514ed20322164051178828a7c208e1348023e5378c28e0f7c7082083e8916b00420f05c81052f82f083e8527081053128ea096276856ddb64eced65cfde7edb5e4be189bdfdc7b3b7ff2908eded37af665bd9806177af79359db31481351cec86afe6b6adb6d8423067c998b3e496ad8260663243ce925b88c859728f3236ebc1d65e7becd568ad9c05104062feebd5648d0514d8b56f85010b216aac8c7198949db71c760515326cfa33aba4a0267199d7c35129e39133326c9ab39cb19b3e6b6b529e48941cc17b2fbe175f29b3b99744d4843c6576bd4688a0041d2e84c098428e114590c113848a74823c21162961c9685e81c4a6bf9291f04d945de915378802149bfea7a74e8c09a6a9d284a24dffa4e3892ba0d8c1074ff0200a1e3e54c081155238c1051e44e7c2126c8022674cd3094b70b0e997b2a6bfa294de504a7d079bbe0ca594524a698a5743eba378357586922910209d0a6f8257818520226c7f1db464fb137ea0b0c3f6879131281861fbd358b1b3fd715891c511d9366374ad02b6e993667041064963017b9461bb1362b0dafed90947d8fe1f153c6cffa76208dbabd8c1656678a1a48a1bdb677ca1e4082cdbbf4b62885b6b13c0d02b29cb2fe3312e0529aaf8c2c3415bdff7ed29abe8b57ef66aeadcc1a6f43115b126e86c5fa248cb9880c4a65f7386fc20041766510ce102081d4174a1029d2540611603d1298e2fb69faea03f18993d614c80c10e377d3afd1b80c363eacba11ecc014c2144b30ef4143b98792e6ab5b5d65aedcf5a6bb53464dc6ed70a5e1ce8b637c4815a9bb3753c055aa70cb43d91beaaff4d6aad7532a10724e108b36b1d6ff8f6dc1687694389c39c16d75a6fc5f8a98871a5a0ddd1459ccb4073bee59472ca9f36b42ddf9ee8e80189afe4963ffffef56aae07819c2df3bc3f9fa31ef52c9ed3ba17a66ea8989f8a39fca18398ed890e9d20be92bbe4315fd853beccb7a0dd79bb846cc8963159903d723c7b3e8d2d6349665ccf9ed927d7ede5cbbafd3f199a652ce5203d934fa3932d0fb2912d0ba344b2cf0ca7cf8faf263dd1d1431833ffd0300615e8510363ecfa63f689c0efb0ab0e8b103a653f7747d01f22d9c7085ac6d75230a57d106de523246bfe0f721134137bbe077990077950f671ad37d9ec41cf16e4317223f298bae76f61788c8c4951b4e7cb711bda53c61e37d956b427e7dab31347eeb527f509f2b30304044c486c081911414346af6248c72e8199ecf9d3886d849c2132a711194a64d8e3f41162329b6c618f338c3d9becd175f6f77d2b8d482bca3eb23d9f89c760224c8489301126c2449828f34c9fe9337da68f8f5d4206874cccfb4efa6abc3ffb0259988fd5f118fb9af6655f2f9bf5675ff6a70a39e32f85b611291bb96fdc258e421e4468cab281b2a4d08ed17761caa67bef4761ca897c353f47f4a0fd23c31edaca3f9435df674ffd659f0ff21eda92a2cf0f506ccfec4359f3c1c83eee44c8194ab5948f1f423be36beb1072267f081ce61ea6a64bc72544ce6860086e90427b2372b9f616a6e62b8814da199442fb05c40e103b4b146ddfe119e2417a8ac83e16967d2c6c3a0d753bd713002470944a3a539eb1ad31239b72630e625ddba78cb13f5fda4de3ab496bf0180b1ea1fdb5165a86ed9a6e40b65692e55426f9b90318db7516b657610131c8d64b967c9964bb5cc276036cb741674fd890c374798c5d3261517841ceba9e9e1544c1648f53c7561984012fb66b41af562bf9a39ef1f018f935726bfb02b6fffd13394383dc3d4ee4cbfcf9f406ffc811e74dc6f139e2f41d2d5fe627d11994a91bed734edde4c738cc81d23087d79ceadb8be348d2e98b06a9d6c757d212394942e467cbd7485ecd11ed2149d774d23d6f7a769472c0ddfebe3d1c29b07fbc1a24b6dc60db7f050bbdfdf84a8e1b10d7755ded3aeaddece46934e6a41ca072b23d1c3bb0e7d3f88a060d794bf9e248642ec3d6de90912f32cf9cb3b423396b482c6560cecff61c2470d061e20052ecd1e0cf91bc9aec495f691bbe9bad1bdd369f9b548d4613ec198e62f245be2645ce5a4b4d59f275f460c4575224f182caa9aba44900c29e3032ea85adb3deb0e70fe91b4a7bde50da59d04b44c136e06d750bd2c4a0025db3beb536d1be85ffb44593e9a76c198b62073bf4811e651430d8f41b20b78ce1a067d3eced5fce131d3d0c994f5b34305ac31a546a5d6aaddfab7e07ea55429c9647bd0a857a9cff2f4cbd14f17c14f8d55abfd65b6b5551f98f964a2da80a7efde9daa9b5ea5a6bad456e1d89ad36e58f7a297e60cafffbabaa6febdf5aabcb7fbfc3e53fd5e3fcbbfc0ed5a3429c96573d0575941e54790f2cfdf46a46af320a7fe488a507c129d2946bd48f7ec7f75e88d3f2df8f5afe7b9c7f947d1e2e8f7a1eaaff5450b5525a6badb5d65a2badb5d64a714ab3f569adb5d2cff47358831f4ce547bdcbb780297b431b95979bc629d82365c31ca877f91d2e8ffa1daafffec1540e6f50ef127eaffa163075f3bdea3f8a2fbeb6d65a6badb5faa85596fd6409f3fb3c65653b954e5466909df97a2d99bd2eea378ee3384c009a02700aa85eeb0c7b8aea74d7ccc78fa21a680bc70c47ecc2e0ea03cf0ab8f982c1eb851a41cefe686bbe5e2890fb4fce8c367db92315ae84a9fb2b2fc51d92b270eaaefc0eee57429c2237df6f8fb3637bd4a3429c2b451aa7715bedce0f102cf69ab3949ceba4d8cca55b7a205afcf7e1f2d2a5f2aadfd1f22e218ecbb7bcaaa5e571c2570953538a5b0b98294bd3968f700bb10cfa0f7f94d93276aa20f82e2d1559e483b600e0a57ee55f3cd307e8870f5f15f9bd362d9ff21298f216d00765e1548e962ffd8e962f85384570c26ff91daa5709715c5ef51c373b00a47284aff23b5cbef43523f0df03c19fe1ab3c0f972f3d00c0294a2f75ff51ab95006c1a6e8a6b51ad3e5c4510299a3b73488fcf848181c1dfb72ff8f58226902faf1278822f9a3cf828c2618da76e68f361ea8261eabecb971e270c53f7ff5bc007431c973095e3bfe55337bcf930753fa5a97ccbbbbcea53372eaf7a973075c3dba326bf8dcba7b430b543e53fc429f22abfa3f4ffaf1a41ceae2c8f7a9dd47f8fabaf5a5e85f229f0e44d291ecaebd73979d268e4fdc956506e53277a23923e4149f901f2f1e5688e52d4a37eda5f6ed7c196311a20b1e71ef1cb673064bb3f7e01b1fd7110c7af30f6d8cd399f86b9e7a7fffbf15462a0a578958cf9458030f47895dca2eddfd244cf1f3150d0f6e77628cb1f465740b425c520590cc35e94e5318ca12790af469b861828069afbaec60d34f5f15507ea1631625789c7b0ec198e8cd039b9c6107aa43f9327bf64ece992029d72007efa384cbdaf64e0898130106de51706c240db9d98c1b6e1a899d0c22c08a43e33965f5dd094556397fe28d9637559253e63f4976421cde46b62c3c82fd7f69f47642bfb20b1679e5c43881ee509660f3e509053347f982b1a3933579bc278504dcb396f396fdab6e5bc79997b2a72d957f9955f2a3f5a8ee62c51e0601cd018b6c8123591a34d2d116d4912c9313065986cd26e09a2dd66018ceb721894a0e9cf97c7d0d7ac16e44c09b4259a366658022f64eb7bdd1eac17b6dfe02d3bab806cc948296c7f1ef246f7fe769601c9f22ee45eb3ad858c02baa7e10c2513dbc40b3d778ffaa22d5b4459fe6f89424bc41109a2b91fcec71ed1d257daf7c9dccbc35926d511cdb93c46c763b6f727a22deffd72210e33744fc5ee390e3fe7eea225a22d8ec81259a2971cb9d768da23f7e2421ce618291bef73441dc4951b37d05687a8035de47c4aeb75648417deefec8e058267080e3ab8f60db3afa625da0eca6d8938d8e6a331fcb57dc290482959a0af4d42bed89e3d79a4ac2d2cd07a3b0d21f4386113467518ee315938ec9b4cb60fd99061d690c2d09cc9144d50093d6313a6841e659091198be1087a94b14007240f2b64cff7bf80d4808cb1efb6883d7f9457d87e2d9671e7b66debb6addb9ed26ddbbca7a217fed041949435376bc4c27c351f839647beccbfa01de2ab1e5f25215f668cb2a65542d6981f646563cc76584705e740db278f2679bebf266740f9e2efbfcd56f899076d650ff26818ed2c5ffc5bbed013639ce5cc8886d19ee1ef407f40b6a41824b378c1155cb4a4174318c2822fb2a0841688c4f99d2763eccf7932bd19487b7a33b8dd377ce51e04f9e20f0a691a195f790c35d03694a161ca49e99c944e7aed90201e9e85382963dac9512929f5a474160f44291ada6cff4d6cfa367ee32bd7401f9488070c4de81166cf70d4ec903df1bdf8badfebdecd37b43b3cbe9a22702abb8e9390b3654a793aadd669b597fabc2670b47b82e0e630f589ab7fcea6937e9de52eb67b7eae48e81ace394b336b74e21d5c6dcc34acb4d9b1ad175b6cafb5d65e190190e539736d67ed5bebb386b5d65a6badb5d64ae9d65a6badb52f7d65adb556087afe57a4e7d357c9c05a6badbe8269ca501ab5d64aa9bbbb530ae32e43bec877ea3be78d6bddb5d6fa75594a29a59492548fe8f9f45333687bca1777afbe916c70ab6671d62cbe95894c05ab69160751af6683e83a4ff33c6f942fce9a0d025f7cb3662fce9a0dc256cdc6b41a55ab18638cb10d42be0ef4521494147a7110f7534a5e59f027e5aada505e1c84bd75b3b732b1514ac3295fb4d7a86bfbda1a84942c39e0aa755aedc5596a5e4d7eed729bc3d47891366e660d9fb9ff5519b44f4863991b1919a964fbe75b3f1972f861aeeb3a4ff33c6f94f368e4d5d41fe14d43c6d4d764e82880eeb70ee4365b6572984924afe63e495fbb7ad296ff656f86968ec81a1587d67ab3f669e3ca1ad656972bebfb56eea4932914971c7fb94eb9ba7fedcf19eac6f7afb53597bc1afb25d39cd15ec2e48a8c8d6fd6f00f80127a3ea791e0db39d4a75dece94940db359cf22567cfaf6d59830c6d79c0595e0159c3bfc9963317f878086192292336167491843de61eba288250173f4c7491031774c1d3c5cebd9aadd48b609b177ec05020d2887eb84f906521a127ec0859e103146242b21fa0d023147b554124047b59c12354041504c1484adc2010d1c4107c00848821421001848684881f362410e1c24886d0c21186a0429e81d6b68c0d1105ed086db78c0d1164032aa690f3f785d5636aa50df055cedf175297564a974cd0efcb19acb5ba0df9a3e740fbf69f207071d690ff5fa77c91eed65a1bd65aa753aa1a42cf7749c3484a2761319d565ba9bd9836c063ec9592b5e583531e99423e61cbdfefe197b5294e1bf3670d9f36acd033674d535fdb648dd2734f5bdb6b6cff4903739ad1b6b7529f764433e50ce3d943594da4fce48c6f3c7bf063cc7d7266b4f18fb4d0a41fe12931fe11387f280b3f09bfef1128c51ed006da43fc143f0c5ce81166c77a34f8d67c4e9f73dad03c1af0ab8ca0ef1ebf1b424e58a0c7d933aa6cfc786efcb3081df82f206de60464ccf6f8292063b8c71eee6cf7c999b9f1733054cb5de7759dd755eade8d9e8aa3f0870ee2e83b3c7b3c067760063590827627abc819faf8a50c1c8260c2b06b57bcce75f54332d050f88e158050a0f09d2b00d9ae20856dce5eb0e714a262cf3dfa102d614073487a00e0c2677b9ec74514b68785207cf7b97bceabe9b4e4328764731c13226c8e0b1f3677854d4f11bbc24e7e5c6f58e1898dffd62882125063db212aaa80832a7861c888d59c41912834ec08a55bb460d32da4a0c2135f85224fbc3a2cb4c5829eaf4b312ad460bbffcc2f4cf04e0b2053685185498b2672663efd12107dbb05d9b232488cbd85cea630f942df06d19665c2cab6d8d41ed9d406b9687b288b8e76dd82a696675ba24dbf6ea165ed428f96c866415a220bc6a677874daf0fa69d22707e32dfc6aea00e1e98c82349e0d9f26bd51246c6dc18fc474896c421f403c99236aa8d4de3155f30755fee6aff56fb16c6da2a6545382983932167e8cb9751005bfea35027da0ca9e597a13282e6eca496c7b8da737b5b05b0e773396b6d6386ac311f6f1bcaa013d49ebbe00dab7db7707cd9f5d63d3f77606a86a00d60e042c27ac071d2868d9f8ef7e5bd97864a4ceb534a6db5f6daf77d9fa360ad21e8f60dc71cb60d6fe8f6dc9cd76e941adb7bbb3cdadc5170bc95664ddbd257141ce58ff45de61f7cf3b54fc35ba55b198e36ac28e1ab912f69add47a0be34e4a4925b7034a299058b5f369b5b60289715ec438a21890189018e83bd3ec230389612038d8be2123f3b4d3b6ca00e32b7f986a6f119ac66a65af6542cbf8bfb8b27c38d3929e95d33a19434393b386737dbf5e20518e88900dac101302c266416f5bc6845690c5183fc88ca0495bc6b220e2aad07acb5816b32c8230deaead94a601382050fa228b1fd9edc1a7750622881591ccf01429704115a300ba322dc44036b34e9881679d3b9d048924492431a2bf2c3bc210538a22a420a26332222ec8b21d198fb3e41eb3cec2a7f445f705198d923dad9689a04fb68c09d1e24a01054c85eeb68c0991220ba1b92d63429200d32a5bc68410d9a384dd233a6f191352c41ef396448fb68c09112227d177cb98909dd21716e8e753f0737094479a98b97ff50982a004741b6182fadc96de04ef96decd0cdf1e7ffb3ba5d45271da39bd4e84a0ef73de49195a9e3b246750b6ff652267e8fb9b7efc2f17f26e61fb0d6317c997098664f9fb6b87f9851eef50133dcea09da0ebb8d6fab566f97287eed069e71aa10b337e66f84839fe4aa8292a3ce9f0f482998ea40a483669cfe7eca9d24b5f940b710d6dc895c02972267056a10b5604899309168488899c8b410517ed4ce054c2164d008927d0a14842e42c756ba7acd6ea919d41d8e20b44e209b42e1842d45a6819a79e138cb64c31ca7a4d1b73fb9f829c766e38fe787afdec0bd2b2eda6536cfbfc3a448f58e5837cf107c7d0299f4279b94fded4c48cc1e126d8b4d13d044c4e6c294362fb978e9036e692592252fa29f9c8993cafe001c9b5fd4732dac253f41f11d156e97df4f408440173378a9d5ea3980e47b1d3e9fd4750c8d629c43e94e5ef6902c856e9fd614631da2a85a62c4896bf45c0f670cc76143381b1dd74321199c21b64d19e8f7d3c73dc0340104cfc38e580fbf669b86f431f80f60db268e3709c5f82b9ede790f60571a0638cb1bbd00423eda99520607262fb9b9a982bff207b2c2151fa291129f92c99364a251ecc253e7b24d5aa5732caf2d12868fbeb70b1148e62a7516c8e64b3f4b3542a85a797a989a9c844743211956e89e7749af183e2a61f70b7d1156d75a1cbe639afbdd32567dcdd082e062be871ba968cfec3397b0ce6603735e2f522174e216739bd94524c2995d44a8c25c6aa2ee81cbc1a1fbef229a482140f7a9c2e57c1f6af31e30d32fc5d057246faa0ad295be5b09a487c253487e6cc5763ce13e3c933c4e51abd600c599a25a7d5deac6d1ba7b5d6baeb4e929c24399d462492d627282929a592c9743aa95c151515aba2728292b279d5badc75a85c773286a6a19c25596f97e29546273f9d462592499f7c1ffd3eff4c1fea745251f93e146a6525956a695151f93e146a652595626151a1b840bbb8fcffb7c2524299564e2996930a4be988140b0bcb8a2ad5c2e2f22d1d8baa737917176f06fa5ecd7b351e565f81326233e88c19337cc68c39230c012043c68c190108800004b05ab15830c010760000402763c69c2143860c6f06ba3329d7cc902f3460701804b062c110038d9701ac565f3a6286ac140b8ba56a61b1582e2b2c168ac56255ea1386d10c141c4a6d8df4ac31da483a3d6d74b386bfed3adb754ac0d9b64b6cd09e33b44e98d3f78910b445c2ed8faf7cdab047c81afe9607ddbdd7fac81731f468617bb43e3688b266942586b461dfdf8e21673a3b4459d3860dad13640d30648c9d42aefcddca8abad05661ad4cbef89ba6d0e3edb132d9ce7f85b0fd47026c1adbafcfed61e95e763fa66e4f079620effbdcec346db9c7dc17fdebc87b1ad7dec2e8f62a981ef5eeb93d3dea8fdebb1321e819da227c75ef0874f1f6e8db737bacd6dd8854bdd088d40d15f5535187d7f20ce929828afaa7f351179a74f7151a56e8e9d1909dd0ef56b876d6b9aaf15de528a5b55a2954613b11c9ce62181aed0c02ef0dc92cb63321ff289bb09db44719b3827a35f869ad565aa723aabdbfcc97554ee851c66812b0188e0acead85d6b19cb5febeffd54afa4c9f9cb5febfef2b1fda7271f3597df76738fefe9498fa74b432c63ea535d0d6f4e1344a22f21af2c5321cff7b4c1f9f3b7d2ea59752958f1e57abe7a69c958eee113fd8fed99ffa631ff9e2ffaac13d86032fc2d8343058d6b44c29f6f1919176b83fd7a7c94ad5053de58bffa8adb53130d1a3157ad19685c5b67f157a31ec901da2adfbba2f3b6487ae1dda7e84883b6dadb3d65aeb7d2aded5fdc14dc486866c68a26d18723dafd0748f7ae60328b335a2b45ca1ed1e75cb15daf7a85baed0738fbae50a7df7a83dcffbc0d090a6c286a1d8880a5a8a190698077a94b10f00a1b56c397ac3197a80f015cc0689a07fefd0268e6c4abd18b0d038e4cc071c205be3dc21d685edae85294647e871e503c46ab5e2baaedb9e8adbb60dd930e28293d265a0c73cdaa325b46fe9e55a71adf8de6a6b55811448454d78482be86aadc5b8e6f70a6818f018f93c483d72a6b5fd6ba02d191919f288218996330c90b1b1001928a64b9f7484ffa3f4a31fa5b5d6dc93840b09e7da8a64646464680b86981eedcc579a909cd9420b29862da2ee2e2343c346b43561329bcd68cbc26033d86c666116369bcd5c9a132929b5d65a6badf5556ba5aa257aacafd9d65ae8fa923377fb571f6a1094fb33dc10cb975a5f5bd0566c7f0985ed53c80e9d08d3a69133f7fd6d3ca6c763e8f64712f07a51fb51ca1b2f185123a2041bc1bd06beb2a8fd06ea009111b57f65911bb2a5b8559eea0a69517d515ab4fd9d525a5faf949f0d082793737e152ee8fae367e9517a29c5b022b4fcb4f8905e4d9cf4ca1c09e322122ea22d920f92e5ff029710920d482ff9e2610f1a7352cea7d7c8f61bdbfe14467a4d1ba3ed4f0ae231323943dab194e443a3057a24bd48af70d43a7c799b9b1e09e62bdf314978099d710c43f428613953da8203bded3133d95e222a0d9976ee2bc76f7be5c60df415da238b9c655c44598e5d7b2415e55a6f80033ddddb5149a3306ea049ae5111e9b5fd61b0821e15ed69ffefc518678c339e734e0fbff46c34d28bf46af9d147acccc6b44c83e48b16d21cd20fa29452db8d78f0a2adfc5e05d992a2644d4aef1c624bf9324e212ec3f6247c85648f94c9f6a74342dac22c10bda1754aa995b914283b28afedcf35795b6df8b48679e85f60adf52167e2313f726601dbabfdd18b647c4167a16b385f322b43cec31ee7101b1fa22c7f1a2f3d830fb90ff910ca8e0dc29454aa70b59b437c95556648d3c4d08fc6b7e10611b802bcf7e781811ac09ff3e7cfe71952840f11fb4359f3f10e3839d242e3cf2f836710070d207a9441068fd17a5a7badbdd6da2a23638970d72c4acd30daf4a5b74c5ffa31eb2c5fdc1466afdb9cc6b94ce90c66c45bbed0a31a4568ee4bbfc45ba526dc9842dab8e1757206096fd19478308f20f2337d82d01de4d479bdd3e97295c01a6633ee5146dcf49149967fd6e1283482914dc339e2384e739ce6ae0ec771a5a762c903ad901df29565e2ac69a5206bcc9f9fc59e3ffa06da997ca1c1c01299cc85e22321589805fa9fa6247a4e3a27f5e6d3199731861effdfc2681338528c6b72225b2c2d6746db577be2bf23223923a7d8beba02ffb8d272c66b758942a7ec514740faaa879c75b8f654d4c21f3a881a4f5dad48442a3f2a3eabd58a46ce38921ce87116a047d36ff942632c601e33e2d70e104e22e72cc606c21863fc4232aa4184a63f33b6696bf2bc785e2ffce25129b94194e59fb3fef00dca413ce62567e8f6abe4249333328aed9f81fc738615e558916c3b0e6938aef6dc415f25bef2f77098caa17ff437fa478f7f14fe2882c31bd27be10f9427fd8f93d79f23e6d7b495b29f62df4b097f70f851c013b0c60c3469148e9fa62c8a8b80811ab09383f0d06cd9ca3ec0605d87f1cc3c3a5ccc3b94e54908a550a814ed17453d0c15918c000000017315002020100c074442c1705050532dcc0314800d6e8c487854409687a324476214a59031c6204208310046446668481b00c44d6a21faa695bdd88540057e08bf563a00b69fe8a20c14bdbddc9ceeb3589dd79dfafba5c41e973c51df2dc4d53fc224df1bf07d7926923e54285d6c0547c6dbfd9a4542903c06f5f05d5047e13115a92a6c8455210014e30e80a09afbf7782daf200069ee9cec4fcb5d0181476a8e3ebf461da85e2033609708a2002c1b829bed5a5ba9c9d423f05891d6aa3c98c6f5a7e0eb2d9013c42ac890c5c10845cfc763ad9e817a5a446996faeb74ea1a18ed05072f92d369a43ef9dec73a3c06140b81a766b3758ea96722ecad727cea15fcb3a5c1b5ec7d88dc1f3dd10b4fc2da917cea29438527ebdaf9e451335fb5d5d80c3d79709459a4504c5eb8b03d27db6f3d40224122f435a248477324ef8f6b78da38f24a805529a87b5288ebd4bbef21c319b85349bf2602149bf0e3ae9d604341daf6e7f595c0ba2fe7763a6f4868109c4e1dc0d9de0b4eb814a73ebf89744117778e04d69bfd4d2d43819649c9aa9a3ecc9af748688642f6af1f5ed98d494210fefcf4ec07401c964d8c3970c830ff68af33625089a6d96825f084a32e0c0e0d41a4a3ae4c00b045b6bbdaf8f623f62d2c3c1a588545778d44b8058130064bdb28ec1e005220a2909b247ae8f0f838a6938e9178ff39925c75d231a78c2d4f65a7930619b24e007e5e629ab1e081fef1710ee230d9e7e0d3a171ae5a0b1f169785661454d536076dea39344e25ba51dace31c85116751b4a661d0e530743054858080825b9980494704eb9524ea7006c3ce1fc33741793202bb912b1055a6308ca5c0d67c0f942bd320b29f6b9b92bdbc2cbfc9d7d6219094e8e3ea5fc05aedf9eccc55808c35431710f1a93662803741e63a3ef343160a478dfc8f5a2c0af735868d4027b2cf1386dc56b890dade39c703dddd947d599262afe5e690cf82cf062e6a6ab9315c373011ca5d674194764a38e5759a7e1c7102471b02400440396c2a744fe608cf0a247766392b5a65a42326b6a7083d038e755b98433bd2bb7bf861dcbb0ea3afa0eb0e59f0824b2addb0b69b0c2dcb817478358d5817bd4bdb8483a40bf81233dcce288baaf4d15cd22959daec350055a47d6ecd5b8ef00ce2ddfac779e52af08a2d92e38c3793e7a9536068e956eccbc458e15a78719bb61d7f46215d508ea9e68953b46a8f158c21e660535ce0521151a74ab37f484184f29ca52c649aa3ee963bbebd14dc50b77a4c53a616dd029565090292d7afa6966cd41527ec8d8d3ddf37c7a7b777a83234095da3f2527f5b2258051c8af149a20fa69ef461ece0290440e6f761d517c0dad75e7af894483ba9df88e79b3d02e6e64930a3f3cdcd2a43a60fd4310bd786e08440c33cc732a880c5279f2a3d871b5e95007d4654b9c8ee43ecbe5327417bd727b168aa245e726761cac32a54ac13b17a126c8025edc7cd12a16d7e42851fc88633355052b64c44ee2a679aeffa9fef71d003217d74e29e556b1e848a12fd19dbce972158bb4a940f7cc7761a3bf8462736e66d0c83b55c1e890531c490a199c88837908b5a4f3e8cdd5da35e79b4b8aab57e40bba326dd606b5f36c2019a2e94315917b3fed8c577ac756ca1524460b73cf35e4da328b9edfdda202ab865f7e2f34f23d0845023df374a176fdc70c2b78415f80e4645861bc246764c627620a62608e11fbf281bcf6613dfe8a37c177a8c2ef0fae3549e74df93c19123e400905045a42bf484f7307407d98fee984dc3a27018d9456a0bf007ae765a705722ca879097784c655fea33418d6bb832380f217e0a773190ca56f7175d266f21baf965549d72a74cdb839c567293d7c6f816e3c8debf8d131c16f73478a898649be81f2647fde29bcce20eff1c7c4cadd59bc8bafcfc735397ceef392e389a4e415a0ef01d8974caeb6c9d192c4df38da6dfa344ff139b94766bed4a0e7cf31e729ebab41f43c427e2c551d2fc9d8bea8bb732a554d4d8ab89212316604f9245c7b63417383f51507c064160ce9e2eda7c6902f49bac72472f1c050820c5f1ed0b72961d05d6d6a4332c4cd194addd3777d437ec549dcddac1a8056264e595165a0d4e406a5c5773540e1d1cdb73bb66e98f8de843d51bf19a47c29fcdd650deaa2040d6190edb7f407746c3ead87a0bcaf3a49bd912ef72d332b87b190c9ee681cd24ce4e31da8428e790970c96430a682408f5716addea498045335b7ac26f7bea71f1c74297e007aafa4c8567012bcfdc99d430bc6ebfebfb11993facdc71757345296ced0f844f07d482f81a70c5e99386554ff4db606e39435fa25de2fae3370303e3848d73173da2b129119ae8e2ddd580911051a515409d1360057253e102569bd74c0652293e4127438a57ab9aa45c4fc83833ad5895926495bb92feae35bcd325600a9ca3a4cdf9f263f4e59cafe1a7c1db0f19526c48c4edbfb3e308d3f8557c1456c51aa1b892bd7a124f82548b0ceac39575eacb2fbb1a36579f524e6c8518c8e0b8ab79536e955d9bfcd401cf72968668bb6f793b0c09d062f8aebee44a7f85959ecb4caa78153898cea4ef7f9d6b22e567f49f2986892549322e108233c09c50fa881eee00a415a2cb6e5216f3e514cce8e9d1aea9c9b9d46bd1070ddb2507b6bed66dd67a5871a89afea3846a6ba13cee60f71a3e224b4ee480adcc456a4602d65632be926b8d9348100b7a1cd980116bbfd63878e52d0aa0428fbd38c5e6665e2a8678e11092c05c519f32765f5873cab7c9fcbd6637f64407b2d8675e8b9e8bb66ae2fb1eacc95bbe44da28a5f9d42b398a6624693a7a8bcf361901a66480379493b80da7d510d05950a0c6a3ce3bbe309eacccb77016480e9a16169e0fbd48194931e0c0f51a9d16531983e1e1e94c04dc813e2a80bd991b981117197f80b51c60b4e0910f16fe4bd563796408fd030b1f428f3effd26f44861bdcad33d2be9c8c8592c1a351500f018f46cd58a49292957714ccacc7a9f0bb951cb960ff95c1712da13a54ca7c438c05f62add5cfba78190b5b923a5ff645cad5826165b9ef1151e1187a2c2be1832a99955fcc4fcef179adbd729c288fdba40035d08e53644e017b3badb4691591b22b79ce87c9bfa609eade0c68cfd7ed7cc8a16ff48ea0a694d38a963e604a1f9df54f9ac4710573bc4131a56c72cd0a3e0057deb03731e6968478fd76bbeaf9c0b177d2901a45406e651c4251c4a964d3bf6e4506db3aeb0c581b103209c079bee08b352e800c247701db0708714b13e4d7269a67c94ba82001e3aa2ab3c39f529a69276d6d0c37edaf8841487246a23f875e4e74123d804fb6a37a9804a626abe693168b6bf6c247f0ad1ea614754695fb6ef1de240db16b61da29d5db4e82c76e6f5f88f07aa1d2d6bd4c0f1d2df31696f5b8be35526c58608c442c6b08cf12fcfdfc304a8fb665ac049b07da4ea8e3b231dfb6c0be719acf0539bfd3032f5b45d866a8f978fa356262aa9efa10517b3ad26f1e86d4287fbd14193038a2330f141326d412315520aa9f3bc229f088eb990c22d09d6762c56fd13ee8e033e4e1db7c3b3845ab7c64456dbe04bad27a520da5400124ae04fb99009edf79fe8f236c4f8f64ffa0c67c3fc562276c5e24d4fc8cebc5e4b11292ab8facb50dafc0f9a3dfdde6447c14b8775b1f63ed46836f769a172ef6b6eee066d328f68ffa78d802662c4870928e1d87643c721d29a4fcc9d27e76ea5bf930482c09d577b8caa485b83252f7e22efea150af8a1986849b6f406d2611e092e11663a03bf1502772457b39607865d3c8414b3614e82d4a03184d83051a4db4f6f0b977c5e7343ba79c08da83a86c259b549e2205a67c059dca4d738bc82766ab9c8d04a659c8b2fed25333ee0e3d61d2382379df7536c2e72ee9a79803f86dc559469259cb8833790efae2515ba3cae401f2da91e4e9911ef51929dc80b15d4e3c703b3e9ffb0b50934404bdb31fad37f87f1d0bb2dc7f7946c214b0c499c3fc4773a1f9174a5632e5fc4734ce83a809735f044732e22bfca99123fcc2a8dfbcfd6d6f5f32103ce930a50c100de58e937d217503e81f6b5972702d53861d1ec1416f9fd83abd11a228e461025615e1da622eb2c198065b6ce5688f28c48acc25b65d1999fda983a860b308c00cc42893fa8d3ae9adbbd132d5efbe74c52ea6caedf45a061422900cca04fca24919368469c537839008ba95375f3e2de2cb4617cb6728f9611cd6e13a65dcc4484972ba07642b271dfb047f296c983cccb22a3006a23c0f130461e3974071c60ddbbb75a8db078e10f282b406fd5a629a1fb423a5eb80b65a513ac6cbb60ba59dde161c3e12acf455955a29638ea7435806bf9dcdcb9073014c5ce425065882796d8fea7058cc70b1afd029cec0def041935d6eefa60df08897a16b297f18fc7324894f923b93fafe5a7019aed62d483823311230ecda0aef5ab46a2139fc138449644e788dfc0253b7d1ff313f2df92dc4b82ff4c08ff36d47379fd86044ddc05a82a0e6f11566bed764ac356252d15a5aff943e52fec0b8a98891f2b81a18195d109bd3664196e740497a0a508d9d9c59955eeb879bee712a4954d25c00bd04f98a25cfe8a0aee8bb4e1e849fa84d8d0361d644679c73945258f96cff91e4c44dca82deb1bf45a1d7eae7ca05b7ec1322263d36478a6b411d795fe0bafcd52b4fccdd137cd5809c71514d2bfea641244ab539f9773883a1cb10505bcf4371fb0089fc81f909f8f98f16007ccb17d419d4c26cbb44854b80932d0bdf1fecc25e5460906fe0372f8e2b66ab5e98d55b07ae183ec2d803425b7d8c62f11fd04e586937b1628ad25713d9b6b0cfee4f7eef155a48f7fde6ba8b906a4ef5e53c1c6a5aeb385700bc45a536fc5f8ae5d5eed6bd653e81f56161adffe442d779fc4b16d039d2880a01693afdcd161e6f06f7b2ce9f3e070b1a0bfd0a28f9e56d01a2f309811968c08dd19e609f9c139e10a306b677e85a55f952cb9bdf5031d12f64682887a83ac67585168c41960e506311e214868e7d3e2f198f7740e026a50a55cfb71b54e2904002684c2afeece5ff79f0b03a6fcc759773af082f33252dc7363aaf54bfd34d5a34c911e41c1c8f594f02fbee561f96f67aa23562fb8d1c99890712aa1a033c2b187c51f9342126b75ba0765793a0f07944f031240bfeef0e1e209f46ffbd9d70f70c33bcd70c2d106d57c0f4d2c097b460287bc37e4d27424052d477c4ff93bd06de3c9c36fe75aec3a88441c9f75741de6fc88a6af0a47a7f17a50521924ad9d2a93be853330a55770e53526b0432269607c1fad82af1d2c8468a7a3f231cf745129ccb269611296261b1f123a15296445733c3ca43a20601aa17a42a7fe4ec329e8dcdbdfbc03bb95ae092dd3493e651bd505f56721e90bfdbb96c9b14ebb248283dfd2a14e3b1db8596696134867e4661ac920c608e6ee6c0b8216c322bf00a1097e0a4eed035199804ec130c262e0d3d8853f5e851663856b9f9062eabcfb4f1db55af481a58dee90630aade4cf836e9e4d6a2b4f1b36de494e04688aab4ce079cdbcbe315c74546ce0163dcfe94cef1a655e86f0bcb6ab7c99bd412f42a60ba2975b5faa1094cbcea2badfd0978fcdc61b38e8439ed7a32f4f8e47d554231a2cd3fdea54d0a6cf1f2c1b00a0c03a53aa7117b6626f115def912eefd7ebe8fc91a0936e6f930c460aa403744f3ee6a1796ffc72484518da7943663853f43616721a22b77113a48f3862cd692bdb214ea5e9eb3eb49f99008f59db3ea705dadcc1c1f9113f1878fd9f46f6bd01cebd23b83972ffa43bdb285fa5ee75315d401f6eca1343d023f0fc888d745fc8258be1e7cf7bf053694ba7b6d5e23b5d182ea920c813a9d0a05c2407e545cde1014ac14509c88717af79f6b6ce3275b3a644b5031d721a2a6562f067bf11deaaf35c90330187ed48dc2d8de80833e1638ec706307d9975a9348e857247c1f8151eb36f1f8d65dc46d381619e80f3ff6ad253badccbb0bd335a60a499580b23d3634c1478a21015801cf1f0423a44523da2111ca6ce25d94bc08c1f3a8a829fb5212d54ad9412fac7083a9fe86049fd794bbf2a7ec57f968807a2188d9cdd3b23a003909dceed0c69dc741a8dccbfc246d9378593c82f7afe610a7a87218f5892db1d3ca1f3b459156731c3ea7cac2cf7158cffe378e3b47d1c595bffab89a2730df357049d290a714bd1cbf9c830735152c521c6fdee2ccfa5e80e896c81e235426e41e9ae527113f549e508d32b8efda4dd00b326e278c428ad0d9f2375d3d7700b3334ddd046ea196e6e881267cce702d2a94eb6a7f915328bce2adc81a2fa9085a3e98f06b09df7ae6f8d7495f4854d983740c6168f88978323aef124b4b91383ce7351037a3361b5f5438bd59e13022f3229a76a193f78efb3fe73e63895116df44153802fe186a261f05322e4ad3e9c741addd8f1973cc2304cb147229b41e25a39c438c790230280ce4351fdddde13415368681911afc3323bd75487b47f8b0e576237f5e3f42629d5c896663d402a5ccba8bc848f886b8b6eab58528992aa50ba8dc198c2ac502fcb4cd79590f931932e5dcd3be810ea01057d2212d6b77f2337790837827a450e3737e12c26783e87707414598acfd4a45b02e424c81f8c282082a7536976574664ebca556a1dff0bcc4226624a225fdbe018f49aec36265dd933bcea917f785d38176671ae844fa218a4d12edc158bf0a558c7e11002cbf19814c82786c2dde069ed52649adba15c2efa32d84a69ebb51f672d15c0fe2cb78f90c5e2efe7cf8f3472fbf629def3cda2f81d4fe1ce4c813f67818c028c2d7708d3bced0b04f311bb8ecf419d1b1cb8a611e4af172428358c22e79190c0b7db305c594cb94d8e2b5d731a6a42dfbddc764275641bb91a8cf5719987a0d0aa1ad86868a96b92c2f231bf1c17f2a379664fa43f6218e7ca4096ba74559fecc0f0ab721b728455ec2bc976e751a527f091004f9528769d449248e6e310504917d1e1c991685a4abc0cffc9f91aa53ef5e64f435cebe1194a730f5a0792012fece49225c2c897da9824e18f526a0d34e53c402714e49808bb0ab0febe0d4d665f44527a84f7d5c0c5972b488102a02080a7ed4735cc50d8edd1156320ba2163b8841df0ba79c33c0ad0aae5a3f0921fd136544eda24823e2f6d4f0edc0013f65c6e93234cc6408ddb91942e0cf332cb79bb3a024f1591a302865b82de7d96c070ab1189c5876138991b2595c706217b3ef495c7d5625b4dc88813d5d6d9b97dcdc4d61567299fb0bf5f5acefb8d4c095e5134368b7b32e7d966144d0a8e9ef133bae11f50c3f59fa936a90e4aa788b6944f74f9527f673c08815c586d7eb08424ea3a95ec1e4ab5cc1caf12c54df2856565420568009d3e36b2ea3d38374b6f22cc2fa859a20f1b08aaaf729008412b195d558f08fa6b3ac5e92f115fdac746e7365d08b3da9f9e6abce1f02b5fa10fe70a8243b33cd6653d96586d430e7a171ce1c8a2e6e080ffc1c09c4e4baf5405889ca78e125364ca968154f29228bd162b2ad2b701cd22ca987d362ee142900ff6c06cc53077f1a20ad4b7471cabf37a4fb9e8fbb726fc91a37c2cd063d7213f812d12b817d6055504f5c230127862c5951e91cb303192501c33fc973dc056dbee1581e107c8cee477cae73baf6b3a5ead10b7a6056b81e34580593c8fa6aca611f685942c433781e837210caed7a39eaf58c7984488ae146b163ab45c93531bb3bab3528aad3522b7d909b381c22c2dbd98a0f0e329791b38f0c532dd837829e88b232e825b7778e83702b4a3317f850568ac19ff2ac6e18e644e4b904836675a3054dfcc27f2ad56904832eccedc2288de8af10d8d111d6ff401b99016a34bd2b7c498c45e3777e0c1372c13772921134784899288a52d38b5a14dd89bffc346c5636bc21da37797e63a701cd5858439c4b6f2eba1722ac8becdc609da866494b5003a12527994ccd30526373eed42908dca2f27091ce50d71e57b15da1ce7f7c52784d292487ecc452d04d50ebf071c6f27cf458fb4f00888371be3e09d07361725d9a345ed02c5e62031dd0695b08e11e442882218a83e1e5c09ab13e6fd7750f312264a2c001ccf9f40991bb4c27399a182e0601fe15b6f39f01e8b050661703336bb9199e2288b0551f95009764d3f5481a634cf69200a0a0abf80699b567b98181b1af93927ce9de7729f5c9cc02ca60bec3cfef563985b7b150e07d611a20af24459b00acad5a7f8fecd0da01a0083c9eea06d2322d0fe350238856d1e711bf517f98c90f6f561faea8f155bc7881c7b9aab6ba96e2bac8157ac35135c634cb2ad4b7a4049c90e796a65f15dc2091a46d2d1f404e8a622d6fb92542ca48abc670c840a0584d2aa1ff0e7151f002539755c2c42c531b09b2eac82d1604764c682b5bfa7184a2b02ddec954580c8ff326264bf53cb7293187dabdc545fc4f0683500988d825a212b4a202d8435c2974fcaa47b28d2c4208a5e094e18722e961647d1725dd25b91cb83ea2fe823a2bc042e2b345d9b171e24f6a08cc5bac2674c04a54284c37063a782db543fbae3d8025400672cbd352f75b8df4e38b3ad38b2a7a24196e1699dcf896fd8519daf5abeffd2657808e34f577149891d3008ea8986abbaa6803b04efba7c391912cafd65b3366603c5e1308164784c0f2adc5898eb88cb1c90b04a07d755362101a90724082912212f645514ae574938bbdcc896d78fe829c8293d14fac4d3bca7632b626375842b431b14d7009f176ed4c0ddd305b0d62d6607cf39562db10ea3d4536cc276eb6dd18fb3eb0024a1bc36f619a84b3b18c26d0a0d8ca310196ab2d7369b297923ecad96e65cbb4cfce2d904386343138e959f95e634e8c566ed8d6d9d747bdfc707a2e009d3bb8df0a83e332ae1819fd8db20d9b41ef0ce00c0c4dd201e7d7a553d1ee73fae2841aaa59dc96d8a89772c06459415f4292efc7075fda0b2fff28803d43f40610997412ea2b1171b436cc9abea33c903a57ffc052074064ea6a74aca5399f64a88eb31144be2089ef1a294e978d4986e874929cda0f8006697acc83034e19cb7136d8432a34f19ab64534d3990f183f764d6f9c0aca3f121cde876a6b196e4584f143e7cacd14fddadbd173125a6f39013ad9daa5dbcb205a10371738e4a29099efb30fb514bf39ad3f89eb6d580929419e5f194c9c6839db30da9f1fb5b249b807b75bb5acaf03660cd71e1916158452dad6a0754ed57cd326b061f16179fb5076574ade8b3b470f752e3f06618170b363f3e5a13cf74378a70779a83b066a0f16c59a2e29fc218b88133ec69c2d949c5fc6ee1c5fbc4d6d29fbe8caf755f0a77f3e1e78e1be4990ec0efa3bc7dc71517b37021fa6ac86809dd1ba05e79fcdd1bccb1bd965c7d08a1be948b94e17f305db20bf2fbfe7101592a9652fd928f9a01e0d8c7c32befc2323757d1fa42ee320c1183880461561c55096f69e90b7c03439db621d8aef530193ea7e756c80feceaa7c1ba989097f021ed1e72a062e981f2d4c19e376b0bf9c5bed5b3c7a0be6f4ecb18390f9db0cf02cd1471e1c32d37e56d4554356d6400f33df18e5891f7f743977de3299f8c58473f822df026648146270ab7bd92fe5023e0851b5a32c12f7b68ea76a7876d68dac8ff33239c21b38ab4f1621b2f51ec19c9f38385617655a4ea9bf2bb1f1bb5b2c821f2a5e946715c0752faea09bda0b77c38d040bb16b0586a6851eefac5c5518cb9d2688d21a343cd0f5e557ba5b3ad8d27e68eef7b31d9c75647c53619391a93e2c595b9651d9bd2e5ed4c09afcffdf1086aca4c63c73142ab08c921d650379e479338d93632dba6d9d464a103a20ef8d023e26196ff0644b02b0dd3ea03aa505f87af1a0accf33a9b0cfd4db4814000ac38c971122a016ef5666b373ee75919d48fe5dc2415ea42fceab2b695f1651da0847b40baa0037c4cf715c336123022402ea28db064b0d6e165182de343035df7c844f62ca3a64fe9e5181160937329b0a3bfefc58511ecf70541f2d78053d13c77c8f9b06a9d1ce9dda69204414bf42a504e2d343028a14f3b03f7148c076109b55f78f0b2b811fbf13b8bca02388822b0c2303a73d1434eb8f26905e8da38f0a5922fde395f1506563b2c2d02e4fb3bbad76113a46bdd0d164dbc06a096b6c035026db4702327ba47de9104d6c18706216e6ce898abf75f42c32bddbd12271f091f17c377793cfa89a9056cf61374233e72913a67c2ac4e8e373e01c299ca450f8b4eebc871eb6962428e58280d7339348d4c9e1f6fd09b6cb6a0217f7bb3274a20bb855cc4cd874de91541b72d8828acb6460b9fd6c0c0c975756e88d47ae1bf3d82df99989c011c2a432a2d7cec01f9e248e620f98d2b28b895914d4f23de5da09a035e26209811677e1081f43865085a1e14e429569d83409745085925bee0808c032dc79da7a5b0d95560eae8745d1e9dd0fae732fdb1132cd004af2968154ec7841ce98b5be88cfbd0e3cd700ceb40795b9d0c19baf77cd7a331c9326ed77ada491aa57e8a63069c039603b7c0498aaa2b38e3758fdf6247e551e744903c97d095d4fa3d9545d467326861b63fb0a0729dca9fd6f88fc35f617919657cc12125920812a8a23707a8716613e60fdf59c46768e99afa9a6da58067f8469a3f8a1a6dfcaee2b14d0916bc219712903c75f4c6b965ba519d7168886582ccbf58835f75b1455f301aadcceff582e77ce8a2b82e90b38e4eab4e3d21691c5e032c59b3af0401627f5788b50e654959548109d48643de4f514b7c1e93ab44d1746fa4b5afb3e9c2ee41636f894aca81c94991b6f27445b41643ee6bb4ab9825f76783f21d45aa7314922126967f12ce2c9a829024b3a2c91aa3372e4fe0d8738cdc441ea77c1425fb0af658c0b8648388df481922fbd18df8308f0f2d89d2c1150e012926da783e5f37256e9090da64b71e909b395859f706d6b4a23ea97e28e3a8fb4d847823412c734391a1aaa217b3148226798ef1708f6ec9ca5f96431798f5db1c38cc0be4fe8add17f231fb37ca188bb62627285c8871bf199121a0374a6bbea912b0c3525a38ae72d1452e3bb3fd45efc13442cf220e43406f6e984a97636f567960137d288c1ee56476579842d6df4d00a02360a874bac5501cbb69d1e31cbc8d518c35c0eff8de2005d26afe64a81860d0812795a02a77504c04a2acbb34b65bc913746c8c75806bfc7339c893a3a1a5363bfa567e1ef621469ec044c2bcfd0137e49660c663263d2862cdc6f281dc3419d06c905c5b52dc130d6dcbc95f57029e5266f6dbcdf30db08fca995c504d4853ae43987d68571971841fe389c1fec94906420708d84449fb045f9a8e3d5a58fbf242395b2a319b2c928bacd990780a66f91060ada6e678fad2099dd65cb0a4e11f3bad420ee753ca0de6fc7556ec6acba30d40cc2ffa7c23d0b41d401fdde0515b8a1d1ae01d9bcc3544ae32785800df5f706bccb63a9040640d19660a70e4a3f27f41eebc727fddf1c2fcd5a3b5b957932c7f12f2d635d52b2f5d3f464067072edf6506807d580e42ebe23c276d00fd99147037282a5b4a064e1fa225b790cf5dd5e651a5b9f1a1ca66ebebff8f502da4f4883da1d6b004edfb0d04fc700a16678dec53b0751025280b77264de60f8404a4003c5a6c46abd5e7fdc992ec70014596769bbcc3f0e2017151d169951d506691472e9a00617940a9bfffd255a06f36401b54477cce40429d0cd75b0b2ea9429b4415e6aa6d89ef56626af902da3e9ebbbc9963d1f348543907df82ac307a698aeedab746cc292216a5741df8e283dade90b443a4371978105cbdf9d2292f6ad695083f9de6472bca4b07c300359579bc3adeb80370db3ba63060665258036aeab1996c2f9d1d43a56fd35bed1b97cb26cca48f150c69c9f26109de8654eeb84d7e91dfd58f983fa13a998135e150b19847b35545171a7f68db1351597868ecf4025a7a0aa5280b907e3cf07f07d01bc48123877e50c0fc4cfe847dce0735f0182e60ada9be06f46e9c6add7328734a5c51258914f2960a3c06a211815fed62e757389e76090cabc41fd17fd11709b05a9cc82ed53191bf21e428e02eb97b42ce2f1eee17e34ccc19a3d0175744ea41f6246b6d53bdec4aba52c8776c787b19a97e2304e8d939829c4ccb2b86fa8c9b30b9ca4517ddcfacfa11422adc975657764d1eae9f67c848b312a7da86242583fd1441fc8a48e7a95495a72e3de8f60b2c0108c1cfb40c6636328d21fa372ccdb53c730b93da1c6c56ea0fa586c77c07a5af50d03e192b6c9eb7b56dfad42e66065642a76e56eddfc2b4beecf964a1fc20897bd7d2815b7af682fcad08e5eaad68267d84b2b6efd9cc87c095a54220cb1acee42a920360a7a913ac5a59e8871699ee61cb1d1c815f1f312ac9840ffba2c3756c2b06150e54421c008ca5445fff8378495160644d82c85e00b704bde8f0b6aa11cfbc0ded259f2289684cb8a930818b2bc37ab0878f0574188c6526577161412705b6621dca599bebdf40cad6e3bc4956f3cde1f935ee5acdb5f80ff78666032e5846046200e7b66848617b9fe94c9c3bb7cb99b13d9df3a6dd33a1fc3f18b060f3964e4f64dab5e5b979810d851b15eb448e46c5b6088360316d3415bdc9d9a80687c8c53e0864c5e44c725d1162c52e2187cd0554d3b820b918c3642a548ccd22f1460f55afe791b1c4b2bd0615e56ed7d1eed834a36e1de8dadbd63e7d62110fd4f15d8f454ebc31b2bc1703e3f90bfda3af7f93f93ed71e9906a386838493669fa19271f665ea89883dc96835b9d4af59e67db7631c41b5ab55f55accedad0c97e1be92f2b3119e469d039dc98aa2b077ac1c3b910868c2448d48928b66e3a73078d9bf7cd407c4203627ac599c294eb2cdcdba6f29faa11e4406dde5932e69e323ba1fec3667fca7601336c41669be42ef1d04b32073c17ce4e379feb635d5e416a4f0f01cc934dc26f199506bdf5507d5f919eb6e6c9f1c4f679c9aeae7aff8c44862bdf9eab73637a54d8b474aa3db84692d29b3c596e73746e19752d53f4f90cfbc1458b5edbf0f1f398c22016692bf1263ea9f79f0e15ce7734d03468559ba798c391822a0cb0a77d09f440fa5056a7d0508fa170f4015afe32226cee9105c68e0f925bd27a444069118ce947b5a07aeb577f7ce3f0193fdb4a4390b9fdd098f285406018d9e011e60e065e460a37ed460e408ae8573847d8dce9e97d11c0a9375d1482cc1529fabb003bceb063697c07256c9432df4f638644e3136e80abbfdf42d8c6c96ed33f640a79438c18f17454f3f51fe908830287e9b90dec8137ed25d0b7ec098d4f6b33229455707a30a1191401ceed7d44edf7264f820b7c91e67adf6478c1b5ddba1cd27d88c17de1fd67ddf3ad086e60392927f6b9499413a59a6a4a95d0071e0beb6294fe7e7f7b3faf797e5961e2adc6aac24fa42855cdb4fb6cb6383469a1d9b5b0fb95fe1caf09dd6a3dbdede4c0143337bf5ec2c60ad8958dcf82544eeb5932ec238a01604047dbe649021e6dc7b34ced91e04300299a6ada995ec654cb3a933549eafd0f09cbf28f40db7118928c03e806845f32dcffcfd094032d44cd4e6b810dac905258594399c115d10ba401e8c179366b35e7db316f6625fbe7faec0fb15e7c653291e7c1a0afdb2fd62e6f1b70a35cece9307ab268cf00f46c473ea1cc94fb95f771a3fa75cf03ce2d56a90e1298feaea25bd7f41509887ebb449e6def95327d6db66beb3b74bc3e8606dfefcf6dd34f09dff7d8f3e72e52ee791bdf5e7cdff7cd804d5a70bd5f8b04f048067a9f05ac5688afb47f8890a3a16e3d79dffea05e6b0bb0c0cff1ae1fbffbb9906b839f77c1372848809d0d60ff0eb109cb04031b867ed81344399d72d071f47a585ce6752cf52400403af8713d2e8461029da043abf0779490eb545595c11008d25505e6a22140b31a3628deabd8c78f39fd0297152aa7e0a1609e28ba20f659c73b71e99d15a4a503be3f4e97e7e1681483861d811ce29158d67665299a2544e8b9e96191789afde0e38f6431c7c3f46d0487366cd24a7843c7f2a0a090412e4abe391e3b36a4770b66568a12624f0565adf24f085f26fb9f994822878a388c2cc5490f9d52aaaefd675bf314ff93b7e51fea85e2cdaccf0c531029d036722adb03d798aaf737615b75e1a9be9ca2c6327ffa403ff2992420d979ba79306a91a923dfd52a8c145da12c35204104c6e556451146fb93cd32ee9482b57b8d08b08dda237dfc064052a1844faf375890b60c09cfbb2e508c479c5c5cbede9519aa21156b167301d6836df56c4f8806ee80289b3daf6d8acf7d200bdde239a58b8cf256e9149783b7b8612db6b8b39d32234c2fd7d1fa84418627b6ae4cec8cfa70e183afb55b0f2be06543e3b7b1c5a41b0a560c11980e3ddb7acb7299e164c0b72b6f74a43ecdf7696c1bf816e6c1e1f545c4a1b11c6aa67ec6a0557fafd0e43ee150bffcab0aeb2df17e380735c25c344bff74c8806eb556c75282da7fae0c30b62babddcc51684352b1136ec8ef5ecd69e21260d159186b83da81dccccf42d96bf0f1a42dfe48c6632319449217a832fec973b4b368c42f5e4b6a7bc703203b0372df104f6fba38769ac0d736535f89765affbd3c5a3e6a5eec30f99bd89dbf10a305985e58f59725c00b88f8af108548fe7411eb58339fa2365ffaef703b5f47e8bd2c4b336c4c0601b8e790d4218b1079dcace49a395efd4c557704176a3f86b2cb8ff4029787a8f61c641d35b9d9e42073f3a24362969458f481f69f9fa22b9c884017850d6d49a5cc5cd817df18a2ca7aaf38e7e793901c9e265c4b5813fdfff973ecd3049b89c37535ad1848e74a2368934e7206b778c5688acfb73c35a9f3942044b4e3211eb2bcf2b376b719f69de60ca7868b478b7c56d3daaaa1b24294db5917be0413f6ef07609e2127d780cc095b90bb34bdc7eef6009405d41889f179454554836455a112b0e739fd660c79a9751feb57479f8323405485e6bc8ba34ad147d26cc44baa501af848ccba3ad6dc56ee2ab02aaa93df6a1588e61db6d5c2b628835deba255c1a9842af465f0863f7469cb3138caad750918a4ce96d5b68a9659540dcfc573e02500e8382bd444d09a292eb4754d8debc7912c348b66d652a268b313842e7b1049ea658143f003f08d4ae5ed0335c1afa1a13fae8f583914fcaebb2b97a431022967720c2e740bf003194ada123638c80883f4d7f4394d07e3367ad1b8add6b115351cdb44639c706dfa54d097c96e6200bde14cba3c15ae5c8207b65cf28d096c379f841762275808a8f5c2d42ac6e12e13dce197811d5dc208e34a6fc42cb80ed6f818e315a3caff03eff94dba9cc7b5721d968452df743355790ea95df3c4749c071ec3f1dd39cb0c72e7c29f2e9b7f7714fd605a024c57363796c83f36cd40bf392b4e64b4a084e6023a9b62de160fe9e21a779167762d6d4acd84e095684974a8e23eee655604bd1b8e36b73a304ec36feca210f233710c84e7950c0c97924b6623391e4825a7c786c0d0000fbece2f11e3ad05378b551e172b9771899096a8686fe0e28a423c3870612fd4feecb5e35e1e84faa9d6765c78a219c4ce3264dfb1c486856e627c544957e3a7b76adb8a2650e70ab10e631e102258a92d5b3b0149c3b34d0353b99df2b783f156cc9bfe62b5026c28255ca3a2e4504ea0d5afcbb62d6e6846247b51c61343a9996386df28a149867a2f67078c9c12312485f71e8f73d33ad81128193b41bb7568c045c713d2da3264ba43a436a29e27f359df1baa4cb327b3cdec952ebd97a3448ff482e63c738e9488551336e70300f7b4af198cfb78a20e03a8cff7ca79d0b6bb0f942edd76a63d33ccd9b0c9c99669c76e837073bc34289a45fd2da77d35fcf642630d61e51d4eb7d996f15aa95809108ce22c2da5e2733e45cfb48e1a6f340d6cbcacafcece001c29dad36f546e6deb99994870ba4c33331262a6aff1e53cbf6af263a6ea363edddf140cacdc0a4fb48ed16a8c0a189e51576e9dbf7c1ba39f9c0c2f95f5074ac27f3527439de162dfb7cc476cd78cd1fcca2a3fb86c047c4c1760e927a36a36964f7c495244b175f24c687589438b456a221e1a44d17b82691b640c4897010e8ad17af9499533a4b5027f0d4493a849d78a2c2a23a6498b6e32070313a74128dd7866080d42181edcfdfb2357a508c430e0ff4e8406c0b40db15cb1e9163e02a01597a1385dc157de44a2d0bea3e87e1248233b10320c5c9e50985bc95a9064a171fa526beb84700bf636586028de38bfdc6e7253e216250d12a3f29dc4b1ae9961bb5224597a5d83660ec997fdff5e696f8c954e0c55c430339d092ebd59b00a73eab89813ad12dba834d526069644a4fa9d1dc61bd160a9d23d884b37e702eda2ba5c916ce614d6a3dc5b88fb08cb6cb9dc4979e62e571ab84361376290d8a29cc41c558b294a152344948579e7b71685e35cb72f8d0797329414061fffc04c1f00b0d0d469a593da077107ff175b477ca5fa164d74b935f72aab2082616a1353a961055c7a68acfe3b117fd5c97dd397a1cef31b7c3a293a29939b0ed74eecefa16c59664f2c6b1ca14687161a1ac6b53fd020bad86016c499f391dfc40ffc4475d63be7013f196509ba3b8757f9fd844a3eba245e8de51c77a4b3c04ce4d241d771661b9155fb3882ab135901a712909b22161358c532ed14eef9e411907cced8e099f44e333d053d72323aecec0db39822b1e173ae9f940932dc2131a4092db728d6e1b8cb3b3a25aa3a8299e0e06a6a5d4716277ccf58df23d98d85e9a1baaf4d20a45355a9bfd7d8408127b75130fb096bd8ffe19d58a6a8cb83e5cd411ebec32dbdcd990c6ec53e8c3fbe10e41ce1a6671ec23a1fed705506a33c7f10ee40a43868ae1d20c0f2dc09de2371dc6368afeb05fa2b894e4dfc23b38bffbc7aefb3a34e9d99ff39f7612dd93e80b4da01c8f2e3cd5cb52018ee3b0621f3c319ec37738f4890a95e20fc755e4dd50e8beb60d2f9f86f034d9f5982c4a01587aad68cfaab1128581e2a761ad422ca082540fc27681bd7292ab01cee7da1e8f7053c9fcf039595f4258513522d7642593d90a38ed8bcc7464f0d4a7e16f01322e881c6590d5ad8b76fdda82e64ec283770f0707a75032d7a14c74dacb0dabbdde355c8213fbdce4007966277ec7bbf38c431219c1dcfffc92f09cdd486c0d8125ae4842f77a972287f3bbe4585819f097f8bc92700fc64c23ca615bcffce620ced129c223eb4510d5e43cf5d8f3d09fe968da43403b319b883c2ec8fe71810e47b4122a35353cad42c3c107f972491806c50dc3b405b949622af078dc7e598891764e07f6631e020577c41375c5c23fd01eb67ae7f83487692d0e31a9d411714ef99b839fe078f33e8c5659434c7a1f8d8b59132d63ec93d8a935edac8fc9088f957fdd901ca5ac30e1fc46484563c12f98ad6ea85ba2ce9e242ef4fdebe535e698f9fc3309f23701edb7e2df8868a324484dd9efeb42a27a118c41f79a745884199ff432b0f62f0b4d0eb1920066d663ca6e238c100e6953f3857b90a55acd02b0956de3162e649b240d01bee2280464cf8b7c5dcf4e356f7320e8786628cd73d863a23162dab36131c2c8c6419883d1f04a1a445d3026a183762423a6057459484168c113bbd27bb92814e050ffc55f2fbac00916da6474c647d8d075a02a679eb5a99c3d9e1b4b493bb363fae6183d016107565d6e7135e191b582894ef2f70e19df444d6bc4343c389da27ac72c80ec66f8cef0931b5c81e7119b03fa6ec692d126fc24c97a6ca97e0b95dabd42d41cc3922bc3dd7437fd55a2d6501034a65181319b78af61192c1611704ec1018915a23027bc018bf4b20bbd4c8f445c40aadd926fb5e85f46beb003bd51e9649623b3d54776ff5215a2ae974b66e6f1ab2af3068480bc075d6d0683742e1cc3aa0f5c4df5dd0adc9be78232f25bf5d56574145adb0d942e1c6ae52776f270797c33f65dbb5b7044e1b86585e5361991fbb27a409c5502be941f2d1306de3ea69cead92d6c026fc6cf9c9b194098db4a273c6e4f8973a7065e137e38244ea348da3f67195eb86b570541add84510259dd8fccb4635ff5b450ee64739bbcd057cb1a23c3619086477c38d5ab178c20004acd416a7d93b0f449619a96a3896e79f586716c37221c5012826dc6ce821a26aa096b45bc95aa5ad17942304ed323cef6ea71d254e9bbb378966eef23e1f9403ac99b835fea3e15b23be21c8c19b5cafc0a557db9b2c1efa9974120f34a995e7d0d62e41122b68521868d912dc8186849ae6a0a8173bf716f6fea4e22b567a501328442e078fcc64e99d21d56a6133898e9dc1e28534318c8046b7c6147f31aee2d4da7d45607a705240d4674052e54a4e0c610f2786ab86070605c7004ce4374a57904e3d31c115c165820947eeaacfc735b6dc4040e1a6e6de66311091683ab09078b50a96b0c290f1214cac1ff6d3aff0a4db233032e759b7857b7d99b04298291ee0499b47a4463740ee5767e7090935830d3b9702f1b710090bc0b6b7b017838c74a6aa2582c8aeae6808cbaf041c4e613592f938f1d34df5e212f1031171f1f6793993da248deac0f6f7b7841d01c44d9e2dfab611f78248af6e2872967772b56c7a7cdf1b247f26c9dc998e8d40bfce8f6aace2d45c14ebd8a0ecc887cb433764bea80c73722f45ad3089d688884e6a0f990e2d12149b79bf5c25c2483155a166d7becd884c39b0d3d7ba1dc40305e50d45e913a00153992e5d2c727c6ca95afa884178f732485694582ae3842c253784c102cdadf0d3cd258d80aa4d6bd653be10fac7223df09ed0282d440ff808f9fa4c32464bb610fe887a8d1e4fe662e3a277e1e61a0ad3417b5ac6f4e8d9333152801a06b46d0391ae072baefd8a0ed33f4e5ee4a8ca41426a61ebfaf26072d08c2c60dd8fe83a4725e996519014b8266ee1059383876c4a7ffd3468f509f3e82b1672cb392617f0be3fcd0b158fd443d9e3322b4737c8e48811b6fc37bce299b2154c0f0f0258efa89fbe79b1cbc0465bd5cd4d20baaa07307cae3234d281ac9b09d8c105a8465963861818d280b6a9d1e502e31eca8ae30c427627eb99bf7bde688dadb5e284552c6c96241406161b406022956887b4f6015a60333716fcb4a77d1685c7d32c08cb9b221f5a147a462d096eeaaddbbd08a2f083c357a112d93886e81b38966e769216200ae07add5661edc9ad29e709e1d6fbdd08f5b5d68d2f6e64a5a6f59121b5237c63284792114eeee781356f6d04736be565a8534bc5942dcc8d6a8515883944a950fb18953c74ee4dd0f31cfcf16845ab49ffa715d6960601779c689d2ee24f80060b8b4301eeb766fdba0d5ca22ca6afc811ce2f70fa6e0b337008ad13a1400f47d4aa1698bc0de4a99580dae2098441ac60082940c33a205ec94b6b80390162618aff5b7d553a7ec60b9437c092ba57852a18e45defd962f016726b1226ebca09a3c622f368707eac820438a73981a745f2049ce4c332edce2a44860235016477893def48defc56fa6f245417cc55b168b41d6d1eba62f9a79e889de4a9420c1aa8bbfb628c238bd3749bf26fa52348d70d7daa9f56a9a1bf21af9da5625693ae1e4554e8d72314de0c381b742d750ed03411d81382ea0bb02c073e1b0a4c130838b30e5b3d58efd12e318bccb8df8237c6401f3073b0967c790e9982bfea422966b03e09fe9fb22ec238e947fa8c2c4c5e065e51bf09107f9eaf53034faccae4681df94c5ff00249f40b63ee18fe1fd1d1420d82a2943853a2a6f79df284b49f1381ec534248885ce8b15f8e5e30393aba82f584d9f9250ec36a28b1792fe276c0d0ae483d7dbbcb99e01185d48963c02081a59547caa3c6cdb5d4f40e56288ca46435ece23f37ab9b46193c8d2db37b0276ddc68a0c9b8d2d4d7912f2453c7de775322a4f6a50388c3c650749a4c775b489612d00677261afad697dd1a809ec6f58df1610f1e654d90c99480896a014b720e1b9454da8a5ebf0ccb3c699902aef67094c3f598516cb4a6749969bc857ee6b2890a1a98faafcaa3d6fa5ce3b36fc3450f8b4c6dfe05e0857c34ed043fac807b42cd86ca2622fa44b665245da40350040ce721db6c9832de2d3767a290571a2b5d9138853d1d75056755cf8b35c33e4b91b9f19009d8715e78a183906141c07ea26f9e3aaa0153dbfa5a394d693cf5ccbef4761c6ee12b1c06352fdabc4253c34a2d5ecb2cb9c2182567945f791114af992e4f88ef4f3def31b4736b42e423dc9f99126cb391a00c9a033df3847f87f5d36680afe00aa7dc8ee9bad28987b02b07e89186346b9077b70c3d43d30a0382dd3e13e0df963a75b5dd291175b01dd25f374f5b51c83a071649d2b97485a81aa4bfea678801f2ea5afbd5a551b4f0f6a2e96f826581c85f3e9f418aa2670717b15617247caca81bf4f218488873d62d8188a5791b2485a2dad26902ebebd46e8d76ddb46f40ab5dbb39ba0b42ed116866f9729360a847730e8de31056ff3efaad458619088648dc2d23007b0bf80ec00495f214f1dd6291e1f00124b40ac71f8a42b6a4087ad9b734e0dd53202454b3fc242049e9ec17e162b7290e9cd668d6a0df6799600a15fb0da6367400bf2ddc9b7854246b4bbb11d85fdcfff118bf8021fdb090ad73c3bf4b17e5d3404e209ef4c8de68b22d3eab71ed59826e17ed9c6e080d4ffe9af05ed814ead42055e2835b11b9d2604fd9b5e22d9e9776595e58c2bc8929061c93ac89f25198503822438ba64e1bd676f5412d7e9042d152aa91ba1b16cd26232090234cdfc87f75903af8fe5785297048a0afe1d176c84f8d5a9fafe9f219c5446ceedea90411bf7c67b90508bf0ecc63b635e3ac8bce80463a30aaa9055bcc49149b59be574c385214be44a133924c6467a7b50011270af5e59a68548408e830bb22522c1ffc244e90a9942ea1132baf1dc2f81d69723d7bdcb0ae030d45a1ffae2e49b44523ed1366bc1adf2bfe8c1681e4177f990a4dcb6c1216e420dc6ae98b65f9cd9251f665658e38d732d0ddc6d66e4f79e5c8b0cfe6177805b9893f7d3956c6f736f24bcce66cdb1093bdb81bd059dd5a619a07dd0b1a6f0ee2c4d000b7610991887dc563f1a0c3e6a48936c461db5764c1fe15b5760459ff4bb97b40ec14a12c7f73a51a5643ead55ea80ed594bb420a98c2b3469c8b3b18e6f0e502bd30c819c5e9abfde7856bc549019022b008cee08e8fbbc30b56a08a6379a9c057a3fa39472b5ce793e28eaf0545d0184c0486ea2b9ff7cfb08e54ef7cb35a0dc24165579f8daf71058d867623b6e301e7cfae7792db952029e67749a4e57c570adf7993ef0430b92afa9f607fbedbe491d21378578d3a82c14a5aebc883bbdac0872395234a0c40d0b3017790adfca886180e24b3d8eeef64da18cc75ed4bff81193a51688e1db0040238141eb5425aa3a77e9b26a9b984dd7b4f59ca701843264a01fbd08a7197797c15572418574d7d956d6f27f0f5d4a55bcd8391088fbd888b5423b4cba81515684d00ec98e041f68028df9d8b5e24560f720211dba38c70624808ba8b4155d0d07836962ccb410ac5c36664f542a6409bd0220f681e72aba68fb4228a3ae8656c9b8276dc86040e00b3201d96b89741a6c424e18f919f408a66dc0230cbfcabbbb6da59c7fdb95cfad999413174e112e98d432a7fe8355df0e62c1be6f81c48e49b751c80a820245155073e540905c2eec03b887e8a1462cc33f5e242120ddd1368ef8d2640cfa186f3f4e8deaadac608c274a586088bc2931f681ada8b94772e08e00971858e72d86feb1218c6bb2c72979d0eefb13625b6922cb7dc3f35f227f361ea281fea09cb9a7fdfe160092858058c93defa94c95d8ce79c76a2c2286bdb7a56707c582ce40fb274e4485bc84a8088c091f0143f542e1c900f21edca4977e2bd5b4878d47ccee9cd5533427fd454d60a16877dc962f6281894455db796b2d89a8e9d0dd01021805ce05a16abd27a9ece9f7aa69d69980a8cbc1f95d628b36beb2d6cce5c6dc9cd320dd4e3ae5062c43b0e680e9b748e0067f4b2776173e829ef2e25f76a447e7c4dbd40e78f9b24d4f6d73d2e12cdb966cf94f42be2f15d9fdb23ae8324aa618891d26f0cb84545e7bb7209696f4d6d85a9d5d07b4b75d79b32d9e46f62cc711966ca935207ca1c4d17141faf3791811c2d1e6976656b94ec57e243693f7518cb94da552fd56436562a59457fad35c630541720482728e6bc804723b1fa2fe1222589ea16d3b459694010177fb58c89877f5308b5302f92218d3a1e6d3f1cbb91d8e74cc53360ad6320d2079ad499ee358da566e03c229ed95b8fd03b4ebe45d7938fe91d57da522c991668c6d9573a251524ae163f0eb7efba06ce39f17ea0747e39d164c1ea422a2c299ed145ec5bc3b4d3373df4059315ae9252348285eefaa0e9256f31d0fd2ccba7c5593604f6a1e54a1dbaa427d5b2888254c78de53205b305facf8134c9129dd8b731c7ceb1799d417c7ac2e54c77b2e557e50a1a5fa9ca53bc70c5cf915c9fb232ba6de51f6242ea9163687358dc9450dd1d232b121f4456d09d0044dc830a6d06592ad9985195f02fa6a3b627322647610732f51bade881f9e7bf08ffe7365384df76d7af0db836873d0bf1722e96ff958a5d0672b77991fac685092f33402424d253efc0432bb24db7f2905defeb7f50535d163a5167e2c44bdec69d89f0759d69410b4b4d34ddff78b2fd578fec2ebffbffdd2574737b17ba8a28517f700742a6bc7f29a98b436d315479111edad1ce27a8a6f3f7ab7f4191386af2abd1f0fb9b1a3b174e07657512782875d66f2e74f9702f615123dc2a2ab240ae824f73b1776d0bfa81e7761252a8309f303e8ddf70b3cb0fbf92b9a5998ae1877d4ccf8cf2323fc894479efe4cdcb57706ea57d8529143758685ea05e4f3ee80d81ac60f716f4f05039591aa3d5534cbc9b596095d2500f146586edf4dd8c46325e3ce9c6379caf15780359264e44ff1892a6cd94d1431fc38f3ac5d4d8d2892b8e34affa182620494e39d324ebccf04ca94977c8d1989570c58a1e90d16f287bb0755da980413f328a60092265ce8f703357862813355efae8225311e1e597321f9cb4c05aee6d33c2c1cbba70c1680459910b7f7a26a319da2b1270d87ac1b81061d50ac6ae45b8209b015372946af64e1c35afee469c523d261679e06d15a1b19541a69b9b11b848abac044a8ea3439e939370c525a2b425df1a80ce7e6cb6ea0bf3ee41b97225bea891f220ac4860b96da108a4649bae339b66b064b3cbf0292ee18ed2dde95c12889f2d8625bd6ec45966bd64e20bc5159634ec936d3cc1278841c22cde3c12c81411236e4a0478a61407ec4ca128410b0a4fa46ab90d7222e9c5ae991b625405fc6326e5b6d6bd8118bbe9c203eaa046c33c61220c2da434202f723b5d03422165b08533319b21727f60e80fe8aca322d38280477371e968bcea88983cbb38848968c2fd81a44774043bd852c84b34db90908975e0882a5c2521094e9179aa6e266fca01b7c90a99bc358dcf443744a6d5c54557a8b12545d70e485336cfd885251b5ada773bc3d0abc98397a25c72feb27f5c3b4eafaca7c10862b9c32085685003c6b5486e4cf95df7aa86d5f1343c2c1d4d54dd6b3ebb4e6a444804119278eb1520d093ae5c5515134b5df36ec392ded59db0c0d44547f748278d9160d521f9e3f0896426b1c7efb2920a0a60e23dcd83e84fb6e9efcb18450fd6f1eb4d63943a5e280a6aea954d1fc28fa4357b1ee8b18116867aa7347bbe0036fcd3f20ab78785fbe8052742253f4a7aa73ef1c10af1f6a1ba64fb612f068b244e1ce1bbc12cf0d868a10493aad47c20d3982eaa3c682d1031f29c2cfe2b4675e6efceab113c9fbfa016730585406dce641570a1ee511d04941fc98c833ca303d5eb93ed2b4c0b445125b459638cbb9fa2cf38273e3e24329ceb0767cc133ff22504890e00204bc8ff489096b4e783702f161a30595669b436b660f2c049f28b662189cfc57253f703e06d3901f7b3a4225a221cfca65ef09acc67744b0914025110d6b8a4644cf7a91c1e375927678be3b349df58c5bf8587062849cae471f0dfc5d247d7d58239ee2d17a3967321eaedc0e6d928733384c10f4e2b573d2443a0c2e24ac23f5de96908691efd77a92397fa0e4aca95f96e9f87d408b87c2ceb4262a281b9a430cd06c309c2ba5feb9b2151594498b0de5b28d8b091a58b0336b107c63e7cee058ecddedbde3a6a0bf99751004ef4364428a1f895b97b8fb40a47d23b3f8da6eb7f04093a0067756ae3c74056fc2714e6d2d0413c72dece251a64bf4b3ef103b67bc09c4ea564260f683f468954e41cbf95531cc4e46e5193c0818b821af77eca5b0a9b7c7c1d25b41a07fb8ee76811e3dd80212cebd8ab0a0059e31502108da5f55e2ed049cdc49d74b0dc1219fa85a269a9671750833441b35201203a06f2829e4771dc279b6859947e1298059188ef4057b061f6e2f7cc8fff29812f0f5ec49833286ddc44a9d9c48e86c1c53a0c3538db8d4c16689071d41aaebf2bfd23fb905c61cbbdba25d8377cdb58308d67ec48082be9ca30d47895f20bfb415891b52be294351199a365716323d5ca95000873f2b36fce18dc120d840799d1f4ea71ae20e35841a6d4923ffa305a14f1cacb4889036b7e706478334629cdf0d4eb31fbbf42521c822b9c85fc5201d5196bf8d9c5b06893c948f0f2a38479baf71fd41b928d6a3231928e89d448e5411b1a371b4cc872a90eb8074934253e7247843ad3681d0e91b8dc8d3ea8169c0b25b9575e5aceaf6f80f0a067f3b573aab9d9b696d5bfcdbb2013ec084b9a1c16b98224b5b887be9dd4525c802458a377810ff213df2116f84a51745b97061b8ba741262c45766645f453ae2ea62c323ced9704c65d14a6668468ddd2123737fede108000414cb193442d4285aad5366a46f5735cf14630b25a0d85699747c94f1f5bd8cde5512d6ec410bff5c49c40a8ff541d146d420742ebde8c2368f51b864b40791d3698014431aca6f8eefa59f2b869354ade572bfa3290ec6d2f6624fd27e89be1e57292f647de17f6c636e25bc38bbde23fb4eb183985be1102358fdd5a7303c4f7182b8a60c8883290af8273ef2c84c18339dafb2e3b455e422d70bf824b11f3538a4e929e85e347dd98aaf1741cc98d3a7493cdc8a05666085732c8a58ac84864606d92257ac962a384becc55fdb98792d2c6788b37d99c9abe574806089301f5a25fda8e60471afe61b50be757f532f858c53822da6b14f9ebd5640273bb3b0a541213c16c6c525f0c1cbd8c994fc14e5af2785b2831016f960c89f2f535bad650a5aaa0df7cc5b35380ac07242b003feb85a0b149eb7e1cc616071fde0e948259edc77c26e0afb30e129a52280a4260c3df5d806a03a28686d2ff843044cbd14003d512e53277f75ef29de7569548b37f425143f75d74546aac90080548f101fd7e5416d0a787d0c04dc441f0184485e48a65075f5071b74eb5fb9b0400991c0dd7d7c12f7a305ae54af83550919881211413303e3a84036e2cbaa7c979ed7c5116dc4897c9a090f2cab16afd11cd47ebda21e0f1cac3e7f50ccf5020eef302c96fb7ea4d42e0676838b03bb2bb87090e08393eeaf089dd952237cddabb898fdf2546c3fb5172244c55605ce92615905ceb7bc0c9c4468e6500bdbbf0366d581507096be15e7b72c5ef6b5fcd78b8f7f59fcf9ae7809f2c96e55e2ed4a5b2bd5869c19cabe2d2dad942621dd56707501739471fe86271c62e428ca79e0c98c8563c83e580f5b157d30a1571eeda7cadba089c80bfcb95ce2856d4813f848baec1941dd20290fbc8803936c290aaa2f56438462cff30d0d917dfa25e8a73c1d685f857ed3240b4aa29a975a55c4238b86ce0460c87f98cc88028c024c4626fb01c507f4440603d2e1b8385ad312c7b8fda3b2977e4d79e60fe8158104853737603f5400b8bb0e64fde59bf9a858a01328203f7971645f40358ddcc0152ee1ccd8fb2a7ddb8be5eb59c143dac089522e2a93974c9f0c69a35a1052b943a93cc0d336c2e2a1e86724f91835039c57696f9b4b58f3c88383cad8e9caf349bcd548a2cc574f3b48c787a0bea22547d9ecf5b8f83ce25ffaca94e57877dad729e01b6ded97d635a421f001c7ca7f0f72eb4bcb2b30f778c2bdd9b13203d4943909b0c18c6f0abcc6a1cd986e766d9ea4c8e57c3c7acdec90494ab79e662fa1ac15a73419ac57b3ae48daf8a04649f315db3b200f535d009ff1ad709e2932bcdf04ab925fbb514917e7d93c4d7fde22c62280ce0f21e10d9136087ea49c31877e169eb43c9eba8ce9a5176d2d528eb726fda602c4c30e07b0bb3e54e00f2f7e00fe7eea43042627b85c5a352d520acf3c320fef29159f7facdca47ea75bc82c1263fcde08553e3aeaa00aeb98fe4e81dedf80600ef0a23ef3eda924828f19c4c0c5877d58b4320b541a0b32c5b7cecc6138160c705b061e8d6af8f481aeac518eafc00091900310405f8b8a18fb46034c784b0ccf71dfe9292153336958556890f287d59cc22cacd71073147776815f8de615ea4b07126a47f94ba0399f7900fbc799ec7e709c5f355034861cb29dd29cfd36a6fa03039acb064e23c8445c64eb8070fcb0c5631658b685ded44605e80fadc594a4eadc15b198479733af5b9ff3b896f7fe4a731d9a090630df8f6940889e29f3534680d0ad9c101b90b2ecb6a7038c84c8ed8e26035f82c61aefa51d6b407229ef3b017dd1a72031cb176554f5100cd89e6cb69dec68fae5d651cea4de44ba2c3df673c22a6a4baa3861cbc9e2acee22c31f789a4a1c2492e5f3af498714016f9e6a946060aa02762619725cffeadd1f84cf0ea52be70c09315782df9d30065744cac6294d4e18c5cc7cdb09cac949d4637dba8f51aa90bba9a8a12c7f64a6b4f44a82d0ed60a2446135ba44030b7397e061d8588b6d45cce1be33730e3aa87918b55171c2609c22372868a2c05e460143bc00e45d58233de5aabd554a300577e7aff90b94b919c07fc91a2d937e7ffc539e168926a2fead1c693e34f6cc18d1d4df693f3e2eb2af7362b5c4f2da61c8a4238cd14e9be09da8b6c9b5a726e687017f3c96584abb79dd97fb1e7d3fcd1c32fe6418e4f211ec432608d2e38b3b8ec3f192ad02ec99995f81afc8c5f818730fb2e4c783b9109649de3e9f79bed41bec50895d4e56e1e2fbe717555b668a827c8637113c353bfe1c62ef791904f78dc710be83fd068774c4d5d5bf617c861d2a8759ca443f09820351eb7304598d1321ab3f18327cba7de5d9519dae4ce814a23d91d5b5a856ae70614ecc8d2fd73de127976be8f92be8fdf45acf1719402f5c4eb7811094ae196a5d786de09f00b23c6a72b5dd6c4027b866b246893bb208f6cc26d7be1928c36a199a4cfd3b157ddef32b4ad5bc2f9e26f44ae43f73edb79f556706e51016645b68eab7c800972e3394ce7377db9633258b82fdf336c8bd3a88d22044d8ad623e2ca6891e1a156fe8dfbaebe7158690f7a046411e8cda03cef95c4fed5e08ab5c2b74d9e4161343a8a2d8ebc26f184b70e5b68d532fbdef8cb83cbfd1f1e5d5cbace98c801323e4cd40e7e63c3de1d600ff02a1bc50cb9560e6d79669f1a8a58f6dd61498681ffed2f9bd9d87573a8d3397dc68df5296973674f5715cf7657e0c9bf5fe9b3e9843406d2d01d5d45afb7a9b2e779c862ae929444b4d35331089b608c17d3acf02b3bcecd81e1a3acc43b3f75b27115bbb2b1f4c6ee84c23e72f05870d7bb74bbfa53cf338c2699292bb33d574e3225489852e235489c52ed1d99ebbf8fb0b59c7645629e74f7a942b19b6ecf40ea20b2bd3303fe48a78ace9683a68d54d4807f6c59a2ae64b11a18ce6d7e9d54b5b01044fd2e32bdfd7e292d75ed8c3e70b97927d03ceb0aafe531f2c2b35655be2508ea60976fe9f137cf4592d3faae62f9a7c94257b7a3e786fb8b5704ca96ea34205f664db4cdab859f14647ce14219422a26ed3a287879234492b275fe629b72c895e38b081cad431a06105226b06e36b17e42d485baed431d2412c3616114c0e7d2a71515f6fb0f49b44ed89358557fd16f974cff249510476744bac49014b579eb57451a8aa181b7c25d597612629be1320879756139ef98ecc17ef896060a46f7ce19d322bcfceb78de3666615ed7c9d123c6ed47f188b4402c256f7c311a40417bf665bfc5fe82df2070678b2ac008c970dd2b112c10413d3a67456c76c24d6e18c5c390a53fea5872f137deb12c2eb303f93f0c3fe3de46c4228aa119ec9b82e498c5b2d6f30c3112dab301e2b8157c4f84712406f5eb5d14624ed006f3a9e940899930b7de24a0e9e419b7dadcd79fa677d3f64a0feb7e058521fe36d86164551307c045162727a5f6923df40246e70437a611aea7db6ad67024e3bea4583febb2dd0aac181ce845169144bbc0a775f72530fe5f34db86908acdd3fbd3b297c2fd79df7694e81164c432e3a8e953a80a423814aaf8925d25b6e106c21762c500afadadcf654d157c9c76c229859b6155e7e5892f16e51ee093b6f447515bc62d7f5bdfeb594113905d2fea6583ac361dd8528141e4d00f6dfa85ca9d35feac4baeabbae6b06a677e83f8f631b7426556f386ebd18328b6c3c14b1f903912cd41c16a966cfb30793ddb509e1c989156247814ed0d30095010e36129be243059cb2a7d82a0d2236f05a7fbd70ce15398e1b06a716cb31f1835480ed463fb1e422ba05329c73d7f01e532438776ee4af2b8396b214735a20bd380ade09c3febb515cfbe9565749e00ab66651edaeaa1ef3439ec7768289d0410c587a482b513fb073c60de1fc4a3716951a3d62f14f7b6506eb82d0d9d4e2ab9abfaa90091b77e03a3183d5cae89062ba57dd2d162bbf67908d267718240b87951d582a269e991b595ede9acd9e58b7bcfd2c5c36fb1b51eb1e5bd4824bac297bd794d23ba81bd9ab070c38554963e4aa185c80c762763d340c674be8999421d731a6eeb69d8b9e64eddd6abc1d2856e5f7f4946f9b70df49c1ec5add59ee0c9f115d9061b83a1117975e071f5f3f1e5a37be34ea6eedc434ee6e4572feb6cb2db4cda0fd45e355c81755383aa0c257403f53c1508c1938949989a6605e6293f840049f5c8f2106c57238801117960cf12af04e4c42ee7093b7a538d3d15705748f03ee7aef82f6165fdf414a2d9885c785e3736898165e150cc1ab60fdcec56a19667be2da60cb86a53b1561a5ef3087e6235524ee3863d0a252cf39c1ab1d1cd7d2a352d1bcd723c7211205dcedf228bd65e4c4bcb4537bc8d43827ba96eefeb0d273bd208f10d7883927c283b554a53770702e776f85ad812aadb0d6d40758e02a456cc4bb7fec9f640a39c8360117d6754a3333e01aea28cb8c135d85848310cb523e0c185354f974cc11cee73e614462267f92a33101cee19f5b558152c0a63d2735a7c024485a7af7ab556a34e3043736b45509a662d5a02e8ff9912b20826d299205e41db0541d3c74d1541f8464093bce9b0e7d44840724d44878b1841795835b6c50a865468d622db3140cd392be96656a887676854e94538f9695db79498fc36f9df4fc15a9333277dfee43e84a7e690b3b90639d6dc282464f9d1896a49819b5d30527d075489674dc7e1f64a7145caa6222a45d37eddaf94a7a4c3cee28d85f674e189468b2ab88a8ce33c96c46c9c7c14a562836260bbb8cb1ce8c8f931eea4c408a4add3a6b244c81be0f920d07edb53fd32feca32efbd55fab0d8e69f41b8204d0d09090746d126ab6e3ccc159ff0ac101d9eec3da912f893a89a71a2cf194da4851466fff016c956a72a9609c4d7bd0eb67078c0910d5913fe27001b315abe160d2942fda4cebbbf94929b8b7b033f71f7abdc9286013ae1b9f66a226d48b35c13b6550af609708285fbb45768b8c4dba2528e0e735133b502f59486980182750887229e935bbb49c58422512cc397efb59a747bc3288fe40d4b9436d8735fb3d72eb19af81b1dd908b132eb2ea0329a97b0294ca4a5e361342d6a45b44d41c7ee4d2e3f08bf477eac87a8173de91a4acc17693cc61b94ac5d5c0c1ce1395e4af8ea4677d4ef8b6228a9712c8e4d241c1cd21cfa3c77ad4b3ff4611b06633897d701c6d4010e7a2a3b7cb2ce45256f23ae21c53916c866aa3ebd49a563e684c65640a5abf3ef2e540c46032e2098cd8050dcaaf08a38846df8404ea617ada62b85f5c3bc46a30cf0f9c4aeb680399a9d71f3d764ede53a4565d4cf2ede1a96e4badc4dc71437a5114b272ac73ee17c90e3b8bf6a6b6d407d05dea355ac6db51483b1b8eaeaa84adf2bc0e77a49e2ef462248a04cd0f72e605ee2b54a21ebd8ca0fc5567f241db30def821fd8831f789fa636685fed87a9fa00833e8e60aa29281473348401edb61e92a11fabb25c7310f94a1f519e73cad636b7911324592db4b2967538595f6468943ae2d941278e8f91f00d705258b7d0ff7ef6fcea3860cd032fc842771d653a6e5f8e8150f8644ab36227fe27c3728868acd5f38f7ae2ed3239143313ad338c623402b5d7a9414a5bc9dc4742b0657af50107aa451b3eae9e194628448ced0a0c8d470950f4e1b4bcf73d3422ef90b313596405efda8bba54e43969877387f74f994345746199e4894594a3161e9095ff192c3769a4176cb880b89b677315691223f369171527e7bab444d39ef5b5d164648ccbaa2007cabdb991d98b7c93b350b0fdda6b31c211dfa0533300b80a32fd43e2d8c9b1af0d73d3fa516ab8bdd32ba4dc1edff8a6fc4bdaa9536302a53c3ffe18cf5a2ed0e029e0ed7e8de59899eb6c9b748e27dbbf3d455f59784d9892493b89b3f0aac5ca75f193eac6c2e2f8b3cfb29324b48abade8b3c8efd255aa344b6d2063c69ca29917829d7182ac061bd888c002ef7fe9e0ba9e99ca29584c1c874eb72480f2e33c8b12a12cd2c2c2dc07cd95e2a1289633a5a5262c87a783c4d984b6d2058e87a8355a9ae8ccfc47675466b41d75d037680413650633a1690a57c54c96169788b19a09b18805b2e1085dd74622ad4f7ea8ce38a50ac554bc89a229c2b23b609a53b9f692c33ed5837b6711deb3e89ba8464e1126d7fc1188b0dc9b197ddaa6e946db9a8fdccf4d9ba0343b93e5bf6f14a31783bc543c0efbe4200f4f50c0ba16542ae51c445222891dfe946a172c451af241829748b0fe3c5f9bd7514c45679188ed51b29564b66a5b1abbd657423e4cac52ed9854b896cbb4cbde1848951599bb1cc353f557c5bf0cf79cf54884c77d32165d4000766f5386891cd35135b6950ff0b9632e91152effed03d89a2750f76f04b750dd914a605a7fbcaf5699c8ee21c2abadbe9512b130857ff1918c0331642979bafc87cb6445c49ce509d9e58867f84466bf7337db673cd270807c916e798ad021d7e95352303b842c62dfdbab6f7177724b9ca3e1caee058457de9f25025bc959f52f2b63d9322467b8b623836c8c73cdf7d8c43d8ee8f371bd5539ea74e950e2c860a9c7e184604a8092c0274de42842d63317039d1db06ce082c216a7e0d0f8010e95e49871d052017568a6873137d127968cb13a640417b88baa0d8396d70f91b1687db88870cb451ec26b0475e7cbb25bf27b7e0a39d85669929c71e7511112beda1836eaccb91206cdc79a3a28d73cd251e593d50a3a8304a4e42805c458034a2a726f582018daa8036ecf0bd9fb8cf980f861287d841c329a31e87ede6dc58969a5aec522fecd75babc72382b3f473c084e7dc53cc67d1302721debdbaf0d4879d158f7202632d6e9c07bc9bcd19803df24d9cdddb69452ee94a40cd806de06e806a220f0b471d10aa60cf42d035d71c20827535822537fd66fdad06f09fcdef216ca5b1890257f41e68166d179a059946ee34a3ad5286f6ddb067a378140206f79ab25f66900ac5e5e774f57bc9aa6793c8c80c57962a28205e4de80d0be883c8bc54e41a04e1c0841910f48192a466e599a4f434cb880dc379c0f6aaaa2c230c438c421c63dc09d83683ca860310c5b46a43426d229b95fa4f40ab5923b040e8a4052a1c2298b4162a7ec379054a7ece0b74418ca4207c33ca5655ef4865a699939ef8d28f0ac3e8661aa7601b3f0caab780e97030788a4b2d62aabb5d5da9f58969abadba7b34e0a16e9b00761d561feb8a7d20b3e2c59da501404a5142103f2470eb2a4e5fe9048cbd09b0fe130771472e060ce3f8dab9eda01d1de3f2f27c9f6945d73af965e0963040aa37ca48314f5df8b51a8dc52b28329c822a590e1ca3a7859a47c1cfcc90cae38a389b5e0e989fffc5e3c2b2ff57fc895e659ab1029331f3598442232611356c39c1346a44a315313e59a76ef06a4a81fa7c815b0286731130e33415c954ef7ecdf7bafbbbbca66a6aa90d2cbfd6200b2fce40fcff421270d02c6b8c110a624fe032d4cdb1b21cb07801c754cf2b7ef008d8003cc600009d32f7a31325c1123628a71bb7b0dc65a50d3fc82d552f99c737e9c7beee722c50ac7c4b9d69982314f4a281527ae64aaa984a0847ab117132768132b4ae96465faaecdedc34e338bd8c206c7745d449fc612acfd8c8f2e12bf77a683919689e1880c545cc9f4736819d17ffa1ceb7bd70fc90b7898998749674e2047ef22fa21103142644a9a271049873bc8a034134987f479bc004f9777a70b2015689cb33d4ea4b30b840516f1b59dee39ebb07bce663d671c07d2b146c5643603a92c11f45da81891b0accd28505a45662c5f6354c9f427cde2a5b403b26db2d49ad601e1ec7334473a7bfe7e21b8df71d01270f8ef11fd3b5adebef3cf8884653104dedfa72fce34e001428c789e761098a0e8816fdfbff3337e65de3e9945fb1dd8437bb8ab03a4ad0e485d39c0218f25b0f637ca90dd0df7e7b78162df2802936d265fff39b73d470ff0acb57e4f5f06418874d17c1d3334909ae0f0ada051772ac4de44e1020172b8a9392b4f87994fc09e6779bea4ad0e29abc3a9b96beeabcc8dd77e0c5b60913bf9531977f29174e74ece9daa286f282b4f169416a7aa4a5c2d1d2de37f63b2bbe7fd48ed5e0d009f8772382174ef58a3ca62d66ab572c256d80a5b3e0ac3960c674b96ba4cff244ba5dc3fa3c8a450c93dbb22f77b46c041e4c3e04dc1a184e999c5d0498793a56292cbc0dedd305f0621b07f367267b944cb0f6c5c2d170e65d901b95db8b6f3db5760abc00cb9a81bc330cc47b325450dbb19c36c15b3d5289fadd992308dade0d86c49172cf7cfd45a25cc6ccd16e8e40131d2b44b29ed6ad03cb9678a866d061e5fb0eed6354d13028ba5d4aea61cd9b760a7c44e39a809eca184699114f51f9167e8542a4bef344a29a5945acd5329cb2ae28b916105d8ffff71f0897d603994d21c3ec0fe1b69cbfd347c4e2a80d2a194daf4af46fefadbfb276a354c506ad9be589034939232246dbcc813cc516550962e22cdafca94615aab3bf5ce27d649d1f7fa800ea7006e5c3412f27e012ce1b363ecd6dab746425903390d4435aa7d4d49312e9a3f83a623cbee65fa0766d9bd68a0900d942ed305df45f3cb14088dd3b29cee3e79b5562a733a94cd49517d8275acc350cecc47f657563aec3e79150a76ac614da2fef569c7195ac883a8a009a88009a14c92a506220172d429587223032aed0229f95464c719580c85344ae9e9d438dc195f60fc7abdbccabfbafbe52f4b5e1836cb5829c82f244ec912037ce4fd8c07f7e2ec22f77d6f09eef1048bf235513efaf0c8920b1ed0013acc1fddf75340da307f74200e119032da4b09c381541043555e21b70c430036d882af571465e4db5a886571be88c0f665693a0e22b0f5ec0064b8bb0a78ffa9c0e7416fce4a6d5e2f8cd379e2f399dd01a9d50b2f264bf226c7d0cd007fe8ebf31802f74b0f855c37a882165266b18e739a442aab63ad691955cbd496e1bebf2a6999cee77d54d61f3b55e9d0d5a1a6695acbc635e555e5a6432674181353064ecec499b2d05c328e38c4c09dc590124c433e12037b16434a70cd6268dc3659dabe1f007234a54c5728bbbc0c42c1e2fceea7f5af93a108fcb2fd0f79eb0105bc81d315c3328fae2a5d7062ca0b26030ad72ec8b805f6e1c97c1f3cdfbd0fde7fbeb3e7bd1fc1211ef8019f80458923b2028b73a4428526e4fe59d332aa2d44a9b1421324a0c8028ea97f7e319fefdb1df1d1079c352deaf798e038c1994d5cc93e6ba60adc1105961d526ef3e05082e7eceefc1c885c67cf9e9d6ddbb86de3b66ddbc61a1593d51ce738713afd49824fc7366e18587cedff031a48b58005c785e3c2c2f572699acbe57269d8f3c4621e4fbbba4fb7fab85c2e57f7c1ae8f0736c1dd58a362b2fa70375d7fa648d9b2524a8b80b5278580d03067484a60926b9a46b234a03854e69ac9b933774e1c64dc7bef0b3cbec00d6899dacdb7a22971a2d11885f90c56b5cf4696dd0d0d44a66fada53846e0edf33a4e55cb3411fb5b05ea872eba3fbdbff7493ef26e4c58c1f7dccb5d29a9d7c4f35ac65ee0397ab85b81fa9def803e74be1ef11135dd9f2bfaf73f2d5992b07c1fc9c5f73efd420973bf7e979a3ca110f83ebdafbdbff8f9fefd23b2c4c9eba2d771c110e014163747863e54e40b7c9fd36e4c8ca7c3b3bbf95df7f27c2f43bcf7bc07a4f1bc07ce1f4c9f1b4c33048e421651cce6d8322f38b8833b60d80c28a440993c9f8683274c3baec0abd56a357d7832df034e5407d2fc60f2803e5880e98b7305e47e36b7e6bddce0d9dfb36ba02be01f4c3f98c4f9ca343b4ded62375aaef77ba9200f1198ae0f8203f7179c29294129b95aebf50ec8f77203fdfb97fe0fa094220a709859eb6ad06ef03ce3fe6daf7d9d8d4e5687bdc99247c23c91a34e8afa63c8e2bde2ed4025ec3802737f3a9deea975d000cf1b1e42c0a2ccd2a9d745f46e9bc7ba66402a98a36d74b7fbf75e3074918e7fe17be50a5e3547e92edda711b2c8f35e207246b2a096042bb0e80843310011e279817570517f9652ce48a232b0180ac5d03a423f23f71f4096e6bda110d590688f84ce9270c5142492a6a938276013f613e6a37fd8c3fe4619f86a9e1b6560cfe2df7b9b4987edb9461f5d537f33e925a4cc344286fd7253d548984ea76e76d292c5bf510606c00e26abe72bcf2a138a16258b9e39573e9ae0c4b105fe1f9ce409bed0cf482ca8811e302681cf77ff525ff07b58254ba5dc2407812ff54f8dbadd4792c105b847132c4e18ecf630028b24188f2a5824b906abb109eb904404467292add5d65a6bed6030ae3f4ea47c79796a7ed3630aa63fc117a97d569f958fee67353fab7b35ed5a6b6f624e40a1503299cc7dce59a9e802f7fc285876f8dbb5f65a6bc79a7f89040c2e185adc9883471f61c741067e01071998722ae74659e2723f570380982cc92aeee8cfb9a8cc4ad83575efd59c5bc28ddc78069ee08d27e01baefacf77f0e57a5efefe36db5edbcb47dc78b9717b71636552532eeafba5723f0c0e6eaffb22633b62db8ed8562d236edbb6a936269b6a6be5de8e90252042b88d0913785b6d2a287853e57eaf6054594a96e8ac44c8d1765fac4b8cb82fd623726f2f26553aec6fd2f9fb6df751d7d4e19c6c2f6ebcdcb871ab7b735fdca88154d621c5a1f4bbd6da57ff0883ebf3046b3535adeff672db48a6ad73b4ca45fd2d4b4ad02c5f49e0204bd9fd61c5a0e5049a7999eba654025ac4de47099012be7c4c905473c8b0278ba4069d64090bfc72c3045fecff0fae96d17e8a9d20988fba413010ac41b0ee6edd74ab5bad9b966d9b3703b7057b1c028281602de3a0906eb55a2da70d085cb4600aa624750c25a4c09179e75ace08d814489892482b987004234c1e0d3f6416732c00754d9d0250a1a90369e810373025816109260f3c4023a05fbc91e57394d24ea7e322196017c9970daf9617dc719136a48cc501c8fd55d620fecddc714d993e6c9038b70a372f774dab8f830afc4deedbbf2ec39ee0dcdc37d056173181fb78e8e1e6e91f0f5eeee1d65aad6d071bd0e10cc8e30330803740d634eddf1ee1c60dcff372a687f25128e4853cbb43901ff2f63892c0a190a704357fa862f0523ec2dfa8989cdcef0143fe9853a60f2c1e1c8f6c8a270ccd5e214795e5a2c6f111b6b2dc968bdc568bdcf6656f8890fd9d2c6967b8665172571c91ac37166591f8a417d8a22c4a96e8f75b21e4c8e5454b44b64bde43428e5cc0daf279a0288b1e0a04d6295af75eef24304ddd73d58323894abdfa7392f32ba5945ebdcecff4106a02bdcc4d403fd3fe71b9882cbae47c2e382e585c6453e60f17305cc2904293bdbccf37f36ebc97979230fd95e523ef0a8f0829ead782c5054b3685749d1165c604ce1248e4f696dc74a06795d894457916b5052c7a1e2ab787f25037585c7b70a8d0126b81b5bce52d6f79cbefc5f87fc65b3e6a534c4c1886422ebdd3e974b3721d4f27cb1f25f806f408f451e4fe2a2a17853478d98ca624320b12ae1003534b37c19464da985a5e2479cb6d5aa26051c2544c8a68f968a6a9c5b1749802491a2097afe102fae0f2344059b71a2098b8cac70e3dcfcdd92d1779be69e3a38f5ee6db70958f5ee60b2fd8007d007d8d7f01e4f2794f7f8d8fc6f75598f5cc473e4a517ba08873c83373afd10196d9e541efdd9ae96ef9c85b2eeabf2d6fb9cb37e32de21c458f5959f66f7c924791a27e97d2f249d3ec2ce8b22cb49396d1ccc8fd5d44cbd0f9a34f63d7e4f9de01a1739b74823e4d2df30c61ad57244c955dc127db6a1928f6d532623d4d81d2320358417fbd224bf3bd903fec16d287cc4717b4add000b2585d9d5b65ad095a2b12a61fa404d32c12a6255558e8208b249a5441a6aa4c98f505d2e64499484110b20a646d819499a716892e59ac279f9425611a4a4b96e796f25c36523650322bb332992c870f30e83f39b260d897e5f001dee4277f94e0662f95a0f376d6f99395c912abf3b21e517065c9caf2817b0f585bb95db3582c0e68651dcaec8bffe7713c1fd087ce77ef75beebde078e6a9d07b4b2e9a0c5d261cb8404c17dc7ce6c96ce67652eea57872d05feecf7de64d7ba209e680558a4b38e45595467d2af5ad1eccbcaacccbeeccbcaeccbcab258199d592c6d65b68abdb12f2ba3381d6e93d2d9e974acccca6ca4ea0fb75b72a660066b752fc6a150ff3b1192bbb59f49422c2047930b12c957b955f89226eadacf44715246c1f3a3609f9a67e33c05042125777ed2b004d32ca5741185fca2bd1784e66e2ae9b0bb59c4ec342b4f28a801284121f1af07f048cd7d51e27c3e9f77d367ac51a15098d5b5c708572be7fa8b975201d8cc0e88a6edc8e2da132a4db3d5d62cb048dbc4a4439f242a450a3573a494dcfc9a78feb68c19da735f398e93538e40b0611e3adf03279b40bcd705962599a71cf154cd9eeffe83f0842a6c9044155490610ac2f35d8d1846e2a2938b46465ad40fd68802ee96b13f67e5a107cc699ac6cd776dbecf9b65870109d3bf7d19903efaefa70109d346be23e0233a74b8a306580c591094a1d066adf58c35321d521ed8fcc2c0e2cf39a7bbc7a8c86b6f9e37d74e0f06efdfe7310416b58e36a7a6cda975c02a48b218c129726508cc860e3b943107d0118662f060efc206274b2a3631141528c6dc03ac652415284e262a4fbc322747802515285659527101962c4e30b2a412e5ca111cfc39039f21ab9455fe4cd7d0e1045992f38776c22a94923ca76b73ce39a97dca1db1385a0c2c061613d3b90eda176bc7704d2c2d330b62b65a0975d900210fa10a9b31cbc090c5308b130623e5092577dbd0538331a1ff308c8989994e260c6706935d106965c254f8336cc2260c0786f3fa224f50c447244cff0c2a4c25ca153072ff9c7eafdfeb5d8d0a06a39102f7649a69334506285387c70becb5d7e6a0f3d1cc2b3cf84265eaf0d80119d726041f0b1663c8fd349de76cbeb25a2b37623941d9a17f87ce7fea82db43ee7ccb47e3f22def9fcbd734c8b9c131c9a004163fadfb1f1b599a21df2f4015fc345ae6c3caf7432f869c40c9f763f3b132ff63e5d3fab83abcbfe30b2c7e58f9fe074acb58f00587f9f73fac96b17395841731538f2958fc58c9f7c5edeffdb47c843b11873c1f2b2d6325ce37dfa7e1c1eefd78cbedbe56beeff9c4f9f63b9f11cf0b0eb97367993fb14ed322b8a752a9d44ce5d8215b5fb7358bef21ddd40d854231969b2db0020a382611e7309e6012433348c5621c77e7dc5e24e54ee6348fcc72c4880eb34dd204ea0245e2a7090365c1dd4120910106b85f861496e1094cbf471898bec300cfbfa04802cf1a28dedfc1e6acfdfb0097c0f3066e2fdb77401eb4970d34d2617b423132cc794ff7769867e4500cf0fd9b8bb4cc2cc2037234692045fd3a74dcb851a34637db4f1df2080226222475475df7c916d19013cca426943014d4d121b5af75375cf005d3f86f09ec9ed4378be8027f4ea5b69bf28e5a4badedc09a54ca6b249142c95ad6b29c7bc3f086375658d3646128c7e82c4d54b2ce3a7dce39a7bb7ba2d80002961dbadf98f252985f44a39ca669367860a0c8f6b0ab69b7d3d93e6ae3d889ab358e231ef188471f613ce2711c65a9ab51f9688b89aaa624359b896635cb5aab75357819636f168e2c362b8f2df3d24629ead6c67e5950c4230efe33d5e1fca904f56921122a1b64c9fe0d576091c5cb8a3714ebe4358eab6eb1c6daac19d63a8e2eee0aef3e464c29b5d62bb5efee374a4ecc4cdb74a8697d330ebd2706045e0c4abfb296853126596a59ea2ac8d11cbb26b95b368198a9266311173519b10ee4d032f55229c2026a026bae06030bb97fdb42ee770722f75f998469d9189ba377f7d61e1664afd7ebbeeeebbe7c74efebbe64a9e6d27ded7616ef84210622cc579e04b8027b40c0409a6c7776f3abf88e2c60f1abdcbcbed93d37d3dc378df71214e7d80169ee7b689e0cb9cf8134dcdfcebfd4f7fcfd97219ebfef012fcd7d0f7ca9e090ee3b3e3ca9efc3fdcefbd3ee4502f73b3fe4821355c1211c384f2f0e0a31f96bc28c8037b0c7d74bc21461335db3f5a222617a52c1056c3a41092f09d39fc3ffffbdaf576d0f0b37afb03ff47062be4714b8badcc949192973ffbe74773a9d9fdbedbc87d334ae394de33ca04dfdd42bdcbc3c9f4ed33a4dcbf9d4936786650c2d60f9784020b0584791c65c55555746c87a842c8d158565fee8403a465d2265281670ea1850dc64b7764a957b6f28bfe7b340ba2edadef36d1c27615cb898b3a5bb5b1baac105ee1c2e60018981224464c9e6cc201320a51419ea9e73d6a826eb8acfa74a8e9c9a26352d14037d4d8b6aadfbed30141243e67581adf5a0c02fa1cc71628b2aa6c005186401c7d41eb00711b0286faa844288ecc8026f2f860fd86180d08794a1aea9695a8873031aa3301e60e0f9378874cdd4d4dc3629dbc10416a51644d21113d0b0c4565befb66d5bbbbb6bfab052985978282fa7bbd33e9e4eb5540abb448eaa8cfb1e65a98544c7f31f0dbf25c22eb12a0c56d965a23b83525a2dbd9d2773dd93f6c7650a06819f05dd0e08c83dbc0ca1a6ee656ec2fdccde1744102c7893f72c8831750f7a5ba96abe3c2224025272867eedf346afe5226900d1a3419633889e0d72bfc7e52d619d31e3400fe59d2e66b4d24a2466c3c6bd37e7ded147f7de7be7cf3bde71ac94def185982c5d23a4bc4ae43b84139984b1600c912d16eccb451d6b96f6059ef78eb234f312399a41e2e62ec144ebda68ef1aa5f48ea30d1767869f5e965c4a5196b2bbc3755c4a29a594528274a454b31d6a9f7e3b24d961e6ed1e91b37b7fa6ddddb99f718d036fe815d3df5872d7e93059c188f8e90303d578efd5e1c610300f2ab028655794578cc8d22b071a44ca54d7126cbdeffefe3ebbb76ddb6c362bb5ce395bd3c21b29ea2863fc5e8c43a1ff30f45cd7755d9717c56c16bb321cde9ff373cd54d58bb3ad5057a194d629f5d5eab0ab4d6eafded016cc959bdebc7c64552eea3aa5ded059bdb135d689b5ab0e9bc25630180ce6b2570957cca462c8b0a91825098825092bdd1e5960fa443050ebdf3a89146182e98b1256ab65825d479e79d674785975d5e1dbafce808495931ee930d93a565587b49f888fe8bd188742d5094e689ebeaba010222e3a610b56565d3dc1fe625d7d41448afac590a13852d29c0ebb7abe713a9c75485fa43f4d1d50ba88aba00a3ba775b7d65b6bad9d2a2b22619a888f3ab665ee7f9145519e12468b20e2a2a6589014a7e5a55bc8fdd424bb5a6b056b544848d1fc284c2c916775816490e326c70b3b815978b59233dda3068bdbb8a9b6d147d5d4ff2dd1a7d5c94f787572fcd19e85c2a12d88938ff01252d4cf042a8a94950537d476d2401a2f7c93471d66604c0377032147b36bb490fbbde567dab3cb47fdc27bafc30c1c53e35ff809a5452dce295556f38727f7632738706409b37ca48307863a507c0b8a2198024c9fc3c1046f7d3aadfa94056f2bbcf21135f56cfae89fb2dbfa4c57ee17fe806208f6b1dc2f7cb7c667b1b4a83fe7da2c388890922f22f7d730b9c9b22b9f8d49182b16666f687cbd3a754d8b4e3e6a21a4d827500c654a9f7e4dfff3325ef948487f8408916f9a881eb793d602f60937aaa505a449626a6901f10ad760151ef10a8f37a8c0225ee155eed52ac70d6e17273829659d970fe8b0a5f63620f1d66a60e7f3728f2598fbcda7160a99e91e3bc0d2451774197640117f9e06bff71f90469a40ff79ae83bf970dfdafedf5554cd1224f500baa2cfedd3a1cd7e974544cfea5a7b72f306cce29a66bb6723ead8fa6693978c0a7108e9ae3744945ab63681d13b5c385c5d9d2642c8b21eeb51e7a44da801c695f8414f39107a4a847a0ac426e0d74504716650c0b0d1bcdf5a8c99aab160ca1a9e59032348607c7d9b86a5438d65121679248a49983079872d2b525cccfc7118e50b56ddb444fe882b497b9fbb2ab61e6fb127ca9f7e9cfccd91aeca5b756ed45d24c87f44592f350824552056bb059e3b419d2e7961af8354cdc54a1e1d202c21f0f898f68802ef7b660dc3351ce6084c0af43bd9d2791484d38a114d404a6ede93a0fc7719c13d60c49df78bae3440af7de23482477f72a046725066bd9409163cac88d0d3d7448ae4f5cd8c33f8b4fcfa2468d7b319628890a2b6ace9c7b31fea73315070cb06751bab48a8a8909c3af2d436025d9082e10c10c134d12508c1d986423802689dc626585e949e793844e98b9c0f4e4fe4b2cb8f05f51346e64494a41c445dd8282b97c4b915c95d454457538eb5f9a27433cef695c9ee6c910d07b208df7a0a7f19726bfdbcb0e0828ba7c342d204dcbbbd0b8fc4b4704148b48609aa48b4cd245be4392dcd95a66ee74c00fc944790d125932428ebce54af8eb895b0145742c664eb374d8f78914f537e1ca50e42956e44ea2a2b0404998eb44c260c11a584f331e34b5e6abaa8a9af933bd0ad6110ad8c1ded18519d570669e74430a166b45d5a82aaaa26ab03c0d72b1582c96dbc962dd1d536071b2b656e7bb3e127247d19943984fcc22e4fe6ddb1e7f7e83d2a18fb268d9678be5e06459111b66dddd59ace6dae3c4ebdedb3dbb59c51461cc50590c6b77ad6d9ab6f5bd634d1886d11b2a140a5509c95987302b4c68491fd956cbc63ad4b421600b8a01166d8bce3a9f82a894eeb50545c968060000800083140000200c0a8683e1906048301e47f7061480096a7e46785a389707644194e5380a628c31461a020800801802a6466c8840001ad35242247515dd25aea9bd1a815eb13b684f591a12e5e2936f07005b91e1280395374a407da2a5fa2210d60d5434e3000446e8254883c0e8082f937664ab41307f8e43c53b3df9214aed61572b1ce2ad97a1cc323d1aa8c59eeff5747a3451153be82b1c293b3ebd73aa827cc48be50b89aabc9622163eee20ef807562c16c2a6b314a8d6a60791b1cb3d50c5595fd6248ee8f2f4c5e7c4b6228d43f319abeed966c94ddf12a233bcfa2a6700f5a1246bce30668549ba375d34189d49b3f5623f8448a707c222d683e61e4096b3b9a3e81cdfecfec11b16b0a315b34081a101288b026c199e6756e1658c5c6585db0aa20ca9d206e649b236e3867254e42966fb596c4572163a29603a08a05622c1a8164bf70c57e235f4988c2c5ef111a1ba5ca98f2fb8dae5c2e2c21a904cd86b58d80d468474dd21d0a97dc76e5ed7ab4f29c8a51e17124bc73ed4189df74bc81424c1321c1f65c2e7dc5dd8610ffab3780f4c95e8602c2f9b550b0cea4380b464ce46cea4746dbab8c8a32c7121946c0512c6f945668868d821e52c31efd58e2b80e46eea42ead5a2a6fd3b02f505bc2e9c793b166242b2c2c2e5f3e8c46b642e630e67b7116ec0953b2577cf6080e775ebedb294a2e77a36220fb4c5af98c39c9b80435034a053300aa68666986d2f655117f68e687e033db859379ca671893624670f2d762e9ae0fd4c2f1dfd186fe3d35519fff39fe9bb4563e1cb4fad2d400d550c487eb1cd85a1f2d9d10f503a1a82bf522d75aceb7d711fd2cf3cca0527dee80786ca9ed53d1a0cef6faa349616d70a28525f2b8ec8bd0626316e61f358935b0e7ba97be1833d150a38d050f13fc02b189a98d7d995942aa17eb56b7ef4ce2f80b3c45455998a70b38a1d5ddc1186a73104db8f226875f21b415e98ee9097225b982cdd68e3586e00fee1b0ad841c54f92c9ee9ce8ace47de7d72c2784dceaf1c4d7c58d114319c7e6ceef8342546d0b4a291368f8c9a23258079f081bbc9b023e2891deab175090f42be2f395a13c7523581df68b39ed85855944c6f99c3602e0a83a59e9737b5455154280c1d7c9bbeb0eb9af43da1dee264bfff8e5749c6ae7d60e9fc6921a8dac6d892e3eb026998dab0511ac24bb1dfe4aebec3f1c68867366fe6cf3077758b7b933f57318f22a1a06d621eebcb29bf1a5b44d04f6a629177780b0b54dd21d95fe77dc91dbf37c8d7bed54d0a9ae744d930fd4a1acd2f370026b2bfbd28596dae134a79d8913896baa4bedb089ce1bae748c638aeeb49322bd1bf1b273adf9110235da41b4a47808cc2608dc583528901d7065d4eaca3d90cceb38d21d93ba6f486a6d020db715c1dd91abb4aad177271d976a75d24b2f0892bc943b46285f893fe5f07e6e41a017ef0b39b7543f17babb1f6567d95a93a5b4905b3c5f667376dc5880e2f2b34ea7a59f683f6021d88fe8ebe319828f28b89d74e3623d51e3d702636ef4df3e75eac947a6f796fcb29c16a111c9404a7f2954b9ba689c2247bd99208978cdbe6a7badbdcdf8d31912522e3dccf570ebcbb51ba0c2dd951a71a9d3cef7a34a664be2252f2e12f1f931798f96bbb90f4c6eb4e4c779e88f9c914a19a9e00d5da8aadf2ca002b29f80e4508163a704b12042f4149f0a34cc85691cf5b9fb16cd377472118fed2c882b486a29309d3bd6d51d468d8f5247624536875856f0f09aef960224e1e8ed563fad2a8b925f6e81a77767016f8a8e626fc30ad4de082f33b7e30d041bf9d83c0eec99436f1cefbc4b2a75f222172853d70de7611aa236e2af1d9c43dce85e7ab6481b7ac00a1cc1ce2522143bbe8db98909817722b5e381a4765353a229156077f6a738f398be0095b551b1fba45e3e80d4814f34e13fee56435bce74a1ab63e7d7f1d00621708d81b94890d20ef8ed27c1f899e31a0404828ef6887d8e5b605d8db427d65ade2f9ae584151ef682c401e708816962161a8470f1dbadc2085e92b591fcca6c66e4fb5cb4db43aaec92e9a3196d464d5e93c81834447948a26534fd87cfcef9d527cfa0c22f3f2ae7d1f4ef22e028ab4c4e7f7dc11bd83f50413b39b344e2f945b6f61c819bc5a983ba97b9e8c678d22ffadaad715ee6a160a9b3f8cee850103694aff8eda216e8ed416ca4b602589029255f97d7214d323a943681463e563d075fb0ea4816b696f10c66753c2abbe1266646e74943699faddcfe58501e7cae44cbeaae05853b2bc484ad84e28b471f261d6ca41a090c415fad0920b123ca408b6b0befb34f64d0fb121b77b25ee94f1f61282b2d2dc7ab4e73fac76a0291bcbf1bb212004d431014b13f26c6cdbbf91ab8528838dad23e9235dcdd369ab5c3bfd9c493747dd7eafe0a2e8ea05bee2679a502f96feee3b2930d56690b77f4ad965913ec1fc193163cc1ce896ba0c792ef35dc4307c4227d0a681bd7d8c03fb1317e128c645720b720187401873c6ca93782c65691b5143d90b0c0a22e788cd2a890026e9567ba97ee10a58e8f4be51f3f9f2f82383d2e87c7c331e719bb2d4cd201adb4538ff2719d0ebe9215e01a232c2108044fe00681f0289a15365b39cac829cb297e0037cc15406ab2863c7371e73fd7d20459379fe60d64bd92f3f5260cc6c0b690aa08f46ba1885084a0688832b09265489ccd9d457f98dea5931e462ea40698808c432a3c9d2863f0a09bbda496da4403326e91e5725ca2eb66d1b4e9b8a2cc250ef85c397335d127a85ac5da441cff651fa4ad5981b833c242c783a180512b063cdccf8d2314431606b7144e21f8e4730ed8ed1bb883b6382df6ef74dc7f06f27f08bcb1db10b369561bc884ea1894d4469054720f6c4a2a185444820873cf73a11bde7a776e6d0217920c057ee2bd4b3958991fcb2f50f400b3387e1f84c55198a8e87a4f460d539f28d260d943ddd5ae07a9eca4bf8eefa5145a8c0e3a78336a688f492e996ab8a56283122b68c858cbc5400f7301f785bee22d0dc53fb134ec25cba8187c5730da9a378549c328d5774995bcc165f9c04304afa308ed2e8901740314631ac3b13cac3f85ec79d267cc9442d775cc0d52bb97199192d4497b4b3cdebb927db7bd410d1cee745d3a7cdbd022b887d12b4faaf0690b9cad772a1871d83f2d0396564a5b380f86919887dbe5190baebdc0333f355bf7f494aa9fa10e4cdcd4cfbd2f6c973d61b5b854c0e700fa147846c517c56a37bbc6e4eda39b526d14fe64494ad792e95b6875718ee0d92cc816a5094d8434a58397ed4cbb5862a1574e06ad975f12db225beb7b58fa7d2f4bbbec8207996d74fb13fb2fa291cde27d131af34ad5506dc2ed56d9edca3514da72170971b34f7fae2fc02493e25672539c3e4d25208a7a57a0afa5e299c440ddd3898a787c922ab0fe5ec5ead20e97d02da5aea9c348148e98ab9ea6fc1e318051ec5818857129e3fe52b346fa3ee6346b45775082b7352135fb2892c7cb1731089d0387b19dd4691331333f2dbbe935642d9b53db333d8c5f8640c04d1ddadc5ad4b92b568ce5db9633a3387bfe14b3181576c57c98c0d68f2b45261b7b614748d092430890e1a509dc61f40686b5689eea15fd9e5d704d0607781105a440aa4561986745d9f8d392e6a4ef31e44ffd2ffe6c907e4d3774079029d31eadc2fcf4a64d65a917945e792d5640b4fbbb97bea9db8786ab457e5adb3a1723767df504cc413641f444001f718f6fff11e9f0ad28b1e8fc2db0dc53b6f9c7646ff3e24cf51ea2ec7896ea8fd8b633062068b8e72950eff65fa1a3518b43dba683174ee80ee8869195af357003ec3a23dda5407b5321814c049f600b73eed059fa8ab028b95f03e71581974b8f1f0e8f0ef83bb60cf33a695036740901601792ee57190abd932d05d7243250cac7fe450d03a1739a8c21689851202f1994b8bdf73e2e76cb09106c431f3aa0afafe1fa83691190dd18a7cc9d7cc3822f9cb434c7699c6aad130f78e5ad6c76e657396794a2da5151d74e12e1ee8f1a74f25e60298a9126456ac2e553db5fba0aef2755814cfa94e1f6c0ba8c3c77f4a3a95509e6e794dc8f7ee6fd78abdd2b045bc0a26ef6560410c63bed05a43d9858d79dedb47f9288cdc04843476102c82c6604147dde05de7c8b8c9f45731112eed495ccdb31db83bbb968ac61900946c6f154ae3163575a29f82e8b94566656ea014d72876c34c5da7a23015a85df05178a947b448ea59edae8c111922d1a220e9878b086de5419810cc52ad341d8e781f9bf849f72b1ca734177852e232e35e6f2c5881f2d84954676b4682445a15395a3d0f915d29803fde0c1d7955add5333aa09d3cccbbaf9f21c32135389ea4acd483bc7e7d5bb61e3d9b7ba8308615fcb5fefbab56cde38a817b9d9329b3aade619998470a15bbc4a88b71b2e1613a1df3c5ee0be45428a5034673a2cc740c237a1dcfdd07b56e03e6ff3aca19a4c665afbbc644185201f77e61226d193e394429897df1c1ce11932aa23cbd6a8c4d6200479465c5183d84f412db145aacc1996e3e8555ee3a302d26cbd2947807b14051e8925393c4a1d29a30c89f246cff02da9493f7a06fd998dd5c34e543a7d804eaa99f7bf3a25c664ec01615463d18705aaffd203035520caca3049c05fd2eb7aa33b488c94651523f1046324a8616124a14f1ff259ea200e42b422c5871a8d0e01eb8316c2671f9244285b30d02f3c242fc0188de2470a76eea3414303093f3ff1d1309a7ef508fc32207c17eb5654658fcb667e6aeb34b52b1a696ae500dd6e1b19d50229555f1546dc4ebda087dda36b0e53ab2ac61ef38ffa244f39a78ff6f933f7783184b1ce1269309531b4546f69b514a026377b1ff3c0d4c50b0d53c672045dc67900ad99322939796e6e226182663889720d49553ba44fc1665596e006d8348adc96371c2ec5d60a1ede52d6a8b3b3146e72d06af5ed31ee591e071b3fcd1be3f990c012ace2b3ef3cc694c19e25f7886311999bee4712a57d042d8f5c410bfa2767c5cee7058c5d742349a03ccdc4550f87b33007fbee823637b1c6cc47ce13e62da9ae463388ee6e62e4209f5a9f07de7af81c2a48f72cf418f397c14f0467bf0e47d8d54f364e47450827a8d83ec05e5c80df651c44a8800dd4a66bf0820753eaad2ef8b5d5667dac02a4a9101503541db6e89afd8c4a53626c39cbef710ff57df37040e18008bbd2d8163eb2bc2096308f0ebd3d2b8c59e7473ded2159e1ff7946211001b236dfb3330db0ab56e8ae5a20d9c2fe69f97fc8b6f3a7eeb19d74f987f86ce6beb81a7e8f78beba3028ee1b9784d949544c64ad4c88c687edeb4118a37c277084986ecd1f7006d2544eca2e301a11121208481165b039077c1a2115249bef9c99a790a42bbfde4d649b5d4ec77a690b00cd0737c26436a3d40e93361d7b34683833424c2b386ec486adb99c30c76a5fde823791a3832cce0bb883373343730694f11f98068dd35ec68afc1f8041637ca965ba98512402bee0f049689063c12110632a47ec1ae294430fd497f31017c15df28fc0cde13f192708d57aa2944786ee7b2d30ef3c3a06615903de899e8b9b6de8ea9cc6392f078eb071c02faba22b04b97df8f40216f808d9d6d3a0c90e9a793545df12e77493ac2fda696f315c5fa26d723a4a8bdac2718ce973647e19127642f2dea87b84642ce065c4bfaecf886c29cedbdf2974f7a4f2ac33a407ca21160af3f111c0d1b7e23d9cd2ab5ed8b288663b84de659137e4e6f3c74ab2af4320d25fd3de3a8c6777bdcb29dc4761dd6f7d8b54c83023111cc0e143b68c01abb4fd221d1c0ec2187a29593ccbc99dea46c7b3c84baa814e49e7a2e6a1214ee5624b52143cc0eecb2d676385fceab7946a52a91701afce00ddca67e2a651c26ef9b222c0dbd7a959b97a0da44765c68b2c32a91825c4ac130ae684167e418f6558556140f50a3e7f876b99e4928981b297fa7b140d9355c4cbe4078884e16df95c9cceedc1d67669da8d873cfed61fba9194e4e59e0d0f2ac17f117f70b16be7d294b743f17301230545af7f886f700fc58fefba5e769897897bf141e2266a418ae5fcafef04b5cbe128c563848113a67ae190e094ff2d7bf4adf58bd83bc0315af29bc4e42b6789e9f447e3b090c3b617191410feeac5258fe55e4cfba3db1f027527f5b0a0f545a238578df60b7d7160c7719415d53502822917951c3bc6e309c69be1a067b5b87e200fdfb161193f736826957c480b14205bb019e304d1c08e621a20d77a0133e010e5c1280d5f178217e4a0c4ba11120a80dd081f53099b32d8f8d186d7d20383aaf732bdb8e245012357c07efbba849ad02210debee21bd2995a90b87e120abede046b0f16dfcf5eee4cb9422c64551558089c34c6455fd927435e3b7046a1ec2fe75d161cbc9bd683f49d5a40bacb94c2f40e02c559930a66f84593184ede64c997d63f45c3aa7c917b8d30c76d02a03d27fc67e7891c593b018f54f68a51b1df174d5a966acb929b35a7d4770f1effd3fc36ff55fa2dde207600a7eca42c08c6d78decbf02e713c79df46baba7dcb673136dba46f2871d3f1bc76fff4faab721a390a93dee33583eceae2809b71c97b1f7b417a97b34e0cc89e53f77df8a8d355d63712d3ddbc2b5a48afee9b5a399a1b1a42f7f54042726d9b4c4389e101396c96267fcb253829c42b49a0f0e29df189ec643912a9edf47999177c71547c199a3a063ade3de8264e07b40beee1eacc23187588c4181112c176693e6a5dba1baafd1ece46af8a055cc4d315de8c64262ca93f8ea0bf2e3cfeace9545810328f729de075297880ba8426ffc2f62c3aaa59362fd1aa8c1b75e52a7232ac2c8736a8f301dcb5b9297ad4e62f96ff97a93e419fc0039a4b0e50407bc022a5e076ae8f56c7249b6aaa017ea2e883218faa9720f46b559c29b4566a570bc6d96ebd9d858b7b297a623f331dadaf75e2246d4955d3483105f7f569f2a3fcac29b149994d12df555b986051ea205dfc3b3df8a34f874f0b54b3b7a7304a39d479441705146215fec87802da013d594c1ad9d87ec7fa2326154261f62ba632ad0c84804a0f6dfcdae9a153e155f15933ae606a171b85c4aec5b4abdb19ccbdfc54cb14943be06c5dcde8542266b71b3c2f0d889671dc32a4c3bd9046eb370fb0eae014e9e227fba17c1fb8ec0ba0b0f114cb43c67751efce48d11e73fd1d202089de111638ceb719a48a78105cdd70d7f17a17b76eab72e1a1adcd71458dde8a3df1b0dfc96649647feb8e63f48a2839a51bed4547e4a9f95a826664e522b2018c59f07c4d45a2a8321fbba03b7fb514f4ea4c6c93bb21df88b60ebd75258b94c93b01749e9afd4340482fe2e1a6f04c817feb935aa96911225799e903f768884baf8b9fc1ef96015be73f9a8df535d5774eeb438301abd695b6f048a1b5ca2023886de887e4c97480e272859f0b9b38f0c8a7a0e3495aeb31b1d44e1e099b2532c3ceba74984e18b6e92bcf8d5159eb16ea7d85cea366a522818a077cb9f718228e5b7307069c85554b545ec4d59aeb587390ab86d8e1488532806b07f7cdef024f1e5fd28eac181cfb8a2dd250eb67127a762e112d7ff9cf3c769bcedfb5221d1cd63403b39568cefee9180a9021f0f8bf8606e8a1604e13a49608d635463ea0bcc3ba3fdfe880a5c7defcea98d852176cc3b3373e715ce30aa0ce0a0987df9dbddf022381bf9e7cfbaa159aaba58b07c7a34752eafe5e549a351850b0664801a0fc32d6647b38a0b49f88f80a402f2910baf0df0ccdfd8876b697ec5e9d54630bf04b8638c95339590eeeb01fd4d7de6c13a3fcb0aa2d5f81bba4a561cf997f144a1213870798cce37cca85a6721d84190d9f2610801536b2ed213f7b72c23cc05c62f3ced50149aceeb5a21b5b36703354a42ff4a157ce2006e7bfb9e50e40658c97ab0adbc4304e444117bf15fe3a2ca2a78de18d915dc87cdc3f474f07dc2dfdbdb7da584c32ce01460a1773e3744918e2308b8753b31e4edb1b136a4fd0966b7c842e9641d6b3afef2c182061be14279e196845c715029dc21252a181a5c1883252023e447c88fe1ad94b18b31ef2ccb07010178b61b7611e69250d0614880cff227710d150757c4837ee649e18dbd3843a923a2df34b0dbf82559acabf4590a04bf6812af248e5689e612e11a88fe5c24d3ce4a1754ec1f61674ef6a98468694347c9df6069fd2ee2eddeb2913980c4c62c2f1b97342603c3183b1364cb7dd756eb2ef8a464481a9da05d2b206c9eed196036fc478b58fc035999259c92965ccc26ca694d194661cd0234a2c4db85da661751618a7415c0fe64f14559713cb84853de1db24398ba8caeab81958c2658d1ba78ac23cfcbec96b2c0a24230236760d3da3926a900461a8a1a62d5b1341b08eacf71ab1d08dbfe50143bcfdb069d5c75bf495ff6f98f63c4a84844d7a65409efe07cc9c3f2c67c232556e7005143e5353b53d7a26abdefb0d325621a1dd0c587323349bd57fb1e082340a788073a3bb67c2d0763b50080887e786624022eb8b3c8be4495d20595378c971c079d704b28121332784f6766ea7bcd3f23f3e5286aab3ee94174131287962195cf5bd2138a567d9d47ce4c95168488ac9382cad4a25d1716a0056d43acc83d7b7dba4c5d42487f168a9c34d866209871cbfc3f5af3df77ba506e6dd582e21e867f74a26a31a263a1a126bd161d81570895ae3e48e7a6b210811331aca6b3b1f675681305f656aca37bd6af4dc32d51c2a158cd595d1e0a9dc771a50cc39db78c836ab5e6841ff4200bf5b061219ef4ffdf6d31f9a5bc1159d4407a9f607b31cb1f06f1cac9f9c5056b5055add2fd5999820819365b0b6481c2d944ba9bdc2eb1ddb6fcb2902e87fb5b2c848c3ae2714f1d77348001f5e6e0ebfc18dfc0413e68103275b2b1dd301f900788534b00f5b301906eb38981b338fcb368f1d04b7ba73f56a1c006591080ed1f87b7c0317c1cc6132452ffb1a933c740b0544df8bf45a0deda8b1656f8493970c416c2e50fb7130591168c2fe9ee176df6490555421497d7d1c944bf5e079fe890a89615f2b574b9263d2b8a59974612c5076bb9ae5fa953ad5909c0a73f708332671d94906c5181f04921dff2452f47a12602d5d3a25018771f4621b37ba35bc9e6aa93561f53ea001d670863b4a7556f6fce9834a6063e1e0bcb022904e8e2249c360d911f8e19fd7c7773cf0c70c3848b27c2933b75895c41db11a4ed509b70d90669416c05d1facb869b7406a11239b7cb78f1f6321b70a026748d0b6bf0a17f956afb50f20fd52628242cd4cf4910df09516801e232d35e5a09d60c9c84e96b52167753f6d001b06a6a91cab7437448d854a2bc488b48c1b510ed721e42af74594d81e06ce5f831a8fe17b6fae02a6a3a25b45bb78d042c3c4a72c7b56be30852490ee91d9d72fb509f4770b25fbcecba1eebba786c6cc3edf65289a3a7d521a80707c00f2252f3cb20d570184d163ae7be0f517e90cd2787186b4645eed11c721c4badc09a1f7992ecca001feda1d21f221c296cfd21d244b07db898f67f6396a27c9156d45bc221e26c3a45a1ee78e9db8e0c194343001f898ec3e39453a67fee72804bf9d853939c46092af30107ab074f1d3c0145fc4a67ced4314185a0e28a165c5d226b01baa30aeb2d839e7354f15024b9da181c1d7f7610a0840b99a5e1302ee4ff16dfd53a81185a9d7a508ff0bd3e2071b5dd28ce329d06e4b90d483ec0cb0c9d6dca1a95615a46eab3059ba8653d2accbc04170a2de77b35e7217ad9eedfa1d2dd3f5e37c06a95ed33c80f5d0b155c9d2a4e34e01f94346e37c7b0d06bceeb34fd501be60430a9f2548832740715f2f25ffb2a7387476dc51894fb89b1d9b19d0020c853af062c5d5ec0f08a6394c5fa1652bf45e452602570b90b411741a59041bcc8d120fc965b7ea663f636c06c0a4c6a2b99208db60f3cc22f3906e24d172507f823311675b0dbe39fce4d234de175d7b2734d4723d287673f1f36ba732e7508eedceed03ef889ea5f2d1f84e6e842c825682a987a6b4df7486e7d6e7fa1583bedd291eee7276789af29cc3ed61005c040c72c0285e8fcfc34813658b07a6084612e15ce429ab6851285284fcf101599573a2cf33c939599da526772ca7f1ba167f88b868eccbc15e65eb5cca9e18b855521bb0228156651247eee9b28b2b03c0641d137bfbd33585152680ba7a8a414562a0401704e8594f0306020e9f0685e3d7529901241ec5c0ab85978c7a83ef088ffdf341bca436910f1a0fce055b7cde39b8f6c2ca2091055707f606505fe0536bf79a0c628090a78533febacdaab21760297e567c1faf220000e10e2e99f30079c864dddc11aa7df2258ede8a7c4a6787e79799436f77fbdcfd69629294d574f3cff9034fa9edf3bda38615f570a5840f3598732c584d88e2bb2a465a412803edc11d29cea511fb217f0fb154a8e08dd6996a0c083dd0442550348b869206809fe5df92508a7474851ca81a92a46d559d040dd8680c008ac08aaf8dec735110b05264928c52c24fbfc91b2c665316f7e55fd0bc55053aee5dceda0f0e2b120aa0c8058e3ce02454d917063de20573cf9ba48884cd02e6f1794fd090eeaafec974c7a15e1fe9f412b78333acff701f8ec7c277cd8e244b6d4f100750f53608517fc92174e1a2f25e3a3b46c94643d90e8a687ac919a4fd293dfbcd558452fe720c82856627d187f87a2c5dedf56cc1510cdda7939060fe2c66155b63957fb510aa4f681b626c392441d5d4a1b482fcf4021c7dc68d800c4e1c24e9ad1b3b4de3d11390b54d2d5a187b233d9969ef323b3712e48387890033ace1acd43d72ece6212bc3fcad79a5f76d771b218124a65e863a238b385b3f4b5f925dadfc1b9c1867a31f623eb73c282b38c599af4fc9fb2d06cf4be8a27101b62cb24a46fdf6d7b9828890eda25228c1e6b5e01427655176c03e4bea1605bd05c351d79f270a50b794c6779ac7968f4a253656d08ac8d21d5ca401b336ddc6c5fbbcf1456d279ba069a2775293832cc455018a380f9057c12a93514d533fd23061067feb47d571b6eef982a20723c4fd626337cf4ced5fcbc620725085aa8965fb81bfe7a0589ccf93e31233bf39afa83f099fb4c1e79219d3219e2c696b5df3530924dae7f3068fc2a6b539b449ecfceae04c03d014eca253180e2f7f91dfe6f2c8144427955944d9c3fe94828917372d00dedfbf6173298e29632f2c3d6c6faff40cc81bb1f50c069fc77c91cb585cf59885719c290bf7cb2b75be049eb3efd396a95059ca5686eecbaa0064a7165f3c9f45401d32def76106f86085980fe11572d8dccd7473ba49f034347e6ab34d22f02ba4014382c54a145477b9cc1a9ea54d30a004289ad6665bc7e391659fcdf297b167718cc3a5af31928b0bfef88128362cf28edbb13a67913b5029b82ad349eeaefb176301e765bbd46475231c8b921a1aaa072068396da180b8caabfa9f947d6350fb8d3488c99f61030b8a0881d96fde491bf09a0c9737e7a31b2e20625da2166ff045a61b42cb39687fd2877d316b505df7f0807f11dc8118aacb56d6a1af6c90f44228c19c5e761d527aefad365ce8d50d8fa13c9f40457e6718086d3fa4cae121ceb4ac270214463558bcefbc7808d71056309be84e2659cede327d07aa7b59cfac95c438a801f0c921093011a0b4175812bc8d4d5874c8d3e5296de8f9c4deb4c79665d3ab1c952443af6b451950afa9293ed22b89edff93884bc938e72574f66337624b8c27cb46fc00c4f84202b526135c15169c4962dccddb6bbda55bb0b18a079e0c4bb381682c42ba27ab6f11cd999b62b5060db8b3354e5cf84521f2af8c05614fcc0cf91515e91537e587ebef3bb3a0c976b3436ed385a4026de29a16593744503b0a30fbb5add02d851594e6b3e5fc914983eca6a572f51c025361d3e3c20c4ffa26355af4326be333ffbdb0a5322af292887b90ed060e8b052ee70b60f6d826b4c75c89a94a3093fa46f91637dfa81fd7e07822c77f7e88c6885463bd01528a420857e0071e89b2ec1003e21fa931c9ee3f80367faef174c9d9887e1062c5ddd5c6497e2686b258480dbf1f4deb1acdcc02487a340843889111f82e1fa5a58b3ee47aa202f3a614c0771e88e5b503e6b40b913b6d3174b47932b737b349303ce07b62e7b3577386c99c4d2c4076edbe4c459728bd9fe57c21c6eff2aa4e3f76a0ebebe434e89a9e79ed98a6de80236e8134243f1b6e828b0d7a910c20fd50be70b98bffd94278c59fc6d3c5f40b61f2eb7e41c64bb03bd87f520633204d60346338cb11566b98431898ee08155d205ca1550f140e07492ccc8e6813ed10de83730d6891f2374e48227cae408b9db53c4aafed1fd77a54cef20c2777ad39c6c30e4cedafc49088a4a43ef267f8f30afaaae01386c4b7d754f0ad31dd909d34c3da32ce6c6bdfc2522bd72d43cc7f8606c29dbc161d0d0aa025be078585826009b284ff089c73533d9d9f5bc953664a5fcf9568aac7c3e54aa94addbe1e54ead5b6925956be0a77795afe6a7cda311c80569afe424c24b86f456cd29cdb08347551beacec138f824976537908197a959234cfbc09ce1841258d8324fa48c416f26fba42653e2cebf0f6e854721dcdca8b482a18542eb1fca0170cab1257f982702f79cf8ad849238baf659eedc36bb753560a07d11dd5609f0bf98706b7f0e3b13bdb63f0c59406e6dca73ab201a3c7c799790bac98f3dcef77bd53bebb0f2e715cef82988a2834ca1f75b87a10a902cb89d42a6b255943ab542b5c7b37dbb5b2a8795dd0ed662eed0fe0d2b5c09748ff378a9b7a95d5ec538778831ac416fca3c42641e381cc21a6056acd516c86afcbd332b7cdb0d7d22a4cb73ffc2a86df00c38c3be0c641f66f490e93cedc5a3f648e59fec32cfe2abee6cf12de5f9da13912667dd9e323d1c32f1c935d6f856444551fc621acc75eb70ede3bb38ef740e6f228fbdc01c7147966cc379ec436f59f38734a6bc38d316d0cc232aba8be940ebd0af2062ad5f13365ecf2d9ace2c485d9d550085603ee7a802fcb4227aef875b6931a78616210ed38b1ac60387bf7a62a793656302fe86012703e3b0104e91028dc443d144a8cfa4b3ea55bda0a102ac10dbb51395d5748a0c768280684763d0455fc3a8ad81ab3821aaadd4b0b51e75696b0185a7990d780b0a3952429040442e76bf74b583d733a0462b6e2f2302e9cc0f7f782291136147c5de04ae63d346c5d47c900bb97c4e7326d019ad298eff44d7f4d351e875c33889e4885cafaced34ff562787c3004a79a568825ece55113c8d2e742716ea2406167e0e1690a480dc16830a0bc80335b5a1d28cea029a96b253da941787987895a41d88edbaf4e71bf53b52492a52c9df1482b7715b793d5b54ee9752010f4abd71722aa57cbc793113b5e4b1ea4492e47336a18501385c386d70b2e46b425e7b71870f6f4435dca86ecc81e7283faf857b5fadee2a512717fc031d803f65b6dd7a6d9924fe6e3afde8957b156b6e712ebdfb1f9e505a0deffb832394f9580994142fea3e5716a1afb387dcbc802cb9028a2a5063c148374538082c6c92859e15b6ed846cb4dc8206835b0ed5b1c39fa91c2b8814128868452f20e17b4ad8635f796fe1d56efb27c223617838529ac4b3b153998c40b1a083b440dee87812e76eecaa031f40840a33bec2110413be7620882b16607c64cae0d78b8d10f32a18e62750b744152a5ebc768b0f83a2ac85af02e07456240f836a086b9e341f4b3346164f01f1be4858fb37d1463ee1063e9b02768570f0dca05696f839384f4fcb053300822af0795a71dc0912605b00824183b3be9d9e709e53851d8fcbcbbe541cad3d2f915a0fc62a185af17ae84cf9a80e3f36a6cea459cd45264232372bab7e03e5069d024b353a03b3897b483696a4f9ee52336632bd9cc3aa36ade094ba51767aeeab6ec70d5221f82d1a44d453d147d219e30a018a78cb6d569f6b6499b21401385711736adcfb01c6870587b2beae740f0e5f84dd1b986ab6543b073f5b8c338ec3f86a42f5e2ac17fe4c8ea6d1f6efce635dd24ab6e6778b00c08c21b2d6b792a9fabd979448fc8845a97e1cbcaeec40ed5e381aa5cb0706b4df8d1b930b6865e6160361378737cf94122d34212716211228832972a1372e88ad007bcb78f68cb14fc0eae8b3e8315fc32191037e43a45ea3d861f6d930e2ce2e22c6c4547081db0d86885beeed3d2dfca16af4f0efc75818a673af204bc024607c6f701ea2ac5c8b372a3da66c9153925914dfef8b3574f67bc250ab1d0a378d77ff5d36ee2248ac73c8f8260fd0c860ca48301300866ee73211bc65b97bd9e1252090cb6d82c74a318c7ada7d20993a151a0668f5ad3aad626c6db88c0b89a3355e0cf48dacd17402ce55d5e8e5c7e968b0464366e239a8413d33c632279b75df5b1e67e5460f2d313fec646fdb9f70edc056e7739e081fc30efcee0bf15e7e9731db9d6a01e1061e4c7b523eb2a7f3b2ccf662e83b837c45a4119c78feeaa47f4990def4cf5e329f60615be6df4fb4513b234174b0909688d3803003b5ccb7dc6448ce601631e0d01e171eed832f76b61e53826d61f6b4f62b940b8835aa423f3a077b5bee6a20a809291859d5880bc2b80c16917793720eb694d6696e713d5cc1212ed547ca8f361cb08bed9689533f2ec3c8896b4f354e94fb8220e9e837abbe7ca68b8835793b4c069704b222f95f6563fa9e6cce67b79f8c340bc3f7f008a1d359073c2b4123dc4819522b34d6935d1e1cf0959fd2f3799dd899b7a32eae6667fb3a4ce58538c1ad9b2356db6b9f0c862effa84772a9071055984b865c34e1ca7e83f92c0c0740dae0ac5ca47b1aeefb40e0f0abde6011a61739c71bac32f80c62feffdca9c9445ac0d770a7391ce1650562113dcaf71b2a6a232dc0e6f79be84c34ca2b7ffff7f2f9fc86dc51e60aa15a399a21a726db5189d7264cce2ace2839a9330368f4bd82ff22028fa66b4ca286db01f5c6aa9dac79c7ccbb329a4da304e244161bd3b3325c5be82fc41ccbe042c351cd03bcdc8a0a10e1143fa8cc038dc61975266480403ec905b6c0075518585d71e7aa4bf1df2c02d5a10b5dc2211c1ab10119ba1e7f61f0f0535d9ea7130cd2abf40504078d9a3825a42daca66853b08807fa4e41118195d4d7221c5e221618fd392301ee403a6cad55f9201b49c1a3bb2df64314986e0051ed50109af4f4f3e8b5624f0f0d672d0e8ab320cba18588e75286b7762e779c460c69f880ceb395de5d721a6bff4eb42a8eebc7616baa751164b1a54ccca8604cd0294cf1035250f96f44533e6393cc039afb57c2042515dbb85fe655feb0b3fce2b61b755e9e36d5deff76b93d04567f5e6b422887a09bbeaa72fe9ab96002bc7f6ebd00d552028ea772a3b720f6b1e5363d4d56a314cc29c2eca0ea7069367a5c02d15d0b4d46758c3c0b06cf9c297dbb69dbea6cc2e6c0a92af6ff96fbb64de32a0ee67b54dcf464b1bd56ef00f71d384d38c9d329fe128c9d64262eb73170725ca0effa96418e9ba4d157c7b1400212a415b5394a3e2efee419103f5d86bedf4cfb9f578a6ba712a16022a8c0bfd24ec15b9f77230f707a8f0f0c91f14fb7fc0b57dfad59970984de7a7ca629825a1c84981ef3b9d0d66496fff4e83d18772ededabaeb347802fc745ffc2c43ec1945f5d6b756c26db2c7ea1665560a588029581c094ed2daffdee302b2a01d6b255c3c2673d7fd54ac6dbad93263791cc4ddba43b485b358178877ba805f2b6025006b3539498825a34c57312b9861e573a7ce89ca073fd19e8f09f1a2e6ed6f27d5d86cd92cc7b253cebe2932960e8caaa686ce9cc42740257a247852b62f98075d10a08a4a4b58e47888d9690c043de3f6bde383ab07f7bd11006d3286a36c226acd11e1b1906c5f83efd4de1a28823e2b743eb8ab684d6f00449bfc0832efd217c9130fe8429b7a7f44818c43c050e948e575103d1b9f06026c6f0e2df9a8756606490856c8bde69cf726b7370a3378563175ac84a8c382f859f51ce670e3e1b759bc24795e49261e16212b869d733d98285f5bce2bfb89fe2c3a9e0269cb2b67da9d384b68a03628dd7fb27681fc51895d1799919a5cf8b05a6ec53a0bb510df5244ee8851bb6c57be96a600e9c03f5932dd9545ceae12746f2c2be5e70fe99a6537707e12643e889d0309e5a1fa019a79234c23f0d8158e30ca241b86bc37e074554ae880a328ffa8ac9772cd93ea2056effa72fcb8e6f803e858ac394cc1ac57f800169ae9a7d8ebd80f5a904049ec5bfe531fbfe3f90280f603838b05daec2eaae6af01873a4f7bb89a15a5f99e2f1c3e4a9bd826dc24bfd64aa511a95e230d8d543b7da799de659c4a06ac616461664e4e85af6144a9fdfdf822779030de49ed4a7e464916386827e73283ad77fe8d148a47b9dd8f24978c2d05bb7d560319d8b6e137273842500035e18e58f45500efa1f3a7abe8ad29180e08ea76369d53b3e10128f363146c18891fbec5c1ab30fd3d6a29145446c913c9891dbf8f7f0e635761eb9d7471a89c4e6c484ffe6e2764601c24bd9c15f73d70afa20c70cf28a8ecab03c4f052318176eba996180126770d0152485278a1def8a9ad62c7e4f5fcab62269359fc99c0622bf3161ed794efc92e1cf4022a7ea311f3aeff9b675507139e94c1e35d44f4e3da7754f8c4c4fb7a4d3ac3a875e47ea8d21557a7165c637f2b319b33751e97e16a70add02a300ee345a0b5ec4640d17e9a3c2489e599338170e746a3805053082e81d4398501ce5423b10b6ff885126feadbe44d81aafea4447a5fa774a202c150da3586d2bc10399aa1941ab1f17e8e33296433a1fc1b002eb98e659e2971dfd5ff4edbf9d9e879118a960e9d68aaa6ed65a0220f9d53bc855dc50d1bbef9daa4d1bbb09e81b15c5cedb6749fb396db6d5529f935f883c67fa0f4a1e0dca1dd21689ef8649c7d34bfba48816c719b00ce34788aec6583cca60d6f6ee7d562a38f773f5062f89985ba0b92279b248b1d36a94466d37f1b3d77e466e8bab9c0b62a84819ecfa5529c0f4c5dd3823cbfce02651990ec43b930c779d7b4c36e6786429f8c372533d12e5605ba077c95a47c0d56905344a8162899de18f30196434be8b1068f5f90afffff1d4b4eb31333aff4474b586b80c802acd15a43fbe0f9cac95568eac44dba55279aaee1c5a3a483b58f8dcd9372e3bb7915ae75bfbf92acf7f8aa92baff97e74795148d99dcbfa8e180b8aa2919694ec63e39c3b07ff98a45c5ce696a387a8b4e2284172f3f0a96a5ddb1572bf1406248716df27edc4068f3e6b468f7c7f11c2b63a693a7ed6f28436975a07b485634042f8db50c3d0a0f46a3f719ad7462260c9bf42ff182c38bb06962c4cf7cfe9f697919238d9977d8e01549865627e9ba600c3aff16161390de872e94d02d5ad5e92ad76be30ee9029d7ff177bedf855c959f7b3f51dbc568173b93e461fbb0cefe409c6a9a1a545262c462abc8add129cb92152b7d434064506438d42beb790b7bddd829db28d385853abcce1dde8eb3cb2279fdc910f019b65117735a878e8bd412ddeaa82cf9d42dec20242dc3cbaa64e6e812c6278d540f2b9d16b3b81e7f0277e3cc7a0cf95931821089518f56f4723e8ae8d29eb79855e0eeb484522f41e23efaab13cbe09621011062a7c7d5154b5ff03131a8c91621f478d3265a9082e0d07014267a0f02d9f9fc80555a1abb6752c0ec96865a40e05c0b489ef07697ac0dd9604c05c30e151b05d12bd2a0c1e1ac36aced0b286da1bcf4fbf5e5abc867619ba5c2d7a4293a529670802dff444f6822d6ff3de81dc576530a69354ef58510813e308ee02604ca470c228282ff2b2554af1b5da533c642f2ef76403488089c539602b07726bd45a6166b2a8500c0fd74ee26c1083723eb8bf4df4d5ab483e8f3435e75721b163c8146faf88afad07f2b348e334898fdea807a0919c1a4bd21d8583aa7e48be0e0c5523e931eb8c1d3e5842714c963181fa5658a2de73d7f0710240d031e07975ae4ea1165193cbaffb6210144fde14488f32c7e559412e2969e99651e29c7bbfcf262fc3997c4f479081c3730a0d135401e78c222b3f8bee160a0a0d0a011c2f0164b224ba43ab1908462745d39edfac97d2ec4036f6c0a0d2a8e952019f9d0ac7e9c9be695b2ea2df6bb7b36419afb1de8e5cceb2c98dbe27b85915b2cc5b40ec3d03c181832467a103cf32ad5a4a1db4ef0eaa584153fc276a6a992d1765e011aea880f700fc3948f10a20f320181cb6c103d79c34e93e65fa4920bc9be7032f99344b13a02aa8c1976377ee1b847bcf3a9524e137697dc78793b0aeed6410087b1f24d5e10572ccff7aedd0adb60e9b042baaab1ef8657865962f28958691a8ff422b6ba9a03791e1db10e4cda3d17eec4d62b56e02f56e1411a4614860c9c937e8d5555ac10698408041be2803a8592a7d38c56a1f7643f34e75d899d2a0a9817ccd81dd813a77e31b58e5755fc4332a201b0aa5ff2ef9289476018c331f165f2d4c0a9347e238048bc1e9ad37f21fb42c3eb351f3ab6d8392750b5237c7c0fbe218671d045acc6f23ab4a35e25f0f8bf8da5d0bd22855513a155ac29a8a0302d22e35ae2d64918ed878862c294109d1abf2638e255a1ed3b3deb10464a4eaedad250d3d130a9adde6f83bda0dc2a23b2a9c007ab7aa03f75983c7f6eb9c4d6ecc4162ebd058d442452ad8bc49016991ad4338056623a7ee5198d0e54bc5adc04557eaf5d5c730e162e37722fd385a7f4793bf159600ccdff9a29837b0356c5a542ca5560e37eb6fb4ece57d1b64729b3dc95088ee3068315bde7eb4724c7bca0c0f11c5bb74870ae635185045141728bf708a0b75ed7d33dfd46c1893fd68b613891f687388bdd544516c91f7c1a445664687b6bb3c8a44bccc7f8c33a1b87e4a26299bf3dd17bb5377d8ab27fad394b7d46c5e50050ab25d363a08ac0225bfb017c45cb1a0011c6bd55e43f7ae25dc9b6864cb9514e15d274ee5b592cfa0f890c772a3702ae09221513423cdcfdf1b9de8d1a44d3e87c8440674f8a61b41a6b308e89211a3424c406fa557c2a494874032c17cd88e4db74f6e28cecd722e498446474bbad9d27b7f54776e3761ab10dbc327bde78366baa0d1db5d39e872190f627d65ffb632dc9fad0e50adb99ac7f9998da0aecb59a7b046aff7a38bdd72fbb4bc7bced8666d4e86d4b6b8dbc40c0a8b2cce98b97a5ae9f41f4b3b6c3308674f890ff0ba8a7c99619b1af214ecb373bab204f551807b9c3c5fc3a528a6e3a77add5e5b3bea0611bab37f96a778bc5b24e848a6f367db1ffeb7fdcc36ea23ae000f86928788cccf82706c6dd920b129182562c8dbd46313d255c266bb537af4b1b768e0662cb93f483516a8429843767f73748873bbb86bc144ad30a81edb91eeb9b86beacfa1008cc25c0e1b13b0464164c2ea368561489c2421e51a80feb2506ef2f36fc390bd034c06d57c167ff421dc18d338de898ede2a7ea87590f755ffc5d93665f69d4579152f0c23f82539aec82501bed1e49871daf8f11d99eb22b73497f2633b78d3155e5bc151330520f15bdcea1e7f0944e77cf4281ac8d110cca29273b3dd0b436194e179eac5c60016008ffde897f1f27d91f08187ea6259ec160f0865d306b3e4b0617a35f4f5c787ecf3b9f50d47b2898d270579c99174442800630839503b87cc487ad5368d0642a1242eaedeea504bda4a45b35208174d3185f8d8dae1c2ebce4f8135c73fb37123a30bf9aaecca1b7e86747c1739b7d5ba28b37bb1907f7eb803b24e43fae983647be677ce18cbd5b693a4cd85217695f47f0fa70d0c27dcff03e4d681a250825c71aab1d88ee7e9b1205488d563406bd7c0c172397135cb5627176c0a26f78d091da779f90c88e782845b6526615ad3fbec982e5f18baa2d835a48984c22e3af8730afec8f461f57217c9e3518a21e038508f068e48b4cb7a5df5568fff052e4770e139e9eb60a19b62f5009e1f0c18a54f3b2fe3aaa274e767b0cbaee6e9800767d82de563d1a135649bd0a1fcbdc5ac89a4f72f44951a9bedca38ada187118b31957188948b32d8e0237d8a1a4a656bdb7fcebfb927d75b7bd68dd2bf371e4fa3147a381f2854138e8e4867080b542fb3d3dace18efb929a32c1d0bff1d5269363ba695a8345062bad65114359e45fc49ce5fa67fa2dc4903af573e076d8046dbf004704203cfc434ec99e434203daab8a49af1ce43f19adec01425c741913f5aeba5cc7d369a27b168cbecc329b38dc48b2de5bf8f6140fc1582efd0e19b0f3538dfad580156d458c175f31201380c55288b301dc313023baa585f8ca149e9537fd5b599ea9985807d291802f4eb48f6df92142cb8ed81df9849465fc65ea30a6b3d7593a537320a4152425ae80bafae36811bd793df55ced6ad58a8c43440058920fbd9bfc7297872637a0bf5de31a213d91cc68e41eecc5ffcb95d3a89012546c8f01880d4906d56310ad2b4720980735c2f1bc85d320cf0939177cb60d539f23517669c378a6280cf5dd9c25e983736d0fdc9482f68b9eb72e9c4cba3f5aa36000c7436a2a04bfe882c4a4c836c0223c384fe678c429875022cc05756b9de9e882ed255006ef1d4d24012bc716951fdafa3147cd31d9e9ca72949420e675da20a7da2ae0108e8ef21229b0371a1a4cfb2c4965f0ef574382eeb0c40536696a960a1588daa65daa9c034ad8eed7e1ebb37dec045c744c70549cbf95cb722968f9d164afc140573840f02435b35ed82e62d45ee7e9fec567ad7ad368f3d204ca1d60d8121622b8a35bc7fb5f619a0adda306b5d91e47a91be2957b194ed9fc99c23e3812d30ba99995f53d2044670fcfdd2cc31e614cee1e6ecb10ca59fd7f30489d37a5da80b42b39a4ee2dde91f428091d660d0bd7cf01a0dddb2ddaebb9bca842659c706bd3c9c9b012dc36e270e9f6eedb38402b9149ea129619c8e23343a0f28c814d880013d5396d87a242beacac0d1b6efde9973f431ccf52cd0b2ed3ad6eaceb2146bfcea1e2e601bb3e1aa29cac84660325193df0b0f27861d9d5f545fa899239d0b0f757297adee7b9d8f4e8d98377746481006421ccbbde87b46dd049024107ad613774097c9f6643e90c69b3fb942d24f214ed258a2a1702fda37cb9418b49918b58d80a9cdd18615625d1b5156bc4210da53e0aa511ea9130a0f4b881061c12ce61eb17b38361f82ee1641c58bf3d59b2710fddffc21026611b32528b196c686e4f6db72ef4f80e4306b4c7758246e878fa8aff39bf7f61013a680690e85e997f4eaee12240f48826b39e431933342b900a74d46390ffadc4782718d2ce519b20c817cd56c450e2391bdd2dc02ce972da75d67f79b0d7a318f8479c7175386f041ad5d724ff641fc7867f20bd2be993905074861fd3a98b4b7c2ad4b648cd9eba8aa4d3e853b6830ff5cf8cbd593905771e35adb63f5ab46816f633afdb0ad99e7913b4af4eee974e140c8e819de74ed7752687876680a37455e36ef74065328741a27383c82192cb36a0b657fc01a0bf6104bd737020ac8662edb42b6dc223faa50bfa5a2108f86b063e331ed91cb05ded6ea3805a945e59cdd103749dbe1a161ee0a55168cb631340722957d5b8bf30165a51fb5346ed3770efe354b73a61ef25b4fb7b93dae2c8dfb4b5cd34250f733a746e6bc5b6a70ca04097fa39d5fa02a37a6d6cf5345228ce5aa1b9fe794db1c93837df81b0700e8c235a9820bb1e6c870409cf54e4168ed70faf7f5c113374cffaccc1d645bb2db84726298942439d271fb6febae20db1d2d1828e038a5137b61463ed64468ab433c4cda10d544ed9c399b7c37aac2adad3c07d9004cf986a3842b7d430d3d2f4e3fb3d25b5212a946c96eeaa35780376bd3cf6c589eaf2d59fb65cbfd32f17a9652ca42162e337448ee51b5d6ca7b1929b4fb8df40835bdc5c9c1ab5a0be2b2e5f64a6154cc9d762c49140be2269d544c41427c252b9edf5f716f7dfeb9b484fb1ecd518d0223f0022745269cda60900e4beaed49990dd0e9ce195fa973891e221a0f52c27fa9c91a47766934bc68b8b2a10120c71650bb64d8c00bdc78fed143ccad3ad9457779fc5e102d3548fea9ceb990f520c45398ec3ee5ccd6193719b31a7e163cf5460d37c1826b042b48c80dafb80996bbf44ffeb21e23710a2daeb631cdfcd6a026d8b66bc8358b855c16b02daae2d8dac14ad448dc277a3ae25b5625785b5e6b23f10466f18a35e9bd610b76b1a0bc3db4d3f21d7d2bc18233cbf8a1158a68edeb9f764a85b736c45b491272a20b8353398a2299356f9b656b2cf0832c9f52a22e4f5938fea061e4122d07616031cf1708390685660fba08e718cfa7d53aa13a939108b320b83bea111df0a1b91d8f2682ad8c74bd464438cf781f89a0b9d677811d2edf9664039e3de59b7143a05e250485b6e27314bdeccb0b05f42b4ff87c6c6c5101cadf43c8c6e09d8dd8255e31c9173646a66684da1cc9b0a000400c0da6f6281b9886f9eb4a10cd4aedfece252aafe4e609d5eb16bd8caa102f46378a1655236658e9a20e8e11af8e3549d16ba9f06ac841752cc9524cf822ec316957c670e2afb7e37a23ed2a1baa7372780282be06c5d6aa3e101e46329bdbbe648df822f8564998173e0cd5e02bb8624a4ec340e539e052694928e84473bfa3d336a1f3fd1cfc21b38eecf7574c4f043e0d1f14ba5a6605e3f65d0fb84814d7f249fbf91ec0abbe643b96abb307df4b56774ab8d846fb2e31aa50be1e8d916bc099fa289bbb0d9132df9ffc1da2a98b1e61a2ad2d4fd458f6342661fad75901be21b073c48500a99f6a25662c267e4cf8916bcfd03622be6602a82f5043d8a7c857fe67a28c0d1884d65354307df2907b064c5073c377bb808cc4c3e2e2e615c2c18ec5ec330069c58adb2d56f0704dbbfd2c8ee30aa1f0c61db69589f7f1e3929baf5baea3d775f600ae84e2e07c70dfab87bb20f4bca9364e6bdd3ea3d363a8c15582207c8591c2c9424f1fa07c910030e5b4bf826b1d4027a4156b0245e413376c1c5083cb05384ccfe7d91cca8414fa651cded3aa4bc0dab07e7a6ffa944e1a0b25840679e4f6f85857b9cb1c9844427113d62b7a8a59c9f2cd8601612d6f11eb24af306749ad5394428930044c64e4e817eb7dd48d218532365e707e70af84f99681c00ddc043adea8c0d90193e0d0c921ec5608515e0eaa8d7426fcb53332c4401bfa6ba17d0a47eee3b8f0db9b7630786ac90a444d3b71fa6dbf451888d5503d7571cd1f0b937383b80128d724850b60ee46af4002f72aeddace5850859b20a79394ccb388ef06cbd7746c6edaccd5215743979b5888f2ff97cca11ad7048db5d949e826d8a02728e3c51ef6837c491cb0c8dc6d43006e0d1a6a5c38bceb7a69d60cb741d73f55d5b2ddd5339983575f51092b0d59653111ad48a603b885f6f2c0735ec2a4664bf4786c55617659d8a78059ce600f3d7e3d36e7791e667910ccdee62992fa8ab2d497aa259ab3bc9745da61266c7e82f1d9b24ff0cd172d5b811422eab668f23871f24073ac9a5e73802c39d293b13557c341066a0338d8ce4ccd57c4979b9a39cd12c6e57a2b1c551f30233eb407e8df9255c7d612854a8076d334d84434e2bf255902094999f64539ab8ad0a32eb35172d92c708a8f90b12d61b3a0aab9faaa267d09d9e2e15ed253060d7631050f3e1932ed83fc2b3c0c436ab7e3f6ea6984159d3d4f2017d6163e82a2108eae8870cbf208bb710737bab0097c4c817a33749d87abd758fa2a175ac724d816d68f5df2dd8e8187044e93ae16f36f1a5502aae9450263e01c648ce26b9840184dcaa569107abb4a665d50ffa3cea042ab365134750c04d42a0657f0f9c7e8ab8bb32bd21b6049f849e54f1e0145d02e999c893db3e5572f8acb46daef587422b87763bee2a5b25131b106fc68fb313b76107da86b0d767b9303d293c6de682afc7c3abc2d8838d33ca9254763dc7ead576134c194455db5f3295b716f580b7ff22e2185b24d3f7779c537f996f24b0011db8d8aedf334f19b25280e9fa71197288764777b98c613ed1add4423da43f344f3aa52e71a1545751677186ce3d0434c66d7deea5d668fc34053139f2e6f89a13eaad9c6b3fd0cda650cabea25f20d5a0f26ea6905ae30fd65f1e4a69755a500cca2d80f324cd441011e5a5351d82e057dcf4095dd21c6eb4c279950c6391b35f08fcbdc17ec4554a741460cf3ff932c443b09fbb270fe90c8e558c7ee72ac6fdd06fcea8495fddf78af9a3398618cea73fb9d2a0e4900e9d23d30ae3bb409949cefb25ccddc8416e29e597ed90fba85b45e1ed17d00fb01e188b543b071a08b1eaf232aef8f4f635e21e8a22921773256270bcf8de2d37df4e364ddf09349caeb7b69a41d02485478f45abe8952e463db17dd20721564e6b117bf0a5ba8f91787db1d4bbd499c7a987e243933488ea8116dd57162336511f5b56864fc1a6f82c705147533de16fabed8d8814eea4343b57225c51ce39934e260496428b09e60b0d6f7cf5516650178cfad05b24e811df095ca664711a57044acc38cdac2cd6cc26118c26006cd12e3a4eaf934c2677b18c9f94e72df34faf4990f4ce5c265cee6ed2b5e8056dcbdbd35016fc1484388ee95267d762430f762ce5c82f9ef9e09856f03c8f72a4138fd4616bbffe6ea733536882171ef7f85806c219e35aa14a40b7707c8fa2488b16470a4a07ae99d2b4a3d199e9c8673993e03553dac294759c6b8d6f42dc51e387450ef7ea9c83e0e46a9a000410dfd9e7464fb6236edf1d48c7997d16beb1bc3585aeb59a275b6e5ce51e1e974ffb4bbe241ffbceaf66e18763941c673cc1f42c41557d1ed2232b900af3175dccfbed3675fc51a0459d7703f64a6be74b3c56d092125fc2facf47992ea89fa0976aaf8ee359af3a6ea2b08403aed869b19bd7a053b2180b5ee0a9e8d0940a5601d453e7636a97a6e920d95b8996b69573a583ebe42110a8e0892871313d841faf6ccfc6bf2814c571fc8a57983870699d5b4124e759bec98ea775ae78e2ee856819c6f8b225648886c84903fd1875d8568579548cd064554041bb8345b02b90bab6357cefac92dc1cb9a2bd7a4ccc3e7cb062080247463cbd1a10d8e218cebcea6251fd4760805cbcf87d1aeb507b2d7e8174a55e07dc8fd669406935ba1443a4b55594363e9edad32a5102a5bf7d4b845d42b871d512f1fe051da009447488b31a06438c64538ba1c3aaccf843fd8d3b7921f23736a2a3285d4606da884c9413720fff7e8770eb2bde0e4d8d44095fa003a42242061ff897f0893692b51a26127945429b6f4bbb5688b82218ac48768055fb6059224baf7764fd4ab42926bd00e10fa1a9ae07e30533e0c106ef1cea046bb430c9910f0659ecc65379757bbf6d5fddd40d6bdc3965c450958d33fea3771712aaf9c8b81f8698e349d32b022116b8db661b151c4aa4641f5927cfae5b985d4c34c5b9345534eeeaccac8533edd82ebfb1c7923141507f8333ab8f69221bc0037899ecfe53419c5403f5b323ed9d6d83608b9f8f4ff45bd49133547509bade3a0e7816a32f95d0f243726fc8ad66f7295bad638355a28f64451281e8fe71d7165c5621685fc60998509bca9e53bbd6ea062facb9576374c9ab246b10dc599fc5836190236d649e7aecc23887d450c64fe23deb2181ca88fc7e08ff5b3f2f100d517c801c32b44382d393c03895a4001e9d44e72a1f089656a8f345619d74acf6805843c34222a215060fa12b8ac609493724ead35b01068d3e33d0acb8c69e2d956845960bc1480177d72300d4ea44130ee064594d6f4a9da8eee9cfbc9d73e724c60bba726b76612b80c579918437b56821ad8389d90e5136e4af71d7c413ceb15d8eebb768632a4e1a62e016a205c391aa2250df0c0ae2db96b223839f62c020d99b5f6fbf452f096b11e7dd3a1cb50c8e4b9521a1fb6224350a755ef71e8f1e625affbb52d86091d5af9a09432547b1090e8012d6f258ee222fb60a625c57b7853a4a5427e00fc3fb545e2a5d8ea8e77b171cdd83b0e9ebe1baf89bb06169dee8f683b6e49e3dfaaa3f34188617d987b39bfe57d826a2d06e31c9560811eb03a5fed353fb94198d2680221bf91ffbb9d659ba8fe57d65d37a0ab1face49eaddc8a605ba649d3d0fa784f3953c44f0cdd88d588caee355f29d3ca63d0532ca85d21229d22c3951c72835dac61c752a4bf9738b4de9b965d8a72f964dbd9af8b3ae15e702a7011e98f29c1ef2e30cc294f1866583265d6055e177ffbda00c05106d3c65862a0b8d5a06d242c9c9131df17301ef8a0c5ec52a6cb2c02aa34d530d86cca2c8191932e15093b0df9574ce59cdc63f8d02aa2630f17092cf16d7b675e52c23dc6efe873ea083bf84ac59b58fa0773b1a4dee684928d1309a510f9140975c6045f5b5ddcfc0d1de96d9e9fc391cecba9ebb55467a2128fe390475cb5f0abadf4660404f5d0a2252d7d82499511b3291e7a7836f6411dc894aa98d5836af994bd734cbfc7492e24b02f98ad29177347a3bc8ba7e9e37bc7f974af514193df45b0a8ff2e71c62a039b8798885efd2e3cbd5b065b3bb6465783c849e05ab8377f902a78c52f2fc855171462c4146b0bfe09d4e46f816511e0160f3883ff371c65ffc9648933774919a74beb7b16c107a3b44d24dc6206b16c539a37c269ae95f3c8726aa19d899e40eb6f6c180252786f8f2311cac8efb275405b3de4094d1e6dcaa4a649f08e0bbbe59ef0f6a15096284ba7d3d1b318dd0fd7674c09838ac68e230d0c47c7509a869148612a79f40063631b250a5130a19be762559cdeafd94a9f40a2484793347b6721f240f9db1e4c3a6c0da408f06f67d1e5bf301ac91d6aa16471c4967c86c0b44594a1bd52788a09197e6ebf729fcd37668cdfe60550c371cb59f0da53911cb05ae18cf6385a17e58c78e1bf3f6376072fb7f4ebe61bc65f798e61c40b6de5297fad0a5c3c84524021ce14030340308c1c049c8c39d125ae16ddaa55947370d7e9913c262664fe39d1fd99b2a37066128100c529dcfb7e1edaaad4b09f1b18c2448425209e596b25f72cf3db230ce9a77071c469ab476aa2af6b097ee00d6a2d7809e62376a7e5e229cbb286144595fcf832f6ca92cb2e00b45a00a6bffdf799f2cc65e3ab93472c63817bf9a0368fc2b0d42ba2e0e007f19ab0da2cd083eadc62e51b915699e4deba81c2e89fb52c94ec40ee50adeec7cd000b761cc935b2996b280e0c7a444b2128fa4cf868289263fcb8adb26daea5867c9b93ebfc8194fe2a59afcd06e69ae7c93e29231efd39f7a62b820e6eb8583aff3c7981b39e8fafcc0e74710860f2d28d47dc1327e81a2a71f939edd809a7e7f61e16a420a9c7f5602771d45af3027011f6a0e36501fbe9f5800c78539879e73930dcf391bb81c993f6f5ea31733fbc7a3f2fb8ffeedca7ddf3608fe117dc5037999154482c0e0857ff84e2ba86f89c4f2900e0a7dcadae595c5652a292cf85d4839eb720d65fd7f3433f9c6ccf5f08da8a380d40fb143234cb4ae8df9a47b9481ceb1422d62ac518f34385a2ba6ce9bc7e90cf082b13df6ce73d56833f20fe0a49ceed8b237b71b307861da1b39f8221f46dcc041146477c9dec57609da7592cbb9a8ef3405a35d5cff42eea30bb16bc0d28d79dbbd2f622e49eb54dc53bdb8e6f0777daf41f9b67bd7d7ce45794f98fe31c76983561594a58b5e3cc9681f523d3e4dcaf256eb89da8f27a425af420f3361a5a12cff422374385069e2f1ea3d61145c3446aa6203c248d1b975753ce8c94a950567de9389724730c3ddcb28dde2264afa166c8d05ba2f5414eb57e241045835b8ef1043c2582d6aef970d99037250c858aeb3df2a1cbb2b3293ebd970147e9cba6c10dfe6d6680a03285a35ad0ec2ae6c9e2d2a22293b821c5ae6780c898c9bf3e21b6d263f03b2044ad1411baed524ae539c2ffa46e179816baa912a4e2180398c1752002afe923341e2e5ed807db5f6279ccb7a15fae30441e670bd3f5e6977c2f63204881468fed91ecce2218ba08dac89e2205de38b5e76c4c502f8154e52c30966712a644ebe8a7db81f2aef9de84290576ad18042f48e728b13b3b71060813435746c16446cbd904f9347426902485fc21e93a1e1cb9dd79047ace9dd7904faf1fa1722da16b3c6305c0d6cf14ae7e2d36e102c6d86529fed6307e304b8136e3e926dfe7aba148882c2d3b93681b6f143b8eec6b9512ea674d6f30ac1bd3853ea1459a337fe7571bf1ee51b04427f12480b22b0af86a5151f1cc1695a9fe03362f0d8372770082b38380dd68afc0b8322ac4d3d00028c3303da0106695e4050b2710e2543b2d0bda5696e1c7b7fcdefde39187aafb4acc8dc3877039e51a3f78574bfd23ce76ac561da0e7804d88349ffe781da1b361fd0798146d8ede60a48702be40634e381333c776de2cb72173181f6d24d44844829a59452ca6e0677066006b29c735655b29220185725f6ae6f7d20d5f79a31f5459825500d73dfcdcd40271508a40282ef6fca54fad912b743a457ceca075a8154948708280fd04d0d27201008e402a9fe3bd51d45be14e591bffed7c30bcc96a6a81393cd7ad9ebbfb86ce9e5d5ebbfac6c89db2467f597964bec05654ba09385a932797cd4c5cacbc9a59c32fbb9aaa77a75090304ebf5c31317ad703b24a77e7f888bacd7f7ecd451ed1804a9402217f011478902a5d79781523110aa898a5ff835e212cae45e5326664b9dfe19059df64fdbb5909b3dc16d69c6fe82405c28eab6aeab236e06524d983a8254fbdbdcacd79711305c7d04911c1066c90bb997b51c47721274e25e2fee15f238d5519fbb808fb844d912c755d935740ed5ddc0a1b8d9898fb804a9b899aa571be21909a402a9dec532444b0bc678a792b6b4372637b984e34eb2cc2a7e71fabbcf25a080626b4a526bdf0b3e6292dc9b2469f40b43828f9824c91658be626f1c3be0e363d89783ebb88dd3388dd3b88edb42249da6e2ba11b47c3ee0355beebbbd3b0eb76c690b5b16635675824c825f5c2f1573ee6cce298f8aeaf6a58f3ce75c472c68ac15e86b346370e361acb50962ac62a870894b5ce272c75acd47245c9248a3d1c779a937c7bf09041cac9440b411e222b30265038a0fa212ee858c68708506a2128d734e5d29ebc125cb0b9f7089cb19f0e7f3362cff096d3e1f7a1bfea0e7b6cec3f9e68b3d1eb779b88ef37061088401e7304b96243fd0f2e1081c2564980a694bdb8709535f496b333942895ee21b1ce2992c17c125c7a536759851b4d6eaf1e012972b1c586d4fede7d6e6dc94eeff1b3ece98e92b9553dff45e4aefa564ec85d86ab55aad56ab952d9148a3d1f7516e4610ee8a445a913967fa03856191e88aae44347b73b129745647f5456535650a30636a49863e316340799848d01b4c56f838632f0c11f76b5fb35f0b6d94d8b711d1d79edab086b311d1df4f439a6e883853abe65a65ad77cdb59381172994fe705cc11f50f342a9031ef4bd3f9df79348a46aadd5f9b19db0fc655b6b298e2ef8fd4a6dced4d2640decfd7abd5eafd7ebf57abd4044706a711f473813631a3af0dbc7518912a930259b0a337960200333a6fe88a3477e98edfdfe12ba46a9a8a67baefbadc119b8972d6dfd7abdeaeb6eee4d908a1c17da681e9052035108be222ab13f0409f733d513ce5898eac3c2d0fcf082bbb48ebdeaa846a93022f8585ff555a3c02cbd4c38fe994a030a1feb4bc7ea8ee9c4ab895e2fe56143c38c41f1b1beeacb86d56bc09c7257f75e9cd76ba7b4fab1e223f3c1d138c2ab0ffee2af39f241f3e37cadf0494d99033c41453f827bd89005fb34e10c7d80393ea87df2824e4f9d5b00a6e1421f2b3e435088ede3351a519bb3cdd9c767b6dd5481693db22e7dcae0881abadd5b6bad1a8d70928eeb4018e7ce93c331c6dce6f6deba4efaafad200b92247768687ae094356330c61e4a5a1811cd1091dc5e449f8a229aed450e1039eea9c8fdb430a33d4ed96761663e1389a22892891f5800861826200b8346d3eebd2b6d07e317c0d7a13c4c003de0f7eb9390cc5882cfc4ac1353ecb71104af3fb73e5f4facfa9c75d799f5a5f4aae6f3f022fb4e95de9cf357a38a9cb3567d7ed87baa3ed50e89341afdbf2ab403bf3376ab5eb5555b657380140c72441b2100e0a289c8bd901282b881d87d0eed2ff143a70b9183083e6ed52cbf8e050fa2a4860bc2bdd702f7de911fc8cd7d90cf7b3e88f7dcdf9b03ef442d7c3edccf4f588e38b403a7e1b899c420a46f17b621b6368649e79c938e8fb3dd7beba76f29a5337bc6219b669252aaf5cc1e3bee9a59ddd547dbfad013f71e17dae01f482145104ea2e7eb166b8a1a913263eabea9230f7c2a7caf5475b4a7d8854ae80f4eab2c20d8629b8ed57666cedb96701113a63a7945d9ad1963855340c8a9d3cc654aafc8bd159f8561a3dfe6ac2286d9d23fec31ec31ecff7feb3c0cebb81089b7a96ebaff2dc655c139a5744785984ae5517d6253060177d2cc92e7ad09ddbe66799026fefc09b33477e0a7aa9f25fe36d62f48c3e98615befd38cb0f4855fa555bef9efbd951d516965aa5ca39e319da77c0e78b6a9ef280441158ac4ea2e7f3221b25359ff7bcc8859f914310465627d113da28195da081c44ad4800188b84421d60698e87909b474249e30c8ff27e416c6da0013f97f7ee425e021c9c2d437001197189266a60cb517637cb36ac25d3a96bb16abba7592a4df54b7d74ebb029d163cefacd67a98b882f16b49ced7d6244c19fd14a56b933a7abdb2a516cb32895df8256bbd5e2f9c33c618df9a730c2a2f6e9361c6542e9461b665a855065b5a408de2c6111ca7b417ca607338ed146ae4a5fa66216de26aa55a796bbdb5d65ad75d77ccc7ded6dabd6bb438c7c48f3fd2930f2070eaa9306526a594ea6d6f2aaa430454c70d183a5b8c1298533a10fc3100995380604b9330a153ccdab61f6b689b8744fb0d446d517b90887b41708a2022b8a5b403bde7b6d99c278c5b0f7a7d1b48e29c258c1b17bdfe96c544a1be9ddb4eafa5adb45b17dc89032b01a0d082e438706b6d2e0bc381a22edc5a22aa81222fdc5ca1887e17c67add64221ab650c5edb77083859bcef5826f30d4146e7fdcb6e02387faa8d0af00a500e854d4e98778e0a7cf324b1bccc24c1ef9a91752a8175326ccec2674aa03ff5661eab326877a129c2287b2a50db6c150a80accc001a063047bfd0d56b120c006cba193c10b6c118d4602ea02bbdf7003a9c8e16bb1f520d142d587e2507cd5e5e05331bef77a3e39bf60eba78fefe5b6eef5add74e3d776c1f0bb761cff3eef5ba26ae27b1ff4dc59a4c9b56ca7dcd87e3be0b6d8278de7b2e14599b204a8274cffde7f343c4ad2f95711864af1828e0e394793e08f79e17d9af11d9b085eeb977a10b5df0845e68c218df2b2b81d4110c5998baa7e1be0bb911bead77d5b6d6b66ddb9a705728a551f6de39e79c338d1cb8ae828ff4f4b53e87168ff3c294b154d340b1eff4027c7532bedaea93b5d66a71a7a8a6fb2122b72dccd54104af4f02d7755fc555529a730e830593226301ec46d1efacac14a7ee18294ec7357814a05726a51d6863057ca4373836072b4c4b041f29496feae8e6e488828f14a7dfa73722fb99843abad7c78cb97fefbdd746109cbeeed32853a6847edf842897041a6c69f4d7da6df58d2f46f7f7e6d7de4b737cdcbf7f9fbe66cca52cb28e48e8f7060fa860c1408683042540c90226720cb09fe92743087d83073eea0efaba31a397c2ee8773074e420ab413d3b134240517fdf8edb720a7dfd76a7dad4fbffd3e272b950d20b8fd69ad9d71c46a872a7c00a230d594994974eb5514acc409e2fde78328c11fa47bcfdbe7333e9bdd3e7370b052ea130a0e4c3a85d9129fcdba83cf668cfd1856f0d793cf711c473291485be74de3a00d3dff9a10e72c0f7a9b5028e27e8aa1bb59401eda7cc661efa93f7e8d1c9efb8c5105af3894d474ef11dd50061a2c8cb50f835deb791a85474575280cc78a5350ca734586e5d70e577338ee399c76bcf79e55262e351c052e43b09cea99cc24669138164bd56e73328bc4e1e494c942cc981ccc524e4261ea17915580c923f8ec5807c34ef8007f0c736196b5b85547ad2f6f3dc05e37472d696fea810e3d1085e82f6a40976841e1de7b6fad57036554983a02b1cc98fa9513e13cf0e813c6acbceed414c698086a1ac14793b534654a51157cdff77da9944ee2743aed4f1f778e274ea5df45f8874b607c02284971680d138c180e7dccd4d1bd57ebd3495b792eaff57ddfcf19709ab37d195470910274b7af754f06159ceb758eba0db7d60df8f8b5fa6bca1c993b30933aaaaa16cc9b8e5d0025e37064cadc1f751118d730472d20d2e9d714745a030eba087c9a31144371010afa688fe0605533e6ca27b3e2e3d6bad2efd6eaf5b7d694b13fa3e7f0b2ec69a4245ce1e3f7792eed82af06f78123307b0d1d4eb8168a36ac8b58f8c03afd0facd3701b475df6bad8d345b7ae8ab7ed0bd80eed426ead76813e6ce7f9f9ddcfaef3849c63249eafc13f3d8bc4f31d88daa2e7b90f38bfd0000f34a6830d5aa287ab5cd0a0a436283103d5dd49cd6086bb0f38bd88e2042b93290db874f701a910ad28b0ed44075e30d3a2a48a406d43c8410717d77dc07985092350a207bc8185c875575c29affb8073c6450a60a2c7e3f13a0ff7d097a9c19397e801c314885c8e1b6ee4bd1f268f11f570c8eaad7e1b3d2fedb225ef31a69e0d3d2e8f931953733cd2c3f1569487f78307c40d9dbeb54bbb2c8c28ff74b5a89e98258d3daf551f712cd672534bd948c552fae87931e9a30ccfcbc70a13a6fe579aae510b55ecc219ed02a2ebba2ed4ae281ed8ab8e3c76ceedd1ae7b3d074cb1cb3a679d73ce9d7669570c180fc1e7b33fb3ced84f67ce0238317d4c4ff887c3cf5aab62b23f860e38beb02672be59c5b40c40a05a6b256de9bf7e7d52866631636a896a419fe69c6d8d25dfc929836753664e51492a9bf1b1929ddc17a6020da0a24f461dd5ef614330d4a9ac92a48cca2a496595ac64256bceac24a5426754564701d65eead97d83a3f0973d5f5e70f8aca34de9d3a7af71dcd6b90796158b6ac6c5bd30f3c36ecfd92eb403e77e84b83eced8de5bd3ca59d7a68b6f9b89c4144290816823643231022044ef85dc88411044cf9756cad03d6d5e96b46575e86fda80fcdb7319a4303b85cfbeb7cf332d689197f77451dba6b79f9e8805fddaaba0c3b96d4336303fa5af3afa3cf00a8008e7c2914661a54c992a6629fb50d256495b256d95b6cc3761f091aa349a1932b7bb991f5a1f676c857bb2a5115b4e98aad9b2a5952505a7082805828e609660eed09b0ee1a95e9832b44f716eadd150964d5c4f6c694b96169c92531dce39ced1d081ef3e723d434be51181c9326562d08163be370d1d68e8c0372aa6f774065f1759d49beaa332a935a7e26c22b54835d2eb7b2b989327f1ddb0c1cb5301481dc150479cd5993138b5548d5498fa948a09539fcc2724120c0c08529d2903d5d4fbe00609f848592c160d287ca43aaf2994c7b6b3811a04a263507ca43a3a9c3369e5af2bd43ea90eed676ad65ae390391f1cd458d5b1b5d65a6bada9bd39ffcfb7a66aaaa66a6a87786833a18ca0074c442123184b0b5149f743c491d42be73f441c4d394ac0c79a0a8136a1e7a0cd94228c50a8c47e55d9127f96285004210491e790711bd293f59ef42aae3e5f55585d479faf2aa74e6ece7b1b56cdf57d1aea889e8af03bafe837a4a78fb6c34d43063b954a8113c63ef5a0c24ff83386a2beb146a7e15853d06b7e1ae8e9a9de9e8233e0ded137d53e4e578f27d4ce3be7fde9fa5e7998ab8e6b0af42c1f24f4fc83809ee53d58f00f7d1096077d76817f887fe86bf8879e86354dfa7ca29f094b83f389ccc8cb3e0559f69da2920b569c4ad610b881b473e0eca02dac2b9d7a6935625535a5537f58ab632fc638e6a9220c2135a79dd3ce49a54fe1235e6dbcc2ab5ef16a8557788557339ce89415169973cef9055b6b53a7e584594b985c4722599bf357b7e6b6ef746275554b62f30e67d2feab51bc8edbb4adbd309b4c1a879f0dc707a9b8412e583dc0441b1d0af13821ea1f226aa0688ab8c3198797f02b56af070d0d251965aa28d4bf504c7b5f93e6f5b8de02865c269cce60828f269329e3bac576acad3fbf8bfbf8d876734331029d2c441b210058ed207a2f0454821d44cf77e1c877387e4d6c2b74b2ae6b5b3a325414ea7b60a9433bf071eef40c7e07615e24db1a71cf711fa75fcb5e1f5f8b03f000b7adbac3654b54f43c977f8331d8cfdff7952d62a1fbfb2a747bfff6776f200c7534b230da7be00f2b534608b384ab9830f595282182883e4e9d26b5491fa70e9d3137756457d614d668efd14c0ba3e9b75e03acab8e2ab86d0b34c2ff878e932bdd8660a0fa685b2693c9e4dd848e4c0ff071c248dfbdf72b89d27ba986d1e82252f66ccbf491944e65c1474dce46cccab33ccbb34c2fa537eb7c7b36bbc117d46e2e2938d064491229c4ad69daa6ddd5f984329f48218599029878dc5801dfb183f2e09c6b245c52dce21f71cc85877ff9b8af3977a8ad1409bfa139656ace99fe83a6cc7dfada2c69ead1680f7b3434fb3d2d678bf1cac2cc186a32c5f4113060d6f26b7b6fadb5d65a6b7dafa6cda9699aa6cd39a7c6699aa669dad4eed5eefd32de9acea96d5b0762eddebdfa40d149c9138a0ef8f88da64f6532c5c0d8300a8542a150282479a6da3e62b23ef5ee9d76842738c5240aaf6450c137eb6570cba93075cba9a33a02149cfec6aaa3ba91755491887ae023466daaba63dc90742375c70824b33a12d48bf98bd403a0521b926905bf5f67f4cbd2e115a3306a736d14804094524a29dd296d89441a8dfebf8f732b2566b2a52a8af33561a21a4dfb21e20645357b2aa144dc3f44b44ae4d460266e702aa1449c9e02be2ca78cee32bda652b494524751d04c198ddab29e520380f191a6521c2d3fc0e97b5f6ef937d0041db8f7dc03f9781d8d40be0ea33a22de4719bd858ba8078a2847bd9acfd30ff8d9e8001fbfad7b403d75130df5783caa755a1f81366ce0e308878e9771aeb44cc2479aead4f5991e2e4827a2ef7df75bf7221ad67861b7bd880be9f75896525a2a331911593d951e2ba73aa2e5cd0ddfedcf54da6ae2a2f58da852e5accbd0799eb7736d49e2f5a4dc4fa3078cb1d6a30ee0fbf89a4c26d38f30beba81a0bb7de21887183172ce39e76abb194670dcc79d73ce4264d2434e1921b4a03c5a6636063427a125fce980dbe005c5560137a2d79f548644af9f434573cb963289b5880118529cc411d70f3ee04e94767397dd4275581ecce00b51884eb212390e4ca1a2509fc318a7d042791460ea78f116138c8fdf8fd91636b841bfe2fbbe6fd50446b38d58ad563ba64a4ddb13b5d0fdf65ccd6fa2a5e9f3f9cc08028fd147d3ecb60d1e5abc1efcebfeb371031f81e467c1841bdebf21901880cc29dd8612985372d4d148073e8e7ad8a7e5bd1914d99002b4937a0933a63e88846aa55aa956ab1e291ca9f666a5ca38965c9555668903252dcb159d5514a6c07eb0a7bea2426f56aad5a5a114e6793c1e4d53b9404570e0e29273ce39e79dbd39ffbeffd188442a6524d94826fb3813569cab22cbdbb811477a6201a9482b91f1aaee15e2a6e0b6e8ed55cbdc2e70a0a5fb030a53b106447083d0c3cd55a6ae0195478af2783c5a6b16da7584808fb9a47bd753ce34c098c9bace279bc17ada01cfa1033e525708b4b15c20b1da4214e2f12207715614eecfb0011f7349631b8d693436230a3e665b6e6e3f5ad21021127a22f3676a8d0d803456662b75473de9952db5c470719675d99086a5e7083ede9927c6690f85a16f09452db87cc8e543a29a976ff9976f79172b7cac293baba32efc1f2286c09ad0b73cfd969677096d5ebee56d46f8d00f11638022fedf0f1163fc1091b3a5cb49f42cef828c770983b8bc8c67098328a97179191f4484175d548d16586a84415e7ec6d3088328a979f9191f648467f9297e9e7b0147a397613ae1875c82b4c386d8a2571bfd644b592766616a9ec94e80c2c95cea932d89e07933befe65d9128bc7237a192c3fe367ea74f92b03b42f22136ee0dd734446006b70808bf02e8f5fb3aa0dac54e7d7af427efd43ba05c76bd32968480785b607aa439bf242d7ee4d776b583e860821cbdbb026c67fa18d4b18e367ec071c6f8a2c1f504731baf04709280e8eaf4f7587d6b3eb1d3bbc536e4c7b291c69a28b197367b9d46182f2caea880817e55cce1810055598dd0e6193acb2e8d56e3163ea97f7e472975cf2922ebf448c0f06970595e624788ee9f0909a32fbeb0e1e66892534c3a1b9cca52de198e95311add23875c77cdd18b9339d6387e863e7b17c58a28f3ae5034e1ff58d5e69525b5aceea8e6bc49d79d65a5285aa91b47c08446d31f42c20111b4c62e8515b6cd1457afd1630971c65d128d625b386c09dcd6c29e7f2ce72f9f22e3a1c3f5441404b2fa10efd3800969a720997c4084fd05249c01206a08f77160af500fa7867b9b43037470b7ea9eb22d1c474253177e41d98061405035dad3acff3426fc55059baac3c4378c5d144399371b4a3f6298c863534fb4926f0201da9a424ea0e67a09d737befd5b3fd99292cc14aa176601c0d2b78d65a3ff812025ea3cf9795221d2311810827cd7882a3501fc5b8d3c734b4526251e8c06c0f1c38e0143565a810f48659a2499c18a1021e3c42f005d4918f3aaa2f93c96430c86437639c71ce18670f6fa94e89280ab02d3ae7fa9cb6b93a4ff1ed2c48de4be3d9fd4cedc2146cb5b6a73063927dc718e3cd0724128944229148a424f8ac53e324520e311daf23cd182f2485241269ca54da2273ac9d110426ad3aaa648eeaa68e484ef8485d1e2566d73670e0f5a9124c4c990b7cdd3e055dfaf45600751a56581d21e9de76617dd18e34656cf727e88a4375d4af391586491db570288f2a441d62c6d413f44a8a8cf091bac64a7698caf5e41585e45caeaab2252a4e58102cbd93f29cdcbbf46d915075cb3969b5d59c0b2ebc85a9d4e572912eeaaa29cd84ba8ae458223e5eaf17a65a53ad55372e578d81849698f8020bbe350e4ddb5abbdbb66d4d3e170782e0235ed5c7387593b5da71efbd65a50d0e22b3c8478d984c37abbd81d02ccdd22c9a44b362668c661d8102cdd2ac24569aa5599aa55930e041b37696f04b6bb57b6b11c03ad758c2bb1a4b38ef359670dad558c2731f778d25fc6509c71ffa53d80801dfa68cbee8135694bac3be58698ba43019e84c4663df94699e0ae38f90c3091fa70c6603dcbe6c7b3d361b3b70edf5d0c1049f3115701c34e0b38e56d0defeac1e0bf6453100d99e7b110bb36f5cb86de116b2a0fdf6d55b41b3b08573be5e5626b3d6daec7d36c04dee53d2cee6c084af9852abd46fa76e2ab5d6aa75db6fdc26a2e962b5e38ca862b12d04ce77e6d43026a7cc2747123e5292921b11542d32a3a4ce988335f57dc4392a9a199bf1234952461dd930ca4749ec71dbc66ddcb6711b6cabda14d68a998cbf6cadba3739c70002d75b75b3c2c9ae2aa8adb1033ee99cd43ae134ac473e9f8fa562084d4891045d04718a531c6bf479ed7da2db3d4d26fa32eaa8fe0f12a6a0388ee0e3f7c9c8de0c273cefc0648a59d9379c70fcf7b3d6379df3a864ceb6f5b474664600002000a3140000200c088583c180503c289aaf733e14800b687240805c3a9687439124c9a1140531c810480c008000000c31ca501195019cabc1bb09c79cd789056f9203ad59a3ac8b70c46a30a447ce99d9dbb71d269c6835b89406e65005a0623fc0c2e1e4f4f60c5e14afe651c890900f851013c17077cea3f18700407172c28c512623ec379e550b45757435117cd6f87f85e95ea391047972fa52af434cbdfa663984ea82ac01292e8f8a3147c4cacd2187b539fe2e828c9b0ac697fa952d8153d626909f3c41b424084349813d64a6c13a1ee05cf719e5c0e2418c35c79a4855cf61d76b598191e68c2629e743a4b471a478670d44a3316d382e526ed1df7b1deedaf1520a04b98491c7e09cc33b6de7ae11f8a6e7ff12da86300cd53cdef308413483735b133227f3d478c7df22b1dc0aa6401221f35f5a3c5d3239e0e5f8e402a04c5c2e8acde18357858a737d576b314cf4dba599e86406da5119d61d4b42df78d6e00bfe0d246202e4a93e2f1db2a41a77691ed3605b64f3bad2ae7c405c141c5d2738e3efcc7d873a525daf90152be2205251af73d8d09ad8705d2d921ca8937290ab24716fe036e13c8db3114172adeef976bd0305f873a24eb526a3cc80459900f78abe8d480bbecd1628fc1f02134ebf1172155671d87d032fb6015a4d845cb160f59d995f8f1a33044f9e12a50e000012283bbcbd146d9f7862a0e1137c48a692a9ac3d445ccd45be773b49f766c70ea4f1c0f888d195c443094c2defb387c5487d1c670a64152935c9e75c03d7d11829416e675b13469631cd6feb19cc30096ef52d961940dffc39a1119ca53d9a48e5ab6b52dc6427830999d4aa43404e3585dd88f30b7dfc58248b31050a307893c322de1162e629b04963d6379a1d5cd90ff0c721e869a0b2f271628d8de514960783e68583308a858aeb718e767cd5c142a65be21687818e1f2e848895f870e4869cda7c209861b0361533c4003630a080942d7b6bc60f4a22780971d00c2e117e1400d15d82aa446136a1182a44a1b7ec8930e2807c8ff2d07ba864e553f945c32cd40e87a9260f32b0e3ce4c6b390534d0688669f9ea734bb6d813a04a6dbdfdad2cacdfcfaf01986585c01dc0c5a50c801cc221cb19023c003a8a04e6d1f12cf3655b6330dced1a83eacea00351da705d7f616c441e8554c1056b84ad16dede116cc87d3d20c3a83a869ea705f9471886f1d1fcbf407786ddc50d2f2d47c24c079b21d76c4b54cdbeeeb537bb0684d90736c5f8ce26b10c292b1e6c9f87f7e4844ff7094beeb675f35f75bb87f3ab92aa0e515e19531769b74152e811ef527d29f0411ddda10d427d5f15a16539569674f22312dedb42d5db87ea950144163f9e39a743cb3854fb4402901cc0ead83a42d01e52af228a2e4a8af08c11dd84f1b4fe08ade3052427a15c85cdad7430b6a6a98aef8faf594b76b2b5791eb2d0a1f5316e4b380b552f5d1b3e27e75726774f076052d7a280cba39d06652b43876674d3e9419036741b4eeafd6803108cf0a102951617dcaad6ba6642e75809eb03f9b5b112c93447f5e4d7ebdf2c137b9470978c1f3bb3eca32c4f645634d4381d5fc26f7539cbe60dcbbd4ba85056929b5c57b29ae8854010de77062cf61d984124a77e10bbc3b93f8364fee6e949c22740457d116d5bd9067568b328265c81b6ef01f3b613abd597ede790cdaac896e979d8872da0e662230cb415b917c2b5d64af5e1bc7b1ea450b8f726e2d24fdfbf0f9f5081c013ea43ba569c8da274d33d07461811bd0a0c3271bdb2c61743a765c97e9e2d76815973463683fa8bf7fc29e895ffaba13d7367a67a9977451fae6dc9974b4216a8cbce8c1adb2c248049f7471b9e9691053586aeb3f08babbb96b25a5ccead731c70245104b21aab62942ab445b9ba8d6b5ab050f33bcee9d9189c3ba7cdacb93e89f101713ddb1ac8a319d9954e245b946079fa6471c141d57cd2e3bdbb409b4fe2819ed3dddfc45308480a5733ee128eca0729262cab89bfb540d8e3df0338cecb9a049512d96fbcff258e2c40faa400337da9d95d12959f250df27d019113f3d232e41496372aa008b60385fce178c9d0d3f159a20c5dfaf21b09cd01002def8dd0c3d63d14e7191bd5a219223a0dfe299b2c0d442c4718718d27f18a1fbe8ff346809737d923669f081ad513fbf5e732ed6a9078a57c52921c9d501c8168e00d80ece63f4a428a27b0dc18a18f2ef14d84e6aa754c6b36db5c66680a3318190ea6550fed154f89b0855f246a41ca749aa85cca838fa81d8c051d7c847b2f0fac118a787969c8da08197ca13f60c416db386faa5a40919d0c5f9f5d4ca24d0464452c9a2ef2c6a604da7e6e57e09839831ae3287730cc4355c19b6dc449a26c873d83fa446defcc9c844919adab189598fe376bc49b31175c8a06d5000663c5f9bf903febbdfd56bda4054b388713c5bf2b7127a3c4ed9711c9182e892108857be8a2f0c68daba38976b807828240213fa197b783b366540df1dcff02129ec995eca16e85175144dd18c787c75577222793f0793de92a861d2203158a33bda1352df299533f8b7d6beeb7f1db1c789557c1e28008bad5f12a6a504dda7b63d58b5810bcb75c2546f2de9f370b055f3def3594b5d548a42fa13a9af06253255707001f1b556cf3fc69871d1edeeec342f5b85edd627268a8a8f0a6ac4afbfc1bb18751ec015432adf733df7f8506416191f5fc435f92c30a3e053062bf12f840353e767dfd925aeee1a8fd68223adba0286015d3f190d5965145bd6e746ba2c6b5a6f34648bf1d9f9dc3f63b63074c2ffbfc6e5554b566d247a4b01a3b279fed4ac00e3bfa7706ab4b2804b3581c5217e4e008939c943f9feff68faf1fae33ee5eb49b6598efde63f3dd12baac697115d3269ff6f926cc3cc8c993a9278e42c700a57866272f19a9478d016479af3cb8bd38523e93cea4a64ef0746330267b8e505103925cd0bbf7e8e0a5c5ecd8906061d4edf29932bb71cc38cb82eada8cdb6daca01b10f39e5e3a6fe52b59ceee150e78c6c75880e2b70713ce1b3bc58a2cfb26a7b1c2f34612c35abc87435a6e749bde532ace4f3b11d3f5bf0509aa12aa6e362f9faa49a9e7354e5cbcc3a804dd7487f66369b03526e20da141c9e1dbc11cbe0baa74d924464fc3c55a17dfd44e535695db25f0dbd6091c0a718211b11cdcebf6c8d68d989c834d36707a5188f636cc29b86cce7d55cb2fff1e7c6535dca80fbe1e4a2096c7d1f4925a2281a16eb26c033ea0ecb44d1c472765ef051f1062fc38092f031fe869d01b1e29b610f8a0d188a43b70901e6b40b59b9f67da257efb08457b619e9aeea84200c8d05b534c5b1e91b766f662163130f30ad13c4e2f15b60381338b25fed84f362cc7373e73f4e33d2062da0e14bc43bb48ebdb36bbe1808a53df952b513c41a891ada49faf3b5d6138d3ed3ebd00117e994e732e036a4540120acaf4ed1d81d3e67ed24aa7f7f167ae812354b995de540c5a901632a3b00c268d664b0684be3760c460928f96e1b063920362b4bdf6d71d250f7a1719a9c2988a66949e42a1a59c0ab988fb0d94297435990696f1b4ff0b6be0a079f42531c1dd099c5ed5109a9f9c5b6b5ba86b5c8f94a9d49c38d980735724714055a6a3b188828a8575406c17d51336393425d00926743e36523f7a05c384b406d8a950048aa5a7a121b5c0db35b484d47bbd21603ed392245f45c667fe3a1f464daeae03906547442a78043a8be15c55c681201c58aa7de99fcdb416aa2acdc40beed01f06bdb47b89fe1b23cc0369e4d1f81b66cbfb3b997fda77dda3737dc4ca90116dc4f575bd7725608a1e0b53dadd815b19db8e0ea7370b5ee583245496fd366bd6f30f25799fb8e187c53e3326ca45e2c5025679f4cedd1ec83f29712a320cb0d4b0a0e4adc281b4e7d13d5ed6bff39554656c829d22ede5f4ed4648276409cf49ef2b344a8c41616c379dce419f920522131e55acd0df1f674f00d64ae82410312648406d44666288a0208fd89bac499835416a791ea1d0dbd8f9d56dfafba09503e84143d677173ebea61eb01a974dacbee61d782c9a0b32ee93c036490b45968e7db4eef66acadcbbe452cee90bbe58d5263a046fa6a88a5f0180abcbc7498b14bcd50e22574489fc373aedd7a4d2e5c6f4d0abcbae25589a22f62115dfc51fc1fec654a281ff043f0d09b5d3c238eefa959edaecb168a0a24f257ea0da85f1cd2245ef3e27c670d075fc5138815c0ce0746ddc22c27fc149e204df29494df0c03551eab765cd65afb7a063e52eb83888814fa05f9a560d34af290dc72bb688835f0363b702c7d6924753315cdfca3c8605d00d6dba944fb32e146fa8c7d82fcb81a8614cc4bf108a56a7d0d76c8a5a8f5d7bdb4ee7a9382f1f8c836d2ba8864a43e31d565f119db7a8904963ea6847b5ca62d93791bda15946b0c011bf5eb704803c656d6f4648e1689e191783f246be8e88919759b4b6cce95b0c592ea6c3fe23920309287057635dff34e13f2d354f25119908aab2a29734c0334d724643efc2183b772101112b04e00607018a768fad5e361d68be1ad551280005beb36d6768be410b5f76da03bd55c317e60397819cbb4c03b8fa9cded6cd45f8ada7792695aea7f8ffc0a0436c3e8bee8460472a60cd379dfc34fbd96499246e54b22910d1fae19a7e3a6f6d41cc277d7b0a7e6ecfb78efb1d117095700341353b8f3c7c0d88b942cbb2d4d38dcf630d896e40691c7f4069c04df83f9c2d3f7588a085720e552f20b066530b57afcca8fb50074a488a9490f25af3446af06c665067ff4a0c16f2f0976f527a3ab7b058407ee53c0d7f9ee392400973f295f230677d0f15e32e1256542e21308a78f832d171eaa57a0b9e8a12c857f1b16980ab0f9baddd33679b7a27ac2b349c70ea6bcb9c5a2ca8db597c3c997ccb9ac532e49ca5583880a32f7b21d6a1c712ef78d9d42a0ea73d863e21ac4b2b16c830cef97d6b3477439ede5616638f37ec89752235421c9cb3b7abdecd8400ae33578d46996f8f8e003c306d4ac60fd399d11a2cd2093dc9d9485d64f710139f3846b5d6821159126cfd896b35f853eaadbc8151cce6ca78fc47c96c9a117824766cf56d5bee6e48d1a30aa26451150dfa03ad1130c3fe50d545892cc3628258b3d7c0e51852bf3c82eb0e005e61c823b93f01271993395e3f3a247e262e4b2a3973d16d1dc7f1deab17cfd70513c9e38156653d26835b61d0c8d11b03912de92fad584ea8c3322624a5c203a682b6c9da1c6e2ba095e1cd974c9df1d29eede112891f12221a8f3b413cec060404e8a0c8d444679f4b0110435b42133e42103235965b59e97dd1d3c051dfacc0eb5a9198f23d36bc2c3c5fbe9f0536d538e7ebda66b784a16b3a99a016a4e286a3441b6227e61ebe31c3f2e5243f22b121f4b061c5c486550b10f6cbba637aed3167dc4f3f97330690b7bdedebb4204e168c9631683f17ba6d30e74a01918a8052eeb3584dd5b488d45a424729a7850765f012a49c2d265d9110c0fb95da5f81e74c3242e32d021e401dfbd243c32f1398ef0954d417833bdb68ce33a6a9c006aab4039bcede821eb7649b0abac969dd07f5816e13ce86e55d5cc79ee147b0e00a58516b31855f93650fbf679d3943e27bc386e7c42d59fc3026bf919e7362be2bfe7124eda77d178603d56508c0ebe6b31201368a0ce29e71c5cf2dffc322267896c2631f2c826d586482185484b6d170088a07d7f8c0e150467ed35d5afc97dd8a2818d75f56b0a29c2c040299c1e22101f46ceca62b140e86932a791a9b09c09b85a94f0ce1e6ec4208483b3b8ae70ec6f91c482742a6800184e7624af489219558bb9233440dd35f06fb7c92b47d5895df75d47ef7df5c55f4894f62ad123bd6eb467c76a9bcdf9218942c49f5fedf127cd327ff92fe24d99889b2661ef1a9c2b7d34314c5d9d1fb47264a479fb7ba638a13007d284627d8ed5537a54ff3696aef45a01f81605202144af65f545229aa6acad51027077ee923ce68b1d10ab3c9842a51c050f4f7d6eeb27ce0ecf5c3da9604ea28721af69ec6ca705152b068e952ae6c082f9c2cad2ce5f06b60aa5ab807c343c55e2e1b0e7a62ca60b004fdadb28693e8a65711e9f9188fcde1bc51f28414113f1a206cc0151fd74fdf4824105ce48905204c54c5b9642ba3169c02c84c6ec3986f0a9dc6561d36b0b638e21412814c2627a2a68b2a550c28da1018f3844c0fbe0be0c0e2b0e3d6515b1fa447d4b9e23402dd9900047cc45f569df9614cf1ad5f583f4b15bc9036c531988039b9e52c87d35130a7a79313315dcab3400f6b67e7d2b64e12fdb19281fe763af3e7fe25a552837c30d4ae9bf6f008ad3b2bfab26285d22c666f090b1c4512ef9946db317080242b6a32dbd9c5a7586c1690a175f31bc048e2a785fd61ee3e7aa14f674bdb26b3f583115b46f103aec26d7e308929ad963f3f3676f7a29d99a202ff1b0f0302dadb400eb2bda468e5f153634003e27e04f7f75bd627b44c637558d6d94370f59c670f1b068afa4b76ba28755214d4e74f39e1c39616d4ccf0e792bc00542b5c7bdfc60c605b68f56f9d17ec37811acb953994eb4fd597aa100cb57d7d81884a2e800d9696d302400c0b02e5663bcab806257e873e47477ef5c750c787eeaced4e6fc5897389d0e3d85eefd33403e05a05cd0f1ac75ff98e5bf6ae1bc87c524256d8b95ae430ab90433a7c301a14381d3bf8b0c62ccfe1b7af6b8466d9ae4ea74bdab52d9399c74ced51a17fc72f9760dde54f954761af6ed818eabf025b08d2e632fbe5b6e8e51c03a1012e76434015969a3aab33d7e5514a4a40748965ee78dad9ba168f8fb8442e14968deffb345a4d1c20d523615d2c20d5b9580c3c6b340369fd7c6e46d7bf8edb11fc5a50056018f50539f44a4a9152e78859d45c5516905607bbe8a80f857d8794ca0deceaf6ce1d7ec4072fc3d2093375d2fbfda23a915dc81f51fa93b4dd6bf7a055cd4cf593b4c8370fd5979a3585e9e1cb18d2ce4acc7ea1bbea4cff87399e84f3c44c49a7646f102723663ec9f94cb1c13e240e20b83dcd22d0da7b2f7822da2396adadb180ec4351916f57f905e6f83d49a044a4ce3d1511c8248ab141db53f00f0be0284d84034ab1cdc38a0603e35735becd2f59566f62be5bd5a318899fa38e93022e78e15a030eab8b42bab46c245a883977004cfc55f81431d514248aba5ad10d4d86a1cc2422ec9a64e59976a341d1556145781f68bf8916a0abb7db1269751911e0748a9215ee37af5b9530588a6b53534f3604cbb2d97f250b25821de35fbd118e7d49198d2536dd292d7e4e58b032e3b332bb7524720e668e222df87c49c69da891ddbeba746daf55850b2cefdf9f790a03e1014caa6190c6cf33873bb50f251f31b4960e9ca449b85339130e540a029d58c173b52af15d9f39d92b0b47cb85f3d707cb7bc030ac1ad4375fe7226701e3a99079acc0c3d66adc4aaa2b5e46d5bfcc6cd0321c8e435a7ac2000f1514a657414ff50a07db0a299d8b33a9ed8df27df341c8bff26f163134f874d579f63f053c92c12d3db2ef8ee728004e504cca5bc7c9909fe4376f6a5750ca57291039026e527b365748ed5968f707c1a9565effe0e0d5641cbb50eb0c6c808f5f56d2488b5e9f107a9edfa088092ddd445ba7816d8453392842c893cf9e459f45f22fe17c92130f30fa5f0f28deb44c01896f623e800f4c339a2424caa6af7f03644db8053ee4e056d7a78819a93bbd808a2e602e8584ab363a5c31813706079cd128bae2da7c0841b0048f56142348df9068c41f458d6bd30e4a81eaf1e3669b888dca48442c9998db5f7a1a8a18492ca21b330fc8cf2ebcd40b272c596f62f8dcc3f667e4a954b3f803f931bbea96f3deb015db8b44c2ba3fc5aec780903fb245a4e53b0f6d5f10f6ce11f87ba852f17e24ac8dd94c949010dd83481d4d825ad3ca81c7800fd898a198749221fa1d92a692bbc88f57df2c685dc3941da53cb836e3925f9b1331863f1c31e88f4f6022c92c4df7080a85a01eccdc42b7260b42b86a474ac57aa01df20e4172fa66aa8f00c2cc5d81dded9b5a6100d94db19866ea16d94e846d5081d2e7085374c6808609f83900398738ca8b5cfdc8be7f85640c8caa9479f5eb420920095c3e456c573612d30c7982c285aaea99efcc92dff9a02a55e5de286aae3bb10458af58ac07faaea8571ca3228a48c43e1ed435708931d690185d39306492cf5a92f831024d8b98b95ed6778ad87d1a339d342e4dbf2b453fb68f394f612d365714459996faa1c8501b434bb4c05eba7f219ce3ee5476eca2fafd1f125b0133800d306fa0a5b321685d90aeb65eea0d43e6b578ea6cb6b089856cf9a40e0c140e934c7c16a17a72442a7ade5a26bf24eb575fe7f0b494f13343204dc3231e2636f3f32cf3f3ec016c5e8e67d0370cc90a508c1a12b04b84ef29df7341f2789915f80b14f482070ef32d186e79176690c55d22ebd6b1f38d618018039f0143904d00e58b6194914addaa591834585fad4f415b57c2522c906165ae4d130af07148123d1a2a66cf992de6a8139965f74338cc0717c68a6f95c7d64a39de1bb3ba6fa4459b55de5e681da223ec9bfa001e731c239680e72aaec60f59b23ea2de9a62008748bd691ef71f6b8b0f7dba190d7e4a0754a2db24cb5c44aa899c306bc7cf84abc06d9c8e3a27d636362e0f765077b87d43adc7d8c8f0cd867b6ee33146922f84db8ed187a858bcc7b8d33b87db2a8d7a5917ced41d7a1cdf45523b768b70ad2d65a3d4026ce00d8d0425ab3c45b5e520f20745b8919ae11613b43ed26b42c1d913c26db05291608f8720478414852b0bdbff9519b930d45c8ffeb0fb2aebb7b63ef5ad105618c28b81646bf9f79582a2e90a63142f3bdc90a1d1c4b50424a51d99881aad394a21e7512bb3fdcbcdbd68bc8b3220145e0dd5e6295dbe0c732b91a5280c025c07083eb3da768636f141404b6f7cf5425318c87fbac182809845931949b7bee05425fdd7af4fb99d27ed2b43b1dc4eb8122c19f76a828f1985cb9bd1f0cb025f9030065ac799d062293e8164ec4e621afa53129a0d58369a45a05c1e15a07d8f9cb334d700afbd242a622f903049d410a71a4d09161bdc7b9f778d466668bcdbee39e76263a9f1281023d7530ae726b0fc6b60db524459a62f7577599000bd7a19eee8ffa3516281f0e6ecae2f78475621c31593a3987641bb908ce29279ba63a0bbf48c37abaab2992cf9e75faf6e1d31b1b6a2145efadbe5b2afeddbd0b642136261724a66ec0737fb30002df8d62196344ac1bc47aa191e8f67be6c3aac322abced6c04b40b20a7e664f2eca39a312f40c8a98f57bb989b4addd4cc4d4f9668964e73d3bd3f64544f31a9a2414b03bb73d3027745a3c1aacc2eee0196982ffe91384f12cd3d20934311741a3bd8cbcd3236ee22866f4d1a0feba788410be4a604daa932be5e4de1db09907fb00ba658fd62c6543864477b19109f34b3636d337bcf866de0f558a4645b40e39e03ca0e546466821de711b848b05ef4188fa7a1718937ff8f7e1c66b2baebd59fed23f8f2a8f4ac91d8dd4ffe2472c8eef9cbbadad6239ba3a90f41c9947410d88ccc02ddfd78dba3e2ffd2c4d3261bcc40f219526b94abc75a7d03f03974f03a296b25abf56d7df5583afa4c375b7a7bc817c7e736f997a7d54c7283456291b6dd84ae1dcd129a34a5fab2962aab008ce02dd3441381f59dce84abd357b99b7ac81d5cfb1d7ac640d87ec553cc2f70562868c8c0ea68ab8ecfc6e839e8d5f27c6a4dc869ce08e500d2189e5ec11ab94f34a658449ee7aac3c518e246058235e31ed404aafbf2ec388b0c9692a155f7371f4e9e1f04b105c17a53980110de11f520b840a0ac8e1bb7abca6a09ab71483c00df58943dd8a8d19388aa07af10a89ac8b4194c62b8685174a6e75c7aa1015658437faf040530a7b01a372f84131250ec5d8cc025ebd341d1bb99fbe012e4a112646e5c2c9914093cc0e26aa3c4b834060146bae96887052d1e346fd2b582ad578f326f8fc0a46d5f12c964f3ad11b8229fea1dc50e6c27dd54c8fff4c71827b119c481e92c0ff4010dbeda115695dc12b0ba8f3ac4387e3bf93717b738761ba407f13f2f6faa8b9fed956f575051850935a2b43569ddd2ce56c89cf6d5e6f73b1019202415c87274a887b3f72c8bc0fba3364d5f2517627bc9d1bbbd8b5513033d331ef62510678137d1741ae742ae0ecb0f4d3f9a32fbc553c88bb24c06a94b1d65c1819177f36da497235c3519f78548c8017650c53bbb8c1cb69cd553ada0b130c065e0d4289fd8cb4bcf155a95ef04debbfa54f5b9ecd657722d821274ae3a9abf45854a5a67315eb37429e1463ec5a983bb690c0666a57c61bc3053001ceb48643f758c8272e7b647d7377b9a76881f07b47047a2bafce09f25865a4a953aa797d4eca2d3a485819759c59866c39a3fddbc60e45b936f7562fee6266852b8446e407b6fc13e4fc60bd94fad290bacab790884ffbae472c8443b08aff302d19ef11be196ed740e2bd9a4fcf2cbf9c0191464c2671b2b7cf943de2d07d6c2b2d1aef897e6e4d6ee1dfeef5a0397b7ec779bbf021ca32abc3bef9f09e14212b18abfa32282b167e47d9d0f9b34393d698fc3379435a0ccdd04ea3bc483074fbe754a16e1eb051992efc744ead7c51600cee60c85e3739d995bb5aab4f38b68052ed7de91ca2d8821451df98097330e6a357aaff8dd640646f08de61cb2b0d7eab089b2cb035b91ec7fdc2012b27958d1f281d3e4ede26cef5b03942937792a5f671778673f9c582c7dc6697554e203f181d0aa22896e488b5595623784a65755f13d05571fef35db71f4100b4bc95fd15a30e8a8f82d343d197a02738e0a6ba36d2c5437a112c3f21aadad6811d08641fe6d2609051290fabc58472bbca253ae651a4ccfed673308a8d5343798941e07d8b4985dbbd484fa47cb72ca4d7f938faa12b0a5b025eeccf27632fea2a2864a9c58969069a31247a23a6e7b64d10b3a75dd798e75eb4b2c597117d04b54a9be554614a662a2adea9d988bcd770a684fb8ac9072caa94e99c7e779fb26108bb36bb46c18833e075ff760c80d87e5bffe3fb302164f2cbfca2be87d9a90eec4acaa4441fb36a4819fdd0933ebfc06be6c3e95341b9af549f4ecc2d5e186bd9abeec36fc3ebc3bd49b189da0ba6f3d725cc57f559a4f78ae629abe4099d87195e502247df521f079cfd69305106092f45a4ee8e205257f5b58a3cc8d76c9a6e43a7a510a0b007c857652a2bd545064d41b9857e5e7d59920da89c03e6c8e53c90d23a02ee29a4d84e20f03ea94c275ad16c4bad85fd02e8cfd2bf3aeac466ea80a18975463a79b728ebc87ba0b4690cefb5acc8c5c58f0bd044f7f35eae1503662fe24e0c5644484604e893fc87f0ea2a046a5ded233698a6f5cbb5433558355a4cb4c0599b4461f7a8223d886eee66d65c8fc2be5aeea14c6153d921084f5d4d0b5cc93797266451f19545f0448b4d062d81fba286b1daef345dd079b5833506166c86edcc21804192555947322f1b436b6fce06d7e1036ee3fa72f1318f2636428b4516e3b274e7dbba6eb0c279113f86caca6568b45b71a16ef97ac789edbc7822646b6264b21a37a067608e7f1073af9303dd4a23080c90dd8b70d785618ed5a9dac5504ce23e900f355a6e08a00ef1a1d3df5dbc91e6f9fb8c7ef847cb41bccca50eabf973f69180c636f1a9408ab12baba7c8116d6632314fe33e59e36c5338b7f7633ce8971530c6f7d68a82d925c24c5cf8222a163d70842f1399ef431041fd9ebc8df7328a17574eaab139f3f9856422c8c7403bc736d8ea5c5b6b4ee12905bd15664a99e2d925fa1bf009d4fcfa3f20b1517ee1eaf429fd4c2f100995f37cc324acc89d71756a802a023a06592c98dafef2def1801033f24aeaa78353abe4ec30da0c368791e80359088c0e0e60e126f01513d4666c8fe4b5d17aa3eeeb5d857b7507cf24e16badc92a64d789fa26ca70b51a3408912ba687d396525f78e38b159de81df7b11d9de73698ea95db309355c26a779a29be4c8711cc78344741fb23b4cdd1917911c043560493a59326652106f401166ebdb9c39d7e384887b8bd76d0c3938f082f98e3450d04a4b6197ab351f3bca83f49545962d9215cfcdb2d390875f7253f5ede667fe10f8ae85f30fa185220e05c9d807496c4b1da39197268b537a3a4ab43a8503fd28c04e185587fd9548c98e5018e1aa589ed9e1399a9e0798304edde338318b299f18389ede6ad25952de4d6f404ede41df1d597b8b9ee947c558ed698bbeb424bb76ae715f4959e09d33acb11e9014380f8859b894b682299df6d9f2877cf93518dc7921ea150d2788ad26f640cb46aee51a911b6246905aa3a81dcd23ec01be54a0a036bd019118a24f76b6ce63f5c5c2104ee00cd40ea76855a7e980ba3007f78049e3a458d07b737691b9988ac6403fd2adca49a1a1c8457d14285f011cc6bf3e957aa77faa1c8e6826f9246805238b78d8f732a822c0a746190de1cc83beff9e34f01b20d8c840d944914709189981d07a9ff41d4b66d3f15754b3b7fc6cf3869f513bec81d1b67b254548bb0b2d3e4112544500c251828c6799da2c340771e02576af8b35c12daf72a828d4a94fd8823997453457efe048295bd616239eb285c258917e3d068f3a2a2755c621f7087f25b37954f075bd04df240e07c827569bea50debbc0b80279178d68de753668de547d20e950fb0e5f191e0728e7d748f4e9aadfc4ca32b1d873f98073c858d20492986e6bf83f9c8300f3868c4befd01e9efb7becfdfa09d7d3f768f83095d5d0386173f8e5b6868899d49b9f15668a3607c5464962a10fdedb6672e6af9573afd079fce05745a0302b3ea076356f84aa51314eb051bd8b780d0f895fad54183fd6e5e824e241848c5bc73e325212e8d8e80274919935d8bd97ff11089489f35bb20340083bab3e461c184f7c9ebe88dc92674240422ea85ece51c0030dbf78af41320a7a50f2cfc6c327caf68f75995eacf7a495be225fb7dd6acc6a3275d5ad385247703df595c1cd015e311fc1a9ebef6fb211a55ece646fc5fa8448d1ad7aaaadddfad2ce37bd13c6357c47dfc7a5c3357f74921ecb671ed5af3d6a86efe10f3ae44f07509c41a67c85d0a750941fd0abe1e7de49f4c42ae21e625f980290823f3a8912a3c4b1176a79ee2cdc41316908da32871cb3450667a8fcd99b2e7855d3bb7d1c9645dc68421760f71e9f74997c52530ca7ae3d5187b673b0ab725447837acd0a3195b51de626a27296b606ae8cafcfe0a57ab8a75d8fa96d4f2bf8fba074971e63d96dd359da2ed439dedf960ac02d1ee2a4a5088a73fb502d3617556a1a7ad11a85131480f4ca76cd3ea480225d1ef97625e370ae4df9d00956ea4bf1d5b32cb37a241d53949e22cfd9d1981e5799204f9c104614b561c9faa24cee688365b60b662df7821acc80e4824067f34129560c690e85e4b51a0ef2c4b30bcc8f949ee326ae84c38a2fc13184840317a8a5bd144db2d701b4c85dcd01e4b010b0e0e707bce76b2fbaaad1df162e870ee0bf5bd8ae55d316c996246aa8888462f1d335639210622e00ee163b2f85230409517006f17c71d577a91ade85f3e999ba48783a3fd329bd31d8f79cd572eab63f717ca97ae0d140228a3e732301d44e0f39f20b90cec76c378785d7682a1646f33959306d05e5ef42200d94750dd1d41e80ef1569c95352dd00a12b919bbafd43333d9a9f296a384f43675ad617eaeccdda12c3027e52138402a27dad9e6cf6e277d30de4723e951275f5219d2fde3ad67ff33fb5c0bae49a15c1e04599afa4b819c5d715731e7a2c7bc6f60e3d800f19dcf2e0b428350a0f6126dcbd874b328e58974489f22b8db688c32a334ba785841fbb01ca762120b8b03bc8418c7ed2a1d433a920a2a98b68fd991d72f01b6a4d7b4b2fa234ce798cdc1a1784db392529a01726d37e5c844337571ec09557d704a0aa3bda02a76bec69491056f0b915ace57d9d8959523b9606c3f1e0f3ed7c16e3cfe92e29c450dc528c41cc76fd6264c1743e825a2309c7e2616e8b8cc218cbeef538f7f774afcab01d61a61807a34cf600698737cb85299a8bb59230b221fd45dc3be6058d81252aac3b12a7905aa70ea439e84779cc8b2413746b2718aa4b0a65051bade844bb70b1d041eee6bd46ed7ccc4c528a808444a11884ae6242748585ad5c94a37fb640670cbf6a1419cbf2740f46cd6094cfe8bc3e47a1d86be1def0b70287796f494d6775be2a768711d31f60d75f6d9a5a060d2671c3c1d7bd31e486c3e25a2f12e254a01aa1f9a186379bb95db562f27d5a78e01b0ac8cfb137d8d559733c93276cafb93bd18a44670bf4026bdbdcc29c3951b2b4cea3b7202fd974214b6baa8a47b50fb2b8a1044e8b64fdb72e4a7d287eed020a503f424b5072d709bd8900bb14c5df53e5fff2f09fb6d191465a0f0159e8cf6c2de04a7bb4f91e22f39dfe78569160da1d08a8ee0a91e5a9bac312729e14e6abd410f9161f513020ff45b8062974000d86d5ebe49d9caa04902ef8059f6b7ae509ccd0cd14727a266f52a6b4dc207f40b25d06b561c4e6cddfdd9803ef170ab62685617ef968d4261eb95c760547d4dd08ac88a63d189c3306334ba9a0e052becb1d17c4f86a69035ee67ed8e788caa0696effeed7423ac3f11f51cf28ca4c3afd36ef84bced048df7452e96dc952d25655fbc4ba895d4531434647ab108f94e59d5a242cb81cd96ef84279803a431c10241897e70231a219b8a6cd4731bf72d50523e94d0a92403bba3d7e1917739b01d05aff550b6b089b8b849955c93cceb29b31f2983351f84653fe1b84d795732a08dc8f882250643379785b3c54f732452bd356cfabdc51d7de6f71b9b2ab3bc9e6846413cc48e347bc573025e8814638fad7ba6c76e9d7feb325b4f6adb47d84f3dedc539bfda7e96e822a1ebcac3294a5f29992949ea7f80e389dde233ee6eddb8e0f800594ede7f156ee3ef855bb27b5fd4fd9af05cb24b06e0f8d4cf468c33fa8bc64d46a829dcb195dac426ef3c76f41b4ded3203726587acd0e57e9f54fd2ac383cad20aa20ac3f39cbd21429f7adcc613031e7c843ef68e38f312f3c119919a53f298ce0774c7a8fb29f58a4f0139f310b2fe3c1db53560953a8c49ded0a702eae16eec3ad8806a440fa1a80a5e8a633c144e8c9c3367687f3a19c8088cff8b8bf64c60f41cc47810f1b3c800230219d3eff359b1af5cd67511d1da08949e9a8cd29c3776c9631e417b7e88ca0c01af10bed1e617b274416291d5d2f4fc24d8d0a177c988c5890adb1122b73301475001a74312a30d5e0ccf88da90d4b69f8be88728d0023adeca9065960946b2fe65ec6d911cac16c14434b47c63896d95b0fc78790688c6ff258bfc27786fac0d8b6ba2086bb674fe833ba196e74cac25060bfd8db4c4104ef2193de2a2248ab07f91bf69315c660bfed13e182d113b2a80fc5e487639ee5a19be9036d30b467b43ddeb388852f45893c768788a31f923bce036a7eda08293e054a14b8680575f181712a36123dff54c604c9c5a0ad7e4407358f7678f2d8fbfba0710c0ea45f83f69004caf3d386c28c2a0e39bc05452041f5ef4d698a5ab076ca8121bed01b943c7af1c844e8ed2448d5ed96f650dfdb1c70b1eb38527f0c41ac3e20caea0b97073a03d5b8e28537618d2bc69145c7a941a2b9f787222744f856439c3750f168f77790401dfb3701c7558da523af1bdaa13289075016be3bd8c12e1c3eca5068a3ca6feb7007a0060f8b83b750df32ac6891b05ab89163ea4dd8b0a3c4d5974fe791dbf6a4495808ce28c322ad0e9afdc4d44813c6ad48f18b50cc36363086aad6110d203581520b08bca7435b6e454c5db160760e260640f371af78acbf2ba3a95be60025a92f94dca9b86881b2452ae3777191c33b9c489905d029eb5e613fcdcc71fe1e651c45b5cb83cfb69f767a3f7b629646ebfde5dd46915f303b284dd70503a69bbb00b2eab9ffaa719b1ee30db2bedcc884e775c4b90e8c58f7ef8e3c0b492665d6bd191a95d54c7878e92de721e82bec3de5903d513ad51bea54e6457afad97c2ca829c281c97d37fe60739401b432cd97d285a0245c245c4743ca17b676575d955d61dd729ee3401c512bc4b686de02cd55facb38abcb4f317fe50dfb0705da71755cbdc3ba7c989dee24e1e44a9406322acc5aa97564e5652335f08270c17f68caaf01c0324ac892d224e3cdfba8301e49017e38249bb26cfcf5428b579d33653ab50a44cc5537f9495ca99dda75ac8ca5974dab538e92247b64e2d192957c211fda88bd871b95964b9d282d7d7727fd785bf5cdac6c4473732f3510fc33ac516615c6e1b0f328386f714aee5e5e539e4bd5df05a775260152ef6c595708f2442c6b72c9c6f1647bc60e51b906c17fb8849fb29bbf7878a2aa00a0d23256f03e532933a5e8e8304694f8ff4405b286694f3f835debe5d2fe3b2819d0a52fa924ce3f369181793aca51d15cc2d932c2c2adeb4c416dfb3089b8d244ab9740d4a8d2a5c5bc50a4bf71c1e14e120c5b30ad5d0fb341181b52953b67d9fc50ad7b2f1f199510d88e8a7517a41b6080b360840131d6bc9fffd4739090507cd4edead665ff275eb8ad11f2278c4dcfe4ef1fbe491074b146b681533717458a108058c15dbdcd413684c52bbb3138c7caad85d928965162f428eb59537d9954ecebe1e24611628305af907eba2a29f895138f64253c550aa2fcf41b88dbf556e0a54595f425feb597f31cb870ca46aa4c0b82d7c9cf4d33948b1b292875734e5469f4d4bb4a7d1744010e438ed57f5abc250711b945cc850bb591b63e1a8f1598ab832ca63fcf00acffa3020fc43ab785137feff22d98f31c0aaee495fa28de5d4876ef4d98970fb1870cba132b81753b74054bdb08c9fb85325efd7ff751d61d9b0e2536f01701e1322a4aa9e01c00821517e3e3ad0262c2d90f6bcddd7b9c23110ff93f5fed2ce345faf9b093c36b1e7419c9e241f4a6dd53066df76923326ca5f2a963cb91d885aa8030da7bc8497bfc1c2a0728608417aaceaf8410b5916aede8f6e16179af4729bf2c6a747d1f54ce04d3fb7f6a538acddd73478501a4b371c81b6d1a5f55f6dc477ca9dab56eee308ba9712d74839395761563fea2aeff298f1b34a57a1b0d32e065d7eca75631587a805b0df275b8b263e39a63c5f9a24cac358f813a81ba077b763beb4c577bb137c54b52c5042e26152427dd934389ba92657db6fff2fdf86533ccbc56a0d2ac712b034acf5b62b17043a787fbfe79fa5eadee7c5d23980411914326335aa615b84dbd41442093e104367305ce358d1801f9b8bc72e4eedfbf4693079ce6d99e52004cf00d25e79006a5bb61f0b0a2e0fbf038a134c4c26fe655dd4991da345c6a17f7532305665c11bd685716fa1f2640d607d801a258e7f59d13457617f80fa3e7f44b230b9491295786dc29dee4c4db00606f5585f2b960887408acdff2cb691a34878f4426144629518cc179ea35173405161f9bd556904870d6ca4a1e2a6450f654304b1f0f3239c52379b14af3c91743e0f3d0583513b9175a7d90545115a6f377a3b149fb7d31f4f8f380ee048a4148ad64981cb7e28dffe7cd5ad37e1f3ad69ccc27ef16baf1b5be48a39ad4892b7ae4747d63309bdc0937b591f0b1c95860f8b6e693afc4655bc57966e11888e5f6b3415b8571bdd0fff799ca1aecab9382abee907847a4d2f23951e8add10e5a25f526b959832520d66158cd41cf3dbb1fd8de2108c1a7a6e8b759236b9647beb240e39a803f267cd92ba0487e11ee9b5e94daa6002ce3ecccb8be6e3ecec6b1f96213d4b4e2e849add7fe0337e846ad8e2ce3515039dfe56a4abe6e45b1cda8c49d2f3fde0d1b22e80f934c5d3184baaf040760bb539320cf697b2b875a1e22cec4f14c3b4b367fb7cbe160d0f829dbd898eef4bc825f38c06c347411d03354aefe7d8b22e8c87eb0e5181542d04db09f7db538030839481a26ca10866654fa04a09706e580a24678132cba2172739fa8d4d2b089324b99ac282f786fa660aaa1346fe0972ebd510de75854ff6c446e6c42ba56d4fe3e059cbb0e33dc34a44c11b9d582b9fa7ebed792c035e5f68f88e9fe7af6db4db332555abaafe4453cd568d648f7dba508af82ae8b26c92552f80a07b0be8905a8a400d989e9861a0afab3932ead7997c5aa8e351adca49fb28f14d6f97b55e0bbe943716913dc250342c65f78818934ebf8b54cd60a7f499b2039f90a2b65060e2f1962636d86bca2bc63d8bc2218da40073e3db9e629ab6dd6cde2b93e27c2812a2a91e3c21c34d39987cc28fcc3b614612dbaa962a58664c3fbd156e44b5c8285f736c508e1b3e551e9827afa0d90d1a9b6a396336894be25a17d8df907809c662c75f23db7179b91e930d4f2830bb030842c9074d88bf8e1a5c724f2f732a187c151935040c852e1136958b52277766c20f61d3dd11734a936b0d56c445f315f8b764e2c1d4f9eedfa4005033ada7c7f84d1e7f22d66cb20f66bec89ddde30e34aa0048092e893fe072768b6aec9c3290e9af31e2a9890d4db6f5a680f8ffa35eb1b95058caefbefc3064399daedb6b391a858eeaca10a74f491817fe0a45489a9d96616bd1841eeae2b76020a3f120dec08e7db4a39127f314778804606d6890313f341d1a8c19323b1b40e32cd3d14a22ca229ca1004081737a5e08fa5fd2a3c5142e77dce13399e796b6836998e4ad6af82a86f2405e3c8b81afff9970b6638026f74af89799fcadf06175e398c57d91d6365464cdaaf9ecde8fa3ce4f2feaab3f2b31b1df1860c5a560f21d4df8ddf46d42ba573ce50542ad11eccdb5c280e888777f00e81c9a91f75ccc1fa75aee7badf8d29be00d36b467815222914a4e0d9924c34da880001184fa2b2fde4cc638ea62e81ad96de11942c9ca02adaf35be6aebdd16d8ab386d13a8e7b5cac25abe9407f451f9a0aca8c7c45b7dba74a6bb49dbe831d7c0174599c621c7aa15c68d4aca456baf33df589fd407cc8fca1c655a089dcd5ec0e94b6b3f1942ae2491b68272262eb02bdb6af120e0b1545284e06975fe49dc1c986490bc052e3043cb6dfdfd1daa5bdb1c6e375073e107838aa8b53c79ca75125c3b94ca35de68fb9e075c3243885d708a156fd96f434f952618aad78cbc7f8333f8737b51686987204cb03c1bc7cda3494669f3e50c8a210251d71dd7f8cc4c32b45b8a327173615e6575b13ad4db2e42e6ff42d46e0dff550eadaf9a86a02244e64b47a7471e5d3e672dba24662bdf5c56cd9b7bb0ed8bd04bd80be7c5878e2f48a35641c35658a5205f9a53f543b9748fcdb55d313a2429e6c29bbee2c942ea144985f60b595688a164dd80ffbb46e42928c10b9b42ee27bccc863a9428fd5a554594e69df39a9b18a1dcf8338afef91a1b10eeb3229bb0c6efce1787c76f712891fb2dc05619828b0705bcd8eb2ee2a60ad91bb980da500e4185dc7d241a6750856dc0be4cabf360a7edaa2add54b45b9c538273ba6a72aea7ea2283a968c20b8e0846260c8fb09ed81e76b494264b4f79a40aa1b6adf4f5aebfb5d4ceefa42c82cf7708f53c0a82442c2d1c739de6d258a2aab6b72fb21d5b3399c782b4432b5843c29df2162bd5855461eb679def39718a575cf8da672405216dcf9372d6b0cbf2d879951ac8206d20c7aa60f2e04b093b706ce346ce1ccafa3c2cb8ba01d7c04978bd955589ea0697d9f9c1864ab15eea0f5aea3ca59f1979568e01021fc5b06fc1bcfe260b7ebba5a343cef7976422d00b2b6d658f133fb687fef38e4e477f76dc2f850f921ef443f1a1b2598e3f7741deead531fb9618a45d59018c76a1a0d5d81275543b0b3d2f7e72761246104312be4f1176b4c173c064bac8afb9d2e97d1e72dcad36b61bedc9e356d890a23c5207216632b9c99860eb817e8e5a15b446e8c5ff62549b6126460086590f2ecf826e9de37f8c08d8e2d7a45ccd24f26956af44d3c7cb7f4b196b84aed952b905b25145dd0a65587056b1691e9065dc4cc70609db79f917e3573db2b0e203a0862acb69a6a4f429d2856a3b00f4ebe624d1378f8f031b5138a9fdc4993a273e4c3f0c68fcb52dc90d4869469ec9a028c7e007f146842155608497994d9eb2362813add94ec625015490539c259275a4389d71483ee688160682f14616ce17e51ad67cdfcda8dc2d09a551ff5a2eb8b0b2764689c9c817b0019209ab8b7c074f1f9de15da1b52d3ae441492e763a2eefa6e40da5f54bbe76843c20ed692cf6fcb6832e52547067d187409fbc058e540503b139f8c1ba1f0fbc8905d6ccbc0bfe08b5d71137211755f4b0868c8cd9e96ec777cd5555c5a994b89a4a92d5eb66e4053cd4c34a7b6ecb1f54daeb780f68ce0623e6381352837ef340c6c90204b77ab5ea3403ff6fa4c72eefb8359aa115010f4faefd6fc8207cb459f02d48cf21ead338d8d0e253597abc2650650b633b14d2895fc46ab4461919a4eee67b48bcae074ea10b3ff4eb8748473e5927df6700bdfdedd417df0cfb71aa5ecdc3825060fab3a2f940ed1918bcab7189849080870a33aa010d9d5d88b64700da39c61756abf43f440aee45e1b12d883336a59048c55d102a9d4897ff974f2d5c41ef3f7aaa24fffd872564c96d1e39ec279fa183c1c1fe6a4c29821b2c4debdf01b20c137f152f96c57012101ec5d6ca4980b59e626ff23b703e3e61291dae24befaccd92ba78725c4b6bb959fbaadffb51af5267e47748f502f9addf2896a752a56fa026d6041ebf8ee04c665be1269ad9085dfaa4f3c0a6573a20234f3024ff07e216cef358d86a4e7281863f0f7205e6c50a3efac602bca0ded81b7fdf2ec5f83c8b08236760ee993a29d61d0025bcd0b13f551e853ab651f6039b83e3b5873111f7fc58d773b46952ba011bc0ea08de2a76b8df8afeb7925371f32ad08b28bfd635c84034cb120e2339034c36278d4256c8b9a770be440919af0bbd3fb976a37d66474b75fb7826ff34d88030311aa88ed27bc996aa3d9fb4877f8884468cf58f0765a4f69ccf148ed6d0f0c6749a77c2814773d8460d48122c922a5815453a371d51b13aabab13c10326b8f00d0200aa70ab92f6e9992d6dfa80287fb07989b3550446caf5af40dfa2012c9bf3e6021811aea1dd308049da641472d750b17a0574039b9974cb5712b442530d0614339f22bca784c99bdcb81c822d71a86fc2729a50923a385459c58b8248238969c399ad595eabfe0a9d81919729493f453b57bfee056813cd6f472283a37fb3ea332129170ff86634d9d6d1283bf49ef410664d5b74ee3f90515b053ee095670be9a7977533d921a49635284414c8f54f813acd9f787eb888fc67bef318979ecb0da6173aae06c89663b87d7e1ee0e5658db21a73428b34867b6c32e99f1c8073679dcabd4f0b01fb26a15eba572a3e0cb1bd9f052fb0925822c47ee1f142b33669bbf71946165df504c0023cab0cba3b0179c216f10a32495fb6d47ed2515caf779ee5f368fca1766648f21439ae37e1897beb862fe5d7b396921ea7006d995cca3b3f4e32b3f9e72063afb74ceaf09c10d431a1710b8a457c9c4672a1deac86076dee177d6dfefbc50de6a39cbe63c01bdd4ad160e596c443a046d85875d20889cefbbf22e93693f77c1939af4c3145ad6413f759dbd0e12851d3c243be8cd06fdc531a178f5e7c49f81216a72cb8141457c02438f05cab66e9aaf602039c5d35d598214be544ed1a6b0f9e4409717a018ca89a0db262cca67b7edeb78fe3f61fa8ccd1e4fcbe8b06f60cbf6d24825802f5578299b1c59b7f85c6fc74b7b3285705aca33540d31be0b49a6be336d9a0bea357498afe630d9eed768524507ae8ef8e7f13a8c4e76e9f0322f58bd5bec62e42228166396ef2abb718bcf14ab510451c38dce7010694b6600c01ff3b8297c62c943fe599936dbf8b3dad21b38f5d23d5c32deefeaa4beeabdd96c25d3a0975782b10842708abc704a2e70cbdeabed664f60272e622e750411e405f2e9d9d536374111d6365e42e8c6e14e06260b9658dbfc4aa13f90a8e01d1a2491a2963fc9a57e1adf9baeadc9a7ada8fc87ef8486d6433c51d2dc756d8be1e81c7768d80504cdaa705f523d6b5b57e83a003c5f7ca27fa980d75c566e66286e1c875226556544a7de44e75a4604fe55662c6b52deedccfb95ad6d0393cf047b1b22055e32a817712b2d64176348b55af0ebc6cb57ec003a93822c35b935d8b26d6f9739559ac1c4e8828999fb65c328b8827e50b667ed1d91695ecbcb189d99ab750d597f4b3d130fd9b6a5aa31c1cbf0fd3d139de71b35a660671375f605878a9e1fcb1f67a792a56c5b3a107ce145edd0806d770ccdb60dea7a108c3c95b66d655d0e1dd8efd58d940cb1096bd627b94455cd0b45a4643026a392f0ed9dcf65b853ce11673ebc36ee3357940735c90f239711e6a008d26f5c511e1491afa68df6186ce53045c3a5d0c19287f14822461b897bda7175c72ac639cb7407afd76c9cb80e8c70ee960cca5117d152721495191e466076068bf2479be07c3bf464a3bd3bdf849807c13c5209e7d0aa600374810ea5bc5988d8377abdf72eb2748165aebbede94b49ecd0c1950ded6a6459d19968db5e21571a355935e864233456a785c6b7827f066cc2b87519efa4bc3bcc12f2e9ed4e51fbfb60d1f6b78f8761e0b23f0e2448c370043299f6ea840b2fd5793777a7193947b2d16ab19be4d168daf98227b67ea4a31e9059fe1ca70eb0480e23f9f01dc468522d0ef37109e73f0ae4ba2e2ac747af6cd5c07d76e3c7f3cb8e0b5eb688964ec66d661bff4ab3e90a98a458e6998fc171cf87a6bd0a1172ca0a6b0ae8d77ba9327d7a57021c5cf8c5d4b55d362f6f8d59804cdd88be79525eb9e0318e3e6e4880471025d71d706f2f9c42ee9fa6321479ca5f7fa5db945949c44425a10b6d1d7d095f04d1baa00bcc0573ff1125e625e04d654126561ce5711f70bd48a68b0631a875e201835294a4500a3de0ee79579849e9b2b0b079e631aab380b31b23a3063ebae07a6d4751d7817c972e85337c410df313417df67d95de425b9bd9c702e03a8325682726d1e3006975f5ec46e8d2ae2d1a2c0f973bde4e42974d9249d283d538c9cb0ecceb911177ae3ee92fadb0451754e6fde6f47c0a84e0f3bd0906a4021777b8ea40d38034a754399752790ca0d61d2dc4a1ca967db990c1083df1f230f7c70121b1c3cb826ab5cc728aff81a56a027aa7b6a8c2fbf9aa9629a44a295a3ddd208de0a14e7661de8ad3589e0ced207c04877e9fbe92f8b3a6b7a1422c68e7538fca57ba7d35144d97225ce0d7cd1a0be055e002c7a5e99cf796e468b16de8cd84e36967142071615e8d4f792b39f9bea0c88990235d177322f7661597512b86949a1eb940c3fc0003646546cde88185c9035cbd328c8d3e2a90d18f9f15a9fe1381788592d631cc8a2cbfb0ad26f41b988e0f8a3b88bc9cbd1179d0781eb46e57ad4b1301efe66d3c797ea0eee2ecab5b5728e1081aa3fc06db8e2fe0f22ff24bcd0cbbba872c38f445d8910b634d4856a6ed95f9e36442706fb07e137ada1ac11528ca0d7244cba017e88f82e51a22f86a702a2802ecf5143bd9ff2a2ffc66ed80bfbef47b532ce7592c169ea0d49e55fafd6bd7a53fa2e25dfb0481f38d5014d035cfc0da872707ef3cf1bf991c9f2e8be4851d769d0ff7118c146e2847a508d09ed9fa41ef73c4adb0b6dc44237d7aad5b6e2a8a2aa7e8accdb6e448044dd0b06baea1eab5a78c03bcca522f24ae0f1c4ad2203ce8fb475bfe40bf6cb4415f92b6b6a21b4a62fafdad28618757747950e12c42c76017010c74e5dca3c21dde1a8694942e60ff85a259dcca7fb7ce2cd4540f5537b3002b9ec21952247c804984ea99a00ddf544b835e5f039997e7bff9795b5f9a4aa437321c6a4aefa0b9d061a0274955ba19221dde23c3387304d82dbd407df41d13fcc8353fb410fa156b2e58c3b259b151460a3e24f4a52fcb566c4a3c678704b05d2e2f1b57d05a327b1990ef00f2de65c59ae8ea5ebc1ae5df6e2a3a4d6ea8b90a31e439952cdd0d2f7ad1ed5d292ec56016af588e2426b3109876ef6e4de4b6ade01652856591107df824a5b68828bf39e2ef9ad544910b1ddcc8f33e502a991eb988e4517f21774b7816a763beb52f344be13f0dfe042cf148ead3683e96c476850f6cd4c5fc896a6f17d313e427167038949c968b279141cbb738d4bfce09e506a0a34423dd172bd649fc8552cc8281c915de1152ebd6695f2349384fa6ac94467c8deb96ed96bc3454c1c2871dc236728e90811f5d74b1f552c516c6dcd0e143b486cb6910360ecf99b391c66c62379929c215c4e34818e74a26764526ae3123505ffc86b4aba945dacde021cb41499c9e8a944af71a432f0eaa7086942e3e20486ee940575840ede582e8adaf6d8a26be5a152327922a95476b15ee95d3117721b684dfddabfb8d48e4fd259020e1156737d279bebe303ea0b120c7b15e91deae47c8a433a55e8975368dbe4eca06e4412de107c8ae91ceabf5158262c864b301b5b7ad3a4c7e8d38ad088e64db8c0ef4ee3c43547f3aae4bdd6cc68a43881033dc70208cf41e3c07f514e0d3613620a5b63450d868b92e896bea811d52f5401950fefe6f5a059c1a64e047cc2cf00939684e71de72db555b1944d4118cef35e8e308e945cd3306a63f6f240aaedfab1e45e2ee220ad7aab1ad6b337638d9f7105a6e89ce1e69e43c28b4842747df4c68c644ac42a05e6a0d2935a0ed65141f48a193497714ca7656b4a1df89b0a0a2ba4a27bc22e7e1842640c9b32e00b5c2cbf7f1afd4340e613ba4ac59548319c8a1bfba0beb546d9097d93b885434d8dc492c1d6ac0e6d7be8edfc2e4dc576628bd74db10f35056d5ee4ef62c1d7d9793d1e4bce966fb6fbf4d501ede69281fd0e892388b1fcefb935875e815c0830e1614f7888f95cc3abe3e8fd563720b69953a9e32ee113efd72bfa61155bee210cd4dddecb998eb2687a86c15ec47b6fda154ea88c7e2d5340c9776af147595f77d94a20fed7c9c0101d434c2b9a178bb7f1b2858d874823a15ff3809e32c3a52ec7944fd6a2e276286f4a1bf29e172dbea12c84e82193b264072dba696804dadada59d1e4986b22f05c95bd88110990dc6ec5ea09b1c7cd5db0bdc725869a4efa42d020553683a2bbc415c57669057fd391c74b9f0a92513c01bd4b40ddab8b9564139bb348db3afa59adc89f90c35a960706bfa0b75b407363993de2df042545c42221c2f0683178416ad4f86ed22316cb2c00b835468c0e36329770839ba100bf05f323d631cabbcfb65250e6af067f538960e9f114b0f5b5db41adc1c4ee7a665699f6d7aab5f207a0f840160ad4713dbfc90bada129a8d31985ebba6d6d222d946f34a6de02a8f1a4032106bf1e06142d458efbcb52842b6ad622e230ad1799763e2b9bb2586f00244e8dbb0cc17201430955b482f3f47489917f2389e711d8459befc52bdaf5db4e74014e60a3d89906dfa30e8c153d4ffb145c5f7d4e3c60603839a08e3d303355f0e2f24b032f41ca99c3debafe805271808bdd512a078e4060d3f681641ef04a61bbe92d723ee098292d9be479ade0957a10430087d056276826ba2eaaff6e7695488cbabd07d1108159d05a531523144139c71ba159ab7b0965e2e80efdd83dc6e6a6700ea83526c8e64986baa44f6d16b056e598d0351fd53e584e9a47553f5eb0857612b4c043eaa35774cae5740eedaf338ee688fd0717610b7ed8757c3c351dea861e313c400ba5a589a4378f58b25f01b34b1f140d86a03d1fb2f501ed6d9ab4eead03aba71fcb1f5d0f913bba776edf8e29511a5f1285227786802de4005b29aed83d671f5d786f3690906f03efd283b6544830c703b0fa79427289f8d46a117c14a0885c02cbf5442637d09ccdab447ad07107a0b00b11a1be30f7ba15a43b9d6f5db88611dd71de6f79cf95dd17c13e36ca0e790cebdcaf5b44bf5369a2b04e63cad4d2c5526027aa8c24ecf8629ec616bcd56befde8b31095de91a05b7798f8c2651690697c23e2c9b3733f06d702d5505ddfb1af5f859a208c22e926e6b30ba69dc4dd9831fabdfca1ff37e1ab6ccee6c06ac1f7c1f463c0d22fff9c86ee9a4030210e825c4b829a1bfcc60e8fb43b58ec10fd9158d7546c5e62b19dfc798d2cc54f089cb94f6db80d1ac360a53b41046b0c93cc635068db6fc1b7236e952fd638df64d008c9f7745afb2ee7634e4d614e4d2f494c89726a410a0793fb42fbe3e4b5b694d5720a271859753300aebc17488875ac11e18301777e758b89915043dde24ce2e5682f68731dbdb49db0b90fb49a5972fd75c726a23c8932a47da0f518faa88327e8cd9f602c4967ff4e24a4b3826b82702113d730048c112eb87e4e69bf04402eba68d5d67929aba2ea9788246883ad32df2015b7d351a9ed6be3007ab2fc7e89f58a9088ded987191c6f0de2e81537afe1fc9f415e08d1dfdf065a6083bf44906922e8daf360ed8ea72edcbf55d4e66fcbd9e69774d600946ae7717f8a8a1e22317ea5ef04ce094050a188318056045ca1d655c27a9a782e094f317fc655edf87a6e8ac0261ad194d7a56573b5b4a4ffc513df64ac6243e2ddbe699fd5568d87d6761919f66f02f1f809942e706aa6d27e1d83f791e2ab4401979d6810bcbfd297f635d042375ff1c4fc0cc39bfbce12ca8c5599c3710e9803ca1d0731a4b41c31e3d150323ba023872a2e13d9e0efc7a3cce501291686de39f138cf7be2ed71790d6b2a7db9b0603069f9efed5d815241b2c065b94ea720083424593b3bae9d06fb5b91e9adff23b59700be4cdbffdc2ce6b76455e892943fa7f69a3f0d9069c84c66e6a4a21aa04e7941a754cf6339fffbe4f2d4626d7e09e05c4046f32ff05ec8d963cbe2efde1a0bb740650b3b6d4362533dd22c92d5a7c1eac1127f2805ee9d574bd277e022e1a6708ac64a67cb028ac1d0e2f45bb2d18793e77612eeb07c1f07cf50fc66735ccfc1f31b6e5fc3bfcdd437e416fea917b2990b6edfb5e291b38d14bb58060a7dc4ab3088bd48b688f548e4e049b41f2be10f7fc40449689c5592b1c38cb33ed0f01b60b66a94af276010c48c5634201fe3d5f44f02871de745a07baa320031f869fc7c97cbc62399d446d537094e198efb05e2724281d4229df5d595e1b03f80fb13c478ca3ef4d6175286f3be3d59d17dd370c49d9ab87fc68a0cf503ead086935b20503ae21c0a33bb97958e0ff2a4b27582ae57fcac616b7a60469b78dff062ada3db28aab6a8dae204222cb12015a000044b81004aabdc959bb2d99ce70ae7cbd287f4756335ae8bbd7c5f7e6d408df675e57bb97665f7962949192c096e09be085f6454aa4442b164940c52789151a8b23e41ad0000f53852a80f9e8aa80fb08f8f4f9e419549ba3c632a53a64c9e9929ab2c45da4c9236e3206b2cc7cc939f7a102506493d989ac1f1549cc171fac142443ebd6ae6f4aad3a9ac516826c90aa53ccd9cc8a7e2899c8952a443c6a752250e9989529443c66e738ab4194556a01f4360fca89f79f02406997970269542d5ae904136bd4a846c7a95380455bbe28b6c2a31cd28b22ef1c084512815152d8cc8a557b572e955e21015152da8e492cd33a4cd27928536fd3b207f0c814ba0490c821fc4255c9aa919424c12592c952a7148cd106290c862129a4d486e882551fc241dbe4a1c6293058c12e4b03cd2a6db8c499b4da49136fd6d90a218a4f460292c85187c5508be0a9c00cde2ce0a0c415392ce2a5055c46691143f0c1f0c49a4528ea21ca4e4ef55a4ef55df5702a122f9c3e6237de253f113756841658b7cbf12c998efabc4213ab4a0a245be3687a4cd20d9fa41bae153f18603e8214b18d9bb259254f606d0431630b2e7953c68fe72d478d7f34022954a1c82803265cad84c226dfec8b14d7f1af2c710d8fe77edb524aa05152d8cc8ddabc2dc6941450b2ab94b8560f725e95c42f5f1f1f121d293bb328967ee55e2105aa64c993299bba4cd9507f964006ce011c0715647a0f53acd59c12c520729840aee4af0defbfe031f0c3f145f2c7dc9f426fcf8f4a7b396a84795503ff5a9f24c7dfd9e8cfa9e3cf33df87bb2e97b72e97bb2f83d39fc9e0c7e4f267dcff764ef7bf2775c5229f73fe1e4364d64490cc126d983fcbd27ba2362d56f7ef35717a3ac7e77bfd5b253e176a3e1bcaee3dee36ac29aae86f50e63b158b1988a0642b784689a78f005ae5ffdab14325e5c506532994c269389a132158a1c2972c449534a458edcdcc9fcd56a99e62d82824709620b336027859dd488964255bc30d4bda56b6deb4eb5769d27334eb4d3967659276c0a4eb4931934a77eb74c147f5561a7d357d8a9d64ee2e944f357cb6427da8976a29db6b495969d68a75a9b2528b00727b21e59598bdf61b3ab09bf4e7360949639abc35a79fe196398b2bdfb07047766fef43ba8175f25561a9ae7317dcdcf98489e2a3ba2f83ca63ffda57925a7524915252a2562a924f5a8a7f95a9a30f3a747616687e6c5e7517d0d0aa8174b9ed4d3a8fc3c924fee918c33640d4fb2fb20c8e84ddbdaa88ffa46ba8fb394e81a085abe28f795dcdff509bcb2c9b4d9d5566bb3fefcfcfcfc7441dd600fd863193988720ca9a6a884544194d5d7fb4a3f252ffdaa519ad52520934fbb56dc0523260aeacf926de6cf1297b344e4a4d5c42cfd90f1122dab8228abdfaa825441d50798fb555070d85442fe32bd0ccb737c55d0ab825cec6eaaa0eea60a520585a251ed218a316735aaabb92833c52191c814696117a2d947863432dcd266adcda39bbfba925305f90bab825447dd195eba20dec45b77530575b7ee28954aa54a5590aa890a48f5a30a52fddc58013e5541aaa0dcaa2055500ea2992ed93003da4c2693c964b256cb3431a6d5ece188872a2786d4ba8b6458aae1d7528b0bc5b75f1d67226c8e81bbbb049f55169379f5d2ae15cdb15f87a5cc1bc16e0a4e2b0026ebc9d126bb8ef7f54abd4407153fbde4087b2f26eb51155365f446899bcb82b4f4955b0859f0d9b17685df32d27f5d0d4551dce896f662c2a55a4ba552ada552496f4a9c10e93bc2ca904c8612e30b5c7393d09b0e50567f5d8206c705f11582f857279f032a608157dcd3f70374dcab04fa74f65c2984ded0e0804f7af39b0a1c12e3388ee3381b67e3074f70f5d1514173684e052201e6a139de01235b4d006670dc78c3f6c5ec596b3da802753319102d163b629665c6bd10e3a1b503f5d1e2688e2de15322d76f551f3caab77e88d026bd397de43e798419a441a842d185ccccc1d4c867bdd523ce4601bab7bb76adb58ad0ad560d9f75564ba84978c9b6d6c546da366d4fe6c89e8c2d0966f287eefeb67d25d7d90d15e0b3ce663353173114c3dfc161f862c9139ec2c7f8bba413fe2e297cb1f426d39742532914c5c0a24e2896a1f7ddef923c04ad05ad0581c219c4605c8467a7b7d6e258acd2a016b50bb9eb19b96b98d10b5ab96811ffac4a9cf504f50a9e5981f1ec887e1d59cd9c158c95fa04969a654b77a9a4596c964f259ee1af3cab90a9ec2c9058964660e971a177c309ec660ed2237c39722d4f7724a6f590d4236aacca84c02a1c6993ce14e00021432803a8bb3bea1d86ba9d1acbc2d0f8a88e4a267b54f357a9b447b5aed6ce1ed19c52ae5d1da8f8fd9e8ce6749f43fa7ecf0634c7a85df50911a31199c90da88745f594a0af5b03d08561cc2806fea2cab8b827c057a8572406ccab64fab3f36206a63fbb306a34e772a13939f09ed01c2b04a55f1eebc6d0973deab8a8a3958e32ea806ba0d683e17e81c5a836c8fdf6c85f15e8e8681c6bf698bfaa2c16eb237f551aedc86947652c08e4af7b812ed005fa482499bf4c992933651ecdd5be3da2d41d0798e3ba3fed51d791351fa94caa8c44aaa417f3a307253c194d0649da714d3c668f4adc4fd78eb81cd431943a0cd46ba8e5e99db55d67f1117f79cc63376e74ad878086866ab29aece8e8c81e5531a167037ad32f9253f09b4c5f32fdcf85e1d7c1bb81afc0889108fc24766b18ba300c8d19ca5a484f466f3c2c2acb5382b2fac518bfc8ed71512b1aafe0131c75603a23172a3da8f3a0720512e8fd065098a95da47710247d2417037ad33d682a35ec9220ed6aa92d4dc165a97b13e9b0eb2fae0bcaaa6fc64846185098fee2525059fee27ea0acfa5b8c5738c70226c62ab94ac9f56b351a9f37c1ccda1a34bcef0e70ffbf6a6bb5ffb4d9bd248ee370a0a0356bbf8b73e27c97f460188258daaca140fa815e771b7a9ea5d6526bfdab8305e8af3f12c791ace538ceafd7713623a4d875f9c537dc51da0dc58bb517d35910ee9de4826d693e8786cb3ce6b7dbed76bbddb2dc6eb7dbadde6e5f687a9df68008d7dc61b94fd4eeb6440041b044f31dcab5964a2408964a6009044b206845131aa6ba0f964aa552a9e4485219fcfbb795c127816f6b8900826089e4400bf974aac105f6c7a0bb1884045cc224ce0f20428814d9998091365168d3853e68041aca270eade278c1dfa612486a271dd42eef1f556f94d59f2acf8b2a716e38b3276e57caa0e5b3de54333333332ad53b4cc50d6153490c8f905969f309222cb79bcb505d438a98f66eeaa3973855748ef36c1d17db2e0f7fff0c7317be78ff4924cddf7be73ef3978579ef3412a9ef733da4de3f9249df91e798eb02baffbad346eede59f54f645b6957f7deb7f79e0522f5dcfe11dc10a2c0c11039b8f0420d5a10848b0d9a98d5b47831668c1fd21839fc0f37c612a029d35998322b5bc16bcbfea12fcdf1ca025c6b12d5396ef6841da10eb141a88cc1e4761a9c77475c0428a6a37d373790a921288cad0a0e14b0e9f002181e8480ca8091c10466041fc8c00315361f6663b6b8d560a6050b846e18411a6088c014fde062f85246f7654c080605a118060f5f6c75810f9c227c491826a0210756b49800003784e912c41819a858e20b111e951b8e89031142c404bb7858388ee3b896b3a8b5d6ba7b128ef31a61e0fad75ef29d45df23a95b6b6d795a2644448810f1ae73794f7fa75d1f480a2f0ea59c0e1021edfa4468d9161501a7cd9619387ccae29e4452ca3acdcc3de58ae06c7f1c899c3e45d2a2e6f998f6ffdd39bee842c755ebb5062048698ea5f45e7b693efdb992d66cbbdaea2b6802e47cb439d9da2497c1ca95baa4f4c63a977b6cad4adc2f407057c6f89d41c108680a70708cba285090c617194a548cbc3cf922831518b0dce04f680813c40f656420324157031b6e094e1156bc8a47abc029228a2f3b7c1dfb4a557c28d1fdc10a14a441060e88e04107d839669c2b26e0220a2f8ab818324107c50e0e069c22c6fad58ae314d1312e0a31aa78465c0fa735f67f1137d3591820ae0aecfbdb3249674a9b3a75eaee3bdc881021d22e2241ec1321d2aefaf48bf40bf4befb1e87ea0011428282b9df3285442233d0ac364203ec5f3f7be945e3c5788aa9338e18bf91b76da77c3e5830b097e92c8c0ee338030d9d83898d304b98e460528e69e4ae3efda976d91c4cec770c97510a239fb6a802d21c16d31b0fdba45d378ed45a6e013709c7d9f6527d683ad4ab91829ba3cbfab7bd681581693ec7eb759c1d6d3e73e4c6a158c2c827a54699de6e57728391fb7f2644eed799e59eddb4e4fedb3ee35733d3d9ad873c93e9ec26c3c885add5b9222e32575ab2946da53acdd91950968f048662199ae6ff385631de0d3f929172045b2d92697eff771c89c0def48acf1442301d33809d2d9c1218a3e64a2f4bb792d18e11e05f552b67a42183d52572704557f1440c9f2523237f1521cbc0253063705519a98cfc555219a98c4a462a236d1e71561ad88bf8ab64e4acfe92110a25a336bb488a283949e70ee09c04e7faef053e62c428f7ef8801d72f024385fd54a94fc9b820c5110cb016198023d792d61ef64b3810a586ba4942281bcdd1919b83e2a43ee7a45df6392123703eb9a01a943b2888c88bc8b0d56280bbffe7869e1ba239ca3cf7231444e977b64e4e8846fadcdd3defa315e9ac80d44a0eb0c4964c21e34662037c42b8c13e18fe02054d2c985a8594e20e4fcd108cf45f493180e96c0c992250c688c9fd44fa8bb1f3aa69050b6433cf1342cac10dbe4f4c0748606b726210cfa779b3741c59612472b5f3f15429594c1982f17ca5d742280290bc4102180f49469b00fe9f27eba00a969d5c6d363b41c8093acef2824faee6d19c5b8537cb523b9fa614b87abf8237cb3bb257eab4494ef9de268165edf2f181f57bb1761dd107f879d8577a593ab20b2c44a7cd1d3b64f168de8c12e91011dd98c2753ea1f00a15e0f36b6c80ed90ebe3936b75f788aa16d40c6a0624f379adb5d6e20097f9bc3da2a0401439431ab12d00bfa5b431de52a3b529fe5969268cf1e313c6278c319ec133a66e899197d213f14d2273e8844d367ad36f13e4af5369ba265b68830b5e8dd0652f4f4ef24c3e4db6b6d904511780e045ee07c146733ac0b125f7e3b8623374c388e60c7540441295371c44386638b2b46b8524378bdf8f83d62e0f0796324cbe92cf0eaee4be41039b13e47e9b1ee8eb944365f5fb20c4690812904076c2c1460cf069b2e50e7aa0ae9493ee2088e6809fe2819afd67075072eac96933a339dfdb08a239a4b70922d190fbad8ce670dfd9da55f2622492537e2eec248a24a2d203c0097cfa876ff2de392fb9e712a81752c8903d2f91908886502fa488217b7f4f5db8ad76d1c96ca716602f2d68b2996ce1835e78226db3daf348445dd013900f36b1769d27209b281f42e9039c826c844e40e129e5a45da69f3679a02e530dd4ec6f130ea927a69418f904d443f6def463aa810bfef269b281a477a3c884838d1e6c41f4a68c4d904d50f79537da7f859afb46fe4a2bf39c6b42a2e1e45ec025370cb50c0c979c8fb3b82649e415ea0b32bde14a2bbb31c3a74d50b509ca6d1364136412957a060d1410ea87d29617198ff8e8236da48d3c03c0a14b1a309e1606908213c0c26f811a91710556a58ea3d38cc058239a6365f5e7c7e8c7e8c7c8e8279c895fe2380e3c724da8b0f02f797325e2bc2781e0832f921d9619c27df72470df77a4e748523794c50afaea6c308a19c58c624631a3119ad09b36726b6d1806b9911ba180442c543e47b55aade6af71ac8db5b156ab8d5f3e47319f23b5d15c973673705cb8dae85dd09bfe2edcd6aed3bbc8fdeec56d160d3f7277f72e6e38d29cd2d94337bad4bad4aa8f9450abfbf1ef460d9f5cad5d14e48cba25adf287b3d58e70cd6778e083593d647f8aecc0c168338ef466269ff6a7b333d017c7a5f6c3d56a6d04bde9aa09f40592280c72d32e7ebc546f123e8904492118ae06724041f84fabb632017cd29f0096a4f2841f0373b55a773def7a9ee77924aec6d5543ea81c665dd7654121f6240af4c61f4441003ad4cabd83a9b51a75ee2507a08ca159bbba775b9bb9b3d22e8e2bbbe43e42d63dd12eeab536bbfd766b9343a1fa681f2a5554714b8051d04991fb4724eec5789c9dcae0b38b5d2221bfed781eefb776519b6bfc18029f7e4bc27d4bbb66ef59da455a55afb9cdc1b48b8e1d676d32b5628a1264ae93b5d91d5145f779b626532b562094391edf3a7ec79f2e63fde94440a3100eba9efa0f1ef51f3c8e273f657a54e967c43f858fc13791bef4bd783f7c90f45f3dca3783aaaf06c7d5d431f4e0863d1a914ceeb71dc7d5ca55ebd584a732d8967e6443abcdcd4dc9d302cc6f9ded7b60a00e9245ea2857f56f5825eb75fc0eeb757c7d1d3afea6e4d151763256d90363911446c52045ba580d14d8b9c028cc69331d248505c0087cfa2d6685dfa81f75e69f75f6c19f9586e3cf5a236badb73663fe627dfddad5d8af6ff2b0f9faa35d35beafabaf4fa4daf80a7ebdf1f533700449bb3af8fa2a2461a15d1e7c7d9ed29276fd4f937699be964e309476e5108a02802366acb40b84a1ca72b33c3bd907258e922ccf6e660442ea713cf9208d18847c904c91a90f4c3248112cd267547bf8fb93d020c1307e63302adbb2ff05999080b4b83fd5070907da83069a43d281def83b500866e0f303cafe9fcd5ff7623c8ef5b3657ffffea26691bfd057ed4259b6eaa36af9964187415ddcd360f4d2b67c62027fc7d1ea96366b8d6c9828f4c9a08d46fffa27ce9e422d5338cca920f645223dd96b7daf61bb2c13600860e07efb379ee0ae7f8307dc7fd625670f19c1da28ebb44eb773a9b7131fb4272670a5d19c2dedbab524a29452fa558b4802f7ab213605abd34db3421ee4418f717243a94ec8d20d6a1a51f5d1596a8f7eefa1d4ae4b534ca692fb69217f71b28f09651c24d4259ff688dc312b94a5fab0425822f2d959727f075870fdd30ac1a848a447241b4645126ce6002dd37164d8e60c0d905aa7b43bd5ddddab12b8dc4f57c85d6d0d50792613d129703ecaeaa753dc7b517ea2207dd92fdff5272a5b9cff1c6c2aa5ee8d1e70bdfd4345ddfab7db82f1f90c072468822447c66d26c089ed6b8980f383c8095883f20297c61333a06030d3d91330a0134f649083275b5c2a3097e9ec8996d9adeb3ece7aeb001142a42fa6c974268418d9661180673dfd3fb0de367380c0e7e546a8b4ab535baae514fb0eb3e5aa04faf56b7976a6a5b582ed0a3623a9b4ec3c6081c5ed2e024b3de0fab67a7d166191d11b6b33ed8a28a5f62bf704005ab470eed5ba5b263817707db75e2d13b87ebbdb2ab34c709472d6bbd28e0a4873544b3baff3bc2c5d9656b5defdbaee8ad9c72531c42a81c1aebb62067249743decb78762d75d3113bb9691b806cab7be675abe19f44226b0ff0dafbfb8ae23cd27715ade8923ecc8f67e24cec60886b4fab0365bad091c8c2b8dc882385006438721246147aea511247010afb4ec5e33a560747d19a917a82faed471d53fa918210cd587d7fded2b010d94d9988dfddb180d4dc9534e212383b5e04c24d1c40ed9988dd99825b23299ec88d43d087a1e27725fbff63e7ceb854a6a3ccf6a8766fcd5fb9b346f435f76867bc32a92e09567a5c97878a8a08981d578507634aea8d880a621573b347fe36f943c379ee606e906b9eae046b922916abe060744a7078740d96763fe02819ce57f2f908d81402010080402d918492c039fa0ec03037f436f65a9f79a57a964fefa88401928eb14ea23fa883ea2f323ca5e43da7c8a44aa212d2c45aa211d4622f5cf083b32a9f4686a901118620b169847d23c7392c56c50f6b719a77ce418924868480a1b493a92ab223523d923596160a57987d1943c2dc068ded2d4d0d08cefb0b1864626a37d3da856c588848484848484849c95e5b7c0f6753c7c9d6efbe1cf586997f7357fefc5781cb9b26c599e994f796984fef053686f40c3505fc3a3aa51d5d4d46a7e7c95ea6d54634d1916a437b4b6dbd27d4f484848484848280c49081fcf000bd11c6ca44a91ab9d544a8552a9bea6f4da0a7cd5d73c8a5ced8c8ffa1155aec0af01518f5209c94c0fc6dab542929b4fef0f0af90bf57d27527c14e8e303920dfab8d392d35209f44191347f024ba0859d4014e930106cb0e344d5e333a4499d600f2f4c752792da2a154aa5fa19d4cc0c6a464888c8d4a30d409ae3ac21642db516f471965b1f7f35cc6dbee66b4a9e9ab729794a40348102d682cfd0c40eb02af67b60270894fd5b2d1baf5ee2dee75e8cc7f11ff4b1b6497fb00b4db44cfa12e883f10cb0cd8ce6d015647fd087e69cb2631ca32c7ffc949e9ed2d338fe679a3b35abaff91e980db9dab1f9f1c792677c9bef81812bd26ba4dbc01aaec8d58e8d5fbd8dd26b2bef576fe34772b573e3c7bf51bacd59fe63b9f2de46697d9ce56f7f9ce55e6942c3c61fcb55e947a02dc32fe88381dad52b24b9197c7fd0c75fe3c3b8237ff9bd7eba2aa7fea33deafbcd552a8c6bbc69242d0c243d70b3473acc23c5b7b1fea965ffd13f376c910335ab7e0bdcafe31eb9814acb670bb29c02e94bdfe4596919fcb305592eedc8de9f3fb20d49612a92e6147982b9a2c8156c3ec37c82a41bb142ad61425269d9be484e193f24572081da3ce8e18f7f630cf6421b92c2ba1aab05956c411bb2611fe981249eef129f6cd3a10d69611f796bde6135254f0bb09ad7691bd261d4f3c6afac212dec2b6bc8865d9b77984dc9d3026c2c1d06faf8b4cbbb8650aa69a600ab124b28b1020b408ae9749a799f29ff95f4180116bfe52cf1c517d2ae8b31922319fc9344a6d0fdf7dd831d0982a4f2d371f169eec4b2a1b4496ad3fb9f80bf4b25fdf8bd545245094d0090c0dffbe77f82f73bd8e4eafbfa77fcfbbfef92a7cad77e3b772f4ddd5393e969cad5f718f7b7dae9a7214ddf247e2751ddafe4bb08a505d17a9d56bfbf922e8da8406d5e5267894fbf076d78abc77c4bf61c8c57eb25751ef323b8aeeb3ab11cf2955d596489e971f820899fc24cfea63fa11f974af0f79bca7e2534ef3f6bd3fb12d9596e7dd4ad3ad39f80fa4795279894e037950fab1d0db9eabaaedc493daae4c19f7a1e1a0aabdc9b3e02f653afd34e2a5bfe4a954adc9fa65c75dffd7845b3dac16f22fd31d96f225124751efc4a6a5e49aaac3ecef21efff834e5a73e88b1ac403e4f6a4a5c7aaab29554d9c16f7a254a705989fcac4241d0781ecae4910da54def4d640f39cbfbee2b895ae1e3e3e3e38215cade5332d9b39d6148640330f98aa1e53387e7c14eeb93bdafa4eef4287d24e463e5070ad02c68c8a3b46b556d6d7a69311ed7a46fa72fa9219fde8486be656f867c3a94ec793ea32cefef387a5dd73d0936773df3973784df7bd0c611de770d7cefdbd65eda4456186d17e83d8849b08a45681eace22a02a6c7a8efca1dd3e392a7c24ca8c7a4e96fcef2bc46dab2e73367792f420c9b1e3fcdab1e857a9adf413d8df75d598d9ce53daaec1f67799f2a4f9f19b907f3fc4dbfe36f2a573bfdb85c75a6dfc16f323d2e77508f5165eb6272f53dea7b602672f5e1df313dfeef71c953e52b77f0a3bac7cf63fa1ed8e9f37e158aef64da75f6ed23536d86df6a8bf7dea55d367f2d11b3c81e18effde662bcf723ebe3af0af33e14bfa6a2862cd9fbfebeefbb25f82692c270bbc22c4efb9ed4d33de94cd21d79f6e42e05f069eec852fc8e3c710b99f4a7a5a4f20403fe320095288208220ca3255e78132b248081133508511b0373772e87a226d9dddddd2d17b4052f7801d5229f3c8470011745432841440d447051148509292d2b95473e534232e4c6a248888b104604e951871660ba30a9f2023266e86162cb1442d8ae3831e30b8703172cc27a2a402d081c647f3c060144f6372bc5e92472d384c8a6dcdddd3469609a436df5bf188819003194fdaf18c4c7336ae035c18296f2030fb9ff1679b9c5a00c229c4842043698f1c30db2386a414c09583fe5807e48422ccdb10e258bec5060f0e48cbf6d858ccd8230729f727777e3581c3a13f2c4bf1ad1200cf269c3071e6e7cc0e2430bcc34405312b4562055680d2474b8d806294420b30108292c30b2a1490e7ee39adca0870e3285906d62d3a1d682cc6cb8c9143d0461c10f6d0c192d1840a63332b60851062dfc604cdf10c6bd95c9ec894bafbd5cf4e0e1a3499108c0b861071bb4742bdb1c6a7db3f3148a52da6754dae2a83b7e1d8b4d2233652f11111125f230345de0fa1d2e5328ea56c5cad47ab5d6ed69adb596e338ae6ba71cd7d1b28201a8a26556f7724c65fb1cb6d65a6b2dad443905fab4e46814998a2f689142924a2149dd1bc36c069862fb463ab184ff2e1718604ab10ad6da54b648b2fd94739dbd626de765c98bf3834c5f455f98fb4e94e202506aa3cfa22f1d1d7a9305c65dc782402a7b1e47a7d0a109a02ff0c1b2c6681528a8319a8344ee0bd4578d552af55583685de20aa554508a05ad415f707daf134b20b3579a43a23a35e6e30b7075afe4b06842c3462e5437b27d09948073f735c6597f557618a5020b2eae7c912d103a4d710548fab5288676c9c05ea6453454c9e78d626f160e8d99775b4f00d98b6f88c70475ad2b6be26486c89c170b01011943930108080819a3188e8280a001a425065768c1ddaceb82c34c67529eb84e48598226a50a0899ceaa88a20cef76ebeed6dddd6d8e3581663d380277efd9adab70a44da33a037de17cf988bfc6ebfed4b648c25dd98ee4ec77b633d2007dddf7770fa3017ae38fe3af5b9e95e5fe9d9f71d2298ebc15d8fa9f3b96f8b9d75a6b74a4ab4246968a5044c394dc37e4fe2b3ec164a657c218e5d3e68a83e3c457a10e055db2bff5287586235ad96da9faa9ecb48bdc41f62219d0c8fe4394fde78cbfd7fde949b3d0d10a2c5cb8ec2f64a75f16e6eeee14763305bd360c67b98e8507c5841d0b98e3bae7bed29705288b7bcec671dc8337bcdd57accffd68937b8efb191a3ee951500f412e080a1a476ed5559104ef57ddd72972c5923b285d15e2e8d107e8eb7bee59a039fddd9f98ba90b96ff203f4867b21fefa4a10d4fa42e6decbae3ca90b58a037dc631560afbcd4e4b8f7efba7b31eeba7751acf7d61fefe5388eab32db601324213029d3a2186af0518167322d8aa10bd704fe322d8a210b8f09c69916c5208517e3e3323ed4e02101060931488cf7e92df342bef753edeabfff34a7cbb73c91e430f1fdf386b7c44a7869160573c5348b2a41a659b4ff96039012048911039024645c00015962a6650619ad8a188054b1b5d220aae13a012283d22c9acf8b4938688621c668513184171b99ce8628734d400aa165b676b0ccec62031ce65f4910b2b5254f08605e3617d75adbb296479b66ff0f7a43bfd5f686b0025c9fdaca711ced4afbdcbd18734ebf922704303105b5dd729d77ef77edad1f09ec606ddafbdd7beff540230e46dff416ce8f4b5f46c42070f570dc70bb7bafcdc6dd7bef6d97ff2dbbd288b3b0e0fa46dab446aa8edb8cd86cb60bb30dd2607477e79c72eeeeee9d53af2b4b5aea68e0bc7b45606dc7536d57bb1304d9be735de7e58fa16fe97bcec201045293337120bb474dee1bec40f6daedf2a80976c0a9c93df53ed0aec46b575b826c8bb8186c8bf80b5bdb4118b86953dad4bd833070cd20c725b9997bfb780630fb289868b8e52cfbb50ceb2df2f543f8824d37d3519bab13c0d26cf9ab05abd682ab2129ac86dc5c6ee064218b257cf99629ac86a450ff2b7fdc52a74dfb344f6087ded80749234d00fb1c04e88dfd07d01eb6489bf6bb750481fd17e05f4b1c93e9af222d8ba44d6b3a32dd7634814fd32d5bda7577dd5c37d7d692213866b4668c7e6dd22fb359d5745285bca7c1cdf1a2349c175c1f1c5dd235218a209ff5a64a192fcc606082c30860fd1a6b781e9541be25c89ec7c48aecc5d0c4a341039fe6add86180cf9b6b98bb54ee9e86c9dddbae088659ee9640c9dd783367b770418ea36c8b5cb822dba217a4644b026bda8e656fe85e9a189f308420308f221f191a8d22236badad3dcad4b20f2bf869819414d8400614d8d9cad6bee9af1a60c698228b1dd5600798add91762ad0dd95e914512d986d95a6b6d8943f8824fd3acb332520690bb2f5e01115ed555a594e2115fcae351224584507a34c3639b674fbe658f25d423b5a8e7512f883c126d89803394fb7f504ae90a63dc5406b625b53f0a163f21d6893496e4137cdff77161aa4dea79a510b2452271c2558d26e19b4aef11f9783e8431f089851469f37b30c1dedf9ff1f8b0d0a6589e3d99fe19e610482934e1b459fab075a44d138bd1482344ec3ed448d620213327fca017e630fca73ea82bfc4e0c120ae9193c73c2b585858a4144a8a909e1cbac45e2b4a9fa7e16bcc334249076d17cea5134aa31639a2aab1314256a53062c1c75b3b21b427afaab9d1a5fc5fb1adf035b91ab22366f53f25498cdf7c0c4b72159a83eceea2791f5a736a941154a9b9dc5b23a216926913be02225f511b832a444355d4304d21c5d582bede23336d18c4c1730d4df86cfd0e892bdbb9bbae877a6648a94c1e85d6494bb3cb1181f1e44b89f0714f8c42bd84c7d6aed6e5e3d842ff8c446c823a82ff8cdcaa35d94479b3928ae7f6fa53b6dd623a591366bef68029f61bdf90bb8a06cbf921df7fddd9fcd9529f45bec858e777b18527b91b451ee9e025a8a23c3a976d970ac9d6ad76d93fe6943897bb971bcb7b4e5890400b4f1b3a8adeca5bbfb58dfebfe035ed779b7abf92d0c30674b7707000dbb3b67b91c9e839adfbdb3ebbcf2b4d97bb7ded18ec4d65a29ee7d106bddfdcbdc7f524a3ec4b0c12406940f8730a21438a4e1c3859f2c409c22ae8f3c3b830638d3d9195cf297e9ec0c1a1018f61391dab2964c604a733fa263a5bd1ff9ab6dceaa7f2faea4579abfbc095c7d7033f7f1d77da782deb8fb64e7aaa821fb73b3eae3fed41e1c1534e7d2406f1a8a7c92b82a3e9bcd5fdf171aa435a874edb645350bd5d0000000000003150020200c0c07042291502c1e69a2327e14800d7288487862369508a324c7611c858c2186204200010022023443b4158000ff69ec42ea38e690d2e044c09771405c4011f467ed583ea67afc5fa7aa6a316d5e9a1dd56cd1aaf1b3b609c825222205545447574be311a73f31bf4e05ee1657d85b386e41d3b00a23636a44e6fa2fa039e24c2673125ed7ad7d328de929c17bf295c09db757a2c79890e41428a6cd0e52ad43fa216b9a7394e7fbc2141f24640485ae806dcfb7fce7dcbe09a6e9aa59dbae52cc931de88dccb269f13d01ef387ca403d31fb643977960438bb517b61feb53340b00f295eb3270fa18d33f8f11c64bc4116767d750087301e98db1ac6d4633382414a2e84a7ee348e089908e6df2383bcbb9c33a6bc4070fefaf2948a7a1672139446e54003ddc2a5340b367ea09c2438a2ca20864c9209b7dbc8bb85e27cfa99e25c8d0abc6fab5b55a0743941122444c6a1bdf349a0e938a5765af780914ce2c5db8025232b71ffd1dd0ac775632fade2dd55129549b129d026ab5c6041005acfd090d752c24c4d56da5cadc13810436fd834c8ab93b6f2e8fb14283b98b729023410deeb901c023b03e3cf9a4d846dbf9c55a4af984d842893a492bada78daa4c294c9b67788d3f9dce807d24c5c6fedcdc8bd1e21e39ee404dff10742c2ff1d630ed625d27da535565cc0001a4b0245f44677d574163e562e150e7be59943cb302e07fa2a4efc54b8db53cf6986a850df30e37335b3b657c2835b3967f2060ce1e25106aa521541cc3814b188050b986806363df1fc5ea20c51005a52a31596b730f98c0cc1e4aed5bf2e5b19bdd87016826f32e56186320193535609acce401d97f64ad000b3d25ddb2c82d22d70d43be22e183e2069e2011ffb7b220b94ecffddffd19bfa5f8a595cf2b128dffd313b9ff8f9fda799f172012ce14c7ba6d8a33a9a53dc88c8cd69631ebe23c0e289667bb6070e32307e2a9f6165a6751101d7de9676ad68bfcc572445e5cab4bb37dadd63dec892e3f114406ca6b2a9f4b423fbdd351a0ce42edbfbc3ce3a9adf66800270fed0445f8babe092448b4f7a46b00ceffed2de727ddaf9732bed5c63783366e6a6a5494c8519ffffdc87f4a8449193576bafc52a71d86d5abe30bf100c92117248556d63145b8d5606f17164d1b51f00073c414f4ea151d206cf3deb5fc57af2febb8d4a6caf2a2d224b3413b3bdcb27fc7eb62c8eb14fb547925a9a305b0a70ca1a4c004949a5fb2b93e9114b0f5fe9230420d0da71822cddb48a10c7bd5490fdcf66197f1e71a92d95ca267b8d7cf209351a1bb251b13ef1772192e602e8859f2d594776d2ada51aa784aa86454f6d688c2cdf80858cb1429d03f947dee07d4b5f59c59fe29e56f1467dbee3ab96c25e23ced021b0de1fda24ee8ef1b2de94bfc0fbbd6461903d36538236cdc14000c2f26a98ba5c5af2859717a020ef114d0d276f682053e452d11e68f8890db8ee607b28e8f94c1acab0f75f60373db21c1f36e191403025709c3106d4895a84cad8104af3a155f9d706d422c4ae91ff3fe2c37826878154d8b4fd5d9302f2668b5567bfac5ca3d5c88e0e4109622df3e4d3c9a0a527e995df45fe1725ce2776c77061b08ed11865d1c0680ba9fe36aabbed77db764b8e5fa8d7315e309d8fb99ad48a646cf68f7822087d8bb2919f1f2c707c983fd950a3db7575083fe0485b6ecd21dd4187a2ae394495c4119eb16264c4d86c1b4dfecbfe986b90b895666ff65538547438c6717f49f2a4c0a4c2ac2dec675edd4e592905a79177534d32d35b72dd221944152a7f80558b11c81ea1cdac0a7ae513d3f74d684a1ce39dd8cb698f31e100944dd5064a6eba3a0073bef4c5bd733b535d0728b0767516119182573500615c1a1edb611f9fe0b9f77b7d1b058cd86065adc7d904e2306cd7f29e69298d9c17fb0919cd3ddee4c10d8cc452f35a3c2fdcc93b02806f1fb0e5702b1448d5357b7f18d661be55ec4d9e098d10f10c5abfa02558e33f1dbdd0b8b4243bb285b1b8cd0da321b830056c96d86acda626f4b1b5e6cf417d834ddf84eeb07a7ce8f3bc7d4ca8a521174b7f469853886bc0269ad1e9e6b7a9205501e2a970299570d37c8c19f382dd533e0893315a9bc122b577af75c500518a95cc0e10611ee09ba2ee657e62b91fbcc5bdffea348643f56e2e00585416c3fc14b24e2ec4056e16d594b64fd36477a739570b9af84188cdad176cf5954d99df8ce22655517811f19870af839cac8680086e78e14b42b4d3c0d1347882a8f1fd3cb1dda5638a0c6b7c10a2b7b1db9af30954bb1e703ae0393c866819f6ed5d1f073013e24cd6ef68cea42235bba7cb4d2869d143495deeffda556f56e58a2d8a9f96d377ea575e90d9e582b3ac035e900d63c0e6c5aa538923641f330e476e26eda339b25b7861d3fe9e15d5d550cadc8625c7d60f60fdad6f962a5a1bb139777fe9e17ad9f64a11d9a1295f10f96474363a6b417633594346085b1e56fc4e8c50f84af55cd9b7d78d5848381f8c1861d31c22558d34434c666a505bdf6eba7ba1daaa781b138de498846def6954ed57575da3594d2131bff6ff25407d2f2c75d02467646ba67d0f622bf9d8c13ede1d387aadcc225b8200a7c8b80c77ae784a030721c232a56cab4f3796dfb5e7be40b344cfcf77ff735a493bf9610a4f02b2e72b882a3bccf3cb8fd1deea961fa2783ad4c4033647447136359ab8506b76c31b86b41de7def0ca5bc15a40750a646af86bf82425c51b8de8614bec8d28f4bee9a9b9ed306449808080a3d22209054ab0123a4a344a9da581045c4c84b6130f87d8dba953dc3c7ba09697fb57d1ee37d9072b317be1ef93e7c085363c9f90dad90eed6ad46a7177a90d98d7b83ff02cb90ca00120bb51add79068df553e1f0315a4562ea346ca6b5532f14363d973e0a67819cd0076c825c6b38766a22f300f1245bb937c8fcc3debf446a8e02483b65238f46b081db06d6840dd2e282a1c16d64b83f9840e76a46889c3611b1c02c8548da19626004028ac71bcb6e43e12fc7ef9906eccd893db8e1b8b9d12fc436ecfc510ae210197c999aa0af378fa1108e19c00d6c8fe75110266df619eb5644ac6526a1b82a65d3348108814c2d6c1392779910bd893d9ec69e4d5a5a2ecb782f03f5ce61e26c3304577712087c04c55dc96274f559ae44225a8c29b883cba51ad89d772f1b4112d3cbe9e105b631091bc348b8e8ebb73af926d0ec9594742ddca5ff880c99a233363787fc47edc6a2166c8b2e42cd8794937587b244835ce74f1e0a0be443a993ef5e141162bc940a9df9f26e0d464f06bf7dac2ed6e0dc05867808851a76ef34156e6698b57f7b2fadfc530e3656edbeea5dcb23a6508b22b2c1f2b080462266d97d34b8db4c4888b4685f53349a61ef52a6532dcdaeff5a11fc9f944dd0c9cf6a7d32765268f5db28ec8260c50c83e22aa99a166c1c3a1b7bc328aa743292514b6e59764ad34059ce1ede5e48b96f7c4d5d1923508adf26b0cc644a8f65be79b19fe066eb3c885f0c096aa701045f0ebd61df89f6821f2fb702843a050ca340270559fd68f36eb43fc44baa710e50418138a54d425668d920bccfe21e39536b3714a91c4ef305c4ee4c7926549bd1f428fd0a81617a86b732108b5734f9cc28fa7c9e2032ef9df117440d0974f851d041e6e9a22a16488abbf539f35bbcd8dbfbcfb20da08a1929938aaf7621addbb4a96ea0c538db69f87d0ccf4e12cf82f70666bb0566ed5c07726881ad405526622300131f35844e3e0d71cac580fac08779f7918cbdd6da2a1bca94c9220850b664e0e5f4bb48a124c073e2e91e00a6a3f8e100713950068741aa19651729943cf6adc62880303175a34a913738902f9557370695395294b2b90f628ecfc0002015a58caacf15b9b2ce6f50ede942a31e851d134026e5a883c4aff869d348520345a8904a5b22aea98153bba8a0a2f2c964f38c534d784d17620467fde8e362913104424eb3cc5bc7db85639470812af75edf2201f6290370860a2a80699606147c3baa4842a21e39f9417bc4445836037bffc586f5153f252e677a57843a2004effff05083ee0dfb49550d225d8f029899408ae646760386a603ca19cbbc99872337d001b9c58f4f5708badd91531e90c84506eccf1ee110b8b4642e91d1e9707cc8793c6e310195c02905350827527a785f36bc06c55a9f3e8f6334302b5275aad8825f4499ae0537ab0a8934eea96d4cf8fdd7ea79d0fb4186dbb55d1ef97d9272a346a747b94f8edcacedf3e866a25659b48b9716403b65c2b93659bff9d83677dd02d0ac0615ad994d37b0f42dc752c7b0e20be92e6db1e047f9e10f56537421c10b1e3e98b809b47e440656fc24d18aa6a40d17738521c87fb02a960c6bc0acf591797177d5104e84efb772b8cc5cda0f356ef36d4a02fbe9ebbba7239fbb0916a2f9a783c672f4aacd1fa0058b55d470d5e040d48487f4ec1a156ded5005aaab19b052bd9a46c89a8ddfce283c35ac420339e55befa94eaba9676f1d897f590f0e5fbb67e1cdb602845576591caed6a0147a0aee9c77c199414e73e12b79abd43d568aefbd604d163285a1b41988ba5dc7d36e1e2346c053498df515bc4e425a3a0ffb776c42ca917f7565c44ba1aed8440eeae84bab8a68285144f809572bf58aac2484c141c5484221b32581dad414dac0a9d371f6cb4dc61df8a0400497c1f35e48ad725b8c69a9859834e7866140b93d9c84cdf5c4aca2a2d2d831919947f3ec53dca6380da4857e290eb8b6dcd1c53fdba060995507fd92aaa8a8452a1effcdfc31e0e62ca562de7036882c8c24af3692360a0dee869be8a2f8389cda3db718491b8bc31e94a25f56db738cd0be367dde84a0c6c54fb8e6fb2f9ed81f270855d468660fa97a2990d780f568a3acb3fb1b91338e6db515e082892414c818e9a089cd5efb84c94b837ea78174d23fe59a1b749182a2f4ff2753db2a1a56bb25815b3534918ffb9a0c272db77f7db8e94bca4f4105f55952257daa90414d3fc7547cc35aef2fc9e0f42215e539049627f1a32cb3aa073ccc8638c47617c76123b5d18aabf010bc03081bf546d83b429fe0c9f2abf09e6725d90c02d0706c7842e74900b100bc6b09b7944f64e7160aa01ddbf2b505853c292f7d3ca5a739a6582a68faa69e04726cca9a4a46bf4dccc04036b9415177aa10cb67df8a08da8e083a933bfafeb240bccf61083b0da8c640f78be3dd44beb15d0538d2be6377f633fcf94d255c512324b4cae838c11a033b707fd200ce0e6c8eeef0bcdf115bac30ff4eb8e0b3fa17742eb7ac9f655bef69bb0eb446e5447a522ec4cbd818e2dfefc1e46208e4e9dc41cc0acea27f0a9fe474cd6d86cff5b788b9b77cc58e9c8797567354ddcdbbb3a521d09f82df8c00912ef5209c0cea89a6624dd408aa8bb6b3325c53d4dc61d09d295273ada84382544c4ba26ff95059de70a57083b775b32c7e276b29678b892965c980922b35dcc4551c424e6ccc62e0ff8f4564b86d2600062236125e4dc307db8e846ccccde4a9e01dc8e37385c98004b8807def412949f46cad51b981550234b122b248a144f1a4c541314adcfddd66bdbcd8c6e4855785b7881ea56152c9e235b575e98445a95140780bda19d718b8af9eba8747963520bf645f616033d639ccc851c25360214181670e9779a08c1b98bb7755f855cba63a837aa71714752f57ea6167a02e3e058ce3ef01346ecc331f8b89d8180e14c3e00814198f16ae547e80b18e91cbe33e3aefd929522a32084de036359c22bfd14a05078e353d3dce53eae69dd5ee5e67c12b6d910b6be651ee39680b5bb1705b9ab061e46adf20e7189484804a3fe56021f5edb856e07b7d87233d8d68fbc8123c55072caeca12e92b31b1361381048275c5c425eeda0817271e01fba5a2e4b2756c34b148f211b3040dc73dff14b45c4818315edd23dc4251dba8da7e3ce05a99216f0682675182f808a1b0c244ca01b2c1185189868c2ad22d6d1eae74212bbbd01d95362c5a52b7bb65bd981e553f640eaf54ad114d35be7803bf0c42b7492f3f751356f668a23b2d48bd88edf76273aff7aa0c8490097f3d3be4be9a4dc574c06e3b79d251db544211931aba328910e1328c1a836b357c55407e836543f324d7d9fea249da4b699a48c488a48c2bc5f2e141224b9e56eee64e49a43d1f4e54492c5f02be85ac00a988a23db4a3da7bbace5ac72961ccef75a235be42f62227097663c8b8f72b9eb987801db80ba6be4131429d79fcc2046510e818ed7baa8e8b8df28ee687e5aa258d6ae79f8f1fd2836ebaf26b340a62649b7eaf30ab49166825650402026631916d042cdcf2f39233fb4e66626fc20209d55db13661127eaf4edb9ec7419721db35d764bf02cc86621627de70da998f91ac05f6935ba49e9442858102470c866e62988c1a95e0db30ef687e1faf559a80a5d8303e08c622c4f339638901c102ab5b5ae3b0471c905e4c9665ee9d3de3cfff7a3333e77aa52d7cc91b62270eae2fba513235f74a13a7ce642abab46166713cb84dd6e1bc31a0220766cb542fb795f8596c6d4fad77d0c0213a3ad40bb5a3855dfee4dc27670c6c87346380678905e8314dba51f512887221973f9f50cd08e9f3b5617926fb4dab023c50d669c4ccd94ad5a409a2fa269e9f5cac00b498c5f1eb038d16a447bb547007388f1361d9d6aaf0800d9ef7c09e3758127fd4f0580f40ea6afb532fdd11c6e4fd689985c41b33950d291f8c0c7095d88ce2f6d296309b15608670dd5b950e40331f92775123506da2ffebfab2f5dec45fc6da9cfb87ab3cb02587dd1accf8a95db6683750457e6fa82a0cfe6de59e0aa8f3ef231ab1c1952158d1738e81d6ea96ca04a3c52522b50201de1f1628d7ad79ebf0b316d6b6d0ec7f3a69356ffd03775654069c14b6388a16f10b6a293b95563f871b87424be1bfb88ea564af503762aaf3511fd22ab78f4dc2f56db9aaa646f497b81fc111740c5d3c1c1963a06c48a21fb995df6372b1eff394655f96ac89a58c067f7d93b9c4413ce698fa0ef0d7b240f5c19e925e874c9b88d428f2240291fb088822c3fc479fffaab5732e880905e1d92e509d642f28d370fd34b9b1a9552c8aeb2d2b41363056c0a8bf298502e381960a53a2e99f71b12fb49b5361e9da7c633e6315daa984cab75bdf00e24c32a1fcfa7cb5fa0d4c0ec611bc537e25cb3135f43031e74c35a2909168e09ab88d5453273a5f9f920ae8ce20b38d5c72c19dec16e6733d4077ab4bf52805f3a71aaa69d1141a02eccae1e0241f3c39a93ffac3aa9d44f2a858147c6a478842b13a9ae0f581f3b9678361013449ffb5660ebb10489d8a4ec22516c1972e7497ee300d3716d1d7bb6f6a0425ee4d69c7df94a8de004bdb5cc7b2cd09684ebcb9a7b90b052cd09c24a264b9783821bf91b68490f9dcea914790e8246959e3aec5bc63ee80c09a70bb89c875a8e5d5bcecfb47605bff94af76a33b9cc33d90fa53f9ecd8a0f617263e93597861ce61710dcc1538284a79e2e65705f6872023f4cbf3c605bba166ca28cd4578d20d080c733dc0425e2243052b505eed8c1f084e3b8563e293cfcf30c4e59474290ae3895039a68641968cd346683360c1c3ba646af62eacd5f186174811e547f153845997bb980542bf000b2defad9c2fc56077cf19742deff1128cb95c41f38e091b038087b1ff9583e14f19b7d8a079f7c784a03f592bc56a69c65a06da2df5fcefd540a04d7302c5787bfab7c35401a5d7f2cee1d0a7566ada64372994f2b56ccef4c828a7487c970bf4319d4fa243f0d535ec06359f2a3ec1e07bcc4f04915d4296bf0d34cb663ff16e76ef4148be3be5ebdec95d90e28728b325e937b53f569a09ebeb66be79b48360da7bc72755dae75613d8f550b8a18fcb08bc8d25537482d35cbfacc13a104db5c181229dced1b8ee0d7a2a3fe789484a3b89aca7fe828ac87edce007d466d17ad8b14fa33ee7808a9d15a8fe0dccf75b9fed46e120d3be129d19c073c75f3c259de4002e93b22374663b103052aca21178b8097dfad11015dc1e59e2322e449facf09cd98c6b6663bbe59fbf686f03c90ec88a97945de579a7bd6c2e70a747d1e1b5b307c8bbbc6fe6b093c3d5d4dccda8dedf4ba2eed64f0ba702083957f2c7105719d41d2e96bca2a60e11485441ae72847dccf6de4f3a4acb766c50dd0b61dfc943d5c46730d8f17500451d5649ee33d8245e7552e44793c94d95e6c8e27248c78fb21cc49a9bf589b1adadbac1839077b466756d6eced7805818b8af23890f96719efc7a3d0016720c79ece8a2db3310cbf0945c2ca37aab613a48ffd68c4a894af14c112272f8f13ced2969a68bd5e4fca2d3419a123aa511c384adf1a574f4bab147937500e8f8d48fd27dc7ae850677bb649b0d1abb961b1a45261cdc883b6408ed5b3cca2440733beda0ca7f20f622e8d8fcf4522592e2c705c9d2de47e5cfcacfaed53c1c44fea6bc2f5f0686cbc2eaccef864ef663e35e56225342c854979ba2f86e5e3148a8ce26dfb4636ddd4a4d68a21a01cc47795a72ae45e3b8a6274e6e1932066105bab4f57ae19f2d2ac33c03b024e833666b4a4be24318443863c5183597946d2ac119cc819fa8c457e9c187396785d7f30e49077d50493cd94aaa66d06e80896a680dfcb9fdc190731bcda6ea354ed012fe1780947ceb223de3dbfc684652b2a92605d3a08a6e5e4a52c584f87f64c5733900111389844bb39fb94a81b7c276a7e36f48d6d1d10d45360f313f8f6a622f4bf905876effadeb985297700ca452a791a84087c9d1d6418feb20c93e4b4d35d1facf9efe8a5aea8f1f28435d51e6fc57bdf86e8012b994574ad9af5a8a1da2f1482df6843e2373c9a9379d360730ea31073e405d445cd48ac3f2d17fe4767ab9f940a00a4262ac0b8be536fa54cdea0940dea45e1cf00c0920813382d3d152b2cb3ec9a786eebf891a054b970b5cec86eb216b6e8d68bb0b1a047c8028ea34a40eb77221e057008bd6b26c832e69d3b3e6994ccdf8a1e045c46d58df461518a4de30931d30dd359b5b4043090d9293b611df01e587c1199f3c75f889743f359932152eec416b54fd29af905a08cfd1b80c8e2b4194b9baa435859a9ec167be3bc7c277a78ccc1599f6de7bbe23cd4513aeff5628fb2fb7a053103d9cb8b1836c3a46f578ebddca2509f5ac1a0d0f55f96d364fcaf18964d08f65546f47d93993cf7cae52ec54aa9b0e31e7ee14c1bd3a4af72889753f6cbbe7c2b2570fd09603e440a378ad13582bcad526f6b684a18104570674a3f043553cd7d38602d0d39f5dc59685761bc5ae8d146549276947677b5a3322e1af9ce4e923d8d72c3672685a69a6ed218c713898860290ffb19ba1a6fe04829c64976b1a27148f2473b6152f232683b6c5fae593a9cc091344e05d2dc701601d9e943db93e1118f7dd0cbb5ce31e56e545b58687b0c0b4467f33b85031b86d52250d8018160e10f778350d0cd39e379597fdddbcef7efad49a0a524e8c3248c70b6a8a97e32bc6724f6906c0479fb26abd8d947afc379ca412d4d2f89ec1bc2082a4f0b628137b10143d0a7200bdd58d6259d9412243efef0b5cfe6daf26515f6985c0499db9d5a8d10e8bec2ed6d331f4694a77d39aa51797d84363bbd7967c25b415202e209338ef122354fbceaa3af9039339db194f8502c0729b4dddc4aea9764658b0b3d60cf97e5fb2544ad507fb93f217a5ef4de34e2abf5340c29e4050e0912e57d3401e65b714adc347df949aa9e5db130484d89e569ea644d1387743dec88d72dcf200cd8e089379e9b841d15ee0d9fc0ff208d4b39894a7f144fb2f99c31039a6fc52233cbd7f00bbc8424c97fa4a3ed2bc864e566860bc58d4fa62a7277c539f733d59736e223a9cfa1d29b0c868abc9a647efb473504ee9510936e6446f9311f5c609cfae7bad89480524534bb8e8ba169fddd769fb2132fdbee1332f283938f5fce6f12df8d1367d8601f5ab93713b2dcd77afd5e8d67033d1c3d4af07525c7f894c21abc1ec9f7663c4c290a2b1f38fdff21013f19bda29f07197f2462869f0718c197694e434f938f6aac53baada38bf404b013e1d31ea8449748e923a0558ee9a8c39c67557f4228b876488340f88752f39ac0cb8395b296b1e35c62375f69126be03fb011413e90403deafd71adc691c17402573a2009377f594a6ab976c65f7f3a6d45c53b68603dacf539bccc433c6e6511e5a78823d718466034125ebd1894b8c29f94886c38c930f81588cc9e39c31058088611baa736625407a4ada6e0bef66221b3ddfd429f135000a2f5287970d7da86a7c5eb91f5a8a38bcf20a460f98645985cd85832342f7551ce6487a9b80b558a489f08874b608f95a9c26afbbf8228b45417f7ae962c6234fe9f290a473d58c67cccd1fc23a617a842aa853a1be670d29f4707fb55a9514276f073587e0a880ee6296a53137aeb157a03ba2c6954809a9c5c2a9a4a34f2899131f53190cc951da588db1e117f5156369feb543363e1fcb3dbf2d53f00a6f726489243d878436c575b150051b4c60c9eebde8b4384c4fa92bcb858b6206a862a28e725523984cb424cb450f46eaeee2c4b27205b67f0c060d4d37ef56d5dd7f639a43b5b21649bee95ecc3235403665ae3ff1a3a25bd002eddac98b0b17eb9e0799c227c5632043ecce47b84b4dfa9713f894643f59fb2301ed5a39ad5ead16ee72e8dc70973dc0e6f40c90ece6573de920d7ad36e6420662b017519104d6055708bb5bf2bf301531a14021b690e328e9c03dd754d4e24b6745cb5584ac769ccd35c40b312a3767c03d0fbbca7ffd7bbd72672dd49c71913f63379067dfb90e0f8763c39ddefb83ab2cf63a578ab88e4bfe51f588b7428f4b44101ea183749de8151d5bf45041a44b953f78a4843c51c9ba6546d1a55856b91fdab53f74b19289e14f66280b514c42251120f21892b51a0c873cea82bb00de9dcbf14891a3a13a0f796c44ca133fee5a162c411629d5274f07c9220b79d0d725fe9dedce15913ab243a98b2eade234121833e798d1fad2ecefab5c96fa82de940a8a609c1cfad6d47a5829145cfbd403a76bd5caa1034e0d3f9ef118abdf6d4668bf52a8f665d0ad98a840348377bfb1ad305d906a63df6f8c840f43ee9970f0a254f433d2c860b7995bc2427fe34c649916ed580f2ccc2f64b4ed0a2930ef5288a6552937c0c781dafa4b95f96779dedb904940cdc94309fb08149cd46b5c64c9e80877cb068972ce84600b6294afa88c2b71d045e8a96d9636354b200c7e3b972c69219679346f97e4fab8269aa3de27d319a6f60fb367e64101d21ecfaaf398707efde4e1232d937fd0641f2607bf9f67d9c387c1629eedfbb9363566be39955a2b84f8b3acc2da600c30d06cab5150df0a19e127ba351dde879a8d7d4b0a71aff695d206ad92130fe9fcc0e93e326e52b96e0990e49de25a135d449c81e240712a443af544edc43583147d20774cc784be2859868022ffdae3e4dee15f4f9a2985b292a6f2a4394fb6e151ba995dcd2365f12b2342b4ba09675bc4dbe6baf7b27a22095ad20924fd6d479b26d7579865ac8ab5b6256e4b8bda8f15bf361ced4064035a96915a1f10ff653a7d2545ef36a10a8dedcb6351f2d32c28897bc04fab6a990f31e0436be04b917d949695a322a33671adb3113ee0872fa15cf9584a6293f622ed413c71652738e5a8af0d49747600c81ad61f4ea93c88c704d1269609e5b4d2f61b8d938513e74bb8df4c3e9a3ee3b7e7008054fb374b08542d8ee194a3174b23c4ec4d28d68a77da7621bafaec875b4ab52716d3d885d8f1a3a5aab6e00728aa23a046cc6d22e8015f85c1f7f0bb490cc214c170800d45b0748c62347691b7b3c56c1dae377ff6931668f3a432c62b43db2234556c721a658b41049abcb3b50f324f766b1905f8ea5e1c90c945ca71514ef3caa7f4929e4ba5d93ed9dcf0f29b3d2a9f5354fa953b4eacc05940353bc88a837b06a9fb5c055848ec86f1d4a5992bf93564e85ec568c8d06d9db3670709a5bace3bf3972a5c026e265e559a8b79858b26c3fb5ab85ff73d87bad6915e12471cd65e9ccfd311f7f731decd5a80732cd48fbd358f5ebceb79f042978ea54c94ab755fa94c89ef902974adb95155b11718527cf82d301fc7a8e267bbfe21504385ab1f5d452d39454d7e75761a17898c67020cc0fc46343d9c36daaae61b110aa081450150b407a66fda274c5c14ae0baa2ebb10e959d97ea2424bc4a49dba5f0385f65c34bc0b81d77dcbf877c0b585867d1758f674ce4ec6608c28ba904e9c2f717aedef3849115d9c3ae206760ca5315af688fffc6c6ab112131c6acf04a6a383bc3d9bc17dee50a6c781167e07393424e832b40203c54950cac608eed24f365e10855e36084f62e6bdbca032b6be67e00a017296eb360ea363eedcc6cd4e27986c29836e719c31bbb43dd91890e5f796a599bab6cd4633952168e7ab1d682e36f50256696e5c83817b76ddab433ab1aa597fe7a7f06180d3cdcea85e76b303b179b7b5f03fe5df611438096d2025ecc324b8cdd824166bcfabdab685b837aa3f01c4eb4a39ca87ab43f4fced39e658b9b9f453bc7fd4aa2f0d0f9b6fce634cb82592da2311ef11d54bcd44e563cb3a836e53e941f977d9ec9c655cfbeb637651671bb99914196e11502ac6d3f5defe914d522fae4fbbf9468ba2e99e1219d632c2ee4db8bf20ec4fae2b07a4a214214a174894ea24c6c5c8f80675367770e6d1b16437328b5b5b030674403ec3d0bedb02886e7ce084732cf34f14be91c7ea6d329cf7e4b02efb3ead68aaffda4659444581a00e7be1dd4aa5dd98e78e0e1b4bdc680049e90d48e7cfe66bd03db09f097d724de936364086614d77ae580a5c86725bdeef4ee0b0639d1056ad7a01e0a1198868edbf61b55483aa7dda2b2f77ef4f2ec43590db0f09f63631e0eee509cb8176516f90819b276a44dd54c3bb28f1871d85c2a2709379d4a8748fba4e0ecdf0d3f91f607ad166221420e25cbc8023bcf6c2bcfb54fc40859c5315205a0bd3ba15bb30d8dfcc8c03828296f5521ec55978ce17a3b4db8fe94d808c34a743205c70356d35b391c23b008e037826b569bdff08bb5f4dbc32ec4eaafb59c9237b3fb5fe67ed30882f6980fe158566d665dc4e33e06933757301b5566d9ae0dd025981a283191fed6a2ff0157f8b44d2f6f4af4a1b268ad388ee327bd7270b60a3e73cb54a2bc4d652f271c2f8d8facc3aee4096f0662ca01346fd14d9ef137220690501763ee5fd40fda7254f1cce0ff7297329c5115b46fc68e434fdfbf0d8d4a250000698f85b9cd9485ab9506767448a2d9252dab27a6bde51d986141eb2400610295124e5ca59559757e908e711f14ec5ab806198123944b8445b30e7150b7b0085d6ab6eb88e6888165db7c54b57cfd75e42a26b99387ce61da530303e7b1678b422692c656dc3f5e2f0858ccf7aa981f9c08442556a97939a1fafd6684be578c86bb1da014e377b80e873c4d6439cb7d5cf5be0d84cd46b976ffb21631ab9c73a44c89bb9499d9d1b3465e5129a8e3ed680bfc33e0ac6ce348fea495277e425271f9b92221e875e219b7ec246015de64c04a65150e1ef01df49512dc70c4326a0a43c468b2d397ddcc29440752f5f9f8949db513bdbbc5a11cfa36af383876ef3a16ea16412fa14d0265c33738b3b30540c203667e6818893ef373b058cd8a5aeccf5b48f5cd6b581da9e32228fe6083913e90f39a3fd2a8b9030d75d0ea1121b5f332cb21c196b759a13fbfb83bf95d406e89b7a4050eda8a6200edc365ffb84d423e416b4541517a144074b9391c068ac8acdb41a7a0840e6e967858010985d5991ee89c29a8912b2ad5e3427fcfe08e27cee41fe52d88f625f178ae84b91fa3c875436527e007b6634fd50603992b37a0a53b58dbbc2c17457c38f30c642046804e8a20d013845944fd4e6d2d14efd0f844bc83fbfc4fea2de3ebdaebd719e3870908a1e4dc11f41d37337c4d936b73582f5ac8e620bc4012801a34884cc8980e264201339c3466c6d769d90f1abdc38298e810ead5269411a42467a15cee81ff90858f638c6a6c681fe95a0dbd000a5de2508c322fb9a7aaebf5a6826d031c67f6944bd2382acd17aaa7b72cb18a1d2eaccd88e79609298895c4b91ac1522fe8e7f0cc86e4619c9efc0e046dd758f0a82a4acc3ae11fdb8a70b24347bc0268b556281476c84575d8f141678f4b4df2318d0acc0a53f8f98ad60527bdeecd097ce8df8677e61c584414e287d925804130b0d5a81b285d1421eb4784bc00257634d6db545e72f12d78c8d01544a5c399b003b2c0dc7037247a53d03f7fd6587d650233b6e74df9d1be68fce431659d914711e419e82b1fed9c86fd3973878d54ed5312dd4405c385efad0146585aa89bfff611f597580383af4f521a9e268fa99a49cdaa18985fbdfd2e38eaa812f8f45828d340094e518cc210d44a7b5b5904286c5ad9a5087db41b84cec37936040f35ba893e9183043fc284cc3a6bdb26f5629c887cad708c994b5c13affa02451d75c9b5c21beeab3b058b257651c05d9716face1283320712fb055c6f8f4dd64fc560e9c5259d82210f904e3324f9fb44f6a5238cccc9d08e01a0fd88bdb498e0933fb02e47ec119017901b9d91b9fd097637ff3a4f1ca2c02d36accd72534b32308f4009039b79ff592629347ca4188179b148ec704bc4ac140ad5170c108547ff861bc0a0640990c91620440832b81ca189648ae8880db02c43caf0c1fde9fee80c5c002a8d2a6d54f646ff63278caea3a66a35358009b3bf8e905a9630c661d6570c47806c4bc347178e8b2d000da8cd372f0dfbf25898e7e8d2bd033a407592779649707f82d61cd269c5b42107e30c58982603b10e3464b3e23087031408119693fbce9118eaa0657609718a8cf8a052203f59ea3c3c10c8a0c5ac87faac6bab9bd8d52ec0d36ce6a2a0c85185343e8220e3cf166ca89e2be79d967b46deb21bee8bf21e4c31f662ee480767d0687d267cb7d99d246438641218028ea9a010d312712aecf571603a231c53a71082d5abfc3e10c56cc175fed776cce8dfdef4d3bf0d9d59c48039e4fe7dcdf78a1bbc3dcc5e789c4f4902196323437084d93c4970fc598040ba251a447216ed3e81fac1cbcd9ee0efa147f762bb6f436af8335bae1267bb12aa1d20c2e84ea701f9b671851b98d6b55012b8361719c3f1c32c42e0a5ef486baf50d4ff788256009768b4f70a5cc18a5162568c575ced919ce71285ff99b3102c38855063c4c1dafc70be8888c2952a5e658aebb2608c7c232da4e876fb07f3a1d467687457a89ad845a54c5165f2ca2b12c27ff47280e4edc4c4843df368249840e4145ae6ea88467dd0dbd909b3c0293397138865376bebec4b48a0471a1cfb18e1310195c4d659f8f249c05063fbb08108e4ea157bffd7251763cf3fd597ee19b28a00ae8a7626a673a8d83b519366f05d32d1afa0de0b5c222cb5633c35943219aa55ec21593f29548cd4c41cabdf33fe42b6f758a22c43f7364bc1d01a531d91aafa65ed26021d47ceb47ab4fc5f32aef5aee00b9d12522af3696042d9692cbceb5c7fbb623fc075abf4132185534b482ac5d2020741f86b3ac3b1bbaaaceb887a0a67e06d65d6517afa3ac9c4fb9a0c81e01624b5d7cd559474d41e137fd66c28c9feb893c59297421723052e1c9b74c220a5ba95fb4a2f493851caf35e057cfc3bf5e71e7548f84cc143caa52c1e99596baabd0ff518d2c9f3778373761b8c07e0da23b48418795dbf5bab05c40599dad48e663cff009a3e5e259e17bbad6bc05b94311893f794b9acc1e89dc99638479db97a3afe3c108de8ad75018062bd58fa432a8e4be998256e8406097962a49d977cd03760fe57e34cf7aa0ea4da8a54f5f87205f6bdf9cce259f305544c15b5ec6dbca079e7d32c3458e275c62030959680c26524548801fee18cca43090dfb212cc08c95752807b37874134ad8a6cf17ba865f5d7cc25ef3308c2b6410eb76c3d54cdfc2090218742aba2ba19347b340cfa6b114efda5aa5801ba8e69ee074ee93a1cb3fa79a3640d81091814fa8611a523b7a054ca68ca39acb28732ec20d3095d7ae22e14202661bc969cd86cacdf550481b07103c6e7461840fa11a9dc2c6ddc06c3d0c4930cba4f24b0494a6f5bd9e47abe09e24acce59c23d717d19aa51517bc40619433bee82e8d362ea50b4289067a3bab37f272e1fbbdc7c062a46c11b26b0257b14d9801ed560413d38683cfb0bbf3a7813e6b1ed8dd7796db16ec77eb457f8324a41cace7f84a5f00e07612990dfe698c809cee2bdccc685e3182937ac020ce8230897459da0520dd2e167a0fd31de55f3f69f95ad22d5691f211ccd061bae4370d51845591d4357482cef2d30f1872996beb80c984f48b8b61872828827255efe0762d9da931d700ceee38cc090144ff4b93fbe42e8542ef28ea9ccd7ecfa28f5656223dd843c8d5fb7c5fdff386e81bff51822b812bd1a5ac2e3d5b07b7e676bea6bbdd705967773862b71a7b5e1704d2b4d1ee967d6c07f5b69501409400016f98909666bcac8df7d5d9d199c651d2411a681f3d94d2ad94f316d5c1c00bcecf3a4bac3d938d15e7d33d3536cafef595e1b2868e14fd4372f41752551b7a24b319a912f41b693ae692fdfc98ea5d12ef3d679bdde5f6fd9e846c720014e9d5d3285f11f440eee6a418f123f4e269c945fa3eca6d8ea1105fd2747d8c0d01f34f74d06f9bae7f3bd0eebe3746d928faa70865e0c68b23ae830b4838280a3940c20bbf0efb1391a4ba2cc53426d04a0f3502349a2e1fcc899d2cbc0ba707375449f4e824c2cb1954d843e1bd1969ba23e410777d2775a3a9d8ac951632ed6f1b531a56a0510fb9e243ffbc3d2f625880e8d51c84eef167c054feb2a31253b00473ec3d1afb32c3cbdd8d8e69267c84c6643040413e35ecfe9eaa97f0c1297f5ce91592aeb242f78e93717bcc0c0ce83f3bf4df822a79b69976b8c7f65728d8a41b51a2acd79b02508185f577842c42d24aafb994cd1ece8bd0130bd6cbe03d55b4ada3b89ebcae9ca4012e705a0466d1f392b87b9b9f51aa502c7ec411a6cba71d5b0df24438117cb6c0dc22a2e28670787a0d099e6a3b5917edc2f34227482693791e22f549f7128ed22e10285f1be46703e92877abd0c846abe95617b0165340321c046307592f6fa9907a9ac280dfd05dc232f6dd0e59ffebd7d22f1b959e0652116644cb11ceb258e0e962a2cbd16f551a9926adae5fea650176126292c8c3e1a28b3c032d2d629f84f0e9cc9b7174216dbd3dd6525fe510fcee8b3c12dc463d716db9572285f6b5d0244bc1c08aad5a18167c881068dfadd495f3bdb04d58d6084df2bcf7409eff573adf4bf07bd74182e2d36b4cad69a4f769a5a9da231ac4778a7c6b1b0bc401d34ff165b641e07ab33f3b9f54e27061dbd9101ccba8df5870360863430553c4fba7e897460958c6ec936de50c5b5faad1520a02c7cb48b32ac16e06edb0fb584611985db2f820b039e5167706198ae835192a8d7104a81f6ce9b504b7b8d907ad33029bb5f144614aa98db14b73b7dda41ffc82650ae797962ee8b7d460ba3194aa76c2192be8297314f713b72277c1d8bdb1fda159f409bdab8ad59212415c39bd9fbc0fcff9079fb357dbb03cc97b97498daf45b7176a8da5365f2dee14a749dc1647fc818f9a7022e257610ca17e02c477977b85e41f53ad1fc10fb6a9e9bdf4d302254aa2831d9b47481be54cd83340365b795ce482de59fe818fa2606c4edf8a0aa0b0886a284f615f341b7b4bba4d55936beccccad9b7c6941686f6c5e7662aa8e9c75b436ef9ce3d4d10cf96af03290015583f7bd67c36ff5c4bd92d38dfc9ca2fc79b1b5c75660841f562032b14f6a0263467118f5a03406d674ee4181b67e560835fb43ee8845f34a0852bc32fb1a38d19ad1db71bf6024e35d32a714b59f00bfc731d6f7b06204d8ae0f226986d4f57f3b773cf4c4591ecb97beb09a0349a509f53ee2945108401b5048d310ae64c903627cc18822ee414f7dd7f166110b5b39e0a2fbc89b1728e26593db47231f8a79bbc95eb3c59f6e60c8b2093d14925a38612d7dc3851070525c315a89bf84b347781ba154cc2d522420c9d5727498df0fcf81bbfaa3ed38f254e45ed3aca631b0e88acaf2b287c56db43fdb0f51e926204caa772c9983f770dd620f6415aaa37b3d1ce5d1d313115bc875c5edecd63391b9ac98ade7ae16479e7ae117a387897411be5a119efc50a19f0d94d50bb09e29d3d0ac7433cfbb7c060a92f440f777203586a2162c0f70eb3a59634173dc1d81a9c102f4b1beda21e543977df7384cd4296d6f47e419f2615712f34e9fbeb943f61171401368c71b7293afd5aa80523e8a387652086e3f1b5cc4c02fa08e67ed8701423ebc4dbd370cd1a4bcfbcdd56b98c63bca39e1525039c318f79a4844d73edb1f75f5193690f26a9836a9446a9074652f56043d93ad6b58eb3e30488eb645c68e145059f5e506e4ba91652c8efe310beaddf905def263aebaff73cace39058c5801bad598b58478ecfabd8884d8128115ca2d3408787cf4f450596029940e4b380f6f926e10ad61045fbaf648c4e62a1165653c50e28a2dfd62cfe37f6226cdc088140eec5a1006b31e29e10be9d5093b116fa92e6ef0b16b49a7e2e6b98632a16126e7adcbdf9ac92023b6e226cea45a5e30a3f5dcc92072fd43a1c63976632c321e710dbbcc4a05cef15e40f34e353d7f21ac9ecddd65b0c32da25dfb83c5a573c157e7788a065bf5df82949319b2ba7f07beb5f801c74c8ca0f5aaf7a58dbda5b09b4e24ec2bab8b5ab2acb3256e055f5e688e07e3c926bb0fabe586c9de51a64e5ea1cbd046bedf95e331a8c81a6a937732c6d370642c00e409db0b6b4f490e9538b86b544d545c163489ce527b3e46cd5d3e9d97f922f59846a7b347a4d9ec2f84989cbb48e574d17bb6a6d3f6a5aa6ff715c1ba770e45e86ed38f8db7248e39334c08ef04db67edae9106a38a08287296842141b786a6d45a9afeaf54d46e5bc072af7c22857976675abe292041e54463c038b0d688dc0d6942cb3120db6f0c43eb47847231a6a38c96e07710475341b24a66a3283797c7a572d56b05174e23ee19ead53d68ead2357cd4604e27cf9a56d917a6e881ec7555b533bd3c16cb761c2e3f13c13235609149f6cc23543dbb8dd297ecce481f5e47afd23d2e469c82b57f5f47be913c2c75b487831243c1df6652e062bf5dd1383ac4906cf9a5c8e20d229b9da750a10c87972fa0e2e58cbbdfa4af1fa075b80e9b73581b446dd71d16c6813343e6b8c1af79012b755334083d7a3710c682ec4503f346da158d301cee757d96aa6251c0435a97defef7cf39028390314fc0a3867375853f57cca7d5d105332911d28d0e835b34d167362c8c61e8cec6adda3eee89570670259cf7cfcc3668590c4cf1b2d9efd3b643e97e00aa0ed24303d0624e43b189e88802f1e25fc74cdf327e7101ea365cca17c8f2eb63475bada05686e0728f2905ebad04da11d04ca0ea3ab9e09846b8e5d764a73bf0c950aced89b3a4b75f7170582d6ea4ca8dfe1e3f81d19536fe0a0dff2927558572e61478c40b018b5d2b4732eb99ad484a530ab92ca0bca03dd2abae1c36c8a65023e64a0e0cb1897d19513b09e2ae95872cc8c864550c848c3dab5df8686c0e7026be4b481571f402d569bdc4cbba21208a0d8897552f9e67e0062964560e5f58c71244e75dad07dd14d2db7cc1837317af745908a1e22a551c0b3e07150a491f1ce157dcc205c24d8b1ec88cf1596ec233c8089324e5798d8230019e85fecd9653bbe4832dfcc5b475e0a1d319b23416901ec77c519b9d47cb30efc75800604814e778843c75ec8ca2a87e5c27f57c3499cbbe5c69723ba5938b0a7c099e5a0b419a4d9fdd82f3c060eb30e153ccd945003c77679345d718ed30b6bb90a9a1786090948047fe5a80e5a186a24328c4b034cc8d31c60483a16daeb3ad0dc7f5f651be9c41543e4de9c5dff28fa01714156101fb5a830e41e676e15c5222d90f41c34c3528ce9b04d22250e8ca3d028d4c2a5a2e6c442ef9dcb68a0a214a3d815036d56c8425d7d0bca6f9fa2c4861ebcbbe672ab4d6e0f9f9579adfbe4040b5337728050caf810c9a0d5c7ee7de56471af3a8f465bb2c5985fff6e9750b393c4153fba1768776b04ebc5ea356645723798ade5428d483ac6125e3abf0b13a58337379f6fa4b08287e4539b5ecaef12900294fce193c02d0471ed247c4abf390987fd1aaf27c273880d8de43e90fc8a85606e84b5e72f84205d546f1aae6d372f494d9940d8cf23fbf06e5f4941b0c4470d62bfd448d918530e53aae7b390a9a920fb894b0317fa74c83ed6307f682e52673875b1840c0982318cbd1da2135008593aca61ceb068cac339eb54225299e05a48487bf32be7d051483b82a4c3ef2e419ec123a92906c878eaecb73712ba45a85c4904478171ef790f3de2412a39df6797b1e51ad4865acc8530613bc654f361d24c20e5d1a262778c66b965a40eb60747c2bbea246a220accd8f88404d7474a5695d25313c92c5a1ca0b01d92e49a4086221383a53ef2a0436bf338ac959fd3dde95f3f503eda305d86452945596c256e09306c33133baad4efa9cf23e9e59ec2512c2a11c594fc54260a313cd2d51a5329baea2dbea5626371ad475009469ab64b6965566a603da696e259a033b858f93ee34fc8edb416da1d1b83d996b29db623c43fb3c1c50aa50adab1ded8cb0ccdfe44cc12006604da8328bac2c5761a75f6c8f6c20321110fd5c11d16eabbf1d9f6b64ab9281889f8647ba70a76e8ee49ef56c048645f3c403c9c7b08201996efc4f8ac9527f99f359bbf48765e0befa668b8a101a149f8a1df0d5e9a2215226c8cca44c6ce4f4acdd27aa545f1a0a5804bacc483faca833c5f94c9e4edf4dda44410d88e3b5dbd54906cd104422aa9be870a02613e09b97a052cbb3e2f8496982adccdd7c349eba366fb0d7202f5ae1346e5681860fabdc5b5acf5513a4d35b22c7e1ee217f0900b56093b1a93288ab083067f9553bf2abd0e06653546dfddb6297fbaef1ae81769bd485d3b17fe0348a4afa5f4efbb32ae031cc0fbc38fc52dab288b604e08a7254df2e9650b95c9e76a32eade377d254eb034f1ce6be147d4fe07807dbe42fe8dcf2c4a8df1b665ede89f88f1158d2ff5a0cf69f11f8c0f1ef4ab4eff30b39fc064dfaafab8d54f065dcd561dd6dc0d48950c171b52c318c422854c43327058bac23369a6f382bdb1fda2509f34812cf32b9eaa7b60a7db50341edc699f67bdb226f5504ea4951dba4a23f128a7b642c901b56cb61e067f529458f33c9bbaf692358087243f98e9ec37e4281f651ca5d5188eecf877bb99e4a30413cfb149a5a9bbe92380ffe1036346a5ec22b7401c7e11cdc8d06500588aa06fe423428449d6021032b969a640f236b20768ce5c36a8e5a99dc7ae121fb702112f93054269786be7a24cc3a4c83b1fad40119313e3569c1e128ffc5a6b9dccbf8a818849d2caa8ebea233175f5b22ddebe0d09226454c1cc15e153716ffee221016c2b94ddce91e24502e47f48c0b00da8f8258641283dd742e06b79e27e4d19c4b0ca2850ab6088e1531d7b9bff086c7baf0a120462a794ed88f280694d6644d74524b841059ce667922672602aef63c41e735c7ec0b4030a0160089ccee93cd59d8a8a6c505fded193b9971e0836318da6e4e99da1ee3d56689601d4ac10c32470e803105cd5b0ab150537d16c3adabc4f0641b70b9e3451f02a3584b2304f6ea4d4659bd100f8b26e17606530516d576aeba9a8e0a2a24d6f8a4cdf80e4fb2df58a688b8934a6a25f01363d4f35ba4e758f36a9a81d33aaca48207eea106668dfd960fb8023685795a37c2d42005800a4eda599db79737f0a4ecdb8da8150a7c74e83fda25c1a56bad4aee515900b8fc1a058bf60faa38460148d1c46ae6f513b56933820c1381b0cf1f4a632315aa5eff8786b34a9f6eb237ad162e76379f1a9476c925edbf0c7e264c1ab5909c8d2e8f9c7222f3263bd2af19e244dfa80f7bfba275e8977dc782af638a7047195189e6d335498d28d7ceaed84924b40a1787954ec90afa97819355ccdcbd01363a716a0a3e547a760da63f1e446a6f09993311188a29024f5e740941a6c5175dddc6422f13c3901d60a3d250b16461925e822be80e93a765bb711d33c774fdf1367cb3af6cc1a2d32d3212910c634aa8d640213e0b64114fd8c56d07f97985834e3312fe50d6b134348c8124fcdc712ae8c5694a58d3fc542e43d2cd2ba7da3f8ef19c59b5e7cae2ab274f178a861c2a68117fbde1ca71b3e28301e54995a7761b935b3d3afd56eb35e5902bea62e68bba11accc13e43b3b25eda5d700650648326618c4faa089334d7f9002a873cff85114c6c3b9a9950b1ccf49daa5b9617c177545c18e2c8b8941952c566611d1b02b4c54805393c1e10c6b10104b62a4255433dfab8f06ba5ae0a6515baa2cac466743026178a2a8ccb3cc8208ec9a896eff4d2aa1560d9203a9cbc82a6bd60322ddfb72699f5b0263519945f8ac8e36ae4b3f5dfc81697c8a0bece7ba975012e188daa371312af32e6b3f700d44ad5436abfa601463b548c764c876a1c9887e920e1a89bede3026e8b2d9f002dae5f54db419c083e7aa5b3efe5a80562fca0e27fd0e15a9139f986ab2e9b61ed36e82a6e791ed3ef440b64d71273ec7acf2dcf1bd6d6e3570a1a27e49b5520033536b0e723546eb503ef2f1c682834f5af9150c121f5db72a1321990b9426695f93bacae993b0713c2717e17860c7515085cbafba1d6ccf9b3e1aa6de8518a1f94e637727dd48b6e17f409a543d29dbfeb74c161cd5d26138ffb71cc163ff59da3bd6eaa80ca062d7a95428fb3cbd1c3425824ae4de219738f48613835018bd5d24f9fe41db9a40535c819b0870bc63bf0fe7f80d96f8527192e59e3e42389f03e97db639458ee882382361a414e1267e3889ba99126ef49aed496a3a3ce60a64aa10a60c179c9f7e4a3f121105a12b4ef2123d9fb77c758da1018da9ffa06b37f54394020f4234945cad3beb3a664c0f3c966385e8b7614a65a760d065e93cec692a81e262c8d23f8e544541ede09ad438d5211d396b116d876cc4ac2ce9029a516441744fdf7dcdedb6dc52fedf6520a2661b4a8662b4ce6ab4056e578445fa713ad0db80e66f222584a02d27e0389a3211034b4b52ae0b4d2f91a9dcd7b5817b45d99e2fe3807ee3119aae896dd02c9e4489d81957fcab3f6e2d02ed903102cf64e3645541c90eaa871bb3abbb2068769aa95c7f95cccfa1905094940ead729c9bf9582a20330030d9029cf0bf523cd71daa2050f616cab4d590ecc48f10b745cc0322dacaa6970bea78306a7a12aa1ba7647a661ead8a30dc2bf5182b3336858738934497a78083541dafc67d1cee72ca24eddec4888aeab7cd7231d6f73de9b993cf9757d15496dcc156f78c6fd21903071712de61f63a5ec981e2c1951711222eb7f8bf2ad080794eb311b96f1d3e98c1335c80ca176d2941fb93c18a829ff0678c339d571af874b33f03520c534fffd46a94fbb5bddb12654f9b64c7621eab3224d39986a42d5b33da1d05491c6126a510303243b78a237952ed8cb45943069d26afcd032be856ab46f320294e45a7a2cc5ef9cc0f0b245e54c862311b65175ef96f151a39f8570b792ba13e92c941a7ef2d7d8f4d07d6265be0dccdb3bee7c245b9d962793b23999f6056fbb985a72a99ceee78ca2d6488b5eb7ca061261e814ca253c10690a6bf3f8f5ef34548ee38de748f8fda9e124bf2ce760e24c6a5d2bbf411a1bda3a67c5b45b573741cfe6b417b72fdc55ea2795dac4403fd6bc1408cabf0df9d4083125330c0916fdaf95d5d5bed9370f13dc9a9073f9aa9716aceeb40a5ae64c7db032b4cc92438bf911d5bcb81e97c03a2a16829802de9975cfcf3255a8ab138a0fa513f6bfbb263fcf32a29b111b179e0d3776d04331aaf925608cde44bee2b41880d544fe1c84d769e1e94427f298b50d52516e549ebab5ccbe2aff6097ea2e18681f625f57364bae5446289952dc964e76d173987a83b8846d4f718cea386215b615144cea451d03ada622bdcf5d70cef89db4020044dd6ede6363731557b3bd3ae4b329e545545a9adedc34dda42c38973f4b9b9e3bcf3125589345e469b97cb981144a6c2abf0306917d6a537e22df410de49e6837f996f1cbb122f172114b39ead3779bb1e2d2ae97ae806f5392e01872e5829602038ef53e27ba1e38a097e148871a78568f6d3bc813e4bb32fa7f1dc5d1f53de0d94d3c66c290c314449fb9e185aee324dcf8031d9470798c4bf7b1fe1f8ff785adeb3644cdd0ff5a67445c481b2f31e17609f696d6a2cdd64c0df182792817a2a42d5cb080a28452419b4084a3496c79b7540dc208c082c50bac70c7bd38ebf4a2aca2341e682f17fe3f65b3ef12f7fc23195a8cfa546fee77b7c634c1cc5ae525980950a39d564959e79874a5bc5d675459fe2de8cb92506605726cb49eaf809dd149a6da46160dfedfab83f328a6ce878ebaab980c4f7a69c6563045b61c8ad4d6c001e10c1945e912cf26861708b51d902d7026e0f543317a5ff9def006b272a32820ce0ba4849d280a21f76ff67103a02a45aab4fb82909c0789d459e41ea4245163ab5d9646c1c033c29a3442d85aa5cb6e7f4baaec8a0b09eba7e2686e535e060ce76336e43ccfc38e8e572b4ab4106c14eeae7d089d4691e5c76ffc3b0d406a6fb175c0d12c5ef9ff4ae677bcffc6fe1d3114a9ad523760db203158d5d0f96d94478c6282117035f3307a75e680b434478631d5a16c7ffa94d7d4e691b3d536c51d114413d691c506eb24f5adecf79d31e85451115f598c3eca8e4982a2a4cb99381499a4575872eb8f7a3955ffa0bca07e69849fe78f1bc4703997cc77b1fb185fc55b3f34490bf0e7bd8946861d6525cb3e60ee285f6c31c8b901d78f9af3adf256396234ec3fa0ca9b0a61d2fdcc90da7de72fd18ec7897557cbe97b4b4e8584b9bf81f3ed12958ce26aacca62121a4f4bd3512d52cb3bd6ea0fe44a23802af18c4ae87f69277d7cf5cc94a8b3b7bfb979f501d72d8913caea7787b9975b227f1c7cc98f71377020b2cf3b78fb21c5d9962aed360f040da1cb5781cfa8af6e44597cb0b1e8eac429808def6113829a823d7cacba16d1f5985ffc03b7b490e7e8c69a30b9d0ea0045f1160713f38a28c6a8b926378c17ed654c7539f488d1cfdaf9ffe9ef6ba4b5721a7ed5cd888271c28e03f3235e67deca9023f6e5b7ecaab8d29dcefab20e637bc21f304411b769950ff4a7f5c4c0f060f3f1c08e8183a5d5c9729949509f503d73a18ba012194da4799ea3a0aa88026ece0334215a26792da859de2ff695206daa449317810828fb9a6253dbda08d9f5791b1f1474239fac0387f7cdbe85e28c95b8fe4655f4e35d1960f09f8536549855d10f33a7c79b4e3ee7372073393cf5cee4d1148a7ecbe448538fb494586ba5c7f94fc23903d8b5b2aa60dcac5647f4669be5252bb33115b9fac5377fdeac8ddc9c298b38cfa0b55f5f6a3cdd5d606446bde4272e5e5bf184e851eb9b52346ef678f8d761597245615a96f5fc7478f82e96a144e0ebf1c2ac10e2e6994f07b14c259a234b634555a8bd514de26db8c8e14a35865a89c830518e3cf76700f9752037758402bba5a83552fe368fef0afcb148c45ac4beabb60c40d50e6730daabb6e8702c27c8c0be7124e325174086ae73fc16b20d38dee419c6dcf5395c771733bee79bef093748a2613998ffbf05162ba739f4dc76149ee9c959d839214d48dffe5d76627c982d42c87caf0aac2305f36278f6f0e11614585446b5ecef24c300bf0dfce4ca244e3875b9b0bbd6a8f9338da6d644951fa9639a1145201e78ef7c47ef342ad49962e3c0b04a1ad408b26109f6465bd54556a23b60a340d66ecb04aa517fb2045a3a4bae231bbb9033eab9421548fb98663c39eb776128c441a33995d815d886342bbf2cb96db5f86f5bbd9bdf7591f7664bb884ed46da350aa5a62b40bc607f156f27fdc2af15ffd33b296f9308e708a69e381ee7aca5ec823886762f2838218205e3e3d405c60ebe8a200aae9c3a596698be213827a5136996b2147a4d2ec2578267cda20527f384b6e3982a09854a361e4dc206cd57ea97e07384954476b2f427e03fab78a9cfd3f720d27c9c9f80c8d6ab6a6c9d362a1b3a264bbcfd5d3bd0ce94ab5c4335c50317d0e5050b743bf3c5e005b9443bce0c7f11640e6824f355a6b2b1333401d73875e077432d5a188474222d5a27e98aa1089a407fe753f53fb9a11c2fb5bd68e910d8a1d0eb95ee20566241055dbeb0c1664bbd688d19a96d2f55a458f1a2556f919842b423e65e00386c203315e7a557b8ad979c55d60ec3f15ab41a775bb420451670145cb40eac69f4dedf84e3f416bc689ddc7b53ecea7b58fef6f1fe61d9f87bbe1e8809baaa823bb528c379a8a31cdb664cdfc19029125440d568cd736ccc0ce650e1f9c1290b7d4a8187d0d8206fb19348ad70763cb75aec03c8dcd0c74e33f6ef817b20f667356d0145898607983070c84182bb3f90aff033c18ff1b509f88da496dfffa06bb9999d3c00a2aad25b6ea8ec9d89b08151bd725065a99ab4647d14e16ca19a3d4d61cbd476ab895d485bd01025046a3cca72861d39f3db1bf26c4b691425b07dc0f48403cdaf39dd906421859ee03da27da2978ceb1251fbbb9698ff158d4920cc38bd553d8be8ea058681da60a14690ab5f7490df1c579e07c9e9b025ed9e57e20fce7d1bcea97e30fd9ad8d349f7bf918f3060110cff2aa8421637f8f898f35b9246bdbe2e5845635d669fdd142ec9ad1b78e2b432c07b6e99c510ffdf004f71c66750dc1949fa99a2f6ce0cfae3b61b7b95ea1ced46a92c9b4f226759f46a2c4c5a9ea96f4051e077fc422ef18fb45a115117588a15390376f6307e8799aa152c23a02f08b76363a804fdc7a5da83ca0692be3d1993e5039e33c7901551d112df5afea1cf748bbbae9069bf79ef5c21b0d0e186442cf76aebb52a59d5cfa3d677a1416b0026cd8095063425b156ec4d564bda151aca9626b393db11570b3a4dd9966d7189f0c767b09895e6a33ce49340c4ed8a43f2d077495360adad8b735908f463e0b3c8c82376411bf53f63f31ccd52be2c070d6b0ede24c11bb3456fe6a00b25385a5763ae21ecacd306b285229b1aa324b45279208d6c32b9c5216e842af3de3b75338f141162678e9ea4ecfc876b675080b37a3b094a2f39520a3406c558ecfcd59e996af0b35253cc6370e6589ecd4771278f236cde9c662271cb28c2a10e38c1560ee73cdc11f5afd0d9b85289b0420755746afb1c7e422a2dc1186a63e91b034c5f1886c1f88d18cf7cc389f709fa8d4c2b7c02711c63ae9391a52112baa21d653cc7406b65e7132009479ff1f20c0394733ad5eb33be3e5fa7817f60e68d1c129779842233e8cca7621a5419859b96a544010944984feb8382bcce3caeec60b3df6be811d328bcfe1fe816abff3075f05697611f655394dcfdc6bc58dfe724e9cec805e2dfe513be5ba11663a4427b523d80c1efcae28ae60748576a622c252eef19219a647b91d3855c05a60a1dcc9909c40ef2418178e10b2a3d5ecf98e4478eb6215db237e79f1c8808ce9a38d53cdc0321bae5d089521432306363556e274156da805114c16aac1eebc0509d5773384f804848c38099e32ca9d50ff528b49a21442e1b7c8f5badeb9d75b1dc8c12180c5452ce740d717423babd7f45680bf4fe0f7819f06280f7e74cd3deb0a2f3b33ba9d09001ab93b1866042a2fdc938c9e9508369f8a4113454807250a9e4401030b1122b4c6bc2ae6cae48c5e806c965c251cc13755c13a0546a76767580055432e6823f2178c64b3c01408d4f2ada312344f3913e87d95f37c376dc324de56122774297161c2da2ebee42bbfceba8c92aa1637bfa4e9b0edc1809b0eae9aa37c9376ed9754337001df7d0b27858f21782b9dc81846972665f44f7bb0c26262cb8772e50bc9bc193eec40ab788d4258ee3fb0491b074cb52ea5f89e9a3730a8ff5ba7f064f6337f3cf0103c54d1ab7cb6a6e8c3dba046354225ac63cd2a26d681a7c8c06ddbdc5c5aa8be2eb440cddb940644ad8eac219ce40f40ce6731984044c87c75454d478a518753b4a9a72514903c02b1bc6ed2eea6f9e40a003ca54730ea2ea9c9750bdc72d11894ef20698054539ca2400f9d67d7cb9648a1cf3c7a09ae8cb65089b6973a0f90de3300ee9ad2bbe74569c2b826bab3c664b6b5e698c1c50e768740a95c107bdcd528ea28c91856ff297695dd8f77299021adb8a269791a83777a699d2c2e5183100a6b2eb0fd5e4325a44650faab201aea4d68dbe834443f481bf37a27d97c5d0e2c609794558255f488ce8d973f5a0ea91c3b311cfc1c4baa902c30017b377ff6d325d66cd6252c0236925377f7ac5c10b97c49b76e0927863cfaa58ccec3661c28c9a96a5b5c09b402d4245fb8c873a82311983812af0f07c80a01953570fe8db2fd57ac086500aa2b7f13a8a21d7dc3ea72814471c1472743e61e7d7c7d9418e67301baf221af265051caea32db56eb8abd1bb66c68c3e087e037d3cec1d07b09d9fee66fa8c443c731adf86963048abd2d8f920ca17ac3802f4c2ad0507f0b00fa298cf7262ce4b68c9efa5562888a86c4b72079d7adbd82ad942f8278ce8079999772b12b79820c02dc6a665025d223a05e689c9fb287e5be78ec6c22847da2cc3af1274d9c07cfc2d3ca52c960a0af635bfe738db05989a2eaa13e508fc7e317f086bbb82e5a621b701d113ab26f1f1860e24c1d778ed32284b0391ff2afd9f36aeaa8eceade8b20aa58f1eb8aa4c8bc4d45c2bb576b209f420b16d54affe788f675281366cfb04ae1bd936cffcf2c5545cc77a481fa44a385610fa7ee931c1c9a2e53326ab68ae935ebc43c61de0babdbc1c211a1da1d3f608b9841adf41426e5c129b67f7a007ebcb9f86bf95f70712037c11fe99d2cacbd2a719b6dd096c9a14716118b78b013e37d0620f7c2f8695b7ed0c60ab33ccf4ca011831c32749ad5921361c34479d925e454c91d08e9494d0fa4d100d58efaddf3674f7a81bf74081eeda5d4bc3dc9742d7453e77729acc2b3a5f5b12670b54acd7cd78bf1023d8ebf7251404874a465eb8b0c600b174865052ceb6e715473e36c13c85c29678de0681d596085835403dff2fbc5a2b215f4e105ab289fbb5fa794bb1bed93718b01a746a668809e7577d596d5c5b2e887308c83bd60db01cb9679f8d3abea9ff04e4c15b19469c7f7bb38a48ee8c612ab7daf82b892d33438ba3fa9c41ea876563343b7da15e342987e344add2d07a20125d0c54cae96179262036c37762b4c22f7a48544c7020323c85950a9210a3f9d586031ae0375f39aafec6ef13d44c3ea67b1a42751f8a631359b64215544eddf722d34f43e81844921a59b924069f39b5b3826e97bc1aad33142ef63b4306b2f7b150306b16f103c55bce35aab662c1c18b6f66f344cead86644706deed609acd6f6c700a0099e646b73f4436df108ffa004dfb0cdd8a7431e385d4d01b71a4c5f8deaacaab11ae13f3fb1aed5d89cd47b12ad9cf2cfb6589ce13b73d90e449c4e9b5c1ed757244557ee4e752e9cf9b2b172093358259c38052246825a8a45ac076aa516f59c3fa7a6ba59f01d734b2a27c03edc3717068471994f1ba41cdc3f29761dbe4bdcbf6f16445d91dc7e06e2a1a40457b6cd38a6f366c95c2568f06bd56b1f0bc96f63c5672b97bd1bc9483b30ff2adb2c9e28d8ad258ce55743526cd9148abceacc863eac4bf5fa7754d084570f47c8e7c05c667b83afb0d3f11a577daf1bfd1da2aa1a080b71718f3e89f6a03128bffe84315b3ced16b63c597c70cb2fb1b978bfce5d58ee351100018f68d0d445aca040ec85c10daa4e5aac5ca8cc8028047f5b3339a78f9ff51eb6e61348216b334fa526f25c392c6a6dc566c73342a0187d69d4b17108b85537980aa9c85610875bc2767d6241a183b1ce3e0835c737fab001f18658b4649061f1aac7ebb2e6ee24124e5642a94430f1b30cc1afe3acbe949a93b0e5cf28c8123bf8bd5d839c0829d756079680464c00d3685627f30e7bc114017e06027b10b4900873690c2b5d315ac55307bd7a043d3feda9a358e7c925f9b424b4e65f310dcdfd27c5b71ef3c8558a2ce5e2f9365ceb8a1578d5018e83843494a0a2e7386e1f273a630caba8f319b9be9c8a99258d5ea87bc7e16dbdaf505526138bbdfd4534ecebef9a76782bebbacff88107060560fabff97c77b797c941880764393c29684259bd0b604a15a02801cfbece9378404ece1c4347d63447853bc62b30c364167c1876ddc7f5f9d067ca7930aa13bbe9d2bcf99646e46838e28e5a980cf19a41dfe6a4d51d369b335062a8e82fe0856b931c167d5ef876c3ee321c0fcd07c72e361aa67cbb25bac9318d491eabee4fd0590c6593a6892708bc6e4fc1314a4202820bc381f1802529f70df65805dd23a0ea8115986429127e94c02a367fbecb631d3191392e5177492a020c6eed33419dca7253cb789612e9564c42d6fded62021b9f0625e5240443118779c0be7438645633164a4c2b3467aa9402e5c8aa1317c83068b45134765255d8504b2c7c9e7940c2e9747d0d89ed835ee857bc9a6ab9a10788cc13a22625e94fe6778f9163da8ff85f5bb5462ac96854d57fd5d3847e8f197d2df15e9efe24ecfe11584d4d44c5d8a3b778dcbf425768fd1cb386a769fe88e2a63cc4ba5e7b003fd4a8a769f817dc8d3947a79654ea06578f4ebaa86b552e9783d99937b0b7a5dc5cd80c69d2e3941348736d562cdeb4a30403447dc01059f1a2e7b7c039c06944dfb36f5270ba73e93a550961e8df08572c4bd336f4b0007261273a384c98b3093f09eebd285b0520d0849e23c1896f4c5f2d5b2ceb7447eac36eecad28328d3e8014886954f9e50a60a95df72e29c490296829f6794b9d95949711a08f9395b275025e2bb3d603e9143644e61bf0a2911a930f29e15c9d7be9c071580a9575c4ebeaf9a2ed89f1a4dfd5cf0db56a57d92dfe735f164b08738223acd1f1d465aa46bb64cc3afcf74531d8552ddd15fd0a1286c06aa0026b8500c1dd6701b7090983a3cea995b4fc74489c7b46ec645c483d3658bca7d9b9cd4f2e1791777ef84f8999cf28269b5e940645529b0bb0897b89eb8735c5eca33e4480623e44896f56d6c219656cba0905e2efe8658b4a015e586f361f29b87b4a738b63340dfeb44d67e0015919b4a7c4fce9590cfaa50497eb18716ea31c329d558a37d61d0a32045c0214349d8701b3f6cf4ba639be60e6a85bbda4f5b65dbd8a010fe8ad7ac029a4db5f0413e3139e252f1524090d1325c187a205ccaa42ffea6585c7e0e594985f4652d4569242addd42830ff288c5fa750d48ec981bed3b08a691c4fb517bee4985b8de12638ed7df237b327ad9d497dd11759eb4b2546bcf11810c9a8b4c8b674694b5a69760227d03c727e2fa95bedf7873d9a88772b76974981e647709afec10cef7252bf543feb8d339b3d6aa9c76be997a3e438ed23534e9160441a064cad0df3b8d0d24939f5a864f3bb20f902c41d40f0b3d8d6803b3afd15fa1d3cbc0ea707c33096d208e0723b195637d6fc6364996d85b4c6eb7e702e9df7c7bcaf1250e060fd4d6802a0cedd077f58452530a4abab5264f4b580281fd1246ecd7117ae052495b1931dd700219b901e84db6f6088e542caa18f72d37901fefc79689b2807b401201af26c8313c317cc9e5d23dfe7c4b3843be76c312d2bb93ac17296b967bf319fe0d547a2b83af666b42a3e0d6244936596003c047c1455243cb61a7d172b955a41028b8ecd2deeb7b32870f091c90105d79960923cc0e6c5e9e858351e7cca7ad8a1200038f0c967be4fd4c067ddd0c69cbea00bdb01d25d308154c31a2f3945cbd1035176a72d93bb531baa20133e396df6cbf088c04dd9e07dfa8804ccd235d47cdda2dae4e2f5d974a3fd4f5c5e45bc983d9b10c9d99b8dd17e743dbd481403846d023abda15f5a404a69351d003f8272edab34503972a60a616d76ad5e233dbbc40715295556ebf686b941d6c1fd61466051148d974f7840cb3e02c53b50e97a4ff363d4a53077fa707ea968f90461df3e97fa18651645ecde6d6defbda54c52069205a005d6053154840ba434826ff34f94c8d3d764bfe4335da6b0f4859b6c2d0cd30bb4e99c02b77f08393a3ff9accb899c822fba8dffddf427a6a11cda77f80cff6d92139d2439ec964832fd4b92d8efc88187e559d889ac680e7c86436c39cff516af7845d4798e33878df173c83ab285d21aa9d96ee57993556b5231157e930a106ec4dc6a53f9cb47c94fb15f07b85f81173a02dea4ebfc48e839f4f7ffbf45859d510f57fac2505b84df7ca71a69cbb46801b62623e1d6caf7a65b2b530f565a75cf39124e6f930c5b7218675bd807d701a831f620058a13433ed3a2d5a18dafd346a5f49fc04929bab26e565796bd8f3b0035f67b319a02559d46dc74ef9a62288b1d801a6ffbf745fc77e30fd111c25d84df6e1445383db13dd8e9df5996cb9b2c194eca803df25fd195c283215c9798787eeced93fa2dd6e2c7c41781c6c4094712457fb1569ee89dc3a40b57f36044fb9f2871bb411c2927de1de69641e9f0c731ddeb6b345159897290c1c8513cd1cb630726572badf8e297b60df574ef1a84e84aeb5caa713e13c957679902e60ec167e2d36ce8bc81f8392572fe9297109f84bdc49f893eb3e9c2c009596b7cf45af4fa51141f952a21be288aa3489221ee683fdf67e22ff9288a3f8a4f0113edafdbe8fb248e2f6251fc514c41d0bad18170a2782f056b963985b25086933c86ad002ae0b61bd19ce480accf8cc222fa5a13455503ca69518839843703934a640bcc5947084d512dd627508e517878c2bdf73ed0694a7e490a84c8a3afae46b6e4bd17c7a4f4fd8cb3b539678b2db6388b18638c7328ea10873e628c49ac628cb13531c67875a4383cd2b7e42eee10fbc6e8ab0edbaf718b1bbbdb0fafd8c24bfebde35f58698aa2288aa228c6d9e18d10d2100d48ed2cfce00031dd210436bea98ba228a2f73caf949e19c270b617e71c9e4038dcf80c01279dc136e1065ea2c9c2759c61fb8e8e347e7e9c66f043dbdf062a29d168b399c5d8ea25233bcb6f9391f9c40edfceb2f5608736994c1473cea2b596dcff82c1de6efb3074c88f48d0bc0fcad20c61f9038b41799a5afc601cca69780261a098697e6031f00d4bd9e09c73ccfcc062505e5d8c74247b1e008fa25b0f73ce9e439c91b299b168862e5e10fc339add5dbc6593eb388f9e43511465f6b31d493293f8f57218ec9626f976c425e390e48e365e11566e9504d2418209e58f77066fc0d4f8cc166abcd43c955c6ee4ef099643888f91cdee9563060e318d8dbc75dd6062f3748343030d8f466ac9c034259a054a697cf8c8debecc586f576430adf1dd9ac86042f304a359a09441083819a6a27404dbf2ac846c95a4ddb18241faa873c332538525ac5295647ca18bb6e55545953b3f559a685b5e0f18625b9e151c5fafc4eeee6163111b47608fb089ad3d4fd0f789029ba6d19ce6b4ad60883b5aa53191610598609f4b1cc447bb96cff05fae223de4cb3e990c3bd01ee127497c7a90729e264e788042021f8cd9b73ce8409f51c0448be2bdf802e56059a7b446aadeedec38dcf35ba375b788f172760f8bc2508eed290a77c4094ee39a843c2b385bbd50b720395de8b7c991548d0befbdd70313cdc7dde6239bef7a9fee3a82cfee0839ebd9aa71fb3af97eef8a8ff25f47354ee7709b54492d028d56354ee31c49bd6b902e9d7324d5e6bf4f299a5a3cdd75e6eeeeee79f597de9d7ffe922fcb2f233fe3d18579ae84b6ca81c99aed46dbbdc98bed2f6bc2c2f68fe064f237c324078793c981669692dd4c0970c9952749251b6608c1c9e4e1dd43d6b002d41a3098608cee4a922472367ea29309bfbbbbfb1615b6ebedeeee9ee164f23c81c54ac243c2b5f10f75757023a5ad8ab020032d476a1cd1b2a918dbffa7d26cff199229db9fa6b4848167e7e2d67585515a23e7e07e4504cff6cf9e0bb33de701a9284568ec5e91ad1d4f3d2369b6bfd0c9e466a280824010f9b2f1eb9309cbaaca7011d2a66a4812224fdb3f16bb950cde7e5e703cd97989e2e30507ee691ce113f3c22ecc13db385e6939bfc871f305888543c455b9a8dae1831c75f8175453c38e6ecc3edbd39c60092448c140645c1821406b982e5d4c847c41ae8c686c8ef0c850e73fa99d150b9e6f8cddac5e90a9fa33c4ca05aeeb77fe742c6c3d6c38ba05f379b067b5c2d7eb62a3c7cbea0a92b2550baf576466fcaec0f8aec4b059f7dd70efbd5f001e6cf6558d783cb68832f62837032f4a6b14667ca3d0d8324604963c60b240c196ab066f46be2fee48ada8655404965a19ee96e4f8d44a310b1733346ae5c8c40b9f5a499a71643ca9d92d5954606a6193919a5a98eacc46679885dddfb9d1f1a2965123353577af533a06b6c9eebaac6d6a2a622cdc89d4afa642003dc0bca8e5c76893f5d554582eb59c4ee5bb4bfc4308554dc5cc049d8ea69b829dae9a8a198e5707c53d3d6e74dc6a4d269c1a5c3515b8aa76ff92963cb3e505aa1a464b2f3547ef56e14ed77d85e52093893ea4f588c37bc72c8e1f3e467398ef95d27b53de30b41c6432d187b41ecdbcad4d82fdab6ee4476e36a1d68eb023ec88fc229a4332c9c88f4e266c6d6833766bed0bdbdb3d6d0394315445b1ad7e6b5d2ba3f86e7b5e3218638c02e312f885f10bbffe7c200b74a2260cffebf57a2d71809342c0e6638c4dfc7a8c456c6ccbf2bebc2ccbdfc0ee322d61a8fa1bf6248aaab07fa1e28f4e9b445d6b8fe2120e330ebbdc762eb5119d73892ca6aa053b7f92ea40517c8dc68e7e9eb464efbe8d22e4bd9493803eff9073f024d21eddcfda02a50cb423bd2a62677bc5170e0d607798aae64892e779fe06769f290782ec3344d517d11355c387954edb2cc7878dff4255f7edd1f4990d730ac21d73646b2d699568d5eeee2f1580038c4fa6579af7936418865f5e993dba3f7e0639f406f9d10c7ee4dff8bca718aac1779f06b0afd7eb64826518f9426ffb332e6169110776c37e03bb61efb45fe8455514fbeafb7a1f455475ad9dafe9b38b9f94f6add1ef4e712b3b2e974cd537786eb4bd0a140d93be8defcdf2d9fd25a7c2494092c7f3f9b27e5b4d6f90938ce5339cb37c86b3cf8ea0ba6702f2cea903b78a575c0b5312878ff04fab1edcd891ba489f15eba5f5520036b405515aa3250e50e024f3b1b55663251aae2467304dc34a8e8a90376e21a2f709ca6718e38b23772d440afac48e037c847928fc08bf4972b024897da28b6d4a123348401991a4d632d9ff6c66adfd3f51f8cc43a4a09f445bec7638c541c2ec17a8efdb8c4568c11f861de0cf8fd322ecb4fd64baa1187e51986a30eefbf7efb6e02ad186b8d3687857da2f2d6a81bbadf97eb4a6e0a6d5bcb7bd4a349fe57dfffa28ef0beddbf6a86cf9ea4b616d513b089fa71b756f17676f968d315a78beb323700e1fd91bb480155c18d27887ad256bd5d9c598e4599fc5abdbd809e6e3a0a0192de84b5b5a339f1a04a5eaefa0c7f0504f6b538aa03e43437f8131df5176412e7f8702dab647c5665fc78db19c73ce262d168b415d6006a1954f1757d0674c772be7abcbe5ec6b4cbb66bb8ca1c927fa9cf3cbccb76ebe7533278bbd058ee9fda537cb66157d86542855b5ec8b5208487243aa14f41adeee215495a1f80245201291df0c7a7b76f0eb6a81eeb6a786f402774092c45d386623455717e6b044ab178871b9e548d6c476a74b39030f3aedc1895667b25ff2526ddaa6cd419f3fc5f5fddfcb548a1798b384b25294a208345abd595bbd58dbddff062fd66de233718a0dcabfac953fef9cdeac2c5ad0e7183ad35023aca07fd92c2c0f4460c92e96eccc291ef6af1f316048519cc873d3b95224732ef644a94a664887d25495edd8634873507a814279c88d021e6f4204330d18ec96a08d7c5696d9080201b8d0f981be8c4089fecb551424f4425f14f4426951d0e71d94de1c6c8b4a46e656ce3608bd4021f406af0f07a5463ed3c0770876446ea36ff002b7b0dff3b423507e0dc6ad1c4c2fd0681b85af51f536d9fe01b510e9dd619889d983489b2e20c2d5559ba5970a1f95e975275df4acdffd91e35b2e9ff9d5f2ddb30177f64bf865e2e843a44db64a4ded28bd3b7c04e26769d3f55571215803915e2a2d470a53cfddfb6f4958a4fcf78a20d04b7577f8c8b99c8fe7ec1afdaabeb7e83451b4ab7d787b9a20c01daa5fcd8387f7bf541f3ea01e509907b4113a4369525254095d5241df473ba025644424404fa028c4e8acacfbf31f9f8d530e68111a020afa6e08809696a1f7e9daf091ff871bf79601bdb8304036b47a7f9e66fb772db90450fc754ffb0fa118d0144bcb9c82fc65f4a06041b9b2da73b3562b94d51edbb5e8be1beac99154bf637b31ba1cc9b7b6d11195b6e1c98496c11f6c68fbb135da62c1a4f467204e32ff94c08d2e128bc4748e0c0b951093ed691b9d437294a53b2ef6eeacdb90dbd71fdd1945b73d9946df69f159fe3952bef2d97d114db49a7d57192bbb5f89f8a1d53c4526cb37ffbccb3c28ed5a7c76dffffed99ee6cc6687935cdd659ef3b4e80ca4e08856f3943cc5918a6816d0d2055832bcbc9d5335dc39e3edf955e7ddfd4eb4ea360cdbf6a06e3b7ffebd9e71ffdcd6f766454f935bcddbfadce4e1e9bcadcf8d9dec3395965c1c510e4af8bde1a49cc61edd8743bab0efe70fdc7092ad91fafe2880ca38139081e1483671f7287a4605dcdae59dfe230a827ffed2f198c70df08fa9ea8f81bbc70f476066e3b31bda0cc3ddb35f1c3b3b8a84535b3aea54fb1231d57bcd7b2a20d7cc34dffbe98f67332ffff24fd47578bd7d1d845e120dd1342d2859bbe470dca123c7312453d28e184754d5fb83f0bef03bd54a12cda9ea3b7cb1c804f9452648f2853ad596f02bbf48a2b6166e704f99c597cc6c7498929bc4e9fdd38afd0ec1755d6368c837b6ff05bb755da320584d1fdbdf0253b7ae2b0c9b93ed3f00dccbcaf617c04b47f2b67f0082ebbabaa00a7ddb9ff65bd795c6ee2566fb5740aeebbaf2e8117d20f863b1fd47fcd6753d2178dad8fe227cebbae288e5b63f05bb755d6940652bdb3f046e5dd71936fc65fb1fd9d675bd812bb5b6ff6cd4852fd8d9fe2082ebba463939596cff0fbf755d73f8cc1bdbdf836f5dd7a8df9964fb1b89bb755d4df02cdb7f0251b7aeebcdd7730fd6f64f45dcbaae26b80cbd676bfba321aedcd367fb3f8ea15fccb6fd3be85e44b6bf04bb755d83ec205061fb47f03bcf6c7f0e19471424f904b77f11fe69e0f367fb43807debba42ad619f19db7f03de6978d2b1fd65389bd4f6d7a0e1361261c7895bb67f86e0baae3622ddcb6afb0ffdd675b571a18c67b63f06dfbaaeb6ddab4f70fb0bdd34f8f4bafd836810fdc8dbf6d7d7b7aeab0ea01091ed1fb3ad57f7e407ccf63f67d8463f68b6bf695bd7b5060e989f39dbbf5c897c907efe6c7f58705dd719e38cedff32410ab663fb93795dd7550713a1a9ed3fd2e0915db6bf3843836f1cb3fd431bd1efc566fbe7185b996bfb631a1aba82e4953f7fb6bfdb64eb6bc6f6bfeeb24d9b627a92a961bbb8f2d8b98495d54589628be2e50e1f24bcfbf1673585708e73f1a40cbae0d95e4436dcd619a0383c2edcebd563a1ccd51c2e1d49e27e5a3c80706758705185c13a6362bb2d315cbb17de8dab1a2abdaa0972f5882a08d6e9f29be3e23722e88b0304f2c9b1113cc5a048c52546a587ab4f0436db5410db94173c50a76f3582643532068f0d8b2b9d0ec4e830c1832bb9e08c7421b9fe7eb9df6f0c1e2727d04ed4d5c10a5e9de0333be87e30b6a8f0fc62ba2b2b9d1e3cc192c44ec4f5d25c61b158cf10178ab901e9c46491a1857c3a38a7edaa05aebc527441382c4e1f1b16ecfc6243c12fc0386be6e4d1bd6c9775851e9f15bab410c3adc083b142558b1d04b1a0af0d96569edfa90117b40ae3e3a2cb132475941d5fa420f94285f5254a903c5de66e0c2e471e3d6b68ead86099f344be569e8f383f563db65128d8e3d1d13245cf6dc410cc412c41204f70e268abf3428feee5bed176c685d7ef0c103d50827666bcfc5838b27bc17eab1c3de7afcd961e9f0e5a833728df0d14f4fcb20eceed891738595ee0e0f400853ae0d617567e557e02b21ccc8b9f912a9d602d4e519a50d9f510d3e5061c0a20a162430ad58a3441462c615080b97291c38b983a5ca4baf22c6047c20a5caed8c951c9912cf08ad71c0f2e1158af023b65ca64d932c50b551ba9b185fd43c7d3947032921c4c485eed8fce9f13e0dca25a50a148e9c38b885e9a381141218c6f2a09162a5052211f7c8bc06f05307fb666bc8002e31af3811f7dc0bc0066cb8aab22641c8c070645835483ef6405a9f4e8e1b952c2ad058cce0c0c3e42a06d7b7ba0acca34f9486ed4c282d46b489fdc1b2e920b1df10d0ba90e537aa854056bf0dee499a560664a1f1f58807ce131b4040415a9292c2b27b4d8d1e7015645aa604921cad7a64899524b1136e1141cc1b6555051b6b96d151499a8110fd612c105172a177ab489b3239f308f9205f7b16427868d0f1b2c0f007325125c059d234707e5094c982c52b00f641e3e2c3070e2953df8e5b92fe49edd6d4bce61b5cacca811d58b73cb2235069fb1f1bafcb8d2064d1f3ab07ca3c808057fc9894eae0bd80a99d4b805639158baa010626141875892656cdb1e9e2b3c74c41eac8def1963785529230709d1a78e9d29467038b9e5461e1653bec953454432d8c9ab8a4c6a94825788fdc8f3a6ca9230695ae4c22f17461da0902d52eefc294346ea87332932eec0e4b48c21d18ecedbf6ac80f418c5307b60c58ac79d40ce0b161c2540bad418c096be4985528c9c94c8c1f3c54b8cad1645388891658c1321515990cc2031d2bbcb881280282fe0ac7af4acd8725242c5ca4c941c983025d89d25fd657e0294adda9d06aa29283c3551be4ca9a94a349c84819b1c55baa2e61c6951f327b73dbdc605177841c2c3042c624c207306098b0c78ce97ba2c53ea8f4c48923d1024e1e9a9abf38896a3728b921840a6ae0aa8489eed9ffd0b98218c6643292b757eceb28d10940d4570a45d68feb89119d905e96cc49074652891608921010384e91801124192ac096c45478c6c302283c80906194646f46c0812c7c415c0c1a205334b9e80607441b6e8a8b637492243562a292aa53c9016096334554603121c19f016244788b64c0585b016293de74b36864c1962db2a1f4b76d0b6553e7c604027a4ca00853d2e5401a9b3b5a20697609a24ab9b35566bfc497f194eb2e6b620b1c6fdc936af3b2a7475e123248b19193b7c590e94a75e0b0fbc30c5cd6b4f09c465e785e094d612274e270cb1b1a70e579e3b4fb89861b63fa14366a84e8d3ab8d812a01d093a72741d124cf79c85ce10d30996f935521aadd51e0ddbf6f6e8d8af6d7b7b9468184d88fc54e1e974bce989f9f59122c60b90296b6cd8352cda904893e3277e409bdb56ddec6c55764687db56dde66cd5fa5e6434b96dd5ad8d7bd0c373c64ab06dd5adcb2eb7adba4d91fdeae01e58a70e126ed26471b375c9175cf022a4deb6f7429a3d6edb7bc10c0d8b4326585034b6588152e6e92a5c72813f575a5c5b4c52a053d300151a5175b0c4c8d3c462d991c2102a7fb6fc9c99d1686b42254e40a87a5aaea480230c919ad51ac265851b50c008c920059b9733b916e60041009d1e2538b953029029293d51ca0aa20e4d4c0c4cca1051ca1151ca92520a95224a563c12565f643d2eba5db46dcf6a6a8bdbf6ac888829877adabe1d2fc0f892e06200581028615fc9da1724d61ebbdaf5034461ad394a6b52733977a4046b8e5a2d68baf4c801c4c3c29fac5a199a18bd2fde20c9d54ad1c468d21230bc5a399a186dba59b0fc3152535176b12fa0386278b89aa31ca2d454f8bd554afba8081ab7edbfb6ed7189da15d0b6c7a5c5deb6b7058f0c3db46d6f4b9acd80d2faabb4462a6d83083b621ff519a1b4462ac66d1046e9bf041c209079207a0f69918921b3451c5e6de83dbc87b4c9c3046887088a3668780c6991090cffe13fa44d191ec33bd5ec976288e2bff835c02ff42ff4ee3234ef99ff85da1df3e90bc447472e84867fcfd797e3c994ff9ef788d62febfe3ca7f31906391abfaf5a3e33cb9c69da3d41b3cc1dd1f5d9d1c42f1f0794651a84a11c4975fce4487e579fff9c8d07bdcbf9e015b7c0b68c2f2f8ae5f1c1dafe8ee54819cabdf7965cced495d3dbe5bf2c7c1f861675007b0c7ba77d659a0098c343dde733f7278ff2a80a14e577da3955efc51803e59c56d081bb2f900353fa41a41758d400103ffb59dae4540391de5feda278976e3ace918a3ad03a2dea403bedfc4e4e3b6887fb938310941675901d87af5bbc73d087f7f0eaa5327db6e36315b0d0aa3f81787fdf89cb73805290282053ce7b09fbd3532e776f2e0bc46c06e2ef6922c4cfd2a68c82949651a894edf546b175686c00004000131600002810080884429120092345d27307140009599840745a30164804712486510c04311c840000c22008024000220e31a318d50ed7e74b2d240f98433a9bae8e5b869ce533a1cb90629b003021a9620d97d049c5f27ec0a26f469174ad554442bd56dc7fe55ea1bddde60a581dcbdec3d7503759d108bee1e274c9be15f71f235d4614ab132a9c5bc6be099c5bcbc0559185be9f8078ff524537e67d56630c77a95f6afab4a22880a996dded1620ad3fdf301d5a14cc044306ca4ed531c4c3d283629d2450139172be36139cb8ea06c56c32d133bafaafeaf524d9329f017a7428ac5f4584b61b6d98aaf71e56fa8c2872120f358c0cdfb5e9fc55f7152265b025d9f59fb872f767a6cb9ca2fdff49d6bb9ab10052f4085d716eb48f0710a45ca15c4dbecefca9e858a1c8d36476e2c6254174e2280a5ac58f5ea382e4c943ed0aa83f3bedba0e508a3ee927a3a02702546053bf97296b5c6783520c1161123fb6a3a6159c9a4403ab1664f5f64539e845be9604dfc42b7f2087827a0c1d7428d826a55ed131b6a237e61591fd8cd0a3a9c8999cb241cde80a58846cf0a1d7906e6245233835a2e992ad00368c68595f665d66454ec82f8293b12f4e04e7c157f52bdc61c148a59a7f226b0e5cc1877ea382fa3d44e01789e4d2283e063e4adb1daccbd2ec126c3c5cae2b0e258d7638f98aa3392be35813f34b15efcdb6ec95c6eeab2555e688eaffd71b702228f6c04f78cb604022da6ef2601c1dba299889acc6ffabc5ed6e3e9d8301809bbe0945d9260aee9227cbe8ed126baeb84771ba1e793b7f4f55519977341d9a14d1ae50427448ba308b56dcf9cc7433a2689b50cd4e19ea45cc4e570e94dc32b99b0f80e9e6b18945b24bb99149751534bf0b1238be72c549b77c83232ca7407b1d81b41a44218a941c6cfdb623c2f62e75cd28a8dc26ba023e2fa1eae835d54d4ed1ad36393c02f5cd5cedbb82c92b37891555ddc395e61d455599978e9ee51444adbae4e403c559b1c507423ca9e82da348d4146c7d1c31e256c15046b070a56e0fa858b5f606e71c2021cedc1f3b5d06146b27a81940431d251940cd01a6e09ecc3a805fcca530e9ec9d090c273282b180c2225c1191618ed2ba1cef22660453bd4e4e8932664235872bc9317b2e6490207d06141821aa7c67867a59b0a7c7afea8d821f78c8324c5a2f7f655886abae281881b7eaddae2e01939422bfe9e92c51c42495d5fdc4f66fd3fddcebeaed14b8afa2fcd804ba902b1a054d20dc1f26facc2992bb0a266e6cb133bcd28b892dc623e06a5f7a9978b8f317e04fc7bf28c78e7c9e01bd8929e68dadc2805caafe65fd0c743245d1b924ed0a60c17332ebcbaecb9822fa154a702fab17e28a46806595727fab8ce96554b897d32481f4c3c8ae78f4a3b29ef9f1ee12d6795df8d3b86cbe22e8948b5263e529d8b2dc48315bc189ec69b23883e2c190d7dfff63221d56cd34456ed90caf9de818e260da0b40275deaf0b8e4b254f188f03fa3353dabb28f5352c2f3d98e218d0a9d1f641360b0fd5e392af677609b00bcf78018fad3af858b068cc9a215e43263e0b55520b736ba6f1f42cb62f99296d26dc271c5a855bcec010bf33cfa8bfece32345a6777966d02fd1df6f948253829f3f15f8ce0b2578449db122da9b118454332d9f47c978412651121944debddf272979752cb05eafcba66be6316fbeacda4a6c9c1ee81bcb5c85e7cef37fe4efafa10aaa432ac544e8a78ed25ebc46fc155157b3e8c6bf6ef2d8d498c09334fc0568fbd379a14b72daae7a3e27f298dc243e4bce9a3700fa323a698571c935a9f3d8a4027422abb2f13ccb42d49b0de1c0be9178b267afde156aa3d455d1da018c3226da687649b1179b6bd5ee33ebb9422efaa9877cd7a98f5d4a5adf613122ea397b66199c32e4be593722022da1dea26e511d5a15dbf9be7cedce665a78ac0cd85dfee54d171c4ccb43dd4131a0444a063759c9c347056e97782c82fa5900c256161728376b8faa25e9f10ffd8530ad29ed383159fd4c4b5a7a35811e468d7252d6598e1086b1d62da46914e7a4f292fabe2b068b42871482c9b00d73db9756e4d628fa2e9f562adb87297c6871a87a3820464a9456341c5717a925348bfdc9b90991a0489f2d705afaf1887b9df1d7031225cba5e9b441a2be0a370b805e4487630c721b03aa9073fcf0f71817e7f3ff74404881e08eb06d761f94d73fba73c122ddf1aedffee5cbd50d81678aee7e164d7ac2dbcd843b8a80d8726ed3139e36e7e6350f5e025d9c94f0b3a8320ee8d9f271bda8e6bf08c8770b31c5248169529f6ba804e7a05ea911c5d45a6bca6eeb3dfadfd56e36491dd8c0ffd8a13b008a1c31ce0376d066dee3ae166637fbc2f19af7eb85413c72d924dde4a4871d3312683a2f91172091df9bb4919f996bbe05852e7703ccda08e4b644355192a0c81125f8499527aa1cd081ee29d4a1a90641b5b2630fe6d068af09024f0ecb910674eabf8a4961d4db21424fc55c95c93ec1da34a8c7179b7d134a0c7b2c73cafe4122d861cd2738cadc9a2e2050013b8d92041b6eeffe6c7590f681bde85cabb229167a46c24e8d03f7465538cd473e1d442fc656e54373cc793b9a1049ae73be630a03ce2f3000487bf0e54eaec3aa8a29f9a7fc01fe6f0b320306fdc85e3b2dd65341b2978a07a1c86c9ce7a9cb60459b734ac82bb250644f6249eb57150a77b63d3feb93a9a7e48560fe7420f4e0bb8e40935ad9abdb18d67602794ac8d132b9170d215631ab47a4299ab6e661e23ff0c2f92bb46639e36773c5c4dd4dcf16401ac2a30bd9fdd6c27d082cdd525c5a0a6b9e95716f8468867524c0e88e08ee9bd1d499f7c5915df0b3fe01ed28b67543e0729b50022277644739909a270b74783fd49bfc79acfc4558dafaf461e3d14ad7d3b404432f27bd3716c2eef6e1abd3568195ac573d402888fd4d1b1e7ee4d6e181cebffe7041cbf01b2fae29480798b3b80239294087d0d0ce046cabdde7bc9a17a197f4b975db2b49333e6866993dfdbaec826394669d824be03758235cad558bb623609c6ce9b564546fb11bd763f36efb2433fe85b3cf48247ef5e225a9d46eab213239fd409e41e999bc41287e10715364b066798249840afc49e4668656bacb0ef9ce6a8a8f9d1c1b42fb163db8da573aadf24b15ca8bdd8866f213c5b278a03e8043bae436d4661d8abff4a8abdb98036790be0d57d819b2968507f90faa5635c991331cad7f0b9ee6bac2ae29bb307a0a9037fe1fe3fe4fdfec0cb9251007df6ab14a05f4ac767d605c404b2b82812878d57debea002ab49e5c541a1b79f1a644481aab6300035a83ac5d72bffe2b7beffc6fe883645224b27dac1a9adbc663b01d99225a49253ae7a7fc5c420e6d2be2e8ad5d764476ece5624d89b6bb29f77679150c1c20530fffae3e4ad7fbbd0c354b692d0c35959f9b93433086699debf3e84d5967f81c57897d6c05be7e3171df02b3ac54f37eb7ac593e16b1e3a4502421d278ee242dc2665f2f3a796f16e416287f4ce2380abc7720fa3b460fa1a8ed91cc0735ea80ae095ab05b2b6047e657e3209521b505aa6a388208730a2ca140a251896b5b86a55799e5c875e62de81d677ff459f82b58328140dc19e2c0d65eef53d2b8bb86fe8025301811f1fdb2c86b660a4db4486802263c9ab974e57adc92964eb54bce039efb2c2fb5f4ee1714b5301d6cd6080532328ee499b08c1f4af902238b64be1b37d4a9aebfa18fd143429fd0818a06e2a85df841c1042756a2ed9684daec8a0b1d83892c069a7dbc659e7f271135ee73ffa1ae289107764a20538c60febedb3c33b1b34589dd95bf273d92ab99e584cd3aa124df80c3a90489b3ee6e3a8f51e83c19cc88ae3d6ed2e366f488461ef6e2e8b4d2af02c0fd24af17191f732bc141558c1b0692b926c1298dca271d1601a83e5628a36c59fe4f7f4ed26647b7f7171550465a4269fb0e739d26e3cd0c18d8a5adb3a31ccc7913a9d3525409f9c842a569570d7f9b49ddb958cbdcfb6ef50b45199b6eb33df7d5bfc8f64e0e0e1dabfc809423e94a54f7e2185c8c999d401183f2e6984f236cfc25214ddc7ff2ca690ce6d46b11e84a6e30948f5cc7f20cd6275ba4ea6487fb803a4e227461c784fbaf92a146748653af06eadc67a4131d0c67a137394d55c2e3cb3e6cb4c95093da6bc2d83f85cacb2d1d86b9b17c46896819aa8cae0237b21ad1223be80f6528cd6c83ec80b325667934b35bec094bd92d4a33397c693602091d03cee8e8e357ec2d67f3e949509f4501c7ce1815e60a5127556e9f06500b53c8dfaf13892e7856248ccbd0f891e066cd41448d7792d2e3da3ff7644876f4fc85ee4a642868c425a3c7622ff4b7eefcecc0a3c2028a88ee6ba7e0cf3fd0852de44e82a52846998446e2d67e4038371f6627e3982434730293a85322d1b5f9f16511658da0ce6f6a806979a274d0e6032ce0ae63ad2da943c0d466650a6c8fab5a134180ff77e9daa552ec3d599119797b19936844bef032edf871ce45111dd145116931cd7b09bdc2e5a5b4eb54dddcf9937b0eeb8b8cc411980c316624282807e3bc09990687570320a38c6e793bef633fa8c2c2de63120fd079405af234341e1bea0940e1ed2d31e8eb57a35b1828f2b9792d9d51a1d9394917fb3eccec4e3ecec2ef4c56ca7793804f6080f612eebe2ee39370aea60e9c1b80dcd61684e8600a8ce1d1ab819468558fdd9198aeb1a26b000f9a290baa29c894e43f17713146278b5e6e597f63d4f06a2f54732bdf4bc67b854633fc0a48310036b1ea709fa6f9f04099220f6825fc1f69581ab3bb1513137fb7903b60e4b37bc859fd6e36b42c63b1db93caa796716f33a209a96e65b38f69a3bc300aa87952e8a1fd6499c24dde75ba565d53f1c60be1edb5b9ffea45d2e0619aa1c47436ab9b9022543fd0ac93108d2897da0d34094c71b53b038409855bf36393001e29e0d7534177c729e74620f22c686ddc394ab45fa51c31cce2172b10d07a9e45ea28f284dac38e809f0ffead1ffda2a748485d38c9229a636cbedfa0fbfef08d3924ee8580969b12d994e322403e9c813e6f4586d67e4a3a5e578d76aa451086182299e1a29f0d8f422ebff9cf4b2dd62107fc3ed0a9b0b5768901d92aae91eb03ff53089c29684391751bdf68fc4058ae2ce110a8963769e795ceaff82ec9ca6eac5eed0f0861c9380a0f1f474f05ed500a25c23aaad2baa93e87a297fd2c5a1d30ad01b810539c67fe800a2e85f614f21ff76034e6655eb23be4249fc277a510afbf8781e984e22f5986035e690e6744529c8f6e0bd825713ac660c09451e2c1e294289aaaf2d1c7d355f2d06f52fb2bb74842b82e4ac8458f24c256d7ce4650e233632e06af4f5024333969ae3a49e8cffab1e8f42b9a1d8de784b538044df1d90dbdc5709bf37a2c2843d5b99bf81994bad0f85dbff61b55fe5ef3a466a36d1c8a3ad8ea36eb897efb0b8aff9e63417593c598af1adff2fd3bdc6c3708335a1c0fe6bdfb53c76209d9ee94c7c838e4099af7fdbf89b29cf8cdd4c23a5154f28dfe18c26977f7306ee8acb9db3fac924f11f69fb7035d605c0534e97365733207382e493414b8b59e241bd860841fe3e4329351d3fd44dd4b0698463418464911a83cd6aa298abbdd00860456443cc892d0d30952f90b605bfa607c4932e8885832be2402e84c00d484d922615dd6da84e4cf6337dff208e9f7b1930c417b1c6dde4bd2b213f3bf2252f1b468f415c37c599cec961232584b1126b446d5881bffbacb3bda4f244f73bd51f6d5759251262363952275a124cdd92210b74f072f8b08006622098582cf653f3717fdd18a9c1f0528cd4b76c1d4a0e211882f9082983bfc8b6662b67cb17924886c9d6b84f18f59cf03c23f8787b8fa61a8c4c9e946f9a3a8388677dd6a4b2c8ab3aed1ee18228f239994e90d37a3a8e26f1005757babc26798924848be3c25aebd503f4d2198e74d282ab06620cdb234977852de0c4dcaa071879b1832e5155493a3dcb7e8108c7fd1fabc173e4c3b6dc360b8c1bf0cef1d3600ee279e73d009dfa1211e1382866053c5e3ee643f1ec4b8a66dd797ca82859cd0e21ca1012b6e006597c5d9edaf377f9330dde3e8e5b7f46d7d9fe1ee23d440a5ebe408211f8d50d21723b1f3d11253ef99cc558760cb026820b30400f896d0c11a77f9f1eb4151208063a0f4171211b2e5cb14469f3b19dbf778b13203b3c441b743faa5aa69ab729dfe636ee4759081534a17cad1cb75b89b1fc8e7e45ec0560cceaa4384a7c9c289b7e81e07cd2d949862d9c46aac447d9030de21c10f4be854aa090dd29eba0c48f8aa8a14af04de0e095f405d339e7fb5d76a5f9188e6e55527c00b94f20c32240288878468a5cb31c8dc7be384cd40b5c321a09986d60c540f64e2789eb378bcf200d86544ac2702f10c028174dbd19ee8599b8e27b90d651e2d4a2417390851d1ff7b886b3bdc737c62a382774bb792ee7636650fd93e1b21cafd3a79628a9c4ac6702f6c4a8029049e704ca19d84bf506abfe0b21f50bd6fb478421b1ecde21f062c70a37a2c3f297f6f65c64435cc041e26360d95a7cb285a0b21537dfefb334c4502c7ed3210c590a4bcdd7104e0569d56b14aba1ef57f644361067365839869cb0c72756b89d6f962ce7d40e530c3fbebc126f48aceba1b21b0ee716fc347e1732ac134f874f085a174eb7d7d8c0663385dd1d3468c0850ffedc7eb11cf6a1056210a6dddefb3430a221e31c1c067e1857036b86759321c32b1f872ec65fd848e506a1876ce1dce3404b42af626c0acbccc6a65ba8b636daf822f88662f7674e43f4c29a42c54ea4c36549e106808606547f2d75d570d7bec0a2d570d73ac062d55039b71deca03de86f868173eda0419b3f8a06a5bb511cb103853d7ade62da5d1d3d882dd9033038d26ae4a84aa132ed072f997c404a2bf7aaa116c220c334df5f6639864b0943a3b2056486592cb22ce787341824404eb29753222b146577a01c345765d21efc3cc706b730f3bbf14f1ac83e60b1e47af75391030d6ca7e60c71239aa76670a345699defc2887d8c81ed60bea6d04ba92251d61a89c5e7a599d9ea64ea71affbc089c694f1b40ae11609de81aa1b32ebb7206cffd23b88de016660e3d06e8a211eedd36586d1320b76b3d1653619bab202f0d537141ba810eaac028971a48ee7d883149b8036866c5e0675c908ff7455468f7cdfb46cab82696232701e0d3f870bd5c4475bdf2815d943666f7bc433924f1adca0faff60577eed0267d8c76a9c498630c28e19590f40d5aeaf5592f6fa49a3fd83528f0079f6442655afe6e8eeb6c7f25e824bf5b78d8b4e62b3e2ff6122ce5831d42451f940ff0f03a15663b427ed322400fe39b90204b5a68018c9e4488e3d74ae93829601a891e7dd75ef3ebd1c97a17aab034954cbfd0ac017f564348364d0c34a69e6c8a66dc80c2ba0365c08baff90fc334ce69f736a9b9cc5d417f2213cb50b5c1582233daa072c7bdb7a947e08923b4f4d62b81f0b1127838e1649f83069e1c8bd78524623b3fd91b7eaed9d4fbcea22cffa78c40cc20b18055174aa6595eed61912ed9f33201cad52ea43d9c6d9d92cfd3f90210009ce1762b99c18224afec8012d91e63c8699230b7daa1bafc117c136cf6ac9f0b1fda5b0b44dc6da3a3f64c61daa3bb79735b4a72c847b1943f831406a77306ac23e99eddbcf38f8ea540cf547c086df4f1e6ec7bbdf0e903a81f7cb452d79c756fd20003ff13cc822ad7c1cf281821f5cfbab4b9cf5639440844c39570c0cf61281415aec1d092014591164f6e849c1de05f8c9f3980c74115635700b0e2f26d31f6372ef2dfae039b215f6186cf0fef8d677bf7e8a64ee718cd69df36f640678b78ff567ae2b9f7f1f5639ff03268094c99ec7643133cce771875a6b4022e6e8d63a7f843d8a0e64a67554cf1130d9c8dafed5cf129994567d5983478e9ef8ee779e483672071eb507636636ea2c317eb50780d379540f16398c356254abf5c8860fd2f3b7855c72b684a5aedf5c417fa3ab66f821afda56e4133e5b8df9c1e266d1f19f9cb630d5818b5c694d943034b6ad2fd278e8bfb844b37483e4e41c21defcf60cc8787b343a811f0ebc79b83f8f7def41a96cbfd2b992c8b1861e444c1a405d4aa3706851fc68f4d288596e75fbbd2b07b530d3513d1317b16dfd6c871f52fede032f1480f63c4d5803a42038acc482ba822c604fa3b837cc938f28c0f760d397f0f5322a0004546c2308d09bd27cb07f05fd1843320cdfee822a1be0ea0a12cc0bc76360ebaff92027f06372b5da09a967b80eac2da55e7c43d2a47f9417e0add5fd4651eb48ea9de85f9f595c494ee4cb3f7b4479b4afa5cbd2f08e4cc46112b9e5c1865c2260f21c3a12c1de4ae21c03726e44bfbd483431698d010cda5463a3f0ec1e7af14629a4cfd5670436a8cf75931fbc38b53cdf1b2a9f241f8c0e0fe1ffd2cdd57b71239b45bbf1a519b253c5d58184ed9654c496c40cb6fcf90c7e626d40393b7eaccef77a65a0f2db2e3d192e626fe4fc9772090f8d39cbb8ed41b2ba9249765bdd04d259d60ebab1887e7ca45827a04f34b8965d249c142b2a38889cecf2bb31ec14ff19524ec2782fa050f85ef59beb499837e3c79a53648a663394069c8364b87dab4e755f0b6ee981da91ec1b10f42ded265ad5cd9a1246462a04890a1e213752ec0ad122c29ded61cbbd9797da69651cea9a3f9ce1d2662d31f88c16f7116e81b3df9bd6d73802a2a89ac7036c89d66e9905e8e270585772741698abc592967bf8deff9073774c6a0969e5e5c46a0906df3823e6a8caf643ffa5d1a6bd4062310ca4d55c85914f014f81e9334aaea0b0546158de22d7ccc12a8ca3893910ab30ace5999323d84ca15fe75195d223be901890fc1d8ae69fbaa2c80c1c40e034eafb815b51bf076bc0174cde9e3bdb71fe796b57be1adcb0fc21423cccf09a4223071d73b110990bc78eac132ec6a3050af7ad2ac09499f9b7555461d66bb2c882d879ae98188a5c717018c2f80cf8a011c30ee2d2c563fc1622899a89928bc377fca40e12970f408ec77eb76a86e45f2e329ad9410a915e4ec2054c8fa3d15daf6330d5f319bba6e3be6356ed8ca5aa0a8e8ce3d909e83e1befb826cba82fb06609eb4ca0b95277cc864abe15f5bc4a87217797002e7883ff280c945e17aa9bc7cc3b4fba9cd10186ebdc7c2e5f95cf9da15e26b30348be9a099b91c7f44b498117bef803f51ea01164b233758c0624c6c4ed913b9bfa362f6d2f828bbb950cbc7002168b21af8f4432d681fbf4367bbf982a99459c3e56b45f0dced78ccb2e5bc385060ac8dc28b0ee2f83a73d830184256af963d4a63f79fadc0ea45c02f5deb60f2cf3feb0f0b0d10f832ec6bdf29bcb8b26eeb7e2695793a172d21e3cf8fd1a35ecdff78516a5ed0d24fa4e5792c15df7758495310d132c25d95c0e0b005a97280b6d51013ea004469ddefdc80f55a41fe05d0217ea1404b8a8b206cb1efb049430a6cba0445a246bb857219bb56058146a7ad4e67141b9f861126a6363bdbcbca08e2c024490aa2966daf00208d50faaf07e5888f3bdcabe7cdb1bcf38bd172ba0abb76dcd3acf6301f22e1de960667ec082001a3522b5e187a8eaffb0569a3d0a57b4bbb45358a1f2dbc560ae0d1ee11ca3429d97a0db71be29c079126d1bc6fc259a3c7b183b1adba9bce5b498810f449baefc2a1dd828428af0747e44849b51dec214e95e702fcad4e347bed2f66cf05a66d0432fd74e478bdfe8071f635b3cce5ed3e9610eab301de821ae8227142bb5a00917e80494cb0c07e79829cc372c12afb5de71bcc30219d1fc0e7cf37158df2b413c830ef03d663cf26ec86184d89224d73ccc8259adaa4b7e8d7786fb6f4f5ea02b8071157bffedb16a20c9dfa6582486ed1ecd15909470b7343d655359b8734f114f74d7b3d12b2e4214d8b8f606a84dced369f96cd44988f375b6f88f77d9284a3a37a12fce92bf75416597f5a5e4f97d1d408cea3e7608261bcf06b88d4ae200d65a7f089cd2b98f16f7b3929bcbe0202592629970e51bc9c025431732ab9f83e1689e2134854fe5e394f4016a442696e2f588dc790680f23418f162fd38b118675beb5f833ac822ff4cbe65497e4afa9313ff3c0c4a82847d4e2a9e11096b2389f583a2e24a3ff3eaf294ebfc2ef0c344e3404c60c813ae6ba0d8f6d34948f0a016523dc66f933541a43429c42eaf2564a6f2953f085bcec8334114ae15a3cce7ce3f13d8e69fe43722758023a853c817b147ef60a670d7e3ab88217de7ba61ec8d0221d97e4e19382676b8ddc8a280c95e4ced38e08a05caf048c0524dbac39c86ad7ee3673afd57b15a1e4358f2d03913093878ab2d5b227115899cc2d5d77f4bb6625e5219c4a314c49a7a5d5ee557cb87ca84137412068e8d40cef97e7a004640adb58e5d50a609020163e43499a225bfbff6dda7a5dac7bd6ba6495afa0a588e23056127dbd3695b6ae608972b8c996a7eac641c331eaaefe8bb75d741d0913b87a89b074e3c0ed333dc97fa1b43eb56238e7dbf6e838bd645b51365c2520417636670204861e2bc4740a5ca9d86e9e33911dffc5607ea806a08cbb80c58f6fdec0bff48066adcd9ff0d50294b9241e877df5fa11110d0d7b2ef3df32faff17c080097959e7be401ac7a52929ce260b26c5d900463594200c2329a640da9c86f703fbc3d21797878a8c1b38c0ab4c1cec38633ddc01eed92972d904397afca582a0f6a37f80b2420c3eba91fedea1b4a320c6fe28e144049ef62d5cbbb36a624c5e1cb999fb184277fe2992de5ccc3687e1414aa98eaf49eefa15b3590efbe68da3bd0a16e1e8b3427cf5469c553e80148d02358788979508a08a327f89f5ca0dd84708f5426bcfb5b6f5f6c770356ed745242010f1ec11b2b114e86e8953db7b737b68ee54376c31c510866d83ef62af1a21e76c2cc301e01fc16741dcea9ad5bbb589e1073d1c7f2a53c2f1344f84a9babfce840bdd752f08f60421d558a947c88b3616e5bdd16178e7e376f2a3b034ffda56e7df8061aff107bf90d9773dc2d36c79a641e58cba4a027e892eab5b9c106262b9fe47ee1f651953ad5ffccdb395a89df92fca9aa719e3481f4c3c2ae683843a831330f182fde56a60a111e5b355e0285dd6505ec85db7f77189e098507572fbdd98d8b94b927767c7ba886cdadb63bb7bf4602d4d05f8122a8b116f605d2acbf8f62ceac374db5b59e3c12aa8a3ce6837a7aa871950ce4a7fa48d41a2550061a552f7b1d4558e24456dcc5c784c29af1875b98d45ba81a0613ae3e7aacb541f9d482e29b58507e5adb013ff9c26e8188803f88c5c63d719e4459cb1f449a08d3dc8304b9d33f0ec62a898cda29d301c54aced91839cbd238b36ab99055a86f22ffc766e69ca601939a8e019b7a42f7b2237aa4f90b09b61cdb31c938183af0a1f50521246da779640975584bcc3f2ee3009a920e08315e1f6222314dd42160a3011d40e02aff95e6b7e62e7706b89932ef9a0d2888adb612ea6ff343edf2acac3d9fc0147bf42722bb26eb753f0bc39f7d123052731b52f3fa1fc27f7faf317b581a2c97693a850033dc5c08b084897bbc4d5a09e62af2518a7ce8f978203516812940e0cccb886d9462cf8af132706224636f9bc4bd683cf70c10bf0fb2a58ceba04c178a6853ed6246ba47de0298616346f0d9dc3fdc9fb1eaf5f2881e55940d0d0acc3cd657da01cae79377c87a692011ee365243c40d6eb93af6ac3b7dd4743b0208cde29f5c22368e5f03a8b2f3524b1c597aca583d430edd81d9c60d99344a5f3e9ca2aa2133d63d65da562a155fccb7126106aa06c625d016327bf3111d3a76daae2fcd4e9d22e67429e44afbb9bf1dc537848e79dfcee41f6a339468b31bba049c4c2168d60ff25f4676f4b885b006275d3e22ac8e88639a13590b8c7c4271448a35e06f3bd9a342d9957ae85f3b5120f59ee03b0bc18d69182ac3b0a8097cc3f333816a6f2544a2f842c2c77b4f442615e1e901977f989581998dab39c42239a223e72665e3df3701b83c7daa2282faa6c3623777d075d69805f00819a542940304c8634c45ae1d41e925d105db5376d86110111e6b0af1c2816204c00a8e644b1935cbc4f4dc866b0007e03193e588ec5d2befa63564369b36b92a65a15a60fb03ef5b0dfef4081a4fc2398d206957e698a64a4d86b2ec18da7e6d9b86e214278a85636605348eb16022b2acc3536b49af63dd91c0b7d708ab886cb81ea76f9371bb178d7074704835be5c87feda7d90421b81abcdbbeae0903b832ee056207cea68c808d5a4e457386b8ae90d2e8a6f935bdeee875cd25ebd36154298e66c07ab7fdc46f91fc153f787db75fd0387ece79b534ccc18345eada8aa4db87ba80b355dac32bd90c0dd00aa7732fab03392af8ac8187e050da43baa6095fa013aa4fa6649bc6e7b9efa0ed4136bfbd8a6de97e0c3adf5045b15dd401c796e339a4ed406131b5d5055ec832cb28355e34528387d6336cfe0e9c25072a4146698d7cef9d2fad445f6b0da06bfa045bae870da69ac17b3462727e047ffb428e2b0b4b234ed2d89962ed1032abc4e5309960112366cfffa6cee9461fb5c99361677b886b6ab0a17622cda853a4bffb441211d02b78cfc01b428566d4325e32467978a1006d76179dbdc115295f12b78f6a7d774c9f167ac956487c333537246008374056ac80d5f4fc93cf6d57a2b3b786cd6744c6a7a20d5b1c6604ff667d74b1c75b308af25d69f576c6c91ff0fad881b7437502f1b7df9a12ce529a7ccadba9cbf0ada8de5c501d961c90e4e505d6189725bbafe8425e45bd102a1921b5dd990129c994edda09c73b632cccf6bf3f7b5f4e7632acc615fc943670bcc1bea2bf8c4928518a89864127ddb10458f76d5e64a8ad45923b6c478ff7d83bd59fec00c0493e5e868bbb112fce8832071efa4e446b3f9283ddaf15e65292348f664dc123c965336e02b54dd8a9413a6d21830db502dcdd35021e0d63986fb6cb551b50a9cd7545f29310cac705e546e3537c2f1bec306256a15f683211a0e1c4be52611dcf98955e9e83a1d0418b30b4d678bdbf74520d96cb430e6dcfabcbcd97ce7edfe591b6c176f90d0a642f3f285f983778cbc3a1786242d339414d553da4a62e7e8e403d99d76152c97d4f536a882c237f1eaa474d9b7c236250436bdb191a5d5fb9108b4d208da05fc91f455fb91d49abbc595419ea41e943ab20127d2eb164d810577d825af6b180e7a71b59121aa8ad90575c77048505fb8e9f29266f96863b0d868d666c7cf51110415e45410f894a103bfb6d158c2a02e3afc6d8ffb73723f51eff0d6cda5edc6b7cc1aa5ac40ac99631e732052f44cd0db45cbe41089a00248a69f87441cc9cc0f83877a5ed2f17b80bdda935bccad3b898c2d5f4a11102ec69d19d6693f4c36bca031f93468d4444caae08b21ef26aefa7e197cae4cace00c8ceb5dcbfc374451a661d0de39c18b4f35511c570b6cdcf306345d87a1974137430bb74589ae9cc781a81b5939a73dfb29adc427454b08cea15a2f85b4c493b800acc80a18427de4de42932fef99334e367bb58f3545c7b392cdf4ffe0c342742e68d9ca8dba81955c01fd92b5ca21c0aa4e1bf311791f61bea7ebac2c03642ab48689e9d19218fe779280b7102d41e7f1e287b6cfb8faf88e8e15dbe7d8a4c26ca42e4e59d5130dd512a90e8dbc72a909a8edfe54cae073a12029ffa3e1377ba59cac67a30071b51e9cf1e92948ec8c2a66e69e9c0676ca14240e8be7c577357d135f50d851cd7d0f5c9b7416a9813cba66dd03ca250d97a2288f6516f8068e519f1095aeaa59c5f2aa26041ba21458fd9dadfaa11003575418e09728c585d5eea7061ec8b8bd5be9482ed7ba37f3c5047bd8f15efe32b01664e404d27ab7741861e8b23a5ae48530369a91a8b79bb42c390218dd34d9d7cc43f267fad1f714f8e385f0f042a1c87930d00b803eec341b09cbcf0ff58343f3cc02df7300709b96050621dbc422d5b72511f3517f1518e51f530f5c55ec6a057fcac224bd5a5e88f99c40fe9b0c45e88497402fa173454d878b377421b9bc3ea23aad74c7c07d80dedff8d45b80e151f6b4f4e261af367696c34d2e613c76e9287361a54ed541bec37b457c09e0475e6feaf9fbd3e21101c833bd6bf7a90747db099cb9d12302afca3c7ffe76b90502cc2751b5a3e7c819a91c26e5cbc4812cdde45345fd8c633417a25cea1700a619ca452f2ffa0f047e106a2c9239a3088ada15e220e9bdf2f03e4fa40f3d516abadcc6a67f5e75ee85ffa332c3d55290de64f77ef3a7f4862278be0d0efde7b640ae96bd1a9e1a0d52693bf450f75465a1ab249c53cc6800bce6b01875c285357b67f36dd457c3cc99d797bd1a17126105da419c63d89d52d9a436ba0a70acf068eaf7bc56eef84b57f877963bb19db88ac3a33e097160fae1b59e532d40a555f928ccd7b349c9e1ea7316dcf52d9751c5f6b916d8f6ebef106f7e19ce5798aab13574fa17e23dfdbeb732fe47ebe672c65dd01acbf15fec8b36887242ae2f041a99ead05795b1a34c8a37718473e1352a152052ecb70be1ceade2b24189f69f7c595ac06b445e275ed35d346d89eb0ab120efee9689253c9ed6395c801b391d357441978d21494fc2d7c88efa50fb3ef18a34c77fb142e8e9b7ab2351a2032299cf1bf339fe070625bf3b0a5145b78b40915a4d565d4f198ead9f911e6024fa17290d19ca0d37ccebf363588874d03f962090e5687d111a7d989cfb994d0cd867c2d32d31284cf06383d3d3c45d38f0da5972d0a8564d753350123a571931b3403d40ade54dc39800e9cd868384b5f6c22c9eb4a95ab227c0854b8f5a57a212190c8fa6e48e8ed070c83999ec2574c7b50bb7c80b3a3ae750f5671213354706953b0b36abeb96b60320181b3384e252dbf296b912f3c93b4265d07561497153b67101105cbb1719c9ea1d0981f663e7882b9aa9e5699b274a321ee7d786897c5853528fa6702a2386a36f88fde0174819142ed60bf85df3ef8f04831fe9a8ec88c3512dd765c889541dee62829e99055db3ddb966b69c8cd4dd80e794b0d7a63feecfeebb0bef3c7c1dd47fdb5edd9897fdb8d6c30f242722e1be9f2637b99101589eb5fa86434825888eb277d3b8881ca4dfc710f06b465b443cb1d1c21b15ba2bdd8c46ad9afedc06f837cb07413ca99a05a3ec3849d5a47ea8bd8f0119ef252364ac50f326df040b31570d004be1b70650aaab981244487b44fdfb2c99d638e5ba750a8bfd35d62aca728f59717188e45ab8a7b6da8a5981e573bc10487836b20bdf32ea565ddaea0f4c0d40db941ce97174b9b8f52b46491f45613d4c9f90697465443b29b2843153c241cb6a0d302b84cbda7e02728bfb09641edb71e1627c2cfffa2dbf08e3369a9758acd4f3ab7f5eb0aa37f74d00aa5b2dd27d8338b9a7764cf789dc35ff941197c8cbb13f7d19fd6785ba639c6cc00ee58dbb138b28aac859c79aaf288d7e586c911d802745101550064d29f0352fd6a434f28ae7f5826d3a6057dfef131042292904f41bfbbe43adb59697907b70f7a924b39b92405fc2590d50df217c85cb76df8077b66bc470ef948d5a0d6d9f8aa209e5b1dc3ebe179ecd282294d3f95edb69faafdeac682caade12e546f9c7fd112f0721060c03f07a4334c2226b54846fd71ed42174f168d34fea114c4934d1cf2ab244434e1c72c6c8494b3956b1161c30cf5d3ddf97dc51748c7fc8d73a7bd3377c6f025cf6d27a64bdb23a40f103cf841dfe57204d495eebcc573e006b2dcc546603b0f93d4b48f74182b91cf859d72cdfbd369ca95d40c48d8aa1bbf122a37924261ba14a01b9887ce9dbedbd77191ff381546776d5a63e69243cd74c93a00178ab22e40f2fcc8fe6595d2e034d82b2b72a063f904cd2de1434e41a8720350646df47553520cd64fa49718e6a75e34ce696d2d825473bbbf6a4ca1af38f42c1a17689a5a5687da69e8f34a2ff59a9e7f02c1a6ac2dd44cda08cca362f9d99350e4a0d1521f2be154fbde064cd10d5c074199953c3615fd59e009654704b9987bf4f77785c345f97ccf8ba8a85d751520b1b1f6f3dbe1e8dd25a303602060ef8e93833538d6676329dafdb77a2ff2ae8907be05896cc7cc3b6b4315f7eb5f01537920f817621a56e6f2e160e87100d5a19f798f419a7a21215e811c52d7dc1c70448288e77a941cba19528ab324040b903c135596fb66cfe23f67282dfeef970941838d57ecf241b08ed239e5bea715d2ddbba4c1318471ecd80d8f298f8ad9c01095b736ccf63c736db62cd03d0f3a4228cace74a579e0bac42b3874d33b9b7d7f629527ccf35366c86337eed9261b1ebeb71bcd2609b6ca7dfc8fa289a50beacb8378d059de2e8d5d83dd5fa58600a015fd3a368e373c83f0157f9e5dc15a7367295a1f54960a15aff1c6dbe6f33b82a374c365f66dc5e80a1be42eeb0fe3609bc3e5a435d3f1db9373364581cf79ea3cb75a237551de8f9140617458ddd4ce629aec49fa2fccc1c5fbef0da1d21c1c7529838738ed3df0ac9e5fa1473e6d8b57064c5cf2eb46e4e9f797b87d26113b2eeab2a10f12e3e09ad9c65ab19a6359ed0f9d461ef03c05e92a643eeeec1a765d5ea492a1af780b46f58a72a1673ae25393695962f95b77b8b0356fc911c3a5017e89f6d0f48e565c5e4927bcc395c5ca7920667390362bd0ef9951bdc92bc174c2e06dfdd57630dec7c4e71424df0104845e554144a1b6f94c8d8ed5b0b7c2a0f7710c277829b218bcea729ba916366d7549236dcb354a2f4d142708d6b8d56a9900718eead5d8f2e415b9b0b867181b23871ff3998e4875fed9b9c1b8cb26be4b390da72b67cc1ba6c1a827f6a41339e2ebb9a2ef98258979d4e050c2de2a5b0bb1acda1a833ec50dfd847a392cd5600b1f966105c26a186e62ac01fe232bdb5b8a6b151310b4f4adc6d5976b77111f6201e51e625ce9001fe4a24dfd22ac97be93734a131b7d8c401c3ef7a616b68bed3b65f6ee887a54e71273e1306a224a19d487be910cc44f8eda12d897e76ee168ae72f205b0df20c91d8a19b85bc246ff7e7499b3bc7219165a3e02d0f5baaa118d8d779b50f726f7e7000a4ec58e4f676c2aef4280791678595269e5844428f5e204e952ad00f45c6fec6ee7d7a0fe3fe5505b70a33b6a68cfebf1e003485d16c5e9f5461b3a3c1ab924e48823ea317ca8e1f7c4fcef3e52e132be355ffee330a358900c97812e699bfbc1e1d489f4010ac39a0c9f41b84e0f95159809cf790f436534d38d809d37046a9e3332360149395da11c67fd4334353189888891926d9b0da98e4d715018bd023d416661c5c24ede02dab4098d4e7c01124e9e0b1088559187d2e159599abb4b53dcceded091c55ec0a3c68cccb46326b7a529f6f9f3e230a51595c71c19681a78ad230a87247826c33fe1b4b51042c039d048508583634e98a1281cf5e6646abee92947d1df51d47b011345a7b599ad6a377c25299f8146b674610d10a5b40e61330560e345d9e6b7092e4cbb6344c84b5d718f86ef939f68f282c6425c01118c54e78feb734001e847a2d5c18e58868d32009d09fb93bb9d2585b6022da0dee4194a6bced0bc74295b9415214b0ea9a6b42389cc5f35f687834bd772e7cd809063f64f5be16b487ff7d6cfb8a0614250d7dc9c64c1fbb23923a5d882af013024a580bfcfb2f307ea3aa3dc763ea5bc1e86382dd6ef2393f6347fd3500f458130bf1c627ec875ea1ba1cf3a065bd2b778c3b1e5968087dd021b56d6842ed3743325a662f620b69ef35e3ba4d62cbea685078e8998298e82a878865ecd472b1171d0eac192a83c579edd7df7781f6a9150f3be060ae5ddc78ce47a8f4e1f925eba57103701320491f429d43ffff50fde0d701ea73d302835fb73e103a95e3a0f005bfe4c95d9299f42dc1ee47943d4160ec924842e49316e43888dba506661c27a23b7d532bf34ef00f49fb18042fece45f0b84bcd0d48116627f3bb10d08d6833a8f01b2bcc3803a388a3b3037cdf9d585e1da581518bbabae5cce6319ff38263f736424bd2f31226ed2236b28b477ebdd434c92ad79de6c16abe9fab0d296baf358f8b6f3e5afd2e2ad1e8dcf600ba6588746331369f6693f68c9d6eda034f2f5bd54e340f25a367a565db349d57a549cebac48d2bde268520448fa19774d3378cbc82ba8206ebfc34837c7c234ef5176995ddbece9b7c533aab3da80d63585323ef0bf8701bcc25a4e7a3816d0d03f4f85840a27686fac92a2384e048f169eb8aa9453c9c91ca32740eacb7be2430d4f62190381f01d337a22be2f6e89592a20746fe68ffc80c083837ad82ea331cac5a234753883b1d1841b5b0aa4239f223ff7f9d2f3d4d1a9cfd6fe0da627b4fd42d32589f93933c9ffb809e152f2f5c46ab68dce011b81cfe6f48c3d13d973163ceabe2aa7e784a2a113dd53ef94fb177eca41f49cf0a64bb9da8b10f6c2f0ad757d535518e043127c558932774a3e94dceedc490de5ae64c3265d26b9a764870a89d558436d0578b546ee399b00c9ad4704613cef102b6ea2261a598790756b0a222c6a509c02145d2c9cc98d9bfb7727f7afa822a9b0103db4f333bf53429644da627de08e687f7a6fd7c497bc3f9c7e3fcf75a1e3b23839467f9ed63344948263460cd4bc61810938dc34423ffa0bc4ecf2876015d51dc9cc667b0df3bad497cf82a5d4738cfc90322581154bdde09b44e636d1c6c78b359f3338f7cb5d2edbd32b95d8f26bedb899d20be6bcdf4836bea19a305ef174e77cdb69cb3a447fe6bc5a21784b2e4127401283e871387d0dc4a5fe457937b662b512314898d785e6698313eea588d9c10fc66b36bec5ac4481bd340216aca5859585cfd09127ca8fbe82356ef09510dec4887699c587633bc1620c4a3d1fda69fc65db7286dc8ae492d017e31f6111f62bdec6745ee6ffadabdcd531fd0f4c60dfac0761e3afd40819a11404f0afe6ce7e9ec2e68c7528e8402d914b0dee8eba0729cc25a8a8ed9606970ccd0ec4831fb5a6a00434d2c00d79d8fe343e415cf87290b8c2259efb9a313356375dd1a0cae09c3d47ce0eeef683ee5c0fbef746f3c95ab241ed3fb21b7eb22edc295876ad7608cfe045a39ae2abd72e22577b5f26a23aecfa138be4ac1136f557215cd8d588e5e72cd26f7b7fe3225c832cb79d543055abe410fca33807b4b3030a9f1a885b308e424e073e567aed2248d05d56237a8d08903b1823e00d2581f168f4017791a7d59e3cf01ecd05986bbc643580468efc10a0a30e83989ae8790c34c12bbf061578de17a4bbd7b4511eb93a7e814fb424d484c8bde5de52ca24532108500880083a38d0bd93fbd4972f5518958ed4fa14fb25238c936fed0d27d73f7ef7c5fc9252caedbb872ce58734f7d34da5c545a53e859358304a2bc46230159e62aa6c2abfe1e4468fb22f2e092979debd1bde6484128d74b847e44fadf7ca9410c7aef9147729dc487163f7d4709bce69d78d3ff63ba7fbf026f76d7d503fe4b2cdfdd30950e4c1500fc60f3a0c147778c5b847f7801d0c85d33deaa37ec41d8ec2b54727278ebd022d0698291094748ffd8a3c987dd457f430fb403fe20747e20e7fdc75966cb91408b6934ebbaeebae9b9dca0235d34fd23dfeb5492c2212c61832c5491c8c4eba8a78c3c98d798b3164776185ec39348f4b19b2bf63a0239882ac7b6ea2b8f6a353ec774a488c65691f89e469343e72ca2cb3d8d3c6181bc8142dce50b97d4a4f1940832c719cfd70a9bf94b9cf94529cc7c1c4f8b2a8c8c176d5146d48846938c912589c49914712875116694b55774facc2864c906c1f8293abe990dd20dd63d2a7828b003c5d3237f7aaa87bf8783715cd2425fd1824288a86632c89834142780a00179f82bbe120c923bf242ed0ab95e2af7ab03d01a48680d2aa3bfab70b01b3bfdb006ed1d224f79626d2640d726f49224c7eca9f7b8b9659b612a5bd0f1dee4b2b5134eabb42f0dfde7ffbfaf37b43d12fe6989a4fb7ed2745406707e1eb54083cd9ff73d107f37c0dbb2816028230d8ded9a205494b946c236ad33eeee3f7dd78b9fdaef820b8e283797b2d622160debebea5dff69bf6d1a5fdf6d4a53d9867eec7e1fc5c202089c56229e49b272efdfeb0ba42f04cdf021208b5a738ac5f71091a76694f7fc32e0d0b01337d30530c3ad85776b1736aefa04ba9e1de72e64bdee99ef6bc5ab1c3d03e71ca2007fbfd29585f3fa77b9ebf3b8d120448d0a34e084e864056b9103481182b314e969b52d020db2904ea2ceeafa59e05392d9151b9994c50447d8112507777bfc0f7a69452768e2f130a3b1b63031b9b642f452cfe8352ca12a9f8cfed8f56805a098a51ee8ee506ff8b3161727794491fd5941662b91fc9452188fb20c1c2d20b3858335a5e682f1cb01282262ea5944b34f990b012e7873b0bfe82329ce90566dc9d4ee93e521891fd5b289752ca0ef294a28769b8867b28b829f982b552caf872cbda74ff3e706f8cb8f1dda59c92ca8c7ee1cc7236e79c73ce39e7b49e573f534a298d4579d2a4dc4fe7944f9f52cfc08c22e5f93745dcf8d30845cafd71ce396717c3acdc36e7e49834cf1cd3ac584ef9d346d6e6d4a636351c0ed87e90996a13c758a454c45423f78211e5baafd1d0b7b28617e74b26d373f7b5eed2a54170b869cc3d744168b67e36b2a669da951e8a6215af92aa14b95442b12689b498166be23fb6892d0a53b4a4bd46b929d669ec41bf935a892b9da58e14a8256e6042ccafd70080b46fe7adfc62eebe40c1acdb3d7807cad47dd164f64893c91f7ba4c98e8e8e8e8e5654303551b926c433b24ef6f00ed463cfa99278464d8af3f8009cb8a13da2e23f968a3d428db147ad2c31ca412d57daa3eef13f3aea1e9d2f1287c3fc4e6a60e407790ed97e53b0524a29a594dddd2de5f4da3c758b0db687554a29e9e790e2c6eeeea6b81f8339a7ca861be9519e734e106ccca6dc9c10546a9cb5cfc9b79de53a1b9dd8d88c71c63aa7ad486ab4d65a28248e55cbb6e3bc561b39c662b19846439745db3a14eabbed5116d55914d79f6b91ec6a28702d5073f50ca05028d4131b8e5a46d976ea9fc43568ce311d750fd954e9152aba24c9e33e5dc7a541ff2e49fe74b3cec9412eedd365d1a0bf276dd2ca14102122ce001a910af10c587d162a8cebca38b94f87268bf6e9ca882d348f93dec0bf43e33e31e66019ed135568b0e36207617c1269f0c03f16bdada19d5827d9df2d0ed9df35230b45fed822798be44fc3668db98f8d3938dda733179df44f0bfdf353bc4d5351fc69b9e6f072e3bfaed8c854c6dec66c2c081aa18dc5f00ac9c6dcc662bbcac66cccc66e8c2381edcfc9cd14850c3772337d79f22f39be955f8a9832ac72337d999231c8cdf4a568d29b9b698626d7c8cd340ba379b9996659663c6c4e747233cd62c80f46f61144ad50ec9075723341d184ab7141be11e68b32dc66f2d225a7723379c19269e466f2a2438e1f93170fa05cb9999e4093e3178b2e8ddc4c4fa020c729b3b77b58c084ed8c33d0e410498e2fdbf2d40ec6fec1a4fe50f7f5fb2b4e52a531f749ea3371c1f64ed8fd5c90aeabcf6125dc57eeabc5dd374cdb628c542976ec962f785c3c2e1e178f8bc7058790bd5f5b213ab9fde54a979cfbcb95a5dc5fae2465cffde50a11b9cbfde58a0f393eaa1760e5f74ed8c96e7eb8ddcd45cf9e33ced83975f3c39d3ff1043200262ed8dd23a1740f9bb9f841ec1e37d99f1a758f76027950c91efac8ce546318a3b7c480e505d44a321f99fb84338afbd024b2978042915f27d3b4d85696de5f8184b8f2dd486b3e4d01a159f2ec2672a6f3fd152900f20efe7278e5cc32e7d7ba6dbdd536d2ca8d42d5cfa98c90d756924baf18431db95bfba2561a98b62d284fed5faf577cc1f64e18631a7daf4cff08491ebfb7fdf260715b68f67abd5e454250ab91dccab3465cdbfb7985b8d3482bd39e4d6ff3b943c5d541774e6e5293af1cb3ebdbbb77fd3afbcc55a2720c75e4d8b4ca769c2a48e67a3e7864d7b1d33c8ebd9d1c7adc87ad3c67ff6cbf933bdccd61afd8375cc37d76b2cf3bb8d34ed3670a64833a74b8efe898e18231ca95dff21abee33c6e75af39bcd3676df92d9f726e613d46ef183be764f5fe393f774da3dbac92f32eceeeb8b6aa99aa3980dd53e7ecffba5d2e5a15697ae8a89820c061441966c600f38297192ad10823b06180c8968711b6175c210133319429c11815a830c410d3c8227dad514f3a758c53e761e02bbbf7f65effbceebbfc7f7fa53075273776e7e1e04e8e31de98c325b91d0b6bbb7d7aba4bb0672fa8c1411b355c3aa358dbee137239de441e5f7670ce39512d259538937a761cad46895aca19669832be9c728b2fe39c6106319a9db3c1f9ad4d8d6edb91d47711ff597d7719f7c1d16fd07e770f0d762c4f7ff0a36a7367f5dde6b1b6b35db5b6b3f52307fe0085748fffdca65677c6545c7768d85240b4df5206e8eebec15ae7bf6eada9ef07ea5a8ba4ea565b13c1c121e7f10fa177f88fc92e2448e51ae5ad9d1c24489c9d5b236a3f8d61c54886cd08fd458e5f638c4b35f29cb347991164597ffcc6270982486b5b197148c4c60beefcabd113688ed808e88ec32a6eb7e39203182a4e61c820c64691134838c91205164b5409252faa382b065ba0608b24bc5a95c400c5191e5062054ce860797861cb152284b0228bdbf74809893cc7dcf0f3162ef864ffae148bcedd7e3cbee87283e6712d05e484ede531b51203f05754a1e91e404dd23eeaf5f28f413c9cc7dff10b8bebf3ebd3ef0414aea51cd7494e4a89c19deef1d73e00f40ee701f4fad54c13c1b797fd43f9839abd146f5070ffb9b72688e0e07c950eb773fded6790ee996fc38c5b234f073b83196e5833e8a07f5060fcf91af48ef6f108824d7d760f9bfe41f58e5eb50f7d9d1963d4689b71698e292042441d6e79532ea12a73ef4ce9348dd591c50d513a9adcf0beb461c69531041bd9714561596d5e6ece5b6ef4e40b63764a29ddde45377cc290f73997629702703cce0ff95e072bd1f9ef71b0922a433ad853928393d486e1541ceffbedb7bff2e7bfb3f90d874640eb9f43f19791d17f2e211c44f2788f5ddb7bdf30ecdab0ab013a9ff34370dec34aaae060d73624e7693c0dac440757e9b04b48e71252f3f46b9e7e0e762900e7bd776d7808ce7bae213a9ff33a3898c03e4c83c6fd242ed4bbecbb6860d7ea5ddbd3b878083f8ec78193b850f884a1ff1b4116bb1480e35d3f04c7bbb0922a43aeff5ec90d9c0448f2c87fdc34e4fbffc74a5c98c887b16b854f18723d7ef9183c8d1f82c1d3a0819380436cbceb5d58090d4c021358d84bf84320d7378c46d7f4dfb01b1f82dfb0c7555c42e86fbfe1126a9e7ee7b0cb6416fe6efc7f351ec787c17f9f8d8f299710ce0fd9799d0d0b794f640757a19ff33a007826301c1c9c9d07004e82f33bb84af73a5f922a433a8f833f1caf040723f95ee777de070e3b5807bf2b8c45381e7f03be77619710c61f61ff1f61bff34c60dee7dab04bc8f35cbf839378efc2556ae8e7a29ff325a93294f31ef6de0606afc4c3118a8dcf79d7fbc02107fbb8e1de781a8fc1dbc0e06f7c036c3c0dec12ba71e323ac468d8f3911a6b37d110bfd625212a58e2900e61252bf4abd7c7f825aadeebdf7de55e8e5d56ab55acd94664b1e0ececc4efcde4dbd7f2954eaed27e5af56dc0a07ee6cbedfbebec5e0c6ef34fd8a579202602ea17b0b3209997cadcfb5baf96e1ee7876e7070922a2b3cd45abdf70d6b7d12d70abb1490f3383f44e73d8c83697c0e1358953f396fdf7d566f7fc77d5457fe786f697cce1371e188e63b75c290eb69e024b1cc021a163def23ccfb86d1f830a2a181abb884a04a583d0ae7c35886fe7c07fbbb38dd7b6804447d2eefec4d1c949acbe457e952ca8da374d39e52eda946a30d33eecce14c85a0fd86ab839a4fec4e354c58ae83b4bd95288fdb5b9adb8619d73555e572f36cbf7deea06ddb5e25e692b94482ba47e7ed5745db07913ffed569dba47c0fda2a0eea9eede6ed3f21c9b3bdfc88b4fce787f36cbfbdf2066a1f4735cd4e6d7635e6fa7282b97efd5e46b7fe9612e2ca2fdc0e6e5feb6b0be2e0f65b06340811d19f2ba7ed8b4b7eea55bffa5c0a48bdea5d12bb24eaed6321d5db6f980f22b2c8f7dd709790ab1fb2bffaee57ab4f927afb4c607665edab7e88bd778595dcb7b8e50943aabf38494b1eee1be612b2ef5a40afde3524c2561f612bdc30d5875785abb884d47630fcce0db358d24d87831694238034345115e02419292971d0c1d6010737543850cad2847444054a08b2f468a0430002f01b2d621c70d081009a30003eec2e59caa62ca594f2c9f5619ba1f161a3d1f9b0d364f0618c791f46229e8f4db27c19a1d87c18a364c97a29ffc36805f5614cb21f462cddc72e597e7dfd8e0f2ff801f8d0cb353cf8f03bf810e4f1e12b73f01bbcc4a191d894a59472a50c721effb8c1eb43edf8c0af1580cffb6a7c227c38bea18fc8f75f91efc647428defc8870292245f8c795f248a4546506214998352e291ca4ad217b138a8f4c52c0efa77d13e0fbe771e7f1edfcb79fc3bf8da7938f8da794220da237b5e003a7ab04bc7d7ac4387069f0d544e3985830ff29b30321995c926079f81c753e43e32070070e0ef31c8b9612366711fd7471a1f3f7689b30826da382696895fb4cc4434ee93c67da813ad3ebe3771a39adf3e3e09f2c7838f8f44fe74f03e3ce2db0cbe21222338181f0cc0179f832f36719ef839a044914939a28294f3452b495894b22cc52e71d614c338e814c794f9a2f5c5279b4935d5eab26a3cf848903cf13bf890489ef83e5f4b1e1e31d6d9e76b98075fc3787c0debe06b588eafb30dcf385fcc3731dbf855755fc74cbf1e93e7a765f9d5ccc1d7302b3b924989eeee425ba69449e1ba4cd6aacdb09db3158123ee238974601a6305d3982653ba1265b2817f5978943b927e6defbe5e418288c8294292c7232c07971b3526d1231aaf7be69c73ca22e9ede81eff1d1146e34b1e6fcb8e86edd8d13dfa153d2a51bd6bba5a6e263142283189f961678529022766871eae38838b3b9cd8b803052e68453b343aa552d08f2022b818195260c60606ab7be6ac45dc2b17653dd59e77e57a57aee78397a4e3bd2410f4d1835d80c354df6e69f864f93187feb93d049165bc92e5531d1db8f1b58f1f38ac99d5b2c1a19759ac8f29202c292e731fd607b1bc224feec37a7924070907e906a985648354837491a454bd4c01a961fdfd6ddbb6d0336bdb3ec8afcdfd5c6373258bc5fa22ac977f84c57acf2907e33cdd3cb1bef5c47a9b27d6d73cb1b0eaef53cd62a6b70a16ddf05bd7f379f9739dc75fbe6b888be33a67e6d7d47cb7be2deb6b7d4a6b5d92595f5bb45573536badb5d61b14abcecea8473deb67b579940d6e7dfdc23f8202922433d71a246d4c4092595f83dc842db35ed69aef54ad6155160bc59a125bf22121118355fa141b9139647d0598d44f000b537c1df49a9b9b9b9b5a93ead7bb699b36578ffaeabc2c6a436b28adb53e576d6a58b5dae0e0d4e0fe61b1587f63f3310542fd16ced7af6ddedab46c5a15e76f5a3838363895561a83162d20a20a2e6a1856ac68a2c51058cc9081a9eac449a56a77d3b2a961d1ba62a1501595690d65d5505cc2eaedcf1408abb741ab5a6b7d9ceea66553539f55f1eae9f6aa2f82b15f6864a35de538ae260dc9ba7d5e8d470de1a5309f8594e5f7e7b9d54e79dbb62379db5a6f6f53f7f820872e254ba94aba31cfb735d8e6b72ffc2328204932eb56f375b6f94c40926fcdf783bcc6842ddf9f9f6b88f75374feb3db7ddfeefbbd1f5be2bdf7d6fb6c4c0d793856659b3fb11199ef08f76bd9d6d79243ce23bff509391825c871158fe2a01bb991ac3572b8210a34fb7050f2e895eaedb77d9cf9701ff9ab2ab7e7e1c341f9af26777b201f46f2a75e961bc93133300eca8d08b4e27a918cd5bc7c1fe33e377ff3f2adedd4d6dbb77ee270fb9ab7f920c9fa6ea44d8dcd76f32d9b9bb73735377896dab6165c07258da51bba9153711f494612155378f0c18525c4c0361558b9a2090d3790e00b2e60a90df571168dea0dbd97af6c34371c1ae9d94c01b9f3adb5d6dac9da5898023dcb1397a0faee670a04d577dfa9ad673f5c48deb4b0b4c13ddb9e85c397eae74cfbd417ba94308201e58f1096281efe1361f2cbb892ca7dc28ca51cba51962f3484f3dbe6d5f8b672fd430f29378e2593898de328711bc852450e58be94c9e20b9315c0c052855316573851a14b1a6e051c2b30d1650c8e0924a66c3f1c3f71349978820a8e9701c443e58e5039ec31ee454ccdcd444696dc31b1a0082bc83892e286306e2a3713193284c04c1a6e298c29cc381d516fca8b2e62e88890a1bc30c113ce8a91f5e2896ae5a9f3422986cd082a4658e16e112f684328552f46408790499eea4514198a58f2a289111168bc883529e2a88b26f105f4e20144c44cf274eda2298a114e669a5e3c807c7c0b4a55a2626e2b37139318459069ba282ab4242eea892992c8615d820908ce072699970e38c1445481dacc10994b14b6b5a6eeee7ea5c45eeef92ddde9a4de6d37957bd7011b5d6a4026a5da46615b95dac3bcaece711daa6b77d776b35bdd54fd46d8d0dd638cee2ee79c94d2f8797b7b03bd248fbbcb962db7f879dea2478f9eafe4e997ae9131e79c336eae7577cf996396438a1c33a7af38e7cc21c59c735e22daa7cb9f94d2eea6ddada1b6ca7576ebee4aa5942d4b29a572dacad52dc82c492997a4944b332c492997a4944b50ccb024a55c220305d78292c6551466ea4835424299ba45a088536fa9a68e0e09cdec741f118238c83d2abf6a6424958b4f3aae52e122941f3515e43ebef3aa952c3b1428dff5a6d43aab731bf0e6bd95c5fa59a75c19f5835145184a78666a9e80f07218a930f1813886284d8e4bb8512c16e3c06c053d38187f32b38a32e601d9244b598e2f8f2415568c4c666439dac8a61c5f3ac931f28b1ce553a3f1d1c40bce787186480c0ba207883e8082a62d4e1cb10516c6a45806a80320404a42aa41082b786608c2093324b862690c2cf4236f92465942914b72966d6cbe77c83636367fc77022db7c4d0a888d1763b15cf3ac14909ac94222b3fea680b0769c608918ecde5fa580dc5b23af5610435ebd2a056455555f3b9502a2ba29314690538f4a0149a13ea258513851b9dc7dec9f1e366c39528ac13a96971cd6c89c96cc717fbb64eec9062615b0f0379690e5ba854145de5e4b01d91a8a186259a3df60789129ad1b510c0c199a6c13afd38c31fefcf833fe8d7902d1f24c89c024a4399e51ebec6003428cb1458c1061a43982e6072bba48628b0e4f2d3cb1840bab1e1cee84c54c26fb4f5a99ac004412134f889278c2836bb1610c1345b327623e9822683aa3868cfb4513def3c41753f2cca2847d7971a656e9265ae7faf46f51f768a64c5f470db752ede9d3d701c3ad5f44d2f7ba875144924f299aa34c29a5342ab956df59f5a8a8d43df4555adc8b591f956ecb41bae3044bf8534ffe44a5e6a14fb19745895cb1bcd1e46e4ddcaf133d23c61cae0e2c1715a3c7182b875df563ae381645295d52d618638c31c618638c2fabc718a3bb7b8d317efd2e9aebe27e622dd238a3b7525432010739dcf0d5c4158afffd4528b148f2107d6d1b22b88c3ee84713077d621cfdbf21eee730ca5c69c3b2279018935b49a9956690fca9d1b9b7bc900595cb7451f48f1e65deeed35b8e54c8ce23fb77d1dcb0d656c6c29ee0b1dcdfbd6502ab3fc4d5fa1b4e22bf26a9cf71cf64eb9eebafb3679e2b377c6525dccbeffe1544fe44d8b7f6f55ded1aa2b2c3aec643dad7af0db312f5aa40f2677bf94338ee25275f09ea6129cfc1eee5f792a77b30ee17913fafe6e99e85c37a7158ad4c75d2d58f42ccaed40f6dcfbdea63ae9fab5f491594922a2a3c34bfbe92edb9979fabb12b8587b8dfb0abff66180a0fd59faf646257f74092a7fb86d55761b92efbdb37cc65b71fc2fd565fc97cee875425f26bf8ca5d874b88b1285a145d68a91cb8aadc4c5d247581d44551b76961668609c549d3220c1459801a9ca81652b8e04ef3554b30437c01bd7800d950648391f3740eebd5e2850240310aa18bd88b07900f67e2a2c9ce300bd222b589220aceccbd2141b744133f98e076b9999a90c24213b210b898e1e4665a0a83898b224a2995ef78767b9d53a33495dbb420242f1272fe56efbe07d6d96d924124eb8bb09aef6b9ef939738304648d4a8baa936ada5bb7399a877e4b00f4fa1c60a3328baa391a602bed1e4a27b5aab717d5748976a133ad8cf685ffe47cbf664643133f7041f750fdcdb7d6a18694fbb532dac736e8bf6a9be4f44ddeec2ee57e2dc9bfabd793b54674d32099c9fdf40bffe9b2c8dd75a163ca50a7ebb69f82f11fab2479505fcc5649fe5029ce43c5a6a88c0985a3ed54b8bbc766d4c7e9203d92b2a7d668018d81159bf311b1f0309ccfc9399fd61ea0beb340ee3edab712d3ee417dc35019c8ddc7c7f9627b807a5487fadca8aefbee49fe58db3dd9eec976360c681efbadef8a6cdf1a59236be4df646e885330f121d7e7d13db661ed41b6426abe9de6b1cffa2c9585ddac9be5b622e4fa91ca507fb16c85c3abc261cd3b2380b6fb9ed926e1be59f1dc706f50821bdf1d49fe502aced3257e4073e81d5996b0286511745db25399171995514a3d4f3bd36183ab8a1eac78200726ba50c14b0725b6b0e20b134d4e8841868ad1c5479f98620917829891c8e9d38c1245e0061bbe20a2881f7430ba00194178e940161e7c80f274457d22738376712fae0a80903331926ac4d8e2cafeb404a7a4ddc04969c92cc450a18a01c3942a2c5144457b222245b988e1843221c613b901ae8a90c6071c227712e270682a48b3430e7b960408aa0d977b52af6892ed935b7333a521f252c60baac752948bd62ae4b0d144a208a5c39814635344c34404b22c8ad0c2820e52b840258b165c999d49f20116c6a3ec1129c63096894f536c7203618ee02226538a4e61c49cc8e1cb89c3610b039aa082055ca6884208a3d88216379841c511175b8ce8448046bbe169082964451c2105091e6ea002083090b8dc40061874054c4c2891a632010227de27d0c20c5416296437452ac40d7ba9676514f909ca78a10c18b27f7542e56672419a23a4dc9f54c3ef3238a44fe96b956a5a8d54a47c52a3c42671de9e4040794e1c6a9a9cb9b539254827add5f3a4e3ea4cb425d1390ed8963f6ee54914295424981ae68ef1be783361a7e1b85706aa1ba594524aa9369f0a0a0985c325b32560ac46a7c66974528dce8f60d688e449378dce89238c09b7c45db3217647799227aa67404d5e91084cf366bc2fee983060bc25a50a74a3ece608f4f42a139572777c5a6214a944a42533af23952560b2b41b10d0eb0582ff4a4d2c0e9798e9be20de9575974cad282929292d255122597e8c4e9da39cde5b52c5df99b88652af7a550abb866c15ee6de8e5d85cc07aa31ae540872be35eaac45cff20f2a7b3400ad3a5883288d83206163f486e00c30da35134721fe772ecde360ad40146a389644346b4752077266229b5c08b15309900b999d074c9f1a312535c9a92cc557deaa510910afbf7c3052228fb1d914136118486462812012982d00649378c46d4e80995f056aff588ed8b455f247230d614cb42fd94a3947224a913397eb4d23d3a17b9cbef8e1f8d96bc5801a68b113258c39c5458d8de09a92ccb9f645c32d7a9cc03ed080d0e39ac76039a984b7333a1b1c14b0d6dea992ec2c4ce1ce14298d9193145561c9d9922862bd09c61ba22e90c132c5c114b01b5846c89871cb612154b34dcb0d402134eb8208514b895b56f7bdd318c7e828eee1248d720a3774b29bd728063c519664a29a594b24894944ac9c21299195d4a94e7fe58ddea9f6d7b11119fda7a21020fcc004408b040220cc194278638aaa1052c3868e1090ace00a20b3136d0c4951d9ce4a0458b0b460073bf7ea596ecb315b2ff0f77f7e8c50ed31916bc3a59378acb534a2aa594b27bff20a746504e700d532387d52add3fbcc9347e3735a4e41e3561f4b340cd73e2896bf7c40ec3343051768bc4289efdfb696b27575208fceaa8886c41966264c9c50cb7be9350c441a92273519ffa224e4e4072ffbc0cea1ef34749e986933ba34ba99a62df53431c66bffba28c84ee2932ca1388fd64d982170bb4b8c88f2041db0fd68783fddb536ddb288e76a3db06e460fbd02007a5b669da576d52ba6d35d28ab5df34cd37ac69af69400ef68fbf7657feb5a6d1ed67d74d73dc92a797b85717ec266595a0a50d6a5aa5786a409b5993f1b92fc2ec8733c8f43940c00366ec1eca692bcdbb1b3448db0321597e7c7dcd43bf9ffbe8dc2001593a963f12164b68250dc9c91567de8e7b8ddf0912f4038acbe5663a7304d3b5b999ce0031353a7d263444648433b29ccacd74c603397c398160039f1c63c78e03c85187ecfe1112dc473efd58eff5bc078db8fc99648f0f829e279fc62ca38c3246ea30b90009a3f8e55f12b73aa84194bb9a7de9ee6e29a594ddaedc34bc9c8c93db06f5614dea43964dcdb33e4cdd0f55ab0f5759f5e1b5c18f627d1fee1effd587a37b00d03dfea82f47f7711fcf9741f7f86f9f06ddd33d9f00768040fee517d59d496c290a12d460c54bec03b01838808505506c61461064d823a6f8c18a253198a88075961aaa90a14b129414b4a0d16b227b162f6160c0a1a18f3c6171762be4e92c60ca527eac5cce64ffe95f4c0da5a1e8779cc532566f7e90e49195a41817749f9b6f3b0f2b20febd83b443237e293febf81ded63fc904796467a96a3747f726760bc6ddbb66d6bd9bbdd223a3f85060d1dbc44e775deeae844c0f39aeebd37f7400ad344cb182b8cd902968220ac08430b2e538821034bdd269f7b737efb7a732a12368e83c59db50d8bb5dddf6cbe5320449b8bab8335373aadd68daaf5418e48f79b75713eac99157144aadf5db36d3f5340b66865db3614620602d43dfeaf577deb6fbea686a5aab997c562b1582c16ebb654ad0ff2db7ab96d97f5f170d0b7564b67de0cdddc74531011743e148e605142b2622509294b061da94c10a411869e3820dcb6dd3c4b4a330e8ec0aab9deb5b94897f543ac6f049601888c10ab9e0d520d928c49a227332c2947eed322ca79c9fac2cfac9a5b736b588ff31787ac6f7d4c81c0fa9b9c677d9de70deb3b75c3ca799c9b9c9c560e1212eb5a61255dec481e4342b282d405098bfff418425c21c3095478228a3130af4286226008428b23601e46caf271be865583657d13a200a874ad3765b174886a060000001315002020100c07040261402c188d144afc14800d759c3c745e341709a320c6619441c6204308008010200044666868c6012a9973402ef8003624399e6e793a3a96eb8f018f6db63e43ba85ad79abb41aee0d27a280265c31b8695aa0ff4ef4572ec0b07f6c2698a16d812663327f6ff805202b0425804d189912f08b2759cc9c17b19b1ff19c96e413b94d8961bddadf550c0bc50099d4120859454964c3296f470f43733b372f69a11d1b4729f3189c925ba87a88e50e0793d9afa07a5943c89622b309ed2f6fcaa26bd8bbb5972b9661e49f07b6a1143422c1a65ab6dbf5c3800b3636512e67bbfa6f3775ad8f313765e442abbdb61837f024f27759c4af6ce318e63be0ee7342e2420fa06649e332246ec4ad961bdb953353d2c067341d7ba9972af0bae62c0b5a3a7b0588c42c0c8acfd2a3249c3a1dfbe09b40ea6703bc75c8b6fe0182a32fc62c7bffbcc721e43f2a00d985ae804befafacd6d3e0ecc33cae3999f0d36cd757636cb43ada3d392bf1dac50f4a61999802e13a78e08b858911719c809edfcc4b12eddc08c3252e9f24c707397c2f048861ca6a13e5e498658d5bf2172482c45c308da16b103dcaaa4631ed95a2c5eb3cb68bdeb4b7abf7e0b1c8c0ae95d216560afd9926dbeab2eabcee22ad27faf54e25d692cc6bfb252df44ba171d5abb9207b01269ab72a045d26339a8275a8722a7ef346fcc72d408341c0d60864acf886007ec0472add5c98f0df8737328cb6ea42051867d69651339b6c3a54cd02402a6ce31af55c108cc339bc2c9ffe7d1740749467d4912839a8ac3b3089828a9b8e627fc91538e92c8ede801cb8f472c75a7f93f7d3a88160c31f7e015c567b44615e37b29b01a966aa4363d7abd8e4bb52f46c0b9975070f98e75d80f67542e59723d5db3083748ae01b4974d2d9dd36204dae6bb861b6562a3c4d72f90ae2d20be459fe81e605c01f10a5c5f2f63e2a2fd0189a5ac59e54e3c87965e609a8d25693523a8274e6c749c02513de88ace66d6db6712ae4dc8ceaaa5d6e4022dd0f19bb005616db2f235f378f5c564e7b5eed114025f501b9a8edb37a6fd67b9dd539652a68ff8f775dffe9db4d4f3e3e90abe247ca56128b02424333105d797a9625c1312ae943d1563326a566b6a9809d6435258115ed7afd7e0560e178266c94edcb9eb250e8c580bff8fb133e2573e0b41452896aa016d67cdb989908578f18415f14eca787ae2e19070db89a415cbc87b16c98f48aad38cd743890889f8f8f819bf4a05fbaf850c9cdf736602a312e72bffc935c7e339e6b01beabe13d08b85f5cf0a45bfa1f27ed5110e4c4a6ea608e8fbe44f647a88b1efafc5f7f34c879ea8804a0feecbf05578c612ea7ae612ebfb97f21586b482d304a2045abf65d6260b03cd0e6abe810107232db811b1b9dbf218d57be48724af21746074881365efee65d972ad6e0fd1e11e21fb2151b3e5d8de87da899b2962a3021fd52e10d52b11c0aafba7d299c867262da47132b07ef611c7bdd056492e3b68c9c71181a215496fbaa38520a7aa80ca244084d490c26f4f20fcbed0348c6b474d7d88f511b2de24c28e3294223802342ecafff7673957a60f2dd552054fa80097cbb3c9b137411d6cb71d4d46a1b0111edbaab9760c1b5ab3704ee6995109878dd5abf188a0e04d977cc3c120466ac1347d4a9a11c685e584c9f3a5c17b493d3967415869d6f79d02267075194dc9b5cc582a4823bd06128f1d451032859bd5a9119e063082b09c7b2c4d8f82840e6a34b0c08de7446efbba9e4e3b504dd072aa4195120aa5f03854ad68530dc03492aef0293344b016b4c3cc4403cc1cfb034e2b87382d4beaa9c0fac21e9f151ff036573a7d93d050293277436e795a925cacb76a90998cb852451f40e9397904620ff43c5032db1b5cccb86e9ac09342df68397631368b9aa09e07bb464fb9cc4ecaaa4077018d35591b6142061232d21a899aaaacc915c2244538152a0078cf539d5f345c6962aac5205066d900b81403b113dffbc08860f529841ddd779fde756002cac5853c22799c66f6a221efc61bb7351f4a2939320a8932c1de87b24f470681231613bc656526685ffe9c065be26db5193181deeb3944d77321d5efe17a5a3a6cb902eb79c044fcba0255e1de14bb3004e440975902353d66ee96923390785e75b05c80d4d7960dbc96012aa3005f048b0431d8b856610b9e044c089a485345a66372a4391e050aa5cb12eb8631618cdcd66a1c69d0d4a9ba1b1ed47868a102e81ba6790056ad8edb9aab5d4629de44f4e60b3d94d203577982dc18fa311d9c914d6b6fd5ae69e7d1e14ab7ef4d1e4dd9eb4f5b67a4c5c61771d77002f32e3ac450da2cd6f6eb428bbf84b668d99bdcce4183843b8e611bae67c15ffc32ab25016a03eadcbf4385b1ad071a55f17678528ca64aa9a2aa4422d9be672e7e5b0151b648dfa74a0f83f07fb69fe63d31c8e77d3f8736735858949f3fd34ce36817b476ccc7cf57456ec8735975a78413d489414a6464ddaffb2dbbb0c1133621de936fad22637c42e1f64e381a2e9c1c8443c29f1c2b213b95a722b72b38cf46c087d59701fdad23c3e6b2087c625f62cffe62f3f7354a50d347d919cf506c5329e2e19559840baacb654d8fa831765dae33879819f6cb4aaa8df5742e3c6925034d2fdb5047282a9676accde57146fe4d0c4ca6e780129e05577638ff32934a35237b2f75e1081c1d6e10af63ae31fb3d63841b7c632002337e282bf9d73e62aca7d253692447eca13b8a0c0c634475ce6fa0be150fe5e414113bb6fd9d930f99241db724dae9380bc14535af67b250a003058c507b9ae6548691e98d79cb86a3014e1ad9069b335739458511e6337a7e671c514754ef5ece8bbc22d2b82047aa1578ec08657a0ad1ecfd64870e2cb77d09deaaa45e729a91497b9b71f41c834315c9e88acd6123f3447331825c2c3929d0d497caa74f72605be6d68f933ac6037e520591bc945cd1733bc23cb229be0ab997156c32c4d165b1b72513207d9bb1969050d5050291b52ee83a54bacb32595746dec0c389ba14f32ff2531f8a93bb892a1e9f9837c689b753040212420d1bd379969a0d9a2b2d0efc84d1ae80d9648d88b726014ebff35eb8cf6c4636ac13f39cb1dc0c5619fb3441da032a00d969939005d00f0fa0fca779999f4c32ea5a612dcc40586b0ffd383e7a685becad59198ab60f6817e0c9fb5f7d08265cd2071bac7bba70ec3cf13c1b0c47e7a72514f017154835824aaaec0c21ba19ca1f215f4083624835af7ea0e1266bbadfbd807d9a307f1d288a3566c3370db0144e2aaefec090c81ebbe0ee973f29134db58f18846e5b8da919ea629e9fb1ad8a417cec460c28321bbee00b08120a8f4b67de7f5ee4f0b482e06ed45727a3342330351f9fd58758d2a47ff8f323f2f1e68c1a218768e109d15dc9ac354735a4cb73b205453c097059d945c00742ad1e4fa556614bb852a486c5919b404137302033af8a593bace23aecb8d71531583cd8b06aefa0270b441d32506de30b587bf0ce1ba315bed903941fe0b13fa36d7a24d07022f902e3122eb25f2d82a667989d495133bc546997b983c27bc2ae51334b1eeb53e86b3ff974ff2c7c1cde502066a1acf39792084e3eb0fd73a9b6b8e17a3b0833331fb5a17255cd435a1dde6abcb8a40207c2e72134b27b38c660a58d565573a4fc46d30defd3cb3d5a6262d0311f672c266403487f867d116db863ed72c24ec2308d19e5c02abd7468a599611c240c4a68ca5e5baedf2da3e4c047ffe323afcf472519a886cf453f1ef83e873c89ba3dbb1547b98e43fbc3a33d6bcfa811c06f22c29d75020bdaa53f05d9ec2baaae97795cfdda6d9f88b6a9da0d6cff2e360251cd943a60309c18ab57e0a34c71e705005621f69c91169df5fe4ab79f3644fff85720e9f086c9df9b06490fd50bedc5ef8834c69dbd087b1c26d831fce4ac28bcd463e57035a8ac0dca0c8a6c558f940d1384982f51aaf206a2358c1e1c6bab3620b0ae5b8310f118fd58d60b83561be7d858fd784e7b070b4106e543a7885d75da4871466f84bdfcdeaace0c939fc2ee45a8a903bc3b04892293b61fba6f3ad2960b16c8e819c5aab957903046cf335da09d5c998e79b4a9967fe0e00940452f587fd127041afa38eb92e86cecc1127e1bd9d81c8075a5c1edc349b7d1e7d0d0abefc6876ec93902ee822cae30e85998404d1d4e1c53d5f47f7ea08055be279d1e2d02275597b97a96cf8440d243ae8fd6028533b18ec70b9be2d5cd631e266d0824982b900b26e2a62ed8f8583033dd1ad2b35fe86730fd33c1c05acc3299d401b13c01be7ef042608ddca4fdd8828777488af673e21262cdbb12a7d2a0d14de108ca1fa738919bbec42622cb7033e73cb95bfbaf5dec2abd35088761675f04b7844d50aad7339bb1dd8de126b3123ab7365dc4467d80563a1c3092452091da5ee55a45338d5e095198b01b8b7ace6f9857fe9f3d2a437d680497b15e2c31af087f061b4a5d08846c452ed6f5cefb1d31ecb9f3e74b81f6a701c37e1245074ec6108009bdab63417ad1e857d979a6bd164b52d9942d16b104eb6d34566380bc34245b661742f22a07a09de6373b2a19988b1e870f57f37e15750c0bc34ec14114782236e4c5eeb4fac0f4a0553af72e00a839bd14e2d0b7f294071ef5f493261014484791571a443ce14a815e91f006e0cacee1b6e1968b03510479baf120b73c5a75312023d672628af14cb09bcf1bc70d04ea09e3b7ab22482c7f479915c434d616898ca04e62fdefa3051bee426155d4626ae680aed24c401f0930c88028075239aa2e9b058b9955a2ed6f8cfcb0dbeaeeb01ffb164db3dc4532887e6a74d2984535718594f305c916c65d9acc33b95953d1ded52c4fc485b96711e575559ef43d124de4b03b7ce9ffb637ebb5fbcfbeee715a2f14e8e887728ec4db95225b0d29dc59881eccb78b8eb82861114eedd478d8d9d5f2a989420aa48ea2ca46f73b6476928fdcec2a63c350dfd3e31750754f0ddaae5b164b1ff29b5e1d15f09cd58197959724d85c176967d98fa8a14ba37de052f7f095b8342c7eef18cc85bd5c42a6258f226811ce6177b5a7d6705a8f2fe18088e441f4cae4f810b8960d1abd0dacc9e36d75e2e2c3c26564f79137f38911cd388c9e4010e5064c683fa374bbc79d2b24b213155a32b33ba047fb4f395d89c5d79073db28cb9b5a424c15552facc98d493cc070093a3993e784db5633e19354deeac3ed5f68e3eca23caa221915cddceb0880e12f4a08521e95422e9f3e2fd760e4868618bedfcd94e6853c595ed0d8875299282a7427c714f1c6668654b16548380fa6aa7c52335dd7cf3b9ab58d70afddf1ad0f48ea8c801bfe268e6b2c4131704b90543f283adb59134f40ee3e07d87929045473422b51389b8c63a81e2a074d967ce4315b35bd8c495c85180837e9c6ad0148cc51c95683b1f44af1912998dfb4f7fde5c7e2cda9c86e2462bc029933404ca83fb885be5e3b1c37ed46197d945120835b2e78b6ac3256e4a43fd67d901c3e6173e1f142479c0cca74ace2abdff4ca791b96e73c14fd25c63b3bcad7672b43405fc308d1e94caacd3712d9272015c478f5fa576043131ee9a6f9c5b0a65e7c8e1cf625ee32da2ab623a5d49591900958e952762beab54dd0c19464b48b4a90581c8a158c7dd65460389fac268a47617ee6a1f974daab7d73ff51d5aee8ac8767206923bed934f410724d643dc80e3635cf7aaa3832c4be66b9f3c5a5d77411d0b98466e2dd71ec099552a0e7ddb85dfbd99e40273e272fac63d793803439d0284067cecfaa324c991a45063a1c96521abced68934ac360155a7b8740848a6ec2b7158d3d7fc031e133d226c38844dfff42f615718ddf329d38e51b23659ec5a97d19177cbcafd1a681a96633064aa5c350a581c41ecbf55317e4c825552c6142157b2e2c2912569cf5735975d656b4c149ab39d1e580e2b8a3eb478d46fc6be527084726fba2c5edf2575b57ad00aba7eeacde5fda77a81184e907c6796755b6c9243efe90cf9e5db71c7505d97aec829840867d6625db1b314c260e7a19da807c81efc640c3b417512935c47a962915aebfa31342331b064eb706c5d58c3a1a1a98e2bdaea456d19c869e013fc68a209572bac42465c138b327a94cd221baa886a0455d90df121875ddb444b4caffc5e651bca6be2f983d7beda53fc46d719bf4883393b73751150174782e9d4cbaf00eacfe61052e5b38c7426ca4c5c513b59e5e2a6d0e66d1e9bebef42df92696b3ef8fc79e8771987a2c1d496708b3c5bdd01bd83d9886f274e10e8434d0ee796868d676d5cdea715c64594043fcd4b50a49a1c8c3e860bcb887d325857200b53ffc2d5a80bbe9205a6b83890e62a0ac540e4a5a8b35f7c74b8cdbaec851407861d3711cad4427f5328ac356aa5f8b806ffad440b92df5e3c505985c256dc2034039bc840cba83b78f5076afc7478593195a471920c0d238e6d5c3d3412ba1846e7cea1b0eb3506ceba468944ca866966550691e2fb4869bda3d7df7ea4546a6a0f028da13ebddd1615392c685d21088d6a752dab31f2b99e63d8123dfa01bd57978246d229a971f703289543bd4551a8cc326a6fd9d46f409641e76e658c1b063aeb0522038d9a3fb64ce89cc9cef1dfc3a81fd8b04e200ebf4924dc0357a6fa6cf66ff0d1860a7bd7987c1edc775d8aba9c9af02830a7a03f3908d7faa85c4eca3ec434f4dc661b02f04941b1133885aea2d70828fc64e7069a96cc4ba5d85ade11aa5aab94044171c9ad06904cc5f0a5ca1fb7347164d6e93cda91c0bfd0216b5627bc4a6854ce402476e59d25a64062e17f296dc7bf6833a0572d2c10b77adaf54d467f56c943f9f3b8b7b59d5aa6f4aecaffd1d005e2401b66d34fa6127b5d99dd9510cb08fdb9287db0cdfd460736f884276030a20028961168319cd2073bf89216409981ec38f205050b0e9d03414bb801e5d9b927f95d8f9628b7696410a731742d49f65b762e650b103fb279e298631e80b2dce1d6ce1240915104e6932f9ea5f3224ae503807984b8e87ae05ef90062227a83a687b69b14bacc9a9445d7744c2c41b803e0b9d259f78eba1017b217bdf422810b949a0b977988893445d6039a5b3d7a2f38cf5fbdc792f10db545356d54c84a6d4db816a2c8fee631e1769745e385202c25230285227ed69dcdedf0ad8e12a59880cf933d80c0c5f710bf8297424fe582198b946145dcabc81daab943de811103e168309cd1d1dd459e910b74d1530623f5e5fb441e34ea21ac519b5c97353f93ebe6ce685983bc7a0bc345b5d02e7d84ec72e82d883e1f75086928f8b54a521b502288fd7e8ddb3fc4969a5c6a8f300524a52d34973ac06668e08f7ad1c4f1d196f63d3a24e4b83b1cd8c4d01783fe7b3022b43c9a68a5e4c850868511437e2823c7f78642a991b70b8abd97d709547a63efef8d153538c4dc24d0318c9dde9f332d42698df8540bfbd12e151b2f4424df74723dd62ce2e04590e72842d264517a03645efae523114f294e05b81a50fac76ba093e8e8b961db7bec03ded2937d3a4747ee36e4bb8e50efc6b4d7794c33503a969e05eb0845aa17f541f747cf3a9887fc5cb43f38213ba85bfbd2b189bc45736de0ec9fef66fc3b0bd8b21da02f919807c223c8955ea80e90796d2515020789661cc3f760e46da50b014fb6ef1532939c85d1de75e722587ffebb6d869ce57b52dffd16ce338677179f41ec80053744dcc91872bf39481b0d7b7ad9d9f61c61ac645423a51b9106ec2b48a7edf1cda8c5b81df8d4e5ff16914a3f8c45f2b0bab9960469a8b3bb5e0f566adf7e6c14c629d03c12540abdee7a9a2d1fe4dae95af84e34ae56ed57d7e08dc1cc1713e677a5b5ff38d6d3c9e49908768b85169ed72e9911447bfd7691e3fac129337c067dced96aba03660dba16a35caaee87958d41599052d6031520746bbb7022491465037282ac51d361ddeed55f6450e49af19e557bfaaecede3ded1505a68564e365c5279ee705eac930a6ceb275d9bb99f416b052bc809733913b6ba6e750cbbd4d71715f7e910d78e2ac7a3d0bfe78d0b7e184a0ec3a9dd43adc77fb6546cc6a4f7bc958c298add5de1c374253023ec5387cacc60a2ab2316d0e12e305d1f68710662d59ca03ec82a5df08308b1e73f49795b60ea433da425749218a55ad8a5e8836000dfb533e5e4bdad5cc86d5f01687fcc656a8ade3cd2e92e2f3112877716479a2d8bde22e5e2dd9676ddd8039f850958072147a3787272ca405d052bf7b8943fded7f6b2309dcc36f0e2494184384e49103e536c8e76c9b96c7cedf6f81d08eb589f6a71d2ca14823f9bb51044aebe507019932037cde204f63df5c50229b0dcef72b36e3f54d279e0c5044b7b830ba275d246fb788f51e321ac2f6910f7f9c2486482b2ee1d009ade9b78b7ef7057d991b7baca47c423d6c0bca70ddc8a26cd18e25d961c6def51a073d11c060c0989321136bffe9ae1b5b1bebf09b9c771d1f6145f872d088287cf47ee78b77c86b59a69ca1984dd7ccc7df855a1fff33d4660525419929d3a59fef52bfc9c173f574e07219afd4603cbc29d7958658dbb4d282823b2aa76e960053da1a8eb2d678c3883e8b60ec18ef7c51b9f630c6b8d3795a98b0d623a1d0acaa4803b3d80cd2c586741c6dfb035b10381aec17bb79597d5fa3895d542c2e5a47099a944e5535d8305a317e8fceb0b8b32df8326d2d9495c365ae480e54388ff5bd5af52a6531b8b52d71062f081afafcf3b2c7d5e40bd497d4a4f05634df232beba30616e8deb843054f88676afb7c62b71e8c27b7c71ef649bb34eaa3cb5a21ffa96811146f25e1ea5b0a3107457ba883aaf6eea07e65dd09bd8cb81d5fb2c743dc01c066c6af22921dcddce93bd4e51045c382e961044b2efbaaf6b4680e3efd758d41740c874520a998199ba0744cfcdda2651eb8315f672ce092437bc2767e2f1596ffb12c9a4788865f14c6290ea068db9195da8ebc8b16ab3ad4dcbc0d9a38b31b1fa268b1cd622302c9ef35ac62e703197efee49f4836ce12664e80bea28517a654d2310c4aed59a44a3fb13989cb834448fcaf6400f04dc367455b76b82e7d1734896e57ff5668e2afb0affdd633443457c24f171fe1b37d9768c52bda8e17919f25180206b159f5bfedd0f7b026bdd15e86a880d3328d3fe0b53c29ee1aee38bf2f4292a180267cef8fb26ffebe2b378423d216e659af003c150d2646f352f3bfa40880aa4f912d4d7774349d4b34a1c4f6b9ff4879c2b77ffe8ea814b045d71ad78392bb22921dec14a20a2445e2db0097e0c31284ca8ad9a4a53296ba0a175c96f86118f6ea2b75efcb1021324422990d6f60d13324be97c5226ba61ff839c2a14f1180107d54afdc0534394c79f9298c012e140840dccf87d5a09b9c58fcab8eebb1c8812338333878c3cbe4cb3c7fe324d67309c8fde32c6d4dec33e1a1a7e90da24e131bf1383d05a5ac2d4c5cf8551a039e487180efbfe55cc2439f703863da81f5f6d172b4631dc4c568ae1f4d542a2f6cf5cfd305764d64d03918c488e31c3c4499d695be73541369138d5a7f8b1740a47a8a38b9f7bc3d43e01013db043524223b0deb75174d92d41e506944e0b4cd5d079383d9542c0cdf865fec0b37efa75bb30acf8186316e4beeef78adada2dc5c984f226f21f3efb7a5e4fecbde44be6793ffb9ffd85d6fef142cf4ddef4d1229ae4b22107ddbe52167bb06b1cff4076e3fb8b34180c74fda4f08f428c430a57c8522d3eb99e2ef8d20f1e30d05bc23cee31645e5c12a38ad5fa65f80dd2420003b68d97195cdb8761678716499213ddc73cdecf66e7ff48cf492c4f6c622a4ce16c31e2cef827acf8342b0732cecf55855fccb448661984e82f2a46ef5b8f0c3a9ece98ddfe87f32f788651c20ba3c7ebbdaa5d0d3af278ff9b6fda789e0f5bce721abcfa04a9c98c20ec30d4d1f690d4dfda99724ea3ee2a5d17e1a757b02fbc4e597fa509ef6dede3bfe6120a72b608f91d37a40b46733605d907e16fc2b8b918012c5a98cd68cab8fb25121f016caaae69544dfcbc0aecf175d9b6e5dc85d9302d5d67e4e513608c3606c0abf481daea76a80156060f84354d56da00b1a0430199f25b9bbb1c8090aaf00e5ba0441503c0a772b735cf4d83b5b06c7df38dc3b835b85b8f44fc2e386191bfe9cd71e52790af90c50048b9dba9ce9986a1de110a6540d8215abc0c1c3b9e152d43b8b6ae6216ef66090da7d21fecee386ff728bec2828cb26ad6cac053403f53a218fa3c057c5162416458484062f27ab1814d753d377c3ab39018957fc5768c6cb160145186f696dc1d94eb5637be75d860820ac6da40d2b3073ffb800489bf4dd009f13e04e47b2f9bb618e6ea5b351efc4cc3ea0dc58624a4444c5caa5d33f79cb4c88a83a0836a8e8a17bef1698af49f39b88f324ecc8405160df729738964c708f055a8342cd7bab8365e281db18f9668c16c10f9d0c5e8eba22bddc537246a9384d297753aa60edb58488240497faa23295957cbd210212f710ef159ec819c1394c0b325fcebca13b01252bb52c803db7d670426c2197c5498ec377ccd732c95b6363788b25ac93ec7a3e47d09ac893f95cec1e5d949dd57190680f52b0f5eb0c2fb678e5cc848fdbd2e87187d81aa90d74394ebae76f24a9fe446d437f96ba6cba187a6ce3f3f0e28849ac872ba34832b8038d341d7a573e4989075f73d04171ea7e8add0fed1cc1644594b2d83c188d8e448d8eb4954a834b75cb6005fa4773c4a8d9b700702deaae3175296462b5cc0f58ede96cd670c687930c2bc43d56ba5df0c359f576e03fb84a78a489f0894afe62397f39dfd995825ccd0688055ca14bbe817409dabb83aff1ffb63925332e4847f248e2a67851c565fdbe6aad82fa3421bb6b92386a8cb018a06fd1043542d50105376e715f32fb2196c221180366ca1073e8313cacf243b46ed8e5e74527a1e50f332463ba1d82dc67c223a684e1033b218d790082dfd97e24252b8b106dcc3cfdb3bbdf3271e50eaf7f2bc5bd3bd40831607f729eafd37cace9e70deeebc2e4d812f42403f3084ad874619de09c814fffaff6e5047d2c15432252b8acdfc6d1c5236839c864d0643230d3085d23821d069096ba22ca82ee5dac05bb7065b2049a0f8f05075669f3d50877b0450f56506836874e9f7703ba889a1071706307288ad923f2c7130b0c57b53270447ef98517d8062fac89f2629651b21ebbb4f087f04c76e8aa59cb1610e94984e96b2766af1b4b4eee94239ada163dbcd146b550cc57907900967150b86da9ea8b7d04808a49e70a788c3ab94c5c60ad8883ac2e5607d40f28a4470da07b63951440b0625ee3a9ce156001855670bcbc5caccdbc70dc53df1ac10c629de708a61705b0505a41381a80dac458ac6166ab35fec612ca4ed5a90c024058fe0f9b76f9849ff1b6a6d1de21dde03900f6a196d9771b9ffe11a1f49370576d60863ab97b1bdd8e3cc9771fd0f550726ddfc5704df19d503b616710b72e2c8b8be68f5302e563a506b6543c1b27043be44f196557feb6be5e40553052399b45ff17b54d5bf80c30e4b5378af700538300a4f471f8a1ff1a61a4e3341fc848bb4f7e35ff835a30643ec10e8a10f9608563a07f054a4c7d0a0b00bf69e18d6f8bf55619449747fe71934ee834f33cf86467ba6ec8f1fa114325f358077185809e959d13334981cf61e64fa70225ebe6f8fc0c6e4b9530be2ac388abccda910db5fcef959399f17b4d14dc6f98fa36567b9024be4f5c002c7784102d1abd50d43e38a6f415497a4cefc63502ecbc2158c11298b39b1caf7caa98cbc100ac691a44810289da75e65a477879dbb4e3cb7f172ddbe808cb5aea8df91d7deb8b68f6adf345808a2ee6f5c62f8a043344ced800de4d4c9dbfd70f303fa181494c356a1b60a8665abee4ec6696fd31c3ff41fe76f0fa30c028cb0d10d5ebbcbbfdbf9ca67b8347e6a050dcf1790f65a5ce05f060fc7ece38adcbd1ebe05bd8cf91875ae49b1cfe20ff809afbf1b5b8321effa1c20dbbabba1a5b7b7b262215da735c733a801f9720d3c79405c584049ace2dd77d4d8939228c1e5fe54b42cc4bb6a428f29100077b3168be083fbe31de23548152920b738a5de776d40d00eaf63fd8bfb8694bf6a3c9ba226deeeef88c9ea590bf8e31398903378d03012091cc3546932475dfc871371e08008924047afc3d4666421f1f9d3df4752d7dee90f7dec604c82686fafa8b532df9175f1ee96c95362121eb99691bb804ef498311ec70e7ab7de2a6b62139412ef8877cb110e6f1b1212e4f382f8ab7c896a9c38b51e5370d9bcd9e57f2a7367cc3d40012827cc237cdf62402060489d39ce7cd210c8d76b7f5b4b077bace44c332b481ffa35ec6675f98961fb82abfc34fedf614ec35f202cc635e30e54181a6bf1cb40924f6cd042e038accfb738867b365fc3498af489a85be7e452a678c18b54e92b9c17c83af72fd87b5c2835dccef3769d84c4b40cd2f62584fce49bb60de389e823f6174eba65fdf1579e2d9b81aee9606d5d65e2e16e4397448a2f4315534a1d51fc3ad003841b5525c6e92bf541152949ac41a2e532f170f5f9e1baa361eefe93c129a55106c504c40e184c38336c8c3851add3c316bdd1ba52c4ddcb8e35de75bb05bf796c54d4acb5400974f28d4da425f4d8cc70462ee8b5d1d81f8c362442fcc53cfda82c205a8321f339578694e2c4621217c6bf44639fe4cc5942862becff9449b630e92e7f223b52111bbc2d04a3e53e11a04c8ddef947d3c80d5c09b00be685bec0629f14969bf588e4648e4ccf3e483e110f5ed7d32cf494656b9de2af6a9d3ff4d494b2acbe17a536ba2e2872e089dc50c29e44e5e63130ef92007a3a20a0299e286b712b893e2302079b8311861bd41e41661020ea3f0180c3d971d79be98cb33d2f39de89fb7fdb277d0820c94178232bb57caebbe828653166e920c9689a14ab519f81344a4730182992e128778d15a86edd4d4bf506a7a911057c366839eddede9f02fb6a84a9f16aecb7ccb632b6a5b3eb95e389f2ea05a7b64f022bc5eb81e740566c583f01649b58508378a1185869a6f3aa1fc5ba7c7ec3d0edb6c9e65e03eddc3b89ae29e32e02f773f9c2c044d859c30559ff78670dc180ab3da10d8404f9295087c08ffb506b5646b50292e508f03cc9df06a31d8593eb283879d9307306c4be0ba216b0f56b686374aa8ee534fd693fb147a0d41adce51240f7322341ce019e4f2ed791aa7779fbed640f8d01da7b59f36364e5980d41eb8333e76dc6c0f81281554bc6d388562da116524ad5c6d9d6dd8e48b9845472da76ad5ba799716086fa054d5a3883c91a1bfc2cf8c88cd4d1de121cd625bc83dce1439e512339b33bc9c06464e37fb705c268796538a5e2e4ca0cce95ef8c32cbd647b58b9f7c5c85c2283d1e8962d21e9db37a92d9c3a8503f91c89f2d183d8c085af3926863b46d6608a8e1ca181a3c60c42ef5eb726a6ef89e4e3b5c8b57c6d3237753e9f794f16c2e0234a943be85c3a57509ac83202ea4d21ac82d2f4c95a4fc83f86564809d4dbdc45471dc199c7e5bfe286830c966cb7a700c5e08bfaf4fe9ad391b08633e8e1082eda31c89f54d09b3c207c2445eb12699ce97f58c65a6d9e8ecdbbfccdfd3758992eb51514f575e39043d652d61eeca8080e762b13290d42fa285339b9212715ebdd2ced70e0801ea0433aee66cbde2f405b1f0ddb7148118f84be453b165b7446029a1364796c7b868389afa7a6f1efa6c42a878d6bbe39559c73ef0508ff27662d3f42a5afd05a0f09303d206808a404b71a18767452f0265cf6501e27d467cb3736651d9a9c76d4f65ea62503c55b8c501528500ce145389de09865ec5c0e437cb164339ec31e5e89c275076c4f483a254275c15568784ab981ef066fa9225832c760119a62239f709c74d349456abb0f869b9814ca3b13f332654c5be8d5918497efebfef656e1401969d8705a5e382f86e0921190ff4d6fba4e84fa81c0b7ec570602f0635237012bd901c4de7b0de4655a2c58929fecd17c284d89700ad43685264d5107f36dc96d7cf1596321018325a1d6d79f6de0baaee48a0c1bb5462d4e2499834ca5984400f2399c7e999ab792276298a46391dbb26063ef069c2da021f024bdcf12051e1c6bfd02104293da79f2b212c6e0759ec8df330bd7ce08245ce3bb7e557e3a6526c894c994d9da903ece76e433685bcf89758f35af860f14e0b4592185b73e98026240677c49d7767924fd745fd7d1cfa416eda5b9b81a309ada71df18da18023fa676fc36fcd96d4838e61039e9d62faa85028b207c781872705c73e505cdf3494f9f2cecf7898d809683c3ded66b8ef8987ad533829a66105ab49603505f144a6a05e168049fd2fba2baa93c672c69cfda4ef3d84c9309b78630cb71cc2bce636a34f012844336eb2e96759fe1f60d81d57c035c09bab77d8c86835efeb2ac3379d3e5a4c65f22bae4549dfe4b05e9268788ebeda9a6536d4f9d8d29c88d64c874534125780ee12f29b891bf39e62cb3cccfcb901f465726c11c02d9cb2ddb285efd3ecf1e84eae0cc4461e542ec297b14f1bae4c8582bf1bc6fe78c4f47ce36b6515507372bb5ac91a558d140cc42f94fb0da52a72780df9ed7b3a2d40017ab62498a3618478a2454d5639cbd0b3dc7ac490c70df4e1bc3085c901c56a0b31f59d7c738e9a084f52663e8fa0ea35ea114fb7cff55ef7bb7e490f9a58d84212a605f46d54b06752d3323e3647b2b6c6582f4ffb187f8c84c8552ad295de7c938dd3b333d3a359f3acfd901c8bd64a745722c2b2c4f4345c7188fc7ef79df7a635cf09bd5d7f5fc9f176f17b054ec4b3bf88d05b86a4443b4bb0a3f2f331002f7b02dc031b84df8b24a29114801d32fde5a3d38d54a0f03bcfbf5085c59796f355b66ebc1ee2ccd142f08c6752cdcaddc80171bb14d32b41f4ef05a9c2a35d26942c431626bf596e011642d7d2d6debfc654da62fbed2db53f8ed3f130d08b694406e69811c529aa143de40c2ec0ac702a386107904acb7bb2342815f62404f93a82a343b40a64923d4d5048a4b623c421de2fee0070df46b117663bf0f343b826ab2bd9b676e3ab5538b02dbf67cc080b257b0ff490b6a85015d8b79fc8cb6870edef3d76fb8b8161b31f5451c6581f290b2b4e992f740ff3495eccb222032195ec8a4d7c60c747c5a302638494774d15222c93eea0089d470c81f1ad0a6e300a18870c817d211bd1a444511d23e97d7d4f4413e4836d73d72bf1c802a7f4ddb42d540e6d134a6bff6110f67cb80bb13b6793e1a4f1a864a1157ac7d73c0f437b5292220c55368ac5cddcd781fc307b0078e5c8efa4cdea8a71c22f08aae5264ebd76354805bb1f273f3e2d8e57dd0084606ff0ba168a24c8d84afd0d138c2a66266258199aabc03b07d010c48007567493e29c0f2c042f63329ccb197b690dec1c6361ecc2779b0b96e166ac1dadbccbe51ea4aad298df093aaea3df2ef84756368bd179873db908fbc56e4efff1ab47564e0ca6b5b2d91542f97547f57e2e3c169232f091926bdcedacc011ac3a941479bb73289e40749c5eb17e8098df2c73e4bfd8074166eead3dc7ec011aebf2845224b7232d534681f20c2411a32c36d722edc463a6385791d880d056d176ad470338270b7e9235d7414d22e9d36062403a467e08c0274f44bcfc120820f7b48ddcd44e1f27dc29bd9300f48c3c40d0c5481520bd52b7ad4d848736111f8f7b97fde6bc03df283606deae1bc9d39de4c5402c7ef939c3abc52538c7ed32a686c156117a27512335f9252641a1c9b33932f71ce6cf40c0f5e66709eb332109e318585408fce1bd66560e2e6b11aa4699969c0dabefe1d1749a1e47917ab06595c7cf1e0922962a8fc92ba30661e7845c172d1b3d5c37d58115909dc2172ca04ab9c7ee56159f7c6bd100b0b1f17836dc572942e58d759fd4a82cbc056c3e2fef1b6a8d97bd957a868c36f5faec7d2568550540b5c7a0b5933fe270e40039744f62d835406ca8cd8256b31922e48748011b36e280332706e3be3e78d195d74a346f2ed127e1e3e59662d4bd0e8574917ce846d51cb1d22765553327b52362bd75e46a2329b40e779f973dc43e5e73e717101cfe1d16136fa2a84ab145509060ff54d0f6834e209048c54493381dbd4575f33ab2a8925bda59d953ca3ba6115f8f9c90de1c12fc58f702a4b88bcd936980a8bc9a003ea2cddc9f25bd1ac1f7ebdc71b9752f996d5f2989fcfc5b13523419447d1ca0412f80246df048cf112dd5b56dbff13efae8e62209e8fe2934cdb93d3457cf395fc56380ff0dfc99241cd917db6de2b9d63289679912d330185582e1203b31c1c73d8e5eed909c207d0a74c914805fab0d2d41ac39fd00b6f2323ab026322cfa8441956d9644723a7425f00864a3062ea74aa6e39e48240b046a7a38c8eb546188b00ff8a1e32ac154f07185aed167c6054d0a4553eac5febc33aae5a3890dc64d4efbcec31ec68e8bace0401cf5f3d58fd0ce244ba99991cc999d5652390c1034c41cd02bb3ecc631fd8aa7f5923deaf884a8e695982963d58636b2dc198032e937fc99bf53da8f103b9e8df0c46d2f3d7a2e6362fdbed64a2f3a83b5a9612de91f41b658d6d8b7d3ccd23dd098cb3a4c8d84bc4e03a5461e9d79633fc5b2d3548f3be8d5d7ca04cfc5e386e6c11dbd067292f23b4210647104a866fa53ef328f9efb1f8ea302c75130019595b9879f6cb51c34095ada5328b8183d41c8bad20cbabf107f3f6e1783a8269f519606c695d2b46dbf2fcf3227ce13a09b7dd97d281ec831e33e631660c1550ef62caa8f9eec64a758d311c942746df061520a3cd395d6b2b83c32252013e6314a5600b8a3f7642c4d54767630ae69d4db61b90beec2505d8a64fd821930facdbf16fa877bc73ffa38ad284db075647d8fcb88182fecd32df66febdabe28116f43e72464d3ec5e1247d80ac601fa4f9dd47d8df4aa86894af8a3ed18884200b14db22bce8e1da00718c75f1dd23fa730701e285bcda46a972960600a68ed16621d5016703f32a71f65939ae1b08aa5f527d4397a8db7e97e91c6b7a250e8016ef45a08e3eda048480bac1933be1f85ddb7566d9e0cae478ed5d07f1da20ffda65f8f4198ebf4ee39662b150bc03fdd0817411762e802faf8f46e2c8995e142acf93abd2ca067e0d7b4d41bf65c2c1b99a2df4e420ecef4983e021e2e304aa4fca0b4bd04ccee587ecf1a1a2278ccfaee6f6f0e6a418a64905d4927506df3c5719d6d1f498a612a70cf89bc73d19fddbf072b65a69ce78c6ead7a93997436e7768dc204948b3469840bc20e24e72d08e647e1ab9af92522a6e417e15f16ee2a5e9138a7a5ae2064b0b64329cda446414d2d731363b0e840a1df0a39553d19df8e0358b7530851add4c447bf01026b9c603973e8d1e0eae594a69cb090b3146e0ad436b104d55aae3ba9a2dfb389f2d2349e640d296effbc6199100fdee2fd2405ae0f78f28aacf772570de600f7e4d473a604f24dd4e4cab5bf7b54b76904c8bde70130a578b479801fab7d80fdf14d6e24e99cf07fd7da4a23ba869f6d80d3c14cac92c2b602c753da87abe9d4bf3f121161fdeaa87b6cdc747e6c826861c14076a5fd159dfffb5b36e45d9c11dcc39a27a24317d0b64e9c342b956a2cb5753cc3d18d9cecefd8d19b5a73c96c3c37656dcf5c85cad59bb3076226fe1f01c6d45e205d4c415a637f94f22f3aaadf4eccbc14427ade84da446781b66fc8b4c48755cd0e565b502f2e6233daf541580fe46d8135ed540e3dbc4f26d9effb4e03e4dfc3d08abc1de42c1cafb0c68880b94b51614426a04131d671300170fa04e905b60befbd66dfce0a8611b697f665b80ac204a20c29c01d6cfacd3f11ac73c7104eddc2a03d2ab0d5959b7b54d91999b01f1f0187dd56901d95b65b1090050e32d00a328dd889f50d8afda0ad2ea05f952e73a3b14ede232ff35a1c7fe9c1ec57d6135ae9888b713428452fb44a32ce931b95268388a753654860d54e75fb3158d6499a0175da09be6e549018ff92019c7c4d5a7bfa30271148c0544a218f396f27b4fb652b92b4eeac07cdce1ee43d771f1accae37ccecb4ce094e7ae1b8ddc146f88f7ef06f6607638705c1fbd9877e48ec04eb1615dcc0f54e7c2b201daf9fe1d69c79d004698a2526d03e0cff03a01de8f7f4573b428735a4ab9f43e97b6c222beadad9ab56fb1b03766fe6a5e0872f223c4cbbdc9978e4d5dcfd3b82c508104fccccf9b137053c7c424524da279e80a460c0d3d262da458d2bbd443cdaff8d9b43d15f157de6c212200427e09daf0da00fa6b84d05babb9c5b361c894321f25aa5ff9bb6c7001849be6857460f36bd05ff1a543255585ed69d41287dd90d0cc72f0eacd702d2a1f239f09e184135ccb2fc1c1e53acff2b5150e441abca48f8f9c8fce2ecfe9933ca7a2436228a25dd85ac6c4492fa81b52c9328a76cffae907234639b948e812a0e6199cd83559ecbc5420e73ee5f72cbde6fd2a016a6c78266b2be62063d21a13be99d8fad7cdf501a0d2a752a8e6532a99d807ccc1ce3209a964d3fa1a5c556d7aaba806e4269b50e1e5af97a0d46d9934e83e64a59958136d9dc7ef84cc8dad8a21a8fb178b18b4dc786d540c27bde468ad646790658b922b08854ea2c0b793c180a2e4212af68b44e0fba1bf3de6ce06f1b8a30f2d75f2e8ae124bee9f6c984a61cfe176a3b419adf89d39e338831faef5bf31e14e89041295a5a61b4ac98880ab0dd21ae0da42ccedb891fbdce9f1beea2d1c7c5d68e43f03a581276155f298eba893c6e076882aa597b8acb8a02c555c76c9b3befda966620d1a2a99cc7caaf0b62b4a9a77cddebc17f70e1732ab947b7478548f12cb94bbf7e0dfa761e6c0a010f1bf092eb08ee9dbbd12adf7318ef5f3c37822152f7083bcd3bc5ade28d45e32245fe395886544bee46e57f380d1630766aca58c737484d5b25750ef77cb4e574a5726a97d9af14853aaaac596de58a52964f4c9bf0d084979b3f36430b560148d2458a3e8f74e80a307e02b704e32fe1d3dbba71528218033744f0f48b92fcbdf19a05bd112c0d3a25f576b91031859191f261710a859debb5d916ba70e2936815b57425b8f3135cacadb7a145044751f535a3609a6e12c44b292416a2a392d6759889982ca1624ee7c699e24cb37b6d0efb3428fbeac018b218db6fcea0b201b5c197077c3c655c8a540331c5640a7fc4bbb97524edb23dc504640b61f36bd1ce51b912991c2fb93593921e106c4a96bc30becf2298b2eef1f119b17043c3184810aec263fea7de7fb340f1b02fb22772a8a7844a60e287ad837f1a6c6be658a1ef2908f0ff1dbcba018a2474aeb40dab9b89faf2ae3be474f38f43774f5ffd05660f9817a9a257b1d606e7f28dff979f49aa65d4ebf15aaa9f67d2e3824c61f8bd8a5551cb130b2327a4af0a7c971971ff08cfb81846eac3dd6c52f7340a8e49faaf4acf9d59551827bce014ce3ff8540883d29e5c564eddd363b95989c9852df111470e90ebd24a20a643758253a89f180f2f1774ffe5bc7add46c4070f4912db64a3f3da2e14858dc8fafdc9486d67bd72adf31533108acbe3d3d94af29fa9ef288b1598541d415e2baf87bb60d0fba0fe29e2bd94547402f1a84835fe73e2f4445ccbcbb5fa79ffc0c26369c422ea70ba3a72eed23ea116dc24927c5aa25200ff03e6502c0e9564d309924ce31ca8d13ce61330e3bd2344767becc18d182d06453e9b389e8ab9675eb5323ea531d11649517e38b35b7a08de9f09915fb3e729aaef4768ab93384f07c9987822c75af1170e2ebf362d9d6b48b8a763b9725f70979c08c119459efd8f49133330fd5997480730e25f9e3bc63d60159c09b84d6af45c6ee880717c5e3e337b2e054d33fc99d3f4dcf99f0ebd8e9a8fb2f1d8467cee5af5aa21dc42ccc662baa65979df8dc421a6ccf22dde2710e8c9954e27ac5809704f974c19e750ff5b9e998346da8f9483bd2cf52892c6fcd5cc9438171e89121185cfc2bc82165fd4334e5aec0bce590d2660e697b4a3106ab351ca4521aa31cd9119b132cedb7513fe7345f58a96a8c5a021f17b35116a0cfeff9470fa97bed9484f57b9cd91b0055899e24e5ece9201d071424693d567dce4e737433be979ed74f89646444c0a22325519d960fcac6c295e76306cfce8ace62b489de22a5dfb7d860c5a6dd8e5fdb203f69133463e507af339d72e392834ae897662c9977d1a24d4071a2354dfdb5cf321311d0e090bf5411e36876c39cb1db43d20f37c8843c14d8b84112f211710f552480d00de17fba214a4c1be27b3684ce88e2ad23f10d74a43f1fefb239243704f42437e8f30b4a4a896e9871dda007154a4811b1e5b41fb3c38225010738379b86e2eef09c9739046dbea40b4cd2ed0cf4d678923bc64b0bf9f818bde626622a7802de9da6e5263c00f5aca4e327bb9c518985abf75cdc66906db003f8560747dbf6600d37915f420fd1779fcd2014e929b98996ef7a420cc58f8661c540e697aeac5f3535116d29a6266edd969af0689848d58d76f0449bf05c05077a1d72a00e9f03478786ae1c732fd2098dd780027adef62b4e9ba00afda42e117df7d2d0048939034589902d6e074d7f4f9dd326daa95c44aee4fe8132580350e15ab628334ea2537c8bcc36dfb9f82d92fadd19fc003c8373a119da84f7b140b45c095dd44e42bb4e7f00ba6122e22f723ac76c4495d949806f26ba30cba9d2813abebd14168c1dc61b1fb46b8fe7cdbfa75e7c0a59b56e142b5e45ba54c2551f3665e2f85a53103bc4f49efc7f5a2d2b819458df1adee453b8efe747ba4c60b60f0d9ca827a19d5b6cc9c633549ba3f1a71c5e63c15444ab87542a23f74ecf69c7e9c04329c583c4da11ec4f7e7292b94f90a51bd9fa8bc9cc0f03b8cda126b6fd5bffb1d4721d6951efc85af4d140dd2c13a26891d8ec024bccab8e3d32da6b428926c9f0509d2f75fd21fc77ef481722647dad24ba85c043f22bd9a304c4992955c9f683d2527ddae3d1f341492c98fdc83442e1999e9f4f4d93472899a6eb9f67382a116ef3d9e9a6b744852f9aa85c339307943ec78fc4fd33aa6d84aca6999cd272fab382298156172151a7cf905f1d89351ae4efbe3f9ccfdaa6bbfa94857a07f04f1180eb7e468136daf2834628819312d59356b1bfd437ed989c6e4a4bd0073280e357ca3ea80834255dcd811f21cfccb594458caf0084232848719030d80c011b8818f980d42c387665a23cdf0f50ea2b985f578462088c3136c954be243e1632b80e4c7e705d797a9304c50f127b731c1dad22b8b9e222385a712924c933ffa9a11403d00ecc99a01850f70f6feba747f39a113a6bf29d43b1624921170bb2b4cb501243139d57a67afa35a4154864db2778b8aa2cc1360075689339648e4c3f4f546adeae5129d413b02ec32eb849a3b38bee894a6922f8f32534fe26fe22a1ad22dcd562d0586b4174aff8262fb0d77cf2f601664f3ac5f4f10e5f07cac64e4170743e18c97be025650c1b20a35fc188ca98cd69e0e8ac5bbb47cc0c5069326686d4ce2f4de07ee38ff9a34b046f4e5fef42269a6baab657d0c03367509304dccf6c992accbb916a3710559a8ac4e3b25e4eaa5888116a654fe7e4a547593658536a1e153e6546cc431e690f73338a972d114845bf7ac264465976d37a0f08e78e388ac4d2b97448fb63eb7872d975876e613bc74bec42c055143dcb6480accf982650c5e729073034418ee91aaa1a7f68741bc68777d718708bf0489362733f4da8b8d6893f3cf7a949f37b419621fe13587c74ebd9b9ca3c5dc3a8186658ddc2a0a2d2bf442aaa0e108bea52a3921ebdd80244eba3cab89ef5c70b55aa158b271a4b5322e8af3c25ee3113ccaa0c62d381289a5a656fddf2abb6463162e2ce21952dd9d88ff327f8439bebbef16de26567efef12c0351b126590b7d2038440c9cfb7a9a9a0671cdace3597a8ceccb0ec70a7521d04d02e6204ab5525f56a59aaddf603157bda1661b0d40751c800c9568c81992310e00c465151889b4e80008c14255dd6ecc4927858444e73dc4aa7773c8e9808f5109f92dcd95fa7a10af18e2239fe81ba3fc4365d9be2d647d55053494d9b12491c4a24481b7dac617c4ad2e762798429133bf66ce1b460a6111bb447221ceb7ca7e6cf9123919a6b1e426672e65a07bc26488fd55497701c4c4effe41bf67927ae8c882aa51eab0cf5ef5b8d59949c149110ddb5cccfbe0cb27ffa09f6e1f95a39868c0a65516ca16a1d0229c9487216fb7548c0043e4936f4fb7f4692295c9e5a16ceba9dc092a6aa2b1abbc0c0a10cfacf0f19f494cfc721e35e2270205ad65f806387a5569d42b23424e2283a67c85d7ec08fb3d1a49d4bc5dc0e5839d6216d50554c7d44b3da5122787a033253b32b1c829e56d245646fc1631dbeffbe99a26d83e15cf9570f4f3a1f25ec8ecde29921bf254af06792a7238cd18e076f2bb26a750e7e725dd6fb161e3d88e5462e69fd6453a22ebb020dbaabe5401ae087cac66ca529ed03446dcb0be2a9e1520106920900a515642efd4db643b7f8a445ed0643d0b8fb1f86a42de7ba47207b11a87e56e86ea6e5ccb42749c38559120265532bd80d17f9b2207b1c13c9ed2dda1fdad5d28f6fe738c48b3ce407ee53a0ae3dc3c73d6f58520254975c4381b600016b44f727e07bab87ed93d0ebd312e650a590c01de22ed38cdb4e5c46bf471153fd6ea6452869251ae7c2049c5674c7f57d1a46f6cca4944c7a62d8488d5d1809a91ed4639e755c4d68879ac36fef29862c1cfbbfc370177ce3c49518ad23413d5992ba907d8e62b089c959cd79ff48371142f117f091d41ab4596686d05914c4f556885de716e3f240834e0003f0847af41be9cfe568df455d04c775cf3a13e39848915e515b8d81348b6ff2b6ea3262d3c7b3873f167cde0665ed6cd5b7a0b6ab2fbe048004b387ca5d8b1b74644a40d0c73705127dc4d846d5ad813c71e55bba9ed0f144c501f2b6fd307102e84d212a1068fc1e36e3574fc2174f4119c6368fa7d9e79589a35da1360b49876ecef094bf49a4e5152830c9e55fc1d614b9f9491ad2b52d56d2560d965904b03276af9547bf3097fcbb99f0018248a814ae7864dbb2b3fd715fe06477e49130165e8277493b7257d92bc3560b3ff2b0b8b4b08bbca3968c51f6ac464bc63f70f82cc57d96413583b749d361a87e0d57dde09ad7990324866c64fc614c08b6a47695576a996b37e493673994f8bd5b395557b5cf379149b0cc905f0a423259c4d9baa9c75cbf6be1565f2006c63dc72892b865b4a52a0c39330ec202723698357cbd5d09c8d9e429df63b5e7cd4012dd43923858c71856529a8b9d203f56b6faf7992e569bcf22a5eca3f874ada4860ca7596919ec32ef76c2b1a1e08c66941844f29478fde5c6d60ea702e83bd1f8db54b40bc4521cbf573d917596ee8533384a189f7cc75fd6393f6a1755d2bdeeda7dfc155543d3a2e49901d3a7e4564c4b83466b71b1b6742b0cd29d2be69277996564014780a96a1aeaf8e566d8500c8ce893497aa379f16904525a74916b1c7c88a9f56cc57fbb17726822b0c6af902313fc9e149f9bfcf2598ebe1816e230d74704c15d3a71c3bec10b183aa2a874452f770ad5069f8df22067245c9c3e11ef900603124234bd1b4fba3a34b01edd691c2d39f4e3dff13f25690134e3f1ac1a131672185f918981da4ac25fa180a1516626a7788ff9161e68a719f00a2bc49528e956c8b296a2fe3271b20d4bfa7f6ad852f4c0bebdcea87d486735b476739ab5317719575633b46913081dc6007b7e02c8faaf9f73bd8c002d5a1db1a44623485a7dc2b3fe600b050b0dc4d002a57cb2763ec8d3d63342d9763eb863f3590d8fc0aef9069f833ea0958b29fe1b69cfe0fc45e2c8ecb34d51b2b1c5e3175790e8918e4a41979c2803bac587ff513c902a9772717238a4dfc0c3f99d9fbe23f7ec1968722933882787bcf352316f8e20c28dff2c22c38be9d95ed4f2661ff84539df351fe3129020f634c7e85403c613ea7c48f9df0e416679c478930656ae330ebf1297e443ed33de93a51c640e6999e4171bae597d44141496a235a2d0299a6782c7e1e4466a9803db320e89219c37f9196e41b81d778542f596fce605eaaece8a7ea3781be64e6b9282af6ae688e514bf3b68c914581c8dd114374d8060ad313552a039ca493867c7404c78e08b79fe4a2350e076edfb0c95cf0e531ae4fb7d35d3d627e9d789a9a97c49a62963dca03c5324454633564ff651e4c1d12d97594ab3e04fc79361161e3cdc4866ed9392c5a4b06b166b233bfa98f2405252d9c8e0b6998201b9333ec832b6e64e041ba146a4121395b4aab2778e965f01f6480e30e4be370c85dce2951d22afd1f8d69ca3fda1dfae26b833b5fef488c096766de23685c81b4efbe29c68e5b74c1619617b9dd485eca7633d49435a1c6af1de6f39de7b404d3307e0636f6f222e52ef98641f74e8589f72f6abaaa3cd50a7893ce0736fc8648f669b8ea692f0fdff2b7e0674c9cf009c56ba68ca34db85c1ef4a8bec49ce23d97398f71c4bcac23b309146fb02c60f9fe7c47c92ae533bf63aed317c46b56a4c1d4dca53d30c89a1c4155a11b6a25beeb9699cea90cfd5b8101a347c070089ee208b0096125757c19ebb9f9081c08f80664bb878a8a8715e62c1e4b06fac48be327f202a412a318b5abbc82755c0ad3757cc1a5accb7e6f8285fa8388891e13e9e382fc21e9356898ea19c57527b68bed66b24047135d0c4265bf01c899867b3cf33ec603b254ee8826830c1ba24fdc4dc214256feac5e15f8ef17149728d756eccf67989de43087e80d537caa99aedc2cfe7b0b5cce309bc2f769b46870de19bc4f2001a92da4fbdf31ee6b1812d435f854564422f6f972c260104c0f63366b654cf46a2c756236ec0d03966fba1af4896a0c1cd6fea753a1fa8a38c9acb07375281d8b64c7fbec0858db3fa79a43ea4e9345143df9b8c7e1c771ff01a7203de9f50a363d992cea950472444efe94c538bc0bcd9ed847f260f8404c51551d42a84d59905f2092eea93951a99bafba989bfc5c2ba2531448c063dd236913f8b7527e19a247a6628fcc3580ad87da2e4fe1b03e214d699aad02451650c46be6bce3c23e3197c2758a00b6085e1c6c546fbeb8e703068bb63efdec9473ecd644dd44ad4c6587d06d871867719887b7e172648b23e5b4ac40d6811869b964e76d5ac959027550f18943d5e6dbbfa52b9fcaeab49cc348c634c1d43533b26130bce84c36ac788e547ef8852c17e7e9b2b3c09a0fbf629ac7c8ff3071b65d54f515dd85edc9bf6e387dc4627829f8938037403eedef619f1cd0185f081d8dab065227ba1823d3eb3a1fe115704be610c9692ebb0c5ebb51b3d147f9ea65bb151fbd0ca7d252e4668bd1ae6be59b470f98ba916d3f1212576ab60563c67b21d9f13997430364825181cb1fca2600184a21fa0425572b0f1615b4102ed2c6fa387a1bc97ec40317d4f1ec9f1fac1a408face3aff2a0cd60f2c48fbf4b71ddb1e2d294a770e28268feb18822b5152386062f450b10d556c18cfe859cac572ede82629710a20815e3800e30fe29b1a04ace1d9471f8df994b400fe97f86e033b76683d920b4ebaf5ddb4e21a03a02a5d06742c31c97b2d2541b889384368ca5826b450d26abb983495acad2fe07ab9bb1d813071801ae0007bbd3397ab560ea7904e049464292a24abdae552fa3c68c882e4e4a0366b7cda73cc2922798834e1683c0e6d9074deae807044f31eb2be018d65624bac4836f4b9e0ad4d0e823526c5845d73218c83829aca70c383fc2349e92b697d41b250084d712c88f598b2adce4a784407a0f9d16ab8affdf71d886b1f1286ac0eb46bdd2b3de52c788973f26717dd8d6dc1d403b501b58606e9b628b96382e47d92e6033ed199c92bb9b9e0443fe0b18d2490fcfcdf93f3de15b24a73dfd1152e79d19272220a4581c35770aec84394db06bf0fd3a91e6bfbd79850c2618840aac0a374c01a788c8e407323635404def5d02751fac01807af36aeeeaa3e181eb4023d01a5c2213b6aedc414374aa295e57f6903d3c4f11269f93650e8b756785c85aa23491a0a10e33a76d32875a6fc7f7e0d1e891b5ba32d4002443abac6471cf0c212f8e9742b6096227ce9d5d22da97c0bdd1e88da09d14c8ebaee574a41649882b72ebbca693b465f45dcd7c52620f1d1508cdc24873cbe0c2c9e200d224089e828eb65cc14aa27a3f21d15c6124ca28cc6e5222a58b987f0d9ba4a3bc2e3c710717d1e9caa49469b4900944ec43c8879a73143dc812fd6ffd247b6f27fb1e0b3626d6ef6365540c081c3d0f133bda9f04254b6d8f3a02fe2282675416c37d0bb923b6edc842694d35711e4c41032981c44381f51f216048466e1d08ca30d35533b061b109f88945001ff468f499fb5b77f261960a688d97c8a0caf054b0af3ce90dfb477c06ba96ba901223db0fe8001ef316134fb21499e6db92e45863d0f3f4fd64ee4c966c2058ce531fd4228c3242766574cbd78130d8dd66a010ef7bfca02c3b5ca3296f2883e30b833e71515be97e82c74021e3a78bd7ed330f80726a284fd737fbc0161ca11b82aeb8027a0b016bad637eed8164a5155578978140554d4ccc650d6c632522b6258683b304a607c13b4bfc8094dc2c12f84a9418ba48ca37016c7eb17da6ba88bf69fd892bab99c223810954970de12261f616f1cd085598e5d9a65ea0dfb2da3064fd13585c233288bacdeb23f507645860360700a4b1d86a12089006fc7a51817f260cd1e4f6a502c3f0692e1941ed8cfb4004f879dd2ed54d2c68ff706da4fc91b6c6f3a906b657f55639902cf1027eeeebf046e2a735978a235084382a1482544b184c3b216f3aa326ea82f94f5a0373c07ee3933b122f735abb5a5d6103f91f95e5ce4ae43e5e1a316dd1fe6a9f6b3305b52a081abb97a37566de8856c9f1828bd7460e4e609f5051d221abc33a320332d75ee821d0b4b2899314aab4e8dbb8c6d3b6d439d0e47ee92423b9f72011f065c026bf47a90ffd9368182ae1f778bfa3ee26975c4f457256f19f4bc69b3b68f6d12d268ed9e6f12f94762d5e0668117851b922fc55ee8641ccec424fe360d59fb84ff1e191e2c2575d1045ac24641a5e5bd6746b5829c814a3c36d6bd33bab42b894a3e7690943368154da716d372c46afe72affd3edae35eb6595545a444cf309b383806900a49236011410c14ae259f2ce7f3a89b97c4f629c83236b3d6ecdd7bd7d70089580209949d24f313dc91978b438d8a89d1370b711d9270d331fa3f34d8e50f1d8d99bc6c429b2b48ae5f688be0e61345b643259cc413cca12e74771c6efb1bc8858efd46e1d560942691e47d1d5334882a3311da409d666db4c422c3582c131b17d2e0f853cf33e516a3c14bd6f2d14ddb52fdbea60c12db23cd021f741bdcc6f4d2a7886eddc0d1a1a6d6b4500f5a78ac256a32b689844c39eea588dba1bdb81bbcf3eb5f8008e0880c103b0f24526bb59e4117bdf22271e511684075656ebad45bd4208eb16c6c9e0e2031286b91086d5c257bf1fd2e81341637d02552b2353fdb7ccd61af16948ba32b1489fed94557bea9bc0031329d844f1ee5b337f80c1da5357df1ad13b496e73cda09fe3a4cfb90afa39de2aaa7dcee5831242f5895400ce39a4efa6395bb9d1f1f582f216833caa426f0bdb8c145eab46b78097a9fd7acc7ec004066307be7ca31ccb0eccc4b1dfdb5c71bf7ddf103e58035f9962dffac9fcc4a53869acd44814e7bb7006f123b810be32492a884f70620f3da0f360c98a078736e3db32eca37994b3edf8b594ce546c3228c52d7de85a9f2ef4a595b896bd8a687bda944f1a4b93f469e305046059d99454d3e8bc9ad51c01c85a71c34c82835e87fa3db3e8a4897ecab39a0d4c84f618ba0aca5b8894073a30cdcf49bc6e427233ac324b5bac4758addce6a08540a6413c6ad9b3668839122407a75b8f12715b07303ab22833bea1abb10dee94682c2173c5cfaf41129ea2008d9977f7868470e0e54c94368b19c5caa08b26c55f6952dc264172ae3e07a294a620021bf44e7f51cb6667b130f53a0d1b877c3946bd6a3d6d6b2789937973364536491275dc530573d6af0606088b1e998a20cd595a9b4c558b2ab1d82ec94f32ab0667070ae803f128899c6cb835584dcef17bd65414a5a7fd1c83bb0abfbf3ca0894571ec8a806d5a612a14b1503576e362a70ae02400c7ebdc3ca900530622bf4242dcbeee49eec01d6c72c1df9076b84e9c8b67e5f8465ad3792b0be4d025e6f8314054595b4201f9b59c01bc0b6972821fda612133f2571547c6da56a2c854406e0bef9c7418be83eb7bc697ab56600c63adb1f27618056876b4da9a950693c76a0cd6b131a361f138bd35bbde6d3826b9a43d8760ec2add22cc7666d20cfbccf43e857291be0a4345fce193a63fd0b8e9c7cd12e323a6adea734e21d310f08618286d30d6925322dba370f0e3706544973a310ced7076d60fdb8d4d1106b53c32568ba0bd55759ec86d369860ca67aa54a86bb7fb3a399c3cbdbd6bb14f5e728ec5ae4a9e29f88b672c181d0e499eb4f806686dbca10b0814ef8f72a25dd1114868e4385b6a8e3e50f3a307650181d355c090839a7cffafbf899b7c28e3f7e777263db68633f620029016cf863dfa7fe87c00f6b04ec4057517324f5e1604fd4ad8c927311c64529459c72692cae0f3ff1144fe8ea5cdcce0157a1a89f53c064b42708ff8753b04f511a15f9fb50b5adf339b51eb1215b4ab23ba8985e75e20218646809522c4fa5c88b9927d8fd8caa94a1c7f7d249068008688ea874583094f495270b5b18aeda2c662c56d9fe1afc612f6f39a44f04574a3073c28f5807bedad0ff73aed6c281aa1ac4e9566bc4d91d85a5e4fb0dff3506689d140197624544af9a840125df3f2306b5e7f5677dd02a200547f9be70833c186f1310cad2480acb21ab7104b5682bbf521abe7da4543294cf50070927370ebb63a2f94a9cc12b0c6b24ded69cbb5b6e75bf517119f879868e801068ebf7beb21db0f59e84219aa7fc68eca6f55f63bec86251ada339f74071bd9f65d6839057bb506e691b05a3d5efac7a2919ec3b8a404d800688eba66de6865a3aab61d4d702f5ea11405206e549d9fe574b102d5fea4a0acfd926966d7fac903869f34c6b641aa2a36c35c7beb91d1103bac45574f424b33c63a5ef0f4817887fca0b010d145508fbde5f6d4221a3a7ac76d494c09b06a8b0f516fdbb219dc3ba1d0c7722232cabd0747922b2b288055f5b8b3806331b0415579122a53792ac827f8f4308969e950c902faa4d689e4e7c48f9b908f84f247fd272e034200d3f4fd65af374cc98fd7b4fad4332036767a501eae3e322a05f967e18f75ac81e4409278e0685a67e03fe29b9681de0d32291459f7ac4184c30509875c58817ee6328d26f776e0cf69543be5c69a3e0e279a5ba2cca7e19bcb2055cf15d823c54ac976554f73ebb321fdf6bae8663ea934fc477c92c0506eda12fd22aefe6a0c6aeec8a8c4c0f8fe966f28e5448d941aa7caf2c50a3e5a2cac91d48e4c73199e5194c909ac6b835ebf50fecbbe1eb58432b870d85d0c55478e5eccd66f66736385140f80527213a0a31775b0c76b20581ef92c9174ab328525f7ac8457c8fe0c4f6c152cce82b0258707c656c401db8f4305dd47964f4df762996bd3c8ff16a954e336c2be388e44dd9b51ec3f362e3a304f08625341ee2da051e748da8a616182bc35076164826c9dca4e522e45724d2c031f4f724b33e0d5988559f7f54cad5184edcbb73a99497b532172104638886452cfad9f0dfc3d794c87a066baf3c7723a9f32eb3c06290fa76ab41a1afce34247e2845bb1fc332b65ac800308034bc44bb62e43769bfbcaba2cffe473266f8cbfb7b1eef1d56eb83d7321467394deec257c752e08ca7e14656caa0613b0154bc966184f51a4aca7c19f247c5e5afa1b159481d553b58f62f511e4532dd72b8d7eec5120313d432cc174b3e255ed159095adc0a82acfbf74047e5df5756c941fbfe84d276fb402abeb65398025fd98416d73d5f4040ce0ba9ed87eef0dac29616ee81ada76a55e1558bbca71b9da101536b5c20a56bd465145506ac0dc8eab330a1ab09175a557835ee94d02040303ea08c66a59304ada4a07ca94563ba85f41b4d278c99dc0f1d9ac5767b6ed689d69f5af0b387a812ae2dd18684005c6748bfc1880eb014401812000e24c29a6b439d2dabb08523cfdde2d3889fbd08110479a89652d219b10b9a59429251930067106e906734e2927571fc6e3e8d6d7a8e4fad6174eceb9cfe5f90d725f977af2eb6bb6810f79a70593ca7c61c486f53a6b807bcea317fe8d4e698dd297a051be1a74999cf4c339279d4fa953a79f7d71d639ea74e9e71ea07352ca5646a5e4e8d00ed672df1cc77134d2196f73b6a6a8945c12a5d4b68db67fc7794feeeb567deeab747eaf06e3acaf0de873cf7da1d0a59ffc7a4424fe68e6faa0dd1ff4fa171b74ba2e18bab864634ff5e9caef0511dcb1bb4ff7f9385a29f6c4e432f674bdaf44a41a43babb3bd26ee4b89d1833d483e5176c2c7f3cf2a63edda37bbf74269dff94d66bfdb3fbe527bb186d92d660774f76f7492b95eeadca7dd2fdf3ae67a8c04c7df1d2650b162b531a948212a504eac80f79bda9871521041078ecd0d141831a3428fd820689a00c5919b262d9b362bcdd79c3bf99694c225de45b1b2c345762a8a6a494524a29a594524a294379a5f49f1ce52847ed0f48932447df3fca4f4180d81f2434f51021041078ec685076a7b331725e07baf7f46e7ba5fc29b33fd1c70fee6610ef8d530bbf5c4ecad596ab7bc17c7e2c502c4868c5d01051d117c3e882b6d1e76acbf5f179801082083dda06f4f19bda16fb1f6d135af1f183b46de8e3f353db883e3e0f699bec238b8f2e3ebef8f8303efe47efe3b354db661f9fa78058b674f1f245828f323e3e53b58d468b9f41abf14934bc8fe08c97e1157d081278b22211903c21598f23cf0a3545e0bd66907069f5f5a3e6c91940c0191f65cc90417b7e235a8c2f7e455f0d238b6051d12d1261e609c97a789e2d9a7dd1ac6806a36856347b51342b9ab9289a15cd5aac508285d714c12c2899d743c88e12224f84a09b540713a0b9353c0b626d7e9207e6cefff1962238df07b681bd165c2025682017ba7e6e01b558c49aec67997ce940573ea05d561001eed28fb2ca9f6dc05d7fae84b8e7d28f2392bcfd3fecd4ee345b56496a5303e401800928b0a164abe1d19e06c2357afe24251b0536003041b30c22933a26a5abeff55bb556ffd6ac25f09d5fe5fcc2a3cbf5ab2ad890dfb9e9e8ce11fcf9a8f561d3d19def5cc4baf5bba35929d6a55f9dacdcfa0e38baf41ba1d5fa70c7a57f745b4ad66bdc44ecacf56b55fa351d4d49d90405590b0404148bf9f8c82f080ffd40e7734a8eb6f4d8c3de61dfb57cdc7aa1530edbddb2a0c90fe701f93c07f4f90f4cc307ebfa3c0eb7301b83c9a72fb9fedadddcd7da957bfe9ee68465a1b6855688363ff96d935ffc69aaa68b34fa7a3aebecbce38664f15fe199b2f0147b2ff93f2bd8c824f43f1fd62321fe0843807525f5edc762b1eefe0c621842f5dab3a0099017f411c6412d2fecdbb5b2419f9fd8a0cfe368210c5efff3f1e3f0f7f164450d361dddee73c0d1757d23cce77eb27f6d7552fdf64a20c09e3d7aeed10d7778097cfb73c0d1e56f848a41fd92923c60f9e7d3da16d26c341ddddae0837dd436fac9a49715d1a46d2e858e56ce6b4ab572dc50d5026b8414dab8f106e84110e32635d8822dcdfb4144d2c134fa250fafc5cf8a6a50decac90f7ee01bfc8569801078b5fe0d648a6888886463361164305de32f7c83a718ce19d6224444ea0ff987db1f6fe8b1fc1dff0d3d16838814ce0f798a2f87b1214f319c5801d30f89601ac4cb405c090755c734777e48e411201ecd776f01f168f270992c623d2dd171cf588341c0ce1e3e7808cb8c350983c0f58fa09c9dcca2d3d17766667667eea77b910a96a347082baad8f8b1bbdb6f04db63b3f491dcee7102d1c58f3420310f908e317afeb53774c5c60f1baa6df1a31fcc3c60a6ee3f687d330f98a9c10e8815af6df1225e836ab02914bad199ead7525ee3b73184cde2d82454954441b5947fe467fe15556c7fd874428fba9c85c782196ccc6a97aa4374312a712ff35a9d958bb5725eebe9dd1fe5299dc6e792c870a683823bef4c478d90efbcbab01ab703c0fccd6f7e373dd7ed6247761f7aa537d341bfc6e5cb5ec8f3761ce78d9738ee0b2284897eb14e37a5b33f7bfca4586bad1f950e846b5859fe38e79c13cdbca22222c587b183e50fa9971b7fda6970c6396beb43fa533acdba91f29cb37e94ce47298d0dcef9352acdb7d16bb54e4ae9332d72a97429669d62289d540dc67751c6f20d4af1308d39db3199dcbf2042bc8d52e076392957bb208f32d519e4714c5dcbd54d97ab6bd5ee255b2d57e55e30af1dd6e7fb94404b2c22925154aad512b9128e9f5cac2072609a5b49926e46d9b3dd65db9805793b92b9fd49f1935c8982ac0b7480d0af48c54296f3d82aa6b8a41bbe8c5ce0aab9fe15ca2e3939779494eac288054649d0181aedfad1751b4237b420061114aebfacccf5ff6845248aeb5645c4442b2334ac00e74513474ec6558873dd7d8517ae3fcbac8dd93044132c35486498e34dce4c5dcdb0850a23c430b9cbdcd55cafba2eafbbbb0fb5111a9281242b159854cb19a97298b861cd13366160d842811eb89871220a3b58a8a250a11189648c3c81228825392c01b5a409244a4045d14413719454714aae6c58744abf40830ec0163756ede9b2a7861b2638214e7f3107fdb0cfa01ff64e37e4d860ebd5bd3ca7db7173aa271be4d8e01e1d2c206181273c54b920c5898897354b70d0b2660930696612467420061d862c11e58a0c0a187385062c70947499ba891045ca9233718218a24224b304c914726c28e365081825503e4860eda172e326e3c62a3d7bf46475004e126cc87cc1f3821411091782d0f3860916ab21261a4e72fb7f072e6ea2c6cc81c2654c9cc6d281cd963554f2485de1c01909c0d1b38207a67093813a39a48042981330d0c3130f767298624d1a20a29a70e3e508be9244892b55ec61c2c40c0d189e9871c24b9d1cd4e88083935372b516800a2368f0418c932b380065090155878815ec541d995795a353ca9c6cc0c1863d5e907ca0ea095368799669a1061922375ce9d2e58601a3eb8367e6d0c5a5cfd3e6c67632d7bf285610a59452c6b6648e3073fb9dca500d43553ce098a2d79e4c800e2865465df9cd5044c765e5860c74fd9bf93b5df719752b8862e50720cbcaa917d7bf16554402e2733397aa0f35b09a3c5bb9f0961545d87e968a32d3452e7f7b5fc0f2739e0b443b5fc407bee13c924dafebf444487861e687fc3afdbbf76ebf0c03367c294cfdeeeceedde979f723127f122ad8fe10ec7efbc3b46b5d0393997f0c8d61eeeeee39274d6e99547a4ddf75230ce637c2e40c61fbfdfee80be78bedf7f1c3a474ce3929e539bb7e8d4aadafd3c53d694be7a5a6633a29f9081ff2c0bc6db3ad63becfa51fab69777f2170e64faf2beac0535cbe5d99bfda56be35b6df5d7eff7494cb649243a72998faa53785f5281c4654935017596388ed9f534e496f13edd6065f4b5e1cd1aae14cbe776310379c71f4f9b66e389bcf97e8deb82dcfc9e5afd10397e9128fe641ca6849afe70f01cd77ef67ea20a24138b6dfea8e95fbe343e22fb333f7d5dbcfec1c3b4f8d22ac8d51ba0c14ac946ddbfd41afb4a00a8d2759ad2f18121bd63be7ec1fb257e85ccc59331116d69fb2d60ade56abf55e63be754e4a69e7deb1ecba97dd179b8dbbbb2c224977ebeeee37acaf6be7d706ed0d9deeab41779fb35629b95d7a741ff938babedc0b629801da69d7bf26f0d545f9cd5b91cc68c19ddc9740d62143d112454cd81891fa89a4b4838844e97394520e4783944e999c9fad310c950f6e63ed67e9609d4d1fdf0fc96a6477db8854bf93927b2993d51a265139679d2d59e78bfba8bf9c3a1aac9c94f5d65b0290fb6ab0e5bdd7eaed39651c83950789c80673fa10ba3fe695f5948884252333b3bcaf677e82abbbcff75783b4db05cacc9619f64d6eca555aeb944524fe99848529e5942848191b8eed0f6b977f080eb7fbe01bce7c269faf578b481af862fb59ba0fd7fd31ed9bc9fcccb345062ce52a37e9945f8e22393ca77713d681d39df90db9cb52c8ddf283c4c1877a68d1849535c89f909cd7c7ebcaaf09b418b49d974f60be1dbf243fbf6063fb65ec6f06923fef87c5f6f30c03bff2671ba47019851be3f4a5b747448a4f0401f1a32fa51ca594a3b6894bb1fd73fa74293bf2972ff9fd47dfa6d7651bb876b7773bbf7f330f9a897eec84cbb78d981f02777757db1d043fc728fbe5927e6d0447b918634cba3ffad2f05397afd7ca752d6504c1a4a4a5258e23c0d4e3f088632a5c7af9492b9353b6eae75d2725add231101293612dd8b0caac943f64105d47fb29ed29e5b4c558677e1c1af3021b9cf3b32f1ad86028e7d7f472d7d2c5251ba5b87ced94dfd57facc4ffd658ffa4db515e8b8c274ad13b586696ccfcf99857367777b770c2caea3daffc7cc82bdfe946588e1f7edbb76459202bcb79cee7c4f6cfef6adb22fb38b12c9d5bb2d71cfe91df935f41143b65d490172c2c30a92347e6a884d4608888362f6317ab757f19665c1f86b3d56a81d7e57245be94528ee3a4ac5e8bafd7cf1d718ae935e59d2925c7399d2f67b73ed3b95596b130cfa9a8a76348f45aad46a62c6c5f03afd5ff205976f4ff7c902cafaf0fdbf1f3b02f08e8b5da5f90d71744e6b5fa3e5f0ddd8b2c045fe1d2addfacf5f568b03e095eabb5ba97da6228eaaad54b83554635589fbc56ffe5d59fe1829ded787dffeba9da36fb20320d6128afd59fcd74c0fe83c804fb1200fb2ab08fa5bc56bfbe8be11b7cebcba8b679f1291b566c64926a528873c51499988b192d2ad8b1f2f4c41499e695d7aa7ba150d589396b121137380e3f437684e25499c2c56eb46ab2a652999161aa4009c5095343ab1b4be50e1a8b6dd98d564d84b841375a35d152c6460795166bb495b88ff12348bfe3105cada8e30d5602624d82cec4954ee2f43e88e0017e92b87299a2953c028709624d7eab822bad1057fe70fd19887e3522929cc05a2be74f777709e3e0e74e1a6bf45ddea493ced70738904f3d6205554a6e8aa5ba22365ee160274b75ad1b358a4e569414bdd1aa890d564e2ab4f9a1092758c26c00050c6e77a65c5551530394397594669cee464d1365d5440a77a35593175a4a645f545b707201393a4c3dedf0860c07dad0f1a2840a940b13865b0c20da54015506cd1ea80a9464d141cb9e2e4f545cbe4c384fae5c619eac71791e283ac5a6e54ceb2c98c4cd75a35513224160e12a9dd27b8aeb5a375a45e9a9024616ebfaf83a76f000e127ca5fda5cdf6c03d7cf777d4e57d6d74bb69eafcb13b2b67274ba38e897eff2fa4acf0619ecbd31f6ff26c978f5e362ce4c17ef4f6c70466ff4dac4407efe31a0eba253dbdd3ddf5dcaee6ee6cf76d3f9d99fe9b97b83eeb1bbbbbbbbbb6bb77bffecc05436c74de90c26fdcb38a54fe9dc735e392ec92ec95cde7bf6abf7df73fc956b45ffffffd6ec97194ae7337dd9b77db9bb33cb33b65f1ecaf739677b0f1d63a41c7333466f15ca505151515151f9f7cb6436262cc982255905936de3aa1e9630e181a362c544cb103676a3159318506042019716262d5059a2a73bc1fadc68b524abce195cad22a0e8095735a9f610c58505a90bf664254972d3f3428ea7292b244ebc90e30428174c0fcf28678c70c560fdc6aa33542e246c7763d5191f6a37569d512393b748c410af3297a9122853dc3016e667314c217395b42974a70577ce2548eeacc011535684923dd7bde63075a513c7f40699e51a93ba7c4218218c507367ea46c4e98518a42c0165a4033edc6192f34d193bdc101a0acbe1fc2ae286421440c28412d99697150c5dac28f074e54b580e69afd2c8ee6e67336868570ee04af916cacb952f3372a3d50b6eaea4e2caa9223e324692343726a57475eb774ff3d6a7cda1d1699bb4d3b6f959ae448b402d1d55c086f1d6f5c7162d4eac5518592c77238c2c56c2c862dd95ac78ad7eeceb932d121a417d32aff1ad62bd56ffc8880d7a8add62b7d88d888b0d95c4dcfa61a4cd695b5512d3b69fafaf64c595948ad450c98a95d62b1571a5d8d78ff1e5b6caac52915bc1d852922bd925ac51115a7d0058891544246e7d1a1d1a1e5712fa0a6514652475eb7f68f474eb1fe160632ff4a12d039fdb7db45b44aaefc3840dfa4cc8f2f326047dec577c26ac78a1e70ffad8ef08fa66afd847a69f6fc78a6ff6fa40a624afd517fa66dd9700ee639f095976c49ebe0941cf7d02e80bbdd06742ece947261c1d811e6bbb293db5adbf566b43dbedd68f7938bc563f21661e701ffb1ddcc7bee83be8fb0d8a8d3ddd786337afd5d853f78291c5521859ecbc31ca86b19b7d877dd04cb49b074194b51fd26efe2d6fe61f6d4e44aa2f83023f1fd26edf1076bef51c20848096ebdba0e5df0ce8e3f5f9101aac1fdd813c1d3ede8e2bd8ab73b568731aacb706ebd36eae5606fe331e0dd68f1784d8cd9568b758abef43bb85d5765f28737db1dbad456eeb0b2ded76691461fb95ae8072e87884a68f9f0384ae8f9992394c5df738c63d08299a1b6aea05668a0e4151d0b8a2bc199216f8acf88091c102302d45375a1df1001457a0b043375a1d9123bb82d29a49b47005c78932354819c207248cec8025cf1c36420c61c17043411b304d58add04399233c3552b2a0dcba0c21654305826cb0d262b609c09a2a7c70a3e776054f950bfccc80a7fad390162ca431020d0b56724ec09345050b49707083849b27920049214d36b41ca0a0323587035d88683263860631575d6480a24a13af2a7758cc3511b899c2cb9e2c501cf1668c153932e46101c64a9d203730d80b4c152288980a288e6891adb8d3f26a5f5647667041565b5f16ca93d72aa7c7c26eb43a52811b264971c4c8912328dc3089ce602b155b5ab33a53f38eccea8905244cb0f6b4c0a4c81d234da6e8206952848d0b4bbcb48c8c0b51535154515636ab73e3b658b51005a5c1ba6eb46aa10e77c6aeb8d1aa0534b33a31c618a574eff923449fed5ead5799bb7062f9a5f46777311d8e399b3efd6aa562659c93f22fe1086cf936870edb612c12bcd62ec6a7f80b7be9b2054b18d1c436f116e7443b312b4a11f1c43cfcc443b8081fe9d006ed7a91bfac92d18771aaf6fe85313c9995c1c69035e824780824fc0012c49dac80c063878e0e34b8e0e270fae2e445881d2159333e142285903c4e4f4e439c8a381d71825af1a19392a10f9da294647ce804c569ca75f09f59c8ed7a4f11024588d475a3af3d7fa1902b9085dc84cc111275fdeb226c83cfb34d9c75637c322a5955a0223bbbbb7bdfee7d84e5f8beeb22b33b4fc9ffbc12f84ae955011f47c300c2c6efaa3c51e5613ccdb69e4b48a6623a6debdb56a6ac6a18327443ce0a394f3fb177fe3ed7997d8b77691bb76d263dd87598cfbf880e80a3815e7aaecbecc55e7aadcbb4678ff6d2ab97d973f1d2e32eb32763f6845e7af3327b967f5eca59118cb7f816f62d5bf83bc9c199cfc3ae0fd1bbf7ba43ef5ee79eeb461807eeb5ae74f17e80d9cbde3d7a859c039e7a7aba3f0fe3a2c7d1ef4181ade4d242a69a9a63a724689bcff7fb94b6c99ec5f7fb111ff2424cdb6048d136d717fdec5b7c1b3d8df7be90afbcf72fb6986e346d23fafebebfdbc478ce4e56dbb05c49c6f7f754db84bebfc1b46dc5f7d08f559a2181babfbfb4cdc52d826fda1772d411d58749525c8c9ae7d19815b9bad4175e6c908a85ccc7a373fd259851b1a190dbf53e8c5448de9117810781e7c28b79b141a0195eec9afd191292e17d5e6c90c88b0d829e7fa110a8eb7da1fc26cebaeecfc273299fe2e3b915cfb1349db6d3592d4591d778665ee769e1f953e7f99097e745fc48830ee5b5ee4e6a342da66b4dd560bc9eea2feda5bb0061e9295d93f21a8ad74aba06c5623cbeea270f4d1e29de8e6ccee536d48bf7456472e1f52df2f8ce3cbe2d3cbe2cbcbe32af2fd18a182f50649ae145a6be308fefcb8b736ee7d1ebf2e66d79d58b1d70b2c4d3e5bc4806ea1a799f7441b78c0cfad2cfbb417e558c3ec272187d4c15d6cad42fe32cf6a9988aa9fc2a462361d9cb5ebd9d7c51d960ec2ad7cd71e498f90ab7cb595fc4b1fc5d5fceb56ab7a6ab7bc17c7e2c10500c284868c510918c458b59918b1730def3fabbef15fbfb62d08c64cc006b1044f08a5e38efd12b7a9d04485c0c3618003d81d790499306f78ab018257077772477773f6a45e082a09bf13282d17cbe1fcf3ed0a413468c4ef717412e848a56cc865810c964442c865aac98091505b988bd80f11ecc7bc162a8dfab85958d97e3ebeb62b468d5889341674c50d61c828e808f5eeeee1e913eef7f90908a7842e5dd4260ce8e741401b743c041647fdc0e4612ec1166ba9bbb23337fb4189ff7305eb8e020b228926067b746126c0b1632a2a11542413120fbe37355a673b52a47a7f4ee6fe796cf42cf8ccbc636a0ab6d9315880c97de4db0178e76a70ee92802086e4d823e468cd165498bf1790fe3850b59646757da162c6444432b84826240f6c787c808a2ced5ba95a3f34aef29e50f9204471140500367c830a2c54042fa90bc4782f1c245d1ac050b1912d1d00aa1a0189045424272b52878210d5851b921499822766e4f70f43cc1c1e202e70b97068e0cf40638465c4bdedc89f2e68d9c3742b470b0b41babde44717d7973048c957163951b265a49dcfcc03d61bd1babdcc430ddd8193756b5b963449b3434ab0d0f68da486d6963c455874d16f7c5823756b1a16a99619365036ca0e8149645075a606c0b37ae276c511015c99a2c6fd6249961acd08d556aaaf8809a263a3716e9c62a353e6cb9a1caa0a609173bbbb10a4b8f182bbbb10a8b0931d6c58d555855f78695e586550b561445c206dd5885a5428b083bf4840a69e0d02f16e8c6aa3464ba232c8b1babd2eca0c416dd5895a64947c4c2b8b12a092a26b8b12a8e98ea03dba5fa04ab4380386108879765a41bbeb0a6e8995283b5d6c907275e80210a17272a1011a9eedc70268a17a69ea881c93f3acff95285bbbbf44ea25f4d0018b77b862cb76948e176d390e4360d19980189d113475652da4cf08274973c018e26bd7b06a6a65adecf7f5f2225c97763d51154a4c8bbd481cbdc57cc9d0be08c8dfbe3514c44736bb8f3119ee20485249c60399173fdff8905ae3ff8248aeb9f048588ebbf8463c9f5d780caf5d7b1c3f5e71102d6f5ef118313d79f042ed71f8812d79f9f8a4461024a061ea25eb8fe2c255587270db10bb0bc30d1e6c8153b57325870c2849b254eccd061f229678a8c4fac32e6e838c51e21ba2461a108180d3085f6c69b0e4dacd1f2440b95104c530921bc00c56bad9c2ed2569cf9a099da4bf57478cdbf7e90d9df9a7590597f330fe6d7df313fc87bcd3f881393135374f9014524973151ea1ff0df3c4c65aaaed42f0babfd75de80fe83c804f4e101fa2a40dfcc9ab75bbf35f078b413d3eb3bf6c29e0a9c32a814eeb724ad84684c101008200073150020180c0a0604029148301e07ab2a1f14800d637c42766234134b23418ea3208882188661180631c418628c210c292891556adb5debc62be24c8b22c941c640f71d4f5ff11289222290843657cbdbb4db4273aa100b5eedf0b70ba4f582f4990b1ccf90b1360a48ac37cd72a036030d738a0530abcad1a5be8e8a8dba8797d3ed12a17062ffd99496f3981cde2a8f782107a7e52217d76fe16432743eaf44ae77749a1bf135225b6d8e9c7defad6aff08ae3a52df0d9f7a806c93f062014a369c7d16d00d1f9ac195f2cba09c0fab9abac3459b635cae705443937e446a5fb862d8343da7cf2f1dd1444a580599fff029a29f69178066f2379a038933ad67bd4868e3d5af00f8dc7942104d5c219a6187688af9cdb49f36330bd5cc854c689a9bae5202c22834bf2c9e29f3d799d213f327a732973238d37fda664a77355351c832cd6f3333c5bac30e51d26536f3bc7cc37e7b45c11d4fa7f5dbfccbe4956b0a3015fab738ec8be84e9353f01a226e858f490e12ef57e6a3d94c381805b6a3f97b6b1aab52e7f36ebbcd9947749516157222684bab84a151364d587d8d98de0ad21a7166f29bbbbb8ac45a79c8d1a4e45eb3c6e9c034627d74c0c64d3c571693e9ceba98c6da01fbd4f2ddf0ab02bd71c856c3641760eea08702bb3508a0da6c6faa3a2cb005cb5988b86aeacd7b8da7989a99af484cb17ec96c6114b10641ccf1e9982776e6e0aa7a478a5efedd35833c48201565fa80fac66635595b8de80596fd0de48a536e27dec880ada6fdfce344df6e682055ee9b467e820eb038c99194b19eee6dac131d39ae5dd1c25e984ab03563c3e5541321905c28853392d9639de21f6ec9e7c3214a925543c1b8d10acd93c43ddeb71a511ece8cd8cb2244f44867a1acc52c0c26229b4204e4ec097b425cad3795262199b5ef2ccccff89ad3c44614dd0809fdfb80a53a4ee1a823f29e0d552a232795e0cd05f1806370a6bb8a41a40cdac02c15895d1c560d12474f35bc66cfc4a10119995517ce103e47826c7f0828006d8f728b2b7eb9a99026e24a909c0b9d5b6e6e3c46d3edb388583aca4a2080164f9faadd5ed4222b4c5509f6ddb75101a6cf33b88b441cc6b03e378935503db6a50f92bfbc6865d09f0bbd4d8a69733a088e0bad8cb47005a00c095410e799a5eaceb97c71075bb5f64f5ed0571652c55a84fe0470f808b3651845b7cdb61d133c606450d37101548e6b05cf353754715c12a6d193358d7a29e0122f339a55b3a4829288b041b2cbad5684f103ad1429290c136d824897d9f859ae3e29c489475e93231c2acb508bb877ce67e2cc433045432311f0e5ed45d2420924fd41862d2c49da2635555aad4130af413d5ad17c3b54ced0703f1a9a93887dc9fc20f117254c670898ee38f6d7421e4f7df026b686fa41417d5729925e7a23ab1f6d8ca2a72cfab97d3ab4832e6f23173b9843f86dd2bcd41c7cbfb1e53c4e76698cc51a858577092aa9783fe140fdc45385dbc30c3348bd5d9eb99d2ac9d0f65c3a5ee1ed309b41658ef1306f084bd253ee35110adb764bcba5ed919f3fb4a3ab467995849f2950b9e1768281455c37a32b2b621085cd6e207be0bd40ed00153616b2a84831610aada568e7986dd632591c7651d063743e66bfd66d7be8be392ccdfaa7847aa486b00fc92060b6fd0b224418f44dc8cca9f78a707e7cba29c9db5038777674f8ac339acd1cd8dbd054966de7f1acd01f684314a16a23001412e2247eab7ee19f27817fc9b628ebfb54a4c951f4e13ecf995c74b2af2f7031fa5d053f4ffee3f514f5731fee30a915e126bf58c5da76292fc3d149502225a03e0f4d4a00f8809362e073a30ff844eb324e4c526eb06304a1324a4f677a02c7a4c573c1033b7fc536aa3eebc5cb440cc9e498c99ffd3a9894985a0d65006e2cc8c9464107b8ab3a30315a23ce44ff0519bf08d77a0ccb87dfbf41e8947f738104c4161404fd1205a37f6a8dd1055a994c72f75ab21024f40e4c69b4ecb7bdd7a2626f9649ac3f0716600ef870774883cd1decb81e5fd3a6b5d798686fbaf9b34a46b065c1f50cc12fb0521e802f05789c2356b688d97e4e4d4a39c64d800fac5acea72acf441e287a64b64ec7ad4955940c797bb50d8a5a3d097cea6bd8c9dd0933c4ef4132cdeae6748f65725a84a22b37e1c9bb770129e926c8b9d2c5ae9ce409dd7bbb7d094eb5beaa995e64f0282fd5c551598efa7be3adea2891185ba1a06cf96ba635d5ca1b2c5d2dafe01d3d1f69687de9e5bc8af8ca0a3e8b6ce1f314c2d8e2969c34afb6132733bc179d748f817686b1b782b5cd122bf9eecf810f3a1966dfa81c266a01cfaf250b1155b336cd12fc1c2e54d004347d912a25027d23d97cae3cd1aae8d463ffa58e997c18d31193858407266e849bbd07f2daca711a05b551fab0798fbd1a08c7cf5d28451128d196445a01bd58c4cab18efa11ddc8fb7205641b3b50e47cc1494330d4be17134e5ac181291ad7202d8e73fd392bbe34a3726a3f8423f928e7550bce91b52fa0c589a1607ccf9562cb3928eda83c5cddc09024288ad38d319dde1736b9f78c0f50129c0c3c26ffa4da0de5bc1e1b599484ba378c633b4874572ec5d69077aace6bbf3651c20a28e847cae7c94987f11db164f983ce86d3140c0de027b547fe6615c41ea0cb8d289df731a2977253aec672acc38e6e6545591bd7b11cc3d17af89bb220c6eb8a7943181fc53fc48c638cf1939d7027e3593999f3496aefe0e94709642cb5c95b2643bd37d6b91d64642b0fea6adc8e75a8c8a5dc54bba11cd663238b2bbf1fb22a670e371827c52e53a7ffdba92c4445b3f570b64aced6929d45ac6e6a0e599aee13a3d1ae5e04c235364e0c9af822db2935e6708f08d4d080d5d8602240b24cbafca46254e9525d0e2360fa8ddda071318ad685b6852a8aef5470199cee0cddeec59e32cc5730ecde88bc713040b6348d18a5026d4872c753eb2d7aed6f8081944dab5782042c01eab807e2963d0282cd7fa49277b4640c25bb3bddfab9cf4e5dceb5b5907942d365606e7e6225f2c57ae023e5f556fc14161f4467c902930dd2443749836a260dfacdc2f1e68440b1905b3df3d3092d57a2ab0efd4123074a1b91f044f43cdf61d484fc14d3c6b7504442441309114520c43491122823d27216ee7eebc93e99a227e41499509364424fc82495935d74546e9dd566cbe74e0f8b8b1fcffcf889b46be343fc86c911350a72fc1c907a72403ba564c172f46dd3890e81b0db4f10d5039f950f48cc1c361cb33bbfef6f8b2f596516f0489695696334b967c2949127007aa4d48aa237904d458f3342663f310475a33fad51c7281b0e4609cedfa02dfcaaf60d0c0c7255cc81d991672ba352dc624d5b4b623fc18926a4cf3731a6dc5c50252d693eb68f17f4699dbb08fccf3ba1a2fe7a99bb1ae221decc37e45c6a7248597e8e0ae443816b2cbae2c468d84a245deef4b2a4b4f1bb1376c01e0d048216493f6a5ec169e945b4b3db581d5f31febf4b1eccd70cf4f3a076feef09446426d07c7ec47b716c95e294f2fede3fbd33a29e02e9a01ab41663b549b12929a23353c66a5cd3b18d48c15384e6946b695b7aba5ca519e3803335d67fac67f06e38643dc00fe48a111e719955c77a1c23f77361412cab58622d3f3170f6d774437b8c80851141266dfb6756f8ae338ba7e76679cf37d844cfaf7e6299ee0c85fc1fa7130214441f8f900f84c37353afea3eb10cc60984d355a42ce1a4d4f849d200ac4053584d56366360ffb537cc66ed18376aac082d0bbc8eb9b4321e1a51270eb0a3b1230f32fdaa8f93777ae74332294d3d00fa3f3264b498ae53160ee822075457f02d1c21ff8919e82b058cf290cad19ec248e5e1e64e29e56dcd25d773cdfd6f68fc6972585a5f34c194478dc1a6660860279ca207e59950c7685e0b16836fc5895f9c7265e5b53a869aa102798aeedfaaaf1c5601d1f4749b047a46ede23f20803c6b2cb7a8d26ca74de60c616b733e341c579772c3ba9317a8b7bb806f3f2a242873a24f355dbb10fca2f2436f205b06df865aa0837f7fbe8c86038e1273ab14de9778a1649e8411e558dbd60bac50a6f744ad8c3937b1627a3cba9a3c34d546058bb743f1fab4dd90169a4d527d860c1e9f240e8322055ad8627a16506d541ce33081f0e4aeca87592aedf46f717a5f6a914ed1212672a56501a98080ed19077fdc96335c3f197860045a7ec429b1fe34e8ca3794ba2cd322c827f8fe83551213a2c346bd81cd53e58c21d5a5f1507df49a9235064144476a6ca92919c832f5eb70549485271c64962166359117eb4f71db54acde7a07cd9adf612e0e4643829dd7bb267ed5d8992c50a77e03012a4b8aeaea6b948eeba400134089f93f97836ea5242e97e89356c303c15995416913db2e7ee07138b6172d9de4565ba656c926bbfa89998364be49fefbc44f127a507dbbb99b08feef92cc9d952704678975e020cc70294cf747deec21436629532c7ff21891f12b9ec90525fcb448a4724a2045d965219101701c472421ea4ff8cd222923de06229ff9fc9abd8df232fe9a031c64da654268d6a8d463f1cf51d761249d100926d8b2d2ad390cb68874b9fcfbc35fea689d180268082184b51be58441cb297b54f3ab83135a3864604c4785f959263ab9e7ee584ae8356aa351564fb2289b904caa2a54e81bd51af6c6afcaa69f34838effc6686d61acf8ea304b483814e30a76b3ffc05d7f4f7b94e3b718c00b175d7098d91540c65fa56b45160d9bc95df16acae02476c65983d2d477c48f503c803f5ccc9f0d7d573867ff45bd6a38c93a4b8da4ee03897f750c3fbe7d6cdec6f0f6c90eae915fb21b85dfadd1d0e74fc2ff09034b6fd2e39b91928ec51407cd1bff318a86988d01caca55d7c2a3b07c837f934ec22fdb1e7da5fe435a654956d928a47089bc59f610b5d254fcd645689c11e9b5f62c7e6a48b8d4447ec9b2ce016c2eeba572fb770e9f904330fd2e2f0211fb826ecc4a4be3493f4cc6740e653a2753fdb3370d63b1eaea8e81d6217799ac4e2362674a7c2cb4534eeec01af6f955ebf736acdd7b92395a7bd475137490fd21d110350e7858afab4de5b0bcc3684e09e7b6c1571890f842020955b3307086b0c82a55af8dd4a168a6e8655c70ab89898d0b9c04dbf7b4839f5070f6104fb9bfeeee2ea86fc1d22164b9b8c18bc2bb04dab64628e2d96fd7de26dde08aaddf80ce61213256275e3549a046f31062fb42a6149d09bddf77a7ccaecd89b84c21d55c32990a421d58fb8d53ac2432220af11543afac65e970a6bb8116288fe262ea514165366c73d72d6b44934e903133a20b5044052a2392d7d32c597aae5061a8bd3553ef38aef39107e104ed8bc23e1a2964c5ae0a78b92f04d4762714355a393535dc24be13e313dcf4fa2cdd85c2cae754b55a62b76b089bbb80c21e6988b627690db76cd6d2911d118701e9ec9121c2e46b32e84328d6e496a02793a0986f5469a584d954af851765924c66ac4bb6009b46239aeb415cbdec0ec0e991b085d0a31804a48403d09592e50f6160e494c37ade417da4aaf9102fa75371ed6f050beac56ac466d7c92454ff415f4e75885511f7c450d85ffa1f8183d8f1502cceb6d3e8087ea75566e79382a07e6f60d0f38b8cf03bf164a00cf8a842398fabb183588ec42299d10f4d4c2014f7959157643708cb6e0ac95f91314b9d97290a3e132bae06a434177996080a02be18e0ee9cb176ba317452463edaa40642c534d312ae77b7810aacfe427364fc7148d2085f5bbbda20bd56de65efb60d8219ac24298df7bcc8703a66dd7c54f40efa425b93d07df9b68e2979ba908a9676517f690b802ff2586d33d1b2d9b149a284953da8ca3f486375abe99ffaaa85998efa3603b2d7d325a5f5328536626d09051b2ee1e0100b213bbf20a6ac7638d3f8c597cf8e3eaebc7d650b540e8d2a9ccbcdbe03dced458294ef35a84982ae15cd9b5b83ce80ece0afe0d5aec3b9b7dbe9ad271a820fbafac43405a8d755e3573b9492042d35a247525d80fea5c54618293789f110dee15faee79834191584df5695e27a2548bc44ce998e214496296ca0b66f203a6a1b5189f38ae9f3242157ab616376dd67b7fb510115e8669fc20049f1b09cca53056fbfb61fa8b101ace99442fc4063ed7fa0593a1902604af9192120eaa62e0e45000b257d289cb3043882a11a9b725ce7f5096be25cbd1f9e685a2634d43449fd784bd281d550e9aa0d4e8a964414c0c7508b980a45146cf016512821542d505424dc0d858997705e584277cf6095c68c2810588b11c5cfd01997cc643f16dd7559e7ac433f3afef2ce9df7f41a7f89bf2f1f26a8599d821572016b0b91443c23f970a722a5c5d2b357aa97880541aa67d2c13cf970a017adea5b80b81f4206237c1071c0da2b9080093ec458d4097c48ff2a107d9ffc3e6221dd62a793c8d30b19cb0222c195755eb6d4e0f29655cc5bda192b9af8c37d50d6c1ffca742a9958cd68aebdcf7e8d6e9075ba9815e8ce2b3e9217ff4280ede3057f8b6996ed77afb52756de080c820b68cac103febb93a01b2875bfb80c04a023d39ca930b473c7ae5a1e19a35b32204679906442c60c3ccde9fbcacbf87c96a9d0616fd11adf7f453618956b52ed3d387fc040505d6255a6c7794cf8042ed77140a2741e97202e5774a84463b69f71d45ef3d9766c719d7f1f8bec4b40174623ecea164d9cabbc6a24a7807ff37086a9640ccd590a72516fa7db04faadda72b755f26ae8d34f8b1afbccfb4f074899d86b4945b257cdd36faf11d1f0a07d348c2105274d45a907ea3334fbf827a831f0af71d51efa4aed1a0789b9eb49dc8529bf99da5c4843640f0ae3ca16e716fc567dde93b8671e4197bb1a99dd3f01629ed8da81010ec21d018a8e97699b20a249d7fce70c24875a965ef2c6453953422d74e948f0b7616e2d33ba24c8eb374bdf4c67e7f16923baa276ce19bbaa9f640bab42e1ee20fb75ce897b944800b3db14bc232f628289a97bdb2799cbb484f7496b87503e70610b56870fdf4cdd65bdbf83bb358cd5139c9f4a71b89a6e022a23a8b8c29ccfd07ac9515a22f244b11b114a5aa24915ce57904d25950dee3d0d5e9425ab9242b9a2534a02646376dd11e6635d5efa1608b00df4b2885b5bd46004797527e151c128399e93b0886f0d5a6725f1ebca0fbc6b15e5264f6b77cd9dde4157be80dabc67636c9250f091a9da67d687bb9f89d2e97a6558f6aa25f25a2452ef26fde69839853f0aa42c281cfd4b48cb962a871ca50bf307b911322097ed1c721d79af1dde4be8b90c46805c467e776c63390cad732fb78a3c054704ba71e82d3a29b66ff04d21cd09c960f29c74d5f8ad0eea129708332548b2be3f41b8e106b47085cc383068fa5002d20814d706f6880f78810e7ae4243023830249303bceb18f4cf31ac2182b45d2ec6a592a982dd32f70b8723c23953589db1b97a08d0159e96d576722c118e517830ff91bbd311e7a747e828942116abd33a6668139700a639064ff06d16d97527217fabccbf0997a205bfcb22550f02162068bf8c5d6d057f642bd83a2898d5089fe89a288495dfe8423c2dc4b449fe4931f01691f340a69e30b5ce67e3be422be959db137f6dc09140f7dd92425274f8ce02dcd57027f7f8d1c11414842dc16bb8f25db12fa57aa2e78cdb14ce3c87ec2badeb084670dfa0b76de64833892973e5949de787a74acc1fa17b75da3c5483422a1f21e455fa460b4ae18a89a16f1d428700e4b0c09076b6968eeedad5d4ba26511e029314ca8c510878f76d3dfd62003d652a128e99196534dc80f6c176d1134e1e5e5b34cdb0111823b15dfff1729659513d650f9b4b4ed9937f23b9039f98451a8a7252a360d4ac9c9a6bc0a8d1530c0ca664f51448e6ed85b274122d50fb1a05792109e226120340cfe82b05b5696d63156010134981d21115f00378522a4c14817628608d6bf6d6e993ad24fd334a589ce1b1f0f2ebeae8d5c9922813100eb2d66715899caa2e6599e4122333c5256aaa0c519e9c227bb62d915fa04873afce45b8799e7791ed93a682ef132782c9c5dbc2d4c32ec7cfc2dab044a4ca0a1bcb69238a1dee661afb64e7e5d5aa5017d6d217176f2e3f6fd0ac50d0947b2091732dc1cb9762d7ab28f189bc37ae49ad6bc778cb0a9ccc16b174d5c18eaed6e16f1e8917d38070ccfc0af711a8a55852cdbdd4a6379912ca0df795009d81decacb4d01e9358b5dd412d57c329df0bc77418f89f7b257d52ad247099c89fd09d64bd2eb76802750b1ad710059cf19dfbde54db30131543a3a25ab57062863e85b33339dfbca1d47cd6eff1e3321f945c310ed412917ff7aa72a4dfff3a831552e9a4a99c56dd0d1054ed74c214759043be8192f3b7cac0cab410017264020db2b468e08092a99fa87cb1f843b1bc5bd736a1cf0bee8e55d8f92a68cb93b947f02dc62523d63a28a116476de9c22703dac51dccfe79258dc8c983ee112af373a9b5c83c1ead6f1aa727fd0c0005fa79f606a71bc9a1bd2ba15f35a33496471dbb2b31c5f8d9edab9288a5e61aa4c94c048b1cd6b217d1e44466ba58753b1e6279cfa2006c0467229b2d8a755bd4c55603c9afa208460e0f381637dbc0dad188f36b0f4e08fa82a3ffd36dbf014cf89dfe1964319660fd96e4e277b0ae3174694ee4b983350c992eb47aee363fcf1d80797e6e6f8a025795a2228d19fd2b7b56fc3e878cd888de5f9c2a834297f0459e1545e8601ae5be4a2cd942bb97fa41d8553eaac3e21e4b5903bc162123567c38ba0405d1b5631cfbb30b9d829f923c2c4bb1681eb25a3caeca1664ede3149256007a73f14352b8d20863b25b8b45bbc9777200095a533ef2ace720922e056a6f2204bbddba45162c4f3a2fc7e54283aeb43f7781d9ea93cb6b8e27dd9ca3865428c2fff1b02950665bdb78c85b0065322cbf4c5f9ad1326c0acaf6f842e48891cb29f1c86aba54db9fc8e56cccecc819d74fbddf428d0614dd02612aacc2c631c880efcced88040f857ef515e0150da0f6d86113f4c67965477b0ef8aa3d7451a41c931cba40a737e2ef2cd82d407ced10fe82ee3c8494da0af352b9e63432195294f0240bec14b90a754c4504345ed34ed50942e6fb0d8a8b8401956a5f72910ca223384ad87ba011f485c7ca7d6d92e43f1c5eba3e196a692a3b5ca0796ae4f2f2a16dd94a5049008b75e7e22d2424d9d937de22b285dfeabd4da8f13741331e2c0b763e5926ac480888756bb3e0170e24fc3a56bd7ae933d2fddb0353897d17574c47113ccb036cb39d7f9e022aaeb383f27e2e39a346e07b246ee20c69abfcefe9c4d79e1132c7331e0a5fca2e29dacc898436588ef684e3af6259cc7082940c5f3cb999a7d19ac92b44db7f68a8ff394bc4f1d1f0f58890ce6f0c1032da8f915b570d3e61e9264ae57a4a26f517b15206940d8a8f69ce832d3c7078590de8e2bd00a0482b1fa6bf317985f4d31cd1ead4ed74c19c93db21ae36ffa6b3b44b14b02ff1da582472f5b508ca2c7c6f584e117aad2bb4ede136842a48a5e8bb7873d0b7db413ec43a9b5b5545c6e7fe987bf2c4d438d3aa02d5bb8ebad141f34e6e6f33bff7c307088c9de4ca2431d70efe3635b3f51d32018c9cb0c1b32daf8ab465a3e3a225d1acd5989836d5a8feb75c7efbc157ab44d5c38a75e1e10cf4a40b12af1a07830d4438a593aca557013c0edb07cce8978b09cadd0aaa70490d59db3475f558e7c42a2e496d6c2ad0f109fdd4d27c30dc56153965fac17414ca7d41961acc2b09dde8aca95e9b682bf87783ad36cda2353729692364a2f7db996e908a1baecbb1025c96b37182ab14d4d2f7ca61eaa39611b82fc57c60bfc55b7d97d413257a4767c77119e93c8636c578558b177cb9eb0d49bdfc7e675f4475fa593ca0f7cab334870a5b89c0ee87c088dff1b8b9e271d0d6ef5dd74af3381c8af635fc4fa550dbbebb45d9e5a7216a86f3a33652c3ae295129acfd691a3492e7df8cf3051baa1639ee8448b52d14dee56209a0d6a4be9e9d673def76702b27f06486a7c4efabdd77007d876d94f91a21a9f4893c9c835c9f22b65356191e5dd461853f52383c1608e56f490af2677a0d339f06dd88227199e80ac84fdf51e82b1aa09d483c134a3316bc7b9b4d10e64b473679a6344e41acec55a4e94e1baffea5663de9f1d0bf8031735294d6d1f72b517720da7248ad11f0d8cfc1ae4cd2043953efec2768bebc60f129c83a73c5f6af60302b97f47e413f8e9ed0eb950f087a72077cc6cf27a7d6b0682f99a9ba8f51bf68f3353e849b74f922428520770140f58d9879b0fdecc5aacc36f0a140f223807e5f323f1f91b75a913cf2c23258fca230af1bcbeface82c88fc29d3629504c5e639dbde4ac3883d9cd52a847ffdb5f59e15806825872f2a998c51367f8033af2733b6f53e022ad37f57a3781468f2dfbfa6a90480e6ef734d5741002dfef752d04f5003b0e5ea31a15ba19a358f52f715d38b2d57dd379f2bdcd68d4b31f651ed571f0cd764925982bd7417435c7aec98f6834c9d2cd486b8baebcf90ad0a6a96a253ee76eb8442cf0c4d02f834576d177f2dfa1c962fb26be29ae5e0f4878b4db490182a50d6e00aed8b2589634ff4a832040d439a0874cab47c8e078fa4781033f565c7513024c6485c98843378ff194fb1d4d07f47525887479a234241ef2975f20bd1b6007d720b3b9aa858d620a642046035800cf7461faae720e1904526e9c9e8a20bb54ed0d66a53f2859e3d2797fdc7fc2e672fb75358e54a5819b3315681d98c9c93a0de7a7821846dde0df524cd088b3714e6e5f9182573601df9ce79c2fd5cd0549df8478e4f58819636fbba03d98264f2425faeb78ec4fcee8d17d4af8ad5b08bf818d1e2818b01f911798f1a5cfe7d486c4b5cd3bd8758ef3bb46e4e30fd275ef093c289ce7d044b49bf154fe0a015d43447a75c9844777dcbc7a33233da6093ebc2ac2d06ad5573b5d904a29a1912c2b2526e5f0cb0cfd81a70d4383f63e278b0a0de78c79958f082ec58ea41a3e1782cd90683bbb960c2b067bf70e879dc760bf904188a206b1aeb1b885e4aed0aac3b8f4d51f0e3d2163bbed2fa285d546c2a2afc1ac1c7988ed81eb20c25cc6be5ac1a4f4bba10d4bbe86fbca268de52cf968dfba9b6aa5dace23ed3eed60cade533251de12fb33348e8c82b50697b4540baf6b6521d9f3c4f7e1bd68b3e9700e2be49589f597a2486800c8ba86d51fc72429f652f221fb68fbcd49975e85172b1d4558014b60fe32e32247c9f5a1da5824aa2bc7b00a54270dbff28b6925ca497e5aae4aef173d4585eeee7ba8c9204ef4394e9c3fda724eebfbff02df1bb5f090fb98246f8191659732ea9e00c103152b8ed7d568937e2e80489481e7884b6efbc085a80620b4d0e5d47a8e50730c2fd9ab6a30eba4b5fa54b9828e1c82c2d7b947b022c79f87706fea9f351af58a19ccfcb51318723cf5fa0c4a209e25e8ba81c26365dab0e5e2c31002d2566007ed18f5f43b5232f23a7cf28345843defee56509ac4348e92aee8040d9d5160bf3b5d84ce6884147cb25b86c6b3f9643cb3d986a7f6872edf912258f1f72535f90cb5e876cbfe963f095424fde4622515b3a1b4bda62d0ade043ee76a97edb44c802f284ad86b98f286010d030cdd6c2cf37024e7a1821dec037e2cf33a9b423f8ae1e73700fe9f024e267a25d468600e5159b90a08c4df9847899ba208d9347ee29f4f5869733c24acdc0da25155df253a86cd39e8781e4e914f0cebb4d71a72b768a84f23870df3595a3a24bb650d1bdf0fb2e0e502ec9b1e80645886f3e8e3d16478bca866fcf1d2ed25a472f3a3f351e211014042450adb6f70269762b3f8812c5d5bd88180cd1a7d2c0584afaa0e666ee17ba1120aa4876262b78bda2d9c7c473f1809129506f406da1b3d1fbffddb1df9353844a4f67f35be96d74899d0f130dbb74cae761f9f794efa388b31afab185d12343c5b3a8b2c298700af25aa449aae5bc0cecdd0a5b889072e81fd59bbd4de37569b43dc62573ece4d97d756fc8b155fe5b477bf6f0e8975c9682798141b68af5412cc509b73dae4ee3d07541dfb8864e5b50eac3f437505e51547a58eb0beec11029ee565cf0000a624ada5f6122d3c3347c07da9ca1e708e881aa2b1f7a9be77a45181d6d5141f03e6e780ac3ea8b0bf1fc32bc5f5d7b3be6c1a66c402bc690082168067b422bdaf9b8040ca205dd65a5a387d351aa88675a05912245cb51a0e204ab280b853bbace330d2fc967099be0fce8e15162feb3cb61057c0703244431f9e4ffbce0ab63cb4919fcf614b227f81017999cf90ee660b2b85ca6c05099c2d35ceac26a3067e0e2d7fa601c801fde6653979902a53b01f7618206f9b72d035176755d575b811ae6f461af08a2cc13bed3aa1ae280a253b707da9decbac24041c95503f3681fd1bcb8a808053a0ad483b6f9ecf50a39e59ecf6120afdee58cdb880aa3468acac968227051a8ae6a867b0a3f05b41f1f343d57d01dd00f17b973cab4104e1257b3dce857a7a61352558b1d723554904607f6f111fc84b7c1215a1d59f42c56914d3576443908d7db98f4fac25ae3c32160f4de4dcd87c17908fe1b22c692b3bab8128d4f6f32b63ff630646151f402f4f5e837a77de939bae6f55b511e1e2e919cd308eb96c0bae738ea9ff9dec5f3cf759367287ea2e03f79befe62a9c8fde9c8a8ae0c81176a35f5ff036a46beff6201deabe345d5031b162af52efc4f0ff91c309a336e0b3c302a9808233e68212f9acb140a48b2c2f73a7571788595f32a94f3fb570c6f7eddf9381647fdbb79da362c831e55dbaac3b1b1fb111847067a2686a282ac66dad1ee5159ca2697b01df76618b8f25fccf758e0e3aa03503dac3ceafaa20451942b3b81b86e72bc1092ab856628ba6aa85e8cb453329a4eea2360c4bdfcd4f9f4c72ecfaefabfe3f6b598f8694f876316fa5da704c604566f80d8f9d89997c65c4319df205a9ac5567f1f4e92a6b8c44c7d4f41c53f4bfb7214148b0a2ae449f630b9872da677880e8bbde9591f67c2b1cec404f2c4a7926e90bcad181409fd16d539da1e5fa4c2d94299f5aae18c559cc5872c557a5470d54f56f556e397a4570c9f6af2edad9563eab27cf19583b6fd1333f3e76b011514bfa87c456b52dadda28e185fe0d792a4c7ee871bafd23f9d24db3c998b27f6e10b83aa8dbb8a3bf945edfbf49f9d0f49d6f75a131f7ef891194c3abb56d9bb0c6c3d8ce72340b341a69a0f76cb111453f7b0115aece97073a785aee3f93127b4e8a404ba6c8dc4e393c72ec908556e046e2c8629a9cb3a0f95cf23abebdd1cc37043c5b873b7b7703ba22164a1641a94ce75d754f5a0f16f6191a85397244468f795674f8b152dbed2b5ebe857de571e2969d194b527f9208c545319025ae348c0096e4fa92e3679dbd2f98dc3c288c4fbbff49cc9aa5c9d5647c49b245ef3158784341c0c479425128ca359684d64d10b86c01c8cc10d1b852271f5dd190996f9d1215c437aad1f28b1b65f244b969a50b8f1e23c088d64eac2bf0b05db80e7cd2d442a560fdd1d0297a267d0e5e6bd71f4b5470f41abfc3716fbaa5a7adb410efdee85d01f3c4e673bd40b8930f0f3032cf40d32e07613e9114c669bbe5b6d726a92c9b219e4d68f65cd727ce8966f2bcb486dd0eef43e4e6ba617ddfcad1c4d759858c97005733fb9a087392ef557fbe07e6e210000402c24a3fd933f26db61d6ce54b7491c848dc0988c98839607b60326e6fc6a4ced0502224aeffe478c1f58ebd4c08b4b731c8b7eeab1011bdaf5004f893d715bfc008c9bac029eb2831f2f73a4f85cdacf32286d552331a07990444b6424819a017a9de6b50fc10841289fd935020d621781da124a45649256d48a3655e26d4af2c9192b638320e1453a8480d176902897318947483eb539d236a07e14fe3c567068c03071c0cc341ffbc718f40a760625ff5a1df628aec7f87694a0cb679e5def3e6d28869cb7e1eec9c32f60e3f3809ce02e74d3c838085b961aaceca8606ee556ea5a84e999fe29db213dbf4db4d6f91b94dfd155ea15400d7954b5ffe402bfbc997428c0f4c31231b55ff2adeab30060a99ea87bcfac4fbc9cdc3b0c96d2f0376606eb4baebde5bd35e49d64aecfd990a78646546f4e19d72a87b2c2187a4ccfd76526cd55a1a354bc2d4a3cc5ba8598078ff2e0354efbce1d2085c135df55b054f57ed067171bad0adfe166bced2de9e08b87c79e027c612063a4a781cf1cd7d7925c4fdc6f77ef71fadf110389078466e9ddeec9022044cfc84eb54647a2f0295ae3e5707136177d01a8177e6d22629cf59e23ad67155347c4ee6aecdbd8fb3dbb2e5b5e0ada986b4e4fc490263d42c43f219200c5900555c90525d7f21a401d9aff366c47fb2a55d51d3307f218506b00a3eb7db46e92396132be948498b4e09fea66fc129bd92433ee099666c04140eb3d3a40db0b9752da62f357cc12be51b93cb1bb4c093fa2337dea1f08908d8592c13459c35cee005e0115ee369505ab5cf15b5327b73a0aabe275e798fdef7f106be94e9178c317c1837470668e364f4cb1f860b88c9e6405b122b6d1363da6c2010fbf2ff4b0245729d1691e8b87e1b2a6150017b99c837fceebbd4f861faf9c537629232da5e354ec0a35cd975ee35f198d3b164c9b2de83a3d881665b90348a81bde33cdcdd26d911abde330822ac53e368a11c3773dfcb94c207b592b9f7c4e3d586b1373f62736c694d3fd2099910e3b8a940890600c1a48733dd9d4ed80cc1c1d9426e8eb91cf0cf20807cc3adc4dd8df264b544afeb1c6553858042659d405401a556b6738c34e5b79b01706d01f1be98c660370dbfeed5cd0fb5cfcd8666c74a9b60f40cbdf98d2de98b0d6de9b80966e45042b7e42a4de250ffb0d1800585a4cbbff76aec782779569977863ddc3f49e2627255ab20484f239b6df61f1db472a63bec75dd1c900c48950106c2d0bac55476e924a09125af4f6c7d90b67dbcd973c2400e0d457b337296e187d07befc3bbe9a29a1c92612a9365e3a47ad14966920615cdded8b9ad903fd74c0c763a58170ac0ce003287c70ddb6e7d28a819c29ed8d1e13ec45821a4d66e1d4fac2829bc3d7459f2979c2562736f32e17c8370554b172f44e3c42f1814d34443b47febcd8140e4f637c3c9fd504f899009732f8c60603122ae2116061ea1a55418c0414bfb4f0cd5f0207d1ba509136faec3985eb442235221984c46f97f2326a762ac78710701112555c8473d56a5992f4ccd36c5605f6f12ebcc72d9957acf14b4ce726e1c13382d5e9f44b6d49f6f43c5113697d2c2b867aee311bae67e6878fdca2c9f0da3a6af54fd81b570e2c3574ff17f3a48fae26831cff9570f00db95563ef3a9300d702dc651f94b2a5911f52335ca44d3e1ba5752865be2411c961b12791419c2709e7c1abf87f6a2bc70ec1836aebc8f8900584e8ac4746db68eafe5726a2c5775edadeb6ec3c7898866d2612720f45e03114183c253391d9781ed5b86dee41dbdadbf227229f1a5928b37ab9eacda66a8a0046a42238e158edd614ef00687b586eec44b87deecd0eb67d96bed51688668b88ad2bfe4bd7f44a939b2a004d79c1abc6c9609bcf20cbf740979d1fe179bdf0e791eb5ce40aff1f711832c9b4ebc55da4f4446d1e12d20eb1ab555952106c80714ff97973919128778c5e23452b1155ec34f76c1d23567ff5062e4f43eb9eb8f92076ca0e48d46885f82ab04cc385f3fd1e8034359a2f452117b011217bc3f5358b1d9afd60d70cc5bbd5e92d7b8282a1067e433c8d34d6a36664c9c4cfa199a5c9b07c2157323ea09e44b88b8231b9d7167dd0e9109f3b4b6e96a3070f0807c25e455e3c6fb89fad64cbf05267e2bb05fa67492a3a2bb811eeb18373bfcf663c8d26239458a0c438a4733facdf9fbb950440338797471dff353dcc6a1fbc4a01e8cf23f08e79c948f3562551f8d01e595a26c369b7d0c8837100eb0177ffe36b1c250e4934774d8d9d05d6210b0421c2df8619e7b6dd03b516aa43d0f0f2be0af3f54fc95a5792065778e5b3060b975150c4644d181d44640efa9d80cfbd106629f1b65a2322623084c60955691a2901ad531f9f3e221401569b518763841f0c2548cd2e225a5b00222da9611d8d2d88b7314a172b07a02d95ac0d8a4e14a35524a8ab79578a6f03d19c86e13cdba7be2ae2000f212dd0ef10f19898d124363fad30fccc5fedc03b16a17f8f9946b513ee30a1707e9abceca8bbcad511819829e79a30e7a30c4264d93aa0de914fdd2e5a0f337d7b44b238aae01d20cd8369774972b9f2d6c13ce266c93a9ba91f2e519c025f18bc47fde670e5a86936ad90d79a5d416568c093a8b89b9db1d8e15df185b46edac6c4430efe9ccf2a499bcd6ddac1c3b3475710a501795534aea9fbf81db8c81a6cbfb990f1d6492e9b9aa8415b47a3cb9693281a38acbbb65f0e3162f5e3a0687512d433bc4cbdb5c90068df7215c1cba215c84d01230669b85716d08e9444328175659512406b25d2084998f322e5f7ea02576ec90381fb74064c9a8a7d1286fc31376596d90fa46c4cc89dab555a69380b06f8168c46d923bf95f7d220fc093d683fa2688b151013aaf187a4eba4f3d4604b9b6febc7e593071a7924a721ad181caabc4e97429069a942e54809aa69b47e028828281b4f897b7992890e2955c2133a8cb4e4d2482c5d8cb58bdd058133924061716374713bdab3ad663ff3e0ef2628452fae5b0b426c4e807a019ad121e94a3e7b1d6b819a9a4326175bc0d35700d1b4fe3aca6ccdf2d509d5a69b08f1d5c8d40cdfbf5067b7b3d886e67b5bc9de6813b560a4a163b35af5257a5c1f9141378f4d64238adc1b3c7fe02df50aae9abc604aa561128096b011f7774bb231674662b6ccf04617027f2f6f75446e09095853f97260ce07665846200093f5cc6dea1b36bfd04525391e25a96308637ba28c8c4f29ecc44d8306a80dea2f3350ca85cd852b2d75149841b7ac491426c79d211791d86142e74e093f37958705db04fa2e1f47add0b1813805b2a215c4919eada6f2e828b3d9f03a88c3e0703a98de5f1dc69ac6094ef4af9f1ba67cda71922e8a8e583535acc3221a66cb1b418d36ad8764066af244f9a9a8b0add4c05ffeaa2cb884f241c9ffdedb278ed09c23eb93d629a16cdfdf83459480ac9203839ce9583361e028b0b40f78a7cb98cf1e8056af46fc3c68163ef8a77dda07905b298abe793100d0587ba02812db83c7019d1eb2460e4f7e532f7a260e923c8e5325046972229e3f291058ee965264e4ad2021c1b8bbf4596509f5c5b73bce23b58b5284be77b23735095031b4955c7f6720967ce885b857fbefdb1c1bca5b9088340bb663f9c4406ffbe3c0c34d0c406789d85a5e5c9bdc375fbc7c02cd1075b4a4c17b0b4ec85a3e737b2483b7e25dbfce8b15053928a14e9447fda796cd42ca4c2a1a38d5b99c3281a1900de02dc1d0b42c01b974f101d8fd7283f6e1338e4a0b04a3083c67278089528fa6bec91d2141f1ba5e000c40a9f1e97defaaa10091c0b998ba01ef8294243631d064d00e24b5fa921997414679ae1f87bfcbc6536275bf4995992fa4de542dbd459f2aa946d9f28c34ab6491de03388989caeac6ad0aa19453e72dfbd2caec5dcd90d77d19809684cba2038ae29cc236afd97596d79b13c8eec5477b71f922486c9b9911936abb9b2d6a831c4ca2eec168865fa1b37780054458d70c74a6dc008dfacbc013a677388204a7a1456c0e6d233cd6459a927def86db6ee24b1b3add78903a82a68d0695bb713c81a81faa34de2e462e23be3650076d990553b987cc7d99887a8e00a5d0db7dfeb397342dc5cbf56d105c6b84290efc6334dce00a1e5400dd236e40c9ae488d3a0865c0962e55931a54abf6759cbb436748e2b5c766137d0dac43b6e69144e236f001f47f1731e581b34ce9f849eefdfb79b0d0e9850673eb3bf4fd0eb080333d8559128798484e03b4df55d666c51da65b21161003c90a2ad52102c93b8efba14966a9a43a74f51787bd9f43bb16aa1396637584db90392a946ae42c2fe866ec5a0a918f09bd4122e36c0e3ac4d2af866ba9c022bd7b9d0292d92d459c53e9ad0b191a6cc8b0ea5d40238c0a2a6b1ff6ea067052e3011c1f3f2be098ae43d141248a209aa168b366ce5a58f41af04c86c45007ae4d0ba732c6b45ddd02d0896f276d72fb171e58393382b292af86585ab1f1155c32c32d74e7f1cfad631d8e8ec82553a5d615334ab97b64f35e2f9b5deab3b6cb1554571339adc8ad110059b43911247fc1023e6449620cff73d3a5c0c8c0bcac2616f872c54d981db99d70a25c66e0763cb9dd264d7da70897675d1b56c8948ce8ed420ef9a223371c01758d6ad2a74ce035d8a5e2bac3254973bf5ef12c5cdd5b0f30b39183eaf56b45fdea02a50ccffff585464b43083dde855473eb17bfc5380261ff4dd126d6618f132c4326a3a72353246c7ba89145bb2f2c8088031c32440df1136873eda8a5f563356573399d2a463042da4f48145e3b79c60dc8e09d1119dcc66dc6a361f602d61d61eeadc5aa3d9f4748610c5801f12c2c3924532efaa1de4f9043ccb89ef2003dddb062d14710fb89cf8f85062752b995feecb8f4fa55848d5b58bb7b96f28c0ff63927bfde78c7b6f7a19701fca479572fb3a81e63b2ced063f63ecb2dcfe013cbed45a09201d3a39dc1adb4f4597a169a2b251600a78fddf28c894b52517c09beb3a09231ce2b2b17630a829b36f5d2bda8e34f5bea21a23b4896a1a1b1235efd3be7f648a51b574b7e268d6cd3aee10d559688f6f6cb61d579597ba57f23816cf2aa52abc64c1dc425a8315e452c70438bc7a4534d98b5fa41a050231b5d87f549c543c8df28b00ff47bc3587c173044c41f5a010f3c43677919d72988f9745814ee5343177050c3f7a55f159f2000c41a7e26c9604f895fcd84643342255eee71855766c2a46317614c94c25a42dfa8051515b35a4cfd37010d5aa168ef02b5a3ac8c6cf8c4e5b5743e8bb9951243c100e74aa819c213acf9eeeebc3317408bf1cecdd5ff12af4bd2bcc51efe149fb531671f4cc3f415ca15f591554703cb5797ff0140424fc2b7b318192122966f2c606aba06f88f050c4a87af0d49e2d55e97206b89aa0dcbbd610971316b9979b35dcde14a0d73d0904eb02707f654804cf9e9d689709d40046b7795e8e90fac78c1757165749706a94c36088901173ed7f5adc8570d8edd89135f8d19229e7b281961ea61538e41fc981f3843b4f27ecb04a1fa1cb0408001c6605a5809974e913da1573900421b90505375de709d0c943a2e37cf7b7638a0b7f3d6de602e8e405bed211f9947a4dbad6d22ca5053e27a1e91931aabc8f84809a80b15408a5fe1515806fcc403334535869d97f37b9739deed4c399464dfb3151162bb1de8e15ce2098d1f348240361c031cfc46564606358eea5fcba21c5887eb22cfc422930b875f86b7433c4b125ceed79cf476d9cdbb16b2c362f595573bde2e70bc9b05ec447dc536fb1dc8e9e9d5b28122efd12c72c1bd397020f155dae9570cc92fa01d3ea0c6b9843740c4fee2ab4cafbbf18fd5df0636fac1944d48d75a03bd400841ec82b990512d1a636895b01a02665710aa16bfdb8fd4f5891c8806491894fda286d9c3c7a5d7956cb1d37761650fdb9762079a54f69d03497f5a76f4b57d374cc5b068f89f56b387880428cca3039998867342df589d50957c7bf0498a168ab06cd8d407b8fea5001fb648dc72da9c19117bbd37f54df0036e6e473ff262aac2ddc687fe309f1ae1f3d0b83314440f491f47fc40db7339db31b2b14e3509a5a00753866813118d05210dc14d7c19f65b1711621e83ab1f447525f686f37a15db77d9c2e93eb55eecb653b24edca375cdf7edbec90a67f7779d6456ccbbc0bdaa099c080fe538694a99dbd4a3ce5658d63b7e6f08c094f254c1d09586dee9f721e8c62ca6bd101c622563dcdc4775ce4e7b96b2e1a0e1b2ecc6870f030591a2a332fa34e324b5532b78ff3e3684c533bec8e22dc23015c0e7dc9eb1092f3c4da403925536acd08a8124dfc44cce70cf8517a3cadd4e43cdd5aa5237b361fe9ea9d796ac9264926f6b2d93fb41ac52582849ba009b7006e2baf8e08b55edee3178c44ab01a64c62f99ce07b237f6de75b98a5bfecd6b851449b22f2b130a8ddaec456df12f3ce21ce42770a3dd2218d81455dad7175c31529d8408e09290483800edd80ba99fd10485b232ab25b8abd3b82f56e5db5b6faa15e4d3e8fb665259d0b90b3e02eb08a566b2c541f4839957974e359239045a4922983fbbe5674e70795b5505002c55aefacc09ba5564307744ac3b4dbbd643089ebc0eee208d60a2c8eab6a98408674bd21279a622eea31a539632a4e6a204790860e2476bccce6cdf00269da13d97a5c03d5d003dce7672b287a5a190198ce3b197d40d5ac940c4d486aac9176ba8634e6658450b7b67eb43d27541cf94d8fd009c05d8be528e3dc4d20a23ae573255b196c30374ccac8ec096f7a0cc671daf11284b76afe148f0561656c7ac5fde4f699bd4d34059b064ea560f0987a1d575ea9cba7e95ead1a2ecb04adf137d81ef7b8225c1c303b53818a638606b25d5102f2c48988312361a6c97a74f466f1d22bc12b51070f5ce5a8c58f2838bcaf26ecc32527d1c3178b317605d289ef3aba08b5667112df9eb945f47041f6fa6e2d385abfcbe0a906355dcd59745416caa7e1c0625a72366fd2d52cbcc38b2146769196e401f98be439cb2fde793adbf0afcb5a7a999dbd72b3e54945e801d84b9fe73577e526f0a50557a036c4410ed84d935ed4290ffbb72cd069ee5da5347a2f4cd8e15f0dbbd81f18e9b4b937c83f9223baefd81836bfcc80cc0baea80e25d3399e9e403be01a354ae1fae41d0948c56068cf683b49bc77008f04ad56107bc6b0fcba0ab857317bc808fdfb8f53f6c05ea40c303cfdfa733f63b7cfa3688fb24c433f687017f30f147bcba766705a5d738431d50d3a16e5e6ab4e86e057648ebe4f083e5a01821874604dd452e669fdab6dfcde74338267b5a3f83fe4c33552d70f985c87d6d6e172aad01d8f61328a1456f3844b4623883fd5dfb7289173ecc3b7db2caff0dad5521092785e560080e005f6fd06e06bec103bda095508db417ac6ddb02b6d5d861a12a1129cda50feef7c62ccd2c68f817d5207daa9e1ee7ae33a0baccbe36aacd19902f454aaf3230691639e23b94aa430f047b14aa1796a1a0905d4fdc285107fef97eac5455dd700ef86a345361a30a8dd37ea8a9ff07e8371f542dc1ff613625cd1e66036f977d5dd74ba4d577de4d362d41ddae2fb611addf16557e999db2045bc99e45be1dab745796524ac9d58c0280e961014ca1b61af51ca97e7a5fa23774a4b5542e1b378be4389995e0640a5bae5e0c98bb4be0ea0421e34f486e7d335150e9c88d69fb65333b10c88d30f357cf66ec577077bed9731627df0e16e18731d70cdf28cf048a188ceac964ac21d101086ed720e6c770d73134a45bb56aa136e42d9e33a228f63837031f8b415431753c25c31353380e6212b04d285ffe72d3d9857794c8282bd90ffb448eac55be1f2934d0df015631890a8d80d6472f4e8ed78bd2fbdad09fd7c36f038be115b94298ed1128f9d8a005caf20e8dfca36ab62a4ca09ff178d3415a003cd753abf8a3f553894dae2cc4f418c520f33f4992c836170022b04fe21d12f9df02db8ab81dc1184411068dc6210d99311c1ba9fd75c9878b8cb4a653cb81f1f987806d6b57b423cbed19fa8c015e898571c5e12e78f1fb1a4b3e817f02b92240f8c4487247aacd3efb4a24de6014fa13f264bf461475ac3e47d2fdb5f9891dafd532803f350db67c395dabba2af1e8f36789b1ee1ecc315ff06c9e1b7f624b079715e96961b48d1d57f85fa9c6b17ee6b5dc5cbd245f14d72383ec7b5a03cc8a980243871599dcb8213802ef2a8d1be5a95a2d06586bedc3000eb59cc7d853d3b7d4304691903b520251b65a6101ad83ce51deec4e000c85277ffb4a5cb02de2a2179c3f0d061c24919f9e0964f946cdb7cb73281feeaf80e5617835491dccd24d1c51b40406c6e6ec14681f09b87853675d2c5aa9222da3b54d6ffac1317a84d9b8a0e89bb667ac77bb3cd1fde0e3826aff3a7599e63914d3623ecd044d87435a0a4ddf77be06a51a369bdd06766da9418060a8d44c0e5fd8e5a25ef1cbeddf19b79656e87151fd8f234af3b027c4e3145394b01c92bd0fa20cd2218ba0733a431119dd99d7bd3b70286eb6bc8735c8e1d371cae62a711f1e20e6c1501a2e25aeb2bbb258df5514e0e297ef4acffa5e1ff727d344448360c4440947b5196d9da9edb05490d848937aa98d8e37509be9b005727c29a55e3ebd992c32427da50808a3494268629c8e72097c065274ffadfd08b5f76e9123b7839b8e70b17d6f98f6e1771e112a552345147555435628fe7a16718015bc11cc7dd4ac8afe2c1d37f622d9ace927157ab781203559db4b7ce3cf89c94a9d11da74ae235592462a010459a17ec4c49f8aa84dffcd83517768849e133589f7d753a4d945124d3566321b856848bab3d566c5cc4ecc1d5728d8d8480da0510bf61a617c465d541f4624d1659ea44006e3da9c5e4c0d0abca140db44037e4df4ca0588c0712536376be23eacb6494dfa8b1e6ef1446290d964fa6464fc0c7636cf406145aefd18c9cff5e56839c88752bf34f92e8f26a78ae37d0e8e8e5e7aa3d5295a22e2d18b02e03226cb8fbc6f841f32becd80a2515e00202c5ddae57a215abdee549f269f186900c71382972a22d67d773f6b0af91b2e0ee098ce7dc4e07fe5311e60d8e57c28cdf50b79f2d51463a9548272bf8958bb03ad94820f8915eba02b5a49f731c3c328cfa3a0a29e29b1e75c9300cf11c4354a40d87572c3940c6c4fd1fedc47a1bd5850f10f0820e01a53035a12dc3c0cdb7e82edca8cf9f525fb87f4b3271a0c7d244ad2efbf375ae175a91401eb0b8f0d5e9125dd14d41fb4a99f4bfefee397c634fd2e664c92e9404be41a2d953c8c1520b651242579ce5703480d282831a64c03ac8a108e0f117761abb5957fb9f0d453d510924a2fc898acefa1065c74d62dd220acc4da693e81590b03f84f53d87483da5c95a28d335700358af3d1b4b2d2bbe670c6f36a3fdb03b530a3ab4124dc62705e5822bfbac53d0ff512623327193f1d584aff5625fc1293a27a3c2f7c9661aee55681ef62af0b8f1e115073d610d4cefddb9b412e631b12c6c51638238782a4aa6b415bf230b6fabe84472eadefa4ad3e5f5f37dfbdb5360357c3031d359a3d17a614cc292bba7339c1c2333622b42a2ac2eb0434233fa97ff58e434051c54eeb599c94c2ca933846e0a883e78f11e00aa52e8dc72b317f698c6efc8303c32a7230dcf6eda8cdf46a0bf82e7757bf0b9980d20796ea593e9252defef2f3ee8bb1196a67b87de9b04b3fc0ff114e699b78af64e644a169187694a476914b970a5be49bf01764962df8ede7ab60f5ae390140d157c9a844c13f170e841f362995cf8e35afe5595f9d890561d99266bffcd3c29e1656834b1675ad45a3703621fd24e5d4ab0c167df577ea98128d1d66b36bdb742918218fa93cb855ef7e8ef5e244e0cb9c6d8f7da37e44dcaf1d37def80fa5576eab971633782e42f364bbb9f9c0cc5f6c3710ab37763eeae98a78107a2df1505ae6f16cea294c508502304cb54dfddab2c94c22d251351f9915eee4af9e24f712fbf45010a59dc2c69154ad0fcf962f48f17a01971f81221b832d12fb61a3fd72435c3bdeac5a64694dccc7906be85058d6d9e6a0ed746aced691325c8c4bfa1b5dd4b757dc04613dd38121538ada05c4b4a064d0b06e3c67f00e14adefb556256a926e21c2f0de4b99670101ef226b25540c9d3cc41f17b8c435ff63e821c11e533a372375ec3e53f9a3898802f2ebde11449c568d16a5cadfb00951359bc711f37343374fdb6ae89abcb6f6f11a2ca1cf8dcb3f090c88b5813d63af18feddada2b27b7c9ec8fa5fa25e3488c5b6b148e39cbb576eecf4913bdc562892af487f42fe2c4df9a875b3e251007d29d8f41ee57be5117a0d3a2f1da1c1413b013cd6ea1eed81b3a960ef886b64be8f190663e77d0c32e7c6844f63a0dac750f76bde94d050b0f963940afaa915b173687035a32d3761e18acd31401ad39403ff7f20fe1f3c857f5f74b74928534ec00f70447d9f393f2811dd89e9d2d2838739146849289592f5a0259add664b0e8d23aee7c53ca8b202fcb2fe29d90da28812c44cccb73ff16af6599267079bd604a169facf3338c768508323fa68a11e6ceffdd843ec90afc6462ce8dcb86d8d18c8141a24964a4cf8b33a695d68dbfce1855de3385ff3b4c6376c58b692f65b7e038904d684bd44eba10e429f02aa24c5c50e5ed34a374dc20ba984dbc23307059a15f8da91c6d7016df9ea803527e9dc832116968e746ff5e0dad14b88c1f4748bb86213703f46da44bbd160b216550ed64527767da4e290513dd30aadacac36404de88f6313fcd228911fdddd04ace86937535708606be26ff7015b63a5ad77ddfd76b7a261ca5b353f0a19ed5b6934ff95a24dd15e51d493ff72346808c2d24eebf62449629e13182c148344482684764ed0256223ffaec2f3f79d6f0e06779f122a711bc5fc3aa59f11ac9f98d499f180b23e4ce2c076a0125f91e029d15329969e94f8fd8f7d83ca1715497a62c25cced053d07348edceb2fb5cdc21cd4e80a1c7423ba9ec08fd2f57ad39638a823c1e2145ed2ee3845f8836abb1b34f3a58ad720347382758918a7d1ef4b20aca11ab7b97b600ba853ea4e699012a78906870ad2042fe9af796aa8bf9c2776642ff1b6b2dd3d569e7f10c42ff8f0f784602ac8a00ea701016402051aa033013208e1899529d5051e9e044a4842352ca0982d21879a7685f809456a694371caa965584d0fffff6fe965246cdb26ddbb66d5bcbb6b5ffcb68f2074c015d0130019ad47a8b611e2f994a62c8c8b48d2b3bef43c1c7a7659ba66956317c50c10182040a2cd8b07023d336aeecbc0f051f9f96746b6d6eadb7de3abd53fdb27e78c90af8695b565e1c7697cc9e668f50c44fdef1fcc0ee9614d426da79dfc658a66d5c79c1e44c8769f18f73bce46331f4f08e0ce652729b9661e8e775a8065317c34cded16921e238284c38244688080162e3a0e9e3d3825fa2b1bcc440f98e86fcaab95f1d4df84e7aa2e72981984e0687d59575edbdb7d595756d5bbfd2da5e56e5d6f357d695ddfa6555efd62fab924834f61d8deffd799986811c063d7fcf751e96691bce0efaa66598d771fff9e775dca6655815b93704c5f16299b66daef3be1014c78b65dab6b9cefbc602ce545fab0fd6e7c6fb799986f988416ebc607847f1e33a0fcbb4cdc5f186a06f5a86791df785e01dc5cfeb38dfb40c7334f7ab23710a38e3f8126a97e2311aff4c285065e3baca3a2f2cd3aee582c94094c9f31f234478481365fdb22aecb69c50a0489aa8cbaaa8af9a49fa8926fa470351265489acf3cd37671d82d677f850594a1cef2445d0a46aa81b2a070a2e2b7aefbd43d0fa1120240a1c409040c102060d1c100f09d2e183891f806c26b8ac58528ace79eb9c75d679925af5c9a7322d927baaf13e7642ce6d816165a91253a63b8a15b7a4df8b09144927d7790f8a65da465e301d321d52044d74451cef44c165055ae4e375dc993f003804ad872269baa348d9ca89f19d29f9e0b25292ef54077534d5578d7d490c0df568a408aa9c9449a5b29d4c0d490cc90cc988c48624c7050c19aa861a62c186851c17306400d110b281034807100f5ea661dc874f83db4cb9ce43b14cdbca0b26673a4c8b7f9ce3251f8ba1877764309772d3320cf53a2edda00e11e9b84dcb30546b8deb6bffecff9edf7d739df76daef3becf73cf9fdddfddf7767777bd35196eadbb751759e79cb37e93c4658aeabdf77e32454d73bce9a35f59f6392b26a6b2d4349132d8ddc3fcb27eb8ceb32e2cd336124db7e5f2680fefc888e3c5256543b0c25c2c294a6e5a865d96d771f93343b07a0a1449771427ca7e5ec7919b96619765e2d2919827a00d6d0d417a24038a3d49d19ea4e87d923e3f3a8af493a5c931a8d8fb72bf2ebfdc5d8c63add5abbed3ae7b57777dddddddddab57afeeb56e77afb57a75afeeb57aadb556afee5e6bf5eaeeee5ebdd6ea9fe1eaafe1ea8fe1ea7f71f50771f5e770bd70f5b770adb56a7777ed9e5f3f8fceeeefee7b53f6b22acab1a5262972fffce8cabab0ce1e491365fdb2aa8edb2aefa1913451b6424bd24c53e0c718e32fa9498a20ca64ebcf39e7929aa408a24cf47e8cf363fcf831652faba24ad44587fd40ca236ae1e10ebefcc7e6c4f5518596c2d879ec4c24f28ef80c807de31b890902974fc00928c25ce759f822906a08d9b09519dcb1f988208ac60438c74b4a93c71365c5b0faf0e8c858cad442c18b1856d91999e1a0329c18305eb868b14204850900e908071501e283870e1c36846870305cb87cb5e1a42315440d516100c0bc88172d340e09cce525062c2f31909e034e88a09bcd66b389303232b2d984301d0c8bbd29eb7558767d9b5551f603a9c9436fe3bacabab04c0b7da2c0cf6a19765955c76d9ec8de94f53a2cbbbecdaa28fb81d42479e86d5c5759179669a14b13057e56cbb0cbaa3a6ef3a489023feb75dca665d865551f26e9836299b6915ce79d1f0597158bde7b6f110f4a9e30b2ce37df9c358010b4beb29438de498aa049faa058a66d24d779e747c165c5a2f7dedb01840813285400ad872269baa348d92a822a34f6b69e53f41f7d2d178cc9e827cd1ea68b634976643017cb7d14ac9c6db5d67a5bbded761b8810a864877c3b1082a201931c042000c010c00ce5d0681400061530bc448c5431180a46a330200c060b828140200c0a0280814000445110c5a12009f24c510db312aa6e3f8902d5808b9f95de29f4901079301cf2b1bb9057b766b866edd9dd5c2867a0f8c70074d3dadfa04cd38915d3a0ccd3a78c43d495bb3438cce59a76dbb3fac782dbe066bc46b7ab1a94c9eaf20a33d85f7b71a9d0d50d16b89601a7fc13b228a0aa012a6ef739d1a3c52ad7d6e3ca690c647f40388d86e46fdad6bb1aa09bfc1d6e67d60c7ee3ba01ad5222f6d3ac01c37f0f280c723428d7e67c186f2278de811f458f9862c9589d1a28936d9d9c0e518a7ae4cf3fb3a7b8013a5c56b7c35d72aec73ed944071691d1a98eafd99035e05ebe4119064a40d480034d8302240d8a503428fb8c6495c56c6421ea236bed28dbd700d02ebbc93e3a820d565c6419dc54fdb1e08042139d628382b9d3d6b553654b3b8c65d1ad9c6948b3c038de22d56079f8a7f29972a4458c4c0d7a3d908eb30236402126bf05f2f78b9ae1f777b4c370e6e0e628a407d1827f238957bb21479d716b50ae3962239ad628b2e6efd2888cb1f67c0d24aff9f9733edf5fbc5ece35381b2cbe7c98982320b241515ee494406df309246a711577bb67230b5759906c806e5708e282dbe134a206b22e4c345717a63b9f8abb1cff2eea607e01f057310301c32866084ae6c0b4b0d98effb48e365daf545de351ae6862130f06408790684f1ce7e8566c970927ca911f1fecb82dc36960bf0d0939db1eea29d9609860b44d8b9c8fd05170e5f0f3b1df42ecfa73a04e23bf74a50c0511af1df865afce80c53c3059a172f294ca2f249b5d55259a8ff623fb68a901d172f80f68f2bbae65ba15a024f78588ba640f681160090431386fefbe0544e52864f02e8195f9dba813fada4514cf7e092bae72acb085681ebaca543eff6461422592a9a7793982657fbf8d6df76f351e1e31b5f4a48f7c136e0961a6fc47cb956a143fb5f6d6e493fd4cdda3c2409253047b4f6f91b5b02705f745d271b13a203304386a3949d621a88a74d98f9660cba4646e753eba45645bc44676081e623c88bf9e5943964f5ac63a43a8547b861f031d181d1068130c570dc9c84b50647079c8f52864a514648002906bd8c7eab1c7403c3caecbd6b18e192d645d0447b83f0a52a04015180ac88e0c3c85a7c0e92b21724ee71a429e17601cf2aec9f6230bb6b120851728c4903dc73e1c72270d8789227215e1906d0e8d436eba6dc8149bd2416a508998d33f255c30dd77387e9b374ef4bb5f5a05ea04da6ae390601c770909d927478f5383022a58f91ab3135bb6b309b4d05b438a3e057dbb0a56365f3040c8e16ed6de2f89bdd5363b5cafcd937ab34d48e0a6bc9f11adb268b16ceb3a6ba96b3149399a442d2ff80ce760ace267057aa0119e182b5f1c24c752f79fcd08f78841d16c8282b67e38f2898eb5576ccdf6cce0cb6b8d5ec157ae8cf3c69af740ceb6fd00405eab73d2d456f08110ce2cdb5a9bb3b1f9a1ec3c45371ef646bb1a0e582d78372177a591cb62e98d6dc154df36eb27d0e6ad25fb353acc1b46f1ba592f8df68a296c5e415c496233fb6d317537f672166b9cb48472b9afbff9c06b29c77d60332a68951163483a4d4a68947eb6e518dc983823d9aa897445470a30488db6e1f9dd11159304b9a5d61cb5fdfc06eab41163e8359b6a3d0ab22aa02c4033388aa1fac94784d39ba13d9c47d3bd276af1614d091825d394ca0408bead4748886302da86185cfffc46cc0e917faf9a98d66fc9599d19b48dafaf7ba1c0e16250a626f7bf352705829637b133dca16a669d1cc8865f0408995a6f71c62cc08bbf4a998c29a0244867f41a478e8e3a20fc47b1b837a46f006ae557ddaa0c2742deab4d5e4d37203fa4c811b0b3077b9b3683f4f19403586c704ff3c1e6e682947a427fc835eea2c9e4734b7472edf8f07a85fbe3eacfae1daaf725617ac76d6d145803bdb88b004ec62874080632efad5f10fdf111a4106e9e48daa3d3d41af79fc94f18f2cb85c9c97cd32f89bcb27f06aa8ddc95bd6fd984a86e453097c94494e0f5e8733677aa0c1842900f0c91b8c794550cdb8d5cd2015a1e655f4bfb08370b61435f12671c14eea9d8ed858e19524095ac746f57755f6bddfbc7bf671fa631cb760bb245e98f01c99bf06ba34ea04b2ebd920bcd062c68b5071e46c65254711b952383bcdb399f5494c54e8b7a57078b2cec7d271d1982ef47813e1c50592f6a5d7221564cd6f5513218685d729548ab80ceef5478954dbc4ed6152c9962dae4c4826bcab16e8d93b3857f12b5b99712faf30d5003db14d1f6790e668420828edca1d73b88aef228ca02e39094c9f381c889430eb10bc2b63b42263f95c9063befe769f22e597cbb65f5dcbf5bdc8e2b591f7a49cbcda60ac8fa8b62c94abb5db288c421d39f999cea0747255d32e621fc0a4e9a9dff845f15ce1e9662324520cde48ca8e209d4b8e1a8a960345916120022c3c4885e580820f8db85a2fc26681b068a890844551a2fd189315df306ed13dd674f1e4b014f43eed9261601cb447c3276ccf924da2f19c197ab0e9c407260b448e0e85e1ab677cb8a5dadbc5a07708b3a11799b32cd6ade0606365c0edd46f2392136c3bf2c0d16b1b8fb4e74b008de2ffed53cc4c86a1c1f2f786118b73f8db7d3541503b4362509372d4e971b66318f3701ec9456f13e13eb2add627204257869268a10a4758ab97ce48cb3c5e9934d2713cced831876434178bda9d1e0adfef6addf02b5ed4fff6b9107e7433cde54b86d2285d81e84264447edf5fece9e45306f1044eb78f778289f609d5c8ebe1ff8befee402b28abe7200121f9f9b24e5faf44ae26f703887fd06a6008984a82eb943f96ef4c9a24ca54e567a91d897d0413affc7d4282238dc9c6da59d37190265e22694349a03e09b65ee8e18b760c26fd6d66ecfef747fa1f109af1437c38f9b6c993b4ffc019a718b86b8667f449070a3296e89dea56c96093726c56dfbdbe5ca75a4b1071df63c4464ff0b3704dc513478848c243e8c9b1036b9705ede3019cd563df38559f5654cc40d3e0aedd11012424dc2e48787674c7e7d8e356f0388116b4b37e572a3dcc645a07db596c8e80b0f88552a825f9c4c7188430711cae6f08b903a373c9f20a5c2091647e61290a46875bbd96227ebee79713b89c20a67dc22c6de0ed07afd20ea3e5b4baf501fcdb2db66344d42fb7db748053abfcb044de269b2095c340c347d97280f07f9b13fe192cc4789ed89115ac634893fee455752bd1e129a977ecaab475962649057910be11afb475a20de5c0382891719b2301de98ab996fc93117d460294bf48c0f8f1023cb4607624e086c0f789677173e1b3c97f467fcce2f267d613eb36062a1ec24d644cb02dd1b451acd1cfeab74bffde1054dea2d96e42856a2b8161793d098b986dc4525bf13edb85ee6143b0eab678adeec7658f96d01567dce8fea1f3f61d41a054537d8f800062c621091873054802314bb700d377fe23a81f4a546863752303a71bc162b6ea037ce0731db89716f01099d928e1f6770cb4bb0753b814463e80d5b6f2721d8102dbc9a37b72d3cf82d8216521c3f03a72db8a4100e41d2d4cffd0b854e66fd9e29f0277748488a0a660f8c3c533506d2b2f1de45de26f14e061d06b7c46967a48a5d47d6d4893affb90f3bb7d81f8c3e55f99be629eda0669feb4ddabaf1b498eb6893e6d6517c4dfc12a83561becffb57df5afb6984c69b800af36ac26f455c1255e4d9d6cc600b4190439c69a90bb4ffc3840e80be7c606ef98b858962f89120c202ec05131b385707cd8016248305c1958a2a2737535cd0d4cebeef99692c2de74f21612925df8ada72ea856056c379df33526394b069edb332b657286cbc65dfbbdd181d424d10651db20f2b2839f251a5e33ad2a3312ddcfbc8e0f21e6e6337f8ec7d6358e64586d458413800b8710d2d9d681b2ac8e4ecf27bb40dfca89a497631a645fd7f745d9eabfc9a45fdcabdb54d135a19785d99429772b19a9c5c8bfe2bb06da45ce067d39ae03bff0dc069ad67d9831e56ae86aa1e4b2efd33063681959a6735b54dbdf4b88573419abb401dbc96f514ace83ce7066b7a9a3387ca0f353fc6c6b4a73741b1c1fcd9e963ae806c8bd3f45452634f4b3a84f0eecfcd26c16bfde4850cbc8e13174bde15999fe88f71bdc3d016ad3302c55801655e722f3139c5f5f03860cee15f4aada13acd33a67c5f180a0efc470ea57c3fb835e5532ea8abf658236e8c6adf586cc498b43f3eb0b0c5cf7dfe1bfe33a068b4d885442d71c06aef5a85b5c5a5ab2a5945206c902b402b502674834fabd47a2d0d9497cdfe09c5342624acf9068442a8da0aaaaaa2524a6f40c8946a4d208aaa6699aa22321d1b99f84b4494ab6a9a33cf548a59133241a796937ed12923d1285ce911289a3bb84649bd0911269240a9d3b5fb59dcdda59dba66a4de747ee8432395153a954aa8569a0c6096572a2a6545555914c911265b249d4b4c54be57aca53572794097f1254eea4a893cf8f66e56f5b5b6b0a55557748749248a57d8644a3912874ee126997482351e8dca7ea549daa7acea8aabaf7de1b8742d56eb5daad76bbf1fe3b980a7e58ebca255b652f43cd910aa5a7699afe0ea6821f994c265b57b216476d4685c2ea9ca7bd76abd56eb5dbeda673c3e5f0d8e47674bb1e1fce3bef9c75d3b9e172786c3d36b91dddcec756abb9e9dc70393c36b91dddaec7a736d39e50b59a76c1b75bad5683a9408693c9522ac914294fa8d8b374b05ac7b40b8b2b84c72cb7949420fc8da89349f59fea1b0bed6028ae48a511f3d733246a4d5237b57fbfa537afdffa6ea1329d50a0121296159556cabae2ac190f9a8cce8e8e67d7937d7290fc93af88ddc872363e6e35369a76e69cedd011f3817d507e6e763a9589feead66fb7dbed26bb61d9ed865373eb8a533dd57d9e7b9ffb3c55144ad5f1e468359c8f9b09ea5affe327bfb6d4542a95d2d52841644cc74c6c38646a386670b434ab9a5255f584fa586ca53aa152f88bcad582a4e4047532e95465a198a8a8fa0bd37a4ff5d7eaf556dd0fc0dac2e54261a529243a3bba1f9c89b6d5ac2f3af9dbaf85f3faa24356dbb65ab7ba6dd7b5e3b66d5bad5bddb636556ed952b376366b676d9ba6743c3a2f05d3b00caee11b0a471b601680ac65aaa78fffaa9552a9542a5d0d096e88a09cb072b43968d8f55f396c3e3e3ead94942a356b67b376d6b6a9544a7bd3da7cfca8edd4e072723a58579bcdb437adcdc78f1a5c4e4e6707eb663c68b905853299b5333d9bb95697cb444742a2938432e901a6898e797c85585e735ef3bf744cc7308d46d3311d9b9d728907aadabb0a55a1298aa6b91269240a9d2b2bfba82854aa76dc8b8c1c1fa12dd6eac2f2af5ff9d7ea72a152c12fb90491a3188222acd58565052545a5a5a6694abdbb345553356df194b0ceb906ee8ec70d12db31a3c9d4722eb76c7c42e1dc8b0c96157e42ad7805dad6efae15d2a269676e3c0033d264720dd75e77a772773dd965c53fbb4595e5163014599867c4b4c92e2b6768f426cf82e2dd9debee52ee4edd2abf52994e287ed22a21d9292e14961556ba665cbec939b21d331e3499da4c4b63c33fb7d80d092ad0b616c73599e50367935939b91f3a3acc93d71deec141f04cb36aba5551fd0ae6ee6060724ebbc0e45ccee51ccb8972acb1d1e0f6eadc9dabbb3ce61912a146a4d2887762d2552a95aabc91e306be1430830603bb101196b9aa2b144fa5eebdf1c65aefbdf1c65af37fc95a6b6d2a474a67c8d4e863feb178f4987b576f16873cc620acb56d879c73ce39e79cf3cd5ece419c6fd6ea2a41e4e889ab16eb08efe90786ac11a9142292629e2111aaa5b2c212825fda5725a693e8b95856545a292cbebfc727c8cae2b142f150ae06bfd5eaedd56ae5839df501181f924de2a35957e4b5a71dd551bda72524227ce7472e3750c35b4d56225ec8b7ae5834edc2f22ef546e566e56614c32f45d9aa138a04ff0454869088e8f0c8323b5005d51404d31e9c9ef6de7bcad795aaa59e4620f3e5729162a5aaaaaa3ce7952acf7c0a2ec55ad3ded5b4f7b4a77d3da15c3eb1580a0a0f112957aa353457484a4e1e7532a558366beda9a75a99a4a8ad97b25852bfa2d24a59a9faca1feb5e726c7c9cfc68db56eb56b76ddbb6add6ad6e5b5b0b0512b4c4a48a46a4d2489aa629095a62524523526924358d94f6de7be768b519b5b5d5a8aaaaa66e5bf548486aa9cd4db372dbda52b9c5a3aa21d149dabf3727f5af412f8459c0620fe31ea027c7f07bc89e80b247d9cd11e400cc04e5356bf03f1b22b84dbb87e16b6f1741c68461f83bec36bc0fd9adbd1739049ae5dfbfbc0e0327d0630e6972b8c13904c9410707071df68586f8861f36dfb063f39f74a9575804fa94d7d6e9bd0b9ef7bdff177a3137795b87bde5eebb08f6963ce6be049a35e07618c8dad80a741bfa43f6776e899140b3f7f5fdfd3bc6b6a17fff3de5b564001913fcafbf8dfda7bc6634afff3df8fd6decbf617e71732c46c2400540d78773f109e6c5c14207bb5f7c09342b9a30c4dfafc7382accb0fbc30fc3ef4311fc8e59f17119e3b5bb092500ec305f201695808b0074efa6696213e37421b86006847f00d677abb96514df05f4a07dc1be2bf921fe519730b628767555d777691faa6e86227eec00040f3650e1c30a51d832a021c109201c7c40664c0019826c421f81fa40c4133d7648d800420f202c8074004203ba7d708142282630c25e9c144688e1fb91c2ecf321050df6e7ed9c933183060364c95e9cd60a5467c40b6f8ba0ef511899c5fd86e8d7cd9bd7ec85f90529403b1237d1c3cb0d71479039628e16860e7cb4a0c40f1b00a941091d3246f048220b118cb8953a18a183b74488715a1e5893bd38ad0c419462587515e4555fde8ccd4fde3b3ef997d47fef385e0dfe2541321cc71e8ee3a8c7518fe1f609510c760fa68ddb87e633d27a720ba6691ef60562c78fe596b183fd958345a150202e2177354d0f9ddea1697a46b7daa66b50a006c7b1ef38c5f2daa130f18f34195c1aa045a1bf4f4367a6cc06e3eee31bae29e10b1247fe517316c02e9b248000e8fe3df96b1a3f64c7dfdc349222be75f6ced6e5b64d5e376eefdbaed9b64db3db3db36b3a485e35ed67a88cddb19bbc661d327dd32c8dd33959efc8acfc3fc21d1e5c4fcd8ce66750999de6f18519b36608f7d812249e84e803397c146533d67145182bc6786756c332bb3f30311e8710c17135fe7d2fc6de55c1007460e2cfa9c96d17afb595f3828ecd3f3a62c5c17a9fe77dfc0a00a30007fbe98781cfaf0a7ecf0591c6f642441a5b7cf01bc82e2fba6c01037085d4b8710520ffcec82e1701004030f723f0a3089ea0f22c1f5496e55972d35996270882231979dde58b1979dd2ffeba3defb7b7bded79def63c10b8c12f79cc66c7f1bd171f2496e5389631e3383e3882decbc82d21bf7f068d1d228688e54fa0d9b2bfbc0e962d3c305f34ca458ed9918779cd62df79755d748709f60934fb791cfdc0dc21181404b9800d08346b8aa141501c4131bcf741703f49bef6e63a6798052cb8410ed32cd8637c322447bc31f8fbbfbf9f07de7d4720f73e0604c1d7a0cefb3fbe3b2cff3681bc7fbb09c67df05fdcbe6f89efddb87c21befe0b43c459b0b8c47fc30c6231fe6fbfc85b201fcc97c95ed63dbdde25040886666e11bbf8e493222618e28f1fb359fc3121fb75130cb17b1f9359f1c51e03f7fd217f4b9801a34814128542239833984110148542a2d09fa407821ee8795efe46a4d17df145fe7240bcaf2d7edff7f5d7f8a0171f6601fbb1e2c7619afd46bc07e9c93b967a944e7965490ec04e25a8a3e1cbfb4d1e8059f27f05d36b82f576acf924794bd0e52528f4a217118542a233f4217b9a2152448a4851c8fcd34445423848fcf285f8e4c761ad757d6176fc8f9f4e79c530f5aa7c7f717e72d88fc3ee5519fffb1274125f66c8923d66b32347c1f37bf13df21b3f6e1a45f1bfeffb185114c50fc910ecd9b501999fccfcc56563eeddf96120bb3f87c631a4f731c4f73eb39825bdbdefbed7031feb7f85e10772d387c15dc493f8c31ff8a1d61368165c60bf47621284c7f740d0f3c28d6ba8b4eab7a7920d0100026318000083300c436110888124ccd3b90714000b4d746c5c50521e8cc522712814478118c4300c043108c44008c34088c290630a526703c3054de9bab1597530f89fefd3a2ac14867a370f3e88b3ca825664022450a2fc2f279a5b6a461ca33ca9243bc088e29492a50265356ed550052e71425ac23cff828777eeef7ee8a55a4dd9cedeb5c96a26cd01d34393dc78a5b8732f7553b257713fe1884f8ec5ca862b0b71eb16acc1847c1789e696fcabeed5b5f7496c5bc9a6cdb5b4f994abe4c99930db9accab106a8fac4d7af1ffd72cf09d30f155fe2568544c68a3dd1e15935fba29edc4c26edb46c999b07d601e0560d3debc713089521f485673aa27958f1568c2420bad1e314025e93638db19992e9f00a56d1285a39c9046825c18c68a8b42a56256c93eba0a5a300595c98b4260bc0a1694edd466f67b7f43c69f89698000a93bf5eb60b3716228935401f24bb0a5b9dec89b70cce29dfa1d56dd3c13b89c77b256cda4f0055b70d84dbff1a0f78cb81d84e07e8bfe6fd19ee64d4d3a1d4e57fa5fbf9860029a01350ef5223ae5270d8ca71d3862af1f37bf61d6961f83d81d7a79371fccdd3901cf6431c5a50035007f0158130237d4c88117809b8558d4eb828f1202c64224b2971868c0ce1dbd885e9b39587b82db93e8217560603493d9cc008298805d8fc37e6e09a6001f2e0765c59eb7d82967119fc32dceec982e4e13d4418715932be67471bc6a71117871c59d320644513ddd8fa618dd18b0a09ea295b40c0808f48cb75dcb517626266a94dc0055ceb7e83716e93c85d5abc426a7c5b165d532ee76ad4c501a3cab3bbf9d2b79bbc5697d28ce770b702ceeb2e11428a3de4e25d842a57b70cfe5b1fe25b67fe99c0b6b47f75622bff92ad486aa3b7d93d0e3c83ffc321a9088a5f96fd238d22f5a38b7852a5d26826cb9d55b80f514033fceb9989afa05fea68e49a6d471e1f4162b877a73097257dd28b19675d44b72670c6ae0b540ef833151698a9512b011d69127552fd973202c8cfd20ca38879eaca4e5be22976f9f4b2e277eae6146734c8bd4b5ca167ee8940584a2855f9768fac676d1c2f5bf603bc8d62746f3589d463a57b2ad5bae880f69c3f3514e6f5a98b634c982eb5bd0fc699cbfefba4728626f8eaf169290ce75a43f1a77a916128be555223fb5ed9a2a95126dafa63112c375d8a8d24bc25bbba4e5391c59d989278be30f908651a3c1ad6359a2705ac30d6bbc4167360d331e20b185b186568c2750a5f6b823bc1818585091667294947893c42880a1485da16392cec3d40c382abe4151d4fb60fae597ba4a2d39d2b0accfed2bfe0f8938e2e928447b745f3a8c87b6abdb699d82bf14f5d9ad3377fd72f87a5ff9385e32db442a38a9941cecc4c7af02defff8a45d780cf33755e03f6c80438a7f858f35ec48beea7a775a060b51a5574e7aef4bae059549f57b4164e6b158355f855f9bf5c2c25ca19809836d2ffd7c723823333e8952b147221f872c8c5e8d9340a64bf5706fba674b33ffd51b65ab5e42d2ad596c151301621846c1c49791b3546a5c25ec149e754a490501b33299ab634cbe29cf8daa23ad9c14b4e5547f2fed8f029a8709408fe8b3e7e8e44a0d63c94e4c42342df42161a5a44cec190273c35951c2674e4a74847a0f7b73a21ebf37459ae10b54960d081d6d8d77b10743089b60bd7fb0efd6b4f04aeb6d107327922fde8f45f74462ff4e621c5ab496a8fcc970b8fc2181bdd3057d7f1476023ed503baf08fb6a85e977623fc65f9bd91036061d98dfd0a482a2da641253dd1e8f4c8116c440db7217f2536e2a912ed45710e0bf18728d4fb126306d6a0a3004ab61d1f1139c837eed0a276b74744a18fa69876a8c327fe23d13e4531f6a21cfe5478977ab13893f7b9521f484002d5dd3755b38b1f688530ab5edd4ffa2c2d11045880119b8a1c2a35877f0709a0f64e02e4861190db1b9a8eca377ac7f2112899ed8259246ad8fabc8175c789d1a6f09d0e25945485604991cd6e46c361c1bfc6464403f2deff2eca606e297d7412ca083a97b4b776eb3f8501bc952606db46f9ec29b5e91041485a77103c99d1b669ea34ac75656d22e275402da1e9d0dd7721c0f15dd235f41ef1cb2c84cd8a0deb01ca034fe99e32c6ba5a0e76d6b0587a260910d1e5118b2d39a5f78b75a3acd60b009343f2a6d6487e33717ee8bc73b9dfc38cc24a7889b815b11c1cf35f95f798945da20ba5af58d1dd49d9414e6763797cc78e36d1ade6a484521aaef9ad680d9f5f25e2e77d58464a315161ed3ad19c12bf31e31c75ad999c5004c759e182d55d145333cf264e8c5c8c24d9c2cb69d887bae45ad81e54a2e3f0ca80c99dbd1a4472652da3ddd71f58c2ca14fa4149df079f751a78cdd141bc4ecd0a6dd14615d8f8188a66d5c1f33e691dac2aae0beaf513179606d43db0377cbaac182b681fca1e344ee10a5d87665ba1b8b15161cc7ac2fe05b4c547fb69438b40efa404a9461f08a3a1c8286e29aad96ffd26e43c904aa16c036a347784a255838add233e0d9b267c31f3c0ba24db8333ca524b463f93efac48038fc3a2bc3678bc6f805a7bd042b8e0518dba7fe9e3b358532402e3cfce231c9454d834c53a8b12e28934268f8859d78d040a9c81471279819f308a65f0243a37784d4b5223f33e0ac324d44786c5a9fe55ca4e19aa3c17978c2af140d78fd13347591c3e5563a72e25b0be7a855d224744b2390ebd2a466b87e9515441e4784ec4f2de4698019e01cb580db4ed78c21ca25ac1940523d0c22ebfdf9c1088554756a0e7f3e481b4f457eb31829253afabb8402cf2ac0fb69cfc59782a61d81ac52e5deb9b83a6206ce3601dd3ac26e0447c40b80be9ee153c69372210b4c76476fe656b59caf2ccf9ec9d746eccee84e720aa5018a50e323417a8f695541b6324b64883485a00f1195b10093ae2163f024fbb1eb6c5580ec6b12be957dae11c4359aa50dc2d8ae92800a9a36a14e4d092f24e3a09401f58d1582ca1858232edf0f9df4c86e587d246669083e647765d4925598a2c23816a20223eeb5522c22143f44d9a2d3636710ede447e0809d3a8915a9a06afe1b1fea57a0dc9d3e31e23b88a489ef1db18f0de264c9d3a47c0aa28c1a57e9d0509c15e34ea84c88af4ab76a2ba6002b68aa641246327d700f9f6ef3e92604c84052767c28996df3949f81513391e0bd42960acd0831553a85d4a35a2d888a0b8e568e2fed1a418d57b25554828260927e00b6645d93ef581151d893a29543e9093428ac732ba9e4904d85eb57c77fce5cb8e787c9d00f12225639c80fe9345f9aa2c012a6c5947a025ec3835f9cbe3420447ae214c22d39a72a2a754cae7edcec0050d3f2d6d3dfcaa335f58674e15cbbaa86a31d62b01a892d80536af7386120125427c80cacdf9d107d0e41c707d9072da660f562c698b4b31cc8d0815a09177ba15d61102d8b017837604b6dacf58c7980c2ad5d696b4449056882834dc4f57d34cd131b7d35f3c1d81e3bde8210671babc1ea7027a082051eaeab51c9ceab2dd768546297dd552761f110851940c4b8bf318453423a6c76a31f2d9e901d473d1585229c5586acd7f6cfcc5153211c11916a707adcb3e0da2401962051767ce1eff374aeca03fcc2f139f9e43c5c03c8ceb4f706a39b2fc493f935b8dc35370c9c2f8840a9bd3c3203907e0e81d89c14b8b66c5a0a14556c8705d8c9f530d1a1eebe4de620b7495c6aab737f3a51393da28986b34dacf0a00df30a6c5f9ddb39d159a216f1ad0f7f3cf0a02e344a7ac49594c945a88203f49c759e827ab8ef34ebbb30577b801583366b28c9d5c61701b949ab731ea68fa488600d8c45106d8a422980e73b4103cc83be385d675628fd14a9f785dbc2641613faef44d0f6032681f0d056556eb0bc7579d03d91c267a5f8b0a2594a5ab8bb7957c5aaa43a48d9861657a3481264363bdce925b9242a02be2eff2287818ecae9c6e4249803addfd07050ad82bc50e9659108a230af8d6d7191cef575e585d8ea56873aae324dd7fcd575f20f39878a54530948c8eaf5009840f928db1111660f33ebd1bf22e74d2c758eb0a88114374e1d55cc33e4bfbfd093580e779168305852a1fd1722f482adeb07107522203a9438bfe6e44ff08851a4fc5962441e86940be76f906905434daa22f2d27ca533a7f9ed4d1380473a3c8861ad07181ecd358287213ae54135cb6b21b016f9870a92fe1d2170aeb70874b46069786cf6b8661dfc717ae9984c1258c461292ff1e8ba5da18fbcc3470802bb4ede77be371663df02cbb88fa6c83ab5727b33a8018b72717991d84c25d35a165b8f41a7c28351bdff5ad3a1a1112b76291dfc2234dbd23e5d9e72441cdb7308c50ba09cb075982ef263b46b827e87be210eec108faf120172fcf270e22afff66a9d044d40055882816296a8ef591722f2ee406d61d2032090d842333844d8cb0100967796dd75963fc03b765208ff7303f916c7dbe509a925484ec1dba4592fbefa6ca2fac50acdc0753bf77f22ef26019d06bb7ea03b9da7bb9a0f6c2022e3cec41f8ecf7bc0114011b14ca08a881f6aefca450a6b96f26f970b5cfaf03c428197c3b3cbc7674ffd4ea5b0bb11bba85db5fcb22c6fccc5ff350e658c03a84b844fec308467b96a3ecc6f300d7dce204ac327f0e094e10e272bfebd1852afa086037382016fa7af4c0bd98101943616363f359d0912844bd9335079945141624987f002b901a4c538758ce3b24aa5a95adad8863327226e36d9c93da991fa61d915775ebbe68a54dc2825e92f52d75c9d6ecb16d5909b997d0be4933cfbddb4260a5807dfbd4827f1995ba77c51f3934ba6ed000ea57d8fdde85d0c3857c51bf59d5f8432b45bbbdba8bf496a29f938c67998a256fb752647b62a7cf2a111680a8c87bad6d8414b33f7c22e989294f4f9943c3739c80768a3abec0ea9cd146ecff2026eda608b3aaeb4fd0fef73aedae8705e349041bc59f557a5ab3d62a88a32a2ae5cce84b550af0a6107b39954151644d1b772e6942fb5b78cbac5710336490da4aed00c3c5b5b141ecd394451307d7c1b050d164cd797f0d9ab05f1ef4c94643dd8c62f747c76d1d608459b40314aa423c51beacee04e24564d1a8f0576c5cf2138b8dc9210f669ec6c6880071b0fad0b159676656a257ef04e5318fa6f0648f8d6f04c0e2bc883983908d4395ac93a8c2291e2d9c496260e3659e5c0b46720def3e18cb4ca03dd36f98251b63c8b27f4349c395b6a6e36c72af85ce743e448a8b40400df5fcb86d1864cfc92de4d613180d1716407f5cf4a6c7b830643d3f0c6d5fd8d95c04958f3459c1f404e417b6c5e53b7a40c8fd0d73ab80e8af7b10c560af052f3796394010b589cfa981cfd96dc748ae018754f5957a04333ace81efa16ce8786f403fa2c0ae670a40f834cb5576ec5f261b2ca9a212d7c0e77d06d5f939111b536f1c85142894c36bb5d0c573e4a85b7b163df5a72117908c261def8bf90f5d2b62730579107e3d6437315d23e16ae3b4cdc6786b0a80c69cc02c8a3989e622622385c5ac1b1663c37522f62801b10e03f42cfd525279d1312956c75369023a9ec1df02bfb473d1b1622dec89646782d883dab127b0f088b526c8c87718d595d50ec96a77a181cf7bc6a1bc9783185c9f8eb5de6a2aadd5b2b2d64edf54abeaab35bcad564357adfc4db52a3e17be60e69a072c83a0956e39555506062b9d9509cd8101c586adc7d15c5990151ab9317777c5c2396868a0e292bf6a5ae60a74f1da73eec08b76ecc436dcb304d1ea0d594cb82c0e73152b269ac8fec1f764b2311a00e70bd2e47b62246771858c2f50df65c6895b2d0bf3b342f8d1e5c087c235d972d92432c3e30dd2689cd0f39bf1108c433aa11dc0bb87aa930c5e563feac19b7a2ca79c8617639ed31824f309529e1ca601bb5d0a6b04122612946d93b3a45a8e5c4b9c0d5e2e4161aaf252a59d62f3df186ca5c2a5c21b3b105e3316bcec0e4a1d6e92d20b47ca65a8a47d7a43c9a50aaed1cedeb797d2d95481a0c0b78f38f0a66b1c921513e0c8da001c25a0d555516b742900387420155b21aba135995ea609985e6ed774f017fae0322f03955ebf7a28bd67c7cbd3654878250775a9a640a437c22546815b8db85495cf972d9332d526c97351953581d75213fb6ccb465a7ccfde46dd939aa39814182915334495033fe45023bf991a574f061e4cca3104beb26c52fd4ab8fdbb0047b011c5ec5d828e15cea3f09c9e0c11ef549def2a9e4a2bb266b1d572249c4993ccfecbbd587c93aacb4cb21c29d1331d9480359b9857330bb83b38675258809e6afd72fb469150e2f8f8033841471f96f2b2f7be7ecd9bb9ffc41935a58a162c33093148834214b40842554e4d30e66100b44fedf1011a79caf41dfab7a71fa0da0996dacd98f39f1d68d2a02af5403556404f8e79403104244a0fea021b0de901aa59e1c4e2cdc1a9f13eba816adce431a8f0106480838048e47087e6eb5a98b65a405595a671b479c2576e40cce05645cc1e12f25c300c03a5e785cd25c3bcd0d0351c2ac32ddc6da8000db3a8e533bbed952a5e56b32f8019cce3c24b86911b64a38d32914a9391ba543e82b3b40c3c4913e8f255ea08ba246cf3c8f319134eb08fc9ea87d91ccc418fd255296d90d27c84bde9424c2b52da2f24e8327ee699765e30757c36cf5de005157af00bea3bc1de97e990ec4a636552b06e1fd96a91f94aab725dad00f6a6634997feb08b652b5f9a320f291e8deed1e5348972b698d8ec12a12235b1678b292307aaf7bcf0fea017bca03df389db32a6225d9ed0f79ac43751d2dc172d2a38c29ea1eab50be3da51cc7bce5d6a9c018468477048c859e6353752f287089f6b773a8a3764dbd788bf874869675186af27384d247f2696250affb450622cb2381259f30355ffe9b865f907c5771611737bf739ffafa2beebe8aafc7a093a1b8b69e4d6cdd5abd028922be1e4e489c3e7623eefbd98e02457936e5382a5a8429d1e99d6fe43d4e29bd045b6bda53e06c49e84f2a2d33cd791ef10c67ef68708ebfef48508770041f0af97b7213b46836d53516e78865bfc98621336e00d93a8703cc37307f164144d19508a43f2aec08416c65e6432d4169511b315ac9b366ea3ad2c58165588d2d5ec8de8c920fa31838219e14d41f14bae90362aa322a5d22468f6dc331b6431de62d9651a4ca20822f41081125eb30d84eb9a20b30db21aea674c173793128494605812d8fec519609b383d2dce9222b6337a99779d40f6eec0dfa78b21f0c69403850e44993178dd960ce1e2667941c8146466edfa9ee08d85c4523ca0ce50acc570881eaa1631ed57c3b45ac27427eef4611fe61421c6aa78bf3873027dab01e9543261a191a45f640022a24da85ddc8906807c27dab7a60ce1d030850b05413c4edd10f38de4fb4cb542b3a190315b7af0773ee13ff92a1ed317c5ed10d314fc40f509e4491ce54ecbecc9180d9251abaa05091ddb12f49721f8b11a5f617b36b4dbfafb98f8a46a4898df272ec90bb25d8d9603b6f9293ca2e0d6503b7ae0c90ec53379f489755edf0992f37188a7150888c702353f35418b4c8d9c1692665975f5155695b7db87e0a9770422dcc07ac66d0f65b59801aa43619ba5a79bcf570722a9781c83c1026a7a6edb7382e5e7c87f3dfd134429d22bb73c0b0c22083fab503d040ddef640101a85eb56db73f8ef733aee4ab1ea635193fb53603624bfd72046e0b11d88ace9952e998108fdeef61cc5760eb34cbfdaf18fa2d83ad843e4fdcec8bcdd93f75344de1a330302c325f37ceff61cb2d7c8b96ca1af357b869f5a32e3766f8f2a914f0bd1aea14dae5c885c74aa1d7543acd6e27f3abcaabfb0e6729b8d29428f313f84a27d9ce85b8f16a226a3d821a21dbea78541f7b435af3c8d460cd17681ca8f0879ebe134c203f7b62bb6404cb40ec4315f80753890b1481f9070ecc6048e1bc07ae5a085ef771e440919f1ed9147a01e0648be086e5fbd6eab643aad9228df6c6a3dee8478ed67621376809c81a6c508f432de18204ee95f34fc9959f8dc51bf1fbd8fafc84484ebf5a152b00334e49118a128f009e65ed25a677bdaa54023103f639e61c912c3da1907745f28d2c9f61b9e9d1a1036a1e5eeb3025abe97406371af6bc1c8564b4ab38b8a15577c25f1ca50303d32cd6849dfd6bf2703fa36f8543f9237dc6a0677c6d3c42148bf6e9b4fe7d3eea346725c0d253cd239f6a29f6431d7c1881e7fd279fde43506d1ccd48068060e810569016ab6d1c60dc280a3b41b222f8dcfd4a6c0200118133970e3c618d49bd6087c22785cb109962a1855a95fc87b77579be6f4686804cb4a6491879eb8008d25b8836cf23d74bf637788a559462d432121a3b03401ded62abea381bd94c780e0c79f0d8a5a7698e0284ff2b1b021a0245b56f37727991c341636bd671b95cf44c69db66b937b8602424830118285095bc79807a0ce3d5194c17c51121ee79436f90675a5da748579f25e7281374a5949a4ecd23b63e1a970f54ffd142b553c3ef969071429c38844ba0efec0d05c5a9ad445ac078007a665ec1496cc8cd9d15a0af74851d2b11e887c87906195556ff948505827d66ffd91a1d0c1bfe98b28b551523ae6d67da2595de36c0e5198add3d89246eb21964d60d03c7462239305e6facb35e078209c450755d9b7804ca746d3ce64ff1857d02a0c515ba90ca2805e09c7a414d8b12c32f0e5bcbe71bb53143be4ff1b247d0c3864ebfdf70e7105ca238a5d681065bf8fc1dd20ca2b98da7f1da1a8055797aa8d5cc184d8e94f33cc02a5e771932d4050b26e9f2ec1507ba82a1a7c6dadf6517bb4904ccf89c9b8ed4a6f4e3399cebbd0a674788d439851f6dffca5c5c56d06c536197b209dc1f91d9b9bf659449cea0a2517261a5148168ce91f27dcc1bc4f7a058bbf2b0ece9f126519c3810c0ded1601fec02cf8f4ecd08d6035af5b56b2c6839f7cf6443af27e201db829c1ab8f1bf7513da54893d065c0e98f486974145067faf465e05e3166448235027c6a4618c4d88153d339c19bebe060545a9ca6000756dfe6ecc9d68b59a3f34e2368405dcc45d4068462c272fd985d99aab20b42a81ceb3f55b55f01d54656ff9c5bd1c0e49649b1046917e342672e01cc1a2f19fe5aecab3af4fc58470f3d0665c716a08a896a7b8c2d7a4c211a8f1fb93b5e7ec80adb4d2024ca6f2b62ab7c6307ff57555978681c2298881c212536d4c770c4db51a16caaade245dfd8cc83e3e8367df17d9765d177776d9aa386c88497394aab6245ec0e792e9addfdc8bc84cc6725f66acc92f3028e94866349dd271b30b9ad0a2245e4efb2f87f3cbbad84443ac286ad4523d454b7c26419c6b6f0d9a7ff601a9f36c4e0d60aaafcbc5681e6838baf57284ce03e738ac70de6a578507da6619daa3cb9e4ae81d8d21a75eacf9a23ce7f0dd9233cf7a80feccc2596ce7a3d1296758c5f59120dc3b6b8d1c0d905ebe4ca3c69cb9a0c54016fb660218f8dbae929bb13adb94e6a3d511aa584a681cd7009bd23e427b2eed3189524a6ef8081595ee55d355d72ba17140dc56af2eaad1f7aab4234ea63947a470466808dc505909dbb0a42f41298faaf1e2ef78ec29cb1db9bc6f5f5825902acbe81302399ad088efe2f7c4433cac503120ee4d163f9367c12734d596e7a865bfd98a20906d2a34988f98831f49d52ee4f81246022155c5a80b6b2790d1c8bc7d802d406389a9d9810cdc002eee5072b109c06174894c013092b81c6586fe819e05d670da02cd933a62e035d488e34eacfdd1af0c8540f406cd1cc607c6e19a415ca000b8b0cce140071caec8b8140330ca2d1c1c0f80e1830d0039ec0229cc2fe0c9a69a94e56b705879f02bc251e160f86f904d56e2c80907c6becf3ccd8c5461633e298f8427d6778e14b6237035f6130b942669f452a39863bac7a35529224e804734071e6adb6389f378fd7acd421c9140dc8f848f0287b14f37936bc24fa350661766a406c024d023727f11214309e607ae306ab4d81010ac880e4c00c36e766dbae358117891e5334c12a2a5691793b41f396265d62454168c748c4d58432d4232a285c0dafa0996245034fa4a328f1953873085c68e0f1d1132e0909642b7063bdcaa41538ec3027585efccf85eda61200f637dac53499beb8163360aef4ad8cd33c009b2fad63b3d791d9733d0dde5adc5d8305e78be2f640dcdbc69617c9720d93820403a476049a5047b258200c5a351da6ed41f13dcd273a8d38287c409df3182f9b932859ae0aff740623d58ac17b1339f0b0f0b501810bec32af41e89965307cbe2e2a690d83b46f4a8dfe0bf4be5d075bf66a27959d8b976e64efbde5de52ca2465a50a780a5e0a634a701ac7284933a4c782f9887dd25d1396202f4001b2ebda4aa224883d4b9cb0e9c28585038b4db1bae8e9c265e5fe3892424ebb426e5e7aa4459fbf4fd9be67fe1ce5761956123efeeffb445114cf10c2d0e20fc9a66d41fc19df6c8188b4e834f2dafe340f91b436447e62e69c50f32162310384105c4de86b90b9d25a9e4bbb6e590837f126dec4dbd708a2868e02574654a7116efb1b4d191985d98ee3fedb37caf2a45bea9cb50e2995279d46b7299c91955118a3ab206b020808e8456fb4a4d679b4a406474b6a99385a52368e9694c1464bca62a325652fca464bc6f468c918d068c99889d192b158ecc5a1bcc513228ad968492ca6182d894515a3dd22d188bf6ffcec16f1f891be456ffcbc12937f2ba06002bb8248450a9fa1383124542900bea2d8f74637ab54d46574cbe60645fb2b5dd0a3fa455df573515751d7f821796a328834410291e7ddf63cc7a2ada238453b24fa34d2156d79d269e28de258ddce93ec5b75f9aa7d6a1c777fb1d6d2adbe324a46a66e60ffab1bea69532c28db3637c55aa1cd36d219adf1a4074110042dcd0bc51fc7703cf1435fe3443954c1abbb2f1ae9ac92d1cdd2dc2beb0e8d6e54daa8142d4c03f1611d34ed9c29510350fc89af81a2bc209cf8a1f751c3c7897266694efd45f64aa31bbd5eeb536ade8701450ffd893fcd5badf60e1f228d8ed0a35a1add92e8efe9a6fb34baed1a21f480b2dad52fab9a2d2a57b76c519e9bed7653b8aedbd314ee4a0994d1cd4d3f12a3a3ebcdd2cefa54c3e8e649f6882b3182b2fe46519e74ff6c7f232a94a96e6a6daeb5eaac528d6b9586deffd69c8d74f63930d219e9ac92895d35d255a0af7d9ad802fa1a2ae7d09d899d89389e4474fd4d6c9170b190519489b2d920d09d9b26be5aa0313ae2a63f96dcbe6d37baddc80ca8fcdc6a466b4ee0a08d76463afb2676bb9da5f9cf1940137d36ed8c6e16bcd1a7d1cde8e64958728019e9dc74333bddf6af61954cec4cecac899d899d919709a7a1a95531d8a006d0426e499b6201d96d27a74db1827c51b0299610ae5daf3c09167b20af7d22c3b00959e371bcd23b54c77a82f431fb1f2e6afe432411082786fe84974ee52feea720e9762daa54afd094a14af576df48057dbaae87a5dd17ffe6e742b1822e37c50ab2668b36e3ff1e6e9e58c5d7638bc60ffe49bfc0f7e1e61d7f04fa60342600cb6a6b1abfc2bcf1c77a8bc168d4fa0496c105c9722f78bb22fa222fcf7a8c31fef2a4ec01d0cea5ef42154ae8b34e59c9a62a551d227d0cbdff09d2cb2ad9bb1563b83c91e86820a82b93eda0204abb1f94c771bcb2b4fba3d6f729bd2ff422b540a018be75ba7fc1315e71baf4dc2127dcbefbdada7d31049f3ce9742aa8b32ae9b22f3622834040210dbbc39761778862055dc1a6584e579bc23e70a2a3fd4ffc59af6253fa745dfdaaf7c4df5c7ee5d583e503bda5e17792da3a75a7ae77610f440a91a7dda7e33a507710797a11670ea42d7b18154f12130524e738d763ed871d77d65b7d72338bc9c27145ecd3c36cd3f33c0f973c7ce300faf0efd7db114fd27f5f0443f2cc1fe6f7c88fa4a78fdd8382d5e6e6051a817c4702953bdcbc40a56ba23cfaac502265a21b477ef0ef8ffdd108df0b3175f32371e0ef14eb88698ce17bf8c11ede7bf8bb347ad01033b0c5a7d5461221b940bab29e47e47d3487b3d96c406a97ebeefbdee78e75da17e6b43d204af659e45ffbdada696ffb7efef0d5bd544fdd3ae996e33c49f617e7215a8281bdea559e7dd63844ecb372ed8b679f458ebb5e0f1fd586ef1e2265b416bb71dcbcef91bee5e67df15e9806b10f46436f59597530b25ec5c89a95459faef335dac377f6e9776c76ae7d2fc6186795ead595be67b49e6c0c8395ae735357f9ec18f4e8fe102980235a5be4931c2c02fe44205822fc43441140f1f651943ea812272471a4f6c3a99e7829a136f4b6f4f10326c5842d25d8345d4ad850fc0f9a07cf0a5b6a28bea9466111b04f1401159fe255943e846ca8fd98c04b6de853943e66a58fa236b51ff50a1035146595f73f5cd486caaaef63f80992d6b25b91dec573441c10e9fd951db8791d77a5831b728be3f0a8c3ae1b224f90b4b6c393c492a8c6a6006945bfeb28edfe0571198255f2bf20048d99f2aaf9c7f013405e405e80301828d1d55aa9fc3226f9edbd3e66231bf4394bf21767f6ce3e84d9159a95e5cc5e8045e7fbeed696d7912ab029608dd716d60d25c0ba210e0537a9623bdbadb52fe36e3bcbb3590d9d445a84e4479f79bb7093bef54a928063c7dd4433ec9ff5f1d7a51d779ffed44b186e962e9ae8336f5a472d54ea47a29452aa1369d1e9390cec8b4bdbea518f6fffaeb8e9736989831abe6d079e44310c34f78aa29fd14bf5dfc670d3c2b83ffb21132aec8f44afe21da601113db21a7684f6a4ef7ef79bb637ed4afe258554bc9344e528a4a2cc6e529807353f8eb13d5c24c5ac44519e28874a132079366d50035c12d1c88f5f46bef7f3ae50d3ae42fed7650f92e36752e8ea3fbabe90930913330c4cd0e62ce8f4afb1a75bf615df1a2397dcb4249aa8a55a63b869ebd2166da10daf2c6dafd67b2fbe24dd600c186eda7269c9bba6559ae066a5094ad3d2acd28a726669f6ad910cdabedbd9f55c0a479125ce089f04221a557c221a1407913f25029feea2d3a3b69395b492ab88c910dc0ce98fa406197093ceeabe329b69b7615d3dea0ac1b57e30d1298cb4226a9946d2b18f524af397ebedc0f7f40c3f87f7b0bf1f6c86dd59c42199e3fb3c7a5e2c869f88c6f612477efca218c6c25818cb0fa357bb7b393beb86c9cab369cbae6ffab1f39d3c75bd9e3b6037fdd8d31996e6f81ef6570c39a01bfcfe7e2f52d1c719a5ff2dd194e2c881dffbca11f0dfd733a3288d64978caa88688c40ffd63b9b76d17f42cab522c99e88b4c8e8c96cc53b898368067ef7f2471cd89d1472535fa044eba4254ffa4ae215305caeb0f429cd947a492b2d71d02d2b84488b2e51ec619f3709f9b1e7d51f013f0e98f8a07f1883ff790e593bc5a658374411c57efc321b919544f412c54af1a9c539931f8070a5e60c5a6cedd3955a6fc55ccc2bb0fa16c94d67e1a65326278b5c2b8aa2add59a06fa2421fc1d378495d44d12872d77dc1dfe8e13f6e1e3c80f0b4b1c4433ecefb07c5b8e487ef4696edf1ebd63082b73ae3524ad0dc5a7306bc91dbec5b2fe505be40ff383e449c2ceff915e499d051a339b21033a097f4708ba99b37b99639a4f60f5adfaa0fd5b497bdfeab09f57c1a7b00a56fb38db33c7b8eb5faf346ff9469e52fa97ca5c42aa01d687cd8aed455b7ab0a281cb095c80b02187eda6b51978999364af8cb2d9b57191c588ed3500c1aaa18d9618b6386581dafefe05469722c90030706d66a09a210f961cb0ec683861fb2fd140e6c8141be878d9b16343131724a090b982c40d2784d14388d963adb56556c10587baa84ab33d062dc36dfbcf5e0626dbdf94a16bfb23e1be6c7f0acac194293fbdf7efbdf7de5b81caf303b1ba732e79d81d7b209283d8c7801ea8bc6ec64aa2ef71ae14039bf617b11d49180c060404f432fc81be6967f2f4b1f3d60f445237635963505b8c1f232d8c04c14d0d983a207ef8621986e5e9afe3dbf9c1ef8576e66189be72460e63619044df70b1eeb7d10cc0587251c6e1c09540705ae5c069f5a90e842e164845316e9000449409faa4216416db29578d1b24dcbbef8b2b92e87336fbf0f77954ce53a5c2513d58543decb3dab0a8acf6598f18edb33e41797805112de4344f0ac10394624189942a553c46f424efeba54be8df7befbd67a5d44b806d940947cb5ade0928a000dbea98211c434f4c2822de17efd5a64fcb4a5958ebe1166905ad877788488beee761ab6125ad4254eb751731cdcca40c34559a252dcdac776133c2edf108f70529cdfb0cf6f7eea4772ffe42fb47cc9e44e451337276dfd3147ba3c027f6d0fe488fd26cac03221e2f29b483b6892de6f192405b04c74bea2d86e325655b1c631bb64598181365e325c32d028d1fb845a0d1c428340a8d43e389f192768b28c6d948a44245ec96981ed9b722f0c84a5fa820ba7e978894821428c5699200a800006a595aa074f29ef01857fc3482b6576138d1443482f67da14d4ba21942db7ba12d3a11f5241cf8712983ee5b5e9aff8f784a80d4bcb07d3d803308822ff7c0a4a5e6fd42e09604dbbfba162722b54a35d393486a7a1efefad7535cf2021b539af796f480b6c7818d4519c6b526fbc37a354224dae0ed1629a5b452bb455abd92be4b6aa3d4fbf5b18d32795fdfb757aa0564d7a93e517aa0ee3c71c5d9f57d8d2bb9cddaf0d7129c2103b17d5377a06ea047823bc15ee334ff3837aeeddf9dedfff5d1ed13db3618dab8fc74556cdb92c0521b3b9b76bd14388e325560dd6d5e09d893e278180b7901b2a9ea0383c3be332898ead92e2de1f7bcec4bbf78a5d6ab77df2d29c80b90946988e2f2d60a25524f329ac0b65f7159a9892bbdb8d63953a2b5fe157bac5689b43e912d6998268bfc6295027b91cc8b77848182f62f3259209d303628257b9094b2ba9dcb8bdfcaf84b83087c5c8e0f2bed1558662adbf9635617a7cbeab11d81a282eb72b566eb8e9327914e55b027f2b5aa7b6134bcbfe5597e63853140e88369dd011974832fa3eebb2f6d718a0ea341822dbebd7a5879fa16775eb5edefc50f46e38a3052fc91ac301a368c9b2bca0c9b89d1f8af3c497cfb1e8cc62d6d98f2e451f749e68b01b2efab8e1a963aaabdb25af4c8be782badf4e2d8bd6fd7b849827dad8e1ed178d0a7cd85a1f829c320d2a273b46dfbd1f68f21d00a65018ba7faabeaf1a4154fbd3b2a4ec4090a450d64421683f9e8b1c393720a4a7fd30fe80756a9866095ea96599e59000130b25e92ffb399a6c04ef916533c6e67ea3a17c05b9b9d02c09f3fd36fabe0cf7cea09fe9c9d3e05c60177301ae924e4e80990779666ad5216802e67a372ab686b5bf06669535609c401a03c7f5696e74cebb7e50aca336b0aca534f50da29b03cdf823b300e8c0144ef119123a0786db3d936dd0348a2cf106a43d140f12b4a702bccc959e1bd8a2dedad20a5686f06a14ff06bb7ed57da835f7d3c89a80c9d8436ab442bc3284bb31bf8f6ca102a097d82ba2ef08e2b0de0ede7a61ad2dfa71f38b5f80bbea946bb7f77946968dfc7539409b763780cbf800ca1c229925a1a6edb7731a5690de9ab40a07d8b6f5122953e5a94b412ea690da9c5d3a430f80bfe9c6d1b3a21972ccdfe0524928f2a105a3cadf451512032c6566b513e1e1d4685507ab4fffdd3fc40aea84b9fe1257388219427d50d556b2da56e5f1b8014edc58fac2f448a5ea21ef1cb4dfb2a489100a410128e3eefac92b86569f6bb76621c7127ae1175a498255eb9695f468a61c49cd845b4128f884fa2123745284bb38f9b4d6dfb5d51dbfe111946855ce156e8c44dfb2cc8d00272b7c32e4bb31f4e89b7176db3af6ddfeb76f5334d6b4724add17d82f43d44fa16227d0755bc63b091a4679e28d766b1cb5d387037d35d3fd3b86d2da0e06ddb07c1328472d39257f4835f562984dae0d7b62154084523073000f23acdab22d10c1c59478fd6b812edad8d32ddb777865dffbc3350d9bf69e4755afd8ba34775b405c027486183eb664582c908b78c705b184db403ac57abb52fc3df3660c9d2ea2f59ece1ef0a6d980c9711caf8b6c33c98031ce62f5ebff7de5b698e394c067ec7e57651b641a547f5eb074e4386644ba395a447f5497a94c10d46eb95de0b93619e409b82301967d3fe6032b49635e0dbf71da06928ca3400ef8ba3d31ccb3019a518d21ababdd8fb7218c32fc32b896684e5f9816d7713ae60995dae6155a11c00811b04f2c5ded75babe7c5f02b3aec8a47e85be434fb44f4a84fbd85ec958881ccec58ed274c871ed19f0d1166d3ea4ef18836c6ae4f8f9cb43fae7eeff6ebee0540a79d4bd456a9a4e07bf9f37befbdf75eb02c49f8fcde7befbdd75a6badb5f6964328a59d3db2a5d52134d456a9088ada901fd65aeb79de1359aa793fc407fe99a5d5214d35af1ce2bd2def7b49adf8e2c5e98316805e7036ed937e1896945e50db219188c91f7437b5c490355c6cfc54d57cd81ff2e328073a56bee4d192b2abdd77f727b254f3f24793949b2025b8d2020c40d2d49c9c9c6e4b35ff9b59f377bacd6afeb75cf3777222926b42645f36dbac26e4eb63b3d5ee3b11316b42ac1f5bed3e91a5da2d87d8b22a2c89c49286b9c30f4bb3d4fe23fb0806e3cb87524a29a54540859b6a157164532daf3e9b3e6c532d2f22bcb876fdd1adb5d4ab7d1bc36dad41acb42534ad481ac058b35b1367b7866bcbabba5b7b2fb6f762ec795fbe395baff962cffbbe9c416ffc7206c13014c73b8ed6eb0886a1288e232c766331eb358654c57184c16231d918a342b5e9cba6367dadb36cfa403813d78409ebd5047d3d5f7afa7ce97127b77985b90a937515668d2ea7a4425525d54985aa4a2a95fae45cb68b72e9f10a6169d30dc3055275b7f65eec5dcfb35ebdead6de8bb1f7ddef62cffbbe9cc1f086a1f51a7e1904c3501447d885c1ac5758288e230c168bc9f4d5da7ad5b0984ca635109089a01b1464bd06990812121a1a3a7102c5ecce66d6eb0ca892413768aca490908ca1b192276032ead6282e0a14d62b8a1c239a01d6a11c239a91777d0fec164e436aa88bb448f40abc9040f0248ad525cebeef62df9ddbfa457776ff7689bae5b9e35e4c8dc2e8d3ace5f541c42fe2ba45b1d64a3defabfe32ee3b254f1f9be6a730dab429b9c3772e31a82dbeafa4a5b53cafdb292d2e5de2a65a5ce2ecba3465eeeca604b07257536e5076bdb80988f4bf36d5b241cfae4934d5b2816b532d1be06c2ae36e4a8f683982488bce0fb7ed8b32d26b32b2d6282c8fb99b66e17e79d2e9b94d52e9f37e6ddb8de1298cc359b6bda21d16009ba6fbbc5f39cfd9fce13ffd0be6c14a5a9e6699b3d6b3d9f9fb34372c7c180c0683c160397bbfae2d4f7dbfbe0f8a488b2e4022460bfad42ca6e8136534b6b2ef565f4b315a58b2d6ada5960ab96b0c9258a044639c38bba2cfa5bde466f5c7b818f68215f4a9ffab9027d17d93bcae5802df823837b31c3d39316e2f7db72ed18d7116e370cefbb2a23d623dc952ea2f5e6a0bcb53e72bdba37d850afa9cbd5ba73a24f6497718972098adcd76860dd5b6a5587313911685f9a3fdca736e8112fddd57814109fafb73c5f67267532c1ce2b8d8140b87a99dad12b54b396b3d9bfd67f0bfc72fe37b7cfad86ec3a7300f4b0c6a8bfcf65e37ef8a7c811e7d5ed1432acf1c4b2fe88ddf929e277d35c7923ffe73e9235db8e9f9eb86c8b32b1afc2a86b58421453bd49775284bf3c741ddb6dbba4c79d26795c4f7bfb70b659564d7769fb6dfa8ede7cd62b5fddd8a76d91db837cbf6bfa675d1818c7c4ab31f234b297d622f1a16e90318a929cdde4a31fe70b78dae7f7e19caa1b29797c2964e0956468383909d15285373e8c0d86cc94152848619be04555ef5aa9c3b18b4a035d9c1892e2e4c2d34b3ee62e33b07c9f220c7e6a3c70e4b4ba3fdef96b6ee5fa6bf403ae1c7fca24fd35c3259f8e0244b0f5b3217721827e482b64369be445bb0f81ae522d3f63f2dd86706d37563b0f2d4db0626ca936a54571caf3b7ab6d32e30fbac5d76a8924991ea1174a9f2d97e855c9d6e64bb05db5bd83e857c6adeb346d1a6ff9b963a7cd4dab44bdf3b8cc1591217240edd427261adb545d6d6c75fb53fb0928dcda7998f3e9f7c610c1caf888b30f6d66a2d78d25aeb5c5582010bda5f5c90868ea614ceadf65941df84d9fe77fcc0ebe5fa5aa8d6ea3d486623de0740a729ad3beeb6f885d0d94d25fa2ef1e6a9de8b228854a96dce9b6a16363a3d7c501ed66cff3bce468db454e4a69b5bdb1e36369a85105dff498de854953f0fc6170f511ee7de3f5d777a56ad1ea36e9e393c0e09a8ecfad6beec89f6b727fdea416fbed6e36c5cae98812a2db1f025a1e7419fb4eb460ebb6497966e5d0283655befcbbfb6efb2dccf5a21379dbe16a2945e2f7fe18fc2499f59b6a52935f11ef36a375edb5f68859e55a0439abb84e4a6cbf67701a35e77473241cf70126d5668d91ccd01a5f91507f5919066e55507ba067a7583a8b1a3409b1bad11c296ae608c3ee9a534fbe39697698bb6578641d9646dff3b5ed15ff89f78a3fd2bb8d2bbbcf4a896958ce854f5bd38d36c8e6c7fa1151b8fb6c7b6de44a57dacd9956adb9741b101d06916db9f45add6e6b054bb82304ef21a27db7f14728b6badf8bf9a55eca02b00a3cf8ca4450d0bef3dd2ecd244f6e9c6e50f607af8dc1113489a2b67e1a6b3702faad58e9a526a7568000546edf4a9cd20faf4703a0fe7e13c9cefd9fee74cdcb9b8b5c5aeeda2d7f653fcda0e4279d2e9e140a8ed44a751b2fd85560ca9c95f94c9fe1eaa64a32ccd6dcea6b0fd6d91ed57aeb339db95b34af9f47e37d3690f97dbeee1b68da2548d7672d36f6e7aeedaeec16f0f84c289ba2d7d7a51509ec7ea457954c6112b6f737b51d6da6dff5188e692f4be32b43bbd0bada89cbd2da2684a692735b350184f3aadee9d8aead6f6fbb552c047dfc75f591bcbb06b58cc28ccdc591d2d29352ba5d152689f3e76dd72bf4e625c9938091d6efb17b1f02a7b896a29e53dade1c7a4b62d5cd0e7e76ccbb7494427fc356aca5fe0fc85ff055afacad154fab6cf1a35353585a60f9567899232e2ac11d1a9ea3e2d0241851b5d75bbd217fe41757489d3185cd1e76cf601d5e124d054f1029cfe00e7013d92419f338ac6031a1cb8a900a7b9180ad0425b2aa079aaba4fe46bf96951addff77ddf57dff34a9a49e8e12fdcb4699b2d223a11f99af7df7ff90b9bbff0a7608d3eb500fc68abf274ed5fa716f23ed6a906dfa2477e6595bc77ec5757b73c5da7a3e5e9bb9d7ff997f64a8c0bdac25bd8ab887fa65edbff12f91afefbfec25ff8c358d0beeddbed49569871aad5d62124f499bbf6399bbd1042db2f212b6b5b5bbdf90b7f1744f0f0a2ebfaa0cf6a73779bd74a29a5b4565ad625846c5d4e47b65722319ab4d5a6ab6d684a9fd5ebcc550f95586bb448007df459fbecfae4496c2f83ab1f459f799f7aff589fee3006b7e97bf5282c2c3d585854b2fb2caac770f385bf2984beda5c5e4ea3713c4947fdb32908e4002154620c2bd6d19d7812d5127264d3ed0020519e44b582786dea00a79d27d14d8398df73999fee6badb5d6deb47d1a6475b456b4d88a32196592c96231ca148bc1609409061b47ca348ef4c87b91323189621852a6300441ca0482f4c863caf9fb28d3f7791e65f23c8c2913c6f4c8fb7be991f79632c1debe53a6d85b6bdf52264b8f484b8f9c1e59af94a98664a547941e79efb00dea9fd88de55c9ef73d80237cfc3842f0fe99c15ceab89f1fccf673f8e183a11d2d7e99589eb8b40f92b0c1177dccd75efca078411104022a6979dad023294c830b66d16e40470fe4d701dad89f36db5207f8a707f4197cefb3b5405ea923564a1501fa213f8634d5f4032dd580fe0750a9b5d63fcb1fc34d26babe7ea7a69b0d080808085b0161279bad06f44c6c35a00c66ca0f959ad6fa892cd57439a408ca1bad5bd59114d4d4aabc12072ce8c80f62b65ad0218830b54ac5e98c9394ac3e40e86a2b785173c20f5c782852ab1ffe08b3b00d4412878319ccefe519f9cc3bae573fd7a7b53a8c01d4969ee7bdf54a221adedbf7caafccf16dafe46137bed6bacc510c118b7048790fc3118bfdbdde057ab18e4123f859f77d1f56864761f9812fa3f4e8962778e6181f249b701b0cc7d781c392478a1dde1979ebc0ef011ce07b8f03fc3be27104ff47b0d4119af8fa3888f4bca75bdb36a54740e5e995f7c73bbe26cf26dc98c7dcb4f1ab80e182f67e3cbd1f5f1c7f6cf0fa70a27f72909347093e4bf8f953137a21b576fb6a439a6a4225b5b4aba39e32e81ebf31c334c0777c7ac90df08b2f8a0f7b0f34edfbe007be8ef0cf1ebbe49162cbfebce02d7584420f0a85ff3df8f7de2b242ba56873f49983ea760ce4806e4a599ce2c3fe6cc26dd04471d8279a9177f839becdc3ee26184e74f8f5cf3ec117450fbe3f7ffeecd9df3b6c06f85f7986e599a584de6152b7af09953fa8ae564594f7ddb93236ed647b0e4bc9761fe1dbdf8cd8fecaeffec723c7b73f18959849d8b9c471ffd381ffecb1bd92470a100441102c75782a5214d13aeace650794c5994b1d3cec961241fd0ff0e79d3fef5a0a69b2e5a29e6e4e4180d86a94d2ceafd4e19552f5716971102957adce0a45ac6a5fbac65cd57cd0218ecc70abfd18626393b83272abfda855045189dd978dd2227f9aad12d196e9e2c2d8f75ea4a5cfa336d49a2bd5853100197dea22572afacfb98a0c636c1f5becd75a6bdf3aaed6af93e8f571c5f8def1fb30c6f8defa38ae2daf275dede685c9b818635c31feeefd3e6cf50ca68187312dba9e9b364ef211698d92df4af13c5b9ea258bfa803f5f1fbffceb03f2bd818c5c6b27dd2a45806306a0beff17f54696673cebfbd8731963172b65433987d65ced2e2b5556c9aa585cd3ef1e7937ae59c3dcf933cef49b04a263e3f8c9ac1126de1bdb7b43d18db032a67b099acf44698379621b8e93d2e6f9090bf88f67049ad9873ce38b29b8eb1873d7f1cd8f33cafe2ecde67f7444f2cb59bdee71894c96e8a1d48ced92a91404484ae4f7ba3bd8ff1de93e049e07ba107e6fc951ee8311cd415d4ae1f5e4deddf418f31ae5f2953f899c647821d7ead3cf2d661fdd876fe5ada07c91d55d49e7406bd3f0e7af7a0770f821e87c7e8e3c3837940eea0ffc0e6ac35ae603b4d0a7a8ffd19a3d45a5c9d5ce126fe72468ff0b760a3bff17778d2073d424099bec7430ffba0c743250d730ffd50c9c2cdfb428f85c820597d1340babecc2d1079ceb6ec357956b0656507ea8ecd368691592cabd59ee4b5e2a8d7dfb197da4d7ce68df1cfeea5b6521bab552351e9f0cf3cc6f04a860e8236e7ec353e7013bf887403c5ef650d37b1073757ea31179dac15b463d621dbeeb05dbfd0db190429386207028275a447f5696ff4ac66503d7f8fbf86279d77f3a8d4bd129738aa0de8ced5ed7ebe97ccd56c6391b10f43a434e95efbd6ffca00b7ef4029a598564a29a546889466e05e6b0bbfd7dddddd7d8e789d1ed1f25e7ae46177f7aaaf303302bfe7b987e9a547b4faf05ababe7d7777a7348d48692ae6e89cf3a8a7c051051cad628e3e73385301478fa30a379afe08dbc0827bb58609a9d8d27af62ae06831cb8a64e695b1626b2020139452ea79d4a31e3d4d8a834c0401e9a0a0a0a0a01431fafe358787dbd60412b11e11eb0c584850c5f5815c988b814a8e1d20d0a40a1e9a665565d94db20dda54eb01645cc6cf2b4f1fdbfb3b8efbfbbef3fef7b9b6ef746910195ded57e0d673d738d37d661ab27db3fe5cec9368c67dfc18e9c4f6ef5dc221f821081fe8bb1ff898e82b3f084b0f2cdfd2ec506aadb5d4d24befcc5a6badd6e9159e64690e7397604a28350dce5eeb88d8febd94eef09a44f530ce997edf77bf4b1d630f7b9ef51ec334f0ae77b505e7cfc33b7cbbf1c7f0db87318d4fdf2f192b69f600ffbd185f8c6d4d3ac23f92951ee11749bff4083f487a1bbb946bf15f6db37defc31f6c862daf676148d1f7bd92be78f1bdb71cef119556a51fbaaa3efdfadfdb8a4bea41c518cfa8e508cbf85b6037a78a8ac0dc5b34c2528e251b4658aaf6491e78e3b03fba993dc9ef83611cf48047ddb5fc4a1e787b258efbb82ca911b1967934dd39c2dc463aa3bdf7a72384b98d4b1cb71c77368166e5acf56cf63fa30aa8549c6aebb790b696be510ced17da184794c9c77126ce66e6399be1f48863aeba250d2c0176fda45ddf1bcb1301bb3ea66376fdf0e8881ed5a8319ac6b19432f9aed56b8afec619ce7339c1ae46bb8e96029e54df26eed179d1f684e4e96287afc55a6bad59ba6e51145decb13997a7d633af3cdf34cb1369c9d26ed0a33d9805d96cc592ae2a90bee8baab577ab5296c8373369b8d4ee7521236375a9ec8cce9baf2860f102f8d0744ea4489e109932668700a1e08b244955315952f249e161c2553b2a27cc5a0848da6275c514bf441b3441165745bf6381db9e108ae4fd58da91b77cb900d4890c059d961b3c4438382094c4cf82a4111556cc084147186cb1d1c0b5dce20004814377a9cb890a5444b04ae254aaac8c025858c15335c5b4a30258c540f706e4481c189902f4bc80044d6047d94c4a962f594a5c5860b3c4dbc9c315244d6ae0c0f3246f6408d6972831811c6682561029544975d1c2f13a7c9132229d451c187126ecc000398342a7cf1eac1082c165de2ec00449e1dbca246d84325ca1e3e759ee4d9814b0a3e683d11e20a1c11727c210933b582116d7cf0aee024e9f34687216ba69c70032b77cb010b0523e49071c14f9624a07499418a08b12a2a505852e6ece9618cd11b2770a2d8a0d15382084e271bf1c3551f3332fc39418c102549b6ac94d17d65a0013c4e6faaa0f0406113066b882f6286f05206852186a8d3470aca11728c8069c282e785305a7d9ef6f490fbb243e4cd0e5fd674795f540862491f34527e9410b9f126cbcd095f72e0fcb9e9f0250fd51f1d96bce9b2e606510c2854b59003922266f07220d052c70bc80b5d43d019c109c9172d45dcb0c515040c373a31bc41028e9d1c3810b505d742102b46ac11a1cb098d10373d7039c20bd533e5c60b1254bab4ecec20a60b9e2d23b6ece0e15001334254e173c32e8b9c2a51585e90520218ba94d0e50f1421654cf012f364ca0dea67c7c3942c5d92c0e3e486bdc3116eda74519287ca86cba006cfee8b9d2525d87936fcd0e4aa4892322db480e4c6053b3545bc41c2e40b09973b60b29adc4a504217121b502234b1d1946407ab2ba9ab23528a58992dacc992c3126682dcf13978e44479b9c1891156b64c115265080e2b30f1937503881b1cac3036c03922464bd82608175ae8a2a6cc141b097061cb1139ae2542b05003794547eb872d50a68c10a187953f75aaa6b850889245889a394be8d49142831036f62881c706222c7c716282474313273a3369b6f8c0a97203cb9c125ab8124545c3110fcb1129455030a14a9a9dd48d1108218286ac2f3524c9b994262466bc58e0e36449d61c1b61961f2580d0e3278d91193060458bc89e365660a6444883a58b9ba923de9cd006b71444949d1f3b76704dc00ce1821e343cec50e48a0c43cce047862837396c70b871439939428849828c17295e0ce1540c526ffa08c1474b0a6ca0ca9480c6852d395439e5dcb84085490a67be6e6c202565a4c9982a4e463c2a0f7819f146cd183048ae8880d19cb0478c9ca72b344fee54153650c5cb1015b47265b44210e50299345cf8c040e40a0d49a488c0f2c2458d9597620407264a4831a9539facdce1e3b4030d3c7c19e24310281eb8c0cce0c53e8d5bbe865cc12192850d0d3044e9c3431ba81deac0001565092959659ca8497263823a3ed04152a4842272569ab22c6122e44894962f4f6c386027678f911f946cad99ea2145ca9623391031048808396278ca0151420b982552b48e0c3924b68ae8e08216154e8b8c1715d450f179618225e8d8c963240529146c046581f3a50d152b564554311264899e228a68012286a62150c8584569b3644f0f1e952f16a418d12609115bde0440cb142264f862e58725bc29499400f142c24a171b66a80ce12a82872062d05d2314cf1337666c00028395126e5420cc1162bcb0389da99292fb92f3414b0c941239ef43a48f121f6e5a40b4c0270a015288a3e5e6eae94e1d1b50d2440159a1862248d04405c9b1e112c542104fe6dc30cfe4a278c86201c90b1e1473ce9594921bbcd68c1101851b286e80f205852a3925599e0b4d39e860b36d61d9b1334401a44851192142a58b9f9ac29e2240c87953c50d57960d10ea4c4509d245880d7c9e88208d4e8f17a7257ffa8890270533564cae5290ba726201266cdeb411828812c408e087af3d3258993343550b5240bcc001d2268a0e58e8d51e27384b6e678ef08105334870f8631b82851e76371ed0650e1239405902c39e264260a452c839c1210635224c5581a20414a7218c580285a3ebcf9cad2b41d6dc5e5862c8161fbecc294187156a12344f526fa68cd0298990c1891049f070e181c99f9b1a3657308cd929a92ac2c709ae0a1f1f9618652139828f0b4ae6fc60c3c80b393471e34394355b4aa88e883f2b68e113e44917dd25797183831c3a5a5f639274708301891256a204313253e26ac81e169e54d1a9a0a30e9a266beed8e6d8e9006a4f1519323cd4a14ae104dc8e889a2a66ac68b0d1028b86155428733353e689027ae69cc94a7226cd9908b0394188177448a1cd170a1848c1814d90175ae092478415f854e132a30392ac2cde094d44984c59a2464e122a4c81a1a9881b2d39cc10853361887523849a2f2b4fa25e60f2a5469fdeb8381340acd0c64a1d343e7c21a193f373858b4bd7d5121baec3c0882e5a4720a13544093417602265668c1518de105900159e5d0978a688d1f283053453ba1eb8004122a6032c44edd19db0020b54bc232144e979c29a41a7e7c93342819b204cb09c9123074b7d5a3f57375a52777e40d3854a18a7b2819f32d8f569ae3f1be399b05f106208354ab8e401539fe60a0061a7ab873a3bc0f095ad08e29c7d9afb03bb64956ecd2b92222a869c0f79be708152a33ed450e5073450a818e1a5567f56eb53769b03a9b95cce79e95c98ece564fb8f42f9e65d2e7bd5ad9c57cee6b63fdd9bf8d52ea2fab976dd2893e5c0fad035d54eb77d64fd4c54f183f03dfefa187fc63e3e6d696e4b0cd5e47bafc4f8894b9fd6eab62d7d6bd565ad6c973c5b178cb556947e0543cb7b3bad952dadd595419ff8b66f47a23c26482ef2142959ed563a67a1388841849eedaf80ac6aa3aa764cf481f70ea0b508782fe5950f0207ee5d3b341a869b01c8d227cdc550c0120c1b75e37c11d1e5be963eddebcc71b6769ec341632f5cc47dbc6569eee55eb466715c24deb9d980eb91112f4d8d46e145e35d762fdc85b78870c2534255b7866be6d1c4b366fbb37041de4042e79c5f0be9fc9db893469fd52be7bcee1a7dd6ae3bdffb9b7af044d50ad360c5e7f55e9bfeac68b60297c564a1ef746d7fa115970592e9a696d225a90652a3d0696ea7d56491ab726677a8b6ff8aa2a7c04d0562f499895caba79bbb56378ca7d30088ece5bcabdb3e3deaf428ab1dd5028fbe9ece4ea1b89db952e4cb0f76c2646d0d11c7eb833521dca0a3b519af3ca375f46cff3b2ae933ba1e51c789d61042df1f8098d1470ce11262bf8b992e32a3a2a83895b7f54ff479af6e97ed7f7a5917e74fb8edf74e3dedf35edd2b4ba399b9a3b775cb5d4eaa14c6e4ff30e5cb84599e0981dbfe2b8aaaf983e8828e7d385a68531d8cc8b3cfd9ce39095f2178eda8c1658ba1800e3e284b60c3528ca5209cb63f0c1aa6fabd9605d29889a6e8cb6597e9e8ea67adb5d4d68c9762f0a02f65fa144024459f481bc9050f4ec7c9671003e2779096d8e81890ed8fc485ab0344164d0f16104e9c4aae560f7b377b37536bed753f52a19e94680c90e8ece7872c56a8da8b8288becdc9a2faebdbb91a735b5c61b2bcc22c59b78cd8beb1833e1daa2ae5709a43dd3087d027ddf911a75d3587a365e9eb44ee16157f98bd78d4f729bee4cc9ca3cfd9cc2901d0e873e619d9e18b9712a5b42267e12ef00ba253a612a8b4ed94453d4c2a45910000800010005314000020100a878442c158301e104390f90114800c81904878561a89c324c69118c5943106104000000000068866a07100c0293ed899b5fa46d87b8be6087853ce6a1f438fc03712828be9653b91dd2df5507a819561d2a7b5c9fe79f09d55c2cc6199e6ab98401ba5ebb91b10689dfc7270701ced8452f556c5a98fa2cfbaea1ede5b1c2ce7c1336044916e47a798fa65b2296f08f496eda95803ee0c7f926fc5b017c3933a6946616042644f60c1d08db8faf29912bfe2cec4677299470af4a8887247b3d13b29cea80f13b0f7de16e4c64699a48d5fa2b76e3e886c2a20194e78d0c33b8e7c9ef561bdcf4bb2b7c482819059f2cc507d12d51a22263c0815792920761d0e36c90c306170ce6430a3a5a34bd1e88e1fd61dae52edd8d5c0552b50abd6f55aa1bd5c83031a9d15bcdae09a4901caea5482977b39692ad5dd4cc41a282f80922c5e8074587ae25483e8b20b1f89ea6ed9c1d0598134b7bfbe4c821296be75a063cee7d2d4fae83a3bfeb619c09a96d5154aab50e281d25a73e5ba5f60182fac47419c8f1238b412c43d9842b8eb91e780b1bc3b7523f2a9b5e2159cc3397a2c1972cebee567e8ad70a6688228dcd48e65d3430944ac733b68831008aac203710d0b11a26de4c8a5242049403e080029d7db09517ade40c8570d35739e9728afa891cf0e2fbb09e4c81aa1d49c6afdd91678be009cff51cbbac391279a2ccf3b70b3a5bc541e8b0e8f041d9199310cdbcec88936c7647a1675bebcd75a5cc378b03049543a3acac87c4b7759d78a4562c5dab86a04fdb5002935726cefcddfd8fe2cd979b797e80f97c1ed6bf9a7b49d3943e97cfe14d3a4e3d3c3f4ae5f3053ce11262ad6662f0cc4def792faa4f2496b2fab289d7d5342c1c3775439d049b847b3ddd66deba3e551a400b9acedf9a4b1872a80dbf8f16a9b1e6b1e33dcdbe1ae46712428337801a6fdb7ad2423663ffcea4fd71f9c5c4e1a668b73060c33b76e90620be048d285490e69b02583c6bcb52e355a5b868b122504e1e1e448a819b729c215220481e7a39e58cce30ee476bce450855e93fbb838755bed47ed982dd1df0b8dd40e6367fad067297e45fc51941564d862cbbd1e53086e397284a5f277599d9ecb098dec668b8662de6337c957377611c01d480f877dd7a17cf460773aac5db006c2251353e843d7a0a5defc08ca014ec139b73e01f41449d072ace8c505fd918f22761cd9b2f2b825a82603472e1eed9bf4739e1f5d122d303e471d1a5e73bef5b8ee72a15edbf3fbefc8fabb257e2c22e0b041c651d46240617190005c1ec685abad281986dfed7f18adbc9b6de153055d34095ebd17fb81a372ec34c5c5e0de0f9415c8c1d5997315e8f328e144c5ce29e85be535cc61446ae308ce942de1837c1a8b764e2f948d7f9b15ccd2f521b999154e498d166c86251b9b7f5861bb5eea0f1ab28b00dff4a8ec18cbfe8fc5b7b3488b8f4e3f79a91b0bb144691f34805d9aa0caf3b7f3748541f433fcf64f1a3194b5fe93ff16080ad44d65d708c1662ca27a02e9dd3062e3692710fc912f89c60747550521dfd1f2358c5790e39bc15c5fe37bb29e5bbc92371b8fa121f790f928f71fe6069c1e71b8ff4999423935abe9571a9f3592cba2d2bd587fe5129311fcd16ae4aed361be5e708e81312011410cbf4c5c35b87a81ce37eae262cf39a23edb1ee5e34371d26b2d05fe46a56a4dee1cc2309e7134920809b8349944c74bbc80c77f62ab7b5d0471f4317fa0b6899f4b8e304e0786526e7d497b7890519efe597b0e485040ec58b4be76eb8729f721b1cc3a74fca2e6704b7669aa2bd69d8a916f7d2cf0f169361923c50c356fd7238eb63ed42a2bc1983c4bb5a30b6a4100ce5f8c1b53e807ad9298434c32078e902702b211b6ac14fb27e1aef83cdf37effda3d08153fc11b4ff2ab50ce627a83298e930a2e503bf0e91ae24a29a00ca772474dc88d0877babb3ad3dc0bb6688615c927cc8d402fbb24da0e44e9d652feed80b31fc44175054631398b87093c6dd6fc9ebeabe8c99f5fc2ac0d6e78506412c2dad1987009f9c7900eb5a05107d9123504374fbf084ec9514cdcfd2bf6d3bb88a0b7fca5e6c8129683af19d6d0c6ae5d8fa44646d03b5ee0e510ce91790386d2f3937c28febedfe4e6a280a186b291142fc921ab2cd633e42c8200cf0a8fd517fac789e733c3b11ebe9b91be3308976aa577c3c11c0b372a37c27de04a2aeeeffedb7f3f98a50bde27ae5f72189ef4422c9b68bad814705f27816f132dca9d0be24bee68da7278b8a7623e249c6a75a59e00afda335a266fcb061a5369fc1a726ae343a4d52741463126d3fe5e235e6f65a857a4684beb6c800d2cc69bed3a7aa96337d74e4d1fb7a06a1ac98d9c92eedfe1d564a159223b47c2661227c6129514d89b4a459b9fd2fb24be9cab02cd7219856c212893b24322a7b75be9f20af560e2a961b5666a8a6ff83fa01207c8b5fb6850220f868dc7f0ef7185ba946ca45617bf8149c72137499431c9dd710448d8285178ca56c9787be4cd94c950cd66800a2611ba57d74cd112160a7912b74583c60e7e44869a0eacba32b70ba8f511a6c57c15e880fc3feb328a65dd7e8d2347efa488be18edd84ede7a7f99ea923f899a052af0d1cd7748803a69f72d46ccbc1a6f80123ded0b564b4e8018b1bac10040061541083088e08e57fda6dd6d90d51190e68ae99d9da7feb17a50af13a95c85c908be0ad9c4aeb4c33a2e44ca320ca47f2e7cd2a7da78cb83eee634b111cf41e8f2c01e66ec52d6c08922aa9a739b7ee21542d0981d589fc6e63580f571950a4907c30576beff09ecd1f4a12c2b6885dda9562d64c797e4f7355e60340bb204c1ccd40b180096197afb9854dc45934f7afdd976b1026c8236cecf1887c8a00c087f5937ee0410f53817a1eeaa64781312596e3390f00842f96703564b8b714c1a7c502c606fea0100718ef6dee5e14a64dbcc2054c71f1a42124cce7d2fff40330189eb48a1515671d6fef23ab5acebbbdd969e0ae8f172df39dc11b88ea4d6e1feccc1c9d6f19f4a0ba152aa4c1db8c8733893aae2af1a45a6ec8559d1048cedf47fab28cf2ce796bbaf14d1710608a9fad7246aab5beb1847fb6123d1464e4690d043ed7004944c8e8e4a22301ac8a12824fd4a8b7185961138138a72292e1f3d41a9aa25196f4c9966d6334aaba813626ab49869fdfca98619657c53a43e515d209a08f7df49c3ea4cdedd0732103bf460be340238b4c610e2d0ea76aa8d6a1521de3a9f21c72d1594ee201cd58011cabddd2a5c7fa6f914ecc927db430e49a004315189467f82732fa1bb6b12156693cb7a92e05c3d34e0a41906d656201a8ee4bc37e4a62ee8d3fb52917ac04657472330dbde4cc0d0f016afc46e71af5b4e08964461aea26d1a9c320882c840331257f5610ce0a3c53cbec712f8138d939bbcb6c3c2a754a710dab3811492ed2ae00c50bcf683b8991acfeb483cf595a65fd430d3eab0c2da24cf91153024b5d6afe9dfc4405b536bc49ee464f5e72ee89140ff260e9f0bddeb0ef2d9175ab023a667162e86ac0545569c0190f6add9a526b8a378c3da9e409d2ac4a09965a2a2205e89cf40abb3556852bd0c2b073e73f7887f2f0773a6ef9ac5820b292ba6bb476e15ab5308e93c90cac281154cab29d3ea8650fc524d5ac0ea857c69a76edef1cf9938d1e523f0594ad8a79a37fdb482795747da6f08b35ad495792aa6453c1e191d5aaef99f45a4f17d7a8af5b6c6bac4e57a0f032d02420b940e5703fc2adda063700afeb36f5a369019508b01a85e080342e73da4369405da872d78f3d5819fc35cd87c750a0651296d3b705e6b6796d5e3e18a73272abd1f51996345bcdc0e1b5fab565c7126c6202a708b15323a7282b2a76476cc1c8148f24ba7eb4535b92a8e85a245c6ed3b0ec0de565e543a420534e664735ad9b69ad23191853ad3472525f64e90d6353f5701c1dbea705cec126d5b774a8edf557350350d931b1860069945c7dd5321115339dd3aa67a890b529023eb536d160194e0cd93e4ab095ddd53e977bc6b57e9edadb0623176a56578ccfdb2c45b9e4cc6d6a5f8781e4fa863700163577aaf287bf3aa36cf96cf1090e06754e7e8c1f183f81193252ff9371cfac1df7792d8046095691f4b45802d2a41a170f02549854b1cca9dcad41866fea480f25c3dc1d83d8487f1090cdb9fbb2fe4dc03295c4c52639fb39e07c80fdeffa4ac8bd02d362dfffc549a8bc56fce91d3f9fce66b60a882cc6948265179d5c9ba5ffab9a8691bde607d5236229cf7e64eac7df383b11423056ebce828fd3d1afd77272c3f264e39366715d71d3293b30add29cf954bec84cfc41c5b0cc2fbba74314070cc3dbeae2893a8328a94e645f90fea3c5e8970bae2f009ab85c1f9963184e735454e80460283f4b2999cee601aae8953fc5c3389286171b18787a27a35dac2fee11d0f1c06ec66ad8f9cf4cbd1a240005bc3e35d35ed4aa5dc23b44904333865bc550a01e64de01c7d95c678b9177227e2927b1a14e59de167011e68cd89017bbd2353c7f134624dc8f68c94610dcbd1869b0075155f0e115e5d653756023629474a5da783e48151ce18ce3468a9c74df0f2e75c5bd42490222ad0acc64fdba82c1d889045494045fcbcb5fd931045f59e3ca77383081556c63df68507387a79223256796b4e5463932772d9f5dba372f4dc6ca3d1b5532a799cd8d064328a471534fc9cd216e39be9920a737abad397fa4855750ac33ae7b3cb3424cc2f3824913f5b8c55d4a2845a9c31dca6dda3105e2eed63e553302e279e4f6876b4efab6bc2c2c3003e82dab162121f6cac5a1515ea7c92fed38f70759f9d41de5176605734195f7711cc73dc307b608d2375dbd594fbd190f7fe41e728e53f131b2a3b9e70c36493444b03c3df3880c0ed2c93182b7cb1cd3af0e337e18a821bfc03684735e8011994f2263ba46921c6586385a1512b30d15d3eae3e1594a463c68a82898c0989dd643fb97967dbe15058f10f741bdf258ed802c145e845c51f968bb7e67f3f615d60171972ecbce54f2350a54a3cab7db3056cc16fa34085d602ec20e677032791e01b8bfc87e4d0c31ccddd2d8485a316e10d1adfe27de7b3cb561fec6b7034fc6feae1028086b53efad1b2e0fd72c78e94645e658209b4192957f1064d4a96a5c15ed1504f4e8661fd8794dbefcd7da1189f1a5530224acb6ef322ac62b0f10bd82258fdbaba321a4e8788b92d18a1b9517fef67b36dab4cb1842eab177034944bf909cbf398a8ab54197a9690d41a092a58edc5e2008f9b185f57873d40217caf86f022238517fc370e8f531726cf77fedb8e8c56ce37d791be061bc6d70d431895687f869a8cdf5571a556ac6cf7b3f3e7a901014ae8891b352d75bf88e6f3217552d045524790458bf034b86278016bc2f9b6d214e776d9b9d054ee93bcb7c0729f0c055f4917feb3fa71ad7ba52dbccf89bb4122218b8843c1e1d2adc2ae0e14c91e2b119c93acc19c1f2758b36aab1e35a9ee584cca7468b466fc14eddae336c4387adf6d0feec1a93c7083843fe8ddbc107c177a3d8786bcf2627ef96247aad11608d2a3ebca874fbc0a4da1e6f027e227a6147594e2d5766cb6ccd344eb950edd955863364653ea8fb740c5c813b23cd043e1c1da62753a302334a58ea7342aeef36bf715d3fddab0c52be8c820a6508d4f7075f39edb987c3b3f96199ef5e909adff3f5e6a46cd6bfe94c3a28cc663d636433134f7fbe29b0948625c59abb58ec2e638f95e7efcdb4b35e73804fcdf55f256dabc5e65563ca449056830eea09c77e89b593f326d62a53a39fc64f2e3be334064036a50270ead0a328fdbcef80a9a657f7cf7ec5c040fd55762bb797539a8af7cb3c736e8909b16f583f7fb20507ce89b04a1d26b8a1b75e02e9f21173414ed90ceac077af06d547cadfa2a2ef8dd82a3366505a2e46b2a465f3dc4afbccecaaa9505e8a51080637f927c1a532810317c4b5c41cc125be50e0d7dd5dcac002b0bdd5d7abffeb8f60a7c3672863cea9374ae840a817cbbbf1cf4cd34ec879e5dc10bcf2adfafd2610bc8b5772ae8bd4292b231243f7663126f7f36a373142dd6c828ab222a220515e44df020b13dbf1946fcc54468f66e1991df09c9b26a4cd7dd3f536e7f3118400d3c68d4a9e577559936942c6f8df8d1770ccef18d3cfbfb10a8dd4e192d2778716894e7ab900da978596dc9ab8756387a280ba2496d9e0958dd49f79736949cc00de151cf5062cf0a96d37a851471e0d6b87e315921961baf0d71fb19e21f1d798acbc8cf0cb69dc68d8ead7a8ccaa4b6126a340cdb72d696ccfa76cb36d2fe90f016c30de5bec85b416be3a8c6438d3bfdc6e045024f0d1e7ce5ff2af7df634f367b0cc005220c1c7c80164f03db5ed11d956b4d03d6f57a642fec75248398995d6a6b704300a12346dfbf2b497e867480b304777da8bf908b848279fdf22df967c2e5224f0329b58c91132fa91f1875ae973906221a14221cc9fe32316620c4ef13d3ac78487296f33d47ad2a95e17360eed38b632f5c1bb5931021bedc4b9f53f7682ab690ba487f6fce72811080ca5d3fa7f96914ea14ec2638dc00cc90a7ca0bc15a95f6e8940161a9d1ed36a097cd876eb01378cf4223462cce1d37982294602996cb60c4bcdb56fa228cce7823782308e1a733d1a9b3b5db85332cd9f29c9d8cdf1de1ab8e8ba06defd1c4d3b4c34dbfce45a94e1630186e3467a2bf0eee477acd33d04b9e7b85f4560d9a2dde124475bc3da5831b81c44009cf8b266572d85d1447262b289e08b555e1a30e66e4a63bbcafa224f9ffa39d47d2eb87b38e64cc7d24019f622a46ae4dfcb5692ebf43c332cf2d13a0189bae1ac5ea0e8c51e8466d57d36448600d1212125798c7ab76cb7ee5281315109ce8ec5f781acd5f389570417467d87ab5e9d7a194e234fa69588259a07a2a57b72d1969ba3df5ab6a5cd7ba871088bbed5cf8a1b113f2f1ff0450adca4c32d49d937e43c43c219c460e4c138ac302fbb38fd15000fb257185f06c6052a1d847210978602b07dc9aaeba57e49a9cf8812bdd960693ab923d9a466a66af1a01e5730915eb2240dd46e78cee481ce7d4991e3f2e82ca47b30e76f167e6f28c2e3439f6b04c0abef516dc39aee1d156385353995b08b584fab4b09e9426127231d07c7ebab9e38244c7ff579c02ab9964a769b49417f95a9395b3326f29a3ace2dae2a7436cb68eb3c1af14a51714aba71b1cf32f8f86d83874143c29d03ee93fc06c17133f8e5c865a7384712517c0e68003b379ba349953f2b9ef38f2ff5e6f84e5b50be7867326a9bef68b504c7a18101972939b4427e6012d7a21a79e2b6f8559ee3410dba5001174ab18e05af7b992175131a92d768631dfdb477ea8abbd0854fe26e5078f5a943bee104f87f99da0a53adfb98f1cb698e0ab7fe4f1f8c129d5cd87afbabeb2fefdef7a1b1c4b28a8d81c0309aa1c5b27601912501e6f99ccf0cda59b51b325e178afc802c29c7b2a2331af7a2e66617c43e91bdd7a12b022679f966fd71cfdc6f2e0d50600affbeb9d9b57186feb1694ff16b4c8602221fbdc9472de885986074907e813060cf1a7a86646eafdc9ecfa1295f99d374689d2376f81a2389da2fc28f660a74e96830e8b85ea2b97d3d748f1e1d455cc27a683a81ef492e49fb468b5647e7ab8caaa5d884825ed8c97e018617036318ab49e7fdcb611937e1bd2bfc9167c6b250126987bec8c01eb19ed2bc9137f9bd7bfbcb78e72eb7687cab48f72df5748885124d1a231ad281be19167d1c6798849e32ff58fbd1daab050915fc2da7e80b0b74b4dd71c0ecc604fe4e092d673624649239b31d97304f29c5f1608520f09b8a27add56e1a4cdb825d053c0d85ca6b9f6f63b476af061ed22e29496bbab605486acf102522090d2b7fb7990cd2e23f40163bff5f9cb040bc779b85acfab09399fc8aaff494ae1dfa57a7356f98e7f929f17a7b0cba37c83d4f6d8c9f6cbc4a688d7fc5c98912c8ceb16d20ff0562e5fc6db66c7c4266db30c7dab25ed3c36a62427d6dc80b35e88ef2c44ef32664c5c8319432d7f90c8eaa6ed7ddb3e5a6eefeb60558bb0e2f3c23c4b2bcbb1099d12bb421d76d6d9299cd63210834632e8bebcab210b2523091b56b68e673510a86518e87555e953e273c1fba0da6d09248d61dd6ee6277cf181d2a44c82702215bc215c4b12a6e498936421d5c0a94c28fe9a43829bc2632c91571f00dd1198726c272a0b2578c2d922a1d65f3f01805c113447d81152ec3015ba9e1d0fbed6a9e0769536f81f9ff940d2a3eaf80158b23e87dba34a1c96617015bee56cdd86ffe042c3441e49740e9ff704efcd9e07ef1c882cb4f510cd20720b6da1bcea32c2bb1660e49137d62eaa1e82ed4cc68866de405c12f6326b15bf058a97176665d6904684c149e024842d08838795b1f2c2b9ed0c870d84b23daa7d107220f8b2baf98a3cf7e5a4bf05c9c375dae76cb86e689a760585ee17982f72294d45e8b910524c82b5ac1870868159e58b468576135eaef9112aaba7bdd138c4a282c24c4d6461aab9aadbe2af7be416cbb1604c3ebaebdf9e9561981a31082907be7927007e56f4ea0c1ed0b48ec2537abb90291056f2219e9d482da35527d69e4bdfebab8a695b292f0e0b74bed81764dbdaa097491d9e0a789e9b9d098b77b2ca684b095a4884d0e640bfa9b85a93262736917045753305384cbd7c2dc96ed39603f4a8019d9894856e28d46156390f3976d1f8850d4b58159be2712bf8dd77415ddd61df4ffc3d21f478e790812b02b4e7dda43c0e60e8433f5c89e6c48600f64fcde808cc17f3eb97edf1d53f633ff5e260122f7b146727ec4730459908d84a5e69144a7657055f4c09f8b3673b5422173689e6e1747f72683250c4478074a6585272e59e5f8e3d06528e4f1b742bbf8e64edb68d33964442a92f63d4adb6004a68a711f9d6a16496aa04d08c5c911285b785ee371dce0825f4152f9c6c4c515608093ff5490b5fd5b128438ae5d4d09c39e4f025ae9c69433b8cc292ef831e122e4b7d48389fee4caf5b31fff04d18241479a9aec54dfa28b3d81efb960ffa2718dbcf42ed696faa08513ac1d8261b51331a0be62109f81f4bf6ead296aafdd24bf0ee9ad7ba21f52a9b18bd5974669684ceb7a2b8f6bbf58b9c1af0062febae782284d7963f8a509a854b520b931f8505f7ccefab7c83281e84239b6d0052e78ab2a92c171e7754f9f5a4c88b69e89a24a77abe9242831d94b5fc90a49ac0d4dee2106398a6782a38734f828b32188c03db7c4ec14a65b3ad8f9eac97623a2aa8bcdcafa82edc32aca002835fa2d377185093a6976ac7026fc5ce7899358594afe1ed5cd281afa534f72c46940314632916908d12588f5fe46ad917da775e32f1c862c8ad45463600a464c257c20ffb3326665093f3add3d018210344ce57c1764dc3490ed4eac6924d6521fcfbe09abde9cebe58a3bd133c1dc1b787363f5927b39f93ad9fdebea52524c7df95ce93cec5d1cbe5df269af779b18838474efc3d7dd86f73300833232912ded525acf39839e6d15f64f06a0b2ee196fef7c3e8e56ab899944f50b40841db255b76c418f758fbb036d8ecb1faa5874f4936a3a76f21579681c29be718238934ef0a3e019814a174c42e899c7c34fae5c5b681713e8ec24313724f880c0c65fa3584668f6ce3e8480d8fa02adc449f31762cc1c43506c5cab71e5fb0280f48629d35093b480ea2961030a76163e00c264053098628be9f86ab32fcfc6d87245d1c641abb18d9a3f2c8b239caa013aa07ac244134eba0347262d307a0022bc8d6652411699c1a00690e08a7498e3eb5f77b6f52b8ed0b6649b49e71abb5dafb5c7e7dc2d403fc5cb8d7feaf5e5f2fe564f832a3e04175e41df9b9bbdca8d4696e5287e6de33b86ee92d5938c6e160eb56f684cad57a2e7860cc1d33b554cb5df92197f45ba240896de3e53362acc0bb9deb662a1cf73b8653a4d4a73b8b9823d5c6ac2acc275d6d0fc5c56228719fbf1b972f2f040fa793a78d532cc73e9889bd97014fd488a801483da7fa081a691dda23892e787cc5ea7077d933f5d120acefd10e97405c3777ab30f62f5b5aba3afd1f91444e3b0f6ee2040e5761ac2f6f8693700a16f589c75fcb02db6b787ee3a9d96cd4c2732d6987d9a3913f712dd185095f20436d49291474a22187b1669830d1c61c2c1d15f538f2fee4fa0fafde6d07740e150e795ec55819f7adacec7995742fe397e3b7f5f506059a00722c86db5a9147a3d79d6cf421802cc3f475c7cc33f977d6856b70acbcd9f6dd44dc09ccb807115f44b5386cba9fddb81b3184e644e2f98db0c7a3234f80efee3502c3427be286134f1e168ac8908e9480a98613ca6177896d5becefe406da87dd7ceee004bfdbcb3b31f22b1f08d954f517b14d40f16e847ca2404d83b58ef708514d83377414006c3b31ed2c4863540661eb61e9fbd17fd44f887d918068ef24f282e4f00860b69f27f94bc086718c74af26e29474e145bb1bfd34062edac4a6f98cb6d14809141b4caa842e55a96e3d3cf531ee382dc0fc248f92ac7add55c558cd0454358ae2b8b14c7fa288a73b604149f07da660cbfcffd374aae9887fa45eb24ffe13a8555aa427bc6c9ce24074c9ebabf640b780a4ed4a41dd524ec96d7b9ae7d594dee788744c58b9c38186a402c1edf7eb31177f46c1bc72b3314a8382172fc70f71ba9241b73203b3843e96e6d1cc56af5dd0f9d0e67ed50566b43a44d1a83452d805fba5c712d104ed10c64cdfcc0342ae9c2a68f49402aa3ef89b00b17f026fc45f784edcdc104a52e8b90943a2840eb067d96471b4d9c49da532c6171a9706a9ef2f94441b6debb794ad98d415788c093ec658c5570640324d361403103b1ee9868da36fb575ef26cba00316b058c0b806854484a2a89fc89bb3407d434001fa169b3baef861867287a44333d30008dbee85ae4283fb975e03ca4e0d0096187e68522d23041255aeae14d9bf577901d28dfc95cc78c91bf8861e2e2630d545ec598bbadc88ed5424c28a3571e5faaac383ee736ccc2cf301b115317181655804ecd730e4374797abe8dbf1fdd5aa4b9fcefb2936f86eee65d12ccb7a99facbfdb6370b9007cbd9f21be60ee367d33950719e6ca321f9682a0b934e85d0af489f0981837ca4274990bf142b1f6415e1a8c2e573c0513cdf5918ab1247e56c1325e670b85613781dc446028d0a541ffea9efad700268e88b309baea1fe60ed018288fb9a46e9740c9fc6113de585b19b575cb98f6e1f256fe18818d4b3f2e26e84dc7b5f8a8f271c54a460f4937a9fe04136a70cd2e21db5edb88ccdd7b91f88a6d213aa360490d333f79755948b6b4cbad40c19f502c2dc851157cbc33e6d8c0108a4702d60f3fcae3cf8108340dbe0770fc09f10b022ded9a0c646cea8427903ec38540fa5160ac99a4052124b0d0adc090f61e4e1a42dfd850f8914d926d3f3462e854820b2e7fdea9d30325a4dbe80578176f946880c65abe118b3447c1c9a580c8533d2af7ddb3d091c582ba86452d887c25d8cc10a6ff15ca7a9b2aee1df554ba657e81b53ccc07f404f396178eac18da74e3474f95141a1b1da5ec812f34548682b239dbe085f98b725444c65826c86bcf522301dfac9596293648a97d3f4e97321d162b14d01f97aac08859ce4d6c5cdef09fa4f35dad7a45a49e16d270e1aed18fe4711680d6ba7d1622b4d4adbc3323a68416c6ff6a000cf9d0d350378f6ab37017a0fc3139fd4709a39431348ef454fe579791161990bc55bf260866acd3e76069f6dc2f4a4dad70b1577799f294ebd12f4340012e1bdd61f46ccfab4a0006c11789747cc56ded7afce0f1f84a9c1cf0545d5cad8a5ba209749f22562c8b9f38c9f7f61c8fc2ff46c8bfd9d9ea9ea3b2dfd0a0b833f4c6396f950daf85407014c63656448089dedcf0864da99071ab681ea6ec5299b6f451b35a3356c8a0375e28bb58bd15f60f5d37568afbba048811f2ad52d2eb362386c535ca510c20a1f81373b744b29f80864be2ff16ad4205b60f0134f79343659fda65fd95a2d68560e0bd2dd4af9679eb2da8cd724cb6c456c332be37f2e8dfd0125f4ba2ca669891bca848227255df1cc2c04e6b89ad707c5e1b2ee62aef5d35e09933561d087273d8f2d68d96ee3159d3573938a38ee3ad42895b77c140e387de559aaf4181eb26c67dfa1cabaffe2a4c922d4814c0729e83ebecd7e37c3e0c32dda1d4c6d4dac510c5a3cb94a65b4d5eaf3ab48298e443e34511767783456d6bebc32c0b397b38a600b07c4a8f578d4983fd7d3533c569e2e0c85b11cc08b98eacc0a0c89af423173a5ee44407fc5bb68ef30e9084b361f6a8553e505bdd0c8cb079936b3945e48f686f2428101142be63548b9c3729543485c7a10098efbc059cdda9052609b07c513cc93ddabf8782465734685a6d319092f4fe80b107336bd3ac521cb5731b3708ced5ded4272822663e7d28a520c7a417869e3fcb9ffd9f763fae715e6118f999bc8c650d5e42f85c2b92748828481b809442f741aca1334293f29308a15cdb0a1d089c3c457677a1c15f9082519fce785898efcb14ea85b0b483c8a315404cc8631e3d5a26cc8319b7385bda59b9258abbd25bc621f66d06c357191d6afa87ae22fe2d938b5442ae72f40d4d501dc989a97eb8057be41d5b0c794aadec173078fe48461c1ed08f46796267e551484df366497316864db6405320286de1d25e678e5aca70efc198a07ec0bfa5fe8529f36a44489dbca491db919626f32e8197d03499bf41ede1571d032239e020dd15de620e36697543158863a3e5ccc57331473de64278d852dbf0bbbfe6a4e9f03ea3658d6625552edac869b80c5f47fe136969d2a99c890904b8c441fd889c6e405e44b99882d58b4675fdf1371efd3dbcb445cfb6b1b7c1519f4d462e92c1289437282c262999f22c562376310c473ac76beb94be7de467f0a088c003aacbca25e314421e50714dc8a13d5ffe55ef300252ef14de2c337cc3b19b650a4e87dbb4d2b28d5776754308aeed5a0174913b3500e98785025aa8b38860318b0f0e522f7d6efe54e33314b63db66f631eecef47d8cf9944f3a14d988793a0c764cfd3a920441e37d2523df11bd48b5ad9ca9e6a75c059875821a6586d797096aa1e8b51005236a3d8a92a6402a8cefcfa5515989b6c9aaa37c1e1457bff963407ddaa3fe0e93a466956e7aae3f4e1abc0b62560ff1fab4773388523e57d4bc54ac86bd8a6aad0c3e730b1ba140f34b1eaa1d5200b76522724b50120f30840ed346aac4147f52748f287e4f361d0a6cd651f43be418f6d09c8931fb97b4a3c268d668c13db1cd37866ce4f63026254be4c972b8d545d66e9b165979f901d9c800c995facc899b1e0a8ffa7eb119af58b0d9f0291a5dfd9797c4a0e855285e8fd1f3362d1e2a59a6b55d35007be1b9d19c585f4fbc0e3126e4ffb5faee8a955c38bb1fb1e0f5eff0f2868ad95ac40758310abe054be014e6ff95451e0b1a5282b3c244447e911e91b017b6b3e63a274d41a3797024b03aee6f6d1552626ed6178bf7539ff9ee6b6d16cca12283ff9268c93a269cfe6dfe0fe42b0f13c55b8e65004a3091c13c8a997ea47c5b28a2e591ab484770dd25dd7daf7f10dfdc5e1b94047ba097e8830aec009a467d07d45fc7e9bae25224994b502e50a2942d8ea26c2e23b3d77823b58788750eace71e8623f202c3bca507b922626767e0ed54735e13a5a9d06636bfdc544e41baea23f78a836ac38d8fc68c2e68df951a8e6b220f740c502206f15239ef07e8e2a334988148f5fca2e31bcae505d4ef968d3ff32230d9e460236c006283581a254bdab603ffeef5b604f0de8802551b857e7dd4f7cbeaf4625bf8160f8293a4afad2c7fde4b2bfdf9805e9afb7e74192c4ac9c62dbb5c41c0c42a7733b0789f1f295d5e51e4bf72e3f0a16b4b468fc5499d1405c4324d83c8767466bdc426a0bfa2c3f04d5f1a165124d957e6a4a957f3fceedd46b06d17aa2ee9dcf21c3c570da5eb06bd1dfb818a8824f547c3aa07a7370be44d960c78b027295e4faa86467474c6ad3d3da1968b3bb386c3d940c51890869f827f22bc494732a3c9ac28a0aa4b4a1059923f58d7d652ca69854465442058c8d6d313adab4f8012b5886d362f4b20af051fc4f148408168817e5fc652a59cf06e305503f69275ec4514e63b67581b62738c4e7210be9599ce10517396453ce9c9c645edc4a7b7671464f0f445db667340642ed152649035398165986b06bb0e0de92fa4980511891a88cce8ba3023206b520637c0220a28aec10603ca49f44229108cc310281f4c794d8c230f67a8a26af4a97c48eaeae2bbccd208aaad47d17ee3fc3fc6820f930b2d08b24ff8f85313261b9387febec8df40e8581bfaa1a4b37ba011a6ff5c7dad37356ba7d54e30e6a12d05c8748c30911cf181d466e68d08eb6552cdc3cbea3d41da6207111553b552836ed0895244f7a8e59873c51c94fd64ec05dbb2d832b36cea55218bbfbd6e9d6c5cb60b1bb53ee7b31da9399bb726a7a4539022aec7e6ef702161aa1a8d353272b6e5e2c53e7b5848fc10c0332e0998748b8f96de056e0a8343455ae08495445a9ea3497a6947c1c44b8b55c59f181ca32bbf5ac977a4e3f8859bba9e8ee848f98b429f1e87f9bf5d4c633d13b5d66805264983806d198bad46408499d6039e32890a03d1525dae4d2b41005a9478d652f8887c8c8876c28f5430527747c9b60e367a67ef173321035e5fb5ac0fd7f3f1fe550a12db7cc11586895dfea22addc09eac023948733a18daea1b12210260d82a5e050b8adf19e1952b035a726255660cf1c2e537f10f31947c5c3b8ca425135d8c9a7d069d5e6113b95bb0e4b8696d189725cd37ad1a7fefe0453fc961c43c4c3152c3bf121e93aaa27368af0c9e0f6626ee522fe29c9c31be7b24e055efb904c06de4d902788d22fd597ec1c6f0f799ed3d3c306dc851cf6a820eae3cf9cdaf7a340a5b829a073b9e667961917a274ccc64c29814eb2fb797a4a78cdca731968e8bb74d737b1a0ae757585113f401cf481d14327c9a47bbd009514a1f54e489fc1c06832c95274986ce4318a85727bd2d2c801cef0e3d9821d9692c9571c7c93ed8bd5b25b66f37e5676207d2ec25beddee3e00ca03186a2329b0b36a2a1822cc4aa2cbc20dd6dd02beccd88c64964d7c087b9755b8ef7b46d143401fa452b2e48c93a4b3024ba23c547f83e9760ecc9b32fc9dce84c0749aae7e311f8439899b66689adfdfe6b90916035beada0719357a783083b594ef2f106742a4c9b7066630293ef3ee429fac61fa1e56b80f5de1b8d87c608f73e39956d33746f635f0b06fae20779982c22cfbc658792e6218632a86b88d742bcdd943283db872de510b2524d41d41eddb30e8c554af26fc325fc328d7eaf3582fddfd8699afdc492d67eb5388cde028af3f11b266bc2f16b376b825dea1b12504df79f355d73ddf95b2b6faa791daeaeea72e96741d9545ad722cfc7735f3ff43bfb00981b85d95fe422314fc4ee9c0d1436c638c7092759c7414ff3f621278d761fd26900db0b0c1c81c31f825b30c05717a00e453b90f46d27ad9611b425804e35b8cc6a5aa945e523097cedde937014d0639e067ca39b49fa6db5405b0114e19b57eb41f00fa530a576a27646f14956e131930b0746d3eb30d7991e6c00d4eea35721f9d487156dd72b46ef938efcf671f23af525064d7db14f0c7b0eb55d6291c8a7af25f048b28b280ec182d3306beda17e27140f3d97990306247fd9708e2c784af4d23ab07ae50e3f6171ce89f9c112a707c18f0d0031f2bd183190f8ad15d5b8aff87397b458230f7716ba765cd59355fd48ed9a83e4223cdf5593536f36a22801e5ac66976e0bc2201b4307c283eda31de2a4e766ea41a0ec24182b65b00d85bb70fb6fde2fe18b66c0a6107c584e069a5d2299bd4762f26c69bd46eb508e7e048a314089dff082ef12c5b665c9320a4f646bea134b40bd62de82ee7b7c6cb6f0a3105f805c406dc4ee6dc1d69a574ea079d58044f7317d68eb596e791f88d21e4be647334d95f2e3f6f0782d3402f0dd28b066e35d5eb796a064eef403253534930bd081669651f336d02317fcae3b9274899d810eea0fa10827b6ee49f30b5dca556c30de0d86980d1578d1d7bdd3583d5ec69a115913f904a925598df195add396d62381fc222198d7d1b25af5fdb6ae1641285129de9549c5850083304b91d4d83ace21c07e25db7455d4e5ef650c212ce6f3e27bcbbbad0d08eae288ed29c1b176d76b340712a825f0d0bb012e1861468d4ecece9114209cdb28ac4f21ec2ef09fca3e64ea060fa3043e764611e7fdbf6f40984485ef10c2e05257e7c33f624c310bd77ba058f108878e1c7638d1e2ff1deb6ce50d5c771f3168729fa3bb2a90cc33c7a1560340cd0a5bdc69cf6723aa5726fc7727386748f94c71f21764eadce8449524ed849975c27db335c8f412f6039bd74b2d5ac33cd2b91ade5182c1e66b84cac155113ea784dc54a48d1d9c77a4d5f3eac5eccab494cd6a5986c67775764e563d8723fc1d8c6a030161b4e410827337ae47bfc448e33ffc35a8c578351bd027cbc7f172c4a91d79db4ee63335a0123fd4348140459a8df6ac1ee728aa7af9cf33b1deb9204a5726e07bc4dc6761f4a3a62b7a4403f2c918e70383a10b1fe2c6b0f95a817f5c7c6029736c3ef35ab2aaa70adbd5ffd2884e7702fc1382a4fb1bad5973b3a33db5f8a8848f8b3b8e8370e6dee0f3e36b476be9a366293bcb1f38e5752831fb5b35b0dd70c9a67a8e55c6b31bc80abba06a2b52cd27ba8841e239ab665161624b8f2ad613e6160acddcbfea09057023fc87125efede61d3f17ff55fd4f20e86b80ab0abe9549ffe8850fa97eb56066a5d0c87ce55db4e97624d04c80ef0007d7127c66a4199b0f0c9d502e2a1e02664f82fcbe5d7ed4f1b61428b2fc943bdb838d5681779ec318a41f90427ca2535534e40c913e5f88dc801777cf49d8a6cff4a7ad7d64bc0108d20949e0e8b38fa1a9e8f525f54a25e8cf7144b7fe1e9373dc7833c3fa36d75ba6bf9f98faeccb47a6f898137563b70be390084139a88647faddd3b1ae983f450f69963a09b11a9ab24ebee9ea7626fe9a1403378cbe66e8ed8fd89a8973942fa3facccf640ba707c62a74547b2fa3219d1d719c35c447735c1b17ee32af54f84ada0f43b1fc75db790bd376208167e7c6b4fae36f7d35c0e8ef1bc865feef9f1c6c5c0845ac25604523e6120c0a0a0ace96a37e16182767b2de7731398ce8b9ea3e71d0d6ef448fb76dd033d57c32438e968159f6c7a4ae1bcf391f0905618c2dc0ca616f29f27bf12ecc9b9c34db97905d2300cb1f41c797095cc04ea876213914edc1c181b495263bd79111f88a692af0be3cbbdc27d87fd13d50a8aa10096d018c730d2792bcb4950d83065d4e8ac71416e0bedca6df1619fe92fa6703b54fcea409e13190eeb8793f6b7e51d18364ee65a3f1abc2ac200988fbcac149368d9cada14021d9323b5b4146d4d2911ff541a214d3a9ec8a47f9318289e62c4f50dd03909d630a83f5c972615de01796da0c6e891748e46fb1ba7b21aaab99762131d35be9ecc6cfe4ea2567de01b5059ebef108980afcfa6b9886a9c0cd5f58c35c76aa15a84d2d1ee7e3cb89640784e221c718e7727a8ddfd7634495705eb2163483866c835f1da7dbb26be43c78dac81b522a33dae274182363beb1ddf8f34254723e38d5c2714dc03baf7dc39ea6d5e712d72b2ccd688f0c17340a2d884acd0eec85995074923a94269424c21ac960de7209ba92e66d22e7a1903906753fcc72a5651b7f305e8251ff1cc5d26cf28c7904600e19db9a0770fa1847bc8b46c284778f92876572414e3bf4b8238f26d4a3989613a37324746eaef9490ac5a79acd3b07bfe1b54e595905e8e8d6210794301fd1029c1a2117521cf24960d06004033123f8340e379f1efd1a6128ca7490718794c8b843bd0ad2493769d61eaf500b4e4595f3399f175bfcd4074370ba1b66aa7ae06a01f5a93929024e5013b13c51be99bc0dfcae6905ce5d26e4693182bb919913c708db2b50c78922b357e79d17e8f511995661d3944f860040e839d79947b01cfb02fb61685c96bfc98e1c1179155a460279963bd80797c0b3020fc2c8949218a9f84cc5b6745e177efaa3b0dd7373d81d6e86c93501a24a9381b7a7af122303a633284635f9004fb6966857d197473561541d52df0e11440b1b2c98d36fb3ea57cbb60223c5ec994e96fc1e1f62bdab25ab18506e8051494e8690cc55212b453869806eb49fdbd3c10f53676bf19789a7d16176dad5064be4998ace2bcf4086beea38e37acc4103eeb5dfdc977d93020c8635f8b2ecc2f5331e328d925b424e3aa7c421263ebda75ee65d68133c8ecad4b4ca7c8bd679404e676b43054020bbe98c897d040816d8640c235e1bd0a850615318a01ec1010f60e7a5f4916c0c68aed2eb622b1d3e80e97599e334cac4fb4c60f68fb30e7e8234e33cf9bdc3e3d8a0adef30821eacbe9b6585bb8e6da085aa2439a3ce9c23a048d9d2040bf0d56c7ac01461fd7decd5d122b9ffdc247d8c895c1dd3aee9b1d7f9dc2457688e816806a732a9a89835027fb85c2a439888d357f500fc900ae4b025636fccdb164b775ad9df4634b1d80ccc98e8467334c7b6437c8031ccc81afefb5e4c72acd4970b72a7493e65cc482fb10cb646ec33fcfbeb3c3154a4dff79b8ee65163f10a0a49cbf963389986cf2a20e9c88ac35bd1c561dc606b60941560045b9b636075622e3e62d716ad39249c46bba14553ba2cd3636668fd7ff6023dbcf92555b90c35dac7eea35b798513aab8a545cdd11211d0c963e724c9a215108504d95d74a5da1ece3201250b67c97d8451cb6c16856fe33cd7e169635dab03c8aaa4c38cd25d4a32efdd480ce27a3c23e3d301f848735f802ae1d1bcb961ba29cf318853e9bd988f85ddeadddb8404a8b4eb62c22cb0cafd38a394abef4e935098acd1f7d7ad5ab60c3ae3c334346bf4b1f42e4b2c5e6d7dab0f04640f988411f22e40815f6d9c779f0a6fee2fb20f4ddf5fd04bbfb104ca249c2c0da58f8f72aaff7c10ffcf0ec567e8a183db584c15599ee02d520b38a91faa48378f78ff94752b9da107b2036b9455416a21420ad2dc79fb86a1d8af8aa4580d05954f28782c1244fbae0eca6f51fcab4bd3a4737e00492fbc7a97548372bb4ceca2d973419dda5b19456dd2ee0e43d58e464f7cf4f07aafdc752fc63d434bb3f84d6821d73b2328c3864e9a709445698d6adb7afe4b5f9de1ebc8cbe39ae1090488ee1c1ff49de8587f495fbe8af114e8288aece73c691f730846a3beb68b8c120113e741bb09f3f01f29e9cf43b11cf43592e8d250075eb65bce3b3d8ea7b0f259deb52a352bef86a6bc2cc842ec58b5b6a24c7247d868e1de48d3270054f7b219537f901ba354f63f99d7fe0a8f0a7e004233f56369b253744db0e7f578e1469f01ffbc06789e987c20a9fd27f2d162e007d8b75debe8a462248e454f4e30d2bf01ee1d45cd02975a278d283aa64c3a22024ca63493f9925105aafcaf58a024dac84d2ddc8d03635a81f9e408ea3c44a1a07645a5f4d434e3714aec05395aec3504b8a6ba9a700ce749b11034058cf6105348605906c64c05b92d5244447616f8f92e634699954b5ff89a7f3db25f8748bfc0080581302a5bfedff3cf94bd3f8fedfa9c0693606e7b3cf054057059292fccd343c6a1e1fd3dbfd44976700249408f77486d53408a3d94400815ece9dd28da9f5761b90365a885f23425111688a34e86694c5450e85cf164f873a0cc8f0e6a477a1fd4f1c3a6c163e894aa33666aab85e4ae228b38a6bcd8d246e3b5373b21f49a0785d988e4f88f19a57b03b6ba491aaf0c2a9a82ba2dd781187ae2a5423443387c74afdf8430b993216b350f2daf9fbc02b75b0f4abc5b75f20a4e1c70b9218be10795ca591ab6c555c48e4db23fd72d042de8b8d7391a1dbd799dbffde01ee482db89f3b21104a181224a2183fe6bba824d19e5e56d71ed4146994123056522ba43fa06603053130d54c510f693dfc9df3bde8582eb624becefa9f90671d734193841195fc6763ba4531541ba670b2d7fb8b377049dd63b8a2f4da6a4df825c4ee395f567b305289e766e061e1592254f5b8e64a32e5fa74d1e587494735ea38e4b50d3ead22fb9141b6de6278e7edbd2c983d394954a15b7e7513b96ae4d8c654803c9ec509f21948a2699726366fb38ccfd5aec05c8908079800cfeddacd2f16a21d4debda295e9e7310c53e85463fa21f947612e2973de14301dda8a156611fe45a45bdea8146771dc81268104476e4e26386b02bdbcb5cbffe94a198780e342c9adec3a888de0c2d95e68864b270f60347113b45a08e5bd64869cd7fce95206b6c24d20517543805364a1b3ace9ccf0e134605b784e567320831266c2b154983954dfff7c5aed42a2da1e440619fd043ccbef5078e56e2560e0b08bbf0618f455d72a3661738f09cdba8968b7254ef9825749b54cbc6c577e951f651ea00867fd5b51f0b1b7c2c5c1298497b5cfe1bece5a25e061eafc3c21fb44ac486e51f2a07c28c86cb19310d69fb203beba7b5d67369281745a0ce63d3a1e69aa0e19aae30c3431e52753980f932585670eb196a1dd32a2ec1357cda02d15e0bc4ee9046b8ef64f8e4fa9ae933e99a504d62f87cb1f064869f8454d409908910be18c92467b0b85bc4cb88ce171b648b60e920265ea0d9503cf28a21643fe7f01b466607200c41b20b78208fd872725b2f290a4394365201ffce04ce51457d8f597fc65b32afa0f863cdcfcc44bab796a2f8a50cd99c78d0bd6e56685179aef2d08adaf9a0f14f37bc4978e5d5eae0c716429878998d1a0f4d05eb77365756362062e1c3b399e2c8f70a1fc15b7149684be39a7f91ac25e10d02cdc7d9ca62f4dfd27bd1a4a08d1c7140d14501e48bce06573186008a73549b70d6d76a4b97845c322065c4471cd397ca8599665824c1aee1fa4c6a991a0ea8bf10927e87b06c58488df63b5c908fcfb548c9fab41cbe2ca8d8dff7dd774f701e43ea235ccee5c3b46594dcbfab627c1d1a4f3794e5dc0fea3fa015e56828d4620c55eb7008e441318aaa7b08369f38a729627caa3b29e127c3fe60ff42b25a255236ada0ee793da3f85b373deed7a40849294991383a71d6ea7ad4bbc60dd4b3a2550a076b6574ed5c92463cde6603a24fa0ef801b96de591d67f17c64810bdde867d568624cc8996cfb0f789d9cfa00e36361782fb03f41f8655c52f27c250371c6296cf253fc38aa6482a5421302e1a61d33c274e75fa3465b3d2c82fc73d5e13a29d0bf41e81113307f0805a2114500cd3a1322cbabdf926ff782f3c1f3fdc8776e554a67688ea266f875ca5cd67117a6925b87a42ca268820f17b723806e39d84a7d3bee1039fc7411a4d68fa12c28504627bcbd972face4321a0d0a16a10c8f106611b0bcabc8b827f87d4cdb1c5186cdcca5eaa9e4d88992806d183c83a609ca0cb808dc97c045b9e3650eb3f97db11d765870f2f7aafd8965120be1a527c412759873cbcc18e422832dcd251df298aeb532cdd6937b9df7015f59ede79b4c6be721014bce3907cb8a213ed6c11f5a20d6d1c9c01e70c1250b637a43e316861e89e784519816bbb591409604b4f2a6c05c41b8c7d00ba9e7498aa2e81a97e1a3e61fd0e664a8a9882b1393d52f2d5cd74c6ebc536f3cc88ff6c9c26ca1cdf373b26e1ba808d55fb9032d9bcfc3265590b76450975a7545a4f6a9910880f489f19c5e22d514c6309daf4fd5bb99fc1ee435e6d4825227938d0d44c8ed84181cdcd64fc619b8078e7efa1b41f867565243e7a4df6b848c45c7463bc9005a555e36b6758b989b0de2215ddd522711feff2ecd1b9d1976b1136beff1acc972832bb32fd3a251a7c664c53bea97977c603702f52a97e76e709ef7a907cb6c3df473871c5f2198816b8c49113d8625dd2b29d2aeddd3098feae5e123b6b0427d5182061f20a419408c5a270d9c20f348fcbfe757fd7e1cd649f00b952ddb1b689b02ca0529d9201b45595bd5bc74096642b98511887dbdea458fbcb4f17a0331d05210fb0db8fda2665cf8fe9d3b025c9ef5cba92c1ee1c2f1bbf658466ff92fb94a10e573606dca60fb9a9d48e19079bc4973af61bcefad26e1f0af450b5a20f1bbef02dcc2243a384f9c2b9a0b8a16d8eee11d16a75d90b071a1ef36e87b24ce2b176f039f141fd5fc6ec3bd8c5d5fc58080b7ce5f4abeff2e64302f533589998b70318d1a1757c81a96cc4f15001a9db05c7969847173e41528652ec5bdb8aa53f846c1eb1a12620b7919f531dec9d6ade6827cb385ed50dd0f4b86b5441a835d1baed5c427991a17e4d55c74b35a8e1a33e804ef1c244f9d3cf3f7bf8800d792c7a01c53c0717ab76fac58de4d88ae027d222e6ed9896c36b3813dc52f78f011ece44f2eda347cfe021d5f81da141073e21910383f1dda86ef1f670a6d6fb9ba22ac7cc2c3c574356e28ca030e3b47771f8278cf6839420bbe1b36563313d400a68ee2b1977ad9ff6a3c462a53bc5c23372b9faa7fa51778dc557b6fd3b5f7a9f3fbefe91bdd8142edbbbda36c3904a44a71ffb9c85e06f99fd5847411e02a0875b4ca20cc73b0c402b7466e99aa05cb36f42102753802ed41fee5d20850bcbcdd2a1e38b1b179c06ff560bf6a04286c1cb1fb9e659abe27de4d7b2d77df57f6941601647e61a9cb45623dc81ae6d8acf1b32c331074acf43d4f00f8d557c32348e5af99d12aaf931411fc674dfceeb72e9ef41bfa14f0986b436a3ae3c9b7a76988f8106e19d545e1c14c9f3e210b8c2a6609f4fb1edc7dedd0884e39d6f7c695cc1a1b297c5525243515ef9827503a7a964f859561613d85d1d671598aa8ec0d0b52bc2619cba984cb29b04a6769e9384d6544f6c0e2344e9394e95640727ac12634bb397b5b0be4d7984d44adcad1930ec2376718a47f4aaa3e50c2e80a17eefe557a9a488ffbfae4a5db4c0e20b3f95744f306e27c030bf1937eeb88e31e4005100a672e98e10be4ec695b8922f6a1b9ca45fe265e7481694a0473bedec1446d227f12e45a2c1c6202113c0c2d6d020d55b0b00bfd042c30d085acf9d97a72211fa086896c4749c628658f6227e77ee2883af0d9998b7f74b8d28afb20f40ff81ec88cc0a836086301aa723fed2b6b12191e234002953e1f29077c7d5c4133a1a714408fe0b3208b9b4acb131c23e169eae43e26c4abf84b6bb5ec2697728ff7342df37d16b7db7f71254855da5cece9b7ee7e664580289d114bdf51dcb35a4f2321bd6096c4b6ead2e8489022cdebf1569caa87ccfb678f2e51e6f361896527aa72c7aad9725f0186e27bc6698de3a10c2bd2794cdd799395aeffb155e7ee1e24af8959f49f0998d19ccfa929036273a9b99567b60b74f63159a531b180818461d12d83749e4bab2bc2ccd70892885700c96561897aa157c6e3a8cb287cfe3185c8ca58c7b26b56f65fc649c46577d0ec613c1536504a2c8ee98d96ce1d14a2f74040faa88f4d927b9290ecbe5fa3865f07a516c60d1adccc83ea904f84436950a62252ffaf025eab46defeeab7e1c69dff6829226e19ba21f2c22abd6a1e4990767a3141a09c457bca2f01adbea4d369a69a90e14731a5eec4c0c8c202b115ea2d42a18284805971bcbd0d68ed64a677d1755f57219e8e05237416655304278c8bb62e355bd786185320e810eb1c9da9d77ce0e6a0c0c346201fdb0b4cec9755c30889ea586f9bd2955d12bb6947936711f0359820338e159de5a5b456c07f9760ce551cb69dee023b203360ba4ba046fe533552d751aff4262dcd52dbc1144596339b0084ac985e9ac74ee13711cd442a5288665a0336fe00779b5f672b0363625d03457639ddd1d5f99c008e97549d534a00b062c967bc903a2afdb693eac0971aa2b9d4c6b137122bc1bd204cb94f2eb8c83241cbc9b01cb2c11ad90a859a2501e7109fe3898f25e1dc8785b568aa6b52530b60fb65fa5e2bf26288bf04226407784c3e423a2829a8dd42753592092a412274e55ea3fc61aae98280711a98c5b44630f9904430cdfba850710825fe633d976c52ed68e30c4cad09ce9c6f86609dcc42a0600d1ed32e1019f4968f0c9e9037d4cb14a026c43ebdcc01418955244a3acfc884bf57f9bc9775efd042d2fb2a9f2140e04dfd6f49aaf8fe12a66617cb83b5ecd5ad43975fed3ebb98c05213e38814ae175af441348a6a5d2fa1c2d267ae585a5cbe405c1fca11ba836d2c7b859607628d4bb36bd35f9d099d42bf1d7a0576d4ce5249bb3307f6e02fb083cafc45f2948ead1f3ba62c855599e67cad77b2003952f3c4faf664230f3035ec4e17de64486ecf538f07f874bc5e4c8e6ef750c9da8825a72aad5576dd696b18ea3043bdabdf3f075165e47c74966756958002c9da691d4c8ce7a4e0031ae9409203fec682910ba309ff3454c8ee516de77c402364e825a0866d698f86f3f997d1256e6ec315282209448f03faadfa6259a5dda06e51fa5d2edb752aa5c15d279262737a855a4125752557be32ea86598f57d30227f9e03f0e088fb3be07aac2e631b6c7b0eea3102601120cafd58a4e7c6c35c955e3dc84e0dc802e0a14fc9158c2e302446251b0f565db17508935ae8c99dd6e9176f28e67fb2e70b992b6cddd6472e93a36ac61a1c8f836ae78ac52344c9a1402cfd5e75077dcafd9432c5a45706ef69dbfa6a1805c5c93dbb205f20741ed11ce9f9598eb5fdaa627c55f6a71b54ba6acd65b7efc2b195b4639e757cf718b2c56a47469dcc2c316f5efbca744f3fb6318213eeb04dec87927a4e478923c8bf8edec87ccab90b8ec0af9f4d8c9db6bd7b48f09892a4d93538b3e6fc24e69e1baa3564848536f7bfebf6a5e6f02b481c77421a39ba0df2bab9c236aaf792455d93c8da050459e5cdc826cf50429267905579a3e54da2404c1f3564f3357c6772e89c22cd3ef6eb3b58b00fef7f644102e41afabff41a4f6cec36945dab512cbb8867c1e4f8bb4f65bb91ddc04e68432dff344d15a05596271a8c8a7893db67cf62fc31f69b27bf7b5fa7ee7261f6a2fcaf8d4c254b20171244aca7129f4b1cc25586454e3dfa250ec58c5e24b0e96eb730864533884b9f22704cba2d35634e5477c28567ae4544ed797756557f6909eef10eeeffd3c2c01fd860142d20b0944565b9e5281cad5e461adad9db7569b10cbe56ffbcb39081132caba43b6202a856373e15660240aad20ae16477561cb074e2ccf2840e643c20efeb64df6a48be26d331a64aa93af117746d96a6c204a9803bb1308e49a6a71e8feead80263fb92a51796c4bf1c95db0db79c0e31d31a03ee4e3f7b7c23f7902d1a7b2c5910b0f790ae23a0b6e64544bcbd5dacc89d8def95b63437651fed0e53e34b8f724be8ec92f8873273eaaa41c15a8c7129bbf800ab16934bd164febf2274d1216e23e9ee58ff1872e72b702a0cd50ee76cc7ff583d2f762c6643cf6c4a6d1f256952c403da0f31df38dc699ff1a7a538425b6f55b1a5b565fdecad9fc7f9f0acc4ee989cfe3a03ff71e72e9850453f462aba8abf7e042139792674d8f2d8fd1c7f49dabae1e0240c3b8ec4c8cab9961b00f96f1ec0de1413db21fcebb4834d8fae40943115c03126b55cea2d4831b5055aef2461f4f1450e211c7e6578861eedcd61b7bc14002663f4ee31d00460fd25d0df1dcd1ca15e2c817b87ec610326014aff7c176b54e7f9e2796281c3b6a97bdbde420e370a89e6c67cb406d6b93fa3213d5b6a2d66847fee34f78557d255265de528bfa143a543cee7fb541121a9733d8ee455b60e8598a84524d4cebdf44528c1fa37515ff6eac32649abe3f814b350f33aab19686647545bb5bc8056e2994a5537511e64c04c506b68d53fabdc46df0cfd2ce039ca4f1b5fad658f0c831df79cdf4d62b4dbddb4ee24b716de65d881d9a71cd4b2e0c19ee5edfeb1ec85c9dafd338de32a0a9d069c36479902494fbca4ec551eb2a1b172ac3c061eda39c1d0d81956b6c5c2baeae7acc63597114fa88c2d1f71f0cf9a2d9ef8f231298854520eb69e3276045965086a78b6e2e78826b1bbded04704710bf3e812ba0a383885e2d52bd078d40b7946d06d4feee5e61074f42fe800ff6441d7455b8c5224430a3246a941b0125537c667bf952e2a7ba975036f5e37f24397255320fb5200286f5c5751393d3129d55163a721d0a2ff9c2583614f122bd79308355b2fedd7994ff376a1e35a4b6196fea86435c0e808e0878373ffa16d62f5c3304403a14ff1f5c7c953f32ab8f9360c92d7feda643309aac9a9d3a0fb3878c52de13181e5be039f243293311c2011abd18214b420df4d02d921ad153280df2e2923d1ce51895d175aeb3bea47d5f4733c73c1577fc83b8eeea9513ae1b7384537cd83dc65345799b5b0f81bef4fc8a55b5a7774d7e8201c6f9614082305fb21af58f61f303d784e76f2f985d6e145de576d3bf1366f41bc25b3c57a8fe1a9345bcbae979d8057ad0bf2344fc91df2aeebd21b9ccfb3c7ba0e54a7c24162e1667b6f16d9343a288708c14462609569902bc68a1a8114b1d423b549f2e90a191f5cfd0de749d0f4788a33201a10c8ed47d4960f09febd2e2eca5697ab4a87f156787d8147d73a43a22360b63b257aaef351a95af635fdb33a56ec1c50878174336d0e2c22d8f5989b7cc100fd23a33e65dccc79070cdf3d37a77ed028dfc55e2f2835668ea5a3fc647b4d981d887ae1d47c94ef48c7afd21eacfb403ce1270dedccb4c899052a571d97d8753e4bcc9622b191303da79c19d5cc3b40ff1189718460d9f45f31d8087c08eb7918c1ea9c1d0ae799af4c833c3dc8d8c95318d59644d63b6cc2c00729969a4b3a447cb0e67d94f2570f98df8e2f74f80ba070766b94dec5613ecde1d8a2d085119c24e4cb23be948add915613f86266710186e93c6977f35662628dc7537a327f0a780b48fc830940bef44c1fafe8988e24724880cc393128d59f8940d716390fd5e1f162db2fac22941b0b4e686e85071dc7af9b991df95a237f3bd4d7eaa0cd01f82214e92d8c60d4f6895e733f709a16e2a535498bf2ca495ddf5aabf9be8824be4c34a2a20e5e4068374c5b8ee27106758d171729ae8aecca105de4601c5a00450d9b37f0041f38c15d5de20a41f31d1843a744455c57e58b4f0da1244cea84853e2e99e89e1a3bfb6290844925c2e485dbde80f6f5566bddaeaf5d39f5c52ee19dae828e58296703981648d13659b06d359fc254ac3d8d8387f036155f3104bdbac55625f3bd84edae025f2b30979388694881c91b335f182eafd16c2f5b506ba111d36f90c918bd674e13680d957ae235d2ed5819655c2339e6c81a729515022f187841baadd1d46164e9770787bce33ac60f62cafb0a5a39760bb0ac527408fb48fb9be63bd357223afea70e6ae343f5afccd9198282e2785df59534443d7ec147fa8c375b02488fb8216d40c48000a10d018114a160820e53db3cdb2c11cc052746bae89167eb5c333ad8f53edde1d7330cd4e445c93b5ad1396c2e494666642bd0d7921f3187d96551609dcac4aa44a7d54de1b21b324e3505fa46f681b37b30de4ac066972854380ecc7dc8e4da539a0844e8d91c5a46a51fe597888c2a5a980a790bd1845fa25df22e9df003dd6eaa7fb2669ebeec0b78ac79bb92b0e31eb8b93a72267a0dc4c68d58447d89459dcee2f5c044ea15a7d91a66a4fd10b034f61992704f53a89479e8def3a7e44058e45ce5c96be1d0ee90bb2bd12b86ef8201e25b986d4264ebe463879d44268dece70b1eb08ab96fdcfb85ceeda653495c06ab1eabe220309cebd167196b8578ac95861803fc3be626b5356e54810ba0469e8616bcd6e696e806d03ef4ecb003fb567f38ad7e4cef29b22654699a6105befd79c5e9c0bb9b7b8f1e1b206a150b54b73684b5298e6da8fdde8c787d2bae4a2cf4b0dabd33f376d12a94d965674d938bc470915f2848d36eb7d4f48ff6dff225ede0d5ca970bed7a600f98d3fc71f18638f0e21f6043e4ff06c991a1c1ee08908998ec237e5c8b5edecbdeb186530ef9d0c20e89cbc0b75dcbce02f085d042b4f536b74ee6c9e55a769ff588f7f2b354df17bfaae565648243a51809cd6c141cabc5f201fa805ff28d1be413505eaef82060b026db8344713a18f3ba26fb226d76d97a09e222aff7bdeeab49e2a429272ed9816bdea1f715fe2113a089b5776e808d2eeefd3027c494e2fe4baf528e3294d750f6ef8cf121970c788e6738d6504bc377e96f7f3b654947962bd2947ff15d576a7b945a4f00c7ca277c65bbf8ecb74cca9f9e3c1e42bda94e935c36eda84f478be212a8444d47ee2c6d700267e0991e103b6735cb8d93236631977b3b77dcfc74aed31cd949f775287e7a0027cf56994662dd2674229d8a302013b500a9359b6264047e1108503298d2ce38c2c37fdd0644c00750705998d416ee389179666ddfca1048cac544fcf93d205ac48e0812855344cbbf0d375633b1885b308493de10b8b6018e0ced0c03d9f668ec7f77748619bd959cf5ad73a97e7c3e332ecd73569d8cb5d1c7955c586c4e7256edd418c9697947e3f0b6dcba23fa5fee5076271d8b73e2812bb0574ee998060a5c44e46779058208084618a8e094d077ee6fff5109fe85857c01273499a356b27653a15cc7c275da85bd62238c680a76c373b1573be54ba2d8af93583658c7219fce13967a5171748d2626de39ad0e8f38873028403a3c4798985c8d865f39a588ca070a1da26ebf6044af350203c2d87866f16defad122f99e76dcef049ea28079c5c121957985db521036c94deec026cfa8bf857f32074ef03f51bd47127504f607d09747aaca14d81ebee868ab0a658ae961d8d581157f7051f4ef321c0beb0d01ea5f940f0b3326effe9adf62ea0bb08135c0224c55ab32963203d0998f3c22e92d087c257ae303a59aab2f5f9c1317446d5b9f9a26597eb11790579ddffe2ce8d7a7f8facc1ac25195ffda0237e1e908c281ffe03452e87f91cd5b53abf052d8437a2f0e17815daf6480dfc857024ed6c392554b4358b9481486a7a1c4e4517a3a38473af8a9b3ce52ecf7b6e286931b3e00b8c352ebde538fec08e5319d0b9318cdaab837901ad46d777ad0ab926e7cbd383b03a6813c67c0fdc29cea41a7dac2b972f84a84411ac01f9abcee2a518d4c0425d93bbf6000c1849343863921e1828dc7f7ebd69922e31b972eced19926d620292d08402fc82b540c82ebaf3287978a3077b982502abd65bfa88933565f02d93fa7eaa03707d04948a692dd794f9d2c8503a1f28b113e1568572706b0ea3a2eb40697ad1a8d3fd82ffa03307a4185cdad85b4bf3a496e59ff81894613c79d171ef918e30c440513f334ced64592621994071a71c06b0672d665cba03458aed4b4156631702898c56be328177c24d25f689cc3d450f0d56ad43a31aa276e1bab529bba0738622e0c493d5259909af05d289f2053b59a3d21ae15436a4e972ce88e2cf2997f0fe1531cfb68672ca6cd2c3e5b7b2568d59326fcdf7aa7f54a76b125a02295262cf3ae153d2758b834d6b3999ed1909a684b7134971034365b2e3ab6e2b9d72061d75bcb5b1af78dc6ce30a7ef8da53c24a0d3626f90c62712b3fb44c9d19562a8fed0cd2708d68433740fb26ad2418b9a18cec35b76e459ee3fed30799121a1bbd4d4e9802e6508c6efd4ec43cf874c3757acc7859ab1f38ec79f3eeba20f738c76230ebf7812916e5edc7befdb282323c6066232c79959bc0cdd7174e0aee21b7e034e722665e05843924b856a53daf7019a1a2aafa318637d08a97f1eb26a4cc80ea1aacb29f31138e5be01ce76cb01a5460daea212dfa217c2f2730806843667629142f7f66ba626ea270ff4a5209210ca8f27736567986f4d1e82d5e8420ecfa8441f3d23ab6c3973f842093dabbb8a2c9ac0c3b52f2ef88123d6f4f587cae92c4d66526bc10e92cc7e452adb5e784b058ed1ec501a27ef60cc31fe671d3516ddef7bcd7fe476e4a7670f6004b56b2cbb21240ea4fbbc4caddf3428aadbb7b44bea7ecf733ec10ea04a099f302e91909962bbb6c13dfb3811eebaf675c8caffd7175144d68ad3465d0fabc3ddefd431e019bd333fc3732caf28cc3faae51101165d2acb12017237db95610cb06ea2d5d06219f776d19282bd8b26e31c1b942d8a322bbb59e7d42c01e15ebaa5e30e5950066fa692783ece7a5c68ab0ab31f3d024d2f1e0bfc37aa18dbaa3632da5e6314ebfac376b0e4bb5930b3dc9695a128b38af303e230cdafc7ecbedfc86d64be0426feb74e143b8de0a2e84d0bb7e4db6af63b31c6395cbc7e5273c0936e349b8e0f55465b42b93c3da41f4dd7003c2394d1008fd8f1c0d8ed8efe8165099baa46214b314ac4b9421fc517045ac4f1a057fa64f89931c38887974c80c9cc4c67548a081712bb628c130fc1a1533517b757deb5c1b6e014bdf14f52f1cdc2625c2569ce6c4b2d8d6464d87c836f28effa16a744620eba48accf06c13e8cca16560a0896293be99db391d694a45ccc61596b4a546a9b80905d9f576f904488bfb55fdcc1d798421b5588b13ca566b380bf08d69505f0d9e10873d61abe16d035ce85c16c632422e1b820e7ba4b735507238158cea84535d020806c85e3b523c7744dac9eaf818d25eaf8154df08cb9c47e5c98f65edd51cec9c1339b8224925b45a43bd14e49b2c400f00b0d855a2edbe758eaeca385ea7cc30269f49668907338056babdacca8fd6cd7d7b292d62c2a626c5cf72dd11c521fdfa06961dbffca2c460be040cf343e8a1804750c5fe884a09a86c32548e2a0473b5b66ef03e85aacd27e153e845a5554d5d00dddbeef24e1b0060069946321ccecb0f53e9fc5af69283ee4661e8034653118c321694aec67e9b083d1eaabae22c610417e8eb8a1b683cf593e20da3d47bbb18c787c0ce11b63861ee7ee7bc2621f2f48016c09f23e82dee32baf53ea2c7ac4b534a0874fb51233abb3199095e6224c9d9d17c1354c11b55486834a9db4ccc62b81dc8a2ce3a1ca7c6aa0936c0a8a52569ab3a51710d0eb5fa7b8a2a5c91b8dee255f049369e38b2689b24e015f9d5fe88a646341651de3964040f430fe4a1c684d6787cb7256521a225f10fed61680b34f668e1e01e32cb06d5c982893c74ceb7448200157bdb826d1ea4233230b9ed330d4ea8e9787d079e41394e945a29383a0e731c1f2b99cb8ac6ef24113583105e0daf0866c7322e79932803968757dcbe0498ea986ae83591e554b4e66cb7ef98256f379077df0eaed91b17b80fad47629f916fee40c769190396f93822a7c422820255eb0bb71bbfcc0a4ccb03db10e858c5486e85719a713987d35e646415248b3b246ca984b387fc6237fc6dc79d8f90356fc435bf4ba1644b4b2f5ab370c1971b496927d10b9fefd89f6858675c20b9670e918ed64a3612ee914e9a072a6b00f2be0f8b69937d80549710c72921068b8f33ce620d46bdc3edf28978fed4b4099a2d26178cb83ad4c6db955a419f610835b0388c87d9c30823d6b8dc61d0b32fc679d1aba0d9512f351e556d55c6f8185079728d5fbeea1eada78aec31873562c99ecf9354f1b072f6ea6855e91b2c501bbfaae52f2d36ce61b5c82e1ee1591ea83b497995e6b42a04f3f648a1f3ed19d1c9e51c1d63ac1b74990891c83eb3410c69a99c2c9fb136004d54c435ae879ed2f515762cc255dfe3d3a84eca9f47bd412fb13e053e3b9a1f3eae7a3ad7896565f54d1fa3e82d42fe092824668eed594a8b880094c4ffcb0553b0f865149cc9fdc8e85bf532756b76131a302986c666d0699974c7182ee7d3910533df6f73bf861c4b501317eb0a3dfbc38d51486962962d4a343b444b0b232c3c7df60e3427c5766de53f0aab2116e301ca09e7ace0236132a5332bd4ea140082ed8df515a98d14f454eb74d12826525ddacc2537f24d065261aa850fc3690f090a5fef620485d3ce5061a321d6999fd5b1330ff306cc680b816565baaf97c3e4cc0f526d1beeac7bca1c8fec2881aa5b6f95f9443411d38aa8c4ccc20b8e1cdebe9948b6b84093de0c575e66aef08ae7f9cbade94446df7420e7056d7aa74096590d305250a39d778bbc3f067034021a0927fd1d6bc793c63c75e03c34e3db359a698702505bba4ea7c61b073b0375a45c53a7a159ffc0ce859a7b8b3e4bd35caba645847495b9d6aabad1031e014b0b3932f90bf347893697687eef526a5feab7359ac53d886bc924625efeaff82dc19cebc6888f50799606328a241a952ec5dc7e7373e43004fad8a7d200a652348d9c71a820538cafb2c05c9cbcc73612946c6743f6a58ee154a3d59d63a863b4820ff12f6cb5cb26a36c5bea453272ac46ad15c83d256b5c88eb8e285c123ed2d5ef39c551b378e2ae53bea59aa51469129589067629afa8b005fa28bfc7abe831572804d158ec5094d081c37c8e3e918447986d649d3a0ed3c42ba996abd80fe3d0353dbd26f1ddc47e8a28ead2be17c3cafe04f274209aa6c4926f6c8535002c55f017c1c4d35fc1dc5431b50801e4e5a377de84829a97dd0e36fd23dbcc8f8e88de1aea9b6b2e9c319408e332922a2a0114ded2d6218e2a0390f9603d1e93a26ed98061a2c84095b381759e4a2dcba26ea05f62f12a52586610837ec29b8d3af9ce3eeebae6608fe7c7392d7d9a94126bafb3a07d1daa2250f26bff8a2ed203d9216a9c1ce1580f431644ac429c7f6d7c93664b8283c222be6fd1dc58ff9ecff431d0b3fac4a0d109856636635b19e5149474efb7f8f8d6693752c8ec11955f8ea5d45b548e33ef767ca573dce91c1082630089feb35dbc9108ebc288492fbbe4668fc31d83e63845ce7dd50724c97de13887b57c8a56b1d5621a064c7713f9374fbca9d66c97b3e81a3758a7164e6025df2a560c2e341631a0a99bb3e9d83bae2e401ba0d0537cea699629c8791ceaa532dc93c726587c4edc3db1e083b9e67716d6a5322120632952a9b4201e4fdf174f97d69acce4c553a1172b178b86d274c412035999ca6c252725ca0bd3dfbc9eae0b831de808bff70c40975b9e9c32967236f371512e4079747cc161a44a150297d8e46be23e19d8f937f6608bced0e5ebe6a8205e808a501051eb348abf6946fefb62ab64946a16f22856b1fcbe2b6231407057c485bb89f3d065084ea92a8f1cd1a690699270664bcd1622b42341875feec4ae7d9d917b8f5eaf5e12d4803eca3d1dce85e371081039021d0c3fd6fbc0102215964c52f316af1ed6fef709c6ad665dd5c906a9da19a4d3a53157885066f7dfc3e9b46137ab65244ad8d3e2a4ab17038197fe5d3db4fa3fc75422351ea9c5cac1a954708a8924a6c239bfb75f7e7d05956a7efe26643793a917cd907c6fc835e2427223f41a3011be31a22eda1c890649e6308c3016c26505eaf966ce548027d996adc5be228d66d38d64d759f49f585b36b8737581f494b35ba20fb1b6631d7900bff4777ad3f17eea805cf7c4d349647eff60487f8851aaf6fa809051339f68a01ee6fcd600e465e2ab9725eb3b9668ae2338d686c7e9e3c05c62fd183fe75c9410ec4afb7c2913adc108b75bd25008a55c83b2a66fde79ff53681be41a94854af253b906950783188012e22eb2068d7d2bd83068d5a06170bf869de97d8841ec6518890974a5c8611b0442a71494f1c3919d72e90e631664c486d1a155c6c5f50f63c313a2c26c14aed24825ec841295c912b7f2b14a77aabda00a40df57f2a120d5986056b3786c08235193b9ebbf062871796652c7284c95146726fcf5e7d04c618ca4b45732c828524aabae9432c15f12a1b4cc85c00fc17a1f03a6a78a98e87d70571e4bf328e6e20be393e8cd14ee656378a414a16c05080624868706cb61f68811b29a7d1505f15c1f745abf114037fc7b41254697f524259b2616209a1da24290b21393b2f28eb44c7517718baeb633c3c32f7055d484b36534756c3d795b18126d4d1e335b817ecc850a35cf182d349b596006f2ccaa11a4d07356f6cfffc83854d4c7106b41380aa26e86744b6425dc3ffd9f92294f5e24338046f51bfc884a237730d64f5aa6fa840524d1542540b4f929807e8591ddb3785617c38ff21abd62fac2136b3146b2bac4c81cadbf1d1f5f6f2bc4c4bfb3dbb050181bab86a14b9a0d0c10181955094370b28248f7fc75080cf1fca46c3b9144d904d0e7fbcc816aad27d37858ec77039fb0679b61ecdec13b6abb204220526a1cd3feb2071023b21afd561b0cca3f30f434b8ec4ef7fa7378324f805def5562470c86b68ff299d90ecc846698141a3a61822fa23e938623e8e786785d365109ba0da30db7c5e3aaac20816e4a543f7d116f45810dea0bda822f349a68ae4b50a41bfb0bf23dafa8e697be1c400937276ce5fe794ba27ff10d70fa62d2da03666ebf0df815d3992e1c8ae75190ee1e24e37a542ef970ce8d229d81803a985e59e234ea1404fa4a9df4d1c1f998c5d46861487a53ed7d0b978f232e3b1491d851831f719368781099b2534f2c6d02761c127ae2d71f09b625fb6a073e3d4f0ebb6694502042636f82b56b45b5eba0d74449febe80b57b70176816e9232b331cb47f783f86fad13ea9af4f7fda6f94e632d8d32ed06f85b7a55bc8f222cfc053a54f95ec500c32501553c5604702e79eea31d96ab44a72e04815dba9b8a8c2163332f73a02e11ffbcd9b9a3ec0497d905c333bd52b48dcae68e52bb2c900aa2d7dd9161fbb63f46d80d9d807abf6f7372a2e071c2712ddc20f8cb3af6cf5e6cb84b17b6e006fb4ed663d88f3050b9a1ce756e0481b3a85174b0495835da89075e912f0488dbc9dc62cef24399227549402fda27c44e1284d0f93ce3b82e60eece08caa6da0b90d2fde829a2777e6a630a20a713e4bbf4a1264967cfba90dfeb55098fae5842fda2f540754208c543f7258f7be54ff435da1bd851f8afb2e8602d176e36116488fc4607beaf3d16011c21f13d3d1bf1c37a8f5d972437791bd463b2ad71b7310ac20bf906fd3741b0d191fb4bddd82bb79f32b634028b79b7b57a6948ab2a30e0a6c7fd32db279749b605b1790a21cee93cd6589526af0705f6caeacb352d35b092695623084d48e75bda2904cb4fd037a904a7d57409a55a5034d78dc1830bae02df36e6a4b6ddc09616e769cb45a286c02a99899b46615f8eedd4c9016b03d2eb003f4bbc1a1054c78921800b44c7ae7d670ff553357112d95d0966d042a1b229290bdf7de524a29534a32b107e307ea07cfb2cee39d1b07543242c9a15b5642a7c6caf3cedbd181ce09baf5111fb18ff41176255889f6d131d29b5f8896d11c1584cdb934adc1fed1fe6e5c3ec0e51867ee76e3f2cf5cb63635def3c59e45db469ca01bf33037ca6a9d05668358473aa69d70b9e803cfbad1b833fbed857ec32e46a2bfad8c7e3b95fcd67231988bcd60769b2fffaa8d1a55ba32ffd57034aecdb348449cab1b073d77de4be44e40397e888ec16cc6cf3faa354712285fec6d4ce0691ad6acd2cad2b15ef4d9b77d1ae26f8da79a4ce3580d9ace310128de6542b607145b90d03380c5a00324e4f88001246c4ee8431609fa18a0f9cca62e1a2f107df69beba1160a7e910dc251fd3456409d0f3e641ffa9e5a8b7019d78da467c3ef8cedbb8ccc3fd3033db753d7e6dd4b5db8526facd4779995879b7661efd023ae07a7047a27cb57ef7cfeb55299a502195d6f3a49319dd81a7d4faef7e1f1e13c30b8fd2dc590354c71fd3a24ac2104270e096a48d2464e52ae27dc1120b79ba7e826dcfea9aeeb7a1b7e2fd3f5a5773ef4b710176f7a06a87cc962a0f42aa557313d0654de8575f1ce0794eaa2feeca0d86d9ed814bb95aa52d54259a02cbff29b3b724dd12345759794f257dd52f7fa94ba5d7ff29dd5b81ee569fcba495d77a436507feba0d04037e69961055af21bf3d430f992a7f1edfa12eb5abb56ae95ef91dd26b51b5561b12bf51d75fd0d9731857cfc2a59cca6ee65a35569e95accce67473d289dd1e082fd94e4df55071235fa421b76fc8439891099c27a7eb62a49644edbef8ec304844dcf95bffd757fb2e2cec2b5dde04c71e1bf261289401a4bd07fcfb7f0749e05ff7d94527e89acaa29124d2c8a4aecd5d0faebfad931956d215550eb2badb3ec43a1d068347a1bee8e1ee76275fb9be35ed8953dad38f7aa3ce015d9e602bf644fe399880a6afdd6424aa516f243fef8212b6d8d0dd4b2ef67159f8e958259cdbf1cc2abbed6e4b4d5bc1c167aecaf7a41ec3d6797c886f5a2c7b959dddecd36bea11755d75ae63837ba8d4086556fd56767b42ec4cf09f753032ff7734527b9f1b37f2a52a0f15dce9831fcd7315efbb1ff843610b3301bd55b76836f045febe5d7f8f04168317e1bb8663b23db0d8e90cbafba8d7fbfc3d69ec4f1e19d85ab6d1ef6734e4aafd6a968557d0f6a278e0fd9875c4045a5aa9a9565b1f59515aaaa29aa3efce35ac3fa3e9bf7fe9c6f3735e27a308086649a3ce985307992ed0105fc1e26760a61d243c3f1e17dc80594b5b81dda026d1e2580fcd63a188002be7ce7321828f9d1cbe7cca400d29bbc1015b442945846e2a8fed1fc1b100ab481b44e6b57eb581b6bf19ea8ad11ccc9cf61f533c4c8dfe63b08655f081db3a1b51ed09efefd37cee73efb9ed3e66ff2a38cf259be7c185acb20e63d2f590380d63d3fe73ef28b7fa93f109d9bce49e9fe61bc0f19e23a67b7f8b2fa4de9ba960eba977656ce39ca6860e7ef3233334366e68706f79c73e7cee173f0c57f2e9dbbc1ae9300aa1091f15d97c8dddff3e7cfdf797b68b3b9fdd31a3bd7eddab56be7a063e7de3976ceb1732557a2a48c445b7be7d8d1119774b77b7b7bbb63373ac3d5a4ea5c6bde7b10c628e713359610ebe29a65d399abe85d9dd235c268e6ce5ea2aea4a4bbbb9949272728288cd2dfb7492829272929292493929494114d494911a584b2949414cb0ad72572fcda55a640b7f9446b8ee709d4bd9506ee6ef7f6f64dbb63b8d8eab1c25401a2ac83cbb977238d851680be9b9082a77758a7bb7374b7b7773be79ce36ee79c73dcddcdddce39e7b8bb9bbb9d73ce717737773be79ce3eee6ee6eee76ce39c7487a58a7bb73743737777737777777777777777777777777b773ceb1e3ee6e6fdf2a7059072f5c1792eb3a0c7d248bd61c10fbc3e87b8fdf0505ea3f5d0254a0e048fe589266655d5816ca6cc4db261c4884618ab0e76fd29393939393d1a8bba973aff243a9406916b4bf4d534668c261eeb6da4badbc03a5609e8e953e515227b9fd2a52a0cd14873b4f4e506a806668c038233559382c48254ab211575656e0caf3e6158785b61e13a56ed36aa99a73715fca6a68a90954a559a5a7a3ae92ab2e4899a94d2676d045087355057375a32c2ccec2d22c3c554ed7b995172f64c2f1ee868469a5a5868554f382c280f13f9322c9085f8c18de5c85369c95151616be308ec280f1436bee3faba9955a52776fda65d13333333390cb3a4892dcfcdc6839f116ade1682ddbc9f116ad89dc9f64c870193264c86876a1e9a82860513079418271f2f504a5aa18f95aab0bab12c37492d13258063465355664b83761c078f1a41b64dc4051ddddddddef2070fb9d10b0e53a843e63c68c9e318367b85168bb000e386828d48c1939e40053d392d948b9b8e8a0c3cb8bd36460a86b06cf782a46280a95d5d0e28caca65fc582b6b0eb59e35c5a3cd529862e598d0efebabdfbbd5f2aa776e021ab0100856119da70ae0e3abc8a11f9b2c2f2f2f202c6cbcbcb9b5e5e545e5cbcbcd028e1226194f41ebfd9da162ed7974b02bbd9ddb9f7daf61597c85961e522b53f182513b0372713de13359510e7e2deba30fab2e976ae734a5cf72120ef421d111f29b99149a6d1745712d6b5a6eb9029fae4844f60c884235efebe6cb7065cd133219d6435282728282824931214941145414111a184321414141c42ce981397ff45999fd790d7bd6738e275763a97f74e6e4e0ac2f8e27cd8ce7d2f31e9022ffa0a9b1866b92babeacbf5605da18c5a34945d96e8cabebf723d5cdfaf32b31a4c947175cec5aa9739ab015f3a3ff8203bf487570b7af9f5006b8555e7a89e952fe75c2abbf1c3fbeac6efb19f79bce7cff5308f29824ad4fd73be957bbaaf545d0fe16ff2ebca75555895d53cf84aadc57e79f3fcc1d7ed8db563713dab4b2b0768ada624ac9cab68fc70a3350f62450b5a1750eb75c1fd4071b999aa63faba8751cf20fcf83e5af15fc7c468a99bff62155f86233e7c181f6607c0112d8fbe2f28089bfe3344098a266e4a34ae070b1e710b220505919b548fe7a373bc0d9480148022c95340026238031bc470063660745412123d5734b3b4a4a3f354c46c71c5d38a6c8f0d7850900f506cfc407050d0b5b9b1443cdb1bfe2034147a9128c4cc6cf9056b99862492783d3795d2518244ca588848a5baa82ea5a2d493d010528af45beac23c4d33901f8e729906d2991532e44d0ba47fb8ccdcf9f1e3c78fcb6236645b8b9292d6c2c47ddcc77ddc6762d37dda8811233ba4ca7787145af016cc82d646dfa314ccf3eac262884614844c1b69203d3333f107c88f05f2e3a595f91df39ee8db88d69acfcca4529ab601f17154bb0f76b9ff70ffe148ece371826efec3914cccabcf665841fd43224fe2e268011bc0c23a921d3a3f64fd87cb381247e23f5270a3ce2c3dcac907c15a6b5220d9f1ae0d72f28f75fc9568400486c6c51ae5885cdd45b82505f3ecd3691cf5be049db3801c90fbcb7507d7a021447319a74927654e0e20dbe3ee103e6889384d8c3f872701d4ce0509dd38a72bb67ab43f9d34abf90c2d3c96d5a3040b092522f28c816ed68ff5e37a58893c3b5842883ca9cbd6d4e35c4e6aa0db0da69e7b43cecab57e228ff563ea69e1e9ee8ee95311a6ebee8e699df744414133e0b98f7f32dbcc24c776c36c8420110ea808e59b3df6332e63a1a465219735c256c8133c3c847d86740f11f9d6b788f925ff11a16a5a1acfb0d3c524d632a5d732a2c7301e07386a4ecbb516446b6c27110ee8013da08cad035ce6089fa2b59e12d06de6468c75c3dfa2fad50147544e8be9b4c83490d25a5a525677126c492449361ef166ff5ccf1585b22c140a5923e215d98de6da5c99ff765dffbeaaa1d414e8e67282a091f98ffff88f8bacddae7fd65f30777317f3f08b2346b1841539173e76c52896a822e8c2f9a24e0c26ed18cb2a312131b3cce50f801b0001dc4b3fb34563524bea95d5c9d7b25c66baa8c7da0cc01373cc2fb79c67d9c3b81ee667ef3214a8e428ada61cc559c52346165c1f5f0e4db93f918a02dd1c360a7e3cb261a79621358affda5a5c468f37c4800c40373edff81340dc10033258e1c61af0dfbb77a3b579395b6839695acb4be2c76da054aafa99399a0f9f545d8ed06736d7db54cf422e4c59b1a56cc0543587057401952e88f1757df5a23a31cca298257a6b4e3729666dd7a4f1506537672405c39cfdf300aecfdeb10c4d96fdb8343d443823d7665699868fd5eb5f5633ab8a71725c8677723c6756be2ed3e14141f7b24146ef320f0af26164df51a51950be253f7ad29bbcf3c1838248cee13360f42696c651f05d16848f123bbaaa07055dded981bcc33bbc0383680d028582cca4606066acee16a8e1e73a24a4018bbb4d24a4618a6b44c768445f9bea6555d569659126b9d557564e8b452a83cb9d36cdb9e8b9f37e0f3791a7a282f2b5ac66e9f856958b9ebb8d3260c74089b07a2e9ca924748b3db7ad9e1ed743eaf65b3d36582efffc6d9401583777d9a6f0c86002dd588058805237f63817abe7c2df62cf0ebe5b8ab6b306d6b92f9bd7b4666aceeab1bf30be552a4b5d29cbf23f0cc3300cd3b9ec56b26c65dfbb50da0c480705feb9f2a4744ea081139eb8f0f926e59c400327d46056d7a84e7d2014c2aa29afd0d3bf68285465979ca2ca12655996615675c9c937ab1b27a1d4a2938a68886614a392524ae9b46829f4598aca129d724eabb2aa29fbc1c0a9d3dda4dd4e1de332ea5ccce8b7232c60f950bef3fb5b08703984c3e5afe2b6cf7673baf1e1cf1867f68ca344668938dd0d67c89dd646be0dfcf8ae46a3d5396d6bb92c5f51ddb2bb519a439699dcac6ff69773275d0c7ff6ce0da0855f1a6b71c17259d8776b6166f89299194266d872e5e96e10384959bdc56e4e2bab0dca151bbae7ceee71763b4149d15cfc96e21f5a2687e9b799a95417b554532a4a3da9ce5124d13381f215fd131541b21b3529c9e99cd44c0ecaf4e7facc3292d2cf97d696ac436176e3241fca421ed26e28347343ff43cb509a8ee10f857aaecb64f6e96b77fbf9a2cfa1180be8cc9536e759a7736ece8f496351c889a556e21fe88681aefca71304ca5776abc4df7aa775d805a1ef0744225b89e7a327ec2773f8fde899bd1b82d0ad777ac7d57088646ac0f5b07bbeb5dc6ddaad4534b749a9e8b3bfb2ea86e0220ca3486c71b1a769a9832fb54460d666be6735a291cb6ff42596867e9b7714fa913551fab2742293f2925d8ff3f999a42beb8e1defbd96c99eca878eef840fa56c54b74ca051fdd39ad8e6d85a6e978450ebaf9749f9f926bf9d563612ca6fd8dd1c9214fb50acf5818da2a4526b13ee8cfa12c2ce7d0fc3405262a03fa4ec6ff37b40f9be3fb5d6377c640df6ee2dd7eb0fadf5cf79c22e842bdbe9b6cc8d2268e9b1a035ee61202931d0159fe666c906d72383fdf557ea5e33f7a241e35ed64c4afb129dae514644896375e700a6259582e916c0874fa0f0ab9793875f1cbe44155ce8b9f06fdccff525aae082102eacf3f2cb4a8d80b35d705d3977ca941cd5dd01137308693be7029ff51450eb652d15c1e3881e6e3749afa024ac06c9feaaf6d4287ed1ddddbed3b5aa8dffa3d957d5bfd905c8beaaa94e8dea974dfb851b8a4829a5c45a4bc0eb819c2111654e79125297b552a21aaaf2bdb44eb2bb67ef9e61b4e44e530ed25882421cf4dc763110c94681d03fbb15717988cbd62d819af871ae0907bf105c53261e96a0d6bb9731100740241dd35803a1d66f970e0ced8d52f67bd98d2e017dae552b28a5897431f2a7cb885eca189df3c7b9ce9de2855a50203b3f7858823adda954c8ed7780cb50ba843361c1edef1f72fb2f1d77e4590a0408f59f27e6a109ca365e5c51cf0b28ff76e9d09e2a0d5356816eff0e5dca1939be03e27dfc686da0bd6d82cb9dfcaad2f0c416fd252d88dcfe95130eb92171e386811b7fc36086c36f15eb8673e36f3afccef82f4380fce8291e507e77e1cdb8ea8636f22d0efbde752e59e4dcf757fcaef1bd7e9344403b1ca62bf503ca73dff7ce7d0fdba0731fe6598d1d3c74c83b9d8b113ae4c59c0b23a01100ed86639246bceb9c8ba9dfdbf673024ccec5aee1c186b2995f669609c75736884908515090b4f8b3aa83b9a594ddb7bbfb0885a21ffe7b4dff95f837dae306603be2c109e1738c2e282828685e77f2ab6391cb0980f2f37bf7e6353feb88c5f9361e8009c77b50d0b5ac8b35fba9430605056d71e3c7c7ac0e8f7c713cc957f69dd579ed02d5e14141f07de3d1b77a1e7c2beb1bdb261237f24b845ff5b8cf4d18617cfd821e8d5d78efdd83ef1551821a8a28e1e3f37395c1bdc8f021c1a670a1210a181409824f1545b2e073832247f00152e40a4ef80c2943912740c1070945b011f85c498cb0831214c9715812ce8786591ec0a33f67c3c5eddedfcf5844416dd4d0ee732e1e057d990debf604b943fe351c07eabe1ed73997b6a61af33ae7f29ecec5cc1b70ce75bb76bd02cdf57673baefdb39e79e73ae85812ee79cdbb4fb80cb0d71b9ead773efb5753eea0b981c4826cfcfffc38d03740ccb8a49c5452905e5a4644445a10cbbde6a71d1e125b5030f0098f1ac5d6de61ae16187d48b0e2e2d3918b941460e311efe15a3c2538cfaee0da7cfe114a3facde114a3f695718a51f9ca38c5a8eeca389d6c8caf30feaf7f87f1f6fd83f12f03c200301ec60a162e4a29282724939211dd62064ac3c148158e3861a40a476410c291d1d513203f330d64c0a7222690c1caa988099a7044441e28c21578c4529c584bc7d02ffd7672f1db8aca6f2419d3978c7ef46cb7f7a68a354af42a2e445faaa28f750b9d3cd758b7bfd9f66e9651e1f25f6cc5e5b7a8b85c05e0f24f97cb32321c8a1ffef529299ff229768b4f42b1cfb9c42ff993bae1dc1393a7f1933afab8c1cb25262526551882e4e08e9edf8d3b7247ff3220aa3004c1c12d19d9dad29a4864238d67fe57b5eaa6dda4a07fc71590da9b75b4a43091c40634463f883011031695fafcacf2fc33e7e41fca4a87a1635ebce7cc8e29fdbb48f9ffefff93d6728af1f1fbc873dd3ac9090cbbe15c18cfd5543737846b92f19b0070f86d07ed3714eab73ae3371739fc366af9ad9271f98df957dea5b243f1b7d41cea8c8aaa1a3f0e955f466596a77118f5c5b5c2b2c282430424040ddc17cf59dcf816cb8bb75ebccb6a5ed89d534db5163fc6db4a8309aaf2f0996d5ca97c612ddd507dc8f80ebc0f322c14b53273cbc954377a4df3c56f98cac3b0b06ef442154c056b0d3e347dfd37d5a4fc9552532affc36ad57febedcaca43080306cbbf781876835f7a93e92f99d5bcc05e9858aa6bcdf42a4fe32bd5c56735a5bf4a2a2515176faa4ec5c55b2ede65352eec2cd57753eabbf1679c71c619bf8a55ac228c6e26be49c93b8f3ffa29452b5af1adf85744893f3762f1319e92109ae9947ed0f821cb7f42aafe2675833fd0676b24333d9b03e29c1da0ceb9dc404f7460664034d0131c9839317a44050f789a2d656b3ea5ff649e743a79ab5775e8e077ce25fe73acaa1b3b974ac7e9692d25f6f7dadd3b0cf1b93b9f19a8c10d83d0d23aaad4a138757bd3be5459d30e68ecc8cc4fd4cf053031150047600050ab6bedc81129d650c51129d69004ca176b343fdc207dc98f8b139494928b520aca09a97e6ac6fd605c884205ee07e342144b881afa607eb9a5b5744c28543d3384909f7e267a1a1fd550f65726ca441c8aff44a17f21be26f51d85d99b999b7f57a4ac1b7c401bfa730f7f01fae52019841e3ea76066628522518a090945f4186ba42afaec45d55d18c242d9bf50f62fa3e9923aaad7aa2af497342727a73b0342141414046130735a1942862c7013ef5abf6135d5abe07bd86d8e02869bf44b2b1d337ac1c2625271514a7994e7e77144c7909ebf470efb60ce742c9919cf393c3f3fd1322dcf2e53b48c0e445ae6a58a9649c9ecf0fc9c056ba16500f038682fe36f78a67199eafd0350a7a3dec30080871db078ff52dfeb50dfbbbc27eefb1caa6bd48cea1a857af3f41b5fb8bd8bfa6dd6877fd50a6dadef9eeca36cad7e51b6d6be316cad7c63d85add8d61edd71a2f7cf173c26079ae79f1d70b182f60b0fcc360f9c7f217632feabc2e63b1aeb595eaaa6bcdc5fbd2fb94f72827ef496f8bfbbea43e2a621ff77d287b8f3dade250dfdf509dcba8f19f855f55f8fc3d264a90c46d4602c463a2043fe6082746576de898d7901fe69a185102162ee33ce618c01ef7afaa87f03d0670c77aa8e332220b8540a873e19018b818f803a7f543211de39c067f70af1752ed063f5ab6aaf1fd9b83300421409e200c2108f3a90063913b3d7728dade6566bb892af655f57bb9181a4c502cd45d5fd59961ef3ec4cfbf80f0dcdd397a7c1e3dbed773af8985e64f97c97eceb9e350d5876af51caa7aac4ed19defaa9b2b2bb88118a50cc95065853ec650cce60c7d66448b4259c55a2bb5f6a7955f798c4481fc9c551155258de04558d7439aa779e43f87f285f0971f44c7bc9736e674135940f7b6cd3eeacf8c3450fe9e2b3e56ff5c0f3c1c0e890f1fff16ae84471e3c72db676baec4ceb4a673f15dca23e6a4b4a4c55f5877bcbae3bdb703e5647a346ac50dc169d1984bb252c29a8348ad81f2f337e6aa4a14a2212c14aa7e34f2a1147bce6f55f91ebf1ad111360a8d46231a9aef755e22cf6a2cfad49a80804fdf067cfa38170bd5adc70d5d91866538375479f4cd2c0ffc723d26dfaad5d3385683b2dc395dcb2bbb5997c708e35695d4b04ace895552ab60dcf97a3cc8838a6e3c7adcf7cf6e8ea91081cabf95f5733ed632d7cf79596c9f0854ce761d87c431416b664cdd8d524a697c1e3dba477ffe1e1394671c8502ca90611234870aaa4120f8a64c30ad9de0967a7465850acabf95da08bf3dbb71d70dbb3dfb954cd05277495ca0d3cd5001dddeb34d3fbf08639b80681bfef621bd8761948280542ac157afaa9678e03e7dce3953ce65fa7476af0f0ab7aa22cce60e7f1d47dcccda58c0afdb0dda678e5f41e7c1100b5dcf14e0f7ae7b43bb41861f24f4d75529a02388c8a61cd532936a69ad35eb37edf98bfc9535c2777005a355c548dd75c53533d331559532d5e81cb74a550fd35abfcbbeffa239c00fad758e6973b4d617fb703db89b894d0e01f3044240a23e1ce6feb07a31bf0bad093ecee5521be8f6eeb4b05ab09a765a8397053983fff1871f9c0b3f4d7f6b5aa0fe57a01102f1fe7a1befafc7b9b36eafc78517c4b9b0f2c02ff167ddde8d8fa6a5352d50b71914918713d04d7bf5a580be9be4e3ac60ad69adb5d657be179f9fe0d114381864b8c7dd7adcf9534a8961d8cbcb8208781f5fd669b7e72ea6e9371fbcf32902a6fcd9f3f5a07a8b67564ea01beffc38808cbc95726e1025202023467e7e7c7c36e7a5d7b43999079b70cc873fad8db4a9d783c4dd47957d26616258a9e41806198887cca082809effd3681cf54cfea3a72faa26b70c18d9ec4d0c087df621cb468ecca44c525a06641f323180fe45ab49fe287bfa42644f5f3ea53fb23de8f7c0f16188eb4fd319fd0b7db4c6c3438264ef32e7209aeda024e946fda3575c41c81eebb7167f0784105a1b7eef6c75c8536b2418798a2fedf6acd65ab33dc1748cf55bcbedffcae5ab60e50e1fef70f7afbc92b22a49c13b2af97e9316e3ef1869846bae14a1cdb305abb47a77ab8f75a3d566c221dfddaa7af995f52c18ab0ba78bdb94261cf1e7c79fefa309877c7f1d740c7d66ca7fe3522cd506ba51fad70dfefe1cce301d2347fec3352d93aa8d185a5262d62cadfc24a105235421043707293bc321af05218edc90b8f07902180bfcf21e63815ff823641a7faff4e0e38e799eeb622d54ac85d65e7c8e2f538d0ba663fa8a3e9335b54267aaa802b318e67fe2efcf31d31a9f3ae6cdebadea996f55696bd2c6bfd2ae7ca935d212ae639add79e854c2990c3469ddeb4f5daff1a0c22aacba647d58f5f362d57b23fc62d608bf568bb49325cbb7a3b23ae4ad5ec711d7b2363cbc5692a9d6f21e4dcbd17bf93c635d7c49c9cf8f7fde07ad8a5d7f71cff84d50f86e7d8680ea8df06bd9e01b77605687bcf2751c712f6bc3c39fb49bc5f3e49aa0d0bebbbd4be2b0f75a544399dda42bc2bbdcade815478f55e5885c4cce39e99cefb4eaabaa92f2b99a391e6b48449b53f4257584e5b82220389f6d563cdf65d887ca6f34f724535a311dfc7873bafcae8729ab4d65537df61cc3f379b80d0fbe44389f8bab27534328bfe3775cf9bb6b445f9bf856e439df65d9ce4d5889385d9bf7300b973bf93f1ff99b7adc7019184108d13fc4cd8bdbcfa3ff088ed9669e0f4eeffd458fc15307a0df743e37dc5aef9ce580f031f66e252002fcc26f59c72ff0bdf27b0de38800bff85b7fb12f754cc7641fb29bd71c7e55586a0835d5e88b3d5f7e5229c8e8b3d15fa32a7aacca873daa34622f4bc0bc96ffc7acc67aafefafcaf70a23f4dc1caebb820a29ee7476ec3c041ffb93d60233d328fe5849ee2faa3030ad71df1b251d50cc03f459538dbe4e545b1ac5836fcd7bbe4840e77396314ee9b4f9b460ccf5b03b8f77042baae8b9ce8a2a78aca8624ac7f021acce7d6ab43721e73ed2a42d7be65f97d56cb429ed08f9cdb46686d48f139079d0492ecc5c6bf2993dbe25bc0bff9d74656ffd1088237272724870fd9b88d2751cc83c85cb27f3e05dcf3aab817df557dddeed31dfaaaccb1a4d40f83b15704e1e8450668e3f74a6b5c6dc7baecb6ab652e9ba8dd1c61853a999c831c2c78310ca5f446bbd430b28c422f505aa95a8bbbb1513b32aa9c31dc06f19fbcb46ece5baa3efc639fe1b0bc999cc33daed53733ae0fdf6ae0146f57fe0b6095470fb213371f9e50b94b6c639110bd331e1fd5c97d56cf4b9abfc0088c70540dd879ae6e3dc19658cf48f54ae2a7155e1f896f1fbdd6887f011b4f4c84da3fcfd8770191a1fd77fdbc17f43ddad5eff52e908a56ee47cf4ac235fe07ee3152308c3755774a0e796aebba203402ef6ae88b17b7c9f0da69da8c4ce3654b9644502000004a3140020180c08864422c1703ca289aa8c7d14000f7e924a7c5a1b0ba42087514a21830c22861010010000919999a601a1d84f23123ae064ae4213926fc04df9ca1a7d842d32fedfbc34464351b9d2a4bf571c3ea4db504781b7b6d1e66b194a14dec4f50ab308a4508a51afe7c564fe2793d46f349001dfcfb7df93806185219d9e5b52f1c5d248003ff86f878d4cc315ea4b2e23e741195f96afa6a249d2d1679180a1c55ed04cc998f87f56e86a38590487854d84d08a9ecb574dd4afaf266712f2f457a6ace1f4b60496946f400bf55da77f8467a50167b56ca1939a10dbc804f1c295bc41b0f08ba725410994b77062b1e05b0494cdcc5491dc65f3c7b7c0e22e3f7133bcc59b10102c6131ef22079104eec18da499a1f9368f060aa6fb584ed6b9e60d52aaeb87f7f478e074fde22dc1b5c60488dcc73df2875be2d859c63e932d676aa0759c8d13088ae5e9c3211712ddc770b234e16d51b259c156ad00d6788fd59396be6b9717fce3eb8b287b84f205a1bfc4764342d0b6e58806a5d5f86275fcade366ead82f10c6af0c235b545427406386b515808a13e253d4d81c72570355ea8988c6236ab47e88a0895dc2250e20e8f418053610b06545c4fe1424103cb17435cf5c22642f6987334c05c815b0440dbd5cf0d091431ffa9625910707318024b4a794169d9db055f536724b591fdd8dfd36c61ee7990a505bbb8d3a06f0f3fbd1293b618442144ced6348f06e8f1dbc98ecd6d8c30a35b6e4588e8d94ddffcb0a75c62665c6f1e906e378e4192b31c64e3ac30db9a58e1477128069c6051d1defd11876c437277bc18238ba1218339b2b0e9cb05c01a4438558d9d3470e4cfaf610e8bf06c17dab914e5598da32ba95826e0dbdf591b560cae7b0ea71981cd010548b7798ea12b0bc788c11e331d6db81a4f0aff5b8c762c3c800363ddc44c294a78a9b56bca67730e3371af65584b3ecb92a766b1625004e5a6d6caa90303b8f3dd59420dedb334c4929d250d202d0e880f10796871a458bde1f967110d5e90971154b9a6c5c1d8d3dad384d54aef3c42b1bb115076f37b37ce20915c68e5dfa8f6626464aaefb524b2aeccf88b6a911850bb0fa52150560a34182be4b665f6af43038dd861b00ce1cfcb6f6c90180e35489772f0bfc7a99252075df86edc4175345bb6aa18fed3e2ede3e175dba48e476cbc49b7243a9022e06074085d6ea333502b9614a310b9589256fc7e534e580d8a5497b781354912af1d92868b2a7d04115b61867663298090d4e5c2088c0f1d01c4cc72136c5f90db8b242f62abaf5ef64e1aeabca144cb98407f031e7ebaf83e159cf7c3729fdc171ba307d583a2a3b0eeb9d04052f12b0cb63fcd77ec2fb17dbff9ef691cde2d901bc0e1fcbbfc7359a737d62be268ee2c99b5ff4b9b22c2f3b7e970f8ab0935dc0354d9b94e48885262057c41e89ffb8494804a9f2c4119273c1579587a57bc903009960b67a53587305743aee3a4898158639ab7b3918441d13669bed41171d11c25cf536a0e5744561e8aa184c2422093efd2210c28cb7e57476d485485f1b921e35b60f35f0e10cc2a4e19815683eb7292f78278c456a45039e2f30f59f0dc013ffaaade8e7abaaa432bd2ac7c162318631b6837129608c82381006a87e16fd72060f2662657250c59fc1068ea74a2b495f51dc58f2209c97ea6ec8ec6ff59c5407e771a33d7afcccbe66aa5e297a7c187ad5ffc949e1171fd3c26a6b0f31a3936b0c035d9d9c0a032647482daa4043d44d55f0529e0f62e668bf5698bcd5e241ca3d4d005e13738764d912309d69e32e1b15c0c72cf3fc8e2ce61c8a4f99f0d63eee14cfa18e99b1f085226d95392f3a53a6ae9916b168721a43575b44b48cd43547150cbe35daaf32bb9fdf66f741395faa2652054c733101b16ad718a1ce2b230117e43a022f5bda1c9e0086d5b4e34987c4c7dde42c4a4ac5738bf14879b9acadcc630132fc9b8658577eecaf804cf028589c65c21615bf951fc9d0003b5acaa4a30d4f88abcbef5513d25c03d59495d8e0ea1611c8345195c54da13c44bfffe7bc57a859632b4480b14e4edd6b9549b7e3b68476d8f26528cbf1489b6fb50e7614c2eec54b5769b8324263ccbaa5c5a63e35f305fa8f4201e7bdf381467adcd46188be6bd8b197a8b6a1c61477bf0064ca20b2eb898e44e805188dd4254958e6de652235577d510acb8f0007a5af69171ad8237d55bbe3d78af815e0aebecdd632687b65e40deeca8485d857633dde5282fae62ed3f79042871b45b3a8dd956b2d278d56b8e0eb3d5ef8b5738d7d0027773397566afa93557c8018df0a18e624b672f80131fd1ac7dc11068c57b49b181832df201816f3ef4c1a225f110b2c46d92c9e9739fff385c847ef7a54463cbdd9a46ed87765a043ce77e1fb2cfef5bf033fe5966106e756ff2e4f68fc348c05fd0caf7a2609bb9681de4c1e8b91fd578eefe77f59bc91ef8d2468412cb3b8399ec5d703dbcf674ac48d95292465ab7a99677b8afea3677581f5fc539fe80cc85e94b828c2af4d274e583955492e645c80c4dd192efd004af710d17d472028b5762eb20c94ab02458d138c0563cdb5ad561a4a154ae78ecd8cb92225d4c0d593de0ad5d7d6a45a37db003f27cc2bc788980532f58e4aa44fdcdf2b308169c9a44cccd791458f6d864855152178295f92e2b6c4bedd2e25e0336a078c84d2149e02e4905f83bcd29f68ed81a731c1d809bfee8855983f985ba5bbc995865398ae9b1b847b178b924501f0079eccbec4e0080531362c3a0f88007bc1110a7f7bdea100ad3374c2f19d0c42b1eda68c84c34ccbfc7794ddcdfd7e5480e3d585dd637e48757fa527abd269c9c27eabb2e67eec3686948731124c69899be399a8d82565a278ba1185650a97a87e277a63dd10874d6b1d8fc967e93c6b36cb7bcd280a963a63228ae5e2230b8fdc3e88ece8fe603b50edb30636331e4b3b8fa20d09d761115400189fc8703ed2c7f38d6b4a16bce9c7b5cc4c2b2f5d39c1fcb16e62ea648f31ea533580bf7be30d4fcfc271096e676e96c5dba75301c1fceab2a8f6417c1b6782f5a021f85bbf5d9d38f40f9b8f0188614af35b057efd6bf9b8cc3ee39d637a7bdba388692da33b3c4da15f36d07a593a86040dc7fe134251c54c9f1d3fe4d721c8f39663d41e8aadc20add2abd7f56fc17270a11ffff034b903aaa183e862f4e101414f8a0b8fa6e7b04c3bbeca1eb18115716c8760a0eb834ba9ae6db0747f8830867606aae5f986ab0a8c64d1cf7cedd162dc6e50d271ed3679f59b5f76dea5b7ac09c593a5b6e9d4b20db1f7ae725fc1f7c2e9cd1d2f2700e667fb951e3efd4364182eb0d697f7d662a1cbfa4516a6695b2f2afee411e9e6e4d70f5b3ab80e63c67304e20e9a2a22710a74bcc5f50c5567f61b9701ba3e84e4e2fa269d86f27774c799f969f28a835eca76169c9e22808f1fe332f7a54bc53501054b07da755a55d2c20e6e50c6cb66546bf206e29cdd7172b50d010b38c755a7c9985241163f4a04a48302ca967dfa705bbc7517aa3811ad429235996078edd7e9cae031ccdf96bbaf16931657430be37a656e41332d7e453f8e8334aa8e4998106b501d9fc6034681d4422c8f2bd1518d72cb62b2e76ec15d7d8502cab0f61592f42a5bc5941e84c11a1f9c813d080b866a1e924d5cc93f4276925b16bd8e579c41000e53267679d53afbd09122b1a3e79deb485fd4632cd2084e50bbe114bc0a45a2087656f82b25d43358688f6ad36c45d0cd14674b8b15155f42ac41c5517aa088a39cfaf8c71e29eac65bb3cd7b19770a8432e4b0bbe4025eb66d8009dda5073204d3bf18c67518810b242fc4c35d53a051ad767182a237c234c476e4015a14877058e3e64d45c228e272dbf6f7e7d984fa3e2daba683bfa802491d79daa7c26333e1284921e02c5ccc577362d46bce8e98f98ac9ffb5422eeeb14be38ef4148ad959161e863ff54a6e730fd901d3529c4af25da7725b065068b090584e22604987ff41577679d61fd463bc0bbaa9e96f986c629970a0b9f7b11aca083fb53f9251762f29804d6da2f4fb66dc814a5b46bcb5b6a785243b38db267946491014b96d23fcd76b9c628e1bbf5f49b896a5a156cffd82281719974d451a1e06e68d300c0198bec5ad8f60a303ee34324c2edd8f0be56fecd5d2b2e7fc62e1a4517b8881d3b1aa01b8da207bcf44df051d9613ca6820f353972680945cd9dfc89a016e30642d25dbcd0a160f8031f9f168a2c3b9d5192731f2657b63243b210b0c5cbf79354ebf3ca9cfccbf52425d3181d77885d6525ff93854833e495d3c8c3e2f525b8100de30dde68b32ecb51af4fc7a02c04144a7c5e6fb7e7140391e9d1c2d9cb01c3d881a4ca586c6a28f734bcbc730bf47804d721295d3d2783dba2c420272a663529324a188f5378f849caff9f3896ac5a810a5ccab951cd9073837f9e9c13ee67aaaaacb26ded3e67e5cc9c190138c97807fd16d1d397991adeed5bb9fd6eea3e96eeb6bf6585ba8696aaf793160d3b924e51c54a9d4f064862471582dcff6bb3b0400fa3004a362926ace06fba176a2e3c0b2cd5519c4ec7adcdddfbe1f8963555f8e897e11c43fd731b33a1ccf7a5b22568e810adcc82334947afa989e596b2fcd3590f63e61b7afa804fba257033851be1119262a06bc183fed6e39e30ebea7ad2e5240493c3eed4038858ee073512614341586933877502d91b147971562be582b59259d8ac2626dbbc3cc1c2170e5eafd851dd61d6cfb02f9c2d69f3c20e46f2ac7016807c742d1a0829ac88386c09b09aa61cb316e3b2a0d3368de9fbc7e729c3627ec769e3cfe020c1827e27c6337cc3f75f8ef8d44be7f341afa47d234a1fba05944660e89634de735603b625404a3331033bb6c57b4975de0ba0812a6d0812bfa69126c96288d7ef39ff8dfbf83b20c13403b8a819bc4c33681c467b115df101dc2f4c60901ccd20dd2989c7ee18dac4184080d93cf778a36d075c626919dc5aac8d57a85cdfcc402ebd648e7a964215c893fbbbc31db832fec8621f38c2c1023f16adcb92cbb2e591eeddca717863abf06f212833def8f4e7ac24252206621fd3fea32b2ce370e43f657e0e76725e9e32a23b379d32f09a966e37e4e426f3451d5af41513934bed5c884bc48d32cdd3f1e7878bea866bdc0d4e4a1f5932da1dd49246e12d435fa80b855ed3c8d2051708c9f7ab5c3bc4df2d7a0335324f98ca22e787ea4e88cda49a449cc2c0d7d01fb50485fdc3d86681f977560d515622dde6f7c376dcc11b47febfc5df1ef29cae1d8cc13528c5f085aeb020dfc85ae013156c9817e650d2a999cfa4dcc6464e55bc513efcadf01aa93e4a5a4aeea9197014c27c873a5c9861e5a15f6d6125f160a87719ac0b1b3f226a51cab66e1744806092532d747990717056999da9f2f03005ad691aaff129e6c308c60d6838fa6854383a6e2e698a0ca81dd1d87549a3396228ab30873883daa2f415ce9cf5afe6ed926044ff3a4f99d9b8cf6aa2071c30276cc59dbbc09c925f48fa1d92e3ad34badd113031685d498dacf23db23ef380ad9a15e1ea6f863310b796ccab09bd36fb322f74010b199911cf1e5364cf7ba077eb3baa33d56b1c994940261b3a1cd9a495fa38231c246e18761a590ccdcdee81a6ae21751e59494662bfee39b3d7d188a78eb3568da15dd37c9815fa57cf41e485938f7a8bbc41b73928036cff66805daa998b730da2014f332592b749e9efeda51c2f8bd1fd8f0beb910ed9e92723f04910cd69d75d119c482200f5e4ea5cae9137de023e7f658fb1134eb42ab74be8b4d35ae2c779e90327bcf5be7536582a65be5d27815d0d3e668b34b4db10d4151a57ebed9924f020eb43cedf761c9f7f6148f315f6970dbfd4f35f5c68e208d3b4572d238d04554e1118a272ccb7d19229838f1de234c0a3a82a99eb7d7053cd802bf73df2213075dd3a193289801d4ca1b57f2e593916677c878ab106f400aae134c349016b9e1e24254c9694f103a76e93561109606c0ba74092cfd5396cd136022dcc38afa11584101a907a884ff8c9beb1b2ae667cb664f3bcda6a83f365892b482901ccec7bf659b8130c153b0d1413d71a90283e31ee105a18780c3eb242e02309242283f16f3d62f23019121e9cdec8be7b3ac20a87e2f5a6498d965a45fb21837edb7bb5dd4ba4f8b3de83097e70da346745a493e64fed831a1967524046e9f2dcb319693526f3f22b58e0f23e9b4aff3dd251aff6dc726525432d2a39ada450566799c6a3209549451abf15037c881e5e551ebc3f01d168b795e73745e0db68bccadf9da57667ea6262136cf48ba81ffe59094dd443e70ba28665440948f0b0e3954ad691102c90c72095df6fc35ac1f510401d4f6e20e3f77e5c77cd2e53980d1edc25cb9e0acd69327b6974bbe2b53653078f1982b8acba6263873d092c897f4e411ef1c79a808b96e6b0872809ffff6d4ded46ef172fe5e840126520e4f5493cf1d9c70bff49313ee5adfc2581415ad3ea1bab66f988949efaa62568e2b3f0ec4074d152b32f10459b2eb3ba75190daefe5f1b1c78bb115ade0c06071e31db1b54ca43a1d17df0dc502499437a474f09f8b23e586e0865ad05c8751c7abb7466db4024972ae3037ba0e303560c05b13b270be48baab0ff79d327398e585b527c6425253090de9042295915fb16b8d29c71fd18b9e0efacb4898b34c4d413c46f81df939ec403751a4e35f7836440f902915986104b22277ade8ec4d5eecc66535d96bb7d5d616c14d94d2e8d3b6fa48370a71b85591b8ec8a980c646d0980f8a6c076ae993ef2cdcf14bda9941e5d9e9c7bbc5d15da1d806ee7e4c6173b3539b69b7e7c60eb3cd74a1ea4a95dab67e8299007aee3a2a671eb43b0fffbeeecf041b606a8814edf57453071a5bce9efe960ec13e21024f6da7e6b61489ca864d77baf04f953612ff4e2eeed55286201c5fedb2bf24a9b3d7ef9e7f7fd5156135be31f8aaa404b6427f1feef41c4c729a03155a14fda6332baf53b4c2664d85887580a1741ff9facceef74650aa3747f5f6cda97b4abc4335c9a11ff36d5f02fb7d4cf0064bc5b0b06013defab01942df33de9e37b5eb35456532e0060855bbce9a4d009200e676d568482a00ae4a8cf70fd3baa31e3fd5616c618e141d100bbb8b2d86d2e34df08ac941becae190a5a472c32a19f70f53eb92e856d3adaa55e12dc309d2a4749bfef06b758548cf9dd57b25b289ccc9e6c01c4a959ebb7ad673f64f388990b53cef297a4cb244d961a1f6ac1d6f28dc091c58bfdbf9523960d8aa3fdb109bc38c18276e36d8c10aac6d38d4c0ed2947e93d90c8f7b35070c9fcb225be59f03b0b21aa5b17ef5b8ba20e5d3a882b845c340b5c3e0f18f35bb7b05b573c2d1417067eabfcb0328854cc4f62ba7ed19e85eae9efe12f6dfebccd5a0cebe799102ca8d142381c5415d1fbb281afcc80e2dff3a3806b1d463c69e1ed4ff5c82e1df859ededfc42649e8e01cf96ea776a3c90c75ce9193a17cf53e400e1471d476756dc5a920ae4bb2944ae16aae34d0d6109ee48ffde18351ee9c0bb438637fdee7a4e4e62f4e059810d31a04596645f2c4e032d0e17fec5c083205578818dedb074114c3dfc69374a5d3281448b9870a33f23e9a78db498423438a96aecf57808b76217d3b59af21e087c7e3f86ac2b9db57e3a285ec62a63774a81a56576f6a1b5f7b2ad85faf5049411977f0e012093cafdcf881013bcb8eb53ecceeb3c05eede49a73fa3f7f7f82e254f92ca3c4187f3da0bba5680e33656d0c1982088dc937f4ba2e9564403383997796779cab2ae66b1d484b3cee61a947be4e25579ca3dd6c0857a8b07871281f120a49a9942f0e45dfd4f2299c9657d06e0d8e0e6e943d5f847468f2411d64221d529e4a5f2a4304c8644f0035146920910e291dbb085fa05f43718ade45809d9af56b2e1a850dc2801461e568c7cd821c0b19574020eebe96fb370a742800bbf364300a0e1a8036d169ce7adf00315eb9112094822b3c6023c8cd3bdb2c783194fde9776828ab227642553e9d2a3ade1593987c6e7d80ad0a2b2a89b754fe97b6e339a1ed5136c805145f25ed79c745a0713162d84ef78f28e29e5dd458992c520721cf0527fe6908cfe1d70376f1e6c41471debd0b6036b0ed89fc2003d7660d67b74ac30e6fa04950b9a76c357692a798192043e4b7d35553f5029cbf239afa8370ebd068a286e613bf46edca57af628756403de15dbee8d5d6d37372aea6b79cb3c2039e0d4f14b813a44530accaaea9dfc6ac82c3b7523c6cf2c0fd347ba97411e15dff2a5cfe33bce8654d0a3db123d89eb97edd46b882444e5671fa4ae7d4d2da27bf167b07286472d80cb63c4c659ca3e6d8772e9e165c5da83b6d324502b6b58e94de6135aa8d4702872d57fa41d2febead44963810760914d0d80138b930b088996001dff0277f4823368d37427e28a737162176e1fb24917854b76fe2033362d185452a3abfeb4cf7849a218b895e41e3e982de36e12992ca1b0e100581c25ceb3aee64c01be8fcdbc435406f082422540e1f5dd0eb0fae31ffb3b0a8911b84ddc8a68926aaed4b990e08aa9c835452961ca9cec4102ada9fb24fc2fd924f17daceeec75901ca18e7bfebf0acc7566d2629fd1a1a25aa93879c4025a47465ea8d2f0741b29243d0ff7456bc1d92a26ea9ae80675e924f71e803d8d06a6891a9c70c8c4c6f0abc1c2957e844a06fb0ca7c28366bcfbd0c1f7dae623b10940a2da82539452a51dc9c5d4e2204539dbe914b300c66757d97909fbe5c632d906df200c0a9004189f2e23e7cc1024439f777cbbbf2342690a9d0cf8bc83dae8fb1fb0dea7e14e60d233ca41616c7105fb6cb794096245b5542560e3c5f9e3995bffdeb490c1be5222360e5ac4c515c54bfd736249aee91d59af0651c04e1c81b2b72276ffe3e26047230db751e6d030205504076156dc4d16caa415f6d881cfc7e53203726e4d03e1e55998ef01e0ec2304f1196ba31365214558ce1db7f5f7f44c376ab8308fa74ee23e0d1a2f3571c773d7524b1f7d2ef01cfe2b8a45e8f2015de0675e83c6bc33ecd9c726637f2f2c05b0bb988397976da7a82a85d0ade16695d410be572e538279e9151f84250172353d2c8ad23f4a63fde5203f7a5c34395c1ea24160680c10710d26b75990656ec70a655eddd377aa667a27fd1313774a66e3bc4f0b42a688ec174b911bcbcc959a01bac57815c5c6a2bb35146f39ccfcf7541cf64bc6fdae21d80e6651666c4676a618a8f007a5981e73490760e8a488fde5a239b3c193c56edc809ce024a9955dab67a6abe2d28ef8c0f468b85bc16565ba3636b82ffc24e3cc6431ca7b4dddd82dcf70d80af4e24757d6ada7eef5321fa08160c3661a0b4a0ddc829d7c386180c134a1a7e0e3ba0df138658291b8792eaaa27b3f33556471aa34ef5baa312e05052e42b3041fda6c2ac5187905d8b8a4c99d98f61a9731cc42c765a6ffe0117505079e7020c2ca125a8c5eea328196f4adda5bbc3a685efad5a6e572303883b3c71177aa512ff1d268db295f4815b9a8ca28d09f5bfde563ccca517d117bb397b7e93d7cf517a6cae43a349917c3fe2c0b56f91d152c0bb650ef57bcd83634a5a570c737d61040e57655de7d7f7830ec032a5171d2856d044226d836ce241999b4c3912025a37aea34fd10d08bf5ee8e23cbca1d95d7f9a1cc79a2bd515210de54e01e0b9e172a22dcf146108e7c1cf9e747e1e98c8052dd0779b7145dedd59036f0f7c80994030ec2170de743826158e0bd53fce29bc0114093ff2105f394d030b44b65d804bdeb332a845b9cba8ba486702b58f1c3f086970847e038351974c194a1da84cf42a9875b2b752001849ca1cbc19d92e0247bb00f9e7f8c7d2b172c70c2cf9dd1350fec7db2c14b6ad057fab93093ddfba1af80c5661c0c5e30bbc6b30ba54d781d5b88720e46c1f068a29508d819d5f7d6c8d419d5de2b4256a99aa0f849ecd9e3263edef36bcfdfd2ba69dc5f33cef9b5728c15c3e2d68b83e9568118e90fb39b78c90d9d8a29235fe7d891af2c5f927d9f5c8ebabbce27e201e001b0624318fb38bbfca87a64512bfedd0d62b17e0fab742cad56416625220b833b9007776f773903a63e8be18c7b1ca4dd5cb30ec664e507e69ddee648c7ae9729341ad30a9d414cc480bc168ee69c3c06ca8831ad83340f966beed55f58cabb79cf26e11b1426def051ceec9e5ff4520816aee40b8a3f39f678435a37ab45db1bb60bd8e6f6cd14c5b0ed17e47d98e879175d3e99d53ab8ccfa2458dccc7833753ee5fd001f1c69145e77f55956325bad01e11abe03502cc00c0edb0effdfe6dcf8e9f9c77988ee8eb94842211ff2382cdf43f1615e7f1e932fea8498dc6f3579f69823f51da2eb320fe5698d0ba5dfb762cd45278577cc926113c404aedb660d2508d4f4cb45cf648c63d7761c7a548c1c6e09ca2a6543dadc4c0315cd5ec8af2be4385219fc8130ad9e29d85cc703624b7edcbaa5c7f8e50ddb9ea567c47167710e2ccf30f2dc0e44738ef7456b1de91bd1337dd4f3c0f47bb99a9232de7406d050055ba0bda93c6db48fa778d7ba20ca0524926fd5bac86ac07118801a15dfd2780703ca043fcbf53f475ddc10f94aa1820a0219746307e894245d3e99339dc1385378f9fdc428e8278e850f09cacd52e3624e5c1d11db5bd0ef0d97dafe851435d47a1d161a06a223f796ee5662c77e2aa3a22a873231b0963655214fbe35415b76094a516e1081961465509e50c775ad634cc747b5931eb191f52abc91a18d6d400dd4bf48280e4bbdd9021d7720f42e63128bbc181a0d6a54b39368399cc0540a8996ddd1a9a4e55f5afac2f13fb3349562c303113c61d67b05aaf30ba67874875be8e08ebecd15aeb471a332d7942abbdb1c8e791c4804cbb858b184e893a24e9bd8e1cb04f656347c1cd05c9452cbc73f29a393644263ff990d6e1d97dddab07267ad3db098dd5a37ed1fe39bc2152fa130d33206388cb5b265b1ea74d8e6f8410639efb02065a8dbc8ac58c60d0e7cdf5e15ff56b1295277fe811b30683d50f962085471a452397826e13b76d8cf60973ceb147df1a09f2099e4a429c606ca063b1fd064cb61a2378bba66c76be306f2c45ad08d1261e0b14621feb5c75102ac9a711311ea63a99502d51a66c3a293dbf6d8a149c913d8502658eedd64f34db8502496a9ffc50003543414088ee85ddd528b201d1f11f52788cb7544e3b0cb8edc83c2dfbc1f442de1ca4da036adb8d494136786eea602771b378b5ae01137fef28d04098aefccb7ee7bd12fdf96d33624ec268d5343ab90e92de29591d88ca98174fb0d04476b4eb0b4a9e65ee2372365f2ae3d4b416efad29517a78d562e142f0bc7ff6d61fe1ce9d392dc8782186a38a03632d0593782345c6e279341067640b63f01460607e6f45deedc8c96d9ca0c94ee8387d77c390e01f3e4be7aa4eaca766a2b279ee3ac62a7bb1c0ac394c122533bfdb9413aa4d595e0cfccec94884b7ee61df60e0c5376ffe45b30b73f403bc2b1ec5775fe00335f7bc877cc1bc3be8a53f9cb2e80292d945a86edf36fac00a9e7e386c58f78b642e52324ee0c88a0ccf8eec24f5928ec437dc684be5745487e3ebbd320bb23058ee499595da0513de4a1c82dffe09811d41409cfa6181b4502846f82525c767d89d40ede04aeb90fd8e5ef5e4410074062b6a9888201d5a31debb518f719e73ee6521393d00005b43f943f85c7b2d29e426c437b2e12becf8bc33ed151f17d4b842c623f833fb2bff51d874c2d4673db42f15a869cde7eb592fadc82b53d8aa683181d6396a787b17b96bd9d665e7db2b86f0541439cc0913fb196adcd063c727255b5c6c1f4be7be0fc21ceb6b63e03854890a4a12d423a31f1585087630e1bdf0a1c5b43bd073bad71352d69ae9875f90bac503078dcc1ac01506b260e21b6e689443ec6ec6b3fa8d536d36b6116731c389c8e7fad79a391c308491164512d05739ca091c413c52c92c2dde48823bce04815787be8c1bef84fa8cadb872a2da41d83192603a4d060d5bd07c5511231ad8c955c736efe4b24f9142deec74fb8dfa8624b540680cb8eabf3e0211b496bd6056940d5b9b4ae69025c5a1fb8d435bfb0c53cc98a8147b853d79640d4c7cf7bb6ebd7f2795e8f58214762ee1056f804c6e4e5ee2a0919822d8dc566698571ea6511afa1cba44a837b363017575a4e8c714a67ea481d117246ea91054c810b7a0e5c4fd006115653feb007bf3d3297c16d1e9e0313556288f03a4008781674cf45e150921e1fb06435a283b732917b984519459f64024081e11559abe3e4edb2c12ce4fc1427248f97075ae11e4c6ba9bcc87c95a2feac5c3a8efa748798317b0b0e599a312ceb732384c48490bc64a1ceda6c0e3d989b74fd0b3cfb6bbe6a75a30556a3fd4a2881809a0dbf09db880838a678d49a2498d0b1bb1a3111276222275474a5e8bae4a0f7c86c51523369cd4b236385f78f065b212847abe10e8d3df1c2b83e762f5cd0c834575313cb1a4b19444380569c8eb2077619c9ca1d5d472f139d501338f12638b12672a24dd0444de0c49ae8891bbd26e2c48e6e263a4145a7893db1892c749a9843cfc44eace8688263a204092f9ac2dc98e64aedc1ec9d0bb287463fe9f7541efec1a2f26da3e4953166a3c50e119301b046edaef3bce20d5d6130e34e9826ec33719425f9e80fc7b745f413aa03194739f022b4f9090b674e4a4ce61f400ebf5cd5d3bb7b0d978ceb316f9a56546c0e51efdfc6466403e7629d18a8e13f25a542824fdc7023d8bb17305d7dc6a65777d40c39755e828c66d022a44a80f379600a377198cd34d2f2aed2dd4cb70ab7970521beba399550970af70c782518c3a320007256268abdebcc8e93cb7f0a4a651ffd73a6bf2b1ac1898055a810a0cb20b8c4c3c4f908315d31d5583e134a8e224d2c11ed484789747e2f40c906d7d73e2b200c86b0111861d7f5d75be5e1eace18bc7a758a4da79d29764245464a08bfeb6261bc0951a389ff71abad9c4e63f7310e031d156b1f793436e545edc3fc5bca60c6726e3d6a14a8671a69c8abe6f2a1990603b7722ab3563af66ff3761654c4c5dc4dc0a9f229d9cd4c15376ee37ba2e6756996314470c0020aa466fe8fdb3a1ff24447e69e40c77ffccef3b5fcc79179f8505e7b17e30c1463579ee4a8274c103ab8c84f4e261540285abb7c9deb94b38d63767443a8d5cef34a09671c0450dbfb3f09cbc75a3fd78ecb7027f0864aaf7f12ac64c7f91144314184ec6773152fa6b3ce20436d5edb3914c78d0ec67b1e0421151ea8dd92e7eaa2ab52bff20a195c39268d6e0b09125a2c3b1fa9ff61c81b1a6651cfdb18c54fa83741dc20d873629dc4f6fd935e09851c0f7ae7125939cfbf75fbc4616e57a1d1dd2e3e9a9c9de21933246f0aaf731c0d7c18e6d4b8508aa9efa89841062079e752a9200c6b944de084d948933ee31a9a18e09664bb51c570c6f65c1e82cea3dfc4fc99b12213adbb9d21fb8637b35accbc1c0dc34204038a41828112ec3f86c075efa03d597a1858e95b730a10b3d9b501abea2009bd922835f38077f510829a2d76a2763571f44561c9fcf54fd4a43570ceb0bf9546e7d819871a9d7cf13430ea3e87a4e25c6caabd7ca2edf086b028de62772e05a0192942f33b2457c3d09511611bfa40bee02502a49d123cb353363e76c61efc939cbee8cf1ba48159431af323a14dca9f3a17d47c56c838c6ff5f84b93b0da6d947adc0b7da5330c2e0328ced3da66487f869c3c8dd483032e1f4412d237bcfd707a745e75887efa9ae98b42382f249fcc42d5c60f5b2715196b6555f6ff318cfadf9c7be1b998032d86e61b779592c52a009f7b3096d8f40e3e6f437f9509b85f722de6b2aa630a02cfb0d1c1a0f520c0e3e10d41dd6020d47f6a0b28a42dc5c3df01ebd65761a1881d2f0fbb08d63974e3d530e3e2143677caa749859a55299bd6d2cdb75f2649386eedbeaad075c55a3b50628ffad84d1bd2bd62374f12f20b28b07c8c50b8092d0810a1b07586f53c373e8b540717b19a59e4e384007a2c7e911e29fc43c00b1da7edcd739337e462ad79befccbeeecbdd8701a7cf28eb221303d02b306054fc416ead9172ace594a3db5139a2de3aa68c3170626bb393aa603b29fd64bf06c2da9a43db5362405f5cffc852eec412b6e52306e9098a67e9728e78334b733bbddbc1625c83753b94d2ae9f2fa3300783f20b81a387d2abe8eb6410c25e0d044120cbb0e198b9b5b9d8071931a07cac4029cfa37190ca3e10935f828a5686d6ff1757de7528a5e977d84d07e38db6a33d4a2bed5f787316ef18379c212fb6b50ba92d0d8ba9fc46cd50a35f9e930315da091fb4ffdae99893d5d917096bc6cafabc31485cc12ffd86b295d25d81f4a2155844866500b82f495d2dd47bed95c7c51ed6ac882c4e7d5bf0f3fca7f7513a95b639252cfd042c70f934559a6c63996096408ffbaac5c71135f1381480e8aed2b6b035d96ed8432efd5cd184333061aece1314adc2eb04638e3aa0f3005b4858e174092b1ed102f712564228b0e1d67e6f8d578203a054956e46a7606873f1265fa5216baefee955f44caa1f155e25768bb13239857dc939ad0829aa4c85a5f11a997a24c7e49b5fd0c51ae9800562a6a07e459a485a5e6ab5aef00129f181df64ad1f2587d49f9baf81851a03c87f9434ce1b2bf84aea84857d80474987af5ca70e4f32b1268b8b5867e14b06a8d5930809ab9b8fdd11cb9e8f250a6759dfdb789bae008d3d17e7b411c53574a7cd51c4681a6944c27fce79a41405c25387b8ae8840d0cf77f83424162babf08dbd662ef7b663b49288e7e35c4969643b0c09107f6c1f3393edd458736e209d222e61150ebf1056b12cc788f25444727de4f7281755746a16f5b8d9d97309187c16885216e9030743acfb180aad849387ca6668d1cae0731d36a114db0f42bde7ac06ba7983ccc984b7375eea518bae2f90a554e9830c97d688893462c59ce3d470a0258297021162986c232caf0cf8e5d635f7516609964a06394d7dfb45dd2b50b48cd29b086e7881ae792c2a5799b1ef41327ccd43fbafffcfa430b40055f4865aa90fc7c4eedae43537034c6bea405a9d24c83eba6a22b65fa435e07940faa5173cccbdf44b747811c46c2de96525f60e86026bf293666f275c98687e210432ad3a420f990f8baf283ad2f1172399870aecd00f0d39b13167a1592bc156ef857ed6f3f196d41bf08c8f58dc400274ec21cf6bac26d4a8b5270b2efbcb11099bb15eb8db54d7cd663adedcde33b29c66d3ce5fada331f6cb682f41b47382253a87aea0dbf402b301d2c941c855036dd11fc1f31bf3e91759111d98145b15e2ee545474e80dbd3962a47f2c23cb6a7d46cc13f810a0503ce3e52c288710d73a923816c525a478aa339de49949326f4dae8b6d7ff0a515a79158f4b2ebbc7b22f245d102da061cfba6e911ef6f1698ddc7bee1dd9fc384aa4aa107c109000637f26ecd00e4953294b1d0e70df2148f6761929dcbd8ad32cffb608caa7102dedb645c9a9102e8065ad59ca4e88299884119aa578e0bc413ed29b3583451a8e1a71958d871867f869c651363fa2a6c0939ef63a5eff070b239a30fe714b981433c347d547ccaac3e35f76809c6c5cb9d70349016f9730b43d50e8f8665403a7192e97996309c26d2bb706e3ab8fffa74ba6552cdd9ae50ba5f40f672991cc86c85e42058483e453a2d002cbd8a2fafc55c8413de380a37c2c31c4c99a81a608e9450f221498907d61e5ca4b2e9accd81a74cb09900fc5045413fe44913b5bbaf13a74080d7bfefa4ad9a200492b6e0b73253021253e4759e04b446f7e009ff84a86ce2831ab3a9aa5e95ac4ae6983cd6e1cdbdc1e4b1fc84b82588600030fce5e2eb72f620aeae2c33211c5f3210c39378060fdab7012ad21c38a066c20ef992b6fd426f62f09069bdc5110b9f450bfe1decd6c732d6d209e778a68c7ff91c444677090f7cb815b5756e856b91e65c3bb7452544fbe8188c38ec8584863e334adf99290975213881a620cbd1db4224b5017d08ef41a2ac279d759f4eee8c30ead128ecf619a0cc664a9ba1f902dbd5a01241994a6693cd316c25bf070eb7beb21e6a9e5ab4426065897480a0528304959266f11ee16302771446fad85f8a0ce129091e54096bf22fe536c1fb7a954d9dd33c3c5dc6c7d29a92748529a52eb1a8d41a2d508fb85faf6610b1c5ad58e0a5a5f16bb7ce263ec703385cf713f7170c94935141f7dececabd027909474348890386792a0c0c8bae3cd630aedce8038a60a54011741e9523b5b46a1e26ca9aab8a1f9e926474d1fc827b4cd3b63b24ec2d14046aff51b73f8f84c551a42693f58c9045c5673ce557ff6a279e83686dd6026b152533e594de03ca3d471da918490b63f3a78346689a4ab62198d0d37dd6512382c662c451b168bc05c446cde246595baee46173953c441255f2680ff1c7ec9014e6e5a148c1456e4f2a2d23864617491343e210f9044737612167b51c70923eaf592b957223f0594a7f315116912363dd9f4731ec83ba02316a170de86333d2801746e5034929e23c83ab70878633d768200cff94a39e2569263ae15e9d44aa237a0cceec1e3fd2d5164db4801442392d7298b03a1ffaf9c7dbe11b18afbe244c8ec490c48850dcf0d178d0037325683bb9beaa40d6a5a0d91fea23355187ff3563a3861f2b23c98f11b53c04791420959250da6a82db31c0fb4ba046f9c7bcfe2d2eb8716c6a65bdf731f5a42745d50e26d275dc41744142f44042ec0db4ce54d9c8c9c942d4e43bd0c1a0a5efd427d28c09f144ec20a80e4829b5b01116df245447e24bd06701bffdf5da60cc553846e86651f879013a94244fafcd966156f01aba33db28630f261261e80c704b1a5b549b86aac4a14944e27102494a3d81dfd6ebdc7bd465df8e59823558d28da55629321a081c0df095ad7d0a24622ad0101e037665ec5b02e4eb49855aa46b8691f9343e98a13f86642334929aa383dc4249fff7fccfa3f3f9785aea2b50926b6c2732f1e127b2a90acce3ab71988d72f0d7b6679430ab0b98c2a8be1a95133abb9531ce3f26bcb5d57a51b1a22751142bfffd1c5da3845f070d203c7f5949e5510ad82148fa9d3f2694e6b2dcd5b47340c0953833857602dc37f1a12594e181cdf665efa1451f9bcec6a2766eecf19ebbd56db992d21488f82f812e4a399661864622b944bbdeb331511c19847dd3486f0f0644cc776e0fe623e2bd547f4522c76c8b0d1df99bda2d0728d7676562986bcd2628317d609ebae444ba4bd934920ed5760272121db4590ace02e51e62d6b7beb9a5211b56905a67915a3f29b6939ee797895a0e4eb33abeb5c2add2d0a327ab2f178772854cff583d8a52d5fa47524e571ab3480b91ddc117b6cc81acf7296a5703994ebdbf7ffd1d8e227773d883df3dbb093f87c9107285a0e0e1ebc72e2e81382008473026661e2996ff221834a2220bb75a4ba9a2336ed4e9a9804c509de574053be22ced90dc1f0131501414a342620eff949c1f5690cb759aa1cc07901b8fb4b6d54470419c5b2d7857980b8216798bcbd4943a30d2157ac15f4603cc2af3891ed24cdefb96d75597bec1d1f531a56d0d81a44a430594aab61cefda852bd6747612a5b7285bff0866cc62efd1c82e6d67e2cfa5630a8bb3d2d0796ffc354a715eade37b5c6a6e9b1381f7fe490395512bcf7660b8cf37ce9aa1631e5d3db7f67da0f35717842320a06e045421de4cece0841ec316f17e627b366814b2fead0eaf0a7156d0b8e3812ece9404d5e02d182b68b9ef0149484587fab80a3bd35424769396659f7d4c81b9cb7df441781510bc0eada802ae0386341d3425e1ec90159a98269542d4231a349df263148f9c30aa0e1105265980e34f8b91fe09658477ac7ebfe8693e4e8e9b4cd6c10226b59b834d988b85820e7dea5da523c98b464fe5d00ca9e6539a9768d5f67f49aa323759d06f48332eae322f3b1003d6f27e329452a82898d95fe225441cec8514a5046827f2526bdc46b416f50a127f9eb421c34e39dd2b887a0c3ca3198ea9f3000be2ee54e87427ca386e3d48f5e681e36ecc3b22cef6982626e428930f82e6a390feabc7a951168079f67b39256bd05cbd6c22a537368721205fb90bcd4beeca12aae60574d779fc7fa74bd075c99355dbead6bba6826eaa3246f3344738435bc45921ea07d8c1cde984dbdc650aae6e7dd8f59166f0517b79b053b90ca0b44a99a4b9cfce15faa3a28247e78e79d28bdca6b9b69ef239aa0cc6fe5957bbc8ad4a3d7c9a452f4bf86ba9f8e65f44d464a18207846a1caa0b2d91b1bba8e0fc3d2c10af62b1a1d7a190499d3039b0e4d09b8851b5c022e712f65e5772b351577c14f08f9dacaa954711b216bab8f05b28220e5a6fbaefefaf7485c188d5cb14547596b82819a4abdb7f6ff49981ca4f6ae06d548f03b14ff88945611951e127fc83e5018205ea3e2c0965342cdc927f51f4fd0c785252a791f80590812c209245d989a983fcdef12f68a8a20b59b6111c4b814035d15749252e607bcf597636b8cbb5e0b35976e7ea567a6b3a4bd80d8a610e78b087064f40cd433d6f0ff4b401c15f54a8c5ba8a859dec5a8cde69e38fd168d14d36907b13f35afca4d1014524318a10bb4b74facbc35fbf0585024599bf47a2f2866740596f5cf5ad7d36ab28dc5599306f0bf2376faf2025783703594d696048775592896c8b87654cf2b17ff6e42023b53cae5b8f540eee857d7ce676b572accaa1ee41207ffd70558baba50e08ca140cc99f686475c472749218bca7df0ac7d2778a5fcf887c13f4f89c16b130e4764b21edd5b3dfbbe6769e6d0dc1dead10387b2d4b4f43c7b9546e29fc0aedcacf6ee6cd5e31a9feb2a336fc717dd02160b65a1343eb39b313ae406e7be3e152fab97a4fa2c660967940be10c2c7c48c349ba0b40f8d9fa0d426f50a03c304061a9009e547580ebe2822e000d8f9f5d7806b48eaaf410da06a40768ff0202d6b4031e1079567c14ee0e5b301b4c09b74a1dd6e588b05ca0102c9e4d6615e3983ca7d938160ac6143b944c532580785b7db12396bf22ec651fd7b30151cf6c2282de14a82d718c81a53becbefc44fa243aebcbb6e8e45e6d98cca3d9b187eeb8c57367dd9d04608e1b7b9541ce762b6c4df7429a317feeb8359aad60ac80d89e3e107b9a09d1536dadc9fb5423c3377e1ade04397aba0d8018ecd2371ae4b06b99245e040fe188a4eaf8f76e89c5b3fd44acf72aa7ab3f0160802602d93c6631b30f30cf05c84ae9a22737fcb583cc6c65af5d2f73315d70cc94a11b1cd1c7d6223589bd90fd2f6ca9cf4d3561b72e7c9bc7befa15ac7b4e10d40408a58fc4d47c9458128ae9924b031543b0306ca5b0af54b091fd0d15c410607da60d85c62ac31c6e31de3b6c95a8fa6aa4bff00e800c8689537c742a53a6ef225005eb08e5cd6e5a2b2d581641524c10b40b73929f758651a54de80db3ae756ce26dd6687c4bb6197a1ec3ff1e29c36edf7033487daf96a8fe97eb39dec1fc674f57d82d96b5d5805e854603eaff8cb94b51a9858e57533a1c36f803e9b8db733d4f76e36460e04c7fbaa786a4f1b6660472130dfd2070c3081cb27629e641165cab5b4cdb2e627ee779200123e4fc39e761d2c556be65514dd447c628ffc357152f6a2b75ce92d92f091cf005883d4b18e5664580274f77637bb78afdb484c1c2b0a365d3082a742c4dc05dc28a64c8d24c50d2e1d0fc280a025f28f2ef5ee5fc1c81fc9206ff76be1b745e495a69162695c5677a917c0c67ea56e088dca3cdf54ca05fee43b5287b9e21e421686b40d798096effc4a0862147089932bfab9438dc3236f617a6aabdc5341e6d2215a38dfaff8d5670312b249c3fe417b2d05f5431699044ff435a7a92b9a04e157da3b3fba5bc78e997edc0a5f4aadfa94fa955a0044905e1c74df96c85e2f243166da577089770b50862dc8fc24262ce9c064bb7971c94158876cafccfe54246eafb7443d2025022a690596c45b55a338d390882e4b1d41df48e829961dab7f9236496fa6b939baefdb652f63b823b07eeaff4cce445a74239fbe53645e2abbeb62ce54cf2eea174f27b914cd4830f88488a64af46879886e68528875086cea00e486cb7268928dc4a883bc6423447b8a4d442857518cd457249e203550c9e6ebd46d270b2b37a6fe27aecd34ddd4059a40e4639b7677ce5d467684b66b7088c5a19642d43a7241ea4ad35b8398cb88a9c844b1d506c307528611270805382b1f0581cd4b22d406ff65a0c0b71cab73a38ce2572a93b41cbd44db6a434998980f5016cb44be8c1659d17bdcded9ecb34b0c6cc2918115df7837d924a262d86f5507001c844b0fc9b95439e00493f8f3e4221e3f513434248f5840e278768a9df7f20af6015236ee093cdc8ca69e2c601965217b59a1caffb15abb76d1d2c2c6bf84cf5b5a9cb1831e939b609d609ea62750ad51f7e7e985a851f6fc7ed1096700ca1bbe385578513e057f87d22dd4e5f0286893553f341176d95995f11a08aff0e97d739d04e99bbee06d634360039b3546a7405dae8c9351c9dfc84a0592eca7f588a375bc9ea197602ee83e19c488453de741c16eb710476310f99169c58bd98d8c0b3ccab42571b1f065d57e34961ea06f03bea2b23298112176ee68c11e461fb9b4a9746e8c90e74d9b2623eab7832ef8c92219f77255e8635df59afbc3cdba83583d62f84c20593bb12eb1ff58e6e7d69a4ae41ae762d3de708cd418714a4949a84d33fe75ffb383d7cfe7fd5730c1fa321f53848f56858a88b69476d0eb64199428e0097148fe1d0913ae1c3e462e2c83583b618c462e7f4ae5baf797e1323aa0c86ccea5284a0efc6db277180242e54a7d1c5fab663c6b597edf1809eef906897a9679f2b73e70233690b9e5162802b90e712320df24f12a57c27f94965058dd7cb2f065bf8e18d1b69a2e67a59a4fe0cac0c8b0887d634704e220cba54ffbf18987ed384b4b290f6f8e4e26bc069bdb45a6c0abbaa934b5d9aafb34eeb63b94d084d3e679080fa80c782fb05f6c255c73130c8d8d42690c72aa91f97d22e8fe389587bf50b64bd059ebb86ee904686bd26829b2f65902ae254b9786a26f9727d8845bcd475a84db20edc9004eb3735eb0c844e4b8580bd37f0e83ea0acb33a833105e70ed72cb019f642dde84a36dc19bdc0468114a52e5749a7d6878ac80c444d949fd506c62d7634068029301ca621b15406332365b045d1b439296d522beb16faf03289aec4f47899650be2419da7820d91fd9db8075ce722f3e40d494df3828202c811ec5727a22a98b35b1e3cebe27a18b8def35c92e7ab6ce0e01922ba9ed8540fd00936b0c20afb371aeb3f676c56bf0a1145175640b61789caa5fe42fe31ff8d3cc6d5260ccd2f869cecd45827252d72a76ace3b9834f169f9607c30cbf70b0b607e7f5d2bd45ddb84e8da57f1338a2aec63691b1b537733432b3022cbfd55888551ee5531f1e3f566096c67ffd5865bf455a87b084eaa305acf291ea2bd008466aae41a6f1654c3ca64a58f6b016d27aa006543eb869985f82d652bf074dfdf2991086e7aad0f65a57f88792b58995db74f7cadd50e632b1266e97a72baa7ddab453f8599504798279025b5c5797d639049ecf5b174a526b91c28d17ff08ae4a5b426e2176027581b3098e8938d911e69f22adfd1a47bc515633232f4c5f8ea8b4c995133d500029a8bafdda62d03ff75937cf856bd60f3bcc35ceba38f34a934d41f28db30b185049a2b8754958d9b360cb8c303c3f461141cc6d27aac58b8f62a42666d071b2acce0024484f21014ebf4ed2f13ed12db5da4f11080fdb217318bd425db4b5baeff8b48a409849e0fa92364e716b706a2a5fd86fcf605602f3808e8eeaa2dd437be3631c2cbc822a4578e8664ff7d74269d14ec682c3bc31ad761aa3483b3a9f1b6b880e8f52cd3835fa6db463925442d46c347c4d94e82b9e620e4f41dfbbea8be19b2570e3a40f66966e42927544f033a51d7ea82845735d3f4b33f5c7954ce6d1272a4d0070117e164119a39feaaf6b4b0563b5101b098298139f5c6f7fd03f9547e320dbf9930d8f3bef469cdf68ff303560a3a8d7beefdbee87ff2152e62807cac116bf22a944b6e05f815c53ad9e43fe695e37a38e1cc83771e53c00b484dc668fb80390f1fa2a30030d521bd8e0850ecfbefeea3baf459bf0d2426ba2e1d1c3ded8a8815346526cb9962b646792a6a629ccf4647e52926d1241184cada5af79bea864068ae5e482719fe6452ea6361385cc926d941e547324731cf27cd605aa7e94cfe6c1a9504a6ca0e7f320bec8d39adb6dbcd294872957840d793f611170e36e095307b51396e514593fb51f54224fafb2d6e0328b271113dddbd01f6d7869edbbbcdd72185fb49d5d65247c9788ea1d474a3a58f8904ee0ab428f9fa07f9d5b9f6d5e989fa6e48b725f3ccc06694e44655b1a8903d1e31ddf25cdab6226d6ef061058180ef3dc8d38e059802170a7c85b813bd646b230e3ef46d725938c11e48d76d33813ce89460414794f7cf7eb991bed7db9decaa87ef370dc6d070fa62a5e82e061719a7d194d8139729ef1a3d661517d8b168fabf9a1d46e57bcf178f6ecf6c01837e9f0d2cf3ec4380cfd756edc480e6e16f71f790211741eae5175afc033718bc8daf01804a1c148f5f893c4f170e715e088bf4050fb91ed6157de90ba720f7b7a3da386eb388b2994117ca4d70e2a7d2154e9ea43abbc9154903d31193f843a98f7f5666df28364540061600fd184a0e5bb74f02febb225c77a9fc2deefb98b64b4fe12e37d737b9bf275ec91217a7ab26cc8210b2cb9c6012425468d286111acd726594a5634bd4d333acd1549b3f0de2bf485923c4db4376ccdda8bae535c32707885f9e0f9b6f25701cfe9e9b0b148b7e34e95a4f845cc7c9b50911db6448347c86aad61aac8d57a776a79eb2a444cd2b42b741677cb14c24cb32da218e6af3979c050ba3d34ac5a72c7e6e4d4ade17751fe089baee70670343e5a3446f5c3ca7419dc3ecc069581208c8bd42bbac6111e173364343c510f42164647b3e300a9c69727388c2adac7339d1308a66df31b233e567c4aea25c308e82fe69b145d6f8015182358fb7b0cdbcf09910ddfc42b273e649f3723a1105fb8e481c2388a400e041e83485bbefdf109c48135e3b84a31c24ebd090ba89a2790d2b9f12870dfac0f59e4e45b95a44d38b5239f8d8185955290d21dfe96d5df36db6179664f87815aac3d668005adb957e7fb66e3aba10552d106f820bd83ce34ac19b34ffda0b19bea54711c0b5f578968f512c317628a10359c3b3fda9616b5421debf951be9c9ff3e28d1a451a21aae1f7c68494df7b4f04fcac9845d6c4b957794cb9b415d076d682ae448511e24827dcd18a9c7a2f48a5494491bb684972dd5d5ec02c2eac11a85e93b9df36f9c5e6c16a66a5625bc937465c8ae93c732c0a5170802377f983c0bdf7beeba636147f1a805467c1f92d7d14eb0cfc4a2b4d2cf893ca6803a6ffbb76dabb82b3b7f646a88cc984393e560afbe6bd65f59bd25ca332268c0022428d3bdb7065c19c149c05294d2e239bd45bba1246e3aec4144d995896c74b43fd4eacec29007d5547427274ecb56b1f186cf9871c8ceac3023036d4d72842fbee243d382b40743ea2cff57832af7ee730b5f63e35cf3cf537e781366e11e0a3baacf3d8b06762b918d5cdb1a48efa5271ebbec8825a39afc7f4a034c1da2208f38fc62696599a9f7bdab06dc531182394e7051ea04d8f77b3c753e3a0fc6165ddc6be685b9264e8e02a1132ce3d976466ca6980074e8cc3c814b9cf1fac00c80e7f71abf06ea7d63dd318d28089112393dbd10a1d7ea64e40050782575fac85a7333549c43a2db9c29c71393ecd662eafa2e47f71c8d7ceb89e7c18714eb816be45935280ae301e543895e19e62fc03994647720e35fa9ecebaeece016642b72b43fbeb38f0a8b2628b71533f5dbc7c70bcb6d8a1c1d806f2dca42a85652c175ff568246fcfaf99dd04ced17ece2158094f055a773e1033a899069c8616fa72fbb8acc9214e97c0cde0b06467f693570c47f84274f0d0be92864ab5d30630be7c43987c62e1a17cbf0f6cec766c25d430e3e016f9c7ec492742c7be79a8ac99ac6eaf189e6e2f9a39b9f62984f5b0a67d104de2dadb643cf4942af37dd2e6f629a5ea09b47f02f8601db9c87b97ed9659bfafa3087f0725ca25decaa94640dbd4c5085741a74508f7f84c6d15e5845724c28541034a4c5f657be16ed87515b132ebe281d9225850e6af947e870dc5e8d4c5e567a4fc9f0d4c4a3ca6f2c96f94d88512bc1628e170df2d19a07c3e30445dc1d284e34e6b53ba5bcf38232d7210270cc8f21aed202ef5d68cfd41806ff1f9b41a131da4ca3570247ae073aef6836e47a00f7ef0c50389a9a9b7042d9397973a739db2fa5359128c7ad24eef1d3fd1fec3dbd9c34ccff287fcc5bae13142c3d0f58372a01a356611480381a11b2710075ad193d20c96edbb17041cb3c196b6efa10565a81bf64a120e3443071c6e6334ec6bc1c84ba6f5c6baa9fe9f4665aa6312d04c4aa6371a90cef87c3561383f87bf434505256ead36d6f972121d97b8c2b27b1d25e457a0bfed709b13d58123944b2db22636d6c8718d1a1bc24be3b5f2eae7797cb11cb1cf2ae591dac1f21f38c3ce0d418dafafb471bc71a15dac231fe782ebc1c09a7efb4032f87066a8810fe619d1756a8c1e97a319db1f6c83353930fcb018c70598d4848d3d427f23927395db000a7c1f3364bf29379939e261b2d414df4b060378bc4a4a34521352b6af6170dd1b2d6dec74015d8e58454ec35f8e915566ed256436fc6c7e9d90479b80498d21e8153b946da59f7bba6061bc9306206690c59ec39460645aa30964eb8aa951910b13d3d892de0063d5d6fb5ce09d9fe5c03df68937983fa79cc631441ffcfb62204c3282eaa1b034bdc56ec06352d073ef984bc2bb5d17e8cd4356a3271b637f3647e5bdcdde0a674e9d15f10c87282ae8148da6206f462a56f6ef27e6dd7051f6240f3c794f63b5408a63559e72f23a4594e917fff3280d419284002da9f9354be3f35dfb16e3b2f9afc5174e415b0ef479ee1dd264d394b88ed9f983c20e72ae94e3ac3bca7c2384e2eb503b66cb0710f58eca44d6d86c1d1505c9a4f3deb94cb1ade582f062ba79708fadef8911ccaabedb8738d51d6cc08f5aff227c58775b498f80f50dbc635e25800245b0c4ca0be47a31cd93e910595a6e5bf46222ad2aa41ff549b3c45b3d3ae9e713c68398505c331aa4ce6fda3f88be4151671b3ebd5937dcf2afa253a24e3840c65f89ab315b4ac66943ac17b86858f2501b649724afd902e68bc5f6395e6ca61d98b303f20bf61995ed61ae339eb3ad8a6dc9f8feddd10a04b7ded1306a7d4152addedf8c561be94203d1e985d908e4331eb6ce94754a25cdc3a9cd606fa82a44e38aa591e7303dbeea20560af051ae222d4318697e31697d56577a680849dcbc16d9948a85359b7c949bb9f6cd9f3045547f0b5651b9a2c79822d131bc99454058da8ed5d1d34c49a88159f273a28529ecc351ca19a82a8ffa3a023426f3b60520db70340191d4261c7af26bbbeea62c29443ac0784749a282eb776a349153c24079326d2dd3aafbeb46c21c35b39a6ae6abe6d7c029f75b4ba641634a02518433747c46a89db4abf46391481769118d9ef50e51a8602b7d17da2b2396cdd6ccd2ece4ebfbc7bd50cd20e6079b9b5749d91d25145aa7f7cf3a456785eecf608b09bf4990355115fe020cd5245934bf2dbeb90a0ff32154c9e0548a4d206097ddbb6137700c15496c23b896c6e0ecde9392e2f4d5bd10ab857a7b98fd15e17d6039c62a160691d3ceb84fdc71f88382502f025cd69dd5ee2b23676af6c86d3691f597bd40f56562502b2477c4d2e07ea332d1a23be58f543a0192f529fb8a1112efc20378023be904aea2447f2c351b14c334a2c8c5601ff392bb0fcfe220412793c3e9cd66a5f714ac32dac4f24a7edfb9100424eda96a9840959baeac8615fded3b92d66d75115b713df83847d4f3c1ec87cd400e3ec6800d62855a5c2e1e630e782ec825b8309168baeae3a6ff1c99e002414c49b2ebde44b0f3c08409636f620736586a59cce22406031f906599d83743a2ac6e16e59ea5ff69d666b93df4be8cc068b7d7456aa6d43c8723a0a6b2180035392cc9b54c3988f060ffd00c2239ee33e84f6d1eb416b14c71600432610928653db01477c04bdee575cc23296aa465ee34bf1d10a300a74b93dbdc18631161e0260746cde0c336a2be4d38426fb9b1e06ac2cb1053bb15f8f3e2b16bc16fc55de0d5afeb8d52bcfbdd96c4ca4908b4bb03054ea4cd032e56be865a07f3e9dbd5caffe44b9d05cebd354bfaa1b3c26d5e8506be10a703d733bc27e0e08f2c1dea97dfda0d52f116757ee255fb51f7dcd3b0e65cf034b809ab4b938716d4db7feba561852bd98504f64e3b4464605e8a2079052692b585db917fc89c16eedc418b5b7897c78aebd0c2b44aed9a339d77697bebae574fa1398a9b94315e844a1d2ea8dc8027a9bd5860386959bb29564472fffa9def661c190c128d08c6fe475d2f4b4eb8a8dfe0cb8146c727a186a21225069d972666363368c5efda675d780fee39dbaddc9a029b0581fd5e7623bef23b8a27a4870f8cc1836819c3091a8f4635bea9c1571bd58b2883a9014785bb24142459a6e1d5b55741d5b57e3d2f361a1ca4a91679081ef797bfe0be769bd07f887c23a42603fda01a3784676f89f31b425c9958203539ea07ffd161b71192bc2f09557ee10f2c2f722c8ba7577bf21998e91e3bd17a440805dfa0a8f2de2a16c2ad875af2953de1700ce4e16d58b0e5cf5553ed1011a6f578d9c6366d2c7805bb0d61d26ff196cf4a44e400439c21a8bf8adda4c7b3d18f6773baca23d1d97e04449f58daddbbc79b569383b4eec175fd87ad2b438ad4930f687c4394c218f92011aeb590e9c8912904b764674b75471bfcacb974672aa0ad11cd75860b8f6ed010b03f992d593a87100640a2c6b5fa172a033008e54c0a012d1b3aa0bf9c855e9134b74cc546f11de413c0cc8e6d8d9b13ece8a71acab9a11d8dbd100e01fdf2e39a7dd4048884f8921be88a92a314d8778289ce9b6c46ddc226138084f5c21a20c48ebad3c31e1379b3462d6c8230f03e9aee17029c63fea17e1e509a1c606ddb0b843b183d7e9604b796f748d0171071d616fb20badf059fb903f594fed7307778ec63a4b5c601d19b115c30252e16b1c08e3b8fa605a12f3108de9a26c85260e5b0144bef642a3431105ea5d18dd20d3a3be08b21e4bca5eeb4e2f908249e4d24e9309c220a9244da728ab081ff68e44d44863cce4226cadff159c9e54d6b338a4bd0d1831d66ec292314bb96e233d7834fa3efcf1f4cbd0c8a0a43405e9c0cae27f57f210692f0f3e87e0bb1bd3996808cc931031a5be6633b96ebb51b8102df0b2da28e1c0baa6828222f4c484c0219783f0c6922a126c5cc455321737b42b67eb5eaaa733036d31efb2d1931285bc0adafa7edd0e06052424f33052a1a812a4d5206c648b0e58fdfa6c31f9cdac4306d80bd9a7f4a9b8aa73f14850479d2c2e52c9f43840491956211a56866013c1961fa5898713ed76abc767a2715fc5ec5ba4f6a2f395afd0cf5f4b04ccc7eed332043210cf58e23eee73b981fe72b35d6f97f99e7c9001b59c28140164365d5718e685d23e83970d10741ad9d0e11e056545e896155f5c4bf7f7a7d0b68dea2bddc86afe3504f9965f816b0029806abb02070e69877b2b2cbf4353cf79a52e2f7c89af6861badb940aea8ac5f926ad8b574f84b6289cc353655b94f31970fd886ab333f7505053293f2dce8be25e86e31013bd8fca40486db42a2ea28d49a963f44faf7e3f5d042789709d00048dfb300a02bcd109d782df369e5c23def633c8f32af03d21e39dd40bfa0f8a7bec52d1ff7346f0c3f0a8ac60100e49978c362db52e2017a05feac0dcb169e1565582f106394e321effd87ad7956803b4dc3e09348b099dfa4b3e7f7ac0bc5a4650b764bcc5e9bb0cd57eaa1fa632846365d50e2bb6c7a7a4d95653b3d09549479c12ee3a75abd4bcabab74ee83b87641b747087c18d25276e08fc4deee9069d916431f39e661374e66064ee0beaafcefab35db6c38082421e3aa781f6639b6ee823e77a983006212b47f8dbfc66b8d83686a3372bb73dcc3fc1f34b66520a397ac97d5c13e0fb756b1fd8771484a62958e119a66fb471fd7dde2514353065a2826bcbf33a93193db1230cd860a1cb47f80d110c7438afe25c563865e9bfadb9f7f3d5ff2c1b128f4fe8e86056dba2302a4c7856f651a1cc79fc65f8604b69f4f12331c78f310748daa520804a711995d3faeb0606c6c1e12e3b9de424e095b18829359cc5215c57af356ffc888649926a6bb66d51c03a9c85a1883bb6a85e35338d4149476051d912309a4bb172fc06bc2e5d21e2113d7a65add1fa54e02d9a7186686ef956df917190585cdc81af11170558483c1a17c62f7995cc149e1a9abde09276119d2902fceff2ba9db11e024d3e04a306835fbcd9cdb35f40cbc79602668f1c51086bfd7f76cd3c0890a027081fc7f4f625d55abf8dd56652d628f15dbebb3c0637823117996896db7d51cdb252d547522f6d3dc9cfa2063a318593dcaacbee3a640487f2b5bd74d1cd7ea822b444f41357d997d6ea5c49a4433b4b6f5ba3e01fa4f79a94d5d5871dc922daf65003d3706b2ac2661d18058a2734029bf1db5d8384415be439f7d4f81089a36c65b2102893eeb3047aa5c4459b363a6720bbafc68204a0557c1928c67462ef5c093e32a8731bed3fa007b8f9a45608d2c01ccc383f229f49992c4121f8ac30a5816770636f3c9f31c4d882657cea21b35b749219635c9708a075cb4e42909116e1722c15dec7e83608e1437cc41928e98bc9ee8540a3f3a1e07e500ac680d38983a898ac0e86ecd109302a10d998707263252572f5ff2280be10604e6eccd363ab0d3e2b941a1d6fd0ee2c0c34cb272780308c9194d950502f6cb2aae7fe8f770f61413c20eadf86f11d22c7aa66d18d50b82810e33f050f41c1aecdf5e45d4d17f50628af36a687a21ea86fdd168089596d1f4d5ca0b3fee3117c120b231071317c32b49a0b287bc88f60607d28c8363255cef64feb1738ee7967296150d574009406f6ac79743bab4387dc3a8054bcc0635cfc30ed486282563ce68389b32ebc36940f4ee68bde3c77e1e4abc2e5b928aa0535d17a78c57483ed6d6d7a9887306074aceb0348ef8fda39b3500aa1726fd78462c7797aac8912ea14c017d68391b58f4491ca0c6a5c99d268f9ecf2960042af4a32ad76b3d372188fb57f9708744600f799efceab5cb0fd17ba93c20042489c33c8365f543789523baf1343e2c21ee870099da0701a221eb245a40f9020e4fcec5a89c1cb108a80f9a78b0d4964fd65c96bf1dbb10a92c70cf08b300df19ef969a9c74116bfb65218504d35c649daae28e3b4c1bbfda0b00202c87d789cabd9aa5493ce54a25e60e9c5443d09223a82e355f722137a84970efb6011b69b90d8cbc01c28ec42244bcf8d3d453b98ec102d82217faea1c86d32cfe72fdc5fc4c232445f443f3ba79b6dac3af8c304bab5d63de46c34c114cec0df7d77304a9aecf9637e0993448cf5efa93f6ff008304407b38498cf81cee6a5a37e061f7fc0b1a5fbc10a207aef8b98d60c757dd75e0b3b3f93f3786c2a4d6099459d096e7122d1c5da7f1875c455d54de103611c738d6c82cd572ae62d8aa673d32f017969ff401b91b00b6b9f1be25ed18a61cd00624a656096874328189ca3c62d9c5a8212032fd6898d1555a8e7c33b25acbad3e368c8cf674a25fe48b9a2b50a4d45488fb50a4bf3a76c02b94399fd043936aacef95573896d36cc8595d0a3fb8174de87a4b299014c683d20eeedf3991b6386ea15f27cead6d4453d801e8e1407cbafee0ca560303cc2fc0ef41e3a5c8cd585fb8b7b8487c3a89c476ffeff9b3f7dbd15d7990780b7d6867df9be91ac25149ebec9d911ef0a8086faabab8391705bf2953939e81a04e895d37d945721ecd29b7b11363f4ea7aac9f36ca8af2b5f1051739c35d5ccfa5efac6c615b54bbe937b53d879b4551ddaf312e40c909ac0aa9d9c968cf88f392be34cdefc320bab3afe060560d5cf3f3378171cd909bda105e52be127ecdcea5b5ae0230cbba97704467890503b703fffe3eff356456c2738aeac5b753d7e63a4e001ad9779b81c313fe234dba68f94134beccd0a9b78c8bd5600e0e7626dcf371e77c77c93a5514004bf4c08b1c762f5e5866705e18e9ce108558b84cd96e0da85f9481f0ccb279f13f8e0b02de4c600fb8f99b66892566f21c682905a42c9d130486362687a9179be05a8343c37eef84044db1107eeb5aaf62a3f2c58df1f0421b57af5426711169863ca77e05e9582fa7c202a5177c177d4f409fec316946b7ef106ca255ff3342dac740741383edb7eaf75a59b6f9318d4e22e020ad0f7f4b94161651e5d7102511412b4f647fd60c4c8e97958c55664b9df7cf86cfd59a3002a79ec9e6fa97e27f048714fdc3e658688201848b328b4ac2b10bde733b48b7f7a395259cf6aa1cfc408dad0268ca7fa0c5023443f83dcd305b50e551d6a737ae458821b53f173999b238eee54baa2cc6b9cb91f1a2c0a35ea2268870c8d62f721051cb2a837924b97a29e0ee6abcfd140ba0d95cf8f7deeb8085014234b75328763944343fe989b02405670d560846cc85fc852086df7106eb2f43f9cd279212a66fa6cc805890bc412c0e573445fd7c75034de9cae828b2e1a94682b7ae8022732bdf6f73a69366d3d007a41a0e2e60602fb4f649c1fcadf6f11a471daa1baf6799cf7fd78c5b51397d9d64bd74c904bbf47c1516c0fb3a3e05a9039aeea810da03156fcf32ecc43f572b5d9406458efae44501b64847e40a025b50dcc3314ba234d0564cab01cf30c751babaa3b438f33112f6be240ae631e231c4b5bc799ee8b09af91ae8e9b08d3b4d7f892bddc7f3ab4db10e9e963c97a18dcb9a6b18125123b48457a13b77d1e80e6f16c5f6d5e32a7c78e4b69c75926eed7ad314d5643ef7ec385d0604adeaab007c438d7dff1d0e1bd660c6debad995e6d630c0c890055cdd5c0d847fe33cecbb0dae3b14838bcf20fccfd431db33929e80fe0217ed066780dc9d2e48974c1fc0dfbd0f74a4a52346e38a3ecfc6c9113e2800bc03c310cdba61c908690a22fd0b251933e413f8e1982dd014312780f62b37859e440eff65924f0eb5e3c1db078a96f9ebf51937cd29c34621957f165f17bfb1f3e59fadeffc1af58e2187d1fb3af04d99c74a9533ad7e8df67a5b06622667cc264b547efca84e1b9b1be2c9a3a76ca6acd0e93818155c5f167e2b6dfd06afc8692897f7609002c32ed26b58f30f6b418312c07f65a82f5cbcaa9fae8583182d16b9aabd61ee326de906abdd132c270fea86349eba9375335d3238031fc4605bd53fd7df2a14b4e84e34c6e3bd56aa7c18041dcb8f712abab866cd5727b9021f88d6a7aabcaa0ca8f4c16ddeb2a9f37567fb12871ba245aa04548a3831623d01b2d3b0ce68fba97b49e7233556b1a5a18d1de85cd96fe7a2a8db6072e101be11fc7b8cac8320b77503edd987e2c8365c64526dc0c7ea3263e3acb94228341a7fa85b38df7fb500a6b5644c64ecdad3e9685b2aa399b82f9604073d8b5d000b2d3b055759ed658beb4d9b6fb0d31d83b875d091b609f21067be7a869e103ec37c460af1c352d6c80fd861aef9d83ae8506a0cf50a3bd73d8794be50808416dde07caa1ef95eaab030fc2fbf31bd5ce67f68760214919122c35f9e63d9bf107b2d427557e5d60a451e63d6ced70329a5e6e3404179c7799b7e8a0df952170bcdc45c85ac037e587e64bcca2b6546957cc63fb308dd26b81dae1d2fc72b1fd955828adc059b927b35e9da67b423f065f55b3e477f70430372189752cb28759814ce71588d397202d4e8e9b13c18ea5e5988cf36099e62ca60f3d78ddc44a0c8919931eaebd66bc616fae4f032a882319be496a7481c869b3e13bac5a63c390da373154a5d758734d88a41604d0d9f6dfb01b77649eeae55971a4a84368bf3e1ee393e4c25d44df71fbbc296320f42668326cd385d683510df477eaee9ae82ebe0f909cdcd660188ce0aa9f2c12c8138e3f0132f0bc8b4b38b02354aa48138cc1e380c49ec8ed834394d239d506a748821f36df6fbfbc312e9df25ce45c99bd02a9e358d8a306c2150cd11bb53136f24f92ce07a4694816c812c0dd09d41b3af2c226f0f129ed9646cc8f080b45a322d824a3892e9498d19049b80910ce96780fd4b068d15c08aa14aa9cfd9c117599836adf6c61fb4fcec0e6df3a912d513547941e2dd85508c21b2d250e0f922586f78649804fd84c2ebbb96d217378d751aee156132be01616341828e4389998261050fb83dc6ce5690acafd72922ead594d87001828694da02c8ce0f96c6a048197896e5bcdcbca536324a412c3ed609d46d5e60d1825d123b7bd3487a95f33e50b8592d42bf8f2c77a9896486e445c9a842ac5f708204a88e485526fac1c1552ccc96c397170fb3afb2f2546fd5d380d6fbc6f6483c92ac7014c02c5eae4aedfe71cc76bc8f93da25bcfe7c6e6f3209873bd8a008021908d2d7b58e143907164c85d89eadc80db7eb68778c32ef195ead796575976aa829ff818f3c581d1bbeca8a5c8df41a46ccbf09480bdf3cbea84e0bdfdf71e81b16072a38fb09ecaa8902937d65cda81bfdee8846e587cff9d8d35359ad3401852c105b18344b9936e0c870517fec632a03ebe28c39c7d9f36349b0ac21d9ec48f7bc8a593f86a08abf30f94a486fe54dfffafc25415233d5a23acc7b5568a3a6614d8bf3e002072c9120acb7707203aff80b6252872daaa2f828b327c81149d494c4a03fe8e6e26364c81e47fe766a654088353fa5d45bef63cb45b5d4fa487fcd9f4021fc5a35faff92254ceed26f546da1f1928548110c8185d78f4519e07506fd48c3277111e7809c50de28ba0740ac6078919fd17e8353dd2ebd55f5d1276466df0a9eed075c0ddbb2a4522975a3e095468c0aa4fa12a5f2dbeade073595a957137cb7dc1df68562aba2fbdbbc7a6909184f2772e646e36e41cc2fe2393c08d1d7b175ddf487502f127dda3306725df791ed36f30a3fcfcee4a39f7280e38c666864766be8349d65e3cec1041655987df1fd105873664621e62619c95a14454f52af04bd0c67b1ec475cebbaf748aa0df8e32ddea0af7ca42c6664861276b5248a1604fa7ea8004f75b2729ba63c8b285ec9f9b6fcb91a34b115297e9dc48e7305b010cc4e9497f8d7ae8900da6a65e963876eb25dde6c139077e6a5670819bab61e21b20af02b83c19863349c1579c7a7ea7e296904afff57b04dd6e0209c5b7cc478bece93372df1920093d107b463fd9050deb6fd426f977ad3bb05e4afedf9a4f64f0f48e98abdc84e27bb4026dea06bd4b0792147dfd25013f6f7412ad26d94f48d9be966dd6a0c6f3a7eaec751296b509f48aefbea1f6c14e8e609948f58972a7a12835eb40288047a486e1889350273ecb3c49598ff4b79707b3cda42404ef5d93ad5e16974684dadae5bcd62227162e2503a55b5cc90c8b105c18ce92698dd0118a4da3dfb456e484a8af376b91fbfe2ed49c4befbdc75d8c8412780b48f01f9d04bd18092ad81ec1f696172e70d5cf6a4e8c1f2bd0c23905d3a9248e2b98c27f71f1150242f9e5420fac2cacf627b424f47435faf4008843731446fede05af5f802f9e0b6413c2670cfe74e122cdc62211f89cdfb65473b36546ac07405aac3a2b4e0519ead5676decc2be7a773397af192e9ecc79daa8c41b9079db9bee25d35ae40f62837298bcab4ab3f59378535c01c66828a732dc27c10c7a0416a1b54d1989e006ca14135e90238823100fdf7ca3867356af0ce0e9331e2b4ccc546bfbb26797f4ba47962af288747ecb61c30ade3b19aef3c6aadf0f846fb41619f7279e15c5e2acdf953d3e789f455b3e553c2b80d48b35cbce6295e2a8b76f97f8c1254b70600c323a5ab58b65e1d526470034f58b3dde198cfe02e38e37f9e60b1499bd516af857492a6eada92062aee55fd506f4dde4c660b9ccef4571cd03432e0151abf115bf3123c8ea4e5ed53ffb1ec9696fa309d08bff2ca1423334af5ed1f76a2442cddb2b4af277a1776569ef45f020c1bdf46ffca6882b07176d2a5d2b15d1157e4383279f8372ef3da4a4bfc3127cd176a0d54149e17672789fe5153a0530ce837b642dea1b6ea49a54794c630ecc6c4395e68b2386924907ac5bc2cc3c9db16bead0e931be03d7bd610e4c0e78c250f4e82a7aa8c1a695d3a3a6cd03261342ad9d69d74f1b060590f22b9cae6dec4a4e6c5496017475039a9716895d308e3a5207a5f1ab841e416006137f03789f611899ab8804af4174e7e6bdc0ab755f6ac44f83bc747138744065ff1f94735707875005d077f4b59175a70093ba25ac848651b12b5c47716ff8023f5c04199b2c217b37917b4b29a54c0132083308ac08269c08de74c925fe0007e8fb656ffc86de3bef45b542f84a960ba8ae7313e4a686e949abbd9d874da6707e7355ab288aa2484f4128cd375d72937386cd9a1fee8a496993375d322567b0d7dd195be9ecef54eba4b3adf5ca635fd5f2f4a03af356144a14734a4646a55aad6666683a1a1a9a4b43935332a511ea55e6ba924c53006542d56986cecc9c54a8959869d0a83468501a2b1aac99191a1a1a3458ac9a1a1b9b1a35686868d060b16a6a6c6c5aad9b5651a66439c77c9338382e5775b95caeae238b688046a3a635e79dac1a9b56cb63b069b55a3735705cd4355d35705cd3e5c2c171b97c247374aa8e8e0ed5d1993ae348e6e4e8e8d8b071e3060e1caf170c16926498a3337572723ea8afa3a3c33d06005461dd841eeb83d7db30af623b1e04efeca9e4dda1a2e3db412f0ca92cc7b7b7aae432c43406b395ded9dd9018bfe257fc8a5ff12b425d67517b0cde74c9e515fad7cd976c72b06b4f6a4130c463d357ad18f40524d1182ac7915d25d118cab1db718e393c007e600784123df68fcb63ffb6d01776cf9b9e75fa962c17f01f8ebeb0dbb169746c1a1dc285cea437bc306b31b6a6a79c7a1e5b93ac723d7be7d3e428a29e7da3cecfa80354613d6e39dfe3d62308348514bcf192addfe4721ea25465d7b10f59aab2ceb12300010838d23393938f757ee806366ae377408f9dead81ebb8d9a8d1f7a1a426997d4b163e45592985cae92562b2505740ab89ec92140686a1c925461583cd2b145a66e4374c1db10d117be8124973ab95c9519f50c74ec3a53f4cce4d8758e7472594967f68c3ef621484392aa6cd2f0506695fe4ffc3c763bda7821672d1a09dc909f9ef9631fc08d13b9fc8690c03deeb9692297384b9f4346ce18d1c5b18a53f44bac423c729a4234ea1decd52929fef40ef69351efdc74c9a05d2a6d886ea8e30af52147f30755012fc0d6b31a577cd952d4305384dda95e4b1b22f1a6897c6b2b2c3aa693a32fecd857473deb98ce13fdc25eae90be5c2d79ec2ba09e59b72192c1e2b1cb1cf54cf411e5e2f8b94e8eeef0d8b1eb3cd1b16e3c05ced292da6328b078eca50dd16317c7041cf50e15c5ef86e46337e53cc65e7e468ffd1bc238677c128f401b5228dd349167ad77a6e72c81533cf6326787c79e13d433d1b1fbf065dde1b19723198f7d0ccac125ced263af0b00ea1decb35b2e57495fe3451263478d41d8c12fcc5ae40804f5ccf5b8bf243df6214755461d93270499ff91de3bd883e87890ac925d862d1e82344ec94392c821471768c9d4cbfe72f4d85b0793247416b51618d4e7e3cc39292533a082fbadf8049396beaed31a463d7ba1881e48485fd7c8de246b93501793d88e0401885fb0429539c6999c749222908b4d9838c13eca865c8a40a20d9ca368138172982fda2819d217c674d2f27e594267a1bf42b132f480c64420d1f6d629c94112f9c716b91481deba084463b489edc98dc62819a49f8a184463d8ad8b5668cc73fb038d753ea405f736483ff552dcf22291c845ccbda564d8792982c95ecf091d9e3842a625c0cfc190be3c0f9cb576ad90540026bbb1049e49bda6708d98a8dd026c50a46397458a3c0928500bd4b64ff137187a94cb2602e1a6eacc1ed5074c4bce4095f9b0326c6bd9470f1ae3b95122fbf0014295d9ca833ba02dc0d6c198867e2df53bc286c89d972ec42f760c7499ba754b5f578ad9b7bba6dd42eaad8d5fd9f3d2877b40ebc9764e080e43074f24261bf6d58e5e92ac1eb56480fdfd8d9e7f26b22502759307a1b5f6097ba391c72199c1e4f179fd2c58670826c71ec444620c5ec8932c5f3fbb8ec4e0857cc912ffa4a74a62f042a66469c159659894360a17a4a338558ef2d5d8afd498e9493c799f4e33f47a0abd86b5d2ae14e8dc93d03ebdebf144ed0aed4d5f18bcf0222d7dd9fe1bb9ac4307cf0a7abc7d7ae327a44cf32a83f9a3ffdedbc3c7932ae4d2a914f07390f423256cc2f809b0a58022b30b21dae72647617e035ad3690cd18ad018a2816ef2f94d5fb7c847e85fdf453e2e7c914feebbc807f73bdf452c4cf13c3d9b3c43b60f28e144045fc488e03deec6452c78e95cae4a913379b34a501e40ea5eef4caf5d2b256f13fb705281890e7e56da797a3891400bc403132699b1b575ac514a635db44253da5c72755a21e69c135799a579f644e2d2436d42994f3a05b68e4d01d58576dd08ad56af649116126d898c9427d922626d0aa1129a7523b43ab688d4225d8bd4d88166494b37986e04052248628906563abbda2fbc286144ab630b89e6935216da34621313b576bf3ccfb2fec3a09739042d8db540bdc3dffc51c17c2306f29f801d85fc13dfd057e7df67e70f0ce43f613a0af94dd9278f4a7f923c2f7a1a93abdb49e226b3a01ec69e908ee7bb5cc56422ade5b17905438206251a424dab0042714989b81835f98401682e97a3399acb5122ca85e6a80c749353231aebdc64327d4a97cbb34007eb29841a445f56b4f2d6dfc68a9c7beb1e98b7eedd68cbcbe583b4134f63d43b54bc7d89819e3a14b9923456c0739c596cb5a79ece04cfbb77b0d7530f366271d3ae5be56cbb77f0cf39bdf6a9da1c94a8a2a767ab98a71084f800a9304b3616609360fd9abcb49eed48ebe0bd9dc98ea5053cefef96b40cadc5268ca5058cfcf4ef739c41d03b9084b02582e7a083240926f7becf1d1cc3d1e4e0e87d267c2ff6ae081dd912e15eb203efeaa705af870513b97cbd3068b29febe49e5f999f862c1c66ec5def5e5180e749a8ab1554993ce8e4411d8327b4886ff2983c9ec84c1eb356a193c7931a758b7986f29c643e7d40fdce39e79c737618daebb66bea7625742d100282045f9d005e7d84071c7df56f27b06cf9fad52b50659556bdb33d7a74c9c2c8092192582c5fa1f8eaa710ea1963defa88b7a12b3fa37443394b72290e894355d6d4de59444d45a402a33a5285417a9bb2bdf55225c667de908ce0cb10546a81e84b95110c62be54215995d25bd5d2db6ba3b132e76e34568a43e250ced158797f524f68ec12f1b633b28135bc753abdfc92de3abe1cb0de2574c9f3af4a899b26721721c97d89bfc6ffd4728052465e92af8acfbbfc8ca05f8e7e60fef3bef366ccbdf7563b1d08bd1789bee84dba475a72e7e53d3a9a493456fd7a4e7d15d4330c9e7a37de2d370c955d2bb77b74bbb87bbb546e50eee62e98d64f20348713b96461d64ccdba80703e7cb086753c3d68a99d6dabf550d68150f1c11aeab892cbebd7281b3d75fb894ae292a8446362686c89c66c334fa80c74ca0374b58ca1b24b65555e5b292adda127f4122911d198b56fad678b45a52a6b09011d248b4c9ae7b56d55262a358c92a2d21156de924a6280bc2a5ab19262502eb3a8f434bb803c2b60eb983aec1d59e4851b60728f2c6262d548ca657e3c36ad8e257c385a6ea4a7b7008df475529352bf0f0f9e3cad3e7ca99385892f79b250f9b203a23aa5082bad6000f97c17011d7dd177115093a74133d3b3ce59ab9e794e8308f3d57b48cb571205fa17607d99815aadf628b0c4ef6f133c78c209d6bf9dea78acf631599216a83fbf45a0762c3188e97c4ac27cfb24ccb7f4656fe7f5ce5720d4be6013fb62f0e9d80774c59c5ba1efc8896f0fd2b2ef480399005a966b6c40b5e687d532b156539e7fd828993c66dece69e79c330cad652db54ae969f74ec9527a1a7a9f867495ec55500ece3b7ea00ae3a9d77a0aa29aa409f38ce95532a94aaa3014e452758f74ecda809c864e9ddc246f0dd03253ee83b44cc6a9c3dac4c19bc294d31f9f0fe8d431693a5aa2b19a1aca8c8ed5b0d09127b2e6a7a64aaa31c255594d925195d9d42a0c69feb041327950ff54388c036b6a34f6fdd4b0d0b1af03353fdf518d5195a170a8dc67f4262f7347f31f108d5ddb1743c7ae932b45cc5da5a7b99a9f2a331d5518ad32d39292f9e3f3993ca89b7e6a7ec4dab5d1186a89beae938ea1cca849793167ca55994ae8a8ca54b80a5baa32955185f9cc1f2aa41ce8655619999654489fcf53f7bace73154e25549354652269a3a46159257455b8a76da3e486b689f294d26c6a3648e60f9498c9833acaa6f636485a442a4df4b1ca8a642d8dacaf03cd12f3df0f8db1c26049b9d5a32f57b8a75e7e473fa557551a465d665cf9d030ea285c95ad826818f52250b8554db5a41293abb2d5924eaab2d58f98f9431546f35849795ac353c7b915904a8ca7dea1c43c755095a452ea99854195847b6762da54bd4aa977a88b639114682814a94a4a419e5eaa924c9867d86bed9c21ad0180d27b3e718fbff6f873d46ea6c85e77a32f1715faf2dc757305e1d025b4b3b4a3889c72194fb98c9736401ad47a86ddcbb82a73dd6efce4a6af797bc9a45c37cf5d543c1bdb7f364ffefb5c41bce7b3652ea18679fef9879b3fa807fe4bfd37e3f39f77cffcfcf7fdb842d032972bcbe7c289a2288a28d4e9f42df1d3ef5095a97055f67d443fbd447d8d7b26cef2a967ced47e66c415d6f96acc3874e1538fabbb6fa6c856354e1af835b9f7b3cd8c3b8c563b8ede03426f4890cb0fe803fa9a785b34970f4967899f60bed421fa99434699b3f4b32497f84912fd0cbb58e2a7bb703d3b952e22229b211bdc4f9fa9bde7e58cd0cf992097d0ccede7e471bd9c51f2d3bb9c41f2d33f5ccfbe9f3e53eb99eae7cccf2c7b3973e4e70e29def396edc835ccf32933a7ef78a2f10e2ade7301d953cfcc51730955d98e5c85dd68cc0688bebcd2757bcfc11db92a5b2955984763363ff4e5b987ed97363fa28aec0aeb384802e86328d03d17910b04bde3b9cce8faa131d795d9f3870b88c9c3f3d226c907de8ba44ba8773ce7e0886c03d4b3d57b6e63eb197dcf71703da379cf772455990d508581e9d817437be9d807445f5ecf7295c9d8d8def37287d27ba2973b96f017830dd075cf3f20afdad852e367b27be7fa25cb12ae832e72f19e11ee4f30619ef155528e02fe2a327e3345c605a00f923f9896ea92a983f5a64bb6a720351e7bf7f77ddf77dbdaef76b03b4d07bd3035ba7ea0300fa42e21fa72fd405f9ed22c49de7144639eefa882c6ca12aad04f303400a9dc0e231a9beef94ac99b1f12dde2030a0366f92ede73301cc15a2b10e8a1354d13597be7a767433d03ddf3ef48c75cb7efa767d33def8eb9a6f4cbf3f2fadc9fb2aa807f7a66726fa5f4defd99eebab9a650f754000a3550e13d2f3fa0f730f0f29e973640efb969c420d73b27cc95d28e5cef784ec1d92d9bfc84f9a54be83d770981a415ea5a9bef95ad41ad773ca33cbddc917bcf01a05403864fc4094fa86f1a036db574dab61eea5f37389031cf57ef3aefbebb555019e89da3967ac6e3bbce793af7d101958514d6f9aaf3f2c6e9cb3a985cf274ced383ca72f79ee7b9b2aaccbae736d7b31aeff90da231211ad3f19ef779df75622e06f0f53d718e1df2f47a001007f7d627ad2bfab23776fe2da9671ab40bb94955c68395accff9e4ad3fa1b1d2081d858c405fb352d4245bd4fb2f1d41087d619cb39539e7bdf3ce2b0a79a318445f748e2084be7004e5b27b8e23081941088d5d9f75ce52147aebed54fa4e18aad04fd96c49beeea4102b6456cb58146f199f82e4efde116f62d0db55ab4ac69dca00adb74ee9b8af5e6bf5aadf076fbae45e32e3b3a582288d9037764e47cfc5a57bc40c2c47ba3bbbe5ea25f65beb1d4a236473d43bf5472dcf18f5acbd7e365a83f850cf3cafee583a268a535acbbb927a661d67a867264f0581a611bb78a34bc4294dbe7a35198197a4825c5cecf01507cb572fc5259ca1dea9ada1a0afaea4dea93ebb65939734425fb1f7cda6a8fbb6a585be6a0bd71aba404b9e5eb6867001b6967df8a604fe087d8338fac251a5e60035427099e5b6823c78c2c6c183c18d9a1a0c3230e13e201b46884aaca49a0c34d0792063082068d02307031e1e0e7cf8e8b141d8ed2f58cf2af9eda911241a1b069008cc3d759b538f101007c358e30e63bd5e34368885263c7efb1c539d9b8563b2d0abece418e7cc62f1789088be4cc0c2a0cc0e616f5726c282415c85e15b31cb47e8e3d463c2d8e320b4b95bcf8c7ad6f9f42fa86717e767cebff6ef876fc834c5375173e1c56f120dc9128320ed23c12d234874eaf148106794cbd5982f3e4f566368ac5c996146cffa53ca444f9d46673a99304f509a8b39f481120d073530ce19c481381c88fb320b51443debc1a2810271b89ef5065b6a596b7d7db73a15c2aa305b2b586b7737699b9c41c946fe84fbd34b68d94c5fed9472a084cbf9ada6af26b1d07fb89fe4246d0ad348a5a16dd21b5f5e5f2ecb5e215ca446a918637babbda545d540bf7cc16e4ff0e1a667adb5160a6b1dec3c6b2d1e3b8c6782b8429316a9512acde1c460d8a76e9da40f0736596a20f7ed752c3ba1af9ef3443ef5b47bdb91ac3a545265c5374db5569d31300e1ebc5a3b9a2c79961dca866c496c6f78c9934e1c546aad1447509e9e438c634aee5a41d003d65a6bedbdf7de6bedbdf7deeb996468dc8460cf6a9d06f9d1ccd8d09033ad1c7bc5e8543238aa1c991c6cc38ededfa85e6dd4da75b3e70d1c7676213d05a9f1dd0cb5aa4e3dd65a5babadd65afbb25cb87c51e9c06aea860c2c85e3de7befcd616fcf256fe0f284d9538fcd21e6783991adbde00545bde0468c4b6d48edc97452d9b06c705c39372e0ccc31eaf8dc857353a36523dc099374e45654268412a132ec94f4463291ee1526264f2fbdeb5a3635a7572edf7b7ae576f08e9907f238f5541e9d47fb7543e8be5e1e0ceebd56e87aad648ec6ad9d7aacd39c7abab1765720d4c64bad198455663215d19c5e4fcc9c7aea0e0deacc4a4695c2c0b698c83d424b633775eab1e48d23f2f47c7ae550a79e2b9e7a841b84f5f40293af9f7aeee995cbd5e7fdd9e03381a86b732c1c40940d7336834c4adb31fe39e71873d2a1fb33439e3532acc001e84b1c030e3f5d2eb3944c2d641a127852a42461b29251df455286c09b94295d185290605b5ea9a043c1155be499efa21b139e086e436cb909815e6e35dc6e47700d5966052092ac42e2210a982f4ac6df4551b878914fdf45518ae85ac832df45517a288ab283b744367d1745b98910c506c4031008a0843d3070c6f9a3e1f1415fb3077d21b5a0aae136639444c686551724a9186caa2c31e418946498f89044b421857998e4800485330ef312a1cca4862427274022939f25a1932354194ac0a413e65902c687330eb30c47322485590b24a62638d008cf40f4f1e0a2173c1e1f3c3d7cd02064c2986708251dce38cc361ce6e1c1432d28dd6cb41a94d066b8152d71e187d644c98c0e30d1c2640b85f5973817012911d19ee4448092c4d3c3470745508a1883f0c8c8f9bb088a0fa61f28b620b28b0cd309b27f17dd308549868cf35d7443960f885cf35d74030e265b4e7d17ddb0c4cb0d4890641adf454fc4f81277423c410aca47223c317a0264bf8b9e2451015881f7ba2c3e095d51b0df9fd71b0e1ef2acb53604c2e021092753c45062861058e0a28915a32c80183a62643a82458f8e0432744548587c590188142c818493fb7385a61281e4d61d814407dbe1174f6a366072260ec6e4123ffdee10daa74fb235bf82752ce9cfa064ca8152a60eceda14554a60fe38839227074a799a70df7552234010d4d1a2e648419bd6ea224b8c8c83871c0407070f793a9db55ea07a04b64eb9ba3d757b7add27dd8dca538c276e7add5fd7de9f53082c1effddb0c8d3cbcff6a4c5442e6f909b9fa405aab2cf566134e8e9edc7f5df4d4b9e5e0a3f7be73aed92957c797f5ac9d3ebf78a36d4124f1d4544c3a8e1a98761a82c753bd942a226b82443271fa1314f834231a91c28de9ed63a52a2304341d79256e8a66e5546c1d02a52142945c3a4a898141d93ea2a49739d37bd9b2ef9fabd15fff07c7627a0809ff68e75af5a4bbb77aced3edb07ae370df5ce7596d1f55b13c3f87b3bbfa9dcdfeb140c9589b75aeb59f5eb3427128dc189190a73af37bd97fc6c2096309e1ec9e11f223143411d691aa2c1abf1e2adcabc2a288c3a525018213143d44724faf92ce919d51e5b2d9dd557b7151691c5059d4d5f744957e6d890ef779113277062b2f85de4040743f6be8b9c602972f20199efa2168078f0bbc8c9942e30c662804cb8edf431828719d4dcb141054ffdb4836403113ede7a78c3c7861540115c9041280a1866280289991b922f5f449005122aa03908d3bb2958f0d969a8a00207b65146152b1b0b6fa7786babe2ade71a86debae9d463593ba0cc2f431a56785bc55b1aac78eb38d360c45b23deba87775099a185b7d8fe588204a8eea9d3892fc32219806862450fcd574a7013c3edad756c3d0bf1b6090d6f7d0445317420364363d6bb8d8eb012d230c9848ba754ac02b6f7833a94c8d48dd03eaf2d4a0af181c17a049d3cf41e88803db40ef0f9c98bf440bd0825897c1e92453e906cdae71f394de043173ad8c042056a351a4f85d50ea260e07beb258f08d731305f47973c21e03ab8e430102881c684e0a38740bd22787e29d03dc203664d84268b08592980fedb8b143fdf5ea258faf2d6beddfbf61245187ffaf61205d24f9d3207e8ad9d21534f684826cd538fccca7b093063bec4375f862f9a5e0c126d1566ebe9e6289739b5b79e3da796e393f31346f4923c7a7108e8adaf7e56495236158ec66a8a0a95e55c85d9aa2cf55361d65335304b5c94b62469797bf43665cb292b9fb5c84674ec63d234947a46dd3a0b47fef42c83b79f0c5bde9634c2789bc422aab2942d65cbbdc5a9b6b4aae432654bd9682c25a3725be3a7cac8a355ea473534aa7e185542b62a53015598751bbebd75d1a60ab2a96ae2a8f251fd8caa24f4656d5fa692de7a290ea58e5248b92a4b05559875967fb9dcdb9451eead934755967a4261d66d8aca5b9fe4d1db948dbeec9016fab2738a38fab262fd94ec00877c6b4f2fe933b78abbe0e711c8e5e882b7731e5df0d6875c5621a1fa03a5175cf0d48523b6704008283c8a05f6ba6b75e6775190cfb7be8b82a4fce9bb28a8c9982a4693a667d7a7cf641aa33e2bc6f38ccf542589cedea15f6def4cefc6db4d6bc9b292735a3a59d001e9769ec55882b00c59dae1eb9e7dafbb39e43a450bb404d1eaa801141a38835ac0828596023e1a1a75a0a520520ec8f0820a2d85e9c5184b569cb2a0a5b00a2ab2c110421cd152a04534a1020da8326829e0b0c20439a4538b20c638a2d511070c1ad885769c2750d2248956c71a2da0811e46d11e9c2831a2d511e787464311194865d41e14bb9690941ba16523b4f69bcf2c6a1d954aa1c8222debaf0aeb8aa05ca6088b742334f75161afefdc9227109171d187342d9345647c942c1a2f7d5c5ad364bcc4f6fa0815d65df284214d13d2798a3442eb200aad755b44509e1d45b684acbc45e4e4aa49cb640f14a8127a95ec4d6b00ca534e44f419bf3e83a2a15c7423347a1212de749d4f2bddfce1bb69fb6e52f92ee83b3aaf108d9595a806755ead74f7debb227d569e7220b468e9cb775eb9d098ab75c1d3584b9d4623299f9e7dc641d5585b79e82d22a1af3c24ab2df4490b89642e58801e85fad667c81eaea7c6169193a7fc44d69602e6c9ad1319f4d9659f7105ac3c456e20e52b9f2137d0039194af667c032bcf64cb9b366b13a0afce67c60a5458e728c83e6b0debbcfbc8129b3a96d7cd54376bf4d5898e92711a17e2e393f295fb649f711a19199f2e4343169921e7d08aecaa1a8dd0c03cb6a6cbb8115a6acc329da77c7ace2e4316e99ac92229b26baab32e925d9bbc5ece5a474f4480ed28e01771d4e78801fc267867b4a0f61495d4330efe02a9b2cfaf0ba93293df19a51cfac93dc76e225b950441b2480ff5f3ea28b2c8083ed207c1b1d58e6ab5a3dc082d47c441d051e4abc2ae1701bdc2ee748addab9fc2b1c14904371e3d52c4517a71005b87a7867177639f4ef35052727f2bf5f35b37f4cf2f89c922a09bdc08ad9e7a84f8f87c1efa981c24817c234febfa685d92c8e726bf6e32394816f15c619e17f9c8ae4d6b1a8d2172ee9deba9deb94e61d73b1d6fd2da05ee80034fc8f8b204e50a122338fc5083210b28c014919145c997c586a239645921cb4f4775a838201e80400013c5c1880d2bc082852bbe50523b2387173a1d7288c1468cbf5f784bc0d6e9bada8cce1fa8da47add0da5fe1982bacdeebcdead183be74d0570f19b2ed415fb5e4e0abef00230301bd7a75c7d5787c700902e82badd2ca4cc79bbf71c7ace32eb4fdd9eb706825bb0c6f19e26fed4f4140b2d5972c33ce0cd9b6d294bcf257efd49092db7996ba6ba90720104087109fada022ac1ec05e77edd210952472560c201ea5d4abd75d4b737c17fd003464848123b61811c18128c210238127bcfc90822286c2004323eaf25860afbb16f65d14822d1ef55d448587dc176037a57dad1540adb5d68aaf002e14b07b760abbc1afdb8429a59452ea75b73ba42fcf4f299ddddd6dc2a1c3ef8aa2382b89423de8f5a0501e36fd244fa7a7deb3bedd330b8661c7c23ea11a25a250e0ac2d0c60f70eae75fcea4f42b5d55a6b67dbb646605d75b7b5b3d25abb6d77405d3743c2cca5d5f3e6ccb244db2bab1256f3d25aafa5b5c785dbfeb76671b794f125ab289bc2309520d72fbe2c53b818b305cd447342888cf0001fe58b67ca172a58df455384f8f0bb68ca079e0a53ed8829054686e032c6a7043f4861748445e2e5882f48ce606294041066d2d16052610a064994b044f101244661a838a304616411650c2f68e824980c2561250b11415b6a1960e440c60d3a7c41228a151c79c13b325df8e988b8558440e6048a2a2a58a2036e694c4d0a2f4da8d8e06488d5025c98239ac00186256a07188003135466b84911ea00077246b430c101a9800c9c9511f048eaa288304d7c60071c8e18eae10a31c669ba204492498830acad52b2a8e8f094ca93aff92ea2c2c28421d7efa2294ac01b32fd2e9a92e401b85947f0a58f05ec1085043804b14208b868339ef82071023184983c112204478c9c0823258856f25499d281a7464522f08012188eb8a2684a0b5ff21c1de98ebe6cdc29070e30c9c2248b920cb4d2079525619c584116221052d2a488a771ee638616fca90f2ac315344ea680d1c3952c5e4431c2c2d26d05267ebe3431c309b0e8a863ea2c2daed4a248dae213a50820a48a048985188e6081982b4030c50652e4aee8a1488a1649f3d559610514368ca0084b142f901cf03386172fece0840b2d75052b740c8e0a6f8b96202fcc0871f8258bc67751182eff7d178101c5871ac697afef4249174face0831030e8b0c109943892a28c123061c509a2781394c0c80519bae0828b5a15508ce0c41061ae9871e40a92d3a0a7de18a9ab620563b878822b020a1217a81d9164c88bed0920704705c61507c403100820c4027b0658ef16423818e1705423c372b91542fdebf56fa95359ac9b8d202a1347ae83c6fa7e750f6c15c9addaa8f5dedba542639788af2b1a9b5e6fba9bc303f946a9d66fe7cd710682dc3e495338c7ef0afd24c1708e393ca1c239ce276750727981c4708ea5756b29bd264b5533041fcce11c4d3ffbf5f6c13a0341fee055c215fa3b49930cf993ec991077b5b2abef5bc01104569a1a02d17e8166eacaaaee4dc63b7bbb45db7fb66fb7b5a6bc8c6badd536c6debdd9507d7fdad64e201056ea0da2af767b4393edae77f1bdb5d6ea16fcfe50a690f505ceb8bd140b870fbb2fbf2a1f4dbd83ad8e16b5d65abdc2aaecc3d8b3f767f6f49ac3c4daa1ce7e417f6f3f9d46e84fe4e9dd3442a0513df5952c25f03bbe98b4dadb79d8f481e10925e6948c6a354343835563d3baa981e3f291ccd1608cc0088123cfd1b1918110d1fda13d208ebe6a5818471b366e6030badfb88183c75d2e1cf7c52367bbcfe47d26ef762e1c9c174cb4f5ccb6db7c4a389701382318d580e5d8b9c911de74c917e8b8c1b1c30596c8d6337cabb2d305444bbc9cb8c13a422b54fbc9f1930471f465415cabb513ee9c7a3adf51b14fd8b5426356e8071af3c0cf047e26700b48445f9604712c80384b63bd23b4b89e01f50cbf7073c81a91039e59a814aed455410a95b21901000000c314002028100e09c5429138301e69a2d67d14800b73983c744e409787a320876114034188186388210411408c21c614d1504500c9816fe54a02a389bac8457452bc6ee419a7d1204e2e2766a9221c9314b6e8d1208020ed8c088dd4e22536ddb352d0ba562d2ee5fc6c3f4ce9889c1d9f6891f9c18c7570640548eb320182007393e344ae008dc6b8a7156ec5a248485b752d54198c1eed500f03f9e6b94f9db47417fb340d3e155a0cdf212314f2160ea848572c28374963698101009297e5a51177cf6888efcb9ded4262374bef59e2f000e8e5687932774d5a3a4bc10e2923ecb45af16bdaa405ebb41bfa2d8c56cb0f2416988171a896d3b65a99491b74a92606b8a3510b6f62654c8548ba01fd9f10928f003ae56ddb0eceb2009514a0570f3da5c856bdea54be2ca13a4e53fdc4deb39d0323a887a9675146b5ad762cdb41221b0b15be6479e88ad208f7337a18d195a76f7404964d4aa17bd8bfc6d0953bf1a5262a4f27944cb96ad3b909426a8357d2dd93f9681258361a90d296919cbca1d2c5c0e05fff755f2b338efcc8ad0404311a5456f4795f17800786219dfc5b631e2f791e8637f39cc3a7a4b6a6aa6a8e751d36624b8af6916a12a29c83804bf3ebab86f9645f9310a240fbe081e13633ab1074f4664683f266551e57385ae7369ed6431f8c5cca063ea6458943686d9a3317d7c3241bfa5c147937c44a40b70435d055078a5be91e953c9f4f8654c6d16fe5e8a41c34880f2def9f56782a0ac4a0d2bcae721afe88f039b3cf05573860221d076931b76de6775d97114af0b02db6552515e63f864fec5f72820c314584eea8c761589cb322e78b013e260cc6967803285eb985f264afd45c0b0a472a66d0e68a2a84b33323c6d3aefc1a50941764a382cf81fca60ec97489f84bc9afc3c68bc1a5fc1a2e1c7e474d3f95569a56ce7b8a2f8e3072ae869987c2e8993181ca377a7ecec84c5fdf74fd20cf13a08e74fe3cd50ce5dea0693e01b4402c0a62133e54127c8d258ceeac355f08226ec9ebd0a105e27d47c30f2d30c29c04283c41b0f907b3cf4a440b410500ad1468a19b13e2351ac76133061a7c03fb6a1eb50a913ec2c96b55edca4f84e32c79e2b784b169777f0a8f894d433384a0074f406293611c24eeb6a4abc1e703f4eea45821f99d470c89d4b1150b2aa591d2b796ecef853788c44ecca70737d42737f80881b1e4f101a929a31bdd03163ae4cea4f3c934ff0782fb58d61ee171c680a18c3c5f228bb7730b15b0554899503b8ae295f8f010532914d29f76da4cf81caeb112d7a699a6961c8cbaafa0b498d651dbe48b907f1a5446661219cd31b58b63c2c7042928a71cf7d77e7da41de7c65b220b493bf925a6489936c394c8f4143f0d860a265615f50deba550758e470bb841963cb857fe790ee863900ac21f38e6038bd0eb6adf957a29fef4991421d71ce793a68dbbc76ddd66137d9fedb6139532eae47307509a127080f33f6322e024ba1a31c0cf97c6631ad04e47bbca458cf8901faa582cad4cf0d6360dbeb581222d1815cea4830ad1fb5b33415bc1961ad9168fb0f3077fcd459317eda5aacea3a29de17e37e5149af178a2ece33d44d91ab3f5e83702fa18b491e96278d3a83558cd92cf91e64fdf9eb1ffdd5fe4d6717c66a8920aebeadd626d7c52e87b7e9f55063f1b3cb7f681b03fefb3b9b4a4f7484b6d7cd30dcf96514e981e3a15c2e88bcb86e2bc6de28fb1ae484da8806e72ee6a7e8eaeb236d02d8505bc0e0eb5f9a5e902d35a565af25686ffacbf78897acc03341348270b6e4f718570e298796680d95aaba5a8d0365bad0eb260ea41c7822e708518823643c1bb922d157c0518eb437013537f3928be5f6d11d7080ae9321fed8b3c7455b8a1147999bcbcd6f6a033294b24516b46b5b6d392c7c0dd6cb3ca304cac118b5f071ceb94aa52889f4a8efc46c008498827a9bf2208581ae3568e64ded763173b3a021b217cf0ede4c76c0d0664083f78f3f201cde1280fea2ffc2dfacd0baa19ab1eb0ab13ae6abd00741509738fcd89ab706af6569734e7a9b971f49947434cd3c5431ac463f7ead2cd2dec4e0aa58272aaa8ecad9fa6335f0d9ef4f787f058b98c795124f6849f4c1ef2383d7e7e42326845d55c1d407f19ba8e8fca3c1083645cd074561b28996790c7b327a85abd8618634c8e03fdc500a55b284ca442929e743b0d63b861da6e2682898481401360704c4b6fc8aaf71de39a148e757b166c001002150036247cd4e3598c2262603825af0272257a82348e50f860c55b7edca77e5b69f6b117fd0d6c27e1685d1cdc49adea3828408dcd88a3402ff71d7365464d718418bb22d5b0c4e3069bc4100dd3296886a16e626a276419520ca580814cbd39fabdb29d355ab366f20b03bea34d243f4655b9559627b4ecbe7951783e82e9ccfa806a5d34de3a409409b68b788b29105ba888f7c24ddfe6be0013b954a2e45dde2a12390524d88bfdff834af15259bb6a5349c2a1e36d7ca606cc58865b0e5f0aa4f72c3df01b651d0cb4c1311484d963596a7866e806a974275ba2e61d9f4a0faad179f6be897dbd62216a0edf22d51fddbeff79b8d78bb875b80720bff0182fbdb94abdf6df8430c33fe7a00b2eecd9989f522ac71ed13b966de526528467d13e98f1237e78986137cf09f30212c1f44790ece2368ccf303b3cc43a607f6338a03430461a43f2842469f28f09f26c6fdd89f89702faa5b754516ede657661529c8ff6bf928103c9faac64a938245f297264c91238a73e63da82f448a495874439de9e79c61f9486bf4f69b246ecd8b9ba63bcb3c6a4b8ea265fd718cdb398caf1c6f7e9d0da01c9b9309e11699c4998df2c0a2e7d1b4e351fc964e8247911ec713870d91ca33879bee81ce99f1d99d4ff73b8bf83c8ebf1d2bcb7dcc6be656506d51453436a5605216885fd1d96f6badc78be8302292ecb7fce9c129c19f632aa50e5d5198952fd543adba1c7098912e8c3f729872eb41b4ee0485370942db997729f0a6202cc6a170c2d7f6faa021e7cf903d1ecd493e73bc4a38b0c38638d25f97c32034414f08354991f3a73e025eaa878aeb43ac8fb1c58d91d959a7f288dc78c3f27e052a1f814d9d6e4571466beb777c2b25da3ff76add53f16b05455050eb47286314227370f6e1731b0cb95502adafa31cf6483992fab82166ecad2f7d992f3df4cb7591e073f558928eccaa401ba451d9d2448d98d43941eaffc0ffc2a2278259063587b741066fe3653b931b1108b8d826af9281e2c1f83ba46945b3439ea175fd8ab1f34ab189e13fdd08c68f0678b5e09018bc982060b540821bbc33d1b4549aedecfdb4ead6bb18e50f92882cb10cecf9067c37aa6c5f85594f29a70e68e824577a1e0c822f58ad24e70edb82b9fa4f257dd6f43752c36e8686fd4a43292c6fd30924e8c99621ac12543f1a96a95639f5da5420c9a38075b92a1bd386a0ef56a05587170c503543a2ccd0b6b36989141a35a3b63b0def12bc7de77d6bc215c9729014a13a1d781d6fe5506d5c7962e477fdbd9d945c05a20d396efbd6ffc8a9a6717a900db258f7c3819dc54e933f21106c996d3cfef258af07fccc0280ecbfd3bdcc5a7bf0da4f8a2a3319829e75ffea245525f505da8aa42116cc65c2f8fc2be84b2f7b05ce8ce8f2eaf15968edb0c1543847c22358e23df3d9ac5603df774fad84d56158b9ee55269a241e736f5cc5a4c490c54ad5cd806cc8e3b8feebd0a47e9172b2fae53ec7211ee09fde8412e4a37babc4c928e5895cb1af11cec396534eaacd215c0944b1d4d1a1a49687a0177ee4a5142f58a5ca4b409c138846951562dc13fa3d6782ef7961c053a0379e53622ad7230f2a1d0b9ea7dc8dbee48097ce9ed8ad03f8615519a0ef91f272ff1f6a5fbd3732a076a34372f5591bfb052b7703fc385db40ead4851739d556b41955123f7d5511ea6db04a51ea2e1de75fdbbb285a7f274ac264273455272fba9e2e70d7dc4e99bc9d4c3c1d8da68a505bfb19447366514a4836dca580c62c515433a6fc75116066ce526ee1167ac47a4a0e43b41da048f235d944c4bfe13f45e58d5b5e0e8701ea412b46ae382e826d960982e9bc1b98ac50d755f4359ce3c93544d18b6a48c6b55d53425c32e598ccde471b44524901c8635f54174e721be5bd58b298c114473c4f6aa7fee05524fc3b6c6c3a8988b02f15e634f3b86c3e3ac65dd1c20cf556965d5a36c3b4d1c1ce02b67fe7438c0ce256c0e450beaff653d4211aea5015dadbd8e86f33f46c60458f0dbed9c70bb02d8b799b020a769f4ccfd036cfee535368c6fd77ccd2002741044fbe876bc10c2f7cb9a86310045f5fa2ee6a91d67dae311984c8a9b21a7f655086ffc0afeeb439070ed1d2fcebb4f0ee78020196c96596f3793e0fd63f4bc91980f5293d163af79e5c08e2cb0594fcf5285930813981ed828810457bc897efc52e89190b39a9150125d5fb6c115f03a75fbb030e76f8d2b513f36514621ebf1744302fa1fd196b1b1ad12670f1b28707d5e2d70738d8c67cb9f7603125bb58c4e78c1d0af67052be3791ccddd9a7cd8822912775426b4c268868a0484eef0049a915ad446ac8e34b37f8d858fb0218efd7aebc727c1add3e919427d34afaa4bc163bcaef2f27479c33e47352c13a1f98c0b4923f5a4e7c09a893e50561bfd01079204c5d41de0580be017b893da8877c52efffbb7c6e1887e7f7341e5873049ae179737349c30143a63b9aa742b3d061d53cd6461507c785e80d14ae189a38752da53650d83c2c7c3a38d710e48f5f0c8208e120bf912b9af88df36bb21246da146a224408bd3caebc291a86e0d31e69f169259f5573e69f3c05e177c61a5fa63116485358c1eaf9f34cbcc2d413e745db718d46881d85196c4df6d7d0097451131399965d5d311eb3cf3a9963dfe4895bad52a335e546490834493524716cc2857051ffd6b30d09b78558377ff2019019d6fac8c67c328915e6699c9f0dd143acc58d763cbea170db51c3bb104a1c0264ec12f2f4bc90d7d22b9db50c958362dc5a8b4b873c9e3bb48d125b88be19d66307571c846eaf0df1851239a4f3084f66c7cd82236bfee9a1b0d2f79261d7650d534711875832727330da2f598f8f40587585551032042c3c82c27bd711df9cd153b260fedaca8d3231ee95a9f49d76d4a7a27259b55179210dd3809ddaf00aebcde6f66228ddadcd3a26337f123959fad0b4ce866bac015e61363c9780621e8524d81ecc4ebd362442cde4c0709966ca5fcdf9aa839dc673133acda5d5612462136c7ae174ab09896ec6284cb3438c092d3ea50d0e169a2a24949b819059e0d7d2a28d23a85b93cd0933eb7f92cc4fa1a37c322a1dd3fbe2a1ec2d5f2cf94a41d81f2d61099326ef9aed5d151d0495dad226c7cd546cae5d357777f5877245e3b97645877dd79f3a4d7944d3d4ff30145914c320649b98df6c10032336fb6e1f730e01aa0288ec7f5d8609d76285ab4a32c2127a456abbe4eda3f2942098cf3a814367fd23f0595acf663beb06f97607916a29ff748703fb285758f099bfcaef144ffdd8278fe137dbb0d18e095e9bd04a423583e1b3ba571919cf63d52f0047fb3d31e12812bb7a969f5c96f060270e19aeb0f8a44a21843f10c3be09722fef6b05123a286aee51d9bb4f556924b705b793d161975c69119cef9b98432f6c3447eb5f19cccf84a6d70e5667432099a462ee863c28c30c303d92e2cd67702d941ad067db167ca257b52d7800739681eeba4ed90270a82616bb5b93293e13d10f1c3942f2ec9b9e517040446e0b6d2900914575bd2429cc23261a8ef73e8795ee6f093a837fcdf9c4d7cccd2ced972600c8ec6c5fa9eb64ad0d476e5d28799e4edc1ef9c1c1b426cf4a7c0f7ddc639a9abff8dd98cc4a83d438a1c5adb15e71698bd0adac5511f17030aa524a55d7dc38e299561e2861eae95dba3760d95011c14ca1d721a5d916363e0df39abfde32e30baac8d87b6f0cde75ecda14f57610dcc742d6414eda98d926b3ae2c18b082b1dde1954958382c32464b2490386ccd9151c02e2c3c6bbef83ea4b39a6aa5e4288d6a8f9f89dacc0373bc0ce8c41aa6a57d1a10e9f230e6a161d652273fe280bd2b7634d1025867b01ad0335f83118fac7cf1eec97100db70b2a5684cac2953e5efa3eda19215c62e100020c029750bc4788b8a3be531f1388ddbb8410b077490f83fda99fe3e587b6a67caff6882a0b1ae29cecee439b2c13e57d36a3bc19e2898e10a5d08527dc0702d5972dbf51856eacca4bfe648ef8561a5f631e51e42a8db508b178667ce2d4105d88d20a27e9e3bffdad5a1da53920cdc5964336f62089aef20f0516bb5b9f11450380c781c78969df02daccc44c42366d87784e5dc3dcf42600a7c81c9cdca02cb85748473f0eb57c8d358a88f0cd949904265b0c45906c5dfa7540e2a9d2d52e4f2a19c3a38be1f2f57a7d3ede9757a76ba1d8f8eaed3bbdbedf674745c5e9da4dbe17ae67a88b770b1ccf98d45fb3651f6025c11d014ddd0e0051cacbfbcccdfaaff8cc9f47f5b9fe9a277d3adf9beb1870a132eba8cd158c92de61ba77d5d2d91fff3762e3658c9eb6a8af9d7fbb9c50a4aadfc3a0dd1a3428b6c849a39eb3b5eb8a1f257cdf831bbc0bfd7adb5f86b1c27e7c056ac896a39296c9ecf875d471778b0b09b44e6889ce43224f41bc46914001ee3ba515c3fb9d5842493eb93180c3fde8b3eb0f32b610ee2a4f96f833f9a5b1176ba3b1412c074c31569b99def6a194dee98d7d3adccac9988f1fb9ce728829829d6b19c5e792a10e69b13b3b33467ff45dfeb7c0662db9a07f9aebf8013a154370210d8bd21e909b471525f5e1ae22cfc7c24436bbc33e2d331b2ac800a6ef0694f9e542651c621f5a055541495d0da8ae04f55d2d76983b02da64210647b91585af6bbe6ae696dca8aae1bf930c9da9b679fb1c7d83f68b86d2eebc82a2e242959267ae51da4b6363a059c933c50581a9ed78beb4ea32b12e2400b3ac2f6f12673d063aa8d320f6973c12f5ce43a5ee7e4c430e017ed5e2410ab1060fe3c2eb897ec89e624de4c8a76da432aec705c7b1aa21180f4329fbbd51cd1577eff9ff2447aff6e50691f07cb7e0726934dd892e4d714db6b4ca3b615cf2ca632020a08f24274f23956aaa80d07acb7e94ee852f3190a46ba498302d8fc580db55b7bae44cbdae6cbecfed7716bafe5db4535792cb6802104503157084c463a0bc6d178a6dbb23bb7370ca424e1f214afd4211ea400574e9a7ac420cdd03d2abb92c6d4995668e5b93ae7998bb534fa1ae7221eef377493ec238e39f2589cb3b591317f6071aa8486e55072e08607536c3b506fb1a2c83aab4a91ca3d6d49725815799aa5171118415fd51f8866d202b873fd70468db388e71b9cd846442839ef168a522768590606c97ac4120ba0d435ed1ee0b87e747fdb2f91ddf23d03eabf82d2653de9c740e9a63d928e4ad3d9264daa0eb1d495e0f827e855898497ace9633a85d69079e42a44b23933b072b7f812014ca933d7d85a8d98386c43563f0c9632c590de13fd5524aa706f20d23d95ef83c7a34b13b164f59e9cdc8f20022e2078e5dc5f696c75023ebf3068168551fa94a3e28ffb1c60653d9a6839cd919ebaf8933c4c451e371c2868dba6d57c386c3299fb10a762716006a0531918cdc26bc9d4d6c26cf9b141927ebeedd5f791d89fcc24ed5a1a8bf3d74651d969c6896a00a602a33c3a3843088544857a5d179f5e359092532eb0e6c631fe3572eea0be8282f0c00d3d413b1a3b31d60bec166d293c9d0fc13c248ed7c6c56a6904b6922f16ecf48f8653a3005a168ae0937c4461761807446229e334a30e31778c7dbf7a20dd0246fbd7d1a32f0e355e9c41151f55ad8e20a49eff4215eb3584e876ed44d8d49c63b17f6aeafc5da22074c416664b7b5d83c9b10aac8301155c46742bc44c4747c952227516fb3a6b1566d399ad1894f11dea45fe14a205af81dc8ec522359ab82bbce85fbb351653d982f30fbab79151d60220e655d691dad884f2640110d08d3103bfe08ad3bce7747d275c62246b6dbb031ee8a560542cbc9c7c55ef88192f62d80bd6190ef1bcb8c4a91490f46ba1e45298e2bcb3729f05f12c65ab15e83d6cf72650b54c804bf5ecff1f43e1d293a5faa3d33bc6536f1bd5a828f0782e050b9e9774605b71ed2190fe0da6f4396b415183351d77e881049d2bc95d856200fc52faac2623913f1b32463aaa23d1493463413f121d094843e1e4bb4cc89ec6ff75ce7d7941787b4de8b5ada2efcbcb98d833474957303c09ac9e6669f4cacca400881e392cc9475a0c7a583f989c1bb6c5e17fa8403f878ecfd4ac3b876a08319a2ed56a4b5f427c102f8f4c0fc9537a637807a68e7f3b15f93287fc74ddbc67eaf7dfd39b650c4f80c1b3974fc92afa91b2ccb83725f80aa6555d9d94fd260fab237dde1bd271a2743c6b7eb4c06048dbf43e16c5441436786066e8a66e650fda9d16948742c40e965fea3746cda4f218796e4622f59b4238e21182ae1d0e2979617aacfc97e55d441b0434c237df2b37d58c8906e2537dbd7fc3e701a3bb4047ea620b2669fdeb79d40ffd39669044081bdaac9777c5cb525d7afa3d9316bef810f34bbdc84da75d5c52b4524cc6d3c784da427381aa5a965a7faabc1b979d4f682d4477ea5d4830cebf8e1bfc30eb6411fc4a7c1f81dd4f16dfb6f216ebd900c0410c95e1629bdf67be21473e452d4ed7193b71cf4c9b90e0bc4b97c1815be27ed1b8800658fc212c71aae323df3c7f3e0c294d67e0c9330a679e4f3cc87502b4176f7e294bef5560e870eea87d9d004d04fa3c286ccfa9f261cf7e88ca63f6aae0599710d05e7ac162461b05b453e02ba140bdd80762c950281ec3111edd56b5edb6ab111363675fb2df39c10449c88ee2d95883fec214ec65af90817335a2b85de55da48d696a9dab1683956c7beb440b1ef652ccb64b0fd5da737c5644c52549321825bf448a00c3814e03f04c585abb95e73a751f5f13874c948d51d51e47f6c0ed33c9cd2cc1bd6bc0adbd2e9abd7b82600c3c5aedef34d416429651e32c9eed01aba84bf9fbe168c2c32ec38c3d0bbb8eb3c00d5ecbf06f8a8b3bc92f705c7ce71ccf5c74cb967e4abdd7850ce50052a374ac984823f135be3db53364a5dc727dde92485837e2cb2c17f6bfbd98c10bcb115b52367a306f7946d63152c9d4fd886850e73c54d53246ab818e41fb9d046a2ad9e94228b8c5169add6052f32c552cd5a19b5332300afd0d26951423085f99da262b78235c4a46ae09a44a639a8ea77f2e0a41c99c88c93bc2ad16f935e0c41db9b6088833152673cacb423aa65835beb2648405c725fbcaf3e01e6cedf4a09cd541079803c6f84ddf4ed43ac1156b5a8910958c357bada287c96d7f8caae629becb80712a9d1595a775cc22951d71ebd705c64c81ac6168f0a7c9948ad4040b5eb2af1bec614e08d2da6f89ba6c9a268d2896a6075a0164253802d08abf80849bbd7a98463ccc27f61738a0a1de2b8efdccc939b65552ef343798c1496d19711d80ef5dc33485a898e854c9db82d05e2621f7332d81198c15964d31b82b4b2be7e010231308efc9606fe128c3156ac85d6cd31bf2ebb0ad71ccb27d2675eb1123aa10863d793f9fd1addbf72862ac1adf6ea4c187c4e50c66ea8a960e78130759b449baae3064c98a80b7e8d5d72520dcc6f85cb27af4108b243d21eb2ccf308d745d971615ab510e6db90b7f3e1d3c3a246da7c8534ca979582ff3c1732226d2913b2078f3d7d17a298027121583140d08c722f132451d8f8f103810dab7c4cb6b0abf534f062b24756eb5c8feb14ffde0d571c430ca6bc89d7ccb2ec9d4a035c36400448592d3a170bda0f008ee6d62b129d798964c846666444501419db18179d6f36d46f207f001f19fc6e006215e64270e0992b42cc94578cd05e70d874b36fb7f062a4476ffd15d1e4989b1d120232c2b919e1f9eb4b3e84be7393eb06f8e3b1d753f6f900f8af5218ca8437463d9c8b12fcb88abd5d6d65fd0c183591d23159bef4aa4822aa12700ffe4167142148ebcd8f7338462d8d6ea4ee19efa3232330583402b324897837baa2a1abfad2fc4dc98822b8fc7c7724715d6234a0c905881410d8e9d7d21e6b1a26c6e4e04929f4acc06e997d08749cd05be190fbe629b5b777b2c9fea051a64241242266ce83faf40a0a1ef7ec7dfc51b139529001a56d139d9f64dde6a745f0e400f304f65e4487343d9a437dd89c2ec65c03b38072d08a2e309d0567809aa85dd2ad30398b9b5518f1ec5c455484344567c808517585a8608353746c45fc448cda07e8604af121dc2bd73ce7fc660e8a8e61981af72a084ab96430c74a3c7257c6af078f8e1725ba905ed3a84f1706c56e93e683a58e0248f3935a99fc62f29649b1d2ed09bf3d6e53fd191c1a2d0849a868f39c260f2d8d45ae36b4a4a1b92096affddfccb2d077e3f27ab2b596e5ae0eab43374e4b9103d1fe14b0a125736338d80d38776682b5226ab3683d51631427a9b3bcafa703eaf9c2eda2f4ad80dcd0b43519234ebed7b08684e7c5426c658805d0577c30de9342c3fbc85f10519405dbb5c885fac3a5142f24a26ab105348b5c9650401fdaf9a97286b6209c9696558f6f2050ea08f6e17bb0dd4ee4a1f8a99b9fefd21c5175565e284979f5c4b0cecff2ae9456d962a77c0bbe6b0d2a868dc0514543214be23f3eb3f597dad0339d6daa2f256ae33962838bcc18cc2ad1aa778a4c833642f55d5eca21fcf10de53501d2382644334586de28bae1999c99a3b53299f956b0f32fb263458b1d698b64cb74401f4414f6f85cf5033e953f2e67d20c0fcbf43d73a8df351a3d17c65a7b2273e0fed4928f97b0b9b95b7fcb1dd947a3c7e099ca9ff48a58d8e665527a45d982aac9fd14074b58c75d8f54938ec11118a9cf3641af41a9027a86fc4826bcb59427a00b8caa58faba199e5fc813f7cf30d62f99493d84358db63d901c0bd8d3a53aff0bde3012d4a1f92ed116e96e22632afd90373452623102c580d280e6d2157063122fa5f6d471414e220f24ce87dcec6992c11f12d22a3f58b9aa58469d4438a56ae104872a835b4aad2e1e8f30b2d5a70abd35625ed4563724d03851de2a94461bf6d7ca2258494be090239b4c94f8f44619939e9e518da215c236c39da7e596dda52aa240f1fc7f783a02040ed56deab7d9ccf53779b2bb0dd65d06a4e9ab2c552e02d2f3da1811014d32d3936d9f6409b5a6d21c02254e762b83e9cfa9034ba31daf8e35edcd909d0cdc295cb693a783c1fc986b2a7593ce4f893c770bea4a92adf201ad764f09384206e7bbd600afbf024f64bbb8eb1543de951de764210e962570ee9e34f22cd25957c56c11f36610c9f4b464c67a6fbd93a1a6097838ba637934159d6251f26eb739d2aad1985d3e65103325d321bf82385c4b0694616304009794f07b764c6b593fbc02eb272a711ca79bbfb7be2679a12d8ff48b7d468899ee32c21c88b56850b2b2b62f4ba7426b6881c932f86fe0658c4f8ed31f342896d0663e30870f2c719221734b42aa2361ec13892b360dfb451fa02b5941ca95090e46230506333c182db8a0396e1b43684b8053ea9c429233449d086379aef2d840dbcdb65d6a3201bdef6893ce965a720746c2692aad28b3fd409c183d784747f024b2bec7c239c839c64620f836e19310b0154a0f332e5db8b0050aca494846e3dd472b5091f6eac65512b27648e3a836165c4db4de7297845b4c406181ac8543c127b5ffd69c9c8c5089bc3e6c06df0624b85c4d925f4714903dbdc811f78d7380bc1abbd61151c6b016d8652954758b3894f68751964ee9fce20c102baf08dccd0d584e66bebad4a8d452ce7f95e7987827698303192aab29e7f7f6ebaa2f51275a141d0ae3529bb048517ff64e56481fb982ac8d0f63006d9550b3d14cc9e24aafc8813b1e9e7530b838fbf1f5b6cf4faace9d08545dd92ed812890c57a6ce6001c76eb862a2be2f3d0fdb4d8ce9492d5a2204536ada10c552bce33ca9f3479248a747908d36c46466792951dd4d1d9e2d00b31be2f15e2ba2853cd634d56d9e9b34d0e46f726941b4b2fe0e2a2350bdd8d59d5569780cc776b02515253e1ed000b2919b757c6e1f326b07180895570583467f0077e52def6c844d18ed3688f3a8bee705e13e9ecc5d55796c31ef424a5b153e7fc16c4250b340aaef1d207e27b2b0c7e29a1dba9ba5ae960db93e0b7659279b93ef09549bd84a6f06481de1e5abc009659cff32a0a140cc1751713f7420126ba9cbaba84be9850372d2233a64aeb5600c35ef658b7429f9c0d817b432266836e6189987907896cc13512254e1f84e3eee281d13fbebf8437b800368355f8ee469193554a97bc15cb1d0886ebeaf574a97609ce966d79a91281d3e830a8b8e72ea30c84ad028c66935aa832e40aba3ba6afb262ab0011cf00e3d4daaa7621572049009dfdfa4d35a2cbd4a82b68db0d0291e55e70ceea87c800ddb33744d71a40297e80b12506cc43f72f6cf6cac3e36fa3af16f43ce1e54dbae371c4870028ea17c295d2d85c8bd9f78a8d7bb721b9f70392d89f64cf5353779c67fdf6a382a566c8254c31995bad2426f557c6c270f98abc786f93526a4f9aca9abf6ad6c00d8831a93451b3a64b5b321be5e88f140c3f515b6a80f15b8cb3cc1592c699a2d6ff7a6e91eed843cf7f4422c12ebaa7c0e55876b0237c9db22531159feaecc3e7f4ecf8523e568a0cc4494c33cac812a5137dc98d5e1d3f1c042e22806f4e6bfb1a2eb0f72ab8556c95049a638b152603a2dd87d62399773d756e384ea9b685bb29ce04338b5dea4d445d780dc74f85bda220ea8ad63df1f9f45eaec921811dd8447240397790fca4b4ec5979b73a76ecff485b09edbce769b280223cb1540963af4e9fa0af46c00245e15eb4642de63f602fb75e131f086bdd55d691b21a88f9d165442b9ed0bc26355c708c8d0415f6944111f491dd48f4dab2f3b3db79725123029b78f94fc1d98a44dd6513c3314eed42c855c7391b082c6af88b5d60e3a71a16ee00ed8df8201db0053294c3f5a8762220545354c7edd46bb486577b0d08047a8db15da2475941c8c2da03aa2bb83da8060b8208062528a9f823fa157e87e9c0ccd0fc7118a2be30a96150b9fe5aac3c87f170a1451677bf01a2ff86aac804d776db5ec6b8d296833ef4edbd56507fe05c97455c710266c527df93d147e0a99c3861f5692fd36ccf904786654edc5271f1e552bc9f7971495859afbfa7b67135300419f51eaa266e0e464b44036f04bb1edf07606c329f7680440491c5db000c73ba3641f3e3e52f0e593b50a7905f84f995909301b8222eebc8a8e90b2adf994e71c2b9064004e4a2af4371f2adf81a6d700a3521af7e4c7a84fac3dc96036350fd67edbaa0f4e0ad4f287ec1bd13c101c228bf0ede0cb2484f15891a635d32e8cd6194aa74bebf2243b477c930b03e133a10a73c04beca29e25860ca02071c7a0335ee43d1d56f42f10ebda2714479c7b0702de6d13bee0567090cac8a2bbd69b94ff9ef36b9bd545097f4da771902b0411dba852efb15ed8fd4ae4db14355a00ef61c3739d991091e401f8b3d54248db45c20863a60d4022aab6d3b825f61a39105a26f2f30cb11fbf42bb238e57036b544881df3dae11adfd564a256cbb8e3448ee02f7e0c462df72514df0e6324b7bb8e71e057034d295a14524c460b791ed2f9e572a34bf9cf1059d466526f9fe48cab4f8c040345d2120c9e14169884216337e577c91bcb2d885a871428368a72b034a55a9b81874457d951b588bd9b7a2d98e18af17df9dd60da01187e52e0274576ac8ed790cb7e169852cd5dd18150ea08e10a15159da31ebfbdfa39ed7dd4efcd226b6b6891763858e320f4ed6aa56b96ce6e4db87c0b74110d0739a59edb5f43a60015ba63d9b85dcdc9c227dd9e830567b80de0ef042480e9ba615a988a6ebfa05b06a63648c5a88be3bc79218fddbd0466faff8d903bdd4e083b9c6c2800b43db7f6dd26ef5d54904c20214984d2670e06a76d5c7f2f7e8ce90e6522e3f4ebd273a6c07433f9117fae0355b3c85fa5fc300cb1a7f00622c3a522f356e11db2d9b06c5b019553e51b9d5964a20128aa2a87cb0ac733cb1faeec8012983f623426b75b94e29ccde30585fe193f98436a2512bd0be3ce79f8d78d1cc06abb233e7de1ea8ae1c059d9013ddc80f9a9c01b9b7de222a1f84c901d74ef1d60901362f5c52906ea94982d8691a29efbc4b167e6dbceba5d7f399c6cb65ad675fe2396ae78b808af3d09af840d374ba2bb5733e0191365143d5b9b11e47b1f1f73e98937be641dc43d88d844fb72bfab55e26195a04c4668c1606225c166a87ff2d7e4b435cc585a13adae99fced7192339790f3107c6813b699e9c6649c7fe951e73509af3284ef21ecb835fcf318a849ebcc6be0eab179f4e324cbfe6277c6efb2d73db7f35852bb260e13cb9603bc07d8575dc067148238fa79495de698c1817fda33a993c7fcecca4a8d517ff1d12e2921418c386f5510c49f70881f43bf02b3e248eb012d1ee27f2e759f43262ac8acd19d6871264481d01fa55056a42d3e95251491a9a573b3766f7d234664c9f2173c6cbe0ac7ee8cdedba40ead1b29bde4cadd809a3a1b83207e8e7b20fe0568c834a18363cd3738ba94b48f9cb53eadc62e111eb476843ed83dbfb68e37f6227306c750031f15b6481fe0c09a17754c0bd5d9669c6c7d3729f7e68559148a88ddc5054e9afcad4565d1e02a3fb259a644c1933d8ddb2509c59c4aa2c1979fda70edcadbff79f1f666ef310c760bcaf7447bc3b13c982176c1c15552439d01f0f3688495a7b87482c4c57224a54f2d2cf55f28e682265b678057943d5d2d9f2361508079977c1d2ff34aef44a4041737dcf0c7314779ed3bc086036c3c21613f718782fbe7fc40c36b17bf93f90686dd08f930c5ae5309f24a19f1955550d48e2496db80af7f414a0f1d013d08f802c82430a6126523b2cf437238609b4762782ea1153cc37b7022680fd18f96dfc1645f8c7b1c22b8ddd769ce7b56111bda24be2902b264c9da1fbe04a30beb8db4cb65691c1fe6c514838f01fcdc3e31a0f1ffe6e1acf045b9e97363f55b8eb1906b9ce8d065443ad83eea908303ae980bc7af2157430874994cffa18f4d8e8263bf18d07326948a3cff250f37c2f6e49dee9171f2a045019438b38c2446895696ac404f34a909fdc4b3682ba32c04a7528072f896c1836320b0b1b487a7a94eda430edadad3a015d31549f7037dcf816ad42be4b2d35dc1ffbb529d9bc03f0bb8679c8630c4ed78f32097c7857d9e3cf7d03d8309a18e3d24f7ffd0fb10d4ba3a569f938723d49bbe373f25ea8ce22edbd9aec5bdc737d2af6dca96a03d048f54000ac930ff09907f70e8a80253fadb6c1098ba2c95ed479409d015e3b7fd2d0a42789f78659d8cf27c8f3f9cf1e7f223132d7c3c2437bf5cd62504fb00ca8467271667b64273ab3ad1319ea948089b7b5ead9ec11cef63e1d690a0740b16ef7302aaffc8116b106d5ee46a5e59b7acc0dd5cefeecf3fbf018cb7f19c819e98713bf400d356e92f697a404d2331d74ac20ce8583acb813da9f480ae9a83bef2d6632d24d98bfdb1907d4334640b0c019fef216b2f2cc1437d01320f38e89a44b995a50d77a0936f340cec80490392ef3a9ae353a940f0d5853b1538bc1b8a0576abc1c50d607c0aad7b22697700dd88aabfde5a1f8877cef45fa00f8ece16fa084a750f1e240ff17045ce8a87d91d50ef328c413fad3300dced91db778a0cdd8a6fdab9fcc45c19be21bd70fdb9b7c3b3290789da3fe08a6b88afac6c0d06628f0e374f71da53e74a6e6895a1d085685b5f896c3f1a75c49605b270f9d5114e399491eb09bd415280f71dfe23aa91b3c09ddf1b6f7542149625de22e68ef8c2bd0c5ea7df1348131bb9f06f39a64313be3ac6b132bcc588771b92484838a7e79c277a37f1349ed9165ccf0f4908656710df7261f932b45ae1ab033e10a0c7d0f931f57876475f2bbb06b57d9f538e57ba75831d1fa2efe45bcc84d09fb0302ea45760da2afb9869c24065f0205dfea9095e5d64658d9fd1c347ce123067ea1a444901ebf52c2f90e9218ded968884b48a423b753fadc1ef70aba937820ed2f5aac1020fef4cfbfa6fce70c7a5dc42c4e5924cbbf1f880d71440708a6e7cd8840c0d6e2ff8eaa5266ef83acac024f73e946df49a6dd289561213e77bd470e08b9e1e6477e57bf2c5a65805702889e8924c0357f25bf79b8ae310be629d4b9a81c083a3fd2740aa7a4277423f80c3733456d1133c92f2d35d11274cea5bda7fb5a95990cc45db2d83d67f1025bef4ddde8e2b0124ccb1967036ac89e9d7fc85131af2a748c4aef62b6859afe10429c3b74857f36af746476b3540748b2ff76bf9ea330e85fbbf1d606086a1bc7e188595b0e704dfcef8a2a49ce1981410dea718d06c74c214074283bcfd21c1f5c2276c552bf1d0acba2efd51103cb82ce19462d50fed6d5021bb811a3ad87dd956919552869c3e1bd55f20e814c801970b4f569ca91d41b4b23c1118c4ceb1801021b6bb7317fd4633d279a6f4dbef98c52cfb1ba259c32ceff5afa6c74b01690207550f0057e544dadff05eebdce89853e0fc01f633ca02071913741cc8623bdec59d37db0ee4fe46ba84be18d500f2cf623aecd57a4a64c2a1f943d0713832f7c307308b0c12648f15b35c5260fbc81b60b86342e377318f97b1436c344a816599e34d05f214fd9842e1a4033e46f182d42c0e68503e3cd5c2b5230046f0ce1a7d8a0f2f21609c3a5552c056420b0d809fb850d7108466b7685ef6e27a0e59ca79701c3bf0691c8565ece5e1d0718bee6a612201206c70718f65760c3130ff676200457d3ee9bbc47432c22da5a02fa24713857a63260d0a3c3a5c02de08a48f269dcc917e888698f2db1d9c3645b795199069296064e8e76122032fcad193abfb9f49f833d277746889911d15b7b6a25838dcc524b716b9bca17d79428fe4b2b40a1efbf5f9944d5fd161e2df0107bc75aa75ac2c935152b963fd2f0eb520bd0bfdc62641d066053d7dd63a7a465e92c5e7decb50c4b1dafd775497c8908e5532469c712da82f962a6a5793e473602b4950065b32564e7220e8ea8ec4d13f4e17041a787feafd2d364d27596b364e2c3926c914eabcc1315ca10e17c65231aad71201d1aa20ba2bb3476fc4b21fc5adcd566fcf7d66171627752ef3f2b5488933276a775b448faf4c6b13037c7c47030197da231177d0e785f8381f06df824a89d53a74cdd86c315f71b4b6726ba43b53840f7806d572960ed0eac17358f32daf574a838fdb77a8972206d56917226e2ce1e2d95f76783d160b0c7513e528fc00334c2483f23a070dbcb2cf47a1e2fec9542fbfd3d6f2b4701a19ae421ceb606fc77004f610105f074d2d9acea1c296a20381d626fc1e087223a0de5ecc57c56002faf3422d01b340263880e65f88526676385b3e42119da4e6c8717707ae7eb6764b05d15c429d24a07a02d8f3870b0fbce71a69488fecbdf468d95adc00436d0f9e08584aa66b2fc8a0f52343063dc57ed4f00274ecb2f1ae2bc651b3572e62330ebb1758801569c6d65b0b56107a74393a8c7f09a2e4561dc21781ea220eeca049e57c18e7bb1a803437960570605c066fb38c2b111881fb84e9865c7f8fddd54ff5c9fc72cc10737202b23f912c81e43f31526171a550d6cd1fbea3685256f92a5365fa71788e2d25e5d40f15df147b79fccf047cbeaa5ae4bb9a23f9b0ccbe2552ebd51520439f09807638fac5ba4c2ca3e2a2399b07442a21f64a9bf3387c9b7cecfd3472b302d0242e4164c6bfc68025bd0cd689fb7c0608c25c853966b8b8bd275f65037a11805e44b2c8d19e5e37fef84d6f55430cb6a63a56847019031665a98e0e95209e65a3b740e871f1f1ff83ab6aaa3d52fade934d4a8a0f348f50a90af3b6824ba8068fba4d38fe0637f69c63b1b0b5233826dadb23e419128a97900027cf044395b5ca1162da9b5b2a520188183f886aecaf70266c296283a9912776bcf3dbac2c53baa7f5f1300247d7fdebaaf78aa70aa7dddb443ae3558db1939d4431703d6279b485d718b598193cfd1e44f4e1d78eac3abd28c12f246632e7f58645fb7c81fbde98c5a65c43088a0680607e01dba485200d197b1c28b369d4b9af3948721d69cccf6cf9cdf5abf2e4374791eb4ef6352804c4b2b70c68c41d1a36fe8125675c11351995c2b39a462e0987eade52aa150653b208bbeda6c16a5d3ba87a88d45589c452598b80cd54816f3644a9afb5dd3621ea7b52b619427d8613beaaf2ed45c30965d5a70ad9b5782965550cc3de25b484058b3d0693f6e40f8dab0a7b650a59001acc03bd7d77cf0551cadcb4cd397b87656ee3812c62d8d615ba60bcf65071ec6933fab42ae012d1d9d0dcd35a65bfc04ebb3105c82ec75bbd1d58d5a3fcd1651a57702705d4b9f11dbe1d9fa50da3e5c460450a1306ba1a4e7c049687941fe9682bf5d1244df28119d02259341d82efd406d843e3b3c05039d8cc95f5ee54b43cd0200baab138b2c391695da1a27023258a089d83a9809e59cc2483d56b234bf8ec2a0af3118ccf32ed1853cc29234943fa45821e3b0269f88a8f9bba5de11e2e43af4e4aa85865bb57b7333e6562254a92b3108fa30192c78b83eb9c56f2bf8d794001a678a835d74f8f2960b79be7da4eeb162819a4773572efe2a3fc72f2a89b8aacec2f783568706ca71541294e0bb27ab18448d48fa9902757b5fc3078b65fe7d940e1392388520325baeb8c870dfcba36d3b38c4625553b859f54a4b231c55295ba603a96c1ad68805a252e3999c1e43dd5618a8719f8c1c270038d11c8834c09c8a7bfc262218125e40122caecea42f1f20d95e7218f28a7ebf2814b193903e4e5054c8758b49d0c603aa69b4b79533444901b841b4784b60b79e8a73b520aa4b91c842484f39e9558aef12888f1d52d58413b84046a86593ec73ca4ed71f887c7d4a738840d39535da02a68f6259b7fb17ef154e250505fe2f5980468482c27e6489d98cb26fa19b3763f1a69c4949ebc20e077e4b2b9f8956e1bf478f091ecaa51200c8b07e87e0e8451f7ec033960072bbc9c625db2d495334b4a2fed68e8489bffa73852887c517603cd9005f9a79236ae1622672eab6deec489ed88dd317cced4fd16778cbe0dedff2cc1bb94c6b33e7819dd20c16e0c0c4c74358877cda1906104e93164ec52ddb23b14e42a23d073d949120410badf6b9c1651254a5ae121df17af12ea1af662d91881232508b3d309c0da7e448b8e49eb815a3a98f953a3e53788c8c2b4ea4e1fadc425907f7e714f0e586f7d9c9621fd5265f29a2a74a74194ff15ca3e0ad4695a4f7816788a172f8d6487089359b89edb164059d90d6556021abea0a5aa609d0888b882562ea163ff8935110365d389146be2032c5ef07a5c3512a229c35282bed36939b13755d4a22b52518ab0687572a58a8e0a8a56dfb287b7474f63b274109c11c3988d83972aa214038693f5ca2df5daef8648ca6d6a848d6b1428b080cc81339f2a08283a718e8b7d166c860d96eda39ff78532c1fa0002038e437a3bd35e647b6cc28fe70013c7ecd617a8eefb8a359cde80634a2efa9ce391d17d14b6972a0c8783a7fcb1c5c65eaecb4ff8b959398fa7bb297518dbb61a494039e08e9276f2107c78843560ca99021723c2e882b6d8d264302dbd58ca7b8543c0b1fa49f43df35096d5cf0a95e4f256c98387508e5f6daf864e985c717e5f25aeba1d4f8e722764a8463b3c489160f0c09f27a7a3fafaa841a233db445478ee23bb5aac87cb27c7746ce9030a8a7a49ecc911434022d02082c738b1cbacb50ef5b9568c40847b50c62018ab2ea3b46bcf59945631c48069d1825e43c854cc60eee4940cfdb8a9a660e65bcb3aed65c0e67986b087c5a235933fb10eef8fd1b5de8e1dad96ce2f132827f5cefe49fcce0e79aa85526e2145c5af9297d8b9d11cf9f64f06a0eb83cb7b5ad88631c17aa00a5549325ceb970fa6d02b847414daba9686825d57a9a86d20399dc2be25fdc1addfe30b968b7c021531ddebe64e14c7acc3242f855230c8b77590eb2fdbe7c8c00be043f96f1ca608f929a2adbfd044faf3ea3bae707085694ed975fb67eacb327366f979f300de01b1ec8a894584695d997a1d076a99dcf744d3d60c0891f5ae76b23c222a044e0e6bc5f7c14c24028775e4d12472ec2825d569c9aadd44d19363e5c1dfd1f49b33be2970ef43992d223fbb141d72dd7e0840a3281d09e46ed7751a8ad417a8348a6dbb72aaefb8c11240ac2021be18e367976effd85b3abfd9240065eed22927b4890d375c83be5db2b7106a0dfcdc47b4441d958cd9f32c8e495440815dec6934f4cc84b20dbe29d8be624acfb8039edac12619fe33a25d7d9f9819d69c9244377869fea116294bf042f7d4ab41d948b5d7d040c5e5f2a4db4252126b960ac82899a3469e6543b7ac5c101835dea5d9f6d8c98312da3d018e8b1657f1f8dcce85085b1d31de92ade7bff9bb236c4c2d13328a3ccaa386aa84888dc89bf065439d348f61e21f3a151ceeb4984b933b4faa3f2dbff398634944ba702d8a751c16a9efed01150ff25b426fce10472d3ffb575adfd21e8eb3c72fc90d56fd26c2db7bc5a32501b9e235c9f7350b1ad4993d6f7ee9078747cc5499fd5a7245627f5c999ed27279fa59f1c5040c0c6c2a560d303a10f19ddc7c2a939f71646b5a15a2bdd9b232479497ff32ac4884cdc444b8150b46f802dbd50ae00479acb0998f0bb85b5c849bce75adf608bf5b8fb9487ed10923a002e83c868cd05c61a8e3b6305bba9e5518e2e65e58e0ef3c81b726586f28e4fc3a41145a2b94892125c0b26a82cca409d208497264ee1be3b5c76567d84910369879ef9c440d0b0f6ac581a341bfa5814fd229d6c4cdfae933b85b8d2b9d9b6dd92d37890c80f303073e29d2fe31681a85e30aa0193895c299f9c00e87245720c8a94cd2105c4ffd8f3ae22e49fb45fd7f5177a3ed203fca1e8c5bbc7c51ac5123a72432acfc28a30cc50fe92b6f4d28186f6e731e2e9e5f347b1d39eb00006032949d51d642c0b4bd5139a59c49c7a000b98a5f37018c5ad74fc4444592b07040390dd78c9d1894117e614850778b6a86c32d4305010e6bca6f9a31dd36af830cc258bd20cb169ee06a2a78f23e124544e8807d96f02bca1fd26e0bfb518f547e9ea5b4358ab594568b1fe7f7eaa25fc5e372793cd07b61d3858cb443f3f6f9406721610804c7428fc699ac9918d9b73e1f7e3160ea75404d5b069f4a8a3788e54264e7a497071c05c5c473b40e7925ac888e933df961b12a370cbc7606d3410d7bc5539e4e577c5bf0b878d545e82a743efdbe283e2e4d799af3e9779f2716580540551ae08222278e6f43467ecdf74ddc892d6e32efc5a6fc349cbb4282744fc724548c5c8624cbe3ffd555a4a3084fea3f72e7fb8e5942f65084e0a0aa93b1f2b2430ca1cd5d6ef1e1cf869fe0310bb6b32809f21c3f482c22909ce23e51542e755ca789bcba2c7a5a50e41c6cfe5ad42c9347cfc4ad4fe2e0c2b17629325d9e3a994096d751f9978df0bcf397630f4c57547935d88d4613a07896e9091d3582d0dc50db5166e72f111110d0c973122b827059ffd7559e4314be226a212f1dc60085ca0e010bfe75a27a2673be913be3ea78e83db81a6f338d86f57f1feb70af7e4dbeafc081590a0329d52343fadf740dfacb2648af2ff2dea08e2a44a4466dadf524b651835848ead35c65220e9eea7a09fa8ac148bade6f785bb862b7cc8b04d0a3d8605531d186889ce4dc15fd68e3dc6cd72a06402b3c663821349c3d1b3e415e326774572a27452f890a0aa4e373fbd86eab20ba87a3bf1739f693de235c2ad189d185df4f2a0c1c31f9187f9fbd224f87a69451a1ea87d31e596bf02ea4bff672a4711e41965b33745d4ae16d93346cc83831d39391f146d3e4f9c93686fa828232d0105a14ab1bcea1811309cbdaa2b9ac75a92ffab73d3ed8db91827b9d093a472b1afa6229c0fc18e154347103678ed10b786cf430d98b06e9facf8b6157c63e2327913ec4842f7e899b2d59ee75371151697fc357a74fb2249298d1fa38bbf45d2b336c4a606896e54d854c074282471c042484148386ecdb801fef9da4cdb138a00729991a6c874139383cb1113201b84b0a65d2baa6d13d5cb743f48b873f61d0d2e526b778891b92d957db4303bf49bb649d88ee1b2ccc99dbcc9fec3fa00240b12b66124d2c1ff5dab205f49cd4db3c2d471be1e02163436fea193d18a58117f7e447847e848b6ffa34b791b770094a9c1ab4178aabcc6b5b34b96d7a19b9977e44ab8648150ff818404bafaa7e85f4df903df3f050e069e9e863d49427d67291c855821d4b6d8cce8de411d4d3caf3fc51e901f706d04ab045bcb92ce20737efa6dcf16803ea77898633b5f812292208d0a16964db6fc8ac903240c0a3ded660e7e3651e2f5b33b14af9e351b8e1d2032e25cb6d7cdb41bfe1f0c6bfc31a3b14de2b3f335f789855439cff453f24934c1173d3b9f67809f4d3406ed4ce9415828eb3a7338d9193eaa87557298c688deb132e0c10abbc19f29ff9448ea8b9a9d3f1b96d1c0df50861a4259c267e1f3852a2b4f30305d52f7fe4f0f4ee9e85e2133d5a1025f16ac6937712b3c89af4ebec37b7d43105431b503ebd4b1c6929fbc060ac4aa24b98d713abdf27b2bacb518d1af966b2dbb30295aa9dd9e72055429f8c83c4434ce71bb4be62266db8625cc7e834a77ebc22155a7cd94cd464cdbfe833c3e19439cff289cef74f3c2c07025760cbe6718bab1b13fe5b301c184261ef4648bd83298a07553e58691d0527921b534f31b8313178066a252f104b3e190530c9d3c2eb599ad769d536f86370e222e7f2875986640a87ac93e96988ec23834c3578db33af3ae5002edc5ef2dae2c2cee062a4aec1c6b2e69ba68925161dd094a0432252889c8edb2178ca9b6f31112ea41c0aaa91b4a6fd20d8a72303c3bac4cb609f858b71e067f01a6d030207a892aa09860d1ad0b594131ae4489ccd1ce0837460efb9ece020af26b05f1ed772912e0086b1d2c85bcf3a7e0b928bf451519880267f0fd58c482089af741f0629612139696d36da67e3065916eee476411f132dbc5140a2b56c814618fbed8071707ebf19de39701dc09b4103bc4bf6ed966f7988bf04e08ca5f70798f1638e47d4c49c2a6031d495059455af63052da0f8fb33dc4848c5f86e973911074e9ac2ecc9acaece3819abfbe7747fe376d968a6b93b48e121c41efa232788bc5a78d1751fa600ac8fbd49caf0d11c4ecf399c335a307a05eb42ea8925b34895d95eae0942d80008af1d4c2ab280860c376ae3889bd5f06e1d1c989e8bc20369c9f005254eabe8d883b23329947475b796406a6c92e4f2a7d35e365c8fd70b0a3262bc0a17c6754fa2e36f3566cb987f411b0ef68e49510a51bb59259df69cf524ef5f815541c4aae99399b0b7f8adaece0ab8234bd5dce5dc552fec7ef850d3ba1c7607b6cf0262f1cf5b0afd3dee0304aae4f14fb16b614d5fd34b732894c5068ca22c1d63ba6d47c13b0fbf0b9aae6b690d1f6a37b753b17839af4eaedae885cfc5a8e0ca7dcf475431070c51fe1a515382fa31bf928b8d1f6e479e2c7a78c608f1c467c1fb203a14a89ec464c803d129a845371a02e5b66e47979af6f04c69f37e59638c9d8e5595c74e37eff86bc43fea19082e3649ee692e2f66e48e111b47b03d8f97aa3b1be2bef4c0abf268ae90cdd224f2202e77e14f4f74fdd8b27c2a29fa00816d7c6c94f67e6498adcd7d306dc8cd1d534cfd5c57c5203ec323dbdaa1d005eb33738c583184ebe0a5e17ff800ddec491e071c0d6995866b329d1247d4d3fca5a901ec606991949f70bb63daf0ba4e2c6fa227f4cd8d0f1c42b7cc3983327fd184c4547f995018e30e78330ff6cfcb89183cde28c07d0f58e5992ca7b1f47caf44056ab7af0055e2c33d8187be96cb36431cc7fc858efcc5ea40ec586ce420c87ed1022c1347e7d9194c985225422572e5d241c13515566269a342de394ed6cd669a6e9ab859766251194bdb60b2019f68b6c0c5124975513083c6193434382e73eabb23ed72a48e2ba77fd30f7cf6ecaf013d69f101bc1a6c05cafbbc2a1fa17d5555bd0f8b5b2f70e8320e4b66420fb9916d11f00d42f9228c38426ca24ad6685fafac8b28cda21d676053835512c32bb66acb706ce77b4be01b01c9c5e4ca284cdc69b721e1c111a76f9d2558d9b750662d0801a35d1564a31b274ae6698087313361fc08b858cb56fb413dc07567e20cdea4f6b809ab5670c0c4d8139c2f85872d009ebc38f69c564b53eea1d562bfb982986b4996593183f7022f0b5f928ce8786fdcaae49f5f593ac9d3313855f3c01c462f483d55f42d2541d17bb36ab5f8831a6d186813f003a50303e5620365ad82c2268eb3e717029f714202865d889ccb5039b3959048827c44fdbda923cfcf91124a927531572f573e57cf2bd8a87776101d92b26385a784c650590349d93c17260431fd5670e61c6fcb32d3ffa8298b6f1818cef6d6a326e009b3b612dfbe6d570407e455c6e082a1c3877683591d2df5d2381d16d23f268a64abd21191457e245d33cb0f21372dbad324ae328c85dd3a3543c880f57cc46d13baaafe9fa8038cc6cc8783c5dacb846ca1ae11c65082632aac1f7dc7e31c2f3c87b592d4d8e6ce631092ed8248758c546c2d0808a1eea6c09a1216a332d75f1185efb26d5c2613e31b06fb3a4de56871ba7cb2ae9f48439dc1b6b772b4ba3b8f7c5d21cd92942d1c8e0d07e5142880883d237b4281dfa90e41f8a50bcf7922acfd02ef059513859621e2e7f0ac2ca5da1936264340413897c8d48043e821d613d1d9ad9e61e04a2a5f710ec56ae17d4f3db17a17f026ca70ee59e6d58fbc39ff9835eaf01c56401290715263599f686c71140c8e0da536d038e047421eed75dc7c67bf7f8955be4d582d97f7d7a717939001ab097b79c39ce975675d71c47bd67a76fc4ea907f96ef6ceac33c45da5b19c53dc102cf0ae2d7e9e42cbd3c8d9d51ebbb36bc30a3d710ccaee4a7443201cd348c2c6cfd29000f2350e9da5433b6cee557466fb44f7e9a2a363bb1c5f3dc0ee5e535a01a06ea2a6c3b3d3c480a3a1c6c1a5d9c505a23f7856f26a1959b849e9be7c3fad11a30fb0c9212c3f759ddf30c954529d78d9626c195017834e2ca2573b2d0a718a644ecb00cf36f2210699aac08d112ccbf81a6ce407e33dd8a92953a06d0e08eab328fbd28b823b045b2f4bc0499b024a753573815a3b28b487b61d86fc2e3e8b23d204b75e1f3535d1900490365e13767cc43baa87b89be045f08aa382c4e89c08d3d9a67ba3c36e84dd6203c09de9d174ddfee067794bdbe0731894f554bba42353933e08cec6f74ab8972fc6ef530d59ef317172f4787abab5056b3daf23bfa4f875989a6fdf4e6196bd5fafbf1f3722695e7d8189fad26da6fd4f1c47df206944598e48c05ebbcd6ddaee098d978f78a42b70e063f235fc655e5d153c1da6c7f66df961b49ce59ad3dd2a0e0f40355298c4790947614cff8eb1c5bad64fad2b9e454b30ada5b060cb95141950a525b0faab5346173bdeafd5a3530b86756a6cab547af1daad39ee634afe7faeb6fcd7a9c42b3cd26533d615982e7510431ac4147c67641995ae639a0be2e8b8549589d03d1f6e11d0d0c0e6f01d2b2a59474d170c2ce9064f740c32e14a4f6ad463568b746469cf5d59810cd8c3d246b8742b0147def463da94272ea2be0cf489ef447a095ab91f90937b67ca9b266f68a246ac2c7dde591d6c1991416a5169318a22fe0f193f1ad27e3f7a4d478a7cdf13b3401c7371c769983d49730b3a55889f752096da8dc330ca7135f1bf76a48b91f198fb90ff686d9b18d2e76ecbaf1e46c392dcf5edcf1e07c0f84e2ad24b89a5f686736fc4d39026de90960ca30999b5576805f31694db77e7551bac5d081e93091955f9ed18fc7a8bb21ca4febd58dc9718191e219d963304a41329540779550c0601523ea6c659c744ff1fc6a3ed1588e4e7038681a4c6fa8202e2021e5e58a678c23922d1930e8a4e31cd12d963c7ee73e3118cea8bbc7594a09ba1372bc2812207d789161becb08cdc328842ba3370b636b073918d16c8251db7edab60e9ef80ebd5c511561399ca991e5af27b94be20ce33f4408e90580ef440920c53657f1e614d360e1f02ac54f59e211ed2670d88975365af607eed40e781ada3a35ebc8fbb4f2aa8969c2cdf505509c98225eb3ae4743b245399c0dadfbf4c9dc6e89e31a129be3e10f27341d7fa9ff1a6850f9db0d0dafd5f7540d1548a413abe85c07a8b992eeff3eea733f4b6ba5e21a46951fa6bceb51936a36b1e89a36d4f040b407c4d8355f9cd0379dbb58b5cb8e424d730be62051d973a4914e71a178fd9a42488507788930f3a3e74f1e43f7bbca8d3077cea81a974658baf61e532cc03bd62b7a32d415b81fe4c0c610566cb08e55cadf0cefb14a2b07b9e3e7ba9f31712e9d5e16f6a7f7c2a86a3c0962905c78fbe1ce25f873ee39eb7d87bddccb0376ac9b79362378f61d2ba0cc53f10238a659a545aea55f5912ed196d8280c268d01c673dc9a675551048a8dc25f946987fbca24b7fecefe50e065c03428768a23340c918cbb72fe2c7663c57eb106dd12c4a07d4f6d7067a9e1c16a28525e270d57d00a1d96f4513afd078824aa4a5c811eb9469d06df8c3b5b8899d4b8f27d4312338c3826af09b3eb544ba32cd40f757c951e354cddba468e11df892fd9f8848b623e158be8292f11c8c1176e12fa27ad3267db02785c205c1e021da9e3d2cc1ffd6687b289ddfa39289fc26765939aeb0680b135e858ef23e553ca30e381e55702a4223a40d17dbd6289c42d4071b3a802a4fedb1ce745698884cd62feb58c7ffd88df84d713aca2280b85dadc590043671814f405b1d684794bbbe9e16b4a4c5122aed0cafc9ef3d8b36095cafab9335f2afeb7a890bcc881f5208d1fc47027241eac377433d02db7cf4f63ebe028d12d3fc4afd065d3606b95695b132d44181f56f14a8c976a325b9918fb0cd2d582bbbd90ebbb2ea68e46f8b603766086146759a01fd1b52acf4239a6773e69e0facca6f9beddfb45366d94e7c940aae37d9faf3ce6031df64a4407b09ba0f05d31ef36d37aaee063c226d05533eeac03059c6fc86dca3e05e820d1f823af2e3f743a42e74d0242784db49b9eef105a686a45ca48ad548e032e25ba628118f68ff3ff492ff6020104a1036a93d6855b3050ba9a0e6512d7f34fbee968193b47a7de584f25272fcab5a0d6d5bd1d8db5b5bb9dbf007312adcdc55594f1f52baa57c2b0820b08e4124c3bd13b33a91ae21f0df24fc13fc3463fc8b5eabdb022f9571be94df6de52ca94640a2308440886089e2765b77be3b0a176afbabb9bbbe7243323c781649d6dfbc89b4f9fdc46e7e4365ac3dc72e0e9520564be9c12874ee736b9c949afcb20495541fafae3cc0f3def3e7232a7dbe901c28b3de8ffc123c72d4803b8b90c921c732228628a9c94db867022c20927e593227018e2288ce75dc76d40a8e76c10f7285bb74759ce5f6e6f50e353fadec7c92f44210179cfd920f05b0584facd06a1be9b6abffcb0e57d1c431991f4b9142cd7a08c7992fb3c195bca6ea52bc51b7281aa8d44feea088251f59ee6538f7a2a40aaefbeeb3ef540dda76c1015fe200bd43dca0671e77df7443cebe22742635d9c7a22dea7ec122a40aa4ffd129af79e48ea57bf7a8ea168defb1368622eee04558fdd2962e9f227e41b92c44cddd653053c88e1a1828db6d1c01cb144115960d0c10d564c2ba629aad478203921c3131d78c151c41849e0ef6febe2fe46965346203c98a2931c60aa3fa33a6eab717dae8b7e24c1e5ef3e312e3fc7f49b5f3d8175f839c75dc041c50994e8c22486c73d2edf39ec619e9f1de6d979e6797f318f2a4961d424161e564c1b95de2ba616d34c06d0a4fa5377f759bb96739c0de5e7491e3c0cbab3bbccb0778d10ca3bc6073c54168e286aab0a51c31d2e465414f183e3b8bc04965918965e1b1ca3868cf4e342577acf17f51fb7f974e92a1e5554fe2ac8d41eb63b3c902a7f65b14fbfbb33eaeb3ee99b5be94835f8467327dc4340ab2ba623c8ac989e682f3d7ae038efb8ee4b711b9d72092462b80e061495ffa71d041e0834b0a83d7687870a2a57ae3b75092d4597777880a961aa0694f7ec91d0493aa394d4ff7408a98ff39715d260076378961db5f55c74e7ee6a624321a594746e939b93eb8e93296fcceeee5488fa312827f711c1458c189d9de3267fbab36a4d92e2756d713bb5ee80d03b67aaf4cb4112ee92bfe73227edececc814705c8e6ed87a024467c31053646d08d00910f8cb4a433cb9db65a5215c602ab3d1daa8487e7777b7d7498e67d1bc61fe307b983aa4e086497a417834a3a41ac74920d7f33b9cc4cdf37f3657ba4bf7f849b9f1e93edd6f966c4856eda666e37f3abe94d67b7148832d02abe692f5e58b64d5fcc67bec86cbb29270fea725eb0b0b994bce73f3fd735ef1440a315100937a9292ee09456ebe06f090c9147a376425cd324947a830b59d245451c84a421da1689b0d5146f78955adc1c6b16a82099b6ac4da52e37ab4864da6068360d8bca20c3dba5d840a133de8dfd901c1ff224771616ef396af7a8ef3451c1b3f2938eccd52ad8955149735c4dac21a620db18c583356118b8895c41786a196fa66e9464c1f60e86338df7f53631f1ba8296ad8fc8d8c7de6b35644ac304bce73e3fb594ccef3857dacbad0a8596d9b8defc63f6425452938f666c95ffda8296ad8f026cc452d35ece68b8d0d6f98587123631d960d6d3cdaed777d2c26d692bfc234d8aca65597e883f5c5ce5811d5d8d086a86d6863235b195d56d26ac64a5a15dd6635b1f272fb3d5692f3b4be9d95c4c558b59b56cbb2925849374c378a50c51837ccbd585526cc1887440d5147b3a31e6646b3d96c368dbe19ea08858a1d3bc6168a6d1fc7389781c6a3c9aac518232ba9417f0f8a785748717564a686a8d9d19dc910b76fffefbbb9a9891fbe2e8eebb5ca84199b43fe5a1dcd9510bc3a629ff9ad2fb7b9dcee8eb8fdfcd371b37387207e8f9850b42a412277379c330e55a5c1c8527a514d88b1e70f45ebc17928fbf47fdfcdcd6c168db69ec5f828215047a82f282ea8236efca616c5b48181a2ddf893a801d18bdadfccce1165a403f374fce2afa9b9b9e10fbfcbc50d5f973f7cdde63b6794da59c4458d1ff9a6c686dd8dded3dd368a66c5e31c4fca54cadd3d544bd4f7b33d123d983fff06fb449b8475e6f760a91f6f60d81f711e0ef5f3a3933894faf991a861aa9ffef363110aec13697e7e0598c6d6596b5db55a51dac0bf0845f545a2f8243a8932e739d2d9b0c7bc81c18d13a148004f553a5d019051e5fbcfb88e76658ccf31472666b20200a3865d547400a20a7611c7d5a62e621f9a58b9568d4cfe92b28b2abf8b542fbf08e83c7d027e31cf11254023fe4acb87d64dad71c2a9554ff5758c9364d4e94305ee72ecc359018c51fdbbc6451ffe9129fa70eb4dd103f9f2630cd887b3ae05eb789f807968bc6c2957b60f57f695d5876dc495adc495527a93f3d07899f250369f9cf94b3eeb9334ac37f94bbeb45c8dadb5b5b252aaac2c12000daa7f7f18694d57f2472210fc6fb538293b8f0c8f7386702770df7593b9d6fade5f5106ad21fc8a1fad6c59550338e6a4b3ec4e5d78dc53a7016ad71fefbbdbb61934ab5a43b7774a39c97deed3e746e3f48fbbaa8fddfb501f0b9d10d71e460bb03c0d5184c39b072b49494c8c85c4424a2c66ddaceb665aaa965ab580a10186060d303d6c3d6c5b0f33fadb6f1cd356a51f7bfc155fb6941e00a755414add9097bca5f78f90da10202e37524ba53fbae6e4a056c4c80ad1c9931bb9169f5099f96025fa8043bc8931c69fd2e387d0b019373e90bb3b90aff7bb5ca1dd108c334ae58b08be88808692dd6b80db2f7e355763f15905c62f865a39afc70ee8812aad1417d0fc10bc41f497b4309f5a17916d09fdcd52e1a81a322df7e0de520710c6e470b585f3299662d410ecbe72abf3c8761e98625073c01ebe835359f50335e4a51c9852d074e5f5569c4a4c65b542255392893e6a931a725294dc375598acede9c7ca3d5f5a5b9d0af36e3605fadc141b5c48e684a6a85a6076fdbd9734cb386e0f4e97958c9cee002e2b1961b9376c6e2d410d513526a81afbc4f7483f443159d558c73f9c4c5632d641f9d8505935f691cffd385767d77fb821aab6fa72fdb72f497426d7c3590b5fc63e01de23631b352c5ccd29d3c884158d468b6d3d1c6eb8e9883a421d39cf84825ffe55f8cce2fae42272e48e2664e1ce0cd8247145bb9161f1d49a375c67fd8083cba4701631617469ae24f1a6e317959671936c96b5a2dfaa4a83fe92a6a9d2b21043d344d3b4a215c919d47045e4b3e5444473a815dd0a2e386846349858c78d9c87a60cbffcbba0d18871747dc5e4fa37d1e050c3154dd375d415d6f19fae399d674e9a8769182b9561f21c6e98721a26325b9cccd00d67971a3e65441d352c5cd1901a16a2ae606918cde23a991ba63c7efd57d8a79b35a38ca4241acdca1337e430a89a9716b47094a38aa51b3219ec5d8750d1c08a0ae583175730a5aea2151d8f7378005ccad462f4856242a28f78e937bf5593ba626aea5162e8c72749141ad6354320a0a461ac9444d18d4c46129319e91d73dcf8f1c6efb18384c50d53636ef8e373441f6e5f8afa3704c1f85c0423926c8eb631dd2dc64823b673185e6226769a52a5631ead056626d29513ac685794ae3ca111c588866482133150d49036591aa6c16d8931626e2c525969ccd1ed17410479b732573648e30e611dffa90ae25da663725c301b536b4a1a530bd3e494e444a5490d6e3c31d6c573dfd2c36908a606ccd85634631c3c51435a6b42399d798f55415097552238eabd38825fd4bb6a84ee46b94698d77fd22e1f4ddab622e7e198b66ddba06cdbb66ddb469fb6c89286881a16d23177a34f4fa0dcedfb511ff7744b7f263811b33dedd2305a5b1ad3b0eeb7a751a851c3386a53f0a71d398ff7db53a486753642f1b6975f94d1595083dbfff456c4c1520de92c16cdeef6217dbadbd3a78635190df3cd492c52b24283dbfb17d460f418db4636a628b6f3197e8a5094ac1014657128426115109c26aaabc631eb70dd37bd685ca0f4779fcf18e73c4bbc4f3d8ddd64fedab8671590f729cbb4d6e0f6de479ffc85e250a86ece80a0a13a8ed268137da235eea3ef7df329ad614dd40c7dda64b4067402041ae6bf7d11148e348c6edbcfafe5afedb79beb35d7bfb24fbc6e7b785f4d0f6a9bd5e0f6db47578cb2ede38cef36efa6b425cc46c50d535b0d883136206a378c58eea6da6e1893ee168bed5b51c3c29451c3b61edb155bd1ddb629778bc10db72a77ebd130face337ffb6d7b56c33626d9392a40424c114345e070b3492e6ede73cac9429285ee6ed235d190d12101050caa05952ee6f4ec68e1a2f51cce65252d4d6849e2685aa6b0162c1d5b38e208094b940d090b1145444ce93c7669d0dffe50632da995a4a4e393eb50a8d73526b4c07359c908a7db7d38471a9cc14542d83aa2a441ff0f68a8f18cfda2c6a7e8d4a07750821a3f8c66bca96193d672c271a6a63e2754e6a77e8523a9ef6fd7759d9279b7d088dc6c28eff628a4db7d7f6194353d313935755f5bfaf03dcf8642b4db7dd8d3366481e976dfffe3fdd1df6677aa80d0b64ae69d5b6adacad15ca9f169aad4d842d4505e97754c62fce9d10dc51365dba4d69b5dee7caeeecc990da167444aa2863db29e1f53c6d8deb7ea2784a8fad9668c14656634338a520b7b7a8c8c66b32833a3591423b061b5d503758337df6379c32337857fe6121ab4407c6e4cb7a7fcdbf723a4c12ebeb794524a2408f0cf023deef6fef5b8326e51fec7cffbed0b81ae911e17f55205c443bd8732d2e3364c0a69b0fb7ebe101af46efcc0a186dd951fcbb8250c497d4d52affa23370524d1e92a89570a0752a9dfb6944dbdfca4ecc6121a9cf684e82a20f1b7a8da6c2462525371369fabe012332c72e9ab18f037ca38c555f1bd148312889152534a29a5941d55f259e5c10c363be917fd8c4550e26cfe94a1a45f2c226a7012c56dfbdb91a86133ce8fb2228f426c8ab99c74c3e8e4cad87c21254c1a0b0ccffb240e1a54666729a3bbd330eb44291ee7782ba9221d715cadadd6a3dc3d46971f51326ea84f7d38be305e1cdbf6010dd50be3d5f139787c4d787c8f1f725f37aae0570a07783cf7f88284623c78581b72377640769d478ee7f1b99023478e2f569956878d474f1aec48e4ea52bbdf9155ead9d0482a954a4d4f01f59bc731c618a35fb761d051838da5c1a69163c61c83c43e5b1ae6763e81ffe2e003f0fd8e1cffd2e6594e1ea9119ddd904eb9ed44a3d0a7469cf5277fe978cf3f6af4d15991dbc1eb78a902a2c3292c766091846e8c3d46feea1e3c7e033d74e8e0f1aec30ee9619f1829c6c3ca223ae5b211542ee3a041f5f762ece82ee78dd67558af0651e37b1d7cfc6c74605dc852280d4627f6893e931a7c59d086ad00580e6c5877d8cf86dcdbb02feb73d8b0af8dfcc97a9b682712eb748e1d2635c744caf14da779e6ff43ffe9d4a0530a0ef674a2b3868574ca94863de5f8e934cf34ecfb1cd626e16efcffd5ff47e3a9ff549e4cfd17f6d16da90a42bf70614c165f9880cc17454851e6fe57f3f1fb3b5541a8920c5a5871fda34a04111440bf70610c99ebf6082c88ae8e8f8f7862e6c69fd6f1a170e591c482e43c3c3a6cddd68dd68d0fb9dbbaf1ad1c1b7200b0d6de7cd84739fc699ef97ca8f3c94e270fa3865d54e4fa76fddb90d3615d1fad3f85b98df3dc3838ef5f089f907ee5b03f38c250def8c29c7be32d7faaf125894e49e28c2fccb9e144f2253feaa37ebafdaa3e8a4429d4179fdc7e2e34c2351a8b71c84b1df65cf6624576fbb68c75b3185ddc0e239490976e942c64dc304e5132624a4f4f4f4f9be124246cb8618bd25efd31754454efb252162f9baca22e2b65d9d242962bd2cb5684141f90639268114cc0e05834cd312ef4182759841243110b237f315704163245fe620e849e1fde0b71d2e0b6c0b8bf614485854672388f4b13a5ed8a2645a0a0891037e49668f2c30d9a4ca97159c9033d70351a781ec74d4abbbbdd36e5660a2eb7fc07a78c1d3d32f3ff7fc3fe5f9220ce6ee7c278db3233cf1b043f43b6108494d0b0f92740603e5d4ac63c132b75e292ef2f147349eb6a40bf3f50bfdb202af2831c08f5fd285bb932ca0ac5e2cbe69967fa459fc59a4e3ebc54d039ae7fd8875efa4268d3a5ef3cfe94babf021043adfea2743af98bbad3a14bfda5b8a5327f514a29a59c8be3706442808a187172a9d3a594525aa9ac6161ce3c43dfe9727143eae4d29c86f5d36f390fe5ba3003ca09c47dbac748632839ceb9568373cecf81a5522faa82208965a05e7e42dd573dd4577323e7bf759603f2a968b906a795f6bff52d9c6f7f0e866a6b83bdd35df1bccf8165c852971f9a56f3e58704c87c8e93614d5b56ba0287cb4a3188a2140318d86e6558aeb3d4a71e506d84250ce578638517fd6563eeee66ee19bb9bebdfedb465ee39ee74b39219b63a9b6401fd409c0bc29beb966a5df4a38bbedcbe21ea90f8d325b5614d71c8f11703578b1d15d40e5644e1640512655851a5c585921539d440b3020450889698bc289a315d218210644862aa8d200422598b8b32350097953cd0c20d1909457ba1cc86c50b60a8bcb0850b24665749dfafddc9f6e8ef5177204338a791e2401d0b5ad2dd60449ba51a7fce3967ff4f6f94a31da55b4f4739e9c6c939e7e4e426a99453ba803ae6df31b7414b626dd95f2c746f61f4b0276d5648c76ca0e0b8e9c80d916888da2350d428847584b89cd2850811f2ecc39b1231723b1edc69b57429a50f492b1edbb98d76bb945c0eecee83dce84643e0524af9453a36119d98fdc6cb1b84c795f65950e33333b781fe5ce9d71be5a2d334c384a405494b181bb5ebee34d6727d29d2884e701ed47b34baeeb5b65aff2078435efa711eeb6a40c736c9453dc186890d020d7a91136850c348a33917ddaea006d58f8042ce299554315693500912631a600242c5508030f8c0f5266020a68a20984060e34888fac49404adf3a823e6764b2266e05c0e15475752115541644f22f681d230ae614713cb449a5bd867fbf8138b2a754a941b7fe2d03c7f8011dcf85306f6f1237ae082b9c474e2c649c58d9686fae24d75dd1719ecbe5523c8ebd9b003f33def3a5942bffa8e090326e0003f5eea0fd2ff50ffee94949ee10e005c086579011143b4600c2d2a98c2c9183d7071664b193a70c142f3821d4f8e58925dc020bd890b64702f382980d00e2d28638316803082e249cb8b215a70620b2dc884e18211b7c5055aca4940a7f4d6944d943a70876bec344424e607f9382889b1c289d1e1769795c414a59ea0c2488b96f829e61f37547fd9aa20dd755705e1542274acb35de70655416a10bffe1ef58e9452a654a268fc7f3a480e1e6adf29628668636c368a6aae9b43254d4183779cd21421f0008cfb108424c00c8d8b420a1b6c1b4afe8420a48496115e709c0403c6086a60cc8020015b38ed80d0f3a365040593aaac9e1d10a899178e6ec8b58cd0c163256a6cb538ee5fc74b29a58c524a295b4a29999999dda50d3b04a83e523fd454833b3b3b671ad630ca71ade7c70e08608fcf69e1842cfe72a50fb7550c4aaee9ecd7a9bed3009d7272d167cfc1a02ec5218f915da073439ceb51d0aebb4761e6ba143f5c1ea118d72da892979e649c0076e80f6e985a1262e906d504666ebf6ca11eaa209a2951650a92140d012f9298fd70e603664410eb967406fd2174778d2622144720449a4c268361082f5d77d8e3767bb9216f690ed3c4076e7f3fd744edf6d7561351dcfe0fb3c3ed07c37071fb77acdcfe1e27aab8fd42a8dcfe210d63a5279e2e2fdd2660c4b01218302e2b813173f959041a17755341e24512cb78210e4931837ecee960891a2a99b3bf78bdfe695ddcd703d74d027f0f08413c11e356630293317c638c9cebc64baf54dd7fa23a9606a9233548fd8875a89cf98bd2b0a2ca99f3748ca22e4d22efc64c38358c8c1e6a2845b565605e7067a4c01c5dd5a579eed952474894ca2025831bb2ccdc1027c6185b382740a008051a368f18699036f54b0bf6012336451f4ae2059887f5343604771efc1ad69bb7f9307e51031b1f76934bc386e1d2ef115c1adf36dc59c1796e6ca4b56cf8362cfb2b456d6a6c08d2b0a1ce657dd14cbfe8479a6d32127dc43216609fb805ebd0a7ad43a8536dd8385cfa2b1b825465c37ed26a6a43ce9bb18975b61a135a082399db50380dd2ff69b97df2721fd7a8e16293f3b49cfb4c60128661f237f9a15fce4a06b767700bba1c67bf41da6a9089181b4afad14c83d446a7cec626795df4364533cde334994c56821855825fcc04bff892f0050a26e10b0c18e41bdab8dbe6ba396aa8b12fa5b2b62a81c7396145bafc2eefe3f57e341869d498d0c29306f9368965c4a8f4cfcb5f564082eb75eacb0a60b8ac4212bfa8a08cdb359ad4300e19f5300fad9ad8e700973fcef8397e1157103589ec6088164e6d757054f9f9bac0dba341fe7a005d355420d5f30b29816f8c32a4612aeb4a7dbc291b67277c414422c6dc38336a90bffb6294297116639c31cff8c5cf1d6d5839876d0a95267260789c53c33fb7d43fe2aff933e54aa56aecfc10321f684e10ee9c4bb154ecb0d631773eab617cc59d9f33bbbb57c07952fbe3bf2bf53de5863de5aa9e0ee1e552d5e4407ecd9fa86e6e934e228a82aed5baa3dc5163eab818c6be7dfb3fb24fdb8089a523868ec08146e7430ba49610d4c09331239f029c96f3fc6c91c344c2871570ddeab29297315ec45ce1a50bd292136a8930463421e5e82266c988198ed2982cb22c53ec0bccd096a60c355cbea8a165bc26f933f2d7629dd8de2cb490ec58c663e671fa7147ca2f43b798628a2b59c088114317ba050352a065042d20b1021c6a90818aa0a30b3d28c8a2b9cb4a5c9846d07a9c249c54a1a149110f35a8c2636860058b32b21966a075b13d512d281659b8d8c0458a0f28818403c81445a1e28726c260a28c46c2044c686819275a5d74cc840b588481c34c89329c5ec8b285062292a2d8528218cc2c50b4a946a5e0707842d229bd84d6c6c5082e555a5dd18cf1a79c5a393b3f682e6ba23a2951831b824a20dd10841b332c61e6054eb8400397253ac8820b148cf1928451162cf3081b67b03411c1161f12c892e50b185441a6c6041216e400035217677ce0018b0c282c2550d12f6670a5858a214a29a59452f24b29a594b239166129a59c62c5491047390011821810bf1757b297a51aaee42f9878310a41142c00810762524a296b7c01e60832375892c238c3c5c8260b96198e3245649951d352c4cae208285653906a600db162e6170254849999617c250f2dccdc6e8e4aedd836682166d24d725b86b618491e93028f2750b9f6c419a78671cd092cd7b9f644d2f5a766e899ebbfcd244b4b44f5fdaaef8ff1696c5090d09121457e9898b86683a84869816c6abccd0bc54276fad573acbf7e9a27127f6597ac3eae6cfc252e196e328ed5fc8ebffc3f88cad350a936b6ae6c10cdd3588e85dfcfb1d54b9a27529fc6dafc929aaf4fc466498db7798e853b0f583dcdcb9acf25adcdc7fafad19811692dd98d0d8a3322da4c66e3a34dfe7a9245a2d6ece65d2f14bbf11ca3f161a4798dcdd7bccd07b90d1b1499bec6065101aaf91a3628d6fce53636282822d56a906a6a3562fd303addfe5cf355df1ffb5dd312517d7c1791ee7fdac534c5943360cc683c15a0199ffa54ea550f947a55aa67a9a761833a657b46d4b2d4ccc6bb6cc60c16130d1b36c8c6ab7e860da20234e35536c8866d272b63b22fc4188d7672dda035cf4c35d635c376aaf11cab3183c6872eabf14154805a9f1a4240ccc68d0dba7995ca06ddd8ae510bea967d21c66c58da64f361d36cac6bbe500ca95ad7b4439c08c5e81315209b57bdca065121bafe2a1a90ea6bd82027f297cd8cf5d126ff195fcdf7e30455f5a113a9ec122a40f555b325d5ba805634afb22e22aba7f9950da28274fd89d0a71ab63081099264b29823f9cb3f68a863f559984ff32bff1f3a548ed56a488e05062b5ebc8c91c996b0606529eb9a76042993327ff9bb5c43ea4ba9d699520f82918c552dac08330343a34d4452b6b22ea0d4af3ef52bebda9e63a124baeeaa776d76086df2973f7572a7ebff62d4a749ce439b6813a549d78da0e2aa3ea447d725ad3ca248d7e527679fa449544cce3696d0ec56141ee7c4bcf861bdf3bb6f0b6a750532848bf3338242e2d8c6316e58ac490c78cf492d33a06df817f5294ccb75a36ccb561e7a768bd5f2eb9cf58324aaf431dca5d30d0a2959b8f014c5165562e030ceec30e4c529872a64b458ea7898d13f48199262036d8627b62d335041bb087b42b0a6050f44435900b14319156cb48b323ff01622326a52443943c6918ecb4a65606822a3ca1435a6aba46f0e313cfeb9e29cb915aef3c7ee6ee79c27f2abd340d791e7f5561be7f6064d66905842c20994362e6761e6329dde61b707f90dfb312074e3cbf9575ef95288c62682f666af7357ba46e064b72fcb6e7c067037f67c6eef8bdf7cf948b64b73285193448b64e3b7dc955605effa7ba194510a6612a3649d792309e9c909c4e79c4aa612ef3e236d5030a7eceb72aa80c8a92a41a8bbd3ba4610baad1aa15dfefcfcb24efc27db6a4daebbbb6503e13dc3a4bbe49c1b2fab3ce7fe747422b9f873ba9c72cad864b8f66ca254124466ce83d0acae9c739b91759a3e4c72a5656732b7cab5b6eda75b33de1c101ac656e27c0ff71f3faacb193c66668e53b04e24418d2a6a7cc9decd44c4f96da73b50832d19d4f82d316a7c3335fa0e1ef5c83ad2a5949267e3a4f3746ff79eb39d9321c71725b252da2a53d929e539ffa7552508dd905ee61c9f71e3f5d8443633b38f0737ac53ea8c1b7297797a2693c96688b90ffc621f24205d610ff8928024855f7c79c6fda2c7968612ee2e5dbafb94d291f8299f3aff5f67f7e7568be3a6fcfede305da8fee1fff5778e79a494538251762af497dfc489ec6e29653fa5d2298d1c0cf1caf76f5939fe66638cf1abf2a59472d2ef183d88fc3a6ac32ad31a575a25f3a9305d7ed944953f656824b6e2cb6b2432b5149e73df6da10afe9c12b74fa5fe949ac49debfe6f6755f0245189ffb42a70977d92748f440afdf9ace3bdea1bfa5893d5d37ca4a15f381fe5de1dc6f93e91045dea1a81feca8a990b76b132e64a8944cad0c7906040a87b1b2a77b142c6e52e41205df939200fc72467a5a8de55403a2b85e6575fcb5f72a6ba0f090684ae149a577d4d68b66715cdb77d9f03fa4bceb9cdcfb5cd39a7cfeea9b771db46376e9bcfaa05743605fadc9d2320d9a60ac9763110df7fc68fc2e37cfb64abc571ef3978de0e78a5949272b5e5eeee5050882af9ae0ad2b7633f735038b282f378511687765c8e6ec31e71fbd5c7314e54b53848523d40f59e65c10ea562aa1f9231279107d07dea8bb15601c998cabed06415f3be631dfd38669907c0d9d8bd962c5a620bf19e9e9d1d10f4d675ce88bb8dc047a06c27c4fd3868e80d061ed730e6daed1bb5d24a18bc1b59ec4c39a5bb0dbbc3c87e7e7e42681e14ffa03e0a1431a226d1fa38f0b2512fccc4e4b15d4eba711dca4ba96856b566060d968d1402dcf80f0071283e6998eb1907478e671dcf37cf1c4c019f5fcf1d3cf378ee9193d4857d7408b0c37edcf1e08367017c1f833b3ee7c3f145e0da1c1d8bc33a3b704ca0c7d76270c7b30a080e0578ecc8d981c2b59565e4f5a5ea11f0e3524a02f0490677e47077c70a1cecc8d991633f3e00ecf737e68d1b371feb060a77d639e7bcb9716327013e56bf5c635af28301ec781082d4e91a1f90ee7c7ae5d2e604f54dbf7b8e49da3d11ffaefb25a877cb4ea45bd2dfd9ca44b8253e871a9ca82f003154cfba80baefefbe3f045daff92ed710d49bc03122525036cefc35e7ff883e86c09dc99cbffc35dfbf4d6e1bc5419b0fb485a8372a23d19c33752792f7a4c2e39c90ce2efde2e51ac6bafc1fdc20a5949cfc204aa08da8842df645412b15d140000000f314002028100a0744e270382c18d38555ee0114800b7aa43e7c521a8a83519002290c32c6184300210000008821646686a86aea94d47dd2fae5a8e099cf943e81ad240ecc4163d2344f0f046306fef3d1608dd823cb868a8290fc286eaa502260f09406f3ab1abd058440d9a7069da3a0584dbc7e686abea4f113a496410fddb61fa3782a58b03e2f7da43fdf3b57dca6068a9707d6837c1f6cdce8155a94643c0ca7cd03290436c7979301e5ce36afa5f52c6419e3d3c46268aa4ef76458b3543eb6b228929aee9ae0b74203bb249bbe34b6ed8f97375899121340e7ccd22bd19f7aa8cb1ebbb2601fedf8edd77862518004f0e2c7f445c610300a4d048ed39f57a688995aa95ab8fc4497bab8f8e41ef54dffb48a5a72fd443775bbf4c91df59bfa943587c4839c08f48f7888fdcd2547259ab61e647c10f07551423eccf206c8dd08ff7bd6970829baa670eb69193bb1e8034d1f5a388e5930691096880448c84a3b3e621ca4dc59d91b638a648bfee6d10e0223afabf301c81153740a65acc6008ecf8f1af1437ad66c85998448146ae69c82401467e8159ab7806c3d245643d14ace1910f55fd59e5e04aae920531b18bb1fb3ecce3476af67d89c0f8696223e544c72f6c8517caa669942e72dc46433821e6109050c00c21188f7ac128868d4237fc777dd8a1305a8ac64d8b0507a86ac03a0744e5a369445090ea0c5ebc14da40459733dec8330ddc17a534d8be74eff814c1d1caaa01ae565f4f0a7f5b1fad680edcbcff7e94d543e5d7c4a86b8ddf9868a813ff4d1722f944dfb3cf93d2369ac96936bc970121bb39f75a30e7f7f7c7496d550b10987c360ddd3561815cef0d6aa077947a0bb885d630d2e8a540c584ed79093d7a49ecf30b79cdc99a4bc09b2717e12caf9197796e6fd1bb2972724203d21a3810ad397ab9fa5a852f366ef0c751697022050a1a86af4a7c5f1769679089ee9b9e52bb4ad0814c798108af197116ccb9cc31b116b02828a49ce4a8fcd5badc5c5778b85c8f5a766d12901b7dd870fc4e5b2d5a97c943ee1f7848ea24b51d9a5cd54eb60419805162fc7efcb699708e4702ecafcdc37d801561028fb2e4d150f12f912a176edf853670a8a9d3ae46066ea493a8e97495af4680dd6cc15b0d50fe005bc691b6ce8797dbc493674b6ace87cb2609d0377656207d09e8af431b39d3f6522cfe241bc4a1494ded3a6bfcdd7f9e96fb221173b12e89d24397547b31c8a354fbf82eb657b4679ba9f5be9151928f5b9f6cc54a1d223f42c8dc968a8ece06fcd6222cf65ccaee3c50c79e427d642d4aa8b27ceac544d692020dbadcea71750ba5f2a1c56e131cf65d3483d15621346c04cdcf842526315c16c97e234a626c20ee58bae1444678d9eef05823b7ede794ff2b881c40c405e0335fb2644ea75e1e05558971d292addd997238fff2c7d93e8c3c3499ef09cbe97e81b85f199779a9ecd84ef48471019747420dfc33fba2a7a7a156eb7551f21645779d5b43b7760c2b0b0a7b69f57f478c020dd20d676fdd587acb8eb042554e75f7a2a301ed15e5037c71242f5d8a751bceabb809671905c096c01bdf4d414ddd46bce4bf7c1b31308c483b027d0bd14a1e0e7aa114ea44248564064e7c13443fe8919bd784934f2f46bb65024bd9731e390468d6c3e15c7b63212db9b77a9a682122ad297abb7f627613a0cd8952aa4edb0c3fe63e5298895502d33a1c2c9d927b66dfa0302640773d9129087938140351b01149f96346b16b8a6be26ab2d04c925512e60a14af220759505fde31cb602de28bb89113a3c305e19b2ebf9389cf678951a168072db716dc9e7e123d5d00cb96e36e92a1d5c4de61fa785dde20879eb4dec50f077edae3a549e1d18807a0ac1a918b4cf4e6fa463002f5dbee7bcd54e5361c5953c3861026d2651c8bf930619a91e75a2e27ae8be85f0309952632684ffed1b9433b3910e44b100d7539ac1c9fbe62cd0e3feef363ea94a856b31b37928de39f82aa73cae8a4e64e0c001e4ee13003bb8714e8ec63ae3ccb50ba2d1b0dbc0c9750a2a1e7d038a3c1be1ed2515ef923afd64c41e38b58491adf14bb011c2c902ce70ed4811b84fd0ccf1d4f59f910ef4dae2e905861026be460722160c069c57df130af97142738d5ac2e4eede3b27076227e075cd9c61011de89acf46bb35f175b7d0a1a1d388abf1f6e9e23d83baf8d9f93b88281213b74878651c261323e94ba04092a43cda5a69228d9ecc15245614b4a1f0bb0520b1fe291a56602e9dc105f9012ca3330607375fc4b87e389de43e82aaff2204b414781e3b18f9f37839afc6be38a9b40bdce9ddbce5c744bfa8f58e436ffc79c5d44eedfc4c4eb3e1794f43b498feef1978f05f641b3c55ef23b027708f44e16805dbe91421b678560d6af7e8105d94b473366ca88438d88308014691fcc0640eb5e2b535201b8002a874a5f35dc19fd8533449248381daaafb79768c3887277cdd5b48b80c815bd99390628a7a32e8fddd757013e20b41f90955a202ceb4377ff0a4ebad4b944ffef54bc9463981164387abec2eaecf13d2600d42a94d7ab996aae6beb320535115524f79cca6e67f15f4a31d9f58ad6b19db02bef1cef22d1dca3f8ed344eb5fcb0e5d116f5bde1efd71f2be2eb0260f2aabd3d336ff6a71f463db8674d66db9166dbed38593064516917ffa88f08aa92b13c57c7dd26326930fdce46ad88de073d16ed0c892e1ee3559c56a7ac857118fcbac0f732be80d6e83e8ae58dd9ed805b6791b5350cb16da2208e81cde836057988979013f05dfd5722ce9864255dd2a5a39dca8699cfd53c78a7f7a5845657b056aa758cba007856e4c10773fc87826b69aca46517c445e73bb29dd990ac280242552da38838564465899516142ddc2fe75ab4e1528222cdc26c89803c993ec47355ccaf549cc5e8194a1f34f47f5b5fb31fa7a1780d393e0eb60b0caed8209583a36bbd16303f00866838fa293706ce0bee804d8668a048f522190a656e875687b54846fd7a9018412dedb4263c4a744bbccc82d76fe64f0d5ddc3faf1c1fc64fd7010e0fc824afbd9f2cc12e1acd21d9a57ea6d213c4437fd1df94459192474d1c838402f7961590ea4e4522a17ddee2e32d4e57f1c3c3bf091dfd2137fcda3045d184513318242df6b86fa15fec3a7178d40affa0df67172aebe6f212745f80392dc2dd561f42463720bc41e762ad4356397fd325e28697ccde7be8c3f3b7bdba4cd1161edea1e54a007ed4803f1a529cc68c5e15bde83af5a0cb937381a80899d258d57d10b0765c51a8d2883b34bdb4b46791fe156eae50d4ec91a35eb288961a97d403174099b540631084301d985fed8272d78b1e62cb15591deafb421a04a79613754fcfc2ad891c04053222ba0a2a7b37bfe43612de9661ecc4146a6cdc8b1ffe3d5f7c74f15662a84ab199171b3394db1cbe43fe50e041576762f7374d4e7d32b517c5fdec3660956dbc02858303e46e93993ea643d640976f233ca883a28ecd693853c8399833b29beac8b0a8dbb941941e160fb965dba9abe889367a89a8db2a737fddcd4f27d7f29fb61c3ca65e2b112d9706129bb6e955cfeae1e09691585b5bb806ffc49541fe68c551c3f7075eed9d9769a1cf55ed1026e3e7366513eb4af38a52699b308063c6b12a625f39bb19fb54abfcb978a35b18341bb03de6e3e5cb2dbdca964e30def322204e93150c56d12c8589c80cce3dee1897305625f6804e1d08a09e2d59ab2870acd30aadc347b6dbd528b1a3ba5aaa7bb10cd6c9b577d8d51bade6e4d6f965b936fe2650a3e936ad46b5da377f39f1fe51e2b5cc467e2bb0b38fab15125611c100e27cb243c85cfc11186b99843fa0e348d6837360eaa1b50501f3f8986559f0b93e1fdbcb3a86fb6a5db4890a3bc012641d40ee6b5f35486583286ac5e935d009923d72fe8172d926c93588bc52c464befbb692864567b8e2f2257aa4424c438366170d8f97ad31be0eeb22f70e744b69e092bf895b1605db392cd467cbcc1726f9be57a84f41adc924a6881d678338da92c2234814799de58a6ac5dfb9d565a46f7b12d502538ef1d3f0a429214f2cb54b1afa7caa2c8fec7b528689d05a5337ca3260b4796082361f9718cf84ff08f39fc707a2ae0611b1ebbf4f95353f33c83318533178997cb13993d847e0ad03d2923b0a3c50cecd675d670f3d48524a5afa283bed121fd7e4215c224223923a57db48ca24f71331f4207301460ec8f6ded41648995c963f0777e4f3f8885a8e3c879cc2425c4f9b39608e690689c9e49b73d138fa3cc94a3f39f0f87d804b3559f54bb7538548f7793b7914bb71f1515f3aaf226ef1389abae77c51c8b5039d08034476b1d81eca3dbc4dbd428eec89526cf5c7c807618f0434b4ef33b6d61e71b5a50be58bbcd5a4290ab7482e853f71f46bb88cfa2aa8537e7ac573b1198b414f3fa5b6cc06386aaaf33f1759e441138bb751f2d449e66039fa20ee413dd88311917edd8f1881b9f81135494013fa1809626f4839ac4dd139ad1aef2be6b58c6e99dada7f28806880363f07126c69f806226fcc46e2d1e1c28afab304b238c7ae91264baabec92f1349da7628f7971de73f42403a24558744f24928a13887b434181f61132a108bae013eb94ec0293bca7e51740f3c74708d06daa8253b6de9dba1a73680a37800c1ac216ffc7a7658c4a51477940df17afdc02d44e9bdb7f0eab722c52e399955ad437a55cabcdb9c23379031ca5d7d76099c235d0f8904ba33ed833263861bd156c006614351f4b7efd23780ed91c6bfc2350d3b3ac712cb96867088dd4873ca14f94bcc258477f4bf91438e9c5dfcf50fe9d682471193fcf5375653b103864bc66a9d63d4ae32b1a9a2973e0b2821bcd90f1949e1c6c8c9aea734d5fe97e8ff3edafaf079d1308d4315e726c4f180093fb52d03c77dbaf29456e4e88efe601b03f9784dd8fdebf61fb03e2fa22843f3afbb89c534f01118286b8d0dfaf1406bfdc799a80151fce7c2f326c8b992555e0bb1e3acf73334e4f3cc979b92c3c5ba4b320ccb7830120dce811de956df279d96742781e1914ee7834a679eae77fa8760b96032907fd0df52f58aa9ca60bf21f35032c7282c84fadedc5cee3c60eb2146adf115f83fc5311360d43909ea39805c2faa1be68f7968b0149e194ff85930e61770a836686520bd74490e0a188b94801c395852a9a2059864e83b8fe7c24efaa9d89c16b01eb561cc9172347d20eebe5196ee208af783fd562801190e2088b680124e301ff0f044a847c5363957e2cc3225e90a1fe60edd9ff64411cffca52777fa241f5881d66101014d7fec3c962e032b7b51392624f8519785c2ea05259525c82867b997eb79735f7d81591b2666f81d057cee468b917ad18a6211f2f95b8a83546d4f2ff6428eb00f55988cf38d5156eb17c262f41f251cffec49497f5c0cd5e00e761d4af0b0fa210ad45019aabdddd6f7a705690ac473ee3983808c25d8a04f06d201b1727f7df89d9e19e1bf8d5793ac1f4876dddcc9d7c1f24d8d0d7f31aaad98dc375cf92ceec1b0f068d67f0f7f4bd98cd869fa1e0462bfaf63d95e87ee8d8e4c4e457e14407ff2855bcfec525a0d471fc8a1ed70a7ea08b31495dabf639ce301ce00317d4d90b28de7a11d29b26cdf344a7f168587c26645adc87d880a744db7e6a607cc1113911ed3e149364537c8207cd7730a1e16f609376d351e22527d725d5d0dd3c0996d7ad3ca6e65e2cca56aa6303d5ad6a80ba2a87c09d90f59e2230e16a6a5824f3f6f6c667728141004408c1696a6151f281cd57fe0de23d3edefb8abc0a5a3db4ef063afaafb2e8c8d79237713aad7a384779df890744ba74a31d6ee29dc16f7d1a5009eaa26ce472f1d9b61e5a28543dea3b8b6559570175cea124750b2c4db8a58810c904f5694ced386672e7fbe6b88e3bbf9119626f23a4374d855549e3e2ffab2034b7c3c7aa99ecb4a0714441d344533427ba2257a147d58f4ba52f6e18173d0eaf747975b00efeac29201dc2294b1b3a6fdd89f6e1f0a6021b2908f952dfd9f1268a404c6a3b868653e513aaa2398a0742691a6de68baafd1e4020f21da61fe1c517c5007d122af5a4caa4f080bf757a043874cad96f265a868147f09ea99aa154cefa0570aa44f58f5049d026aeeed2f1c8965d8be8546b2a60f94f0e384a7499cfb3264207a280c00b7685a73cc2fa27318217b556c873562754ee373157358f58706d2efd5b4d559eb0fd9a9e51f7cf334832c5297a2f8720f14f5c049f9d2fb839bc201678a4238e1ab89bafbf3316a12439d1a53ace70d108cfbe58aa375f75934bef183520c20ba41962647c029d84038de992a456534081aa0aff3f4b1b3aee59ae2c66c8344d35d3f0515239828b375444b9913630c87b958134bb01d9ec46691413876458daba8f2a9d16374583f4a7aa35dd175c3819d0b6ee80081244a0e1bbbe4ff59f8e044490511e6788740b34266fa644bbe13cc88a2d3ee906af4785aa408f2cac2d3a53d3a82e3d8888704187b0a02cc8e4a65be66e870c77aa1c2f3e558a417c78bbd72692d757a12a444eb4de02996813212baada11f70f23d9249893146b92b551079a529a1d6441b4f4a9da036006b9cacef9aaddfc835c4b976130c831f4d077e540b0799b56fe9784d89ecc458a3fad1070d5e14d68ba68bc2a3f806ff97ef8955d3f8e62cce36cec9bd9279755aa4fd0c8e322cb0e0d1ddb3a27180f6109ca4388ae93e8ad0f80f8ba48b5ed3e2cd4220bc15289b7d99bd709d3a56d1080ca87518001a0bb2160e90f97d528989462251fb3b1aef4cc5470258b3154256054d8265f540f20dcd7e73248eed4d7499b19357c1e1c42c86170488cdc0e3c185e0b235d489e0ade7ed1317c75f084d75a2906a77eab811851d7db4231603a0f1e5e772a03c81b3ccb8e164d63061034ef7d180b4f3f3509c61c17f54a4b264d8e57fd247922c9c36ce467d857636d31636552497eec03cdc5475ae726fa7f50de060452f78056e7143442027e7fc8d16cf90a6b07779ba69b09dd37c5378b232d64ebe5aeb3592b4a7734b1b5c8b8b96f55d1d1bb98337ed3283a45dc4c5a42607ab3597282cc6d592ed8a4910577451d5d735bf1050d050f01391c561de96f0649af623e7ad7422ec35a66d86fbff8d93100446db440511a67d2d2ac83a77625f9389619a5b5fd58972f026596f8e361f12ed6aac713ef03a25ea9cafbf884831b1bcc05ece55bd119474a447dcdf49d4439acd4de383713d19f97027b2037bc525cf57a01009a19f124737e4c40f608bf88bf05c8ae3aa16f02641e803df6f3ddf42b91327f5d1608248a71ac68a845efe44146cb8103954f56afa1233b532c91cf4fa6393080cc48a927a6991296b254f4e0c72386a6216edb70fe0d685cb2b1df0e59301231724a957e04423e902c604994c76f8ea9bf67a1b45088d08c41d2e5b061ef96a186c73b2509c139ae65ae42352b460b7682e22575d61c1abe2b47192c3922822ac61e5190137c72634f5202b0798c46e8a7e2388149896d8bd0d6e5bc92af0fd431118659e764d01f7b2d9caa56f3409163c8c638db03baaabccf916f8e64fb51ec68f3b33121e92f2eb92125ef602589906d4a6d7aa6d983842b150aa628c56ab31de0e45f07291215f529f93656d931dac0b264f4e176eba6cec7a9de7c62cdc5f607f699b08b5318ea97511e6ab08f3d186bbff7c93f49ea8702bef8d5c70bb4514700929eb0a2fd04af851ec253943a7148d70b7a95f3af845c9cb9b47f66edfe5d8c3fb11078c990e5f6da020d06e6368871b967614a65f17ffc9ecd539530be73190493f7855e1e4c5237b06ef7f864e5a11e9ec17c466365f55e2f90181b7f8f90f4fcede66d92a7777ed2881220e7b18e4f7c90c0380936e75a639e8b4148738178d2ab03c9dc45cd0a7cb0a0f00def92c0747bba81dd8eaef40f99c368aed49388e6b0de2eddb32b0d719902c2858c9a4d495799faa21cf6a98fd206826e5529dc20bf2735175ba76ca2872f3862eb4076d461fa75b35da3db82c119eed9c22225b1e708fea5015514b42fdc33394ff7323fabc11a0610669391a6e551a06cbba3b630d5009115ccf11555c34a243dca918095c31a2a1d7604a0828ac4625c401f0a9257eb1b9c182887929b55101d410e713578e5f04360bc94f2d74a9cc9b006881b8aaf27f32af9f37b6994381b8dcc65022e704ea32ddc3b5e935bb89c71759bda014c4fe18d83455ae24f2652ea4369db98fa04eeba90a977014c378743fc841388d9363e3e939adb5da8bd5acceea7dfceee511ebd99d83370f2112fa62195210fe6db117a7dc74b0251fde37d076dc9065847c14f750f17802e09e01d56ae3d0d25295526ed2fd635a57b9acf796b87c7ec381ac80382e48ecb83be2945393159410d25715c1194fd261672a472de8ec42321051dfbd0b1e6a8a351b973deef6e657f161a3d65abd4934cc712d21936e6f9ce4c15519377c1458e54cacc0e8aec57a45ead51971ddce39f4c02114d04dafcca41fe564007a94bfb50389185a44312a311d3c1597b2a86e1ffd1075e0e02350dc2cde6ebeb3a33b0b9695e8fa09681f3f6fcbd4a32adf33e066af02c9ecbbadfaf2690a4c55eb26e69632d5031feb26508bd2a8c3add6220e98c42d7d0ef65dcfe53949ad2f4df0f6d02afeda89b4609f5601091b034bbfe2c4ee8ce91ef1b1c791a1da62cdcf37ddfc59c136a052410f8a7fce1893edc13906e5552e997b8676e7ab8dc892700a524d4bebc02a567df803a4a649d425fc3d4fbcdfe078844a40799e14b003d898c3007acc12b50eaf077afe849ba4a56cd63d52e6903c0c39f253ee3bdf9be50426d86e29f7102d7d19a16ac8dab417bc38638b33665a13e9228aac333a456b04a5cfdd6cd7be5c55976b998bc5e428d545eb8ed6fb1844032673b14fc8f73cee5663c4ea1179c6d4803c71ea4536536c9f6ff6e5391022cee2a7a8a26e5f387fa3fe827d1d3746d7780983b45261e892544eca3375e74d21de1c97bde9516bc8fe469aff653ed71ececdc592a8e93d99b72489cc4c70c377d1b48ae8a17547497750a2664e8e557e18036e044640c981a5db251f08c8f5466a6bb5da0784f25a038e3bff2c709fc5e8558f5e390a0b21317762294f1be92ebadc641835121cec3270627dc093823ba4bff7093f6c80fd2d6e9158af6ae431293c7263dff462ae912eb96b1e8357946e3d61e2d9e6c1754b1a668e1bdbcb0a6543bfe0ff96a1e83b31b364b060007b5761cb94d1edbec1f640529e477564203f04829c10f10e3c011222dc36a71438567c2a80db08689c8352ad3352676438106d98799c8a731285c3cc4d93ffe963691b047aa692cad3fd3e15065f712f6527440939f42865cb71c2e23b46e7ff40b87e94c6a470326cb9723e62b78ec0d70cb67113bd2bddf80649378e005075a6ea3f95b578b08f6ae082d83672ecedd08ea848502ab31ae062e9b838ced42b3ec1e6111d964919dbe421b88586bcbe7e81885d8e9bab67d905b043f3ec6fa3fd762370a19df7a719aa72b444d31762931820a41df4b7d9f13c8ab8f30d1dd143b7737184a38f963a8b8caa2857756501a3a754944d76014e552a7e81dae2d6e0da48cbe28d8dff782bd35f7d128d2b88d412a4616273cdb487d778cc2af0c4cf1f042621a3ee96dce25a6574392b3205eedb79f3ed67c383d04d4aea079a9c1cbbd8e5133617279a909b327b84cd35785ac014c4e7ec09c3f6192387516828cc641f6a9090b9299335350241553b69e048b903af4e237c54ccccb17cb5234146462910047d48115e9d09cb480fb4088198a5b09aff4c83491fef6f4b19146590f2c2e7c46dee44ac269eda1cf67698dde7d87a240326dc173cccac1fcd14ecd1d20ec261100746e5431016fedc295b01170332f33ff75bf6b2f8bfc97339b39c6a7905de393f68aed4163927e1335ce3704639cf28162c29c03f923e3e76e8f059e2b1360e694be7c8a42178f7a9728f8ea345b1010f60d23b3805200678041660a6167aaba9980b37f811bd9e557293072d52a05eac5cddeeb33a73e556573c13d0aa1141855e3c0dcc3323c58ed3a297b5e825be0c7bd7960302313bb49a77a343b5c7a9b8ef006cf6e970c7f9e2d6f018f341df2df5f83ca7bb675e29fb5408964de566aba67884a80036f3c5849cfb66b82b3ae4cf6caba3ab80d530d4658badfc321061a550800fe46614a52b624c391466387274fdf2b93606575ec274092830a05a2c7670d4274b4a2666629a1fc7d7214dd2d4656250ce51201777f74a79571aaf0766bd98b29e1431f89429c0aaaa6194a78fd7812a4b3a4a12efc5a881d9f8284693636098cfcfee3213fec48332e03e6268c3737557a1c88ac1a921db06751b4bc13cc8d66ce16d164a4fbddf999b9676dcc6cfdabb513a5a1c91845af90436684e145f42fa66a557a01accae11b51abedb6554fe8c42601010de0aac36e1eff757fe3c982186fc6681abaf1a9e4bbe9a1a2b71bf98d6e4338a08280cd1914bfa65bb834c9c727dcd89f1d94800296766c4b22d2f9ab2a92759a4e76ab21ef895039aa29634cf70719f6db2e299684dad46b474b251773e0f2166d8902af7814582dcca9b396b6cee825e826c852c9051a2171727af956e55fad047707f262c2247967b33fe580d5b3a83fa376c56158c33a09382b7d7c5cb226b5b25a61b6c9989313094bb35956809afde13e4bc3d1cbf70eab1ed241b6199db50e3317708b912e32a6ed0c12509eb5d144f7fbb8cbdb5f74e13ebb94c49f971083cbb86c3013fd7c5e3d2cd33eb854cd1d9d5b10a7b764205f6f23b918ae24a6994efba53745b0e98bb2ed0067f260da39986b5bc2bc258a857b1c8b08e0e3c7805ab3bbad90c6e66c3ab4ae73707dbdb169434d8c977c2a7db55fabfa9b3c9f52df6a24cd907d63475bb5d5b68c1e90dee67ee22b40ef31262448cc3cd86d44f9b9107aa23de84ed8b44a641721f4c02338b557c98e382c162ff496b0da5381aedbdae30b7eed73f37f8148f6101dd0db1c2ec94b655eaf32938494b8c20795b87605b40f77771062faa07e27e1aacab378ea484c2bf7724625ae1417c6a1cd9f58059f019f544de79fa7fb34b14e56164522cbb8d6914b12c150eb3b56b2e3e878ba531bd43bcd4c712def31500cc4baaba323b42a25407b516279049c4206521d6973643aaa2bea9c1b42c26aa53d04a95ea5ddd46419da1ea9ce145800b4e34435c538b325f38e1373cf74d55f62ebcafce950db8cc77b4d7c2557e5e1ecc75c100813133dca67859c9aa3baf147dbe6e3473e02ffeaf5762f07ff009158f8ff39ed930faa48d5ef02d15f32291716ec0b7ebc55913a7648411a8cebfe32f33944306558a75284d72c5e2e91b089f6cc6f06d17c07696a3c058b666bf82cc8ad4718895021af5ad0400b7e04503f23556d6ad01768462796a743b246992bc82ee1cbaa0213610c95f1717d176547fa1e9917dce15385138f5ed50c1cd2aeac699e6503015eea3e43dd102e4ab9f825061ad8863024e81b352fcd59b2bba345fce50eda201a48936c245ec7d4b8b7e3b9508a33747146ecb780a9b777205830d48c4de859240f869e427d1613c23b5d08b7d0a5f26f61707c25f91d2537d247de848933b5fdba4a1b15561ef9fdca43aea7aa1190324c42462c4a4e40186c753db74b3e77d9a333cab29760102d9cfda420167eb8d8ee31baa23d607fb9f63cc018199a3332bedeafb5e9101ae75cc3a3c51bf53ef44ab83e050141c2e34ed72ebbf8d945aacea7e35372297b0b27a736ee2d6b7c5aff2e0f7cca34597d6ab5adf21d973bdabee624bc6d6b8c491dc1afddda9e04efa87e670dc27f946e15394100d4b3da557a0771c985e18e95d87c88bb5707e79adad539a46857e3f315850269e1c04787f2abe7fa4f2d3b6e06d3d242154181717c370c73e1c691722735d87cf39059ab33e54d601d95bcf09090fbee7b82c34dc3208a0fc90b3df0af9f83334e6802023fe47c4e102bb526ec74b5390f158e47e8ac34928998e84be853177ba4a2d981e54a6c89546fa9dc219d953ebbcf44a4f3c11278e83bf8a6a14c712a29e433de4ce0895aab8a18d3c9b269b3378379f8df6fe156cad15c92b490dd28d72623a88ce69a1a321847df4c9b41f86650a9ad241654cdf367336f198b1a13782e3add4d25ef13ae9c40c8cdd20815483367815aabfdc2953177f66ba5929c9923e95d98845736459afe9927d18fe1c09474a67e18e19c06ffdd299c44672d497855d42c649cc46f1b18bcae75116cc19be0dcb93515d7b1351a341fa862938e571eb34fe2d487a9fb38a8bd8d76095427624f9db1411e68d8044dc2b062072d44c903336fb608abe2e2f5a09a4b46f10d28815c7a85fcebde45a338f56993ee29289b2e7de1603c2877bf5c4c18fd37c64856f2a96c85053c68170f8c1dc9acfdaf89bc03c6531e5a42111a34999b2cf37ba9337596f17f0d809da36c6c4a8b76636966b19b855d5bba5d2404879a12c60b8eb79c65cdd530f29593d281288b1c5f7240f6b6635079ce662b62ce78d2379160574ea8e0a1c97bb4634bc4d0f207702777f5be6a7e0d065444e017422b08377f9a9f2cc5b1f5afc558b8cc5cf8c3b6f8b6d9fcc7babbb30f1b14072f2673d4a03334863ce61fb0415cfc0ecef85a6c4471d50946e8feacd4f7b4fc183182f9550f6c2db2b7228ee58658bb75de9ff9e8683a216639787b3d0837c6b2009e2ecd979037786b4534a13158f703df37dae8c55548813aedc793fbc6697d5650715ab995ce4072f1d232a4cb666d31936040f8c75ea43c432fd6584172ab8d18bcf65ebd544d555a2d43293b4a51490a5bd1a864dc984c352d1ed1535af31531a17b32c5150f1fef2a39140200e3accf74494762cb7554f2db117cf01b3af0b447c272718d9e250a831363e047be1b0e40093a047e19c1b4b19ff578d18bd2b7220ba80015b611f374dd878fe9e9782108f9308307b6120cdd5d32844ac9e9745335d521ab810308f3d0a724fdac104e82eee0b95a26ce14da64e105060a0eb9a2e3aaf94017e5c654783d932d67dc4920b41e046344077b60ea37822c524297fded04ed38e55477d3ce142e0e5a354f66fad9decd6b2051ae862d79671bf0c6012028cb53360b7fa9c8d0436667c077cb36ffa2113ada8657c7ada76cb93fa5a4e43c1108e622243c982ef80bb2d01c129318f639ddd95f6a172de4854bee38bb960379436d4bc2d8cd19f71d5c0afd6a2e32ebe5a4a7abf540b9d9841de064e233535314c52334d878e6b62d671cbd203e76c4de154b04f07746b9401a873434cafe8783afe036aea253e2b2566c2ba42ac4c192ec7e4c7b0ce3d42add17f6d4ec3688f5c8d4034054d4ab65bf23ee806c2fa5c3fcf3572409a54eac8d3e402c0f9c8c701257733c784142e4f0b4a8cca80a0656f813cd7bb839d6c2de483829140cb82cbd564f2e37448a00d5212a62b66b07ede928982f1c8979c8419ebafeb675e2f578289f2c6d37bf105336a66302a90f4777ecfa6b202d7b14129f7205216c7e42509eda5a87f3d4add07a259f9b35b85f88d5adb9f0d3dc8be4c586a6daf1026a327bdcea07430a495d7e743557f98fd686e47dcd6d63e32c94ca738db704f0116fdfebe4fc521ffa28589815c769766ea01a40f8c31fcba380b20a2a99b0647ec874f40fb5102225707cb44831ac97527ea29a67d76c9fe690c2b5b0d5fbb56918d8b7a271b3dceb78808906997a91f8b8744248bb743b6dcd8af150fede201cd9378b685f75679c9adc1afa96729dc80e61ce197bb3a1e172f17cf526da73c65edaef6c2f6cbc0e7914a1dd1acbf0772de8f286e0551bd23054ee1a288413042348ea378d055007d886e40798914704b29ddf5a61f29882c41436b20ce3527c1bef98c2f5296d83e8c4cd93ab2f42f10af66f27cfec2f0c11ab75146e5cc524487f2dfd0cf0ea04a9b570d34e4ade2608c142b73a1bd2e81e584003173ff0895f6aa99443e5fd1bb2570a3fb5b34162bd752dd3214263c99aeb5ad02bb94ac6cbf3f5dd1346cbc3b75af8ffd7e223ade405c0ca962b2d6d09fe7535a0b64e07b59e669143fbab9a7d01c22dbda90620ea51a346d0d83035e84ddf2ad3d3a258db952a56e59204e21005272e3d58ae9414695804a885e1c87018b72aef5cb0db4da19d1c8c8ee262879008a87b4b43080f46bbd5b554c92b6696583140ad2268812e07147630ab0003cc5badb2c4434b537c85a8473cd457b62fc47ab4a64dd1be42e81107e5af22fb02aa740542d3207ecc470091d31b143da7cabeeddd214a7bca8a0861682cd52f56f54c198c81f15f9b4dcfaadbcc115024ccd6dfe2b6b95f7982ed4cc2550337a2bef741b20ef8ab0669ae2e488b1a0fb15a184c16a182cf510f869e9c238f6e76e4224fa5cfdc32831ff698159c0afb22c761315fd8015f05b4adec2fc643df7f79e0ade06f287ab71baae5d09598294b0be9a46f8697a9aa5653922f29691388c34cc43ed044040c83dfecdadb16bb3724808858e9dd0b26543bde0249cea128ce399c9488a00419c2843e1aa028a2c6af65d8cbbc070d8a403b9292753ee71824a6d4ce485db7b2214ee2119a87985eb938987f68a53ea00be0af0cb1bd8b3e4a1616e8eae63f9d3457668fe7a9a595bff4ad2011db8df45bed866bdeb972566f0b8a8a7afc2ccdf3325645266b55117fd0f837422511a56a945b417f55c059f55a1aa28c62211721a87a40e30c7ad953e348a136685930f4c503039b6419445656c5917a96f24e71ecb80f96304ee1601627b9892ce9bd647bfe7cc1132eb7cb28b800d6fefa8e95d5062d0c45c3379025bb715a5674563e345fe71de98822e326a013d5d41050709c00c1e8cbe2386401d878dd30513e1fbb414fd27a529779331a63c0aaa4cb80ddd8584132143c081b57d670c53366aa6ef368ffbb8174372d85c661b09ed613819922d87f7758ea9ea5dc41a6fc9f94415a29a0b4da1d4cae611cc0b7b87a5e8506cf9aa533d221f08010bb9555e85ac52878879ddc1204d9fe4d40e19bc0e2d0bad67b5c20b2001bfe7173e99950ee447ac7bffb89580fba506d8863b0a25e293aa522494bb6bf81cbf419c19625a3cf3c85a3c32ae42086a10f915c01d27d19da532bdb53d52f8406fdefcee89a630fb64b2a415526401ecda590e33c4a82304cfa976958d6a2c93f26e067dbe025bffaecde441dae429a6d3e1da1a94686aa5e35c1ea060b37857e9c2a87369671f66d8d31606000571d57538da62812a3f8cfe6b2cb68369739ddce703a9540ed79bd982b9b604670ca92fafc7e0a8df5ad51ce4d38266c22b2a14fe3cc9b6f654313f6265698e350e6d6a4769e099d7b3e0e7e54d66bbe2f7907cb9e5e14ac6421e12404c1bac0a4b8712dfc9497059dd674e039a23bed1a8502665feb37270bb44a408ae87525bab4a96c9709a5efa1d97815e087d5b42ba080eac6e82b28ecbe2cfdcb361497caeba242cfab40507c46bf445c13061a16fc74753f332e216c235ea7ac4ca014ebf830d524a53f5ce0e69e18e3396f60b2742e9b83514b249c8d7e624168c70b8d9f3bce9e8a72ad032f6876461e3db05cd3b74689a418b49889acb536cb68159e1ea77f3eb334c886f27803a13d5bae3bc024e0c942dce2b5de5ab0e4e58367fd12d8f508c66805528fb44aee6e6fa16ef2a2cd291eecb8ef4f629431f5f02c64ce3ae191cb2b84e7f8098265d55d237b5bbb0aaa0794681ee5cd98e40ad7dd4eab02a51d64a55a1e5355a8a40841cf16674fdf54bf06d42e9744e5744d50842735f53883a7b4ed8b3303d16587e413ee721a3c92e46c223dff1ea64d107ca45cd574c32b773b9ca3619e4a76faf64c6f1a30bb74effff693c453df991be7c2c56975c6a4c8d5a1cad54aec24b2bc1949b3292c2d42ec738c3860854caf306b1e5dc36566836a1bef87d0e58e274e0386b008469dc5e9093ac6d5152c2af5f756e36bd990a083f395adf13737fd00b8107c6cf1ad6f06a9bbd029cdca351770b4db51d30119c56809f4cca6326587107d365e064e7331eff77d9adde1fb6a76ac3c7c68395179e47ae53b7e65f93cb7096b5ff22eb8f32a60000ce7d8f48ef81004ba97380f219c73d9ab22ba6aacfa81aae6bb0f79742d45209bd6e42971e0384471f97408eb2159dbe8c6acd695a404e64175f815fc2cc2890c878266f1e954138318bd86858552625eed8d24c4484552c97501d6ba431dad8e9124498d126fb3a81190b4d839eb82bb3761658f0a3dc00f7f0457ddc069432e8b53d9c2ee86380697c698cbb4a0c916d1812913abada106bd74090bdce99f13b7b89114fd84e0a66c8d92d55684e1b97be40ce1345363281404e921e6796b56358caddb4e0d209de24bc627f5a11e3589c75f9c2f4d06619975c8cacdf2308353959920ef056e8102a36ddbba8779e711582b80ce306e7bf233d4da16cee5fe03651d9da519c2cb47c03e9c9fb30138e7c4d123d40529f4e834995f1bde21bdb68edf99039ba8eaa52618b054d678a6a75356964d7b9f82cc56463d4b80a97868a782fb33acafbe0823ca17f5456ca3f064005ad582d655eb97515c65c19ec5276557fa191eec20ec4d838b2e2487688167f9ae6ccd08e5827e4235f500d6212caa2ff4652d1a2bd2febd63c751b2a324a5206e96b86c7a20eca9a6595fa8ff9a9a114fd6b72b2e8c2e9ec6e51c6e397d5a4e201b64393771b30210b30ffca4c73b2ead1d1b8abb6d4351838ac3409909ad2b9a78c80e821e84429fe9b46c8cdbc8674a461957960f8a48dfe484495f783834ec951abc297fe1f50c13ae5ac53719a7c20e50d0073400747ff431a945909973aa6d974306aceca894b1e61c901ed5dae1c5081b49069d4a437e4d76ed334bc3a2ad1e90919d6e5e80f57e80d5edae85ba40fb81d758d47d4e5dcb9b17c3610083cecfcaa968bcd2fb8de2d802cf7432ed7d4949b970c22fe272a044841297422a8abfd13e3741e962dd773a044a32840a86a40788c9059feea250f6292eec0ce6b8988206a87f8d35c8d41cdf81326c2ddfe91a00ac400ff74a73b9614d2cce586a8384bd65bb797c937beca9b83a4ee50f44131fbfb8d30d6aff047fc3677a86979fe136cc52e214a450468835dc4e5b04a39cff84620951cfca1787ad8b7d12eadf0808e2cf0de82344bf478bd8695b6c44f98d402f4429d510e5cc6725dd6692b87ba1885e56abbf21aaeb2d823dcae71d9448375f9f51aec05c2929a2e6681e972d21758b4dc8b194eed9f026b5f7acf678424e69a7f7231697b149d22d1f46e1516fd32d6a3fad6a5b23ff268b13812ebcd36f6b5b174fa514ef97b651a7547d0aa8dee314b9896713f9081412d139dc115c8237bec79e9b9f622b31691e50534a7b062d6cff7d824300b5b1a07b7133ca77fab5f22b9bed4fb2f22edcc6984e283bfd03fe448566158649dcaba7372902d4b53bcbcb01435b646fa1a638825edbc0f1c978900f9ddfdb66b1e840b5e6bb6b6731ec798682ec1ce6895a6244c2eaa67da5fed23bae20762d961d3a88e42683a80b0461d9fbb2ac82c8388e7690b304503110e44e60b7cea02e1430e16ec574ad4e3d3be2f3e00ec840ca1ceb9a5bc08875dc91bf9d2b75c7fde9fbf58bbf2afe949f340d85b64b69dbfee362f8a76c4e5ce8da70215f7d4ef13f12fa6bf13826e228d5484f581414804711d64542810e159961e4f8fd0972d467cb031098b5f71e7ba1cf16068db1c0ccd51aa83872a89f4f9b40f8f86ff22cc14d5fc43022cc27c4747431c400fc57fa0bcbc2587774c9bc24805a5199a7040cc3a8654ce1c78258d0067bf76ea5810a37a9295156c623a945f338ef4ebdf750f746aae4bb10e5e643c1c62960fad960a121765cc2d01512ce4e84020cd09acd47f408b6ee2397d1f8e0694423f409959577fe267633b1f096a586848fffc0ca243f14560a0891912fe037f4af1a3c4d2750575beeac819e2942870579ec1965e239204d8310a1ec27c5a3ca125b3e92710d5360d91e5ca54e88bc65423961b82b01f9d86cb5aab765f3b7d76f2811c52338bfc21156a3b3b8bdcaa067f451c235a86cf511afa1e615740e1e717e0d20f95db3fa03fa86aa68ac4236d465590c1508969b4f775308239a5cccbcf978ebd1305c5ce5f86086f90cbc730645c2d8dabb056c7af0b4b4418a22e82f9f68ef359aeec8525105b1b8e51e53c6867e2595f82bdaa88b0dc2653400b46730a66656f6127d3a99904993f4c39eea5a043c266df81d594007650d745c8d43a18d5decdb7be312432b47c72c878d5275df5cd9942802c5ca045bc061183eb18b68418ee047633fbc7313d2dd52c40ca47b959090b337270dd24bf8a41cf3b49d666d1ea45cb5ba58ad2accbe165e455b533b7cfc87675c12c7cd1abfb753aa4c5790c5e9580ad912c122de74b34705cbd8c0d075e4d382c904b8ce912ef3760be6b84d4573a726b3f1e75c543de16b2bcee524807ec53750775fb4434d719cba7f297874781ed56bb8c4d163ae60b4fa837585c33a56938cfaa3db93f8eca055de4a595e1c5a18b0682c3ac615c0097196e40fbbbd31fa09cb0d31214565e305caeb5da74c685ba8891d7b5a84e4f0fc0fe61223c829b1520492ed2db4d2fda4639e780d743076660e7382879f238b289fdc89e46fc2f88517d2823d311358513ee0d33d9b5a36719b558d17680f214563f48b66b674b5f1e64d33eefb66aa96463c5f05c57a39902433d01017993f9bac37545ebda87b82d641f4948b7b3763db0908f93627ee5598e79d4ad3c8d88742e92266e35e031f0fb6a9e3065b9a9b81b62fbdef0440b76c846d012f836bdfa1d347c7f8145872c64a8bc3ef1474d2102f2d96523241a5a2080a59dee1380fbe81e6a856de326c4dd75720a816469c28f2e168a54b86b3d0485895ea10af0506b4e24868a406d62874d059300ea69baccf056170836088d62491078f95da4dc0fc26c14e8f0b8200720ae6721d66c7b21f3f33a42753d4e26311a31496da152bfb1372b504a82c9e3352b1e4f73d863acda4c5704e542675e98c6851349bfd8dc2650869c22595563e0cac07f142d0b2eed4129ebd8b9df0e84dd6498c59f48cba170747e0900095db18373539225b1576c10fa099ec639c61545d2398ac37ad641f2b4d856b8b76492c3141fb6cb5851dabf13f90580c79af3af21da19f238c38523a9fb232e6dcb03e5978e7041528542a1e7c4008d45f69df3605e273f1a1de74e3a906e6ad9916a95e388641fbac8206d4a892acced5aa62501c604853414f809ca1ec0b2cdd251c0c042d632460f539dad1e716986562e5bbfe3b02ab38ce2cd40abd52e8f84b1a0de4dbba28dd771263358a996450ad26e5f1b2da33acda258947046c9102a4036b59161e043eaf6ec14648a109fbc82100cc184ce8727d6efc13a7a26a8451f0972a1e7fb08cf083f14247ebe7ec2cd620a55ce7e4aca5d02da8972afbdbea270032c58a85b9541ea35ecd96920b4de547c85b79954872421b50659ef4827a9b8894ac8dd647aa485f2869f9ca1d8b5ce71f4888a360ce62833533c17e5bce9b2ba65afa092484f37b17c1f9733b9b280b8c806e7befdd56f8a0fa324f2320dec8f1fd80ee70e4a98ae126eacefed4a6692f47785ab143e9c191bd964bbf95cac6b791507b5a92e9a8609e8c39c3b0a76038e1be0f3776106ad527545e2e69cca0053ea5e4383f9220d02a4d9a19deafd8196b95506324027b6bca48c07930a09115b89ea1736b814018752fc11a34e7b29ca78b86e96f42fd258f1c6309fd9baadaba9fe82c0589b3eba957f42ddf89218cbcf5f046460aa5f4ca6fd28505e066fb0bf2ddd360459455ce10c824ee2104e02670e19912b0eea9959463c04db2855c606fb3c72f7539e4437ae870e0d4b49dc81b078efe34470e7f6f5f01509980ec309ff2208638e77235635248884b6136069ecfe221df77752aa94803d24ca2ec30c12537c5134267bbedf4461053322a27df149eff71fca96fbe140460f14fa73931995d8e37bf46c64e9b6e3a4c9858e3ea145f877a9619fb4c9ba344da54489b02ae89c3bdc468d5b5ec2d1454b5d03a45ffa2fc5f5f5b5bb432d1f3d86ca137c73e964bf6bee316d3e81a939b76c4ee1bdc72593daa9a69f7dccac7a5fe4677b03a1399747b5f2ecd4b278909046107691b95040fc6aca15335a011b2743a3b74cac73acd2de163c47f30389b174eb19127d002f289b5c25043e628e5b5f503c23d89ecdbb009c8db82ef0983ce0e7cff96234bb78e2d1a9a95452dc19328ae3268e9dda6ba2a48587a8a1e397d955d94b786d100e98784e44411590389688ffb26b6c13de7a69615387b19471cc66da60dc181b88ff614a34a82f8dab34a6cf45672d5c33de3618d08b5151eaba1685f382a9f033a5374b4bebc465ab529f68ca35162df4f2249ec591d1a7f724b589f56279916b6decffb3915747ce1f0efe9e3b7c5ee2217d2230a752e25cc778ec428cd079e83ad953b2fdbfafef8952ee4b7f69d06900a3ad79b107ec3af029a491f22df8c1e80a45bf63f4d19f4690c49d2457dfad0ade56486cbb2665fd4db7534ba4c078ce841917269bc5270f17984194a81f792c0b78de9dd05797970db57fe154dce080facda9daa77d0cf3c2f3071641a1935826891d31865546ddc0c21b0dc607b1e893653e85285ecd11617c2f6a53e4b2462a2524cf761b94bb4e4982cb4576e73f306e45d23406ab855e97703032fa1fb24214eb8887e2cd601a20fcc105ad5718732a939d17456285765be587206fabdcc46cc4cc33b94d4572ad7d0fd2c49290ed87b70e1baf6f23c6fb2c82bcf45aedcbd484b378d09351719c984379379585fff5e94f6424fa9c848758fa37cf3d44a6cf03a527766a6445d5f4d23e5e6d08a8632541f19f693c8b7272a8fbd4b06965cd19dd7999b7bcdede8b31a8ba0e580f440932ce67143c01465e4cf4edfde96f519ccce0f8b0d44df5e3e6c29231712ee2e1adbf41292348a007c90b462f3e4144222f446c6e14839feed21b0c986b85989f49547151e90675dd9a50b1a9a0792e9357daba48fa819a088510a76f50c2cc04585c24ba4b8fc02a8d6960a3c7c5824e96c26369fc488645b7bf68f55360d96d75a70c314972a25ec02edf244672d150bd6683e854026fcc193723e99382788ba4936900698b9313838ee8b32eddab43061b5f34270458fdabc7bd5735199d81459cad5a6b81ff8a61c342711351e7af5e417f936bbaae0b7a0b90b4739d8351b7660f182a88703cc27cc03f70b17273a7e306b36f54bf7bf993a80459b3010bb88f43f03591671f09711216a703fa7b3dc0da47d08230024830d073f332b21a41460cacc0989c092bad4878025844ca7c98756ffd195e44f983cdae0ace1030fc641a22549754c943b434b56e298bba45bdf242aa39dd50cd62d3c182d3603a944e3753749546855d276be35821dcde468458dc7531134f6cd32758e358b40443056f72aa4b486ab40733b522f3a69887e19c41389b624572b4b54305626d461c7ad3944f60b034cea38796b837bea76a164d5b31448f986634492986a881027119704991b1fa38f541e609691c5ea4436f4caf5b2f8da5481b078b54cfbc876b3b6a4e32e6f23ea64ceaf755f616b81387a063a2302836c951de8c71915a95567fb31bcec6f56582e9100a4e1172e6da6a19dd8cdcf4129c63593f77a063c305b988da4ccbf94e6caeae0cec8dfe2215dc9da1cd539e727fc6afe973c5514acd9350b839a9dc9834a5afba5842765bc643d42c78eaa561f0cb3d0eae0ce3a19ab22f05d39bc8d28c271dadb74d4fb75ca09e37192788147dea18346e627072aa98c1ee12653ad01171970f49b0c8c4b9e830037c629df6081165e6b954949e5a345c817d1c472561f82acbbb02e598e5c171a6d064d4b7896b5ac611170a8907e5fad243172aca22a6fb2ac995396d56848daed0365c27fc0754351d0113ad046a135a590567851dc1b22997d26d8f2fd831f5d57e294e11689067a01d0b2783ba96848a14df71d5ca2e5d0e075ee8279f2ee3651c9057aa561ed2862d6fd4c0ab11f276a2d470e36d6fe4222b06c2c08d4a56a24efc253cf40d5664f9f4f752db72f30f792ae577e03d0bdd155d9926c8764d3712e22e97c1be4ea6945f84a0c59d06efc1d957c3b9bc4e7a5f35390ce65919de8795b9b8fdab1baa97715199dc017978f535d87720d1e6aa2ae50a09e6e0c9282a1fca2509d5c23d697db13b105f070add2fcc6a71b8f3702393ae57be8c0074e13610d589e7a8164af6e7eeec85e586dda784873742cac4692b34645b1b3e08131db004dd3f3330cc156ffef26322192a478cae6741d35fe108decb0c78f61dd98075cc2a63ba6e2458dd4b5250cbda703fcc76edaee4bb85709e1b5c76b97b616ddce6f629c2c4eb78ec6f2bdf62e77138280fc6df33cacbed716bcc0e31ab9ec8025bb8b188314f41dc424b8826816b71870eb1c89419547f931ab94d00636f952acfc37e4506a4da92294bf012228db848fc5a2050710c163b527769e03c5ffd3cd0c1b05883ec73b48faa4351cb7666f8d2ba4eba250b093718d100d5db694f8a318796ccc691bad06f9b1646dfac7eab742cf6451880f397310744b157a7cc87a7f70b010338e00dd621513065b1f10896945103e62e651d12c54fcf349924c92a5986180be4d9a6fdcb08e187492895c63942d25fa518424d7f8877e02126c2625463db1e5fd16bd76022ab90648e8375aed018b1dd12ac9d0a826418093250e5501dc284a2eb64fafa96000ae8b426f99f30b31e5115ab6960d401ce6ffd4fd0784a03593a5c31177a05d627ea165f018912ced5e6f487f791638b396ab5b4bb29f10479c008a6c24bb97fe0ddaa72457da42fd761482aa394c1e9c8e9c16fe4cdfd956f2989ba0c37d7865701a886619ffee989a181a1210ae57ccb12c29e3ae24c62c8103a0827852916b01db3f225c2dcf6d423115833ec8b102ac02173fb4dde82e642e502fad549f575086dc2ea5011f332bf85ed860dd5558b7974e89a7b5ee525425e4c40ce86a814368fe874a12eb5361879957150b7fb0deb67a347302bd27ce094d32a67655168b52bf94392fded104396cd015c60267df80c30c0bb5b181a157e2cf97ae4ec382d98d2155055908295e38fed7967b4a5dddc11bd0b7c02af738670d3afd011637a9e799734a367ed730ba1c8476fa0469b5f201f35188e44b0d1d1c87dfbc1b2616320eab8460f1845da9ef5ed0d25e4e7649cc65cb5f659e3a6b2f02a1cb11e63840bfb0176b323636a486564d33d3b95e14dfa5b8ea98eb23a097848195f28b05334914366b9c43b1ca3c0e31324e1d12eb659171d9a87200e225f1c57d070f0d8012372db73dce99781e32b1ea4219f7410464436934725ac2b2e2c586fd44347676129b06a91692092eff51cae383eba9c19728116c36c663023021cbeec88be4f176705570f73be9cfe485a804b319c60c3a2633227f4a10db17e1207a8346ade2c4aa9283dbcb8cdd345257c0b4b4a72344bc0e74a8bff264482856e1841459dd9d0a6136fb2d50681d29365aa3723cb86cdd6124514dd8d0866912ca251bd4eb57b7b7db6d8f864b61cff08d5aa82bc8c09a3b0b4b0ce71e3f8e220ad9b20e26be7b6e3488cec1fbf9d3dc2d3fe9a9cbbfaae65d608cdae3edeeb0c277288792388bcce210ea6bca3e4d31c2b19dd1f55b2d2526b6b15ae697768cb740d48927f580561a001f87550fb6a51a4e04dcaccd8cd69115a98ce82f5886507bdcbb5d35764a567c45caff7bc34f46530fd907484f7853be03872f55b278ed7019126ed457cfc86b8213f54c6ed6c84141cf573c73457b2ea1ccc6c19ca98a2845e4458b2532129ed68c962c94f6f555931507907e5759f3b207735b71976700c942b57a6e0eda6f66f10f8b73abcfef2cbe1a6e1cc8a6a55503761996ef39d0e962d58b4fa55352b10a60dcfdb0312fa28ae9c2b298580501c9b4787f8d1d2f37af36886b7117af4664606d582105fbadb8c5c5d500a4e822325019ed349127c17e88182444fa38018b6baa71dcbed7c76e570340b76e9d0f37fab2bce95b60606ed8a66df3701e2d7edc6c170e3e1529a4dc8290f712f71d9201f4906cf58e4f6fadd7a533c4356c8c9c4c8546da7f8b69185216a92c45cc01c3d4123c5bf626ee96b95827504e19f55a8ee327dcb1341835ce068b37ddb3fbe5524b796bbe881b3140a27e135d77bcc03c28d10c746fc7289fb9020d266afac9ae98a4e12b1d7a588220cbadc525adbeb2df625a1666ab71e05bbec3675a389e521795f3a1a32d804c1e63d0a3099d5d7a30093bde1221c349f356fa470d5811a81b117823cb17c72cc971ceb6be84626972f199d32b9aadbd9cc8f31528dc46114b451469390dc621ff978b02cbcf39ac7de0bee2d3e0cefa95080bedcd6c211810e64d395f32ec79e70724f37edd5555864b37a0016c8a51385199f8157108d3505c02efb2c452dc8cdea5e37df38eaf820022b645b403b92d66b21dd2e4aa0086f5d0f5961398ae78df05a96c7e877e0765210f0130309a54c9c3c5359a13052084d71bc39900c760775f0744034e2e91e7deaaf17e9cdce92e5dd338a270fb034273bc4903e9f6d20c44f0681ca0317b69813359786c6ae8a1bbafbd2431e266b05cffc1e210120d8d04d7cb31638861a55524047221eadebfd2333f119a64939904bdd00f484bfb8a2860e4863c8d060eb3bc82ce87340727d214be64d59e614fa34d5ec7c8667bc3cc2b1cebe07637288946406cb243a294fd6dd6155037f5e8da1e25ad7908110401ef011ae1c51098ca73887ce3cd7316ca023b06bd7cc9fd87af5e41bc390bb20cedc06eb554382487528f5c68f2d369e8553b2afbb9b9b2e284a271c7d6b3517d73f9ecaaf35bd1ae9ef486f168729551c54047124fbe08a51daace0e9161c2807a1244e41d8bc82724040d2c025ed6e69dd811db0ee6e7ad523e2c5e2cfd901a3c14ca44d3f9b1cbcf54625097f734e3213153b0b3962f788dc4491876dcc79b9810b9224058ea3d1e2ad948fdea5e0e24a9c251c0bf899c4d22269061ad4b506f60a363128c880d44da81f1df08fd2ac19a7dfd9f70230e60560f62caf7442c21bc5bbafd91cdbe95e5dd48f6f3e646ec1db82b128a36b83af958e1d3e5f91b745dcce5d48010e125c48d7820c6c5809b29c462f40949f9c59de2f67a28d48ed7bf6c0ed4d598fc286be09dc94319648c83bc5802e1c618fa0820be5cc94b78f771e01e4f88ed48f65fd7dc3cf7ee225aa6564986cbb4d901357a099101b1be5552728cfccbad4809b1c11522f442288e53ad36067ab337bfa8d08db6b018880020b87337a55c8bc19e30e32b444d22ee5718256beb143d962ca92f16a37438c64c74fc7de0ae6c0298bed8f36680f760a7b805396f71ce55b8bfc06439ed0eaf79a22b65b7d45c0f56aa87506b4a5b53d6b6352bb5c949e03ef4cdb7b1588f4606c494fd596acd373ac24095bbc99c648b7433776f2782a0a4df3e221543638112b4dc51f802a8506d0c8a3a2609e60e8ef5e508dbbf69b83e8ea1a534aea99da5d89bd065e7df0ca1163fed6a54e662b17b2de40cb85c292878e620601cc80eeae4a6202220bff842685e90708913fa8f6d364a4c1aa4fb6d8961fc444a3ed35b0d1ae54ba29e597d44130d881806d8a03eeb56de1c7eb00a5ba14a5cf1b9a9f5cfa94fb4c1016e5c084480526a726ccbd1a7f8dbe11e1a7668212cb9853cb9bcaad2d96b2ff25fcb6c3ff892032d47f8a17aa970a9f354213c1d9c5fbbe2da0cc20ec70280735fbf35fbcb935fddcbd4e5f74824e610f9e3a3741d2e7800863ac7d7971640af76eb9be9e567bbf7c1371dc513dc78afe717425c4f9a2d403b1e06bc16a7813ef74cb48432431cf40bd797c2113a42d58e1fd948358ca443a52048e124d615e207883fa0afd0854b300869479468021d03b9a29536f81360ace7848d2bca47aade0cfde053c987349cd13ce1433c749c2dfc5a474267e4e921d3132a2d6600bef8b0d45a22bb3d723132002b941c06369a743e04ac0aa5b612b31d9ac2e74abda39472bc9f046f951010c7dfe12ff77fb99a248a7e7e13b1dc18a791e2f010569293043a8b85d4c8ed38c23b9e9e0b5059a04de2a2ebe07cfd4e05e5b7e3b9a59537c714b49964621f5f71a133683538789af51cd8e1a960303f16d49cb50a96478564bae0746acb8e5e6e94f83dcde962fa9882820146f8d68642b7ccf46f9d148257137516197a04a822db6867fa55a225f5f7f932fd3e433a65650bbdaa7c4db337308880bc05ca9e5101b053dc68212cf3ae7aa64a58703a1c0f60736a2c79b86ee7a1a3779676ec83a0bff706ccce9e3103373c66f2db12923681f506cf23d8ec0fce3047cdea31e826ce21edf41a9eef8b6e26bc4cd4a7a6b07e69a2a9f413b1b308288f62a0951e5afe80efe428ef76df9664e83aadd4d1d50b0c2ee62bbad3746a0a194d5be1f830898d81401ee37c8405312a4fcb1992ff8149cb351075d69cad2f4ddd6c6dcde124123aff15a7566b650ab296052bc3fdba49355af98767a07fcf0b29c24a60c52c0e2bbb934bc46565d169d19b43934a8f19d0f3f6cebc08d5be987b9505bcc9758b1ccc441e231c000802e180c870d6ba968ffbef50538e4d3bc2f0d79d11f2051aa9268dd6e1f07c518ba52de606ae9273277c9bf0d92d4d37519b306a8e1b3b20d9e9641a01314c0026b61f1946c811464441306280114b2d8c7ccda160c3c0c25a9b9d4ed4c764a9d3cfaffbf9407ece240eb0e8ecc418c54a1317c4cf06694a7b64ebefcb140556c4376a6c302ba73c4fa977a02396b10ebe44ff411c80f558ba59fa410131c704d842e80c7bae8754002daa243c6977d668274fdaead1ebbfa86525ddb845ca90b3bfb4337f0e5792d8b0f140c7cad252030e3e4b4a25a0d9ea573e89d7e81c202c9eab9dee5594913c9ff5c2cf5e2d619657e35150c9c5ea0b0a2910bf4250f9b91767671344f8d9e2fb60b2f909d7b8789a46336f441d0e2577ab209ed3848dcdc540311becfbfbf8ca1f354c17505d5673f7183490f0b6385292acf3facd446782b3de9d452342bc8855f9e94b5e21fba4207490d0f4ebe0fa8a4fa4bc256f4feee6f13c4a9766300f5546987bac3093aaf64d0b8d649439e04f6729e82c15e43ff867fccbc62b65f6626508ffbbfe0b031c541ba2c22603a159e6012ca75a30f506a863c8a1a57ffa390e68ae1236d0039ce7c12c97865dc75592d03e6d784a042e937438a2f1c2c1376e93d1391d97a38055bb13c147cb9ab5568b91959f7be54c061f8c87e7f47f59f7317a4754786f5510488e36c6eaa3b647b3dd9ee8f5873df2803a3398657559570da6ef0f926b995ae72961b8266ad97f39b8fa45f908b86987eca02d28acadf776fad336a5b1d660323943e29af0d98f7e4ecbe6b499776a143eae671925ca11d371ff13c8bfb2e86d365c85d39d3befdb4efff76f903f591285b8896a09b3e9c9bb225091331ce5191ed519badd9ecaabedda411c48c6f0ebc2853f7b9cfa996574529dffa1a5189baa0472718d2da754405ff591db49198f5ff021649fcb782cab8ec368be19c156d77870e5628d5e94352fa6fe63124994c55e93be06919881bb036473cafe12be099fcfd84f737d1fbe69fe1ad54d2e69fad83241d6f7314dafd508cdc2acee182ff6f6fe266f59d32a884d767eef3baedd5c53c2ffd81ec2376d613202e27e475f71ff79313f4e8c3fb402ef505c191364675c1bacf2f6aadf9415fc0a23eab3088c54388e09843c4825cbda9b429795e204ccbe5954475812ad8faaecc11bf1dd2919b65fd6cd8ceb55d518ff817a57f5f63726ff4367de434c4a88eb9a033c2529caf079eb7e72f768457ad1f5ad361e5fe56f29bd883feac832afad0a6a1fc4ced01a5a8fa6f30ab772f735617d9131e13e0cc7025a4e97da15932c6d914cb89476f3847432bbbcdce330d86e4573c2468f96d4c804b11b8d0caae0271974995aa2b3b80b386aaf12e1e10acdafc1bfe145632cd34d7f6851e47743e3e2e1546d26ba14a89f3be2059867daad0682ec76369c7332a2aef204fcd776b51e4ea0ff22ec6f8f0372ac5301fe63ea107be7fce0d48bfce3466abeba2d22afa6ca09bbcaabd60b671eec6b0a7ad43b7081b0680569557e4cc6482a3ba1bcd0cc3f85199e5699d79c79546f34f6fbc0dfca596111fd5511e6a391eed12665fe48b9383493a90c22e89c7074ba92e3de935ff90edd10b41a9191b95f194e5866dd2c9f5460a1d88f81ab7163b99c3714056c8b309821fd77135df8a4557ce97fc42e044ad7ad36f57021a2fbfc17b4da59fb33f58e81e8ea88a064ce00c98c43179307d60a4fc04e8101ce115fda669e12f9ee499777033bca7f756b45f2b56b387ee4536085dc3ba6fa3383fe67a84aaef7c833d39d3788fbaf774139538d62f831a4f7e535d3ce3f08fdd3bba198a94635fc81a14c0e8cb8bbc4bc03432ea5708d659f7d18b6c39f1bab977e5c2bf7c4a07e7725ed4effedf0c29694340c053e52411e7d32541224453a3d4f6010b2409d7986925c9beaee28d373c2903039619e8e0278ca172810008c7e4171d5a41c53417a984e2f528409591db7026af62dd3c10c62a3f20afa56ff7149739f688b875b86869f9edcd731d38e026cc9aa67a953a7099e6701b675d2c6a6022db4d30d610708ae674b7044f7eed55ff9954cab2ad55cc297e6c1939744f363f729ebf4e5b63799d45eabc892baf376e32f359d31fd1f4909b4e3de8bdc9afd507480ee93495bb14656d5408102017aab8c88c34c346b390d57ace73ffc7919a6619a4a895167fe1d642d38f4229a2e33cb5315816df226d83196bdc3a98c06b114ac9894a0bb2ab571bd263d7b0915d5287eccd1f710b4392cf0f4f3c98c6ab0ee923c2a142883075e7b30165f5323f88fce3afe0a8538c56c7062fb4d035d06767fb13d6361cb33a252f34185ed2f3d4eed5aa95f7718875d027b99aba3fe6efcf28c6537472879ab89c3dd159b1d2ce7e6898338cc64155ba15594a9ab9b058059b1ce6d892f035ab168913de158386873e340a2b473dc2858e055ab229961f37d76b19509d31e0314a871b9958f7aca994353a8d70937a28d1d55e8b1ee3105e1204e11e342db3b874ad2b44875be264d0633ed15ca283206f9f38bfa0e98db59aec0d744d04a2c34c4eef7ab803c8800741be902c62e6b2e02a38d36644f712260ce2f097f6f0542282e85ea0eab1320e65f5ea3437e79f0379812f4c2d935b3ed7ab0c92b68ddcb518c71351128eacde0642f039b471c7ce68858d44f7411adaae0db0911a82b3afacad28a01565caa4753305023d7f04e8f10d038dcf571b463c2d5a07953669c2143a172c4e1f12e649f8cd29586022f789a239e61bafef015ae5931d9df14cd8a94450fcbd7beeda5b2cd26d70e6b415f09a3bb60fb421cdacccf94869884a00be10a890db10a9bf015e4addd19e34260765dc00e2c1ae76366f59ce7ed6889fbc59de93b8b7a743b1d34ba4296b97a94e275dd4ff3e6c529a1978106f489045aaa3bbe551048cb6a3a84a3f14889ab8ba2ed22a4dfacb67845d981c730dcf277c44ee8a9311762280ca5d42cab117c17af9809cc849c9897acd00d6a5a1b229a1bf8ccac9d37b2ad7081c23ade0ecbdabddbdade7bcb94920cdd0b110ca50b2e2e3d0a7141f55bba681f8f2284d0b774d16c6c643d8e2284f0293b8a1082e53bd4a3f8d4a36a8e1e9b013b1fe451210380fc8baca057430becdf0a2c8865050579fb56149a65605084040b92829afa72bb38453e987ceaa87ecb5711925a8ffd7a3b614150f0717f945a64aaeac9c910be3dab7a523dddfe959321882e9a0711a7b7ac38bdf5e2f496eb8b9035eabca58bc63d7d26f541766c2c057b19c552b0a3db2edaaddea23765ed84fd84bd53fd5be2141539e9a2cd563fca45f3aee314b9708a6e7f41878b36c33882c28a4e330007feb9e3323805795ea754149b1bfd5076c2921cf1e50aecba8e6b4e82b32f7288611a7bcccb752639e6b8e5aa0c39c6f8ca37d6d22eae07d7ff4b514aa99db02ff50798b029b6c0e296ba7141791e95d22970993253c8c8e0539838c932323217cbc934e7d3e7a6701cb57cf91f610249ec4f3dfd2cd7d8e80b18b0000b2e3b88830cd8a4230b2e708cd142c9eba76007a09fbe337126a2778f2851b934398fbc26ad6ca922168bbd71030eac8005d5b0f10227ea188ac5829c6896e42022a3e90444aa0fc5dca79e76cf7dea83b84f75ff812108865fcfb951493deae77fa1078ade6f62504a1ca974415ce73175eabb4fa5beefc4dabd88127bbcd5f4a9704fc57bee4b759ee81d51e9c24fc57b8e0a8aa2bea3ddc5f179e7714f592c741df79d38a6fefb4e7dcda19ebd399df45e7092a262108a592c74cf7d50f75cf7540cea1e250a75e2b7e731b5e77def81ec79a2508fb73ef51ef75d4ae4a818c43d4a14f244f15b0ea29efb20d473a250170ee2be1385503fffeb4ec19ec52cd210e43dea0f30612ba1ea0deb3cb10b73937627c7e7b56bce21bee9246c7adcb36ffde366bb3275ee59a4302b5e8536afc1bdd7a1a8cf0d56bd6e9663a2ba78bd80e88636247ca048c82e6a8b43892d0e2ddb9d65c46184f7831746163aba2e8c23c66c5e47e607649c3a5693eeceef3a324c1bd7510fa9888c2b6494569cd8c1d2184f4858907490c6186330ade030dab88e7a70b0e0ce32e0404add9a3b06cdc98b184b63ccc460a748bef9ac267ee7fb9d22cdfc99b749144760acbcf881cdd18c556380c22204109313ca3881115c6ce8811348f8d0c653930e9a7a5005921757cc7801c68b7bea628e1ca2bac5c08b5a07c68b29381ee0a8f283d110618451c50eb44401061c6ebc6185185fece001718f381ea0805b41b8a9c06b7e82c253c1135b1b47402730516196a9a1be7062f5393ad0a157cf9d113978a38d9d1c287b32a851b0c7a67c3daf4a379d738e1bdbe09141a181840ef009065d19153ed59d65e4e00c3378ce31ceddaebe737e12159c043d993f6bcc1ffe1e373f7bd5d3ff3db852f9366fb825d754252f316d4a4a3c30d9456c83b962a21a71cb1e01c331bfe41edcb6e1cbdec1c949b7114bafded29d56976b27d149c9492f62b6fa97f09ea84ec56d2742a3f297eee4aad6551f51a1c70dc7d5167a9fe139723fc3966f68b7396ea80e802208b66f8594c873bc1b4a9c9387e33cefb9d6755c0bc29ec81b08360fc364e1e6253e1270d8d9e8ca37bad1eec177645cbdd87f7f6c51cb1fede21ff367de6ed56ccdcde96c6de055c9503d4646a579e2eb39b16811850fbc21f1cdf9434363bba7bb7bf16db08fc18db33c5b54039556712bdeecc4c66d1bab898b69038b0d977bbf7c3f8e5266e2a3eded77b3f36513d5c5ebb5d401e105b5850b252f8ab660e3861570a8820d22a00843054a5f9ce81718d43812a855150355040f211120b419be0516629a0083871d5ae09283ccd21a51b0e04a0a8abe2d46e0e418001a3784692329054c70f15f8c41c70ae0706248065ddcc0c17481031a2e0e25666c81830a1ab85186072cc8e6e8628d33ba0481032ec6745cb4f1c304dc463d9603f6bcd8d9c9c9411149615ce48004471e2a0bef7833d579df02ea53a8f7505d9d99de87df42ea67442adfa7a8809b45fd0b30cc26284efee8f4ea994c2f409901888913da3dea41d0033beb59f17617d470dd6a06454521263a52ab34fc2e41601784fa5014f2c4d15b1ccb4a0ff51c0a35f3bdbeefc10fc597b7e87bac4af854988462972f5f4a809f98e488540ba9ef514f25d5028aca27d6d45b014a7d10aafffb096b9185fa94c8ea3e8512591dca0acc0a6cc2780ccaf2ac9b98a947ee857c51a13889fae6b888aec5b2765dd7df75ece4ed61c13d6777ee7472b23ca722cbf37c04f2f7d664ff163a086d0a2491c52df8f7b77f9fe2ec0cc7e25c7c716210088a3dde9af341db635b9367fba1439d1bf7d9717b94b76d9bc7bc11b9872474a9e578c77695df43a45d25919e232f6ee2a69d0677da757be92341c6e2e7de0a6cb32ca61fc462107d4e149a40ce56d5637d5db7fe44da3569dfbc1e125f66f2fd0b097509f2ef17ea12847a7fcffb8fbef72951a84b4a6c178550e2745ad694e889d35baccdb23691c582bff72df4a7442a292a5f87e4e4c405285228a59476dc06442995d4f7bba5f23deabdf767c067bb04a5c4ea284bc5137d3bc1d7fdcef59e4a3f8f9ffc4fdf0a6ca6a31fe44f45a12edd0bd119b1f46ef89d18a4f2578d35353348451cc771dc4f8e732389537243061cc7715f33d3719f93032c97ebbaae73428214355ce1bb28d4c7819dfdee0c531e8628d403f9ecb124c24df5dbb6ce865dc731e011402f77869428eeb058e8e7f1411dc4bf23bcd38943e36335994f9fefd3e1f5b0b7a53bec438eca79943ef9fc9ee7edd19b73e92fe144d6d35139aec9f6ac14bc18baf7ae7da23ef9c26cf93bd3912732d106a3facfbb8d7167193850ba7ccbc9e47f823f9376cd32dc0073fd5ff087c143664e92c2ec919f49e7c2d02ebfce9af4f6cc980cbeb9f32599f3c8eb0ceafbcf77e9ab6696e6cf0c73e9f6ba34e7cef7ff6f6c175f1f72549c15fc89f4c8db2ff1df4496950bd4344534454ed6d9a25f698a2ea5515aa351a854ea3df5549c3fd4a73e10f529f0fb362e352cfeed276cbec7bdf72d74bf8954b6efdeeb44168c0aea3991c5a213efb9667b446599c8b1d273bab18f746466e62d3ccf5b347c70d5a2e325427b2eed717242f116fd17bc45cb39f6f82bf5943ec728c33ea09e308a7aea33c909a3286ec5711cc7596662bae4333720dcf0cedfc2034cd812be41f573a8f9e9ad0df42147adb9f3bfee88cb46842c783279d89b3d535a5182fa68c86261fb1d1f74f33cfebbb12c27dbb30e30611bab850f429b022906bbf18ebeea5d9c9ec86241f53d9e45c51654aaefd1e36f7e7b560b37bffd8dc8a2f909bbf94d64d1d8d58d7dd56af560786718304997f6f4d8fd665fdeeabe87ed01c5af13b968c29cb0ba9fb0ee3daffb42079772620edcd7cf61fb9a1248504bd672bbff78d817bcd52539a2de7c8f6f755f1a59623a754a51b4713b23277d46e4adaef39ab7ba779ab7ba4ef59dcd77cfabefde8d9c04e1bbf7a39538614e866ebec703358b05eeeb3fd978ece0a219208a9cdcf11d9b609213d6cd1da98e879db01a30c5460c8695584c118fe12f8cc469f01233dd2ee5b47bf7d2fdd7e10e18a57449fb518fddf7b037764c75232feab11ba244f5ce4664a57ec74f58a712592991c542addbd73c15eeebb7504365ebba671a8fefd8e87625cceaec31d5893b3dd2221eb6bae52d2e2729a243f58e1e54aa5fc1df9b4d8190a4b81eae90c34fbfcc7591294b7fdbf5beeceef4b62694099989e4a16a1697fb3890861c09b3c5fd16a230733db167f2705fd346e56a5c9193394c9289b78638242ec7097139ce87cb3d7d83ab714f4cd243959c092ef74c9ce49843e23a663a9d64791f7a419e18047e280ad1884233e20848d407b9ff423bb9873203442db99a9333cfd52ef733a80eed844dff3c5c3223438f5c8fdccf3051fbd2f7a6ef396ee501cefb3cef53224a2c579ee775ef794a5b7f6c7ccc71dcb672eaeeeeeeee796dd46ac197fe12beb4b472ddbbc3bc5113218420f367fb9df9c3f530dd30c45c16a374735c297d594d7eb05882e0d24c9ea699118129e7bf79b6b9134b1763f0f7b27b16bbca620cfef4c6e0af52d9dcd81e93a757459c6a4943337ff87dc8516deef414cc4b7244cbc950277262872f206ab9fa6e32c9096b6d93d207c3e9f2a740cd4cbc06930f3e2eb55cadbe9c76b5ab1cbfdcb9e3f5294ee49f13f5d8dbb6b1faf97b64eef77e37c28d21304860d208c109ad0c1ef4808c2bca0813421264d4f8a1cc1b4d6421c5f6c50a94bfa00c3030146ff1bb605fa5fa6ae79da93333343334b5d6fa4bfa561474dec51998a86533b5ca3e7f073269d7bc51e8ad81753760e5ea7c2013279be94938a69673e98949e7e7d0941ec3ceaff333b41e861f8a52faced0cc88392058bfa4379c0fe43336c74611ba3a3a51fceacc199df75089ce5b5b3d12d4f275f9a3099f454353fbf2d19524dad3e5207866b684979bb444ec969c85696a18fe0d7f49dff05fc8f9a12e5d7eb1d41159363fafeac1e76fa6768122cbe6e9b579fe21b258cf97f5fced46bb582c714a8f311f5688f52cf03363e98a14ea67be9ad1822dfc7fbe7b34b599bc152af11d17f893ea8439d50c356cb821f82ccb4a017c7ff05d64a5c07a7f1763e09ef5f37e340cce50c94c5d81350c439aaf6114bece45979f9999a7f4c821f8844d13e94ab3359f5fd52e9648653dce6f5ad5a53b5fc8ee00c2aa470f4f42532cc7befc4c0866cb751e9663b6c60a753123d28865f550a4495ec31ad62a965e3a0afebd7bf8a175a71ea77f9fc8fda58f1a4c8f483d26f5c87fafc8dd29d74651bf999c9c325bfc1e9377b5309a4fb689c4b1a2e1d941193148b8fe5c111ceab8c1758f070544c2b8c0e920e2bad37174bd0e1faefbaa5677e7a2e9ba3f93207707ebd11c2bf0c850828e2b3f48020932ce8095f5c270822c9e00e24a0cac0003f39f9c0fb8a04355aa7e506b95f10314ccc1c51bea66118afadc377341c746868e5bf6d06e6db1dabfb371771ddfdc29671847b783fccf573df528dac47892e8bcd4cfeb6db39bfa0f678d9a527533b8a92fc894411068d07688a595bb0385f1e214ad514b170d096d0773eca771aaaa6fc97c68f387e63d4663793c8d53db40b383d4f7a7bedc89a5be6cc9544f5beca69e47a55fb6787e94522a1e1e43c1c7558973f294b4e8a6fc6e62b9d9e0b5fc80d32dbb97619bdd1d3f43253bb6fcf820249061031a3aea8e1fdfbd8bd6aed4ffb02e2dddea77d160e08921c6759b584a543d9d515573d8c46c86be1d768bf829f13f959d41f8dac83670a6ea73a0cafa75a3c77662fe1c33ead73ba020054f75c03e9c09c2e38bcc8acc402c341f5a1fffd1cd7b07cde561875cd6eff820b688ac757172bec8ece6fb554f37aaa79a1d3e688ccc8ccc8c6009224208eefe851620331842c9c9204fe4aafe6b30a6c3123335a6b089a99e7a14f2442d5b32d5930821b88c5ce112bf3bbe886cfef0f846635e107e4e1710108acc788ce64fea8b307d3c2c12dae4e90782468f1edfaf8353f4aa2714746e4afca1d5d2088d074f4a4cfd4e4c84d8687f18fd08627f20f90f25fb0308131026275d34af56204c2ea875de1b9d1e3620d872b3e1962d59697305c40155b66f9122b322587aecd4abfe13e7509d375544cbb545b2cc11b400759d412d5d344e9a020b9a8bd6ae949676ad6aed02e1038cc463b0181c06836130f80b36011fb117dc0573c15f780bd682b360232e0163c157b017b6e2fb492727990a9e82bb7014fc046f61127013bc042bc148f0115c0413c14270100c048b807de01e78070e01e7c038b00d56a880606c0955e118dfc043ac03cb9807bec23f7cff0f8f80b1f0104cc44670164e8269cc046b6127b8c6503097ef47527392a5f87e24454e72d1f723317292abf87e244748904e689a3f3dbe771e2709131535bb3334473f9b04a2e4ad2f954acddc6ff3ad799b5b37a37a46b253fe03d603cf63d80e3c8b616b780ec372e0198c95f20c86ddc0f31796866713d828cf477686672fac069ebbb01978e6c262e0f98b95e1790b1bc3b316b67ccec25ee0d9c842792e81b5c03316b602cf57580a3c7bb1303c5b6127f05c8515e1990a2b81e7223be4790a1b8167292c91e72ef685672e96e7390a0b8167286c91e727ec039e6b7684e72dd601cf4ed89e671258179eb558129e9bb00d7866c296f0bc8465c033cd1a7956c22ee039091be41909fbe4398b3df27c8455c0b311d684e7226c0bcf44d6f54c844dc0f310967c16c2063d63b1afe7202c029e47607d9e81b007789ed99f671158169e7fb0489e7db04e9eafd824cf3dd8159e79b00078dec11ae0596603f01c025b80671dac009e73b02a3c0f59a0671c6c0acf37d8fb6c8325c073ccc2de8a6df255ec009e8a65f242f68407815df22dabe4478bc2a72ccded618718d1d2631ba919a1f56884c648d603cf63d829cf62d80e3c87616b78066339f00c8695f2fc85ddc0b3092c0dcf4736cab3177686e72eac069eb9b01978fe6231f0bc8595e1590b1bc37316b67c36b217782e8185f28c85b5c0f315b602cf5e2c053e042bc2b3151686e72aec90672aec049e8b2c91e729ac049ea5b03ccf5d6c049eb9d822cf51d8179ea1b0233c3f6121f05cb33dcf5bec039e9db0243c93c03ae0598b2de1b909ebc23313d6c8f312b601cf341be45909cb80e724ec916724ec029eb358139e8fb04f9e8db0aee722ac029e892cf94c846de17908fb7a16c226e0198bf5790ec2063d8fc0fe3c036111f03cb3489e45600ff0fc834df2ec8365e1f98a05c0730fd6c9330f3600cf3bd8159e655600cf21b00678d6c1023de7600bf03c64ef330e5685e71b2cecd9069bc273cc0ee0ad58027c157bc253b14d5ec82a79105826dfb228fc68973c08d6e657f6e65356f53d6ceb0219d363036912813019a1dd7e214cd4d2452b8130dd7e2334275bdf6fa4e6e4f8fd468a8c18b5641fb045801c7d3f10a59a078f6ed70051ba1d53d9224c37b6c8181b5ba40987561661bafd2e9a931ef87e57cdc929dfef2a72b203dfef3272b286ef771d39c981ef77213929e5fb5d4a4e6ee0fb5d4b4ed2f0fd2e2627a37cbfabc9c919bedfe5e4a406bedff5e46406be9f8c398981ef27654ecaf0fde4ccc918be9f2472b2fc7e92e6e405be9fac3909e5fbc922272df0fda4919315f87ef2c8490a7c3f89e4240cdf4f2a393981ef27979c94c0f7934c4e46e0fbc926275ff87ed2c949087c3ff9e4e403beff1573d201dfff9239e9c2f7bf664e36e0fb5f444e32e0fb5f342717f0fdaf9a934fbeff55e4a402beff65e4640bdfff3a723201dfff427232e8fb5f4a4e22e0fb5f4b4e1ee0fb5f4c4eb2f0fdaf26279d7cffcbc9c915befff5e4a401bedf27e66401bedf47e6a40adfef33733285eff721729200dfef4373b2c9f7fbd49c64f2fd3e454e2ef97e1f232751f87e9f2327957cbf0f9293277cbf8f929303f87e9f252761dfefc3e4e4fd7e9f262781bedfc7c949017cbfcf939301f8fe9f989300f8fe1f999349beff67e62492efff2172f2e7fb7f684efa7cff4fcdc9d7f7ff1439497eff8f9193aeefff3972d284efff4172f2889341c421d5ebe0c1847cffcf929346beff87c9c912beffa7c94912beffc7c9c99eefff79727284ef471243227392e7fb91cc901021a1e1f4e368f19b7aaff5a9f153a954eaa78d299460f6adc0de36b940f5290f5817cd557315b98c5c472e2497926bc9c5e46a7239b99ec818292367241149236b641169441e9148a412b94432914da413f9f48abd64afd98be8457bd55e452fa3d7d10be9a5f45a7a31bd9a5e4eaf279f988fcc67e643e443f3a9f914f918f91cf920f928f92cf930f934f938f93cfdc47e643fb31fa21fda4feda7e8c7e8e7e807e967e987e9a7e9c7e9e709490c890cc90c09111295dd12e4855899070b22fe28794b057ac0e2144db138461db0384735581c240e581c252916676903168789068bd314c5e238cd60719e346059b10c58960c03963593c1b28862b02c5a6959b50b58561114cb32b280651d55c0b2902860594a3058d6d2042c8b490296d51401cb727ac1b29e206073620fb0393207d89c990b3687a8013687c6009b535b80cd297a62738c1460738e5ab0394809b0394a41366709013687e90036a789059be3e4c4e63cad60756206b03ab202589d990a56872805ab432380d5a935b13a454cac8ed112ab738482d541526275944eb03a4b03b03a4c30ab73ad0e90d51180f51100eb0300d64712eb0389f5f1637df8581f2feb83b43e5cd60792b7fa4db03e94ac8f256ff51bb13e4ab03e9cac8f276ff5f7d81f23d81f45ec0f1efb838888fdf143043b14e471a8128389f04276bc0e3db03949e0f13ed89826b44af4c134797a27e6439b2474ebf8d0e68feafb7ffa7d7850cb96cc12914d1e9e96c589591c99c599e110f5a87a6ac9809a872d7dd4c0c70c6e7f4d11170d491292253036182176fb41a84d1e1b6a9119679f0bf241ac6505d90ff2416c9020d606f9256cb0b16db533a85852aaf64b1aa75493b5486ade4a358d228460534829a4105248292436ea2c3273d245f356ff6ae5e2d2aeefc522b3db1ff425a5bbb7b3bad111788bdb85cceaacd579c4f6c43777aed3b94ddefcb7ffdc3b54f7ddc7c04bb8cce5b66ddbba7b9465f55356b3bd018e6f67d2f1c114fa9d7ba26721a4e6cccf1daa6fe66dc41ae8dd21c630f3e003f587c2cc83ffcdafc1192e017fe6a9092184f03737aceeaf6d6c942ad7e6c6e62fcb46e16bc33831e8587dfbb35ddf7f9f28fb7ec8e6678f37ffd9d839c325b3471b71f6f83d50dfcc1ebf8eb52c663fd632d90d958b84c05155fe3732a825d73e226c6e3e2fadf34364d9f7eb581e5d504b96e9bc3f5f69d204988e0917a83bc6b24382882151f108fe35407e27c8bbf8fe2c66fef0ff9c3e7ece1cee717afceac5a25a72ade634ef2b1e6f45ea43d4ef6da038c9f27205c5c909f36a932df9da176df9bdf8aa9aef5bf340c4b2af6879a9477f6b398d17cbd5ddf13f441f6259ef8ed7f1ee8e67891d0ed7566239f610cbf196af6bf31c2ab91159cce4f12b3c63598fe08dfdac6723ce99077295a5815e1e76872d4db825974cc7f5af76c6a63e0429f47ea2375ffc7ad566407a4713dfdcd928a5be811f9de1a29eb394bd3d90c3251cd74fad5c2e67b852e8a5288c7c8ff4b8a5e089447adc7adc52f0c49e1eb7ef442fc9e4d936282f0c09a26e5f4ea69ea20cd349063feb0e14f73af4c0baf7de5f070f86faf1696ad5fd4e52e0bb89aa1e2965b1871c51cb99a442bb5641a8a8e5ea5294b52674235cfa1ccfed77cb6a1168f2d0afb9fdc409bfe7b4cb27134dc137773e28eedcb7813fc2d4548ae60ee6bafb7f28cfdddddb38f5fe8c42f13649ef75f0607548f682d5d7c1830d0de9f0b0f075e829c3cbaf336d2608d3b54d57f76c2fca76cd72e19299cb62cb68505b355fc3cc25ea5362eae342ed13b58bba56aba5ca0345504b15971efd6bffd4b1263163c64f4ae38913d31112510f1628d3dd7f0e326eb8bba3dc1de55d9b3cfe9d6da32f3d1e35987ea2a9b8fe335d826ba40c6fd935b17dfc1edd7f8817b55ce5ccc21a0d112dea2472469d3fff031a42449d5fbe6650b7ef3ce7e80c2af7de972fa09793a81791e86c7e31e161177b860451e7cf60d0ed3d71986ad3f9fd0853bd3b516ddc999444d1e5db453349891897f672b7ffa8ff58a3d6b86caa1eb7ef5aed21223ed4fed2aea306d32ea6b551bb90bad6454e64564bbea81f616af7234ce57e84a93fc2548a227b87d9dabe6528b1c75bd5a8aa56602271880e6aa9badbb3e61502442d552e66f26c3fa4071c5fb12aa83d137b8817db77ac879e6b3d6e9cc5c16ddbb66ddbb66ddbb66ddbb66ddbb66ddbb66ddbb66ddb7edbb6dfb66ddb3ab1ac3fc254fe11a676932ab7f48037d371e9baa86b3d6e3fc4895aae6a77db9eceee04f2a1d160cf6f9993dc85a96759bad62e2fed9a49483cd159123edcb2b15c6f5a1231efa236ea2fd77b72874a72982a0b0706955bf6e4fcd49335792f71927375265ce4cf46fe2cfbbede7577777777975514e3e0a5afd0e9ea96b59773d9cb965db634f78a6541ed59cbdea8a577bf4c1e672b455dd50ea296de0cef0c5198cfedf45d697fa15d76f54fb5acaa206ab542cc830f6a46b09aff6638abadf9cfa3b931a3df7312d4a313af9b6ce7edba8988a9e54c427ae2531b4c7d4ffc69c2a7791a27b68787dae192a027b6e41b3eea6798824a042dedb169a8244abd21588566993265ea106ba0371463e83e752993767d28b0acb7c5eea66cd93da7badc3b993c8f9a0ac00967fd5f4c85f2428f4388a8e53c5201e884243d7aed3a436f555f164a8fde2cc220be40048d5aaaee64720a3bdca12983d4bbdbbbdddbdddd79a6d8e076ba719d87a294db50a9cfb90f7430e46ef34ab70e04393092aedcda71bb37d8dedded35d7de9b534a5dddcd6d1cfd4da4de5c37d8dd2111125f6d5758a301ef6ebecd917eb7510fe4388e7a4db6db8feac0d65bbb5073a4a16fa8b0098de711cdeacd9d494870b9a5b7e1a086772621a1840e90b8d2b55179dc9994a5074f557567529619009dc04485383c9b1ec05cd9a14693aa07122851a354e3d1430f4654339e76f0708325685020abe1a10c25665240ab3c141d11aa6144c3031610054d333bc891c49782a77007359648a92103b340a1f1f4793d3b2091c5f3aa0756a7541d4a744ac2d05031c8c22951c1ccfbe2c4a6e40ca52e499644124b3f68a2c674841233944ca08492349242c04508256818f51c7925f9614616511091455d9541d56a60022894b61ad47a6719501cf1000a29d6a8ab3bcb80620837a088795e5d75d172af783ddc74e9eab5eab942bd5ac647c8cf1a448aa8a30549462c1d01c4115bdcfe3f228edb3f6651bafd333d2c00897c5004096e7f182ae9daddb4bbbb6f70bbc7edee6eda60a8a4d97ff49f3eb8bfbb192af0e1faeababbfbe6a95089f38634c604d3f081c62d67d24c430cce2de7182c26100209219810e206b77feca1e2f6bf86e0e2f6030171fb991031c5ed7772c3ed7f424b226252d24d687c2e08a2045e0d62ccedef56757c392378a2c8edf7ea085670fb574170b9fddc7321829ca65b8820a97276881c0122073140b071fbebeac71efae2495a438d1f7a2046046acc5645725041a96241920f31f8c1e8f6f7aad65893164a28a9e00a1d341cda1060bcf18317517801ebeeee396e6b21e636eb7677b777d33874e8b9a58a480f4a23f450e6ca1457b4e8b95eede1435208b29ce0a90c30497abec79551f9fdbbfb1a8bc52e7b89f1508f6d57afd78b480b6aa9badeb4295ceceefd9d5755dd7b364a95eb7905e8ef58fcf37694d2efacea6b50475108965a8260bb362b24884ac57871cc7c7a34d0e106b7fbdbe3623af14ece0f92094335af0ec171fb5742dcfeb76226e58083db493a5cf15aaaaa241cc8dceee979164997de8f59a0c451a4415994f6524f1226415eae8b7182028e5b82344c5b5a9004451ab79c493a97f2eadbc5e00f5e05758e183f35538f4c3d0ee4fa136917cf234a93e60f93c9c3bfd3dc3dd123267931aab7da146ff678cd693d5bf851bfbd777da2dcb538adc79fec28f445fd37d5976741d99e2935a1287a509ec537d1b5f4a05028d1695ea339cdc91ea739ed3a753f0a99beb953766deaa0f4d8cc3444b59c4d53bcef97418a48c51545892a346b7beee765b23d7def7696b57df7f3a2d077fb6f9a602e142f5cc414c5094a57e030e6ce3274a8dd227726e1e0a5c9b83e3d8957e7cf51fc2393642ab868f238e5d8941e85c8514bef841e81dcf39e8e8e9ea228d99ea328e19e6605d54b8f46fca5c7a30681b8a84777263dfa33cd42b3b48b4ef931462d7bae5756cfab15e4228ec5297f71985e37c5dfb9e889d2ea605eb1571e3cec7ce1ba58722f65bbf4fbfbfa0335cd0f6ac9462b9adf3ab0fbbe147d71d58354fdb92f2b7f0cdcab762c919e5792139838097a420487ba024dc8fa68be55832b9aef075b5cd174e066691a04699e9be699e63d5442238e9d05e28998284c12991b76cf653fd83fc37db773dc7b98c20f4e1cc3ea24c318882effd2ee277a22222ea2f8da335f9270d072e9a39e2a5d7eee598bf3c72feabde9f247a150ff31ea67e8a447d4033595c1b95cd4731fae40df7b6a9bc8f64c0a2dea91b9f45893555a3b6a174aa9c1b40ba95d9ec6929876d9a4cb607a3c83b2ae54fef6d257da5576acb9b4ab94c2485f2e7fd3daa5a56bac999f377cfe2e62d4b327c9aeb8531fa1680de5a150aa1e696da3355abbdc472cd4d39465a17ede9493f3d38491e0115f06d364e5e724274ed2187489c19a8cf8f9a85d335b4210e3f68a6a3426422273d98dcb7c144583393aeaa315b758d63ea24a33637c2b232a0bf5b3ebe9e9a1a7bba7e336eadd0266fe1af4a17a3db61039aa3ffd7e838a20654ac68a51fbc9694b2ddb8d4bbfdd20a2fa0aaac79807493760390112932b294686c648920d433b35df8f076afe980b088245cc44b8a828c9432de7d3e3886957c7d42e5437b931f350388d7671ab29423ae41332a982597db9acc5a6dad8e4d8e4d45a6bc5b24433e95dfd4c8f0f2d6bf5f382f06e6f66a038396586ef2f65bbe1cf7cced358d68ee7bbe3ab65ed709b63a720d5f0fded16203fc326e1c7e04038d62efe1282a8e57caa329ae79fb1cd647b0c8d7562f90ab56bde5a451598f4c8217fe81531b1148661183e50e72051cbb9145f40e0f259ca68e2072cae5cfe0a6cdbb66ddbb6bd6a73c1c6b19a88ac14e883d103e4eeeedc3747e74f0dde9d3f35d43b7f6a586d4f275bdac4bb3578b7b78ed5e4ef168377fb995f4a94ee4eb106efb2d8af234051a41ce9d19d29333333534a5de9fa768233be64b93d5dcea4fb7f5b8bdb67e4f0d350037d29ac267fbb9fb71363106bf0ae471fc86990e27d0cfae5b8ef5e3d4601737b02f5584394cee7f6bf8ef4d8650fe76c59deb1a54b97aee03233b37f69e5fabb5883df242c926ed33792aa9883864bf9530b7edb281d0dfd33ca06acdcfe707235db87bf644669514a14be35cc28dd0541b1640ff54d5949147eba9f38bf0647d928dd75b1a4dd7397592c6bf0285d99261da36595d8f5ff2e757235f49f4be552b99fcfd1d0b11ba56bd2b1db82cf6b7288723fc270e032566ec9df94eaf05c334ff1a1ee4cddc9bd953bb9e6067cb5c9a1a12e653fbf0e3d30fadb4fd1eaf0b02ed4bb9bfde1548519023fc17066fe78574a94eefa6fc0ca9512a5bb566e99ebf9f86893133697b8e07c7367b32594edbd67de6cc95068e818cff6de770c51b8cc854243c76e2746f144ef3db1f608ae3c863979ca9aeb0f65fbdec4283c608feef57bbf7df7cdb565716de9125dc19d61d7dddd9d75255945dd995405d1e5ff38a98ad9e5073ba98a5812154f97df9b8c0325a1a8f67b2a954aa5288792958ce5963928cff352a9542a954a656957698584a25a36adcce4f127610a2f73fdddaff8cccbcc9f9902df89b27ec5673db2cb98c8b15cbfe23367227e35be19a44ca95caabbbb9bca50dcb6799ee7791e0d3b919d52507d0c99a71e6d6ab59c4f4e93098cc9bf755eadabd5e4be39d113a914aea158a2c43d9367d9cd4f59dc78ebd19632c0e09bb3a57c3376b9634c5c34477984dbc5956166513a9ddc31fdf213f192744b50698aa65baea6f872cb9dcb47a8f77ca0ee36f2160f362a7fd94660b3eae674cc639b0dfc3f1d1b788f9a1eea3dcff3746c505fc70695d3b141dd363a79fc6f72a8a53f4d11e2d87be46c910616a793c9f344634e7eef4f97da2546367f369fe2a896058d0aa227664bc88ab8ee3120aed3a4922a3ded10a500a8e79e85aa2a55c1a7ab1cba2ae793ff0ec7a6f4e83f84873a613c65f2f8f793931e9845533c515b825604d1757f771bae3b939133f918effddd0d77f22fed469fc62a09cc75386a399fae3b214df93e1626c9d30908a08f2c6ac7f8e9b3637b5eadab15b8838f86f9fdb13bedbcb13b2d6b7edf79f92604958f18c90c4e761c7be9d64cfa82491ab8c59f4aedd88183238a42849470cbe954c22d995ff768061e81b9a848522d7b9054e07690c3981aa4c173cc7db2a3b73ad6adf93ceb995e8be5f7ac0664bc210a66c8a340173269c850e9975e49eff633490a30777328dfec4fa9ae92906a5a86624c62be18116121e3a494c4a5261b1ac374f4250bd1139934947a88b8c14a495c6a544687c6301d7df12c4ef444260da5222e7da5654d63c01cddf934ce32c7d39dbf74a467f24c9e71562b6a79e4cef726ad4befe4adca9d3dd218f1cd496934cb1c4f4b697829f2995f71a309098c96a6756c0e314b465e78e624039371e77da82cf264dfbaf8667f1f3f6771e0beebe65ec80a8c7bb6a515eedbd2e72cc8a0d84d9fbdbbbbb9bb4a5bd9dac17cab1fd472e5d4ab32b5b9bf1d338b2ca79b2d895cfe1d8e6845ddb8fc1db8caf9bbd14ba9c8854aa84841e65fcd51cb9516b5a497d30041b8a1f6fb5f6a8f8cf3270aaf723e907da3cd93ab32032c783e0b7c1f3f018597c9d5803d529578f331155550b180d8821460680856547e700a2ccf4554cb4a3dcea53b65f8788aa2ca5c8223463e3ee2d5e54eca572a7f0f754ed737df4aa943b7ccc1d9409d49528cb9e52a87476065a0f4bd3dc739b73d2211a424212a90795ead93cebc9565fecc190957d4243e03bfd9711cd7bd731dfd2f4797522f9756ce7233549dc8b118b5eb4bbbfc68fec89ca4316fd1f756b298ecc67aa48d458e5aba2c76a55d8e65fe5c317f7ad61ecbf3708ebe2c3598ced2b5f6d2467dd4ded62d89e9baae9b39a533293dc407757ecf668bbee7cde813f5bbac47fa4dc91c264aa48516d12f3446c1cc688d7aa146f488225dfa9d3795b5aba44b344687280df48a2ea34bed9a495bc4b44bc8a55fba0c2887885a4e24262a38097ae2c2d387a15d32b42bf5f4679032a55d1fc33e10653b8fefe720f89b05bfb3dfcac71ef1c3a70995709c8802f733df4d4291a65f4aa750723fe3851fc79a5704727ebfe01772dc94eb1cf840ed16c8fd8bd25df013c71e69093c427ff7f37220673d2c3de72d21885abaaceb3aaed3323f0e14125925f008dd538e1ce9b1bb28ddddc49c1ebb6fec69179389d4b38ec90c0be538a21ea6e5cc6aedbb42739172de9dc8443d524ee42c62cfc231b5ec19d1a5b276cd1c8b13f5ac5db369d35937650279e7082e4e673829d576b60fc34fd9796b580bd34c5012eaf15876a471f9b9ec71a15d5c1d47ba079c79b003c399f203a09d37ec2e87e10cf8813db2fb10a2eef8f9359ffa1eaf87417feedbc640c52445d4a756eab7adef333889f3362ad1094704c1f356a2d2f72831654bbea9fadfa3c0ed7bd8efb3dc7796e53f6b2a13b564239aa41ee79d4e527a9cc285f3da63101b6a5957392bb19b850598bfd3e3f7c84a33cc16bf938b9dfd3617d3dcb2f8000c6b9973d471c42563d9714b26a271fc41fcdb47410f53e07e86208e7b4e2cc31b2e7d2b33f4c836d4c0b7859bbf11abdcfccd0360e8e87ed4f64d0100434717004347d7c52d31000c1dc1aadc885dfabbd0e71bdba529f58196428f0dcadc168ff4d853469d3f513507b061fe914d57a727c6982133630e136a4b4b4e02d8420b330be32500368c29ba5b0a1c5780eaee3ae698638e53cfa13cefe6ba9b4688fa48b3b5bde771dbc68965eded4114f72c14ea3b6a25314d66eb34eeb6b51b77dbfae96e3dc7dd3c76b747751cd775bfa46fc7897dd4637f8e15b5f4d9ddb6772ced1259dd73cf6ad2cffd6f449ea55d76360b598185dffd2ca6fe9b61932d3362952eb5a86e1f5ab9522cd0dfe296d0fbd076e15256a8942d5299a18a9472cae54aa1cbfd6cce2fcac610650af75f839cf5aef79d8dd25dafb9eeee58bba6ccc999dfbe89266cdbc424596ac7eebcdb57ebcd56f7f68fe4e4f446ba5bb70541aa5ee4753886e3ba8d7af71c79251972671945495cfb0bbceac5f11161e3066d0cf970061764cc7cb1c6510e64a4e00b0e383ac0bc804711386af9979c302297939cf08113b38614618608d304920faa1768314616242cdae8a291c070018f0d0e3592482046a53ff90a982d37f7eb53500b0e5f6809e3f6371751f06035d1e44d2fb5d4c4525251d28bf273ef5d6f35a29a678bbec71efda6da338aa09674ec51ca0c4c8b82d29ef908beb9b345fc21a6cea7f30b15f2469db3dff99b3771a7e79cf367e9cdf9f3a8afd8e87b8fea0ff50c54c20db5f4bcef9d1c7b5ecc1022dce3d84f38c2a262cf7dcd2a132021b35a528a060d96fae1122b97134b2b979362e5d239a43667f86644b047e619f1871cb19a11a833896674670bee4c5242cc5522e96e4fe48bea3d1135aac72068a58c2e90f24dcb3326ea9183a83cbb350ffeb7e36b97eadec315aa30955b7ae04eeacdcc07ea999c5f39512d11d0f61c59854ae6b3f89a3ccc53c4197ae41fe245e52d65cb9e5a69ca29b7f4a76e65f5999b997b35d3df122c9f1eb4a14525a4fa9ab712c60026c4439cf1014c88c75711e105b09ab752b3c566137f88a92ebc203e79a36e4f435b4a711bd1856ed1076abafd185399b282543388c7dbbc8d28e4bd15584b06157cfa4280a8fd655de588a0f6ff8841dd848cc880073360558c84b1c40c6035cfc30a8545c0aaf0b801ac46ece25f1fa83f17c0df9e636128ee3c28bef064a67183549841adf91d230f1e2af44879bcea9fa05036dbd3e9e27ee31eb421d8bfd9ef39cba4470ad41b0fbb8122cb28134af3334b29f0431a2c331f6ea185c1be40639f883aa8fefd43347ceaf70591053ebda0f8a447ea82acfe139447279d61b41073b71db6a68716f6e0f329fe10534767299ea4472eb925535e8adf397950cb890424be9aa82aef039073996ee1befff302a647a8e4acb486552d99a2110000100041017314002028100c888422b1502820935551f614000b8aac4c70541909a32447619842861063003000040440006666b64d948d99c2ee6b9058bfb721277fdb76a8aa23ca06bd1ca28ae4383c658aa2c382f9d5731134e16eb9b2a16be881c8851291f32ae795747ea773889f33628c4124a05ce9f913a620634d3fb9d8efa89bc55ed8a79d7d49ae9ac05373a588585057542d58fe080c59502b2263c382d3e11956190cbe7af3993f57186786a623872ee3eae928703edb0705da3821166d318771e07fd0381a4133a3cfa14a876c1c364de0bb1c6b5258a7528ff74e1eaf16443ad87d7b3e7ab0169352f892a546e4d1dba496948705811da32c83459927e600a4316836e56e858055070854a457a7e68b4898769ecdcd757421395f2ceb52d9c7ce715a68454a02987d37cee16a835666cae6c731a3bbb4fa4ac7a58f34d2e3ca650fe57d990e32602ab8b0ac0a6154f92c45749ca9df1039f3f7a6b3f68c0407a79742f4e286401ea8318aaed356bb2b8d702956c7e71c6da77a50f3a33ca9270e9e9c9ee718eca48b3cf7485cff54791fef1e0017a677d59e2324901b84a9c2dad0fa2e2c70bc0ab3eef6698d37fedfaf54493e3e10545e6008faa5c9af2bf944d9ca6471361d7b18c9b02bf39d08affe88f258f50a29903c3b2dbda4322e594493ace5780f6f8c232c3a033031a0fb32c063ac04e309e630eb6cf24c070574c78b597fca948d33a219c3c132e65a3cb190dcca8318803717f0d9b81a40f0f5ba509983bffc00a4d2e215fcc8d5345f774764866f3ce0ddd280f1e20d06cf49a59cae5923fd3c43d585711e6c07cb22a50eaa76c6683bf27e40e17fa08b06851640930f894dcd4a52d2e4aee3a491825fb0d36bb0bfc8c247687523843004f7f7eead97d41c6a2183380b62bf464a6735bb0ec460e799a5bbddfe8dc563886b1b0531abfcd01e7e946ecc5d3b34a69ed0eed4d3524733d1483cdf6a9e20ef60c0ab89e53df5b0765dc462edade1e78c66e4635bc28a3d27d5ddcddb9558e8f93fe3ccd390821fbcd4950cbc30db4b80f3a02d7b0462e6c28b2dc1e0800f13a9b5939981936872c00b8b0d23f4be4d674500038990a1e9424984a4c59b68cf6c6ed75d2b4a2e3aab610000a710b5b72140ae4b716e2c543e16bd2ebaf067c665121e5665c9791af2154e886b68b21bfb3a3096e42b75dd53b5f84c476a8836bda30364e2388181918e907073e9ee6fa70b41664030bc26e269ff303f356ae37e70b3925cf3b965fd789c2de95ac118d2b356abaa965fe3e8a2371c6d038738a7aae3c1991f668db81739de981cab52c2e16aaae7eac0d4ca056f0a1be5a8a338aed4c6b7c04752d5e9502f783e9b75d24578ece435f71bd2f862e183b633c8617b7c7826b8c4315077c3fdd652a66710192e2b6c1bc38135ff493c8040395bac1151ef0d0131c33ad09bd314cd1642b3ad8d96d74ee7baa8aa9779bdc4bf8d1f996f9b3f602158398d999d8c194d51bbee7e09cc7f86c22f52ef835f8ab6c0fdf9765e6e8162438aff9b5ddd7a9f6fdb07c3b3713c4e328cc17795b8309f52ca7da0ab9b8f9e5dc7d6af66720e10dcbf8b86983cecf215708f7962d60da6bddf98e64ed4943a08c9667fb5d2e285c7a1e05a84cd70f419fca9b635e9a5acec7892f324c9cf78dca223e8081c400b8c7a3c47f0212c644c1ef18ce9083157b0e519241997712b1dd0ce016f06942fa2ecc976c66c1b5bf3916d35051251402c204c641f629a569421ea276dd79fa51181b063c2eef8937851be4475dfcf5c711034f58fd8fc8f0cf7c7cb82e0d7079209175a9a98b975138b701a953feec8e235cac54e7958010d8a7be3af757d68533d3a6f6ac56221951bdde9cb3c54d9b98a36bd8c36ddfa5adac2996adf829ba6fa4322bd90fc764ea72a455a49c71cd53b5fa70f4855eff6d3dd22731f3037f030859030c7bd12e4199579aa23bcd3063489f83f80fc254593ac73f44c9f43e3f874d290373c4dc3bcf9d2ba47708a7974404d6efa54d97850cb7e691d27561b6e0f4539978c86df43f1f0a8f162278ce4cecaf8a28156dacaf168ea8c9bafe1a52494422491c04cacc616931f4f383d5b1b6580b4662f933d59591005e7b84e789baebd67b7740eb983f1f9fd45d0733a040d067000349d7fbaeb0df024045a3d6fcaf4a1522b292a007798f871a44d4f4807066c6939b0da54b53488af0a8230762f204306b901a63624760e587c66e18a1350a1605a0f3b4f0217faafdddc1d89c3b1c72f17e54e5084fad7c76505e79df0eec1172a44da9b059765148ec80503156fe494ce78a414ce2df401611e042a3e201688559219ad924133e827d3fffb0e91e26f8e4f4117c9dd23156501152900f73c385ba700c7ce7f1eb4d51da9ab441e22ed618ed8dc141ef757ac147fc28fa65cc67cb89d86b9ecd2c0e534ab1f4708f111e795efd0902af1b2d1668f3f02a29a5c86a491ce8000124e92f51dbe6c0f6025db21cdd7ac950cba77a85249dfe2a6c077d559aa5bb044aaab2d9c6eb733a6ea16691851e3890d2bbf9f9c0f0d710c406b88a5375822dadec50b43aedd5d70468584e651b79a3d5b0894fb1ad9f4cac050f4d7cef22935bf4611780e251565be1e2e48bc879126a6c5b25abadf2893fec42c7021d2b6d1a61f95015f987954f55251a3d2d5546c9f638d94573d6880a91e65e3e2c20f73f6094ca74cb0b423aff59481c3c9559a3e33cb9e0c1eee42591ddf9a1a7d56cf233ee7ee3923420d1f2ab64554dd26a425a32e0ef52a42caf8ad5fdc88b065cb3edd34b8ccd78789dea6d05d880720dfa9114d382f6aeb7e09ce49ff140c40708cfe66ec74addab0b6193ada306bcc170e460dd022474d9e854d9fb52ab893dea9168e94f366dd76356e8b769b4747d5dd33bb3778a9b508305f378c1e700e2170eecb04de735db76f6a5ca05663fbf206d9b3b6087492b7e16e7e0a5bc1a46b94c9e292a6509ecc140b63a710efac14844d5cc3820ba9f9eaf2996d05582b669a35a390dcd2ead4928f035cde7722cd1388aa40cc329825fdaf122883bf1ef8ea630112045fd72ac455e4a65382c2f5f5eed77b4dda3d6b8921f0315710d6f8e9e225421153dc546f650f5d690acda7f1e9aa7683625b2e9bb70875626f09a402e924fa337879c33c960660e9549e429346ea142a068ac9fc104b187fa17fffe3705a61843bee01cd7942e031198cb9cfc15170d3bcb01fd8fb5b6af68d361484679ec4c0d86661510720f539297f2de2207cc38c8605f230a5e62cded7b7d2911ca355671e4feb6412de2d62bc2536ddf0e819bd423265b13639e18d570b36b27d81257d45e807ae1f286bd4625ac5b1fd2fcc409f80461aee224cfcbdbc7a5e4a7f2b9b95832821071f86d1e1d3fa4b0431009b07ed03570cfcdc7b5caf7886174cea044771ba87304ae9ef1896becdd14229d44fa11cd7d128f18f6ea928347d9d4d358ffb0e844b090f3cf51e38e4cc2ab03bdae0fffeab3e562f394f64b1104006fcac6af72b9ef63451ee0e5b283722752d7ccdb51e9895406a07b327b264dc1af7e6cc62566b2aa7b4b3294d2bde26363f74a9e6d0bb532b7f880fde66696068ec36d7cf6c7bbf9a3d6de38faef131eebe1a8fcfc7cdf738fb343ebe1f97cfe3ecdb38f83c6ebe8fdb77e3e1fbb8f93c7e1f8d83dff5b9981b7cc6f75d1dcb8393eac7c031403063d0ce0892b13241a73ccf14d0cfd2efec9a0fc711ff7dadc077dd67e38a9fbe5ee0bbeeabf1f17d9ce6cf6b0e5c97b88fd4302e717bae011d5069757649b51935d9537251a9b3fa76aebfc524854d57336c68b86a32676545e1192b3743ea17b9157afa40641a514d5bea8852a48a72b8ff3cc32ff6abdffebaad95d004ca0f76cdc7bdc9824b9d44f93ada15798f45e9b2d48832817a34f6ff4704529d50aa92a7729cc17472a94c9eea08f0f6fc6a9738d525e23ba9687ae3f3d14c10cee7d216efd83c0f64f3fc38be113ae21307c121726a679538640f58969e238b2022b099e35dfde7520b8a2435bc12bae29375eb38d80415537f55d0978c31b5e0bb369e2899ae8c6d0d5b5ac10ada047cf93d689d7eb24759f92ff075baa469c475034dae04748f360a2b826ccbb26e23e49a7453ef155fe0bc2aab7e6c94e27d26475dc53f6d579b543ba6cc1316a714b46bb3e6e8959f381969ea0dc46fe9a53a7412cd70edf80525c512eb2449d6d22feb98b1e3a1f9ceebf6aab876019a8602617449fa4bac05a53b945f3c9f1c0b99436050825ba9fda93b196e0139b5501f674e1928ec62d1bd5bf10c19278bc0fdfeb067c3ece8ea9bbeddf172cb7ab77fe30413a5dd156eaee89672e322bd361b8cd4d97987f43744072a545d06e5b324f303a4ad6b23ad9bed323088a63caf637140d5cb094b6c35ba2753fa93c9a4c3b21ccc32b818b2c3493d80fe16e48913af070e69def1a3c54ab1a5df643f8e105a5007795d582105205625264c9aa53deb6ac46c65462b8ec2d445ac2bb880df6a9fa83cf49b677b90ccc721a0565ce08c5c698973d31abf76ad4a01d89ddf7d5137d3173bfd386744e27adf78a9e8660b68c0638f89864ea9c6538fb70d1b7b840cd991523807754146dd09101dd21fad2bfffa100d5305ae676279a36c0538849c3d81d3e467c02ea2f803052634b06bdf60c247a0fc696decfb373805095a5bb4dd8098d654ca5a7bdd2b191a5764a72d0267cb91083a960a87afb8d06f8b4b089480b21a15d4441dcdcd90f3951a7ad2c0b8b3b26d60a41270bba4164d26287438cda0ba1bd83d1deda30ee3e474c70813ef4b8944db7b53f88410674e41aec8fd7a06c3b9fb8eb4c5fe970c73ad694a837ff7173a3a8a7ecec1662e614b0653cc97efafa486f25ade2aced3c2ab1e2fbf04e69bdc2229f03af60208ad80c8a136ae5578f082beeee21cd6a0e82d7f87b790e206d94784f74a7072f421b5c43a880f0727ef13a580c04c72702f3ba26ccc1150d15b891ecc10a92c409c5453d236a7a2978e9780f894d0cedb528ed58e6f4193c1112f7d012798c205bbfbb065cde929b367324dc491009cb3b2edb9dea31f6ebd9f7099bf8fc9a780eea243943e3ed47e2562ea355801222d297a9897ea8b74913ba009052b120c09581243bceb6e15783527669cef9b308a09a3d32e2f4c944de92f01a175641d3e355ab09d76054ebbe7fd0cee79be2949c40602ccd08318bbacedb81ba6b33d65c9a22df735f2dec86c4cf96b808615288a62fc130796beb7a84e6272c3816fe7fc632d8aa29e051337332400c5cf453a206734151f83f9ff2c09c6d3b908f74205d4928a35b777b4960993f4688d2567678c6b4d5860d3cbbde6d01a8c749a2a2351fca5559cc250165cc29fcdbc65779583cb9557fe560a4e044127b5906345f34dedd865a6a89f6360f4fe364c5e2135c5e2315a374ea55863fd21a82e0a2363fd990a2f3d9aaa44ab6f325d25e96700ae41f0ffcacd382ad1c6043fa19153a286647c02d4c892fa8c5636b2acdc9f94ca7d86ff160b28b112248bc95292861679348c4392f5ba76afa2bdcb25506d705ae1eb94b6585aca22fc75488233fc06f525cf0306dd201593da93ec42d416ca7762d5a23c1a6b55f83a2a8e369124e3bf491a80ba4c2f4e09a68f6c9d691f1f6ea8a9cad3aa118dbbea5ebbdaa77d0429314c60bf3d2cc766f9b6db3ea2579c2ff5dc1d4ff96b73a6dbdaad7b9f43dd3319dad855dde51f8585822696afcdc1022b821d584aff527ded7f878e6efa5c58f08d02a811b8e4ed964263ab5a8c73cb85b4fdb006546bfd2a7bfac87c3761ad52679935fef6313f61223fccfa8d21f27aa575a6a9062f51aef575753bcca8277a920d0abd3a8cf895bcea0279e083352dea5be116dccabd29e9f9dd47dff6b43050c0858e6f198358ebfe7b6f738a9edec4edefc4636fdaa6b68d35c1dc2a06b5b2234bde35eba58186c7748df5b8d3534112dee157dc9063d0d0902317139285c9027edb4d9e45912a3dc9be6ea6843914849c49c37c85219e1a61c39de05bf8b0b530bd6fe888b45fa4bda7010eeceb8597688c22ca4f9e7b6c5c3396b83c386368a9423a14acc604dd1c425df08f63e840c2f3401cb9a0f10b4560621cc58455d85a3eb21b0a6e6054ce9e15f8847a762447465c2e8dcdd0430d0e8b291a4938bfb60090646ae71fd67c8dcffccea40f49d236331616194990d32d22a96f422922543f1f90edad5f7fabaedd5f4382ffc59061304281e0f5441462fc5ea0b75951f35ef99440cbbb09a4a00d3b9833c441a1bd9f53f8b15c3fd8bf9bac179eea1243cc5d02d97618a46739c8c14390bae5b492751605af761dc3a0968eb1d15cda83899926a09fc771fa7541712304c8c61c82b68a59758855a9ca3eeecdba167f67ba3f07bfdfdf667f5103b8d33307cf955457d34a02c3c306f872e235702ca1f04bf093134861289f28217c013a656a13f8755024f262b5b707eb24be39d870a277c71b271b9475d6c9398c74085f96ec160c173c5533cedf27465e59f9fad8a16efaf3209feb32eb822f6e3eb012813f076a1d0f59b2b6f9feb995b039c856d824f3b1e90ed5cb71143493722b02b60e69aaa8e73d618dc3f6708ce70dfa4e658be1ed8370c13743262f7abf68096e681a083eebf9430eeff5a7ec0f24fdc39866c2302350158340da4e5e16e3a65a9bbeb04cd2f77273b0caae511cfac8af52d9bd818d70e17acc82dae204b44a78a523ac5bbe34cd6675fc67e111fc23b44bcc320c19f05ecfa0c18995c42d1e895a38da644bbb7e0e4a96fde84b57f84e4637ffc006afcf55ef45dde6cdafce1af866a8bdd668b782e2704051129045c22c7019b0fa4030847dc7f56583f294e141c0c16f12d69e538e0e4660618fccef68f2729e5876e2d02790c6c0e0b801e0a181583b4c2e7736d6d74b872ad80a426bd839475b1b049cfdbfe13a8655192494f2c5bd1c025bd5da89902d49f000374cca5501982165432526ae8ce4792ae5dabf65b02ddb2d6506543b9ce2fb0c108c1008951b43c9ebde834067d093543c4aec981f3e88e53134288824786dbfcbe0444560714a4a877a74604311be8fb9afc3a2e6dbd153d3e94b774974e9d59313ce3c16d9971b6d097d3b062476f70f8b9ad1940879c97323a1933828650de83b06d75ce57fd7c5784ccc7328aee744731d7bc380dd8bd2ac20234f71c70ca2c8dccd74fa9a875e42befab1ce132dedb4386489cbec315a551ff211da9eb356be94349baa72c038371bf50ff7b264c0971e44a83ff5485c096245a8417fa5959a9b141b454a334b787d8229e6905788a37d26ac0e862f4b97b422087b6bcac65a9fa8802abde88229af2e612b04942fdaa802eebf472757ec86bc8acab76974dcc3ca1f6553d49af81367653eba28298763250ffa0b586a44387c3ec10ad48da3634b8ef29472b20a5ffeaeefd2895e41ed97cbf0704506da4c7739240f6d87512d6611779980dd07e74374b46e4993d4f33abad0bcbef36feecb804fbe20ba32c0020c2188c25d939a8ee4232bd13a3e3719b82d72a56a5bec35aebbab88676320501a399f4409ada8c8ce4ec37967c2f5bdab49b0e57b4e3a2887b74045ec73f72144a1ce3125bb570ab8cfd71a605dbf77240d08705677c4940820502751f752fa5aaf0b2241b0f0fbb0b8acae5bf4320fde3a93457fc5217aca0db90f5139e547d3d610712cbd6ce47eb207bdeba614fe8a9c1f212c8a1c2bdbd8d4b835fb12a80b41753ad724461aaabc0790896397e56ff36cc94a3e607abb695e516aae75604b34ac498774da1dbd559f9a1bd91054238e64c729c409f5fdd49c029bb9c01fb76dfc1d8b6307d2a277390e493fdd90211bc141897d534b6122a4efe3fc243361269a4090f98ba74832665832c0941560bf904e3aaac6dfd2acb6935e07cd42ac55e3e9923c30680bf42d15c2b15fb161a7a5301ec3b0bc1fa6141c392a6da260496d0e8ad8de6d5c8211c6e0bdfe6b85622e03602c26228be45bdaddd23995a4df361e8170ff33cf749d884e38866947c076ee7498a86bc4a55fad1fc339a11725788e3823c0ef524cfdf12502fa501c851ec8fd97a8e768134ee30886cec1d14aa3aff70da50edcd4b32893a994990b1d449e15b6bb8c8f9dca8657a624c30d678f946799e4bb3983200cea73dc5cf19d11a969103b0b24cae67aac398e40cca5acabed5853162726c3aa7e34986a4486df3d5a67d85fbf3849bc7750ffaab625ca22f27b73960a329534cd60dd3a0cba2620c2fa3f09967af8075ef5e4c0f257978f0a2f5963dc185a5ea91d4b31addc99baca637b41ae864edb6377295f3aa0d07b46722d38e8db3beec33507542c2ae3ccc4024626d55cded18e0a96733c903a2c084876309e3f00fc307723f4731d187c4569dfee2c5a0f0fdbb871690758443f5ebc363203f5427c45e5448f779321888ad8687a907df97082551aef75bc436d6e9bfc53293219c025f5671fd1af0455f004e68d7701ac7873de392a9c1aa8ad089533d831ad66312e1259bae1e368d3d1703c764d285b9310c40c88f1274456bf641fb3d996ad65919d77c1b90be006e6e18bee4dcb1ae2ef31c39980ec9e25c6b3bec4460be86b9bcc1bc0a476f67ead41deac318515c561c3b1b7f812fa5548a3fbbe8878625a21df4f26a759a2dbf5f2962adc7b9074c28e796fef72f5e069886d9bfdeab2da21a7e084fb043a77d526e6485c6e2f56c75d2fefbd925803b8b37dfbb08a3088800b5b245b9ecb320f775df47356c466f9ef2989c7ed03b626e3f35b1f2c01117892aced75e87e8e965527cd0a9507e33a2f388060f78fa47a929e7441b8eb1fa4fecb63bcadb881d08019ea9f69ccb5073d93976f1f2fb39c1f3e64ef5bc2e5235657f9ad6714b99ee19afd4ede4dbbae769ea84b4da014e78c677d8d6fd98d45250aad594564a6bd83173318d81a8c82374deb7b86d87e05f638d2c3b18f574f4f9093fdabe5d3042f7e439055f7441a6a8096f2ba6cd8279d8960eb7c3461f7e190a4e6adb3392c5a438f565ece17a78e71d247bf17bb5e46e64db1044b24f70d89cbb4b2a4104f1689d957b7379df4d3252a94363418712e7593a1b604ccbc1b9b4f9475a56402b92df41652c6280d3714f63fe6c84a63e13e859447cf1f7a83efc16e20438f19ae14ff580ec736aed6c9f9b784ef3d9c79e2c9ec501f91e70f87f262158f7b703594b3b1a4df0539c0bebeecd0caa13b3a1ca791eeca163a45327579c1ee534cd06869bdd10442d11c82d6c311af7968e1dbbdc2926840bad24e9362c5c74755eb74c1efaa6d84bb1a90805d0c5aa6b63c6ffbeca8e17757a075d9725e36976756a60931f852f8b2328909dd9c740a0cd3c1305a0c42627319610ac1535a4685ee0c7825e9087218dde845b10016fa5b025bbb0217a68bb5e10342bc246e988bafb872b144d962c91ced19e7672b1ec424813e8b09c85025f0ad5115519607530ed757dfc5089f33f419d8f5d63514df6cfc51335bdabb604ed1eb29ebbf5d5de54f3975984efd820b1a1b818a4e5385c7bceafc4ab0fd1ab703cbe71d85a577c7fcf711310bfe4bfa997ceb5d20080ffb3ef312d71620c4b3a274b23a22c0f105db0a32fa0070fee82826f731505d8ef7d39434130fb961d12dac19f5fd340833e6fec8963b051da5e77ca6b128e4e905443f34547d1a407bea6997e253ab33fda64a263e23b23f01e6a9904eedc0eedfcdeff73cfd8b64ec21b72f69e31c9ec6e0549cfdaa0e99b6644c51d45954a9666ffea4cd3ec67b3baffb9198c6676592691408bf311a9072ebc4b05e5ff0e3c7aae3489b036e9ab25bee8842f16273342d04a3b4858605d637de58573caf981dbf5dde16cb767018ee493a12359a367f0fa5bb15bb556621492aeb5fe1c0ccd5fe4d30ff2f9e3350f82d93d454197a6c01735bb8b0ce83a73628a521a1588bfcc3cf495ec610858ebb9cb54f9f0b6a067a079859b506da6402d30e9689346a2890fcf8913f4acee76ff7ea862950f9a031583870b435030657e2bc0ef13292ef27b86c8a98418feb1451b7ba35ac788f6d1298789b6881a5b175541d1598833dfa98b41345759993978d478e9f9c3fe39aa84e3386877f79b5006e5eb8e9a2407fc45ddddc8e261508066c4b1fdaa44820f1f9540fcc4a66c1ec328a252863b039350465684680d0055493a3fcd104e1404558dcc944003bb1130d79e1bfb0a8f65e1308339b0f539520e9a05dd86b8525c0afb586709589ae10caf6a68a73de07ad284358b2022510c1b6cddd14980d53d7eb71b4593d2d09201c92bf56e15f9bceb9cbb847891c2f4d9945a5e7483eb583b70047cea2933db3beb2365149e1fe14acb61b43f3510b14c012c2630d18823bfe9345a45290dcb901cf9c0ba2143d3beb7c929710a3a02202f304d40c26cd4bb619c519e43534f2032e6d16bd9d821c5e0a275b1c4315b93faeb80ef5bf08499fdc0dc4a41fdbe704357f2c371f7fdc05928c8de11e31c50c6af2859f488b88d5f9286839224e7e930ac439a40afb21e323df0c07a003fdfd4d74963149a19cdf92d31561d1c46482c0cbfc8588a886119c60bfb1cc94862f70166a03d3ad3288e9fd04cb1b22ecb065e6fa8c1303834272334985076e2dc1af3d1a31b25f330f3c6838a11920113f3ec20cf5af0aa63ebc63c9a6d21259d333b3a150fa0a6ee39fc5181895612388d0bfb7a01bf0e24da0b0393b08c61a13911db27c2fe4d17c78ee26f4bc007a86e94a1886edc902ee07f4cbf017e3bc5927cff4e4316673a46794e992adfe00fa1743cb90f38a409d82c7c062e25249c26c8c5ab32670c5b79e89666ccaa123346cf62f208687686566434d7779a28674039560ef5ae79b09aadc4250bcea899adc1af1846c7088a4dc94ca3a3e0490c0d8275971cb64710c72eebe266a7b779069fcd078708e6ffd1a12ce691fb981d2e75129027da921ce92ea0bbe5b146ebf1f3f11312e54c2df1de625a2b1bdddb1f0b6729956a185b3ed72287bafa9b96e6e5cd3dcb1bfebbe9a321bf8006d3a86d1daa4514756d6626afb0b3df9a5bd85225bba8b0579f53c5d73367deff12238ab4e445164e37891d0af83690c67f78d90d44ca7ce1ccde0cad0d08fcfefb7b013df089ce43c006451b955c2259ddaedf6809492b5c99cd5893e6b220428cbecd74e89b6273ee74eadf682fd546992f97f49a0f031196890b5513c72521850277e7c091d708423ed18c528b0aa1c6941d151160516e7a69fcafff5ee58059cf668749891804388114751afd95d61423f62e19045c78d6467ac036babc9aed214d9be9ed565475d0562a581db0f6d9d18cebf9cd0d845f598023280cd96a81545df7852f85c24a8354d2b90ba707e2c524030ba8d0ffdc370eece9caf793a20689a1e77adf7b81a6ca66c902a18f1e9577df1e28a588ace6ba46738ad97f83d0da1b11c190a53414dfc3403b9fd2b37c12337fc11fbd35d729a959eb65bfaf1009f3d4191eef08a65c440a1d990bc8aeacbdaac7a2b409fb572da886a22176f125a8fdf010ee59732c6f74734fa6c11563c7deb1b72aff3903c5f8db613de4705990478a5c70881c5b91e030f30abede23e70fcb0eef078ad3b8d91786a826afccc04c4056ffaa81c5bef0d165722b1e73852306681953ec568c82d395f6c56486d244cb38c758cd92a9a9125153eb8859fcf2672db1122b900cb81b13235e59e48e7f9d4c54bb648ad54256504bcb3571379b024332dcc85a9a336aea106ef67ad5e83970f0c94024d49d47256e17c59df2bba9bc9207d54999cf467fac67e8baea6855fedd933b8a45c8ce6580ead5c0d15f305c591286f4f8bb0ce6d6dac0b3d1f1042ffe2b76ef8deb491e9e975b604175a3f408025bc3c1377689fc1ebbf2f1a84547cb551b522c068f16d8f58246d15cd28bac7e7f0ab6d81f8c9ac0af2937027a3bd591a0145acca04eb799cb50c9037935a43b535f94c4568d1990d8f553bccb80c25f75a3ddd7e05dee4af0c53c412d8e4d5a6f559d2fd45264a6222fb6fa117311bcd468e3d0fe8e061b10b81301487f3ba9efe5f02125d1f06d2aa478b090752d38a29c7126388fcf82ac3d3fc2cca85014e371d7995d700ca650f5560ed7b500ef38d714691d5055dcb71665e8c9583a28d11b97c8ca4c3e88d9237cfa9e10c9b693a8f32c66d107cd4315809ab3d783c9f1b369bd2dcd10e70534f58aeb28deb85d4eb6b5f23d3a09b3e262e445235a1406df4ac09aeedade28856ea6ebfd110aebb3de325bce59b90de3517cb62a216ac1359485d9af6a09523bc4c2353a0f053f091cf75d240f3f43ab17600828e1f1234c82964168b33387d93a237cafa1d5c200fc4d3c8067df1e0f67eec208a0a7708e3edb37a48dc7b3424d084d58805659313944d920f26087eddcd95f2e93e072fbe82dcea4117d2bb6f49f0a0d8bf641113011c08f590c2c8ad079c603050f54f73d906531b2875a2164fb1df039a5400f8f5e2d9320dbc39e1e10d9386ca487a2e1f106c17112cbb2c1aceaa707e3f026c872fd84bf1c55d4a817754fb0c0ca357a2d42eb7447f8ccf783f447d8104469541b76557087e84e99dfeff4f22d279cac23139d8618422a60a1b12118b19dc6cfe65e0b47379ddde2fa88a6d0a66e2b2ec26eb26e162df66c0670073f4262b95fafe612c01fd974abdc5848722539e79dd1cd8c7e354f2bac64a4182b926efd6b094bb3bcd08612ec6d3f79429b69b65cf04aa5c53e75c086b1e56a16c104fc1d15cc0291b92a158269019e8b92ffe2ae35cc590022fd5d3107d427c2ff341d653e7371c0453faad52d2a35b88838695aac1243cf2e01daeedc3e321c850fa3ab9b5f18440fae7cbbb2c63864dd2138673c25fb6c7c3218662a16c932245104e76a589fc9024d4ce40199bf53284b5c3ce1b9a2d21f5ae1a265ba772f4e3094b200497b42a2c2709c19074741638a11580e156f2e7a12ef9e12479d6c1317bf5728589be7f7374360620d534fbb0bb34620abe60752acb6cc0a03554a5c702b1959dd2fb19194213ff80f2bb3cd89189afb8d53bc7ea4533d1558ab62d0c5ce070ab72429d19f8890ae6bcc5c58a5b6eb519aef08f107c14bfd05d2221cb1bf3b4008fe661dc95e9c5c831b6497d76860d4b67fc789da11e6e6f46f5fa593c04d445475b3e7e397c4c06150133f139a6e4d6dd95ed164bd6aec5da31ffe8756856714a3b200215bc7c21b2343dc7ba5357fdb508afca45c79e47b37f07c3ffd478ce4c73b217f8de49c67f9ce97ac97f2c86b12df00c41f258640fcea69d4135406c02c4c3de8b05e91d079c73357111c20f72b60c908b384dab724a611ae3d9935304f66c1bd00a59e83a682c741d24cbb993681c9cbd2c9e1c2e31096428befbb7a0dcbf913dddac027637ae2da81e4fd394fd6abc5ecb5dbeb832bdaff5b52dc4c0814782515c5680f60c410581cc0869b5b45b8bac4a4fdf8827143daf777d6a4ea6530c9a699bce3dcac5d24c19e405556e04100d28247a1a15640ebe0b8cc7585da89c666406a9ffbe3ed340e630eeb52980d7810758041117ae137095bd0d1906f45a00c05c2ad7b24cdc767b625349217333fd53cfef851808ed3c5b9e4187370ce8657201750634f5240421f9022531a072d819721414ab625e430ce814005dd15e31f9babbcb6a7b5302a66c06b461241d7176b89885ecb4248d65b6d981c82b16cd01c50bb4abad4907abc9333700524a9db219d0b2ac02bd86d15a592aa06bb41cc48348fd4ba8e588b64019d3db01c0d6269dbe43844a651f933d21da9980761dee901118ac23f797727f6d5dc2bee0bfa8306295c1991e97cf42266883060aee706fbbede3e75c8b8161ae6e251ce146501e8aedd7dcdcc4ab5a7bf6f9ad178ea9526c2fa3b755332155abe523fa6f445f6b79d4b74a2dd9ecb68a3ee0b1198127262bbf889a71f98e630e33f970512486f31d9f4815957c2855b6be09db6fc11cd74a320f37494c081dd601b67b4a4a2b876da0af150a3e473194f5f5ae63a0a06d41bc2b7cf3c601b83fc97d2494c8a08f7df56f0512f7f649c1a6e6773e7a49aa000ff2b8a0aa937233593bfe0054894dd34fa3000c3bf3ac97fce66054e4ab4b7cd5048fc38f9e769cf68a87e7ba1f285e7573232f765942831c34f1b84003f2943e8487b66f11d6795cbf0c6ed307233bef4708087438eb6143ae4acc5c698d2fb96dc08dda7737ae7208aa699795368a7d50eaf4b63710b5dab95719d2940c3a3e4e3b43cf1690c0946ce196907f637ad6c42804086b0b1aa946f23e79a66b434495741c26b1a1dae85020bae8b6eed9098ce31fd6be90ce5b2f3b98724c23fcb867ffec83d7bdfce2439a2cf85849f4d92330f038867d8b78bc1363e45603eb0be23afc3a97404e76d67744b89aa00a1bdb03f9dd9a7f6bc49366c1fbcb29e993f9d6db0cad1475d6d35d206f9df4b7ce71587ea996e9fbb883c0f063861dba6e7274c9dcc16d706459b180c17eb88c89208321c0e56b50885baec68cdc8304b9d847c4404cddd202b35420cfb358f211050ccf4fdb2600df0c5f2117f1c2707eef55731b1ad1421bb5cd20541b0ed16a68daa615c013e5fa7dad91060f8eb688622ccdb7906b7b11d191d4aaedab082803043d3135ca1a7a35b49498ed9d527ce1a05a75661e4c7bee9d24fab255fa71cb9fd2528084311232b61bffadd5b04f5a4c0b025b437da6ef1f7407ba3790b986d991b31f3e1a1db9959479d6a8d700cb9257e62b5b8e98dbf989219e421f9a40798ed88e67585a0127eb72280df844aa9607ff44991d3649fa731704de8dd05f6a4e060e1d321c82e20e88904b63424729a66b1a54df98c10514ef3b5036af547beab3e372268890d01555f385879bef1c58f00b5cf8f9865062cf0ae2fd5ca10df992fa4a98e704ac4e5776ed4203658d89aca2f446594b52bdbf923e88e6c9017d7e83ec7fb757c58e4fe9512b5017c075fae4a30d95ef1f336e13f1b961b9213bc92b20f04a91178db6b6a8d558e4f55b3aa7aac671e9cd46b947e4a4c63f20027e89b6a4a3e2d028c6af5ddbba823af35a180a05e291f7703734947f824730ceb53c288a540fda1c16349747e64786bec371106b2d6ccc5b0dbc8245f6e8dd4b75d42be8631ed1b75670ba532d39ff3be09e3f43e96d70c197d947e1b26a25e691e1c2b3086853c574113aacd096d66e11c6c446f9f833a66f7fc59952d5c119f4500a42d366f6527c5cbeb04fe7d4b0cc7374d10179cfd708a9176d31e1335f1e5bc8f5a2d72b3fb7173159650cb005642a5fc756d2a8e37c5937b383957fdc4efe7827157f9c1f238504e9a5c2f61d9b558840eaaaa7618798ed73be174776200f4b5210f1a48fc60b325944f2656b1d8c6f81eef4d63070a425fe6a4721f8d775674fb14d0f0a117e0a9006c2bddb25b63e44dbf9cf045b582dc5a9f67250820d2b32442c6c0c71c25f7d68ae25774aa11909f582d4e2448b5e0eedb89c1f9013f6d1a1b84123fe0378df2b0a889a1344d667faadd623ee98be2fcfc7d61987bdfcdfcc46377ca761d255bc092b892aa51252a4a1e4a0a076a7cdf19a4389c25d3b8e291fa5951bed1ca838cad64eda7044d3505c5d6be27841a3bc72fb3e340b6585734d1ca034ca552e9a734cd1283ab73ac87ecd8a048a65fb9ec243deab8d7f62c02347f82d69e1fb6adf51fc4529acdd89db35772abf20a46bb773b3f695f2574d89b5743d303e21e82ac3b0be578dc47380835b6dbf4c069dd088adc6853abfac96133462d738a1e62f268bd8afcfd4fc62c65ac1a759eeb73fc29a2c729ffd01d62c994da5a9133f16b827eed58bffa1eb0f383104e24399204c597e2d250b5395d720cefe60e70ef5bdb0e238b40084fe1293ce10d44d3673b8f8fe9f472402de0729f6c5324321484d5a98fe364d5b8b7a64f270b471545602c172d952206634c09060fe1dcf8cc80e6e70961e210598fd80bcccd0049c305dc37c30550eccd5b2193a02f5839df62400ce364bae899662fa4655deaaf1e5548da00ec7f1df68dba8430afbe1cd5b91960812d07a167560ad7ed969e2637925f21c607642866b6fe9485b4b0129b38aaa3ee2e618e8185ddfff2e0898fda04292e58cf978897c16442630ba13b168faf2c6dbaf315e410044ba0101acb7ab00de91bba4a7a6aa1076513252a2a90740144e720694252699c36befe376a23516f31ab2780469a806653fbfa831acd224c5427fc8907004ffd9525afe90649ad1a7654c6c9513cb17df93d1776f28da19a98e0016b09306c4dc0368bbd3b72153a9c4668bbf6c5f403d91d0843cbae696e130c52265875bbf5698060097a613c97440197c68ff60855ff0d0d723de086fdcbac4c673635343ef05ef28d77fdc29c0de59c1509f92edf2457b22269e3ce2bd3c584ef0da176fd006500bbbed11d7cea45d5a884072ab310af211361ad7c6756d049155aac8a54ceec573c3858d0401cf9dae33062d4891689b8dd72cdd00210468dd0f3dd1e3f7772e8032f5c7339c9926bcd577397255366391315bf087ebd47f1bc14cea91fb004572d11f7f1fc96d44ba5b1d76ad2b0ad7dd43c2d3807e1943a331d9c46db5aba8f8920c77a52a487ba15cff5b19db71a8173c0dc56e99f22224d0a57e4333a187684e61ac177ff4c9f3d3ad97eb7c20ce328835a420cf6e3f824a3b55b73066848b696c535f4be21844237d39de43c6c5dc02369506cad7da6a78e68f6c8a351115e20a2c5e26158d684c3380671d092ee7a5fc47591a59e5059f28c4d0793661f92d513b167fb88e70e3800466bfa12fe88a91ea93cc5f1fafe0680348643eaec33e25d236e92b13e157b8ad7f1c56f471cedd6dc626e46abae15207db43bde42a4807dd0899dd38ce772c4e1629538202b5f38ffe8b4e9cd8afe42898eb15aedfec9bdac65d40928cd00f7b37fc184bf5b857218807ad5434dc21b48c980490df7c056257004dc18221891b03604080f96561b2df0078e382edd7c2c8d647eb4d33e496ba6f5b8b7456c786e4ca959266b69d3eee3c6090966ee5f9150b5cf56c221705bf57f90e3482c6ccc93c21076cb123f46c7c7765285b072787b32fdaf354520e90d136a66bb41f89c60d91eb111ff9ca39e4a48bbdb6f17935c7cb506be31b5628f6a044953c4527b41f44df453d6d1a18a450d0b4321ef3d627f9c983755741fba1aacb7a7e40d308d3ab7b605d5de2d3f6ce8e66d1445e2500da549ea4743a2682a3a5fde56c1485e19c1cbcec3c7fb5d95936dc2805cb3d6c38570827b3889e7ef62e322f8a622234c2b083fa264b680f6a488a5e1e7c483db12cbb6736e65046b7c93fa94c3f2b88ee909497a51999d43e54732e7fe9359e0b41f1cf1200b9ce0e2913e9c63d6a6d78103954c23b8400310980dbf6c9272a87304799a0129a8da23622f170271bdc832f210ce4f289b905c6fa8bd26eeaa3c5e202185d78fd9da6debc5ce45bd3c7c3683b70f3682a82a909b2eb279209667cffdca4b1d4dbc41312b93031db52b9e352d9444a43205c9e1704344a031eeb4113790466d522a3d6c8283d7fc25ecb7887aed4df6c7e9c1a56225c134db2d04655195f65629a169a0d00f637ecf9d834e6f47af2d51b0fa0f46a1e2622e6f4f08a9cc47fd44dad10003d267370a64ba47cf186577b43c908aac18e3d11d2ba931b4f68aab77d8d2925640bb034a0d915acc87fec9d8d1bced73129eb6a91514a75e10334cca42b23f54e5d9a7f3118de94710caf5dd1c335226ab2b45bef6dd88b7555841bbe902f259814fb7d798c08e6e38fb14a76eb44881c9c03a1003e8f3d8f48af3620e8f0faa73885fbdf02ba76f28390869d9dca13ff9e2c9f6ff0b52b6523381a43c1129348757fedd3b197ade5910e5cc956c8acd75891fdc4b2c59deef4999cf8138974fe88a0ada849923a53fd89c114aabf50c64fc38a9d205083a0b117bf176608e59837b7acee57a9edd0c0c816119959354b26fff0adf7207c781414cd6a75b372b3141ec75c7c7b1fef0f12bac7c0a75482b66adc9af8cabc880ff3724c91f8f48e912e05bd7d1743271398005d739e3378e8c13f22e2da4715ffb1059926c7cc454623092821892be6b31a75bbd5ff5d84e353b02506440675a8eb22ffd2d2bc70f1b8ca0bb8e2623e1560365eb46d9ce19ba4076819424af6fae303e49eeb65440eb6a81cb6319626703ff119f368b703e34ea6a1a49baabdc7dccea78bb66e2df7e28c06413954f4a0d7a54fe7b8f92dcc6c963e2bdb7bcb079e6c3f4af38397320d94fbe4152ca835ea3c97bce2cc6ae494651ac1a9d6708f21a7b827770d1671f1e90cd9c128cec297f93923139f3918adaa4e84b901e7b419f8a62a47da46122996180a8ecff9524f0bb375402169ca7e56d6c37c692e55d07270a56fd8bf785489b940e0712a0d0c142dfb48e926a4b36d813e654101443ac8d895831bbca3f86732e066edce750cc0b70ff25b69b307339acd9227ef3de9185b184b25708f4653d334513f0b773677521db9845f05d76be48be4f3476f6a64c1e67f6633e47ae7d85966512fa25c43a6ea7a22b3484db6badbcba4c725804e962a2cabe8e392e4ef8b4f021d8395cd2f036e0a96721885dd7982d995666a89c411d837b35568a1c465a84d47cd8189a67dcc49c8685c8294001939160b33f021e4cc6a13d104bca760f9eafaaa4f8e5bf52fcf85a605832c0fa7d73e46bb2c659ef48762757f466216ebc2665cb8a55f27edd36a162748dc9904269564e11067f25dbb059eeb229e678d6b559aa3fdfa5517d187e32a5cae219826e3a0defb67c92f5de2ad04f5bb64c0faca1bc17dd23a1a6de8c0fb77822f1ee643adf0f5b99c7ba4c88d83af672f4700e9d4c3cfc697c9064e41f9afe8e045c189138f11a78681abb2b23b43f7d30065a13c2d8ccb02b9c60d32a6bfdc6835409a7ac2197006accc45ce8bae7b574d0fce7e6bb9c94f26fea09b4023e5cb3611607ef35d38ef1a9e161aa4848541b434d64730cd704699771b934b3062b482c1fe2ec705ef58ab8c8918469fe43752562a8ff8033a8d369eee925ca62c25428ad92ee59058c2951651ef615676a741a1059d1027001b2f928344048232c2217bead31b0fa3ee282a0bb16e94d0016c59533ccb3639156dc023cec9ff5da16081276093fb504436342b0f82e1202688f0de74f38314abd14db9b297258b55a2901e31d5ae174c9fd712f86d76482858db61ae81ea9328ab5885e793f338c8f49f0fc35d3388be548583c71c14d2f15ef781266404866bdeb082d1e534c95cbd2cbaace1152e137146d015e2169d3d372f73c657c5149fd3b445df5d9007e2bfd0b362f8823875a78ce9498d3c656710184edb6cc1ef6699951f905667ebac61f52e77c79b508237254c9de5c395ef7e0653b401dbb07720629ddefccd13034bb87772d58416d82d0fa14c3a6fab4968a077a034577d22c63169c71072c1c51eb4eb6d2d6dc1a6339ee50faa97ea7690126f1d976474008a68e3202bd20940989e2b12abcbb905e8c7d053960eb9f58e3ebb5cdfa2b1d8b9adb8c419b5c9f215f24722593c692c5934758586456283e030a1bc97829f9e20abefca06a95c8e6c00ed01c30e16599f61e344b01736d489a394a5f1894c4e5f67b679e474271c0474ad8e234e364e18ed11a4ffe855494791e4d6572e6d52a2ecf39a99642060a34caec85102a3dfba16db7a322b3f9be051e97b4c6f1022afefba7fe6eb673d480e1f7792ac5500ff16c9e0b165700773c2d785c61f392bf7efe30649d1e0f445e9f6e960c24cf2f038f99359f04f2ac9fe5cd86467a4d4d597045ff243194438fd2883a139164aca677e2204367d82dc7e780722c2a78c17b47b8d77d4076513861af0883f1a6c0921197a47602f9847db8872885d9273fd4177bf1626094053e76da531a893535a32ab99f62c556c129dbc66e0da34edb3a46c6368ef726a780538c9bd8ea555a581aa698c3ad695a30efa4d63709e27c4ce5a9ef00ec734954e21d4ba95696689de3e854c5fe509a47c2d75e8d89183a090ee62031c6b2edeb36f98cd4384c3ca1921842dc4a15b33e122be86072ef8c080153b03cb8cae51dec2db229db6b7244d3792688a78925fe8fbf78ab8db1a381e62ffc9c4ac183924e6e030e56b263da4e07c94a183070862f344ba01965cebd1ffa392a1419567625c628852241d3d013ae8638daec50f9f46d216d7381990ea04a18a25a41fa42d8ce0941155ec00e267e404baa41860c38d6ea7448a2023d11131f148b8c0b3baeb73aa58e0ac0929879064b4b05b55035830520bfffa8f9b7452507d4ce70ff77398b2205432e8f42a60f363dcc0ce85a2e2ad583ba108d1a38bd4705d189bee39c49786359a98c006753fd0a05cd9832939968990fae4fb73b2effaba867dd675e492fa5342f1cf12730cb116d50e2d166746fe68c96d42fe2d2138de69cdc5d70f3c76ebeee2c3f39f776111c1aaa8d57bc6a51fc68d24109edee97f6ae2c4b422b8b10581ab416180dafba0a62673a39e9677f322c7e933f2b5e644fb2cffe49f601ade1a4b8dcc0fb0513844e91b8eb57467211f0536737c007911e0fb6b36d1079fbdfc8ffeaff0de2c0d440dc44fa0717e284ae09daa87a879b871b52f175b1eb7827a2679eea030a7fa679662f84bbcf64ac680452f9409300efc666198b88615255a6cc4b0ac52e2a30da7250828b8d60f377c590ba6f443dec4596e877cffda0bf2adfdf14ed2e5af064d5e4f6fc6810918c536e9694490a947434c57d1aae4b4b25b5d0f0ae811fe665700ce248f6cdc0551ee59d03c07756b0956c0316ebfcf1fa2c1461515f281d47f27968763c57b521ae840cdf9e73b9ad9039273c0ac55f0244cb5c8d09de8508659ef979eca2b5b6f3bee8487f6a07dbd10e0f66c6d40df60f1069c6d0e6f4f0feffa810920debc589838f18ac87e87c25180d58212c0db16b22d6d641417abee3222d952b47d831f19623b23a5012b5502e5c8f7b4c60de4801446352043343b5a433d239ce456b8e7d6e81b939226902d726d1279bd5ef4cfef0335080dc8c83b8996eaa29392680751cdbb9dc3324296e9bd122bc88aade2c2261c272a448637aa0a59584bb0adbbe49c4f6fb1571a5e6519852ee0d35ae49f12c1bc436a42fde4b893c3676168f43f8f64057021e74b40ebee1b70e3650825f8ce97c59bdace6c0fffe80c34dc4ab59b532816292685c421a25b1ced998150da9e63c510cc9a0f44cee6af24a3df406f688c8dd816e7582e728b2e9caa3f6e0d246151ddb38f92ca0a7c349eeda9061efca96a4e0786347bcc85a0cc9dec291a0bdc0b9ea031193acf5a12a9016793ce5e28b237c325c118785b7a26eb2c0da7ed6d88e34e4bb75112407a46bcefe32ec8244f0f4a0ce3e51ee810861e94ba5e817838f8ae4e10a7cef480453c839be9648b7add61315824a64471d594ccca6a90b2baacc0c05a935ed9506c86e6f7fd5e2b9785740f41b325212e70d59b51bf44a1af78fb7be9a715a53c46c502306a0390aa18eb698fa03e1e15752c0c792c4df5b7eb8d843ac227ebda1b08ae141505be3a5c92ba9c72c96b1abeab90a4f327b7ef2065bae77e99c67a04642d50f4b8c7a9187a800585a8be22233ec86974eb1dc5396dc283e4e7b265442b5354d7b73a153471daf67cef98e6791acfb2026ea1ed9dd3509aa45b7a95d911f270d5dc047c72f6b11c857d73fd1c0334acd4f63ebec6f490740ce9a9cff76deddbf5e08029076926d0308da47ef51e981a86c8c9bbec87fa1d993efc842be6ddedfa2ef1dd12bf63be8a5368f173a6682c9cdabbc862a19c73617beb8fb52cd8b8e82c024a84313d9d02a046e88b667b5dde0d9835b94025955d4021d060c68e70ec7092d18df5925cd144e103dc3107b62b166a480025a7a085058e7da2fe49e88dd366a8cc515514c9061111093d64b7aade403f253f19e6e72d29d02b53af5bf923c1fc3e1ca12250dc3bdbf705c30e5ab726002035978b4e891db09688c962dff7da7874f8ec6c4e57477432a48c92c10eb611583a557f694ad009dc62308977f78cb1d04a236a0dd2bbd50968493bda533ce2391f1be53331060dd05060ecbfbcae31897eb49ffcad3dbf10f76df5bd9372528259ebc71bda0970e0987cf3a6b5c56bd227c121a470ea30263ebe82619dfbd4c36e4e0dd1eb2f35fb8ed27917201d34bde723550d2cfd8991d361a83179a52bd26d26891575189b28d8c642a403faefce1acc9ed0e1df259a9d84238b1de755c10fef1fa9e94673035df28b6089410d9c33f164946e8a1b6a4e32008b4b56a33e2e201234b10cd4f7df74c7181da60d256aac659175d0b03b0980ce4b0325056f6b26d6197f78a2d0e67fbf39f49f0f412f43708b548dab4f7d4bf80b6e6723f413790f0eb1aec688f4626aa9ca7852572432e34dae209601cb312b923db6532f4fa56228b1d95b2a9062597a1e06ec789cf4f66c5fbe873aab463f11664dba50568e7c56e3f87afd94f09a6632451780daf0b42ea68db3ef794577017c631c8b273b0ae8dc6a57e0da3e6ac92a40536db3b8e0d89f74f0aa92a6e982c91bcb9974f9eb4c1b75158ae8ac5b17bfc571aed361ac612755cffd9912eb3451a0246ba6b6c6dfbbb903783cda2c99366627778a77860d17979e1fa5dd1f6e033f251df15f2b2303ade8b124b679fc35cc229313c6be8dd99de025fcf0a023f5d397c22359a298b222950aae470884c04deb8f0224ac2aae08b78faaec8cfad1ec42016c9a053402af9594ccc313e744accad40f39a4dadbaee3d3db87dcc17edf79cd34506b313ae9595ec5117c75102dd40f888adc214ead654cd869466618a18e1a39dc25d45152e190ec6bba892e5ca272c009891026b3369162e6c3487c93ed20ee386656eddc09d704835ea3c6a08004aac389a59912f5b5ec04c20afeb76cc8530c18a6c19712d29c1ca377051bf917cb242b481440d7f3bccf20503c555301237180bb32357bea4d18b21bc2d941a25b1af46a4d0237361cb40cf7d99093cdacef0a152e1cd3232bcece930dc5220a6ec304040140ab6f9b3f4df1464c146aa5b24439fac1300966bf651e229a0a39d8749e1f782d4d011f927360637fd0e178e09629bdb9e2f86d9e0b9c03eebdaf4a3b97a03761767edd0df55e9403d542127b891e74cc9b4b049d2c3e813fa330f71ce1d1f5b89a24d82327329f0a4ad3a853c7aab0435658ff68cb802dd98578e17e0021828731ec97d7c200f6c965a2cca2c6d262d4581ff697addcde505f41a50298f104e5c4039119209cb0dcc8231d9c99f4093c54b60d81279b4bf55d70234efe58082d5cc5e8ca297666ecc03baea4fcc30312f93fc64ccb303f3aed6de0b81883d43d71e4ca6f8f42d667907b5e4cca36cf0b267fa04fd58f5223ca7e484ffa975808fe075a4751c3e4994866391b409977eddc558c9e894cbc82e966fd64f71ba7c02441feec9e2b942966c4a06942d5994b246f44c8f0093a1863b42b0a5f7c9a067f5f15691ed323a7da81651d04c6ab100dc330703f6762f03cb21ff44eaa20bbb376009037a66a0a34d1beca9e7325f5f4e3347928e58b66016587f3b27dd4594f9a94ce3314807c0734449999665077e4a0915dabb9186a5a5ace9f4d8ea67c8b066542230bd0f0dd6750d33302e90c9773066d6f461acd704766101e66447919ce5806d92b23d094e192c9a08564a41719ee840cc23c46f49f6338cb1864be18012a864b1283f68891f661b8c730085118d1230c2707832c82117860b83460d0e62f52f885fbf50521f9229abd705e2fc83a2f02c10b17dc05edd945cabae04153a7ace0a22cd2259673598f5c1c3e2e511b2ecbbcc519dc12e168cbd20f51bde95a0aa116544e8b20a185e7e882f673919e5cb8332e080317d1bf85b3dd822c6d11005bb81cd55ad8cee40b01a2f0856490820fe71cbd577f62a876c5e80c787e228123c1c4b2e02a6783fe83684530c5e40b06531a80d1df67f7fc29934c55a2ef0d93f149a7c3c79cf691618171ed9d838b2c8d1a6ac83100e970e26d1aa479522fce2709934857eb2279c1d365ed67db4566acf90d5734f430aedb288d6a926b1a1d756529da4ab1358cdc2cf8df9733ec919f97cdac261370a1dee097254dfaa0de7c80794467427c81c99f370f8435e9192c68a7a3a21601806e3d238cdd2efe631cfb882a37630da659f30115740c398bca95a729c1338fff825a5799167f56a2bd17dd988736262efd728ae6abac716e847bcf77cec4594f12fe9635f0db21c1bc20cb3cf567510f78139e9e09b01ba6fcb76b00f70293f9689641bae7a61efa26203719619f4e79ec5542ee1b7d929879c45ca017f5d289da8fa9bdf520c3e8efedfce9cab319a033eff34d7f4f652c1d3c963f7d7b9f5174eb41cee8efedccd3956773a033ef339bfe9eca2d1d3c9679faf63e5774eb4186d1dfdbf9d39567334067deb2724d47b337266882f621594c518e63944d44e8fe9b7b30b515fa6f767019bca40a6e23f102d44bcac67f168dff01c1d5fc094611402f9d0e341ba05ff45e5002c5764434a0ac6718e6ea73916a45c7d2cf73bdd4bb55aa4191a0a02f68b6887e8d71795a6006819040e1b38ed6cf5dec8b83856cf3ecd3ae6896629fcb18fb27c9ca6b1c8d7dd6d30e3a909df5d451a88d7c7ee8f08586f45bf9f468a910e66df5c06d2cb8a01cecba0e7216691a16c054e6a593b850942f7520b114dc945ee163619d1602053e3f3850cb6d7d71e98dfbec82e188685db6dd438126fc79d39d30920bbdfe10f1202e05b38c96455ed108cb81fd6b8dda957bfdf3a29cf5286fa40cb6aaa8ce72953e2ee0e419e2fad3d4fa17e95c9d52e1d2b9aae66f4e7702eae9ad31bb7ea5f5937d97d02745836b96e8f879754e8f47032c5e619123da3c322c99b475e6b39ef77e3c497a0f596c74f2ad551238fe785b4f632db4ebd9daeee583e8cebd20ffac8afb4690c7f6e37937253eed350b8c185b74478bf2672184674c866790e631c980704d851de7ab457093f4858573118b4754dc724c19328de522cf8724af4143c451b08fc819af97279776638eb1030da4bdfeaa4a70078416f65733299334cc9ec3e819865da9c8734b1f91dc09875180e401644d089f32aa5634e88916fc807ad880cdf164152f7581a5eae11fedd399ff7935a95e09161cb4c01357d0ca4ec47c13e9e8310848a484bbcb1d72a46d2544dbc3c739e47248c389a3b20072449f0d98431c4050958ed628e601b7aa7cdb69ab4925be1f17fb343c205cdc23bd8fde9c72d8d3acfd8474cc0aef94f7a7bd45a87631c18b932ac2444ae079b57b1757cfb1e45bf0c2e9883be1ee35b3703b65fc07eb34f66b1a48c883d282bd722ea1e7927b99c8b12a589f089d5979991fa3e3c3880c349dc5f1249ac40317832c3f17adabb505276bc43f1d441210230315add864ebe0becb685207fe9e8f219155a2a3a548831c547a948ff939eccf06601be9b054bb03f4d14e3de084f5a574dea656bd31a5b9603e1d86e748338ed598ef4ed7ec0c9cd4b2de797e25a38fa9da1bb4d1ae08e3169a2a320000a815b58ed2a1cfa4d4fe3e98dd4ef29181c3704babe38833b572585f72d492aea0cfa3fae4ba5a920f4332e7830b805ed69e13b7c015ea3a339adba44838e5dcde10d420f34d079c0dbf92edaba5697a00f3372b84455cff7d20093aaff501c551dcced18415302713451c81475af5d25de84d895a50f71ff94ab0c7f953950fc360acbeec5bba8c97b86a03d549c0b8b14d6758dbec6e2fe33a9015bb839c5f56e2cd50228463fb563c09ae8538fb0b1fc93595f0dacd36534330f29e15d336711bf9f135495201cb8b6f1d89b202c473ba43419f076569ad4b763d7e71e635be1b44498d891db3b1097c5e840e510520574fa7730259f041f746e5e224de6d9b758b2d97aec20a02b4677af5473ad2a65c99da5e47c00b8d37f14a86f49f89fa63830045022f81cbe399ccd166b4a40f20428338df5a91d00bd25f9dd9a1f8beac9591f8df9623d02395eefcea66e908d54c5c749dd1ce0f805038fb1563578cdacd4a5aabce1cfed14baa8a4ffaa8bda445e64eafb4e0ef620ebea8ab567ed3e937ea12290cea8f8e8b9aa6fcfed1e4fea7144749d851130dee51cf18e2bc6f2cd38fa5bd3de260cacabe94eab99fd566619839d2b2092df01f3e5824ba7267770d537b90c021398f011ea7b25f4dc6132fd5bff91e23600726ae41eeadfd9fae6b59959438d63cbaf2408cbcfa68a1f2e099786d3a24a0ab40a5e283d50972ba85abd84e68811d94aff7c4510cf0fba2b5fc47aea815dcc6cdca7da3cc5582c86cacb4c377f2759f6becf0ef2529265e3d6e8f08f42c120f8fb528d20b1302eae490222a0d5ef8b9077d36cc3a6d2b060fd35723fd7495fcd53d1798bc6a1dba8bf6a90de08a82ce2ed1fb7e02e7342bd0300f1383164dadb5972c1c332071e705cca87a3f469f5705561f54143386f66a2bdc57d875743d5889b814c373bd21bc1d6759aa6915adf73bebff0ea062245f10e0859f6c0972ea69a4233fa5b0b4365b32e9d76cedd379987db25b8c0bb1a369ff011dc4077dc3e03d6c108a73034fc037bc992c5f088f9e26abf43158e3ce07bd8f46bd01d183d653e337b67c157933c1c7ce3c0054652a3628407ba903fa7041f972fe39528b08b1e21e9ad828b4a9da7861ef73412ec3c0d387c191e61daf9b2d46205a7bd59806f5eb7aeeffcf1d2f54cca983129f8974db845f4493652d2604e8e2842d8916c2b91e6ea5564a0f5be0506298c8ea66d6ca82bfa64ad6da8375e87fd73bf4404121c689c3ffcf5e11fbff52a1f7a982d35805d74cab09555ef8302c7aaaa02febefcbf868e994bbc4f7ae17bb4e32df1bb88b2bc7b33aff558d54a40a8016a38a589559aed80cf858af0ea9075a7590bdfb75b7490a9ffa959360bf3465960b8f417694c2865714804eeeb66ceb3ebe34f8ff9a04e617022967995f214ad55d1204225f5da58577d565d7e5eeb7078ff4ca55549a0a59e3706835ee9c48801e7a4a375b2e58c3890904eef5ad0b5887b8a6de4df709408cb86746f7eb3d7291de6f40ec9fcb0ca1665c2caa8c3313098c2c945e228644e75a0e2531b300524c9c5f2560be700173cfe134b7437726819ae919cc4d2e34a035990ff62d3aa0280f03cb42ddb9dc1b7813a007e0ee7a31eeff79ff47dfa3d22f96fbe6db7d0d1d4f73d0ebf7691f57c673f0a1fb4695f46e236771e46c6231b574c5ac3656976713c18774abfba3dd629f4bd5fdc43572b8cdbb37cfa4b2b9f14d7959df2d38232a979a66436f449c6e9a768ee288f4f7bafef6b297765ab29746eea61b07d5f437ed9a6e92817ab59361ff5a5213edc8af6710eeb83b88a8159dc0e0558705aec434264cc925dd898ea6e20cf02259d6cdaaa7d2ab1fdf9c8931cddcc1280543eb8e6ffda31bebeef904db411356d9e34884e6cb3f1cea8ff77ddfd442af79c078030d14e4f5706a2bb6d4546fd796dc15748a91b0d282ba93a1293458d61a32f9d98a3d35e88dba72dff00e4ecb6f1dae41b9b880afb54c9ffbaba74673ba34976c9d89208c28e06b3a65cdedefeb2581d4f7119558a81442cc47bdbcaabfbfe02b14fda48a4a47c8015428ddef2d37f30a194015773e878fbbbff0efcffafacfa5a10578468dba62c7deaace027b99fa38477e4d4754870db8a8fc4c41d323e6dd253d1b42e7284bc6e781b9e23339af52dc0c9949df5f671d4daefaa3e3e1b3a1a1fb50f48de9e60c8cd3d23b34139773204155d1933eb8f2df3b197a667fb84ce515742d3990f63e37b88667135f8afde2d580fb9524d67e818aa7f3540410fc40385ec0575b8141c02ef311df8021d4ac09da51303a2c82d93964247df195704bd42fb81d72a1f7399b4d6a3c3ad4534a98507d04132d5060428a9958f0b6825885e6070250fc28e5e0a3cfe2663fd4b4f0d537150d62457f1b58f1a7dcb038fb904ab9581d8e707c6cef380bea221881a2df03cec63c3bc662facd5ca80db0cda16536744ee63cfb120f5a663152180252af4825641c1722ef98103728b6bad2e3a107ce52e9317d4f70aaac0181178de6c731f3977102f708c0ddcf5d57cdfd8b80c1077eae2b3b5ea6dc6db099db2fbfd15d3828360ef74be1a0f111928ee1acd41d05df7ca440b555d23a2051e7926c9a81298248d27b19b824844242ce1916253fce3e3cec555599b5e19a3d0ffd149f2348dab8c35e549852721c16d89af19a1a93568ce2811206db5cf8f22f950e552eb5de8b562940484e362d44f543eaee6c9dd00478952776f2fef1bd4529c66eb8ca9a5f6d878f0d0466dc71c6e6cced9d93980d82eea3d9c5016894c4e2e23d65c11b2d25d69bf8dbfc9d999c042b70512494491669e2d76245c1e5355601b8ddb4e267fabcc4394aabd69087d96d00ef5acfc10e4c48b36abb97971c67116029d25bae248c96f2b34538b4289e3f5901fcb4e2cb08cefbc6f9a9d53d284bab6d9f3bd698b9af26caf6707c054f5bbc6abe4b57e863f752716442a61d733f7b6c105b095d095178922cdb327fb8f5448b189a16518e18c6a624f434925db05fdad0ef82ba17a8664cc4b070b9af45fd2b161d6cce6c0a7206e807dda14641d374208801044c65876601022f3f159269485961cb3a0fc8850ebcd1c5a0ace7f4ddd2c6c51257f08f65ae1111989f89539bcbf45c3c21e7d5f98ac94d96101fb43b6e6d025885ce9b08d5837fbc1fbe6d6d9e14e8178031c23c0bf0dbb670a36ad93efadff7a3a0e3340dc410ad83d816c6de2da1447c41698d9cc0c2136d5db0aa9131771319fcb8f8e06c37cfdd6878905e5ad3b81344762fb828eb75ee70d2a20238fa43436092301b24886423ea034cc9330cd73318f4394d7c3de8003b018475705110066a8338c076d37033278f90ebf1826b4274a03fef5b1c330702f26899043ec987975b05ca3b344926e9938d96c194e1791ba1e426fe5530cf9c1e025cf0d31458c99576284c6ae040085934cd78aedab345e0c44560e87958d36c84c377048aeb8eb89586e0ca23d474ee6311c7268e2d832930192387907dec785a83bb9623f42f8545ffc2cade194b1ba681dae5dd98e07b821e32a7dfb894e68ac68ecfdc9c2561b1b9774a28ced37149194b0a7ec7e8b589494a55458e1a0a4328655ad11a73f41c13cd1dbfe01cd35aa673640562e5c155f8d8b837b0e44910ee6c2b6514345916b224d6616ac2c893baf14abf554c22b78e7992b4831fcbac458fd7964aca102cc40de2d108fbb1c4fec509b121a799c15cc23dec0f0e762f2cf946ead518ea25b55c711a7fe6ae7dd98d4770b1607b580fac04b77bd6e571f90c901d2bbb36f6988cc8dc94ea9a634c568c72a267499e439f118075fe8f4c66ccbc4fc48d8480009f707005236e85349da75f405ccc50c7ccb12bd6f9e96e8b1639ceed47e3c676378fab6360ce6e79a170ba2c0f0ce4fb03d17e423d7dc3857b6e4b1a8f16690891e2f5a5924ae13d0b791c4274d17dbccd3139aebbb67953b35eb17647e6f49bf35de287d66d04a40d370c31a6bb54a1362ced6026b3a47e2363c460029aa391c74e4e44e997ebf0cc384b1e8741e75c64b001720fa16e5fa712692a94837307df9f2111d8b27dbdd3c509c30f483c037a0c7cd5eeafd152f0bca8ccef6cde6071696ce6ee6c76a83ccc9269e5ee6c94bef1ae8a3dfe765ea08ba5cb9ddf50348ac88803ee9856ea83c5f7db60323acc11a4014a267f73b0a3072c2d7cdc34ef458402004cc0253b2a53bdc5655a929d931f6625368e98737fc3435b6c230ae6283a692f23183678c46be1b2531777c2613edebc720dd2563acf80f05805addbfeae117de6b98ee906e44ed731e3ef3e3bb72f84044ebfeb5411d98b5508b82065afdd896c44c71dc48489a75f999e2243ca8e26c81127394ee0bf35183d664af68710d187838d960947acac11ea4a1e77f0791dac53c4e2ff801aff0827d3b3254f9ae1c2c55d977791ccd12161be394556beb7ac7172c9641f0e7c4b168e32c337b29249d8e48991c0e2b65a8b4c382b0bca91cf0373d7532d82b9540e0b2a04d56fdda081af8c54d284c01e120287e328643eb66927ef3940c13b584c007eb6f8808132249f801493c12d634c4b624435144c2e29e0620773bb859fda98468cb5d7cc06dfc1c2a4d1a707ee020178e84ebfbbba0b3014601d15b60e5e9c4aa99a8eca9cdd7777e233ca90901bab011c92d331fc9225b14e2e23edd42a051a161cccc50c1163afd0d9a5d295ce09682689b83050a153af8e0465c664b4018b003128f25e4cccba06396645b9bb44c2780724cd217bcc25824a6abb3eab4bf7cb04a1b9273045e1cd74970567cdae59426ac2e929753ca9c267bd7ea05411f3eea960f34108f4dc24e067d012038df991e8cff107d494d6a99845267a83b3026f30a863d605e36d14066115a82fdb3fd81109f4d59b01c3bb58b9947104e0c79a158962b6a939b01beadcdfb1ae105594d44b9c8360fa69f57d1f92ffada161b59344a62655cd981ace47011a0c59833839b37153759844533e3a2512bf6432eb886d124af5d6ce729788960944cb4b12f2531cd0d2bc63f2e0b1da5da281f1fda951f9fcb35d23a53a11ca127553cc6d328157d52c065069fccf1bdd3a9d25e0c094b39753ae2b1749eccd739b03e974bacfb96802e092f1884dc2459f3278f35b199d157791f510881e2e0ebd29402cb62aa71baa1046986b65dff0a29f22484f6a2f5fbcd21232397a2cd3a747c5bab6cc00ea71d684a5212359e90e0d16e0d75169d1c21b210a0fc718f170630f5e9528edb1e48b338f1771b66e651a08e5f4572258300929b9288928d9c8baa2f701a9c3906c74250b8dc8ca4f4e391e5ddefe4edcba626a200be076b0b387a1f14d2dd6103cdfe0c1a88d226f683461e68f1946c57aaf6eb06526d3f2d790d837ca6f64272a1e46e6b36368439e367574e2047a3a5a765e9e8d9eea2644fc8029312c7ff9f86f6c6f1d2fd53cf442e0d2dbca4442392cff538eafdfe71738c89bc4dc12b7706e6aa4d1f92872277554c4b9eb7f459dc74fbaaed78fa0dc6ce3a2f1c9ec3bc4e7f12345b0cc32e29ab9f55833babe7789f1f111df6b0c8200abe1e30ca4de3d7db1ae8e8a1037d8fd626f261da9f2ce3f47e9bbc4a3b6ae3a1b3fcf4137bdbe20ac7ba835ddbf0b5f9f42fc1065c6defbeccf28acead8166c4c201ef8cca8ed08fc82cae1e205764bd638af235060523697e72b1b6948d93020fd01077e81360cc77d545484b3344d60abff7099e72688ecf644d8fa88a31f0194823e8848e72c14b7180f98a53cd7ff1570661b19f81c25e2dabc42698e7775d565a7c098c3c99d85c6722cd2bf74d0b07b2ce184a22a50fac55da482a8573bf9d49846e0e179c68e776f2aacf343f593207f3da89333f35eb13a1489783683e6b9727092c9f49bc8cc062a1123de210e7d9d6f964a713c0c0b8ee4b33b43006c397c6d80bf493c3675e62bd792717c16c98806ea7051095c406240a2b2bca49889bc61a74b852a86e62a42a3f8280d2567ff82861a47034cc909bd124320d66409ca8bad2b2a6a01605ed813f631d9542d7f49deeb0f0519a0599904ce803b6473fbc1a6ef2c707621d66d12afc58059e2f34e3534c9d66452a27d1464667a1407d2c8f0e3e88dd2179b60eafd65abbee086e6671ed5fc008009a70bb0027c88eebc1b6210e956a315d323a5bb0841aa0ac337a085a597136620304e098292c1cbc2c14f286152a988d806dff4b301e624037ea91bc4fa44e512d6f6fbab9ad5ee19cef40da12bc5a0d80cc3f0c777f40c9fbb555a69092fef46783489062fc15894b0410a285ce60178be49e6e838d7aa40abce9ae69c7cac117ad0657c8bfe562f4f159acbafb6ddd8ad7ba367ea82fd0cb13ad1124d39651e97658c0e11f01e9f87fbeb0e7f2b15b1f8944b3d81dc020eece15934b2a0da1c80c701b0cbb901d40201c41fc070abcd3d504d10aa080099021c6ef2b22e6cd641f8d6bfd0ae427355b516b4e872e2d6496abb1834927b047022b9e903a1041d5570e3c03acec8dea6d806c1a80381af836ac900c67dc106f7cf005fe7f3f65af7d4a09a1228d546d1ac92fa6820458b87731c1c067905ccdd0e44297848821c2f6162f3725a83a9ecbe7f8a3d892349bb2aac68aa42c21490e1f48bba6cd5726ac6790f1e8f2bce8ecb580d413352951fdfd8548644317a186db54e623e1fa8b0e6d4727dc7cdb8e314ecb0fb6e4729786cbef4aee853fcf1ca5e84b99be389069cfc80ef41cfc058c0ab18f96a410d1893fc86fca58938a5a649445db571e6075afbfe4892f2a6027db6c1d821c329a2344f2f2dc21924cd5bdd04e3b676b6fb7060bc262c3cdb89cd1ec3967d9c194c0f32113ef5456982b1e272c3838faa3d6eff04ab8ed8a0c4c7837dac12ce137f743dc8c7cdc9120ccb6e8e2b3ef928eb6d2b0a11d82e1755f0d2d270c38e7b7128de95ad156d4e560f8e9e73fc1c652b05b16459cefccb18e51d1fa04a57d861713298ce6f9d1f72b7fe04e23cc8cf7c1795f327474b2ee00b0a717ae03ac832081c994e228a77cd8fb235fcce599271f16009e2e51b208a5456f98ca40589a13082454e0c11ba78f76191a921435bb21db067747b7388cf4bd1667e0ec944fcecdc7576472506096f4a275e9b90c7f5e0397792083507a2e6043b29c4636cd6e71b59664eab523d615302866733849d095f0f09fb074225f53f095d68390377b2b9e024f27da2e1f933ebe2abc493ab2bfcecc037309fcff3910d980a809582cf28679269199fa5a9a719380d0eb12be0623b0395286c15a1bc5c72b22122c10f6e9545596ae8e5d2b625c0b3d5f78b2e64f797e81f2912d6afd05fe8569bf749a3863469d33e22580b0b2ab0bc5731b558e3bb8c1d2693b10b5b0424b343eb7d0deb4c720a7dfdaa610d3d4fd7a8dea5cc5f8022ca6f30e4da1c6e6e4618094b14279a6213324a3867d8b8c60349db48861bc7366682e0d152cbf1799a134fdf3a033fcf26e08150f03688dae3b32f0ed2e879673c86afa81f2943f4a901aa5936506171972f2746a2c4896045e79e68d1c4f441bf29135dc83994319f61c390d687d5bc76e808c686b416082cb900d31db1ac6174e97157c0400892141cc9564271a3a882d1f3ebbe12dbb6bbfc7dafa117ff046b42e8194d851aecf92be798924814864d10ccc3e8bad39b63d4c6874f7275be6a1458d21fe0991846833a2e82bd9c94aa585f7e69e3384d3c8421a8dad7a99c975ec44918aa93b4c1f04470d08359c2571eef7435390bc5977a4e0b43caaabe1553e2143f6e728692b8dd7e3920933fa07c66b1488fd3b9e7614ad6e7a929dd4bb091e2d3ad69f989b1465f099be0ceb003ac09cb8022ba2d04daa5b5acd56e2c31c9f816acbcf484f9badb466ca31bcae4fba8673a2179cfab68d87dc66bb8e1df6fdd33ab7837c1bb1acaff34adcb2389a96945b8aaddaabd3a9043ba74501a757efcb74b98a07ecf01718031e8bb3c572eab67257c38a8b09538fca85b888564cec98bfc4285c27ca9a134532020bdee0deb55c6ab58e34cbe9797c38d1ef8242d79330b9e1b8a6a8e4520a715ae0c763ff383156fb2a6e38307eec316c42aa43fe44627497dc5cd9c91b42b556a4d3c8bbf51b15f3ed85f322fb357e81a99d7aa6cf847955fb899e72d5c009a046eef06ff2a1a72d4cfff0019cab3ff76c45311d5a9fdea734dbe4f9cbdc47314f8e4eb45eeded2dc4a4701a13cbb9ba509328bb92b7df2dcc8dc8cd32dea0f061a81da28bd4cba0ae9070ff222deff24f584d61c854572f52d51c99950288d0d18c65e374de92385fbeb886bab36af92f0b1a1efccc3a5f15fb685ab57b18415225895780d4d788e1e02e4ad75ea494c0dc62c8ce3809bc8ae80c546dff17deb1bd28f1afc8645810963cfaf3ff974367ee2e2290d51a9c25c8c2956ff70c48b795132b91a80b85dca90bbfbb3d26b29ae8bc72ebea091b9ce7ccd0a13a2067a5cb29318c561b89c2d8f4c3b0c033f31f39d2d06235654f7c46d9dbb713c9123af36ce4106147c7933d490abe28eebdbd477c2bb21735377eca9fcd0be49d9d8f8b2f5379270e21e71e88a600f799dceaf141ae5d0ab1f4b668041a6152c51c23345dde65934b9a67340c11f79e6dd1706fd83ef906eb166cc28b1054f1e02c0a6b5f0ccb0fc533fdd121331911853cb3e085bedbdb82bdb581274cb766a14388416c8dfb699bf9226c9b3ce026f34c8b04d653f15dc0665a0325e4b039c808628d5d6d5dd2b3b77eb9a71e5e4d3445fd57feed5b684135e8d8c777374dfd2c5245fdeae0c575d903e575b9e9772ba028015d76c60c87b418b8cdd0403966167a3db28286aa2ffb77dba5af27f47d4971af0c62a6a557e9f658370e64d1661658ddd1904b379e56d88cbc4d879abb0f0479f4ceeb19c7a30692567368002cbfb46edb29253fe128191742b39d3b72c766dd10f2a3889a7ca28140c341b0d12b85301dc6cc2221aec5240e8ce9c593f055478bc5fd4e09afed9606016d8220092447668e56a88436272bba4b9e8de2c2205eecbc89a1c19260fdc67d9bfbfa1eea6e7ade90164bb7bc2a36c081509b4b608da0843f41c8a60bae84d5099c06e4ef4a3ac96e5118cb4cb489e1a0326cb9a4b18ecccceb740d0b0e6491e5ee7957c4901b559d4b09c13557eacea7bdf360e82acef55080fc65b5b6ce31236f58a77263bf7e9f5247c4fc41704a2411d5585a336f92893c316f249ca282d3c21838a28f8029303ddf4a1707825fba1449edc034b360726a9a0de5216fb3d08b6fbf768af802f2f52abbfa8c4fd3f33d2d0b884a866bcc5765e0788c9ec22f49e0635f0c672d851e48ffbbde80c108879cd2e9fddfe6ddf6ab29220a621198824ba05bac7f6bb4f8b2b3780d325ae5cdd9b56084c36ec5d936f13dc3825cfe0d08143273ac02288e7fe52809c2e02ca7af94b5a3098594d077295699f6fdf369bd2167b1095e58a68c10b5394f74fb22269b114efa7cd663bfd9dc07a16754054a5bffbe031dbe3f801749773a2e2c6ac743adf7b9503329e61d9a26ce2150e76031621d1daeeb6b79432c99452c504ba047804954f37b0ecc32b54a87dba81d6edbab3bab1fce05a817d184fb87245f5d30d3175bb6c6db43a4f37c4fa65a066ede5d06a5643d78c676cdd383fe590f51b6263871aba6e7642a1240a3551dc9c33a2e6e6d3047bce39599b734e146a57a81c34892d3591e2b5362698966db73b57450824908d18d45ebb03c5577bdbe925859fd6f63db4366629b78d526edbd60ca7b580818179818972bac4e0b498979717162f2d1f83050b162e2c605c466091c212a5328b11969f5394135291cafc9998485313688a998e2a7bfdfa879e6c70b7751c779f0956797b975334bdcb0907edb74e4824822ea7036c0b4612557d1230c1f664c323e0ef72d2b152aa77a624ed3594815053ea8e4f88708044fd6292da1156bbb7e686496a7f03a1ca80555351df6c145392bef922506db8ed911823959fdb1b7fe6acf5c114a9303e95f9f9bf989f9bf8ecc2447d01ab1cc5484dfd546639d9601a4e53ad76e001a416b48cb2b8c069593659502f709a8a9900050f5ead4c050388d6e6719aaa4fb0e407a0d6b6e2345583a0ca1100384d1500256450d48281cb543238643c00b5b22edb6ab893dc6454c99f72b270b1e132550fad6d3bc51e5a9b492893aa4864f93b06518e448d0a1744c986d6a68fd4d68eb88b43dad110bb9c6c784f659567bde210f44f1fe955ffd6dd001d1ffa6d94da434610c524f275e2105cf5eb18a1f2bf3854a3aa856a01d8b8034b2801d4ca543253b4603494b4e52e43b1d40d36372a5b9bee14d017774b39f540d04652c50a45365826826e931ab8361883ab8e71b197d84c8ca626a342dd4aaa48f4a9db33a56310475b8ac56231cd8ae988c9c75444b332934a498eb5c73580a05ffc893f0e2115684c5b82ab7e93ab5bf360da12c47124b8eae7ff25d7965c5b6a97d2ed569c8a4fb9f1157652fa463a52ade143dd6538c6877e5f915850a09f6b4b3108a9763cc2a43212cfeaf8103de1a520584be9312206a900b992d5e91a7f72ac6a2c6aaf3fa3591df632564e0a16a369ef532f2cac4d73716950ed8cfefdb5a1017dd2e4ff6351cdd3a466e8cbcffec055d374aa068deea5e6c6d3c097c24a92ba52584102435d29aeb0c42f09f06515c756486b00419fd9612f47d48b6b5b9aefa454fb83aa57871254a1402691212cf55e8530b8ea8f41587f7b0f6bc8a4bdac7a076135a01f23c1a038a1de4c65bc0b087705e17a904fcc62ffeaec7b521aa2055295bc38a724b892d1b9a1a07f4a9227a5d312cac54642f5732359370a228678a28d804e49308655edb5cc849a9082e81ad5958f2a42fd9c92be53d2d00b0554654ccb906908e2b4f4cc96216f19e2962198a2971f97a496a1961ee9dd1a5577589977e012ca46f4e35e43482f3f2f402d207879b51c79196a41c1cbcf0b514b0fc43975dcd253e57313f47349aaf25d94608b56c12e4bb245a9f44abab845afb02e49a797cfa207e268005eb972a5876b712f9f26419c5307534493b80e0abab059370a228c54982249534555c2205509d37d304a55ce585295df4fd0afdb240645aa06c434f0cbd74eb03af3e55431146be3cf2a36e219fe31df8cb9d129898daa9c3188a36531355640f9e35e2d4355fe07e58c712f66827edaeb25a9f69adaabca6f81848ab2c100e880feaf8a50c8ccce47f0db901103c68c4ccc8b948b16302f2c5c5a280beac46d262d9b323a6c86bfd3dd1101060f6ff09ec10f2455776dbcfe01af58a9fef007bc72e5f9a1ac4057ff1fb07ac73d247a355edf70d79dd0fccca5930dfe0c082184703b21f93bcd515c95ebc6d234954ac576401c971f1e0ef0d184084bede21d1c3ccdccea9bf8fda91cd455e35357ec64e2eac42ebab6960368604a7b5bfd83287555577dc5206410827ef45301e96c37cb3e1cdae3caaec9ae1d9e29a50c4250b94735acecd7f49f07690f48fb68afbf852ba87ff64258082a2091c2526b88132182052dd3f7c907124d0028341c0024faad124fe3143922fe0fdf327547c8ef67f5c76003fa4920a7caf7778da8c2ae17764b68f707c129325b3f7ceb88ece7e3b043ea2249c99d0f151014118ff6fabb1f7504f501fb7fa2d83adb36166f4df5add24ef3e7ff4b9d27a86d7dbac1bdfc3ed9d07c7be50fa76a33bd54edc7556aeabe97ea35c477f91c3bcbc90677ba316b37a59bd209c1a45eb468e1c2452af5e2454c8c8c4c8c182e5ca4522f5ec4c4c8c8ccccc0e89ab03635df3561b522800db6fea5711173b95c4468ecd8e053799f28a91f47348422d42fa7b2f3cb4daa532a64668e31461796a0def90d2b37a20a7fa6ee3f334bd741dd325cac0d7cb837daefcfbd31dddca07e9f25c533206f3ded419faa9a41a2dff6fa1cb621d98622901487f58dd7d05d3db821690f76f736b4bdbe1fa5f2224fe244eda160bd207604eb2e2fe23deed31e54c1ae624450e1c31f9e011f3a1215ba101f55a30abf83ba7ad740db6b7b41876d445c4b2aecee427e0821ec95c9016bf7f1a84f361860a800a847b05ed84eafdabdcb217eb770e5ddc2550e70b38cd29d57e59c84581e0c30ec2ccc53f002bbd02dec42082184ce42eca46a7e26438b6182b1cd7032a718d40b961475d1d262f783ac03532164f1f2c202c6a5458b0b9a6279818a39c970331b0c530c4d46f65325bbc882d3c016da057e81dbf550b05f8ef0349542e15e75018a06d0173c175af818e567a153bd8c18306664625ea45cb4a8fb1b0b6efb06e625cb5e58b47071d192a22f58625032dcf6cd69fb0606b77db36ddf98f6fd33d5ec240b34de42bfb0e2b66fbc95879a33be36feeeafa676e4e8ddddddddddddd1b9bf59cccca71c4292a63dda708a96acbd9a0a7f933b1007c260dd2645f0a9900a12887235290213d8640846400aa18c3e5f2c7777ca9dd07c9a87c279bb0f5faaeec6ccd57d94ab5f66fec684acd48db9a089ea376466f7ccda93df300c41534cc37cf9318c0397b72affebaa6451e57f00d8199f6a4fbe7c1892a012763235b0d4f97b83a5ce8ef5816d7f55bc33e4d7a96df3b718b518b56cd37e99becc48d5d378df84f23fbfffd238956d5f4e8e147593a42432ea3a0102c99109a60aa07c40892a9288708419ec122bac30831fc09c00842853082246a8984294281051c4496b8b48f0041127f041131330697db4a78b80527a58e295c48a2abc008a0f45d821a4e08a269c5812a50a53a0a18ba8fd9bf5a78892b6a892c99c4802b6d45a1d587125a9b5310d807a36c8794768ffe64898c21043b188253f10492eaab6090e0015b55cd5c5a0b54d2eaa784a1525306ab92a86e004ad2dd372647588254b2cb55cd55128e12bb494bfbb0b218c1a34c10d42f7cda4755f2a53c157651f5537e4672a183f7ba9fa0cbe77705d88712fd89c8cc055a350d2f236790537e18a2fa0b0c5400c14e4de0327c4ad5552b6942cb9bbbb635d8ff9a48387fa61a04647edda7857a1f9d5854c519a543c3b41b0d37afc9eb6c30c66a9d4476dedb443ed4cd33a6e6df8d7630e486d3799aca4bcf5fae9efe0b061bdfe7c54aefa6ff743887331081144f718638c9d674368d64c2bde3e4ab62a5fa3c3ea642c560ecf8e1e5258464f8e90927480c0deb009d683bf3ba57eaced58de31d0dab82862d1c08a6808dddd214cedc01e3388d07626d13dc61863fcae8a0e1e6a54c51a87d4a8eaea0d79e31330eb62581b8ea1366b6dba66aadf15c35a85a6396fc16619cc12ce81244c2104aff2e2391781923c3a424a8272245477e0fa7975bdb5f17ea01fc7624fa4927f008920ee8a0d0aed313ac7bd40188b11ed37d8dd65ad8effef5479c75a1b566d1fb59bbb3a717729a38c1e77d59acfe54e018c10caff16c6b323fb1bc25132773bc86e1eaad77e5e6f42280524bc7a7a7e807c7a9ac480d1af5dae223fbf5eff0f21f5878fca942b62eba4e84a3da5935245d0af915a0a744108bb2184707d10b74ae910babb7315ca68dacb4eb466dc139c90c03f669d659c7177776bbf6d4ee597b39bbb79c8d4248ee9c5d4ed34ac399b0d33afa6b38cbd59a3c91fda5e77c7f85e77773b747cafa6bb6364f728a46941c05031e7d4b8a5e5b3009229a468d6f3862a84f065bc813ce4eebe54f7453f7ecdb96e655b1a1c3f8314f9094242a2d47304885f53de7c2c2e720092e981f8680ffe8908f5e731a794cfc37dcae7211f7e0f8f73763ca4a9477b2e38a15028b5473c6ce8f13934a415a99497eaa173ae03815b9d4ed2a11e59230e4a6217fbf00f03f1cb238e6f8f6c308a31c6f8fbcb03eeecf0f08028a0df1ad507c440847e9b04a46fbe5542ed1b1f0f589ddde1d9e1d9e1e1611e6e7538a2b9a4062edd5d4a29a58470bd79811cb1bac32831e02ea3ec7690d085c4938d29a5ec1a66006e378ad786bb6b96b9944213399003f5ab6fbe1e0a027228acbaacf65880a05ffff011ae89fc67ce39736a34cef6a6df5f9611ea271ddb0c34d4e0e119746ac80650001d9e33c38dda0f71d47ee899ea6b74a8fd907aec9a96d337eb191299a669aa5dcab90bfa2659ac1c9e1d3da4183d39428a4b7df3c19e6a0576772369162c4e4fb12bf8471c51bb673083daada4bb1a2ba08d2476fda4e60af46ba556ea1bef689a4adf3492d5e9ca413f8aee31c618214b8611d01d3940f950b2da9b59426d58ee599d75779f43788cce10421c3b70252308476aba5e2fb7a03e1ff5870fce091cc42a5518b5ec8b6d07f232738c9c1520113abac71863ecf534cfabe1692f6e4b34466e862ec421f710dfb6764965c5abaeded11a68ed0f52fb997246e67477e756a6da5d35d7439b6594a652cf62a101cd529b7913b6a8031a63e788901bc6287c597577673ee5d0dc63d4ae1b4b748f10c618636c82fa7f9e338e841181b98c7075a0159f631c13cc07984b890b04adf82f8c4361455c2e2b2e215af1679886aec65fbe7197abc618ee9e14dde322d1189f6d7a48bbfa2bc0defd15e81aa3f42105a343e8eeee7daa81eb54f1f40aee0841fd4f39bcebf524066a0751babbbbf3ecb44dbbd49e400b8b1709c04480ae4d37059c4eda37eb32092a9c11d1639c713af773e3f54cef991e66a637c1d73c8781d5f0a9ddd4710ae9526a9a0d1c6419cca66719776ce8b12fdfd8ca2fe42f0429ecb829e073da7820ed448852edf85d758ed6c96e9bb5b1eadf8eca3eb68d933a6877f7138559af5facd730d6eb8f877dce694073c423481198cfd12aad15578f9c0efff378dcdd63d6edc015fcce451170050835a7470e08581df69c1a1dd7d32ce033ee0c9e953fa7fd8b3578c8a99153635f7303cdceb0eb325c888295f31f1a56454bcdf44da6ad945e2450fb9d7393698a981715c18c9414ed159647857e4ce41cdb01c440afa120202476b5f74207e8c73f3f4776f4cdba5857b0acf8e19a00eb7d8dd0ec7cd0e1d2637477f7e6660e4e814d39a74318238919b1c43f1cc4432e777838c4a494d279f4681c97df9cdf0522c544160a4f33082cce0e1db26c3d4de388fa84d41f4204b05e7c577d3766e0530edfdcd4d1d021801abf4545436b7ebdf82c2a7a522d8daf4795d283310fe204595a5ada946822cb284da5fe59e0eeeb2107bba4f207912b5776d57f8bb3537595bf721c74adb7a52268cd139cd04903324829a38ceeee1b3be749788dd58975f69c71c6eeeece5034726aacce898586dc629cf35bc6d9b1d626861beaef2a3e4a15bdbe813b4e2acaa572a82a53d4b46e21d34f55c7d32bc9bd68f76fdd107a429807ee6e8fec26538dd589b33526201c8210c29e523f162b0a0a9170f00a15333d48d1c86e01d1eb178da10650024979dda332d7c29700a9628049a5a9dc47e5e6e901d7993ea79cd27b6c6c3021e8c9cf5290be71f50859ca590fae5a80807eabe403c8cf0f9b155e299a5f1d19dbc1c3013e844024495496d8c53dac1c201aac676554ac6258826a710cb02bf8b2dbb136f06d4c403fafb2a057133bd8f35747fa2b422152a204997429e3eaec92aa2343dd07c04a334aa9ea66194d753172276919d154020eda15b5cfe6fb43ff2d4a539f74c0a8fe1bcc321eaaa68ad5a76a48d5545de3c9c6d4b4ccab1132753c55745029e79c6c323995589bb9d78bdbedbd64842c8369c29903465e36f4f4fc00f9f41c01619103fab1cb55c486d7d267e180383b9c27b548b239393c1cb05372a05488b449abc44beeee395c0471d895431020a09f9f9ea52525a52fa7763c8e36e99136678786886a7f3945aefa63a73252ddee470e3fd35e4f19bc68ac4ef7f4fc00f9f4b8bbd3581d7ff2c48913279ca83b80879e2780c551c0aee07bab23e8c72ecf355384c64b8a1b3091a2f13c560d1c3840f1604d624748523caf45129e137d80725e82adeddeddddbedee45234067077e9d28b31468f6580d5d17eff009b05811a8109753df5c43231430ceb59f6382084aa8f01aa1add630f5996d4c312b53fea90a49addafcdc70055e51cda33196075ba66567adcddb38cd2548ae5068e045d9d6e293b5f9b2cf39ac94e48eb8c504d6bf9c46374f7fae346b0419391c9c814eb9bcf74646a623232050167a4d0cf0433c14c4ca00969c666d12c32aa4a66d1944b755bb0807e936812cd24330683e81e79ba7fcf0792d5bec11f7e9c337a648f9123bf33d72ce394205ffce2a124ec3de1571113a3988cceaaf1bcede3217ec115fc16019597a8348d3935317466440000a080001316000020100884c2a190503c286a9ae81d14800f689a3e7c521ac923498e0329088220866110020821c418030c50481a34730de576912d14b9cbd9a0176b156079e2156016c8430a33d63a2712126694cca597d8a44ea56f62cc15b801b30514a5964b8ab439db0a06fa6949745a547b116f36c20da6373a07a338fcb2e94c2874e8abd9edf1a65ca74c49430eaf716bbcada5770f12b79b0382ee3a7555d3d0a10ef9b95817c19dc421fe99d2ca76dfdac0143ed856244c59f61a95422d64a1913b09c4d7d22219ed4c8f9764f94870a65f08ba9c1f420977551174538938511cf43d800bfc5f36afc05b85edd54504b8814f95f8550673b084af6a991a1cf7565c69a6beb12144a9241caa9f368d436fa783adc4e155aa55525ace3446cc2aa514276cbcf99b31fd0517561db2d5f09cd9bc893bfd19818118de24a2c3c9d69292205bcd7af35df359705869f7d4561539d9d830b3417f6c7df70063298729759f7c9056d342c7edcebe988b7d17adcd9f5fdc03a1f13a04f56c4de0ab49cc2a212b7c0dc06f05c4603e1b1530de29302778d23e93e6aae0a928b2117b670fc34c18dc1563ec6a75c8902ea54247adaadfa593397c56c0032b61e71314959d8477dfc00cd06b1c47e1449615bc9871ede547ac1967d46d951bf258da8b0d8a73d07ce1ecb63c1dd267d2154a31daec48b42f05d31d279dc8acef2d4439b3c6eee726971a74396ec355097964f1c1a7ba1d7e28ace3e4bfa323c9a7b4786df178a46d65844a0764d661b06dcf9b43d2d9c810a7245feda091cd787bb0690dbbdf717136c11da54c2f1a42bc18fc887ec251559101ab071da2ab680ff30f6488b0dbf1f52e2477f323870a45b80ebeb85426af224b6054f05ccf80ef908c28decf8ef7dd0274a64856dd05c01ed3a991c20002b1249e05c3416b90dbe281fa65b20b16d0cd8cb9333e1bd0f6a3989e6dee8db7c13775df0c7d4e29ae946b8101870824c3f02ea0485b2d9857cae7096c972a12a43297ab8a695a791aacbbccc1698e742c2905753fb83d0d699032ba90fccde94a00c95a93e6b1fb84dc4b3da6677d622f903a2885909e30a2478212f09e995b92157fe44b5dc7cf087c0ac30483a94235da60aee560488f189a37c5337580f6906325bd386ab16f1de470355541c09f90689083317c788cbeb865582cecb7c360f6f726272e9529254f4b0b967b5d324328452385fb012af65a6c15435dc2ccfa4080280d82ea9e24a101c1487ae24b393d1997eb7a17e444ed6e8356b50a8adde8fcb382e2e202348d4ed6a7ffd21ae4d45c2c842f673f4f952f71b78202b1ffb88491fbc2a7ce5f3b15184c6ad5bf50307d6fa25b97fd114b44508f01cf0af8c3018fb8316fb69f9c0bc36801ba1e38b70baab77acf0c8da85d3d7d024fab6fce7f00e10deae01ede4e0178e3326d5b818717c0ec024620b0f1b9bd48ba8ce995174766cd29bd674dda95090b805b4b352d5900bf1b37be6f01422d046ed7d381b8d5b876fc43b83519242454fd35aa20c2a6980ee67483e3c18edcaf594f3cc21b2a91a66c138f3e887356a4e0e6303830912f2a06fb0eea5e13efa610466e060d940d30a9385f00327fb2e04a38943b61635f2090795f066bc17d96f08b60d9f5de119b744cee337f5a537a94a3374899a42e7a9f6ee4c4821ab5bc8328bc371b47993112bf652e02cb8dd8d7b58b5a8824d45fa59d79862c5d861e416d9026b740aeefe6163d1da08ad6521641d8c9569c51bb0d9b538d8d24a6d74d6f4421780675ce06943ac73c086caedbb54d78d4d5ab81001666613fc48a3ecc56c9c44ec489b6290893c30ce5c3283d503c5bef6a30101341661d50a9c11a8369ce82a8693d92aa3e7a24556ce245a665b8098305f7f8ed816c607601e7c843482d7233fbcbb015984e87fa7382dd52689426fa95f6f06b33582b00e6fb2b58ad32377e8043b57e58655251d1925a266007ff8da507d30297325b66876463a3b144b5fab8b6ec7b56b56e2826faed65d1016efc67804864c4dde4213098df4585ca4156f5bcf0d828e88eede03636bf449a9f4d5ec8df2c08ba26fea6aac261864b21c3f066682d96cc64cdeeccbcbd2c0c26c41574aae8890db0db2ae20a986e72769ed7b359b91596ca3ee6ada873f44341d18a3fe50c2263bc28a579cbdb05225a2fd31e93128f10f4e5e6d100855703af73d684784c7548eae4356fec905d6987de5462989e14c391dc11b11b78dc29770a2d2d3dd62efc777e29369cb14cf1a5d9261b92021202ceb3f72da48602e0f2445ddd4e4c938ca01eeef07c32d0400caab7792aeea8991704e4be963faee2cc53e9cd22903daaead83d44c5a5ed4d914d102496f1853d260214e57baf0d532c1066b338637b48fc310caeb2799cdc92aa095028eaf4d92e780c0f5ef338e816600aa7e07d94931a6deeefdba89861967de1e75b12dcfd9ff2d7af1fe72ffedd3cd20b76d4367a5aca8a9be30ce17485f5a56641896495273c9a21a052e38cdedd25953ac9e161ca4f4e15f62113860791e84d000bdbb8e099fb6a6b2b370573ea4045bae78ec4cf7abc10e6fa39712e5bebf8689203e580808d2e853db1b52a31a5763490f4c0cab99e814952b2e2679f637e7773df84cfd3b5dbeb47cf025101586c1b327806abb554225810b71b1cd0afc0ad571906a25af5ab0b6e00c44b4b3ddf1445e8863f6e186618a073d9b1042ffbaf9cb9664fc1b62d083bba9e684299e2cfe94f70dace3bccfda10213562171914e4398ffac514b32f616d1b576cf1083314a0c5f5550e90133a220b3011c45de959a3fc966bfc1e4e1be7762eab1fb2c6b110d243d14232602865871451fadc8933508e46620393528ff6ae49c52b05db91b3ea9921a7f8e72b8a6fb2ab80e30726be52834b836a0800152092e5d661b95816c60651d0f624242ed387759cc867096cc7673cd0de2ed7bd56e54ba6ff78591de8f28a06cb54f6602d2005185f14c01b602d91bcb8a950b68f87303e8f91b55f2229421f9f67d188faa081299f0b68cca0bb9be562d448ac9778d496e221af705979362ead23d5c7ee341a24f9718fb6c69a4fadc930ed85c99a08e0ceb6e0836b5c40f7da969b0a0f418782fb5f32f776e4c28f02f1f5663284861f710d48e279c4ba739142c7e990e119ddaf22da5f6a6dd9adeb81e1c9a00ca146714d9ea46ec204bd3fa5a7fc8c0fd653d2ce3127cc7f035bdd2101afa370f53571a8ac23cdf6417faa5f011b7e84fd33aecae4c70f3435813d69a63874eb7b47eb7365ee65db7b4e5d2672616d078d4a3af037bc70ee82ad092e9dd6bfe2b7e0ce76392146d809f99ddd68cecf51f80cbf8f35d4ad27579bebe7071653a925cd2f4eebef48770a97aea1f33357711c90f39d900c176404042237b9d1c9f6f148205f40752cfdd7299d24629f33ac3eb1360b64b78e0bdb300ea93d591c57e2bc4aead45e77fdcc2ced6133607b9b7cce13346fc62780c94553efa99f58d63987b2008c8c7c41187a36b4cdd840a3a445bf37755e88b7d08f20039e8e07182e76dc037dd9bb9e95e0e4c64bba9941108cfcdc350fb22c0684f636b27802a0ad4831bee1408b6ae8cae87dc9f8eccc8476a6a8e8dfb66bfd138581aee98f1fc96a16b49e1c0986c841dcfbf14e8cc09c89eef873ee6569f348316841b000e9317cf33b8f80f9527ab26f7a0c5fb7eb3f7ae3f054faafbcf8959ae62809934808fda03d36edcac489664fe589be0163a1157cac5691323d195b1e35e1018c08c4de75e26bf1d54c62bc482890341054831011927c14194386763897ec414b805e4d7951e115b43cf581bc5d2fb32360eadadf080748866d7a249888e05ea0002945ed6f243fce26975bf16611b6774a254888afe426267818277a975bcc0dccc73b934b915fcc91685cad605c7c8b2f10a0321cc29202369a92276ca54c6583fb3c52b6bd2f9bbc60ad85b82a9709a24e181338e4d3c684ab27f884bb4c1a0384a6143aced76d7984a6f27115328e7b903a19509f3b876d26a1e97072e32b035d74b72779fcb2022f90c05c3700e1ba7cb257cf70992a02a6d1e93d4c75b3396c0f8616683d742cae9712ad05438c91b59ab6b3a2b3a6ce268ec139e01066c2ace2fc8d041309a83e7e53e17722b4c849f70246993d3743d2ca3f005593e24cbe4542a3cb46986a5220a8412d114aa34a42f7073ba0cd27916d40137e37cf68f9dd4c5d747910cfc71068ee573c4ce007c24b36a58cdd1f0422b56b34535a6aac019efa4eee2ac972da90946f505eaa98eb6ca4f16f0fe2c7b50640a9b3cdbaef60e3fefd21bfd08b0e3a7e8879263346ab633deca92da62d7b130fdb4b7b9f7db868d4bea47b589e61e0368b890b5e1225e167be3ed5ff26a11291702fb604d8050e57b59dd4e450ccd4207c51940ce9de6f54b25bd1bdaad359e42aefebef4aae9f797a90dcc5101859098a27164a622a0e98f17eb91b0f5580c5c0f44e1170d8cac7c7eddcb97bbb10f977f29d8fb888fcc99a2f5cb60e6ceafc252dc7bed8538bb890ccbf3585471daec88df0c8c38dce2439e55e552340e7ff35936a3c68183b5e4309dcc9d8364e0bc555fec90529c368c5bedf9b954c11533a34c6f4ff399e8af475624d5b1cd1f662a4be3fbd0096bbc6cd122e0d688e62b90c72955689dc2f123fb86321e7dc141fc2e28cb12c8d3f970d0494b3cf19044dc86c514403a1c51d1eb82c411db08ebd2953e26352ff56f7a014db6e835dda09e72d485d333f410436a818eaabb61fd62bc0c1fb3e9ef4c716e879c43c6c32880dabc0a12254878f3a4558e8b48739516a41879e284b9aed12695d12750f505196ac1439bbfa4124c72bbd9a540f4af61a8b52993b7fb5a4d5800a40ce9798697712aa0865f67faefc93a59c905da8c51b2af95f8c3a98639eb457729754854ab1fc50367cd1247c58284544084781aab42112a41f8302791d900f3ee27cc56e2b7127ee4e989079c0006cdbe9b6aabe3b258829d736825a183ffa6c4016273bcde64b49d6ad05f2137bb3cf71af59e1866261b27e7120ad811852e7e52fe88beb4176b4f7eb5c24d0ffa4a8c280a788f7aebcb85561e76cf89a6eb8aab200f3881be06934dd767e2bc174c45c3f3c6128c8c83c2aed00c5a18e48d39d03f9ff30cf704f4519d6a1aff40c4510d37a417ba360d10aef101335d349245f19a69a2f8259341f8036f527501033924c20fde5ffbb82d6d13315e387bc9bf80adf62a4d9e00e8919ab09ea7cb8988790db1a4f643e92ceb86997b9b4216f50f6601b07fff628e1e56c955a67fff2f41319f050e2cb72b5cf9ed97fc3a9da657db173b84fa69a3caf92a976a3cfbb594df000f7e5034a046176a52e5dde87962f25e97a0c8ca0cf395e4f352e2f1710b2e65435948fed96355c88a918aedf03efa9dcd81c1e286b2a4be4f027594d824cf860d93c1cef4069285f0fcf9dad5f2e1d1fad1f6224bd468871c8ceb0f1610ada36c395cae6fcb00693b85b3afa11863e893638fe81d5cda331014ab24590ab99fc7f1a8a7c9748ae57255725e31f834211e9fc10062950e7484d3f5a4db8c547f34ba7824f2ba60b413185c0967151713db3e3eebd59bb5c660a82cba7c0f85816130d46a2d89ab00111e407582a1e1cfa5400f860acdad44e22ac4922667175c3ea5930b861a82dddeeaf6cb05534e1d491cb9817741616af551b84df6002bc592c26e89cf5ade96ade7880bc992ded82ee393b169de773a083ee5f0f693ff08be446cd31dad158259a1313e8ad08f618585427bfcbb8fd728a9b809dce70bd006fcd1acb8fd7fa9996ff0d7f1654c2e97242d015f68dcf72fc04e373ba97f5821bad13de197531c287005150de7dba8757c04d8e5666c0419f793e331cb936cc1d7a63203b1e754131c1cb703376c3149ab198d89278f63a1011aae94ef15aaeb647e645d3354f7c1c94c35f255c270ecaee3d0dea0ab73f5527dbf4881ca7f0a1512cd9524b3479db0d44185cc76ca5683ba7c6f8f94576f18f5a22efb70142989baffa0e8a7fda62ac465d9e9f63e052723e0d3cf0af68976bb2fb3966e6de283d8dc74624a80b3a9663267fe6c25621580ff03d40684f65cc03934aa8eab4f6d854ee633f0320a0abad5f1deb278c913739e8dfa6e1a680a3c627ae9e2db12d16c29a53fef2726254d3e3cead627ca1bf9ba236a219811317f53893d85d6171e45774b5a70d4d2347b1a76c3ffe28fc8f5fadbb81edcdeded7216453246bb747657c6d6d77578deb971a51e66c80f3409ce8f93081975ec405528f13ad8d9d164de35f664822552d2bad414acc39f236dd7c5eac84e372dcdb95847e5d21cd3d309063df05da6dcd7f6debc0f8e00c0e52d69476f50a70f21dae80d55a940d58cabeef4100f898f94ec8b02ec3618e2b51f3f0810d1b437b0c9a66e1ae0dc66cfe966cd4defd568f81d82f268b905d88729847bc374d680781d7427197e86e28889d845189a6218575d8b51280f9f75fca3b3c78fd3a5a3aecf337cd958d2b10cf9936f1d14073e7d8f8397ff730e9e8537dadd0bd0022107f136e99e9de431cc7f7f52f2ce794c86ddf15944b0afba2309ba144c858a4ee1941740f93397ebcb5df676c60cdae6e0c7a98f8a40554dbe265084ea74d1a8cc5c5cf25fdefbaf66ae31cfc4b9322aeee17cbf156a19129cfa2ae6834bf4272540364b967eb51c96a1ccc8b97ddc624b2a3bb892912f98fd28657f4849df585030ceea978c0e3541d2754b9342a8cb364ed81f31cba02f39b3949ecd14b413a8782b9982b53117f3e82511bdc25803c6ef950f2d7fc8e77035877666f7e54bcb002dc9d6d4d1311712cfd45d4ce54a568a6178799c45f1d7f908c28bf65ea309adbe24179303e2625e87ac8d4b5785ac8158223e0b24d1db2e7c0a7e7acf138674842e3a4eed4d036633452453be86c307160672e87082d53ca1b03b3d0071ee14d14bb17abc42684d37c9182c1f59639e15afe0dec570878e65f75dc35d74d758c2f1f79785aed626567e0809e5cc90b00ec03116a1418b32a9ac64649e9c413fb0b20bbd7086a71939a113e9b8d7d873f06bc8bf7f606364a1a94acb7f1649c35051fe703748426ffa6130580b777cec48519215807c55d7261cfe41a73f75c7cc0b043a7a2440beba7d1697b9567c2b7852095a440e61f184985dd521db9bd0eb0ec6401b2b8f6e10eacc9fe353f0a4c6a5c5519030db8377f6e02764a45450a41992b03a25a86903469613b26f6f0609a1d7511ff3cfa482b63e2a6e972bab18af929022fe190820e2d16ae514c1e9b8877db5523fa0d525eb331290ee564085d3058b1fd4e9f5bff697218946b7d83b5e622413f05a06d7cc3d3ad5835e9c3c78659371c858c152336888f6d896134deb54e887c24b7c082c848d32dc15b2e524c8c647a12f6512dfa3bbbf0b910dbbf250068a57c231a71a2d64f628d3f7a4cb4a51eef028eaa3d914c93349b45460ba1c38ecf713d52151d73ed7d12b820d65af68cdbb683879fa853ecb8b75bc8c172e9428bd84d58917789de1bd7782ae0d312dec4fab79304b8b3239d8086e2ce7f8737ef928faae737253bd33b0cf578002741e6e35908d6e1d2129d7d9976b6e3b89c1123d641e252806be581cf8354dee3546c85d7fc002742b53984dbe0453035d38863e480a0b5960b5f3d5227ac48f616250441ba8aec32b705ceaedc21192c2d8255ac951f6bcbb8af159cb573355d95bd7077bdd85cda6700249653c470f09e73a8da210321929d22a281b991713667f7ec5331e471184b8073806e79537a3556cbae5832ca1fb5737cde3023a00ccce44131a8086c53c7e984f85c981875a16281b600e8d6152b913c574fd917682681892c6b7b5c00757cb4106451e058a6de3342428f8bee1b05646d0006771f17a5811d270ea98f402bd67cacff782243ed9c43dab80a434c113ce1351506c94e0e313aa6ec7973b4b3ae87fee1851b4b7452bc35602b59437835b3e1d136d6a40e8429b6b621c8b7707656afd13a62e0cd88ec2a22ca511e901e989995ce2aab4f38e8e5d86ae754a93d0f4f2c5a98cc58521b67e6140cde46f31d2720b1c940ef3d5648823ed1b53c080eb6e5dc63275774dde2aeb0c78b1e0dbf9a4d72c5f29ed5f77433ce68908355387c745b2829c42a4e8022fb1f232a7822dd066987e649e16e481b28a66f5939a5ad0fff2f59ca6786bb3aa15f8dcd9fb25852d73ef51973caf5311b2a489051d8af68e653939c6f2daa4a418a7197ecdcdf831d2ba4add435285a67e6db49423dba0c3dc4ccb5836f83c7d9705ec75b4f019bfb1dabe622b7a0a73242b6ff39e408bc5f946937d18760fc4a9a082184c2c5183d3f9a6e81f071a96242d6b0cad214b1aae4a3a06cc0f0cf4d287b5d50feea27153de3bd1c3b2ece08790ee74de111376d51bdf641acb0ecbc75bc735d1427d8d3be1f9350185849d781537e22673fbfdd6eece35a9a22cdb9bcc98a903d53f3abd2eab55e68ff8c8d5fbcd28f4e212582ba17547a6835734decbb1bdf54122509ee113e481e48a1ec1874257c7331559b2945db1e09c58f50d0dcaa80fb82748b79d5a18de4bb71174d3dfa1f5c18a3877f543374a95a74c56de223a795354146dd9814322b6b6b520c6e630de588fabfcb6b51a58fef58b37e5aaa486dc683cc6e7fe707b173da9b723b84bfa8683671cac0e22fa79fa076f02d0ef3757aa4820d66c4d49a0b227b585c6ef29e1e551c186294ff4a46d5e36a32081536aedae4b8177bb0806424a1795ba948d019da57ead7985825a588b171aee1231bf46612f34906dbb97f2c0636204d1b9cccda743e7837e9eef6a4ec04c4765792061fc33226ca3b9ce275add9f746e5e04a4ce8a9992760bd19516b64a9b6abf7d5838ce160e68fb3be6c84d02203e7752c41eb827a021bb3f44a64c34c6157f9086429c46f7e1a2da7e8d67ff0b1815db9b50fc0134202aba0af5bef94abfa2dacadc6adad97d9032e4567d1fdf2a6db5a96bcab6825ad03633b53a073ad332ea121268881bc162245acef4f500ca069199a61c1b235cc8c322fe1ee03726e9d8dabbe35212850014f0067356c84c54cf92b8298064a5dd034375a1bbaa4058b7f8c2da95b6b8604313e08a05cfded9b549239ca71a50b1126f3c700eb49d4884fca590519a8328e94f803cbf6cf54e4a209db8877c308eb94e2b596cd037bd0ceaa63773859658ede708eba86977d2ec706f26047a54ceb397328b31204e82029830a3edc1e8d05919d6594ad6794bc940ddcd930034b6df1ff9e8020223680c15d2e216d289961aa4ec4e7e7eb7204405ae2628d57ed8a680eaae32f199b655179d016ccd8143d7581140523e6b3a8f8948b7db2a88a31c28c859c0ca375a76b5d653e84ec9ef10be6dcfe1da4be9f26cb1690d96ea8bf60d851fd435d66ef8bb2c0a12d26d1f3527dc9b03fc8043f832ec93fee9fbb56ebe4bf9f04c6c6f49d92bba5f52bad469fed90ad05754707f292064bb1b590a05847973baa27f3189eef28ac9f24358e6db979dc1a8c2106e9c966c85a2c61d421b717244b6017a43869ecf8221d9459504db861dab023f36c97e197b1dfb2ade30656af57527907fce8c4e8e452194d1c206cc6387fc48f8b8dd6039aebe032b8786172db00e6025187f0127a7e80d3d25113a98303148ea3948a98e5d9dac38f6e04d9a2dc1e2873f6fbfc1d43a7b264d5567a0bcb76727a0012b88529ad1c9510891998255e2c25b8ceb8bff09782b873d605b3ba3af40ee9d1a7cd01b87122de29187cc3e865d3258c63ce52bcb6136e1499d8bd2bfab50202d62542a3bddff6b2746784355d592d9217013e2198523278979e4621c1a8cf4c1be27e46be2008d6d69609e21be645048abb642d9ff9ac8b031b5196e0ed61d6966443ffe6788d621c724d082b137f9403f9867bfdb792825b6f3f17b6a44ab655cd8c1c2d09af92561ee9f5788db9ae76e354444c7f1e9375d05e681708ee52b959cd624e76ff8bff431d05133738ef600d7eaaf162893f34c979480434e2eeb41506939030d9093fb6104b6f79519997f92140b600cf6537f9546da687024a0135497199207e64dc904a0489a3d8948638ddb0d8f261b2ff226f1c14b00b526ac77733076d019e718926e9169c1a80a0962af29d492493c2813d78f0c1dc16000a4117ff07c814500d604441fc13097315cf83507645a62a921efa810e9a25c0332d7a9e1365689a3aed987202a613dabd44b9d6392123bb8774f5993ddf17075c28bde4ff7760a07309d567df9b741cf1450d802e53f754445a373f014faee1589e0fe2e71c3da7d5a51c7b65f801266e446a3ee39cbc05d26cb899adde6a91376bf6223284036ca15aaa928dc110a6980558e10413d4f483eb29fd3ec58b0549ea1af52a3f127d1f0d824248b88cc80db20489494545de0ec78d2e6af7a25bd187af8c81531ea895362c3d026f02da324f2dd17fa6b788444416e06945ad926ccc1011817426eb51915119666a63f22fb8881565f0dc976df4e107ecb691308bb5318a81d9e966a17485ff12df76840e6b1121871e67915777f12162091b41a7bae51b0869812dd4227eb409a6fae3235b064956b715cae8dd45d179905c8763abf797406fd67baa03554d7b1cf1992d1bf91ea2e218ba61debe7da0bfc293c5d93202984f46990e0c6348b3b10fc72e8498df31f0ebf8704c5319503a7da75e95190632ca9bcee9c065c89743d6d4692122afce00001bdb2b9c45e0803810dbc4c824af9d24c86afea17298d6018cc54144106a152d6ed0d68823c077d77fc13afc1e540896f89480e8c0124503feb387d1aadb93fb10c1a271eada07a3ab6a9b2dd83ab6851175c08e5f1df3580de7612f17823152cfdd6d9f7b85b36a98a543d2bd2e9694dce1f5135863e208be3ea6177a8329f6274e72eefa2918b9015bf810d14e5673ad4f48d806609a0938e402afc39d6e7876127337bd955ef6ede26feed4d207e2346c0b32ebe1eb6c558f7fab062c02284de633eb3bb6790815a07a9db645ed407132ffef37b1a50c47858a893c372b8203f9d072c87e758e08f13b232ebc1fafc5eef9053a954e3c1280c071008f0425fc0100c5ad207aa6742180952ae532f16c50dc124f4a95c3ab82b84a2bde308a7b3b4c7787a2c15f4e1734006e3bbe9e9d781c4ee6e9173c80949c02e295233d85992e607384f254228487733c0080421bc050692ca084f1f85a9e42168c18f6f8e4023d041efaa7b295092199fd21c9a5c74c854502df06ff805bb5b6bdae341dc60c7da07ec26c9699d0e7d4b63b422441c7da9b5d6c29ec449cdebf4792615d687c027aee099e7bfeb917c0bdba601f1d4e6ced630103d314348868ebf90e4b046eb5163040cae23ba045a2f1119b18951b22cbc09c70b36e558bccf74f3c5f6c066aa62e78cb18ef9ff9c9629852920290ad633b3352e75656194fabfef8ea9aec608c9bc7956e305f6746b9b4eb7703fa8e54d6df80588ee425c7c1cad46f0a395b2b04101f30f97a060bfe93331bfd3dee205589179e41360dc1b3121f2453d9eaa297b9e4f081681a1f5a19f82cc357f3df81fef9e3ab138a2529c66f6e2815270964513046d4c2dea2b0e42d9b111f994425fd610741ca395019dd06f5b5b8054b7ad3de72ddc5e2dfaa4f64466d5b48270be8819f05b58e23c5d58be07fec2527d8342a2a3df91e1626eda816b0a649317698456b408b5eddc7992fe4f3a2f3f8f0aa5a37f0e316a3e5ff84a83299c2793657535c808eb405ba79d7a3a767b0300fb81210f1c9da48311b436439cc6dab7a49ffd94137e0d5c2d3f58de12ebc92663234f75694358a68c0355cbf27b75dff2b4c37732e53c0e6c22202c82b08fa20d2e8ea743d3b1dee60e61da1357113f1fa18f9ded24c56319f0037bd4c496141932af1847ad9418c00ddeaf7fb34ffe59b83b38f83130c30f9ef8a29e12fdbe5591a64dd5be0021a4b5b0eb4280ef579cf49952b3e19f73cdeab80c756adfe5c945fd759f60fdd4ea838cf7b3611bd7b79ff9a5d160b9cec387debfb87f68f36a4aa150b3c864e7b0d57dcd33488e7b2df9a42d7d46da66c4c5d6bd25f0bae62e25ba43136fc72ef7d1334841b2e958f8c0667501e61677a1ef4384aa9bc7ca21493ce9e53d161134131e8111417551a6b73cac21559401b80e82f92a746972d4d5c5437375ea6e741eb3bbdaf440695c304424c9c98634c781d03b38b0f9668fc9ea2d8b5d9852a95957b07686a1eb0a0950a2a48ed32be04786cdf4a4633cfcf0bfa3d14e4f5fd2171e60ceee7e507d8a462a540c592599fe8480329b6e35a699ca5a8101853937dd24a952701f14e2b5c3b2bc47cc26bb5092969ecf387c59d113558faa029ee22c4c11de06e0d596045f9dc84028eac861140137c3d7818f347249fdd2eb44254ceb54968f79a682ebada217da25d39f9d70448885339ec650d4056d1705dcb904f1af0f122ca3870208f324daf1cfb33c3ce5ff5ef224556f92d9ae757346505c639ef78698b5a02a327e7279025c330d43b96a5dcd94de2fb4c0fef0441e784859ddc34f57493492d85ffb9c50784a6bbdcb10934ed576cdcef794d3bc8815386fe34b65347fa45340c5c4a209aa235922191fa149d977cf51e1e67996979cde23e843095d0247ebf6e5a83bcdfa44fd1705fc376d66816111ac9591859f255dbeaed94a031ac64ba81f1f3b64c4d021f033ce3acdae77ce49d2fb04d8dc9c7f86fabe7d421024957704380b5e046d3089c16e7ebab9fb3a01ff0fb2461bee8c4cd13b354a3416fb9485a3a0fc801f7b484c6bf8b2089146073eaa7808403e078174b313a236aaa525c4479598055ab10088c044e3391c54127dccb735fd1d5389abe1379d86eb43bd9a11ac6983b99faa98def0b9d8db78939e74155cf1f16ac6bd0a4ea61b2de1a0e9ca75fad2e93ea7d15c488096d151eb64c3e8f17f28e262fc69fb757c5eef6696aebbb4bc4449d8cda19b7b81ad96738a83f9c8395f895e7c1c1f10739e350f91c84e26316517c6cdab9839676060cca43ad06c85f88b34b34cd4df4d6be06b5061bb569eab837d2e8513a7452fdd25635c3ac734664109a77f7e6466226d3b9736770768d6fe70b80c7883c9ad9c9d41945a0064ac336450dcb3bed913992dbcd492d105acfd165234eebb77dff6dfe56fb5bdddfb4f67fad40fbf918e1a4a5558126eaad24d546a89ae8a393ee7611aa12184c2cc8d6cf06edcbe5dc8969899b95960e2c749f226b43aef66fb5bfe9fa6deb6f9bdfeafe56fb37addf76fdb6f95bed6f75d9affdef3ac4e0365c78c9a1011b0fdcda64f640626cd60f03a7ee6d1695bb23884aec1ea4b1872c619c63e66428f54168e839893d861883dc5215012da67825054b3eb441bb019b2df030eed6fb2a73ea343e93b96550a22ef744f5101860396ee4abe69b552ab2d695103870431c0436c8813f8203f145ecc21a094e4e129c94e5eca7a83a1a42134c2dc4402c7457c000175a6f0921c838840bae5d03cec59cc542b734d630878d4724f48663635261d16ebd57c238b8cf4a28565d77b18de1a0c4c88f311ad8cd910cad511f8b09d82783ad66cebedad83e3c09ab0661c330882df31a99c4dcaf5603db1e9071db2100b61d0013e7e00b9cb2d69300bd31d45c41f47cbd2841f8670de3333ec2aba2c82192e000a4886722d7906c7f3bd1837326f101a38111a16a05e9c9fcecdf894de83a3ba01a0eb6ea94950e946a69350c344b02c0936d8dec7c858e10eb628571f5e3ef3e7947ff867fd5779800a1498cce95a8d75c54d3575426c4787bb52aa1b443da57292f886e49e74cdda32326aaf6aa7d8a5173ccbb8be839aa395b651c1187a8870753740348ac0ef01a2d826f74105e8628aac88eadb829afd47bacc3d1b8e23d0880019d024032e8409f185381f064b062c5ee18e81b11bc9d219f6e1f5c1c14165cfdf787498143471085a0e134f8baa4be14e895ef4952274935d7d7c35a7cfb9cd5b46ebcb3b007d1496afc722e69d07518f79f44b021d98944532dc6639c82a0594e0e927f7553376a5c5aa46fac6c06ce5c4db42d1b7376fa441a19049c6bcd3270853f2f5f759e1dafa78bb04a5019ff5a561824203f1abbd7a3e553f7346df33fba9186158cb8c720169aaa230484c71b4e83bc7f9883f629acc910f6ec58156ad8495841d3023108102ba5c85f7ab3dedc86d1753e184d30a1571e0d3e9090fc88036f9cfa001ae4256fa1c45c4d31aae3ec942d2807843e44d446de916f3c7fb08c1b25df1b539a8a3651af31d1ff2fc9ce7352f260e56e6033ec751ade8d014dff02edf9f4f3fe22d7889cd8724ed3ef3539111c4a932a706a1c54af9af0ae9e5b25d3d77f92092a8764a2bf86a4a162455da5b4ca36667df4f99f8e2e4139481511415bb1dba9036374759beb7f52752e478f83857ae99f34b86e1581457bb9481d0a11aa3a648a30bd34300eae48e09b6811731aa0bfd23700830a76eb86fb09126a9823f816655209da3a14e1b784ea7a16f011865c17e56e83d4a8bc1aea95ccec18b7d6e3ee70b2600e4f0add0b886281c6a7f0b0add3ee3147db007e70dba154c26e3b7375badae531a2e3748fef955e6bd34d35784869a468a1298ac4671dcb3bf1ac33c4c47262423c37da69d3c1df7a14f1ab5bb160d507dcada05f87cec75ae55919f8888352f69eb1e4d87c4e5a9ecc44e60e080b97c77bf88a97171e8b83c97bcbdff31fb2cc7b76a59f3c40688bce92fd2ab0bf610b1667009bf2a7f4932e3729d3685725c59fe710ae4bae0416ce57c562e04913552b1b4b4e9ba203b80c2f90111559de35a259f180de14ffdad408c4e72101322287a30f847703024e4f406041480282dfa4c61e16dc886f2a23b6afde0d35113176532dae8fdd91a494b0795e3f4804947e66a45ba1a2168040c1d946e92e3a76f4bc97f89ad0c181f9d951c1885639b22d0f602369625c9bc06c295c502f88d750fe22d15e3ce3d32a98fa6902fc651540e69bf69128f6a8a0e3946834d08eaadf4d4f6599e07843a29c2864376aaa69a5bfe309fce54dda128f02add17a0ca2656476fb052395595a1a2e8555b8bcb6eed8ef56a540210c1e57070ad3d8008e531da2e4a95221c9dfa7d9a1b3a6cb309d98e934e25f6caf79cb4b6da88c39a79fc17dac53cd94dbc447686acf001d52ca7102274365c9f80057e3d18ee92797053d2abb0a2adc9ccaf9295842125631673a1ba001db8d89311512daa1011bd4955b5407cd27043c46c6f3333a6df6c4c2e3b22cb496656198d1f9a1e7891610e2175a8909d8f73093a95b4d9acb46e73c2cc229f8d5b569a3f37f3015d2d9d99d62bc45027cf042f4297d6d3dbbbed54345f52673212f24feaf44fe0ebb1e44276199dc07c9f08e7c5db085d6a9fe1392e135ac0b16d9ed5cbf5d1bb0ae3d0856ef34b3692712bf5e8612f804d9d3d65e54e6b27c6aec766962c6a52d9096b0e8e279511aafbc647a5ad70866aeef2f035710405cdd51117a086f03ed14b92845f91b41b7f4cf7e4cf4e808804d86dd0ad4810aad07cbdfa4d6790b5b9e838762d7007612a01f183b8a8fed105eae48d10629cf072e2ce9bae5bc4178e3869d01fc6ccb8ef0600379150c46fc68201e0cd4eef1eb069f864bbc7b1dafc289ffaec5e9d1405aa48e500d2b85922246a8b5d74eb1b40a2b58bb981f5910e47d98fefb59518215ac4abc4a70a0eae9d2a72607512d4cbf2eef435dc7fd57f9072b3ff0634a73f69a342d30cde4407d0e03b6263d7fb050cdfc393c965a313eb847b3f09786377c454655d9d0233f150fa71b6ea0c397b4baec897d6dfd5092c591f2cd60c52c00ba9108a8279712a8a7eb5fec9cd299999e241abe8023422175609514a6ac749595f03fa48838ecfdcd4680dbb81f78044e9b1d69018ab88d24905d101ab0b570f6f72aec5c3fd9a225f281c44c36a9d3000048522f5cab3d48532b1fe41ebc1f24ea81a84cb11cad6cf73918a6dbcc185f2f2ff53202b89bb9847678514a24a6fd4439b0bb6d9ca9265e928705124f9b6fd4cb55c4eecb8b2a26dc82e12abfb77161ed6fb11b8f08c3260ee094a60b7afc4fe11c99eef528d6bab0fcd7ee0dc0a1caf48c3bf07a27c16bf72a4983e57732a0649caf644b9905ed48ec267c5ec93b2c7e85aaee92ff5f78fbade401b27744e9d83a6d10ad3418807c81b9b22c2ae91134328eafe0fc0cb8c2b260d83ce6ec51a5580edb8983d0060710945b988b6045176df65258831cd87a20ea510521b62547cf15251d525e38876485cb713bd437b3a61da0ede2a32aa46ebbb0570fc6f4b8abc0847cad1abb809276b8cadddb9339df24100e9fbfaa2a31664d7855b52f464fc861a97fe5b704eb340a4be06ddb3c6ffcac2bb42054b74e417c83658a5a43d12cf138ed58d8aba5e248ae85317d4d1bcc943520fd824a0f10aa157c01ec0aca9da05041b82902c1600f1ac10242b095a2ed8af0dd8594b50e39200fb150e2401d2406b02e0303d12137a8b11eb211c832b06c53871820129a50a147f74ea4c3cae9c62871bec082fd8906bbfedfd5996a4a1d36294f28d941433ff1e2d163c62e16d0cc5df34d0c358002bc9a2c0e3dd871a8b5bdc5c03045d5dcbf733fecb84a0ac1c18cbef9d787a21d7217a84c328de6bf57fe141aabfa091a6966e9b11cdc5bfa7e7d7a5d3b04edacc417716680212e69e85f94ccf4ea5f656961ae396760a9da1a1c45de742915aa05b8bb8010477435ba60093392f43d4adc635c0497c4ebde960aa47a4ca384227af57d43008d7461fb4fa163156e841661a5c71d52320d2bba3013d2b9d41d582dec70ed44626bdf845a87631e70225269947a3363c6b0a52329d808de7706942f2b348d0901250f901de4feb156ccfc87039d40c53e379daafddb206fb0f17637aa95dbd5b7e1e0794fbe997adb35450d7bef1f76a4cf0934e3610f031df15b3e6f7aac85cbb212f035b35c15643fea561c8daef4a293bc6277df95340415498b6634833617bffbf137c109bad7778030a314227efab112dd5905302893f294292a4d7e5ff0233b0e46704c02eac838a489496ce9c4bb2f11289c40016542334237764423d0d969e82cfc7a87f2e4c61ade339d3d6a0a2c0b0e9afc74a0bed3fdaf2203f395ba8d53b0f9030227dbbc00e8550ef38f6c2c3d512ba1b674a0d75c6911815af01b8227d1002d3ac32c49528596c7d2537782b87c6efb7d46aa0d3fcd24392f38f356154195c56a47331209e6f058402249b1df8e81ce734a703d99fe814e4420dd6c3854cb7dbe6a57eab169c863e9bb6dfaeff245e3b67621d700f42cfea21c1440d81bfeca1f008fa1b6bdcb65a49cf8ec8f3f97eae7c44cb4d86d16200368e5269a070048ed0fec403a215599648e5a9738fc7c6718452615ef4114345ca3e777601429f6f7157a967bf32f6c25d2286c9de2290b2f678759a0df12fcec002b0cc18e37f7078aec6420150f68f1861ed8c5983f035aab50163106726ac71ec46f1ff12859feb151cfddf9e3163c533c3d087190061bc6fe0dd49e5f59c35cf282f4b889e6d1350a1bbd0250b403e2b9b10b31ddd7e93fafc56b157b54a632550308df98f14051549aa779f64c784880d2145049a2c160ac4fc08791df6c655240ca1443df18c8ded7fdba81c34c00f7ce722ad5164dd8e3cd6cb0c2bfcc30510baa00c9b444589aadcfcfef5d00bb36fa5ccb732bf5b85f6ef3f536555b19c386e817737a580159137976783618e3ad119ef92718e6510a591674364bd7cb7109899f9bad86fd71d1804dd6aae54dc49d98dc9b62eefcbf8493fd31ae274c1ff4c08521baf19d6cb7664f4932e42ea9d698118122433b3feba0895de2d2a82c7b109f8fb3283ad680346590c2feff5e690eca4df0be81be3af3c55918cf699a6a37268e7e0858bc59683a40cccc50cfcfd0c08ede2301bc8e9634fa699678c143bc73d4a0dfec4d67f445945b45c050019562e2a366bc5de65d530e2d19dd4b1d2fb516dacab4abb305456c4c7daae29a4b3b455784be64c1fb840c24fd4aea1e1b11ba4d8531a44a8f9b334b07b68c262a95788c0fa3c04cc39d1193c9f8a484abc8c04cd6bcd9a0ef5c9ee932f1b1483769732461a5f702d725ac76464e41172e914a29e8a43eac2c3ffc98ab100c72bd74b8c1ba2f8c4c2899bf5821cd9c4d106032371024047c24040a2317a05b3054b24a0799e92cb0b8a3897b817ddd2944e71fda97e6d155eca77fc2f5426ab874ed93cebc20428697c756a1f307aff1f3e3e48c0f00c268cc0974138e5185aa16a835c060287f972b630349f5ff7f49c8de7b6fb9a54c324919c209e209f509dba54dcc920e917c38fa7a8dc0a74ffdf422d333df260b3ebcfa515d731fd5354a1de8332ff5d5c35e5c1ce340028525f90f138281e70bd56347a4abd78b614d86b08b7209d16b67f8cf88eaa537eac527d860cdc7153d466dd48151276c83511ff121bca198c31bcc3f89bd401d986f329658aed64fe503f5f25217bc19621b77d020a00eccb10bc01b98c79c09666146f006731f76310b73ead1261d0cb34589a40d765d969d061a80c4afee033e751f7066813cf031a740409e766c5a790ca8e9b13a8da87b15d592457a8c62cfb9e456258d329d0fd4f3b5f006f3118cb0f23ffbd5f94775f81cb330ce2575a80bda605e2be77accf55c11d6b4727dfb3682119675a833763727dfdb10bcd9362ddb138d11e451e1dbe50dc2b2cbf9349dc2b04e4adf6e83ed098ba0ef6d8b6fff38a1ef2478d35158e9dfe6f46daf6f23024ad436046fda695097d49955a890d4a1713ad92a49ffd1984e52677baa4e2fd016bd9b93b431618afda8d06f4edf4e13fda342dfbe0d718e5ccd18d05443a74dac2344da50a707c4f73c30ac0fe1eeea87fc18c0ac9f1f77f44f8721eec87c4e2d36490d411ed8c44f9f3ec30d5247c6278e8c3ec01d41a28ee9133ae11041f1c34fce0a759acd398e522efec65969c2710a32b3f8e893067df4f9f41342f17332c95479caf4d12918da01309758580cf3a0bcbc5c19a4cd9c9e02917d711897e133ae848ccbf021322e4366888ccfdc1f973673a6a69d2f9e72222f7785f98b03b5524e0426f5e22ff707e5d6815a36758f6e127b51d7a346481fbda34b1f5d6261e95d518735b8b0d9a54f510735fae8980ccc6a77aa9c55b141ff60809867fe41c16e50769128115d8922468c387b74c095e1b2277360d93f9739b0b30617961d4a965d1f69834364e9e64a0cd13cf3ec6eae75639e39117a57337322f5aee69d3eef10ec873ae6402d2cbbf526c1e86df994c5a94948083e262424242424c4595e3a3bbd746eea999920a08dec3be32ac104f643cd30410d71ce37c3e4a510e7b48b732a6a09e77cddd14bef192671072a48428e8fb5e65de212aa4221b061647bc52b229857c7bcde4884bae6d4b5bb02c27e2f472111cde9c541091c6aa58e5d185711c332c7885c1cb26baf531b29b08e83c362d93082b1fbc177f583959a5879a097154269d34ebd1e0fe8e1037e8437cc0d21134dd2f22cc49f1da3843c50eaa0e59de08d44b9325410d046b2807abe28d793fd665c8f72cd081177a084a28e99269cf37593f39e2cca157734e11cc8514e8712670ee6a43ee3f4797f80aa03b522e6d587605eb10834826dba9c4b9c33a9709e184ecf7ec311158e844c4fec079d8ea0be76b1d3674b7a577978c52f5179b8c42ce8b40633399cd80f45e36db1abcaacf89ccfb8a40eca056da4d73ae362940be57a19a713c97c3a0e945bdc21bd641c5a3a11ac5e289bbeaeca4369635d2f77801d916ecdfb83a435dd87e7b54d98258750ae12b058e81fca5584dab4ac52ff761e4b629be8543efa165d8b9e458fd1b1fbb1e853d411bbfc37b37cf40f0b9a4cb3695a6156ec60c0829e4160e37f95bb5892222c0a1584053d7b09586cf40f1584924a12fef625d1e474440f57968800e2ca900e436009d242084b5a585e41ae10255d091281d51e264d51c414b63e4c9a4203419a9e643c4cb20118df0f939a8a5210219c73ce597b0a1bbde79c937960c1135a1369d0e5500b49e9249b24927cb54a4569236d1ff8d6410e48c6805978a0f60b5e7a64a24a9b7c2b5fd246be7a78f54bea4c26eea2e736fa792474d4aea31e62923af3f56a7a39cd2069c35e91ecd2917ca9aaf45223a954d6cafa1f922326957627537c21613a3a3a3a7a0e0a7a513a5fb24e97336806cd201feacda452592be9fd64f8795946a6415e54968dd5f550072eba78297dbbc1228397d2b55a3b47fa10cfbe0233334711458de481eb250f74f0495c8c600ba767598b3d11841516204501c5113f5c8e8cb0424b131e88d2c23ee0849386753d64effcc759b912c51631891346dfbd6c9f5d8f8e36ff71505839da41109ebdad952f18821b610754683ed0031655827ee0c3095a43a49452042fb597524ad95226ede0045c6d4a0335b8d88e396260a39412494a49d4dd4cc826f6986563e2f3360108cb8a4dcc7ac1d7c05205f0867d9346f0e6ca224964549fd9ebaa3d3acf58b5d7c0ffb158ca2e2dc42cb9d404121f75921c382624b1b149d66a6dd3b3cfa03a46fc2dd54484d128be5443d62594b5cb50e1920fd481d0a10e0b879923e51a5cacecf172bffe17daed304ebdbb3b22c9c425991b9180e8199771497dc6619c7a289799f13a9799f13897f1fc379799f1accbcc7829979991811b8c973985f1aa530ae34da7301e3bed86f134a7dd31b75f607ce48b37c35baf86f8327ee065cce165161f6ce2f36810049657d00f4fc0c00932c1234ae795ce411cc441481189858298254d00c27ed1296a894e318904362e45a412beb03126c64cb1d98d59d846ba94fe05e0e3e59935b8583621a98986f8f14ae761b19f2c92452ebc7c77ecda31a397de9e90d8246da4b7012b8db02b8b4a80818dfe49c8037558b20052361bb1a44ebc52002e2f1d081ca55b0bb3643ff56da7a6976e4212fbc9a222593483343021fcad35e7aad5d8c253c7b0235686a742349fb57acca026a710d537ea6d3f40adcdbf2a6413c2cd49c4bac432df380f87cd7f3a6f4564c3a1c3a1f3cd6337a4cb309f98f5aab4a98e09e1ee0f508b336221dbfd8942380cc38648973a5b02ac6ff7a7737bab0dd89094a3a417944a80f4cd6d13db90f370e01c1527d68fc50c49ca3b8747d8874d199ece30bde898075fab9f55a61c94ba4ab0a32e0edd0bdd5d0de1ee8ac8e6d2b73a6473eefe6c1885ade9d920b9257a0096235619f66fed18977d0c785a318cbba11e793ac353c738af34c848039b9e616f99d8afbf2b867dd4cb30179866bea21e9d76be55af08e6dfe6d5336f05042b4294794536c73c763f36c76ee77dfd5874cee3a8718f2c9cb2307a76ceee97d523ec5f8cae459216aec7f130290ba48f9d0b9c63f7db9cbbcdacee7e36c8ce0576eaecf487035c908eb955621b7691ceb52a8db06ff57e4d6bd6353bf2d486a75e69f899409529ad4cd901ecda2d529dded50f7a574030978eb9ec56c75abc1efa86fdc0bcde0f32ab529fcd25519bbb6347666666016b4e4ae9a47462dd4d29362785526b55d59a016dc596ed0cb8a3aa204f7b8d3b688056eac4e045151f2a9bbb6364d657652c33f33da2e2c1d2bbc28582e9e0e0b072bca258fbc9c848e963630338355689c990353f24736240d42c519f186358ac21c222d710d51471ce578394440d1124923044af79110c91b439aace5e74f61aa26aad8a61340fb2d837efc60d10159ebd8648ea70354491086e2a681f10bd5034676f5e8dab59e2c11416dcb0c3185dfe8bc01863746129a564e588dcb30bb69c0367cf49930234badf6a8cb0fd66c3b3dfbcfadbc57e2381fe56337fbbb1e190bf01807fb301008b859217f360ab67cbc9746936953cbbbb79ca49e7a4146339f9c2cb30a0419689259b5282f042931284185915ef0454849085890d2a2086069e5c2085131642489a22440f42a030106441449024c612cfdef5e56192184588c101d80d5dc239e19c734e6fd8ed4566dbda031a2f330bd8ae8f79ed84c3453e104328045dc0a8a24b0fc4e892c552172b8ce8b2d405e989071e9ebef042881594bcbeb862081f8abea022b48290d117525c2bf85065cbccc2ca20e1c4600546501981b685ca6b7e91fd808a10555505931fb66d76cf49eba4f4768d64a60e21e6957358ccaa396e0d4be6ce61960cb1a83d45963de9eca658ed9a499adf3c729c93d230d4716993c2f7bc4fea7de00d1336eaf858eacc2aecfacc0879bab52dfab48f0ff5e9ae6c5f64e1f8131ee8eb6fb3a3d87a57f4510ff41b9d4d81628c4f6c9bf7ad7264fd04fc56dc673046b16d53ca8e31c6eb6ee359b38699650e29a564296bec1338b3aa07dd90639e2d3fa0879b9414edb84d7b999bb669dbb6715ad723db5eb8c65a6a4b5e2133864520d3b616d49a6990d58eaae12585acd620f0d2e3cceea4df1378197bcc29e551e782c8b227c56aa66d5c874ad18edbb4947d9935dbb2ba6d9cf6f3d230315c0aafc1b064e5601d1c66085beb7a4c67815f1545fbc754e69134d626ac3736bbc21f73625d8f49bb1ffd10a3282d2ce8d4b2cb11323d9bbe1a1d679be860c8a0d321f393c6cf9a9f6050f929839fd3ed067ebaea033fc3d8c20a400e2e62541c3f2cd9d85044e7121493482a683c6141002e1be0028497ce0e45d29312c824a59c82e5a56c3802eb830dd6d0a9b2ccea806d55ec0e507d9bc0d0cfee79abf7845531b1d03feb4ca96cb61cf2c067a19a208f0a743accc97c4eead912c2b09f3b94704ee980fddc7d6a9ae6d06934ffa6939f997ff3023f7d0691f91ce21c17e4e17cdecfc86c7ad9014b299c2e6f369943413c3b5131c9ee85d9ea1c68e8679cae9f3eecdd6cfaf9c517666b7a6d0ac0d35b996539e9d57a4f58d6751398d8e8ed4d29f0863d7534831fbe28026704767b98f4c510350876c6102a062c7dd24060b31f08c105c5c2561d604b6cada20261332878605147740626984a36f530490820d87460510f93848001ac055b86f0013bf330698b46650bd3962a3e2bb41024694b111d420a8b92eb098b141faa6061810f465848b064088b114ac240c2d2810a2c61b9c00f06100213961e80304017d7952e4a0cc085e9ca5312037ce174c549c8004faf2b3c5062003086ae5ca1c40061046d21c2308dce96383829ecf48890847ac0720f93aad0210676c6c3242aae0461611e265151057681242a64d0c5f6c3242a9c58a2a281212bc2c3242a92e8818a0c0c61e9c3242a5cbcb38587573d4cba81d21217db1777e00d0efde850caeeee962d25c7ee141e28c6c8029962d970420aa59492f2e4e68b6296b265c76d5a562565863c6d9c604e6696dcccd6a6a4aa62159352b664e68a554cca96b14614cc12325bd4641aa7c8b227c56aa66d5c874aa1521645dbad7de9e60b0c0713b3c5c868323359aa9ba93264602f0255a9381877cc87cc9ad133389fd1f5983e83a6a9c32ba8304ceaf1d9f11d75409e962ae992258554696363091d998e3bb21c35758337ecd8fde8b3c3501abb5ad1601a7147c755af82533d4bef4b0dc8962bd72abfd648f26ad4c1fec235ee801f77d887bed917abf14a0cfa5b6afe9692bfa52004fa2d7af3e7c38f2373e42b5db6648c316e2a2d35a75b623b9863d441674b8691259cb3461433071b1d87590ebbb32f521be378c95005a7dc52b0c692451161b12a6f034b8f178759d0bf0ad9a3b4819c740707078771e08d6a0a9c38293029562bf62d719019d5e6d69cccb4df3aaeeb7a64dea5b41c35b6663938145cb09302b37ad88651c0712902d870a080342fccd676718a6cf4a31fb638e5c762a96cc0d2ea77ff34867dc71d10ea60245c6936b5de24e748a9fdc6715d0fcd39474598e3332dbe40cb6a30aab1946cec126c2e94b6a405752a3bf4152e75614eb2c469ca8e059efdeb599af0e8c811504b74c5261c9d3cc717d10a9e9378ce9268633cfb17ad3c17c15e8f20127c622d86b0428a2bba90e20346ad2f36a580092496b0208a962cac16197cb7f39d6f5d8f0e05859e7bface65a4c046ef50d16df44e5dcfbb2040dfdd1afab9edb298b055685a1052f09ae60593d7bcd8e23555fcccb1ae47d6b57af5c157200c7d75daf5a8164ad0633ebb1ed8009e3a5151adfc54fac153d5690d7d2a6a62d4a52f8eb2582dab1d7eb00ab308bea1a00283efeeee76e278830bb1f87234d105932e9a7ea0e4075cf840e919e7043e70f25dc1681bdd34bea9f8f66eaf4a7cbb2a4bd2777b0edd83107c77ed6ea426a9eeeeb64958b0a83dd860cd0a739ac1ba85375186e830ee80ce8e5119664b8e348883501dc3b0886db2d65a6b7568848d58acd56b55c9ae8e79b156afd565adb55257add5656dacc6af9487af0ee114e3ebdcf2f59b3ef88ad5aed43faf1a55ac6215ab58d5eaa6611a8669b23acb0a44734dabb5d6eab556add6aa55da8459d5e90b0c3b50c92e7531abba0945367a7558536b18f3e8a50ec736d13f9f45acf65a4737b882204f0dd335cfaa67577a5b6ce69c65712ecd25a0c8046f249603e499be596fb6a697d28e82908424d32bcb9cf3c0b0d4677cfc6dd61bb0a0b88326071c275693333d84920a491be92ed590bf58442f8b5e62387f73b01f5c2ac00a08f5c9d45a247a3d61563b0a49f68b2f94f78c56fbf4569a4f5ffd98d5a7033df5563f2af57a2bea7d987ad483a40ee4828221252a9050e24116ad4eba52f44237b4d7d7ebdb9948cc92492f99d8463a0df227956cca667cf2d12c499fba417695aa289ff155035b3da5aa1d4ad35ef3609697db6b34e51bc6594fb6a6877abb858d4e7147f66d04796013d55a95ca5f62d82fbe56a8cde123c527c803b9d51e5f55b314f60df0a68168b5c3b803f3e928af7674bab5e78d2f1b5ff0a6ddebf245a7f67ac59c4bdccc41e424756ec831036bfde5834f4cbcc6d1265ec5a7af9f79abe8e48561a9ac3ebd2a9f26c713f68b4eff2475a891b7533020cf8fa1cfeeaafab05633ed46271332c04dfe9cbc11f8543dfa342734b1d335af52e7c533cd85ce3589f25aeb5dad5e8071eb4460dcc25c28adf3107355d5377f71a0efbc7a9de655df66f8cc27eab2c00ea7b7b916bff3cc33a2face51dd8d419b7703bc41eac4d70d52a7b61abe3c0b1b9fa213b34ce8c162fe456ae46d1b573deeb5cd677780e89a03fd56bb0374502cff100e9236ed246d3ac6617cc66160ec1de232b72d0e8cdbce5f88c4dc5577572f58dbf94f8c5befee1098178771a0168c951e233d09cca546d2463ae7120b8bf2ae0617296f437950acc32e01f60629515d89d58fea28af8e4239ea16d13c7a55f27aa797de3151a3eac5cf3c8ebb1e42340a06bce1a0047d76a91666c9d5bf98275ac4ac1eaf5b391e04eadfb8b48859373cdae3c9162d8237cfc3658bc7fd41d2eab99448daf08eb7bae13c6edc1a88ecf01e273200e7e13dced3737f2a8ffb0337a62cf0867d26c939e6c9f57ce3ce202d5919bf41f3ba342614d919ef71c37d3805ffaa00fcb33fe33000fea97e4604ff6cfc8c6f59200f0acebe31710e8eb36f56588700cebe31c1393a9c6f9c7d33823c2798e09faa04ffec7736fed5ef3a967ffc29877047741275b0a75c05afa7083b29112c80431e2fc0fd5139ecacfbb00ed6077c1cf701ff060a8ec35570ef86ab80c3d3e127b80a5e7c1c1e8f24471f83d49953a04dbbd2b7a770bf6a836f170063f1ed01e069e5db457014da09e04d26d8a61dc79b46cc6ad7e1cd26cc6a3fc19b2e78d37ee34166e5b8df1c9a4ed8a6e38e1904d4d133cab79b703f5512df5ec2936fb7b917f876961300dcafc65fb9e4e13e0c7978d76b78ec5ca0e1f7c28e056fe515b91eff8687c37da4f4dc6b3cf824783d40ef4977dff156ed3dbee33cdeaa6f0d29a4200b1cb47e761c09842207265a4a48e7e13c6e5df6a3197aa719e29ccfc6e8798759343c6083700e0dafe1ec2d08b1e1c11fc16bdf564e98c52be95ed7c55bc9db3da1829eb034afd5a519ea9858ea1fcd10911dcec363476400dee3b11bc2e33cee0fd38089168fc76ec88ef7dc1f288516242ed0da711f49e3c19fe101bdcafbe812366478df9432e37d9b0fbee98af1687298525294e8dba43ccd946f0e695fcc530d911deb9e763c1e6fab418bde955fafe99eba27a943334433d43dc9eea97b7a569a82e5a319faad06ad1d1707b6b6c8f124400062e8a04a6b0097b5e3c1562fd98f65b301e5b0f712c19342de1673a30b2bd3b9854e3dcf11f2c0788f8064657c4675bb99da671c421dc7c9628cd228120955573cf2a472b298ad55ca8871cd93f1fe627cfd079d8efe834622d38c6f3371e6473f2184112fe37c8d44a69771ee80f413423c7919d8c95c9c18184f27c87e3bec3640a7cf061f214374208f0ff86d03b3e2123454359e6c3b0a05f6c55fda3b3fa224d290b90ffe2cf31166b0558c4e2391e9534c1f639c71fbbabd0f0bfa7e7a72726a6a3a8248d15938f743f28af1e7e8db37a734fc7ceae8bb140df253a9bbe21ca23c1b8e78f13d0b587fcd09b584ad0e80306cbd324d6ce6f9161db5aa691984c2c55a2c3d27894c5a34fdc775152dab9811cf972333928d1e6c89e0c1966b86555684a46850ec10fa61ab80162e680737d841070bf880054858250b204981c11229868432f03245084a8d274b12892de41414833460228ba02b48d8e04a152e2830c10503611491012743b0a24ea9401631f206594bb1b2a3c9c98911cfee23831298269864c4b4ac7b36c69557d8a22861f29fea099b3d5452c2c3ab96949404f150ebd5303a9ba60542625800fbb0e599ef43251fa6f0c1091553120d22ac746700e7c0dc18bdea9bf758bd30e3314e24e5314e044a9b940720898d71194742ea7ae8c53b47f926616060601ce8a57cf1603cebb0ebfcc5dece40d4d179cafb78e93bf79128af8759bc734472d77ec6f7ab313831dfce0b46763e3aad416c38f21e142ba4059f17a6466c10ea64d5da54b794379bcccd6e668a51d93dbb677743299823a639cece11929d96b9e96c86ccde53b60d724efb566595b2bdcaee6ee64a5972d532b65de79c933a63fe4daf4de90636c9cc118b0380ac56edb4f4a802640dc0477b6d0ae4a547860ae8497b4ad9eddd824db6943c008f5505c8ba016da463372f1d02796ef6972d218437517a41a7b0f4a1920f3f64562ceaa19290185bbc50b2c549488b20b61c255d0972bac202ffd51f7030860a70a005c7c3a42b3a00450b0db10955b145a12254d87905e95480e9092c414a9b16a3e9c4c9d0a8c9f1ec29f4304c8259a0169dff60971c50f03ce5390c251da6e080d20e5b3ea094848b120f4728f100c643a51ea478f6234a150841d0e3606b8735406080463c1ee0077bbbc0de3d7e60ced769f454455640b848bc2b20d78342a17f38bff30afa79ad84d60ab9612decaca873ae79e6ade825c2b9b6225233dfaab7a29cb7a2b5d6ad4a18390fb62a116e6d31b4f046767ecea879ab786dcbb6ec9a61d56347845bf5cee875156520fc0ac5aabab0d3891290406362b1874a3910614e763e54ca01043e2bb410a4c6166d658ac145931504890105112ba8a0480c15acb0822a2d11866974b6c4c14961a7a73209c256e08a85d9a21d59981d502d53c8a08a295b5481024d08551c51e361d20db6f0c006a5dbb8966147c8b329ecac035b4f2abbab43168ecbd9950697b506610f2233334b29657310c2c99021c31d29a54ab28cde07f45b9ced129852b6477985cc0b5f25a594b7331d365ae31c02c7128410564e4a1c4b73e258a2fe350e84104e31e79c13c36200216c0821c56aa675378510f68410e2a0d2d3238450353d72f006faacd365774fefcb308a83ca477fca4fa51581848484d418682424242424a49e1d45636022216db15589a52ad6458c2c7b52ac468e424d5cae9a69f48759413168934711e93987339aa1c906a78deb05c45085013230715d8442baae87e65de7837fa21867e7599ed276c42891833c9305c5a50dc72326866294b823aa00ea60c72e0be04d8c327fde6894819e9d9d157c52aa9c6864c450a092f568a89e506557da29d66086520e4b3e7acfc7181610678c3162f9fbd3bbeb31db2a052969a01965154260ea605d628c19cc18c88cf104473dc1881ee3c677dd818d3b43d8408e21c8c0d63ac56561edea61cc1144a6af47f0c2469e9d8359fcd19b63a4b2c4c62a71a98427962212af9f6eb7b031c87dc219fcf41c1ab0edd14b98c2c6e0d35b903aec4e3fa57d0d35575863be8874ce7eddddeeb7f98996527af56e2965adcc51727767157677bbc752e9abe6556a2e359fda959aa669f7cb6e95d21b366cd99285d058c39a397661e6366acd738665ded9ed6c6634cb304867eb748b65d740d5f1f3af11de0a55cf1ee5bc12d66a2d945cd44d326fb57af1dba35fe318bfa2cedfce2becd2e0837ff4cffb2179e9f4e36781f1b62afb30afdee718a6c52cd6fba9bcbb1e31898d0132306b019cc3ddb105690399636016775f9bda9136d09bce1a43367ac39e01de40666646c24092ab13d4e1bc75fa4729d5c1fafc1c010616875910c3e0ad4185be93a980b3bd95cf6f1a9f0946b3ba69389035a13623945e557242e950dea6425ea08f1e3e3c923a357a5c923a5aacc279fc62d3471859d2bd78249b524aa7c32336a8ab089a9c8237dcc236e7c421050e296cec49b19a691bd7a152f665c274313233324450cda059d1a831820df72e09353770cca49ab5363fbbf135afd5ccd5decc576f8723733e00f36da67fbb217fc301002e8b0060a1fa36bca1002dc1a6930473c8e9642fb9ca392c00fc2671fcd6377e9b9cf46a3ef36807036c552624fc86dddfaaf75be6bf69367edbb81abf75347e43ad7e4bd1fc6667fcf6a2fa0d4684df626438b9c3917a21b4917126cafc2623e63711607e53bdfc36c3fe46b342fd16329e70c5a9e01b1c6161843d3cc2a2e8e11116af874e1f1e6141c4cb787884c50e17f244e12ca8280521c5c80b0c3924f18a5bbe1c41086110420f21840c2194114208236408238431c6086552942c28adca593162ad0a79620703d6ca2e0a3fb01f7cbae1877376526056749b8fffe1c4200e427b750a29f5b18115e442b145310b97c5a6ecd6ca654e1e85201b8026f6834d31c6196be6510be7749edd9e226c7492f18ef14f367d4b2718db32373ac5c426eee5364981114ab2f7c62b629391fd2012abfdc87e314a9417d82f1211a9c07ed1891325ec175d2e22fbc524314909ec079f9e56603f98250b0cec07999892b01fa4422505b65d4dd8afa7c705f6c3c161c27e353548d8951396faf41509ac4e6c92362e7a8bbe2fbf6e606b1c1282e5e2cb09db0ebfa53c546262e5fb5f2b20152a59c0cacb6f8e926559f6da386f052456090afa4d763e864c603f7edd786311eeaee8bc2b7a81c42af103162a59a0cb532ef3da09b350b79bf41073178a6dcac2ac8e4e4bf40d6ce61148f5ec4220fe379d731fae1ebd58fd7e34723e3dcb327eceb3cc6996c18fb7488d2e66f9a871c885ea597c41a57ed22e29b3eaeaa157515337e19cd84f388e731ffd5c11e7ac8064ce39778b54cf6e642792727b7f7018a2092e2d6bbd9f55920e783144eb47e603ea86a45c89eab556df64bb9ed49bf9f43887f194c89c7ab46321f38a705e3b17d833a7dd0faefaa6753110d9601c760978f118ffb18e849b5c5081168c731e04e2c77febfdac7240c1095c2d998bc41231a505e331de0f9745eba787d952a273241d8216cc55823d35a3d8f6ce13e2e34aa53c7ec236ed5b45d9d48d454deeac32d3b9ac8798d5ed2a8a4d63d8a6a2f60f3655263292e3b3eaf19324f825a304f66bd72b36d91cecd72ecedbc539fc84f36213b3da338fe6041d587ed2c4328aec079f6ec8814209e09317e74c67400cb20521cc6af700f4602bbf64c3dab036ac5052ed1aea1638677a7b10213b6c13bd6f77ed1e02deb46b5e6300ea68c7bc6e026fba87a42be3b2ae07b6d5ba39dc38af59562b92e7bc6e1cc7a5547fb9b915c7f14beaa4e08ac239479cc43950c9b5f431956fee3f36622934dd5c0e16826faff5aee2d726a9d34dd8a64fd881fd3836497ead4c60637b2c8a51a2d176abf7f9578ee3bcb2505da35acd1c76358b35c2b9f49004138e3608b196b29bcaae614aaa522483242bb4b0e228c90aa3d84e1bacf91ace3aeb8ca194c69692e5c0e96eb8f5b6fd36b90bc56eb0ce3aabab89d4a1a1f1d80a6f94a35d8f7ec22c4c6676cb7018d70379264da5d1b43aebac2804d998ad3d6656c98113e370f6401e76e870864a0487243809b7a570bc6dd447370bcb3940b222b6c23afd92e123380f22780d95bbf330c36d38ec68dc731e564ec3c75b4df7fcba0d6f55bdc69d041fe24e825727c186d7dc1f12dc86ff5c77076ad1f0562f787e7d35ef10cfef6a080d27c16938095ec35bcd11bcd5ace1d36bd4f09afbb39a0ed4aae13f357ec36180ad2456da607efdc6fdf9b9e1376e953618506b04121cb648f04ff5180917b6ee85d2f38064bc3d1ba8e7018d005b343ca016ece46d226661de37866029e63197adf4eb31df3c66923102bbd4472d857334df1c7b71ed63aa538f9e8c4befbb5faf741f29433d96919d18ef3372bf1dc661dc87bb73c17a9491f1188f763d625a803fdd07fce9403fbd1e22e88c8cd7992b85883a64985ec67da48cc7798c87f217efcbf1304ebd8f7b98fbe23e72939c93ab496331de6f76b710a42184137be8995bcc535e74f2988a911cbf79c6b2ebb161ae79d06b295d1fa9c0f292d4e923698361be6d5f0c400fb6bd8f1e630861748a4f478dd41e8e200b9949ead8aab2ae62390b7b499d5aad55a9fcf2eb316f6f2ff5ddf990ce43ccc2bc3decdb0afbe13c8655973a5c3b86798dbef2228d07e50ccf8352040f4a9b0fa72d508a5d07d027852e215c61ca39af845162f70709d6c22e840e2d60a3c71ca8c4a4cbb3d755a382c4c08025cc8402272520ac7c03e1a469cacab143954aeed0156c90634f996fe7b9846f9bef1c37ec7d383bd2dbebee96b023eba061b70761cb164698b2f35d7b0002ac022811d4e0828b098ce0a28b232c558722bad080164f787801096812295e30a29d236a0d6df2df0e0e5114305069001ea93295d330620993951faac8c194244045b8e055051155a014910413581227524e78e84074450822b8ec9005d2c08a2d5376e0820a97a7244c9264000706a56685168268d912235687049686d18959d1ebec9edeb3482f61a1c7a48dd26ed8ce7476ffe8bf124a0c92f8309de02203b34b2771b073841735063b8411a7173b4754a952292d11c1f650698907ba701a0f9596ec204216be62f550e987235924f350e90727d0b3c13ec042a51f96fcc7d13c54520204ae1bf0900359930f32e362997cb01bf4106b78a86287ec68059f168228b101d73c545252829f0f959424f10456181b2dec8eff7cca752c91ea9c7394c7f9a6238a85cc424929573ea4f4945389e27e14e61dca53bee958c24affe28b7a3ea60f7a2110656ffef1a6529e622e76f356d9168459ec4393870fff8b148759dc3b4236d41632ab17605cc61300e33237012f1e736160fcc55bbd20e330320eb38af117df64bc15e6320e5b31de0a8b812de3c156cc4c37b76a8771d87af1567d5f1cb6ec12e7b6aa2cb7c492369cc3785c8c175f3cd8b21cc6c52732c638774438e7bc55778f592acc6229cc627b64916c956bed927cb13a212fdef1c9141b89e2cb535e421796fa175f3d1db046761e753fa0e82f2c6e6ab2af1166c93003b398015dec078f988e78f60504692afb4884a20aa78f5f7c75cb653dbe5e2fc803a91431d21e61ebc501f23aa53846ca066b3e9ba31d1e87bef94bef06125dde6df319de07f4337c86d3958d1c1db01f0dcd108d13ce198186b3c7aec708fecda697524aafe13e2c2502e2d738ec6cb80f3bec7a90e03ebc6db15b01c0a1d4e1e1edd72bb272f87236c9e170e3e1cd168df7c5a7f12fa23c0dbfbe315753f382dc7438ec7adc9c60c3fbe2db78417630d0160f1578789448daccaf7ef6f3cfb6cac5ebdbf550bec57bb7946f193763498f192e1ff16708c19bb67e82751c14acabe0996f3351d81b9b6fb3e994a8cd28e55847e39b53613fcec52d256a8690f6e25fccd30bb38572491bf6bbfa11fd86dfb89f0e8f0ef45ff7d474c3e36f4d37ce37776bd2e16d56ec1696668886099a231a2990e786b3b398208f0acf325c85fbf967321c85fba93e93e138f784fbd5cf704ef02ff59c439839843a1d93c78e85d4a380c20a05f7f196f3788fefb80e1d3c3cf079f4782b142e941e2f80bf774c3897e94fb85feabfaee511c07bbc96bfd7e3373c9a2078c34e3304e3a987f12f05f31e01bce5cd78427debce60eaf16634cd7092364c33c4f4ddd317f3840ae29c1a6eb80df573bce709f0f7c7e7d2bc08707f56437838019c00f7a7009766e8ae84ac5888373c4e69e2d58a5058616a01b576dc8acdf174bcc7e356cc93d4a1a9d5c6dcb8e1c5d7f16ab041e5b40450073bcd109c99e9e9f1a50ba8148d36754d0b95aa1100000000f314002020100c07444271482c9cc6d93af614000d7e9e3e76589a8bb42c87511432c6186308208000020044648088883300f1233dc602bffea6afbcb3320d16aeb9037f28b514d779cd1f01c7ed209066960d9df822958ab7367c56a8210083aa9cbac2a55611cec40f04ca1acb7a4110d05ebddd8c872622f1badd872a8a5d1556a5b739f03d52c3ffc9a90ba3b6bf474dee5964a481808a40d99420fdf3842ba5146ac92c3ca1a50dd2f0522cc53c5ead06b44e2c9b53dd311ab5ddb36763dab46ede6e95d40b0ee012ee490f216a7bb33524e4f2e8ab998ec0e8d1b4166a6aa7ce67ca456a5d089655b40558c40611857d4f92519e87dc6c0268de1fc894af0dc2faa999b9baaa25922d3d2614389cb9cb861ceba8386cfac25d9e31278cb5fff9c096a056132559b0fe4d51dd891fc1209af7a43d500147c2dfe0e3e6d18093708b97b991b3f65fa3087ae85fc8d8e431aeeda06d776823eecd3de4c1c7311965a45fb925d5734de015882e85c24eec3f11d821dad253d5c47e28f27e5489c216dda7981d2b67e13b8622caaa9c0f7ea18fdd9ff53d08b38667217cd12e64777d8bd38e223957b786858b7b956a341e43d6ceb2efe9e6b2d7f441f156c4bb0dd82159115a06bf2f6e9e55825921741485b021b4d66e6bb27e71ac50de534f33cd4da0d6e2342d9eac01f79a89597d4622e8eff0b5272d3828721e1a6c2897c27521403bf53c07380a732e9d5d78963beedcca3c496263e836523fae9052fa8d4ac72fa612a2cd2743cc297ff4d7e33949c2aeeb830d58bfb1016161ae2df3932ae6e1724c970407be8b44f4cdf05c65b0eceb82d72d2236c8b54669b22a49f265912039cb61af84b1d751809f6e8f19b0938d40bf70db067bbfb8e0533456ecbd1b5909996b783ef5060eac5fe1351632003ed1d1678e89b0f69a22d802671077e25ed7edec1820f54f65f7223963c84445ae08e072d50aee9c5770ba4b7bdedc4a531349ac5cffa2017eea38aa1f0273a73dba2f7e6ab3769e1c6d236075d5e12b99a00b0fe5d215ad8aab96cb88552de91b7fe0564961c8b5c58eecc0601940a4409de6bb300a4b6b433dbcd2791942695d23c00c06dd73b49bfa99feef38d45cc4f3bfee13c7813d5f46915c16878ecbe3f6a4568b591ac4e300abf023827e327193d91e0c8b60f07d8bcfb1fdf6248eb60e2a08649ec30a82bb0de83a583231c8dfcc35700a814752f6f0b05ada14b99cc50b860cce2177d354769005415035a131a41996f25f185fb1f031b4d147ab22bbde70a1a9055611e2dd1616a2cd4a9a9f32d9237bcddfa0c0c801f5ff0a8bd9b9fcbf7df3f1db8179b24a0c56a884838d22dbb4c88400c1902ca2d5dac409eb10ba25824a4ec9fe419d71d3033a42a4239effa292301f82435e536344ea0b55d648493835b15913be42da96180a20a5a9a0ff8129329e30bdc1d55c7649c3d3e7389b951aa8113577c41877337e73f65b9aa26c9e651b40eccf46e858979d437f8829d743bb616356a2ba6ae2bdeca4ba2cd0c78f08ee71a9b0daaf5ccfac78eda7fae6272f1155c162b5fe191e76285111f1bb5fae6daf0acd5d62fef24a7f9f3d3ca525076d0e1db9c1afbc06797efb519b44d19daf34018fd59b7b2fc1c7376b4fad350d9ef4024da7ffbe56980e13cf5a90349f9517cf12386a07af780ba2454e46544f67d9bd000be464b07800f7673698acfa55a90777b25e7c7424c24a20cef768ee90031a18624143c34e326a5128b1d01bd855a410b2b20facd1b5e8c5e18abe5be0676df6749aa8a78905196a048e8533c35f7d8e2a646c32a03f9709a4c16ac1751cab3601882943a74c7dd4268001e69efe173eae6080f4baa60227bc4e7098b3d48412e535a1ae4f21b01fe01f0c2cef405a14932c57eb4c2b9be36942443b34153a043ef2ac4968523de3dd92443046a1eea4c8649598ea5668d0f0df3bbecc2ccc4baa34c905c37f785f3dfa039298b61073c16ff06e5c91eda13664a8ef8e7335d6f3801e4a0b35c8d8312f185192e821fcca1998827f3cfb1070a6233602fb7c398f3c2d1bc888f3c1c8e0e30cbd5e8e9a2d5f4df755459dc87a079706257041a4f89354652db6e4387da43c53cf95df13831c66c67f868eb42b7825179233ba957e8e544c1e172748a8e48222b969436c7a1b6124700da441831beb6baf46b7259ed996b66c39c523aab20cf1a1317b337e404ca86d49989af46632b96ffa0ce40a96ea0e5b374c5664863ce0bd08b382b0bd14156a39c6090b129471becdbd58122714ce6363ac26888f3a533013ee4060aa060de8d70a4b62488c6fce645a859358c4410fd4248366a79ff0639ae895aa9a9daa3607f1418c5a84fd6034c173026088014da939fd73718214fc9cf4cc70375dd28abe7811b8c5a2596105ab9c911c059e77235cc9089c8e9c5dd41780535571ee80727a11f26a419ad50564aac8071697e3e2d05c55822e63aef4cdf5faa2613e5cde316d32a174d040b143171e8f785143631c01365f7a66baae9e95b920cfb5d45325586c76b3e0900cd5dcbc287df4d948ad7dfc9e96ee994a1198d9ae7ac6f3425e0c90cd3228a32e1acbc3bdda82fbfe1028438b8f174bfd0614322a6f1b8cc1823719c3094993fda72ee2b17636991e1898636469e65230a770c5fe724a4acc8274847f501aab0f9bd185f705d1a961a98f2a10b8c61975c4c9ec0cf97f3daf08cfe23091d480583514046af01bfdea0494b392b950c76de5924d62c8440de7a77d2bafeaf26868883fc87c8ae3388132760370a31a7f2aea3ebfd131ca0aa017f24f606d16fb54a8d4d778963f4fac4eee846d625c5b1d6e0dee8b8391e6d478cf85c59abd20a7324a92c433097c00f713bd7205ae6ce8eb7500453ca2e199986724d00fa4e71fe6c70e54748429b0e46e3519b5481727ffbfcf7188dbafb263d2930612695f178a24515796cbf7fccd332bed37dc47af3e4f749d903bb3a216ed68d33e041f7101e92c76eea6b1fd07f162990c070c0d8a07388a664a6c472e0dfb9bdf6288b96ecb431b306ec0d90d4f9b8dd7276cb9d70098850cd41912ba2335cbf49a71bd862d08d03ea1bdf48f35b06045a1f1c3dca7cc3c5b03051b4d8ed81ddc08fce7189909bc6a3839c7a4c0a9af7542fa3eeb0073d2aa5cbb8ae203628eadd68e0a841a21f6bf4e951143cb6925f8c5437fdcc8040de74da2c743a65c6ee3354e4f7f287d22fe01d707d32c72f922c5f3410e626c80463a8df7990148e4cd7979e2f9dcbf059d8c132a7fae9e8f5513303b81f1a927727238cad09661eca44c78dbba0cd4c020a4d1e67c24d4d336e531326bd9038c6f21982b660bdf12f84362c0d9bd484cb82e12b84e47a81f4fbde472f229ed0d4e5139dce6343474a8d4e581dd1b4abdf011a029bfacc404c839119c8c1e915014b6684c8425d259b72b8a037b0abf7b7a870eb0ea893d3d4a44a86374bb9846c16e607b129312bcc0c3f0fceae3cc482779cef9ce0e5e532cc1a86f6c280cf30c6015fecf19a95d1edd83e98cef41909be0064e01d73313814d57fc7b46af8afab8c9a7728153fb839e5ed39f8b956185826b0c686d572476af426b59a6105a650e2bae421f0447b7fbca77a4e3daf77ad007e926d03f5631210c9de5e69e2a146cecfd6c3e5aabbe18f3d26070b14711ad534c9cc84ea60835e0ddef09daaa709b4ead715fe7009c025833096b970d4898a300a9ec90641612d92c8d7daa06a17d5d45772ad73551973f157460802c1fa24a29ff931469fa97ad1a628455ea4daba5098655ecefeb2eb1fd8ca018b765e17a9d7bc3111cc09da467d3cb7e6507901d94f34bbec29c5c32c35b285159ce7de2c0ef765108eb634586396930bfcba43aeb381aa8df6547737e2d1bd8a75758b95693dafc3ad5c7f64c1fe80db20e570f4c649d03fe64c850f8d162d9fe14a1c2cf4abd18976556a740b09360ab7810ceceb472f7d4cf6e2a039ec67b1958a8351353653407c1a4afc5e10771ca298fef4a48467c2af401abbc4d9bd93d7a820108376786958fccf055599925989578f5ac77ddb49f8fad4d048d9527d1e27327fcf1aadfb51c34fb450e60cbbc568cbaffae41bd8bbc48b3491004f284f8c559e9da57a1e7b92345781d59aaf8eee77aed5b69a6c0cc50a1251dda38a30ca583a3332db4cd0e0f74dac646f4692e3d32ebb1e171aede5e0f7ca3d7c2c864ac9e8c4127cdc13a10f65a52705b5ed387e05323e3877a299332777134fffc20526e0ce0ec9d37606b3a5a8e1c63788b1baf9580bc92373f53fb8f1f385ed527fa121c5fc3e039b07d1a16de4670ca57145b0475b7e55a9371cb58f8d41f2c505ce10b3bb102cf3140416cb2c6c4004d05884324567156fe2116478881bf2f97d31b583cd7d844726263b95a7877940b0ba0ae4765075cacaa1ab5218362fcf2899a2f7b2bb73760ec8a5689083c56ce82995b410437b30ea4a7800a89cda4f8aa5fc3d6f91669b5659e415e6d1191c807cb9ce4dbc76d86d52ce45834dfc2a83e089d81cf3d046814cfd915ce0dedf03d6b6acc3087d4d19dfab3ce67d5077b7a3dc0c66dd2aa127e8dfb0c77f4b54d2aa17d0c8d0cbe13960fc6087d63212a3dbe7304b534a5175c4be0a5e283ed11c4c7920b137953f38ee5e7ca3661ad8ef656dcd181eaa74abac8b942d38bbc0d332630b9f3e15f0d28b6ec35be49c373b7982edecbffb2f0a1d3b2fb0be55cb38509ebeb6d618077a2cab3fe54785f03377438d19c8a3981e03f0dc1a6f4b8e4d15dd841298bf0ecf2915960f9ef9dad41e877033e99db31be9ea956136aaa67089e45055b85a67aa1fc7f888cfc3fcbc77b3a2b85903420db46482feb9a25b41f5561003826ad9efa420a6ad7e3c44d4cf03dbc2b4a1a998e13cadae832f2777ebb522ba04e5d1917f685316b46eab6416eb4f479e629779dbc2acfe4293a79edf22d8c0999f36c9a45ded75a008db89735eb539407fcca5722158552823285a53dabbc935a2e2f08039985ae8daa2bc750d93308a5db20cf5e44ee980846e49cc9e0fe18637cbb51390c9dee3c9497b497e11f8434b3e99123650d8cb232a5db30a7c089b376048609ea00acffb2f670d99b3fa044e89787050180667a3a461165a54e969e9a87514b1cb785a87845badd942749cb06bef7886bab391f4d269882600c8fbb759b73b22f8a0f2216d00090f0affb0b1fd9eac580fcf31d650212ceef3874818cf0a0df4b52aa07a24287315553c7aa0dc35ce780593d8c420c7b241adc862799bc87945dd9464a7f596310d8d8424369309cb096a7eb884e092b39254801e7c975749a78d26cd2eb0055c262f95c4e9c2d6127af29b7339aafebc7b0c3c0ffbc5282d82538c3bba328bdbc319d0e9b4af5940a472a174a93eb69c75e3c5f7aa61aef33718f8fd780047797b5b2fa938baac04aec719188ac0b3666015cc5fd03db1723e9a26f390e2935053594c99cc6cffcc1491e697de8bebe524a9e9106640906de84813aef7acd293b03ad3a5c6bcc3575cee4b02c16dd0775fa3d25ea2afa206fd078b2251c093bd900445cde52862c7d5150c0a23a4a2b81a00d6e10edc636210b5d49ff585a045a8d8ef8be0992327a4757f74115772b1b3e5014e05566014bf5acacd6d68411a4205a6f0fc5fbeb544b8aa4bc896e2c074dcca8d0918d6b046dc2690ac09b72b823ee5f113691fc8c1d82073b1e7c5df50561c5ad9ad1cd809563ca83a6774d744ea32753ca6e68db541323c64b08dc19a289cd977fbcccba9a582dcc69b2b922bc8cd860d0740610f10207da135092eef5178f794c864fab4e0fc5669ba9bf3626646bb3638aacf0d8362494617a827b0d8da8be181d65fe5adeb439674c2b4382f22f07f7b2ed0691cdcee46444ba7fa320e77917bdce4498dcf90fee5e430dd705c99a7f68ed8af326f011756286344e0f06acf43cc867b11edf132b0fbe85278f7aedb209b2be2fb9e1870f6c6cf5b09f87e22f11801bdcd65db5705b9bc17c8a153c7f7970a45ed8545e3998f894019eded0c25416930156618f4afe820fc19a6534dac7a5d5ffb20487d5052269e351dc2c49f94da81916aab2053b33a942840cd3dfc0de97c6727207d8a1e3ac60e621b2d2478f7ec6875ea0edc1bffec59944970426ee0f07471db4289f4396332e18369ff6a4af8ff6ac8861135a1027512873a2a1e8bdc252cdaabda9adc25279dcd9097f9ff02421283d079198f3650361ab648381a7170c179b29f58a03cbfc9b0bc0cf92aeaf71a03a1cade447c972018107fc6f2f74790fd75b9d5a19953ee24e21901d16c0c38d9a62712ba2cdf34709c8cd8da319b12c270aef4eb56a6af8365678f05ed3c15d48093118e10cbf803bf01bcce98401d5139d9fa4322c19d0b48002567c104f581077c4d172cae875a4f1ad19623169e8c9544c34a29c77a28cbc745237704036eaffa06890dac4f87113cd9441cfcc22fe5ec2f283b0baf428c2d9c6c45810b81bbe4023e0056c26b63adc5696dd997515c00f43e60e9eb70fb702f9c75e28fba331fb4129ce57fc158a40c22cc49a7af063125aa26f2719b29a34d925e1897eb35020caa4371abb09063128b91a9921ffd0f8e156af03dc2aa6939c90f398fecc629d678d5c303fa265590e1c0beb7cfe60849b2b928bca08badcf15679e2c9437f968886c3e1bd88433d1c86e3948749e91cd7e399238374efd91de638e4a40a929e6a64d372890128e813e24b5f3703d7b755b8519ff7813cf3b1074ed28441aefacd7d8bc31fe677982c4457e0328c218a90e432d14eb80d3a940f4147ee7e0efe9c2a67de07f263d21ecc29697352d5bc29f9d8e4c3b79c1636e75b2a5e7fbc1e773fd1204bd1cc7e5c3da2676f41da8472c09e52b27db383cfdd4fdf14cc47521446e0cd7d4a0cf101a4e5de90a5c2842602c16030664c7aa699a1bf5fd806f7cd49b154a7d4caf111d836018e9094e9f5503b2e5e71c6dab242bb8d84b5cfa0597a9326c49c06d4a36d203e1eca9f4373c031cc3f4ed04d7443f3bfd18bd056b4aa05b88e833cf99323aaa1b116816569770ee3913ca4bd0811097a14c3698b70a5ee70c86c3d53bf1da80e1e7cf096cc369d49f66034ea5433a508c4fcd33b1e48b2b490c23f81a5f7c9aa4b6b113f0c9e221f2e0f2be2ae1c2e28a2fd383c67bf6ca44949c496cde90cdf4a44eabd150324da89696b8923a9eefa1d76958490472e4ba772233ccc4b5b89c729fa0e0e789abd948cba2ec06ff764af76c7c193881ba9a25b6e79e6b2d147a7d3cc48d6014ba6a93b3dd98844408ed68626c9eb0de83192047a860b70c62ec6654e09f387b6892ecf12587b7118af5de5aced0bb143c7a20ac3777ceb08ada9aebcb0cb8d6641d2c687c0c33ddf3e1582aa1aa8acaec8d2475b8c8f5af48edd875699370678ac8d0ffb5b70e6ddaa12590f20580c4dac684ca033764bea87e80c6c67cd1806a0426d7e83d4a23dcac361e761ebc84e427761333423d1085f3b2d501838ca9603df0c1e904c10a823532e5b7ef592ba1f3b28fa74c0c818be139386c13bd747bf4fa1d1ba573362ed94d97d5fdd064c42dc054a7c7a9dcb0614a60e69f55322bcbb8b1ba229cb85399efff7d39e8934c9c7575adbf35a15abcda6377d979a9024034c44cc488ee7248a65b32f5613e869a93321773c0c243640a40d481dfea88004761b3aec4d7dd9ed4997d98774e240a6ca32343f1dce53a1ae9044beb2594fb1696798c0e99854a4a8248b8f8983b1ea2b3ea68c5cae0ed5bbbf73f4a4371663860e6059a04b396867ac9b7179f1bfd01c8d9a0698165491ecbeed69c39625863a6132740f1b7f79827fd9628572e126acd53ad030138b37390fe75bd8b928df46751f2ee218c1438846c04d2129da973d6ffa7486121ce72244143c96544b4104f41bbae82fbebc225565dd4708316decdba70b72ee7605e6171cb9d1a0a382786f13152ee94b0f247e66446c85cdcb776a345c67d428e91815004d1e700d904a9678c07e3d4b39fe8159ff481d7866a5c2caac3c71f33e7ccb0033018e1eda10cf3453f8bf9f67c9a1320ad17359cd494520251569c68b52582f0009c698c8347f7aac746204477f43e09871fc90216d2d3ef84d4e6343c9f2281fe35bf1734e483e5f63545ff52205e9e66a6a822f6f31c0f99539e44b876970028fbe2194a0c97e0950569e8c28139dd75ca38c0334cebd55c162574d2c58a9de39eb903e7931d8f8e881ef517549b4cba7d55bc381cb9a75285d9688baf3ffd65ad5ce90be4c41604d97cc79f276aefb59c083c974f6004ad43d7979e97fc892ecd6f4755e6a28016122837616197a8930f4d7b67a6bdf11cfb9dcfedd46077fae1c5ecd5b28b6c3aa258aa8151716dc3e49eb1f2e18c197c28b38efd344643f8d57641265bef504830f098b6f0e17fa6e0650aa1dd7d1a3ef5eb96dc64431cbf05b3ba13d6817a1fcc40256222744d9ff560092dcf60f5a75771e088dbfdc305421409380e0a956e49981c67b5e6334e4f2bd2437e7da8129108228e6541701bdcaa2856a3c1677aaefa36f2b8eec2354db53f72fa457b9a9476e7f5ab5726c3fe578ac9b606ba0f5718b1cefd0b898c5b41587dfd698ed352473881b7994225be23fbbd61fa6a03a965c7fb10545b6c735c8b537454b4d1d7083399b294521b8f9acbfa22596e0c4a6177a04ff2c9693b7df3b81221dc037a1b33ba8e7e19413a476628b26d0811bb72f0ebd882e4e10de949bb63b0b49a09d1cced0ca40a1e0a2506e92f4d8231dfab966e88f169acc0470c6e3d21f04cb19d965aaf47e4890ed755a1a5bed89e29b126340ec2ed2d4cf9ca0b3669051c834eb905db64e461938282001739c5d254c62483f7d3022faeed098848e604878d72fcaff134883b222b54e57aab0a789db2ee7a7c9b6fc79321ee6e3007b225ad13b2730f385aab6fabef4eb317331ec2fd155038b0564f6e0a9676d5064bbda75990428de9af2836528bf1bea6a499c0d52346540115b49daacbe1c32a4223207dd17f4fcb8fe58f812313bef4811d45ef6085bbc76cdcbc76c4dc01e56501d40dc843b6d3f60921cca801d4aed2b247400d8c020b755b7c5f547ce26acd61c9cdc5dc6028889ba8fd6687d804e10deeee09e58ae7c579ee35db572044441ee8bb7ef83e96a8bf915ab75b4840c1d440ae11c1a7d1c46938d125d7de83a188e9bafcd58bb4f7d575659fe44009bd00a77a6e6fe0e557bbab5b35abb656592c34cc64f6941eac98eb4fcf7d7458c4345ee2bcb1fa798c96f5307cfbb21d0267170d54fe2ef357667f1fb2ad7d25d06cf29530f3065c65627c6cfa42829c8d16862a0b7486202a83c7fadefe8ff6dccc04b9c2923d53b954aa3b50780e81f01a6182b6bc245c327b468c3d71da5f4548093b57a76e83e5be03b86e1f0c383fa5bb0e97499d23fda007e5ad3929dc17118143fcf66fa247f7f10038f5d9474c9f7e9b9b33b7227fdbf7571870b1ee3381520dd7fa6a3a006c07e50bbc82331e61dc97b66e3d378db68bc5bb7c52c59af367007f95518ccaabf9a731026053d71c5f2882a46c43bd2c5f961bab8cd60651d5b0b2819e8abac72dc9a2b22af463248d613aa570f8917740c071994e6609f10148e9fe8751d00b90b4692c59be2561151e98a55d2c3c15a1f410275c58d2afcab2fdbd2f8b6b1ea6d707faffa2d6aa1f3aba6eb2423fe05283fd0c9ebb2002c46fa8371c4b3e50b3a5b620fdf08ddd9714c01aaf1ca45ccbf21fbd633215a5312ecbcbac925e739bb3a3ce54e8de02eb6dea4af85b34871ff166ad5bdef4ccc4b5b5c6b361b2e5bf7f6a80d5a827365d93e08cc826d4fff0e1b68d7b1d19a04a0338b888ad98444666e53980d417b79b80c477df94c9e3e3f91ff693f55e23ae34258aebaf81aa442a50ea3dd5c789895e98e03caa83813a35a05e97205f1f31ffef612c2b8cb55ebc3a44435ceef181aa946f2b68de245787e42255fe92c89d30c0b4af86fb0391119bd5d97a6384a27bae50dd7861f992fa59b474f15bce1b783ade9e0b38d1b09c58530b969a66ea4008f8a51ee1243c8c800fe6bd316cf7d5415c8e21c3eadc0edddeb36ef11621565cf236d75f88c49ee8052b68017bac3f3f6ad090c2012153b0e3425194ef5d02a5a49ba18d4e65a30ed8c0882724487efd35408d62c9a236d8831d741fb20b2c3c39c0fc5d6cb809ad9b6f05605cae5cebd4ac413c0dde2627750b7929efe53cafa4e500252c71cc91301f3fc8f8c5bf5c420cb5a98855845a9ff2eb937313ca06bb607520fe3a421eafe4a4a0745f423d767d8c5b52d29cd954278a804fcf01478be289d7f00593067a530a73b907ee35f913d4d441ffd4ff685f3f1a8443fad9427a940c24155966f7dc2226b7a683108f061391adbfc94f1e1c8a68dc34a43d1e4407949554171865f6fa06ea0c3ee481f9eec788e3026f2650fa956112f007a8c291e39b583c085d97a7bf5acd484b2ff202e3eec7bf1120f4b48acafa3a46d6da6d1484118ba74ef8285c1bb3fa66c7e055f7c98dfe8e83218b9aee18d866e156c8640950e6ff8a045d48189fcebb4231ad01dff0aae4bbd62a355a7cc0524fa79a7b5724956a4d687e90d5bb92f0e6be6b93e5f0fc8f63be20a189458c9cd4118dbf1f1fa08803d62924575d0a2b4b53029f729dc88dbe727c32da13fd6385aa1fd1d17a58461bb732ba1d7e4853572ba614e9f4792133f99c18f5861c9bd931794990c04ca22d634b3b5f8e26e0ab1156a34a1b91c37275e48e8c9a45c6126386aabb2190aad79acad100509dc18d46ad805160bd2920f09c44709c37eb9ad7552d2c728ad2550933ef7c37791f11c5315666b528ef8e055973b6af9065c203bed64da36892734ebe186149c2039a857653a1ebd25d473958ec2ca133825b83cb71e9fca85b4ed182d60ed2b6ab1e6855ed8832927b44e90558e24eb72f11a04f2f5f10dd5fc031474bd056dc4525fea9053cbdfc33d0cbdade1c258d7ceeb97d8b638b243f1203b85ce1ba8c3d2edcd1141c23559a024352082b325ebb0df05e5287f1713eb3e7b3bdfb6159844227625c95f07157879b6fe19f26e69a95add7700e010fb554b177295364a7d932b0415f5ed75beb09a182e8363f4c3533a227f1f5901b2dea8a167b21d9444445416626bf29bfbcafbf685f3d20c3db26a0ba5d0a066862c0ef2a4125347f585571d4d7ec043c3719d0886b88070c449dd94d7638d48358c714b72adbc200f315da539bb5a430e0f0976aba403f67f851071e4be0bc16100b61fdcdbbc2781d3000ff1cae3f9079337da7f090e4ce1e99b50870e6715e22d0aca5c9f31cbbdc5ea630237827266f0c2672ee6cca6420c691cab60052562d8137600b101e81bbc84970a86aafea2081bf394e32b42845cdcf9793d6019e1c3df39330bb3261af85278fe099a12b79997508389a788fb35dac1a40ea5484232f4a36c6e5f721d8d5e92f70dc4e8ee7bd04ec3d9404ae6a3fe2cf0238100710815e2229cb487530adb6c09e2bd627a0462bb2ea1cad244f77d1861f3f6eb6d950d62b92be4f00eccfb1ec486ba7f98c059411ec938b84294c010d694c6a0156de2350bc8608fa01a10c87232ee502de81e6140e694680a2522275802a5484f6c1c49eb56a3ac7d4d0d48c493be6698c414339a80cfbd49976079a56b7aaacc3d9ec542daf6912125a8d5b288ad10ce9e0199561b5e6f14ad83dd176a276ebe4960928300628e99813ee3577ca4d6f8d29b0fe3598d5c212f2429b2c5041e2dfea43c043517519137aa90a5b757b78d91bc0af96befa059890495686da6483c8e21c817810f2c1ad7990fac43196ca8cb49a47ea56f19e9a86a021985a1c47f4463fef055d61ca80ba586e596998724d32f932d063af1eda00e70485d941c7ea253d0cb46a2d5ba6b6203b95cea66fbbcbbd0e2f35d250b51ed15414fb8df398bd52d3109ae637e20a0de8177007fb9d0e0b40679a0ced73f2ec64ed1e74afe394a3ebc5495bf0f464acdedbb76552373e217e79eface0440e89f6ed1a05d7a67ebcde5031ec78bbefa0267e0f1369cceb1167ad39f1b7faa36f323e2913ca7e827feabfe472f4890440daf2fc9b9323ce24915bec144daabd6cefc2eb38c4d082d5b780e0d7b4b3e9ac77560b0c931e7c65fbc3569fd45bd91bf128884ce54afbe5c738b5b6c6629df48b21d19d08f9cf4cdccf12e2d90a1c775855c15add606ba24a8f229ed3b58381bdeee7ed32eb74e6f63501fd67f6f9efa055428569d9244411b86a31ded970d29317abfe811413d0e93c0d1edfc532e1dd883088e113325d90b53f20d44897105caec244fdf9fe2cf3e8ff48228af9bdcf6fe68a87f8f806d6f3470d4f4d00280b86cff01e00fc6265c9bd12b504264d14339e086045bc04991f1cb9d750442be5ce053deeaff38cafe3ba8d342ff1d73e25464c0184f1fbf895083a9686aa4a81042dc13227f83c8f91d43b1e98f914404144fa83a98d373eb9a7b9311fc9ec783f2a0de416184cf7102fc69555250b050028d3b76454ea070a92b29fb885ccac6905f3f02087e60a549af57350ca49ab80aa6267e3f72bab3cb909a1c016db09b237b832bf05842229b0ce57bb7d1db092ef7c793241c29499a78befdd7749be325e6075504f1583b061cb71d952875e9395e7dd0a64595bf64dc4aa4eb92491dcbe61b15a1d3c81e92c29c9657b421602bf3ae384574dcb53df6e0a7771332e20f93493efbc590ebc71f74bdf31bf5fef65fe6576afbc71d5d38d0406ba9e7917f07a09d8642860cbbf4a82165d5357374eddc41adb835e875e92ea86155e1994f27747ec0003271f2562cf21d82c263dae597e49557cb66922d96e84f3e95afc468268a0b3ba9b3a14e91b7b8ccea3691b2720e5dc764408c164c92da704e25108c70c35be53496a454acb06844d150b6ad7c1807fff298278c2e8c5a5cc2a3adfc1c098f96956280c0a419f4fe714b968d36868bbe83b4e087482d38c47c0adf11533fcea298e77ac06535065ab645fad8c9078a3991db3118cce6bbd62c08bf04e645cd513a2db65ddf65d11eb57a4849fe9c529ef419920308549e27d0de69c4c562c6862ac964154b316f3af0e1c27888f0736109287b4ecbe3c374610842520d3e4a260cc043d562814ae49374976087ed2daf43177ebbc0c73e0d72a8391d5b652aa9102ec046fd9c8abb2bd4bb3e31a56492d894fe1c027291b5e24d7f9c8c5d1760025331b495fa2975bbe56007b3b5de028bbf5af0af40633211080824d9582c07efd5bc173d5b6b32f73fef7477e3a2c5406a29ff9420751db9b3c0ca817db53b79b4a90a594bc74a7ab03d3e966f7e7ecd58a930af6286e3a7dd8ab113d48d3984bccef2c4bec4ef1ea30a36dd65303a0ae7070b0b15c87adb90ab0486769a7adc5baaa7afbe4bbfbbcabf0b971b12458f896831739a4d053bce11bdc4406ee8122d2181f2bdf56353c09bf20de9cf329224ca1e7dc195f2e02c954936b02df5c296672a881c7cbb7314ab699708bc803ff8dab2bd27ab4cf48d1607b4accbc3465a186d5144b4a2ea6f09aa3c8312295adc9203750d710abcf3eec3161414d116458137b4e802cf8acf48c02cc79fca8de2c347d0f4930b1a874501d213c4f6915e08858ff6f404040b1cd60bcd495b44c1a9356705f6a895b2b7f4eaf4914738630400d86e68115bd9003963d7e73bda321f5f9568f6f01c15f23e8778c3e9d7cc291d1a654efaa51c82c78050ec5af6290ab263829dcd99e5cff8920120adccfb7581e051d0a8bcdd5938ee0746a8fca6e96fcf0c024d17ce1c9b045c636ade1935da46121d082a59644114978eb8d06f6d8ea410518b3a5d0fbc8766be7cf19e45f01c783c4b178bed13dde3b16789c98c780afdb125044505d00438ab5d532b9102e5de635cdf6586d1cf16643c09b71ba388158a73ed88610a8bb8e00c123cb009ea79831e8c6c9e27ab1a970d1d9e13511b4c8472d334c0563529f63e7b047a926c63296adcf028e0cd0bb6281aa4a6f0e3ac6f518e2b0dcf9cadeca01c50a1bd0ef175a0e5b56ae71c3928498596d19d0ec62c41470ffaf03df9cc195f1aad1b27e7836ac7bf1c054a441957af04174c662cd9b26e928ba5e2910ae4a5d0e0508bbfbb161ef1069444fc2e50c2a4b81624624f293ca142ccadb70fea72c39b9840468c163537c287890154f8a018c94afc04eda4c0492d90e113241090f24515c254850e8baf40eca04822a3c42292742864dcf1e9695f007c09a1987f7e15f048b8a1e7ee35beb8211a04dbb008e41e55c60a334746029494456d0f3c288993f29f1edd93cb6f0c7ea0ee4cc2216f47cb1348c7b42db525362785d10d88b6b6335385f1341719fc95d45decbbc4a8dd1bb565ac500354040c4bf9ea8244655bb70efe4ed4e7857f81fba1e7cb3563d930353f1dadc5498cd2ede28cb1abe06decab45c252c8448f401690469fc0a2335c91a1fafef283019a0bdeb336366ef97cedd9ba65065eebcc3080a6e39158d076b4045e61088e94ed3f584b631348d09fd1bdcba3c8619784e242039603e02c9a8bf5efc70aa8fc7400b5c957e5202936f73e565f4530415f94038c2187363d7be32121f6efc08a13c61e2178b3bf30eb1d2594bb07a167ded256910a506c410559c8be1f7fbb4ab3b79c69bc8463e39ed6da280b1b5477be9afb2e9c94ac604bbdc7b2cb3116daadfb784d1a21533ba4f4623935afe8337267959379c298588ae49d1c81352f65bb0815655cb85bb28455adf81b430d6eff22c80dc17ca5ad3a6ec57e699187725498022181f2ed861a7a737010ace939176e3a8e0a1871c6b913368c565d9cc0488396b5134e0b34d88601185fbeb605131d9919326c693fdae15cd6ec16002f688a4b59bb707716aa019b3a5259b43bb01487de7f688cd715541386eac208c9b48af459bc15145a7992ae90b77f00f16c5ef85cf10093e7a8e7dfe0bee2d5185431a4124b6ce1367956db4d22ad7d6d4b25e04aa471738365c4bfaac394ef3cacaac53a8e600784831beb76f3cafbdffa466440363603556eea4384b0f03e90577342514e1517106d04ea679e0a6469a8f7ea179edee9063f5abb10a0810920908d9a1a5a143ae61834085149733f0ac5d832d2dc47f0403e494a1588e89ca96ada9faa0b1ce8ab5cb5b3a613b6ab8e29edbb57c0068954cee3a84a085413b9018b61bed51db64de0503efb5fc4559ead42b53ebd11fe33aa98583b728951e71356bb64006d5dc442fb4e740afcbaa54013c6d15b97fe2688c0b7e95d6d55ad2c5fd576d37ecb229f3f315c4287af3333760c487b07dbc3304d1081f541ee125d8ab3b5b2b0099fd0f31ab1992fd618f1a118a3ff5bee9884dd901d12647aeecaccb0b5928f72726d20c0b1428a02095ee115a98495745d53efcae364e53d4db2ceae68203a1653213b3c4272b41fe679dffc33990a738d24a4f59cca1a579f1dbf40da659e4ac165a4aa95a44223d1057510235149a290f49cf61d6f10f634ccb7368fc500e39e4a5a1cb03e5ff1c05f731f9794b98476848ce94d6dfef475e75eb66d8a9629cde3f10d681c351969c64b129d2fd7f34650176767273e984145756b08b1f5b7189cbd1843c8e2f08d91b001b28c90204ba67fac1fc3e57c8309cf86aae391d1cb4546ff20d02ca7a72917f1d859cce75fa9f3587c709927b891fcd10552aaef40875249efd1ea9b5ee107b47070ec666ff843e9e4f768f54deff0c3d2e4efe8ead106f0623ad0ba78a8137a94bffefbb6fbc8ea73491f0c93c225297fa8c0be6cee1dc84ae1b24a129b6ab1b4836ec73b46fcf453baa786c5832dda23f3c9fad2cb47fb58b4651640136caa6a5863d121fd9367fbc079a78368878b6857cc83ebabad9f74a7363fb5ab74eb8b522ece28adaf5c39493c72c63d45f18fae4d664fcbaba092e9859d9faa494398c02a2652039d070ec315d2c1e4e0304789f45256f106d9ab7aea974420b4888f12d1f80cdc5d6ad24ad2d3cd031e624f3cfb44f671c48e9ee3cb488b538fd96796f3a83b4f5036326c96d9418a5ec8c98f9667e75f738da0da99ef2cbe07809403e66101def5987dabfef43595731ad6bb83282a9d306b62b5e2864e85a32bb108d2a549469b99f6d3414d63dda0c0f46afc3c90843b8afa74cad7ccdd26d06f5532558e0865e5c5a67264600e14a7294c413a75d780aa7a51e8c8718eb62febfef8f641499fd1a5db9682a7acba304fc2c74f21a3a4daa96827bd47b20fe6c846439ab7c881784fa5c8dde746d2c73829b4268fa6e4e5a8cc4a595571336d7cc659b03f36d45202acd85199181c3eb48d8edfaca2b2cb41082ed48fca7c4eb43f6688d619f6cd680fda1c182bb5554b42783f9be21b5d1a1ad07de3c3c2d38925f4ba4556458b2e3537c7a6dd0b94b579f71b1e8503c594c81e2dde500a14c561bc6147aee087be1cfcf905292744476c35d36624477087c2c112960dd21fba7f20b9b46820c34d0c83ae208a91bc0a96ba4340d73f35ad3e488abac47ef282d1021329172e9d22c405a8b71e62858bb18ac7ce17629a8d3a83567d8b6dbd45f0cfaa0fd81cf1f6434ed60da4f0a7130b46a9bd4c99fa6859265a64c1cd968761c3a80babb97df683a86147404ef1122c15f3437f138ede5d0f602ebac991e8785acb9a279059399f6e6050a363aedde20a83a361faa5ec47706d5f4917a775f6d525ec1dee9a04951db64f2acc8623a5e4e3e15a41d85175433746a2142270783af70e423cb9132bd6449cb3e5061f0cb40c58173db1366aa9434103d8a11e5ae4769223f2be2432fa1a83d55ac8c1f21dd2538a6f47eb6219f037a3289af1dd7c874bcc78d7c2754835309d3f5acf1eeee5aa5916cb6d9db48472af070d884f5e08f76ad22e94666bba7383a7ed7b136031ab1638739a958f9f0d06ab3b6513bc8d7218e0bf8ef4cef7ed32cc6b5eb74ddf8a6c2dbc8772ad8cf1ab61bc1361d6db28364a6845550f2085150437f11f010774d5191dee371b857a955ef5c00be1772186a0b27f16383f87e1f9edc3750ceda79c9135264f7e045f4d28f7a046b272ba12b887d03b771f3709e8e1c3a63756ec4028757e2371116090bc487e490e1b031c4c374315c2fc48478780218c23df9ad7a5042af967b69f8d8f211d29bdf45259d4065a9026d21e7012601e6ad92b0fa088b0b775eb2b065588bdb4b5896c0c9aacfe62c25d2176496f6519a4f55ffad94c20c4c477dd4f6959ed11c3be23972470908be52f9c0bdef44aff436f63fe8b44d8e7cf72941e406e9317318632ba48a37f78c04cd553c96fb71bc05e95b9de4d793086a6d1899d5169a0c82b918d01e4568db7b267d750566570240b4aa0d3c86e508f5548b74d26d50c2a4fdca4d3b93240cb1ea35e13b04040234b99bbbc32c88a3421d07ddf20b914cabb8373ae7ad109872ef36cf98fdef81e9461a6238ae470ae67a7214d719b52aa346b2b9e2533c7b02071dbfa1609bd05409b21c6bebd29039fa60b1d0b0365689461dd5a44dbae2e07a8c0992381de25fa7c29130118f0cb6c2c9fdb415e76fd687d0408fcececb3efc02a15a5861a9c5fcca397b50f2dd9654d1a06b8de5ad46faff15473b7323ab0a13b5b45edd16014346d8e5343ac5de9d781797e3a0a184f1fdc4c302845922927153524c31178f8a31c4da9938f36a311a66246cdf42294cafd338019d7b27bc332ea701907bbe8b140b07809e251a85c6a10d85caedfbc509162b56a72d2cab452754f346b15d2884f28add106c955a109398c3a04e510e23c25a6c704ab1d67970737cc2162afb339013815d4933854c8d63dab24a2db281314e093ab9ef19ad3428a9ebb035471d228b2c066c08741cb14eeef5f08a3f71e3c669b2cd3b9f21c81c0243bad9a0666fd502ccc9fe15dbe0057e31ea8ed68b94b92a6bf611ed8d5bb675c9929c56d13a63628f80c0c6023473590db25d315782a8a48f65423f597a63c759b0955910cbbba2315b32c85819f781c2eb747727b7d19cebcb34295b8083039acda3d27b60d30c467b3a2986531a82b549d285adc3e4379ed54b0fa598f1d983c73cc266720916c5cc63ff3dd05357e21b424347eb5a543e209fd88e022b3f2d8703212a28e7eb374e0553f1bc6f3ac74d5a0f8b4ef5b09c64a067648e9d41c3c941d4f9984ed8678ba335ca53fe0abba70c604a11b9a9cacda1decf57c4391968f4d25f9e60a0767f9f451850b85a84b07bb3f0105413092b29e2fdfb88e67197d4396542069e5fdd436c8c5b247aeaf91553fd27c652ab62c7d0f5169e0dc716e9df6fcbe60bb9d397f45f66f999cd5acfc59133b13c9a6cb412b3cfdbc05e80fe5efcc333416f249f912c0a6cc47e1f3901dcfd12c5778448a6016f5f723ae328f09d7f05da583e747c077b36f692d32f0082f0eb6cb50535783d51e116522ce395b145d98e31e2d59335d4e01fe9406f1076c40fe948cf19ec90c7d0a1fbd73409b61a8b693c420ebe0020ebb158e3872a99249f41b194a878531f7c2fbb6d27b7fc8c5a4e94368bca0aad10aa6ae2cf7227b5bc3e21f4676878ffa43eb2fc02511345cf0e8166391384da0bc3250d74d6865650ef76c243c83a2c2ddd3353c63b42ac0e2e2b60e9e367242dc404c6ee72ec8a12a62f5fb4298444b59cbcf89c2443fabc54ae244df255407ee7d348accb76b14374a632220727368559ae095489238f1d4c43a2c4750aabea39dc0ec39f5c815b27e4536f287b36633c712d44fb84a9ffda8464493501fba9250c7bad6387f31dc208bb210f76eb6a8eb263ab934805318f92c81ec5559f0f3716086bf03f48bef6566c4d02fe08b64a2e19c2027b793f2ee46ea2c8b26fe8f5324e70c05d5534ad8bca0e16fb3398ab2e7afa36cfa74d119e037b8b2b6ea3d83ef8883f62d7166d0b9ccde282ded084fbafa1bd6fe2f016e202fe7014b0a00fc79e2cedd494161b1b390d518d8595c4fb203efcb82ae2f418b45b921143cae471dec82de5b824c6c084f1aa9a507586d7631d4554dd8d1be54435926410aee4d241f5ae3aeb632592f8b33861c218a522e973014116a920ec023f05b05064eeb84fa284625f2b117b109494cdc94cb8c4dad37ed077963accaf3b628e4f71dc29ff6fc7af2d83852f9f6325017abfbc60ce8c50c9d8b90232add95015a5e52ad087c108a344c40344e9ec3fba0f6b3d13278316d4e84118bc0f26bf6bea296daf6fe279fc373a996bbd5b2ea50e2dbe5f747dac7d1e04be22068adda31636d8d054c586b9c98432f182126a78efe5a3dac46d3702410c6be5af56f5420bf6741e816335ac8d14049affe3dc2cc901d14740faa232eaa23d9a1f5b5abfa3c27a3ad5845607dcb17dd93deac0a8a8e4e72b9050a53e24a2968061015a35e6f33dad24b0f644b9a8c9e5e549dc647700b1b13476dacb8950b97257a41ea977d06afdf74839ba1469293368dd6753ecd15cf1ef637e03890df6d81ff01ba0c2872a22e427f0bd51f76df101d0fb8a978ed3df0866d0682c5ecb00b9c6931992b7aced9e4381b3003a98b8f69a91dcdf695ad7295e37dac463c3918a35c24ba2a044288e3742250c76d2e982c366546f9aecb8755717de309456fa4f7d47ed3e1d46d1ad4bab5b3c50ac0456b971c7366b01c5d9c6a9f09679aca185deb59586a154d9bb534a0b6c721ad686f314de6ba3606fbaaf59782ee2242ec3ab73a3aea4689b1de73c4b2fe7b5be10ca1474852cd552fa0aa5c356e24e3ed86ecd4725e081ec90862fa9203f3062eb99cbdbe8830e7848e8335fe6df1038973d870cf8803f5acc77baaa0b79485ccc73fae17887e3ec4fd3303685f90c8a0cf61cdee4de9d97a0350de0b3582459ec09abd9052d9e21640299d6d008f7e6e02e90bf90cca997c26b9eaed3fad57907313a3cfb97ee6b1dab6f856616b61f327c88ab6ed5bddac0b435629449bd7e103bbbf68f7fe9ab1d1c1fdcafe06713ef5c4a0c00e27e2612efa3f419bd5b714c5d0a79471b53ea1a6582105962c1b7296820ce7821226d558ab13a7b94c9c09e2662b3d0eee975a9d380e7ccd7de33096ad9a75d09d23b89a03b8c3e3f575299c6f180e16ed89bcc62714c00d17ce08b3b0f2c2b2296d2978bddd9a61491cd128c6bc91d8585636f2af6fa284d21d1eca4f71ad20c0a35900a5d6dd557ac079727d644ac4824ca1db64247bbbc67e328a2f45c876b86765ff1a15fff4c9c10c16bc23b62b0d81cba3e3e11df5aac1717fa8ef551297d6a2488458dd911c197bda3e7bf73afb943c493059dc2870b3506e8ca4da1873309357e84510a4950e456eb3bc46bc865359b9af47d24a03375c8dc0ebd01e576c08ae1f8b9ce5c6b0c7a3b9c83492ca173b54c5e958e7b1061d4cf2dc855818ecdb515c5041bafe811de76ff8153fdeacc4bd05158e111fa2500be4f3af74381fa0e13b9783120c1c58f68522fd38cc626a187b37e30c30222444aa810cc39d6dedec7cb805c900c41bbf164f999204765c2cc623775534177bd2d65decae9f886c36fd3695dfc8cdb9f89ddc9f6974d500980f645578800dbde7e2270619268fd3a64c9c6de2925e29351f780f7d46a4c71394ca7268d3602c24a1acc664afcc8af8e78c7818896bc1a25a5f1ea29acee1a1c1d557b9ba880c3745bffe9f50bd83e4a873518ed1e5366406b7a3cce4a86f99729b36ca5419d7bc73662dae25ddee613fea62ca65cfcceaec47f919df2ac0d4100b4a958d64860d8b2f2d018d72e52691ca4c7891ae44b37fcc6f2536bf3582f8c0b4b56dad97a1026d5b4320086fcd6487cbef14ba61a9192a99a5189987b81d9997ba6e742178a438048e15b6f755bc390b1c8ff7a86ed58e813c59f9ead4887438dc5031ab68b7f16b6444ceeaad22ca5bf58aa0ee60deafd3770ef8527fece159caea8fb59a9e2c26668b40d6e6a1c390b0400693835ec85ab6624a8e54e5eecffb124d74806f48e009ef804e2cc77b3c2ab07795cab75ddc284b05566cd37bd159ca6fd24d7009a1386ee1e0e72d17a9bda593f3421a83dcd0e82c4fb758aacbfed7a09e75073142f91f00d42974f2ca9a71c8a45d73abd70ce2f5c951358b788ef95b23fda906ad106b4294df44b5083801f8e884800f904e7b28f31e788e92c8ca3267280d7d397fa0743646c4267e10066e9d907085a0469ef3036ec3e78d7dde5ab6d325f1203aed490a4c3402233176065be3b7a780e9d09c36b5d7af9d1d78cbea6396fca53f1d6e0bc2895baf2994f9d0c36eb7781e2e08bf7b866d91f0c64be1cefca89bebbbde969bee35f6d5ddadf4f0e520d280bbd87e4581435d516d6c862a61d44611d4161e884ed4461701c8adbab5cd134aad71622bdeb3dbc9ad4d92f7478440a9b0bfdd7c43ac4c0b15bca88471a488f1590edf8883b446609173fd9086dbb7104b6f1a334ea1f92df256bb41144519e8cef4352780dae1f46d74e6972cc1df09e1cc948f730a9906ae0bd206ac398d946199c391d528de553281ee34a53b05d5be8fd4fb0ee14e516d09664d47819130d7832f159d7daba3151a7d7e11a09f78d2ba46dd8c461ddc480566a0ac5403c85f5502dd5b1a9342d20ae9fd056766404145b0463fd959468f10e542315b383340b8bd65bd8096a83dbf0dc7a98cac12b35ac921b3ca197621915be8b7ff768dffeb79d0411217a81dbb7d26c055c6a7cacde22a128eb516f22826a5fe5823800dde5317d55df2842c8c03b0b5e13b3280a37bc6f24e140d16c40cc7a2b04ecfb9b253f6adf3d884aca5f02a247e26b084c9e3d457520f0158d6939aa8c305d4426bcb73d266d4b385daebb42df2d48c29016ba3fa390d1285101293a0500630118e5e0a1d04576ba9af65265d53ebb841394fb5e76f292eeca6ea9cc1566d7410ed4c40c82dbdbc4076f5f8148818f969660df7d2c2d7332abbf98d35290a054d74cf243eafc5ca519e00f82a09bc786d01b9c4882fd24ba335b847dff3ef3ad7422be7ff909215b0b420cf84a779e13107c223d36120895b35416368a1bab5d452fa35a42180d75c6a47d50ae3626109a45d8ff8e412c4c49a31669f95134ae2b47f7afd5365f76f1c0efba30bdf001872ca41bca55f8f8ffbc778afc7e080a8c13bde0d8fd64fba23c63e36d8b2585c668151d8358703081293c07605488956c02b6b43cd0851d22f0b6c50c2ac1437e121c5758ec383f522b8469faf1eb93b32c9140e49abe90f362ab35317ee571df07e95dcf7f2d53771530a4d3d88782cbf4a2829cee498ee5634b4d8d36c4eee76528c79ad99086cc8eac369b60506a1aa26f0a588f709657d4eea10d08b06213bcd55d9089876c78c2182241e819bfba1555450a86abec05f26fcfc712bba3f4669824fc82ad4a0a30ed6925e4c908b7d4d103ed2a532034d563085a3c0a37b31f78deef7629d430cd6c5d383a2e87240136e20906f7cd5baba35314156c402dad8f19cc7844e0652b05e575d7e97752a90a2ec00cbeae36139261250627a9d99a140e6149534c6ad68e7b06f70e442d9997aaadf28ccfc9e42405979e1b6801357b3d160b8088ea1bac351ea8d0e2efc17bb6406573370e0017ddb233424148f5b65e790b83abe90ef101b5d56876fe3c1a8b8decc330baaeacececd2d65758023d9958e9d966eb456d707e40382aafefe8ca71dcecf4ea2ee088f9fe606dc96399ceb8cfbd7a701d703021611371a8eda79fafa8d4419c062667ee6578b4bc98f1143f5b97e53196ef4d389a23884bce6cc331f0feb32ff9150f94adb5a3a2bd0831e811c492963cfe41de6b1f080e2235a0b87b448acc93d46f4a98620333ac6edac2906a9e6a078c6cde340e4f15127cf53497d0154f388772f2491bd0a7a0587a7ab17d48ac2c10ef1130ba2107e046e8be30c2d7df219d254b9896867d3c76774787e26572a6050d6dd8ebfe8dc4c37e5b7ce2b31f01c317e784936f7097c85863e50d0562e71d4ad9671f9510cb2dee75852961c98f2fb3d9d8561f1d85e9b7adbcde8b30c967210b66dedb69b0bcb9e15c92aba76b85b64383c64f399a2bb3a5253cf871b53ebfbbccc597aeeec0c0c1144b2054b41245141cb243ca73d029b213b15d4a569a766462310f7fd78528e79995802902ceeae968b38a5f00440864d17ba3810cf365de00674a5e620b073596038adc27eb96901cda40c7314f63fd77587fa447249b1da6347c43a4a2b1e289037565c4a6c64fc6d0996701630423e65558395f210d79582227c16ee47b0a25a4bd3a7db3a272dd8a429132cc1c5bc4eec5c2bfbf01e06b744824c01db2041652c94b6b6f57353ee4ec01cde38b8b5db90e00b54269a70efabf482b73d365466bbb911a76cbfc0f50538087249f75009e6e194d4e439029c65f80820cca65bfdb0d3c543a62fa0d044e275001a206b6077c146e7e1c0f18944cc4addb1ee1146012094b2f3900cfb7693dc13a13176694c63310d7a035fd0433e266a12fb2ab3290178652b32b3f0ee4e032eff50b08ad1d59b1330f1cb744915f92edeb6cc39c335e77a66b21ebe4531145b31b46e1361147468fc3b44193bc570af9ce4ac09e320ee92b25da1285f935327c0c68e47615a08a5ae62db99ffe590b499ea0af9710c2f67c651c4a49b4934ed8c1fb9fb3a42da34d85bac2c09dac894e50d7c2b5d2646a6a54a5dca55926e0da11b6899dde9fa2658706316ada5ce3e4b85c61359d02165c78e334429a23f2de91ce3b4626009023205ceb1d50ae13eb055a2b182fede06252e605baa17f8cc0a26ca187189c017e0577e48cf509c1cf1a3924302070811bdf674ee67305f8f248024dd61a026a14c1249d533298220b9be36900780328e756d8c68a542b1f6290b78887c6b35064de967dbc126d7b690aceff137af2c59a411ae822c4a94a1a0181b29b629da52737128651c7e8ca528c83f0a04274505337b5e28b32cddddcb1a3634f8f6774464b7305d4dda73d50a1c035c70d8ff82b408624b9e8e1352432815eb206dc35962fe946b1128fb69622aca0231ab4e801516f64825a4d1f27a3a6ffa56750f589c24ba1834a4588b47f0261489c0918e7e32d68f990fc62b9db92706e195b5c6d9e10b6d61797c66ede1cee8c938a44f018b3cd031689f15914c83063fca831086fbc414e9d07bad8e2e83e8247075c7f5df0e090c44a0f8e54f06626275382d22d91f9e9088bea8761bb3971137e3bd0e5595f0f97dc01383bda30a7174a6c6011dcc36750178da7fa78e911f9556218a653acb99c1286ab1b060baebef0a1d108e8c022ccaee5c131af6cbf7f12c53c7e4f1fb4d84dcfb2f1f0b8f3478adee60c95899b8246ff66b1d106685e1f6f06fc1ca8b22afe280004dd20ca3284f9c88bff325a6334a0f8850732953896008683b41615c3fb32857feec858c69eafed4944d458608d5e469b55d431b3d7095c50447f5ea14823b2ea66afeb828dbc6a78d2e260eb8ce652a87ec5158334f13769affc29168ae4a55426a812c4819ae0e80499d399115b5c06bac525c6525eee3770df2b59ea647d2940bd88d3b098c7f299e7ad931099c3f8d14f730d1f43bcf0fe7f9d38df46e877651d57437702046c8354b0fb7b46537c0d30f1f77b913c69b03e2aa89b54165cacd8d9e45e1ef55f656339cf0b019088fc3ba73a0c8af31db85c46d25ee1ab245623a976a1cd3ae0a9d01fab040eb5d8e5995e8aa99d1887fd47a9e88ae6ba9af7dd796144111be04650389c89006f82fce479bea73e6e6f9fba115eb1e8f402f2ac1b51cd2faa47abf0205130e228777969a4fc0f01741bddc27f728d9af3b858ed8458838f0c64ecfbc5140f248529b5a3f1c0a052f2e328c585750361da0b8134ea5607a991ec88bda9770c46f8d6ae440e5c89a88e78e05b89e1756a109cde1ac59150ae150c52b5571a8ed759f1e6387fcac6bf92563667a885ed4085d8fa43d50fd524960ec1eea49b7a1c11a0f06c5b50c360f1daee1f078a74431f64c1ff3b444be21c4aca92d88315d936f3b06dc37ca89526cde13194445717b02998ce76fd62c3478dc8b0b38208614adcfef4509a43a12e52006889aaa5ee009328f2867a9ff459a1b4408eec256757f0de1878e1f62bcf546948186c2dfabfe1e001c9253503a2f62336112d6207a0de1c578e7f53586e42fb6c85a2320bb79db51fe4fc31e2282ecf5affba4fd8b6cb48d9ef8c7f4b72c87be045c4446b4ff3e718844a1abdef9bcac8a16cfe826952fe5aa6885040d2745688417203d0c8912b9ff762e8dea1e44c1729fc9294eb29f96fa9cd677c8a35b830f6c878efd80638196e1955440b4be7bac4154ec875e7c53f4d6b8b67599cdbb95056c59e8ccafe90244552c2ff6d6e65bc54f019c30b161ded69694e7a0fa22181d57a561474ed66d664d2db219f33536928323694e0f6a61c366d301699c3f6da6fe51cf6ad47eb54b71d41fd1c0a1d3997006e6aee54a3238e5bdb71b5659c7d0ee19fa08fe6ab554b2f57211ecdc78ac62ea7312153dfecb615af96843e6d3a0aa1165c19cf81c84fb4cb9ad78ba52c40be28c714199871232b31e4df42f3b532a207e36b234a46b169ae7da855f0cf71a766214cd0b83a669b354d021b3266a40d665166733d90a4205ca8e208b410d6de31a1d1388823f40a2c177f0c854f4914e3e430e2bd1e722336186a2162e41a15ce92f4185430e8d4181bd4267588b740ee47f6bd300795e206f5ac6cf0be58bc082d54913e300d1d19aaf5d3504c9d103d8d021d15379753a40e8fbdba5fecb8ee9310d21ddc55c5037ac15b3b3d913863086944695edc5f6256f50d3acd8f0060a4cf541ad2dfed806a75c45e4a2680d23b3dc55e0f9eab9f5753ec096736122c3b291a28aedd358544e0caa0b71132de2ef1402d7c0c47c4488805f309ac4b8d83bb28282ec75b1201bf091c0af5461a5028889004d0c03fa3bc5074c73c459ba8e7c7ff13bf9d4257cba0c5898676bd86991e156298df5239983e0e11b8ab85a2f50d6b3bd71744232654380d35bbb92e5d8cc6a479656f75e008457007d64ee1ee04d297f65a4cefd2f073e0e31fe22023769947d0e4e86735eac822f5447305624f292363e015d8cc46e852fc5568055abbb785bd1a0174ffee39da21dee2499abd4ab1f2ab7174136ecf209fc4ab6d0b06fdb4c8dee428ebcb52eb8f8466a830aee80a139c540b2ed01acb6309c78209483bbeea703e65afbe2159605b81ae63e815a95e6b3ef91e9a79990687b1016e382e188164307a698ef11869bcdca6378153a65a65792979cc959873d6b3de72296f8a63bb9a7e3b5aca34e072d257f63f00e72017523198634017283379629d0a296ff8fcb964edd00f32b69bdb00c6e80e3b874d91f2702c0e40b5766aae8f08c399a00295006b0ccca82961c0a7176b19088fcefe4d232cd33f288dadd9d6608901d0c04271c48ceae3f7c1e9993a62e1f8e8b4a7bb8427bacb5ec3c1f2bd7d19b42cdaab0bd4e47fa1ff907f8319d0086449d28facc9a1026028698ebaa94aff30e95fdc3d4c45c79e712b17ab3f2e954fdb8d09d2958d84eabc470e88452c8befed1d2083adc1fb086cf568ed9ad1bcfe253143f47cc1a59128040cb9bc6882e7493e563dd51326c1a064b244e56b81cab6171c55ae1e05fcdde460acb830de6104c7c855063a9cf43ee5835ba419455a8a1ee982d1dbfa0268ad956a49a4158e08d4685032e81de8c4559961610a44cf10eed1ca7f3687662c51481a3cb3b409036d9aca56092fe92aca74f8bc55131d35967c65ebc96c7a392cb0ac23256f0ab728c8552deca3c96e083ae0397360b84e11f9c41d81eeb4e43ecf689e133f890d2181c20d599f169c2e8f2e09f3631aa2106c9669c361162c8a81510c38b2986b69e5e2e9d1704d96316dac7c28b2aafb7ee685d89e8d7e176693acb3a57593c6c36d862c2a2a30f8c8ef17d09dadd06acf70191c6501999f444ea3b80bbad10e7ef3c26646142151779e955593cb8bc645b108bd4c93ddcf1e1f5ebf1dfe4f199a0ebac7e51291a7d6717644325816c802f57726bae2e461ce56ce830c7316d957fbf553433870c0fb14430cec2424364c411fcceefeaba45fdd4cdfc8fca710137e6ae4661e3e247c0f972ff7e8fc4762fadd8184bb95b313024ebd9de63ae2b3a0e2c1dd6fcba3080de64512d664c5cfcc93fa1c120ab70455eb276915978d954243933b0810af9f37493211a2449005771aba1f0b11050fe9b2d6624a144cbcc868e59fb8938afed914fb5a28e3d85b57b9e7199d32e63a6d57808c9762e651a8672fe4788a959669c0ad40af0419ceb4290941ba027fbd2043f99be8c581d17c4f7d6f65aa89b059fcbcfb978f315ed1c4146131cffabbcae41d10506cb4f56f4d2366999d690b36891866418e13a5d7151eb7c1d7bd4413e51edcdd180886bc6939aa37bde79ac8a53479de99a762754efe6ec680f9a6c9ee91a3054661c4a727e6386ee477f99e26c160f8d1cc0ff4183db7040a187d9ed0e77f3939a92dc4c7c78c9ed1bd12d8adf8eb9cc9d567806d4cf3f51f1ca742017850bca1de7bd2ccee060860c2c770cf0c0f50122e99c698e45c04c41fa264b12dd0b22e02f25f05ee978c175414dc5422785af196f7185e67fc897a45b64c12761f16ceb6e3909807ff171b8c3d91941ba1b608bd334033f83245a3ed408ba9de6f739f669120febf9503dc0b8edc5700547e292b4c04eaaaea4059325af13b2153712c8e60ca7defbab3950035aff022b095c550cffd08c503f501557f72630036b75112cf07d40c3d819986103057281e00f756672098f5c0a804a3c891d97257dbd8398bcabf9d82bb05dab00a5cc7fbe95fd5b48d5752955935ee9c32edb2966328b0a5444f9d80b6f94892de544374b8863ceb8ef3143b17eedccccda82d531e1fc6b41aa530713b8fe5ff826ee41367b468b0a21c4009f873be25f755367c958167fdc0a4a2347150377ea3b73c69a16b24cd4c8ef6302979e55e55c3a35cc0026121d805c155a68e6aa17fe5671a0750428e416b686ee7490793fe9a1ad74d8cb613893156543f942025ce448bd8866cee44155763191c4b24a25ae9879629b32d735bfe5f7f292346cb09238e11132d4488d145903e6d021c3b226b601fd944d12310e4318f70e0ba731e7752f0bb8239881382bd074664bee02009dfa7b3c49848ce071539693f71b256b49228b912bee6d9f6264a258ad89daded00863084c30de4d393bcb49d284954434da48fe8e9c02935b391f70b424caa4d002c7defce593d5b4e5b0ea1f44579c8a95c2acdf031e43c9f657a6e9e77e6e9e4b0d9568aa8262e076acf5ccd76e0f6f33cabb792807df3800743ee545be550a16ac2345be5deb92288632506f0e9feca75d98478fa0a2073265fb0b4900290cb991947f46edc158712751effd1a48721c8573b849dc6e3bfe6d8e6979c9046c3c3689eaa81ebf101c41c36f945f8719e3b737c006232f8d8c8e52d9a8f1d8f6066d81685cff8461ca6fcf4da700af61928f3a578013a0e05e6ae112ff243bf19adc734262b9ac5493efdc400cb1aa2ba53a2ff488b618066ffcded4311b1ca111ce0d23be27ee83c79c08896d62f81e2760d0cbad8652d00b47af7fedcfa0d64f09ec3f26adaf5f9243c474ff78bf78043f3e4f200c705d61809eebcae4dfb90ce6ab5439df02b5494d6925bc083c6cff0ee154566676bcc1439b9dacf630a1b618bbfeb93126928a035d8bc483dedf91d59afa90bd49a934880e8d529caffff6930a40925a82b0e7e7a3d70ccd2757685e4cfade8ab2c48f22dae327a1eb7ed683491f8d99b60720f38980e9518f0a6df6fc2b645910f1e0ae9f0eb4261e3da68a0dc5d65e9b1a2ae8de4c15fafd9ed221866728a2ee9cc4bcd9ef8a689306aad0339004727c8c09f245208611e6138b8ffab3abe60699fc6259cf4c48f83ee2699ff2f858602a72dada4ede293a55a497eb9ec9b25c1c322b46d5dfc34aa4f0b57a861e859d031b533c2d4cd921884aba562ef3a38b10543d8c88dca1d0898975d52bd1a56577739cb7daaf41a3c0f3289e12732f1d23e029f62ed4718ced2dbc4b6b7828e818a0c6944737c094d8f900a113eb9898ecca085298128bcd8b282ba8862eba6df9ec8cab1ebfb5a2028ae056c5cc102408d5496a7bf0e80bf70f9e0040b10642f51b30a75327a4ec897e48727f96e356d62f41fa58111810286ccf4e919583f8d3b7cef621bd6ebd74cadc8b000b01bb286021164a9bb6686af684031f9468ac3f8c661397ef327ad54a5c53e775d0036ca75b50c7da2d9f30fc00597993d81552cf03b34941664f48dedf350351d78c0383e3d645073b07e07c6dfb69ce645b66c67c06fa2c94d89fdf53d10ab304074c897c92348a9ab829d0a64be5d7cb2aabbdec4e64950dbb4f3014631339eb539edba4b4aea354e2424d7458eb1a962ca9140d5c404e38ba882e90ebfb56887bbc120fdbf4fa11a0c8f59c0311cb9a6743c3bb7c634007dd85fde58a15bbf7621a25472b49ae506bcb5b13b9f2287388af4e66ea6479885c04cbd429252f37dab80ae8941961872d62bb342615be6216b35b0f8bfbe9a26374b5c6c9843a88624d8cd1072a11092cd23dbcbc4732fa6b62bc8a29c0b998547a513c39ca282a7d92881ebe572318fd36ca53393d10013f4f718bafad0811fd1d55076c1a80e8584da1d492b0ef7ac4d47111b865a2d9139e0db78352ed5c58af8cd1973c74bb8bc2b3e4cc342bbcd07329e1b15ff1e3f7a3679c4ea1b5600eb1262cdee396c1881d93ed61a13a9b5d8461fe5c6919960d486d04e68e2a2243854b58a23e051d7c97c9bd42349825c136142620a64bdacd7532b1177e936dd7ca7cd01ac9ecbed38f38a6c0099d9bf6ef9658185e363828a021c11f8ecbd035054c25105206cd3523f7e85e1ed10365a0656485a68c81fa5571ae0ebfb1d5a1a2e06079f616470f4739486a0d810ed72034f38eb28879402e66cebac618225dbf1397775f48548f2e5c6a1bd7daf5c7c38c3915b01d3f1c333b052cfbe129557dab1fc555a0796c6fd3d4505e5aa2399e2cdb96a89755ae68d26ff94f7863a225a24686f88268b5628e976e7b3e5bd6535f99ab975196dca881382cabf245a98c210291839f04efbbf9fd514c3d52333e0a20536d160916f6096cb89d8d8f88ccd9dfd469f1e9c54d5f8a26127dc9441355605050bc062036ff358795a69d963630a456ccc8154409f89f7069f54a070256a984d60370d1e655e300745edc34f26bb5201e87ec5e13eeeaddebb88d606b6a51d9033a860599085c6d0a19ff01c442ee2492646dc5b093d98919de4fe59e4dbb47bd89ed30d39268b12b39eda6b87a3580ae57aadc70c46451f816ef0f297bd374f002300e637dc95ad13c781d407070413bc73b6ad97179f6ded2a19173e21c6caa283640302036fff5090a344beed50f5195e93b64d0ecae631dddbcd2f1e322c03e074c9667d30dd8383a1daf03502ca58be80abab6ec56c64b3fa788916d7160badabd94e80e882a3078050a4d4a02c7d2a3151baed265b35a0b1e16ecd24c837510a9f50ced50cb88948e651c5940f00d5d5e53e0e5f541133ef0f672747941364838012eaf7c31d4613e552fbbe5457d01fa2e04560874b8818704d42cf9825dbd829debc776979534fb7170bd949f975d0d535731fc0008fcd10082abb93523f62eec44cdde4d99bfce445275d5c06687d4279f1b1bc2c1159f8923d11428994f53249f20606f2848c3d91a6ce9373347e8ae558c21b45f726d4993cc01690c0aa04e008dcf3ad4e2c2163389d407da0569861488ac5f27ca268f38730e27b1552c30d48e78af983853b73f231ccec9b20f15af1e3ff58d3af78680793e20447a6e45790bfcbe9cab599e4db5f9a1d142825485528641402f260983a86c3eb207ff48c025d81a419f7d3b00635d104ac709d79c75822b006742dcda914a02db077124a83709e6514b36e6f13a5f6478c4381f28a15c3454acfedb6e30932e560bae883278055d45c19bd6474088816ece1c9bd7ae305f50f0e4746be6b125dcbe177a7d5b609107fe8798daab5595d448e6066c74b168d6c0dcc39dd8cfcc860cd8cf12e52015aa327f8048a2ce50ef41c95df6c133189d01b9d7776a382eddccf5e078fe24e407149f870ca257769365519e22fefa49e8a1d32246865095428e28fd028660158dd7280ea100fd89261c4db7dcf818a812e3a24bb4f6d6c094a69a52944684a87ad91b016d9264a763ff833106abb9831e94e9eafa1b45178cc73fa4b09261c3abb417aff5e6370e4e74dd683f8790eb0fa8f787a076281b41cfd4ca8c03079a748bab1ead7ec9db5023e461e223d08d71b1a5d665269b3cb2b104a51a42e9fe88898db846ae5174e721086eebcc8c80e380910115d543535d756dfc2b8b499041984af4c446f136f20334d005b3aa896223cf04b314ed7ed0a84574b711601bc8a2f665046c744d1bedb7db59a6290293eb4b2728a81f092a3abeaa51548db3a140e0d666af93bf37a3c06937ae19e40321aa51d0937246a3b44a7c97dd916ad4982a20817b845ab4e93a0cbdaad19aba2903a6b7a10084204971fe5cad1700c5caf88e30ac9a31278392ef6834b5c82009a398b1bbb553c62024616fc62c20468988b8c1e2755a17732b16a54e2169bc1bcd820dd4dc135123e4114050c617dd416b83081a11208f7f0cc8a99deabbe7e460aa96c188976194a29b783d0dfeb47444e7d541c4ebadf9fc6d295edb274d09d9483f20b76e7cc13ca51a50a7a7720b38393165c79c1021292a360cef0a3fe3265d89b8008751452a0006758fa61ece35f8c468701b75444300bf4221780d3da787fbfb6278ad6fd09d8a3122c03d99bf5105d350c9be32fcdb693ad6ece0ee8cb43a2428777a50f7f144c11a2d9901533119ac7de81b3e77bd5974fd0e480537e35a0e22535faebaad439eb71b2b8b9d6588cb448fb7a516d37aa3bac1459429aa22e509152c8bc2328064bad70a98ece2f85c76ec5d2d409546d193805f112a6621c72a0dfc2548212378764a24edde3a1a0fe354ed7f3b6756e5579f181206cffaf61e0994885528f794543396adb125e11eb30db50de6385e1cb6000c76ed5c395bcd76eb8f6f957fd1af83879a5084e6942d55d53244945249daf37d91ffa6f798e3b6d8233360cf35e36603117f040ac66ea2f346b6c161ec07f2eaa7cab24e49aa1fe870cdff3f826da1c5dcb088eddb266afc2582538a704496b62d90bfccd0955527158134cd86d603768fa6950ff328a88850712ab8685c350d1eef9b6ad4ac2bd183d7ecbc05bb6944a46b6384430736a65b279c1519031f47adebdbf439d7d87803a2c406b2ef744272ac46d42fe444f5fd9f95f28aa359385f782450c20e955df989f2d8c0f53de3c8dc33e88ecc4befd55bd99b4f1c944be1014aaf1786a54d2d0937569bf9101af6b2fe848367073ba1441be5242533343b7adfd87538105da0e28228905f9284237de07318eba50aefc557121fc49643595045e4528833f9d5dce091cb6959718ec4c3b350aac1a272a6f5f7ea5b6db0b53ebedfc41e4dcb4d2aca841e28e4211bd617cdf74736bc3454b6b47798e80c98df1eb1aca2af5d553962bc8905cfa5c576edf9e5fa42dbd5639867b7bd08dfbadbee3c2c4826bea23920fa81d50989ce9238104eed0c048c6a095bac48387a8a88ce1235f2b74988a0781da5d8b086427be3fe0f8a826c2f3b9e3ed1c6893a3335bab5b0f2a3dfc3520b38988ce324c8c4e42600972f18d26c4a6a12f45a0518a439826e60a09114d2404722acaba86f3fc9fccde76c8eaa09ace4f50418cee21b4f8d4ace7deac9ee7a397c9336e701ea54004c18705c7ea1cca774b95be5d1acd5676207f10c8a219d98b03861e5091a83881cae00ea4037bcf1db741c764c011a2067479c8dbdefb62a38a4887a98628ba1da33f4fbad61bbf49b1c73dd66e3b78678a3f51a3431747a5e38b6db8dbeb2dfbb9f7429fa7ec2e9ca5da87c12cebe6847a37e07fd7aea404383a7177f85e4247ccae35cb4e8dbbfe7c17daf18e4c6455ddfbdf6bcbd22dc05ba0d3dc00326d0ffd72c7c3a00903a24748abd632a648a529304b3cbbd3adc34eea54cd0e81e39d863f69c6053146b7fb64256bb31b6cb11da60eda2a2206c9b1d3ee62643daa654d743d41c4445f652631b037472022aa001555f40103a520749337a2ff74c9eb17c5fd538234b5d7f94b0aeab24a8194f51eb0b914295d6a0661834b85a30fb5282dac12026a46c81ce0077c299cb62cca54decfbc115a33efa5a89c860da1f697b9e45a2f69b07e511d94df6de52a694640a2c05fe043705d3a548fdffff7006334c30816a41959672ce7108342d42087265195c8910028d09593896fbf7301668ab9d8be511b3425705bdd0ff0fed38c1554e432bb5f5411fe4ac2ef46edb966d97c1c2732fe590cc02c73949509dda133a87b33ea8ebfa9182ba1c246efca01dd07e2f8abf64fca117fa3f09a9adffa0eb6e7f4bd7b4fee81e750db530d7836055d023008604a798850058145671dc78811cf76d0e677d4f685d5c0682c1aedbefe9b8b1a7a784c28dcb4cd3a30c0664a0059b057eabecbceff597c3cf4f952a8cb2e99c65c50602dff4c018a4e3851b56d85812c314214364c780af98e224091f3220aa62053b4f86a080e8c847902a349c7904edc8fc232fcc716bf031b44344e767884d2b05432263004ba2fa61f244143ad0600620a0244549b4c072b0e1c36b494d1180978e12ae08c1a8b2654e0413dae658e52073285ac827a90cd163d32dba60e3a20b369f3bf1893d94144c1f2170a88f0e3823707033d4812efe91d8cd4322a7062f12d00caeaf881bc8a4acc7e622ab1ccdc0975e0283adf402baf88110b358055d9437f88090cca6450904119b8f0592a31268b5296c3e174f8ac0812182899e17516043309a184216e3082747b030e6c3188eb1026ba266f3c9907142e665c8b08c8c1334b8a049cce68bc931c5e898d884237f6e301e9b4f0674b1451939b28d49069b8fbf19d2ca9478d07106cf90eed26ae1ce1703a92048cce633812e4a23a288c166d3a20c6283cd37430632e0f10074513a81a246037491067144cfc79fd835bc00064734c655139b17e58f1c7864f624458711f088281d45aaf0c85ce35703e492b42cd8b428b380b6f95e74c1668a2ed8c860f3221fe192c1cb864b9ced2ec749ce85d895626bf2dc5389071df9348a96c61896c06f1cc771bed768c92b9797296220b369d154021b17ba856f1817d8808418d12bede7a05f069ae104ffdd820e9c89fd7f4e4a39aeeb3cef0a89c4f37d2058faff77e9b8ffff7ffb55d03e51a7adf36dc88205c7712dfe398e724fffe9ff3f0ccc8b1730beed93649c2c15f97eb64d9cd384ea145857785b61e6093d671782b5eba8d7cdd925145ca4401bdd1e3d4a173c396128d3952bd6e7b5b54d9f63e67c744a01dd6839497a2aed9452be9ddd3b9ffdbc446fa860074a51fa90ae5b8591b9aaac02e00baaa95333b3da629902c250f6773bdf17b303496d71da8ff6a0e30a7f7fec412df7b747bb8f2bfced41d93aa5f2d9b6387b4cfb9c5de1dd4e3af670abc2b4d44af719504a291dd2dddd34d8092484e8dacb40428e70b1b3eb17915bd5b988dc2aea593ab640fbb6649f64bfee1320a78c0a9e3dc14b25913db0fba6fd1f7972d3722329013d56f8eb8d322a4caee3c49ae4fb627620a92d3bf61819013ef698d6ed1c7bf4f011ecd46a862a4729e4e38f4116ed0b10555a3ae79c7352cbb99d28b0e52cb52fb29da25bb72d8e45ce999dc1f620cccccf2477676667d18aef5f7e3584093bf5bf82a7563faa5b27b9d862e196c6cf798ed3aed0d76d277222d8bdcdf7f031aa822c655326206f1ec9b668749be443f7b32d6fb7c5020ca480bcdd6f6cb5f0baa4b1c7db1ed472ad1fa9e93a08829641b16bd15d5c25a9a06dd502c08c61a7ea25594bf2c6aeb3f91cb8fb689fa8ee7588b7ee62c7e3e7a4942bf1e0ba0e7c0f7c91db2d898769fc7bf14b3c3caca5ce1d76fd4e9c97177f77b79f14755aeaeeef3ee79cd4dffddd7ddabed3dffddddfdd8693649feb93b21be4e1de318d8fe0d675573f29e5e6a44fbb0761f76d3761606a3834278fc9145a9be738f739702caa933b35168d45b5d5dd07ed58645d9c008ddd19449f6406c00dee2f2c615247d61c088c9d72bc8953974ff0e6b64c93631e16f76aeebd3c9977d32c50c7ab51596d04615e0da67acc7b81b5182a4c85e95477e5efa1529d368a63d4aab6738b8f20f48673d861f306e3d76d392cbcf376e2a17e15137853f4a86b9e8775388b0a0911111515a53c968a5197c7fe69cc7178ddb62c9aee777fdc9677db5f77c85fde8b039ee542f9c3e49475308bf2aa3b57558f4f39b583dc964972d679e894568137156cbba559de4dabda0a09111115155199f3c8788ede8b36a1317726cda253a80c46563d99c77628b3bbbbbfe9beed2167f7d1aab6418afcc6c8e8b656dc5a05b96c63e4e8ae15f3c3b4aadf7dd6790cc9c7a816cb4cfff4f2c80c4565f14dd7533766c41c9da2717d5c75aaede98a7555e8aa192bee819626095351564a79830e999e2a65dcce59e1c949953606078333752f505606067c1aa24a7b12e2d4a44a7b0aa2049e4a50a53d91a04acba75895f634822aed4904a453083ad39d999d9854694f40c4004f20a8123cfd50e589a74a7b3af950a53d2da93366988e440712b343893f8e9d2aedbb8b6978ce69278c7f7b825569df7e8ceb930867a594524a29a594524af99cff4ff13f34d3c0b8df75524a2b6827f818d5026b0e84756069562864895245dcbde5b6dcc7f5b1baedba5ac3b0959a45b72d8e7b8ebb9552ca59d42c0ab375cdb43c463d3e2e95d12074466f688de604398ef8e2d22067791e0f0fcc59df9656b5f5c1132476d39323bb3acdc4e7f81df154695b1e8f6409e37ad7ba2606156a5509596acbf3783c26cdf21cc7a9a276ad6bc27730a6836ffff79e6982ddddf97fa6099e2b8963674ee7e114a9c65dfa0cce69a79d76064bcfb792bb3fb295737c87e1b9cee3ba1678f2c6b9a4bc55c0eb3620b9e9799e970a9708e5c81fc3ac87fa29013b81002c7bca752c1b9a22c8d6292afe0f56dd10e42c9fbd6b0aae79186641ff836aa1366016c9457a915c540724d71592abbbd9e1b6fd5793c0ee3367713ff8067ac5ed1bdeba5a1c90fb409c458f66a547b473750dbd75ea3bfb37f0ff6056aa5b5925ec8ff4c63492bb9d08a4b3e146da4adcfca6593e731ba433c4c4d6e4e67334e55def7216bdb9aa2dbd7d4675470e2a3966cef2a6b4aaad152c41424344b6a29bd111bdbd4b86030437c9ed426ff4c63a4830128fec9cdaca715f1c750d0cea01e91a0a05a77ae6aaa6419d6a2dac6a4b12fd0ac6d196ce3ca86bfcd6140aae711b70aa9dce5c0bf7e3320703b3e810bddda61c0db7ad9778d0a14eb5a5efe36320811bc25774372ec96d5bebe880eb5f52c1fa91935a5060de4819a00ffaad6b9a5b1db8f3fd0a667db6ad6b61562a0c39173af6fd69e5fd44209d0d69ec3e48b35ce640bc87754c3bbba9e504b90e13b735f1db8beb376771edb7dbae113ad576257396273423aa157946b7adb78573f9e8d5967053925ca4253e4681dfbfb74c91fa5f3339b9ea1a0ac8a1dba3b20dcbaa564f8c07d6cd6f8170061586235fae1281194808ee4d735bcccceccccceeeeee37d89d4170ff80aa386666073244aa7b75cccc0e64081bdd8b449259af505469e7cc7c0dd5409d666a3594a9531ce8d3dddd5d426a7ff25017ddfb8620a44a16df29eb1ed2804638030f98dd458b1930964db725c3fc029c31b7e5eeee73860919cc3142f7903946864c8c3bccac35653155aabc31556a8f8b49396ef2d0f08085a55199ffe58aeeeefe2f978a033233bf8852a5fd92bb7f2770520aa23e926703ec263755eedc29ae9269dc1d8493900ffa03366aa4c2b80c54e4ca6d851c14f5c565a02244dc16cb389d5aba0c54e45b02ba4650c244052428a2e449141d44143a3050b103262c883d15b513d8fbf95cd71d5152848d072d4e847c04e004162388f8c08b49139b2943cce0460054a4c80744e4a8080dd72f03150112d6c0fbddfd03feffeeefef333566e6999a64d7e7de726f7e99596ea4a8a44658515999422a21ca52b16047a583a954eaf30098a6ed000660c36c369bcdc250cec974b28efc117674ca1d65ed8d54cae74b5a08ca3b994e3a3d8927bbe69cfe9ccf4c9db9d9dddd3d6666a64382823a45e47bff4fc16ac75c9fd3ff1f94ff11b8ffa4fa3333f37b833876fce9e49ea02f38e64eba0ce6628689c9f1b4e0ba8fc402fcc09fb0cb5f4b964f3db8944a3cd8babb3f8f0bc5b9a71eaab4b3e4ee140c71ecb068e102e60507c1c0b1e313c78ebfff0c13a71354699f99993d4646cb788c34b1e02798cbb89f9038e184b4d5f07ddc124bf763979225d317579cd759f024555af7efb6925d46858fc0ed96ed62fbdfeeccdd4fcafd7f77b7e4cc952bcc5c6b8c18210768133464769eb9c2b6fd9464e68a7c66a6cfccccedcc5c7960409917304c251e0f83c3072ea4b5414a394aa9c3ee0c1931301cd6b00eb90ce8eea285f3d8d08662eb41165bf37a0b16b4bbdc6df5b84fe79c5f8018f7c7a0cbf25a1c3e5489c3076646fd77aa06337f5f1751351e46cf80364a3c3886bb5b8bc38769a5e83e7de6ca094b9533573a1040b8718326090d8d291544dad067ca5523b4aaed8e98549154cc7577af6296e5e727fc6933d9c6483bf1a3e4c7090b2544d044254458415332e77cda046135189a92171ea42949e2e727c8121a8d46a3d13e4aed7eba2a684baca04999732e9956d09ec88fcf8f15342b6856d0989052fed4a494424a29965002c8ca4f15dacc0454a494b424a620718414991145b8f7db8086fcf780068d94cc5d756aa8bae9825dea46b34ca14cd73534fed988619dd2714fc7e3f160ffddbafd7fbaff9cf461b43b8f7e5ec9a5e4c2a2850b98173068705dd766620f755007ddb61f0d295bb6d33daefae91e6bc5b09b74ac63e3090693e6691ed48ba2d93a1faa86a753a3460d0fe6cd3c2bde0cc499e1ba69a341e3f4ab3d06e3becc8c54694571044f39f5046241d968e1c18e6eaefab97970eb1ad8672424444434c354da69d729c5a2c8663399646aa8b869231a1a9ab619a3527d000208373e90522828282605c2b43de7c1da26adb44dcee6f4695bdbdad6b6b6dd9e2db1c4c828c99a077b81d5c01a0d4d890788a553cdeceeee6050a71aac85f002bb01d63a2c9d504724a748d9b485b7eb5152bf1bd346c3859247c2ba9ecec63a7c9af5a2d3aab642424444454546602d9ce30bac27466947c6240d1802c876dac01a0dbe9b08e06a7a3307875987f4212f0e100093276fe028005c07d69cd58dd3d65ddb023ad5f601a6d24e0324d3cc1600009e72ea08d336b90eac75a5182a014e7881bdd45e749af519c1c01a0cacc1c01a0cacc1c01aecbbc914b50dac8135104bb33c1d0f76000f96c208239478ec70932361729d4f37a5b3326dd3366db6ae67c9b4b9ebb46abaef88f94820a1c483ba33333309b3663e751bfe84d3e62aa34eb5a5e23cead496120a34ee1ce7cda74a19a59d54aa86d530b5b27248b0cb51027b3a1e6cda6651b3402c60edc11a97505d03b0a15d210897e5eda8e872ed3ab903212128b676562410926258e4e835a6e923ef71993bb92d196cbdf655b689dd16e7f28e9090629d024f7ededea4ca64db75b2653299ccbddafbb0f058763bec2b2c16bb75cd4fa366793e68cc6134e6301a73188d398cc61c46630ef35c34e6c5e61135ffffff3376db7a55b89e3f5a125161222a4127b8c1e2b28ccb56dad52d25a94f3881a5892b4cd4965002c8ca4f15daac8a09a82431058923a4c88c2882089f2854a03ce9713284104d82b0d6723c50aef3487408275f7ccf839052cad907aa54931b4216a49a295563004eddd4a4a0805aed5a2b8514b5da74590370cd89536d39556518b68a01cd9e06bceb27057cbf3f1d8774a238fdf0e42cb18742a345a145a1d128f7f3f37393cd59141a117fff2834ff28341f9969b44829ff7b58a5dc062925e55ac0b839fd273d22a3c9683f3f3f61952ab39f306c420394175854283a9eec3a124fa7643428495481a23384d28732c3cfcfcf10284368341a8d46aba1c2d5099dfdb1de4afcb9e94fabd070b8215ed0bb8ca6027f7f3a87bccb683ee04b75297d24d2101acf4ad9cdb8b2febcfcb894b2803f5307194d4693d14810fb1b94523a9fd2d51d810842c0040810fcc0b383f201b504a583ea01a504c58394f2070543254121411d41e5a08ca08aa088a0705043503ba07440dd482969a81c50425038a05ea81b5036a06a40055935177b71dd07ec398b94253624258bcb2b26737989d2e6932419da3c09e19678e86e25587793401fa8522e6ad219e67147c577b79779b797b57551bb21cd1866f6721c87ad9c653d972d69e6ac1448331e2908d516498824d4352d1214b7ad0e9efd51d7d51a8636bca49b020a66a4a17fa1c695b107541554b981133749630de5bcea759c294475aae52ce5c92efa1825fa7fd05c0205f74562d186ab548a8a29932fefe602d774ca76c86e0e992391d6674b29a7bb3580745d1f9fc72d1f8d8ba2cce26adc72e8345ca552d7c71c4aaaace5f031aad5e2b6ba1e5cae23b1b82de5c9ab050fa59b6c012bddf8e78c2b5bdc94cc30adaab3de654b1942182f6ee72c1fc330b401545b3b4cb8ad832510753ab92dd59c71d286e18ccd2121aab455f6922d7cc638f6e20949caf77291a47c2f8f8145e556ff226ba894359de56ebab86c6142166cc20c2245e84e24f19074a4e42409365f9435e78bda9c0ee726883461e290830d2fa669fb721bbc3077f28587927ee02ce9a8eae4c0e60e462edb49844d98375284e671d6c41927ce8bcf8b4fd7b45ea2bc44f1483fdc261dddf6665367c266cebc91264c22d3c8dc61e24c9c17d9ffe0c2e5f67b80bc93db922eb57983e315c19e8f14a14b543c69b9d46e976e321a4939ea59b9edcdbc293ed2044f0a124cd3b6e51571fbc513990bd70de0fd1567679615539e364bec87da8897d524bde68bf4f2644ce3b2c37c59cd66b3d56c367bad56ab5468d4ac06b2e5b6cb8656c2ef1792a1dbb66bac837e93db82a1e1d86e7b4336846acbabdd2b3e726ecb1bea9a96b7c45dc20507da6d6fc8e5e50575aaa987c5ab79435e6d88a8591e91373434b4828f51adc9ac63257b266a9652eff9ee0e93929ad457ab550d278fcfd86c327ba6cf944d188eafb18ecfb2747d5e961993de1089eb2c479a719934f2c8755c9533e62a9f29eb548b73868208d7c7d94354db96ec2cd2f29aa0b6ac458142f57f2585cc2065a8d2d2dc90ac43ca4f8a7ca5942820555ad48f2a2da362a8d2a23e80f28182a14a8bba280fa05e40b9aed8c1c98a2aed962aed4907555ace418c531555da18a7a32aed494b9516e684832aede90655da935195f66483530daab4272aaab4a7db890655dad30c664e32a8d276ab535195f6344595f614832aed090655da93edf4822aedc90555da530b70ac70acb82316e080e6f044880c95e1c80f1406f52f031d5982834aba0c74c4487704871962908a8ec40083fa721928470b079413831a6064158c82e44305af783e6abd0c947384e753635c06ca01a2ab22078937430e0ddc4e05afe8a4a8df6520234631232f9012c888100da49cdaa24ac7a4bab80c64c4c99c551997818c209937a8dd6520233b501f8c78e0a6966ee025514b0198dca8140d9aaca964330300010563160000180c08064442a15818459a9a730714801061823c6a563a1d08035112032908a22088610801c6004094310621858ce606000017c8c4065e76bfb25c3669bdc369148d411174584935211f9e0b17d910d4ab6bf9d078d10a61fa1b236ad794246a688a93890b6d3c505daf422192ff410deb3c2b370667e6708975744ff4fac4985edf5ae516212844d229c5b1f264926c40a11235d8d089ca45cac51040a626d22edf056fb1e588afb7d534fdb52baa1f5c8271d8233031bb5351be1e80b11f1a1a8a2dfaccc18fe01c9b24c4d5dcf52e6f84d9bcd632a405a9e4c360b00fc9541e21f77a9930c8ccec0f28ca137b0578dd7a123a15f433c3a849e1207517e3299443ac412f0da7bfa430f6c2af6ac6d4c64174b1eb24cbe6133c42c4adf2f429fd8cac74ca9e3ed247fa1a987304f58578af811b9e92c6df755fa6a4a7b1789c40d84a9096657987b477c45fe77f8a192f602524df59098a814ee63bde996946134850821fca4ce20125e6252de2015f040f9149597bbcccdf631849fa7c71a29e1aa308c868ae77bb23f56ea854c2e2a106532fb6efab781279a2cb49658b2b3c74d2c5f0ae70127ffa1b3af5acb026993826ce6d67b125d6ebdb93a4730a486459c8839bf8b233d54ccc306ad2ca08e2e08a89fba22434649d2bf54625bcab15960d304515ca1bd2125f8a4a06922a93ae01b5be8e39a3a34dea3ec9295f99f9e08ab548afe71139a9c40df75a28f10446285c1e8540801bd02f9b27b1387d3f07a99f41e8bf7c60b6026713bd130835e29348be757457c67f0bad08d9c5e2b1f9fc96f1bae61f31847dee2e67ab44be24dd8ada343c2017e199a97a322958a430919877f7e23a375638905025d5ba82518f5abb0312ba7cef86ad91af5984a1fe2b2eb10943136956fdd8816549c5923ba0e16c25d4fbc12ac22ed5bb2ea53096ae09817414865d49a810c9d7af8411a0b944e28bcf1a17eb2fc0b7defc34237a36c328cd276c29882af902820d68a4f08da5998953d06bdb4729f8f7984c5770bd845ce173a6f1d2b9f5c4ec9d053430514e73579e6fb621ccfdeb751870104db35a24897ae90be786cf4392bb0cb758d4720f87c94543d4d7daf75b9c5c8bf0e29910dcd489b7c03587037a1aad8321fe87e00ed6e05826ef550870e33f08b8ad4340287ef59335112a52a6d61fec3c60946e6f27c4f2070b8f355b83ec802dbad37b47099a5478f38fa7a0411b83da07bbc616048c4be200649db55cc5167ff1561060ee84345abb1734760e536580e8ad3303bfc893204eb9aefaee97468f19c2d99a026a153bd4225ae6edfae28040054e0a53fb46bed9a1ddf447842d22582d981abcd7e4617c3016f55a42e405140fdfcd6cf08c38b8b70c45201d4f6e912b3d41ec25773514aed5687643697a91e09308821be997e51ce0f8cead99f8fa73876be945ae4a2fa2df5bb2872433eda6ac480f77bed2bfcfe95c2aea551075fd9909ee4eec2e727527178c2e2721423008c69c94071b5012968e8a70ae91dcc5cf808a859dc881133f66d62559891904a88b76a10067e989cd9131365e873de257a92bbf1875802670c1aba0ef30ccec53df674633b2e77e658a0cb6cf58e4b41f8031d6aa73f5b9750f18ef2870a42fc6b99e5874a2f756d72404bd9b5f9a0a08dbfe9640f0305e6a0dd52042e7e83293bdaf94387eb3dc429ee6a9685b800fa40aa0743c037fc1807a2221f093b408838c7e8474ebee063eca1393d09b44ef41338e4cd5d77eb7e3d747990ad17387e22b1b639581d7ce3f298acccddb4ed1d017c40958132f590b62fe24edea512d5c0229e0ff511d61d98973b93b5ce5de3d349e913e2c9b7991c778e02cf90dada22177600740430567132cba3acf058d1ec9ae1e891697a98a52b198cf5d9e7484f300351c11a94307affa179d4dc53aa7bacdc0635b3259516f18c8a2af6a9759a258f052f333a51b8484276d366a3a8bc6b11118cbd83c8b18c1457f1135488e9d8081dc2dc7041561351fff13f33db70f48cb06ac94ce336bc16c69f43b068b8cf2695569d3c406d38b266a12b9adeba2038b8377a9515cd5d172440f45c702f48ec7597ee053997f7ee9067c8f97c138ecc27880406e99e09d0fd13746b80b8196fe3467e4a66d2891c29b0c98bf86d4e468d00056f46e3c2aea56e5ae03fd725adf8383d97c25af85e367527cffbc43f13bbecff80c45ab06e901576e3023d15664851f91e7eab39a922e179813739681a63828172786c50a6b68d72fd2f6e893842e33c5bdd741d375c56569a964d5b2e79fe4e8b498c3c3360ee762a6d83411926514bb56a043141156ea835087260bce2fe32e6185ae7903158666ea60be19b5e467015c2df89fcaecf22d8e2c31748175a5c592d89e1467f17e7d0bc97e29445491e38c470f8b2b2a5da1098a0d86af5095c4d4842aeeddc10069dd0bd100a7303f4a753c121fe730323348eba71a36df1fca91dc2a382f18da920ab58783f19ebb94124aabb0d01c9c14666c8cc6cd64103e16a1172971f97ffc5039455d8c24d0e41e509bf210d98312b9ecaed49bcdac2c96ec7c045635ec94e48962ea77e6452d58ec94130a8b262cc561112e40840d59a7b8c217a2ae703eef5ed5b095d1d864f3e6ced840a9dc0e706a43a68219d280101a3b13cdcf513879e21759f7fd638e0a9e40ea8a0067c5fdb1bc12d5d80b0aba32f2889b46dcde876030057c2f74140c99f4f44407433b656e90a8f41ef503d618cce2e719d521ef18f19c6a630fca391ed5613e200c7eebe9308013995211900934793282447845d722ddc3d43d904be7348351ae82fa7607e6a1dbb0a8f8f8788a6065715c2073fa5b88d0a74bb64a408abd5666480c37b2d569048fc0e9d317cf901987a11a225868536414f545b25ad3a0483721a38972565ff3cb949b50a3abc0729a3e5a0f8553ac890baa5341b7abe5561c5e971c3b52e24c14824a429378963f9596e728f50edac409e4c13733776b69e454b8f6e6d63af7a54c72d177f4a5f6a658e6ed53599a3c0bb825bbd0bb334f76824c98c708205e3a27a4d16e0078605e4d84d7cca8fa387ac3ee7e70e9b372dd83f37805109d5b0e205fe8eca0dca262f27b385a55a7b56bfa2db2503128c92a5409be581e2ec2617819482ae287789acf904b45a86500456a593d160cc7cd78bfc007580f2365c511b5f9cc03cb5e4e0fd20ddb63eb4ca870dd85e36dd518d1ae04a82c6b1884e140502b9d7faaaafeeae975e7d2a5599e8404ee50394bc3353a63d54e90168f1825b0bf73024be813b8acf82ae16734b47f467996b8ccd668149fb4ef6a89d4ecda43a0b0c80dba6ae6a3a3b8a5e9a7ad7c9f16ce27d2462297b32e997a7df02e623974c49c0394785b353857d9f52d0b7dacce4938bdd9fa72675d562de15dc2849800402844b9033105b5d7156d297642554e8b62ce010c16354950fce03b9c092d8936758be08259cc66a943649e29f381627d51494dd9aa6b00e9727a6344a309b89bfd5f806daa366e6eab1dd7883105b26a09208b3f75358aba21e06b2fd11753f86cc88154c2889d090038ba7da78261924181283f5cc190041971b9de32119d9750e11a7bf861cedc77421c98d641948dadc2fee774b6f6ce040a167ca5b842927a91137ef28cb847ec8f5b2e9882ebf87e5f05e04e80b0c20ac087447c3cfe67c5da2b48fba987d29e19051ab7b6b4379bb0713a11cafb5433ebd24bcbb730ae4c2aed09caeae15206fc90853c3820825e1a2eff2de859a11aea95ecc3bbc461d3d11f375ce262e5f8407c6fe1c0985d746d5d55bc7eb7dd0f2e1702beef0da07d6165d149e30572509e6385f5c6a86b4939ba37f64c2d8e09766b0b61f77e757f600896afe4ca53016d34dc418ac46795250a0819a09200cb8bc7d56663ed2d1fac0d351ff9258d6baecee52571442d2254cadae8e9e8a94c4a431a4fbb684ed5148535299a51877d5aba8a15d296c8d63990313c65235cfe1b8340d7ca551db90a42d956e914bb767df20882c42056c69261008f2bf5e586d0c766ee81427780823ca34e2f2d06b66552512240083e2190c08d8a58fd6fda6fe0ead5141a5b6e15e99710f430960a4fb0b5c0c16f2d1458173565d50a0639f3b0098d70b95436487e0dcb9b29a8224498aa2f5b740b0d2343663cf21b8a86ac8f24668fd88f1dba73613771af2d1ae1291602bd2b084bb19035cd8e0c2c5b688635c7871ba1c3a8ee50333a1eabb5a5e1d6c570bce5b61870e1ccd705ab314cad464928cc76c11cf334f89800239b63fa1f44f72cb7968503ebf3e38b45ffb7b38868e2c2bded7fd20f4bcb401d62c73d189292767c0c93f6296caf08d166486035fea98b54af7c9229d1f03be4165c33b23e2e021be9354c9bd1a2c2d7392524d02120fa4dfea24a6e1d6a87f2ec0d3fbf26b31ee40cea15a0f1a53b986bec78c5977e1c73881b9aea24a239dc5952fd605fcb850ff7130b57b813ff98140835455ebc0a586b33470a03e6deaa98304043ac4c93a5ed55ed7efa24d6a7fb43199ef8ae2555d966a7f33e6c915b0394c07916ee042c542d712283ca4ccb6374bde0aaff924e8d26b25ddf4fa5be9affe9ad4dd31b8989e4e831986669ac2fe78aa0e0e350877f270d5b5cdaa06b20edca9a7fe838b2109e7913035969a1bf0805ca8108ac288b6025b004555f9319506858df50d99d20e68f2d5412f98e21032a97a7bde9f65998a52922e1ea29e43f0d93d0fc290b143d061eb7e91d94f6e718d84ed143ce7cf4a4aaaa6c7b0efb8465cc49acef252997d60ee71409b853c14b5599074e1dff7580b42693b55a250246dc4b655e6d298907a2dea43dbdaef96d7b5a96a0628a8270ec05f93c2b92bb078d9ae8504dfaa0b5f10ea9f80fcb1977d1edfd7aafae57f813ad0dc6c522dd91a86858fded3167fca20ce2149d71509b92f783812752d9a3f4885a00461fec228480c00eed6574e68be2ce5e78dfbefdd39be7c3017ae767623bc2812d0c31fe9d3642f87a3ce995ac42dc8e71f346480e9b07b6064ec5a496d5dc7fa5cbf610b52aea90463a3e61bce091da162c4d337c9faf9d4148ae0a3f3fee7e8c7c4c37cba0f8b167a227258c40ba18b07302505fa3234e4afc7f23c58fd0073f1ed47308ed6ef60276255541e58f04070f1b189d2cf7f1f64f1e07a0c9f9ffada3df5111e1115066fb94aca842cb6a541b9b1e8b123c9063668ec4c3698457eae1d908f7240d9ed6ae055d27ff2db88ade33a3570683ab9b43e6fa3c75389ae2b4c5e2bc2335c06059cc622ce7a25cab732c25c7d87394ce6f7b470bf8403f832ab29b8d26a5f3cac74910ba139eb85420787f9071d9c0c192634ac00bf42cfc370c46344d703a8a50ba627fac6f630bd01e0656dfe12a539d629cff1289d94676d64d205a4c23f1258c917b5fad6b82c590574202e5a34e7e7b20e9add1affcca9ac2933ae01b41583f272f1d60cc536d7fa7387e0927a01459234b132d4f57bf768b554d0c84fcea0a42de0e59a8ca60a80ca67a60aa8378aafda6baf5636d3ba0eae190d8052bdf7175e9f0860617f0d5bd19314b2d8bfff58186612fad68d877810ce3b0cb3d6821130e06bf854cfa580eece7e35fd1786fe4fb806e74247b528f60b782624cca8abd816913d9a8edec2e94f7f04e2b20ced64616ea4476898864b08bec6ca0332894aa60e82fc5ae5ca2544db1721d7800df13d158d5a36c37b9c9430b43a2715b2ba1ddfba9d5d96f1ce8f14f108dc99aa16efa70c3d3e942ca57c985a11919178d0e8b77cd546701bbfeef5fc97a0870a6c9038d3054ca03cb8c4f120258d2d23874978d4c72b23adb700cc4d83c23c4a71f30254e99fc5b6099f26b2b81f7d8e445fcdad8497be052e31febb4f619ca5bfc439c240056177478e943e178163da703052b739d3b0f462bd2731e036c254000446bb472735e70849490e49ce500a3bfa7a6f42d4b0f5d9c73e5cf2d0630afb1cbe4a16f29b9413244557d7d32681e844d6c2412c8da46892211847f3ccd8e95455d572826cbd03058db724b01bf5efbb538ca54df4d0c772a96ff60873781bab0e5497d5fc9b94a4c5b83c5af232121fa244025318d0660f044d544d6b34b62dcd8f99dd9c00e373fe7194b1b9ab630b64c4c93ba98307135070bc3dfb3855009752a890f0074301370ee28b14df94badb5356ac68081615c2bc62c82ad3cb327b372e081d9ee649e51565c3e3755e44acd6ed21a3ca262c3f6e7e7c8d89d88b7c09b060d485f0f67db551388ff0eb05e400306f1982d935731207aa69d30a3ab41603398685f6503f6703b69858a6c280ea12686a6e1e76fbe0c20b1254724b5a2273e04e2c6ff286ab5f54c91717c334cd46e70caf09f07da6730b2e9af6ced3503d791a5800d1dc5244a148d10dce761efe6a3e74356026a288b39df6dd24062623d0ec1aaba113f926cc565c676d036e64fe78170f4a7e2719cd499d0301f8570620036d2fadde038c3db288b39ba6639cb5508d99c54fb8eb07847cb288d5bf961c74db4d00dd6b2555154591f1cb833bdc5473104a062bc519d418dc993b5adea51a619482d6eb1c6d73b63fa13a5a3e8a71b4c73194812d9e8ec00ea33e439b806e85821446dec4949bc918b68a1ca18eecfc0cc23519ec40c62ae12dcbb43b7c877359d93f4c426c28fa20bdfeccc239d04e2d35eb12e1f8bd9829d6b5548b1c8cd96293e9bc7cbc021cb8c14b375c5b116c3c55d87c45209a34b28d868461d0943b75a54373d883c6883b6dc7a7a191ec7323eb2df74eb2dbe42f7cb15e681f770aa49a99779b72b735703d9a9a7a169b9f75972e4dedca7cde43a335acfb03ff4e1827a14d2b2055a5b19ca5b3ae82a7734971cc061690c2433cacbcfd399b4da88598ac8d0cb6242917d5e0a08192960ee680e758c6858f6cce1a1a49931c6c25d4c134454cf81354c11fcce791ff796b0fa894b4ed8b37af957161a87f3f033ad139f357ccecbd900b44f122d467cc9f0b023c0108957f53b020c47ec29c9a2ea820d010f3fe49b406a6a05f4b21d6fa6148d509b9c0419f31a31b745cc8f3d7e6ac2d7eb72dd2c2a7891835a153750cdca9ec9862c0a0aaabdef017d44460302c2aad21a97e02d6e7c797954163143c7af60f52ad8a4fd53e5092524fa8901403056d3014baa8d3e2ea4e5c79b21d7c6913287fe6b865f2690de1c9fbcec7b8c4abf812986ef79c2303fd2246120770098dd8f0fedea5a1af9c313749e6ea5dfdf050d314af5458f445b552c3d0082f06de2d6ff424e5062795f29dd0b022f095e74e6a3deacf743f77a2441936ecaef49d5c47b0075cff4401e4ee9a8847367d2151528dcf2824327c445dd9edd9e84f7e664aa260800ffd3f9fa014e1759d504702321c980ee5c36b3d9260e0594684f0e1fbfa04588f66d4529d1d9df170a3044d91ff5141001b67cdc6931b9de5a5a889d51e4ae094d17efbaf32f4f4910b86e0536fea8f430a75d6922d7a260134b69cc30f88b2564b99a8c532c835f6d32b2ca6ac8009161fa3623690d44e185f40a98e719191905136aad91ca296acca2ca08bf1ae414e14751f2b5861d6b2ac5eed27848f8c8e095cba2795cf67cc635e02e8c05e3a4e965c1b54e3917558a4fef5347de57888860d345fdf90e856918b3860df44fcae3fa093e7f0bee6bf1bf2ac757d6b58eefde46162b815d54b09a81a9e82e84e0507a5409434f4c2013868b2ef044c24fbc084fe197a40779deb54b3a8d536df5de6c5d93db88e68547890c3f90555987329d176a5fe0d9410c9341a5a6e0f1e7f79c7ee0fa23f6c229bb10289b3804d124328f7f75b0084b7dba2ce7668c61cb4d21e38bc69c64e0ea869749f8202db8824fd20238f6c507830335c9910d7d9a1cd65c6b92dcf717987f30b430c9b86dfd35ed56b2e92fde4b200a18e1bd4766d30a9d029af66da6f061253b0f770706299e0c5a1eb94fc87cad3d41b7d0ebefd9afc5fcf424e6a933314e044b1641e2e22e2a8902f808af2c2a87203e8d41ca218b8c81401852532817a80c4655c40c3e129e40d4e2d977dba52597f4e2b49d3a9ca7d7b163e0869fb8cd18099d55f2f73f76af04a6f529b7d6d95a1a442d52c8e7c0d650db6681433eb21c28e8afe3cc49dc7ebe8388cf21a33c89ff2f6bec265480f10e8a422bd619efac3f49ea4cf1d329526d6f177a0e1f273bfefd0540b329160567ca8c2d8c4928d3b9f0cda96ed77994834ece298e2f303280b7703cef1cfe87c639eef237c8b634ded8adebabac42a5b9a237a3b30e502c4362a1df61863a2c8eab973118a951f45b3ac880580cacb60dae4aaef66e723f85222b0446703be8a8b208832fad7c5a9a932e0b531bac0f66b97e564f24ab1e08b318267c2c739fee04938a2ef15ca6477e367aaa764df7856b6d7753648a6bc5641304596193eae07d25d9a4b1a80f8762a6bfa5a431aa835eaddeb6d48589b645a54ce92f969d85e86135a4179841127017f46f7f1d16667afabaddd7db0e79140f36e61013a31dc77e8184a114a1b171d88a1f0883458dd9ab06c28ffde4b0503bf59c321df095bdf216fe31328adabd7e958580ae129125a7162fc2991b8480a9fc9c7f10637b093bbf0800aefb597d22b94d5563bea9b04f33db8c724e6429d5824d5b437947bad43766249ba61f7e47af53cc786cd6291bf2533f0dde01cc5837d6b4c7de6277d471ded92fd9e040b9633b0090e143b767dc3376d797aaa0e656171a89f57fed2c1df667b3501b7f8e9df9e933ac837fd3aa3d9505734076ab943a45b6c4f00bcc446b01bd15f77881fee893cd442282cef605f7845989ea25b0277181f1ca8f392a0c9c229e30744ff79caf2ebebaae197a2c5f3be58741f2ac6a298c14d7c5e844d07aef46d80b792c9f3375fa60eef8f045dc5f223e1c3e406e95c48a50502f5691d8be1cece50d4c63846220a88aef413179445c3d0a2b783a985f416d40eaf744f43c4b79495fdccd59a733ae3d2a189c54070b3fd4a0bbda396c1fce5a6ede4e0eb0a94f3bbbe37330a7c1c4f79c6d769933b2f2b164fe43edb4984aa985923bd2d541f4598c29f9eb3ef670afaeced996ac0e06e26ec7fd6221f7bbb363f4bd8c4b4345857f467c3a62dda7b31f19658d5e17390027744fd032e9055309c02c30f115a71287618a383b04701d9a6451b08f4d62877e7a88c84cd22bb305288d45956f0812b113420540ce1e8082840c66f29eec32ac1ec0e3953e5b2047a5db5e0f3a270611754d3ad782ff131bcf3fd46c6428352b6abd9c35f6c1558cc0887bb4182ecc05b8ae0b344dea44a3ab641d259b759b890474809a962112cf56ee4980f3694bf47d5c3056834c40c40f896c1f687577d45a43cb565113be6c691b518d6763e806a53df22a63d194331fdd061fde41fc3f6d431170692e857aa0aa6c41e1c815b6f8b66ac642e9d576c53c1e97c856c522b7d4c7efef718be179f80853a0661e2cfdc8e72646d4c9c3c231de05c21350400fdffff0bb33e6f51e51d890f80f446bce5c2b1cb23b600f44de3b8086782cb1a2dcf19861059e846faf9fa964fdbce1130c3d4a5e4706c695e32bbc02a3bffeb569c09855b83dc77f9a4d0c0a13bc23dece30dd8dd7d09097d612d152ad735f8951b2fd0d81af878d540302237e91c1fac738e17e3f348dfaf680500c0c91bd5b3ab795d1129b9f90664651e679c5290eafbca86fcc600f94652da211cb590a07e4a05989806cb86bf25080ae10b0fbc376b6ba818d27fb1dd9cc8415948f78c98e170a166002d9bb9da663182aecd6d83fb3f78547b5fa02a68371f7068d69ce6b996d9331fc0724f579b072bff7d7f4ce43fdd4784350205f3f82a7972e4448cd2d4e01f9e02d8d36129d945c86799d1ae11b1479cb4609a6dbf97794be1c190c3d847f417684cdac040f0e785dad8dcfc61f43974797d2c65626e8c3b3e2b3cdfb189858fc9b5456793ff0befe46292be6b1419f08dfc03408efe725b78f28527aaf027051f4685b05e88209ce4615f736f31cc8aaf8de92ef2ea8b95e513cb3eb39c2bebd6ec50da6c9090d53b4657e6dd9d70d25d18dc76d029bb34a5fdcf719bb7beaaaeea55f104613cce403ec8d85601ec4fe9db8f4b6504691144819012cf64c9899025e0cd02122854e5107ba8210fa5f651e854a9e011d9437cf8011b16e6e36724513ee5246dbea0a9d11ee06ed222361378d48da3503c75d9058e165a809d4c056a65799cc52e329ce353565c4223796c578c7d124d1d95cf08c9520b3eea2864ae1387a428f556a3a5f1f452aaa124d463d55b5ad2637576c2691594860efc6f3e41154582461b5bbff1f619b13596b60ed4b7caf584639093fb3d8245e933b7e31ae73a3180b8d495fb32c0fb930b7f0e5a46525f290883112beb93cd1236d02245ade41f1a7497974536252ee2d2f32b2ec5c63507ed80c535683a8cb2d7c2af2520690f57cf895ae739d4f37602c8015ddae31c4a33b2276321ba02e5ca3d005fd73155f1c4dc242f3292f0e72f89f3809e043bb5409a76aab34823f64fc768778a4424a826d80646e0c12178e7140d2e1596021c7e116e1f0698403a711eef488daf5eb1441aee1492015d57530b7b133b6a2f5b04cc1b27a75f49e434a63414e2bd8e3158d428abca208a32877c403a4a9278baa219da406774b56689139afe6140b16596fe10ed858f356e746ccfb5704cde0d1e8e075c37ea0478008300c8fc3e3783fad334b0c5d72f1301329397bad89ca63e5c043c11491291efa49ae88f6780ffca6a250cfbf7df7c39cecb7936a16f80b00588eb0d700494f4aeb2a7c3e2c09380d3e220401076235385663c421a36a4f71261ecc89a0a049e1f8251bcaca1a6b2fbe43680de90567997e3e7f2839d38f340f17344a1234b0120fc983babc39f8a4db9f714f44864a19c8e319faaa67a3462622fb053deb44205c6708a1a5d8c4470aa1810e4245242fee29535e9360202cb46692f5033049f12243101275bd79b71158ba53f3a98678619ce286b243c348280503b0bf879dd3524973a3d94513cd2fe9a78c96878c3aeb236052b2b77f4f28247e041e786f947c692b1dfdd83a38666c2ffe201bd0df9ee16547e7c445e5081ec4cfd6185e25bfe76e268197314c95d9c3b14f4ccd01b1c853010a74bc782c461476ca80c63eae96d1e2bcce65c0866c22f54c4d1dab0f281ad780fca12370c9a5959c54a3fbf0a632250eaf75a8758b1a79a97aba3d7ddb840b75dad81475f420af28ff5e46c20aa1b3df6cb820c9a17f98f0925f850cee0a5894ff1640213ff2d217cea27c4584253393c72d7b7bd05302ddb03a382e260d8e5da8471cd6f0c694a67a36404781fc3a187def450588cd61c3db45121c18c725f2243a417504b51955cb5e3646ab2f1f9331d93d582e9b510f7a1e63d9645fb1cb620f1dd150e66f4624431ad1fc9bd40b1712dc53e63f5002f30861f24cc7d2466d550941896b0ff31487b8b878f737efc865c33b4b611c156ee0a90213090a1794717564bbed6dc2a5ec31c3dbd27bd987b7099a92e3fe0c139193e7abc6ee702ab8f8dba436395dd53aa760cff764aaae0d422c448500ef49fb162280cfed3d98b3afd91dd179f27198b01434ec817b5fa1f1002ce3502cc5a6b15e740972b73bee78534f9b18ca25dd1226c83852a4b9a6b211553a3450abde69f2c1a1a7cca3b13d6d7a65322ac3be9ec86ac408c7581634125f5418e9bf15de246f912b80c4a3c3da206f588a8a9bf1c787efdcb2973b33aceab343aa7f2608461b2a5389ffd20680e87df965799036823015fff3126fc85c08eb42823c97168cf47f702e831640ef1bbc46183b322de5d2e001615eb886379e78163296f1959b4583de94c191bc2772411677d159668e1c5fcd973b0f4338ebe1be37ebe5be1d0a3aa05bee2d3025520cf74a79e06803a6b2e70d171433eeb5f053539443fc115462101b8dc517e27eb15525af886640933b039d6bf599f69303e9d49158ed18538b1c6e099f1b81ebd24d99beef03b3e56e11a8b29afd35cbdaec0ee96e0a230094293b98dc27ba42f021b97381bf0eb38c26e5ac01100082b6cee587245085db1c3a004c0c1a6c90aaf458345970a6c786a785021dd22a890d6c649b625e125c241131623b71154f34462bfcffad508118421f43930a6d60078fe18ee6a04c905f3fe462fc8680ce74f5c414abc9d81d56801001ed1129d2c34a9c140bf1f56ac5b31491dc09d255f0f3f5ebc7bfc2747d1f16e19810c1dcb880376a91031fd5bba5521102e04665332e885f18521f426892743321cc8a88f0a8e859a937d4db30f33c0e5b93dc82c9b7d56aab0f888d6d1f525a13491ed2c4d4377d128409900a228bb2447a7fce35ee69395095cf1945382531e07c6ac0038263ffe8d9b27102cf899b69548d3161579ea7f4ef328e9eef3bd5ddc41aaf5611c6241d7a804904bc7cb85641170d375520460e40560b2913d1151d6302a146efdac21bb48a47ccca7f3852c4a1511e4ccde0772f899243f6f12486e6f38c517771f4e64bc6c4afe835e980552ab6d9a7ccf068381ff34bb11d66d802c36308f255852c6d1089708adc48cb21d1739ce9b86feb15cd2ae088e4a5e66ca8c0aaf152fa8dc5ba2be23e968e2178c41c93b229bd88c212a190167fe7d03e035a4f592615ec15ee616e7140900a3cc0260735c86cc74fb102d554e61f3bad75d3fdeb61a6aba5588ef4be975fd25ffd9ae8f6ab0828dd23c84f510977fd1d8452239a3af7a35041313c81247573059426bcfd51c3760c6775a36b35f9c2692d37c415fd6639b943a4fffa927b33bb20a72edd6b314285ded9d4ec6557a4c7e5a06978e25183b41859a779f78ed141b03521513ef6d78bbcd5ef660c635d21c40171431cbb567c87de48272f626103532cd1608a0b205d93c001f06a4f912bf95f7c453473131372c8ed31f1b84e49c41ff6ec943667a0da46b7a07401d4f87a22fa8a7adef507cbbdbc15f2092e77aca23a7617aaea51e7970beea8314a63827d1321ed895a39eaff4cb1594b759b84f4cf6eac8c1ccd01ab365848508cd2bba84f7dc4a12e0f92763e3839cb893c18c0ca69ce073f02ecab5617e2bd1a44ff58e04c0c02cf8445e85fd197084e72f26333a2ceb04ec17e5b75ff98221c1e4d68508fc28c5342b6061a1f0a33fb9ecdeaed70e183609bc945ad245a4bbd842541c5b4996b76bb71964ee8c2d2c498aaec0811581487bcc1f4ee8fcea0259081dfa7400ee41c714df622d8950101231f04a51651cdc7cd2152f63e0a6f35d67b57855f2b9c7e5f9c7a5110a1fbc0a09f20f8437aa357d802a42126b2fe6973a827b892047ebcd95dc2d5dadb4678f16059e81c59e4bda8d99c8412e5db9fda6e393e6f31e3c77ea06515cec4198cec6ffce25d1b42b11c83293523670938cb356c0c991ec8299989028bfa1726d36d7d7908ea92c92d07f8ce2c7937a5fe627b3b80d65ac7a32b9187ebcfa06baf4e66f3df097fa4210b70fc3c2d79352da279897864cf6236fb32ee5beb92bf465e010465404f4f0834f2321c7b33897dee0c04d281708046ebb6fd466ac4222951d11b4b863e20953a5d609da7a87872b61710b60ffa58ec41dfe7a6e9529468e71d434079493173c28afae6d1025216ba1ba83433d1ca3aec451b83bd2575534fdfb4ade905d9807e6427542473363d26838d09a5f94629efcdb2842e2465cf6f1c3b6f2e53ae436d911d251d6fe8d329a4ac65812d13446c87571f839b265cff92fc19dc21c50246c017228000cfb11962fc8feda94b094181a0b7296600ed222a22a3905bd7334ae2c472bafb84bc8e65e05a0ad2b8a4334fd192318ce6e375f663b8100a5ece21a39fd03e1723c856d828862b47d301d5516ac6726e6ff7956b28b36669edac153ef43897fe0878a0e8f7bde98a9036ac8f440f0e08d142154acd347b0b5cf789a4a8e9970381bd0c95b1cef1b190f07f4a0513249e29bf2f9d26bb1ecc9e9a58ff9245f3cfd97fbc7b6b9eb9316aea1a4072a5b89d5b05f8d1f1fdb130e3be036f0bc9a457653b7e21da4b3efec4f0d8320ad73c66f88299155ee2534b3e88429665154cc0827e752a2d1f49b8bb6390f7add1a36275cc22ee190e99b6b988b908156593f35dd57a9ea3d91c212bc08ac15fee19683e652218a09d459e1d92e126f4254ddaa70247837f17265e1cca2630e54cdc952eca2dc888852fe973cf6c2b84ac8dd30a4c8b71554c210290b333725900698410d57415465ba1e89b74b7fe127a3a559257b9cbf0e9e01c2a5084325427cecd7ec5048d923cb699887090679886a8f9d8d72b38492e35a1d311ca530fa93ccb4f24ae895c31dda14870769c6d4f2560397e6030928f8c76e22e3aacbab6bb20439d271b33a27b8bc3e3724229668784c593f612d8fead6e960d08eb1538b2d624d904dbcd54461d32fde0e11f8f2aa24b516b0c7d6eafc562801b33ea52fb5660d5a51430cdac723fad9579cc35c0feefdbd9159c1ec0076eb81d11c63b7649552ca5a664298de8d2505e0ecfddddad0ba7ed6f184d78ece2063d38e7e9f1cc0c6fdbe285226f6ca782da34f8270f8ad7277c7dfa13187c4e546b585d9f675f43828b6c1b6adfd31cd8b5c776567b5d03160a08211477e906ca3c682fdd629f077a920ba4748227f6362202bb6621685af65c63273de63662977f6e3889a5f08177776c19baa361b03af2ca916ac6cb900041a473c83fb4fee3e54418fafced79eca298090034892aad01090a05f20c370b15ac335a4f8a9bf15b212b9b1cf7318d89051ea2af420be1e8e092ad4c2e492c20a374fcf54e797e7ba6b4f164014769cceb58b2cc16322defbe3fc35fd1c35aad6777e81d75cb459d01e829cf48807199655fd600d8124d9c9c18183698621f80334937b8cf087cc1869d34b8b6cf1241cda4f9010a25746577561988d12d189fd4004524e2568c50e60f7c83f4a95d0532730c819d46a20893237ea936df69a51362eb0e0219be6f039149fb937b22f1122cdc137e62569fc624496b22954b764411931e2dcf04d301887080bb3dcee827ae00624c5ca4242ddd534ad45eb9da464255abfde67803e460467cdcc4d06d524af71e2b33f3768315e8498afc32063a3531305850a288605b752f3632a6294d3890bdb61921e758157ab8f05645fbffdf97ac781144b6671e7efbebf262672e3402b119df6c5c942595a3f2b7ee968c5fa3d2813aade7b89c12ca2a710da7d81894ae7a229e02a97f712ccdf7321d364808f1d70714d2620c62f5de29d53060093cd6fddc41a99206c41dbeb01be41af7cce53a931b7379307156523e887e9e6035c9c296ff331a04c1c43da8e0d670e8efa967e6bd34667405d76fd8711a4f66444f736c145fa0e68bc1889eef4e839c0687ded7964f1cf483bd1d867b4b10cfd4313d06b0c9092e230b8029121102046f3c97fb1423ba9273fa5183d88cda96a3080ed4ccc7c6811a42ab5f51961c0054793c2b1a2a8ba8c83b8d679d2881295cad00336d0995140c5160af7b1b276946bafcdb8b158cc1fa7347fad0b5866f23280b3c0acc1b595517c2e559f6442cbd113256503d871fdca6a4698d20d2bc000306ca8d9013e72ffaa8473a53003d3c6bb874e49b6e8fb4b2829e77dda4b484b8894205cdd9704611721126878fcf1c92132cfcd73a60ba2da4da5a97eadead48df9802405df48802e7fbcd1f51ba1d49a2a7cac8310b8500cd34e3c8db04178b33195640389a2309ba189cb263e21d1122439353cd5f412c52c36ab71256307f7c623fb2c40548d9e6c5811a2bf09121ff364ce9c4431488b59f7295547e18d372a026a0360f3a275484970122932c1e9c51fc1a6e4bc8a1eefb5b8cc44bbb5f76e2f5f7342edb364a62af98c022072a84de20af74e83401038cd5927856b5f20e78519563a5fffc3920ffc2e9417cf8ffd8bad17ef9fa74d7337adc7aa3ff58c878aa6993b2c7c86f1dcb55e0f7640bd384ba9b508235bb1798dadf7cc5d3065a5d49868c324984d16dc7051e66abca35ca7ed67a674fce2b93c339e753cb5de828d7aa41c20ca90a670d280eaae01118522e78fe9703a294b516ed0b0d0ce3f772b27ccfd34bfc8e77088ce69640fa77830d7617fdd668df44c55ea59bfbddc11931c22a24bfd1eba50b89e721421d0af9f5c2756147bbe1776f801725295ed814f516226412d1e047a9408ef45420935d8106624450e1184a388061c63a418800eb9f21cc97b87c68b2caab70574f762e2873809132871610dee58eb34342902e8f99fe483bff0029c187cea7262765dc69cd93047b1d8fd0565aaff880e63a0a89569054e6b31c786bd04d3c0635fa79562ac208e1004fa5fb3da5cc398fb04d61f049232861b45fbf61330d0d1dadffb73002e8ea9c907748c8838d9c4c24837f79c47cb9f83e5f89ff1f277443649c458bba527be9423c2ce8777ced5b5f38bad2ccb29a134edc379022d2e39d62e0801d65b96d8c5b93234d1a8b9304d05dbec8f9aa1d519c41bd836beee01e9b67acb3cfcead7b57398dd6041c472e8cf55fda2f0d4971081d3a710145fd7df109fe04bcecb3c80d7bfa3fb83b80bd76bcb332a4ce804000bff360ac5069399a15e1cb463db8467d1ddc1039d525a43df75c5649c18094344cb6087046a5bab4ec48a00ecdbca13ef2ce7cf31bc41b0b76f8d1c35a145445352c6a66af5ead69af0f1f81495e8b4d99f208dc03b7aa05c1631c1f85d1b3ff218e5f4d313062cdfd1623902465c48586106acb183a2d83453d09c94a2ce61ffd65287ab69d284091caa5cc1129758072eba8071e5306e932834032062d5f3e4773b7c1fe1923adaa052947301f1986d895500432f0b682f6787969f92a2932e4709af2063c07813d817dd4ae98dc7cf505f49e551aa9ccb0bcc7414e85e43e88889f3e861a204f7dd8275bebfd15f8b706b4f33c3f4745c72b2d381d8547d330cac4f052beca757f4c3f8b492d6ba1b8cffd0d8b8674a79d03f4353930c47cb9686e049a416139d0603ea7638d772caaf180d2235a0200305c727cd56e031fff193afa5fbee3d1b900da5b80ba0ff4b34ac0342f9e1ec0f12fbf9b1874679a8c6a203b174f12c0d198fd6a36cb9abb0477989df66ed319dd7f453e08b8152790d8cb39d95489b6884f7fad4cdca3e87f27c7e95ec10141d8bba1afcf48cfdf6b8953c0ca459c531a7c13cfeb327abca4d2e0581f9d7be2c73ac7a6a2503acdb4ed40ba4db59e983e55aba8b4943d16104ee98544d1f1d91babeac4b7fab69db8f5c7ffae84f97a00cb4e50d02a086d5e091b48c48ab0929f569659d8c3f7f5a7ebf8dd5511e469cb4f877b804fc7ebc504aeecfbd3efee2c8b7a7ac1c4ce8cd7ce401b19773287a649112aef25ac95c2322057d2f26e4a03991e669aeb623e6b0e0de84a48a34f25e9d781ee221a626a0683e32a948385e1c37d9d8650246e80688a3432700e959ee748147b2595d4c37067dac072790e9402eced78c6cea0462f7e9c0b372badb850b9159b24b38d99548fa76ab93ba0b6f7fef27fd789b1465501926e0d3448af91f6d43cbaa26546b51163a49d63137abb60af6f678b87b8b13c1a4c825a4474bfb5ae006ac5c334b0a2e7fa92f1c48b74a146296561ce9c7da085ed99c9ec810f0fe52ec7e10ad3738900272efa68efa3cfc65957500f0d8aaa2d01457f8b02faa1f6eac59b2341a20728b26f52dedf3aa7525131e86df5ab449390ea945eeda3367a5c6832ab05a722243c5db6eb3e006778597b72425416510b6e0cdccacc4c9c0d511ff0be6d936debb899e441e5084974fa198161cf5e1b5ad8a490a44a387e6c341472b6ce54c4e12c174f224fb6c3593b92d15351b96c8df27c68bdff4d602b70b8f2550c1df6651758f2387fbaf5564f533334ce77c1bfa594367d6538e17a228032e1b2302cae0d570876de13bce74da3c1e467b19036c0b8c4ef1d6cccef17e34c3993a656a42f854ba1acf3315d62f6dd73268cff797217e86beff6fe055998b5f00deaa9720fc98447ac5a3a0e0cc1e85b56a01b3933d1bf950e5f50d28f702a481f72a911d984b682c4b39a4967584eb8166ac82a09026a900d8f9d94543634b91b483edfbb3ab47919abb9bdf400d2f1f94807f852a8a7bf7a8139dd869b1f3d814a16d0a8db4c5bc8161c66bfd592756a7761fc06e87d1c4b36c502c9f8f6bee861fd7fcaf9af825564fa3914013654857fa2abb94b96c20aa50219b06b78964587e69ec20c310d8c8056624e860bea016fc2b214ccb400b8ef2bf262895e15fc4cee7c9f5a5c46781392bc16424aad3b7190808e0733b72234670271de1717d029e7c23ba98a0107663cbe8960ea49ac5e97b03a165cdc176ecd471249fec85ac1caf9df74750e291e70420393b2b62b76e647a5ccd51e0262ab3169165dcc2466d740f2daed7ae97b091bc4705d1a831a434a264378ecc50e5fabb7303fc52336e32b8d569c541b2578978b91374c1a40166808230d6c397a22a85db3367315b30ff5a23e749ce6142054b35c5ad59a0d0847afb6d019a9d8c6380d31f1478bb90c62ea0c62eae23c09ee30792d767a6f56d30327cac70c5bdc1be8355d229117e7218f298049917810e145e8c9c0c46ca91b6f618bdb66712824e80252f733871c6a46378d11482008aa3b3f615514cc235ebb9b6e5bb3e22a68e292b3b017298103b9011fcfbe1c2010ed591f58c440c265014fe6bc93c4c288417185b3b992fa794231b0d1cb61b702c41ff5f84c7466c0641693eb2a10639098454031ec773fa394c1950a7afb05bd4393c7d56328338e503584fe2481b96c8e39bc29ed117231573ffd914ad8fb0807fe6b00665ae2fd4b2f8e4c7e7f9ac0203f9d5114443b6acf7e82959289b7d617aa1d78a7948ef905a2fd07b7f875b87b0631eee7c78651a2210e5d00410cb5c657b6999349d26d744f00179c71cfb48408c92c6ac03b20efe0bb84813710a785a88599b1ec8e9bf967f37f172efb09ca06bace1bddf5add55f6ad2e0716b4f5da1c16da6b2dd6236d7bffdf858027629086fc9d04f13fc202e23bdb53240b97bcd36894f10dbb7192dab209865591368edf3838e3ed0d917bf2372254c371d78b069985a2cebf2c7c8f7b77521dbc502d31c3585a6db7573ea49aded431759e7c6d8addcce819bc16b60ca50050c34f19c270b1cf127367b3ea4a584ed7d8c45b65b760d26780caf36deb5ec7d90ae1924548d3f1d755d0b58128395eead58bae640a33602a8478c501dc2e552ccb51e94a4dd7e8b4f1dd990143107f3c45e017af867b9f71c91dd2704ae663bfb2729419f03e17f1122e54e08f7d94f60ebcf7376521100c5f2a9ea41a7356316b922faa150e0e3f9353c0229455a9038946633c50327c92c72893270e47ec812647fbb1491e1a6f1b9f1c5ee903a491d4baed0b1dd5b782de56ad4503a8727f78b454dd6b7c27d829ffc5454f094e17c0e39e64233ff4e2de57f4ada7442b32ab421263d9eac72a0f51b912f867e11b694fdb2b2ea1ef6cf2938132726ab718339959c22be16edad268ccc8997ef014b5aee28058921c1daf452915f5fb9846786ebd7097d32f19fa5ff77c19a296dec8c8919f2b84e951e9739ec2afd25ca7a3dd4a3b0109826f48a8a8b7ea12286253e1ba94f3cac07a26a5535208344a2692aa871a850f753e08122b11c8254f5a5b44665154645c5a0fec51519385a849eb230d7e065e01c92a8199e903b72f7840c163d31c88f9acfd2926f5f87f72f964a1e3cbf84d6e4d4d3289b0f356b793658e2c9ea3b0bc79cebcf765d38ce301980327ba5f8a1b507543c1587520446fa32860b09eee552015a4aced03f7ee98d24d8cf78ff895a355a8cbeeed01fee29cc35d2a1b24f0204d7842420266720aa3093aabc9c6d83dea93ec9137f1e2e2b4ff6c593d9acbada32f22f57f43e80a368e2cf73bf41fdad935dc133aa38134c69e796ffc7507fd23bcba21a17e2c83c8fcaf6e10c8ff3117f9e12d8176f35efb76ddfd3dda399314447e79b1b0c6a0c8b50eeaf5daaf0911f408fc8ae2ca22bb725e36bea76647bcdef646524c85b24a223dfd75e1b30ccb189554d32029cb119feb62d652375f76c60545b7258d049e435546deac526f285799e4884ebc16e9b842cd34c659723582a0950e8de7e3a4e008c2116d749af68b83a9c0f55c9a98d7f93a229aee6d03927595fd0e091355b2a1af7c9bc2d391bd256f5310b950d5a6086f45cd2391ae9c5e26957b7ecc3ea4bb64a4d109059ab2b3141a9959dbefc76880d18e78110e0936a2d2b58689de6744b970de4eef9fbe878cfa29919ff8b8a57f8265c20d0b512c32a288b51380c6e529a0c9ddb9158d49c26f6877ddedadbc2cda1ada0d099934b7925e4b4df7eeca51710ab4b17a7ef4a6e6aaffa7ad4c8f70223a978765ef28117917342d73f303954f702caf87968604010b2a20ea53a02ad4d86ac8827d663d67a610aa469b876d11705d1142d635726fd12ca91ba22b2f65ee88bc3eead9aece1e79c4cb123300fccdf5c4683ae1f5cd753fb8143151fc40f1367d156344860869a8a288decbdf7de7b4b29a54c01be06ab0609062ae54e2997744a2ae56efb8c25ed5ad3b121624972483828375b9398125419a3d168f279327042a5dcae2d640e976f216fdcdd915bd4b2ff51cbf46b9335a335d488871c6cd06f0250def7bdd329e7af5acad9f659232816a3634939eb429212c3651d7b12b3f92b568b295162d767cd688d5892d810ac5957c668349ae4f39494fa61874a392b9464f558f2185957bd53a2200a026485a09269cbd64555a30beb4b9ae787bf92fce5c2e259c183f60e16be338557b18d643c10e560c3ae9fa4da678c568bd174cc665d279e1ccfca0a6943c672216dc8588fb7a865ac0fb5cca4652ffac7fbb8f83b85d600b5a035f5c3a04b85e78429fc59f77993ac4ef8c3baaa4eb8c45df5439a75d16a4e68abe6109e132a51a33af34d0a6f2e4e493232d0cf45f318f11ce159d13c45feaa0f6a416bf0f0e03529f0e8b0836a0e4f0e6e561e23bb3e086ab173d23be10fabb33385bb9638d2a6599d9d18b84b891d28bb7edd71819be55913c404f22ba87850d875078b5ddff463dfa17dc668e1ad54eee44e49326cfeaaa68da54f228aae461921d92b4f49ac92666d3b6a99cbc3e818cdc69ae8984dc76ed6555d1e458250b3bf32568bb1205b1788b33a2a3066a563644ad22b4d5b355d5ebce81b14a4652e3fba942e74b62e1717258bb5cab77361b156ab1569c37c629ab69797163a9719f0f5b978faba68f719f50d0ada2f5a8696bdbcd8b2c8678c2663c768d51cb23a1f089db11844bbc668bbbe68169614eeb0f7383ff64e49272d50a48d52ee9454ca5d7c4b39b3c32b2b2a2a2a279b0df349354f492ce43346b3edfa315bcd394f49bbd294d49c1b6b724aba1e80964a7d55721f1742e45aea015a10ddba5b2fcf1e5ba89ab4f43799ea5b9f7a2d406bbd2289da0a4423538835dc0a37b0f6c457d302851a9e917dce38c1872152182aca9d80033e4d9086a080480c52923022851a3f76ad827ea00882a0d7596c9a998ab6ffdd825e7727dd0ca74248bbf7deeb55c9c5d8886b0405c2ad4ef5e9321522ec2144c1125c0eda819fbdb6f33c12d4c0c43edd1684ad86230dbc74ecb841fe82003b904523600b35e010a5862110d4c001a11a7c844d327905120d4834acc085165622a3927828e4d10478ca08f6e9b6246880e1abd1b0011966d8c28a2c56b14fb785413268035b0e5b8e1d361d3bf0cd66038db0e5c8b1c3a66307b8c4115b0e1b0750ab3f9247189c6006187828f082ace0410104dc802d8a2d872db4c187016f06bc021b08a5a3d93e266cb61c3a7690803be1707474747474c48409931f98fcc08489576b5bb843ad1cfc64e2c3a87522c07657ae54b2f061d45438d5759f8a00b3416e39fe49fe09fe19fe29fed9bd38d29152b2547a52d7ed254af7a8e916c1717c702ca9287e2876def7bde7b4c7da12cc4d6dd0d25aeb84db6cf55a8cf1fdbcfab0c3430b4b0831840a470491c08214178678008a253a28c18dc2d6e3c920c2ed20899c1622387283911c30f18128462240e1e88885871996b833182145eb8917300060ba9c40427a1d44d156530b8a4c1f9743320982b9b1636ca2d59ec076de87546f37e61315896e2948d535c5d2327e3d08a97ac82e54564ed45e1c63db120bf9cb3f37415f56acfab8eb3ad1dafb27feae8379f33ced77317fef16f578cb212098bb7eb6ac5766c432adb14529b6d6ddddad75b76e63c46839e13507860af00ba77a4821c9b4d2982ed7581343c6cccceb05a5196d6a60f6451eba193f9a4292a90763c5194b410290a3334367868c18391a632c56434687b1b5d65a8cadc5168b3546ec6edd7e309682086074db76182a68d1a068678707f3f44c00a77ac03d3d328a544beb8877b4a6987eadb5d65a6badb5aa8af1b5d65a6bedf781608a29ac25836a77c67c15be560583550b05d529415365339b5298d9ea986636a530cd19330b73fc8ebe3b83f3a6699afeaa262ae719538a79dd34cd2e08ad0d79cc7a4c6a1ebb5e111df66b7d075b0dcdf61fa9caeac02c2c8a4c69b52fb7225b1172cdc578a6a6769dade962ac544b5438301accf5d59c1a7c034b4a898b7ff0fc7daf5205c1350103961414dc799e0ab5ae096e226b416931d15ac25edc79b49250c9eb5425217fd592504908862ff7e5721488182e73e85e233e6e434b4091393a3a3a3ac2339c6f3e9a21b947f728e7fc04a51477b72bf1077b24e80c7fd51933404029b5d70e913932e7312773ac4d92390f4839927254441145a8a41c91e076b317fb6015ce0787335283548c689153360af27d1e160a874839326272ab0de1213c84878c82d068349ad1162296859828045b3298e5868e8e8e8e8e8e8e8af822bec75ff53f803b7c6f4c86bc211c08e23ce64f6e56ca910aacbd9dbfa8942312802329869fe70dd199bfeaac88b108318c92e99f013cd017f7b77d9b94525a29a595e2c0c9910f44d888820062ab95521c88107aa1efeeee9edaee64491387d97810edbfd4f2f3f97a68751a12b65a1a1d66acfdcfe5031af24981cdc33ef862fd3e120420198300961aa86eefa98ebbbb243657396142c5c66d2c746bce22ac34f5cc10d96ea06edbdbe16ce640263d56daf5511f6c8609b3d6856cbf8ab0b2ed77268e5bffc325c0ea98a52a49bee2c73e4df0c80db513c16eb1c5165bd87a2d0902dd55d3ce7636308e2744f4e209215c6be381bfa8add5c65ff4c55bdab84937eee877bead8640dd98e213e87e0961d712effd0561dc61dce1bfd83fec73a5c8160771977d1b700edb621eec90bbe87f5fceaaee52ecbdf5f1302d08b13e16c234ab036e0639dde6d9fef5ef9766a823541df7a90f42d1712c7c101285cc06206e90f3b16f774fcdfef571589d17b0d3d9baaceba1f86ce983be09772b63dea45558a71616138ba18c5a113243f001b0fdf3eafd5f780d100aada9244c89c562b158a8db8d7563b14a130a8b45f3187d5e99c98886543f56d002d4edc6badd6ea5a865a549abb4b09c58321f2cbd2a1f9459bd46adac6aac8f11b5f6a161bcf816285a95937793a4c3c285f1a265fa9852df582d2c206a45b42a274f8785abc342bec99c5a6466468caec8d104d1a4e0e2429522697edc0cdd5a2c466679c5e88a1c4d0a34412e462e8c54462923d2e86544f3e366e866689f5a5037f1a4a24d1f53b6d46aa79695cc8d095c0d4345445efeac71f9d37c55d6b3174ac25b8b85895b5ec1d53044a4e805e782738153e180e4c7cd767d99174a5e28d9f54f2da81b289e54b4e963ca965a0d865ce922f8432d7b51e54f4443643aec008ad664b28e7c2c244646ac161622d910d4ca0e3a80a235a99c5847be23fbd4726a11b54ce6432d6b3da8652ceda3488bf8f657322e542952c88516b7164b5e71a14a912a999aed89bfeabbd082d688adc06b622d70a1c546ddc432e64d5ae5d47243bab5b0422d937951cb5aa05eb56e4619d5925961b995316fd22aac162323b185e5c4021fb5926f0fc3caa85f3d0f4441be7683e2afd80bbca67e1330d82bff2178d23298558afcf00642a1354a5368cde9a1ecfa2b91d5c29242ad90a035a908edf3a3c5944ca13562442c3995a6e4dbed6f59b3368c367d0c08f32b160b66a563ca91257624cc08f34af3564d168c91a5dd0726d432d68bac150c2bd43298076160605837160c0c69c384d204eec692e106a509dc6d25c38df50259acb19ab7db0dcaed06e5966f2614d3cdebb08a4b4580153242b27fbd94de40146584b8aa095deb1d6996110223071839c020d2a22d191999566be6611031cd9d2442e46e14770a156ede5c35ab4e0cadeaac7458e407f3fe7888e7641d1f2f780eca1fdbe035ee4320df80654458fc14424f2479d04dc2756e0feeaa7fdedaf6bf495c07cfacab3e1e02c9f6bf3e784ee955de4fef3e8a88afc2fb14097d14195f85f771f1fee08b4e69ad36642ed8b4e12fd5b1984f3e99cbaf681e232aa698f2c42c071b82a8369015543a1730ac232e7d312b7bd4b298c79ae7e62f9e293c483c381e28d5ac4d6a349bcc87cbabf0f9c030b1ebf3b8c06b6a8cea5f05988f8b8761a2248911397fd5770153f37c5c6828c9a78e905d693ad311da558baca2f20fa37dc0c8bc0a309ff2f58d105a439fde10dd8c37453734b8c1dde46ea8b0d944bd9b24a47d9afb8cd164748c08f7a07ea9634bdca6bed6b1241e805a3571d65561ca18cd6d681871ba117273c30dd17823e4a6e8860637b81b2a6e72f6a6e8a6e8f779537453e4dd14dd9ba29ba46c5d2a4c6d918acae955f422f29abda47821bd925e59b4b0a44031a4097a117915bd662f295e48af2c5e492daf19cb6b967acdc0d74c7ccdc2d78c26485c41a146fbe2056d6565e56dafc4df740c5a4813e91bdca4affab3a6e54ff3555917f92bf1b6bfe918b490be4113a9fed6f23796bfa5fef6b715fea68b50a914ec4638a258b44bc4a2b184582fb084764dbd5cd0b45de822f8452d638dda840b94b7e93f96101611eb86f09454bac25da59c65155516911af355d7b4b18e54d6ac9a44b066bb7e8c565342336209a1357892b06e40c222aa393c3e0cb1eb8742760dca9d924a57b088b08ac653923d2591a7a47c4a3a259d9286f05712af5152cd188d8611f97409126209b904a5522ca40def4d281921f9ded21eb5ec5fd432fda196691f29785b6cb1854f111380f21edf7e4a28e5426a28d50277d1a7295b0a978ae2267dca425314a4220d690a69535aead22de564c8678c463d1790ec9450cde1f1a1a4798290fcc58342aa0549299bd5d9992215654a0a5773769e98d5ec3335942a4f739f297028c81090d4504e21edfa5fb3ae61cb14cb0741f63fdfdf490278d92a5f42284d1b4e3e7ced3d42f4a774fcde35f8a23ec3107f085ef0cedcf2f7336ace57eaeef1d9638324e8794928c594522156d81866456e9fb06b2b16c2e442fe7d9ed0e3f3bed33c6ad78120f895e5596dbd9756773020023527a53b1212b0809a133e502a45420252e58e6cc2dd67ada55237bacffa84fc9236bd8b4eda608940eae5bbeebb477df7be51e5897a95f76aaa543395bfc4415641955ecd54798e5be50cb757f374d29468483d7dd5c4f1297b42e5d353166ace596b28d4021c4001fa34a8e6e44de9d31f54289f50b59a43cfea116dfaf549cd816d8a42a1503b584a902a47e84ad9ea29fd55e9f67fe5f429eca2547a9732012e34095a48559edf4a797e79a3ca14062a59acc82a4f42cda17fa252507f4abd982a5f44287dea6f943ef53d76a7a2cfbc551ea54fba519fd25ecd0ee53df64a4965406b4e47b603f6e9a4c1cf3acc207c8f2dddf713e8e52b7790a091d8e12efa377ccb587f7e2beea59698b8ffe7bc7c9f7fde7a27dee489244931b000d7caa37bef45b13e0f20bbbbfffdd99e3ae384f506d0fdd7bf4fdd6c55b362dc9dd1a75888b4415324bf098909893b088a3f6a0edd670958687f47366bdfda897f6c2f891434d9e6f6248228c1066dfea21f165972001e655ffc347210b4bdafa40d4adaa0919487fc45df7bfb9dd0fd57da1bac5df3570958c86a19f82526b22e98289ccdac0e26fabeed74b6692dcf8c894cb40f06b81f4008f59d00f5fd63f890fd3d06103182c8feeee58b6aa5735095a7a46dabc8dd1bbef57bc330b4ff85f6ba75fbf7be8ed879f5de1b3efefeea30bc37bce1f789e54f75511d23dc9e7bc30afac084859a2933eeeeb2d2f7d452e9f4c75b9e1410b125bf3ba1c726bfbbe508bbffe5e0f11282ffbee557cd3229d3af3e432c4f9848c72328b5c1ba92ac209217f257fce2d70a82fd1bdeaae6ffa0d429a54efdd63e1002e287f533f95573fcac45519ff2bb2efd29eb5bcdb1ccdf634ba8f1c3d38761b8f2a757d1e7dd2a2a2adaf4272dea5bcdf0b32e8d9f75f8a692fef4688665a971f937fdf0f780a298886882c1fe77034316c5b0bcfea2efa28d0efebc4f1f87cd16f9d62efcfb11c08625ca86864c3f7cefeff6deea17ef7d7fab3be3abafa6ab54fa7e63ce05c9d5a438eee458a26aaddac8ee5ddf5b8123dbaf6bf2c3998795fbaae6d0a7ff81967cd8ee3e2c75e1e35dbae4fdeecbd3ff2c01b6c9c79824316e971eeb1307b64db05d2acf1c1b973cfc79dc27ff84ed8efcd3cbdbfdfd51ebc8314235a9c6a1ebfcef1d99d0ce0443fe3ed767a641f961341b6e7b6e7b8ff5f403221082b74f0b6c7c428ffd40179624e3b73cec5ffbf575ec0a9d11d10404df5b5617ede6e14f9f3e9015b176d79d53edbd7fdfdfb86fa9f7d8bb074b5847abc6c14aa44db57d41b4995ce83adc75dee1af6f3bd7d8f3f7eef7b0f6929a964f34e87ea0e4076abd74972ecea826fd1630e083884d9fa506f9846d6ac2855593ea1722c83760c2020a9b3eca636ec4a66f4ac9272c17a9bf29e6e1b7275b7ffbde43a6db79b8f6baf2467daf3cfd5afcaeff2b61d6757ebeaf856920c34af78a9342a4ef2dea4edd9d3a0c6fbff75f42144db45ad01492365e2891fd45d32c3cb29dd2d938de71b4751c4767299d3d36fd991bdff6dac49ed556a95b8c3fb841f78cce236fd0fdd1effb1c979cd6786279967069add47330f4ba10dfd08661a5a1b34aa704368c2db36b798eb069f9b9c0a4c30b59b6b0d615f9d62fefdd41b665f98237dd3d768f5d03c73366f9847dad3957a4f5039c19e707bb7402c40a24102b92192801dbfe6f75baf7209a6cff5426adb687d9f7097d36e8505985589c107217fd8f529adbd4a935627b82641b12626492c1bd5e777789e20e83e97425b5dd1fb627399cd00b3426d4bd627777775b8776c52c4bf23b922cb69341ee14b6833c03c7073d3f23e4d0517b6ce80cdf9fe35ad0aaffd5347f466dc15c2892ebeff78af7adbabad581c196d8b02b45c16d7dfcd67eadd65efd807bcd9248b64952b0ed13b6daea0405571c19220765adb546830a1b4175a9413ebff53fe4903425065adda4cf82c5ce39f6cb971c24b80408897bfa0f850bcd5b238bed5f082656102df166013a63673575d7146f4dbf9de92e59ddb968ea2f5a0370fe56cd8c56bb6b487575a58b2876023cdbe07718d38c58cbca076fc9b2dac5c6f7b3ae981818d7906a5610c4ae221791cd4c859ceec1ce068f38a3d52b1bbf781999bf3fdee7c5cf8f0b6efe08559a229aa29f21ebaa43e20b8db30407091facf7a1c2e753c4041380b2cb03a9f67d59bd0aa6093f4356e767487521e1b1d3d7c739c2632a4e3cb6e231d4d7c731c263a9af8f5384c7589878acc563aaaf8fb3c4632ebe3ece91c740223c869578ccdeaf8f2384c75c622fabaf5400276a9f38b4983f59368eadeec47c7df16748cdd9c1ed73075769add56b57ea7ea55d44da65832b04da75836b887689c0858376c9fc555fa55d45ae1c5c23d02e222e1d5c4554b48b04ae1dfc553f06b54f1711cb76b1749117da2573d70eeeaadfd29e8f9337baddb988acce0e92abc8d677ede0333f66847e82acceccd00cd14c908c241955c8a8c96822c326e3898cdb8f0b333e7e846ace0c0a34455647061419538c76952165d7771191a58cdc1299c60d87864bedd6853d4023891d5ccda9bf836477a4ec5c713a7790b096b5feb6ca9f20eba2a9d118d1e0cc708c90ac0e4d11ce6b1c221c213843da839c075554d383240fb4c8020707c707ce0b99051b548b6c6636336b6354cd6a63a364574c82a0da218d2838b41d8e5f1fa709ce101ec36127f11a3f43280eedc747d581f9fa3f4130dae648b5f19536b3961538b49af37d7d1c25383558924d91c7c8af0fd3a2eae0f8b099d114d9cc688a6c66344536339a229b194d910d4d569121d4107bff9145a39021414030c4fbc0d4164b1c1a52e4d366f6e19021d40d7ea73d30a44444bb3e481feb4f0ffd04d11aee352706b2e9535712643568f5b7adf67617a325536a7c5b586ad84a4d29d48acaa9b42ab194cc5eaa029a181f3646413bd0fb28052fbd94d27b29ed3a5adabf17bcf77be9f9c1b8553d140c5001374005fc23c280ade3fe6a841caa5a75c6f1bbf5f558e220d7f38ed5aca5cb088d835aec4fb07dfc5dd781401ffc1bf7c112fc1e1bd4677dfc62edf179230e7a1d97b2f0c372842719071294d64c6bd64c5bab79556cba4df67adf83fffda7dfa4a19ea1b5d6daffacadd6ba635391fa1ef8511918987192e9fb5f0bf2a8dd574500ffb416c86e0fe3ec75228b4f7baa48ea1e3edf88811e3eba878f9337e8069f0263f9f2816e5f3ed743f1795db54044eab466ca8a52fa9363a43d47b83badfaa6f40bf507ea513b81c172865d00b65da4f688ce5d6c0d5517e2e8ca9e9ff03faff32ef4bc1e15adb1a22abba235563fd5aca58dffa335f64713b1c55f19963f2f3d2f74dd124f02c14fefcd2e2f469007e0ffe202b9e7fb520a32dd1a03f93d4908360de1f49191a54f111e2594e04964400741fb960db0506cf002bd5f09fadff0ef0dc3f0e6eb2f5a9e40d6a25efc2c794384effd6ff87fa5dd62795230fc4f87e0f74190fc8f1de3a8e64f8f36d2a38252690dc2874dabb882e8adeef3fbdfa7747fd0f35373c2cfa1c3526a677c945ad4a6efe995c7e214a21d81eebe2f2188392abac4412e89f737e9d52c5d512cb1c8f5c727c9f2a47b14e9586291e98fff5e73c6f14fef7b2c4fbac9c75fe9abace8fb8d237db2145fe55fb03d8ddaa2e8a40dd3d3cfa69c5f14ed98f5e9809def03e8a66f0261d4be3d0d80136c27b3f818e8ee8efc91d440779f2a7ff5e93bcd23bf4a3efdfd938a4a59cadaf73de91239eab3c71e45919a4a3a6bd335e91efb62f229f9257d3a60833feaf045907e106a8fd99d76274ac4b0f10c24ec97d65a7badf802ecbdb72a8e1f2cf2e934fa4eb3ee53be14a0fa807f521d0fea9e1cda477ef7aba28e3b12bda54a92857230afa480f75ff97d0f963d7c72ad2ffa77b873d86301fbaaca7aa5dae90c17d15a2d35479841b6f4ed57935293522f65f796d4863c46d951ec8bb50ca839753b212201e846673ad8e7b84faf8d42417eecd37143b97dfa94ea97097d6a5a076ca04bdef0289b46d9b4cc3a8ad8d23fab83e3cb385e901f47add62a9214b6ad600656d6bc8944d5fd96ee25acf6fd19b2ebacea99f70973ec30ed7be85e9a13fb8a44dd13bf1577b04d33d0a56e56d3bf9a4e9a2088a985fcbb5695fb0b20f2e934557ebf7f029d4036e3e771bfd3f75dc7f821d38f8124d3f70d64c910aef711d8f529016c99e9c656f3b8efdf0d4055aa6c566520df5ba2be27ab7a6ed868e34f287cfb609c1da884edd7353965340300000073150000181008068442916830cef254543e14000b7588506452389646235990e4300aa220438c21c410428021861084a8886a000a94ec377a98db164184fd2ca107bc803092e20d8afb601d4a1831d5f538326ac5ff87e9b58b9af2dd0282cab05aba9dc72a5ba24d06ec72cdf5820c1ece49e3510a2a430d3dd286cfb5a2c8a5a73ecaa7958dc1e3b8a5a71915079d91f2435a0ccacb949d9cacd2e9b82a295e49c69c5dbffee974187aa3e20db41a2667a323a01c281e98f5b054c2e4bbb818f797a5e01e05b1d8d437c6f1c5671114119245d029372eb8035cecac51a41986fc22a2f3c6b27fb1c71c8b930eefcdcb45c45f1c3eb1cd9680a56a998938e5d9542aa73c6dbe10dbb27c4f0afad2e77d2634aa408238d5a751e9acd25ffa07b29ab4c0aa8bc2a14fe11cc52bd4a901f6fe5ee1e4c6cab29142478e4c83de2889de935dd6d3c7135d0e45f06567e33fad05c5e792bdebf0ca19cd6205182c417986a3286ed6b8af8d40cce5dae75615f9932c10c1701868de00b21fb7aba3f4e45c36830741d1502a2b97be6f36457cf96fbea3407cf354d7d96574a9a0679700a230d53799049f9d6f70a9bc2a457d49edb60905bd38892ee88a2afc3fa0dd39cb576033cf47f2d9ea70ca4e9e4f6ab2e1f15b5101b53d91ba3dd9251cb4eed1098d9d445e55efe08af264369cd9935af54e647035f32b549177afaf3961fc934b2ac0b77596b5de70c56db73650915937f012c7bebb11390f21099fa53e745b03b49c9b2ee91394573a0379c4e0c2d3a5c52f81e3160c66d70e0dadcca2151dae51da25aaa0154b38b80134bd06ee8b834cdfea52567f65b2f235ed5c15bd91b32313c1a05d51ccd18818bc9c41119e7c18f82764aaac8c145fb0f508d48a6293aa7a3557eb9113ba7f27ea2ad017b074c4deda824ee165a8f00e3c24eb160a7c7b74ce2dc4e6455fbce00125151ac35064262a36bd5bd93661b2a2d35cd717c8439f22efb953ff6b75bfaf5da1d51e1eeef6bf81809061ab369982fdf98a97d0254c8c0501aa0aba290884aca49528a684f14b17f77f2c25455a6b2dd4ff681e08d13837a0bfed743c370b9243276164ca137d171dc5102d22b6a93f1627214993c4393ef079164ccbf58a640771c3be274c908cdd266a1909acce27e091700171e53ccb985ecef4187997c290c7f5ba1a51846d5d0100c0a63804695c51dcbece06e5a0814e17005737a06d4275055a0b088d482a6cc637dc6c58fda193845657584da07478d52bb3ec623431ac18d487633ae6a611e90be9d107bab8dc363d618df2994c7408f7e1d9c1121e51f15aebf3166f2088530d85c550ae2d5c85cd834c0ae6c5b711c4e4e22d74e7dcbf48d4eb3443eaa1e12d2cb920fc4ec22941579f082be1f4af184dd556dfc423830fcda70dcd5ea8dbfebd505254a5d914b007eecb4051f747613171626f3a8ada7d0e201032726dae64694a57177b757f512407b021fb8d0946747bda9b08566cfb569307279fe2236d0c4d3a61397aaf1cf1267c7836f3f3cbf60c78d08ce7a454952125f63f9f15cbd0fd27aa4a58d2256ffddb05aa6d4feb506a20ffe9f846b1d7900c85a306a8751ed40966b9924fb6a04665e35d5329667ab5c7c32d1511303b4381e60104abf920ea7bfc972f70be16297e32cab58367ff8e2a955aef1bf5cef353e72606fb210ad4d723d8c406edb95b3d1ef87af4b2936a84323c2e63f77a0543371f4649541dad05d1636a5139c4420f871d3d36654bd87c6e1722aaedb69ac192eec761f75fce573e8a22cd01852580c92719f0f215f477523deb7f5c8213ac41b8cf55c1709055d3b6a6fb8c1232fd0d45ccbcb1f36843c091229233fced0c9cd6de12200ce41448001f803c41e73099f72d50b250d6631a6c97f61e049233b27c8c5522f169c5a8218b8c48c1b9a9841b02325f2b6cd1d80fefd6f668fa9fbdf587414e75771387e0645a57efccbc64667e22d272776a44e89141cc1a6a878b45ae74023703afc1396018330b77a05261c26d3baa84342859c142c242f52f53d6944581dd2d9ee9de82412ab4690fe61bae6003c5302c4e0b401b3302bccbd65843a087748cd707c8f9219be551dee5623d4b00cc7a978d59cd4136135404f39a35cb8c53dafc827df415ea6fb5d3ac3d1f7d03bc5862c5075e05967557c6522ea35797e964d41cc7515a45f83ae3773c83aa1a3988c7dc10d6c60119b68096ea7a42072731eba73814b238b7decf8d7f9ad8e506d0b25f553c4819ea108a6ae57972d417025e79aa5ebd547b29553b22e090c17e1cf66e48dc6faf3f0a24c37a54482cd3f331fd1be850abd32bfb9a764407fcd144e9731cab47495eddd91301bf3af0242e857beb8d2e35c09af5333386cd813e98b84fee3d9c0beeceb7f341971ba41986075a159ef0d3d7e162fb6358642deeabb3212e2ed6ca903da27f273afee07721e7313a441e0502d5303e268bed0e0d8931c17992e6423f597a1e661ab8f71ceb6c8d0fc51feb20d885192c409bd7b0c756e11ac3eaf82d8d8017cec21b52e35b6496687547e777e300cb0c4389cb6c24325e0920aae4002687f1015e24ff25476f3c4727608c24e0b88a2e7b4a70df1ffcc66c840d4d6aefae3103a928e60c6260a08a29cbc136680f61e69eb48b83c30a0284c87748fc9d97ea4db5c6c78e91182d66baedf978f5cc08af5ebe6c5d9650cdbd21fc4f508169ba65229cd999fd52251b126bddbf416620a8cc3bb631ce880ab3c2f4164e95e1cb6e00a35e0a815a81d1fef6a587b403e41347e56907495c59df1c043717fc6fa8e24cb4913088d20ec5b6ed28de2acc95ac65d8ef8cebcc2800e890a1f186eec7196ea04f478b6317a27e38d214619afaa8b9d54b5a253af62230e27636edccea7422290a37548eae1feae60e2036cce62311c29c24a84c4b6d99053a4d7c903afa9b2e2760050c6b905b2c36a46e9e026fe372341b7602a82314f6e8cc28a41bcd4ff9c09520760ea94e638060c31d7a25072348a232de7e6c63d126c0b353b7830364a57a0d90569a7045058ff046dbabc1b9293103017a369a44aa8529642049cded9d46a00e50fffa08fd4d533b736704c012f69ad6bfef1817726f6b21fa6bb6ba619d9c08105c57b13bfe1a513c883e108a1106ba73cea5a1892b80d07ac4659f994154a88b8ef01028f01e05306170996bd3e52eb1ca3447693c5584e89f20b36453d11526f89aa707d5da65621ae36a28da0dbaab04085af70023fe769760d661f5003c074470f7c69508f56f9af92cf751b4fdf128b76ad7f71fce169e67d9fcaffdba3ddaf880e64aeaf24a111c0c87e8aaaedd51d7b27b4502e33b4afeccc7e6496ea5952adb80a5ae5a178f1b6cdabbe93f32d15ff978134f7196301d401463d6616630a8bb4d18c3bb66671081176a38925051c4f5f5c075da68b1eb4e7046f51f3a14eed8257714e0a8c4de9544cf8942a40ced808d08233001a8751b248186abf30a55185559522a403eaaca26c68ce53c06862867cd590f94799a019e6dacfdad319574cda18e52d4d3b3834a1fe6cfb9282d3805582b466e8c05c20c97c9645dd8e45d78fd1e005803205688c51b9f145aec3372e66fa53de2688b0e9ca1d4ecb03c1aae679ea07b640e21d57546c23b5ab8bfde38e4b3775ea9308150a9cba3e2ef9479758ece2aa9b834462bed857f96e4f60b367c6d8cafdbebc0b33f48780e9aeee929d1d44dc86316e5a5ce2f22f5fb161c6863dca2d3610007d0d80b02fa1e5a012fb7d7bc07a6ccd81f155b72945a77883f4cf52bdb4f0c5cf82e0c65494e2ae5ece4d809319b8406a549b0a91a54e6a950097405a1115e4d68e7cf3f879425f04f47b3d466d752710c0f4d68c80286d7a8a46f62a0cf16acb1e9e6c6e1199663806d3cd903d8fc728fd106cc027b992b68a9c3592cc19f0ffa2e0d4f75c3a78292a183dd3bd51236d8a1f6e25302a10ca30e368e19cafd0d677c1c8f682faaf933d17ed823680aac9ee01270887d10b7b79a818e986bb2bb7dd10a0ac86494c941dcd05dbb28181f6d09d90fd655ec2d2f81139ba5b80af877fd2e0be8e6ed62a09c5e08d7bca5a5338fe727841ef32732cccfa7e7eee31c8b6027f4c7fe5bfd0e6631504ef0e117d147528c31cbb4325d81c10285ec0380162346ca6984301c326820228f80442414342dda2f32d482500273401c9afb3095f172f834123880c1444a7248539b132307008e353b33a80f74d118406dd2078b593b6f744361f0799cc566adba3b70b7bb389d59b84294bd3bc17de327a076087b3c2d89b0de0eb2313d326fe86d14f5bb2f582e1c8563ab3f64b6ec8ffaca352c82d5c3eaa398c0652b09a5fdd92e90dbcf2fc79173b56e0814e89e965c466544eb36af0b1e4bc01a213a042d563b2b55540ad7c6928146575ce1b817ea151c8cfb7ce0ccbcc52b344ec2b4df43122a1a806d77fe86ad165b403c9eb3ce7f3dd123a37b1a7b120944afb9e66f1e573c72413117e52aea858a1f13cf10ad9ff85689fdf2f2e1af939d99f71ed8e46e264228ebcc61c1043c9189f8fd583534bcee9bc003443bcd054aaa22db0c8c840b3a50109a49d1c2f79f2f5be1e4d0aaccb1d3284bdd41cc54ae9e4adf876e35a19547695952be2199e7dd8104eb9549c355e164d1af5c67b250f67c8d8fe8d9aaa0674eca7b4d7d573c6280e5218c01bef7700abc165d96d7f6ff8e0611d6cdc76c222ff855019a05f7bfe475334db83d6d9ad56f085fe80cd75407b096560684ac5e19b9fae89cfb548132001d521fdefe2be2e2ff0a5f4ebc7b5e49115ce805eb67004b121a5bdab8b70e45c475d3ee60bf1e33b01f031b76f8a89c6aff35c2b35a89190a171783ab7137d90ede2c07b10905dc317d07b1118834aa4b40f3f576a00da5e3dc3ad647400a27c0e3e95f960908740f246808e716885d6edc4928d575005e00b42380e663d3d3823cb7af743decb57c63a0b88cbb4c4a5462bd5f1b4cc0915111ab7ef0ba70a703a184f31808acd80e7c3fc10cc1a540001caa38d4272a977f3eac5487ea1d4e093fedf7dd82ad7b4de6879dcf6524c5362ca3756196b83ed8e3a431aecc77fdc25a64847f75785b8fc85e3317d554785719d5c877dde3616b15b93b2702b74192d7278cb7929851abe3168b73f31fb31e4275db54438f531acf45a0dab100a79eb4fe11050e8519a128d91c9c30873cc91d9ee81b21e4756363eec3b7e10b2feecc4c285f64061984e35e5e06be415d3428e3576b6db261737720a2c6d78dbb94778153640c7a21eef50bb2ae67ba1bfb1d07660fd597cae1288098134e1568ba611acf2755a964b3cb117155b491764c9e2c62d1138e4ffe820753e69a4f9cb05ff920e46bf185e16e8ba220a37b8124da3669b1a386a0619c07e3f3a03f84a568d1373b2f63be859c964bccb9aa17541611c5dfefce4eb5d33bdc0281ded3caa065c1a2e83323a3c4c7887b07a8e6f3564399b4a8e5f6e4a554b029a166a7b8c88e987ebb704b7f3f4522c92af1860285fe84179096b732efa713068bf4aaf9fd9fd16b9f79dd253ca3c4ad9372ea87b92fcc8985086be8a94efc9ca87ce2535e72a133d7c5c94cfa9930073dd90d76879f94918145fb3a680b0d434491c857e19698fa0dbc7f3b2486b0168255a68553326751032b12742c8ed6d9311c54dd3fea4683cb2d6548a77d323f51bfa212f271eec42992174335c1a3764e572c25be136d5c97d528b23fb868df00f7b0e7a1359a066a1a569b8625bd42ce7c49093ab119f142a984d07d0acb5c34784c4e82b8bb0f360057cefcb93812895a3ff61f8746f89e576c354d547563cd976fd102cb02b617a6f103aa597a9568221802c1d5de32f7eaa212a7987e5d98e8369fc0b94382901cabe7bda11c1e0f3a26786f010f2bb9a19c8e6d16ec5adcf7283114324251b6fa2b23e7ba5c3a7c8078c2d27c0ed2f69e76a4a65d32c19811912b6bc52b5971dfad11bea9b0d582a28e2839105c4455bb5e18227a17c150151a877c02cac9544df7f4af592d951e1562603e5ba8f33ffe9a06307914158ddf0adb1e8424b5863163b30bf95e94545f3e429256342f086be13bcac0694e3c58a287a01eb6afd0d56fb01c06443afa1f54ae70b1bb102aa2ce18043a0ef3af5c3b7b2e64a9f6921195cc1d41b31281f5c022fc97cc53a963024963394bd10b5ce19a9f30ed9de99e7fecbda8065d103190d3c3e2f669f56742cd1f4094832aeb76bae55964249bbd14bc96458a36eb9df492e1f82ad495317bfbed7fcbfbc3ac742873fc4d58ce28bc39e6cf8e6ff036b6c0119e44a303bf37b311fa97026e90e7bc676c9c31a579801e116388ff6fc581c7b673a460041e5f67192a8dfb59593e3c7a1e946003f87834a4a424d53ac31487f664a6e23ba313006f6e02b8b85c4e71e85ef5b1c3cb10888223b2a2daa841f1f207aa8be749517211b237daed9daf58c6b556f7730bbc7b41b30617875f91de932dc80374e576836a2790131db99033370f29948ae16730a90a2ecf02d40980be967de3b6a855cea56e09d7d09f8c948ce3677e1f28a9ed399f54174e360e15ff451a580fe1c928057d60bb00f6dbdc4f40b194c0299c83af540dfc96666179065ab7a950061b423b570a53462e1b1b34f722ecb0913d0e3538a8b390b144eb0375ce75ae1c6c8edd09d6393b79737035ddb732b0f4152fc0687c70b621c77077ab1754573cb00d5c50ca529063242e97c70ecba8752092dea05999ce42793ece5c1d09ca62acac7e712c515b11b008246aa9647fac6a1e4cd14a57905e334f8e6b33c0bc7d19db4e630b8f82082b60941f2003f8cd99a7ecceff90e967e4a1c6b331acb38f79b1656c2df205cb62f76a78cd987b510f5070a4b51e048cd4375b4048929fd25fb9175b96855058c415cad425e0e8a15baf94d141f848689139700137a0edb6d4f9511f5b6f79bba8f7cf5b0c19f6419562bb4d95824e4f43953b17109077377d0bbfcfbb70ab88579693c5079b50fa8c336b84a11121bab47ff03d15221efc6091ddb4768ddc40f3f589a82619dd18ffe889800f0d9e2ba446761473cc5ac5d467eb40847ca4a507cf6956f85a72c39723d47c2735d97e58e41fc02336bf2d0518910916a2606dbddb7eaead09a3d60b0d98046e3953a3c88c66bc032015514c734f0580d2491b3d7005c274340b6b56ea38ad1770d062ca8871c13318c84ccfc58c3f06e6cf918681f90d5c009fe82565fd1381aeff8c720111d748e4182a7eddda1909439b59f3e43a1345413f9a6ec1dcceb41a818e5ca247cd5b6e8705b2cd0bd7a7c555968ce144b7c2ae647b6f34e8ec64fc886e850ed2b84507510d85c18691f74c0f4adbddf0c802b750c087e447d587eb512af4ff50191d96dc466ff4cf92ad3cbbb29b958d835b12fbbf21903e6e7f345b7d83bb8f98b426d27d6d1565845eeedde10f67a911943124c0ff6a7a7da47b52028c00cdf3ba7f0063b30ee682f73208cc2e0f53689fbf6672300ff83b7182a6300095bfeeaf33ce6d9146180da48190d7c30674c107c69bf0a2afc170ed44247470285c30836502ae924e8d1aa19d19c78f2e634a0fc3664ddd3439f29d7fce49178a1768613370425d023c2bf6b2ce36167c86f989b6cdb51c4f7836e719f5b911905a67b7e7f3abb8af55378d05ab7e839455a33266bd5b99ec9c2a8d755b53259584aabc400879ab10f19d95cc93d823133e729ff8c9defc1b12609277457654d7f40f60ff87bbeaf651265a9dc02f05e460cbfc73d5a80486d54664106dd4e97e29dcf46bd29ad47fe9b65ebe74e5d0a4f79079295563e154f266ba86ca38aee6b94d9a25493cf7568344668259f5a9b816987114dad41107a24935458043a405ac0a7789760b21aaaa3b27c62c9d4ee72dc67e8fd4bc0d43da362f5387fda26a996ef9993573ca61b3c0d09b46b06f3a7656d3e5181d376956463885a039b67e41b6cbcf7e2ae0e0cf7a55cc224a04b8b04e9964fcfdfbf06828ee47f92b8a42f8375aec202423a5f2c4fe85344f144a5274e8d64b8359c878a82eb11e77936990cb158fb0731626cbdaa97b18cb15b6b1940a9dccd7e044c26773716c40a9585415e39d6a87f7afd78947faf36983a5e20dae98769172ad1d0c35e1529db503ebdaeb264e60370a8318999f6561a067a2bc9495f7914a6e015d350be4d40d1d4f328029574bd2d8f22d3eb00235fb7ba91f12472323ddc80d386511660f509bfcac2bbd7d16e5a42b5c671ddeeff40b24ce97285b02a63057dc5e635b6924ef009753a728a9a5e8a6accd9aa6be00ae8e236d94dc9505c2ea5aa9cb70c2249f42d9323b032db001193f6c849a3811778d1a44fd2af62cc9335c267f26f9c5f747d5473c6f568fd8323f16af7b0a00cf327df20c255de8927d09322a696300b24101abaadab873f6704f8185ea79ea60673ea540655b0732001b6c14201f4ee46a8eec62996d064326e81cd08b5d105a3ff7fac1962520b96d95ccf0ed00350f79bb2d5c7b301a4601b8be3156fe66574f96f64043b0ebbb550fa41c092fd2cd99be3aa808f9dc94261421a91904c0990801d83cc2f4d1e413d67a654cc32a18411d2e505abcba267c78f2da5b720315ed2582c0af33472e4cd4b1af5b1c5d2b9425f6588cb36d12081ec1b30d502dd1f74642eafeb5c61dbb13fd0f99fd7cb0a5eaf4636e8b6822df31c2d0fab0823e09e7e068961eb65b5efec8422a03a89ad8903876ae290074f4d6e647c35ae866744073e985df6379b188408f596efcb734af6d090f8e521c4680eb418f1ab9278158a179c41e1f5e079322eee61241eff277a499da34161424e088f018599d26e0cb8f15a99c20aa6d91b5a8ab133d609ddf8bf6978d9b669f69b65bc8c71e24b93dfee4698536d007fd6ff4305d55c8e9749794c005c2255b554f5fd50b443014586eab7a364d38c5bc7d58e949409b6a9a06d71b0845ef35772fc34ed5f4a825b132d5bfb2566675bc23080d0bc1edcb7f71fb80f3cc88fa048f2062f1d6f2c91a233f9bc7b7b3643595c555bb4685f9ebef289e4ed5be3e4a0ea2df843a8fd1a4d804c2fd7e54857bb10323954483ef05e37fd7df8fe6a0db48e5ec89066da212d41f082b7f22ee98f40caec97ca9b900ac210108f8654de1e03473b1ceb88ba394ca5771fd166b5c5874326a90ae9bbc286f535fc9a9144ebcd7e86e18a10bb3276182e0514c25247e62969a760782c18b519cfe179da7c9c1407e12c803b9ae2f8f8a7341d45431d438bcba416b500af57c52a4024db43e264f901cc58971c1ba64a504f5a59168507520d5c5956840b141b65b02c3d4caf957622abdaaa5010679a23365138d8e068b20feb4025597cd42e48ea653eb2d42bff43a13957cea87e672f31a6b960d4cd12f9bb8aaa229582322ffe794a52f204a342b6d4717ef1f6b6ec80eeb2968a9be008be681fccb3b6d3464b873a20be208c937c9f3aa2f20a6b53689f1cc79855bb20cd0c66b1599f396d3e8680fdbc829de18b1778e3ab96f300a5133b49ab75b17db682bc2c204b07d8baa99b2256281c36f8a512ca134b16cfce89b863fa4b0a446f45848083dc7f2d866b283f468083d90495032e9f9b8991f61d651af8cbf141219cfcc666cc77abc88fd9a359cb169fc8cca507bcafc398c1b0c2eacebb42a6cd623e4397b39b73883871eaa5130550073ec3305f3a1a57a3013990e9cd786e1b3b92609fe893264cd877f000e2f10452dbb80696874e06f2b2098b880497421ae1881f4df72f3ab459cffd935b898c9ced35dde2357031510b7044f4c810ad0257ed97b13f9f276786f2a7a1508f4d9c5949e53ba3fc5e91f05ee43ea12d2a6a5da90582623f8c4f945222eb0514be85266771c794d1601795b1ef0ee94304432eb181e8159a93062cdde594658ab96cde40fd7f2e5387cbbe398e28f5ef2c92a1a03f168ed37074cecb3e01ca5d3d279137bd77849c70913b8c821c29616a154ee8b412033ba2c8fd601678291be8e0f1e800dadb78d97e8caf19a1bff07bf0d18c0bfd65471b816e5fb720403c1d6832c4e671b5550ad4875c5f92a5c900039b9964cb21c45bf1dd2d23942d6d8979a596fb9d1f083b8527c4f91c1ae100b971698c26a39f684374f92b0361e56aa9ef255591739b2e95c8e9721e43e42c42e171766c6809ffed8378494037d2a3c8d5d26d427b6d88198e3f1c77afed139d46ec31be10c537af69b4ea6005f008f605ebd50b750ed78618072ea6427cf9850705d8e15220573a6da15cc662537472ef78f15cf1cca0a6226299dfc1e3a9c6087d1f40c15d28dafca318ba3ce7c90f09a7ea62dd4b932784255e477553e2b11d1e7101a8526696cc7b68a341e0e3b6cc51e4c71c8c3e0f8860141df00217b784da5848185103e58bb1436f54236477f52e23dd8d218fd50884a51e2849e4d2b373fab497f8f1104cc79337e9839ef7f1be87712c41baacdac501c7f04e5ed3dee9a9811d6947bc6b48b8cd01419118eff1e3c080e1e776eb9af92648e59711e52da58248725328b18752a12d6f24b67c96a958c904396eb6c130a086c15d038796b7c0cfb00ca4ad8aa54857f8c70aaa41903bfe5cd2bf4d5ddd4dd308d5b860f51277fa6db2e80341d80e1596d5d7707b2dfbe7eb86559073f1bc04b547034f1bb424d5eed660a55b39171533c8eb855dbb2d9e1c4953c10bcd7935f0cb7dcc91afcba2ed9f2d7b8c40254c5da56d255ba812372305c5695a2f89b1069f22b8c07c301117c88376b99d9d9d88bc25b303cfd2de1b33620558eadafbbde0ce60adf8e1d9ac40ddf423631cb59b27ff8e2a5d399239278a96b80405ad3c693a81d5a62e855991b79f593e21f5eef32ad90b3884ea7eb3d985b629b4b1e02caf17cb9bdfc144710f33a9fab8b9243079263725624d1f95a22aa2e34804589f40889f32ab038e2b8d0a878029e29b767fc34726da2b04e40f869b49591a82656c021968d222c45d3972ab0fc0f471a9483cbed38ef4f382880d817aba8ad801530457c15dbecb0f599d21939faadba36a26f6e2e986280bf1e6833ee9869ae3cf2e5b9d2c3f6441dca014d86ab154a13e1293a4498b84e307ce4cdf124918d6b9b5ecd2fe84200872f74f5546e74afb9532381f82fd04b9fbab513e1e04c3030ed7363b88ff9b3b30036c107db1e297db2e8cb723cca2fc8656a35751a6db3128bd3ca7ea862f3d01e05f66fc79c7312c159974d695b5c12e26f10986b47c89f37929e7a945508b71b4d765d8667c02b0cab3fc8ba6d2869983dec07ee7fc49c343f36b3d8105f8283ae3fb980d317fa7dba838acfa37f5d7b3e7c78efe359faec2a2de3f78a403d96e0d8a725419ca020a10d955a18f585af487ad99dba191114fde62919b90da5ba7d5cd8ab1612b05b1ad78e365c1a4d71d2d7a5ba9cd9951f0f4a774a5400951d485d36577cac0a92e4f40ce0203afb80d45888ad2f2e9f08e526eba9303fd407bc393ea9f3d362ee935a588c61daab27a0ac4f81100e68663c849e0f89e85039def13970094d8f9828acfa45492d50a62f3397db0d06e4834df916d6463efa911faf87aa58ae8dbf7a108e57cb470238b870f109a43202a21f085e12fb3961b7ed7b857da9f481eb140a1109cfad61edaacc9779fc3df9a70e87e67834a1e8d6544d8466b463aea4ad680b3b0942c22dfa02f487544076908bde082711b005132d5eac7d5a2d07a16515dc9057cfd98b02e4fa071b8c9f7c3b789ccaa96f0307c4eb727caa7a88e5f38a58e0949cc9894076b63a4df18515dc2b06f4c789d0c8592ef1163d1b6cc5f95e0be0c0f5673aeea38c6fdb0010b77863d48b466700e25975960f6838c1717d6f03b309ac80e29d6819f45e2486cd709193f04e1ad1283d39e9371ebdac5c72dcf54778d48865a099781eb9c043763ce5f58f02eed11f42151083e8baeca35b3d08b5c02973e368bbaedac239b61d63432babfedd4259c2ad3154b499076739e006f54d41a4fb82b3f02afe9610e567912c6d3f18008bcd19bc02690074c3c9cc1d73b107d7a40abfcace018ab8e1914dcd076823f712a345f870546bb624ba71629cd2fc908c2ad109c1c43125507efd732bffd97bc7e2b782722769d682123342061795f0f11f4cf13d18272fa45db93009369889ee210ff2c091724d2389ab3aa1bce74c22b50996997d20446d922d497c2fe38bac679ce1644111114c127aab1a3a3593b15a16aff36e9f12de425a800442e5c7c220f3099f3e0609bc3a5363114bea908dfbefdb2789e71641f7299e32153371631aff063a7a3081ae44de06131218286929e7e11c95e7ec8ce86b1c4361e044e07b517e6d224c85f2c68dbbbab0bcd230bd5038842ec31ad0e28c36f6e1c802e013b98ccd471af9eb14912eddc99839f814b4c9e58d59545c20c4f36232fac07b5c0db3b8393aa28da48c581197a94d7e22cb1827e2d33368257da6d9da04ceeb699a8b0a4a050dc2b0d4d619defb9f472c273889c2f44873e5aba68f372365883deb7641dd576807ca6778eed070dff6e1dc16b915f6715f931282e8aa6b1105432f5a9c1a03b3e05133b41c5e067733947b699257b4f97d59bca95fc113409763bb5eb2f6f70d94827cd9e0fc71dde2ed4a270d998c944390536dc943da8920df314681845a4fa8f1d1e300f0166fe8bff529f61dc57e241c74ff17dcf19864d5e99238f4db39307240090e4552aaa8573096ea7eeb275c0e878cf5914b1886ecd5a2d2b53cf674d46376c12427db66d5e540f350e94df5080737d2c52140bd2930b1e9edbb46f88113c133503da547110dedc47e019f792e37d7e67cfc0e142dc4a84fd8dde008fc365367ab23a60181c17f32ebb0fca60c70870d1a6fc5450b5c9bdac2c355bc31c147bb3c8e16896e1d10e38f1157df3f2ba01fd26d9aa590a3077ca3fc1dd330189a1830105293466c9184f2b03f5f2af9084fa54c9cc19649021099e4b5381b36a026ac49e5ae3eb891432c355c6afaed37d326f21209ed0d23b537d11971103ddf60ce8084e594ef54e88c7709929aaba0baf47e058dddd99a384a5b257d4548dea40e4911c4d2dc6cd48bb91762dd92a35d390a8ac698924f0a5cf0357175ee2fd0e19175393bce3581a4ea88ace681eba6d821d89270a827e9dee8f40cb4f4e8bddf82fc50e18ffac78d28177213b282074c3d88390b58f07c96ecee28e259a3a6cab4100a1e01168f062b39cb4851fb441237ae47a99cac6dc220094b7fa7ee246ac285f838ad409fcad21cb1a6989f8f83529e4f9cf3de7a46543284c0b19c91d83509635126057c8bbe45d6225e6e3c85b03b7c55dc0798c37d61576d30a849ce2883b36ca650d40860433575e71e5fc0ada8a96d319ca493ce52d0a40f8bc22c924997781f65ed0624bfa4526f99874bb53a9bd4b33d99312a94d577e807dfb712930fdd244147817c4fdd8c0e97789a8c605148c44502d77b6eaba9b7715455da111d04656ed058e6dfb6f41ad6f8b439a11b249bf667743b64a2addd233dceebcc7b479d9d2cbc31095ece4996acd20005bffe921d4b6cf2bce3df4bfef40dfa715cdb94c8768c41289d55996e3006267800453fddd62437957f6871c172190d665bf6839e61a1cd433e031afaa8267541bae1dc0bea1c919ac346919d21f02268355334b00541592444932551606f06426ab51a8de684c37d86cb66f82ac78eada9fe0b5d38d36d29956a723c5f2aeab2e74c24134742cf32e10e217a35eb25dfe8e5f831c678b806a025a02d61a789160a0e90eb7ae4185cb81268a00a39e99f73b5806c0ba71a41ca1984de7a47ba22dbc090eb03141c8d6dc439799f13ea685145cc04b48886b3178a49576897e83b4f6546f31bb42bfd88ea49a5419e091b1b3d68b53feefc5eebb277a102f61fce2596de4295136b457e3638dcadde4472e255451f288874a43b532138759e3c0213358f0030e96de06b0993592b9f857a20ad0c2e36e61b2e2641e6e9f790a0700f8c481206e5ffaf08a04380422a695346ce87f5bd5e3959e4c59256b471c89aee1b13228c8bbb60383c5259816edadbbad3a74e261934b7cc8c553dfd2450a86e41bcb98265d8bd8c7d17f8243fe97a6839ad53b0b0e148077940b8110a252867ddae5acb9d706ceba685f4f89ae650810ac69e232bc4dbd5c4cbf4d5c239b8085c22a5161f0ca2d50f280b45424d0c95320232c4968e0e61d4749fbe10574edd820f573e52762c717b29167906ee74e38e75a4731a2a3b573d3b0f49a0803445e83e18dc7f024135e738d04f639b63d5f6f76423e3a52e7faedc2583af751b96a19d9686adbec4929f35d3b06df83627f0dfa59e7fa9059a249c269cddc88089dc23f49281b9982819aa931540f1c872a2177f470eeaaa9e3b6cb583d03fd38ad8f981508f5bef3373440e37fad407e5c35bfae55f4e0fdfd3be488c1d6bb8eb091f17f26b81d6071b7c73ffdf3e84f4f42984d8a3b541b298163768223d5fbc6637f964f1608926c2536164084f404745ba0763cc94f70b3adf88fccfaf91387f83f97d78bf6f70015dec83da8049eb25a512105e2ff245159d8755d9f1b03ba1bb6299cb3c711e93c46ab3fdacdb78edc65ef4cfa18dd380ea3253ab7cc0481ac80859fb0ed05dd2c9e0962c0de70ca5c8738c37321d044907962b222d520776db5d93fc1eedeefca3c32db6833ded4fce0cf1d641f1edeb46dd95b2a2572df077ff0574691cc7bcee098eeef583cd151698221caaf7b10f56fbc1e2ea7d163471242efe253154f0105683526703ac0a49b206bf57833dc22ab45428bb455fb2a7f916f5c8c87a4a242eb4dde3c870178b0ef9f0b4a9dc56baefe159d7273783007c83399779c5d54a162244aeacb3945406c7c2621247969b501b65082460d00acde7755bc1af4ff466649e675c3d04621cc3977feddb125752370d24341357bf2a1a029d6c66294ae8dd3dfc00adc52478f46506234d03bfbfd8b04d99c664d80956cd2e2819305a9d77111c5addccd8926c0e1f42b7699458a153c5c240505511d917249c8883d896ade446c84023c1ee026725a6fe5cbd262a361be7a962e24204418b15c4fb2972f402694df1dc2b743ac94260664f6480b4d20f017d2e5ef6d58057eefbc51abf818071a922b11f9aa10210c505e323f42ac486d2451effda11b2220165a77e92aec734e21f0ead41fda44d8e213ed10f28d21dc078fbca40fdbc95bbc2983af95542f63ca4fd5240c166fb79a709694e5a585d48efe129956973adbf2f7c79814f365119973cfdadf952a2d4ec5c436dac56fdb0460a20521f220def94752d3229fdce4cbfa9f39e66fa9827102dfa6145e412d6ee6f25db229157f7d01cebc86651c7c54ae26ac92893664ecc3beb1ef9f936ffa5f659475b5f2e70fe66a9bcc968b025f2e9a0919f5ec215c5862224c89a80f59c55ad7a82872602dab3c5c7994829e414d74c544948a245b3557eba52bd74fe6f41f6707053e2bc2f79702efa9cd3ade7a7f71549f6de5ea08bb6afcf940cd538cd70809a0806c2f380047f94081adbd6d263df7a3c5571dceabf1029f66fc60845ab1a01bb0949d8c93e281f8649db25c6b9bf88aa9d783b5aacc46c9349f8c78b8c2c8b1269a2f8b06e6abf7ce49b7b1aa56fa069c59f5b43412a0aae13a26b6f69d0c5d63ba6e4042950964a85055ac7b60359587fe9c4f3b1929437bab9066f55d7597145afdca2f987c75286122aa650e8d05566494c1a2beade28177d6a2871cf0eee2c746aa9e774c298a5eb08ad6eae3d5566e07c1e98f8c9d1acace6764261d0cdb950a28958a73d72e4264766d9f3bbcb6608ed97684e79a982d36bf2d1e8bf0b7fa659423f698d93e05f180c2607449c0e344fb047d4387aeec58d965ee86c3178f25855d21be557a4f489ece4c8510816638ee1081c007079bc70b2c4b39273f54ea4272df003e4bb18dd4d135e0600e823296faa3647a9c133f01c245d37cf21887ca3f2062bb15370562ca597a725d9c70757b62f024a31fbd63d01ef85220ce9aa129e8e689b14159a5f65a1a822b0621bb545c398c2ab4d549535eb539d78613edf94a73b723695c8f53534d5137a55b606ea1aef64d5f73535912397e0f815a776acf6e58a3bd72725c064983b3aba18efdb131584623489d80afde0ba4d3d9869727702fd623e4e175052a972796a7cd6fd76223dd97c68249392f1d47c3570b9e1004222dd0dac69bd5b086cb83c2f0280f14e65afcb21d97e088c17738360c69484cc7c9f4d4670d365862cc4a34c1323eb0f7fbc34b4ff21ae8a6fbab55789561c63dd58993f62f6f869b3a098dc7f86ee56253e5e808c87d22e0de9785eff4cae4c6230a87f51305773aef1bdcc795798a0e13b59022ac2bfd0d57c06e791dc9d3d21614834bac04c329860ebd70ed13cc5a38a8d4c5b8ddb73d93e172dceebbca9dbc46c69cef58039f8dca9d3886d498e6b3c0580193cd55591a519ccc3e04ccf8199615dc66669a4195297dd316e2cd90e732014b7b77ffe3b35f570d5a4cf4307516cb99aaf4db081c04c4915a7a6b07090538fc47d048023c6a2ac5a9ba4140b7c1a622fb68ab41a0ce7c0be4105d0a9668cf9b7a76bc15ba92167f82004d02bab453b0c3f80b1436052107b521134748f70310a9afdd5cea95c10ab8ac5083d2f8501f3197cd261272905979b74fe927ea78ab11b938450f3038a446b231b5c1f43e92a247e0f3ba76e4241ed982d850ff4746afb0ba271691fc6c7d8630ced105b5d0347e35a8b4c4ae4db8a63cffce4059a2fad7464f803875118f4e9e163538c3b7c3a502df9ec0121207abdbb87afe7caaac53d6c209a7e7dcc2be9dd6e1651d8aa6e82af27684cf496a48c043a0f8e2506cba568922493dfa434559e54240ff776b09d19b8598e69d8a0315d080bd2a19b2bda21afa83ead68d1594561544945868ae97078bd8c1e885d29724e1f7c020c73030d8da0fcb18d7a8f30d4cb4c5e3526ad62de88a75a010502b2d90d040eb7d1959186c55d3acdc95998d0b9887f493f9534c31571acbbba7bc4048790b3e4010d8ac51f5d9339729d49897a376e167cdc116fe3f206131e8eb30e97d5df87f8d1cd560a477c653d068c1f9416ab61abb971a1865af4ec5b09218841caf5625c88879322f7af100ba6b8247919b2d88fe800f1ff37846b24c6190003f2112acdbbd1178c3d193e6f7558a128ab73620f4336b0c80b430a2b68d582ad1a8880a3b8197441501c612eb08ca05103ad39f1a97895aab068485e9e36343cdeafc18441907f5297c347f1f8de6094cb60767ef469e57098f89408038d12e4ce9ec5ef992234021260177ecb2e534758865a0e4d9fad31a43e6a0690e4623c33653b7beb402806862c509acdd65b1fca143f28afae5acab4750fe76e59f064b87b6409b06241788229b823825bd033bed6c53f6b1d1e1b9b29eba30837771ba05ad52ba026fdb30cc674b33ce6af96d894dcc7d5809a0a36d02ab6303f01a340632fd516b806546f1028ddd6966ac3b76b6543c89a74e6438bffa52871c7a9a2d7f7fbab7f156396ced9ea7086ed3fa96ad683970d6fc3faa9ff8530d5f9ea7387b1cf8dd2cceca0acac0c7621f2e01491861605ef5e85e4ac8689e8f73d9083d3a620410579650ef317232320375e5b7ce6031274bc09427b8beb17b1901254d340baf0f8324eda1b36047a5a91e6fe923357044638c47c0d87959c9f4a22d11d1b1ad95b9fea7e65a6f6bd46da69d29b2c231418764520c64f4a34b32eb9bdf3b4c2097c21245c5b1b2200bd43bc53551be40bc64f774c486c9859768792947b865088c90afe182c7cd360854108339cc05f44db32a59eeaa49a971fe2994600991f418970f63de3e84723007200ee893ff2f00547bf22f8f263ff1c7a227d688b7e9e30b77d5928b1e9200bb1f1f8910dc89972097cec87f7d525d18ed31ccc70a768a4440f1deaea7fb1a13b25f1bf6dbee89fa93fbe0e20dc604d4726c19ab94a131783963b530feddce355f81d72535bbb841510357d6e9918510d565af3779c6c53ef8c91f53fb9dc6d0005e3e84168ce8ccd9957022d5ad9b781ca654c360fd160499113aa46eb8073621765ed841d1132810ef4f9b6f8b174aed7e3c94fafb05a724cad8d2449f214a248ecaee69394d9b29f27408db284c5cd88c50bca6678c5dae7e8c5d92be2b0832e713414ba9403f54184523ca6b602791c129dfdd092774251f2141b0dc8dfb9b4cce65c69017c0ff419fdde97f6a981f5c00f4416565bb28cf8aead4b3a1b1d43aecb94e35a6b75e94f98b59589fea14b5fd2d1d9eb72f36a2dc85a85718760e48d199251f456068fd984ecf3d533bf6bbf0f1e64d2a5d6a39be3d41155f673f03a170b59265ffd2fcc5159a8e5252dd3617665ac9c1f2b58341ac65a066a0d1b796a8d59102c53dd45b11c0e80e7d7471e3a4b51c9c2e3210e1212ded8a0a125f438c600c5a031052218bc6b17d83cd7562fed537725d58e69400eb413a7154bc22028c7a6218f01a5d98a0680787d1ec1f2f48e96d311a52c497eda3652fac13a93d9df4bb26bfc2ddfc02751e9ec418a30e32219768414af2420543bc99602df574b4eb8977e7354408e8cbf4b8345c8d8d32869aeefbb57a47bca929f9ae6310aa2d4843ad83e67c802656af922dc7bd546fdf4cd632edac8c298e4424aa938a4d374b1f80e4c9a41aab2539694335ab41032d650cdb1571be7939571763c4338a8af20b9411bf70b17abd7beaca3041ec84f284dba32d2315e76d61a5222d303cd1fec0b686d960d5d2a7562b4e6a00c45bffe4aee6c0f8d8fcd4032502a0f6125df3444d1253bdf3c3ae1669050b43cb7a7e7e9ef74cac5d5bab311d77a0a3c7a42404fe0b43b32fe5dc59146ae565414b3a92ce41bcd8645896c41cb67fc0db55b647029f3f78a52d1de312112325cf6d40062bc7b287e6b85e377a9153ad72328a84cab86dff10875b80e7964952cfd8e0ce9a493626a969a2fb7d06cbe165db2011c2de2b050e5a974253baec2d567c138dfe8af01c22d2a2c6d811bb8ba219ee985e37b74a6c20073497974747ec59c36700f0d4ad77026d283106de1d021ca879160e66ebb211e5ff088c7edfdbedb93e0d4ffe9f1b94f196227fae8e80ab5aa51da44f8c11e9e9dce45721f8d116ab4647ce13da1c55ff43b13be34dc78f818660f1bc73574026520d865794e81ae0ac5de9009d4ee09a897bec3fb55270fbdbde52f5796f05e84ddaa0fdabdf3ffd720d1c7409c3a6b41fba240cadd070aaa057f3210f2b5e627cd14ace510cfddee9fd6b97dbc6dad6d9270c9d6b259350023495a5b4b877f04b69e36d9f7fc5fc535fb7ba078fd032627447045afea3056097391f60739106e9d37b98d4fa326264f78fe1e3a57eebda44cbd9b6c7644986e1b00fce1e771d2c47e3de63d21e7df36521756e1c234063ef8b03cf78575a103befe90f5e4783d56206be9271b527b865b0470c0bf54d8d5430035ff605401d8ba6fc1ba925fa4f2d88b4f0fb2dfeeeac085436d58bc4699d95bcadbd02792134640b95fc9cf779d27f141557f9b3873a5ea5511a9803ebe2a678f05dcb9ea2ca3fe622f2850422f78785c7164d5cb6cd67fa9f94237bf7e533b409412287723b0a93580d1abbc52976648b360c99d5a522c7768818c9655674a8bc957588ca11b538d991fd158b4e653713f1691d862cb91ff803047e7a43d659adaa7eb7b663331257d65247ae2ccf292492ad2da0c6dba5b20e15e08d83cd3a7d1d1a4666ba2dbb51cc56e88c6a882322916e3c46017237256a0459da06cf082bf6f45e57fe68536a5e7fec558285e4a0ba9327d551deac6b06bfbd3dcfa75cfe26cbba403c243989fe7ba5d1f237bb7644767e5d3df8ec9722e93a6c7be47d80cd88f4100ad8eb9d721e5c7b64a598c84a540a60d6c2b3b3c8eff53135a57784627259cede46aa3a4b07502e95e4ee9a76a2e0f7f6676981ce91560b8c4b64e47104a7c96d781b5cb319b33cc4fb6087122cd08382a08093619728073654edc19fb4cccf7655e9989504abc77fcbac9095af27a17fb0ed563e78e7ce81c1e7f4d4e5eb8fccba72f1bca241706d5173e2b9db9faf92a43bba9309ef0c9ea0475bebc04952b52c47f770b24914f55c0bf9f0216cef75566e50a65e7223228b1c413b9af22fa2fd7a09ef755ecb158c1f0c7af225945e9cc07fc2a76ea55a04a821e10b702d41971c7ba6ec4f954f45873a0c8585568c229ac200790302ea21208246d07e94cd32ad45ab3ff597b7b7df7ef9ec85a480e9fae196b6bcd531e793d4ee7e8813c627855e75d67bed75a651d819b219b6add6271b43176935d2a047c8abe4765cf891944bdf0fc91a00d26da3fb10f67de6a37f8bcc3374f7e47ae4eec2684b8ad55833bc8f0dee9a131259c4a5b276cd10b9893119492a047ba3c5ed3ace569c37734e341eb82b1349d9510096d5c07b735bd9ec54ab4df63c726030e29d479df0e1e2da1b26665065ddc782ad053157937f4ad0774bdddcf035a505fe9c62e64f32e38aa1d47587b89b89b362d754b67f6d3844a607f94aba8c75189f661b05422c40f0c9f843ce2f86327573f279f7720815be8a2d2eff4e7d14481f206c25dbc8fda1309f30bfc13a8db84910c2fe6a7ca22af0f009964624fc337c8a091eab88132f4b3321ea273411f239004912bfff746d2ec2b956489c843466dee9224eaf1929899e2da0ab937c608dcc07eabfae6fb85ec913c34ffdfae2876edc7db46ca6d74cbbe36d087db90fec8e31a7441f7370165e550ece46d65ef203d0ec4b341d71fdc5ae940cbbe11aae62f90697ec72795218ab0b8ad4af9c8c3ae3d8b4088ecd9442b136850f46c3de7d74e36ff4f5b6a10c2e619d89a5e8a4a0f77d699ae5e2815428c2f6f563425b60248085af28c4faf51ef8ae456c5292b50a0f87b54b80b9e304aaebf6697be2b66f58a9a768f8ddda3d17f521110da5c28e5241ac651352184faf6de8e93521062bc31d6ba7f56070f8b1f9b70ebac82312cf15c48072ad08a7d9887d3a810c78c86dd63b1f551e1776af65de0bcc4bdb031bc8f6e668839c3c955d830c56f8877a4f068d1367d27cf54c6f17bb927176d0d9a21be63db5da68d8721e0a104fb6b3d3ce73ca4d80224fb4b6d0b2728736f985b234e70d4480ab8ecd9ed2d994ef2e9da60aa30d25cab1af88ee8a467c966a71e8d87b81ae29ffa3ce5739358dfb7c2e60cb6fa97d9e0e4a7bead943b2b5458797c557e593e133b0c06b32fe713846527b81e1b5d9541eb0aeb0c69bd1057b56db1deb5931747b79da001f6b11983a6773660c43bb001e89f16b588ae6ce2a2e04729da87bd7747a0aa8bbe8f3f28f658b8845fc09c6bbd6c845c08af35d0515d66f07aca39aaab8d6ba88a2d92e484a2c4ebfa01437ad5315ea50cbd7be3770ecf4afa8134d6decddff2660e7413d24b09f40fd0c001a01bc00df0ee7d3fd04c44972744d66bc309553e2bc9618efbb51925d89f8be04ff0d8424c3bd51395ee24306a87e903233412f11beb78c60755862be26a3660e44125a6cefaeb4735f2ab30980bbb0767574f178a0b31efc783631ca8a4164052204b0a74178ce11a50912e581638eb18c8c0c15095c2915302bc0cbc9671c0aeedc728bd01648cee0f03a1e3d0b3fd21de2ece83616d3d86f92bb971f79a490c9a12dbc003c1e02b52185257062d8bf7550913f86cd3cfb592ee282c2ed71f141494c73b4fb49c3b0b63d18ff46a0636225481398b872d6c8c250e90913c91226344b94e11379e3530370616b54e1b8aa502f0a12fba7533c9e7fa854a63830e840b43241030559f412fdd2f9afd309aec859aa845f3640c0b810a38fca92b852a4682f6a4b07f0fbfcaa52e2e1e3dc66f81acd406d59e9c45fe2e961ede3ba82035fa439ebae810e57ec23533862cdae1cd03a8f3f106bd4ffcb24e1ce1d69ab1a68ef177f50bc59ff62f9b1d26b940030c9dbb1483e8056abe89640621f55cad3591e0190a8eac0080e5f1518e1a18f60c9b2504658ddc9e5ecf5dc6c6d6340c828326e16984103f6a00450b7ed289b58bf4c6b240aee2b8d887db4f415bd298efd19102062bc6c807e0f74b211f1910ab795e0602195f4d462162dc90297e07fc3b39f2c506a9639f083746820d143e6ba0cc7a5cfd9604dde35e7b4d48cf751066663f96d2533769510fb7de444b42ed1d4eca9317c2312682498f76a0c7b4ad8833ef8785ce249352a2d9b4ee585566c902ace00975219f332e671b4c205c2f5b47a4fff707612e1834e068f010d4f102692b815d7f64464c62de47385f7be8a7b6dbb1156449381b4728e8e8d7bd49061aab1402ea1b0418721968e62f314e66f2df2481bf7ea042d765df79f80e3fb264dfbc401407199c1d203c08e5fa7c5cd06bb76232eb3ca6db357850739fd82cc53806848021a4bc70be04083969502f2fe636b28a79e37de672b64020fdc28e0043547c4bc33de3dc019aaeafbec08da0d8196c6d83385493d6b0b3ecdfc2eb11b829923e75e8ab06c207d5b71e960e9f9917adbc1ae265eba1e535051117aa439c41952068244bef40f129030501c132c0452dbca3dd9093a7effa9891fb3a6775f5cc1f2fff03c7f9cd4473bf69937b7023f80efc9daca5b822b208cb0be24d026d9b51dc283e5fbf12ecfa6e25305e7b2a2b4710f968c38359540d2e3b8881da805d5eeff5d631e16e06f0b7aae652aaa975de9e391e66ee28c459e61ae428dced98c42d4470780b1850cfa1eda72740613474f7f6c8dbbb39d9e1a89c2fc0d242dd01eb961d227795bd36628a005e183884322da459cd7e228910dbd0e6ff565be0f6da2a51d457d69be1b33930cc7bc3b90e82eba909ca6d2eec31afa9a41a57fd84bed391be814a22c7928955f9995640e2658f5de554ae26d87dc43f7b3e8379cd674313c61d9c00b259b6a2a3a1161c26b895086f9470374620bc2ed13ccb083e0203226497f8f82b48ad69e83e730b315d6355a05e7e3fde5833c994a0dbd1002f1f9f20dd6bbd3e53e1bc052ab027d0c0aea7b96d0b61e72a46f091139a429daa81e88377de936ce7d9680047d9552c6711a3896218ae1f45c00e8a3113debe203f19bdef0bfedc77eb3de9cd73ebd02efd7631bbde675d5abc779a55160bb1d6bc71bd0607226f3f55bb98928ca8e3c0d02f6f32fdb6c67512a925365813c280fadd0af7671fb476aea4a7d00b51bdf6be20ddce124f25f0c907322ba1fe5a3efe6df310a334f2b83575315452f0c28aae9b4a4fdb78086536f8ea489250bd0e97ac45243d9d3eb34b3986455b4a681ef9c267e20976981c5a7e9696ea0e771df16feeb3c37335fc6be3938e34100c1f5a7969fbda85dc79ae381819bd238fe3f0ad10e95abf1ca9a2fdb5021c5773a857587171fb5d06c74db6883c6c4abdcddbcc0df12b667ee127fbc94de140546299a262154f688fdd217e91ebad781dea3858967091cfb45052fc96e79b9ecfb4907596a513ac32f3b5bbaddb650f70600e0f1dc9abfcf446d503d71662a5ef90bb9ca02ad82b1ec1074cfa05d6fc99be12b5490b56a66a63f8e1f82c17801990657f96b96293bd767d8297edb5717078619fc9345c717333c70ea9d72bf080455f013a1f41bb27eea2f64254e44debbbcdd2a6249487952c1fba805c37f23bbcd8c77cd01fc96ec8ed8e7c875e7f8b96426dadb38ebb6fd7aebe57fdee1cc2d5735e60afc6e44f64c7396fe5b5a8ea97a4088b62174e2dd6eb3b8c0ce46d8444d198a9a1b7ed3679b1ac0716be6452f1cfb9b798c66ec0f60704ee5de0f4021372e3fc19e215e38da5583bf077c1e14d99e41163fd582513ee41fa682665638df1b2e7fa89db9eed057253fd797ae3f88ab26ff7a61717dfd4de4dedc2226407df3333570bd1d1b02cc8f4d7a24c35f357d935cae15ca6adc39cfd4af70fa00dbae18aa2c8994629626c4591309a5ae462f286f2455c78f5bcb4d1e0c9e80f3ce6242386bd4d6fff922166341d51b1332a657af519fedb8413c362c5ffd7abddfdb97c35f78fa58627c86ee9402fb9cc704fae816f70b243fa33d5c4f52a7059fc6c3ed73708493536a9b604e5dfb86c1421bd233984486aa347561130894ee73e4f94e5b4afd8577cd0d80a9d40c99f615d969b3d394ceb10cce29610e3dfa7d7a5a9dcbb4b64ba27443e840b015506ddc36428b674490a971a14707263ab8675e1dd19ff3d3ed15e889ed4612f36895a0ab049d7ca934b6f242acd20b03f9234f26a430e7772cbf560cf7db14de9d7037c38334d084e794983cd0cf3c743cb7f75cb103939b2a3fa255843e6be1ed13069c7255d14c481f78971416c2d48a437fa84ce0fac949339bb1aee4398021f6046d929e4dab95fa6418117f56e53afb07b92b8698dae995ee1607ea802702fe1070a826883e1bb9070567e1d06deb4529f2cd81cd35e2e52cc2d298eb9821b22465211ccc1dbd3b69ec89b08023387f8d75962b11148234791f01199d943d86c25a5d86cec8eca2fa93a0130a831f473fab960600ce58cf95c1fcc5a5d9429a8c24ef988a96858dfca9b548b1057147a4cfcefcb79e1923ee423ff37169d0a13c7cadf30c980fc12256ec759beee4b4a986b9c27b72a44a8ea867512212734da3d1c8963582fa2dd3a7dc6b59115fd18e035b149c04a54db03daaff68e5a20ccc29a0e75fbf31e1222d880cd51dc9fa684dc10d4a1ede1375973c25dd702748e775300b6da6604fbc4868ae1a7661ddf0238f0dbe4e3af96af43c7a4e085eb78e70aff1fa551d86b4e0c0ceefa65db7b77db724b29939432d408bc08cb08322c1165043332515d11db7dabb952c5098733b4a4ec40ad9d168e6a84eb7d6d46d8720e0a74adb5d65a6badb5d65a6badb5d65a6ba5456acc504da922320bc644d3244af38e2a7a3a19213342d6615809a4a4aed5314353d377efe18f9cb3e8eea71395a5ee73ce9f7f481da9cc48fcd538bdd136a1b428932a40c5585f5dad7758ab633d0d23409562ac7fd2153e8d89a4111a13bfd30ebb1f8e3f26835f14296e209f055ff4fda2bba7db7b2abb7f83bc91167523bd9f7198404f272ab32d8eae57acc761f77f8c7e30cf28a72c654ca0518ff510b9898a6c971923d12118f708dd51dd2fa432127dade89ebe34b1e1b834e51e6c379b6da8032009b0cd76f9baabd966b00788aac2351d68f02ba40e70059596613606c90527295a649b518f4f10075ff3b4204349df2afc4293a95de66dd3ac3d9d9a8021d3644b1158ec5b8d3d9d908e7ef67dad6cbdc3d75eebeeb57aadd7663ac519a8e7cdd0ebbadbe19cafe7d9d5cafbecfc3cb076b8c666d69d9eaee79c9ead5e105f3927adb5babbd53d2f87cdb7512cf55aa5b85dd0ea96e639e7a43196e3a657b4936776295f7b7eed6e16eede842f09f085c2dd9bdcbd095f12e09b67ee7630746d8f3bbdaeeb7c07be1ce8963dd7de2f4ff75c9996cdd9466b371282870d6ebac494a29b2959dcd0946ed874690bbb4411b923e2cbae5db60ffa35577fc4a75fcdb03c4f6a9bcaa1008923a618c3c51a21623ca099aaa20433e84046acac4a15aa466dcac2d92c22ac6c16139bc57a5d44d166bd18fe60b5c40fc31f623884173b7c30fc11662c4e4344995c667bf55ef86365c9eda9f1328d2399ed7e4e6982975ca14286268b619b288408226b2cfe794c10306cd7ee026e5ba34dc4a220954613e504181e10501460d7bf75669f58f2596badb5567300c40c9507cdeb98d991f318db5a98534d4b4f135f7e307ffa13dac130ee96ea275a7b3cd080634944e52731dc9895a92ef79c41b2596750df6eb80b247e45d31d53af98592f47340a4bd416edb483963163b054d8dc65d60a9082d4752b7cadf7f4f80471e0f4434e4c8ad2e09e4e348c609799890460ac214194027e98aa5937216287d1f27d140323bd85a69fe6cb5bc1dd755dd500b83169c21d4b8cb7bbc5e18ff91f06edd881762cbdedb58e2f2eb457ad0768577197efb51d78ab5cf8dbfdfdf2c501e7e0e04d1e987d8b6d0687f0dca6eeb762d002d12a5a8524bffd4965b46ac6726ea05579f274dfbd7b204fbf9ecb59a8520f69441f92087f48b2690efd493b4a2b67d5a6b2dd6de93a9d9ddd69d95df7b95b72b2bb2532bb6392b23b26355d0f10558ae1bfe10fec43927d65b6460f5218069a92125cd6463c529c2693c994dc701c4f1c6cc7b279ec726ee1816afb5bff0ce5caf6d72d2862b6ff2b316dff5714d9f6ef89f2b4fd8372d8fe43eed40311dbfd2794951d401ab3b63af17084d4ae8fb56729d35d9d9b8f2ab395cd5403132cd9f5eb0da7262e20a1008b2066f0c0243d393303539918dcbd1b020b1277f70f4c8daa3e5284916b820a3282202256eaed56342d0dd18509a06c42c47437254b92ed3cb4984faaec1aea505f57870717f7feff4efdc1d47364917f0407ca99dd1f62420ab4a875b4ef94eab6d1beb37ddfcb5dd074d281ccbecf41fd9928d8f771dcffbcebbaae52327f23d49fb208fd6a1802bef7872af879b9ca6c77f4deb00cda41f7ef972f16241b5fa35d4ea84d13c2a98f596bf51db2a62e94aa766bda25dd12e29c7290da2575cac1b64bead4ccad9bfe077553fafbbb209ee1365380cd9fa96952fd0102d69132a148f595545f7e5f58e826cff13bbe7ce9b87df93b5e07991d0749de20a991d31945f22792e566fba7e0404431a2587d3afa76cf41a26fd4877f0afeeeeeeeeeeeee1e000a34298cf5394e6b3cb6e8262009a8e5ec8273b3d17abaa5fee496ab076dbffecfc0b979fd2e1c4f6f3c7d6aab40441ce64f6fb4e9a3142aa4748a4ea1365a64a99fd025a01a24254b2dd5a27a333d39246d7258de39de67dc6432c7d8dd27e23f83b4714d06edae67772f7ae79f77bf225d238d95d4b62f937d9f26d12774c971dcbaecfbfe408e827aee97af5dd25b49a3a85a525a8cb7ee1d67ecc648ab1c76492a429dd5a839603eeb23d38ffbf492509bc688a80a5e89322583a5d645d3ff28add531b602bbb54af7def007eb3f8c71d7513d79329829a6947a5ef8035c853f30d62d100443d0022974799536fd501445960e7f68cdd262a86d6cb4d65ae36b43a4fb0b47babf6fa4fbd323dd9f08b2c2133e2b516b7691f9748b6108ad1bde54a72a207fbe238d9f66bee6fb92f953ab666a64f32b55057259911b55a087aa62c01ff1e7d72947dad9debbf0b11c3f5fa702dd9bc3ea0dfcdf0776e007ae40d64877063dd63831fe8169e4d0fde110ad8f2d03c8dc00d713bb55f8e55cebe38c2f4a91cf9a8a7cb66c0faf3a3162c829d8bb4b517cd8f433c963810ecb8685c3860e6dc74c87b66386937bd4bc118a057f47283a51bbecd1a3c74e8f1eb61eb5273958c0638987d2998b65b5295454817ac4889192a2a232c34389c6eec89eaa1b331ab22c9bcd764983064823fc817f65b78e1aad63dc51a24d9e4a951b5739f80c1c7b4ce911e5e1db0131f1b9f9dca42a95cfcde7e645bb84f9dcfc6897b08e049ab172f66a56ee6b843fc0aff15fce495074fc50c5b5a85c41928fe10da85df2806ac2f150e251b3b56cb5251f259f221f239fa3fa9a55d9d5878a0f1330ec01d5c3e63d6a3d6e3d9a7a6ce9d1e5ebf26541f6ada44212247d04c7efc61da4c953ff8f8ca2a4a6a8eaab7e8eb1dc49dad5899922352d9ad2d294d59c3d3efbf8252199a952b323db296272d4a4e4b0fa3a6ab62a58be0dbac81554304ecfebec48710549bae280e9187790680e9b4d9e6a54248312132535555f3b46a38fe5007796cc0ca8ccc068b027b0a51cdd2a83dc0e2d0333301a8c06a3c168305a267d642b1e4b1548c7cd3c38ad5fe56b016841f8e3beeb09eda3dd3fee20ed30d9994d5199a9aaaf0cd4ec1cf96ca7e806a3390ca604abc1a6c0aa806406b90dbac8f598528174d41f9cd3e57cf47dc9df31fadc1c563f87cf962ebb861eecd899f469c2429717e7435e9cd3bf4dd9f6c5793ed67d472801760a55408ebf43470e1cae1b365a357268e0dcccb0d12c3104bf95973b7cadd728727b7ad0e95450c512041590a38b65087e870e2b964674e4c0e1ba71c5f208164b153af1ebb228c69e25d012687df7c76056ded3f748234c74f51ee9ca46bc278ab9f2834f147357fe5e48f87de2836f248c85368b21c53910359a64d9a2463de3f43905c4ff81384962f2d2a439e7caeba0befcad514e944c265b610a6d3baeca766a44697489d6a88dde2854fd292796ed1437d4410ed79514171ce9fbf8cbdc813ba577ce69a9b5f30677a388da4ec34eaadd65547c53c7e581b881ecd7d6f182ae3b7cef4700ffa3ab11c86b53ef57ae0578ffbd10efbfaf47560f7e381e61aaa490fae047ba2a1924ac1688c3ec83631087d9ffc6b1064d95c857b6b909dbbfa4105ba780a062a9082590f82217ab4fc3ba1a33ad95d6b74d34176402241499dad6d26a2d68ade4696b1d1a9b47f88638908b3ea52bf0bf37e2c5bc5f3d510cf446d0751cc51bb4f7aba02904810d265004a617db6ae1c41ca3c40893c7be4f7dadbc9e111ca8551b62022dda627b7c7a7c6867a36d6b23436d2887d99b93da36876d7f6565d7ccadba6a565553a8be45bab76f26c554b32d6e25c627dbd668db10042b584921e2830f9246c0173154fd1163c18b6f858ab2f6ef0d577f2e547d49317f2e15f365df92d6896dff62908a1c94bd25c85463b7fab49245eac67a539c4d2d48eb78b32906691d5db8cb601dc14d3db08e333675ddfb38bbfbef03ebb8da1404e904bf708ae2353379ecdf30e68efd3a869bded156724e1e7b73e0cff059ef00f141f208f8e2b3c8234c42c01749d711f143d25567ece21c8ef6e67298a4e078c551bff66b0a5d2f268f7dfbb00974bfa049b6c52c6cfbe506778c6dbfecb16d4ea7be6ce80261d74a7e7dd99bbbb7fecd39d08d5b651f273d99d9163fd996c9b648988695b6fd5be9973adbdad7f9689a8b6fea945f2df47627fed45b1cb191c3ee06b39d6dec0b06c0c99c1477b80bc0135d62d96aee8a547f6ad250fd1267cf79bf04418d43492c1b81beefb86804c912e3ec12cbb0ec8218f47d2cc3e37c3a41d5fe30d8dda9f1528d37773f1c6fd50d1f6274896566be5c01b1efaf6a53a8fe5dddc7325c547fbc3faa3f4653087f17e7301a16f368dfa82fc92ebf59f9218553fcf085881f862f92656689cf228962949cba54e2d3cf13cc159b4695b476a3b6da145aa5fee4a7bf81d10631501ff407dd60e6818e7da7ea4feeaad917cbee54bd58cc9f5b664e7c1f0c184bdb3d3ef996993f73de169d2ffab703e9a89dec2f8374c4316a617f1e58b5bf1548c71b32fbfb403cbaf0cf271154d9f3490465361d5d983cc1cb906d7f0df6cffec02aa6dce809a49caa38da943cc1c8e640ce2e224a0166d99f06e9386388fdd9807874753f9f90e4b0bba7a3ab7b9c9dff9b01d271d5647713678a62fd70e3713e2151b2bb114af839c4469804495c545f57d4414f272ffe063568a88a491aa73585f00a93e7fe7d1b1308b34061f7af0d1bbb922596c186c230596225fbb6f6954d9efb6292d6f575c570c4b8c3ff652ccb58e64038b011134cab3f77dfc74b514cd9b7c453f6c5b27d31d2beb8aa5de227fbde2f716d5f6cdbf773876df5e7de6b05dc495c3cd20775fda97f1fa7fef87fb59b22eebcd7b2a27052704e507451eaeab5930bd47623b63b41419b4fdf01f52979847ea55f8fd4ff48d7cf1838664d8203b93c7f220ee4f24807801f7ebffa7045babc23ab074997179b636b7ced3fa7be7135f6883968ba6b57b392afd26a67684bfbeeee42e66da87ab6d2faf3ebdf5a69add59b3c146356f96dff6f86770b01a1eddbd083d7be7f6bfbc35e2f9d188b2e10f0c65f3726cb07ec4b7e9b061d463a01b65620dbda3df4b858f55ae55a16a8ac4e167ac82b3d81bbb5f9e9de9b1d46438b33dc597c5d475ea2ab42adae83e7eceeee4a78de3649116b9ca4d9220c1458ca0091f40210b32e4db1b2675b7b655b25b675a2b22d8f2d676653aa88920554cc3a31c132c66808a332c088596badadff5daf82249c0755238907358574f8b02decba7d0fd5228cf674d28245efe9a4e5c976da82dbd3694b6db7f674da826471c531d24cc9154849d702f4b35e887e16a9492336e47ca298fd4250b4218f301d211d607364066943466da24d6f689d2c2794991d8ad0ad59b3664df7de5876d9c748bf6b8dbea4ff161c1e628fbbe8ca4063e5aa458d57b594d12255df9d7a40d76cfa816f5d5f3860c8aff91e04089dcdd6f619459dbebbcc917c53a7874cfbcf1b63e81e138276aeaf7f1ddd33a5cb1935c40224d41f202370d0cd903eae63fc5d62e8ad63336d485b5f4d3b7b00becd7fa3cdb772ced7c0f95abf35d61873461ae3579174ad38630dab26cbd7fec2fa0efb6cc6cf8e45aecddb904f95282de44197bf71393b91a86d5b55dbd6a91b9c204d501f34469cf1666cda43480832c22740a702d178ff9d0a94f337dde78caff11d8643de90de6daaf56948da3cd1b61fb2f40fd53a126d5be46e16799ba01a84b6bec2909cdf371db4ff91b304371d729c5d7e39b1e8ba6a9ac9601081981898e492c8b7261ef20064482267450b0eb92f625dd7755ded3adc7d0d24ba6cb5c0a89034550605597820438d952c57ac22e0a4c995284aacc031117377f79e3274f9da3db854a22a5364c43039b303d20b9d65da5dd7755dd775b5ebae773edd7d8b290eb2761d7eb7dfe1aec3ddd8ca49a34b3def9206a460c9cc87334d922c9144134dd068001425502dec00831360bcdc20061326b8b202cd072498a0d59851454a1326baa8a108db1134b6d8a205aa32686a10a2ca9a2b49c0fc1005134f43100105092f4c7261a48ca6e88e5822089d19a868410baa24537039e2dfeb1527ed911df9aa313c63fe2d28364a5a9862885b9634606243bad97546ec4e092bbbfb0eea8fb83b1dba94a144aa488c24625dd775dd50d791b6c3b8eb7037963387871290c3852e7502a6d0cd422482335c64f9a1880526b6a0724341ce0c2ba2aed40003134a2871040736cc9ca850aa628b1d6e0d892438e84aed0733b42fb8f8709bb62a22083370932101e505882ec478323a798823a2b036700a96ec4065ea40ddee1a4c109fbdb703d588c5f8fead459470dfeeb9cbebf686f56b73dd1d768140b3d74b62aa41922eeb2e81fedc942cefbd25dcefb0bbe32f0163f283b92f69cb29e46848d03ae8fe4e66df28d029a400ba665b12a34037c598fa98f69ddec903d6a7fbf6f0b42482916d3f8770e9e75977a5f4f1ee403812c2fda7a5a21a7e40b4edc6395440477d85af8296ce0d2b1dee74f0d8417dd113e096844d2801a9c0f0311dad9e24f14ee0e4857c8224b3eecc0c984ac98d3ab25d8e7c08488b8911d4d6e32abb4b12ebbaaeeb3a2ad4759d98daeeac0e6ec1e26bbdeaec00f10df674a2c20b313d6c1b2adf7420cf6221450b1e4a9053051022c84256772802e389db6cba22e90b1c104f525aa05292c9625f680a8a25d1a67f69ac92ae42ad2ee549d39f3fe80fc779b552f47cdf96fa5069f8f2a2e9d310b2ed800edcaeba3e4ba902b16a2c9b055074a943564d0c3d59b45db26a33ccce5125d3f35935cbaad59fe9b44e179d64d558b54d9f65db4375a8eac0e1ecfbdb79eb0112df1fc814c2ef2f8ee1088ee3ebe43067507fe4f4e9c4ee8a588d16ac7ec276f7808c499dc9d3756fdf4a607fabd54d60dfb75d8749eb7374d23e511c0a76cea74395aee03d3ed5d65adf9fda6abdc77c6ddbe3b55a716d0e74bb3565edaff7c08a817d611800baa755cfdfdc403ba5ff690d3ed081563f7318fddc7d2b31b401bff12ed1a1077877e49de58f06a883630728c33175d8a864b7e580e095797b829b46e801de99cc636b0af1e0d9d919e4b8403653dad456d361c1c4edf80a3cf7d7e140079dbf46f8a3cb38bccf39c7b176203d661a5ec31db415805726f4fb085de61c16e0b8a0a56fd8684101400639b51d1a351e1e336c4a51966abfa32cd96a4b516cb525a570cc2b0d6c7a740f166d41c1c1b169611c1d00512b21394972d5b4e724498996e4448976932ee97d02082f6dc945f2beac3433e996205911ff50657267ee03662170003f409ead3f368342f93fd077c21f9d0674f25070f431effdb29557b7ee2f304297fed8bbef3bee59933d376f0e6e10e08bac88a9fbef439ff3de2e16f1bfd0af1f8ef6bbabe4b029b77db180e3955da32374796d3e433c85e7892eef942bdbd9dd7895c20f5edb0260e3f1ca6e5185d53ba5c39684ed02540380b6025d99d17641d11f061a5c60814e053c7876320000ec85414fae3e513e5a1b62d5af33beeaaf13d7ae4e7d4e12423f8bd1b5d65a83e8d10ffd1ca46ff476f354b7a67d165966912cf5b5d4d2d64863e0d0fcf93386501a0dea79cd2fa98caa35df8656396c929546b1eaf745cba9cb6c97383e2d1cfa4f57a8550e8ce5eaf6c404af26502a0fe81d3a72e070ddb0d1aa914303e766868d668921f8adbcdce16bbdd20ee8b985698a134db198ee71f64f58cf0b88aadcd48c429a19c9a0704db7fbe09e385dd38daae044b552db37f7fb13551ad349c3c5a4511fe540396bed9476a37d5425298902ddd4b17893dfeacb1f00686e733a6e0b0fe273cee9412a509edf33e44034d67d140c3f7c4a29a55aa4264ca8570f142d8a24931d3a6999b24510443102343ee785d4f896485252088dcff91cd208ced398b81d86afa54b484508c96cc3ba7996288affc1dce213ed702c7f0fb9194bba6f5e1cc31bd6dfb0dec6d6179ee2876339a13870123e1d4b22a5d18409f50db937769fc732c7fc75fd197b5ef375dca6662a3d497499b7ceeb494ad4ae0f5a27bec67a5230f3f444b5e7d393988ddbf3e9e9b6e7e33d9f9ea8ecd59e4f4f5236bd8013154ca891deb2e78bd9932c525f333c3dd9b0e9d313934d9fa400ae8c2a3635787be2ca90614f5c194b7bfe991dee8923036ad3999e4f4f454fb8aa3d9f7053b8a83d9f70381c13db66cf27dc944dc959814fdcf3098ad9a64f50c876999fb88cb1e9e76ecf272e60088511f3e5c916dffca933058dfe0728e8fadf1370aa36390e4dd8305032e090840de3c427c4c54b843ce09b8488d4615b0e530be3831786a6c3ccc2187d60aa3278c314217dd61478828c030c98bba713982ef435182c606cfbeb412bdd40830d18a41b5e98916fcce0786568cca042e3080c0b3644a9015503abd136564b6e581715451647921638a0a8a0a26c5038bb25a98a4d3fb4926da84287beb2c3f6504a50b45b1214921e2d944e7a81cc5046339d2f55d9822f53f9824fcc05a0e705b462c61318809e17fae013e017237217da17fa61cc7cb9a17594b3a7d317a3eca5eaa3a299060088f13d9d9c98b1509f01d8f41981f774f23265c340ff4997f45e8e567b3a7991e5a6944ed0d3690aa829703bc3a0c3291e395168407ba6b86dea9afa2e28c1534dc9812a90c4a504392b676460c47adc92a86021440f2e10119b3f7fb6ebe7392f9893d1a97ffd0711ffa360e8e0fb832e8cbd4e264fece92485b6a188645028d2f4dc753bcc488e248c502c8e9850c5c0ff6cf81503347a3a8cce1ce672f1dd4921e2b3482354242b4d365dc441eb0fff48f8abaf4242177609117ff54734e9c2a490f059226984a974808e2bb4180b0428bac554985c6631f13530a53614913c32e459641087d50f7f7299c5582f3e8b2489388c831a9c4e39acfe8f8a830a2f2f3123dfaf1e1c8da84097ce8c0087d84732595045ab4097c88cd1456c85a5deeaab3e8fa52d65bde57033fcc85ae342973557cd9415875d99fc6bcd816acec95ab5d59c124a0e840349ab2c9e314a2b0e69ce81c010fc5644681cc936fdd86a9cb14f93d165cdd9d8a69001f6f7f5ddc87fe540e0bb7e22d60b119ff59e470a61bd268dac8c804434259757bf5689afdf01acb761bd66912ecf9bb14b6df4e6b699dd43d285bd858f746192e22814e9f2d5ea3fd2e5ffad1e7c7005feeab7d0bf6bcd4d587def6235f5555763ad7258ad329256d557c57964abe2aa1a5b737ee44533669928d7d781fe47ebb6407d5112e8a465760b0ca93f3e4b220b90505ff6abb8bbd27a5b91512498c0529a4204a0f446161d9ee8fcd2a7bee807d517adf93f3b290a364759fb8d41f5e528d059c5211dcc280b90507fc217ff3559126ded7dce5a97ad9dc9d2fbf06dc677d88af543ae47f1bd1a869ef8ab2c8a9f37387e506c742a107d1b7288052a8c3e8e3752a13f4acb7060085d74f97a01993cf58980a0657e710bba4146e8241fbbee45b76c2e9723921b920b02a3cb9c1c7c94233f220e34348488030de5a0724153e832ef1ca61ad01faa7826aaf96664a1607c4af5a7c4008329e46f2b92a4292d967479a79ebceeebde5eafd72b686a031f578bd77d1de9f24ec9a6ee575b9df9a64e79b5cdcdaef3ce235d06fd941cec6a6974061243af219de78d133117ea5249dddc8c0b11382e45c8268f12a5a5a827b54a8911d3a5cb162cf466866af3c587f6123d5dcf0dbac44d402a7dfa5886c568cbee82b4c5d06c0a1f48b344db777cadb7aaccb022ea93a23ea6a690bd5483f29620850fa4c991d091f04497b8694e357546e41adcebba1170130426154fec3a71403a2036e812378145a0d114b25356a64453aa95442e31df1a5d521995c9681aed5fce1c119a52ae92a1cb193524bb56a3cb890b626dc85c9bcd661bd2b9e5822eb14d6963255cc3369bcd26457fb8fa63df66b3d966d46673208a4467363ab3d19a8dce56d065b6edfaf9498eaac105e9390cff2a17aafa9d7a24daa373ce40e4db7e1245ab54d52c96c974b6e490cd181aa9fe787df7926e0fc1078a216bd970e99ca7f45f9ad22e3fa9a6a0a6666566572a8be29b3a9ff893259247c4078f7c9a3cc262fdea8fd8acc66f7451f185b05e7cfaa2f820e9a246c067912eca7a21dfb39e86a411d6afde88cd7f1fd2983c19045fe713183063e26bd28891a9dd0893109b120aeb4919eb59a40a47865ebf0df859d701e4b2c7fdc19128f636a3f87a643d1d43f04dff03472a3332c461fe209982c3fc5160c08c9dc080190ba9ccc6e6cb99b3cf7a5d69a125673424da4c7c7064fd0c45f0fea3a34776809e50e90d0523e28b24ad39cc193063455464b186fceb8b218dcd90923826b476d7b9ecd39fe1255d960c811c9289ba9ab1d0ea17ecbc4e7f22a8f3baf9726786cd973e3b68f2b85b9b71ce57ad20784854436d0530686882690a2b62b3c2565fc7902c6233d25d8d6cfd3e9a00ee1950707e060ea95361f66d46ba6ff843874834786d9eaff06758041cad0d53d8aba72f8e73bec2f710244b237b455a9c51677cfd11dadaefc126b096fcfbb7de647177af2248fd9941863a00f23d41bbce39a188100197bc47522615568188e4ea6cb73411affed449ebd576a1d3e20e8258bfeed7cbd8ee57aa20d9eeeeeeeefe938b2b479ca9626326045d1ef21d7dc61e7f4a963ab90a1918321912e854201bdbb1024a6a8c2deee92445d5eae17377afaf5c5f157477b7d6adb5d6ea3ac5c5f75a6bedc5d6e2fb81711fd4ee6efdb670c02779befce7ef40ed10babe5b4a9f4ed14e7f70f79d22747dfad9babbaad1e4a14f378ded4db568d327da55b4d0163050068dad0a63c989354be4aeb460656e7172f2c416c51563aa545d3442a460090f3b0cd103166b88b00208a918a280f1421755f58c0e2bb22bc46ce982c68814be60a1a20a2b5fe0e0c4991c8603c0c82181a1891460314410275344a191aaa20cda19d1cc0c25413ce103172839dc5af89246891564bc08d3c5c148a20c346b72a86176c44252103944d1e4650b2aac2f66134740a1e2a68512499a2080cc1819b850b1c36c8be7050296a449e26987269a8c70218c29906842022f929af872442e48d96104512b8431430c2ba489020832a238220a49d8c5ce0f49b620394ac26136c9c882ca0f567e18c3c90e980b2750a08397309c38a1b261833267ca9c4982448d0c9a6e8b28a6386121e98b2a3150d0b0b4c5d4122d0731b2548154385dba60418b318a6861d45052021bb4d0a2872d569c01d2000c2e3488a9e149154f5e664fa71c90d0b214050f5c9634a0854793e18a292da4712244acfc20a2206e4cc4049193c50015a3dfd3b4f39e216d42f39a5fb24c2d16483345ca48ca940f68ba2cc25853860b293e3c71a4040353524f60400208a8a82450f46736c04d0a2427a81c92a4c059985ec89a907841c612150ce4f9f3025d0aba28a5618a818c2a2fa22863d39f51a4e182062758c8c10b08a634e942b5a4ca122fb2f8a03f734d22c8816cccc73743c9099d41ab2d1bae9c6db8e8f27e47f5a7c421f3ff6a1d0576c613f7c688297c63b31d98b3d63d2f0702e2b0fa2ffffb0e93a2aa3f75aafe7856e3cd2832f3ab5cfdb1d75b3d3db6007a70d487933da8002ad0d7181dcbff1b29babcb8d514adb0f2267d6249b42fd237cba9c2c1e5f7f05b4c5ed9142a217cba57e0686b9367f5e10bd5b05a09d9a0c1ff849274f89e087ede20f857368570f6eaafd114aa7bf5dedbda14cad92b121c73f687696df2dccfe183f6cbc27df07960c1c622640fbcc7ae10f2e3cf227424c629536942306983dc99c3ac06b48aaf56b2bcb76bbbdd17826d0ecb0ebbd9138426525bb67daf3f63f48402ec39792c5955a095ca8278ab2e77d923bb37cab11599b11d4b9b7d838c82629e0553c8df8d33e67527a4b02d0d45e8f60658738e2774db9225b8eef07fa0a35dc657f4e05a387448a0a71316b75db6b0a8ed32b770bc8e2b48feb9855459ec5b79abb1c885a0587ea31cfb3e72f579f4880860cf308499823d492fff073c8f9cfb32cd5b82add665490f6297340aaa3dfeb27fc73d8d5ab1fbdfddd348c7ba3d1d8f463976dfef57bff2d347ad94feb843c9ef84056d97190b249ca7414fa731b8ed344636a669572ba0767d9c6a43215516f3429c3bf7b7f545f30f790adb625c4291ba2dd901dff36ff60c43c0604f12ca07ac4c4665b258fea11ae69bf3c75aafbb7e39e79c28d05da47e39e958a4ceb796bed349913cf57867635d7e1f33595d0bf03eff085eeeec58d4bd2eca3f1d8667ec678fffd2862080ee7af7f8ffabadb5deb0fbc953ffa7d074e19b3a4cf78e1364eafe8e28806065b2f9ba21b81d7847148450992cf6fdfdef1be98479207831f01b29e86d8c6deee85a40f8e08ff023cce7c086128af8f67e4e6da21851acfef78d451f3816813f1db6e280a64f9855bb886ffc3336678f8e5a0f88c071c6cad6aed88e370c41003bd739a787a2477e34638cfdab1963ff72be5b90bee9404cf63d26fcf6827077154227ec5e9b3dff137091d7037f1d3b4ae4952a9436841b3ae7ac57a41db59d659a239de19b3a4cfe391e99e8fb88c23bad36682b8462928e60c47442d02ea1c8268ae1ff4ea0b408bf0b4c2704ed22dea3be0b4d1f63772cedb65fc3106e6ea8005fb366bb02f2f5e9b5567bc5a2caa8244ef555310915b28100000000c314003020100c07c542b148240d24395b3e14000c76924676569f4ac44992e328ca18630c228000420c00426066686856010ab84147f5bf29e40739a288bf58f6f3e206c2ec85a9cdc49152f2c85623a5307f5d698740a5a34f7238bae1fd53d60c1e3814eb6c756c84e35ee683700bcec65c7c19b5c071b2b9634d4a3643e8bbcb19375c399aa46f71aaae7f9d973a9ef3b3e2ec0a706201bdee2ccf801127628a477555f3a9b99ddce46a179a67f424207abd4555e34ee4d3f6ad50db97dec9e8245f25a595d11dc3de5e06b24141e451815eb28c7ad279bc8cd8dccbc6e160cd8a33758ebe6a2f7ac06f6027935ea6c1c669463ab32caa7269762cdfa34138ca8ecbc9ee36e9e6141c0f430508ba157e6437c3eafe00e095e714c5b35c54ffa9588ac0473efd332c7b36270d76f1bfdac5ffbab13dcea52054f1e40cf317d04584d6883be108f2136433c6437e8c274a75f47fbf21072912fee6668cd24318171fbb6db89725cd2153e85e2837851bc54cfbef9a6f3c9e257b2887dbb6914ae020e2245398be0b8bcbdf6732317b7a2f89ef92b5e7c53244adafe37b477735d1ee8893dcf681e2bb252a2e0878177ee41bb7ec9c742065cf6b593831bdda386f178bd9cbc280e7c3f3dd98ff70de591ec6e040481365db0645efdc741f43a4c957169ede04f1d15048d6e4674ef4d340a4127a98068492e842fa436a63a205af0ca745bb9845b6af47d613c9561ee8b3e8e1893e1b3d60f696e0a0b1f1c09ff343b4895e55c606766d70591160a4b705e224a71284c63d92053edbef334d605985affc50092cfe68a7a0cec3bdbb494a6d94f614aae4a70ea0341c25633f1bac6f0db80fe135154a97da1801c220334b8b267554bb433281b2d3e96541ad5f47dcf291b7fc7a11dfa95b3e4d2d8f909992f46f413b65c05cb69aa5479c7210ad709473aa061f248243f61d2a41a4ccd2801cae1efde9181b679d8ca011f9e78f4e826bb07f5be094574b1dd50d6a9dcea3080182c4d87143e476e7ded81e3d91498152692a5e37d445ac93b647414a6486c472daf23cef58c7926c5a99f9f7a192436aa93eba1024e45d13f518e89e98c2e95c2b65efd0436f471a8505b9c32bdd318ca218f360ba8bf25c313469493d1a543b2450f31013f08eb1d61329a4cfd39e24c15e3fbafefb08692a4e6aafbf37ad42b77a30ca561bc55eede9e183dceb4346bcff97f3d50614d46bbb9e367a61963582c210ee327ac78ddded6ad9ab03f53f3c07dbad9f4078057eb7d4ad705c5025b427fd8a3aadf58cb90874f97befbfb66bd40c38a58c6499187c589e1605fd0f0a51b4f3f45c5167107b6ecf5d5168c4b42051e3f4bc2ebbebd3c364341c14bd14ae277123fbb7b125fce0124c1cf1f589cbd5f939935363051526d4bd7d99fbe007eb32a81d7f11027a3fd8f1446ee0043eabb9cd393762daadad132ba383c87afd70bb83bd84102b5c48ad5e5a742253b4a6dd237d9afb19366a855f9cd1de74f0a341140b377ee616a0f78dc3fbf9dfb6d526ccfe5538955262fa214efe1e140dc10cd490ebb554341d6fbd62097b373a56dd5e9d66ec760070d875955df97f17c88a263c6a809f431a9120d96845b419db162b7e97fddd9c116419a8172159922709d5e88ba8b0a9f25652a7e79452154744d783a01ef777bcc562f7225400ee7e6224a316e20b2ca729fe4b9b3322e5460e5269f130df9d5ec5807006cfe0efc0feeeee4f65a387ce9681ce82d6a074339cc0946890407e3f60ebbaaafb87c07f98e3b9d382ae4f51729e67f0c0e1b90c13692aa6bbab37f73bbdcac63b5b31e03eba4705a1ce5a01ee1d442b7f0010159c092a0b5b4b22ff6a47dc5517d26e2986a8e9ae8196c5a0bc172050ecaa2e9b3023b78d4c45658c4ad404f2343b9b9d81646e3ee4693613ebb7e9586bc9db123ffad0b73a7a3f0039c6279428a0472499d8a54539c244b9c9aac7f7aa5a70e5d7e6a06ce931c7936ab115fe88b25e23edbc190bc0d3c8b32938980d4b181cc08c2b4de62cdfb4aad1dd3faaf7c70374da807e0ef4de05e16a88916403a93318bb783440a8dc3de5f4145ac52050efb4a5e2c72c35e91e22abb4effcfe5c3f469d2d7d56e5e806f330d075b22e817ac60d620aa9792a6e3debae4c496d0c6e4ce3d22d5c3bf4ea087fc4846484fec7a23d49e6d03258595200d46eb3269e8ea149f6c5d336a0897d72fe62dfc27678d80fc174a06823979cc857522214020c9abccadbd7274a9fd850bc8a52589ef3ffa7f486f2b7ccc8cb93314f912107dd31a4d56810c9bc7a59ec3d1c80c1c799bc2fe865e3db2bf55fe155f1a9edc352563438cfdede8dbcc2161dd255199b44b9032971e15065f21f6685faacbf89b4470a7a6ff47505bb2ba56ddea3d3ad758dd52d4c7c7ad25a44ba37bea2df63408be28710012d5f6d4b0f1bc067f2c481d133f41c6da768d0b84eadf7bfc4129ff022b2b54af3f4f1dfa1f248e2023153aaf8964942ba5ba253357d7b8e353a5d7d6809f4d4f0cb9b96455e18b591027b7ddd50bc4f502357a7a6239786749045755d1ce1e09b33299a2bee3a3e4cb723caa325888a69519e8ffc04f55d9054f3d0acec8dd3a2e62e4112666367a98dcd94159eae1ddd9712e04dbe465a0bb164a187f5388d81e7acc38ca38832a35ca572dfbd80746aa310b3d4d4fc607dea1f0443c166d540466599237ff0e67e4d06b3a28a69f747974bdcda227674f01d78c3ca9e2bcc5255842cbdfba62a0e5c8df4d3a7a78d4a76a0766ff777a879e3b6e16d3b9e3a316fe0d424b138b9ea46d2aef073c10bc1848be3426dfacabb2bfec533155c3fb31f146b099436631aa2811a2e9b86048cfb7b82a654db1c8db3d913cda8cc2ec62c7cf7c49d0742fb9b27667a03c3d79dccf976d0d5d3b83f7f4ee809d989b21ae4b6973ed3cbc23e19ec730146ed2ec3a7af39cb1567a04ea05adc8261724876dd9be7d9bd000e9f43def0d98f6916acc1f65ca95b21852529da9464f8317aee9ffcafd0d35c23516c91040aafb51eaf0f7c25340c393fd29c5b9cd9673a699775908d9a351a71d9d30e217fc667b0664703f2cf13238d0a0cd3f6f8d362f819d0db14e7c64a1a8f1dad0e09167931eea9fea7eb4fccfc6c43dd3525e88d7d4c9a2249bb6887dc313c4ac40a9bdd45077d95855802653c86d5717dbd9c3fc67a543ca216d62d6b6f2cf6990811ce15c892ec15bf35561ae33d9510ae5bb2d87b5e09848b4299e0b70835a6c636dbc6d626a798524d4adb0db0c8d444ff0cb1ad08071fe63aaf4c74709cb1fd3e79145e7eab8dfefc02298feda7b31b2a39bfc09ba767e55b2461f58578d7245bc375f3d9c7bd9fa2add836177590f4d41fd8befebf4935aebb4386d2668707328b609fd42f55d2d0d9ee71625f59704bdcd167f63f498894989d19b12cb14fa7f1163ea405d3c14770c0e474badf272e345485511b5f9e947b03a145878c861e39255fdd44c37664b03eb46b81a7cfecf205247580ba49115001e7529ab324b3e127ee402283d3834abf37d87c5758a77f4ef71c0113e41d622fcbf292e9be95b08a8f0c03e70e97e6e39dc9e9f012e7c99f1f47d2862df2ff614913e81c1bc4b6651920e5f88b0f967bad06f0fc1974b0c4f81a4b8ea913aac8836adc3b55bc425d50be0b328701ce594f590af249faeb7459d23e501beaa570fe1d97472df5fa778ae9d5e3fea9843fe76bc40e4761229a05a2eb0bc8e6e722e75476bb98a1bdb56661ce53d1366722abb79db14f4184ad1d34f81e51583bf6e44685ff46436b913193e420628343d2d9ca8404fb734d4eb6bf7f08d296d5e89c0a3d253b6f699f655a54088318340f846442f71e1471ea839ad44ed24787010631e465c027f6d27f4399e4b45bf1f1e0936809befcfcd193952612be140ae9dcce9d473d7d43503467dfcc7332ae81003967404b394f252696d963ad9d7762d7ad9d35efd6a21cdf7a4a6139ec7b833ff80409beeef104125b93dccbf4d9142f2f6f7f1b91d89b3e363abc8c7e767b13d10fdbb8f3db89cb2e9243377f42f463e5b66211fd44cbed4e843e6ee29ea459143bb9bf09d8e78d3ba6c845b9197873e5900a1a50212446ba412b08d72676ec02fa33ad1503f5ac7f7079984574545a6e836e2ddcbe8a6e94bb41b71677978a620f0fb91d74bb941bbe76797572f327e01f36f86995dfc959227591b457f80d9198e5c31a8ae847edb97d0d4c94925b9dfd7ef8165bcd38a2ad9ed70cc982686453155f414c7d41bc63d267d8df46dde75378e35ba58a89ce5f91288ee7b6351a339aafe333d1bb4e782bfec51bce886e580d67b937ba2eb0923edb42baf2f1f22eefd5e4ed331384db5c81e75e350cd14e834e1a852490c1d534b20e13a255399dab9b242809266abeefe08ff6ebef58f904b6fa7f2a1498cf703cad64e71ea855511460bf0061d9b29c430b35130edc60e509453ba81eee4c8874aa2db52c3e04127caa743fbac4ab0d536566dc3bdc499a6aed71cf6451122a912f857ba46dd49e17bb6f65fced1dab1c4db24db8874eb10251a1b706aba2a3dab77b13218c04475b09e9d123bfd45d1a2a32529fa1c5cdcf5caf3a4fb6feaa682d6bf84ed07f98a40408d95e7689008afe284449a89424c1d7de156fba4c3da2c4bc867392a1ea63067e66fefff57c5d81f88911f0d410775be2f0c6ac873fd06de47bb16c4a1367fbe9ebe986de20857f793478599c50244fe1574a5729d6a90c03d39b8abf6c6b0c39b5b16783f92c130dc8cc0e727cfec07d63c6b0793d9b6b2ccfc53600a3985e6e969270475fb80124b638df5c5795fd28bfc07c30fd4f2107ad3712d81e40c725b775170b73346db09001470d3d34b858cca2109084cc712d2000717e4d8b7cd1d997b8e4007ebf10d2f7886c2ff3abe2fe6eb8c94aab49b440fba83e1dc9825f309a6acfc3b408c8ecd80724182a1d4fd12533fe572c2cb5f029b9f2cef0c68a4b2ab01debba674b604dcbda2c0611bc22d6844cf77d7f32dcb0d9d5b358849879cafa2e2dd12fa3981e88644a45af65ce6a32724b0930c915732d8433c132abe7aa72d2b778f819b3ed5e1227240158dd120dc06f83afd5e6c77028890068da2ad5e30e8a810a054b247d761ff7a988d3a94b94e215c8866e477804f0464464741601c44e22281d1b730cd60d8881d925634481176b8da1779e7a8706443314b3679484045c1ee96d2eed477494bc0712bb7c6ab98849824b579d6ab2d75b9fbf9c0143641da1106352454ac5ccbdfd82b97953c1d79485203ef846923b9252817d3372ebd98802c9604374aa50a378d33116375af05aef69a4e365727a7477a3f04d7e4fa082ccfe540c209426a0c0a1793cda4e52467cf86fa838f9c11afa7806e2fbc01836dac9af11920c2fa855b2cfca53fad2994f596c79edbbded7319cf10224d4f55518a13ea1f6800817dbf0ac6f341b2ce4b7f8e178c0041801a14e33d342e233296302415ba722d110416aff8b0200f4c95a199e8e920bfe253205008f25c1d3a760b03216250e3bc8b0c5f22200fad89084b4c0a35da28eddaf9d938d60e6bf2a1efe52a2eddcf621c2eccd9d984a725b17656cef4252c8b4fb50505a4bac3afafb4c2e389e082b0e0704989f318859377d0ae7fa8ac62fd3e89c1cdbc628a2386db7a28a308108d0a92cbce365d7341172d330f3795ccd8d0b65cc6d36a4595cf4d69061ba0c7d7a8ff3a7103d175dec4b59eec4a0e8c78cbb76cc9ae9047439e048735c3b263b8b4f483947d94acb53f99dc1346352691b1cf1ed5116427851690fbe0b35378f55f2d025e0f6bbecc83e65c86547beccd1be6b7066b0e65423789f2eb7004708474f0c22bf5fe13a268e94a139183db4abaca2e5ba0db54ace155491fd458c278c3d6a2a684182a0372529d246b655cc74a675d3e1db9aa74e34fa46ef3c6756f8e9f74fa6c626dc133546b7d002b9015286e2d8972f92dbeb7b9a575f5c65203f1456cf28685f7d719bbff2388000ff4b05778d847de5a6c28bdd94c560918e86fb14ce1085f3c9e131c498d38da06b6167bd1dd2b15a9057541012475a5d5f22f46acf05e9f310c50d11b799736f658f78cf3f5cf3db6c090a8a898e5148a9d4f82f7fbb00f3f45b445f5a4ad00f138e6e67edcd9be5c04156c405db19dadb0b0ea3dea86cced164a2008d0a33c3708010931183c41e855804bfaf0d4a4e85b0ad9add58888b90c62cb6f8ccd61a71e1998b3c25b9326cfa80628f20e87cdce008a92593d60f30abcfbefad76598a792aeb1f3ade22dec589b6e893817a8e1ae02a25a355698bf893724faabb9e6d4b28ab13588c64c433426d0179631c5e45da18829535e8dfe1183e2b4ac44eb47cc91a7dfb92d47bf61012ca9d8b93c056b72a9b7bc56022d768c0859ac88265fd594eee8a82219643e4ca8433cf7a68e0c292286a6d5ded8048ceebe28b0d317dbffe2bb665242eb0f1a69655b54dff0567df225dba1c9053cf8769c39bc426173e20db3813a1bb2f5a427dc37dc00d4804f0b7a0b8f061cd517ce07ffe3003cc4976d1c7eb2e280c1372ebf7ee79fcb990f44776f3e5e37e642a1c92940b4f61d3667fdcc09f0aa13379165a5baaa867db58b25556cf922ed838fc0dd202e6b000ff916a4d48ff5c23207d38ba262cab4cff6baae29128990706480aceed12c95b10024977f31121db56535db6ce6f34dd78eea24e2c03ae90dc1625cb2082eb6b01312d2fad88a8eb3d935963899ff7149b9fddbc067ab507be4cf772b8b04677937469485662c1d0abcc8a983d55c8fbc420d388706dfd8921aa232b0b8feef723af07218e0b124c235ba4bd826e6c8bbf4fcea21097e11874b99d55b2d3b5fabf11dbaf7e18e94c38301937ef67fbb6dbf105885894cdb0e07adb7e9e85e1a459950e063e906b086f3554836f3fd4ef81f0acc02caed1ef99f268cf50e3b9210a4ec8ee358f363e09f8322f9984a551ee1b9afd5ce1b07156f1009f0d549d7c7d351a38d3673b64ccceaf983016f1d018fc33c1a462df98303fba51f68e05c2245d13815418f29ecdfc00fb74343aa57882ac872681c45e74bf2c070e43a14571beaa82510242e520a8903ab0406f85ca521b3c85d4a27e561ef440ef098957c866391e0c53af7dfd45ac26828e9c2a34ede99290e0075ea5fd1229456fac5e21edba2b16b98c84642892ee92d77ba49fdd2ed82d2ded75d0febeb144dcab70069cbc0b7451353992d42d38d99db4b250750149a492534d16cfe49fea1af79a1b02d25da4da09a103815b07a997ef7b271bcefb39c11291f41ee595eb3e93f173d2e9de4e675f040dcac73472cc0b65e121592b9ffdfe2c3a4b77675564cb48e10a365495d0a94796cc717e0946ba761308e10c3f6f11cafb396752c66d2a575c651449c2050244a34241fffc5b2dd9c71ac163e86b1816ec537e90e0be7e09411e78792c69c6fffd35abaf0d7aa2f9dfd4500718de5081a8bcc368717081660140f58577dc1d077701abe99be1338e564ff47c05f249b85d92de58cef003a16eeeaae4ebddf736e8f70d5f600fcc99bb21401961c0e56f9b772412585df53cc026729fe20f5b18b0c223ceaa97a1b5d2508a9ce5631ea384a7e7e85148ba5e470174526aaaf671ca9aee9def91ade0f5c8e7195067e7594b7d12e955d1c930d3c23f633568ac979e297800e8f9e384e056285b74504ebbb52fc6b49d65ab2104c2bc2ec73f8e1906b571ceba643159072fd19abfa5b65c5dcc3bda60913b1fdc3605a9398f8ffac5f9aa246474ec00ffca32002b167d4c75c148c95e457580fffa48cfa400de4be945ffb31340ce134f1ddb9ad4d6becf315077ebb7997dd2d8d27798f3b7213a0c1f155cbc34d64c37f29889870275b039bfe62f1d2dc0f66b510c10116f4af8c880273bdd3c66bd255fec249904bbeafa21426a22d0fc6df7d37f9d9862247749d5fd32e863b5994fccc86ae84ffc56de75b986e600074a5e0c617fa16bf2bfee30b6e0f6f9984dd04ea88a2a5d9fbfbb81bccae66cc15e3d5f603721a0a054801711031d0c59c881069497aa15fb765c07bb60f0f3f3e76240ea8ad7c04465d9a21972da52895e3ba4d2eae4835f55bbe6d725c8b29a5eef86e92932ba94cd5e5db46b925c80384f3890f9f1219e0110843329911a803a5fac562588d5f121a3df8efbb2630e881510ceb5781ef1fe55f43b34360c49e444b944917869b97260ae2494aa2b48275d4aedc3aa4924cf6d994baa5f0f22005d71038a83eddab4c1cda3985aca60302135ac0f259c3a18226ed3ff2edf579b75507f129a63a487033d292c8ef206670373cfb591a8aee2b251b0124425c3884a16559af16137115be15c054a078c1acf95121f41fc7ff031ce70ff8147b1d4d2e2806294711a6b7935d67b949224242e13d07952105b7c3fd145a816248a4900235649dab0a1700c00a97725523b35fe89ef07aaf3adf93adfa339770a2001039db61c6ba8f64b0c2520fd9fa8452d8d4395147c759574b7f99a8a81b628efe4e05b3f005f712357556cd95e00e0c0d5cd87023ff4c28fc3ae8eac6922e3a69d804c1abc4dc94925a8eff5776c1ada2f1120edd3f0e4f36ebb6bd1c8b32a6ad571511ee26ed94130903bac9d45669981fce989acf9f913fea418005510c8c85ac7f0dcb8181fb478548f52761500626ebadc67ece56c204b038f8474c7b1cb3995d7307bdf448e2076ba37600cc0335e1eae02cf7609bb040503524ee1e13bbda4d417aa356997ff29a315b0bf8a454fc4c68f5abcbb51c03b291f43593843b200aba8f689ffbb84bc574b4a54faf27b85b554724a4a31104a7e00840e8b84dd6b384d497b3c5bba0246e2a9d55326cb6411f4365d762f8004f299e5d93bc8dd4815121cc633b96db5e0d5b01629772dec5116b6b979dc8ea23583d0def9776f801371b5b5167b3d668632c8a2970db180b19295cd933c2333be39375b74f0c0e44fd3c7b12c4c25dcc62dc2cc44e805854733155360fdf484329256be245e64a99efb32f4f9b1b534e588117851d27ebb41fdf77c5b9d5817dd979fec7cb5012000a8069f21b8d590195f079a93dd77db5474a45e675df493028ea0fc1e47b4a3b406e38a93e9b2d4c7b371bad4046ab04a22184d4f8ad7750c536b824ae4c84b0de1185c63f737a39b84aa5dd51215d2c4e669b7a1689b7b63604a98909f5676b86c2f2802d786a887858776d18408f00795578ac7fc42c3343b206146cbfe5997f150a676e8ca84c0cad2ba2686c30079fe10609e0d80c58890fe1e1562a6974e4efcf0f586f807b99b06a44c1b4568ff78bd15c84c4eacb42ca3cd03f0163c86c135537a4fbe61445c457953ca531e736985d0a3729ce60125502887c70a74392b54a90e37b65a0f046546ca2d4752c7361e2cef83329de4abc3b30cb9394e04d0c1036dc974555d7825ef57a57720903c39452a4ecd3dcdbf130b8082dbf66759cca5fb77865927c0ba8e8a245b177240c8dde4dd0526192c25210fe16adcd4053f49edc4dabf2f4c06358c4a9d50d7549b12334b9fcf0c74a6411db55cd87876f4427bbf16f0511931182e5c62828be30e6dba566fb1018e4e6416f291dca89953fb54d9d14071c375a060fb7daf14142a4c7cb54d03ec23a48d8087b9c887ffdb80e922318b23b2bbee5b058c51d0dc990b7b321d1f87afb3d55a9af2acf44aae48b00a2d5fe4db2efb71aee7236959bd96f95d0fb353651fd045af3e9a724805123728d80d11a9cc992676a7ba871b8a134dbd838ee349c3436cd4531a933ed1b4e71a234c68089a8b7dbdc3751bc7f09e6fb4c594c80fa4d7ecf7ef0bc380df826fd7854506194a13f8e21c863b1609874dd8973bd2a78252c67c0eecc3b4b333fbc2215dc3db45e8c4b8c15a640cd9a5d441ad0d240d7e6e688777d957b5e1ae57bbe07369adfc8cd411d63a104af8a654d2258ec70bb8f4f7c38e43546eb936a9096810f87146de51c456ad6c022ba7ac89cc68fcd1d836f91a658c74321ba7c13598e3480602f8ee7625b6adeefbd5d78ca58e5cd1dc8a18174d334e5220dcf165d5c14a057f022eef752ca51197f6bc3a2c9a37794b989a25e33f95f8275c9c04b4d9610a4abf664878cd45044d51d882fc60efa3e280eee026e6b286b2ed534cbcc2c6c1856ab964a2825b6c655ddabb8686ae01ba9acbb14929499058cbe915c669653f54564a527e9107a2f722144277c53749033352016f58ee298f27de274ede7a92f2a146ac9148ac52e28a6a997900a18fa9e10a67093edbcea758e02642504a60b47da7e3e43f5feca433c964d1b367f43efdc69ea37dfb2c4aaca42c86050167f0eab5c84cf6a86d2f058827d187dccbb069b7e5ff24e1b8299e3cde69325623915a679a1024e33b4e021d18f452a0af7bac907d67b84ca9df0100ba692a122aa1783e721d984d0272e1971c460430b71873dede9b0002bd27e89fd24c613aa5fe8954b36b1f5fa8dde50c0c25aa6ad4f657ea44ee0c4525cf862e3ea30c06e14a09b77ba492531c548dd75dbaaad5d1fa1597ce4607ad0e24f6756c5bf0eac45b92a2c66df536f67a6c3cb29b3b40fb008aa509caffbcf6cd98d9db79bab94aebd1433ad982cd2e55384b4c6a23f9815a46b185af4067c2254c16cf556c68eb5f89f7f75b44e71f3da138fa316f70bed44f797ad887e5128851d8384e16c63bcd1297f9aa1d2b621977639d2eb1f7685273bbd288ecc409512020df625f393a1cd0442a807441c4f098173c6bba7d4c335fb915689ff9a601be3a73c32da664b42fbcba72e6fa36d926e38e984be6c4d43b0f12409db9ab7bebcaa073fa3dfea946b0bfbf4394a2e600369c62762fa74039fa0aea21ec9efff04ecae9b710a24c3104e2d9d79398b6f12cdb34b01c27d4bef0d2ab0731fbc9219ad23e8e34c267d0163402f997e9aed14a973286d9470db7c9ff2d7f9a014e552504cf45e00f34d4d1695ea85223e509df8c51bbc8b6c30626bfd1db20ad1fa967f9f127e702456d321008acf5b0373cbf1f00fdc25a8ecda23c7db8d14ab90d02fdbde092e88fe746a7f03efcf9deb2dd48ba13521a19017e0dd9272669f2c90bf090f3cb7426a6b78e4e8401af2e2cdb843dfcfdd77aa07c0718da89da5ed092a65907a8be91ef814f35ff94e2ec064c1c8c20bdcf0bc2b44145ee07b0b720b15f04ad42a42f07ecb79980b8e0c181235416e07b53db12f973ef81e118c27c618b647aefb2ee881b0817cedc8ea06b75a71d1b23b5606ddb5527cce3f4cc46d86fc2ed8525db0b54341a1c229c1b2f90a41306453672e9299d8008632b69b90613e22e8cc5a50d0ac2e878d84a29523055422d67cf1e6b09f53a397bc107f8f84b5476ccf4b01dfa0fd54bb58531b9ae74d70abadf1c27427d64ea87bb388e13d30bef302f49c3ce82000b1b6fa469af5025c5cb5c252c294230d8d45f301ad6e1c8537d52f8ab0556119333badbc5d7a05af6cc17ac18eec3a294e393a572cb1f4c2a55e0687f3c26c0d0c10a91a6c69110bfba6e5056cd87c6f4e8f63b66878abc293fdfe0ac2505eb0e152b4c1aa5cfa26780a4903e258ca0b8249937e60eb994f3e9412c717d080832df6faa13ef0142221aac58228e1f923d6cb70a102b346d6cec3f1110fe04d8976f4ba5e61174b5c9d42645fb26ab793f965c02e8b6920344dee42b7a0fb6cc14557301c9bfd3231453b8685b89650b1d6acbe14c680b6215b2a73e342103969d842d86d9c5efca69f61bfe786ea412369ad815dd258771aec920675d1d8ae34ae3b0d764d63dd6868771ad74d23bba5a16e34d8258d75c1743792f92d0d0d7e6c3309a2be926ecc8cb671cbb30eeafa82d1c194bba754e166ca79df45d46e2f04b78040c2ba0a2f87b89704f416e22e1dec9d0167261598842695fdd149a50700a5f211343ddcf94ab3b8e0ba1c3357083dbb3b2709fb9ac426e8b3733a1274ab98fed17d289af84b228dd0cd26f10b6bd3315740c772790bfccdde1aeb6d707ada299c06d5d7f3fa934e52a92b85973a8e4c945ea5e2ce3288604b9b36c8e00548d381cb0ffffbddf160ae3da3a2b78c4ca23e1a652c06d6cddf08f61e58108a43e4c0d2444985910428c4b9e20e70dc68023f2437f9fbc89dec4d0125c6742d1b132bfbfef09de8a6d16b942151e57a6a426764ace7efc97d7ab81ac8757d9981ba9b5d1d4470fdc98e0ec4869e4baca222173d588ee058356f4f541851d67b7e783e88468167cb81be0ba1a33161314e7ea4a2c38e9f6acff78646ccb8fa62d3716410689e726aae7e16be7889d38a843b3c3f0ea016bc2e0a493136734fbfb55a7ecb3e88c7543279938301440aaeca0b23c7ea9b39adec84431e4e114011c333aabd459e60e3f632dd874bd50c8321af274235aaa473fc7c47d08738074f1f58285309a092ef264af732fe2631fd227603a998e877480426b98cc1ef233fd7eabad2065f70683d954250715d735651878f6b4e6cc2111003d4914d357d35919b0716970f879b56d2f4d456b550cc193ccca4adc17e027bf98adf491e96f1fd238d1d27ac08246511eb2bef83921b5186ba140178d254e3f0f936709b140bec607939ff0df9e9c65faa0e42e01da8b9c9c1f7b2e4f062e322868b2396bf808eebd890d2d1dc557c2d1d1d9501b9e516d735b9f0a5cbff7dc9629c8a856a5037fca6def9d0c1ea9ec80b062e2dbb50b5de8e779ae74830b984f55ad1a1cd2a6e79e3c56986abaf9fa225cad405561b671aab8de651fbe29c3e305204b2d7a092cb2c884f69672bf005ee5de745ad43f5717387d6f103ea8eaedd34fbe1908ecb22e971ef20cda87fd0a3a944dc7ef0af84414b5fc67a7de711911da53c30f07461e63f61ca7097268e71e610d1b5c3c2408b7012378a9433414fbc318c6f7ff6d8d52154243535c1e175869ca12d031a3e39322b92400757a730fd0a73b8deb82791fc52a5375fdafaee29ec7ef78c2d2996b43b453d45fbc1ced874dd5db4c724ba3b91d5bdee140a4cfdf93b8d70834b645a4564e79d06e2d729f3a4ba422f096dd798228643e38a466ed21ce1ff41723408e4f747c724647d2205096b7c9d632366eaa0ea506eee1be45f642af3c35e8dada01892efb26d7e7722f87e641f71f892fac0e52e73ac200eb9a13c2cd491ea324de50da514a8d9b98d56b3478909ff9eb04bebd38807a9fd92e3b8bd2a718d70b29bc8bdeb6c505e69a1c2773d1948fc2a0f05c77bfce4a428cab734d32b329d7162a01a9b7ff39508af4906fb0d571f8f1ae7bd4ae3b2cccd2af33f02278892c3b68199607a611434ed4934a278678a16f5964b8f11f787dfb60097c33795200e9875e90c452c898c7d688782686563d346c858148155822fe04d628e3521e737015e387d375ddf3dc558b39e16a0a2662ee1546c72c2379a349fac7c4940c21e7322639351807af57be27bee1ca7ef11c28274d20a816a604c01f236eccecf3729d115145628cf33224cf56e88d0183a735afacafd6fea0d64e417c2b207d4323969aaf266371181ffe1ae2eed5a918c29bdcdd4e6ca720816db489d5db7d83bdc54df03b33b4138be201c3ed63f2130cc362cf3d8abc3b83aa9881d9ce036ddf22bacf2af62f65ca8d2aad8c11683ed0649765f2917cc27aad703d6499bd744744a2a5f7bb1eb1d992610ed550f4a55dbd95a987423939752525c94225e516d6c9854a79026d355f9d9cb4c9440e578fe350774d78c6a5ea696be1ca9e37ae1aa0c3dbc9372d1234881130650132a8baabd4e3efa31d24a50e1c25e83f1d495b32a4bffb3e21a85053c2569e15c136ba72025a9040d9d61cbb784179b409e1ae251fa1849764d14971c0b56562d554cab3dd3189ebc9613efa990fa76c84c05f79a772a36dd21ab217905adcb913c920bab6d94fd62d6c3fadc1003b786ecd2e393ef0d482fc072ee8f97ce3bb2c7b3e5c2586edde2ce0197ffc0b0193093bbb593420991c6ed6432b552e9ab83585924667a128032b7641cf2c7e0028054abd8c6c5a6ea918cc1dfb2c703660405ad8b5fec13778ea61a264fec90022a53194d642c37c97f800ff9dd46e79a23d446d31e69b8691c51b4872236599c15243db4a777875502584261b3425cc88611c7a99c6a03f29b6f6ab0088f881f5b740925ae075dba1b78fb06ab9c79f57d8cd104bf12c51f68e13190eb6ab0ee2253045bd38a4b55e541213afbfca7162e8a4ff03fdd2ac8793809508d4d8ed5f441ccc9107d37e6097b36ed946b9bf225fb947fe9ff9ad9b9d993b3716937dcc03764c2191dece267cbeef66708f348aeccfe4f59a0ded882653e78752532de22ed966f9e022de03cf4a1dcb345ce2cc063ef97aed9b8504f3714d5c42797bcfd6023d2729bb8d53dabb629ac4d7d83f9b45b4c47fb1256b82378965dd3509b62a9597244320fed618336889c2ecd06529f4860c2108102768d5c508e229cb0884731ccfa72bc6e4424ad82af9975e48ceac86c06eaa47417956ade4a52da3de6eeed31c6d440661bcf6761bcd21db6e602b77917c3c775471c49e2a0dfdedea2ef8a4673011dd748ad9241eec300b87c64702f72e142b4b6ea3a6843e19ea39ce3cb0cd4a0c99cce961429ba3f9f634e1184d9ee24d5b23b78d3212755d90a68ecfaa41163b14e7a2a4f925d2e4296513e3929017297352996336c0909052e053b84b5abbad38c9eaaa42619b2486b7df73c7222d34cb4246cb59fdc012577120ba28aabb291c5a06b68a1065648a2977cf990efdb5b3cd952cf40783894ab4ed90314c554e4bc84eae9662b3a8a5609f67af8ea21af02d5499909158420a097e73650892d158a9189556d24ac4e55b57630ac6e2009f6ce105c9edb9d35e7e6a409fd5ee1315c16ea5b7fe224786b87e8929857588ea433159c40b989b640d98efbd87b8d8a5c0d6a8d04d38d8c34f93d1acf7e8d1458b25b1bd47b4af604cb2759630e60425104eb389314137d09c26358a53844a26a4e11ac452cec08a3bf4f510a4718b61a35ee572785291bd165ece53d5d2141ecae3562e55ca954834268df9df45dab338753a19cfe5a8b41e3dbab92c642b285f435057ec644975384f883d4e79d224192fc24f2945172f1c4394b1c85c3425f83a56539327442dfef819724c1738c873dc818dd208c4d59418731e3103876e101a82371887a42fcc9ac421bbf344d482f35b074698e4fa6893c8080b8d12788acea47574ad6f824b15f02700c42870cdff4f1056c4a5b1fab6c2fcda632f6981ee9a01b84bb3ec738776a190631618c2f05a312fe399aa9bf2ed1cc1c4ada2d4ab3f001ea8d0fe78bceaf8c08a7b226cb3e1319b3766dd606b2f9921eed163ec8bf1d05aef8435279ff34227cd66b2ba27e9bec7b1441800874709f22f36a1657dc719692c3c83b754461c05bc25c9a056505dbc12fc72a42b48579410be09add0a6acd669f24ff682744c5b1cebc41a4572536146d2fa4b7e3bca24aee987c79506c86e7ef72b05ef78b0abfd4c0dd905526f89ba0b5811d8a710c0a70e79871ac1210ac2cafdeed01a3f1427e5048c686463c741c9c84fc19f1e852fa2a593eea6c9f03306dee60662f8074cdaa087f8710dbba37df033de915a81e310c27722cfdb884e530ac30b73e03b8216481883fffcb9dffad59e8fcfd309b6bda7088038ebdaac3fd358a97e364a4421f9271aa19ece877ef4a1e538b1ffb075118231610b9bceae81570583fad155062c8a5ba7b969b270ee256840fd9f89b85a0c455f6b8e55c72c666b5b79b131d737d900114412aebc8215cdafbdd48838b15434b2fce64550519670a1fd81416d1aa514e143f96d92e71423cae69973a9699497c67c37e6ec823ac2c1e00fa7ca54a3c71638b1537b678b162c6165b5cacf1e28b1733b67871628d175f5c9c71c58a1333a67831583c6d40095f54bac6b87ff68a6f577fd9ad9740864c6f7c74e8ca720dd12420e593724d4ea21815053a89bacbe6b7c24022570d3f9991f8d2153621f2f6ef83e48c0f6c721585ac2922c438a1895aefe35c630cab1633b9d02e8fb5c4ea6d489276919579a6c8301d855e549e16f5264e2df2c2b098a530605df86ccdcc7483ff0d12a0a0eef0738d5f7881b3826c92a3c353b1f54156a4c3ca61dd0690d929d11ce9d6ea0fcf960108596dcb292081c612318d4e40be30d2a92f53d02774e4c8be60c5318fb5a7ba25469c06df33a91fd2a9cfdb29394df8c32a7e1ba0806daea094d592f43a3023e6d563b52a8e5b8070315e7eb421547599154c10d3ea2a28a2f9855699dcf5641a298c5e50021b2b22f223b914ec1e46347e8268c7475f677296d16b5a8ec7e6e13116b9a056afe145201416d95a4181b47162021db688150edae880d5d19da310e383a857f37a4c3b232c9455d26535e00b454411ff2f7f42a4354d8f60adfb651d05a08b1a0f01aa96489f0483ed7672a640a02d085705731bd6c80144311577a282bd09c38f4f21090102ed6ce1f7f1332e91c5e37dcdfa7d386d693e5a3f7d92e7f9017cf9a3e75101acce9f4b61b9237e09b5547d2bfcfa39b42e40b3569fe7491c7d2cb961b100a24abdcb71bebfd45d26c85f1eca6c802d7b9fa9305d64f817ed3841a958c18e7f48fa20a448e4170a8ef278f85d2277f4100ea61c03d4bb87bbd67b62c02b2492d1ec67f121f7f033ab0de4826cb23c03bb0c45ce8fdba3176619171d680e92d1308abf3d0ba3cba11ee0573c268867f5625505d441f7df12029612d6e2e157c9f4185ce96abdfc4cf5498261d5e291d1893b4a5572532846277ef47bb19baf5e10992d3752e918c5d507b59a5df39680936478c30041610ef6bdf109b78bbbcedf2afa6e3b7432741ec8108a64ab0146dc148f3df36bda5549bb209fa74d1217321f46dcd474afe36057c0366d1c0338b09dec0a848a1ad2015a256a7582a483b69b6ed0191beec2d84da74d67e8b066da44ac005b1f91505b0c6c1a68581a6d720f833b8e335f800d4d7a9056a69a908a582cbd84b6f42b8ca7615deb5cb19700ee9d3add5e21e10bcbf664e43579afc0d5e9670863e38dd1ebcc3468f85e00f985783055c6b9af5464a1a3ea823410b17512ba24ab120aecbfeea4c6fdc397db16e8cc52c86248223fb70bdcf27815f3770a5459d397d477b057d2c02ff12a2ab763083bbc0a59be40a993757885d03eeb699e105393576e29e284613f5a83d33a1b1213a3b8f1a51e5a0805dad38c9bb1dfda00e0092b78b7486df01aa76b4091337c436f70001787c8d323a166e0e32537b0643335634b56ef47182bfc2afd146cc13960140d5601cde17a76c41988c612186be6e414f40a7af450aa1580703f54d6815d0eca1431b7a83ff507bcb36881594e2759fd3d029a463a20da9507b6322a7f51f3b76c8c1af1950f8c51a62b9827d063e340d3f1ba3f3dba70501d8918a527babeeb269bfc8723ea19958c2f0c95bec967ebc5d96625a869e2a81232b1cd60545421e4a08abafeb8baefde3cd1f7366654843c6b4e955186253a5441f8a67cc0c9cca51397c7a8b11f28f41f86c021a3b08d73c99e3507deec2bc1a311351885eb9b0cca8ec3399755d4910057c7fc572c25536cd9f7da2e25c5320b52e449936e653d43837b27b8dee49528328b46fdd8dcadae99d2896c3e4d79ca4b55d4f964a9309290c4c14a213e01eca3d0d762338fbf9b4e3dc7d91cb97fbb409c9e6ba2c87f4b12657ab0a26e6ba4d860c614073b30ef361b90f7e77215e5eb872a405b216e2fad261b1fda2fba432953a3506a664c31cb27da63f4c4121d28c1783976e8fe1127cddf908ea293e594698065b627597610962438f78286c246002c4fd2ed2329f0c7a86d83c0a1e89cedb3b4570dce2a1ddf489b7b3de761497a0baae725e400b18e82f35778782374566c4a92da3d8e7a68bf6413862247866e67c16a21cef152a23901a0b853d3805fa2c45d352547d12e68fe74581836513fdc7db4b5e059ed08b9086bd44c9f29eae8ba0ba7e043a268b6bf88a7891b989ab1299af266a462396a26d7646f43f1c14fccfa543a61a5a1c6a08e38c66656eb788ac9f072d478faae983709cb976b096e043c171fef32d1415c54f863756ed5d6d9f1afd19bce06c4e9c134cd1b21e1fe34fcfbd33588eb02365cbf2b9be2e780e064aebf9e4b3b74931b7d4fa40393c801c0ae05e81ae2ba12c686f86ffb3de3f95b56610fbe9d80ab8be6a6ba8ec47122794ae5746cc26cbf069739f195fb67995cc77326fc339075b1e83860b3a1c14b04a3c6dc30fd4f1ccadcb0e12986f4bce714c1dcefdb481a4714cd0271638b052d44e933808388876b5ed559f38563b28db46167796b048714313ecf247b70a45b1811bf4716a55a4a01f395eeb9be660bd7a0e049675b1830e8f8fa10cacd25160304230808241d5cfc2705a57ee949c3c4a69a10b7d1ca033a58b39e3a380d3a293774d27f8efee653d19205df26d2ef5a4e621e0bcb8a6c4c61a4cd1248d876901ef996b8232fbac948ff4548149ede3ae8a063cb009290f904c60bc91fab4cfc3f0f5161ba179d84f97269ca13611bf6f0fec64d1f520f658d4dc7aa093ac2d19de24431095255d8e379d4df005685531e2bf9447183194770f26b0777bfb221e0c5abf64e4975ad90fa7f7f1d781db906dad5962a565771d96f19d0b3ff92c37561ad83d5b6d6fe343c3696abae364d4d2bd3c7ac32df1a62f6940c9b8c34a5087855f823019c7a2013aa2fa4c717ea4b79a015f6e616fce196c21ba80c4f7863435b45311afdaf04985345dbe2f807a4e93a1ad701b98d2945f3cb7086ce81a70331a10342435306a3604d402ad8e6df83373ec0b96249c3f297ca42b739ceee736e3167d7cb33fd8863d3156c514dae171c2373641535735cd79a8abfa5571d42c8bc0bc3b0d761aa54fb73bc0b1278ce8a27a74735cc3df1e380cf22ba602cef672d2745b6eb48437a2541cd67ed5ac14b577d6ce81c1e0c0b49fe393a8c4d084de540902104defb529196097d0efef626b60d195c3cabb591ebecea6bef04169697d967794084300cd063b2c445c89110fb981bca8b76d89c552fbac292c4f42b7a04034a3ed98004bb9a63fbc8456b5a6010757ddbcdf4e1efb21cabbfc908dbfdb8f1b33a6a05a2fdbfee5a3231c4f157cde55e0b162549e983cdca5a11d7f3bd71000174fb84afecc6f65337f620022a2b6798e3a89a4f13d5ed205d11634b7a183a1cde8786431c8f9cee0c2db58dbf7e161d5a826b45dd803163bca6f40de11097860d87c45ccc5111f30a71565058b998a82dd2ae9e51ddeacea81a422be5fa73e93001246fe815f12f5a0417b7ce82465442b3b957def2c8ebbbe1db567556c04bb4acc616706694309216babffd87504ee9bcf79330c29d0b7f9b87b7cb2d83ee6c3d6c7dd5a7262b654f618ccfc31007fc2271f4c0126a8d4e13b9a365947ded5425e9ea7ca3da9164eef8a18af4980004bd9052df3f69717a70f7543171cba232bfc648db6cd43762b40f419d33fb6c64ddeaff619fc65f38e0a065bfde363a7c5d0c7782ed77e2075a6ef7200d8f51989bda2d03a67036ab06b4adfcb07ef38a5672bb59ae607d181acc24cb16f1c8d7bd62c5f5c978a98b9d7f768a9cb2b326dab66b6993b8045ed7dea7c9a1fc0fab73593330ccd277394ecc9a2956f3d5d71c42bec07808d98a5c7045721fc3b7424cf43c22f2ef1859786b327c05d6500b8459cef6ecab228c23916c7a9a3b0f5ed1aa96e86a52bd9d7c608a763a9ae3db0947efb7df65201c1ce4ab71a06bf6545f11dce02d55a68c7abc6f23ba90ff59e32de7ec9df45deaa032062909eca0a7b9d0c6cc482ff4648bb5779446cc9af0eec998b831cecbd6406b17f90ffb899eaf311ba17d6170892419327384a9c2898788614ef74ba33f2b70618bc172037ec68a535df4a2640b49bc9b20dbcf6b712df8105556b44b5026b6015e218c7bf04bb1cd6c48d8ee7227696312118a98189dbbbe23686b08c4b9973e1beb11e98f9ca49ea41becad662c46a3f98c37a828c902393b4e6d159e2e002376febfda8866433a097f1eebcbe7704bcecb475615fb74064b63f1086e5adcb04f7f67c0e0d42061b73021097670057878166b1caf06b0407ffea9ce9122a0963bfeee95f04c7b88c615a620305da3d546bb5741768f5c7a06bccfb730bc4270973293af9f35116e1b8e0b2e60449d7c20f6923c9611e1605b2c0845944f427e1d2a79b88943d739b1ef3e622fa05ee189d05301fb080b6e8bc8a942bbc35a6fd93819aa62d4c9da5c186085c928588ae35e68151813cdff9f15357b43151619c41b1a8dc0b53eb2dc09776e2f0e5416310624307bf43a29b00cb758ddcfce337359f37faacf02c3d80c5c46c6b805180ecbc3a266ce39acfbdeca437efa01625f6e092aa0ee93c07f0cf984dc3cfa0fd89e7b0eb0a551e803233aa96fc21660a6082b312a950d263fb53d618a7d2e32734a5c75e2196056ee10a5c0ed126decc61810981e1f0d7f39894723cd41218ca78c51be3226d10f243e88dfa8e73b2622797f4c72c77c3a5dddf24488eb62e49e096362ec4ba1d7321dd6fe40cd5ea75293bffdd0ef8c97054e0ca0e6b96767d4ad94a402d402f557a52b13527d930af807149dc495649bd6a989eadf14f386e1c5c2ae29bc60b185618d9177f1b86175f53dd8dfc29527fc7323e9729c120aa45fefaa09e1047aaa7538f7848af113d12b255931f12d56cb1d416f49706bd7ef8ea466a7c3a1b7f0efd6c23866f783c5a71f5342662429d994e86096289c12dabaa1d5a5c9f3a4955e8cb3b2a53c3fb1db8f167ca933d4b08699c254f3f8d0bfd1a835beb5548e3257a3bd8a38ffe90ed41f0a4936bdaa02ec7c476835f3203c193b08559ab6bb63df410cb2750670cc910b0b789af7f31c7ac1c95e0735e3a8ae6db68923e1ba6ae558393fae03668add06f0bda30b5f41d0548760391681cb0c5e3455e03320d73e8470f3fd5d81bb6cf68144ff6cd6f623d23c7dc43dc77b7415538ed6a103f748ad6f2e7745158f7240040a9c7726219a10d227c3029e7f1f85330370812663a0f7bebf17d0fb0862f6a83c4a518015e4eab418b9830420db56a34ec4f4b5a3a67c1277aac42d87a2094eb4461518f9044e074039cae4213a4b9b1e58511f5a72a45b4d3091ef41371f992304ac3535275e3dc7cf11d076daef7cfe4001a884ee2253092c7ce2785ef01a0a498ae256b6f6d2c2052f5ff16b23346281b3954346b5b541973b47809aaf97ec32ef2b3b03645c58305750e8838305e5c4c550bf41c93cba14f52bd0816f5728b63becd50f6618eb97c455e8052ea8e712cb80e1b1148db18b944918c32a813c0196b84d2ff747da0dc1fc07ca67e65114a962c05c35d30eb41f70b392ff814025c2f15b5d609ded73b718afea36f20836367e21a6784bb39fe6535d7f8a4618a349a11076e83ccf0ccdbf81332ec518668ba82c7fee0509f3da07ba6d8fdd6286749703b60f440c340b70f4842c88df337db566f394d80efa10900210a4623e0d03e8f386461fec2cbae5ccbfe67874f53340f8e484922d5b40704912355d2b48f2976d027fd471ea05180da5b8bd3f037838bd42bc2bfee61b8443d0101b004e5bbf935e486ee35172681c47363ae0297553c2f30922baa105c08102eb0152c62ea556ce82b827745d1f4cb7f28132bd0776bf48157b2d7b5789bdafe45859dda175033f85f7cc437a52be675930060b9649ac8cb2cf8dc677b8ccc9461ee0ace6fa8a37761ab851621d790b7d2ffb1ad55d1b9bb9d25000174248eae4b47cb3cf7bc3342f705153ef9c03baf41a4ed48670a43dc43255252645c0afb6da5024d324de75e8407ba6cb38139d3131d884b6ba29888d975bdb6251d9a352599799c83eb9bded27d61a74b6b0468c314b270e3186feec7224fcde8c502d778cce602372f4cd5f72e862616568be9d8b93f26475743af5524f4d612715741111835d0e841fefe5beeb316e22081a05e5f9509fb79575d92d5421f03d186b6488c4fa61e713d66f0d097d7f5b90f835a3d40827319619ad6803b326b641b183c6b08034787451dc221003774a2a5aa1cc039ef8386bc0168c228940df3e2527247db022ec8d09f35542abb26230e5af439e054d33311364c235cb0e9f92a4efa0d28dd93f36b021bd27cbeb38ef69df8d4221ab333535c42180abdc7e9d6c7da4991f8bb1bdf642c75dcc37783d7773f3eccd7565948daa7aa501c74115a63b63375c00bce93948549004eb8353e18518b5d50bf6b2a5bc9b03f0781ad1064510e8bdb1f1cd6f31f9720185167d9c42323d17fef5cd90e91d513460553204255f33a03b4ac04869a2d7ac54899a17b59b6dab912951153425dfd178fb80377159dc8f427904646e249625ab2599ee5ef7039db1c427f065947b2c4f843e5f1707c1d5666aaf9faa5e0c1a7be67ed392258e770fb70da221f3c95cf318b7cbea886d40b070ddc60cec1128d174fc911bff2ad086c067b96559ba39b09958399f4051d7a36129588a40b290346690afe9f9b2a7ae1fc5452067cc6504f1375119f84f55f70f08a1653abbdb163446281f476dc65ed1135277e57fedafb23e62d5b791eee76120cdde7b3f07da1e5e2194b4bea18b0c77c74825614d3b07826af2f9735c1693898331a88598b864c931b4e129f8be88c81ac505fc5c17b6a67c584dd67af761567187cba9846665d0956a12fbabad0671fb81db896b3bcc003228892ed7380e330130d1e291858e3ac0f1452244eb7c19b48629b3fa78e63551bbf23f511dafd4f8d1b7919a643f43d1bd12604fa0047d7385d3f277f9d57a80ac2c252774b479b25b57f3fbeea5b08ff181fbbcfab20267729b60e991004096f2985c938dd2350a9710941b395ac359547902270aae9812acfc34bfbc50b63d8aa9c310a9fe285d14f2bfd16a7246d5e462aa82f85c8753d178668b0745bb74a3d5cc36708d01d14b2e5e307daa67b24d57b3716276475dbd56c9db5558f5b5a53048a8d7016b5f138df35a93482563d2a66cb475710420d4c87d9891967886e257b3e33cd83bb75b338241b4852c858051c166301e5a279dc9b99c874baf59cecdbab8ec9661c72205a05b72d9837e5e13a995cf0505472f3928f9803335cafadba31ed4adf6f454f08dba5e8c0abb5b90fb0fc5d76d14fea831fc7c15e3a680bf2eb8e26a8c7179f9cd5d80f7309dff634409cfb76460e465fd1583b901b447ede8892a341a65c38e8549957f282041697971f459cd87d4a3434b7f45ce40a31c36a462d3e809f1514d09ad0efa0c3dce01748936ef2404119a9b73a62a9c03f12245307e6bd55287ca8faa7a1e86b6078342334925f21edfcec35da94ac4ac1eee8b15a922ae04eae5b0dcc4661acdae211b9d1500ab17d191da1aca8225d580b5bf82d5c150ba5dbcd5999e2e3814232e195de9b4994e2d6fb2fe3f6b43b29d7956d2119573b0cfa34a1ed8133a57459422e3c4246c5dc60144cb293d4da98dc824a2e4cb1bf4ddee5679c99fd5cdc4b9503e0275963e13440be59303d4f4bdffe607d07d5f6c52aff76e4f1a5a8e9b42bba97835b4955f0468918674b04ba95591d98b420294f11d6236aa4648a4ca46245c9762b111f9c566d364818bce9ef120ab45d4ac598ead45986c4424e8247a28aad29e9da3c27ecca70bb37c166480435bd2028c6c5cd797888a6b8393689a296da0866b1024f792b6c875948687aaa40309a89b5f903cc2d2d63a4a1d3991c28e5f2d7f446dcb2e679691207299efc15ee87572a10ddfb335e6da67dd400b9b9b6256971209905189e6ab36884ae30d1949f5ce03c81a7d54d3e7d1f0079ab57d8158137b33d5342987d98dea08b4c127dd952ff40956d168a346685049f961ab6635c1627f386c36bde4c4064bd00acf7ffbaf413678faf70e08cc54103dfc6a6548bef5ccafa60c5f365503ce0e70bc581b414fb0c501880914d21e20d48c9f3e2799c3abd16b6b5a9401baa07715534955f87cfb1bb627a795b610d804019dba52416fe408ae2b44166595af440a700b5f43f086f34e6e6fce4afe82e0eb3126aba3aa32cb8bf9628828a5addc522562474375e72d4d6c790aa739e3a38aacda7a7b2c440109413084bbfae1f2f7c5bfd408d53b8b9bf755bda213cab3b9f3415f1f894b30b3dcc7a6046e7675f5b3a28310bb74eea35ed67c83b97a47d8ac920a2c782771984297ca9234b6f2bce007c35d6d6627baa2bfb3e5487a77f84528ec9d50c2e7b7a152569fc033cd9558d6bb026a08096ade932c627d33374690180e24095b4c8d0e7bbc4831cc4ce63583c7911b7e9679c2b91a3d8c064ea461f2735d1f15d99cba5576fcc87c32ac093a0422b14f808cab14f32fbbcad8826e391ea1e808e88866441cace1a483a270c74fae90904ba7fc11b9be8d405af0ea73f7184e6528196dacc5ee25e518e734c4f5cd3f9dbbad1546928bdead044612bc0d32068b7f301f9227a1ae0d35cf0b61377d1ac1b57798eccb17b6cee58f14890b28c58399f3e67f4229c90ab951fc9506b8899fcd6e95a49abe20fdd6999f26d3d026f92eeeeb27c6d83a8cc329714c8adedd8f8be95b323818af50dc2166cb0e7a295543b0c2499701b31dbdb57331cdba7276422b4c1e2608016d8442d3a370f4fa22f9e62ef35dcbeb27053f284ef57872f6d4b6213324f0cf654fe68dc88f97ce9161d51b28c6cf16662a0358a38541a985a8cc34ef20cfc706ff106a7a7211ea3f76f634c1886bd18320b8ef62307add33a82e79812d3ade33ba34dadd96cbc9be9cee55d4264fdafc7129598367ee9213f9c2ad63da7554e1ca7785b2f1ad0bac235c78f70d790b38c8f61a35a02e9c6e11daa8188e37be39d6b40560e24a8825dd7655b15d88ef41d79e30ff0e7a32041325f6b46f3dd4398b229c71619f8b50ea0a27cde209418d26b83a907589ebf708a84ec41cc30b124973dea5a37f2909d9d5bf2e496908abae571ce359fa4b437c86aeee02c08b246065a7760dff3c1cfa817c31c59f620cd32a746ee952b25b15e1200fe329b3bae1c686ac7429f0d48b0598b9d16f9760224fea9753703af5d12476fdd999d6918c2d77b2238827d6f518fadab2e6f7b3c98960ac5f2609cc8afddae54e3ac61833215132758ce405bbc0a70eeeb4314c5f37ae2e700ba73c19f170ee0524928db512abf67111c1890a6c2fe4c9a4b7f3eaf0f664382dc193dde435fbd0ca84cb1ac323ec2ac3f2996055a918d83f173cb9f27ec041173cf9cdbbb1e4742585fb45c982f3d71eedd28905336bb531b9a7279d52c413ed64ed02d9866a145e96c6e079e8784224639be5b264167f8de8104fba23c06ebd3246d0d787c87b5aa5bf1ebabe96868d3de3cd8b537c2af1c7fa889419a6c2695b909e04ce98b392aac68fdf84a4379f327da6aafbb8d3c5036506da0b7d30e8b5d151e223d0c13f2ca85f769f8c68f2c8b1a899fee278fb6d5c457a86357f3501c4469c0529931c5276d7f5f19d7ee25c5bf8f037a68bee0f3854fe83a5fb9aeaa96736f99b8bdfd7624b68ad9a8c7566321256631aa6e65a364c747d95f320c434d3f25ec2a8512dd1d04969ecee0de828e6cd640d7cf7e03ae114006ef0b50bcad3b878364e32a5b6ba0718a7e931e780c30ed043fda17f5f94d2752e7592ab4f855aae610111b735f6c724d24d3feabda48b575769dc18e22ba5d353165b8ed11b0823707f948cf601b6bae78f602e83ff6544dad28e6df16201a94fb608651f749882b14583c1289e71de9fc3a44a80f9c4afc50296fc1c1f6b24e1bfc4dc029589f742496ee228af185892891944eaf254a4c59aad4400541a1a1fd6f4f9afbdee8115e5d52007baba076e98b8cf4ecf6a6fb65311cac83939213f9c21cca0a7e156262e94b20544122ef7a958bc74cea9babafd90044db0f5d27acaefbc6d5b79691d4f9e2780825d3c7257fd1d848998b181e0cb17e4a3b18941c1eaf5b0e4d3fd8d2355f110d2fd96b1cf729b773378538e0a7d9f06f06ec5159bc73e9c5918ee88603cfc92a9da8e3c590507e71c265490d57c7e288c24e1be863b37d4c610b6a3f8009ddd810342ab732cdb7a6c6fefa1ee81a894d18f0a7a82daa61aa1f6094281551ede8e0dda645d886a8fb143ca2f88982efe046c1c9e0485717ccb3742b42709699bcc901389c43c287a22a6e0975ba5c417ea9a74ce4b827e05d0ccfe7e1cbc57d2b3f08feab6316383e79b359f46044a8971a434b8f1d4f2236d0f47960caa0b104502219ccb59742abbfd9f2ebfe70a15835ca071fe9d2fd1043f7d76b85cf11e72059e2d75f829cbfd20b0bf613f64c6bcf3eed0ac7f6b3a893ef2bb23fa7942bee9987124a8f8574fcc067d3bfe6264ddc47b73a2118575045a6d9b1d4ea6da1653b1b6d7318a941dd6fa4122949195437693d9082d22ea87e2b2f3b442ea40afede338f5d1b28f70c546367b0157433dc98812ace281107dd4152ffef22c5622b700049e48e453ab447670a7baf217f3b9483cca50605954fa48050feafae6c1796b54ee60e9ba8cbe326bc68981787c77ff7635dddb1aa0bb67b9ccc4c2ba0b1ed395fa2232e43a7e693794c321668085a794e762aba4afcd18f308adac9b057f2540acf40c648a8a4dab45b052725ea7a09fda677ae0ed3af346b9a93e69c81cfd28c00e584a55a37f812a9bdd854f3c0ab7781c931d232eb1c2b851a9babc4c74d240042138a776b05464252150e11bceaed4fbb0bc686e82a5d109d56c5805c49b5bbbb270f49440e654893116741a280feb56f114870080829707a10cfc1dcad865925e73908b3a83b720b39ecbcb52673ff4c34e45a8ec2068288951999c8cf3a48ba53476d6930e486c3d8de941788fd23034e4a0bedfbd7da502283fcbf91f6c4518b28ae2e6073c055aa25ebcf9d08fdbe30abefa1251f712f829905e3ed3b0c81cb78015003706355c889d75216dbb505d00c7c40367609d9b85f372a91cb1d65020c4d9c82d783a255c7d547b208084e2663199ba9f0e579dc841b20bb3cd92b2244614959c39d61b20e7f1ccd6e0a43fb25e22c650bde901ff21651bbc795030ad25548d1373e85d05fe4300b64b229d3273f60d90212bfef5178a98be82dbe7e561544febd003b29ed679fe3e421f9d90615194c1658c7c0969697951fdddb41050b1411b1c77ac5c7e8f25d68a92a514d0078b9014d2c800089e31f838b0333d8d6c46a7f94046096c0679d07fc242902f03edcb7624bac8eae969c6fb4708639672494a4f67365de1c6c40d00d56cbf2209e8e0eeac77fefc73a0e37a0e6ae344611fc25fdec90e778f48a20eda50a35e48256ad1595f6949dd1c7496b3a0ac517533cbcc9ad42e700cd815ac405215e82ef098b6b7ac9915377f5b94c7d23b1e451ee06a79384849596576bf183d8c09d4cbd2283ef3cb8777e5d772a6f9395db3037a67e52b35f693718d1c5e505c890260b051d63d84edbfebd560686c9921676b36cfc55c20ca35ae0eb8e11a177a0e634ef32e2253746a782015aea5a8ccba41199772830c160708a419067633b9d30bba933807eef33e30f406973113ed4cacecd1750b6190fff58b38daf22ab06ddb1f3bbd8fba2db0d4a25f969ffdac06ae3e086e8a80fa35dad9042023586c1c830ff7ca299eba01fc93f5f4956a2ba882fec6353a113299bd84c5916bd095493e584f6b180f81a63d5876f89b3d9d9413ad61fb50df11fe2fe24fa7b188e98d8e509daa844a3609ff1e16d1e76f8ea46dea77d83a8da4b8b8e5399bbd0774f4bca985dff8d098140cb8b72cd249c61fb29c4b710d05129665e4e016830ea1de913b46dd8bb95c2db5395125455efb85e17855aef5bbc6c1cfa31145a932d00721f9c33879bd15064f78a5ddb242432cf0ff0b5a0a989e336c7312d04829aecdf36169e89fa4d025cf08c63cc8e750977b2539f110887e395d631633e2fb4715e36587a0bde726c64c72fe0ea988ad9a0a08923e5a3bca925d466191d367fe7899cedfc3a647421b4a7cc2b72fd744dd78f3b9a791c8bd5c27b7a02058f9ec91e89999a5a8d1e86368baf6f8240822a4c7f7ed5be7d9504cde1c840612a0c1bf4c33c4141494b4928af983da6d36dc8475965827140d9c872c0dd1ba16a62b1c2d3a94fcc24c179cfebce3cf108355d1c09eacfa2355a51afaa8d92470707def06fe80f01109bc037aebb9f45f3e7ab738a1d7f23410175ef227bf8d835ca8e6f4842e231342a0fba57dcf6f54a308668480600cb9f1e063ddaf1e9a0189bb35373d5aca6402456f1b94300f976596f8ae37500bbb1cffb0d4052c066d148af94875720d8451a6273c99cce596b50a220bf8b3916e8921c8d1759f3d6058b2c0753a546bf566b1900fe7779f68f20d913127b24e9ca2f59cdbf57d71096918550496405f32896858561098065e98602d37ce9c580a14d4ef95db564ffbf615dadc30844a84c9d4f42b98b3a7ad2efa3afdc5297c3ad22bc8f344207df2d7a89d3c93a1ff3094e8cc9bed49727f6f07254371deed2d7d6e3244973bb33ee7252df97afd4984092602f83a4d470a9ca4e290ecdf57e5a3ef3fe27bd0a0892a56e271836e4605d812c28eec041fbb5f83ede7791b449d9550a3cb3b8907be5179631f0485ab0266991b348e48a077d630982254415027cb09e942586ebc9eba1beda2371f85b98f50ee28853a4c105e98e92c3abe90a7b015e85af54f4e49b30ba8eaa281184c3bbd466fa096526a0e4d680f3f71df0e5a29f544c8551b134233d564e9234484833c53796ffaf81807906377ac31a8cae12d313e0012b25c8ecc1605bdd5c305320ee64b4a22afa64b9d0964f3b6550e3c6f26375a1c6a2981876b588f3e9b6f026f2ddbde7648e686af1f01179a46109bf2fad16a3b69044923b49addf9816164347449f27671dadecee680886ed7b623ae0c5549a95d2a00a58f9f09585166515c8658d34c9e25b92d4ec959cb3d1fd0a68fc7f50d22b826bcb55721acc6b226fa226a2cf5644d379840ac7ef90c0c3924a333b181d7381ef3519d9551c82a810f952acc5032555022d70d64a9c4c0694cb7876d0ee1278e207b34bcc18b91a48ccdbb1ce24049c0bcfc2af17d00b461053ba5407210c6838ea5e113fe544553627c1b6aed512217192088b9d86b02bdb00af465afed0069340212c933d3f677e1806a6a78755c80570cd60ff3838f1770f18d84d0b5375135cffbf4143e9404c682756475f4bd0cbc129c2b45912fcc6c3cf22dc92b94f280497a847c523676ddf6dda7fbb9bb0535f4c9b366e467761219536fb2cb310048e2f4721ff8bd3fd12f5e0120b1f25abee2c318aa903fb36217240a84638511112de160703851000aeb5b29dcc1e649eaa42744e71855919a0d360700d2506326531d6a964bc97d5969a7261068e194a8d366885ae64440d9eaa830600e423700673c4f1957b111e315eaf2a5f12da874d994307c3ecc4b7e08d2704f3bbbeaef9968fc25c3fed325a878581b01dc9a1118c62744b5e61c2a0a52030b714367ff9474a603febf52e6094fc29c257d10c565550c22d14b7081e21ddc2d2ef1ebc600cf751dc19af67ac86070d80528538e27807ea8aed04aec8353d8fa1c9de9eca1cd48d8ab4234945255c6683bc8960e6fe199056b294ff2fbd7ebaa33b325e8d5b05740517f42277fbc55434f670d34b0ab576faab32981398dca24b8ecc7c8e31908cb2e6406e446bac7c63539a0ee3086f882cd3acc128eb08ef34dcec5f90e6d8aed52e793bb0dc1bedeea7521dd3a481db3f9d550cf392655b297bdb44659cac040fc12be2cc69c16f875cd26e197f00354864965cfd829846cdf0af58d78aaa2e0cb66c48d6c3e636bbe6df292e62dba9e21b8925b64bdfea254afcc63a1a0c7a93f46574e37b6db4fc5636014c0aca8ab0fb041e0ae27f6e0e3e67127ad7e42c68afd4dec935482cd1d97d8d40c8673b8472be98b7e72fe174462c6cdfc0d4b0cd41c756d73ffbc936325f2315f349924a356c62869763cc94b67a257596f051a5df24db7add8c0bdfd6083f5911599d325bae0a297d59f6023186a921cacd9e20634ea31809b7c30c61d9b1eb914ff3d94345513660a5c4078fe5c289082f573ee39473713183e1fe88e1f1cdef6dc1efd122c5f9fe8352b570212c0bd7609c437430feb2713dc329548c361ecd13b7ce1f2bf3aed689b69a5e7ad2922336ca2de918e3905856354e94b78ffc29ac4bfabd074c5c5329c68ccd0e9a4db86f8acefa15c5fde2e46b1dcdae93d5977061fdeaded28e9bbcca92e23ffa3332913d0d99ab648d9cfdcd6eec610e181abc18895c3ced82d564ca7be8ef9b45bbd2909307aa262c0391a0c21cd28c8bae16eddc5b712e1195805c495af0309841c8bd835180a7f822d2b423fa2be7ccb0c1bae1cf4dae1ed2eb6b174dd5d67c0339c70b69503e0c7e4158b682f5e6c5ef0fe625d8ab983cfad431602e3eb2321fc47583712b61c221eb30340f58337d2f8b6e38d8490b4c7290a2dde38ce898d8193294722a343f9e43ae6cc7374e5c10f3f223e6f4e4686a7a99aebc56ca4206a441fe2815325888896b2cbcc8c3a55801c22d3d393fd620eb972d8ae15b76d81e6cf645b61929ca4ff2d73d421a83eeefe012d01425bf66e8e6b94721083d084c1eca9f5604b98df779c072ae795a22672c96f00fbe1e3def533bb65170aeaa8f9e1b3a6428794d3a900d1eb91a0e24b5803d981f728ef343c5dfba59fdc7c1bc31ee8241b91d2179f7c005c9b85023f6b481729fbc74c85b85b6a18660c8564857bb494d24714b23a4d2ee0851f50d2c70f0ee222d96fa4f5619bdd08f5245855fe18c1e5706a3e17f9c0d6ca362b44551106fac2af47343e4f01fa7103e263faa84e81a8215667caec395b8e5dac707ab3fb53aa88ee5b45a984a324865112b208d34df25610a994f0f1bbe12344b0cbf41515d848cf750454e34c8c7b13478cfc42c9e309720bbcec80312a29844e4191b48137aed2f395b6a52ef594eb8a683541f59ed5998b845baec1f24e47b0ce16680b641553eb148c77516e894c41e219be26d9cb2926d18c5ba737fc81a1a0087d61115216090d889f9f19f0d85098793e4edfad9fb0b720c3f3acaf17b87bb90ebfaaf3bc72cafd3d5c0ae7e0dd462dc39f88f2f4953cbc9aff8611ad936f4682f1938e2a6ffe8ddf5646979030f9c9cbcb0baca3480b3df9c42bb0063bd8773ea7855ec6e0ce6dcfe0f07b6e6322e4273032a4115773e14a17cbd2a2446311769b12b9885fba251d79a555f089d337035442de8716221f6399799e39cad3638559a7b0d75af7e64090b1c1a76921a3eee7666a3fb2e8a3a21ffba77db29b5b8141927d68fdc9464b2cd384e2657135a44c65603830a5618d9eec19dd3e47d0eac61e378eb475cbda24cc27d23362cf1acf0e12a807564b15a75e710b6cfc010a33753f60508eb26d0e6b351e9ec86702a736ff899e10b52c90f0c8fa099e3260389ed0d209a4e3798141b94b86a44be276a80de12082fc173cfc5a00d0bb85b7d1fca72cb028bb135caaeeaf30eeaaffcd96d9c4d40002f46627f1bb6bb6b79432492903e603dc03c103d6bede30c899192819167538165d3c638e69256c1e1c9b8deb59e16ed9e6e9689dd14cee70acc3446378c3ae8d5213a5a4182d17d3748b055a3870a175360cd8f87d6d8f16c2f73b56bb5e74822565155f1ecdb3d9b8b67e7a298ed13d810123fe9c67dc8f6692d096decb8247550613dad6a1a5e642c602c45a6b9f5a6badb5d65a6b2b0cdf3d320a002f41887e3bd653adb2e3575f63ec5d9252b275bb604b7486e5a592918b058c8872a6e26b8ff7de910c0c2ee09d8e306032458beb5e2653cc3d05674a1253a2702864a0ffff96ac96c579a70c654d1dc348de1792ea27070b2aa2d678f17e3c80413be49ca9c8a499128944fa170ed4dac472dea6c8832b423aeb11e88ecd2237c457fc36680104a42443a3163fc4a450c9d9a2a2c0fed7cfa75aa37ed6c003a17b3e85f9148ab8bcae10f19d62e546603f3dde4a4ca9c4f1a03b6e9552addbc2567cd01db74c7de35d1247b2343d261e42f70d3ee8058b7168bbbc18690c632108733e2ab81826269fb21763b7c6f2e95f3e3ad8229e3b7358973b028332903920722cebca54f9944ff96473e52ec7906748e5533e1dd13d668cc1728ea19167a07b8c3e5d5b95ad72276c39699f138861b59e973d3105ef616674f66e704f74e8411b6089e1057580d278fc79812586f94396ad0b9483a5d845627b73e566614c3b6f5da86434c6599e287caa74e7799e3a74e8c0202074a7670f81db1d836198057d00e3900e971732c0309644777a76e7cdabcc86b302440811202a8744891a8290729e6942690674a7a3492507026709a1cc0d0e4b0811204244c699171068935028c4449b5a775c9d5c789c900afa8105ba63f38465c2f14d1363139b246c62a020ba6313336fd6999233c69d0cd905bae7ce64f5dc61149098ac13a782501da3a4121c0f93f7352aa0d6c021864b9b8259bb14ccceec521d0aff2283eeb903adc9cb8a5c3843c2edbe516bfceeb0ea5f2a127bd3755dd7755dd7755d07ea9e3b24d6f443f8909c3241de73a7b2a69e895d8d0db72f18709f771ed809cf461740b49c6baab6505fa8271d3ae88c262a14a1c5e13ccff3739e2123f0448622ca64193a838b5266241606dfd897f33c2d8b87e0fd11823844e1f3029535f56bb3412c14af912ccd560e97824b06248356c3bae1a020bd0e0804ad9649e6c6e72c09dd738ee7ad367a922a72759e55a5e3f383ee993c5be48a8524c94c922449dec86499c93c927142f74c8667eee8494f7a5a11f29e4b6bea1ac85510254be176e3110e4b3a74187b44300bba672f0bada963d98d35f5bd312b5aaa345b673ee514aa1c42661b8b613ce89e3d56288ebcee5e22792d79ddff51a27bf6b6e889a5d93a31c6e14d200a22e30d7ce31303ddb3277a58db32c7c4d71e56cabf7feddb6d2f232c0dba5fdaa839b126d29aba3d45a1820294c6ef0bb4a78711314a84ffad279df1fb026b8d3baa31a022fcfe2b46f0373f25d0fd02b9d6b2a6dfbffb05f21f5d2a28bcee2a5657785678ddfdfaf07672c199a0e65c9a31c0084d483bef50773a9a25038cb0f38e42773a921023521c6e656e8021aa79c642880a5cad562b8c3f1c4782f056784567489183affd0cc91ee35889d95be5d5157a5f92247194709024c955a13b2549906d6a8dcfab1b330ba034eecec02cccc46ccc486ef1571cb5c6570ae59385ee9414f3ea570f43fff3eaf32aaff2cae6921b428736268ea5f005198db163841964e199b0824b1213b24d33d184153213b291915aa372faa24ec7d66e8116ded978e31777db18fb6ebb7dba0a8326b05fc12ae44cf094c25532f702ecea01c34036375023a020419b08419718a14976d092a851f07a650a2da0a8539ca82950c2513ef8169d99083c21cac8f4106a276bea5a8bdbad9ddceeedd43ab7d3967a186db38c97876ba186641c11194ae36a1f24afa1f806fab694b9819d929d929d92295e3bbd21499254752c3a48c9a80c520973b640d5b4901411bbdcb928cb3297b92c73994b100c24496aee862d308e5be99e4b1b991b64ebec38b2ac5560d80707ecc491e312a15056604a15250e1c2023bae7923cb7b0a60db6ee2d0298a8e13ef04869413174b5c3b865058358a89d3575edabd1424dac5f05b54f03b5b0d610374de4116157087244e00f8b822488874f0d1e583fac65856ba27b6ed55853a7a70e6bfafda981e7b3c2524cd350c6a160d482b4360e04505c7c44a0413470dc129f8f2afc7fd007a7d5d2b292d23db77616f388a3f9a034eee5000b00b45a2d9c5b5f255b0f53c1af55bfd6985b9f148472300e5b4a8cc04a05eb87eb3745f7dcd27c58abd558cdc66a438ad08a701d686387c75b1a35e4504f5b438266ddd6733fdc1b31319f2962ba1a7d5718e3d26980116440da787740777c92a059378f37f8c432e058bae373db642b6bea24e8500cbe422d4ee1c1934e29a5f4ba59c6137cd319ffff9852fadfc27fd7dbc269a682534a29f5800a5d37bd17a33b385625f3408a6affe26caffd2d4f29859175346d497457194e2a6eb957df7b6534b9ffffdff25f6dc79bf2fb5bc6debde39a41ebe28b45199928e1bdf7de7bf1a62449f85756733c4c3692a961299324ac35cbaa1332363c9e8bf386d1d242c72cd3b28baf6c09bef6e38bca50b1330a6557f4fc13702349784732b556259bf9f7627c45715dd7755dd7b58917cb8d8b6b5f8ff385fddf60ff5f820edd9efa1e4f8631c6348ded8ad52c0b3d4ce77e47d3f0de30a6176358cdb2e839cf3e5f37b6d27b5972ddfe5f64e92c51b5979a4fc307d2f07d20087e56efbdd90c1de9c8b54063f33b1bdbbf714e09d8fbfe25dfdf33b5461e71f7ff4159e8bbf3c62a6c3343c919bd6a4274c209100c6700c119401004c1b045d74083ca9bf2abf178aa029ef1cea3170ca0417934288fd66bab60ad89f23ca2417934a89535f57ab2bf69502b9ed1a03e4ba2fcff6950452c89721ad4d568509ff52c8ce634a8219c06b5e276a341ad284783a2410df9110dea5ab12ebe30c6b8096df1755d178631be17637c31be70cdf5e27bb1063defc361e5e1b05a799ef75589b200ca6f159cff6fc0f3e06f2d8f8cd2ed7757c1f2abd17ab295d2968bdfd2a7d5565a29a574db8da37674354e0204c3acba37df9c55b546fefd1708ff4dedff2542f7acfa70eb3b6e9918988119187a4aa0526113a3d86c991734e6acfa8c7437d5dd1afbf4cd1fc803fabbd9ace126078920715b6daa4d051ab5284030ec3eb0fb3e10044392c425909104328e2449e232f3b2efedf7f7ef5f2cbb248d85344807ddb199d5bccdeade22fc8ab06ab4fbed6f6adf665ee6b5b0b935218e220c61288a221eff3442d36f9da7c64e8d5d394f9bf3b439cff33cf369c912294e97dcd4dcad395d7283e255582e1e095dc5c66a39df1de2f10112fa8e76d796147a41b7843476b1694d3c3a4e99b43ccd29939607f8a96e0eb8b7e5d2c75aac386552a5080f71ca240b1af0ec2bc6a35e9ccd2452b8203e4cdc2a3e33a04c500bd4b4b9cc2b44a03b36b3212c5ee236b4332fe312665eb14329f3d13d8cb5093f3c78564574c722076583af317e42f7fdfbf7efdfbfb98897608e06ba63514a694dbf3170453cc4bed4fd188f76ac600256fd8ba755e452696c338e75ac631d47521db92b18a67528b43789f45d89999a64634a1286fd0fdd43dc86b82b544e8664cec9694db4f4ae9336ada99332155c478ce58ceb18448726dcaa6a976bd7d201dd313e7638ded80ad7a9888d8d5249605dd07de3e414ceea4f210e26decf123678ef7ded546aa7b6b7bfdca5766a7b39f52f9c14d7a531ac05dd774ead52a99410389f844731af4bb56bb0a14b5d290de8be5337ac9ee170dbb3108b8f89d684634d79e358ebc46216efbb0831ec60cb8112a2285e376e90c4a7ff2283182926959cf1f5b820e695d7e28288e01df4f5926911dda9585ed70dba845226ba53b1947293008c5d28e1a8c040ef182596624d3d84520c52081bdba17ff97d6591f658fd507d9ac49af01879b70bbc407bb21ef830f6024f7a7581f6f401ad914af0ba99284d603e69f1ae9ddc08af5b0824b869fa50cdba85ee9524496b3b1b839dc19eec091403ddab782a2f7bbac40e7240a9a2bc222f3486d9a03b164d8009d1f9b4c0f38992817e68a0203650c702bac1c587069a1b0213b9213e1f0e5c221f3ff01e83c44b94ee6d3fa059c8c11c0dca8725518e457b3bbc8a70d7022262838f83cf1400808e843816b87c82e800e4c30b24608c01e0420180bc012cd95c12a29bfc320281079f2362808410600a199c0f1fc440a2f2f26952004e091072cea01e301c829673fe1899f180138060d8fac0d6f78120185e01c130a4431ca8038cd21ef8b3a6de12daa11d0a59619aad20a519a42c4dd3bc4292e547921f499224598ae258238a35a2288ae2686e66cda6ccefbf31a5920674bf52243ae3f7957a01e17261874258e87ea5b6d29a3a9649de4b29cdc260fb4bd8663337f3eaaed4d662595913db2fb4ab6d16bab1ec13366deff8bd8d4e60d976b4c36e9611cfaeb6b5118c18518988ee3038de18e7bcb17b6d695770317651addf7d5ddabeec66c38355962d01bab7ba7bd0bd69598707bf2a5c9e8dec0aaa089e1eeaee887aa01babfbd26cb53cc254741ce3f7c3f2c62e90ed38a23bdd82ffa64cb4f85e72c8603ceab475ed7b3dc639be7ed674f78f5aa3dac0fc12fdfed2c3b02f8fd9c8f130bf53d0b1ff72278a9c1c044e9954a172817a801c34cbe79da56cb7afa68dae25613ae38a5448e1d49d863294c609d694eddf38ac49443f8ef7d572b0ec4cba441fb040dbedc5b6e5781850eb743a6540859335551f5a9cb4a665845239e534e19d9e3941f05e5103f88de50a51263929fe1b863581c07f9ff0b55efb8a5e5ca319548fef817177b4c3d355b099086f36b2eb4504b604503d740f17a315487e6d1e3c8b2e2d8b36962d6379f07bf936b23faa089ead897af5b8a788c733a296d4c1b68cc576dd2ec6356bba59a3d5cb4129a594562f877df94e4b4a3fcd726796512a60506bbf5e8c73be2e0c6bd2e9641e0fce326ddb2aaeb5561616120bfab78baf21ad31c6dce70513fa471d2301816aad2050cb66a3830f444d9ba0402ec20bda135ad27397908b8b0b0038d8c0c5a505e4e2e2f271e1b48b8b4ba73ac0c36fe7f15944e258d42bdd1ae0e1d707fce606e33cb2264e8362d9ca628522ce632c5a12e534a8d19228b734281cecc6c2d03064b1404ba234a8d09228ff9c3ca267b4425be1113da247f4889e511447194f4451c6135114457104c170efbd474074df1b0441d206497b8747642f7f40e4555e652f7bf923c9d28691b4611c49922caf8060f803047f80200882e69123430c41529156385ffc9b546be4df7f7ff702680c43a23b89ffde2a15a9442a91481d2c8c885248010a119253dd11fa889ccaa99cca9d5903254f9e80201816f181457c1f0882a1e77de0ca03572bcff3be2b2459b24692358e244996579070e20434cd560ca61983699aa6d922c9f20692bc81244992069514a8644d9b2b1d640320800000b3160000180c08078562912c8d23b1c7f814000e4f6a3c5e5240368ec762e1502847511444311883000c02010c0200a48c430e297c004a88ce44bf8ab106874144fd3b54967914ba45556ca8e1d83862b39986bda97098b486de66dba4e9c0c434be265ae3d784687c5c5cd3b789687c5c98a6af09d1b04fd101e6e646a7e3e1cd9f2477ff83c62855cd91d70bca9e1a8fcedfb5986e0854be060d0b384c48f788f82344737ed2f90ecd9c5b2516d7399658832748a89e458873e34762e2604cea91ab4b409b815f2384c4a29da67b7e59167bf8df016e60f38625a434b83cdfbc33014d5f13adf175219a3e26aef1ed229a3e26dcf8bab8e96322353e2e40d3c7c48d8f9ffa0b2bfa68d2b9b551ca0145475b350c958a37cae6b746cdf269de9cb0f135319a1f276e7c98b8f9718234be26a479becd25819152ac1c46306d764d22320d8072d7c78525ef5b8391550db325ec05ad7a5194c302565488db5692fc5628691846025520d0cceb9e829325ad24052e0c7e92b8fa7e20584b0d6b5f93d0adb1250d4d8e0501444ad4a10009ab8446c7ed807918cb9a39518b66fe8bd3803d2120c2b86a8344575a1c0c46e0917f2127576dfa202fd3aa12796c03a0329a7fe36082cfdf48e939385dab2761358ca1de56f6f47b9878a9d409e29861e94727ba63b26f2d7b9e74a9d009833163e9452fbb3e76806af4fbf1a7bf961ee35d6051290304f68fe86f21b85dda231074375729024369ef2bb00bd0184ce1797242fc6833cccf8ed1f0a732da80ccfa7b36a7c4a2de56830f180a3063a8975ae379ea0126ed20965db86b319637f2222df1d827fd500ea18b0accb6a7533402f6ab00c30f4e12387ecdc0af83422d12fa88fde6c518d49455b375d3a9520fbf33f2586cab77c76671f7e4c2b4dd33d53e60b0e7027007f5d2f62645d888ba89f88300f08e464781329d13c2430150bcd5130ff94f7fd86c0af989ea01239b577847e6f276ded9132e79cd1ad9d341ea3bb4b23d260332ade21a31be1901bf5c00823c9488cfd9b3e4d37b30b2ada007a772b5a1be91b995724bc6882011238848fed057a5576fc9a3bcefaf5e39d1e8598c86e8492a79cef7ae5163a571a18e953d370589e9ca098c2ddfdaf92556b611df1e6b40bcea95073f04072347059f3632c33160d6261f2cc192a152aac15697c366db5d88e123ffe06ff5ae17d33acd65becbd357e72b5cd8db582e06693a1f504cd22aac9ba52d272fad68fdd4c00988e0cfbf163f24c7e5d1672d39d1c4155b8b40548dca1951716fd64dea7a7ebedd33ea6d104b214ced1ac4f76d7bd583607ad25584241ec9758a36aa18d26cad19c1af63bdd1a2f4260159dc0cdc67d2ed49002b1f3e32c9b4436e42962bf7c8c58428dc5ec0865181d76ccf165dc030bd5a3402c68bbc27146367435415a1ec211b1c4f4fc26db54706c34782ca2816fd8314e2433d9057063292b3079d1f05cd5b9a845cedae96441fe0f17b900aa770ee7ed5100cd8727a3e1a413d13c03b9cd0ad0da0b040257796240422fd270a3bf2fd4ac4d11ceb50cb1a84905edd1128799c89263016f4f762943c69e4a63f558a01038c8c4bcde3ec777bfdb27e1afdc4bbf89c65e563fc0eba1c9e55318e2b0b100ffa4fc9c09cf96485bdef7da31113e520156ba49951bc8e6908a67717c43293c61f5a8d3ee8a390c0e9ce3f8a93877c7b6727102d38f7281c7e18ce28607d849413e753bbf35b2cdfeef8ec8c09f5c3513cbb91bd1b294a8316cae7ec7b708099b0dd2420642e28adef32f9890bee5b0cd6e3bc6da52f88924a15b7c456f979676687463da9b28cc6e3c6aef0982d7b1bc34596860813afeb6d87a56cd0668ae0e1ea9410431995cb02b6b2e3c6219c4d4bc25aaaf52dae73ba62108d9b241159f62f10120b46352003e0e79bd68345b2b875b9b258c459908c5ff2995dd27b6cf46f1be6739741e2a5bb621694a910f89cd2ea5dc1b4737f364fce3eb8469aa413c15f1cce289d5720f1c9b5d9ba25607e39e9245bc3168d6ba2b5f3ef0fbe01f4ceb1d111df4083c4c9e632bb0cabdd3998ba6020149ee8e232578bbce050bded2e493249879d2fe484c464fd89c9014cd84958d15d589fb727f9ec85f34ec85f32977b967ab7b0305984252cc22f2966d7454f94478b90985c9348325bfea736a5fff7b38057ea033d5568fe05f698f2c2a4a467d45095564d44dd4a975d2a892f9544c627ee7f3b7c56ba4ca2d7cf4511f3db8d99c6b0cbc953d45082852c087440e9d65a88deb6d75053fd5f01457e779be118c495de20ebecd6d7c5bd16f473a7871184271772baf86c0ae6c79343c10d60208a681881967a163d99e1d34627240ff87278e06b198bbe0413593bc734e5de72c1b3bc1a672f350b5764ed8db3fac4c60eb5e49f6b8a651b263cf9deb7626ef8ad042d7de0cb46f06daa82e9d45cc8c44ed5bead4de0b94572b5bef2b084f7756eddda2aac61484968d63093051edc8cd811d05cf8d0e864b20cef93dbe5e0c2f85990f33abace889a3cb652b57b33d1d749738f3ca1721b34384d9d219c2fb0f02070ac6d0ac6911d45b6a300531bcdecd88a3bf244008d002a0a0ae88fd6bd3e25e3312fede1dc0d0be4d5d0800a0a286a919ae7460468f0521a133c8a26883f14093180fe96e3c2b7f56541b3e2f878902b29c20a5c91c31a58d4559fc45d9f5df4006a85cf4911e44bfaca1d9c9fb76bcea957ec7215672acd333d140fbd9ca44b2f25e7e7047a1a1c58b9a5991a0e75c72ba6c9323dea27fb00e0e883e94fdc78581a501fa4e80801cdc70cf3d3d05271140c92d5c7003b79c292cc850f3d2a10f212dcebc458cf5692ae2671c3816d6780fadd16dd25994c883ecf469a08bfee1d3ee56aadc5d4ef46585304b0166d686cf1a4faddca71c2a801d98c469ec72aa67ab77bc7e5dc55c23215257d59097d7630c6ea76cb247fe3ee838d75b692747fe36182bfaf41e93b7576ab5e92d5b1fd51b793d33af11d843ec720fe39bbdd5cfb6b5513e2a3403135a2f4006b27d252c18d638ed5a240783c9954dd4c14863dbb62e9f9d40a21a5329ed1434d055f59a35397fa3b016d3a87107f3aa74243175e005787c97c3524f4687dfa2ba6669217c6cfd78a263f6776ee8f672c9e006ce73512fe6ef6c4ddc51cb443b99e5602df19a31a31b560f55ef05a5229468c7bf30b1957ee8035c0643f289a993ecea334038a65bf575a95b54b11ce7a2ed6d685cf43c215f2d2dc5b7f83af112ecaab05abf7c3b7c5976ac42aec3c6f21a1f71b0326f87a0dcacf81dbad9e63951d29badf1830a1cf6b507e0eb95da817c08eed8dbca594d67f4c88f0ef372abdce4e97ea0b4c3cb607a5b468b7cd22a518c11c775e6f93d17cf19c842ec720f639baddeab3d2b6b1272543ebc53909393e43c4bc6bbb25349278597935275494790568735c9f6c89bd6256335d39f74398c8230563633f01e73f0e4cf0f71a949e03a75bbdc0386b921a5973d760fb81f0d15f041d51a0c403dc867c5ad63460c2827d4258fccd8852ebfca977c54eab7b04f29df2d7691db4a21e8861832b37ed7c63a7edd81163b25cd86156b8333096820624fac63ffc22f04a1ae36dc09ec9297509e6d2b85ae0a54c2cc461f897cb70330c8ddc0b198ad32af8623653af437216d5cdd778c8ef8083b3e47ba885bead9ff472a51b37a8e92e069fc07406b032ce4e34ded27d61f16221462d30179d71fe30bfccc58c674e915a4b0206906d2f2d030444a54b6404c86b7c8f5e4e7dd35626451a2eabf783c7924aed2449f70326a13bc63b085c8791d87372bbebe4ccd73558bf27edf98bab60d77e6561f6d041ebf5fce3323da30a1ec6b9351369b3d97addabfaa9d61c022d4b1be454ac5f2908e58b3b8617b4b0a85a511ce51a8853182339a2e2e748cf14e18c44b2d8781998e4559fbf0b257d2588d6783b99ac8b925434840d86181123fc3bfc40db3a88b84089e4e20c5768e2c9b738cb20fa2157dfa3ebda769ac1c8185984b51927ff847b28bc13f0686f720168cfb32658f999f4c153c38f889411b164c8fc9a50f0adbdea7e56b5258a613d490d5dcdc00ceb89dc44df08def28c9d912a0fb621ccfba0d259c26c7c2f65cc5ad48e38cf2cd3d5a603286563646279da1bbe176559f123531954468b307f3a3458b08c1c3c5a1a21a246fa150c2ffef54dcfb8a724e68c62d791f8c980202b65d270137ef1ca7057800639e5ffb46c839f7cf44973a10418b98d1b0acaf9d3e77b08695ab728b5e18612ba9ddfac1ca0df5ac6095170e85afec27e291348487b9459d334d20ca9a343f785494e0550db26d8d6aea19732c552f9af6b609c21c85dc8b5c86f164012cd20371a49208797f1c5f55e6c1c032a01f0b65ea587848bf726e192dc507b9acb6eb15c7f3506435dd583336c8e573b6681d7df651f07fed217c1a535ea61aaee713d3a50cf53d06f1c2b98af21d22d867162016b70cbe4184ebbef10d29a9c9b79861f77cd92618be4126a94ce858e16dd8c8dbe534dfd689eb763653ef68178c5e903632645f020a0cdf10815381f8b530396d2aa222010be03ee5b6efc158d7d0d24b5aabc81218883ac387a01bad765a9340cd375c58b4d0730565d3fc0da67497e9140c47f9062c0f995aa50f7819f57efbd5705d4e429beb1a1c643fbe61e92de965eadc35a7f86e50a1bb4832f843572e2248e148093ccabe59a0c94861541138640b9165b660503d34868b7eeab712925328572b5bb0a56159c2405ca6d7259821f281fb6ed761f7d34dae4b150575dcad84172555f44a003c2c91b58f3c89e80f4eaedf34d14e3f59c2e7b937f31f91117268c46c7146623afa289111965aa0ffb6e104b56b061720ec54acb572e3f49ff078df9243cad95119d5e2d9fd25efcc600e4122f288bc541ab5ee7cf83cd70f092654d4273f63d6f65cf679cb50737dac314acfc4563b2ab5c2b7c3a084702d72b4672ec4cb93616c934a9962f06127cf64d30ea4e672b5c92810de1070edb3dfa994d2a4489f654f2ba1ed32e83de39fa723e7cb8ec48bfd3ef3190bd4c260e9d09e151b1a72e87e47bc3aeab4ef15ba1ecafd29b65526dd3f626eb0d27ca8684e59e422bcaa492d17cc70611fc7ea3d2cfc9edaae359cb8e5451be400c82a5b451fd6910ddb1dbf92b175c64cdb124aa1f41ebdcdb6ff0e10ad78adeb30c0f6defe027b5f97c604e88c752eda0c7066d3f06f1941174e27ab4c193200fe2bfab7040338bb6450400f6508327f5bab860ff9c22ef3b47007811dc4b68f1ab7f7d59bcd8a70a4266134ca067ead3ee23327969251cdbb6e38cf20ad55b71c723a3e42a3c8210edc1514387611cdefd913d0b4553727974ec518e1e01918638312d560b5277c9c961a9667723be82129bc510db2d07024b4c8d96843c679de274bdecae69c031af019f2c005689eff5ec7497bc362f4fc52b31049e494733334ccc993e87550513fcbe06e5cfd1e956b78d85ad01f0d028a3ac828470033afed879e90aa9373c7c14d68194287d4c6c0d6d5bf7b0316bbf454e8d2c3f2e2a3a08bc1e83f87374bad50d2bb58d249fff6f6f7cabd5b38d68e1f10f590a85a64b8de79d67757fe567174d83731708e3134bcd5c6f0fc86e49bf8e484d5af1f5bf177029b1925de93b7bcc575057193617060d36a2f2dfa058b89fdcf3b33357e1ca6c903e88ae4753465578070c4810694dc9597459fddf835e3217dc2232d8724e41aab88a636a8c870c5fe5d1735d2603aafdce79b5a3ca250a27be1242fc57c4aff54233f5d42f754416a644ce5547829cce17fdd939f63f0a4c866c0f0719cfedbcf2439a37f1d41453cb33869a787538994703ddd3574d18842b74c05a9b3621ad75e4fa238493d6b8b4063a684a1f9c077f021d4d9fc4b42cc142376dfc31fa9ecbf37f31b6777a7bf212e0c8cd7a3b87e089ae11b3a603f257115dac82d69c5e7d34f76b0f09c98d58aa6981e3800b38a0041bfb8e60386e6086af95af6df609b517d7d6c21c9a796cd5ac7686e208b761997559f81a19be9961420a9a138af35b2df77c12266327274597db3c6e5dc6ca1d6367e78d91650d8d821dec9f889b390ce478ba3eb74bb5fe7d0c5c1efe6020accaf9f1f2eacbfc6be46965f6937c8a333ec5e6948183d41280b20a3fc3b86bb5921ef4a62efdd8e31f1f8cde9fbb2c0a85a45ea29692784a93351af5c9b1dd0e71c68f5c63fbee0458361348a6597df6c93fae015ace9f2064de32075bc1255ed5033418e838bc1962bd4a76d1d5bcb7eadc8225b20d4d3eec1343f345f74828f85cd04d886ed6bde249bb5e9a2406877c22fc34afa12a262e70447e3296ab0368a8194f6175af82b6241f1b6a4face92e70483d29e53928ff137ef5c0f5a17a9d6eb76860ac50730a8490f36073ef03a874101884878094711120d0a4108c1853b24f0e7ea6b4cb09b8a2cf91123caa6f998d29b79fe69a2903a5b3488d35613eb7a007abe1b0f92e45224ea33b8f9d75ae4d3426ee1007385eb8f01174445f204a8f18d5aa7abd86d84d417463b50d8cd070f2f7fe82021a4023fbb982b4cea10e30e547410cceaea76285023fd2956640d3c516ba31baf4900a1a1e2b716d590b2156172a6c824305c41c8fd0e43a2e2ec480c32b3715f8d45489e6279409451020a1f16d7b01ac2918921c22ea2f10d24542842818275b264ee98671cc39922b827c5df3a12c581f7cecd4c670834fe87c86b84640222f9a6376d707463dbf9d3cd3dcee394d70b3d11765450b8d134c394b81c02e84277812ca00aaa083b36ae08e0f8048ff7310f08030b43f2124f807ed69115620419f70420eb79f336c812052113c8d31cd0e88197abb051133d09bee55fc88ab83448833453b2b40a07c6a17c58a20218830a4e34ca1b6f51297c1af21e006ebcb5406ee16e8d51beaaca2631e82a3d006cf389f01ec2bd8d318d5f1587f7dea087b78acb399f783842c24b37a0e2eb7c759d1926ddeea887d944ad845de0d570355761c2c459bc41a1ea6b672f6d6845c6411c53b48b8737d6dbda1b4a245caf51fceb75ea78a640f53eff387c59eea987392d90c4848f7557f69c77cf0c57042f51b52869404fa97a5aea6f95c7e3bb5aef88a58c4cfddc35c337fba00982765c38bd404cd2d1efb3a998642155963389f944c50235af0f30ca5cd5239423fe1b6c6e5eac300545557118dcab4217178cc1528f47600a041c3c7473d9c66c50f51fb233ab498dd3ea12afd754d38415553cc6b85627588fdf59cd0f6fdc832040f4482d96d690bf469623ae9c92db552105ccaf03d1005d9417757f74928a98230bd24c631d1af294b1fd49a973ca3cd5de3be16961b00e04cd31e03802fb8aea0ffb431ce42a99d1e92975b3ec68fd0d86f41336044b67305d76b020bc2bd73b079c34b98822ac3f0fa210e851ddd59e1f22be65442d29d0df67c2644760ac4b14f12bab386eb69a4747cdbd8002c01a0f41f8f442c2c6ab0ed77fedb812539d4bf8f1e5c49bf1eb18c7d01661089e7be9cd37b74f5df80cc10e2888b69f011c7fefc02d748d18846bb5c3328d26905cecf3b1ecf54fa49e5539c094ae8ae715a941d348f73ec5f3103b8abcf2e0f702567b00a379617d431ab514d956791d6147404dd173f786fa4ef045a3a559d66c0696af0a5a8e99a58f4308cc0253109d01afaefbfdc0cc3db5c9d3544bb814c413ea5e13427c8482c4fc6ecc537d347bd785dbd11a61bf8ed82988a664a03f9beda875eef7f745c5331b2929a0b9717474db91cb5c41f796c27ac32304e1bd1e2eb9835cf77547ca09133a43013b2a72844ba23cddb209e41db0e2b81e16eb2205f0b6f7e634dccf10e237dfef1e978a41b824368ef6991c2df2d43d49274a9877f7a1cb771cec48660e77a05cb79aed1a19fd27c61605342c176cf5b5f25db3e4d6d2b882dbcea6c5718be2b33ff8722716f8a14c983e16a16470bee6317eb6f7f820b01caa1362f2b7cd40535ba0640577eae736655e0ce83e2145ba8d811c100e22037bec6c4244f727f929a8db005048871192e994c9ae7c0fe7630b9bff92f5615546eac2bae681073218b2b4a12ccd013c680fb18b2acf207192d321a36b3ec12c4b27cf6d1ec1a0ee124a48bffdebf4d2a07b6476b1bdf35c42f75a65a65e1bc1e2c99261ea30374aebec58e29d07d640414eb542ba8759e9234b97f15ebb0677e0645093dcc0e6b7d037d9b7f6f5141cb14e363bb856c5cda8e0cb423f7d8d24a71fe463ae7b3c982ad489fa244d31cb1cb5f4d32eed7d090649465b9c1a468112c074aaa25a351ec2fe287704189598e25f7c423ed85c145fc8c1a70881e156a0deb5a5089f552caec664fab3550bd325770b22ca7e82dd0fefe298bc2c54f7752504030a8b12dca03df603e886de3e0bc4176471e4d182278e35c87ad32724bdc890671613deadea39272ab6d01202eca6aecd8838cc0a520372acbe0b2ccd951d927121033441979aaa241decb0f3d2ed07bacf946a537d672bc2c298acb073409c23a0eea0bfa7407179f28ac2bbb2fb861e6ffe3640b7e45c63ad3456263076f9961c296d0335be6950ece3a4853f62c0601ae0c3d387ef1113a34889ca39d6a1c519547c74bf289c40737dfd151d52663183312fa06233e7ffb8fb1444056486490b840f3831781c1644297526267f4c15400fa351336aa1506755f347e210e6128b3f8817c20bcda94851dc88aee800a833d6c8f461668c7830ce655746a5c35270c9801cc0a68e36f1c044ac279f1f9a36e32d7ef0d5d09a6e49f07f5873d75f9bcd3d4586a2be24d8dd176b48706b14ab0658d60636487551d8e8a8007a7a63cdd7be7018a056ab8994a006043acca1ff194171aaaccbfdfe491e8d0d84a3ef09b09aaa0caae9585dfaca7f03f1654e6b63674de76f90df1bcf910b53f94690d034392e27b0e322669003638ca80e3e19646afcb3085cac86e12fa3ed57d8509f6217cff30445c23999f48008084c215bb23ee98b1980e71d5c9287c63a1b757c25bbdf8d77fb9dd434e11fe9472216dc6c45bbd901833c3d27e904a14fe708c3bbd0db6091e8851b94f7b760e93e6b1f6b708440ed085506c97c3a4f055436d80d6db754b982631f6271143163092bb6914a977827ca6399a27e905951c68212ab060181b70e5d6135859eaf4f586b18fe80eccf3bdbadbe066d6775a31e243bbd8dd2ac4feaee3a1d7ff05fa89f18c49144c98e5f313e40f605d47d0d54d4c56ff460ba4be182d8d3e3654a2da5d3cd1f23666414a739ad789d9af06a00d6dbc2700d3f6a7537c94e4958de23566d0b197e25316d16632040116419cb2b430930b587e015016f2f5ad50b050b571ca3b801087c81a40c3121a3155afaeee94ba726fea395c4ff3bb34c2090deedc54f80a6bb80dbb1d78c1a8a206b0222b5cb93a83f18ecca18b36fe4eb2496a4373697959d1d1f0f348b4ac34ae026216afdc3c6824f8e88a6a28341ec059229601b48ff9e2e0727d886be2b90498b9d15e269b5def42654e1a66b60d5bd194ceb847ebd0921d23a28a7423c0410fff25e3c201a10f1e2f279a439f4bc7fcd8c02f280cf4b5e5134a1463f2cd62e67ed89c4ce4fc89a5cb7a0020d04fe5c4f13704d16ecbe51bebed16a2b637ca3bc74c1c2d553e7ef65164ed9d3a64c680f202e95c276888352b52779b2f4ab8ca06268a0010851480d8a42851db70f5ca3908d4a6ff4c2bf26fda0c67adec67bdc25c62d1bdcd396164ef8005ac9262214d867c36d6ccabbeeea078331f3015379bf57a5c70e6301ad33e98cbd120227a8522b9441522729addffd274aea4b7419c6581881a03f81ced22dc130dcb311203fd02bd84a0616b8913819d400a705f7e4317a12d69e99b8c27d5e3085ecb1f200a02b02872c6ea382c06c1148d3178bb31b614f08c37e5e864d1c9396b51702c7dbbdb800656d674c18945c4462d184eb3150a7d6942f970a103e2b61c3125773cef6287a2e8a52bba444db3bcc4b80c2a69b732ce44c4ee41761ea98e022433051bd551b4df76c538e553961e7838f321bf75121caf49f2bc0704512c54191a40a4d9c07e17c42f8444e573ed6f068d55e03aae5e080415c58263fb9a632e4c909fb443ee14cb0a542df7402349d12684f4ef8a56fc75e2289439e30e9a4760fbad73a6ef72606642d079ec2bf46a5e675eb5e5b6d024cd02120b16622d08accff5189aa2553c59c7947e82549f3f5dfeec1ef6120bbcaefebe7ee586415a7077f667ee20e7075a7d2a8942464cb3c6a4fb215948959666c363998e1dcb685c81fa0c22b3574f0552114c46f4e9ec8787a1f387e5094a06d61d99891c4775bc647cfb1fd2704d995d408a3f786d82c40beb72b97503d4b42193fbd0b2768bf352758bf51a421cb248cd14eb61a00e2b3a34edec661c8fe9143b97986406a77a1e60ce40c00dbb6c89a9c961c810467d88f7164e055e9ea14103ec4241f4a55761bfbad12e2761706ddaefad0e57ea8e73098ff1ef739e36fcc44ab705f8bea06f8a62a4269c05490808d08d4a8aeb02d46dd2ecb49ca979a93823e105cabf85ba85a82d71a46904149241efccaa3450121c67ee930c2b64a41006e2c49406ffddd5c2682e6d772bd572f97bc7885ad9295c21898047ce3b76b54b6fe4754190b6bb97c85f50e54153c4a6787ee743b12ce116580a5aeea936c43e1a0c989086b250768d691204d12680bee5e39f69fef0fcbce3f703a48ebf349786c9b0f8c1bef5bafdf7b320c16d8453b39db4ed7295ce0144fda07b486567023896ab63c8fabf3cef2203cc99412cc133034fe8ee55d36228ca28ef4846036ba01961886f75ba767f66033eec5279ac47656ebb84ab0c218b77b031b13c841b61c0f954ca864d91fc4c7b8848048300c93208a44a594a4c95eea9392d0401e745b7cb1a90171bc1b5decfb450d90b1942ead35ef8fba2e02a8c26c9f796a2699b51711151490b0468b3c63ba4bc913566fdafebe46da53cb0f7042bd24eeffd0cb4d22a89efe50f8890933e6f90c1747bc932189a00d6a33af76d862d9bd5e2ad769c0a6c10189cdc13eca89bc68d93dc541958c8b165f60c9bd6093d3fb8794dce11eb3041ba7b683ee8394c1701af600cdf0a4964bae4a1c32489c1641744b1820de30d7d088d058fe519b2a77fc99453b8b6132926804fe3e19f29a50a11291f8686753c08a11d1f4bb91950bf395a5271ede02d9bdc1f563f96e998553ec3a23d414e8e82eae50ee7a352cd8042eb4b559233bc08e6e65baee2d032acb9da4578b0b791dd7481edbce7b39a3d8de8ea072ec23e88101cfa4eb8283a97bb1cfa9503b72426866c6517edb05632734c665289433d72b560bfa135afc58325df1f71f1495896c86c7e8c88b46cec05d70816b24af82998802a4147e231461498f0cf57127a0efad5ce8f1d035da0f52e131441730a087288ca37745b4a23d0eef4ebae3427ab37200549f0f31dcc59c63a642797773b7c9d60342be2d4e191e0ffd584496ca663aae987bc7f604a122a9052c863a9e4e90e47eb94e8e04e56f3a2e48825b68a2932df60af71e726904bafa86de233b305390ac82edd9ea496a446692df532400118e988065f2d9c64a82200470522ed6e011a629f4894d5866ce4e01634d2b0031cc019c06c66358afad872757fc3511554ba060f5aa838ce8a634b81fc3536e019bcd51d261d667dc3a49093929b41cad2435c504dfb0483925548353ec2c8bdee43ba1c7640641e6741ca4c440b239e2b0b085452a6733a7990a466f09f0f8564ad46490bf315b17d59ab640d56414a6bc233cfe7bb62e3382c6466b536ce974af2dd46e51a0e22181720a9dff29b93a8358c744fd1a9feeaa804141878e1080c3ac23e753df53f14b6d0002cba9cb28bda760625c7ffe0a8bc98aa180dbd602cc584720c60985b5a970dec5372a5e03cf4784c9958e8ffca05c11ea9bd7362bfe1c87914c6b175e2a13ea6f59aa87070e46b03c24af8d480040897b1db6bf56fec692457b634499147c075a189ab3517a01b2aead07fe7cc96d8170cbb1ed6e8546d61ed8330333355b124e5db9d2d886e3ff315bbf228f2eacdf69609037ce5659e7ce581d2212a21b4f7214a6821cac30a9bd17a6e053b6e0607bb362796bde218616d70e55e6d8a2613c466ae0b9837acec080fa67b0bb36ea527971ec22cb23c2e3d95582293641fee0ed586688e9169e2030c865b96ee4ed4c459cea47298892cf53ac4612b8273291c8491507870cce0aa157da3bbc823d4dcff13e8103ac182c291b3fecf50c9820620e1c2815de8a39f645c4fa8b3cf1e5ec519656d3c544d4456bc9501ca6e104b4fdcfee22b5f75573b65b07ce23446258593b78859594c5594edc894594a087db85b8e8181a17956186756639c34544658459aff021579139ca4ff6ff6a566f1197b6ccd7b7e19e384d7319d6b57dec41b1ff3c3e34eb3c2f37edd498c557cc9db73e0c01fd0b8a673c5a90aaf9818ef5fd4cf15f7f9d2799dfc1496ff4933300b27eeb5debadff8839d77eeb513181285c8631c9c956d2149fe023a6031efe5f4494b9c1ef4da31f02d91fa84f215ecaaca015211b936c3194081447fcdfa7a8ac13a4b5dacdac0517b67032d480fd4030fab18f28900635b62474ca6f89ef2e327b889b5ce124b73d39ca4e4f91eeea26f583ef86b201c18cfb669d44c92b07687e77c76cede7ab083f7abdaada4366152a840c9ff9178517f29373cd64c936495095146438172ec201bdf48256676907666b11876924feeaaa91144cb20c4f8ef0ceb8c31b6803c41f5a3cb1705c8b157f99a1b44c0c4d3bcd848975cea1adcbb69d780cd23f82ab6256a2401b6a3382767f06acf8a1753061450dffaeee5d0284056cca2f047d247ef9374f6871c3c3bca9d415b06ee21bfb72882a9262434c4cc79fde3ead131f4440b40bed948f4df194d25933f780878a4bc9aaa5e2128ea4baef5c56db30d55367dece5d42e2d4c912fe7de0dac04bf5c1f00c563ae78387645b082211e793d43659737c876dc2a8eee8f21a295fd8ca0c5a20aae5dccf6bd234a6c1c0cebe23790b9d86fa69978debef3fcdc2f66b4f32ef0c7be1795ade3b669b0e561a1fd1faf884344db4b1eda33b16d2ca64208c5e40dda41967c7d50f669b0de6c1ffe4419c6f22753dd0e9ef7c8bf3c974e390d0751061fefae6c484214bfac0c9e8ba56123c0ed88770773a63ab6600870481562203f8ba3dbb8d20e088467c8b44174f3f37ee2484f31f5e874953f6347e9f548736ee676b747dd0cf30c4a330045d7f374d401eb8f99e16319466b324e9723486d5267aeb16c87de794c42a9fa67380de4d0cba9b00c8442380c8d818c1830224bc599bf6aaf4653a18a53bb03a6cfba35a1a90491a24d11ea40079b737dd234a04b036e5b6db92c59be1b4cfb18674d2d6b2b13d2df90bdefaf268ce2836ca45ed2bf6ae8536603a235d8f051457a1c40cd007cd8af38d5ee3a2b59789ffe683e43ffe9b832ba3196cc8118afddd4df2ee7d4b630e8aad5f438d84df63d6808602d3401d8620420513502aacca0b8c5dd6ef05449ed07f6ceaec6019243fc39eaee4cfaef559b88d79ecaad43994ea87baeac110733ce4447a96e7ec76d99c12c26595247ce0ee24422ab9ec1e8a61174d73604b34aecd7fffcae01747141a1a56a142e8a9e13ac241e6209828b0837430c06ee1c9304a2fc78bf8336efb59c8c39b0c1571f4a477972d37de16fd67afa22b716d22874d5b0b3c9f18ec0af850a553d991810246f8fa2d52c6903967b250ab4398a42d228799cc9ee3a20a32843e8ef1218b38698f1695231b9b24b19ddfd737ad65dab8cbf4da3987b2351b6a5965447f0d6682fab31d0076d6936d3d14d5ea456d8f08c3e84aceb0b03379e7a9f8227e6fc40988154f9ef88e5aa6a2271b7403e56486979642ba46c99f6b2db91a52b0b36651e4a973de02c312a249a6f52fdabbf2e549ab8512a7d02800332752d9c53732e24703287ac5256ff3035d2d261cbcfb725b1a77184657b62f21e44b40f6ba49f194fc29d457ec5ab0833ed07ceb0879eaa2d937b869688370197a9fea25300b3bb25e1af9f86edf558f6af3310eba8d861cb17918825bec6de01dc1bca1989846f9de6b905f38cd6b8e64dcc9a684363448b407b9a0d0eb7d0bcc252382a74636f3648486f577a975470837a9c06d54ffbb4e7e2052f8a1ce913b713b144cf135362c6706a010d1de31ac985638408e9a92dedcccb76ded5a0cc8a9415a0da5f3bfc30474ee3ed15e1e0b599f2a4cf62a8f306125413d449035d2eb485c2415305c60cb15db190ef2b57dab4835a43f268b06741c49cf43e20d0a92002d0cd40ea813c350ed5544f7775678d6ced8890dc4ec0eed2de4644eaf05dc62bf0e129a501957b4e14ee082a87ec4c7811aa6fe3b632dbcecd5f6debcad79670871da3c6d7158aa5cfa285d790087b77484d130b9ce3374539a10240c22bcff429e4adfb7168118c6fb62ac93a57238d8a733c1e4bce36663c38c53606ca2eb6ba847a6714c3f65200fa7730670821225b5235b7bf4c7c7342ba90aaa50fcda5fec2f99f0d06cbb6de39b291f9e15a3ffd58a3e3c3a597fc88486056cc476f175509f8ca7ae99d45a2664b4296e07070e9ebc954c58cb89a278b416be305a540ca04cc04a2b88604a3404730596bc628e9fa6282d71efc9ffadb2a9e6a0ebc82af23d2206c58bd391a2593630708d51904a389a802fd0e54b60cdf50f782d0c0209b9c3559ef16af2f522907273828320b4a1c165e6f15042a6138eb2a6b14a63380fa98e016f786081cab365039538bde27dc2637f69ad127388212ae55e51fcd9e6c02af89f09f256a17a1824634f02080dc2635ad8642182530fd1aff09467c07b03aaf5d1c846651e7de75061de69b145755db254a9beb16f0571ae2ae4992905222f5a3f2cdcf8a6de20b769b226361062609188f53ffdbc0fe9fbb9e19f42d67252ae2dec9f92bfb3fa07125bdba0a8d41bf3d0399b398f24b3f65a9f6dd1c8aeec2d5d44cdf23889d8cd1665a011ad725b118b508e610b0fd0f6ffd2fcfbca9f374c7c0642d3d74307f1b7244c88ee376bbcd86ffbd0f1f74d81e06c0595b22f4029d3a3e98a9b6044c25ef3dce2754f5f14e5b4fac5d64954e1d186a49268db54d6515ce9504239db087c4fcb7636c3f33c03173e4b4cc5fe82acf30a94cb68595605a465c392b50a62f647d7bbac077629f507d8ce7f6338cbf457651ea9a770f9ad4915c1e03e60b61a0e11cb704d6a61600c4f99cbbd1ba40be51662bfeae86f10db47d7bbf265b71552643e0c933afa7a52820f3fc56c0b1b4e04a1ecf1c00f13eb2f0e207c68c0c09845b9bb425ce8bc7a455f6fed2860e73ccc140a16cd9350de518d77a318b3f69790aabb7640bc23639813c3969b771361f72d5acf9fc9a36d6b0d4261fb86e7687325c1ebf5f62ea435be3f115a83cb2cbb5a49686c6017347c6b8d95293cfa2f65c630e5242338825a91ac057acad5471b7963ad5ea0a947973e10abd1889d78b0f21d0e225454b377ac8015792c47f6d77d64817cec6477647de2e8ce858a9eaac3199159141011b0e7c6bb99e2440f2937c489b38a1e223e06d707254ae226ed3dfcbb7f2bf95bae34a42d40a3a150b3b128529b4917d3d9f1723e94e0c693c9a137b6ec64d1f543ab230251ec6bb3c682e664d9379625d87de56051a3145514a2bc1a8e8c8ae61f8a317074c7d0a4a9428ad0b80d8878bb4ca4796fc1c603dfc5b1e930e31e015de5b3e50a695188e88085542a5c86364f10ac644502592a48ff11a59a495e19609c74b254c80fbc0cfb42fea5137d81630c9ae6239b156d838c6ed10bc7e8af750c9ef2074cbdf3d1b71323779db7cebc56cf7b81d165f9765710c7d290cec5e5068f572b23e8473e6752effade88d2ba4de2086b74e2af9352eaabc91fbf924bca6d06c19d9573fe4e79acb142fad39040de0d7cc7c62a3ae8e95094285b764b6aa09edc3b29065dffb9d9a3078d4fa05864a4701513f5a11301c6c7071e5638b06d05143539aed4cecb3d0ceda6df04c2437db1051190c315b22c7e2c19a709789bc448ed81481ff203d5648074a1681e083fd5a459ca6a8d16631acc86ef23593a400ecdc0fcd58881495dc842fff452c076db1b2b1728e5487a61c7b2321403f4383f5966a411184b7a874824adbd8e8142ac3f9c011f2c9113621d81f4ae209473ffe519d1c209a8b5f980d5a5e36d0477e42940f64056b971341f0992983149707d5b27af62410892059adacd5e16cd0443f58339387d1325aa9d1982d400dc00490e677db498b250107e0fed1e2840ec1f3655105ca01acd5255dc9cbc9ce988e00f5856e1a0d7abb66aa7cfd8843a222c6973065f9e2657ee762759ebacd5e442f05257c7ad97f52cc0b1b720d84b4d0a3e12ceb0bc53df8dc321d4b987fe45b3813584231546a692d35c65e461f12e59d22031825f9a73afcd728f4c27a7328fb454e82d79cf773fc0943d41ebf12ac91d85aa213f65b15049f37d8fe2d79cac40e0530ef87a5fe168b360c8030dc5ecad2685f42ae6a14743bb6a45fffdf1905ccf31021665d36b4d27373d0ef556676fca5b55fb61876868e59b198e99c8c34ca726799891fcf364fa4720a14a57297a15a1d9bd9330e091aaced2dc86380242aa3335e2412575e7fd558cdb92421d0d6af4652a9cc3d813bcfa881ee62806e16a3535e31344d3126034b54693a80c00f62017272f1756e199afc9e47251c8113ac1babe4eabde0a297d4bddfdf180daecdc0894a870bdce2c13f622c191fdfd07281642eef6b6f129eb709faaabab7eba17d9b8ecab5001691a7172308c0e71b3dc946e3e07c92255e4c2cdc620f4b746ce360371ba209f6c691077a3e92ce1ac4ee8131ba8fc8c8992647beab6b5dcb09b3bcd52c76994ff2177da16b66681641adf0a698121e53829258299414aadce767b62d05e731661e8fc5c125807b9b1dc3ffb100d030a1128e78ba347ace2820b7adb1deece982d53257e00bc8522d5bd221941b2808b8c7f4376d0ad11cd03388068407030a0fea685c30903a4e07aa31e9ae52fccad045332e99a4cc8de263f87da403fe1803e3897fec1d88fa587b5eb289ddd13a66b131ed0530300cc380bc8620c7916c774690f808f0746a8316b6c1244bf7429dd4e1a309416defb626a59432a524036e067a06600634c88bc2acc19317c5764a8a94142914d87c0a0594e8c6cf64ff700ab26b189b103f7e2f0173bceb2a9658e9410e13587f962e78135f761f24fa39590fe6a9f8d54a52d73476e3075bd8fecca8bd28a5bb7cfa405c76d1a8bd78647360632b4254d58c602a7e8dd18812318c104a29a58450c6d8f9094416fe8e2f2ceca0083a090bff535dfe0e858485cf3d25833fc2188b8257a5b2760c0b632283353327b0f03311b05898d397e9f377440d9975087d12438d06ca00500b9617fdfab0855240697ee961eb48773f73327887626175fb57b7ff3b2283ec502cb4ec28d05ab0bc6ef7ea3a07b50401dd19562805681828550ea580b911c99e76a82194f47476444aa59f1d6ac89c5ad73f9e6281fd4ef73d75f2d48f613fe8447564cb1054ebbace3406c426748139dcf51578d332de61b9ec910b668813213d823763c0547fe5e1e2b692dbcfa66b7760bf18a331c7a1419e6a1a1414330085c51c878853e801e6c800e2b41430f5ea202e95542a124808210414ea7e34f6c1fd1ae8a3b3734061fd3f1a14c1d80f16452f9b066c246a2fd65ef308c27253acbd50a8033eb79f3be6a9f6eed740b15a690c28d6314f7db15fed890115c5b6b05c7dea930ca2604bcfa552778c31c6d87da4f1c2ce8effafe0756f23478197eb2260b15f1bc19c460dc95e1ba27df6d9ebb4645ea715841a92fd96bd4e4ba7c52fc335100beca7ba3341d6c6e6a08425ac0851eca7ba03d8096af9fd7e5c7ed8cae2973815e0fd01849517d5517cd1e276517b03d809baeda5891a4c908e19c58c54465607f61da7c88d19abfb76a9f43dc3cac00f236ce949df5d2a75240ededcc8e82a56afa0bf48d1e7f257ad5a1289d25a6bed4a690ded31bbca7895c143c618444cff422a9650b9700b42bb3260f78b3c6508412e62a2dc2ff27cf18a81f28a501a07b698b85fe4b99f47d7dde955bc42e5f2472711cae5f7235609ac9123f6ba0cb68026f09b11e5bacc80026754200599b32fa5b4371578fb0184257dad9b0adec7a4cf2209c29bfa24d6086ced68f775d7d09e7f6f2af477c72e57afdc9231c2189bbd1dc352fa2e984fb90874d195a1390cf4c85c278237fc239c61f9fdc771b40f8add7ed94f6a206f695d0379aaeba9769f0315e9a2cf381f47da1353743f78c47359134374f99170e42932525f027c499d1103e8b8241748ddd7ad73fb935d912eba116a375600a6f8955c661cf8c9e5af8e03996b882f126eb09f0e8f4d7bf0cdb030fa646d83325813e17743d890fbf8a563c87e9a12fb591af8d03b147cbe901b01bcee820cd67c0dbbfc157ed695532005804bd283680c268ec41851a217940ea281f9c82502111635c57e7c04a4bb677777b7cb7c4f2eba5f929edb5c74bb9361be092670d1e5d2cfd151ec0e0067c27bd72e97085ff321fc07c1dce6fe8361a0d18ed7f1ab1ca8ff78e736cf8dffd8c9e93f7ed9f88fa1d4f88f7b40f88fa3cc7c2ca5398b89b7dcbea2d44cd41f8cf1ccee547777fbf84fd5e33f56fc52a5f9a8bd76116159ccb304f230faf3f81338159772ff11388ea63d77777777777777777777777777777777f71e1cecd46680beb3ab257c97f026705f112ebadea16e1e5eff123ad4cdd77bf37cd4ae1b1beec5902079c42b8211b66aa9676f8495085ff32174cf5f64865efdf31fe9d58ee7afa1573a9e1f49af723cd33c3feff40af5389e9f9df4eac6f3094aaf6cd400e17986a5306c87246e70b5d883e7e727ecf373965ec93c9bb6c07aa5fd2a2b912a007e2580f7f1fc407abc07a007075b3e38d812818317de8e8397dbc1c1ab83833707d77d491cccee071cbc331cbc2070f0d6b81bc7d70400aede1597e2ec89a3e184b4c7bfe286748a5f048e01355c089c033a2e06aec8733b7470357048d8b5c3dde0d809c72f8ea130081c47f169ef0806e22c42bc856318c757708cbd30110b807b4ff1fbe0549ee20f00d783839ed258b79bc77168fa1585f9a8a9f44f03b5b7cbe8480c1f31d721238cb8fc1cc67fd1b579781ca7d6e6699e587d5c2e97129acbefa3e8327d35616bc4650727602e6218710dfe11bd1b7642734e74f887949edf9ff9618704890e64c8b209760169aff46f12c2f2a3005354b07458b11f8b056456cba25dc7624d21202492bd02f8618701f80c9f31c05fea5024d8fa86092132190a81a95430150ce6442c4644042c46040c168bc58866cff4f161bee66bf6cc9ee94382588c04b1582c16232a8a3f1c1dfd7074747474e4841342423020828480080a12121282d1c8c21e64d147380d2bb18ae499a71b1d9185bcb4c7441c8b5dfe6c0719acf91a08e6c048aa0d43f358819ef759e589c26ab97ca2e2fe7085fc0383e3308fa798878747c7fd2011acc2057893c30aeb8d05ccf1a72ebfc9e0150c7dc6e5da8571f8c753fc5fbc68302ef30f7c860c1fbe0b30f48aa580f9791ec7e92e9ce2fff2f2e23283d1478c040f3716f6840b5d1a97a0782e95de028cc383533e4930e5a5f85872727a70dc8d1bb38b5d2d793958ff0a7370a4627c203de3ece84f44487b106601c681bc00ff0ac09cfafe4288c01cfa3a7a4e3dd81c6cb80e71701d76711d6e61a4be9442aab8fc5dbe7841afb7839552ce0018b9bbfb8cd0af0c2929ba1e638c100a711462aee53f1e975f72ace521165aae138137aec4921e5271f9610e2bdc9df4a598821bbf95c1ed0032c40ec528da0de98f620652ee11bf2c7425c742377a6e3a23eb8fb7c714bb1561bfd33de9d0713a7556ca4a9991d8f5181bd7304f716371998ccb5d8825066f82b01fbf7e18fa53e995771a076b0e2d2a3f00922abc710a13c269a114cce9bf2de4b57af7412d2bc01b1e2978e35f04c2bc63310d6b210fd88fc57091a7382fa2439c82905318bf1c47b3027320dc54f02c29b81fa96156ac0b7910094aacf69f074df9fc6c14c60e1456eaf882f6dbebdce66ad848903be297d4d12136611a7d3a3f973e10af2c4fad006f1e007398993f1d5e701897e378109ce237e2f27fe0e54bf45c061ae232ec1c0878c36cc445edf1736f69af612dd41e0bc1b296d992f90f29e9b9255c38e4e2223e81f1697461dfe1e80406cb2fb75f5a8138de2381608e9fa8b05a7aa2e02f6e7ff7491e48ba39acb09fe4e1a3eee3239b22acf652bea41230a7077eb204e3c42b724a913422881e3d7272b0608142425cb4026ffadbc60656ebbac753ddc7471f1f31fdf8a8a7b41498c3b77f0acc911fc59525ea9135e2587fc00a2bb18039ec400ee49e05c4e198a7bac01c3278256d60af9fbf00c3d600c65a0c28c6fd244f7c6d6113c6fa7ff1d5536e7f2b71fbddcaed871dc5ed97026ffa59c7e9f5f21ec7e1d3c95a20efb9fdfe5eab00eae2405dc447314648828b0b510eb86cb1437784602284103a10ccf1dbef2a74ec301ce84b9017420e06cc5d70db085f89451fb5113f0c1a92cc2104c9978c22a5c015b85e924acbe83dbdfadac8e705a5e32b1ee1ee6e0473fc7ae740bd82432e286ef3f09c58fede88e8b4ac10e8edfea987ffc12022ce0981c13ea24aa8d2730b25c4f4a817608b5bda772a4fc5a0d3d2def4a6105876d5105f3c35521eedb3f8f254bb1598ead771bfa8e3be5e2f2a4e5a6e33904701c446311bf76b1bf7e3587c398eecc2a9fe2faf973c0a81fc7120c791120798ea8f010101ddbee109ec2416eee33d3d502416fd9c141b7bda7b491ef85f7cddfe1d57348d1b5cd7da23e753596b8139fc47b55adb2ae0f682f94b972aa2f40d7c62ab8053fd55b8badcee2f5f17f940c5e5aeb570522c0f30ecc7e3760e2b2cb30ffbf81cb90073e0490b84285c3efa4eb8fc2a98139f2f1fd56a2d842f70b5cb49f7f4115e7ca8dc6ea227eea76d3f63aab85fbf88c2dcafa3dc9612217339620c13375a611fe77161adfd2978038d4ab287d807d224d293866c5f8a2a8d93ad1257a96537a158f0db7d44ee89eb56737c4b08b2b0055bf2493f4b2f896410cc31823935ee7c1cfea6879b02a0972212d2679a6d6fd69f25ceb600e6d43103db60eea44d29938c4a1065c22dccf3296fe9d57cc19d3f2b732fec78d11a87f4f3331247d3a9796a6fce2a6cc72984eac17e304848af3e29f4f3e7afd0027d219803ef9c3fbf005b9011ac98324c189803e76b5b6c6772eb1a7ad3021b0b3301f1d2799a949efae773d78ecea799d2285381d7b4f6cde0b0fd32acc7838aed875cce287a6666afa78cbf7a9573c9b22a299d916671c628e3fb09c2e95d9452ca8e177a476eca3d92795e2d65f7757b0d10a77e4bf91e83a7e0e954ebec38f392cdfa31384ee9e1d7005ddc035780156663b012b154a78737b8fd5eaf50844d28027af2bd153cf740165c8416cf4aa0277f85a7cfa48ceb31c91807404f16a1af64ccfb34d50e0678239f4a22ae0b81299922f2b90e04a6220cb260815c7f8f05cbb5be1149074434ba740f0117642041c4151be0608a211d4a80840f539668e2ca0caaa1633411a3c89c46e02c2480b8bb3bbdbe0212410500e2579e20b5149a25463a4389db0f8408049a9238a34b075280d819438861e7855ccee8c94070060e672c69d2a73fd10829c3fd8510810d113261ee66e4e0fac7f61a2691bad7b0ccd082644691193033b204f634a32568d68053f82afdaf54fa4fcbfe33691e6c9b698b5cb7ba99eab699344dd3364dd3b62ccb322dcb32ad542ac5772f6532524ab517b00f150b0a696992fd49fb19afda93a72568cea04e2aa564a65272e44a2b2d554a4b31c618238d4292085653ad3d9dbebfda138d4a08468411d21fa91a4766aeb4c4b596b23967adb4c639e79ca54a6b9c71964ab546a694d219e9cfca5752e1e3b24edacf7834aa1a968db5efa982b4501840229b156c8fc572d6c7fa1a161572fdb827ed673c9a1ab6898c63594639e57c2999657d5959da6a4f42efa9583746596bf745494b924a4a4b52b694f2e57c39492492c32be47a92f17f304bb5f6747aeb59b68c633dc535fa67ae7136b93effe418a1b7cbb78e53abb5a7d33f847d96c5fa71e7d7973ee41448b5966aac92ca5afa5a6b8d55525a4ba54aead81921fd917ad908e9e3fb76806ccc98fb2171b96eec48921b7aac513ed78a253305213dc618a3bf2e8c4117c64ec6a8e349bafb8bacf6eac6c9460d9cf9528230f3810734ac8c69d3b212a9d229a33733fb66448c2e79da83efda0b3208536828256cd90d3b85be31c61863945d8c313a0d2e846c027c18142f8a7dcf657f04924f1c07b8a23ced79691cfaea18d5c1c9a5403f62a484e1437b82a27822e57e5bcff6d28874d8a05c9e5e6d4f209018293d9d29e807fa721c0d4ca7fac3f484715bcced6de7f6e6a4f4d2884a2fee2452fe6b0a65b55738a84ced158eeb36668d9b51cd39102ee5244cc5b8b150effc8c568da439e7c1a571b34cd33493464d9a73dbcd6434e7b49bdd8c86f681463fd0663410341bf16627ed8646730385c3e45d8437f167e731c8384915d401a08d3f12af8dd7b99f07df1d8a851a335fe375aaa058d8baa97d243d8c98617e2c7d2cbdec20e7daf14b7ebe5819861258549902045a6046ad1d5c735af5588aa5d873ebdc82c8cecea0a6ec1d463114699c9dba448ccb7fa406c7d9f16068a704979f77802e0186988471997ba6e4ff1d2f85ec7cb7a3b3698f3d1c6c4b6e6326a8cd22d42bbac5b4712c1fedb5200448018076bc4e4bfeeff821ff3b3a2455fc91ecf8efea1024ff9c0d1b9f75bb7a2381fdba45840347108e201c413fa7d37f95bb8ba20f9c0211d785f0df09078eef381ccf71389eb405e9dbae5ee968278d53f3dc7f15a7fb1b5fc375085cbb8c3a857a4671fe05e9502bcc8efb66b8d252c961e087c607e2cf3d3fea4bff5c733a85606d8eed9f6397a7681e88dba0e1501c0ece48bcc17d0de5f29fb8af8fe88e7d523b6016c3cf001b10b6d03fdd6769842cc3186a941e840e45fa7a49cf5fa4571f3c1f997766fb0f3ad45744753db8f669742899af57c6dde572b97c58ccfd184ac3a12c98b032a61f4a50362d83818b0eb76380c1012af8e1b20424d2d13946907da5edb79fe995f6f0d2876dea96981e894ecbf459c79f5a4703e9bfccf4f5a3c9f44c745aa68e89fd2feb6820fd9ce17249c8bc95e970306ddbb66ddbb66d2693c96432994c9fc4b46ddbb66ddb165f6e2693c9643299b66ddba22cf50c8369734b96d435467267dabb7183e5ff54dccdb407add7633f55dd82b094359769664894d247f9cff727912825a9be8646a3fca8f8fef1274f29e59491d9c6534db1fc38d89af698344353733bf3925966394b2f29a594524a49b5d494524a29a5a49e73ce39e7ece94d29a594525a996c07b091524aa594df84d592cf0489ff69cef94d58add92561a2d3921d13f9b49b734ec99259f24b4e026352cc60720598169c51a585a40abfe524b54b5eb2f82eb98f24a409b7b2cf90dcef48bc3294b447a2d3d260a9a3a1fe079f027e93b080f6f48174b7044992312ded99e8b4b48ec9f659d7d1505ffeb433dc9984f61b97845d413e2f9e1d1b94b496c0312d9e1b2dadc341cbb22ccbb22ccb344dd3344dfb26ac96f649b42ecbb2ec4f3ed84cd3344dd3b42ccbb27e773ffd1c22838ec3443b74016a411e8268c187354e3ec81ae3a203242e3850633d508932a6ab104363215183e285434b74200905cd1d9c8b1ca21439987121260b87a12539dcef54e3fa85434b9a482d58043f4ef8c31a8e45cf8889c2f44e969793db43368471bf9aebc1fdba5b5f477ff5ea83625c52f8c7092de3f6f395d7c7475032ee57d3b026dd28c4f8b9fdbc83a45728db5edb184cf5438e712c167322129470cc06c6798195f01610e704268239fe1ec7bc9c9c1e1c77e386ec5ce854ccb156f3c09c293007d60a3dd50b42b9c58b08deb48a042596babffc386f1cc21f32c8cb35a716404829a5ec5841a01c796aaa24cfd095f26724e501c853f0caaf4f7aaa34aa69c1cbd48cfd832b709cc032bf9d61752a1f3b08c32506366a293589a2d6c04628e60eb692601e218229b65ec8254c12f7abaf30428009f3c3fdaae34404bc8a623cf1b8904b982c5e512e0c56a3b5b6c6292a6d02053243af0c5c7e66e6e18a8b02a545314a1e90d861c8f295226c50a4412976a872dd8bebdf168c134250a10110508061d4aa528b1a6b904f9dc2ca46796460270514c0b41b573088abc0891841bab27ccda0b21400c09eb838b1c5317e9a0e5e6eb71325ae8d3a57a8b0811533e892832e6010e30d30308a220c1035c8402b4ae1a65295c05ef20596a55cbe3ca403161cb76f2d4d11344f4f038124620004151bbc5060850b3620c490155fb8b0f8a2e5b3055a75d12eb6a059ba28a2932705d4bb708887089e1faac820cc8931c648ca4a5b0cd0a8d63a54bd162650bd5a6b1de386a8031dae3fc31630b37eb450bfafb859ea16d8021d10509200ae3c808cc9470b1b37a3790d03ae97b422d79f3d19914458edca4303be0cc1e08a2cb400c10c7490b8c2c91721c8a18b218eb832b334d1458a8e914ef4b049b14419590ad985433c4e4a57c84a659c31ce0fc8297aa031c6219e1b6e8c3fd3ab223593499c205c38740318376c518266661abc2f6c752a39ef0b5b3bcf53fc3870a79d40b9dc512ef343619f1dd80d9e78395173f56373e517c048caa0af66677b3539ba9faac909eef7e34a39e1195742085f8578e146e3051ba8b407650d2b563eac91cec318310a1fc154dc5dc89b5d06590d86357c2c3f842fc09657fa3a9c849b6340742af56049170e35698289a5170e3511418cda85434d3a703f15515402dea0ca17452f1db89268c2004ab09ca0035b7cc8125445b3e20135c3889985045224ab9a1471fb6313236e7f6d92814be3c2212662a4bcadedf5c7244add5744bbf32b259de4ac4f9a098825f95fed24f4fc6b4fd919217995df53caaf11def805ae7c08bfe8041b989da5d43498c327d81057809d73101bf0a6ff0425f6f36edb606863099f52c6f625648ef4016fa6ab1c764ab6775143d5b6b2bb6b47d9d1cc5865fd4f4a39254b035afdfaf43ff8f0366569c07a51ca0f04cda6a90e64083dc4602c3b1f484b2965f7b953a72592fc3ec6e891c8959f04932edfb6ccec92898c5af4c844ab9fcee5cb1f716845d2d56cd466da8b524a496ad91af58ff25457b53dabc5b6b56a362341afcebab5a01324b260247645bc2ce6ac7476d9e4aa26e7d3f93e5f06ef2cf5195bf071630ede530f58d91dedaae4b4aebf229e663d87ac5a2d4e49e5894e2b63ec8a68d79f708eaba0c11bf827ec58af32de2235d75f90d5ee29bbfbaf75b6cfaf7677ad1ee3fcfc639c9dbbb78ced710c464edfbb4f4a2244728518bd7d68f76ef70ac0ae87e0823f4de650b1833fb714d434c898dd653c85615965e3b998ac8bb0b13ed378c10630dccc094938c7b73dd35e4b97fc69f9bee57286b08c829175fe0884c3ee88bcf2ad3f8d14d29eed15853bdcbfbff0a344c922aa0bdb8b31b248dd9c13beec424acf53313aa4420521346251f2f9721748732ed860ce39679c73ce7903c990a103b0b045682ef3176f119a8b033a6577445e8eed822cbabb17eb2ee4ee63084991b9bbbbbbbbbbb7cbdd05df239412860f9897179e8ef43359760f0dc3478c1417ec28fc4fce272ad89a38b4026ed1c2059714f8bb43f992ab79e803762a3873a3e4663a0561f70fe1373441c9f50373a2cb792e2c037aae04aef80842082184902b4f7551585502bd7e08a1bb8cb2f8713e579afe7e14d42a141bbf0aff4b72658cf0398c16a5fc60b9cf0c901f34fe81d31434b0ef2ede0d5436d41ec2878dca9dd8d4784735118c5d0242c8f2a1b2f16a9ee63463356f08cbef3e48950fa15ac40fb63eaa0fa54cdba8c94429d5d204918dea673c1a558d2744f48477d27ec6a379980f93966a966959a645aeb50a1951cab4cd2443a5ad965a6aa9b532323232323232d46432994c26d3b66ddbb66d54d3342d324552c5fa0113e24264634fa77fef6b5844148a59cab4cdc432325646c646ae3255c65619196b32994c3226934946c66ddb64a4940ac9b0d5004b55c3b2511915c91dd2ef34b1a5df69f2ad253e664cab4af64d54ad2a3446d6b8568d526d524a6b8d7552aa6559ac91d2f91e638d7466b1465aa2344e4a4b94c64967294e4ae79c73d239e7a4744e4ad2015653ad3d9dfe44a38241a1a9d69e66c4e0f73c958d161a065673bd93f6331e8d559d5e457590f6e4094d23231fa77fcf5379364274074436aa1ad67b2c22258268aa0d9ccba8640dd934357568460000080043150000200c0c074402a140249205d2aefb14000f758e44725e3c9586a21c866110c518638c21c010600031c01043886ac60601222888c38903ee1cfbf2aec6c22181a7c6b8895c8ec5a2bd5218a73d02b5d7039c78ed5ea5dbccd46d8c12730d1ef01dde522cb6cfb7b4d3c7668e474735d1a1245940384448f97410f9f74ec2efdeb8d9dbb88a6ef659c8aff1862c2c945fb98b9a479d7ff19d1b87f29ad7eedb88405bf59d4a0ff4e8a5c6fd9757e6983e648509f1154020f3e0a311c24dd7e899c8013830e0b34e80039a2f3b78d0635726c2183abbe21288a1e540d7f0afc8569ca6a32a48a772cd9151a1e53106b90ba989ee9ca7939958b467ea7f45ee3f78ad0511a23e424edf0e29182a70d0ae20fe306112e344286cf322b2780d0270db4857871b0f348b26cd2eb41b93488c70d6e180150ad7d5d72697516691286d83d6103135e36453cf3ac68c329aac23e90c0788ccb21ed02c8be6502b23a17f4888c6645c9b30f80c104ac4b4844de31845182e5bddbd6c891237bcccc372b137b52da161dc3559cb2092f43a4e2f0345821b0598701d81597046a8ada3ef622141dd47a875c267e5368e68350ce999ba48e16181ebd3edf72052fe0a92cac67d48ae62440e45a9ccf110bcd00a3433a8a291aaf4f9564fd437e4576dc058e3fa07ce2099b861e21cc2f09593a09a2ef15ee3cbd48d060c1c448214b11dff54ddf64d4b18e6e77aeb66b28b3625619b2bb5a002500ec795ec0c77ed19bbdfa212acbdc273315ba2b6db2e727d93d6fb5bcba081e0b72a3b8061320a526a0959d90fa461c24e0cc840233ee6a3657afb1c8b38bfed19656401ac7fbe0d27230a35a6db100f7b3153769928bc5f6dfaa304bfdb8dc4691fa82d6ec127e33650dbf245d7ab38fe9d16b024613c02b5790ff9b6ffebd234e550e18031d8793741c8102259b5606f07f817f19ebd9409ed971f0b75435b3c3d9f3dc29e0c214be44d87fb8d3819e326a765085805e2c6295ff5bc1811128e025f079345f5110d2d30d399e3222680dc31d7d428a04a324b5f6b835b6a69f9a41fa67309ac0de9474ad1b2a92facb8ca9e6cd8cb0766bf5dc91386e260b3692cf9e2d6e80d652ad4024f95965315cbe760bf2f043c30b4d8001fd19a2008815c051c3a345f62a390fce77e165bb13d00465487ae955aa427afcf87b543776ea0a52e88c5913a6090d41dcd785c2ba9abf599cd7896da001de1ec23caf9239414492c0e3e1decd80191a2e22ef3d6bb51a641a3346849a243ac79c0b1cc72ef4092e86a0e28d77ea33563e2d7a392daa3d4e14ea11e8534c8fb3ccc25ba12ae95da887c300ca0e0076d471bd78660c0f8604aef3e7cedcd735f3b285e912363714e2b4f643b215d09086e0d66f8497bb8b5b93e3a4c406a0c4cc7ba301db53bc6106686309dba555895e623d5fb68ed9f3797829061b63ac46940d31dc4e8f46d484601724b39099a1e5cdd447a7373bb27a8a6033f84f58600c3472a768683b73a09490aa14fd9e0cef50eb57f85b372adae93abab6166bf6e58f4f1b388f81d93acfd3e8cf51711b4ef32052812c9ec8774762e2d2fc107cf4ef22e9468d7123b74f27e18928512a9987dc07d4b3b0e7d98a50d73a54c8284ea5a7b775433495ca451d66a23d75a44b0a27694311cfdc869ad4f529c1f8979031797164e4924007dc3ad024a14e831c3375801ad6628cc94c54024a27a3f64510110ac4b5bbac474cf3c8962e58ec262572fe923c52206834c5c7424d1dcbfb18657bd076d8c252dbdf255f89f6ce6e48858c85c902adeeb5dd74c7d9f93f5d2671c1242aff45dae54ef3057a3de009256ff044aa52de747013f5b83863091c9033838c7428ab1f8d63733d85df56072dd769615972ca604820f0128ff30597857673e6011102b3fab6d7936f6b5d8a54d119611e98c1320ea8a46c47d641a1348957d2462e8708181df58078e8a71d623ee5ed25a7c0868f81ff042c8e4bd93d164d3ff881bec1cc08b43e695c3e548b5eadf34443cf8618a1374740e6251a9a92c3ab58740e3aa035382f3a5ac97280d0e0a23a813a59d1b1933d0f3cd36589404ae2993bb2cbbde7d1f85ae453d8e427dfcd5939f079a12a6e48f32b57b5d87865a53a9b22b483822d99ab1112c8a614af630f0b47a8f0a7d27fe4840e91517bbf50b806212665ae73d871319b4148549c551d652c45261cb9559bb91e864fa6f68e91fdc13f2a6762a640de58a2a259d49954ef2284754aff6e07aaabd1282d764a9e4971124e202389531b1a9e336b731b840e0cc60394d5dd412e5a553a67e51ebd96266b428c2432a640a2ce91456203c3648bb97f862080eff3ae409e0f187801175bdc8773b21344175a68e18cb4bac38ffe8b5584b661e7c8c3da5a39c6d2159fdd18bf7e2d42c64a6e0cf1d669ba088e12c05bea4ca6bd9a63a66c4ae08b1ea3f1ea53e9973eef0673733514863f755e5b29b97579d5d0ef6f331515a813e8ab64d0f6533c83aecd58e5c24727ad923a690e0777e5220f13f19fdb3b7499a5f3b49d0d9928d232c18172aa7695736a0a1b347a7c9063aeed18bc176c454eecc22c237b91a10d147e6def467475a5a338b1c3c515033ec355de605e6edc9063b65fc2b2dfa8383c9b482095fb7eca4af9d1c8be43ee3b1182526bd1f6e3573bff996bb7eb1fc1850cd0b9294f1a439ab4f132da6917c5cd20cffeea489c1e33bf84d6f7bb2fb979ff90152d1d5444797d3048825cba5c723ec0e6ad12038fff499da757a6786a8ee34ff454e4806b87cec47862f6b2c924c731160f3829324d59d1400a54f3d1e6b0a05900840480fbbec28c13135b054d95bf0c261bac8b7589c4b54ea0a39630950455035641bd3b521601ab23de41c7eb78fc0d808a9a47f788d90b280822291c1c2712408e09e02166086050691486b04f0811a20881d397e64729098342d9306aa000b15f6cdf34cf02225a1a10194886836e060beccb8273648ee30011cda6a89b04fcd4b11e97d25beeecebe62540d3b581895a5c30929189608c9b262bf53712821cc60f622f9d388cdd06d8556ad88ecadbeab51b404e4198ede650bdf93b5f28c7d5315fa158dc432561296fd811eac3726f4aff8ab2ad548bbfe73563cec60996aed43aa0890fe0a671383f1b20d96930e841f10514c229d8831e6930f664b56aab3af9159d0bdeaf4efefd3f639291010a7bad8c59a208cd2686336b28faaa1ccc870af6b40741ae2723b8a0a719e146964e725808f4849f71a690032c1bc17db55d804714538a52bbf2fde3f98bb9c42c34a872ba253a77b5c666d0ba12ed54b33154efbca5755ccf0acf74568576d103c437740ad60f3132a12a2d927004dd8314342ca4d79263dda5c5db416fce27f63a28db1e9fb3f6c80184d1f0a8c32acdb2937c3c286b5e096ed0ffbc0d39aa984839f4749be3fafc10e3f64ba01c046a4943711d4b18c2aecc72384435b98a9145d45fc34bbeeb059d095cc5eb9cb2d40f4212775d1aa3b802249f88609bf0cec4e4ad5dec16385bc0316fa734ddf49d5e25cd259046bc44b6fb58f97e0cf478f3afeaff58a8886beedf96300bdb78b6cf30f42b176dbcd8ea12c13c1c2dacdb96a9f728b46a78d0286edc274ba2f46200e7c917922d5cd8214b96e03c4e0035c5e009504fb96442ade137389330f703120684be7181bd9580be44c35aa2100489e85c41460307943a83f577c433748a30d103c514b07e1a53fb4dbeec0fee3988022938ba075d97a4630ba30b7b7a09160dd365cf615734fa8f188ace8876a2e4a6407eba12b46f3ef7a028a6c65950832e83b88836cfbd416f27f525f65149abee0c1449ea516ebd24ede1d18550b14078e67e2dd3e4a14d41d35b7d7e795cf77879fb65d0cee896dd00eef27b6db3d313a8f247b5576db3d26850b00bca4c3f6e290dd6eea31af169a689c71d97e7afc113b682e901768540c2bd6640509d105726636e732cce19da63bb8100077426a303330526b1199a34a006ee0fc163595e72a7866fca5ae4e9b182e48e6795a9c291c278ca526f8782f65122c74d675b0826c0a84b4c89714bed3e99800ee90de515b1b06fbd07ddcbaf80883cf26914a89dbe2dbba15ea928b6c136b8c91a75e6adad3d533528b14051176ef9d7fd10af0bcfb0c14e6aaa975138e05c8e6390309ebb101a314db74cc76445842e280acceb964b336a71ebd80ce03d9940391f66bb6a37a2328cf116e909f52b8013b5d0c9200b523de46b5cf64e66d1437cbd8dcaf5c23296318f6870b09d05e730c7b6eabb1a692c5741d456510d695c4c42fcbb7d26315ac7610b0aa21e002f002a9007e9379759e919ef47a80dc27b6bfd3bdf30f1a50f5a128e696675da034460302bf281dc2fbb488fdc6da482dfa02941ac6535561200bff540167488035a5f5d4eeebe7a5ffdda12803e709e68bab95109f8d96a237533844eb84e34974c127e1c387bddaae4177370646f29d0a25de696a8c94d7b5892fd118b34b411c57da3137db07e4136a0120159917968ed7e113115e35eb47dd2ff90a977bff5299f72354245ce5c1084a75479ce9a2b23ef8ebc283e004ce39fdf50bc284f95e60a6f23a2679d278cfcb0c7fbc006a7d7bbcea5ebf245df9b3d7cf34562d9ab7b24ca1a5606c0fcab03d3180c46016a5d1015ea1be0573d26d4cc2fe7e9e8504042d26f55d48dc463db4d186f8e8e7323d26a439a5ddae62a6a9da381af0a7c8f3061a35d53ee285d0821c4e7eee9eb81cd225412f9a202a284ef834d00bf168bb6bffbda5ef57204b64b8ee07fca4cd8c39f2958371f454c46485e945d9f4169d2b1d8e71a12e959b87d51d1c8d1c6c21a9ad41d9f91c580a9b999a1569dcd271feb2f306623d3fe42a0dc28d0e5012d73e3b1cdc93154a18f18fdf6735d0a6337fec2ec3ea40284d77ec40e64fc29e04c2b3ef7a7ad6656e90ddcc97329ba64a328e191247faa7c121522e9bb08d850c869d51a299f465b002ff42cc1580db3a7fe094e55afe8a8e2a9a1b29cde5a4b24ce914f807e6a2390f5d3c204a4d02f0282d4d282df4dc41f5efc4c6421432fd2a342ae11c433ccf772e5c8af91f0786a8ab3c93466818ed614f241616730a9a1ea58c1db353a80b7ec0f0d1c4042a43b302a882f50bc5b70249a946fdeca14cb38d6951a9f12e31801e99e2d3cfc8606474f625fdd756814a23c9ff78b474095fa1595e3a8e636683f447b1f17ebdff08602d1c465c0fb2a2beffd77de144ad4e21feb131a880dd523add2d7ded90b6340606f564bd9ec25031e6796e17f895ee2bd2fab52a3bd1accfa898a8bbe3d56188138c7cfe45750c1e6614d936bcbd89f8988e695c0c0e55a690a83569f591dacf81fa636286be2ca54b4adf10a0dad4d8e3e243b2d1d8c603fab87acb859091cab49a8248e1fdbaac0f8ac50f52c5d706f41459a1c9444528270125121d02310060cfe13c701eb44d307bc7d0bfcab99cbff24a22f17dcd10ec3e9b4731d37e36bbff900c50e06090ea05bcc3f3a0c092319dd5c3fc9b4310ca6298ad1ede20833d6391dcf29346167d4e9e7c7ab731a68a1934b2429f3a8f1db29a030c7fcf570c9042851b57f287d9e1db51cc0b54cd84534b60955066ea3c7ea616a6aa706af533fca053124dd356fb77ead4685302b36d787adc33ba62bd31ef2eb5a218be167223e3e7a3fa8b0b70fb3aac5276b833d7544c33e9d59c778962d46e83cca61773de4545b38df994bed7358c2ef866141dce97224c84a31863c07ad63307197c000cb6d82619dc31345ed4b376af5762f1817b8bb524927848d0d93252449c6a889416baa7f659dafcb162543e656b555f48b5454f30558206543aa1c9c55fbaa0f9d90d6c5dab10e9470570e356cd2e3f9ef4818b99bfe71cc9137dc5cf43a997d9081d3c8d38b6ecf4b6a5a48d10e8403654c33b67d0ee1686133b511f395212dbb873249459d73c67a646c3b7444a77134ab34111b7028717949a49a9750f24c686591ee87f7774ef0471ec43ba662d2d31fdd2a4ab154c625f43541ebc282606bd9dc2afe51f61573441bd49ddd9641da30bf40f38014f671874de837c45d62ecc39bcab05874ade4a176d16fb5ea196030d9653ccf121af3a5fe55aa5db8fb4bab6602b51c9cd8081071a78403c9c603d8eb3b95ddb603adc6e6cea20104d1d9e0b7f2d985bb25f6d4765893a8d7e45b4f6d24e8413413b9c8dbec2bce8364d6a646d56824062db0a7febf8266a7a3d84b0b147454fb6ba43a549059e0a63268012db06a126df51b28ac07b63848f3b80498b22aec2ea874cb36a63a6e1df3ed3b6650dbf6ef8589e456b9541fec6b9899c31622970302f25457159d170df57fdc0424322d3a4a2068bc246bd6957be05a96cd3943cdbb64dc165b413445630826edadc583b62690c040969e882dee792f8653b11afa0cd989aa70979b5b049be7eb3c5b53cba23bb5de4605ad4e16bc0934c66ba9025dcf310d02bd6f2a5ceee40badc2afcdef04c71700463a3b4447eed09005d3ad27ba1a70f9fb8f734a3f794ef1e826dc96185d2913f244847172b5c6928df9132c64f7bbb8fe42f021c48b04af9605a9f3eef4a210a5ce52583be62a58d4fab9f934de0144614445fb48901e6358da5257a937adac42e541ab7cb41c198606380767f10dc08fc4768f6a1b81163f1a83baafff661def6d5e85ab48d13d9d629b9781d297f69824067bf09f46bc5d542deebc89433147531eefd0d9e6eb3ca376b136f9df9dd732d98078a0fff7ac4e48e1e49bd9c2b649bd545dbbf72d03f95b33d7bf3c3d36ca1fa826e116adcb45e81ee9624513e88946853239b9c0fbd52bafbd3de130e1ac10ff527e501580cb1492c89fd660bf0d33cc9d295158fea75790dd3f89d849a402a7d238c018ac1064a7c901d4e50613f5dd1da15753d28f8147edb13bc1457c50ee296a063c064ca5541107e22b61f04b25dc418192a3e0467c9c61be9abdcb9b9ffd502f22e7bdb79fa947830ddb21d194e643737e9bb5f4226a3ac855ca17bf802912573ba51c6e2a63de74bc924965dc0b5a37bf6093f35ad94bb4e947bcfcc22424526608b047e7f112bc66b0fe64a6f6df6fe1a4f7fe0c3be1fca4de0d16665891652a40b6b92d16b5f0e88511d4b4c9cc898c45ad7e842d9dd21495fb931ff084069c05e046d91dbd6f9f59d558ca3ad9979a25b574b40d6296adcea94652d36a09b440b7f6c93ce3282baad3af3c4ce9dd03484070b4f13c46d1d56163e559a5b46417c21d6def9ba17c5cb36ac5f8855e0d8d6c3510b94865831564eb8814ba1ec46f7e3b02676dae4fd913d2c5ee10e17a1ea1f75cdacbcd7f08543e8733a077e20805127f6e266b3eaaa1ddb4d14054f4beae5445062fe69e1b260c0eb43b42b821d247d406835a5488d14a4d60659ee00dd0ba468322a13d664262792162bc5a169658a50896e1b86ea804d6daf54a7d2a14a51e7b308f4efd74bd5914891b446e3944230a821dfe55cc307366f8780c49d8e12a12633baa561a8101b10728ae10dac4d17f586a67be9b984854d83a5866aa6b8ab95b5bf9f35db8a183b1a7be53f10d0bdd9de1cbaa55c89733db6fa5aa5b007e50b1ba6812e457be23c5ead7f51cbfaf702f20bbcf6b9701740c764c5e7b9a9feb5143e2b4683fe6137243d33c2bec8a078a53949d1aac97447b5119806b40bbb37eb16ad943ef230a3022c6469501efad94264b6efdddfd1e07a6913f403479b2ceed91fae61e55fcf46e018f248af36de4cf268997b1dc61bf0815d04cd06dd6e7afe42b69843f4db546f7f021faca60461755b7acf0510a1cd920f634d10e4f763abf5ecb8fd1d41945079b0e865806e1ab0ab18b66af39499e3243b844e31e912aadb4a8a589c2d5cee76812553bd5e96392c7422db72f96092063ece5b00563fa43ac3c3a18f35a95b5dd507a35cac9d670a6947fa84c37481d301729bc74a58a97d7b208b09dabf279606c270c1a70090b195eb0692c08a7f5d53c4a2a369be7914751eeed04cab897ed9755d0547e1765d95184ac5297438820f4ce92a4719797e058de1be0b4443255796e389fe0150154920a3e3707954689343fa032072def4f36b8946b06ad1db10910fb125c192307f0d97db7de4ac5a6cf181ca5b960ec0d3553dc731273f9d5634adbe043eea986485906a196f1a35c0e2b45e209fe817d3217408e9fbd15085811f5ec2191c134b99aadaaf7a6fff388d891f12b5050b943afa2ba1616ec81c24f6610df855cb7aef574eb0276c9848ed44788e7d5ea2ee81dcf170ea64b2b79ef6ab8918a7de6ce00ddd2262ae3b4a91038dae677570f1b077029967512b656202f7c45701ec34f5c56086d9bc289a0f66375317561a4607606e2402fed36a6095747a8d2c67ad19f2d7665db90a15bcf9b4bf239691abd254665ac539f7333ce552c767001537816be7095d1b9fa5d673c1f38981f39fcb8af9b4506b9a0406bc093560fcb0f237782fc316880e8771c43d3de71fbf7490149b59ba7057480f4f88c4d6c1e33e2d060aedf9b6a766e4e452051b0bbdb55b49dee94e3149fa65599e0967f4ba4ec021e8ff2d545715d414d45297f0fdbc155054d76a968bdcc3633c9eaecc00d4fbd41f70ce7ae1bc5bea4c29a3206c07875bf26079e3bb8585da2f57698ad7a568757d6120f656be6adfbe3df54d88fa118483e308058fb8966f1c2931f6c65da2925075b8921806920d984e123618c12f0e1d6a58d3c3ffd30de863eff8cebe1880efc26c90887c14e307b602beb5fdb15db5cdf2bd823536533b488270953c0bb4aeae543a41f1a72388934485ec0ed8c9227f05160ad1509f1cee4b6000110b5b2153b08378cf2386d05c78e499a46e6e210933b340c2c50139c25b0acbd6a21d4a8a0bb308282f0747664c7e61fe49e21e8f5527bc804e1c4304f9b1c3d4a278834b88e0ffc3476d4add4f968ca1dddbc99ad90acbeadc38c90f21d94aa276a7058136b0c544a2196f7ac201141ff6250b15665d677d0891aeedbc0b0b95c1a95aefcc2bbfe70b776f5851f08eccc155b9766e2f5b55c5240e733f5fafc2346757055a589523b0084e0da0ef31a8bb0b26854dd5140c48e405954f4861a9d03eb69a81206c509e9aabb9efab418535a54dfa497c640b4ddce5e60184af7f8c7cc517c71bbf4585157faf81336aaee6bacd927e6d9566749ab95555e566150b8604ff54a4fe855062a06c5ac1e66d764db4578330ad3220e1961896adcb97232dd5902f8a49f55b07131884981f19a0b60964cf58cf9700bb962590c6d28632b0b6ec1e94a9eef7918663948d360c8f6b3fdb4265db8741b62c43fa3a6d965d9e191a543f399f2e2131a55ab5241089d9d9d08f391641db21ae2510cdd51308b3e9328362e988e442c9dda6c9b5c727ceb15b5e089617d5e607f11f5df56d82d53733472c1903b309451d56bdd8c878d1ae2035dc4503a5e505e594094cc2a8441fa7a0e6d247ec1974bb027d6000f8214c5c735df400f8695930a014e34364aa15a644f26822fc49f7284ab991f8f6c10fad2f03edf32f34f44f1a80aec3431834f97de1664f7002dcfe2a6ba8f340402977970a5c95ff6247c8536aea08604fc44e4083ca02a37a93caa12092c0f58120a681e5a110d381c581129581e540131781f550129340fa90c0c4e406913bf318e97b02458a7ca1469c3ffd73cfb4f8da78f34a36a1ba2f42e485588794906354081b1c445883db2b516bc47de25f9e31dd991d2bc33ba96cfd170bfc577fa71b942ef713ef33835b7efe28284e783e11e0c7032a794db322cc1fd54cf247ca3facd8f5fa491f3558bf83e8a80472968ed0559e073874b0d767990cc3dba1818d445fdf77e90c3f2fc02448f818dd7c6c854262640ec4189007ac9be21baf0e561fed65e031350e8ae739d0dc741e5630efaa199df9c77c4dd7c5c2a2500bcb995f90aa71d68f9a470eeee04caf49d009bb512dc9b178219b72b5ab44ef5af8df73a52dcfd2ad0d92fef3a11d7054aaeccd5d739f682a045aa284abe391bf715ce7f374d47241b243a4ed80fb7940bb22a1c9b6302cc599464aba0c52af09c7fb5b46ee43f3b52e730b16848082c1133b5cd85bdcb8812623fdd76ecc716c429cf4d71b0b9b468b59921a5a8050bf985163a4fa5ca8c64372912df4aac627fb43b6350703682d661d887acd98f9f90c06bf775ef3d4eed2030fb0f075d3a77b41560f14c86c829c9d39541c79299de3b6d304c8ce62f68dd0b3362bad5bbafcd60dfd5a75df177ea0dcf3f05c170712e5925db701e0b799a6e7edcf97e089f45e2ff30823c7b01fd6a5253d18ea02b0fec91a8e99d6d2d9ca8c003e9356da2672f629209655a189e7d66f83969b85cece700cd94cda337f56045beab29fcd35a7316cabf4c59339eb6543dbfb2d8c990103e1a4d4ac66e8dc7df3224425da0d1d61c2a143580e1db324264271b8615ff1729f1e9b72bea3f4b30c8c6e1dd482e2fbbe1a54cf3fbbd39ae64d821ba35c083445685b8adfdbbc20a16de3b58299bef521932ea988b02da1cc4ed60f789eac7a0576ee500129ffaf88d09de5a64b7f39721948f0a4e0f5323b653962a700180da0f61a410acc833000c901d627af760282000292fdcfca87c362ef907e3f46f1ee4c9423c3ffafad77eeb4ca2313d9c6b6be44c83beac19ae82e6c9a42f03b5f0ec80b21f9081c48ecc1cd87120301b0a442f2227f40fffafaf75b8afc94e020a4ffd66dd95eb635bb3528964176cecc0dee300262ae3df7ac164355bbdf12b6e49bb8cd83b85f2ac5925a71cb8015bbb2eba39d6feb4ab3efdea4f079d23f3fe6b7813d18a0232a04af436b3053004308c43135ae521494cab61f6071552e9767b93490ec84a854ae36ece74ef6d00e17400fa2be229a971c12d75725b20f4e74c179e263f9cca8fe19280e2ba096ec71c4aa812a11a8febbe1bbc4239dad578f1800d2c041b58277b95944912b347cf40724503d1fb4952c132528892283786aae865be1c4e0ddab26230711b7fa90eb42a0c1b26b9629b93c856e1cbfea9f8f2cd3ee23a8fdad53a6d8d3689668d8ef5375434531eeb244186fc26c1eb00bf9427ea3e200b08bffa1a34095069946be50226e6e3940e368746d49fc93263fff91fd9ae32f00068215f6237f7b5aace2c03a1bf58e012e1146dba93dcec64595d7a15ce281609de11f34f4e51e00d9d016ce7b2a417c6754ba3188e07b51af5fe38b6d460afdc3975c897494073a00f2e6ad6c02f8b507bc5ef3f2d3e8e89cb2fbceb350eb3a7f9b4369323a1ce41c124fa9c070023dad662e54afdbbde2aeb8e66ac79aea9e4efb5e5b076dec7aaaa4be064330453fc285e24d39dfc48d1edd4d301e32c8a316187d762a1b60f2cc7285ed35907d35c6579c744f0e4e9149706d45e13c96746c404372cb6e2edbad39f144496ff5818da6ae6c8d2b09b8b49f1291eff72cd7c84d0a38073dd3b905e1f4df1952750234488a02c28ccb487236312fbff8132761e565b393bbd2d5fd8bb6c3f2de960a5b9930f97141981cfb80411fad3434244a82ee731038a2174b124f9f971adb82838dba949c913deaf854d7afdee138572a448b2546bb7f3ef81ae017111dc63d025b9a7bbdf2c0010bcf7c0f4faa98dc7ec3669aef60b03e53a28de2534587e36e3c432b8e2c7a1cc92cf014a1af794d25b998500a16ec283188a3f2f21ee74e3b7b02627abcee1686afb3953b4689c804e322984c15a14ca09915066db4f4a5d926144505846b3de06fa144dcda2607847ccf34f91ca472a9440dfca9d304bfc32137e0dea16d820593a8d414fafa696a32949517915a046f65b295b7b1bd90458e5fea0781d02cbbc83af7bcf5d73230ba44215156a751d665f66a060e80ea6b8bcc74d0aeff7b40147d7c58f9dff33da88778011609e9dff30635e1beb0b0e960aa82d6c3c3add728eff69d134911133bc8e8f074f3616edf2c257d4374f48d4fdba845afe4ef74f028b4447e2b85719f95a4c2bc7b8945f36a98642c62e1a746ecbb60c67749262f537a76898288883d770f8961eb48b061870e60d1db396ec86f7d055d72be492260d541074eb27e842c87e339eb84ec5ae715266845fd1967242ff04122b8b31bc12f3b4bb9c8158c63e1fb677a7326646a396b7b3f0225c810c7386ee902a52f9ad6b2b664636eb63a4bd29a189480b0626cb0d0c8165d78002c2c0a889a11f8b762f8c3660180b0c71a623053405ecc6c47f9c158b054e0d454e44e6c71a3616f19be785970a5c078d196103140170d22dcdb7cae7e9ff081c3aeedcf9540d31c8cf21002048ec64beb8ff86457bbe3227c980a587bb36ddc7bce824238e2268c4d2755d24cf64f77640ae7fe99cb1a412cef54f5e56f00177ac97d0fc57760c00a045ba7bf06e975117f436ce1e455d021ff88898700a6af71e48670f5c70140df7a4bc1a3423c810137d4807305ea49be8956b4adb20d49ec6d86edfb908477c1743ab1d23b51d19efb7fd141b9b588cfcd643a7e1042633f1783dc306b48c1e61179087f479930313e92e8fbcaf2d827ec5d2277afe8ec6b10aa32aac318d2949f95807b36b2fdd5fc9b502076874dfe6db4e3a28b098e64b92351617296ad36c4b3a0f250e13a5c2afdcd1b6d1da631dbc95800c990b39de62dc497e3163ebc57ce06f4c031991d65d03b5fc709666b7e17f1c0b6ad2c9cc0ec61119510d3f6d4a85ff0a5cafafca108fa99794b49188e5b4a69cfd8ce3ad80bdcabbaeffc51a42f28373da41d5cd9327bd84558cc0b51fb8e23ee3218c82e52dac80e83f182b09c95ef0bf0a97b62144899b19a13a5b82799f96480588790c80ca39948529f9d8f3cb602983dec327ed7d2f4d9de24354cb8830b34a1900c8fdd4c829723b0035ab4d94289f81050cb16689305a4d97354f9ecaf0a0e276271e121b8fa43950187a05a7a45ae4b4b8f9f42aad8776304b20a11e2f13584f56df7e33b943596f5f7932d3f660df60ebe4f8e67f1b1f7d63ce4311e0079baf5c0b45ef265bd33ad0107e344f1010e5014bba7d8cb2c46cd484ccab3f45d2d1e57de91c36b25f39cebc7fdc82d9f640e9089d7cc03bba642f9fa635e01fd046d6907fe80bd92f1bfcaacd1082be325c8b9236cd9ac2d2ff9d6cc44fe2a599850f5ed9d67803eb072e6c73b74835080ee8bd982950ff74beec8abab7264271f329c4a31992839b946264e0b459d71d0740cbc87aafc4b05e78816494aeb98eef8e73e38731a8253ffd1cecef700e53f601625821fc56cbb8005c1b9b7b1cf0005e853f256c83231baaf8a74167af5c2a05fe1ee00b6215ff04a65f16990806a60a300e839c50914bbbc62f2d91d0abb6434b911ad10fa6f55f0064b4fbff5f3deba4049252bc11bacd4789259ee31d793037941562851560588713dc932d1fa4ed78e5edd8e16eb45d5f7fb7e9d6282beec6fa7d4ef9a04f86182a39f4f5fd51f2156523b2c8e089d0611a8166d3df646c850b4dc311f41d1dcb9ee1bf18430b152df2a5c4bb7aea1be94120857c1a9e2bdcfad584cb3937c110eb856497103e5ab038944200c30b6891ecc684658e15b2dd4e449e0cfb2b26c513c1610e8bded7e31abd0fec194f5eddc0e06fcdaccb31ccced08577e25d26797b65711a589fdbd37f9b1f5caef71122a65c07bd78f0805c0615d14ca10a285be1f0ff4ed10b49e532763753afb709092218cd0df0a289e72df82ce77ad771097422cb89fa0c0bbb6c098546884850169313fa741c8cb1207b313ccb65a6540c5bfc9afd3c113ede53fdc4977cf920f1813d030e39ea523727bb1610cb46e056d4ed359feb8fe99a441a55b8a91255e943981f433a059af8ff105cdac143beddd60ca60619b1c553d3eb4ffc63e06e783e69fdaff2abb47b805207a8cba1193986b42679274917b7f49b26f3119807771adafd64946a4dca45744ef1a0d682260103d57ecc59a306f266ae4360a235225cd42bf393cc1b0a63702dde2c6abedd5e505291728648242a614222b6c9da941b906cce99a2291491f052aeffb50ac5912a20e2656349f2a4822d7437390552110219d7b58209167ae1d6803e9996e8a82cf4b238ff80d000d81966892854ee0ac62e07df3b89f6e3e29f8ee919f4651210de8c65012dbf31621ea49767ee4a541456e91f930449aa77625cd8b696dc3d3ea923875f51eb6312f75dd99ba58ce42242cd3d0e2133044f00522acc920e96a660079a51363e6bbbfe559b11df2c2aa97d5d44102162f802d30fcb6330e8e56fabddc616fc63fadc3bf05110997a0a62e54936a217bc9891ca800047ef49e830021608ece819cd1154f9ea37d63041dc83de2f53214291eb9c459a5777e2467f46f1a221732d1275a1330f4cd38d6b258af4c55c9400b47b9fe3de1b466c19b6618f8f50e82177c847748dc600317d20b4d51abbdf2065be0e4f1f45330161256ee4a3a739da560ab95878ff75e3288f320b32bd8cd26035aaf826a1f93b5a2688b4f39556a29e06422642a88148ad3beff85434aa4c615b056cded2e92bac84e95419238692ffacd94e5c30d64df0d712251c2833ebcc06a4c406d2ad51dc30ae984a05c0a9db0a58408c799b61cacb0c4daffc8fb5cfdf95cc3a2a599e866ac370c34333da97d0f2415817818834659cc78a8c39398554679556b7014067e4b57edf0bdf8c81a94a5c2867e7fb058cbed460ef3d2fb868a4c1a8387fff81e7474d5ce86539b908b4c07e0ecda41a0fe6e59572253cb961539d6ce0bd81fac9d46a93c80aeb7edb30678783d4985bca4caa055f5dbf9a4fbe611391247f14a2285659e22cffd367c0a93cccb00d404c21cd28baa4ca96912ada7cdf5083a3db2ee3395e8a49945248ba13827bfb23beb64f1d3821ba4e3d7ebbce2c74ddd8fe513fbb48efdaa871b21e6b96d947eda6260e5409b4f324277da6a54b626e316d3caa0ccfad271503a6eb8512f712c3ea0e943abbac30c46b6ab1ae588c715ecea5805ee03167693fde5acc0ef22321627d282cd1ceb57790c68fccb57d0a8dbea006f2ba472a0ab5d9ebe3eff21195d6ab7444e623c6a96cd9da5db976db569b21e7516edb2a5d2a0ad54e8755ba105ab75b492acf7680f69211c4c3fdc2b5ab691b77c08fb867996f3f29db23c21474788f20d33f40a35d0fcc693b955a2aabeccf0853f63c680864faa5d513c3e17c3e7a9d2ca9068c11590af3694d2c2afa2a1b2bd8da9e7258ef787bba084eee4f2b1e506356a6cf0776a11519c1a9fbd214d981dff8bfa3951bb9d63f14b972992c4a4c9baa33f43b2a3092cdc35cb65dfd697b5f605f1958c1fa001204bd41216ea28b72f8589d54ce6154e70a6481b0a93076aae29741b0b7d8396a3d82a4451ef34e2f35f49ad9caf5f546d2cf9cc5a8d0af5594ba8dd405edef4456abb7f534367153e8827a4094bd5530043bd5eccae51be53565f9d0d3ab19afa6dc46e32179fb5b89c1b7bb7c0b9abf559dc16468cf4cd066c69e72190d6570b368cc65d515f79a7d26af4af3c736de24344efc0ed650d0b32287af3a65a1b456525802c1cf9dbf27f7202c4fe03848d087a2f15e176fda6c02c2d4b1bde2c4ecd9829f31364db839e812ee35581fab446ee07883916806994045eda24771c5ebfa43568512fcef0e39b3cd57d535b0b161181702b1703a14ccdcd36d1caa5ebcb6f15f05a74c694ee58788a2ea2c2aafebe6b1e5e64cb8e5587493b27eae3c645ef5a220f837e5fdd19698a596f4f22eaecb9b44eab2993ff5417742df522907c6a29d5e7dcc58930760ba6620a0f2b10bbaf8cb882757d5f39e4b6d4208997ddcf9f2dd0fafb02ed325579f025d662d62d5582639edd45777c0c5b2e5633a899740b50e56296972f6653e20d7365c89490c6be223691de575cdd506cc8973500fa67a89a43b91760370583a9eae5c560ddac8122bf4214bd6ca2d33525aee4dae8a27f5ae5624d30979611e80732b8c46245a8cad8427c1b365952de9324074901f27c597e2c2406042b317c1a1bc26007116402710572e103321888dd2a2a664479a8168690f50cf8494aa23a7fcac39b4ec4affb48f0cd3103a7e3d2f995b75e5a3a11b240e466eeb90b8ba8a800de2a279d0d59b8785cbf5639e7bc300fb8ac37bb7632472e3d457eb1d135840fae6a60800fbcf67c393578f6a8b10b3c4af2a959ebb449eaccb5aeb5370da777293c19f3fedf9c4cc5570e29e7048d49b01e862dffae96c9d994ced52bb5381581dbe3e7f3ac35435e1b2c49a8cae17975dc69969d601765d0dc0823af0d51b5db0acea54866a4392dbfdfbf80f7628e8659a4a63f6f5c47a23b8f276cf17f5c4e9b81626aaf37e306aca94de7abc4e8a3da85848e5dbfb6194367048642aeb43baa2836ed947d205a091117b81f3e476398deab16833deb4b6f3df84417fd3119a08dcb88470b0ddc8286f7ce17f5b0051fe2fb306e315e48c5af6f74474fa68e2e7668a79a9578ec4c67a611c8615488370b3d23c2702458dd4ff005a65b4fc37c4277c95ec0c878305cf9b2c4b0dd13cd493f3aeaffb70aba44e6054047f15165fd67176fc14409f4fae8b8ec3e4dd1ff224e9e1821b463a50c519e3c07588c224fbf705eabd63ca509a1c80b7144579a2fce4117bb7f95b444bb667ca5c593e7081e3c437045644de8ab6cb3144df8cf3f005d082786e5773712b8b15f8f8eaeb060033474c0a585cee921481d21ec63cd047bf9cc05714d54eb4f73c2726a7157b385f95122f1ebdbde3d668acfd8b5762d4e1afa738a85e61e4eeff9cccb44b7d0b2f09c033c5bb0ffabf4a0e806c830aa0bd8be17b9cc053dd86ca7975842e985f3b6c41282bcbc84c38ee6102882c0752980f16b93a5cde54822a8bdb1beb10a96beef437542918a0e9088662eebae50e4845882ce19e4e00cb89c5a8861eb7a957ed45a0b140565ab91cdf04f453459f75bb7fdd71b26374f2252e34f5dcb501002a7da1376afc1ec8c838a4b741fc212bb4085f4037050c8d0402ddd7b8c46cac2e56f53414a9bf5a59232793bcee8107c462c6ded846e3eaabddc1adce65959852c559e3d21c4419712ba55a02c369caafc53168b3cd0b331cdf3652b14304e14607b5ec4c3f9bbf7f98732a47509fd4dbd1d67df4f3fbdc4ece0206f0234e31eefaf4dc8e60ad398d0c1c8468562469775341dc4038e5dd895eb2cc8e2a0d6837234ae498207306e07d2e135a627c16622116ce2986654fc9a52ff05de427eb63a9c8d1f2b271102d028f552eb2374f9f1aecb6c86615f493c986dbead489f6056c48539a13c2b142465387f78b3aaa26891948f22001a831fe15b2833ae7283faac1393d417235ff2e95e862dc8d84207fb3e8a7945275ec5849f10c3fea139dd1690e1bb5cabf133f5166be34536c7d64937334f29980aaea7d007c3db95ac3ab41da854a276f63d6eea50d7872c99c5e43ab659764f45692e7624a704dc4a6d8b086eb9490cc5d45d90bc73f22e9b2116d9b1066cf2b9f7ec0da7b49a10865bf4130e88afa0ef2a2055c41301350ff6a7490c6a868d8840b38a62f5a062ca6b0491c35e4799c4e39822adcdb07678b1c34e4d8a941e1d3d59a270644e461a5b53dc9dcc1870b57b30ed92b74428b6bb1425f2be37e45835adc507cc13d5e1ab1006a282b9d5220d22b2d5481aa7a65cf30a69b924004782aea5ef4c535ff5e2a938b0d7e6ae605e887e64a3c5b1f45660c0bc7123a4dc61cb349f1403d935e2f988ecfb55b4914aa6b72415a1a0bd2bfbf8c70943209ac741b0160e47f2ba90219363cbe597b5dc8646b54edd8175ed3972c454205827f7bed59e9bc30c2dddbb5f317222764658baf92845afc94f37035be396f666ae296a258f52c373f19272a4a5153341078c27deb402a4aee08075e350914c9224c0fa083d1167267a6731d7ef14bd9a3df0c6e87fdc89218cbe74aa1fd370787ddfb9cece07107b87ee4eae49ffca5919535c5571b9e973f48b70a915e395cbdcf7392a173e2474ea28a33e5b97d16946c972a939e8aaea6e96761170fb19b3d0de877db194fc4354200b1d92eae5758e29b78d89f9e5e7a7c9d8afe54007345a1bd24af4496765e0d0b37d91a2888b702363d161099b32d9e7068aa8c749ff603b05e91ad3237440ce46b3243034a9cb7b3f77e9438495757ca3647710bdd36bfcad11473f3e7f58be0719b1b9053f7582954d9a8a4f8611b19e92feaccb702a53598b8f31bb2cf7963a1cc4df8375f5b80e8cdd7afa8d44ed27fd61438b2516dc48eb9c65635f5246f59e88b1569caee67cee362ba39273276d85da021e8a0dd99fbb03eabe4865f13cfd880a79d5dacf0d21cbe0d0ada22fb9bc4518139cc6520ad2f2491232e1a37db80b1f10ffc7b22d7b0dd4ec8909ff47ad884ee9d0fbb45021b3612b85473032cadad230b0284ed19d3db0be753fdd71b56011c87eff547d63244d7cc36231f4e48c3b76dbec9e092ede4f5817175b1d76f259f70947daf66a77ddf444c3ccc8152d2c295b098809ceff6b700d8cd85e0c139bbf68f02163642ddb08ff4c2a57bab819fd15792562767d66350584c0ab47c53004f54f91e3cb0e7b40936c2fbb211f729aebf9caeb04ab37aaf0e6fbf019514877e94261b929c341345669587fac30bb4255aad9dfe0f01773545a15392c536c5370d08ff729e6d3693b028ac0e343dfdb95c61099e0db90e3eac07e089ebbb795ddb3768797ddf768020c74fdf524effcd13ddcb53cd3d4f04701a35fa40f92975a4604147504af4232760b34298881e7958f09dad8bf13911fb77a541d325e006e67b261c96f3a47996388b9705e5eafcbb3ce34745863d49d0cb2c061ba9bd0b0403fef3c5317ec6750df25757bd1c3c763c0630303af4b98d80e6ca92c841737478ad832b050279b9c3fe977e2717c2b9803efa862f8604cfc3f48cc76f5e4303577ef04b25ec041285300baa7829ea3fb4c9c0a627cad08d2585b82ebc982cb0dccac25554c40f87a964f4fcf4bd465156ddcb51fc6a0b8b00050fd85bd4ed2b58870172f034a2a26905a8e0d88c30cde653a992768de414c05e1fbe232689717d888c8b7b4d04a7a63864a934fdf0ecfd606c2d2d50ae67d7be8ad484c810523c810db76db506fb27b71a16e44746ff775d87aeef926d38fa37e00a428ec81078bb83804c4f0678048eae5224b55e0068fb3ef85772b3d7aad0fb73fd69c685f8904fa2fee016e5e7c87c1b6d4bef89308532d18999415064565e9e8fc2d8be2af5a029e62526520192b036577fabc18f07ce82e6d29bb7c802dba5d2d9f4d32cc6f3566135aea079d24072c42fecbe2eb4eeb4ea4a5001670a628147f6f872195c55237fb679ce76edd2797de5dd0bda5942a7829209ce2f9c6de69bb5144bb93349de5ab2cdcb8592a2d5463f059d01f00278169ca7d48698cedb91b250796b87f5a5e652bbf1d896b710de9b50a6066c28ec0800f1d63d83d11e5f036c702e78220263bb800229061e76eb253a4946162a27860aacffa6bf92792be532f6a9d68822c4e038465a5a1e8d9a858e6db88d40cdbedfbdaed40e877f74674dfaf6c89a7afd474a8a606a91fd39277bd8c6ef583baf041dd5f1aa8c97c25ce339190c41915a009c9a16ba783d62f971737e48ef7d6b111c82bb92fbc00581a31141ddced818202fd12e3a930516545f4aa2abf753dca314b1d02527daf0d1acf568ed3f1248dda1b5a8c62fb24e79e8b82c8fb24c6b4890982ed3af8589495867f2bf1a706a1f13c8552b1a750b83929c36af67f84f0d1c0affd7c0e595968d6df8d2320922bda8c1a9857543df386d6606b044915c2cd9fbdd17a57819c87da9c9ce278602be7afa0d56ad32456d6d6c2263d621c9c139ea8dd606bb7a5a3168b09a8e97d54af5a10d31b4835c95fb0b020987c0dfda7d2a6512c757f8ac8a0d5e43021fa6182534b2ae14e4f5209bea2a11ddbcdab04ffd1be5956980e7e4a560545684790df4e1f9074de605a23f7667d6fbf1d50bc5adb0877a4e7b9c0d0029af5dde03a28ae0c82f6fa8a9385e9ae3827d67c099ca3746f7411b03411caf222fb4b803fd25d3c87db39865309dd35bdebbc00a1f05fd71a5d18d142e738c0c5578743c0c32d02d6bcc1a7c754f602964e45bf4a59848173e4b947d8a59042744ad12d777c2b5cd6a0ad5eedb65da09042ce16b458075b6193c8fe365a3f5c4af76a58fca075b7fcb30d87c90f185e4d20f96579631fb1b2d38ba634f7cacdf3b3eaf67f701aa47b3582cb2f80c1ce7e00179113db311efecc575c8c12378bc13776d0f736512c39aa9783d373b3de83144372f79a482b1f04e1e63d67e0f38d3faff7e0ba047b498b8683a8dda91ac450bdf2fd5d5a0fe374f6e90ebd02ecae1743135d0ba353ba6f2488fdec95f7cc8c37e9643acc1dae07b4b17db027ad725dc9edb1615df4f563a8e5db6aae5e0ece61913d3685ea1684c8ce971598f185408aa13f9d1dfe3be931dc79be17127d40867268ad607aed970b4bbfa39371dd034293528e6593b7e8872e21d43cee3f19d13d1bd8b38046f19e1ed9e6fe261e60af251321d2d98e2a268509ecfeac835dab8ca83c5d989a68a4f1117f25298dbae649a18f368fb70d5258c38059429180320e369b6cec9941c2ce9ff40b9a28946ab8dbd4fc1805681afd157947451a9a8937fddbac8653be707db4bf19fa8c144c9a15138f9bcf6f1fc8ca66fd09a74c8bb513a40316bb072f148963701ab169d6c9957ec85692c4aea1000dd31e70133540c6f1efd082b6ea251e48c3d2399c9261b10e262f348d6564e755c0aeaa53e9074ac2ffa13bac0649028b03f3f39a8625a343dc4040f1959cb9016eb6d33bc40b7727cbf8694ce0f7adf170e6ef5967c9ce41ec75479ba187931d3831800310a3022d64bb7584e57b7b117830fe6ca03610aa5a98fadc59cf700433b8c3887ac4c6274f52cdda6da1382897cd6351c0b8d8a260f25ed5fb1bff3e75cb42c4485c2f5e379b8da6d2d6e834e4e9c10dfca06983dfddbfbfcc8ecd477951579815cdca9b03d1b148c2bdea816ca405862fc76d9cf1b47e3f54f7f12ed6623633148ad33b238d65fd5d1ffe48b519d2de0ad16f18feff58ef3644c78c9f025472fec6fb578447769187e22520f1fed809b1b54697982ad3d91773c85d7e95992b64d5acbe27ba12c234c162ea391804c6ffe14c2de510fae65bc0128eb0b690f240af786ca2726b8628a7c4a3cc18504bcf95a0b61a5df8b4dd52465309366e9b7ff8a54c5a7870e522eb9ea3a98db69563222068def994e9d0161178003f718c022b94532e86dda6a2189d798554d35ca1fb8cb591c56829e6a181f22806471b74152e30c70ee9eb9f64a4d6f6b2aac3fd25412d2927c0e05a10d65ad917d7e621cd99bae3a75b9716b92e17c446963dfc10e433a2cda6b727b64acac2663137b00d59d8a86526120117bd7de91231e53d9dab956367dce1d890a69f3a58f133a8161e2cc761c7e49cd3b0ce6f70ad33346529102be4c5a75b0f53dbe66ae287508c1ff5fd3bb8348fa6b2cd93ec013b36452138d466467b6212345b3aefe3dd634e3dcf8b88cbdc2d88cb58c3a9937bf985f32290496915d5547e510e65b5a37e3d9f7f15ea602dfa3889544b8bf376ae61c2f07053484eed422cd3ae884e5ffc47e905eb78b997b2ab955ea33fa93ce0afb5373bc821ce19e25ea99ff1daab0e11df3f477c37f252d22d9c5815c402943be387000e4c409b5427c8789131c87cc0ec902f415726618f781c4b238ccff26feeb40c38b8cac2e253cd83596b5e22ad63a05e861ff7580dea74849926eef5747ee1da8ad41e709380069f53d3100381bfc213343e43db760167e44989f468771a44a08e3aa3e8ecf2f033d4b043e3a536babd86d5980a4f70de6ff13fee1d5c41db21fc053f3d76a42bc429111fdb82d7bc43c7c75a70af9a44f4be62849898936a37618a441da7803ddc4338544f4d56117a60a3905d909c45cb7246373e4e0a11dd3a65c867701a0203e919af9664a9e749ad70f57cca2419ea4a807a3e33083836cc935d7f288b09a53ed9705429589d1dfb9fc80fdcf0a5619d7bdf961703d8cec7ec0533cc2cf22c3a30386b9e322ce2ba7a1a8bd5f1f49dab4c86cd44433ffcc26b0d00ce7f46f5d1e5e4260d6e06c3438d7153b8876e102ddfd2aae99b8eb67813b0df27271489e2ad4addb0a9cfbca5ffd572204ab3baa20c1747e042c53d03a383c070ba958f1e4fd2cdcec75341710efc41dbc3ffa14caac836b03fb04c66d606afa64279cea5d583cf22921e51f8356d11dfd27668fc6673beaa1cb24b73ea0dc27de3c1112deb5f9489c98207674cb0cd88b47d99ae28d28d15ebd6da43dbf84ce1ca1145dfca82b1f347174c345a310573f075820cd80a8a4a0eb4e7fbacabd12a16dcdfad4e2cfce6a4338159bd24eef96a0bf31cb2d7eaf5ba63c063ef1793839569d522c6049cfb756bc6cdf82778f84748b46aeb5f5174b8459d01ff091d4592d2579bb3d52eb3aa236419bddc1ad19916b96ae415ed48e0631b885128d73ad7e2dc0fba369373da84525af6c0a324cee285452a6f77b77e8aa777466c485aaad60e675d81768f5bcca93bd53f9da789248b9dc1a091440c06654cc3b6e9363da6130d10c4bd18f2b540bb962dc39610344535bd6427a5303118029a096577fa60ec57f26b395247f0bbadcb1f07453cf4f13e2280547e9cfd3bb9908d5991f87222ea42dd822da4b95e26f5b84821309460a6662f82851167fb3d920ee01d546d83cf3b7491091fb18cb948fea8a279c6c6ba55c107bdd41c69483d466a7e0d72d4ea88095d6e2ccf46a18f73a160d7b88ca4446afd5e88aec5b7edc5400ead898d1c024d4525ddc13324cc4ad40024f42d832fa377e4a58c0db256b5591c43bc625cc8485a5f77fe862a091c790408941f60fd7509c705bb289042fc8380d8145eb6a185e33f74509142e5dd6f01db4163dbef823dcb2b6e080a51a0dc36538ff17877ad2bbb77bf1f81c303e97c15a014c9da576eb918ac09dae3cc34725e881e0f14c95d0a4c610ad5ba03e59da3eee07fe6f1039a81de879c979454acb1e427cad1a012497b9562167c76986c8c84b14089aa66f192613d2a3ade0596c52230034236fa054fe7c2704dc45b5cf041c2d1359124f8b2c1617b46a526f37b6148c4e4b102f0dd25525b6324032e963b3a73d00be07b1ff8250c21fbf25a8efaaa161399d437b27f2ce12c67988f42d51e9486637d5a2d7a1aa714fcea1cfb32c210e83c3a9a9235d95264a58a64be9219777905b199dff4864a5d2b48392384eace41b29230d99bc571b3b62c29af02d1c16679e364f0c8d21e62e53a554f4188824578f87c20c92a63e9c6a77199fcc3b2a6dffc1a17c5653827c7e86be99eb96cbf32cc7a89b49efe29e26b58b53e0c12cff6220ece447cbaac920eefe93b3204f519ac636664084605f6a6cb1c3a0ea1bf3b8dc78b6a02ce4bfe7e0ca95f96a104d199304f66a8299ab24b905bc4d580a256ef191eba25ec5ccc4bcc9279712dbbb3f76d2178c9d231d069136ea641296afd069ecee03683221bdd85bbf3199794fb5f6be54cb9834d40e58c4355a936e08c87295e8db09b413d6944f1724ffc2183116c06ecc6c2a10da996247d9a78cc8266320e1fe4d8e13774615be2a3e6993cd44d9a0e99236d4bc2918f53509f88ec550ecd78a534c97aa069d3fad9e37986f4451f697e0bb0a8dc00c05387311cc6221adcb698b8ad1285a96f7e46e7377ee1e3f4d43fd0664eb77925f2d12b10ff42748ac53bda7da26d56d52d800ed4d4f449644da917d6a7b5ea87d9b033682c040f930773718570a98d4fe6c1693c31ca6cc58d2176913525a96bfcc0ba8be2393f1ddf22367723eb39b6f5bb2df9bd41170cff99c493138ce9a6d8f982c559e6a47f7de8eeb3d0f9655616c35c3d5371962a090df57cd0fa4aa761d6903cb91419c4f42512d670213dab563c451fe32835741f8ac5f71a0624ac62748d5ed41bb548e77a18f0710d695bc47450a1b874c46679bd075dbe5c57b13f30ebe2d0a68a3576b6e51c1a3926eb6057704af20ac0a6a1be33baa6806756e6ff88b853c58f405c404f0bf36bb05ad9a2847f29b97dd3267a80e9ae813aec42c9ac1fff6d468470295b506ba5cc5ae7bd70a52b73104bd782e14a430e15480e3220cc496305cef79c980ecb25cd2a27e4b24088ac63dc0f5eea02c7abdafff3cca10204f209b6577c2b7f643a3e90be5c891a37f116285d5728002ea8029689d87318be5b68402ec80845b5eef691379b6a9b24a10c6c978967e054adb6f4b265fa93f3e9b95f4399f83f4fe5954cfc460d0f63fdb35969b9599dbb2becec7448710682a7fd7f1688fde05057f9f474edd1e6a45aec16ed1943d3b45a2ec03504af1cf12ec4264400198ae7a256d3dac098d5b44cd38f0add65cac3336fac4d1b9e381badecc19dec652f177fa300d4e3fe1454528f1d78330d4d5f5503e80b0776063e1f50729461b83e63904620824f7bd6b5fb88bcc91a1d2fcdc3366852c864665897faf86aaa2fc31a99ecf7b7345d33f3891f560e19ef426dff389d1f97772ab409809c1c83a8c909ccb4d1cf546e70447a01a4ee37fa6189b94989164472462bf5c7c8885c52dd4384e5028d9a82cc901c89aa770095e15b4ec3527c533911d4fb145134bd962ea0318afbb5b026cf0f8739b1427691da997acc8fc15c834bd27a9ecf65b1b68b502ac1c2231f17b015790225936d90814f32a6dd7688876e992ebf656274752faf44832fcb5dc1cf4c05b3f41440f7acb68305063b32edb28c736726045cbb6325bd2e9c25076b1765a9f49c8912a75ca97f7d8285ef2c6df4d0542044968ac4c2da0d9552192af91d83b127e8060a6c987493b1f4680fe9341c4037b6b32ea33b636ecd8dd3503f071dfb516ed2055b5e592955c0a4841bb647dc61c1676be08c8f75900dbe1b53c993f3063b9d7919f21a56e7d2b977b0384e99b6cd946e03c2f08d5632b74dc6ae62566e2673b4bca0245d51f5e601682896ca954c834239e54443cae9971c493a94c4196d2346ee3a0bd040f668e5e49e943e924854c7b9d1dbd2208ca252badc4c394c84c276b28c3970cd99ddc9f0084502b15e1bbaff56707659c10db613f0391b65e33ba13c26c85ae3ae8f03e11b8185f126ae053e723671c5ee4ee8aa0f90a1cae00f01fd15839b6f95ce2e5cf9b627fe42041fbb976c7f04ab5f82e4eb0c378f559c5d57ff4e80e206b503fd88e04ac22824c686ec0dba2e933b191fa14020de6b43f7df2a8e2e2b7183b2d5b2b1fd6f668aed87695869471b57fa8334569ac38d15f6b8b92bc94a265460dbb573f415e4ed032af3ce965a20181ea5033d9acde470a13059648294f547a6e8ae580f6d8cd2cb48845e92b3385094645a8948ccb06fe0d102a9acb732d90397473a1930848510a016c9a10d324fdff46c658d5c140c3a8823961049c8de7b6f29a5943225198c0921090109398eee676844e5287fb088e786979be40f3e069a64f99f975b42dc5f90b867738c26e08006dd35a5efcc175c2e43232a3ef9b3ad0cb118c20e41364600d26c88b9fd3785036e0b1d496cb9011015a024888087ecdf120192cdcd52128951823bda1f7ea96fe6bba18347f6a2ec53b6647fd510d9ffa111126040a310c820fbdb2411348567b20028c7d782b2bd4289a81631370ec6bd8885c9f1498d1ecc1b5e5cf85144815b9072e14b16d09d712fda50c1c540930c9f0bd2d18c35313beec5ef4ecb86dc8bdd123fd94facc986202b7ef69363673b5298bab812673e992a891412f79b637a72fc6cc75d33ee15616222869423769423260624aa2184dbff65431f06e6b16cc8e62b7d3425528ad7681fb78f3fb94c2ff3cbdd7c8a4bf127cee3acf85bd762382bbed6f5f01b2d5ed362a2f09a0e93c56bfa8bb36ada8bb3aa784d73f1a258838314c3a5189761bcc6f4f1e517afb91f7ff29c3ebe048a35a88f3f7ddc35c56b643ea63ebe1c8a35323ebe0c8a35333efe277d34e953147f4637c486c88a9f8a2fd3f516671175385d0f4556ec5a8ab3e29bba9ee2acf8a5aeab382b3ed7f515ff0ed62f572a927b114cfee618950ed7c6145745e57eac9963222bbe9d63628e19dc99a111152436a0ad89f58d8a0d221b88384eacb9f488fbc1239c58f3f4c66957465819e1faf76feeb27805656b520c93c04c57b5ca3db7780342a55a41a90a324283e2064c88f112822d5510010210c42001842e437c49e28819f48483810a2a86a04188a1392acd913f9bcf6b1dd1041921c4e0a8aa7e2608323008725299608fe8a28702210a45d92106587811e28a992300b18322f430040852d0022e062ad80ef8db2e43a323a4c8598646476451691e5bca2863f4e812045a92a4947206910a7f5785a143d8337c9ca6551df67cc88517797eca06105cffdee9b62de892b0ddfa3560f86b58355e35c5abfeece16be21c4d47c3abc638db6b0f5f4d362deb1ad369f25acd5aed63af43356fe8d176aa4adde31747b9be5663c86754ab4701e6a80f13005fa8df823b60ae5f1a0377402295177707508b0140e8825c1fc26e46d54213d7561eeeaabd4a00fdf939f4275ec99cf92bb97d0ef7db4a3e075f8e734c2bf91cce7dd3c357939706bb5664d5377536f5b7fadd1157e216a8a83f74b11a4377cbb03322bdd31ec3ab20d9633f43f618869de35bd259c39ffc1b3a63a69c754922d69932ec9a49a403d00e8fed9a4aa403d24e969d272ffbb76b4c443b20ed70d991f2b2af6a57f3ec0065fb332d03a6d132f8d7af7087fc5aeb9b8ea8d0e894d27697a14f8f98a3605903c8f03b58f33fe3bfe441fb68eeee54cf5cb3e6ee32b9bbfb4bd261e4ef9497c87e4967e09463db9dbf556757458f51da1c713ca9683e991d1b0d15cd386584de320c9741be54a188a932028451060863945ef731aa50c4fc2fc618e34c01843046995467d22a65a553c21db336cc41730812b3a451f6c3ee49e5a4b7093a618e1cc4f309598a2811ed51ce496985453ac85e531b0673543b6924a40f5b06fb10e6982f3dc7873433fa9c9f69dd32ccc722d113a932b435443a07dc616b0da14b89b40c18cce125fb57eec754818898e36b1adca22ac6f7a21767384137aa3d518360c4511423ac28aa1fb928795168d053654c142b7ec8aa146d518682c0a81c6951847aec0882b2284a00518192b0285084a023b0519c00319500a344d2852246082022283e0842044750b47802e403258b1e2a3d50acf0814ad0b49fd20124d2b4b82730b25ced0b0f2ed5010f182e581260b6f48029b2110212be89975f441732b48c8c50c109cca645fe5234c8df4c1140c89326cff9f3439e3f5ff2d32844d90631c6bf5be4f8aa229a2022042f776411128eae0e7a4b49d1c116430c653722224a56b940026721ca163990b202c7a2411aad0613f7f6091e37189fbe72568d715e37ded2deee886b4311ebff41a4031019e25e6c98d449163e843ea49cee6a896589002855401c307f160150a4802c8965eb47d020cdf7af17dca0cb5fcafb448334df492857ae0613b70613b766c8c4c532acc1c4b53598b826ee29e763f32029b70bdc016f90ebfb4fad379ed0bc1b36aa5ccffe867b9f75369edcd975762120abd660e2cad460e2cea8c1c43da1061357cb7006ec6fb8c7cde05c11b7a5b8eb739e9e5cbf725fdf9fb8abf4f59da7cb8ebbb4d5fcd33779ad26fef92814ea7564fdd216d44b4897be7c9311b5bf7edfafdf49b1267eadef4240e91a872c1fb8c3f43b76c000430b2d609c420a1f2a6779fe97e5cf7d7ec46cc231b70fc4511fc8bdfaa8ce7d22ab7e2928d7dfbafad77f72fdcf725bfb11f3094a5cec391f91551f5371bf1e62ed70b5779fa8d5774e48f3b8571ffbc6f04a95e119f7eaab9ec3381a7ac7bdfaaba771af7e2de1cf72f8b31bfeae863f55e68361ac7fbf06249155ff947d915873fafacee5a0fe621d2cd8ebc847610ce7dc3f619df81717892cfbf56ffc9095ccac6466ac7329cdfd88d962b7f56fbcdb72ebdb5abf0530d76bfc8a8d9c84b81eb0f6686c3bac125239a78c31c6585dca6e6cad4a25a58430bb3e6859967387c54ef0e3d3e0f6cbf8b4d66ae5bf94766298ccb2a8699b675c3b845e4b5e196794f1ffb3ef3fcb4ada13dad70ebd87ccab200d719452cee979dac83499e24cbbebb256b7eebe23209105bdc7d75ff78dcf3dff7e3a5f03744e8a69a463430d808cbd256f689de9373f6a73f6f0fa59c62aad5362d99cda5c21db00c0ec708e5df7c11f31c35f05f10c71bf20432a72e715b8d81eb22b8dcdb5d8142d2d84508b0bc6282595534a08b718218c31c6f835e0a6c211b60610422db048859fdb1f1bc20dd6e0a87adf8d96ad58490c972293d49152c7c405915d141515cda028c6a2188b6691945372994151174545453328e284f01d13964548e85ad44a08514a4e43c9501d1cc6344f89eb9d9d7ed23dddf3b37156dae74a0705c9a4e61224476c9031a3a3a431620874399eb0f500926fe0566e880c3901aafac6b76c8888303fead237aef2c1ddb83bc3a9542d2b8fc16d0737ddb15a7a826b6aa2b5e56a55a8954b43e0734d191a4109c2055078786209da977bcad0488820685f5c9ba191103ca852ae96a191103890428823218a84000a632f512ba2705313db1f5200c48c218e543f280145c6077a4ef8018a10299f31337ee0e189cc932019b675041f94bd76bb4324a55a2dfb05caa965d3d26113658bb360a651b8380b6699eb830d82b84f76503e5cf1c444c4d0c987277c4a3bd707267ee0a004997ca0f2648302a6e4c310406849dc1844643f106d627ec08010d27a0002101688a3ac871a48a93e45986dc9a0c7de4b840f6581102d1b9b0f10d12582b0f70ad185f610e5a765632325888e3962ce19534a8ae7040271c8b78dd93a63c428a5ffd1f8f2e50bb49ed24a1b23ad31c6183b463b2d9c73ce15a4b8fd3cbdcd1a4d5ad1a88cb26a34c82cb14c398b56b111c620cbef39e77c207007f6934529a52ad036ee69b80ececfba15a0275bc8f05703b6b142960ea00fa05b6818f6daa02945cca41ac4f323871044ad8031440403088c20bf56b8903284232b4551c0e86245e827a98b16410063899a0cb100c38a1783c411e120bb05ea2027b2fbf021b44739a90eb8c3b940b805422d1066456eb5d28b2cefb20cc9f5a2b5f74ee8cd23d09b17898d1bf4a4c541fe50f1cae2558eb59f7536b2e47f164b7cadf10c0d2fdf91a63f3343e9fc1c3be331ccb733331ad6d6fa4724b0acdb3c069c4c9f7b72bfcdb2b2b7c26cd9b225ed8eb4727cac5ffd722e6eee5a05e95ee560186565af762bd8c8b6d65ab3ac7a0c14431f510e4183345f3ff62fd9f50bf5db6b7000b76ed106b59d5e436ae9389d4ea8d7704e9d357c81566e6c04f5a687dc0fd49b5e43c5c6a8d4cb4ee6b51beda7e7fddf6badf636eeb53e7067e0816f4a3f45c3b0875c8e0c5ee5c88fac89539fc23a2955644d14842a20292cdadb129058b3392b6eaf75b6bbfbf15375953cb59f280db59d50a7d30bd55ddacaa7bf9887bb4e7f429d7e8542694c489a737e0f41232b405328cf28f29c4579a2b4930dee9aaa233309cce974fa19643ec9ae7f3c86f93819f5d9f79f7e7e675bd73feecdc8f93875571fd51d69cd1f77ad82b4767672f632bb6a27671c0a7f4d32eabbfb5adc93fbf5cf76faf9da8995bd53b7c28d9f3a1b79eb5276e644a383f1f0012c2e7831e93c4005062ff9cef938c5a0e1cfa23aec1bbe28f7a35ea095336ca4fea9bfa27e43fa3ca3741a558031c66842c6be7bfb1b4761f802adfce1e40d1bd11ef5e164143ed2caf6d47d2d6bef55a9fef479f934df0484eb8ffa29f37de8a6875e7217f6cdf94061adfeed3e9bb73795ba4f95b7e7363c5f3bd2ca98fdd47bb126856d64c9e0cb5ae2b62ad6c497ef4d4a2e830570879225496af6ef0c1d7f3a8a800172c45df6e3db40c409a4ec39be72e03cdc2575bcdb4e89ec3c5f7674351fbef0e47e57466bef6555b91d45d0c4509ec9d0a889295933c1ef32703f9ba5c7c0115be218e7c3243537fe66f7dcced0a8892fb91fde15dccf1a35d1f9ae84402313e2254d78c90e8d9ad8e25646256849aa96a436f1244ae0422326a6dcc61205962bd93f2f89524a2e48bf941c0dfdd363b7ac75ee4773eed1bc85f661e9748aa7533cbde9b1d39b3ecbbe3386598b751f663130404d8231d976966cadb5dd25dbf692ad7d196be4cb47b7f6dbe9b1eea4c2432e890f1affa3f3cacb529e96fa1e776118fbecbd87e37cf84e7b0942d294c680ac07b286e1a0f15a76e365bc4c966553fb58f815344dab618090b28d5dc55d3a3a5b1eaafd82680452a6645b6d0a5d671d5d4f71cf6671af0a18482ec57fbc8a07f9152fd9be0b65b1ef43b10662f6c875af05e56216abdcb35feeb764e699b75f07cdbc5dbd7d1a2a7c36ff5fabfbcfc3ffbd8ae6bf3b24b2eca3f033dc0174fccc4f71d78c0b2d3ce492f8a0f13fb69faf09e0b5efeebb21e6d6f76f39feca55b224e6171e86d75ebe2000fcc120ff05254b6236b2fdfc2435b7f097036f2e6025416cc63e88cdf26547e3bb7bf72c06683c86695ce860c6817d707fe3bfc4b54eb2e5c9dc6b4fe3b3c734ec6f3cea531f00ac3be16f74aaf71df7a1a56e74331eeb240eb2ef685d67e771572a1580163ae7f11df72cf63caf45d14343eed97cc56671cf3e8438dcb3d0767dc53d0b71d8875c907bf6b14e3ef62cbcf7abff3ac86b165e76ab962c484faef0903b00868db0f036afc0c2416ca6c142e661cfc32ce02435d3f815fec64fd8afda8bbb3edfc1ba947b5850ac815e08d96fa12cf63b8a18dece6cbfb7d855b6d0880444d9facb7e4bccbeb52bbc7de7715767fbfec45d76876cbfb91966dedcb3bf02be21661a4362cd7516f636f06769f07701803f15f6187f8f7d873feff1d7c2be06ee92edd3e854e8ac7bd8cf749b7bd84bcec7ead4a5d0c11c43173b25d23e0af655dd0af52bec67bccd33fe84197815c466ee5742a411d4db1c1ff532f00af5728bbcfad13985bf19604e5233f637c48ce12f3eeaa5972cb9c8327885c2496ae65e76c9528b1c391f9874af84a17bf071dc355fa5ba1746fbac2a37fef733c4bf21660ecb94bbb0b7afda1e72da2ff11c64fb811320c8d8bb7342b61f386144c6320c3b0e6fc1031aa499f10fb353b79a39328fc23aa997f9d9e5c83f611d192f3f85a4dec1d19386afcc69184426cd7e48ac815f7c8ee0e02e996915a14ce996e98a529f4c1fcb66cbe6a70f99d239e774cda7df0388a6699fe12ceb9bd8dc8fd2cfc8d5105f06ce300cc364f02ae7f4a8476d1c0dda6718723f4aa94ec69f3a999fd1a59eb3363ac67d66448528dbc7b82f616f039f0c4b18c39ae37ec44da63b7daa936132994cda09cb07b5641cf7280d2fd23dd363bf3d8ebbba4fd2a03d864ddc8f12e42aae21be8c97d1a564b8b71d8d7b942b59eb91a3a1542a955ac3b2191d7c9d34f9a2ef99328ecb389389e3b8bf711af7b6bb44fe4d6d290ee2efc896b16fec4b9f659ebbd4256192b3cff2ed9274cebe39cef4d5d441d9a15e86e3380e857ad489e338bce21ee6205d26d3a15e76a72f52c46bfd70b3ff601722ee515ac30cf9278f81be44e1558e8ccc118ecc30769a1c0da60deb8a10e98630718d5460fe673871118fcee7de54eab8d738ae542a954a1808d7ddb847bf64fa2ceb4a2f653af83275df129fd1e5202387d4c7d7b8ce732f637fea749abc4e9f65f82bbdc984bf259eb12f7de50e90612b3dff423df796a3817bd4e9b3bf8959f619b672fa538785e3b0e71efd1b2f7543dc853d7d22eeca20577ac871251db27d5fe242dc664ab85f2bd3d7e12e687fa3dab66134eed12c3bf87a5a837c190fb99cd4c75f31e1ba98fcd75df5293744fe09af7264a05ec60cbcca49a5bec9abc38265d90fd192873c0d2f5eb63da7fdf6da10770d71d72a486b997eaa63825dc1050f5d5e5834ec6272f6a86e95831ae231d0477d9397c9877ef6a76e95a32333c45d329dce56050b1636783179a331b4bca0c7f0f9979c7d34325d972009431cf1f3ba89a80ebeec6bbda12cb6a70602c0914a755f9b72ce988424202123255e903fc8c5084a04adf20793a01833ca88002a479005bb5824c882190154c04016cc9f0a08c41104b2fcb5c8fe01eecd57e169ccd73480c45d5cd350fa7eba0407b8831352fabe617bed6fa20add4c6785e6571d740f854e8954752774df36a3fb545946a7a4a6ba259d65700ff7e6e34cd4295e7c136b68f0941d949f557dd6da4c916a380b4910ca34fa8624d6c878babdf630662fa36b185fa6fba1b6270a2d999ee409f5a697df48b4568c6489d65dbdf8477ffd1a1b09bd91455fe5c58791691232fd8e90beb5f766cd4dddfd5396244d6e51d2a639b25b6aa628d2cf6056bffe9c3750f79eee9ff00d9d51f8ebafd8c895528699b3fa29c6d3431df8bb53507868481b82435483b17d7c6ca0f1084d5e25e9dc7f83ccf5939872c55fc43dfa1c0df52fbea173e3259d2b9e807bd4e7a90dee51bac3fdbc53d751d07f95eac621f7e8b36c70efd79f2fbf46e2c9949e30ad987e876931ee925fc140775d2c1b4955e5fa944ce97f3ab01f7f92297d0d066db78b3ab45a21c783e77e12c90931f2d7434344994a16640a8d9c1043db6eb165a6f629fdd83526d2534687b4eb37851cc77d6322eed1b75b3d951e1a9d004cfe7a88529844e9d752327d8a24b2a8d528353d4d29696a37aaa98a609d84d48538a71103edfb0c33ec81c01d9eb53fa27d1058a37a085559785a644dd31e5a4d4cd6c4c8da8dc3ee4ed025c330191a0985c95a732d3f995b561d33b64f38edcb6c31d4ea296524d4257f3659fbc9c35d9af640b44d4b6933db75427b07e29ef6d0ddb601dc45b17c20eeb256d31ed268d848efd02aa8c45ed37c6bee00b4bf1e23db3132f69506fab633653a83294b9cc494fbfb89e81fe1bc2a77ffe813cb8738ba376be48698ad68807e0a5946865c4eefecc864c8e540a2172a47911d43c7d03358d033fd5dc447605176fc9d85f360815888c98655843d652bffc62376413ee51bf70821e72fbbe8317601022ab4392bfea41de3d3b88b00f323ac3523eac26e2da5ec606b5a51c16aafb47fe37425a446f66f6cc461fe1caf827cb6ffd9e2cfa6e5366fffb34f71abeb74f8db3762b10d6eddb8d1d261e32e8aa34dcbbd9863a6d6d2da7257679aca6ee15108608cdbb641f11ae33bf6a19d619c1525ec31714c4fd7afee6d46305f8f99ac7e9b1b8be12e982b52140262857b2040b8879048bb34352dd5a7cab06aa705c4c311d05191de891049a5ba77bedb80deb40f5979be3320f7bbc43410c79cef4031d2e8fd8e437ff0e5b50e4877e3c4fdecd66ab9c38d072dc397ec9d95c7d0595f367094a3d0845107c2d82ee83901195df1e16c0f279f287c8c96c8020805464b68e17c087ee7fea80a93446db55f6bad56aeab60e5ce19e28c0edc6ffa14f5c7eaeeee5ea103cd1fb8a33f6260c2cc2e5e0471c4b873f4c2bc82f542c742a13ba1809d9e382b4e1fbf02b2628f7b518e7197755177d5d9e32e2ef24886915fa4971cffcee0eec82eaf550d580e2bec79705f1ec51a2f82acf8d6caa31ca3b8227b8c562e37a304b7c88b44e0400ee4400ee44091d5e39e946c2726cd1b71d8714a29a510d2a949f1e9ee0ea7ff207d716f060fb7815a06a4f8c56ba214b82552e91aa741864a01b700831f459f0894fdc85df18abbe01781f214f7da7b9c75c583dc2743ffc910c877b4745296dc499b11341892b8f061f576f88682608be0c22c8cf093b1976f273d8a44d1bdfc45a28f18aeff2bb83ca8dcf692edd78e2ff36ca4c8f2ef8b046323493c5f6b307047e7249d9421c4f1b517d9bfbfd080bd440203774021d84bac93dd0d9d6d131acb0517d3200d0ab96fff4c865b9453fefcae9b7b040002b3c4aa9edbcfffaecbd9e5208b2574c9420962d89eec592c8127fbe7402fac8c436b8bebd342c01d504a4ff3e4ce6f64fac9f9324ffc31691e1c6bef55a9e2518e221b500519197e4b070e28030ecce1352dcc6ef83b6293210ce242a8f1f8c0fdba07764fb79af807969d81c0dc2477cf344013bce27c405f490c5b94f2c854c76c8f13ceef9e070f17be4b4fb6842e6969152443fc31c91d810bb340c24ede91611647d072a3ff5b792b888548f79c0794ebabfe6ed5ef65fa72d558889729f6b2ec96482532fb432b3df695edd063bcb2c737a21fb98c2df75bd5c7425ebed779acfe8d0b53a6e5989ec33a58b4d7e1de84350de3f4906c9f9df6b1567bf950c31f14a33d9452d3b477cda45deda4697fba54669c2538e8b84b7bf913f09afbf273bce654837af9a8cec29b5873f1859035a591ec29d59e7ead75dbb69f01e60dc70f49fefca97dec6fbc6b92b32e07a18c59fa3751526cc5f4d7a3941213615ea3180915e5ec3f834947287ca70fcbfd0d6b6c220bfbd6deb577ef6e758b7bfa5decf4d9d8c01d9eb127e22e98b1b7c15df1b11f00f658c4b088610f21866112cbba1bee6198863df7b0fecfc6266296c3d8853172337cb7f6dd5996411a6c06416b0f5ccfd0c804423410ba4378adad74ca083dec21570386e11cb0dfb0edbd6fc8d5e0afad8132ee6bc0b0ed31bc8a58c4197284fdf65f13190159fd22282ac10972ffd078e2fe4fac59c5fef69bc8eaff82a87f2a6e2a1dfffcf060bfd13441dbba9563ddcadd71cef626ac63faed7532cd94659dbfb4de4cee3960c9293df6397038fbecb72e8752f62b8973dc0a1c380982091f42e0e5b5cad91efb0daf245692035f483c25246561841d2821042a5ed863f0cb8bc33a364456ff865959c3a3177c61ffc1312f0d2aa05fd8ab5a155930671d7cf1d02f2c38d84324ebd7055aa7c5fd92183e6374d611f7bb2af8407878f817962873c45f13dcc3e14f77c37e221b433708a1ec502b753aed440ba03cf162d256600045d0cbf45ca7d3420f2f2633827899deca9ddcfceb836b8aff9e0fcdfe3c4ea882fdf62b9bb7b791a82747557c75f7d67518f7fcb1ae93bc22adfda60530976268d3473a79899b70cfbfee8d9b32dc3e3eeda3fdca7ee78fa9eb9ecdc411734ae21b3992ca115f2095bbb111fc580fa40cbd7c6cc45c21cdb5a239a7c322222f33c9c8043a9890be706254822f2a4c87d562363a2c80799efdaf2a15fc6e26c1f5fee23a1c7fde8d268246416332342a410f2bff53060271f4ecb93d3f7a8c31c618638c31c224249d43c8852d3647ee8adf5bdc253ffeca0497477b2af6636388b4b8d7337aaeefecb40c91488bd72c71567f7fdd81ae81a159fd598642a59002c62db4d082a16df2d7caadced15fefb40f34c18d9dd778ce6ad9d01cf980522d56fbb3e994bfc291a4b26b0d2d2831e39e50af79d997d0dc1fa57bb7fb54e242bc5a59711d7ff7c6d075c105175c70c105175c70c105177680e1445df0770e9732c7af128725eee938ab65480273f83f710c7c46622dfc205e85c23d21811880403a8aed1db2c32564d6e2ff167a6e8c3516b352eb3a638e12533b1ddb4208450c71b30c8d8880b052887a8876b8900116dda738caeef0ba47055164418b80298a301e3343a329ac5822295811a63062882b2343a32978b41e5c99a1d1143b0890628c4c86462c6041964510437a509112114abba3bbeb71971389114adaf285a8884b17243061c6788f509628babbbbdb470b8d488c50d2962f44455cba2081093366c85d1fed11ca12c50cc2c1832875c3de99f75a3a6c6eb048a465121111f970219fe6c675bb59a47eb8c3610371b9021494a587888ab674c9b09ff669293da57df2431c0dd4551aa8813a49cb110e0e8e9d3407e7286748ce5115347087dbf4b474f0f81bd5ae84941e664c6a1c9ef45e9c61a27b1fc36ed70348dff8945c23c16b99a60db9a9192bffef8d1eefe9b0b90162009c213745e3debdf7d27834ff566871e7f3a428149fc42a7127fec4a078250e6598189e94e34edc893c7127eec49db8138f2c1531c6687160641d41204c8916dce1407e6e7a18c0dd55feeeb522cb06e2c8c139c201c2a0f0b137445ad64282834d4f4b070f57fdbdb10698c00d909c21456c38820407bbf570cf6d0f203d886e7cb02737ee82f006ead868a04da9debbd1b29130051a8dbbdc2249699f23cd53c4061cfa49ffb8be0ec2c921028b6e580b9172ea86bd33efb574d8dc1499409122dbddac15da022471302dc3340dbbe961007777c7699e1cf7e051ce909c239c2584e00e1a70024d2eeefaa60fa669f38a960904873acf707dd225c308411c7002e58d06da94eabd1b2d1b2c5691ee4d202069254caaa23526678f7d5c69af69453a7064d30308ce10225a86794fd36a0cc3b0f8d0dd55f68d609ffd87fd96e154cb5bd84fc05d9147ce0e924d0f2038438814b1018b61628c313a67a3b5b2e9702fdbc7f72d4a1d31dae888b86575d0822cd97efd5a315b31ac3a123e60305b81b4bad65a57cd43892ce923864cc00624eeea19d0a80557b27fefb8ab27d674a5328c534a69e62d9aa76fa4befdaf06a91a942705e85005e2e88757dc83996a3f678b6a3cfc4bc3586a7d5b63adf8dd53c11db0d62139ee398e7b9ec53d98290be298c91d51d09286d84dd84563e4ce1536709891b8f127eef82b21463e23af9278c6563146bb8cf1657c8ae194585ed15c9a561a9a4a051df26136d1038d134c821ee20d90a229d9dddddd83706b86464543e40f12dd54372a92344e246664c515333234b2624ac632342a7292a12062915ae207405488c00318d0a03502275fc4a841115584c183e843f68759a693317ac42842d2109e24c105da261f30c2d110493c71842614e1070df80289158401c1159f2f70c08424ae502103268c008a11ed9202072de8c207598ca9220a0a7e2840051228b8628c183b2f8063f020063180220b9e1d2bb0caead67da60663c638e119421364a0c3eb536d2c38028c116334c18a15bcfce1154fb2d3ecb688eceeb6d229a3ca480aa1a61fe04288cc03114a0c51832e8e0045092329aee4cfd0688b30b600c2cce265ff6c89c82e032a54d005142f08038957932b4de820cc0e55bcc862042f7f95cd90f35627194521d4d8cae6e0dcf01a1e47ea11263b10429e0e1b286090fd6f80b86b4676a328bc64ff21b1c65ffe5662aa9b6a657f2cf7c9887cec3f29318823fbaa59f93008863df7dcd2ee2f4ba043b0e2043d2f880427c62892e145182e5ef199c8d0c2ca0e2f39f3c58b492a88978ec458fa23c6e207d060acd1915266b0a5e8a5c304ce000b1308bde4eb3061e10736f879c5d761a24aeac9e2259f8956448517af5883e8a5c344c6102f89b1f83391217a458ca51f3e136f1cad87fa4ea494928993262fa5940f696aadf5850f6281236badb5d65a6bad9562085fa8554a29a594924a29a59452d25a6badb5d6596badb5d62a6badb5d65a9f498db5d65a6bad9276d7651761acd188d0fa5d7e779d020a3e5cf8f761730a80afe9a73fe1a4f00ea9d769f24abd46b91f497a8c4c3f498f41b95f957eb57d7c137ef756252cc4cba52f61faf439bcda80b847538d934aa5b013993f6518a69d95fb3217f7907a274c9c34f9d3e97452cd4f412c4ea9542a954aa552a9542a8545e22db93f8555545cff88757a38e1e58449ea743a9d4ea7d349063be1c015521401050fbe4042e825f3a877c2c44906c0b8e04a184854418223bc4ecf24859ddc542a954aa552cf83cd2b859d9cdefd653a94ffa9eb2ef92d8106f10d31001a8c3552b6ffd0a4bbfaa5bb7c157110ffc68066c497c4ec7815a41ddf10b311f84dba5b3768703febd2bcc94e8edf648abc9aafe426c7863856130b218091f8107690c6d3c8fe340a204bd95fc92d65ff528dfc35c93ebb1e237bf731d121fb4e6ef8f1261a81ab88851020fb2b814419e2551002647f028c91bda575b2a23fa9bb326471b9fdf63f1bb31a35b2c5496a64fb5a7673924eca36492365db3274cbe03a681f4767694ad3060fd0619fc90ce3381aa6ed0a90212764fee7798602648b93142076e6519630e0f9069a6d8542b4e88c9427cd774c685e4ba2e9b0686fd25e6a1accfd7133bd508ecc0226cb2019341fc9fc25538c3c352459f6524af944ca1a658f7c9204d658697aad93575c0ac9229b4dd806d7b9b837df8f7e86c01db0a6214bfb8941314e3c1a1277997efe12994f827f3e127f0b937075c813ffd73de429a73665fec64d5f391f49847cd6381fd8772731fca3bf6edc7d9d3513a6714f7b2d6e5bfb164b10e2d0beb56e0c9225eecd67e1e0664ffff3a33886d330b4a7eddb61c7923d5df778f294f12183c74431dcf533fde8684e3f32e1d27750a94d12ab818452ce47f75a9b249605c9a1a8ba32c8069954585cecfb769bbe6dee9737ce838a69622f391fdde3b40cd9cf5700dc217ffe02a0abd2fc67b38c9b65a82a64f5cbf8da4588d5c8fd364ec8fd349de7cf98fcb4cf4c32d502c00600ba935967247b259db16f5bdb643299f00da67f23a64ffd8d678fe127dde3554e903d3d793e003a27726fbe8dceb5386bbe56ed140ce8e7274806b90b7f0dcdcf9744b2481eb92b8bd422b7cc28f2c46da70c823bae4821d3df20737f12536e3cf332dff886cea64f05cd9ff13aee92cd83240988bb4cf8cbdef4f37b689811e81ebec243871b6be2188ca5509e4191359f05c55dbd0a4fe3e3fbcbee71978fbb68fcfcfed1992d25979ee787e979e870b111d32fe92cf346e4949f5813c7641b6c99e72f19c3c3bd99e1ceb3b8379fa6f3a1c89aaafffca8793a8ea13f6b8691b837fbff53f8d523598283bbfee7eb409b51b8283c8428749dbc3291cc2415f7580605a2c0a8142d3765412b15a2111100000002e314002020100a0744229148341ee89132fb14000b839840725a9bcac32447511c841031c81040082186100344466a884800031aacf0d5d739f9fcbd14924a56f631046ea8a5e3fa9c22763b5c90a02edd4e786d3efdf95fc828c0af6a32ff02223cbe7ebd216eb8f23083ad3cb6bc4956b1326309f510fc9b5adc2e40e6426f7185fa9c1c7679add2fda25affb855f283e1ba02d0d4f95b44a06ce4188c6887b1c37956bdab508d5bcf75b7d152370839da51e3ac95db48566dbc3918d735032b92053175b47f52004659d8c23c2df1859f3dd15876c9a87a51789d866c0c60068a208aa4815054f182afd58b35de20399d5f9443b5a152b00f896f46e73833169b6e12c1ac48fc84b79a16a485c9d2a6155a1d120baf45ac96087f2b33735f178dc59ad86df98fb871c537a2ba6e36e33b6c7224a7b416a2a01b1125f00e8909a3849c9865c10c5941454f05c640a52680ad7f39af52191e940fb38b8d812bf0088579360082b07cdeec3377aac05808fc6e4c39f55d4bcf9343497ae636043d4490a4b32309098296ba4a748cb6d72e3c450976fda83e1cec50377735856ab64a0dc6a7be1ef3e5cc2062961ff6f0b06bbcfa32bc45c0281de0066b29ca1d7a17be7a178b1602a77db4a48bb75ad79aa495c8f0beab2d381d9293c889512da56f85d2c205731a0d68937f9384f2e0feceef5261d379096603375f9f4b515b84e0ed82e84bd9421c441bc5e1441cfc5c33141f958b714e1631b14199c6387bd96bd006800fcaf2f3e184f00e3dec38b9d9c2552f7f740b75093690bff5bdae5a2818789f5c80425c58b6e5034bf08306671df7c1f8c7581ee90696ffbb6655308f619a1e679299fc33afea08628d4e82052e256662829ed6febf2b6f6c52f4b8526d14d88cadcca8b62cb977ca75a478e0158f294769262995f6fee3179da1009b34eb51df62468efc9713da65bee239fd12cb105e1cfd4a7dbb8d98177dad4378be147b04f42c6f7434831e573c33afe331f7ff7a3056fc98467e184ebc254166925bf175c9a8b55b72b82e2d4ffd07695f9786cdb0b77de2a61c3434770b7ee1f1455688ce3c784b12355b04191d5de47fa13e0c00c2c4733040f1a6ee8b1e96bebba3bcc1bc48bbbf26cca946e9744e0575e0c50ffac3e049d4928cb7a37aa018b16e1d8f67698101694a85dd91b816466c658af64ff8dab9325fa12fb510c8c25655376eb968f3e9b31f961954e80b04121ea6873f914925bc1b33c243664e50184611f90e3dc217615f07dde084b1c04ed72ba845efeb631e3a34588e1eca217f18bcb2b43aa654ef6e8387debfed9006096e3d7976c3b1c00c419c2706c19c37e4958254c6686005e2dc9d0e1629839f8e863f876e09be2c38712740c32638b6a669e83d1f0457aa00d535bb754bee89dadd07a782c7199b528060bce485fb66fde52b4044913dc85473eda78814f7f19db6fe204043734d7969cec61220df17fba9c3994e968031443f478018c7a9f630e05a47f47ad10aec5ba278eb45c1df56c48461556fcadc9f0e80ae19d0b7cbfbfd286e6266af80a6718b68dfc83ad78c3254a74bc26cd7f8ec900e06514fd7a4c4b1d3ab17e3e356c8b44b3d8783ad27d4dbd518136794354faf79e006a66301e192d2a09279300ad3fcb540b15b345562a55bd1a0c5eb62f4864eca05799df1e5cbde52416c40a0156cff90be3ebaf4d3279e4a6f033aad4bd583316e27ab4686d336f2a58822e600d53817e61d2fb8aed9c11576f5b79c88bd71fddc688da7862cbf6886d6c7db8ffb2bb48c8da6e0d8005ba0430a6b21853a9b0bd9fd41137ae6bef2d93297b8a309e573c4733d2d467bd1a0cf04199fb855c60628a90c1e0e0aaa8cce001abeea86a2797055772bc8c597e6a9df4e125aad253e07ac8f814795de6772674ccf1b3d234ba9f1865fec358cc0a5b362d47652ee674ed5a01193425618d348479231a20b69a212f3731e7ada34595ad4e2f61414bf34d3ef23cc7d27f64f017d312c73532418ee7fdca39d6e3bec73337d127c760f141755e2a93d8b9d6393e9b066b53d8d77e6cb483a1cb72e7934dfc3144954140e9a31a1c8cadc40af4508dab3888da66ffbb6ab3781a9880618600bd0c727cf0c95ec5af34e8e2b6ba0a4878589738176cb33caefcc29a0a59e7354023584a594311b30e8d41f42f6a6a7c30d3c400f3226107fcdcb53603e97c538017518e54805fcedcf8fa051a189929c6631c79049f25824c7b0a2fa1ed6d61ccdf8b81539ce48f21e6138eabbb4172dabab51f6df013c5a168db0687f0fca33918463966871469727ae837286dcfcc87c04c67225d6959601b9e3bf01bcb53b71f0aa9f90fd24423ddd123c11c9be557ac4a90b7f1de2486441184b1de9857e04cc7db562f1cf53792402026c9b1986d15bda1a217b5a31bb92889517abd2c4fccd0fade9bf7b8dc0b813f94750fb25cf0c1d9a83067a68fdfc53cfd8f3d8bb8269647adfa822bc1ff1232e8c5efd4572f16b53466d7a0a09aed125f085b18ac29e463da9f3df77f807dd6c5fb207b6a549244576b2a2b209e6c717f6f4c345fac3c7fc82383ec826d73835275b403a21e28edc93ede92afe5e8f202b16539075c9c420806a3aeeac7250174cae26aa05cab640b24b6db10ef7287fed50d2478095929697eba1a9a116109d4bec9cd0c9d4c2db3c38f17c13033564d11e13111862eff1d035268d582de491f68625f8a17c760a3e96340d25442b3c182d7367f335c1c162ba67b550c2b45e7f3e14f2c8b5cbeb50a1d3f11923afe0c0fac7b596c39a52f64671eaa53ad17aa3addf58805f4a91c2227adc0b23375c117d7c340141a468ee049200326d2fadc8bf0cfc873b748a29d9d23763c5bab22aca3d53245f45fd350087d63cef5efe8512e7152ffc5c6771b7092e9a165b4ce47270e69ed4fa5426b6a2d16d4e029eb338667dbac52c344295f66f955c2051698234f3302e5d1545d515254b2b9529402876a6c09afd703089acb3d4bcb091d9ae3d8231826fb277b88d9a78b1667e3257e17691e0ca67e4b71a29c813f750479b083f7730eb54908b19b156e69c01444864105e186458363edf187a6caeea4d10c456fe3c6318869b47381681df190fba287aa0110c997a49908c71610a011120563e2e6ff8c508a8ea37d181adca052ba1a93f497453555cf4eec6563035963429d1658b99c888188ac9ec1e81381f2b085f52e419c0ea617003234e9f06abaaf1d39dbd57031f227692e093031ec5d1889a5f5b38c4f1f51ac1f366288b2e5cbcbf2ab42737909e4872838af1d490dbd5aacfdfae6ee012dceea0910cb2203a3d7fcb4f5f645e85c83627fba56c270a335b34974c08f660e55cdc4db07b57a23a2d63c17f79c0c262b79cc3a14d26411cb775a2d54187de7a048f94cfa30644f7ed829b29c66f8cc4201edc50d82445bb9a918a00b09f0b5168e500a9042e4d8ae62d1bd34cfb6e2c5a1910f615032406e5b8ad1747260dcca0ce436b185be4041e280d4f6d1200a4d06c526b54b3aadb42862850704b5a87552d913e9ad7a2fb209d02d52828f0eb0bc036f338c706a1caaec10fba37c6f9699fdcee47163331b39d586cfdcdbf2fca20ad74ec4d86b28df7e5d17cf9084f6abc15de52c831a10238250b74c0d4f583549af93d1df88f92265247c1e5c2a40cf5a4aa49b359af7fc453044a2afb2b8786d11bb937572c6fe46fc1afc4790f68595b76ae9eb1a71eecc60ec0a834114895191a9e8ef9cc24dc714210e2490a58c157872c8c308b6a5715c8ed8820bbff8d6350176dcb04d3f1247442a0fd41620487cbf2a9fb3033dc0e14a4215c6f4516ed118c4a65f1ab06ef9a7e6148031a41c5c26a490213bebbcd43555249d7b6d76e0f2798d67c3e455f801d961c196f0a958aaefcea6db962151cb2b96733d4265b67ed1e74385838ddb069da6813cef186ebb449fd04fd71851d114c19ba2253ad9a612003a65d772e9fbe9f23d176bfda3c370e21c77d9960b8c6e413451525b0ba9e4a2465023624ca95ca7165c1ac7a8ed0cb2b79da620ce60c91b961fbf1024d0eb2d6b3ffc96bc3d8edcaf1ae1a5a5954d07c5d02d5cff74673df6fc21c5e0ad2e52c66e3c8f7d81eeaab95ce560e40be196bedb3fca33761f8fcbc851b00bbb15c6db8febb128b5a42936198801aa8faa0e9e866754e5b88afe5ff443ab0be2bf376e405b112b3d941ab6d3e7603101623c04f9f5c6f9dccf1e399c3891008a0106f2a0ffc97ae71414a072aa96c26fda4043b86ba6b38798d5516114cfcd168fb414483795ba2896c823ef89fc78b429cdf79144af284939079352b2e2863f4d820af778358d710dc9ddca2c3520c546cf42aef31d4a0eb0818865860476fd1341b0ecbcf4235d256bfb2292b0617256eb5de696b54a18226b4996237c2d57a938374a209c9b191ccca099de7438052cebce821c131385460ba27421c6d9605bae20a45e00cba2776c674cf6b76b1cfafd7191cf9bb07bd7b29783cf38d72433810b47b27cda0bd54e3f11117bd8718a1e0f3ee0130818ee4d78fc4a0339f676ab8c3be0af5e83fbe8b28660ae5f9cee000db6e070d32b285bfcf7b402ebe5f38dd08147d2b3ebe837e26c1d3edbea5320a5e3a51d083d70ea314b50ad9a82041f35684053b8feba20cfa335bfcd98b3283be7adb64025da9cbc160cbef202778f3c3bb79212ecd847deaf8bcf1f8899236a082e3ddd7b82779de5a94da0df12dc0e7bc1f307bb281460af8b21bae04c8627893aefba522af6790b3feb50b4d4f155ff30bcbecbeb2fcff2abf698cb09b22f19d918b058dfdaab8a823cc7fe6936fe2d4a04c6039b99add6c4d94fd6a246af4df30038e1da00aa081783446bcfef69be72a2020f55ca6837b442ae75ebf3a59b1bbdae9711166dba81ef6e45b7b48a094e56bfcbad80e84a16397051f29f21ef1591253ffdb1eba1ad17557f414fc98357c256e6175d8ea568c8c763e9ea7700aec9e5a718ddff4228b8091b9ce6791d6a2af0c1fc18fd7f82b43062d9327073a9a81a0c5d27d7a76a206de6f7530cc6e6ecf022ba405b73f40a4e145003cd9e4ed32563b13790cd28d4381b4acc82b3e90b32d5d3ee05a6112b7ce6e5e4c727bb22aaba41b0c72e7616109c20f6d2dd04833faa83d14b5af71c7a7ff435ffa9f7ad8cf85297f193be949cf589e4f5dc0e6a6f36418854a9ea5fc0a41310ec36e5083e1de5e18ecb8b10aae6e3243b0a5441d1e5391645d217a4c15306e4ae5496ac090a9b30293a013041ea49f099c430fcee57812f80508c9bd47f6f46c01e5042f7b9c7b4c7d1639871340831b429be30cf7fce2614f7bbabb731925f81688ad1264971f79a316381e4688747252a75620eb68663a20386d8ab601388048c2825d9c1fabcbccea6307ce2b19b2dde034362f20f9f7bb8055cd62f4023836e9367d2572787b8fc44437b3e1986b48b06f4287324a7bf4313843abbb060d96c3b121ea0855b4572466876f64a5797b4d3f3cf31b42c2bc03b938b4ed35b59bd5a8a23b7612094e4f1d666441d8d11f46a9c8d303d92d551a04e79efbfee7a58baa53b00586b79375f7f09bbdd4c5bb14e899ace2e3d902b30cca123e1290624463595234cf3c362c5841ac741989361cb693a2b6c3d898934cd36706e9d3ccd9b3ce73404984b4a831bee0a5f095e4e56c0224b5d2c3c98b5a5acb12bb2cbacbc11c4a0241c7dddba53a09e732c1758ce2a35dea4134b1856696f3aaa52e7acbd7cb404a2382c31f82fb2d19b8e5945b781228902672aaa5129228cc6d3a445232860fd80ffcfdf895db1c0946ca8e89c2501016793735638790c13517ec9be4aad436447298056c4e1642cba91c1e2fdea13e87835527c1aeb614ede34aa4fb2e8c6ead4fef91f947d9e5393ab6c1eca8914c12308c486a8be203d088954872811373b9cd8472fbc2c3cd27e234746218db7983f91c1232a01182eca3bd9fbd0b10f0494fa677cc0a4c1948dc59683c6c87cbd5fa3b3249d444af3d7c0584896e90a848cad628e2ddf5361b133c7a3eba1e1eaa1104987fb2c84bef1201c9dbe349d9c583f217ceae136c62fe8da72bea1fd96e5281a4ef97fc58f8ef99258c2c0dd5421872aadf7da92e344e441b31b9dc38e626558540cf770377c0dae6b8d1ce47b0c93e2c66e2c42cabaff80c9fe19f123912edb17c6a5f865988689dff9d02b7611d2f53523a8eb9a64c5d38e5f3c2578951f1113b989de2853a945ed6cdb188fd9fa58104785d80ec81703bc491aeefd4da159ced79110ebeae729b93cb7f8b804c01fe58062fd9eda9918901aff4e2cd0707a810dfa07efc45475647be267e633cbb8642463e55689ce3c7c897da07dcc0f4a178afd129c4587d57a734551138d37f2d7a407591e1319961dc06c8ce9dd673a101df790600d254b23c4b81361ce00be42793cddbee0aa38185d63bee874ec16731294dac338e07969ff053a6260212ee3a565ba1727ba6f388323d0205dc297da33671a831728a1e1c419256952812b81345c603a5f179145749a86bdfd138aaa99132697f7bab48b4b19b1d003622712866f81cec4c71fd3772e6c0eab033b1e3af6b8c09812167a1e5f51044eefe6e27350c63408baf2a9c86aaa6a4d61f0128c6030140a63dc3e889de7e430319c352eb7452b3212d9239753bc9589211d461418b61881fd70283d9cf6ff62f327aa11488ddd20ce18210fdc7beee8e7e8ff65149f7a327a084dfccc49f682d57d2bebf3a0211ee402a1528300596c62d40b6552f430cce454c3d90b3c8608718ea7fd63200db7192797c3a5183ce4fb163b012e1950e89057457ae2aad81e786a6f32d1a6697bd6f4d9755b7997e3e45b86491e6fdce60a5ccb7d1e1cdc7d52b6b21f0421ce0021b7a545fcac833e4b217796a26370559e7f11bb70467b84c8b624da78db51e2565817d214f6e009d47f30c31e8bf72a623f2fe755935f9cba7620da556e96de9fbb9278906a8154a692af9534b3a499fc8a2a9429ab531acd546bca2294f0c47c3f1c4c61c9a500b130bc642874c429e9ab14f9bbc286034300407d00f0388315bb905a73988a2155d253382c7e779f0b540954a1f1626cf286e45dde60147de499d00a41042eb20f583e4cbbe1bb05c07eefc685575692e781ec204115a2da2268bc1bd7934280815090c0a6ef0db73a44bb238b8fe9b0b3260de0c1afbb671d8e7cacd6a8cdbc0940f5a30fc71c0a9cd837473e8e1c54ba040eb8eb863aee3d591101dda76987b6533e95e00e27655986e082b6773ae25c8581d60dd1e3042f6242adcc453433ef5d930600164764a41eec607706fff292f69a09270fbf57fd7c07a313e9619ecdc0bb21e95496cd275be2e8a84876575222db98e628a1ae0c5ec8056ab2a7c6476bfa6b1f99fb9486a8780efb262c1851f30eb23e8272ea47ca0d4681038cc651304582075a225b3913462a04632bc51f6b03a03f034d1a5413693f878344549006977d39d381f325b4e04afc3d8dab0e509aa75bfafb91d79b5d1481b222e285dd00fc0da438b987916c53ab693ef0796656a14c117d231f2b2ac32b3577906c7a2abca466dd08f2b195268f5b0a583c0378a99530573761f14de85b282748c8fb29283ab8bdf082ef83231f73978e3c5dff144726689f26ec171e0df3b28b84da7d5effb2f635839122a706e36ee1b30d8aba8e8212b1e9adb689d3f41ef1be947d78b0fbfce6fa3dde122e5a0a5eef00ea1dc591848f0655623d67cd5e5e99aaa03253fcf4f3c74de621cc2f849f7fe5da5d7aeb5dcc1fcc931bec0ff9006e91ff8eaa134905e2504f66ee9f97ce84b9c6b1376e29ffedf626949c9bf79401a38fb68abb370fb23958a313813131101745ca4bdf344ab7df7a638bc41423d5d7b86dcd8ea71b7b1ba1a9834ff91f2648c8e94f73edb866edd46bc4c7ab80c7ad95a1fc222f8ed6a199412a5959fe6de7968d2221e2b2a496f2ed01169153467f48edfca0a04fde9c12e792cdda0a8538e8178168f505bbd4c6c7fd93651901a6facf610ea956dcb6e373d099c9064cc89027f62a40e15e150c013357d224f240fc717f19491b641f56a1cc34d77d4343692b50d6c609aac031be8d9e6395b9b9f0457f7ad2d61d61c0b896f03f667dbd2f4b98c59baf03272171a8f4346e1bed193873b2a1d5a5272680cfa66857f2a934a607a2ee4c3a0dc790a4b5d7e73b01430d62bc75a6fc0e1c0c1ff09efa48d3529b4b089072875e88ee1d8cdeea96d7ad99a4d0d4b36e74be7fae3ee493b3a1097400b36679332ca1bd8742c3700acc945cb0962de4fae334feff7858702e1bbac7ba608396dc946ee61333a8deba1693cdd4a270201e0036c2d45da7269ea4216847bebedd9f60fdb2592160e6ec5f24961783596e0beb22f7010df381e34b03d5dfc39900d23073a2b509a7f99e492bf2c783e52204c9ca557fb8cc0e98f4a9c385f294629654e4569ece12189a678083a5dd3d24b3c5c3bdeff2ffa55ced1ed25cd954dae11bc37a01fa251641031c9b5b1bb21241979aef87bbfac239003f390d9997c14d8ba470911a1d99f06cfb60bdb632c729f3d79a839c84113017d197ad69154ac2184c2f93612c698f3564e031db719a6e5fea7c4ab4d238dab7235515a550a3b048dc3f996bce6e78f59277ded9a6ef0af715db0d5bccccbf67250b1975b4ab861a2d3bbe85aff87d135bc46f6d03ae7e4b313bd7ccfcabfb8ad1ceaa1a1c1be062e16c5b9293e2322b812cfc8e261f2eab294015254b384be12ef05e6545902cd7243e8a20b6325afe2cf1d578e71d62a9c691d3f62f655c5ad09dacd944c135f3cd27eccacaa9247db3d78835d0635b495a1e8359bfc5427e73222ea465c6d223f88bdedfcf2ebe2637af9898e9a1056251c65110e41a8ab8a6a818b4bffcd34abc655352e9331aa60e243b04ea0255a19db044d0e3ec74871bfbfef6afe40748428d7f94898b788f6ec82d9743820f86d38a38d084ef201e46c74e849811c876de555613075a51185914c4337b02ce81deabf44093a3790af912807057d377d6500f437868aa55d9130da23b8bab0e8624bc800b8eefae41d8f32821e07d0930367a3a70d218dcce55210282da01029e3ec15bf24c67cc6dc938de9fea6a21fd1c8cf47b916453b8bfaf0784f0348c4f2643fd6fdd586a4329354949e4516369d0c035629f302d987fc0365edb40bd64ac41d5d438a09ecf01f7497924edd12671e4c5b7077e40b97f89ab2275136645cab0a03b53e94328dca30d09e9a6753cf3d6bc39a3419894144a095a75620f8b53f8c80206ea6f09a999240c17dcb401e3fefbb76c73b6050810c87aa94d0f90fe5797e6dee5ba0904d659021532ddf5a3eb54f612e329c8becc62086bc8b350e87b075dc0a12bffbd1116cb30dc2f780d13a5f3a3a41444f9c46654e2790ae9126453858b602984a007e7efb30ab10c714a80a31c29b309cb018211294b69e0c7a16ead8c1b4e56612693a6cd7b6be98ae41dd409eb45e813f5f3d1440aaf1d80635ade2b0fa5026fda5f43947cd707526cf9f9efb08049936a610085d4e39b210b80e65cadd83a4a4cd6f0496fda19fc28dacb6abe3f3262204b338d32e27a51c42d9836e126c8c03e747881db53d351941cffc4df27e9c39cb67f56ebe91884100114b64e171ec2425de48cb30233e74d7564384921a7d64018ef7336810d44bedd7e159b49f4e568bd5f70d66fe4a3a951fa471a30f2cd3aecf715e6d228c729f2c3a0335bd3d68770a52b5ae954723e64e9deaadfdb0ed527afaba516894967a21e7c0f23ec095a215e4704057d383e897aac69210f8b586bb8a9431efc7773eeb8091431b12270629b5779722334d75f95a22fbe9f958b1c1b530aaaf491604d89ca00bebc722bd1733edf3712f51ba01b97197a2b48e8c62d3b6895852ed5e6edd1d0ed9d9a88995446cc06f0de9de03bcd5df3406a45807e2065605c3cf22a14b1457845ccb055de269a61852c07bc8bb267846a78cde558b5191992e0f0f6b9a471a26ff6e73108a174d3c3c5e020f001e888109b8cc2db315f4462ce388c85efb8cfbc6954c2c0b8f8f48628d77a2284615c263db3cb3bb656fe01171406c8246012193ca8b32082a6aaef0aec87adaa1d2f43bdf3ea43a4c24d5258fea705224702567756ddfe2b9afdd4f13362a3741fbe0a83d0a86586eea76fe9cdefbba0373c3e360affc2be04b72c004aab2ef075ad0875d2b5283292c5495880c1bb13b13611a66ad2b02deef77d5c8007620069249902b2814edab4c130a53105b295bf79b6e23a41c5ac617e90456dc69190ac113c67962e89b518a97c5b05bcc5eefc6130cfe65af303aaf30f74c74b327a270418cc699b3a3bcba68fa9fb7604f6f80e1c435dfa1527df580359039422d2bd8c3e613d7042cd4478601159977e8d0e943d563129a9fb5c86614d2a72cbe8c72aa3bba5ea5798ebb8dddc2e368b5a062e810dd571529f6fd6331aaecf6f23b8fb6e03e4b8d0ee99383e41a249801530d4c28efc5a35ed8e7d0292d467441706cef7c7a365554d5180e44016245155ef7226891c67375a32fc97c3d27df14d7e38e8aaaac7aacdcefdf434c9e01987b99f352dd8d44749b01ec4777f9e1f7f2d0b6326dbd73493a0e81941401ab423b71affee63d933f8d9e55295dfd526eb463821586ce5a0f55a47951644812fb5c7f25c201030d546aa4501b2ef632aca3902dc782d1838d6e19f1229c47dbedfdba512e34233d8642da4b3892e193d6056e03c8e19c395dd37a6c1d924d7bc69f088de661e1aeec25ea705344b89d5afc7c3f8650d8c2d28db43ced6c92fc83c07128096cf986a5768687ada8c76ead378564bd5387ed3dc2ccbb0f9d15373600968e892b903320da3a2a2b5139ed35a788edccdce0e6f33e2e77de6c921f4645a29cf60566050d6a775bfdf4f5e47dc785f1cac5e72158fe1c0c499d6a1a97834ddddb7fdb822487fd2dab252dd138d8b0994812d9886727de3d4b32c197304e597b7a243decc5ac759b9752afb42c9d7efeec5c25eff2a034636be4aafae896babb4fead4da5226ca40a29ae0d84beafcfbb336108a82f95b9aca1ff1efba00a17c52b361f09922ecc388c222aedcd41d03584845f7a014b394068646ed0690f17dce2cb4afed57527b6ba066a99760dc8ddad8da73c3e422be3560f297dc58c01bd217ae101795a53bbee5f29cb532bf1670eb87f02bf2aff8422c6869ebc6d845167814018c704387340cc97803570d03b5c7558b4c300c4163995bded53ce33afca44dcae6acd4dff1900e7d03cfb65a7c5b39cdd086adf3a8ec996ac376b399f78fc6c435b1754ffac16d4bc15da3ad57a4c12cf95eca996bfc6ce045a9083edf7b86cdbe040380e2b2ea548fa1703babf3ffa55ecdb3e778b55fbd70b763fe6c6ea310e9b4e806d43874efc20c11da9bd1fa01fdccf5980d051321f2ce1ee3b0df5f2a2ec27cc70958cd1625b70b694ac4f1d5a37b67053e0f30974eee66174028ebf43cb1045bbedb486f64d264dd1ebfc950c31e47c55ddfb3d44c87f34c2b669a99643f169fbf65ca079d55c8faae32e37e75dcc8e1b0c517a9765a45574f5acb854bb0e15cd845f606d580a275a7d5966410590100abe4bf974b1348c47a8a1b90842a2728a546da8e23d4637f75d08fa76c83fa59b6820baaf8bb00eb5d7451160fcee6b76721cd9f518c0f6370c7125358a9d8490fb453733ec26225dc5f0a389314150a5f536ae150557cd1a072a2857c80d9d79629a66d70f8c858a24924da042bfba3f6af8835eecb9f0d36f6e84e1a6d02cb0b34a4d8c4da29a0f2ba00e07d589f82f505e1506252b968dc279edcadc51387c93082674dffc2824d6402cfec21579c0d2e83adb1cdf61ef5b1c133772fdc9735b2c2b6609d4ec1037b393c073b26b741cde7c7f622c33ffe43c99d2df69c397f39592b7edefdb762c916778276a5aca98a9fdbcae94d9c11ef9c8b7ae0dc6644e589104328e2c4c96b65f85a6d5ce758dc0c7097a35ac842e81ab9be07f1eabe1f81348165ce861a92dbaf9fae248c8a62212f7f57e3a5bf54e3e7c1cc3c99317092b7e0f190710dcd2c580686f250ad61659eda436ad016254bca2ec15910691777470acb49ef75e46e0255a171af45b97c16b3aea6c8149dcdd04c31ed46118da98e6a38798f72393420231e084e4c924e25494fbacf9d1a327d526d53775334f9e5c17a035e84f3e38cd48557e700808018cdffea5ed4b515335813ccc73937da6daf888d1cb3b73c7d137bebae064e3cbe4d0c7fbf7d4e7f933bbe2e99c64b39f3bf3cfbae4ef24c76fed2bb02e60c270102a883e20ceaa54496b0941452aa283457e96b5458f117966759a206cba605bd90648f3e2420d86ec29a7201e081c0146931c03c310a3b8b84d6321b0b839d958f6c1c8051db7aa144133040a7c9782b146bfedd0bd01f31376f4c1a0474016f2151925cf38a89ad2478c6200ea9526e9f4ed26d1b5a7bf2a242a08b240ce91b8197cda2ee3c0a0ae23a2176ff0800877ff70384c5cf8822f8959736d40f6ce323ae3419b911aae896c15b143437eb2cdb4c1c1d4148c836634e7012b986675b080dd80618cdf61cf88eaa353854ba36d0379f906dcd298aac9f8f9ce1587c624499d72b5e7fcb996624e4dc548869d055a4f56546042cec04299e8d4298d909d7df438e3235d16ccb6150a3771cdce36b03ceadff59d8f80c708426102d0ca23cae81090429605513c446d4e623b522d8afe788f613cfab61c21743b9d02560697803ea1437a585ef22c580f047ce195d1fd543765bae341b72468b0a6adcd95e0e048a553bbd6c6b7380a5f6cf0297ca6bef1c0f12bd5413c5327aef9481e530feedcc1f946517a315ed17456fa2dd39a6b37a0053c88b621865afb41d47452d8fa0425c6092c08a83ace0a48d4947f628b961b8740fd9ebd31799ca40d2396ca0f86ba8e1a06190fb9e8469aa8f2e2b69282299c6480ba124df9d8652af17625ac1dfb7e544e79fdefc57eb0edb7d84a5d73ce0d0053c19e79c6adbe900d744d118a2c11f7bd419fb828b16810a8f6d8e1dca65a155c2b434f5e939cb7587503b562b8404eb695fe2a1e233770677933a400c6ef6586c60997e545b058d6028a06a3e17eba648b10a40ff55809ef3f938819156bf7d4bcfec0b27f45c437fa23b563b5b9a2cc011c653abe2017414deaeed6ac8ed03488e25543a93a7c7e7ffbd75169f7e73929ce58e8bc648c7792375144290478e9b0d0965bb8df146fcd20d807ab06a9239c992a4d5600af24490b1617a01b8b030008f460189013d35070d952e20efeaae58de3a6f4c7f9e45042714457400e600454f76b4b9106cdbbd2c1aeeb73e758e8faccf2f99383eef006341672e8d2ee46a93183f6c15ce494821b127bc89063292b0dc32b3c78f3379067cfd2a4dfd64e728f96b244c1576f4168aecdc7201c1cdfc2c363d7961df64bc9a1279b2de49dbc3602730e3e5ab3c9c171af92bbdd44af50cb817376ac7a8a8ab659b589ff4be915e35dc24193fcb7691a1adcd4f4225273819364590f660ab5f954bd80eaa1d9f61c007fe0d111078b00c47c68b41b0b50a5fabce08a6bb7e57d626fdd0c278220ca0810134ceb03ad0181eb6290e0732e396e0f1d67446cff7d49fef72c43b057fc3137cc8986b05f9ac1f3bb961a97504791be5f27eb6438a0a5474e5da4ef960b42606cf56d21f8fd5eded28c8411b5ecbbd4c3800132d86fa5add89267f851baff65dc29424e687ae736c9856b7f8b78d4770bc8816e042d33385ea2d0d516b75d1d93f4224f43233204995088f436c5b1a371a5b4f09a42111c850df2c2131f504537af3212e81beb49ef438a5fd77096d1c21250b64380bbe5e26234d609fe7041f160aafebc8ecd38d2996fa2730a07bf1139c70d39f1505dd0a9174274c425a62f654e9b82ad202050a91f49aeaab65ab9538c37409c7d3e8a0daf44a65be862d58e3d59bc1ac380a10db12a7a82ff469544457c92ab69007329b06f196ca68021f721617cde69e47c48c0a55d851a5d02e9bad0c10c47a3ef6fdf34ea3eb32a686138294597656f5ab029e4c3a04c9ce0fdbaa7bd97b265346cc6bb7b1bcf5b96e4f50eba191be03120770e04a7ca00c647ae64941791185f34cae3e502dada49fb52b9e68f08dec4166375c0c0abe3c5096590e38ebd1910c003e7201311303478521e5e37d473266e7514b1ccaa068719edfcc75d32c22f8256b8fa68c54c705c2a93909eead5e999dbc116613149ee5f9a00833448a3e1371a44fe853f85c559c6f58579c1f14d35e1d249bbd64bc6075bef6445b242b955be94e476d26ce77eeefca37a243a3f9ef0808e009da7c46f57303eea010ca4700e3c89c63d57ae8647e0103a8d9298a2b07710c53736b07454ffec31be17fe99926693f30712541f7a4233032cd2799befa2ab15d15f3af0d17a13e0150f3222fe4b55d7e507a3a28fe7519d8fe6e39bc9dc3c70e6d13100a431767982918e0bff0021de3a58b33056c1bedb280b093169ffaa030cee03fe152fef2ddfec857e297195de120afc73a8f3d13f04749655e4c2ed9df1b57c2e32c1cc553ae40629f1bb3688d4de1b01005632b24cb1335d8453d25110aa7d2c87559db5d6aa2db8256fc1928c0f7dff7670e685101999481a53215a443381741556c70e99b78be9e704c85d0df119c9dd413b88537bf06dff8ea7abbbee5d6a9d5fa77a336ec00023dbd2721b3e46702c8c0d69a6b77904d3e25bc1de923ce62b1320f3a0d470d8db97e2054fdf675d8e4e6e2be2a22cd494f6f3672ab0e31e302909fdae2a6246894585abb25d12e61949007e6c0a4ebb62d86c1c2cd7411f8f42aa90269c0ec60de50c6bfcb623863950418651126908ead51393df4593720507e2c044b7ddfab982a8f94cefa985cbbfb6d1020d35fa831bfc1d02ab942b37e7695969a28bc5e8ad2caae4b3f3d190e28330dc26fca6836dd25b227094c7be77964976c9a727ff595c73f9aa6eaa4942f904d4ad2bf27204bd384d22bd1b2d943e57996f3ebd242e968429f6f82d0d8dbfc92c0a9b1b7c077a0ec16c5892979f8319262658a2f2d41ac2f953bc64cf1a33142da1b8a3967a0ada0eeb5d3054e4267c6f6ad6a445304b6711d38516122bb36763db3d066b8d5ea68b46fb0800d9293b2ca51b58e9682cb656a8f951e3858d046967d68f40f5620d6e893104761431dbaf71ab09176657386144634d8fe1704074397b1e330cec3c66bb88f9acf61420834e78380366fe185d470eebae6a17b5c70c81b6a9800a7637f2b3180bab1382bcc8347ffd998272910af2b2c0da1de320914e49c93885f3cbdf5d5ad125983541225498812b1829ac7362325ac35e3f5a9b78f9c1b8e5f1f615cde33a61433eaeb65d09b49a86f1d8c78ceb7477a60a4eb0e76517020f938806990576440af4a574fbfad52dd826034c7a1d28b800ca9552fdb39185299df1e5bca918a82b55d094581ae6c605b6c3d244c385e89eaa6d7ff87d62ca3b8e36de8b10727fd231a678f8caa682ed383a04c6aac7f957022110b4459366580f206e420e93373e8605b6a04e37d790743e7243325985979b43a9c95e032935038615325b434736bfba38601872f7ee91466403788354b9c1001df73dbc8911fa5f49c6d4dd428e962b0204fa0c4f8a0799a72a61f64fdbdfd2099e4a99b648cc8bf9e9901ba216f1639e79d79abf5123a31aaf3e7384199a037eb3485312d3e6f9e00e151c6cbef41088dea41124c389f26ae1a646a2aa5a58fdd91343205b3994d0e4c354485a4ab1698a15778fe7decb78e53c5734123579fa4840f800894182572d2a7baa28677a65cda6ae8bfe0fb28e32e95edf536161d1a2296b49445b908d0511a1328a1b100a7d945e829a5a9d7b6322ebb4dc07bb4605c4e3ca84901dd4803ba5881e9dedb018ba2504123f41d54bb77264baea473f6470ad1096561eef4e02723fbc321ed43e5f46f3c68cbf90b90ef4c7e28314411e53bda5fc2485da9ca4be4bb094815f7081f091572edb35ad32a935ab23630d643afd3bf671d942eb1cc280307bd9025a069879d657ac161a409d243b6d3c2de5c1bbad6b72561d8f0d9ad0400c2027106a429828738abf543d39028e9fb16aede11f3048811e79d08b71f295f1a2c16b6e4306326fcdfb09f0837cba0083be8b4c93198178eff15fda11bf59a7b2939de1ae3942d20488f156fbbf193d85c7e9e0158d410e4baf6f11d340c5d77f4b27412aef2274a3de9ff08934c5c732ab2b7031592b2e667d19c5a812e54e250a4f7327d7098f697985cd05ebafccec3f995f26fa385c7136a86b22194169543bc3be1fe1394a8f897c95daf8a434032841d4c86277cc5e919b88bfb00c9756dcd1a0424185cc3dad6098ab84b1d05d435a441fe70d41782a56f2bd5b67682838843e1c11ac0cc397cc8baefeeeab692d9cfa2329a132ad730c107f8336e4991400069f793662e65de67cdacad5445f299faf6d11bc903276dfb982ad3167a3405eb92b622b6ee0d2f93d6a8af57487cc0a114401a4346828adaa1d8531a462a9e84a143a3d871768f60905b0d8d08877e3082f63a595b1bda5e11daacaffb7f4498eb07b00cf5b6c64a17e8da6d4d70745bdd81d9e16016afd33f9a7d78e1b6a60cca6d9dcbde9881795b3797e426013e872bf5f0d2db6587879102884a76f2e76d66e1b5ddd426a3b47607a84aa2a51568bab4fb141c02525ee5e1dcdc0c423fbb1743c80a1bb9eb873c1c6c8103666f394bd88962e487bfcd4f45afd09d5f90fe6f60071bbd02e16d85456ee0489d9565b84138add7aa51a4437ede145aeb8f26792126b036630a1687cde9b492ac5800dc0b4c60cbe79467a7d6d67e63741a630bd274df396e915356e32943e38dc9e7d4a1d3ea540a4db76e04d263798c42afa070dc437cc4649321e894d2fde5dae700b1d0b2ac0135cd314826892f4ac68842e048e7cf2a2d79069587c17671b416d953ec0773724b0ec11a8ce7b42c7e420df9a000f85407133aab987cba19a98dd92ed393112267801c8d58501ae9d5f0d81b4a0a5d5427081dead6f5b00b77b17ddb8dd623d7407b88d30b875283c298b03e9ef610ce309cac70204b8346fba11cf84b67941d03889a3ce0c9b3d49521a71a036389ceac62521cb0d607ebd4d4681523eb12988d960cfe95f469c4eb89ebe704164f7a7c8f250749c1a02e95e2a37220988b4df8028d2d24f08a827a7254b5845afb955bce17f8030cd17ba503cb4d5b52918fad9594f85f3608e0c65974e715702f5eae4ca0cfbf8efe58a31c9eebcf3361a12fbea7d0aabc307c93899a7b24a8ff4f3e58956e7b170396405938b7311b478b74edf74bd2ea21cc6a9b3dc0a750afdb73e14cab110920a0f69e2959f8ce7373c27edb63379703f06c5bf1449363f58b1e2b32726606c249d3bf19e60d669e738e0c448049777ef836d3c557d6dd0e51f3fe6fdbe3e8a60206c0e5d1b5bbe33a057745421600036bf11f9d5f6f53f63f1f01eb20d792eba3944123b3f8bf5e60339c8ea39211b35932629072d98e4a12942af1d3465d281db3a05eb1d26732b88b1bb0dca412c4cbe87d53efb724081791f2e9fa155c875446c57cec345aaf021b3a017afe3761434a5116a272e388edfc7f35cfc8282d4d1e93588207ab1510507f869474908fe9bae67b105ddb1acd3168672ac71ccfa9a5b4856294e0fce56781760c60134f0f9cc7788da28957106af42fa0c387e95983896814590036c0948b7fd5c69a6ed21456a348dfa97b4e96526dea1722861377789ec25cfb1c68e693c7a24bd8ddcac9e19d13a07dedbe77f54bb0ad7cb2a70646c1afbe1690810b6c147c50e6ede54a3f8625dafbdd5483827a2183bf2a655d9e76fec0dae49bfc8406dce6117804f8985dcfa7bc518e127c28d4b1636593f71969ab8dc7909d7ae9d152ff7b7077039730353728e6bd617a7f0ff2caf53821a144a83b13b89ff418bf0967609c144af819c30244079a7255543e7c8ace0dd06435c93e6ab55810dd63e0e57fe36bd79a7aba9d829001dba926b17379090dcaa80fc9162ccc188ff50d101cdeb6e6e5e639f0dfd6e33c45a22b4a50e7275988a553d730bf4c652c7dd4ab0ecf80072505c3dbd231471d5d6debe8d798ff6d3418b61810249d07f91c54e7131ea2d23a2f1499852c1ee02e9f49c67cb61edadf5bc8d8da036403401a9b6bdeb6e0733702bd000e7192662e59161c4bca2938d67f5d772b2d95e0c3114987f22773fa606c092c11a9c958158b2f43fff52f531f0f0fcdf25539eee75d1d78b56af6b4bc2f471c2379eb3f83daa4c88544f8cc5ce82e057c8e75f6d1615c39844901aa6112a8e2e1d67d24128a17feedd69a48080245e2d19a02b0a597828ac5e0041d108e450bd38efd781a6f46521a3ce51ef2668ab6403ff65e0f81db220ae282799105750930468d57daa10240f397a474480e89742ff9b8754a460e344d513a071942468aa951520db133fdc95f5cdcfe5fa7435689a864770c9428076a57b7aec5b01963ef583559503dc677c4195575ff6d6f0f5e9511698a9aba00d49c08069762859d5602611ff82dd2b8f8ff92373809ffc36049d7776e439ac1d5e03b3c8e424aa3012a257da6c4c8831f2038280e58431cc386e77c4a06f108b9915a7a0948f51a1c1fa7bb90b7b6de945241282abba364bd27a8717101b9724e81d4c3d4eeac948542b1099a624ca15569e4e304d959ccb4a310741539fd4dce51bfa6ddb9fc497446132d4f60c4d9bc1c92c65818180818d74e2959ae5c823e6c225e63f9fb428eadd71f83543981cf85e9bd599676409ac370b7396ac3c1ce6601ede26bca5b5104a431600c8816cde9fbf43e2266458ebe9d1b9d061fb6d0a06209acea77beaa533e7c4f5b07455b5f6775f5ec9476ed292e576dd84651a9aea61bdf6dff3a66bd68b674746fc20417a789c7b50e4d3da1f53c5e4eeb31e3b09e02882ece16947a2fc661b39affefdc3592528179093e10a9eedc5a086e42e4afa883736edd0326dae183d5658afa216d7fa06e9a88535edda315df216aade1ba283f891c1177c1a8231f25ae0fff6cfb58d3e126379f8cfd06305894698bf53a6e44fe7732fe9199ba8d5525a6d327ad8db33fa2e8e476b7ed7d1068436c443b0ce4e7033de9c6781f14a6c594ec6b85699978cbbaa991a3a9e8515b41d7abf1d3f5d462147aec9a3c7df8d0301c6cdfba2161a24d2516c74a1fc465f383f01c4868c626a11c15c81727fe86dc23535a0e661d05f4c9dc52c6b2387a0b82790b84a56932902fef4a03b61867456bf8a138265808df82660a387e2ed34f5e161e1ec8b408ff150737e400f94e6fdde14e53871b79c91491f71877710ca804047ef6243a47504cd02607c8aa944f43710a318a5f80b5c7a33ff62ecae4fd7562aaa38cf7df872857df97ec79f5c392a61097d5da097d677f5628662b9800769dccc5d0caa2511995317b5c95b41574e86b97af9c0bfe6710152b135281729bd5225d90e65d512dc111163e7d24401f8b3f64fc66236fe7f45efcfc55ed2eeb49d1e1c801f08901f378bd69f8be916fab7a00504261aeac3ce61a247ae868bec530dda8bb0ea3b8f0a8f44ed0bd8b81b1053a2faa3bd4796cd605ad06c3e594346a78a1a6f79683a5b26413c2bc7472e9769644959adf0736affa08c4bdd9c7fa3fa72dc64eff888e6fd905c458f325e3261d3422032caa06ef85e450fe355dc4c027897ea4ce9714aa2e40b40f6244f992db51545921e757d3268ac770c395eab29141d3c6a58730e8bd428e4a11a22eb45f5284d7c49700a8092a0b6ca6fd765c8eb60394ed0f444cef0c2d031179376b998bdfe39c5224f59ba4fc7de184f953e5440fe57f70cb5fb5446a4bc83465eceb1e2bea923ebb08e9becdd08c369872f7b490dfcba695581811f91fd4b5d50683df5e4efbc2a7b6a329b7485c12496f154fe962ff541f153ffb369ea4c2f9a819b3a9612009e500d57c366d01ef21b00cf1256416bf0aa64df84a8f8d30bcd6cf3de7ec06c40df56a93e9bcb0a9a0d746735f8ab3d07dddcdb36b8d492fc3da0a6160b9ef4bfb8cd046b8c5cc2983347d861ccca2ed6c7b44cd3bc1c15ada01b773d4c06c86cd770dfbbcfa7d884e87aa8b3a00b04ce2c91a4e61a41d2055bfd16345ba3d56b457eafa1955d76c6e0624bbaa2dc4cb88db06d6162e24aaafaba73045ab3e93f529e6610ee4163a2ccc72b105fab6addcfe687c6a501a92cbb00bfb239dcf0cba81ca82b66419ce0816bc92e5085b6c373d8455a888c9066e9cb5e84295df3bd9540c583da1dc138aeef6003b22ca32fea90308dd6fe762ab2c4d3ccef85884d699cb24943fa1f04490478e95de1236cc9b024ce1785a4590932b57bc40d04df12c0369326e29b41053b4b30dd4b7716e5b7c91178752451e224d6c856ed206a345f29ec439be3541e0c773babdbb85bebe3683cf923ea474914c0c22b949001146a09c2bf77f0d8fcef1c8a1c74bd5d589b6689e8aaabe505ef3dd1e7c233fa3146fb5d8b5e4fc5ec37eaf44ee9893207dd389054535529e15459921a0894e40358800089c5600643022c28eb971778c30eb032feaab460a3f2cf19ad2f04b2754fcf12d1af70d04244efb0d50aa1fac02f85ea5c51c2d553dd4f12d254addcf9745bd26230bf0fc4924ce91bd8b482b54f1885b5adf0594e7eae90bfd75b18f6bb0b107122950169c8bc716f5abdd4f3b3ec1a95ea0feea82bd2415d7f30bfc7ebf70c542bfe83250086133d754264cae015d641968e27fd40a83921bbf107181c106892962296bf84c6d53b7bf3d2dbc0ab928185e054971f1eb25b0d68de02c0da5e928e00d43390ad11cf775a20ca66202631962f650f7c5d402fff520be952d3630cd16305095e007571057cdf93754e91abdd15f2cb8d73648d214b23a4ce57adbcf8b7590678daf8a9a98ddba91e8e4664f7a4f27beb3e43cd3584c522756100a94c5596903f287991b8d41c012638e216229f9f9e9188a0846b0563f5c34a0c47a2d86ee7e9afff33af7da4879abe57ba2c5a8a046883d58b1c06c004b6860ae1a40c302f740d11e9fac72d59fc5f665cb335826eb93b3f259d99c9afb406afd7fe37b377a8ca4a3a72404465d28b066624cabec6b4f472f98e43d96682704bb96a9307401ff1b41dfbb393c0a05a9956a40d7ce12758a2024b99a474ea603daf3f5cb52d3bd9c328d126735f696c0e76b5a7bf060918e53f247ebb456bb8b1909a0cf6a2841f457114abdbfc2e22bbacc7cd9b025e6765519f59efca39af7e80f539274c8c0d598a8f24fd7a4addd3861cfbc568cbfa0de87fba0e95be132e79f446a1c385a76248cf66c816b37588bf188fa6a43e92ee6a222b8af297da087342e1fa717c2b62162df5621779ae4fcd076da873d90ddf42c6101c695c788cfc579672e537d06058457aa63a1aa19521bb81024fe6861394e665b2e7a33ec0b6f384ce0b9bcdd794edbd7b05284f2324c7a2123df064dd0a84b5c59c22446329f66878d7e165168ab73ec271c651e9b43292e8858874eb2b5765c02a9b34408897827aa1912a695b6bc7fe635b95dbd4d73c87a6f4a90eab915101cabf5bd1e56c8639a346030703316f5db63f39a8a64b9fc490620f7000073469f68f7b5121e1a65af4f612cdca6b22c1febfd4a1a39ac4560b1181799bb2e22b2e57731bdbb4f6def27e7a6110c673150e8f906e724d8ee4aef2e7618350ef308ae5812e388e4ac852d33144bef5072b1aad47f5435ddcd132fd0da41a3c758a16dbb7c2df5a4155d0a191596d98144d36e7a0a537e07f16b92ee6b28d81b6ab3f3867a448f03edd91bd0918147605c190b8f2c99fb97687d6b550e086aeb17a040ab9f36055557bf32b59f7f6a70454fdf437ad49d164c7aa4cfe6aa89049f4110619458b390fad1cf9a9dfb0e2636e8ed61d25188379986183894544cc9595b4a761fca035b95853da9f1930b3da110d75bec2b616729200502cb56e3be43f3feffdb0c86c5c7e3f011efb009779a932fa6dde2c2fbe453441aa2c43edb050a147b8594494620c4ff0097350863b096a3b6a647b646bd0253e8f36fd13d1adf7f1476857e90812268c518c4c0b4660b592bd158971edcd5a9ca8273ccc68791b2c5e50059a1c359376e0d98e69be74d9cd0c0f93a27392ce7dff2b78d2222c846c4340e1edf389b5872794963c07bc06425b907617d177621ae185ca551474a92754dc3129ab8b5f7c24782b6477cbbc2be80655ed0a1a175c2a9e93dfa732f5a4b5662a508ec6db6edc1214b15c0208bfda5519d40e44672b5109b2711884a1f7a1ef8fe05aa7df62baedb92973a601b610ef5c3cb842d1b67d7f0ae347f109250f350698e31295a4f35eaed8a5378d5b8e86f7c7332c43a255daabf05eac0dea6afa76257061744e6c07f7701c90e48c0dfe40585d475a3ff074fc4781c90aada519757a13e16b2d22a94e1b8f92cf30c98b1578ee82e1ff299f4a8bb11543a985044ad95510bceada89198663c5edb18e2ea0af58638fbbb71900325d70dccb084fc37325b6a3234a57c401feb107d55cc3a0b4c97f1c2fab8e277a34d07599d733038403fdd1cb05bacbf7ebbd8a88bb1c8d7b895d242354af496e3b81b3e0cf1a1d65b9a5bc5a4e78b77601f19d7cab8bd5af065c582c247d77376bc6f0ec791e6eff165fce852413c5d649e4c002ff5479a2271eb09dfbf8f731485af3961ebf6c68e52d61f9ac2d8669e8fc4c4ef025427f8d4ba920c1cdae0da4b73ac03c0db74a383bc20466793278184f08f81551800dd256c9e473742495fa4e08a2d23599b60f6892378d4fda902c07d5e386faf2335742218acf8b52f527924710b0837586f3a09cbd8b8f6c1e27bcc87e6a9f2bce042f2c84ba1ac2dcb2191b6985f0217e446d38abb91117cdb6a75db583ab74ed3df8b676fd9f5a909301ae981c815d0573b6f45282713d5fa2a49e4570ba6ab1d603af091f1ab79d852e94478b708f4847193250e0b3b3c9be3a97bc8f542ad69d5202fe74adb7d08f1227875e5415826df331d3b8cb53d8128935cbdf08708b553f98e9c9c42aba2415408882a2ed0664695fbf6380d87ad60bb39a5528b9ad535fddfc62f5cd6bd9928101e5a547c6f7def1417b81cfa81f266db7f23760e7d72beae533b01ce04f330e59985c5c0d154aee9d6aa4fb7f7d42c72aa9bb5a2bc86af9731cc640d40d75414fbe8cf62b11d2c67581eaef72a96ddf3b4a1108d626265bcf9ade1201c21d6c08e6b0ca846c72a3939db751aef892d5cf856b02286ec36a6f07fb523d3cf719f685c996ce3fd6dfa375b0fb8275a9b3830d7f344b724ea3838dbffa325b8f3550e0e573466fdbd59bdb943bafe92bb49f532132d142a10fe087f400d049cd6f1ec68612a9bc6a92741e52a376265cd62c1f5d8959337cc2805e49fbc2e6e42156533291632a8cee44a64db9d103277c6b0a5ab2c8993e326d694793e52eedb9f27905db60de128a4182cb48305eaab2c35506963cbc95cb990915235c78b02b322411b00bb8b70d7cf666b374c4578bccf2b5ab7f7f713a4da8d7298c18862b0ee9cda16705d11febeb972a87b526c5d5c43c37e8d09855c76760b0d3db2ecf9593bae8d22a90d04c11e872fe31173f536481cebe34395d8b898ae2de9ab094b713a04ee2d5292d475c67b4374c9a669fa524feb8a7c60b1329c846fa993668cb2684b4a80fc1094cba507b157c7dd7b024d62fe77a1b83c14ac1d67a7d4b794e352f271b5b05c6a223830211d7b6f86acaa8967d69d515f0791050c0d77c6df1d414fea1a2e35b8c1ac39967151cf426bf367592d39d5c2590c0bc68c8b15839471ebd0658c187c671a4c97d8953c42d738d5477df101a1eba6cffac020b05fe807fa1ab7976c778739176a5585978dd6704432cce835fcba104e3f25558e62d03562c20951742df3977c129bce8e47d3f76ec5f3b3f0d6337d978b9d1ad7cd10dd1de92f6335585f2455000c2a19653154e7303f874712109b35b581c5f9314643e1bbb22058faf42924852cb0490dc08cf95f0e8e5114b45032e1c3d0c63959b4203e8a4044009021a725b034a7168c43addeea5159b34397e68d7970187c63b630ea6c5a1ea374ea8332874308f6f771eb998cf1063d32b16c9092af6732f277d1bef3f66a7a77ec1fab91fca506dff29d222868ae361f43e3a60a9169cf82235034e61261bc961959592f5c426e7ca4401e8532a4e6b89afb47451b5a20e34cedaaa4808b526c10bcaf5a229a55b0817fa790af3215a7023609e105649f71d94785880fae7c76042a42ac99a5ce3db8a433a1de5f702bd5367118b436ea048d4e9ce0338d07d0bd039c8044b69a4c7d2a74ed4f0144484f4065f47c50b284ec2cdd41072962b0013d7b5435a31b87a4d2acb150a3e613a3aa147dbfebe279066d74f639af7a21a48c509cf6a638d138d5dc86b081744b02b085cc70687cb05a20f6c09e6bb2bc023243d77002c2c38a445dbb9f30d262edb70544bcbfbc8a8abd6860806d5f4f527d74661e0c13a26ad0ad959d4947b4ccd17d6b19e0654f087e0aa4b51912cea40481439d7e638fd29a671505341770741c575e5ea495a8d73f9a31566c8c17952c1ae789830a602a0a0a72e6343f5fea6778379ef5c97a3fbb7819078228f3e5f8931851cff050a899ba3d0a86a25d3b875f23d5f023bdc5668b5be3bdd416e022244af975154dcd957e1acb119a24698905e23c426b936239b63c6e8896b82dc247b3ceeaf2a423a9eb043178b923a0dbe033e2d5a823047f1fbd01e2fbad3aa9e76f84ab6ce0156336f179412b8153acc0e0450099c3ade4801bc9030bd972c68c3e94d0332a4281336a292425b9213b0581db7a8a3863214bbc0408e62c1ca997509888a425c5a249ed06b8f86de6ea1ed1e7149b4000533ca8f3622fabb6560ae85a44ce33bb74cadcfed829bca604f97e3c9f152bf09f1607ee00e3cc8f08ba5f2be10dd362be2495cf9c57ad4ad0cbb04bd29b33d48b89498cafc345050ebbbdf0d363f97f2dd6b51e9f1b0fa550d7bfb65bed016f07e69652c95ab47811165d7d8ec6fe713d2b9fc87f02bc8c8c00b89065031fc7ffc0c724041fd1d03e0970813e8d5ca695dba0be80bd742cbdd017c6e023a1885b0a644acd8473be917744078c84211d01f266192c7a6472baefc13f7282669f59ffcf13b94cbc0b2e9b239ee237e1cc82456daa16722de219f12d874767ffe4bb2cd790bf6234526a0fc183544a979ff8178a1f57ffed956d875aa1614179756817285be69274ded3db2135b0004f04141e4a3180ae2001e1af88d36c3a818298ddc6003e17b537365cf238504829465cd4fef6d64cb6f7256fe1c109a725debe5091a63b917b1db2c0e202a42a020bcb01d2d534088faf9d538e84b8ee264b7642785befa736d7783a8d82658f09bfc4eccdb4c70cefcf15e9be2f65a2795f2d1ac8406e44cd846c9885a4d294386255debd915fa18fc81c043997333b196fec91640826af2bd1f9f200df4bbb4d65765464885b4c0b81c51ba45d51c073ef65b062dbc05240ee9d22d574543a7fd37ab349bce9b15ee63aa0f37b31c00d3e6db0b04ad8701bd4a4bd790871319367a08d98541fc4ef8b38a803ae8c7d048ee061cad9c7a513e55eea5547d57268c3edcb912b637904f1a87df6de1df5beff5e64d7807b1d15b804a0136545b092f0d5b3adf53ae6f5bed9890e21a5d384d34f6c3016f4cd9e389a31b03a65bbc1e0a4b60ee4c9a0a8f29baeca79df10017b65cb9483153ebbaafe8c38ec540f54cefa4111482ab0d6e6185e647ec0e2678ed243c1ad927fdc172cafe41b087a8f6b10074e2149cf6ee8f3fca4f9932d8a6f0309e58b83d9537501fc76e43333143ab290ec6466bfe674d627e5495851d7a5969cd0c06c230afd160d691e929f14c76ccb3109b68ddc212d8e6f91919be4c56994133c49bf1dab66be816a5e0e1be92b23b31d2b6d85199e95292af83b2e46987e27d12503e9aab9d0dd0f2508733bbdecb76c1a582a3fcadaefcc7e9da6a07c0c8fb090473af0f564fe8384360d0f399d7cca2044db2614b0cb67e736dd7b20a18ba8bdaef1bfb1a49887cc82e0bb3049fef78a4c0ed31b78a23b286024636ef17c0f9bc45b1d74009980b01db65cb1f32ef0d0005a32470cb8047c9c5d31f0ea41c92b795202877594e0447ea0abbfe7f56579cbdb0b54fdf313f4bc3fd294b512d4fccff33968216d47e6ef3f1fb004bdcf109dc455eb6c5869cb8713f70082db7ea1df5e282e91a8643f0d12eabe63e02d31afa911f77af62e19e9d4846aa67b029a4fbb5b7e234ec6d0093f27a0eced70d88b6033b243a4e082843dd471a640e091064a459ec83f26ceb2453c83fb80791ef715560f0e6042fdb7dadd9a4c9eb75653fdda951240c412938ed14314a749fb377fce22ad9ddb7152d5d970b76109e7e98de96190d019ea9bdc89c1865cf4e600d37049b5a14e23fd2c15ce4f105ba86c21c2e14a0633475081266e1c78149c3968c4a1aec7b91913b42fdb7f246198b76c1ad964d7646f9cfc6027f0904895329f8865219960ae8868054bb2773e5eaba205b813afc152f2f689ddf3385f7180821c6b41431c248f0b86b53934cb6d4d2a8742ff909561e20270146c75749cdee5797da0ae59d069a388cc6dd4eaa5523914066134d01fc2196bf1440ff0340f7a38427070b9dc326efd5ad9a00e60ce93651275f5a45c7af3fbbe45bbf65320a02b9a449160451d618d8acc4e21513db31494c771f6d1931fdb58cc53a618a14e181531fabdd4fc3880d29875b240135e4034f67610223c1e611ab5f30bb30beace537e79fadc5b82ad569807283cbf3a8cca8fd6488c9ed52ac162d36757908364a9df7b6228dbd948c5e3599410aed018119282c61af6626ad2558f2322f006943fe923817add1b42dc62be8f3fe9593c889d54952392968be441b2b088c352c3db624ee308de425a12fa85ca6e8df6fb763063c588487a056c41d9ea86a756dd8c05e0c7ecff202c3ba04751a126cbaa1d2bfddba369f47c1373566823696b85bf4aae56559a4d2c30bc01301a027791144fd7940f9a193690a2ede09be857b21ea51ccf81ef593d0fe8d6221396fc052b6372ce73d6d9093ee9440c39e1907aae8e9878763b19cf6e6b007493a27e0ef976c7b4e34da5ac7b6630189b5663f2c38922bd171af152782c5eda6fb52a946bfdc92d0334de7eb2cad55de0269c2ee1720e3c88086944923a984d5583f432b36ead5b30aae581e0fef623f6069e5ff5aab906a26c32079c2d1fd7e1b840dc7479864c6a8a74496ee531f9987a08966c598fef37615ea4871f38ddc1f70312573180d01204ea54c40d00641e7065bdcc1eff97289d1ab609fcad7df273109073a2b5b596832c51a897e5fcae95661668af77243beaebb53c7fb5a2f902d5fb4ed9c6ac46f3b223dd83ea747c062becaf6ae04fb0eb3cc05c71281e017fc82cc90372cd46e8892a4d33194ef39265fa343a141b1373f17f24fbc4411a64007d1cf4e8c39bdc5b7f97e8634e275f1f7c8a57c0f5beb2eae2f3f34fd6fbb16d59947f5c21b85646f7682eb8eeaaf4f0eed2fdac8bec4a852487fb72a9ec0f49e5851ab771faa445f798830e073f75dfc6a6397667b86489e5cc3cf523cfea07894f84271458b86a9a5f8f7a8c2b5ed58f05824e1012d2909fb7dd98904414e1ec86144886415fd19bd77c2c443d1704730ea4eeca354028ef207f4420e30bdc50e79cf743dda8e0ad13a71ab4635075d319d53ddc04f7041d878aa71d60498c38d1c9194a9e63b88280346e525ca9e2e32d7c3bb93d67eb3b86f98ef210308e73f3ce6fc1cce5db96184cc4353a4cb69f51455e889744d50370ef238fa918043ee369fac8a5ff72491804f702179d25b4d11b63a5a40a63e685adb823f7a6ea827664c828c18393fb8c8efaf7ef4b6343450b1c52d1527caea6b7687019ba9f004f7e59380dc2ee94f228ff3298650b4661cfc8568b6dbfc4beb498d3ee56937f659fe04d1f8feadeda501b39c8b6ddf2516882db2379a1767d4d54ac4e6c5ca20643f13ea58227ede28fa8753452fea33dad5f482649b7637278030983fae6428e463753222796fefa88f00508430d00e788ee010e2d4a8d54c5412ffe08164eb1e3047c3d7ef0422f88ce878265c8afb812506c25c2eabfe09b9bffba90a073b1b52f877a22107896f316608034de08ab0f3157a601bbe0621dbbe8dccb139887af73f25fc8df0aaa1d3a20efb04f165cb02dcea9175c435c80ebc8e01699be33893a9b9a3212337b8293410f5e4c2baa7c573c6c9d1bb2d6c45e3278071a510c86a9d07cca10ff971e20ed73ce710ee3e8165ef5030d444efe0484c533273d5d10d7a0b143c516b28b165d3bf174e28e202d13d876edba8c09e2d7fcc0ad406919b9e60c22ba2c3dddc5374dffd1368323d50491457a114e87d449ec6b171ca9f875da8993ed8cb93c881983f20465cf141ac23471d04828d3d24c38e27a0746b3e55911f557c4a87dc8f86c5eaab57d5140ec9b7f3d6c438658b9f275e217a79f0e9cba9633dc4bbd7116eef70fca65f7a8a65632ba560e86a2570f85858d3a5e12ac698670a8a056757a20b25120d86225216928b1548148c587970a0688a1cc0e2cd565744b82d72e150aff899e0b30a1c412c69704018da03821d3e9f3a4c82e34cdf55ad87b4d225b8807e950c1f0235df33daec773ae4566cf1a0ba0d53993c8b5f21d4511f5409b50d80931e589e474dd8801e3336cde54c1d7787223b9a7fd0dade6d90fb8adc659bb2cf241c1296168712ab2ba13201fb6422f0b28a43dd40be377b5114dfcf78d68289316eeef425edb2c5428e795664431958c74da7715038650c64efb5021f629c8e3091e6c6ece832b26aea96b04d8e78b9ed3e88d6fc1d27fbf12789985af71ee202434d57405acbab65d6b6e9aeb9d6af69784662888908263ea1fbf1400aeaeaa3d2cb5eecdaec275fd18441711fee04d29abbe68fd0e9e7b12711521c620fb8f242e2da633235f8538cacb16abbab5a9bd521128025e0ae995404bfda91e6fa58d15beabf09471abb64c92357ac6744e9ccbb79b95db5a5b5444892dec56ade38f32de626ccdd840206410beeb8d24d95d63bdbc1ffadfda1d32df2cd84d94e76b45f4e1a86c4b133c4f7fdfa8a97c192c616feb0fcc32d1b0ca8f8213f0a96e60e0293361045b4ef84b9a251497cf7c7a0337d07916b417218509a97bf8acbb865f24a5731606df32f4c349ece4a7981efc45f2d1d0ddb3536a8450678e31af0dbb03a4b656714f21554668fcef1a6e4ba086da2b9b0a9b7ff59d31872807ba86f538582458cd2b249760814c3b7ecafe9fc53f321faf1b78884f0845486fa09d3d33e9cf9e7dd1010256be375bc542479a360322e44a6270f893445271eeba74e382591479a1f51e17e4656cf45fb6af29c5dadc20c95baea75ff9e36e5c832ad3b6724fb5ed250181b8379365706f2a162fb10fc081e7483ffa372d2d6a790db074cfa156899491a8a2a7cd97b01f8029b1676e8841837b249bbd416cee26956f01bed5210d2057dd9ec955e82500f16298523ea5f6efbb8ee678882b661e6f7c21a307b9520b54a7fc960062c93e5724d4481330e32bc5587f048d0a62b7392fc975dc3923af8741ff3a1a1ded2b97c05fef7a98151ff0c2a4cb8a36fb971a398ce04a5d06645e2a4a640283b3459f526f49fe862899c4686e151d6d85e0c24d4c4fd868cf7683033dd01140d858089b4f843317c276fff5b7a720eeae37443a60e994de1cd27a01df90a159408df370b1dff74a5225d7c2c9426d7c37162021b95ea2a3a02e5de239f60dee077746d1bda200a4f9a1f91bfae52768060b666851080eba66ef1700949aebf1a0f5f9588f289f914b4a5a98c8f19e2aa867d52183f04a09d62e55211f4e503395f656797b643b8accee5b5af33aa10e747f3fa7ac50700ced32b9c8e21d89a8fbb0dfe8cf841d9e93d91fba7be2dce745b59fc8dcd96af8c139c75a03e5f76b5dc07980a7a4237512dfb7def9387a6d26a9b81ccbcb30adc4ee91bf88ad95f9594c3135a66340ffa72addc4d8e6553f507bc0e0526df36eedaf952940d7ca86f4246dd10cbefc97d9226a2746a068ebf41ed7dcfe7f189c58ccbdc5d4ecf57e84733c772609a049127653a05b0e5e98e573153267a572b518ab8590eefb448934c0cc0a016e014013bb9a42130c3e0cb93c62c1483740489361db1bcaff7fc342521b28eeac229a0bba86197f6a901093572e2cb7443fe12d693483215cef596ed530f17a7802caa62c8ed6c88f571889c9d30a2ef19c40b0bf5985b1a8b67cc2ec997467d99aad17a396f7caa5a5800d73e1cbefcf3ad44d1cec2a1b19a5bec21df4507541fd5b9ed86e328a67a560db1b43a9ef78e3b269b4c6e23f1ade4777d0e45e0191121e8811a35afa3becabc27358dedd197c82a4d0077986d18b1d5c1d96e8314a88471c3211a26902ee86e52cd7f7ab92cc448c3d303061b6d6bac45892e459aebe2e7635c8494eaa66f355610ac82f428a5108158fcd741643126696e7acbcb537cd9de236d603276a2c1622119cf89c2af9c5a16f04711f68ca57ac07246ae80dac85a2ba50cdc5fe0ab25d90c4a0cff7234edc5a9f030d2cca9ec263cf04658b6cba79755a645b9705af0c3ad3aeda675ea5a6b81d2db36730f826f07912959f784acbae186e011c21279b4d97d8a726f1026a7fb62a72035f0c8e7f705533e679cb516abb31f4ea5b3a59835188f565c2dba4ccaccfa4ea117c3501d7e5d1430c3454bb9648ed3a2f0f66e369c1fa3e82208d7c56c34946b6503b6b471bd3e3706a30c6d0f097788beb5ec769b179fc9ff799bf06b2b350cad5806152f874a5a9804dd124fe0c5d586c53ce58b41f8b73e07dffbd7ab7b1a6b4e1fab5179c8bd13e5fcb7b066050d0f2fd25e35bfc6a73dad66f393aee650d242d084a284b7715c83c7b527ea137b7a2a23f538816dd473008c6747a148b713c3e6d26de3c1297331f3dce3744b7c66426169383125f22a4dd27e625862fa297f40299082a3862d0c1a4f9670921d0676dc2512c14a6f14568aed5c586fc28f6365fe5dabaacc4bc70a935568c6e094e9d2e277735f9c5b801f4a4250c172bb16b5a624df8c826ff0e559bac3962d1384d825109d25d5dc2deea44381a402e713479fef46c7446365ede51e6dc3a960c5028386b0b72141595f56aae1f5ad65c41ed61e7a244a55e9af5bb96dc2c35d04d07505f9e0f2af69a75b8dbcb9aefa5820ad4b513e4009578786b1a567e82229c114fe8e7a35164561c621315dec9aaa4fa052169aea2f6b8737b54548bdc7e1342132bbab7bb6a1bf56a25dfef109a5a742f77d1328ab596ed57a134b522f6b873ed5153ad72fb27046af605bad002ac977b30e6f629087f83f2357478707f73e81f41901f485e85feb7ee374df61904f206cd57689e08c10a06fe9e12cd613ca2b41fc8d56cda4b27b294e81de1012420024a7a394b5f509419271d93e39343ee3952de4e72c088d36b79272185b51e23c43502cce1281a21e1b04710ac8d00e914c75c8120d23539c01608031182014ce8ef037d1df16c7ea66f033a845ffc3fcbd9b8977eeabef5c04317adad6d239becbda5dc017c0475048c043e3d5d0ff1c0e3a2caa7a0dd9bc538f66a6ce06b7a3c13f16a4ef589baed76e9b3f2d0ae4a85b98c3ae32ef5e5b602e02b75b2946a116b537d97ebb8546a1116be42b577398ebd8bead602c9e1ae232c3f525a41c657b88ecba6faf63aae9dbb58b0a9b6a919b8dbe370b72ee7de168785db5bebc39e0515155b8485cb90711d970ae6aae3c05cf5be6ac665581f323ee33e5487b98ecb06e03a2e9797dbe3bcdcbe6f01f000581ff600b80f97bf5cc7c5718fe1be73170b67a9ec84152a0fc197f81900a830db4b5da9f372958578f600f3344f8c67a9efaed4c93f2b6cb7ee405b5866611946df3a208dea321ebf03d2d8cb50b9dccaa8a9f9c397781d97aaa6a68c78957d50f5e7b22a8b0347c17564d25a9ab7f5adb84b7d715beb9fc9749a77fec5505b5f5f8c1715860a35baa81c832ff19ba8f29221ae829dd0b0e6e2536aff5053357e548bbc784bddb9cbc55115480e77b9b00feedcf5c2b201dac88d8f403c2e3ece7baaaf54b7fb5ca8cd356dfbbc98f81da86659168608ed46e9b468161668d103142b4e4067dddd1d219b84501ab72d52160df43093457022082736d0323637ddbfa9397d9ce660c7186bcecd93c59c9e8934d248238d393738b2bec981dd7d8393d3af95e4d11c8cb1edb1a3b9a80395ddf4cc1b6ac0d08d8c5219956930b879f5d62d1289b61999349184219af0811336e8ee6e668e0c993972e4d867abd9ea318182c38db0490b24303ed0deb66d8b318a628ca2d16824aaef36ec36db9a968342fb514411450d2a5310c1e20828989939c618f9bd5a36319bd60b76cbe6c5e25e362b1b2b284fc82868fce6ee777777373f61e309a8c5be9a1319b8d112a104d8ed5ecc888cb3588e9ed15143acbbb9359b4528535471bb179b2be019345ecc7f71bde1db680eb2ede263bd69aedf373dd3afb7be79d908e2d70dbf7a8667b815ed8a0b7adde0f09999b907eeded880b063f15fef059e0914236e0c1a42d4a00c4d4bb65ef3f134c4dbbccedc7ff50c6f87902143b8d557cb6625448c1b5f22d8b279c5695997b196103a215c08ff007ee1710b7d781b10b636e8841322a89069424c9a50c244892976104510b1fa002604d400bd7a4fa6fffaefc6de4eaa1d8b0e02379e636a68d18ad7023c0fd4ed8e86950b0f573c0e5ed4dc907611d0aaacdd0e8a0309e18c8767a84108a1256993e3571c1932b3954f76031f993811828a21128804a62601be8fa3f639a3fc8c9a167780382011833c425c40d10198020d137473ce77abdb34ccc339e5b55595791f00c7e5af5a83125aee3dd06eb5623de92738bc5aad50f731494287d56a9684637d321cd609f48df686f91b5ae8d48b692db63caee58cb1e5c5b416512fa6357909731989d4b10794dfdccc0c7fc0fd5e0a2cee8befde1ef7295a7e35f1a6fb5264ed94db87d13ebed3edf80aafc67109a48e4b2b97d4f2d64b92b0593e798a1deb5c528c514ac9a8e65e44426373ef3581a48210aa0082beef51143f184008e106482a6e7908212cc128a36469a6516acfd22dde80be73bc017d31420ba120b5d4485a0986187768739b736e22d13677d844737b13d6108d78057104e1c604c6070e7ff196bf384b3dd236250393d9f6b6a98df41c96b1ace34a0582ba8bab5420a9b35c850a44e52b2521a88a7aaa1e119da5e670970a5fa939dc95ba4addb94b859d0e02544450ccf4922c76811c49790e77a93cdab33c9e1edf417a66c5234df266b8a707d2b0cf505579d743807e7c7c6255f8f0b8f8771c25855909b46bd9657196c1262c200feda6d45eb1f2532db262539c528bb85cc552577e43f515fbe3c80f18575920474ebfc172d555f6c7ca59fe5c326c8a77ee72b129b6a9195457f90dd5555cfea3c555bfe1f2a3e52e7f29b688cbebca9fcbdac3f88dfa15fb63e5f530ec8f23382bafff01e3f6cf15a3a6fa2bfcb9fecbf88d185fc1fe68798ccbb03f8ee0b43cc67fb4f8ff5caaaaa2face5d2e7fef202cb5613586dd5ee7555597da3c3ef4fc00d9b7a2be4bebbc293196b60d7432591e62994708d2c090419a19a469795ca91406aac55bded1bb5253fd158c9a6a7b038eca57b815ebe32a2c953f57cbbb958a3db2fdb95af48ff07b401a95168f67d8dd4e6a116a0e4a90e6a92b2ad416d22ff12f6af7b0d4075395c88d4fa1fadc781728dbb0050c71e36392375bea73b9a8cfc5529f6bc525aaefb6d86c03bd5a32159d94664103d253c1d0e3c5c4dee1e2931b6747db3cf4c25ecde9f6bbe6b9f1cd13a483700fa4319dc4a5e6696acea973a2d771994ca6d3e97dd09b4aa58aa2a777ba69339dce97aee31acdd271e8bc0f0e87bef492f541fb3aaeeee613c70882763c84fba6678c60c55c007af9a92d77f4f778c51d5df46878f4d733f3a36faf8686fe6b89fe36196511a43171ddf4f68a9ac2ad4ccff41bd4f4d37f9436d34ff68de60f6952239b9a81fef41bf4a7d3bc71fa9162299b4a6dbbedcec83086c5219066a3287a1477ae5bc51840a3db75de68aa01a1290190df0baf8c788955a0961ffea8d2d070341f0389877647a36fa28faae80d83c8be6c8f2aef2bfe26be473c8d31c6d8b01713bfbd213d2d7e48529387b147507372c9d476faa6b3cce074538f17234faa54d0ae615bc380749057cf7412d0b9a26fa38fce3c50528a42fd23397ab7baa377ac2ef57835a72b8168cb506988a48b488fa14f12d94efb0458e76e17d5ed5aabb98ebb72de1d2f464a48b3b9e45f3b5ecdbcf29b9472c555bc18f9d34db2135dbb8fe6e63bed26cb3ccdf1101622ba4683f6926521cc564a962c79547948659ee63412e9424dfe7622cb30db0dab3d9a933cbd83ec1dae94ef1df885be7c0f5488d4ae699afc2635c93cdd73b240ca53314b260aed568dba5c73244be10bfce9a91ba5937da49b4ebac95a54e905d48a073adf5195d39ddddd7fc12fd899aef1b885f7d137dba83bb905a690c664e1514e50cd6e2f04f4bdef53c1ad6515a4a7a2c9a1a3b978687134571f8bbc783c2f79e1628bef9efea1675256b41ee311f598c2e3df9b3180900a5d809678928bfa5ca8fa5c2c6300518d044baf5773baf1367ac60734755d6e0f630c9cd081109aa00312865cf1303fb4e358cfd047eb6223ac2c184823016a2e7eda6e7116679901ed3806833477c53c9e8362e991e571e5f10dc49be12133186319909dbb629ec35d5c0c393732081b36cdb9c191e1dce4dce0e4bcded00e1e3d7cc058ac85030fa4a722b95001dabac1116d5e38336d657aa571336a7aa9647ae94941f9241aafa6fb0a8007daad6e94797ccfa09047130c7f3191656a02edbe83478fbf1ad336699d2618e845a2ee157f26d6b92b2cec00b730dff3a3dae1b8f32d486b8a95692ece54bf5b694f33699606bc4702353dced86d676d2bd956732f12c9da3417e7bbee28a3ec8e3d8a31b6460cf9157b7cb59261d18891638c71c793f1c4a52745d886627743f8c316fa18813e902184273537ecd59ca2298653af56308250d1ed1a7600193a5078d22c35ecd574c74d0505fae0cb0d103ade21c59ef9fc00cda8853bf025a2209049443adc81a70eee90b652c3204d3f512a71945310e8832fd0be5114c80e6cc8b6513abfd9596fe03b2a954c3442407d200dfd369f681a6a1b08be44fba2b827db4ab8315a6804088c20b4658d1d11dcd9e29cf3c194128c24506ef873e8d34035b40b2df479319148734168f7c0dc80c69be2e1ce8537f1a870e139be187852a90423088d979f6653dabb9aad119b5019615040fb51b68207d20b1f1f1f0839087d7cb81713fff27c5ecde94410608becd3a91f91c8e2904836258af7417ac9a64456c7157f29a8663988633036a0af39d21950b22406ecb06fdec9714771289934a2499415311a414141edd33dfd43ff20a7d641f315f46a4edd03e3a3bcb677dd53ba6946ba192d694e760f7c912fd5f6a9f29507d9300e0aea9eeee99977032892b8d2a767e20fcd499808dad456f2e9d96ad0d3ef1424fd18597a29e8b4bd036b0ec60634be6b580fd08bfc0d1c4fddf6f562e4678b15c45a11db8ce0840849c4600750805df99652f619887f18c90f4766feecce5848d69c3c4c11949f6019cb30bf7d8396a3f00ca6067493d4875e4ad2696a3ea774d1734c1fa520a9a620d79493ce6cba019272d25b4d7f43749a523ad91f249b9a760668714436554ae18c4ca72050f82277e08be427cdc96ebba4284232c93f2f3ba01dcf64fcb3e40931b8320acba03c9b0e20837a21ba1508296750cac7d8fdb8d3ae22f7d557c0463a909e2a6a419663453417cff5e045446df662e2ec2f269ee2551308ec761308ec6a8c3a456dd7e2f6de6c868a36beaef206be70d68857b37f31f131d2866932906729e5679685cef25c0f68c74297675086b83cfa768c9760217ab9ad0d1c85d88b91871184b65e8c3cc74697afc614c3e9b66521215052c7423575e3ad841a342183b9463675e3e3084ee9a3a7703eb23e8e744576d8353a0c253dae91fdf1120c253df2344a50b2872ff2c19791e52124d7a3bd816ff76255de678a816d6aab11efb4adbeb509d52c0b0605435a05b60d082169a209264e8000b6e120670c4cc304546ea2f868d3c98b442279d1697845511445d1166394716ed3c6b25aaf18638cf13146196514da64898e4855e38f469af6ae941bcbda691f8d46da471f7d1b89e8888ea83c9f24aa2fed2dc99bcd6bb3ace6e4a59452e6a0f2524a25985c4d762f269d3074e35988e63c1192c97ae5f3a3fee9999ef7a6b9a8d2b200d7acefb2b48c5c1c3f6300d1ed764fe8b6a8297e8ba7f0969a9aa1c553788aed8d164f2175a3254e84544c6880074f7e0842d334a83961016b094b1c217f70a0c3114d0845a1890a9a24217382c414b2084a5060fecc9f2431ee63f26489100e4964387012646588206442c8a85c8e528bc1603024ae272329bdff61a7a2e776df81d00e4108f590a40510f32789123260c2c4921844a552fdcd5cd5c4081fd309501c400209231c7181d6e6fba5e138846d5d40bbedb6621d9359e0f6d08d1a40c2481048f03c264f7230cd8e78e288274990c1c80165e205ab950cfe40891ac4981022c42a88257850c42c89c8872492b8c12f2c2183264d700282274a86624d782067aad5b66ddbe5b66ddb36259c724a4d4a09653225138928495c60fe285102190cb61da129a89831610326c09a8ce089105b0f4b14210651c205b21e7e264e9424b1446c453c7f83c160b098eb3dd6d7adfe34e63f2642513490262660c18418640920926cf0bdc984582c23f02c42164b888650cb064208211218605101bb1d4b090dcc9230917d40fef0d08c09e77cc79ae74f39e7d662d160c1b318da55e458dd8392034ab39830018b8ad8ed5843311e0d6a50831242f8048824b21f55cf44c9a518d9543d93a25d80b46d52a55fe4dfca092a8fe3cd1483ca8db119ad0d3e2084f1c41393491cbcd54af5e2bdf0df2673b9512c5cf96e008d72e1bd2043c511617b1c7739e8502c6889ace3717bbb36f840d19c783e8365a35ad188052d91bda89d60e399401841abf56ccba66948df268d7e912c0ad08e5f4905c428215c49183b2bb759575d8fb992e9d67e88908c4012638da0ecb17246739ba816592107b4e35ee41605480911340e24b9f23048d3cc18d0abe99ee11905c9cc88d00f57ca88402143ac23282142e340ccc4d39c7c14234241b1a1a16e75632b9918a4310931110932fd2033191142321b224a6cc8c4d3ad6e6c25c362b56ce4e478453cd98312e54501233723b651c18384f141f6df525e762026913ec0c09570a785a494524a29a594b203579a3860e2a9252027f80ce11808a6a6c94b29a594524a29676976022adf8d7856bc186671b983c0ed4780327dc1c93cf1334414a5d88788e27633aebc1c1342e87634b8654849e1993c909b08ee9b25c92f5e0d0c534e08e59c734e082543295b4ac92d802a08655acdb58d666d5efcf87ddbde7befd5b289c1d64bc208212be2e8991c3a6a8010c2586b067b43c16ed8ddb07340028629010220840d2184a9fe68f4eda9b63736bbc3c4da4da9194cdf9ed2ec0dd3b7d40dd245dab33e4c36a57da469da7d94ba9cdb0f561c9aed76dcfe83a4543fb5dd52370c06bf6d70d61af3eebc18789e1c48b3cd0b7f187b41505a22b23722f2060784c7c96900a35433150ad26c2e544000385018a55f94575b2e7ce0bdf75a372aaf06aa1c0974bb7c353407dfcb2636b2cf42660819f21f4386d0a6f58a36af1d72d378c7460b056325f9bc66f8ea1450160d665142b777181238e051951ed0a62a92f94514440e8014b45f1f4c0958042ff6f9ef32421bef7ddaf7de7befbdc74f0a12a908e93fa0fd68d38d8343478e19db1c3a74e098e9f87f1d3872cc72e0d08123878e9c570b088f8c6726640811de61d8ecc50c078ca783c10e6970ccfed967b3fecc00d70b50954ceb6513db80468497d2b4f73aedeff1ddc0f7ee05bd436ba3b97ecc0c6fbadbdebcdeeba6b7375f369e665bab7eaf1b9c0df59a851345c7d60d1b769010d253a55e8d0d2aa517035f71a028982213e033ecf22bbd219c679bb637350747162d4e4e9429a8b44d983439e910cd000000410093150000200c0a858202a160341c877b5e7b1480117a96426248944ac3a12447631c454280006200000000000080cc4c89885d01a288a83f0c36aabca9d738a6452a7926df2a073442e3c1abacb4c80569a3ec7aa5ab3fd71ea553cb7b6740039901d696ebaf867c2a6ebc79970fecfd5f444ffa7892f4871a23af129176600ecc977ebd212fe76478472333cd0e57d0610af97f55b3a8d3c2dc3772939170f3afdca116ae2c152d09f347dea7e53c444d5a29352f496a02e55fbe0be2bc59d6195e523b653b685b9ccc5caa24930d37bfac2323d7208cfd3cd904dcc919d0bb4d706ed50a980840117ea2af79e3f7a8331f1b41a3ecb468cc8a59c63dc01fd79db778474c1599abf624323c0128e02ddf936ee829efe6a623130461006df38d8ec19d961337fb1289cc3ed06e4fe2709610c56819c225f1c43c6c674016c72c92d55537a762d4f6af3b5316fce7d0389d0599d542927bcf64cd70e73fa7ead95f969e47ac9ece46c428f49e0e6d40781ef72761c7a3d0c7b22b62834793440d56b44abca6e91f18f98713c5f01f45202f85b43da167e2925b1e7d00bfb79fb73e62058eb715a96bbfeac77b7b6247c720a9f8e105776fc95c1f2034d240aa999bd3fd10d30347c0b9beb4f593af0b2000abe9e104b833f1af3257c22607776427a3fa7d86035909ffa40c9174aa80753c08f086821e6c337be3ec1c9087bfd36c74f71b640aec3d43d3b1dedeb8c7cb2f384693acbb57f82dbdf971b509edeb09497b70495a616e54068e6e757d887b6c88d3e69f3422bef93fcc4d3bba8ef3b7d00404386e8f4944e84ca406601c577c158e04f7f01057793a0af76cd4ec0c1c9ea09f58f173dd17adb91c1d5cd08598e58449572caa8094fc268d253885cb7fbb591ae192f0c4675dda433baffae171bad5818b3e382c8ed72c6d67bd0ef527a28587a692780fb73f859e463918ee255a1fe43c761cc5035e0e666198e4df531a8f4dd0643f21da2d3ea675695e5736c68214153d0316db1b9f7f63697182d03e9259e9c45ddd29510bef44be984aecf4cce5b776b34c33f1b14f39b417ee269adcaa1aff59daf8bec4fb6e54aaf59f4da8508beed5ce226fb04fca930439cc5c2a66ee4ec019f75246816dca6e966b4c997ffc26005d196d36651b10dd42acc3c09f90b72086bb3a1d59dee36f43a5a9abbbc2ba2ef95b861f41ad37dbf15af4dda792a4a6ebf5890ca16e19814bfe6c82da11a8bcfc1b22fb93dc88f8e54ae2ecde1796cc860854efff70b666285c5b0c1f95538bf48e1a7165eb64d3dcc7de19e16bb6c1ad0b7fa03adc6117d31e3f63d1e342cbc55def9e895e97f48d7aa565b8d650939e634675a0df12c53555fc8d9344813925c524d59ae2542c136b6ba8cab54da337afebffcaa3acd08793888ea9fb6a0757020dc62c20353b92b85da758c3058a96ac863f02945025791f776f36ea31e73be1dad041491b7d103e5832664512b0941b1b79dcc1b35a1d7a69b44187445a3a525c1b47d4fb6c9355b83be861345549e51f69987adc887a868a317e13e96f1884a937b4fb1713dd5c1d874c33d6a33c63791b58e761a823d1db4cc56476f13218022d182579e7dc0b2c2a75a91817c5254a82f575c74f863178af04e040de2b8c0fce7a2d0280354dc39455b05941ae9228bb60e3db1c7383bbd19cefb7d962d8b74c9d3457e9a11864b4c893638cd63259bc7d18714d895ec7edee3f873955597e498cd179fbfd844b0c7fefa044a1b71d39b23e4e4c3d820b34203c0a22fa065c0d759409f3ebc78e93bb5c1e56d62dcab6746ca5d4c43bec341ae9b1fe6e08015775e963f20cd867e2058e3a2570faee3ac5a29a3bf6abcfd7cfde3e0f83fb74d23f4119fd7785709f3a3a03acfeb539651f52ebc7a791d5b85c4b2543444db1e0412a8ae772ba0b2383ea5bacce377b9f607c45ef68533d138ea4c7977354f44edf83fe4885a2bf7e0a0a0d928f9c0f2216a65f72d307b9c519876985c71c3e930fda2d35e99644f68e1171c56a12a3da5e72287227c516b5300c457209516addda4e1df7951cc0b0da2a4099b610084b913398e32be2e613329a4e05423b0eeba8e6e72cdef37319e7642c19fa5fc8f6d923db89a7c7ce9077ce07ac9f482380c0de32f72df4ca64c0a877143e76d44cd4259bd9f866e1e1459e69c0c81b992a8e9ca6871f45b6e269526dcea8f309d94ae3d13be1e5c9ffa5ac0936fd126ffddf0a76e5ab62b8371e49e245f08af874113714c966520e7cad3a9b97339a58cbab47c080ca59a8c69945100bb28a2c4053ce1d22899ee2b4f0a806125bfe2419afa41b8176596efa489a0103ab0a167c85860ae4d15b4c7607042c38141fdbcacdea6cd05a96194372d28ac1f251d5a7213c39929ea6d62f3c968f23a281601d89d12e456461eeb707f14a5afa51bef6bf2dbc15d3046f7e2ddf83c8f1a16ae443cadc6a797dbff72c870fb0a90b9e621da4235e6703e91c1d70e67598d3cf2e738e758497468079dd3189ee4aeb845db4e3d9604de3fd6ea503e8c9be96c88029d61135596015e0b9732f4029401364caa7c4661babce2ee88a31178470249a35d9ea06ff4b5aa481f44042f9e7f081290b88a0aa8a8ccc9e9aec39a8f508e461a4ef49d77bc38a6e044e26530e32843578c6d7a0e19307dfc81e521d10617df72e9e186cb79459d587170520c522568407f88343650afaada0e39cfeaf68928b91fea9d5038581c61641f5729d458361c0f54ea408f6db20e1477509a23922d63dd222226a8bbe9aacd278bfa5cc1c8d32e0c455751f5adcadb4be20ccc48072d54a6b63cd7935ffb258e847ddf502c840256272abcfe49929a562c4c39829aa8fdc90df163ce7bb2f4c49fc1114cf6a37d42c6925f0a8d6d7aee78ba9af9b05eec95621682e88fb4327bd40f1a9d7ca69ad8afa6b3b03d00d63f957f2412e2e39090473de701fcc6158edc683172a2bd7f10d9e81159d62b3550f6accc32e1f586a17ca8a87d6b75f8fd8b7ae23d5e35dddabf99802eed5dac876c388beb2ca8f0daa8d81aa192b7215ee59b5b2af5a68a8aad054f19ee5dac515f1e54e0504847725b70853ed2b3ff908b90748b91b5321e0ed4df97b26e62c7c9504590aa71c7301ffbaa1e32cf9363a4edf1e7ea0e8fc2131dd579c21237b4b69119459b7474c3af1863ed7937e3966fa986fabe19b5aeb7bbd87148763de70f9d64f6811d3e8e0ce0e05c5e62af198b889864c76972403f2e77d698cbfbdb0d35c1e4ebb1ccbf3c6f5c20c5eb1767daa1d7c081ec10d102661e4676fb8e378c05709c6158da63889c77b1e47af445655307f6fef165007cf388616d7816d59947c5c3fd8ad888c91e7f72e3dccafd06a1d5f3e6bccd98893142191b7ab3644756b9c2378a853e5a47736c8a21ec5e0e201af14290623f1a1ecd4f3e7302a3541b8fc896b0ebe713d04d03a85152d824f2a479d96fce279b7a386fd2d1ce1896e116240e3f1663602d1cfb0a0ade69a593998c8274c4ed4b3c4af5783b1d2da9fa958a5a0c8ccbb924e83dc861396027e4cc3bc6f741c0839e153203e9a11593357e0655d962a123d3693129127445099e0bdb2663073336708f9e57bf527d79659938f212184b6987819c3ddcb3d00be3e4845a2512e55088e10945ca03fcafc607d8742d0d893ff32a10ec9efbc9e0cb5915d7a50a6ed08fbf32625c800ff87bf92d385e0a9617eb0a0cde429c49fcd2e3b02358bdf74d711d8b9215bf4fc3a82e99329e6b085ca47633b52ee086447f480af4b370592fe27308f453fba42a569f3899805166ba898d3892938ffdccb2a5dcf38ab80d6a1b00d7849a671042729812f6380403f7626a2e24a09ee2800d09c3e56603ebb0fcd2cf129f0355e1043b209a652df88865a5e1e46e2f8611cdd60694cf6714009f758291f33bb5b32a3116fcde2fae46a7767b6f0d9200b2e8567d2f8fc57ed0dff36194fdbae1744dd8d7f2e5e2a81950fd99546109caec420e4c49d2f79f7f5ada965ed3b1843d5b5086150855a0a2b26931d21a66cd3845f90ccee0391a41e507ac44065b2eaeb495c9dde79c3ab55b575f174d370a1f005c1b9ba13022427d21add438d15f0d3309d8e5fa32b22dc1f57df860602fd25d5390dda830b09e6620f8081081e5a93aa229d080642a36e663e96971570c0498c88a7a07cd070ce43baaab48cb65d6f625b883ec2df39abf828c8c947c32b7274c6cef04e53b2419bea843f56d04167f68c9284cf308855d7953f87fd3aaa8ef2f2e46427333e070515101eb0ac5c71c2a8d242adddfe96de255a9e7de2b0f533bec8e641c530e502414c02e52202add7fb04db8446f743d3a1daafa9d8e30768a300cb1962577d912720050e08dd3489ff0cbc3e415d741b188d0dfb6febad095c46821e4dec2d05653f85fc9193e26b9dff1e4f17f90ce1a1bc98739bbb847dad131ee7e0a2b8410d31b5236dd49768eb1a434b3f1680afa4c1546c2e6a0a807a322b2cb39a0a7a118810cd493f03aa24cc372d4c58178d8efdcec3d8a177ea33eeb5b2be109fb796a3cf310239d32830661212a8a271b6163ee6007a594c23a288a383e3bd376e6cdf1b17a591473d083d32d1680b4a349a2acf7425e59d6636bb31316896314a92b96d76bb0efb6126a02939d4bf45d789c83f75aaad519ede398355a2ae7d138d2a900dbf93612c550688a1ad02b0d065bffa65f8c0d582eeda80f42b9dd7036d159b7ce47bbfa23854019bf34d7f1ce7251b3512b0d79f4093ecc41b58e4270757e4b3b86ee164fe593bb9dd80da9900e9dc855899c046e3de1b6915be5850bd35f26ea7d0a83e90d71227faf3bc50e2570f5d96c9fa432e41e52bd95323c5d91d2d5067e885210be6c85bd8ba0084b1fb5e550a72805661ebc3b4c691f652c25cf55c62049708f892aa539565026285e108e37142a8b6beb53a199f1b8b89e7a66c5214c7e8faa5ce12d514d0d0684c7def4d79e42b4a6d45024f0170099427d2847268e602ddc7385d270c81faca903bb497d8eae101947d60dfd7970b62f3b2012bce1321de810fdb3fe92dff4e4ee29883e8fd6f193b4d6296f6cded598b92457ea94f32a7ef1cd92dc1f18900e8b3e33f68a7b23a1e31080c70760716ac97a2eb6464236b5e283dd9354fb9b7a6f715176f2e4636548f38d1c76d1057b81006251a932bc9fb5a39f01ccf8e233903bfd38b14f9e6faf61c144bd3becf7c9fa6d68d0f43e6f4546bbe9021a46f1d9775f9a66187d37b9fc2e98c9cbee187db2d41341fd11f9275dc037790090f4c643d99ea8dbabc0c92dbaf97667b5e16f8eaa81539b2ff43095644baa520637f51114f9ab42fc7c7a36e9cdcdcf6aff7e8d7cde54eb53cdc7f8aa830e62200c9eaca301a8b44699c228ad114592333458092460c13086568b7ecd2bd016882e9383c2af0280e3e1f12dbce2ad70e835b2bbe2bea830487ef430c977ca078e3bc52646706489d775b02bd4b5994c8d1edce4091e39cc4116bd5a57787cf6cc03d5a736ebe634bf3663d948fbad13a2d540d3bc245295b2b848066239df94c7b4caa63076bf8ed621c5c548826d81d9f6c3732a00c2287749d00bf5a6a5c7c60a676eda8efb3a009b8a12645721c71555ef00786276bc0cfda14cc8742d262e8a2d538f6bdf1aa0e1179dc2ff2855357205fd4815193ee1bac98ffaaec181726d5c09881fbca2fc918ac995936c4aca0a7b8a1b6e34b7ab3780265faaad2df88ecc47d17a6f228e2ff3dd4648306f949b5a6840a131f111bf2f02c5cf6ee7375e9b341ba50909914948b996ec39d99114e34eb51ef476e6c7814c30932e175c2042c10285f824ccedcd3899b604d67f1cc7a142ddef082b2677e63355af19c139abb85dc68b5c12bbc7e327064442d2806aeac32cb137fcf5f0d6d301c56bd3a82f95c1893ecd3c1339c2378b8e3bac03a88f463a147bde21524ea3bf111d82df5f815f349682c51040d46c483783a83d29420a84ead44b05ee4a166cfba36b12704b78a79dd7e8d4c00c830c86061d74e1987415e2eb24e3da66d44bcd7a9abbb923d87181ef732b82004f6397d9ac1ba6a06d9350348d11b032aecc7d39b47fe499506ba37061a2eda9a8089597783024c6a90737d16835ac73e262902695f0fb09ba13d4bfe3bf489ca492f603ff32cffe4c71c4b71d60105f78ba23ba299c36e4d52df8269a548c1eca94bf54386c6b7b2337df45d7f4109ee80302119237053653485021675d2d483f130d4655d10c249bf271cfa2bdb0f971038bec95d9c201235ba44377082e5862090e329d3e27eaf585916b4be8fac23c6ff63c21224ada8cdfdd22f8c05cb983ef1e234565c2a4eb7da5a029f32cc82cc704ae987c3d86132a8ce98463bea3810e03c709705189be36ca038de66adad24aefedf964cd7544cf3ab346f9bd881de68d507fcdefd270788cce2bc1349f6389d66e9cd70524db14fb86324b3de40162f795d3da35936e844ea670950ec1cfa1b58dc8e9fa935742d8e0c27fc92aceb5fdfe6831037f09ac367a6511a4b5455014ac3acc960e33f67b7f669bf168aa0d98e01e75e0e9a174d4b41a41d952f7390f9ab93c1d2c115c08f4f439ca3e30ec167abeaec18551b97539332535a9aeda5710ec8dc42bbf4a73f8cb12a90814b122d39f0497b106eb802e5c23aaf179cc53de2d6de682f7250286d41126ec7c098cfedc7e227ebf822ee061f22fac44f19c9107db0e90bea52ee62e66d3a9e681bf20cca2747e95f5f80262c10a9a367685d3a0cd42ae3ea267314a5ee276e74a87f14fc5eec8b03347a073ffc4c9b4db49e4a74392893fc3cb46028e263fd817860e035a33f30d0d9a6d771285c5346f38601f457a756e25682dee0b45971cf0274dde01a43b634807e1e84cb5c6a06f7aefaa2955f5071fb1d045ef1a2576353e8df561f55bf22e344125c0afefc6592d03caf626955551f598250ede74ae0ca8d9f4113c3f1c9486bba8f58c1449d9d1075626cc9afb4e637b6bc1f6402aaf1f322a6b88ce08eb033691e7e0ec5b7e0708d88e8a67b27210bfd48b7c1222340cbfdb639f362deca0c4f41811324f3f482119016bfaf454b1b57208ad81686dd136dd69b5bb85c583176290ecde3b0cd09674bfcc21498bb22c179693b8907e9527c85c79c604419b34ff52ccca51ef8e5145d4a6bcbeaf83e4e227d9ed23e00f07d870e0ac740ad3c40cc35474fb5a1663af1689fc45b2ec22dab8211ff7ce66b28466c0a6fb2c6a3a7850d60f5015cfeae7518484438b313457d6741606e37f7cd4f2ff91e909f847a768ae18e68ca513cdb2dc664ee892df0b30c13b13d8ab4c5a1bfbdcf62ea43b2101ba1c8d0241d44b1156f438979ec4f509e6bb943e96b178e684bb61c12da4e7a43a0b39113ee7c4e34cdfdae766a2433f932c978d2c35d47c6208701f00037d80e017b57b6e33a98e866480bf531fc92dd82f914920af0dd96c2c233c502fb6981ee27d07431cf106325de81f48a925c4c7d39cf95f50bc74d770db35866c7b79a943266b4a6cdd345527e8270b648be17de6e60641a635661811aa641cc21900fd2cb5c04b693c51df3b9b2be758a6eb0bd2a07d5df8efce70959653a604cb2f9d6d0e467a73e7341aa20633685c202e841f6bb3f7bb7f1b9326c62fecdfd7745dd955721ba2fb48c13e85e6cb7d46d09ed9f7c278d7163f381d41477c4576cfd86a117610384e9cac79b1e6b0aea972c549ebc612642002016c700b1f610b8c9ced1d89f34820dda58a3852572caa2907dc96c90af7e353db508754c1db1725481a29a1e496b4bfef3b22b23cc108717c07cceb2c21ba0a41cc0ab1586b89789676d49cabe2b7100a3d738dce6e40cc31c2a9665f17e69676f4f82f6f65778111132521a9209e68b5310ef0ea05bf98379469d81705bf327456b504f54247f6991e8a384ac11066b61f62d4ae77ce6a2b310101a71349fb8e5ab442f04e4bb632fd39fa0684ebf61a475229d5c5080711bd91687440474108be39ce9a78ec50945dcc883d67e523e12f06bb44edc222f9790906e91a9db0d929ad40d101688a497973b45c98c8f5b2cb18b6cac6c06768d147dd9241ac46a5fdb759dbe134a0ab06eedd0f62ec093b0b8ee21f72f9291065f7a9104e008294c98b97d655d0550dab347041da13ea97890f3db9458e5647925cf488f0832daa5bddffb75c35771f174131df5528388e488f87206dd9309e0980627582e947abed8dd22093cda2d01a3e8d4c41dbd271097cecc79692f7886ab53511a85066d07378f0e97e0c011012fcf5614ba9c4f12f1c8d4f39594ecab59d5d9f5aa87062ac24444deed4000b0fd0188b9a93dedb5ed6d0ce9d74ebdde13af8140836092a08e3aa34cb69a46e8078c6b850650627611044747da20f0a8055438c7307d19114ddeaf1e2af29e28120f66cd50cc7f6899e23bb11311915d4210cd03d5f14a2a6cf5bbb3798cd9fba4a5d6d9208fd0767e255c5e1daf7df71f85cc8af04e15e2ef694c1c3c387ce5084f98ced71a769699de2534844606c1c7025c8dc1b762f0b72bff25f13089f1b611c0290e39e503cc906801bf981bb06970902145e745ac6f6e5290db1f3bb7d5fac6a84b02f593086dceba5bcaead6da902c030bdc9255079f3406e53cf6c2c7ae183dc28978d7ee75af71fbdc2b3c8a7fa3daafca02492a5507948c80faa15659e5882bad2bb2113352afbea574d520e5495733a40fea05b70791a26a39fcc6fe380775f2029411209a06d8539528edb024d8686755e0deb02973f700986e625cff752ae3df0b4704273b062ce21a609c857cabf4360b0921d921b964dc1b89465b652d8d3118d4e632476931f096db46627aa6fe54047168357630c19f1ef186a4f347999c607cdb35091d884440998fad1bc63e8c1ee0f402d981fb0a03167ffd7037c501d5caea1f8cbf0a79eb3eb1c75156a5da3694443760f6e06efced69ae90382578e6da6019af3534e680ef284d00626b0a956e72087b4f721bbe95aa3ba5889a3d42da6b9e4f27b50c43c873cecab6b82f96dde4672b3c33c2bfa7344879eb537463042371b1ffd972cf67e0fffadaf9ac3c7eea212f69aa98e335e21e7f0ebe056c1d257e29d6a392c51720cb32e29a50f4df392e3d809f4bfb86da09bad738884b73958782cba3b58b0e6f7a3f5be1cd2e74592b80bd635b8b19ffca331c60911f37e990fc271f47859583b8c7fa70b900cfa0a5823c24be84603935a6e034b249aae66d0de690756656cfa870807e90dcf4d899bc9f2d8cafe2ea0ba943639a21c87fa30bff5d7d34392588b0ccfb1977763d0c8181ba18b9132912371d39c3b3a4446b158ca8e7b6696981c09140c76846f7afecdd404402fea9d9b91a73c99d2d974f7af5fccf0bc7464fc938e758fa7f2dbc54813dfff6fc3a8ea2942be6fb2c16c39336363b6473f762657ae1ef495d0cfa16fda3b09ce8443dbfe114a7c65513d6105a2558b31772f21e3ac129f7fee831a7ff93731459b27a5108e08c5f9e9aeefc9e7ce17c88118c09a47edc4f54e459b7fb5585d36ff484e3b6c7ab53e626b87bd9d5114a140c08d3f09d32d5c490de8152f5c5f86b3f8c5601712df41ce232163940bb610795f17a87c72151eb08f5c07b9a71a620a046768b79b7db5e73bfcd7c47a1e01f1b326d8cebba7e94b814cf37ccf454809a768485e0e3b333d0da6e03fe1bcb59fb5fd7d106267d55426f86fe542fdd4112bd79237c0eb7f7b3623533c30b5d062dc60840d6f193e2f46489fc45f231238785417b1721cd0abcf9a1cafd1d7013ad5a0362e40eb0671d01aaa1e8cb53a6f538ab89731ffcf97d03883ceed9fca16edfe2ae2d256430ced7c9fa730c967620b2c59c3ebd0475e69a2c48d471bc7e1ac7b5c8350493017d8a30dd6283c7c499f371ab8dfce55c7afb49be1979cf1b8efd52ce231888c8c5df3cc3e9faf8b897ca2f6ce53b05f6f61423ffad826fced124a340fc83912fa06d263469455fcee4fb06482df194743655b2fe43f937b0801f71e5ec6d8f86ff3c05cd2ba97a2bb7cee3b77575cda2eeb1fe9e1eba644dc308682a984dc72f95adf5e01b93abdc4e8839dcb8516624a9cba5b6d1080f04cd31d94ca9633d999b25ef85f1bba66436de41a45f59ffaed7d966a9d3b8ddc0a9026e6005efce7ed0533960abfba1f7654ace2dbfb1d23ec3271447d76c01d9867e11092b718775fd581629c97009b8a50799753cbf5c6606f9fe9de1fb43d33980ebf517a5a754cc39ccbccbd45c3d9ebb3bd38713fe9530fb8cf9891cd18ffdf565469b81ae9924bd02883c318b11070a96a0abb351483674e619ebf1a82cdff6f2b3795cd0a0de80e19cefafd7d7a2b7740c5ed2a3cc1c9f058db1c5e9889fb84cc40cdfbd8afb1f1518a9507c185cd2a2955c80641f1f8d815ebf382c5377e2b38111804ace428093c3a9cf32282f570b7916f9fd1c56c260e67dabfcbfe39d3c1b4d83ae4ca770d949303e2d22dab76fb0d723dcc4bf633b5d2fbedd3aa58e3b7e15da1bc3109a2df29d3b26a0a04ba16c96eaf2e5b7b7ee382c444b0f75b6eb8a3b963d06986d99f98a012f2f0cf78921ad61418b245af64b401ae26e2df4d868c9a7fb987578b8b355fe21d24bd21bd95e157615f294c99ea5a401e02979d3f604f0c9068aea33c89e86f8cd3736812d9fbe8a8ddd609199239999fc58aac2cc0012cc1692e4e6b4bb1f9926901284a381bc2e247d74670d76b9b410a61240e72008acbfdc7463a677e33c2704d1425092cc0a379f647a93cad8ee7e101b9a639f26b4967a04b352715e37abde3141afa21cfd6051301d86be5bebe22c6c1ca5662249735b4b801d9bc65856cc3ebb777ea716fc7c9a7b1a780dbcc751805e3cb638784558ac3c4655313bad71e8ca472d2c61d003f7f113e666f69c06300bcf78f544353d2c13e528b44e4649ab152643a185c8252096f92933e0d45a4eedf9f2b6345c12c1e2c525bbfacd85c63c1301e645a541d7a91c12662a287def63ad345e9c2ff378af8d164eec09fc8ca32349a5551f553111314f1932a547b5ac889ae3a671f72a3d0580c0f18c4562abb5d4ee2b90e0d2155d3b03399b453f71de33075f4c523d4aa907dea43204c573cc16186304d7c86c627830424647468c188b437f0086910f734baadf6ff3335ed89f941630d789c07bcc3e360e1222a27018368e8f96048d5f2299239e97977d7a3fc0932644849829fa63425ca6ab0d3f62ffc483f91737dfd358e98116f480d2bc7866a3903472e7d2fb50d490c51106a04a3ec262d7e3a708b184c95300fba72549ac56d222911d8b8e254b82dd6754e1e98f35abfd3e207c5783d19fb46109832e7d558a1b3330298eefb548716805fd478c68e865d259aeba546bc9a01397ae444b745cd6033e2214cbb6e4c802abf0957862bd0240cb94d0a6e4bebeb1b2d56908513887095e74df8ba30209fa88333a3984d00c0080be8e55e945bca45b822d30a0c4e130646ed0535ee4ea4abbfe4156f89394932b8e0cf12180b8dae500878178c0d5574d7f775e5b9b0f2ef86ad0b3e1b0721bba3dc9cf645cd67874f28bb13db883795988ccacec4409241770c4ed6e3d80d8c777aca29afb046bb7a2d3f13ea1c6ccc6fd7c09f9f7d24c36e4e1825ae102ad1742bd27983ada2c913022690bfbe510c2370fd1febe8726ecdd30fc69abaff5c627456d62e434e4afb4413c4bd1f27974db5bca2ab0039eeccc210bc1b4298947713dbbb3259f300b183a4c3cb62ff47a721669f0a27d0e69d387b084713fe80d629b5683a2390e470c27c748c7a31d068393e3eb1bf3ff1bbb71b23ae7c3137ab9e02ff77bf9fc5b5046911ea98efb7198dc349fa3db3280e715ba5b43f36f1f3f44f2902a13fe3a9a77783813020174674f741a6ba2cd4141f35d754228922dafcf4b7d76a10b54048e3f307305a696ab5e2184e1b530c18740aa6907abd55cd8cf11cca66894a15178c0fad8ccf61807896f5e90cc7b05cd0d063fa4f3aac6f14c1399a325fe988cfc59f28c223a8d9b5264b0a557cfeb685530a5338b1ff62d9fbfabda97c7818bf5dc8bef1d27053435bb291ea7e5ed049f15d30eb408afab35735fcc7e93926190c77712aef9c4b194374c58dbfc630afaba0d88d858239e2d92e4873159cfa4f636bfca74199fb6ca761c3f66993f24e78664cc78ca71dab5c5fd27c951cd1f9e39ae5c83d6e3f1994ac4109ee9eaf546e7c03b4d64e96b8c20febd5f916dedfc06ffa656a733588d0b5e5f6ffa2bafc569285445220fdfde37295eac81ed0aa55d3ca3929766056005b24de6544a198df5896d15a9a3eefaf52b27dd05b581993fbb11b2404fe1f8335f3f0234414e113e6ce61f474db179775040bda69bace1db587b9745d2a54677a6d5ca63d0ef9a1fcc82924761e5b98b342bc609ee3b236f5df4b074a986642ae54676f775f4f8e642265d5682519ea0628cb9b5cf640a98ff2405d05d48d090b1415e1cfc2e97326b9f8260244dbf1ca6be8b29bc1711cbe516cda7500cccf34bebdce1c1d6d7b912aa7197658af6cb2881fbec1677b49d236b7c495b5b009cb327684d9aab13e5e217830661c1a63a3f2b43f005d00af8f918d2ad5638048f9389982c892b047241ceb4565ec75bf91f5bfc7d2ca74637cb0bbc135eaa994891eb6097370550bc250b7e31cc7c4fcb4aa82bda256e98297c8b76a4a205c09b74cec6ec48be9804851d2c94a9f01ed984a3a47862b4df1870212e1b35059bce22d5583a604ff398914875256a4b688ba42e1737f6c8a966454c3281d82be3bbb9e7696d90269d3eb176e7099fc48f29c26cfd7eb8db1eebef8ac25e1aa341a83fd740a42f794ce6a22bb68c47b77c11bc4d6deffbd47eca7397f5cce79c1f7c2f81bb53a6598a62ce4f39370f3e2b92816eb86483460ca65dc7f8209ddf86905eb876dc613750413aca38d97443d74940f6226aae366e935d9180fea521423c0afc32d66715cd5a06bb708f70d1d85bf791a96d8ef56a588c1a3d9efa7a8f898a407158795f062a4be71ee2265aaaa041aaadc56ac71737c1a8adf38e7b25bca09575694249394da1836e45bd0bac64b8141c175de9b525b1922bcdd1ac747b6b0a8766274049565ad201d1a9be07111e41688cf73c1584f74ee621d6f9b548c4aab76727af241031b5a49674320fa2b9c0e629d82bb7d71f7bfe68c54b3e1feb61f9b89965e49a070a108244580ea13207450080a7c71e85605e11ee4521cdbd80b73550f2aa06422fe84d58aa687b5cfae8b8fdfca9237e0a69219ba8a18d5c129e3a5b8caa64e949947dff40c4657d64f4107a3312c5352bdc204c301fa442347e059f39d8da31d8eef3c42856f3183a4d999283e408c422db9c912677e68763b91ad4ca0543f732cd79642a4b5a487a0c173ff7835aad2c92d6bfeee6f0da6ee46cd537bd7174c4339716f301110a4c999334a56e489df8e2ff914112a56a1e60b69184d0b4f9b76403aa71ff7f778ab7ae53e9d09f2ecb431675df372ca5d9ae58ce8901ebf4bb74daa81b2772802c8bb40aa8a6725048dd6029e706018d36fa7832bb1bb83fb9c128f802c1625f23a555fbe9813bfcaf841edc92ff318998fec2f10b5843412e6074dd499bda6cc396cb1ee180493e10cdf67c205908d4b17795140ca3b2b908bae1fe8357ab0fa27187338e3d482a1a62c1c7c7a242a077270d17cec50807f7b5bb2be80a82a521881e3652006671a37a6b596bf718e2f9a634857536d92a218d2e31eeb96b9a33ba4a2011567f66536d610f37c44ab12ab8cae0cc30d11bf6ace12ba207f1c8554a767d7a470df195de2ad3636bba2adbb635fa8c7c58ccaaf78ab4fd17301da87affcffe80d0acc687534b2dec9f892db370a5a3b2673c5909d69a1c88ff6c12bf1a2dd1ec5d3d6bc7071271e3a89130a0b19e17e3aacc499c32d504abfea0eb00c9566d9a2217a0bc854fbe03399de87d01779969fd0ff4793657cc2f239076c8c87783d0c797387dded6d728ffb4930a6a0281c55833dfef3a37411aee80468e7869fc06852e3ebf978b6d933d7a0f33306e2b37ab7190de6074ee88eb85bd0226560beaf96399e040440de8d1bf5667df01e5b52037524d340a10a489b3d879b5924e80650f9637d31062ebf1d2d282581295f64a23115ded90cabdcb8d16488ec7cdb8bf8923701565cad18da95c6478180788543244c440c2b89a484c6e90278de75953ee494fb5f4eedeb5304ec86aea1aeb746aa57e979a968c00326209283f23c385d5b6d545867486e7020a653f553383371525afa195ae43ffa795dbaeefa98956f0be8e20a7d33dadd5f407dd70f1cdd5485ee6d2f5b49479b2a757462a6f41285213f41f74b4a597413ea84eab86d7652b2177b3515cdbbc4083ba7c4fd3c94fb5a5014116263b592dca3ca7f3272099f416858cef73c9a756c047a98e79ed1d76f98f6e60131b027685def3be6262f33a25556097fd4eb6f17246722b3fc8c169b09ae8b783fbf6327caa73191268d04e8d383e17427d5f04f68e5119136729e1aac2902c788a10d2f6de3e4f95b6f0aea5aaa5041856aeec53256613fb9adbedfc1a1b0236bb66974e5155d7c1046be4c3e7d8c6268e186291b15e3038fd6da0989f8f78d47efbcc9d387669b98c3c77c111b03c8105544314c08fa7acf9c3cfa1ecf57f5314ef39c379a122b0cd220a0894a347f32418d2d22ae093f8c1be03286002045a5e41e51d2d92cc21c0bc199c277f618151b9da0b6e818c2ba28248cf313cbb988fb2c59a53c7ca2646873561b8d4d876f5108f0aa9e9eb48df288b3470189d246986572be4ff4c1ce00f35885d39765ae6ea7d3e60fcf7a1c3879064f6ea7bca5478711624886c10e47d3948b466401b730015e13a27e2e1ce73bf110987d61112543034cd9d8ece31f796574971824d642e80e95f47dd7f832269229be42a8b9a349e1d280507372f4f426427306bb600af20815d383ae094118efd52b112ec471423a8afc84d843d7ac391312c445ea423f6cf5692b051c7996f3f5f501bae14dd1b6e5909493c73f068664ab298e0126e501091d437b22b3d8f31360fed5b3741d11f988f8191270e229ed5a89b45b63e167129f5933dfc5578f782ee27b0e37239f9881e052a9e21c6bd90ffd99e2100c3912903ec6053a7255f9df28270fed81934a349d1c7b6ab512ee3eb58f89aa4b34e487b97a1f6770ac2772dcdabc7828009f434b2a4aecac21305a832cb471b81fd87c8f019740dfaf37061ef9001ecafcaa6abf0001612b77fff5d54bda079d71164e05f11a40a97ad971d708ef64bbfeaea5023e046c282bf9ad5538c6cc91d12061a93d590ba6aba6c828dded09b3933a21f89d26f8046fb82ae37d3ace04ece50c34b2073bbe9500fd9996d9cff26083efbf4e0a54bb3f893b20ddea7b47268b62b054c7c6fb36866744030d0228fe3bf767836f8d7c391de5108807ac16218e3170086c671eb150963d5d3cebddba41f9c36b436ae6b620f228e16c6160c10266250f29153ecd4a10f14740857062a261f525b9273180f80d431ac2672f8a72ddd401f1c92516afd4f923bf8553230959d16412578b040a5cd52cfb187ec097230dd8c6bd162f3fc97a611d4c6779f0d5ba63d6ccdfc2b4d863a11b56811d2acf888e9a26983958b5c671c345a813e6a0699797dc0d1426d962c302b9b2662d4d18e7ad434a82180d6581cd30291209f29bd97b8e18c7792fb150233c1a385ef1bca14949923fd1d4a410bf7be851b33199e337403e0cd7dc43fa6c5fc9940049844c1b27e39a9e74a1f2f9b5ab8f1f357666fd197fd3cb087c55767e732e2a3faa4eca135856670ce7d2a0b6330c7e5cdbd0a69d82454f530529aae8d26eef322f7a0498c1bb96562b3732577f82c2164f07bba6c7d368d28626ba53e0edc5e991748b1efb99fc6057a861c8359519a12ab9ba0f85eac437d95ee4a83e7da8b4f5960db0e634d380bc7baf4cb6608c240e262450e40042b427a9944d049f2707ae392811cc00bac1e76a96071a9f6a681da60c941a63055c210002e9d3b998513d8daa3e0fa95550164135c7a8ea8145790cd0026b8d6affbb03766bf4e061998932e3ab632044976d1862329c6365eac33fb9dc8cbf9b471366a76436b1d4fad514b2b5f35e4092eaffc825354a90765c9f5ed6380f9627052c48cdb54e76e5190c17e6ea7dcbbb79aaa496d51f8f479bcfec9dc5a5d89b2098ee2e995004151aa45ced007ff5854ed73f5ad46543111c7c1a2c051e722df30aab27107a4100040431c2d68cd9afe60d86780663f219bd54e3084e39a9608289a05b9152b58faa4213323c334ae5772d777d0a90f627e42aa377af4a066284ccbcd70d82a5a89e940b044405f3de207bd2db056d68df3df841e98812b864f3e7c443317b3b4dddc9d7260c018f37e5890aae32e780227e95af55e3610ef37d53863da4e348d811a9108063b54ecd6988026223bb9e772aa53224e5c8046297a52c0d83ca3a02906360561c82573f579c015e433058d1be3cfe272ab3bc4edee09eb6e7ae42c9b9c9b979384bd5cabd95f6a814820e3924ab51a146a202fb50430cfdf354ad2859e34154ea8792771da62cc8413c33893ca5e0f3dfabaa900c59ce84ae148a4aca18206d33c316b48120936dc84e7826fbd54059d75e7775452628c1fafe2bc022fafb31e2294938e7ad77411667c29d5137a15b5ea6ae158977560414ddb096880973ad39996b65207c3ca589953b76f5b2303de1231bd4e67c51d7369f7c9a362aeb232167950308a6f2b6e16e2383b0b57d48281b787e6c3b10068b9a08b01900773ef9b9a42de2987081a28a45102b2a794cb24296a7ad87c24e9d22762b63b4349b3470f3fd78eb85434eb0366a6781230b76935fa5b7140e5e97e49935e5f12fda2a442193eb5979623abc3a29bd41a29ea81a16ba0fd7f5d7e944bde5766df5e28ee49a1e160101a7a8a44fbf3f86b3a52626cca8af53254f746471e4ec88ead99ac3e95bd52a38f8909c251d86baebb35bc355cefb2e1ce646dda81a0eef7350063a2ae95f523b09ae4d63eaebd37b61364b24e0e537a00cbcd78392c30ac34ea98e62cf2bcc9199e548a10085fa1a52f3a077f263ab50e462288b629b1df00212cd3518c263c57f42e836498e5f5f762c547915b8932d9c13e89e20a06b71de73b7242b828dd6022b26b4a4167808289b3922bfb5cdf735e62a35f13976102af65d8e5bcccfa451c43581785aa5b1296415112868ba078c5d440691b480853dce5b78de947c56ffb67071f4cc9c498f9151624d58b1837735502ca267530c2bcf46e69ed4468598387a8cd3b1702135d10e1a66de9bb024c7b1c573acdacf33c84c1032fcdcdeaa8caa5f7a620f079cac02b6d88aa9e30cfa9ed23bede05065f08035853cb5df485614c1850a7524026b37b8803b5e6b14240bb75604c06785db135ebe7c1eef5041d3d0cb86e5ad2425a9fb25ea2dda1b450830a1df9a064651c7d44be3929f72fcf241256192090a5e7ba88964ef0c85757f1e873ff810e46546ad962d85292d283e8e4236ce982c547fdbcbf6c04ffa65042e51914c595f3edb19d31e4be5c980cffc61828eb9773a73d7f0363cd822c3197a0fb989e057c0d04eaa1ce8359301856a503398aa0449502d81d8c11bb8749ba20ffa05aec8342ecb5596bba7afd477bb3294410d81fc6a7ba8e6b7d06340cd1078568a048ceb12ec5e0428560216c6c185b8d823ce8f2d03bde2e3f2164932da59432a594020a08ff07ec0775eb9fcb9d6b8627494507510fb1201dca116a39828d25818bdc93274ffa35110f51d97edd361879cc4f964cd71debc64faacf5dc9a579b237278ca6baafbfff908f5197ba8184c33a4da45bc469fc67917b42cfc36ca029d2579fad4d19e15b7611eebf8f3487d6b6f73a2f03d25abf7f14486bfd39b4d64466f0e8e4e0bb638952fb47ea622f9f246525a9135f2fd10e26a5d77c55ea9c1b3d43674fa6a38fb2c183b9bfa15c30319df82c4ff66686ea4f97cca8b337a5df2f6230b1aca5ec54df573ba8d8968aeabfb1907696542a5929bdff909d22bca605941e83a5f8820c663f77c5d6542a911eeb52cc0f66bf9f25fcd661e9217cd29b1e50a245b06ca7b592ac18895e1487d55aa43070b6a6c51526ff24b16c42909361be7254c6d11197d136ccccd97e511d6c1f1fcd676f4e3629eef7a1ebe577566a9ff639623ef2e123f619729f1a3b8d4dd77346aa6bda21bd7fdaa735afd183b9adc10abb664ae6a38fd27c181302a74cd79fb337a7952461396d43a43bf081adf1154fd330922e7212433e9623e377164448d3f863a730b097d8cbc7017b893d0ef207f6248cce187f9a1a2085b9ed955ae405119281b59961357fc74fbe08c758ce103f9baecfa1527a7f66027b7f0682bdfae9dd07a82be614320ac982f91bc3003e8eb6f16bd5c2c7fc956dce0dbbe2253e433e43ec63e4e563de08ccb7f03e2d3ccc1b89f99737d2c2c33cff8f978ff91f30dfc2af29c5f486978f791c5e3e86c7c90fa781f91668c4d079d1ed48952d2eeff29807208ad9d8fc2bd3817f3ec6d8bb66d6c2c3f497e92f975fd345533e58fe7a1e2c7fb95cd7e5d24237863393cff259326ada9d19c4c868b535fe9ccdb031f86f8d3f4cf692a98c988f6a9bea83669344e02e8585380a7314f8ccc39d7ba854a6b56d7f70829eeab8289b81bf5ca157c4af62cdbd7e42b99a293102e67cf4be5d5321c1dc7a682b159c7e59d4a69b91dafb45c5b8f4fa086b1f9fc1c2d4c1fa0876fba8c030d9c04a5af3ffd19ae70cb9bbbb7ffb0405755050f577312bf5511ff55f6937edd8a3eabb3009ac8f3aca3d45dc47faa0a590620aa1edddeddeeddeeeedeeeeeeee9717b0144951c3e8860e1c160b3243862c66e9c0713a709a9d9748070dbbbbcbdcccdc3c05b69201ae17b6404004545a9bc1e1bf41a89282e13bc80c1932dccd54385ae367150e966b766666fe21046c679c736fc8d6b8eee74710fe5ba5622ab63ccb4f6ac4c98f9667792353b5370ba17f4bc63ed990bd39ed28712ec9a9cae47a7a96f7ef66edc0b5f4acbd31a1a42963652757a24110b03b1443756b85569d7bce39a0f7c4730d5fee2abaf79e8c5062ae989bac42364a75ffe0ebc70fa60ad9284f4587a7c421be8a3a3da21c5505d49dd2832ceab6443a6d438477d8c0d6f86aa769fc688718911fdf08e9af3792ba417e7c1ce447cae30407d25fb1a330020b7a388d3747a9f037211b45c329c164ca243ecb5743503c848d27ae230a9c9919250525e59314e153b967561804ac3f13351f75e539af02fe3a4737f88f9620a493965a933af53dfc182c228cf051215a752d8550f5bfc158cc07341fc8579302659acef214f2fd1906ecf5c6686fd60745e0629357d08099a8fecb1cc5bbeb4460576cc412510632e2c4c8cbcf67eac298469cfc98fff2465adee58dcc7f79f93f5e7e4a7a83cbb73c0e2eb485cec7e185f6e0796338b922494fab85a2b8054eb4e869c177026c0e6ec1c6e02ff905d57f2b40cb6fd345feccde945efe4be69209d1aa84f0e147151493ab8eadec1f802826bb127c20e6bf4e9207f6f2d9e40363791fa697cfc3f492ce6c0dcb1f49f55849750c319f856e42b47aa21b3f07f888c36798056d6b7a87f4fb457f8f984cca40d259be72adede1ab6d99182833623eaaaac1046d0a99daf40526596064e62a0d2aa6d3665c1deae79e21ef676f96cae99b93acdce58782698d73b6a69f851a7122df88c9488b164d54d21f2d74b64ed9b6e8145332b36a3ccd8c253b994a376c2b6ada4b291f89b93c66de2469ce45e2217fa51056dd1e75ad6dc6b3b92a8beaee36b9b2d63e29fe0664f6b42866fc477578bfafc3fb99d61af01e62efab1cf972984c47517388e588d4a4294ed5350c2598dd42a5dc1fa98ebe98aed7f2a7985f5fa17eb64069645c44ed7fa11b0751fb5db26dad85a2b2759a4937ee791563130b6a6a285446c4743a6b4c41a39d097c60ae5c29e28f05808cc957b0c7d99bd2fbd75d3d94385be37fca8098d608a343ea12adaaef16aaea6b85869a42ee83b56a6f56a4efeeee26637ad5e9df58285f6d8434088b8562c9752cf83bf6d29450323333ec2befa8350ffc545494ce843ca31afd31256db3614992bca3b629e35d11f28c4c37c016a9c55ed46dcaadb9b2eeda4db59837bcd7c2b09eb6619af2115fc833aafcd93b729ad75a938f4851cfa792b2d7928f623ed009c63a8c5c861a0032e6fb55fdaeb6f5bcd85df5783204f9a29291af520f4221c862f2376a7fd44f60ccd29bbec998ef2b03edcdf5fe6cc4ae7a784b0db235ee92720f5f61c068bda8be44d5b3114c47716cd860c621e8de8b8e424919639cb2b58d30ce0c66d9e8c174cf5f627202e25ee48f35c6da1bf9fe08d81505ae174e30b9625e62edcda9facf30e61601b255ac734f12d26fec231fc5a252b5268153cbbf6fa13c4ede894e7aa4f568e901719a9da7b992f9de81f86a9d5e9491d41ef982165347d21c1b399891fa6a3e03b5cf8c253b65920269bd252049c1137a5a913ecae4f4285f0129d250fe32244c47a76cadc619b38704461554aa1b90b688412d34818b219c73cea954aab8854a85c3624928657cf1c507df7b44443a4960b19c900ccbd288706820dadd6536c29d93ae72ef82d16439672f95e874293d7b215d948a7ff220184dc53fe5a46e383df6a948713899be64c61ad5eb01f277f02aa90650750b5285a04c99bf5051ce5d088a88e9a8d65898999971ba856a1ba73ac8bfde8504a9f29763203d4e0b4155ffa983a986eb5d4a130f29976390976aae4975041b434c219213ac64812040dcc62a42a15828162bcba1357e1d140ad53f54301d9d366ee03e1c44751563596ea11cd492b11323981b07d9ecb4b470cbb7d06da72bd3213bdd6b8649b584f9fee76cad7fdb1932c4848382ba494d6a09f302f3450e04e7e01886c9765f481e84c9e5fb87ecf42a6645e305e6afa791f5c8709c068636ddf620568796373de625976c9f4da7c7d8fd796c757aa472b63d4f6da9fb26969f476a4b6604a8b20301d35ab3561809a66e7bc4411021e2b6a67f09f3514a847fc78c21d486122d4d12c2766663a1ed8edf6aa761f9f6f9818f93b0509d08577354d3eaf53abe9aa827aa477a5a3abeda5691516ff790504d50bedad6eb384dff125d194b08f6c38183ef1dd6a427f562cfc31fa3d7468a72cf677627b1bbbbbbbbbbbb3d6eccf0e01eedc636e39cd98cd6f68f38fb107677bf9d98c25cf6b1b252fad1fd3ef2a426042ba59178b60f998061bb37f039ef5de726cbeeb6e6da19c130d13d93d9503255d21b37981beafddfbdeabfd3b9087d6cea88ea802a1381a93baf3a3d526d48e16a20af778fd1dddd2f974c60d8ba27dbf3d1665a5b199665795dd9d7dd39e79c4c6bfb6ee22153b98c1b4d4c860fca84315b468cc950bc603d2a0e0034b3586203fcf8beebe07b6ff7ad0a07eb5d319841d960c1dcaf802be2dfdd5d56edef0a678bcc98fb4c38a1a1306028418d29766912747b1641e510d4fda2a67c740db235fc4663b85684b9bbbbbbbbecc218bc3b8223b7ceed0b15f3d1540d5eddd6c00a1c3038aa73efce9d83cfb97577eeee7c092f5c3167eafeeeeeeeee5ad12a151898134f9a245104904f104838491133841c01a9f263b7b51552e198d15032a5246ce4c8ccbbccccfb7177e3f2261104b31793a6f2d3f062a21a6ea99782345b0382c96114d1d7fef5f02390df8b3e99cde43f947fdbccda2b775f8430a8335456ec460feca3a23c231b3ff81035b250c5a868071e472a13f83fde7b349078bb4c83c9ac41c6dc18949c1b633239428d283030bc5a260316735733ad7e9fd9b7bb13a7dd938dd0df935ebedcd5f592a2beb55d99182c3618267892079d8ca898c940d4a3645a6b94cc37db58626e73c1da6f0d7f0e6606b09d119a3586989bb36b002bd37f9f77777737e6c85474852d614c238b29e9be8d26e64ec1ae049b3ae75ea63577a33a4d43b50d7c674305b206ced14081f3540efc19eaab29567d33541b3008032b552272c0b60db084b571830ffc33f38b008a5b06c0ae50316b03f36ce66f8d8d1dccfdfe554548513a013863c6f8bd42b4ea358498db4ff69d7735124c7e9c5e77ba19a9bb355fd41a56cc652f98983375f79979eef2645517c1c1e782708155594e3304168bc562b9271cb19ce52c67398b15646b5230fd5907334ec78ecbccd281c3d281a33d8b85a3727de3068bc562b1de17af57a4528521511a9aa6dfd5f9fc6f4429a57c7ef0e13cd65834f46000cbdd5d4a09afb07be618638c91d9d9d9dd9d3d875e5e5e66762f689a0d820f2f851338b3fb83fc9c1f3ff8de735591bb226362f23b1c2c952ac618a373cece9dbb3bab543f3f103dd18325ecdadb60010f8fe3330e1ab83d76ec38711a87861e34f4f06e219cee6eefa3103ce71b3a222bc6e8ce721d38cdc45b91c2fdf7dddddd9dc3810d5230e3b226e64ce5dfb76166e699224851c619ad83f7de3f32bb3f7ece8f1f7cefb9164bd870c2f91d92d29412c89425294b539626f7b4d6ecd345482965510b7991c3542a2993fff9732ec618a373cece9dbb3b17a10a025b609bb5a5ec6e4f1020bc05b6dc9ec9cd4aa8a6737f9b13c0766673e9a9fe4646975193066279f727b08a51d1d64040ef75b02fa5e0294bc554c461be3ccb1b7179d9bac785a6e26fcbe5e7ebbcd054a44c60583ebe7c781975516b31bba1f4a787190ea46f895d05265b79ca8c38f9c1f2a596cc080b4d3d9a82f44789a620069f09b38d8a6a5431fbb72e223d5b995917b9d1915191509191509151dbf4bf4f693784847cd5455ed442b0a881dc7bb8f3139732a4c4e8031587a552b9604762633d0c5517aacb4f561cc434fedb7caad812db412c57f6068784627950dd39d73f145171eda7ca195727188612cc9e39b40dc38defa61d444c20e45176ca142ce4040712ba42dd588a5051dd984a75262ad24112cf3133b3a41b2a5a601231c590156419d369ce3937e426d11095ee86ce3987d58d9fc020c55ca7c1a188d3b89f5be3de2cf22a40963ee0cb7f116397a6dea33574edca6a9b652c4a299d9da1bb3b1dadb9bbc8d281c31a8b45a483088706e7eedcdd3944624807eca07622a89fb44d50db38012184bd6457bdc405e90e9c851e39bec2520cdf6746caaeacc6871e14e4e3e31314743deda08ba670789acae1b9aeeba24648543ef6a4dfe40b4854731a9722a4494a846baf941e4e0a2b5ec17ddbc4f59730e67bc77f23c70d6c863165d89bedaaaabdb9b67d792089b0fbc5ee187b5a7e1cff9df7373807cdc6e0bf37b42c93c17cce060d58865c1798b39473a250ff9aca65f5d7cff5632c1811d1d35239d18a0f3bc180f439482e9aeaa7a92ebdcb8a1ada2efcd1ae52bdcd20eaa2ea4157687ed0417dc58b9c46fef095ee69c2072aaeb4a268fdf4505369f9d99bb5a2faf5397b03ab2451fe691b4b4cf85b934a7cc557dbda4a0a8f6e17b852df63dbcdcddccdcd1de4b40d71521fd556735dd757a91c6eed4be652c55065e2f2ef4acf85201f24e167e2617a5734a58a264d000034858a1e18a65401f4de7bd1023c271ffe222f959f9130fb44f8de7b8fc7d71d8a54d343530304504d10bb68ced670c6a4e5b3114c1365e242937cab85e6d0345f2f20ade5a0d31a7f15a2eafecab22bfbbabbc952e9ddb4a3e4a4bce8eae547caaf0299bee01d7852103e77777777770772ce392e02cc9441cdfc8dfa70d4c772833e02b6336d33518fa46e3306d0c1641f7f6229ec586a9aeeafd2ddcdbd0cdbb9eeee06c2465bd50e3cb56de0e6b66bf6af816b3fcb000421a7a2b5cb2d8719b7b87d05337bd352a2507b93d9101fd0b54b6d23b1b8651ce1334f6477db07b64739ba18e376c4851e0c58266907f90a0e0ac5baf67168e8d136f16a930d2cd55dd27dd395964cf7aefdb97fdefeef3987cf753be79c8350dcb9b6d94ac4c580852bf9df9b5ec95f275422bc65750d8084b9c9394f3ea819950e190d074b288a94284b1e4591ff9052873380c91b2200050ed868623707ccc519dd503a0835a6e886ddeddabb9b9f737ee420e71e81ad5c1dccfd1e5c303733ff00fb674ac1d4360a73793695cd602e45cd1e9512b065ba357ac0337b6086ec1431627acc8893d21735c129e2a6efbd9144ff45ad9689a6724a18f6bbbbbbbbbb53840748a9a8f452ce8942fd6b9aeacfe88946a809337b3543cb67a8fdd3363aa4e43bd7a1c6bd694ac3d6786bdc825ded581a5f4d2a5a6831a9484002a49c1385d2321bcc142ce17fef9c93f2fdcb48efb1953bf0b0ed38d263cfb483f4188914638c54077e57657691b2f79bc1c7f882ef247cf735c26c6b37167fc2ec6edc1d1ec01f290a664e8e57103afd50f6f9207c867e7eb4d61e84b38b17e5fc98a9259389e6b4f62468c8a727c8e7ba7c2e9fcba727c61e98181a34b2dd980ce63a3d4eefb4cde9fb8bf0b4cdcb632b1a2d7cc7bcfc16321ad93b4d0c098624747a1696fd93634c5d7e7b976ce33fb51ca99b1901da7975a25a3b9d284c6bdf5ae9bff4a52795de6344dc4cdd76e84d5ffde802356572e4d02506dcefe796242d3d2d488ab605c9839047916a36f1d2ffc0be2465b7f4d4fe969efe16242d49da06be942d3d06a90448947f28acaaade94cc98cb48615737ffb2a5b7c9e13ccedbf776da3398ce65ad3948e21264ce55f38e7d6f8bf164c3411be443c43ea4e0b10a67c285fc8734c66fc48ddcae882291f5ebb10eefa83bed0a13f775f2a3eeedede03471392743a8d7b3f09e67e5ceadf9a3637544569d01f0b6cc843b93c29e662661eea45ba6a8c0b4998f01fe971dae5a22e990e566bd257aee574c70eb35e18867563cc7c750da7d29f1ecbb65931161af35be8e66acb63da0dff03700eae979309a407035c5c32977fc9b623f58564c391daeff2301ff3476aef7485a107e0185c1ec75f321ced4271bc2563f999b1d0781c67a1f13e4cfe96f4548a3035e2ecf45eabf58074ca27b8ee7969cc08fea25dc741fcc43966e71cd31622f2a1d6daa9f89013b5cd90536108bdc9d6bc16daa690a3358cb298bed91621c176a694f34327fef5fd38be3272fad2ebec75f2ee3d3a55995bb775a2a91cd3a77e947e1f85914818866154879d57e5f3624f7a99318d30870c27b61685aa71064b11a92115dcc5a97d49c2e4fba7f8698a9f7449ff6dbe36c3a4092a219e5f1f1f93725f663aac73bb0fdfbc01161dee8e936e378392c61691f62a423a553eccc7e33ded57c2743ec6dcf7206cdf5df32338ba4e6b4ee38ab9f10f13d24312d57e878445e8e460346da060364e4be8957fdbf197b407035a731a70bc853fc559b4cdc65dddc911101207c482eacf49405152fd541d0948aa738444d205d51f4666989fb9f1cfcfb51e95fca07e22659f244fcc248c04c9a9080950eacb96a83aa5a1357f940f13d37cc53fbb722dfef92a13d55a0f17190bf969d0dc542a370931a9c8b034fe08e0c1ba9f60aaea0c94ae72e932ba3b2f0e964ae538bc8c1d77767700d49dc245142a3b0f05014a1d128294b6f2f8c77c349523e5a77078920e01223fbe931ff05fea86f778247cc17c34d5294771349d9c211f035b5fbd250941551dfa5110921a535dc12cd8b7bca9647a6c4d3c8e54cee05fdc3f49d44bcfd9cb64b6c95aa2d7fbe88a7de4276539b51f23bdd3940fec99547a57fa57fa96528976b605a95b7c21a80abf25733f3323291fcfa4779974ba09b9bee55f361f66a4c7b2eb796861e69fd747966cc697d929934e13699b6a70efbcab5408a9b461abd48e4f3004ba85bd5b96eae1809099c975d11b5738ac21fb41fad2f5580fa42f416682615405bbfb516c6304f372530ec0c3abfb3e0094616f52efbd6ecd39008b8757477b6c0d6f590aa6d3d954e2606e0f0cdb1fd294fb232d28910c711ae71ea7f1c7d1646e8bf42ca7f17f1e273c4e7e5c0f9fc7c98ff7a4f7280fca699c47befc6dbd16a43c4e7ec097ff5e9394e76485104ece58e2889e9e16fc6d459a72746331ad51c6e46e0f02c68e999999999919720b7a7208b2234454798b2aaf95caccaff7bdf736e72b323233730fd89483a2084a28395128997f191d8c0465653acda11e3513843d5282064b9061b16ef72dbb65d8c64e61ccede12bed0a821df5d050d47f294acad6b410e61ced7675a30a07932b84912ea57c1efef282cc84f4d35724fafc358098fb2a8f82edbbe3b1153e4b15162396222196293485a6d014e22457eae2ec8de3a8dd4b847aa43291fd17b337379b8de3342df4c0f0a79343518dbff19d6947dc1ee62ef3ee83fc961f3ff8de0ba50248b91608b2e9a813c70cd68f1ac04c01d1b0ae1fc2e722906320e74c2c32d03090bc7a7ad68aad0fe440b257b294529e4abb372fcb2dc880c8a9ae01ea5266e75c77fb200261a84c89a47ae7d5dedc77fbf3c1ef32b012d979b533de79dd5447f52ba0d6b9f7778bc3ddb7702c958e1ecd7265a830f963bce15e724f4008213c8560655adbe7c79c0b8d8b947f5669aaf6aabb6275d26db1e41c8490e53087c5923c9976b8f76c83cee483e574d5699ba0d40ea32461a5d3c9b403b2904824928358bc349d4b5ef2a25b91fa7e1d0ff6283663fa27b19c5a3009dd2b99aee843c2e4625fb1c74c19d77855796158c9c425d2258342c909a10b742f5e246c003e30e460f25b4dbe7c86bc9a24c90f540825ecf196402b9c7b2e2ece6bc0112abdb8a909e8ed304a520933954ea575af84e3d5bd9cc3b2dd8b2e4f29ba479af9bf7c965eebc139dcb42a1c2c1d3834a8349c07f2f5511209bba40cca997c74752ca51a49a6fb969294e11cfe5be59358b21e3803f8c1b9e8a2bc1c8ccf7970261f0d5f1532ed80afa36d204eec815382596aad75b40df429f54909946a8ea032f714254c53a870e229506a8e1a1f9a764469f34c3ba07beebd7c3fb510438b25a81f2c6656b75275a1bac96c16759bf9badd80a2fa4f7f141645a8fecf82ea53b210e30a30aabb6ad5ad6945573e9ac215772e8705500841142e4cb0648cd686aa0e8812643185085664418812fc8080074660c2c41196b472488162a88c2952008194164a2221836b8da40580b46685b9693df4153aa804a8ec57acff4e916284cadfcf5d6052be77eeaf1677a499a180556c4d36643a6c0c1bc29d57bbfb5980edcc4643a8ca777fbf5b72bffd33ed60d92bb5486bf2b70a2faa70418b8787090252105860a95fec4aa70a1b9fb063541ec41934142822cc2dacc09ccb27bef2971f9bf80ac6a12a65eca2d628995b51db1c61736c95d18b2a5b8821b590d1c8de31e95ef86172d7df1bd38d5ebd2e9a463e2a4d237ff7e601616be46f03c8f1b6d818ae526f3475635095d9aea21130026d8dfc93189306529e67a50623f8e96945cacf3f5800f5b4b67f9b25ccb4e3f4588d24a6ba3dc9b4835b3159ea079c818816a4297f1aff829c46c638bda169d0174379d60a44082d69f1f060f2c109091cb49c5c7fa485954a0a50c28b29b47878c07c683999cf037422a5e5e49a8188d686aa12894cd2362f4b23df09bf4528aafcb844951f6750e5c72a339af148318a8c54ba00c2bafcf68c504fbf3d30aa945f83ca7328efc15ce9943994d6e43f20134c98dffc89bbd04d524a77e4a45c1e90d3c8081463243f12b5cdcbcb8f54daa6e5e5472376f586e4d51f9de86846af743c76d11d4495524995124995b18c8e56aa8c55249418256651e5639ebd275bf3a0581af9f249f1a2ca5ff92ef4866e41e9a4f0867eaaacf2df10bb62bd9f19b096a8d2a59cc2989ec46b1081253b7e74130ef0235095f94a2ffc30b11a49e616811e50facd7dbb7c948f23db81877c1f25ba438d0f33e6e51d898947cb7b4f8691aa0b794bf692c9270ee5bdc7572dbdc77bbcc77b5a8acc22268b454e23ff94c52eb2d8527c15819c46be9473a250ff9a1681e47f13a60fb526bf85ba94d66ab8606e6fc8573ab3ba64449cfc223abe72294e235f9e4ad95697521a72a208d49a7c97225fca3987acd047d49afc127d43ad61ee09ccb4a314a97362bee761a32e96d9a82c5f45a0a5912fff052be61bc2a2ca7f54dac6f4f25f179ca35f9ede943d2aadc9d31b3a55137d435b231fa76b92cccda554293f0249a02adfa54897f280ad52af67d38e8beee092ea4043282302c6ec1c7c8733ddc377cfd5bdf0c3ac41d2f8a4c7a0c9015c750c31e1c5d926771e468b60a7376e30d939e7a02f71cf45298304103f3550c2064710e2052df8e2ca1146e4600a1547b410c32545ee1cc698052b3c49c2103968c20c2758a10415380081122730a182bb422663c04408254e784117538042869210a060c915a04c3134858914362049f1440112062c24a41799a22c5118b51f070a4525222881edae1eb7cafddddd0bc005fea94eb235fb5c63aa9576360ec5746109937f06bbfdbaa39b6d33759ff323e8ce618c477e888084268e008612869c58820c31a650c1159c9c6186142980520c71723d745c2cb870428c02cad5e46aa21af20114e9440b21be0cb65eab8579c945e7dac78c2d2cc6d36e8d6b316fc183254894a081cf1320545284d822046264e10390348208084f28c20984b872020885951e643144122b90c0e804a8d5018bd52476f166ae68c111a0f0842ac838430a2b6070c1842d4ed053e404162c4c0924c50f6f098e85c417ce42820ee1b19088b34a54a2bada3eec151f3180a001135378e2071f8e30e2c910097ab0d282d61457c4e841144dccbc808584640013b56b37ea7de0c39204ea0599438663d0817f7bd99334e523bec3e91d380b3b70162a4e3baf2fd47e1b5b801dc06a312c0df7afa80b2e00f730bea3a9afd03d184ef5b7a66d9ef3bf59c9d713dd3fbdea265c4607e037364326f55b2b7161bf8fd89b97774f5a606f48bf1f4408cb6fe9779f93d89bf9bb2ebfcf437b03f38bfa05c0af007cf5c2ef7317bdea245ca585dfd8ca169ba38f88f98d8150f75b06bbe22327fdc4935ef1d090d03e3bd91c6cc58a12759f83e815070571115c82cdc159700cfb437ac53e572eb03938098ea13f0925d47d06f46ac8f6a0eed7cdc14a3601d4fd006c0e21dd849bb80c00dda40c7581c90b4cb24f61311f74325ea613a984b1b4b8ccff35ed0000cc4b130f580180ea247d440b34682789a17d04cc0d3366b034501cbda090e0d2326425ca9095899582b208ca82a583b24ec2278912dd1a4a12a42887b092a3235672755027d15a3bd1423847cf6063e89774eb28b53fd2ada1d4fe1a6c4d3b7ac38cb9ca28634df8ac9b384dc7df2ae1e3f4be7792a5f24fa6291fb3c29f15d217b24ea29b8460320c0c3e981b4c1d9269171af0cf0c899393e94def5eb53707a832c850d7b4e38218c9e537adbe977f2c34751da0ca5063762d1575e73dd735d9006ba665a8348e9734b9748846000000b3140000180c08060322a160301c10a55df70114800c7d9642825e984ac42889819852c810430c1100000000001161da0437a6b0e522f92cd1dea1f89e37971ad5d5ae6a19f08d1fda4017a2b26520cb6aa0ed8c4096de7a7c85e6fcf3fc69c0e1280c41dbb03ce1dbf8164a0ada0d539c14afea76ae4c05ebbee972f67c993ea3ac948e8202c3f4fc2926d0e056b3a5dd8c5f4e19e78cf55573264b50c74c72e178684dff59667d6b287d758ab6c6b84147fcacf6a41592972c166e59afc5377e3e1147ab9e622219a8118325cee7107ba4ef3e8ee2dcfd4d4b0956c934a8b32cee0b8ea6e1470a4a8a4867d0e040498af32353c25cc695a03fd8bb5d9833210360401d1bda1f68a8f2abade700d26ed461111c2a3fcec7172ed24bda9be33a2b4f4bcd1c37859ac64a7e32d4193173ed1221198a1642a0e84990695df40bbb8528b01e40299b5a7a282d3079a3899448abd99005d84a349db69a06748defc6d69d613ab6c191cce9872ea292a7b994c13aec11c00b1d459a6ccb7e5fd0393c8a3b1ddc41bc3108046a34cee57d58e4a49eb76173a8aa42c064dbabe18cfd566842b1d2afc61e2c4d6bb250050ac8c0d185b0e1c87070280136c1ee2ccc5def23e24ced8f71b9ab83afea5634cf6b76c1fce88e58213a065985221ec66ff4fac3ec96a850b5bebf57c567d1941a4434848bef5d4b0091f9327a3bd742eaeb26e487b5bb09cdf252ac5ed35395170539f9ce0f4a5654b95b264c943fc941fe1f74b9894ead8263769b0317eb466029b8d220459e3839c28ea990c7d3f4370633dfd331bb285d06acbe1b15ce55f4922409f3fe1375b456242cc52aa2a67666a6b94d178881c0a8f1a265362f63d748a7939809de85ab9590cfc0bb9c954f78449a4485e9e5667e89a4a5669a973568b732ebee259e57f34baf616c957623a29b7dedaab895ff888f41375c9701b6887c28e9c80d2d7c1e680818e368cba5915faf72dad86865638e9a3ca6584615786e18f927e06d17924563d4471c6fd5fe829081fdf011d33bd55be5d69084183c481668173b227b7b5bced22a42aa97d7ebc3836381e206d5d0bdbc87120913324513483a85696d75365fcebf717f041ee7efa6ce4a602a10889e5502fd53c0ea0cc95f32c5d09eacd083db3def055333d5ad4f65a023b582a704cba1d96a4e80575765b5f33b07a9f2c37af8a1efcdcec3f3488194ab170633e432a600cd5d64d6a6a684cc5b9e468cd019dfe805dac20167afd0b31005f190ebaab8ac58da12bea89604fb44d5f8bc5bd9e938cb9a72fb4807b061b9d3e11c7d0d0720801ce5f38a0919aad0d418aed7a138b95906c8a70f31d5f2856f88961f0683cfc036d9af8905ceb8b28a0bf9823f518eaed2e527bdfdc401664eab89ac9868579fc69079984a802c196546a4c34e57e35371e39712f5ce9afa8383764e0bffa4b8b47f0043368ac780e1e5b94ae037453de232812902c616971fdb0a8d9c00414c4c9498b542cee512ef9618fda4aba7d9e685f6ba3e3bc2d4c6c89e7558bf29351644542f5573e53044604c50e1274cabdc5db0a2e0c5b9d297b631cde910a1c73838bdb93fa2567455b40de3cc09e8ceaa256d8deecf131d1b10a290bf4f60ae71d69686d720e20738298acf90e446044250b39da5af7d6c7adbfc574f8fdb71ccb2d08c7c8f178028c78b5dbb1f705ec4371e03535c2c5635533d33bacc1fdf70c460d1b64f46dc11dd812c67c6cb1fcdec2dcbdf97dc69a7c77d8a1335967d90cbea9e2d24e6126e9fcb2ac13a09c385cafaa9347048b3757403c71ad60b3ad0be104cf7b4011a79ad4e18a9fa2b9252446416de918d40d8838f375fcccca3d40c1a59033d030fff5a34bfe9ea5ab8a6a52c80d94333837551bb82b90f9f8a520b1ee8584205f216a27e4be7c432bbf922239a4ee63d363e48db00ba1ae842936c500d13e6091caae4a831574e97721285bc7053534c9462fc9fcc681ad695ea818883c0be88cd9164d77e7aec733c320f2f150b743f75e1d81735d02e086fe3e45cf99ed5d601375bddb55c1517d2f3adf779c06b34f4366ab022f945844b6c48e75c948755d8aa5161b63f8e6421067e633986f30d3ba20fd1b1f7c1eab219259830668996ba3f60738827bdf99925ec8e381f92765bc5029d60197c94f2ef0be469ee53d1adee894e96f03abd70751ff87b5f08da0a80c57627d1ac10e2fef7f0e3614771621d55688ee881ba39fc359bc7a8f3db25e264e8db84c65a35b5741c928a4cba3eabe4fc0027d44b26d811b0fd584a10ba43ff18e8fd26ac3df562de1c86b466d161d8bf206331bb325f02d6724a18ed9bc4943e0183fae027f6ebb1f3f735a1c7e51417615c05b9f121a6dd55f02069da2a0464491ff376ebc91c726b58e255b9cff9767b1821355883fc6007e79767eefc56f29f1a0548e87462190757dd8d13cb861a3bf7a9b1254810d7e72d73e98e5fded4b29cb34c8cee367e791c9b84e6d5289724532e1cd63eb1302fbd00816a9f3b9e22af4cd0b92a340911a13e5edeb820f62d3568a09b8f6dc972c8742859c879ae757b7e9e49ecbd1bd87adeb42042fa91e0b55317d40d030f4521d95b76b06e3957c9e68083e75c45911f79f312a80840a48371f1e518494b6cc00f9b2265bbe9f6d71ae25e3a161bdab4bc9c7119c4f407562e13915eb4cd6d97cc97447aa3de3c0b6db5a2705e3842fcca8885363b86d9dadff2f08d262111baa1c4f7cf5fee4654001ace2aced542a9f48f1e00558138da355864e9a45a48cf147db037a77ff6069fc1f1011c1a191ff7f239732bd9eecb9c2ebb5a6a621e21c6b7e799a3de30499f63385682116298a99822f1e05b626e6ff5a465fdc8a35796d657e82513404e1efebf246ccdc228798811dfa1c5e1a2e5003e9aec41d9cf159be304a3dc48de91ca874f4cc8f7398f643b14cfcfffb2567b1a38cb9bccf422f4a11dd75a26f2ce4d3b27bec7c807cf4e2a32b3f5a5d9038d2c1a174d9d98054577bee976f00519eaf6fd4b5561c69f6860bb98052cd1c20fd0287ad0c0497810541dc22f7d76854ef36bd718397ecbe8c0187852b0e193a0d69d58ae2bdabf31486d6e95c8066f538a6b60e6e663ea7bd8f4fd7e740846137c2bdde6ba8e6993482ea4fb4dd898159619d684dd5df2a0069e6c6faa28270a8118a9027212e0f214b874c110fbf94d2c1d6cd8a03501a97e14e07b6ea6834b899bebfd6c0a3eb22f14f8c033d9b7fbbc4c7a4a494da664232d583fbfdf8349425fb3d2ae473f6c7e475f7b282a0c6eb74c8a76aa0009eeaa7485ef6448a892655084d9fb6785c79a71f9382bfd123e92ddc0fd88bd0225f0dbb6145c1c18f2b8805d05b1aee7c1c431e3c1230e96c11c545866c61d1a64c25f4a2f38d5004ee03250c9e9ad20c5d29116644dab3e0efee04961fea8a04f25aa9a0872d825d20aafa1f95b9ce8625b97d906ff39ff458297e20462a7e6f213d4bca78e01f980d552ee0b8ce95ada802d7552a233c3449f9165641387f1e2a52631a4e934d9c612d0bfd2dad6fab2d35502af48da2b51a4e8b3f1e25f14d72b96d842b90bf48845ff47151d2496f02889f89c96f0b220afb300f8d68111a1d5bb689e07d067d22b647e7a9e4c2d0d2c1b8b278faeef76a7e86368d5d1f8874b043815ad0b381934cc4387f2cf8766484e2312248706a90fbf4ddf681b9ae17da265c56a0db447013a7f3d47c0f958f9a302fc61f7ae351b84c9a4311dbce5c4b3956170e62e0bf86cb54216bfd71e845f353d28038429f97febafc4d49b4950472601993580b20afc5efc308cd518a7682e9a69c4f4b0c926bab50d4dcd03ea03c3cbd514dea36ab9595a472bd3175c736621a9fc8deee642f5a5c4e65d2af890383d823d498f26e37d8a88eef40aface055d49b044a1595ec14893624282556cfaab802dc134d0cae99dba1d3309594d33c8999095c5a9bd3619512d1ae85d673e80e2582cc95c8c46d3040959fe7c1f4d2e2992493677caf04c2c2fc05db515c9dcf02ea0e1c8608615b72f412202b3b84191d3abd6afcad98ec896c54b4b2133d9fecc235abd75b8db7de64ca129e0d23b2a578cec8b3d51b84b81d59f3c90a8e83b57f9d9880d0cad8ffc56686fab428f0b53ddb41215c17312954aaa9e4ed2204fa5e1c0ca6197a71f861456eda9958ca223266ef1cd45b794048e1d70e20c8ff6283e8e64027818f4e2394abe32e0c492f0b650d014935d7ada36abd6b794e22b6b6ed7b4bdc0b45a852a252e88a896da978f976258e73e1710957c9a67ce9a8dbeff41f187845e86f2b88b9144eff427aa44d8c1f95e8f910ce78104552dd1c295fe7a47a0014435b7613b5cfa8377b7731544dd137aa4ca6ad1054fb5c029c8fe260469b5630975d49d754b57ef06690728922f96ea53232346ae27c181186c632961d412ad5d28e404292573e8696a49e7c9d31e1d4de43a6f464213fa844b8937b2849d5cc86fb0efa101709e4ef94d502fb8050016de7b6525090b2aeb0a50279cd6934310ce4b8420fab73ddbf06c4e28ee6ac38cdcbe580c6b8302f3ee70a70853c0699d5d2c2b294c30f6aa6b2e69f37c6254458f7fe42420c9040ef993ec7e408502444865f21355a0401b2b88d8314e1bc11a6c65bba14124abb8ada805f9b84f1f271db02cbe351c292d52ce12656d0def703c6eed2af423803616acce8821637ba2bed4db1bfb48a64a4ada9b23d3780cbb9c46550c3f3f661bdb0a8410d3dec0ce54d5275f50e0784051acffb72536568ea374cd9c9324a5f9e81ba8fc15357bb4c94057ea709b3df870ddcc7a6fa9d4a68000238dbd23ff4d051123b67590c4e2fc0b5c5e1642c17052aa558bb17adbd32ddd30053ef4c3f09fa4b278a491299d7afca7a6260f60d7589df7ecdfb060f1e80e5a20eb5ffec13750963380f02c530893fed0116b10327e0309ef6483b764e184b70c4a0035e01f95b0c5e634816925441d19b0a58041d7b220ea2241015a5f088f00eb8770f41937629b3f21198e18724df0696d4351765cb121623e33d5c0693abcdf0d97db1da4b4043b2f987022f4447374a97c14cfbdd72ea40fe0addf7f262d71ecf0f5d94981f11e3930d99635f62007beb11741c4b1001f90f87d43c38353e8438f382201779327c24199711ff8e8933f11d5186340fe87fe66c48853075bdefde6d5bda5ba2485c5ec687e7908f973eee0ca78f5eca8236cc7a7f21576a50aedf7b811008a0d5abfadb6a1cd7e86f2a9fa23493edf886afb2862c0ee51814d0f820ac9903ee7b622766e8f9c358b445f7994830668006e9619a4c4a23ddd47e8f4df0aa5deffd990bbeaf34c24b897fc3c3cc4ff70803ff4cb55b810983ea99c205ea9e128182ae65cd3231a8a3efffce7f7d8a72cd934a90f7e7c6c0eb7c229657c3f44579ad0f77e96ae5c869ba29402c891dfd42e2b3f4b10febd750c690fe2f0ed26fece5e7b7c2cde893ceb77b1d267560eb57b5b391b7ee684d1ebffa0cf2483f469fd3f0f9c524c99430d660c21d35d5313636d32581f998fffe21815a7fd1a3fa087bacebbeabde37997a913bd0cd6bfe3159e42c6c9e85443dd68635559c296b53a48f9bf1ea8550779f48891a27594c42bbc99b8fe6ee57c177fe42e7fe56032c4ce73907b4e5fa5cb2eee0dffcd4074c19aae70d0ed6d33b0c299fcf0eb217858e200a33d313625a32df5713591f0a443fc05472008acf36e5ab71ae7e7bc8d57b89e6698a26f775cba95603716b8a35d9384c2073fc7a12b6e9bca91cec855d39a3b914599396a95c1499058fcb7e48f2ab54bbfca0d6936b0422cfd6f2efe788d332091729ff42269729cc190303b89134fe5868ad77d8ed34ba9fb7f51dfe22678beac53b8bc8c64222943305ea2b173764d6eb4dbfc50c22ee72f2c7fac9bd0639f93e5f357a2a22228a8d1158558b109c9127b565211112808aaf084d2a1ac147967821a691eb23e1662e47b6807b04d28f55dfef06dab40975bd671155295217eb554dcfa3db8c860e55854e8936e4f474c457ad17834bbd5d0a01c4098f2964124baa8105dc53f11adebcc69bfe98488aa9cf1d82f186b6d89d468ad922860725f27d83a9a4b7319336c510d518f54d7e385411dfc886bf6a2bb8c1a97acf43b1913d38f2124537b6c15d5c0a6eec27f06f28cf5a3541ce201c01698dbb7eb7d77789f939a41e470a23fbcfb2640785cc334a12255aca1ea88d20bfc319cf293f12067792a1271385d5ef0cd4786ff98faaa86d9029a48f154032bfb8e06992bc93f5a6358ece5c98deb80931b0a686b36312d4808cfba99c3f4b408eecf19170a908eabc62178cfb14cac67141e9ce32f0fdee7ec0950425f1f4070b0e5667fe6dc9a292dadf196dfc42c4ae5e8f04482e1752d01e6e6cc67cecce3775b97d9d9ed749f593c8b207cb60cecf3e3c787c59a41d98037647461aae97e653bc1434089094772c7cbf7bd626e94c446a234932766f620ffeb25b96fdbb2a1048785517106e8d76a3f328a756b7c134165a40603feb6cdbddbb798e70654e7e1a4ce87c3efab2524fb9ce265bc8dcdc32ad0c0836cf0974a015027254af520dc48f9d61f2f011e1ec523689ab9a1124cc76a0e8059ac5aafcf2a49a33b28335778f8a6f29fdc81d68b3e14ab97e26ce1f0e28b80f45a99970cc615243d9e6caa6e3eb9857a37d1f7a4c89061b1db4b29150ce61c290b5606fec0a5a1e249589dd65982069a861f6c39346187f8a0bb1a7aeb31d5b766c2aeb88f6104c8b9ce72eb8701585b7bb736402f925b404a8ef7cbc7ebf2cc2250bf08e3a0168b9abe070bec1579d7ada40e033d43077e3ad636d1f1d511d9935e0c2c5c916ed9456b5aba20d2c9e06713a2b2a18a6a066fc88e1fa0cac0ecece833f9d94a489c9e88bc781cd949c36c9956f64df1c9becf7642e3a8f0ea9df5c28236a318590a243c21290636195df81eac5957e911b1a2a56a5adcfd09e03b037429df89e6e3c2f3a7596c98e992fd583b1f6a5730e1442499bd1a0148c8d6708ec1502714633da40ea5dfda27083099c63a9ee95269672607cb63db9ba78e9a1d203b7a36a70d3fd6a6b220a11559687a22dfe7a03901ba69a05f9730b59229a2f6ec9f1ae82b6a72367505e4121a3c34793b3c174a3020be757a979386516b1cc14b411e7738c2fc8b8588e597b13c76fe64ad61efb052d096a2f23a4e1c32fabd8bb6ca479248ce243846106f544f121c6455496e96f4e5b80cb120c471b9b9c5ad14eaf0703f3afe0bc6d138ff7b5162201ffe63634e0c80fea68312e4780d99cbc49651f59f3fa1e6a7e36cec658d83ae0be9a481785746be9c259037e87d1e6bc2e68ea42d2e1df34f17670764f6f3fb584112114985abe277b58f3292c13ba94bd380d2d47d0d75749d42c1b520bbfb12faa21a465fcd1e66af1fc8414212ac21f9e2c789944b973ec5f49bbde62284074222d28bc180219db376c7926fa5f2ec0bf422eb7f5e6ab13f34853790fce584a578fb2be09f5ae194c406049b9f9b99742d9e59052316e38d8c309847b42d029566238d36c3de4fe7a8b3dc99d8a4ba633dad850b07219dc37dc18d529a7daef5b611042224fdacba3a0af8d3a5d6dacf36c3563db07b8e98dd0850621d6501da885b7d8cf5f99fd783976d320d79c28f263626a701301e7f14a40f4c5d8115c9ced7b8612816733bb6472182386365e122d1b8b892072b549901649ad8028eff9a74e3d74ca0a269dec98edc55fa2c59d8bc48bc2b641ddaa6b002de2fd3730f47cbd7b237abc6e6f462c1866e100dd20c797cc1e57521286ddb3afe87cf8ce3ec36e3fede6235cf45c4eb821fd7dd1146d6d8daef728df8e4b242e400e852b7fd6e5e2845df51ba4a460d7e1c2726634ebbe97bad0d103b24e397027a00d319ece199b8a85098d60a654ae268aade236ea2d12f5f2cd28804cb86f4fef09b4ae868ad2e0f3678fab4830190ed0903fd833f01db83fb12aeedc11e02ed1470d5cfc4b70924f3ef1e3b334f50eeda4815690e84336782572e302242c89a50d2189f0c897d5fa28fb74a228ae30b813d1286d50f9e061be052bc2326192bc4a1436a4883d02718e1e25efe8a80c6cc775fcecd1f62b9410b4cff5dd13ace15a37eb10cd2b22779f34d3560b7c30b1d155dc135e3b6697c6aa698b4d0212916f9c46fc4917ae01246b3809eb2e501ab30d29384820a15c4a0c506a1a72bb4e24ce53259a672916caf7b40bfa0c4839223c27f46787760f0e4582f66aba9406501e04f15dad249001f890b47c6d69a11088fcc25081532269fe1bc5ebfcaeed1abae16e410eb7b9edea4b908b9328ff7f34bc8a979873718f6e70eb40f57df555081708a63ca89e73df2295ad03599d88b53bc2c8e9e19e8a5d44263ba48c045c8f376d59228e0cf549f6779613ccd03599b5704ebdd678f436707f250965af1571553224aaf80c0d112451713a9fa2f2838f5a433fe79b81f3060c980f2850e5cab8ade9514b49363221639a420d0e2acd4f1db509220a394f0e6239601ea5bd9350fa834bbd9ba1bebe2b11c52843a61186841d3d22b5e091bea95d987ccc4058d369968cfe462eace3ac6955911f0a11976250e9fdbc3e6faa6af57f3ffd368144ef358f73848fd6f20efb4917d28f8bb551e7e61c20814c9a41245f523f36cf4a34f2f515f1b30a2b531b99bc4378836c33e45346e2525b027c56f5362251a3faf55ccab9244164716d4ccc8b4716e59fa5f9788230dc8da00fdb6c236449f83e51cd13218ea7c27effe38cc67793b9acbc4638ae4628544b9de8ebf291198933bcd4037398c507adcd6612de6d8dc2a8cce52205202fda76f21851767b2427126df9726ebd0434b9438602f1a3ade89914aebe119485b48a80471237b09a1962c0b213c3c0321350bde3420649403906511c24bca715ba30c85f02c030621e0232ae620408e7366622ed961327acf24784f5152af3426b39b5e4f19d35c086200e2ccf07e6802672cd14dd747662b8f6f50b0ff3021b1649af962dd5cb4d33c3c2600068ddd0a9b905f8b04683440fddded5345cecaf6ed3798f95a1a46dc318e3ab5711595c7fd74254073fe4a6b12e9dd07e9b7d283af5ac4d2144be16ae5183f50507b37c59da04720131f2ff5122af2232426b7c30defa2d65510fa8f47a6d5f14dddad6ebb1a3d88caaaff9d9e20cef776449e883187acb3d79ecdd38ae93ef8abf257bae15eb97ab3f8712427ae1ab0dd95d7eb579156f8ce01b1d3eef83ba0ca91aa4b01fc0e8045c8d2e9eeb5eb70f3f91c2890ccc64a7bba8b8919940499d2e3db1b62059a1c1dc081f2e5b3d240e805d6bd83818fd812299577370c43341e9cd49f711f1761aa50d9159c5d10102954afb820ad3977597c206c5ce15093744c2beb582cb7a3c1b41954a705e762790c78e60f7fbc6af2b18e93f7dc37ee36388627ac04120cef317ad0b1a8052f30a9cc9c827caaeff8892f15c97830bf8acf09d26a3536f795b1cc2e9882048b0f822d5fd141fb9ce9ba1c3dc12a37412a231dc0d43b9c6c4f2f461d5da5046527c7cc73138376e9b20cb006218912e6acb3e2b7ca22ac4ce4083bf5ad022085446696fee410c4bae905694dd8aca8b1441c5f3e1123e7c16d51ade484ecc50cfbdeff24f50e3f5a8d6368ca4cd30f8bc16f59a879206f3d1f06a83964e0e1762632001e3c7b47fca105ae41479405c2d8af40a4cb4c91af709f04ac9b303dc31c3867705edad89b30c7c11d4a43d762fdb94176241a9f0ed57231f3d0efa16c2487574ca9d130287eb67e6d3e6f8565bdb0c0d44df43e1c0bb518a8ef9341a5fafba1a41779bac1cd0654ff1be3277c3aa228af50b4711c44080ecda033f23a857bd0707bf4d87a860c8916ac866a15dc3f97f8eb0c66c002ed056f06cb9cb84e1fe8d917598b4800ac033a5533e4230c5d854be1f7156c06623c6068ca30c16064b259c1bbf6f1bedc291d7b35ff83936c9103375c736215c23b06019653198b8578b6075f99945dbe8c9f5ba7e7d9c3ea1fcd2e47847fe3baa53fe300e7487ce7f23d4c3f589a2e8cc36ac6dcb10a90595cde30efaa117bdf8b5442525b9e5b7407dfc7aec4cd2c6093423c79ebeb6eb9b9d1044d149d3951387c9894c998620fcf868fc3441c1ebb224e6acbbd1ce82010a3212e5335a2da0fb85b4c6beea4210e81f2762bb5485df0d08588cb556a0ea3a7c3a9d211eb63e8c6a4ca8d364c557c791581c3edc60593926a09d56cf73c1ae1fee92a2d252d2316ee06cb3a5e4161ef295dab91512ff1c48d2d161a83827ecdc4ddf6960137f8c6f5bbbb1a6f41ce82b8f94716ee03267f14034ecf1d316f4a7bb1461e6eaacff2111cbf10059fd748821cdbbceac659a73c6c0876e008b0a001836fd860c4cc5fe9ef7e7c614fede49f6b1985d70bdf98bd104d99a51cf3cf01374ee48cb80a11eeeb698110b5c2a0a0c87a4b73388e7a556eed13648e98bcd23072bb27dd7694b3344577f07ee9290b2e4ec62d1322ca4cf0091ee2167c10fd2c0bde344fe91206793e4180467b1b86e0d32a5805bc254a6df8a1cc3b7b0af76951650627b24af71cb0df512a47b87b7a960da0d0195b61fcf10cb462754b98f93d0c1368c89d4b9aae382a5e3a110ebb0b133c1ca95e0b9b72a9414a5ff93d0e3d45d75c49eda0403eb2582e47191cf83d73d79a037d1f16612454214e1c67202c3ebe92a9b046261523bf5380cf18b279731e7510d0e215f8c459ecb224ba3575e0dbbe4f3214e34af0216a453daac63d100a9c4a0fac5987ce78c6788de51a7170cc7b4b915688fa88c2c4a88fbe041b832315a63ff1ba0a4c7f1c0eabd2f6c003390f4e3ce76f9f2de1137f801efb6f43f3a3e67cd4337b30e5be8f6085aaeda67c098081f3866ae9448238ffb79deb79e10ddc99bb591cad9552461010fa4f9e5b0ae60cb50d78d26191da6b31ae98f4a2051714a194735a74a53125c6b408c2a8cc0a5e52e51b0fc4e9108636c213fa7af17135011750a318eba568c834df544016a8f77dd5e4907a78a4430236a55c9009667b8935a0326287dab23ce65cca5185bbbe5a6d93622c41452546336e4a4712a3fd0866d0eafaad3f728b3a05dfcf6633cae62b494cf9c3daddb4fedb5a009c98ea6cf979129f5e2d9063cae6af300f0a8443fd25b414e4f5404a9a019d636f365866a0bd716794c933cf7d7293eb5b09694d7245e23ee1d314223d86abab9a2cb294310eb41137c836f60228e5d24930827106c16f82fdf1c69716e4ba0b3d692de91ed517ca5b28a6c74b74a8e0c823de0db44010e62eaed6b0fd756bedac58cdc0cce2b20fa05b2c519db6867c4574a42a41a8a9d903b3534eb62301f258c22d7128a5319d5c73cfc0b420834ea219bec8f1a6a68a0ec93a63a8e21c16c766037c208948beb268c83b9133b9af9c432c755cac7845ca47ba5425d583ed7d8ca9bffe6e04febcc5b374f02533ea6bb2d15ecf4da2f10d8c01ad4a88a7bad6daecd5a66ba4e0f13c38c61afaf3100a48af17026be56922f5362e717a893816a6d6cbd504c7fbd2c068b5a3aa5d2f2bb2bc1d1840b0d81a420399ddec97170378d18b60a0323bc60579e881932580639ce3bfb6e4cb8631716fe41803326b0e65e235cbcd513dddca8182a9046a8b5e74fef09875750eaf38bf991cb3800f3e3e611e5a3933155514d2b41ab50138ec0be376befe13a5669026edbeb216e189db794969b92e0af37e125eb51319332ab9cee6029465395ef5c2a26fb912d8f0ae4ac9b31cb265de939449ef54e4c565fbf3d7ed769f80174394688fe6a06f3c977ac5e3bdba9f222c0e67116b2b59156217901a27643d93ab3aaab02e42d1a6de7148585fc464028d58f726b21344d196aba5f18ecc1731e99f4a470494d99ecfc4566fe9df8e2f6b7d1ae10a254db2f259c27ac973b29dd51a917faeb0656d90913b0fe5d7a3c5b3002c39d0937c1f0168415f24bcd9c361ceed1785400598519bb249886f80d0c4025a8fa5800ee55cbff79c9df684c5ba46c0faae04896a8a4297dc71b2e30fe8fdc89a5a744e1caac32b915630a11f5fa857823b7f9592b2ad01a3fa8afa79c6bbd12786cad632a206797fdef9865c1d934f8fb3087099f8e9d78748654747cfdab18195056f8dd02fce06b6958d8a1c6914699797638e0dbc1bdd8371f04a55a99187ec54bc016424df0a91f4bf3b448939a5f06ca8931974d904de36be11e24b374e5b4951c311d87cfda86a52a9e1e77b3b574d27217194f9e14a0ae3c8c6cd09e56b049e6fe6400dee422af6d65d8fd055dc1237d0cc3997b0395a90b8af31a8bd48bab28f787835d64c0dd099cd9bea5d0fe1b9e4c021aa6a2cea4c1f7517781fed540809d3a468211c30aa12dd495308fc9044979c087669b4c537bf4300b970469481cf33b8322cce8280b1b621d354cdd4184d2320bb8f1f9a47d6ac7d05300ca9c7d39645018f9406afad6d370c70b5acc726b51152d2b1578ebac3028892c8347ea8a5c3d2072373b2b21167051867491ff86ff48de7a2d7ea7303d66224a497c8efde42a55242f285342e11a3b10fd9c51790c392ee5ae2ee38592564fb86f9c0e10e13b368cecdf5cb27abdba24d1c41d071c256900d7a2a7e14f35b985c385b387485c2a0ede9171436a3c6f1095b27412b9428a394372c2fcdb1672c61ad70ab11e62c8b736f3a30587e1914a6a6eaea740c45aed230b428d1d23dfd853e1a290f540988cdbc6f455b66444a28914c747d9a963041487c0187c1c1b9e54afef856430cfcc6cd09ec0296c1fd63883690a43d2c6c634d9623fa482336c86e767fc563a56e1a08348a4d4433141a744fff8b5dfb2a222e1cbead10374aa6b5c09c621c95d3d60cfc466ddb326fbefe5bd447b98cc95c15ba0f1b7f2b8f01bd45968112d9b806165adbdd9296215d6898240e71db522c05a8e45a749ad2fe33d0579363bee81cde83638e7d8393860cda0ac915e25da03fcf51280bfe12f38785e4a8f266f35fd387498185f8aac2e762f30a23f4c46904f89b38a84c2f865c4365bc6392e349514d3696c6445d300a363741df73c8d6bdb85c01da7d4aa3cd87e9c128c1da963f644bd041fa69caacb0128a4dc3f11d074a19661c104ad66614d4d9b909fe65964d14aa3a819d83b1d830266ef6d38f72ec17b48730c500ff8156baa89d3d1d9c1c2242a430dc7afb802b53c86707fa0349c76925851e9e5f0ee94a1a90d0533dd8d8b6194baa4c045e8b0b18081a2ab3974a1aaf6ed4aa60759d7d0eb1c0728abbed2ef0c1d02a49017a1079250bb69486b416e786544d1e47990bcf71af5bdf3c1e8174c6fdb813b63b285403a641aae0b07d8da190b8c9ee397cee5fd007614851d3d2b7ae9c85b459c6113ee2debc0ef7a2817210587af26f1dd61b6eef953247830c76ba0462068a9b1a61cf141b77c7bf6f759b92f2455a653eb70a327e4d53dfd5ebe63ec0e03346e42ce882a0b6095ffcb58e9d2554478265534ad461e37dfa77a819d10e96fd82a2d6e06cfce7ec9e2742f790def169297d2b802149e75a08ea9d1651882ff55bb00a4386be7784d89aeb2fe36ae12995b13939998cb8b2e74a69ee433b450c914eecb5139afcf1a4480e6105cd21973baf81d28e75a42ebf464ace214a7949fd893b526d681c2a8d6c22c2c5b34068fbd2a1a7d228c719db052de518405b313c78dbbe1614e3d7ac24939d24ce4094a7fe3a4cbad2e19fc701d7c63289a2598a934def10ffafd247eb039aa7c4658b8bdd6478527316149b5da8b2af41a5492923a5dbe1748fbd69a7a9101f06ee62c081c3aff8eb2ad87dd919853b939e5a4b58c8d4a08c8ea6caf9aff75d4f2827c88b14c3c7c56575770d8ed2660f7c62813454828b96878b43c46a5b2a27bad018abebe9fa7c77fb7893e4c9c71aa1d95a7f5ba9b9c14a5dcb785a18a41f6e801fdd2425aba8099091892af4b5beb7dff39d8ab85d89db87871e09836f78d02679bb8af70333d3230c09881777f4be66b633a55137b4d1a1cff05ed846871e0e1a27781a5eaf01d22e841e881539ef3aba434efef091d3ffb4d499ef07f57c3b6436566e27bd52df34c1c90caa1586010b939051c6a2c26bd462050f4b1f45606085082fff7bbf1480b19911af71801eafd49919b38119a581c5672e3da361e11330c23be2b506bdef6bbf265391501cd63044a3c2992ada7001d4a4efaf80f5d9df65d02b874f3f622cd888700dbdafe214fd414ece95304e58bda70d860ddef26d5fc02b1e3b1ad26538940a65a09e1e5e306904106035053d83d92981e7c10436d066d12814a324734993797932dbec9348d8a3c1d47efd08deef0f2feea8c46b5a603ae84b91c7811ebadca3703c55d973a91e81d7cb3f212d1424e0b471880a4403bb018c4a5bc3d26a4646b91948e32b0d0c176572a9dda8f2b46b4fe61aba58545bd8c85ae4c5279bd4578db77a21ae77bdcf845be816f8be65ec5534376941421b4ff45311cac7a0417fa5247086a4e334d4d5bf2ac4f9effaba24918e4e44492d77676ec21c9785e5f860cf0b2f276e767120032badedfae1284b857fabf681f4ffbb3622bcd66667bf8f71c4ea7794bbe4bdf4e6489d9066ce2a79b9268aea46e80c496cef2938e6290c4cc1b1b893e1383e01dd5b351868d9e6f8257e8903b0f4592aade8b13fe23d842ed52c3c557f1ca1bbb9c4675dd81a8925fa0dbcb10e1a823e6ad4bfbafe7b59d6886f7e44bf15a9b30ed5370fe6c2ac6cce310f07e759140d79e28dd9a1fc73030509abf274e5eda474b5f8392e9e82bc36e251913e0f5c486f6a92fcc03668e09455d78a8149d12b9b5354862a43a3de804562f953c38bca13780dc49be93c70e4c09c22ae1f9cb83afd88eb34b43a9de4d4c7998d878b8313f5433090f13539927ab982370b5e6bad30aa1f99037d650555d401a6e869da500b5acc5a3d41203ab974d94ec06c129875c2407490cba3e8c6e45654ed2f2c4bdb55a2f6059d20501c16d9751573293bd2dc067a97435feab151880643c3c588b781ed58a63666be562c1a9551dc09243db5f419222d17c086f02e1e49c79b10446080a5282b1be99a5fff411c59657d923c778add45cca198301647fdc85bfe483233b8944489ea6d238c3506309c57372c22c1f7513338238b70e138455a109c412ce9b68a85b7663b9b2681e10875717d2d24aaf2deffb7cbf04b2b629aaae7354925c595e627ecf06ff880679c4a55103f549f80102fb7df80a6fe5b964f54f9a9ef2a46a35126014edc53a21e0de85c492dac630628c8298cd5d848e369f1db4b1bf4a684ffa6dfd77ae4e97ed96a8542aa9c3e467886fa81d13be30674e51a1b3ef90c822daa1382e0b8dc3f78a7ced51320683b4dd41afe50cd611d870574ad7206b05fb7885f5e53b58737e50d33142f6cc42481e0e8a663b2e5623ab926f0ffdeb6d26f7a6cb32d53cd41780d7bfb42cc5b2e737121fde26048984b03bd1e7cc2c1c980dbc9254358bfdadddad3cf9ea908fb4e8dbe610228ef7945c0823834bb33046fe11ecbf96f0890e72ba9337b2183c32abc4f6d8fd37c4455a6fd53a926ef3b5de169b52e8054a09825eb00db573d28cf5153405886ec37588fd815492de1a119f49de8c9c8e1fa92647af5085b26e033a555c76ddd2fca82da19e2097c6202c1fa03d0bae54498809f8e34239aeccc544fc58d662c34d09770a6b13421555a711b7c09255c60f02483e150c5c32405c3af12773816800d04f17c0d61611f29da5d2a06b6c2060aa8332994c399c3907a57b7632a42fb7babfec50b3fa6f958de6a53842799e1412a52f7d2368fb2e13cc335aeef8c25906dce6bf50cbf967035906623eb24cbc913731d2a1c6bf17242a1960a8f982bb47a4b07924eba5eae212ee8311ac144d5f37c9fca0a485565e18ba1b088a10bfe691021fe624d2888992c0a1bd3faf8a4f3ec85a9a06a2ca4282881acf4d3f96c2e77538f4db8a9b61ab9d1b8001b917f540dba8b2f1d51e0f8614c7785698e8d3484004ebfbdc763921b720780124e876fba631a35ddbd2e9e8d980e24addb94374f5fa5252b018ebb6787840ae6f1a2ff6d4ea118ed902924acd82251087f5a52ce9e63954b0f7963e99f169c95a82d4901644f025fc1425673c02f648caa7de8942641ea80b92a2d45d88b0c7f2ce993f037fa58921caa5d052517f120994dee841d8e90f01a4276eaa613d98a64a68128719715e05e5546bc60c047913186f9ae15a4fe0040fa6943d015495ec08b17b2eb20c18ce3b279d06a0976f14ee2ff91f1bb36447c54553c384e5d0c82b36cb4d44fd00a1f6d19a7d852638a5a919562bd74634ed8de4d1a054835b363ad503a08f5ca1c8e660f7882edee207feb0021ba045f8f1ef542a7ff3cf744c5770ecd16544be029191376bdc2c44b5303a6acbe6c16d57c867532b4d669a9eda34085b73f6afe660502926d784997651184f153eab5cd8047b6f8b9171db0342bda4e2d7bc96bb440b5e66acf246241872a5b058a52ee5676c9c8a88fe0b201baa609e2729baf49602dfc5f69f389d6802bae66688660056944e4b3571167455490a94e6be19afa3310c3ff0f7b06145b951c5904c6f66bf491d13a6c73ec680039fb847c2ec5542b80fa4b20b49b104a0738585dc1e82d6ab3c538c192caea5f294694708a52e7a64cbdbd05631b9ccb8c916f46b725d864d1c942bc638d775e1eb5eb1603dbc85b7cb069153c4fce39115bd7041d1d45eeecc7e5df631b1e01f0b0d67b3140c09f9da91c320d13ba946ddbe1d46e13238dc47d7513a38f0350021c95dade483e69a8b950e1701c7c665af92b36fbbaad8b1cd8114880443b03a69666da42361425d951a1e604cab4c488949a8dc4162b390c3da39418b19fd839d6620047d22582462e0f67d8c53a241155828f2828248eb2b73fb8d6a329f361bef0714ae685d5d7cbd67ae4d08c1e0115828f24aef2c745252c4eb2b76b7243235ad98c15fca4c98465122d91b02980c25240f52c464cda14416978ae90a00fa8e15c55ec18e7779df81a14565ab81ec712beb1e0516461c4cfe13f57c8bd2f552ea3753f6af4294b9d8f98b236151f3a9ced565c95b12af16cb0d61142c774a441793d3d44448537653d444372b9aa01429a33169ca4bad9f0db99c3a80a856d7c08d8065e9a42554943ecc9061c1dc636657abb2dc009b0038a4070774ca45f2cbddcd1ea6b8b156fbf1171784cf6fd46fd4f934929cfacb90f1a7a0403ac011ee78e88383b4f92c561500cad97baf59bb32735c218ef2baa09295c87cf9c002825b8e95ef60799a6a947b045d32410fb75138c70e7558513d9a7b94ac13f0aa63b4fbfa05484fbe7102dddaa4bd72416cc69641217b413b46c6597d3eb72e2401ffe80f98c562d7da751fd9ab84b8b0ca6c3c53ee09ad1cf0b5a734c14a2056c901206e97376331214bbe5bdf91e5955e7974963379482a83b6b4c63c02586775c06384be876980a8233db75b3a146c8fb97f8ee1c3b657f0769f8aedd0d1e28029562fc4f1b20770c4fd028c4bfd132715a2aa8d68006b135ad7cafba801a53800718f4e7804462b125d80930f141159512f276622cf55fd592c06551c4e85a31d51b059fc0879730a70bbcf362d430f3fc20dde6be140a2c711a75b2602dbef84d25260489db5b3e6002f34743f4367f6541ed994009d660be00238ba4a22076ba994c7c1806eb383fea291bd491f31e19422998b3d4276d302801a023a203c8ce91920161bf6b0d4930b1d408075cc0750564b22a7dc1d5f9860ad12a398ae43df821e01116a7d92a421da008473b23305e1819bd03654e61041f37086018896ca59f9edeb4330ec16c95bc72cb3eecd1ccfdb6dd7e1f43d0741aaf264210dc98ea80da625ba62dba112766d5188b8949ee2890588c83c5e3e36c594491a9826e5ae7d3a350230a45a0dcca52a415e905608d03d78e5f38e06e4d7027687b921b730ad3909295a764897ad2c884f1b4a61b931ed03806388a11e2637734a3d409c8c273047af48049ab39120d4f4b943be1c342032f47df8fdce1a00fe223189958e9aaa3e406c91279bd9f727beb4ba64d757c1038f1fde43cac27174fa0ef8ba0c1351c3eda8a870ef291b6da7e6918a37f9172855640953295f6a5e1c1200a4ddfded5f06e333bc02e94f2df9016084275549429da16f08bf686b632f800073441dba5b25218a95a64044457b5669af684f7c61c5e9ad1918f2ebb758f677e95f5274faa4eb4a5589205df935ad4eb30bca5353448f46522bb4cd6b73b7c1922e986a397e281c7fcbf23ed7566c13eefc0e293b741cb724fc50afd7ca092541d29602c51e289de3611f0001413300592b845147ce0c064032a19c8a4d2a6c9930454f01f3d40cd97a4c5f03657f70f42d60223aca318881a1e396ddc79eb36a89937dc111688a6cfc83d9d9f4ab0c244b35787593bbfaf4efa1169f5a0f268744618cd054afe27b02e337a7e91fc0eb0c44d0954ea5962d2128234e2e5c705ad25bb665a8f5efd734d2742e9495dc7efc3779b899226d7099a73fb1f62af4d4316ffd697dc6b32d973686825ac7d7b9187c6352253581f3891d57bde4b4354a64f71838c7390f5acb7a911c7db23988c7f09fd4d87496e15ee74e69cb46d808b417abeeec7f75ca1c2323e73c361c082a55d38d35cf8dde8e0707b0a02c07122c19e4434f190eaaae180825d027680f1eaec4fa891582fc9f68519ef7c6e7b50acbb077f456a00a1b92603712abcf6590cf7a5ec80cfc15e172f2ba4452e13b2c3b61eb3405dafa64d71a467cbcc814b78af114024d96557ea8373f077e3e04509fa69473f086ee89d1720353fa441478a6ebacc21c86d4c11db6ea914bd235377e96caae9733cc43445a3a9eadff5f57e748f531142fc649bfeb5df867884e47be2e34af9aed43df99b00812fbae3ef04d83788720bbd7fc6f80d4ce57dfc97273c30ea4011ff600a1faa203292bcbc7f59365a8a95cce5e9f42ea41933a1ca72d8db8960f204173f51982a85bb10061b4304497b56c84c548de60688ebd651d8625860c5077cf26cf2c24ecda4e97875cec8cea592ec24076cd56d76faf382c827b6c687b7873939fbdcc036cb3f97341314740c27dd272a8a43ca6cf52abddc423749a3b10385423c7acdee2afd7a4f1a21dfa591239929a3e0a8c7d45678d40a167064946913579884b2e62f42f2fcff68fffd2cf05fcac7c41cbe85a0178c1ae667035ed4f095d14f9411230329b487b5b349c367d4cdb30f38a67277c778d4d67f42b8a4ec9b34435e86a313df3f5f30d0273bd8e4aafc5943b17010f363879ee3c94d3fc39f72c27ff53580de411c5b686a16aaaf0d3eacf61552a5380c3d2e97c1de9c0edc0fd02ff6dc2e212ba5c20cf78a4a001a39c589f1e25bc0bb506e999989b6e19c44b16f98d86179da0b9d9f91f5e36f589c8e272618b20ce4361178f5cbe15b14a8a9e8cf260194701a2658016b96160ce9858aa1313d0b1425611a94d2089a55611b4b576033ce44fa6c8767fced849076fa1d7adc48b4fc062b99d3900ed9510521abf3e9f53cbd43059249446c3c2d589130b9ebe79c423d688b94f91b59cc8c1c4faadb1a5cbbb77fbf8fac209bcdb850fee7faf44df5dd197af44a8cae568749e749b3fc32312d9ddff3f01635423f677b8ca291ee28bd4a8741249fbb9d30c5709b17297c4ae18efc0fad0f00db08392100cce618f47c2356166ba18149ad989c7d043189c18f553a89ebe312f0211f2685408fcf36cb08b03d4943328cffd7aa3aa5054240089ac038e304f4ea99388f5074472e99582611866834a951ec5c8dd683f5f0424532f0bbec7690de72f28d9b9888626ed1eb038ac79e4bf7e1b976c6b28d1934ec0f2dbda7616c0c0f12086fcc5619ed9ab59b241474a0244ea76ecd83c0cba45cba45693e6c418ba3878bafec30d0c07b00bd0db7207a12c80623d08839f60f4a390e020a93c1d9b43c3e493bb0a76142cad280ad64ac0dfc1b169878fb7a221862728e897b8bcf5327d77f70006270acba3cd14674541fcd1bb64d655ac373c4af7ae7a324b53e1fe100c51d82986e954f26959687c9d2e67f2295f788673419be50b4fda3748fbfea585dfc2643c74833a5e441847e9ed36a3e79c20fd2bf6f8e38017c503ee7407c079fed559c7c4a940af76e8f8c087cd8f8d97ce2d0fb3ff8f9be6261c3f2f86359a3626d84dcadb16a05b55f1a892285611aa3e91082898f75d873cf16831914bf35a92fd1685cd0acde5de7f1f289cc13e3d346ad212b9343060719932b8ece56014855bd20e32533299ac63ff253d4e74626b1457f2a5990236544c41f370d055a30906ab6c74cf09da6762d96057c600d199e5d9f8c37b5db67c12c3775b1688c6e48d170c4254a0b013e0ab6d8a86fe23282eac0cd1e43859763f83f045e2e8f0ff51c39dcc4ecac6f945f8afbbefc06a43158999f4935466c8ed89c2587a0157e2d26c4473ede6292322e6e11810d44cad0fb63234c6424086739ebcdaac4ceec56b4a25408a15b132b27cb03666960c0877470a136d0d0540354debadaba2156f8ce8ab2711230d85b20bc133374c361be8c6b1092805c7c19dd2089410e7e86727bad81b97bba4fb6da6439b287ade143be60c0bc1d92205afa6d3e7b7a34f87d742eb182f60b9db5ee283eb31afb1b8354dd723f5b9a7f5c2242e8c705d5b32b696e5f2812b5f9509474f48ebe5bd95a76bf4538b4351e736428e9025d0101ddf28d57496ea12e4cf1d603643a6ae3d11048acd2f56f52464bf1fb49a313396fde52fdb8abea8510663a4a2c7a1e72a3298235f41e23ccb66bfaf925f979080c73320bccfb8bfb5435b647b2cbe7fb61facb9cae926a48cc9de11cfe4fed76cbb1bd3632f4893fa480158b556facb408f77b6893188de464046ac00c9566d8ae958a6b8fa0c1b3a66453e13854c85321f389040cd367035a48855aea86695cbca1fc67ee9dab8c80c359472546d884f0a6b8a9309ce13bdb59e639d4e8efb78d3bd9cc27cf746d6eda11aa9f2e0b68782e0faa27dd31db38eb49c238de771b457c38892ed42fc6c1b4d163619f60e671ce65f7cc323b3072f8d68db1a9e5ba61e42a3133c8e41aaf4d8d714e2d74b1dc8f901bf367d4b3b74a9f0042bcd42658c3a596e8a900f61ee10294a625ca1728a94273ac3faf8f261bcf65d3ef7dadded34b246624b82a4579d41fcd6f898388de0e51ee075143e2eb00519811718306cff5d57565c78909c58819360fa8b4611ea61c1171e1558206c1e4e77731a143cf0bc1302c9d1f2beadb1e2b66ea2a45e812a8aef13c9ed5a55a24521249786ef0ee1e074c91dc037a25fec35d6c92451e5aaebb2fc3341062899666ca31968e7c6c9094d72ba9829e0cabbab17324ee416cd852c5405909abfec57375f8c36c5eff2d511ee222a7b4438ed249f348a68b5560339d1ebd4eed9088010b9120b2e9bf8ff2534d166daac503e95828e45c1d5a7c57026ddd122693d749d7224a9adbc0eda0c321574a5c20b17ef5bad6a7c292314b4f413323bcfcd15d4c3f014989bad19d368020dd9b02eb83f5975c68a17612d9f9af8fcc07d6ac1b555e32ab1bd450b02fddfde09c94d26f6de82030cbf2c2c0b5825dca086b48daf0f234e5c4a465fdb071b99808127426142cc1c11a1b5a565945a389855d07e98b1e553acbd8d1c29b346835c440731024d4c6c64990ab4402814beb87d59e75102086217088f1d23cde8d549cb480998436acc40968255722f2c5dc535be8d113ae621ff1bb1a8b13576d09314845ec528d98f0557c5f814898d6f2ecb238b3009f7181ed9cae1d5e15178ab2c78f04c17b88a9ff7ef794558c63370ca7865b91a93b8a60ab259cf2792211ba4f6acce88e73dbc820eed992da8d365d004f35f2e8660701821be38c107c5493b16fca105a15ac217959b39b83793578046e30ee6514d0971ee35d832fc38e96aebef7e1967f9b3553df71e230dbe259160f51cdc9a0c55c60f63b4ca39391d6fa9901b535d20837c6de112023b8c7121b5635c8d8b5ec556292bc7a2b85c8e69a1192bc4c3f705862b416530b8149c63ffed98fc8dff876fa21526450901bafe1b588f2e80d5022a7b99b31b4b0fead3fa32a70b601cb2eaf3b205a9fcc48cf6adcb370a20f88cc016741338aaa98e9d001142ac0ee31f568b8f9268699f64313b22cb4f7c7794f9f55595d863399710c8f68400dc4c4f4d18ae0505ae9524608e1893370e4eb2a5c74cff7729faf308c1e06d1180de3d48b982a38d43b8bfdc17ecd4c7349a329b7e64e7b29853f48551ebbe43c869274804bb2c6529d6966f106a2e1606a5c303eee0a47bfa3aaaccdc1cbd0f3af68b14b19f4189946ded51cc35f191a546d82cd09fd1b7236d8598088a5d663efc226166e76688fe2e60a1de7c108f07332c1ef84ea3e0406c2f3ff8399c9dc6ed681856a48c15459a4732e8221011e5fbdc608ce420fb3c4ea8f87779c2e8dbe4bfb31f72f6e1ec75aa410746e01c1065c13b6545c540bd87cc3527f1726ae10ccab059ee9829c7bb90da6ec3d6b2ca8a2a52915d2af6c932f5243d93d6867740b289e480641120d7a0df971017d5a6e74695c6e2dc515c70d1e0db18d4bbe1958e5b627a6592f5f88bdd124f35628b3825d26ad30c058746748d870a6a9442fdfb7b29520a2626bf89a4257f83df77b9a5dac980ff0b81f450a3340aa7f484a87a949e5ee6c14321e0f1f533bfd759e4ed3f7962a653a811439460ba243e353caa77262979d0a3019e105ec7ed053112351917246045521c8e408bb766310240afe616cc6769c9b7180ee194b0f8cd5046a6895faded2c84187f8fcbefa9e53d88594bef08173593a8b24d62715f54621b56e9c5de54c4a87ca48cda10c13154a9682d40702c104f55890ab034d14ffbdd6017ddc4c2bea3d4a03803930cc1c157e9a959b3dd9898c77efb09f4f20661013ef1b1c7f4a033a004ea2043078e0218cd9e60623f7584a8302eb546653a3ae78e1bf6c8917878d66ce75033caf18bf0891d5f4fecc1a69d6e55fe1641132989dc91e6c095ce93d9a527f34cccab22b82716bebc09740e51ed84ccaef1c122e9f970eae1a94f769f46b342befa5e7424307605205919ea90e1f7a0dbf3a4d28e65f1d3ca04c957129c64e3b6420463c8d4dc6800c830d3bcb963ed535a30610c7a71f7c51687c0f092576598d8931004b44f01063aa77c0c1f33f75ebb6307ea59b1727877e8c104ea33a29cf164b4b5a0205d56907bf6db7f5ee45fcdd79d2f15eeceee2db3e458841ab122a049578e6c31c69b35a350db543d39d75af890427e30914f3d5c540da34dfb6393218fd76203f2c614491764932ec90a18c138b2670258320479bb0d1cd606e345532564ae953ecef89e7796706ba1a4549be570cce8f6c281a0805e570c74df88cc77146790cc9f709767b52329c7dfc27ddc31bf52f1524c3dd8db6f99dc02f08e6300403c7ae1d2246ed46d35f4e60bbe8887531772f4e4c3f953add4f1a6c0d8a3295a300912a36b00ad048981b0f4b6e2248d445d5e2fdffc0006f490f078eff3103d1b22dae8fd4d787369404c812bdc1ae8bb4f12159d87825cf56dbd22b5848559e1412804c2c1f84d5eec48d57cddf3ea3daae01538810f86995be2b22cfa180274e97d3910d05845c8ed00b2e2646d24538c94d6b57ac1142927f25ee54ddd823d2bbf2a0c1e35b4b485c85fe4bf0e6ab2438084cbe38cf3e5892ab8f4b42e0d83ca9996de012fc136086710949bd892e3ff20f4b2fec76c1b26fdbf3e8529ff53fa6f584133fe492df2a685058b2f12302d6690cbe3c23857c4e407d85e47f9e66c2ac231be138298b39710847e9ca338f5c57ced675f4d7a0891842bbb8c2a7b3d534b01093ab88562d684a6242417f3b17db7b0d9dfbc3559a514aaddf78455d741900249d7738a7b12a5395f3055e01c0cf7c1f9218747092f0ff753b03cad2f6a2358a7dde355948485d20f011f93ca34154a93a6e2f1e79a7a4f976d1ad1b84318f49ff4b4ee383342456ff302cb26e58e70a14acd3913f30b6d3124903565e9577133140f09893e952374c3ad13c5b49e15ea1edd8a58ce7fa4ba4d0acb9a5d2f5784bd1bcafddb4a311ffd6cc322ea93eb86f7e19c4432bea86161598280cda6c8e61965b5d53b7789525142a447570aa874a20ac0a04b67f9c222cde5418716484871559d00b0bc1296d25159f20cd1216fe0558c8a5cbc2ca91944431c4fc11e364479fb1480d6a3c4d5d5338832355283efd365433ebef58a3414931815219ffbb4107c8817b8c553648a31facb61863c3233df7d8b83546d6cdfcbc167b30114ba4436ec645606a0266c556225f2d07dccbf2398045a6bf1c45f79410ad0cb4ce7c5841962aa00bb797c60acca554687b80799153bfdb51f781f0df387fc0bc7cdb31e507d40aea310ffc08de8673cf0c0664b2d20c8dc1a1e715d0ff4f052d0d7e0be4a3aa2218f982bb1bfd4510a74a4f95dd744230d2ca617382a0a24627099f39c08d30f68c5d8309c8ba2804ff2240ad35eab9316b104953ef3963ac8c7bc9988cabd4e4b21040a181f1506706f26b9ccaaa4d41e63461849c494283d1e3396ade895aef2abba39dd3f154376fa613064361c94dc0435ad0b374395db17635bd4af95c110189f4425ec67658d59ed9fc4362cf8000f8759679689d6093514a606a812ab55a67300153ba6d37ec51c282072f1fc07c88398878c8ab3ee1e1653ef34893df1a419291362714e09951e83dd9e989f321e002e0efe044d587a665dd031e9cfe219a4efc051df94c1acb29022708c6504d89395e8cb5e14e40166e5a8e09298bee70664605e34fbee761b78e68bd939e2338955fa92085fd53de16cc22b3d8a1be709b38775108b183aa4963b0f0888600e1575f0575c42a835eed62227ce8d6db6a5f876f5a8d7c4c5ff96529a3ecd0c666613c61bdb0b6e230a716c712fc48038d99af22e3f31c110af2a84345058715d92222a5a5feae614196cc0d106de9e5c3902b3e6df150681022d8a6e827bc0cf76138376f79d358fc78a25563163239b24524aad1e595e3466534caedb154a7c8595f650eb4f355ec95d541e7383a68da882265497711c078226d8fec9a30fdd921946b8d2c60927ebf208fc63902f0ca85e72f8415ffbbaa96d4e6fb56988114a42b5a03173c963f8e34f4574830172efc258315e7d7ba92287e32d79250466471434aa322018a31e4c4f157159a34cba1e8d2ad19e82bc3b011161d95a8959da3daa9f46f2efae1129da985560644c77b5c04de98a730cef611b66ea4f8ba222722a00191b0790368a942cf73a21d4cf26f837451c013734555a84b72deaae38744a2b22405026a2d0b677aeacfef2e407a1ea07282a6f6c3e4ebe6abaf342eba52a442e342d38ecbf405cca44ce7cedd0f3af307749cb7e95dbff4c9261457e0d9c686c5f46f5fe8fe384b2d8c17a09991892b86b7494cdadcb72e78afe44e1b862d0bb8dcaa4534eab540da915518566da86e0caec121d056a0f1db1bf3acaddc9041aa768446f97043d01598d26df356c10063e30a9bf6a8a21589408ddef932809bc2cf8e8cf03db5e1c8118223bf02ac0125e0204f4f5a7cb185c8eb8f39637652265ed8be8c4007f78503f5e8ead8b9e9e0e7db02c35ca378086ee076af0492c708db609924a80e59580000a368cf888cdd38d895c0106de2c24daea3f5229936c404d3e30726f18b1caf69836146b1106b6fe428700aff6a4a06276098aeeff7e5416e8fc62b621769b47682fd37d352e72008ad95d13d6826e135d468cef1deb67fc6277909e2da0ba8f0a509a01f8857596facb6c1984ce38abc812e43c710d6d187594cf677ce40368af523822f2742c61c18c62d4819727aca2f5f1295ee4de7052fe7458db5e7a5994c9a41cf3578bd65dd63d4a280495d8221acb89e3ae0a8b315d90360631b3a759007186ea47ab328e592a70e50908553b343543de48d8ba881e0c1c7a681129a51772e6a8ed995a9bf7d60936b3fadfc8872b23dcbca4b57ad260aad8e5563a222e89b22463238f82f65ff317d420b362184b01cb5eef28a6e675145929b819c046bc7172a1a2658270774d7e8d06aa1a2b189f8a0683f9e4ca99a41ad94237b9bc7850ab29d5d64d89c9085ccd889294ec3b1d451b505a21b556ed946e4929d39cdbbe895ea2bd8dd38aae85b3c3fef9cea2ad2a2a8b729547168127c2b3b42a0c895044271607d110f4fa4e7ff52b79b206db45289e2bd21cb9204faedaa0e207175d165cf4a2441011a081180b78d1f2decc997e70144a602eff2c1bd0b6ad0135a30d55ada2b08e286800ac096c9d9838083fa2b41c0361a4ac0e069a9e46e4594a4bfae27acf7291afb32e40089fea1eadd748f817b40ad6dda229c3ec78d0696f780fda7dfb81ad7c9b1ce4683660a7db797eea7a00a1874aeef1a47c4e3f6bb74814aeb95c144815fb1edb767c5d484e4b50f3af23715868c2cb3bed0317cc27ca7143c3065e428d06933b4409fe8394f7344314f5c566aa8b55dc6823a4812d03bca708537b8bc9392ee0861cacfb8585fed01a595f619c70c080381c30034f327f75141c597ad7bd2410e2b760fa582ae820b1336ceebaf7958a57151718d57922d5df4b9264db174aaba4af2d6716449e83023e08730a66bb2e60faa7bd3c185b0ac66edd19494ae508ce3add8a944431bee1d6804f12e431b27f1725b45498fe7d834a5b47ce295e3053a1e798385799b6646ad7be246c433024b13722b7b0ffe2d1819ac408734d8e4bc780f6b0931298693363c99e68cfdad196cb56e21c4d90e0207f19701b24422d9a35742086c71d83f76c55ac016d14983a0d66c0f38b55f7e0eb3146b36c0e244396dae4bbc426b42e4052dd625d10691c1df3d645a01347330cea9da0ae47cd3d2ec79b6ef016ac1250665c0bc024f6270015a16ddb317b0ce4efabdac72332fa20c5ee1cbdb234834ff63e7f291cd75b0047b0b3d21849f1508e823e1cc36a5a771beff6f41a048affa0b1292b13308c98686b105f33ef4467a547e6b40c5e91f1e19650e9c4095373b6075118e5187494ad8cb0aa8b652578618a2cd15172314183d39c7ea3693accf65d60cd485750bbe2390b2a41bd7935f219781bb1ae312e332dc5a9551770ef3da9cc18fea40262e75c615c81478091d3d230fa78c60878c65edf35be60e32097724629e75b63fcc586a9a31c3e1d7ae733e6af452c668d1984a647add56ce19f8ceafea522f38d182dadd41c2418a82198dd36bb39c955e1df1edd34c128e6dd64482d42fedc86f092677c9a496268f6bf083f2606d04f95fabc2a9fadd5f8d1373fb75f0b5c853f23187254439c1af7f65826853a1f708a2cde091595545b5c0ecd29366ccaf67122c706ed6815d6f7204b3499c5a7fae7f12a208d46ccffeed6b839ada70682f419b7041890326122772018325dfe81ad88327eef05415d8d9aee5c79d6f072341335f192407e8aa28b2f07f7df247a6ea55578e682059b21dfc10ff9a32a656666da68660841d078563b0991af95a1ac43315d7058e306a2a30b5b453d13aeb96501356cef3b6961daf6480ccda6086abc98fa214efb568a6fa9908d7d100cd8549552194665d19688794a020069e9d1a1af2773dc8b616d7f6dcb23d3e9e16398e629d8e44408efed9ae18b72806458a61a4ca1a79b517cc676353d67faaa99f8e13a2697ea8bc4873f555eff101f48292b15611207b55ed6cf9882001fb8f45b0fc4da901e9a50241f860ca87047f8c41296b7a6ab7be206841c60a8a8d704985ec23be7bb812c33d65a894f650252498aa6b349d1d6fefeab661631ca5ff6819a32e50ab4ff81e08c63ff59876096c40423fe676dd7ea018c42658f055b0e7e131ee4a99aa05d02737505e9ac5583c7be063693744cb41bcb903ed4c9a5202a9761481b0101d0d5731e2c4131a6686105241057b44d8207ba1617c1ed41fa1ec5b4c357e9d7aa6767e0300b63466277fce2aa299aab550b32cb3892056717c000b3397eef1b2f4d7a655a7dfa1267a34b4f5c67386ddd613872c4632119aa4b0e0bfe4a949b58ce38d7b7d5f8f9574ab07175da1df8287b72286178dae578145304c210167bcbd64aafa6d9d4f01d6580feaa77dd66721d408bed1f770b04b560614ead1ec5accec125c78e1dbc1cc264e6bbc4f2b2cd05d9ab92ae8df35b53f565018f05bff7cd8bfd44e3e564b37f5dbe4b9d880ff2a2af8fdc8e2ab9e31fdd24a7b91672fd251a7d615340114dbcd5d213462147d425ba1d45bed0baa531570fd63ccb1526a84dd93ef37b28a76bdc0a55a1b40837337708dd7aa67101b38009623685a2ea30ebe65638415024537b8f6411354cb774a6ddc152d4f9bf08760772d6f82436594ffde49ddd020b381d441deaae7b340512f62cc14f17273e78cd756cc6deec2a956bfd10685d2bcb7b867e6684018a2abf82841a1eb052fcc4572df46dd474b5af72020ec6ed003a251f42eea7ed09cbda5f6e03de3847d108630fbfcd523dbe254cf60024c20bdd621f9ef752309c0c2937bd8471fbeb31cc128fdefc9a5e123158e2932dde031a7d8b3269836ea02d4f09d0cabbc752af5260ca8317d453d8c9bb3789db69a34e1f070ac4263ee9a53553c44696bd91fb595296197c2c80e8f63c1ad24b34374adccae4f79bee962e46099b14606d7ea98db23fc0f6d19b0ecd6d0a622936cf9ebbdc434b2f66ace6c8737a1af15a10ddd9dbca46904bac021a6106706cd0416e3f1203c1fa40e3195fa4da198c345f23d56d031807defb50ecc96b255cd25c0a8ff1086211eb33f1cf90c2c3ba6bfbd90e855c10d0242ecfd509cb49f971bcb8a00c28d2c7bd1f988e2ce9ebb74b4b355360b5008131a6cbbe12ff019ee30b4d5a5ee0427041e596555ea7704b86199819a627414ef0507f92454424853f5afab87042d735ac15c276feb9d38514e3d736128004ada955ca067a2eced1aa8b990e952f01ee88f03305f0826cbd1cfc40cc8d6d25dcb2bf4f980fd2a05b7132c7e46c9209911d8fa4a183e32c4e944a7146a29b7cc8241d4a8c13f326451210bb28bdb83304ada288ef0db846365e3dc2bf1739c4e993234fe6b21eab5290f0da895fa7350b1d327bbb67be456c025afefb3dffac3d135ffab55feab09b46710c5c9348468cd3b93224815de79cfff281ef062f045540bb2a3c381525da0fdf48303318357ff16cb8106945027421f90f293d4066a05f9ba1c9625f1a928c052dceea3a440f4299fe26018a1d8143e35da868e572b1000548bb72c2b148a5e60c9a34724041350e9be2c146bfa15eb0508e9c6b3e940c7a858333eaaf4ad0088d1fb148abe36055f0fd89a2b2005f938a3d2b70d775a35057db6462bf74d491e46bf1de7ce33a9790572af0f148caeeb841c48678a1590d36fe0ea40d129c6003e5f345e2cfd0fbb927b54ebe4c0fa70b846c760ac90faf87f0c3f2620c9484863595e3e4c434c54fa49ea6f0fabb62995223943b9f66acffc092e430c07be273f10503024c6299c409a4511cc07861441938a69e02f11dcd08aca566e9e351ad2d1e0f4694b63a8b8dfd0006762ce141853900ddb1aee2975f2d400074fedb4625f023dd756442ac088a1d2895e004d12082a6dc6789690435887ebceb74da86b198cf0a6f019b7389cca9616cb8883662e4564561384f362c1f3792835c3c38b3aa35a9f7ab5eed510e2f06e561d3b937dcea4b5a85c2b0373289d742676aa32a421301a1c80643e68865c02c2bb0013b6b19d914c1a17a2c91a1a916ffdf7ece1096531e7fc83ed4bf20e34b109b3458239b173063edcc7d61119208093f5ed8125d1bb8642a12f0ba1914b783a8b25012d434171b03eacd1c527421b01d9599438654961d119d211873c93293f04683e53224198a045cf287203b4eb18de4690ff8faef85d22ea54b49553749182023e4f3f7d30490a0ab19f1b003233996d243d5808a4672c3de8d3d5f35c877635ada3d23f5c2d4428ede9c9b8111f2366d4608c125e4baa7958bec4de8d7cf206a4f27651b23eecf9b9e62d8b3624cd74a2246c9527f12da85fadb2b08cf44aa78e15ba2524563258bfede329d3eb26dbc8564e9625b99306e3203eb583ef53792a45db09d6bdff660c2beb03338d7118aa063c03fa046d99fdb686ab3b21f01a2dfee3aab8245a3f9cb9336466ff176ed2b60f26d4b8ec6ea8285a0665be0f20a4db33305edb9fc22d6a78b56b0151deb719e42524dd819f7b332a74382ad63bc6cab69d260125cd9b8a426383768ecd88d180fb9210a921e17dfc93908e0db90d395fd04d870ed932a297c3e3b7a4188bc43e0419558e41f85797fbda6bb77e39b45097fd0fc16968ef8ae522e1a7264dac444a2bd0f4d4ec22db106d828344d37d1565a1fad795a36087267b390d3b7753465666e7eb91ec7afaf048682e17fd89d25c712d518f8d43e84cef34cf632629fa2cef7bf9a43c8fcce4bb631607b67215ed2f59c6e9ab305dd8cf58a980bc23d4b8a0022f1025a086cb8d9222332139f24b40a79a0df278d70e38720a1c5fd8c0e2fe204b6ba7b9c88c34b4d163763b439ed7a404ca1d09565e3fbde52010e8852d11f0eb7d47812d8c9f80c884aa240103eea78213a849edb1a4bed4d3194b929e9ea7011c4791776d7bad1b4a16375e1f4360e0cd5243d60d6a0d2a7c5abb38aaea0a4919d18135733a3ceea1dba37349d09d706f548929d34012f322d56fdf078d4029769dd71448c1dc43564051dfb94f52a843247bd320bded956caf554dfd85fdc991989d12a53bc1eb81468da0e5a07e089b8b09c8cf212415ec292898f7275acc2ccbb219047178557048d890ba85362df2aeee83e74de3b9b2f54ae8bef732365743fd4f5e150e5729446501d5c84538dac530d60c34fbf36b03f8465a2bfc1609c251465fead4ae71a0628c4bf401805efca8c32262c9b0c851b3a0d39bd197610857403b4bd7b6af10e43d586716e70487cabddee304ea3e06ec5f15dc544ce978d55202c563aff6027ad16ac1660856dea9a91b079e18b3c1def01556243b89f38e9aa61e67d39375463e6d23858e7c31e73ef2678272c6d8d029d4522fd1197916058cd41e73668236b3e0abe2300f19d2cc7489056b57c45894e6aa2432be00690100eeb24b9f047db98191e67138f83b635f8bedc2c5b2794c571cc65d6c4d20c46064dfd29595804aa7bb2041469aacc34baa4b1e240b203123d11b41d4fdcf726fff5e88f807b67e88939f11104cd507bb3dbd0e335ea1fb6c206173afc214c03c88f5db525295f8558742501ea252ff895fc5d12db02809d0322f47a868fdedb39449537bdcd6089a835bf48e384c388564c7b325e6b0c20329b3d361340e18aa12c56bbeadd3c5f1c243c9cb3df5778a22a6c9ab55189860a535c085790c6ce5a9c9a7af05b5f802bd04e71c016250c3c350c3fd0078fe3157c03495cbbc65cfdc62b6bac8b35deb2f0cad67d2a4d604a4d55b67e2f0dedfd7fb30980ae7b185067d1fd04ca80ad38fe066745e09151f97a31b418d1c377c4682e6e4926b4902d9c74c0d4d4c98a3f47a89ef86c89f8cac2e259e79431333023568220ad3645cbf8b470a6af254a00125669d66e718811c7ac785e1d8ad8a9928fa43bcd4719095ef7cc26c860d88f0b034793e8d776b775c930f1c84a4f279cc1d7263c0c94ec4c909098c546e131df07e36870dfbe73dfe5b3518a57568c0a2991cd56cc742dd213ade0bf4caf2b12419cf71abb861bb5c4a9fa915b0cc0e7a25cb340396bb4d2cd60d1dc1f3d54ee46cdd13cccc18a03db72c33311ca03cf9769169bfe27537355fc8db6c379be26d1522d439f796669996262a508bf601be8e20e7a74f129a603f5545189b0164e4563f5bcf97831f93122db697506dba799107d69b21719a2a3460110c468fce7930839294b3d7268fe63de89128243e35faa6e78c73d4c17f0a29c1c137f2f39cd5eeb0cb76498532d2787f746112d55f7019bd06c66602b18403534b32bab2a7600881d25026e1cf711eeda544c78f962e39cc3e86c1366fc6c2ce5d887105e1c92eca6d5ecc42296dc97c332fb0ec7145463a2183dd8654e875ca4ffbca284e0953c0870e9d3072c3e7a897403e8792646be44f1534aa77ade41eb96e9d5d8dac97628255b869335223dc46ae507021a141ac1e323fda5234f3a9a9313b501fda6e607990846aea34e69e5202481b88420833aeb35fd58f3f43bfc9564190d59c05389d90e4530960b6c83ec0ba54df1cc62b784c6424e946672e3c12d7f5dc6673ebcbc90da85d8d74c9076e4dcf0fd7e1c5906b15405c799c4e00702a6541ada2414ce1dfca6ac0a682c7209744ad60744d5d3270fabe412051310a9ff89f9a133b004d9d116404a195b2d06cc541a23a4bfbd8aa93e2c593cc28c66d959d4b94380bd09899f944d16ece81ef5a708dcd290e6c4db7148141e507684aabf4f12f792dd639d1571c1f4eab50b6b277a2892779df1a9e30fbedbce0bdfd2f13694d0751a452d8146d43fa6be177ecb7ea7f0efb338b8789fde96bf050983ecce49976e42264b3710336ff85833549c253fa58e1e82110dad4664b9ce5f2fe0fbcba28fe7b6128757d298154c81174d19b29a2c1edc4468e5e25b56f8a6340ec41840e2bc2491387cfb18d889beadb9c40cd0c3a0e8f29e580e7e7086b57052fe639519053f2017c5c3ff4c51677d9ed8f209a639511b11dc7ba4ce75ccabb0f0a33e30371947704418898d88469bb1d462a898466513a41592b84d66244ca425162bf475dc06fe5a64de6074674bd62256b82709aea1080b82f2b85901d1762c9d2eb0fdbbecbe43a6048643b1f0ed65dc511e33d2b7d67562bf32dd7c991530a44b8a03f85993ebd4ac1a32c98e64fe30784dcf078332df842cb558bd677619250dd76efcc012ed493ac303056e655d027aa40f00718ea0183e64c1001493518f31cce6a7c76b90113ca62f5187197219fa0748ebd125644410666ce70d0ae0221af3db1110d217e3a9bec92a998bb511641d4a3299bdacdc9751184a7f67ff014739171ecd315f0db80100d92ab08b6224e0efd08d2b508e385621b859f0ee0cbf44ae2630dbbecd260829b8165ada8a120d0b5a7503cd26d29e3930e00cf2264a1f24bb7038535c001abee20c87b2b49a5b201eb8a2a5a6f297161b8555de6516297b4c3d66da473f544662289cf1551152268f912c1c9c5c2ee419e15f83eac8e526cdf3f3b8cf12b0a2d1a99d1091e33ee5b7928bdcb35d7db1c4a3714c222202eec32494a2151b96ebad066a0e18bd1137bcfb157d5a42b108ec3bd88cbe0bac4772a4163bc633fa35146ea996d2a107ca3c56febb4d1fc8b326b7ce081716cb0125fad15b5eddd8ee09bc17bc5b1e8d4acbab5501984ccd6c2e29f5ffce5e15c5b5f927728ff9927a04dd6d38f1382bf2f4a2dd9093389b5fbae5501cd12bb4a8d2caf18a625a19ab872091052651eec5fdcf2c1ef675cdd29ecbcefc4232e1dbc77719d826c391d2e4e238bcc2d15d6fd8fde830ade9c82ecfc242042c3948d844f467cc25f26b35ef27bf098c716514fd2e9f9a3ce46743065a11ae3c66fab00d4b452a8850f204f8d9f654eca932822a66b35a23d676a70d9b78685f56d11f6ae62911c217a1b39bb03835d030c2dc675cebb43b9d82f7c8542102ea05e9935acfa19065ea00f2a35a3096f0771c647a20cb14b92d7475bcd670cb4fa5f7cfddfedb25c9d4ad2537376cca37cc6506d2aa28b15c8b79a06e6bf6c6021c0f2793749618184c68b2abc63f467518a956e5116ea452873373dc2c53141bbd4c044e2b0403584b2a7aa2330401262ef25c20637dc9ba32d2c66b840d392a8a55b7c34719bb2a52d13ebf8ffb9362253734e148250b518865aa76f5526c2f635f52c5df8f922140cec21bc75ec9a1a638b10ea109a98319d388472cdea01e9e09a0ef30a7681ff9e76174d5eee00947a034c859eacaf2611ca57f7d1715ef02a5d79f8546b8895e3e2537446ed832ac999ac240f2d7b002c4d91741d0b72d8628eec47c8dc8116a22d76b0a9aa9fa9e61a0a4d850d7921885dabe0e0d71a84cfa9b8030e280a404fa3ad84cc1e045ee1b558b27f6ebff87025885b44703b77e740f568f4934ef884ce59c3ef3801715b1ee243b3a30f800951dd1b30582c91cf22ee59d7f849575f3f8128f49980fe5c6ca03f177cbd0faf2d1e6172cf93504321b93b7f5c50aa3c157bd8119d1b64fa6a25115e4dc9400e38346b218aaf7df05be2898b5d1b01c42487a1c0a84020d14f5dd71df006ba046b2a07f2515f0286bdba40ca6563751e4d32b458c6ba3af6320014a01376a1cd078a224ca8f8e6a51fc256379a2ae89a4d902a169076f5b728ee11d3ff3eac96e606737e003af8376d3a1348384c24591f456859ad235f869e285b032edcac0a93036ce8b0e17f23863591d52767b59d31a91daa205d605922147fddbf01ae711609aa1058369914ee66efbb8867a23500c36713bdaf0ae8482a5c2c779f75406b98f6d257cb93796df3b17576dcbe8c48111730c00f75529a22a2c4427f39c478f501a52b1a8e0c7cb664dfd080202d3e86172a178f351b92612c9b1dade46eb16555a807bec8e07466d004c254b6044dfd4aeb888cc00242e068af9dbae20dc6ea015cb3031a0c4faa5420ca703a1d0f066d54822641171946b47507ad029e8549a1779794812c50852ca99acb720ead9779568bf57d1969db560102c1ba6c6778afbb9377a3a6b94796bfdbd16f534c23af7d662ca631369bec2da59432d10b950a260a67e268f579abd13667238f94324a82ded4ecc081c6250b180554a07d9912c7ce9a160de07213c3c40c15356dc8e4c061d482511bcbe5a36d84a96266d1239ca1bf336f80dc5961b492864593734c1824670e23725ec8b933e60b961d179035287e5c619b93858c8e0be3436d8d991b993232753d277b2e1f4489d462c7eef48d0f81cc193a4ba69cd181c366dc29264c0ba02653f4c46d41e943e74cd52fd9884031e5a8e34e8d3a6d3a0c983c20c8f384edcf9d307aaeec0de646482d851d2963415274b903060c99ded740a608731664859b1c3960d28476b977e74967858d3f7ce00411e285035ef0b429a2a3870a2970a51130b32b695174d47003223423248b8fb0e3169af30b98261bb820b3e7c899b3326f6c987480094294f315a73e72e8a009a991c46b878189a156a00fdd16252fb0e6dc947149f1e2c5103a491a6f7780fa9f1542d8e8ec1892e64a9913230f2f5668b0b945d2e0de8c20e264c699990933616b88c4f479d325c5598d17d98b172408a0fd109312034e720616377e946cb5f08af1d6a30b1c16f4ce0c2371a80439b224cc4f804f1c254fae80fdb972751cb824683ffa68c12386c4051ca413a61ae017da952326b214d98c7181ebe12b6185860f2b57c6885129b16091e265a2cfdb9c3aa71b1c0a23117169d0bcd85263cccec50257050f5814b02957ce2d5f9003d00a019136b917466a941f941d19a10f9614639c531bbfb829594471c2a58a9f2e2562ac8cd7b831be53250f1f0f215c68c489ed68936cfb42a65742851cb12a78ea548ce0f38dd94fe5d5d8110f0d167d6c40394fb62f6b74c00811c10b6c479b3c3605cd12442b1b8373e44e193579ad0950928a392776a8a0e2048d39e7c879f3171e4f3152746dd941064b912cade54b0b366408b2b68ad869c36546af38c00834bac6ca68e99344ed8b8920ab3178c6e008b91167c71d93b6ea9dca73fe482983c1a298e6069767dec010c9216913a6088e224729695cd8d1c60f3f615b84acb870da98c83509b22699cc02828d588f1368289aecd1f101b7b6ba275933fef031731343058d2a7dc878dd13cb1b96a122712edad2bcf0c0b5c84031690b82b6bedb6dec1b89c58f65aab7254651bb3c965d514edcb053745b63002d6865c0a29c719171654b99982e30b51e492278bc2c515387434a1d3c7e8e6f47be889b58113131b5262bce9c801b4a6a44c92ac2f0d2870b08f0a0f1f2c787193569e69508c01102074e599b0c3c416251cce4bc65ed5961a508122216173b3a4c10f9020357e54d849e05548ce122244e93b433baf266b1371526501a13695b4e64d1a205803a798e7ac04cf8c8a272d3fc89c3626dcf0d185f8e5c294e92106961e7c8b14c9a973b441f5eecf831c2973e2c44c045bcd009456d736f0ddcc94a63e30c189b277beb7dc48b170ec2dc58e375e5448b1545f6856bd3426b09111866c6e4285e8c4745ce529881e51102a3d7a2ef5e1ac111a7656e04639f2c53bc8cf9ba077ae6a4e1a14336f10196b66affddc965ae1730a0173ae4f068b105ec461c1b7148f14b0996231e3374a4906950d303ce8f1b376436a68c5cce8e56a2dcf98ae225c70e8325696d578824cdc2f6ce6135d6b8a801e3ed09dd69f4c2c5c34093b4197bb0b8e499c2be365964689d9961a37342f1b26217813d7accbc49c216e48d9a9e7befedf3c571114f649da9ed506bab01b7697831718659c2b676878e4e97277b977befbd77f9e7ce4f505ecc520706ac5029feb0012589579e33016b46306df6801dcf7a6418730c630676747b73f7f4482142972e5374903d71cb20059b1e4474d0b0c18664136b74e9a1c6426b499732275dea5089bdbd986326e4459cd007073245d4e2d0a859b1e54473737eb071078e971b347386e023565b8ada582e1cc35cc4c9012519e79e7539f34a82e78b2e0cd2471d76efbd371b11a58b4c15a4e8e27173b163abc7091b74c6ce265dc2ca0b770647943a4edc8cd129cbb20cc012a310375d61c60c29cbb32ccb3213e965a9d4cbf2875aaac40f3334803cd13337025b96393f9af7a7bebcfb7dee76bbfd278a1d368b74c132a7b059c46c4a571694ae1f778371618394abdc989b526ceb3aa326888c4f1d8d21658aa4d5ad38999c5951c442c48893166390a83f3af54ee9342ba420eb9898d97364ec9ac105f9a48800c6e46c4e51ac82595a762dcce5b23b95bb1f39f3b8652746069f3051b4ba80bd403291f77091325486658db9a121c7c9123ff74f133b695486d040c1b664b780a3e38b9626264608a2828b8e2224cba58f16b03d47b8214a6a98178d961c687ce4b161460a05f2ef8d02197929b871222ceecc9326713a49df7bcf98d68f3b7de8c8b68890b637ed67e7cee1eb564742df7befbdcf32c80cda05019d69bad37def9a382e54d83921054ddc59e6363774f3f4908b92f6c28e9c1686aff483aa9b90b0ce683a373140267611a5ce45dc1958925387b96d6991824d0f9935b43626ecde7bef175e0bf93fb379dfa9b2cc453bb272dd824ce1f28a1a1c2cf6d829cad8a3857708dc6ca46249312d59929405413285b5fca53127038f092878e430b91acbadabb420cc1e2763fcc88d90dc4776e8f4093715bdfdc3a85dee3628cec28870a933f346242285c79126469a90c9d248f6f088347c8c790286438617d60f4b3ae493623a239d6ed959388f4026286a9b498c3ff88cfd481e79501dd9f2762ec1e146e52d86153d7419cb85b32b4cd8c0655959711ad96265c84452c56d091b154392e585a3da72c6bbf28489645a477a883973c3069b4b452644c40d11b464c57901466b579022bd7d17cff24949bae744991d1e67926367111f40c4194aced4d48001e5cb87dabd59b6e828d58c372501e6c69b23689a80993112e5cf1e2349196ee67211225b5ca40a10b31397e624cdcf0a06c4291a91a0583b636288a2f84f6954238eb9c1114607c647580eb23a387ccca1393202d7102d1e56cc7abccdc833262cc91f227dd0ce8ca17811823bb645ebd440999832675b38dedab07befbd4b354c3cee958e356b51e478701161939d42904e69c0c0a814b1ce98f8f6ffe0d236bde5e724518bcc092f3073538c3cd15c580b4ec5723aa0681de19c357992e59e23ec36408b8122c81c96156a2bd2364dadb2d672ba081ad69c28c8b83a3b6667102c421dd84326075918dc93b3320b76801d371d76a2bc5133970139383dc25c8c5d99bb9a4e73693bbb000e3745e4b4c4b0e0215366ca8e2f3ad09cd4b166c6e263c3d69c386246c588442c89d96f9bac217bee88e9c2a449bedb579a9d655eb898e167ed4d7206db3e890121a370274c8d0a3811d6c8951b6f8d45b854b472c0a913e38b6c4d3693410b911d31a47889f145ccd053ef1bc91a9b9fddfee1bdb7d5f0748d5359e3281feffd1fe4aed78cfc0072c8a3e48a63de01a4d05a8fd070bab161c3cd860d1b366c805df916678cec184b9d468f3f6365a9a4c7fa99ee14d0e31f5618c09d0a7afc06f870a7861e7f0738c58fcbee944f7d2c410ad3619ce452e52cbce24ae136dc16a3e3b66ca3e3c739301eebf8710c2ca3e30701630c60391d3f081c47009ca53f610a1d7f04adf049375d2a03e00bf9712b3c4fe059fca47bef05629577a759ee7a18985d824a97b3da5cccc51659c51b79458c361b6dea1aaead2e32b5948bc7f356d78a21aeadae15614834a8343f8c7803746ee5ae6c004c9557986b9bc37ace397afe166a450b37d2bc557493e6e2250be6d4caf91f040484fbeecbfde679feed101474aebb5ceabd77690671207e0acdcfa529ccbd2c4d0984ca72af42daaccc1288079b98a016597a7b26613b0b4292a2fdaeb19189d9bd196474faf4995ba627a6ae012a0f8db8e87919f20183e706278405860cf42dd9c362e245d0162ede9d16405ce0d038679b59909ae2ae0b101719a697aff3e97c32a37cd2f004a5c1cdeb7c1a0bc13ed393977669339f9e4e1cfa49c31394863732dd74cfb52b2c627029ee81b1e5e886cbcb11016c624f501aaa80a83e50a443fdae31496231a13bc244ce2df5f5bbc644ed4912a9dfb533227df7bbf664cc0c8aea5b966559966559965a6bad4bd3346f5c59963bb3cadc69d06f9625d4debebd77ce39e74bb7f7a6c0bd77e79c31c6186badf7d69af79b7326d1b38989d430ce7a97e6ee040a2a3a4f11412854dd75809455950ac5d4b3b9a61e863afec212b1334d2ba3b1fc0a2710cfa5f10bc559efd2347b1df46e87b3ee14bec2aa9cb14dfd27750057ca4a3765a9c7e606144093e21f966fa785797116daad774e2f61742de25e2457ce725fafef6fabfdc8225aae177d0b52ac7747bba2ddce34cda223bd43f18e9718689ed9db3d8f97fba8c8687fe760a7da342a3ab2d23b1e90fc2790e2b3f9d992630ae426f345e4a199969e8fdf3c32459cbc2dff3cfaf63cdb2bb7418e3a57f369833c347fc745700a5c115a0ab3bd0244a0972fe2cddfc0347b1d76df1b80067968f20f7928228b02394ae8cd1f91a37a6fe2ac1cb545dc26f3cf27a37535875ad548afedd1df237e1ebd79b49e79e85bdbb34d37277acd831e7be875e03d51fbe5974fc48305487f7ffa7b0ff1f634779c0bb90fe5cf94875a63dcf19fe7699a3b4799fbaec1fd668a532bbb9cb3fabb4ca1df3539586ad4639533fb01da99e58ea0dfb5386569ea24e8772d4e988eb2598b03e642bf6b7280aca5f103d7cf8e0e01f50ca86d47a3199958c65c1a04b583fd214bab6a475899355cb0e8b4b0e6aaa54197247133749461c2c696ab08dd94db2bd7adf2f9a7b7433fbdbdc63ebdbd707c7a7b917bfaa9a79f79fa9994d1d6454d859f2d42583576f6e04003e54e991d368ec71cdb9020476aa8b17b4d3b4353a48bc88f22db903842deaa3ce1aa1b637f9c8833a3216646094be64647eb840d316dac71cb8cec8a9d2bc6196c8b8f279e3b64fa2063f0513bf182cd70b2d0f14873737285cdaf069173d6c6a3881e36b775c123c348450b071356277fc8c952f7c2ab8ccd64726c99c0026ba302069b1f042d9501186f66e27e20c183c62e8df183c41ad2c54c8b251e7182a40b868bae1f746c7e6cd452c41827d818a9f1c4c79f38160ee3a0ca7d7a9e52e3ca5892af2343cab0398e0089a1e518448f1036bf3aa726cb4d73e1f08b9e91a848be7861e7eb0deb013e7892e4786b01a7caed57871a9564d5910c2ef334bf56e4e4cc344f73bc820c56dbe6699e55687199b199ff1b5bc11536e68ea779b682034671c3165692cd5c9886c574d8e6dad8cc2f7bef60992184cd3ca9067bc7d85121c6663e418dbdca689c0ca1c39640e38c6087d59ff9d50435b684111cabd3aef9ee079f2872e78f2316326ce64f652c3ac4cb3c821cace657984c0710176c896c228d4904aec5912df5d80982c5a25b67dcbb4547422dd164f1e30e199bf9a532842d91b1c6f1263208e27ffd75bd0ae2ff553f91551202dfb7aa6ff47ba3a527b2fc89ec8427527822dbf444768227b2169ec852f0ba09bfef282928e18fd62088a3477aa4f50ae98f9ec8fa9ec8fe13d9f5892cd31359099ec80e9fc83a3d91ad709f02aea2a5162af027ac7402270a7ad2263e8021ff609652e01a48c0452449db0bb7816ec2cfc43b5092b697aee39fc0415839c64292b637898b98ab2c5de2d88be3af2529061f69bb93acefdbb363313c9687f8f1ff12591a36ee648ecaf9f7f7cd07abf765d736c3f210631cdc747988df68393da7e97cbff4207cbfb45e0dd17fe5f3fdd22fad57dbb7f9875faf30eb7b34efa469eea4699ae6d09039640e9926119199979e0f7d7e3ef43ff44b3b99a3ccbf9b4f96e2bf2ea1ffe8afbcc4e27c27cd2f2df5424b42e65791697eafd72bcbb2dcc9bd4b336807ed24163235ddf9a995f6f1cb9aed96ebf885b807bbb73b596e9d3ce572ed36eb1acee9449ac972d479a7e3cf5eb94c6bac732ef79a98316a4bd228717cd44df893386ed34df87f3ad2161f3b9c6ec21fe458ce061d468a90b698ae2775137e249eb14ea43f9e8b3c1f8949db5ce457be4f9e3e3e04a8fc5dc97bbc1eaf27ecb9f5f57cf24a0e047dd0ef64e905c4e5e6b6658e8e4b31336abd2dc73ad665cfa8e47de666ce652fe79c332f5f674d02f7cc270ff16bdc9325d697d0b73b598e7909097d29b6935a2a48aec4caca52591ac9c64ec75f6ee5282e2d95d533b6e9ea3847978e79c75f86e5a8bbc626ade32fc9b41466f1a75c0159707978fb105780891c5f516d3eed749cb970f378f944b99906b49ac7d534e621fea09fb4d5721aa97532479d751dbfe673a7f0d56ff4b9cd72ce3d332db593a7695626cd76d244f63ba18490589499c4b0b080885acdd5734e0e3b5ec09d2a1f6badf1961ca4b1e0a6fc6e58617afe333d6b3a1a418ff90c311e62ac3263e164f9b9e7afa0a0c76e584a01384c983367dab4e92dc6ca41fdec05ad1e74dfd2f1972511ef51203d1e84e6f3355616cb5ff9aba7ea267cd105dc29ddcb070eb728a96a9a96c9b5bd6ebdfc04dc29dea3497d9e69aa5555a99bdf2a25bf8256ad93ab462681bed548bce54e057dfe5b7e98f34cdaa6977f953a50f93901772a27e05a28d72009dc5e379e6caf5b6f73d283be60c26cac15787766c0c1eaab5b45091d0fb6440f481a7be60cfd39fc798bc396286ba861776930b2fc614ba4706ed8dd7a73865643c7e74a64776b30c4ee817e770643049dbb075a4f7ee60ca5ee7530bf670022de6569b90af310e70caddaf1a99baea6c65401c29628ffb0bb27b24972f97a02e95d6382d6f39f6b725e3dffc6ff548e41a76e578530619a4bd52ba1af3046164489c261cb35dd73e9de3b831c1038b6e4281c36d7484bda407ad7ca94e1bbf7de5cbbbc2557bf79f8e7cdf2efbe3783fd1c5cbdde37f7bdf8eefe815331e36b060e9ab7b5383c6cb840c98154e3b243043823e81329670c172d7884e0a862864c1f0178c9a166842772c8eaf2ee496673cec6a04c414752471c1850cac4dd3863aabc9569c32a42e3b805c96fce9dda3de8ae19a3640a6f2c6d0e907302458b24264e1c39e18840d416a1087133262dc61a0619507ff9b4654c35a68650d4ce4624b3214c8e679aaca1311903e39c5263e349b20bce5816d4538521139edcb38ed2564113156cb0f0e031f146974d88469c6409d3446c8b5b59e6dbcb55b877ce755af253066ba8d84972fd2172c2016de0640109a3960279cf376ec6b0b8e04b8a1a2d2f3fd07091f1c6c78dd915214bb67e70f2d39e3849fe207bc0e072b689bbd3419c570b293bdc1457d061b3913557f443b7a28caf5926ce8ad19a33d300a14646640b8e2a648a9c6cca6ad40d897b92a7c59d176ae27a1805a9a9990186e58c8a2363f69c7471284e0a18e1e81882440b1523194bee800d4711ca0b2349b2d856bde79a0b27a64ebae409968c316bd6c4e49c0570c3479f3c5fd6583039d588315374c9c0d8d1444ff2861f1854415af9bc38d2b2d4f96f8931d6eaeaf9f19a98b05e6abcfbbb23767d579dcfdf712b6d06fd59a2df0fe71a2440d0df0ffa7bb61b74902f2fafed799e98b723d047879ec785fef2201e2440f977e814babf6f1b02eea6f91ceccf7f3ff316e3ef5dfcbc6cf2f66c392040fe5288f3dee427ee5da0dea9796b3b62bd1d3640c4bdec75305ff732c8ff3b03fc39efdf25361128efdea069be367bef1d021b3077e2decc42f086c6038a4cee7cd13366079c338db9437b6de02c8b4a914b45961e1762e061d13564ae2c8e2e0303830f275e4efcc0c1448e91aa16509e88d17186850d093e3bbe72b0a013c735278112b03845a40439d307ec66e1e28285160d28715960d46921829799923068da9248a0cb8b97a21a8ca48c6b278d17133ce2b00901da991f4884eab6c088b94991278d59124a8c1a2d62c4f93acd9849f831cd96334b7888d1413136f70486989b3353736a6cd5a1d193e3c7290742903f6c8688cdc1e86196350982c70a181230278c1f8e5c5d5b6f5ea868d360b299cc838aecfcd3a3850d185702999f1ac4a8fdaed1b56143f1850d7ade7bff9eb83437188a629cdefb4355dd99fccfcffa8d7b4acef929e3ac772f4d9db1794b21541337ce5450f4485f7df96f6df7b7f9efee9bb76bdf8feef2dae2fc0745936aa4493552fc17e39c73ce39e3ab33d3b5703fcfb9cfbd33cb19fbdc99e58c1933d4d0dd0e33dda99dde993e265d018ae9dc0953dfd4042b13cedad4773864ba533bfd56e0faee67c7f72b64a9920c0b0b4b08cb86024b0f8845cf7fa63df5092980ba69b74b5cd777aeeef239f61667e1adae1c5de3b0318dd1a07a8bd3d470178deb2af416f3d17fdbbcd575eeca39c2aa7a9bc7caba46cb6d56cb5dd64075fd675a87a3eb57ebe074fd4fa5eb1f9a79b253a7ebd770c7ca47d73f800f78e074fd1a8848aae8fa3708d3f5770042320d569e24c53c7db8ae787dd175fd588c4ccf1db33d598c388e6d7cd8e0e444e8fa315d9f6416961fb262b1ebb53f6a5e2274cd86b547cc0417323318471c97ed441db89e8d141ffb8d92460c031551c9806e6693dc789b03c506971d36adcbc3e5065a98b6387fd89cb3be9f8156f4dc26a5e79c73ce64d2f63bc6bf3fe32a12baaed3a3eb3ac5ae95e8d26702d273cf9f5ae91819e64b73e19caa689a26d5383ddea9ab86bf74938b34ffeb4f8002b01408ba49ff19263da3350d0f70d75bbbe9d73a2369740f30feeab797b75c0b1a2731320f9de87c955e74d2fbf80d80914f5079981fc38c9487e5eea48f8bf92cbb740f76f7601793ead216cb0551a4ed5708eec75b7988fb5e719123d11a17711159c2b8dbdc1be313e889d22122554dd7a155e81cf6d2270f70d720e4a146d28196b3b98ef11b8cd44d5617d381a54db7497f05e74ec2937e17d3f8a89bf4abc6d48cec3cd3f47fa89f7ae9234b8d57de8c38e6a852dfb8ae776b595ae5a83bbc163406a183a35a8eda5f96aff2d2b22ccdbf24708fba1ed20ffab5d61d4c80276d791d1f3b38f5b16b5e8dbb6f137edee9130ebf86b49cd70442a373834e570a330429afdf353ac5b6353a594c5a5b679c55348f9ce956c524a30694d7aec25ad05062850ec99823ad3e4cda74a4a1c205472a240854e472565e2f9d47e606a62ae7d499533727cd1c376c042db55ead74d37ec28ff1df0781ffe207817fb75eddf557fc5d3ffe10f9affefc72345001a0f746e57b31407d8fead33ccfdd6edbe003b1be351c7b6bc8346b48b354438e6a55abfd55fb6f8eda7d69304dd3c406c84d7b00bcf6e9dea79d9fd6611e9a18c3be32ebde7bcfbdf7de3adf7befd4bd3a8bd56c7a9eaff29295004b664bd62c852e5c0bf92ff4fc17eed47dc24d500f784cad69fc4dc167793536f5be21d2cfbd10413ad979edf943736d2b9c6bcbd47bbdb64261cfc2b60a5d2ba0427f7b2434c83f54db3430b974537ebae0d07aa5e156ab8ce25e08dee35e88fb81f31ee50d3d8fc896436bee81187a74bd427f48d3b51aae67a1f5695575931832c9e3c1f28bc78320ae8e3d3fdf46dd9477105016eb2d3e6aa98da5dbd4f4d517ebf9d8731b9c1c9d46ea646b7eed5af3abc45f24f09f20014efce74aec569907d1c9affb9575f2de0aa6719785ea785866bf3fec85487b214edd94f5b3a56c53b67a9000e567623fef4df6525760d2da87e65716f0b479b1254e25493858cdafb29c1563bab0257c756c4e01176764330fb2692c34a8d0b1994341c926e6b6b0d8cc97b458d4e469ce6b50f921c7669e44854577c6770724d412fb52db962c586ce64a48d812196336f432b519b0baf9e88d0063ac817231b68cb8ca8db5993147b5651b900a53cc444bd15b336d69c97cb3880f9a75162a4ae6e152d652b12f652d6d29f1e94ac93c3497b03a061b396bcd95ba72ce5c5869ab6ba7628ed2af1fbf52310f4da7ae1ca595b2bab9a58485f1ef2f3a1ee5a323df13d2c9ec282f1d8b8e405a278e5a0aaf46c53c343ff73ae8d288ab9bdf413fba7910c43e810f5caf526196347b4832124b3a159d8ad7428b04d7cd477d41dfea21779f53514b51f0e5c4e594c349cca9accbcc09cda9e8f4e534e644d6cdde3ef5d6a9e864ece6fb764b6d6d51122e47b56a72492d4799c86e02652db54b71dd6c95b0ba07c1106a084a66bac97cf52f5bf26008094a46dd64be84bf2c8564badfa9e8c4d5cd8fe04ada3a15f79745272e2db557b26ebe9258371fa5c292b64e45acfe01ee4b6d71d82a757573e9782d98af04256d8dc4baf94a5e4ac7e007d7ab720d86088600fce05f16a8d476b5d76088fdc217ae2194bf896c08e0aa145c95ccf6b197281cefabefa28890e54a8424064100812bd113d9cd8bb8749359f2a262d198d64562abafa8acc80c2d0f8382f467ee2b22f3f122315e3456446686a24345c9a1a2e4d05137999f665e84a493a323426aa92088b2884e13217593f944d6f43d2f3a6aa28c75c6380b91c0186858671445725a2af8e617d16929e19b5f84cc51bf37bfe898a37cbd9ed7ca276d97c8ba79f419c5b84c0e7312bb5a7375ed5e07a7adb234cdddee3c8180dcca3a5c300b2243511eafc7eb39e570fa72f2ba1684b6847a1d9cb89cba2e845d10bb5fd782c9bb90a3c385afa11e06bb5ff0ba16cc47531e057329d1a73d0f1374a7af099013d41111f53a38e5c843f381655227af3c349dbe6e5151af831357516fb743ba90861af190f805b40b461f0f895f30a65d40cb43f3f7c3bf0b667968fa7c47473f9ed3561e9affeb7570e2ca43938290531044f0cbe01359210f82100a9fc8eef56a3f707ddd0404aeab9fb4752a1a61191575d387a2a46e325f294dda4239717127af8c71be4442ed073abe2c945c8e22f61fdfbd905f3608259787e62f7969295368c96bc9ab9b8f7ff8f7c34e6d6234bef0cf87a1927c7214d00928392d05758492833a421df3d07c1f1f760a6ad2b6c82dcbacb750c76e3e945c8e6aa1926639aa35c5928c39cad85ba72254f24ee16ebecfe89d8a770ae3be7b33084a6ff1d1c353c74b6641c6aed7fce6efb8f6f1615f42cb51476b3b822c47e5377fa96cc9a835913ef2bdd1588e6a9d8e8e24e0cae2ca91a32e1b8de2578ee2cd1033223bf269a7628e6a97968e392ae821a9a3c56bc134df692b470199e0ca51bc2eaf1c0594c3c97ca7b01c55c2d150e5012ee21e6c22a762373fe51eec212e0425d7cdef151dbbf93cde12d175f351de16158bbcba6955e455968bd2ee54b1484c4b9dacf944745aeab25f68455c456470bd35c580d69628d9d1230fab9bbd554f5ee5232dc57a5b9434c58a8c398ae8a8a52edb0627a76291a9c56eaa5c5e4466dd244aebe603ef51ac9bbf5bf7e315f8796d4f20bfb70c92c0bd94bb16cc28a064978e497fcc97f0ea5bb54bc76e7ed956c269a9a16e328b92bba2a496928065be11d696919751d8576b34d6cd6c74eb2d0f869aa2241b0cb3de1ae500f6d6e8cb48cc88ac9bbfc3d91423cb51ad06b31c65aec1ea2dcffcdb9a68ddd490dfcce64be0aa9901ab284bf1404f34680522240110909053141305c674f72657c9557a6929a13fbffc2ac3c4721450b11762ffd0df5e88f285b28604a1df2bbdf2f07c949739f2f07ca1f3d10ce75be534697bb625573fff3ccbf2f0fc3020642a1c9e0f7556f55317e9adaf9f6796b3b0133d4f7c9665255a4f5fc3f3fc2ba5bf8cba09bfaa7ac0bdc24b61b03ed00b39d0ab684392f5f5af0a3915c6be3e5ffa25a6677aa19010be225a60019a2db0c0020bae8842a6b7c04978c0bdc25bc0f49be90affa2bf5fd533fdf374bfafbe8af43e777a95f7283cee59087af87dd34bf0b79f39ca47f5556f95518c2f78e24f4dad20aafe82f56ac357fd1587a7aae2c1a9b7facb52f1e0d405177c88aab75a43d8f0557fc186affa10389455fcea26a695c703f282bef5cc431ffa2daffb7e6fbe054ea24385b760f520f5c247794bd4f903794bd497bee42470172e2d39dd2bfc35f7f89f40bcc55df897af370f2908ffdf2a93c05dc3da5678a99780e32ee4b7a3403c2025b4547da2aa3160c050c1d37058c15be50c19a0fef63a0060b783fa75e5f178bcffdbebb03e9a7b2470e79dbf55be5f01cf90e195d0d2e097bdfbeacdf0197c1b783c20d08752bd552676e0dfdf4ffdbd55be44f43304833fdfbde80a846a0d0a9feaabfeabef37716f9ac4654113d76f16346869bf59d08cf5aea19e87f5d1ff7174ae4bb1ae98d6d7bf2bb2fa654b61ec25ef0a854261a99126cf443970aadfc0ab5e8affbe02c79d73dcb5f1f1ebaf57d5346dcf60f0834ff51c5e03aa95c36b50b5de0e3af0373c7a7b4f5d7dde87cb81af7220efc25f4ec16ba43069eb5e06eb077fbffeef71312821ffe35e06ebdf35488009fef7b7a3affa567cef45efefff35e7b773e044f6c76fdfc089ec04bc25f6f5c3847ac03528fcdd0fd16030f8c160505541e8c1f6ecbe7f20e7cf7fbfbf3dce7fbfdd3bf3d0f748370f7d9d03dfa36b1b5c3fc89df7be15c88635285c0bb0fbe157ad59432a787aaa356b081400d62001763ffcdd0f1f25e2754de997ad88d5716f5d31f23916ae48dbec85e90ab0fba88f5a39587ff7b7e36001861cac3ffc0bf50ff5b88216e82b78fce8cacb476f0fb8b6571dc8e3ed55e73d9a3d90c07f56fe5355f4d50ffad46f89fa5551f5a2ebe9417dfe17f842de3f9003fd8fdf3efc9593d07f386faf3ad40b797bd52b7814f3d6e1f09f7f90fbeeefe39efa2786bf193ec3f378c7f02a27ea19be25ea1832fc9901c30361f8dbf39061c5f000d869390cbc02aeebb84e6a3e4ed2361f858f12f19ea7aaea9a8faafa3ce003d77677de2ba1a52d0f484c7b1d783cf5d5351f851d80e472d45d79441cf845bcdd7259c3c1c16900455454c4814fa491d4208a7e9bf6b0d2ffb7e7caf3f1d7e1fe1ebd1aa98fda48246d35b2ab5fc6f34c4a8ae07104aff2b0ee9d027e7bbb745555abbafa50578ac3abaf26fd069e94f4543ce9813c495555fdd5795c23f310bfae7b5287e9e7a46e62353247a13ff4f8359f8d7597962614274cf87ba570f15120f468f38638f08538f087f8edb8a851f47dbc2576df8fb7bbff90823f8e7e10453512090909e95121bf3ffd05fcdf07794becc147354f187c1e6f55551edf00eeb7a7f4c46e955515aaff1e05e2b8e35ef0510c81aefe13bbca5b1e011e575f0217fe08de852b067c2143ffbd95fe71f483dcb7eeb93cc45b833b857f6dcf756dd3aef4f7f6fe3e5f5bb52b7d4ea647463c0f83823e0dfaa3a0a637dfe8adf44e7996902f9c07b8b71ae9c14e6a892e50c04754e8f9d1a1a5bf40b1be3b2e2e495b5ccc49b9befed5fcaf96e2dd7be5b0962b8db73cf65bb6f55bc251556de070c1b7c36f9f7ae7f75af1a0bf80073d870d559ceafc3a7f88f5b7ca39a993582d4731017d0702aab798a3a4745203a4b51dfed6f6d107aeadaaae17aee3388cf116db8a64aff014d85814bb04af6e20fe13b89e62bd0eeaca2b7b1db49c6b01137b7ad256cbe9f81fff9ecb51490f7cfc5a0edb0a3afc1a99a32edb0ab98e5fd7f1c1e0fe0ff73a28f1b7caeadaeeaefeef712f83dc1f49ed3081733dd71fe955a5d5c35dd5ff21712df741ee13564de73441d30f87aababbcfe12ffbbb6b3001545ff521363c8735040ebfe1abd6108680e0f01b3e84aaa7facb4af09a4ed351d0729a4ecbe9394d7746f013d4af7aaa0f51b54a1082c3ba61fd0fbdfdd0473cf508fef2dbeb10c17ae6e1840914dec2dfde01287c85b7ca2acf148643eef4162a3439fded7598806735de14c14f58dbdd2754e8dd3ccc4a8f7e95ba061340f5550f82eaabd6ab212a1508aaaffaaaf52a53ad445655d51f6f71ff21fd552faf5fa5375fa9a5f0b77700f525c81a8957347775bd7938e1253c7f2b3d810f9f02cfc53cc42f41047cd8c4335a36cb43cce29b39b8afbbaaaa2a07f7cd8c6668c6b6446f6b538f6d47b536956f0077f5b3d1f8fb6c9687c64733f20de8aeae2470ceca6d6d79f8ed07f9d822bdbdcdc7ac639b59360a85a46df6f2ca81c3941e2b8965b2ac1c9524b2787d0a7f35ff082620fd93a67afc439a1001855582758d606dd33e61e52b6f55d776f8f454bcfd20f709effb24de127bd2a33dded9c3e05ff87071dfaa5d029cd2df15c3e5a1d2a3bad701f3f9d09132568efaad2deebfc71bbe3d39fcd55254df0ebbfaafa5aa5efd0b386c507faff4e88f67ac3c4c7aa5bfdf5be52a2adee1c76f47e2239ebafa57e933ab84415eb15c904eda623a8ccc51b81df1d4919e0ee9f1a3b727e17faf72a4b5add0d5fff15603880ef7fccbcbaebefabfbfbc7de217f7d72abffd4ae0ed0f09ddf198f884c7bda447276015c85bdc25fc8f23f11677a447558ec1edeaa39a378123fded21e07675053e4f551f83dbd515b8b6f77ddff3705fe9257060f9d5819ca8c43f30fb84f5fc812ff83e89f330cfe713ea2f15e9db54c2e5ad6b7ba27f35d7c6de4b58dbf3445adb14f7fed5f5ebefdaa6bfb555d5f314aeadda85c2ef0d9f84df6a10f2e03fd7bd0ec05f327aa517f296d8859f8484f4390ab8e254c20f871a793568e4da7e6076e0071f05f2e76a8d14f85659237f8fd3ce3b3befa7d1df4b585b95f7561a890b5fe549ffe3ed91d2aaa4c46f4fe2edf7a3a0fac0e0a3416090dfbf3de0bdc0f503b3ab57e51cc0fdae238cdee883dde8b7b6c4fe7b95b7afaaaafa565a45faa3bf48effb21adedee482fe155de626357b154954ece781ed336f5db0bf7ed0f9fd6f64357bfd50004aafce891f8ed123889ab6ef4aacfe8ad3212bffdc749e86e74e4fba02c0008fefcf9f3a78f78ea467fe661fa5639c36929de6d4a1fa75fb4b667fa446b9ba66b3ba2421f7af385de4a6ba10cd7f1f7f86b64c76a204654b87dcb6d3a8ce147da9e7923a7328681ccf94e95a7861e4fe8c9f410b7690f77aa803b4cdf46e871f636ede761d96e44bac630d5f795f284a8efbe020c7d236097db0a32003af925ea5b03445d6fbddb3d2e1fab1d65ba4dbbbfbf81149fe5fd1de2f4369978b7db958fcb15c8b9f68abc92b7b799777050b694d72f9b165795f4ec974dab68d4c28af352be2ecfdd79ee765fe9ee972d0baeadec972d4b0cca3542498ffa5d4bd3a5b767993454c4a465bf6b698c19647d99e6a7019e4ea8044d35463d0a2ac6d5080000003315003028100c078462c1582c8b5245567b14800c6f9640765230940763518ec338868118c61843803106006208414c19a3ea00b67659f1135a3f45bb41bad2b8d5fd8c33c9e01ab613befabc027eb857c0fd863488540de45ddcc94f31f93877c89690f638aafc6c196c195a4206df681d70c0a426f1c7241584c5a05183412c5310dfa43881add307db713a9aadbd5f26cf4e542033e0a9ff544c9bd38f1a1672baaf5a3dce3a4a02da4ef56b91cc436ab2ecc7d4fc662a072da512d204dcee46fdc5231826fcc658d7c89af47291441e64accf7c43f0194dab7eb313f98add55c9a8207f981c62c7a038a903ff5b05b89118c34825ae39a2b2e25fa6c31040eb5f512ce2b6e5721f78f58bb2b5d4550c26cb0867223613183034ae30d42f334f97c503d136a4424216bd7eae6d61f6923a2fb9306c421a4032ba9e7866111c092c50e169ea7bedeac223ab29f2c9e2aefd727e33e90087582e562ab5a3bf608b16b790c8110fdf647aba0a5d5f35c378b8a28c95303319e58d694067ef71536302ab034a4201f87d3896a64f149439505d5090a699c690dfe405d618ae1decc70308024909451370165c2122b9c3b018020e3a66d0050b665a2090845c1469046e17c3abe465d1684ab5d43a82095a584e7072eb1fc6b38091416a28c51a40c7085f20a2197c9fc48cfcb2854ef6c2a3d05edc9c29c22b5ce89d3ceded19536a5f2d4b84c6eede442b840d10da9c4bcbb1c5da6bcf6dfb8f80d5e95c63c8a375cde32e435fdb4e3d1899245ce7541f849c9adc2b99900e6eb8a228953151ea111cc12dfe6381b83e48b167a56762c87265cdc8265764edbd0703b40c27e430822f74d5745f7afd6d8f55e6b3c88cf628d037b81788247f60ef718d20be4be67dcd86154a55e8882fff19efcffac494a9144b792ae5abc4b2ecdf4e12fb9b5c3d34df5033463330f446cd0600b8583224dc91c2b1a88863b4d487ba9f028d39fe8cb7741d64edc907186410e101ca3b39ce6dd81a87874de7674fdc073c357c9b969834ce60243e110c99a9d6f23088729bbed4505aa0570cedd7dff9ef563a305b90b8b399d2018e10c05719ffb34c3e1ea3c10afb94f27b821550b3d6f5031cdf3860720684bb95457b6fcc365ce1e0dbead491994d2eb9f9b165388e2f56310380411ca4d341f42d2aef50419a89c12a5cbf09d64224da6f99df015f5e1a6e746c420095fdf74500bbcaa3e1a26f1e40b2d355ddb7d52f9031fff0a12585477b4661db903bd8b2f5cab3438afe9e578cdf63c4d1a406e75d25fccc976257df13ba7b306111ad5232b5fb431fd75224a3353f6307b30ae5868f7c4f3de595f4e7d9b706c960990813a1d7b34a65825519db587be4152e10810d04c7d12b29451cda25f6285c5577c1c0dc2a58fdc508c844ec3022b4ecd930267243f5c97e4d33dbec7327e936f06d7c38e630d21892742dfc34f720950be9b2f2f6093ba4a2e812d99a4af9ed450c2e2937c57844f3777fc29a57646122627d20dc4b7086cb77e0a1bd7fb155ded046e3d9027a14453e1fc2d79d570e5e27271259d84080cc319faa59dd6b75018aab0529f4d36d839b1ca1ddce4d440de9c38ee5c5f504201c04714b12423b3837df9b29ac4cf9e9b00578c7c6528898c13dc37d2f7542323577c88935044433a6e496cd461668941eaed91ce39242cb239ec18b1989f30c8e1aa6e5a2f5b467cca2adfe638bebd351fb63c565505e0e6b0eca2b6fecd0154e7d4701daf70866a3f410dcbe90bca91c07090e1d271222a89da4a0ae6e844975b3ca45b22505f06c44f4161fa63f178df13901c85ff2809c46884952c4fe7517c0c2cf46a202f18523294f2520512d73b8e471540c55d1b780300f898ae8c2a872fda11f42875b3d80be5193808815bf3428c8a47cd1a969b7085dbf4adf6508e930a69c17af7e1b2cf0128565f8c0b8b3e3e0168947efe84ad3462d891e62651174d862dfeddc08f94abf00f64c39c2843525636739ca7e44c61a2c5ccdbe7f051399742946c0e02f37ef18e9edd70097add5244f469275534a56d69d791737038e044f56f4885de4f1d7153a68c07d2faf0aa1e8c6f2c1343e3f7c58243c3698ceea74a04e7b969850ca0c4e7fe2e0581894b69ed3662831996f9b16e81fa66c256355e52015d063115c235877346fe298d6c620cdb0c8b73827d065ce22dca0d463db6df06d11ae64894d01946a9fbc85e9d9b43439ad9a28f833c7beadedd5be39dbdc0c1e7a4be73ca01965da20d5bb5b81f243f32d0b3b0d580b4c2a5c26fb825bf33db860612442a07d4cbe967415c000951b3ba8dac5113a15b7a8c07fec3ffc5a475964d01ac28c6fd77e3cc79a394f0759803cb4627dd6112a5bcd01d90f6b0c3fd036a497cf1b1770001b6beb4b14a4b55160374880e720b4cfec776a74d0560b1b9fff537012486881875590d1a828913488281b485bf7c9c8cc20159d2a479e392e596f7556af0f4ee7a756dbde2a26317e4e52271a42f7ad732d7e962b86e6d9dcfd9121ec1d3a214644f586c681a6622bd79f920a9a40ce26a1dd807cd749d02209a4b1ec8ac932415f2e3fba3546594f33a75347e64545774ae309c6a1fc514c34b8be3b7823b026564547f8378fa7363d40b47e1cc2a8e4120027d66cfef17d83e3082f3188b4351d082402537e7b360e707bc32e7cfa3c20afa3221f0f820a4b47eb383174f22586e33956aad1ecbc26b0ac37ee74f01e2cc7ba173d130762e4ce99594b1eb07aae29cb989ad103c9649f32a6af7237e79dae587553878b5a244ce64594f308c7cfa14d26268caeef72f2ceaf757674695a8f04c6e8b2d096e08d4ef278b3068bf6b4dd57cf516842fc98170cafce1accd7c40e510716cbcdd7857e50f16fa4fcf4196ec26be5272468da00a4d50744fe9b5c33e62c27cb7525cb93b287c297e852f12eee50bd81ca12119c255be343f9b229d9e1301f85e1995c03ad781952a5da9186c809ef1c905a3fba2eae54d084807374fcb1ee0ffc7cf1bacda35320d7905c77b3498153acf6544f7e12e77e9b31cfb5dbd5db7ac6c7de2867b5002cee598080c979c0b184c2570f231731a2e994cfe5ef06f99c2943fa1d7965223c268f7173f6ca531131ef2423cc1734075d143b337b45f3e69738a386def3d58b073e6cc62f3bd64697511b8814c8a118e840ac980aad1780a439c94d176a88c9d7d68a88ef240b77eeb655c54d381c36a5eaf17c63d741e79d95e31f655d012df80f543f66cf4ff0b2b6be7244284281f0345046ee784da26f8d9d065ae6a93413ae34099df820aa3a2c8ee42208872cc90bf450ac596b2d3752579c0176a5a2c23374303035939335ded550afeb2531a11233cabb85b9dc501afbdcd4101fa553c279c13f1c2b3fcdc452868d418a332badc9a6a5d6f3d4ab7e44af544059df93d2b011fbcd28477b448d1dce163094e05d7390f8ca7a8a3ddb333ad6e156ba7b0d716732178933fd507835f0b1e0189e503fc1b25a78262f574b91c084c4bd82183b5ed102efd19c0f6ef6ae8a97085931236693838acf320c4e59cb77cc0092d5a55db516f2e86df06234015c4f9a356d1d159048fe27c1f304055e5e9dd102ea4d52eb88957cff1aa907c04cabf2f90e0752deb28c228b42b35c2b7bf4e208a11fd89f5691b4ddc84f9c41cde09cf3ddb0be830e382389ee70e5ee54062da1bdff664b42edb1349e671c1f1b38a8410129245bb3f205339551006acd5d88ce5b27e715702b4a480c6780aeda3c981b2078d67b84a09df88c8c328105c332298192d18a86418769bbde714538eab4c4d3fb13079515ffe3e57239e2e99f529d54cd40da6f495d8ad9c50ebcbe3a6f0e7dd1ae2797513a5ead0e8aad8d2d6960b02f06e38557a184daa6ed0c3f773cdeafba390de0f88a885d7a74ad762624b687709fa35703d7f1aa92990d9e8602f5afac01936eaa5b92e2cc07bbf8e188e7a5287582605bb6410e648722a49b32e6449bdecca57e85581305706e8c95f2462d16a2989ca7f1524de513fdb281fa6db9edb85d8ae1a4d2358eeb72df4887f80aa09633dfa60038970479bf7e3da6ba4db54764d17333d5098a22e5cbd026e31449ae87774ce85beb1300a0eb3f39ad1b618df33d0101e4907796d6924ddb98c99a567651e5cda11911ac30033f729b1da413d4b5b29aeaf309ea3301915d248f0322bab1109c624edc666ab45ebe77c6a7daecb4ac19158997614d32815c4824e224b61ab0c86e233507ae1531016c0dc32bac084768d3f780e0e5a49366cecd2016645cf72b3582e1151159b1f18ca96974f086724586bc6f619e57fda3e7d2ae8459e2308968ab3f8bdd353b9da7a3ee029e684f7684796bdd5f06acacc5223f9bc6bd169f912664ca661438c7c92cbe4d33ac438c623816a241a74244db1e8e6455e591cafb8c1606ace5def66ae4813e81d589c975b4f82feaaac4409a9a585d36299290f360f8088b7daaaf313e10a4122d65579bf97ec4619a2d47c4bb34b864d5bddd722c0e3b3717d857a47e7c8f7d251e0182c98edbe0d70ddbb3b58c44475d37ca30c046b7974b347980e5b516d545b241c84e9ec16480db1ac84dad7cbee454be9d7309b90dbb582f5048eda534047c8b6f6a23e4f11d5503ae8a9c90958b4007d39003eedad5017a2e934ef45f4494b43c3017ed765c9e282b082d7dd98f6d8f4924cd09e07e3e3af93990f96a3858442d3f69b336be43f8b534b52518a37ae69cf800f76991f52385a9bfea33d61744fca0d84487c800ca4bd0fa276dbd6023eab148da1107950b03cfb01833a4778fffb7d0d04a12dba0143d554c4274ba1df85873a1d9fa92c6a5309875bd7b0ca5e6824e1046034d3e3143b5b99b5ba8b6e34db689eb6d39c4fc52eb4705531e75e0278e3c57c55c47e5c66b604b6da7a5ad28d1caf5a0cbea16d8b0e98bd8ab87c1ae3ad0018008a3aeeacbef46405ef3d1c623c07567b746cf49a95cd7ff516e2d56d6c7b889b052a1ff8548491f18e543880f75cff4c147fdf7857c01cc12cc48c25181d713e5ba44de7e4eb3cead7c0acd39d642c99ffa0e07e345819ff5925484fcc662ae48ad2593cb02307cbb03b877d35c6fa35a3bb2131ffe011a35ae814bf3b6343453f30df928840ac1f069e16793151f20b01dad35f2579a7d37634b2212d8cf2705db83d74c1bfa8ace2ed6a50f808014a2a3b4afbde58e285970bc8a5f39da408ee532603df14acf8db568ebec843f52465ccdf37a7710ba55e39e7f21da3b7eb8cc53e3ae289704a51852d7d11e66ebdff4f366843772ccc2a4ea00021313d3291a14f5f93fffcdf6fe71d51a9e2a70f51581f2006a3bc6c46938b7148278efe557980d04e68d88eb6254288fc0f389a8e0f4b96eff3d2ec54a78fb5c1f54cc1e9b81b2a21a3b361e993f789c7b4ec3f058f876cf7ff84a2e634c4ad28a62e84d429a153d658c2c8da25fdf935a41d8da4e43fdf7c686f42663706ea7e765595b345ea788d4a0d33506ade385ce7c6a88ed51072b81c9d0a7cc6e81c51869038fdd109392a37e206b84137d747a5529da5ae76950e866a47db6793307febf010784cc75d34a68480b17aec0dc0f82b96ac01bf0a317a2e09cc69c287e22cc00bf705f9b015b4630eaab9db69d166c1a077e2cb30ca5a4c31aabb614cf26b3225d07d0303aaae80b4a2a23ba7ddc31a7e1048456f2a6ad503f3a4207c584bb13b64dd355ed8ab4a18d874de53166729e76cb502e1b504fd5834192f4e804b97543b822c24c0206842b95c7402c20011e4b83892b726fddd33db9882f1342fc6ef32b5a464ff1ff40d712e791c3155874f68894772a35a2c9e76766dd7c08f68a7527d2a32a8e2582066cdd0180066d5a246bd9f596910798ae77b5c1f1667689b31805dc3fb9507ad33939ad29544d1c83345e3e2ff87fd34086f3edc344f3e271c36108b364e1a9e3a6c720aca625ee3e43b7f6480180e4b1e42572342ad0425c232f4d81cce00d3e4a47833d72a2879f1d4e4b8e5d309b32589946c39e7c08faa1e7d93ec8715724b75dd28eea4b927e826e4ffe6d44711cfc6986e42802719b125a4c63bd3b9b4fcf855b0b01c05704d3207ae5d296954dcfcbfaed449fda7f7082cf1c138968ebd7c515716f4eb2731f3b9193276dbbf2411fe7d8263676f10c9bb507c0f3184ba761f37071adc5bc0f5505ad2bd31db72a3ba5bd58be055f6511e01b9db3d6f80ed32ace09ef825fc3740cd9119d8e5458b9732afa6646e48c4ec003c779d4b7724ce4bbb1867519578b569d6c55d8f13a8e90844b9a167aaf6a3e4474f82c6dd74d4265ad1084caea0e81b282f468eb44320b0ccf7ba810ab665222b1f590546181a6f2d3ae83bc5f8090fc5bd094057d39687cc646e0532637c9bfce6cf1fe1452c574257696c9b74ec7d97d719b179c10338be4da3d85a92c55c1724a8b3ef2b05dc5df459ab5c88c035ea193b69eb949760937c3db8a46e18e8180301649f2cbadda64012c402248f50e1aeccb0c382d3a7f832c654eb6c5451d9e42d47a60365bc3d323d4f0fce7530de9d3d2981d537772e7c81fa988d2a3874e04f71bc4dc97b3087fc7c2950df300b8159a4251598966df15de001f160314164e0ac4a43743181390885b768b905e6d63ad1e14b98bd9694169c2bfcd8b22cdea3f87f0174011c016f6a868881364542a020646305b0db0db027d0cc5ab6aae5d07b2ea0cf9dc121647d9caae74f58215997795a6494c1660e4d60ab570578ed90d325d40831c6fa002ac15167a15276073d0f70c297cb67e101ac0d77da2c3efc56448e2dec945b95d16476f4fd12ed42774050aed173275fd9e0ca1b661f3bfb7eaba382c54f8fe4a7de40b8947b6efc6f7bb775d5e3330b5d1224109d265d55d156b0a114a0dc3fdf0389699f2c6bc6e060f2e8b5d4ce6a222ae5dda224454d08af899d1d2d403b5ce4423ec4a3ec2086276ff70ee9215da4f4ef518d7cda2e40d38b5ff97f690da862953a7e4c49b5a02b4c374c3bb5e0150fdc7c705fab8236118981bb2e0d719a86b16b66dcbe012d87055627631bba118edb2a06faaa7a28229c2411fa9d57541aa2d785695b00d65ed2f7c68aa03999f3acf977e6d36f57ac2fd85ad184d420653f0d7adf3f0abd24a17041bc68c4eb38b14a1757d4f781721f84b4166773d320a1e6c773dd20b52d1a122fc41f94a707f78f5547bd83fe61715c91a809783b59a1ffc3c41533ce01bca8153a040c6e4cd046dfd163c68ec0ff4f7ba048e4449d9e66eaca8598172ddff946564daee7103275a37cda11c0339f3aaaab9f65e9c55098a6e052c033b320a3930435c92321791f352837f4955189e65e9c4b0de4efa13fa12e2da20be72fe7585fcb4d6c0205c53475435b68d20c4045e88391b89a8f1862ba35a80f56c146fa6dd3a475ffdbb1b5b29d4d7466966084439c5c76d6e2ecc0778a76c7f38a4aee1bb0aa5e93d0bc06423c17694358a4c1ef2888386c87d4130388a8177c82fadfdee2452719c30ddacaccfcd69fd5b4644215adc3e9e136a07174153a89f99bad29bf1d9da113f03ff51e3eee53c2d647b62ef42e2d7441d33b21e5ea03854ba10cb7e7abd23b816e86756f0a5b2344820cef6afb44f0e4b25f01a5bf555e1a81c8cd52c8910c458cfa8ed1f5f885e59fa18f5af768320f14138acebf4e86188bb69a82397f5557cbbef32b31c8d10e925c018343fde051a5a4570a36d00ad7726f9d6fc782eab613af88fb71138043d4e4764cbb4f52af29f701b01c6fc67ed41dcd82e5d89f28805f0a0f4e932aab74d5d837dd4b31c6d7e19a5e5dcfc85e2b0c4c3256b47527e7d3a9729d80172e4389771739a01abc90e02efccabbd8cf1bed38c9d7db0b01212086e65ff2cdfaccaed2abd3333eaf84ea89d9f500d04304263690b8e43185596a3ed21e7288b4115092987346fc83d91825d0d119ae3a28d0af4ed22a3941903998355ae2e21ea41aee1d7104f5992e800d2b16351261fe7e81d3ec923b15b397a399306427a8e1d5b930e7cce108ba66a9c4840c863d30e265b25353118df0a6f12b79cc720e8987568b776f30c08727b79f110d5e796fa3360335f1bc60af09b8c3fa107fa636cf43690a11e05a4ddac6d725a0f7112394eed3bad53e0c6228afea810dbab25dc517d1dcb5b03c1cea2da329a6b60a72d78dfa82cab03837ef1cc759ed2cf037e2166c16a7af083932b63abe5413cf19459ce7afb9f9101d2921d0400639953dee1ef7ff880d7012803c798cdc1faa57f20be8aaa87b21fc801f2663fdb913df31c697a953d9942c2311b7d9428ee72e1f2a669093021e5c944c8530cef16f0df94711a012e6d878e3715851547af58ad2b5d18f4470b065794431e5b073de3b8ccd547983b8cd4b020c4ce58d93f12e022e93108d199cf0da6d9909cae355d7496f9745a1b8a010c20e572be790bd42242e10242dfdc064f42c8d9b6a85a24b5aed801d8e9d0b6de0a15536fd13fcd505ae093ac951cd35b8871d9d7ef024f291497ab13c8737d5a701a8753ecd36ea44db0e2e8c18fb6002c10469493ff2f2fd60353d2fc38214c745a7bb0fb5150e79909409c6161d77b071e4e5c4d1058e356de6eaccc7a91b9322b845b8f2201541b83798552d978c5901f5f6d0c59aa96519f6fd6147d4dc5df644bd9822c6ade50f51477476f31479aef5a91cf2bd36102916038f98a50ade1061ef980ba5b874c8a290630f0dc188e1d7a53f8b29e6a91673f7bfc07fd66e68f7b788adba51bb0fe5f2e94efce43008723313a80d6d32ac52327695bad2f0809487e0d6dbbcdf9dbf9e495e256bba4ea2ae3190028b5dd613ccd4caaccef6839b232ea92cd1da50931a9014786f2387101831a0ab81c697762dbd822678a222bcd2721bf2b875d619bcd396bfc8dc6650eb10c9f69ac701273e7f2a5d1f32297729d2d9c0f3be1893e448767faa8ce187c9e2be90aaf0f736f00bc42c206aac7f5528adddad0c40a2733e60e4adb03a62ca7c6d3304f085291a5b47dd469d7cd753f60e24815d71450340d0b73f93bc10c0073a5fc18107123847d6d69cccf3dccbed62db1d6c5c5a1a345333dd2e804d3db817d5eb10348af657de738fac7764b96c9397b4d7aac37fdf3c905f9c026b3aa5970c9d0424882781cf271b9b6acd0d65019a6a4182b16289c0a33fc64060715866003ab1f34cc16f3d8b92789046dc29ed208ebd0a58adc4869d340ac5c4013c3291154ba7a90d5783e3c1ec56bc787d4298dc1267fe9ac70a66815081205fa4fabfc8526f5b8373fc380c1e02aa6031828c92796c28eb60068b2809403af78af24dc5c903e67db74a3a22c2a1a5a8946dd6141f1babcaf2df6743e8c2ef79c471de8a29bde2a78df7fd4e05e7b3d5f8648d0ad31f2004c0e27f96cce651f57ec9c85853483b45477581c627cd4c1c5851ae13a5b3050cee3e9d263452db69c5c643017f67bb0184f9fd141cd856f5d281f7834374fbbed77f2363c4d2690d923502b7b2ca21cb3297437576652c0e109f55c402cb31f50a34a0b38aff0b336acf2c8547d2bb944f1871056f985711eedd8589657de578362feda46432335d0b66e442b1f54fa715d20e7cf6406bfdbe09d6106c0257868168fb30e930576506223768661a7de2135c4fdd6aeaf58e70449dde3a3a88cba420a636d1d615e47f5cb070d09d0a84aa2e08cff65ee05ccace999bceb9090ff7c9772f9c6f6e1340b05258b6dda87eb761f9fa92b153c44828ace90cfe8aad527cafccec344af98d2cd616c9cddcac13ae2c5e7cb709b447beed54482c6fc1c5c375e6f6c2a32ed32c5c7a541f48baec4f547069b66a9040d8759ebe4f84e89ed3432c8f6938b30dea144168c46e2a87363870d90a176663f92726c9b2e4ec69d490cbfa7706f8b4c4feff5baf1b8630d71a46ed5f1392deda8aa15277344889de2877b0b316d05f5d7ffd933a1daba3a08ca7db00e0e2245eba4465a5ff650b19daeac5d8d0199c70941d7e93fd8401ac41aed42b972047dada2bc6126d18fc4aa6e6f58b766b087289f0e3d951d784c376a7b89c2d1b8b094d5a431e04874dda4514b61f403201551ac40c6f020338ae473350347874582801af1eb0b036cc4939dbf90e87521111ebfbbdf08e7de989ef347adc7e578b1e992b8062f942c36cfec741c6ff6a33c6571752cc4b3999838947ee7422f0421089e2b91e94c532f3140e2d9489e909e0d39622d59344c8f95705646a9169ec3c88c48f982a40053423e7e96b640783505f7e7d50d8e9ab8af2a4d0582271f7d4493c245e6ce7063cf99cb2982ec0e4bba711dba495db731692b490d2b406401d09b000bf0d80c3cd8e4c223f52ddee6a1c9b82424b33955212b9b73ec216e8a58776e22da0cabb24acdda98315e2a2da88f7314f151b8e4f47912daabd5a6a002db294b9e2095aad3bec0e3d61c274b2da2b8ddd8edc8d82849d8b4bb39918af8a392b9d9e808b69bd0a419c7d9e323a5cf10de66447deddc22a10b67f827f8402ac9e1566ea3636f946de1f0f36a5c675de5725a4fe116cc04860fa1b8e8280e7add130a58152722f5e1fdb36127479d7a393622de81cbde593f3b0ef9b44275588ed96ebbb7737909a3f8199806bc10fe15f172ceeebb9720476ef38037941744d408ae76b0afc9b256293a58ab132ffe5d8f737a601b18f6001a676f446a15365c623187efc1a4fd46705fb5e47d8a30c34d4c23f4f2f98adf208ce6d1d52030099d890a4ec7f2f8e46923add566e574b94a4e532dcc202c4f07bf45bb2cd3904740ab1fb504465c05ea64b8974c87a3346ca138900d7c4e940fa719f1f2ba13ea5b4128f33e68bc2c507763e6f4aab29c062ec8db1c8b2b1b18fb04c591955a1ac8f3a829ce33d4e2bf66b71b4a3a787b89413acc1aefe240847f92d69f1b694f0d950b4a5aa887eb863048032683d65566b6f7cb4aa54c8e0d436ba1332ed8105d0bd5232e42c52f9d56743aba41ff8266c0be8d39295bcb563a5eabc27343b511b288f056165fdc56335797198e61f0217e1365453afd971c3e8f4ce0c656557c64d840c8ef3cb2fec4cecf8c968d254131919f56ec1111489af8b4df6fe4b1452c908b0a38d98ddb85d590d60ef1a232f7ed30c001e3240eea61a45bf4a808d9677dae29d7274c3d8e5e4effe962ba69ad07c7833cd6cb319bb2ac60b0ffe94caef6c4f67ee6b244866a9c0cc44634ff2b1db1dc13e299e200f04128e5b6eca20b12ac4a10819f800f25c16978169f62d69ad2fd20476f68a85db0893116082931048ea1edcc124667ec058feb9ec5e0768a745ec94d873239a33905e4cb936ed040d8ddf695702236f1353d41493498cc34a3b9c077e160740d4898c0b72410779d9ebfa931a2eebf4c7ed2c3ed121c04becd70f60aa2d89808de44658add1ea2cd71285b003937a045b68461fca2c9ffa7e34fe6b4fd1b8e094551463e9c9b6927c6aa26119f65fc70d8a774aa54f25d34cb338e8f145745fdb260d7ecc6a787f0e5f0347c2f389bf464b2c62633ec5c297bb21116b2bb62632380c1b9636e70e2c830d4702e7f6b8a1be3acf4eb37d2453df0533ad083838a2f489c8f8a8b77072ec34ab20c37b23a3730675fd10f672b1ec5a8f7913692ae92153e296e8e5335e2aaf4f928ff72b0c869be5b7b49e15cba0208894b3bf5a5ed815b6ccd05418b113a5ee2767d34f435c508aa56108e73a4cd8e1c017e11b70abddeea8167fa1ec628ea45c0ce586a6d3bffc01c5f137abad42e48203caefd91be2fa423a7d3958a2f0b6da2124a50e316959fe28e2c8a67b4dbabf2992a1336d38558e13942818e793a67b6caa8cdf8e50e31837280382eec9cb97eabcdf294c3bd1b44d72e87f564fd27c36037feed8cd86407b4b9b9cb6795ecb00f9241049f953d0c6dd51336ae8290abeec4fd643438df8096dc96c1022eb0172f06ac2aeb146e336e0276e9698bfa5e5f3c24e27c0e0c942e693421e3662ec73311bed66773a97b5ba73e2fec4ac63c7f311c5be35ea392889d5cb9329970cffd63dd45b715f04994057d33864a3663b7ac44124db8a807c95202866dcc310c4bf01c78c38a23db945cafe3de182c5a52cfa9949b92c096510d3a349a9e91d58eef7fd0fce5a3f9eab628b9fac1e4e2f1caa75148d0dbd81af1bb2cfb36aa90d7e210b6fd5ebc48e9b3cdd6fcb8b43eac3f426c2b431da18e820fc2f9cc4aa156125945bb6da94cdbb907a57ff0aa05f4a4d39c2825c2b662690f3e6970c20da477d6e126831cea533396e1a994d40634ea78acd7f41c6bd25ae59ceba5131bf28d5f12df564cfae3844f800aa7698342bcef57a7970cfcc66593fca42ad3461e506fc6ed1b347623fc02e86f42c071a9adb5daa6138f50ecd9b8bf36f2a9cc000fc07a278f5c041bb7a9d564003479d85eca42a4670e6f661316f1d1c737e88f6ac1cb27ae8ad61ef14aa0e2e4ee81dd8a0e713d61801bbe42595dfc24b6d4463e9e120353ebe10ee000f96cf472574578f5cce16db6849cbed900dadd4d28d6f8a72d87016e6ffe5da40c21527cc3142c4f2027928c4c6f6ee586812cb6fae88374c8a194a923f286a098fb9e1e2c988be0a40ea0bbf96477f64c33409a55552788b97869500e4ca356773ed743ef243aac0a6745bbae2a5d4381da15cb025c52b9e80c197f29de0942dc40f1b367f0aa82568973a636baa24bd71897687fa5107ff5711f53e3c93f5e2df8726aa4004b417621d21fe7443f8ed40f335f125599a86b1c34064d8b38643819a0f54496ac2b5a2ec2f866b17a5cf38c2b5619dc42b77b4851da535ad971794709874dd24d3bc7aca5966645c6396fabcbcadc84f90978c5aafd966af79c0615373c580bee80795a045f3a2f538b619f66e7118c1cc23716ec9f0b70566065edfdce0944fb47bf508fc43d9c829923fdbc8e7e5eee8b5db670eda48e83fc9657409e806f09d5ea26e6e80a1397c599bcedd92fb3d8fdd7602e851bec09cee61b1206629d9239ead70ea24f4d6e97977188f0b320d2b30ebf47a2516fbb16a5765d6dc5d96661211717b5994b27e353b8abe90fdedf764697d5747052316a42f6992af9b220ddbe9896c9044dd8441b7902e47b4f557abc48d59fdca59fbf1a266f638e0855263a1a1f7acccc173a01b9efa239819027f550ca1ec22b2d3bc7ac772fca89a05262e964e16d08cbde6ebe9a00e201414d24d874435f95d6fd7cf84e1965c9f4c4d2a3aca0ed8550e8527ca69932133a25ffc7e794a0625e534292c2b8a932f44f117a252a0a998acb16b02878ade41157638e88c4eccc74bb6793dbe2614271ad6ab852d6dd8fc3559a5f7ef59967e41d7bdaa4a87f3f3a7dc0c369b464edfef7eb04ad55a4396d2c4a49a638b0a7c612c7df8afa913467340887d6dcd39cc8617cec2d80cffec71ca549efe105a6b65ed66b5bde53b26b60e28d5190c383a9d0eb0ac944d6a28d86b7f5f911d150f4937bcd216ad63cc3f0e18dbb3652f7f4dafbc7b51c5fd981bcbbb7e966226133350acf6063c867b1ca996e95a348a86e361cea49740b2340fa253a0312cc67011125c1e40574b6eae657869aa93217c320840a37b30981a3282b1706df90fd6cef2da4395bba987585ae1e904a3310a2acd910624ce8e9b65750368779ec7ce29dd853bcd376c0347360aaa1b3d840e140014bbe4c5c91aa2c95d4b5cb8274402b7867880bd3ae2ef6052ee3f610395c479ed8d4bef4020b5447d2db908b6b7c9b8e3071ebcc946818186dd5425c33fcb1e37ffb1cd008db91bd5b9094a61727e00a79325cb4010713dc2e26eb7e7d23d59a64c9864a2c6aa767af1c1dd518abcbb937e34a3ee043e6243812208793d23dfc0b68fc6e955448b01695ba7b620a801697eb69b291257cc1dcbea6571362e508fa51e0ce6df0f69b55fbf162de098fffcca85e8933be85cea3dafbd66d989178600fece72fdc3468999fad43fa9f472bbfad25b370fff05194243cc926c2845a09ee24c9666c6cf03786748d0c1d3728e6307eb9399d3006f7c728ac5bcde0e02ff6a96010cac1d3f6a6f4dbfed005d97cc963cf6139b1f42c74e2d68fda1e40dcb604ef6d2651ce22ad06e72976219ba94a6f895de1b9916b75431dd5e7330e69568b3b48d46d4966b75f5d1a769c0ffeda6c01968654eb0e8ebeea379b086b5ee3fcfefce9705a0e1c040cfbbd477a10efee9f393ef02c7fde14b4d0697587cefb35d783773874751b1ffab59211f3ac46d18586318b12608f4abf3eabe50d527b4b44f038c5f81a3521b081a3333a524c78660b3b933d0c8c6affa450f213101a4297dc6ce82533c8576c7935810d7523a625e5555750bc49e73012b2a462a407ac31a286170aad500808257137ba95e928cc6ed8b17086960489065ce9b3d6deff4c7411516ceb7fdd8a52c61bfe876356a137ea5b0475b9292f82cf958d7ea4dec8cca0e31d3780d814a4d1b9afd30ea9aa0702bd18f2db8839d2c3d560cec63ee0d3e1c6c62ff44aeb6a6b32ca23f3dfb3164711ae1308a7afd3c8700860ea888a122365d3eaf14aa098db7203ecfdfdb6b52891c1131f6ba341e6da6c3c1fbf812181ec0a5da512c294e7fd1c2ce3ea6e1c7d1c17630773f23980f3fb856f7dc7b5d1caf0a67439bb8517420c47752a9f05f70459743031eea7616c8f172a3d3fa854af78504bcc5c0d930895c6fcf5408462d05fd518bd0b70ca1049492d43be221dfe7883e5be4965f77aa885c1b08fb5c25a02a122877f2d9b73828152aa73c90ca4f4e22f3d1f33bce0f9919b0925bf9460312250aa595de858ef034f0bb1d2662c7775338c0d88c5d0c4689b3374643cd00f1ff1bfcf5dca0242d492ee99cefc7acb21825b41754dd006de0b0eb5db5d2cd3889455c2209ce955d453d0a1871f7721dde5f12f7ed3e2dfe22f3760de3cf2f06f1e6a6bda0d2321d4d9d441bc335a721ebaeb167b4d7f70b3821b9825d0797e1851fc3d43176c980176be909b123b6b1eebcbe9aaba00fab04aa4d02b4783ce2a1e702328fcf7a720897bb582e5b2f378efcc567c3c5005938c45510dc586e82a32d328ca6d96f8ff1bc5718b8b352633a442e8d31250704457e7022d6eb40e855d9f39686414c806491a38c2b87d21ae42ce6dc0da17f26b0ac7fa9314ba796197ad2b9879b9595e61dae6775f5443aa3097568a6a2088b0e0dd4a31b631f2a9e5a0feefa4f9b52f883014d9d863b3c627950dc78744a1c00f9f615fcab68035d37baea167505f98d42af5d08f8b7961f17c6a0f2335bcf6058a0ecc8da98141b58698355854e03bceb9edf1fd1bb96d00b584d60731e09908777c2b7d0b1ba9301cbd9282313480e059722464f42283881473fd916c993b0546a1592fee2d73edd2f09c374b1e0e3a6ed212a9c3cf5f8473031080b61ab42aec3ead87b07e218df5667b64261fad172af53d0d0cd8f9cb55a65e0dab82c4f0f85f4a29cdf84c5c2ee88ce44b8795bb001c7b7b5927009f198abe57cef643420b711f308a216f2ffaf36308d82a10c072ca1fbd799943048c3fce63c340703924d7bdeddcc7294f9efa9443086ea4585063165cebcc40487c21bd0b4c8b632ca2426cb3723148b7c4fc9fd7341e78eea5318ce9ba5e37102359a80afbf515f177452ae28da8b67169ef4abf393618037e2f022075724c7a7a989922f523f30020d215b2b188d6a790841044e814205b7548e199606537565683be5942f693970319b8d83304f7e279027f4c462429375203518f5f7c118a320b01c2cd621e7824258720a1559c685ee43667484bf94fd67bb1c07f321894f996d8d27fcd0d440d29366a34ba5d9ebfcb4aeb89d942161a57fe9432745c05e4d85e5d02bd22e1d6be361a7b5b8f23f22e1e07042398cf1e81b2f4d06624e65c9f247d989c4df74f5ed077337589d42795fbe59910ca24f0c42bfab0301222794f7b2e8d6540ff47b88489d007966e9010cf2a32ada8ab221e45b7752e2799061371bece8bb253da2e5c2984faa2501a146215766ee27cb3a38843e9f0a31f03eeb900aa55c21ae4a536379b9fee0cdab6fe834c010a38acc3c7effc7b72758639436fa8d33fdec4501e87ba7f0358003113042dd0bffd1b46a03f858349158913954b93f729e2b5305570471ccb2e24aff82c8bea6dc12f6fdd070751595843481845a26dc0fc4672321e58b75db1d21837ccfd8f07650538c5963821d07125626ad0dd4d66a98aba259731f63e9f44b018297f6ee9e4e9448f84d436aed7ad9ed2587869d707c12929cb6b3ff5ccce4945c5fc8db8d41570b6475b3089ba2396f2024b8457655a78a5ec74b80032ac1090a6141b75ddb0d072bd68a7c93195fd161d47bd4b2f901c3fba5a7ebba352ee9e459dce552575ed250e3ec430344cf676396c4625c4513a5df1c0fb9d272223e294ba2a8c5de22bb7cf0955b97872d7bab31bf700090062498b090083d75df8db9f41a11da308a4b04fbac3b3c1309b6df883bdc2bc3ad13867056c51331e666fab129f9407d775025b58f072d7682091cc30355858c3afc7d3ee7a1c3b029b6350550843c174e9afc994574f71bd8e7fb05d07380e7011d8ccc474c3546b22708f7925c5714e46a72cf10db463da51908eb89efcd694c01a2f3f1e10f493e99e469d98ecf2f804b70b164dd50e9d07b8d716da3bdb631a7bd15a1d73187853384dff3d4c8a54de14081b999fc8f250f4d674a8999a6d58340b427d7e02cc540e8baf6166fee897eb19ae06234d804c0ac392836fa79f0d7286b927875a1f4f9a7bbbf17211252ad0ec85afa2a94aac38f67f29d55c70acf684d6b211b4ca8d101c15c022e7c183f1aa4e8cc5bcae3006d6c348f605dcc7efc5fe576dd3cdbf3b7f1c4f63b0ae22c8a7c88348273c9172f918dd49295113b3647a728c4915de1f5273967e4ba6693c65dc0fcdbed6dcffc3818e801d7088225ec4e347feaebc04d1ae33abef50c5489214bd14a2e355c47053141012bc0ef0256b00bcb1fd0a49721e3bc9f9098696094a7d2c43fe9a7f8a641edf296627a20706c0a5f74c040fd8b1059226c9f3125c5ea1cd9ea953fd48f3ecd2f4ef1b820a3bc1558963458ff6f885f7d98d1f6c450aa8232ac78a818a73d24cffd8b01822310f94bd070ab00fbb1a4f252a41b9e61254645c4bb35d4b467201d33423304dd0bc04af0d962920e93c82e7d84e6d24ba0fdb9d4d561e5a36674e5cc66958a1a438c01b1291a1edf561fe85615b919200cbc39959ac8b937f8798a19225fafbda4ea20cc8dbeac897fbe6b061a3629289b03622cf05a37fa85fa6a02843773586f94b75316da99bb6db10aa2ee03287f999fbbb50f4047144b2f9b5615fed2d165155bcf15376d753fef35b8eadea303c44b663f5e537d5d2a901d4f0834d97533deea56c289e6276fc7e5bd4431f6f6e8bc3eac34430b284fc14ff69a0ed097ae08af24c33e7d9a943b55ad6d68008c0b1cbe4235ecbf2a94050bbb7d4e6dc239d26582a1eb58e8c38000c8072d8bb13db9d730b06726add42e8cf94a241897d3beae8c3afba0c3465c1d4f061ef05dda706740ef22fd0db5e1cf9d14fc56bbf6b2065c708049abd88e6c3bbe9e47a41a527a8b87755ca21c3fb03b59396c77da85dbe9bdd876bdb181af2545c4fd1a4925e6927a9d13500e20aa99b0a8ac8ed0ecf2b43ca08626e052ca0d18d131dcf076c0a8f5464daa62f37a68f713b4ed9fdcb81268182098404cf71ff4d405148fda95c59a4c16189da52c1179db7a226fb61738a4395ef57f0744313f01a710a9ef01c14087f220c26056445d53d5d1e687eae2cde57a84c61e9fb3eb7c648c3fd52780c7087e5bf65a81475a797dc1fd88b7f4e527f01d6987d86013a9d4e93e3000224bb924ae2891e1011d27a99516741ed123bf685a881b991e9f7226c7c12285bc8c61db86f7601452265b54ee68893dd04802c4d86b4550895e260cd202cb422c83a360601479c329dadd74554fa632439c441fc874dcec59eb56c0aa008d906725126a930558e7a5ab9c6671b5e5bf37336bbabd5087515ad970e9e5d86c40931d219fb478e91f9b43eb3a322030bce84e608bf6ff9e2d68da4ce00f10310dd8828559e751c2d0f96e4c9a5758eeae60e968c68f64244612eaf5eddd970553c3712db89f5935465814e9f974e5e64f73c7a13c96acc90e35e5a0308858f7701163a52efc41cb7af9613c6eaf0df8ecf950e3ace48af4273eb8dbb63544675c578ea24e7390bb490ffff0d3ef4928cc74c121d54e592cad248b20e9ae2f88eeb6eb85bae19b95026c6495fc11a90cf3dbd8efdf9d9f0a370d0486d71a7db383cfdb924d0f256537360bba346ba3cdd736b519a11e3fd93125bf098ed44918560058e8bd54753a863d8b200ed7356bd24fc60bb89fbdc0d5f10d0b5a860fd1f0890a4edd65c65590830e2de4ec130a38cbcd4d2df316549b7eb4917935c0e78893a32497663a70ad0a1b7ef23b90cd87210c63d633d148a28df54b72899b7b174fd940b9e54fc8d3d406257d4581d8d7ffcd3af448b532c5204896dbedd8d24b1fd09a4ab3e89dbabfe79c3743c84a102283ab523441f44d49908a255b1582cad7b644b5b456b6dd828794b12a6efaa7604b138783f8491c4e53d2dc91443f1bd70755e296afab4aa84fbe3562276f9f5e93d2660a1065a96ee55c15b12b765046d5f0145e7007ea0c2aefd1339e83f6566af611629335cd4be69a71f20023a73fe871a50606c8ab98876b6b5b5c005761e99a98e2a7a6e11882c95e5c210bdc4618e546e5291021694270c50f171fd8540af41cb0d02d94667adaa02dc84b812560e014d4d870f0b425d63f54f42d23d5900379401ddc307d925e29cdb6cf6a097b0497f224587acde3a898dce8696ddb85827cd17040014ceeadf6cc9b66cf35c53b6d236835c63ede93f2ce496b56f9ae1b9d9af0f666a69e903e7ea4716f463e154b22bf9e933e1d3f603ea49213724925560993431173970c6c9b2417cace14f38e083e42ea59594b9f7088b23cd5fd3cf0548740ea007672307e5170384f50fa034bb577ef518914db8d70377081965513d2a87c999c0c3616ec5bd6538a572fe0d7a6fe944fceddc8bca9a7ae3e325373176fb1d048992ad6fa29f2114351131b3ff5f7868377cc53bef41c6de8ff173c54bc5ef1391a0a319a056629ed4011658813f399cd7ec64a838e8d7bc05d7ce18b1c68132ba432778691ef43ab0474f42548a5c7c631bfeccd6e9d3dc40940b02c7b58f7d3ef310c3ce1ed74824747d01bda61bb7f9b91644da9761ee9706982faf4092f99550d43ef378a5a667411d3546c4ef4af2c6df1b3b67f48c6cc8f86b5df394b1bf922825ce8137b5874a3e5ff3aa69db4a2761271a97d6743b0ba9f9989483a138fc06e60903fbefd205f20c0d2ba8ab18cd707d8f545053eda7582edd37afe84625491c75de97242ac87bd7e54b63530c494b6c235fdacf319d0f9c16d7c2e5047989be5aa85549ee24e02ced025bcce5c5067443b924a9af69477ad77ac52590347dd1d41dc578fe6acde89c944d2e9e9c66749d9ce85580969a4616f370a9cbeaa5cfe95bdb7502f5d2b475c5ba80d2a2b4fe5c411ea607246954b6735aab1c29eb6ea9f5341534c0e96d332eeee522d251eb4d4b969681756b67b8bc000fd20ba6a6ca6efd992db8fe4a5df853abd27eced2be471a6f56252e8b1f3c5b10275e85ed56f3b420b2e9b800508a490104baf42c8cfc008a79b7ec2529a377027602815ec57737ad7c01ca99b6625eb8a049ba93c82ecb575299a469fb03b8254e861d0db02eaf64872fd0254c323744e59332cce6a402f0e40aa1494ff699b293081b1aaf0ecbd39f3baa982729494bbc3a4516b38bb50ad92f41add9f5844eab4ab49c88ac27d13baba2c3086674d485294de3936ac39c9e72cde129830e9fff0ff3e4108a3a874a0983fa1ae9a56551d189d8945e11a073a0a6e92329f6af61459408ba224af8c2cb49d102fdf366c99659e5288deaa97eaa8307cfb9ea3deb1f31e8b2b1bcefc925339eb8fc48b7338457e236e3eb4914167065a47153bc64369ae10661dfe1272ae9afa411ea1b7de787a370929829c9bf7ed7348e5c31ef19a1f82c750364c91e41fda0318377814320a0fc5274695bec98b6c318846c2f6091218886fc5559222046848749bb4f63348d87d0e28d6e205505b67837eed442f564d690899c5cccabd71180cee6026e804c717894e0978861b54a692b2c7dfed574c25561051f0880b91c2c5ce44a7e10704191f1d793e4e5b121b95aaf7b6d88fca61170460d1cf9ac106410c78da688bd9fdfb11d3b7543d91dc640b0254da0f84920e0610060f6f2c900b9ff56966bac9d5ebc7e295306151d3a4928858b5f423f9b888a98001721de556c59f924bdccd8429d8ed95693d64eab5bc61d71a43f9098ab6d3ad0967f4eb1d507d85b70b699dac44d4f69ebb3cafec6da74a80233a74057a56d26b496aea60901eec40c5c6d5038d2abf622bd428104d816c166b54702127b002c13d7f180bee4a7b8412ff36ad3c9fac87612e2e1b95457e09b9557ce8b1474ee36980e282b2698e29ee2df0966c575076869e98fe08ffc5503533aa50e0bd52c3c81f460fbb327d899e228462cb3142d29f68e70d92ec5c43114b863749a1e87f36944a5144e23f589bd046631f4c1b1e3de3d4d5028776d76a685f2d83e95918faa4b04a75638937b91b7fed3ff3e865971724815dff1318c6f63c532e040e995068f77c7f1262f4503dad6e1808a1abee2074a5b57206f10891c02b6e8ee4c4fa9f6cd58e92a769a4ddafae17f69007d2e4a3e872ba54405ed75e213e821162fcbd38c6e23c4ff350ca23e9c90610f4a75e2d7d8d5d42fa191f4b2571186fb594fd5329e918bbb1a682a766dd79bd54b7228e320c7354f6abb0259836449aea68335992a821d3c0a647e8aa38c85ed983e1a2bc703fc3bec4ad84d0db4b4e68d099aa953513f969c3111e027b149df938518d998eb262be9fd15edc227f001678173081cdcacc9e82503e5700636b33e04a287c3abe20ebd07eb7d68f15dccccac2456df7393860aae8d097f61a788229ddb60b3791b8dff0b5c251be621e95b84ac455338326500153b7d1505704994371ca5955b0641844f6cafdcc4aec5f6b8d27067db24dd2924f112fc111c0aac0b16492b2c959f985d8846f4d13c8d8e51984ae4fbee65dfa1d7a4cd28b366d258a2d6f51c1b36a4b7e7e543d56c5b534e7e68d6248d5086761b533d6409b8f906c78dd6001cee515720559e6ec5bcdadc55eb99b5497b5dfb929f7e5aabf49d152943ace17c12c569a53f43c29cd5f57facdf4ca6f177a4128df236aaa825e0b4a0665a8b78f832e9669c6c5369906eb6d3819eb5e8232a1759ae60ca101bed6e05adebbbbe0c18f5b4c59d98b7a194a4be018f8e05f60854e4e3e9161bc06e06266874176891f1a3f41de21d2b0626495a7c3c16899062a367002629cbf8e408d25c76f7274badfd088d3d96c6f05a683d172c3919017137de46b65d1ec95904052716dedfccd32d1a4c50db6f52a0cf42dc31680105e948eb7997379cfb6e14b2a3ea0d853e823f839b8903625432cd7acfa06430c175c2e6636e631aef4c260f883fb0244a31c2418ce21905702d2baa354568e957d34ccc802d8c042517487055af30f04cd01f5d2cc653f7a732eb34dbb3f2bce2eb64ee9526b77e0db4980fe23e407a8a51ce36a7e791f6bbf55bf331abda96697a450666d0a372bad1718d202363039b2e0b699668293e5140ca81e81938c218d640b8f420863dee6a1991902b4873fa90f2b969e4188dfdbba61bf722387cb99833916c662ff13481e51f5599cafd31b369712dc8e109e7b244649b4c3f5036451a030dec16fd9a4dbb9cd51893141c6b06429ac375b382ab4d0b5394a05e730a90c031c2d4cafd17f43abbbf86947da3029a0d8e3ea3327026b205562c5511761389d33d539bd8117bc7909e7041dd6522fafd09c01ae53e0dc53c7ec9abf2398d9091fdc49a52ec12f2e56350dbff40a97445d08dfe7bbc01fbed24e10335bc61234ef0f10a1873eb2cf22673e67f351014f48183a0470e7de27252fc4613e80466ad1ea1ddd8b41dea52d582e75d88c29ac1f753acf2be29cdee452b15c2da709e5c0adcf1770210a2dbeb0be7fa4c01754ec84fb61de21bd34567b3c68388678ea553b5a23a99bb4b49399f87fab4733a057102572878821cbecaf5a2192d05a1a7bb0ad0716a85e41199332458a3eba82ab5ba94a22672253ece07232994ad1fd0689d37c7bbcaa2b32353b52141db412a1ace8887e0b1b9d931f1807284130a2d8264c9fc2a94c47ccae0e205762a92fc0ef4abed72f4be4696b0fc46375a0a51f6cbac15771e6b13fac02cd8c3facea81e303f5a0b4359414c1360e2e1cea8874b84b8d32f40181a1896544241b681f42e1a4b37e03f367dac85a6b6e9d2af383cd3789bd221f808d85cac9ee9f22f16b7b64dd4f685c300ccd306ed09b8f23a93a6699ed8a88019bb6aa313dd7d9bfa7a49c75c1935d123494071f6ba68f67104d9479be9f241096e5cb4495a9e9172a90bc120d04b21af022f8c8fcb0860ca647875e09c2ebe5c1b69970172870991f93b5874abdff06ca5128fa93911f2d943feec0483ec021e0dd988c7c5a971ddead8225ae938bb9ebc4ac18b43a5342b5e39a223b30df162dd066525831da8125003458c81660166b5c54858620a7e27585594c48edd7e8206f125ffac308f5e02f31e3bdd7380e119f3d2f81fadf21d946d40a377e9629eb9f1bd7227004788e3d3124a07e1ce43832eef9cb8fe113d01545402dec0317603e45966d9d68585280a4bcf93c0239c65bff168812d227377ed85a0ea5a6af6afb4e84c30f59012d213b63d3b2e0c74556f2e5f03bdf6c66aa3302f47898245f92dadd5a9e1c84a768ca02ebdbe83bf6ee7d6399fbe6bf9f753347f9abab077c0ac7cd9a0aa0ab1ece316bed289259c500d3e0ce58a1043334457aa58008c1305272e2f8c185bc75077f5209e13c841a7c3bfb5be90af1053cf382b7167894979150932df731c07619207c066fb8336285c6302f2e9184968767d4d4164276fd274cb4ce28ca268521357796cf5b2fd7a8d6055da38db9c7774baff9091989a28141a3d5063b65421fb307eaa9a1496683a14841f9af46a22dfeeebd4a0485407f1ae1b643debf66c28dcd9491357a95ab46749880107b4ec779c16799ecd127c78dd9a39edceea8a5a31de25bd277bb8f51d3394b603b26329fbd897fe5cd6c48ef8c7ce4a172b8c099607766820bfecd64a5cc3f4d36a9173ec2ee5d6f57ba9e2103f0e581cd62995834589d5ac5345486bc9c902167e1f4d66d236f37474013da25d09b8d1b95303979c58d81dfc2d02c5e6ae31cfbb41b96ec28faa70d508b400468679b932799141ade97351a5dfc0fd25a9d97fd262eb0d02f9ac0075f22bce782d10f4164077c6d1b1fb8a947d6d30766ede165be5ba0b308a10f4b5e362d609f4aab4c2969e5b942310b4a33ac8938ab02592dfe858661f1c19509df4f06e47b21d29b84300c16b72d3bd1d00bb3d38dd37985b559bccebaef28b29a15da12e9adc3b2d9353f7cd0c6f65956e98ab6f615ab238f01a51a1904861e6f5b60a14deec07fef3d104909c185a1468c498475eef0f1bb02ac6ec5b75ddb4decc88698b4d11dbccc1e367a21cc53b5b683cd48796b3080a1e6deca281ff68956c819469f0ad0dcbb779ded3b7d18c8618044d8071137cbe862be7b36ca972a542c05a2a30d83f113eef050a056fd078f8599626a321d4421d85c79f5c16774c429a3026213058ba2b45188a6611e3e08073697146bf1aa8123c6ac65b3d38081f90f10abc76e8a7f4e9abd9a814e2eb2998f03153673680af8d49f943137a9ea61f16619e16e22d63743b0be7d1ca4889dcf949861bebc02652d00497113cc07c48ee209e437077bb0a8e2c8ebe536b9578843b4fae1f16dddc9513a5d4294cba8b9819a2056cf6b31d50c0cced818ab2812159f37017d8d55937eb605fd8d134ecf20aa4dd1f547125fa406e11a86bc14d089592afbe5f8048464b19d087734ae2c4c88ee494fd56847b537169c2b5fbdc8816eb0ab5f8705ccc5db323d71d1414470a0261650c3306cdf8084d9d5157595b56c07773c732fe7b1a3229b9665d13b3a8f53367d75be912224744d14a8ebbcab006a81466bd85bd0dbff24c35055077e50e621d70cf90b28b9cebd400cef29a1b536ef9361638face3fd742a490bb45adbbad4a6bc005fab7844e6e0eea8a3e0916210105d3d36a66efe518572cc18ad154e0822bee6a2efeaca85922eb0d05bf56c70cb70e08b06b23a0dac0bfa28cd428cc8ada00e26c7682f5a26db409232433adc4e29f5330688682de3b2609e5d03f09caa749170a6581e020772a7950004a8c77a1ff69d42109bf0511922f6693927a65a0012a1687d8459eb68b341282360da20fa795b4c461d367a0c0bd1bb71dd46e94607f6fe55b496ece0ea7be44a529217aa47a09200eaea0e5a8d89064b75d6434640cafaadff0e9e92fc8d2f1e2861636815a59f028dc2725523a4851863e4fb1cdcfb628bd16b16bf2664bc32c4b2e681f26595c204d57d06ea15a89b1cc1d817f568550247b27a3cad850a038f808d8d88a05fcbde64e04d3adbd7763692850247210452c30d3e6674c4c7a7d4b5410121d3f3c845cc6758f9bc2b2e8c519a5efc79850ed0ed736b1d5f66d1fe5722e4d90697e0e67610b86a6ce0b6e163d800fdcb085c122fb197c70fddc7a9ca4cc0bdc9f73142966e473ef48245330df44c39634ddc0784dc4ea1b03c7076091cc8d35d3c5c0582361081dc21a7e95628ef8afb0372a061fb776f2e85e85205c517bbecdc2d353378b8964203537e5190c3c47180be2987ba262eb3d59446761171f69df24ec1e3c6f4f122470bd88b2b682a7b9eb14e37356f268457c68ac5c3c951a3ecf90495327b6137f283a1a831fd3abaf3656ec42afbc2330eb07a74b326cf68403a4fabb21040680fa63c45a208a98ed53a5211b4d0ed88c28fdd38f5758e53ea118cca426462aa6178389d18bed9ff13a13f6827b45df8a246e2120f7abb59ba1476c25860295ee7f12dec1a850cc0d3067354ef7ecbd7bd43a359b0226d0dba72c3fb9452483186012d45264775d7d46e66600e1856ae6028a035e1a4fe0b256e4a88f457dd8399e50c7a398954729d38d17e06d87cd6493e240f4dd1d745c4a06dbafc4e191338ebc9ce880dfa91c9b72f772a2752cd0002aa7068b26db449669ec8c9025201a19cb0922e1d5443bd4953c074836f3a4234ec45b3e676a13972bfaa742ae482c39d67c072e7b6e84d8156309433b7e527db34c4fa2271e2665aeba266301885055bf3c10ea0fceaecbaa858903b716914ba59d83dd3026263c79dcf13ee4dc4f883c0c6a02a12f392cf5267ea86beec99c899042702ca4d4386893b14c40d2482ccc0925d174b1e1fc7990786b0200fbcc501260e648194c3b3ffb87ee8c69b00c95245c5f4c35dca94ff468582691b40725c1fd898074ce4a4201296bc2b39d3f58889db25be33df67ebd3ab895d2797c97c4558c41749a507797c41e57a155fc1749e46c8266b9ecce9e6312ec47db26e8d248116cab45212a651f5d64534de8229e723c72b89da429036050e9e6e17f1b6763c09202408687dc2a47cba95994997541079fe8b0a2dc915072e64601a6ede530bf93f09b1f73dfc0b44fb5c0108a50f27aed46d36faf2911b6ee3bb6ccffb6dd44e887e2625e602a4f2cfde0904b77ae7933e4e68ca6a86850b0dacaebd9f1e2f4d54b506ad926abf4340a4d7ff808df6fd9b40121ba78e0ba200b286903a929d81471e31381e07dff25e31aa3107763c0b8a26d87cc6bad38fc01af16472e8a532f7906460d8f2d3230667cc76c6d80fd6e37b79709c3ad31aa0b79a6f9bdda008670e1bc651441766a23c8a05e1b02b1897d7b8a68bc6580d136365a85b7ffdccfb35b00b8a9179775c52fb8b7b0d46a9d983aa5fac07cf89756ccb1f078539f54a967166f14f7781f70fe209fe69d0c61d9c66c67e3f558daa0ced6de20f87e38784d287ab7e2f1f939e25de792548fc13cb88c51b77c423cd81b8498f7aa976f4270101c363ea590db1faa9280e41b146a60eb40b6913983a565cfe4b4bf6d4b9c7f3aee0db224d000de2bffba87087d432db11f71211f3e5df9da93d3e2a12d5c633ba97e5361a897c5ab4cb3c26905cefa4c09b31e2cdabef94d6eb7640b9acfe9306565cfe46c2e545104ef6c7e8045e7c1357c21325ec0d1da3451f2bd9d4e41eaedcbe1955b7c41367ee87a134388577dbce66b7fe91c4136375f6bb31e87a5ad77682207b15efb721f3638f8924600124f05288c9b3a21f78032152f6a6b48b395c0b3556e23ffdbe70333bd9d301c843b1d0a44df02d23bd7b03da298f3d107b09921f0e07f3b92425330bf69faafe3422dcc43afb1a12b2e090aeb13e4f5dd90c63a7668eba74ea5792f8831757c00998b5194148ca6a62c8e45b543c13e6d2b44c9f7d0f98248fdc82961026d9603fc25679e30154987ba6d50fedd5188045d9cc0d610343ea7931b347f765a12b05fb9934045033f1807749105d8db240872f4db5e2c06ebad2ffbcc2e26126ec42252d8fc129484a16f97a431553642834509733af9aad4b54586c898e4cd91ed9cf0673cc398950efe78623e0c20bccac83f71eeef0f8a763da94b08acd4f7a6502e643f40c777902ed33cc8a3f6b919af4aba0ef2b68fe5ee70f15ab743d67023e5ca13d659bd0f17a7358db4e5ae80455d5c017f6ed3f3971876bd9be56bf2a85c15926ce1e145fa11114756cf2ae51bf1f2e63444d6b204cbb8b03b89e393b88f5f958ba8af4b586cbc4c9be238e6aad69c4193742d6ce9291ce9ad0e261015b2a88c1c4e59304e75735aadbb48612f64ca373ca8411b10e37ddfa5c23fc5238e1c3b19970a2b5fa265cda612002c7c945ac466648062a0c1bf772d2becdf2259ed5a2f1de5bc4ae33eae24aff48e155e96c5ab4b113d825138cb70606501beffa4a15e5d74073a2db77bca2efed6e8a068be79d29e9353463c15c8559bbb0a8b2351d3c3b81c6a1908ecfae7173ebc18113f979168f7e9fb1550e56177949d618c58d3f126d68018a7c4c36c165afa010458e1a19148fcd4fcb87e2da44704fa4f3bab5c30145a4d07998ce5c354b49dcbe3d29a5a269d22d7d66deb35b42eb7a77eb363b0228c7b210452e64f9cfec0873e047127731cf34677bd0e9c838baa691761bd61abde0f109832dfaae5f27c34d6a06051486b7b77db726f29539232540ace0a630a2b5b63f498b596bb775badf09f6084db46f34663fa1385d4714c7b9036f469764c874e38e2faf78ff42729a963edd33f2d6b2022229a51ed0869ca6690d0d04c1ec520011b666cfacc9f9c1c1c3b7ae41871479be9487f327d7b57ef30398b89384476e8bb91dca1ef3387d11d218a349b03429e320803a40ec5530769d3df30397ea9ec35b20d153c16934191d98ee5f028663ce2548cc35d0efbf0ea520fdf0ecfa8e0e2d8f0cc3a12abe4f602244cee5cb185344278e4ce21211a38dc117834fc941c0c7c6bef5dad5c7e39db1652c0e619b82f9220f10c934bbf77ea7b2514ddd982f725fb43bc2ffd90ee2dcb47e9bd2fbd873bfb1d2e6169b175d7c491b46e2af3b6f7e6cb7f61de9878ca80489dc6330869b33d87236fb07870df7d67cff2e9f752c41d25510fefa7bc418197443f65c79d34776ddbbfe0b012163fd33d59bb6ddb865be81d0fcf99216e7dcae11390a87182dbd34ac3a68ff7dbbc62edbda00eee3bdaf6d3675ec9db0361c9db759fb217a7cfddb66ddbe44e28c40d62c211576cb105b087f7f73a6ccaa46b7b6b370e6fef9542ebae59caf2715670fb913622b44b49ccb6e6ba7d2802b891404a92225f0c7cb626410c5b802007d91757146104992c70b0c2050cbce80112b4a0527ce0a2a1b03d77e87aee6005122c5cb22c42f2446ec9b208899455a783f77ccedab2e240df52aed65ab17feeee95d659c35f407fe28f72fb277569730d5bfe5a6c23fcbd696d2bcf64cfbf2e94c91efdba9095bdfa75614cf6b6af0b61648ffbba70953dfb75214c5665aff475e14bf6bcaf0b532ed903bf2e6cc99ee9ebc29bbdd3d785a7ecddaf0b4dd96bf9ba10cc9ecbd7855ff6505f177ad94b7d2f5f1776d9537d5d68b307f3752197bdd5d7855bf6607c5d58b317e3b1be2ef4ecc97c5dd8d99bf9ba7066af35d3a2a99fca14b3363c830ed40a34df37d4f9787e94d24a316d91d2ed6b9dd551405531b8fef2638070fd37775fb5986a517edd2826929b099d9712d132ab2f85f36869aee1fdec479d486e1aa3b925c5a548485b9fe2e64ee0e2f6cfaffbfb32e8df9765bf6aeaa57c55ff99ecca385a08fad57bfee8fe94d66dabdb4b1cdd656fca292735d52a324b9e3dfba86b77d3aedd9614b79fc6a06df7a3905c393cde39aa90e7afb2ecb467c938fa42a96d72ceef580d6340923124a42c3d9182dada90690cabd5bdde1fa4c683d85793722621b9d73ae79c73942185c32bbd92c74f4c32652df64b09aefc71be7455e92fadb532a6a4c689156d146fd09e34d440739318ebc7dca93f772af6f976ea5f77c967f9cfcc3a65c72391dcc402155b77fdecc2f3bafb4a29e7fc666936c54879ba1b7b373fb8fd5248daf4cd143753dcf8a0c6dff88000518a6c000829638599fd63fe857e18ef591c13f332312ff3ac897fc4bc0ceb078c673d8c67d51a0d5cfb758993055c5974a48b3c73c8b2c8c816790723a8ec6084fb2678f148245f16c8026740ec83a6f53438c884b530ab9bc1ac6e06b3ba21f2a8339964fc8c909a6f59158408bf84ba81394aef2940e61242d60cc3d6d3fc8f99c77808fe1971c8bb207730164264a78559d347f8ad9fdffa9fc1425aff2f64e6c3dac5e3cca6973b3558bacb11d07d13166b3ecffc1f319ee669b010229ed7df04758078a4197c8f559a0959a52f95b08fd6d36021257ceb85c8f89927b22341560be18f7f56a9f5343f64063f919d1f345ff3357848eb6930ab8469f041f3180bc97157adbf43eee0e81270e963e027f3e58e0c5cf212eed1e27f2f77c050e6d61de28e32e97b1b4010cb16c1fb63e65b3f837fb486d0601cee32e116963b263cca1a11108fa5ff7e89f92505b4585b40560bfe320fc45f06b380f4b3f0cc0cf84258a56fbddc99c1acf9342f7740ec03ffcccf6021ac1266b5107eeb7fccfcff90d6fff80f3fc443667e0763d6c44f83870c011fe3fb3f688680d703c3074d263c7636fdcbe33044a1b08f184f0386a56781d8470c1fe16356e94788f1833f4f6f7a80ea1486d8745281e12964b15ac04ff33ff0fff889ba1e1e3ba33ec5327d8ca7f91bb258ab373dcccf67b1540ffecb97fe3e0e592b13fe1103d36016f83160304b855b88f134cf02f18f18341f3e7ed60bfe113efe103f0ebf61cba31ee0f2a59619646e7109679879e251ce9699670c2dca84a17d56685f82134be0c9bdff99f048249b7e965e3af8f369c0a720eed1a2e9f4a5f0fb1b8e1eaea11be439bd770a4b35f8ec7ece84ac39e79cb384470ce4d2cf70b4add0f43398059a300b047f060b7902621f334f8385e07017f8332f04dc99e1875f903b5e49e2202d5656963bca208db2fd69ebc784720746287770f8341149b52a09504e94a25028144ad51406068f44f244499a7d1caee2662ae5a1be460317f5f463b4b8281898944af5425e1ee5d4b75e857dd0d0a8706a4e0a5a87b57ebef45a1fce2009f2a872c495b58ffa71458353293c06c93327d31818f518e3b80bf5385a4a7fad295377869a28262da7934ca70cc6a3ecafc2710a8d32c89a0e59a80c65593465c9941b321330c7f631ef12c6bc3743160a8f4482568fe3309a8781791c0e83799a10e743e92e18cf92f9182f775a3f7e9e333298d5c23ffe1fad8f8187d07ceb311ef2c407cdb77e48f82f669c8c7188c35da96f8538ee4a3d4d88e32e98ff3035e66418d54f14ea67d8a3451814cce368160c663d0e6785f655e178736a944839f5a9d4cf9048f65621057950dec340a94279bfe55b212bf5e394ad302b8573d830c135fdcdf956bfe6d351ce685a3f811cf64f514f5533e8f412b42da6b0a79e26f5ad30f51fa61e26a44067d54b1c0de6001fe65121ccabc2514856a5469a51ef2002b815b62da2ba57955cde419eaac2a3ac65555086f954ea2dea671516ea5b307a14099fe65928cc6ae1bff53efe5b2166a14eff78855b58080d66a1708f22533683dc45ffa5bb508fc2234e9e6f23e8c678fc25bc90273e5a1fbe90273efe5b2fe4890f19ff4f83853cf141f32560212f7c88853cf1113e0d161243885b8f85c818a7ec4749f4a33c7ab94383553f4aa316c67197eae5cee37797ea670c8c8910c932d5a345d5c3843248a33c55ff1272d816e97025cb221d92e47116e950840785472119158e34a77e94443f7172eb5b44763e9c3b611886447668c2e9a3821097e65bdfa3080d6e61e9ae897178f7a8d093b925bce1388dc85428d3378560387adf79b8c3d257a83fbfce8914d32b1c3cefdedca3b294dc512209e997046ae8570d1b6ab458e5e4da478ddfdebd46769ceceefd9bb51656e4c936f390ca53915b67873d64a8912d7ee1e78eb216a4014d80eeebc7506590b5fc5776655c28b270b8638e01fa35d6d079cb51a1fe0eef041f5c58f7f2fbbaad84679176d5f7701a69f1c75db5fe093db8e3ca48bbead7b7b57e2de18beb0fc41179a33ffdc075e17166d77b9e9c19f47a4a2adb57c115c0d583df87f3311f53f3aaef8b898989514da479e4a556dff77d48dff77d156cc5e08ed3c7915a31b8d3c767b5f23e26f4bec529b36a71e2f083432c8b38002165f1c5a7e5180e70c007e49a08e535d30bf8f2792f251105f167163f0cc598989897a04a15d3a06d31d5443a623e7ccff33c55ea1be4f126e8799ee5c01c312f23a59c3eaa4d05e68879eebfd0c62402f2787dcee3e85438fe2ae78e01a34ce206d9ff2493a0616ef209a1ec93ce49f3c9d4a6eec658b264cf4103a2f68706945b3e4f56b11657e6ba7932262efd96a134cbb46ba6009298a66902bb3fc21205a99bf334815c9137a6dcfe0ca4e6b01e2cedf2286a8deba53241d91fe469a9954b41765d3e85216e4dad86d62e9f2e26ae9c123392251517c8324f4e094fdcfe31c7014b5a74160b4c80b2bfb300d4afce0ec423894717fe2c1461c1c79f851f169224657f1664fd7ac9fe2c2ce9975ca209a0eccf42109d0e009205f56b94542c7100130738e957a5c17480cc014bfa35ca28b35933a586e825558bd5f470c1cfb34cc48514fd2f0fa4f766b8e5140adb58f51cf15043aba119716b68996be1ea73554ab9a3d820fb4b589ec98c8484f51c4db9c1e18eb2762f0f2e782089220e4ea908f5f028a5f03122c5cf298914b2ec522cc9ee0501794c3c275230c91e508b3e7b36f6642d7aebe0f2fc19569f1fe9ea39029a228dd41075ed40eef7a01ea017d7fb51c2d0d97043f6dd90b5d8dfcfc0e50f869f161d06232d7ac3e0d3a27758661898f40b06188ab488420e77f46cc234ccaf148e528a22520a9f7c6f142320b57ef595232c4090b2004902d2050cb1262f2f7393d4fbc350a45f271f23fdfa812149bf4e5887cc321896c000d42f8a9ba0de1f0626fd6235f698b4e8ef2d9161e97679b270886b0987fa157343091c140d85593f548f7ad48b91c3583e500ff3303f5243509f7ab9837a223b13f5e3057bd89bb96ba65a5a5c6a475e2416f3a91dcd192486574d96efa1bef95e92c3503f7ff2fc8ce449e96724499ecdbc17eccd584979fe0b1e3da21ea429927af41cb98b8a965778d4ae9576485ea50da4d6af514e410272c5290fa47eb950c48a447da9971790e7ce15c873bf6e3568144b6963fa5a8396fd4f9b09f720b5e87fc31e2c3d4732556e6d56579f97cffa0bcc475f2607777b14a53f6eb1148ad60d66f5c1f8649eb8b53f266dfabd188be226b0a8926513588c009065135898e40aa3fbf44d373ae7349dde9b734e9134ca29bac8b216cbde7354a3f983d10303e4e9c1d2a22a8b59fe0d2a7794531c4d8114c3f241478e99b419abd00c93f5c97e8962167375c105d44b77398f0a4a74d4dfe836b76ddba48c69ac404ee9a03a6c8bb3e22b23333333e5fc36c9d6d773d2404515945cfa598a8e26a8a70e43e1991918ab150c8c419edbf198617e912930837ff1c5045550724bdf7d3fadbfe1e89e29983ccab0ca52b630cf40992f6cf11496c2164c7642ee150f2467c5e0cef729dd4d8d61345f4fd9e2fcafb586d8e22f648c2fcfbe12660f2a0cf54d07ee28a3a80589c9578d1352bc42be6a683d480e4b7dcd277bedc70999f74b4ab1f15891e47ef73c3459134721cb1b1e6b50a62df3627cdf12a933a54dbf8cafeb41cb15758b3c2514257c35337ec60c9087a3a20940ac485d2d326a1545117a8ebea3206e4d30c1041a0da001eaa03988b4f1afd18184bd601ea93b458d153c90909830f3645b5099695bb9d22fd30c8b294a1747c4b2632058808cf288224090801c01a901b9d2a2df28baa3acd520201a353e2a6f72b8433e947dac31eb7ec199a851518c5a33b83580b23fea533f7a403580bc469037ae01d42f54ceb31b4b5c290025ee588334936d91b2bf8d0dc85353e5e6e78e9e2c4b295f70cf91bbfc53d6de97973c8a20612fb82775a77c911d53c101a78606f2d45469d17b8e78b823cca706f381197199bbfcadd0f564d953c84013b99fd25278d47faaa7201965bfa2240348ad3c710364d2c6e702f5cb26fb7b4c1a16858a939c42f14072180a6729edf22949f966071e729661aa1fe51447b518c220ee6ad4a7de5937b8a9b067863da8b027c95ddeb8e7a8c59824d4c61a5af6a7dfa30cab5cbfc54c946729195cf125bcfda8efaf31b23981bb39926752274524753aabf209df09379fa4b4be8ae88e328a5acf11ad1d865927889ea31ea406c8a48e8a0749ea9cde3f4b99efff49293da8c116d92591114e8b27dce196eb46c3f66e3e0fe793fdb238287c37462e0f520c0a28803c5c0c00be09ea287de3f186121701decf921494d05c73ba9936d37b9e9ddeb314222afdaa6fd4affbfed94abf2ace44a7305369f1e22ce54433ad457f5398c1301bb528df5e8765234f85999689dc95672dee70bbef7b52007370991691c759b3ff8534ccecf9c8508570ba96fd3b907e0d5914e708a99cde079a4e7d5b9cbaa052f54505b38211c3929969d17cb87138868c126aec0cd1654247a386cd093738b23fca2c7b9e39ecc64f26aa926b194b92298ea264c92ea350c95ee48125799451ae64cfa38c72943d0a52f62849d97fabb4e7a8074bbf3a23d9a910ba3d9bccc0933262720a4a563545bf16536072ed8bfb9c927165defbc57ce306d7f3c95dc3cc9f0c63fb93a7b724cfc769247f2edb7ec9642985a4ce5057933aaa2cc75496b04fba52f4351b4b1d2f668d625315122a0de1ae26bb3d549a499d23a9a3a24627244fca18712bcba71f874bb2cd7f3e30fb0896aaa90651f2785a22cba61a647f1ac224491b2799069a4f4bb27f0d51442dfaeb7871fb4714914cf674bab8238a28053405799c31a2427926266d5c4776fbc719235af69f319aa9611fa9a3ca8e22ca3e93718d084fca10401277ac31d616d77facb1ecf6c33a644e7daeef620d1c0eeb902a649fd87fbb31e5caec9fcafeb6fef4073c19e4ca221faae4fe79c5bb0fa83fe748411e200f0be4ea74fa03e6f70af3c869fbdbaf2c3dcb593bede4388ee36aa972dcdb0770b766eebd7636734ff303b8fad4e2b9235760adc0e24163b15c3f572c2d53457fe92e6677aeaefc65fcdf57b5d64a25a5a1adb91f4767dfc29adfbd56fa8dc5f356fddabc66979f2292532228f241ca7dc0f68d2f8ffe5a9423cd75f2e061813aa9142b1ea9ac0fa0fe54bceab552f1675684840ba0a21e5650a9fb6084bbcc30a11ed02c151f5891c74fe80737e411c707b5eead521f1421512437a5947a08ae406319c89ec70b64fa8ea5e4415fe207f8016456520b191919191999ee362fb4d26567dbfad372d972145cc1e6effc56aefd6aa052a4d6062a843a0a5c6635e5a4ee33db03125638a14e4800b6176029cba21e4a800324900051274aa438913b370a50361063c1076a55be903d48410f412f18a20a124c8e6e52a7031250e050ad7454b8954e07d5ca8deebdc84b6c9765510f3e5809000b964082021b3401e58824274042104514a5204b111fa0229841877082225105169523f26e309d204977829f1b3924b02e23afecc5e1460f3aa4b8c8540b8f0b4fca18eb4fdede731fcfc1083746f3367b623a9b37db6f8de911d2667bfad3bf3dfda12fa03f5b6a436d2e5b0ba6474f65ba901bb99043e1422ee4426ffaef4b75868871956707354dea70bf6ddf4dc817bd428adb6f2d98ceee8ff6e2b14607a54e78b4a6edbae015eeb04f8ece1ca647d266fb138ea0b3a4a48eb54fbf3c233f9da45f326f20bf8200ee2dcdad1cdcd2fb95120fee2dae34b8a033d68f212ed2a826755ac22137b43cea85a030eb87cb10d4bbbcdc11d2f2a8166cddf564db36af49d7f676dbb66ddbb66ddbb62d07c78e1e2f04c931e26e6f57bfbd88336fa442223bf488ce286da3b35c7fbc3eed2047765dd7755de7799e47c548894b92f592581981bbc23bc27647918a2cab7e9c7efbfdd504a62e281355fc7c5ed8eff7215312da3dcff33ccfc3f032e141eea7f68b1bb9dffe9c9ee8adbcf74ad86209833bb3ccb308d9620e8f385b75ec92fbaa80f04e40e276de4fead5efceafe10c18f8199c043946dc91ce2811a551235aa3475ef39a1f399227d118f5f19807491d7ffa1ef312c817ad98fe04b320df6a131226e9aad6996b8d2261a174f9e7b4b86e5081dc455f46a61b664956fde7febd0872589df96ae2f1d6990cc5dbac45040742daf8534a931c460329c6c4654eb2bb7b0dca5edb8170992ff1228f9fd75aab0321759aa707f51a6bd1a1dc20d2c6dfae9a7bb73fb664b73fbe64b73fc264f720ba854dbab75c57abd459a5b5e844b31a8259aa461bfc29ed78589ef04c5a4873c395eeeaa7f14c1a0d072eab76f7f347177a2f926c70d8a4c9499b575adcf0685d68d2f0acd9e043429336fbab4c239a4c9ab8895d49a27731f79855a6118dc60bee7c1c706f59f6c52d64594c838ffafe34b82077de5ddcd3c0fd0c2ec89ded1d0b11b2c2c99cd7973b746723b25343223b3638acf5c3fd8c19e124cd4912ee04b42749702f99e4712ee1384e28735fb21cedc992ccbd02fad5f190b91d3267adb539fd92b413042173af42bf4ac8dcd7d0067771f3c75d2eee71340088ee2893f2fc06c00dae0d3e4930fafedc0ec7f5f72842df7fceea90d759e4ec9928ee688566a4b8a31ddb869d63851c6685ae5006e26ad9ab9594508ed49943b3ec442b5af6e7ace82f0009eb2da4cbbf3d86a404956b983ff37cda595a74f74ea888992866a4b8fe6fe53656c19332c6d36d4741dad41f698b08b794475aeadc5f763b1c26258e0d5352fd9c9f8e6db4583b7feffda459d2d5f4edfffb0e3bf6bec34f29d8a3c8e7dd704bb8c3fd230e8eb4a94fc381add6df30abfbd2734f6bad5f6badd5ce9a0c3b1a164fca18b75aadda98475276ff1060fbb19303f0f99ded4750051f9c9d986dcb63c764370522ae0e36d926db803627dbd026c568a3b2c936a1cd886db6116db49a0e8cac18e9a0419e1e74c906b4c9a05cff7193e56e1bb96f3fa5430ea3814467548cfa35fba8a9155aa347743652bfc68ef55163e917854177a48fdcdd6352e7a957c326dc6fa18fddd9de86453890b3b3bd8fdde1a8e4915239ca43211da244e1151a826bbbeea933611eb661a3f438e8564a582cddc5613a94c73edab0f4fef1843cf6111d72571120dcf6c11d6b910611b7e66df192021177b491b7f7ba7923c41db758cf6dbb34aed22e157733da68f346957ebdc8b6df921c46dfdebb7a2e96b7bf3f7f7aefc3dff3def1f5f13d8885f87ff86e3469d31ac20d3723afd68e3723776db4ba516e11e1cef7c2edbb9574df277813c41d3b48878c3c3770592bb06c8b5fb6f3bd886d31876db4d5b644121fc8253cded047d8402d6e9badb1bc7d953ca67ad01a87d4996f646bf7688594379a94b7ae92695de4edb3846d4d48d7f6566eb58d266db6bf51d222c255b5887063f4f097e00c43f24824b37270555adc7e7e91c30ddccd68a3b5b83d8d19dcde5ebe20d1a0a54528cf9fe1c19db972678d8a3bf68fd4a9797e27b94652c787c877d77c2f74e7da364e4e0987466b5aa5d1ba76a9f41f1ef2c4c7101924865aad7f1cc6f2c9f2ee7d78dfbd7f87853cf1ee4b9ef74476bec7e27effd8e0ae1933f1e0f2c420cbef3e4bffb84be6ae190a71a7cf71fed46eff8c0f6effcc0fae909090909cf3a74520617267fe48e9f24bf174f796596b51b608d976a93253e58eb37b5a7279fadf65bacda7d2c336fc5aa48f82cf1de52c16933aa5223e4b648a7a0aba7debb0475d19f777f2307d7d22d9dddae738e724912cef7b38f6957cdf86a304f2bd61f7a7b0f4a650b6e88d53966ab1f350f0b952babb944f5d22492ceff49d558bc56219483281a6932428990e511a3485aa4b1bfa2595d0810a8541a6524a49658884a481e46e5586ab16e96f61096ea56f4212aefc0bd425e179275ca12101e0792928b9325a4c81c995d27573e4e6c8cd919b2337476668d97f66abd5a75dfedeeeeef333447fa4fed23b16b81c491b370d19310d350c92b4f1d590c320ad8850442b9a4c92d451998666689e8527658c357e327d6fce39533018a92c0303d7d28ca7e79c73fa0ac68b0a66868fc36060d4cc5df7aeb0f49a83b499d567decc97336833aab869c834d42f234cb3af32493368fd72f9f933aacc90396c45e4337c6618e957e9e7cf983f23899c8d38e26986cf29cb90c9583273980c1c64f060650091276a264303529caf0a637c21c5f92f610c24f8cc1b3192e64d0e318e90e7cf4f85318e626069713e2a8c8114c6c8d2e21c710c13612a440ec3abd1fe154d785ce18c2fe218cefc52888b601fecb9b7f29741c7461cfbe4898bb438dd318eb598d4458bdd333199a416a74c529ef3659264ba98f36b5015aa43ee4f6952677b23d9dd578fa363c2eb2e7f18a19c3f968ce4f9311d0bf2c4395a7973b982a6c03494296ad62efaf4561f50c74cde46972b321d51b34cb91f61b60883a40d5d11c924b5485fc78b5b6b84a40d7d9d2eae4cd27c5a23547f9c816399fe0c1fa993caf467fcd018923aaa3048ea704f659232a54233b986e3aac64faa5b66605ba4c2795e66b6fdeaf1bb593ecc8f2bd8eac7ebf22345a55ee6b015ee2077f9e3eb47481befd9bcf1afb578a5c5ee80b27fcb77401d932ee8258dd640af3995d12514a899f48bce7270c4a7b2539685bda4456f1ca4cbdf9b87ec0e446b408a5f48d1df259c4890a27fcfe68d99346f8e903a476809e7d1c4226ba21d2cb4e8f7c3ee787c91c335fab5d8ad0fcc9ed3536e222a2dfad39a2806923b36918c8888ca3aa154773a7894fa69e6f57bb4c58903ea28e5d651cad505dfe6f47ef76f2127877add2a4779c61c50472953504729ebe0b8d56a03754c0b76bf479b524ae994d6d4a08efa5d71632b6d4e39668f221bd8c0d4114a9bf9a1b4b19d8ece412da863b664d9813a2807eab8b7051d5c09742197401d3353efc4337679fed8d1f7befebeeffba6b4260aeab0b82467a99dd68db32553fd0d57d60aa57102d931913abb291e7d8f86373edcf932266d64cf9063263b6e9c8388cf15a8a0efb4ab894e3f71208f69036f0d92bb7ded544fa7c779f673b7a72f4ec0703c6119aa50be7f4f9745b76af2fcbbf9b932546ecd28773cd6a0596794823ca50f12eb49ea419a1cc853fa7b3f0525dde0373dd1d34c0ae2d3afed67eec1d22fd993a5a78b7ec92045fa35710fd266da7a927aba08126bd1bf7fef6f2843157a567fa52d8622709c37a7f75ef705f1f1ac37bda9006e00e2d102b40c56a1b0fbae95524a29cd46609e1db9a5ed65a84235b41aa3f0da59baf100ebc70babffe577502921ac1fa857bd0a0f61356eb27ad4ab1ef5722795e7a70a334cb80af3ac03f0bd57c1ef842b20988346e6817480598bbe84947cc29591726d92ac15668cc563c672e3185af49fb9732a0c12c56d6bef5dbd28daafbf07c11de595a4ec2d1ced4c6d92408e3a00fe3048d95f1545920bbd03a4e62e7fd592eba51e853311f803f5f4ca4bbf9272ad274bc382201539aa463211d842dd79c12d0ddcbafd3c0dee8b50f6643d4750b24bc952da4563c604977aaf72a3427bed4c2eb1683ec16d7a93a4070b0fa4da9e109eec7493e47a42b0908407120f242a496a161e493cba88b16084455948b2840a132a41549c5011a20225fbd3aac3c5279b4e271e591af340e2e19ede54e3045843bb325c667582b65afd83d763623a6d8f235223d463b264a314476f3287a1308c2cfb732d15467643895bbf960021a9d3ef9f80a12d1395debb17e499c9f2bd1494dcd34bd0f4a93007adfb20e0bbd71ae72092dd939702935646210477945194649e2f0ede118ead76a80e4079228f72e65181b2c4132851a6dc529645505c60e55ea1a11c402d66560ba22b544407849024c444072e868482c8610b9f2d7eaed091235d1633af8824f06091804a4564f1c37161d415d183239b10862c8e7dc248c5c9c1b19163e42e69718aa8c10fb5d77e778b2177495bc40b8c607154440a7cb0002a020809164445f8704408b1e6b8d256a9e3e0d8c85161c61dc982491659f0e015c9220359c46ec062081cc0620b19606145c7040b28bcc0a2099c2c99d02207b4227b5770451114225c66965c9ff60b054b7df0a428fb0a82a0e2f6f522ccacddc244bbbb9bae54b044767b83b692c7546e192129723fed4ec192dc29487a1b2c454247c048c136c51b9d813cff7dfaf49942a6a2bbbcfb4192a11d4a7d468362eb46d0483c1a13d098e0963a2582fb49970609ee482912d856a9ff0863c3d55a8ab1cdb141022eb8adc47a9184a04b33458de2ae6cd0c57d5141698b9b020157c5f5b22c42810f1e1614e0b07d71c123949070bf2cba27b7a3a21be27656381b5c5bc5aa608922ee9665d1131b7826b85c96454f664f86b6adabd45bce701860070b56ecb684bd56b4b7f4413ce1438b4a104d10444766a6d45a41c84007992664334134f98105c5904c10497c888942c652420410c0a8421403f258253b50b2a2920443090d400073839f9592263255133518253f40bcdca0a6baa249ca09da4b076e976591ac96479c291e70594228d5020fb4d080504420b9472e40ec70324095580b0ff6bbbbbba1f07197b5321f1cc02866272e3cf04d1132e15820ac30e2e1e4e0d8c8c98191831688288e949e307aa2f601c184914e07419ea5c562b10d5819646bfbadb56f6d78ed8ff6b3f81611b54bd2acd1adb54b161dbde884338014409d10483603d0902c8e05e2c80e152707c7468e911323289cc5c9a284da6bbfab84358012f6b77be5c70d4044542d0e0e7a704236ebc1c8e807284672f0433bc4b191a342d73835218e88c8a3b54637264b268e74b046e06eb8a620944e705da028f9705335d8a0b897059d066e15f238c0e488eb65c984154a2ced7e593261c511ab81db65c98415459a30514517435c54964c5471c50c7e50e2a20a1c507155593251851145b85b964c54d1028e04d70439dc52964c5401b4a1e0d22c99a862899d794593251357dc608952ab9135591bf7d9affb6628a548221b3900d903bf19cac81e4864ce39c5f34ceefddb56375ca7fbb7c232fbaebc4bb673574da19a423585947de2dc7b73afeeabb7978aeeeefe77e53873dadb2b7777c7a3bfd8d3dddda59527d3cc0e663bad9b69e32cc8c28e10dcf99b3d759f77258fd6dd2dfee072a5d2aa7a5fd7ed7097a4d113f7a33c422785bc6307c5e3e7e8bcc307f7e2add26eabb424679b1cefb092522b613b24ad524b4da7d3d6e4cef770c7775b2815716e4ecbc9c52dceec7339a1daae5e94d451224e2e853b2e4dbd48f93b5aa43bfaefc9b4432696bd66d9ec0a3f7bf59bdba55c01a44d5873099995637af69ba14c6afc6860e598998eac16e68ec86a61eee0e82a0d36d750f3953f7f622b3d726aa4ec8cd900ce6e771b2e7a77535a719204dc25dff4cd90b5c2fc949ddf0c6df6ae6cd972ce79e7cc3dace7f2bd6497d06617ea02b224ee51b1cc3ee46c87621794b747450dd5f30ad66e63d912b8d076c7ea21524ae9a525ef132a80b411c2d24628d7d0f9fb64bf6452239316bfe290e51ac416e58f5b3876d9c3b104d67a2f7d9956aad35a4d3d726aa46c920bca5f56234fbda8589036f26d4c2a4a1bf9326ba5fd9a5422f56baa66aabaed6aaa783ebdfd47eaeeeed4eb2866a9fa46560f9b5b684d95d1ce55bb3491a917fdd1dde9479d526c5194baf8b7c2d24229a594522aa594525eea5e4f9b9b2848f3c30f3f34e09b18892c697ca0f1008d07683c70e7734f93e4ceb74f93c413e58c7e291929e5cb9f927ae9a39452ea811fa594522a3ff497e001bc866a29e5b85126d91a34afdbd738b16d55523979f56be9a4d49b6609a5d4be648d1332a688565ab797af5f5d75aedb5ce6c4558a95ea0045e9d672c39e70dbe6c453dad4a695d62d884ab71f4c99f6b0d1dac3466b0fb5a6c0156af64a371e74d8a80e558723b43140f35e105e82eea48955b5d1fac3b6fd50e9f6c3121baddb0fdb0f95feb004adb46e956e3fd43aa5582f909d565ab7252add7ed8b696aefa2ea14bae3f2190fd279dd2a66e7ee9122e271badb46e9ced4ab6049a6ecb0b4cca49bb9a06042e94c75cc17069a15e89ab265030be29612e2f5b5ab24bd8127e908ff9649e52c75ffa64b15832a7ebf232c7256c097be72ab9f3c7297ba1fd924ee74cab01fdf23f62a5234dc8f2b18475cc7672052387728a9422cbff41965f0009eba08eb9c7fa551d84b19191d3ec906ad17caff35519f938707678173660e22046ee0c65e0700c1b968090169be6e7259c3ebe83c23386e486bd3323d092e63d2a5ede4b70a7c49d65312145aa0257a0d9a3a101794c4fd3c5b03628c0fb7cbcd0c2289dc8f27b489d0e46bbc9f26de48d49933af6af8c3c85a89c4ea79309acf295b0aaab9c11cde8c50a51e1846aaa8751931d1ec6200ff7b8cae02460c3aa906964f92e79630ad5c0594da32af3a67fe47207b564a1611dd44156a851956e4655aae47e979630a7098e0c1932b6547b597e276f4ca3d9afee67373ba87f5a4ab094d29a1a90877ecd0c9dede57f527458cbe33cc74da379d3ff20dd3a66748de8ec02e6a8d9710779e0b66c79f9de0de54e8b4bd812813cef0de74ec5d973d1895b6e58744d50a5502e2f34539b1084dab41249c68a9ef090e7a8429e2f2860ce62b19891f976d6272a4db5916bad555af1b94145b9feaa044c72fd174b8044ae8f638225b97e4ebf649109b6c8f57128916b2d3ac116b916394122d75aca336c3245f66f6bab0ca8bdab3b6f8e104e2e68128294c5e20919227e0023411099fe8a045a64faa8878194d274a136882822b7c542842cd3a77f2d92124c7c9260c244a67fd2e21bc11399ee20d3215490e99bee16320699529b452a258222dc11e0c04357f28b243e80f2c654144041c8fd5704508090e4fed2ca065fbc7426d0426045082c110a4cdc0938b8020440f0f41232a0596a755aa2280201073ee024f7d3dba334eaeedfe1a3bbbb291414534a7fb491c54cdf5e1764faab9f4c7b4025d3a2252ac8b4e80346321582874c738e108277670471945be58427658c2eb56cfd732921119dcda27428b06e2e02e9b23e8b99373a037ee4b07eb77fa9f099d491525c2cfd403c7a2ddb9fd1c1e5fe6604b7be149793b42cf38cd11d7d56f32b3387bdbc45d11c26771c0b90bd77da0d3b90a97667963bf66f86b815bbacc597d089bc95e43e9336f65b46b848b28811f741eac8fe49010be4ab7b4bdf7ee3a07330a3982eeb17f7b6b990cd83099b3227ecaf74700d20210721db97b30a284f64fb2d0309b3c15d2a98376692d948a412358062955c1158fb0dd268e2cef71a4440fd1270b8f6ad5d4206347fd4ffe867f5403dcb05b98362fdf812808a208aedbcd8d4e3dba2b58f7279d6c53f52a977c12cd68f9747fd0b66b5a030ebe2e82b8496506cd1fe4b88e32efba9507cd3566f88a345fba87087bbecbb84d667d265df84478badb53f651b946d9bb2ed4bdb531beadb9f49ec4b0903acd6f3389354e9b99b64f882c33a236a5fba0d2795b3dda5566a141153468bf476776ff9137de9371fb8fe5ffaeee97b5d284b383eb384c91d2a373c5e49bf93aff9953e8ebbe873a1745778e5ae6e08ee10def4b95286b27c23b2446589c70b64296d743c29634cb588703fd3b488702bccd6a7c02ad3ea4cea98f2cbc7ed3bad138955e58ed75aed97700bb9cb5f08f75d0f65afb84a69d13da607a804ad9556454c199a1100000000b314002030140e08c582d16030cb1349f13d14000c7da6487a561a8bd3244751983286184200210010000020325043b4018c0f58006069b7f5681341a15507ed5c4750d5fdc46fda86218da9d6d378c9a6ccd1530461e85b913471aa077bb1becb7a0f02d3a4a2425c0dec7311fde01ab3cc8756bf877d3f069020048d8fd86e581e47d6927c29ce8a491d400fe3e21d540213116c00b940e9628904b4256b74159b79d59a5c1445d044110bb4dc02d8af8801285f6162cf65c8d71e09dabc420c44389a4aaf313815ac8789d626128ef3126112c07892d0e13ed17123260508ddac8ff740c99918b0017a590ede49683688405c23942d06bd0006a8002a2c30f01515093fd6815bd97c0435ff4dc6c46dfcce71c529a12b5d4bc9e84280066ef719a34e097404bcaa8a94408b3586bb5953634f137de1494f7bd93af997655f34e3ee69c0e36dd9333a75e990e841ab09b1f109bbc42d040f4603ae998616d10977f8a2e38d6502b6143f842c50a5563515ee9a4f6933dd70c550927864719fc0010a4d519e556f691c250b4cabbefb31108fc54d0d43e6b17804e54a54cf81b361dc79a2cc8e0bc302e568e68aeeb49ee9803e72df69d48c93f96959f6ecf9656cba64a3542f4776398a61a5c615095620a5bfccf21dd3649b1a12d9c07f6506852a5e46781d0235b13b84be4e9437ab7f98e948944da2401824a263b7236022c274a35e6111517f100e3a2f72ff07882e87b02abd73483a30cb2528e62e1247ba340d822993a422457cabd863958bc1e91246ed9283c69fd75add5c0a5502052aadb6cacf286ea0b8a221473fdc6e5fef1903811091dd1810764e857adfd177c6a1aa9cb62de1d67306b544978816f98bb33616487c22b662cb0111b348aa686ec50fbb500b68436a90bcd04080ae3b1807211720ffa7a061575eb7bb70b0527eb96766d75ea102287ba8518e3eb3242f5176b84e55db20a58aeed861405ba9af5d2148144cef8a9bf1b32739192a05c002b0485527072fd4e7293eeadc26ca903b51d4c9e7f1496f5ae6457551ea945cfa58c848175818bace80c8dae4ddee487418d3e7111345587603b824354cf71652e3c513f6046770fe3776c7ad1a59f6f001ae2c76a3d4d7c3f9a0c0486de681500921c0e09ce456102ac2c3f9b080926a217808373e87fb762f60225b61bca67056e3558c7ecae79cc64ac13ca1cb103b3cde58e3d8184ec8927528491027f336e6a6f75bd3f2d64a0cb80ac0a54a18892b0a6a778903500681ec58c5002d5f00f6155140cb1088bd451c50191562771903a44c71a4908c9d82b08aafb450ffdac089189ba81cf9d624cca60b0f5f6b0abb6985c3cfdacadd641cf8ac5f583747ee455102161d0bc6697903b2574b33b322034a2234b3a200a2fcce46f69b4e54b3e51ae745b3a902fadaede5f7de08f804e7101b0a2b4bf503770fdf30b46b8b27df2f02cd4614509905087bf6e893569348de8ab3c8974be506f9c0f274904cd8e2c9771079067b2b1cbcac219a36af0882a9af72579a0b9b38a3ec0f4e078c94bdb9bda14498e473ae1d67b0a7bc8f4b5fe28b4b9b4e69c3bd346f3ec0dd3371191773c5c43504ef71363a6c56ae7bdffa2414ce6bc44884a209f848f395b3ddebe91068624cbb190276aac08d7884e2e74ae2388bc9c68135365ee680d4ddfcfff6be749004353717814a23f9e0d5ce0b80250e28e42e16db6b641ec5d18b0e62bf0f37d4da6e00d2d1586e8a51900cea04468e53e277edfe311ca240d8de062bcd89c04cf6c55a3672554fef75b7c1fc008eb8f6a358e354e1e829430967c22f4dbe058353c1884353ce24a15b4efa531385700f821b0cf091e653150a94a353fca16fdec6a9af31288dc84374d278397de82174410cf612a3e750b96f6f649836274c474e5a333108dd0d75b773746ddd002f067903e84a206fba65f9d8fef5858f3c714b3b5ceddbc9c445194d359cef9c859d1fda047da2371afa89bbbb653f6aff9a17296e01f45d960dd73fef30136a13ee49ef4310c0bbd93f934d5d7385d82ac03bfdfb3ffc888b2ac8270bb0bcab89502f47a145c7a914a2b1f92643ed8d7edb032bdaa997168128ab232a30ca182c5ba370110e9c14bf857bfaf7b4a895526f82e9567a9320a9b60b739635ca24a64540c02839b6f50b85254d4bfc7d8ed2d2afcbe991f527cd8d7d79fc42525bf60f2921bda49d3faa175a7853d748db82af76c9451ba5fecb20a7f952e8df1c7794bc6cace4d36e6df326579e228e5d702abd32ec93f5c7527fe21193d8aa25282c215fa54773bedd48f201904800efe9f951b263a25767671cca6c746762c6b3dfa3bf34a67e9a0d786fbf8fce28083f3783be7c2e1bf01ebd39ba410832dddcc47bd2d03ae467a92ab1f59dbd0faa2ad71ec27f76e70afc0936ed2dd389db80e06efd80a73f7383069e234eca4bce08ffde8ad254fd09855d36f8048aef1f57e3119d70d472aa6f96be7e286cc5dcb60911d6c2598a0ae3289eb77e32eefa9f8fae899251669be66a6601932cdacaf9702902706303a7468b8864624d63a4ac4d6e046b0041e08a5c8380a3faed02926ccccc9c0851dc7cdbc491635681c3f9776b7cd10f701a0c98f63e2b9797a9ccb80f7b7eacb8152ad2d77554afed3005034be47c35a7947c6c94cdc72dd0eb7824b9b7a4103756816bf1cbf33a90180e615f4b000b18368eb1bd323a1f0ea16cb88fb17577d4ffeda2701211c97b81c15ffe0503434c7b9c4ed60d66d518351a06e3da22ee37c1cc219dd67706fd29a5ad127454a883c77d36c75f44eed50c20cae63db1376603b9a416b54d18545a9f8e8627f7de53a61cf89642873c2069793cb93f44d0169ce530b1b722f87f28d8354b1b510bb35fa8ab0de074cfffa8e7e5e30afdb125f22a685ec36acee7bdc1718f49bb96efa2c856627d6819d754fd10acc0e0e86ceefe6251056dc271b5de4f49deba376e228c8c69456fc1bb28668e691a51f985e54b94d6281af5c80e17adb30632ddf035a4ba6db02900152b33713cd5874cc5c920c8ae734fbfbeb2ba7ec290b894d3999e1b3447250822f81dbc0a1ff8e471591f234a3b80e7e2725233077aef9a5129ace43ca62fd2a364ecea94640ea5c0bf84bb851fdbd032b53b3d343206ab100288c031ebf937a57d37855d0ea6953416573f84182e45c851ad0c3d71449cd14d72fa988f17738d2d828ae9a4ed973cd9c9635066818b213938407d56fedfb61ed023f0f22e69eaaf09b62f7e0b677cbe54d8d5693538c59daab93dcd705617e8319ad18a13b98f90f64e9042634a632bc2a86e1176dc5d0d9a43d9f371fe3b5efce1ab0374e4cdffabce56949952acceae19e2d863e2263ce19ddab93f04147256bfeec1e87d4374aa8f83a2ca74d6c9832252532a681c07f9cdf736a35fa225163a6d8fd1849fbe4afd156fd9988dde35c829c90ff9128b0fe4c593d059254e940705e53728995478b17d95c85c70647bee82c71b6612d40a6bdd9b52615d91e1be2978c21a126e293f710cbec5bcda0a248d66e2117fcf421b9109097f78ad7eaf44b3a81edb228a321cc72ac1597fc32976940fc19aab9920384f8db32280f3b0f2a27a62176658c74027f090bc922cf3d9b39c0aa31b3a3d8050043297ea0168dd95d46edb4cd815f3999b7e12bb4849b654b9df8da4bb7ad5bd03bd765fc167c425cff115169dced3700158c5dc5da7e120eb55ae9b1beb93adfdb908c98b133d581cf8037cfc913445fd7144fc2ebdd7cb0037c7e9b356854f6577aa352fda1960986218a7a746aa042cc7ca261cd9897f361cb047c331b0e213e78ddc55a2099ee48fedab931d8c789714c38877505499645f696e9132db7327822e1f763ab1bc51f3cb6076ad0c410d4d6b450e403133ee2a6df338ded6edd6d332aeaa02cd9df02e1f637eb67517d5bbd6026ce85affeb0f8dd8a39eb353a45af6551eef5d9b9117e0be6f840c7b840ff9bab7e72cf3d2956aa26c853cd8854dbf11c0d7643e95b118077ccff4700c4dde15cbbc40ef266e021f288295107af41e03d2df6a555017ceb1dcaca93de1eb93da7eb336450aa8d14c19bd3d0b1ca3b7cc51292ec58ebb0ab0969e763188b2d50cfa31199303549d45b1162c6abe58186db8778b7279b02031bb6d1c6785f1e61285d8b754f4db709204b6bf6e88e84ad15e13147ac707149d197010901882689ab4c11fa3f065e25ec8c3eb00b08656a98b49112570c8c5843cfccc63d0f7b61979dcdc8f1be2c14fe71bfa8e577b0154f87920cc7251d0d53f62834bfaf9e7ee3491e90e145a950ae4d63c1401916098f0eb8fc3c4e92f69fda6e630041c06bacf495596df6ce03c7e7c36cd18c7fe69f4c6882382638b6a705286ddfab1bb74f961d131896e0229a65bf41204733792a67e24a912cb1719b1e58c8d5185214b4da6644b4f31cf7e2606feb667c66bbdd518b48175d3d2c3d1aef8229bd91d8a0f00f17b08d712a6a2c5f996d6862310cc612444523fdd623311f07970284888d9a61cc697b87d72d8ca66c3162d5d023ba160252fbb571a108248dfa647d26f6c86fdcac1524e009539b6143c40f138aba2492a1f338790d869773ab175429ec243b8c28e4d1a71a103f9721ef0891737407cce1de33e62890793f8cf66bdfccddf132791bca21a1745a4caf4f30b67441fa8cd16c78e6e6c7ca8f088f5a4b73d8a39ac6164a9542b16142059a394ef8338915465a8bc19ee720a9f2fd0768939b076d073a161b7cf50679b4a3990c3e393a7d1f7c60d714f354e4fdf0eecb2964018d0eb490af9d28b65ae558e2895262168175cebc5116b7b3157f3399229dd239dfa15f78182f17e5e7b65e4d218e9bcdcc1f6e949229603a397010c8dbcde9835e62c90063d041491243d168e04e0636003fbca694f1ed7a6b0ba23410f604fb68194d54331570f0280a5205e472c96e86b81fadb030098c815d49512a952631eeb0eadb378b5f3aab21ce16bc62ffb05dafedddce6aa5aa003bb824a927427d7bdf9a119a73bd57a6551c721f3b6420d0ab8925e744909c5d204f3ed258e208be43c96675d0196cc9d326c33a2412866ba9b003edbf9625b11c0241503eee7180a076223ca36358dd184df8f8c93e52bbb55518b7fb02f95a96556588a89e02ee1469d54f40fb694e324b7f405f945eeb2143e3c040b4b1acb4119179ac415ce33993d9f9e5bda0408f7afd44d63abe145da0124172e792e2ab89fc614f69fe698546bea13b4634e9b02c28f3e1b40aee9614483794d55aaffe76ab9f9a131767c20ee4bfed08f54d742ffcf5e0fcf33ba51496ff992e4acd0400ab83ae5ada101b1cf75fe54c3c83fa7a0002602a2fa53401159f34b2aca8d74453bf6054350216402924a2c187bea80e5860e5bc5da1127a7190f78cbf2ad6a083e8e903a873fbb5a85bad2d2d09398a40b34a929a95643d69c01904dfad1daf45b05711fd6a321a92edd8ef0cb1d391ec155ef363ae7ae929dae22682bb9b8885c8dbc3a550176753add7af7817860534f50824b35a6b7bae74cdf3a7a0bddc2e21722c709fb1d860595c7ec874103fb6975632d6b92451c52359fc14e2cf5008cfba4de4b9a81b9762564c896f71380ec7f328b00b133af8b694b1158025e12cac7866086eb3ea78cc21dc2bddbc11f84e76c029768feb27947664d0b0e8f6e717449e5b4b9b0ca11590e30d2923cc9a3e6dce7d5bd5f5fa9ab4d7ef8cab576685df8be9912be5b7048026b1fa132125197e988ba60dfb26a5efc4741ef4c84121fac8184dd335c3e72af182118d915f2e583ec4181c8e79ce70635f6cbdc9c150331041564f4bd2152d8fb1bf52fb06a5b0109dae8bdc28b49656aab8ffac714503e4563a25d72f153958a969361362f56d8c0b20ecfd88f825e093132d6019b851c23ec0087bd31fac7d58311ba041be71550c76488b67991c0f7d2cd02920a1a2ea43b25a9a7c33b2a67984480088bbbfb661a1a22be40ea8278bac04ad70c3ce6777e840eff83dbbcb9bd4268892bb4f403fb6f43283e19190ff911eb31086d388d6b9d5f7a0e36e906e891f9eb7c46b9d19a26d8d8b04541cc0adc0f85714432b64118c36074f51429f7709c25973f65f7b6dde65abe33d331b2dbfab471132c07280c6b395803afefe95b79c8acb2069295219bd16056a978a1b4056aa6ecfebee43fb99a8724daca8a34730e51b3ae40acc05d13d62b3e564f31779cd8114ff67ef880f90265a4037196cb4ea458c3c4dedaac4505bbc20007fa2c0d58526390032f21a8ef647ab2cee8e053cf1ed4a08ea313c93804c415799e8777e874deddb8feadd14fe8e2642ca0a558bb81b70dc9c53355381459d046e16886079671dc06b22113ed92329103308401e60415c0463b13e09479aa947de329c7a0482c26147b4b44c7b1fd535308269a505706e5e7c34001ba2ec7cc5a76012021868e53cfc53555fc54ae6bd12e3ccada661531fce74e22d6730f72960dfe6a2549c9b99852a3a3e0bc12055a7986016591bded7153c43df16fb48fb74162be2f43a052514e74e88a4ca788bd501d35f7075f3ad8742d7495db69404cb7ae45b75485b4e6f2a6223ef270ff703d2267929835b388ffb07a628e1fdcad5dc3bf536cbbd21407e4bf38c467f730609c29a2325b6bfedc715b6e479224870e3e0cc9f7a6667217b0ca3b350eb49f3ec7c2e0442f9f4b90248b1a2e99638e4f3d964456b8cc2439793d94740111c96dda5eefaed101b7f6a2b1a6b214915da55e5d66e2622545f5832740fa70621704e0ee9c3c570683d02666c2ab2f7f720582a509c0e47755033f2195506a240101c1a0b6e4de9ade24b80e46bb2bb4f15630595c22d73c89905cbc6c26bc3246550112fb95877492627b330be1517b8e9d50e6bbe92968b5811f3268f65f513108382550978b448cf603554b0877c0d44f93469ef043e84c422c1228043ec1cb1a8584e395f438c522576c8898e15c08f139c5e0a294a888b84e7ce3ac5999869f650637b1472b90461ad7a974b9d6edae1ab4b91c9a65e6278ad397fb3e39743cc4777d5531bd9355505cec77121028f9a5cf9359e550d6ae7ae608f0548bc2d2b1868e16c55299d440cef6dde2374bbf0ba46e7d04ee29becf7b723090bbd29d50c85bb8c7652a4af0525ee750bcf5803bd65f393e75d4b47d80e3d3e6f2346f4ab4a517504e7db3a5db3f513bfdbd1871852667d075e49228b374023d4b4f13c0164eb8053dcb180aefa42b6c727a9c0367b4afe049a1b3062ae984ae226734e88b301bb6213ea7b0587094bf835be56f14d5be81e7491edc12b8c72ac99319ff151dca3c321c4b41de748e244dc7dacf35450d0c1b41116c6466ad44a85680592bd9ee5a4f654f6e4c445a400844b8c2803a7f7c609a7d8ae9dbd2a3db50a71b647eb35992443315f2951b1885bae769ed2819e660aa22218f16b5cc89b62e629d6d9d7fb2afd68d1068e8ecfa7c8388b1903e2a50c5207e8d3dbcb0f9bd073f189ea888fb2b8de2a41460e5c2338220700e45a4dfbb602723673c0133aeb65cc8c48d07d84a8a1f2bf21396a146c4c8c0a3063cd24d8ec12363d0202f1e4b0f0da3f69c2a1d46ed8e035752e87559986e00f63c377e15ef24d2df6920f96238df4363f6ae6b86bdccaecae783791f787d9e08d36dd3dd182fcc8e1641779f2b6e4ad7fe89b60c01afb24ce95a9470111b87d5e8ee18c106b2024bc489bbb028645c6fb23665d044b092610bfcfbb354dc08c09100fa238ad3d9640facea5e51fcedb5ffb0f0f1ff882ebbd9c8c117de1a68a96c663e1ed5a18db5d152b2eddc70a8e1eb1669cbadf436250b364e0736db8fe9d1df80a2c7bc04322c6da978dd4d7ae55daf49e38dedf3f842936121fa32f8eec3b30a998da3ee3973db00aa607ea669504218e19b94f012ea7b690cd87398204bb93b42d3e7b0d6261ba9b0630ba920fdebf71d6f5636ccd397c614836c7c66a894a872dbf22002cc99bf184a5d0add5beced8ac15eab7676916acd84f597f3941c7dc0b89ec2bece60d9de91c5c279f015673df0be264ca6a4f775ddf3e5c65fa5e232dd74edd791ad7b4ae531d9f3986f4942bd5c5724994c7cca2e583b89598f4e947144fc7fcce9447ab29abd2d8ded946238dfa1a4bf336201d0f3df3464086364b4fa0686e3585a10881f55fcb84b5840cba413b16c006c69b1fa44403c1d6854ebbc0570b81a0b424504229c5073c6e6df81b5aad49815d4417ee91994784e3a78b044f97cccc0d8aad2d265a63161abaac2092861fc0d366fabff3d9337d3b589ae3c6f36471d6736127a61acc4d40268bf8bcbe150ccbcb6c55d433ff4a29c562a635675f353dec999dcada8acfc9f0fb4de2070e8bf28aba3bbf8ecec04864fe487fe7c65f820f595bd9e27bc3a4407eb45fd04fe6e521447dbfc29babf084575005c753bda17af366f3619fd975bd0b4cb478aed973c0ac7f55fbd39b9fa870d4924a0943fb97aeb41b0bfdf7399c9fbbaaf1a011c0f90b8efca97f01230e7da5c8076b7f561c7f0eefa3b1fb96da2786be56a028cfa9ab8398ff1f40d2e947cc32402a5f479e775351ef0b450e6d48321e61945893ce090c60807586c9eed9d824289f2843fc97255cbba04e4e6eaac52eb26efa432c45ed96218b83a1e04fde382beee80862482b2a633fe50a0aec9733c0dc0fdf038a743f1a1531ed13c080fe49738d169ab8d4c484e8e68c53854e8976358eefdd8dcc1d9c270d24a9203a003958b55bd474734c8eabcc553c78331160501539f4915c4e75d80bd45a2fd4911b3041b1182bb86a42d8507055773a7d7f87a9b3e48038fb875c7b5cfdc76120c9ce522ec2abec27630b7cfd2f55ffd0eb57270e3933ce958566edb1d35ae41708a16c1420b30451e44373a1af7c1dad9004545f474781dbefc6d214a72fe058d80588b6b97ac7c2165f31802a0a98fcd6328592b728551b080414cead34325b68fe7e0205f2a11a404121c3f6b76b988d83b49fd0b1b3658ed5e4f68699d8764cd43ec2184ff61a7aa770b165bb38ac439f01cd58716415e4e74a7a3bc983b71b493ee2229c6eb8f99897881eef693b7333647b4ab918a42660e5c67eb622b81e332275896039a7cd8c0b6a4cb6dc7f26c1239d9e8f2f0ed3425acddca7d812bfb11504c34e92a3c3d9b5662048a348721b023a71f3341db92b7982a8fca00ff96bce32f282693524c7292898a4a0e3384aee1396512eede26784cd3b6fc241d55033cc5829e0b6422c06db4b3c92ccbe706a074443a587c9daf6ad06e5fa9c8bb6ef8f8e59d3a5e2c9e3f6ecaaddf09f284d5a21ba2cb7bad612b7c3681cc9249fbe086c8c5c3aa3db7691043e2f5a2ca0be2520f09dcd941f82bda99fbc6bc4dec8185da93c4d2989af2ffcf60122269e59ec05ddb2ad4b3b7e69ebe4513fb3961ed199861ee3372ee17972fa257b4267b68bf27aa90d5727799c81d16c94c45ce6f72bb62db9e3433788921a49dff5095f7b4486847987a6ae67dab03bc356f230aa0d39dcf3a51433a701a324ed7a72c9cdf39c8f6bb54cbb2d82a33379bc0546d12b65d8a917eaf674d4d96f4934d69a96e77c59a7d8aa0f18d43a3975318e79174f57d2cc7fecc51de5a182852f09d46087c279875bf2c60da33f43e3ce6a47f0b68be8f38071711f9445cd37af5092dea466191f0e83e43e66905b7f0a04930e02cbe26a8ab04ab388050933275c1c53c4d1e12d0c52b842e9c4baea7e4fb7f718da01217136c9784f0695980537820d5b29c07f207173c8f3a17230a3b21708a4e08f166eef94b2770f01e686abc8a2662065869a0fb7bc077ff52be60aa38cb78380040d4e25ec7261316564c8a30f85076c50ff8630bdb9e07b9df694a268ce1cbb6d5d4ff423ba3ca57179f002716a7a3ba3b4d0f9afa3259ab40958118c99db4b87bc99145bd56594be54d7a6e2b14a831f26377e125614f0724ee42284dbca4ba891b3c680333323a311d0e7210714820321839e58a90daf00ad60937d8325741c44eb96827f3adc5ddcb806976aee1919946909f3ec005aa86d59b133918b6261eb1a4efa8fd03ce1283b61967eda2bea5be072e8a137a472b54e9f68f8881b1f57fde67488a6a45aad44e375fb9a90b5dc58a6ca02e7b3768b0b9ad819411152b6de189451e76528676fd2b152b70bce756b8270d313011159fd12f907bdef1cef2212c3a114c3421f659c2b0e27b8b1dc1306508cf6d4d5bd43ff74f8b6a2cba95d0ad1f3650ac059538f4d078c7a7776ada0f75347354660831c600fdd89d0261784754b7dc472af8fb1280227247b0c58f030f5c452cebab26f0b31dc7a09f3326538a645a22f466644643f08c1a6c6d9439e2bf0e496480270707fd9817548e7f15625ffe2ffd4370488ad6665d1cd3b55f0ea08175608f2a4c3118ec1cdb7980e4fc85315d49b783d25437f911df8b948724054d377a0a549d68bb6a3d28a42cc3b30bb1ad2c77294e020272275107c197b5e3fce910283afa3097de480b8450d744b24206882c7ed3b774d9063c174becb286f7a9cb567ebc236161efd8985235d34ae25949c88b7a6540eff1acc3061b6426793c2d2d9fe42a0d2116257039e325462e5a12508bd7ecdefc0ff6e32a450ea45adf96347dd610609acc9d09f61a4ac21db027ddb48ecc44ba4b4b306e6e03a4074682352ffe93d12735aadc3b014b7ab7a345cc529061c5d326a97f55318631202b064821e20faca88467b1a0b9b54bc1fb435b6d2d31b3ab54dd4cf7854948434fbeea2374bdcd37d8552e61f3ff8888b7c53996eb5e84513a8cabd9b34024edfc79c8f99e52a402a1d8912de38318b9ad1eb1552c8c95ba9689064ec1c714a1953d954ab0f18c31b18d416ac616b8682b5e0c98cf14ba64b297d087adf74236ff29bef87ce0b1d0432a3c81c4e685e2df7e4c46639954723abb3fb488c2aac78c581fbe48f2c32ebd6783e72fac1470bf0bc3cce41bb0b133925ca5175ea9baf8d6b64ca1e419838d475a246b4d0acc07c1fc51326a206e26090ea51b8a04b31f18809b2b46888d5a6b3b6066d32ad837b88f248df179a6c3808a230cf28822a911c11b6d2ddc9134ddd551ee08fb3a43181cc1470dd5582c7070e52bd8cd8425fe7480fc901ba76ef6730448fe0cd824ca0a74efad0f8d4420c9101289cdb48a246ee88f9d9df14a3e030a4330463bca90f1b6336f17135dd50cfeb6e9cd65a4dd608b6de7d7859abff6c5c63487fd3151744acf50ab1b72eba2ac65f22872548476c3b6c128269824c6032162d0ae46eabf087ba5290b383a7bb72037b54d347130634aa625dd6648870cc0585a25dd8a0167e89234c95923220c5e9411135e24c2e39a9991eb6e0165d914290af9210781f8bc133320c4d9abe26fa491f9243beb5b04b29b3f81ac1a7142a982628c8b570a1858a9f80978c3a52946c37b4d9be800d7fcd185e3ce59dafa5ff027b3d9f6428123f390b8ec77f9b1f0bae1c0419b1a8f0c032f250624dbba61408db092381630e4a043b4a47aed704fce3a59c74c1a33822a3c890a41b8a6c2cdf6a9663c545a2473344d90f5025af71b5cd801cd9726276a3e5da7909ae77695f8d18412180a40c98b0e3098766b7a582a577494c33d3734e156acccd9f06950755f06468b36136b1e13925f1d074b545149aac9b25ef125d2f70cf47f81e733c4fdcde218d08054aeecb264dde3f1657be2d6bab3ceb3376cfc9b98269dd3e01404bc1e907011f8890990f8eb5ca1386b79097aec48fe370525d2c6aa6b4bf3beea90ff2cdc54f10cdd566c082e93a2c7c19cc5534a4fdcde47382f6255c84ecb138a3234083a5d7830c8cf5c54248e3fc729fc3e84f0f3244df494e2f40adea8e2da5cebe670ec98561a07c93175a4fe924d360f4edd5b711582ca447403db33b7f089c9e7e177c47680e262a6de1f8aa26c804d3821ff44110878894173dbde7517056cf58711547b19cbffad612d85eab1c5e0a98b68189b6f1f8704a1c76cb0220a7bfba17120b98f517108381b40aa592ecd436d5233b653c8a03de51a00f7cb164dab42009a3c4ac35030376d4bb35027be95637f9f66b135f49029695966c6c3243fbefb819fb4d5ac8903e76c26ce19e89525774790615216f33f38fb56cc6b81f1c8f882c8332b48996d78d02ea5d4d5c4a3487ea7e711845a50aef0c86c410d932b985fde669f918bdccca572aaf6bfbcfadd6d29814e071a450eff99684d2bd3a6d4d756a94792c3bf4f3b4f41c5caf4f50aa151f26bf344cb14ba69b29ded698f9f4410dacc6ac7e25775d835c0b0d2e07c7528ce199bf224af630407c76857288ecaf714cac37197aea74e9a52d891c489d148cc39d0750b020af9b515f291dede25d356870b3484c7e5b2076a25614949784cb64f27f0766280ad76bce4da0816225642125859eaad811e563009a50e009276900b689dd450fdd5fa9171a080e2864894ead60ba9be13f4586182bc29485cc23fd13dcf0bd8f4e5d5541b6b479c1ef4c34cf32ae6f2cb10e97bd7d1b1154fe2827cc95540356fe7c57e1d88e4f632ba49ce4aa5bc29276f6eb638c0c04d07cf113717b1445dc8917f7471f1b0e4e41a7c97e26a3e2784a2ded6bd9bc705510afbdfc36cc60e74f8b3ea5271b4fdf34c9dfd6c62130feebec238a8a3b43c858a87353d2d1d9e58d271db0666f492530a72afbf64c82046182e39c7e8f3a2954227a1f5398ef79d46e23e721c6c1d85b73e72cbdd5386b37b1c0be0e71b942d91701c8b1bc2bcf2bc24b17ebd8eb883fea163e5d4c8baa4a45ebf3cf1b767b17816ef4b11e147b42173d9bf96a28ca9026d48f756df1f1b3296cc4291fd4fbc9738fa47214dc1a1fc2d887401f0031fc700491196c03f3242c21e108dabef433c2840113fda35a25ab347790345ddc996f481278c1ce700c7c28551e6bbba415cdcc23411a93a46e7c02f7ebe5eca29d623529b0cc0196a769f4f4c91299815dc47a6f13b62122cc9c45893a1e8f664f7af0291b5446ce2c72c92bf097272eba39ea976f06bc7ac1a2e9d927bd898c2208264f2aae4b458b98e547e86d6e45d7420716c87db722685d6c9e974cab0b38f983dcbd4765652d57ac85f51335c6469c284fc48322d793052be8fe580d093a07352a164128f291be0e677ef212cd3f847cedf2834f619665fed38d3098d5d522c88691cce5a495742db41378b5b229a0d79eb8fee76488cee2d47bb0ffb9c672c5b18dd9394c7b6a40bb82eec61cbc0b01fdb4a21c99ff8b1a8d278e05b6ffccd2d49cb31092c88daf85e7877701b27668211a72e1f0c2218e366bf76fb77ce2205c6ad410707dab2edc604d76cf7cf988c37ad2e268dff4ca0af24ef3ff934db86932d7b81de1402803cac05a19427d3fbad7309bb195deceb36f3852f5578f06901434773e3710b26cf10e3554dc2d1fed28d5b35da988171364c6b9ae03ff3346342b58daaa02fca85075233d1ece0a33832585343421029a7dafa7cd09914116852d6bc3b3a3b6a7258445859e0b3955ec5c245309ebd0a5a05e7fc56383132e3cec162c4331e411b81df0d4c616f94e90c8cd946c8c40edf1ab67f8b4095911407c5973e16254dc24d3f80e774570ed30f9266c2494f1c37ff0c0bd05c05e0929412c3e063060b08c719b3c78a0a8a87b4a4a33edc023753a091d286b8651fdc0d9f65de7f00c37b92e1f18a3d55e0a63a624d859d0a9298956f3dca8104d789cdbd0c67fce256b4193795c848c552b5228aa61ca44ead4afccd2005252ae28d2da8981618b48a495cdc4e57f1d8d822e97e2cf7333bf673bbc697b2bf7996dde830aac5300f343dde4bc2634ae12aa1285cdd5ca5cbc7adcb3a6e3a950476eae0acd053ed405b5b19aee99810d55e769e0e538185d4bf10582bab7b6715ed32cb4a3985bb4e21c0e1b15e3ffe57cfd4785d3eada310061efc06fc0b212ce26ef931bb81eccf08b3d2e92aee9ecf8d174ed15c3dc7fbcd11609f0ca8d0a0a82c301f612fb22f5894ac20688a4ed1cc00bd3e93319d3bbe4b4dd0f018533a1dba06c1306d4e16d463d7a0757cd1bff2614641f1ece28a0ce2ec9b8f3f88cb5feba607e519dcdfc84e0fe38ecd9d585c7c19f2bf3b1de79fc4363102884f6169994eca8d671eb8359e0a206449f0c21467287d2b6855f466d96a25991f095008f99ecf3b79fbf682cd360677e76bfb6a193088eac40b55ec7ed10d418bcdf74eb41e15198f0bc4a6adaad0ccf06ad9bcb5c8e4625daf3d2e5f5dcf51c020da324cb0c6c9fc13be0d14844f38da99408660875118a996cc2e14de330c41bf5e9cc7310f9e13e5d0d40690e79edf7e4b0ba223619bfcd7beeb505255ba33a6fef3c80098d82c109f2aaf97f5c55d1a4378e6453311c0918114829d545d464be3b419ee3611462e6997793102337784663cfe948740cf4aad28c2b408a8956ae64a1e992450ed931c6e7963ef32d22ea906d326e70c07912f617b454f66944538a3e251817278c44961910430109a0dac2ebc1a806e151d3d157016aa490bdc76cd5bf383fe74fcefd15941bb0d30b29c5a715a338a230dcc4714ceb8973399e871eaeb69b05e97a2f95e64b9a313b65b3873793130bc58548e80ca8e31300afdbfce4483fddd6e45e4c6c670ba11981fd9a2215ae01436fbecd4b6367e4da26a820c33006171ee4d86600eca1516ee3e14ee9b5e6f15a802aaedcd7ae6523dedaf6224e6234d9095e3ea914dd93910e672994de12d279149ca83ffb67df67502ac723d9544d68e72d50f69bf7911b4d5633738e2f697f980f02472ac32a37814910c628cbb294ffbe1d64fdd7da7ace79f69753c8709934aa2809cf0f2d20442ff0a3f3e2483f47f4d65ec5d054bd03dfa2e8b40c8b867f645e6df586344f5ddeea81d287ee54ee7d8f6ce51a315598ba53c7cd667594faea585c548bd8e2e7bb009577ee5ae81dd03d03eacba373b9c1cd529100760f601db3d70c16e64f3e5e6e928f839e487b3089723fea3e65881e312346b120259c47394b179f74449d53239c33ecd454518bbaac4b0495640584d77545c5f478c3609db8837340248b6cd95aa238e1e27399f56c0ce0755793aaf019d943c876413233d017858e544bfbaa9e913f8bb2232d1c8fbc01903c282aacedc4ea787d82ab016266a11409432351a1d3820166325e2085fba8f5e06eef8125590648ad138fd06b0fa0df58a2a636ee62071a39d4591c452cf5483c423649a4ca80ccafb3998409da56efb9f9e6c89774f4d41e742f4344729f304ad4a3ee9cf11dc655b543d56715628a37bdebe325b6d857521a913701c1b00a56fde2d0c477eb280d3bcf7b940e718eebacf32de8b637b5f97d9320d47186d9cf49ce91c574442ba86d273d07ee60b4a2d8b682d351f721269565392035b878bc91f4eb058dfb577ed1c09986d5fbd136f255b74e7f5b4bd78ae475b6a735a4a75fa7ab654393156562630f9f5df05ced26ee208f5f02a2b3e31bbee73c99a1a93f1fe93047a8974e08453736873c5c61ba879334a2de32f7a1cbbee14f9826e4920bb797ac7d67962df72938cb25960e232f3293d96c14fd0e123d158da6bceac37d104697f41932f81396226f191f919f6f6997d7fd73f60ad5ae60498cc6d48e840046de04fe5173885c1e1132b5b40145a1aa523ae1431768315c4e754b5146537b1f031957a0ab409293118d4fdd424ee3107b6897fbcda0ea1554059834848cef503ea23df8fd422ab062f10f14b4d004c6843bdfc98dc0bbfb92398ace29a3101cc1deac54770ba89a95ce32f1abf973950c4d3b6dbafe699cc9b008218517f8980bf482fc19b7199089ed89678969a9f532e50ab3460cd7ff8c945b8f960bac6098ca3b4e44e0c7d94b3571c869189522806f430e0c31bc558e6eb0bf1924ac6e4be75b8dead6849fa7d87377cfda02686f930f67cb400a2d92a19fc3d1d74a7987d79afec004dce023256601dcf389a31639a727cbeb43d47f2471f40c415d27af27077ec47cf6f0097133eb8db9ab2895ea51bc3d5292fb66b828eba38968262a18acdba2ded3f0a29a38daa603f4ae4158f19c5854a69c030e0f8d4f4313f81498dfa30e545d815ddb7f5b50af96e339c8ce0425da997a8cd6b7e5bb5caa3df8947c582f2c3d2b753f037bd48784a5465057b1e3bfcac3b3f2e264e3cada2f82f9b31c5020482e4bdf5f96ea23cc3012b15297bb37fce57db873e540d172b6d2427e24f30dbcbba8dffa6bd500bb5e8f681fff226e9ad43eb9612fb6b71ddb2abca31286d9aacda5f4f337f57c9704566da969b9ab1d4308788b1065528e6926465b364a69476dd861caf517080317b61010f4d07d96e748c1d17bb174ef4f660725743e8f913a64ab1921ba980d5f65e630ee985a6c71aae344b12bf8498d93131df11cbc0d0f4fb3adf9841d92a1df52b67c9b27349f3fab3ddae85988507781543bb653c99506090585d647a1cd9374050e1262e9536cdc8247b79551e21a30bad46af83904fa11b3db065abecaaeb45064a586e576bd000f0a3bd8095d92676634a7dc3790bc8d57160a96ebf64831795e12c7655c62edffa4506e4c121e5e7787bf4460f7e7e3d56173f699ede9886265cafa7afb3c41b6a2b78ed1bef983780aee87e6b95295eab58c9cb113aa86a507a234faba7405397971cd912964539cfac31c19519de2f3e704c3ee652c24f51f1e1a9c6146c2b115cefac5a8156ac20c34380562b84369a34990e5ebcdc2394d82dbdd139bf4cb3146fac34faf0ce2befa7b6a50417af8763e0eb6b223154acb23c02a018d7182a5b2448f062c2114fe9b69311f57aa78b2485fd8f8067bb3a4d5de4254a3d2145c77b5b0d67dc58d22d6d7560c6c44120f14b355a951805b22927f20c3ef69b7e9660f4de9bba747e3a79eb3839e2c0252cda83edeac07d99bfb2b587ecb27ca663378736aace4afbc90edde5f90c0a29b530ecb3a353cdba472b2c42d5412f90edf7fbe31edc0d45dfb41e91a563ee7ef60284d8159386d7014c9239c6bddc7daea2c8290a16f809880780348e9bf495ce1fabd1e505762984029a4cc1a567905ecaaac00e1a1fe15cf19c82ad1cf43ef58114150b3e6dde4b2ca8f341cc968ff1b0ae998d03451ba5a2d7f480563c18edd134458488e4ac888b82d784e18de8a8729d2574492d887404ebcfbc7274935092687771ac279e15db64ea09e8bf4bbf3106ea2117b9549f2753b885b42a061cf3aed4b030ae5091dbc99ddb4a4019cedb6cf875ce4ba72fd45742c5aab41270be858eb6864fd2c1b452f6e31c654607b428d0e43d4087839735649d82d2b428eb93471965acddd1d403aa631dfcfb90895d7d6943f393b0282e5a41246d011a4f1b938a1a12fa945d88493d0a3fd4ef7cbbd63a9ed05e54889d056df592b9d8fec2f73bac5f96a26f1bf3a28413260244dd7832d04c94d6b54266edf21c8961102965e31c19a09cd236d7f023d8a6da2612687ce4135613c3611d60612289ddd4a9361676781201a9dcf86173f5ca0f37a081b6ff292269b319359fc02aa4b2b9dd276ac4a32f95a254d226cdadbbf1ef7750f49803f186946108c90215b431131bb29c34d2abdd5bd06bf12d97152a295d00dbcfcd07d0f881958b15787200701574605850ffd505b6d5b09b1e68fcb8d25c3eb1b14431546b58190079dc0f41002cdfc75cf0f3f9ab30535515efc93bf47b20a50cf7fabb19b3031e7b377fbc15b056ba293b302a427a5620ed91f971dcfe1b537549131103813c4f8d83a45cd504e8d27538bc29d938ff9712f7cf38a5431e4a2cbbf1bd3427b686355ddb5bbd2044857632fcf50ff2d4b4649ab0f1037cd01b396beb786fb7af8ed3e9ed458eb96f5a4257d842a6ea54d7156e77c9f418e1e4fd9f43d48d2d70fe288a0e010f4d8bca9615302fac56c4926085ea5a460105b5b4bcefcbda9787f8127022d053c240ac657d03c424dde90c1fec2e7fbaf682f7f21597ba18357363fe3b25e9a460321980a6c980bb7670c332e2bbc49366251ff64bfbf15c80c220a1a1d9e239092ead4067eaba84497c4fe1eb7c20d66e803a271afd25afdb86bcfe3bfd5dee7f0cb7133816c5ed19aa6398472f496d450996021a6bfd814f0c4933a9dc30f3c835360557f4f815ed2f7ed03354918d6a89d44b3bdf958870dfa94ca920e2d4b547d52460a8583392961b3579b04f72a5da13d6b7a9605b78d7e53cf1830e21dcf9883eb4a41f7a09ee0120c9bb8bd43e2d0d6e0be2d567fcb35c484f2ff0c360d1baba6d2d28e664145f7a308ba9e516ef54dc76d47296745968f48fc1d7ac932da43058b1aca518092412ab84892648db03b0d1f1d36de362cffafbdebffa79056b6466ac00c1e0e0dbe3cde4a6515f39c969792142204d0a703af2b05442e07b88966ba023abfdc2fd0d64ba7ea943dcf37f8471b9ab0fed0816efbd2f77b321e4e4f4ea43193ef9d7264880869bef1786f58f52d17d80e3737ef1bda9a19f9c0e204589a7efb796ee0d0b8e6b0d1cf6dcbffaac4fe49c8f80337e82236760e580d0aa88c577fa589e50d521135edfdcf60627b372c4b573a5075aaf8ddf5c1bc82d5c4a31321be90a07a3b0a55eba71a77cdfdb5fa80e52544172138bf2ee1e5a2e7e79552780eb965f683347558d8882aca3ae15cb255c04495787cef7c23f0a8f7b43c1ba1d8ede6ba5df21d2efb3cf42772c7222b0a74522521d2eba805e6aaf5ac6bed2972cb7dadbe8dd05a57664d58866f2ca513d5ca5a328874cb5636ddd7980b5f21e3ea7fe395d1a3a1cba00802dee74ef70709c6deb2073d76cf76f3200837947831a644396c2234f46869586699c17c87a98a45d62e9a59bda417b82e67764e34af509cb8a9cd221acb8777a3dc13098c564ef33a3026711e819fb4b3493a0a134ad615513da2e966463b1df4e2bbe6a1cd3955b32be88a58347d87689609a6aad00d6e4368bb7f59fd4c610ca8047e41fb686b9810ad5e4efd0a24b48f63a0089d7b3389cdf0f3b9b2c3041d8704ca46fab2edee6fde20263d668683d0927bd1205626c27ae43c55626206d2d44277a7d55f5b48ab5c4271ae9479dd8e9ca5fdb2d215f66253ba8d9582bded8c4c6dbf222c9ec1a7ecf50472c12e89c22d8ac23ecad805f552178997fcfd671630cb2034a903b4e972a777255dbb6a9101912596180e1aab64dc07809f9952af5062986212dced7877364dad1cfb29a67f94756cfb2ac898cd072c67771311a974304b8d8cad5765d50d74d3090b005bd16c4a0028832b8885cec1c28f2eddc946eb7b69e4027bfbe0b821081ae325bb571bb083488f6016250de3be2904a9e8cb0a606c27ffa366ad93df3c329bb60fb95ed0162bdbc3368aa469e058600318727900b0121bb9d3d5a8ccf6838f0d102bff16b4cd0c1fb49423b13732e9db6b51e3c42eb39b4eeb19ec35765646f8acd252d703202c08bc02e3590fae9af79fbc029375a8ddb73e262794e6ec197ab0ccf24281f687f170133d68799472def59751d958b2661daeaf4003cd485062ba9646aad2bbe4b58fd294526f4be95fe8466dc6b8f0af9d6e88834fb7842093bdebe9c4cf47f01096132602ebeb82b49d2259f10c42b2fae62f1b5e96aa6b56fae5b2e8e5c91cc2c6c304240e1f4337091a4522018347555713148bc17194f7824e597984279af901eea8bd0154e20f0058f5f112049d29ff8daa305ae92b0298e6cbab6120dc0bff790d30f197cb383356dc3d02c38873a809d17bcac46b5acd5dde402e6a0889cf3ff78030f0711c1fbd78d0576a01ec1d3bcdca6611eac3031542b7eb5ff6829fca85e4325ff9aad19270fc1f9582fc0bbb713f7bc6b3bb6ce7394158f550a245680b37330d6be4766bc1632d0f272ceaea227b021108085acee18eb49a911ff5261acd4814255e5e688d7e51e470996eaa85f146c60d2ab4d0abb9ecfb58e79e8bcf1d9c9b3e05c10b93b632e9c6b53740b0426c3a44de6002060b54de65d86940294c33b96910dba089fadac1b55002d7fc980907246f76353ee2e74e3f69dea6756addda0a807495c57d46da15bce2d23cb82c02dfd24fab0dcc59ac8769b7edc1d3a9a6ef2e8b007631e1853523061626e0daa78cecf0438988fc35ab06e1ec0ee97ea2fad185dabd6302ae0795a862fcd44f01380fe18964cb6093faf16745267db806ffe234ed82edf4094ad551eeda10c8bf1bdee80076223f4175428b9a4250546b2c2591679bcc25ecb2504539c9811b33ccd0cb0140ec9c3c7fa72060304b0e7d606fa49be9bcc39021167452e3f22cb5c2d0f368d4bea976083400812e4fc0e3a2277a27167a2ea885edd107a5c2a50f1852542d68183d91aa23291421f5a5620399df757b8cd4c0af98a7b459b9d9d593f884d9fc0cb55179ba9282992cac43e6e3821fa4a82d718518a94979ec5a627db6a6870da25da330901c1b88af7578879ea57426e71091b9614b55ce2c8df5ce126de5503ff7ec64c76bf2828a8c340a6c465daa863c719a0f6df289b7a807d0c767c99b84f85818c5913ee23f13da00834f8958b904e77254dd45936529f8890681813c8b0252e2392750acd07aabec90205eb6a46b0aa83c90023083066271c2c512e8fe04a8941002a8a6c2c0c05fd2c35d20650308d2f4e3ab3e8a3162cf4e810ea77aa2c256e075c1e65f0ad37e7c8445428104ba1fc0dd6fcef5c240a3ef2b1795bb70d9a407baa8539767fcbb95253c0ad6e95a30d73ccd752ace0413dcf5e25ffe6789c8f0d8037315f1f8aff25299ded5b4804d097d21378ac88543fa20e6f209cab9db2d3b2eb46163d65c4a366b81fc58b24b40eefc59825a351ea546e2b11aa3af35698ea05cc1134cdadd118db7de148ef88d21d87a659efcf2c8231af51f04463ed34595895420d034bcae25deeddce40ea7b2ec478c35b8dcedd5c2ad99857506a3a19437c84f6a1c4cd604e99c83de14bbaa31f56f4b9cc5b7b2a712520aff06d72388ae38a57ae0cccf6644604b0fc476afc30f159fca169580af7a1bc702288b23693588fd7a04c676bbc14e9a082d941d9edefc81940ce28c9c4f24389c7a348bb9d5a2ecb5c838d2492dc19c87d11928b9261ed35009611b3258c8ddcd1cbeaa4c52e41f3543e5a3758c91de8ecb3598d2f0fe5a9357d6e0a89ae0fd7699cc42d274fca3051154ae516f845c58b130543e883a1e79d11a2b24a228c2e461ce4a7a59c8f0e14e9b33ffec6b787793f3b58552a5cdc6e3f73e43734df340fa94e5fb244d109767bead51887e3531380f464f24a134b8e9c8e9959a4acbd1ede384c3ac773190759b4b689c23967b4aec329ae498af8f1a1dfafac8b1e9c8ce84d02e163025a6f42cd152a5eea37e56814c7536175448072f36508dccf4bcafb84e7ad91e4156d36b92972efb6dfe65ae3a8c8241b425734e21b987130c4b130f01e0763de38f5aa4ab465b002f4f1eb3445397df7e7eba40f5633c0ffab75e56c40e4501037d066260e62b880789cb52aaaa029556790e16a89c1b37eaa70e02de77fd7079cb03fb9477dc1a1623785895777b93966037208c39d8c20808f042dc8de218e2d0655a64fba71b44082ed7d5822152d459ce148eac8522dbdce1938da9381c17ada130edd7ef4bee10584c89f1aec3df9e373aa4b81c44736f6132a995b2e8ec1d4f9846bf2cda4c2ac4726774ba50ee4f546ad152d97f104ebbe439f5519649b609b2769576715c0f93436aee6b5a4dea6a1861073ef5eb1715788749ae8a6102e5c97c97373ecf76b94138accbfe3c2f4f8077ccb3ad6c528ab7a2816b7a6bf86e0e934061b8fb2ec73e10f15bcd62c05159aaca17e097c05d3e29cc3a35bbe30b10daeac28ab9df28a39d464f07d9beb7550597a251042bbe8d082cc711231cc20107a731b57dc321c412dedbe9069e79536eb5bc031b0e28dc78facd97fa8174b31510ce47484d2353afa24e230abccb0f7e4b36d55fc316e452c71a45276e861002900340caadb69519c83280de88034853bd8bbb893d1766520dc605bbe020ab1199deba51ec997d8fce5e7052be09b5459c04bf884db2d6f029b1cfd479d36146753bf9d4ba681b957509a9f062ccf47c63e56f3214f360e6b3ca16e141ece512deb80500582787b3d221aa53df50fddf359858b65a834f7e6d4af650b1fa1c89e247ad867bb9b07d1044d09c1a092389f1de579b42090439e0b1cab51b4dc1d8fdc5bf89ba396fdfb93c8812b9a29cfb5e4ebf2c397a3e317c2fa01c6c552924f09103c834eb19d1e5256c9c3fabc61f094065622793498a04428a2e69982e8a8cd791e7770e2a4b23b698001f862377869bc1c42f4b01478d1c15e7991d295e2d0b30b6ef8bc405aa29b7ac4818e0eebf8597aa060d7a42200c732712c75f880000c512ad138ea9a8f72e20d0ca2e75b79a1ac5d9a53ac292fa970dba48521f3f9637915f8c880a099938f86b193b84e86a9bd5ce177c8092d62e3165fcd4bc52900517c007d352f98d1b71249c69621cf86dd765b2998f98fe67e16c08e5581a8207b314cb563d7f60a62d7dc70e7adea17691f54790cdfa8066444444578e2a98ca4616538a7be67c9008e640ce4aa18b9fda9512b7bebb96c69102320dd0a464a32dfa4524e4dc968edcd78a1ca1678bac09b5c7385c6553f7e310a3def7e921945a56049b40e35e2555570b1992d4ac5d1e85593b2b50dc66bb2e7ce360d825518e557e84a13d13162206a87c75f4fafeb1151369c58f4c306f61f5470d3991aa2361d8c0358735d0a49030d465c5ccf8d978edec6bb198d286b8bbb384ecf8477b78eae9544ed71499e3813c67daee0ede79b10db8bd06c1f2bda7e423f3b8b335f5885dff27a777a89827e85bc1098ce6b1bb9c3ee35e31dc328f68a9dc9501098b355b2a274105391f41b5e97e6f6e92790a384b17964cddccb5e5f907a97787d62d55c09e7bf8c37f1904a1160b653c8dcaa539930aed8e2ee20d1971bfb3d359cc40a4a332df16dc09963d6611e2e9c03e307e74c725ceb272a222825de6d0777c0266844f13b0652c736b5e404143cdea75c047ba2fdfd5cb7d3804b3f16e4717aee5e17a20d5c224ba38d9e0975857f3eb5702df56933ccf63062bc335a72cd3e1e821c0d0c319bcb154272af4188cfefd761e949f5ce4c9f71b5da2570f2694a132cab7d439306db0d2c1d983e9257329be9d91a5c2d048d6044fb2a4621e37e7ffbbe37e63122a6e90151981b4a2aca6f82d7cf1d208a7b64b5f8a2870954664df34d36052890f50dd6d62e66dc242314d2ff94a395f32063b58a673d34187f7dfa47422bf263168cacf89eb860fbec232ab48c40168c0e6a0f8791ba029e32e32d31b90bb9f49d84a4fa55fe64984d1b7049e19dedb7b6bc6b93644f7aebf404b13463f9949a6b7603fa61c154c421e1015e3c1e13f0bc2c9e53d4147a7c3eaaca6884cd7efb08c43146958b4f12a029d71a82c9a5c119ae9dd2dd3294b69a16152bb65f5a21df3b1f7f52e8ede11fa242e44bd68ec17c7b0c625cd3b271180364c54c298798a48975f06c35ae708113e1dfbf225b4579e9a62f376dc218c034bea55332c9c2107527e7c86dbe235d57ad5ea28041c69d0c611c728efe1305b563165e78420fabc56ed96c22f51762149518a696642c83235d4ecb009ae37d8cc9321fa7f0bd4c9c860de6817e869822f5e7aadbce64d4117a99160d7ced1a98275d5512f6d49dccde0d806c91a651966beb9ed02401533a9f0a55578a1895a212e7ca7f16c582a8ba3a64f13b5f756b04f9e0388ab16b0a636192a50e132163fbd332ac0c8a57082d0c7e359295cdb0235f2b341db19843c3045603d4ccda05ad847fe3a7f3e4cbada8c33fac08ec6eacbebc731a42d7cbeadcce026818ae7851892d63c64ca69d2082618d17ae42bea52b7117c1e810f0f0f277eeb7153812bceaa605570485d282b82afecf80be7f7ce23b11fc82e62b591e7949c485470f767544c55bd5ad4de8792115037a05f3498afe6fa10f7b11229bdb12fcbaca9b1f07a16c474ef13c883e843f7a0b011c526d00f589ae2ec87bc323767663276df2b7a1ed0791e7cef33a9c2e45275244d708cbc8541d2eac4d518296d1a58ea94ffd8a72a2102039e2ce59d28b94eed21ba5fb40f27ed8d1db3e2fdcc24e271938f46dd52b20c7ae6663d629e6101121ff177c5b8eb1c5a5d4dd39426333a74f162adfffb2af524811b73a05b1547e3514dff15148e5059eef75aaa18e0218f00bc6d2a5a910e5106a05cf6466ee6499b318134edc4b9e10ce677b13bb4ab8114c9bc8b72984e94984d4432a9bea8532a657685371341bf4e43095916db038031c0aa723650baa8816e6db9f5fcc8971b3030a05bad9b52acb139513c9bdca0df230f81364f9baf91f4ef599bc3763461d2d9a39aa60b893c4b69081e0044a8b3bec73d7ae594bf078f35b6db775196a37b3aa63504caac07a63d7fa8db2873c541f273854493a17b374602c4109d097cae77d3680002bd158eb365a51c6674e8bb54a6f1d93d0409facb494bf8c3f60f55fd779563d0103c1143048c619236f96b7bffad1f9a1942b4264c09c05f584417fcda8f035c50a7438fe0ca786dd649bc34003a0bba2bd788735590a272108b070a105b41f0411955952299d1065d3d836bb8f91811a39255f0e6e86da0f7694d72b78a9ee138afc9aef1c0a4f469af6283bd4c0f44d0d280fcae81dec26af7e23797295850cd437384541781b79e25792d2635cbd37622328e7cf3b19aeff8f730deab92ef3dd88359e1c7a4831ec147e9884a715aaa892a2f6aec359af7213bfbc8d3ba628d3b6c5536f1aab28b61cf7ca39e02e947ddd59b638432e72d3b5598d01ed815c3c78886a39bdf2e98b397764612dda1c7bd00f88887a6747c48ba0a9f40e91b2d8d2c5fe2c0df0d62013d06dcbec20b7b4da36c26695a96eced3daf276baf48e0959afb650ec2768271fe25770134089b0276ef42ca1427339d20cb3c1755195232f5bcf816137b6d41ef702b0224a4af76383a99e8e6641463f2e50ec5cfd3b1dc416be5038751d564b83c7ea0dec74fa290fa67310f32f641a995781a36a844f244ec2861d00af69b657fabf1517894866ca76460bd8c997c7eaf80a77491d37faa944e963c1c6aad4114dc624ef90a28f3e7298a82f1e1a11efd01ef4650c82f8e03335bbaefe3af99c1d561e345e2beb10d5bd5d807937caeb12e4e898ff64f6ccdd0a74be8a71e4309e823d7a3430fd1d65e0c97ca7d2fd6f34efb3a7877c9a3db947d6970dfff83d34b7a6e8bf97914514908f359a37e0cabd1811749455ada7023c8585d41c89391896255b064a1d806f261988f730ba42c0420e54aebce711f97c5179b7b08071da6e5653467cf6e53982f6b79a30b1546182182f950a72ab17222d31cf52006996f1f8b305db07ad31cf3970c16e22f3499adf6d37c969e8460b13974d0356c5ebdf0edd7b6289f8fd9049579de0386d69deb79b32d862594b7b77bbca21856aa427c9eba060ad414c80ed0b906262ace17144cf817a4444af4fc924af7a9df51ed925c21df86a4c4de168c048c1bd154a22c4c52c22c8a5616e9718c61cdc8d5df28b7778ec6101c18166cda46072b834c594cf231d93a4314ace5abb7fb2079f7a8a7e8e98262e9f7c4969aae7dbbfa6bcef28e916a77f86ee8cfb099f366bfb9625de77eedf68790d7b054eb7452b7582b4abd7369e1958981af589789bf7780b82c921e30a70d0f1c053f5962510e28b658d43d3a9e8a197d73b50b0188cc3170c2007f40404d168ba71c818831c4876862160d6c6caadf2511cebbc22c53ec98f58ee1e2fcb16b4b6541b3b9cd788e27862e038ca14fcb75c2e58423eb3390b6e225138177f63b20df5393a4117fe416184b574610a1ce780d4840ae57431475de325ef94d774081cef7dae04ca4aa0cbea79b1ed14db4ec52189c129c573473cc85c4fa45f800761517bc43630d6edd2f17e74866f1d21bf3c44ac734d5e367491be23c7a31247e88241cc29a0880d5f58cffb8692ed9f2c8ef768db35b9d148c4b0c784e380715a0243e873da7cc74ac325b873606a8eb82938a0347cf95e94e6e1c3ccb0d5f9d86216ddd7f050898de600ca358c690e5db0d7a0e1ae9ab5d4c69a342bb003b548ab63dd9bcd53210a35092c42462f9698376432d23955548bc5700535f5c788d02d8383551afcf32dbcd9d12cffc0e64331801913b01923ff5d2b2612d6bccbf419a23c2004463185ff3185c8cba703c73b29853c0a9b608108b1a71d3986da223d8d7ac13c3f4ebb85e064ba9974d7508569cca22828dc1a0e4c05998c3cb3cff24ba6f3d0e27d70406fade30180e16011d3f4e9d207dd5034919e564bdfefc3e83182637646f2de6a572070e8a051d413c72e0a1b72efb68a03df9a6a015f1d51553e4230c29146ea883859a8e76270b52b2d043b43cabf7930f9a6263b4619190caec406b0a981236d1b24dcc1df61e7b3fb24797c8c2bbc0c58a5ca0006c8134239b3cb780d0ae073eadc2d9e71db85843b3bd1735800f9fdd3bce5fe26a4c64ef0c575532fa41bafdf93ec78c01971faa00d1c12e030dee75b7de47770a02a14e57525fb1a41a76ad90b9662154ca4fdb121ddb8782f5b1b24a6026475217827fca025b1d51431c841dee534c211c8a6900925a8cefc170f5af5cf15d4b51678f6574c10ad3833ae39c2eb54908c4fa6a8805d2a70376a0cd1a6ec6b5a48252ec7b624d3b2ac51876608b80f016b0860533c12040bde77948e8e5c37db7fc34a927e03f3115ee585d47049a4074ef324a56ccd38d3f0eff4b59faca213e27a71c5336ac4b953ae4222db3218a4ca726380e8833cc8b7d95acdf00b84627350e413b9ca13219753a914344bdbbb653080bac60e53aa6f22859bfb20dfdd8b1d29a141697fc13c0a44b7e196c679272908c19edce8fce4941761d78d05dda4ef064470ee275aafab92355a42692fd307a2a2ed01390657adf00690c9afad6330029f70667f650f8cad8a36540142a00e1f776b96a38f3419f0e49fe387db91fd03ef77c5bb27c2dff1e12412e9a20f458de5dc68ca553e2ab9fc951c353a846d6391e46c8edd3a1b92729f335de032818e9d62f142c09339982a36b39561d944608a319add897e68889b72914cc165b18cb9fdf9e741aec27cee4d118875225133d2c3e76cfe603670fa4b14dcf41d4cb0b14874e4e64590e39c50c29172c87f0b91869c3c4b2d7c04b214c940598a1b6fca73754de31a6ca0611eeb97b75a7600b6a3cf58a39d94d8efc38c897eba9cc25e54c5f8c7d6c9b5bbe2d672885849d851b706dd690bd5c36791a04f4c551753e1b786273ba4ecf3830e435fc6bdc3adbabba77d1e415a3b9bd13d5fd3b110ef0cf567e35665cea1313752a276f40dfc307dc1c73c0631405540a5a1a66cc540f82edad7cea37869896bfae0c879d4a1e2dab26f6cae8e133878c23ae397c2827ac617ace9795746029e7cb25086aee560eb60a049e954bb8d34890deffc0686534c31d32c48a97d98df53886f7d9a75a2f05cb5f002c48c5f7231d6fb1b8a08a3f7ceba2dfbb83819967547eb2f4ae4f215994e99a70fadc66d6d60cd8d9f4e74d47b9fcc39105d8908791e5ed01e5f401e5665619b07c0e7f7ed733bdffcda82882d25d50c904c1a5af78c8de0834ce128a4bf2656c00b07205146d8b03ca27ce4bec4408679b9c1b67c5ecb8f221b91c12bb39f975e6a78e0405339146cbe424ef87380286a5e057efbca8553d1f156418542308943af506b01bc7309e654964304f864b60519504de4f96807e552466b6b29f79a2df5010c9e84612c46f08fea4a865053a17ab94d6cf15b24db344e41a4d29c0a3d235edbaba926894aaa8e66ccfa5626a644afd986864a0b9fde1492fa26ef8e128a814f28237a2562ab72c97203500dbbf59d04276723a15780708c88a697b28131a9556acf0727dca42f5c23cb8208b335041149e21cd0f72454ceecced393267bd73f33b36b721ce5c21ce186bd8b5cecf4845474a1c50ee9cf2be2e79729783fd322749989f25810d4db614e47352848c13efdbb6a4196018ced538718856219f5f2c94122780f8bdf7055824565c5ffa58869b927f3bb8c92c48fdf3d4c11d5b78a283764760aa9b4980f7900bebb90ceeb82c41ecabf4e9ed80840892b94a72b45a42edc9afb405800a1a22e63cc910227f3564e9924e0af19bc3aff0e6621b5665a0a45d3e8d4eacb60cab062ba378628147c6c727addb04c1b555ce7df1112c012a58f783ebd2d5df5ef29a80f86d06b518776f6b30837c43d3791de6ffc7457ea72467b25f41d6bfa9553a298c90e5c98858d692b01d2501836ff90fe18de9a249015e01db8a3889fb0084977364e58fa48b7c957cdf411eadb7e970616cfc8889f8d8cc3eba55c77fe3082343b4efa43bee7f89b47f1c9f974641ca57e33e2b1f3ee27af17efa583102963df4db9ed213e20afeffd47837a86651cc28c2743f7628000eab626de463a2af9536eac3fadf84ad14094661a3e6989a89a6cc91a0e6df272a59fdd4939b9565dddac7e4daa4d625d4fcd3386729680f8489730af36faaff03eb48444cfb5b184eed58c804b8a3d475382431b07ca1578b5a1d612edaadbde3f9c457d897415a31313a3cff89f1dcbe94986eb492047d9c395bc690bef00b9908e5f41ca5eb11fbc6b4395b22242150ec14e5c51b59df1c6977755b0f4a024328c30f8c52a8e8b38dc73568c99003f034a6dbbc995e704df83da1027c93a1f7ae3e4eabf3081d5e01c4b78a52615f4f2ce49cf18561dcc19f93018eea9bab97c278d79b9f35478ed53e7088d167251a635baf16aaf89889b8937dc3136f57912cd9a90c4ca9b22e8d64858f74412b5f516116aa8350b0775220943e899c84034d4ae8588dc0d8413d141df6dbfaa447ce384f2a74eb274f6639c73ca81813e6e7602c92f60fd9e89c45aa7c29ff3b25d31b3aa9de664abc2329dc85382499c60598b10630105c5779b34428ef7381f26a589f510adf684d31156bf58e111099bc66672feccf962fee7419ee2595dd9097db08580b9b66984040578855e8561f1214828d2fe184827cc3cce54d459ed38cbfb162def06cc602c002708283808898f513faf5e02499a73189fc49bb5b5b61eddba0ace5b117cd5b9e085d0210408b41d5343306cc72f92211c945c9b7582b77397c213001ad4cbba7e28184220e886e913d1e112750e2515a27f20896249d8e1c97f94d324395fb111a15481e533e5062e661616c3b9dbfacd16f95a91958aabb4029340f571b3d484139835f41861758f001254e14c90c99ea261395b69281a1b40b342384f900509e3034a840623904f74b83a44709308a19d10ecfd627960043200970e4d7d67ac98c5a16540e7fc1dc8149defab2a456c31bc124028eefe68548f6304a20e0b8eab247abbe4805b3279b2647c03830ea7daab8a627dd05ab8baa386f9e5df4452e11a221e10d97a04a307137f8b00e53c0716370b5fb854fdf95f72c8f6e0031a3027bf92e2554ba06c4a8a2410c734459ac3da3fcb76aae7b16c9889652f30241ba8e7b610b0fa6ac9874cdb9de21aac07d9d4e935e3ce87b4f42f527ef6952177d874fd0e7f123636d7ad23f9cf913c8e3a86b29261c4fd78250d3adc1be518c4988d1f45bd1be89e25ae3274e6f63ec91a8a658dd8ccaa3fe96de449cd1aad11ce9fa4a5041d0bde9c851a6a4459f8cc22e53ed6716bd4642b98ebfe532c70efe42a048ef4316ed0bb4032bb6fdebdcdc0998717894f47131fa007f0d6b50fe33009318fedef22a3759e8cfc2790927f2a1b53f7615593174b600646f6895a2c1fae5d0c36f8015f63c3f132317267940855fe8da43a67288ae1765208e41a7e17c917b64d6c9edc905589f6c98c9a09d07ef42cf305d9ab1f54aa91c60b20f0b785dd1d020f737f47d18c1483f82a542088841e71fbfbe528112a535bea0c213341b79e644dc70876a644cf81993fd6557bcd8044c716e0a8e90e56010ee315ff8ed471d17c36a24034c94a3e479fd17853c4f5f56f1293c5f384cc8a0e703a1ffdbd62fe01e99f7e2f6f5c1ab41792f384ee06d2a9052bd5296175a9ffee40e4c2e5f04c4c88de4128ba5afcfcbd635d001bdc5407747907e3deb94513770b5555c0a57b05c95a597ceac5aa7fc758ca2d30cbd1f3f3f5cad764b40c531acf1dd6e456081aaf899cb5aab9f5a9ab85692bca71d970ff83a3019d1f5bf1099fa3d1e55ef9011fb75b274ab532626aceca6bffb54bd36fac5efb52a1608cb6ebfca2414b0bfcdace371c865dd69397521c62e946cf477178c0a0a0570f767ac78254bb906d5060fd6d0c5efa6aeb8824d2bc67fb2815faba4b6c9ced052b7da7d58ec19e5506c8e3196b73bef62d51e05cfdec8ab6a144e410680d6214f6d657589d389b6e74daaa04a87ea8bada76a05771eaf99be2cceace522d0d636f07f9a54025776258bc0453798d83401a0bf33835cd0543011339384ef8db65260c5d4a7ed7db4026735bb91b14223c092997c05b4f9eedbee6568ae453327d01358b253b0b4c3f5a1d794a0b2c12ec3bfa919a4b42f053d801fc80ba3a27d6a7d78fee703a25a335f69c045ddbcca2a264d98ed34f48513fb209ace249a7f2a034b232689734d5b879a6d0e005c9b01be6deeb628f627f8dfb00d6d1cf017aa676d371f0edef4f360c6083b1e33061b6ee8b0b843758f4c15ad1599fc879184101748392d9e79cd0d6818740082474a379764849941b15b2b2f582ab4fbde12802a6cf021f5cfdae058ae93db89978d8849efb7f39a91841b4a2b4626b662dcd8d08774cfbabf7c87b113f39e4abb010ddd943ca835b9bcadf09048d15599c3d3434cdcd4e3ce1b5c241ff1d24e5f87f5891f5081e94da9f72941fe47129a3d11576a2bdfc0a5431b2d11b9f131c30536325dc6fd1985d364ae88b212d5a18234879bd1fea0c8649e0a617bcec08c047d64d1e99a8b38824678d4fb92e75cca479594f201f93594aef5032c2d09907c9aee2ab1fd00a7334afbd6064e02d49cfde1c0795210f7bd8157e3a29bd67c3394e5a26c42a5da1b6c9688284f0f0c186a760566f06df4736935eef0aeaa78e992746367dbf1b1cf14c21b65aadd7ea47840cb09e92ee0b231eb7a9eff018fb8e530a1c44148de3fb5f2a24e154484257729586caa34dad7d093e2cc4017e4f96e18b63b007db2449a736c00cd22118fda189cf1b7d83e945a0288a2913724f4417add4012770549b00f84055bca0bcf2fa9f44f7aff1a65b62d86cce137847466246e0d38c9d35ed0f73684871ebf9899721a2ccbe337e3c3e95acd37b9a58008ef2da0871634c394ad3c3183e8d5ed00f4628f4f968804ffaac6119701d0b256f741e25934738dc058e96a487ee2963ca61408fc9afd40a2fa58586e1cc69df0c653da9189a574bc67fce46da4439e9acb1396b2f1a4eb841a86f23cd74c529b05339d2eec8811e4b8934f72971a93a79ff0036241c2f3c74fce874dfa9131c049a508fb0683f46cfce9893f92193aba9a7410d592a1beaf41277a75cb54e028e1a8a4b1d73c76e1104ac53a2bed09587916d9cfdd0e8df78cadb5ab48391d472eeae48179f3511a692719f41b1c91bcb6e68b60bc04546b409df5f1c974da0dbf2d86fdf01e46a1d1d85d2bb1f7b89abf05d5a371ad9ca82b84152c4e0f50a6ba854a06a4648c699038b1548d4b708ed2a143329004a00546005e6a37fa9dfd3738ddf2408c3d131857174d219ebd1c9d1112e48d15466d9739162ccaacb4a4acf057b1ed1a785552eef19df539124f694c61442ea7620dcb9dea3398cef1fabfa404f61624b4d77519c7efa21ec9c0bc3f4265a967fd4eb9d6d86aebbd058ce2cad4b957d2d011d0b1bd3ca6559bda5037923e9aac99f5816c0f012e4d2398aa01a8d7904e91745d455b3d747365ddcc54bfad2720f9dff443ef5665f38303f1169defabab2c3813e63a9622621994e47782f1c7d732a4ed3f7a54ce38ee0aa8a1ba4d2a3e292e8bcea86f76ab824e427a77bf01579ef68476a1168f1e6fa6ab2677a500dc160124f591458b981d87f013686a7cfcbd21d21d6f2ca39b4044bf85529c98b82db541dee3ea91dadd14ed0a6b0d81143f8013746044d18da4495ddc16ea07df8e823742d675835dfc8146d9d265974b7ea92bbf330269731b81307c5b89c3897ae5da5c93f14e7e5a77ee1aeae17c23232d41df7c497fa9f0ce1aa53495a43fda0cd57fb53731dad3fe2a06ffe7006a337636aa98595eaebba26fc38538e451fa6d0f19a7d1681acf80e31fa5e8b763274e254a814ffe1530c06392ffb111d2dba6e84907a35fd6bf4d63b3b917eb4fef98d2b5d6edb91bcbc29ae45d91cb2e5c0b6e6aa6b5edd52baaac7f80eab8fc31bc43ff3d8d88bfa2ee57b4d65c3809f4e6c076bae8db66393fb674d56a5e066cb6a4d2cc16d1246ce24309530b2128e302c7cd33ece3f1186c19c8d5b4024cf7aef2aef1a1b7ddaf4ce2be3c3e7a46addeacd90f8476d18087d25b8fb2a59d0588eb64b8381e648da570abd835f39dabfac3ec5ca173b5589012ba00a55a5e6e7de0d54a368ddb067cec16e773105d2dd95ceefcc4881311008d6ecf342d07105a2fd31a4f6ff5c81107cb90a73f6a16e8056543abae33842a45f449f8adaa2c7ad0c351f7f4fca170312256857f9631b6f83794be8f76b0f307040852505f80d8ffe854376b1f7a3ddff0a741ed7503bfcd36baf69b8c958f425526632f1c2ae0a76b7aedb64a65a55e97d6e827db105b612eee91667b48b831fc596d0aef2e3305c8210f2b346db964752549239c3020685f96518b91f041e68f90b0459dd40190c009773e7e438b2cb6dd0a34aaae0db2e597efa8bb8845ae2374ea161b821193dbb377f17c36fa49c98f98d5f131fb2ddec88b1f3427f951268e226c5cf3c8dc5dbba08ea4cb3b13d23f81d8c3dda40c061e00c4bd31e16c374562682aab6caa650443c83eddb3a95f1e5e46f069b6c8c4ca558f33965101d9413f41aa522d2da1c4217e39184b0ee2d38ea78136a5323865902d3b3aeb0d9c81bd69aaa94ab6c8bd058c39463906a9bfd4fb5d2d7da95bb83b8305c595f063635fe2c72d7d1fae7a27bda68006845069e03186dc534a000ab9bd3249e8f3b51fd78124cabf0b45a674358397e1bc067f5495d499708e87b856ee32a0bfef95290176de9beac28888568fa4351719e8a46c6e6b793bbe6ea373531373b4393f302cd684575e9187e80766576e9e69d4de7bdb41fe602f8851102227a5700406f59b261a39f305a63d2e8f563235a1636987a6b730dc2ee8677c9b1730b2d4081e996024edabc83028ccd9c2e136a3235ae7c186c2ae3da3e23eaa2cf053ad54fcc524f1105209f261a3a2f1220e56d231c067631ac73cf59203d8899a99ce677c669bbcf37284e12e104f5cb70a30ecb5401de3f0332a83c90365cfff3b68ff835aae2e63362fe2c381946bf5f3a39350030b91528b70a41c1210d1a7614857cf5c201fc79a0afc8956c717c908c4d0d1fb628a2c45868a788a389affdf2705ca103b31a6b929665596feaf21f013d2d1585bdc8b2e6b290a51f8c3154d5f7f8adc1392a810b25f910ec7dda37831932c72dd3a85f001e33ac3de1e300c92661bb394c5c22a7e29890a6c4bcf732cc7de0a1d94e1cd611d282d809fa23f9b2c327fec4094c2f13ef7ef8e1bb3d500069b50371e1025eeeea5cfe9f3d625e58260f0ee0cc559b4ad615fb6f468ba4feea539f889bff602b04d004ec5c045a868bb154205e153707b9a9a976b26dc0de0f505bf22f677e12bf66ba393accda75396376cc077b27b6b5f374d6cf1ba6022c5e44eb83206cbadc8708a371ec267369392cd277b9017f8d419ef6dfd66c77f7cade52a62465270b5a0b820af38505a7575a2c961383c57672088611268c161484849bf9b2f2a1f79a5e6938389e04c70627f41e7a87c184d178783c0639f48e64be98807aa5b5662c9f71d2aa176798309a12256990cd171526bdb2b319cfac67f6036b9508c584d16aaaa0335f5cbc7a6563b19b184ea8c587be7b30616c50d00f72e8db355f4a1fb238388d04a76b424e8709637978b278325f483ebdb2ad96ccb68042295e98305689922a72e8696cbea07ce8e9925ed5d98ceacc98cc787228646ba8cb1272e8a992f932fad0d356af6a8cba5e39147e100d72e8a90c264c0d1ad2ab8a337bf5040749e661430ebd07264ce5a1a10fd2aafaa107325f3c59e813fa1ebdaaa1d73161aa12ea627feacc66a197d12b9ff16855f7a1d093adfabef29043a15828147a70f41c63c2d49a50e86bab268c075117fba10ffd0b104728270300f6f331300cb6c15af04fb6df3b88f0d6da94805b0bdc5aa1adb529c9f655c6d0cfb69ad00c9c8133fb220b082316148a8562602c28db77b1f29d341c1e50c309e168383cd97e0b93f7426b694a40ad056aad90d6d29464fb25954e9c6935a119389b6935d93ec905d72216148a8562602c28db4f295db7383c6e71423838f651485b8a6d2909b16d29c9f64728da5667b66636b335d97e38b2618dd5a01a8bd5580dcaf6456d086b2e379c8a537978445eadb8a441a3c9969252c4162b0969d676f659adc121ae35d9fb4220b0bf26ad3dc57c75654114c67322c6b28d05e59317d4a4fd2bf395377394130ae35d315dec5b99289365eb8639c37392ed7f1ed09c61dfe58ab0fef7b93e9798e3abf0cbc9b6334eabca30675bd22acbc3db3fb56a7b6bbbd166c7f11d0af3b9a88b7deb0139ca7e18e264dff180bcd55ac203479abfd1e736496f7eae154fc9dae7caf63f3088cfad7d9f00f294620eb3fa13a4b8560484fd34db0d35d2e81490fd7bc3d0064d582ec1c3dfbf5fc3eb9afaec6cc89f1b298f7d19403c8ce28f2d6493f63f960764bd7a40d9fa7f3bb883f4c09bd91365dad2d2e4c4319bce4a7bee20794292bba162e18d1feaa75ae57df7f5ef57f2d62f69e46a23d7f7ba7182f69fd46a8be5b86f7036c971a191d9a449a3b3a5deccb40a49d37890215eb946924bafc9de36ae6a535fed836b6fed7bf7de7befb655ee5ecff33ccfebf628adb7c3d5d5a4cfb8ca9ee1c64ed22e9f71244dd2e06e353900997fcf349256d1b48ad69badc93f11badb391d0c429041106e62704a021639f49a66610db2e91406f0d3730d9ed7d224fd80379a2b8f36d681cab3c9f99ed7894b32cf509d334224842d74e2168d76c85f860e540d997414c9b4a953118625d9ffc35c69109fbd5ecd2220f4a7f93b089476bb3f09bc39d2f95eb77bad96be678acb2293bafb12fe844e9e52c8b3c913acecb95011d29f266fa6f89910f6c7b2e323aa8b17a84f6e4c7da8cfc6528237bf092ea01a714a67baf7ee7d7bef4948df7ff3cd37df7cdbb8fb694f3713f8fede9bc0deb86dbbdb568ad947b276f6b927656cbe7d0585f0efdebbf7ce1defc0640feb36665ab61f2c6e9e84b3c9da39ee0d43519be068da504168df450e614966cd147afaf74d21bc83fcde7bd257f75eac914db637b7514b935c49923252f3e5134281f27b5ff620443716ae4c65fae97fe3cc9308cd1f9661f2be7f9a3cfa14cf1e63bf8d9970b280861257004971852c4f29ae88e5f95c9e525cc1244f29ae58924b724a714512a4b8e225d2d041b7d48aad103815d736fb9a28924da664589cdab00c5246ca29ca6ee4b885f07bf8dfbbed44f1846c495243417fab4ce28885db9b56f10d5aebe7ddf0958adff01505c5f7953851fe58c4c92de6aff46bed6c7dd0e2795f775f9e25a9d6af51dfcc5aa62c6008bdef2a188487a11d0cc28aac08ef6fdfdff72c5708b5bfe00e1fd615ee20a249fa751d6cccacc0639c30e9d81c832bf8c1097096248141cc14b8277936614213b97e3dca09e3d1046726dba74c5ae5d9c67c5d874d3b6aee3e889abbf97232cd3a49f3a5c5cfb760105f76172c84b3491a4dd64fb5e44abf9248cc171ac58f60aea81528cabea561985191edd442b6b039c3be0c1484dae338027e37d155366bc396f48e4eb64f9df46a5218908d2c49778dd8476850b665d8b126eb5b1c582b2c43d82a878736b2a5e123a36cc9560937497865afbf3a5fc23ca963249ab4df92cb39ab1167a1290cbd930fdd91d1a0564d2bb84007e749b65f0b996de8a94a7a4371ecd32596e2e4f0559146d93f729184d606891b25b26d91edb398212ce96b4f61968479ca51284c087f1da1ef4a9acb1fdcfb7b3fbc0f62e6f0bd0986df8d6179c308cafb3844cbdf7be38fd17f193e0a9e4258b2c8228bfca37bef7dfc11e2215af65ee47963c97df7c37bee272884877f74f84737ceeccdafc9a64e32fd8b04ae766774066fb6949b2bb76fda7bedd55a0b0ac1c13d1034db6f9ffe6995f7f35bd62a7a39b1ec9df14ef283f59732bed35cf58da3c63ac9cffbf92191bba70f7e1fee3a5ceb13cbc261eb13cb6ab27bd8824ddea9b399907e596fbabba508ba7dd4ea70200802153b5e8001164153f0c1c523061eec24c17505114037746e831d843a36484871c27603288298cc1c79a20a52004dc1862564564441064b204181820a278857d802c0832e28e141122cacc023680b6128c318aa8081cd0e783a9d1d58d1a22ae10227408315343f8082149630b284119830062098810b3d4b9002138ef040095e8409c8010b3fb059011390e4800a2870420b8c20861c48a1c4153355070859705e038e2e21093de5d964092c31247b42817c2e908c94afb839377ec8c1e3365102154ac8610203bd57188c20872ec8400b41541421073a504204275e00434cff9c2237143f557034d74b020e6a1294c8fd77873c9b2881437e916713253d1b8dd72f8488ffe4c9730a09401ee2ef1f84900ade6cd9b6de36179d39c39f858910b481030adad1cb46cc17dac2c05c51921c47159511c7610ab3df12c2fe98f94224cc96c2d8d5f7fe0a982fdabb7723c76b4e0ee78d33c6085f51ead32dff3967987a7446788c4c9d3eed183b12b93175ccde7b8c878b9820a6c3178b27f9207c4fc4711de5bec3dd734dc106cc986dbcedd6bf6e646122f43c8f1872f3fdd93d872dcd114342cfa5e44c3dfc8dc49820c6f33a76cc1d89dcbcd9ead6431bd6622c5ec2e4c363ea7b4cc5454c10e3783a6a3341b73bf1daf3812424697f6f188a622aa56197c182b024dd3c7be420a4bfd12d541af141440f915267e2cd9612c595b9f766afea7b8d26b994a3b8e75e636122dc7a686dc6597e6404e32e8b7b5292d03af7ce7dcfbd2369154dabee73ef35adea9e7be73eb46d8ff2a16ddb6e4884a3b80f8d282311dc880b39118e652e89fa299f843fe9a967bf0b6e279828eee7869d356770a14f22e5eb27414af9fa3e52be62d316c23e48effd2d9ea33a99c3454a587414e78413df97b013dd9722dd6992fbefb7d1e6067750264d7e9bcca35f098a21f8b48faf9c3551dcdfeb93396d9c63bde3ddb6df6e77051084108956d9e7befb2fcf14af3fd2e82e47719f32be32e7377306f7dde86567f90a0947717f6f188ae23f49bee60cee3d7b479ae47ca649ee3becac39cbdc3b2b7328ae0f0d5ab33031b91e264afb1a597b1a5bb8f7bfdfee5faef3ee36a6c4c9e1d49ca1556cba8f4d172fd19fef7f59bbdadfe85b23b5041112cd6b4f5aa7bbadd552ed0db47675bfb5da161db4b3ebac3d2b13d79dce5a37f7a9b9db396b7577f7e9eedbc537aab5d6e25abfd6eaeef334ebd3ead6dddd45315a6bb6da4b36c04a95bbac3dcbee32b7552df738bbbb695c68061b19eaf5bccd66eb8544d556ebb55a6b3532588d0c3d4cb2fa90eb8eec63fdcf7ad6dace5a8d0c5623039d24d75181b657ab6ddc56bd7a7dfb3ed08a3ecfb5480d3f1087f6a3ef46df14c5e54da568d4005355fbf9696110cf7d04e2d050b6af1e869a63d14fe56a35a11273456f7c7c598190ab133509437c59978c71982b1aebf1653d41ae2da83210e2cbdadaa698ab66f1f8d2bf909d0cae061d5f7ad08a11e6aa5f39be7426647fc2a3c0f1a5effcaa777ef8d26b905d090742fed29b5039c35cf5ecc6977d45ee38f8090ef0a5cf9ca0982b77d9f8b2b1907b8afe8201beec9fd2b7c36ab4119a093e7cd939221de6ca815a05b91b065d831ebeec24a3554d7d49c3e0f2253d03bd22cf204dca43b140a190f1257d42eea74988f125bda142e0e14bda03f24b8a03306ca12a987480f1e57c43eef7408b7286e1054bbf0eeefb3e406e1f72cfc8dd2ab93bc6f5e18006dc0c71d343c65f081ae3b163012c1dac1c4100f1c2f1fa4101313b3bf786a278809ed980797119c0756f288a3ec0681480003d3850ca6500ad19ad7bc3501459c83014c51855c68277c0657861e0f2b2e0f2bec0a616382e70c922a2e0524c0989b4196d8625971d8ee7f2a2e0e17837deabc36111434dc365b5c9e34a47d315a17b75aeae35b25ed6b1a063cd8046eff9b1f3cad8d953c901436c078673e25a4bb87971ae959ad3d85965ecec9580b81870331c6b06245e98197c623b2acda47369ecec8dae2b0a3837af1769766f7069eecc65958e64da793476f6c01d36c87c623ee1ab0a39383723ba241c3b831b6be3c146d3ca34860590cc079c419976b6374d603938dc971d4ec7842eb68414ae285add13d95dde10f69732e8673b76aeb8dacc15d5400630d05f5d29231a7f7f65cd158d5de0cb3a63812f2b4d05fabf6914d13bf4cc55b328f0a5ff4ce04b7722815ef9ae4144c3c099ab7e45e04bcf81c0970e7b409fbe6df86896eff79ab9ea1d077ce9491af0a5db0cd12adf377af40ba0b9ea99cc973d63c097ce12a2c5ef1f78b489c95cb96bc797cdb3802fbb474797be73e4f8b2aba0335f5abce6ca61417cd937407cd938389af4cde38776f1fd7d64ae1c48015f3692982fbb26f7e8bbc78d46a9ad047c496508f892021da0c36f1f367ac95cd51c982fa9cecb979489011afc2682ba788d2fe912e64be8fb696baeaa6cf52575a9bea42f1ffa7b1a5dc490b9b2348ef2efe1cbf984000548f57b60c21821fafe20ade2be1fc87ce95cbe9cb2017c397d66cc9595f1a58e09b301eae28ffa72ea04e04b1b02903157d6c779b4ea7e7f8ef9e27d3fc9436e1ebe7c00f45b0eb4cc178d4e1820d4c5bfb7ef17411c7de32bcfa5019c017a83811485a14d1891f20be0f2ba0570057029fad3a030f455048dec1d0d055813604900d7a030d486881a999345e00581d703b00d0a435d3e6cecf88acb71c0cece10b81469921eb8ec9ef98abb32b8bc0cc042e059f6ff81c2d01675f1e7a193fd02ed702dc0a5c33f0785a1353970d9f9c282c0e5050286c39f0785a1343fe0b2afcb51fe0ac0310e94fd7b50188ae4062e3b6f334725a08580d601b00f0a4367a88bbf8d9ae3ab6de7087591f96a7b154161288bbaf8c3e4e41820a7062eef0a975785cbd0072ca3819d65048529a2c51c456190a02efe05a021004d0f38e5824b312cc31958062edbfaf84abbe1008519425dfcb5192014268800b04f00ac0f0a972289cbe601972200700c8ccbf63c97f5f15c2e97f569621cc7711cc71e4da00c1ec796c7df827149f388c771a4791cc7f7b73ee3388ee397560ca618df12a305979549a6afd70effffff3f8ee38fe3bf0065c6ff1d7efc1dc6ffffffdf61a4f9ffffffdfd4f263cb88cbfada61ec8c3b1a9b8ea6a3e9686c60acacacacacacacfcffffafa88032bfb232fefff82b2bbfb2b2b29257565656565656564ce3fff8b8ac47642e994ce662399d4ea7d3e9b4b2b2f22b2b27119459399dfe57fe574ea73f9d4e279691e6d3e9743a9d4e27d3ffcaafe0d27d58c6ce30b89c245c0e97c3e52479a1a2a2a2a2a2a2723a9dfe74527101ca9c545456fef42b271595575151517931d2aca2a2a2a2a2a2a2625af9d3ca0997be846bb5b816d7e25a2d93288aa2288a2a2a2aafa222b600655444f1f42a7f52c125cd221645d134d22c8aa2288aa2683abdca490597decab4f38b0b5473812ed005aa69512a954aa552491445b1540265c45249e5c557114ba52f954aa552a9542a954a2593ca8b2a222e3b28c36860301a172412894422914aa5d2974a241228532291c42fbd58c22412c9c548338944229148249249fc9258c265efb8183bb7b82e24d7755dd7850465341a8d46a31189447a12699402ca9046a3d293be441a8d7e341a8d50469a47a3d168341a8d4ca5279548b8ec266633b3d96c26250cc3300cc3d168340a5140995118927ef4a41ce2300c439ac3300cc3300c4da41f9146b8ec9994b133cace919d9d9d100882200882611886e04f991004471ffe28c4200882a19166100441100441d3e8c351884bfa935fbebdb6d7f6a22cd1f77ddff77d20083e087e2128037e5ff8e087f8fb3ed148f3f77ddff77d9f297c300471e7d0d8d9db584536d6c6da584f3a8ee3388ee3beeffbefe344a0ccc771e07f0f7eb8a41cc7711cc7711cc799c0ffc00f9734490c89582c36f3eebdf7decb71dc73dc0d8132dcbddf73ffdd7b69bef7de7bef357dcf7d5ceec6ce9e7633e4e6e62648abb5d65aebbdf7561094b9b55e5cd25a6badb5d65aab89fbcb61203acff8aac3f12014c6738961a8cd6477f566adb5d6da5aabfd40996aedfdfad7da0ec73a8e35d58a81e89c9a333a9b3e9c5387f3793ed852351ac673f56ade565ddadd63a0b9bf41991fdd3e9d13b2bf4b50d8dfe1b87c273b6cf341765a1396643e7d2219bab27b2e4759bbdd1a618e08eb0e270653da4c1d66266092f43d97af1430513b4e64a7749cd9daa809cb8af36180d22468b881822b87b9dfbf26ff5329519c3d76440df366cb9761adde52d0c9f4e2eb36086910f57e74cbb487bad4a72e3da109889be76f99e2fba3312967319659b487c28cd3a57eadb4e7668bdf0528f4a7ac7bdb8ae45fcd2769b793fd2abab0b6a652ddeeb3b5c19b2de5b793697bb5da76b9cefbc090a8e6e49abd114a0aa9d4c285a8f2c2745a81c1d2ffd91bbfeaad7940b87b30d4aaf0e77fdf7b2bd4b798e4d9e271c77194f59df99ee3f050982f47c653bd70fc5a4f66417386fd6ef480e68c8ff586e9f2e57c34587c391b6c83b50a7cfb1b935e0520c6961d67835117fb381b4c347eadafc69b79414f7a8321c9f68fb8ac90edbb541196d703e256e4dbf7c80ff5a1401da8ecfd48dabe4e1c49e1e73af568ce007138675c21bbb2ebe402b5aabf1a21c9e5abb006d1197cd4f8d57c344d7e2ea0fe5c2d916887178900208af1220f0683c1442d2ff26432117e91f77abd5e229617793a3aa2f145deec991991e85fe4d9d88860bca893c9643291e945de11d1ca8b3a180c06139d5ed4fdfc885ebca87bbd5e2f918b17753a3a22951775332291a89b11892fea6c6c442d5ec4c9643299a8f4a2ee884824e260301107137130d1f722eee74794f222eef57abd44282fe274a88bd511d11771332291889b116d2f127136a20b83c1603fa2fb23f2177d90568d5ef440e64bf87abd442f47591dd1d51189ee8ce867cf885e46afee0c8f56712ffa1cf3a5bec846f43291e8bb6b23fadbab4de628fba2afad9a30f70875b12f123d0ac421da61eb005063885a6032d80e30982cdb277188c57be9782f16efe5bd74b27d1e46f0bd19cfc69b61f166bc19cf26db07008ccf24f38ec84c32997724db8fb1e29d603f30130cf693edb7bce85c742f9deee5a27b75dd4b27dbdf418513bb99ce46ec66ba6ec626dbc72d6e89937547443299ccfe48da72b9e17030ee470c31ec27dbff140d857b713a1ff77a712f4e27db67a16e082d37c3d988dc0c3723e26c3616b733e786c37e603087897e608422112e69644be3be74eeebbeeecbaf0eb752676ceecc7667ee8c5f9b6c3f0c9d4e9bec1ed9649bac6eb27bc4d45b678d7b4b8624ea138091fed4cfab4daf3618ac099892185fd62539f435f4558909b3fdb47c597990435f93cc971d3ef495d5ab6dab335ba509e1384c984d899239cce6cbd8d32b6d36fb99399905c55af5534c98ad66abe9024fe2f8250913bf6cd8884b327ff8bd939020e26ba0ccb7e37bffdebf951596b1777862304677d9348a6ea0cefea0dc3f9fe4fe236816ebe8dfcacda711877f8fcd647c31364f93dbab6c2f8edd33b64f93dbb718fba73436696c274d36509341e1d8a3b3661c89d3788db79ac4db7fa3bf1a46e9914622805ac1904b9a6b8769adb7de1009e1f6b4bb76d326ea2763bb2d9da1a169b91ad60d9b2ff65547da441413860a61ba5c61bed0ed2975010a4b1a4dfabd1e6d02c72f55f27298b8535d8242fa12c29c3142de2813f2f6d67e2e3ada6694541087a98238aa146cb60dc461ba17c471b18cc664935b53da04bda146982fdd6fef8d3d9aa44fc1c6531b891de4f6b6bdc7090992ffe22973dfeeb8b85a87d1a446af42476d7fb76dabd1e48d7fe9260c58ed84995de8bd10e779de8f34df50a8fbeb99aee3b0566deee4dbbc276fce93376792b7f716f92f8a61b8fdf4421863fccdbceec31da8a3c3443cf0a3d6c6beb4258ddaac92b64b341e9d0e972d9649de6aab3c2235732f449439efd65b6fa5613dcff37c3e16de1a4e73fb0c31fa0c7d863e439f8186f53e5026e479a20fbdc8f33c513b216b1cc976b77bc330fcbe90e3e805653c0edcbabfd1e1bd6178b5effd561bd6e84f400db4e00eefde7beffd3b6bbd9e4884e228a00e54ae364dd6d1b9ae7bad1f7cff06bfbbaeebe7fcef2deff7fdfeea3d0882cf7d1329d4e400e4d9e40959a6c9de4c0f5f1d43af8df5bde98dda7b4e914fe90541efdadede4ed3437bf2f6e25cd19e89dab8efeebf136666cf4750a6dd9d47939c880b7d73df1806a8238489d02cc2a5e8c1f75f0165fc394cc4071f401da86c6d9adcdec58ab0973499d3e446bfbb57ab45c7d6c19cb17d8f8d83e9b2bd1ddba677405db6e7c65662ce4852abd72ca00e8a7ba7eb6aadee5e6badeeddd8759dbbbb7b07c343a3fd6e89869322756cb0c26e0383b8b8ec1ec40ebe13a9d95f88c89b4d595fbfe7f33156afbac7dc2ab99b861e9469dce07fdd9a13b6c79942ce15603b34a6699aa6699aa6699aa66942a8e630c7cda4ecbe776ec87f510cc3d68db7d7301097225cd27e6ffb42a37d8f35e953be1b8550229748e8c3994099ee3bd62aaec7e705b8a3fb7eff31fa21ddba61280a814f1a7d0e73c6f629a3c761ba6c8f328ec67bc3feae031be6e2fbf66e756bce70cf7eb557dd72d4f6aeef8593b79c144c16b50ef40a0a345f3a200a4481b6efaef3ee09940171c544babfa00eefbb1fb7c9ed271884877f7c0dabb56dba3a6f283e592baceed4582d004d92b7ef9aa4c96d4e5c009f791c5c0efea4b2e8585b354975adea9146d5542479bbd3ddfd3f779abcfdf635dcb3fffd663869f8bbdfef534019bfeefd7dcfdd03effb97da3bf885a00e0d13a1d9c3d7876fcbdc38b34b16e1f6de6a95e3112873bf5b3beec5d93c6f746143389b33360a33f356b7b79bb7fab6dcfd0443debe9491a7861323cf39e7dbb9d270266afbf99a13e6ca67d53586af42dcc215a640a7531feb30639388f9f22a2aa3d1fd39a389d4dc2f4494fbbb9fa18bef8c34b3d5ea4a35d95ad6b49c25383a3fa99ebc7d4932d9bed6da73bb36add5feb5b5b60d56d8df93bb2febec6d6cbe68797bdbd3abd91aab554fc420eb246f77fb596a47f2866d2cac11b524799b4c36ad8912fc8eeb405cf6eff075a3e64493693f4dfa349933676ccf8dda139a14a88b4e93dbdb518335b9390662d2a8edb5d96585331bcdd6d278f2f6230844673acce6cb96b7b7af56f56f5f9fcc17cfe2157da5e1543a61ea8cba6cff7df7446af65e88287b366cfc2c53d94693f4fe04ad2bb623c2eea77afb5b815ac495b054a5c8db9760be6fe7aa4a3165b4eafbaff3450365381a7aee4378668e070dfd1d2bcffc20d149f893b7b2f6e4edeb6cc6fd27ea16a883c344680e61f05f73c6f6e0589b68727b0dc757f5c651330a5385305db6df60a2b80d61ced8beecedc787db05e600d2dddddddddd16c4d163b764bc6f4c84e60e7c2fc688a3ff8e1a8eb624c751dbbf2886f45df3c9db77eb037558ba83b664ced8be8e1a4e1d42ed9f7a103fba07bf5d497a6cb592541b577d912d7f1249612a07b603802f060844e31f20ee9d26b76f264d6edf35ec8e65cd6dbaffe123aa3f61b283ccf72f6ef2eeb4ca674dfa7749e149fced7de6ab54a3fa6be4ce0961e2ce6feff9f079e36873370aa1f9de1b86a258fea6e1e4dce192dc9eaba08e8bb7fb35dfcd35040cfefd069edadd3da157aba7b5cd5cf9c865167a57bb87ce58deaa150890ef29687bbe941d865c3f040ae1ce715846936d49df9dab8e4d54fdd93eb117367c40bfec98ab5fdef41fcf11eb1096f547ff109ab95ae336ad2a6b4eb6f548ab7ed0caaa3315c97c01bf7e85c17c097d0d85fe1b4b51083b2804fd92be03813ae873df3de3460ff25612a0961cc2d25bf357e1d7f7e6e8e1e83a8dea9873eddfb3bca8425bdc77a66010be44f8fda4555fab6c886353a443f86308cdd57faa0d148465a511b310ce2650c8c93fdfabaccf912741f5bdedeb0175a0b21f69b21e51a94e932dfed364f59c39a3aa9c202c2b2b0fa1ad5cdf93b4aaba5a65335f80305fbeafdff7762c41fce14a9347dc579a26eb8f401df4c7ea0287b0741acfa93447d45c768cacaf32519faf2dff6995ac913051f59d70a790eb5f21d7df424fcc8f7cd9313168f6cfd7ae56d9d0c97dcd1cad25c96b2a858d5487e6f48dd76751a9356bb5e7c907894efa27d799db6041e83aad2ab5afef4fcc17eeab7f0b11650b0a418d08a71441b3dcef8ea7c9bfac3d9adc6bc1bad2596d6bcea8475ad561194dd2faf78a55ebaf9ae790a42683341936598fa8f966b166caa2210ad1ef983e0f1efdc3a4c3dfbeffcc3c3016a186cba9d3fdd4f5f5d7882d97846b93bd0224b42fa2fd6bdfe2854808a715eb287cfadcff0fe35cf57094f63203f490b512953558902176ac130351520be6f81bdefd0d0f32a487d5acb68db57e87bbd6266bed6a576badb5667bb711a9c9ee67932778723977441fdf8db57b4debbacf1ac7dd9f2087494d6a7fa39bd41e01617d8a63c341b44b83960a0631f3f65fe9e5592910f40335f20ffa8e4bdab8cc91fbe958d6d0c2fb76a2e8773f27cacf398a31e78abe88461ee7d53ebfd1dea38ca3b10c4563682c79c81d3e828238c49fc32291a222b427982f47da6a3d96a9ac1181d3c387f526776fb5dbbd37ade2d1a4df1b86a22dc91293b034714fbf4d1c994bcacad1f2ad182b9996c0b9a22c47d5fbcd17203532fd704cc52024894d5a3b522573345d0c44a5375489833c8ce4bf6337daf041c8bd89728d77e01c4dda6f795b5ed27f0f5fb5c0a57b49f8a331bb6b93da1cfd3d9ff9665a471f0a8843d3344dd3b4da54738d7ecd137fb5f5ebe3d8b0687f82731bf5cf26394ebec74edfdafd4e73423d5262abb5d65a6b6badd65a6badb5d5dab7d6566b2d17426bdf5a6bad2543cf10c1caf58bf091e6cfede3cc74cc6992c393eb57b2be8cda5e97294aa62f32e9a8fa9492755423d799e33245587fbe8c56d1da63beccd9d4ab8f61273b2853eb04a235defc58d91fff38feffafacfce9f42a2a2f8a5f2a3d89f4a3d187e183e07fdf73dcdffbb5beb54f5bdc492acaa1c167e7c3c9a84baf3c1727a3301d0d75f117c530a4e1649e13deab9b818b3a673783ec2e5a6952ae8e86c2cc8e866eb9f4ea098aec5d8ea6f2f6daf2ce2830c96587d3aad273792e1b6f12059decdf2d89293b1dcf15ac6f23b3c93295aa5183c2a1cb306fdce4ba67dded04c8e3e604716ccfed98cf4d6c7f6c41f87e6fe87d93d01d34a4668bafc5d569a2a091b7fa7d5f9e322d5b3295914a8de048fa6aa641c31ad19ac2c12bc9bcd1ae0597e3b8fdfc0f90f9c77cfad6bf4d508dd8a659d8dee724732a7f0d5326ed5bbc9118d268d252de07e9535efb94946f818bb8f8942fd2c21b8d26edc5371283329a346c1a02e54bef03e54baf7d09177142c33e462fe2222e7ef4455a3cca1b89d9b0f82a5f8aef2b17afbdca288ea5713a0a74149054ce71a3156e3fdc6817a3496b319a347c848f16efa2f42e709122d3df484c10ff19238af8635cbc7f0b6ceae1e24d22dc8019e3024f47d198166f82008d69f134a6054e39caefcdd6bfb417c77def6a57dbec6b18486a4789892998c82494981badba392c5e22c4a9ce08d817053e270a0a61798f387104cd42bc0eac6ce7f788e778f1c602c24d3bc2ec3f962660e52137fbcfb1aca511d9ebe658d9b7d0ca04c8b389143fb90a4f76b201f2acc2139feccd1a61e86986b5aab17fd95fb9ed3e103473b6f31e089a5f36a73d2336807be7cef8eac662a9588d982bb6f9f8eadedc9bcde7de6c3ef766f3b93775c7573716faa41ce57f71c29c14ecde3014c57f924ca52850a571b1025d9f85ac99eca22c741f7a7333bb01f2771a5fd10beb9d0b5472a0f40dd4aaee9f2749b26b343c4fc865f7640f595ab0412e5bc66393cb9e39cb0a4972e93e93bdd4a13134cefc35292a117e393a4dfeb48fbb90ee6932140a8d424261e9e9d83c63c7402a1ac3b1bcb9848fa8791b85a1d1247ad297de0b471310348726380a47d308572a72f542f68484638de5098eb50b3a445f7ad2687aaf4752a7d0bf39e56f4e5b9df903e54bd18e10ff187df8255c7e2f7a2f34c110e9897826e1d2fb144cc4b387d23ff2680c127ad38ef047e87510a3534c72639bb0481ae55f7393d8d0490f5fd5da44a3fc6baaa66c8ae7f6fcec28b94b8074b27f45e24e7ac757cea451fe366292b0a61e119f8441373cb727fbeffc64ffe6e9f1e91f77248d6a9dd7129792266cc424618d1f119fdcb80e15420bb339bd44586e3e3e2954e4f1a601c2ba22bd51f8379a74f1222e5359bc69f128a75f791fa75f59f913ca89e54fe510944789d5bea95ef53cee2b77d32a25bd0a592c16abd2d880c2509f13a5f47f3c8d736a200eda4af91b4d815a559f06f5ea49774db7beefbe1fe9cc0f944f79af9553fec5d8208e17efd1d27ba5d20731730997febe911c24a37c97c6927eca7bfdf5687a12ca98c44da6436c36e16a03ea92f237fcc54895349992829738ad8cd351a113065340157c03821fc4574638aab6f8f2e2f296c42b523c5d1c47efe26fb411be225be0f266118cbfd125cd28df98e5c7510a2e6b4679d2f758d21c56a6a91a3367c2e6ce8ccd80643edd7d7a1c9bb099c3f223ee11641ce744fd384ba552a94b7f7d75fa122e6fe47e4c29e94946f1c9a36fd1a3c8b810cf28584802b2c8228bd188321afb2788d296892998f0e9e1a8faa71ab912b14c4cc1041872e31fa20fdfa3dfcde1580eb14bc038fdca09cf1e34e626ccdf58fe7844ad47caae41cd42521beb6d14fddb52c54699418bc9ab5fccb3c91550902a1faca1598af3bb07a2c35b7981a4de6bbf02dde8904c91c8b448a63f51525e03974694e452b7f7a0271aa90d7df59dde895dbe3787a5983b3084a92b280c8012a11129b851f00def1e08f7e1b06d8f8fe57d3bcef9621a62f4a19f40f8a29f74340a471f7a15842ffabed13444ca871e02a517bde7df379a4c43a47ce87d945ef4331bc90efe0704cd20ca87de478b17a17ce855d0e2456f249b8640f99487000a36818f62fa20d0029b409487c0e85170124ef840f9f09348f9d14320fc16df022781f2e1cf9812367dd834c4e849ef63f4a40ffb08513efc145cc4091f298ff2459c289740f906cc98244c8059288f824d9044f8a49fedc3f6298ff2fd36789082a7a35070cc084f2fdf519e67047dedbb2c53357239a466eecbd48f244368f6bf3fb4b7bf8d94654499fadaae817ea17b665a4042ee1e2b769cb615eeeeee54eb21b9bbbb3b6d2bb0bbbb3bed9ed475d1dddde9bbd3ee717777a7ed85ea4ebb2998e0426e1f2bdcdd9dbeb715d7dddddd69f7b8bb7b5be1ee4edfdd69fd42dbd7ba6a7508adeeeeeeb4ab204577dac4dddd9d768fbbbb3bed1ea7ee9436a5eeeeeeb4fbebb883f6fb17a80ff5c9f4bd40772a1c68e005ba6369aa608623997e4fcb9cbcc008b29e2ea7cbd182df741194d020d3efb1319ad1f9810d2aae6b37d4b52304eda6a792fc89b0e41018c1824cc91c98c87a80e0a659078c18b040075321c3850f828a20a376cc93a209ad19abf10405329f10f94401055e8859210b42ac47c63959e208b29eeb3db58ab714a8fa40062da040b21b1ba440d6736a896206400072828592e0b401d6739d0a20345262591803101a54ecf80a90e060a7876a3a42168bd585ed6e5400f9a660628a217c5588019882092e885aa851b1f395010939983bf68642e18928d89b1e20a40a933228216ba0d84441831a40521548eaea784b8525d1af5de866751562ab86d49953ab983a22164c410c53a78754001c303103898a214ebd8a0e6a9f2656d0413d48b058ac13e4eaa914844f6a202dd9df3beb38e15cf193e9d711488b6907c54368f692664a05a5dd943e118f8a26a5ee7fc4d7aa966e80375b4aeaca1ad56834a9857386f63593af91c20dcc19da1b5187f0b9a734fe3f7a827460c214415de6cb7ded4331bcf145a4c44eb1226b37b45f394ef3384ebbf6692eafeb8afa5edfdd2ff76e6f9aa41d6b92a272e8cb318f42a3b7363abb5d3845ed5b294c8418723fa7b770cb70df88c249a36e4411d4e4f479ab4e75cd19acb0ac403fb81f427d1a7c5a7acb9f5c55fdf169552773325fa61ae68be6bde6e192d61d0e1462763ba00efffa1cf71e37d658e5f1993f69d48e1c5cfe2bb0baaa4da3bcb5d51d9e56555cb9f9b23dfdda83ee595e5471aee277f07d49abba1c10b7bcf5a3ce9aa4414dba7021f49fb9ac409952a0994d775daeb324534fd224d569f2884a6d9aa45e759aa4d53567d01fdb0fa1331f8e558f5415cc97aef372e29266a02669e867aea57f05d2e1cf0535497fc3d5058bb024ddd4eaaa40ad32b9b7825ae5ae990eacba7cd56e9828fa3d879b027f81e834c894be2769b94ea6ee2d57e24d509f9f0fc4e17573fa7d439f1b298cead06da42d201691b6209c656af2af268e7bcedf959369385f66bef7de7b695cbf5faf11739b2eba8cdfebdd741fcb8985cf2c326541a65404134531c9ba6d6a8398327deedd4b9a7d4ee77e7beeb79f4dded8e67393db30299c33e66fa055261d37db07b265229e4b9a6d114670806691dbbec7c9a0b3a733da6a929a3abc83ccdd77982669f204f38542d1ac6ff4d1e49c307d435de86b4f5b3af3a5fb7bc390f416a5d45bd4fbef8649fd108744e670777fa3c13105e0173112037e1d4b23144688e9c23d6dc2c3c84d2e81cc9dfc8388e7254800feccde03e4c60d83a38f650958d9ff8673e3f613ecbf63f919ec862293ac4f2b44012bc2ba91af5bbe70a7f57eafc7b2fbe65aa7f55ea07cc23aa9cbfd8a29ab7af77661586b2d31094beded6fb824bddaa6d5e2796395f8f7febd57eff4f3fdbae95fbcca8ba7ec4f9231fa50f421f0cb09c3dc7b676303bdbabddae84637fad3f454e5e9935cb4f8d2d36f2165a45a350a5ff4a1a77fa355e0d3ff21078feed12afbf47d10d12bfc1fd540194ac2f89587b1c2a3c92356de5f7d2f4b1d6168a3f5c6fbe0e87d68045f341ac3474179d298f2a591f42dc6d2bb185746212660e57e1f85f4ebde7063f917a3e955c6172f8e2a7f1a69c6e3112760fc0a3e06ff0b944f489f36d1ade25ea797f45572fa9206fd97f40d7983396afb166101a87ca8144c180b8be029a21900000441006315000030101007442291682c0e34518e0f14000d829a4e6e629d099428c6614619621032600000000000008090c4910040d5325db31821256c9bc0c212f6d734bc1426cb686ec3c398e0e67b070b87956890058686b9cbac8a33c2d6d703116d41e57f5f5da201f25eec1276888067266476edb21f5a870ccb6e3168c79b3a361317ed071453a31151c6b4eebc6bb8fa7f8148edaf6c9a76ed8f01c691845986c3653d21f95c780bee5b2c39f2f8fb58505e59b1f9e2e560e8ad23f1d17c17888b8375e193ebdcf7de3607fac9d47cb573344cb6c039840b4f93fbf71ae3dede87af40f410b732444f0fccc183014c8bc8cf15da442753082e7a0837d5a3b19311e13c019bbaccc5a823d27e5a154ff7b3065b05cabba6190135c7b1c6f5c1fd200a347528092dce211ac5a932db5fdbec3694b7c9745230e7239ebffded8d6bf7d24fda0808b6db6855a117c44aefa98da10f7327b87f622090298656079f0b777edf9a274b883ea8821a65344eb06ce5f1870f627756855686d3adbc6a5ecb6ece22580765597cd6d4a18b1a2c4a111785f766635124bd735b2936428eddbade1056da6e6cb4d7943d63f4cac94b5850ae36921174f27df2edf574d47af5936ab074ab689de91f640ef991edffd35975e298a9adfa103a2bcea98f48c136888a681db396115db70097832f106b4bf706f5fc3c85829950e20f107ec0a2e50536d1c34ace53895b46ee9d30013d8a33df4a784d5614f5353ef4de7e503c44bd9bf726553b332ba8b3223080fd9bda9ac5eb9d038f39a9cd3cf3a1811b9b10f67607f012c43eb1edc6c055515fb56ebf26086aaee62d0bd90f3530583a458b233798c276ad65f3e53cfd741e1579ad82ecaba11b5d9a7abe71ecfb95f45bc782451808015e458089b952bf6a07ccbd2c7b6abe8e7b33fa57287a730fa50d0f58549668c1782a35ae53ba8f2407db6372f41e771a9c46cfcfc1d4c8a77403b1718d35ada1c058918a335501f13ea03cf121e9762577e8a6bf9c8546a26b3bf765288f6c26f9cbde9a07e149c4c494aabf52f29007500c70fe72b4922a9e55edb853bd5cd73b4da6b3100f719810356f1cd7f0f43782b5317db005cb6f0bdf7d907b35f6fa4ddc2ca79596b180513a691595bae44f3c2099cec9bc05d83904506d526fcf5dcbb3ae1e8c21db09e16515df2808589eb6dadd282a0c76863956ac81cff89c078693be9e3cfab53425548339ade7c8e7d6df95a385e1059d690c62fa1d5ff54ac5d41de00feec181818bd49fc626929240c42bc685d835fc5846a03283302fda2cb9828bc16c51c436dc76e82e2d32ce7873bcfceadd34a476d58772e45315c428704131802f7988a7ba07ca6e4aacfd9e6f80c3528a0c619d9cd2ac15b840813960bc17c7a103f6af642542283c793cf340bc32dd37f402c6950e9bc468f2b9b818defb58c5cdc04ab4b58e455218ea9f82e1b2601029bc08c1d1b45ac07fb75c00f69fc3c4550d49140560651be187de9d97aa778414d8ee3ce1edf0462a95872ecd910a60834815ae4f742f89fd5669803343e33a918098ce086047c1e0d83ee201365c589fe8fa8c0716733afb32ae4baedde2736e635c205ba96a4dd4486e99b2050b8513b49c2415f70fc44fd209b94a94d4608ede00f2eafe88864d6cc37ee22e7343772d828762b979a40e12f79b7406a077a14cc11421d52f2c0130a1e9d88219d9e066455eae88dcb4d3c4e196e7781b39ae6ee1ad145b38ea828836bde6226a13c275169c5942ddbd4ff765d156743a36ed6b45f6ff287eae9f59fb29bd482d9631785ff49cd8629d23fb4f5f0f69a7225047ade4a5dc3a85dd91eb125ca581f87ec02e82729dee7d6c8f79c37cd8fde2300a29cc204a59f5e916d0354f9cd1c8cd133cb2ff3ba76c748b34afb8a0a3333810425f1c6df7f5779298d3d1ff7891563e4f2cf6a43574ac68fe454a36bd5603494422f7868c98e17b99e3f438bc45489258e5f65726f637cb5581cca644bc4508e324de0cf19140a431c209a2056e90e9f750c3b15682e54ac83c308e45922b6759746f094801da41c0fd136ee239b824c50caa248fe0e1828766014bdc084c1475090feeab881d7ba30232cf8ff8a9453c8b3304a3781e7194f424b3e0f5466965a1ed2b674cabc5a03843f8dd081a96b3c3183202802b01ed1de0fc48a1b061b81b6c132c2521a265608e2ede19b73cc2ca5dc2f61e37602d695ff844a0e229ba86b447397e883b2f1997b7464705227b0f2cda5ff957d965c68a5df69b65679aabb18db9ff9c89b4cc1a986336503aeedb41da4965377e1116ada8a4d0c3e7d6fbe9c0f507d7da80a8594efa5b67aa20d5454884c1b0a841ec71ccb5fc8d333c164438ffbef2a4326122e899405c20411c1658b1dfc0e69a31901067aca816fab1bdfadd4b4b68cd5bfb4d2c0e6eb52bd1a23c1da656270671a6488eecb095820ef19243d460355034cb1e2dae27ab875c71b6220817f092da4e6600da93bce3b14cf421ac0c6f1e51f7b500b52c51c14e1e3402d7bad5f918750928da3e4b965770d55f3729a55334772c299ceaa3d3c123482b921ee7d9b300d1dd418c98a7e9b88cad8fe73de51b6238edd9f2b29d9361e41fbf21187b7422174f8320536d66b4fd368f33617f2ad79b105283fc8b4f500f2cfe5a3b2cfd94e101d05df25829cd7379935cbb3b1ac55f0567500008f03e8cc792f955eaa709086fdc8e6ec0bf1ed43a49c07e617393d0dd00f5808ccf05ceb1cee0feb493b9bb79b0bad123f486fbd5645ea9b78e2dd8e462cafb56a09501e58e2edf67461da01cd37fa868918d5215c35d24f82a6b92abc289f740b99f4661ccb6ea1b2450fe23c6f25567b91d25c1030064605e398d54281a6c9591b51a47ed3c6901d8e3d82c7e13b4bfa9249ca39a7d764fe16b5a848404abc99422fa93f6807a86400afebf2f28a4baf49ab0b87da1429794e64c2867d81f51e5f51e07ec1fc4421161cfa71041dfa00a7e27e99144493dd9f474afd15844c362cdf5ff5e30f43665db438f1132c507311dd378c816c47138e482cd01182a8daa74c16ed2179b35239033b66cb6749fbcb719ba175f0ebfe52f1849754590d4ac034d119760625a806598a3e5dce4f42938e87c3775320c37802f8f3612ba708a92db8243fd8c1406b84ce92e7399a433d47af99f3e103b35e083ef35519e40a4268853a5838572a6506588dd0f90b17ef319c52eb7ec70087dcb8a1177166a1a4631518bb1d9539fe8e7c2f678efe1867a9d048ab2ba2f4c9554b6a0d835a3dd1c7cfb794148ae56da02e9b6af33e798d0fea86eb625782845e01ff665bb99c30d7c9d6a0b54939a1cbb5fbdb39126d6c3350f930026a08327342f7162081de721dc2211c380f77c11f5f50ef2861d812dd7e0f4905cde6bb4efc0fda77894cf06d2a7ecfa032ca419f24744b0bb336805d909a5169287868522670ce83b63a675c73893f18e8e496aa5fd1b7c62ccf7332849ca0d4f044cff75f1e6e12905c6a1f209c6ab2f994bd991a66b04e9f2eca83d27f8110d96c5a840d385baddbfb08b440f4bb059fc7d1a273c0844c1117cc57d494cb3716f63f9d8f5cc0ccc62c6e84c370b39e820d669292e8b7bfd306f42ca362ae7381b8b356635f48e66abe676a51b6bb467ce26fc6957074d66ed1d7d0f14e26ede2b28dc7ec05569ba6fb4bdcf1d79d3337c7d4798c8996a97496ee05122e5ccf2afca062bcf40b7a381eef7ea4842a79a5fd96a274f1c595e86eec6711e033e73556118334f96ec0cb7e54fcce5262f03dbebaac9a590cfd65ec23cce649cb9461a2394ac84af57b9b6a709f67074e86bf8e727e4fd45105684297ebc525c2dae7605b286f6cd7e3f5cfd6193d5a73929b1d7e029755175e885fc9e78113907de191ab74c68b176bb4c1f3e340ed71ea7933592f76d7863946669fa4b70872062a76fe44444de7fd9038a15ff90fa07853ac009bd1716574a48782c03ee6665867cf9c99b1b3f845ba5d6984eace854b9f04caf3308b52122d543402efecd3f8d78e26ccb70a8120ce9e5c6523925e168597c077dcae38976aa0e4dd3e0620a8b67154690e4f85a57d978540466211343cb8654b5d4d7029be8e85713bccbba4c5a7f240cbeffaedba2a4647dc526bf00371a246c6df273a65433c098accfdd5ee145e97a93bd3a3fc27347e0825efd5e41ad6924ebe2db3dd15688528d198a336313067f6c300f6550624fa74cd421780d2084322c436886a54fb2a423cd16472e46f3479370825624d0f84251874eeb454594cb9eb98f463ee97292a5828bd918d66c6b52fd4b3d7a545248c2070fe13aa10ac8c057fc6c1698ab5dbea554a75730b18dac1ca6e1155d76e3cedf5b9548eebee830d23abd7dba32d9c59091e06bf59e553fae8ec0abd415fc0a22a6b8b4c1f25d954b2278f4b61bc9fb2d803a84eb822a920159575162b849a6d02a8acdc4aef12bb0b64764db0a7ae5056e8d01c34a2d4e5661d31aca0d390483f51687e56fd137078ba2d4c43d7f957aff8497cc311dc4e642fcb5a8e7ee406c7355c6f3f26aa9fa5d6d5f0a8c2532f8be6a80dcf8e35c470c5d7b64ed9cbdbc86c58e1e5e8cc6b35f223dd5c45b8e2e5b2c81a499bf31d4caef52048032187f3af3f2280ff050927a27f854855b438c25ae510a7d03b630fd265470116b015f80ae31a62bfa4d1bb600d5a72b3831e49b32dee6c537793c871777850cc5be9a60cd3b85b6c8ad2c8a8f9c48755442a89c44dd83d162144b7685dc8515939df7511ea62d87495a3ac9f400932b060c2aa524f6c84a3099d70b39308ccb49e7b9e42cb64e1a2e40ab64528d4db5ea046bfeb80669e2d332fddff4e9c1f5afdd593e94003da45761bd8a8a42e8e5be590002e65b3a89e5df9b7320bdbe03738920970ad8e4853202ea2ea27a22765f425486e544a605ddb9431adbe0644c11e1991e525e419ef096d24691db52ce7acf405e83c490dc3c64da2a76bb6f6e2d59a0b30ee17a054c04815e328d4de67a5af8c292c17a71c39e6912b90bae8395ceb1a97456f494959863d94e109297d1f1ee3497b9a599d0937df98659a0a78a2c960137f5c4eeb769e26a17a31437241c51da19bdb8f235f314299136b664ba416896dea1a913f33374fb4de61f181056ea3862b35c3142b9641afb3d75c17919fde4e66ae9441a6cc94bea55dc9bf60a7e917f7b252a2d3195d8757926be2b4c6c715c9d6080552f763812537e53914ccbf252ef65c1cebfafdc6b7ab1a6f0eb66ed05fba4992c8c7b039891984acb628eeca65c9a9856a67740d22466a92f50795ade3d6ac462e7ea066bffb2c4e279dccf7d8ba017a523f7e618dcea3a4f5f4a0d56588d8036910067213dbe194ae45d51d2d4082606ad182455e8fb0bbd892044ad9aa0c0507a193676d9182c01b42592d7d8a6a337c1a4c45863f585a69c16a2cfd0bfc9b1441916cba920f811e477cb5c2bedfced0834b9658b0d4ccee33acdf6ab0392c28395df20f711f7f3343725d6f16005fc3ff0e4b6e948f69974db0136339f575d649405d583a0e31e4789e9d13b814eefe837af6943ff1f5d2f9d1aa398455b2d28ce6e3501786fac5fcdf47e387ac62514df53b7f7d5b0ad853491b7eb287cac1d8aac80046df432af71988eee24ca0cbd70db8e7e64a765211551b29adfa7c845a752078768344ed777a430f5d51df11038e3f3a77d6b9b8f283e11b3f4761126a5b1b230bcb912d35b234426651f98735cbbd856f481e91ad6642ddd75a13dc0838c2f8e95ca114793d50f31ae3900be64ecea067ec88afc82f06a7589e5d2b7e99757e740705d06731f35cb86d1930a3b8ad689174e91233a64ed9371dbd814aa33f1d3ecd1224aeacf438b8d63ba795139ac1ca005063f919913c448922689437803963c78c8e02f4cca0ab9d3c28348af455bd5ef453c140699b5d1c59aa32efa6d283d10831cdcc54ce222674511610c5fbea724bb1d7cf8cf36120feae9c46fb42a4e0a7f84013ad3a676802a0120603f74b7e18c6e17c18da068054c8131a8c55b78cc169c591a5744b261b04c0a37168e91bad05003a5dec9a230dd8c3f036c5c5e91bf76e396ecfc2742a9371b159d947b7cf185cd6464d9dbb7dcc3d159ca4ae89e32d07eb4653a3f3f809fe1869f5712b52808510cd062fc52a75ba908cbbbb273c4fba4454c8947de657777ddb08d0bed4702eaf64940984ba63c4610e0684fe213e7008dc9a0d122fc70975fc4d18e12b4c8d567b235176169ed5423affce25912a8f654d72f7d6a11e8ca5c4ab30abf614088e021b964f30dacab97e9dac0f740bd10476166d509d4b273189c20d5f0011213f2ee8055350a7a0bdd73718449729afe1aabaa35edf4f948a215a7b7df743d1c71dbd34af7432e9d1179a22fe33a93032f0f673e6fbebace5d3262e335748e0905568c19b8bbaab62f20d61288780995278cf08920abba3e0b8f704f57e24908d86c7a1f05aa21f4a9acaa85f4d9454ac5d3ef58d80007a1291ae1e2b5c95712edab46cfcd682c0618fd900a264d90bf4006640800fef7f693e0e21655e96a235a0464957e1f2158029e3f242332f205c437ba002ecb9233b611689d4b1572728bc9b2a54a7ae524021b964ed9054bc0676c47b260abecbd1a495cfcee554bc034b13eef69576be2d98ac01f5467e02fa4d45293d0f14a09f84add47740630a6b05e8184c3e90ffad07cdc7af357ffabbe5441c03a8e8258613fec18a85810d0408fcc905e01343e87ff0cc282c67c857135f72179280bac2f1a634bc420e0436af101641dd7e4d4dce63a06cd4e717c19faebf72110300c763e7d9c5ecdbceffb84059de8b84925adb57cb937488817a19a7504d3bb82804d4e08640a1e5162b01d8a7da90c4d1dd18c6de83167d15bacfdf6da17f8568afd3b94105966b5d36b8263ea673640dc9e67d261546a087d446ce3fa019b8bdaca8bbfda71f27f5c8d6725d929594ee29baf8942f137ba517d416474b352ff76ddd7e7957a03a428642df331142b33accf3a4619c66089c806d848ad1389459b58fed954232cbabda45221f906f8105e4cf420e11de26fcee9c597615b3fecf3c641a1a48e97c95312387f8b4e0dd0156a51b3443e72755a1297257c7721d5a96927b297e11c96a5309eeaf273440dcc8b4b969cf56be7d6914181b107bdaa10f81b6317a79064c7555544c5044696751342d08c1b6424d210516041466dd6e3af47e4173be60b17e85c27e31da9f7328016f7c63e25c0735d0b08cc872926ade70ff02b5092709a3d08d5286d45dfabb0951902a20e400103edc1c18f51045f5a3e370583bcb120bc2ac27b99ea0f923ad39bfb78d6d2dce3f3c50c21cd1d8c053a137e870ef1ae142f9f68bd567b9eb0c162e1e00c50518351a3629005159ad466738955e2339a528c676b0b71b93f6c7ab40410e7e0c7b4442c507e7c7e9a1e3517ea3aade02dfb0ed943a8e5227e4f9ce252fb373c0f9e80f986112aa9c008a09079e1a45e506ad953a2069392543437e12352b51af941bb6daf5b26e10c4c50a9beab62b0bc5dc0ade6b944f7af61b73f4fa76b4308d1bb6e8699d20d510295f1d06d23af4113d588f62207d7bd150a754edcfbe4c0e28c540e59084e2daef7c307b01dc9549272df3b4605e183b2cb4f54331162156eaeb5ac2a2960a535454d153fa49af94194c921f140732282c0cfcfbb038b85096a19763a3f52b606ffc44bcc04f0e1084a627f4013283802f9875896c33400e81fa9950d001914e959e0f1307a216e33144894c014ee640e995ddaeeb195cb83cd3864be569ef3cede0869b06b00a7ee26ab36e90c708ba48f9ece423f9a66163f8216da57faab78fe65c23f5bcd851f1865438598ef927160009ed0558e054d30c8b185b3c8ac273a01b9a64ffe853e5531ed299fa0905788db763fe2c8ed9868d78623afd1b6600ee5d544d2be4aeb99b07f906bada903568bb214b3385f26387fd953c4e227faee6aa35fa4e8a4b610c8a2ec53fb368b9e4918db8892bb2f6e3a4a7fb06a4291cd58a26fb6d91128ce2fb8390aade555c83bb2c29a03d041e33aa65e291567fb2717275ca8213f0f7c56e2087e24ac6740069bb2e02f37882648ebc0833a6948156bb511776c67c02b5621b1df7de7c7ed966e7ade592c2b1c3616718c406357fe4a91d714712ab460f537b722f334af49524712f2d78c11dd7ffbb1cba75c0ad0e3935ea9bf42364c4118075b0268faaf5b61254514c0a6e693e89934c892b82be6b4ce3ae771a802d688fc16b1429155df7f95a33550c3a8cedfd3e6be56112b5087b66a7465982aac6c53078b3decad970633f7cfe5355ad78453f3b791d88d5116ba0b5ca7480eec68aba7642eb3466772adf514607bba38ea4fdaa36b107982602e476d769aef3757d85a455ae88ce12f105e70394dcbae6d8c6b6f79116f1433dc1fc0a37c9ed1ae62d1903ef6fabdd69c10ee354970f35ce3e9acdc2bd389d73256ffd773c55845ed82d9570da64aea83a53217bbfeb5b43458d0826e26cde0797986214c0139dd076be78377c81b7266f398b455f7560ce29fb6aca3bcb801e86ced0c24ebe47ecf41f91b404f37364064c112975f5e33ae505bec1bb2be6421a7ae2cfbd3ad5f4d28b89a7f925a8646f8edf56a0182a38f16394a4920bf426031ce30f5d7e3aeef3a13e2c411ae7cf089d36c53ed7a57cacea805d1941ca8961c0b3965bba6dbd3e71bdc1f7f91e651a9f0c8acb5f66fb8106b80daf43dc10230449e9b56eb7d4a00b838d5edf151b396ce4fdb8f9b4c3f728f379a05ea623e9877119f29c91fd13722086b1db7c7e9d63a6ca800e0590854e51b7d2319fc2695f5232d65a0200091b47a811255001c2dda1917c8a73f0f7a29772f74963b90e39a8e60b8d4018a79604c37f54ce2162b6553b2dbdc35898f288c22c25fa1730748cd9fd731d1672a683e2e816675df9dc1041c4234bc42d9fc0445f38ed6c0a8757b6bf64b32008f8c045b071d564c85fd3c8415a61348f9750fba14b829d5177e7c0e29cdfa6bd5d589fc1d14eaa526d095e12500ee30313541bab14d8ad2a1f24149eb7537883b9c37c521aaa86bae83f8e192436224b9026a0e2f6a89aa4640818766cbf8c5cb717f1ec97b056da6aa016df844a4e26be9ab62ec7607fd73c5ec994c3e1e61a40d0055924043612a950009a37febe918336e3879e90b59d703263d1eff31cb41be528afd1b523f520c49081d1fc796977714a10cdf317ff6c36a2930566b5d0ae7de20cf638d96070622e302553b05a617ef704a5444b763984f552fca11441d6a3c6bc0a39588577a6aa4fc8029a773576ff27ee990594ccd2bdd6f9d31a81f3a8e0366ac01d111f68a50313b9c9cb85193d2f95212d1481f8e41e3acc25883b7f1705c70336ab64d0631fbb85485040c200cfc8c410128c743c198a375e950768215fb3c6e99145a7027329241a10f02f72514bf4942ffb6353356c08abcbb7e156b10940e85d6265c1dd214897c06682be46647639e1861026c9acad9b63b5035d840b1023cb934e1a7377431b86959b8087ab57b08e676f8bd095e8baea2dbd0a7b520dab63db279043da3b8d5c184ef0635f554eded86dbb494f98c4f7b5b915b124e26df2d0c64dedc5456d4d35c4012cc887a0a8ecb84a8cb591d09c6407a9e90aae76db6d05850c4a7505bac74ad53a830aca5ba1f2c32d41cc5ddaae041bee068c565d766aaab05a8f6a2981381e3005d8e790e47e43baa07c7b720c8b8aae25be25a6838bf58540914d9424e49525a5ae4c198e3b149cdf4862c88c210b774f37466d63dcefdb841010c71e8823428e86015d6d346b1455fc50c51df200932283e609616dcd93d615704697b04fab3408f8360c2efcc9e0dfeeb04c2e543d40a341029c0f3e8218736bc0aa079a578e2f409990cb459824b2da708a312bedafcae64d5e202b4b2fb4f0a00b326e6326651e19207dc530e1e2d09be55e463f013ea18509ae2c014121e68d4cb194d00f86668df8ceb068f93b15acf7dddc30ce95701949508ee8d0e55c2fb49fcd1475ffe074b3cf5abdfa5b7aee7ad381d42ed45d632d98ac3ffad491285e9ae2608ecf46cf5fcd0443938ffc1a5a1c4d49f83ac95bd138ad5cdb4eaea7037345557ae1c0d255528059c10a8fa067d1049b287fcce22ebd7015f7f445ba974091fdd1da9e6f691668970467f444187e710cccc5f77f224094b48dac848b49f65506a079e98da82580606d366ce3555a5e6b90293b675271914854e4dacfb2ea2de58fea5730e216ed500f18c17f3e642f2df8e88c8ea1aad576d081c58b866beb7c7a5872f635a4ce156558a98eb8512c75ebd3612b8e377fc9dafba22c6e5c2a88035fad10eb60e8872a283c1f80c200126b01f995f4618b56b924c9139e01c6a7753c37bec63b948615444429980e505c422b4f658104e03a683eb80055898805007d79a608f7b2c15935d19b008d663289d46038b541e0396297df638afd580528dbf85e3dfda15f10c70705fb0b3f2694184109e2d5d25c9c767e247c22e5d2513a45ec02cdd21b2ebca18209aa648cdbd02b20a113f5a295f772eb30a1902245fff79142166352231994521496fd8ab1ec6a8c00421c3223290a0c562b5549a04b18e0040e472de7ecfb792ac3a1d813e9db44d39fccf4ec464425c056c99fe0dfe9d625ec81e3291039cf5323fb11b155825c6fdf561f28ebde728012fbb01ca44e6dcc81b38d66bb4342aa543ca8356eccb2b40d8461d04a600e27be1530575704a8b4e0c02635c96d13c51b10026212690d1814aa065a883d7e534265bc27ffeac1658c2634ab5f4a854ce36247158dcb8438ef84bcc70a262c77f0a3d854b1085181e098d693ee07c2802ea2f10ecdbed6ec4204a071b12c3fb10cd62d28537b5349654b04a2de67cd446527eef8456881c6f02d69f8ea3f0b180ef91e07fe1d304fc6f7e91eac1ae76e92311abe834311e596fbd08f830185aa2ba001e03431a95680531e67e880bd4d3af5144df9ded5f7a4732d23b0d24480138c47ec913d0b21bc35fda48ae107f0b1e21fb1bf02c0c788840dc64cbb2ba8850324c954bb59c2520ad25d74047d5f45772c16efec36a569c489bb058c0ac54089822b8e653eb0bedee244a5d4333d97b0f401b23d51ac03f950cdc0255994c2c6728b6402c0f03944859c5d364714333d4fb406e93dce3dee7b40feadcc10636f2add1a64c5df50c56b1d3446957d60cb2de27d9e1b8c9f921fe1f4a44402dadf969e6f2d03e434725424a10d596f2f0ab21d589d624e64be67ad6213e08aa9f23b4970920c70358ce31f3367f92a0f0dbac4534615308fb338cc977e8428d0ff7164a4b05298d6710edb4a97c4eba56d031fcdc6a0b2e91e82ede9de3ca048182795501610cf32e973ab524781a15531b04abc0a01c099a8f258bac6035857e4b384d9fdc899f6e2addb483b3fa7960d39a41ba7f0a0a809cacfcb6e88f42351cef124187bd9a279ce6633d1f33c492e5790357bdca2f4ad624aea9661add86fbb037437e9dc61bc76190c6df23f4a6e834d254824dff961eaf962085219eb5babcbeb77522a55a9af84a5f8d7ceaa05ea58b3f9f59bed095b67de356d6cb6d1fea54daf6d98109514688ba6780de41d7ed6fd04880d3d04f357e5a8d28450975c8f987d86dcbcee8c8077323ef2519d63a421461b3f6d75f5175d3438314e35951e3f6e9f1d8053ca9faf458df846480a761e2fb93bc1fe86fd1635e09954e3721e913ae1886d8d94f97f46508de682acf28e6d864040a2d6311de087c9511bdb4e3706a3eec9a909b6432495593da19019721fd98a22a2f725391e9749ca491d1b64ee46bd4dee46bdd775d602d95d490de2a809c9bce27f1f3feb754bcce8546fd08f78027e646557ef01c41ea1dee1af1392c1a0361e716357ce0cb7b696be6dd79173b60ab124f1e61386630bcd30ec2553552689dfeb12ba9d411867f5c7c4c6a445183c3f6526604ac56afb061a881b14b4a7b7dd952a1c905f175410c149bc0ab9671117a4c237b2a344ec77905823138778bdfa25eafc097e7ea618f0b6d3cd2629a020a0de4b59a604802ea744c07bfaaf1288f083b50debd4f62d66092cf88baf8677c0ada54e81c6de19dd578f0de37dfc8dfa7d1f3c851f978b5f4b42bd8c990619fbeba4e6f3498ac946b1732c72255946000dce8742730b3728837066602a7242cfab7dfd11472f369b3df46dd3d13ad19987615102180a822887f97e32912f299e9c11bbc8791fb8c4b6acacb073a2b159826589bd3dc5e8cf0eb53d844ba78130a5ece095b1f0fd94c3654dd501dbb6941280a010d776320913aa789e89db66d721ad3416239faefc11e872360c3bad5d16c3d9491fe7924dadb6a1c6f44e66f4f836ba76f897debbfd48381eb20502eb19e48fad6abacdd95747a513e8fd3cd6274c2f20cc05d2594d0396397c8c16fbae7a7123e4be67ed6aa24abeba1e1e43edafd0753f0080a4a11c469bf712f575faaddc07929d04c399f38528be6a3f4306df394fce2b6531b7f8f1c0359f7b968884fabd24d4dac5b9ee48edf24d07e4a1e921797c31952bed34065810512b3b9485ad3955af15f1e67f595d0a08525003cbf5fdf7e5d5c527137a39d92d8db140800b93aa1b20f07b4c5aa3d3df61890b1cb7e6dec166b0df6bdb0a63d5f6682a5390bc9c5af895e869b493f865eaa18e829058feacb97ac05781e439af54c41ba506c4433d6341fb24754f1a224762578c027d4997e7240b08081a5be4107e0e7592cd0500d636f6255a7b40fcc88981091a8520203443f32f46826b29e11e3246c7a82205c62235af7867b91605ed7865b2aa16d62bf38cb05a689e39d01129cb3fb92f23fcdff7283b68d80581c7b3142d0c1d56b2b29ad5093d00a5cf746e016a5be797dbfd8a01527c82f7906287fec8d91f578146063c94eb637ead774f2c8e79e024eddc5f7a5ae8c80739ac7390dd98bbcc7936290087b71a1385d13cadd2ee622993e9776b8db6e5521a7ab892b632e141359cd868b1071db241fc2dcd49259e0ef27e481bf9be00bebfde8c97353077bfa69d12e3e435cd143194adb8e1896b7edd69a68ccfba43f1e38d96b406efe85606549dbb5cb694146e9f52f1bca0e3ca3fe19d751f4baaa08292c0c76c0a17b21e6fdd04a0db12d5ae5a75478775ee4aac8cf72ed9539700d50ee1986eae2409cd7c3da12cfbf57920934b752542d8ce6f5831d9d1707d12a2d427192ace7ce0b37b2462c69b9d5633d42e3c2d54ae7b5da689b14f8e84d01b5d588b370f8a4e04f115ee51efaa69227549777ce54ed075bc3d51f139182b469764b9185f5c8883e11dda65964d01e54d8631bb3d4944abb4b16b212ba2f6455e500495dc5113d28148b46be3f5e2833992fc0bb416e441e9d28607b72d89d5a526ad2f91521384106bb1e43ff3a4a71935c139d46e94e71d7ee572c3a0508a7aeadd323d876ccd9384c1e8e102d7ca6d97da5e8e57c509094a52b3c234839047cc76c06b20861e4aefe4450a5d87311583b76bf849634c651c0b158c3cee05f6c641aaea5410d924f4bee0e3d0aff83b2e55420e2abb5ce26460f0cb261fa0530320c9cf7004ca212f4ee04486a74e493ad33a7d8cf1dff278a82c243da38a123241865fab718f4d5cdf43ec07762481d6da09c0f0c6c69464849bc2c826f190cdae0a177e80fc764312aaed274e636c1b23b67227fc6e9536a31a0f634fe196fff6029ef89dd4694886bd0965b6878b37910aedb185792ec5ce28468e95807d11c0c39adb98f87297403cf8664db0cbd55e3e00690b5a444603bd01b55a04f2149556b481f58d116f068e50da138c18f8006373b965eba8260583c22f2baa953eb86bcfc7b2d6119d91a9e0d86b94795f01d17b8c419fa50708601c0ce651cc75e1d5ea9c6340d2395f643baea0ec81f173fccebcf57c187a14ffe8774de590962334b3a9f149e320a886843c650e4ef7ca0bfcf9aa1f9acdc989acd73bbab1fe0607953b42605d9dd3b1a4ca79d10cfcda726600f7531db4442c34d2968d7003d6d98f4327deb0e4f9acd448bd83e97c8038ba7d81aad7ec13756fab171f83778ad3a38965a87c12d80d53f36f7c5e6441e52da15b79a9d397d8eb1a8a95c0565b25bdc6aa6526ca2a168bfcd34432dd20091ea9839e1419b11a1b5245e85d08af241c7e1f6d8226d79470570fc436f7d116e3b5882f7263e83d12d7bb69faef5bbd68319368bce8357302a8630a803d1fe89c4013c5125e15155f7373aefd3a788e87e1cadbaf034d7e187afa8decd62635d00928bc783c6076b309871c0bcc28896b42af533d8993034f30383abe7b8d673b2a81a02a4422975662cbcd26e7aa06a495a43ad254582bd802401259a95bc24d7684f1df7de8ffa7cb443e04e1f720d12cf384597fd2ac759376d78a2ac3bc7554de70a1ce349e620bee7a240488a720ca2719d0cd52db4888fbb38d0997e60bf11fbbcbd6976a6d796bd63b38ecfb868f3f6feeb437b7bdd8b71c9d1031a1929680ee299bccabcadc4a55a883490df389a8a0d6d6762649bcab0ba7d2d049d821dae6331a3b28d5187c5afed7c21ce99d5b01f4a2153dfaeb68823f0c147c7efb7e9dc4caa1726b5e5dfe4cacb3f9f567e64a2684f2cd2a309cfa346d96cf2d0fa0a12321217ef181313e23a6b4637980c3c56c96c865da1af3d148789e18906f30a6fd233702d4381c8fbdc312cb1b411b2d5b7f71891a943608620090a22833f232f9f5deda8710cbdf2efeaada4d113060b2a18ad26c0e7ad42ef2de048c739c5580069bd35dbc8c7234d48a4b7b66852ef3bfe9a938ea4431626219ac89f5ee0093786c957e4eed0c8599e482f297abe329156d2482fd54eeba85b7b32ec1d616ad236511056ade5079bd9edaa3585a737882ce4d839370209a01e682aacce33fc8130bb3d384c496b5342b06b86ccc4d0ce3a9d4ed13be31d1ca88b9e05e8db6e04068cbcf4328f59ed1e181865e1199d1c749ad144ef8f62135fdd994202e7dd434c464d0d3169d4ffb8a3b58d2850a79042144f39b9bf8bd8f3c3202dc43d8fd0cb9b6a1c0352bab00eb8bbf4247f63e79a382812a60276a8ec378bfd0feda9b0aa55142cfaed07cfcec1841eda73c058039c879848eb5fbeb953314e320bd1efb4e5db79833826cfc37be4942af1ba9066083838fd6403035acabb308b075bf43acd12eb0b8968d15516450e3cef4e4a276ceced81e2fff0187052431d3accfe062ec45e4676a935d7bb16b2343e92223490a68e208ac04f292e413860dbed642f4f595f93275c7199066689f37cbdea570150b6f93a44c981d2d92b918592cdb762a1bbc51f039a21bd527bb8d3dcf3d2d4637d484eeea26e491f254ce82b82f429694fdee245306df5f3399bbc2992c9c0254fd87fb754e4848590476dc70cedb32dae66fff3dd20ca57048070c8dbc14a22360bc5442d3e14cf430adaabdf0aedf75fb50ec2f02db5bb2f9d4ef3188412f4ee97150d44cc37c18f0bd5f57ee8a376cb8e768612d829a03c473dad6a9651cae9fb4bea2c4b2baf377d88d2b1496c24c25227b48ae983d3d39f6614f6e5f165445f9c892b8f602307a4044a61fac9d144c736c0ffab5a40be92ab4832efad4713b9fef024ff174e23e6cf886638652e4c09ee1d099a39f16b50af6cc8aa80c56edeb675d50563016b5d5a6c3f0d790acb48a839958216fb980c4048f4b96648f370f3ccc4bb2237d9f602c80beee95908b0715db92ad2b85c1989704bd4b41bcfe6bbb208990c73fc039c74092c3197f1434e83a92f54af67a23cb3f4d82b9aed6b33cc92f9a3a7054d42068026cfd790e3f7a0b924de1de639daa7284c6731f51e048ff65655d37532647617159a31d2939052f11d04c8ae6a5b968e655fce5178801cffe9b26ca5dc63264c3ed5cb6dd39a12ac0d88163f662f4b145c879bb90f07f787f3777ad03c37731948bcfa5bc3778884d417ba7b8b57b90940defc0b0d76d6a775807d7a3eab14c53dced5a35e0b0ec19076cf4c1a7fbe6738dc905498a54a57c9fca57ce3bea6a709d81225b2e052e9a962ee6f18ad96de70231f6bd6f0f804d9ca5b9dc7323bfcfb5752769362db2ed9747ec823a329c08baa2d3536a996b2384986ef9da0a1690bd8ca782c8a59aaa48e3b3c02985b50b780cf6208484cea56e3f29a7152427159c802046ab15ad675ae6e2b44bb9d20f5eef1013e3355363dd3a1cfa9284dd2d5990b8806c32fafe2ae2dda9c93ea8f9e85a80900d2a1e916f2ccf053f62a197a7752f4fc067b2c556c8596874147d40f3333fcbc6332c11e0c06d8eb069c2114104243be40643b934ae34aa7b1c30deeb718ae21bf254e9d2cd2c2f8bab79a5cbb0c0454de09ea03029e6b369b27290d5212301db28179f08b73a6ad5c7b3cc8494671f2bd02c2a666cf9b32ec34429c9a378d960e9188bcff999c1070c9ef8332c64e2d17f4b9b0c09dde168c4c1cfd1f73bc6e6b16c74a1a9e0ee340e2ebc2adc551e7e914c2f33c816d2100aa17cf46647f688feedb53ef5043cc1c6f8f481083d404099908e763a33205a358fa7f30bf8b105ffbf6ff249bcf1325a6fcc9846ce0e92eccddefbfc2f0db402d3db28daa4117b09cc220b429bc993ad5ace8a90b5835d9f1863785379844299165934e08486d29b78f56c3d30e0605f26bcb12a071b03df86891cee2025a09a66248d9ff2bc9e8ca8e0c20259fff63fe4aea4e2b164a696b1f1573e692d499346986e94329cffa8ed0c8d05a5f57e1de2f4e6a30c9262a4ac52fd8b97c8e9df6d3d0dc96d4418cf53a0114987409a870399e968081151510d6c4142abfbaacd1a3281d377109d3be2ec848afd7324cd0c139f6da990be2d9cd424e9ff976968b30b21eb67238aa552becb1bfe239a7b6f9a3756f3f6ce12b9f8849945488bad577bea9caa83ab531729c7d72477d799bf2b70ab7945fd75a5358c18a2a6bb80d94e38a77005e581704133f621e424fb18b9ac042042acb8da9f31d9e088088601208b715328fba07ac7241db8c2293c3a1779b3fcd5017e4a61ba374e5d72887e2a16c0f809ea013688e02a7e17af8d1cec34550f74b931d9242c5c6b68b595f1ce457abb13f66f9e2f3909b21cb230b6acd344812b3574afb5f92fa264ad5edafe37c8663f0cb6cc2e8acf4f3bc27297f14b71dc03531a35975f4e15c84c12ae9fa894c5141e97825145b2efb5fa4103c463d65034737dba107fb124bc0401ec658c762f968e6acf88a1cc2026be847cb6df4a33044758712ab71d91b87f7dc955985616e57bac91bbbf309cbd5549b429f448a6dc87dde1968c261f40e210634c134f578f344b43c3524eb9001104c2cbd8a668986ef6b3ac98334a85b13ea13135cddd01ed144811ef4516912e1e9028a8dd8843f84842be9220180cb0429b03a421aeb6228da9dc9d8d0b35d8cfd46fde9f0b1f2903684e01eddecad2843cedc2c91dafc0a69e9f573e288771407d28bf04b063ef31082fc38da84bb17c3bc6dce9400a9828fdfd937d31a4c02f612f1887463c0ff51fc53ac4bc4f75f946829bc865bf24173bc21565442fc521e22cf20904e1ea0e6423d031b049348adf609cdd761da2039a12290dfaa47d45fe2c763c96c80ddea415dea1666ef64ac2e2e8c95ddaa22fea770d36efe727cad17e61d921c960977c14cdf19262c6862dfcf09a49a766c7511d49131fae1e064fa81cd0ab2e25e3a3eaa46b260d4cb8e46ad71161879491da146a542e9b52fdfb1252c87242918e90a3671882a8fd42e6d70dfb293fd490cb8845f2821a791c438b83054f5c94dba76d46b61f65b3afa6aa5698ed4b45ff5fc10d69ab5feeab16f3e857c390cfb4351f401ac4ae4fa06a73ab3575db4a877f5cbe6c17d6990bc2569c2337665397edf2bb34e16894cf233384efb7f599220d5fe247712d013abdebb79a63baee42aa6d8eb8161b0cfb8dbade108c29dca5ff1decd7b12eb0452b6d638c59f2b10dccc95c81da4ef61fe89417a259e13e4327da78d7a255befcca91e135f5d8e3b529165cecb4635763a0c77d7a5fc7242f05d7a4f18337f756e40d1f5c725a15bd1e85f2a8e80d55403cea1d121eb41a9805fba441e789a55d26fa5989f6e29c87db7f84f88144cb014c0a7d10979c685f5d31c25ab2c45ff74a343aebd857d42aa40a8a5803c8d9bc81e1789dfc73376a6dead9dfc5c0a46e18ba1ff649a75ceb50b3ee7cd5134a2ad9f79a65c786df9e7181b52361ff3077eba7fb68b8514fa9aa98fe59924e2d0a7b3e78356915e0f5a790eff0a5acf60acb42975caafe24e28f99d0e0a967b37c493165af1305e09b3c4888fc4025f8ed10e69efbc8ebac6c21713927377ca2a4a1d1d698e4c1d64a421a8799c736209a1d1dd46bcd8a994e02781df00941b7392d91168266d1e073e430881f24e74b3142e3ad56cab59f5e4d359193f79b09b23d370214d559edcee9a00440c5d5ef18c7148f10cd0a845b864a9bad4308eda6640f99061ce856ba9c6fe55906f0ad5dc8789337c531c7b2f2d2e9349f2453df7392d98f06b2072145568fafb9e8ebc1f19ffe69ac653857370036ac7fb11f373263b64957c8e9e8552ca9d966455990d75cef59ed60e33a3b3ff55ba2546a73b8916a614f9e531f8695239bc5534fb1b5247de79a8579795f1ece42fb826abf7ec54ddc81bf7ec2c2a7c8ccacef723e3df3c7aeba1b016eb6cb6c87353adfb8a2afc8e8acf9035ceec162a1e6b76dc2c224cab1b293476e45cda02e8f1f2d35f1f6fb752ab06f1e34d786a536c2906711fcfd29de7f1449ef05c96d2a73d8d2dbbdd2deee5d0ccee2e7b2f2fd1ab95834b98669eaf039145a0d6174fe85a5c245694e9b4877b904656c6aafb8b0bca9e8bd43962dabc885680e7dfda6eef6b8cc25e2cdb17d060838645303e057dc573f15a41eefa9d0539c2ae27686c22bb986c42800fe617313f678be82981e8e0a11294503ceffe5db8dee5c17624241601ea9700c5858287ded5be24f05ae5412ce027ab24e22b5e888543849f34e42a09cce0746160159186ba5da51afdd706e625766834a628c2d2addccce983076f3f64b17fb3467f0eef18a1d58cf29e792016f71e383fcb2df61936ece69a6afcb7b3d8ecc84bfd214d79000a9725fce0ba5c6679caa3d021d7ffb50d80847dc31daf91341e1878b78caa56e207f4928413c481f38db8a1f44beda91fa632d3e7ae62fc2b36e878c5cb618b0d14af23055dba6d0a60fa40b6b1aed7bdfa6fe16d36c856b900c4350ba4c94b94a764c92b894a7df093242dd54faf731f7667c5bdda4be4005a34aa4b62cc443599d5d014e3c6fd9111a96c621acfc8ad6e308ea766d11f1773039b1dc46e981bc790bb9bb9952eebfac58a5448b6788208a86db7d3106ab2efa24735fc5cf84b6c13d31b4687dbe4da89efe6632fea2e1a341bfce6deab7f1725115f82013ae2753770fd26a8c9768b95abb889f1b2600650e12634da4d524edc699e21c39690b61452eac0bdd8508bc08c171611354ac65d17ec2fc5b6e494c7c94034e0815c4e8141ad9a61c38b06ce54d3f02d3126450d22fd5e332b1777bc276f8dda7999f6658f04f98f9939fbf343732644317fcd990842372e04d952d50d9f7cd278034f336be9398fe6f522df18e3a1a14c9414dafb01ec47c4575bfbe5deba37492c58df0dc815d88aad37353a9ee0d083e9097947d5b5cb7f2301b2674a728e1e5f10a5694ad6fac04e07fecc38e9d4a49e80df558c2ac46e91a92b8170474a2e672bb38978f72328b1c8534b552ec70a698b7744cdcab546e3c7a22dfd44f704e3512801ac4aa6e8ea2a69e53d8ce7a5e7b0cc984cbbd72d45328317e086ea09f8318a73036f58439e0ae00d930d4a04296cfe93966240e2c071b6d6e59483ed1d3429275023d5c44ed411f37a187cbefdc3c796c1f00e93d11b49fef424a89c188d057c0da2225c22c1e37fb5f41412f95b86289d4df54f28f06c1092126236821dd2817584345309a90b663832621bcd10ca1d958c266b11b12c167c041ff00efdc7280b24b809618cdc2c85fa25e3d70453d2e8703a0156cfc9fcc6d16a42b0958367c902c9d2fa3574b02b1db7bc62fac81b0d4bae744105aa6a6d651e1b91e07fdc158c3cdb94bc770187d9e5c00f9afb16246d97c02d0b15c065492557794cb53fde80ce93f3019869bab06e9eb7a48f652a90527426b71c96089bb1da2b313a308dd07615a6d285a7365b8031155b3a47aee47d417fa26676d3a8c6131f5db3ff72319af179d9dcfea3dd0be35c552dccb35e3eba6785d357f7f063a4f084ffa62ef7f093805ab2974bf74723d4df3b7c570af3e59dda1ba2bdec118398682ce292c251636dc3cd0187dfe671bbad8bfc4dd7bbbdf4f1eb5bea951306296efc03e74b673905a200462f6a555874f720136a3b15bea913ed439b80cc3fcfec2c64a8f432943f395a17e1b52b49ff1573052f12b8eeba42d7a8efc08940cf46929110123caacea6731149ef05d5a1b88e7a67bef0839b8fd260c284292fd6c197639c8befa6741d5e99bd50efcca53e32527d191f8c9e21a1291c5d3c244c60dad9f064b64175214374ca6baee9dc92967bfbfb87d89fd4b7930ed3063ed31ff74b1fc4cb05a82b382aa7ce2464aa6ee0a1a1023986ec4f8ee24d963b9cf0f830296d1dd34c33123c123b81dcdc88f077406203f09101d5a88e2e38134c708d2c7032dd41bb2c2b38e5ab28745d49967bfffd4f5c4faa2b91096b073eea77f7a30fe4d545c4299daa53e5a4302b67e0b071809d86f04f46e135207a4f49657effc6436547165b0e3827b0fb817df29572b1787d446bc5d4e8840fcc943430d40d4d65c01f3acbaacdf13a517a2f49e5bfffce4f1d4f16dd1b0ece06858170139fea8ffba60feaf502c4941cb55325328a919c628d748ddc0437afaf27811dac5d15a970f76bc00f8574e9cb147ce4d0a61fc36e9074a45f831f0e0769aaef48be184f4269578cbe384244e4f556e3644ebaa6ce5435c0dd72e1c39c7ac5ab3d17d132df78fb65c913bdd563e2bac3f7f7ebbee18b7475917865466d2a92f41fcd10306a50b0ef90f989286c15e4ee0b49b9efbef7b7ebc865a5824102c9cfc18986e022c4465f1fb958cabeaa86431b5f673009a8e732d6b45393be692063d8d2d7bc3ff3f25755e345cd020bc4574faec0f2a22bc3d1cbe6e7e02682f185d19f35dc9aa85e5882f1992622857d7f2a96998416528793756ec9584c3b88ee38cf40dfc9eb2bf79c48ca78efcd236547a8b045189faff8ca6586e9de3461dbfebd0ffb0857c1a61e69bb3002a60932c84559dc60191a06bb8882e8ea1f0cd84ee06b44f538c8ca7bf3bd4f189de8b43c862b1a740ac222ea817fb33fef1b3e28560b125372d44e9548cd545cc4636320d0bc287f4e496e7d93afc8d3c0b272f18dac8cb7de784468a476038b63301f29fe1c406c402c72b034d4d10be4040f9c914544a6bbbbf1b4ff299d636466ea1cbda8c84a0919234aacc194a9c6d79c4065bc2199507c1a6d4d09c29aff0f121d0689004a0d75e845314b1028b682111637c1cf378b42e2452ad15aa2c04f4d6727add9fd18f043214d9a925e1490acca2fcbb04a9af82c69869704ea715ef48b222fb90f33d334e97da9e5202f14da85215d723c6dffba94bca07ee543456a982ce644a15bb8b8d1e649da899b627ef08561467b5f06aaa1a8d37473d1f369e299d5d378dc480f28e53b6c3b40d9d0befb6d19153c0e3801944421609177ad99cea7c2f88e9a4ec546f9f8ab8a73a85bb178a3aa8af6ce3b90665e78d1651c66c56a16c5e79438c1d5f4c0d03393bffd607266af2bb696d78701d6888b584e390789e1a1ff1edd6d6267ad85747b1302471ce97627b5d4eb49fd7cbc49830179192fdeffc394265516e536a7c9cc20dde2ce4586ca0858bad118b19f5c24dd400341b231cc2b6906630cc2c38a18a0c1d03a4339440c01d5c0a11bd6f10d8139a320071e96e3e344ebe82cd9d1af3d95d5dddc951b7d7515bff66d5a0838600d1d725f3d81ce1f4c2c272e6f7c4846703e53dcd26d9f982a4aa15443176b1c3bdb3a9769b7dbe3905cb28da1316b4c124908ee2892d99b5ee69fdbd43ca2784ac0e32dfb1e2fb720fc9518952a5c3e8242bd5ce4805e1b594c1782ccda1a4db3f42a308fba4a0d33aa9a0a17659d840266d388331880f12a0edbe3559267a5f3e78453a35df8a10986ddfafc9b56847ebc6b47b91e1d8f9c81eab80ac698c9bc6dd8fea13a9e0c5a36d68e13daeae3fd4b60b48a655dee21fd3485a0c0a122cc328dcbf2e5d636ed7a4383260b2f79f10fc6da42c56b30b870b9e0f16b8db8fb3424a7ba9cd8f252316418b45ea1ebeaa32af6604a511cbb803be9149eee1f72e88e082aa312d7d2ec4b06d0d2375113244aac2a6b24e11a3622740d1926a842e6aaaf995a5c721c0779f8f86625ca8f42ecbe7faf610af5984bbd564432f007b1cb2081884a38d6fd724c8a803db26aa84db94aff22bb41b2cc83bf5d2de5756926bbc94c425db0deaa7b276dd2bfffb693d07d1d9c651317914cb293b0c27d6d4a4c0a9e8723b92d49a8a1a469c14719c4b2d7551e524c2b886dd86591b6b91c43a6dc1e923aabd02c341094a54079a33549ac449a7aabd3278286bbed4621e11b8ff797cc283e6daad8b517ea272571ea72b8a03d71957689036748cff24e64d8626f1e3e5451233cc413c1125392b4e62825d4b559287d69c77bd610b7eed1d6b3497f88f745e25d73f3376af7ec36327b262fca0a603b5afc07f7207df6e515e34d52440af5f0d00ff961ef8de191a16e27dc91e99214e6641771470442aa41b9c65c46ed66cc1aca6099043e0626245587ad411ace2420c7c787ce46ad3acd8653f964b9b8b16dea4738daae6d30330a514bd8180dc0081f461fcd4e59461c8bef180c2823691c7a0d40a301e8360a8d86a1d90874da400d4275165fa3550b5428ad11e834064d03a1db08f41b424336f287ce86d54850c2d7d2634b04ba5f24867a908e3998d52b08bb78e5c383dfd3e474a93673a951843b739e446119090189769b16a92543511b2766a137fff72bfd028e36c05022b3b6900c3d96f29d2b16f432e1a814a439b8af2f7a9aea3b6191fd8185ce32052eb038c346b2c00e6400d2725a4463608d7365ce6c90b7ff4de888d39aa119a2956536d2704a0e6e452413a75a744c8004dc9e7810a833f1db9807b737210445d71d87d14339c692a45bb40f02a502b3fef7dd0c38fcdcc528eb6a3ea311b66549246674fa95b1e0e1d0ed8328731be6ea8f6cd65cc2e5a9cae1db65aada2956a32e35e62200c33f8312d34f8e36d4102265b2d28c091fd371e0a09a28df4701c486bd949f721e71ddd49269ee98b999448dc9f91f6154d69fb69ad728358e861c4f84f7f54299366dd246b3be16318e514bd53ec47405f7f9ec47a7ae99fcec37f80b8a036d61949cefb997b89e953dd3bd1ef7e15916bba8a8e306aa94ea84c301d0e7dc90db4ca4b7d6d5e5aab3fd91ea1a5c54b1c6478701453f41137b60ef09a5f814824cec297881c8d792c5ae076deb3cdf51fc91a6e945144669b83c317171b6d13cf74eb4a868a587725472910bd5b8dc07b2699f623a52fd68313ff3a1addd91d47e7d03230e07bdb5ef0650801093f15f79f17f54eb5788c9afb094fcaf9cfc9f5a99f55f7cfb8f93f1bf9bf4ef7118fa2f2ee14ffeb8ffebacfb6a53d64ee1bf4892d2d29eb61fecd9efdc5dfb2fb5fcbba085ff2f22f967d3fbf746f72f5d98fe8bff3c5c6a1c84fbdf7f056dffac9ebf4ee83f89b3c4ffcacbff0bc7c8ffe2127f9e9e7f6bf4ffc280c9ffe28bff332b461ee5b70477f67e06d532c62afdff950fff351e2bff8b0bfc3ba9fea135ff2f03642b4726867769ceffb555ff637801028f2149fe8b94ffc94b77ff756cffb319ff8f927e1d3873ffcb96988bf6e4bb2e751daa96055ff437e2485172b570b8390667923c11a470f0a43138b3aa0cb6780ced84fecba669a7d5b5abba67adfecb6bc201cf35807584d9733efd695f38db7f69efea23a5ffabf143a7a20041786f138cff2a77bf0d1338e13f34ffffe612795e15d532ba3179ff45cea1da83f6538ffd656e2fdc070fbd1f3efcd7447a345a11bc7ec1c18de8886360026c16b9e8ddac8d636a8b5ac2f5198eb64102a9f73fd1d612830d738afebcb5b8b139a1b2b5763fc4850a6d3ef297f39727a25003fe10021c2640ea88fc6f8454cabb38c6a1336542f2479ce890e054982b518ae8fb0f26ad64ba94bf1bc7b9062d889e8c48fdc1d6cb4cd1ace5189aeb1f8f611548d6dd315f07b3adacce0cede3cbc7f56f51686169c8c8345ced23933772bbabc6aa8722e82567ab8e075c0cb230c1676fdbc3241a7077392b756727a04d5164f7f622a00bc5a5fbbfa3b190c2a66bab8e011a2ec6c024023cf9b2d186d8efc9b4f561b66a40b9443b3137637962959a904244a7d2da1c3e38df8d071e6f4252e7276e8ad7d38d37998461cf494fb3ecbd9d13d5d2dbd8486b6f095d430760fb6937c7e5608abcc1b3f94fdbd93f83671bf8b14c5e88d6171fa6e2693013dbe64e3ace79a7db541f8222b1c770112adfbc0669355d5f685b42415352abbacfab5cf97454d7a2b7148a981b3e866385087b15751448a5bcc2cfb2429068627825a83d62954aae6c3bd53d8ce6033baff2d9283f01ca1f45f47cf2a7edeaea2632e3178ff67fe3f8a3bdb15a77fcf745d503e50d9d0e3f89aa3089086324fad7f15173b342b6e315488d4751896202bd57f41b6980a37b808d275d3de5486217b5831f1c63c14af840c41784b5112a45ca3f7d20305154541030aa6f618f23ce28fa168185762f2e41c4df0f14523351aac2ef3ebb3de6038f0077ea60b897c420ec1f98417aac5a55b48431a3ea078d82b1109d616637e5cfc522d477bb794a95f1082f958a60c48c4175f2a95adb4c215ac1fa1981a858f1cfc3d2c8b8666da2e3b6dd5671e662ec03c7418bc6c4212722c9d1a72b7638007ce5983ce5677055f051b6a5c1735c3117377886d5ce2ad20ef98da1bba3634d638278961ec2cc45cd8a1cccb0c0ddc3fc3a32c40d9a4f676a28690412df34af2465e3468e873d0229b7773c4e7040f80dd05bdb0b0e53ce94221ed226089df6b87db5fc2170d4d822375affed37a6436d9d8a6b9046d85670f148579040b58ed67d7e5ea39b3061031298237e28a041b36abaad5e241619e82ef8a74081f6aba88b2c4460289b0abd75a09bb6d2187ef81c04b5adcd9d1b91f7917422ff18835e1e363f338fdb16146644a138c386f0aece3b082241220a35e07f0b0668ddd689c7879943a4b6d5db8598ba312a5e30d257129a22f902ad5991ebe95563be466326157a91c2d53253f3fc1976431f88a06cf8715a528d2e027d3627e576d79ed97a3f1903dd69c60efa7c528453d9518d120df88cf306fe415b5dd5c05d204378a61a9a7729042826693c5c4021002968bdd3d3e0a890cc0982486064444bf305e77770da3f3f91c10e55d958769916bea0be5b78184601f530ff2e70f022100394ba7d11c9dee6066274fb98be4f896170aeda2befd84d60ffe9399cd264d217328c574a3561396c9b04dcc2ee2586a1382828b8524548f2dea58201733217695aba9d6c64fbf0a46796172a5406659c7d91a9229d963d6240a81e4b195cd45f09d5366af3eb4f402e67edeb5fc3a6881336ee9d2a6e2a5664526a5ac804bb662c3ae41fba8369ff5918a71ec2909ada78438fca6ef91b65fc5751da6ff449142e8e6bd3101fe6585ccbb93bac737532c1569c435a675396a4f264bc3c5bf186ebc6d511e47684455550ab8f344b19a2b016181cadd35f84d7507bd0e395d158681207ecc9f03529a1ba66d94405fef13966af3583167326dc8dbfa7de8c7dc6d1840a4a900a35691cf83cc5c9dbeb01331e5393f0cd37cf0553a7c75f81505024a1f466e038fb73006e792ef439a5e35c9d43556362b44ce3035bf9e942cb8fdc9818556bb4bf6410ceb9e91e1a2b1a28d815408c45d7d8b389a96d1cd2ff3a519725a267775f2946656c684c4ab24da62064a273f561d4654e54c4c4303bb9aea87aea3e2d7953cdc719fedde514d0e3635feef7a37151ef404831055139e995d84bde32e18dd1bb4ec69a800153aad0d25ee44273a9eecc28e015b2ae539c14076522f8145f14e21a2df408d8c417bae7bf5d94ee51e2ebe10421d8351ffcb0b35694ab2b5f564bbabfa7df47ef63aa100eb72b81e6704e2090328e5547e94079dacf38a65887350944d56661ba1282a916a6225d1d555fcac2713597121dc2e8451c97c23aa49934125608267bb78fd339bc6b436e259c23d7753f511cc4d1805360bbe12bdada2b08cafb878025cc5c72365b15673ad326a0305e675557523d09812af4b54b352dc39cff278762cc33c2c200309cf3f73421274100259a1c6fbfca5707bf27ac4f1acdad89e7780c1be40703bd80224afba6c03a57fd2ad61d6a1fec9ccbfc57622fe10f189831c94c8bdcacd62b27cab7b3925ef5738a85b6b7e340b367cf9c62132b0989837b13aee8d8fa0f548eb3adc519921eca814e1bbca41952b5bde79c7b518db9c4fde2a69b64b92fe45185f34620eef22885b4a143fee4ece91da5cac444bd517d5833ba1115283b3680267ddbd659e89e02817bd5750e28cea29a4a65f32c66b01b9ac46054b3ed41c9dbd007b149269d58be88581349485832bb2b0b111ee302d110d3b1fd528070f52d822a76abf10375e19f1f2e1f59d2ff2f31c850bafa32f27242d70bea093ab7745110f397b754e267c7d2fe5f7288c5f517d46316b759d11cd902394faac175da31651ec85f96e7799134fc81c3142cdc0214e51b4a47529cccd2d4e2203da294f8d6bfca8ea497a25aa4e027f4335597109406304c2480e43a609f00ad8ec681ed3d736028402db8123b30cd79376cb79506b1852059380d48db2decc6086bb4d6345cc8d10bee2d78af20bd05f512482f41dd4b211b2407d46a7305d5094ea2bbe921e2454c0f385f2726f9e31334ac2a9a09b285bda8e4a77fd1b642417baef274b342a7686fa42718967ae3731d9d52b44b769e700c23ad9797590d43174a83bba25a29a56373ac3cc6e017f975b7897e17868b70ab8778171446bf2ad0c7502c3358f9bb3612b9074e0524f4b4a81d241415b69f7c417a9cba34f01c4896a65e2538cb4916ffcc63a9a4ab9f180efd662571999cdfba1e2fbb3a784424cf7511f9b61607bc274a88d7b02158f7d1bf058d18f251eba03fb2c7cc1934dbc61a0cdf5cb2236dbeb4f3a88c285e1d937e3e10f086db02b7e4fec9a1cea1d15df3845efb80ff64080632e31a29a27bc8d78370d82327f58b8aa04a8a9355a5c73e5544845b45e98a0bae910bc1fd25403b7418ebb0e2510e5318f7e3a8e72515f6838e93a468d3866c512c347fd765ed519a3ef123249540202096706d9225f61d43e164757d4de18ba39209bf47b1127302b72234f226a6cfab4e6d06a3ff3e2d9d4e17cc15508a836094ca90ffa3582cd2257d0358041408a1f0aeae7f520064449aea8e4e1c235ad430f98eaaea53089d878ee9b844452b7faa6d169856e911bb87028a21426a4ac7f4bf37f40d5dc62c287b0b091b77077762af0ac3810f11d9a5b290e8163ac824afef3c6ce5b13e5bd35620c28cb0ada8e9fb8d01f8e397e9a510ba53c3767c0b9bd3fd61840947d11565befebe8ee8846dfb44c5d6178ccbae4f5d2063e81958dcd42f0dfa88c985bcece7ffd9ae1b99a6fb5395a7227ed323e7af75de773c0a76848aba7523657b84d605055c43d2a8c3bcfde7d7efe8618c00e51544aa2f023f8ca90544637d2d880a699340116210f4a89b168ea387eb6405b9def464e215230c927a108b0f63ee6cf872c609b2ffa6a4230fb468fc2494817afcf27d44ebe84c4aaffa63dcba2024b86c7ef5f1435330a01a0eaf7b0c4af2f08d0068d8a157dc868dc3b1558712d16fd27d547216cb21be1a95c638252de0194b08abc1cec9e30e958489e4543d0489e599358749d936b5cd9421d5b2c54ffa7203f7fb168265be6cfe73ff03221994b9683cb4ab2615463933266ac9af614e9c320c9b464b2e7e5ecd114014c655c455dbf28f9722988d5aa12cdf2f62262667129dac08696a9f06f12d622e0f173fd2454d4ff384df033b2db8afa1b6b039bf1ce91aa835866e259a22f51546c9feba8f72d489c112e84d85f37609dccd187c279c76bcff5ec25bfb2e1b59677702503c76262c127a2d6d9699cf8c02e294ee0286556e77b42a9eef585368bf7432fabb7205b5b2bcee6ddc9adea628d3fa21ba1a3dd3b4d3223b9ff39f30cb5288c80d540fa5e110fccf08aea1041f6531e5e13a816a26c9a1bf2ba18a233fdf4a4571742d6c226fcf36a34b33da7ffa44fd4323436f65c8bcab8aa4d5e690a369b46ac791dcf1ed0b67aea91ac7666f07e164dc812a17f043894f0d45f0d9897180a53bd57772e1f3a3f9b834a60dded1051a29595e3a6b9ceb2c77dfd2c86e816ba2b4e88fa1c90a597297aec79df4e8d1fb8fe93d41b40945b0e37b33618a0714889525789298bee8b3705a67e3b065a7af8abe61c273d98bfb51f19dea9284056c1c9c534263826f7478b1461d50f13d57077d9cc4c361097cbe10e649e319a25b18d7bcde92e4290a483d074b6d985f106c2f953b1ff7d3be445587850a64ce898cebef46fe70d5e78fc96db29545ca02d93c2378446ed31811a0c29a05f8ba908f81a957427f4f2ebb7348fe155155d2e1985be0144a7c8830cc0101218079184ea7bd2489a8d687c05b45952a711c81b624f500d4a697088484e40ad28ee783b3b9b21230807c99a20ff4b8f89d8220bb25428d81d89410d4096332f072555675d9aec3ef6afc119cfc41aa312bd19c827ed44a4d26721155b8d1d97ea5eb087a2138c5201152f54ef099e4f1f562c10059c5e895e084c42941764bd58243cf708f296422687fa1eee479e02943cb7b5ab4e9e2ec47371e95da452f0244341988a3d8ffcd364d6dba8cf139818e658cad0d69e7a67326f89f197ba6801705b26e3230c3ab7f9f59bba1ac7bd56e8e6ee47ae5e48292e06d0e8a17261687a08ea99c5def24e0fe19edf7494ff01125d41b7c95df2e8305d217137845d71f3508b1ef55ef5131140cfa0a12bb9d27b1a18581fc6823b33d5d811023bd34176f6882ba28a090b1e9d52d680a35d188742ff61f5617e83eed574518a7410607dd0c35676e1f777dce5fb85c9056f5345e2718cec63fee79b1dad5a213eba8be1e2812bc74ec3ad008192587f66d636a9be1a2a7657f6eabded6fd62d7587929253c9c40b718d9f6210395b35d4aadaee2161e60a52fa9a43632e5dcd8dbbd2027532419d397145e5126ccb07f79488495b7d863338760a723fd2511ec96e803be24b74334b60ceebfbe8a7880c41602e2a2d09bc87120210a5677140f240cfa6ba085c8f55cd51cda1caf79d560c4071585107caae29939bf165e1e6caa480dba8a0bdcd84501ec9102de7f4707b78a0a04a2040ad89b6ef0433706d85408e440297b2dc33c1b463489757dc84440e92e6fd71e4e3eeff92eb0363b038a57b58cf7bfd6fb80cdd5fee1ab128ff5815295ec632b20aa849ca859123f294a604da45825f7d35e8d458768e02e07ced61cdaa14f8923c43f4b203d3b53d31f3c41c20a7954630122b0f1b7db020f7d69c32b541925d90a986b2db539ead6f48eb1ab76143a23efd1ca5e202c106a67eef7cdeb374de4ab7514e3fcbf80bed755eed0ed470404140d2bf4ef22a7a8d796ad73f90f85f8669001e473aa51a6e2fc2b9b83c9efcaeb6e80402377b2f3f0341da3836c6b81643e60634f9839c90471ee4770b839a3a97906b1098e07c466547febac1227750a0e6108042702baa2efd35a6f45a3b8d5f31f37b206be43da1bfb58f68cb78ef148a2abd7a94d0fb784cccc30e4320fafd68af20259e89ac5d63121a09586aeca020563afa6920fe980afe81dbe7cdce64efd5a26da613783d21c64de3a5c5a85c33c320b4b371996e90f2167edcbbf91aafbae8123c3c206899210e7f9895ff0f01212274fd3ffeb88547609391646685352fb9938aa31073da2ab9e8179e9f9015d30004078ead143d5acf680238ef1aff4aada5576464d0a2a6103d5f0cefadfc5737832561c1273c25c37335915a3229a7eb22a706d2ab96016a4b00c387de2bab98f2647016e27e9851e6ecaa5d7668e69c01f701b4124e301faab7300906a7bc8ab41cd35f65ebb2af014d99ee9577657e5deae4d241b56c224beca5304e45cfd49f7cda075b4969d59bfabfb74728bc1b66d686512acec72f6df102bde91c43e823f6917928dfe51591d54fad949ad74b517c957d51b950b8a8c2d81d666381501ed04034ca54b27f5aed46207c4a37bf33abce4a6ef4be59583ea5fde507b3122e00a548541b59c06195abbe13313d42ab8534c8abd54edaae2a22bdf105fc6c011a9541e3bf070d0c434a7795c7ddf5cd4a59ac2836cdc022c9ae38ff4137ede955aaa6fcf0de1540a111365a945062e02782abd83522aa397fab8e13f37bb7e40bd02fda7d8efa8e0a918c0bdd00db1dc2a2a670f194d59118aac0f0d389cfc56384767d843344d51e07c098eaed011578a5ad3d8d3e3f63d729c0fb3334a805e924c51406f46c3db17c20f97ee1f5c7c950c3b9da87677c83213889c4dd4223f3ea8e55626d06093824116d93a77f06995bc05c031c0e861708d43c381339c4a4292e12201c75e8f07c30a8e714cef8aa4f3afb14968157ff6d58ca8a6da5afe694f927885018b28c458cb01464cfc3388f665be63562e775cc7180a5125f16db9f110dd19fd1bfa213e333d12c091dd70b541b330907b72b4d4470d36b7de9b4c2f3cd48a34cf51249515635d539530e94758827bd069c2a017444b8d05063e9ff107577e7656f82e2065a3dcfe3340c1b612f239d2a39550849e90ef8f9fe6431331d65929fb1a7c88b4ed660f92ca00d309035fcad9167f895a9bfec940453dc43cc02f7fa0ea05beba7a2aef6fcebb9e3aa1f682202a10e5f4c7f7ae485040b69c7481e06a378cc34b70a031520ef6ae4043a70b1a78b11b03a99e1566c87c170e9dac2c6ba4e116c3bb2f5593fad87f5097a0365a53b20aa650da7c222a5379280e740faa6630e17d9c534d10a7a136f6ba2a674ac43ef11bf14e0f31e94b65600d6649371107e969d7ae9e3bd8c4d36fb49a1b0fc480fc0a1ef5a8115e1512aead377ff7214a0e39f324c613d05784881186ce1f2c18b95ba01cd847133595fd9230187ae79a163e722d31fe1ea51bee6929078b36582ba94e26b2e81dacf5d7f81274c62f6c47aa2194588cfa632255a7e19af219fb43bdd64661f57698d451967c12fb474e47b03f1254507bc8955a57ae18e32b1021c8ed824edf047ae5c9dc70d6e2db92240221f82069857b93d053f7620e3897441797a78e5e0713ad791e6ccdb468d50b01c3ca8625089a650bccd85c961687011822b22886fe02d6a8002e43b618daa4fd81692acb5027c673f637d2c6fab279864c823b4669e99a2e9239cf52c2e8de61214cf9cad6eddd65458a0a367c00af2abea716e82e34081dfbcf4b84aaa9804d2b5fbf42cca2e7268bc4f50ee9d2c8077c1bc84d966fe726075d70aa74c1fca613b5f04bfc5ed0fe0907febafd244542e12090e981f5beb3fb7f6e20e08a62a96c12d69c7c409e50ed8292c69d7959ae5094c3a79ea6a50a296ac3927585ee3a002b60bce09296acfd563c9d231193090e070adb6af62fca4de46a2bc5d37f7c93680fc4ec184a3593ebcc616a5afe1a4a81f643d77742ca44b44ad3433ec2c7dd82c014c19ba193c5415286ede77cb557d873bd765b71f6f06eb9e5a6d71714c137ed1c995065236a508ca25b12f99c894fa63462ff4cd9c31b5459a5de069fe9e64866296336b9446db6912aa23b4cc3957de74aa6139956d3dbc0fbfc4fc4e2581d3af5f653bd6222ec3095abf3ba38e9cc83a638b1148b20bd2d140cc729fa7aa544c478cdfb49c97c978ce845b64b6b88fa13f3d6a261a88cd10034a197c735b6d2a658181a391b8b804aec2d9e938552e70fe0ca28a583cc35776d99e07e8b221d9e85cd85fa5b996be241771e4d2cc66e7ce0efb3b8b89c462e65ca376c169b466a23f18503c6b7f55c550745b693da3d11767f67f984c93d5b58d90d87960485cf7e32d9e90697873b7cbbd0369cbcb40d515aa95a7ccd61575947c27599f1863649215be2641f30f367dda0ff14caaeff7b45033ab2d92f1b9be5f62325d5479b7c2313b38c67ca9c6af2c03b91fad138077bf7e0fe7d052311d6a37586b4f830d01d7648e20a6ec20abdbb59a66f4efec40ef047b23bd4e5be9d42b959eb7e4c7307f8a504298a4726953a49e1a3c82b1ea02a0ed407ae63d9583d0c625fe5ded12d11e623bb102fb5d0d62e2d4241a2ce30b44d4a74c155f040437796446318e4eb359fd2eb959b64559a947ae35accda2f3515e9885d83150404b146f51952ad644099592daf847e8a4aae2af8e4cb5b13b33b1817ec8a9ede5870f18f0584f23a6036c456a3cdf41622b56e6131c37db8552421167d1c49bf6b1484e08e54cdaa62dd960f1cbe84fdd2049afbbbcebf4d3f2070bf610eaeeac96f82798979aa8b85d5bc80e63282020299462ebd3da6091f08931876902c5749197e509157da47950130b28bf4228e1f4950f8c09b6befcee281b87bdf0a2f2c513eac8d39a681b81357125208fa10c04c8c90165f1fc657aa0c9245dad2032f1cd528a810137d9e9e8be90438bf86dea29482d6ad9f30af2ee122a33cd017f9e80ca918c03caf202f567569bc66a5d90461a0e8ceb13a8f0a6775d9e97115ba2b80104ca74dbfa06122c08606efa8ad56bf86b59d944f1401f8f2dc5cb89dfa3fcf628f464377bc3ab0d60f7e579f3ab6c30f14ecf7042f9802e62246be8a3bf83dfc9d635081408c8455b668cc03f8e83ac4746faff3aff9bf1ab59fbf2694c8475db4e75a983d0afb4b5dd255417858186d1d1033c06bc41fad1188920109cae256212a693368c038e52a7b881473719ddc030dac6f8f891a2d00f1440da4b84512ca0c28706197c11a3e065490376826c0a2a66d19f33a06a5928dbcda9f4d74c488a6f44daa43f536cc65a11f049b8c4292f2b1091ff12b84312037fb2987959ca47f9a5444bbb1fca29ebf3813e7004af2d59dd01f0c45bc8027c3da320c402943465acdda630936df4e62ab018030832d00f3b6f7df8ec0a249ac4b272e4a005560028d2e245c7f5c60957ffb88b5c5b78250e0e0f48a2051b8d106e7ed7534e72f91d9b7ee880a2f008acbdaad82a11770956ea8a6f7ae85148c8a77466ea0e19b1f7bd011e451133334cd9a24d42cad6468acccbbd4baa1dd7c51ce8d6ee9b4eaa438e4e1fbd084c304c55ee3478f579cf5d9148c06871b9c6acbb60f76e54ceff11e07f93233e6926093c322ddf88046a3f5a6526ede3a70401fc66d3e4ecff1c09a2a904dd70f345990584dbc6d6958c2bb7a06321e63879c4312e9fd41c903e7e6d885d5c686ef25f970762542b745972fbe09e10cf612a9e6b56d171557381d2725f800c4fe76f5560f9ff9a8bd3af3d934e65da33d2f294df80fc71f9c8bd7d537b2363ff73236e279788c872af1ee8ce2d2819573720b995ca3873e1f8249b22e88fa179a1561aefa9057f693a4fb4f22353778f5387dfcd9d5321ff2a58344dd06abec0c25ebcbe23083c75de0338554c756db432f7fedadfc7d133b96388169e23a7d1d47d7cd7b49bbc13d2b3f65fa6ac2368fb95cdc2394f934dc10708b8e3435e5438f0d618f882ee9c2aa8ffc7ebd1ce7472c93ccc007b955f0e3c0a8837021c66ac97091bb1062f8ccc574b6b78d9a939e8e8c3bc6b2288c98e131863dbff724bbca94d46378324165d87eb5d3a0862d37d5c4b35dc32c7750f922a503df8010e08d53d186d5da7ee6092b0373a06d95b2d31c297b037d0a3999ab3ac8e5d2e6181bb09e446c8abd219f7bda45f140ebe4d69706d275dc7cf83ac042b35f9218b21ea5d9557b2ae8b4b88de69b03924452fd6008cc74036a818e805c30d61da7036e2b2a8e388b3729257a04d5568413120d836f7fe6e6122a48445a24a49d2751048aaafd841265d853e57c3d7a6538c3795a10e2e521f2821550590557405ea2758c95ffb517eaa48efec57f696defb626a59452269902af072508c2073b76ecc861661089535ae50a35bd424e0e13a794524b2337abf4975eecfc69942e193fbe949d247bec72a4fbf4f86e939b33012c8346684f0f570f263d7a7a7ca087ab874b688248e86c325db387e9337dc03825d76a679445a3238892084f9df464adb7d64b2bf596c998a3567faac54d1a80013187779ed13b1afcf35aeb37e7317ecf2836a5bf6fb5ebbd0cd0b3d0184720a1fedd6def2579f66507ee506ba58ff4d94e70bddb6fb507ef97bcf8f4da7bbdab79162b5d5436c13f70a29d9e76fd767baa3df5404ae94669f4ae7f718aed52778944fbadd731c77dda4559b69d27a5d3dafab69b5d90cef3a9243995525f765546dda9532adb3f69b3ad7549a694d6ae3ea5524af94e65ad2f65935aa98c5426c589094e626cffeee4c7ae35dfe8cb26fef511bb24cf7eb943ccd12e6572879823beb70726914dba1c79c4e6ce9d9c54c88410839021342e933b3071c7416684a669cdc13429adb576cbf12dd6812c493891040f7890af0726c9f7a5732fd84cfa982547e638a9039700b9be496b800845ccd1c9b71dcc3f1aa18839e8d74f12b3f8473d66d1e4463bffc855ef88cd4e3fce1d52ac3eb13b83e28280e383465059ceccce334bc62f0c3e5705065fda6002617b463b3f850406bffcdda8b27aadbdf8e184ca17a6b779d373a04dfbcecd3f5531bb140f3889bc117224753880632b897f36588063f8e42d79ed2b39ebece9243442e5e3bd8081c1df9c0158c4c4bc8c8c8c0b172e5cfc4e8681992e60525d8b984f753b19b7887916319f2365bae91fcca35ec838150a8ac5e9d7efc60199912981e6d2bb3be7a4b4567b372bbdbde74f6e6de31a735776b777d4677a634eca52f8846cefbc6b550e70f4403ac53b1407a45fa65f86058bc8a25128ef58c4af29e55053459c56867ea0f0b46458a804f934d9328b5989f2d3c39345165271e273b4a5e686a68536891fdbbb312b517e664f165948453a39da7225068be24cbcc7288b50189d7039ba5243058eded750811bc86c1c5facbbf11078ca29a734d5c4dad22d3511a1d56f9a2e667fada60a5c6bad35cf5a35ede705533d3df002b94e981a2a708cd7b11cc28c3d3a8c0726c93ab9be0bf2e6d2c41c2f9ee4b4adc334d14701a610b824632f028dc3887ff2bfd293b8e979fe18e0f9ed369a57ea2810c16b84460503cef671b65e10ea79aeea039aba12e89bcd8baeed9aee12f2f45aaebc1b3a3791670f60e8d57cf92ec81b09f46afebc21cf77429e17c613302ac7da38e6771ac0f8aa10624aa3ec90d01c7fe84e412635893e6cb83d348e0da9cc43e38ca0a32bfa28fdfcb843e3683f83348ee64d20eda3e4c5ce517fb290a791c689795edbb7bf6abd5bbfd2ce73d3cceb9589a6e1f86207387ae094b9e6e8ddc6b1a395c19a79aa96ce7ae7f6cafd1685ba77bb3f3333ddafb515d8b7d7624b9726b048eebf292b741ce1f81bd7820a598b59729f380e88fbebb0026baa2a387a272ec84c6efff0cb09e6babf50b38cdb8b26b04c6eff3e2d0626e605c79cae8d898989a9d48529fe8c8ca8d925d19fbf7dccf3e60976a46dc328edb9f91af7820e186a481c904a7a4ddb6a1773c7bc6dcec15093e7bff88182982be95ffc408125cdb75907583be6b8b3bdeb4d6fcb52fb5e2caf5f7f7184630f6884264740deb878fa35c8246ef3d2e2e947fa2dba1fb8cb41c1c890c5c37c4c4c4cea77728b0efcdce27107d290f1a33a161d184932df1c867916dd8e8c276d1073c03caa03bd28c37c8e8ce9a67fd86bffb0e7a26b16fe93093f877ffbf69be92b0ce4c5bb3732f6eaa933755c07a6b2a6f1c0ddb67928a7af8931eed74edbb6699af63bd93bf0411ac0984daf75dc37b7932577fa1cb9798db1941f3d0a1c49928b20f968f2c023366b9e8af49e8af4f1643df04fa50c6a0fc45f3b82c43f66fcb23b3dd6809c4c5c90ed8fd86cbaa523d60699e5fd2336df0d48e9a1e0fb24396f0d7d41cc03b1ac426e1d84c0276bcd0531bd7fed4c7f3bdf4aa4fcf2a08bc62f1d07e4e5b5582a953e48e7d2efe4dbd50ea421d79fb2beec7672f529620efc39f2a59bfe693d4fdc774a06eeaf7f9b0d476ce3b826ef88cda5a7a00d32973c30e6bb1d895d3af707922297e3d70ebcf314670b342779d107fd6e5eb98a36efdfbc9dedd577e5cda9578d23feaa6d647f31462ffaf0cf6d3c4ff0cb327a2d43fde843f5c283d4eb98a3630efbd68b39e8fb178bd4808066db50a899997f1a1a2a47f9660ffc6c63c64f422277066bc01b2f3fd3320625f37d945f3c8bd7e2869fe3384e2b956660c4e88f0183e370b76c926f60bccf7c2906251323060c6f7bad3b163f13bf4906597c8b162d542a954af53bb95fbce86791ea77f1a273998b0e09cd294fee1073b0f81cd9a2ebfc6e13f32ef311bc37dbcb74b7677ff6b31e3893edc378207ef1f0a9036fc440541743bdf07bc4df8b712ae536502474c6dde904668ccc44a9b971e3fb6a6aa847287eecf8f1a37ac0ce0d35437323c71d3f426fa116f21474687ab0e647761b2a926a77a87b0e3768beefc68dea110a29a79c31bfc332c53cca24a3837a9922a637bd4906f92761fe499774b5a40c8b169145d7bd92e9686ccbc7a3782516b98dc9c358bce25f51c4d2954a1ca7c9d3e9f4413a9fbcd39b4c27ee05c604f39223711779fcabd9c1e3478ea1f430cb9732d6e24ba89794c4c2a31e8f1a49438ed46a6a626c4b9635f827e57b1f5fba94ee21f692143c2e4efdb763874d38c230fe1c897175694da37591e5f3629c4a3dd7040cf610adf6efb776a5e6edb0def43b2cd2f55407d0def443b437793a524aafe395bc21da9bdee4e968de0e8bb4752d3decabf81bea5e52adb5deca19a0ef95ae4caf7b40f43c4b03a29d825bfe898a41c50dd5c5a126c460ac980e45042bc7743adb1058318f92f9984e67039415f34b66102cd4cb743a1294302fbf93f1efe4d3ef64d3ef64ee77f2b643fa9d7c7f27dbdfc9f57732fd9d3c7f272fc13e20c142fd64027717d56dce427c98970e77584aa41b99f8d04e7ad7a78c4c8d297ce043357065a7edf402138392993232d2a38c0c95b5a059a896ec9fa2462e5ed0996aaa54d2a38acaaa4f6d529d549feaaa50eaabbaea5015aa56ea500deb951aab613daa5b2a977a546796c7b6eaccfe5828368afdb12f3bc5c2eccb16d92b168b2db2319bc5cafc731b83b1b99c34bebca16d48fdc564ab71aef84d0acb67712dbe257aaf5158100d8768ac0816140ecd8e5ad575a73895c96454ae10b692bae258b83c3d9ca293561b8661185e97cbe57291a88ccaa84c86b6719cc9743ae197f9f2223dbea0326dd11eeaf2a12ffa738bb02c65f4b3efa8862e0a73b95c2e5750384463b468e34ca7300cc310bb5c2e97eb616250281919162c5aa4662a253da662666c16c98c6647afd7ebf57ad559485b61188621eda12eea435ff42706f57abd5e2f19166118d6b0865dcac58b172ad5cc0c8c1833460ce931064c9e3f1316f4cda1d9d16cbd5eafd7eb5567335667b35b64343b72f1e2f57abd5eaa3aabb33aab330f460c1932febbce4b61a69082f498c24beb68f64c1f1b7bcdd7f7fda75218cf9f099b41339c433164bc5eafd7abf35248818666c60c1a35668d1ad2638d2d2c6a49594b1ad9d8ecfbfe53298c3da77ade755b9e8d5d5ba98d4d7f1a9adb73792e93db735bb7c975dd5396aedb92a18b933159d42d797361d76bddd66d65ff1917e6a69c236fa44baefcafcb4543baa4d4b8249374350e7f18d2255dd2e56a9cbe5b04a3a0028f3b5ad380b2255d470a70942d1e8df417acc92d8bae70e6afd8a4d55e7bad2b86337f4d5a6db5d515c319add41dac015b36e9a4d135dfdddd678d16e0f8eeee5e53a305eeee8ed3d7895643081cfbfb6b0881e3f7c7d86005b2c7e6abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb1b0808080808080808080808080808080808080808a81b08080808a81b080808a81b0808a81b0808681a4143e50675220ab42827ad765a2b3d5a49abbda44922498fa4bad54b2a69dbdc36e9712b6da58d339df0c4587ac426fc0213839a2894f4880a8784ac0c855762e1ec680b97a319e5a1ad594c4b868749f667d1d3a249f64fb95c4c172ea44717ada02954826042214c1ac92c528b349232b945cea4cce5d3c4898f0bca6b8642feb99c4372ce7925fbd319abb356e9b1ce5007140cce998c0946a9542a915af9e53f0ef3a05918866118c26030180cd68ab55aad56cb8b5ce6463ef3230b83c1603058abd56ab55a3164bcbcbcbccc40cdee91b7bcc7150ec58a6461188661e872b95c2e9794c1fc0583c16030ff719807797865188661e872b95c2e180c0683c1de633aa0e01931611c8ab158248b46611886a1cbe572b95c523693c96447def21e77b98f75b95c2e974bcaa44cca3ad50c0c183162c890f1ddec3ae9b183715d1ffc4afd3c2c7ff11acd8ec2300cc3d015ba5c2e972b0ec56291cc280cc3300c5d2e97cb25a74b868cef3acf4b21059a1973c60ce971c60b0d4773369b61747ddf7ff489aff813613128fc19a6e0a540433363060d1a35bef97dd2e3876b2e0f1ca686e6ecfbfe53a9d935c2b187be5e7366677346e76cce999c331a9a2dd257ec68704162ec6afcd4d8624781f97141e216bb15ccc6b461437ab4714daa1748397e94a75876faaa91ee5d446337f531a7313ac3949bab1145a3c179cc6d646aeb014af0a16a41e61d8da37b60ad221428734a2822c0f35f5082c8f2391f0c7e710681217cb032c5103e589182653d9510fb3bac18ca8f3df2668725df7649b464f93a6e83c3f89237cd92f1eb11c4a04c0971e0447e0d79204f221c08c91752d278e5233dc91207b90ba28888bc49d27d5424a3f7611d2fec38f69b9b61b2ac872e9031c39e7b86af8c198eb967589a726b521660464dd268e1183778c9a494f23f1aae2dca311ac98894ba21fef9023a1ce0a741663d6a4411d125bf3999b8db95339c514160f7686e1d1c81c4911766964bf2f4542dd42c5f7aee9eb8dee5451891a5076252111aed91ee5e8f0ff460d2a307d638317af400692de58e0cce9933a79c72ca504a49a994524aa9e55ca11dcd6a52980ed124a8100d6912356ed334a44374688bbc194412ffebacffef36ee411934e2412fb4641089ab5e2a12a87c5e18a948d02f8c542fd58b1423d5590691481bb34b582b76c82e811bc7ed908dd9d84bbb118a288bb0e936ed020de6c3870f1f3e7cf838d19ec6a93e7c48192bcfbd3be69d3b56a8e9157ac7e5766ea44ed01afc3cfa31beb5525a79a5955e670f3107fd29e76c927dbaa8947252f78eba28952ea564f5d722687d53d2b6e7dce7bc5e2913c9bd50a97b4fe79cf5b5faded5779f3ee78cfe5d8d10054b962c59484e72bf101ef266b2bafffafb8d006eb0820914284c00718065e3891ee8d0822b74d8d2040bfc620b68f02a6242103f5889a2ad74808916132b41a072f403fd8112563c1982478a12b0c0043989285c25b062022a5010c49322f4f840020e04c10a0978809f900f3e8e48c112a01ce123840e44705283032cb04203a10c8040e43345c7119c2c9101275e270865144e98810c7c3074031a4811d42be594d5da2357f810851c6c1142122fd8f1e13284132f2c4988c209a411dcd40b92288a519260424b12b194d08e7fe7bc59228ddd9d78d2e833d4082ac767424ea63f677f911a6ab2f48cd4ac90bb037574c7296b9612531632d82f9b7aa0e7f9b3cada42ecaf903d6b75eb4eca287b641eb2b3d958c8b303e54f9f43e07bafa7b38465bdb9a56d269594c6396fae94524aec84daf5fddb994bdc5d035af7cba65fefa473ce26b4f6fee836fba337493c8106e309f885eae409ee584904be9fb4f2a260f0c793474d07c2277e83eb81bbc30ef6a6a06031e064891d58b00408a68022959ba84a145598689aed088c55e84069877fb186087c63e7c859ea8acc2fe215914fff37afc87d6d76f26bd7c160bf345193e45d9a29bdee46879acb2ab4a6895afca36f4bb86fdfccb7d696ba684489b8d13831eb481962fa8d7bfcf23af85baeaca763fa93d7de8c7f18c3bc7c25a69f0f83779f3c25f8e5c3fc09e6f4e2a9ece96778f9d3e99570ff72fa194e9b9017afe65bae72e40fe1098008e1c19e8ea927b24c3f430696983c2535fcc9a341ae4e2d3bb55a3dfb017b2afb4ab8c79ee95bce60fad39f4c26d39bbc254ae2ebf4d83b799fb3101fbfe9c1e8327911265794fe8f1fe6cbe7c161bee971908fe79b7ec87c9337443ef654766b16d7a9ac2784b334e22ece70c702ec3e2eff287d1588c0f4a3ccf454c690eb36dbf993be88d5ba5247ba32f85b2fbeb4a0499f762da594b2a5941bc6dbdde89540c4e036f2d5382d90deb5d760e03e6eb708f751dee8481982875a1683df4456dfc428932b8781e9fcd5f90bc9dac723f99d5e7e1b89473e78fe9678e49f3b4c17a65218c4de7c79b9eb425d914905762b7ea549108ff97785f0e961de99bc1c16e7cc6772e53379237be4cabfa76726a5d05048c541f9922ff92361728aecb9f247be64cfcb474a28fe79284f1ecceb9c1ec3783a30ffe2a9eecbbfe48f7f530811b93a75a77ff919601e7b4af0c3fc8ba744ca10fc30af0463fcd85b12f3f85f4e9e8e942127ec29a979f99387598f846943081cffc5f31e67c171cc9f1ee6c1cfa9f9c2a0984eca7dad3352f3fe4916ccf4be1a2570fc96fe9237fde33c28eeddfa38f1d68c473390c0adc609d2b9ea4002831e128129058274762d8dc31f06d2d7f7d7ac944a0fce5ccaf15267ea8a90bebeb66d9d0b5181a3151948de9598514638201110c2307f7ace033d742c514635fb0a39c944bafceb99cd2cc7d90e6b9ab5cfbde6e9481902f3a7c73ffbe6f42f0ff3d65aadf370080aa65fed16b916863819b88f5e49db36c9c9509f1691ddf61389e7cb79409c8080f9ad030283b2c78d3c8b96c669bfc19e7cc178add64bde38c6d77f8a8e23b007c15e2fb7013dcca10fc99b66b5a29013ec431efae72a74006bb247ba667ed4755b8751a9196d8b1c0cd75309f150aedc7650ac0d28987a0de34aa404e9ec8f831229d4038180f91962126050a505932baf41aefc5b4b605e493c7dccbf3cd8b398172f86300ce34999de7dfc606c99007b118c2e2c5732a3582c929ccbd8800cca4f8e580a1c8b704fe3e0e4fab52b88a7942f49cc2ec262907fa61a601999f4a5219ad0410f4de0605405ab7ea94b2257f5e7cfa03dc9f366282991dfdc019ac5739ff4395e2a59efca15a94bc955353d81a3e7de2757f5733c660798be7ffd30575b6d558107833c72027a557f08611172ad4bb0d6aaeac721b7b9e2362d8b5a222cd76a25d75aeb51ae6f6757c9c14aae1fa7542251a8d301c7a118fa57ebdbe81262d99d428b41a3b902d3afafd54e355f9b3a52a637e4bee6e9707f3d25a4afaf73df7a4a94949efe0e4b6b4e7ab6e33c25dc5b255286706f5f89e9ef9b9e6093a78aaffd7dce531d408bde10edef6fdbdb597adb913c062993fe7d92a792de10fa5735a4da2984e75a1792654d0f1981e36ad5dffffe1f6b3ea123d0eafcfa028d9c01689619dce1a4e77987c6b883ac663035ebb5f7dad21030cd4d54e5cabd81a80a0f3c26640891051055c18126233751959fbce526aae2443699d0541d3dcf317b6e1aad71447f8263ee6f9cce436453b81083902129274541326b89305fd6dc8d01336adef52918bd79b3f540cff64b9a07c6af3f3fc62e5dba5cd142bc5e115b372945867f65510ca12e0809721b1bb8ec018329fba939b59fee46bedcbd111eb97e24fd9cb18fc710377fdb1cfc52c9052d027992ae68ee051e197421cf23d1ba67e4c3800f56a67822cf9f008f3c6541d327df998cc802687040cdec01e36094c3ff1341fae44b939a61023b8bc6297d300730f87df76e180a063f17f29f8e92b20929a59452ca4749773f7591f42dce95f458a703cf6a5f8146b2ffb4a42bae67c3ccd5562f94402a1c6457c221ec681c199f4e15f0e89e5703f843df41b8f51c020637d29764c906ffade70a3254010671e9b1db809f7be08c9df651924aefb1449a2d1a65972e5dba746e61beb45b8dd432730091053481c1ce42f3dd70c0dc4e5d30984a19ddbbe10c603095ba17a73cba47f72863f021ea6e4f6024d22d03a28fce310281efdb4f813fb592067ad61e9c597bb0861cbf3e4d12c6f995005dba70c9f723b893afccd7b38166e9d9e0397a45e64b3a8920422905d2d1769d4d9b521ab3382d81133f720a802212c4cc0f3598a69637d7d4d590c12996751d7fdb866b951cc77d107faeb4936dd759eb90cc5caa371ae59b23678d644c6b1a1c59d76d2896dd2757eecf83db82c12e1a722106213a84c02f8fff7e091bede04a6ea2d8952c80dc443111e4779bfbee5ad4e284e1fee9835c920ec933e74528620eed495ae9dbbf17dc5d2fca025e8302bfe191227f03afcafd7388ec76e4db351110a2644ab2d666d28d1a1d47c20aa468b1b6a7592253850a6b7b29ef4fcfeef3fe27c57e8c510ead204b4f0838870777f743dbc0fc712481c83374c03fdc467a35784e60b0674ff3dd78b066478e3f83077c7f860f26bdf69a56e22293c484a49aa84b987d08690599d40591a49923b429b9898a82b2d7e036e02711b26566d2931bc902b7c8334307ac45ee769274affceba9b010795343cb591527f9c6597c218de3a4289a04d1c8b7eb50ca4fe6eecb4e4a17720cd9da97b10552645ba5c81b192e211121fe996018ec590dd1756a822b7b4260b026dbcd9f48e3a85aa839fb2f8086c621bdbf034e3eeedfed1b9fed9e60d9adea28c5956bd0b9c255c3338b9a74ac7b4b1f4d193f556ac6bf1d35312563c7544fe39fff69769ac91b21a7d969963df6354e6317e9045ad3802e62b97fc60db08d5f7dff943c5c5128323a92531a81b1887c54d4c2c76d543db5a800742e2f6fe6fb4166be3a9880417bd4e336f7ef6de236d7e3e2369de577eb48026602660323968ddf6195522d57f8a94baefa3bda3add6bc4bd290ec5999dead882c1f8207d714f5f764a8e0fb6b0475df0f4acccb345fef5abd004df076d91db5c4c7b729b3a0a4c190566b412875252a2abe29892ae22eae35fbf00a6e850c38a28be99f3dd3d78ff412c2385ef96b62800fe82280a4c9cdaa222b751b910837577f74c3f8867da47b8210332d64c0758abdf61697e3d00ade61294bb284aee6ff0f2e4fef6eb2437bdb0dc6f6d40cf92fb5b25c43fd2938eddebee1e8b689c98fb6b38011391ab7e5309b0ca3fe777580a20c00fe08708e07304f0ee0d21c00fe007e0e910e077582629f0003ee7c17864d46f8f1a47e67e1661e3b412391ec957fec97daf0722a9f9badfeb974449d716dd6b8b6c51eee9236f5adc8b712af5d5b4f0401edde24ae368d5101b3a4b5c871e7c802565c6df781bbfc35a75aa21abc7f1383c1d157ef53b2c1d55e098fb2f4ea95ce078fa00f8d4e7f8167f53f3fdb7fffec81b1ddf7f61778a5f2a6e83fafe1bca9b007cff1d729b98efbf56fc66c7f7df2b6e03f3fdb748deb0f0fd5776b3f88dcdf75f2d77266f6ebeff1e5d2e7ec3e3fb493ca41e79d3e3fb492eb7e1be9fd4c46f70be9fe484f492373ebe9ff4f3e3fb4953dc86f434be1a2d687c1f8d1761cc4114b6d8f8d5a0d1c2a7bf85131a3468d048e233ba194fe36978e00c4ff502fd193fc303532d7e27b3f89d2cf33b19f53b39e677328ced231a0fbc3705cff3624e6709d0d9017402e8e2d17b2096e175c3f0403ce381299507fe0b0ffcf27d171e5893531d9d427ffceb6fd1d1b0a356fceb97e9685147b3f8d71fd3d1997ffd301de5d2d59eae36a92ffffa4d5d8dd2d5a02a5463158b7ffd3fba7ac557fd3eba3a2457fd385da5e2abfe1e5d85c9553f8fae42f155ff4d577de4aadfa6ab4c7cd5cf42575b72d5bfa3a35b7cd51f808e1ac955ff0a1dc5e2ab7e1d1d8dc9557f4d47857cd59fa3a300e868145ff5e3e8e84baefab5962ff455f646711bd07da83d923739662d9e2760c9fd97894bdef09c6250e8f1719be90407af0bc56d9ae80942b9fffeb88dccfd1766493486316cf1b8937e7f3914b7995472bfff7814b7a1ad163ef7b6f069e1939b524a41fa5a75cdda3ad086b95feb401bcbfdde81f146a7c3e28a076247ac25a8276c61d978153a9d6d88a5b301ca9262c393a2f26feb13c354146c8f2c177b64a37bc52254b1273251dd2e91be3fbedce667d5352b4ee982883ded2e72eb000743e4d8b247968b7ffd9d12f8ed51affafbce4e651d20f1cad103717fd3b457c4456ce50078a2af26f481508713d85f662d4af1fa41148cc2de37b0e20430d6d669472c4d8713980b422395b2d0b5cca8bb8c35b80d187992f038925944ee82b894c6182391221e313291277438a14308b87206a89c0cb1870c2e2942b62fc411c8103ffaccae715d33818420c8585ba7f28165bb22f16dfd9137ed040c46c5897cf0cace034b76eb9155b59ee5dc203d01db4a0afcbbd710113255a56682483da9fe2080074b4de368da6bded3744f7a7ee28feca13f3fd933b900c738c33bd0ee6e7953ba2175d7803d727fe7b953449e1f8dc8f7ce0b3620cfa775d29ac43610a49f77567a64092a4b5a29e560b0b96ebef2bf4cc0b32ee1a8d680061e9082082025a620814b091958028f14a02a551c310512a80e3c14dc97dc444448b04dd0486303c02ecbfffb5d9edf65faf17311fad33f235d9e125391918a483c0891482f57c2023d2ba832031f0f18c1072a5917261419010b028a9f120f2f80219d40ca9c87bf32d845e057b342152596102208212e432cb08724a0041c8640e289236cf00316d8312c3e88a0c8a2e52622da41136e8e0b0570d2c56108d212851610b119e400068f112478f2042980e8010f1f28f1e0834d7095c849ec80871e7c9a40a5080b5112587c78b281101461072738403485e827f53359f016d31146b861cbc0e6030811501384e8e18708433420063ff881080dcc6240c50e3fb0423b088154021e2bb8311039c93172132d71c5125b5247885b94316b73c6196b673d03c4e9dffc5a63a44392873aa40123a225b2e41cb98974309435ba4db7e93a80fbf2697dea9c0cd43b9224470f881e18acebd1a76f9f7b81c210a5b7614f029703062f9d53ce19141483291d8318144427925971b8b62361b701413a27fd9e1ef6cf41235bb6e0259148d6de4b64461a3178b9c611b3378e8d82358346369b83c682062c68d0dded050147f92f1cff3a8d0c3405e5e3d8f582807bce5a2914f259bc20e0862bfe75eb8861ff6e97eed1a8ba5adc90d4ac12725f47a674cea9b5a424d2c592075af7c04eba6f57f2b66077d2d39949248d448aa59fa52ee62091669c33a04ca8948df635350991a201000000200073150000201008860383a15028498359731f14800b7e9c3e6a5218ca234996a3280c8320849431c618600c1802403332432600417652408e9e5a57a18edca51e9bd4aa002a841284718d62085db891d1b4932b0d65d852b70e39fc1e61821426a5d4e52f18ecf670760c2f5e32e1e0b36f5e401530c04a3591cc82adceefa52a458e031759c681ac48b32b858f4658be4e9c56b72cee175f0fb20b4cdd458e9511461953c26b107826ee598afffdb091c1396aee88da6761bafb00c920394ebe589855e803b79a6e0389958154367bad5c7d37e3b8d2d66277d5a1f6558e764e501f2f4e8f33b7315c6e17a714e4d94054683ea6e085b8c12cfec5035e662615759c38cc6267958419faa4835fd68f9f3e8f7410bad72c8e70dfe2e6d6a3e1cf87ab83b93df800ed87bda88893430f7b7325d95f3dba511e3138aa9f03426ae700681db01bd89f6ce279f3e704ade989daf5edc51e67f931340a1ac14b3c5a745431ed30839f56c2b4a7e8c5299ec4e4663188a381f5ad03991ab6f018368cc8cf903bcf3282273ca77b9ac62d9f28cb2a5ddba7f4c08365ba97a530d7d40d6dd87cec500234777c129b326fe595c712376b1b7243aae828aac8a78a066bd261575e2b354fb083acd8949008c0106732e6315eaade8c94e1122f2c2a212d73637e5b9e4d30ee730e604b2eaea7d887903743001b5348b1a80de5a58f4332306402277ff62f0ad25a498e7b011acd2510298392a4faf167e1fb5b972eaa42bc289e07c180aeedd2784ad945c9722384d604a5f8a9a22f3533d83066f28e00af8bacc466bd3fe17eec70709f5b51e334ff947634049d1d8dec56c23f78e9d2786f175dba0a4275200e7c4c8a3bb9a9318de6493b24bddb12c386f41e97a7bce667244bc3d8dfe53a54bd4c909c6a56d8b598bc17ec63591ec9940fada5538d5f44cb83fa332338b4f63995b1cea5c0a5e52f0bccfc99e14064dc8e7918e48967353bfa1458361d401006dfa9b029a12b5ea0b616d6102c975d9187a5fcde717ea7ec96f0a815a8a7a7a6359fa7a6ed71be7470037979876a76929365c1fd618352c22a7a8f1a9dd92f2215a701f2a64991db8fa261e106ddfb8773c6610468c4755db60ccbd065268e325e1560dece671846a4a3138ec4f6f28ff3b04abfef0e438714e38a27157cb7f7e4f13edb9cf3ba768f6042072bb7a23e9c1e116be3df40f258da34c0d1f0228e637a5e728f32442150b7a9ed67b6533ecc2375bbe864da7fd27f725d47ad527710c097a6a4147ba3f92dbf2c7782d9a3de53827c9ff43b50018c056db56aec94abd8a9eb558d1af09f4fb2faccb6d2b40466154d4d1871c3e5c18d9e076a988a86a89a2602738a9072c71a3a6c05c5ad2d8f43131c2c207b8eef5f170cdfdeca27052e6342afe0738d0e858ef55590f53afa3dd8f969e005ef6e3f270d00d0e4d2a282b7664cbb7c5e57c2da651a46f822a4839636f1d381b5f970827f2564eb59cabd129042c56f4971e0dc6f64232e4b4b67f17429af83eaf36174e551d0f203471695e799f7bd420001681733d2762d9c1026c1b61a8ee5a785c05835f33b844594dee556a1822587672255607fb4c319921d3d934f144206b2d029212a4cc4fb5fc4d1c506b428c06dd4413e880255d523302ef379a156aed529fc270aa02b895192ad35980a1526485344956224f92a584b5a444ff08007b1e2ff16a7f667108cb19be2ad0f655f4185062176388604b3df9270cbccf7e75a03823654cc0b21d54b30370d11d448f6733eee6324df21f60db8b135022556beca9d0b1c685570f98bb7b5021f44de2229a1597831819249e398589b7452534d47c9696cce23b958fd3eae888810d007305ff2f2800662c0c0158a6e5ba634bbaf81a35c8c0c0c61b3e4f97e601d0dda4069f1f45a2690e29288dba3b4ba3b632dca5bb9178c390c71f8db63c846dc6b8c6b61d7c755c5d5db6120cbd19a48ff7ffab909671a941fc1c38c460395c5b0effb1b74e4e3f8d989491126ba40ab6c8c210ee723b1599fa280622248999e46cb9b43171238649648cff91fa6b6f348ac4571a8ad94f7d944975686759ae1a783435f88183c621d0d1b7d68001a470551f1b4f09fdca6f16fbafa9a02c9e28015c16b00b39212d1e917659034db367b7add3eca9489603b84837a0275a4ab5b54610b5d8e87017ee608ad68c43c09aeacbfc51943a36ce928ab1962a1ed5f2e1162624f478d1663c70d7fc405520b47057b38e47ebd5d77b9a5d39707c03a8c941f75781419b0db62d4bbbd0c37e9cfa7dfaa9d9d347ee19c39f93fc052fada4ef816a48c70141b26edd559f4e81abbba5193cca7c5bce510a9f7ba3f331954c11b58f7e10aa0ec8be79f7fe0f4acad2b7a493047bdcac0f4db7f8bca1b24c40638978b114a5fa0273c364d17d068700641ee598a2bd7a9859efb48082a712d195ae3b1d0e87b0a9b969d870ff7e2f71d8f652b74d8cddfa818bc207970227ab04ff3e00dc753bd6849e6b64bc4b4f2802903e9ac8b7a613a2f0c8a22e026cb31ec631c0ae91a99697dfae59d35be2e3f24a93760a214d261f049b3cb923436cce4094743b660990672a00002f56f1246a1b3139c817373cc50224477ff33f38bf7d56dbffad9bbac8961afc955e1ffacd59bdb85059002b908345277ed93aa150fe0867220e3c5aa5fe6f23d999ad3ed3082ffa2c89acbc0120a91d56160da4147eef7b32779773fe44323d0e0cb9318e0211d6cb5888b5c22e1a6772879b9d6beaab12179c3e11e3b380671d094424587ffa44abb5639b1d3f35cbb09692bea10de82257a622c5af8b4584865df06135600cec10980ce131ba739519ee954400a080d3f75511a4064874db82a8d1ff049f8c1243779a81121333a38e1fd508d3d84818f718d9d7145ea6c82961302360957417bdeb316d5f8a4df78fa613d9ad4fc610fc69a9543f83cb8f33c4343259b7697630d647702696e0361bb4463ce09c993a43a6a3d6586e91bf1b6f2f811d1d00aa021014a59f2a604e98ac2c9520bdcda668ea071c0185b772ef742a0d12108d5d31f5db050f499dd1691c964f8b4f0fdfd87d630ff20dd2d79381994bc554e5a0a6675c28aa3029a82026c90dc36e2e6afa9cff17157c4abd223c32d0fa851e00b3810fd41086f996f70f4210f3e866537cf5740ea5d25d1c5e046005d2ab70a59a164e51cf8734d69225017ae31dec7e22e7f89c73d4142ada1592aa9fc0af9084c278e455add419347114e9091e0cc0e78272748f0768b32314823508c5f96fa6d9ecf91eeee7f0a26fe7fa70a63d36c0e17b211c0fac8e7d99d008a11986fe8a14e71579b320c0cb69a9c18e0ce21b84b05e6602eb14947be3b8fb72dc6cb1c118c2747c9f0e1c51d74849421efa8f7847960db87ac3785627c42318dcf801052f6530e1d9f400b6d7edf0cf3ab4a79e34a88eeffb47bfcdfbfed288f33bee34e10e2ef5f3c7a1b30e13348c45a03bb57cb870746623679be7a5da388e2794798c070657c237e99c9f62baa112ad10f94452f7647efa29b2af9751319ead32d3547e547701944ea6e501972e582e028bce328cb95d44f5da06bcb03f6b01b9db305d28c8005640a44f0814ae412568facbf0f760159a8c0ddcc216b61ae80943108f214f8450ad619395229aced19e408869395626c65742846e4e01a12f1caf615903c2d5f43e447942291ece59eadd5266953ead1c56e2178c84458d33e1ec21256f6efb2b401bc34621377978287cb68adc49db328baca2b8816e3acf4151fec28862392511b3890d5924fb8ccfb80e0ffff162acc55cad68c292a3d870a8c6bdcd527e2925fec414764e50a360563df8b0e66a12110aa221602ad88158301751d2c27e7ac06b6160550040d89890108d2746bc2041ffb69e5a9e1576433a9582a44687c99d0aa6d239bc4a269f84284242435fa50ffa8470e56ac9e073470e36a1192b65c1455936cc800da6a6353461ce610a6fee36ee21a15cd65f7cb9e28b273e9a88b1e4fa16dd2b5f352744e111d00e9d73333daff45d4ec58509ab44b73fc10963dd2edf6bda237be6b41b580822d404bd04d8d82287957dc7732ac3483b9fd5ed914ff84bb1b8fd004e10095df4472dbba1ae82d6518e64e5f829a9561baebf3f20dbfb1fabc85bbcf9ad7102fe78ef6fdd6f4e1256293cbbaf77438cd1c95f34e24a9a1b5216d3b693ce83a832f056bb717c1f616f041f15721dda784d0126bacfd38b72d0a0b2285540355d5d289d97fbee0ae7fe87cf73f3fe19dffd774b206402244359847309ad893dcadc137557c157032abf2ffbd2d49ba447d7ed9d1c95921b355ddc0ef29f60269c3cf4f61cc7a42857dff44720df6630e65e965e848e8c05069d92a16e0af00efeab49a3c80c5a595980a0ec9a1cb671ffcea44fcf1cf5c155b5c3c0145c4e7b732f3b3558e05f73237061cc6fa9d9e4a11fdb9b2945e2cb254b0628b22f63d82fe098958ca8cd0e71ad6d205bfe5b48229e00b2610208f2b5064bbaee5b05dfc7f5d9788499f851fe2cf06bf539afdda5253fb956f20e7cccf752566812f368f93d38ea9ebfdcf51c1421b6ac1b3655d6ffbc0c4bfe2988d626a284eac4e54648c07ef266ed3847b4b2ad6d08c402857e52b3e73de5b60460eb95a1f18ea0aacee1d0a80ad4812c996c2a344502c3006bd7063a78a25a5b2ffa24105ceb5edc7896d0cdb3eec2c07f37b873ff1b8bc6e3cefdeb2fdf81bceed01d3bcf3cb1cd47f880a1b785060c0199fa2b92229e412c334dc875617408566cc16e3fe4fd55064d2e48d3277df0d1b93042bf344146cdfe4c87bb8ec1c8a1c347f49a804bd94b741a1b033066e439580523cf6959b88719086911546ba828ef3fe0404486fe4a5bfbb0c7e7c1893b3e3c965ad9adbb44d3d4807f6b95ae12014ce075b80521c69a01959804b47ebe70ced2f03560aed83a964ace2c7110a2a05eabd3396bff6e633636dba6de21c4c594f1c7fc0c2ca8fd2fa35dceb129f28a09cf1efdea1f8842c316a771db24c83cc97231f56482a8993ea0f8c78f168eccf2d7ec403a83b5192f95aeb93ce58096fad8478d2b551f989ca791ec7bb4dfc0b8575afd6543e6df2be80f8e5cf58c305ede52fded057223a441ae7b43e57d9db7231de7b199f562429b13bfc6cb5b9641f54d97e388d4ee6eccaa2cebced341b5492d4a5bb6998d73193e3a5c43779514f5387ec6855abb08d4d284bf37beaa7ef958f391021f8d9d0feae0ec28e6c4023d6536c4a0722fd9e1565b917bf753a428aa7ccff1d7bf18e475c17bdc5f3178872a1d01306b8c9ec7cd9e817d66e6e00fbdffbc830d8e3fb68e164638a0ec23543ce9907d42f3721f49b1f43c907388340e2ad9973a10532104fc2ecb43416ed217081e6b03e3c1fac61219e60e1594175f5221ea948db66af4100b380fccb285dba2937e7a3025a54f5b93ab3435c7385205a28ba42c430b42ed1a9c9cbc73f6d705863c414af195e90b02f7fc0a2bb865006b14a9418171c6ecaac746afe14f12a6f488eb69cc809faa3ca2cbee776e86a14b58dda1d98da73365508d3c6f94692a75e120a8b4307cb9f814bd49bdb085a1c558c2fbaa7759fddff0eb5051a70ad4e69d36abc8d804390fbdc62f92c2d4d038e3f01ba7444fad387a48def6821d6d3198caa20ee46e0a293deb85b052b4a7d369bb86f48f3ca6578050f5d1d4cc142fcbad40a11a3b28b77903ea792870e83495c7211c3d971d2a78061f21944039dd517954edb4ec30a28798c1a7d33268c2d0c678083b7e97a2ef4d7f96ad01603e878a0fe333e312eaaa28899a35667844caa0fb0e163549996c7bfc5645ed7da1edbdf2636264968e2aa6cbb097159fd75d2f80213793f2933efa008859ca07c2b8d6d167991042ecde6c16e701763f5a6f7e5ab089f2a821d621685057dd6851832cf0d97452f362b409dfe6abed123d766bffa70f4eee4aff7ad203082fa2855d90244378c7af25988aa70fa6f64a91d2d7e634aaa98720c7633201a23877bf39360a1c6233b4082ea5e8a481d6375f4b6b29a4b43684b6702dcd9e7070be0e75cf1ac0c520250d84875564121064103f0502a5e2cf4da077a1bc3fc94adf14ba8f7e4fd4caac1e9a3d4e14b42a33a98e8434337470d6d2f532482ee890dfc6fc93e8b52d27a0f600399988530f2802a66bc7b5fee6532e650b319fec4893abcc0faec5f808f694d338a2303c51cb0fa1a227405d2c4a86c81c7e53d5af93fa28c9d276179155697ca65c95422ff9667dd12a1989bfc88bb20beee03826333aee03c8854f4b46376e4c85d62b13867df088d0168cf949251bca4ddc38bffb1683b3231b7b7d00a3a71818d0ce900c9c125765e3c0ed4eb6a03b15f7d6dd28c5a6313b8c4556f62046d285c77ec1ce2c98e258172ed7f3fa45b20b3e2cbf3336cce48bfcc78122a4840630dcbd335d19ee4b9e7b5c1e8012d067190b2b719c3b690abf7b65d8411a710af49eb593c6050ef2ed397ef675c9fa294aca748ff0706862b6c1eb0ac452f60ea00eb8b5a68e7aed6e44188b232f20f14686bdba80e55b6c0689ac953400225665484d9cd87a2ebf9004926f55568a8bbededa8f2d6b7845b61196a90ef23a97bc5c80b2de4ebc179a64c7655ee3ab677aa0017286de4175b71fb1009993f58f684fcbd81b9a475fb7b7bf71d39c134ab817c9f04cc1f6d2809ad02822dfac941bed6e6df42b9fbc0c0ae5dff0b2daa86e5e6431f786b8931dad4e2c6f361766a81421d575916bb5103137afa08846175bf23ea87d2f622691e57357af0b351019dde272f0a0b3044e161f7a31d4a83491f74ddcc86493bee377ebc4380ace1a3576fb680671bd2e9c2317132a4eb0de610a01fcecff12c280a47370c351dd02cab5bbc2ff6e17b9eed5f9fe616e54bdeb177c24acc080c66140b25460a9874b3c6b38cf619358e1a3fa4f1190296d12363f09080cc38cb0dfe7b74c5b0df52336ea2b617838b6d2e02d2ad39e5547d8cb099a965117ca80824bdcbcdb3b1f9ccae390d137b871bd0426da833a139ae4a082536b7a08e2497374f3e20d0a51fcb6a1c2cbb81cfda3b903d3175293751e4b10dea549175dc146ddb30042758416c531e0cf73cfbb23eb402cccf691bea3b87a81ad990a63c1fb0e3e6862cf28411c63162aeed81d7948fa622120a34a00edcfef49178752b729a13c429af3c0bb267eaa8a0768f32adac8f24d6bb9f1282da266736409e6023176ba8bf208268fe56af81dbb2f21939f1b72d34dcf5a02ce13b6261eba66b63e8843f1d33820064a4d9393d1de4c876a7f4184b3b3204d49922b2de90149c0a860f6cb53aeaa0e0d289d84aaf30e5a8806f8acac3965e2a901229f51ed145565b0924d50163f8c8be041c6bec508c644a38c85c4a612ac016caa23bb128b11f14439f9e2cc5039f6734355459b451e71859b8242c719c45aeef229a95f91d5ce631fe2f912661f7417228140c20c2417bc37b1dc7bafe633a17b2438364c85b08f8f7502e58b06689106fea5da1571665f7b7140551030f65c9f594f42468b5e12cc38274304bdf67215c79a7d1a74b82eabc39c82765ad928a40b1946b01d55fa09a662f7a86ee857ddedb4d8a5d9ceb97366c1cd6c8a7f933e7e3b6951dbb40079457a259fade86729f2c79494dc423ddb4097cc0ad088fa3809217c2cb5f65234ed95854ae1bed397c2e1c2a13a4f47c6887f2848d8b2e4ff9b5ebc5c32a37960e3cbe38e555032584b10e2aeb53759cb5ff8fbc6befc7e281c2d8dbeb33f54fa4437956e689f4f2270c2cd0c07a175c6dbc03e532df39fab4a4a0be1dbe5e39f033e832f0b1397391419d0d9dd537d5634a6b5762263f27b355d30e87c706aafbe4485a188339d7cdd8c0071fb5dcd4e3a18a14b88dc6a3902d28af5fc8132f97dea8b888d64a2aa2b470c7b1fb8530d434edf58c5efbd8f2ae88b7e955638d599674ef29e1e04c1eb54ad482ca57d4c4547b96ff778c78ad2854a2c30f86f3dfea158ab6e87b95ebb90b7d081ddb53aa4c7140906eba4c0324374505d22dd852d04c0a61308a50a0f3b51ebdf03d67569ab199aeb328169769b2bcda2aebdf028ef42c7a3168c5597f75db7e9ee6b1f857104fc8a473e4b62ee43b70b948a0d58cbbef236a30ddeedad6a270a13a6edb5c2d80c95d91d371fd4c2409ddb7d046f9d5e0dedea3e9e2a518092ebfe3077007d8baa5f1e23574f3a0d95b3e84bad7be02ca1135a6b7d4badc45c068a9356b76a2be43edb8b4fc36346584dd2c87a8727303263dae75ddc980ca4e81f86e6c6f193061dd506f4ae41354b6c01141e2aa3a2590fdc5e87178b401f04a8625f2d53c3f5f8c7fa14932a4cc2a2bfad70b08f61e907f2ad8e12b57dcb0c7e37ccbcf832192ba82f9014e23c013cb4f57f590c5a6f73746c9bcd8142acb66a9f26f630be9550856bb5bd420b8a0dbdbf5198680b51021dd578057fd70a1161c702952d2732122d64f625e80114b071c2690431dcd09f0e1768c0b5ec123a0ede1aeda5ebb7c3d2f59251afa0940f6d0549e5d994379db58710af7c9d7bf69ca908429cf9255c25595d818b482ea28e89407398c541ad652b67bad433b7c7d9ce4826ea1e895789b785cc469158cbf608952e1953ea387df27e1bf1760107d3e547b72b2e6f3e9eb1db4888fde82f48f53eedf45752038948a6f11c7057bc27ee12358aaac7c0b3f9a43a10000a5a671d4698c82f16d619c3ca6e53ae102c25ddcea6086f87a00abd5b950547b68b6c808b426094c9e1a413741aa6bb187b103ed9c6d09b6d68c82aa2af63ac5c81c8e928356017b7ee1a6bbb788e09a8e2ee3f85b9270f4552fd07b78f2fc784b17345846934a9c469e3231ff89ecedd24f5e7dc04d0432dad2c9f816610db840aff8970e9b5b9eec701cfed59ef22c0be37cc4bcdae5760be3ed211ce0bee1843a713684fe2cc91a4421922b15ea88c7c9402f222dc03289869bdd88e19d948b13c8269713a17100047939e6ec4124749e1bee471eb7775bce0d57944cabc3b0cdaf5fe8b88172e6051813acb9a537b651bf0a3c1cb1105629ba99be314d1ff1f9c1eedcba6ff974a1c031095ac12bd9b85611a494eb357f123c64a237b902baa3fcec855072b6e8d5c20e4718a869ca188ea257d476412d00a246625168d559c68d4caf1d91103f8f3ab8a1c0c449f6a1c781986510d29d2f987fe0bf41a8c9f9f8b9d76af59047dfbad734471382d783b6cc43ff777d5165f824042eb47f86207827c74adcf6b02b832140535d778f030cfaf3a8439abbd54ab5ef34fbb675ee751cbcdd78f0cabcee7f608be0ea96af9f66de81fa46f654028a103b317e90f52174e4d0350daf2cc84be1c2e3e63c0caf96adafc05982c872e5aea860d715a6460c915140f82dc50f6f7a7dfdf34c28e48c0311bc4ca2505f3270d8e8f18655bb5665af7e9327cce5e07bfa6962fbd3e770c2d6973e8ba3959441f61614eaab45b57fa8ef10d5d72d8adc7b11a08199091556252dc4b682e3d487279613e2930cfa34c017327409c9ca1dcc17d667a8718901faa04cf48c04eff2c218b82f975e1f19f5f96a24a3b7147107a1e70e5c0383d550793936abfeaceac4eb1c6f4c8b88caad3c748068d424b39b48b6ff065a21d92ea9972846f17fa003d4ab57bcf99f962e181f88a9e007ad599906b1df13ca4ed2cf07b6ec88dcc8dcb2968b90848aea471a30f21d46745852c7545a14c33f8c4f7b277c3d0a0b41438fba80e863f4f2ed9a46528c7b2b342b6f0bafefb4dec72851e80c182caa1892d81121d8d30bcef2defca0ee2515c428280c796fb417d7b5163672e4ef734de35fbb6a6a92a27b1dde54ac691c5f9a3fbbd67a0abb74067fd3d48ade85f2dddc142d74faa40aa82524358b3d1730fb048a35b894aa07de948bb55ef0a3d01f1b5331c71a0493e4a689fed2ed775701f6cfb459bcc6974f6211edd5375147e37e36305b34498c30b28d099a91ff27582b90531a552c20d05cec952c9860f1d7f76810d4f09953a74615939919eef38b1ad8a395acd1c3a598ca07cfed4b3c4b7410f1a08b9be11be02d7a4a1bcbe8128b06374249162c5d1edcce16b984ca6b485b95ed76038057d7cb8c9d5656931d22f7978a65a141a7e22093dc78855cdddf6f09c796d71391c6250298e15519a7d1e7c8ff5e9e0abbd9e466642112ae17577df71561a1fb415e5850c13d027ce74e0a2ee1fbe5a1a8543c251ed56d1d11fb240630447a31003f60ffd62ba44fe67d074eab3bb01d9509231d83091a71909e7dd337e569b45b7f26b7224caa9382847f44deebd31b6860462ef59a8326d3e44ef973277d818f39592ed50fea00ee47eb90b5ea23a894e55cea8809e04c688b58b4355b7da7745f4ed6fd7a9001fa474c62bcba000da1f662c9a26ae86ea14a216eac16e28ddba90843e43e2e2f0bebdd19bb2461d7982c726c53b87c13223cc42d23a3f14d9e7d7c94d50a8d4b84d6dfb30139ef8ece0c8b3581dae3c612da6f1e94bc6f1745f8477caec8954ad9a81f29d16e7b9d36b1f28e42721f9d04e3375ac7ad490af27d02a59605896c433ef560c80fb0cb780e6ce7c99a19c7c979eb0b9ed052283c946e03799a7328e444433a6919225adf938ce9f4644b21f9ea94583efa0dc4f06723145f9665b9255e0f64d39f226f8c3b5132f58c286acdfd4062f7c2a9ac09a8d420a4f475e989d5a44b3f486c1d5cb978c33ad48fb1f58d6eea85a219748920c971c4e458ebc4c981c59cdb57812aa3ea5042926a1b956d905d3e654ca8d283a1de2266b70847bd551a4d6a4c3c732de7a7cf8bd53f315db87c54ff5eaed500fd82e21807cbdef89580c5c5a8b2c40e08d5f5f3d24f4a2bfcc8fdb19b5d3c195d715b92819242f525f89d0683d359fec4be40a08fcb26b7f919ed7c0cda24f6a2d978dd282bc054dba9e2399d109c024d8caee457a08b6a4f870fe842f8a433a9cce30bf5440b6232c4b4d7781b1f431a797612c58a106bc706ae46fe777424eb0c6d8c5867c61fbf2673c2831ba4e7e139ffffe12d8295e7ff717acde83395ca901feefc7f63cc26b0058df29d0d9ed7c05004436a86866d66a921043284317aa40eac444200b25cdea026ba07c647cef7f39d90c862ebf7d6d38a6b0e32fbb5097c699321ea5d2e878885cac71edcb876afa4ae3826ec053f38ead826ca75e46236742bdbed488a361cb4ea87465d4523f552ebe86e62ad4d877e21e8d33b7ba9680c7ecc981d9696af9e2b94c6de2d7df3a3190b64540666b0a2ef7a2137a5cc52ab9b2a560e1a34b66247a2f9ce4f232d948fca030ac36d7ed63180b09dbbef36d522219543fb4fb4ce23980edd810a4d5863009635c56618a3a14dd2dfb66c31a904dd9eaabab33e1d40ec225d0b574794d2d81d4517999eb94924910886ca8dd67000cb01c0d0acf0dc0651cda2c67f2ab3831b55dfaec26b53e16985d41d82b43b2d82c0e7999c441d9f59a677536fc9fc7dafbb228a48b768458facc335cb4c305e4586a6e50da71097ae7d6e8182a5ed6926749c4c0483863d132b27347c325a66943008247370dc228f304b5a3f0161b61e5d8d1955f8440902c4a414b5c75a477bc82e201c2d72e7b20be4dfe8f516e055b3965e8cec9adec1981917af33a0b66c6936c0916093ecfcb2cd3917c3baae3081724e25bf83767fc04e476ec32ae02df04603238fd014b64caaba44af5025ebe05ea2500d8065b50e243355d04724d399b4c140b700dea7c0df965c1aaccbd0bef2da4da47ab47350916b36419eec611ba1a4c74afc1b71b10b5e46de7f0f392a87d984f4b78d4d4a076ddb910fd2657cac043e2767e3d7af4b7350691eb61567ac4829747428c07839e56cadd9a173e6a515935ef44f79043384d6aafcd66e15443bb2c5623ee4504f120602735c33ee9fc34a30ff9430240781952a01124ef1a8f614fbd5ad62d614a07a3647bf40c521217c9dcc9e5d0a6efe0e0eb28005043bfd8201fdf50384d3204953c842bf0041f1fe422d4b81fa4317d2fbd24b2f0bdfd09951ef2f1cd8a49f878078b565e468e665ff8128f12fe489348046187f213dbbab3a826d8f0b695d05316afbf99ee32fdc358dabca0d5610373bd21349ce087b237e2f5f179cc108abcbd7410aad54479a69bc67386e7d943c534885421559b405dc4312595180f99169ca83e99f820b1668afd2424eef628da83ec361b47684ba600163be100ce9f11e4f8e17728fe70c38e37cd37deba2520772065575183116e23972bd99fe66afde1b3f370180721a2733d04f7108e967a0d68b15b51748e384068baca0f3c2ec38e54e3a686b0dac46e73070636a2946cec1e4021a0ece6831db88ae8a3f277a734c8ac4b1d120c029527ea4381065bb04067f8502aba6050de23278024e89ccb5a785233556af211d6152d117056b5256a8cbf99ba8b9a0360f35bbbad36936ec41a0149e25cf1e7e766bda6813d47ded9f36e5e1bcc64f9527c46a6811c32e73496ba74d734e13ba3651a65a12119fb669385ebc9db549b65bc0cd7f29cc617b49ecff94e2522a169e27e45b8f16e29770aa04ef805f39b0319b388d8fb5ee7098483041f8e21eb1d15a708d031a8c8a448a859f9b61303574a786aa4fca4b48be9596494f7e96928f2918b7da891a08210c2527885cd564bd2ef709d8b498aa7280c7afbaaa5b8fd6e31e3d812c043ae24674d2a85a54843b7e0fc7b5efdc7c472910c0e65e7a376f526c3779cd42a80545610cfbe0fb782900c57fdc007e7ea2dfd527d317e4d84fe38d9db59d5ce745e5e64b6a4ab1a8f2644f7232df46b8011510e24f1111db6e9ebc0a20d9d951b3aa53c969880d1ee5225f0ac8ae4085f75e0cb741e3af93619f3eeb4b50eb1bbde20e7c4b6178fe8b3e965dcf4662d62a1ec40f2ad8ba9fd88ecfdb5c332459da95f6eb990b543aef74b93870bad6fb80963f7817dde0b023157195c59a2f2ff7a0b73340fdca4113d1524998f17c82a8dea8f0ee556b5843611b02079c1b78f9230e2cdc48f152271c01e32286d3e7cac435948c05f18eb75e3d69c15dd093a6d1cacca2ab386bf6f8bdf77e1445f157709a337198b378a76e93d003d69405de3e0701998a35413477208559d72ffabbec879f4d570a580d40e9e93f923c22ce3538d0696407e8d30a3b897198059e4b349b80ef4270e35a9595441406c14f32c9fec1350352afdb0a66522398053d97a4d83fc1115c7bdcbd2304324f6e4eee2aabc04b84b53f71d98c573bf5a3f4042a8e600d7c679af1034892ca0df56cfd5f42f6b5f0b0c85ec0de33e25e32b0ffc2af3706963d1ee65f465002049aab6bb937e1b162c3e8e588057dfffa6f03ca9107130b2f096afd4bbefe386cf6bc98775910a0b69ad062f8160aec10bc1ba00acdb0f7938358cbc8aadd504d5f8750cf4baa8686fd3718b67fb7728cbea0e8638afb3bd67e48da91f627ebcfa491257e73350af7f949f81230cdba8d064dfaf9c6cc8d22f2d94b3ac5b2f122ba50d8e743e11e33e4eac7193c1a5de78d4d3aba13f7add0ab3a2ee84edffa88c4faaf266b12429f623ff81f49bb12df59e9410a08c37cfdc76b0042d1eb5463780dde3554f1e9ac0f70f3a15043d31198c3e860f99f8c662189f7881239528ca592c70c63485db3650be900175bf01e69b611fc519267be933c79046059226d28849046f071092150c05866fbbd48873fc2798864e2d7c6dec69d59227aa51fb91d30970d1fbf4ba4eeafbc52bea7f9b40424371fd4fed9f92fbd5b66cd92e52f397b7e16b70417e78b60ed9b08ff1b1cd9a95082d71746fb97f832dcb003af3c5162c3f1cb3869c1c5bcfb6d671a3c1944047a5135c402136812f26d4d6adcbec84a2378999dc3140fa1393a8d9a53d2e1abb15acbab4f55516c877ed571c55acd8fc1e973e88b4fe9febe76f47c6d8d8f0f68f7d75f20787b767bcdd63e90983d0c6c1810ec79a03598a1014d371ddd6093d155766a96690d1fae88c3d89f28b535bce5ac2cb3f4b2f7d979a0486d379dff476df75a89b691f74372548a1bc24cbbb66b00971b5b87f52324ddff9a29111e65f563a5558581334f7e252791d4cd7a99b96971241060c15f7f83e2ad19ecfdd9deb1cfc49cdddc79846139f65b8ae880fb20aa25592d79d99298b050aed95491b93f68e708f80931b69835e17dac3f8ddfa70a31e76b8e3814b409940ac47bb306f6b677553eb717f8bb9cbcc3a69c87f05a3b0bee070a97bbe00b8a1ec84860cdf9fa936a3dbfffe05a9820f354bed4958c75971b4a1d06f61cdb5c4c32da096eae0e73bc65bf88de8dd0241c0a05f42e678686e6639da3b249659e2ba548a49259127c534cea98c1abc9775f2a8afa9f32ffd771af90f0a9caa8860cfc677c784d1701f6c777201b2170f5f48235c254e227c52dde5eda28664676df324192bb5cba23b3dc30b6f5a84b52a9ccb1bce4802a984a171b3a33ee1766cb7bcea519a6d35033b804ad8056001aa4aa3f24cf1bad4ddc586ce118d7d1f3542bc1300e9537a4a6da8951ea14156f5ffe28b7a5d75fa680d74c905ef1cbff966c2916cb5eba2c3f46659b33251618a7884316bde3e194d1210dbcd993ea330afcf8cc9a6bdf5b8b3c837648d78f2a48e61080181696db2d3f0396c5196f5b951f62c65b8a8b645dab511bc2a8540978950e8d2070a5b3f7a24221f5ee7530ecb4e7ce492da4c60c09dca38b166421e567783f2dc02e26f9755865684065813564150ae41c6462d41e0ca65d10c6682d16eb89501b1882840a0fea27408b06db04547a419a0143983612c6a586dfc6111a42dcef1dd22cf364f98c2308b2455fd962c7e13227b8c231fa51b007f0c63c9edb571ff4ef5009ee05dc014fd68bc10e1598eddaac8f03681cfd649b8b91d2637d3c83aeb341472088256b60546e1816b585dd46d41a238b6d47698b18d406ff77a4a46ae9e1a5e622d511e208f66e1de77b1c4f3716df1e6f9428df798b75d22d7f0ee7d6df8d54bbb3757bf17a61d9fe1f34b4943e7e31a7fcb816975f015cc1d0a8976bb8debd57cd43388682faa6229d414f82d7e1e9470f37b9528bd596ac1b51f5f61756ad42a2f7fc416eb4f1757b926e19ceb3dd188040cdb2db7b109ddd20038ff35a58904147b7a0f12412db11f801716113aac8ac6bc78e0b31ab436227e4f6d6401da8c7da3d3d6a619df2c5c19f7f21bae3693cc7ffb7ce048ddec75f5256349a5132e618e29f076be92aec1522a135e430eb29eec26da64f30bfa5ae01327df0006740ac7ba62c59e113b084be0e34b9873f93b72aadc3bb24066a22e5d4d9b84232b5be09af7cdb852ae9cc7280d526627b4713f5b8f0a3e2f10be02e659b50b49f58580ef0139185ef173bb550e2d516bb8fa65773949867f5d3b6dd28c2a623d687da37e1cd2ca57e8ea149531d04822697b2d391b303185237a353cfb88b2789732306cd741d8e608c64c554ea9cf047a601923dbfd643a388e5ca8412aac314673e45d9a013c65aa5c96ea5d18e7e9427b99d063b7a556a2b251b276f8e060bfd566a955a0d167aad142fb51aade856a9a5d434dad18d525ba969c4a35ba5b652b3d14637945aa576a3856e294d00bdaae967b4a2e8ab6845e92b6845e83dfdbe53a9a89bd5aa68b7f5aa28375a735f956e055d846e1d5d84ee0f7d947ae7fd754951b7d595a2ee9415a334ef3d596e6b2b45dcd32b56e9c67a56d145e9753ea6e1f43b8bde41719f9c923f77b7caf2a028e606d203e52e461b30a7bdf260702e3c3a03cf1b5807751767d5fdc1423ee918fd72ab34a6245ad5af2c49523a5c15a34005682f98d760124c38860682506f6bfc74022adffde499d732729a8290f0555f88f85f323fd3e5dd5b8a6207b259cedd997abf961dd51512fe17ebce7b0ec1b5df65404eee2ecb55342bf1f6286905c74ffd21e56badfc1c17b8be09edaeb03427736472ef265d05b303ee1da702e9abbbd14eec7907b0ad3b8e7910edaae9c4f59c384e2b270470ca48789ddecf244bd9b96431858c34af2321a2d895dbf8ba637d2c4d624742b7b9aeff39378124f63fc0db4fbccc6041b8afab53d631087be594c5bd9a6dd28c30fd4bfca12a4f61894e5b04ec7c3ac8481c567390f9000573cd0437f1e175d9063fcc55620bffd27a522b96c98719e1ab1d3419cb6df8316fa31923b70b37a23c0a9ed3784a233950893ae6861cfb35d777fdeafb3c7b89a99a470da656020a002b8a0d57616f17b384558e0bba7b1d2d5608e0232e75df7af0da030c1e09aa075685edc60074de273658982967cce5131b829e427a72c543053c8abab656b0d857ea58ad5f7959f7eeed6ef0e716ef5b8e7785b5e5975b2ecb27ac4f93ed5df2bc4338ef644648d753be4d7cad2c63986218cbb3b24da5983ce1764d4a558105da2e545ef180f4d5b139d3a574aab0bee71f107e21309b5ed95e9bc30a22f3a1bf3e7fc4ab84063ee3968c31df8c3be10ef5e332f796f0a968bee484f0a368b6377546d6a75bf57e7037fb4b6ee27ea911ef108c08b124584838f3f8ba1ab8ba9896e99fd1d0e51b9d9dee1a4b4b2fb99c974f2eaa4bec1e9108c0ba9cf6f1a6c9c26e40310ce33a1981e031fefe40b901f8f7e3c4b53739ccb9aba5554dbc9f68a24114e28af98ab1a4558f6bd3545431ef5caee8f7df57575053e87246a8d04145b1d29d57f256940f9b3153cc43188eb5b7bbc09b5ba46f39437e30a2267db5c269717c928b992a5c546c4ea861d060a541cf3aff57ddd6bedcb72fab6ae208c11c64c169e902fe6c2ae190e6b427f2d8eb40036438b7ffa2b28ac6066a64f1e0872a12ffd4a1c7a5c43659859d7d33eb86d4188906ccdc2cfba3e700bd392bcc818a7ae9223ccec5bec551d7b35e9e9776b8b5aff1c681351a1310c1ac6d71b87ee47f5905fab7fba7f3b38984e1abb2ef32faf0a058086ce8973fdd190ce149124034bdf99c2afa2db61815126790322cf2fc3dd6df89f71cce6fdfeec957cd7af55fef163061916b2d192199ee2bcacd0ec950120db1d580fcb56835ab2fd303d27e52f4bba5dc1e53ae5e3389f23297a735ee7e6bd07dd3d8e511e65418ab871d95fda8e578d8c855e33a497ead05cde2a7d7d9608c22065960f352aa5fa33fb29d099022163216f26079593501b76e198ebcfa4d6f834f0c47ef599f9fa8248bb59e15b25e4762a4e0ba3262e1a55a8fd9a39caf0a19490f5e0635508a4d597217e263e38811f4fcbb5f027b5954240a3c4e6696d209ddff3c6be25a3229e44da0b6a30844138edbaa4456a1cf17844e4bcf7094c7f7069cce177a77f0d0d1be36021de0fcb71429b6421ce8ae356fcd2d135301f008210c1ff02aa5886ae1ec6ca2a98b298a90ba30f93e3d2694755888601f9f8c4673a67dda32a34e0431708ecc36137ecd576ba30012e4da5d95aa2561b124ee86bfb8d81f843792b1d841f902c5a858a9e5b24fc50d23c9e49961f21a5997c1bb07f5b0c20d4bd4bf102a1b0cbb146cc3d350430629f020f10f73584aeffc93822f248784abfd13ff7472e49de8a24f8a8ca30593529121dd7ed35a9c6588b3544b70bdaaf1fa04df8b638aecf39dabe21daf76ade96fcbf9dff6ac4982d6ee790cb94b6ceae5c78849e6a34adfb0fc008c77384c9aeebb9a6e269a275ac7464ebeb5cd242ba4cd9608ecc3785d5c431fa29e999e89c550b76839ae54e2940f2815b9853760da071ad82db071a3e006b6b9abde04e107c7229a42872082e5d4f0d96cd1e26f031b46d14d30974599afe2f7e3d0f224b02ecaf1e60a9159a04ec6557bebd8523990674e59895f367d4582b852d353bd3c8919b62443b9acedd308fc89a2a934c33219c02a1a998a0d46306d5357836b1ab020e2ad89c0d23120c913cc44133ba3f186fce4ec36e6296a1bba68e72735e6d5dab9b1121454cd9c5b7b55e9d28d424188633d6db025a5a19053ace4a7b1f3ef1fc1177909d5eb57e3e2f13e11f575a57dcc90b22b73453ccb0284360899863a374c04debd9ed09116d2ed458d74b5d070a810b6befeb3238c8a90d67850afcb30d41309c1454956bd0c29be4b92436899da192d4e38e72446a0f4280dcaa543e7ec70548ba8c684734613bba300a80b2b86dab4718132ecada7e95ef30b2711a4651111b2a2b402f79d115052cda7415898545100c8f0a319738277d6ba09ddfdb61e173c7da0cb2ba95db0603175e542afe458206d469cdf2c52c6d4a54fa1a8e792cad402714b511bbfdcefc7c2c95620b4550c20797ad109eb34dd343d90a65b7469c0633d5ffa5c8396c0a429d8888a00abbe4d9fed17e27263434d318dc263dc4c0a81b22360efe2c1d60f0bfb4c16c9bcb8c1851dda2a7671a3844c8421b62edc9c3501c21ccfeca4c152797d2a229a0be699679e7535ac7361cc2a4d81d746a9b2748c6673939d347890f330e02cefcac1e6d2b8dab5392897743078a0454b9a2b2ba069468c25ba9097a40cbc20e40f1d8184671a15ad4cc8320610c830efe4c3dc4e8742d3591887d278f90d9432044e5b2d81bf4a487ca4919cac3087c19ddc9293982ef62c0502a3fb5149dac781b8dd09d5f8f092b24d21ba101aac5c7a2c59da119c15351c820069ef1d1d98e8f0a5dad2871652a06dea496aef95691ec2c306adbba00f72d913453a3beada27e5934b14d0e59ba6f6b532e5dcf70fb9c833b88c54cc788b14c563ba3f6ef6ac78ad1cc7990a5a44acee76c0f729c387d7ed79a26b949d8f4cbdb5f2aafe39ec2cbfff1de747447b38abf04dcb6a926d7be6d73dd6f26972608595dc23146e8d42eab5248341216ecb37c828f13d30edf8832d328f951709d362d0a3e152e6ade20788e0817e574b7b5726391fc3192704c4ca28878686b90fc227572078f88d534c32f177ed3a1679b7bae9aa9417173efc5c7168404c94003d112bdcc535efc2dee2cc639b59d299e2ac65e8e564ae43b5bc5b2c678f3cfcf19e1d5c6526ef631871c280988ce790689cfb48f8e41658f94b13dd204481c7d4dfb5eb18bc22075a788d41515c0e472ece71909eeb08b7a38e8c1b99683e0f4f9c10142ba00c6d1a7a1f848f2b10de780a0f26feae5d876c531fa234ed83042489e5889974cf893f1543eec737b4974a428835eb71c2f88101560d1683488c8877cba7af7d123eb986a0d0db1c1680e638acfb805e40a81686ccb6302a3110829085a40ce2a11d1f3e5849994c88c528c63f26e1fee6e32faf2941cdcb4fd002bf8da92057efe0bc17aed3550bb6ea734a77478c842fccb94dfc5e52afe530ff9b2326daff2207bfc27cd8eddaaf1d983a68d1b09fb132ab4e6c7e2324d807124c8aa5fbd2f54c3476fda77f05c5c13ac7ca14b24e2f594d094bfc36b6b10c49bbb1d3febb9bb8d3b6c59bfd7821b79cb5250b72e9f74592d70f000d056c796c43b0a900ba125042ef6ebcdcb7a56d073936100fa820d16cf885d9cc1e9f21decf769effa482510680fd2b2605040ec989a05b4e695225a4ba9d3f582d7891dfc0e01ed81f4e3b9a45376ff737711f7bd90dcb3e8fa4ac55bb53e191338e668f506b9eaa1aa2bb9607f10705220b2680c083fd7eb9a29f42e87bf75a1b4d6714e971560da93ddca1da6b69e7cb364c31482679ec697593cad270d29eba0c9d54575b72373c97cca4b13c646ff33e16f9fd54673505a4d0acc5ef433d1fc25ba406fe35b7c3236a7ab7ee49935c347b3226d7ca84894c2fdae58def3b3693cd4c407ac5744682aff96e90f2564739d5d8409f2db4875f5498a2063a77ce04535d089315465c3ba39d6d6b29a32b37b8000b6dc9a50713775072268c7dedbedf88db0f9a959c302ecc56d9ee781979bbe540c4b9ad237ac13e425c1b383ed7de5733453458440ca8d6152f854efe2ed7c60e1002f8a02c6a06ee0017fc944b05a2249e6b44bfd933c9ef3988d9e2edfdfd2d3baa95f2b0ac0a03c15deb392e97a3b55e49260a79904a0ec0f5edadbd5af3d339538132735da11d99de40d27f7ac5e9dce0710aec50094efa3d7938a421ffaa1435e23880bbdead983f08b99e3c783b2c7f38954b593966db5fd5201f2c14d258044c70f82f0a46ef21ad045bcf8283eca554103a92691debd8cd8ed3d4b7b11fbbe0e0a5258e9948c976fa46056451b22b990db4152eded2a198a9020912a3fcc252a156052e9a1b4ce09225d8b0e43641257fdf68b0b67c1fe2ba0b29f01c19843bf70c524c94343fda5295db317522a309ac24c6815208c8098fcd58e2af90b5a06480a7604215c0cd0095a8b298cd4bcabc90ec948cecaf4f61f65ef0d6eec444af0888d3509662735bd515f9b248b949894daf6c4cab9bc81b130bccf3fdb16508bc09eaf9984b9fe830e11e48aa47aef5a2a2769e805f5e1e5ec1f2aeab5efd79a208ca2969f1bb9460e5579b0c3ffe9197243fe2acd38e664e0861ccb59f8e09e330104e2ca4dd7b88a356ce0d14c1ef39f0a9c390b2850cc74f306c327cd2be80d1c7b158bc18fc3d830669f096b54101ba9f8c11c7f12041306f5e15863476626091c8d52c26ecac6c2ffb9b296f814fec4cc9cff6014bbc6601871e432371e5d4b8e4c074c81ada445694e76949c4592ad5d10c4bfc78c67e8c365254a7f93c170b027221f00bce8e2d2f05c476800ae99a9082052933608c501ae946eb084fb023a4001af736bfd9253838df9b708e6f5711fcd84da2702bd15e4e2945e18d4c45d192a1c3acbb5f8f1c61e20e5ae173419696d04bd68c43acf7224a79137f0d3e4a736edec8738b384af38be5a4d258575ccb3f4f8129c876a30177359a60d13911442b6fe2afe137aa8744791b33b8dd66853e28b3cd76e5301991843110a90f82b7e054e803770f24ed75cc18ad240f1dda3bcb1df0909c13a2a3a178807c295324436d499bb7cea689d16804c2a546576ba2892270e571a5c01fe5ce42c7fd0518b32e0e5f2d2af71b0d221c4a46d5ce799391c5806b5076d44de48fd01d061078347fa4b518e5c24e3fa4e6d35d0b110f99a9f362b5368c00bda9dea5bd160fec1c6850fd14deae68d6ede7f3a3570de7e1f7040b28cc8f510c7d351aac70fa247eab4693aa0480c8d01e0e901db89532cc9bb7dab6224c23e7ab8378277bb30a04d883e667b9977248be95eefd5c3aab21d39f188518932b1d69d59f495f64017bf064231731893b3dd17596d78010b10bba3d3720dbb2b4e63ab03d32eb4fc7d3ff83e1eaab27f50de0edfea0c68532ecbab30cc70d42e88789d3f6fac4c1955333f4c619957ca2bf24bb89a408703042ef5f5820a5f970c99ccd4650a71c0e01384ed87cf791a6d7b01b7516b6c653cb3e93d6df4b2010d701ab6e7ba519442cb9f95c14fd0038c01a2c8f5a6eba63cc3962608a22a3193245e3b44c8cfce0eb74ef934f362ed382f4176894ad05397689e55d99b1a550f09f2879b6f779ffadb2273b260d22231e763995d3c3b47055fe8b9c447f8426337a8e2b09fee9a31bb09a7fd2c08343b0e6cc158e73f3f50af10e09b2cc0dbe43c09ce7cb0f6f266503a9146f8768457654ca5136d7a407977b52cb3b03c54b6c49753585455577040c3f01c47049f1b92be6858971bac97aa5179b2cf84f7219df76b819a782d321fbdc52cd2057a37ef1db3f596af4583c164d60de4381c2c9ee5f659210187ca1b9a04f116d0fbb87e884cb8ec1eb191c699970ebdc2e8016feeb51bdc3f4ca8b0199700feaccedad5cab19d657b02e1734372e3352c8b17e55770f590136d113be1426186d3b22537bdfc8b98271ba428ac49f4cf5bfc7e99c007e7aaf7bbefe7944b84f30df23835b2a6e901510143c970d68193bcfa2ce7ea9602f01ec846e80c8d93871db47d0a220e1761e001bd794c6a0e62bf9be0901b498cfc6782daae8fcc7910810d6951ff83aa219defd00f8779ae3040f7629e6be4b03710c7bae9a591dc3034298019fd105929f0dc81413d9dc05e85cc2633683d5dc95fc32593717ea4b328dce2e5f9beeaaa2e494fd1106b2f6bdbac7fc64bead3c6d1d98fc2ebdde9c8854a607b776010d42ba0fabf95e4dd8219aaba04bd85dba43001b0d50f761280788d17e9bcca6a02d7544e82a1000cc195ceb136e8f7a4229db2c1e311c616d08590890de056293f9118d21b505c87a41d5496756dad1acdf532893edfa3f9b5f2b0aeae408fff75159f0ec1c82d037e2fd4c853884316b992c127b0d091b82ed41834c5c4d49dc3ae80aaebdb7578b2e590e247f0964f86a4439667a353e04644e9988dda060d8836af62f3a44046830766002ef6bba03270b1181fb9eb6e234710592b67009ed62e89c9059369e69705df44cd5534179b9cd0faa71bb386c035c7982ccb9e10b8bb556faf93d0f1e06ae61247e7f07b2d785a86dcc80ce29582f3c385aa8034851c213bf9bc44305e8c2ce9d0426c0f52d47f898668646b514ab2e2241c1abd261b5f13baf80b1e12ad1db3ac609c9caa553f018f1c82aca475f1f16d73445b4ffc6e0af03ddbbd178f21b2ea40e8e004e68284e2e6bfdf40e06d67b2914ba1b37d7b590a626927e2284417b888da9411983677c8b9a3cdc905c1b0f3487b99b6efdf77200b432c4608c9a60e95fb78291aaeab4a716d78e4a90908b9af2bb5d41c91b1c8504dbfb375f602e0c7e6245dd736daa3842ad3728e903c9ff1639ecae40d84da513b59d4245105ce3f733ca2ecd0c2a5f5c399bfb40f26f34a5b0b0c0fc0c093fd450f1e3653cf6715ea8bbe574b90e589a4af9179555d90d84cfaa6c248e33b3861d9b0a845827b397aceaac4df3025020e3828abfc25392b1098b14a20d64996b7a540ae7140673a68a729aff5c71c43171ae7a044e987044b0e7612fec022a7365fad1d29089925a959ba125572e1aa947323cafd7e833a1240fb8c60c54bbee6cbabbf473679f808c83e5553660f47250f6b2c1d1ce08a21f350eff6a1fcde5b2f01b7b2617c1f02d9b880d795b81974970432feab7d93d76361d7d0629ed8c54868937cddccbe22850e893e16f4c141598eb6b3df9551745f932daebeafe446431c9c9b78f4934e3ff3106935bab1015176dec37e90ac3a9090e545a2c0e3eb17fbb623cdaa3128c6ca5c44c667ac244253b84cc94608b574847cc1c50b30a577d9acca6b5206965ee8d98975638255583331a1df0a69457806ac5e0c0444292309a29f7cc8598ac2a179a2cab74ce337572cec9f2dd8168794da8c1e413c58186504c28e4457d4221d47ae2f733eb66443d0f3d36a1ead85acea7582a623a8b694ebfdd8ea301bd5e218c83f7af6fccf70a93b9fd889e29a0dedf31a252af4136ea4b37daf433412f49066ac9acea577d76cec9d1f29ad450d1c09973a12efa1a9a951ae7e6cce2425d0f9f3c3101bcbe6896d7a829c81ef60dbd60fea0591ede6e2294de91b93d84d6f402995e416057b53ffddefdfad4510247a03f21c926d5560b68ed9ad467f38a93088a6b1f5da6432fa0f72c648a6a20981bfd15af212a147595d7e8d29780f6d0bf024166fa99f4c623dfa0c3db91250e9075c973d8cd3e324a8a3a68ef41981fa8ccf9ee84d02eea008c875cc9a54a8f64131f540b6b72ac2933b24ce2520bd37550f12d856023b4986fb2c8805e48727f6c2c50df9b4ebc415c97fc44aab90d2f27e2620c5005bad74a66c87cbbdf7e17a21b803adc688d05f25dd4c26832d100b630a8e3e7fd02742fc1c5448532deea520435112acafca9dc09908cb8d6e8601406902ed6714f227effea5408f1782744bc52213777e662c85cd023d21e50e4c4a00701b40877da0bad4087cd10c52681cbeb1753e7c101f07f5b2a214c693b9ff2a3dbcfd851db058a0437f05beae019f92d75f08dfc3635780c7e9f127c06bf4f0d3e43bfa7089e31fd0f0d11246d4a740b274c696f5ba905bd1acec8acffb452a4f9d5559b056b123a71160c24f3153101fe56a2c00d86999f07ce270a532e36ec57fac13096605f9ba6483d98267e4b17dc47003e233fa70dce6e57985e4b70cc253f69418488afec5f72150123b460699119e0580e8bba7af006da0855efe7eadd469015b8abc574c66a57ebd47054e920b19ba2f65fe917e4c04d4f82aa24987883437271272978b1210ad7c65cc6953d789201e3cacdfa759cd2546bb9115338fab8e3da5b008c9c5e182f753e1c119cc93286a6dc4879701acef12c0749ba33a8504181044339437279419559ac172089b1202b0b9a72b3255a3996ca5e294b3c4ed4809ebbd8b09934a4fd2bcd358378cd7bb62ba3653b70108bc256b9d77594c966ebe21aa06845d858dc500f78cd9e866f4decd8bdd2e971cc54109f68b37c050c28cbb42ea724b62ed0667715f4ee218b256ea18c4986c2fd41d36df3cf5834ae99602efa38c7ffbf7ea1319cc10535d8a23f6060bd671534b8cced698394164c6e8368a830e909f333d6c34c3855b19868db2d6f02602748867c8b908389e97b073fcb06570592bda3366e54d0009f7d9ae4a43387b880d8c90ebfb18c04ccf3e48f994674527c123fe5e6b71ec913a05f13691045c2c8f1e1a232e93bd890192216d8a7556a4629f1fa7740c957cb5032ad3d0cba3a6547d001e1011ce5059729dcf9566d2f69686f75601428ac9d2bdc090f4f454dd6424df78ce70bbf096f9d09d1e4c15a252ce778355e84cf79a4f38c807eb1feb735f410474d247af54fdbd11f3c4fd10b5e96c642c4deff93ec3a5c697cec747fe9e9325f196b8ee1c44c45890d36d024a54e7d7ec02ec49f1ae197b0c184243aa0f86c294d713198fea818dec4137cc230acb0834eecfbd557c9d01fb07f3707b1ad5b39a4f8e0ae01f872c5b6f53eecc4d058d4e2e39a5f460bfd38b3b6d0c60baad8ff8bc69e683ce2f6af3a2e4a376ee34713484f5f5aae445be9ebe88b8086fb9b7cdf56bf9ea0dac87d77c12a5d869296f125a44c880f84b1be8a09b037cb87b9397a310a31ad137d0501c18a60c094f6592f00783d3066e5c8fc8239cf0906bdd5bbae1a67fcb643c148033f5c50941acbff1955b89fa905d99f139a16de1da54b3cf4b1b7e3fcfa6135b8c6aa2c6fa123a5ff40c954057c6a81e39f834b7bf5d56bcb6fc23ff835f95c82ae9ec8859b4da1f0287939543618f5a78e7f9fc4cf044b1dbfb74bc67843006e3e0235662e2fb72d673187c1c61778fb56cffe7cf266825b6e5ad8e7fe87aba4594dce01123bcb66c6e8ca912fee0cc1d31702785323cc933919d1b7f7ef8b3da7d66add592e63e88b72b92a9177bd07c062337207e94924ebb8395df808cfb851092e96b80388a425742022f72ea09cc7de632dabcdfa8383340677a695adab58573568f6ae2a0e03a74390e8f9b992540566c46da30dad9d82c2f8839af8ec2eb0bedc2357b3720fbeed398abbadbf4d7d8787c4cae231fa0d8571fe8319942fa095aa4c23b1418bf05ca3396e70414572ef9ebae5c15feadad4e714e6d92a3096bad7888ae0e6f8c5bcdb4641579f5933f4d64329ae4d9f5582f0720657a2ad3a73f187f312cc4e70cd0eccdc18b3df4e7b067c0baf35260155f87f382eeb828725b2b69ed2968154ddeb3d23e2d3fba160f0756907a06919dd2b15dcc419a0c50dbefca6a4cb95adf26bd171e2035f05b5bcc7813d8623b63153b925ac8271fb748df44479adb98a765949f09c69001e0e0db7cea22419ee87058d34f8be4eea7270ae64d8adf13813123b077df887fbe521ac862800df1c7770f39aa9aa4c22450e7d5c9547517cbe79ddb3151e729b097bcbdb4bdbe2a9dbd8ec32f70100508d84036437501c586401463bf4c9d9b05effaab06e841dff3e4d5f116341dffb97a039bd5045048a7592875857eb901bc5209390be4d8cdab7e8d8496589fd3340f65aab528df322c722474120e0bc91bbc29c3738bf43aa8cdf8d9aa9b97357edd70c20606de3ad4657ae2ec85890c724fea20cf29171e4264adb4bad353d2d98967dbff66b2e1abc408467a945d6ebb009945e39f043a54f044205c9aa114c76ea1dea5d20e60fc638fa35df17a0e70bd37cbfb7834dab6f32ab14ff5c9e44c9b89a5c9309c21b9872e75cbf8664c2c310eea14ae1677dc549505a40185f599ef0fcc5ad7d219c45f6bdef9664086bd07931e6e751890e640f1718c42980744fad5d49ccf9dc0f3aca92ce0b3c336e64015071cb6267de3093f920d4c51a605feeb9bf6a31aa4ca475c8ed26452ac3e74e14496853b4e0f820f2572b355d23543dd0229286789c27348b3f35a92c664a963958481c49c0098bffcddfc09dbd1fef99274c895db2bfedcf61efcd4a849028a2ea1654d730344a1250e70462c9b78e9c6bcca7fa85af0dcb42ebe224a520d824f4c1a6ee271215102d9de754046faddddf65442c6b3c7107b7fc25b6de21c74119fb5bde8e721e218a786204f4a1c89ed7e2f88fa178b793834b641fc707288647c8dc891b85ba831600a1e7c84eb35281d99434abec69fd2b311b06af6458969cc002a3ff3d3a109d904395cfbc5053a37df5a9b280623d44fdf07d448e127f53fee46ecd0fff21d7b92a35120ce1ace0877826105bf893d4a4b913f5dd92a40c84af0654e2e85617c99cd39b13184f4a78926e6025333a1d61ac6fa8857f167fad90d527131c4f2da4be8c697bd9b6cda8d6b8201f1216a0058937426645b83f1462cdcd5e8ab71f6dabdb92cf2dbe5fd9dcaa456751506180db1ccc9c568011ce0b8e1373df908e161734e3b7da10c5a007a3fec510bfec0a380675b44855bb17e4654ae594934077eb0b8ed3469e39e75ef11e79cec6a6e6481324f4a7d9c27fab24c41adaeb0628da42c44bd97d0463f329bd6a53fc8e2067267aeddd6ad9e2acb3a1552c635cad2cc3bc4bd02bf2e1f42b64902592a0ebf4cbe0133ec2da8b178a9296c8879fb04e6604ccf26371ff05999b178fe8d31e5741b3a8b55186e78c099191428c21fbcfeedb85a6198be6fc830fad987a60f47f43313eb72a49aa5f51233cd49e6ab7a8700698cd48d4c13687918d11bf59ac95e3aae679a3043d2ca8d99b4222bbea6ba416b0c492ea4366a2a228f385615c06ec739619bb035ed3225b894813b0812ef202b716ee052e06514237769e61789d95a26b1b0e58970952b1b24e1f3209acf8cde8cc917f650367b4a7503376281e51f4a1a3f7a87249354a630671a230c13cbe9d57cbc632e3b722371e61862b403c9b1048637bf9aefdbf8c6529db7102cac362832b652baae02324d2b9d0401d750df8527429be5e89f5208055410c316ccab8c700ae4a06754d5fbed5b6e9b6b4c8245fb59019c550ea648319c9bd47272b7b03e01472a018384251e1cdb58f040d9c5241f28149b70c2b07ed48049ae55131ff1e306881c068a2c198906c82839d8d4d303f215d0f501de5093d7a04f495ca82d54b05141bece06d016a1a2b239565f36ac266df1461559b2d3c34c68629f62c60f481f9f325a2a6203f881143813d34e3acb5a3e9fbbdd8a4738aef0fce663db40a218522b298dfbaa8a1d102cb6cc12b64f77acfb196e38c485d627093dc889ca124033e24d1a33eec2bdb634e60b5e0395f75d8aab193b4d290769a48d94e740ab82c94adcf8604a40805bbdc52f8fbc2a49e65a789c82ebbf55ce5c68296a653cfed5be44c5016e52a20e324013153cdbe009772c9ba351b34db65c9a99edcad14eb443fa1910c4a2d802b08552741711b8dccc9324448b9fd2de9244a9a59ea7594ab516a97fa7a67480a6f52c662e3205adc9cae4d12c9eebd296224ca5d91a07aeb651192f5d794b88a45bc8bde218d94ba92748e2549e2f846fbc31c582b7bca270629a3c2e958ef9bacc5ef34ec1813689b16e59c45464b5353a6683b44597b1a8845869a04a42c37e3ae964845b0c06637067a697f4fad40ae6a4f1398030a8d048f1ac82c71fdfd08d38f4f7fa891f64396ef8e261bf51e4ee4456020ec94c15256bbf3d706ee02f0a01d5c1ef296b865fa9dda39eebed2e0d394fcd9c3458280c6e730d843c49d0fd65bdd0dfdba480afa99fd3e06e29903649b9c1a2e2413d2f781550659cd74e3713ff92037f26ed499b1c2513777b002341906c7d88859a40b739ac1de102ea56a0f17029ebdfd645ff609b272413d8ba369bb97d5765d61c4111476b4171ca8c3675907df9e4148fffe574c1b34582f138418035a2ee2745a300cda4a07cbc0ff1d299d60cdda49244798f1b69358a11b08a96cd17027c854a084fc4a6f62cd0f787207e03e73fd68570cd3f14b01e1f8b917ff2d0478bea9081e76d32bb9928bb82d052184eef8fdc9de9b6cb9a594324919060724070707b928f42f440a3398f5a4cf83b4277f1e8cf120e8629607b18828f220569790071d162281ffb917227d0e839579580b2f4f79049fdf983004992c22752d1e0f71c2e37bdd0d12992ef9ead4765effc3a94bf92de82a280889153f541882640443d6b400e5ca51e5e1bb0b99ef13dfdddd34420a9b05786bdd7479eb4688b70e8648d663a4a1a0cf4f0dc650105158042183104a8428bf3d886b856fff6e745aac81f103140f3fdcd982b245070834df413447ceac302fa8b0d65a22cff6a0068431f44d748027a755950f4768956153e5db6d586cb47cfbadcd913642f800435f893082304458202342396403238820536641c162e44836c515ae8410cbf86024009dacbbbbb91011ebeeee4a67bc2501102470e1ad09d2f440c3f3f0edf6c5112275d27dd6647d63f540e507962f22fc50c4d797198448a1c508293144409921cd51fbf4e9f4dddd7dc3f6c882488ae21a313c48560b87c301f902e6d2afb57f1e0601be3df300e49b071ebe9b072476e0e17dea483df5cf12cd7eebd9fbbdeca32e29c75039f2018200b69c1cc51c84900e9a231ea7fe412df2c16288231f2060dc51cc419071c4335ef99cfa17a35d099d07fedb389224eb0fdcb7b7fba0543fff731d3546ef7f6970142b2b69da1a2158c1ac3144299834da7bbc5d606443558bc025ab6d07e42d4713cd441f0950f1e787688d0a2605d46b1075cfd00648f3ffdba4f1f3d42d68a229c68e0c538c1d19dea816f951a560caa7b30cc1eb2985aa514ffddaee7a0bbc2aef5e5d6b68833e8cb6d94420c41c1dd0f1818f26ea320fd5ad7e60d6e800df59e79fa0a27c7cc0a30333064dea0e680d1d933ac96892a77ef3808dfb75a456660cea624ecc89b9167362ee69cbe841940a7bc51dea2a5efce98e46aa6dfd513346cd5136622ec5cb1aa83d83a28fecc76bb687f141332bc9b7ff7483edd33f5d6b183df435eea016b990229a49232c7d775b3b2b6ef5f1e999f58ddb7cb346c29e9e7647d3a75823771eed12bda3cdfd48bf72164599ccdd667baa407666b1542d6a81a9ac9aa86ca23540a09ee6a8ada7d80cce7a5a3b4735118995a4a89a8884390c97ade4a8cce5a954dbe814a62ac526ea4a568fc5623c3cde3c6ed44d33c063a526c25252392a477577dba71ad544569a88c769057be9eb8dfaa916d1ab326789b2aaea7595eb255aa39d704dfbc9e22a10ad61976e57a7a7d76da661a9760af6b8e39258eaa170b5c84655206aa5d013668c965192e0f52496c25cbac8e6b450c730cc1ad6696ad2a06aa2a7ec978693c291c246a7a7220c76cd7491575620ea596bb4b6b8babcae1cefeb29f59ba348fb949f6819aa6df8a902516cc57a3836f58e86a9c63b622b166797688d5c2d1247fb54819c688d3ae2244a41d2d3259ee7f9ee91cc71bdbb6b77e81d861f9e9a3144a78e93f0532d12472ed80aadd123866152409dba9619833a8981d4118f6d44eb524d9404535a6aa21da0f3c8384777f0109fc7634e5341d6d8080d139914500f693887976838096ec24e6da358c993c04a4f1d86ab45580a86c3230cd723296229d8134fcb8af830beded531c61763d701c2ad158ed8639eb44e4b2908b43bc9a4a1e2e7c5b7eb5a6ba551d7e7743b5629a94aeb6dafac5a556f371159d75cd5724d13cda6b5da52759d9eac66de5a4a956bd5a294525aa56ad107746ac6b02ec308b1675413512f7a7555965924a5a232dc88d455fc1d653386553181ac5bb147b262d5b1674dcb59a7f32d094d6f49daf5166c4b2dbed58ab33c1f4c80b573cddbaf0f6a11a59ad3da5a6bad36dbaa451b176ee1a0ca53085219ccb4a995dc97ec6705593533cb2056be67ed15fc9c344c8099aaa9aaa2fec455cee9c662a5719a5cb3a02115823c5a5655a05912e5ecdd50f1fde1aa7aecf993b340be9e6a393dd9565ee50837d029fa88e396887b2b0315888aa1aa9a3472066a117daa4034b745bd39b942067447192793b513eeeb40196dc48e610251e7b1a1e2f3d854330675a31e7d10c976ea2d644eb271ad346974d58c41b9868660c0a865ae9001dd116c6caa0a445dc60f2218321d9869b47ce2e1a93d0d08814c5556eee98f5b620e974b8813d75769fd7ec7efa0ef854ba9e4e28a7a5cce399793463b75aac32ca2546ac23ca54a54429e7a98234f9d3ed5a2cfe9533bc9f36da681a86ad137760d5db8ad5e2386a78d483615552da23aa8a1544bc5f7484b3662fe590a59f399fae73384803df14d558b606316656e6bdcf8834836ee0b9dfa592691794b36ae71b354b2f2d49b4b13f553a7b86eab174444a4491d531898d4f59356e26d98c1f48fce19a6ce097e2a607af6aa94a9aff95906517a1a6e307d7a8fb9bb3d7b306350cfb3dc54b588ae40e6e92c715c32a5d56b8a6b2272cebc4693284d05cf1e4c1a3dce6c60db8ce1156822183428b6da4d152b22ceb2d3254fd225eff98c3a3d1dc1c6b9a2a70121fc3822c56faab6518aab454dd554383ad6a67aeaf474449750345c3e5dd7598c33c6b9c3d76275187b8e3fcf2f2dd7a2cf2fcd83ffbc03ff8da4e7197bd8f3e87b9e7b38478964bedeb977ded98862de7906459f986787c1603c3c3c7ea369248df4f73e30f468f3431a8ffbe058992805d93f1ad95bb0dae4652bc54ef08a78bd873ecff31bd4bdd17a5dee46a1a1a18e83bf9184f164e7414d542790656a618cfd463b1e3b1a693bbfdd0428059956289ff5599b3ef1f54c6b50bf794a0cb23d103fba727d56c75883ce617ea373d868495afef19607fd3c624a41a5d7d6d9b89fb5ef7cc2f82ea869165a833e1691cc6fc920d1f6d90b82a0df6807fdc7631a69c1ef601df8de48b3500aee5faab74fc38eea6bd6773b6b40c9891d8fa407df6e542dcdd22e32be64cc913147069c1332152850a4482193a950b162c56c26a34e8b162952c8642a54ac58319bfdfcb070e1c25db6e2675e4a014dc55c8162f6d334b70dc597a28bce8e9122f83c0b33b09f678c9f1bf427d480be5dc182d622bcf1034e9a8bf046ffbc2dc09fd0860b9f36e642f47111daa86fdb86e421122d44ba127bac2f5ebce8172fe88b7144aad55e0460084900e18d0eb2d9808006308049fef83c634c1f4100d4e88b596324086f6bb510e9bb2d56bf560e1d6760c4ce2f5e843760b88c3a31e468aad9d3ccc9ac6905d7ccc9ece9de4923f5b49f36a459fadcf7ade06aa2f977f6d4368b69f8d164ae8a10c9a62157179b869cbfaac175d06f5c0747d07f7cf61cf6d17e7ccf9c500ab2f58e8647db3717058e48dd8249e33651a6301fb5c45976daee6e447fb2b5b4b4b46a0633beb29f26eaadb6792d6a2e2f4f42f4d6f26c7ddad651dd488ad78ea4185471d7ea8a0f3c26f175348faea8f97c642f389df27d7312b5db39aa19d588d46db7c5b7bbbbf1ad4e6dad55566b9d330022cc490130634ccfdd3fb3986fd63e5a411f3a2f9edd7b69a55d5bc759ad467d9b4e6b63f5daf7f24d74f77aedcc34d3222fcb68d1e7d3468b4037aa401fcd4834aa40a207804983faacce49c3ce6e23f7ec559e51a781fd3a1ad149031b19e10e4ff8a8ad183ba573c6c0180498368e12abedc027315d1e27d01dc05fa1bf0b2801ae182700a31c2891bd2be606404c3846895fdd95af0d0fcdf9de3aadb578bce3bc47767647d53a9287248832d995d5a29087274693b14148eb0155d028f0d5e7ed49ed91950147ac3ea62022d52f9bb174559d3b08a6839d2767d51c3a47f8408788cf747c28d2761a682635d07c1b45961a680a21f6fcc4a293c3bd23c67e62d1a9a243e5195d8041021a8b4e0e9bc1a1889697214f5345702978ed90bba2c3043784111b4b4f694aa0fa92247765890d25a528466c10c161a921a1898d2155433cb121442aab7462a304ad0de828617d55cd1388267e6289d1e1c9fc02969831794964f1134b0c0b188b38fb892506c96725f2fcc41293f44535470e8c9f58614830c72b97475cc7d93f1e3ad5449d53fd9cde753d775a3d0df285cd534aa7a2ac48f1f0c03c77eedc918a727a828a59d0a3643505ca294793d0a630c7ad04941826da4473494a4be09089ac1cda2c3d4dfac00ec57d411fe4f092038391628a1c16e4e4f0608bcbcb615341268817b83c7040d69a5cfba12ac10f6b1c8041d9f1b8185830adf04f4d0c13d4d0dffee61cb2019c59e1cc2da8668361b1cf8c26648280f1b476bdab160177eedcf1b13807786685332bdc8fe28b6f4ec08fbf238f3a3b6bbf693f3aea33c2376b3588b479ae931e893231e726a2b44a29a594524a672c889383eb5f06c12e022d9822d2afafea5757659995a5a55565b81171188a759bc52ce69c6f36671773eebc3ef7130e87633a9a8eb7ba28a88128eeca2975575dd56fade9ac7c7b0725a7ebdbcb8ecbb777546cbaa92672d1357549dfdee1c84075913710ed6aa596f54a09574565bfacd795ba5197eb6ae127dc84b38e48cce5dbf114b6535add252d33366ad6ad4a85b5c85c75c156df2d70144e22f5dd7ebf9ae8e77a7dfb5d33b1e6a4f0dd2ba82e549bef9be4dbaf5213c92eae8beb082a299cb46bca264271d56ea5e07cdb269bb3f3b5e5bb76355109af59dfd54ae99bac53432ca9b5df6af876d28259fe560766f826a79ca822bee79df7bc9d92813949cdd02c2cdf5b49bdd43938409a8a4b775b7579e5f3649b69af96d3ed93ac4a2f7c3f5997eaac9a57f30b3749ca45f6d37777fbac4ddfeede224472ebc25984482eeccc340b87fb16fe1322b5b0220b332c707816487879162c9028f32c8e38e259f82c4462e19ed4fff88a10e9c70ee0674750fdcc558448b3152e0b9156a8b8f32a3c4588a4e226f1752493398a104956fb14377c0a3f1122a5f8ca148153853b4281c27d422414e2f827e434fd093711229df0f13c8b42241fd184115ede84f784482672091743a412b6d64541413d697ab07a7a5e7c4f8f8b4584f03d2e2b22eb7bdc8da0f23d3ed77c8ff384483d4344118329513c238a0710c5a1177d2a79b182174517e1e4f0a2cb4e78318e9d17dde615c38b1e5482a5173d16228937f1793c0c9178ac8d1131c3c71c0c916201a153da8e9897701e1a69c279fc133dbb0e0ffc78d1e79c347a88ef39f5ea4da239dfa87ab4ec301a0973f0619ed72367f77acc32f0a7383ccf79e8e8de67ec91df1b2d68db90d1056dcb3af2c8233b1d41ec94c7c9a01d3ceac7fcc33011d36622f6bc2c3cea831ea3e188b9e8e3d867a8009f1187e719f699f0461d1d48c3811d741b6ee0efe344ce578ffa9c317c9cc72c037f98cf878d382c685bf5fcf9cb307f133be68c41471ef9b38efa264c38ecd6361d17cc18d5c8440f1ddd57306354d7719b31866030cf43278366d8619e09186d6682c232cccbc069308ff90c15001b7164cf1f236fcc2fd133f6c831d1fdc5b147ed5133c84f9d8746693bb07f238ffa7787e73aa89c08dda3c9fc044dc98f4690790a2a2948ea9f83b058fddc9fe97b2349a98fcf309a8e9a4176ea39a45191b993adbf954dec7cf5a126a216ecd04145c98f94fcc8738fca092a285c46b31955d0a3e9f0c08fa782c24fd04640e1279c869fac6df5e7a3050dddba1ecfb37f1e6de6c5f01ed5cf10e6d166302d1ecd9bf2b2fc0ca91b75e73b72ce9e471cd8f3df19752fcbcf6ce4f760786f8af6a8241e7574b3b7638ffa748610b13da87a89169fd0127dd569a80841c2979a375344e61c39539472f08a3215441234ddc25587e98a84480d304980d85e413624c704576a30019c1d56a081cd521821a40411a10b92322abc176eb82424510394262648e29405c995365a7408a3c31926745cc85c51826891320526cc2cc2083744ca2d59547040f266e6b5606f188b45b116cddc754c90f8aef349cbd8ad753b55e78b0d288cc9a1ab841f3354719284a393041ba8a3b269c8779e54dd61e6a87dd70979891d15bb2ba54d0d56253cd1ba537524d6a207dca0640b570397d299a36cc97c97e32614479c6f71e4ac9a17c8423b7c9b89e77834c2e002eba39d47be5607bd560fb2631dbbce25c9ec08652e84c7f571df1963a44e09375a623ce0c081db93b7bf3e8bd82922c48899cec372c71cb7d76264e9817e9646aa7cfe591a39a1fc668c113d21166e0dde2ee8a27c349d832e8994dff3b35c5a23fbb208098f1dc4eed86d411ded07dfd147212c5994fd2c89104144abaa6f9873ab8e48cef2eb5707698d165d106d3e6eb76c453edd01dd7a4bfb992d76511055130b619ec05046ce51f59f269212c9af851541d3d7fd5489d4ed639f61033ad0b69fafb36d20ad41bfaaf966ad6dfee336918d48fbc88e648ee6fa3aca5c10e79332b10219f54f0ddd43be598baa5f9f209bbee315ead341a0944677d55d753974a5d75f39f75eddaa6bc3bd82e2eed862cf4f392aa790a1f2534e2147e5282ac5c5d5468bd20a942ac855a05441915a414e4b08ca5a6badb5d6363535d55c6dd26aaee6ea207aab8368aee6aa545555555db854aa2eb5aaea5e4ac7faf4244485ea537daaa195eead9deb5c17b9b79794ba48e73ad7820c11ee37a77f73cc9da5a2ca3235b350613335723596d4c8d55852a3a926d444946571d26650d2a5a253744e2f23a32a9bdbb24df7da243667973c4d7a3d986be604a8072318c277e8d62a343444c3acf282c14ab8b59fb793d97962e29773f6d0bf9c4bd0643edb66e43d6e5461220f8d1caa0a8d4226111cc976cc0346f37ae8efd08d33b7de86214f8e812e446be42b4429b830999362f7e08d1c9a4143f7cead871d11bd7148c80a75a390100adfac2d71d94203f5413f6d3823e7cf9879ff698399acff3a7036118e91d845bf9de70d5a3b923c6ce865c7a106b0b7236d13deb0fef967bbcaaef7d0660532aa31ea61ee2229d7e7ea337b3bd5ca397f341c22b5504e848d5cdf47494b8a19dfaebfcf23ede89451dfeb51dff410883282882b3e1027992b499ecc95a44f00063e6deb29238838de983f9dfa6c3a11a9d7376bd57f1cd9fa659c7327f3bf30826eb9c393fe8c016e471f57b0c3461fd6dbf1e800eadee8a33af50ae49b35f24ae192620ec48f62e3950fd754892e359117133fa7ef734e1db46957fd3c74fa81340ba6889f8763677367eda7836ef039cc3fd8e7f341bf2112f881df375a3a52adb64db25a7596671e9a95aa964bdbaa7f14b4483c32a6945a1df471d88d96aa6dd5bb9e8ea4b5b2b25556aa02592e966a0791a45a5c526012eadfd7cb3363f43c422479baaed3c0fae737ac7f947a97ddab3f7e34aa1d6d875a7fe38eefb32e68918f243847245db80b5b7ea947319fad559b3a91e6315a484724bb37ba00836eab32dd59d61556e09114c1d563da8aae155c33275632c64db5a26bf684674fd746c13e180c36929e5f918a488a1c7cf6b39f1139d4a117f3783ccf796261ad2192f7d9d0adb5a10dddba98dffa17d26e3b48233fbf9de7d6fa3c56264c715edf27d02b087a6c2461220c2207356752bc437fbffccd180db434d0ba966dc23becd7ba28764771e826c2f81ba3d5300cc31f0f822208bad725a6b81b2638b3078ea4f8dda8e2279d1e3c29936d552615dcbb8e93582d19e38c4712e78931c6184b055d96ab2ca5c555a099b15c5d6ca526d12fa0a192430984c0512335074c1839658088214dd3085263605e993159c418638c31c6f331c618bb80ab4033638cb1956c7d8a6deed4174ebc34fb9d2125de2ba781260730d869204feaccdfbff7de8bedbd3e6150fa7befbd335a2881da160ee3768107bdb5a0f1b50e5a4a29b5d6eba351a893cf067ad6d01c98d1e48792346ca67409a3c58ae9071d7e4cc9a1882c31805193e54e95333ad05862822a2fe454804a530587c7b85400149c3425308571526786139e9f65952e5865edc9dae7a8fdc5b45a0c8ca874a540c7da2a5bde5a6bdd5a5badb5555e786bdd67c613db54ecbc8b9f65952455828ce0fa2c03d8539ebf23697d96c14cf3414f623cc349c4d8eddf71d610c9f2a0df5daabdd65e5ba7841dcfeb045a71b5d7da6badb5d65a3b9271300a493e003fcb146e48c10a05203aac0c6547cacd2670b8c589c0d5161276f84213250a064d26a8d13ad3c52486890b53d58b1c6e71728ec141336f15130a20d34773321154411307c893375d7006b093c4cc102d38227c3952027be408131e0e44863092a5240d982d2dca3421c20419b0e8d839ea8e647d77848d48c6037f96506d32545843f016275719610055862a89b3e9b0077f3647ead3a16c58aa7995505cbeeb6a5e36d37e96504fa094b29d3d69125a1c54dac1bcae9c856210edcf126a04ef4ef6b219d6e16bc994279c00ff2c4ff852e1a35144ea3d5e7b4eafd46b90a61178223357506a816f36d1bcf7de3bbbaffbbaaffbe677bf1147bbf56ac3fad4f63a7bb976edcf5a58adddb45a1f9d670ffcf8aaa3fe1d715487517c04881268786e71728b9fe5094c667293179fda84c544beb6368b9fe59423a6fc9026e6840213ad1eea0451e1cc950b60c6883083d451d704654c3e8331ae615c4e31f218638c31c6425ba68430831132883e3ed4a08317295e9e9c55425562accae66b6b4b997adbcf72ca95294f4f0645c1526dc55de76fe660b132048822ae54c10202a4cd10261411e7868cafad52b04891fa9642a58ba78e007e9652708fc99840734384899718de9410028d324c99aa375f5868ea94b0e3cd8132bbaeabd382d2094fe67c29296dad09e149112a4854c170c4d4c533ebdce2e4173fcba7328f7f964f644cc839f7add5d66aadcd6d445861d42c11dbac619521db6aa565d769a35eeb5427525b2304e7fa8553b335384f5c66882092414143375875af858c10b3cf0f41cfa0d37003d0b397fd0369a1675a06a0872389a3739883383a076938a87ff373e76ed438aa7bb9a38f4dd07ab234e1eb7faedf70031c5566c3eb1fce007b3792382ec6816938b05f9f21aed5418a8da8d5e4585be3c02dc7ad080edc6a8ffb38aa8360e739bbe75f9e25103b9fdf7ef3cfdc833e1d6d8ffb78c461fd8e43bc2a245544683549a208a7339e181c0b66d2dc995a1204093250e3045f4808020e141166b8ea2ae17051422748112460a0081d303ee4aeb0a074316900852e2430e9503546870be4664ca162650810282e27a047e808f9c1871d5048b345e668fac480cdd4af5fea382e38d2a6948a24504a13040c93285da264518a0235bd37b71b93120f139398953a021532e9a163b255a2b130190166a2c6d2a46b6b4741929de69bdbed4b9690490a22932232392b961061c39d38260071b3a509072170544dce68a9a14d93252e884bbc1020cc12269e25527a6c08a26acc92281898bc1113c70816921e9aa03113a5e44d4c091d15605a00d36469088e0cedd2039210b4a8b06507255b605602b0bac5c14aacc49434f9ae5302f55dfeee0b1c99122026aa6e71f2f7b38ca26462879b179ab35259426f725e3a610b105e6fde6c89e10813c25439428622565c5e0d5e95074f727237b450cac91ded70f244a72cc2c40914906fb7659420df9ea1d849a36525e6276709068a9c92830ed83c19a45579986f6eb7ae282357554ab0852987b0045348d0d08406ac21921c8125795283865b9c24251c6901bcc5393243ecc898b062b9c5c9267e96507290a334fb594279e184ef6a5e2306425f44f0670985c993321a449e9f2514a59741c165153f4b27216857ad6615a4e6450309352febd4021317b4ab565b2148cdcb3a355921d4ebaac96aef49925ae65d87976a5e5d76d029a9e6653d143fcb2770644872d7be1dee3aecc64b52171c72261852e6044d475278b3031036776ef80e490b5e979b11beb6f613366acaaeebbacee797ef9060692b69aac070f07e964fac722e6690f9fc2c9f484d71070a9ad99be611e8eb8b49649dc5db136fc3b77e6791e77962983752ea7402d119fda6b507e8eb96189678790bf441288cd9debeb22591cc426c7a86900bfef50ee664d7751decde194268776735f2feedbc1bede30bbecd3f2e0fee62a5dedde149e66e847919c4ddd449d9f58f0cc1db4c2b52bdf7e924bad3c6aadb78ef12f169c938a06557eef26824c445ec7e964e5a4fce52a88b130f4fca6cc941072efe2c9dc63c19a455d958a9e9dfb76f2edf42f4c07407cd1c252c6c8ea69692254360f84188d59da3765950772ff94aa39e0090d5643f7e2449ee49e84dd775b4d63d0a0d81812dc5cff249094eec38e59c4f1932c392395496b8b152df3edbf38f2915baea248979418d972d4f86226c90d0300488244c477309961ea43081612a923b121a22480a53998c57f7b694284c7dfd4aebd3eca497b3e78ed6a3eee0615d47f75dd7e3019c57a8048ed5553909111909000090006315000018100a89042391389406a2b0b90714800a749a426a4c30130743418ec32888612008a218038c310620640c320a19950d02043759ce9c6b0904bcf5f909cbd65c7481c2654205b7cc431d905cf7a0b1ac251e5f4c3ba8e83c6eb8c8e30831950f372c0ac03bfc9392f890f6a39d1546cb6ea70a26f746c1ce99a1a830b658290af32dc76053f5b5e173fbb0109395ca4b160026d2de9ea58d9b32e9d65c28f7f0cc2f6d20ac224b8642085c140908a60f39b8b0e97b61af82ed0f8696c6d98210e2e9d4fa865c9a159d58e6415c969cae8fb5ac8a0e7a52e1bcdc290180471e28472e33c3f82f04e57ba58a0d3ec5018801479ab7a847562863c2c2c3b188025231826125a9516128ed36181611843238f8b3b59a80d5aacffde539b05d2104127ff964a8be111385fcfe4e34065683b6f51cbd7f4f1b48100aa4e581a80021185654809e170918192093965276ac45f0dc93004792bf39d8fbfbf506d47712608edbe95243aeb20ff80cd57e49b929a848ac62d28272e50ae7b0ad1d3b39b1bd8b7cc7cc48b4a7d6f7fd3a05e453c235b4c341bf4cab861dd157bb66538d99d642305b00b899d6b39c6955c7ae76933b92b418b6be169322c74484cef2d4a3311c38d2f77ecc75d2b47e578f171a11598b5700a47d8f867b9801d0c6d5c0b54c4c89d41de34ccdd3fd25f75d09a6f1dfa95d7c4f24f7ef5c7bbcb036e29e2683b478d9ce96fe2457c7a189f55723afe846e473607a4d6ea524999fb75d75c89d4aa02e22c8328bfd7923f99bef705981fcc22d2b42725a1cae42c25cad0b83ef047666a8fa7b0bab3eeb178f246b2d684db38355e6f6726eb691628308c0a72a08e83d1c56555f78792ffff171952e7e85180ead0af2c022a80b079e3851646f2ca51fde564d26db8599be577df87cbda5bccda0a6855b6cd0c540161e1d3ecc00cd7d7cc855c4dee61e3f04ce30b9737b702d7523aad30c700d65776288e4e4eb6b6c172ce43ae534952cd9a63232ad2b65cb260c2b5fdb7ca9a5bfd7f97dfb7138ca17b6a44c6cfa6553d7cfd78ee5f38c756f1b1af0a356423615a197961c425f647afcb00649d493a87a4cc8bf683df756bc5e59dd153801af5bd9f102f1578b5cd38919f45e3bdf723132962a3f544824f1df6c68a2ae620cb821e96e004025e5484f072d52ee597f59a7f06259b30baac796fd7841d5727c4e420af9b1c2adc6d9a6497e770d762496fe6dedcf58029ee0810fdebedb47a03fcb648245cee0b863d2ea8d664be90dd624069cc701cbc883e13f728b454031085629874adb5765ca39e8b2473eccdb76fdf7fe2c1b7c9ef090dcc8714e6910b339679873198313f6692e470a2b6591d4173c1813465969d40f32a2f6303ba7a0d470f4199021103bbca1db19e9554aa71335ebe8d8f7e2c08576e9e7da245271a62efe396a6f843a642e74e8699634f72a1ff2ee5d882a6524e7554ab3755d2411add001489d7625fa78d15fd22bbf94b1e7855b80387eb2f82c529f7b43dbdc7b31c7ef8569b492bb33880135eba6df0713d60a796a0088bcdb45c38a82efe85471abe4f283f0217be852cf32ad5f62003ee16677d549602a0c294791dbd76cd6082c17241d22ed8b064521165a80e3648024a46f4dc7a4ac27889b26b3d6e50684677bb3b747d8619ce40041f0b90403998066ed893052251fdd28b8e151acd7ba16eed5b970512a363fc4ca293068cde17df822a8b024699c14364a84da38c07dd1d32efd77214c231ac22c6956d589fefa88c49304fb5b69623ba22afd4c4cab51e8c14ba39b7ba87e43941bbd445a717670ecb96ca1b27e480571cd3288abc113716a167e168a3ba28e1f86bbf1862dd873b7aab4ea423ca4697edc1dc1dfecb79b263498edbeaa0b5eee480f8cbe6bbd0649a84de084c00c47f6683306c773aa85473e80a964024c30a04c800081e83190ff402552ae8b363bd364077c1da3221b0ca23d2569ef963d3db4a380bb249640e0fce3c776f40701581db2ae8a9d8a03940b1dc43bcec7e8cbbe50a82d05ba20f09259262436c8308fbe5db0ae5cb44b94756be3d2a4a2dfd3b106e5edfc57de022b0e29c0f643588941bbafa793ade209611e5974df089fd4e8d5c165dee0d1d01038088c6e84d6f172e4886cdc605e549f0d9fb40feae386dbc7d3ad9e696663e50b5803cfdf0ff5f4d41658bed053865ba31627fd22ad11371cc44bcc8d115d1e55d79245ff584c9ffaa98a48c2a8451d198b26cdaf60cf72461dead2f2e9f9965d06bc0228f69b82763ca3b594de80204456de8d671aa9c5fc7e581f940a7fa9d03fbd30d0bc38272ff15f0d280798973429149358fc8ec78acd126a744055c34eda8da0a5940a4e70bac84e1adbff3b8a76bc2ca4a3c432b30e29a87939cace2689006dcaf9c366dacfd1fc465e55e7a5d83a8de753caeb01c198c0e9d4aabcb1aa5b4156dca9153f6275fe8410a328b98ab1dac2672a09e0f9e416a88523955f78b31862bd06aa81f641e919a5e522bc11d42af53baeba4d8a2edd90c48fcb4e2cf74e8ce4674178b89e3880bbd87012d7daa33eb5d4cef5ec396a410baaf811b1bbacebaea9053680d9c3e111ec6981a26d0f87694b23971f49212afe0859753765f69723ff60c00f4aafb4f8379d9a882f2530abf7707b09b828411c02a194bc3894cc6a14d1bf6ab3e9ded9438b58b0e703906e141e11fb98b8016aacfe0406789bf060c72b5125310c11d18b9a9b83cd8c81f4634d7e621e5609a80f3bb2e00a35bd223b04f4165fc590682ececdd57e9e5063ed4bd958fab95e9c846fe63f11a5d27290c17c4730d6736dad0a6a7dc4a1a8ca1e60f8e94467bdbce4ce9970423c1300be3d8b27a069e8b521087e3ad1c78bc25d728bb71a82949e6182e540f75025c4c46d366d9272b89c3fe06d922c484f1ec195ace85b874f30c447935b891d07bea6aee4955887df38edd77be8c4d80e44094a16de801d3177583a4d52ac29de965dadfbb35512f9b956d93938203ddc200b6a14066d4a6b07cfad3e0c7d9ed5d8a14d08f849998720c6549b027e46100549707f7bebdcddeb86f37172a7bccd9cf626f760889ed0077d0513b49fc0b21eb5ab28c6c58cfee6ce78cb638a584a2734201cdb4061dc06cd3e82c3f624e58ed53c089267441558a3e387b2f528dbaf66cd263a9a12938859034fd29066072372e49f80fc3b21e6af4ea5e063cec0658a866dcb047d9d05f615d6c10a0a8f437807b74ecd70842aabe06051960f91cdf2fdc86824cb10318af1ca034015f00a20feea6c74470c41830d4993eaa0e5cf95779cc1e1ca1a1da5664b5f62c479580ea432b468a8ba4d6f133ced7bb3f116712144335f60d35dc6a0901d04b35ff34824d34c21ca8db918ce57cd403b540edb5ebf2f24c9f40e4c5fd4785318577d418b6b7067d322f381aa54d749e01a2298e53d079f0a38499e9816a3f09d1a1a27d273fabee72c621b87e907c8d09312ebc86b7ef74df1db48ea535d032c02182b8836b187d8996fe82573c6b778036e137ce82330363110726452dff445148173f181f0387c4e8d7b39fbf5746c3ee45de773d2ceac3133776f6fcf26b0faa0430f0ce7b59d83a3fe18a4a682e4e37ae7e11891428f8c5033646c78c1a027da5b6ae9110ba2a44fade25660675add24bdcb0fa8e6652d2edd22fe5dfd9d8270ca877fe9088a5e0b46e020c3ebe01c7db0b920d0a68144f342745d36b5cfdf25d7bde689cc055e99020c22419a5431a467624beec4a6176cbbcd36083137dbbd2fb7a400c38d983262eb330d75ce34e8b3efead9f52f5ac324d138a61432b5e4163ba1704f4e487242f72354a4c78183cc463f8378a2b9dac09bb7f3393f933ed97158921be9fd59918e1f31f1acd582463e9095e0d39dbb265e81cf77e65f480af3f58bd0202f020998c52326aa2f11282a86527287582bd5bb443e4474491dd2d1232a11db9392447213d2295c201b458b739719b01f303f42b6bc968b49dd96f988418d403e497c40c5485eda287887eebfeee89881cfe44168556e76f0481fec4cb59afda220bae47ea7a7e0f1ab0bbb687a1de5f3006cf279478d19e64a8a7543a9df9ae08ee21b956e85fa203b657728802d862283e24b1d7e42f408ce47f5e832283c026dc826506352d231e357184fc7e2218ed53616481fa5d2d7017e6801c406bc26c2b025c70b2c2a6455dbc94fd693831fb99c10c5e489cd15b18cfdba45cb98bbbe38403a00569db12ff8cd65dd771c63b6775b2ac4204e8ea49ef6b1391dd7c5373299cec29c1c7e8151ff8c83871db75c865d2fe0b356afe6f218b9b0041e43f3bb0fe2118dd607a4012aaec9e357ec0bf33f00e3ca001e8ef1ffcad037e3c0cc11d7cc9d37555afe582efa51033f0ec06e0f3e9d878e34ded4a69b44d50bb4a9a2ee771cb97ea0204f9e1a72da7fd0cd6d6868cca6960353066fec53caa32e0d40af76dd5f649f623db8cea0079f34d5ec8e90b6b926d962eb91ae3befb680c6e4bba3cb416b0208c84eee5ff062e64bd3f16ada1c480c56eeb7161e4c11ff156f568e6c4876af6bc94c05e5f6589ef421b64bc2e9a0f1e0db4692a6bf1b86d1f4397df5a66dadda272babe77725deb8238701453114fd4b8da57ab027e1ccfd8f6b225f109aa90863ddbb599ac22b9105ef735369afea56ca108b7f3abc9b0772e621458a18c1f8fe7e236e29483a46888f6d0c5ef64c95fcef2247746332d862e37737004998ca914436ca3c3f06e33a1c45a8bb2e76603b38ef66a66bda3c46d530ba37c07b214ab5af90172484f4bb99f7a4ceea2243e91df91b40108cfc3a8ebcf7efd277f6dcb2773dd3c340587ce0a62137d2b079663c1129d25bb117ee701f7aa20a03c817305a9e657b5fd4a2fab7843e4f8080ffdad3dea21bd9b614075b021ecd7515c31a3f07ba4a18ec455bb9854e99c5dae071ef3bd24b7e133db7cf07ba5379d23d1436b53193974e34233dd1c60954a9660fd1eab2896bd283d20c1949b394d16daa1927008f54e7528a1e309883e0094a7b3356da35b9029faf00322c05917d3925a4ef31e8ea408fb71f558e05a6f7eb10238415f23eec31f3b159afe8bba9597026f395e9fa8532b9121df7c5d2692a319f9b21d387e22be86bcf4026eb94481e8107c56fcc050fe1c84d2c201ca6194b1dd20d60b5ed784f8f73f2f6459c35c6d82bdb8db87670aef751fce78737ceec7b5704c9a40ea544bb5ec0dbdc12593efbb3165ff129d02970855ca9377eae0592e54728b2d84292a5e6248b98e0af93a1824ab871f6b3229b4340174f7169a061b1c3f0d09426c8883d8895b1ad2917ae417748b0441cbeae3c90904d44fcdd10833633c063dd451f88e64bdc240c621b2eae22219e5381be9d26124945641c1238dcb7fca1ceb87c4e37992c3623e08f2b4c248dd33f606f0b4618331308021540ad4b8b46eb46c359b4465959f254adbeb9f72eb1f85986ad26ea75aed544fb6fafadc28e22d6e694c5d59e9cc80d74687f56ab259c7e557b5588d3cb46ca973525b794b8fd9f75550ff59a84c60915d5bc5e163832b447308a88a69a32e818dd292b8eef84d7c00f6ed2312a9240f9826dc379f157fa078a115ab2b53968559e9edd9fcdc7d44261b6035c741f908d0fb25098f8416138b15125be48156a04c095d04505740308f2110731c1fcb71e03b7ddd5ed58c676e710fd7ae82eac64b4021db6e72003bbb34e897133de8083e38db27aab76fbce78f56a855964ec8d839bd3b2f8011795d1339f79e65da31dbf3e26cb20902567610b56538b53c356bcd708a50ee32ade65cde08e436a5117cc3d119d2c8fe2b4b5b81a2b607764d34932ce5aa79e8372467bec1fb9d9541d384c1d46dedb6a00a8297b6473265b88e2046118064f440ce72d7abd33ec2a166c5671993207f812ba45af56226b26a0dae37d26567b5a9de2a149e9c1280323a9bd80ad23d73a863321134e1738249e335048b61ec33343ef95cd0589330a7452830f95d316c7367969392b84851cc622ee227d3c339348c5e315f3c60c8613d3a77207d67e6208bed3a3df2a2202e005489a455f12a5d61d25ec1267905da54193f4cf69c3910c9fdb439a768057d94b627071d38e20f089923c792e14f577e3f4f8315dd8949c1eed18e8e7437ffd34004e143c602927c7114d75c7f3fd8f3bc7a39a433eded13b051bc8eb2e2943684889b12da0d2bea00110588366733e3ff573c107e7aa5f00a96d6a222bee9648199cac2a83433500bfe899e056d5232ad3b37010908ba0af66a4b2a475a6ed198d481c1e446426b7def172888a8a43cb1a6283a199595677f97d4b0846a01550f788769e0f8c62d1b2d4bd6b8156c4cc5eb39c6f7927f84da062c536bac1c9cffdf712a8b1e65cbffac220353f8c062bed3bd6739b2a3088d1d08cf698543d6ff2daacd60e6cf53b75ef045a619f9fec2f32649faafc026b958f40087579cc6d20891cb4a663266cebfeac1f2816d6bc4a06eb8e8d28a870c9a88489ddefc255331dd6e989c556dce807345f1a872fced4b8006e2ea8f4b9257bc15b7fb2c5cdc03a82ffee35c01564ae8997a3dc27d691fb53d08f34d0fc6723d7313659f5a6d7f51cb9c6eb4a5a52ac6697bc8cdf0b7ae306bbfcef08f4d901b295dddfa9364802e3ae3a5ac146d8e043b911e03d58eb5afd161ecbbdbacfa34e0fa275af0fa7ae12619149292c2581bad58e751d8ab692e33d17e6715efca88ef939934bb806b1d48ab9c33236bfa7774d81fbe0952be568158b6f9652016cfbecd5c15405503c766dae1ab543e67e5dbf225fdfaee03876266b44d7ab89cec90f7353ded571ac76fc77a1384fa49a8300982ec5cb790deafe23c7e17bc9c13d48a933359ffe2901bd6ef28285bec2232a0d675247192667e5476abbfd13dcd0e2409cbee6c15480ce901734ac1ee2d3968d8c8cf5d334ac6f2c4d70aed8fc36a811ce7861668e4eb9fcd2be75f6b18a26de2faed46b6f5d4461c5f91b551fe253c9e5d1edb435460ed9b08610ed326fe56647776aa1c676ea9606e5faf1825e7999cc2b16fed4edd8c5800aef329c46ed5770dabd9f9b31ba24645ca1e476edede9ca034fabf7e5c3065572030c9ada125a868bfc4331cebdef0e502f06eea56e7aabe3496fbbe2afaab1dda3c5bdbd06d4f6a62e9c4a10913eb45d1da0b9e9b8e10b92405b826869ebfaf109700d6f28a07ab9f0a0e37dd806d80b26cf0923c0f5d282941212a1eff85e2e6b60285d4791188f2f1a2c4dce6a346b7879404ae8b3b9c2f31a4f3291ec09cf1b492171b795bf4687682f5625dce53dd3a4f5c3612f0ad6aa359832ae726a55552aedfdd951d52fa603403bf3cb24c37c3af7e3893e5d82c5114a54e826c96d17a1b5362e33e1c23b7900747141d3520b428538a2dd97f6480021576642e9b731a2240b0ddbe4fdd6a352fa77c80c605e750aacfc4436617a6ff3988e91b7fc87d21354de7bac0be01707451dc9233042a7e81d19b478d7e5666bdbc92967152fc30d1c74d374ed630328c0d1dbb91c23b4fe6dc3a5e496d0f5d8547c0ba07960aea2ffce7801c3ec0a811d61fa1d4697f5f0e3c79912dea37ef5bf6c26fb24d14fa8cd1d515acf8e8577c61db31df700beea112be36f2b61ada437f50949f59a1028744022a0b9a1a292181a279f62a7c481605f9cdb027860587b6388ede2d8bae854a6833832f808351e02adf5e5c7be9fa765582e535082c55d72c44ec7b2dceebaebd34a9337a5320802f9f1280e65f0d2e28c6563c99960d7400b822b2851986003443f133ccb89006767c3ffbe00a556e403afef2bdb0bc28fde91fc163123961c0aa217671089a904505cb0751a9a794719c18d101cc1ecc3ef792a37e99697b60ac816ed3ca622f9b558d4306a1511887c5c0118f751ace5fbef539f01413aadfb440d14758692ad1eda75f757fa58fc5d39097525f0eb19d2565e649423b5ded0798fd27139748c072629790968b478470667fe24b8d47444228fac13e50d54c51bda49c0dc396133acc7781425200abaf3fb61caf44bfa5894ea06d3409363c2743980d87bbe73f8e9ec6a2c73de23569274f1e367231aff91092e402968152d35ba1ba714e7a2c12408ddeeceec8d2910087450d425ea14b091c35ed245ede166af81e2b6c7c74b804109c6e564c1ab6a0f0230d142717e661cfb83226d604d79cbebad25d3695f3fa84c711bad70d69ac3df4fe7d7abff24299cb934fc5eacb2e079adf667175f524990eb50378126e4c3b3a7601b75307f632c2c7fe26cb72b42881b6f4951bddf7c82c976543a3ed70c4c9326dcf58779789c1f310ffaf06afacce9f492b7555d6885a697f3d374327018bb9065c1a9b16280adf3593a82750e5f415f9f3d61004780a96a5f28b55789d50b90449d73ad559fa0fd1d86ba80910abb774a794487061585df91e0adf3f370e8b092886aa7d88ef7b76e5ebf73913ae7291642d3a165816590aff3aac19f9b3078bf7f43ae7c25d5bcba98f0da998ac357c0c495edde25c7b2487d3842734e016ce90026cfb90d6c77ada2e51c2c8142ea1234589c054b387003e0d046565f2ac427c1aa75fc291012205d2487835c598df6eb3cb4c406852cc393c47f38d95662cea562fb45f957c382860e184fe7199e9cbec48b5e91b618efad74fe92df0c319d9efe03a9e97ba20989e4ea537511503072e6db1e8b7cbafc28f7272004295799347472fed0ea7647d3904bd2fa943248934a4d5520389a10b0e1eca0eb691f333815642c8e00f55fd4113adebe1ca12ac478ae23a511b3f5cd456bdd7c462994eecbbfbf33a8c0488d162b3f59d56a3b97c52a506eceee6688890702d421258875871f04d1c820a1c6753008fbea4d421a0dfa9ddff8d2363afe163ec536c4bef9b2ecd45cff2250c0036bb1eab847190fe09d0c332fad03bc62236b7b2c84257f544c37f532cd7b9cd6f1b5c4abd7c6fce6262099041bafb0664671a2837c9a918bfad7f14a2f5237d2e7d696a9356ef9674072a50931c1202628f8302560c3d141e7e93e6e708ab10f3fa33874481b8843b4f0c615fcfa4b738cbd51b75a55bc4949a2b3a147f6709399328e51a867d21daf9163c58fe480267b97c81e1f4b064d4256eb2870cb6f5366bf6d2a5ae864c681a9d812ac03fa943bd04945c0e88aec9b1ff4cf425e5c17365db048841026fa17e18addf22a099debdd5bd463172cd9bd3b8f672b25ab7d05aa30eae86322827f2b8b27d55bf6eaca9be58e12f9fd0ab05d45f6fc47fd5922933a3f16b25b8a05e0f0a7644821ac25c5ff8bed461c2420f4130ae85837eeb5d37d068f01f7be4c0f2baa0d5834b4314be260be0dadd8640198c9a6d1da3d1f7723a2756ff28eada35488c2879e2b9b9a60249c07f6260ac40d38fc93b257610b3aa598bff44b4a3e0a93cb6d17af8b4e2b6e7c6a1e3682b525e1e37a191af3fb7ebe5d7915c64d83b4638e00f47c25604194905e4b5fcd79f3d7c5ca01566ce1bb15ea1773b0abf4d236cfcc63fd6d3feca55e21e872e262af6d4e5276b4ea41359c54ed52f6f107b59c60359da60ba1a479afb66cd67231d8271b60b0af9a749d6ced0e896b28f08f856098e1fc8a7bb6983604bd246bfed0d6938ab65af790790c1e508b1269e4da2f9490c9356ba2e9fbfff3b4e7435e04daef74585104aaba42c36af765589db165bec2a9e61c236733bd83ded33e66702ac843b50134f97037d8a6a064a37ddd263667e94d8dcc52bbf003392d82aa26df142caa9eaf129addb45bc1392b3179982a850d0a9da1327800c9b4d285e5bec0fda36ea7c147914fc05ca1cd8e1a592e7bfe56cd74a3c286dc83be3f442831172833cde089bc164cd08e8f2228c55fbc1aaf6eca3f29f28b1f1290f4948bfe7d236979e223e36fdcb2cd4eb7508a77ddcba333d29ffcd352c1753174be53dc4f6cc2ee5b806ca9a4d9f3ab3a6c050450f99b322edcdadfcf7be1a7ef72d3e3de8ebcb15f6491b803a8945aae411cd0282f67244b4408bfd95d0d6101faa78c985f924a819e4a1eb064503aa1e3297af2e8dd69bed43e2ab149ffc94db89bf4b46e4a8ad26984c8b2293d811f62c25a7aea93726bb9de4b231034255f4b8de6b021551c164448c9a7a71506983e8cc5b88b5b1341009b103f600aa30c5ab9038189957733ff6c29bc0a743802721d4c4920334dd1f9ac8169f6fc73d806a67ef13782d307e5d5a0e06142ef5274e881a95926dfd50453bcf909a6b2ee80c28ab2571f21d249a87fb6f19b9c57f444c50aae9a47741af88d9125943c38df904e43d73622131ca7a75841c261a40274ca871a2af05ca30a722042dcaad5f2d2943c0cb74f312b96ff01df629240b4279f653957b9c5ae611537ba34c1a9f343b3e8cd1f6b4637b79579b88940bb75c56573c813673f61251abc3c1d66671255d085a7688fac38e7f0b97284fc9d23c2a357b7da65acacb252bc2ee94edb3f2826ce574b7ff85541b216d855f98596449e2256820cb250bf6b35c91914a1d6d816e0fe0ed1ea6436a8ad66169ce9687f79028d0a8118846085c6ffb5bd120d60cd5aaa13c010d099590651e59f3b11e77bfbaac4b842c7f20755c72d958c63ac9aea73f6c9ddd19cc9d0fc2fe0238b157cf707620277c0e3150f348b8ec5b86378268d39f25044619d4f032935640b82bfa431e30ca2d12767a144862818a92c1382234bb4528dffbdf9861a643e5a4ce9405d00376a699ab2a74df7bae6c6f44c64b6387da659d4f041028e1d7923cb786f94a8c603a2342c948154a38da56bed04fc0834f4fd7a2d869d0034ad5bb646e6f4141b8928c3561199f8f430949e86154997fb68b965276e5604e23a4560432dc340ba7d3057425d10d7364039bf65ad4a3a3c1871701592d627ea4182891f681f709db36dd07398d3a5419990a8dc2e2f3d02c6fdaf31a79e0939f76ba614e4470095ff0b93375a5e2f1108157de56d995f1a0a2ea346e5492b6350f644d087cd906dcf93675d287e1737269f84212fb51f67238774cb3f188508a26d9550f53fdd8a84c6bc91c53fda2d5179b71dc17f20ce4501929edca6082dc7487d850945ece3eb33902212741910ddd4efca96d943a931658e59b1273f10ce92d4442a0e64c54e841007dcf4fca029505a3b7ca51fc425e16fbd5d509d07d69850360f56070e717b3c0197ab4fc27c202c009650e6757bcab32c1a0d5ffcac162b05377a2a04594512ae8552ab1c9e59cae30787b22443b8f6c07e8497430b8bccaee901f0be41a0366da8646f4ecdb2536e393bd60507613bb4d4cb4c2b9454f64c61ac98139d42eb5d637281ad3448b8d210f4b6524d1b9533300f5f8e2161ffa2355c0d41853839ee3f13cd6c091278240f19ebea40f4ff59cf0af444a40ae7922ad7271becddfb8590455d6ecb8b13623b7d22954421b6a96f4784fe5a943174f1ef7b6a5db0669cd2ff45b68c6553e8403d53455f4e9468c1c645c1ada9ffd25de6f8785e0004826d4da8728c9987538964e4992ac3d7df50f095f0635a50b5089a778a356efddd8c1644e91582a259b109cf46ecb4f5ac189ad052edf57d0dab23558b8fe879381cee77ac7b1d57e0c23cd540cadd89c461e61aff870762c3e4de608cbe342fad0556174096b0ca30d48e2f095695b7cc95ccf386a469fe88f6774607e4c53e03131ba8f771d86015d1b9733f21e459d89569b1328605b725fc28a979bc72c7100ab81690f7cfc54fe039a195c66bf11ce736f061e313e718c1721f2d2c604ef55e6c25858d5ab9b67d1f71432f61d0f1d902a52ee7b1c07e46e07a500191aeaaa430de1ab3608a0c91561106aaad7d5df597a063d430dc9f9581a0020990d55fb35ac222ae6d0c84b3e826e110d6e8e0b5ea675d487a9f547f12d1022a5c31c19481944f1e81509be6bcd29d05677c04354c5fdf9056799e89948d8d52e030660eaf0cac281647d599e91ae04d2db15d98d71fdc437b0f650eed3eeec764a1992abad409fbb55949b39b1bfe458304deaf7154b0f13603993d9f4abac4e925fdde6d07e3f98082284582fb9931a1a5b55f36ce92d2a562ae1cb4ee65ce45dc68268479752b02045f2ddc4b380c6a149414f807d6dfb13e41f78ccebbdbbb9554bcd64be663193e630f4232605c230975e7d947731ae4b389b61fcd25ad1042f804aa63994b31c1cf25fb3224c1fabf4297d9ae4b9f5e6418b9d55255646bec6ce11ab5a50b31ce7b418086df1268e481b953fb4bea455202ce2574c991977f42d9aa3564c339308cadfa532886216d385ee017c3795445f10151f1addb4df42b0f3f36076f6164963aea5bafc18304064683346201bc1a6bead9297059915b39b2b85d4cfdb15927409bdf8e023c762526b46e2ba440085a700a90eada594095b7e521af9e7508fab63ed98f6335e4c887feb188bc7a7388a62acf1afa1114aba1d9d69e561872395ced1484fb67cdaf1c1c9bd673304d7fa8373f7412a536d17ae588a937a5efe4e05336c5da92163cae9e7b60528198490363428169b7201a28a5d37c10e66e3580feb5a612fa15396436c164e15dd3c304cadc6e4f11a5eac2ab419bb1ff088d176e74b274088faecab1bcdd24e5c7735863624d711c501013b0cdc2e306bbb529ea0e1ecf95baf320d4c9a5312f0d0cdbdb99a5235e6f9f8399b55e196fe5405d6e63f37cd1ae20dae6f0de8f62200f731f86c990221e27dd0db5c79a863946d765a96293046a83e0118f3c46e0722f15b8575be0a101cb431930657437942ebce52e2be21c664013da5d49a5e0bac222f10c72ae6fa78cd413e3707266ed7aa205f916c77d0b52b5782a4664b5918916be5baad76d6e8f4bdd9e0fa5c5ec0f9a79589b6a881550ce237525f51edfbdae6b6a249362f1a696fc18e0ab9ac8ff0a02dbcf755dfcf8488b4b70d4bcaecbe63ec226027982c23878d0735af1000ed9d8441d408e90b111a39c28b92f4875dfc3811806713d835ba18b14ba8bd567f646fab48f9b756a2eb92f9a1ff315f35bd765d902d2ac07507bdd848ce9b15a31f147511f4e666e68d4ee633219fe602611f2d7f310f2b8664ca622fd61c1a87db9aaddbd8f8a68e55e2dbb110e25d8ec192b594334c87d12ed3eb17df55b0332c2c438b67d440512ef90c0b47ed8c06143a0579f8c503f248629982890ff826b7ce9d3bdee5a1f1c5dcb7a7803bba87d09f275501717086a133d913b7ff948936a2016b6d04c6f16e460dbd6965e509f519a91bf46cbda32b82657acf5a529479a846bcdadfb00562e806daa1d24c0ab99269f2548769c6ea8809debe3366771af87b392d7cb7a6025202da8713c03ff3a6973b43419918fb2c717c91125d0c66d66a5bdd8e030dc46017567490f6bad46ff5a6743bb2ac638a3323e696baba58ee14c9476d4728002f215ee8ed2da6aaed2fe787efde22c49cf60754cefd111b6cc68f884e516b1dfd8343d31f93501c28d4fab9094f0d8a2f3d0178161801891eeb57bb4a44db051fb4cc16021d100928d0c85d2713be6a2be0fd1458d6b25fe72a30ddac7782d87abdeae4e2b33868c026b669a55af0fb8c9a34a97b278954f44167fe14ab33f6d9d7d50b60fbe0ade21ea1978e8421160bdf898f08d4fdec2289b05ac7d1cd31f7ba9a2b283bacb1f54566d97fb018b1707a480f19cc1a0c916ef8a94752ea460261877a3035da3d894c7665d2dbb7311e925ae8cd5bbed198b81c020b13ad0191a3411e0bc10342035a30ea172e78f16955579206e4e4b0189e9903bdadcbff1309059b35b6e6785aad8b1f957d6a6225d58a31ed8bdfd2716a7e9702cfec1acd91f0a594c88d7e9eec057a4c94c8469d1bbd0b8f9f435f00aa0259fe1076719d638bf9301e4d7c9b494915c10a08d1ae5b9773585f6e8426668d6ac09ee935ceb4eb9b1df29e893295f755b45c84480e38c87f6acc8b593657ec3e0f51081bb8537cedf4e16bfce18c7bfd7ae089e3c764584993b9900be61684d22959975fd7003f1161c5a3cde139771239cda9ef83419501d5065146b460259c758b29a2cf27181de23ad2903d0bde14ecafd99a4b03379756a496be0523ad417780309a5349de66d55ad23bd9d2e0fe766be8be27424a97823398bcefdaa1d09ed3008364a8a5fd5544f9698f848a3084f4f4590d00e8360a35cf1d362e56aeaa2d71696fc47c7208e7ed476a11ed0cfb5ae20b7836275845fd00c3fe30a66e6c79992542d1c44643516b3160acefe12aaeb10d214fe730de30dff46aaf1959d6f6fe48dcd3a0be50dfd0ee209dacb1f8515fb79bd38f2a6fe8aadb4a658c94b99ae904f882bedf035b30cf8e2b664465644383f99ba25ed957c7ab3a0386f4563ded78189ebd3d1a371de50df988b13e17db1c2b93c9fa0f50d637f4ed50b9af5fad54186115cddeeaad9c4c23d1153f4ddc910aba8dcdc63500f8a30b0819d7827d48a00388362661f131de545ace8f11c5a04af2942ab7866ce216b0954a1233470709c0e05e37568a10266a644fd3161de09451d831c3e7468b05c78a6551ad3cbf056b25c266d8c4c2e5a06379cfb1cfc2ed3ada60dc17e24f94b3b517a7b3474602c6d93dca86aeafcbdc5dccef235a5b3cf095d44fb3818becc68764c0e79baaed7032f8c86479413da0ccf32a1869d47c94f267decad843de4a2bc1cf17e1e51016c93cac69997e14a26cda8deab7d852b9f3ca4f7199a2411871b6335d697e3e89261360061a7d9ab7b6fe8fd395819432ae2e4c2d577c3c0b8b97326aac0568d1503aeb395a60c7979b0e3888ad01c554bb66e505b5fc563d6377fa9700ce2a39bdef9d7b09fe506da41e170fbbcc8cea4601f3ebd177ffbde73c10ebba1423a91877743ac7ec059b009b2e9f6415dd4d44ba6bc543732fbb378f311bd1b3027e34be323e0c601e31d0907bd9a12b11c5171a11af7852a4f94ac3fd2f3255308128abcdf611f5c3644b1b7281e9b41caa654865410fa376ac3beebfd7ce61de80d56a81da98d8610c53de5cebfb610d7d547b84c9ec37eba1ec413a506a5506d8e4dd35bd5abc03d4c9fceb1e94652a0f810744aae0a29f9cf831b8ebdc59ae8160485fe1778498522edd6d9a18ea54f2630bd076e885b69407527f3f10f0b494b29d25dd7e930329ae2834520f338dfaa47d3f2001887dd3d12a3acb633e2d7558d103bb4370839af49ddda6c12cd977c6aa2e2355b8b1fdf0c124ffba103415549662ac24b32a083d452b762d4ae2416c439eb92a787f7b7521046916077c5933f90ed1c0d33bf98cec56801442fcdbe65b55d2eb2310bcc59aa71721795302ef011a8a7520932566bba572175030b5bc716b370d9a198a8399880c59fcb6b55aef4d773524f36a28d7f11dd3862abf058f245d3b508452712f7d72f1cf2ca5f6c29c386995305bebc8782079fc709f1061e4b4fee4c4a9f713fcddb9db71716dc431db63b76096f354a0d56803802f8ff29905a58110297e167cd88dd8f4b0409487f9bc26510fc48829817e8e1c4890e4186a2bda35664c88e7ba12f3ce0b171b5083484c19c3ab530fa184e17dc802120950310c6bcdef24928d138069ab608a640222d7c8526011a781a1a4e718d831ff269647a1e904766dd98498b3f9d469a984ed9e725a2b92d41e2db1429b3b845d2bbc8a37a8d2032952a1f2cc4067581af6d2bcdc44f905732ccbd264dc11732a402d29d187f494a4dec60929e38dcd84f7faf8d3b64055094987def5a5fc230477eb1ad0572cc0f718985ddc8490b1e3f1bd1538f1f72a003308ac8c1df58d2a67fafc31dcd522d490f4bda9484683e4564c0e626730938427fc25461a285cd530b7f27be6baa08f223f3a5f99e1d7ec8cb8cd56e40b843b209f9e241ff1628a2f908ac3e45e41fa289c3f464c0d5f93075b0feda419ea4d36f5a59353c7a453e554aa811464ddc4b2712b06250a29506d39abb84227ce4b921655297bcffb62841d55876785527d2301bbd63883a9a501e68a2f8a601e42a8d9983d1beb00857c3b5bebe187042efab6d91b5ddb670382fcf469793759edcb40e85f6f56866815aa0d0fcba11fc55f0e363665ff546b3cf6708821c1590048dc6bd8c38089a047567079ef15e4ae1ed89450df0ddd0e6f199caf295f0306cdc2444497b2ce3c8149c39bd2c0593b492928fa2919136400e51cb8c8daac6105b0460e9c49a02b7ea3f539cca2a98ba3f0d482dc2c552ead599cf22e176cd1ce2afadcce43bc7ed4d39b9dfd257798b560a834e6bf41dd061b1319bc33e92d15398584b0615bf59c4361c1be29f892aa2413bef4145c9a62a4603ed33d06de83568bdbd4e60e15286227f1a3df7830e9b57aa0449b2d365e90a3ce8e34bd137bc0fe3385e285a144b8c83ccb312d48dcd074e2941eaea5b6ef5479f448dbb4e6f12a6cb207c8aeef1368028e6ab837ae18af4a1c71539320350ee388f1782d3c6b4beeb9e7910b56b65414ed9a8af1560387fbf494330fa6600bcaa93e2fa8800dc8030da21527a9d3ce85d67d789df4085431881d4e4bda613c7d954c4df91f3053eb4186f4a1bf7c66252a6dddfa8c34639f1a742cdea0c05ecea5d0e598c16dca108c98cade11a1be792578bec2308fea40fbbc01888c81b4110299ca7c00fb050924c2fad926eda6eda4070e1201843675ef7c279cb5b4023996fec61c0909a0f50492dc924bf0e517075337cdf4c39c719276a72776f4fd0a1b3f14a15e3d8d97be1e4d1f246f54ca4634f25220d8f9d4c2f3124a3ed55510444dbad33f32f6a6d79b5bb20e12d44ea1ca03e7c97ea510c67641ba0d0648d3efac8da609e514efcc1a89fead14f21d74bbf47b313e812799eaae41b6d37a7af18c4a99d7ce7db9893234b488e84fefb966fbbf14bdc1a4a2ec58bc5b464f716e2dd7be2b47e247b3b1c7d7295a6efc6adbd2cf87487947e8e7beb9b6dae1e1c989c850df38439fdfb19aa3c736b7c65e6772b3241b524240074ee488568485677bdbf73351e77e221e44dc57bfe265775d85bce223f6457c31c004810d1b2de45c6e24b526a3494942c0585f4b284c43db5f3bb6351297f7ed30d2948fa9798285385074a43d07b5cb32f0dace61a0208abeea856522744069899100eeb5d9be56bdff6f59030f09a8f92ae52917c5903abfd2b6d26f7c58725d0da5f69f3be3e59e067d4b3e37d2f89d6474d810ff32d1c0e7107aafd5502ce9787580d41166b9d9149ea736dd167b32d03872c81d67e95c4f3e521be86e0137f605a2d81f78998037ffd2a61e7e3a386cf25f0737dc67a211f96aea0d6438f6402cc831550958b902bd91ea7e731d71dd04fb83a120314fc0c49a0d590bfe0f45da54bc458cb940e9653d21520ff85688878c2fdab712f3fbb6fa483640d94f9c72c3991412788d0f6bfd3402d7237c2cf7d4643f1b2ed8e0c3a9a182a4a9b6a2c78e8fd5cbd1b8f401dbecbaf5872da8794e5408ec709c4c253412bc639d699b091fbb432e8041b37b1d06d11c57e4ab1ee9c780ae3ecb9449968b339fa08125e81b4f52149881db64a406010d8d29287c08f06f29e091c093d7c274822610e11a9e5b1613c0e674d6fc09074e5c9d2d0c80f1bd883cce105d8342a855eecb9d71717cd0e05e5e222b3f82c129096305de0608e46cbc6d67748cbd0cf4654fc817860700e18cb5269b1fe6559a5e6322b232585a88b222f5d61ada73e1cb3429840ff7499f615df7e95da382e1e0e4ec554df4284042b79407f480911b18b6084afcc3c8740909b73a12ecca6fe242e27a2497010c485a64f35aaf7874e26ea032da937add48655b46fae39392223f63c868377711c4ed4dcddf98cd9fb593cb9bccc72973067859a240d33a7e025ba400349038ab936066b1c58f256747a98fa42b5a2972f0ef65663055f25d48789514d0ec6cb2d1847189e836adeb2490a2fb3a3dc19ab6760095f5d425ac34a567dfaeff340123828a0152c143d7a05974478a51d8ffbbdf8d3958a6ef28370ad6bc7f3a04809a78443e9261cdb620d378c248efd98c8a8da98d8d047180679773f786a072a9813308d8b00413a56b7052578389c25c0d4a362ad4034bda4ca423f770116a230a14cd47215ec66ac383098f9e13f4d848399db9c84258533a8b7ab326cd0a41a0ead1404ddc8d7f9964d5695ce5e99f907f0ce2aa28e717f5158d0047f3b86ebcdd02ebbe5879dd8cd27e60691ad8302e913ce7cce2af28dd464cef730947a6833235981e9aa12caec70303c4e52f8c027e934fb92a8a3a55fa0488979ed9947eefb6c39ddf681d64fcc333de4fb6d247bd0c3f9fc6a9c6a4e20d988b417aa4a61cdbd62f79358fb8adfc5633f70cc5d0b05cdb756a2ca866d185d22518579501555a0e47d58660c412d98d249d46e7d270ec7ffa230e93485f88f92c189afd1a8c331a9b1ed08d30de8d7ada17c1742b9db6b488221110f9941367eb8f47105301edf43d830bf1ce932ac4a06c58b8d305850ed48f2419c74f47ba98bb2ce1ec66d5220b8273d4ff2d15dddf3fc36b809e017092b3dbf1700d95d7bb29580272bce9a1642049bc3043db088e7994a90ee6c1064562a2e957349182a96fa0006841063abfccdcaf7ac48955a31828204a193c768bc20884dbdb8334528d8dc3f5fa45206eda2250c5b446600c152c033fab6a617e387c87846ae6e39f91047c9150c86058453a4417f0e6d67aa5442f48d90c93166e94ca0cec8b324fe441c4f7410d8a8dc2848b8c63d75e97ac258a0aefa8a70468f34ae2925e0b8c30575e7ecc0c78707016d712d665fd0bc63ced1b1a7c2a8f97516dea822fb76dc448a5edf2b55ea92f5f3041706f70771a9190c69f2f66c306c1b019bb0d4fd4a78e6a9d73657bb113fc633e28fd77fea7c24c388d046efcc242f98a9a21de0dbaa88d868e2d18ce114c53ba073358495701125780f8b58d312692e601a1d97ffd6c9b9fe4d4bc19fb8b60604054538c3e6adc2d64cce23a5ab10d82f2d594d3ab0e09841b0b112efb19c2a6e3914876a7df40cb65c6e0846d2869ce542e1f25f9d06ffd882efa13e5f482d640c43c5a41e2a12945b3dcd1bac9cf64193d48aec2b63808bdafadcf67c077a9fa4bb543c4b425dc892ed699d73d067b1698b377018e293dde6b0cde9c7057a1ffb0bf4462d42f8ad9f8947739c6fdea9cc79961e1ad08047ae77cb484b07af5207ee121999236d151568cf7212d99876c313072529f7a479e4d73df7a4691d6421b09844dd1a9bf38bcb69ec2b5f8da3fadb44e7d9149de830a5056ae5f2dc1f4b719cb7b9d55fdd3043fdc61722bb8fc790a8527ba7270fc62b61888d215f186b4358a9fe0e34ce7b1608c371adde4412745000c38c844b02514a6bdeecde9c742c356f5e02c5184285f701ad782bd10586b66a07c01341b1b9186e03d5a9b0e4dc32aaea0577412e0e14846bea82a75d5a90cb4efbeb9e7d7a1e55939461df5d983e4e74a02f95b837e395053c2b08b488b82c28abbddf8cc9e98f9aebd4a70416b2734ae739a177315b1073cb46bce298c4fa8e6a82bc7d63a950a7c20074e886b24560eaffbc837d609a43155856200240e213e0c6578fb415ea778228be065bd72eca2582b174e73eb90560a62f6a2f2f38d201b3bba728a171bff676d10480f3a9f31e6dea54353ea41bb24d90e96e929e65aa93dba7e649a2141d9fcfeff3f31be30154f0271ae6b49fd5abdd97199d9d92c0994516412f15a0f6cebbf5e4783e7d739d6c2d279d83d3ae04b9752abd68eb2c6c4e0bba037be2571c57e1e01906fc13619448a0cd3577f7ce3d2a05f7530152553f9ba363e4f2c617168723738ed1e144c09736857e0ecefb1032e17981d30b81f53f3c23e16f98a39eed1f8a62ec943ade2654b91397281dae75f00079b572b29d9cd676b8358c380b384ea2422271cc2936c4eed234594eb43201bb5621938b7dc591ce2b20235f1e8543c1490ace10e414ab60157c6432d88d90be951da002e02a91dd0fe4d064255a8abd2addf55a4f71b641e3120fc4f7a831fc9b0c8a27dcd9fdd12a05c5728cd381ccddebef0296b1cf37fa83ce51af2990f20bb284845141114b7bbaac2fe8e2ea4149d49e071f4da8788ac8ccefb49f260487c81155b45799f3dd00726f74281e95969bb44f6d099fabb875e1a3e92a296efa093f2d44326464ba4652add2662727e0988afd50836e592837f57bd88f2530a20bbc29fc3d08f6c561775498a603e7ba562a06b2e7c7f257d6b21a34eec1df01d465641ce9257145833a419abdbe6b0daac71ba91b40f7f9060e06614819b1d02d3f6f2ff5c02bd0542256ca93a604142a590e812c8919278139692d638323185eafed048c51eb5e1f605e6355d281b45e9cee158081425b81389234dd5889e70a34af4b389d90019fd33ac58c1e1343934302c2ac779223c4a69eb133695f236aa8521097c46d8b43d1412b422a08498606f2bbc6ea4540d841ecba008b7b1aa5e85257d526c12a852883d2bae2d433eb97d116269cfeca700c621ca944953029f55c43547882c2bfed8750478ca257022a9f1e1315ced868237d10901a42c1dcf32b4033e58577e93f3cb2ce51d0e3274669c44f3b8c62a7cfaa00e7acf044573521b2bfdd680deacee54cca27657c5322c717180c4cf19d8e20be524918cb5149a69d6dc37c5a4d6a0039214dca5bddbded62b3e63aaa4bde6fd41626c2566fe11fe633a5694012d6b353f175c9eb19ca1ad25d02aeb9586dae999dd0dedbe4623904f94f5a4c0741e192bc4c294bb651ee3d7310d99323537924296ea8e18f8d9616b94e009a07e6e4ebe59281ed31f6f08164b9ab9ddcb9570e3423d81e3a6e4faea3520d3f461cf4767890701b72ef60b237dbe061ccce5b35555088fbcf534febf62b357809990d5db3250a471962287b122ed40c6a0d9e71ea82c98a91cd7bf0d3c4d118a8250c4d1c5987c4581a6febe334fb895be2703491befa598047a64ed0aa95d201327f8e124399f5ce00ba7739a7b90d7d9aff7c58e5036032060c970a700d851dc23706dc530f2c140dd8bbb56072a4453aed64ba043db8ac739cb987e064535c761801d30d58c77810def7bcedd4904a2252c94ec37a020f5ffe87aaf872d8f6bd0e2470af0b4594823e6a7643e291024c3978b8ad40f8963670091493a660937294efa581ca8c8c5684339a09357a69f9bc0baa4649c974234d77222c8e3b76fc2ab08b6b5c4267ab6697d120ff8a635830324149bf55fc705fc09f8e4905e1c5071af1f6a56478bf4f15001e39a1b9c128ac8f38719750e0ef800b2d8dcdcb391ea9973a0f2be11408a1e2c63b84d178b23e249289cdabc22171cf505f9d130401a12d1f87977027da0ab7316ded4b0512fae9d927e9621c5c5b61c9928a42286506869b360665fdb5d8efc1c1974d861e59600e45cadff72ccdc3a97e2ffcb918ac0f3a7d0fc0a822959b047d253e044b464ebb6ca1d0812466a784111608ab4d6ed7b6b2f62a5a948d276318a8e71323f18bf4b20481ac87081105e5b4c7ec85cb0740fbec8161feea796c045c2df71f8744501588fbd535195b5745ae74ca43058c35db926bf634f37a51a655db4b7bbe9de709eaf5b9c800e6c2a5292eec9d91562718905d7021b8fee40c2c7261cf3ab0032f811c6473d603ac2b46e26c19ee9e6a2947f674d9e409e5fe482fbf9e06a8b2cfea35fa3ea11a6ca73a1b63ec8cfafc0f27f1171dcb0df4f8b2aab849e3ac57f08cfb1b25a4ae2a9e822bf6742771c2878c8ff70abde039a7c47d69c49b2ea781efbc70eea9d7bf8eb4fd5addf64e901f3d0d43bdee6fd5182214109961f297f4e7300cd0cf52b92174227b917d23a7138cb595254849a700fab5d105b7659f40cd262441f98ea0f6dd8fd78b53f32ae6fbf04f988a568190f22597a6ffabf185e125b0a319e249a5e5c683a34acb214e1751c57af9692a1c2aa6f16227ef263ab41c9fcdb461e7ec25402bdb81d462b1ca3d4f8e2071a66a481908da9df287bb73d55e6734504a6cdd67cd22b96a4a13088a7af58abdfd4c900d1f12e11519a5a2f8b7b36e46a0c5fd34d954fa7ac0d1328d6a3bca429da0c86cfe7e1b808d3c08bdf50e964cb14bad649e8834916d583e4ede40d1203d6b8bede74e934ac8c3fa8ca1d44573e2efb031a0698bedea92f3ded65c7e5917985540e95e503e27b2b4f508f4668ea2b8e2ebb411c8845e9d34598495854f992753cde7636ea726d4c86630eb55aeeb64b834ce1bf6649f56b593bdf92337ca9c33d51533e333e18046a5e6d8935d3740d5040a17536d5c4d6c906d66fe98ccd872edb95cc836c1b79288d51ccaac765be4f6459537485f7c3862f6c40bb9aeeee91724e23357bcbbd4faba9402f4ab4b4643172c8c3c1aa6190757e8078d3235168eaf6be22f5d0c56381909b1f5b52b1c77f52423d32742dc1ee0221c1941b4840f91224bdd5a309454c274783d3887f86f6b551bb1d118742d8f015e9cc604d5499e04dd1117123e2bcdc17f7c13c493355c517a5237f7c2f7c094008da4b01c2722594451d901bfa24a3245a6a6ca254257be50dc176493dd90ca686fec55b599a4f8cdadd0411bb23628d0fabb30ccb766eb78020b42bfd53044551b9c6869654dc48ac4e8009bd931b697888fc1cd93750f63dec02f454f84d1158a958433de339a90d23d5b84f3fd845c2671d3015fc910800aae14fb8ee77ff854fd9d7b612a194ec1f837eb3e88dc524c20a483cebf9d5bce81cde1c7157f9dfc429a32c63a61ad94851a28cceebb0be32062fe9f340c9636d54f328de21bbf354ce014b9f6019ae16e361c2b36bfc2008d8e21da688bf12c56d4b8a7b0cd6b3250c35a53c8b96d05093ddf9df547466cb4a1ff6fc383f4fcc5fa081af5a79fd68749c2d56ab3900ab53c7386867815ed5ce1dc3a0555730efc0110910a21ab2ce7f5d0c5213244f0a7a2d09335e842b2650f23108d1d582e004aeec5f3fdcfe5816693de0b43746e0338215599c82c510a97d7b6d4801b76d55f7dba28f936297a3a8679707ac0c2b66cfe1cd0b3df50e4f8c6398097b78833f061557849ae3b6a723c4088eb57eee80069782d66cc158fd9b87a7328b8762adaf633aaf73f53328e6d6ce5451c37a7e4f67a215f60a6d41e973e895de8afbe1f86212dc104cebf1150912cbc05cb65b2e89e407bdd4596932f04d724bf2f326b00ba31b01cfcdb6d2ec2f060a30125dd250c7114641235ce85344d37441f421106ce88b4c1e181f2c8c9193ee968b369c40ea369baf0b48541c3852992327879cf6414b9ae9865d1ccecffb7cbacc360f693d2ce8e0827619889f73f6dc2ab629cf98d5224ad5e1f11f4cc10874a6b85c1586308a4fef486ca092c569027bc4693d76c616655f6e69c85892633df24ceb124dce334a2701859bf771091b7a9c60af8c4bf3060e120b7824e8791a3ab75063b360d307976eab29a22b027f905b2fce02069070de1ca8acb816f352c62e7ff2068e57a4106a6a5f416e6fcb6d63a8e78e0d89790f30879fc96a0b711e98b4c24210174522a076f6f4d34c0f5e87569ec9823da547063ef0bfc023690ef2de0359c5c10f72f68944baf21614c8244b6d327adc2c5dde567094a0e864d7e7f16367fa6d4450e080de2fe724010097ae5b91bba4f03b17b059d8f0b1cb8c08a36b00c11a2607c67af2c8b623c44b0738c98cfb1f49a41293c968b79a88ad3f6979adb7faeb584cbdd64ce0e2a86299c37995fd1004a477e22e112fca54a2497f5f8b53ab671a312cd250de6a9b7390463b2fc740bcc326ac29b837c8623a70a29e340dccc0a39c1c2c25af5d25d3d0537ddb4212fb55dac0c14ab0404260d60ca53e7db7bb4761ecf898078d86df602d6c816b8c8a930f0baba9b3220ad5ce418569518f45e9bae8e94c0deae6c9bdd31219649e25accc3b91ffee7c455f88af4ba88066539f968702906f74e670ef1273b74770cb47af75af202c0b1859541585036493bdd79db7ad1d0416481604b7814b3198cee24f900bb59c1e48645f117d2f2248971821950a0c75ff38cee086621c31c2d499d571ab2e947031d82e2564fac92dec4462d3dbd303aa03ae2ff1bdd91798f5d48cf68620d3c6ce7412d54a928a7daac937d70ad43063c78dd9d9f5ef1a9e60312b5f561481b021102ef371d4832082792fbc6afc37de3c954881672ff39c578d63c86cd3a4e5a841b003e65a9416f723fa8a499e56ce44df44095bd0aa738ee99675c56b98770430d16a30e9bc5f80a7581014a43f9371418d78a8f5a4c994f4ecef1a3ac7b6e7109b57eff9938895f9b203aeba58f9a4c0612c349510dd91f1854d4d8205f7c60864207ba4f9dc082f626fd18187a0935f1bcc422ddbb05ab2fa2aca7cf3645a91861010925209e6330258b33a054e3cd591871c413111dcfdee71d43faffa1e6b33b5e90de2e1e3f5d4c20b175739eea7787c667ed2800bdc8bb4633fcc4aad77b4cf031c1f2b9b790da2d2791816b2781be77ee73e2119044914e6fa934b3e9b635b5f80f28eef14f138763c76c6f7c013b7593cfa967d5ea5f1811b6c9fbadfcb5a654ec8996e0ed9a470354e2341a134a61854010f9e30412e59b5a2339e154c7f4935141a705faa58ce7a9be08633df21754b00cb7e297b919f6aa4fa704b050278c457440b187a14ce7ef5fdc83fdf0e97de1838871c18580dc0b5747214b354878a23b9729416404798453fa721817e19bf20689020a44e139cad0947866847a6369bea7b9aa5c54ddf10e668d311ab4ca94a0de82a6a6209e18c8a2e010f09be64f9276740d66e45916219e3cf5df6bcbb0e73d75aef789478cbe93cd0337656258bf3e3ec34138bce746840f77db75aa5a86701dda9c6f98b0fdee31044522a26172cb42e5f685f759f60ab90810b82c9ea7716f7ed3d8078cbf2f5878db9e16a5cd69ac240ebc99b17dc37b7b1e3bf25065fb8d735d3f4c665283189fb0a7bd373da0f1c9d70e444cf311c2ae5e032c6d63e9266710e33ad7d1724bf7fbd7df4950a0196d9b6558a1bd24aa28a4dcc41b4049ed4bb0259bd4444372d26163be1fc56f029ddd24ced93a441404fa523fa9592052ba92160366452bf55cb0e97813116ee22bc6c94bffca56f16e5559efa5cfabf4b3efa637db33f8ba01079c049b59dc1cccd1018818e49a4e6dd915850f970da4c33e81b4a15b2df6fe64fbdb6eb2112292882412d9dd3b670ae809490af897e8713b8da7daf36c8479d4475bfc6c6824b9e96d364b6f6cec8fa8e538f9c4cb1177d9e24711b2ce84ec3599bbcc379f79759a8cbab18a6ca5525765d6d6c5548c5d0a8c38c2977d747bdfe2b6594ab9544ab3b667c78f60c411ec33ac7f48c1487447ef199c37194e1eac3f248aca4698107fe4e9eeb52be276d45f77ee1c77da01e12896a5a48a0759c4ec6ff8bac11395ddb3e12b4b1afb064e36e8f24492cd6decb346d9f4892d1b68c3d7134eb6135f9cb8b25f4e98d9777ba74f4ebbaab2fb8cee3bb5b038971514f3678cd709d976e47e313831ecf489eb806097fb2a67c7b2fc0d4b27e7068ecb2ec8e6e91b8336a63f11eef5eebdf7685bddfb39e3bd79ef8ffac8dc47de371cefdb731c47e7a04f38f42782d30dfdb5b0c8d1dfb9e8684cdf680cc3f4f661ff8a44ecea230f495e782bf7617a4a25579cf14bda7bd234f6278f248fe665d858fe26d1dc5ea4f1979a99fb8b459fdc933e8db9ffb86799dedec3937152da2ef273b303b61afb7cf68fd34e2d2c7656b30c63f912b0b303ecec5fcf4f369fb11b14364dc7cc6bfde55c3e33623b944dbe8ddf0b3b1488e6bba279ec62e208d8a38edf76546702c6ba97f527c2750e8d43dfd0d1f1725e67fedb3486bdeb4c983fbafa8b5c57c4ed1967fc6603bb0df69ac389c2de615a47db28ac1c7372a4f203635352311b3b273471325ee5ec3739751bd926d7e4295d9e125445a0b9a67aec4cc00f9a2a115a97da0b82d8b2b67387fb67dba8bf9eadd2471a1d1347c062d498f6fbf8abdd93d9a3fee2d63e2b5b7463285cd53d6df547b74ab3b663cfa6882042abf5af56184fd9b5de63457eb6f7afc8cfb6d9872453b933c1fb91d5cfba226e7b8f53aed8b5c65af557e467dfa3b4f5f40783d2beef3e268e009f368d547e603be5ee4cd33151044cd71bf15464077ca48840546c65832b58b4506a832d5e36a5d4670a9b7dc1b264d30d5f58b234c92beeccf1e1d8572ce6248fc9552136bd22aee0c29dcfe26fb5213c3dcd93ea8db6270cd3aeaaddde95dde8be62a737c2c7be356def747cdab48bdabbe0e4c96ed49dbed66f3752bdfe56b1f9bda6a3938bc9a8e6d8b186b50bb3da9569976b3ba5bf37ca4edf4549bdbba7e3cbb5845d751b1dab68573d8d76a9b4cbd3aeeed57dbbd52e4c9e69647f9f695776ef291da368173d4abbbc8da9d3435c4c46d6b569abf13432afe392a66393a7a626ab1ea72af831ca939d56af9c328d5f98b670884a95529496062569ed93956d49a7c95397e0482153e6b96ba61b27d350c250528e67f20cce53ce99e4eb3061691d6b73305e59b90b1cdd5c07647b2aa5e50fc9cef947f34f3ee12e246988434caaabaecc3552bf6084e33a371ac0710e757e63001a87eb5aec6abadb78771b2ca2ee35ef5ef32fae56f9a3a9afb7389989ea178c7070985e3062dd429d84a35d3867e9e86af3d19112d658438dcd22b2f9fdbe918b7008dee423f1dec6ef6de82331758445745ff3fb1a1dc3dc47341a69eeedaded39bd5cd06244bb988c70ae733879a68e76c5a5c9630500ffa0d3ce3ff814807f71291e27eb3c66239ceb68d78ff39cec521acab9ec5829e81ce72ae8e8b310a3b0f4e150cebcd0c4c949b1ca0f1e9a62d3e49142beba95b6d4b263e1c7d170f2a8f4a73404bba2baa3feba6f3a5e484eee29948e61eeafb58f3211b6b90b200720c79d1c0130ffac91ec4f7e4751234da4f9b4271c7af2443eb13e1fcfcc1e399f974b4c668f1b9f389fef201cba91bb915d37be246bcfc9ae9c2fc9ff75b24be74bf271e064263897fa9b5bea642638ff8dcc04e73890e696cfc94c703413d5474ab052c7806daa8fb2c3262baccf39ad1cd150c290ce6f1ceaed39c7718d898e4ecaf1df18300e34bdf6927c9d7f48d34ac42b2c4f76d3ab298d3d2fafc82cfbb34712ebf0c6710e7b363c843ad739eb1fbea17b2e3479e66f5ce75f0f0f38394f9221e738f452ce718ef31b1ac3974eee52804339dd378f94b0b3e74c43094339a85e92e3377e37fd82dc71498ee7fcb3975696e4388e469a3bea18b09de91f726810e0b83cd49fc51f8eac63c0f6a7b46b8e9e37b40c337bd8c9ca70f254a27aaa8f7e609dfe36edd805f9010470f2c81ffd00829cd7d8a4731d5db35cda9766d8b459190470f244100cc9d17669e7681c9b36ec800cc1c9387a3579e269964b1ba56443e2f0e0c243f8dd451bbea0d9e3f242b3c787e44f7000f431f7c7452c53e2d676b025eca20df8eb69e2cb96efc15265cbffc811e02893502eb62a9c86c4d7acb4561a033c5fb489268268c2c9fe7a74e043056b1bbe9ab081be86acc044174c7871824b0d5b986842079f2498486209134664b4d229993001134b30c4daa52030c316b2d5aa47c0998a022c51b0ecfa0bc5880029f0079b5cc059411fd06aab5d85e66b6a8a80720840037fb00908242279481e95053060b2b4eb19007dc0d7ae2b2e76b562d72876fd8d14c334843be69fb01b4ac0f1d662bc5ab564c5b4769bf363070cc3ec4ffbfd5704864121d3df1e959eec2230cc8eda6e1a763f89e50c8b9bd48e28c58d6134c058c54261d579129a0d342b888082224206decc420413229c6c4a978288b035f0411da2467a1d2db02752508b704277aaf090c3dca9520315d82077aad4008711ec54a194d660864de94e15aa9d765785b54267f52a42e8b47067605a6c6070972b32d8362aa84154512285812b55007184173be0620713381304133960228b921eaac4c0561142aba20a94ad4a0eda18585fb9e17a012b034ea8a2c4a31408dc18d888297402a57576f1c0d894ae4ee9c459363da53488884ae910486c4a8768da94061161972063892eda933842dd3e5d28b0b3e333034a777c8cc8b20db0e16b0927fba268963f78d7ae179ad216d563fa8b5b22c92d3fa52d239729289f2370dc1185b8e313c95525b4eced4a58d905d8f09584182131ee69f3bb62fde636728eb8a3ce3df5cb659aa7328e476db151c7d992c495bd85952e7b764434c7ddf1b1ae08758e7b2a7ff4de551aca16772fe59d267faac33780758ce3b277d83d206ed6c7ddd33fa460eea9430eeb50a039ea5cfe5c9b3bd6a1903a667547e98f55a4ba873ad61fabd3442a7c4f43d982dbb5f139d531efb53b216ed651f9439d46ff9082511ae9f49e3e62bdd34738475d48aa3292dca8e3fc711a496e564a3f677642e251971d118ea6b2b5d2af47e9ef86ca960d8c02d6f7b043c1c6267f32ec8b4f947542bed4512e6c6ec60e85cf467f49fbfe6679f1539ad35ffd47650b85aad19fd2bebae6f553764472d7fce61afdc57d31d6dff30f291869e26b192902c14874df7b9f23304b48dc18a5bb47cd228a477ddbdc9748b2756cf852c2cbbe9243e523ae23da3686dcb78bb3d743fcf60ba3140c5f4950b994f33e1894b6779a1f21c94df30f49a29ea21d90237263bb5347e50fc9d6392a759d0c254f774f958fd0d0e818e2c617929edcf8b1131289f037fd71c75eec8a20d65f4465d553797644a8abf4678f83c8ed1d13a13495adee42f2887bbc9e78dbfcd90f896b437a24438a443638b2ebc167082d8286d8893e49f80031848f148c377c59e1617fd6c7072b4da658492203cc9df901892f4150e10303acdaf085041256304c48563aa58f95132cb604d8f0754419bb6ef83a22ccfede83217c1082089f247c5e7044184778e16345067144174778c9b26c5a894d3a9a75cfb2dac8e8ea14f0e9599956019fb254407d1ef5790b5f5d9c366469df5459deb29653c0561ba19ed22ed45dd9e331861b8544b77cd355da646a87ed99b5b388c8ce8ed92d83b295692212881a585ebee7320ae3eea87b94574473d53dee6a221aadd2a977345e4ea5bc73f744b677cc5a8c8f53879bc8c7a2d1442a0d652b4564639497baa9a352fa88751a7d84a3f2581cc62814eadc2f87cf79a8e373a8638f439de3388ee37e6a4061fc8b51a81ba9dfe0501c8ae3baa3bc5c94c22bd9eac1919d152a7ce06226cbb2df8fc8ae199cb1e39ee51a372b05efdd59f074a75920b2eb390de76a489195dc0117263f4a5e672c9729dbfe7279f2daa2691deade2f2ad3dccbdc95d7152a2f28535c99c2088ee6dcb1ae081fc552a13c8f46b3543a9c87facd5feaf00de8aeba90441d760f88287c8fc8461deb50f0ce1da6fee18dd22c152b751658d7390b387e83a5d2ac944e81759d1bb15437c2a18d6cee37b4918d0f3791cd1df5a58ea1bae3fce1d3e81f5230d6dd51faa8bb2a958bac36ea5cfeb02eb2da9da7bf222b8ed334cdfbf5340d750f6b9aa7691a7714d6bc739ea6e51a0d3dcdf3bc6f9aa7fd28413d6ed4397d746fb9cbe50b172bfbe8dea2eeadd743bc7de1b0ad97bfd526b2b9d3a868f48759787b1ee779455638c71037eaa8c75bfddda3b21759600185ba779d7ce3ac8ce35cfe5646ace3d0421395e5e6b244b152b8719d1bddd070eae8ee462c7d395d64b5afb687f80b225264b56358494f8b299abca6b061db0d5f5388006ff89282cc042e94372e31e5b7fff8c0efbceddaefb474f468a9aa69536a52d69e546edd8bca19b6bbba718e70c7dc9ea37540badfaedbb6d32d27dddaf45059ee2ed38c43e5e8c572282f53d9c2027f32abe4258fd67197b272d73295dc29a7e70f29da6f9472b3a754db186737d8dbe196ad17787bdcae0e15b89e62cbc10fef6dabdfb60ec8c64d1226094c3e2449c0563a9247bdc738560af3a8ab20efcda3b412794f2b6d7bede658656f14bbd0cc2cdd24fd72e18efcbfabbf9d7d8fdda3f9b7e2b4cf0eb0f6968e9e1feeaad707491edbab2ac5d1642f73dae6ef7ede723a7a528af1259bdd61be10c20e42a5265bd31e08dadf09bbd347dc8fb220967e9cfe8236f7eccbc08e447634826447d74ff679c2f79b86f01a841aea8fe3f0d6d91f52dd5387a45d401c08c105c01e3d43a09c3e5df0079b668692e7dbd9518a57145b6cd8491f2b4ea8913e64e06ec397145fa470dadfa5944fe8cc36953c62165b7bb65a33fa8870473ca45ad435c36c96ef6dfe8aac36fddd74576d6e2a49b09287cf13fee09ce77216b7cf15f883673224ae1823f7511886481123485c71e92b12b4b3d74fcc6e1d102c6a31bb5624087a4d6c0ca2d8b21f8faeec7996904965cf4701656797b7f9966d5e938fb2d75c95bf2c88d24edd9a61f4526e764084a476e1859cd024ba37375f6516857bf5d801615de7c66fc7d1bcdd38ec80dcc834e87c491cba192b7ff77abfbfab4c7f93e96fec724e8fbad39cdf6ce334e37bad2b9aa7b75d515644732db372be3adc38fa53da38a71adcd115cd7ff7343bd5ac1c1d4469a7ce12b23acd57a7b1ef72cdb5acfacddb7172761d9ab7d4bdfaf36ef3a1be5d69dbe8cf4e1e1a1894f67655feb663f5a97c84d2757ebb9025d7b8b7b3dcedced923619b7b81ebee397b35843aec8581dadfac7541b2cfdface5799a370eeea8d7f251f6a9a96cc9d7d3cfc39d7a23b7268e561eb7594c4905e61120f3d8110b6c43aafe62cc5f6c22672bf1b0e331e8058ddbfa04618b962419ba132005f2d5c313552a5b42137645557f2e561078fa2378aa8fb8f6b785a4ec8e2049328308963684ad1d3f8da041b246721dd48ec48ee362dceeddecdfd936efd97624ea7851478fdd51fbf0007ff069af668f303e42c0f0d662bc5afdad1696f6516f7bb3dbb75f9f27fcc529565056f2c4d5d55bb6d73412ddd8b38c490a63cbad8179a25327b717dc0885290a81511bc0f138e0186fc0d1a70418beb658796da9b285871dcfc933d9d2c296a5fdad342c74f0b477f69c3c6496da870ca6b16aeba305fe562b9d4f2a49d0b4dad94a27bb90cc32ec93ad745cc8322089c411e2ce6e44f2883b3b12922c2e51b9f00318be745065c3570eae6c046cf8cac10836aea134531f329862d1fa6c813fbceb577021fa80e586af1c30914f9e7cc4c0579e9ec68c799aa187bb72ab95db58cd863a1be3bed6c6303ac687cbcfcfd6341d539bb82d1d3966736adb7728d5eccc324c764815367d87521a67a492d208ab27246b0a2e9438d802c5192d62f64541c943fed0272a06d231f4893e4d2ea8f4e9a2cee9d34545a25aac5634537bf953bdd29152876cc9960db363d6034bccc8873b20f01489e2cf66914aa15c150f03b3e2122b26912d192346aba83d70ad5947b624ecaac0c25ec3ea87342fdc34eb4f8698b3f81dd9337f716f1927a5b55ab4519a89d5e70bfe7aa8de628cf160e021df4dd8a98ff712b46bf4f9d2b3c2a2bdab95a6bfbfd5d25f4f0ff65827555a01ee90ff59c23a3e5f62f5c1e92f4c00ae59562b77bd4dcb3e6b0704f58bc2284c2ba6b57a1d77374dbe46292f51713e719ce39c9e7e71dbbb715d7743a18f223b37f987141c7ff39d5d23ce611771223d464f753ddc517f936bb046e5ef1b754353b3e9716ef3d5a9fe50e71e73d60159fdae705638d4014a1b4723cd7d73db65b85737366c32ac895d10d4bd8e76403c8f5aaf3bd67595ee9b21ddb10b82bdfe2bb2136147239553ae22b6e5e86ef77231bef3b0c71c638c18e6b43bef7e76dfed990776f651466de630ad06a6a75d9c47d03a049abd46214955cb198282beb036c829ba00c397962de62be6450f99f3f6d7eea00c20823e3ce823ee2d1b3b4b483c5623f3871d6159c8ea5cd95aa85cda01f1e2cdb4ea98d601f1bee56f66348770c75693bd7fd9bdd4b78c9fe579d869c7f9f3be9d267fdeeb5540bc228dcbf2b59cd4367645d83ffb69b337848638b4e51bb91aedde85644d26f228f6f91dfb6f3ef5ae0b92bddaae68162915d95feff7c2283b1332fbed9dfdacd15ea35942ae77e7356d6a150d71689ee636179a4232eb8ab07f93fec004c203d8dc8cd29fd2468a5b7b7d2a1f798f1be7a3ee9a4db693d2d7ae08d3813ee2ccf61cf41161207261c7a8b11c678dcdadfe28dd73c38e082fc99d75416096a5a5fcc211f8b4b4b49154fb7e2271fbdec8ce7ea4842de10eed48d8de5ed88e8415b9b0f3911c474ad811eed00ebb0628ed4c43a8a31ea9ba138436843a3efbfa4bc3c52e88bdfdbca6f387833be86f07e18ecfdbb2254354a2915d167a7b9a53bf1c77f3ed9bfe90a88e9d09f71bb560c4305c0724da5f0defefb5da3bb5dfec66bf517c19b685d6467ba1696dbc08461c617bec8e5f844fa33fb9bb0b499b6d74fc76ed3f1badddf451777c1b23de365372519bc5db2f9ad95ff62d1fd9cbb023a539bb47ef89d9ba9acc7bf6fb8ffb76fdc5303b3bfed66924b93b8d243f2ed2536b6df7a85901d109fcc5a6262fa08f786b27c6371bfb77b323122d76bef015bbfebbd91f3c5302d4513fb305a08e0a9d56f01235303f4758f9159808c1f8b0060f2598810c7ec0021614c1c5c91548fcc08b2e9aecec8b0b384d8c199a80d8624509bca051c30fd4d882ca0e8c78a2cc17253bfbb26403e30339802ec8444106142808c21939f4408c332a50e3883174c0e2e60b0ea60d255b5c21054c13a62a2c40a60b33388c79a2c2e4c9268c277e86505a81134d40b0a18c13229a28cde01406184ed228a3039430a0c01a183f557e88d8d99901a53b456c4198008c2084b0860e3a685f888082167029c3ca184560a1811d2184102248881dba43a57ee1e454c6174f3f4c9913154e5ba215779e8b2f18576ee6eef74a3aad8d3c3d31acde84a961c520dc1996e98fea3fa2238d7544f1f5db96e31a1bfb16e7943048b6640f367f61fee88630d3c7fa8a75ddbd87a751739ce71d7e72f947ca3d8ffbe1017f3db0076c4291802281c9873009f81063d41adeb9cf1c77e745259cc61a4f1e78a9490dcb853b5766dfaed18c7dcb4653d346f499057a4cbbe21065a580691538dab152c01e6f84e97a267108abf59c4eb2a48421ec4ce250fdbd8cb04aea0d993cf637bb3079ace5b158cfe4b1937ed24b3c79ec65b48fda7e6a973dfd6093b4ffc1031e9a111f0ecd7f3d127b3d7c4a32bf5d88bacc2e2623ee5e69e47d6a57bc77eedd7ff020a3c693273bfda6e73f2c6f6ec3e637b7b9cce88de2297dbca68d562b3d44bb988c6c3c6a57cfe4c96ee337da46761b996ddebbcc6917938bfb764fbb6293c99345cd6997912bb5ebea26f251dec564142f5d4c46dca376b93079b273ef8e7b52874334d0490587620687b60c8750d969b24abbe2d04de2be1de72426234ec78dfb0f1e30f67a75ac3279b21f2dc03ac9c58425d54338d46538c4393971aab22f94507a3fb0866087001cc2ae421caa43536640c0df2d43d7c6a01356316e66fb592ecc6c389160977669dfb46b7be1bb623fa2e0aa8fc0212881be7f48f6cc47368de62311d3476636b3fd91eaa614ab139bc78eb2ecf4b3c66ec2212d26b970436a84cc026faf71d1850b1f367c71e1647ff6c545926d670f97bd8497fa08dece1e59b742122881967cc84e1e7aa882b6934776459bc6471fd4306da7a653c3b8c96903d4a7b463ac97f76a5d8dc13b94add915d54b7d245fa33e92bf7a45b917906c0cd8f16d57245f9f7545a8630ca5574af2488e7de43dc7f60ef78e6c6d9a5623b34dc69387ca861bee2ee2e35fd439f9786b70d024be459db3d101499d090e53a86ce181bd6fd57d28fbd8c9df6823a5f93daac67b69912dfa186514fcc5299ba6452bd14a53bc92e553ca74fc60f30fe9b52bd22ef5a7fde2fba8575d11eabb1a06a55d138fffdac2cc86af2dbebcb6d8b2b5f0a2c5d38ef7f2a87bdf7545f8567ff2f89c0e79140c4adbb5b15e15d5441f88e26bf4470345b6e8553946e9017f9149f4b2297d8f117cc8e6f276dfd35fec5ed555511d82260f3d928f932dea923c92401f30763f30c02ce013260f152234737e60803ff8a2b0e92d481e14678026c960e337b739bdd14b363493bc8dcd6dfc36329440401f92c697f4eaa37b18528f9ad32179a474769ae252f03b2dd42de63829f1b58ee81e3f5e14c517cf1e4356903c28925c6148137c2f8f332a23c97d513ca4fc0105a38ec2871d0a4b944692fae85eae648b9efb8d50248f289247fd21459e939ce4a4e00fbe86481ef4b0eb80c827b2883ceae618621179799c85cc22a8b38ec47d1f519ea73770bbfc030ae6501d10d955aefe8082f5a649cd3e6eab8f2aec50a897c71d10a92d24924f3a50e68fe4e1c6fed12419ecb76f7ac95ed349a004fa3ef9f909b7c6c41212f7b3fc1d21c93db12c8315b284542985c0e8f1a164d8a547bba27aecae4f1e7e4aae6d7f330ed77341ea512c21f4dee9bdc36df391ccdc6b3ef20eb7d0f43e24c9414942aaa2f4a7c4e443291252da052550bd2b7519a004c28712c87b95f7a83c74b1f68ae8b10dd2dd6aee35a32ef391978fb86bef324b083d777a0ecad6b4b6d6cf935505978b1beb340d013854f32c2321493e4a8ba9744da5e48d66499b24978d6692af391cf22ea526539aea577553dfdcd90552ebb3ac6219966159ed82a872964dcfc3ef3a554a95b7e30c4be54f69a7bcfcb9b6f79accc4d2f40b46355f6996a6fd46b3344da4baf6a49adbe8241bb7f9cd935c3634938a49bbf7da15a9687e6972dcaa0ce3539a46438355a97c258af3b08cc3b22cc3320cabaf4a29a93d016567368b5bfe81e6f772b3c33eb93197cb4857947d461ed885a691adebb4631c0ae5e5adc36e6932930fd11ce7cfb531ca238146bb9852773175a7b9762da5fa55e5b85358d5a57e5339ee0e759597daeebdbc9d66630d953fd746927b56bbd56b9a24d2bea5b459dc5bfe010e5dd899a02969bf5d5176ecd7eb3af97b2f5dfbb347923bfb94f6b7891d02d1b485188c1bd35f3c969b1979ecb5c5951d5f7f51174a1e94d61c7f2326257dac4a3bca599d5c282f844e4932cc63b335c33684e9a549a130da86e8675eda8628cdb15baa3a49060a05d44ba92fba88811a499696e6125e5e66b2d0b204e4a8083cf6cf2edaf07d853f1d5b5a1d23dbc6b407e07944a26dcfc3ec816dcf1884c5d251914983bc98a1517b8082c1b4b4a186934a16658ed0440e17cc19b24822f3a205405ecc641165671bbeb2584194f8ccc667750b1ceae99978f9b2af98b2e5575744d9f23a3b5b12c1635dd1a6230c2854dc046b871ad611d5798ba726a590a37a63575435d570c7981f14fce4f07382a01f124829b3f8214116990e3b3b7745921d5e42f04705599609714493306ef0e2822784c852bc10c2194d8af86228f3c289173bcbb29f12d82b3b67c3d70ebcece025e3d08d39c9c20e0242526618b37dec6088001cb287001c4ab2dd2aa9a18421fbed32c3a1ed4a9422ec22a034a45d48c6cd9ac7eeadd1f6bb7d6616e2904d127f5943e2210087e255981c9311f7ecf1469976d11087b2739a491cca22a4927af542f2e69e1c93f0d00bc99f2943f6f435cb7d638efbd609c021ed37564c6693c2683d25f1f23627d92bb1ba86128692b22bc9740d250cc9cb21b2895a895e24e9e2043f4e76764c500269450d4c76baa861c38f09b49f145831841551b42ccb320d66d0f2b8d2c8c6f06a6778dacf22514bb7f6f816910f0fd9f6d0624a56b6bdf183af0db56c7b2e1f99db03ab6df547647317925aa691e8966bfc2cc9b22ae3a7720a6314ea34b7874a43385f9da5b4b367f6579593289311bdcd93f06db4abe6aa5566455456011f7515e8575a27ad926a4e8fca49aba352a039be658adaa8e654db9c4473acb5635902b19367fbd492a4b44b69c8c5645519df6623d5b176290da9aa547166cba7308f3a0bab63cc6281e6f84635da6b346d4473ac5d718826764392a4aefab32c1b91ffe2ce5298c76761656d97a62d9f75796d016cf8eac264c70e082b05d4f18d50c72e9aa33436c2a7da5573acede4b1d9b767f2591e62e3701bdddce6ab0cf38f16dc1bd1e31bcda3fe93047f3f41bb26a96ef3544e5a3df56bb56f1e53f7544e4add86ccecb7da597c9637a619a96e430394c86599d345e4cd696a6e3493bc0d9d9454739adbe8a4d455359a6569342b53920a4159c418638c598c31c61863ccf4c4e2568a6131d68a61316211ab955ec6901d5eeaa884c5e9e5c29d1d49335aeb9c73ce39b38c6a669c70643279b6cb1371411ff45ece1bd1e6d4b2b8946924d84537a02fb0d19c3a8679dd017fb0099f7500fc8baf0f75fdf91588cc1ef99ff0853383809c7e481e3d33c76d7c5e5e813e521fc0a7003e03f09dec72fe6b7db0494e9146ecf97f41fb93518a0465d981c8c03164f34063e0bb923c6e3e7f6fe4d2b6973fa4e0082406fee20b1392587e8102d9ea8dfeac46ca76d475b3915b3579856c04896be94995e8c4dd55cf3c61f24c9e7800e4c824e76865f2c43f3e47c691e1bc91e1e4d1c92c9cecc50be7541346e7cc9ed80d5c7250c68e2f1a31acd61831cc09d7af9ef3b9820b48d0c7f6f921d8e53c91f9132c76a02ff0d7d3f31384946d31712923c12ed94a02773c912d33f14c1ab215737264b2ca677684af189665524a2925a63fa49ac636235b11491a510c50185846f9c24a36125503eb823e3017dc6126b6207bb42079e2aba5e1663348c805e8e31ede62873dadc9935d803be269160aba91ec617482ec718254aa325419c36841b66234027db8e08ef89eb3feb57870b485a0d9e3468ecee1ef0d1c5a76e46e7f2f7694dd3b96bf1332eda50ea5ea96e650f2b0719b9baf50c791a1e459e90c25cf0d8d5ea9f4a7b3ed53fadbd91cddabcfd31ca7c3ca391927cf1e4060e0afc76616462866474d245372e79d827af610d9a25e2884104208213c9d9773880b77bef88261b05a2b952abb2a4dd91586b115868161c20081c1da83c8add530518b1208120322035fb9b4698467ceec6f05f405cbc7ec36bf40b7ac083c83248b9413ac6177cc70dbd963839227864c72b1deef76398ee3907ab6952dbbb7fbead9c35bb94cca6f405e60d435d9e2ce5d1e95b9fcd9a346f270af5a6b179abf79cb5f8da663f6229522681fd14349bf1e0d95e9bc0ed983e618d61d431d8ba1ee23949d3d54c76832943cf7febab0b5f8691ad5a219a52f5bdabd2eaff28e953cda53f9e64fc7d6ec61b769da5e6862b9eaa951728631c0ce0e03e8280036ba566a02600350fd51f97a2821a4af32b376b5e2c1f22c4cdbd5048282abb69763dc961e40adb5d6facb161016acf39d56c5e41440cf0d37004109e839408b8762814d59248c52a8d2aeb168ee588fb34e48102519845e5ea2203f8f75422ab0e967fe3451ae972790829a347efeaba7b205299124a2d087d28c5207a57d2b57b1675548083a22ba8fb0df8cab99882e2d499a752870510479da0171c17257e8c35e7635c77d35aec620b785d4cb88b0cf7f714ea69d0fef8ae18eea826cd5b7205b404de00f7ad97585165cc880cc2fc4f81967a400a84b3fe8b2e10b0d34829078e215602a5b700aac7f9897536bfcd9f84486f3ad1ed99ad7215bf34055e0afd5d2d1f313f4185cb803b140b8639e205bf343646bde01b2350fd4057f50cb090e1862b4420e27326e90b871e0799b1b380953d558b65612a8a60658dedaa0862038d9f170070853367c9d99b27f367cfda0ccd63a5848c21d58c265c17c7356731e7e163fc19d9df45808fdac9562194196fdf5ec2da0961624161bbc6cf99fcdc9fe388b691dc9037718503fa9e4114f5f310502c7cb1da79c582764bebe3a65a1342801df0136dc7085633548e9672744a909788492399032dbf1b41322a1943a8201a7e4f1c59c190f4405feec96ab0887e431563b201895672eceea26a24c803b4bb1ea515b55b359f5acaa5f88f6da0686f0b10c6d83e1956274c0adc13728a574c56d202cf85bad74bed3daf1f1324639697a96dc203b1766154ec2449f844962d8b31ae07912dc1486343748dc18c30ce575181e6297c390de0d27619224c8f788526b38c6045c8b21bd7007b3b28561d88198c09fb51caef92a6e7a49e5cc703d3d16a55462398b0513c1851d10a8235b404db8b6e29697a752ff80d188e98a857083c44d5377e22024d9f0050433db001bbe809025d66395ab814052f06777bdcc2fc48dddcac61e336c5a926563fa878cc60c5f40b0b26127332d7112a6f9ec71bfa08f488fbdeeaa8f9ec68dd8bb11e2244c5102c9276182f1300152b25aaf84258f4c488c59f64e48083a229a554a543fbf68821216650f17c22c05011a7c883f10b3e3068a828178c0dff756c38e3a6e88315f01781e1eb993250f5f3ff8b2a16cc5166e06ee85f2c62f79cd9ca41cec4ca072ca5af53c1681a8987352298605524a29e5bc625aa8c10dde16e0ec14cfbb59f85da9d0ac5886552139aa8ea16e3ae7950b630ff318961b9a24ee214f65ab13328f55298fa8c638b850beced852e646208230e2c79a6008f11607108c114c910228410091c60c361a9a88e1258b27747046131a009100880452ced9544512507cb1c60d94e4009d84c8c20564845072260b1a4f303476e0e40b4870d15082860dd68c1143b8679801ca81564a2b174d3421e50614bc5eb082231278c922075d74310111676cb1e9194e0158a3045ea6988122849911ecf81b9dc057992b1bdedbf055260d1d73c0f055468c6ac357192f3bdec289833ce38a192d765f548414835a78c803e530eb9c1506610c210a1aa0714610a6984f2d788205116768c082c3d0d4d4d8734ea012c421ec2f684b26a0d0018a2c6cc0c10d86ca74d1d228638504c478e203174454f18329e8502cb3250b33c8284961811638a8b2449632d47041143b20b103304b38f1414b26843245604d6894794199271bd235d688f409374d5ae604fbeb2181106c9a6468a5b492e141a605218d322348e3876b0619648650cd98c10281cc188c8c19ed4ca5539a6186156640914412643e2e3a20e344162ac400338134a4e8818a22aa7841165efc408b12a5090d3330101bc3a10732579c6146141ecc2053e5a906642ab064054ed830e6890e6c70801252760863c3191a0c41660aab99015a32c3dbf065060accc02196e06600cd0044c3ce0e900828dd39cd992fc40d7dd00d218f17e446ca9047d594523bf79e7149562075d2ec81261e544b9f9cf86087d57e526263d84f98a7294f3ecc566bd7d34927a5b5169133ce6c770ab8e8e2cb181a6465b6b03e18c1be29e3033d410a70700310383011030e810a199cc0075de85004122f509931868c30c694d1e48b0f4498e0e9098d14f0a004a5043d40220a134e3730c11814992dc21873650c97313ad0420b2d88c8c458a15263dff0a08721166841c10d4968610196059401e50b1354a9a12989981eb0f624851562ba886245971296f081921aa450a1c4175cd4f8020c0a66f0c3097c20c649a7f9400a2bc43021c68ab4c2f6200b192f10a0b102272faec8e18a2c3d4003c7982692681201152f3af01004296c0fb4e84197d71417108295304778d1a5890765643248908145cc93234ea001a05bad073bee000a0f2d30838b993286729c44c96203334488a93214bf8a5129c6f84414514411f4050825c8304293810b11fc6083982f960801bde8b203130b72204616598061020393c5061d03e6080b86ca06a6874bc610645801c30232c8786283aa584bc60c592031060f5a30440e5cf01a83899d21e81845e4a035e95cc089918159b28169b28d41c30c4e8820892596941053c419595cd1c41332b8b0f2a5cbfde2c500b4301b182ddc172b5f9c08aa628f68d2c3184db6329cae60f94435acd259b38516a721f18584cdaccd7e94c0dc862f317e9610c306fb83af9f24c45882be86ac204611664419e5ec01f1a41c11232f44db44853c1d0c7b46d8a2b5567d29077f2795717a9f127dd2c4700156c68ab1c40a78041866be58c34a501007d0a8c2cc1445486922822651aeec50a50628510051a5ab01a7f160f52cc3a6ec2c0c2a5804550923092a8c1c6c7eaa683f47801103660b347cc4687fcc006cb823ee8cd08a22c87f19ee903d3adabf7710987b08262184624329e113d9a251a204a12804e415db22c0b4fbc3f312c9e491974df10670c7d402b6e465cc22e39538426c8a22c84b2fb6ac62886d03b843fe8b4cec11d4c0f1557ff148fc086ae020f501a240a814adb4c54d4b32e6d00c0001003314002028140a888422b1502c1c12865ded148009a1ae4266469507b31c874114830800c6184300010400024006888c580184030b8a11ee2968b940770392ae982df38a65c01af9dcbed90e116e2947167cbbff800c1621919eb31bfd26ac969e587c6c52e55b9b561170a7608b0c9f7fbbd188bc154cf992be1ab71074820ffe6694d43548f28e701dc1fc2221b790d6ed5ca39e5e5d6f315c738f9063194029d00ea9ad2e477160c049f029a127dbe8d17606dd40b052548847c14e2bab6e9ce23e9aa6b71ff45edd42388ee72c44c06a4c794a187e009e56719b253e94f64c1e34ddfd78d18e52768c547cc02058e96cbde0305b4e93d08ea1497af560109d4b74833692f903680f302cd7653f29fb6fdc01116c25ad0d1bee49e65d8fa147e899d1c5b3e8759bcdf4536553bbdad201a7b26d1c827fd9145bb5554bbc1d42a2518971f515bc077b8406d0a63a66a1b5aaf4363727b687b0c89b573a718381bd2a0c50a34ac36507727ac7cf54b670bf1dba282fcc702871e846eff600628fa8059dec2412cd4ef147e961ee53bcf144b5b27bc2c757dfa8eb7969e45e0a5a11f851fe3c1ee64cd23b4110e511660d661df61daef6e5825c968b373fa2d092c8687033818b8a2f92390e7aba30c927c55bad23d5abda633e573a684ce9c2e585edf4314e0e34f9616ec76102f2f4c400c705cdc53e61b496275633c350de0f30f31379ca6b9a10cd47a4b7aa7783c41a103ebf116ec7eb07c6fe73b734a8933a71a77d0467d3aa46fa900b3373f3e945862de0e9bc1c4322de237843e76e031b8e53583def47dc166af611c518bc089c721eaa874e8a910dbe3293f390d2dc0eb0c360e1fde1116f95b2d59d358f8e99b7ea7d137acd11630dbe4d44d39a140c97a128cdce99a3af2764ad0b780c5ce4c6beca9dba81251bfb0edd3e8abf288bbe0a795d87b39be773d558cd3475f69412886caaff2cbf7b086f8941d96176706e7aefe74a241ca2ac6dbae623ee528661ad5f8c43e61db4994cf7e08ff6e8051b2ee2f9b5c04cac0289e28ca5ec18362d05aea9cd3cbb8f2c9e1926ca6bf80eb21513216fc90ea4c6cd21178c2adb747ce8ba17f53cb64603d6a84e8dde1e385a36b2aa4bd6f6c8c8c84ade3b4e5c4e3ba13a348ebab430ad565adb61bc6c8e6f54562c2d0c9ef59c4a557eb2f044ac0771f83ba26eb8bb4cb6bd88e1f40a89ae435baafc75237f1e1b4128cf88f6222c7e471def96d7a3d7229b7e004193bd13143fb071e8d369b492741d1d45825795913039948f15ec1446c30c61b3a3d49e7e90e74f5a91304213e7a80de3e544b544aa8146356ebdfa59a6a9ee4fdc1d7ce28f174f0ea0bb42a5a87c178ebcda1048a45eec64ed02df809ff532ea65a878d2e70d75d33be7b802a7189f7c3b0ea02b65d7cb8375b2853146dd5a9878afb93f3ff3a85b047320244a16b138f79819c356098718aa71de02fea86731d99e52c1d17a15c49aaf8cf320c6d59be77c41cd682cead514cc0bfc12304d386ddf1e3397032b0e11727faf331a69b93d03a60bcf09a2bba7945c3391e9be07da9d3c423ee6d88b6f8e856e8d356b15bee320d8e940a18391f82925c0280dfe0fe44ce8099de4c62e855dd6847242370b4f533ab982ecc871f103d95a298f9d7139ddd1f26d607e8501c29baa0033ce62e30d13ac39cf8d6ffbf3a48aefab54d63127d1e5ebb0a5c8845b390430f78506b707d8025f916fa7a244b12e0989c3cb73bdfded0708443420723eee4475c082766ea487acc89bb089af58c9c743bd4f39d1d5f1071dbd3a70cb311ba6763ee45f0bfbd84607cdfae4b6dba655374a08a5fa44fc4085bc5e5b74fff40ac6864e29c218cc0f298278f306bfeec07f835e3b87e62291e8b535fc94b0d37dbd48e7eb1aac045e4f8c1eb86b0779f7829457f328ca1b5becd778c0bcc11a398834e61c47750e91d782b7d8635dde86b30df75e0bbd691c0bc19de32ea511d993ab3e27e4dc6ad18dfa227f1024562dc060fa834d8f622b67367d080d8fed2eac4814c22328da7377616dfbc936b7ec11a0c2258f3bf0a50d02af55799be906736f86e17c0c20c296aaa1a3e783191c93e22fdae58074046d65d1916d24a18587a8d8c2465038470db0ba7a074023f73749f12807833958232d3d663e697353f87677c09789c92b6b9108b847e5fdfe9e52ecba59e177cb8ca9725e067fe127be7a3929898c66ed139bedc44c67a16f0421ace5eb3fc0ec547ef1e326ccad2737225d905797bd81993982e85654b839ef330ebc8b6dca9b9fd505857b8840a5a66422858fc67c9b2cfba35ed68923e15076eccc347196921e5388342c50a01b52259bbb5987d927916cf18464a320c639a7face711016160d8652d5ad2a6518fcd8a0263680c63f09da26605c75de811c97a64cc46fb93061cfde419a5e31143d28f66b1e1ebca380c8209706e30a6805d9914a4f4efb22f1936b4201c9160cdd45d5dee30dd0adcce3c9a24a4aef1db00ddc2388427e7a2290fec4206dc7086d88615523169a53647a9714630163c3d6b3ed63a8d5bc8128ba3588b5559978f982bc1969298b72cc8a804b12720253bcde9d1def5f360eff95bb08b7102fda401707dde9b1df38ff9ff8db3e53aca767e658084c0c3e10316cc99d89a6a45332b1c4110e001e6839905fbe98d4895c034fcdefed0fb054f1483d933cb7e6fc0bc65ea3734d40054fc87afbd9201a4545e5839c84e62e7394a11fccc681062779b99d3fffb0d3d281c75f824b1aac002c7b4dee3cdb1ee9f3b2d30b7bc1b55d4339340815185ca8e6934c812e827acac5fee8aaa4f7d926c9e01311584d941101ef3387fa2e21f469eb462823d211fae463c118eb4dbcf15dca843a3d1155576d030c138a9391eda410da681f3a006a681d8cbb9dacc15259b0e07db48969cff9178c420d8cc747029f1396850bbbc7e5303e77108f6bcc0badcac0bc786a21771327cfd89a7d4b61fb021bb309ec3e84c348b2c90fb3950104123cf89abe001ec5e5fd8661a8b986d329d039cb9af93fa7dd1e193c31ddb53a5df9a16b7e4ba8e56c7cd91c974670cdc48ec0f8461014d11910b864eef43ec091404201c5227c0183f04ff59b43e86b23846840490a7a2f00fcc661b170944a1b247a228e3770e220249487007cfa9de4f841e302e343dd1016d9783cb4d01a2bd3c126f6cbed5fb8a4499e25286d0b9d66fefd6c2cfd224a0b815a1634682824f55beddc7bff24dd8a3066661b74c278225516d91a3af88cc88d4c5abc0df71cdb368ee62b886598b6f9699eeab3627081f57432dc55a6c344c68a2207624b5042647c97e9493acf6f16ab35b81bfd4201a0bf47ed666b371432d0f4e25f5a400afac97c2aebd3f1a810e365e6853164c1fcf7d10c77190bab441af549d37d5dd92ef9dac688822c4fd35815240580afd55d70588a57b911a72458b30d2634b397076fdbc85c36ecd7e0a228c6d23cf8662816eddca1f3a069e44c23a4ba871e8c800006b49d593f320c14e768c65e65bf0d88ce434ad017ea297bd2d32d13649ad9e510eb81a4d2cd1ca4bdbd4c6be72d7f230bb346a15e0620060b42f9c8633a23ad8a3c0d959f8a8aea9ca0c6cd9a61b6850e270e7cb50dd38b9c5c0d2d9232fefe9612b1a1f3f0e5fc01d63ebc372d80e52e888be164c512430566f7e3d92e62dc378e30f713691b4c2b879299695e76d3b829c592225a7b8f4cdd9cf1fff26fea0e38da1728c54eb9d79e8c652ad810c927bb64ddb759f29f9ab5fc2be7b69d50b8d0c006846bc9a4e861331a8cc944ab4aaa3434a90fa354921d6b1b89953ee5b4e1e9f48ca1cfada374f222e95ffe0299725fe20447ffc4c83d6e81e36fe75b9a48640eb42460f4321eec38fdf139e39825fd9d45c914dec32ad46e7c830de96b5198f531ce02b59bcd8c62450d9894e80b194d86aaef7b2b590475c444fc8878403e8a2814dc7b2cc9003e2a9f0a1c7afeae6684a9d334700bc0f54c0c11dd54ba0129ece5107a2ebb9d74bec8daaa6ce39eca3f23a73e55a8d3e2658718400132e7205223a9cc0949dcb2cef5ad3dd0491a52c386f8a52430eebe38cf05522a68ee64ae2f48d73a1ca94dd116ee37b027a6821fb9b8b52c8642145a411da04cf0ca92b00e92986bf784333dc1a6c44bace7da04476bf87cb4b4f7e5fee9ec9d1d890b927200e6c354e26ddcbf6332e8be4e55b46c7a006d3bc4ac417986c08f5b683378be203fa11174c0317d512acdf69f21e60dc9b84f1b13269982f8a8ab791ea139e0863c1ba3df9e244cfb7f9a77252240b7b67a635f465023a979d0fdb48e06538900c1c369a2edf1a1fb1805cebbcf7e40ce349a97f08feb352d74da6d2598cd52bb62b17165fd9faa520228aa7542feaf43ee96fda4061aa53d1a5052a9117ccba8b934fc57e4a95dc72a3df0047ddb27ea6f014fc4ad3fd35b8df696658872a2c94b9dd9f9123bd51767053388796d46b6cc2dc01c7f22b2e39865f8139ea9801625d6af8146543cac25f6912fa09fc43d716bf2a0da800e7e52a1287331a2a7f768831e217f617f9322a6d4dead7e303e4c4ac10c1bfea117028501897e1348df84123a28e4b5b8b9f1a942a89a24121d131ab11ab8671fc0afd9018f2b5b3d82c6120bbbe0d28daa1f54c744310fb0dc86cca45b38a6c0fd596788f6ca02aa0dfc65fb5ec49a455dfe81bc84ba122abdb26e0709d1f36500a9bab4a604fb5f1aeafaade5a68089b463d217405dc0b4852f17e72255bbca4e08bea2b2491c3ef4809d22c687a15790e1cbb00b7a0388cc2ed28679b2dd18878fc8fa1d478c0fe83193e6f0f7897a21d6332ce954437c0ac1f4d72e574c952af63d763e82b6e47e4db1714ecf72759d4aa778073aded9c7399a8c334036f7cd5e3e359270fd7e3364294c9770cbf1307434d285fa11835b83ff738d6f3c0be1b21442ef2bf555ae6d99f0bcb78601b2c3faff51ad0de1f656efd0ac42bc8cacc278b8ccc5b2110ab7afa32afae6c54f3a03e857a3011caeee18cf867bda6516fde0ee6d14137f26f8126f4aafc9d9aede2c4f471e11bd6ae48d2a3e12fd53837c5f0f72565163494587e116ca66c0939e8fd8b79769802e541f616cec6d958eb1b245f86fb85dcda23c663b222bdf5c81509292e5521c5ee6cb965517e6c9a07fda0b2768c84db19c2f540982be12cef661772804bb38863beeb2d1b51235e694d782975cf3008690dbe803d5234fde5975b2a2e689fdfaef1f61eadb1c4e6c16f511a9c5a4ad192366647e60c5f008069e7623001abde309642034370b33899986656b1d48e78c81e6eab3d6f95a524aa7d930c982f06436096286077688224c4cc27eb88bd953e9a72a9e9d9bf0d9655f0113cb2c6cde1e14867e1b6a4d8b88fdc9199759d7ca62bb85aa5468f6bbf83bc58aeeddaa90463787a37ff547fd43700021c822905acfc1e226dc542a60188da032ac02c7835c8cf18ebc8e791ac64d22d50e72c2353f54da7e4c4e6c59b7e91628963564a8ab8d89514c6b6437b97dececa815e38e626f8816d1e7abf5113421aca9aabb853509f49b7b81f0ec7b3b2dcd9c09af284b28a0e07a4afd8c38dd9d604f94f8e50ce06bb51e74dfb421c5eae43350874ae8a0f28de2e905d9231bb0477358b3e4de89b2d918ec623ce71979cb1301a74e0eb067801648e8b3f8d04be990187b29c38ee0c68379d828321d39dd5df856fa16ecd5fbf48f021ef6fa81de461cf443b143fb5db0b81281ba70965025a62f7b6135c908b3d29f207edf2736415b1c0f9791d17591825283a78caf262c2cfef1699e30ba4c04d005c4e0a83389c73033f0488d5263881b90d39218d64dd138af3e1396060956fb5f34a4e832fd2923bac124e27d3893f98f9071d912feb3194c8794f0986d5e475268ce15753654d7a5c42e8f3d7a4e0a398736944ef5819fc9fd126aa7af23c566e2cd8dd287a6cf4681614e7c00cb3a45fe807a37048ad83f42b50c50a47dc8db9ba25038ab56e66afb9c66bf5eb12fa616bb27b3e016e8a6a60eaeca15c1feadcab4a38f83a283ab5831e5c2844bebfd6bc15fea7b10bdad924a36cd7130532305f6e9f68b24d096c3a4f4eaac87f4674ad3028eb3143f3ac25f01c03b0a9cb0a81915ec84eb2664dfd0670a7db7055ed1d799b4609ec2d05147116ed5cb53780e34b791c06ef3736ce2d3d35be2effc33c14cc43dcfd731ad2979a2bbd3b6a4b42f6cc9e0794d5bfbd350ec7a65f3d4afe1750a901db56170fbbd9c89cc73fefa0cb6d88606b5859bfcee19d695c5d45a91117371359bc579b6bb2f0b51dfd3253ba79ed99c4885faa36a213f3fd2b7a00ee5dfebd7b225e3c6e584bc9b9cb421454084d54b0908dc8148aad8b121fcace4af0a129742c6cfc40a8be1fc523cc777515c5fc54cbefb7a90ff9081d63af5bf44bd344b431bc48a760bb242fe4b1345ee90c5303d5453d2c7bb12448fa003240bbdb8f1dd23acafc052d6f2c8a28f8dd5ce7b41a02f58e82bb912d6dffa8eaf917b2b24cdb3eab91678b0c44dfbd00453ebfc322ee3995bec5a7df83f532e90bff7a122a2525edf8f649949f8ac29a62724c615c7b918912a5a70d3683936ce96ec11474a207f54234cdfe43fa77cfeebb1666efb40ba55a18815a284c1c9d80c643c0ef51685ef3a97705e6b50e9df679d91a7f359cb56577402eafc5fb566ed393e4031db8f5dade5fab563c8404ae577f778a10106ac636d241a38615c1c93a0c9141fdd615f820c5455d256b8426b874c21e4633e1968d5c9737e82f3744c758c69267b93c2052b7e237b09664493aa78690334065d7732421c9811c44c27acf50a00087b9f803351961d6072ea0507f2745d4a88ed20ed405cc7c465abec0fd42d440a6a94eb90d698b78b6807b80046564d5bd8a38e420f71434a076a3a10fec61d973b62255cdf1485a421e795a8fb7cb8d11fa2096d61e58603c791ae24f6f63533f4dd26c410ab7d43abdcd85a883d434b5a1cbc2d0b869ccb661d833448c00a695d5ca96e63f5b1f75cd7ed4c0f77c03f632137179b63a2c858ae07089eaca1c4321cf81a30238e07ca0652a97a9de39608c6259c26df1a0210db572ef1df0506f8ff76e0a0077f86cf0b43d2861e9e2405024fd03484d0448747e9dae5a9fd8f5de2d2f5e39046b17789e65326bf0917d41f90867009898f1f72dfd8c8c6eac58cd4ddb3de8972b9040cb4f888025e13ed5c7374bbb3fd85049621304c783822b676a0cd0ff007f28446bc53a550ba3008496c345df6d78b0fd8ce89c4d1ba02b0ce41cca410d1203b0ccf5cd34d74ec61007b0f556834a2fd4c7fe436dc98c5aaa1db758bc4d15d772da40d6fd043badef544a83463271a44110484d275c8aab553528e16125f106351ad2e6fe74c50fc591ff5132291e62a058c0a45e3e219e8edc4124a6e65c7c9d5a9c6056e3f78ebbefc2dad8027fec51de0e5d8d4577bf5c27d84c18b211870c0f2f193083d272f82ce47da66fe35f7ea7378eef3c39bbc0d4e05eec9a4da4b0c26b686e5af375114c04f5b579e952b237854c81ccc6ea8fb976082ba6d122334473a995b8569725f48a8c68d2c9113a7f0a4c248639f9cf7b884e0ef61a0d0e1f59552766c67ce034209ce0da17500aaff1e320ddb55c680d1bca118c16cd18af20bd17225a393dcfaa41bbfe4095a5daf4057ef32075c5982e4e8a7073931cdc8ca58cf2cba70822ed2ddd69b9b65a2ca70baa4da579802620fcd28104e246b4c6cd526453d25af386ce19e931d44e5140921fe4989c85b92ea8b20e344a41b2573c56fc6dcd4e66f49b2edefcf39a5579fa1861f129df4b0b07c833a922fc86675b46dd549cf5f1e790bf0ef0dcdb37d773ab4914651029acfc6c045b962cf3815acebc5802765ebdd7110f36f645cc0e5868ee16c2a3734f6fdef511d34da9a187483db05880f41608c8ee58247dd89c7e38a5a9463c4b798b182148b524b69ddc1631fcadf7935082f0a3da49f589a2b3f62e5dee3a508e744122f3c3c863785adfbaa50f3c448827f2c93afe028b43d48a93d0a5b3bf83de34f0041a5a16efc89e4aae8e6a1b5c6d09ad8232d4faf475c2a02b1219e917eb1028f589f7f9c881c48b6d79bb8d9c14af6dacecfb04a4467b9c710fe5dd795e9dd8416b29211def557e3b71bf1de9d090d4c307ec8c509970359cd77cd7c546a6842fa4bc1272da3ecefaa86136eeecdaa030ac6f2537d0b4171b14e2335382321c90482cf072c1d641710e5f3390d7841bf066877a8ff7e1c894d2bba8e6bfe087801680cc76655601f870883e951fa1e088577c79e3df593869a645fc968330f599842228323ef9e6f6790856354967441631583141461834305d2dfad0131c1a32e5c2dd9b22bd8d961ebc3838bfe43826172d2fea6f94db69f090cfe5c46add8da162b029ac98628f2d6f69a93921e8c0506d7166949c8e501ba2e7b4606035c13c6df3e322b96406917f98960c921ffb6f2a1b47e17d99846ac7fe07d3a78a293a51861cdf210e70894b0a5d511d703f97d88d350bbece678e68ac0c19fb1e1b351f89561d198808ba13ef4aedd8d37355b706dc279482b753a4067fc000a7da177a74120141d9f4320bc8636837314186f8368ace17bb4064cef76144e2709718d29dac578ede55bbe11871ab15cc1f2581713afbd7c3a13b07647aef77d5d84744dd20fcfa3ff0df8eab2fc9b74b5854ac201ebda5e5268bd4963d4d2e56f59ed499b18e6bba0fc25be342afb8a9471802d0fe86c984352adf7b9e0f933aed1b558e186b2f58dc4e778e62a2408ffed59d9d9a2a5ec5a88644ef4e2adb842409c58538d4c8bc90d64e0406322fb9cf73875e00f7daf6f8d586669d272b3899eb8b43b7eaf08ddb0d8ad49e24d3a4963849bcc0bee897b5655c93068b803adb7232a6cd43e8c64d0b2aa9bf507a410b6f730079f87e936d4b338ff890f86f310db718c5aa35f2102abe258d187fcd08f63fab1e4dc3fe9d448e50d99b325e863727fe5d8dcc3dac5f34c744bbca4726dc1fa0339622d93d3f72026ab52e9493c8d652243a4c0572e5594d43633a5e62ff2dfeb51db5c6670593dcfd59862e399e88913111590391803b294d3efa55051109fdb7dffa5f1a4761910abd0a6459e07f088b2b298d7261f6c03bb8d3176a163201de35589adcfbd2c5a76c1ac27439a376ea0cec82b4f03f9b23137211f0257b82d8dc91840097aaa7bb03b5ef20415abfa35f8288abb80bffc8f50bef5c343f9657ffa5133dcc61b0f10d79aff59222a95fb31ae507050f125ba1f3b04b9b92c9feda1a70c0923a8e1829b5faaccb4efb4f70a3f05b18b63276ad04dea5f56a300de1a7a8b241ac352deb3581d460d5a2a0f63d287de6a9d7e595183d447181540a978084e3e179b3d34f65cc898ed8a5bafa08a0e903f0d4339f019825f50d6db591bdcf2626196a9d6db4139b66ca93197ecef5f13a018d5da421cf99106362984bed59e40f61f9f8b6dd7a9afb4279d21d86244026620646833433f1b9da21044519f15c93143a77e0209868bbe4cefe294398e03b73a4063597e7aae0a424f4e45eba165909284fe1527d208af3a285d23aedbb6bae6a565fbf5454b1e0dd77427e7c4b2d766873661726c8dc83f2c7da6eb941a04818e0d841691d28c517ba3f6083dec8610b7460ea7bee7c3c77c9eaa19ee25015decc06ff1d8cbf725e6369246d09c75d842b6d25e4e90291d2dcfdcd52be1b3ea7f217733cd45e81aed25dd32daf057bae6092936071fa8eef4daaf199c023438b59a313f694b5150f0629b0bc344dd71c9ca558974bb74345f88734b7a7308b0c3d1d46a4861754a82bef77c0a7c6b04ca9e213618708b1a5e3d28963b32372d0e94cdfdf20b1d706f1d6fc277039a2ef5fcf91fc9ff6439bc599e6339bfde5c48f8da216c8599c3ccdae216d06462083fee1f13c5b4f77d84e2a0fb2a55cd2f705e27bce1a6a5bd97d82d78af51b616af341838cb36012dcfdd89db0dbaa6e45683fb44d60d6e17c546fedbf57d878976c07de238ca1503b34899befb3286feda9a585dbda9150690b826b2b2299b90f48bbcdd01f2df94f2dcb54397c08556af216785770137ad409c485253fb8e1b582b33d36be967bd2e2e45e7f6e663656466d1def01905650972cf6793f8511836036c90f72bfa314fbefef7c47d56248f318a0565fd13330867dbe5563e416ae1db8189db8c872d4bed6ea4c2879e5eb67be73bc5e431aa587b7ef90075e5ecbfdc96e58e35ec4fd8108521e0865c724a0115b927bcdc869caeddbfa399ae9f96390ae63b73ad1a4c1aabeb3e16e4920ed8919acb1eadc79f20579c03cfcd62b3f84d1094d389ac2e660b172fdae8fcd9f412591dc313dd750bf586cdf2566bbb8220218134f4e488df2e94bf51270b2fa860c09f1a6c7edcdb7872d4441d3b79801cc9a139602fb24e8f491a16407152216594990bf9bbc83211c84aa5f5052407bf62ae16410a64e21b36dbe13205df83ad758dfcddc70b65a8d35fd384d3ee899409350c9dab46af1c8fc3bf7fcdec1e5d903fc60122d2027793553b5bdd7b7e4d3c227f3ad0ada9a5c74a882a45d5acab07dfbb433c752d7d357e4549f392fd8958bbb208fca220d1ec9265ede4bd1535285cc820b765667ac19763c1e8671d4a6a50fea840abb910d27856d94e0d3f7a84fcdb7b276300ab2f08be473108125bac98a8e35b4bf542b1c4bf7c713269d1f9d16164563b7b7b62b2466fd26240301f5d09ec6418ed1170ba0607a68544dd61e64115c0a67ff12fbfbd1d375e745b1961c9c07e1a58b05493ce038feec81c6524a61b0db613491cef26fb0d7d926268d7c7760ff84b41fb1cef1f4242f833ca3f6d45306f2380b67b3a8f824e9464470d542c0fdc0a0928262268a779c027979d0678fc884069847bafddd7bdbf8f534a2f132c79fd9a737af15cb35c001947b3d19569c54873f20613201c3ffc5427d7aa870a7d8a78f106d20e771c7615a1b8f38e34b86f642a770193e1564641281c428c066a7910de2dfb22820be9974adb4ac435771f80f15ff982d334776a16bbd9f6ccb1e2809a0d20e66509925e7810d92365945d987666952492f4c390ce0701168743193ded5c1e87148965fa1101e0888b90549b34d3c45c59a9d23e2384634c0375698f3648e48c4b3641a3e57a77a234f9fe555a0a227b3e094c7aa7b7075227faa1d1034a20408ae7fed648a45e1bb05c3729e98b97f286506f0973af41665b42caf690180cad8f1ebfa0421bba971cf5cb3b6493305174d47022b0df2b31cbc767d8e128f81241413d7ea9714a6bf7b3065237e2aa199fa0548741e3fd2a3a93a283497e0a6507d071ab5d29348a03847b273c5a45612ec20998bca7bd97eb1bfdbdcbd16950bb56720bb41b2ff9d8534582e056c938af0b8fcc148270894a2eac1cde5caa8f9c6eabe4c6c105212a2886543c777f38a84e499a198157113b73a0946c394fd84e3d214fc5a271ca344c91a78856afed88325563cab0b4b6a5d86f75c4ef6da011ec160e817c67c7a1fdef016bd82fc1b7eed78109c0280ec5845a7a8f52d39ef3186b90d70be1ca06ed06182e8fffbe8371fae19067d91f0a70a2127b2e4eaa55a473b8de2060679018828db38aeebf987395eab10f398504734ad86c9fe1989c14b7a130461bd3747524ee2cf5dfaacc3db5650035f8cbf3655b123d8eb6906a478d925897d55b5c56af64d6e910e0039c551b4eacc1c385ef0f55987a80aaa4423bb797f82cbfcb62723dc4f9757544a370c3c012b4a707e9c4f66de422864f5c49e53035556371f5b6df54b3d5971eb68502144cedc80a2c007075297ff24898594e4739f1ba5421b5a0e17d69161a5d2919c53e84fdd08cc9a1684a04f9daf481467186cd0d2c0582004e458a11fa8c5503e97ee9cd0670fcecbf7e38e66cc4538a4c48a7f9c7a5afb1a6f62d300b6c11ada78cf51569678a60c815bd55c95f78a1e9c095795a2cb67ae7d02ff75bfde5156c22a3f616b52cf142d313137d3d59974146642db0efe24d8a815269814668ac8245e4d0ca75214065d51da03703a3f94239a9b859c0031a22439310648ba3666eb77e83d6dc29a64ace22dbd27e4543f084e474f80cd1e2e64406743babd08ab88d51f0949dd326ab8d15c20d1c353244457cbda80a85f2336eab181ca33fd4bd3bb2cbc632e44adf19cf4e441fa3731198ba212a98ba014ac36c70596656a0e493b0ccc5ab91748c03b4ebfcb147c3529cf3a8474d9e990ccdbec7bbdfbd563d523c172eb81936840b28717d5e13ba25e3037d2c94a734e1ec34d5d96a9abcd49e1180d10418dd7b14e8634a38fb87ef98cff579a0cef21ccc1ea47afa401e42003a0203190b18c72450d829319920302609784e97968b2cdfa84c816199f06544e95b9897689965c36351270f3bf56e01b9134ba945311cc3bc2f60dad02ff86f1a40cf2c15b79416b36582a1cd0bdf31559649c0b221a5634f30cfa64eefa49e1172d885a2d4d1c7f2e092ccb17f2ab8fe1e9cbdfea4c77c3571b191f50cd2da43db9fe9c3bba583a3e5720dad1ffca478881b8b758cb554de1bc94bd0c6c2e39521a6f8588ba453b67ff2e5d607842139a76e195b33196fe2d68b23dfed52fb04ddf12da5d3ab55598524a1caa36c11e513458b72969cce3d75be1ef2a935ada9788918c425ae63b90d259dcd4c8f828bacebac9f6676954f0c0b9a2c5926ac857511127988acae14b3f7d563bdb3b3d8f273aad0cc372b01c6c1c9780d0db1c98fcbaa117473b623d4e5123a9c38a57a69451bad0d81ac8a66692fb885f860d8e4b76df7afb1b168a62bec4d4b1655dadd00ae16a5b497df0b80b6e7a1661891f8d5d07649015f40b5e6a3da8b86fdcbc7a0f5b2b8d6e786c7ca7f65c30ae75bc0fe24dcf4f74421a9c764ecdd89729acb62ddac4f7bb07ae5452790f1ed2bab926967ef8cc764ebf903fd2319ba2aed545adc4728b8f0a7d44a727c91668bb84ae649fcfef8d0a00746e68120f69079866be9b343bc27975dc5c08fe7e94bd77385abbb57e611586e3771e556b8147c104bb42fc8ed25da1b66bdcb63859c3433f5f13f163e5ad0682289914550d03a0bf0ee3c48b10d3d3621ae2531f03f89b25f539b890a609fba3167dd071013da943b61ac4091fef198dd3f6807239a85f6bb40e5845f33474a2fd2b939cf511aff9b1499eda1bf58897dde428a47d29ce648cc121a2c75000d59782f6bcd53bd30d49096d3e158691f06ba1cae4bd4c5e402f7a36336949ff8845a3a9035d2a8c9287ef7eb8b5f4a925045de0fed6b4926347a6c9fb2cb6e41e13bdaa46a9399b7f45c931cc1cf7b13839cd75e64c7a8cfa9a73bf3432e1a8a999b88e9c0165034c2ef34f64a223f618db00e02d829f12b0463759294a230da4e874d81c2b13107ba43326412565a0fae074f120deea0a97f51cc3284f0d0f302432c050a5014014d65b65d8981fb1d31f6e1bdf0e0b4f13d1cd0a21cd6387ace1ccfe0909ca49040d10d07c6d17f25ef75120072c15dd7648cf24a20c4e8362e2f6f50110de213c6d77ebaecbcf482870937ebe88a0bc49ee8349052650929cabd73f645d7f027cd67fc6837489f83e65cd732aedd7eb0167683d64b0cf11974b0e042ed67962bde41e3c9e33cdfd6c12204d854695785a176057d788234ad8f7f50f893ef9969e0a9b311e0445235148b5fa5d79126e50d7090071a41386890981f9d3301458dc8a9a87cf723a82824458e8dae4ab5e8bf590050024d4862e377da56c3f23721e8ab74c952d125b72b36533a2ab29bd3bdb6402e68abf719d80980c561b938546c1be55530a74234c7bd8dcebcc781d781f5e91e96f80062190c14575a8d006a9ca2c41968b0e996fea83ee0abf2c20b99e350299f87232caa9a41ed06864fcf3fc186af50913ea0702ec9d0f1a45f4b6635a6d2c46ac2d259d88c7ffc9e0d2905e86c279cb0ee7e409747602cdcad00b2f12660cacb919ee4d6e34b808a746a3fe4aa63dfe529d5bc4e21c8c5b464b331112241b74a79af82ae531925330e6de36254da380943dcd83a9285c14b13b9494c98fb5c914845a195ab4ad8b57088c23356d36b36046afe0ee21402f96387dbfea2907ada2939f6d360a0539aeb1e4d7b315eb22c99c19bc59758cc0bcd89f4fccdefaab882aaed802c336c0fcb9a6fc29a047a6bd3f098ed0180f335a33902f9628b7aadac11500000042be841a7b09681e08912fc7741e07458e98e2c6a74719247f3978e48f278a92c1b860cee85f0c5e1697a1235168d8bca225009e86409e75630e0d8d0b7a6cca656f8183b6c8f608b9965ac55a75ab04231d42d9f91da342566a633b346256cb53c7da49c7ab39e4d79e1c573003172f2c36600c70db9b47b6c8fbf7084746a7157bc2341e595fbde178d88694d058f76742823a024e3cabcc0b86035794ff291044780129c9ccb8a09e3496c988c540e118e9748cdefb311cac071e0b1155bb4b5d37126cf9ad1bd3c410a1939ae3b40ee47f718e918b8d65b205d3162255b923f35ecb906f0cd4efd127ca1075648e4d4ecb669e96ef870f63c26252fdd688e790971e8d1dd28387098b7e3df5707f7ee7a92e893f341f826f44a594f28cb71ad99c8a94ba95c1e3f21348901a5a8a5c4323de4b2c278d8d206d06562022eac5921c630a4105ebf061bb1bc8f4c4ca14be67c05bf089f4898c06b23a3b74f17742d64d756cade818c152eb6fe8ace8e3a446097beb51354cfb30cc49a6eb3e070271a70ed4b1ff2218e1017e97a07bd510cdcd3571256b1d4438b6c72512f9ebc34c8f4b73fb5be7dfa6569a355dab7485a1a472f8ee627b6df735dbf63be0d1bc001300e18ef2e3f0b79a945ae91b539f7536f8f3e130180315949cdde9bc8bad1c558e9e5ab698e2e80c79ec6887cbb550c6d2362172387e0dbb5aaaa94e54fe572155259046ee6d0d00e9d9e37d963b03f946ba2112d20222e25a5915b8658c2ca3dadc2ab80bbe37249be45ff7d84abba74289c00d8654d0a2a783650fd1db0e42460b8af613572d1144660bed6b1a8f683962030104809fca6b4b3bfd127ed6b902b961a46d981a7d3805111728180aab7b5dc3f863dfbbead53a84cb57a91b6eadb4e0d3f3041fb0d502d20085aa84a12c98afb51c3885d68bd0f8bb2cb3e681754b7a0692ae29a3f1a42fa5afbdcb9d65778b8bbdc3ec3697c04ed963db8b7b506ef4681ba9f1778483e346d400e43d815901a5fad8df28f600f8359e753ae5211e7c5608a80bff8bc88127a8d9445a5bb7f551cba02be0cf6b6dc152cd2baf138a3de46034036678f341c86c975bc7c31f620740f65830ce4f872e15b5e359dd80d5f021a26335e93eb2b6e9b138ee8bf5aa1f211b65e8ac80cf71b525762e136f239d2f0f356b9617fd3923e56a1e347d733d390ca44fc030af62ed8cb36a2e9c7b05f69ff7d0a69f6110190a8ceda3a0c4d143188d03d6eb4e083bc56bdf4f1fe56ed53660cae1805de188da75a9fc2be14e0236665ef3bde08e714581019f3bebfc4cd70612c625068a53a6bb38b2eec05f58a80b8a12b1a2ba94ccf6d00ddb07ec539e860750471dcceac67370697fc3b88ae1e90110e0296e1e27be597176f6d325cf2cbfd575ddfa5b4d1c31087cdbf4eb46c6f8e1c6cd666fdcf0ad19565585a307afa39a1b45c956238e4e15090a86bf6d02bad8d9ba3861641ab6462d1c2f0bb429c0227cb2fe3122c8ca25dc3aaf426e9700883d29ac74a92e472058a9b35ed1bb8bbefdefc0ce4bbf9d5ec81897e338866a71242b7895391c10983e2e82fcab90d5b90346010157d56ef8349173ee31a202ecf00649f010a33748da9f7b9764e53d4b182aea4a6a26d919c02a45bf360200e7f45493f45d374ff2bdbf0eebfe88ad74187159df6c17dc9d079e27e3d7c95bdb677b365a2c93a607ce64b04e757f3d452c6146cb544bb26d1a0c94c238628de8e325c8fe1cafae2cb4d666e0bc758a50f4d15c3eeacc5f183fb8c7474f2253e0933cd97ac5fa110b774d296fc03dc45b5b3d769dc94eab1279971d0db99b1bb58245c378e52cfbcfc15fc02b643f81388422c478da0463092f2ae429c2475dc76ee515669c28a9693c9a6b20e19a0baa1d77d1195fd63119a6c8113fa9367fab9457130f535832a65288f0257b4304e181ab5f9241a3b46b747bef26248eae3f4cae633df56e4de574dd0000de3014fcffd331d670436e31a56c057b638871aea913dbb7a5e51fe056bc33afaa81733edb6053d842eeb7c23a46504fba6d6de4cd76c02dd8f117c9803acdbabb5d8f0b37db12c5392414b0d29ea6a6eabb258dbc501d4fda3653e379a9a04fd835c0d019db02a792be1f9b0177807e0f2ee4caddc89f54cd6740f9c1507996167cb081aa3c94b482c90f36871372ac04560722019a0b5bf68ec7f46385b96d90f9932dbfbd023c26136573cf465f32dffee5b8e896409a07c7ea8889f514b906218c5f931b4900e1f82a5828d66747dd23ae77314a3bcf9366c13c945c0925143ea0621d3f559e4fa1f6ea84787d0c2d904b829bdbbdd61a22cd03756712d66b71f9e1cbb449c35de07da41c6a36d4238ce00048e85a3d2ebabd4d282606a1a039d6c0f2556336247c5002d98db040f2b558fbcd0138b1cf0937228e42df18603aa1fafc35039b4cb1e203bf542abc63e6b83a8f16f84e718b81915e42558c64dcc8db3399972db241c55a8c49926bdd3ad5c35b0b72562802eff62dc30cc6a993a5247a6df41baf86d3134f612d833810fe23ae6d4a7e89ced9c2c94d6c6e674823a2f3c09c9c0dcc5d03765a4151d1bcaaa117d5f5390181b4b6b475e571c95384d8828160d17d8d40f14d45ad2bafcd8849a242698eb32001657198676359c8679a3f48e9dee47735a2b5f58e1d82c07115a3ed6def5b6b5473df42ca3253269c0f70a84f0e3e8398c17445ab368f76951016b44a7bf7d9cfc39d2e83166b83a602907214da32bb2dcfcc62d302b3a0fd06b4b89658ab70d08df9e6bd9fcbc6cfd25bca186bb97716def62dfaaaf02a6737e27f8647ccf78c5843494428c6b21a73708e41e6fc5ad35871330294630fe81b7fda703bf24581f0428e4aa6ea0d124bed48d102dcde0df8d6b3c5bab1dffe0370d53da9aa25c1cb5a161276d4b9c939a1669b0d0bb31ce3470a17fee2b0da0f01a7f72b83414d579ad7dd4db80fe5bd07fd46bf5ad405cbdf6649ba14ed0075695da6b3b52255e5ca4159d2ab9b91d0b4057e530d8a58105778c57c887846e749ecb7688e261bbebe1e62c890879e5bdc00eb344a0196c72c0c341396252069a7c9a625ff99c29ea8a9027e7a9767e9a4fc9c06db743c3e7651ea069c82faf611a0003183268cfb319d2d3c57fef90fdad2cc2e6f3b06a9a3fc8525d4497afc49d104d7e79e3dafb2d77e1fb4dfa5808fdd336a36ef597e09a57a5fd96d4d9fd93489796f602d492eed95553fe5e13b45ce1acd4608eea5a979715273921c066455e301cdc79f8b3ef28ff9632c60fafb6567b5dc2e2a68c6bc7748d791b46347bcad1ba62b69e2d8e8800b6fed7b68033a40a66e0c6254d94e9e870d6975d20ab756f80f1834ef6cb14223d930358cb427f2b88361189e8bec09a1f34088f8ed031e40c0bc2bced026bed894f2497c59eddeb1e176d06cf8d3e75c3a4d37d0c9696a3f9c51bf83039d9798c81b52e6685d160ad317914a7b02ad45f6ba38b22fce013f823d67608eb96d4547af7a7f50c68494776556433386b9f3b1c977459d94b61f949411c4036bab0e0fd183432c1257da0a2edcae135b737fa175f063db0e5229f384e16758ba497608e150c4800482e27c7bbb2b656f3e2c6d593e0f9f6c634cf182b54e17746b449795545d10ae957557bb8b4c208aabd82a4aa9ea9581c2e9cd6703c05e84b7a3565524f4bef3ead3042508b2e90e20024a2599921fc185cd5e6c19ca0ae09e5177e35f072fdba4669099f5c20df3478861275e6313fb8e7d47cdf8d724dd9404026b2581ed44aef671a582c1792b9094b3320e3eca91e9f1096527e0809bfe3fcc810feda5de3ab3c3239728a3a0bf0c67d07c690f9cd4d2935129dc9690836dc5d5faa8e4f4e8d0eb3956a9bcf40b44a5d6b4313a73027e7f791595b48551c712253e713a8ef0c4ec56b887c53b951254e0d0b6ed85a3cf24d5b960937fad1b01dd583f4c0fc465e6242135599fe96131c9fe94bc7cff1d6a6583797c00c85d150b59183813af6499394b6df7816311c9e0b6858381e4d92c9cc43955271d1f108ab89809b61d2c9b86fb7407c69d5d09f9e0e2ee3419918ed196e9b1cf88e8f7ee66dcd27438f9b6cb1fa579918bba8d4eb961ba193eb87ea7b6a0c496994a2b85574e622278dd3bebd5c2ebdbd23d403f1a46c64c2226bd3fab38821f94f88aae56f90903f7ea9397c3c7bfe9f84b58ffd4e04aca3fab654ea57242a369e6416cd473a0a3569eb889b65c5547cb7416590f2cece1254e815bc1eed2142d638162de6368956264e8790dc44ca5012fd5178cb088a91a7767b61d73f14c4389d9e320322edddb297ee4e5370979a0daa136a1266a1a669c36e18328e680529843ea7c460ca6d748276cf29d7d9f3fbfeccc0dd0f4b89ee4bc410ee954638a55b2e85350041be4e2d4cf17930214eb179250483efd0cca98ade02e89fc7c9a2fbad9b0f50f591e09b763b88a65e21fd35a97b149ad75fc16da7d52cb806ce380897fe62fbe58076d3048bb663fc357b9e0bd74f31db5bb7af22272b0d7fbebca85969e56dc50bb5b269f72eb9ecff601a940ab92c465922dd4f2fca77ba55243879e1b9c78c47fe38c17fe4e03551ad118d4441d50c198517090c628d4ce14c0a44369413612c1300a9c37d068b11003c000f96fb33fb7366aa72b2bf5e91c50c3db626f1152b7225a3f9b4c7970ab63d96b41819f22458d144d4a3f1f33264e8303b5851b3402b5da9f548576f82c309c49d15ed502a0510b4619ed2e1502b08d05382a36ea99c64b325ac8ac96f0f27f186e0ae4e3bccf5f54a22b660c4e9490edae06241bc1daeddaf78353eba71261901c366eb6cecacd428df76c90c2a352d40c3583c1aa60c1465f0d87903bec12b75e76e92e157285cda428b1dc5e7c0734a6bfb2d060f4dbb371f5a7e35367c143c29a2354c144fb387be3a6897b8370a9eca1c1fae0325b1963191fbd4c8827cdf41da124913a3ddf0c9db20819be2f0932159b2f8fbbef875a3c722d1d22cd4b67fbabea0e2d56901c4cb710ecf8f044226b52a25a8eb6524d0f084856af29abdf94c2406c9ee08302ce28c7b631fe8ceb850904234f2b3869567cb699d63e2b8183756047828041ada118a4c5ed7516e55e63b8a4354228068d503b482ceb082f4268705a65c121a38abf3be68ab82ade2b85083908c4aa82e7cc0cc290b611d030607f0bb1309c0212a17e4026e8bcdc73f88a21dbc1ddadfce266c36d30dd38df2b6386db38d4c627b27ffa0179e43350d4a22624e15e10fdac3ef758f173572bfaafc44046f72d63a762e9236cd37c7bdfe1a058c0c89bf2d9f0a255ed1ad5af76aa1171c38295358f77c98912ee66c668f98dc64e6405ab0f6bc5bd1187b9f252e6a287a91c95a7cdb288338a5505a624024ca90512cbda6c6f94a208cbee06ca89e4a608f56d6fff704aa46985bf6b928591fc500df6f2346a40c70d8bf4b8b6c0e98d8b18b0407d8cca6971f661d4c842828f7e3d7ee215cdf89f61f7e8312c14d44b5b9ed3e0d15bffe40892830ca508005fec27cc5944555805d23b6bf5b23c563b78ca00b3abb8292d1c205db5324a6fc89206450c4aee4738e422fa14abc3ef19110e563c7d7482c4bf645ef3e4d0fac247ef6480b3ad0f5323195e4b412ca169d9d28e5838754812ae5ebd9bd1a680be32eb71343abb681042f1cfa9bcb8fa7b5fae63aa360c95ac54908b159e6dac6007f810c09b8cd560babad3bbc63dca7b3a35c2bfb4c5513d28ad34072dc7e3a794a6f03de212e12070fa0e04b217237f3caba77e21986bc7cdc7dc459cbd979d2b41a2eecd515360f79a238598ab3da495d80f64a4d1949e95e38340a86afc28eeefdffe685930aa5bbabf0d68c7abb0151580c873b2a0d7adcfb0e8a9f1455740e4de61c4ae3b6a3bd4d620a7331ddf6ed6d5a027b32afcd59fcf3fbda82ddeacacb5f5a9b505f2f38822982a6bb5299d030bbb8d916b7529b18ebe79aa5415451e285c6d6439dc0650b9d76339adcad3401f1a34bf498c38c0658b88ce61851f288b58b61cb9fd48b85277348064bc0818c416612b91749ce3e534a98f55341dfc6f6d8473196bb2499dc89ae2c98c104881995de83b2a207c9a7e9c1e4ee4c7f66995fa7143a83b4fe24ea2700312c2c6cacbfe77c3155c9ec122387436eb337edbf471eedd40788804a08ea04b21626138f89d4a0a0ba167703c9dfd0be6e7731f54c7b2ee303241f84f9c36b11a898322827b84f1d88a2f76c003600db30defddc9dc33e27b7fcdbe235789335b7e2f1396273657827028e9fd762a9f6c790744e42ef085eb35a19ccc58b6374046e08a5679aa0abe5c5df3b2f59501ed59f97c73b8cd9e73db6d729950114000217f592b68f4877fdd3b23c2b07a15754f9a3c2b2f13905d74bcbc4b04f60303a0a272cc565fb4d0fb9df143928276c688c099c745eb4bb8090484cd07cc13129c2fa3e0bc1d2084b938df09886d6f39eead6ee080fd06f7eb31985cd9bf7856d8640689da3355d1779d308a839662516f312592205ed247ed71c4ecbb0801ca8db6abe31a801cf4f339690df6d965a6f79e5645f047650047c60d1793e82795f4531ef23088626c01b2bb4a05bc79295c0a840a6d8423a9b9d14484f1ba5fe74fbccb25f17589dba51326c539f81b494aa37a5bce14f6621f5de4dd490f57e7d45437177d095fce151fb6af39636aa979dbefb870f088ccf543ae38343f70cadd7bcbae32e746cbc98ac9c64b42025859d1647b23194a695453c1ff8c2008edf85b02212c405cc60bc97f194203fb3aa6c4d76c6e02fb1d2f3c792cc3bad01c772a2ea16d263d65bff6d4ea30d872e250c7f45c39420e13c4ebaf54785ab1b66ddd032aacc11f7696536228a59cba24beaea32d0b3a0ff5d42b0321cb3d613dc8892c4f41359ac52f6edbc7006afc0ed3f9cf10ae0bfe389310b3f995953f440a2bb43972db1155931a083482d8f0c85d68ebd6c2cc832d100971dad3526b8eeb0fd3d6c2961b7968ee4c6dd22b2f0f7e097be18fb5d2e035a740a47501261ba1cc2e2b500d25175e1d166da09e5914878b003f4339acb8c1063a31f2f80812dc416066cbf0b3e20f9307116e1f0985ced773533aca5d3a812bdf265019c62c182310885c925a039f77cad41d1d390f9be2fa9b2c69db406a3e256380705be3019615e5af3f1e738b1554ee0349599313b58a8acd2051c96a4a94114052c41ea2f4ef8ff78645619ba6eabf826a5950ecc7f4b3cf866a2f07e315400d37b4faa378d28533d491b8d111f6cf3c7ee52e7672d5886e912db401837d3bad46b48864592ecad788fbdb191d248f0aa13e813eb11e88b86a29d2567ea107c64073c608b1e19926bdf1a937ab5f41e356556df1e6b6a92807d69e4c7bdfccbb4ed7f1adc39049d5eaa1169490c7bd0af960117abb430a2a289fd0ac52620447403b6a70fadb87dcc95ff8913aa58e59ecccfad187f01554bc6faee89d4d8e0ddaa2726dd932028c09c849522860e815492392834483ef5588111eead79066ba101cca8edd4f991f65f19e04fb04738005b75e8df44f04c0c8e88381afb2b61ee5c0b3643dea8d4ca43d300e55a70c46f4cdfc8165c2a76c3bcbb7728e26cadd169fcd3094e3e84d7c7d43325e7ed20c6579a334b26763588407265629fc99f24b9d936a0622cc5eee39f660aba19b720c634704d847465c8436cc1b455b27111899cf0fac8a69ef76d7f1eb64b32221ed875877ece36cc2f89b2f66f4b43fb20900e2c50efe9057daec87c7c123338618e343e7f37aa615aef7e65121e4046c30050e6284f781a3317cb053d89cab1cde7468eda6b8fc94657af7c62d3bcf8f48054d5aa2b7a5b934a208332939b457b4a956896a3c1cd666d75e0f71a16430b777f4b7f22cd024723177cbea4cdb0a5b1da2b649dba5e6dfff83ef4f3abb22d6b3bc6cbd4155956b727232a81ca9ee0a55fc89f1955ddb6b1260e935a12a3508a2b20e9f658105b9281d393b3f80e2e3f36fb42f4e154071a3601d2376c92d18b50c8b5a2d12ec6109a5877d127e168ad34fe045b29a310f116b229187116d23fa0d8fa1d2c3bcf2e4ab648794eb5eb650ea59f2cd6cefd9070e97f029530430ccf16da45fddbd4a84c778e6e226b4e2b1c6e45fef16d3d0f87bec99a02f23b0b6169bfe4b3be8439f698e8bc6895706d123dd9e298d1025c46244d260c9f4e393ba94cd28e9bd4c5878da1e519f83816679d97ffc74cb18ce61404c75b56955bd265e83c8c1350ec0245f3843ccf11b71e9c38008a6dcc78d728363648597e86705b25c5ca06801779bd8cb821a6365ef593aa442e214ed37e043b7e803abfb4ca309cc865dc42c1962e8742646104288613e01a2c707418400fb7b404bf2e0d37f0c6661961b25a648c46783a31607709974a94235e7587a61b66ae4ac846475a53ec946fc486243235e0eb24c511c4584b22abc26c43d2eaf433e21f48ec6c8793f060666a4ed1751deea314aa7c7c4ed8b9755491ca1c37fb11eba554fe08c058505d2ec8b53210e1ea744814441a85e4d5e9c0e8ba99b350bea28c47c1bc7d41045ae4ab2adf56efc8e9295a1e9fb8866f1ea599d2a9290ae28f3034d684ec22e24533c45458c216db28282e06abde31351ec9afc6aa452e601b884eddaabc50e4a9a9426e423ba074829a9a0d28e8964ff2359acfe46508e99c3b4c3de4f81d5ed16ee89b1b5d8b0144fa83d4c3e8692a058d3ab639d2ab2497b19c1aa2c11c9759adaf61b0c52ef8bab47388302f7f6c678477d23d872029cbb7f470460dfbe5e9d0677dc5c3da359596285cec6ce0109d6b35a05a702084eca8bec734597f5a1be295efbceeca630b6af3a2d4d790a83683d58c1d4f128c3bfe0fe8d6f6005283dead907225bb0dba88bc9ff124f9c00fb2eae10d10414e6ff29e66a8da221790b8b4d21312549f10f6f46c8289b4628aad84e568fad21e0a7950a9e1ec75f1bf502680da1553f80189fc0d56ac7ddea82ae50a13517ec3b75467f15e702b890855e5fa55fbb9873c713594a206d5a2260fca74add26729fe12480b4eacc31c288f3ac9aca1c4ac4becc603dd5068756aa964ab81a0ba0d2f4c5e0149e0f4182d3c79fb2082431f6010bb5acda8b41998fc8e019dcad50aba1a9166a1b5d206e77ab49362eb673c6d00d27f9c65cf9eb5e1263d50d7f1382023a5b09726c6b8c983cab88cefa4490b82e809e87d32f12ece162e5f944f1b64b02f75a5d05843b251241fea6618e5f42262107d9ea54456e33086b4cc5a7269f44b27e4b809b67c105ca0e13ac7af73138f5c42998c4efa19befcca6b6bc64f684cf43cded400ad2fdd4ceb064e19e8863526e586e2da9270aaf340768c21e2a7ae0294aed4a352cac9429294b3dbf2535a95d801528845df116f8d835a4222635ebf88372bea507e0cc02a2d3a16867b64c1a4306e87bc0ab4d33e3cf4dd83adcd2a15764ecee1221c3a0cb4663a09a90ed53e2044fb3c3111d2c767e014edca50488115269de0ddaba2c8e5c041dc5b45a8a33eebc40db75a0f4609db6df2fe445d9c0598a926125fe9908e421f4b24abf6d1f089e61556bb572c082e588680961934baeaa4c97c4e83b5c8a0daa5fc520364e7dcb3083675330bd38d507da74000df6876b8fcfe4ae815b9906c79e6ee7aefe84976da9582277ef53a241f155d8eaae5e95b1d1c5a363a95f28e81ee27d7b656ee077fbe8d8c0b7a2f0b25604e7161431e0a625d054dbafe59d3fef6fc8c347d1d946f959b70186a2c80b6534306fcca4b70fd08d18d3e397a3e78a91f3334e65d33bcd88fd75e7b804ea1d241a8bc39bd28a8eeb96cef105b23a10f4fd670fdc2a2ea8496366a2af5471f85a29fa909b3c208756472955556fd404c9bff37cd656b705615d1aab6bcc0333190879186f8eed19be5b12e2527a763c0b3bca7f3211afa4add20d660d67dab8b6a69bdc377d90de4b6f7209a92673f52462c9267514206955bd1f0f8ebfec83f0b9cc41b9fe9cda81cf0b1652fa3c2aa145171d7de367971a794a7100e388f9944c662e54584380fffc243a787a84e85d155f7086b0f0c317db07d21681a82e25f400d1f44c99aca07c9eb19ca7d4ea7dd61cf3ac526e2d399483f7d3461335df1fc2a22e94dde6f9d8024afd0957dde955999df58cbeb4ba2da26eadb7c19ea464b6f2bc3f9d849fcfb250e42d2756c260276a8dd3402fa555351bb85d09e852d00804cd1860f3b3bca96769fe9cd527a9c505b768370b66427d31250919c1388b8220d6ed94885267dd42e8cde809da3e0bbd01caa17adb95213c62e34df07cb100056d54eff8fab232c25fa8e3bde04782795df7edc585eef396db37d1f3baf8a7fb0f3e651660a90765641ab1f1362465725b1aaabe6e643f9ab48c0ecbb05e91002e65ae2e33cc9ea9655a3180407c733842c9326de9da968f5948ef345c36a04c4c68d3da0aad83c8189507508656954414223c35d541fd0179dc66a7b6d200153de9d184ba31b72afe07f40bc0ed0ed01e44f15323a47c724a8cb36ec3817d208002845887126c761fb1f2dc22ded8c61d37ca2cf501cf6074f4b196b1dfc28b081ddd588ea2f2479b9593acb390a77785f39eb238bb0c70b8c7d8a14f095f5ec21574457d40e860c07f925f1a0293cc101d8fac9a58ded7c10b1fe517aa4cd17f9b960bf698015e35974429aacde3ad9dfeb0c4825a029c866a37bffeb9284b4475bc47c77bc99b8832d57defac3ffd1c4a18ab8b5a98d9bd3ba30725a1d9f23da6228ac82f067a1ab761a48caefc5b0e04a7f230a1fa58e1bd1a239387284d6981df8b8f9756d04515ee0a35c3e959c037d548047eda7278bef0b98ca1fd7cd5f861a9467a06d5b83b0b4f99a785d9ccde960b850dbfcba75d2de4cb5955d542ad25e3dd032068423f61ff086408e0faee155ca00a38e276d31f4d402a0cebe98f2a10d3d95c92c4f255b7f4f8aa060c7953c626cf12c26c60b363d2555e4f0d3c9b4d376c1a3f35ced71680bb720b96d52b4c7b531d11ee2b3d50ff0b31ba0478ec30de017e9e4bde5571d36131f0be7efc4826e6008b2d5a19ebf9c30b1fd59545d1c97dcb757e71c512c8a05ef1e32714306ab4302979daedc16be72ff5f93209195e95a634c42c57cb1377018aa020b41f9e70ab940041877891c916a95a359176ef705a6a29892665a1a80c4c8a874db6f8eb3854c9a37472e01c18df34148a1409815ae0a7488835024b08a0f4d00f8c2803bd0b9d100129ef68538a2d98700de603d1be11ea0a6aa0abd2de7f8253be6e8ec0ccd97b81f779dbf6a0126b24b044c88e6c964c45da8384e9752d738beb870a2e7902c85011286ab7d222eea73e505a387f0f788b27a1311026d4e064b3040880b5dd9d17d4d75085ba5268f7d0a0820215caabcbae91c280197598286eac2ad7549344621d638a27f640627dc408f4fdd7bed7be9fd7172fbdcc8b35fd17329b509bfa1456c10b40890787207e3c11c61da304f76ef51e5d4c40f68a8a8c2eb01932003778a0b63b05f5430bcbb4a141a922253b04176bb0e1c01f03934a913ebc1063eda07eae6dab94a0650beacab2e27f7610cdd4216deea56adce8104aa12c9f0670d5f3eaddac38f2226b8d8f8b698bb8f5b6c1947ec885794ff30abb65c5fd4fb34727ad2a5961a1dc15e4c67a0346ca1c15fa07522b852b7298c59ab67a3a01afb3e81524552e1d563c8847b5d6057fe8e8e5f0ca98bd8807cf9b38721606975bb7cdfeb2ac608572d53fba95de6bfacbbd0728fb9d0770f9e099d25d835691e37ea4d465f96d8ef61362c4ddb58213faa2afa42e85a2ce856fc16a644b436eb59b8eb87ea26a6926208c70ddd94b27e86615256a63bbd1aa5162634bbb2dd8152ed453a24716c36fd4fb669644e154dfb0d49643ee962884ba5fc388b0e21159f4da242e36ac98897653941a782ee565ea7953ac237df2064004d178850aced5cf8b5c304aa9deff9b6d176211fdf98b4152997d6480e027ba8d3c58f710b68eef923960f704dc95dd5e5c3746f1f42cd6cf56414b801500e145abb30d875c102c6e3558fb7cf0eeb88dab4c7ebb76287d9e4497fa6a3feed72fbc751bd1fde326524f9c229bf6aefe869c7af43c74ec1d7c7c3927dda100fd8c408f1227037c0d268ff31c2384731afa71068caa39163e62c915a5514b7bca19ba132b34b78cf4f8ce4d798c5720c593c83c84788f56181cc5fb28a7f2c7be0eed65b0090f0cbb00ba7f0219dbddc4a2ca0cefbb554bf5dff23623bd87420df4cd8cc3c62965b35186de4afd0318ab851c94c6428831d7f32e910f793c199faea8afe4c5b9f719a76c0a04858007436c7a01ac436e0b2a93d2249f00ba2b5ab4403fd59fb6a0b4f612c108e28f0425a822d100592364a03be18ca37460c5cfc20cbb4a11d477c344264bc1671bd39b2373b35421335c2a78a26915a67fe71dfac52d6c3fd500aee219bd3dcfdc5685580490d5520ce00308c472a2a2cb473297210a1d01a26c86b80ec072a8b802791f855ec22cb67362a9bfc049130767dc7404d1ec4f19c6875799db87e395f82aa6c50a304447dffe52e357c419238e43154675b5022f30df355238a6b02c04707d226cd999f1ed37b419813b396d20ae120e6cca58724b5b6080aec5d162a1efd275dba2ec495c998ef65e7a470517711fcbc5cd0036c434906b67ecb7920bfc0f8a49f4794032694454fe46abe1a649602aa00085ccabe860c62edd83822a0b808dd66fda0194c0afd642a6d531f5b5ca15a72a0c46b75696d43d035b23ca016f6f8fbb3f4b8c3d8ec3a793580afd748caeed32071a0d32e7090d6bad68b4c2ac7c5507572ab2d72e10ae34a4a74b766927016b9fa45a24f9f5182cf65f5c5cc2d3937810e83405056195817cf3fb7a8efa7231e9d4a821b35443baae10f2307201dcf36081c1f92ed7656051d55153574514b401b2088e635b5b8b724c58cf27d1a90dbbf83bd0445f3675d89de1f92a51b144ce2962496b3c9d24a7b0f0678aa8699c2140ab75730dfe74f0a2180119438777271dbf97e25950905c09767cc6f0465236ff2ba22294043ed0acb970679dec3eca94d8d01071b2bdc460e2c8020146cbcb55faffaff2e51d0d291ff99716239e4d70c0ab273e53d88a3ecc3a076d438f799e2fd0117f4086e63e251c54096591a1903a9d2713ec8f34d652eaf086e06cff07986bd87adecba1b32e4981c7eed9076da42fb0a7bfa73b5e4cc65c63aef02c567d8251f1bad6614a069258907d8c9470240d0ca7811cb270411fe99760a5fde9b128347a6deb0e6a241f8aaa90bd45df19da7158ee2d25cb2f5016a62df338af0e981b85c0eef71a85d6b73d951965544d082619579eafa963fd4cef3e67ab02cc57ab9e5204494975166859c77efd058d825f18f5133cb5f0c1700fe388680f36b51201c4bae4896d6c8ee237f2eec6e43d08d8967337971a551d8dfa2e373794ed42676069eead2bbf03adb81381e8af6b36a619f2e21bfeca9693051e231c335e120733f9836fe8cdec42eadad24754022e04e87840e9a651a89ffc8575a5911823eb3a78d50229e3eaff7b7d45f4f525739a5d5fa1d088fc027404e606d069c6a88e18aff3cf859e02aa8c02624dc5fb96d560824034c652f30fdd11f2a6aff1999fe46fd0b03480e25e7213bd0e01b66d947d79f8c4fd1e38cd41bb013d2e2111e31e28c3beceb2037268b1ed681957b3dce75807f2e9524470f72ec4ca98a3905f2af272e0b07843bd650bf06f11599261f1ec619b858246302cc4aaad718fa9a6e97f7f2885e48dc251a1b0518bef347edf079a9a7984ee7fbf4331c0ebb1da80942e7ae2833bc790b52dda7927fd05d5e213d80c60eabc6bf65a0192c2a566009ce332034bd212b1ed378c1fc3f2cd32c3c841d7a38fdcf3464030775ec6ab9260fbd8b6ae609cd828a140e0b98a1b2f248f6ae6b6722dbe891b2655b2ca68b80d4140c7fcd0e910d213a2556c1da51c4a7ac3b0641048b51006c2385d78ea44ac815ce069c730be2053a272f5f6360fca1274e0da8a8939dd6824faea95ab4c9f60742097ee32968148cf2899e7a681ec7c30b200e701ad3d054343483e0e65700eaa7a91fe44d06d2d955d48564d78893d2d9d28aa3d3d0d0d7ed2c5454be9537050931a14036962892762a838d4ec5dd7da5dd41590fe84b9bf60f7e2421d1bbaa5e3b48e1f290ffff46f1850af51bad93e7e65b3e0b8485b7cb0292f1f99c9bd20e82ee8bd54a80d2ba2f3e88c398d53141a55c6ba028525f99355560a970b0cf0815734699c1d48ed9c3b361062e3ed4d424f6802d7c7ef8629f2612563bec54213bbb8296808c133855ac7816e0e42b05df6cffcf3b4f4fa7430b875340d60d51c9ed33adaa097abd744028a331e861b17c1a134b7ec3beeadea4344e517184b8ca72788da2f9ea5c52f9c9cd038cdee507753f13c7416e4b84318588e481c634f212dc27654d6d4a3b7df22e5c7bb5683ecb812abd7056c8f57e0e3d59dad44909d54ddbae456c11bb1ec78678f576472f761ede6b512ed53d4c29bab88e145499184159180bd3f015374ec24ec8903ed8e9c96fe398542e256e9668481790c4fd58004ad539a52a7aba2e962661409bd4a809db7757e2fe9154148c71af5cfa8a5b5a6087d63d2d7ffb308a07d73374cab1d799c0ccc403d6566b62c64b1825af2d661e90c2d75ee1ffea5084eb954d7ce3bf20eb9503d59afcf779f957ad2245832185846225857f7b75789cca8ba0034abf8a8af3b8c45070698c8373ab9063243137c3295353a07b1f7e6d08ebe34ab0600035a28cf2529433ff06d8acbda4d0ad7d33c9e463383ff357f09d39ddefd23ec6190955777012029e466c03db2736a697e44cd9de1c46df1cfc3303254e1a34b64d3c76ff6d80009c771b80e519c339ecd5c5520b36816e80130b4cd23ecfb18b0c15366f9e40e5aae4e3ea9effbbeaf33f3dc0d16f594f6f126d37de6e95a33404e74ab8f1807c2e2860ff36f19e47965a21f22cf79b6bd3a0544077d7f892773b92a29dc686a3ca5acaa4ebbf78e780ea1fa464fcc7a28e0bb9777b72ea95de11fa5ab736e45410c2adea685573abf0e2c3af3bcb65df0038e55c61ba6590bf707a5298c8cc9ef2a139b437c2344870d8f079260058c2b103d47d408a50683632d3e568bcb907278990cb21097596ad011324c06d5396492d1af0459409f2558f44bf060c1e1d455cc03a78c24b3bfe13667e75ad07822bb6daf1e427eeecb80a0c87310a1a053e62d091f31714dbc5f727212d1544fe46227c0764281321cb5ab3a2e76c157a8403bdff841e3fce55df2a0be63ae59a8d957421f650180d8d58031c5d131517e7743472a3b0c7713dbdc4035d330d4a11d1cc9401da6e93d3e57ec93f542d720aaf09cd90666191ad874d9ac381cebaff0b0c16fe50d3595e74d36c010f2b2928c51e3889c6e3e860c8fc9ef447bae031a83f422213dfbd859dd5b091b5f4bda85eed0bf677cea477a258f382a83a99ddbdddb08f700dd2962e35ec993a6c70eb5acb703c718460c09eaef7a16fb412ad8ae6a11fc8c04ed51443e8275bfe9f0b06bb009ad12250427543b988bbe5d215b03bea09e19d7b548c5c6709bf3764a14bd183168e208a1886a1a77f194ecec95072cf8b131368fc29e92d14b13468c332abf4a9e38be43e65728ee5e956f7b180230c2ba3b8370d3e07f0bd5507bec2cc111c92a2391068a5efebe162c049e9880cb761f50ec32c3c6907b4a494fc5dc64ed9fe43490b410d9ad7f31ffae2b2093889ecdb46b9a347de34d5331b2823081146e2f8d0db2cead6aec667032272cd4338afc00e4f390570db8b8cdbf7fc6baffe39b0d7ab390363b5a119fc9d844942be14da6ad85328a04d917845974cf83b55d0d0a39408149dcad7b3023bf4d5d72725da35a5614c7a9de131ad769e21bbc6b97806a47090273d33aaf7d2630d493d1d44af5409940d88b5d2820eb1f39d81f885f2b1cc936f6d03027f3028ca00de6839e0650566e24a7517faa048019b6c315404b616d86117179871c4f596ba02561dce55882bfc4e44a99517fd02910d7b445e257aa2c19c1c8ff37a6b51caad7aecb09fa83f7e06c7fb7d474aeb4acd2932f0c77b71e90270738f6d5322b7e3209b4291ae9114fd94076613b403f17166eb644fe3c5601aedd27b492ec57c023fd9d530a373cd8ee979ce4011a8756c2a08507758adf0162022de26116e3c01213ab203a50f6f788cfe6a7620c5be6ad45d9d5ac066c8193458e2bb34a123ac0fde420082f084dce791f23ee131ff1f19836ffb6d9969d11c302c0b51a5774472a2576469eb4008ed5480228c81f3e010b5fb00dd266c627e52bd40642693488c8cfc32a6cd2930f13f1959abe20cabbc0f06fa52f2697c164b32c0ffb6ffc38618917f28458b1b9f4e06c9af6f4365f4c19ea2671c18e607cba041cca86e69e46e5d232364d41112d9d89b3808776504eb42acf7026e36e015ca933cf472ae2a42e7fc7c5b82ab494f6a62b8548ec177a5b4338ebe4857f6ce8e52b755feb60a5b289a70fd5f63bd020add4d1aba33a56a65b7358425c3a14398e9c7d0c386eb6dbfd975060a3e8fc801137f37927cde1bb60ba5d51796184b3cc4ade3384e45ec42a089ee92a5a87570efbb455880932f98d6241f719005e8bdcd7592e27e959928228b28270dd3aaf2f5cf88c5d09631ffbd7c68573a809a26ecb6dea9cd1bfe18820d96fe34df0e2832eacbb800318ec1f17b484f3e5d1596083a6c0f0516f10301bda34747c5f4e5f102fcc50f004640ed4b5868b65d3d5074d75d47116303ae074d1ff6713f677ea4fdfb57b1df2524edefc97c3aff2dfab9925674e03c60d0d1b16f59d569536a7167b7b7ae6f82bee430c7355f07c9bbfa70344853e0c75162f75c3b24d84e55dcc78eb2f0b3baeb6a02b7ba715509680901c105b72957ec17be5e60926f5770cb0268114ee4d67d4a41a248b22c2e84962f4644e96c837176b8afacce9d40211356dd9f7e0a82831c229ca665ad4c37ff636ecf18c011d20acaf8458a9a958cc25919c8b4a9b2137c2e3032ee30408cda09a4b13892af8eba5698ffecba6365eb6de9d8379823cdfaecb54c1670427b98e3773216c1dc11dbe04faa7e1c71a153ee6f72930caabe3e43bd398b7ac3052ada62345854caa30f27ff31d49ff5770d8567071922f812731a8512a696a1b40a3039188cdc88ac00d3a99b47bdc6104882456ae061b508ea4a62519aad5aaa51b653743a6294ade4fec38f43874d6bc1c75db6046308ac20ec1f721430b509fba26b1ab49957c76b990ae8baf12eed5e3bd7e448c2cb74ed7bbbe9337b971e74309863711ff257b6a3346b48f6bbea9cb86adc80895ed34e4f8f0ef621dde0d01c2cfc009ac3ac2d525010b53a0441001058c98599a8925ba159813995851515a345a608480300000060996666b68438153db32cb422b2a80100b4a8016823c84d967b1cd020cd1dff3d30559b3121f28f19235c37cb5a29654a01c702ae02cc025438c440b625b3d4fa2bf814ffe238a6a1fab007c3108c761a690e0eda69ac9976477b1bb23f70a86b8f723c0bb85f433157a4cc8e154a0783ec850c989190a029ab119b6f31a0621f504350f36e2c623b6175d90bd44d457d8a5ffdb8d89adbdabd3a7b00baeea83b4c4fb2b3a72fec06ea2c2cb46663c09c4ccae60a4875705bd32615d29012a1d4943c257363fb94c5b033a86758ba5004354f332349a0ee393c4ac976b181345849acb0cef076b0da33a9946d6a845632c21445d5eddacab6a03e1172b6b12b7b83daae46afb6b041386a63dd53741432b29e958cee4667e56d713de50bac73299ef5a8b96c23bb1b675550f7360eea3bfba3e6d971eab841419dc6ec90556a3a3ad7266a881dac5a7b0dc76e8f6c2e66629ba8793a5c877234ced59140575b6af3bc0eeafe9274f1c5c25661732e07a0be6d10358febcd5e675d2ab3ef1126555fe95e6af6da04751d64cf35b643c5d8559d6daae7212d593dede1462d43cbe6306c335bb9bdfa10b5883ae49daa61779c27fbf59aaab3a3ec0b6a621d663b4bec355b8bc103359f5182a9ca16a026ea54fe0443cd2a2667772db90239951fa768cf08897279bba8e23a49ce548250549d46813acda6da06d4c13acc1e515bf51638eec5cf3a558fcd638cd9c53aa42ff98baed5a0ee2daa3601f50a14b6af96a096f3c4e4e013360f0b82cae574ba0dd77e2351d3b07f3998f58cd4886867ca784ea0444f3b30b9b53b8466055500742cec397b867d072ca0be45aaa6b2ec7e4601a7aaa53a0d98bb79e87808d45836efb27b0ed460f20efd04a1a172bd38ec3e7e05f7debb147655bc1910b00787af782472e0a90041e47af14e6e030ff9219623722291e31d7147f6373ec7de75fd23b1c876678d3b9aead08fa63a1841b0236a01daa0fcec4c52643b9167b7ab66d23d23e98a95a875c1926a5dac1fc74610b5b86bc50ab5b1dcf375749f752e5d1a39a802244dee2e7579b68c20dcdb1947cbf4aad27abb7a9baa7f699a5b20cd7541febae39366685640ec549c612ac8bb6e8ab7f96d3b47b55e5e1e484bc5756651f5214d5f487337c82fed98cc90ade8a438cd5290535da63796ed1ca2f5785e2db468e575a4eac79ac890e62af117e451107f3b509a99aac5bb41fd0d4a09c81d4ac8ac53c327dd7cc9f61f7976fe3919fbc78fec8fffe0f903f68061f8e4ebc3c5f883ff0f36122d84fc15cad06988bdc87901501ea891072ff24f967f57679bcfce4d8b9d247182a26ba885b6e7e9ece7713f04bd7c9fdf50a88f30e6e8e0e808c1d11182a323445c3c12ffcb01770e8e78088b803fc7ebe18e9e081f7fe15e4f1ec62fb0078b10018e833d6051e8130a3742d0208608177fef0751fefc36a9e31fbdd879704304e1db391c7b808d84dc481bc5c35f7fe1e1effde8ef558f471c43fce3ef97808b2f7c9b88c5fc3c464032f9fac712330d93ae99ce24eb1f4bd410a5fe019fdf26402638ff588c97c2fee3f1efedc1b188235cecf0db7b271ebb872cf4742a011e99fc72506417a7ef8942d27b269fb193ee093bb94f67d68945794a6d0c018d4628e3d3b9e41c3a879a42273358453c726a0bb126f6b054145f53c9d9e349896730e291539b49e64bf7145302373ebf973f580f241e3ebf9d50ddb9f4063fbf9d434e1e27cbed4cf6e08267be6657132bdf4daa500908e2f3bbc9136cb2dc4d9358d84c0e3fbf99746762df033c03637ddeccfaf904e0f39b99f5a35f465c16c8eb7e998672bb4e742c5d574694585c1e15ef8a86f15cc4afa70b6f762f59d03137b2fec1cfef65d4f7f0f9bd444162f8e59b597f7e33adbf17f9024c219ecf6f26cb3ffe98cfcfefa5dd3f0e97735ff8f9bde4ae80bd9f74f1fb165320de48965fe2463e7f87b107adff49d83f8f6f284bf21ed9ca8a3fbf47ae1e27c4740c9d6234d227716ca4519c5c25636455d434b16c7488f4ee60ca9e907db2ece1818f71421a5d398102d6841358e9137b0205e932db838ae6318351ee0a309a7dfebea231a25529be688a945ed4681947839470b487246a53129549028b9fdf3d753d6751c0f780201f1637f84f04fe3f38890f4ee267340243188dc5df4384888b7047c7eb7baf788461f87d455a8528177dc5d8e3059f889708530979cca563f9efed43b5a1e3d7d0f1df5edca1771ad878568515f87c02863de0789b55c1051ee5415605165c80a118ffae41c7e7378edb873fbf71d6feb1e37b1a65fff8210256b3e5749d77a0e633260fc36845bab5f14e2df310ce5305074997d4cd476df3cdd9360c8eeb09cb3345f998a6196d4a2f7fbc12c7375fb037d0b9eb463927d905bd45d13c8ad88a2e1959fe9e9ada20dd2465909cce8b180f658302675392c5eb899bd3b833576bc7e0b97d9e756d450e0aaf3234c7f1506768a4ca3c55c3a4aa09f1d43922b5998dcc937c6d69cdb595dad38b143eaac8e74467b91a2b0bdda471ce6e3423c81a56b679c9ccd7c9f0382ee6eb95b6eacf54881dbdf8cc3c37739b8b979a31a14966925a5ddfe66642432d3bc378313b59d023527ea89e579040ea806672b060ba644e62c890c8dcc9c0f9a6edec6286170c9f861da39a974e564a53a1ad1d3f276317932214b34491172537a7a4cd2d63655e1edbc2ae8a6652bdcf521651568f0fa3295981c234e73c1891393affb33637cb6811307fb235cfb8d680f22e9866db683692a6d8d0b4dcbd3c8f5e901ea6ce23db66a2b3192accb3e0f2715877d448d30c339d517e5c708a5e7cd605ea6bb828672522d06e7e2202df3cd6d65b696717af59aae595ae5e5b9d819ae62024a3202fb423360382b7e2a52dce9316e44cd2c57bf333b64dda59c42b46cb3bafc92a485ed3bc86343f833cd20e77662e5af14b16a7476341ce3eddf9ea6d674b27b5beeae5536831afb34d754593ef419ab9825876ae66e6b215cfb6e2045b41aae87aadb7592a3ed857c39694541acf8a6b51875dc781d961353e3fb7f82c967bc48ede0b4a9c303a64cf8ec95559a54577f3b491c87ef049efce9714aff9a62a3ea7a5b44a899ac509c342b745c9fa2a6c0a530cb65969f07029e1e484de58a852b8e7c916cc6a859424847304807bdc977f672e98744b6d5c64564eaea5c9a8e53991c9493240b0c1d35b0eaebd30174802773b7772337263765dca709542aa6371c078a6ef409484b547646872480620015b6a55f1a6bea6701b6aef51de34992673816849213d984b76774d4a86e545c590eee01930370d9e967cf99e367fc12d0c26155c1d2ccad7dd06d36b9c8ab713269c0fe423b22f1f718168dc1705167321745865d4189e32c74e56afb692941c347a4773bf33aad88434b8ec9a6b2323695ac9745bd59127221653a5180d9899e8f1f26df5606c6cb4f49f90b7918fcc7dbd2223a2da2678409d5491c918171992ab2ccbcc29f5e6c459f9dd463370b08cfe2aa27e013ebf8bf08ae88e6fef3f7804875fd883c3233ab2c4715862062dfa8d21832099545dcb96c7ceca421b32c6c396693a4134aa5a1a70ef8d8986368854bc203201002055a36c47868ab6cc415b2e5dc5a1a889109dc4442b5a22e4706ea8050117832a8a64a6945655b5a66585915d73922127f4415ce451c07b086b83839f100a211fb17b28e916a2c231b7fa645f318e637a2b8e83337690a288e17a7391c352750b495fa0595953352d4ebaf0e7b7104fa7af6e2094fb8766c687360f5741ae61508cb662926f202a6d0554f43f7c7e03e170abe82cffbfd7bf2f09c51488c7df4ff21f7ffd6d41c8ffb117611a8b087bfcde8ff8b3fd19e47f03001b1f3ef5dfe0db10d1ff909be8c52e02fe1b37f83e374143cffe1b86bf17dfa2076e82861ef267e8e06f9450ecbdd8a742fef2179a06421231018ab870d05011250d3d6145617972a1255834b7a00c1a9af522001afa237e7efb24b1c0aad46e299d534ad94a80540f469086cd335dffc8b1018a05a894895d76992998045014b319000003201c48721c86514814d10314800432ba4c5c543c44948c201286826150180c04040261000000008401804010100e85c2b1b990ee03c2817c31ce6825660ec688091fc0e3c9e6a86584e2f0e01ad0c31738fad419e1278f954b2c88c61cad542eb686b24b815a55b11098461082ce2040104b916820eddcee1f734c5f6e04acb792c1a3fd619f8cfbb7d28774032a4d3141d251c101aac70fc61e81e7df15668412021c0d2788fbe877f439a9dfe3948a160670d234c37154393c879eb5cc757183ebbb2c30db4c2d9bedd09fe4909d8a34b8df2ba821ebadf95348ddb7d954bc2861b1b5ba1a3b1cc40c6abc3357b4055a1e4316932a1671e382300fe71826960b42c08386d2892058490a7b7a2788394de48789dd22d9c995a6ef58c8e8690cb193c6dda3c88a4a1f005335cd6150941298f3e4e64a20c08eb447eb658ec1fbb98b0da8ca7fab496b25a9c633cfc61dd5f12b4ea9d70ff8920935f41272fc02404f44367e59d5cdc97af750ccab3fcfb6d63593fd9b56190c0630c0270920d5b3cd4df4b2fec4e68daaeb6b41a69b1fbdc066c19de53e3217938c61a09caa825e3d255289927872ae985806647853d596210eaf6a8d646986fbcc7dacc171318b925a2d6458b9ceed3cf26b37da35b00ceb597d8e9dbd6c6b386ad360f94248acaa8c1b7a69f8866c0b84aeb71fd9bd065b9a56c81a6be902417a2886fef4e16e7d0333fca6d3e47c7c35154a18d391c319d24cbf5ca96a3ce3d5d5d2eff8826d23e737afea3714696e5eeb1e0d65163fc9950a5318b7d00de11b50fb717d0f6b2c95ec5167e10b5afc245b782d2da696ae6cf746dd82211a5f403fbe068ae30d7a785d4a6debf4e77ae57667841a510775c41399629279c05cb05a0bd1dc3354ff1635342a028a7de030173387103b7f9ff416880d47f0de9bb08ed2412d301979143ce1cf2f3db44761e036b8f7bc18ee1e0598e3e32477803e700111e2a3f84325d86309d64de9565737035f8b7b67491136b9bc51c4ee3da86f445c947a46d094a19821e15b2a921137ed3df4add0a6c4292d1d817a10d131d0926e0788fa4fafd199d6a5621d26388bea719bf6f55d3ec943e740632abf7a24edeffc69306e866c8fee66f2c436535d1c145a8e5b05f52d2b260beb9e8f3139b2bfb8783eadeef9a5e48e4c9effc3a1c6204e329f8c3a3e67d1f8981e4b9140197e4a372be819ace7f4932d6cd81674d19ecbf3755e0124dc968ab3bb30d616e933b33c87942a3a725e5edf481475b7fd069a479bc1e3dfb583317f0dd3ffa73d96bea4d6155f7eebff2bb9fadbcb1fc0e7afa9e5f140286c41159a700b4fb948f011d6b0dcf00b6b5f3daa8424f85b3326c84ee8e61053ee95e0fa680deb3e24c1114f66977440d490a17118a11896ad0b5445b7bb1efb99047fa688f107efe469124cd8a58a14d96458a460c222d2eab5432bb1bc2c2bcc4a6c055322c997eb0aecf0f53189484c1289fef8b43904ae2cb5704737fff84955626c4615c4799ccc05fff761414b24abb442fe13eb1f047350e9744e41439b587db6323f57105053e92f5f3cce973950418c4b00e33ae7177e8144d143367a322a06dd395540a31a7f944279bb44e0eb4741df2ae36d93584e954090e8ec4b16e07cce434473cc5476c9fd2a9bfcd5566b46a6e2413e12a9f0b4cd2e1aa61a2ac19b8d6381f2811f998b0663f633b66f5ac883d784aba823587536769f7fbbb141d03871ddd7ca37e99760ed245be2cff85a5b602c4acf1504d17ada740da15107d4a5369ea15692aedf396704acb3148991d76c45629d9ed989f336efbd03ed361280249545f336433583f43552ff3b38f4e2a6743f05dc68e682531a13ad86985741b7e632edc489fa82bc0dbeef4e10cf5c98313c9266ac71c2127420d8911234421eb4b880502a6338fefad8df202e47e8b4b0258ecdb0975a1cf9c9b065b31384012bc7d75f7fa349408b28591b20b8e3c5cd0add60382a12aef7b5fcf90e1d6612eead2ba8b9271861be3e4dd16f956c036819dbcea46d462e11bad826effc220ef225a52b7cca4c2603886376b63c60406379460c11fbf49b6c56194b0407bf2d11dc65f4c8a7d60bf9f287aba75121c70832095b9eb01cb5ea9a687590185ed6b7c4d8a99656be5f7068428f92618f1488c11911489f1e976b3c96847885d082069b10231ff97d84d31c47ce85a87161bf2b12b4784ddce297ffda65f3e2b6d034488c484e9796bd201cc4da309dec1301916c6cd953f9f232f37bfc58a5b4a4ea0b6c6dec596923e820c7760f69df724c89fa09e40c7d3ed3950035d591ea8116154533ce0db7aef25317f2baa539ec377fbb7555d59bf71b569569b1b581bec7da442c5e0b4d629f9fce0478bdc40237d457c36663d9d9c3a6f60d9b80c0b7fed3a6464c03376fe36d3946e811faa1eefaea5f4e287ddca5f07b9dee2b049772e00611207630f2aceb63472289538d6bc268f54cc1d1d6a927472902f601050bc489096d13b964f224e18ec600f5412496c6344e60427ad5ab343a7a2bdc8191ea6c2adca3ed6d432b0d0d638448ee794d05cd2c9d91a2541759275a9d988268b229a3c0bc48cd4750b245b16d000c8cb9c877b73c79c91da26e7920b16b8e0dd0b43a58e1605ec4a64b28d9c410912417044bf3b6c3c90ad7f076b0acf56c313310ba08d456358110d4b7f305192e44182d93ba68e4229adddf3149f823682913830c155e08e011340f9231c02f54a5bfe2028d493c8239227521d94e28dc57345dcd096fc1fdf68b982017fa4b188c6c4e637252bb74d79280a1b97d947c06c0fea239bdbe41c85c84a612e1862747a5ece48e707c16688ffdf660c90edcd336d6b1e57636e4a14631056404da0b6904e117aa1256dbce2ea6375f244d5e77b0fb589334dc8b8356b4cfe4ec707bf36cc03e3370ddb333d14a66cac34ecd1e8e49697467077c28f60aa9022a8758428c1f4006c86e7dff622c40e3ba53e9c7c2efa8da74a2c7ced1bc6e85857107c3544ecbd4c55c9e57c3241f81236a059d7c3eef737788ab116567398af47211050b4b04e40646dbd3099824f309faff2ff095c4c4d5af00a617599cc7fc1e21fc856785dfab9162feb535e06393810c2cbf3e4faeb2db481f09bc54bf5bb392c8ba0988e4e377ca3642141ec4fed997eca94d0448c599595626abed054b9d3c5c65b6ae6ebf47ee7f7c7f1eabeb3004ddd318aef21114f46c6d02d3f98145cb42d1b78a5320285c0edf62cae572775d050ddfbfa4bbac92e1ae7fae53eb6802f813cff50c0435d0b7d25a0d9d3438574a564334589c5a523ff524a670e6aa70ea8e6aa9ed94e1f72e1977d4223b3f329526fceccd942998b575930a2ec9aea4eb5fb63984d964067cf236a458e6ea952ab547978bbc8f8012deef6640c035c8647d8c6c0062bdd840d3b99cb85267989c06da7065957a9fbd55ed8cddc88087a739c7d255add77fc023cf8faa44b9543dfd3d08bc1494d947e4e300dcd0501b3f552d85963c83879ada345c86bd7b3ef339446b9c255541014ab38d2cd0d7254a380cb2506fc31fe8d39b30b69c036debfe1a18c46b70978423bdc415536d0446679c470f40c6455eea049e3075d478c3483e71c2620f8131e2325e41fa6b2f8d44178e1702be22d9072c1b31a10b0c011dd8a56df9ce197027d705a11d4226d9c571c031fde8929b470b8090d1175337ed9d080a27db53d2a343d52dee0e50cc6fd7327245672280733938b11338bc531f02b1619a487a71a31ba0590449e6b000d8deb1749ad7246e953b978faf04ebb96582fd20c7e42734c8b2d121c4118d0aaf4d0222aa1e1a2b3f8d18d87862147f0b8332b6e034dceb66eb6817ab5ebfd5ee2335c30aadc0ca2eabf03678841d0cdea6901ca6d66ef44dfb24c82423c0cf769322c2145a554fda619ed6bc8203f90e9540897fc6905407d05f5a589a3bf0a848802b4a9cddc96ad1afc2d5f039c501b0ea64b25117db8926a03156640b1557a57daa2cdd2c26bd456b1c33b0e99319cd7aeb535a5f5ccd9a43ac6a31ea20dcc90f140ad5375fca4cc39ed0d6ef12d894140d99f6380ef01e2f237adabe544136cb244b8b2d1364f41ef61798cc3eb870b1311f1db966684f8c5315ed4e78169e6d8a28132d373f97b622a170b8a76df533eaeb5fb87730315fd008905e57e0d58b1c3e21f19967d45fd7925919688e910de589d50797a35a96773bb8f479b931d49f41b21cea9ed02508fe000c51b836676e2200bbc34d388cb43000916da90c81a429d56a0a8169272cc357b3932dd4d559b034c33dd6a7deea205ab33e3b238a16cd115e8995b7b366bd7c166c8e5089edc0acb58cecd728406778686781639c805defc796f2c12f9dd08650b0db7beea371888b973509fba2ebc93dc79f1c138d09503352c56efffca3d9a95ad4b9931963a26dd5e29f72840e3539501243fdf4cefc2823483ced29f6ffecb49a9f9cf8741bb94fde083be04beb47555112274bfda5286e68b85ad58a21cad2d853f77e455cf5de7c16b2ab0d053c9de6625629dfdcccc4b2023b47caf694d1ed9f72a98cf8276d3e0b0898f47ecfe0be02583b8e5dce3867980f7511dfb84ae2b0876b110e976e281e7e56491c78b8fde8b9f8db2a5f0c73d734d50285accc85c8995c9782e1abb59616958e56f252340ce06276b1a265baa142219fc6085ce4e7cc086d219223e079e0e252141e5eac150598cb922a82d8577d4a38c84af92f19adf1e8ccf6b24a542fdda876264fab8b55b92756dd28c91482dd6f550eeaabedb190d37a54fa20107eb737ae9421a3da2cfb092823e03a1171639a6b59368a6a6a2223d74adc88712913ad1fe81d97884ee2449f0dd88b439c33b4cf1517b8c655dead9a95bc178fdaa59c6d745a98b8231977e33bb67b63dc131ded58aa28e4f67c82f1671c638b752c6f8cab24abe77cb024404e0985ce79d10670a15954d8378b7c8ed2259a12bd95616bcb934ec89b888f2e263021917a8ade37d821888de90e28b79511e311367fcae90a0d4b6a24b3a1583205f9057dafa41450726a7ca9234ed28b126a525fc832f1bd5768c99a6691cb563e6cba23c49fb37f77b874c71fd8b9fc5c27dda1d1c9eba4afcf51e896d011ff912ad7c5bda483dfd5f9e49b0e7fa001290db205ce1bfda0e2ace96fd63e3fbf06526b40a8311400c7ce3bbc1d35bee3cf732ef583827304c6cea20e4247ed4c76bc3b6747ab68a1b7028ff4bc567d0396fcc90cf8a1cfe3abae13f49e41fbdfc099e651e8bc1d9421f488d4e68e16c101c71dc7ebe7fd7f107ddec0d179f4a819b43f4af876fb4775fd27d81c20d1262020740778395f21bd33fd8e3fca19ee0fdacf3d503b5674ec2f4b07903be3ffd999a27de0b58ed0f633cc5be850bf23c4d69910bc77b4b0c83a1b6f4d0f7d65065da37d82656d5f6fd37652bddf9937d8db7b86d70795e70b101d4e9d75a7f41d7fac33c43fe83eaf7076e474d67707089c33fb76758264e7e1fdeff27cfd860e7cc7dd415c9f0c15abd37b431262d87ac4445d76f58250a6f3ee2c3b0d1d7b87ae238ff620eddc74141d303ae2e9fc66ce7b8310f7fc2af0289ce130e8283b9ee800aacedf2f6b1dc3ad925935f20e1e949367e26d0e2fa8b382f388728e3a875e5940e5759d12491d282efb6774b49db07602e9b3df9f7ae7b77adee283f0e70a823a359d699d97ceb38eb253da4ea07d5618fc3e9dad9fac0e20e1d9fde20ebeb377b6da09043a6b1bfc09cfd15f40939f660790e0ac3dfc6e492648da327d4279921922f7b6fd41a7a7d35864b9044bc3400e190854be5a506b2721ecfc8841b0243ac2530663a2290491f6ee033a1ddfb9c7fb0c002c757cd3738081b6e13c9305bf3be7523e487a2e00adc3cb4e20fd4c0f089dbaa3a763ef00bdb46832c3434673efea07bb110424c09ef5f74827a83aff41ec784a122826272f70e641b0853b54d765c2e13987d0482c48073a72b18e7b2433883008c8daa020244fb460abfd3a7482bae73c9f41cd597b01a15c11acf05d23ae3c5d676488cc418825328c89bad0dbbe93dc73d63c384918ca0fcef90619c5b191075d90672380efe4fcf80f72cf0f7d40f2ac0804ea9e554861073ff4b3f9a09ff25c804427171ddfed5cfb699db763cdceefe5ecc407e59e1718eba875e69dcfced9597742db11bacf31fed6f12b74acdf6f4e14372e43dd88bf4de777fcfc0ae44238430c7ccfb3ba3fc89ec1f901d167bda1c7ce79d40f92cf4548d3a93b1b3a161d7a1d9176023de7cd5778e7f7757ed80759e70a6e3a3374ff473a9dd3f97d9f035fe86821b6c12addb3ae1f249f8b41d01d0ca867b83e483f3fffb9e0a40ce7e312df27009ab2245268503a8530c3eece72878d64fa19b7a78881c80221497904d28264356eeff9cc4e4c9d707684d69f1954af03087cd6168e0c9f07fa8a66e164439a3040edf7a80e25eee2baa34e37bdc2b33be20e4365d67bdf0702e18b7369a09fe01c01a5a3521d61ccb34082224591d0d9041162e0d6fcdb23fc76ce0b3fe95074ac42030a7fe1842dce0540a031feea4c75e0744e9def7400a967bd8210f25cca07149ca397974e9073c6a03ab490d8a18f190ef6bc6e4d93a59c0fdaea2f96842c47fdf14240ea3ea33258ea1a26958118d336eb56e221c903842740d2650e8abca351fd3e88daa56277e6e9fdd9656a85f4446948aa65f71546cea5f7a754004f64c45a37066b8a929d19997bd2294386507b8cb17386024358b942d0b20794e9a573200853957c575a6c3e130d3048479e2cd5db7221322643cd4d3aecece746dc2f7cac1634482c87f6b770e120f26626a9c67438039337c3a7b64e6ac1008e9dc240a20c6d237a2ec139108428f99be1ef5e1c074c6294658ab39cd788a959a3eec6b71702d8fe46c781ac364ddd6a5e092df7db83c33a966765dc6d05e53c00b3804c5f2c472c8159ae4e1ab49d2b0dc52d65c9333cb94e736913e1723c8732a45f82412dd25f882399d38471488e45d9b681cdad5811cf8402e072455659a9ffe94e92aca773531d080458e85c0739419ce1e129f8062a04611677156c3097ccb5d6912dfe2df35e6a41bdb2cbd1d182d8aa609d53a9ccd3224573b9812a8463096a41d6b2209075bd589a83ee78d4ae12ab4295fb8d36fd2379a7b68ab90c85026ad475615f40125a4d07926d422dcf43dc484799044a99eb108cb557339bedbfb77c5f1495777c9ddc827c7e57b762a0b9629d226154affb5f0b109143ed1bfbb991453a6b13166172e09f95017c18940f7b09f1f1dd2410635b6fb2f7965b4a999294017906b205f005b3c57dff4ac42ace6543487e70c48dd37fda59a64fa03ca11fdcbe1f53732e9d90fb80cfb2e5a6cbd2177b84fb49eb943c5b9f65563f2dac648d252cbfcc305bfdc2d32d95e8d5306bfa57a20764d6f4bfcc306fbc1f2f3c7de395ddaac17bc17475dfefd1305ddef77b42bc193c1778413c1e0fc87485df6f4b9781e271af05d375bfdf9361ba76bc1f9e0f2f06af9cae94a50a883d09a4578e108b4102eb499527eb05b0c61d3b7a3c09acef11830499577dff67afcbcb4fb0460a21a05bf2e9531001ce29808f42f1e04c47776fe74ef553a2b54d9bfe18d13a316dfa61446be545b438b046a27d62da40316dfa43d146316dfa51a23d9a36fd27d1e660daf483a2d5c1b4e93789f68a6891442b859d62daf463d152316d6e9d807e19714e03902a96382902c8989c57a28d62d6f4ab444bc5acb1544c1973da236beb8904b59cf8225b9bcbf0ca59d38f711896b756cec6cd53cc4d7a25379e68d3a6df250b49144fee27bd32f7bb2075bb1c39914c49148f109d9d971d3a4b997449ca1d94c91088e47e140f4a084a06828b47724c7b507ca81a230409eb6c4629a5943a80cb608dee6e2fbd74f7a6d5f05a6b58cbdd5a0d8c7344e7f98b4421d7ef7e9af322d7b1ce725ee41efffa94b9fee7d222ecf7af3e763dd3e55fab8f9527ec6a61b15cbd12e8ebff5a9c2c56d7f9b77f8f78dae018119235d38fb9912958a3e789cc19c370da4c98eeafef0ddaa8a3e8a3d8e0cb053ff73c3c1a09e0e7fe04cc7923ee46ece02bb441473a6de8376a867d9d4cc027e071c638e305bee8cfe7401b74ac1cf8fa66e6c09c98ee18313a10e7879082af2ebb47b137db3bd59f21a05bae1d4340c911e449b7640e07dfbf6c587f4e5c7fceeab59ec2473d8fd383e1a3fe84704485e0eb7573fdd95b5edd7b94524a298540aac6e6777777bf38f79e4ce7bbbb7b055f377f4747b5beaca5f3adb5177cd53bffde9773dc880325ec5e6d451c281df8f2dcef7f238d0d143e94e93f93fd4e245b2ae4bcc8f7735e643bbe788147b216b9588bf2b537d7166f5e41bdf1b5a9fc4ce0c2908226dcb7143ce18e78c45eb325a3684a98b9ff35738f377283fdf8d49f5b859797fd5f5ea65bf2045f9e978574d944284fa2263da63c899a20a9b489904ce22665a6df0496c98a6d9e443e5964fa552953a40fe7a7a788e24c1f8300867012f90c65d234897c84f224f2e9c97912f9f4e0a383099f0f916906ce5f4f509e443d434846540a37d4404bdc07223e08a93ee8f8c0033359cae2c3e9e123825a9762887b5bc81105d1101f687003951800c04654048825183081e2e3e1e4e21d5dc589206850bea0038a26464cd4a00517105144468bf97608717689129808b710dce55ae829305ee8b06006430d6234281949a2c6440983d1133a9f0e274b863c7cb4849639672205ea87104278bde252b8dcaee5f15305cc081341722c2922cb941d90d072832c98c04ece63081a440d40923c3184092c7c14e1e10644c800851652787c399e7078079c96d5d5c103804852c321c9952458c04316a01854d95102067e382ad6800c8ac00289500b2f284183081a4cf103050c33f47cb0192a4a5b7676c8420a904f8a2080b40c5142871477cb9576242b8e540413235c860072b96108cbc140831c749e8002ab02841018600287233b5c208203ec861abe2894071be76d41b10d6a98b28323db0f0e2ad3ca0b3e9e60a108901e598aa0b49881039621927414c103061304dd7c724cf9b192c41215ea992bb42d5908e19061082ba440f1e343d4630b26444c5547ff205ba285161da8e4a872031ab60022881938a1e50a2bac1b2d092242104df450c40a123510c1f2444626035a1354ccc0a78622ec65318412290a40b92c4294a80ac124c827c4954173188f18cb124c9a4009295172a4db00196650030f233dbc3034e489a1248a08a2b16024968ba076100016e8200a0d663a58986201263d9a00b282051c5070705a62b4c7951fa2c0c109901e769853b4f8d163871638b48045c90f272527c1852156627812a588942119ac006d61238276039399c9631863f18c68f9388ee3eac5583a9e2e82cb6227125a9e10d9e2881990da11b12a925002cb9392b653b10061052b907e0c69c202202670840db12850344113fafc8710f8864e922a4410d14356e589d913259ad0804410131e9ef030832b2e3044942b43362458c4b058f2821c10d1928389e6a1e7264d31a9382a12c48f155ba62c01a40543418250b223040f5180b4852b4f601886a03532eca0c20a2778a04287034531620643961e587af001009e154290013d2ee3ab5d26b787bbe42ab93cdc2477365d31b5af277567a9275599bcbd8054edabd5a7d12e731bfc061fe244bc881b711ca64d7b0e0e03d7c19170a2c7e08a2e03df61daf4a7c41e314870594e009755a2e390127d87eb3bb8cc26754dffd28e5067e70ac94d4448957db4371c1b849f0da6310c60a5e0eb4a80c532993c26e685c11ad6592b6732e11875e00841c2faf5d5ddea6647bb93bdb63ecdd52bd0e74fa290bb863325bc94c4392b7577734a4742eeeecd7324546bad61ad25294fbe9733791321e7224e1321f724ae39f471a6f46b8d118284f431f80273a64db754c849e5a472fd222a924d6547a624c618635ccb51cd69e3017d384f501ae31e76cb446977b7cbf6c78b6362ac0d438c6bb52cd6051f70efb54fe9c781ce8125cc8c82df97fd8b824007be68ee7047bb7baf8d2e05d90a8d3f0af4e7fb78697bb5f7f230fd77c209347d1cc7711c0df728dc1182843477c4cf514a2905f37d21a1ee7677f74a6badb687f6587b692c76397216155109fd6d2b53f7fbdde87df734da411bde3853f97e4e2a95cad78aadc471dc0aea8dae4d40aa6e2d7d5223b5d1fc96e2b0e9aa59fb2ea6f27ff691ac41dbabbd1ceebccf049e50a1cb0b4c4c4ab562c9cc9035ec48336da875316de80b0fa6cd0776084b09a95823a4dc4fb64810fad6ada46e298d16878a90b4b79b854d1b0ab3b7dcde8dcb41b7d4244949132632c9aab50854e02746afd769113e110a097d94743431228a1a8ddbad40e38522547050840e11235b163e3610e18328098b92167c2b648ee38a601ba6c534d70a2a24f1602b1242168bc988d56008922542372deec2f7f598516446114ca3518296104bc8e549e44344888f4f8e4c3b30e4424f10772fb6d59b46a3841e2bde86837027ec396aa22f519221a2d914578f194d84383d426e68061421396b33b00849164e0b218bab618cf10760b0a6e78ad13c897a74324d9e443d39f408b13b7352da187745bd6cd43afb065ba97b5ec517d9eb38aec39c576b8739cc5955d7ec89de10a5b74ebfe1b3ecf3fe75b5105e7f3bd6b16bdda28e95a86e373a79be6561def4b4319f3cbff64c5be70db5386cadd36271b8f82277e2e926e4324e4a5ed38f8ad5c8d3cd5a8b390b6343a7e548264f4aa79bd7348c0ce614d4b4a5a42424242312e646c2dc4c9984b9e57e981b4c128c52df58ff691d366d54d93d366da837d435ed09754ba85bde50b7ba366dfa4fb7dcfd2858df90b696fb9674523a2dd9da74d5d72afbd835d5ed1a7d3842b4e83fcb384fd06799467707beef04f4b1481d05f8fd3a1eebccc513d287c56a122fca7646a7f8686cccb7ff9afe1f8ad26e378da66ed5da737430a74e6f5a6bb7288d7dff1bf963b9779d6d6badb58db18d971549f041b6ef9dd375d20ec117aee0abbeade2b4b1e0ebd24880fbfb3cba118fd86b2ef8b2373207beea9cb8f33cefeb3acf046e9c31c36b3acf7e2cd6770277ada9ebac7defb3b556dbd58eb8035f3de7e781fd2670d4148626d004eeeffb09dc75da2058c2ccf6bd561bf6c11ccf53c1cbd5cb76f44cfeba913fd064c2604e074e0c7a273b8215d41bb5515abe0fe5600ed78f430bb9fefe9e2b61e62e04748bf7642d9a73ce39bb1e4a29a57d94fbbbbb9b1331cf91bb574ea8d66a95ec25ef910b8e9c882314e2efc00670d9f41f3ed96faf28f70b6f24bd586ed216e51ec9a25cc713d4f207ec0c7fb433e2038a5156508aba514a53312bec2c53d495d96ad451b7fafd5522eb57a28ceda9e5c64a666bc6aa4fe78d3d6267b9569791b0d61aeaa86fec91465d79127f1464bdea79c8fc6a842028d03eca84199f5953d3e06bc667b6fa532ccc97979f13ccb9f98a37af54aa5ffd09aa5ffdfdd5988218dc51e6579f02d68c0744f87dea29f8bad9ff657cd3cff4ccd05c86ccf7cf27fd5d3e25a662a9d265acbe4f3acc8cfa396f2ceaa7cb50a5626478cb0d23439f95c365b74a5e46b266da373d2394fb6b0a944cc55a994cc5f28ccf4c6dc696fb3daf4672b3ccf164abc3bc99b3696ddbf6770c28383e6250e549f4039597e96f71cc9b599fd6d92c6a1db3e50deb963f5d3a922443e231a2df525a46c7ecd3fb747c91ed0f5b5a9b8d756bded8d2da74cc1bce85d9f276aef41a7f8cc390c5f27fae63d8c6fac6e2982d177664fa8e63b668f9f647d98eb1fbdbc0d2bd7419268f2b3dae2c3dae2c3d7f972c747159fa24165268d4a8f255f15b9bcb7031ea1a7f2ad8284462257dcb51dc1d5d6cdd720f5566af494eb4e9e2de3d160363a8ef6f327a7fb09c2e12dcc9bef4492ca4d0a8f115bbd6521c078e15619d4d9707d45fc216666481c3c29359042af04313225a2c8ba0737fadec4a12b6b2d77ba2a38f61166d4ec156ea9303b94d9824f40b3838b6d09e944f703c9145c1d172b560d25d0b9e4d1b142e8ffeafbdbaadf55a6befbdf75e1192dd57dc6e34da1521e8006e621a1b6d977cb55a4ccb64302f349770da6c289c242a050bebc2c6dcbe96e535d439b046b517b3c20fdf4d17db6bed75569e79526b4f9c8bb56bfa5d65d87ebaa40af21dc3cf3aedea74d569d38139b46210e7d05c614cb56f6a9e38871d24659295058b0c6e394ca18434850eb61c0d093b4f22275038b1b2a3cb93c80916486005e89821c70d499438c243451622b454119bb2240553e97c8b12239c2cc91ee449e424c80910b2465bd637a7555ada69a3b171237fd7d513ba7a4213155d3de1a4e37c8bf44d18e4a5b4ab575b6db7d76a6d554a22eb9212aed5d6cbd9da9155286848a813c92aa5e6711cae9d672b4fdde956935548e5f9becf04f69c4c0de604d18e8c908e926ea1c965874eee7f89c190bee3e567a2a403f5e4d0ec555badf734da6d5d6ff781a89718950c8d18e3525b6d8484a49700c5088a3194e7b78c26b58c0b2cd97a47ebd87aa785dcfaa60b6a19b42c874a292595d28822e5f99446a34268940812da920d60a43089b5b423d3f2027d739fca4b610d853308846e99c790d135afe9af34994c269369b29e7a9d7d2e21ea04fad7a56841341a8d1653ee946559c2dc97d96cc96c369b59186c070c068381207a7081699bb669a3952693c96432c5a8c5c4f8dcd6a14ea07f311df60f86164473da47a3bd943ba5975f599abcd96cc96c369bcd6c0400c345984ccbb22c4bdaf77ddff75d80c42cd3b4751875024dee82b92ea405d168b48ef695e54e599665e93637729bdbdce636b711c034809a4b69341a8dd6755dd775655896256e1a079afc43711777345a108d46a3d1ca72a72ccbb22c808d4ba6b71bc618635c6badb5e28f46e36e1734f9d79d2ef6aa47a305d168341a2d86a900269c2942ced432996cacb5d65af38dde2e95795666655666c15a6f35e9abb7aede70bd71f576ebcd0026031ce0000808c1840030278404dc24e0e6c69bdecca7798e5d6bfdb3586158233126db23d2dd489a4c782463625cb8800102085d7319964a91910d29694909cc76b4351f42f2c26a300ce61a07623833273a5800948593156c2e001d013d01248513201d80860029612baf1c61a40a103f7cb25421b28203c90e33004559800c44704005902355645562e03132d402161bb86009084a04682d48f8e9b0330488098e0ed00e0e0c403a4042706af8a1fdf8fcf0f083e4c7c88f0d3f3c3f527eaaf8313a32297ee5cc1b4da9109892e55dc3311cc3b18e61201c73192095d28807499674045cca7ddad1f3e960a00face1d8c05ff5c20e56f98adf8e0fc624244f1f2cf79f76fa26d63754a7ec1b3ad66ee1578529ad111f8d0d7ffb2f77af31316d9a31dd634869e8a3306f70360c31ee582cafc13726c664b2ee6168eba3605fa08dfe9cf9feafe91c9883c1ea15f9e6bd1cf77ddcc77d5ceb82353e9c1b8424ceaacc44f88da4cf32f71c48d33d0af8bfefb08dfbbc37cd39e79c4a99a39452da42dddded962773efee5e8f32c77dadd5f6587b39ee1b71ac7c228e951338d2d8c0197c9cc191542183a7c7f934922aa0fef40eda40dda2ccfd89fbc856ba4732e745991bc9fb954c412d7fc067eedf8f9751a98b494886dda2e324bf0983fc6c4a7da3ca534995faa566ed087576582e8445647e3d5ed3f88bf209752b25de1fae0fb3a6ff8b326fae92d9ea3bebd60fd3f5e43ab940f7e736b93eb7e7faf005f48adcdf39a599a0e4fe10e35a6bed3e2cb91ff50dc9fdd493e2c96842b522db114c2693c964324fe6c93c9927f3643299a8cb819574107ea765ed8872ff89fb463ce227bb1cb95fa6c3235692318c9654468fcc7a60aa9aaaa6aaa96aaa9aaa06c3300cc3300cfb804b92fb5af991fb29875979dab824b7d65a2b375e2b370683c160b0d99dddd99ddd55cf6ac90a68d5b39aad8256b4d52a3bf1a45bb92e6c2e6c2e63babb7017eec25dd85cd872d7d13a315bcd7c06a68542acda17ad66eedf0726550a34dbd14529029090b4b072babb85b985b985792abf2881120c06b4178ee0243152865284378447c25b484b82029467f22482920494a13aa3b6f6d29b566f96ca44a02124674d041a44a021cb47deb079d9b41b95a15c800d88794133d327d2041eccc8b0fc449ee003d64a95aa2712059f8a817971b1273205a24b883a81a67b22553072277205f903c0884ff49d501a5bcfb84c65ddecaa6360d9679efe8cc074b19e3e954dd7eae9d3db74a99e7ed3a62bf5f4bd9cae7efa6ec34fbdcf04be5841852e9c28f31feb93adb28c917c45f6bfe1152e4c4fba04657f97201af0c9971fd93ff563e6f4e48b95ecaf7ab12283fa154c1256f8e427cb2eff7598e671a699e1b0a8ca32224b8cc0b4a1bf12a96cdad05789f4d6342fa7cd7cf92a7ab569e3301e6cdab866e83ee667625e441791a49388a436645a4543f118bceedad63e596dba30fe640eb03132d4b3599897e0ed9ac46da5f764d36ea6b73335a70d25674d4669a4979c3be1b669435dd0883332b26b6a9125ae44957db226a1c1f98e16e6e16061d34583b305dfd2b1cea64d43a0fee8ce3d69719c66d3c66135142c4848c6d43c58f68fa94d17f8fe1f28da1428be744fcedc6664d3c653321790909cb9a564d9ff03d9745924ac586731b099543689337f286fe696fd3b919cb121fbc7881e2ce5373e5a63df84f1b9704a63f39e7197f1cabab95de5116e08abf76cba54798e9c85e5394be55967350c834c63060dd519e58e64fa3466c00021841166908d27bc508ce4989e35173040086184dca50321d2b4da821b6e56061995dd1d28659e5074326d89a694e9879896942907c4e7dae1388ee3b898cc72d1555b6db5b533e1119b8884336323524f73cc48dec831eff2a42311410e99ba7841ba0eeb3d84bc0221d318230018404325fe18c3650060f41e1fc7e935420c98371e65b6ba040f5e8c242bbb18c9a719c99628fa12b3a6ff45af326bfabd47a86fbce651e68dd760b6fa5389377b0de68deafb7d8979c3c4bc513dcd7f18ac41c3d1d8fc357bcda917a944cf5e53899dbdd6bec49451650173268074c9f4e7440099ca7484390d40ae32fd17ee44f32a71662e8b4f33ce69937a99d4cbfcea3f0bd658a56e6a9592f98f9a4a984253680a4da16e257aad5bfd33a24be956d195f90855ef7d4c0bc98830d9e5c3f432e24b76f9005f4674e99111431acbf4512f23a2b2cb4748ce2219f1945d3ec2d4935e5b3dceab915421af5e04334b1c53313022e946a44391fb5d447266a99175068aa42d2dcddec82bab5d221f70ea3e6b40efb0c487071df6f8e60cda4d296d1a826fcec0f83b91b433941d22a3f4b169b4474e47ca1e3b64ded89fd9ea7f7ba4a7dffecc9b391f14a78fa4fdeb8d73da74f66d27dec7a2bfb53f414ba9a5d60554ca2d031568952dec816fc22057b014f5fefbba2321cd9e572937697697aeeb52a48b08b110043eb3ae2a216969a4cf704fdfa8c4fb3b54919b1c4fb26913149230355986a9e19e6ef98c96fb245bc16c163454cd3ffc170fc6f33ccff33c2421cde1f74ff0157e3d7da3c38c642bbf4c1aed329ac6cf1bb323f19efa8e4e2fb5d2580305d21c87e048b23e7ba38fd48ea49dad72f74ec3380c59acff16e934a56eec8e70aa84a4776fd3657338fb34dc937548a817ea21b5fb0c09c24994044c042e18b87270e950de2056056683157c24551c1400b2e50710cd05447240e1c1e10a154a8c96f0174e58a600fde063840f1f275b6049c2a30821555ed09f909d2237cce0882c3d3f24cc9f1dc02132638bfa03964cc6b8efd4c504c602ee57f70ad6e86e6b0397dea8e4ad9506350a9532010000a00003160000281810898442a124c8b3244fdd0714800a6e824e644e3a92c782b12c478118c3310c87100000310010438c310659552b081e3502e61e98f8688a58863c2983f088bcb7c28124f4c45ed41a8fd9dbc25478644e18d60859ac28139cb6e672293e5a7a4021f5546cb85aaeed57a3ef4fceabd58f55c4124e8fcd13b6b0ce40f77eeb5821787638f9a1d7b24df8a62b4fe5220c72a6cdf8934076fdcc656ce070103a2a659401d472f31afc94866db417d773f464d7760b882579f98473809d9a0346495f63984d1f4c83dbc171dc5f7c7eda58cd898b7f03f8e5113ddd900171bc6c2a58ff497bafc72564aa00f16e2eb881a442d49fae200a2d3c1620797e308f5f32489920a2476e05d15aa83f2817e586a1de9f153a46a5e462a04cdf74a68053b4e90bb48bbe0157bb2220c1b452d2840f86af649eebb2148e6173ca6ea0da7ffd26bf8957d1691cb88a08ca7c8e99725a75481a802b337c558044307215211b2f0be6ded7fa4c2e1e0cb8e6158169d1330845ef16b9d70557a9dbc185aa1acb85dca354d72d648b3a7510ae151b7a5fb247c66e62d513c4a3f97779c607b75da857367aa3cf573e84709955743fc77b05878e6de47190d3ed2ff204228de8ce51a75393373474fcf038de872279d4806498ff33d032c0e3e47e6ec5b2025b79209638623c9fe4cbef595a1a613eaf5fc1ea036af5e7d9962c3102ca1d1b4ecf45e75996958746d1e2611f772ba63046eff9393a19eabaaf4a265dee5a2819ad70e8ffec65d74593f3145cd41918d2529e4dbb261a157051386289a95b9202fe68cef45791dbfd78d6968005fa968e0d51bedffbc2416ff4fe739c01475d3ba359c32c065a0cb7a83356906f7d4b4817ac73bd6591a2e12f432dbd8a4362766771a83bc80e323555dd03b7b8bc20897e0acb164af3b23d4b7782b775a2bcc45723c22df40a3c64d61ee27dd24cc992325825f2f19d8927a061cb34bf44914166c9d2e52a95d45a3b333dd9608933832c3bd4406066dabb656cd1102f6d71dad651bc003669180945ff75e0bb1a65fe93426c2ad675fe3eccf93a2a32439e195d129c9e61db5ee7994709726799e05be491b1e79c0af17e3ba2bfa652938639faed79f7744bd2b8bf7f3f22ccefbf35f1719fdc49954fca9e66ea9f41c245993bb8fd7f1f6f80a0929fd76e92dc7f812619d2941ac065e847db9a329d007444a9fe0d42864ded0332c5ea6709e7582b85f97478922032219544f2b543a21af4a3566f5613ef2f7d1c28a2f5da03b0cab00248355b85688fc223b07bf5801449a19678e3e0e93e06531e37f6b64b4963f12d5a79b1a420ca8a102d4b8388e3a1c825bb43e03f97154ad4e705e29052074f5a139f677aa9f0991f8bd77e309c0d1338cabe582549a6a898d391dbf0267a083650cc40399762ef653f210c45f3cffd7be7c44656aba975e878b6b2471820bf1cf4faaceb2595d30735da39bd9d079398149eaeb9016516e4e5df5eadc73df35ab3668614e5770aa3595dec2d2b968fda6d7edb0bb7d9c160fd429d91940f80daade70045d03eaaf6e63e4671219c7ab76f86e2123433457a8fe8c41a928686cdb46b5c34bd989d18cbb7fcce83994c93009ff6381261b234093ad060816cc3f991aae0cf5796021bb4a08bdac4a14348df3cf574f5e1f637ef93586f1abe28d51d1f6ceca3a4e893fb05245767eb006c96a25cd42efe5f60037c568529d6e6881339c1f09242aa380b7463a187af986cc0e710060145c1269c0178d68a6c631dcfdd88d18760e88390b1eec3a011182d9a0d9a2c641c5bf9085373c96aafedf16a4ce31b14b1d880be7ac9c1a2007cbcf0c53cfa88cbe5121b4ec02507ec03b9c349e7491b0ffe154fea28b8d0bfd90abd04bd452498962d47016bccf66085d514e61ba596011cbd6bfa14a32dbf960a4fb5cfc25a5d18048a1a9c6296612d9483dd399d8a12d8e889d80f3918fda6a4285651cc9d44f9973ab9ebc17700db9cbeb0509f256bbae9533996681f21b17c0b53f6f3d032b4f8ec91e219d4076b00a492637e02dccfd2e6115ab8822313bbbc1ffc0f027da2aeab42b11c7a2c2ff9a1b3efa09046da4218fbc54a519f9e542e46263454a777855ea3f6e09071f27086986e3c605371d3ece83ed67072509d96ad8f39466684d4ff0cfba2c29c8ce333c749ee424a20061ca18d8a63ef6e33263344e58dbbff0ebde57831e5f346f4a73d73893dc02109dcb3a765aff460655c88694a9158233a5a65b231ce46698d5412e1d5a99f0890bd74500fbcd06d1e99b502bd6edc14717b6907ec15520c9d2daf929c80d926e45735b9e83319ddff22cc220ebf70963d32402e587ba00c83cc70c03453ee06282e26cd4b5095ec3046b08a4e96259a857d9ae90f8e074bc60bef335ab43c177a12281dfdd151016a93b1660c55cb39bad07cce8affbbf3ee151662219d03e1fd983070871668007d9daaade9263130520a601fea65b306401c02f6f1802259b168c955c842f178bbd194926a73848e10b53cc3812856ec79cdc13529926c1a104ec9984d00f2e0c6c20272c880c86e0fc7d790b6778dafcf57e82143c2f423dc48cc0fe8fd4d4e5ace262d366c4bd79ef308a11cf50afbeb50338dd0f13d33e8524e15da75c03dde7902feaf405e240dd859a9e60ade4c0951c86d39d1693203467a1a9f494a34636b091f6e23cdbd8fad841565a57f34c09302eb4b62f5a5e48ef5e298ed23982e1f023ad47517af95cd26ad19e8b66c1e792e9df53d6ea79381c58ac1e872d563a11e68cf07a538b0bb28a73251c99e0ab18840274b977eb82e935c2a97edc076ac2e60720eb06047edc0ccbcf78bb8c386761bd0e12febd57631f6b3911c2ff6ae673b6b5b5b6430bf765ab7db82755ae8bb38d72809a586acbc2019351ec6d7916d249d0d26525fa4d44e145801dc9017d4c92a2611be3e5f002e5f9ee8ccef1b2bfacd377908fb434b194214ba5e4f51bf97c9cbd4829f393011c4bc0ff36339fbe488cc9c3ab4a014b404d7da245762af4257b80b4be92e09bd066060c9a8b07eb99fd930b45d07e0d57030ca41139cce9e6a65b4b94ae135b005021a1339943ea4e18eb0a63e3517004860d92493c4207959d446959887a19f3db966fe0cc431c8602f53e3f731e91170fb8cd1f38a6c8591b4385f97d3950d0ea025ebd4d33285dedbff8bfd010daa015d241b4461ad12685c7deb3ab368b97ebdebd9ff2c1b66c4b40b21c3e90df6628fa85650a40bedcfb8959d740b618b6b12373336a879878ca3173aba58ecc9f964290b84522eb10b4a22be481d8431fc708d325004e929167059663f3972435cb947ca41d868cc1227c3cc0b4a3b6f76b8228587cd59d61a56039aad6c63c9ad6701d24905854435eda1aec0375fd734ff72a24ebd4fce3d8e6caeb4d4a388172a5cab4a0a46b23d4b9b1650f71251fb045690f2944dc9c28098a0da4631d6e465a063d866ac1e3bca334640bcfa50bc051441d2f348c22f580400a4d116a88d4acc89db1ed5c0c750aa5248ceb16ce842c99582a83fbfd12c08926357da05833740ad9dc054005d861a00ec23878f7ddd447bbd588a770e9af99dfe5ae7c24e921105abce7e3abcb9518fbd34ecee78519c35523dd1a40696fdb6dc318bb2b58578ea8cc8bd1115a88e795c0abb7f1e477e7f230fd76d786e91b57f7bcea69ddf4e4e96a2e7100a9f3472e3455fcb74604c3428754d4980193a76e0bf608345f7235371f7162b261f301375360762e6253f7dded1e4dca4d213f60f9156bc7f428c433b54b689642e016861cda44d7e2d5afea809b3bd93df268852c7607af3a6c0c41f9541a985a202e9f776736008bc7139a1979a2220ef3202b88d7402ffa2c21ed91fac7c29c30ca1ba4a01593721dec84ed10645f8e72bc77a6381364402321aba14ba6a4a3c34120d9d6f087d00b1b5b14b0bbfa9055dc3be3c1d3be88f664be17f5888189e2b6db449949e4217e74231bd936017e08a54010d6021e4f781f16345a2a4c655ec611a5e44e21cb42157cfbd9a24b846c4d9e5822ac1626ee7a3f0b436c56375d297bdd82e86b36ce822fc7843ead5c0906672cd6f1a7705cd293dd71671b1aee6d3715d968d843b3b0253c655de98b3a703f3db633cb5f8607d54dcbc6e73594285dd4c1a6600d67fb2cdd80387a48369e5c320fa2e6f5fb583bb774b93a03ba88849859397a68f3923100ac7e283793859511b6c40e5d2a3cd05bb51f0b810900e4060dbd0a030a64c2b522f4114401cccc10d6a72cf5cb57b7a3a3901c5524ab0d7eecadd4df03681694e8636c4a73476e0b7f462d9f90ae32383964c268ca375e7bf5dfd576241757aa3e3ce77fa685a77519e43b108c22e07a266fb63acbf335095514eaf292adb6de42447460946b7d1b592d0b5144cbe2be3401835cb768c002ccb791184b63234bb6435305d2ca951b34a6131a1b530309b86951099a5559b2d7a8fd02209a39fd7afb895b838a5903faa8bec3464bc2a267356e42e8cac2c214783a4b164470f5af623d9224cb7bcd165276e491396319a7745021c26c2fd987b9ca3dc53802d543b4286b89fee0552fb9c35a7a0f69eefa33065a61ecdea61631188d279a55cf33a7d90fe609b355498f681142689c9225d6bb87a8532463baf21e3d4a8b0838af62aefb0c4611a7381e25eeeabe504185e97946fa910e2308d71a812ee17957cfe916ffd127a7066851151a687402c8c8bbe3e67a2226e005accd45485a6947e590b4a6d7c7a6fb694016de4c94fb67596da94ee6d871ec415e63c962f31e2d31c485668c22e2003c04aa8b11fe27cff3864c0bf4a8d6423b690bb49762fd1a67c15c219c2ec3a9c49be3c05f97ba803e34319d817f7a827a38bbd9f56a77ecd0544d15d3e72f0179c5acc58052837726161325090eb25d43042764fbf27c07bf7c41a6444883a75bbb71a97af5dc35d4b3dbb9742416e0985be1fcb99b68ad837c2f2fdf5e020a4de476f9b52b91f474af4b1184ef31dbdf1856c887aa84ac96cb8f25f215212c0037f6eb439e72a9bfb243cc1331c1c2f0f53c78613c2d2e62908f0293113f088766fcce17cbda756325cdbb63b8742ed1737b114d3146e1f40f23ae77201fc5a7ccffe72811a8252b7c779b8c368753ab2fc2004b01521f6ff41047be2b2a8dccdeee062889b73f8c727bed6c3cacd6f271ea0973963361d116c5bca8270b8d2bf44c0b03eaea92f223088262929067f973a3365a9a712094f33ca12b7a52a9513e1009f32370adb1042410233efa5524da5f63195a2d1fd887c4cecb8ac0193b5069933f89044e288a43cc31890aa5213212e1f2ec41816c97941208cf0f78a18f64bdd1d7f543b2f093d0c198a787961c4be77bc2c0d560da218c20be8589b822712bb52314d29429b5900e8ec1409b7924750193d132ba852d138c7fbf68a9ef1eab8b554f1032a30ccedb15db82dcdd2cfa242bc3cd1ceb93c8785b8ee63c28e7281dd53bb0809a091400506adec8442bad4e8764fed922f95c085dcec005b43d631695935e5c9c55cee75eb9d1fe91b75096821d5621a0f88c5d432b310e5ae699deb41c0c71291358bbc8b3433b5f329d5a28916a80b1085497cadc46a73b924fb43a81de0bc020fb5e1a911aaa4f037b86b189bf8e08be2042dc02fd10071ebcdc3c22f089439544f8e2e93b7921969806b1c517919c2b28d40501cd664f42282da4398f220b591327f8049a5c2f7118e91d01da60fa891dc317630c7487d02c0603466a2e5bfd41d4fd7bde1c34764fde848ab0c001f00c21a083ad42b982466c2d2d04e5703c6ec1ded0468e9d367312b524f6699f6e8e69138af7500dfe5657d2518aaf2a4e25a826310416cdad76bc8dbf3ab2890e8f242cb440928aba996ecedff21f3c522ba02830aaf4fb7691109c40167f350e20c0822913aa32a2bcce10c2220d5ee1044109dd67f6fdee9f16c568f24321a4093bbdcd1b9e42b7e52d05a7021c7f12e9bdadcbfafe315802e030b5ff38da2c363e09448c37dce93fe51a11946abc4c7a18fb6785a267e5cda2c0ed83be6eabbf5cdc8ffa1ff76ec7bfcaf956a5853ec5b7bc05e4d5db4facca00e3c69628c259e6efc632da8ccd4c6aaa018af73e2e6fb80e67ef511b1691cb9f60bc9986a107dcb5d95fc897c2f98dd80129ae4d7cc3f5713f154a4548c50555497de531e456d92a32240de1c8720a6e8aba9385a69dfbae3098f44582f73a94725d28b4fd08c4c8ba84bd80900fad4283893b00608bfdb6e0af1916b6dd83a1b6a5105bc2ac9462bef77802c8d0565b0de59d95f59b61e1418f907c9aa5bc67ee5e3978c2d291b39da9712154f8470700e0758b544f735d293774daf6ae4c28a88c4fe6bd1664274e712a82be17cd92f36c27716376bd0c83f98d3731d20aac4bce0b39d839d1890557d11ff119e9b5025322f76fc1c142a75b45af25bee1c1a15291b9efb8f0e0e3fd98b197a8ee18767e5f6c2028be8eeab24dbb7dc854ee580d6fdbbd827c667bd0abcddfcb5af7cedfa4cc3dfaf94f014e6bc5ddbaddce677081349bc97d5b5442b4524bc8a33a4baf16804fa7616787761d63139193d00c1f30273ef79d182b1ab845e6b415db84aa2cb36ef8e1b561babe5f1629340947e2f081b485708189505851036f170c19ede8ce3b4f810a26a212a41f8e3ebc0cea8670e0fea8294e9b4b6caf68d0a55649496798a2dcf5a5f1d802c05413eec7c07791a22ed1e1e4ffa292ade5191e1fef608fdd06ea0a037bb75737265f7d65763abb236d94ab391a86a42d1e76bbcaab366239efb8f674440b2b482415150176ab56c1c78f91e8f38b9cf233380785d1eefcbc9d80be0aa3301edd2e3941ec4256e0287bf2586e4150d22b13d67c33d6a563c45b33c8bb7e8f255890e1e1f53be7eee4d248e8c74c8ebac7327a5ba6228d3b3e245371139a4ab285e772a3d65d6313c81ce112f3117480eb56faff35fde859c07cf485c1dda993a225e40ed269268752cc0ad820e210e05ede153ec0b39088a102ac6c211061f3511c46e517a508e86dfa79c7fa0b1dd146f03538cc5d93cb1c42291041a816a376a0867faa4026ea784bf9d1c342874d6c1cc84afd5af8b0f022930d38ad0d26f0fd0e324583c4c4d79373e4c2e5debefec099bc70427a984f858fe08119f00afe03d877ae8b3a9a09b55647003e4e3574e9c5032ad2563385197211eb15e49f2996e5b9d7b027f7b29eb18129fc89f737dce3d7fef87fa0e7f799bae7791e6ba4d290f1e0c823d66fdcb6a9922239cbcb7e2bf21aaa3d2c918f38ac848492e83e2a8a6b100d063cd69342ddee9b88971004c628ecf7d449435ac047224cf8b88d8eb1c39f147c92529ae51716b2565f1f3a80803089bd0d115230e85fe188980c0cfb890192468664b795f40a098cc3334de628a400c7a3c394da3d5be6d91b6fd0c390c5398041e3ce81a5a212d9aad90b4c1f1bbf21d068ba49876a32b0f5f0cf0466e137019304d7313d90a4a1e1447fcfb5f810f11377ef560d0e8b5979423203880578fca7580c03606b1a50ad9442e88fe6d534dec2f7e1d0c0d373996f4ed879f818d50c0536f870623359a4a918b5b58731f7d0ccb17292b8c0649f8f548ab31aabf52e41c9957f02a67e216c5ee4cee4da063fa056d353fa0e823b013acc0bf4432f0e6127e985cfbad581b4e80be9c8e1ca352b4adc61623686cddc7c8633706cbd1ce1272e3167cbf77d7e051271dbd5399e6accf2cc557494036c563b223cb751fa3da75a74be512eb76132f1952044ca699b4740e64be3072a6be324194be0800686cf23907a0e15e5da2f7c56beb49a41db80da4d268dc2764e4ec86b8b3f05d37ee42f01814e226524610cc915ec36f82402ea8334d62bbb5edfe01b8970ac741af6a16432aec1ceb3897ad3a21d93fb6784ff01207cabe726e486e29e86c48cd549349c26c86f8c363cda566c266251131409319224a5c134a139d81342b545a97e98ce350256fd4212599efedb30c8ed66dfa42cfcb0159e14bcf4c5291521f9e83165ffe2ef3cabce8be0d161343c16ba373e0d0c41b8c4add8eae825a052b73bc201ae40c3fdbbf6b36551ec4d10531ffa8d5f33b6975a79ba9825ed8ab0f338824263d82e0888b75f5117c01b40ca4c5f3811a040635e5f01a965bc6d8d93b98a547d828089eb00efe3dc1b5ce6e382e4bdd71b7c464e36e668edbe07d2cd99fc15ea3a94d6a01b4908cdfd7e710114a598ccf052d4e73863889ab55d19d659d0e6574dd5f7afa87ce4aeb6d96894f1e5643e637844fed00d7f21759bf02dced1141ff3dfbd050279c24c8156ba0042cc9b7c040324639b33f451924b90e67ec62ab3e8cb0a2ad58fa94dd31eaea3ca4d337fde809a84d91a5ae288efd29feab8be6f08dd34ff0af4e050ef65654dad99072ff07eee2ef10a8c51cf85ab8a9c727fdccae3a5815ed6f95817a118e3fcc5d26135471292559bdbe94c369eb2c8ae74d961f7044ca1f3b5e76885f82ad27039c997533480fa66feac364b26a4e06206d5820dacd83a3d56491dec32174060e14c65a825e5bb19815aff7f84c8075f83772ba0eaa064884bcaabc43f8776c0ceac65fe6d2a7097246db66c0e7859077f03ef3a6781d90489ae69b8f549301a74b46c1b9acd1fe152f5f6fc57bdc956b2fcb96507f2e8f382f40e423d4eafc081ee5a7291d8fa24de134b7a12310f043461d115f03c51f6f32623e93b7c3e64ab540021311a388819ec4118776b7352c6c19ebc64f46ddacb0145cdb2c70d682541c77166056122474a2c01a518a2178186f0d179e28a609e9584de77d11986ac94ff6730614fc9a4babc8c07a6ffcb8d5a233a085d57bfe7a0bb3388a405720ecb72522d0d184e1dab81ad49b11244163ceeee16920f05ae7c1c79a2ea827e7e6f9e40f9e51c5ca371ea7eb40e7be5d51befe797421264414f8372c10d0721e7cda223932750e7c8f6f45c87970ff9dfea057836fa746c7afe4dc2af5fc886672d92d435bf076ab9c0bd9059a6f659f2e4c5c29c75dac3702ed0fbc04f1bf10a181cbd936b95946701499f12b0601923f2f05c21cf0070a4c22c35f6ade71eba00f8a13c946a53e38ef3a09ce0271e616ee0b0857d70668a7b97a0525a096d416b70c44c97f01f553d6a08ca1a3f565209f77660c2865bb0ccc8f3ac5ae35161e084450e8635d229e5470b4cd8538bc6b59990d7618343b3ec5d12b5e8e72d66a5459f38cedbbe413f1bd3250bb48c835040d0531cc904040215a96089b9f6522692dadbe010ec3428b1d6eee43662fc7c8cc2eafb5d6bba2a89cfcc711424452eaef1899498ac6b711b097526dac0461ed5f80d061ea7b0072be99c1fe70d4323a07463738e2f2e06fb88c390a4029d754dbe58c49c625923216b17a6db6237a7ebe63cf4a4c7afa38e72406eadf7256aec8ae4d097c3c09a160ff03732ace668b412e23276e7688e805efcdd345d7042e5671874bc7bdee32af4a959281ce66a809e2ed629878f01d8584d99f996ecb8997df850975acd0fbc14ab6dc63e2b3958bd2de3e2707b5dbdcf4bd39e4feb4e62bb1e30610bf039ff38d0c722d1c7210743dde8837a5bc3cf176171fa44ac8ca9aef1c07b95703be19e7fd66fe3bcf2def6f38de52bed7699ccac0cb114de5b891bd87863da3689ea18a9348c75362726a4d382ac81c81df6df093686292fc26ebd3d3ed9e1555066831f590487b35fc4d306b0813f685bccff9a6c32f24d8698e89c5283626f4a81d3a7642e5aa7fe9df8ba0c83880f6c6266745f396c71c0b7ed2d75147752f339dd4f1461fe7a27f8e04f4863d9bd3e5959211360f3e4ccb36ecae379c12bf68b078c09739ab796cc6fb97d520da6a53b56514d939c4f5272974a3ec28116f4ae11185b1153c54053ffda291201dd6067ef5728e7f155c61ace9b23ca1326b6b3fb0d87d35609c3383260eb7266102cb0d30c83d766fdf8ecd17abd8c95f178704a44727ae99a5e2e402803c823fa0a114d2f32c3abd927cb12c13df717a93d2ce143e2d4381f6c8d67cc21c762c4e15d3f9e3a1ed57f89849ef2e6e85a7d004df5e88e2ce383b058f6f2ae9608d835b0a3ac6eeda2574f9a7f0021ce35cfff8c091229b5348ea81077df377deeedcd7f2ea2a980a15a249c67eab0033d442c58a37a471b79e150728686ea73b52f1d16595f66d5faf8f0146ddc6567c033d818a42efeebeb33461286015385af79de81d1e292dd5f40e032de0150c0f93244ab80a0f73023bfb9c4f27167abe47c96a31a731f8e4a53ace8516003f9fb7f7a93b674106df4b57e183734bf567f0848739e137519dde835858ddcfe7979e3c47dbb1851508b64ba549ae9f09105c2169405bfdb7b011cca3655c24281895e0c14cd072a304aabd2838d4cc8f6b75bf4407ae3557dde33e67d714b4988adc827c08175f9a665f0aed135b31ec340c65f75ef2b1de38ca13c586b72ca185fecb3223c0dd04690c9070e741c62068a0aaa1a91634a3c90140c23ba369544dafe6dd5e384f0af77bf0de1972f2cbba39e76e7fca62284b2aeadbc6c1a23fc43c4157677e69927f7f5e1c94c1ae9872825c1698a03a496bf5f7d7be5002e417c7cc9a58706125a956d5f7f7966392c30d943c92cc53d8444dc9f7d7705f370cfcb0fe6f6c084ec7bebf4b3e88182d902187689ed4f9fe8255b75ad41d6a84dd8642407ebad7f7f79df5e35f1bf499f11c4de58681d1a4f728ecde34d3487f665e1dcec83ffa17f0c74c0cfd23f6e21741085b6c0c428af0339fc794aa7fb6d19a6ffb2b7f46638efcce122c930dfc9924ee6cbe5e97a2855f4a64c3db51646be61a9abaa6cfb3d86d468b06b69d7baeb02c6032266e4a2c2206aa411e4d5298af650bc13497b3a521b5813d4cde61f70e15b35eee481bfa3a077021e8f0d75b6c4dbaa98ada5bf4a4c6363a9cf38029d54c2a0544d909bfbdb482fd51d5abdb6d3621d660aa19f72b150bd00383063e7fd83114f04aafd0e95a0b73689ea7718d662dc66eb76656bee957f6699ea355e213d3ae740790086a1d9e70449bad94c9fd4aeb63c4decf589e697969019c649c89c9f1af3d31c912fc734f7bf9dee9f05bfde5cebb3045918848eb2f331108444765e907265bed4bbeee363ed96568ffd879f7295e29877eff19be98bee1251cd637c3d0b3823db258c240cc33f65dd9552000577f19b24cd10d47bcb3b65aecf7851c5d0e53fa162a4d8b7b54ad7bdcbea8b1796c3a2b8b238c12663baa01e79f49e8845f2413effa29d8cbd02f38d45ec2ef562169a21c227be5ba3c407d885f25907651947970ac4dea71e2a3ea22634a28761996986397c0fc46b577ff9b30c64593e304bf4cf8dd0ad99a271dc82f57ff01ec7d8ab203164653f2536e81a1fa299340275d423a52df2ae20441aa0156009695945fe359b52756164ccc98df44867b94c3b53895c2744c9b52f2c31e4ce3e1570f991f7cc23118e7a4a12c15ca8d3a602d91f181cfd22a5cb3bc771fbcf8ba7cc430ff95fc9a63826c7a1305e158df1a8e72aa8bffd15d0ef66778109c2b6ac1800c135910b0f094838c558a734639fffc882992332f4d6c2a688e6ba388a43a42d1cfea9b0a80f83fc0d699f1bfc9cf564812f5e14b26b2537b3f5220d79890e182f9ec2d8e4d07a9f11f89e57c9262ef9a1ffe2450d72d81c724a60e067d9dca93cc5705f14f13bea3e007e22e0c9e1c1b7e9e68803acde305998d676d490fe960bf59c418399007879e9f8c20e7cc5405d16cd9fe5bf291b069be5d06ccad2ce623800281b8804758a0646d6d46897774b6068b6169594de85ce5053b86dd130b1d606b48d5c4bda9f5334a1c7a4985e2dbc844839309bea74c049d65e2e898097b9bcb1bf874ad8af8910901788a68dba1fd831a360a7a1ce2c6dc48f826a9dc7659de242512cc19804549f8e47f715c13b6f608171113496f1e513f90040b10514d59c3c34e982ce8377eba7c9ba944bc0ed14a1e503be2175824a7224989700490e1fe763ce1a183e0cc28c88ce45a4493b49a2e11995766defb8cb73dbf939ed668411b5078b717cb488f3d140d19cf0f69410eb4fcd7738894ad63c56262209e3446ca5338fbebca375b2a3f7cdb609b327ea93288312fe2d62479c25e934b66fd1d35b462d1e7dac1788c5dec96030bad13a6522ae86ad4b7c3c903a8b867bb8f8a6c34dc0feba9413f31c6554a507d94d8d5f157f0845847cf2b51ab332da3b2057718d9984424a3e374491ab14b3cd21e1913aae28b2be53f83695c9c6c5522b1e42becef728eee1fee31fdef22bfc8daefc6c7a935d1801acc1d0cc54e66086446bb1178806e7cf9bcb1bf66266c4310380f016a3fa94d37ee38c9146ea2452dae99a9f85bcc4d71f762862d0e48285d84baadcdc58aa4bf7190406cd1a4106a3cb093f58d47a11528cf0aa0590da1feb5637c54f407d8a977a2bd8f7b498d813b5f4dbaf1fd158d306be4ce8294467a283cc4041bf55f5a8a159d5ded6c1cfa9ae518be83dbf873ef4bd58d17e01b8d7f007a467ffefc37c3ce6a0124f5f909b23495313541132b7bbb1d06b20c0cda56acb1fe1bb8954da5d02fc77177ca31340536676ffcd22b577b2d3fb92c06c3caa1529198638b2a4541fac6b1759a05488207ca617782d9d7dc57f986ce290497533db1cf2584e78157f9fb6cebda12ebeb92d928ee6770a9e6244ba0708059a41bace83666f7c63ea90f7006e63e38f66f8846d710c5f99faafdb3bde142784b5c152f077938587bc32ef849d97f4b35d6157719bb5769c73be09163fb3ec5a83b9c4422c88cd8f26122d32659b51c818dd714ae4e7ce881ab52fc67de101fc678464dc4a73cd06db2af85788752861983bb134d0235dc1cb88c0b9174d9a1f8d2c13fd28dc069ade5233c1b5ccef1a17a525375d9347bff1c9e5d8f43b4f4ed7d3da6ea2fd06ec8c6f086418ec7e0091a4a704771130e569fcc5d6e521677c7211a8f6042b54538c177e8897120ce29c5424c371aa269e36c8463df31aa980c1798ec09bac1b48ddc4837b0742363cf33fa884333e625502c713bd751794691409f6ad880c0210ecc570212edcca2db1ef7f2ae00328bf198e783439ccfa4d8f737d65d614a1227da0218ce07692b6613f2963e4f508dea5909195aca8b6bf1440cbfda7bb48fc4ef7c2308988da2ef31a4ef9418dff3c1ace94fe5021182950b247d3e1776eaba3cb86f3de97fedc8d1c32db0d39aaf7707a62c2f9d6ee7920586988682200438b0c902f51b2cbba8d55b90c7ca05405458d9d7f57cc340a89ea3e3f0e99d423bf6e1b9ad5b5e6b574c82c30ff95080132446477052e7e011aead81f393682a7b22dac234294ce484e24ad203e0617f03af7682b075d3d9d320bd399d2ef86f5944d6f5fd909c68e05e99b34d6adc1a8af65a429e61e9f44e2d1049690a2134be5fcc79370b62efeb19867c55e92ef7bde37f5abac87d5f16c6697589a74eded8010ccd55bffa2109727cb561b408b1ed5f4ef11cab817b57dd3cfc1221eae71c00888e03e0209547548263069849dece4fc5de39268174f71d280cb899667f4644fc6eaaed86935ffcfee2660b08f7a05187dd596a8348f9c15003298783c950191e5eb872e9e57a8c47c3050fd07c8b32499dc241764ba1ac17079f419031b9f1a56ec285456b4138a810541e471c532cc600ca31bc6eb7cfafc52f3f4231ab87e8f067dc71f0e876a1514832820c30409bdb8537a17fc0703eed63fd7302ac8bb7e8188ed8046b41819884e3760a97c9a0ccfac50fb3a67b70ecc9ce79ba7a50ad100e6d59d33fb68fdbb381d22f7e7eb83988daea692cbd510e4a7a2de17b5957cb3e20c78ba797d7fbf3136a7912f77d76425fa3d69b8b67048ed3821cb8ea92d195a4154ab9f03cee48bc9cf817076c745115e0cf257610586fb9e7eb43a0cd65a108c3851504bab21fed3565d3486f91e9c46d5780aac4e2c9aa298a59413060b0fb32105629ca32329a44d521e7473377272f8daa2be3917a2dab3a622624ae5f7d99388b603d32b68e21bbef985f70e28f0fad7ab3136b8090bb77442aba9dba62804a2d39cc85bf01121c9233faeea984e0139583d42aedee69428755a9e3096455c171ab3281d4c98055355c22705636ac4d690996b1d577fc308757414d32ab5d67e27bb6402d9297d4339b653d206b8c9d1baed4798549a7448e9ed21e1cd05c4ea485963ad7a54ef0200bf8801b732ff552ecb70b17cda0976fb3dcee42cef965696d289c9027aab62421e5688de0e6167348625a16aad29dd09318f0df52da6eb7769caa76d35fb52b274ed3f81724e0ea3c17634c869e36eb58696165cf851d67693640e3f0625b63259a631fb3b9f80a04aa0aabae12f995792437b99ba7901fadf9fe4d9f0c6417ffe65ed25af91f770f7c18c4d2e2dc940e66f40538aad8313126bffd06244ac07bf360ce5ae60c9b6b147b93195115f0af689581d2ebbf110a0517f6a4df10620dd3169dc5fcee797371419a2565f02fdea037bd0390848e6f17a01730f9bc6d373c58349ebf2590ed0c2d87c2b25859ccdeb8266606b5f17b4fb83747f716f242c6f8c07b1fe472a74bdac516806ac4dc097f7a8346937b2dd104c4b74ed962a9adf7e01cda4978c2af433e69e37dbef5c8a6034fcd3553453401b0bbdf33cc75eb6abca36ba534b3b826af0eaf3b58dc41a1102befbbe3c9852d8339b9363851155cd0bab8280e4fdccc2ff2d058fb9fa271a041dbdf79f7501b965f90391ba6380718dfa5b51637d2b4f101fd2a0601c7e83d0adc98a139a1d5ee9744454c36ca3bc06e422b1cc22ecfdaa137dc51ae7b09a6339ce7acac52b57ccf7c67c2a2e3998b9f5d04194e412475d7bd400585fdb08baec85623dd7b71c3c305d375f22221b29f3ac24fc1c93a972eb299f734230ce8390af762f3c15356df1ca9803cdc9d1d13b415a8e4affcf3925c02a65783ffaa6e811a32e60eb62165ac7245f565d53b039d7302a0597b8778431b263a6b18fd633e8797ec54a47d9df56b6fc40b7816f5332e42fef811368c0459704db0450f7ca3ffdc55e5d80338cf1fd3303beed470d2ba5a2046a688115d91e1ca103c694016880546c477be01c67d23a1b279252a98a7959b74dd1a1c948c770412ac48fa8d8f1d92f3415b190121ee20b7940191feb711e61257bbcd2f11a84f8836707f90a04ee447186f52f670fe8c3512f3f6beeabdc9661bcde4cedd9b86374732d1f8276c702e28a56dfd95218218679947d8b54baca6d549fa93596abf08d73dc7d5028e560045ecd25dd0745c7466e015ffe08bdfd13f84abaa938eeb3b0bcb6a2338e485e4bced911c38c2f7352db289bdab1ae2a9a986f29788518d50aeb233f5f15c357499b264e66fd84c0df65e641d078942f92c265ccfb7eb2cbd6cb9370494f1c44c9c3d96aa4a54e5aad72fa7a7f6070ca9d0947658f1e467de66296750535a19201aae112197b318e8e57cdf03cb657677c4ce871b9f8b4e2e223bb50954a999f66618f71fea25174d9d7cd6e47803f127829771800a94dc1b47f93b92f26ed74226da9654d2e5ea9264f0474d537eae778a8107c3bd580a3280f9005ada51181a055545e7011431957ed7c514a265cd103e2effe3ecd0d930920b55c3b2d32f223f6467d4dec47494c29c500a6743afacef7dc23d93c6ccc4cd5867d12119a157e032535d02ffde24936adba64af2709710d81a7f4768059db1a3af21f8bcde0905ba17a90dd4c3c965f3b113d379bd3c8a32efeca074012aa90c1b66c9bdd95788abfc83b1818370569e4a7622de395add87d09b01b863df011daed74695d66706c72ff8b02ac607de56f3c005fe3b0bbf6a6938deb7210c496cad68209e9306cc48af64de7eaed44a3c8e3254846addf001bc918348a51fca426ea3d20da72c64dabd62f63f0cde8a0c26d3f5eb54042d593b7c0758f9e6c401925b3fcf367f1b93ef1cd95b5c202b4d91fc6e83965286ef6b85a6262643a031c361412ed2159881c8366a5fccbeb6037f7d82adb8a35534c82570905a40bcddb787bf64c998a8a313ea47941d10045722f28808c593255dd39279605727a00773f4a6bbd1f21bd3a83b0d3f461416c842b24bfc8c2ae206a83777280153913373d1b063b6c26964e8559ec9a19957ac35562bf9e31b84d03f37267aafea80cb7a234c2173606818c6662a14c50478066836df275f97c0b922c2a2256b2d5e0d226149c536ea00e79adff708e7938ebcf447ab3a783413e9538f534560b817706de2529d730f2c9e20a5e124fc31f3aff0a99d061ecd480b196916fb9556b504295e5aa7ac0b1a65ead5f0acc284107350fa47b29189fadb46aedcdaa254fa223fb58a06988387efb783c3d49bbc1e13bf898b63d1d83060a480ffde6b314e236495061228172543388364847af127e3cc2951b6a4ede1b29d55209a76f5e845ceaacfc94c2da4a3e6f06f65f1c7087b05412eabcd53b9924a148f1fe206646a4df44de3b8218a31a44c78e89fc0472720085e4d79df044da364fa2bc5d8f1cab38ed2e2c466d1623dfa0c071bb65b59fc8d0859a2c1700227b34def10f04a9e05e92047065b416f272d8f71292ad9bb4e6fe59b7b8f2e1419541d8b80d90f82b5aec0e44568d3bdb077178049e0da79f3a50b242aa52f92bf876a339a234753075dcef88d35a2a5d0c1c72e9dd7c4c0b885cc4726ff53c27f39ac164cfb2398b4f42cde4ba1069d7753a7a9e16aa6f43e7e8fcbc9c39ce94a9f20b20a0f9772f4a07b01b41d669341cf838f27c2012a45c5e3cd08bdc1a473cb2f485afc4b94dd3652834160e28dda50fd2bdae481fc92dede88363d52fd4306dadff99a5f76732aa0ebab8e88fac89acd94b366a334188a093a34f045be831e511a42f3733bb10b7cefb79bd3c14da0f65902326e6ea77669a2a1c89a959767fec3370953a0149840fefab36c52ff457a925cb29dbb42335c99b083f7f2509245d95b5017111533d5f43dd8e7e7328bc3b52490eeffddda87241355c4696235c2db09cc72efb2b394455b75875f1a94dda246a800da6f84716508e3f9d2f6c5baa9bafd7995ddb85e0b14fa4dad06fd2642d425dd101bd74241db113efec586978764f022389e8934a699207a43a96357cc43af63b7f4c966c90b6ac3f59ecd5a8e47f2db758f1563768b4e200f6ddbc896e735e7fce17079b39cc7dbee73e6ac75cc547798bad63974f905d336e7fdf434bcd76dd4f8ae8f297b4257097c197eff10f051b9b70a3bef23ae822be9f8fb702eb56b1c6089b3ba33eb443920bfa7efa5443c572cc7bb5ff6dcceee64b92c656ea68583d130ea19d098645f72ad84e331699c493a5da10e41b05d404f8edd2ec06ffd367bb665812f081891594cf591bdec166ccfab2e99632ac67a4adc63e4587bc22377c99bb5cd3e462307f7c867dbf76f800cc24d64e5f6508fc4bda598e94fbe854adeb21603d79afa80cf60a666409209aca231b43eb85d27f9b1f37cb020ea4432dd8461c41428774fbd45bca075cb357ef61e8e940c869e3daa278d1f521ae8e7300cd43756871cd990a9808862d763e1710c7c710575ecfaac888081899557d937c34b642183102647b6591aad3d6e589349c9913d2e904458258d8e9e42ae808c6ee0b552393f06495cd44047bce30ff510613f367b24e3296eaa9e7dd2f96eb720bf611981e4c6dfd21246339f800a08e23c4214cffe8b050862ffbeac03a4124d89ab933475bb33a3d5602f21f735491093f0fca214e398d1b216fcd58bb46060f37f3530ceaf846f840603765f451a8598594264191e68de3e2e26edcaeb217f683a91d05eb76ca8eead8c9679ad29b2562478901fa94d2923c0419b10846ef60c7b27eccdd3289f403c80dbfbd214077f21747f0877d2da931bf43200be39e977ab51c5c6a17d938155c79d04121548f96b1b78f564fce82ef17957866d2191bdf7e9f53ab60fe9309842ee58280229ec875422f055f78459d9ae70322c2785f901ab154d759634985256dde8696ee5d87204fddba16297173ca09bc4da18b6f106fee8e58e53a57cad23187de465d780f467dcdef8ce10c6fd98471712920919687445b09803f93ce4bc73a1f1a9d376520222587c435e18736b096fe519f40b544df44960963b96ab48541ac0045373dbdff7cf1c294462b5326b12dde2d2306c448f150f485c3dce4bc766e9da2043e73fcf8d2c27e0b18defd81d31c38e2105af100b101379613c51b49f3d318849e96a42dbf5b2c21c1d25ad9e212055148df3b51f05412ddf0d5e666efa0e478b8d06ba10bc80fdc4532297bd29dc5e38b754c2aa118c7a1fabb60544b087cd02587862eb1ff2c03384f478d82f89b276fa4f47c02400e6e31877fa27d7d7f52fc0933f3033fa5928fb06294e1df961a3cc332de3c24cb8f23611b565106808054344333fece06fc4085373e3abf85108d83aecd78985bb91d8774f61d43ca17a2f7e38769c5e008c102b5a5879d27050894d3315aab128315e3652b51b3c9304d258a42d7bd5dca76323f6a3d6044a4389e786064f03c38558d352c8d5ee1013f7642288d1fb152ab9274183b5d2126ff6cac7f30b199ed274d6c70c6b222606aff24feb647dbd0bb578f5fa5ad6433ec9dc86038b21712f0e4bf19af28ff1c6eeff3da2681d20357ed5468f6afa6d7e5526ca3172c9072ed177172992ea760f01161fad206473a2ab071981341f10bb91e5f84adb5767e2b984662e05b2284b7486922f49b1f20d97749775f12ba7127001cf0ca8af147d986fa5db0798a9dde355198c7b7e7360967e29e5f7a2962fad52631ce4fd2906ae1714bfedc0be07371ff4dcd9e1a5b7e627076885dd075d4fad077d08978514e39ede18fed677db5d416579f73f9f483777fb17791fe4ded4485101d39809cfd31c37ae8a29ec1491f4c47f73b29256e3e9504a9d4bf8aef37dbeb0d00cef6d62213b4b370a3b5a0436e2bc91dc85f948f6a3cd67bc02757e3981c7d2294c20b3b8c785a3b93cbe7b145317efac114c1068f09b27c547e6f04f2321f3eb4665279afcae6789c957b3f3182ad6c186d9e993c4d2e3a63724778192905e4ff6613d2b57bebfd33ca1a4fce03e723063258c60d051aed599d3326667965cc62f66f5579aafe64cd257ecba5119ea6806136fb6612f649b2f5c705908e0a44d1ff55df651ddfd0ca23290be6f04820f7df006b542bafde29db376622120c9885e16875143adb344ef6a9e06f4985c74df4bce5ed9d4ebcc82bdcdbd2a301df2dc0dff01c14f4649d5ff939212f5037e5c08018a430d02818f31974be9e5f8c887cc177a51fe69bb78e73e1a9ff4de9cc704ca4f9aa5d4e4caaa3e0e82d8d2ea91119e60b00fe2eeecbeaf9abe9b6f174491cf4cdd1b62c97cbb7fce4dd8cae668d6270e8fc9a2ac86b57f10904d966d9b1cdcfc7ae28c22ee35f463df412151044b6396427126b134f1187667e9c9b03308bd32cc88335566df43eed5bac514a4e3c175782a4bac2ee77ed8b729fc69204bb114a58f39787d862dd76f72b5f4580b5ead94836befb504d45c8bdef127baf7837d0215710f6384b86949716cc4864ada8b4f0bfb8b09d26bd7da9e3af15bbe066d9ed9cd6570b61eb08fdc4472b9f83796471138279e944fc70d0153bd0e6ecca1335c67f5380e35d4980bfdcfe41f9f58b7dccff5cb7948b20efdf5ea04fbe18219e81eaabb9fc63734bba2fa56ac00570f4e990abdd696ae2e3227b0fb3ee4e7e0a11744f9437adf603af968ec036f597ba185e9a08d3fd206ea229e564d07500a95e7381cc961315ae34657dc833fa80c08afcde7e114b0cc7274e4e78cafe5cd9a05761b9e7275892f06bde73d56db59719b6f10238e625368825137b3290e9b6f902327402bb19b913a1be57f56b86df7140aa81605246638828c32a41574b973824789eed926afa25c2dc9917426e2d6cb520fd107ea1078f54ae9213d5cfadcd3932597db9c08beaf3e889d4fa61cc1bdf303a7734c144e6334bde936e7c5e869d87c14b57e1e6af74cf5d6ea389b73c7ccba49e32b9b1e0998644047b6497bd4647b7abd1a2b7620656c39daf6ca45ac25857b215f341b57d4cae357ec80630262ac783dab7e6342f4d15a58ece676e5a30604904a6aa06f03e46857d3f631137a2503c459032a7e8e805c30d659491bd6476d36a53e30432a746064503d35ec74a6bf46fbacf987d35da8718069a337ee22846add30225dcf271b3faecdeca1ccdce77ded1b5a40c301542c60f29e511665f5ffd09b78154d6c5d476b9b88904d24b2bbbb7b076d08fc077b0744d0268e34c1441349ae0ba0407975c87b481994dad04967a7c188f1dcbe1a7a7d01d8b86fd5394010b780c295de837eec71eb174c1dd339ee635a87006064d9cce8563fd33a04d0a97dd1b144cdd8407bff76b8f2930bb6d797bdf2af029d9ebeb2c0c361890e23d18d2ac73875accc9da923adc4c933554e5a4ea0b49c14110d4929a79c52d26a2fa6184f19b1b417631263599659d6f446b76dcab845a949bd719aec3627f0b996ec3ee94476252216cac2326564913f728824f22387c8221248fa2051a98244c54ad2110b491216122743427115796290b88a3c7148f4892a098b2a3c8a52ce49698d724e4a6bb5b45a7b2fc6d8c5189665396b59d634adb78dd35adcb4c8c51dbb2f850e234b0b6d699932b6b0b4b8b8985278e95a527059e14b0127caee45e3c40e436160a68c30261c65e43269852d5c4574a00c04e1faa1b35c4180b8880001072a1c21021f29e222e1460b38e8d11606d862954ec9bad142eb88b440ec0fb69ed8396c23ec2a5b0845767087ae561116b4866c1dba5a3cd14a4e8264a2c83d120211d7a14b08435408424208eaf1b52a842227176c053a3ec10cf6aa7f314960420b26b2c8a115830584000475b1c0c2114626951b00d549e5063f64031801c2144392a0f8210a252daef8a1c8094058810e4f381285e71563dd688109284c181d651823803e6bc81a78c77ebedd0d1fd0d1d1d1c1613f532865942fdb7c1c77cb1909882af49842876fd3a7c699e953e7d0e4471a2396a8191dd2e7409f2b1011041f0a044105270061e458441012466ad00155bed162c7d7820004218d1b27187184099c24c5d7a213253de20b141184c44dd2f3b06dff70108a9840d2a30d1bf08bd1341a6d48ff686878fa57d33fcc4491fe21a03771f384d68d09af94b2284af9cf842e1fcbe8d0e5a4e524a875440c6e90c10ff90433b8f9912ac2e5848912176c27495c4e7a10a79db556d5a641132070682284da264049f98bdd8d111bde18b1e14beea3ff9c734a89d17972615aa043f92486da9a73a658b084871896a880dc69812b76b6051396903a81d14b0951144a845aa0c4c80a94106955990e5d4b585da87f2b50a49ba31d1f721f10c28fca8ff65297b44be9d221a733524a29d7115de24947ec127eb1df7b71374286ecf596a7cc1dc4a1fd781c2cc804444a33168ccc596bd6add065b2cf293becac4eeb59b7a3c950bf07eef773ec768c582376fe0d69847ebedd08708f8ffd08623af61726eab8d1120cb4c336eb208edcd5c84f0fb19e3b8cfbec225627d735d329f1b511db62bf9d76194b4a29a553ea1418e1441599bce612492c4c50263ba85b153633c2d59e60ac0996b132db9728a22d118476e9d0b5840e5b4b87ae265a34c162377995e2671625432d1a0d5ce26713131d5eb62b305a16315915325887aea1d7cc4b87aea1d3d00d34d7d0102e86820ced7453872e259200237e7e97124f946862ead0d56407319a145123d3a14b891f32627afc0c00dda16b091401582225000090511383770fe3858bd2b6d9ee0ef9e6c8773d7690fed1601528d9e9f179e4d8b33a27d6b394524668b34169d3a4079998988fa17917c4f4a044500b9478010f4cae9c78f28f069ce0832d74c0e1093f30f141832194f0003d690152528cd2ca499da8780800132a7a000093570e326eb44053446c960e5d4c98b8c164073dc458a20a6e0414744f78be0910184bb05ee8e0878b223d344b049182d3123a0499d1a207192c7862627ebe7a606eb400594d5aab9798a72c1c3141a27f9045031e17263fb430d161c572a5a79405cfae0205dc0bc8d64488bec10ab4a12154908782ec9025018b4287273b3401b28315b89a14c1e352e2870f58f840a1836b8914d512a00ed3a1cb890f2e265acc40c2c89b33a8084537434cb91982851124a9d209d0a12b49928abb2883706743883d1fced0eaf6ad087e6a50bc42c4dd0831842575ecb30b08472e200c61f9ace5e55f64def42e315ade3afdb9e3e26b40e0e9dac358d15c4950498227899d3e9f6adcb67dde3eefd29679bd65fe86d476d6affdb6bdd50ec8cf9d4aaff1ef8413af70fc3b95b88e78a56ffecdd0eadc7f33b4baf6b0cfd0da5f750bb1cbbcd67dda6b6e4388ad711e3588fee63932af790e4c4993f9cc611e7e8c8b06f3d2f2f535fe995c5cb296cf5ab2962cdb72966d2d59966d39d35832cec2f259c792715cc671f5b9c71997e1cf6e84c030579223ae242a0cc3302c3ee64aa2a8635ae9b5dfb4dfbeb4fdfc1b73c3302c6a1caddb3fb5df3af47f3528736cf7db7d35e89ba155837cc0444d4a86359f8b559771d21a67b597e298ee436a2fc6329a6553c6acda18238c3a94d68bb12cd39ca78cd9befcdc97168ccec5b2ac693d65d42c8d63d26e8c31c2086f8cd8caa7cbcf418674f99a8f26d2e56f3f1ce5b82923b7d238a65e5943499c0cb14c504c2d168e49dfcf52332599aa98ac9892a209e97bd9d13121c51f202245807e8e04fd44ec5f885ea0bc14bd10bdb4e88bd1cb8bf297968e6a8747a51364451feaf9394a3927a59896695bc31a06a34d18058a0e7fbe620c78e8f0e72a32e1071d623289123ac4b387203afcf813450cf0c63e84a71fcc2c61660819283238c4e000868abf93d24d6b0f678d19f9e9075dbe9d73ce2ca1cbaf599637ad65999b19a2cbc7b04d6b589681d2e5532e8343ecf35e2d6777c6e0a0cb97d65a6b2d0c15b1babc6082648bc562b158acd56ab55aadba7c9797cbcbe5e5f27279b9bc768985a5a5c5057f7631bdd0979729e30ba6b1b4d2b424c192050b91d2104a3f60942ebfe62c7f78e8f2698629a574b624c19245976f5988c8d2104a3f764bfe000509b1867e582c168bd5daaddddaadddda2de8a2419349832f104683d6853661ecdd06ee884d8a2d88561263d0e5d34c6b996e1bbafc89d1989867714774f912e70cf3c93729baac5acee616442bd12ba424a9a35afd98904c482624139209c984d4e5eb955ee9955ee9955e6933790979880c4adb5f9e739f7b4ec3a0c9fbfaa5c6526e58fb80f1d5f7a5d6589debaea9e3aa24e9bf6f7517f74f98c7dca754190ff61535ce8bcef990f160ed9758f297e2a67feb89de7c9ebf1e74c6061019cfc19e0b8ada01a5d7fc8b18c7f9d0ed971d717f5ffb1955577d31a86b0fd3bd741a73380ab73955c7bfdd544faa27a54af5d8d48a439236f6b38eab226decc721a57a5c7eb6843902abd3cf424628f24aea2b74e87a0d75230c29020f455debf5e37b432e2988f40474e88a824a8f0249b7e9d01545901e85939ebbe6f974dcf3a679abacc61863dc3e7a59e360f5ad10cf27d3392acc8fbd8bfc70d6a8413230a6969226adb5f97bc89cf835f4bab50bb3636bed6b12f39cba350c19fe5c3f7ecd40b00601ab0f524a5c1f6a8d3ba07ead41967f3bf22fa6d6a0ca3fda7dbbfba0a186a87d26e8f535ee11e939fa6be8b5fb668fdd85c63d1c1f736f087eabb9e039f8350c2fdeca5a5f68fc9e4f6ff9af02c1af4060fdaa82372fbe72aaf1ebff78d817b4e5271811672f2ee6f7e9691ce0427c6f2551f2ed7b41a257df72d96bb55f0ff9793e1acfb1af3f6b18b42867f6c7bcd0bc4b7e99eb671aff22a661d06a7d9afaa7fabb3e577394d91bea60741b898d5df3d7af9fbbf837e60bd85d74dad374a76e771df456d94b867f3886c3f06fbf7013ff625c780bff60b0e46a79d4c8527aa9716ccf5eb3c69ed92bab2a5149e2c7726ee9bfd243fd422cf113fefab1af660d1b8e7fd8c62666af3acd2afb557ffdecb7aeaa348ef6399a7f4f350c5ad7de66d6a840809408c207ca03ff78548d7f21f0d1ed676fe509891ef47cfa16da48b650a7967b42a20ad54413659c8821b6e494d55a6bb4b3d82d6badb5d65a6ba9ecac0a13884e20a484edc3cfa662b79e40d2c95fec32ab53ce70c19675524a3569eb97c07ea9535aa9853df69710c0e876a6db986e615e14d0338665a85e6567eab45216728fb647dae3ec02e8794a1967b6c5e71d6a1d19c59a1c40c7b20340c71de3189d77d8a4e73ca78c31c60873b6cd4fa25fad23eb184b8b558ae11653ac38d19a82c594d71429535c53964ce1c194235fccce96b2c594266011a7bce41429738a6bca121e4c39d2c3942114f3c829278898942d7adcc15e6ba5d820059814a014e0225b8a0d3f2c147edc68c1da2a39c4bcb5d65a6badb5d65a6badb5d65a18ec0fb27ad8529c4899424a51ff56d002762b4416668dece1c4d8eba8753bf97f601c3b46e6c5af7dee220eacc35d8434eecf4e421af763d7afc4a18d00cfaed471f71d5441beed62c000c01972c6a7429770865cc0bfa50f2bee28a411f3ad5dc470601c1747c65aee2c8e8a23675aee288e9cb5dc4d1c59bb5ab64117dced9eb186753771e44cd39dc491738432d38d6e2e7246d453424d37dd6538b4ac35bd652eef08e5a61bfdace76ecb2e77db516913b9ec622c1dfb504410122c3d8825237207a00e5d4ef8f4b9828e75c0b3c70955b781d2daa16b8a1521b2b77ae2f544eb0916920e5d4f14792208f984cf7c224887ae2776fad77558b445519522a322a2a221a1688b80260c341f6e0df2e1a21f5ad14e872e27aa3841c58915a61071820804f14aa730c85e8f0da400f56ce892e223650729394c293650281055b144585ca223ec4054d4a18bc849efd045d40322a11e77874440fda344437a7c8ae12b93c81e4f8c73ce39618c4872b0ba9456747a7d796447561e8cf1c517637c31c6f8628cf1c517637cf195b4da4bedc518c6b28cb59ad5ace94cab9aae9a56bb2feed4fadbce0625aa6afdbdb55abf246db5d5566c6b8dadb6625bbf7eec2149109144271f6040972f19305b883c35861b318834f2e15304a9f8f8f97cacba8c52ce49698d724e4a6bb5b45a7b2fc6d8c5189665396b59d634adb78dc3d7765f0d4696e334bb6da9a459167c6bf7ad504d26adbebc681506e38e65855ebfc5a8d77739c2dd97028e49c3dd67a3d77fa901a9cb7bbf1a5ebdd620d4e57f71a8174048d4894205baa2587111f1c42fc268071f7420c40db6d89982a7095454d1c288ec83285644b98215a54914564d9c3a58e707082b66800d38a000c8106e5022ca0b7c40c41278d0041e9ac880aa2ec6517ea23c20c39ac96f5cb0bfdaea998e8672525a390c69d0a755870d0efd12b4810f75b8481bf8dc739be7da411a50c7b083030e55eb889006cd58b33a077dfc19c3b29cb5ec6a08b03067d08799c6c93af7396b5143808bd17404740efaf9a7e6b8fddc2e614803624803af90354ed6f7674d8b1a027b6b1d013c67c0fd79d3a6ce41f77e4de370bf39ae23c3b40e9ae19bd96c2b3d0b879006fd12ff44d03787dce3ce6dfc66c8ce897f636a8975f8598775b8bb954fdeea30868f52cc82305d4480d2a16b08500ad0a16b083f7dcb107bbed98d0ffb5ed38f96d9d0e7df8e6b411ad5868aabe55c7d7e66bac2bf6a4397913e0cf2f482845d6a1da6ceb5208dc965fba745316cfff4f9f8f6cffee9851cfc9d5ce8d8e905fcd8633ce7f2aac34f2ef4fbb0736a428a22df0cd9f4e1674e86fa33ea9b1f76fd793364cb9b211a07d2188b80f1c205cd69462606e6c5e4628b5a584a9b12e136ade50cc348aead14ca191c89b28aa2ead04584a44e042510c14802743f7639020a0fa01c8192040a0cfa075b46a008a902ca0a0acf4e112b7c9e2ca17f31503c8142c81329373c69e249107080b2b3458458dacc19f91412b11f35354f7cd06f0d1146f4e019e4709f08a1b23544dcfb8405fdd610f1a4873ec10108035a98e2898e951ddba1eb8912190a127ed4103185eade7b59b062d70e5d4dbc9eb8a1892c6810b11f35354d0cd1efac21a28916f45b43040afaad21a2899d9a2c2c2c92857bcd229fd32f75a954fadc95a494527a3bd8f8f5a63fbe765d01c5750590969cab0a2b3d7b4d73dcf6bafb78549ffe692fe54bc941c9bfa8bbfd53fbc84fff7da97548d9a1a783bd6ddfb7eed39c47f5f139f2f961820b2088573aa7235ef94df10860f40a04475ef83be09cf1b4de5a55381107b640a59014924252480a492129e4803be79c73524a29a5b5d65aadb5f6de8bb190f484e4e4736a1d35481f5566377837f08e701e0e788c31c60883a9cf979452ca3be79cd3524a69ad15beb5d3c38187831d1fba203975c1f2aa43e7eb70d1290daaf13a21bf84120565d63ab23c3fd22d2bc66901762d7badbbfa0481d26fbfa3c4339e3df7f96ef66fc8fa9aaeaa9e7947ec8c7fd863b9cb78545e5590c6dcaa4f9f40fafc1aa88f4cce23f85049b1a73cb5c258d7434581523ca99e8c950d654173c67c9b25e9f36f26d42b500d80523d35c85a545a1bf22a48a2229594c3ebf9489b4b65a434d2ceca2ed6ac93557dfe0d9977faf48cb8c81a34fc781c9e907880f8f337af39acad4676a515e755918ae4f3d52155356b6c3106630d138939c87621627fb5b55bb3460d0a6a05b5825a42ec1cfc15071d91284c08092bc9109652fd645d2502f44344a2322018d04a84d65410186cfbb1fe007942ec186fc5329aa57a52ab1651500b4a51aa274ba9b254cfeb0ee3987f511593eaa94819d2fc1a2451541ee931f21839a443c01ef38d1ed0fe2ad27c8c9190bc20760ef635d716942289ca2f89aaa878c43f1ff7a1ced15bbd403bc66fcc9a44da0cd521899290566f085a87f4f85e0cb6fd2189faa217c48e56240ad3b13b12a59228ec82d6bfd83f4f485401e33ea068cdaf491549a2a00b8aa13ebf5691a858adf4f9517b42a20a913e0cb5d748ebccb7ed2a1322e288816282d83e60ab3367d8c7da638e7d604f88e71329f6843c52b7415091a8b7bf8f24ea771589c23cbe240a49a29224eab791f5841475fb5e14fbab42dd3ed44e2c7ce33c1d95deeacc1a3968ceb06ff18ed9ffc1b016a8db123ff90461d86ffec1e0f8178305a9884c479086fd132bc3e8f927ff60e4cbbf0d4fac6e4f47ddbec7846dffdbafdc7da62abafdecdbaf6e4f3e746b751e69cb61ce39affd7b398ec316637cb77b31c6b82785b19df7de7931c6f8ce0923a8c7fb75ef48948e44ddcd235138b5e292244ab55712f59c9578314ed2e37b50ecaf6e333238e96c1d7e25f4982d6bc6076a1d2f3afe1b328a126458d97f79c8a43367c4dff9bf1919b800411af1a4d3e37b59ecf81f97d4677e4c2a17199856323fe8f1084650cec10c62ce7a7fce39a727c49362c71823fd0ac3bdf70af17ca8ce71abcd6123bd9e8f44dd6bb12724466fe509c1d99027c5ae9e8f27a4bead1912ae42deabb57ea8b5fe942ad2dfb66df22f760dc3be34d6578f31474a95e2b13687a53ac78c114a944ea9523c30b592289bbb4ea960e784e60cac6dff5519748cffd5f1674f889d63bf76fc485440e9596a58a270dc3112851f738c33d49ed1b6ff65413a5e50fc1c13db652a9874fcd3da68ff45871a47bf7dc19bfbf8b7ce06101b52d1e76336cb3428a8e3c7d5676a1dfa617416bc8141599dee3469833956c79fbb6f77fa838e1f0bea98db10624f1a78b7f4aded5e9ad498e839e7dcaab49b94deca0b223d2259e334ed3729e5a66d766aa9bd0ef28478423c215628a7861eebad75abbf5d7c2d967da66d9bb67d8a273524276b5af65a7b9d452ee7d7369d7d53975e6f9afe52b7b38f87a6cd2d6bafb596c98c43aca310f3ef5ade3779896cba6ddb56e9bdb75efcdbf57c3c1f4fc86fb3446910ba7da9cbe12ee577fbd2fdd24629c7fda5a5cbb7ba9f7f21f0f1d5cdb7a7ef09e13a4f485461f38478423c215cbc3924e902e8d045854fa742d5230f1dbaa6a8421f3fcc258ee3b89c2f7b1b63bdf86ffd1eb25b9c7fc686101956f5df90a99e3bf773a512572addcfd9389612e7b8cdfdbe250e82d94b5f0d3d27c2b03df73764e97bc81eb9df746f0e4469bf4b4b867df6b95ae25f087c7c56a873bfe3873bcd5f7feb387c21f7ccbf0ce32e7ff3759136d156ae71f26631f5fc9be2b9fadeabf5d5fade8b69fdf752ad756a75b5d6586774465fec3ea6f9966efebb71ad69f9de8cf7a01d4bf5acee15a3a339edf79079ce298cba013a744d1134e77c29679f1304b34bea83861abcd594f369ec608c543e1d42239de2c728c90610db669923f917b39c61d745ab41968a154ead28c613538c53ab2cb5c218e3c71ece1a1bce19cfd26955cfcf7dbab46d97ed6319c7523da99e544faa67b5497b83144552d4583bbf23ea07e8d06544a4c7fe45fe490dd7f915de2e0704344cedc2ecb546f8d1de437ed1a74fa3203d001dbaa4a0d2f3d5ec85f7670dea19ffc9713e1f3918ffe29cf527cf8937f7cabff8747289456ac59662a5562e3fdd7ed6b487f9978ffcabfcf22f6a8d936ffc942ad5935a659de346fdf95bf45720125562c915487d71dce55243ba9ced6be811b77cc638a54af1702d2e8fff86bcd99bde857fb26f6fe2a955bff4bb37c6c8f19cecb78fdcbc57dfc7fa3e4e0de99fc6b793997e0e3ff7a534e65e63fea5565dbfccb0cca494327e3166596ab15b97ed3ee65fcc9ee327d3eb977ff9e7c2fd944aa2e4e34ff144ef3ee6dcfd2fb54aadb6c6099ee7799e943e7e8e9092f0935a61b183842c1280042324245804394589692c7d4c63a9b57cc634b1bf4a1445038c86e66580b499fb28e986b499bb481aedcb6d48f9f28cb0bfad7348ae499b1a9b6813491494f6b5a9b4919456a1d401f73ff9564e18ee7f37543e5dfe0b1afb7213cd18dd87bf1de33d91d248a264d1ab52a948336af8c58baf3ac70b1a1a1a1a3b338331a639c28c6950e3e4af12e5cfb448538d728e35319ecedf3af9b5755e7c628c18cff9d77c0da7a1e6797e55226a7afdeced7b7951f5d9f233432f3e2f435e7e5e88bca8f44fad6241a2287f4ae98d41344f3f22a1d4f492a88f0593914451131589ea7e726f52cdd726da451245f3f3f76b1bf9bc788ce7bf23c673fe316a3ec6c7e034c4f81aaa6352411a73fff7e243d3eda2dbedd736923652ebe6ada617bc913fdf74346bc4807918f3dfec2f0fa729e65f384df7f9e8349faff63438c6f842ca1793a6b341637427f9fc637c4d778200ff187f927c07ff18a71d35326864d474313ade51ce42cc5e9046c63b4ce7d845d2663ea6379111fbab4432ff6da22e331367f6cc9d99a1f94d3423fff0befc8bc12f5ee47061ed7d1a1811c68bbf2f9e76df07fa0b9677d1953ed339581e3f4df7d9747ceabeeaa392e9b4eeab4060baaffe00f9ea8fcb8bcf8b4f89e823ea26a33ee76754d3b1678c6213a39bbd17d680a71f18925f69e5a9bd27f6a7cd54a059a30a5596c4da738f83feed4d6044be09b4e7feeadffe6acffd0eed39be43ff46a3ce8131fe9ac9a00f744af10402c08afea7499a81bf9ff367195f731a3a0d9d86628d8cc75e5a128629697b69c5aefb1dff9d8cffaff99f41daa40663c6d37ffff2d9ba1876647ccd67af08f62df01fe32dd03d7f1318d951f3fc4d20839fe6c7f8ff186f821a7eb21c0231feff34f98e187fdaf1dd738e7d963651e7a82aef883da5dc7c74d96941df07baf637a696e1fdec973f99923a6df957b9fc89e854747a9d8c4c49a6a7a6a40c6c007b3c6bfc6398c4b089611f8f44242955aa07937124511f7cc9a02251988c2a12f5e229cccb88f97f693f31a5272256970fbbffdfd1fdff4bce77f0efbee33474cfb90f1c72c2fcf7d292b1823468cc7f27a27f491bfa5af7467ff454a48d8c2319482efe9b7d4686e667302c4fed4537adb516d37803d206c32437b54c44f389cdf2a616bc914fdf44346b744f399a871065878036f45d4c3bf917a3ea3a3c67e47f3b04a4f6273fddefa2fb66a7e15f0592757b68f799eeab4064baaffec474dffdeb33759f0c2a9dbe4bc7d27ddac763973a1a3a12489b287a50893c3c28f6bf1ea9d391a8f99e131bce19704812edcf02c98003fbfc4b658d7ff89f56a3fb6fc760fb5da7c919df4139237e545d0b3467d0977bc80259200b64812cd08daaa8028a3c2b890a626db4402fba8c1511f667813e18e3c4feeffedb43ff82baeb641ccd19f41fa953192b226c208992424312851fb3456c903d629158964d2251925369036570c0fc0fe32e5e14f55f328ee08d859ae61ec21a2722195c98ff7940dad0bf5f54eda14eff44249f9e88f4890846978f9d88ba05eaf4935145a71f2d9771e40d617f99c56ae59744e124434e321489ca44b948a224ef9aa5d603d286bed11195af92f456246af20d481bfa300332c4fe451db74bfe2f4883267dffeaf4ad9e4f02f954d248e9661fc64837fbf2350f5401c08a46026005af3e6d9f339f4d67ea587868b76046f45ba9ea1c2c9f69b7a3dea512f62c33e68cca98332aabce51d238db36bdcbef307117bea38543ad0304f1ca5755de115bce90d4e3b3f8e891e5659775df077ac5bed471ffd5a01cb8d3dd877bb5c9199531773680c8a88c5193f26b3da26b90b489ef19b1e3dbc71fffdefb3680a899d7cf38e595470dc262b769f6da524b82174512326b6bedb0b7134ec8eba775e841b17794add9e8943e02ae4b0c4d8d4d0a54839408cf5e3ffbcb5efdbfeca392cf0df90c91a89a89a8a691aac6ced9df788f481492d8ef5d65afcc283ba21205fb4c056fe257a222239decf3ea31fb1df9334e8391cb3f1cf937676781e864aa9f4ee45389a44d91b47949af6867f233a49e2575a9718ed85f0cea58557df4c8a3aa7a9d1ff70fbe21c31a38e4b560010fecd8400362c040063c29fbf24ff3a6ecf8106768536c39b798129bfe9450f607873c28fbfb39776c40a226a70d8841a22aec94d22e056ae177786535423ee1c89ff433fd537c1f1df21048aec305d7e1422ee15eafba0409c92e4142ba4b962cc14b2eb6042fc996689c483f6b2963d4c253e229f194784a3c25d8122e335ed1fe32211924f41c6bd6a8aa3963fe6ae5e3f353815c7c84b823eec8c5873bc25eaa8984820c6b3e2ea8cfcf9e13bbbe9dc1f66595582b0322fa01fa01ca806806d4e7474eabe48294f8a0073de8410e0f092504f1606b6d7fd6b8bcbd1682b83d24b6c6fdd634fd59dbb4bd7d49d33e8d7b486c1c76eeb52d731e9cc673f467bdf7f678e021e121e121315fa236032a41ae30a2f66bfdfcd107eb629fc17f31ff6638eaf7af8f1541cba7fec81c582c168bc562b1582c168bc562b1582c168bc562b1582c168bc562b1582c162bc9dbc1b6e228bbc2a767af5da1b20209cb6753ccc3e8e73a99d73a195f5b51a4eb7f19e2b282a788ab0a22322ff9c743bec5895734eee5732f5fdb2fd37d1b17f3325cccdf90bafbb8df5c9379fd1c274fdb6bc9bfd3f6cd70d4e57f331c75fdb0cf70d4bf2de665b80d2176cc6f9e13f3323ce7e5350fd97d5c0c87d2c6f41a7f79f8302dfac5c4f2f535ff5c5a5aa40ca105a8c4edb556b9848a46000010006316000028140c888342b120c9d23cadba0314800e7a884e5e4a998a24c22046611405710c62c6180200218410119a199a150016746f29383d0d840dc709ec8cf6838b134d1662ae6aebdac3757f84124e5012adbefda5b5c71de54d05c286ab9b3ecfb47f2327e615f4b7d6dc88bf4d14a6afbcf4e5af7fb417f7665a5fe48f5a062b9e70983c97fed46c03ddd643afbd4047f261326e27ecde9414704ac0d2283dcb3b98616210d049210816bea8a0a1882156a616c4b7f18cba3e07fbf48a50062aeba67dbedeed8493ae7b00a2ea99e4a39430300d02116bb548e5f2f0ff7610117965a0b09048557824061c4367148e4c481a18158ebdbda96bbe9cddc0fad2db5518a617674b122d490195f8765d2c227938a6f93a090cf5d220110d8a50d8c9492b3d2e0732f7665f6749e320168770424e02df44fd78f7e6bf6e64d97e2ad8cefc94ef6f79a5bf58961dcb8b5fa33efc2e7da567bdae2b756f158725c963d737c71dbf14aca4d8156e7aa2ba17fe86b48dd4cf9086b32a7edffea193a8b38b2f95a063568b29cad0b0e4ba770c1f13a2a8527e488870b7b1f1ffe46c0879ed63a7e0b110826cc8cd794daf946ddc097a15f0a6c2b0e0503c6d4429d07d84f9cb85f8f5470f83eb019a824d3ccb0758ecd01f6fccf2f077ddab530c3022563f46787999e8ff633a1b1327debe9fdad829d0a2faab44fc1c6c4ab3cac76c1aef87973a452b43812fd9d1712f7c1a983510e740f76e26f5fe90dc425ea7cf30e6eaef343327a2322db876fb62b1e4f3809f0666406981e73f27b374ef8b902a6e105efb7d8c869a8f3454a1647c64724a66f9606559e793819d87ef044cd152a4814dec59c955068c7d729aef69c87e562092e757c3cb0e28680ee3a16a90cd9b7b246c01b316e91d9a3df33d3fd248ff54808398b0ff496967f5bc6e853d12c0aa6e1681c5f38b2dd90798eda3637925d441b822d86280c186379ef000830570b9a10053a0d82d91f83b05a093df6409d501de73fee9cfcf6292d0a6a85c6f2f6f7f6c20f0fd2c7e09f436fd0a32fab4a167e32108428061bf1d7e0f30521820605a75fff368a5f8be7f94dde7bf90298969b9d7ab504048ad1a617a814fe3a1e4e24d1970a1bd9363f2e0d4a6b7db2b55e2b3c0d773bb1180809303791de6dfc0e4712f81c0278e140be549303d336a1f842cafbc1b087c4506bd0217987314f0a3fef6047de30a5348c188cb4957dd57059d34179510f5adbf74a1e26c121025f251872e8256d3dee55f187fbe247ea03eced85e72f379ede6c655353d18cc5975319ea151d34ffd24ee1483299fb71444a652a83a778099ebab75ee4d3e2061d40c99aa8228846ebc215f2174e1a7ea319e614f8dba0117f0b0d4ba559d590da289310774ff8198b561c4571c59edbe16ff5cf2ea0f5a0280b362242c9a6f93710677affc80a587970cfe175e50f6d335d158534858600a2286a29e39530b8416be068029be67f53d69ed025b440865c11085050beec8cea6c05137622435c361b482ae4d672d7d5945addc570683b0e40395ea592b28aad340b842e2b1b9f93068fd02ebcddb89e24bedb69e2372142b10c3296c918771d9d075bf5c37ea8cf0b97aceeb6fd3c97733ce8773c3c932239135099563803d683b855aa67e5e1d58184fca3544226bd5e3e9e8830dd24f4c155a8db17e30deca4cc48dd6afa301c7d95e6cab039346aa44ff06d560525bed1bd4c75c158ce9a65cee7c98220c11971ae640471531d610ed4fdcf8e1c2d8e704d449931ead47118893c3f4016264d8a134806f3010c29a3316f4c5c8ace1c06f79eb219163f9c68a477fb1acace17d170768ec8056cfd71a551791b2e5705d62fdb226de8127662e3ed264466b587846c24b2a7116f58bf6e0db4e1c99321f1958980e6d81bade5450b942c4ac969590f926bf847774771d313914a308005eab2cd6aab57dacd5f5fc0ead8a5b7a78036a0fdbeadc8acf5a884771052f19c27796dfe4c4a95b04220b03bd88d7be24a0b27711c05bbcc836ae40011392dc2e22ab0a89fbbec0d936429ecedcfcead7ca18202f3bf4c920b62d44e387bb6be47de0dd71e2eefc84124413710309570143efc45cedce0117372179a2a80f64e2d57face0223f4666a1ddaa857dc2bbfe5ffe9f59732a92bc9c7c22a04ea233c8d11f2ddef343e9f6538f70311e48ff3d1d1a81f8540e5dd4694a5cbf13dc841fb3c86342b49c2c0b0515f6b0ca6488a2d3cd8b6a23fa1e82349c0bfc137d435b57f05d2c539bfc6b27f08703ef0ea147a35c13bf4c3a7fa7ec901a667755c273c94445652b6cce154df5020ec86b2556189d42bc4df0f5f03333a3d3e2dcf2a17fabc5aee8104ba83fbcd5cc2ee539e6120cec9b36eccf876e0aa967c24880f8cd5f151ce5538effc77d6d48c2c4923fb1805603c8eeb0288081885b67b89e8b5fbf4217ab1afd4ddf1baefdd036f6c1e195d9fdab1262d34c8b255ea0bd8641a2bb5a62f631ff7aafcdfa36821cdba46f0769c7978348994f884fa4f667179568557871518c1f03f83c036fcfc3118d572c2e0f25f8c09ee212bd9dc5eb96b37ef1bcf5ba122bbf7656a7708131afa8d82ba5a6c766f3cea2070a36eb498215551be26d8f2cf851b1aebdfba68c6ca7c4fae74a83059cee8fc3d1c939f7e3a27d8732d2823a8a41eb8484142936e7c4295238706d9c32ffe589453b40abe4113e408237d41740a2ae223a8af0c526770381940fc45cc879181f6d545de69e87e0658bcff7b41d32d19a81473beeb959f80a5ddb120777e8753b4bc7b42fca70813f52cd3c01e5da42a19eab6dcc5b8dcae70b37848b804a5a5442da01a38101885cd8d00c3c78d36d2cf53c5d81b45f809a1f89ae0f2e72c3a0838ec8c0056dad64797b876244f6d3d9ebd9296d713ec88a17fe86b26dccb145ba693af40ea1951107901ce8cf93d65479ff394f8fa740cec2fadbb8eef0316b4218d0d7a8df02199834a11441e213d9df48b39654cdee648f815701b66877f99b7590ec7e73b766932078292d4ef9a7ba5e0db1bb8dcf088e48ca33680d4d5beac44062ccc316703691015f00915678911d056faa79a5b178c494d43a58e6b926ba2db91940f04a999b4b162dbf8988df8e077ee10678f6cc3bfeafe28c00f6b1d5742d997e0695f70d2f0968f72ebedf55ed870c95ba78bad2aecdec7110be19ec12e0c916bf4564540abf7848b9367a7245b67f38ca5f7f15e6aa980f11cb7256e44a08832cf488d17c9a7765f1926744c8924b8e0cd239d1cc860dd166a6db4332c2efc46f0da7d7cd89062a122235f82f4346cf55f9b138a3c2b4e9fcea88077bfb1b08f93ee1d93676af5a59f7b7b32cd9e8a94b9e01969e50494dbf33a8cfe238395ee058f9efeb02ae94524e6479022294fefed7a8f9c58f10b582eb8d57280112c30b0d6620ef761c0e4d86a4ddaf45770b0b660ff5535fa75d29ddad0d08c8a511d0d70626217072c4900fbe0191a1fcfd0d82f288cbffc656ee76f1dc67d60143acac0929229449b00b8f1478acff452d1051597a57a306a790c0c5d9405d880940da9c7594276c55df5a7aec41fe5f1f8bc9f5df679d93a8d8ad4189418a65bbbc632fd630ef78ac2aa91ae8d4b061351b94f3b1fef4f31e5052b9f2e48b7c64032d7b008670d064073f1509a2c7204a658084364ffca156da6580762318384307be631d2f8f1d28d26d37d44a1e8ab5cef2a8eb8507bc6e6080074ad4be7ecdd960614e03eb8f1781abd5d859454be80236cbe3aca9aa3c3e654e56c841f24aa756a1f0e40ef5293920cc896b2e6b96f7ce652f2bc85a6f88b3122dab401456586557aa865504975a42f13ae8ddb0ec542b4234aabdeaf8068e079e5ca6102ad401434113a9b835078490b466c4e71546814bf8dc2f1aa44c3260f9278f063e542083b7ef790ee48184e0e26977074ab612b4aef0c209fdad25a4fd14f8e0959a97953b90701d99214726c947d2a8c5ed4c1841cd99c49b82df9f586787a40157709a83db960a871ad5f04304650b3fba464e1d2dd31bcae22a3a6c58caf20c44eb8f772f8aff0b05d62e01d3d3159eff36710fecb601110fb761d5207854a3b82f70d3deee36a7b68fc43ef2f7c16656a2a95ea2265005a94c1554eab1362196743455ff3ee472faeee4afb63ab62fadeebac6b9077a9f218aa228e0be8e28edfaae5fe13a7a16cf0fae1641c45da46e33d62537b9be7dc6f8241d57f2489d38617e22c6c0aff4237956865d8c7ed1952ff8ea3cc8e3ae44b007cba3c9bf9d209b83e4e15c801d251cbac5c57bcd6b4e0f7118a21a56771264921b3826c820d17ee9abd924e7cac946515e690953e0853856d2660f52025ecd66d85c5f89e7308d37f71a97e9a6ae47cc98f922cf340576edafc4a889176df848dcdd247568ab9c84babebf072f218bf3edafdeaf8111ac3db6aa62e9ffa18109ed15052aa54dab132a1dafabbb9542b219cb40a043854953603d3de10f8e0a4ac977009936ccec845e87d586590c79702c387aa2470da9b359e9193997ce8f166c4a9d403830853b85b4ef643ae7db2ac0235f962b3583cac655662c196622b3c8e9f24932a5b36155dc4709f8779c399594d5c22ed6e3b5e43b09d6b590e666a7866e2b9bd7f1b646125c07daa5d011a7074fa5eb18979be52876be147c248ec3ae45cffd5cefb2119cf2d9b29c7e850afd7273faee26f49211afa0e87189c31df7ebcf11f92af03b5eb2044d728e084f2cad67159f067ad5d34e3108b13008a2f0c23e03e79dc37aed53eb30181435c31f6e27f7a530608ecc0eee2a0be3cd01fe2cf6df5a64a038f85a9bdf8912706ea56cdeea893fc40e4b4ded585c3aa3e5a665d9147362f23ea2848117105a485fe83c27474d3b25121bc8df972e74bb3d0d58184946e62f2c0322ae155dbd9f43e7a12e96e7790cc4ad1e2fe6db5d2c9791cdc458190579325a7224fded9e77bb099b17b7fd908563270ade1c180c4672bf94af64731434498390386d50ddf3f31a7ecf4d8fe8e34b73abbc178b07d9b5370383420e690b7a4b897269e7d6183d1180c7b65d8516edce37d2bf2b30b7036f1d111deb26daae7a805632821038e794dd4b22a81fbc84e3788f9722eccb2e81ef6847db888e1125002970572b1ad015ed08ccea71d72a141f39c41ae2d7d9341a83710d4ad3fdb4c2259c3ffee26a6c815d8dc86737d00f81c392dcb3ca2a85f5608bd5e22799e5beb40c5a8a2e140cd6f50fc8f0c73af029527a64b07b4f4cf0046f50c2331f73162ba1b592f4e3aa2cb87e62eacd8506468de3900ccccbad44eb0f009594cc43e3177d8234fa5d756167c548ef7885b38f1c1c93c3cbc6457548f7b485ab55dadd36467d3fd106d49cc335322b2ace62d7d7442ebe8a639442aa5eed34b82f5bd6ac0a85bdd0b95daf4affca92d65346962b5facfb452ea0fcfc6c7e42ecfb19e7c8b8f0a8948a264514951901e0836ac28ce1719e238e45110ac7d5c05bf6ca6d8025c31a12935efc5d1983b893c94c616615443d8ad994bbbe7db4b103c74195ae20a9f55dd62cfe1a3d9baa3a42b29f5b8acad78d217927eeff1ec31d13e8c5bfbe22df6f93fe57bb7da7b6bc4d86eb46f5982b6f251595b9133533189bbdd6dbb0c79bbfe6c144285895ee87ccdd911424c8a4d6239b51946f3addc948af972993f27d22e9fd2457c18b8cdc60b4e02dba79c7376ad74e9d4f2181a84ff0f0524b14c8d9a558c005614cba3cae1c407d90d213a8814c064e5baa8a32e6568ccb353dd57d89fbdb881038ffb24846ffea6d2b65eff1a3ad42c17d1829b14ed48cc50b966a14074e9afdbc20f21f88d957bb7909343c3077e0c4adad665a1714d0d62b4450dfad113c9b3e7b19c8fcfebb3ccea3190cb80875199a7f3bb9d50910b6ce202c316a96101258c1dd4bcafb75663ec5964eb8547e9169ba93e970b58d0ad3d07468c5afe9961717339f4b4bcc7d3d6c969340ec9a4ef3924511c9519d1542562f364b67f5ca19e39cc1995f57c2ba6e665dd37965e32dfbe08d4bb0e93210a77f65a9952781d54772764b72ad8c5290c5ed2fa19325429c8e2d4a7462cb2172ebff1fc0ee74a1a14a67bbaf9c229a9c5cc2f6343ad2e21419374eae015f0a4cbdf563a56f24308a96fbc1b75ab1f8ef7418d7d49d1a9129652cf6749679fce9d8bec3a04ee3189c451aed54db8c16a418d9de22474d9059febd075b45677f3f9558ba2c6285b8fb6087ec5a947903fc08a26d92c3e34f82eb49c74aeeb1cd79afd81ea5f58943a1c7e52edaf600918038b20dc6d6ff2cb85ba8b46b165c1366e06aa1c2be3990b5a86267068c6666c0d34ae5182deaec9892ab1d4530d02c16fcd4e3cf502b4910481aafdec353fe95e0906d83276d1c7267e6ee224d0b70beddca1f20d158b1215a42b6c1494fd5bccb05b69dbabf10b678dcf9b81a68746f42b6c7bf0350a96d1460a1b6a8963a957ddf6e0b0aaf2ef6202669a57aa6cd0342aa77f54c63c1ee8522da1d002fbe4c178e3dd32a66d917a2578a122ccf34631236b5b274c8f0b300a3b1569daf66b91982ae65743a8558e98a6182835c2aac3c7376c3a35ce9e662a3ae634048bb0285e8ffa7a811b8816d1053a868d644d80d8fac2b341daa34298e7ec31af6870b962737c52034f0a4ea867708ff132ecac6db2cff49d400fc847d68b1ec89c6809f0c293f24a4e5a717a0905afb660b135d9ec39d7b82065c739132ed04544966e7b783b2f92add39b22854ca30a734dc9ddc25988a6e172dd11611cb1e2c567a438909dfd082a770fc4a57de0cc51c5e8bff740a59dd812ede98261ffdfc2bdac12a716d3d2375133d0835eef0792b99e09b4f887919b9ee129224bc5f2929068af88deb0dc8d05d4170fba2f11be1b76873330a668558f69bcbfe0fd61dc0af3c1ac57b92022f1d345e8717e26708c6029479b13592612cf2b893fa8f5fe1e987aae703de3fdd74a2c713e39a950a32700c1220b6e9435d99fc8150698f5930034e1b0ab9f970b71347b06219ed3f07873cbec3840cc90ffd585b1539f8f8a9b7e328b16c2cc2eea16f1169311f2cd0da8b066f591c3fae37d5c5c866694e3d41bd96cb64cf83558a33cbd0e647df6f81352d3e1d4447aa3e064cd08a4337c16a5e13d2731d403855896eddc06874044855b390193dbb3be9f2db1b4232a4a1fe3750034effe6e4f9ba33db6fb157689c581d163a0975307fbe316c557d32b7d654ec995c89ae19756b2ecdff76c8a10c4f1b6a169c054af196c377c81ac281b80d150380fcbb06e8c0e07df372d9d43c3005fdbbed2c60fb46c228cd621f092ca269324dad49093e34ab1fc0e359ed9e017e596e8b46b2ed9becb978c6a3904ac896a4635003ba24893ec6999ce8c383f04ff74d1591a2d2f700f4fe3037f0a4fee8b3c8133882bebf0acd051f73ba54a4afe9b1f947bad2f7cb530a00c98386e6c65bcb3671f7f06c10c2d3c3c67e668aee1a3f4ec0fc944116bd19af5351b5311b684354b58de49d2fcf29fbca854190d6de12a280634ec90058ccb857c45cbdbbcf164752091df17523e62132650c4454f4b83ae87d0c5e78eec96c77f739b4a7517a42777d3b7d0ec2b322b2c4e9f195ab4e839afd81d326f54f09fa0665ea4e4d7d7d361bb89a88901b1b5df8ea9c1206cf39f970c7ad22344312f0644c25625fd7f7e0b37e543667684cfbb9ab18ec542106cf8620cc9fd60e599fa13a16cfd115fa0f8dc7afae05f3d8229771717be106d9aa72fdf3139619837b29d63f65a922d13097fe4c21469a68e0c511ad7f3106c473739d800e703f422640b91e41bcb4ec225cde177eab3606f793a9610d48563392cc927441ee32228a4509538c89ed172502fb32d2674bb268dc3e6ef50d641d4d3e2307abf3cac7f659f820b21327d6e64b4cc058b276d8f60fae2e9ea47ea858b9201aa10b3399820f73b29dc330128d70b0285696ae643944dafdab372525c7b2ccc21ab719316a6ee85b461b4a9f600ed42ea38bca80f5ff9939115107f73fbc7150460ad1f9bd137de19976e73527ff1359cc42edb130afc18f2efc8319cf8d1fc2c91d7c12b58b2a1ad1218cb697c182169b75c3d807bc1b7138f42354d6ec476f7ef7ea241c5c66536d8532e01d428e1ea1b81be6e70a8829d61e73418cacca4b5d8744aaeae666fb866aeecb8c609c158bac7287b009b60b0209024567a7fd7a47d431a414ac4816a3fa2b2f114c2b5fe105eee1c54d404ab9ba502a016523df30ae708ff487307e0a1d9d849f7b0534081f0f74e58ae3df57bc3bcf5ccc22d05a6ce2571b0b93d56cd4cc5761982a55d91e7b604eb2d10735b32cd2141c462745e0504a02bbe94788d18be5cda6129906ad322e5c02a78afc4091f8d50d07c71454ed7a498dba01733a091c7c9c3fa6564af770a7ab5c425566c966db22616591a36be16b931b4fbdd2adf7326ad89450160ad2b1f7cfe43625a3e729abbd6872b97ae6b9caeba459a2cceca813abcdb4b143ea058cb1327db3cf528cb6d784d93711f7c954e6093500eb591b7336021b1a93ff39bdec478f0cf357fd8f873ec522857b170b5423f94bd4d5e3e2d6b32000794518591c4820bab0df0e19e99816cd9b391937d335a70e6fd91d411d71c18861d16e7edf883c8790666093f4bc6f0e893669c84cbbc3ff64b8852d5ceabfd7e5c382879affec9e32e4e1671ab6a4c466b462ad7832a5a9c407a5fd940eb4ba7382e689b68282b458f78f1458f9e629c99b698251067d8dfb7cbb706562241d749fde02f25259dcd5f3e60050044696af814df2cd7a07e86f886e972d02c62c200ab73b15944d7bab129584ee3b6fedb7bb3617de1edcf3ababfd3bfeb44962c97f62c0b66240e55ccfc04b16746f7f59f15e4030fd50d4063a2006e34cce18518df21c05c8d8fe9861ac70879c3e52fd81b8322de0e3079aff0740527d1530873eb1988768c4304c7d9b3e37ef054bb117a017d58d64e9c589fa64c5fa89013a106461f3ac25027e53f5e8fda123df454a53f2c56984c94d1644653055a906301627a33dd53f8ad4282dd495b48eac3020060d7a802f4948ba168bbd70de3c4a15bca102dd79e59f97f4b21e978e5e60129ec524502d1aa7f1b4ba798d1b32f443e8ee6817a65eca4040204cdc43d9de625d88c039779851cf04d480a7efacee1336abf1044584975f85af493c32d37e6fc79e563543a16382eb23a3670d804e8f861ae0892090a8a098f647d78738648f210ac9c72500c6b869d8746610dbea4f7f87f5f6efa479eb003187722c1f030a7366360b8e9856ef1183b756ee565a488abc77866e87f7a967f28e4e72b5cf5264f9584c9713fb05b23624166d9322b4234d068ba464d693941b34f3d2524afea11953cf3843f6d16a01bc0745643af3013f35e1377c0169fd3374d56ac005133008404c29423b23be5df5b8c8e8eb331e6891a298a6a5ec2cee8995325715cac3ef3a8d3a1d1d5e2a3c3fab1ef27ae298ba0ab836abac101f9dc4e5047343774f9a9cb810020dfab251c58d33847d4d6ac33d13dbd39c0a26140275c3a7a0892e3b789687f3d78c24c5b5283e01e03b87634222d2b56b61555d1916f8389935468982f86798321f62e413ac608086318e21cc555e57acaa1282a7cc03ea2ef2ba7f666bc666f5e8e7c6661a0e4c562c3abaf79eb217797535caca59984fae8adea9d6b6d908cfbbc0fa32670c06e105e3e2a84f51f896622ad9e943c79d3b4e4ede9e40a30d440afef991a143ab696d018d96090d6741f3bf991d18cf6eb188cc154e1012f901ab806e3c7bdfa2c440d57c0e7ecaf12e720ffe9bff21d32ec8c51867e03eb75329ff2baeede0bae2762fe5ef6e14a6f2e5c4a4211b85122de4c31400e29f1f60353cfa9a8271961fe87c8b49327e899b82b586a70e0dfc906d4ac9a55144ec901aa69d737634b6138fc48ebf106ac246253bab965d2193a9ae6b41cba4637bfb24a3def3bead22799eb0c892f5b942e844bd9270565ea987b53eaec3712da17d8d02b122cd018b7e2ec5bf74a5645189ef94071cb72b1de6a2d4ad1cb793f472aaba35d85810d84efd0d0a0743d56420a036ea3e5e50080b0bd90b28f0d34db804302654b1bf72d0546ad662034bd05756d4041c43da69105631aa70882ca7d735fbf841dc4134cd6034204caac578f7e454f8f391e1b86a19602b9347af8dfcffd6d520b4a7e9f686dbc774492073561759add12ca4a72ec34fa6b680923ef80b6488aa15c06fc5aedefba624f371cd356488fde14dd275a752639168609bc9c599e10968344308df29f241bba255b04ae7b599c49a1a85ac672e75e41b3b8740c7bc5d3dad53a67f7c71883ff4f6b196aaa756ec2b65892a825154d42df39a088447287d2b57b153418605f88fd12fdf6dbd953e9df8e4a7eb8b6055b839dea4c2d97a7876315842aba14d442852a1e77d05cd1422249c8c37a4e171b2f4385a1bdfd4619d79d12ce3c792fb1f6981c9061ba22b64c3d2b424a194d3cfcb49fea34849709219303ba19ef500ac059cde62b99125c4c474deff3b312170cb44d8a337d05f8fab0c580e915239c7a7a453d7f4aa264fb0ad5a5683c647d69a56ce2c44648438d2291b01befc6ad122dab84704576abeb2dd9aa672b26016b832c8dc0f08385e221bb7fd3af45aa74bb3b659d77c1733b92a839ef11260a8532d11b6a8550d462d561091a02c7cd2f3840891781bf6564f7e7e5d62c206092d4d68715c6f4f498cf84fe945cb7cbc0225656a2df9f500494f8943d867175653b254a0496e227fdd85121d036feeb3396b5802b437384d3abdf5a09bbfdd41e969e1380e30d293191e4f36a8ef56458261207655718326afa2204767ef9ba1fe84a2b3f4127ed156719e89e2430d342361c579c1ac2c017ae24355952220b6d3a7a402047a758c4b666c038cde7e38056fcf7a0014ad0f01b8b399244fabd55dad16fe2c803a98d6c1377a3a56ffd3577c876e2861df25b56e6b00f5da31d67c8d5ee7e20edee3fd526b32260d0cfe63eb70478bed74236d0c86eae7e2959d09e9f075e8c7c580f91aa81fdd7c9c0547a33da6ca26ca904356ca2698d643ab6ebbdc390bf3d4a3316cf5bf17cd9907d02fccb45e346c07ae9bf0c66d2586b18021411011e8596af42ee70997fb4efbe0b1139d713cf969b972d2e121ed17f32a174e436d1410389d76c7f8859713770d27a45dadf0f67a9cfb59a4acf800986a60d02be5f65596c5c143428bf1afce8cd163b93adb2aa3d918a57d2682636cd883127c6cc50b21f6c6531bc8e6f78d23c564d643c4201044261e922ce5db476abd3faf73357ab4ffcb7f17b4ff3c17db448779bcb17bdf462df7671e906763a5884e15e34c5d2d9c7305b02193ba91c6475e3581afd7631da05cff357c042addd71db71eb3221c5a020b086f595c2e25f4c1141058ad917000684b972d33f6ed73136b292f9ab3cf6536d84a6426959bd0dc0a01fe75c44096a845f15c5d9c3dd0e9e0b4061d4251867c1cb869c478e60cdb43efe3ef597747e9e4a7c6b03b0b3a4d2dc5a21546accfb5d4970c20711bfb09b8e36b9a4569755b4c538c024585deb2b14adbbae01b208f2f93772546069c27875fbfddc39f3bee901610358d1da045080ea7bd1f29083ebb2687c8412ff9a703eb986143bcc9c6de02644ab9a4aa257fe62e265faa6cc0218341dc5d96eaaf5a628c08dc123f0646d58386e7c2794c946c2af61e4d595fc6f8f28c0e013b39c4262ee07411f0dbfdcca7ef0d7c19ceb2346c58486d1fef7827722c014eda3e10c6429f396ca2b9740053042845ecf6f78aa62866db7d767b952360306a0230de0d903158a624e24340437c6e462145fd804bc04067b69d0d80fed5810c91ed1d09039507b7d1c418c4269ecdfa61f5fc3fe1a71514d663cc4d794e6e6c0a9bce7bc42fcabae0582337d5127e523271538dbfbb0a864b1f10efc42530b409a8b3d7268fb0d24cbdd43e079c8e019ec6419b39ce3d8b5b66047c173bcbb105a8955c5e61d5948f4900489cedda2ab5a47d254fc65c0b721f9fdf322e5afa3d6c4299e090ea15cc924ed2e20c5d6624e958d3f6f86607cfcaa59be49d7a2da68195ebe40bda5895ed9b55a797bff32e02fed511ae16c6de1a37f44d91edbef43755fcd851e6cdef68e9791d0ed4cdb9ab1193c377620e50132ddac47dcb914286c4eb7045c43c5c8e6d38009a2f6e0306619b97c37606845a09018647974a49a0c78535cc17a90d6f5270a4385aa8904a826d48a220701048b54a275c67a9de7fc6537305ac3cd3aef1d57bd60925a64b05a641de708dd51221cc590b8ee1f6eadc17e128c000f6b8c1dc65f585bab50fb96eb787b51e93deb27eee2084665042d4b95bd06b326f0492f4d8a75b506dd1fe946659b893c001c966293e1190ecb5683de40c8fa39d07ea596a6612f2fc2b90da6010227635d5bf8b55f3eeedf586fd5f854313c65a3376c31491a6289927cb74c3cf45cfb6e3667fa7628a2b312e79b9a8e4867f3b7eb1317e6e9c34ac083bd577783db5424b119cc1df58948ea4dc4d79ea68e5449ad0a6d48730a75e6d018115f9541532ba4a9f9e0823ffdcd8388e9ea2e5b1634ec3970cfe76683453f7b506a31196371e91f96f9f221ad2062740ca5f2cd59e490536b6f1811baad1d24765d41385de8102e7b52f5e8a4600d4a95698d06ce2448a14e0d771b4c55908abdca3430d645d2520c7409f7aa922a603f9dc5a684b7632ffcc39266033bba05921e9d158062cac6164015f00db3868888acaae727b51ff7a961a6d88ce0b6a2dcb9d178bf1ecf4c9903b2bdee6f944bd2c2b52c15d0c8f0dced01be228103d3ebdff011dc2ddd719aaa1b0f5395db162aaa37c8c7451d7a2b1db9231374db4d544382510b4fcf811c86d2848a2c06a219e9dc21a844c65e5b1dc8378423a531722b44db503b4269a6d4381aa311801a8ff7b707738ac07e34bb243e396bce6d6b64233cfa179648fcb55689fcf2a22096056d8481083aa748e77713e2288bed4b3f51e9709233f02be3854cae2ce206acbd67f4bd9ef708c73aca894bd756240e94340164be18bb37f909c601a92725cf2c79072d9dc57871781486b9f15fbdd82289621352857e28549778869b7ddadcfacdaf96454f72d3d87cab1cd6b1b923efa100fe7416cac92cb13cf577e7484d039ec7e5d5e2af2897815ed7fa428ca2bebde590d140d529964754fadbb392d1654d556ff172afe4491f3abc4d3c3de9b2b04ec3b51053af6b562673976b0b048844ca1def81b465df6ccccf86f6b0f862b10b187c1f38e35917bb8a9671c85f9f7f91b26ec52f46e3ef00ccdccaabbff03fa07e4bace15d6d0d8ceee0504796758c61c6dfb8a765251fa62d1d9fb23e401dc755793610693e875184386f82d1b2946eaa8eec5c8907967597bad25b2bcd461ea5775e89ea5599d86b421bb0d2f00418f0b211a0e9d93671a6fc38818099a59d37451ececc9e9145b936d197203e47c242678d663498736d1895f0857e238c9c2c40db020e9b186e53d954bac50c325bb2508f558035805c1fdc8fd69e50139cdeb0235549a5980d33226d814b24da58c4b8bb6da1ac85281a0c0eaf99ee99b85fbd5aed98e6df9822cc24fb12d699ab7e81ccb200b820573947612d0fdb21fbef4e3ba0b22ecd8b61cb190e2bd69e93a6415c20ab5526ce0b58c442c1ba5f2f6abe1736cfa274e649be78f4b4db48d258d8e188ff7f123359b89914d546e7a911dd3ce1cdbcf8490982b2acdf22b05d1243208e9e958aebbc8b1a6264440584a7900c0498aba51271495702c097ab873165babfa6347ddb2ce944402cb487ce4b981fbfeb76b354c0dc9ff6f3338deb8b1ba9e827a74cf5e0a67b7b1d15f9460d9661b7bee425fd3c216f060a5a1b01cfd9db3602b985a7819bf91e2f377aba1bc9eaed819552d91a3fce60d5aff67f11c7bb67ce60635219e8dced839918f1b5b33d540a2e422fabc28898ce387e78128302ec185c965e72c9c7de6c6927ebf52fbe847113db22b93a0b37d4c78d26091381f817929a2060e9e68cb046085af62bb8f45b05a39cc989da0d9e79b8a5559f986bb2e615d457793a5d9719fb2df9319bcb13199000bd25a8da4968944af8028039de478f28a8b7c4eba8a6f66136746eed85a2c1aa01631629a0562b31618664eb282d6ab52cec54cd5bd3100ce7b8038bf8c7ba1497bf2aaac7d98426dd85f838823b394dc94acf91a83a68e819260e990c2031f318a01de1672fe1fe421a7e32f52107c8f515031b5bddb0628810107ff991efd2325bcc0ee94dcfc2912a2c51e286ac8a4619aa0b74c5c89515dd9ba74bda78d10b41088074b24b54286e32aaaa59a0ea7ca8fd2f921431f83b08afb9c874fee134793230f8b47e23e577785089a8171be57c980bae49525a0d89c917501af40a35006a6952a12d397571aedef0acdc3c052dc108562086c9337b8f0139b707280e74cbf5f93fce1b0c5f453ac6d1d64eb4e607ff57ed83028b1b3948618b6880fdbba6f12e44894a80e20ea75c672c959625f1f578234895ed87d32815c75aca312963112fdf247e87762eb38ef7d620b73f42563969956c47c8decc4e7ec6d8ec1ab22e2be61227e7a40c2503b7048ac4aa8f527aab32280c14668eb87814f5c1e6b3e6a09f0917327606ed30bf837577c5d2202102b27e9e08ce0dfe0afe109ebb85447f9761b820c9f4387d79f8dee35c4d63b07e9d57e2ec7f169c4ef37a1d865f061d6d163ed3544e19b2d2ab5d8a9e345f39a273f02e6880ee0ff4ae2a93fbf77793423aa5407dc96211fac4360007db3c5cfd2dfd44799447719dabceaa9129fb7d496ca284c2f082aa00dd6d567cfc254b9c68a3cfd6bda96059e5f4bc4ea96ff453a1f27698a302d851cf1cb48b9c523eabd5c3482bd5c2400046cf54c1275be83111b6d4a73b18324810eeea20e2278e72af314d9f1223fabc88ecbc34dd78e87d8628d8a9af7700bbcae8565774abea996a5b2632d8dc80616fc9e79a4cd5c096658567698dcb83e1b87b80ec2a0b9e47e0805998657667234407d04bfe3b48ec1dee80e30b63546edab78a43cf65875e91cb8923cd47ae47d20799df580a10582ac1f042ac23e2ca273956153f7f1e4100f69baab4b70bfa24c76eb0a7778cf75c5e252b8ab40b543e91f51569b7e24b6dec55201b9ff2f4c92aac19e08eab3136b32e8038ea1979c3ac56dfc86086707162d587ada2f6029a4048becc2ebe0913cee99adeddb323a806dcfb0715658b57a2577d758db26767bc1166c87c7a23c487c30262a2b6c3938ce39d27fc00b840224f300081d2828d8cf6390f3284b89c6c1c4ad37921598ae40b47a51d7dc3cedb2a37f3744ae7a06bf07d8cd861343063b9ba79cbedefec5b7a5ce7aca283e1e60131d26a366c2064a9479bb8a7a7f376fd7426929bcc1c8c133b4f02d1060325324c050025ffa8cf6b9880a31dde9726f77fe8503e0606ace643f1c4a0c0065f857d483d0006405270ad2ee3a31fe0a40647b37428d905b47b99aebaa17b50657cecb63dc16a2f5bf860c5d1a9b866f0b6011e53f4263d81fa9b4a2039186d1c4e405052c97b9dd2c17f5f34112cec4a312af78844896942d2c6a67e1745068a7d4fbd1a172f668f4952a480a4b0397d61c7e26d8e0e2994caf7177e2d931f91ad0833ac6c37aa96238d4b3da6373c765af79d71ca3b1376008bcb43d9763d28936d771b5deb372655f727152393e08defb500cf80e24922a24c84959558dcc5eab90047d7358ae037632498dd604fb0254a30d3842b5798abe0fd4385af61f763d1ba82da5c94f1f80d25aeaa4425eecaa02f944ca7f65d98aed94e09370d95a46fb7b6eac3f6a2f005d3eeba3f0851d59dc0bd0c7c7e612875042df57a5c1aa19079963ca53d88493af0daf0039c41cad70c8e5c81e54069a23c369c3f854c1f7d8bc0a3b2ee78be89887edd8354323d5d315b89590b8c7f154c5d168ba1309512d8490a90c82fe5baf3008b249e9d8eaa026d66e49318c946cb1eecbb666f793f279faf26d535c49b5d8f0dd972c5852027dde6ad154292e6fe9579051da73b843b181e55da0c93151e63decd5e127a5dc101940eaaf828984e906b68faf359ff15480b5fb50c4341d5fd0691cb4f487bc740ef5bae6c31fc23b20a1d0c7e799e2202c2c552570624503c2be80c14840b43a498a95dd2e831032cfb24c4e2e52decacdca18072a58024ec55d77856cd28bf4267a0ce9a53a5e60a7fcfc08c6858f043037d0b3964e0ef0e41794bbbe4a0281bd0256704d58d6ece3146b51516d6aa51bf84a95c55d698675881988241ee1361c486c96be211a0b126553015c2d25f59aa2c9e41d4cb3652ab8d6223ffde68c539c77fa443e35cd0580938ffe9a6430f42d7ac4dbdb99de900ee1e9aacc1f1f967639c4ede0b49de2d04abbf4f06439095d5688c210e746f4e243de45e3f4fcbaa9de4c4151ef4ab7d0e6d2dc13dc4fbfe2fefb7dde0740c60391f4582379ac00bad02ee35715270e30e0b02a7b60465ee98865e44698e32f77b72583e37b1d134ca3b61cfbda09facc441f1f442fee90089ce9b032dce0f38a3b47dabf2fe6993b0c9569d0ef3d6deca94d8a8f18c3549806400461f206a0bc1e6a361e8a78eedc97fcd56cd5781f03d6c15be3e6056b2b18ce69c894e2dae990fc67269db490d2fbd25a1e25e1507854ea864d6467e378039e069df6a916ff66611b9766d9ac5c36a1368f250f684916e58637caac9d174314a902984553ec47e87e867de1130f97510aba6d2524c35b237188b7c9ab62d7400c6a88edf5a502618670d030065c778b50fae6b30a498315ff264597503df77edf919adf2e95ebcecf145cc98f7a7e4d502e7c8da3101c5482415a554c0b6597d33d1ea161871ae813645296c71fd4fbd1f4fdd575030b8109496989c242078a446da84aef0bcc0e3c2538c2ae41f74c2c3713f81e91519ee235ad219873ef13d4e48a1b94775edc7ffd63ec6186f21f823c123053002f7351de8644d3a2446e43406701c440ba1e7b85f257dfcc40778e5e64175768bffb6302a29881c4c724facc2787dcd058af29cdce695daadddd235240c573989101f1c5d74bfe1970e97fd99ed3ce4767c0d4a2e10e5021da245cac22d09d3f826620435b741a7c5d8d779b2eef10690251748122f300d519edb8cdc15727375bd8309129a764607b7f97a03cf1b93e1a2fd7fd5117dec0724b0e2f2eb88b082a48fcfa12f2e29a1040b98514a9a595405e4a849135fe93a27e0e028c4e16f18eea85db8e0337b03e6ae8ad959e0248f0fccb62380b608c75e120f00e704d0a039d282b0448cc040fe1b43216c5f47c81dfbe65234f7bb6d5bcc2c43d77a8f205076816198046c46ad8bc679e3bdb36ce2c2cdf4df4453220e2fce341f83fb533686485290324645b3fcf17962d432efa4434badfadd15dec2cdc894680dd49297832d651218cdd6874ccde6a694f062e8864620f3d9ddc2910ecd245bd5baeb2e87f5f3f61644a31066a97528d9d12a5957726f66095b3d06c322b4da4bc2a678415586ab92e369dc9a9414ae7348eb1b3d28a2af9f51956990fc8accc559697b323bd253c553e058e00114c384a7f10bc3cf934f989da232721e8f5563572eba478224b281756c8f0990a01290725e68451120905be6814102590449e0023d1103e0744483e6244cfe84a2a4a24b3143b7356a42e4a5e1210101fed069a516efa98f3734729b23404442cd9af75ec127d19a1fc70f7ea15232c3cc3dd960be4f9a223069d8f6b1d9ad99694e8fdbc5f911ca89401485d42d75cd5ff4e4d249e4e4679490a21f02bfd4b34ef3bd1dd22a84acd6249ea38dc3f438725fa4e12c7138a04f17c9028ded29f886b7a25bfe8c4ec14191fe2f2af7c00fa33e45805a304197e315e0621272afc7b0615f631fc86808bff153a8b92328ae7d7444391e7b28975ff932c03fd3f5e260aba7da520df1a8d8906c52b25bc2d1eeb9500afba35a2bb8b821abf027cdaec929753b8179c529073b1b84798bc9ca9fc8cb8040876280791f32c0e361cc6417d356de37cea00f2ea84e3cb53a5cc8fbf4641e89402bfcce892af9f780f7840bd82e71a9300385255c39e9dc50089ca21651ae0809ea195e90af20f6bf7a82a43f37716f9c9797ad48774d3cc376082f8eddc18c75e447c807dd586ac8383794cf310f85513251ce4910962aafd64704d1019876391ce2d63640010c894792260328610b1100f1066f8970a35735fdb4b38f37600e476e6e17c8ac523f205c51c01fe45d823781675ad38d55e7edc9eecd24a5b229609750ef16ae67d50e05c140a4059841c74a0d3299dc29c56d22bcb0f0d950dd619af2b6fc976af2e30cbdc102494948a494dbe01f204ea73e5fa784442e5503fd638c6625a481594ecc12a42f2112455277660f7493ab0af9a65d633624f80e2bd96c6111f021ffbcc05ed33153976ab88fd6759882816b287265559c9fc9ee0d53901786d6909ea905a13b74e5e9e433389d1cf6e37d88021bc3640a25b984f133bb624eda7c3efd7fcdbd0d8079182a84a718e1a0850778b89dced7eaff80bd73b4ec6dd545aa56d40ca3e40a0814456a0171eb01b62a5706c4010870a1986287f399a5fd96366a5fedb6a75658dc14f8e3598a5050c41fae10333d97db3d83fe11aff671b5e14dcae3fdeb0b04e05de83e754138666a698bba716ea13da3d29ada19e94de623fa15085087599a917f467fa9b36ec78062ea9584400ff2135a1333c5b181c470d40e993b46210522a035e059402f51e5c306a0690ac557c5c097574b7186d6b884de17e152b922f312e5c55c4ac76fcf0fdadb6cc9523b724fae1d791e2ab8a7498844d31010042aeb259090000f7abe69faffbef695fd85ffe57e6dfd9a81ac01e9f3e8c1f7c2a28f9d8303440328d120743285afa821649239874a1cec2f000deddc6b71becf7fde123dd36291195f373601be07ef666fe45cecdf757b0f85cc8d0df359bef42b7f0f7a1c0a9198b2fd8b3ef01f2ff5278d2c3bb0c81a1602c223ebf0c59fa979b874ef30335fe27350d05bf63f2b9a4d4bf12ea862ff3336734f97f9ba36f25e89a7767beea6113e97dd12bb753b560b3ab80820e2c6ab49162d20e5bbed72fcd1a919c2562fb8950fe871e4363f488a3e46eb7f533e71a639ade40e070d844263939e4f0848d7f804ed151c4211a4a1c44a38853ecda27707e0ac11ce8343a820cae825e30c10d72ffe88e4ea7d1a0ec3062237dfd8c4b579e298a051635814d8163bcddbbdabfd117bd999285f757257764126bbeaa52538d089b3465525d81e03889c4cb87021bed6804a7bce9ab7598c6495af89f64611fb02f59dcbbd873617a4b49f7aec17fe2a470ff552df09c658aeec5b9e23b3a60aa549a46196f02441fa705279b4bf66bb2f4d641b1924d3be627b23c748386a3d869152737ca570cf76db3f5771e503b0d406fa57f794121003ab1c36d8cc1cb621bf866e3c6aef2dcb890bb8fcde4a6f3c4da17a2e30ed48d9420bd0e622539ddda82529e1f776536f2419a764392310aaff2fcc241600ef62612537652fc69d5b0d859664488d4d6df02bf32ed49ef397b410b2c1da722520532cd1006250d57ab890db0416c57706cfd88f3254880c8bfeaa37a4192238ee25dee7734c7140b300176a0a06fbbd7b37d315f0a4373e9b495a256d742df3f560bab5926465235f183332c9ad687525216b54410a513e22c76bd1ca6c9fdd39a70126324a89ebaddbb6de31851f492125b6165085a848ed7993094cbd212e7c4a3cf7dd33a5e92fa223b1f2376360923b43954d7a3b204b14732aabff09e467f8b5b42b086216db8025a4aa8c88747e4915d79bc7f8d32bcc69fc625e54b7aca89ab9f881ee1fc542bb6463e6e669439f2c5ee761aec972f102ab0503ddfb0462baa8419052d3e467ddc6657731badb93d8888fbcfab99e6f2566c4a76a53431fd9fb5a77446f3121ebedb0e003729f5680e05a651b269326b310332c496228e27b50237a36e0376aaa0b75bed0cd0733c25cfe472c033586276a901224aeca3bc082f091d3641485e9d430cf5e81f68b18e9d3e7013387a9926a54c2b84997dfa612e591760e1e615f5e0805347da66165a47c9d987b49967ef04939c99ee9bffb20020306bad6096c9b179a8ae7cc1c69894cf4bb16a6c56ac75e71721d11e2f41510c7ac1955d7f588d8e8b013635c0606991bb2b77afbf0ce245d284ef8c526738125cbc5e3b490394d63ef73258b498a1303003511ff20d2332b31a8fbf238e0164df40507f190def9cae633246a13f6ee5790bff9894f11a71764edc77202e00d006db993fbae0948642c532acb83c43328c8f511a8a88cdb076780dc8300ea36c28228661d5e51992c53864a64694b6216bb638c1c550d8df18259262904aa35659b2a702905c6ab23ebe03315bfe04344392d07a3def91b1ab51bf090ba8eb4785ff55244340401e3574cec583227071e055a8915fb38b1ca4a7686ec850c4671460de5e01a015ddcfa8ef9e26da2953eed598480e78a3ec9efdb099e9d066e73d0c3de5632a177fc84d9a4716950202eb2d2c58c57174624e05010a80f357144a7f088d3b750699d75d4f7d1d1d49885390fa566da2e285eea4939100e77edd50fc203603246d820769c5020ea1e8ba94bcd0989f374b704f1318667ea6657754b69f21863bd4492b538c86ecc7fa343fa207ba99028f05bcdbc49d5f3c823a01480ad54383cf9a16c04d5329437494fda03302b8b4f470d021c98309d8cc1fa8d3660100304be25886c4941f6820adc00d502a7b8b3bf8bdf2f0603b380b86a50aa5d2a53d0d425dc21ad434cb55365b24cbcb33d674ac7c3a8f70baf46e17b2a52f362ee21c268f9fbc1b4902b9844dd40252f194820a2e165093ee5b0b50c5530250387140efcf6f5940298f5248c1c1813ea3e42d251936a3d392c416352ca0a09c88ba4ad9e60ab8261a0185c8e275a50d5886c714a4b9de8d97d086a2d2f00029b28aad685715113decfb5331137b6fa125b9508d20e94f102f2d0ab322ace5d388972038f152dbd78f3b08cb4e15a9881f8d946999a6fde8138b59c2afe9403f9e20992f46c7a9e97fe808871a4d4b8fb9f9e2c846cf3f31689d2d70ab898d38e40d1c90494cf0cc68d83970aab8de9a6d02176214628bf361e0cfb4abbcb5580f85a4ba99bd8c218eaa70c1957b0f61058ad88bacd0ece5c62c95244443562ab438c929f5e1cf0b243c1c102f83a477b5815113fdb98a43a509a2a8acbc9548550733ffb8c13765ded4805d7cc7a125b397133b3a423f094955352c1f56d455c6659466f7e0f8d5a0395d7c29bbccc635eb6c3060a6fb26b501dbd4171803787c3f75d94fc4d1a8b5a33378edee6a1fe6bc459cdc62fd65ad2cd04ebb90e88007549a8a13a21ff2073128463096e6e614ba452bddfa394a5110a4d109ccbe04b61914868469c769e298289291f9a8caf1c7448c04bd27da70eecc1f5c5ddbf24bb5ffa8225e02bb7f1b237a2c96ae0694ba2830ad7cd7f7c3ef96e8d0a4c05ae0276b068032d11ebc9b4004f4de911f918887da54325ed2fd9308b6033398e1a29ee7c1609cfc4f057a422b4c14cdbbaaba312c1bd382711f45b0e6d0f26b8b0e6b1bded7148cc159e9709d9199252fcfbe64d507b5ffcd6991d34ec689c16b5df9295da443c61b6a398b35c7773a98c99d2f38d7df330ff63a177caea4fe9089cf6b79c6ac3ad0cfe0fe2c07aa5d4396b774c28f540e48c128089eee982dec514938187fcce2ca699d154d037161fc73c8b0682f018183fcae071990c7b401e867b25e910e833cb2e980f6d408d787995a97b76255b3f54001598dfa244765fd0dc954dda31eab1caadffb539622b3410d0b2076e415a77a32c6a5d7f7ef8e1be3eccaf3be13eb12e87bed2f56d95f8c271635fc83711f8826f0d585dca7e4b20b9d6a7609da41d4a270a95c28afa22d342625ec5965cc28589c85502e311b1e9fcfb58a51ae898981ced82501e00fc2c64708f03f24a539c54f1fb172438cfcf17d7c1fd28a90554adfbdcb7291ae62f4bc206b393d0ede23e28842759c24ad60b638721321c83d6580d5132ae8a77e7c9bfc8f68638dfdbfeb4d45fa017cb1ec9bae341fecfc995beabafaea5a3caceb65acabf3a59c96e6592dc0662d3eb2443da658803fbd9df02d2d80eff49c5575d00154fea82962cb17c3cdcc46c5fa8fcc806d1800778b5a793f6559511afe43c411420f05ca604500de2564d268a3f8059966ad2d70051774a0f50619a8ab081c1d65b28cd6307a0944d42a403c1e1425e52e2bc528f1f944d4e8910f5d7d313d38ad29388df227c06ca9656bbfa8aceb75452f57e20f4e68310b72139c7b57d7d32b85a857e26df6103e23bc1e601b73251fc68615b183d56c7918a7b5b8d88aca19cfba5e0c78e5fd53bb5aac171e4280e94f71a6397207831ac881943c57c68f871a7e3867d37559da4190a60a14b0a37a56fd50ac555b188a6093fc330b24825e7bec9be005f1c83c3057de29b675deb8981d4cbcda4402968f5087c18db8d848d3a1a0e9739fb66d4fc2a85b435994fdd8e1a11b2477a484948f3c2a3acd98184e23c9764833173ecfae8554c9c3844dd381f6fa201aa6bf31587504188be2b4f003981df20f0c96c8c07fd2b42c2f07f9ab4707671c4d880346f5700a14594f1a91b907a8e83e4d480595ff5d9d888a4ef3abfac96335582efff6c0c4f045431ab5f9a8c73f5618be91deb75f0595fcf6613142842a7bd73370105947a413df93efb0e28a5809432acba0ed872c27d0347f44c259a80fc2aa8066cca1fad7ea58baa824af49b0cc233eaf434d25bed02445fce6df1b3a03a695f3d41c070a6e77de98f63a10f154c4b9d1062f035681b30fb0aea60ec061326c84f09af0d58da6e7e6a251a31932dd4e1c994f45211528790cc3f54911dad60407e394f4ed2c78bf2dcbee98ce505e18ab020ba32f3841ed4c2506f731bb9f5dbe033c6ad8947e741b033cd616e1c0b89a66179d5017e1085d2f8e67ea88351fc9e6809fb038449f23405cc31d8f936bce9771b12d29357038caf541b355d61912509941e3436a67cf835cb7c70e8562c96ac54f3d28ccbc55bb1d0ed5b8da6cc37b1a45aeb6efb3fabe3f066b71e3ef03909d847d8e275ea1d18d74d398bf75d7b4a0783f2b56e82cf9c97fcd26e1842b82617152b288cef51232317d23beac17345208c283831468516e1f564847f497e0034c59818545a285b8156ab4fec2c7e5558848f14175acd725e566fa8e48ba931e92a6577fcf978f8b31e1a6032af8aeee3392f4f40f0a58f6cec702cbe54dfa55b77427226eecd41afacb184c82e32f84759d02ca46063eed729d4434b89130feead8944cf699e2ae3d9cc23befe27776befafe9ec4050672b2c41464e55ae903839a9cd511651ef4dcd3a16153280071c69e0dbbb236631c48b3520f0392dc9664c3141d16f0c6a13f88ade2baf264221c4ead2e05981eb9f27c8fd813a2dd7f51dad8232204d5cd8f48aec739c9623c1e325fe6acc8b52c0aa4d7481f71a16d51c52ccab6586c5bbdae539d7942940cf11826a23040e5a1f680c4f099e7c108ed92cb454071adb31be9e092811dd1c7da14ac644d98225e4b7497f2e3f8d5bd7887fd8dc7b0e4b82547bd6384000162c8f13c0b9b4c3c8e449f3c9a81ac0bdae0511ae89f6c911196d2d22d89f3daf060759517067f495adce5c2016529c8a1c257153a11d40172ca61519e56c280db00a74271366e2daa284c4edceccdab0f382a3d22b5dd85c1d742f0d1dfbe98fb124d81a7c24055af40ef2cb9cda9b217a2a08b6584a5b2b39c2e1b76e1c6ccd6813431e44b082df25efca0399f144230570902ac9098650755c2474b8abab818eb292518fa1bfd6701f1eda42ecbb7d741f9b8ae17706389c9c8c7f252da64a7266d2013bca316398d9db6c5312337836bdb604d89f6f8ee38c7f3ffc1e29f51a1fb21ab77e6861016a1bf1c4f0b5cdf22cfcf795708b82704bac6a75887112e591c72ff537e347ff16b48043b0e38535d63d061179abf9d0f61f7329dd2f540331aefd506a7d85720250280adf085c8d6934617ad5184b5b6b3a0b59b1daf4d8413b8b6e09057e3a0e225e89a63c37b23e6024eb338cb03c3a3e00d8354baa811e3027026d04644b3f9088ac26fe9b0602a3442101b1e87efb57544093092fc3182dafa6a3f70c84ae130a2484745362dfaaa231f1f74360c69dd14dec35666442c1f1479b1ad746ea3b9fc96afc88b4729bde88a7081cbac0ef23a3c0abc18b4c2858e8803b8978543de351c05e09d407194d8879127234b08c45bc6f0f448ea0dd0d1cf84c529628f8390ef3761d133b90d1e41473f098b53c43f0ea1fb5994a8d5a1768a2d4a62fe65c22253b8ef8dd0305e2fd84c12417328390583c3a097b67213769c305f24e2fccd1fd5739005700faa3a9fa25d4c5d202fc2bb06e4183183088b14637439772d58d5e65d63602996fe40f793f545a367eef19151d2943cf66425fe1116babc7d46acc9ec958f6d0a13957ee39720eefe8ad8d916cd07b25c1d16b1ab6ca91f762eb6c5ca8d16470aa88440d5cfeb07e12f209352cff84a104fede055f6fede7d9d979188396bab259d2a5c39c19b8ad0014a2c64ec92595e9ccc0c8548793436c72d11e737093b7062aaa0733aa33955b26ee936b475582a6aa74a350a31726f0d2aee2d82bc74adf08b1d1bdd7a83e8ea5872b708010cd6e15d26cf5b20ef6f12ac43a6f48fc320ac76f419ad815667e9c364c089541a750ae617f8735e5c66ed2d97d3a0b2b461a248312cd7596afb261eef2a3f960586c988ca56df8e50686211d16e3209c8d904bdb3a202d5c9b959b7e69ef5aca5d8f66feeb792676d3f01ffad7eb91da17200cf859bb234f47468823c8b64d899e9de50dec61befd9e2668030208035dce1901fc99ea1c2d7c75405cda030200462c7b348e24e85a28a688bfb0b9c0b96dedc3518defe4e10c2ea5889bce0186a819551f872a07f6b43f2a803671a3deee1903d986d32d8640879ba21e416b8bec6162607140a04177b256312daa1600a2eb5ce93918bb9c125bf2ecb9a021031ee33c08e22d27f3635d7e002e26a70edcbc781aa940f8d97e969e258a76f882223f2c26b3fdf13b7332b5c09a459a65808914ffa73ca32414ef07ef8b7e4369be8e57ca233932e91b577737740d836fd8964d1b9e024e7c831bacdece3850309d35e9d6c2a04c06c900959c123203eebacb4f5f2fa0c6940af3ec58716fea9433ea41d81a4c569a20dfd3bf094bcd327a4ebd82b68f8cb325cb07fd432232be8f8f4ac746b80fa8038059ea6709313caf9fd21d3ee569edf07bfa3cdcbe78f5f0c8184257c2cc6dfb51b6fc6a766e612d94484292303b90233fe43bbd6e8c49261de4d45caba580997fbce9d5fdf52a78673243b835c783b0031c78e406dc7ce1d329219b27696500f2fd59611c2eb2d1ea2a7d5053605043c52eb75e7c975b218e3c734b612c4142a631fffb222ac10e70b3771cccf0e36e8fa74d853c8107bd8d1915648b2be683fcf5372d215c891a0d463acc776dc994ee1f43bea1cf760a4af23483b7c44ee9d3b0d66a3f60fe7854f43ea291c9509ad901ca029c062168cafa404c5d44146c41e18c8d584900fdf33df76228fce8ec52907f77568922fc901a9520bc653d5bd4938e5bae1345325da493283053f4fc1944dc84ab9dc9871df0441c11e94a9f2e2819ecbd840c74af1642437b17981c0a9549189d324b24c9644c758901747095e0efe05e88ed7c86601b20e3686ec320299f8ec3dea99cfe70459c785ce506b4dd8bb3b585984c0ca0df4a6f675f7a74af714a83d515780f8c04e7cd64a833446ce8b5001857cd947f020c087dcfa5acc68c0c7c1e0e013d0a448d7a76eed847dd352eb0394a2b78e69123533a8ab588077468f0fea3be9878394de5e706e7ce7daf8ac43fdf8a2b4412d71748ab8c429be670a8600839b782bba5c754dccd0944e685f4ab38e9d9426f21704018ec3ccf41485e8eb57beb334b03495a0a12f9b24e11883752a296b61f59b62365223c34704e9e90aab272f442289243c5c3796cee73a78c76a62eea043e21d66671e64d7c14ff3d7430777cd5f29c961bb83f3dba395e19d2be02f4187f8882f82c46307ceb78814432e0e8400e9579a8278083f8284fe3f6049ac013658b08324b3cc661b6d2c368600e0a3a381cc54500d419a0d1c3cfae4b845cc67e87ca36e1432d77fcdd40c16ee0912adf599e53d044a3c9c7a19046509f69d97dd2d6643e1c5a5c75070340bcc303c1e6b6c3aec3a0df89e7ca320a0ebbb623f469cb4e03320d7d08bdd1dfca1ef01fec74f71125d9cf41beea28d7963a9df6faf6637e7e12a5fb317bd79ed3d985c29380879cc8cd12e966f8b29c62e1c86dabd9d613eab886a70c16140bb7e148bd9b3882b067e66cfd8dec18a2aaa80644246b615a0ee180c0602fa8c5264b4a26aa63b068c62191c8e248044a18547b40b29707a992132da486292c95ca8c28251a507e7aee2d0b8cc0b6516861d8310c9edcf9710590810562b0833a1605baf07b767e9224b9c74b5e90ae465f0291d9f181763a7027648108ae773db085dcc9c1b40054df69f803770f958b1ea68089dada617e06c4c399f800947353c4a1e3aaf036af75f5164bc6653540046007d43b669ba00935b7574b71c789ee4b25c3f1599e3bee192f774e7bd770cb1143f76acc32e8bb10918377974429cd71eaf0cdf7c0fa3eb6f9a8ef3893f94041c74f9242ad6f4678faa0ce0e8b9cf47b80f79e0e3fea328d89880475d71e58fb51326e7a3c55c85675e2a6318d7721951416bed6ac9415f0cfc050edbc5b813571058c96a3af08b8e86152e07f5536c597e30ebbac3d22721200eddf3c5d65f51ef5de2ee7b83c42d25d916d9c5976e24ed6ec9dc5a63b3eb9a6cc8163ff11c4e4d8f482cd768c79e131c03c6b909d8ffffbb096db2770a6915a012b4134286006730044ca4bee5083870c1952fac90a0ca79435ae2c910a01a68f081af1965ecd0e1b2d162f1b00392a22d280043052e288103c589200a98410b52d085073270850476843120e0dc4ae80c8433b4881106185c5c208800f4b0640725488a8808b9d0020a276cb18120aea0400080105958015f176acc40064c724f5b8e2084202ce10185135e2de862041ff0400630808512491821f6a0430e488a88528082119c8003508660f0821474c185073a2005048e20420067686941181ee8c0161568f2f424d190978c1632c6980109b8d88006b2986289023c29f6b084871c888600f1a979c9a400052468c0029668f2640f3610090d01e2648c9102149460041bd04016584cc144124d946c20a201888f0f1e393524bc40df42c6183228010946c0c5063480c5144c2c9144019ad440545a52c38e308d22182962a3460c567882c4114a72c089a20047ec9cac70d9923ac2670455113e22b4aa00a9f8a6f824e0e97c39291c2f84b949cd90a227b8f0ade0cdb05448a5e0e10051f04e7029810412522ed0464c0d978c0a3129c0acf0f27261b556ac6fb552a9529eaf9abcc0608227960bcb05acd1e261b9a458884912a208d68aad5e5a3d608c0d0f8c5989a02e25937a815704a080a7558d8fe502dac8b0d04381a797243124685343888fc78c0a07d05bfd80e0890623425e02f8c017d0488d109e6e30840c5684f0543e2f178208f1812aa46e4c8f46a69a218ca7d5ca05a32626d8002222454488013ca5e09243cc8d981b3e089960b6f44b109e7eb60b111a132e964b4a46c5041a8184102db0c68a05cfc68e103888c24506163469453951e383510579b17e80459e87294394a08abd08bdc4b05a02cac0fa318416501019820a254e70e13491198d1040044f30a76d010290d1b1e1255921058495028f102fac1fab97568d940f222229165e8482f0f4c22292416a0dcd0c117a71198a41227fb4784201b4e17959f99420b37a811902eb418aa797d6500bb5239e542997ca5bddb07a510159c9200382395d74b486562fac146484b8e4008b5c50b8b1420c2a9c20436b8622473108f1d20a593b323b3e888c5831204b05954f8ac72506d44183b05c582fe00e5511b02788a79a49d1a84ec071698da91f4380e068bd9ce0e24388a022181ead189803ccb1a2e249861aa010d50caa165c72802bd8c849b130c453b8c34bd95237604a0500580f4d7400df2b2860056aca15544080004100e1a4996c3fd27a58b283922438201919b161c8a7672716030c2f5070045c6c31830738a84106034c851458514ee08504a4b861480d3e2c981003b312c1161ab0428a0420f00028a2340087988e1de102149084b4250d346a3b9851860744fc6242096b930179614959e2890f17175c99428acf0f1e146ec0bcb4582bcc6400034b9e4452640391d0101f1e393524bc6ac8804f2461c40048c0d283035750808a207248e28307c70df00b2b3f4822a381c785b5c2a2080d54200a04347104001cf0c4134a20299201d111e3152145842f0ad442cbf8b28038f868a0c2e2bde06bc1c702973062c0f8bef852f06df16191bae2630297bc1c9e0b2d16542bc8a4f0a1f099e0dd7895a022e17b792eb0c607a37af95c5aad8fc5527da097f2bc95bbbff0b8bb0a2e189c2f6b755f9bcd1d4fe2d1de9305772f05037adefa050c776de94b142f4fb85e9eb8d3e8eddac7e9680da5e187c668f859b9eba5e67ad9c1f5c2c3f55243a3364c6b688cd227adbe966a4bb7a54076b9e68a1b69b574ef6a4a6118f2408eab1e38eeaa2430950bee728180eb1cdefc7b577347de7a0677b9541723d76efd24a51b5faa1f93b426f6633eb176095d7038797f57aa5dad28f2beab3582561614b76ff74b6ac3f4475b6a9ab16de7ba35fddbadd9dd5b7077b9e132f367deafcb6a638d00dcee3ed3aa71f798bbeb78c1d3c18f1c2aa3399fa30c3f7ef4fcf0f183e7478f1f3c7eecfcd0f991f303e7c78f9e9e1e1f3d3c3d3d7a78f4ecf4e8f4e4f4e0f4fcf0d1e3c3870f1e1f3d7cf0f0b1e343c7478e0f1c1f3f787a787cf0f0f0f4e0e1c1b3c3a3c393c383c3f3a3474f0f1f3d787af4e8c1a3c74e0f9d1e393d707afce0d1c3c3070f1e1e3d78f0e0b1c34387470e0f1c1e3f767a767cecf0ecf4d8e1b1b3b3a3b393b383b3f343a747c7870e8f4e0f1d1e3a3b3a3a3a393a383a3f727a727ce4f0e4f4c8e191b393a39393938393f303a707c7070e0f4e0f1c1e383b383a3839383838351c271cebee33ee62d9b8ce61eebc50c6702fabddb99ab452dcb63a9cb6d702b97be8ae1503dc77cf44f5b6f433b67d8d569afa56a5cea1ce4f96f6ac09b96bb582fb5f4cf5896dd367933eee4b338747ba4f8cdb56477779dfa766cd51dd5f5ae9b5b7af51bc29f9dbccfdde5509002f362fb118101488179b1700506a43014029a5d4dd63707718dc3d87bb832fa8ae501f5516d487a662c2a52a62ab78701a8dfabcd8d068d467dbbea4f48556b371379b29ddb62f6334eaa3ab7edcb86b8e061a1a6850d9b85431ee54db7dd628d5f671dbdd61342e300759a88d0e1d74574a3ed3686f35a178f071dfe7918c731ea2c339632077ffdc052ae1ee61b873b6cf7804777081482e30e635f4e787e6c4e85f5c44a317db6d2271edee3bb82bc501d739acd972675cabee26b813b9832f30550209ee2e77b7e1ee35dcc5dd6380bb2f71d76700d79746caa98f26ef896bd486e93e31c55bdcb63435a5e187ba7b8cbbc3b8fb8bce214ed823ccb9d961cbc1c1e991536b351d1dd2478e8de706db50ffae790c77796b7bfbbc03df721dc31db58cf7f8b81d3abfc6610709eefa70ee658d8282bbbe98bbdf70d777c369c8afaf55e9bc2c3a8724ceed18bfc9e5798101773fc15d5e1477bf5fd21ffa354a9627c6695a43b58d51a727afa5df84739f45b3eab4bbebb87b3cb87b0aeef2b6bbeb1c8e77a75b7f96b589d2721e42a3b7d28b29ad2666d6acbba78fcf2e4ffd47344a7e59d6d1dda9fb5773771ceef25c3a873b6763b9bbe72bcf38e7a7b752f26f3ef7e77d3ff7a599b374db9a37bd5dbb77cd656ca3350af720e0ee2ab8cb69ee2ee32e57c2dd4d7097fb407e69ab8deadfbb1aa5364c2fb6bbd25dc6b9cfe91c7e31eebe82bb1c87bbbfdce53cdc5d874b5bfe264c77db8ed5aca3cee1f84da2aee61d63d63b465c9675c72ed75cb3a5bbab52a0bb7f2408f104e3504f4f334f91d0240d18989f03e07015e115013671e2d1225a291f3ffc10808fa668003c0ad21facf8a189130aa44a72a12aeab01f8aa0402ad80f0158d11798130a94a22eb000b4604e2890475594050bc00aa682a5a8d300acbc0bf383809647e3c40a2635cc524ec0264e4098154c6af898785e0e303f4efc28c005d21a340e042343f3d1181a8fcac8a43e994f6646884599583009ec3eba82496097a235cc3c189aefa32f30d48907f4d22446e6060772691203c40bf55c60405891f4423d0a040c958909e285a6881a80521486a689130f28458ba8010804a90c4d4a7940df07b6649ad4a02d9a263034c6833d0111801485813da59a38a14032f493d94186068800a4680dd8538a7e3724a58c5e689c78402fd485c68907e44261689a145103d00b75e201c150988f46867a343337805486ee90a231b445d3c42587208060a8478178a10102867aa91a156db9d0146105931a662bea01fd447131f12db3158c4902bb8f4a6007ba8c3eeac9ccdc60045297314ad1d4b7b200cc0f14d7476154b0541029af088c83ad264308f1d10f74f7498160cabb008c7b1e93b7c4a22d26a9990b0882a00b65b540960b9862b15c582e2d18530a04413095fac1f3a80bf5886872d34755b09da22aba822dfd9052fdd052c1364d31a954302616fd5654f5518f8689f5c30ca4dfa7ca02c6534b140646e544a9990aa4aba68fae401a2638664c2bfa0263f2c3cc857e344c70cc56b09d1af266add4cc05b604520fc6e487190bc6945a02614c7ce6d4658ad8987d1f08c018087a204c4a86c6a456ab9915a5595232ab99a9621f4f6cf6e998adb60ab6b4a22d153c6999a5e86a66453d5a0316cbe0cc2ac69a69d16f15f3e80360fc1381e7ee35dd82987d9e02541fcf962733ffe208516633ccfc0b23a031db82c6163066302996475330a918157ea268cd107d94d5527d9e8c0d41cc58d465843ecaa22a1a9721aa997d54c5a29951d15891ef0818cfe1c57c2bea4259608bc2b0965474453dd053aa948aba8a36dd8298ad666656b1996a2947ca0b18cfb1a452d1964a45795855bc453f18168da702411655b158b09916f55a30cfa32e9e475d582cea59f97854d43d30664ea15a312eac15930b25728181aa97992753244559acd58aaa562baaca020250a4282b8a31662cda022345554610c14c455725dc28a104125c2b982023e441cd58e04ca582c1c0d034b16249455f2e26992229baa236648854307045552b98d0376351976fe64213832307cecf5012ad746af2840152bc2c604e8041e1938981408c4b8b7e2dbab4a25f11ef0b2380d192216ab9be98d7a251c9144911ad60e007a63cff54353c281b4fc0781f08033f2118ff56de6aa55a5198956aa54aa5220093a23029f7d920119c5c9979959943997d54458508ab551338642605a3817119a729e2cdbc20664efdc891156c29889914ac480a4cad28cd076e30055bf22828736429889994cd8c07b30153a994cdacd542e279f4a3aa09b45c38e8a78281a9a80a86aa543f4cb8be99960a46e5f281339715cc05d6e4a932a8a2b0a5184e18511ef51c9ecdc7935ad1d58a45419921abef9b61d1158bc666332cd88a49457f06e00269cb8769f5425d56d405e6023bb2a22e2cf08b28b3144d3d897a9af94c457f80840f9e6cc9624b94d9f66629eab27261d1150b06ce409818bac199c752b9a8284b15d36aa5605232475474059bf1668ac466ab214b29baa24b3345623315934757744635a3821589b15654b5fa59c2b5a23e43f4cd56b4e9b694a21e9d69d198079b69c18ac462309b8f67459760331e0c66a5f29915f556aa9567e3376e63e6f98d67f3c5bc55050c8c8d8d162c5666206d2da5542f2e34e502cad0189a92194265a8476363d604ce58748333f005b6e4d1189aa25992f1b4cc9ac019483dea4b2d3ac3c49bbdc0664090824ddecc85b6609e0b55510f64c2e54e552dea026bc1fc26b5145b026752d4b3f9620eb3f962319e2a0c213c99398ccdc7e3335eec8b398dcdc099bb0f134fcbcc832d7d7486459d7eb019162cb55a31ad28ab45615c601e136b49073103bf9922b199473d580cb6a48231f198bc0f66332445809894d06acbc808c1f80b9d9189f12331a09782155951b7f9c2804905218b598bc280d485b6102ed80c9d49c18ac462e817fb62423331b4096c0267eef48589770406d6441d968209cdb0a8477d86052b128b11ad60365fccf38f044c290ac6c82cada8cb80344d2acfc30226cb2c45c12b369654948945895c33fd511818caa2590ac08c459754747b600ac6046382a133a75982a12e4304d214fdaacc521444e38b211860a6a22a2636667ac847d3e435792d22302ed4973c242bca4a51907ab026af95a22c181348b7375bc140150c1462e2cd9878b30fd67af1400980942505a42d345a2e1c34e6b0a519a29a99cf6c66a9235ca91485c9204d5190e6278a15055b542543b4a22c50954aa552291006f20c013d19a29a9907635ad116fd689640daa22b19a21513afe96bf2662acaa482b57200e339987860eabbe13155933703b780b1e1371eb5e13e4e3d1360fcf3a6a0220b175a606185191552c081c20926dc28818497cb460d9918981797d6173e78b2811082108420b0a86a096fe5ada847554f5230400e7e3552d4035de0a76ab15a2d560c250286bec8d0189a2413034b8281bd106911b5601e90b3605354535ea8f88dcac9142a53a6b88831f3281517171a4fd5b03e150ca2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a6cc5a4881543c164859340e04040dd7920a8a0ae652c56fbe166080b0e09bf295000a1715f80114205a54aa2f0715ae58cc0687874a05e53eacd9b78217b3852b453dcf7503d7522c16530901c71950ce4062e65f6849e30b2d65681963e6d198235ac0d062458b1737b0a82045e50296475920751fb8bc190e5c00e5c16e40bda0f1e4050d951752a4489122e57bcdbe540aa6ba81e549140da4b430036137a03ee05a3241ca0aeac992095266dfd28d0fcc3e1b52fc064a0528550fa07eb856ad8fc7fb814acb929d79206dc196cc99075b62d1f8e725e17cb16f46e89bb16892cb10e1f1c580d4c0f502ca28f1d80f62be305c2f7409e6090fd7c7e3fa623318d8922b01b32ab3179a251e51ae2955587ec5794aa8a15aa95454055b4a097d9ee7f862de2cea8a0b4a9494d7b241e38a422365e69a92aaf95c09f0121830fbe84745852720cc05254597609ecc7200a181cbb301c502974797609ecc3e28972198007502901ac47832deca6379aaa854cde70416c5e50c973783f93ed5075bc211038b2202330150e5cd54556026f0f1bcc096543c507d55be2a5f95afca5765f6d1568c14284010474ae5040635035d70a1062e0f08085c4b30535c54dc27a5025d98a9b04c8101612664f19b8f0209238a77c213170f688f06081964789ee7b947c6f77dac8f0c2d5a52a9558a0c5005822a32522b2064b83c4ae4034206abf579df9016133242eeb1580cbdc1819a10e1a99aa5184a440daa7a92aa89a1435a32371831ab415546784d0c85597d9e832995ca89dfd4a03232d465808ce1aa019ba9416da8f01385cb8556a9542a4555506cd0d88889a931631159b5545358ab198b3a711f191a43dd975c68c13c06e664a5a2aa29a997147589b9a23282456158f44586c5125ad11818136f8b0a8afbb066535c683e150d9499eb050b4b014010f0e3c9941a30186a0354d12cb9662a570c8bb65a322e160bf62309168b92f00a92aae1d1158dcc0f03cc3c1ad372c5bcd0146dfd70f20389179a98161697cb8f275fec47125b159ba5a64cf991c40f273f9258bd40cb04a4b8a4605c5c680c58837e35e84b0d1919984a86880c6d5118204f802040e6bb8163f5a272690179f2b56866e062c18040f910007e54f57d2a20568a00e339965c56106961060303fbf1c4f35841803668544f3eefe54b3921e23960804071a79e0b7ef3d1964aca15ae2517b0b8e03e58b2ac66402ce0f2684bcb18365a748a1507b896b04479c1e2bd80e1535801e3ca8b942a383ef0a2c50b16b1282a900aad664c5e288be6050d9ad56c1595c68b16201648799f0bb32f6ab69ab2840defc5c91753d9983253a9e80b9417245ea0785e4b85256fcaece5e5e5e5c5c90b124f523e64a8ca658afbbc50952a86aaa8aac9c7c3522101f442534e655e625e54f485c60566b55ad980c2c05315ae9694094cc982ca165022a8e2851530ae8881658c2c3c785a0010282b20137081f45b6d0125021811577901c68c47b18c9185071f8f0b8c081a5133abcfa3711ab0d572ea7935509acc6866fe050db0ccbc1f4e603f3c8f7e535c4bacd5c762a562626258302a2729964a05f591a10232856b69855989c57d5c9801d1024816fad18f5a492901048819505872f03445044ba56a0a90200276df8a6f1d4b5bc56af36f9bc76a6abd4f739f382cebc9e475ec1eb7777f31a5b7dad45c4d5cab364c44a9288a228dfccf4234aa2d253fbfcd56aa7765cd559ff4565c564a23896aae46b48b2df95b5b9d3f776a5d492bd65c4d31cce99aab79ebf89f856848be35cf71c43463fa9f6d343f6edba79f83e8ad4d5f7ea6ba8eb42c2bbd587cdcce58eb1fc793866d97e8c83c712642a3e9f0a5d15d997013fdad314e476d9852b2b4b8713f6e637387a34fbeae354abe0f16dbaec5599b27ce374a1fb743bd9f08b5e66c67fb070a494bf7ebfd9ab4e27ebd5f8bfb356daadaeabf7f1377b6ff1af93bb4a5fad4f7f5c523d54168c810201dcdb923e11e6bfe7d2dc522f9966a7b43bf498907fa178fa2ad89d2681bd728fd5cd5f42b8eea1f2d792db5d52f2979ebc5a6aea7d6f46b368fdbaf4f6d6b5b5f5b6f7567b3f99350fd4df5cbd7e5101ad22eede8c8111b5acd8d7d0e23511a68d44644434d6df935ad3463dbd19123e2d5e1cb246efd352ddaea9762cee5b40d8b39970b7118677a74e408b5e6ec6b1508b7ad4e14c5703bfdbe78bc9696a7ed2f121ad6dc7c6e32571cd53666e9ed5a9ba5e12d7c6aa34b5b6dfbf3a89932d6edbff4715bd791ac38d7e8d7f08d9575c4a5f9e358e9d7c85bbf5643a35d5b770dc768a5196fbaa928ee9e09d3dbb519b7c97f7deacfe73e85687831fd265b526d7f57baafc526dddd4ac30f2db5d9b89bbd5dfb354a62dcfe1ca6fa6df99992f5b7ae36e37bb3547faee66a525d296de352d398eaa64446b3db89719bfa0c4942524443dd644f266f73b553d38cb5fef12ffd5cb50de36c44c37c92946eaa2ddd3d53c5bbaca3cd786b8b2bcd138fe549e2dcdfaa3ee99766ae3a3dbd336a5a9cce7f75d886a90de36cd24ab5ddb8d44e7fc31af2c77be27b2bdd953bb27e2e2bd55517a34e7fc95c6f9fe9c5f65a31c48dd8fc5dcb7008d00ce8bc595ba5b76b77db96f5667b32f94cad59294d641a1f37ea106f4a7338dbe82ed7265a965647ebaea47edcb56f0b85e8ae34cd1a6e7c69c6d752f2c9b31c2dd5ff393cee539fe5782dbd955a73960392d09a95e667ca5827da6c38a44cba6e7a6dc58d37361ba68fdb48343f591fa7775f24b46645a264b87b263a03d5d5ac6da977cff4241e5f88de3d93780b4d4a3e1d6264168444c9dff5feaee3c5e3110d35a5f5d8f649a3957e8dfcbfeea17ebb6d596ffeedf4d53651f235369d9e7ec67beb90fcd7bbb2ac58ef9ec986f3df2742c97f6d856b4892bb933008c922e40b979029ee4e69f8a1d48776bbf6da9afb4ca35b5793fe786b1379eb383e89838cd85d9e4764b29ef367fc243f0540e288a0330440801c5c414b70767ad0d1facbddad547f2e578a1b77cd19793db83b93bb80b0b8cee1f823e409776e6e687017101477279f0905a2717e1fe8edda5d793125eb97146faab7ad516bb39d9a92bf6d16a75f5f6cea3fca8d4aaebdd98ca44442ded94ee7b736bb7111d2e746a75bdd48377bc4dd7392e024b935cd94f20c87ae3a5a9675a43357902aae204e1597fb6de997b76b359db9820471f7509f355790cfddf1257576ce1ab870771cdc5583e96159be4e576a73bb76eb6c6dd486290d776579dae89396a4faa90d53991152602bf5a558df8ab58259e919f9b9df44b9df441ab76d0e41e4ffbe44b87157201a36e0eebecf9c8730211992a49364dfb7e39de524d9f773bb6a8aafeb977ff463068f9c9b6bbbb9b9b936318b3f36b6c992d4c7bdc4b8467e0e8f321e3ce78fec67fc2419db6c8a38bf0f17df9d752daba96b1e524d2420405cefaaae9cfdc5ba2ffa3163a1dbb563c642daf6d9c8963509b65da2bac799bed544ba5dcb54b7167d82fcf081875bffed766aba71379ba36fee76a5f96bb9f3d2c76d9bc7eddc79cb15b7e953dd1721fdf0c00f9cb28e389b76fc2312e976adae9fc71792eb5f6ba492f7f3db3e37e533c87d273af1e02122dfc90a65bcc76a23b1cd6f9abf3579bfb43f668c4b5b59da5a7ea39e19f78d4ba4cfd9a43f99541309796d11f25a261f502e1fdae5c3050f95966c5c6a1bf25a261e9684fa71ba969a92e46fabb1f9e4bedff4545b5c120d372e35fd9cddb466b4363bbea96fc86b9962e4ad9426bea6bd69561ca591d732d1e8fd267ba34ffeced8fc4ce9ad545bfaf97149487c80e19bbb4df5db6c98e7ec71c6aecc7d3622bf2c6d119cae1b897cf262205d626c543b91c85c757f54626c54626c445e5cbb385ca21fab8984bb9df80ed9b8e89bacbe6f7b21b76b77386ffd42c8bf6f22f95db72e3136c51cbe395bcb20f7b29ce96a2671dbe6704f6ce67090d65f929fdf4834cdeae3f3d796178b3977bf378b34dab2761af9f8fcc8e9d14327eb1d32769c765a3a6578febdad2ee96f354794ff76ad9079332a6dcd0dd9d81ed53e87b2dedec8ae96a6b64292b605b262dd55084f0f9dff8c4b2ac2d343a7e290787ae8605dd233d512486747578f727674f5086747578f7ee8e8ea518f8eae1ef9d0d1d5231e1d5d3deaa1a3ab473c7474f5684747578f747474f5084747578f7ee4e8ea514f8eae1ef9c8d1d5239e1c5d3dea91a3ab473c7274f5682747578f747274f5282747578f7ee8ea518fae1ef9d0d5231e5d3deaa1ab473c74f56847578f7474f52847578f7074f5e82f2e12da6dbbef93443942fcc848bfd57d11ce0edc8669eebc4f6934fab8241f9f6a92b7e6dbbedf34c4dd75b80b278a87e4e74efd192787e4ebb39afb7ece67d0d6d6c86cbf165d38b1907c5b9a66a5f7bf4675c5d1fd9aeeb6cd18b7cf4a755fb4e302e110778534b82bece1ae7087bbc2586b757110f9e43d315012f9d9ea17a2c346304efaadcfbc2f0ee43df1d1673c22e5df38c911af17877d4f1c74bb38e7a0b373ba7bd2fe5baedbdd918efc7db0481989289ae269e67090fb6ebc7fcb9f1bc234d65a5956211cc8bf378b746dc5055d243716c8df5462249d333e828b92cab2069d2546223fe38d848b8c98466c04c96edbd2d6acae2f54a499c6c77d16bad86a6d73b513a9c4d8e8cb5a2d6d6d9a5d1c36c669b35e24773fe23e3ef9af3df237f7bc795d71e68ddde599dbb1db3657738605b83bf1f4e0b1a3e394433ed3888d04f96fdce4e373bb76e326db74f1f81b27f98b8b7a74724e7daba550cddb694859ce466d8ffc0be93777dbc747eb8b75fd231994dc55b3c55d353f70574d0edc5583c5dd635eb6b6a58fcfd6b614f5add644535b234ede130b6d5cf4242eba55a0cf55a44bb471517edb547f68e3a2df75b4a5790aa929dd7c7d93c3a4931a166a40a778534dfeed56dc6862fae7b5fbe2d1e64d4facc3123277c5ac701d573f26b5c56d8a1b2d4e476d6eb5b4d124f2f5494fac83ff80137bd091864e8813e6340d014272948444f3dc93e2e91c7e0de7ad73429c50e7e6da327fce06a2978e9dcea135abf8bb36d96c8aa24ec823c4b9b9e1f2f3b9ebdb284ddf536c62a2e993925fd6ea7dfa35baf599a3e4adb4acfb7ecee69bdd33b93b11f721ee8a210d213b88c18826a908072441a290221c901c894262915950d09022f456dca6f945f29e38d3198f3027c4b961aae3f84c4f2defe94988a79727f7a727ff9e3cf5e4463cf91147b8bfb88bbb3b7127c093bb3c3d09f174c493fbd31301fc690877f798fbe82e1856d0097772429c9babc3b986d31597238a529cae43eeee3974e0eee3638469c425907b59b8fbbbeb852aeebec7cf198f74e3ab29b5594afe1edf747aaa2d7d5c12054213331669e403e91cea6d73b6bc0902ba5d9b379268eacfd5bbc76ae670908fcff8241e9b74764e597e232de6379d6a8e69c4652d9775e32d3ad59c53cdbdf8bad6643a3be78f53cde56e128621717fb2e69b89c3d1d6d588ddf612f960cb7aadd068f5b5793b0dd995a639cbfdd63b5d7146f98ddc3f8791fee2a2241815dcdd88bb688cb80371f71edc45c5f0dffaaf88b34d1cdfd43bc66fa2509e003c1d2fa786a772b99086eb1ce6df56ccd5cf5bdbca276d8e24da5f96d5c8e762abf3274172f71f3d6575b5c0847b18863af69736bb7ebed18d8b68a869596b798e651d6fd792f7a49f2bfd1c7cca6ffa52acfad6bc7d70bae25af871df19e334c578e374c5519fd7f99b3e53d296b5e912e91ce274c535e5d77ff49f85466d733e3efa3e13dee7ae1be9c75bcb0ae4ee64f95687fc4d48c8bf3808911548e77c7cf4dfaad67f44eb1f71de1a1b61db25da65bc2b79eb91b2e637919435977111a977d54846be69dabcb54f4e57dd8fcee18e7047e7e606a72bee9e3e3e3b63d33cb5f8b99a6d7fab196fede3f339bbef99574061051356f068d4874677a5bfebd667ce380817e9d741a98702e9397990fd88653df758f5ae1afddb44bdaba6d6b50cc28dbb9ada0ad1ba96630e1b77b3aff30ab86668709d43b2b4274e4ea873836dd7de7c59474dfebd59ad71bb1a7511850a552c208618280ea58186eed7369b2a861862a034c828795fe523893bb80107ad08e20e0e000c721008873b380379b87b91bb5268ed8cf50e170e1e3891bbef70ff50f8747077d15d389876bdd9a6ea3d0e2d81ef7be291d220a3f74b71dbbe14c912b356d89aa434d0406b62f7cb70ccfa8be2ee3cb80b051e27f1ddf19f776d4789c71d3b23ce68c3e961e3b1edece4f0203f8787ccf951499e1e3d7a7aecd47478ec8c3f5e67ec41ee18b73ef30e1d9288826646b320fa439d489bff5e9bc3eed6231827b98336f949db84b351dd5588bbdfd8b8bed8eef1cb211a9b4521f9e4ffe8f454e7dfb8897e3ef51de25f905c03b8c86df19546a28b203b9da75220042af574e42923a3261962e083af166080182a70860e9e6a6a62c6075478389884f544004828ce6a01912074a0a9c73d01e01727ae5081b38210850800e1cc16676dd9b265cb161eb80a0147f8b8c20602f7a814d73a31857f392057d8b08bb90a01a910ecc4d0c3553b5021a40747a87b0d4b86236690b9337951021cca98817b2108e24905564d9c9542152380220d240eba7cc000e2079a9c554495274b88b0c55737c0541aaa6c7167d56f6fa1c4bf1d0c8539ace087bb11a878520aa20315e541410d30b0c5593f463046f9d980ab701005cd83aa714f4a0c880997039e3a52821274707a807f547486c034587016110790e2c9c813ce32a30706702086e61e4604d2500247037c35a3c3861a51a6b8fb0cf766cbfa3e58bd4fbcab465ccb13cd593996830ed2e0392b8a47aa5e1ecb6d78aa13bc1a5e4b07f4e12903802db0be564b05a63ccf51f842ffdcbb01acc173161095db5879ee799e4ac5e383f9dcf3bcd437e4792ceff3bcd4ca87cffb3cd677c291e7ad3c967f9e4c98fa56abd80bf5c0ef039f78a0e77d2f1e103ecfc5551ef8a5def3963ecffb5a387c339ff7adc0cfdbc1e77d9ef779deeaf36ef050f0bcd4d70a812ac5aae19de07926b4525e03bccf5b7d9ef7a544ef035f5c787c319eace5a972a468f058df07e6a45ebecfabb1c1e30100cc81114a197d0efa17010f4cc540d5e7a55c7500af069e7fee72b9bccf2bc36b7d3278dea7fabe94e7ed783bbc9617f37ddfb70af2747c1ff87938a9102685560c9e0c092a7c4e78aa2f050ff4529e7f461f7df140ffecca29cd2b40ca6942e07990117c296fe5812c4fc64b41f9be964fcaeb4979df07d22fc625e6a93c8f8503e6b880e37d2fabd6e7799ec7f23c1feffb60905a792e1f986af260dfe979a91bcf05e6f35a2cef0bf2b5f0b5f0b190f2947b36bcd5f77932a02b057e297cdfe7ad3cd0e6b9e4f060549fa7f26af898f98858302e9f576bc5b03eef06afe579a9cf03bd218f85efc7b7c207f3b13e9597f23eef83f958a09752a53ccf8797f2629e8b17e3791e10af85ef25c5f25aa0f7799e8fe7ad4ef86e78e0e7a940efc707e3a5be16bc54eafbc00ff47e7c9fa7c2f7e2b9782df0f33ccfc763e17b61a53cb0057a9ee7837a386468fda466507929cfc50371782e2e3e303cccb4e0bd007adfb7fa58efb94cc08119ba71969bbe43109e161dca70aa031459ace84033060f72a835a0000e34c0e249342f702428be78a49a023f82628b061cd160243740b1a4c5a8f20862048a167e305457c0f901058e1d3f6a8d2a7cd04026870f9a178f87069e1178685b9ee0a147f0905684166e68523e1b2c52601b8a23c30c516ccc708146635ca02890e0514a50729a6a09a7a000dc53eeee32b8832fd400702e711e2f23661df5db9e1c6bf5478f0f9e1e3c767472709618b95c68e81cd65d4951c6466a26d58127b0004fa091950cd46301410897144f2a550c2b86170801429103a21003812a560478028db89cf0b2020e013cb9e800ee906a0166af625a42ad9ed54b0a088e1795099e5a549e6e2c11c2c547aa013e8899c1936acb932a4605163cc56c58079e5c70d4f85840543b54067062024c0a4e0c0122f16483c6064deae6b5a385e3b56508d50cad1ed64fca46eaa70581a7d4919c1dab97d5049e52302b15401b989c9407c680362f42aa19583aac5458bdac96626ec4dc70c1e172024b8794118658a9909a3284aaca130c4b608e8a30b000fac4d858bd402f75930a028d6250587dac1c5833ac22950935bc154c4a05c6a452a92fc54ab5522e2f2b8029160e2c126c18bdbc582b969762813cc01da0d74a213523848b0baa2a9e6a4c4088d70a9c6905da1e79008b97a5c5690f480971db7c92ee2e91130f98a1078c4234aaae0307e8801007b4b8873b74a55ac75f4ca3519b8badad29baf608ed62a06b8fd0e8bf8eed6ab627bfc49972c0021ca085b6aaa9be5d8bdbd4fc67ba5dcb44561a2671a027db6a0671c015fec9c4de9392b7e67e136d8125d44cf7c48df4d6a02da0729fc35b244165329d1d991099cecee954739624c98b6bd7e6f4ada61673e7d5b6cfe6c53531e33d569b6cdf1ff31bfd9848c812e3f467dc16afb87f59abf96f79365d0d48717751034e1a18daaf3540b5d0e255d4c28a1653eee9a45e5cd382965f8b9e9a5fd4fdd5c2259af573162a55dca944712aa6fb7e4da547fc31632aaeb2c4795f2c19a0e2eebb6a8afb7506a0e0dae70c98ee62595adc98812039bfed4971cc40cb3de3bf160359dc47cb84010ed4fc22beb27dad598ffce724205bf3cb340e4ef588ec87e99eb8201c6ed7e274dd5a86dbe60bd9f9f824511bf3d4d78a5aa6b76cfc24b29ad8cff8494c998cdafc7c3e35369d8694f5246d93252f910e5fa015d22cae78b8ef898510d18c8bb288a22d898bb2d83dd35116397cc45a578a77ce52ad635b8a35b5f9265b7e116d012dee16a86281271742f43e600b0c795873cf18354f6a810a68a9c094b28eb756c0e9d60a186d5d05647c07f99f6de4bd3597df4c727af26271c5fdb30d8b291e2ad1b078e2c37fb661616261c4b178b9a658710f6bc86fb2e514281e6e5dcb8bb1a65893ae29495352b8220c770f6b3e77ea18de7446ca64d4e68abab5f81bdf5d45525644fe6c6d8dbc75fa5b54d6fbe55f5b5ea28cc5ff7c9a148080939502d8dd7db88b023d1e3a3d79de6c2d57b525b7d5fdcda74967564485b6aaabeeceac80f2d06657eed18a28332b9cdc37bed40a23775d29196445cc277045eb7873b7f704a0ecca7d31de3675368121bf7d699b6c367fd7b28efac99ac337a88aa830b7e3ae2ab4a03c39e7d55553cb70ba0e95650daa02c7ab68854a34920a2c960a2aee4e92958a274efb264c054e4edce32f7da6c2354516a87c9abfebedcb277165fd8cd375c8c72729e39c1fdb2ed11431774d319372855e2452a854d23c694fe2d18726058a597533293329d4435d714fdad19e4812f022572f05729704b04b023cdc3d4c92312deb38648f156f2a01971450a1eeefbf6e7f8d3ea9c3652905ee964f338733ceefc3cd75490183fbe3765f44ef9ea9766ad9ee99647f9635c9ee8be47edb27f11801288fc0935089a6f7899fc46304704ed6f6d964c15d11085296962902383c54a2e9bf555334ebe3c4fd1a025ac4fd1a02563c54a241200a77a65c739f87c8924cbcb5ed8f74aebb92350ff1f1497a1207d576f588ac86dae8ec2cd5cfd5bb6fd591444565b581bc9649276ebb941fdb2e51c6d7e644f1da1c796d9137775bccd8be0f563fd368b71ef265edc442b6c6397157d1a9e672a393e854734e3527f44df6c683e794e5ad2fd1cff849749a7e72a3121f9f9d26998f4f924896180a27f7d0e96da7a6da922506423e6edc56a79596e4c7e4a9795802c590d2121e96d090099f4b1493a7a6332866307922d5c8fb48babfb2a41f1b12f364c2d80889713a270c549675a4122ad176cf24eed751a0844a345dc528b87b8a983c7594214c9e5a8b03a0ec3c7300ce2bf9db0128689bf10bd94e5f2493c9927e3216fa19f2e384818cf25f1d92dd17f1f149723de1e44f0479e286874ab4bfdd5a9ab2fc47393f999f14b2f5df2cb94f13a7ebd0be9fab29fb193f89ce4fd61fc2b64bb4c9ab84a3a3a4b3c30012e4dbb5bb6aea7f1b4f0f9d219cae38243e3e5bffaea58f4f6e74fa5c6e549271ce3d6759d611a7eb506e54425a716b3c9244a415650b704101555c010450008f0460f19056436d48229b188d3655dc4902a96702aa48409204b8879fb37b674c6d6afea6bfb76b6bcd41b1425d509c3cd4e47d283d5e8fa0f83b6102279a9ca0e659bf86b78d4dfe5d4b8a00331000055f9af84c75d3285911d072f70364f170dfd7b3031820aca1e54625e47d24da6f1b8ed1fc3aaaff850e707400d03dcc914906f8c2003f78583f1b40c900373cd4fad426de9aee9a43132c68e2c9c323414ab2cde930a564c53561c43dacd48687b89818828b8929357f33aec5e8b6e1d7eeccc584c9840a5d2ca15b42e75a22c7132b7ebf4631bed15d59ab359ccdfb4d375ad6f3d6233424df34712677fac4f96fb7923564fd7cbb96d658a8afadb9214f9a9e50770fb7b6396d67e1b694fc8c2fc6bdee4890127a32c1297103259ee88aa32e2592dccd9a37dd3fd6d27429e1ae24a84842497932b1fb6fe4e954b5b54dda924d49d4e0ee39b8ab0059dc3ddc96e26dc3745775145f5a4b6af365ade2c6faf99e54575d01a0e8b3e2b6c515c00c0bd013ea8a43428b7bdd75e3dce71f772121c577fea66b491a0d89a14dfe3de9e3928ec8b51c9fc48db7de7c0e3a828a87e43db18d923fd2c7251de1b4bb3547314e3ac228dc6d33f7f4b34e721d11730f09a0c5afcde5af691d4904a84200a7b0e64890126ac3648dee3a7e2d4680210ff3efd2da86dc65445448fefe6c7e59a3251911e5663f7f13bed5658411f770ff8f34e34dda6a7e92112d2aeeb6b336569369ac25ad549b1597df28d4f45a5a73bb769f3863f2d4da525d752e274b2ea698a458477735655963f4eaf0e392643f4e1848262bcb1a24d33b24aa2b4dfaf9c98d4ab6cd592322f9a4cece99fb6dc57f5b6e54229bed72b5a3b5fdfddad64fca6435b19fdca8c409030da0e52ae28aab8828453895bf8b18ca8d4e38dc55442c54a2b988d092e32e22a67ccde651d74e7d4f229edc9568175b7ddfd4a7167fccd8e622622854a2e9fd5a5731bf4d249f08193c54a291f7b58f0f8d07fa8fd4a39373ee7be25ccdcf34e252a69dea116a53d3a39373521ba2a0d8cff849f2e74e7d3f67b7aca6e7a4363d67ece79618d7446d65f96dfe9389287e6d5773e4eb22a6119740bbe6273f89eaa59261b5582eee3d66eeae7abd72bcf0824b8daa874ac5549a4c37b8bb0a869c1eaf1eeefe82e1e505090c50e9188153821120a20c99e0c3dcb163811577f7187ec822cadd5bac95ca25f5793eb87b0dee6242777956db93942cf15059d620d2e224f9cbb206dd6f1af2a4c5294ddca749c3c1f57400ff8b371eef496d849e905c4f323869cbbaab8d5e7ca9ee2fb5a19fc34866cdb4382de6f0d6a76edc3b279ccd9bd535912c2d4e64dabadab0cea499cb386c13b5a8b3a8372eb5aea3489e48b79ab39f8dbe5681ead69fb3494ea4677ac891e4887c974f5d3f272539d25bdbf2b7c5e5a093380e37abdd5dbfddf7c44064697141aead91fc1b2779a6baf5c561eb2ae4ee41eeb9e290888872763327c4cce5216cabb91ae9df67cdbae66ae4fb7e6e567335caf5c8ddf5c62592f68a4b528773901be54625eeee983c917cf0c1dddbb97b4e9eaec9dd3bbdadddbdccc4dd333dec3e3e2b7fbc35e8469e368cb7defc4d98487edbc545bb3b7b7397b473c2d9c8079395a9c446494884d05d35dab2858c21844058400dce51e00494123530e38a6b810016402db1445d0a2a4d88219e11e507e082ac2f1441c58b38820720282054dc29064f88210113d0bc6c620c166c6003385e8d2882d3f9423d0707883120f042891761e0052b2880060c70210cecb0e5388115af81082f9ab861450cfec3d5a4044a7c208aef041d1da5e06ae2a14c0b44a480dabca607258638a37e0e43cd0bb430d108719a5a03683ca080390b46b8c01764c8f0e42a9c9143074570798e63c78c264550200137a103608f190c40052fc1c90b4d180942c95f479440054d249181db08017d4201352a4f35623610c3043f513c86ca929d12a0ce7882c919a1596419fc25688ca72c5570c05d7ab4387aa206503cb5863200011e54e09e584c5620a288243af8ea8a920c29b648c257de1542f40122573da5e16106368280573080021397251cdc81092526104413415239986d19c00d864a09a0290a53872b9e5231300a2c5e8882fac2908114412710e0e94382840b984c5e501f51179985224488f2d5f8e1441143977a57b4d8c009657481e349a1828816505e583c2080b082024510c3c84b92c50710d0c309eaedc460880b4ac8428b77e389026e68379e78542e4091344ef0e433c039326e0568f12a41ec185e98028a67c1c20c11c02dc41c8a13d89dc40870bec40e34a4204636e44334c14303352660c54f235d1809020446dc8a30d84d718228dec31446635491c593e3e09200db0448166e845c22c30f4c7721516025945b20e13448f1b2829a26aefba8460420f7038fe740c5544338d1e236581881011381171e8b8185a817a0ace0395e37353c79c089539b9317441089c15998d9a902082568c05580810a100709a081a300448e260ef85101372105145460070174380968384006481fa880bf58424c452441e4368c989093b4012d2ec3011f8800070e311ea3c4062c8606428739e1081ab8392306ee1204a5a01b362082b77e50020d9070e2f3d64b0c3050ea0012ceeac932f3840a20f8ea07338e3481040f5c0506095c801101ebaa9f0aebc10b443898c58c01127003000efe989201287478c05326c880109680aa9ec2f50007811c74e129572823c51737f807b503f0023dfae71446168f06a27f3d4124512027c6bd2358008806549e70af045d6c192ce1718f01b02258400440b8977f761520c270cf089473478c08eec950a505174c10732fe6c6029b0f28b89fd1020caa1f10e07e45015350118203b883e0003bb4ec92b853c08b175c81048b7b0358a416167cdc0be06ab2016cc13d005ab42cf00410ee4c5820030fa480bb4d48aa898a8c3b0f32a87d67e0c0fd68003a80a1420eee36bc80cbf18026ee400960818e133fb80301c3dc32acdc7b7860888e0d5ee08e3364bd20018ffb0c221765e423b8c7108431649822e5fe827731ba0005ee2e30118111472080fb0a35d07e7c0ce09e026d479622b0e07e82093af092c2c5fd860f4c6831b8e04ec23709d1920277571154c0c00921b8d7b882c40bacd881bb4c921a1dba30dd618a5083062b31b8bf848006fa810bb8bb54e142123350e1debae207266460e1ce3ac14d800942e0cefa968405d081fbaa88192fa70d779514991620f1b9ab6e8481050740eee093033409238a3b9842173e1ae0857bea0a99d60952b8a790d840b90114eedf10608648e2c6fdab6202251c200bf7cf26c31f39c1fdd3a1c5160280e2ee99114518c4e7ee714026809905dc3d2588503406cbddbb19fddc12e0ee015569920615778f46084af40872f7c01f2a600207dc5d071e0e11057757010f54099670f72d5a004528c9dda78040154980ee0ee5731eb8c1dd9de0e055a5e6ee3e14010d2e9cdcfd02008503b8b8fb588314272cb9bb0e31025c51c4dd8d70c45c51c2dd89fc60d78475f720518021821eb8bb8f8b89273877e75193031626ee1ec2e0032307dc5d061c383890c0dd61b0c2801f9edc9d266a69053cb87b0b4d869678dc7d66c9e5450877c711c5882049b8fb092e34616ec0dd4b98411753c4dcfdf50222b2a0c0dd5d2e2f58000edcbd062e7763e6ee31676012a4c0dd61a230d1c3e5ee2f4cd048618abbbbd45498c9e2eead9c0d027004776731f1540606dc7d7582b2c708775fad401343c8dd5540e0d0438fbb83659c4466dc1dbc3350404440c1164df8304087bba778422203b8fb570327b090e2ee9f134f4ffcc0ddbf249831dcdd7972f658b15964c9b3de9bae3557f3e29cfd5aaddd9a6f4cb60da020eeee4c487777171331a5837954451837b6fcc0dd4129514c6154c206aaf87077af06267840f2c488066ce1eede113b70a126ab7eaa70770f04a920566003183ee0dcfd1bc00b371c6003184a6002774f01a1073d5460025c24a007eefe2949810aa6e09841184bb87b6a4a0c019266aed00191bbab68c8c9a270e2b3b9c2dd3f23436a20e3081d4708c1dd53262861a50c27a06ca10277f74c090000030f5062060e77f72c40819acb6c21050aeebe52c001a23c307c8e10c4ddbf3180b0c40f693861031fee0e2e80c64a00ce044b3370f7fd77ebdf373bf48e1df875358f1c0969b45d49259af6f1b1958f44e381bec6818636e45b4aa3d5fd39fab89d7150b875ed447aba2b8ef6190759fb341c1296650d0af7695e4b3f8769ff423889f66f2bcb3a86b4b2ac41b4b7d9d01bac3933fab789788be2bf0ddbae15ef97dbe9b4e6ac28d455c45bb489babf22de228dda70599becc984b46289b1298619db3e87713a6bce7ebcb828c45b0c6924d18c76f11dab356748629871a51b9f4ca8b6e64cc86e9669373bf67d5b8e346bd65dfe263c6a4bd29d7e1b3aed9ade6622e1aeb4d930792bee5a32633c9678c41b67f335b6d55d5973789f955e1b5d446db8fae8fd9ade6c98964fe29c3ec3d7373bbbf1edafcd3567b3495a5dfb1b596f74b77f5f4b6434a3a47d223b31ccb9d196dacad7db52a0300ca98dce0c40d4266706a0d8be95bc3fea2729c5dbe66da90dd07d5c0e34245f6b1c79928f1bb56975766624a468764424cc6fcbd8f6e79f3724917fbbd5249af8f9c98ce99735ab3536e9ee6bfa4b9396189bb98c6d35baab395a96ba6aab6934adffee116ffa4c35a74b5bf793f4e65ded9df6d678c828d4bbfc27139ab12d69dfafe567aa4f7c71c68d77a7abd611d65c4d1b164591469f24ce26c54228cdedda5bdd9a56aaad0de7ce9cbd368771ba70f74c2553fe1cada415f5df33ecf177ebad7159c58cf5f84e7f312dcbfad914456d6b32c3fd3ae35d4d28899128da9acc126393d27bbbf6e6b34985921851bd735b639b0ea55b631cadd96afae5aebce4db2cb5c13651bc38d4e43795587fa6e4c64d63ad519bdfa7a92d49dfac7944dad544bdad68e6324e0cb12e6b0edf201a6afd99242bd5e5df5b71a30deb7d45263932fcf34f263457ddd561925ebbad69c7cf5accfbe6d7db86ab2886afad2e3f6e631aed7318e94dfabb9296bc75a4d5b43f7e162fb6b4d9671c4422a131ed6afb85c48c6d62480bba5d7b6f168916bb287fedaa7848afdd39d905710fb5cb5f3b1c4e3a70024198b1cd673cd24ae94ce76b3fe37157271c1d16d74d2971d24b0745a7c4dd431d4e531996d2260334d9b82b2db9d8f2b08486e49f669c5bd07036a4e56109cd76ee70aab05bb0a15c1dbe4cb89b3d6bf9cd53d34dbb38ec8bb5160de5617e3bdab2e668d54fa1d6b8480fb910dd3ab17898a1f8c599c93da90d4ed7a1d8cf9f4c5ec8f849b28bc995ad9938b94c94d86c98898bbe501223f3cac64d2614770f4d236a33b6bd4c9793d80a7e52f19273e7b6c62da7dff7c7cfe2d638a7cf7b8acf84cd28d7f47a7bdc6fcb8a489235072557864a34f1f7df6a7e3223d9164826d3670db23519ed2aee2aee2a927fcf6cca8a7ef4e7fe2867f70f5e06f110e3235a6dd3ac0469c83481274e537a1faca636363cd042f2df44c25463c2e14e5322ad68b3abf1400b773b5773571bf56b498beb25289c7554dba527e412cd7d0927c4a1da2e799285b24f3686d3e2e10bf7c4dd71381ede4b77b5a0db15cf46478e86e8adf4f6a4e486e3a1b6b6a8c76d9b140fa9cdba7ba849224b7e9587e25ebf1c9f86132ad1ee9bf83d54a291564828aef58f24ce4325dab6d79247c6a890fca6fa1aa5f8683a39f6b81e5d3530f2635a7715a26b4feed78c3cd4fdad51aff55571b5a7d2aad09ed094b8d3622e6a0995682215f1491cf2dd787f6bab7535772fb1872baf1ea2844ab41ecc1e7094b2b8bf94a428392929f912a85089b6c4892f315a42b5f000e5a112ed89f340e30167872828dfc1c90e467edfc43be0c0e23a4cd1c1e9a5431071bf7ee9e00a95684aaab82b49c0dee27e5deeed5473e5dea2adc9041aef4ecf709bb43a11b7717e1ff4e3c6cf39ac7518a7457caf0e9325c623169d6a8eac8fab4c1897e2ed5afd3e58fd198fb56a736d12ff6d22796b4e6b118bb6dc84b7689e4914c039c987a41c18a7a3d15dcde6df4669a6dd341ba636b47f1b6df66f13df26fedb44d36ed90bbd4d1472d3b95dc57d5fcb7a7c7cc8ad4553231d45b9d2121b8cd3f1b08486d9525d71afa3291e9219db6cb5261d3d31d5dc5f7c64e4ae752d6f88da9556d7bfc18a1b947878d26c48fdb8bd77d5157703ce0d2e6c6474c5bddcb8c9c8c93dd4e16b3414deae110e47228393bc78acd844a2c41d090e1297874ab4571116772f82c24d4550eea97f57f5aedeb26e6bd651466d6a904cffc6497ee3243625368ac984e88b654c233652b7aed55dbdbf71925d3da2041f71b97b686b46b46821a8b29c198152564d8de0fc766d90911e0f33d67d0e465a78cf5e45aa58f22bc5bbc8114582e8dd33d1cf61b2de8acb2238f6ef6c88720f5f365c711b9edc3d5f9bfdbb970d384ea33b4462ec94445c109961dd95d888863b920867084bb6fbf3d0d3eb9bad66ae8e43b4d7b61ee9be8846af1db22102e5eed5081127770fb52532e44ec415bede2fa12bee4e858e92d0c7ed22212a7eda849cb8bb108ebd65ac752409b53cc4b9cfbd8654d1f80e6142f6f9dc15e73e37c408e73e2792641d12fb212d0f956858a0c81702458813133685e4102ad1c87b0ac982b6ae466a365bf2b5add9ac63d0134146dc431a92b616240344c543f25a4a968fa37ab4ba0df4837ba8236ded05640372e56839d0ccd758a7a38f4b9a51a129f140a3f96f179794246d4de835abcd5c1e925f9a6726ebc9843ede543f699bc80f72c53d2ccb199dbd8240710f5f41704186dc83d01aa2dc6bb8524307dc3da477e352d76054434cd4fdada15593594942220449064566ba6c4826030d57dcab99b344e8ae9a3a3e3f2e898628428868c8cd643531912cf16713a96a721c227eee1c2223af2df213c5fde7c943255a55f2135e9b1349206284b76baf92c8030d0802800c79f944b987485a47cdd53471cdb70a859a56ddcca7caf54180bfae6f24fb0409956864aeb876b198ff76b379fbb8dcbd2cabf8238b157f40b907fd781242441f97f4e347cbc39a1825eb67dceec1e2eede0315d26ad403c5ddebe360fcd5e3430fddd5529f179bf6d61c2e8bf8cb8795abc3a40f06f8c09b9a55a7730dcdaad3f4cb7137becd967407ddb8d495478bbf266fcd3d797379ac78f8241e79a4f06822dddf27f198abc9d3727792ac3daef498d2e38959753d708e4bf17bf4bc7ae0e06146fe5bbd35272b31aefdb57889fc5d370f283c682f1e74070b6db66380d70e939d15dc43ddeb50a19383ce9743829c04e40ce5cc7078f0c27902c7c9c3cf66ee4f4d146e4babbd5dbbcbfaa7d63735345a8c925fbb79e1e0e0f01d68cc5e3bb4d831ee9809d1f030c762bb6b7e5dab3638d06a697316c96a4bd2b27d85458434f7b086d694658dd15daefb9e256e2aeb2cecf1b035bbc18087341ac59bd2688931ade6a7d19b21f25e5c74432d5e32b18d96106f7c6da0be66f3a4c886e64eadcd8f87336c99610ab5c17b776b89b1f99a8166337dcd80c3dd5f3290b62646673248e0258391bb87369a31c59b2ad17c7c683cd06b6732b4428a77cd150f31ae89e2e1aed4fa4bf27546af1aa3d0de7049751d2f119dbd6a78b8bb117fc5b2843adb1a8be2545f3127d727bd3616f39c2df3697be9d0e21e9e4c9eace34b47938e1e2f1d5f0c54c26bb10dd71ea11da1e1edd2c88b6b7809efcfc5f044bb6fc4a91ef1f1a1f1f08a01c7b7ae653e75d10b862c7bac4e0f0403153f77909696181bc1b084a9e6f2d7d4170c405e39b2fcc5b8fcdaaee66898038a53cd51ada3c43887510edd5fb1ac355cdec451f757f757a6fbab4b4c5e0c54f376fa6bf192786daec4d88441b9bf60513c54a2c14caf39f1051b7ac170b8bb4893c59d06ea4513c5dde2251ad3dd69863c54a2bd687078a8f4a258442a2275628afb69cd43259a1665245189b1517e1f9f249953cdc9763d0ada358b5fee8d336ecb6a623259d20f0ed44696f4935f74aa39f15a594d7f898fbec459cb927ef2b300e5ce42149c3b0b41dc672cb4aea52b507177aa4768fab5822edcdde8feee482b92565c2196b335ea3553e535e3805089b623c9fa1b37c95e6c3e1b511bf2f5296a23375f2a68ab823b4d218a3e639496312d0523f7508fb629bfdef8e6570aa0df5e38aebc700ca1c43f97f5dcf79bcad7b9c76dfcfbd65ccf1bddf8e2c613e9666ce67e536d71e4f8f185e3e585c2c6979a1585261ebeb61485174ec8e21eee9b5dc36dc95b5f2770e0568dde078be4e393f4b76afead9a2728799db0e332d98fce27aee16ef6af48debf55a3ad6b29a336ef834532eb0ffde8ece080f725a2363da7591ff73e58245df413a4f7b5356f7df12833fa193f8953cdbd0f56d7e0741d2a8ac98e72e715cddc293ad59c282bfa193f0929abd927126a232bfa3162e6f21091993bc56b7340331cb6ad1d0919ca2f931d0919fa01fa193f09d3586b1907c98aa8cdd08f98b14dd455c4a3ace86797f71da26bae55ef13977b376113e32cd6d75a8b2253ae3a1ccc530f8965dd17cb9ec441babf75572164fd21b23e4ef65223aba136d446d4fb9190481c94442489c6266c8aa425ebe332deb52c71503e75cdbf1baf4dc4a279e24ce4cb9a354f9c6fbb8a385d87649f71d089c58b45f3940dfd64ac716ada888f8f8fcff84ddbd6a84dcf6981867eb6191424bbf8f79eedb6fd193fc96edb1bfc5543898daef977e5ab46cb3dd4a5c5e9e8cdd6d5466fd7daa02e253592974c14f7f02523e41563860e7fc554f18bcd9386b87157f27eae396aa369483492a675b82cb18dea5dd5bd629ed036beaf1825af981a3058dcc3fab917cc130fb57dc104a93f44afbde70b4626246bfe172ca112edf532e5f55284fb93ef8345aa91c9927e6ed73ad523e4cb92509b22e2c625d2c6a596511b9288dafcc64990643f41fb7e4e964412ed4722ad115971b9aba6ac06370d91d9ea1bf9193fc993b8e867fc24d87689b6c646b86d7378b5a4b887af16cd29ee6671af56ab159a486e701105f26299c02b2eef97a2d5892f96d38bd5c372bd566290efe393a4c377558167d2358949d72d7bad68af55cbc3b23c6de4fd9beeef67aa82c2b55bc7970ae7faa51af21f6ff84b15235f20969cdddbfe1148c5c1a76a1279814174ddf8e6627d82383c24aded73b58849d7242aafd493570af74af588e42b7582874ab4ddb63299918fcfe7aa7d7de6eb1b7a7d36fef2b2501ba6943e2ec9c727e9e54df1a497f78471ba97470bf7cb6bd5ec6a2fb7425f1ee5e546ee2f8fb9d7d9cb7dcb94708b93708b120fb7d02364f1f075c599478072f790e9084f47303a020e235871cf9da4119c84f67746a0b95f6c049a3bc934b2501d6940699bc693ffc5370d2569c4c2671a6b2e42d417218afe7cc3d9a4d7d24a6db8160157041e398caf0ca7eb104e575c59d69c48045a7edddbc4bf9808389e3bff469e77085157863065084f3e04a350892692f7b47d1e028e330d01a62696cbb5acfa73368969ac7997650d92c9aedd9565dd329bd98bcdae2c6b12b509a236d40609d3587352eebc5d4bdaf149d1a9e6aecdd9f1c97d3fb7c77a5fbc36776d6edfcfe123e2e76a7e36f3d674b4bb6ead2386dbb5b94cca64493f5f9a6752109e8434928816841e5bda6c185f0c84a81cc67706842be1c54540b800258764a639a3ba529208083beef56b3bd7c7dd2f458ddbe74cd4fd4503aad6e85f7c040d21704023481dab6da62d89cbbf71375bfe20ea075642259a0d8bfbe26c13af15f769fe60caadd63e377d36f39be629de6acdc7476fa7bfa5ad9bac8fab41a236496262fe265c9698247fd7cf3e802a4b7cad0fa0f800e7a10f5ca5ddf7a4f99b30d565893310a433b2787806957cd6f289a90d9ff1343b03577406f5d7e15ba91634b47ca1e529dcf7cdc76d1d2ea9b65a9478e8f4e4252a2b69452d38ccc8e20e152ad14433a298e1142ad1cc30720fcd885d33dcbd0c28f75cc6b6fca60f65e0ca5012de722da3e5feb9f6600ad575ebdb83c777f7a0c7bd07ae5089b6f1bd270fb0f0c002f7d4d9a9b95d7bbb9607d4fdbcede02ffe1cd63b98e2e10e9e76d083ef0edc756fd381955007523ccc98eae840498d6e1d97ea80963607583cac4772f064476d70510e681ed29acf3817a3bb5b7340ab2e8b95da2e0b942c41bceaf2937786031db8cbb67e9bf11671309423e280de408bff0d40e0bafe7cce26ddc7e96433a77a24e31be0d4bc3fdf405732b0e419194f9c8c21df6d3270b87b38c695319eb8ebb2ac3b8f61e43e1ba3860daaecb6ad399b77353f531bf2673690e2eeb8c8064e5c36303d24ff856c30a45d36c0d96d3337a40659dc77b7527da406556a20c53dacc19310a21ae0c21a04a135a035700fb5ae9dfae52e1a60d9318d7623d120cab65992d2c0bc3a7c533b916810730ff3398e98062cf7daa965b7cf3232563bf5bf4d74aa39a3fb194bcc3596195c99a27f064e2ccdddb73d99cca047dcaf67e0f2da29832c1e2ad172fd72a402c526039324ab0c82883258c16ba71649b2ce9cea116cbb56a665d4462f695b696bee6536d1bc991bdb4cd65e57d6db9764f95688dad4d45d85509bbaab9058dd55c816438b7b98abe3d74831a0c488a2fb22319ecaf2472b4690fc3a204b62e070874116baab516d61b085d66104032618189d78476d76358a936630c0f1f008067eb335fa822be10ba4d48c695935368b5e5056d70b70d0abc3e4be27d63a76bc7541155aba40cadb5c5084bb93567c5246446d5c80e38256ae3a2c4d389b66bd42c5b7f9e358af3cc15de9c9d6747a71777f3bfd1597bfc6e5d88231c4ddbe27067a5b7e8d4d9c4d7157f14f52cc78d77c8efffacce16cc3bb05389c0569380b2cc0029abbe3cd82180b5a619630a6b88761863561d0ad698c86e12109c61530a884e4eb2a6e17711718344b7e1e5d60e0086b32b64d15f7356d73596a2b80e261cd0a701eee6b7354d71c5e410dde314aaac00c1544d1b8a4fbb4113284ea70f935bacf9a0a9c76353a5301ad3d496d68b4b26e9cf48596b2b44c3abae30b28f79026f4c5d3ec8b2054e7ad3fd3ddb6a43d99d8f28bd637e5ff5cbd56a0ee5b7982bb591cc5785bc1b9877fdeb7d273f3d904b2d2a269b2c443e46bb2c4b822b2c4ff19c8c72729055452e0c4c533054a5210732fab68fe33a1206ad7f1b3f9a4a851602554a2a1208a5d9f1445928869c44648ab75d6b75adafeb3ed043c38019418bd27ddb62f1f9764e909701e2a2de16109bdb313e09879818517d7d2fc391a44c3bf98b4619a76aa476854575c92cb0b1c5e7526c8620229b4ea6639d87689744c80638256a844d325b82296608a6ffd4d2520c2bd29bf49deae2d01908f4fd28f1306aa65594712946515a790c049937d52d495e64e82202448c171dbeac83fb148da6a3a3de9f46425712edbc4f7c1ea2aa6bbae42436ddad16edd4506ba20bbc0f1f099eaded9ecca5addb88856dbf44a4b6c785842bb68f908b0d4cfef83d523785213a323a0b98737fab9ea18818c8b280fc937c9f2c463cd7f675c40dd6b69cd8f8b28174e98b8182282dc496a4bc98bc7d73719dbfd9ad62c821188c0741a8de276c63a4ad315278220ee8e13c10d4de25c08ca0801145af3db7cb66fda643c0b01ce3dd4f67154575c08703c2473d5659c04022baef39bf4fe787e7e0d8228198f9f29089e4090e40281cc07a8b87fc089bb7bc639fa015ad10782b88764aeba9adff58196bb3b75414d710f7518f739acbf56d60b6586b46b8f7c49773d42431d2e29c64150d46b7e1aabffa864308a26c29e754ca11901180000000033110030302c188f886432c96c4a7a553714800377c06288569d49a3288721849c31c02002000000000000002000d692dd89a2067f7b6868408e3cef9c792264d6a9893ecb9337f547eb263b8f97f54c86315561b9af52f180927b3928bb8ed6b64fc379229d0329e7ef4f1d0bd5123c5316ccd7a42fa5fe962db51f80a6364c218bef71d9802ca7ac1b03567ee934a32814b2985c97aac948a27a9fa1407cf43097be70896858a65dacccab0417aad0049f2c5032fe0865e686883715965e84b5fdcae6a94a193bdc42205a996bb002b5b2f1d2285723d172634ff5c379bbefdff2fc4396cb92b4d533f16b0a9e3cc01e14d7801312ae61756c3b234ae4f231dd9b38795e28ac6d6c4c1c4800fbf44b3ac03664957aa7100bd196d044e9494ad1a70909ee631401b06a2b5e18a463501a1781b35319b560ddeb94ee37d49dbe0c64f8f6a2a5e285a446ff43a164abeaa0ddc014b095694f76b5ce674bd987dae255e07ca50f7d361219dabc1322cc951c5435786746b9c1903d70bca4bd3de12919f4259031458abf4bb8d5d9ab27b4898a5e2df74190481f739570342e47ccfff9c25c4012d27e95939597204807e26ef580c429348e7251fdd0139bbf9def2210e8787b7768bb077004baeb212a0406bdefbdef162f660deea2f8f91f2d8da70f765e52cc5832a4756b3684bfc646930a113510e8eef12c50399c5561e11a72c361b48a5b8c5dc704e1d5e4c8ea0d2a180ce46c350434917d4eec13cecc98adb182d8005e12bf46c4cdd21ce40d37179071eb607c25857d15b3337e16155a860716f6de7743fb0e3b70320801387d5d96267d9000fdccab6b97a8bbeb8c3c5349f06c34ade9d55e478f81cf4c953b5934f568925651b39fbc1189ce152e6ee806b22c5e7228d32053171ce65b73a9a6d7123cfccf7213cbfc25588d19e4e9b461c4324d9a187277e73bf3e7c4992988101f2b10a078bf6931c8addb5a967977d9b5cd8da716e2cd1e9dcb72e9b7c27dd17d1d6ba01123c2874bd7b7880e82867db26d3e06c5c781dd9ca7658f5570345ecb37fc5a30334450e6605eb604ca95389613868a9db08d3ea8ad11be6ba665ee423b54a8f15d6141eb13e674f13062d694e73b333cda5c3675f4116ae51d0088ffc0c0d573538947e23c1a9f468da6754b3d537c844458a7774236bd371a690e1e207ba46bd6d36d6db941695cdc27f32faa4fc41d2a2407a00da6839f2a3266dfc4e9b8cdb2363a7f9051c65dc0ab40946a59774037094f5586975b7c00fca6dece8d16d04ae44c45483c7aafb3f439c2b3284b644d3e9ec26763e9731996de31b4dbd32d991aa9eaa80f8f2beddffe196a3b23b017d4448882024b0cd9a0cd46dd4fddb96292ce6f711ed2262f5289a3505557ff459f37ed732795ef85dae12c369b7300314bce1d16332b1298136fdab84903ef32f5ce1f95a2e217afc9741b96e17476853659e391c1f7860758f5c7f2b7478c1dfcf2b941d9e350476aa7fe7bad4f8309219c304495c98eeca0f59cec3a247b242b173945deb09e7cb36fa18386962351fc38dd2c9603252194de5c5d53dc0b9618c51af3f8d84e28deedc1e1ec0ed5bff7479e2dd16308e459f9f9231d684756250f0b6598ca40a318f27783ce9c19dfe45eb6b1a66323a9ed862650c7874bc3942e1c7cf22d91df652d0f529025578b4ea18a5f6877e226cc74b627dba170cf7ca4e5affe79b45a9fa38d35819d6906792f99eb1c4bad48d8e15664619dbdd46782aec32a17ac2d0ed4379ceae582bffd104a0c16e4fbae119c9706f852bde270bc1f530300aeef99bab4127a2e48124c6f9cd6df15ecbd751562aa42861b6f15b5e4ddf3c043061cfcfe2d961558b497d965eb88d77ae3de2898e0e1bc43a8955f41478aac0b73b34d04c0ad7adea8b94febfa0dcc3bf528f9d15c8ce45bb309aef887b25cd9bfc4b0f812c30c352881eb7a3a97a424031c85b5a65f162c1fa24f3917568c2d31a77f6e9ed8f333a84626584156ce6eb3a87a3ce448db525c8072669dd6b05a3a2451eeba631781cc2cc221d8d93eec7236bdcacfc99790598db92681842e4e81c9e0b8be7d75af87964f38606d640832ffa6bcf08e164962e524d60df90587e0248663bc1968e11ac416acc60ceee93536e010f638d28cd350999fc4d30a5eb05695fb7c1468b104e680d2713c00a338df5506a4a30012f38e463fc80a8c406f3dd2d73cbe528951181c316c0f79a79f5b96a7dacdfb96e9334b9db791e42618cbfd378d0f7891d46c6c0c86159163b5c94ddce1bc71634fde9c1f13b09b6fb40043071ff639d4957e714efdc8226790f68afa6c176b39a40529ed207b66d4f81c71518a4b6ca03cfdd2b1dbf8ec998581e0469abe2eacc3469de065e0cd865953059a6e24014ce1caf569ffdb333b2868abf01fbb42e2e0e512c409aead7d76d906d0280e151dd0b43f3ad491ec7903087095a3c7f1f175983020bd029e912a7f2bbb27803a37535ed42e9cad87410f0b115b864630ae285c5c7924d048c7110e0c6ea9af3ca215edf2ccb7c3995a0d3de5992671e4719eb3d9c1819eb16e9ebd8fa91f813845c532f8f0f04e76b31fb2ee172bce5c3f637f32bc75afd2a42797610a5be64427be1dd8d08a16342cdad3799aa2094a52f07a2fb0ae6a5b9593451ba1c4f84206b91af30bed3d8fedd2ad3bc2ac36655b539b07841801777e295f8b6a748744b08239b056a0e9976d4057b36385efb800317c07f726e3856156d5bb43620abf7b8f0e4a73f3a8a0edf4980ba59cb1473cd846011734061cb871cd393264deabdd6b4019d8b9bde92a56c08ded488d180e2bd1633e18ad28fdb400888bc0daf858edddd488d98100914dbb3f92f8510904172cc9731750c9d494add9b5ab7b66bae94c2ad31f9203d0d333cc64f70a9b1e244e1f347052e73406ab32298a26accd9a8b8c3250c6293e6e84cd6f24fc938a5e03503076185c4840b651bb9ae8b623100ffa6c170e818fccba81fc2f07b822e0a3383aa802231612ef81e0542ca13b2edcfd502279a07682ba47d5cf8617ff750f7e718041eeb9a6254534cdaf75ef291d72e7b8dd0fbdf57676f3734c400d159c385541fbc36bbd54572876b727fad6db4501cea8d5cbe0cecd41e6c28f3f4b19a5069832c0ba05d85f1c64d940f0785a3b294e4566ca81d66e9ae38e27e49edae11c4849fec4709cc064c8ff54d931414403b7d7ec72ebdfcee3ec27c360f091bb0e73dcc7a598c05812631a26c8d84af20a8ff0756a6e4ced63785e79c3169aa533c108f78555279cc61d7612276f8e886418efb8d951992c02aa0e131ecbb524ad68609d25663680df767aea52523482d78ef6f2da448bc51204f46c61b7c120a4c9f1e305a61c73044febc879f31ce44d8d1a173d2691ce5c6ef093aac95245405e5d63f6e5ce8c5884a75313826d3b824cdf636d496f457f4ec94e4922068f0c282209532d0b23a696f4c1c4b9fb8b1815f732ea36bdd06c1c374321214922d31233a500c9b46235f97f40f413188c717609a7e33308f296782b3a9fcaa10f27a01e7e8ae498ad90a81522d06de26c91a800c3099a615ccfe986fc466e232c15b9fb97dcbd6ffda675fadc5f21724bf1c90410aff2bfcf6d765a0475326c5ac1c599a52c79ecae4ae2595dd1aa454b56b4f332d81ad75be1bd4f651064a0ad015244d134cb321832b7ea7b48a89130aaef2e0a3765b517e05f29804f028d192519677b71c2a65ae8352cc71a311e91aaf5b480dd6c620bcb96a0582c95cf9b845331e4820ac7db96f526525f3863d4c65edec4255d6e091a039268caf0f38fcf88f4998aeb39f8d5321cabbd7060bfcc8f1580336c5cb6e8fffcfd00c5c0feea9824252e2ab5ab793c1cec4ba206e962cccefe55d55b700e5be40d0617f52cefa172d2a25474d0480a9b44036a34e1966f9ca779b374451c3ad4e05010704242a017b33e60f9ef88c277b9ccddf0c6d07adbf319c9b428c72fe21406d19b95c5ccff68aaf8e9cfc066245943bc05302e53543fcb7765fac3c5a684f29b1b3d7ea13404b7d905dcf85c126eb1b63176dc3f1ebf4d01774a9c0b95049163346d172b77bbbcbdce79338885ab3751e8a2bbd98aa40c435d2ff3e0f7b8333faecffffd5cd509d6fd852e63354d234d24a54f0d16ab89342be0bde77a0612e735c52f62ac18c1b557a850ddf85b689a682cede2c646ff4c57e2911a800e3db01a30ee5c4b20e876aafa71489c7c18e2049ab20cfd82522c210a160416fc426c50983101753bf39abf65684e1fd1da6e546652c312eeae89f6eab8d1722d4d4c5516877f522024e79a38022844bc16844fd28238a8114b11f1b6478e5d82d224ecde4ab18abdcb1584aad43f6bf0877e6ce77717655fba907edff2a6adf1672871b2833aa4f5786e468ec7fcf87f77f5a5cd0bca068ec62b7f1e50d13eb16303f1fc9ad7c1ec73439a41248a2424d0af2735298335c619b9c63b89dfa247ca3a42e8d04334cb0239258df2fe310c6a5578c4793df17447986cd41ba1a012db8edaf09f0a74e622ea01d893ff3a67249c9e0bac52b734eea15c422a8fa84004fc3bf91dd3dd004334d4f61e700a19ee9934803449b5272c8594c16a4a82fee224c2f94b09cb7a59309e29bc97d613e0fbe8876fe0b449b6e98fd207db11278c2bcac673ad076e4dcf9b4690a0318ab7c885664fc355277360d80107ac9dd00166da455c52883fe224de2c1e58639b5c72b45502c91ac2b8c5a0e37b5fb7b918f58037ead859dd27937fff82daf8fc280c6ef60eec708f3d16607292b6b566015f62c6b9347d71ce205cedcb41eeff61fbbfbd43f457ebf209761ebc1e00dd024a6a37065daf3e06aa5514d470a2b2dbcb363f4eb37b5e351595b7612f043b9f72af906cd725e5884fb73f19c201e625df7468c089242efe7e21ad677e56df6e7385ee0224e2841034398f46f58647cd33e1376a2f3dd665d6f3c20056c8c80a191bd015d21452e4e8c7c2a43decbe279af5c3d321b5b15112aa1b49882f1bb6eb604303ee11cb1c5ba5e45322d89e3b6d463028915bdf4b0155f47d127483af7238abf5ccc77ea30da2bcb5bc0688b4a028465dac7209ef3f59b18ee676930680818db0d00e9bc1f2ef747efa46fb74dc0942ac96f37993b345d1cf0ce981713f4cc0882c313139f32ba8aa0b8c79296d210d3d6b3c4f6b6e65fff1fbe9f50e1f573b4ea1d907377c9b6c87666aebdb9f0e34921dd45b509fd5224243a4ee17a6b500a69dd2b42417d2abd954754c3abb6d24668f99cfbe4ed879265bf8db384bb25bf52c9e010e7714029b9c8abb735130592a33191e8e6f739421113b8f1347d2d64fe558ef084738c390622e8fcee36875436742264c52d6749f0239dbff42c936ab380a136032f94305bf9e5b828231aa82a4ad801e0a56c1837fb3b761168e84db526247b7146e43f3bc39bcb4d956b26e78bbf770d22d8460019579af65d3432eb21e84b2ce4af85ba5ed1d4e3fdce89b7a1495c09665f5f1d8b5fc5e414ded8ddaf5d17ede24c172c633cab581d69613b550bceae86a243b65a2aa2bb5145fa1f2075d23676d84989c0ea7192d28d30e5cfb611addb1dfdcfc38247df832f02a615bffd7e9090054979df5544103d7c009eb2f0c97d36f22afb67f48a3d31b9b19372dbe81791fe6bb51e71ca9a2cf50eb859f8eb5d526fbbf8274c18db9648687b676840916c314cf498609f55db69d86cb07bd428071bd648007a187d04e2fe65c255feffe7723b17fddf02b78087df57864f36d17064976402f61c3cfbb200dc7d504f6087bd5f8742a673a54a7bedb1064543569159491cb8e66cacdadae10a4fe48aa854d3e2a3022ed38b420e42e96bafa616399106c6b0fc1ac83894b45ddb6d88d49a3f576472bc7ae1e887b0b09045ec44c14b4834fd6b865a47a64f71a853c84d1e131414a941ba5ac509cb556df5ee452a46895626506979672a023a8b3e8f718590152a7654274eeb772d68f512d7eff1a80a91399436d0d41e7d94ce31dba3131b9062a13dbf2e5be6987900e99ddde5bafa122aea35c210b77679c876c74cd111675762a84be7631a4fd9661eb0c21a4a0301cdec30275d2929116a2ffa19f50cc1e65610ea94b55114aa973255216f7b83bb7edebf092963a700b832493bb8620257cd16150b4495c90484e6d8536865f2bf3a7c06bf3ff79bf067df0c1e9e6a70bb1301a99a92bfaf9bb8bcea2b20145220cc0afc0f10cce828396e89019cf57071638856a966c84a40e9bbd741a4502b4e88acbffbf39c8e3e3d6c2458016c678fa588aeca103d20719cf82e358890b00c2654358361a021f224c680ecd596cf725e973af931e74db1e8eb73b799c3fcb91faa685a201c6a5336404d71b9afd72d2b74d5be80d6a0c52c00bce4b6d52b412deff49da6fe558563fd9a653b3f443465856d2e7a8721d6745d777ce6f2d6958af6fe91cbd489580905a639d20094916c0f171d72136874e4c3c2244c77bd5ac10cf9dc20ea6f28f818af27451907f0bf02320830ac0ea99aa58da056b01af064940a38f32507f03af3ffd773f84e270deb07a7bc0f22effd3e14fbaf7445abc51191556dae1aa1582a3897b75430bf7df88f98a5577f9cea29117be6a1d4d578768a5e0358c661d52f3b2319024546145937467224d2fbd9a6ab75764560245d533c77374316f89bc7ac32afe312e3bc0e102f7e74db087e70b7ed29110aa0e6f1b3e31ecf8699769baa465aa496ac453828b7912e36769c9ba06fe99e12f2c17990bf55ea20dd6e225aca9eb106b9300c8180461e1168cf025c28dfbe6c5d13d200b4e2aa4b81191c4a801b5783a5a46292bded8b21ede724351570094458e03dee6c9c9bb75539b86d22acd600fcd075ca71b0b6458457a8555b6413cfb2403853e81307577ab586e49842ade485779c6853fed15cc1da2a61d2e5dd2834379efde389ecc9cfd99738893b28bae06105ea9b72d9d59cc5898b91e93cfab75c208897245c7c4ddcfe864b72d39de6a96f082e2177d50f5bedec4a22d44f58517619aa814ea747434893c8a757f645ac97fe79de2085bcc9d0d9aa6fa407072c9a3cea7ca7f863792b42dc5354a7120168c5085d6069b9a1b796e59a76e1b54123654b0291f90d64ed25eafafe81673d35a682a077003904d9e5aa194d3e24649c3990ab32b176dc58381e44505ce42ee792bfddb4be6c093fd42321fd83529d9ad1b37843a7392c3029a4a07f004cf179e7b7b287cd477a5da187c20d971679efa0dd2d02a888146fca9036134eafd9236cb5ff7407e3ef1cecb60a014d5efa4a68fa0b271103d584f258a0b7a8e31f8a5d692d7f91b165a505efd59c2b63e9efb4e46e2b33426c70594b9ed7309d676c96b9ec4ce82113fda531e46852e25343d65342fecfeacace8630935b4a520f340304ad55d54d0a11915563a8705d265f404c5b399ae313be65d41de0e074a1876c7be57cac69139c0cf42855097306fc1e930467cc540ca0ce60b0bcc47d172cc3a48cb72335713399636bf6f7191f53d3bf77c2644ad2da57838256b2f94f609201e1675d1a28550421942e9e7d1bb37646b3cab793b4f10c9342105312ac5f41551b0085c4b460664139b5820041a64502fb14f75a4680e517adfa42ff7ead1de5e4754407c42cc239fbba19f41cd6e7d3ce50235f084d70e0930c03e6fbe4769637cc0996ddc9142a7be9b9077a758057a1bd9fd15ea85598a6306d574e851a003eb124d01f227ef13c6d67392d0b5c14903ee672ead8d6ca558ff0c4e78024c888763afc1f731d74194b7933f06601b91c728801837952e683bb15327e9815b74420a84edf96736c59d47fe5953b82850fea506205627d2a9862e2b9ca52d602893c6c66ab85843ac046f2835bfcf384b15309e1eadd7e40c54db38ebde76736d7a34f4cae109fd1571c488d26c1bc20ff47563241488b9700cf227db5c10585b35c76c3c1f445eeb5c9121aa8ac0bbdcd95f35a0ce8b4f353a92cdc680128de035b614b43a3b2ff2b83a4841e7bf63db986ce1a6d8a664432f238545b160c0b2442fec0a8ab389915c3ecf0606afd76f105300fc505cc00d533634a581e6803154a89b9c1b6ed49be65335b7021b4607fcbd0ee135394600f3ec68cdf530ec3f1f914c74ca5d02770bab283e297583e629040790b7a72b8ad2e5dd3cada93ed5e878baeb05215770fbccb2f250456d8c8a6cd3e54c135f5e16ce08a7407526dacc992fd8ba0b5b7d1a6ead82fadfbfb453bbaac76a14b5c5062436b6a66768589dfa7de18a75bf74f2e672828e0fe166d1a148ceae954063ef922a0c586dfe00da81a82d060437bdf7c1731a8644e552c4b3c7688e13ea891840b7f7b1171cda475d4a6291f4383ac25da4bab0802dab6a8e50ce03d3d91b280a65c6eb141c1cd32e4d625122697914e9e90665f66eb960274903719ffd75992c97b82ceb31a4ee4c0856ff2dceb058175f10743c3d8981e79521b3d1552603c440446311e3170d66fdb271015af6c983a3a6b0c69920e88b388d83789010877aafccbc8c92cb42c6bea2c359e34ba9ac82a1f49163a545bec01f6242361bcb9bafb8c6c5c482ff672d1db032361e8ea805ee1e4d949fe486054f487554fa56aeea972a015bc40eaf33804848889effa72d6117b33ba0947c13e9b06426095264a4e3914fd7764dfcde39aceb7797a0d2374db0b335be381acd50ffd64aa375d20ca56ebc59d3631fff38f0d42c93f2a9f7eaef12c9a1a7dfe11105c7a86b045beae61a9123239c2f725df263d154ed7cdd0be06a8417cef1a9af0b7c745bdae38cbe98dca6d8e0bd546c8de3ca47ab0541b7fee0eea3d0a0c096c8dcf95b6c34e4aceec201d85d25e0d9c460af3a17c9eb0d1807fc2d871c877ac8f556996ba3c80a6d43f8858187acaf866b68a143db8601c3daa06cc3bb14a73617c3c6cf6a6b77c7c152b82b587bb9a03f480b53255ca5dc86201436023d740c13c5988f7766ef155ce320ce0fe77f718f867011162c4c2ee5864ad41dfad3fdbd2c36cf56cd7c468da0f69203a912cee4608f52d9aabaf8b81d5224c5a3786c1c601fad2d7070c45973fa8448957be63bac6f50ba3685521d04891bd225e3abbbe5442cbed448e050b870e1362576ef10108ca0a70b8239f6a637a0462ce1becee6b3a9c800c37c86f8f72a549f70a0575373ea6e01170d4df75a563c1caff18268dd36d50069a13c3225d5b2988a306fb8d7d934a7b4f67f671f39e00f587fac140665b879f005e27a6b6cc6524141377d0c6191e6e534172affffc9976124701a3681a2ce395c7e1ae7aae5c147ca799df11308f16d98c186f6e0b1b59e226ab43d90731882c9a8ce361360e299a0174f7308a51798a244cdf3518329837edee9cd701631e806092a07b2cb87b321ae198250a7e3235103b136d81619e362783364a756a0f8bfb3dd1ede1afbe3be1eca091b71f2c437f1e8a56ced8479d48830488575029c59d72bd9b942be5a88ff2bb9a451bf8e8d4263e4e1c0ba85dfd0591d9ada146f9784c35748a3bd05f7104962012ff6e3aff5f65eea6963640bd6a6ccd0c09fb0c9bcdfd46d88c3cfffa16f09586fb6d6f20256ef4b2d5f88c9d4edf57f26787315e78efd0f5a808913bd3c016d753504e3f793b6ad001f624981f5704f764376d9cca78f1c60408c2b3469ca016eddb2ad279fc8c5af5de0d90c69dc19b412ef43400051f42687dacc64d0367ab8e1dbb5d3f76050ad93f0e1e9262ebd79cec9d219509ac0f21750283e57b8c0942e38af600abe4abf2132ea67c904c610da4fe76d09b104335b6d67bd34ac676335d857362e7c2c564b6e0ccbc7271f92a57372b7c9ca079143663c05500820ce372429fb448ae18d8a1d7c5b60d52418ee9c11072035b779f9158082811d473001bb0e46674dfa88d47f39301818bc15b7e9a9a731ab2d9ab621646e3ec51aa0ca1d1347aa852efb6eb3e67a2e19a9ecd364edbd4a1b6747034c536cec00ca6c90f7182ab8e8c00b719665ddeb231ab2ca31df3e830881c7ce8c1d2da603c6cdf1db1781a9cff36a1d86a798b2250f9095885816c59b7ae419e33543c35ba9533dae441fd109a46d036c88f0f468c0a6c49bea41ec18f320291d3b274dddcda7b170b7712cae036b4845e0c652078f69e7651d9bd97c7fac8fbf3e533ba4a757da34a73bfa7e2fea8f6d950bdee5df158f07174e22a6f3c9392f37275426dab6240b5e06c5671c3edcb50dfaf6246730408b89f4bbfd0971dc8d19c4ab9b7e6a9d4320bca1a77efb05083e29d040fda88883789df0281bdd46506e13c0062528648e0e0293cc40e004a4cf342df98f8d4e8286fec94d5f6bd40f804c2f2b00c687af67e214ce2e4202da16c0cfb6a68e252cd01507737c531613a94be624316b5824b089cfe043aed0c21677d251ecc05105c29d561e6fe6106be4dff004b18c6e3e7b0777a2f25f5c2ae29b1ed3825c2b8bf7ce331f5890fb64f32cf71a94cfed05cf4f76dc985f6f84e1d7d74f29d508e5ed32dcec103bbd6e1e1acf5bc23109a3116a172fe275320ad8d681214fec5ecc5ebdd0a18614e40da19d8f370743c61cb8e8911d008df0915806210942103874b4853faf938b694f09b3cf753d7918dc8efe665955f85ecfb239e0bb0efbf0b83971aca6a21fc7b5850c502b10ace0a8d9afbb069ebf844eee01c7191bae6a68f4a2224fcaf6e23eb58dad1631cc113e2c67b0ea031af5921af81cf61d4af209ccb4c70521ef61fac7a412db67a30b4014dd9da5582ccdaee4460c45eee091d93079ebf993c5efd0e4837b719abb9dde887e95aae9316bf1edf08c626bb3ab2a98e67ffe55b0ca66069460c74bcb37bca42e42d59a233b7e554bb27513e32958ebfb04280b44ead9bbc433eb160da116c30f3693b46969c572a9da5ccde2e3e36f85a5c7a8db98c072a83fb4c2904503ebb21bebab497e1f89aabde79e1db4c7d8e6e5aafe633ba773cfefbf1aa17647b4a625c36bbf0b8ea929754b67d35439b71bb345b871837698b54dc303498f4804601737296d8ff7a5ca884581741bf00b761cc0b171f50280318f6c54e31d8c648b65b07efdf28220659b05761b00edb2b3f734fdacf25888d8e194596b654cda7284b3d57110fec4d5bd05be07c1a45987272677779d7322ee6b107c292f973e786dcb092aeffa9ec191a3fb01df002e3adec76a73e6a6b3243d77a83e37bc8bc20856c1f9658fb710a6e43e417423a5c5db093972a83733a4bd4752abd7c1e4ccc97baf772f9494426aabd2988f060f70226f9ad32a7129f9322f5f03a05ef01a7764811335a4f57c47518dcc69cbfe7041c5075a8e4fed6eb510f0a7d283d1951be4c6bacce8d2927b03dde1d38070d3faa3b26e1cdba50d90dc641a78e78eca96a4979ab6faeb0e1a3837ee9a2a1bc535b0108dc8cc321601946fad79d6b6fa2c0e22aec3aa911bb208e61289c0a1528cc2a3ec824d6d17881e51745d4924ec126b607cb5ddc3ca4d33f7805bcf7f1f369c4f62fe5a7ce0fe53282fea88fc676cecac58c96641e7f22e1eea4aa9aab2a4b97b6a197a2a2370fffc791c5cc2a0b2d33718ddcea4f97c11a490d454145bf162a2117dce86672afe6cca8dc70f961bed2149f694680ec8eaeea075a3c5471dc2f0ff6d5c8fa6c31a074a0c7ca3f07d2ed3cc76fcf22e3175cb5edcd57dcd3d11a763a5d94f9b500c006094a1bf0e7a7f32a728cf9e83283636b19f9dd6419d320c1d18c3cd3066f705adb6e59ab500f0f0d992dd6647ffd76427854f61c85295c61d6f035e12e0c8a041edf77e6b4e1bf8bd58d85785de72568a32c6782de63c489c1e615cfb6feea25a16e9ecd019e9f0c416bc3f205f035ac43eb239f63b87e4394ba8b845746483d05b7744c17c6113090e64619231b7a41ede21d115cd64b8ca036b3765522fd764e55dddf925087013221353af6193e25c4171887334c8b45a86f814651b9986fa2e75d9658052058f6c1324a17fa934194a72964312562a47b4c4b36dd46b373f67f1eee87dbec414deff0707c240b3b71824ef42210ad8bb5fd282817374d07165644e4a24aa3f43d195f0c85445fd951317b265b1a5f3ec013927b5cf44aecaa24060d25a26c795953cd0ba4dce3251d529cc0076eebe6bad17d5efcb7ccd9b21c1ed9efaba2e8ef109b5cdf949aeff3444b2def3dc7eb67452d93582b9160445667703bcd5c8b2155c0b69c6c515581b4f433621eb2f3457b0964514992490de25a7d911bc2f4a534224ec69c019a8065d2ace735febf8c7db14139c890983fe19e81d8300e025e24dd9d2aeabf22bf16a183e71af5e4bdcf2fb5edd38571829d907139755c2abe51a30ce629c271063d622697f4764b7aa88cf2b11a666bef68f03c359ed4e0401bd3a117215c84d74d9fd56cdce188383c1182eacdd0149cdcc56ceee64bf45eb35ad23ed1499eb744755b8fba566312992ada51ff2dc136ef3f5cc666e36f05c8b0ad68d5767073542c63a63441016cfca9d1f821aced831a451961bc27af3bf1b22d60a6dd286adc19005e79ec5f916fb611799394a334795f41e1c27f214ab65e3ca5f8798701003711762592bc55799e1ae4a5ea0f75e9b15e4793f3957315206610e819ed558367fc55d6b6c7db97f7c676302a6425aa305658cec8b4e261f1703e096e1d6563ff049a6c4b2ef33db3779ac0bd0f435013d3c9224c445cecb3c03ccc59ba62cc46599412317ced2c212cf968759d61f339d71de3f35eaad51ba9471a98839d8fbcad2b60253f275e6528e6ec972c54edb22cfcee39cd7722fc6b3021d2e8b588e54850a72a3f620c390985f2d4ff0d171a4b674c28161884778268cb7b93f0bdd600a0a6ae84cb8d7e3c4f730c867900396c23b13249fdcf70f69e4e5043eda095216db6e5f5bbd35ebd6e88c119e320774a9c0baea5cab6d866f822ae4d79f88fb0d4567733820cf7883da7eacba9976844b323e1ff8980d0d62be90f38d3a8bb526436c5190592bf08c4d350d3a54d85069103cd0b28604f083ad047793338e8f852018571fef004a0248288f6076c84933032cacac02a879cdb3010bfc487cc6361352717c2db4b8d542cd67dc761ef3aa4ee88faa46d9bd3813d3ffb9c9ba80716c80f966525cbd60854a8992a04575f075ae0423c36ff8269e4c528bc46dd1b67c73c258431078f7af81602e76f17a045f47e32dca309fd5de35fc7d117d0d617cb84be88c28514a0f816a8d37bbf50ccc0bf7cbe0d34729b8c3740cdb4136a0b4d1b1146b041da8882a23f07dd932385122ca069bde25618ba96e867c7994bdcb774475ea1c84654bd88f07e170a0c3d3589dc4a78f0fb3c49c50c1b600ddad3eb0c90ab0b50fb86d4ff11d6e0bd155de7370eae3f9c853223f30af395e62ff84d6b63829e9a1f782f67764cc8a9429ca3c059e84c64096a7a34a7cffcefe328547c025a9f79b54fc8823b930ef078e21c8f94e0bd38fa98b5bbc14ea71c6c70e152aa6edba4d40add7ee3171072d091ca9b63be6d7b3d015fa55f1fd3ddc32dea2a70cc289f15f63d01089ff56fd4b64e72c33d2a0dc9b0426eee2762efe234ff54d89b1fd7aebc04fd783ef7c0d5d034ba8337cc3b9d251ca6e523afea8e71719cbf2bd85ad0bbc542287200aaedb865babf5e0c0d902081e6df944155baedb24e54d3436fa2fc8608cb66001ff4bfed3633ced17b38d34301206df25f1cc6a8945147eef20e0516f14564a1d9431eb6682eeb2f6fa6fe40c5174beeb90ed3499afd894b1593f2d2d7d05da7fd5e171327f5f492f8c293afd11e4d55cd7f573dc8c621d3c4ef6a0ff81fe0bc7057f3b02239ae521773558560becad8b4af2ea5ffddcaa39bcbbfc4002ecc370d3e05a6705ffe398331ebbff0a251736d848feb922f8e185132cc8998153847a18c9c119787cafda1717b5d3181a9e37b5f837240be2f6e56537d17e776db5fa263bed3b7792b3c5f1a6d510bad1fb3529eee500a51772b6c010d1624c69bfa9d5a9f766f7cc9ea397c3a156f058e2a218b78d1cf49265f11244207632a212705b8984d3afcf355ac33f71aa0b227eca9f86e27daf0e2862f885264aefa63628c187b3ea09525e40b5aa30ee504d6ed2d9ac4013eacda90411f83a4736209166da428ba68a1aa56dfab2cc1aa1493840a1cd69b6a1a51fae0402146b8aa447b52cd0024663f9a7a3082915561846b787af984ecb90c926f968cda8825e2029cb627f699aa87adf871b23fd14d97af1540d776edd03785d7aab90c4914417fb8190288c1d75de49a306a5a4b48e124feb24c75ad0a4494c3278627238926884851c6985815d184b218a32e700bf0374d538d8e4a70ae455552cadbabb450ab7d8db0d2222d559876eb8688f5c4603aa57149ba99c2b1721f96ef91f82ca4dd1b06be0d9144d2b97feaaa5a1f16365861aabc1a9c332721cb4b93fcea6aae849570d5028d36b82a1e9ca24a0ffc20f05e862cc2bfb2899becc43ea3264269bf4cb88f140b8da2296a201057558966d7c039ad296410b5659e1b55b6e33883c6bcc6724f98c106770c50dd6c555cadc4c5b07d2a3a81fbe1ed672a4c2776dc8f9ac45174b5671ad6105d0ee6938cbb2055a62244726d70952e4e2ade2dcdfff0ed176916de34570153ddcd05f762c79ed9d6dfb82391296d91002c34307747300ee38ebc92236f7d4246d96c2bbd18d9bdbe5a76363988fc0b67639199ddc7053e1ef9d338b3f658cfa32b12df363a4ad87d69c51f0c0eedb7c0522bab02bdf2dedb835adbd91f64831a582304bcbabea915b6fdaa16edf708277c1daedc343b4c932989d2e79bb340d1e3d6bc1830da8e03ef29b05e1162666505231af48249bce78a562e12201edd9dbb4062380757f76dd9f8e052165e78c7478033ab7d7d111912861f7477be502b7f839e14c02bd7c3622e09ce8381f3afcd884e26fcfb83f4752e78735813d38ef8fd9a21c0f2a0d6139c2b508ffd20c0c3f5e6526e02f25bf1e0afbc84b15ef174b227023e605b9850af33a9cb2d17a4e040defaeba4ac35ec5f3d363d822f680650ee722cb407d022fbcf524fee25114f218808d617fb676f0bf762f77e253b1ef1a5512edc394d328beebdb972f7cbd24f0c6dcc152eadd18bf56e50ee0f3ac18a95244d06b016b221d128379d41d6cc017b8ddfd195fd1c1dc9f807cb75a9872d0749b85e27d8facc5f461103825d149bfd516b32182a769e16de3673bbd8db2bed7f23dfad6f6459446e6a276531e4a161b1469bae6314bfe248617329ce6c1209bb8f902bd8d903b2278a5cd9f367e441683bb81cad4ea6778240685d79d1b88113240bf0a97172c773703f9158064ea64fe4c2f4292f3d9fd2082779dd282e7f9aec53c882b41b40c4d42e2d100a8f651e6db9820acbbadfd8286bf802b7724978b19dbf92658f46f265cb15cee4175eaa42f364eb5d66a7b2064a26c10aeb381c443a1a717942110c1cc67e0c7533a1d2d5b653ad3930f952e45eb7311acec8aacb8ac6c6eba6a4c9bafa27cc04c270cd7b9678538d5ff2302b3f99aa554fbdd15a4e209983d60e4fd4c6c12c216cd8d770acabc0551a99290b681d11dd58c6efb199091042d28c665366b4ed0ac35dbb3846c310f52f62084d82c55b0a92558893926c90d8b32fc7960b197133dc2f666a9057469db3e968e36802017fb801836fb26131b8626b3a061fc73233cbbac745d45124fbfa36445bb6f3bdd19f8ac595f1a60c20d7c872eca07b86f1fc20d2e4a55ba38d7f296d78ddd6771af10cbcb93d37d35f4af67e33a32043e1dcb1a787997069850e609b74d196da0992076b9e404739ff38af40c94bfb1b88cee9f984c993d11532826113c7344c17f2c593048883830e7bbe8750204c270b00b4dd384f93a406b5d23ce895b7243761f45517b3d46fef80b8143aa0613417c7f71a96e80cec9f7bd71b36fa3c64af1d15b0a9987fa66ca7b443d5f00f39d2ed8000e4c05c47a67c2afccc7379ae6281afb21111f57c47490fa7020fcfcc25710dd40a6b084a7399d7a7354538e7996a6b4126d4668a405834f4e3686ccf45cde00aa9cfb2618ab4a5ad8899ba07d79cd85c79c42b7ed9f3c267c50e49b61c0264b22d762314c73e77de76b5ff649825e026000c5dc68ed967c0e6d652d4c26e7fdb9a3be8c64dd27df6a7c1b55e41bf8dd9254b31640c776474d3b04094357e60901dafb573c9c6da05ee60d54e506e31c785e594ba693cf7c20138546e59e912908752284134dba3e52014dbf9b48fd39800841806dd05cedbefa3ba386276064bb1570e07728b77e9eef470a6766883ee7fecc3822c4c61761db8b373e441a102b7b1c032f667d19168840355ebe1f6ccea31a7c902c8d60c4cb015066301d5af094acc4c04c9d5b75bb52e0b5aba0da9ae5096bd81b5e325df69a7e1b0ca9c827a4902fc4b5da0733872d4d8606df5a2ecfd9d9d19b9f7e351ebf2da402aaa03a1c77cbe16e222894dcd043f730c7b89aa36a8b585eec403b69a4f62d0578bf9b3c0cbb984ca9a697a73a47c205612092b3105f6ab5d5aea6fcc7465591cdb9263dc0330351085c787ba0cf192ae0344783fbf060eba3a7bdbf15a8c68ddac44c6c5c6462e35d8be1ef4cf0ad6dbf85b75eb3581173089744257f98494d9d65b5384b717bbf8e7099a747451dbfba52c60d091f7b3d77ee41b6ddefe1b8d86d5e266ba5842a616a86b94fbc9bb757ecdf0433dc992afe08596d58da5362410974ef0a792b5f434e2d8b00052d8a8ff5f777bcd789a4ed9f619624791093ec9c86d012b09859d3276281991ed5dc5e18bcac27042bc347618daa3b48162dd2482f9a9c225b7fd4eb9a7b7d10dfe3d4270fd32cec23b776d0be60e0d2bd6f2abea0feecfbb8439386d416db73a38cc73fe648a58fdd823e27763b05955575de47d855943863bb314b611465614474834c1c4a7f87903ba6d2ffc5132599c688bafd58ec6f28b8e717b5ea0bb1653dd517c15c00420166ba130fe9e42dde84cbc6744fbaef5977bd17218032b22b0d4807a23ac5bf220925c1a7960c3468fc82383bad9020e22e491974a60869883d3db8473cd5f505b3433e858f30b213d7b77a261526704da34e2cf722e0d0a4952bdcc80c154a580e5a7a027e698015829caca8b824d551d45a082626ae71ca263de9d3927298188509f64d82b998077a587363294f0cba7bc35f12f461707c421a87947d44177356f6a13734bbb10c7e29e6bcfb0c4531f45e8fa293efd48e78fd515335d6960a5f71784460846bd6a30687163dbaaabaa410c1f581af9bf6b3b66ccafde309c4565deffdd24b6b2e6d1f2d5f9d452697b563007cedc5155f5839d6c211690e8f82f0cea22e42a09adf21ea86c6b54895584049e6617b41fca16a97dcc4ec09bfd4abab60d6e65d9403ac8836af7f68ead51456a7605a6d14b438f2bf8a2370cca0df9811a7e1d966256a4b21e90060c3bbefb1a8148fd48e4c160f8c11b58100ac11eee836f94f5ed150c6012ade08da277b3389c53f5f82ac8e24d62576da106b05e4f307bd01f208d83f4319c6a0264250fd61e5a3b58e2df578143d1a9db5f8d4ecb10cd58969975c3025183f4e701773eb7ac113f1b31befe3eb1d98e11d462bbd40ffb76e61860b0f35fd3bbb72ebeda48975df67bb60e2187e13c498c1bf81d736aeaf9e3b14582ab5a6b0e7d511f69f099cc17b1e816b0c8091a51c96b85837cc70716114d7c7dd71af98b2beb54c7157e7a8fc99307073e4ff45c09f2e1c45b6c4ebf9841aee17cc3626ce99c429f1c11e9558ec644caf42063ae5d11b760b7a724e2ab48bbd4cf1418f7edab664ac7436d65682efcbdca79101773271f673900e7eb83e6a3867481b9de99bcbc6aa854134063415821b1e04666dd18e52fbf4360ce420c4418116941a6e8fd6b114544377069ee2c419a89069e18591246af36935c52bdfac49d973757206994ec669fce20b3bface0f25a69964b02aae63648b753d8b296cdd014547d5e8d69aa8cf7179ca81f2d207481e3a47e510cdd9bb7930d5a46a5a17f2f7e7b079b07a85d15e5408576daba48656d013c45dc4cebce0f1dac1b0497d703164cb57ab687399d148dd49dc430942c759565c0b056945ee2a64c97e67e6bc4819b5dc89bb408b59a9765bfe33f3bc6a08f5da75b847579b6d533e4af9ac7f94b7620051e4b3640e095b6d3e282064aae4f97631b2388bfc9181f18274471ae9ee34490921ead08a2023bcee3e67e25f4b115f5bd7d9dcd6475dc8784e44cfb58fbb8ed660e352af9e467568aa7a6de8fa4e6de8c785cef2ee8c6e7a0b36e4eb9bb53b7b7321a037198c4d30129b0c0f638b0d5968983f0e138d1c5b45cc6b39720900f707d59feed717256cc2341cb28edb4b974ebf51fac3fec9edbbd572aa5fd96f73290f8fa39e92216a9cb06629c8d79083a5f2098a74d112c3e4016d9a2430f9529dcd0dc05789b4c517ee166fbf62b9c21f45027245fc452a3fccfca450c7117e23918d012fda738a23407fdec53882a80f03431612bd3ec1e17ae8c87c2268e7cbd18c763cf9b075399da6b9ad494102f5ef8531ecf130e81016467fc79ffd72e7d52a6c18dc275dda76278558b7e780f102138deb0dc90bd66054c7bac7037e2707bb0b972d72786cb67dd7196b30e7275255dd1127bd6d8db72532f13c753182b920b8d346c7723046036cd52dbb316f0f829aaa98595fa86edd1662835fb3294ce1c819c823948604c563241845a31d0786be7957ecfbf0e87059a34fe30a5a7344bd0d8786f5dff2f0685853401ff9dfc6667805794ed40c79394b764298df48011a521f90e346138e9f69749a98a091bd087be9f94a8a26b2a4ec9e5030f4395c0c0808398054e77179db13ffe1744d554fd437d70beb2f51268b91ee315eb7cbf96960a24f1f32d2216da8ae3dc664a929e96cad0ea00aac094da530521a7b12c52aada4ea5c2ae5acf8a3d349d2591547cf8ce2cb313ae0517c8aecab31b2fb4c755611a9f07d9c6b10d4f2799315b0b0ef8d16027b26148479eebe0f348dfeb922cb8a61ff11c03607f98a86202ba4e4f9158ba5561f9bb00759ff55a9bf5590c58b593e3ece55f5ebfed04cd9d128c381c71d72897dd94c4c6ef4f621d7bbd79267fc3332de3f05ce3b3859df76032606cf32fcfb7d68ce6597311fed4064fe87e231227dcc40185f0d7306c5b430dc83462f03b7a847019dd583a4df0c52de23336a980d84dfb2af7ba11c963ee8d9d72031ea9d818d247a2eb83a0c3e8e27856ce324cc6c78b0b3ffd4774872a2150dd301e14e473bb8248acb86904274b1987549b01cc033974353547435b51b747dabf3c348db65cd701caaf62a6b08ec29ea7ff119674acb8cd81bfd186ed1319686158684d484dfe69e628cb05d0c5ec9c1e63c6f98d67e48a296977112e2661188f8a92789170d3361f4f6f15ff930b9573e5549bb9e68a591e13968d68ded6ccba9f498735d142e2ceda1fd5fc8b9b306162dc327c3a26dae9b42f43bb79ccf419e82d0a80c701b709692881f6efa7f00ee5ef4bddf95cfa8c36432ebece689d3f113b5e513dbd8e10263d1b79a98bd5f9a1bfbb0b315e37168d248b1d4cd72b85287f864eb95c903189785c5d704cf3582360934cf29d9d775636ef971fac1545d40338771aed5c77ed2a620a262b58913335da03f148d9ccc07ca94612f8368b183de65c1395339150cf7c69a657afdd20c9f469f06633be92a7f469ebff3edc82f13e70e0dd07a0b394461b8c1991079a52df31430b873db1f5d3701790fed938c0b2888ece2df23a6f44e70e580809178025cd8947a47ad15eeb07772477eccd366c11e043f5922d9bf04fc3450d6aecb4f544cb4442fef217c2f7db6b51857e122ab6e58c39dd369989ede7f0b69440d8a6d0726e2c8328d9896d304c790ddf09aa610b9200d70ce522edabc6123a89327a60bb3e597839fcc2da3b4a6a22155ba1cee8eb6224d4f7862b86c75b3bf518d22ff061cef0f01a5ef68a7b92948a182b59d8fb32ea6e6a1da86eaa1df2c370448e9d93a1dd2bd5593daec6ef0990c06d8e0300ee93d635a0f9d53408f4b806e7e38bee12521d309ab776087cd9a37495194b6d32c3cb94a2ab9c8ea567eb6aff2edd6280ecd1d17793837a3db2da9a9c33d2fbfcd90ebdc08a5199bd0164e058a1de38d45a0ecdbd67d6700962d530cf4baf5792a499b43a2d2c383864624429d08f9a0c1ff18c1cd18bbbf4208cf8280f2083b3c1e897f3e7b8d56a96857865a0637150062bceb9c714dbb7f803cba8f1d7c26e00c4c73abff5c4442b0cefcba549dafe6f0da63d03c09ef20351cbb13c7a0237a5d83111c31b55b1382c4dabe1b10af440c4115ee23f6b3ec1c233b9943220079ef2225046dcab25e1c2836bc3226364e3da6df1f1fcb36316b3a07170a36ccdfea5f3d9c0f3d5e75dfdb32c130645f0118a245ded62cddd065052cfcf806422b7380761620c50010b97bcdc7c626fc0e93ad02dfc4a6c96292655eaff4f90532f2c24b7106b25f2e54c7e23b5dfda345b26766aebeda9ca78c93855c7e20aaccc3af00689bb1f1a427e7df7b4e9b37935c61b17c6d9004d6809fefc011f6c060d7e808c793e9de35fa3039baaea499f8c6048b0166194a1fbe42daa2c4842026bc0585f917f540fce614512aef1ec8983ea0bed647d0db83ecc27a386605ec94bb7627de399262e6fc603c374ccb0bcc2a41b767a9c32a7da16b865f4f10d9c7f611963f6f7e82d88f15290b313ee0e338ff66b722f01117947d1f0fcfd82d74124d1f7ded47f54891f10e6e59f1329d487afdf9c2584918083a7fc7d1c38901ed14df02657ad3d43f8dc38c73d50aa271547e5669af7e07989d6dd8aab1161d903a44da8f50f1cb535b42acb1aec7d429f10bfde9b20a246df8cc3cd97b2149b22e631ddd2336912044bdac180653dbdbd9e166f669fdf93b1c75f1e27d1ba010b67c51154db4c1546189c17b475449a0c69f84afbbc3786a2d5ab3e3fd6c2bb7c7744e35b6587753c4a7907ecbc8064e3349328e1a681497bc8abd956963150b6fb125ebec489b631a4d5f51703ba77ae4bbabf8f1cbf5fc248aba904813f07b1ff7193a893cfac2ad1b11b481400f0a684e518e1901b9e154d87d6949cdfb72700f0503d08b7d10025ace1c5884c3dfbb00d9ccec88c4103a2b8a0b92723ddf39950f699e66c853066486a365b10d51ec75223e92d7ad4681173b1dc79b4967293f3f413cc8521bf01ff8533b001c380a89b8e86f7f47161671b44de5b4ae1c1607246c27b71cb027eadfaad1ff84e47df05588a0fbb98720e9137f1e7cadafbee0d86c30dc175b4135b9a3a005a99a2f1b4b5053489099e7dc81d500a700bfacaf324c0a1bb373490ae3490e289508239ea7074aff54f1b9baec8d55e4b7b2627cfea5dd491243b3d34cd47dc29a711fd01f6da9e0b057c6d33f8f1e50b96a9a76c4079baa2107492c4da4b1f9d3938508345504f21a93bd4b5c4ebf75a55b0ab25f123f9f46e985f7e58490ed05d194d9d084b79c6f4a6e5c4d102964bb13cc576041158364bed5470c03c52cb60e3466c2b06a95157e9be192ad7f46b947c47cfe2aaf60da08a8befa4bd67eddaa9adaf4c8e778cb759349ff302a8d530b32fb1a5dee688fa70168cd2b90a43691403318f495b6397bd794ed5d5e3beda7004313a2986cc07d9305851e09b30a4ef2895058eb0e9ca22e80be677a15e03903818491d66d17aab5c86c207344cb01c679980eba63ff75df7a074351385bcb1b805e393ab9beefa05a746de06cf5dcb1af48cecdaee0f0c18b7071996ed7b613b6d0e850a7ab4b847352d8bacc7a9a00d65be27094f30194c93b0d2528809658412583caac8aef4add0059ff81a10d3f24dafc58739dd06db8a8c3562a9b21854a69a68dee22860fe192be791622f215cb5891ea9933aafeb9015a8400f2bf5c98a203802efb29fd9eeaa70b06ff8b3d7d1c140bde5692da0e375d7d233b02cdbc5b067ea6691dc42ac7a470db5d236d14c2bd227b171de4722db7b912ccb0f66aab8c1a44b61cb255c890ad765c4371b3396cdc86f198e3fd28b0287a2b2f35d4184b40543c871fc63a6255de5a766237d6db62b8d0845baaf9780cc3ddcc77663fada52390fe35be01154407ce2b5b98c64f0306a8ac4a84f7667bdcbbd2bf691931e51155171ee0766fc602d9d5ffdcfbc6e0a6d0b2f5585d80559309cbe1f5eceb4908c5e0530c0ca6628c480072d32259ab078951042053476c84e95bedb0d50fbb3d2c386a7c0cb6e94292dbc28376e8a2809c8302e8d6c417aac250e1f75a06c54b71ec1578147b1147b365efb77e269c370084f633453a29eb9f73b73d76d81ec6a1ce46d5b929572386799e7f7f1087ee10a4c6b7cd0a8aaf2664d367b0bfca7ce9e18c79f372fb3c037d0e97df0d68246da3ca98b3c39282c7a9994d67ee67b89709f7cb396dee1d99e7ba219de9c18eadb9c6911215b55266a7506c1950c76fccb2e41a75f80e595e4d2ab0786f15e579bf817ad3c4a6ee00b2f908270af02571c135d92a6cc59b9db66753fd32819f73da748c5c39a77235977181675e8fd2f9ee5e6d0d67786b48bcc92a448cfb4bb32d04f3f560cccc0fcab7c20ec7b4740a9db580d493a12520127e1176144cdee11427cd944725d2749c4bb88c1e6a021f6306ffcfd9082b652a274903d438e117ca7e0dbeed27adf79483382d8c3fa7a8030e4c965ce9f0a23411e76d80f020d8a97cee04311b8a7f87542b335d7098f26e70873279a3db4f6c05859c9a52c30a8b6501be30a9057249791ca95725ebe971e2c68d50cbcf1a038497a1f2e3006ece13e65c0db13931a939bf0b7eb720ebaa72a04738f019730d274a50d19a2e8f868fd5f7867f27fa384f1b509433789315b5fa54db8741ff86e1001e04a832b5e42a3f88afe7d3cdf692a9264d625f3d18516e96cc6bc050000b08334a46ce491bf38e90ec1900161cbe50ee14ca9558fe161ca327cfc46c3f35ccf0e6cff3ce613af9bfc66bf5aac736874bcb16c0b6972e669e89cd603571e026b6a05d2abd874349c1bf035cb2543eefb6c884e31641a1310adfd1c9f741655ee2e582afbac162fd7f0ab7de71f4e139f453576d54e2aba00333ef7cc1808ed4e593481e6894c75f8e0419462d348f2515c25ff81433c3fffff78bf74fb8d5757287fcb14c02cadcb46510641c549a5d34126eac0074da99deab907af5e2032ef4ea28d82a76134ef3cccf741bc4df7ce60e0e5e1b9179505a47fb439afbf9e2eea04a3a4890858a6e152e11110227184619e00d3fd1c1f3d2915e73b7dbc71a28e4d999974a03657ccd204225be76bf09407ea326f27a80dc8a8a0332a2a10e1da25a59a7caa01e455e8b0c172512b78a4565bb71723a3298f102d0eda9b3938e6ea1a9da0d43572cfdb99edb087c9e3e4e91a32e9fb2f05cf55e996325c66225fb4b234d084d164b3a57c969f294cc25cba81e259d193b9dea1a5a0eb69b19b60dcce42fa63e2b6bf596c07ce8ae596be540571f7574f3ebe464ccdbf4a9019d8f8933293b4bc32ece653297247d3f8469235d33008d10e471cd1f49bc339c923905664300b7d59856c549213ae290b35aca4321546f87ddbab92a63efae8559fbbeb1367fc5dcb3b86612a9639fa5b5e39edd37a0618d94b310406e89bb77a87a311a04ae3b91b8837f69df2a6219a45208ae8223ad5beedd0b671e2a4051e3472b1481d221a34e3475f33c02fa376ab003561b56b0b13103655f2d5203de05e30e5c041b9ab15a96be4a5c6f793e6d7707852ddf36c142d0f622ee751f6703c0a71bbd36892e9d9468818945ec12392c69a99d31b61c654a7f89fde57e8a3055c90c00c88affa4384987929b26c09443ea8e1ca038a878bece09e8d887d9080b4794ce048297c6f203221d1ff699fae68e68ce4da87460142bb85f3c3bd08c23309b5e3b5b165233c54aa5b574c3cf1ce1b16c9ede0e236fc2b1495a450caa2acc1d4620af5a1b07692498df450f9dfa36a64307d2743c5698a0c3a78143ce0be0fea427a37c0a82af743233dc1ef8290b31543bfe1efe8af43364e168ccc826c49e00cc6bdba1976e7951314be087fda3bc769c75b01c3f9c753d43eb49b416d025c23346edb31ed7882a80075e52a0506ab684bc2fd437abe907ed3fea3df2890cf544971afd75211b8c48242469a424e299016a3a728b85348feb9e28bee1972e8321fd598f764323a5ee3db28b7ece06d90ba08bd5c72ca9c804ec7fcb4ac1c6bd3bb0143ac007889e97023900f906cadd05177694d3818e08b600b40bc34a02d138345f415754f601d75c1b5ad74e500b709adfd94677d72b455e36a74c7625a5720d77d396a02eebaba8065bfa57e0b286293622e0d50c4b550e32b2f683fd806958618ed9e6dfafa2999e20aec8c0a49d3a7479b2ea153c81343bee58ac66224a57f81a036ea4eead46e7fbd9b480af637ac312bdd2ad1cd0937092efdadbf5f31ad44cf14d907fb60e3cceec5d14aefc42a7020c0f6c0f2f41e1c2bf210742b4e1664c3032b63fc2551499ec7de04d9b214de0443fd6e14d9651b4057494a16ff0b17644552ca35cd0bbea2e694112c50f011e91359783c27898aed31694a9340f49060b60d8174964c62a7e7251e109a7bac249e11a31f98a7f5a196629ee403038b80298d789858a4e8c435072d6dc79244b5435342dc0a718634900b7c2ba7cdb44305e8a005fc4e41185217109ed3a0fe4414ff91d73a58820762964cc58e01c7b16d34b391922eea680969ceb05577c48471e88d9b5fea22f421e7ed7139f138f62bba538dcdab6834b8e8857bd1d71dfa0890c73a76e6313657cbda9a87c3706739e4bb532edcb277aa6779e214fae8a2d6ca75164e210fbdf21216b160aae3a4a66fce8d69f82ca9750f7c06a55f4593e353dbff8ca140e189ea6ca3f31275dc5d7f59633657320e60fb4e29e3cd99ea6cfb80091cae9285a4f7644d0788a4bb870ce10d42d1c6ba3b06add8d5461085f379d7057d6fd51cf32ab8505bdbe6280e1262163cc1e308cb09f2706c563d9c8ca22994c08f276472ac4417c877e5b4ceadf002ded60bf26aed2d840a030d0cab904be4abe98992673b481a87a5081ddbcea8be408702190f2172f79c8f1df5163314d6ed2c40116925d52787470850d53485a429492bbda66882ce34e00d078b1c99d0d4d02f092af514ff48acc48e003e8571a9e7443741cdd0d21b4e680ac26a753db9f4f25b2172e22f86e65c00de0b91d57e772f1159d3f60fe2161b38482d08f40caaacf52fa0916eaa6f13dfc433331285c9667221865461752fbb523d5de30a75e4866001ee29af227a5976d7968a7bb2ec9eb6c9cb591afd05b52eb005b427fc5748cf98679fe30748c117a055b4df4ca591e8000626a5856a1a2ad00b2ab9bb6e4039f16cdbe9e1281c69ec73f85b1e075d9514f90fc9c164160758c440829727604392842be1db7bc719fc5d1b34784c7a408becbbfd8101832a9ab314d942d35dde56f98afb8e54eae3bae907242f66552d3da82a1710a53e27c1251f46ac44c8c4acc2663dd0cbf56ba33a705971c8321a43fbad07c8c950f5765e2b8069bc5534cf4f252abb37d15e98fd901c82000f080f46f6ce2aa043296299e04dbef6da501496e83e0926722dc4458d3169b5aaaf00703e84ec99f698dd165ff07e644870044c0af4fd2d988b842075966bc14148350874146d075e76073b3442bd477e74c286d79061205c7668da52feb339d47a331fabdb5b8aaeeb0e85655f28697a052e699c51df596a0ef7fb0da54b3d0e43359ce4785954f3b9b009183837b9cce775ac1c4c5311953f81357413bce0d76879fa0c468c8a622d181da4461c9853a002c252e599441bbc045424ec8a98b8577e765fe8c87577b3cf42af5d1db5cfc4e6fdaaabde7d4e4f52b7a15c9d9dd125f1566c6c8a7cd7264597e6690a21f176518dcd4c1c0eaa90f15cebc065b290438de01fba71e6a4bcf62f3b651b4a4252741b17ddfcd7757cdd4788ce90e9fbc09879d4bf6435b6818b915f50759f5d2d1b5d102600215b190c40c6dbf26b70d2ad95e7273dc397b091413cb91cc79d3e6d3c99fdd06f13726e03fcfa9271f76331e4abdd3e0f972b51f04d87e87145e945cf3e4b3994fc72173e89a9af42b14f717d9eb727c525cf41a0e0b3dd70ad9acbf1235813c5e452cc97ea09eb763c20021452150258356bf6920c42b65c295e6de4e5a311bed4f4c9bfdedb8b125cfad0ad4cd9e53c9b2cadb4fe3edeadb08158b49821c7edb70dc138169d7f01715239a5cb9d821159c5551526f8bbd873af240d55878516839f0a20cc924912e06bd19efc319044dd690523af2f2e4dc16bcb1142168fda488da43ca9914beab340b13a5848c6916060fdb77803d0d391d1484a3226b111aa703215c4438b4d3a79736da8910e43d02a6c3781fe94fb813adaf6a09286aa79748a82d08f614c402056bdf71d77d8ca0c24315729a407f326c433ed6b830f8b48063f1c7ff1f5e411315957b93cfff3cd52f55d3328748045b2c9068f116d9d3ef8ce6e133ce86fa3b215fbe6265b545a5f1fb924efe335da16bc34b7ccfa8c5616bccf506636da3f0f07a170d0e7af4c62aba2007f0a8aae166e0c1dab14230d2eccc601d35ecce958138485b390bee6fd9d9147888e15b8f8e0d0c1112f78ff5799072004c7f17c1d82f02ac2738b6ff7814e01590adc44680a8ce38e2cb07a3fb7bfd63de4de4fabef00f75a6d371fd88f24e0e254e87bd5a102dce3cdba1697da1487b37cd8080112e7ae0c22231190be88c996b7fba16a2232ef86924149ffa04a9ae6281bdd2839a92e3d8300679e94698c8b0914383b391b4d52fcc41d3196517f0b0d6baa84027ac13a5f63b3fc25800c97788fef1d237dbecafccc85e09b972ec41f6895ef536fe412c4ce758127574e20083d8f4b78059a6e8d66a36f07bbc047db7c125cee9b5f4ccb649e40dee6660188db9d6654275ba0113ba6d3201bcebfe2b9dd721f6555a0fd0c5d1000374ae2fefafbd293de7e3917b73b44df518c984c1059660ecaa1bd2ec0c660adbeb3dacc475ac6f0deedc0402a1278f4a5009739d028717fac6458ac0710c04770ad399fdeff3fea4e6c08ace59f8a0b3b7308c4d7b9d66881c4f8be2ee521ca6a5bb47793fa6a69c8e15180801af9b7d8e80eefa92752c3732ae82464f194eb1806ff0fff66da1ed875fc01a7c88d0be6b49da93c9fe45ca662e55302a5bd8b6be86d3ac3182f7235a33a4e4dbc932e34e8f48c0cdc37062dcfef36e0c302b7cec88625cd0eb2b270a2e1ed92f80e75ead0ebce901d50e60b3c36819b240fff97da9b8faf45d663145500ff179dbd85824f400682b60faa6d2429fc240f605bdfa0d502628cb63e07cd0a67a1c625f772dee2f0c96823da22e50a12f2e8cfe378793aeaa216ecfa353de01e30436370f9eb3960ee029ede19741b3fa5242ec4049efba96c288c4b32b24d1e6c179a018cbdd6e748f06039d95359ab91aedce0e58d9379d071758b7086611e13a54a3caf6b284d6bc96ee38807bb2dee819d36040aed1e86b8014d67f11f08b110893186383e48d19b63e4a1c375d915b005e9ee77c190e46e71dd377483e6462aaf5ffac9dfbacdbd89617e95e81248a6e5ccc76332b0a06729f460bacd2454a74ca2c9a3fe440a6bee708f2b768e9658ba66690e10d0b800b1c0fd08bf3497cd0598b56e597b54cf566a5e63429d1e00ad96c6979648ec215a38262d2c4c6a28b1a03aafe582456f9c6fcaa9fb61250da0e372079c3e97a23f152060af0aee0e8a34ce048eafd954f8fdaef7891e9f9b977889dcb430a7a3861b7cefb056231e9e34891918bf3f1ebcb97b60f6c637fa11972b528224a7a84dfc1bc3ce7f19f73112e8b85a3031e1fb782d1709307ca182deb8a09a49951f0e24aafa75da75e8e282371e0e631b7aaf6515b368ef8621d1522d3f52b8b6175a384934db47ea5c0ed049df5db3e62a177ac37d6e572606114a388cf2b62f7456f29693f2349285ae42f22c343c173edb1d555a77c065ea57f8598bf88f3dc40f55ffc11322159f25c24762ae58a25ba38977b27e4018fc4cb97d77111e72755ed7257dce66273c5fd98770c9877fe8b45fb734cb1e0b772bf7535ff784faba594ee78789f0f5d11c5a0ebc658d2020c8bcbff1d1c062af2d5bf2579b640be1735322dc2dab9cdd950a4b73c226e8a179a8e248bbd9ba4be8f9f4f33ca38db4ed8c4d192cf7074eca1f15827ffd15d17a05bb02fdbc35ba0904cf147e8238e6bf609e59bb1c298a18651134f5833f3f9af793874c3396d01de3908dc17a62fb1009f091676268e55e788d0d7e6f8a96675c04f6ec1faf00c0684f76bb1d4c83f9325b5442a1fd777aab8ce5e8aa57f4680316ec47a61631771ee7aa872d002b00fa29a2409e038a22f430c180b7c61dde3bb964183e64658b59edfcd65c8b4bcbf05fd98f6649cca26165773ff0ae96444219d4d932741efe38b40e336112accca18d24c1c4d2fc5e27f73b177655da545cfa9b74b9a5a7a60d1df66cfa3f6ecafbd14b57537c46ee461d34d30b1ff3bfa67ba5d90bdac1b26a89845cda9c3094bc69e37620aa5ab5b79858a56033d462c9ad3ec9798a231a198be66de611a1c7dcc79a21b5ee9622d0b2bd6628aaafd9f0939245c0f22e8db9cf0c1e9b87f8342e864302fe5435c18095dfe343333bb6575d9d8335de3380e9f463da6f3082c3bf962e8e09a97159bbc76e69ddd94feb261b22b960885f8cb19985dcfd53663a7fd3e2b458689b81dd32e5e3f22adf60046fca248d24eecefdac3a3930cd76fd04db592a8cb35f9e3e6341885b74babb7a406f3bf97e1a37d4c5feec7bf015dadf9fc788f9af39775499f87c5179f93dedd9df2b2cd3a917907bbdb306041f72029a9b5c23973e7618aa6300f98848309c79897a2c57016d4f2985cdea8bcf912883c5ef5b89db27fe8c5efb6eadef06129357c7cffa56c18517da52c36a23f064f5cfcc0fe59d21bcd476af86f43e03adee0bfa60f3ed6141642f31f1e101996bafc99f9cf9a7f013fa8e607339c8fd1689440b061c8a101fd04f0150ab6aa7c4ee0b1f9039b9919ccfe110b25f0d5f9c70f62312988d0c58a92747cd84c8d5c3748e4593f0547edb141a62c988f9bf4bfcf0103eac4a14f3b136a536781d73d7815f5e352b78ba9ac76465daaa577688b7ddf70eefd7d8e557bf5e8b8df7a973a18a2f503b3fae94326cec6b042bceabcc305fc6145d6afd59adf02721fead2a95f524a1eeabb0c94faeffe35ea4bcf7a13994ce92bdef7a547ffa915c3dcf43d1932924c3d2e5662e92fb440a1c69cb5657bd88cc3ca32acb861fc7189e364d78f7fbec1f977e5e93232c03783f658d0c2e56cd38fd1f4cf064e7abcdb9dcc5177ad1e260a42e9cf4fe13492c4bf4f7dce62febed15dc67a8ea971407d236042e0770c177bfba5dc8df3366b643a0826e80a60e241a6bc876117ca53b2ed6dfe8227fc4c6ae7d149eee82611046e10743f8a7c894621eedbe986ca1470b265d9430e4187fce5e4af086b7abeff2d1b0db7df703769776cfe16f90e7bd08f7c0cf0db148e532f1e4e21edfc4aeb7e90d03399bde9ad3ed470f8285533e7252fe79afced2914de96df568f01f2bcc3f440d258d7da53b1f729a47088da9ff1a5d97daba6526523fb6fc3da71b0fdcf2c3a5f933e404e60f1294da8ba52f0cf82db042376a71e55f1009d414258f663f3bcef18691d9a5f0ec607fd56fec814a55cc466754436d059f4c8a3aff605592606510bcc83ca3c67273d58babadd226b7da6c2ff34a730e77ad80011fe977373ed7f11d0bcf36fe73fd1219325f01cbeba900e9e7f8dea516a0cb4e762eec91cee36015ae35fa5164b6ac6ad2e9b56ff8b52f0ecd30b5217955f6470e669bdcf530bfcf953c606969431fcf6825d550c49c6927497f122ff0cb61acef46e7756f46e226a1a698ea7845925ffe4200ca8b4272cad857dde776ba84015fdbfb9f0370e1b0d5446cffbc5df93919396125564cd16332ad64565721e0ac67d223c0900cd67b61199a656946a0270c4c0620129b537a6334e91f5ddf1c6276d2bfaa7342b1ab796eed4d7d6c5c18ea05d45c3944b803dad3400e5401d8374487270edc3ea4222f574b02a9deeb29a6e178eb230698d2cbfae5824943575d0767625d6caae45d133317c5fd94f9f92fd881cf0b82490a72e314a9b6f31c96a9b9496ab8882780d47071f5c671cb97d2f9221b01f1681429eb70f06282d3f7e34ca06b64b7369172e77d83c0e03057c63228b70010074497ea78fbe74a8c1a922f8d2cc17e36bf6e216d355f2dc3796ab40a2ba4302b26fe0a23cc8ddf78aa27ccfbdba9356abdc9f5fb494c11718c0932c65eafda926e107640ce1dbba8a12a40bab185b05c2c5853cd1017d3984020c1db9d614dd4dc7d160ad8a484d7362c86900272d949ff550812d80e329daf8e57d7a653612b84c8be59972175beb84d6b21a8a4288dcfbcd81e03c0e192cc021ed440cdc301aa6f8b5caf2622d3cec3928c122c789f5ee1041c580acae24c485a16175a6ad1b2b5d2d6e1783578a6815645c88aa0c91d5dd218ac268b4bea0a56d562f961000344954b5c93b56d33ab9a2a8e3617118146fcf82013f34c4cd1119d3999deb28bee6422c04cd2fd6145839232a85d3ebaae4e3710017840a78ba582c132258fa4bbb27bd6ef6e207f7b738438176e62fbe746b66918c163377de5c171f4fd7537c70263244440e0c17cb3016cd3e9a222d439b3a1251acc8b3e25dd6a2d85d1ed7122ca9dac882c1172bcd02e8d694e3877472a94a0b5bf6c3d6dfbc882866287a6c61b154e99e960750bb0e37862c72e9b9a262c21ca1567bbf55c65fd0f9ecd4cbd6e28b422d5c46c27e17947a4aabe4755a289abe8ce720ea554cc256e1aec55fb03406948e6650d2d3842fe476205562590179377b73194f1d80fbc8c3f7afd2d056b05ee83dbe0cba746d116d90c5708029b9dfc2c20692606e90ee87f83d4fce2621648c0fb9a587836af1a2c6b422e26f12323552214e4ebc023ac474dd555d0ed02e913f373787b2ca03933146a91a93c130baa6156aa96bb373415a09ef16d4d6f9583eb7ac7c460e6ca1c28ba40dd8953439e012157b92c5f1b2e305e860038f8ee0208a62091b85a9fe5ad088e7530249bd04e293a548613489953f2461c132f9a12ab8261bc4535d6e7f0e150c5cd3067909b996d770985ee8808147952ac6776a46240a83f3cba900086904dc7bcfe46c5eefb8b8e8fcd914ed27b410274e82819e109759ef8a366cef94ea95ff58adfc82a2299e382e13b1415e2d4c7c395d683b5b39f245a508ce51c31057b11f9647c3e301490f10fdeb909c1c00ee162bf057ff419e60d8a0f80b359e383f8f419a57b60e219703195b20a8a6a9264edcbeac280a5b9ca87ef02723d0403d8e761faa3f0b19e9399130d347659e99d11ba0e0ff0edc9c8b7be5c983982af3dab4f6599962489a1e2f82b940a02b64f3b2cd34c51541d2372ab6b057f95490c701e07cb46733b7b71223a16ee65a24a1257f0ddd5934d0e862804698bc35c896b108ffb481dd2009ebc9db0d111aa4e9c4652e3f33d6fc967d14a0f0d4e3b7e6306884446319449019c457a6ec83abb4a7d197fe96b3b9549910799dca51362636b30469114f2db38895c3ae7dbce69410a18beda545e0a92d731f636e04abddd971d4082e48610b314cf213cf9703876fb27eb0c3ab3f70c101e0c06e8835ffce03b0190577e13ac8c011d1c9a4d31623400d3df54400a24c740a974f7d25082c1eb62099b611c4c47a7fb11c5dc94fb5ac99f5d1adc3bc6858baba74f3800a2b66f5594b9176c2affe078d4ff281baf3b4ccfffaa19839e963c770bce10b62a7aecdd2a42c3256415279c73d5062005ab5fe834e4103eb511a0f3a013c7072a6930b3252884f37aa4079d39eac52b6366d94a3b03d4567e6a47edc2f8438b2563981bea903b323c0c60c3aa4242eb7755f5a39c26dcf05317414100c57a07ac6f3d4de0d6ecd7e6cfd9cd7f2bdee68ffc4ca360fcdd236425526586b9495525fa22b34decb95b18be4b0dc272f3dfc2114bec9b9580d0b0846e57d6a4e122f00cdbe95e8feeb9030b639a48521418bda43de92b2dea0a9b5108c7df43c893727d3885160e9652da9d8bd1cda7731abf4b7675d24a624419ea82f2f98040a5f374f98648fdd6205793f77d843c744928c317921556a4ba41e897d0a7348a991b15df0f14753ea6f0ecc37ce69ce61f44ef4924b2503a0519842a366f4ac81a79e1a97c92043bdfa7403b9cee1e7e6922e53da2e60e02c6078128278806a5dc338dc200652c05094973cb152d83ffb46ac6e1ad6cebf879e28eb6b6afb13ad359581e6e7dd051c1a3b4606aa078a75e670a17ad6c956400fc55202c0e2fc29f6715fdc31524d57c0f34ed7c75ec4952aad65e75e53905bcf7e1e14360868248273ffe9b15060a5b1a977271fc80b1f4e66b5ca4852c9b8f300b7faba05a19a06b3fbdbb0cb91b79e5b7801908e98f042f0b26425f2c23541e0ce7197d11cfb90cee99dbbe45cfcb20f5f8659602d3bd7487276661a754870f746a40658bf1f00535059dbfc810eeb8f8ba6580751891f4f13fa5f7a9a2037e67c602e8986fb149e5555d1db66c0ba72d078a0bdb69a0ee32d5e4eedc8148fc8bbeab4469c04bff49c5f746632191a55ea485ee6d5c9226156c647276022e6d6963e8b03f225315cfdb4f09ec54e976a148c7e328a4328d84886df869b94298b02d21e1564c49ed8076bc1736576f317085040a4c2d4481276f187e980d4f3ca7484425087f5836ec12f34ce98e107ce0923206204a0cf6c51b43bfebd0776519c886fb21c1297637c7222dcf47a44c80d618ed7e144b44d49c7d0b5f9058cb50b37de66621fa34da89121957abb6d984e013a73edc8e971d7664cb9818e614dbe29dd692a271754f6e191a83a142099718df86db7cbfb7b41f49a62c76e0c034c0506efc9d5cc932272a2c9b59cfc803b673e8da9d3501063925886b4b56adf6511607ece176eff08b47d262965b70edf97822ebdb875839a1d100362d0103a64391c812f078199bdb3107470b533c014b85426ad548c4159c51e84dbc572f89a4eb1c6ec226901638a1848aeeb28027f9ada36685846e91efa773447403acd48a00d66b053971cdbd87380b4eca5125b25a8af2758d6951b74a35b12f677ba3e6b6b6d5c56c4a88a98426d1b9eb0da88bc057f9502562dc4fa4fe73685ef318ff32c36673fa4919f965fc3e0699216d18d60176c5a9c7310a6063cd4ea8abfd57944bf1ab3d8ba865f69fff105f6c97cd7e8c11706aca015fccbfd1327969be2aeea177a469c19844d2ac92051d0c99063de06c19c2ca7b0aca1a9edb86a3595db02f65b962807c3829e80460d72953ff07343652cb5c549040bb019e2c1aeb4d597acd6b971f15b6818abf35cdb5f2553b998491205742cddc6d47a387221418b47fbc7e1cefe919a39f8d554a058b08ee29f175a095212f2d41204b1b5acfa5de1677c6af70d6193f830e10d438fc0fb31541101244f50b38a584d30584ed4d406c7f70759faeb81377245495f019a37e2da5d89f60f8ddb537d3661a49f7b4d2cbb29a1bac547504dbc8dca5e3ff3c69de044f2f6c79a9d4106d9a46077da4e36260bb42686e84fece4e7b6a4766eccd21b03f2309f24193184bed4c6e390a8abd8a70d5417970c9290e2251a40e8979ed02034fa657817c9e3f1563fe98ecd83a6755e027204f5eb02b8b7ba9e42c132594b8f77a2dee9061001770364684238834f8543b8c1daa4a03f0022cdb508a5a217dff39afa2cc7d48cc3b97f76774bb2d6bf9c432776a5acae2d01c58b699cb023bd29851e43d0166d6d97ab030ade74aa9b73e1734909221fb24c55b957ce62971252c2130deca751e402031794ec5fdf160496c685c1baeec70769b1396122c46e1b4f7c9590831df02dc264052644eca7d0403b3aa896fbed9f5f0bdb316521732ca00b3fdee2dd26ab2b9bb9fb993035ddd2eef59ac864505cf88f8c4e4a4ca5b3b279210a75f96789f48f5ed6a1f5a403e7a749bfdfec456135435dc9eb9f638a61033641560d3e14e50c03bd55a722cfb595cbc73752bf2fb0e3943709e622b649e1bf32667633b2edf77650f7c6729a5537f03ccd3607ee9d379a6999c9b133ab0699095e1c07349abbfb0556a354ad783134aaa5ab7f2e36332385d56ff1e11c45ace283d8e58666f4c335c9530b96863dafe5ad75e5bbdcc2d681536b888b87795afb11325ae6d8c6a2ebf7de806161fe42f3a7afcc289dc9777ef9e4f8e2dc2905b6ef8358e47f85963c6746ffc57c342f26d33544d073a6e7cce35f6fed121414fc54440b02dd9c6885363df63d948a479b264a2410041b06cd44255ba6a53f6a0b427bf7f2a04ed6dcbb5901b4e3f52e9167aa193c0a446e64cfaff9d639da55d4f433245929b1c5482f05c7d9cd6bb0b049a46583c42e2a7ab1d5604420588b921d50d38bc5b2e8a3b920969e2b4e5371e09848a9e4927b5dfcd5b988de333ce4a618f6384e5b24e874b9e238278c6202c2fc47d25e4871beb84b6d308e0871c7d67118692e72fcc9671b2f7187701d44643d3dcb40f257f650dd2945f8f56fd5960b71b206d1308d66d39987da9ec6f07c36226bd01b061378a574f728ed7ca964ed385eb8c99d35cf20781cb88e5f20c91969e2f8e5bab707b0a21aa21691121f6a69e54249ed5398bfa51e4551ceb6745acce9ec984132b825c085018f072a6790a0c956d6167423710950b3e338e23773a3f2d4a93d458034323789d22f9ab954480b927254e715ee3dcd0f403b116aa31bf4d07ab5b29dda079acb2ffa7713e356eadd4709f672eb37a043a21aa7a204fbc77e6dc7d653878eb1ad34ee2bdccf38c221f5e7be14dd27424bd6a59aba34c8dd4fef108e477d88cbdac83ec55715d02eb5acd6a98d2a6235e54b33cb8bd2bdccf86cc156bfe949186423da9d9455b46eefa17285ba1f00e42e6cab008107f130ccef64322b89b0d57d3e51b856d6cb29936f4621ab1e39476cc690710b10d71771c47bea224ebfb6794c88c50e11fdb9742f634b26d0a94335678d2bdadacf6b54249d0bc12b4afb542ced06e8d658d1cda2c362895b4a37c5ae6e181d888dde24ba2b967613746b2ce966d16db1c4a51ec294cac8a8f544e1da58834731a4aa910c60ffc53b2dde83edcc0f214845c805fb2875fd4aefedab573af7d0b45c9d22072dcb508784072552ee9608bb4b425194e7209713c992d4249f73b5e947e32e139dcbbe4f8270e36b5a4f470db0e67e48d79bbc64ed26abb4890d785268ec800784e5004c6d95688214da12a315be1654a9f51a0f6360062a35097d9509bd1f1d5664a59930f9d126cf95571b44a89e00c664305ada760ac26461c3e8db02f58da859013f52c07c062a26b847b67c5ce669e91a0e80161403ffc0da2e1a522e6bb03fc68a60ed5ba1e2784340f90fa43e78132748d509b3a823571369d74dad1a52d8173e93f18e4d3943fe434a1475d0a230fc9a85f42ff41b7a80aea29bd059e81adae8a2964aa5ae525aa928b596a4280bdd864ea0abe82634ab4b2b354aa9a552e98aa2a10b742b9ad46595da4a224a459bba10e79c42477095306f7e1ef7cfcb2bff5e291717a211d0d8fd9a27bff2a438a4e9b83f8b705a128bb4591445300bf6768ecf27a7bd29422f85ba50a7247695525f2b90c86114b2ce08273166bf6d77143dda681488412970748cadd81c9a0a72b2e1abb9d58a1edbef9d3a3a355be466880a851c1873186b42d9719de885d29f4c3eeef75e725f559ff1e5064d19e7c35081d9bd02e5055b4c54fea1125aaab3045c6828850a202b9be4f07ca845e6545d65deebf39c11b459d6169380e016005dba69671957b8d6a5fb08bd4d1358a5576f301c0915ac3cb12a658760b74f112f9b1abba40d598472bc70541b1a18c65ca2c186c1968b94e385e1f5c05854ed767d0a8311e33bb62b5848d762a9e197624a7f919f2ef09c79f321ceab20205df491499b43f287afe641d233efdbf9e31c6c3ed034e14084ce2ba35e16ce075d3dfca146bb8850822585e6bda886c1eaf24b08de2758791f9d5707d5c711cc83a068c8a1020306709aadbbe5f66ec8317d08aa2c401ce030f4e5dd101878093bf57f847e2d296dc27e832ea93a1be75e1daa553aa4843a081b217e8e2b13c2f920037e7780a6da5d9e8e771c674a3a66cfce263a5f891302be59d60280a5c2d8e92c6bfd03ebacb091aa043e20536cc5493ea67f8b59094b8fde8981bbd45369835a56726a902d83af9603fc4de2cf19eae53f3642689b7e7220cb82f13a6afcc6038e038bf8542967765bb5f20f5e51a9a280975b0d89569f4c639b1bcec1083d739d0a0907ee25945982b51786d5b272b630ab65caa3222ba04192ac89446dd1ed7e440e01e92e068020d7aa59af47bc9c93ee26da6ebd1adb642dce0ab29ce9a52804c3fd89a0a141d2b2269b9e91a1e8ddb9415e99afca280a8e7e732af1ffad456e6c2ebd45f9af6669f6d0a0961246293e1491fb6bb9913d997d0342a713abfe86c9051382eddfdb6cc2b81cfaa6ac86ec98b796a57cf28993290c1a7a4e155fcd454c6b53294e154f0e6d0cb4dca7843fd9a61e5e0063871e47fa6e7c1cea8d5c83aa52325252f470c7d84e07262b046d2d97dc5ef2ef874a815a763703a627c6e00a96daee982174f6c515c28ece7828c528d498996816af9760556395a213fce64981eb15fdebcc2647659279e1f0cc9488393c3f4c0b3831b26d002dd005fb345b1ab79de85fdd79a6a9b191f3583f4dd5352965f617cc2cbbe39b6fd5405a044f7eb5a09ed65ddbbdf41f37bcf81a13b305ea1ab461a2018fc062bf310980f4609887fb46310b1713ad0f8b1d2380cdb129fcf96c13e2677a4e31724b60480375ef6818fbec2254545d6ec42a8f58293b484bf385a4cface27ccb4597f2e25b86cfeb1c20f22571c2e63e768d6fc505948c924ed631ba3451408189d092110d2283dbde5005ee4b2b6936f195f53d98c414b9723cbcb63d42688256503448488b038dc2edbf51e5d456ceb539f1b2ad507c23459ac9d6a469e39b965a465f2e86c435af6fd32172e662e579b072ff002fc32095b207646a27743dd22bc89ca6f3f2e53d5341bac2c815397e5b442edd5c231609d85dc9c151eee5399f2cd974a73181ad34c8764d90eed5382fc1dc58370d57effc630a301e39de2ee4cc0ed26451c17741c69879f6871b9dae4aba1f72c6f5a279e91d1b3e70dad9eab2111df1ae454f72cf0a5adb3991bdea66384c2d846ba3a2c31c87ed3507676cbe22fd7cdd041e427d902a4583ccc8406ed34d93e990e9b15a1cbc0c256c6dc3e166393cb47417eb88c2539d557722668c96893292113b9e08b71c0109d4f4ea5649759a7dc0378e0ec44addc948c04b395d740b6c2d1eab4b4fde135161f30aa6e762894b3d4d53a4044551cb41838e51296539fd0e697123370cadc6d832a785412f3e35072d8c9334fb57de398d3ee0569f58275286026f9993fe004fc70bac486cf1b2697a9a314f440361fc298eeea6506d8f639a9cb369573deab1336f31b0f8f7f24b49faa2fa3c9210d8e843ac39b7eced03726dceaf7a350f5d5a7973ee723852c72e2fa35db66929ea92534a975cb45991974d32c228e228a58e9ce451b9f57e9cb51ac66e943294626cc90059ce093bbb3a20705a49621ba7f455b241e27ab9289f08293fa172e06cd56aae43c75a8c2733875f1418e4f2b1498c9d26ff16e23ecc93540c700daf077737044b06b19e591e34dfa643991030d9f95f3beecd2be18e644b8255b1aff366b49792b68e4b465d7424801c974d321183b3038834e37b583f854dde9773c65258b69a0bcce989e44a3ecfad9eb52eb702b38632e873b77b56cf95a2d191680261aa9156b2fbcdb2c715f5fa065705feba0257bdaf8603dce4c646ed5350668c6bc68ccf1123abea00940702ef9046170015b00a70b68f00849e1ecc15b8f394e06528d1e92c402f6a5bbb4c1351cd88c2350d95ad31a7408fe7d58f991705668ccdfcd1a27c692bbf23c64568b129061325f1aae0a8ef7e92ef7f53fc54822bd68bc3bdf29d33426c7337e85765a4ce3246cec445b9b36f13f6b26fe77f00d88f5d6f87ef3290fe1cbd17d6ef5086450f7e4ed673375cc4f1af5427fd2dba82e31d9fb748a84c4bd7f455ae37e4f9417556acd1ac739228711546258a2b31cdb65dafb24672c9ce6c991757f9f66750e529a1833c3b6bb2c40b6a34411ddf7527940e4a5f32a645edeaead5e842a8ed58f40eff4ed33dc485aa8981970fe0c61619c99bcbf3abe750c88b10463a159482a8a531a81b0a3b254a464d5172b6148121afa6b06f1ef7db4bc173932c7946f7d42931d8f2b7eff691f852e1385c45e4c248da71cc29d1ed4ea7e4ffa8ee414c671d67b0db054db794ca98338d59bd38258b38fdf3029d823b672b0216f0902ab4ab4cf95a37f5adfafa5fc507ca32d3243192eecc30bcbb5875c9cf0005de4742802db12c757ee1132024a1685ee8e593ba771673718f441b06830ba71b5596d8d9af5e458a96da6e815056e268c0c044c9682c052cdfeedf1cc84ce4a3194a976c140919bb987b564473f81449692624c3e991b814bdc816e6071ad70d29950876479e7783edfc4d0c3324745867b857fc4048ee1da162ff9128b806876d034cb902a580a5df95b1a0cf2d650ce995145a2a5e4d2d6a1dfc6d97dda676fdaf5e79e795441012b06d3e72c0a0df6a154be4f6a3c945502186e1aa77f81f56ac79ee944fdc74212472f74ae03df733252ebcd6077dfacf443ba6e6f0f37f4686433165ad11af678d61806abd21644eaac9d85cbf16b9ec8d5ed39e099161de7791a66bf3992c369ee0099a4f6308d5c0bd5243f5ec671247b53a780f53643da83179f27cd655666f4fac175bf0ba4ec9437b5c3a485e727f2f493a5a670ebb34b0fff07246c5d00a5c3197334842a70055504abd3e54904351496e541510a1636d608f4f63c3e83440c12afdb39ae7bfe9d9422d8b365c0fc902607b13b6e82d71720d9a6fb45654553f19656e8cdf222c0b0293035172b669ea46fd8f1323b3064c7de0a8ad94a0f5b6e0bc1308c9b8774c5b4ef718fd4803c678db3291c89f56af0db989430517536ea7ae335976027a8717fc100c1936703c400d6103c5673092120712f1cd24b9f186824c4b0c42b81c4f6fd389e8099eb66d8949a0aa872c74d85c1a8eda6676eb8dcacf08667e0d82a1904810d9bafec2e6489b518e6ba35c1a5f8e7842be1a2f4779fcef99dd7fb89ee5c1a0d1dbcd3aab940eb29b84865be2a60bfb627a434f53b5b83a854e704ee0b8ee86b526980a30b36f86b01d913346c061ae6a9031f1c055dc216a26ee0920b868cb584baa46c19bc4c971d2092c9ce48614da27c15f4c77508a129a34fcd5928b12929f921f7e374f311212183d0aa09069a498b8966d297b91b0e838738fb2d662a1b6d6c190033ad69a92f58f2b8bc9397a7fc1645dc7901d9ea51d16e1220052a7803e58ec35ab0125d013ffbcfc95d303c9aa028cfdad92dac829e245ed32b94812416d4a79b2ba5587d46429b488cf2832fd3f3771f9c500bfb4699647a1f0290c5475b738cd30d449ac62f361a3096a4a5a6d901a895da1f982d690da9a63c79411bf101550e1156076dab504a7d604f73c2c2f4bda5c19ec137f4c9e8a2a240f14548e37b16ffe509c62c180132a2a38aa5093963840b32013b13eea95d1973ce4c216b4102ced405059a8e29dacd144df34cfff2df89ce61611ceb03c903ec9ec59ae6402b0bad4dfe3c829d9c1feefeae1b12c3fb692ccaf088f8f1dd4ba11a2dc3a406f72b024447b14244de142e389dd9c83a24304e6520c762da41a09ee58c19de18b3d78d89226c303c65dad3778c6a7d80320ae03d35565515c4ab27c546f1e24eee4124594dc8755951e46add99e823a449408bc803b42517215801fbfa4a4253be2b3aa1544bde71cc32f2bc5e5fe78c4c54f3c0686a47158352211717fca64713428ac6e1f66dd3ea397878d283dbdf0792d762e04f9d711a89366740a40268b1d5d13aaeb5c283af2dea84be9cabf063b06d6a7c2f02143bc4f19ba569acd3a3285ebaf051269c00e66bb44dffb89915aeedf4c251d83b09d9036865ec86f6537526c8b5448b73acd594774d2277d92d85bc2e97d106357bbea24b591ae8dfeb360ffe15f49f0c1c2cdc3209c301ddfe921014492da429c4e1555e31a783d8678e446859f9f00c74afcbe6a7f01e6fff817fd3ae0015cc804da2cafa6551048cc381d80f3b9d4d11d834457e1d7e0b20710eb5a011870b10f40ee0daa4462f51dbd4a257f4ba5d922fb5fa146d2ee26f79785fcccd446386708fcd3461013450a43b88a03f31c750572ad774df2c66d8cc8a6f209240a630a37980c3329dce0055768381c197a4ed889c243101626d0462fa1a177d874778d150cf8418b09ac34571ad30310e39b490550e042c3278a93328ae8ee965118ada4e2d3eecb28ec3e49d2fc1ac749c3f7fe482b4792ce70cd8ee3c7ee574a13e7fd71ccd65e1274f75173a5d76d01178e464ce3741a4d33823057774f698e262729c7d349a530c71c73d098c0cd90e96e77e2fea53285d97477019a9b594049b3a1122f2755e55643e241c383338575d3e8d0dd33549c3feba699d17c775f519c4bca1ddc4c0d3753e266ba9d386a27d39eee2e71dd34abeea6d25c5fe91d1e2bf196783929b1ce2b42378d0168a0d0c0b0c20c9019ef5294520b073428908302d7629a44c5d9342a394af87ab34cefc4c1a4f590ae8d79b771e68c21e4d0f87a4852291a1e0e68531c20e81966f8698e0aeb0d8fd0c33ffcfa3e531c16888304c1387684208710da10c2170d85e54df34692854d6f1a2a4a414c572ce96ed40de6953ecae84ed60c53a22824ed0a8d629d42344c8966780a61fa53fb95687d5e76e790b5aebf41f34e564f3dfa7a748bb0bd8fc338f27c15da62dde6f846387f0b7f486f513d32f251dd609e1fa3c8af9346f192b4b04fb23deee171de4f7a8c6595624c892ed1e752a4ad1f6595b65ab1a25c16e12e6581457703d1a61f04a16f8fe4b61afd08e5b2487c1a7589d7fafcdfa0bfd68725ae8494247d1ffe249a298d5eb21bd08331b24a6dbac736f5c086af579f269b77a6832485b1256b8ac434329a588b0fcb250d5f8f46b3a19829464aebf81bc1ca96f8a2c823fe91910f0f986859a5a8988d669b44eedd72fe4bce221cd5cabd1f15ccb16d1279f7490fc90b8ecb91f41f95d39bef8fca6d689fe98cc14aecdd27438a67cfcbc09b6a69b6341f6958cbdbf848743cb98cc2328aa766dbe7893395d9ec6e045662236304acace14f8a2a9d3dcc6da6f93ea9f29f6b83bed68ab25dc1ca95f81f94edaae5aa5fc5de20f1c57fb1d210bf914a346af510fd181d89f933b64319973fe2d7ac588154d8b34da2d036893c9af1df462ff2d5667a4b9b34633eed8f3bcde66c7bdcb3d46fe9f965b749c3a5bdb5ec8f5fab03597a7dd27eb566fd96f6e679bac56e452feded6b560814ff5529e87586f67e153f721bc7f9f7484ce5458a8c8070f0158f90cb8d805c3c40463538508fbb5a4744eed527edb4be724fac288c5b98dec66a4110dfeebcb9522cab769c20e818856331fbe2bcd967b907042d1e67690be02008ba0fee8e72d40e8dce5ae4246a791377771edc7fa424cd86b6822008e42ab8c599d692065168e0a3bb3d1b1bff44fa42e1d85fef6edb263522e07d6ce25cc2ea87486129da9b2bfdbe599bd410e2e1520771f2b88791423be42eceff91552ad6276d4078685e20f181be0a6de16f3d4bfca027f5ef8f381689229dac7981d038ea468385eef6663046cf59ae93dee9338ed3c7287f8bb476e57ad5fb48b73a81dca332c52708ae10e4de2c9c7f3ff63fde2dd35a5a544ecb3dd40de6fe77e639fbf1ae8dfdbc40f759f849c71eae65b2bcb0f992551a96e25f70de27ed252b05417f10f42fad8cc6aaacc654ee81af943b7110e6bda7720ff4eecbc41f021d05da5ec41f88f2944f01bd526a83dcbb51f76ec023b649049efc063c726d1078729c7c677e5ccefbf9659e55eecdc23b1ffbedce4a61e56dac799ee423392e023d461dd7470ae7bd271c9bb79f5101bf8f089c12d61bc613267ecdce7c92781ab917bb19df60d582549cc94b56e9bfa680fefdbcf37e8a662f494e9af3b8f777fa0da695e1a5a1dfeebcd9760b63160447b1ce19c65494d5795fb444392af76ef302b52c0ef59fe57c23d612ac350bba38fec9bd8c5f26a33007af75816129e2169e17089c82471f9f3355a68e55feb38c348e23d2740fa4e2284ff9bc405340bf7ff381422e16d0cfab004645ae964a08ccf7baca66f7329d79b52f3a6ade77db8bb73afd069b721b3f4f2a3e8d466f318ae7907bf7fb40bf9f64ff5a22f748f0e6e4dd9cf0ed91be0f046f636d96692df517357e2cf6d7c6fc4b7a73bb3dd20b83494f6f46e1799d0af87d33dbf206708a639b5c4b5b451b5672d25054ac9f1f63b2666f1e366b9db553befd13f75e9cb437e237e29f50600ee836c754a3bd76163e76a0209e564a4a511497632346263989dcc3377e4b1bab9d7c9c333c3f7c283e1ddb64957b7e1b6134e4714f7cb1dad07325720f5f3bce17697ea26c57781ce9cc678ab307d749b67c8ec4cad3ca76856345d6352f9058cb20bb12abedc12c9e6c57d9aeb6006d5952a97b410653ecc517d78b097811841756bc5872e398a24efeedd3c50eba10c3e7fdf9230aff2d9b4601dd4d6b531659ba6964a079f17770265f856272d2fc6b262ed8e8a611bbbb8626e482092e14c0850f5c8cd851f85ab2ba8b262ebabb66ab631f66f878f00f04bdd20f088aaab5020a02fad9428be721e13b9f24278f7f33ca1638ec785bf8f89616678ca1c5175a3871e3959edc2b75163c66e7fdffb418f23c5d8b153c8b37ea1c497cbd91a4d12c7c4c2190a1bbdfb380c005c43815ec2e2cc43416572c49c2c15992f47ddf7785077a0914eb7a22b742dff77ae1ebe5a452df87c910d8d0ddaa29d70b31a5e1e01053dacbd6a60f7cc1381867167ea6d9d08395b34c6538381f26739e799ea43311ff96a24fd307b6f0400efe218514e98e239d8562b5300ff8e86e2c49ac318ef37fe68789036e74e3ebc1521cd8e96ed5eba563aa828a55edab0e0bf8507340a19a3869e23736919e72ec873ea35b94633fe4ee5e73e0c16d227dbd4cfcd70e1e3b46d82143184d765cd051a6348333ba2609980e225324e9ee176dfdc4f72f091d4f3569e2decbc467c20126296c30806d8a020cbe1e0e3969226c618ac287c6d72327cd8a65cbe70a4dd8ec71d2dab936681ca7cf387dbeaf87482d94efebf17ddff7627d51a4b31725e78bc4f8611376edbd562c31266977f6d2f950e5a889df090c3a3a3a3a3a3a393a322c89010625495e40a2b3337776761e367b761e3661d6f57d2b389ebef31f7b25fd25bf2f0b155960598010610222762062004388f1be5a9ab517fcf26670b4160682dfe7026f30bfb6e8ef574a4381374fb32dd031080e9145b737c42c1c4248777b54082e8480a23d914e9cedaaf208418410a76a6f75e6fcb0712cc974fbb5b1283e4558ba747b58528e429a5fc3328b8285863b1f0b8fee927605cc952cfa0a11f5b1acda1be58a5f0952a78308a0c16d9231274eee571a2bdaa94da31d9bed79d5e6c52f1b0262af20bad4d21404134184ffca8f9dec840fe59d60db24c22d7c537b1c355a0b3bb90e80c401c003b8a340f778ac98d1ed59b1e2e2b5b2d30d440f80a002db64fafdb56108440b0822deb535db4a3d759b363f88f1fc872cba7f384276e70fff43906e0ff4418d54b5f5e455e50313ed89749c3ecc72e90311db8b353cf5a0821b2fcc5f4b474dd8a9071b257b58d23c8069f7afd6c4438b072448f7e181ecf678106a0f8a657995515c854c7797978a55be10aa0236ec5afc235905dbf87a295a684b7ddffd172db47d1f2db40981012122d0fea1fccb8fb1f8585c58680873bafdf3be965eff621b66fad7e66b48ee51a15440f1bf6fca0de6282ae08f227d559b678f7b54c0fb2cebc2f302d926116ca272621693ff4f289e54c059a91bf9f28d04b1421042fcb38e7271c6074fc37f0024ba1b536a7b6f1a295caca6bbd473749707400d803bc08f8c2df9334c3a0a0a2618ff688595283e2b51ac1059b9b182821522dee485f226fe42e187620a4fb6ab719c3ee27ca16c57e3580665bb7a424edaebff66d8f77932a47e48c10f53e0bffea40db1e7f0935e48f36bdff7121f697e946e1a39ba6986d04d1347378d10babb068ef6ea742b827605fa885f646355452b896cacaa90c2795d2d28a26a257459f87a38a99758e70bdfc279434b7bb18716ba8b54b12bf1b35d89cfe31ebe30bfd5787a8cc42a495af5238d95a85958bfe747d8e75bcf7dd6ccf3c7ab969234fb7fbe556a9b73d2e67dea81954e2210cfd9c7f2c474d66edef4fcb7db2c9c229e421f54fac8688fb52edb8b19267265097906ddcde505544ae481d76bbfc2b49a1dca3cb24aed0af3e8eedb78d78821861dc4c480af97ad35aa4da3fbd9bec69c5fd5c6fe8786aff77d2ca29f3992f87a2285a5ec7d1c5424ed0ad92611adacb472659b44e2db26d10babe6cc85f10fdde6f83f4996659b44b649d44d23813b855eacd959cbaeec7d1cec7d1c82ec7d1cf0f566780addc42565ba9b0799eeeea6e14110babbd291465d62e5c9f8938a9020d45c0f1534d7434a7323a8d1dc083331cdf1b0f1e8e64420a239118234b70389e67678733aa0e074e43457934597686668667600496107023a89233956142145036ac4b084088898f095617b018c154f5041c5131ce8a691a28a6e1a273610451354503185145140f144378d13dd344d74d368e9a6d140374d06ba6930c0bdc6702f303417e8a65982468917182f2ddd48a11dc379e5057b4971eee5bd84747b51dcf33c0db0836e6fe6ba397106c8a2862e2dd144c98952144d93848fa612032a6674fb2c53ffc0042e20c6a9a830a54b19e0a810a552292f895ef24517702d74392431e37218bbfd8b2591399cba48c674c87fe69ad246ff486735b2746e0a14dd0de371efc5295670ec2f3745ca14af671c0e26f059ec96290eef1e0b9c32c55154c03c6bd365773a3ec2d54e9f13c83d6c43b2a4b376b163fc21be39f9d7fc6be3e471ef2f256d99ce9acf1b0cc855b42a5118f3b8370b33ad619c6f29ce9495f9f45ad26879be406fe26496e98f6a9277e6faee2539be4fa2c4fb36dfc6e9a8da4c2c2f19c53d7c29fe1a0cb3dca35191a278dca372eb79d1fa80537cb0a5dda44e9e6def37f53f2aafe3386354b4348f59a702fe2c9c3ee014af45a17b182427d1670b2596c402e9486d25cf9c214dfa4a3de55f55f98b367c1d60652b5b283f45dc100fff6cf61ffc6407dc932c50fe656c594faef41329fd2405ce063036a080b30109ce861c3aff751467c34edb2080af42b18a0c3e529dd1ed9f6d1241d1aa2054334ee5eaf6cf05c7fe7d15da529d542570426c74b77f98ca14210f74b7cd294e8886eef62fa77aa17b17ab583c3640443c464199ce329d4e6e4e20ceb62f8baa2ac808cac366cf0ce580b80072a2dbc3b5c7e7220a4c38d315dd343574774dd35800db95f89ecdfea3f2594efd65e13c91dc9b8ea188f5285b965de129442b8d5e365962056279b711c4df874b7babb7f1a9ec47da977eab739c59fc1b8ace7219dec4ac47058c15d51fb24d22708ad3db384e6cadcc79fc65d3e6974db286e78fb091de60572f9b2cbb32ca76c5cde0a35aeae3840d5a918c38275abadba7385fe85b6077a39a73427ef9b77186ff06714e5c68f1fbc23501e361637477acb92643dddcce986e5ceef04e583b3355d0ec74f74c051a566212767874977ac031814017f11e7a70f1bd8913efa107bf3961eafddf181ec7e9f37a79781c27acc4adc38a0fecaf846f8693a18c0c626450c39bf8383f47cd88e16418298084873f69fe187e928b3f71aed4b2808efefb422a7e3d12c5bf254b7c2e06bb04067086a710e8a8e9ddc0a0e3b75b3ecdd4d36866d92651ccde9c3c77c191bc0082d7e67006d52f672ef740f1667bf2f1ecf1c447026f6260bd4d3c6f8f74f29b0df577628b63e3b7ec4aac472cbbfa1136eb51507ebd5e383772142d4d7ca3daafca964e087412d0dd2d20d61225ad168dc590dcbb652379d2ae0d5aa2046323be4449abe532f76ca2c07ebc47b221c61336f31467780ad5f2c5d19ebc0fb7e03310db588d51bf39f9e37106b9072279a104c1f2badc03dfcbd88eb89c65b715046b1ea3e00dea04e2bf311b73fc98d6390be91d537926a3a3e39092168794e471e2dad9719ddc2791834e5c3bf869e2fc8b4b1d6236954beb56e6d9569bed71ef762ded69a94a7d42b1ac58a52a2f1de58137334fd1867672f7f093932897e4382bcdd6e7588634cb2649ce9f7d23b5f771a876e5f353ed2a87d6f52aebc2e27ff864eb6973153ed9d2810517a44777e74c6086e76c95391b03dc50c4d9ecd8e0d89c6c52b0e961c3c346846ed2fa0d0b27ff6e587047b1e01f691dc5829fdc3f14762a535a28836bc18b6eff6e4eaf7973a5df4b9c3f7bd186dc0a5bb8155a708de3f4c1d436896c93c89f465dde0dccfe7530f494eb80270743b094d1184da2378734633a52fc30a01e9e1ed9bc9f34dd430ae985f1c82af5c9788ea8986d6fda8c3fa44fb3db3c5dfc9c8ae5e4e8e009826ef309e5592769fd4c6b56c83d4c478c6ab977832fccbaf8361abb9136966dad51c015a8935a815f6789025fd58237d3b34d3d553a47d26f77624bde273d46fd26366f2ef76e13c9de9755b0058239e02da37ccd519816b9070ab96a58010dbd5c2b20a21a805aaf5591cae57364e46aad8a7c5e46403fab23b0f498957deaa3b8178bd9d4fc286eb40aa787635626fe58b3152955a90d53135bf296e4ed4e7c3f499c3e6ff0f87f7d3a9e390a877446ce2bb399bcddb0d202f010d1ee67cfd7ce7039c62a95553ac26853e6d7c65c45ab32fc96abe0de915cff2bcd8a75de1c3b3ef56c4fd2192ecd84a0b59ce59904060320f1903e8c1b4286f723681a1950ff9a33c174165a1288260c4ffc1d9cc92d7f6ce21b2681a1f41875265faddf604e4b0243e978ce88e8eed91c9008701d190d663bb640c7d7e338305eaa529c31dbfab0d9934a650be52f2b96c4c2d7fb6040924a3d8c0332c4fd3001f7630aee8796eee67eacf02348b77fddfdfa5be2a72ff64c1be922ed9d4213a087b490f6d140fa4797d024748f223a4637cccc703333a49592068c8ea0610a397e0540a52454ca192b76788cac200a1bbcb91a258e4cc067a4580117194c53ce1b33538a08c04700bb1b498321a3892045388d949ec9f2c509424960b81a214490c4063e4840c90c453485992c5f74e16aaae0a000483a4447886c516688ea012a02ecb0e9191370310a6968ae860e99c9f245090c5773244408089321d880e4e940bad100cd980c14e00757e342095c8dfb1881c8ea32d15ccd092488c0a347ea4644136faea64796d902da0d0f8ccd52a15921c7278ceeee1ee20caabbc56e1c7e10a40a0dcd95c804377819a179704878680e09d91c12b13924539a43c26a0e8950734868680e890cddeda36b009c8e68ee84a5b9d36dee74d4dc8949732754770b216282079a332189e64cb8d29c0923abbb7d98482841473747421862736148692e8c55736130692e0c9ce6c260a1b93050682e0c1ecd7581a3b92e3c68ae8b0d9aeb6246735dbc34d7c58be6ba64d15c17269aebd280e6ba08d15c171e9ac32475917486593fce90d659f8ae9186b5b43e3fb39016da706ee410ab1704b568ab38edd85d5222090b5400caad0300d86d45f2f6edd0e96e2adda120a643618c0e852e1d0a18a732256dd8a150e4c806d45da280f822909a1c744418d0e38748648a5653b19bd411396affbeaf3be188eefe1212e304241081234a4604d14800020f28c201a5062880e60025069416d07d73aa2962c8986e24dd0d61a2bb1b92d30d39754352e86e17ba1332a6bb6f4e3727dbdf9c50379d90d907bafb87eeba18e0ebe18c239d25e8eeb2bbee84413c613b7426b0bb33b1d0dd9e37d25c8e3497df87d35d10a17e8c64adab4b39219d6109a7034244770744a803524207e4ceba1f23e86e9bef7bd91489eff9fd5c5a7722aac28702fafd5ae79d5130c644ee5d9b72af52599d620572140bc8036f588e529d40f74a4115c80253fe61bf819ddcc395facd3c91f771aaca3d679d30fd3e1cc3344f0cb2404f8d9407f5e5cda0f8b47b23c551af13f835292078f3729494138841bf36466b98ffc9a3598f1edbd12757fcf6077f15daca944687b08fbd8f83ab3e593423801788d1de0de6ff313abe68f30dd14908f4d4ec013de5ded76b3f10f494ff056f6e884e428eea7194387f7602fda321553afadc40e4f87ee80e816ef22684ed0da29b59015f4f4912ce48d2e88b92134bd746c0c1cd1104ec5efd71af89e78940a0bfac66c54a6bf67a36463e1def7c10a372a5d36dbedad40d968ac5ac4db5977459a5792651158b87c7ad1882d843c019020a2b30dd4d3617c70edd294e0839e8c62ce8c462761c674c08a7eef6af39d0ddb53938a248a5b27501a00c1825ca885d90a941f7b5f70229a0bb6f73647e96e08290c50e1e8cf63e8cf644a3b5acfbb5e2bf416f802127ed8df08da12fa0c84192c2a3b564ea0d21f9f5d4bb02409840372527ad7c1f63c4748fe9625228e37c232549df37c798d267fa832d1a5fefc5f9808cee15e641f282e883246a3e187d20d4ed1faa847d1fc647ed0506557a10c7e732d32856465910af1e2471f13f4ab62b3c8ed3a71efd65f58321427bb85a7fd8bc258fcc7bf790aead15c0bd3b4972fa9123b3f63deee1197076d0f3b4b9128570838999aa748cc5446b6b18471e548e597fcce31e069db87644704eff1263ca0396e17c6c51a0ed57e04867ccaf7ba328529a8fe38cd566e1e441b28e6d441e1abac30c09d3034c0ec0ace1df8d7f27f7cfa9f837050727633a64c20198ee1496cd04000738d5031b5edc60fc6283310d470fdd3dd3830d6aba7be6f9c3c6c5b566eb137cbd7c3fa9891a2400d53335106b40430d96b8cdfe7969540313d608b3c6083cc7b41641f1ee357237598f320de948da80d648a2c23c2125ad2b7f4b56e948e775d1a00d914ed6f8493f445a170d92ba6dacd24e428d2e24506388a6080b92e8eed4ede69202ba4b09e8ee9a5296d2104f6fee346669e45012a2bbeb57b17f83bc5889642dcbaeb25df51b221022828692ee4ee51958e9f6cfc6aa6a064e3a08dfc229fb212cfeebb52a52b58c80a0bc806ae0312a72b55eaf0f5fcfc66cac529c970c86fa5bc18c6e9a146210b365da0be3fbf4de092bd2dd3f9a834107835277a3d09c193968bf7f513e48d385af67c6c90c1b3352e8d6e2890b8871c7d72b03a90c270d45052e20c68bac80582c1e2137028202b4f29fa1a322a196b754422ef7fcda187867244d145fa49da91c1956705e48c2d2dd5dbad25a1dd9f092c24364ab5f4b5fe2f7b5408e16fcc08a656b2648b66289bb8a167423857684bdecda5cf95aa25855e52041f2426d1a892adb8b75963615bb4995a66237c928c808ca0c4fa1202328792cc9796b2b1800396fcd6dc69385ff836e46b71be80c22bac56876e1fa48d3f5d848b4e1dfc499ebb7c44f4199829f6e2cd6c763983e8bf38dacf7b35c837b5f1b615456cba097cd77af662b12121d6beec5acd3bee618e797dd49ef4cc24398c8478a7b37e338a9ebdc4ccb1b100625481cc923cd11f6c43d8c8faa0a29b443f83fa8956b76a8d5b22b71f6cc9e37ba9f34c2663d0a12ebb78eba69c61202faef0346d0a5bb69a1ed25d6c7277801770215e017c17023f638cf87e5db3941342db48dc00a1b3680a37480ee9eb122042e4e74dfc61c72664ca3f9ffc69afbe2f4858f2f52349a440e384a5b8ee81f61305a6340e2e5a460a20861705b58e8ee9417a417d30b17bfa5705db00185eb6288eb228748921360a03201213f4177370a615e1021071d38a0074a0dbabb878ede5103a561186341cc6c02c0d494910289110c00c42354c1c1a1224698729c7a4036808a6e1774370e4074e1c5c6853882d4506201a6fdc30204fef5e01f163ffe61e1a3dbbf2bce68ffae80c2d62b48ffae48826f8f14822f2110bb3b0e102ca01b042b7c208bfe80d0077cb47f1e30c3035ada3f0f2ce9ee0019dd8122bafbc57560a7db3f32382b462b503d72608c7f1c20e2c58115ba0a30b3e6aab055b1a4fddbc097ee0d14e1df0686dabf0d10a1e20cffa880c2c6a8d899824cfbf79a020c1d9a9b823545104e0a32fc93e2886effa458a1fbc545914547c18a4200fe7150a80145b77f64b77f1c144bbafd83a2c63ffc840afc7b0209fff013a8ee76828c7f4e2c003be1f2af09315c13593471a5dbbf1d5ab8269234a74505ddb9246dfdc4d933c71c73d4cc90e00225ba4af70e7d460690d08095eeb6ab1a0ad41fbd89132767f8aa7dad198367c6886362d65de2f17ad15624a9a737a748dc610656e8d6498dd35e9a545f84d20e0ccc98888309369830c187c4d3d1f17452e127e9d84273444da94433c30677811ebafb06dded43734bb4d15d9ae96e1e64ca3a456e899c76fb333c48284a68d1ddfeaad9ea54a6dc608e23e2f9a58ac5436ff6feda1a8ae23287f34f1ee847dcfdc35fd6b23fb6a969f330cf7702b98794a3e3797ed7e63a2ba55931272747279593a3e3b659765a893ff131acc49f7210836eeffc5ae41e9ee1ebbd5e111042b7ac84f9f48a403bf398751a1bcb98cd8e2758a9cf04a0bb939a3ba28a54aa68e627e28c40a23be349915adddda4392358dd5da48733c2877fa5c841608b96552afe87a3ad8f642facf6b59f4fbb85379cc5f96124795a3cf2b887e944d14f12e964fd07b93c6c3326291d49da04419256c2dcb6dcc318974c6e5c70261fe447dc05ff8fbd4edec4499a5ff947263724cda7709ce1ab89e71f7170282ae3f28220e89eff0d49f3c971ea36d6f2a656a0cf6aa9ecaf574bdae9363b0882d85a2324cd97261901c709fab5b14cc792c6e37f6d48d2ae90acd26ca1fc20857688c593e948b6c43bc53a738be6079a2bddbd4373315a378d0c3cc4df41c75d701d40670252df711d40b0c5620df98e53b0487c1e91f6609fb1759f857d5e56a751b6630b7bccba0a4d1cc4711074cf9bf6e6bf3a9e722639b8054be5d8e4e88814766f52b0129f46073222d677231497b694d15c5ab2ccf5ef8cb9c59ecb221128db159eacaa62054e9620d12977beefb64677fba28bd49aadf1514342111566dddd4e687cbddb23bdc6195a277a8a06d0c820d0d996d4f4e81ec7f942b2a4a53d8d8a7fff052848a0d042296518e5165a684be5cf36a987a0820ee3d05d2554349beb9cb15e2fffecf7e191cefc3f1f36d146743ba881af777f16e649434002ba1dc0ce8edd0e3cdab661cdb0665c4f0855a1855000b410daa385d020426ec2167233d4426e92747710213eb485f83869213e3c5a480f0d5a48cf095a48cf132da4a7012da4274a0be981a185f4b860e331f41019ed21ba2fa33dae719cb4d6bd41ae4a69627729ca0d4a3628b1d15daac1d3662dadd15da2811adda53468b8e0ffd804c699ebac7d12957597d098c119d7e6fb25198ce30c63509292f18bdd345b1ae7120cfa3e35a3bb5446774902dda517b8808c4e871c09d4b480041e9e351faf14e8ab5d79a5d786e284d1a1eea62e5015684d76947f347b63677477778bd0dd0c8c9915ed9f9dd51c3563402e6d3733c04cd5ed1f0a5f8f9ce27c7532b0c14a5faf3a4330a6466c8ca236fcc3e411be5f6b69c4b2fd6a26013341b060860122c696ac2ff22b89c0021874ba3fd23ff663b315bb505818c90b4740b77fc2226a65dbaf3ed31f5c4355cd0b24aa78c46a7b2a25bafd137cfb27b77f22de591371aea5c5980ed9d80c4fa15c5f28db7e8569a1143c85700fc65f3fcf21a36cfbd538d2d9ad3f84438a2bc58fe7cc368944550e7db2ed7f24e97559d7c726ae47f8f64f5478b4b6171fdb118b63ab067c6dd07df16b9685e705b2fd0aff643be2a719d3a18ce790acbbb40215a4600c31be784141185dba7482ee9209ba4b25e82e81512241abc4faa451aeb7ec7218d24d6143e5c5a8e3a7168fa2ea4745ef8b28d1e6963ddedf49629687c54fa22cb1da1e0f299c30d82d749bf1cc769569d47fb4a929ffac8a524649c1deaf92f3c4a05707417184d1fb359ce991233f2a8f5937921f1ba1b4fb1676cad87a37a83c4ffedd5a6e5bd6ba3a160edddfe702b2b1aa2ac2938e2f5a22fc1f94bf35c2e667bb420aed50be769c47375f4bbe7044da489efcadfbdfc2e548deb2752b7b846c40ff337fb4a34f7db2c8a7f62b927685de25fe1b2149fa3e5a28a51b1a3314a669a16dc83514c3900a6efb2756bafba5b3a49b4812dd3e565deaacf44c962f807ca0fb08866e214c46c441c487f6647ecc518930f2faf121e90a0006554516564638c1a5862949078a084202104400396105338ee0843b84142105183a2cc1a140091129f0a1552105093a2136ba779c7eb9c38baff0934a1b681a09744252babd70c6629dd04efb77857cd0d8743578a981033534d1dd2eab34ace5cd8ec2e338439c2036ae084aa2f1f5be2fd50551099ad219d7d21ab5a868254a5394a488c58a6acfebf562a9627f59f7937e857b8648970aa2bbc5daaf6e309b3d9cf11ce9bc798e344f54aa5a5a5fbc964ce5d88f36d323f96f47fcce98e3e937e2b527c7f326633ad6798295d8718d8d7346c7597ae2cded84c517451ecfab5e6a8e25ede6e39e97edea966b697b6097467b91781cc7e9e3e4eb4e813e1de636b9fe8fbbe02549f24f21f1bf1397962625497227297f2169c8bd6a51a2caedaa06c84905dded93bf25be85f1b48c7eba2f04dd2704f6f0389368778e3c9ef8b396955a7cdfaf8de1e0fb48b3e6b9cef20677d523ef31be5199689b441eadbc393908d24ad15f366177ca7c8e34d60a62a9fc5a2769a5e8aba2960d181cbf0f043df6e2a7608e2aeb9c13693acaaeecaa1eadec8f75c92a9d65bb9a3de3580689780a65bb22f3d3dd50d1dd5d122c5d1225deed915c7050543d7973ddfe09385fd582b747b2c17816529aad36fcf1be5829ce2b7cfb277675fb273c76d5e93869d005c6dae80e53c60badc8ea7ee3c74c00ba9c24bd442715d2fcb414897188003b1c237c3d1ccf072f7b523aefa7c799edc97d7cff40d08776281a3a14aa43a1bafd6bccf397751b478ad41d39c18f11bac728f2040a205e6cd071c3d6dd1d845aa182ee6e1e31cca0f86102102001e8dc20eace8d9eeedc48d29d1b2d74e74690eeda28d35d1b39e8ae8d32ba6b8304ddb5b181eeda58a2bb36b074d7860eddb5c10a32a401d00109e2440430a40538ca36c1f16d8263a84d70c8d026388ab4090e1f6d2ad3469bcab0a04d6544d0a6321f68531926da54c6016d2af3439bcad03695c1a14d6582da540686369551a14d654a6d22c383369129830c176d2233459bc854a04d64b0b4890cac4d6476da440605225d778400ba3ba2a63b2378d09d1132e8ce882edd1961059020270081499b80706a1310506813104468d31820b4698c0dda34e64b9bc684a04d6390e86e1357c484128876343724a6b921349a1b324173434d3437d480e6866ccd0dd1e68672686e68d5dc104f7343495228120002082085165448410718dde968a23b1d0ae84e870edde978d29d8e9cee7408e9aee68dee6a5cd05d8d16ddd528d15dcd0fddd5c0baabd9e9ae8600dd9584d05d498dee4a22e8ae444577ffe0ba20123417b44473410b682e08371704361754030f1f5958d05d96137497258beeb258d15d160d74970502dd65c1d25d96dc5d96ef2e4b01bacb724377596ae8ee127c002181041e4450e8b084a03b2c1ae80e0b04bac32244775892bac3227687e5a83b2caaeeb0c8d01d16af3b2c46bac332a4bb2b737477654c775770d0dd95167477c54b7757b6e8eeca14dd5d31a2bb2bb6eeaebcbabbb2eaee20266e881334370417cd0dd181e68660a2b9211cd0dc103f343704adbb83f87c69cea78be67cac68ce8789e67c8a68cec736820f93194bba3303a73b3356e8ce0c0074674609dd9521477765eca0bb3268d05d192ee8ae8c1274578616dd95d181eeca60a2bb328ce8ee8e840e052236438694f0230827c65177620875274693eec4b0e94e0c21dd7d79a3bb2f33e8ee0b97eebe3cd1dd9722bafb42bbfb0276f7e549775f60e8ee0b0bdd7d39a1bb2f40bafbc2a33b2f3fe8ce0b0ebaf31283eebc8cd19d172fbaf34245775e2cd09d170674e72577e745ecce8b51775e68e8ce4b9246a1738283ee9c8cd19d132d76cc5081e66608a2b919c8e666d0a1b91970686e861b9a9be1497333d0f083b3d2a33920e6680e88379a03024c7340c8a03920c628d5f0280901226689e6c424a03931b73931617362581c8f1d1ddd31f941774ccee88e0919dd31016304127a744a88ba53f2d39d1226dd29c1e94e090bdd292140774abaee94ece82e491cdd2521d35d1231dd25b9417749cee8ee2e4827654977528c742785eb4eca8eeea2e4a0bb7df8e02107cdf1b045733cacd11c0f2e688e87309ae38104dd5d0207a46b42a7bb268c74d70490ee9a98e94ecb1bdd69d941775a6ed09d961674a7654b775aa8e84e8b05bad39280eeb4f0d09d16a401fc2801480f1ea61c94d0a63062da14064c9bc2ac1166056d0a03469bc260d1a63053b4298c05da1486016d0af3439bc2e43685d1a14d61c0368591d2a630ac36857122a4041f417c943968ae7c4173a518cd955f34575ed15c2945736512cd950b68aeb4d25c999b2ba50039811b92460fda94860dda94c60bda94869736a5018236a5f1449bd288409bd208a24d69d0da94c68bc8109c9bc33934875bcd6127cde1244146e0f103003e82f8e0c185076de292469bb88cd1262e5eb489cb06dac4454b9bb848a04d5c1ad0262eb6367109dbc4e5a84d5c7cdac4e5a64d5c4e68131712dab4458e366df1419bb6acd1a62d2b68d31612b4690b166dda22459bb628d1a62d1168d31622769cd0e950d19d8e13dde950a03b9d20bad349e281460c9a432305689ca03934ba28a1336aa13ba31fddddf0467737f0a0bb1bd6e8ee86177417a9cca864d467eaa6850a91080000000000b31000303824188bc582d1805846a5f901140002609662aa624617894914a314420618038001000003000000834309920a57e5639f5b9345ffedd4cd68d6c0c19b77c8486438460023d037399665f13586fd89bafe7725a66221bb533374af2a36ca09872ee5509e6a6a6f3dffa874a5b882903e1f1321fe13f0c3740f129b618bc3c26748f93dca8515badd9a1e3c6d86e3a5d7f418c0179c25a6e37782e3ed2e430576cc74662500d984e006be07a1303b1a5e717515aba0b07ba46d37869e1302c41fbbbcb518c52dcef09e4a0f2845f392ad5da7d69a53244c7f867ac283be38fd37ad44ba7834423826600241d7c80e09c31bdbbd2cf9e81c99139ab1c0e3d260c5851617b96aa4abdd44fb71b66f204d3fc2127c534a688cb97a6c09a522833496f39ef1ce1ab887b90bbf0dabc57897a3bd2ffbdf08e3afd408a7f3f150d9c399de27a1c289a9d174e9940d4f447f4f325c471aa6a672a65d945ae4926f75a148feb47b70db0cae3980b1a162b7e172de00a9c983a65fa3b2260271925103a7e4b10e184e0aeeeecb814bcfc8c59d735940448efa8b0e52dd75e39cfb75503e7e3dc586ca985f2c3fb1dbcd965b4de979d108fc7d83dceb911da33ec72ab947640c1bb11f3712117a53f4fbf57d43406b1f6aa4905c1c294bf7bd502b784c9f303dc5f485cba169264f76cef16a86fca14030ba77e20eb58d286ab86f067a603955f8b58b130871eb21f5ea43c2f951f55b0791ee2661478fe59037932e704a0110815f51175a0a68ed83bb0c5f0e39d9d32977b42182db6437fd074590b996a7bd4c87921fe25aec31199a0f8d8ccc0f537f4f8b1324ba7b8befc89f5322e58fc2d4e425e3fc8746314399859a4bd734b822a2f547706d66e1caf1bff456aafe69aa7666c6513d186db0fd77e82b0da53044ce7ce25fb821e1c736d2c83838a2ffba7b3e86aea173bc126ea2fb0cdb42b7f01b785aeff613f75782ee11235d80dc1b137017548f673e6ce49bcd3fa16fb6c66b9afcd2c0c1ef9f7fd789ff09d91b42f6ba4c39c4fd7d37dd71705125df42db4f41c8e43350897ac2ade1e130eedd35f9e56a19605bb0db89b351e22f68482613d8228141bd8fb307f12ec1fc671a8df1940ac5ed2b35d7c362ea4aabc7c96109f066ab7673c77861eb4663bb848276c47b475bc9376a77da5718a558c82e81d5a7b9df5b915270e615eb0759abc8245d7d4ef8f8153953d3c1b0df03c598ffcabc085fb59667d66cc27e5a12d392c0d9097514f6aff3e62b21baab6a54871b1df3f32aea491704deae14880738cb28313f4de3e9fe7c6c79c2337b0265f957393f2ed6392f6848fb95ca41ce8c90bdeeb9278cfa77e3dabb152761065346e9ad6e338d1834eccf5ac79f3c753c4393e7afd7cee93e4ad1649a3511ef13e45cc947b753bffdf35d23936453d3ed1694878cb1fc0997e844565ac1a97905a4003327f25041fde0d93aed8e0cf059045d626240136ec9c12c7342e166590a2fdef08636f3854d333bd1088c90e9a2d106278b12719ed49d252d5136441a91ff58fc255f502f141bf4fc344e0942c20b22a6bfb18d8c83f67b704ca8bbf17a487a86bc878e042c67eb98ba062615506ae546087d4c6f324aae086ea46e2a1a49a40be43d32c6c21c53dc573c3b2db0f0b02cbaf7b8ff101f57830311a5b250794ff5e6cbdb181932bf1ead39dc1356aa8a3432d53b78a4079c866a3a5eaa29fad82506c0fccf832d5a77fe9332dc9bc1220d57fbfbe6b4b5bb34e23cf63836144b799c160fe9c201e9e650f7e0a936b7bca9ed598f28564460bdd06e185a20cab05027956f3e7ed54acb0e57abf5f652210a7c49259e4951c6d45faaeebd77de7d92a453a09e42d4a39a84f88282dcd24a420d9bdaa1467f6915cab897d6d3b31e18d92c8091576c845ba2a32aeb1ba9c91cd45c556a550e22970230b385cf0bc527c010809e8816b89fbccd9df7f9ae06dbd09f344c6444fec1d8535372beec2c3760ba7b19d16371d945600066b72e313405b57515eed30238642f23ada7328fee909451724371a3b62e82be51a8672c7164f0a0a1391d41d441bc69bc6c1a244187965be29f180674d19e1912f04591260008421a66f9da636bf74c600fb5cae2056c0793c192fd43dc906f1bf1f8e5e4e3c65c640599223f08cd6e2da729989bb72fd697de8c12ec21d9c92a1afe53384b4d8d3fd173931c4ccb8338f19c777cd46437cc0b501fe3e61fd20fbee96efd0c5fdd28849e2594554b125eb44268194ab3310ff3af6ef78e1ad01da6374b719471ca87a5d0d839ffff5de11c0f7cb0f2dbe1c4c021ef2047b699a02426ee774c6162eb0ee0c7aaef16d512c19dd07783561077bb59cf45a15e7217876a80df76bb804716ee097302cd7ff464a597436d73fb0443196b360d4975a9979e39be158f19f0f8f947fe178f4ce6884483e66012b1aabfabadcc6dea260f4a270e906f30702109d02d5cd85bf5fd4bd96ff6dae244dfed366316cb4f9a3e90bd259c6cc2e4b699c244a38c6e26c10fa8f3b8922c4645358e2299c72be95c33251f10dd21517dac1890b4a40546dfc42ff66ec594709a5f060ff76c3c8a07ee25c4f6610a6fe2bd547406e45062d4a746b4346acfe450bf73f00db7974b486703ed40577a8450a598b98f64467aff72f77858464fda8e8ea7e09f578e9827fb905894898b1d40fb6130cf068fa87b4bf38220e397217afaeea9bdd51c15a5af22e1920aaf0ed12572ca55aeccd73818ac8862883f3aaf7bb84845da66c9ef0925dfba00110b3940c229efa20fc6505465a12409c458a4ba22912e17e532e29fe065336542e22bc0b140198154e7421354302f0dcc841ef2d8ad31457716b063c6f8755586ed9976ea30a3ceec25b3b52b3be0ace68ee80c6e4bbbf84e677c4fe700805d3c964a67e8c27c9372827b161a5d8b9191e262a962354d1c0f7d683b6e58d671a891c1df22fa023a8a0849fa597e1036f759058e5c8ff6758b9a215fd110ad6b8458f84aea9b57ce6a480bec8f8198087ff005f2dfd751ff3de033b73279a89d30f1ff297efc2a3bc9cd49469f48114e03e7c77e7ad71bc7dcf7a80a26afff58b6f53746f02da1a28d3b337aba9ee9b0a46ee74c8302963204c8bc9ef9c05690bda8d12f127701a9380866d700d08e34e6665e2cea264801adfcdaf769fce3bac75dcfde455dcf5fb5542355cb8306ddee4f33e6a5b466042c77b06abbcaa192dc6a02d7e39d75beae96d9a1c716894e9014b65b899fc872f812d8dc392d9e7a64a89aa56ddf1f4b8e9fdbc123093a21140af728907e70b5ad054fb944c887147aac51f02eb3566e6afd790682f7e055fb30d482273e32a1fcaa6567e1cea4f0de82cfb2b8e7fe2f743faa296570e32d539cb14f92b9e0d1f6d255ea44437e7268ac0ac69286509ac56b8ae2b99a2cd80b2559a2f085c41318a1cca84a6efd19b1cb07420bb83ff4f9b36b0f34edc340ece18cc316b258efe83c2bde118f7fedf3d77e2372e1b6236edb9faf25321fbaab3a1907ab68eff2c9dd12e3d577c639c3888bb9fa231ce5979ce4f1e34adb3d443fb7530120bfd0f63acbbd2da09c95d428356b83b0cff5b3af0c9718871b9bfab2ce575b71d1838efa0c50bcb414063e60fc02b7c70b127875f47ed461cbd14dc8c9d6c7a63a2c93b0aac4168f41feebeabdfe7839e9638fb401c0989c5bbc02061ae81e6ac4b2804fa61b430f6f40724857c04443df436e0008681b87d516d6bb8dac5c9cd9fe10fbc2b87cf63587ef2d53164f4b39248403673e462b7dff7baec28718eb5657734463bf28c7564577fc9f6dd112e8d5d7e13f4f799d2653bdfe29750142bd00861a0029cd3e9b710897688c04ebe3ec1016357d9b9c6c65229c1677fbc73a2db1175cd1dd1fdc73339ad395e18e0e0c7fdb48c798d19a6d550cbd8c1fb46d1e6e3c660dbdcbcc0b88885c13b8daf943f2dbf9e5beb1646e8a84d6dfcb9f3b80fdaac7108d8101961cce1c05e2d9e4a9f30bc77414be2bf6b140dc476d346783f44b7a217cc308af379e021046da59e2973294c1d4518c0ff76b534d40938bba985c2eba946a95148129cf641b635b0594386e929201744ddfdacf2d66118fcf596f92a5ff4f00fe32226d89e6e6093bc0ef65670e00f6853b17ce1397a4c1a7fb6e80afa521f3d5538de30f9cbca0fd74842711b21c062f6d5c7f51ce866958ef6b4eb8e7cf2e035e6668ddee8a8e2e2ab0a2cddb205b49a49c54a7c9966b0df3b5f7d976d34498477b05480248ae8ac8800767cac3628d2fbd70744a3ab16e51f6a587f6798e67a949be389ce2253122e477f86885d957f94f7fb5692373346019dde302d3cc243a94495444a6f86dd9d835ff63ff2b84a24b580181b1f7bd95941638af3fc66a81b985dd04929e89369d9064fab54e320e1442c2b7581fe67ad04c2056904fdcd65816c4822cd5d8b529a278074abb23b978b7bae2b5c93be9b514416591d83ad789bbf2453b2312023c0691f5aaf55c2adbd2abac0185d9e78ad34c2722b09542c1612c5cdcc2324f770f63df1bbf775c616f26ea3cb42f8c4ad68e3c183a0f6884160f6fe5f011b09f6e04b9ce082c77fb323b542c3310ac4a89665c4b58a6f2747a71aeab644a87eee3655a56509d32ca144be292cf9a0e1e08f19028dc91aceb6fa66b6041f0880db4530e8c2bd80923a224828976ab0cbb3689402242ddc92d08374fd0bb75aff3c84bce5dd64b6215fe1353a93ce58eb9472a205e178afdc28c0c23c8431f11e789af69c47ed80e3404a71755cec1d2a43b081ace7bc3af160fe6396dd8f1072ce6399f27ba07592897fcc42ea25664e8e3a9176ce759f961413b4878d4431c97c008a21a080635d0ee98c4b4cca9eb84bed17c3fa8992b9887282528a69b479d8573cbe6c8b383f65074ba7344ad2ba06026599825119cf840b49cc30cfc6d0a8f9115ef95b3bd87c02c863c932ce4a382a3feab064839322c0affd334c05164e4758df06c883c4bd03f4c7fbb9d615d7d34751741b6d93ca8397b81d72ab52395a06e71437046f3ddb8bab175b4277375c09fcc610ad75770acfbc60a24fb72809f426f817a78e656bd4aaf1e6eeadd6756bdaf1b1d018c64972dd5182224b7307f8ca0b90305f01d4e3fba825f43eee83e0dc59c207668957caa025ec37f4b1e1100c59265d1b16e0a25634e4168cdbf3d37f063cb117a6ae893ca0b008eaaeff72e0791bc24d535979475215a2f3b16a326e5f6f895c99021e6204b31734a697ddefb0583fce0c45b6dc5b8ac0ed184b334f03ad735b12d9759f0a0c64d9a76d0dd6a827c67208861304bbba464ae923d9cfc813baad71ac471775ccea3646c92d9d6f36e729202086ff9829b3a845177ffd99b195a1fffc8a227c5729b78581e0dfe4febb39ab39f7746fdfa9b158e29c413dc2a4c13304475057bf596de5dca23c557eb607e5306df23e937b1d31daba48df9c04b800c7c8582793cca7e4103d7408bd544fb2f85515be12ccd7ddb387ba8aa1762079a2d0154ffcdbce93e989b016518a18fcc1a5409e258c28e494459d6b05386ecc019399b6c8c148c3823082bdf5df8415735ce863d6fb8df0875e316042cda95a2379620042cbb7483cb2ab79afbcf3dda6822ccdb0d1ffa0ef8ad836bd58d11badda7dc4104ea60d1b596be5ca9b21ec7caacbd60d99a4ab2adb39340fb428064f3066a03ed995fb2ca946011aea6ce84e849f517a3b340420d4324704e37f787db4e4c2c470635b321b7650c3e51ca6d23f8728d73b7a38db91d5bb4c5ea71dffe1866b3bad51fa0a64eccf7f7faba042543a0fa7c9cda84dad6ff59d9cfd0a938ab810d824e1d6b51a1355d418d34e06b03f47236579c4760af997bc7c5b2cc5e957afc055f5c01c0cda8aea679cb2f804a4ea757765ce07b6a73b2f239aa3c42b75c46d0f0c45464d3ecff48793b32363349e30f605abf19112e229aa80f55325e237a4465087179e846b12efb062e26527844f2c4f2a751c2cc1900d03f047516529509229552f4a9f7907101126b9d9391ee12c6efd716ee650bbc89635b5a795809ba0c46308c542d53f839046b37fb1406f41d29e32e852e80a0b4f1d510222391b49dc88d9f1e64c04d8baf08de9f2190a572b6c84646ba81f54beed944d7baa34d49c229adf095c21f3907f0f9fb5cc9a120ea13ff7c4131e95aaef687215bec1c22eaff2472ce9b359e97e1584ae87f7b3a2ef8b2076ca758d71f3d24cd905eac2cbbe6e61691ba36a5c48474402256272cda11cfbf4d3e4f1c404f32a8fa6e738d4e4702214e435ad19921a1dec233b04ef658e8fef41d1e5d190ca82c23a87b63f2219d9d9f46b4fc03c1ab04380404bd1253dc4c50f6241c19bb31250af81f34328f7a1faf05fa7f1c03f96d1683fdec3034c830c4f065d131d681c518f7b8f2604411fcc0b3f508fdbd12da81235384c7d9d6821394845e0590dd87ef9ac8749970170c29e080b8e5e6819309ccd39febe47ed6719c4e6ba0995a49a4668991f721029f43f6dfcdb4fe7f1408cf2d254fe170ed05ac3a601f67bf62fb43aa0b5b3ee30267477cbd87f6f6fae6f0d96d9119e1fc477b5f98ef527a3199ee3c552acf0e84b7faad82f2bba08970ef19293c8074b992932fe43d5ee869e439c6d921ceef4ee781721542f109aab0f6eaa47a963ac60d4cde780eaf981045f3310a8d96a77fdd143e8a727fb81fd150dd0bea9ac61e5eb26f0789ae33f790c190166df3185e18c1ef2f674f3af889882f1412a6526e58359721d1ea1dfe7ce5db767883b1adfce51e1206048d20be77504edf970447885ba51f966b4f2bdfe3b778b7f63f0699c70ff9fcf6967ed1e17c35e81cd2cc15afbfff1ff61fe2bd44183e7f5237e9299e45da4590ab5a04fa4c9cbc7371b3236ed30abfef3e3c0ebf77794adaaf40bc173d1f07b30e01f7cf9fca94fac0437cdaa9b77ff44e3452f4f4b2d3d9363a1c11c3c3b48e723f846ca3bb1c5cd62943bf6e67708e1512cee5dcc343c909d8d3450cf458c278e70d1e6ed1737d2285e046e53909405bf0ca730546839918ec6d97f20f821f367fb9e4cdeb562b798e39c214e7ff3fa4a59f131d6beb4dcf8f1867d21b6f8c95d4e3a2b51ac39541d431cb074e6503cc2ba1598d5ddb827860b6e72d93e9f6700d5d1157bfaaf2c0677db5c538c079c7f683d02f8932439c5fc74c88424b1fd3787e3fc6cff73147196ccb21504dafd2360755d8b14f778b0b3509e3be00eaf9352e29b166485571ef314d5f829a5f6342b177ce9c7e738aab7b0bc5ff1b95783e340198b79491bf9a224311780bf4d881cf9ef2d8cb45d1fb461fec0570adf17ffa0d9c4f5f5ec71ea09790aaaf5fc0edade74633b3aa0e67ae07dc8397390cd3e7cc59e6fc71909f9465cf89dc2316f80bbf8771bf76e1db6036d6e89c63ba634e286a52178cd4286e73100fb8359995098ae0225e3bb3c538f31f893356b1162256f70ad777c5b5676b0046b4d42a969335dcf454eff6023fbdbc9806e6c51c67964990c0ca6c8b07acbd111d714065146c70791d7ae7a651be353bf57d06b8d777384bcc8da3ec3b8bbb65546bd9b619caf0be9c04b7f3c38445ca7ebf40841f5e824f9bb90418dda334179ed9398c7a983ff837a4a0b55167ce43fea1decc079b061f43f28c9c3f3b0606e7b130f4a1c626868a970e542a1c55abb6706f729fc8a4e97b1e4ecd4703bc50d64ff285fc1851644c4e6b1fc60c6fc50f4a26bc995a64cb568242fc403649fa3992e650035f7a5b35b43aa71c64ebcb09912ea4f0f4c9cd00a857fce4a43983e14b05f44ae0cb20ac484f866650ff78d72eeb2725a56e7d1a0a830f8df9beb640805b5dbd1058e2dc380c73d58dbbffd9beafede2c53909bc617672d2ae317fc402058571343bbe872824218daa8d55817fccb95b1e4b2daf8ece6b87579c8627f005b4a228843b2470d54947fcb7c03727ae4c30a88220c664e9d33c0e9748c9a80c5a39e438dff5e0dfd08d236a130f89c326081d914c343e08e15c3254d720225f92b9eaa61253cd19903e8e1f9f8d6f0bf587a8a20e6e0f11738a06f4b355e524cea79bb7d0d2fe64e41f5952eb406c95c2911a978b8bd788c1922401e6f4abed369cb46a329eebeb64ad8976632f384254825ee941477c44f174e4ed1c70be635cf4506e17e08d3222826e5cecf5bb5880d5d20e53e778ce73259254e0525c823393e063340f75e550b883e628d133e86dde5d40c13eb38a863fbad2220870959123deea5bac66937b41a2fe3468f403502ae8b03e27ce335cb305694a5fe7895277ae249bf00f9e2db224dac0a05120182f58773899d643bb5880f74c25afd12bd9afb8603aa4fccc95f324ae5f86d2b6e3a1aa017b002cabdbe25fe0d63f8191609d048e98bd60d81fa4d66a10e287b4f33d4593ea2e326a4f516c1321d9ddc008887fef067e4dbf0c141cd4ffe5a6951e3270a09762cbb78fc6b9b58795691fea4d478e2ceac866d0f9d350844ece0c159528aa622b37a85d247beac06787f5fde7ec14b8152b942615493523f15e53457516acd6c021e7c766ff7c6ea2871b64b50151b99304fde9f456d350ff2ab93dbe6aceae9b46f27f1c705c6349acdecc1153ca7aec9c831510c7b38afdcf29a94400c2b113ce6c32a68a28ac05ba34f5cefa54658c9350fc517f1f13f96320514d0d153f299e96d1b2e35589f1b2a06fa6b3d71d29c4d6c0aa58ea1e0ae910ce1b63f9dd7a16ba1c48a02272a306570e68c3ae0f9a09c7a6de9a19ebb95a5da0642c441720c806edcada3a01d94a653d5738c720d58417adb24edd350e2cb1daac54c13ab61774581168ffdddddba71012e3be3bc3f19c03549905076ebedc98121c77709c56ce0998ee387716db907904aaa2fbdcb8cf6a853a61d32cc3bb8ffe9d775505c1a6294e52b52d0d3121ba5db7a3d354fcf05e3422563e396cd6e1f2f91934e0d1db89e7f1ffe98b4a8c8e3ba53ca743e435a74959b4d77f826d69922815f2c6bc496e094cfc839dcabed12bf49804bbf454c487b66e660956295064a367b5995a36b415724ec88c0f11116e6ca55c77aa1c36188ac200b193bfacd48f431ada94ca6c8e103552f739913a7519836bcd252dd07d4fe819711471671416947d787c874ce9a58395c14f54151f9dea9350dbb9942ccd9309037c5ab1da2b1b1089d444c21abe0baf853bc349032303d744652ae10cb26ed5ecb61425be40b271fd82ca96961a10196fe35aa3917e919b0fd949795527a3b4b90bb30d3c290c4e99eb5872deb15034cb6fd02ad823b5c2aa9fdd12c7db8bd6308e0b33819b3f875f9e3f19fce17cd0dc6d5adeb8f64745f24f6f254c5ddb901f9dd5b958169298f67e5cbff44225a3ab692dd63cd451089c83d7a4f31a08edc726a793ca51e4c03af30691cea619a9892cf2a289934cee986aaabca466b1bd2348534dcd511c177ecc411fcf85498635a9615a9023b47e50a464142598a2638c73335a62fdfecff3f4b25924e755cf846e498c15fa48615ca330d363976bee0086b4e3441615ba41a9a5ed608ae054ecbad0e26239b8e2233540fa0cc8462ef68f8eeb14df7534c774c1c8abe51a93f818b34255c61ff2a01a3c0fdcd97f0c2b10f7fc1d86169edab7c2f6fed3af0f9e633eb7c5ce3b1be0a322f0f87b1383309de0635f89df4dc9205f7d37671e07e04411af2916c633453f24ec15cc9bc544fc78f7af699ebbb10ef9e7ea8be052800b7f56bb68257c4c407bf8b5d8b7bf15c19b51e573883937e35d2449f18584b84e21780754c901bf11d728da0870d7d7a45c2ae6715b612be868f90372e5e4054dcbe93391bd55f4413030c461af6ea964412deaa07db79dd709633d366caa91b46ecf4c30e7a410f94c2b83168778cb44b6f0c41ec8e18e7d0764c6f8e503b9e77610d639d08911fdee066a384550e30ebe38bc063a4babcad8c972a56f046a751c0c3336a393cd2083c04674a6aed22f04215b22afbf58e21c31be910c7d530235658780492f5677df8a5de7945a92ca078aadaf57217ac802b8604fae60ecfa544af7067be053dc8882c967dae3b61effba521c798d6cf7eaa192671bae3715b6a7922d8490ec23d8624454c1c059051022e805acc76bfb3f1fce0bf5de4f29b927fbe021b9e0891b18229c7200c07f85d065e4bed746fa94de0a25750fb5fe4283b57d7c7208b1db46b8635e20e35cdea4942caf0b611dde31e5ea3606ef99ce22fb33e734434f256c75a650da66dd7d9586e98510051d7a12ca72056459cf1346960e7433b604aafb0006a15a2084398affceede9c93994894a86a54bafe18a350bc6596ac7c5232c964e22557bf2f207a2c6c855211245b28fa84bc232d552bfb6505f73d96133c4925063402b766fa19534a0297a83c6307f0064f5f99222facc5d925f217c5ff5444c51d4ffdbd648d11b1974d15e3ccfc860744fca6cf86565dc9bcbe1a0d29812a2f36c85f859aa45fec0636d8400f359c9b0a8f4563af9ebb516b860076ff34d156ecc3e087888bccf8d17810d6eb8e0db8fc012a12ebf25e725091515645697918b96544bae6918cd633ab6c858619b085b6bd51027fbbc944e02671d8134cf7479cb50223ffd88d6d41914d3123fd089d6a5d012059732848bc96daa4599c17ca095c46f4162acbe175058c2e7ca89481447885817bf33f7815f13565fa325a5bddb2eac79903bd8e5e295b4ee20a961730b4c1190edb6e504ecba300d8005c40edbd6962e5f2691c8cd610f20a5f5b32a194b0d22f6d8f0d99ede2bc654859d1502df1f4ec45218aba9ec0a17a30a5b91324214cf16061e77c1ed3bb11fc16bf0ea46872173e139a8eaced493d5720630834e5c5b231d7d3fa9a78232cfb9fceac7e8d0b95285c08f0e66f070a59b4fa9f13cc6c8fddf2172eb127b696de14f5352922206b88334a0db78c55632866d07ef59e9d08e602b1e8d6d836b7b1a7238d72cce7b8ca11e29059c47c171759261078caef753368f41223a56fd3b48de1bb64c9ee3b07dbfc3c4843b5f08b77a425f1bb485c55465f537e13dcd5386f74c28a67970dd11b061a91c73c4fcc2677aa3795e0159d13a6ba914d4e50ddcb1c1bc4ee493e34635855d98f06ae360baf05993d501f965177e22957ea7cd481a4a7b95afd02574151cdb8c5d85e086eed1e14d6113a7e1eb528b1facf37220742c206999b5a15fd7e6277252c33d46646736aa7061ac4628734b59f82bf4435208cb87355ad2344a046546f5429d1018239150567d9a747b60e60b1d19f2f1fff55c17f67bc8ca6d50cc02da976afee6cad5585bc8c707f7fc9259ad80f120aef231b7558cb729a6fef71447e57b6aeddd6bc13e5f4f82d58f9fcaf5c7f58efcd5102e180a1dca2cf4806505ec56f2b2b05c5aa250f2eb28e04b3120c771ffee5aac0d397b362882d03840d3db913e03ac2fcc9406e7c80d6aeb9c4ce0a08be214db9b26fa7a09846ae903221c9c62072efec4cf7d31e4e862196f2636fe45a90fa017782574af6c7dcefe0f0d706178dad3a3c494c89a4ba1dc158a8c8dfc78f4b614d80190e32d7abaf9f9a20dc40deac5431d54bd6a5b730a183228cae2718bbb13cbd973a95ea07522184bbc18530767e2d2f3af3fb6b476258c40a48d263a75ef5d81dfc2e481e49b03c2f2d3fcf83f6b78e4f712a38b42ddedad4961df0fef1f7997c2ad00900604265280a7cf35457b7901d8fa466dc1e725c3d53b37f57f748b6063581edb2f77bf5ec7fbfa05cb3d8db5bf176a0834064851d57c4fc3982d124729e044fedadd181ebf035c22697588a8e9e25483db57a80cb35045c53e1402c86d6ffaf7946d0b5ad3fc63e1cbacbb479c8309b2ee17108de40fbb666d0a3c6e01035c4dbd0a0a47f55c31d62bbf7a532c1d1aa231d258c37bb767d068f6264174c328510ed359e58760753f2e749eb74eda7c9c2b289ca154362f4e6c0c07a03b98b55adac6bb8ff19740247556840af80eb4ecbea9d54989c22d2a62df40c0fb783ff247570fb5a3c2142ec055f4952c53d45d3aef2c2f6fa2b27e76da87302ef852a63ede2e5b58469166083020c06ce1b62788ae52bcb16fc29a71b6e256941af4b3bfe37417582fa5dfec3f71e6c736c3cc8d81abfc8cd273f129c825caab7eb1b0a263b241b525995f8c40b3a3ad1c7693fab5ca9e5aa2efab194e46992d6bd5b96e25bbf2ae16289f0a2c4a23c64fe4608d05f5d9bcda17c0427e1a5fad01662abf4808ecac568c60da63c267e0dee3a1d73a54922b1ce48ec8c75afc8ab0da93ffa8bb187aae57582f65b6a41e07f4f672cf08a70f21ac6f0f94e745c6402f11ae5638ccee29c477be216a0aceb4d5b743d70867e741393a89511ea205ae82bfc604c4062464a35fa02fb946374bfa6e469262ff396f1f76a12c9a87f86c83c7ac67e9e08598483618c43f66d837386380306d69cc4f5e7f5507cbfb26f00ef8811abba53fc9565a67fe46144f70b3709a24cb0b315d64a881c77476d6a579ab5d1f665d51814b1b2234ef81834cc4dfb430f4a343b48f92b36439ae497ee3504b41d860326a827bab02c98c03f1a8d58067f7106c023ccd460abc50ff2b12366d3f69bf8ca612a411ee50dc0ed1aae9b1574634bcb0ddc8ecc1159e9a70fa473c0bd89adf435155033313ea0677733aca31c73b19da001b2f24561cfa56a37a3e751d1c4105cc0936cb0aceca14c751d1019c9bc192b555485200f934049b15cd84979754d00c02b127f90664abc82cabb8b3968d7eb44657880098f328b150bc8a939a5ccb35c07c4d8b78a2ba56125589ba39ee19fc5ec290364d82c61950d4d1de5b8773c048ee304908c0fd11147d45aed9489d6bae3a97448fdd668af511067fd291cb8b1996744f89781f091ff65fdc1c09a789ef918acb25f7f060b109c6011196ee6720a825de760f06102fcf13ec750f61b51a97ed47c6ff3263ec682375c368ff280f72c4c8575e60c4f561bde4979df268db83f32988faad10ed7dd62a173dd23bd9d13ce67d66200439e313a7731fb66148ca665cc1df2d9d6eae3164a2a88b6e546f3b889ddefd9e91e1999ef1af21ef047bd7390d61b63b82b59ce503059ac0d707b1fb8f9a3e974f107755a7297891b601c237b8563235f9d1ba5d98f369c292dabdd8b97020787d2a74f8257fe872a90f3e1a70513de0770a843ea329ad7def16577e816b86fdb0a0f853a4c6fc492f77b9859cdd4c07b1a37b83206265d5661ecf6bb2ca0a47eb19abc15d7cd18f78266a69e3ed21f409685b9dc2635a9dab028335c1952f06b8ff8934b83d064c8f876b0311084cf33b2ebc123240e7b36a463ba517a68387faa0713f518b31629e215eab8c1b86960bfa0fe63bc3d1bfe8372b207a950c05c7061f979ec312fef6efc75a856042c30acfb8a19c555415418dc734e4c390f0eea91a256952a5886b88c160aa30f6d24d9037b9c4cb328fca42d16e7d8d75bc61bdebe91c5706f8cbbe3620124efc477eaa144470d201db015520c13085d7277fd8a5f5f3022cbffbcc05ef9102a39684662f1a880953e4daeed7429e63147e364bc954c509d81271277db43b4cf45b4e896d17bfb187a390749db02bc76166243d36581722b4b65fc36b7e174831998dcf5c1a2e42f48e709d722b08e88d9a485fc978f0036f14e2ed3ea80d047e145d543626ecec4e2a6fb3d386897e787108ded6f448b10c589be0f3ee08df3888a79fc3f36046bf32cd4fe433b8cd71102da8805ccb93fd9217010d12c034eb837104b87165e5587cf953284a1d828d6b0e0da5b40721729df88a369cd12e158360084f46b00c88d3aec9ff145d1e2edc23b2966a714124e216c57aa5818e07ddeb1703650bf350cf1ab886304e93c1b9bdbdc8e1d4a012c28847c0c443dea4d789f7a0238db5c8fb9d453beafae77e3c1ad68ed7b659cd218db7f06f8014e77fd15852e99fd4d5346e9f55741a8e1761df28a0e5e38f9fbb5766aaa520b2173e31e806be87245da5b30fe921ced4214ee5e8bef370ac3c7cbdd4331b0f5aa92ded6dd9e761a50d6e49d9d5eac2af511c25dade8bac70600f9735b096610d52328d1577694ef801fa79b44c9c33daa80fe8b4e0679debf80fed7b964fe13fd3c9233dc7ef4eeb9ab65e63ab7c58b79743737f42b9d09550f35e6e407f79bdd96d10eb07d58694991afc691be9bb6eb94f6ab3d283dda89a971066c0b5f46c058e699ff6182fda03bb54875816527d6108b30b86cba205c274edc0b9eb11d3ad386ef41ba2304a22655352c8617e8b7194b8dc75277d3f25b48eafcbfda58464806bc34c1f25fcda87d515b7520c250cc827619c37e786050a277f1e77d29b2ef331dc5c9774d260a669b2e9fc13eb5f61a467f3582471a15d9067161d09a9a697cc96eeb5bd9a07897584e6350e01a646e4aa5e7daa65d63d5194d2b51b1c6e777b38d586dc01b8679b6eeb65700cfeb0cf4159cfe338d1e04c5fd670ad1f66bc581f0f8c2fb773f066ef4822e88c2fb26078e332b93d31300cc252b37466fdab5361a8a46336f3cf1a0475bc638f0ebf2b9b5ed5060ab3b7661018ed007fa2b07adcdf1a05531b3f662a110f0d5e878e5774e142d7e29e94cc73e2f008c18029e9fd85c55c611cd5222cc1fe076616be02e0f89bebf1268d5b45f41e024c2e9872db2d791a97c5935a7e6d2b66e2090dfce48699b149217ad2fd3ceacbec48280a7e7258eb7682fec4f7cf964fb84a6e7f02380b29ddedf59823e73885a0881d5b30171aaacda2decd918a8f15b7908a1f5adc46b314000807e07a6fddf4d3443a9201f4d861d1e7abc09500595c3e3b9b37acff105acca0b01c1faf4c71ded8ef1b63db154a6cfc5c6ee1ea580d45280d59e8da831497a6f73f6bfac36dd2c7f71334b0e3a6be5d9cbc3adaa5452526b532e09c3ea318298c684079beba37382b0c4373309ae664be5477fb477df65740df72b67b04d0e90590b1d7dd040f7ebd65e1b133a0d0f04051c1dd2533290493bc88b69ee3f3e2b3f591e9f04d267bd9ce2b438b611b0cf45e370c5744b6abed45f2cd512f75fad2ddc641faa2f690bfb1bb5ebb89d0496c9c9c4e5bc323a6c524686d4892dcf6c654addb8d68ddab36bfab7a9db3679eb0db8df15b98579b766c74142a217835c4679f08ef6a9fc5173e42d6bb7e438cdeda6a58229ad14d2278a81f4ad40dd65d772857e01e3f7fef6707e86fb846bc796e321b87c867641bf35505b4f6f96ee4b6ea44eda7a97f06588d96588ad6ec47744e780b75b3633aec815e9e4b8d9fefebf8b393dbba286a28eeb86054584e62cefc9b430a75c9ead330e3969831e2f7cce84dcf14f2de736b1f286825f4cb9a053d808589c30cf3c61f9a23d99e67793b1f8e8b3f5442363e9e3d245c6f913a2c0e48eb189faef662f8e0b029e88f4b6fbe0c29d03cfdfb45d73be8e4a84e3d5574e72779814c41f9424e4c0067fc084686b62a1a082a2398aba7b35cddbd3f4e18761082f9c0b9140200e0ca6e3431d734a069aa818d7b3033c84540b52563b7a67dec11c83bba033d2c76feea55bfcdd1b2dde85db74ac8d57fcc48d68be2bf5f9b854a798b61951d7a942694bb8632ebdb9fbc63e823309bb3b02c5a6321653f519dd00d4bdefeeca5fb31e6bb1a855fe7f2c72a44f2cc638f481d95bac6ab97d83a75e5ad05cfb9d1b0d7a93b46f443782edd82165c02202761b2acd9cfce60c309e95b5af8ad4c59d77f7aa9917415f15d29b56c406350124601ea01f1095d5720fbc4359cbda72c57c5b61e8bf1c5558b21a8a28a9fd814ed7410302bbe3465010b6cf0aafb8b373a95831448994a9c1d93453705d147219397ef238b69d1b2227a7551ed0be15b12609bfed7b511a8c7d1cecf8c53e5944e707e170786c8a314a6449f197cd2b4b9d7b0404f93bb2bef431c8fc1f07a74eb08462042b50174617020e331ab397be036a610e90becf0f8d0a4c66502caf73da2a9a42a153460d2013647ea86d6632d7c4ad3917925b4b30ac5715b57cda60530c5f8116a87a7a89f25fe406a8d4c7e2a1cec29d7322cdb66080aed4fe230e528501162921a10c9f0f5d93157cb0e4565619b18d71fce51890817bd39f530280b5058507f16d1cd74059ebac6b0c84725cbbd9b17f74e14e11ff2319ae89104ca36e8ee7f65f10200df7cab55371946b6aa5ee8800627e880e9fe04cbdf7ada9b6741328359590eb01af70ac0dc5aed8273c1bc90ca0181736466ef09d807b5e508debfccaa53fc1139ef1b3987551ac98382cfcd7109486e00cf8548f969981dc99b0f468ab8503d30cf541ddeaa00dd66aef254933a691dd9f43418b499e54db2634e6864d5959161faff71e460ae8a707141aef4e168b1016a693b86637e3c0924a33a93c98d7ac028f983c52f122ba6ac2befb64b5edf75482cfb7f4c7d8e6ce382d67d5ae21aec0e389a19f00e7f3bc7113e952ecfed33684859d26a5c8b17be659d0c8e6b740bac68966f3beb453bd1311e32a327165a2ceae0983df46cb130c3f9194474e7c46bf7f5f4dab79234de6e0968ba4f16d2f52a6cb92c54cd976cc84a1e2958db7a86e310db0b0ac24c10b1dcabb7e0f978462b8ef0e5cf4fac6b0c9f48273ce2d144360cf8e3ad8b1d852619b448d4bf01b84f119a53f316d1eff8917cd5c4248553125a796ee100204329c4a5c8d6b36bb857357ea2d69e52bfcc3959a01c2139fe05111f88b136fd076706a5822bbd5f6915e4209b7b885e49997c3e5b173b1f932c40a88fde3cb4bb73508ae369a23162c3c138907a750ffd2387c12e99bca952b94ba469b13e2c01cd33416485701586e5316779dac4961cef5babf706a90e1cf6461a89d939c930fbf497f1556df2f9233368b1a79b1d8ec4f29d5629803bfa6312bcdd8cba48970d92e74b1466fa47891cd1422504eca9a438d2b23854fc2971d412a1f4b84b01a06249d0aaaeed28ea1e2216cbd03f65de57ebd13bf58bfdf108a66d2a7e769015ec9b201bff10443864f6bab91639dd8315f9c9bb1aecb26032fb65bb1c5dea1b2bdb84ad0beb7cf376dc796484de51832d3a6055d30e54de8fb3c4fea44d784a92e4c33e7148b0ca8325943b9a6ddc665fe7eae2d8a49e078af8498e960cb1423d05656c6fbb7059f10288d67543f46b6fc7ea9b0e8b518bef437dcad17ffb8e2f63ee4d18939047b4a61ab49389d0bba4bebe29810daca5dcf927d09fb13f9352d638140226878a945650cf7a14d2a08b9220e45857edc16cf9c0113d1c3a1f95319e61935ce97d98ee85534f18ad52a98150920760a5eb11607c9f3167e087df8b58afe41fc524c3d32117c7654d424d3a7496f4bc07c22677b9ae3edaa3453457632746071c8b41fe1d65c51c2a29151bd2e57d12d1fa21aa6d78b49992ed759914c298e4138917e67f1a49cb425cbb94fe111db70f470021cee1ab1977e5568e9c0ecf49ded764d3852a04150e1e55cd177e8b856adeaa5b26891581caaef3284e8f838b98c2959cdb193b66ad046559d546882747081ed6d2983c9bb41050bd3639a743f98896711bceed68b35c6661c4520d4c8b704d5a45231c165036cc08f06f41b7985879d5f58daaaadb85c67897660439d68fc59ed7ca23c5e29beebddfd3416cc7011fa1f839421f0cb03c62632007f969a0bc825d1d8db4684e865338dc0ad177f70ccd1cd3023d9536e6d4846d70417fb21af881cdff073ee34a4321f4353f32646286bdf30dd5f64899d206928c4a0dd6f33d6140e4d01a21b1fd16c07d2170489dd245fee1478782aee1e00b0d84347640a0882db1de91c87b3241d2a5957efa08fc5abe909e91681e3a41966c344993ef9b89a1042076c0c9ed9e024350c3801b31ac3b6150503d673839a858af2baeafd9c3c5c388510c90784fcd708e27d50bb1767a74cfd8db58e0bd67eeaf0d00417c87cf84e0c1e97900700a5c2a03a653ec4ea05ea9c655e63cda0b2ed8ee8716e8e572b95b631333bcb43c0f0c53ae5ed43a9a9d6e4e2263eb06aced8e17f994d3f2ff644eb77b2023980a4e3fcd87eaf20e14f81626a63ccda8b4f48ed7fcbaba6fd408296a30a94b6cd2dd385508582f4b4ba86e67784f1574c2d5b6d6030d6db14e072a69d4c24503fa02d331fc8221f662eb8fb5cacc473be6b360423d459654a87bdb9225538ca5184cb5fb995580612c1faf405a9e6e41cb5a1b4a858756c355704317bc1ebe9a79d1c30dc7d4b3b59d7ceac3d607f2e9e3e271584dae1df4432036b6abe4316b9fd1f19683dbe74ea8cfdfa62856042fc5f3de9ac13307ed977319adf29974141c986a46f6893f562eeb72463397776cfc8da1273869bc7d76a83838bd6321ff53a5ffe767286f3b77375b6f747abe4055b91c11b176aed6ac29be7b91c32971bb530cd595705f6a33d96e57571b6584054f2ee9e484bc9578c24420c9cd681f79ae0f795799346b3d34fd88a95ec8b51a9b3a9e05245893a721e88090c788ca16f3824f5e6be5fe14e4d0274b058c928208dd461676ce5a1de8867b214ccae5156733a4c4b43818a0a47e8f2ee283dcc54211bc6d8b7f91dd737cf06e70efb9bffc260bec09e40976aed384e45359f871e1b92dea4b9571265fd2d2099630c57d0d322a5e86c12bd592fa007b327a1e281816a7e85f0cfda3cd24edb27f16a2c42d342a9527f0517db934e45f414fbf086720457b8f0c9e36c04438f048616b547df19f58ccff3e9b555841f90b4d17f2e8a42e80f3be03c2277593b065f4fa5cea0a1b503421d227b0ca6a19579d2eee4b9ac8233023c413d116d94f3075a7ac23c60feef13cb484011c09cdd6105d05205b4b5429dc65764bd2e47898807cab354e17b41231dd81849d0b04094416c20c7b0684c65fd65e8d3ee988b86864a7071f58e58c2ae6db80ce552288eb199f5004ab7b4e9e41e0a3911b542544fd86ad26a59528470c3774a1ce71c463dbf5e2be0f18655396bfab8820be25217b4d4219abae733b89437b544743053922e176b5bfb34870dee20b84a852ebfbf0a6de26161f9e7042ac4273ba95da9b94f365c9a70f8f046fa85c329ff69efdb06de81b8f6b459838f791a1da2b317b8e3a4fd6be33af364d3e09a167f4e4b56dbda793432d1717960321d8a23a999165f29d11d71dade6db1ddace6512ce170c352f0c87681aea09383e25f9435eaf055a6313dc9e4a15481617e82119c2b34eb496a1d7a6339872f323afe8317c05a372031663a4a41f01dda7c4267f530b9e82dea4d58de591df0ee8fba05b9b8e87ef0b8571973b5e5551a4d58f54ad7b6fd88dd73226ac4047d37f41571c26f041b18a990e8db4180169d426221d70dd2c5a10394a961074c0cf27f896376533484f2176823fbcc1b2b281c1fc52c2b368ce4905f38f09454f54aeb0ca926504392d1a4834399189332d4ee75bc64d1fb1251f8b55e4c5c616298460be291ab986ed78d99cd29b66a9a46f2c29f445d3116579c7c655c6d54c035baf0d5d6eb83be83a95f1ad286e4578d7d26c8b490d7bb2a6e4cd6a08cdaea5890ab6dc953855bc001a9ed0c7a841428a692da6ec243c32c15f3a592ee6cf072c1bfc1e671e0fad43871b98b895154827951c394a009a0bdc8080ce421ef34a2a028470f1390905f172dec18c495ae2ade9b789174a35678d3549f2e8d1c7d42f49d8d4acdb6b29be6ffb1436e7d29cb4c1cfb1fb3a76312a8899a93f0706bcdb4ab569d04bc1975d7e22b014f7e98f3786180c5e8d5c1abd91392aed7caeb3b2da20ae9c279c2bca013a1a8b75863eabfc5946aabb1df5213a95c517acd2c396e6dbde5036ff36ba826d00370a88c64bd2b9412fbaf779f0a08fd01e6cd8c18dbc3f18ff740597d8f9772df8c654d7d392d09252477f1902785e99c6e2681a56f5955a8813a084e4102e104e18cd0330980e52fe1f4035569b036027e091126e59840f999bf8206c78d0e702e2a338e4bb4d0c033d70ba51c293a490e8064ab82d01917fa4d77e0242077cac40afaab951e1f7460b5430a3edaf11d4486941e06bcc7c8c7116f6417f1e2e78650b5489aae312adf110dc36c75b0589cf9785a5ac6482e3d690e0211f244739080212ce40146b0b8c1151c018be7660b924c1523d3af4dc80c6ddf2dcf26c26cc44e74d9cdb73cb4b811bef76d760e224de938446e4cda2025b018f7065b4e487049d0051859830b9ede40f85b5fcc0375bdc196673d4f74824a1411018dad3044ea55051e5aa5eab0670e7efbae48ea51b25c570e36b85274a97699fd90219fa8602593c248166e87d2ea8c64d57c796f9770e917eb825d283b4153a5f9618b84ba50b6d070b425f4e8a77b4f158a82022f67f9b03fc1f8c38785d418ed71c92c776e475ad9a6af7a922acb38378eeb13a66e80efc89c55d8a255691a400a427d61b7e1077886b6000c0df7b62c784de243bc727b61a15b7d08051547aa3f5bb2ee021089528bd1f4db050c0d7428facf10a5428c35551ddcf23bed8ced931b86c4c3d2f4df343783448c716edcd4df67e20c11a012a0e369527963febca08acccd86fc6085877d18c7ff152604697d278fcf97cba1882c2c3e84ca4c8aeb1bee089bd770ad06877828062386bcf6ee7796b7706bbb69dd29091ebd347d7a58046b67b9cca346da21180453e8743ebbe6fd362c9a07ebfa87f2ffbad7dd960f1e5a9d22fc960633ccf3705501e5f9a9d08dc6aa8b0d072db296365f2a6f59f99097efddd715847c67be7c49bbddcf6a8dea79449c73c669a2f8fea32488cbcf35b0d803fb37d13fbead5929a3ce05a3d76cee5ec100d7b0f626188a7470fc85b0f4ff1f592e4fbec41e043f60f906bccfffb56f7ee4ecd8796a48683850fbc1d20fdbbd29299962e936270afee6fcc7f236cf0e0096f6970c8fda531408fd5e3a902380a51e07e0c9d761d05fbb1d1e9a56c14d8cefdbba2c8b5ad8f844aef138a5a9a58ca91b96816e2b3c0e62bf53e0321612c9e64420bdf37bca02cd2cdf78f60664f6f90128f5d55569e67fe1e9f5a862bfa7f6b3b069db9f1dd3d6fcdccb052d8a957aa7b00f4586f28da94da704b2c0406e0528de8cded497b0a09801ee646bbba8ace0467b82399b84d6700512e91b911f5ada6446d6cb83f61741832a390dd177a9fdb9ea47bebad105cd303bc3588180a23928af8e6df208287b03fef6da9d274b96a191e0b1bddc1136e16d3960f240f6632487101274039a5681923d406c73768bd8ec2e447ec841ed6048e37655004ab440e3284e714f4b0bf8cd8f3ffe6f3707e1fd5c95ea5d863e2074d78ef0209f2b7bf88cf2590606e8288e2abaf3c92db071c3dd78293f64b030a218b8bfafb8fa868946478e26c07d12200505948db3b00abf45dde5513d22863a14c70757ca394a15a7f558e9d03a7a05120e400e489883ff247aa5795f01042b592ca8144db5e9288c12df9bae1a43692bb45fc9f218c460ad70aac1333720179a957b42de510481c15feaff5e5c171670c2bcb7742ee01ba457f5ea4bb3d4c80cf9d13bc1aeb1f2b559fe09e68a3de0ff91ef230f12388cf31e2d4b0570f95d70ccffec5c3a69939f598174b19d16ec3dc615a5d8f5eab80b65faf3db0f5f880975a7382c9d21cf39cce6780bc842e249c50427bfc55f101a2d56c9fd5b975ab4e96e6d03620039793701263b4db0189009c2607e9f8a2b968961644c02648370938fc777e77276fe99785cdfb5152dcffee36c9f80fc4cb42d27797c7e818eb3b2201be219a067af033be32090e49044fc7db8545904a897a4f5df5c1998f4d2ac3f8c0bc3d3f82203213b4eb6346c5577370b9d6e94101ae095c78584fa272c32a4e9e33397ad273e3d22fcbcbe4d8e49c3383e0237a73c95e08be58f53b3aadd4d8f743806e064d8874c40a5691142feb021c1e889c457849121d6f4874c30fab86e83207e0cde39f9abe600f3becbf5c82bd3d91a8425c4516c284db98c9996b672ae0d50bb30e28443fa19384f799ecac3cb6bcb1f6b5fb39c47ee25bcc8db6d50aca5be5441dbef2df3f1add02462c3d1c4d8e76e7840b1b23017af18ed0c92939f3eb6dcc516336aab7d31bd37ddb837795f607d700d8d35cb5c4cab26be830d18900209e4547262e11a72f6507af8b2354785e7c8d03027df6076fbed42f1c7e577a52b5bfef7b7c9d32344d82195a5f1a2cd2c27eb7e8ed73200681ed112f1ab8547caddaf949043fb9d6ca73c86ce273529260c890f123e481738ee6f2e979bc9747f4d491bdaf032ca60ae12f163be3af029da1bbcf54b58206c4d86c72c2b544a3e842f11babc660e7472ae877bea243d366841b19cd6960333486770cef4fe4a3429803987fd0406b5061cdc7469faf7a0f8861069c2ed8241b2a79610ecb13ad1508e5ec46470f0e3cce1ac6625dde41c3cf1f0052f0af3fbdeb7bb9671240154959b6c19d61f28146b3fd3fa52e3cacf69d9536ff3dd52e3d24225a7eebbabd69bd5596e1ecfbb2a851d8b32ec22a99e682257d9067ec1127b1cd20fad809c0450f966e32dfdb61ab7b3d9f14c05361bdcf8fee2e1dc0008176dd88911bcecf8e4dbb53bf2bd162176fce29099680b7481b4cd3349dcfb6ff2c2544369b7f56f98a6a26b65e65313d17db0b2547905b238f01fe45880b1be2441333902dc15072223971452f969189a920a4a81c12ab535fa6b0d8a1e7cb470a31241ca16aba5444912295609d5137bf3275c9e04f4ede1f4f13541a18c7f7c4e6b217b3f6b7c60388e2de350f2d51ea429dd70f0ffd05be00a616dd0c65ad5f4105d5b01663bfe81599273624bf680abfa90bd33f63ce8b8b46bae95297a49803ad066e39e4f05ada03d4ac365c32463fdfc93d65bda754c251fe2771041b3bb12fc7a3ab2194205b1ea150f5348f8905bed5679516c2a3305af5737fec21cb22f8bb5056313b1e6081cc78be4956008db5331e9029edc5505f7ad15f3fade4a4a4f2de91b33cb0e6ff20fff2b7befcc82de26e7810f67ee8a437014344eee8007c76450e58ab15eb16087412b5f4809e39d0d2e7c9b1007ae3b31fde6c1aaa8e257e90762cd2000f8f766827ef114f53f2f2af9dead75606dbf3dc7c360318b71cfbc95fe1303aa172d7f97e84cb4d03abe02a74b6ed839bfaf31c343829f3c5a07099783895f735ea1bd69f321f363a4a5678331a1b4f61d6729c7e6c501905e28602b3a7149b44b105a8c4644717e3f9c325ea85af2bc311ea0ca8091a80de4c07138057c6caf9d4d80eca4f27fa355f16bedfc85df5f9dc43b53b0f058c38a633bc16d8eb8dc81b69b173143d1b15f2a1e1a1faadfd4dbd083372c8a35d042d3057310127a62a1443647e3bbfa8e82e565c11611136f880b2030e870518494363ffb20ce0eb0a6e2a7171269065b681050028193999763ed3ceb14fca79b17339c67673db3aa7ceb85881a7a27543f945f451a9ec4c9c86ace8a84a5de1a9ebfcc298cf3dce81f380ebcdcc5e5ff8b11e7335e77a7f991611727b4ba124e17fdbcb0fc97b157784b422b0bea61f8d6095c088d333bb4fc4b147fa7ee53f7f13e86e33c3b1b58618a8ef5c85bba8a632534d87385c283de451c41fdb49452d6dc284cd059d81379d84f6710f465f7f014cdbf213888e2dbd26dcfd655f31e6aec0ef5df0df71fac09a94d06afce5cd23ae732f3960b9220ce0d7349b10766a53951a02348e00bca528bc8ddbce02d81372ca11a9d751a0fb290b936bd864f19f87dd02d3b5100134fd8f86d05a53db87e684569622180e579738a80fbb8ab08dce17e2cda7449ac2ad85666c646ce0d7191bf4242c3289f25c7af22337ddb05db5010c543692ce7325ab08affea98b542eaf7d286cfd502b34ba69f40fe7d1bbf6c270183fc6f093056a0b583945d89e39be75ab40b563aee1bc48e89680e7ba4f5573e2d1de6d9b20e3ba8dd3dacc6c9d4918e3652ecf3969c6d0058eda49ce2ca830c7dd991612eb161b9f60f15656e4eb3ada95e3ae02fd88411385c16deea0baf428324d2ed17048aae1abb460e440d049a1d561910a1038e1af0be4c338342d185b6a93cb207cf7d857407a365b7c520ceb275893e28e602ba70ee1c0c27a26916ec0bcb21c4ec43f57166ae8a392606b6f295a1e7f37fa4c58136552c92e9d2306f2d4c9085041b2377c6cee603c08ce3db49b49307d9b547c0e447196a377d50375f687a41a2e385da0d03e31b1ff59c0b63568399de009b02572fd42e19dc57cfcf0811e3fca9ce8bf0e8dac16c3f3410bff6f921d2a9c0644463667bd54a7cfed38d1f725259ebc68665ba0d918052485873dcdd203678efc63332d2accf9115e885ea7eeda49a7727122c7b1cd0543f6c9b4a868bc8e14962ae140875e2baebed072283575bed8d36dbf59e1efff79ed3d27ec05d09c422daa9ce89c1bd1670822c9a9eff37f25b8554282f387a7c78223e90bda0d0619a4a9d8d339e23b8ce52d53f20777644d49578ce345e1839688cb0f3996d49dac68d75a6e7d8c966d7ff56f4f17216aa92c952bf9b0867b6c59f02b3d28cf869e317340aa7ac45c5524ddde9b87556dc29d55809ad7b4436b35dd2894dae2a6fc04d537d3665b78dd5c6b5e5cc8462500df71ccf70356a0889afbdcd9783211299b849fffe2588d0ae2d3921959156191762ff728dc9467e886f8f8c480067e0107b90d632fdf487bec9a7ffeaaa3f1db888f16d8d7ee2c2a8688af79a6ba46f4b06881291d8c6c16f8fc650e48a9ae0c7819dee75a0cc444155947001c52ed1b5cc273f9e3b5a541f629dc394bb33b40cfd52be022ceb8e6583fa3097a29468d4ff4fe8065ffb6dadb0eb37cd95ea6f639db3e0a9c19f1a589dbbf0f3a77c15edc636f8858301e01d6923cba4512769647b4a63e814186b975db8cd191014241fbc8caaa69ed739a2f166312161c750c699cbebc9ca288d8d74a29acd4ad49a7f9092dc39fd8ec373c014a762352d095bf222761387f2e956249d46aef2f9abc2719c4fc58522623ece8b1e5b11db2202c6da8cbe54ceab5a1d7df922b96d7b6410240bd3436d971045989320c74709bbc516792cfc453c0d4f84b05d0ae96eef634110d8ac2622029efadc408d41d0b118ba0c62130eef353dcf938b7e354432b322f78cc3a47b5c6110d9b02a398e469b07e33d230634404e3af65115348221079ce56c64051ae2505b95f54c9b4d0e4dea8e218deb9b38ee2be60746becc353d89cf6bc175e962f6994ed62eeec91850d5429992c2a783592c7d1b28132f8b4ee8a8cea22fcf1a99e36d5610e31fedc6d98618ef59a80d869848c6f1c8cb4a218bb328fc0f87b5fd36c1f779c7c65dc75bf0b934fb5c03b8a5b83928651bc996c36308a6c9670d2aee5400984b76a8a7b9814f04aa6ee4fae5de308395d6320985a84a83072f02403b3b8e8696c0fb70b83100eb0b4bed01eebd5ce19cbbe0c17ad47fb26bc39e1a4bb7b183c024bc7d48a423cd71fff8487514a2beecc8006f9ce0616f22292f1ba71f0009cc24fe86314dfab9c709a620b3fd116ba6d284f1a057a9eeb6bf2002a10614aee6add1eb75ff323aa784a3cb2e615ede82e344c804be57c76c4d233e7baab476e254d7ab6485cb20a7bdde13de9935c1b4e5d5acd08e558e93ff1d725494ee4fe694c6518ab125da9a04b4c2c286527364118309865c1d3dd4c5f155c882d606e6ef7555f9553b43b192836c864c038c2124144e5f632e30d5310cb6635407d6ef8027568c8df152a8ec0902de1cd2ec3383b4361c9a1bad081a88b174da7d86268d1822f2cadaadded8a688898e1fb8762b00ad48942f7f32a28e980bced32d729cba5573f0b3db44952c7a192cc56232e830f43ab4acea33b520cafb17ac4da247153c8ccfe86e4a888c956948343f45b52bf19dca8511535c09d5f1e5220fa67c1a9045f1641c6b1a1c317f3cd5fb34545ac6d405da18bd3af36c1d4c565af3efab040945abbd7b7d0af0c72290cab03d2a16367387179fd1198622b87172f3605bcf515ae42560cbc9f670f328ef0a2c52f54309369e226048af96a596c0c3abebde913dbfc0e9f02c2cfc8b7741d036d0f1bd6044bde65c86e477993dbc22203b2dfd37dbca034628e6d8ee9280c8e724b943037fd0495682108a6df4baf5056dd991831edc49719d80185a262f3b5ec04a06864cfb61d07fe3c6e24424fae25ddb6508df9772992df3a507efba4dd14b5c52d59ee2e0a302b9c6e913c4c6a4e183446c6a7a3f3d9ca325f62a86fa9347161ec83bb1cadb148da9b42896e797af176b60a7bb2cbe20cf2ca056250061d6c882c584431f1f6c08a482617bf48ec9656c3442b5671cb5a0211c6675bfe7bead6ecccf20f02cf53e05c5250c4ab96db5a67239e7f8acae55e1a47ad4858151dc07c3b2fbecca62b896d75a69b08cbce99cca1725017b1301342c617c0cba34d195333209951015d0ee682bf14141b60aeda17e6fe2997da65adf7d47e7e3858a51533d4dfc3442d3eca21a5feb752b7eeec9a0c5497ec67fd1b131c5b6f8233ecce4a887982f8ce9c35e32d95d0e565e95f7f4fe41f1aa166907a0b1b3c59a72280d6816c68bccf553600372cad8ea56142f00e9b8fdc70f1688b2491eab0ace10354a284873eed197d6ec7117c7c0fc6b83d60a4056115b96d2312eebaa7805749ee674f26062b55ff71a5198fa46db34a80cf6f59a5b4cd2aef36fbd856c010716f49914cf5689b30337694186787022f7be551110da7211da2a1607ba8be6dac2d86434b9add96715a1d62b45fe90692c8cbdf6f4d1d980061ca2241af7ca82ffad0a6361b11d65b535446f259cc5040804856b2c414d11e81ceaa26702076756bc847fd96bf9e1a96997b2742eea9219cb233be349909cb5a02f3b236c8a184654ad8475630a8ee597efd6e8aa9055b2b2ac97b4afd7ad498f59afd3be16589ed3537c13795c1899330a87f1b9fb5a046b2bf45438771eeeffb0025f232ee6d77723b9d331a56f970a3c8d958ea5444012c7c40387d4d3b6345e74a2d35f5342d919ca3d385b00734c43351202f7359a4ecf5bfc3aa7b068614525eabde95d157481fca6a20457c0fb588e54196b0f44c255f74660c57436155bc89680d859543baa8069a4eb957b901eb811660833a9d70098ffdfe3b118804be3619014cc3ba57dd7353c466ae0f5f686fe1df1fc1957e55fa1fed6e4a435f9a5647d2b4aba1316f161e996d0de1d28370bfb488407bc2cf95938e7fe0a09dbd817682a70cedaab4f03e2e3f09db1e24b707c273979d183ac0566618b867648d5efa233a9ae008fb70895c5984840d96e29160bbad83ec6724d74487e90936087b84a74a4162e04d89d04b0d5f8f0a17fda02d34a232d7aadbd68c811322a6eec025367e4839ee1aea634e4b29630488d069cd798fb5da57b873e887b2ff24056f66fa23529f00a8b989a7b69b26d9a3936977c91f9bc7c9c80141d97f2151c0ae3303e5123cd58043c5245c0e03022407d2b4146ebe0f960236df9846d1f5ab7de14e4aa48c16f8f928e20c533e6ec3a54259b6b9092581dd294f5426ca8bc43201dd722523553dd640740319b4bbe93bfbcb83430cfd3b2cc60ee6383246f4cc1bf5822a78d7310a92a0c1a497e603741f78db44a4a09a470e6ad052900c37e40db10e2d38e2c8069a6eb874e5b301023fd258507041150b17308a94fbe7cdbcab512743fc9c9df32f6472a72c8809511697209ed5f260e8bd56604b7046213f95ca9de0a9e1cb526d62a19231ff4c9e5f0c75a919c1732438c75300af9a1ed1aba3e2051a6e84136192e4cd0d4592a772b978d6352f3d8f9fa57f2c6ffa0809bf9c32452b3db5e4aec00933037aff654a4640e9d8600845006d3d928c9d530cd6752e26adecc47b0b056cf0a2bb233c3eaccafd32be1d23984003c9960e946329cd13e9d9c6376401b6ea96bc4328f7126fb090827c7ca73a92049822d6968a648336bb2d2e5a928304b1f3459cd3c11ea5d24fcc3b9acef1b5fdc57d84566d56cf8048aacbb32be748ee9b9136ef6a00b4d286fef92a2d3e408fcacdfe094321645fbf50fe48e3b720cffcfb3a17ad22c305ac078e2675038018d3fb0421226502a0e2808885bd044c2b78e9d03a946537302ab009b90df4a3c86d48b5f2644b7b563b5a1006d18131949e46c5bc590370e09802b0c36940ccdd74ca7e28eabb19b749e61d03eb62ceb7c242be6711dd18ffbf6f4852c0a7aa2c599208785078acb4d3c7e23403ce3494de7f0a0088d37954508d3993c79be9e138c9311f4ef0d79b67024ac3c6f1751e7ab21f5347b2f53d1c082b24d5958a775ea6a4c3d5a5650bf9ee0e2dfde83defe78244f4301e24f13b6722b8c5ed97f556c100b241f9c94b8b338b94407cd9e877024ac16156723243cc298704e73dfbf82d7d72283197c009b448a2f318a5b5fc75bfd5cbc5de516c039c2f2dddb06a1260eb9832456e8de7d3c0cc51da176acdee7bc4c227173690927a76c2b13ca9afdd7bc79a155d587f23ac0fe9cfb332a3ac9ee3ae7161fb558903b45921c1eaad34fe80fbda1b7680ccc064ac97e5a46046939d578e765edebe80d7a5ff8c3851d8d325a681c93e99e2ecba94c20670fb023eebfd1b591288da909e029353df1dc663eb27b32068378ad8a39f38155b0c293c5417024c46b0ec74e27746d87b431db03d4630c7d2ce6cd7b8441f7397b734c1e70c8d21c29b28d0db00b64005580310bd1b2212f4fec35fc53ca31b535efdbaa33b36b6854dd1f6db38867017de13ab688ae174db07fdc4840754e89a3a8f7f24a81807ed24869f9dd9193c03463ea3107186cd1620686fe6ce90615ec7185577fb40fc4320603a917eee798633d324e21c4cc4a8860b1d045c3e7c27067789086c6efef9d554623b40272cac7dbcd29985d52618f4189a0600c4661b15271b6d58e4de831417d7e537197f645cd81a069e81ef809fd76a304f034fbb966108ca1d24a7784f3b7b8591fe58f5c7ec86272567a8e786507f3aa67e272eb7f8d1b063354c88f0079e010db85f0b6153afd5756f2b18016eebb4852f35f9e7162ac2372862e203fc37e89b71115f1140b7a198819e6b0865400d61c4b142754f7000d5e01c95d69d1364c09a28ece3965fc389cdd2b53f0387f0fdcae6fb5eeefd9e5cc9d0482e08b06520a3cc4c60fb32f214389599e901107bcf9a47f99180e5074f009ab16d14bc311018ca03b0ccecd4f60804fffa2b9ed59297ad24278a7ada31e0ffced5b86033ea49029b8214cc14ece47072f42b1214d99076351be3fcecb10ed13368c7ca88bb6e93505c4616a38c5af7d10552e6785cf060925f0e7797aef8170f021fff4f2cc550760b71f63efb2679e6f783ff3e406bf147d6413ba260edb661c01ae6f35bc8dc45ec7f030959610ed1cc62c8874ca4fcba8b57867067509cdf167b34ef5da8523515a6c635bbfbc1b5ec1ea1d2ba241d00d5feae71bc9a4f160f1f7390d99e255d402c197d5b9d6afdfc0f546eab8768a3fe78ad66b4ab2616bb9658679aff8311d1dd7868043e2655a749e38c72d01faa29f571d1003350209caf303da7f3b19dd3d39c06ef60910fcba537180d79e6571ab0b47f16b92bcf077cf07c56a16e0d80b3f26794ad01c0a1d19927cb078fb25e5296fb909d118c933f819d743e6078727619fe5e727183fb5f14ae1f85a33fb968b96a3d7c72e063ca0e686b7ad37215049bee88fa305069740ce0fc68be65fd3e42d042ef37b79cf3fb1f81fff0ee3c7844b4341d684effd5a8fc89a026b783f092645a9e5373317ccaff2c64a67fe3497bf80b5bbd6bb1ca62eff8a19d9311d1895095cee5bd113798e497fa8f6e477eecad06e52913d8b75c921cab02fd6c263f0e42efa46bb951d47300bde06d6cd6a686748b7de24c123bfe45be025543a150e6d2fbc7c7dd3c17668c0347769f48d703f972c712af4d1324e0c8e30f4651b0567ab4fc2b3ff0ab974bb0d571b259bc226c49052c74ecbbe4b5fb37afe4b703cb5948312a79b3d8daa1d8978f4ecd0c8c2b7a74e0302db2314838cb4a0b33261c5c302c99a21c7409c6e95632e548d1f324c02b8bb0aaa6d22d9ebd3c9a5fb1e50e17a291693a4cba87379f953ff5b3c441a68629ea512576e4fa52d30d3bc1676c7da150059b4d47529848403b4cc6af5a96a90ed8ff66d88bcd41f2f32c475585391a3d90cdff0ada764694a931ef6c4a47e6a0646bcb1d9118a9c6c6714c92bf63dbc6cc6de93c257c032c614513931434b1249cee3a0114aff46c1651ba4b5017486cf10eccb579b871799bdef68869a86f3fdd04cdfed6a5f4f7c54db3a11d09ea37927a1daedac52fde9519bbd8b84fbd5af71dbe04f2e7bce25eada84130c3d1411fe3bf6f1287af50b596778dce4ded2ad4afb53803c2c5dcb3b3268bc0268293b70857fd3050d60436352381f4955af88c44413de9f00e3c6d26410218f755a255aa97727efb617d7b264e26e8599eb1a31caafca6020f067f251ee748e2fcb5f3cf18513da11a241a81cea6ffc47c594ea2dba2667c3c441f9bf113781b6f40c2930da29ef3b0ac9951809b81dbd26b0b50a0c38d0263b5e6cf7e9c8e43e994f743978b0ca0ebebb804bb8a3df37e98fae70ab2e93bcfb5fa7985328f6497011c828016254bb7189e262312c746f0bd62bdc6ec33551a40a4c245b8fed9a247abb8a4a9070642f6ae48eb2c7dcbd334828d35c86029c11637cca5cd53fb6c3a2807b2fd341860029491907d89cf804abbdb187fdc18fb9bd1ce5f67a73bc365ec6e1d7d4bd819a20d55df4f5995448ba4feef4317afced441dfbd3b45c1378b81f3cc0790fcbcc36fccfeb0df0b332badf633273d28e16623f53ded6c5bc4110e826492e240a7f4db66e8344f82815ccda13f30337f57e167122f32f371abdce9c07133435c703f79c133578024fa80ae6900b66438fca89b1779e8d635eed178b4b1772b558265b1531992da5fa16302cfa07b46a21c6ddf656605e31aa219fc4f9e9d77cad815136f6847d84e2d95f2adab6ae059c00811d5d5e1b739283178129e849d6bac04bf8a61a2c6b339c612be1b12ee987b236e4962e8b3c81473a88e9aaae51f709d6a6e5506d9b41343bbc2583639dfb153268ac2666a75d82e50fb3164638cac33a8841ec05a796424f1edddb20dcfb353e72ce23acbf16d4dc5a4f8c54e13d802cb180bca18c9183ccd1720e6b01a1e2e849bed92e69ca3149295d76e4bc3536134082fdbba727c2763af50b1b84077edeefacf984acad2d8df31dd9800c984295c544864ae74767791b4fdd4f4a16727f6458dbffd4e4bbfe51d222cd88a4035c076f9b4c4e34138b45e3e1c9b2940892cf30e599ac57228bc16d768782002ec118d0861824fb10260ea2fc5051c4c2785323448344903d2aca7b598acbdfa2a10dab8319659a0d4611ca8c482a29646b5c33feda57aa5112aa506831ec5ec410e7f69195548eaf87060c4b731aa48d633e0bad71a2b47bcf138b4663aba863aeb2f4e7d65ca36727b1b82c36566539338e1299bfce6ab018ecd724d6f00053fa2125560ca30ee1fe50e436c9de57dfae887d08d5115de756a9c514e86d2c74123f4805cbf054224cad1a28ab12a3d57b1bc9c9523421801153090a350508b5285a9462c6efe8451619e9dc01684310da8c0ee55109050c54804f037c1294843d65bc2d65d5c63591f291b315369fbd9e82422b5acc7724cf64454293012d6437d0aa4bbad1a6094ba04ac6041d904bc397778a9c5b6fccd94f1da80cf69365ecd85d881e4c8b0a2360321f74f0e2b3fccbc011c79fb28c32a988d586cfb1d73b897c113f2413e36cacbc1fe25263b7683929ba1b03d052336f12472e8bca0d4e1573806dddd4db8f5555dac6caca40297088b4612ba90e0ff0252b08428f38db33b7d75d51599de8ba087195b39906ef0b22b321ffac66172c5e91b5399023a9f88a34057b672440a098a6be91337f5e676c985922d926eaf58b9f01d4e986b52b8acba3ef4279a9be9242d1d6cbf337cf2aa30c721c0905de9c02e19056a16512ce0b3d3d579d404af11526a36eabd7a083d166b1fc626a53de85e56d4b10ba9045ba20bc7b29c6b06815368570b727b31d32ec1c4d0e743446797b32f30a8d501b5561b897775e64c453b1b7b42ff564380cd422f141800887b0698b0bb0026660f600159f92ed1a238f52dbc42b37e99ddab981390ec6faaaf167a99bbd37d87930064ab87e710138458ac01510964f8624c9dae77bb283744a3da846a876514ea7c0bf3137248ec744a6aafb6522db90222489b7eda90c0b9d6093033153e73dec541e6a2e50644627467bb6258f9a6ea6626cf81f4f7b19424694e5d9fbc31c02885502dbf233a7a93d7fc53865ccb11169bce715529f6aa0eacc0d4605713cfe8d08598c3e8a81d0fdb8a01c1c99d78e615bfa1a22834a6c6e817020998c0aebcb2c3483fd39221ee7dadab2d5952e93833b870fc7225e45284c770f888d0a963d91c2d4d15d7d39391f27098e46be68747d1d33aa417805f9d95b7d899d02140b94c81172fc3d79ae1dea3e03bac4c4571c0b72d1a420bda479613deacfa7dbf6b4843c1d5116496126c1813208356937d60e12d719bfe5648a0f7f72f07408394a1f75389b2d7fe0aa904f5c7c0fed77a28c6ade1bb1499048a8f02e223bc5fa9b2be0291496a7835e1b7b8b9a3a7759f7507557196709c2f2d51f9ec88b4482afa64195800857c909c6d006d2d7c4ab64533f26a3f27914817209420e80ebe8f09a20e27e16cd1f019ce78501b2c9c731fe9c860097b491a583032e8646925b8bc9b645369a25a093e12b3083c880a96d5c5258eb05a4608f0399be9ece916011a1a400ad420f8236fa543c26433ea938c19c4531e05252f99e440010c5d10b53cbdc2ed814ae7c251aac8f8239a9518d9b24ae7d75d16271c5a48d271040a7ac5e7be4d5c2ad130d5ecb8e710beefefb91bf2527366058e12f4fb514f8bd8f5a1c44a0857f3adc86e2f34eb29d081b1848e7ea62c513ccf8a5c0258cb20b4a6601dfcee6bfa88e493e836f35642d1e4b2d3e032c919fe0ba22021de0b089dd55b051ca9b90caf1eeeba700e345823e92c1169d97d9c75eaeee55d1e7e2d0769b9fe2f34fddcd448dc563e54552601d65cf8291accbf117ece2ad906573a52dc020f004b8daba9a62de2c21eab9d5262871529b86393de595f782ae216a330f78101c93d95514587d369c037bccfe2fcef3303c24d001f7d81ea76c68d6c28c7094e1002f82bd0a1757b979717c6306b3de3d3fc4588b1023fe8721fa3015aacb7bb83ac3ec75c53a9f55fee53ea84d50c70281f0ffd0f9592afd41f65057293100be03c9fd7fa0b28f613d52a0f98bbd6ce6c5eee477e680d037bf315e37622846c4b5173c120f7a65d23b95654f8ceb59722c8090cc2e7a7b3a1f1265f4b0027e94d925a2109970e59eabc4e54d7c86a9a998e9cc08ca121df19a94460b6045424b7583793589bab38adaecb81e42360cef437980e685b549dbd967aa89710de5b99a5469405d56a3eb7a99d0c882e7e47420b60b4a794487be2d04bf9cb986eef644e8ca0d8ed139f713075409c1a1ba08aa4ea2532ffa6c266cfa4b52f5ec45e67cb07be70d0003b49795f15bd9c708bbfbc7f4621c3475d2bb0a9c35affde49bc72b00abf023d0f64dd29a4651bfe68832a4215cc0a61a7aaef7b843ff570ff14a32fb72c9a1e6a822a89cdc098b4011a9577063269cee391c702ef67e880c312e831368a1c6e0229fb9f34d7323c1c940fb40483b852d86b5549fada64d48a91fd0b688bf437166881729154de2289931359520b4c0f7421f0e15737043c4b3712bfef60a2e83ef9772706b1ee0fe4ddba895636c195e174140b450572bde16cc4ef5322cce7c6b00c7be23f307bf424a743f7deb5d3d1e5f2b6def323a48d05eb21f411f43b45593ba4d5ee43df59299e913067ce909f62e1ff62be49d15cc8ec17c649daa50b97e2d9cd53612ace05abeab7ab8613e145cf54b01b06bd837f98193f139f1a9a80733c66c2d52297baee344040375c67f077d69978d541103565c6d0b8fa7d9fb18926d95451836478229640802386c824a9ea12ee44736a36678064614a30790964ae04718faa31a16e88e1e88ed07a58be39ba3ae2000f43008aa76d98afd564b6774e84968fdd8ebc0dcd7e7004c2ef31ee93d65871a94924db3b4c7057cee6e52b5f0e01e6615d8affa5179eb6edc994c2e05c3fc010b3a4b19ca1054d0c000389520f5ad4ebd82bb3ef34081bd7622d00fb43a481a0c08e3ee872e38b3abee215892df41023b9a36be9cf13e25e5d266c3ab183b79b345a52d8f15ab3f045ec71ae385a47bf5492907c89e349ec8b430e4a3a73a8afc4b56a4279213a3de40d080804c104c27f1057745bbfdb0a884f6efab326f032e4a1e210f8dc012c1b0d31e3ee54517431a24d76c5347e7d5140da543314c3ca2000e2f1a1c87a1455d8d96f4a7b98fd801833261197af23f50520263c11dcd5169943c906bd7254acfebc75b6f98973fe8c6894cc90dbe9689b6291c625eeec48523e910920492ab4470f61335475e59dc6ccc2bbbdf16a00092961bf488900694b8c10e19229fe60aaed92aa73a6ff5c94516490279a2f4851bf5e89e7cdb5df5e21e0f8c64b4840ed2c595307c2a7ae4b1470ae404f7736d932d2eac00a5044966ff499d8ded8699163fc90542f3ed048017d2d86956a6fbb51609b0771d4a5456282dcf63681729f0c3bb25ea5012f185b9f2074bc19fb10f4ed7be0873443d3f94a62f0ac3e2b5128970ab5cabf9971dda7d50aac41bb37532c629286ec7b496e59bea8109ec89384df70caafa5492468aa0895795e3ba226688000d35d957627d5ee0ed103a19aec243f17b52e40a08a0b4a1edabb55a555fbfa050c36dd8b1bbd89e086529869f1030e2b1ff5a8f719e3948d2dc2c36ea99b56c22c645bda35d921ee398f44131edd4c50c0217ece13935016cd67aca4cf72caafd059f8eb68ee517296bf8dbda08d7c9328e643681d8ed3590d28b18758ee76e04d35aec4cd65769fb84ff510f13ca44ad36546e8713c31b9705f115954b8c7e00914e28ef411f05d91d980afbb32b6df9e043f19ca00b4e71104dd2092f9649f3e2aaf08dfa1e347742afe613638b5e5c74bd18b1e2d91e06e9f50bb7da5657b8032661838e31f348d40ac15fcb4c80fc6074104acaaf511fd0c27da4534dd116002870dd98ba42e35073462b95efcfb378be7a9d9b09d6ba524897a7bc6b2d2f98e8f042649e7dee4ce9e57e116a86c18e0a318317c1c554e1f6607154038cab48517b0d4881b1b0da9f37d66b69a7309ba5c35782bded400af1805aa2a54045cc396e32ca6ba5af19c58215eb7fc7fe42fc72afd9e08153dab07002abf80998feb32413ff910692469551ddca9fa0932fc664ad6ebd29b702570ece51efcf6e11c2a746272e6600f2fa85d26a4afde38db90bba29bc33573056b5daa3f7644e8af305bdbacab73da49c774fa65bbfa930f0689cfa02149cce3dd61d4bd9708f85cb7ff0304afe93a41f8989a556f938155cc0a57eb5148eb004e178d500d495a05e42bb4aab714f6558c4c1f1f82642b410a1c2448f1934e715b50c2e2e57f7e08f8e87a28450028cf1c4e6775bc270a695db9f839521204dd3e7ae815a1e943381c17c957101c4c174bfce55446e2b78c268d2a6e09cd02a641378e489db6a1b8f41777a86cdcc9216f7768f7b3565392bf93fa7340196978eb978a1f3bca4b0338a4f9915113d9fa2bd525099340ac02057fdc4fc00e62c8e41db9597baf4e0a780a4ed7d2f8e995720b3f5d0f573dc45d2752c4efbb7e6d46862c2d52f133ca8d1d49fd1df85102e036a6d1a57adf40fbaaf3944ce2406679451ed402939dfdbce8eec03db1f2d71112e27dddf100807549ec04b6d711f6c8f51e6d01a6ea0c7d43f2ff14aa56b1cb1fd09239c055fbf897573d252d4a23b407bd41dffc5f9c58be3d8d2116b5ed826c209c596734cb5c56fa3490fc5449c38edabb87f56014800f8aa250eb6436bfa5f7def10813bda0e5675d729404c72572b09640cb6aca4a3d2dd6345177f3067bf971d35af725a9d20d7acb7372d0db1e07417a4506dd425bbb903bbb50f38b8a8fe4ce29b9e105cdc3484f090fd0a2b193150cb713fa534fbb809fd667897a9cd67b7e9ae64bd84956faf6b6ead09f37bd3e1612a35c21f49c5f2141ec479a7f4b60a80a90df5288f628339ece80fa577a007b180362fb4295f418fedf3f3260c5a55ec1726dc66dec961abbb86c44ecb478f19763b316c23669db2dea5d7d9a9f50a5ffaef8ad96376a633c689194680568d29dcf7c9ac627935a107617282f940ceea89b6ec4166a1454d64ef6601ff011716a42b9ced359178976b77d1a6feefe8455ea62a7e5d846d9c8a0053c7787a6a3ac8553383fcd3413af2a83b5bf4dca287f1f3e14db9803580fd0710c95560abc3a03d1158aebec3ce678b4edcc49aee94cf293a088562fbf2b6b21a727d2633d4f434d1b4430b8410dd4acb1ddeb80006ae6c5576cab65702143c4d34690350bea4c503433a774eb5eeb5f73fb9cab93845dfaf3ccd1039be89bbbe1827e69e6609ac68d596155de634b7bb3da5346e04baedaf1e3237d614c5fd7781e58dcf70f95fcc39c084f5a1ce599046fcd6d3ee84cf076054ddaf562eb7e111f824214b365f46013eabf3fad7f2df3b2757ed57bef2358b1fb3f446d904c2af059fba709665e50564e24ee219e46662ee227e0729bd8dcd478a10ff15d0725de5d0a2da23b52ea3dad919ec3e3b701ecff7a477150143187162fea8697018cbc53bb9d248e3e5523cafa335ad743379bd0316469b17fe8810ed228c228e79844e75b748274681d9bf2a30e43948c6262d12d1fe802e9d16223ad5b1d2fce7fd44a9fef10addb78b1218ee33ba80bba67b568cd4732470f9b9cc409eb67ff8a59b616a843cc556c5f7ae038e3aca221cb75024aac481c534f3205fe665919b8fd97da4dccae37f67404f3f7bc220849e3922f08b8a512495c76e0f64f136a3201571c2914f15069bf87f23ad8c14a983e97a11494ad982a7dc5bce161e02a3c50d9f9e60bbab2e42f30c4a79cbc63aa0d008ede05f84ba9ff257110d0fd1796160758fe9632703a113e8f75f7fd58f21c0fb1b94d20f341d9729983933d33fc74a3f3acd86ecb3a279ad21cc540c680d919973aaea522f7d27536e6cbc14cc1dddbcf8c2e606e7d76d875004b6068b2cb5334493d5e4112d76118b2144801396a25792c0b32de5784d4e1d58ed898651841a359bb189482c772a16e115b2fdcd688805757cb1b11ed3a9e7da98853f0454c2cf4f8ca583d356fd8ca240051e4ba115d6dd4f9ecc35f7c63e8740c586e54b7b7019d6866bf8402cf84b0bfa8ef934f9e71317f3927cfa6b8dfc960f0c1e64f22568f4c909110d8835b122be92153eaf4ce01628434956446054c31d7faa86855e578960a185de37b4b91668be4cd82b73557f9e83e22b8562a5674219a3811fb569f6125701f07027fe62c3ac1e93f905501eb867056443a46c83298bef0e868bc56f3201a356017bb109bc5ebeb73a0b288557c1cc89883d55e015bda153622e265f0e28d62ba7fd267ce26abe86daa46981f1057d4c970f76eb4a27190257f333a5e3e77b62080c2e3844a81352e089faa7841cdc234eaeba20cf2a139d1d537b5cfd4f1e7fb415437ff259930c3ef8c754415ac150ad048627dbb1a8335096f6451ea9eeaca74b853e8a17ae3a2572a78b2158377f1418a1b6dee3573c46a98df12ce719b8b852168e0dd829bc147c807bac736a302ed60f46ddfb0c8dd891cfd2d9f81e39a2ba7d6048e3d35ca6e820be106be42f6181965a7a482092f42e8d00591e482254ccea7107ca442c1c254badfb39210376c8ee223187f0a06af7e8a1e2c25c8d2c99fd03afe441ee6cdd7118796a19d0849242f27825e34c81c1b1ec642fa29d8cc687884cb16e459c963d36a3b6c34126198d00906942d1f171771bc226764d0c291063e5927eea180b1e4a52c0bb91cc482355e9d7588d035e5059fd720b202019d12a1c0e76fbfc3f6f566aaaa402844fb0043f7051275ffb3b610a1b2f6b850eb7de0f3052a501cb4623af8bfc48d7210450794655495056e7f964c1d2e5fa746ba04c0196ef03761a14e2a5f69dcd450c5e981424589404c7d76e802b66c2bb6a90e5530aa2c1c834a4ce33e0b7339224d150e130a0f2e16d40e5ca5ad857b6f23c31da77950475a5c6263aeaa5a6442ded4c28b3d861b4416be458e32e22110fea2f66c62ec21040226540c14052d58267770482eecf4e93024a402adc0a82072f2ba7533135473583fbd2c8360b79202bb36a7ef836a529a7f4061eca4f73ed603da7868564ee1441bfa5e2355433b6db1ec81ebba53884da63918a973a3fe469c2e0cea38b2dea32e5f85a49a04c0a5ed79cea49d366abccfebc4e65b9e86461c50529815e1be49ce3941126002824700a061a3e4229c0c0acb62768c1d4ef74f51a3bb23999019267c2ac33b991db4395329b4400f87bbcb0f5e35d1c95a0a68bc03cdbe16cb3d789347d83b4f32fcdeaf0eda432c522f7420e53d0b592bd4901a8ae6fde033cc093f25cb8fa4b48b334a70a8fed0b26641708b19da179ecb6cbde197d7838a104219c28039b66a7fc987949c1d940faafadbab954bd2ff57526f79b1a594a1d2286e7d2a915a0bcd1a8cc22ff3903a10bacdec4c568920efe17272bf672109cc4c5557f0f815a0ab7beb8d4909bedd12adcb0fde5ac299e6e713bcab9ccd1e21428df8de0633a61d1d9d97713acf07bb530b999633450b6bafdf16862cef5e636fa02ea326e0c63a793d155f69613545030e1acc85a380e4b2ef2d2bedc4671622ec40a3dd8cfe8a832d0c7f6be95ed15e867386f7554fe454d9ec8b6aa5b4f810cd72fae0c2b38904b91976fe335c88f79db46899057c479350864f869116e5eb3b715fa32b9f2385c23310f4725018314817ad99a075973b44a836d346342931e577deff7e1e8fc04165a4d3396064728cff9abb8fc91206d70d88209df3ee9fd74c65b5105df0611af067630181913c2c0f7d53892f9569f0494233eb7cc3b60555f27249d0a71d260970e2270fc46870647a7f3c9272502935433541a507ecb4ad091123c20a6826ea733695a3350564ff438791b401e7e5e878d31c865f032357632aa7a22eb5ecdeae41b351edabf0effcc546e176b63d734895037ab6208f01c253d19bfa79db7efd775e150df5b0ecd300a9bbb9d3f6d9337e08ad142368f5125cc79abf5a9c2a60ef52b62889e47d9dbe2a167ea7b964b7e2a38e0062cf3f4618cb847cce32c641c20ea9b26ba616e9df47ceba2f631e7dbd81f715d76c1ec3cf72c4e23b9c8c566994724b43ba155214c617262c6a7eaf0ff5c570f070c56c7ae7cba5426288a4ac1791108d2a713a2168d1611e049673da9e29009510671e01b8ea929f1c005071e34b4d2dd8c3133bdf129b7fff19b8e7e61963f0adda7f2f2af3c59929573314433425948b917a0a19351898afccca67216a5ef7e61ab9207d93265a0a2fe8f4cd1992b84fdff01e800f516c4db607d8eb5ff1afbd9d70812e6b3f9a5a371dfb7fd22aaa5a9f479cd7a8be6e7548d412ffee59620581e399ef5b1e5bcef804121d848176037220a89309ebe9aaebeebe553181e915e53e85b98314b8d10bbb2e59a75219949bced1a5bc35d08c969d1e24814e9a3b167dd1e9bc0d14d35d74a15ca9882f330908d405aa92f7f2a1da63d910df66797d0dbd453bc53d36e3763a033da54d65ba0635415b1b70434cb274f8745107ca363b0f6140a4582a5b03db02a72ba4cb5e9aaa515e861ff8aff2d97c634b08aacfb67ff40c1825dc6878105097cb399f57af40cb14ba3aa4976308f61080bf1e91d7bb5c28aaae4349fb908be57df8c4108c841e17978c9adab3910c9e6c6018e05574d9e9ee021453046eb704440e471098459336c0c040a3d6434f5818f0c9b22cf6d53a913c6e81502324a391d6da505bc995dddb293e0c03a8fac0b24088227a58fcb2bbbb7bb34999229d5dc75466e1c2ccd0b71dc910320e010d5884c136586cb6c142036c8345136c83c500d8c6481ed8c6c811d8c6880bac0b12eaa5fa1efaf6f07155538fdbe3f3b93e3a16151347b2eee3fbe158d77355d3944397139a7238f91d72b9d5dfcac618638c114208218410c2f7de7befbdf79c73ce39e79c73777777776faeb9e69a6baeb9e69a6baeb95a6badb5d65a29a594524a299d73ce39e79c534a29a59452ca18638c31c6182184104208217cefbdf7de7bcf39e79c73ce39777777f7d65a6badb5d6bcd65a6badb5564a29a594524ae79c73ce39e794524a29a59432c618638c3146082184104208df7befbdf7de73ce39e79c73cedddddddd9b573a6584cff9e75e154504e4c2814d902a1863b7fa29a400836da46001db485102952d3cf0b98fa4329227b601c2836d8038db0069826d8030806d8030c1364052d8c63a826dac20d8c6b6c136360d4c1440bffe50424249aeb7ac96cff798f9848a50477c58c654967cae0a0754b460d6912c86a86c80cddc21d40b632a4a9230c6546018639a238c31c65490a81cf90a89bd9e277fc47ab93d2c6ba238d70887268efe497f74f533f7c3f9dccf1d71a18205632a46185329d20203c6545e185321c298ca10b669d15730a6b20117b6855de282a4f3c3fe28e2e3c5763a7648921f458874b46821f2a164ae88aa44439af090b930469e090543848e7880fe7291a13e3ce8c8e543934cc85a231f19d8428587158ca954c154a8d05fdd1117560734facf45c203e6b2bec7be3f64664fd52bb92610e8c8f5413cd6c888a8489eaabf3f246499155030c67244a161ac314d11aaa00cabe8c0000bddd0049aaa6c4dbaa2420f0c0d1b2a3cd5774c3b00f0b932c8ba4e3894907bdd1f9d0f45e199cb84e251c5bdae664c452565c3c281239625b22aaaaaec0fc6545054348c59f7ba3f9a7bda454f9412c6d8ae9ab0b0ec4a49915d2981728bf7207d81723497c0188b7e6946e75a3a3f8f1c3ce848bbccecff1ef1b20e90234a74a805df1e9ad1e301034d9793c9f668e9e14a801c5162312633f1c8f1388a09cad1457d2ceba23e560e28471c1d508ea2c8408e28f9184172592f6364574a3abb6ae24c30d64a20ba22abc8660a20303661eabce3de48fa888ea8f31194d3144e50e7234d1d26a60141a5b1da10411b44c0010b58932b363b446c2433e12001b062a3e30bc63e1fe949aa378208f684554956a77ad146878e4b87033050040cc48051e74996f0c1468a2b30c6c282012818b32aa9a3ffc9b43b22ab8531d623c92687c57eb4845a36505c6103850f52eac006fb5495cdd4e7d3d2b035e4028320c2e6021b60cc021563296bcc8185f1441a9e5882554b364f0cb9a229662e3acce108c7735d11e7f3696161d9acd880a54c2234a1e2848d05d6d858c0033ed838c1c4a60913308e1c988c4ec886330536842ef0c0494105f470814d05f4c018eb3c691bcec418732eb51d3b44a024325fc9c8b430f6b9991a62c9542db7ba463e04d34704aa3c1b09786023810c5c95d67f512ffabe1027ffa2ef0bd944c0061148d940a00e10c80193fea29a58d789c7ba423610d862038125623cd6f564204a8c70eeadae68f3802d30eb4ec1360ff8820a6d1e20a4e5014b30e600351863317a32325d119a98747868cbc5059424730192b13a1f8ac2d9bd51037a6c18b0b26100130c6082310e0b753eb2ee16515efb223972ed6b858049e6c0cb912020a03c2068b99e8c5ec92f997302a264c9a40513101c79302130b201219eedb94498582d727c4097479a429258861c491205479a7991fbe1162ded0f0f8c0d223292248b249e3c2da9921c993e8913bd64511f1209c30507b4f00cc2c2d32204c9f595cce5cc60171c2ed828a00d1b051861a38032360ad0c1460134b03e32161e15e8e40005f2115c684305e070f590851a2031c6133a0e20da30d156b08735d070c3049c4530f98c7a5c4f2cc8ba593c93fcb94cf2bd9010614aae1089ae48743b2c2c1b04186283802e3608d8ec0afd14fa2115b5955c0172b91e897e1d9aaef80a486cb23140caa6004e5827f49f4e27ff13bb9b18d1a1e90a1194238f75857c280a8778f0e0e8e0a15d3a3cb48bfe7fabc383078f1c5154915f890e4d5720d1a1e90a3df1d02e2e3cdc1bf1d0555833cf44bb34094d577c0e4d4cacbf46226b09679676716fa45d84f8606109000c020001211eeb0ad900004401c61eb1516983f9610e8cb10fb08d4acc2645114c0cfa372967489b942752689a9ca454b1b9b1871c53141caca9cd8d2aa46a73e3011b94456c50d0d81b941730c6a0601b14cdc2a9a8bde32b9109d846a386a68c8d66c846b384b4615bd8b02f366cc8f5d5862d61058723e94aa481b3e32b512568c0e940255c2ad17870382c1c8e136c80a31208a844007050c2101c1d1c4a8c8112656440070e4a0891383a28a1b22761c5240cc0a25feb07a2bfa22e2492208331c6246125eb39a129128ba8de88e79291627244c1c20213c3a1ae98188e355d333baa37627dc5c212d3014e2887b55d38f7c925e2e4439dcb1a813a9c113533a2667458574f5493cba12e6ce409cc11e999782e4b743f1f39978ec8b1a6fba21e121227aabfaec74e70ac0b9a389bfac19162622e1ff737be2e14505c4e45714253b56387384f282730216a141303c3912c8e745d0e68531cd07baec9c9358db8906242534c4c14319c4de968e1485fbdc7c5125d22d657a3eb5a9c99ebb95a118e745d77e25071672a10b5454c4c07383f71b68889e9803551d7a642238a338339928e8ad271598f6338a2d1570fb2a890cc9db40e5d3b5e8f36c7cae256562644554e72114f1e11a128986be4f3190161727fe6535dab8701086293872f04a20d10e7af90953a81786be2688e0efd15132615e58449a63e80900403c41638a1175180a00120520088108b8ed88485c53561619944f76238fe50848ada327f600063d80f9a31b663478a1218630ed071b9689747a2848585593e34a2734dd88a2a461c0b33e18310c6d80464f670c6198c85ae08498b1ef4c0f250823c8c40094aaec0831d581346eea01f0625741540819444c884a626526ac0580a194b04a048455595a6184ba1016329638871461b0eb8540ebd937fe9811dd6084d1f2555b0c30d18b38311096bd4e081963a9c810896883ae8b02ae9006c5c818d19e06023056ca0808d1184a84906efe05c0e0218634eb0b159630dc6ac08fd87a343c602ade1e8b004c71a1c3a54820e85608c55c170d0c1094a8430c131872bb0221eeb0a718284f3fa72724894c5a17444c1917e46749d20a17cdcea1af9f1a1282332a149eb1fd7a8889eee1bcc8079a2556aaa6ee8b3c541c2919ca53967535e514e387f8d3e5468ba9e4ef31135c3d1d19cba704c8c355953458940530c27445d3b2c3d41019aee47445dd3547deec4b1aec96af97c6ef54d2c1e599787a3e3529bf3202adfcfd7b29a4c204a474c0c87874c753d1f8acad6a427275768c4f9cfc789075d99d0c4c47242748da8eb5217f542bdc08046a049ff8fd00f79728958dfe40ab9a817eba91f17f512ba3e422f2a5215a99e499eaeb8a8978a62624d47a81e33a1960f4519a1607a9061c3382c478a1c3962394d34d1841a6750e3098c75aa8e0e0ecb145647871a6170acb0c20a35b4608ca9b1a2c603c6a008c661094dd66505631a2eae18c31bc30e58889a44f73d1c960fc184c4258d277058d270018e344690061769146139240e4b13fa7b74ae497f07949f88010c31a4400c23e0b0e48e07b868012363084dc882198c3110c311861446857376581d2a1c10bc08a30a621802181cc0d88d00b047300d002ef0852730c6a41c390a0ec659e04217345c9064469803f25c5345c97c2e27e643931dd2a345888f167be425c9243495a82852682a1113e4c63014260ce58322330386f2416182a30b65c8c85cfc47ba702f6b1ad2851d5c58438af9cb9a86c470ae9b0547d2ffa14454e6709e63018e94afe7e870a7a339a7a2384d4f9cd0168fa3c3717478076238143ac99fb4e61c87baa66f42e1cbd1315072642ebe46a2cf272647141d6b9258582c99db6307c79a2c998b774c617da66b34458ce813c32486f3f9e4700e069e5c9094a32305678b28385658c1d9c23918e030e9408c8e3c55d783a897e15c1fa27c702cc091663e94934b874539b980e0ab450b11169618cea674e8529548e6e2175d1c3d71583a3b26d05b1d8e357174e8175594058596b9b8ba7ae2845a7435d22e97c5b13ed3bdae3caa6e0f998b6574e8be682ac4b146435e2a690a504c01005370aecb094d9d101582f91ca242a2ebc4ea40a10bd6381715b22ac99bb0b0e07802179e608624499c8adafa9f10191b85260a0454f54bd068038d32a05106c6382c3268683102612178c1189b49c2188b3896d08614ab620ce5105cecd8a1843d304b66b280848a582f738d58b7b221171f936882d9457611075c8031266238ccf0006348ac99af2820d40eb984ae0889e5b1ae90904511b13efabea7850a62fdcf5c23d68bae132414102b025542fe81fcb0ac9f2a0a0835f9b0f61f115d22967575e8655aac9f7611eb87b58bec22d58b46482a0a0845f5b0be326259fabe90d05796e812691922737b5cd63444263415b1f008494b450171f22f445001bba6d0280707031c782b6a534ea821d4934b24e43255949307425130d48b35a23e4455951d61e1841af2d7fd4151413e89f5e4120951d305841886861f74c198e882585858587eb088bfeea7a22e0d193f20007b1085446602c1571c2a1a87c7680394e1304302f7351bcc074db0911e7158867c88fa61b5507a8444cffc157ad23d6803470fce601c4a8f9058b743e911a547560f9c31c612c0832f30c672fc68e69944c152f6c018cbc170f0e0048c735d263cd082071a608cc3c2b9eecc3349d93b00c30e0250064c13280778f2c4856287282020892206808223780660884230c10227d2c0002cd08032c6aaf0c318386954a0063d9680e2107e5802021798431a9813444460103908928302e420004224216a8c31160197323c8cb18d093230882b30c6363b88c4166630c6981ca3038e605625791316961c7cc19837e15017a722e28223070588030e1ca4c1188e1b48425397435dfa521fe962c65216c058ca2605a4df9a58585e67c652703096a2000368c0067b48b991925f090e1be8c051832dd4600835f8823186e270d4c0016400828c32ac4a0a51d385830665b40089792492f52e2e42c6d8c1185d30360587e5832f68d484c22d631861d635e18e154d74588224e931461d638531c6b1a2898bc57004631c1631d610430e38c40802632c07a70a4e144d70582eeb7e4238c400430ccd3856f0e070582c3134c0981812601c16315066408819881863d60e6b87feb776a07421045d608c594da84ab27e5f4e35ca997aeb3f31f995c4bccc05fd35b570249910f5b1a6916585a8c91aed50889a3820eb73ff7a99184e4c8e28a2b8de8ab15a3892f5219840d325aa804cd515baa04742ed90cb03e93c109de48712e933dd2bf41ccbd211bab7a23c16870a711ebb48319c7f8bc332f3a9be09c599b9a0109599640af415952fcbba9f10d5e4f6b0acfbf1a18ffccb45bd84aee740f517a5e4a25e28180af444ecf5997ae8cfa7c58893d75f08e18b2f66fe8a98cfcde1840e8d769e6246e40496228a7cdda91251954814c3a9a6095794be9ecf877ad99592904b0b057a223f2898197d2dea054855444f3d2eeaa54911d1f5415130216a2a12b2211b72a92e108a82b9ac6a0242ed90f5d38e1d3b44160a8a30c6383d4e9006564953ece8585e80c19864ea93e435f5e20223737b781131e04505bc58801706f0a200321773f46fd1014e193348490063294ca41c20c5005d14813126737b70a890b99810265803634c92b998a3a990654d1f1c2678c23ed3d513e571c2c2e203a5007a28c11349238812e8608c713897046d304ba34c3848e00346e120418cc4c508fcc0186b32e118c115248c63045d541c2300526bc521821656450174ba0ca360e34797aea99b98ea1ca1060a56bb4c61a315cb871b4a77cd13e06e8f6afa1a7eedc28c3dd3a19c22d0f45c344eb037c38ae38591ba8ceb7d4db0af7fd318ddf3bfeae685311a26585de1dc744a7c5f7e0e3f346c96db3d8cb0f97651e308e512ec9c18ba6ccfcd5ca7acae042b9fbba8a3db78cab963126c951a6fa8ab768777f333acc3bc65dbf83918f17e29fd753448b04ec7ac31a65747e7da8c22519223d8f8f0ae8e33c4aee5a7f3c90ba9de0935e4031a23d8dcfeba0de3ac19cff8ead4a379405304dbaa7687ae5d1ce3eb8d93489224814621f9b2a4833544b0f969eceadbede5e6fe310ec1bed71ef7735763ffa8bf53a3460876ca361bd6cda1feece443af7a24d585c47d5697f5aa260896fe7b3047c7f7e656dd047542ff993e23a272741d472b302b388e56dc6b806065d3bbfd6db051d79b66a701cd0facacdb6dc75adf6ffb5b7ed843638675b16dec707bd7e17dba5ea0dda9fe697c609fd64f52ead7b9ceb0beebe981bdf866ec0fe576947a9d41343cb0593e18a7abeeb59bf1a45e5dd60eac944f65ceee1f218dd4559755869df5dd87a586f3669829a5280c5f9674846874606b7559679413c64df7cd9ee9a20bca81ddf766f74fe7ddd0f7b4a64f731c58bff331a538cbe92dce6dddc0ea9aff1b7ee8b5ddbc5db481bd3b53d71c7fbbedba4b610d6cf3b97dcedfd929ce5a3f322caeee379d79c28b9fa3dbd1c0eaa751c32ba53f7d69c5d16ac6b014efad1bdc1eabbb9fb367bafbd48861fd46e75b561d7fbb1bb135037b6b7e38fadb5a4a39217d61d858e77caed5fbf42774e9c0b0dadb9cdbbdf8ad4a7967a7239d0cecc6cda5d4336a7723f5e799eea8260696cadfb369287d579f128a44231858dd74cb39ca58b3be5a46cff427efe954ef84fa44d7bcc0c2bfeebed1ad5f9c147eae0b2cf59befcd98ce37e97e6f818dd7dfc3f1b508a55339a1e60bdbe473ed0fbfce279f939ee9fa8a9ea461818def390de9ccfe1c965b7ba63bcd0aacd4fb3aeae2cbd2d51aa367ba4569e8b1ba2c8d0aac7baa357d70dfb6b3db3805163f7aa3df97efefb62bd6a0c04299ef84713b7c6ece173527b04f5dad33bbf932d678568d17d66d2aefdeed494d639e2d0b4d17f6337c9f57e60d63cd7a7ba67f6e25a3afc879f517904a4d10299634d237756bf8a7673a753eea5ca04d8194c0be0863bd186fbf9eefced4f9eb90a0e5eda8ae6e3aedefb2673a7585a60e94a3ce5bd51541078d428fc8086ccb93c2fdee67a5957a135d22b48ac036faed5108f7bc717b082c8d3ac72cef7d8ce5aed5337de6993cd12542e58c759b3a296b93f9d6d974135d22f4899578e7e77cbbf9dc9e2f5ed634a43ab10dc69aa97675ea8ab3feeb296de2304f7db78675be97a3677a8419d978ab7bbd9f8452ba9a75abe2b2d7fdcefe6486ad5ead9b65e9750fdbbf4c5f432db367bab4a2b2fe5a7d18cbe65ce28da1677a44e24e2fd07e5c5818dbbb0ce55787abb7d8a2af1189ca97251d199175dff561fd36aba6b8d6e7f22b2a3bca62dcb096355e28a76cfb4732554b8d2f4b3a5a84a84bf8aeacf86795f039f8b2a41303b2d7c5afb4bae95cc77c6f752a3ebfe7ae1162f8a0bbf8c2c4e6465f83fbb986cde5083dd32d1d1a5118043662fc6a73f77f5daed83dd3a38ec9e6e88dce7c69c5184ed8746872121a51a10e75168fcd396be8d037c4f29d5611687a58c662fcdcbb2f259e54e6fc2edb3aa7f37bf355bcb784fbbabc75fe76bd7ee97e9cef84d40eb9e429748d48d29b2f4b3a5b5b97dff2acf06ead6ba453263431a92d5b8733c6d1b5b8277cb44e08b17dec1e7df7f1cdd5eba4cfa5bb763ae7f31d76e7bcfe949ee9a1ff74a48bf1478c75f4b55cefd6f8b5dc66f4cc8e3539af1dfb68a3126287bf3af9707ba64bdd79d07b44b79289eefc3595a7d0686ee003d66985f1757d1937e9f13dd3af27df9119e1d71d793dce9ad5f564b885757837f9195fdab2a64e9f7c59d2f180076cac73df7db36b10d3a7556af2654987031db0f9dbf53b23c53edf9cce335d4f9d17cd5c730526c8ca4ca8459266421746be97251dbbc44ed772d57abbf85eefb93dd3e305da17e0c09335d20af56b19fabecebd36d2c25618738c34df9fcf719e4fb4cb0acc90154992244b44757cbe2ce9e82cec6cfffeafce31bbf610075132ef53e80eb56ef373759ee92b30415668f5978b0f49d23f89a82c499624557f4d408eacb8e6d525d2fc20c9acb0d246a3934fba196b6bf5b1ab2ee68da5ef8f907aa67f0e51f573a8480888a496884202635bfdac5f95d5b9ac145614be164042e1866dd7ea6f664ab3bbcb114867f3e6a4c7595b7d9ee9ef0a2cdece8eea78b5bf87733bdf8011f95e6e5a9b7315666faf3a16452e6cf7e1db309cda79959ee99a42f252f17d5953e7d05fa3ee5a534788b88f2e1bae58ba2cdfbdcd1d19626184b9c6292bfe87bd5dcf743aafc83fb3debea58b176fdfcec16cc052072f9d7a36fcf47eb079ace9d22546095ddb58de26e95717fa26dfa140542572874488dd30dffb153e776b8c2f7aa68ba84a7b0b62db9e91eef82ed49ac68f9ee9f99b74a8eb39107b657e8831a6d54157a7f64cff10f5c99decdcad7d0e4fe9d29b7c59bb163dd3698f1f165f19e3bf5c5dffc5707aa62449d28bd525cac247a4eeafb984d1b9d92894d2b3538ab7fbc3f5e5abafa2b6cc08ff8f8f0834b9081a85de05da4e7a587774368f32b6fbea762df6a196afeefade6e34e32d5d34601b6db3359825d653be47cff4ce73979ebf49910c58795dc36f57fcbfe37eed99dec9d5752f87662cf883876df0e1db22cd544ad83acee505da4f5a619bceef9ffac38be184d533bdf96b2a04a37b4b15208aea7c74d5e908800a2bb75397eb96b1e647aff34cbf2aaa01160ba1a3fbdd74eeddd4587ba67726ad364f37f1c69aee8cf586d0339dfaa456d71bb73bf7d93996727aa63ba12a998ebb69fdab9bfe2ddfea17fe65498ba77651527cf78b2e3ef44cbf40bb268936be5be795d061941acff74cd7a14b69779303d0be97f3d5aff3b1935537cf748f3512752a6acb96151f2b302b304356f22b71728f549ff1654967c8b3d7df778bd1e5da3ec3ec995e5d4feeb4bfa62a0beb66b1d2dc68e51a8156801c59598119b2d269f16549270be72e657b51cefaa874f95c4e97404d3e1fc9e2fbd74dec5ace7aafae927481b634df757babae784bd75ee3eaa2f44c5f8109b2f22198acd10acc90954e68ea88a84a4b575da2f71595e1cb924e15ad638daa4e070253389413909e504e2e0aec6072737e263a64741c0c38f770a4d0df91d175a4c80145143aa080e202fa3379728e27dc8acc643561819967d289c289ea89261c88ca93e3be49c799c8e844f92d1d15b000053a9d2726d07972411590800cf591a13e0f88000702a007f8575b020ee0342007039c588015c5260a1c500199fa4891808aba6ea7733d790b30e14e2080ee6b3481038046210378e73d9d4eb62690040a000501ac070cc0515405010150522ca1ef57100800050070bdcc03542c09a47814379c132811d078e7769ebc0458154060c9431b340fbaa114163db8803102b035a4a00d2d713042a55346f89cb729a41d52e488028a0b3cb16201279ae05480021390400420f000073480010bc0a180043081800318a0000418800096604c40b10463028a1579a30d04606bf0a28b1646892e524cd0185ba20e84609a4168e6a0c182e60a25f8a11252616309190c618cb9b00d09604002cf86049e9c0116f4288109be08c266048df5800765b0a045053cae8a4d3d385438ce139cd07f1ac78a2638a1ffc410a4c108452461093d701006184c09339281993200408819a90a8eca1a74604c650e292750794307949f30a6220738a00ce20deca7ab7a1537b4c1491a94e024032a6c5803632c8c261eab922c35a0c1984a1a984c68fa8caceb8c2b8ccdc536a22f587c00065506aa0a95227c2ea63e68b8aa2b624ce50c4b98a10c337f450b1853990219669e099413632a6a34cd98ca184054880c151730994214916b0a25f98ce19305507ee2b1ee57948fd044e56b02421654a632754487feb23e0bc654d21003634c2a0a480cc2c0189be9c1980a18bec0988a17bac0980a17b68004267f13c6b280852b6c40a007152b30a652052a3095294821743d305f51443e4f9492cf9df2a4471bf85893cc0fb1a1241774add11533a116d784854587a62b269f2e00ca4faab746d58b46485e18538902cb9388ba18538182ca1318d353c709ec7a02ca5ae8ff5012c65484a0d2041526c830813115345496a0a284eb33b26ef0f98c5ef427a1a2aaeac960210304949f9071860a12185339c21bd45086cd85cdc6c2664f81a9c4008c22a81061088c2161ec09e13ff8ea0f25f9dcff41bd3cb1fa33a2b278d07dc92f7a623f9f1110ea458792886e05237a621f08f5a0e97e7c505528c95551a21ffa4309f90fbe2f8ca904e1f31901d11f4a929fc81000e527d5e863e4132a32f3577c9a9bf92b548000e593d721f7547ea0428619b7003185b0401023859833984a0f18735a30a6c2831d30c6184341805580ce12e694e84e013a1a06ca4f9e128b6a31b5905a442da0164f0ba7856bf1d50bf9c0123e1004cb6d81862dbe80a94f0ff7a4531ce8cf9405632a3778c6546c5003fd453e1f32f47f68b08b7c3e2d9f4f0b632a63588ca988111a6dc65466f005632a61303db980f1d7573944f9604c450621eae53faf090b8b0702d0014930a61203f76020fd05d40570e6562df882b15012cbbd262c2cee356161714d58585e136a875c2c6a875c78847e088fd00f79d07d72893ce886ee75350feb7ab44be835880a59153559224b7fa62c7854915f4968b4b5747a55d7c88ca67a5cd5156997194df5e0c1c3bd2adc4b72e9a0a32aa8f3111dcd3c132847937b231e5a8040dfafa01cb9261d968ec8cac20e9b2cd490c5167270583afbab28b220c246577e25d6246ab126d1fd884093122c2c1827940f168447921eb0ce4fd50593840e63ac022d6c73640c6c73e40bb639128431d6002aa4a840dd1c696c830520d8068b25b04d9456fd996648d8dfaded8ab58b14cfed8fb037be1a377653664765738eb050427ff351a7afdefe8db0df2494f1377e7a5f8d9d115637ff3b1d8defedfaf422acab74e3bf98527729c68ab09a467c73db386fafd85b22ec86b7bea7dbf96d3e9d4b120c501061f1dbb7cadfcf219cd445234356e408e510f6b5fdef49e922c6ef74348485bbbe9c77d4afe5cef015e24d29618d113a74f2c5e9e0ccf9697698b697b7bac484b0f452badd73f5c93c1f66cff4ea2b4686ac482b3a1c84d555c37f72ef3adf7b924e4158f77b4ffc8e27a5133b0d84dd8fe2f7d41dfaaddaa37bc79f155000615dc23ca7d4f549b71d6749aa7fb0f1c936e97bb95dfd176bc79f80e207abeb9eb2fda35afb8e353b41e983d61e6fc477be973574d5258241e1c31ee29bf545877036e8cda1bfe9dac9d8f67618ee06dbbd287ab06dea889d431827745f6b1e6c960f7f6e583fd96083120fd655399fabcf61dddfda06e2f56549e709ca1d6c7daf46279f7a743a57d886fdf9f4bfe5a71b3b9c9b1d6c6bb8be1cf16e33ceebaf0e767f9b3ad628f7c652cbc9867df79bbaa86bc4f33637d78093521addf3369fcbe7a0cbaf9bd6e7d863c639df7a050a1d2c7e30361ab7cc34370c9b244912d54c01650e4dce5a9bc72725ac4fbebadf5feda673136af7b1032872b02efede58eb8b237ef8bf76bc39744a408983d5ee395f5c5d95d121fd8b522249d27c59d211a1c0c17afb17b337e7383e7cfa0d36df88a786f13df98e9d76c374281b74d8a484b5c6d6e4bb5a567ab3be3f73be75b7c16e77f3d6991da55043cf6cb06dded70fb1c6535377db1aecd595ee07e3d42e9b6b570d764b579d3b77e862f40de30c50d260b184b15db8f5cbafd04d499224daf168453458fcbc365cb1c30f7b7d7806db1ac5b83dedaee7e79a51cc60b1a6f7a95ff9d34dfa50868152060bb17b584297df750fff254992320a19ecbc32477f7ac2ec52ef7f99d07f3ed793a31af6debdb7c6f23508df431f83950ef3def5c9fb13e20ad3bc390b4a1a96d698f7e74bb79675ead6094d328f29758ea4cad0f4a91e245f9674288a18ec75ef4df9f4779c323e9430d8df9e677d38a7d68efa9b56a080c1d6aae36df735cf9462975fb0bfe3843736ea60cc8fa9674ea2db792f4b3a128a17ec7bdde884b8e9bca36bfed97103285db0f5bdfb18ce78df5528437d1e0a17ecde17fef33def7bf0bdea992e430dd982737142dadc7cae515a6b9cede55cf5ce3f3d53ddf0cbc8504344d48b24c9509ff8aa4b84a20537298475b62963756f90ce569bbcb9e2d89e7f75d0335dd4a1f26549a705250b166e8773d6ede8942e3f2c5818abbb784ffdaf4e78dd156c8d5a4e0a6fcb0dcfead20a36d2f93484ff784aa7b3ab428db23e176bac74b658a1d7e96accde34c513d6d62e15ec67773faf732fe25c698b60a04cc1bed44d4fec326ae920aeb50c1429d8f8ea7efffa395dff522c064a14ac9b4eeaa871751b5efa7c800205bb6996377a8b94ba863ac6f9b2a4e3417982f5f7bb5ff5ebb67caf66da91018a13ec3bd8aeae77dfabf57cd9d3a336c1d2ab73c3cfb76b90ba43cf746a39973e509810619cee39950eab8b9446aa67cc9756b827adda9f675a49926a44c3560c258e50c3e9dae3c34bb0336b5ab38c373625d85677943b6e095b7bd83e09764eaa21d5edeafcef9e3cc33e95f16186b73eaadf83936a5c808204eb6a8bdb9de7f66e361c256976dcf9cb92ce0cca11acfb94f0b62cb7dbb2ba68041ba3d718efdbb2491210508a60bfbe4c658c777ad59ea3ac44b018625873846efa75af710856d38d5b9dde5ecbb4d52d043b61bd10c7363d4257e50b82f556e17409e7fcafaf518050e16d0f6e9721843fb0ade918319cf4eb7ef78f6286757a77ce1be3bffa56977d601bf6ac33ddeeed86b3a63db04dd3adf1d40dbe79a3933cb0f5e64d279c0d3fc75aefafe00a4c10941d389d6e3af86295d4a7cb09a7862dc7f75aeefbb26acf7499093fbf46a2908b73f70aa50cbbb3dffa6a8b4fb6ac67d32e1dd781cd324a27bfd17f3fdf274a0e5cba6bd04527658befb953f8983649a1f47c9dcbd3331dc89115575da2a7040507d69f7c137fa5f061fc3a72484b8f22438248e940506e60b3ab6db6c772d62669d3d51d05f95c49a2b50b141b5857abc3a6b796f33a7ec16f9600a506f6e926e1fda6b59624a979c7b33581a04c020a193656a7ef5ef937d7173dd3c0babf7cf5abd5ef7679c2316cac2dd3a8779bd8abbc62d85767731b6a4d31c4b3350ea0ccc0c69bf7f597d06de7d0c130acfc2c71c553ea28b1dc0e0c08df7b95d2189bac8f5609676e4d62edaf6e7f1419d81a27aceeeafdb729ceb0c6c04a7ce9f6187196783eded4baa65b5df20c1418d877a57fd4144ab9df73974519711507282fb078e38bdf376def6d664dc9407181a5aff98c0def7c9fba7ceb7e7cd41aa0b4c0ea1b69c5faeeed9e9ed23dd3a91db266ae11499224da718af285adb746d89eebfd1e694575ae97814e67101416d81971ceae69bb8de68b618f151f2b2dd3f5f890ad05282bb01a6f8d5b8338dff96f6e1558cfbae1595b7e75d7aaa367c20c59b1a6c71f2829b0dba99bdb5dbfaf3d8e1405f6e24627ac94b6a861845eab172827b0d23dfacc7e31d63abe2d49f46549a7098a17b6b9df37678f0fbf8475d78ed300a50babe76fb8ebd31bd7a869f64c9732039a4ad8b7bdc128e1c35bbbbbe9824434d2ff43bf68a45fbf2268286175a33f1f95534b4863d33043de246cf577133be72ff3d4f985c6d048c252d7decf08efd3325f7c6186ac4c303491b0db63ddf8dded4ed74cab04030d24eccdb5c97ba9fcfb68bcfa1136cb58bdc2d8e06c4e296ca1ae90cba57184755bbb747aba87b33f293dd3affd9f4ee7aa28ab135d236cd5eebe89bd4937ab83b1f9555116648475d939beadd6dff1bd5b84adb2c1ab5d6dae23baa0e93315a58ab0f546dc689310c2fafc3ad10c8c24d50e2d439308fb3e25d6cff13f89f3db4a24a979c72722acce716b19bf5ea7ebbed29233976b3fd01cc2bed4b039fab9bd7377f820d10c8c24cd5c92d4f199cbe9406308ebf65fbde9cc2fd677f52e84d533e68c3fcffddc3f6342d888b5c4efb5fdce3d6239085beb751ddddc2f42f9f487da90ba2e90151f2ba24b44924417e49a0bc2d6f6efda9bb966fd506f178fa00984757f5d8e32620ab58b384640d88bb3deee5b7ef9dcc33f58b96fc6f9622cb7bef83dcff42b34793a1f82c98a31fac13a591f6e0e3b87d3d1996312347db08d3ea9a57e776ee7375f3ed8bba384f9ea5aa5ce0ddfd7ccd0ecc162d864ac3ace99af8bfb453d58b79da6b54d89b7abb079f31868f260ddbddc78cf17ab4b4863c48395ba55d8f0bf99a17cef833bd4159a5e4519a1ae908b24b51368ee60ff46df7a63f7dadcd81b7425d4a10f4d1bd66386f7bec732ef19a9d694e77a2293a825d28886c60ef65539dd673765d4f3c12895a0a9839d98fe8e6fce077d6b4c914812f42692e4de71e84d1e1bd6e5d86ad5f775d331b617e51a96ce2a5df3fbe24f389d337264a51d59f1b1d2b058313264c54a92247d44a0496a78a0a183fd8df3d6cddf7b0aa38e4c3e235cab22fbfe101f2b4a567cac5cb1e2634592aa67525dd0fe23afa91749922469ba6484660e565648e776f03d75d92af64c0751d5865f19912410550191a4cba11b412307ebda94b2dde8e8bb8d21ad2f4b3a1a1568e26061cb55bf7ef567bbfbe16029d454d20cdf95f2bebcdf60af7c5db77c9e5d75cf19aec004591151d50f491251956e1a37d89bf76eae4149e57db80d36632adfa5cfeaf46bf1b2c16e4d23dc2e7f9e75e737d76031a412de87ad6d6fd3dd33bdba541590fc22249294bf096dded19ca15183d579ba0863a412bba6b469d230a34b07a38cd4e78c3e9d378d2b8538faadd263fcad4183c50d537dfda7cb7ac2d07f3a54a8533dbfa672cc1dea67b0ae758c50ba6f714247a914a2a44e87be2ce970a131836d6e6a186b94fa62d774037264e55597e895c1e6b8e763ea669cd0694906fb307e14d6f99aabefdc55c3e2561d3619238ef7e5fb3e3fbd7c13aa32224972bad5713e09cd18ecc6f5797b74fbaecf697db56eb192a47f089a346cfc5b5dfcdda6ce1a7b6e4ec5607374da6074b44aece0969ee94cf215c12849d30b4d18ec6baf35eff972bfb7eb7ba6239195e4a10183c558bbbd6573f5df749f9ee95c7ce7ca710526c80a17f641138c0f49facf85479624d197259d91e60b75d6e9e073fea43f27db742d5618a76beeeaf7d7e47e764766fa7c5eba271a2fd897718e6fbbff4ce1bfd32b345146e0104d172c75744fddf6bd7eefa6ef99feba1df1519dbaaeaf2e6baa2a8c860b56fba3b24a3cfd9dd6fa79a67f46a0f719119124ba06cd16ec9ef941ec8e1f560d31f54c67e29c50a2a885460b16fbeb57e547af51e2a953716139499224284792244992343532d064c16aec9a7cee7cefa7ffa8673a75518f10cad1fbdca97a4bead064f29fabbf4935cad25f96743aa0c182a517c6e862c38f3e89efbb82bd4ed74865d6704feca07c59d2d942630589777d34ffbe53ff8b585305dbb0c6b0667c2f84f4c646052b67c3d99da3b07e8cb569a6603de356dfc50e7abc39cb9114ac84b06e077ffe0c3b48b983cdf35e3a238cdff4dc5b7aa6d3a8e4b2284f67125d6b8c9436ec8d70ca7777bbbea55bd12549923ecf5c9324499224f95899d97baa5e09911649f2b1e29e2449529e24a9e4935f4b92c822400b52ecd0a88c59e3bb3dd3aba9e33e6152ea60f39b18378a5bd478ef0da363a362c7d5ddd590e635ac6389aba34ef574173e6d410a1dec6e57ba7ea7b47aa657175d8109b2925b7cac54a1070139b23253c1b8f8b2a4938246ca1c6c73d7b3bfd32d4edd60f44c87374891839df94109b78cfadd8deea6c4c13629379e323f74bf31de70b0dfe474aaa5cbf23d0ce71b6c94543fbcdd7ced36f8a417296eb0bf37de185e59a7f37a771b2c9c517b7498278e373e6483ddb76977e7cb4f238c4e6ed59c4bca1aec76f2b1934ee97ef90d7aa653f72a52d4606bd37257ada77bcbb865e77aa4a4c166b775d6b5550a37a4fe32cfa513844a4183ddf27fdfec4e7d42bfd59fc1e68ba1aed7f17cb8357d9ee92ff39f4904cacf45201f461e1252cc60f19d13cb4cdfbf37df9c2ef76987281f3f2489da920463829432b43cdf6d774d1dc63547eb65494783821432d858ff6dfcdecf9ce77e77922402c91435ecf69cf77b74bf7734ee36065b5fad58ca48e1c3f73e9a868dff93e67befbc7262872962b05afafcafd76d1997a484c1d6862f748ec2ebe4ce1ace9802060b6fae19bf07a5a4f0ea27540f49d2ff84c26e7ee1b584d8bd08ebcceda9673a04418a17e8c7ede8d70d9b769fcfed486e87942e40a7b9fa7eeef2d6ee28a5254992669e50956877b4be9234dd0aa655575d22943aa470c1a593d8b9765b9ef39d674a1288aab624adc00459a1710e295bb8587adcef71e24da98e5ab0ad3de9d37da4fa41bcab67ba24b91da464e1a386f4fa7d2a9dacd36141c6dd60f62a6b7e7d85fde294ee4eb9ef74dc3cd357f41cad80268f253559c173b4d2a015a0d68f237c31be46a5ce9ee9d708d4f97c6ea6d788480848c422a50af645d78fde6ff95bfdb83dd3a37b0a156ca3534e59ab3fbc5752e7991e2d4af4e2dcdfcb920e929429449f703a6caecde9edc1f8a6cbd06d1ae7f629efbb5aa448c1ea9f4ed6ec4fe7745daf67fa8b82750e71d3514bba277c170a36c6cfde5ceea7ae3eaded09d62b6e533f8f314efad279a6cb10a438c1e61c77d37e9fa637eb1782c9729ed204fbb6d3747aa4feb03d779bc2042bbf51ad61adb76e77cd1d0d1b1de6b804ebedaf7ecff0b9ada3739fcff5f15e90a2049bf1eb58617dd16712a2d709a7cbeab2b9e79ca49c61e19377bbedaaf4ab6b7d2948b015bea9dbeb8b31cc2d7e4555d5a71cc1d22d75931352e7bae997be821423d81677832d4ba7637c72d32258a8ab96f1d5e6ad627c2111ecb7bd23add0f38b3466390aa50c81462adde3a7b9e297d14a11827c50c2592195d4ebf32825f45a5b8eaeb79e75d61904ab73ded5bd86bd3989bfa500c1bab6bfc6ff47f36cf06bca0f6cc62fbfe7f08e504e7d3dc50c38ab6baf52d76a6dad3638a1847753f897ba79e1c7ea03db5a93916637357d87ef7ba6531e293db0d5259c99c2fbdea3d39207b6e5475f6cee77dcfb6998b2032bf1d3b3c2791dfdd8fea59461a1db2deb9af1cb534eadc148d181750ecff9fe1c8ecec1a6afea1aa93248c98195f8ffe148a73fb8a5ab0e0716de3863ad1a53a8bded7b034b6b76dedaadb4fe76b8dac0be7e7862e7314ed8aabf1ad83df593b149f9cecd3c9d8c7bddc6efd5877ac64d039b5fdf0d33a5f81f53776b6c2963449fb0be37e574d249fafc4df8f7797bf3c514312c762af1de305289b5ce50cec0c629b1ceb9d53db56fbd619012868554c71731863fdd4138c1b050bf99fdd2ad21ae7a3b507ed2526460a3acfa1d958e3ec6b3c5cbfaeb0e01e5278d052931b011ee2631769bb638b5969204841418d887d251df4ec65869abfbbd175838a38bf7b96b3ce1762e4992f49a77fcf96b428a0b6c9e70defbd9b16e54cb2a4992e49a4812754d9c9b91d2021b5b7c0ffa6db46ae8365441ca17563a0a6f9c1f3f43f77d535860f7dcf5b6e81aad583fd5292bb0f8de7b7d6387ef6189af4b5181c5f475ccf5c9863d4f083bde454a0aec9bf8394ce77e5c67d328b095c28d5bbc38c7b837dc27b0b4eaaaa76becafa5dcd90b4bbfe29ff365ea974e7d53bab0bab6989de30c1bc4aeb94a5848e3733bc2ba299dda514ad8f6dfe8e74b33a5726bf8ea359a84cd17b7f9343b17f7de5b5b496ac10d4958df4e57092786b5662775246c8e34d256ddc52dd3e8141214beea5e95d5fdcd1aa9d388e5d4cee59cf95b8cf73dc2d60a5ba474d288dbf3fc92249d23ac94b335979b6ed335f86823ec7dd1f37b0e697c35436784c5994e8de957ad3dd33b33b8d364d2d17bdc588475705ebdb3bbede44f473dd3afa97aab53519f997b75a20bed4e471196b64b65acf8fd4d848d5fabacb5ee0769830f23c246a861bd58df0bdb75181fc2d2f6e0efb6e3ccb0ca070d115d95b0396dee39e7b3d2eade863f5dddee6decfbbd10b6c196f56e75e64b08eb627691ea26e7c337e134c18d41d8a91bdd524a7ae7fd3c2b1041d87f92cefaa0bf8db7cbec2bb811089ba9dcae3d381fc377f812206c9e77e2e9f4ad735fdcae244952ed38bdc18d3f58b72f6cf3522add0d3f58e74dbfec74c44ee7199df6c1e687f1db5efdea5d2bad7cb0cee17d387594f2d6e96d0f56d6d72a9eb2bab99d8e520f16b65a1b94ef9ee7e74e5a37f260ebccd0e56c72bff67a3e1e6c9539bf1ca9d3b1b536e51d2cc6174efd52d2886186af0ddb1e8d7753a9df84f96a9776b07b4ef9eeb50dbdeef7eb993e733faf231537ea60e7744ddfabf59e51d2a83dd3eb37a9463ee2cdc00d36ac9ece497c5f94ffe6c4bf8695eee78db55d9ae3cd35d2c1e246dd3dc2572fae2dba3958e7323b9cde9a5f791b96836d35c2e9393a775d377c6fc4c1cee7746eb3d557f18bd16fc0c1ea396f86546eecde63279d4619dc78839d6def1d77fe2d659e53df708395946ee820761e9f74fbb5c1c2e7b9b9d72a1bc5cfdf0d36d808efdfeb33ea776fad8f0837d660db7dfcf8c5f81252ea1c1de3861a2c7e39ab74beb3fc0bef96a4daf18ebb9106fb26a5ede2ed3acf4a9b43839bb5b9da28ac4e4ed93c46f748b7f6c754d38af78efa0cd65fae78cbf7efebc78a9970c30c967eae97eaa8759418ff96244992a4da71f75906bbafcef7e5bcb061b7b52683a5fbdf761f5b93bbbad8d4b01bd7fa26a6b7652a9bdc63b09246985f6eeecafaf3b634ee9571d6e9ea6dbbfeab6278de7cba39278ccddd94d5bdbae384d8f79692bafd37c260718dfb5df48a5fa4504f305898e73f9cf3a3bedd9cee0b76df77d5a33bafcf6bf41b5eb091b6975a66da72d50ebf1b5db02fe69739eb27b7d6aebd1b5c90deaaacb2c629a96b2fc249a3638f5a468df1fbf9e28d2d5888ebbc15c32c37a4fe9e0a6e68c1d20c5f6aeaad6687299e59b0dadd3c73ad2feaafb3b91b58b0f9c61bf3beb2bd2b9fd6f4c615acde57c3f9748ef5c1989b15eca492d6d63ce7b6e9c4efb95105aba33fe759cf3831cc17afc004f93173bd2ce95437a860e1db6ed388b76bf1edb8a760ab86f3bfea7dfdc29782fd37bfd6a9e794adca1d05abf37fc453ee1963c4170a563fa7b5ccaee6f7d2d127583875fe1bf3bbecaa7682cdb256fab7c12c9b9c4db010cb0cbf6e47378d4d32c1ba19e5f307a996b565f768d877ad52f85b6378e7747a09366ad97ccf0a6bfea795609f83aee9e6a4cc3edfe72458a775c296a5bfdcda7bf80cebda5f6b95c29763dd8f04bbdbddade926bf69baf5116cd415c7eceef5fcfdf11ac1c28af37de7e43b5c1d17c142bfd25d877f43183d5622d8bff0fdbe7e8feb747a0ec1c2bbb3ab7052f7995e298560dfbcdbc1765fdbdbbd0f82bdf349bae9dd71bbfc40b097eacfb7c147b57cf8c51f58aadde559a76eb945bfd00c2b6fa5fbdd86d851edf8f9c0423aefcc7246a877a5b707f6e1ed1ed6fb23d6d2511e583ce97e7acb99378e74eec04a4cf7d4317ed30e7a7465d88c778d9ef36ed255ea5c07f6ba1aa1c7e8247df0e11cd89fb5392adb7bd9a5531cd8a99d467c639cf7d6175b096edcc0c6166b9eda69df57c76d032b6bae10e73775854ec31a58fc3abb5b699e0fd3e7645899e76dfbffe77dedb54d03eb1ac6b1c928316d4ebe1ec366d77c36ecf2fbb765cc62581ae57450c2ea1f1f3f3c03eb5c7defe93c356efaff8661a5ce3037fdb9563a271876d3483dbbf84e7e83b9cac0de989fd3d2b5eaf4e318035b63a5eea8cf786f7d8dc2c0fee787317b6d335e89e70becfedbb0c718dd731fa70bec8375467f77594e59630b2cf4bf384afaeaa4983ef985dd124aac277cdabd5c290b6c84f2ee776fd6bf7bcb15d888a99b0e63778d2f842ab0573f87fa418d65c3db630aecbbf7e618a3d30e3a5c5160e56becb1d61d7deb4c4f603d3a9cf2cdfd1c74ef7961bfbea6dde7831043e76e74615f6e504fbc5dbae7708395b02e23f6ed5fb7a41b6b4ad84b9d8357435cb196314fc2de485bcc7fdf6c7ae3f6246131940ea3ce38ba7ddd47c24689779e309eafa8f431a9859116a390310000009c981b007312003038241c8d05a3d18054b08ceb031400034e7e62aa4e3c18c963c124c7511044318c410618420021c600820c54383702793513a7c91280b511ad6d9522735c2a27fb90867409efcc57c540f375e0df93c56a4aa99b00f0b687cf290c6430a2c704aa3713da25c89357278fe7aeb8ae9831238410c75c8156fb3c0aeb32f7272093abc6ffd74562a6b1f62a2d66c855d36359165dc2bfbb1d3448f276fde3125139830313506d8b4858696eef3ec9130110aec8d2f4598463dc699a0484b7d2ac7e029f2da19398ccfd9ec5bcc6d76f7f76200eee0489a088b9365e455de0523f88925cd55faa1318fa2080be3dc0800640606e4986d574e0d20c65483a7f9d834ad9f82fc1755e186ecea81f4ec956c6a16ca63c983909a3c5785038f4517bd0eabce68274c0ed259d38b641179a77ea3a8f5c575de2402aa5f4ca0821f7404aa342ccca0685a32e7851aa47ee15a5ef917434fe4a0e1cc7926e52a154f11e639645053d2210db98da3041a373196d1cb787b14092e5ad5d14b767377b1b211f649a3282f60f27a4f066abc76a400abe786a6f05a5f69b1078d6b235ec9a03cb42483835160b5102533cfb5553b55090a90f4120246fb80868356dcbfe4fe9284069e3c54af047d54085465254f8d745299a9faf708cc33ff2d9f53a887160412750c28afc215e41ac7ae23ea32922002e1c4d81f58e14804efb764d6448b4f709be151de2d7563f715bc62c04c0582c56072f720e96770ccf051f3952080c60ac05e67c2b75d1829ae8c6dcd9744da0434cc3c54824af50d409b510196c0f9fd95e776178473d06f990e10d40c824e905316cb4582d439cd19012e60e75788d83239936be6c6493b5b3247dfa9e84d4f8ea8750b0d166d3b4bb4433f091e54b64f8d3c2d7a24e8a2118b20c8cdd7b109e3a9b3bd1e18f3f3c262278dfc5aaa71379f7b7a5cd50b25dc86233b515ccc85a0c371a7d4bf760e9872a0c36582aadaff6ec64ff6d93c1065c8a08e35b8c4100fcdba2f7cbfdfa898019fa1bbf62a15fc1a9281bf1450d7b634cb1f4ee5338e7db74bea9d551f5dd58f9487ed6dd329ca2e63853c5ba40247885a8b56e7ec513de484e2f4e4b8a36b58f2e53c91aa2485244342e87685b102a77048e605202f7a226b1ec97b1ee41e2b0a6925055cbcb0aad792f9b12aa802ad172a6b900cb17508a031dd99399d219f2cd6e609d9b9d902d970907a2ca25ec65cdc9df384c1376cdfe783be9fae93bed866a6c498ec4302f684e3b66a1a5a30ab709a72fbc6d35959bca8655ca6e4270cfd6dc7402b81e23531ca8925b869d6397cbd7f14d4c4aa6f6e6616017f45ef52fcfff988d5f6fcd68e00c4c93b88741f012db69f1c72f655f1a4e3bc14101016e0f3a653eef6ab5a23fccd4f8782f126c87b36222b94af66af6cfbcc0f813f5048447503c6428de763159bb58d1ab927a01f75338954a2f68efdc1b16a3c3787721416ae4a1b676598191c29d5b160bf1e243d16affe6b0cfb5d154ecccc1a43a857c0876cfdd497acd49ee672d57f166a2675091235ff8f6b720734cb7321ab7a3f1d2162b4857af567f3916151cc5aec76886e284bf0a471cfe129dd6659ccee403eb5854d19932322edc84b6094050f0bd35ad0c498139a16496a11f738f1b235220028fd169f4b6d6354c9c10dedd3d8d50f1605c91f48d2de10b6968c9ee5f86566b694051855b234b5c69e25f8abf930864a48e39226f312ebafbad0446fcf0f02b719a89081974f24d65eaaae7baef2914ec544dd9562f59b4102da6f4a4a0e0e34cbd7c79a8682b6582df639b14947f795f5321e3cebfcc765bbc4f5bfb1580953458ad428071dad0ffc7c5bd079134fdd3e49618450e50f7b263e0029dab5fd56d5b9a923623fb5c52024e9b0971e35a5229009a948ef4f0a3429838b5b80ee476689e07b23131a5c25067dfb62f971535bdbcc452b63cc9b5399fe475f93a12a17b9a4cdb0c131155044f5c42159b76fa99541f80b9f6a00b0f3defdf3a69abf1130be6fc6590a531e2ec6d8445dda86ca3dbabc958f62cc0890846dc3219e6b0fd0e7364bc45f3f2596aa799cdafd59081485482ce9704172900e0904f5066d2d43f1e4b0681df5dea48a39fd636747e06ead356548cf52c385109ea9419dac9e3921ef7b4034ef9aef5bd59795f48b63db86d615a12aba3051f9bdecbe1905f4f743cd2a5d84f5cc562b70bf037623d719bda0e98e96420c13509c40cafc9c81d2a1beb8d8a682b2f07cf11a1c4f26ee88492a4efd6f0e138a9d73617a1e60257e5a3f8a175d85f3cd7585b0aa8fe50ded5bd36096b4aefb2df450a5e9d814da5878d0849ecf35fc246cde79196be9053da8379dbeea9644f0ac0f9b16ffa9ee264f56893e46a38d0f3ab792142ac01c09800b0b02de543031d6329132bb9db4e465a73cd6a0e93270a7a9413b87103a4f8121d9aa1de54813ccd3a39b0912453e244b31a13361d6012472ac43c5f1f5d7d77dd0c3cd246d4d507843353e0e2ed44467ac0aa659702e9795bc23dd2920e4865af9652899f80c38d77da4aa6cd1cc0a52493e73b4b311f0f694e63e71d7d22c04d8d27948142a758eab8e285741978573f782cd1f35cc3b2be4d3b1cf5dd6219f7d927893f83b5b6f9983636d9ca34d1a8c47cd03722701419ace2de470bfc31d4cbd09c3c1f83569c66805b74577c5ae85451b3d2460be611f7a32d8a1a064ab0722ef688ebc402795973692c48925842fb8cea03eefcc7a24b38f87156cfa68f75210cbd99174b8b0e2cf728e2a342fc30ab83d3076b44c97e78afd4b366d3a2920f95e4a0d2ab9d73c93c39ddee2e53f6e62d849a3cb9d7591663e2a6bc7b83e2aa90dd88f5fde5b9cd7861041d17e8fc4cb5a6eb99241ef2e0408e9475b92f4d918bc370db807fe88e2ad34c1cbf2bdddc629761222d2b629a5bb70bdf30ea19f46a7b9da61a3007749374d4cef4937666ee8328b7a7dfb5801d4434ea57c3d44703b47b6a65d1e94c0055c10720aa1f5cad919df032d1a81e20d2d3da024febe8ceb87850832c3531d32c1e4524ce0810ae93a1f7e66b171b66b48c69ce96c0e734b6334d6f7f74a15ec7a7b8fbcdfc8164fe1c01b089c41eed818d025d410edda7fed860c3a129bd86b34a7a7309da8be3cf0814d8f9913591dbbbd1186516ac455da3fb0fbbef2cdcae681a784cc447c654ea1e1c71e1c24ba02f8ee1e3d0ae776e8ebeeaa9d9ccbc62d04266e317b87f9c789573871b3b07970b2525a943f1346c5811125ee30b3ff98430c545e914f8783b0105a6f371065e58c858e0c175544ff7e47ba0431b303f85627f63a0c76e2e68e3aadb7e6b3469932b7aecec02ad15c676e330d29d3bda62ba56d69566f36db4683f1b7a687437f6d5c6bcf7ac344833ba73b916dbca62bcadecb466136d6e7587e6d5c6baf76c346863e8ae11ee466ba3ca3bf271b3e37507661953384cf331b1c6741647ee1d2b5b659cb6fc49ab2745d6bcefc394f72a0e74f6bbabd6367652dccdbb3c9e38d0d5efe5daaa58cd6d3746d9afe3c6d3075deb6e66ad6ad7367952c49977fe3045d79bac26db67f107d70ccc4a28100e796de497ca0bb45f1a5add4c8449c737e49a5c80d4cc953a4eecffa4f2a0e987d98cc1600e26d015d22da4f5e3dacbd6fd4988d0f21d5eb8f1e2930e34f12405da45c889e441887416708c2a9d9960dc04948fcd2d05e3dd0d5930366d89a7b946463902005062ef18024557ff428d5ae50b26a0859aeee721810bfdf7118366747db528f63b64987663661e4acfef73748d955d5748581aa49f5e6dc4e440a8c2cea011909ae288396dd4d73124d34fe8ea10658a84a648c17390fdad525eeb71958a289fec1632d286704f91e99b42f17921ffccf887ff96ceae4de398e6077d18c285bdc70889613da721eafbb940f3b2a3a3f2cb8d0708a607db79a6f530b8055d8c2c94ea47d3666ddc3545568bea9f7ca609f0e19c29d51502a00a9803105d98d6c2a9aee04c7327499e9d344333b4f8a6d0e641f1ba3d7235b12c6b231aa699208001809f0299f019051e78dfc9079670099cab082d2245dda47e132701f1c4753a61b5485f2a740b65666507854fc5558941f582719ba5237dfe2c277b2551430f9b16890d596d23e2a4b4115d7b896ededcaa75991d178485f7f352cb99a0df0d80b9e25c4cfa016861053ced9048b757473f1af2f14c1bcd500af1d9dc59846552cb2320dc91e715d5190c03da1794d7965954fa157e453fb7f64e5522eb9f19bd8a2ea3573f1a437d58ccc43d5391b45b59ae3e89ea75bfc89cbcd995a5d38dd35d39ab3a0155c6bc0bfddf1209401e23aaf9728ce6d5d9d8382461a856852153602d6eda42c9fea3acb4bff512922c85c9aa0a009b2accc7d3231746c6bb179a8f2749071e2712c8402205b16dcfb2c4aeb40f186d0c608945f20f84fccf11ea4707040f5c37d25098a0870c45eb51f73d3d9d9d26472b9532ddf5851f055b2ec657ef597d38791431009fd343d4ba98f5259a659a24d588f99703d858befc39cc1c9077a0120b01c4028be575683c543c272f2a0423fb21270be2ad87020bbf5b436f638db3c28561f3a9a2b773afe6395ec3307b5ba647af7ad57351593a5b8d9012099acf38b4d4601fa16f87d335e90f29b61f82969189fa99e18645954e0905bc3bf8ffa4d32b781ae41e3b4198ba0819a1d393a85e05c98a6fd56185be131e01a2775afe6a7d76717381f88018ed8307d435f916b502209fc7268e438f65ff6551b569ab54b6b6312e59aaf670f971c11a065e26bcbcfd5d610b1326f353477900780028153d277b09fac131bd8343531d40b8b73ec074943065d27aed712e44a850f8bdb3d34b3d1018b56071a2686403a66f00abd25a711e687393034e29b502f8347ab3888258d436086b512a12be70b13346633679607626d0f953c39fc847d4c0c0c3543b0c3289b5fe5a70381e2ce6b728a38fae2a81b63c4133a6ad518a8e0f1d7ac9701612144cb4bf2e30467f9468056ef7e2abfaccdecc6a4c7e5c58fedde0b7223729bf79cb0d27979ad06012786d9366303bf430a439c558f4d53fdb9593da1e6350210e4685fa88cd547207548de6b6e20f6f0c4ac1f614e754499fe95d198725e73e180b158cb6c457ab65c578b94fb2971903bf7d602e6959f0289f2420c652728d8db4111bc541407e74c86595e14806ec684235d524ead9a8fde34ffe0c324f547de9970c6f8bfc71a6119b33dd14d155f2a4b5bc3bd0c3e9f0a90ab707083804c08edf6c1460c5778efb31d3d637529022553b1818be6b6bca62a8f351d81500fd33e003299f4a6e06cb81489d1edc68a4e164385c852a8ca44a14659d0f9dff71266cb0bb2e734f62968853a0b02504c22aa22e29bda8815c19e462181223edfbb554fec8c949f3ee6a22de385a9f13a93e1563d987cc90937662027cbc9519006e46f3cc330815f415655a4b6de936183917a778485d36abd1b639de4cfa8876c6d7635fd3f682bec27a74d39feb2ea2ee81a2362cd536265c6092cae4261f166d68eac46cf260f21a60ab5b32626bea08a8104b9ffb6ae61fca23d28d3edc1df0f38f513863cb3618ffef3944090c6da5e3d5662c090426649094612acc4d203207ddd9e2896f0170d5aee8a8e2110d7d4700e0bf354cd351089ddc4c466291601ae76683342d5f99e101d01077b0efc1d612f51f60bbe247c09fd3369f4352ed134f0837c7b913e58d41ea81de4131b2fca2072dc09465d8cf5cb05d913ac01e55ff5df6095b4d5c0da916cdaadc3c8a04f08147ad6d21016fc65013fea71612f66a845f6ba7bc2062fcab7373ac96a311ec9eca95bf76022548c6c5bd64e8246bd5be4e6954d8fff0ca8ad0318e95f1a054b92ef4b7448f96a10c0593e8c424d500fbe63bf06ba96f7dd86ca6d30d9b58996c034dde42d1f72a76d0bc313ab81496eaa656b27b3ada7003e0ef06183490627554f4c4ad4aec9480626570a321b0d26d00a8c3420123b9c64696ca95ffe1c429db52f09c07963807d3cb3950007405a75019681fb8855649cefed86225b02e805635cad7ff005548bd26c574c57f368635f606431ccdb6da59575d7753980e56e6fdaa68dfe228310d437d847ad119668c15b05d5e4b3072b125692b37dfdc604a9b060168944d6abec8220ab9f474626530f35f436cccb85d7c539b1507bb7504dabf68d916253588760bcdfe603c2bd208f429550934bced60889c119b7519ad602f42fead85a7e10923aeab41582bf2ea4347a91902b90204c94dfb1d9f9cbe25e1a5ef06aa0495f3ceac8b828ad2163ddb248f6dab047cdbd01c26ac4726e9301ed20aa80617fc5855c6821044bf2805f0fd932bc6ea9494d85007fe273cb38b36742a34b719b13d7d2a714ac073962786b319d10f9ff6877eac0b36517bbce71477b1bd6e6db658206a2573e0d2473dd5904f9847cb3166d74c3ad13ad19b36a337ddcc4817a1797f88e82c2abab80331188e2c2a9f3e9289fc88964276ddc97ea8704564fa7fee0a1b1230c3292c5f38ba4d0f065d1b898bc8bbd7300fe641b46e902240545e3f923d54583f25a2bfad1a5ce4d122ebd3bc013eb277b77d28f134dea958739a46dfc16c70870dcc0cb3b5b5873312378e0dbaffdb04a823ac499a1ab6200e82633a55488a07b6355834c7551a6352cbdcfa846689decfc447bcc6d7498ceaecf89bc452d3f6bd3c5ec97862ddf43b1460c6ec6fe3fb7828590f6386058883da9d6deba3d947be3d3955570f24e01dd4b0d0833401bbddc1bc70cef5a0ad44d5b51a925504053a6dd01781f91df85f35d8ee4c4bdf70a6ffd68202277ad18bca07a7ccce43b6fc542020d34ad20f02e6cb6af6dd370d8edc5de04d77faa771aa0416c226ad561396d67fb5d63d35aa1e0614dd2a78a0cdbc34144a925cd383b7eae179a40518540fdeb95351814482209c1838780f8ae1422cfb04524e1e0924cb03262875f9fab569c8eaf45a15605dde2b0a77e3651cdc238a314dff4aa6ea8b218ce4b3b32cbe05b967a052c7761ecaf9d04c9e6e35e5ee3969c4a17da77c9a46656122286a1ebc851274586613c385c886b3c80d3700afa7fd2d04fc647a896b7a38465ed98672de9ae674e5264f1ffb534bb5cf069e0e64154f1ecb5b9de158d0a1119b63b0e4ba071e637a942cab89c9202e068b3e0da06851dc2c631f59707963ac6e1f9dff8de90691244371b246f9c9df2dde81d6e620fe11469720e8d23bd48dce150cbcacf14f03be4849c8a605374a18d6e26ea9ce9919d4c04baad165ce00a55552eb526cacc80c9097a96a886866d7cacdc5d67abf308b543896543f5f7050199cc6aa81944115dbac64e3f36e15cfad801e37b9fef4edde1ede15d5925ec8c1db9d7e4209642a9365805b4e40f146709e1a07020a805a2ad75790d1094d246a980326fc0ad6ce19ea6a5a2e9abd46d2a62b861a07febe277820599d470293ce30b895636280443c7c2a330e0b75c0207aa3479a12c393cb01c9898a17344675e299ad7ad3b1c518d0bc8bc9ded1de1afcb31b05ac9dbefadd5f82e23320d728da96bd8fb878e956decf6488e83414128b10d353f0c83078d32f99da710f3937fd8523b935d3e7f93006a8f3c620c6cc87b254b656cd95988142ad89e253c319d417aea2df56b1c4dcb20dd046b19be8cd722ad48fbc47beac459501bc01b0547c1eb3c0c9124799ea35cdf41a304147808ddf5e3bd92d51f3fcf3a9634cb8beebd712eb05c6cc58422dcba67d0c7cf9eb49c6f6794ae7d841e469ed1f96cea13e0c13820941c9a6319bb991853aa62259d7e7f7c0a4e149117fe7c37410178558420ba01b622504a3242742e6f96e6247896de25624b0cd24e45f90b608580c79b4381e3e459315929574b707b88cb9025ac4494d54c23f69e00d43b16bd1b7fad16c8bc725d92010bfb75bd9c02952f1d67d8de2e45023b31a72ee4fcfa1e3bc2f6a4b7ac04cb2b4db983d44e50f1f37d48834b8432f79e543c29cc1b743f679b37c76b08340e7b98771fe3e1923e871b761747c6af30fd289a59c559ddb490407121ca5d1c64a73fcf85ec115748dbebabd072c01301723b0090b0227f9ffe63835d851742092c8cba1550b7c9d6b0604bcc5f0e24560c33b1ae10d03238d2752babd8baf89ba70ee978cfffb0bd1bf8efb265357487ba1272cc8902329ed88a6b234e22dec346d240dc08517bd44d663b407e8669245a25d8a4b25f8a73cc6e792bd1120b5956080ec508a180d55562660836299d460eac87968bbe258ac7a59720951b8a919562e7e20b09cc693bb45d41eec1f4f5410a5ce80a60c692b302bf829582a553e7e13f548809335e9d34a6ea3dbfc2af295099e28987fafb9447af65cac9c64cfde2f840bb5719592200cb648846eca88f045480afeef76d32e12b314cc76e058e77a24811972b05de1a2d41848b5166451c2410ca5767aec0bea4f5b334db61344d4f87b3390ed355e98102ad5c76321300456f9358c251d5341d1c36755774c36a8746aa7b7863ad13bc00d59bb33ffc24825cf6054c702ef2b2e34239532e23c349ab70b492331f13cd32a4df0ae95641e5ad5c021dceca41a517b4cc87e71f11fc9d285a7c957123547746ea78f86a00094ba4f62f3fd8841085fa4f716611c6f016674db065de55aa15a9ebec6ed1a704f7bcfc0fc57fb146ed0563040d4d037b77022c5135392246584c204bacb313ddad640a767a77b82b21fb721c0b5a8a5c8cc094269ea351058975613d4c268b147086a8025281b1b165c6e01e85fea5d8781ec8e9023a204ded0beeccdd228a2073e15a1c023be9f568193aae64aa41ee31952845ebfc6283d0f5fd0e7130243ad3d5f0f0553a062583caea3729e70e5f2891c100bbf7c7c8da64252f6a7b48b4164301abb8a984b617de792f9ed9a69033cc5490b00708e288bb402d43692ce15b1a13b22e2912b91667240808c872d2d111e4a1d2aeb5118739e5a9449d9156d871c4f50f6b33092e558145bf4a19d4e8078709d75a7f88bdd9981947f89597d5d158a81dcb265e13b3328c14d820490a6b2fd1c733ce08cbf501b12a02a0f54eca8263409966759c364690d83baa2438f1a00f24f203db8a50d7ceb1900d6161061052eba5fbaf56a8560ea377b8331fbb64d9e77c0ca4c1f22a8827a65d33d48d28408b7e26c4fc885ff6856c224c334612f51eb0ff45c056fb776bfbcb5a5e0d4fbca4fa046e0d1f7d4ecd29d281a3493c7dd24421ace52a4abfee7100676437ab565794a5ce713a6e92044937dd3dcfa39782b689b004173414bcf67b722146e3390c334ae26d699014a7362040930b9350702cde3265ca77ee9798f2bd9f696555476205dcf8533a8faebb0c04c90554cde7529e232e56cce0724147497729e8363d28aba4e9bc5d96189c52ed2cde3f4b0542177a9a7e6ea9c3072027a303d832cdfb61079f849d2351fd71a46b7e7c75f6b8caa93ba0eb9dbf76f1b96bd3383f60d90bd039fbe7fcb6f8c0cc4c5ae35e1f7b2e4cd3b35cc9ccf9cb96ca4788a33fafb1a45b95620f1686ecce9301f9de7126a8b03782e8f356d7e2df1a1ecf5aebe45d740f6b79cdb565e8e64a10284fbb2e41d958945a585791227e83b6f1161f62f0e049c9d702fcec3cecafa074aee256d07e04b196e376905cb474ded3191330a2c5d3ceca6a1eefd05729d294edac1fbdeb367b326d970596357f5b21ea5c0838334da66fef77ae6be61bf37def4846efed2f4abf51bfa498c65ed13e87c4ef3efd806c00916c66f00c08f87d907ebcc1f6eee6b9424ff8ed9334f3692387bd3a1ca22b1b0bb8c1f9af5113bf22a90bfa69021195b4f729dfb82ab856060ce321270af04dfa71619067c08a9a18f28dfcf10a9ccdc783beff6d801eaf741589f579bca49e030a5d3ee9ae809c7f0a76408eee03df83c998fa517d05322df3235a7cd6f739e16ab52687f02e83e06a4d1c1ff75a00e7a901303bbe751375137c7752560c48960cde80b3aa3492f295c9fc0b4dc98451f9650047cb54195b2c72166c33a1dffb185427e46d9e10cfe675341b8e36f9eefc29a792688211de6d6e10765435a801eacd3fc4684edf4d08ce9a38998ed3ba8669caa0376314143c08d8f682c66d464e54ea26b232caa6b1f71db09197e558c2b4b076fce8ad7e3104a3e37164c38119939616c4e400ebfcd75e0667a39aad2bb67fed0590301278eb95f285640c00706f503fa3aa3fde4c6ee4e487c7869122433fe3e12a58deb7fcaafc621ff22149314114d22466dd3f3a18ea38dc955392a140dcbe0a41cb0c07343589debe9717ebb61879450d9f6bcb5193bdbbf829ce737b3e2f77182fc5336d91a32c89bfb0f7313ef582c023353794461b6c0c599ca23e8b92624f53f9f5207c8208ff1af3e2d2e0d69754033fcc734ed20258fdad9241d76dfb498de17e8f4b19840dec658d354dc90379fc6f4b7f7053cb777879c5952c7763f2bd844f51cec05d1a8d8ff99048e42c71850316c7a14c23b265b7d0424db4bfb0304a0ae25244930886f36b304a66d68dfdd2421a4e566f4dbd4aa151b9a432d511ef1f08ab4f879b5e09217dcebc5fa6b188796e0c121eb6379145d07d2a4ec54318b515e5854f4423eeeec39a4685b754fbab2139816a0123d5cd22bd2dfeb0369060903937d0d6c0e5a9d169899f8c4b261aea3bbbac96f5e10f063dd9f2e245dea01d6eae6482d43c570e65fc53c3b7b42290e31cf30f8f520069d2ba0b146b5cb28dce0b514668a16f7dce4c24e6895b776e483a85f6f72b9183e9ea9974abb080f7fc2c19ee77fbd3936eaeccec1bacde75df40af69a71344d579ad8a84d14e8c00f8d832a7beb24672030fc2cb4b26e21a191604b398e6bfcfa33d471f240ceb27316017b31cc4394b25ad471e24eca4c394858b450d0d5ead804d9d8e50d2a3089c2fa751eea7d9157bc110098dfb1b9ff8e3084d0990a9baae0f28e87354ea0e4ccb10144926b8bf4ff0baa6768300af34900c8f3b782c76c22e4f64b1cd5a79c94c8b9a4c79873c6ee11f2c4e666debbff5acbc34b8d121ec2c363a1614cf3631f4ce2efbaa094446650a428fe5f6272b8256cb2fb2a36ebd612d34844eeddc5fe4815739bd72330a71640f62080cc08faa9c6886edcfe68971e7acdfd26074943b77dfb7b08c9ea5ffe3e1e147b7481770228dfbb042dc3cb995a29c773da4b7965c29caf050ffc4065017f92b0f4a72d6fc0cc7f2255806d7ce6f7390f93526709b23972a57aa569f635bb8ad1bfce84abc5b9001c8c30eedecbaba9b2fa034e07005297fd1377445a66cd93a31a2caa068073eabdb32461a9e3cad949bb15ddde5d8025bef1ccde57ba0671eb284db6dc3e6866007483a2c87ea286d610860bd42e335678d22b01f8cd451e110a5708cd3fbfa2d0608ee647fcf75a607b851ab7a735107ebc8c7ee739a50033612a34f0f183ce7e1ad4fe7a13e236ee5fdcc7273a32c44cdd70bfd80d697c241583275c28f6f3f001f9be8a7ff3a68c01ef29e7333fb1ae435a1bb4d7daaf570ecc7521a28d21c2bcfda89e9c630f2fcb8dbdec4eb120d814ab4cdada240d252303a2adda42b927ef64b1bfc1a71c6c89bab1b1b770b13ccde68d867b09b4916a30b04ec96fcedd8c5ce3fb8a51f7f3527cdb6eb96c9b0c43f51968656c18b5bad57b2debbad2ed732eb704087a3b830b798d0ce480807b6e00a5e9b35d76ec55bf2d9b985eb2d37d9f72dec506f95ceb5d0cc38a25a258c86b735fe3759e1ef1c22189295f53a610dba88238259e30a213d4306d93ba8131c03ee6cd51f58b8c14218ea0ac9f6d161ad936471d1f20c3be10587a34443570541b9b010dd04592d5ca196e10d46611e37caa3e841372f03b9452dd3e31fdeea79cd1b1d47b67041fc450dd99355144dd46cdada8ce484a0fb1c3e69f97ed7664be60a8a854d7fb381ba20bbadb2cfa7e19c28b022ec02e4d673fe1e00c0abd7c53d5fc9d8fa86ba56406ed8428a8590ae2a96cc6841cc1718b9cad47a5f190dbfe1fc0125198151e99d955b065833bd68650e86d951b141b28c08851a23ccf2898f88a09a0d4d03995de5e97a0ebdc5ab0ba8ba1102967924b10a78a977919a3cef5511d88eeea965a68fad121fe764ae223c6c7bbf7080493fa00d9f86c36a617b82d5e0630e249c403bb99134649a74f495e66bbc9955a7a27146e751283c73167f5c8c9061d06fcbe1d276a1958157f1b7af1363764516ae090c2f42d65c0d79888163094bce8e88145f23c987c944169623dc8ba86f10ffd053a4f969dd33dc4f12454bcd1d8080e54260499db40c4d04545d119f989a40fddf7a65d3527227901d4a24da809aad9c6a20f17014c6ac92c942b9c700e494253f12175a9e2e44eb5a836699efed6a3ed9a07cdcd2cf037545a4806853016bdc27c4916cdd7be912242328954bba8f909259e4267f4030037659e05085e6d996620e5782c7a4e663e635afcee0487668040ba91fc8ae19d8469110fea340a8a7a01df41dd594e3dbf008c1e8fc54b3e27ae0d5d3b035c1e9a7b4d5a9632fe153a3829ee267e3169f519dd60f0e259ec59b2c2f7d0b5292b726d4ed0e962da5b257f33f18d49adcfea068d1fcb6ad79011ba9fae0d0e3d839c1f2d7d4c1b97327e483a3a2ef7907c356cf5096c61f8ec2df152bac8f7e0d0c4b17bc8e589b5a7696301cb4f71a793ca5ec2af86063fc1cd8c2f3ea51e4b173c4e643aca2ec76ce9869b6eb639a44dcb6cfe62d372cd1b6b1aace612355dc55fa9ade9216414422fd5d678123822e17715353c0c1b91f885ba7a9e068f22f44e754dcf01a3117babbacea3b09109beaba8e759e8c844afd4d5f6303c02b1776a6b7b0a1a8df04bf51a9e858d4af84d553d8f0347137827ba895c69c6114250911ec29ca91ba464ca2f3418f6fbeef0f9e9b1b679a670a9afdd966218a02c9f9c08e9d8b17caf03f7d8a6482ae9eb154831d357681805ed777cbf03ee1d8aab64e93a2bebc02029955b3c7bfa7711b803380ecdc3b3cf1b5131cde100cccac7454a9f6e0301c5cac9ee63c8d06c6cd2078f21cd44ee1ba2168c3b2989ed2959d40c49d06b1e488703e84084a918fe181e6a84e4160cde5c3a18fedf9331dcf2e6cfc832720f7f672fab0ecf6304b5b3b224b7a517a0702dce6a09530cf3fd4f282a5b50842b71a45babf81b31467ae62373883649b0534a8cdc625b4348857076190aa38d14b82f5ee68fc741a361f7293ab56d9bffc7b2a9e3feb20577554e4e50417cc5d57727bdd73831473628289d9ace1148c29a67cabe3bc8514f1a40d21713036db8a05cb78ce399216b7067b55e15d698c2d36a5b0825b673ffd78ccd0aa1ca3433eef47d06d1ab4132734f6cf2ba11c783e7f75047763dea67e92d09396f66750eda688ae26ada64ddd02f19efec8dda4ecd05c1eb9f8535acb46e271e0c75e8351ab4906a3d35c3b1907a288b52a9b08744b7c16402938f669e95c0fe2631f2f2cc11caff01824213a695a6d215c221e9e89e93409d38eb2394dbf179597e48e7ceca4d0210fef76b36dbef2413b71cf430443bab29808bb97330880db7fefca0a333e19f4d857f842d5707a201d1754d4bf0e678a1ab57cbda0f8c9a6b7a9934695fe8f7b770c2eeab3f7341c46b914bfc43cbc5e362192a581b175586e3a29564df5959fdaffe044685896489e5a103edfcacabbabd4b304d551f70ee1965c4862e59d09c43756f0e0e99038fbe66d5debda60b344ac4450899e546059a7e6cf5f214ce1f8c4858baef651648185b1f93998526d14194a8e99e92ae80d45a9db24a2cc871cae5f45011b9fc01289e468b533f0779db6830fe83349c55a829b12800e9b46573c84d8ecbf5ee3ed7fd64b07622824a96e51caa3a4e01fa979455191e0d75a3494390a6f4bfe1dde47817551abbef31f587c96551b71d7307ecab4487c5e461b8a027a582139ac821ac303d40cd9fffcf1f8b2446a08b07b0e6c8f8e061ca5800fe6e058a1fc8b4e6183aab3be87a12fdd93498855c2f8a3746b7f6989dec4c0ed433ae02de0810d4d136df9638bcdcebf7d872de248b262322e06d64b5a7797bf9b38a8e249c2bc2976801f52a8d46feff8455751888ddb4098355fc18f7fd883d2ecdf10b7322c44d8ad3fd0b339251ae4ac3f021001b00c710a48db83bd32d55b9b998de7c2fa87ac93c99bb93879fb078282a82c89478072ac70813c53946fce73cff8378f6669a80236f161cf74cb507b9a29509167247a60f314fa44cba4c0c8514729919854042c14c277ec0614a5f437eb00d52d999b56a3dff72690e72b21402732eed4911092a024ee1793547ab0eb3d5b54e033587f729ec2688d1702f157cf8bb844378fe0ac3f261ca1eee5c65f3ccbafada603065cf7daf35f9e092a12195d771f49e80553c3131dbed6ce3432189eaff451dfcc71973c6f002f987f9ca10744af5d6bc43a28f1cac3050c845d9a9c0ed271781cb299604f3c5a8595c8622de59d2cc165530e8739f51df3fd815563b254ce91888b70f8f73e124751821114661c8ddb50a46be157d39ab764c4b15134ebd5e8a432588392043c3189447a2b0ccc1c4d74c5a74e1fc888fea255be9ce2857c8381555a16da5902934af36ad58de9334d17b529d6c7b23ff3f149b8c97f65ea4138cf77d78ec8b2f7e6eb1e280aecd9d30e923575de827f1909baf3f2c70857f1a8bb4c7fb35964eddd5c695bb64bb58888311835bedb47da5dc4ff515a18e7c970ba780c473c65473640e1f3e9032ed9c875c7836d15b46107c3362fac3e0b4a31d3621191ddf6b73b2f963362cbd7a67b8e687001ab34c55bd55d9e752cf1b86e8eba61a52b5bc30e8be19c3e58b9cd48c98e5fef2a639b6d947c40875f6a4acbb903c3af4e4ba8037e58e15ae31a0c26c2e87e5846076099812ed65292be56f97a988e4cb5c10fda2ad873fbd7acfca3475ae9509cd2140ceca897458cecb1f91d24a461f54bdcdf1b425a95df79f9b71280f0985f2ed1f726cbefa916f454793374f0fd3113339252071311bb436e6cf26b864b7e9e6ccfe7e84fbbdcaeffc89abbc64c4ba75a063de028752b092eb96a03642f933b742c43c5e783c2776cb26e0b0c101c624c3759c9ef05c3ce06878d415b6cc8148238f72e9e50ead0c09dd2eb50db7d68d1d9adf23ca83dd3d6bfd51c3e28c9db8344b28d098689d1bfe44bab94f3d566bfea0509010193ad62805eaef6e00988f00f28dcebd07f678101807824f8b55ae3b2e366b1a685836dadd41fa3e97e62c9d79804070ff9acbff366792a5c4f2ec7f3b24f3f3bf95021b0bb492a6061fb47827046f37097823750c9b77d8a92df4c3477dc6aa99a4a79ac2859ab165d7555aba7229a977a853f17b90eb196143cec4cc61c1d312f24c303502d1aa8970c3bf7f88bc8130dc028d8b58b338b1cbe0229ffd308416f676aec9b429443afad1c4440f092aa3eac920ae3542213264238f4a93182e35b9c2d7c9574812c6ab934ea13a3090339266f6a3c401165d4627fe56c8b6c4577c7a49bcc7608b9084dcd7025b45949bed19991c8441c1b81ba0e65f842fb721710dff1369e144eb3fa7dfaf44d6d22ba6cc774e1949ae065031f86688f19f48b33bfd4346f60f50e4b4c734909f3789f02aa60879bcadb32be2b3e83c28daad90077158ffbe79e8caddf7b627792c1cb74b21e39a41b4b015ad774d9861db09e48f519aaa6ad3dbbb7ed54c34b4297e1727433f385bb7e46bd9510dcc3fad3d56d249e0b62eec47ab02c1ef9a373ab57c0855b0092728a469fa1da0e817043244261eb85c7bbb04f0d3b22f6992c2779b19a5b750a7724f03321eae55faadbb4c818284922854da6d6cfd4368311dfac42006f58b66e39a064322708ddd1da9e5f82ac9480775cb1e16ca37372b33c2931a7b1d3d18de1237aef6a71d13f28b872e6ef50c99248fa57dfd2a7bc7040c941e0ee428effda06d36f52b54550326d67d71fad726c3aaa726e92e4ed5cac8e9d797aab19a259ed415c2ddadc463f55eef98f2728bfe24726ee179edd1727f2bac6f3a274663835ac2497d1e42211ae8c90044f350a4bf97355a8be49bfbcdcb38229cc26850fc297f991b924d3df5b8115ca3be2220187780a1a9ccacad0af65efeee5433108360bdae2458e9093a8ffa8b0896760f02b7c4c4d6dd1acf43aee5c26f3056a43cfb56d4981388f2d3ab47b8518df5f7a55265f283daa7304474bb3de1a6265d7ea7e3bddcbe07b84f1e31cb3aa9c32c126829e137c6aab0f6f658634719a2e96a5f438891f78cd6afab39212059f23b0bb15c722177a04bc1339b89a41fc1503d27bf7bccf1fe7db41fef7364f98386ac6d4e0f1d63d93923c9f585da88ab7eca1dbc954a52b5fd564ce28c4d7bc3a7486dac979d6bcb9a97a35a3b47add727f443498cb8998a6923e6dc78f3face0f09c4e819916cadc8b9bc5812e13fbd161897167ac7f85d1334f683eed2fc2e731fe4b71c377b63ac8abb4f33a541c4098faab7a4773abda227f65cf8fd10d57d295413629ea9008357742206b28d4c6100a6c1450072ac52766d580d16c253e16e57e4418490f5559039d92108d053d86d231e92910185de0c6522db9393fdfd62aee0a5973371ba7637e44f741a722ab53813b428dd7f2372e62ec9523dea8765624ea65e698c45bd8a0abad8a669d191f5737aa6409f96eef7d7f95b3250e5ef745f04f8f44a4fdfcb9e0cdda5ca1d4c9e23cb372b07f808b422f274235410d0c5c25a03adba156f18e722edbc5b26ef4988ce90ae4f965cc195ba0e32dcfd3e9855ee03136ad8f7fb25dc48aceda482787c5bc1cbc2e314a8d72b042e571aca7d4bfd04979ead16098420047db8e32394aa6754c56c47d0a549967cdcea5af1c46c35169ee121436724f976b4ec83dd3fd8c237b5a7e91024652c4e4cf1a2fae336f5bc5276cc6a350bf0cdf0fae07c5102f85f3dcf0dd6d312143eda9aa5ee49a960a53af4d34dab428b918f0eeecea0edcf452216ccc44613400d6c22cea339d49639321d67416aabae6734db0a0ba0438b7e391340602491e1f541b01afe6c35a00177ef898d5f8c703085e346e05df4406896f18cade50852fc130eeed0589dc9eca9671c136172332e07241842be47aeee33daf3754017338c7518f75b7373981e99c78aeb353059af6b030e4c607a31f86c88bbf0133cdd0b42086d0076cee68985c74fec1d93359fc3252189f9c34c9630d04867afbf6e846e389ba3fdb6377d6243eb995bbee3f09de1a406021606f1306caa852734f18795adbfcd7a9e2355f3093966ac0718b812c105f0d0eb987caed73ea55e035c11d37ef2c48f09c840c359c294e82a0808089cfbeef400d87bbcfaf433769af38fc19d1eb7ab439c15a9afb4e3becdcc861ee5b9475a458027f1a17da5fb17eac2d66708f237c758c47d5edcea2170b9e4f74cad5a8f6eafd93eb61e0a81349f15cfe8f10b1f42c873baefb0726a09818e53079c6f27e63117c20c2ab06ea1795f2df802eaeb3b1536d3cfb7397a963ae1d71e127fcfb5b6fb3ba2ca12a840a492032de8cd698b21534fd50dea84fb812afe95008914112d29f278b9fe7cb83044de9a358144cae3537c00ce605d1429e9bef7ba3b2229c2ccd59e5173e9b620eaf603bf661ed45dab2d7e6825af00e910a8a3990b22e73b94c12807ca0716b5de89d4402712f666a846a3aff3ad01628f522d7815178115ed2d1035a8d4f702fa4ca0d3253e4f2426e8b4e8f703259ab51e60347e5ff746f06f42eb51474b4d6bc93ea6d4064d046682961bc3932a0e47d8159762addd97fd1ac06c08e5c2bf594db641e9061860f14a02ec1e5d35154ce49d9197488004ee354ef3d0c8f092a19dd7cad02fd0ca7f33cdec684972a339ba694010b14ddc1ffd5f7717d298daacde5de4bc4c006fe878d531d78d696b90a14599c10978036ab1648cbcde6911a78dfa0e4dfdbab8dcdae56fca06f556dd75b3b2be043ef855595f20b09618e206be2a4987cdd34be7fedcd9411db2506d83eee0b9b7b5b43ff19459027b899f7ca6a3b4a1dc08f78e8a897111acc455f8281f80f296e82b8650ec1e2d625f43c0143ae40c15f8bd3c9eb063dcfdaec189b21f95c6f1f0bac31a5c49704205c7795bda28396fa7baee3579232262a1214facc07b5698bbadd447a7c714dd82bc863754672afe722683ac8e0fc7a95babb2c288e8ac45d61f53707f13f3ae3812102b0fb7c11879871d6a8310c0470a34febea19c72e12fa2f2accbee2dce7da5c05810064800d3900a2ee3810b62758a43f8b91df5fed942413f5e6e231a733b254cbc8ef2b96623f75a0c52d5b54d6733df6f14f0abd374f75a7d8adf810b77f7805067d472130fb921a70dc504409300b4aa0eea154392c503b6721b56147a4ca6f234bcc2376be27cfb09fa27721f58878d66ac2231e36114baa0506da92412f3a8c5f8f4549a8a99f2ef3245c316868660645bfc578285766392577244f2c4d7735d37e1bb6e879b3183cefdd047b1ad25aed046b80f2eb7f8d01a2070004758501ca245c3c1361dd166f6b255d7218720e4aa7793293946d17106641b15feeec1dd108c5ff616352306ac4e82f6463eeb81d14ef50eaad9e4941176ee900ae50170a0b6c54d4a7fbab1b42c5af16b8316864ebccac868063a4dc27d83c3c36a4274d45ba2fdb9eeafea711421fb1440c8a63429c5c255f56db7e58a33893f91f3fd9cd2664fd413aab7b948f3910c2ea2c7991481a5763b700316508342db76f8bef3d24116674c721ba6f6c9b9aea7d71b82927b9a137a7969ea5ff70ac10bb5f302114c36fd50e96ee5049ef42b879825d73df1035a93b1e179c288060b26878101725c1094852e7dae06db36ce0f805ffaad192916ab077f6ad6c443c82db1f7501338e43aa7733b061dc739c970cf1145d32030781cba955999049613489acb3536ef03dd5a90179e8ef78e23161e779c175bbecafbb2ee627a77ad512c00ec668eed1fe6092156c404dc78823c5d62460a7c01f16f25e3094e59f511a017694b95e2294740dfd9603005d16b120c6160950b3d6a90f4110b7b1ba949991ae56741935771b024a8397ab3e9c23e8d77618670273fa99666b6d3d851ab3223782685de7aa3c617a92ada5a9dc98d10b78a7969cffb0961ead3b3eb0ed5ad2600a19965c568d55643e0d35759e1ed21d152a44cbf0c569fd6cc9f9ca5a2f81866318e40aaab5124ef7caeca3fe7f7df413736e4d96d8b0c1f4c654e4239c2c9906b47ac868671c39fdbec5292fe9b7c90234001983527fe752798d311efb6fa769fffd3355c37344a98826f3e9c4d6fd57a09e750f2478e022885b48cd300059c67f60eb297b2ca49088f2714398cbbbe106c64de7dd7fb7c1bfb032ad3303b16991e7b6c30aa890923ae3081f172e5de0644fe4c528728cc94b90b90550644943ea34e9e7c78c3a888240da26524dc5f67fc460242f4f79ca10bfc0d9222bc58b528fecd19cf09e48f364484cf837592eb3c8fe2443c1ed2c80bdff153737efef0f6a0f8f684ff5212faaee3f0a3dd2ea8e8bfa80f36d70bf9ce786bef909a2d94c37c47fdddd0e3bf32c4e92f85dc3607b39c4fe8b76e7b72527f6928ef0139f9f8404b283fe55dacf40b6f192a5e1ecec1e672c2cd2f7fa932452c46743a5672a1bba62af3c1a892d8b2363cf2719965f7d0106c8694421e5cfe4dae0f294f71d02230e80eb3aebf84ac8a7da52433ea05e66774efd602a0e5c4d804bbd7d776f485f176331931efb1bad80f6aee3c6b4277a8ba9f4f1cc7da4148a7f826e876301c4e927a8644e32843e70e7560bcdd29e24cf3eca24499bb71da440ccc831288db73b8fa73f33956a0eb3228e77024f772fbd227f8c818e8ee0a1cb05ee37ab3f37e002881fc7799d1995221cd4dceae4e10df738ea815040c10f16a116362065cb159e1cd019f8f3d12c717c3db15f4f0667929d4c4e97fdac5036f9ee3101752792fc00e6ff1f391663cb881878e7cf0eac818ce4bde908439431962c79bf3c3c9fd018ce55c63e7d0254619b3028f27e49cd3285eff08f2086c85b18974646c3967e0d32588801383f9510a0d7d89a46e138bb501a03ea8be809a013128190082e256e9330ef90381c60161bec78efe7b8da1c62c8c7fb250bd71988e9cfb28600a48ccfc80c33839a4832f3b8c330ecf3da44861b6a3a37468ec1116fd800d06ac8758dfd7c5b4aa5170869386e06c68eeb86cc45358ee8ea798a873efe05310a3f2b470a0eb544b6e26cc831fe11eb3de2067dbe212d686868a328367b8eaccbd24aeb4e5d45deb5f3f36107db7da07fa4f1cc030930b9c0922f72f339b897c505a3efb284066a74b6c3e6f45c5cf88eb87a0ddf31fa1b8e36926aaec98ddec110c764cef07c715b216a48d9a61e41103d7de33542201ad6299d7c53a19ebfabcf5d45d85e73e089b2bf493504de334324160b4c012224ce77a3c5e394aea91d00a1d7bccc4a9be8923e3d7568e994d04fc5b876e1b60251d931ae44cfa28d374f1ee1f3fd4dc2a0e95314465980bb1151d6bd3cb26715018915c022a853dd11ef5dd9db953eb6f9480aa3458f1effb3661eed29d9b24fcf9baa19398fd9fbb07e3717e5e17432161fb278d0a8d464c5eca1e1310efaf420a9769cb819470976946edd6cca63e2b38a7a4ea06c63be22e45227cb3075efa6fdc24f62ca7425d8c0d2191ffb0f30ddf3ecacf97d472bfb2be7dd47f20ccc90387fef311d8153a79e32daf8b2684913137e777f64dcfbcdb91cd136071c50e714511a3efd3e731aed09456fa13fa9961dc093d722527c6f61cfc59c0a665079b08f34bb1edc3ba1d91041682cbbe4656d408c9843150bbc04e34fd7ccee36e4f8b80dc7cd5e5510187db841d80677a023155ec042b9464933aa804eb93b580cfca62890b368425bad0104a64f73cdac6b07c6d00c36bd919cbf743fd0e42a91af98743512352313b0d275cdc8bda81b44ca5724c4f7f6e19e63c3feae7d8ed9d1530eeab32ff1f041fa96ddecd7118d3bfaf5e8aafc3545a7e627a968d528b1281f2152f0c1687bf9e56ca7e23d77b11bfa113e69c3f2997a6eec1aa5812b90698c6cc7f00c8057982bc51115379d22d4085f10465b03747d0b9b0b47b834a580f4ba97dcdd22a2c1a3017150d32204275117fd7e2c75ed356923292ea34386d5fdec8edf89c19116c31d560006a1493847f22119c66085bdced7c85fc9b604e955d6fb9d99828cab25ad723088a71d1f64e064bb0837dec016b1e9028c997013e27ad4a3cdfb872ec387175b4f0c62cd651a396078d9d8b5d9d873600928e7d75aaa462f23bb546376090701801d6a7a3c4c1c1a7b76a6240914658d661b1c293925327e0bd10d5666532a47fbf599e65ca86943319e740dfb503599149581d0f0d19548aca10561a3ccba8ea6722e260eae1ca79e4fd398f8424e6464a912c270c836fba4ed438cddefbe23c92e272996d0521273036272fd5f21a2c3c1bf32170d94096aae6dbf7d0003f039fcc0b8e7cfe104066b71693e4057d366954f5134abd0b48c25ffd36dfee0601b72d921d0915892222a4ead1bd63c605c790f414259ec9ea7ee883c83579358134563511a0e570e95b97046f8df4bb002d9092e1f4d703516dcde7084a3cdcdc3d4345470549eb8e72ae9046b3d30c3ea471d915bb9f673fd1a7bc23b09f9e2c1080047a3c306e20bbd2a7314e4a38fc8cb393cbdb824d4a7e411525c230c9abdc2d7ca6ca73b216a554148c0ae5445424b84971bad083322997fb0da8fc29bca9dd20c8f642ef825a7de880248bfe94e960803381e0cde36dc5a71fd9b053f6c8d7a19e54ab327104658a430b018426344f1dddb23f8fe64d60031ce0cf4a1019d2907cfb3d4198c207a9af60bba635aa4caec049fba537dafc2c098410761f1a0fec9165dd119e9f6d96f3ae6b3eee46daa66d7995f7f7213ac826966c33aaf261c73b20a40b91d0517bb9afc1fc6a3a74faceef666a4074aaee104c135c7f45a44083c0d35fd13c7a2842dd37389a069454793eb79b5823a25202a9a8bacfd1e6d5cd1d71a7fd61775b426d1b0c17ac6d0730b8107c248edb807bde1000419cbf75348140c26b8dc31693765e35cc251599510cba8c5415ca9deb3d5d4c512d4b2c18d7eb1dbcd790ef68f716675703bc785a395971d77c3a5bf81d804c36d7bcfc5eb372127b30c90a6b38edbae78a3f53322d55aadfd0f837e849f90b2ec8eda5ee519b8be19a1aaaecfd1e98c635a0d5038bd234c58eb10b3ee5ce23123f8454c586bc1f19b2121f30e3bf15932d6068bb52cc0691f24bbedb566ba458cc5b95ffd4187edaa63d8b1667085e06d4a5d22e3a5cfa2c162586d05a63620a8b080e8eb61243c0d771a80e17cdba05f39a81359ee619f6f3cd42ed566b087c1c1a11a02871a1324e47680c8e59ae17705ad5b1ecf505c191d3561877317f7b44d255ae952e81f6bcc0e59e0c401ec738ac01a159d42dfc7066b0de86951e2b77317719c3d88177bda7ac7159a65c62742ff582e91664d130352e48ef13c927fefdece2c41192bda9173887749e2ee26efb68d69213a3bdbbc87eafb47fa723d806d6b45333ce1a2348cf566a6d975e9d52c664ad93c4b050325f868a364fd2e8c89f0db9a3347c7c53b4edaa71268e70a28caa492ae34ec4d9570454b596592de9641d3f7b624b0f45dddde2222dfe8485d22ebbd65583c17211246951fd3f809f1f9a3ff0acf1e7fb9ea6b759e7ea31bcde103afd35f290e48b944c380a4dd3ef669aa49c98a2f01629c1b2919427345e27fc0b29b36f24c7212208fbe36c531e73bf2313ad5544a76e1812adb662ff95486a6e73d8e02f5bd52bbca26ef0b499ee09c8d7741a1fd0b92865e27e73dd4f8bcc541b1d6e9ce821dbd8e1cf2c47e31d4fc81df97a3df7268f4bad1f56db0509190359f71c7fe70ee313d49be16f6976ca636d801a52c9a1288a5d7fae906e29460ccd6d86b196a65c5cf1c6356870a897ba030ff73fa03688bcff69c1fa04393ca81ba3263b117a99a84ddfef97b0023ab0fa7d928b5dadd813dadf27087691897a9edf70740f81d881e306f118f9b9fa445f7d108954e9b39df5e5630128d7be14805b8f5c817a2be64484bb12f07f08b1c7cd06557959a4b7b12063b6b0b5647c1964aa074a86ca043c5d20f1a272bde11fd475ff133ab2c3e561fb69f2a38322ba33a150ea6fff6efe2e80d51754946e5abcd4a17da47a2e026046d578268862e78b5891fa442ac16a2081f232631e00227acabb25e9630159d7b16e613d5f86d1827f9d195e6fd7b883de7f388efcfc60b3ece61873acf55bd35a5154df1067f367f8b553d8cc8a34be71431a571abe6499629721625f72def0423920baa11fc414a6a0a60668e5e90f0a37fbb33635c7e4613ea9da64a8598448b464727c549e4665069c6354f33bdb8857c1721c78834313b1a79e2609c57ec3b80b90827fdf66be60b7a42fe56bbb94e486cfc3c1f437029ee582864b5b713d5493d2f326fbc595d38e523bd9dd412adbc27bdd8c05631188242261c01b3adddbd7d9400d5fa3e6fe6287b0c6ea7ebaf72a70b29d18ceab746d200b1ba8ec6669f6c12669c240e70372d8339743859fe111c5d2fb710ec8f934d15e14c909030fc719ae936bcb71df5970e805e3097fa2bae76cd4878edc6a0f62d1df707190892e330b9688b82e5964b469c2330b30f1243229591c64553f5c35b91aa33f694eb44cd370f13a3368e92954d04a0c3811da854cbd88f580f0be567d37e35292919e197b0df2497af534ab9dbd24150732e7a6797290d7d82b6f700c4053bf62ab7963c19329cbaa398ba0c63367cf3b88ef06b30214ec3b5a77b1de8d858330b58c6e5e6549a9200d252bf092e38c252b918b7d30eb96a727ffa6c503cfcabcedf12c4150b3b74c9da6f2faa908490d73815bdc31d2102f6241ff1f8071bf237ad2de32d775d0937147c5b8e4db2277743728af110b8e198a18d347edbba689dec3b9c4ad7415d1336d672d7d57b2ed2686bf73e45958e31c85780b853b2c35f156102b219bb72f91b253ff69405fd51da95c45c00a15fcc512779ab51f6606b33f895467449ab5bcd4987f54d7b94f320b056eab033cc912f2b72e8ec588b9a69433cd6378d39cceee621d5e9e65b6674db1998b7808c3cf7e7184c84a232d0a2bb2fbcad0b69a5155c4983057a34bf802e7162cafecd5501a4aa699bef00c1427102362a8ee0c939405437052eb7795d6ab6afe7028aec2a30fdba416552a6707aacb7170f34a704e472407cc21c99b3910df1e83e901f143a2cb403010532b56578dc00a89670cd9fe0b32947cb546dcd472f35ee47153379b2d6d1afb0dab18901a51ab339a1547bf0bd6e7a8f453b0773335b20ddcc30450c38d856b29546c784195e017bbb6ebd2f18fb980f95cb2e17f34427923b66f8eac1c0a5e00628e4f0e6ceaf7f2223133c751626e0cad48b1ebbd40a9d3f8451a6286c2484d96312d33c9c663f96ec3bc7d7a4b874b3a6114493d07447e55465f87a686d76414c9f8d41fca0110b8f41a67488a849df41a09a2870190032e6beda58ed15b395f94b5eb991b750453ca8fe1ac1c45d8d762c1af8399df75c9eaa13ed143ae5fa1d50720dbef1e25249f13f9df9355e3f7b7f01c80145469a51dce75cadb9b971beb1f7cb8b4bfdfe93d8f4d000e773dd876dc3f21f83ac0694dcc7d3415804ae94ee2974ee5030ef561611cea9e37af168c2d5cc82a5ddbcacafd8414eed8424e1db5bb90130706e3a66979f7487431ccd5d77dcfddc9973c9f4914bc1a69a00e89d42b42cffcb51c5b0dfa7544f3076912f0c86694cf3f9ddd9d9a2dba554e3a0dba44d7ce7adcbb544155e9b4755d63ba3a9a15e231ea305b8f9f8e96b737dd5d54202409e9fb9078c462f6264ece361a9100cda0a13b30a2ebb3678113e69b658dc0dac79d1775edf30ed69459652c508cbfe026694699caafe0be51f9258a294506d5a87f4a6a0e7b92dfc1cd7c588971fe782c896e8574b8a08d873384581d40d46ce9b2f60042788cb456813c5492396e0ddecae8c3082a661baf294b357372b5e9a2a598e248f68d28868d479f22c65cb7beab16e5cc7dc0f862bf332c582639b2e0e7220d2292710e8834e88066c56c97a5aad6d6eeb052a217ea88203a01d501bfa1d2508f6641783d99cb3050470fb18a2e3578684d8dcd87b85b17f67e6d6ea4540b40895686107cb4ce002aedb8f8d4c973525f032f98d9c982254bb6ad5e736987e45e351d934785faf8bf4aab7613ecb62b9afb418e4cee10f02025870f4074d205ecd2525c82cd35990cf449e342c82295ab8629dee5af22aba75085a2489096754bb4816a3f1d9432a5ad13a4dd391c3e23e499521c4b8195b70c7176ad7ecd9c583aae92cee1f829af01fb2217fd7eef27e64d8e99818164b80375ced2c3ed0fffba81703610afe19034cb4131074e3db8752672c2cab30468bf1427817623dc7071d01eb47bd2164051828ff43a77f5714a2c4d352757fd4939057bc8c035c51986116857f914bcaea17b378cdae49032c5702927370d8bc3599bdc931e397a88c3f3df5cb95ee34d52891c3af724f7be0de3219b189860a0898122d5f7eab63258a0d221feeafedd7bab567c0978141fb340c0d4c34ae803564d95c7c2cdadc6cd336c0f72fcc303e813d4a08252312a9db9bb90606c139608ba8a135cbddab032710a7cf22066fd6cce4f502c4e15766e446ccbfdcd7d251f64c8a559a21aa4473458fd25fb93a0302cf94d205af18d0c780f3a6dbc993e0b023ce889cea9971532a2020ba1d38c6990f1920360bf2f5a29db2c3b8fa0942fe78ac3d5b0f55ff1cf3ed0ecc5a05f147d84712a8a38109581b464024b738ef21217f610922fa399c9d2886135430420a711ca9da665d81ce954bbb3f4b7720100c233c2582cc4001b12b5af189f8980a3c5f85ba9de928918c1a3853e09fd00de8163cef1484e0a97fc82ae7e2fe1b4d4ff8b2e308c20c8d3358eafa7eff2ec5f2ddb6187a9f9cb18b9666d27819ac8f527a24e0916a69dbdbfc0335d29878ccff9bdbe0cc3e30aaa16d48fe5c12002a726609bef45fcf3cc4e1cc7fa57bb37d575b2fb9d6a4a920b346992c9fb3d840f6c3ffb087786288fe2e0168f1fe2040e2c30f54b10dd92aa1968e723d5231aa469e5faf0107d6f5f8ed0dcbd6897774d785e5566b381ecfb99ee9e92dd40a7dcfd958bf02277b2ddc9cc8dcb66c3e7406fed30e2288a68b2dcad8fa7833110bd5f9ccdabd5305ef01009e9f682a4b75f7298dedeb0701de6e23b816823121be786a364dbb354f323637348b56ff0001cc35b6a880e3254d05750c57ce50a77bf9a3150cd7a7ab1a6b591bfd6914baad0d97fe7fddb750cb3a3c43f91163710eb1b229d5b98bb5b2fbe48a368146c181325d16d018a54a8ec7b1f7e82c6ee76355d4ed5db9502805f4482a2c2945887773230d599dd2af2b7cdd24cf5ac719b2a88c2147882455a23f903128f8147533cd9c0ac57e64432557de6f43b34450e2d93372881097f53513374f009071de6ad8e74091e5d8ebbb23aa49f85626e2f5136199c8acd9fc2d29e45677f4d575361aa760f38afbc3b6f46acba5f83f2afa6e1fbbdef2ac707a241700d9e3e5eb7942be4db30ee7befaefa715d413fbdcda29f39b66d4f528ef49c507fc63e2bae63b07485d9a733ec50b3c557f6a6f1e7b21fc6ec3b0a46d704f059e09b77952c69f882af484d1df1f3ab0d61ec0dadc8ff3c9aa5a7549e5bc9a1cc9403268736fb5b880c2ff7441e0d642b1fb7cc1ceb62bbc215118d0035e80fbbd06bdb1e5c807e504721701d413cf90c93fef433d3cfdf90b971ad8ca5602da2a158523553cc8103e451a4d4481e366fb694bee73c512d11b0c1466fd032640c1dcc8ffe367ef10510f6f56cd9ac461af82c84aa9c29ffbaa08772b0834dc7e3c8c94992ccf3d85f9c30eb055897945fe3f8f5c20d075412270200ede7ee04431cffd05a3bd6030c6519b2e9354274183d3bebe84df615bb801f5323b56866fe6724c71389c59ab9c8e5659067289db9309a50b67e00dffdf9491214e75fb039732712c8713509ced0131c0b4a70195ba4c8ec0b283a22c7b0dbf1fc6412ed2c4de82859e6abd3f51180d0d804e499c2ee45002613fb99f968590283d52786289f149ece6461deed0759ac6e676a0a9b298aa163f0e24c96a0a98e0c0852029aa42dfdab437bda93efb23edea1a740ce383cb35d81744fcd9a6be9ef47e2542f680061bbbe4975e70d160ea6f6f4e737178e789e45eade59957130d30e5aae84a40444da2b6f30c458054be0608abc611221c80d3a194cc2d2566904c4acd1ee8382caef84095c2e80f4ddbd836fab2a862108b2adef33ac9471aec7765a995367a901fb3af6b40309937d205777154a7262d31cb03b48f16438a9187b742410d097dcdf4807278fc11c35304fc9fc868ef696323aa5f91aad21ece631fb45dbcca5d43f5c9ff259d530c306e5110677aa345a0c11dfb973ddd11a4c50198f826ee3306febb5c547a17816183f00237edc975b99e3288bedb4c40a9b91b95e65be7e1241ec820eea49089dcd61019cbe44f6869f6be914b33965f82e20c672815c3e932e2bbd637e38034572e01b9c38a9b80a30eb4af10d4152773487211da08141226a60f818a1cab2304ce7f435e03154bb801491fffeccff1f8c0c02236c5a52201e7731cb094fb0061d569e5066e1c28f37f6ddbf859dfa58b4588a93b1213981e291efc2995fe312611349407e3c6c9e27cda85453f72c75f611bb62bd1d664df72a04d9f7c54434f64561a4279373b901dcbdcd9e56a20630d838b2d76ccd5112389233ec95006d87476c9e3ccd6c376f4035fa58e8ab9e1d60959172e6626dce3ff6db707678e462f99579557d2dd4b71b353fe48e9ec7ad04c55576a4971e8b2bba9426f56db399d1d25923a3c71e7c0655904af4139a1aaeef2453ef0d6420becbce48d6e5041e0410423e9742403c92db38e65cdb7dc290c2a92f63380f85ec463a07b28960fc40456909ba96e5d40816b2e1cff8ce8898871de7feb394c739a1520437ebe9694e7119a08d221019cf12846dc58c1451bea34307450277311b01e2898618102670acc8a388819becff18ae7b9e900fe53e894b380a0a6e60a897e910d81229d525a9180029147f02cbb0366ebc698d4d80fd0a18697e69f883d6dac496a5b6ffc42aa9763a417db0a37d9941c116c311e04fdcd96f01b84ed058c7cfbb2a07763927e43b936d3e312eab38e802890736be6303755f5fdd8ac8be41842987d5d9f6d0afd87006448cd51b90ffb430c93e5e0692007b82dba29bc0c138c6ef8343fad430a23146ed6df1bbf1b36df6dd18056e31bf29040782cebda4e26c9ade103a369bf8acc57d07034460f170b6b80a0d90708f9e0d6ddfaf7996944715304ad3e42a5cc88825806eb276aee9df8e20e1b533cfc0b9f9269caf8c0b32d8056057ef670b96af062537027cac8cc8bba92c5a0da4eea4880358eb62bbeb5d76e792e1c586d6837de51e42629d15a493a874c9feb8b7d84ff5864a8fadc03367c980e5d98e6c5bd3383c677e485f0c0c9dc9f49fdf2edff43e8ee514e5000fe2423f1c65e437c4426aecebb0bca3022b6324f219bd824d42c8b981564c802993bf3844ac9703b2d2fe32d6f0d555575df68cf1ac49bb28cc564aeab893942a2acb4810ec39017f7df1fa9f276a25ae59dadc7e298ad6e40b82c1f79e1fbcd49e01de4e754a311f4df428b31bb2aa251bc4fe3cd0be4a23c32b1eaed0c29e930a1161cdaf51e8439452bf928e0a600a4b3048c52c00d1927fbdffcbda35015ba1c93e1331c7612243b4998151df56e69c169678da810eb54cd7b4566dec78d3089be15016fe9bd9e0784c7e94e44039aa2941a77afd746fe51e152fd4963479267a3a1c4299ae0ee2346dc75eb9c3d06210e7b4394370c59cc613e0af1a5f316228fc035ef1027b34b8cef22fe179a3c345799fee6932d953abedf3e53653c76157beed0c142f8a1d8ed079b03be5fb7bc6a60c62cac42e0a905e0193c4a9a74a128772542d53327a93b30e8001efe9abf705c9410bac1d760b56c387476481c1d0df996ee4147c48026e7f455f0d2e70b4940e000c30c000030c30c040701bc4752559a950a60e5ccede00be297353923649d64684c6c584c6c544d897280dfb0c000d05ed5499fcb1d38535a554176aa11e68870b6b94665a4a39d336ce16762063e1289e77485a0bcbf763b06a394a867016f6a0a124ba41ca560c16f6d090524cc4fd87e60a8b98c74dbe98f1038d1536adbe3c9141f0303155d87a6433da870e2467a8b0e583f45929b443be4c618b616258f0c813d3228575f3665075932be31a851da4bfb42133c5e42814f68e8aa1b19369a7e813b654f21bf2857558d4097b4a9bf667724e8b6a135675f0e3d739440a95093bca9cd191ee66ca74095bc8e819c4ce500fa712b634d1247476ce679984451c3df4f0649f538984e53af94dbc494f361e6133ef1053e6ede41434c2de536279e1a25a148bb0aa7fbef88cfb954388b07ee78be915ab264d86b0dee76c469d84b0c8a6e431ea2058fa82b0dc7f8e270f4b293d20ec3874ff7aa63187fe602de99c29a59136c407fb477218728c959ab31eac394ff97ccc5be9613cd8ce2cf5aad442a2b5832dc7a4b75329a399a583e533234bff9841c8930172b0fd4f55e8983efd840c8083e5bc1ae5905421f171b7582d47c621ce655c639c2d164bc761364cc7f25aecddd38f52861ab369b145e98f161be57cc82cf6f848ac742ea31f2f8b75eb51f288561d8d8fc55a53e2d7a1428aecb05852089509e5601ee4bc62739072d347470fbf2b76b019e628c374f5add8bee4f45148f2b164c5e679b36773c4375cc51a3e690c2162e287a862d190d97cfe7399eb54ec91a4bc7388d628d4a8d87e3b83c9b08f297d8ad573778d468d1d6a36c5ea481dd7a50e530f2ec5a6910ea4322d334f8a1d260797d636a35852f22e4e44bbca1851ec69aae1c86842b1a79cead7b1b73e2fa0583c273d7f4a939d2b9fd8734da806a2e7a12b9ed8530e15fdf42af32a9dd8434f07cda9441dad9c5827751fc7910faad14dec2867fcb02ecf63a99a58b3a763ced80f39a29958d671b2f0305486a59858249a477e9834b29397d8c637d287c6a88aa625d61cdd0f5134c334c94a6c15b1751acb623f92124bae7cf995a1e67f9cc412d2776a5487710d94c41a5592f92627843889c45e9f699e515d5e4c0c123b88aae0e7e9d693c41eb1559ee4e0323d4c133147ec99e38ce48a9ebe41ac119b8f748639724a393f63c4f6d9695e9363657eb6882d8e87cd8b8b569f3345ac23b1573967ee5bcf12b167383a13f3731ecd0c119b55eaabd4cb0eb18fa7147975693aa7cc107bd57d946b9c9d725921d61ab5e429555c8a6584d81a555cc9f7d13a5636882de7adcf61bcba246482d8f741b050f952c77a58203689fcb70e33cc3f0d03c416ca3f47fe154ff1ffc3fafb4173e77da4fcfdb04ff0d987d1326bfd3eeca82e4b4394f59fcf871d6c4e0e298a8778fe1e96dbda33e9cc49e1eb618d670f3523cb98f29e873df49283941482e4381e36cf0f8bf92476def81db69493c5d5c6edb0d5a6bb543db9abf13a2c9727258960f137753aec18259f8c7ce28788cf613d9fc69b1646d473e4b0f85ddeff10711c3d71d82e35e2ee79180b1e38ac99127426de7a65e70d5b8cdbf399d9fbd071c376df602d754637d269c39663dc0f590e1dc6cd86cd6a3338ee8c61d45ec3963a1e8349b61a36cba01bb7eb81c5390deb48e78d52c93c9bd1b0683786a9216fa283cfb0f8fa5eb81c331cd99861dbb416222733dfcd9461d57a64319d5694a892618f9bb89624fc9ea56358524d4a8f66f1d24f31ec3f2529634ebb1acf30ec3977c671a25c4828c1b0a7e47e102155731abff044cc5d3ea917d65bbd9c3982e897d885a52c83c88e8f9d4ae4c256b93bc7875e1346dcc2f255617ba2c4ca19a8853dd4c49dd5ca8cf3240bcb967aa43507192b040b6bbc4751663999577285fd73520f19828578c40a6b380a31e2a7d5ff5558cbe2e4763263f4478535c66a2a5c5e68ce4d61f5600ee3b2f23a7d52d853e3c38771738aeaa2b0c69b0ffb413c8dc4a0b06dac987346b292883d61998699a28350966b39618925317743c918aad5843d775d7549c4ea9298b0a39d108337c8891a2d6169904c3a2c342eaa843dc5466fa41c27c624ac9df341485d740c1c85842585c6186a6ed411b6f99fbd14339ea9514658344c741ea4f7638c2ac296d2e15d296e34cf136199b48c3a0f618d31fe31ba861d2c21ec3096c3cb39e37482b0566d74c5ac0fe17820ecd92176e56b3cd73fd82ec64f396348c3a0fb60ad7ea41227e142da83451ea61033720ac08325544d8a0c96a2d95d801d2c1b3fdc4f28a94ebb003ad8318e9956536c0cba2e400e960a1126963bd267740170b0c6e4b43197f76a946fb176c67b96b9f63ac6b6d84c2576a73e5f655c8b653d4ee70c2ff9584c8b1de30a911752a46ef02c96480fd9fcec8cf6228b3df23988c6f7917389c516e3db30733e896481c58e7f27f67e87ba4d5fb139d0941f5f3e134b5db103d3f91424667492b662ef0caf4769a51b0759b1fad4a4b58c1ae7435ac5e2e11beb40a28a6d2e39c83417835f24156b4d458a7ab15b61546c19761e9cf9a71c3dc5969eca27363b5c77a6d8636eea2abba641578a1df959663c8f437c1c29f6f975247b711df2a3d87335c7ca7361cd12c5162b678e21fe61842c14ebda4efe74112c3f0c147b4d9cde7851970efbc4be13e42e478f647979624b0eb3663a74fcae4e2cb97445d3993a2a8b137b9e079b06b1bc6edac45a963c4ffde4a6106962c7f74124a47a5c7c502616bddcbfd21dadf44198582c4f77dca43d870ebac412ac3776f9c3ee14b7c4d2a5e163b2bc128bc967eeaff59bc829b18ccce44d886b933a93582b6e58debb25b185d0919a364e4c3947620da39bf5a71d6c65482c9db1a278ccfe8dfc88b5c43f5d64c6114b839fb0fa7c639569c47a295a44bdb39c7761c496f158c81fd52ee28bd82c34869a8e50b95645ecd1cc37755c7314d6446cd9207cf0d40fe5828865662a4b743ed3cb432cfa71fb61868f9bd210aba7b85f617305b30bb1a6f8a3f59fba4626c4123b2af56fed1a3c883568aac7f315991205b17f657c1a92a8fe858158a3efc983ca30860c882dcae391bf8bd5dc1f765ce791cc42e50e113f6c96e366eee5f4d4207d58fbe1c5f015dabff2619dbc6a3b261e72c6ed61cf30e7b8f126421ca787c5566206b1b63c2c957cc77c754d420c0f7bf8943b6c712cf6c5eb7c55db61f35ecd9206331eaec3f655b934e3dbdfade8b04c9a989b6993327e0e9be7443bff9afc1539ecd034348d58e59d71d8b2e124d1b81c3ac261adac06761d7fddd11bb68ef09533885bde1983006ed87322d89ddc46cd8d418036ac1e1b3b88444a960408c0862d4543481995976d0ca1600513d01f10600d8b0319db2093fb779a1ab63ce65b36aa21fbcc34ecf126c48498baa48d44c372a725b6197d4f86e619d6bce099a387ceeee3cdb046ccfdb9a365ad46cbb0a5f8112cd53ee5873964581b79c74893fc316ce3fd3de952df474f11c31653ca19f129457c180dc31e72c8c1319c8e866a83614d0f7d43c31cf2c6a45f58a42c536723672e632face93398d81c3b6d90ac0b7bc89342c4703184d91c2eac9ae26ae5aa0c4254b6b07aedddf5a418e3fad2c2163545cb0d926f8810cac252576ab9d16a83890c16b6cbab1fbde63979feafb0848a948408f99cda5961f59433c80df3868fe1afc28e7392182af67174f354d852bd26658a2893616a0a6bc67ac31a3bc7791f52d81b843bab8a5d0e421d853d2393fa0fba97620e0afb6e7a1c62901cc7317bc2de20868df9d2f56f8613969ad114a22ba514626cc292fbd51399e7e36764c27e1ab1bb3db621265ec21a628c68a59537295f4a58aa73ef61a93a46399f84f556d622747e3ed33c12b6b492379d6e78ae0e1f619bfdc87916834e679411b6d3bca4258d2a348c14617b942a67982274c8771161b14fab9bc299e6c9c710364db964b13f3444c684b05f8e6de6cc254d2b08cbfc8649588c81b0d7f8846af4e330eee6074b8a21a709d98d514ff4c1323956bec6ff1121a4f460abea502a9eae31e88e077b8c4b55191deb1ce4110602ec601ded4855172202e860499b9252e13fc25c740402e46079a81229b9763f790a0170b074d894d21ac78f1acf5bac71a4bea76763ca61b4c51a35e432de18a29bacc5a6fe95c36426dda7a88b2477010b8a1ae0010934400603a0c59641e2c579873497fe2e924810031658bd008906cb05174918c02cd65f8fae39914f196764b184de182533ccb8514563b179ce04d10d916e7463b0d87724c5bc21f2c6c8f52b763cea492b65fe3421870424a852c107b8e0e2b8627b60bfbf73bf5569d245b66000ad58ea42ca182b4e5acc1d566c92e2a6484448367bbd20cb0a0358c5de51d9931d43e3b3e3820b2ee8c83000556c1a2fdc54c678c31fa5048901a4629033a34da83cfdd56100a858ca833eca959df92e499e18c02976508f3e44c84dfcf1060330c5a28d43ce5f49cfd5ad60052e381b0ca014dbf5a410cff5ab0fbd0b1898600624a8810b60408aad73c2e4f8a35e1922198511e14ea52b1c7cb84571c73aac0c0e73582d4331ccc04348040b8f195d2491402b0e0300c516631d9f69b0e0d5e84fac132a95536708d2bf27b698fc2936bed00d1d547430804e6c8d62431bad4611ba2e41924b209513abe9570a9f112d838cef22899c02ac30804dec1f35ca490899722caf8b24a30201176cd8d93026c01603d0c426391e43caf829a730779194d48047a59c647a25aec5527fe9b36be5f77e5aec31ff8659cff711f3b3d846bdfb2667fb4697c59af3e86cf0c46219cbc956ab33241b168b87c6385191af635eb1748c1b1f4d39e6e9b862b58c8268ce70b5fb56ac5a77feb0f1831066c53a1f63e83ecad4995ec55ed538a7c9fdf31b55ec13f395d12f5f2653b16846a978d428a6a8d852af466654351be1536c51bb73944e9e6636c55a9f1fc6bb20569f29c5b6f7b53966902bf3a4583b37a7fea38e4f65145bfe89fb979b2aafa2585546f6470dc512bd9dfb3705c51e12e18d24c61c1ffa897de24f9aa54b590ff5c45a91b1ebc852cae9ecc46a5ebf2144c65f8de4c4fe513dc4c6c84d6c7e214a324cf98851138bf674c8f834124cccc412f949f22e6cfa0431b177348cdd19677a849758d5373b36840ccb134b6ca124a6fafc71f34e2ab14c6ac817663c544d28b1ca58aa58df603b9149ec3978be4ef96a6296c472393b7fc3d91d4b24f61836ce94cdc89790d81e6720df971632788f584dd4d374ee1cb148ce31e3f14979d93562d5b4fa59131969ea18b15d48c6304dbe936d8bd8624e3925ad4d114baa0e87b192e6299588354a82c6fc78b43e64109147d499c6c0436cb9f25583f1943cc4107bc7cae8e4d1603f2ac4e63f9e7191552127c4fa38e61446a3366dc30c62b15ac9e9c19c9e2c882d797566673e106b5a70b8a13e20b693b5cb7c12bee5ff61499e522ac731ac96ef87a542cab519a4f8efbd0ffbcdcce8898a65c7f9b0398e347dd040d53f7bd8cf51aeaef9e861cd31628d67d967f0c9c376174efe73f00762e361ef0eb6295ef4dad577d83c37cea441fd9285edb06eacbe6062bf31721dd658d1a38427cdc9603a6c17c33236389fcdcd1cd66816b476ac268e460e4ba5c638492a5fbc4b1cb6df87979b1f776b81c39e3592b78df2864d42ae7c9b232319ea862d9949a4998841fb6cc31a196ec4e6c986c5c3a5feeaf7e99e6bd86fc5d1399028614935ec1bf3b73e1766d54cc38ec2c7eac73b4234d1b0a8c77f18d723c68f67d83a95a743f918d38666d8d16dec9fa95f0d6119f64915334c32068e2464d892e7dc17a28a448e8c618fd0f827aa7374fc8961cb1837ba685b09c3baf115352b0d65b602861d68482fadc6d50f2b5f583f2cdf84a34891afe2853d069bffaba9ed5c952eacb7c972f0cdb5dea970618d2126db88ff9f9dca16961c336abda6a2852dc5eee77f0c246ea86461e9eb0e15a1bc3ba382854543c7a1a7ebfd6e942bac9e32d3c7186a217f2bec21dee57421ade6f3555844c23fa4b39826fd545873755aafb89515fd29ac93529a87be558d7c292cd9992b792384c53e0a5b10930e26b936a70e14f6d56d90b1c3c7dce927ec316d0ed9ef9dcfb413b60c3484495d3761afba88a9193bae6a26ec388ec95aa545a37a096b8ce5ba5b0d6f1456c2de1f2db2c2ae3a9093b0a35ac993cbf9338891b0361ec9cb1834bca839c216ab2992e28f34678cb04c76a68fc690f12fc29e365a8f873f693c11b6aa10266cc6b13e9721ec733392734873131721ac5fa7e297813548294158aba2c9e7a3924a1520acbf93243da3b7a7f283a59269ca41e24bf33e58ec41a6a9dceb9bd3832dda4f883c2977f0280278b0ff5ee5f4c8e7955104ec608b19c97c5d97851045800e56cf4ebe9d6299738a801c6c716386b312bb41a508c0c16af17a93a64f92ff164b94ebbb9aa8e39fb4c556a16725324acd256bb1a4eae30fbd239a91b4d8828626fdedcbd9c859ec38424cbfa375a991b25822ee57aa3439e283b158d334d07218586cbf123c743da45a5eb139cef738cd53da892b960ed9cb21e63851c3562caa3943d39aa3641356ec239ea7a366154b9e942a1fe454b147cf1c5224f865ea52b194cce5b89ba262cffd382bc2764cfd145b2ae98d8e7ae41753ec5024efa224e52ec55af1657bd9513384146b7408212d1bc51ad2591ccf9728d6aeacd47741bcf7506c8e73e5301a3bf9028abda2846838213dc027f6888bbc1e32ee8b911ec0136b08d188121bc132d2037462bf0e1f8e7727ff3ff4009c586a37a6f90c73307fe80136b167146df4a327a131f4009a58834e0cda251d1eff3c4026d618a283ce31430dd1cf0360e25cd1559a3c7e8965746f1f68f949d82db14666485cf1c9a03f95d874e74183f8bff93e94d87a2a04e90de5a13e9358e6335dc836b0981d49ac12194d324b0fad3a9158435fca641907124b06d950a695c236ce23b692b80e0fcb31fded88cdf6e2679038315cba117b1a7b1cc239128d3523f6bb48760f6c337a5ec4be92515e6786e96256c41abd32ce4bf14146e1442c5d95923be39d451811dbe5efca9faa0a0e3ec4e62973621b9ec96e0cb19f7ea67edc2863630ab147d1185b497d326208b1effe4c1895988e5306b1d876678a91d151b40862ed2889bf890c2a5902b1d874434d21d7e7ad006247d3402d7c472b2a7fd841046918aa3622ed87d547e3428ed13e2c65b63983101e68a87c587eea91e7b29b1ca27bd853a6f054b929744ef5b065fe6dd00b396ea779d8f3d443234de261c95ddde06294e79a77582ac3a6b046da289976d8b74e4d1dc38e3dc93aacc11ce859ac250d493aac79266ef525dda8720ecbd823094b87e96694c38eaf2e73c957d605e3b0a9eae71c9dd2540ac2614917464ced33e804dfb09e45eda05b13e34337eca1a9438947a8aab00d7baad439847a663c13362c929ea2e73cd0d39035ec9df283454ffa713e35ec9dce2a04f5d2b0c34819f94af09c3e8686ad4fe28e5e3890a89d618721671425e59d5eccb079f8e47839c6f0c132ac19aed9655a473f293260f1315ccc498d61ab5249763a6993a4c4b05c9fc5ad1022564d61582e05bf702b816139cbd9d028cfd1a32f6cea31392af7331a79618d379636560caf88b20b4b8889c550f2bdfb482e2cb13fac9ae5871b1fb985cd3ec3c38ffbf8f3482d2cb3ab318ce6308f31320b5b4e9744c98f852df25fc887edb4a9bfc2aafb99992167f5f456587a52491cd3d4cd7b15f65a4775eb337351a7c276e2b03b4e3e85354c8f79752c8db814961c42dc466cd0e88cc2f628eed677070f00852567e5a4691e91b7830778c21ec74b6e5732e6d8c103386149bd13ca77ea31b4f1004dd86f3b1b6a3fb45c361e8009cba39fdd94da388f8d0758c252398f5264733e8ff1004ad86e3a2e9cd458c8311e2009fbda4ed0289ab2418c0740c2a6152ec4048d1554830738c2de207de7c349d5bfe0018cb0e61c9af267301f6ac1031461091f62ea376f70b4e20188b0e6da8cc23d1a8d18c5030c61d194ceb7a50a61b1b5ad0b750661fb8e6143c7bbce198130a8cc907e55fcc1127d3f9e7bf28508fa60f5b5681b927e4851d2832568df65b47121ec3cb81fc79bfb77b0a58c69213d67c3e860cfdb151b7b3d400e96b2c94857e223e51d0007dbfd48a89e3ca972768b7dd5f38ee39afdce6cb1a31cfcf427858f19568bed72ea39e9ad897ad16293f39861ca29eb4ccd62cdd395e4d46b2e4e288b3d6f9e60d2e9cc73c2582c75e63166bc19250d212c96185fcb9cbf9626e12bb69c733226e9bc5284ae58e26a1fcd442b9d085bb179080f7a67e26667202b96f8d15297c370153b0a8d5453ce43890355b1fc8fa40df3eb1119988a6ded53658e1e3a1a0351b1c84f0872c1d2b7f2a7d8422ad86759340edf14cb8547319f8dec69bc148b65eaa6648cc7d049b1894dc67b2144f0948f62ebee4ca331a95fe5a2d86c1d79fe78a9817f42b18e7db24671506ca9f6fd199fbf95f38975c34f94a67e8c7a3cb1060f693431e6957827f61cb5e3f943d6d6e6c4a6d73d12eec46ced4d2c55e52867aac760d5c4269fda8de44c2c5965d921c3fc39c29858536c5fd2de5c624b522b49631bc56f2cb154ce5f1a3661276d2ab1afcd9de7891c7e6228b1a7cd172773ca24360d2158fedddf6d8a24f68ce9f651c550566b24f65a554d9b3435c50a89a5ca1c84e4fdf853f4118b6f04d1305147acea20a9545a6a546923f65c16733ac598349a8cd8c41f36383dbd1ccc45ecf5b86625a78c7ea522d6d47fb19f730c5a6522b6896e9842c768dd48442ca9f364975f66f8e3219692d5a0a325653168886d4f52646da7a8060bb18f8664cc2135981c12628933990e574bb627835852c56ab89489a113416c97cf5278a393fa9040ac9b32c6a02f425f0e01c46adb9b72da8f19a3e40f7b9e67caff5ffa7d7e583e2744b4b895337d7d5822ca91c64bd78d727c583544da4e92f27ef4f6b0aee4c438793e76e4881ed6d0933d92e7618d25294dd9a7fd0f1ef6483e216dcc11efb0f7895dfc9439d8d861eb7e541ab623545a8735a409f61ff61b11a3c36a974e3b836a0a7f0eeb6a8f8488b127c672d853488efe99b451340edbe795e4d168f37170d8c17e5c6b942759f5863534ca75e4b1ac23372c3f52792449a87e541b3687314f88bb7131cd86fde397e4dfacb0f21af68b5137aa4a3b64d4b05cacdf8c9deb23250dcbad57081d1f693e090d7b681c2c6784b49e9f618bb6beda2985ca7410332c5d8e3393c668ee65d81f6a6f49e8c9b05d74905e8e1fc30e76337b636cf8ed625837e6a4214489162d1e861de647a99f622b630e8625d337befc112b5dfe854d73de65c4950ef3f1c2623901c730620ff37c514aef2a52cc2296c8ce69424e1a45ec0f75a2f67188bc9f49c492f930fce9a790c36610b16cd09eb234de4062e610fb7f86863146ca81650cb149059d8d9de12ff885d832c9e70a652a51e2845873566d79dac66cf8205629499fa17daeccb720d687299c4d705c9f7609c41a9226c79f9769765200b1f4e41b1d89e89192f287256dbeb55011ffce2a7ed8614446a15921e51c953eecb8e1a4d1eff061e9895c29ead54e83f7b04684e80e25b1f662f4b07a074b41336c8798c9c3bef317d3e799583178581e654926b3e81d96067b3fd1f234c8286a87f5a2247892681df6b878d31d3e3cff74d8b3635a0c63153f3e873d23f198f1e54c43510ecb74f9e6cd30e16c8bc396d3a598b995983282c3a68f71bc9442649cbe619d7895f2cec3ba1aea86d5be472337693dfedbb0558a0731cdace4e4b061b91cbdad98699f2a6bd8d226cbbb7fa61af69c274a3d4ea661fd1f8719ce4e37b81d0deb679cdbdbf29ee8f20c8b7d4ec6e1b0ce264b33ecd133c6299f858a69651916f9cc49d27888c1a724c36293a17fe5f5cd9d8f61ed5a9b50e56863c3c5b0e6a4e1624d8361d8a266d81d7167be3782618bb5db195ace68f1c62fec33293936a485301bbdb0a379dce9c2966b4246611d1bb5825cd8ce2ba3989437132a6e61e9b8dca892a8af03510b4bb060d62103adbd0966619ba8d28ee9195906211696ca46c922437dacff0a6b55c6f9f92c6f4e6d8575d3fb1e63183dc67015968c4b2337373f480ca1c2268ed4f174660afb7f0a957bd24c8f2a85ede344d3c8eab1948cc262de9db224a7be0d42614f3391affcec234dc813769c7bfbe96a423b77c20ef3520acb9c262c66bf377d1f1396f9e495750d3245be25ec713a1983efc7b2ca296149df101d79f549d841fe10294a277d4591b006497d65124d37e38eb077659857e1c633a233c252a9518458a8149a22ecb5b35e0f744ea226c21aea828d444a589587b003c98c34ca6e798c11c2525f31c3f40d323a084ba6de182e7f8647251096f1cf30c2564c57f783351b6ad4985259a1f960db8956a9bb95aa523dd853f014a258cea011321e6ce291a324cd6b013bd83e47cda386ac289e5a800eb60cb18e838447fbe15a400ed694f24fb49c28f6a85a000eb64c6191c1d37e77fe16ab434d66162ee2b3b7c5d2b30e3dc40549294eb5d86fb3fac3e595be9c68b19ffd87895439a2159ac5ea67612b394e165b9a4b1f2c796c4a9158ec69995327e386c620b058638a9e2b2d6af27eafd8f7611a95d017519e2bd6f38e07174a6d3c45ad582758c7cef9493e11b1623b8fbeb291779bff556c2156c8884893d8b32af689dca99a3aca844b2ad675bce17188a062d174c171943dbbbc4eb1df57c50e490d66a4d12e83421150802996fd30d628fea5d83b86c50a29b3c3e749b1a5b90af97248079b1fc5d2f854373c66c8e78b6271e0b981ffc79c1d0fc596267542ed038ac5e3d1388a948629e7133b0e1b37c73a584d8e27961c711afd934a659c4eac1b620c9d2a3ace7173622f930c2d641e4fda9b5847524cbb18e283ae35b19437b8ae8f924bea4cac65f753d561b177c6c416f3e463b4ff481bbec492d342dca45a62b5d0fce515e162ae12dbea86f558bdba8d12db77debe70d560229ec49ad24863604953081a492cd28f91a5ab901f47622d4d1548ac3dbbbf31541eb1464694aed9d06177c466b11d526f32394b23b60f9b62a60a893732621d0733e2218b58e6d641aa862a62af4c964ea74fc416613e469024229647d2b0435e6708e221d69426ebfc426a730cb1aa4daef1e4fd13420ab1a6899f642f78c39e106ba874755e6e109b7ab83a890b6253db911c2fe6759c0ac4e629efc60815c2d70588c543e51ce3868320d71f765039f9cf4442aae587358d993acc70629dd5873de683bcdd49e2a9e2c35a25bb8eeeb2fa517b582dc7545efb180bd3eb613d0d4f07abba51a2cfc3a6c96ecdfac482831e0f3b8cbbd05fe7c13ee3efb038bc48692e7658f62794c50c09ffd5614b13aa33ea6d108df174584aba629c9677a7e7b087f8142ba3fc992c72583de6ca8d466e373e0ecb8d239d95780fd370503c2d74a58abf615bd10a731437acd152def4dfbf29da86352aaef4639832946c58e6ef2b88e79c10f2356c41d7f72b6546891a96d4e5f3fd795d7d1ab6afd06192a4c9ced1b0e449de9cf4af7a67d834e7d5e0316dde479b61a994277aee285b269761898a0e1573ec1827c372314e63d8558de231acb71dab3f3a859411c3aa62b1715f09c3925386292b3560d8b6f4f3e53c29a3a0f9c22a992c839a8b3fa2f1c2d68dbc1e89478dae74616b50df1fac324c58b9b0f8c48bfdcbc9e1935bd8917aea14c4fa2f9d5a5826340852a1324c9a59d8fcd2c68dc91cc5142c6c1333ba88d7711f8257d82b2d8d4e9ad30da11596d3a825e93a27c9c02aec97fa3987daefdf0915f6bf58eb4e21c2563285bdf303d51c97c2f20dc38f66ca30c75c14f6c97b287ef2d59983c2d6f0aee2ab7bc21ebab327373e98ec841dc4c5ba3039358e69c2d2158f626ec6841da3281d92c954a86c098be6aad4133257c28e265c474c51cdd3e549d8b781657f389f102b47c23639237385a89b6cf223ac327be629a60d31496e84e5520c8fbc242fc25622b99d36a529464e8435c771ae49da1cebf021ecf511aef38370937a212c61eb8d56ebab3a1e846d73e2d759e38b290e8425c5143267dce391fa0f169bd0e05198d59e8f0ff672e4f13cc5c5c7b3027ab04699afdae827d559013c58f326cb191d6d928615b0832d265377e3ccb8152b4007cb360e8f10436ee6aa801c2cfd38537d46954ca20ac0c15e3a1e739dc7c993de62cdad3189e5a91b9fb6d8bec2a74e6a195f2a6bb15fe49832ef75860d69b167bafa9b4e31ea338b1d754c8988f37d18228b4d5384b514b527a42416db49ece7111f8d232149c7c94477e4153bb85d47121f99c7882bd614cd8b7e0c3f3d482bb608b5bbd98f157beaf570a531375e6f155b86abe937f5559e9c2ab6d8d4798f5652ba4bc572d531b9277e4e5da1628f9571c7f4e19286ea9c629f90142b32ca147b0c1593a71c078d97623b1d8dfaa9d2e69c144bc830e7c60ddad7a1516c71e3a428bfcb4d9328968f1c954f426caae88462d59c63a894122a6fc601c5e6492e45868fbfd2389f583d4cc641abc38def8955f536cdfbefc472f1626c459c649ae7c45299bbe2fda938ee37b17c4afb9c51ae893dfcc606417272203999d822c64fce9c422cef6062fb92780cad73892d244f51e38f4ce6b425f6198bdb09c9f6c25d89fdd2362c4544cc375362952947d99dd1250d4f62ef18613ec7b1f41396c49e4b42ba18e28ec41239e7bc9b361b48dc9058ce3ce78ca99b9cc1fd882dcca61ce5724434b81db1449a8fc89d6ed26fba116bd84c4d89916357d38c583a864544ce48f3677a115b08291ec66684cb29ad8845baf4538670ff38a513b1038f7c8ef26394cbd2885852081f5b29967358fa104bc6ca3039b633ce4a1b62078e343772daa8a37621682039729da784d82f454aef8839c44d07b1e6af3efebd9cd25410fbc44aa7cae9df280dc41a6c52fee6b28c7902620f5a9bb3db319d27ffb0740ef59989609a4e3f2cd16023a9858894d987a561a75fcc0fee82c987fde63ad7694d5724f7b0449e9033a9f4e62cf5b0c60c3f458b49cba4ccc3aa17938a6674f778c4c37e133ea56eccb972b0efb0c389f5892926cb19db0eab4857494abe394fec3aac5269438ee9b0c4e694abb9215e6c0eab7c2ecd8e97e22f94c3e2683e38c8eb1036240e6b663091f13027c361cda41ad3b86a92e70dcb8590a16e5969c4b8614792172ff7cd4dd8866d33aa935fe9fc216c5825a64b521a7aea352cb99f41bcde6d903b35ace1a257f4f81f3a9786fd6156686479fe618686bd2a8ccf9adfe7adceb048fe34d950ff936d86fd4b3c87d775984c65d8420edac82e4fee9d0cab44c83d09f99b312c6329c73cc2579262d8723dccd049a395637418d618f7dff5201efa60583d9437a81c72c2fd8525c5c7991f529c49df0bcb8587f1fbbc0b5bdc3c1361762eacd13f39ec324f2cbe85fd626398464c86e1a3852565d31c83b0deef6461ff181ecaae465d76b0b05fa8b2991c827c4a5f61cd949163c6cab3acadb07de658cc89d069741516c92f3fb3a9b0e4e568f138e3633d857d7767a62fdcdcca52582afef7764ff62e8ec296163d8ef72e86104361cf981a2cc661448e79c216a7123756e5ccbf386129698c27c6eda7579ab0caa649394c4f532a4c582cec7f3cda941f5fc2da25219eb9e1495c95b0c4e954417334093b8a29fe420a364155242c65e5252a61a38749028eb0384c162a4886a1159200236c7ed2d31bc276d59780222ca923fc24f756e3e3041061154f21aea5ced2cc710286b05752cba87e552e739c0021ec0fa4e2ee324a548e1310843d1fd9454e991dea710280b08414adc9387f773a4ec00fd60a5a3231a74f998e13e0833537869a71875f0a1a27a0079b75ee88996d0c43e304f060f3907108870ec23fe304ec609ff9aeda061956be38013ad86634e7f43974647c710272b07d59ec7c879c3ea5380138d8bec3f6c7073a3927bec5e2113233c47c1063886db1f76a01add89238fcf81cd2a39dbe00600a2f58b163f08fc7539d5c881329bc58c516d71d33e791a8624991c2c31c134242f924206178918a4dcc53dda48e8f1f47e98517a8583d736292c6a1a1c6f8293655efcf94185277a74db13fcecc9052b0b0cd5729f6a8d1232944bfb263a4d8a32b422efc8f7dce20c12816c73087bb8c57626e85043570010ccafe8528d6b3549231acfbcf60d4e217a158258790e1743e49f00214cb5f4ccf547a86fd2110bcf8c492fc235a841ce73e5078e1893da4df4ed468a3d2e82e926250a4f0a2135b7d6a282977c61b22e582725d78c1897552a8186b9f3a7d215d249d2319b8c01d056c0e0b2f36b136bce84a2911628e9226b689167e3ac3908b6a3951145e64624b973c85cda4626219079e5743e4fd9ed5451209000e5e5c62b9d09b3187e069a2c7241885841796d8e72fde36865136fcd645920a4c9723bca8c466a93f766caeb8b0124a2cbebb579d396359407831892d9957ca9c3ad245d22001f0c10b492c993663cf077f3495466291f4d131b936191e975c7801893d4aa4a4f3ca186bd7472c8dd2586cce2d8bbdaae18523f6699c61ce8c3cee71f20c2f1ab1d576e40839e646fe388c58620a932c262783ab7e117b9c18d7334a8459add3f04211ebf9862bbdb449c47e397dc8609365a4e15210b17a6510657cf37d69fc105b4eae8de5302feaa986582bc46c824546131e2cc492616708562a19a4d458a001426c5a13bff142b8a4497a41991783d8720631e4575e8be4591749242082186dc63087a549aac12e925e70825e415141c18b40acaae1d693e72b38a38af002104583177fd873f4b3953899469d7ae1873d324c35890611e6b33e2c613425c93036f3dd860fdb3786e17266906190bf8b2412ace0a4105eec61b3cbcf61d2ea6d8eea610b9f0b639b1c85f54e1749e71812ace060105ee46187db30e307cf94e0380a4810033cecc11c64a03313e793683e787187e5c349ae9fe87a1cf50c5c0524a8810b605088082fecb047069736e2790ee509fc057a012eb8185475d87118090f7aa2a3137791448215c0400526a04ac20b3a2c9954477be2c40ebbf8094c0ae6b07f8e7c716b71efec413c7821872da7a3e7788afec6413376f0220ecb4a04e98ed520ea3e5d249140052b18c405172f40010a62100108a840035c70e1ad02ff5f01175ccce1051cf628be212be7d18ef9ee22a9b8e1c51b76d420a73f43927b90d2459209000d2fdce0dcc3fbfc1479b1c28b362cfe295658c5909b50cfc055c086f5bfba2f6c6688fdbce0054ece021380195eac61cde82ce34e3157aa8a6af1420d9b95747430e9b0348c5d241d2f46bc48c3f2f062d48f8dd58d9f857881861767c0426692eecc2078ba48fa1590c08c62811996fc79c2a414f57b37c661b0021990a0042a204436881765d86ac3e2a71ad50ce32a861764583c3f1cc4f0f74943ed22897ce1c518d6bc35cb104bef942c5d241d4f36bc10c31a2fc42ae5073f270a5c008326410d98046158bc4159f4faa7b30c0d0c5b659c3279d0989c097791645c40f4854dea33280b1d63cf372fbcb05d488dca3f1ee4adb58b2415ac40b9e0e2052758c10aba502eb8501970c1450ab8e0e2008087175d584cd2f6f24fba3ce3b1a3820f18135e70610b67f79d1aa44fc9e82e921c059c14e0820b2e4635e1c516b6d310a164733c3afaba48520ca00bf23ff0420b9f58cec0e2a701d8c18b2cac1e2a7ea7b047673a0a6000037f0162e00516b6a435938385751edbbb487281090c0bce022faeb0fc5428875ffa1721e7820b3222c20b2bac69424d9a2a999099430297010a56a035680dc18b2aecd01fe4db70631749480df0c0051ae06568784185e5ae3a055deb8731a6acc0054f822e5e1003160caa4091c08b29ac6129e586f4518b1927853d5987bc39329c63e8e8c28b28ec18874d953cb42b99264d1abc33c9a6f6842d8aee49e465b4f2d50b8a69e18513f6bdcc394622ec2289a80110680041a00103052c8881071ab0810b34805e3461ab5fdfe0eb0fe278a68b2412bcc0044cd8a224ffd754886078b184fdac34cf726aee06a12e926a800214c4e08b9020f042098a75a5acd095a156d2486ada7934e4460e63a4035c70c1823cbc48c292563a2be6dd5d2471c185111256c9a0b31ae1f4d1668eb0686d860e73a3c4616060108314e03b073c062830442ff0c2084bee78d2e9a234a7ff226cde5bead1a6cb40032040667841844d2b92e778c86826f5212c976a1a3f1ad56ff20861d5281d2b66488bbf38087ba5ff10162468ac1d08eb4fcca7f6d9153b8527c00213783b07b8e082c8800b2e880caabcf8c1ea18fa654e0ef4c112bef32348ec66b0b8073bfc1829aa5229ae7a78b05f8a85b27cfec5e0c50ef6186308f590318d4d8a0ef6338b39f3a7fb1c07f1052860410a4cf082173958bb1fa45c9e3b3eaef3841738587fc256f8fbf81d7331e0168b244f31194a08ffdb6db154cc343122d35d2491801ae0010934200529a000962e8201b558755267e9c65d000312101dbd00008d60002d36ddbab92819b398f259ec912f622da98653ffc8629d349662869863baa8c4628dbfd1a27c4a9f690a8b55fb61c55784cb07e92bd69473a24f34dabc7974c5fadfc143f4a41e520cb66251fbb815a1222b960dbe39a7a5345d9956b1a6a53d7e307529a7d145920c4ea0380906a8628fbd9f3a3b6a6f739f8a254226dbc655411a7550b1ae75557ceae831fa29b61869fec6b4c2d366536c39ce678c7fab1bff528a1daae50809b98c272a29f60d19ef73b84c6739a3587d2269c69582a25822844916dd5928160dc9931983b8dda8ba4892c10948f0c68f406001520128040340b159cc104c63084b79f29f58d2a5ac1cb9d51043de137bcf5834ceda10bdd29d5866afbb1b464ed88ce6c4e6f3703f7c2791ec79135b7cf8594aff68f36f34b176daed1e073963a49a4cac7d9bfab152e6a8c860624f36e97208cf25d69bb8306ab395528a25f674f16383588651334a2596082595419edbdb0d526253dd08192dc3d998dd24d6cb18c9c69bc3068d2496589f54c5310cd131060322b1e59cce51c6b36477372416dd4fadb8a27695c28f5843de0cb43b928e5835f4a50c53c69b4e93466c13ce6635678c581d3f8a1b42855634c82296c99f19eef9d6fca614b1a30c71120d53a30429114b0c2b13e75513f3f288d881c5c9fd9f64f1727e88fdc327ad1895342c850db1a7fe4ecf28e768c9510ab1e70b0f378689c3092221d6c69f39194d5ca9944150da9d628c0c15c4922bcd675cd8240fb140ecc1b7af6c33e8380948ad800180586387a812cf32c3e3f41f96b9b0a1f633d64cbef861d978f9f3a147b9cbf461cd1d2e46cee70ba1221fd686b92af626526f7c7b58e2585f8eb5e9306d7ad8c363cc9b6dd09955e561199b3f4751442e4e78d8d13d08a376375df1bfc33631c43a2bc964c4c70e8b8ee68c227ea9c39629ea31058b871e4d3a2ce697d9694fee53c739102c4f3a327ca01c5647291da242cc518c83123f4a9ac3a8e0b0c69e9061fc9ede6afc1bb65aef4ffa3192eced6e58735e77e7c7c8a16c6d58bd7ee341c64b15d161c33e9b3bcca488d7b0766ee3dffdd5b07e880db5535506319386756432c44ea2924c336858e6fbcce358ece59433ac75b521e5ddafce1334c372712232580b29c3621beb62bf716458257756a48668dad0c6b0c7ad3c917037922a13c3bab1ff1c5fa7c2b06aee10e65265581d074393249e2735f90b8b7fa806990cf52cf4c2be62e141a3415d58d28710c7ba739c89a38ba412a8c0042f70410cda5d4002a4129c9dc0202a30800b6b79ce0dbd6a2ee474749184f40cd8c272392a95c687601e1517780a48b082a3236080164e0fe1f555350a8cc3e0052438010a62c08420f080527e56a082634016760c6dbd43deaea8cd5901098e0a0c096860822783410c30400313bc0500080cc0c212c252ce290e4b36af2403222081081870852daf6e860a9ed67f7334062403222041081860857d3e9a8ee6acfc9bf22aecf073fa509f3bc7ca5b790003a8b04c06217dc5e0abea2853d81f67b4dcd9717a7d94c2fef5382544bbc9182451d83a626c183a74c8d98603180085ad3ee3854b9a538ad43f61077f7b9bfe710626b11316bbeaba9c223cfc7c69c25ea931f2a829ca578c3261cf172dcbe7c2252ce1ff743c592cab8e28618d51965358924bff86041890842deee690bd0f3673b091b0a4a39875e93b837b94236ce981a94e88f1de4c8db0a30bd921ac995cae598455c43f74fd451b4d95084bbc990df96c7b42cc86b096e58784b0a7687e79ca736557461036b5082162f2e9067120ec20e332cfdeb578f80fb64e1e0fc626c689b40fb6080e6ba363701b323d584b2e4f0e21dfda5478b04ceef0a82bddc15e1716ad73c8d570ea6053f1b11453e8c48be5e0a918561fc3c73300076b6d3eaa9a90b18cf1b7d8f3a4f0f90d7463c76db1a43c0a2134ea9474bc16ab8f75facdbca7233b2d360d52f7fb17ed2ff6596c71f229ea850c25322e8b65bcbcce41fef44ff158ecb3a9e4c4237e7574582c758db7a256bfd7f357ac8f61e54d39b92b160fa6714b4cc54ef256ec79316568ff3879aa59b1deae6d8ae44689bc8af574673c1da8a8c4a862c7b7f321c5907661928a1da5aa4a75944a3a878a753d23d9982be568df2976e418a79d1497d4a3638a2d53d3c70d19a7149b9a68a6b0cc99cc27c592529cdc4a8e6289f86b192693a9ea8862071e345dee878c3a1d8abd52ca7d94c9d16750ec93be6193570a71e4fec43af9d5e13ffc66baf7c46a395c5fec8f144f3bb16ea4cf29864e6d3827f66b7495ab1f3219b689a53a348c9a2fa5fd686275dc38c6ca8ccec40e45d567729e31b1560a193c367cbcbdf325f68c7e42da99e81e0f5b6253ff1434f3757478732576188d2c7326cb7a664a6c92b344ff24fb3ac293d8cf6b2e56d4d2183c96c49241ce4146277caa184762d158954422df86943124168d9211f9e02b558a1fb14c54c6a6d0e91c8b1db1e359556d94aa4ee3a6116b574c6333a3dee88881a844c7c3c22161010141c1e0e0a04060606074ed3a43180800000463419023511244e9031480023c1e163c16120e1010080a0c0a080a08060a040004060604080006060800040400060608e01193106e00025a44a1e8520a8b62820fa961834b99f6b917f1673915de9f0ab5a9bedae966be543a985d1e661d2fe43cf5c0b7316041545642de9af1178bcd3a801c76354a272f2985d2145e964ebfc952cdcac9ca79ea314e497b453aab2ed292cdc6f4d16a59f8699717ff12978530f93597ba65aa6292af40611dd1e312c801988d1f10f392e8e73a92ef9bae42d8298dffc9ebe3098265d241e826f965f620249a02f5cf29669951bb3333030e16f9ecb2710fdc5bf616ffe4187b1d1230ede51c38ed24864727d44c2c60229aa9d42be91db70fab943e4065116c1135ac7f3a270ec9274c123125e2b8cafe454da6c05397b2f88224f516799844975a5a704559d38320c907c5677b31e95caa838515ad02fd1a81665f2030f0fb8c0775cfcb50ec89090e7a50f6410b6908d9ee0f50dab9cc6cc9169abd4e86bb2410d4f2995c8b151bc64739aed26d05569bb6a8c7040d03a81bee8bbe3770e90ddf517a9e72436171ee02fb223bd84dd046a6a1d790c65ff27081acd5e3555781030b011751e6c067d0822a32907841844345b29e5eb04ad13609b5760159546b76b43dc6b264c7f25920a5e974f0d6589c1b0828a08ea77eb25f4b7ddc46f159205cfe2c4e0babf8ec4dd9045d83f25b91544aa74694a654201b5af50b73f860fd926a576dd4235eff7719e0926b97d7a4c52b667540efcf0e611bba3fb3f24e7ae24776e775ffdc15f818dafda524faf0590ac466fc69118caffedea723b5c701b802856118596fe05b83c97ca796223e14727b99730e6e5c0e1225235c55a5cca7710904e75f0ef9a65d2e0f71c55cb5156ca5eb1aa6ca12a57acbd594b9aa7bf62abab3ec99043fd20e89ff796852be7c554c637d8e37099aae14be69500467e674b03cedddc67ab4948b1a7a087fe014450669da4a1fa39666a21c0c4ec60974f58d6313346731c5fa8d8bce872f2716d2baa53851f265bc155a8be2b14ca02594493294026ecc7986b0bca5f33466acee0d8f0e6e1bb38ac2fe2ae9001c1614a320b4a6df7bab1c176bc400c313e9a9f91d1376eb8d4fa9dd80721a8b6043f1601a42916ad2776d1be8a16e2e29a4ab0b6de6d4a08f66f6a07a04efff2abf12c635db7b5ea277f3370207f599577a79ddcee44a71132325ce1b28b01894c200f733990b6b7de23aeaa7df7b37268d8d67b0e2f56a7c26dac1d6ef36bcef370ce5b3ff2d8d245fe8a15662afbb8edd0e2b839fd467bc8d5d2799acf3ac25d00d7ed8660d8ea7d8fb5fbd20bba166424ed0e82d8af1b156d682519c32cb61ce161f46bc9a14a7cdca9e0c7f4cf6be2d0346a3f8a6afc8c992e582832729160f1d883c5743ab756903b850c174a98005b85c4674c64d680927758fb36f8affd40785114ca363f7515250997d7d47053c808bdd1dcc091b38e119ff75cb7b87a4336ed92c4174f3f3eb4854fdb2dd16460d8c0004fb28064e56481e89b16c08e715e78a93304dfe2373a8ec4d63afe24f06ee9325bf18657d85b8b0d4ce50c43da93e04cd58014e4d6ef70769c9466873e496cf5154e080e85b86888622a3ce1715022b5f28b40a0a7d7a172ef0b93756dfd66247e4bedc84c7941a8c1b07fe0f4548e696463d6e5c86c8ade04de1b8d25fcb6e10009f0421304f3751a47fe2133bcee87f89b063451a4b58a6609286b6092f1d639eedb5a06bd1dfb996831bc4276d691535a5c2403f22dc0157f16db7eedc77a050c5a9dc37e389f5bcd28b1e7c0d6c442a7c4d8a09ff83dc51f899aa4db139344599916ca6a99b5df28fb157161db5095393e7deeebb85782958fc748016b340150b73e9e80a88d0d0aea3e43183e74d9c9808233cc3e28227acbd538319e3085a73786bdf5899337f23c1370287a3fafbeda6f94e90af02dd6da13060e8e06425976a8e60c9b4792df36ddaa4a9f2ed55135d84cac94bd496ddbb36162c0cacc026af234ee9b28aece305e1866102a48eee0fd41fdf2c030aac4cbdb3d40f84acbef731830dc11a388aa5a979e649a5db2ed3a9cd080bddb3b537b9bf29f89b3b6dfa4377144929449c214ff4999adeaeb23e8a2c86329e13af36db025dcd1d35543f47614d2e459190b6254fce4d2a7511ac1a857aa98ba49469fdf7855e152d6a775f6eba0c9cc50ae4c18a191d67a7b783e905a2c72d79d2e7ea7f96bd11f40dbe97c667dd7477f8cf343ec3fc526a6f848345fd45e8860627f294220ef0d02fc659c1468ec1b13fa527290b29920682ed980a75585b23e416e7657fe9c241ebade4978b6763d9874a9f92ab3745e29660438934a555ba91af89c5dda7f9e1e1e2608c4ff0a2f2d8cd93ddeb3337f8af9dabc0c218022ab52f63f074e6e4d5f3fcb0fb0eb5e4ccc3be0574c23c2fde1ac44e6e44483d6256d34225e1878e9fa09f26ba86f001aa38df59fe061792185a7157ba18859355eed26409bc5259ee2958f9da64323abc85fdaa02e2e406319018e96d587127345377c92bfcd7a568a511c598af1d3b3b2122d15d5329791fa9e4ec68391ffe94e42b9a64f1da904d428f6d2a2a2eedf952731e43071f2b234d14a35fd310677bb516d4e13ce22395ef116b42ceebfb24813f29494cf25587ca70c04384b5b2c1152ea2b171cf78c702675011ec7b9fd0e82209b1a43ba06cc80ea044cf82f302e6dfc797c208f29af17692230194209bf5c5742a9713b95df8aa8b90d677ff893f70eab7efeb9a94a5863a3ef936e4dfd877391f2fbd5d25cdba7d008ad1ad4e208965f69204a1698dcc21098b1bd3ef48e5e4593a92edca3193643b95bcbad13858a767992945497c4a5750da47a97b4a6f94025a5b299869fb2b85299d0e57128bf4350f7475b19baa2a8101b05d042b9b8e3253aac3539f273d3d4be2e986e72d0fa0b987ea53dc771fa1f050a18a540d4b209e878a54274eb56dde3b4e38924b3a4e441af9fc7b73e46a8f4a55a69caffc41995206af8c5306aa2c34b2fc9d47bf7998366798c195f7ca83cba6c4dc9f54f2830e562c9cba3b8452670012d692b51d110fc57230352c6d69c707c75a0764341e8dbfceaff16ce3d7cf1ec39c856fdcccc6ae77e10a2bed316f24876153e50f8ed122e95e00ab6d643e9d516723b3e98c32f389c5b3148b9a31704ecc0e2d46a36861083199db4c73b8ca1e82897fa8f5df60b51b150ded2d60e1fd42740c5ebf16461c67e250e58685d1486bd89db70ccb62e0bef01ec344f185112a728e53902e8c05753dfe0ab540cf02a08f852156888cc1ef0ba7048621c64c91d62303b93cc3c8fd68f01950f70b2378bfa181cdf419ca53cd822348033acbf3a25289468de8c19be0bf0269ff3269c4794f4c5fb2549b64f00da4df843ee2219713f3ea986b5ce444b5aee9d462577ce0c2e1d72909347dab80f2c5a67ffefb1987427568d3a3adb6209c21fe07c946dd8bcd853828195edd6e78c2fdc51324ca9a0003744638943fe40985dcd21c8f8640e6b074cc02caa2cf5228f667d92f633bb49d14c7f10b08a9028a1eea4b7d9af2ad99b38aff75d4cba87954e9eab9f47228c676410dd16635288de73e3c34664cd4c8e364ca0a2f184825385507a6a296ab5e9f267035961b363627f566522382ef2ea365ea33d14e3f27570f1d07366e5caceda4341262641e2bd17e6775b758bdca8a09e86c424a70bb25dfd6b8eeaf6bf045cba9b7abcb9b49f8343c916100dbd89a90a221c581811f03172d44f4c8a8911019009e9c877c681078f05216f69b35e1e2c7c6c84f38175816e0dbbb1d9d3157e889fac3c443a44923f7ef548ba9bfbcabc99eb7d9ae2f8373d3c65e814b92ce29522ab05123a226ae99ef893bd5720952049872ec668a3e16e884c8830e15775c9cd4dd368d92b95172d23636db4bb4b3de94c1108375b57a2d19d539120d418f01047d56fd99dbaa866a5f589afabfc53ddb1a9ec8ec62abb85f39bb6eb1a31436a6207633ac37499bcbad1d9a2839361b0bad04e6596a1b5f99b7719c87513f13c31041a69d380d4a9c9aea006e8e2ed7f7966c20976079797d787fb9399c8f0bae5524fc0fb1f8134fe6512ab9be4824bc3152dcdc87f3e33eab111ddf13157edcd93a4b2accdd3a2041a66cbbb78312332bd07c6ebd30cab5aba02277e2018fdcd5c40b1b4924ee17572707d7f6e969532d8abec0fbc50903641a768e014445c20d86b2f53cf77f92aee3a3e4480b2d146ece0d1bab5062a6c2ac14aa7ae5598ac9371f1dae6f2ef7372cf917a7ebcbf0b0612e4fa572c7d0c3f2297479db9026461484c5bbcbf699557ffc3dd1404e9b545182c05bf0a71122941d5eae5f6f53a3a54e4991e6707bd3483f3e99f07f70ece8fe70ad2d504aaaf787d76776df2528196055bc319273c724192add06b1844782e6f2de3fac77276be3c231d55ad7dd78f74747d7eb7b8539a01dd8939410151102525a0464884993458ed83921b2e3cbe9c9f1f4eceafae472df449838a3c8f4abc0cc51e53c29062a1c2a0a405932251eb16758f93c7e7c3a42e68a29cb383aa60ddb611a0d56787774bfbc3f5e4e1a445ff2930a36f1fe747373bfb3cc1819d61eca90fdf1953ec5823133d3e74f9c333f6376e284b1f95454a58793a0368717bbf9a0b1534c7859664496b2644a34c95a0d50c18bffef6f9999bf2884d0f1e5f526779e7310cc1ddd3ddf1d9e2fef0f361878c2c33e748ba58483fb59e4b05ddf7b0007ac5db52ef6171d8d4ab08fa73aa682c1483120d78af89d42f5e2e0ee70263888dcf58a87ef9707c7dbabd3f9c9b9e4b0cc6e0a4337075683689a600b39b83d9e1dafa7c7a77321a35f1acd29449b92300922c53e797e308e0e46984859793cbbb85fdfdd5de916909cdd9ff4a3cbddede5fcce1a957a383f381aa024d1a04d91ae927f71beb9b890cc2cf2f80330323ef7ee748a7c3b3ae43d23d09b88f91de7992dfdfc7a432483afb74d4566db1f9d72d86e6b89b131363095522637614306a68c0c1f1fb15cce67699f5d8ececf8b7d43ca830e5efaf1f5e0e0bc3d3a1f9f9f9d9d5ceeaeee76fc69e622aa081ede2f6ffb8d052ff23ec5cde1f5eef678f7fa3a39391f9d236b5d078f3b1fbc3023a4cc6183b1a3925f5c26b6a36d9a3de2c5a91d7a12a4b450325b2c083e3a3a3e131eb66cfb2668880d45a5709319e2a8a17946c60e1a99333f7ad6fc900307e921b6b48886e154c22bb88f43789e8307a7762523cd56a46834ea7faaec173b629484dbcbf13196f4296952a0a2e828886c77d40d09ede4c5f3ede9e4fc1c35faed60c3c279ae0c29378b4146144205727c48b68fd58f16dae1d19d313357cbe683f3cbeb4d6ed685d3156be7e4beb8399e5eddefdfdfae6e2e7757e7eb5b16ae645d6dbfc315d1a772a3d22d302878f0a85403321a35c9089dfa35155449cfa24753c984d175e1f0f87674757d797fbdb9b85e9e5defaf0f6707a7a3b3f3f1e5edcefde5f61eda92b5686782dbc91a9bfee8767b83ae0a050d0f33f7fc7269422121a3d38f4c522fac0a196912442a9dd92ee76a881376878757a7c7dbebd3cdc57976f6747c6e9408291d4aca34e9d1154a17d27b1025212a3214542951a50f4f27c787d383eb6e570742d9a6babe3c5e5edc8f6787f3138677f5358179f1f1f4fa3a39389e9d3d1d7523331c10009d7b71beb8badfbbb4659fdc6f2ee7d3a3f3737304643f7d500db616a24d58c98e3e6ceea46488047b639963c04b458a6dae5c10a6234c8e78767e3e3dbb5ddfb9dd5fb077c93a2a8ff3d37716e48cbb6b0b2afde4707c723abec19e02b5ce1ad63bd52bfca3036c1f91b848029d5fde59ceba0d0f866f793db6cf5dd9c88e8c90e8890713f4cc4d9bec1df5229ec093e6cffc26c838a1e9b7a6b8a8711386183c4a4a650acc788fa12c194a3a99affce85400d5731292bc635e8cf69a0621dc5147107430b453cf96492615c038c0e460bcc3a431a16414ab18d55b4086ed4ac120c0c060f2618260746104c02c3153649a3015613a60ce60fe618e605e6132603c60d23121326c0c40192d8c7018258c441806182a187e9833985f9803300f987ccc7d40866c67e2f8f08479c260c37c803912067640cfaf531d411a110aaf7e341e0f01326f6e22ec1f72426ecd688f689e63a3b95b82595a38fbc86bd2a8d7148208b80a7fed0ef236490be9ca14c22c2a363c4ce1c1491be2d9f95f404b98c1595cfe6eb3416c82a2d581f86048e6585dc72c19387f7636098c888170688adea8fddf93300f993b61bfcb3824270b386fe942b62549293f22855e09e987abfa351d5d3c58a86ac2f5301dbab4b50c6c8f0e0d25d4e0a873621631c3440359b2048f50f4aecf00d6ba37a0e637a02523d2b356ca9e9d39918c4b88a2e768dd1478ee317523441b64a184b9956f59bdc9ef867dd6fae5143914d1d809f143ba9260fa0ab2049eb60a2c40be8a866426f45964011b45767b5d84679c417083cd5b47373236c48b928756f04d6b814cfffca634c85ea25c4ea1f49101889019331249ac308e4bd7e14a62d9715b1b0a9bcaf804bdc33006ab1bac6e9f1dfc1f57a7b9143024272a27ed3ecb1a03d95af2a8c0523c49dbe0166cb4f8a5b066681fb88489772673010dd63f2dd1dc5e1b2ba1e79fb49b44cce40813884b99a0b76719c5168673ee51dc2e507c9e182a4bc598cee1850aa3e9e3e8639e4297e1142e645962877e8037efb0c198ffe9a05a63fbccc3b2658638885227721f513946b5f5b58ef6711f36b6cbe301b68b07b00f42f906509e66001c4b19eb2299209aed6e7f26f9951637611c330addc80b4c8d7b15a0f1399ec56ae51a7c4da69f83170a465357194bfd6f97c182998f3717aa4cbde6ec15825561a4ef1d83b6939b0764b31e04973a510bc5918558068813a386010a428e5e7190813bbdca99e0477b7f5395f49f024e6884460b3660b46439330f0f0f0f0f0f0f8f1c341352db36863bc82465aacbd52715719a644a49a614096726bef47466e2834248b2daea90200c107d0bbf0a3f0b04d31b445d26c4400413828757c9ea501fcf4330c93e87b4a2be84d29212420c43706b79fef77bf739941f885108d6479a65ddfd1434330bc420049be95992fbdef45278b6821883e0ee73c5cf2482902af687d6aa20062a48cf134deec701238c3f14c408049f84d2f8938f1880e0449bdf76486dadba3eb4c23801d020c61fd8cbd85fa3f7f3456d90cb8183eb6211c30f58a66b4a2155a55c9a2b98ed4589a723efed05001bc4e803dfa5946aaece27d7b4e60bde8005e01031f8c0684aebddca1e91ae97ffe2020030458c3d702674c90841490f6c0915cb245c447574f0f3c076f4ecba9c60cab5475f7491ded1175d38a0468df731c4c0039b722e19d3dd5a0789c6b8037ba537940eb9b603a3b57fbb9a99eab4ac1875e047c99c2a59f0ea9cc4187440d7a9d7d4687de478cd3322c498031b73fa4e1eb445e618fb62053852d0457b7162c881bf58316853192252fd94408c387031a909696732a7519a1a350811030e4c8e2125b99952d0374bb2b13570548c37309276554458b2eb9cfed02a165c210662b8811339b424bd177234951c428c36b0265ba2f5a78e3f42ffa165c35780436d0b0e3c20023288c186b486a474d8e5465e808b2d2ad0616c2047170c28f6458781a3dcc811c64120c61ad2daa136691efd5b63e00531d4c086b81e62f54bca3d211f5afa91238c479986537ef1d14df79c835c10030d8c484127d5e952a97cc1f002c7b9b100ab03c43803e7624a521e51cdc0594e29377f78f89615a30c2955b1d664f1636f67b6e0c0034cf085066ad4f81b606880587f70d11f5cd4a8d11fa76f680c3270294c44cecc6f18fd1f26c618f410cf62ec1cead71862e043545de5ec90b4a39ac6458c30b01e428c947a3fccb2e1457791e34687610a880186d247244b2eed3eb470d84041ff0d2f1ae30b6c4a6ad2a41e59e771f702af9da285794abede5217b8d371d2684d2217d8a8db6d766a7273fd2d3039c964d59e41923c951698745bb9b4049511cbcf02ab5f252a05d398d1372cf056393a4ba5068b94bf023b16263387c9cf685b812b1122a28e968e575215b85135e1bba2aa3187a8c058660e6921a6da4841536093a992a331660eea7529b097c44c5bb3a490e189021fc3e34ed4496a69d450e0eccbee74dace13d88fc954c8d7c1d55a27b049b3797c1b3b1d546c022779c553a635abcb2913b8f3be9cd3c9509d447409fcd7d5e41c39727b25b0412fa8aefb4af2c926810df1d24f969062882b12b849e11a27a5c449b23a022bea43c5cd9da5439246e04e9908112fc44e3a761178ed2d95f4f847ce151281ed9874c86fe5f1f44543e05253e7b7f3a4a3bf10b8f2b4ffd3247350c90f021f22c974d7510102a394ae6edd248f11253f60ff5782b611161fb0d9732651f2c77214951ef017723adf10bd35d58807ac6e8acc6699e6f9bf183be05424f5d59363f2ce493174c056249184dfe5911dba183960d42ee656656acad91203077c90317a34af98fef28b7103de52fa76532d3a6cbd1836e022689e2c32a5f6d2b11835e03da878973e67468ac5a00193524e6a447c1d9f189b051f2985f2ed2f65c107bf2c31ac8f055b6ee32122c5359931b060939a48114998eb8ff50ac6c72599bc1d6b5129aee8379ed457ff5bc1a52913d5d198163ac20abe528be8a6d12a185331bc82bed839a9d7a10a2e2bf533ea9ff649928e541cd95247af6497640645c0058fbee8a2468d2d3840811c2970000c5ed002fd41072a4cddcf4bcdcaff6fe408a3e314fbe6601bf5324c654cc1a7c73f152274edc47cc1404729dc283992e5b8a15df7400729388d75e92f9508cf3e8d821fc9bb9a5387a524f3a260d3d8a6da1c1e3cfbed0805dfa3ad5d418d6e24610728788fa2b39436bf361903015a4004366c747c82c91d849c9882550e161d9ee044ea8a20440a32c8cbb3a3134c1ad5f92124a8f86b8e2e1c2f90a30b06d4a891a30baf5103471860acc0021d9c60eda45dc4d1412c947043d1b109ee5214f541f4cd4ea63fb4ce0460131d9ae0ad7c47092deaf67767828fe17ad639c5bcb136356ad4a8416aebd08109d6d6467256f2282af71f5a557ce8b80423dc5462aa0cc28172bc09b45882f7dd30d35529c875cb875617613429956072be7c3aecc60f2d7294e0325f3368cad23927ef43cbc61760d8c84970ff9e525257fe29e9ca246150e2dd16163da7f1838b2d120d02356a4482bfa46d3d871053bbf61f5a37f2025be75970690111d848400724b8f033774f3b49a4463eb470982c743c828ba739b3a95e8c76a62318e997363a66379d4ffaa1d5885346d36d1677b4093fb46c2023381de3c8097696d38d4e7f5166118c1c097e26648ab82e32448722b88e51a485c4a042ea89036983e848043fa2134d95a7effa2822b8dc99e2e4ac3a4a85e4e5a1e310fc87bafaf68d7cd16d3c741882af4f5253c52075ef3a1f1d8560db62a6cc18c2d25660648d1ae802356aec133a08718b10bddab123a60f83ff1b29c78d67c1df3070e8180477b1ae4c7de4fd9319213a04c14955c96a499d644d203a02c19f320d5516bb362d0f086e2d6b59865231e44bdda1e30f5c6e34addba6d13e0801c00e1d7ee06488189ec94e525f4c1fd8d0e5a3ba2d6ee4bf3bf8c0a9654f7fa5e627cb1c8d6ce4b801468e3e5d7871872ae8d803fb1ad2d3d8954af57b81bab0f105186a81f70245c0b0a1430f9c9bdcaf131b3f4a391074e4818ba9933acddef0c08da44a1d63f9c7b1a4bd03d7a2692b8a10ae1df80a66dda24af3a5d775e06a3484f46c39a85f45075e3f645091a78642c71cd8aa1132e5d5aa5a47ed0d1d72604589de98c272960e2283868e3870ba3ca914254f77f30f0746cb3d698e99dba3c6e8193adec07a76ce489ae75763ba818da927bea15fb2cbc23630e69b354df48e58fa2a6ce0437554d71fb58f555b1b3ad6c0bb999498b32f439250193ad4c0d9a55f4ef70e3abc948635d7a7d2da776dfd436b0b0e3c206fe40863061d68d074943c1d96d2d3c5fca1e30cdca80c59cd3658d66b06de53d0b78e23f7ee8365e082cacf4aba77c12d880c8c6e0ad716e57f5dda18b8084208f51ed5e89a1103a7134f926f454c3555030df8424718b80cb9a2e489deb9ae57173ac0c07b9ef426625db0b7f20b8c8c3e322584a4c73762bcd0e105eeba438c49bf46bb9ec9858e2eb01d3fbea5f47e153ac22d7470814f9f837b7a3b9d31695be07386ebe56c29dbd36d58e8d00227c146865d08e964be6e80c1454716b890cf539259b592c820a2850e2cb077a94984944ee468fa2bb056f1f428175159626a054664f537e549e47dc6add05105fe4f7abaf44f8391c8143aa8c0c48ab8d93a482f1dc40a43c714b8ff1a69b92dc4ac9e4a81d31d246b0a4a59c53b21d01105fe2686c81c3f26494906053e746c1d4d2241759e743c81d1c9fff57749abaac7098cb0d5f3589362aebc37811139a6605e3967c9f732818b1a1a3d44769ec7940314d88280a163095c56f10aaab4365ba4046ebffd54bcfcb2ef4a125833cbd7b5f2fc681b12f8d5dd683a73aae3088c105a9234dd9a3f49aac308fca41482b79d6e3dff011d456025c914fa37e930e0c6d04104fe627b321173ffe9895da16308ec96d2df24924708dcd876decc14496f073140858e20343169bc09faa27e1d404873c99442744fd1a4297ee8f801377a5b2eba42be604aa1c307bc7fc7f024457750627280025b180f64d928c3025bb55874f4802fdb8b13b57f47d308012543070fb8a4238ad29126b32d85828e1df0bf15fc2e548f1e059d6303d745870e18db4c61b513b535a673c0c6939f792786365e7023c761600b2eea705499a003076cf48e9ecd5489630b2ecab43a6ec065351791f81afb42018ece61e3adbce82fba30c18dae80a90974d880d76413db7c4be65fb5065c08a2c793654e6a33892ca183069cd0a583fa175b4d3f1a25146016dca80bb2bdb44416dcb57e1d0b5ef775344b50124d5558b0219f8e17f354438fe915bcbfe44cf5e61a4fa45dc1e75edad4f4ef2afd5bc1fea8265193af5e93598502b0829127bd52a80ee1080ab00a46694d0b96217812f368a000aae03d2ba78bfebc2145c81601e6a878f164cc33c1c6317dda930e9245e598e0f57ced2be774d5a74b7097f574ecd35b82b1ee8941f763d2ec5782af0d7ee31b3a25f694e03d72d64b1541758b26c168a43832898f69ee48821d753159e505fd7723c1c8faae20c294c66b21c1ef4b88ba1da64d691ec14a52916afe9ffca48e60440c1a94a9da083ec52d2f5756cd3219c128df5cbee1b13fa9f422d8d4229e928688242dad08eef5ac35868ca823441f365af05f1c130c9008f625f6c6906123821fe59eee1a82ce54e94370d5ab3fe9df4e74922198b4a66bf5f773f72f049774b449ab6a9264040310821f15d15f8d6a396510dcf65ec5a4c6fbbf23084ea346941cb9b4da81e0577faf444de2a41c105c8cab162c8aca49f7073efae91025d2e4aada0feca98f8994d93ef09b162992d4f081edf2ee90ef6f9edf03a35349cfe0a3bfe2aa077e3c44c516bddb319a074647e4b4a2430a42a878e03c477753f1256512de81b7cf49f3438e25ddb303a3b953453ca14c9d6cebc087607d794dff636b4b072626ef31110be5f1da39b0e527a29d4892036366415850b2d674290e4c3c597ec1cc5573090eecc68eb973ff377025d2940a9153481372037f3a3d249b90eb1dd4063ea96c67e2a672d60e1b986cb72754dcb417d93570d1b2c53c35f03189121de2c4badaa481bd131293e9e9ca1d0dbcc555cd1938dda1aac64c6306de42fcb41873b61fcf9481b718c7cd926b0cca3264e0b38b789d5fdacd791d03db697abc4527d3e9ab18f8a03545c9ea583a8e340c8c7e4b48137d3345a460e07cbbb368ac8949d5fa055e628b8a9344c5de56bdc09f75327353119469b40bdc64cfb395d4126d552e30c2f26dfaef8f9852dd026f71b546639aac9b542d301ad15c545cfb1047cd022bc184b6242ab75d50b1c0a6e8e7254345afc0061f4f5a82c8daa5a915f8adf74f5fe2b56baa0227d26d3ffbf79999a8c0e58f57b0b25c4af353e0ead376c414ba7abe147897241a3fe507534f14184b551acb3a6e58070a9c4cf73e3183e510ea27707947f28e260b2d5a27703ac64ebbd72efa671378fdae28c9433a3b9309dca85548cdef341f97c0c8188296f81a279645095c14535a4f7d49e064e9d41dd1a0af3724709742b552fc088ce9674f9e35d3ab32022b5a32a98f481621e9fad6218e9e08fc6584d49522f2a1b53930c010584d9e56e3d952e62021f0af2939e7b248b5a320f012276daa241544040181d7b40b21d5e7078c12d3e731ebe76c393e602475d25fca8248a2f780bd78fac2ecf387cc79c09fc54a6679ef80499944a69cab93ceb50e783f53e36d750eb8fc92e4a91444bb5a1cb0316da58ee419d773033e93f237fd5cbfd7d8800f226dbf45bd28b9ac01674997ceeb8d393f67001a70e126b34adad287565512b498059bd362361d72b2604cc44e95ebfcd72eb1e02de8e96cd9251f5a36120bc2b091e3f4176f0a169cfaca93e4b5b8980c5fc1660fca7288952bdf86aee023db4ff2cffd2b2a6c057796af2a5a0459c147f7687aa9eb459e56c1aa45ab2433472de555c18ec69c2d949ee89a54b0961a5425a5a4238850c127d5289625a5e4163a052792a7ce21454fd26e53b4ef9eadfdb4a5e0eb7308a9229252ba2505a792f75fb39a85acd0875618675a8c829ff45992455562881105e3976df94eb388a8a1e0b2d3dde34791ae8282d1163bd31552a849f9043749976dfaf81f774fb09154bcd510f53aa613fce54d1284d29d524a71824f21493c84a46c82fd4f293397af092675dae892f299e0fc740e3a6da48f108409ce2a8250fb25187335dfdfbdf1505b821f553a2be75b093ee968d5f15e478a28c1498ac1ac3bf4f23e093ec554d5186324c1c9ceff29fe1a09feec738ea4bc7b4f90e0762d24a193a5bf2b1fc1d7644d16e48852330495de6904bf7a6ae3ed8c6082b632d5f922681317c15dbfa608f6574d4ad63fb7950a5a24821fb718728352a1a73a4430da22d6c591b816876093de8aa94292f7137286e0c7e366c5c89f744c8560f5630769b1358f2511228716836023aaa890f51704235abe9744b3ae8702c18f440f22eebfa91f40b0fbb152d095e4f875fec0a9318f1e927ee094875c49b78e0ccffbc07548b5137f4bc598e583da9b1bdbc321e51c2cc6a492693a045ae8818fd9af7a2d4ed23998075e741491c654decc100f9c9a34653b52e385e01d3865b9fa4c594515153bf0b1b3c8fc21259df55207cecc3af669f7986a313a702e9a9a93de1ecf98cd81512e2aa8d35e1599991c78c9f9f3ca92d234497160afc39489e910ea3a70e0a39da5a8d137b0297abaf8e72f1d750327f3eb65f698d49ddd06f6db3d57acd9c07d9260e9bb4fbdb9064e45331552a26a40811669e03b85dc63b14ae49e85064ed88fb6d7926b1aac33b0e5e957937d881938a9a17cebf6ea23576560fc23d6e898a6648914193811ab0e55419decfc18981462d61cedd22678c4c0559031689d4821a54e18b83411bd2a930eeae3606063b0c8922ff5bbf62f70418d593ccfd376dd0b5c4cbf1b323772c77817388b234d921e5b372d17f8dec91272faf4e8e916d80ca252f792527f530b7cbef5e815611638d71493b64987948258e04dc97cd954635ea75c8151aabe6b79f72d58acc0e498f527a355e0fa3d44f28b51ed3a2a70dade7b2cc8ef60da14b8f34f22e4a0720c5a29f0c92d96c7aba2c075eccf5ed741bdf691a38b166479d107054e5b9a52f1d34f60ef3a694cef7addb972029fd6a38dd09126b0fab993a4d86b22e6cd045e63b64ff1d496c06826e9397e0ca141b44a6045f27fdbb99f04f6935a8aeb223f942791c08f461babea1083d6f5087cc5105cebc33eedc98cc05a5dcec9955dd172faa1b50fd0a208eca6de60264d746948118153ddd39b2a6e4e33915d408b2170ba6a64daadcc4d3126d042088cdb76b29822cb34a81f5a7f63056198175a0481913124d539846801042ebf2849ca3ae507fc697fcbd12da95b8b82163ee0a4c78b9944599ce89e1e30218d8c98a2e59f74192768c103b63fe73f9dbd73fa10b40336f97745d04207bc26a1935e0b1e226891033e7bc4a0a4989d088be2800b719d94d495d670c914b4b8011364101d3c8d84686103b63545ce39a6f4a1950dd0a2069c2719727a309121aa03022d68c07bd87da45097c474e5434b67c1a9bcd51f21e9023164c175f0d4542a84d48e4d20462c18193ae295cd62b5e71f5a8f0316dc6accd11253ffa155afe033fa5daa0c12af332688e10a3ed3a458eaad7713df0f2d1cc55a118315bca5dc904aa612a59ab120c62af88c96ad52cd847c0d7e6899a28118aa60d74eec47448b05e6458c5470e942a50cee3978ed3150c1fb66041dd51d740aee09629c82133a4b483accbd54670aaef3d45bd456ce60a55230a653482985e0bfa63e2938d32429b88dd8af3d0a3e849cc7cc93d0912a48148c7bca964a6bc938c2130ac6b4e60829c74c9d4a07051b21ae898afb9929da4ff09ea3e3a931b3daa027b8efab14bb903ae9443bc1ee788a05fd2fed6be104a32267a864e229c45236c15f1ea554cc9682658c26d25bb6a3fe920cc6c804a7bd2c05b529bf9fa99860345fd2397758aeabea430b7d189d021ba81819625ca21c23a914f2a706d5170e1c7fb6e0c0034ac5b004f7aeab57b264ba51a20fad4730c4a804279e5b553c424e13744ab06af71b62e53d09c64b6dc4a4795983144982534f7133fb7f6ff03312dcc93c794d5f82f7a60e12ac794e9f3e95f608364c8d778ef9b385987704971b3435a7dfc70b7623f89cab4e7345df45ef19c1a818b362f97f9b4c2a8be0e2e6a819939260999d22b8d3a045bf9ef011ed13c15801e994b9c3b380113c16c1c65cdad1ae2d9e9dc543116c2e8fe796dae291cc148051812db8f8824722d8cc39bcdd7f63dd8f08b635724e91dc82a6f7108c4aaaa3a95dc94e22670826a61275c22c79f068290467ad1d3176cc3c6a1282bb4f3a597d8212d99fcf01060b8a0d33780c822f135e1523f5e66b26084682ce1632b49e0c3194038cf40804eb9ea97d848912952d4030f2cd64496f55fbbdacc0e30f8c7f8bb6e8bf39a71f79f881512a37c7b2b5d4dbd0078e86c0165cdc78d4ff91ead1075674722ba5739c0f8c59bde80e1142a491ee81d5bc10b4e46cea818ba2b294f6e9f3aa0a53e09107d6ccbd538cf69bcd843cf0c025fdfea54ad4d9c78a0d1c78dca1d42c12f3a460c1c30ec50e4d1d9e29b44ce9521ea20bfe8b2978d48195a06fdb6dc77ddffb020c0482071d4c1d83be0499e43cf098031f2d7b04e5515c0f397091e2c690511c60a42fba401c7fce024a297777777777666666666655555555556b0111d818002b3ce2c0e7935c3539a5943d6f8788584a29a59452cadddddddd9d999999995955555555add1c472c605016ce00107c66d74c40d225b79d0be81d1218b52f24252e929f370035715337d88071dbdea36b026294733ed49da95e078137481960d7c4a6dd12228fd937d8d81c71ad8245f635996eea1062e33a7dde82a168f34702145cfd221367034291c0bb080086cc8c0030d4c50ef41e420c16f63cec0c752fddd9baae2f67f689981cda582a6d8f9542999b61761a4e0b5051e65e0b67db4e7100b3cc8c067ced71cb2651aef13021f381a021f38fac30113d8828b2d2080c3630c7c0e2bcd6d21a877bd376eb0054460e386871818913aeaea7da38bf91e6128a648c2444c3a33040f30787c81db187935585ea3461838b66cc0c30b55c30b8f2e7027712f293db8c0266d7af3640d1b13da17fc043e703404b86040036ad47064230559377284e1078f2df04982aa0ed354abd975408d1a356ae0e8818716d8ec2c3d62a2cb834cc902db56d1b325396ede211e58e0d365882245fa25f5ca8796a60be0594004360470038f2bf0a25e1a42557712325bf0b00263d972ca66419a54fd3eb4aac047b54893844abaa236bee8a35af0a042298fa898315a58089902d7d5a1ea6288177f1b5260bfafb44dae09959dce8247141811e61694a80f0d7d17f380021fb5327f091dd2f7877c68d9b86156058f2770fe1ba3051f1596f9a2df8b63a36f74181e4e30ff8794256ffe3bff432b25306ca0e0748102b3068f26f0eb5fa7e11f9ab1ec0fadf4376c28143c98c0554e173a223a6e5970091e4be03e47580ef6d9a64dad044ef98945be9df4c12309dc066ff56c1b93ea344202a339f4844874cd273b7af03802ebfad14ec7d1b0d14d8dc06e6acf5359a392834711b8f24a0ddda4525ccbd5387810810f6d27e468a79231533c86c08b0cb2bc7644cedaa30f2d05c343086c4a309d838cbe961b02e3989dc023087cb2d8a53ca432536f910710b8a89ad27d693395bb8484c70f98949d3629d58c0fd81c4292ecad9e36c2a3078cd656883967da2bbd192584070f18a13b24efcbb8762ac563077c29d7947553ea0b0f1dd81d456f341a004178e480517639896422eb5fc4160f1e386062ef46b07c6ed5c1e3068c6a66ee3ca9216a49efe06103469e8fb41293bfb5690d386d77bbb416f248be8a0e1e34e0278b594c1bf4e820f159f0e9175b447fd498265a830c59b09b41075d766927c8520d3262c1a68b119389dcd3033260c1890e2964a9c49c40c62bd834dd3a1949dd325cc1a68c5e4982b68d6a221f5ad60a36768d4ab7d458c19f1279641c954766dfaa206315e96c262f97481a2ac850051f54ac501ba4a9e06386e829760551c19b925e962a654a66b15370a15534f2a6460c324cc19659ce24936ba560738c37395e34c9162cfd820c52b0ae112b692b2df6b9b1a360b5ffdf6c2c7fbbd72590210a3e624b4e7d1f4ba7a0f30119a1e03a47ed1a797254243f1f21031464915c2e7192e50e055facc08609bee8e2868d17a0fe1b5a9fe04d8fa5a4d0195154f4a115c67f0b7054056ad4c0610150840c4f7032e48b9f04991e7deb045f979e1355e4b6c97f192083139c6de974b35751d15d199b60d3c49c227834c15bd7dd4bbc904162454626d81d611d72ca4947d09cc4049bb946dbfd6d4edfa3bc04afaef7f93bc492e9271f5a5b708002a907199660625e4dcc29d5460bd14a703e964cf89feeecb212e32083125c5a0dbe296be8e80899049f74c85c5141a4041992e032bf6afda424093222c17f4a3a658d8d57c40e093220c1fe569bd68e7916eb3c823b0dfe49b74a168baa23b8ccbee96934ace4688d6054eee4bca21af4540e23d8339db542ba3c41d43a05198b603b5688e575f1ffe4f6a1e585176d6323204311dcc9de6f4fe9eb767a4c046f7b7a2be96f0c9e768e760ac840046fbe673a5dcad433559140c621f810238527e1915a4c936108466565cb1123662ca310bc6d0e52a377974e8b2c136410824b5a2cb87fa8a047eb41309a440effcf923b952708f664acdaf68ec9080497dedd42f22c32820c407017a4a7b8276a635c8d1064fc8109e9d3de7966164f1e1064f881356549eea4353bd116197d60846d8ae4f676191864f08115cfee792c6fdc8c49d805197be054a9dcf9734dd497857a602bad8ad075091764e481abd2797eb983e83d0f1ed857134fae1ddb32cd92051989767e134b0b32ecc0c51ff1ba4e42c60a32eac0895c2a2619720aa14edd820b3a705b2acdd5da44529986828c39707e1a5cd734be5a7fd6041972e0d547fde69d9c64ddd1403d41461cb8cea27b530e95b1b5c76181e2041970e0afe3996975d31c826c0b2eb6e0620b2eaec87803779d82d488b15479de0dec28bbfca9a48fe5b4816f8dd77d2f2906391b58179d93a879aacdd01ab828de1d324cc68c1c35702a9578f260daeef334b0a1b73b4a369b988306269e06a525620cabfa0cfc8ff2cdeb9dd3a4d70cbc8be7491a8465e083d4f494ee918137d188391a82ba680c5c6eade039bf572f62e06b93b85ea691266261e0329bbe9cb3fb8350253030aa3607bff1bfc08b70eba032c80b5c52da4759deda309d2e706fa61a29bd2ce40e1738d31872ec982ca68cff1678cdf335ddf77f417f2df01a3d585969b3c0a4f0d6cbef0a5f150b9c8c9a46c85379f7ce2bf026d4f9ebe5bb4fa61538cfceb4203aba2e590526070b11cc829abf4705b6a4e9111d9ddc253705de6bd56e82c8c9bb49810b39a490e29ae797581458ff8f904e459896eaa1c0e84e9e7bc15310abfe096c9d9d4a7fb5f15bf24ee0767b7265ea975ec93781b52c3992498826a2338193591a7563fbe9c497909e145c2530d2d5e3a7be69bc98243049e5893caf20494f24f03909cdd39e75948947e0bcaa73480c8dc004ededf9ab3456a61481df2e1fcbd8ad712c44e02be6cb93c52749d00d818f64228a090f09814f955fbe6f393ae45010584f6f166c7b842a19020227f33dd6a6e0416d433fe0b652be536bf980d333dd1126e46711413d60a3db55bcee9165f2800931fb5494dcf1b3b403fe33ab2b59f624261db05f13fc3f8559b99f032ed25f8ebb796e4138e0440e326e1a492ad47303467dfa4ca12ea96cb50db80a4a7b968d4ea15403469fb4d8bb2ef97e1934605b3f7494c7cc82d1904b7b26b7adac9105ef21c44a9e31867c31b1e0ed7458a5cff51115166c1a13159de72bf8fb9c73ff4b869c82ae6074b438714daa886c6905dfe97ef4ee54a74861051fc95c0517b384a02594ce1a9e2af8b0187289a43aa9e054c6f466691d5430f233d3988c3f399d4ec15fde3ef548aa524ca6e07dcf825076edba9d52f0f13cbdf89e5f659a14ace811667563aaa4eda360749a0575b628989c639bb0d016a96442c186caa1a12c6a5279e3a06094d4e4edff962b6efc13ec862acfabe399b4e99e608370aff6f47b428ade09b6f5ff4a47c70f0d9d13fcad6615dd8f99e2c537c1e5cf1ba23d082bddb926d8cb90123402c198ae18720a410d08d62e555dfa9341e7ba7f60628abe971354fa11cf0f9ceefe4925c53ef0d9d74679c7ec0ef181cd71434413727793957b607594f77e0879eb31470f7c86a452de88631e909d6fef62877860cbdc4582cc19218feec08a6e9a5b471e3b91b303632aa9cfe9636a7c6375e0458fd229fa8a08ca5374e04b9366520f0f53ca39b049273d316651d39003a75c37ed2c84d08803a79dfaa5b9b342ab080e6c5dcc39efe45bf57534dec0c9f4e9638812531242ee06fe26e6ac643a525bbe68b44151fdb14d24a55d5727d060031bb2c7ff8a2a925334a540630d8b8c222adfb0a0a1067e93ca194787fc3a4a9b038d3470fe2987949fa9076ad450a58106ae641addbff6c281c619b8d1dc1d26326d50495fca24689881eb8e24cf83280d992d607491c3062a031b3a4b42d07bb71c6c32f09d2d6af2a01b2e493806be3f4b2fb3a47422420f460e3d0d010d31b095ae335ed2b10c34c2708c95a379549e95b6468d74830537d20d16dc8d33d00003eb973feb44481d3bfefadefa05466f23c46f33652e711a5ee03daa9976515a97a2e443ab58036874614b26258ed89746521a6870413d791b7c27869ed816105e7a4a77a8795006400a34b4c0c6113245543ce420ef00d4804616d8147eda563f29dd22d556d0c0026791ea4ab374b6e0620b2eb6400058058d2b30297bbede4c1e2b7017e397eed17c7b5977028d2ab0f563215ca04105c64b68ef1193c614d852be9d95f4a510b1f5c0161ca0c016526094feec27926ff29324f4c50a1ce085170be800fa6201356ae0481a51e07c83ef77b85785e61ffa5e78d15c7ce4e8e20336684081ad929b4474d2255d251a4fe0bc336e9dded0c13549c309ec9fb9f9a6642a814613388bec7ae9f626059d3e1a4c60745fa3b504258d253016fc5554f654095c69dd14f5784269cb6181461258cda22bfe4b8ee636228149da6ef5b46f4fe355051a47e0ee4646fb9114925462046e528f055bb5f4a6361f5a29b071030c1be8bf304117388acd804611b8d6e4d9c3f257fbc60534885069aa4b14ed9492867ea03104ce2e242926833ebf8a87818610b8d87dbaf92e78051a416093768cd63d1a3765030cb4f5021a40e0f347ef2a0bd50f18a56ce377d22d1368f88089e16974c5d7bb98e4a8011a3de07feb22e9bdcb537ef3804997a21593bd7de8b903367704d5a9dbf49bcce1e822dd4043077c3a7ded79422607fcd9e9ab10326adea938e0ba368230a1466492e40db80b1a342b45fbd0ba0146187fa3a0b181860db85c179692decc165c7061822e70bc81460df894630e691de94c3b1a346084c848e9ae828994cf9805af29fb7259ccf298643364c17efa744a7d5e67c4824d6acff24b8cb13d68062c18350f325d53e5158c2ebd6ceaa2549094e40aaecdde84867a9138d919ade07fd36cad3cc60a4e8520ba3e7956e9cb601666ac829316ccd49b50934d8e3666a882911f39978590fc37ad54702ab2ebfc6d9f810ac69446cc340b4b9517e4f86205572d98710abe36e8add48e23820a3fb4aa0f334c418e685ee1a271e0c8f14517608461e3061a624629d8b0a4224308cab3a6f5a1f59fcebeb840072ec0010aa4e0051d86e11f6690828f9424c58ba61a9a320a6ebfda52b5883344c1a83ca23747b1d82544c28c5070263d2fad94d9e6e5d80c50b04985dc4ddd1235c493cdf8047f9f624e74fb4ca6923cc1ea49bbaeeda04ea051b3051de45a3338c1885ed0a99e3aae6e76c626989cba2b72cc925a7ecdd0042f32a5b49b6189604626b8bd55915dee39488ec1046ff2aed3d896fead9d81199760337f5ce3a80a8be0f9d0524bb0298e8a1c159d4cb50106322c98510926ed5eb8e9fcdcb0f743553083128c90629541c6f4a1a5d436cebbe00bc198310936b7a8750f9a5a29671f5a36106a62409821092ed6a9904c7afda185c50133010b02b0831991e063aa0921a94376f1941990e02e4f4ffa7e6ed64faad261c623f84c2af366b6103289a02ac30c47b023b36e7fa7688561462338b190435031062543adc8083e9b8a52cd4e178448c101062e82b75c25dbef93ffc88961618622b820a93eeade29a1b24f047732f5ef4e9b5b6b66ae30031128987108b652efb3a978a4c298610836e75c1d7fc31c1ba0c08c42303aaaa5ea87cc1e51f01f4679c18d5f4106ae70ec0c4270ee61fa6fdad24a6c808131983108ae247ee4d1397474c9ff0b30ca243043108ce63da1a15de27f84dc308196b180086c2060462078f136a56434fd432b53f03922b0003eef811a350e10fce937a5ef69f1acd63c38ccf8037779622e1df378b258316898e1074e575a4b2693d9074e63ce996e29a253b06ad4d8c20c3ee06d392d4735f7c0957bea694b59d2a4d0f4c0459710f4a7548d1a17851979603ce5fe967249fb1e84073ec5c817b3a9fc0efc5f789a9e4c71534eedc08fee2c298dbed48191577a5bb6a1031b2c0611838f2c259436074e43fe2492d96d7a901cd80a69d94ac51c925ac8066ad4a851a30933e2c0e776a5e89dc6dcf40f07aeac946f86f44a0bd137b07e27fa64d647fde8bb81f110a4a765fd0df6c936f09174882725641f69aa05c30c363039688b23b3ba3ed7690d5ccca91964e4513289781766a88111f7bc937eff3430d93be7d6490b5144101a98e09b54b2a89cc72327c7e3c091e371e068525a98710626f578c55c328d7d9ca819f8fc1e47e78df6505a512bcc28039b279a92a9a9d44ede050e30304006ce334f74ca0c9683ca47c0046f811a3570d4a831630c279821063eea696bbbb7242b34230c9c55e5dfaadc26f4da1b5d34066a9412668081dbfea4e6bb6f95b4fa05764f249be8be5d5b671b6678c10ea1361253cc7781ab102fe4303dfae31e3135cce0026fa3b6e4a61ca480195be0bfa3e897e72c26d2a3052e69b1accbb0189e6cd4050bdaeaac0433b2c0e6ac71737b98fe901b3bccc002bb92840e9e33bba65ebf00a30b626e987105367dd5bac72039283d5981ab204f7b664c1518bf13cbb8b15e84a8c077b4322d5d229b58d014186527a69e213753480adc25ef28b69373486f1478d3365ea91b63c4140aac88b85b59c9f3043e4427652ab3e304467829b53d794af9c79bc0de5a5aa47ce59334ce043e88d024645497c0f5e59d6d59b49c4525f0a694f9e4d75c5b9627818d9ccc94aa18b525d54860bdb29b6b57fefcd111b81bf5973ca946e0dc46c7f16411169d74b89590086c5f92dc69164a2bb83386c007f5699e237d454cd91942608245ba9843fcf879db1941607312cbba9359253b660610b8983fea7afa5c79bb99f1034e7ac4f7329997a69b193ee025073d32855ad1989b193de07334ab246f3463bcd31766f080dba4843e1163362ba9d9019b9245b0909374c0e58b46b3f6e480c9563a42ea1c074cba8a183d96f2d518bd01df51f399a8e02b221b30bee12f7af3d4ac643a478d1a2c30336ac09a567b724bcfa0013bc2337eec1cd94ab3e04226d74ccd64aa29b2e06490496bbdeb7790652c38a95127ed7710165ce8145b24085522eafe0ab65c7365be64df96ba82cbb8ef1d622a6c2dad6072ce27428c9b929a8a15fc6ad2bc69ea3d720457c18550ba2d795d25758b2a58db6c97b285647b7f2a9890f3b8ae97870adecbe458e64e6bac8d5282c729b851d79842f48be8eb4cc15f2991d3268b1b538e9582330d22e6bed348c1c44ad72443b4b8288d822d1d5293d02551b09b2539a9f0ea607d28d8344b3b93dbdd220705a3ea72ad289ddeaefc04bf397a4f8aba59c1e2093ea99074c671ed64b9ea04af75e6b15a249ce0d2f47fab7d69135ca76589be9bbf93724d70fe399e946dec902ce891095ea36849cae48f08e9c5045f39df9952a14d786d2ec1ee2895f304cb3b3ae6e90c3c2cc1b69daae78b5ccdf9af0497429a9df00d3278e45082dd572ba12b7766c8492eb6e0c2bcc063127c04ff4d5f5f9204df31245f59cecd5ac21a356c54223c22c1276dbaa23f7520c1694d297edace11697d041b3d47595987183cd28ee0c32cd8ed4a3209aa6d047beb96c482e8cc0f414630f95e4bb5018dfaa87470c6e25028100744c16010c3307c625d01f313080010302a0dc782d160a448d23c148003502a244a282812262a181830160746824018100805046150201408854481504820516b9db90671c09953c3ff104d00fea586362b38cecec9445044aa0a4ca281ddce3e486c0678d35135c259486dc1bb74c8fed6d5ff3bd463c4a6c50a504555056e23c2e9c7192efeaa0a612982df0e8b904d972f162419298ac77027d99444e53f450ed1135dcc41cba0d9619d326d012b65833afb40ec70e01baa7a120186a375aabfcf87a7a23f3eba2603196357ac0f389d023232e5f8b66a49778c742b00cd5aba133b897241428069ed9b4b1bbd2e1317b5b9341ea880a2a32905b70b39d21f98b07136f58c70e9519fb82151005ab1a277142ddb283ddbec027c22ceb100242e780f78fa174b4f35008b97855e708c0eddb90fd3f91709a481dea4d6d52aafb7040a31e85c8eb153ac29e84c923722efe921a6211336db4df45b6a43b8fbe1a34d1e87a5a5415a76fda794a08cee2e4c2816dd070b881679812e3f47444fbb0f02a6c221058b1effbe44a2106fff080044615dc9d963569084c9b3f443f5ed648248c752577d994b8b638af5134417471c8cf4fab456e27efa89a3421eadf740d12f384b1ed83ec46960881238a0939d7446ed081f83879228a65c93285d3b44c7cf25502600a128303e884b14ac43a5b9a356105862fbabc62658c92581bda1011044592eec764c341840db3e845ce61f51f0dbdaeefc575fb6f15d5e96df9f9bdc14c32e3405caf196a8e5fff0fb092d3532eead586ddf67dd359741a18f356b4a54c7c271e0f6c004b2af0e5b2294d1b98053c8cc10611eb1a6fb73bceccc9300eb2a55b77a0b3555304b1913ac5877f58720078bec2c7de64e98f6c3b90c089ee25d7b4de69b9f6a9d9443099f77f96aa5c15a6ffa08155d4b7b44be316f233810756f9793ad41eb39bb5dbd4cb803cb84db18f2b4f3e9c41f6d1252a4bb8d783ed61e3b2765666daf4c528f2d48bc2dc80254490f8b18c04c7cfda26c0c6d4ea9bcd0a2ec5fc75c9e868ecb0ce614aa098e4e6046ed61d49a9d78fb3fee61cbc4e24f0ea590ba18dae721d933fa054edda17cb664c62fa9622d2ea6f1ad4638af0423e64ef35dc4db046f451a90262b46c1e263b6ceed43472720a8103589da56455e4f7c175c9b8b9d5ebbb3d7d6c49097c338a68ae8f607cc0ed9fb547c892f550cdde50409f4503b8d1a5e19aad4dd03d4637aa4055f5defe022ba2967389a4d138e64d07989661306df9c4c5818346bb6b633dd99065e0cc92d8642ef6519dc1b6b2f6cd841b6a2bfa3d66e0c695d8e1603484b71000af7d81da913ff2e147142c4c2e7c642cf1be37c0061b3fd8a584eda3f3a104c0a60f2cb14b5293226056a8593014b4950e3bf1eca4a7cc00c2e38a284800fc1a32b387dc20a8d97b2bd49091a7a3d80c5f9f4475ffd13b74515abe0d53a41cf9ce88d3df9e9e2d8512c8e1735675d7eec7edc107270057a63af1b49b0aedfabbe2dfc8c5a9dbccb7475a902dc3c06efc57e2531f4c01a619f2988b8314719404a9bb119e35966ce8a28b1f06baf70c24778ece25004df46d380e78452ca7856958f1b65fd7f047c27a5a62a126c1f14053e25fdae7b43287cab1f90c8c7eb60b19519673bf735e60fb2ec49a60575f4f268258278204908eeacaeec5da3f24a9fb7e007975710690750abba1739531228416cd633d0522a515847ffc5a4b89285b0d6f57c182cf9f1bc62d2aed976cc91bc7940f30e336168a8a3d18ec33a859ac0678d866eb6674c7354b85a0dd78156a01a93cd094d2b429deee6bf07108e4e5c87ec2409ada82cb4a14f2eb4cacd7ad71dc1471b25c4903935386089370108d7a9f2503580724093b98ff2778353f635d72a5aa0f39db6f1785d30329578ae80b49968d31941774ae6052a42bc5c0461aefd76238ad4028c9ab003f5acda9a7d97f90011b2c3326ffe97b7f8f5a4e675a2d0eef6d94a3e4fbe25ba24b65d769edb2b02b4389d12c329ad3e52e8587d135355f048e498cc171bcb8a3d79a78995a7820be964ea809f65fb0c7b830eb4a410ceed29828dca0f17dc081c17521c1145d995484ab5cc44654faaab8191985c43c5ee37bde7ab1237f4726758c876e2cd56c2b65828e94a65c7428654a159e273790fb1d1c37272ef8158d7a647b55ec8e3fd42e07b08b91961573286ef5686fa610ff29fafb8f64e7cdf37adc40fe15080115162f8e93d3d950003811d4adba50b3268cb34422b65394ff059c064ccd4a2158543b335b9688426310273a3f29f7d07b295f3d4fc0481a391661f1d135900c9266df5f36e529a66163d89b6818f467cfa796e273f5af0f2e58ca8ef2f6cdb7c89e405e6ebcac1b501d62a65d542cb1e8682d552945ed1b34834548b938a3dbb387b127d80d8beda4e130bd9ea48f391556bacdee887b736768391cf985df19906d42dc2c99dac3642384e95595b3688c969c57c95171945aa5bbabc883e8b0aa6f2693a9a14185a540e1adc4a40d382c753f3ac6b43e0f34105e6b5c7770bed5e6becc3df970a2ccc958cf24369f26db8e112f8f317102cce41d84ac03d8ff9f2425f6f12ca1c093a70fdf94c998991f4498035afee45682c884c871575395f9d045481e31a0504fe6a802e48c2cb45a2da057f53a952369ac1ccc9db427dafafaf37a0900595d8ff332302314023b6f52280be63f258e1feb3155500337e70cef42c77a555dc56a5679cb371e61fd3d0927b00fd7656769ecc78876ef20ff2c28a41c42258a88d7536c3bb2503a4b63600bcc1c4faaad06b12c042284ae2c21057088b51345965fae18ee323339b08c7f7921b82f0a2198bf565cec607202c8d8e0da17c57398adf9e4012fdbfc1ba420e6ef17270d7bcdc1e685636e61056630a86e2c76a05a07d563cf731b944caf91412711c2eb17a26004932a0b9eeb6b4a32504a1b1ab50a31b14a5a2142175728ef190c816a2c76f5c47980de15c8400d97a2927907b086d581003be50825f111227010abcd950c237b80234c92debe9425b33ba6c38971661bdba0976e4b1c172ae82b5b7a563bbdc4860aacdfeb499b1109660a87026c7cd40d2d64f696ec0c08a3bd9f1c4c49902b9bdba128222c4ab189a2aad5e19b8ac08505cfd1ef8ea8ca1ceb708aeaea2e3c3895bd88bbb8d7d64e8c0d48bda453aca201abc5327d5e0e205c7115364564a214ceb80cc0090636b6c5240cca98699fa3606c9ccbee99f7164d4e3f5bd4a535d43a92d3724a6de1269a8efd5c9fd0d92b95b41ac95fe66db8dabc01f4fa9f8ede3451fe27e9f3eda4bba9c56218b9a62387d0ff377a36a87505142ffe3d8b15eefd67a582860fe9baf165a70be8412edd110f5595068a5de4757df737a9673ddc6fadaadfcd7741b10965b68a001e15f35975c8e31379ba1f9fe818bf7f17d92e0e24aaa10403e4e423cc01743787b1a4b55141a19b44a2185212faad04a1f1d24cc0f6980129ce2f02684f8eb45a1711ea7c10696822128cdf9fbd07c56a86a638191a67c6dd89acd5219f783c51bc3a29ea2c619903dd01d507c3485f540c08c3ab752a36a800a397515a90cde3437366b2bc3ee43e182ff2b0354ac7fb28265fcf02cf16ce759eb99ebecfd59d219f76f37e25c27a090b81dbec97cd20b905b94413938023a5665582f60469cab15985afccb232aaaa00c68607f1e6a7a179678bf03258ad56c9ad06103416e9b18754798cf9a33a7bc49ee2f97ceb2c5428deb5386f3812a086c343dd597e763a4c1422502c4772b10ccb439a18a5825cc7aa5ae5fb3be72ad168636214d6656192f486b85fdd1d716268adf6b289681ace3b317d5208ea7165e58adaa80ef59dd53985def1ae8247a6da51508d2b169e714185873ba6236d98c5695ad0c5b6b6dcda9e69b94f12cabcfc5c1a8a38483129b03bb9498e36c9e45ac698ac58b11e0fbd306d4e3523dd91cadedfc62ee2f3dce3739febfa5c9d863434060548266286590b2e943091ab81b28c323cec734f7a532ac56646677ae1a49eb2808718221acc6be168d087980de3034b26802a10cd861c034c5614414218b92cfe0bec11551df9833e6ff001acb508906b4cd08873a6932dc6ded81c94d13092ba10ad9d0f8d08ebdd490181efbdc169f5d79663ffa454ea593942248d6cf5ab8c86afdf4f9a7485053b318683cf0587038b98c039790213de8c46e659f4c115b8bed15c7de0791b79a183645ab0407b8e2419f6e0fe2abacd5b07854eefc94b63fab9cd7d0af28e16899a527f7a790807b7271ad89397bcbb0de85ecfc31d3d4ecb1330351a16fb005f26082d4d9258cf2b5c4fc0439d328b78ced27ea1bc82fc3c0d8df6cfbf9c3573dfbc5ba9f6a91e9e0acfe0f04ae569b5b2e3dcc5769c178c1c69586f1d34dee7f0fd29454f3b749edb0bdfd5870a7ac05829b9410a0e50909fbce0f7039e988247c1b42a839549c63cff5f8b4d796fc3b3f7fa03073824c707e51f46849eb276244b9eefee56a2f5ec27a28012f402f21f6e13eb4ab305c93949ac782911f96efc2d68b0339ba816cb4461de7043419afd9d004c8d616c8080aad947c6e6dfa1d3118510bab20614eadf51945b0d10a503151ce5af6236a7011145829c4d7e9809515f63eb18d8c55986cd2b21ef23df30d007439b121ecce08954f32616f6e5d4a7283209c47b48766ad29f3d036a8e80bab92748e6df41b2d08110baa2c612edaf6174190910a5631895cdbf52188ad43b1806c3581aa57a4408a1ab7d3174cf09586be2af3574aa76752ea9b643d241bd935f4202de6dfb70be87b8c9a8e47ad4a985887fdf63b2325d21707d850364348cf80271cb8bd357079ac1404e6be451909c809322a4d316c255b4c9051fff2925b7e3e3f3a3b684dafb14f4259188ea01a870cfb626daa30e1bcfd88fb48e0a570b0551c5731e9051bf11c126b2fe6ecf7ed8ba83b6b7f23102934ada797279ab4aba50accd2afad3da38165405a28f26382ad0e615a572c7b9b660ce6d585cc3f114be7619f48c31ff0ba3ad1d8a533497e79c81ddbbf035a34148b708f8650f3cd04207496df515497cc0ca3cb5dba4dd52185b95e05e10f5fa2ec6b09725b038744e72abf6667fdc243d71b042f8a620d7da8ee0f7a4438f8557ad7dd5376b8d8028120a2a964e15b3cb1d4d7489b56097a134b3552eee43b302dd7ba1e2557e57d077af7c6e5dd2390ba2da1df7a82b93895a9657d9283b4dead1f4260a1380f9681103bd80b0c8486fcb36580a087cc6d83c9b4834477c3738b5d51faacc947d58281d8aad7fe0ba097dda19e6528ee76f8a28d144caca626488638a5b53432d15bfe621bdafb68eafef5732614bb89fb5008ec5f284e20b04f70ec4a23f477effccd106c558d4b7528961ed1efb8d4260cb52d3fbf7b5b464492a59b1b6b89ecb2b89821738c5f1f4346ea65da82dd1bb2b6c4cc1aaab6dbd29931f4aa28d640b3c75c8715ce4b27740b1d21d91fb18353d829da93991ae9401c52b7cc10efa66074ca0c55c9adab29182eaba080fd268d5aa27a606a8c8044810bfede14391b0159f6fe2f1b5e3ad614fb840d11a1337edcc3b14e14e334eb5ae9e906a7a3f727324c7903d69e5a06d6f66834dc55e002eafe4b62e102bf0d00190785bbb50666223394995cf037a9fd6a4d8e252587113952dcb53168e7afdce3b4391422051405721324461c147173ebcdb2da312ee322724eea8a93c0c60bd01c5b2ad24b730ce4194dec0c4887642d330e65d8d5ce3a9001cf57676cf8410030cda597dc28a5db60ff1f8d362ceac28453e2f7d29142ef9ce2114f91995ab4ab90e489c395e324de814952a3fc5d42037cb81ef4559090e02cd96fa1661275d15b90b0ca8ac6767265b25d3d73fe7e4d3906890801aa08ddb45a01f3e9117bbf3e60ab358efd2c0f1d1d5e2eb954f70756415da71eba7e204bc54a5809b4729720e2ecb74291bdb02d647d2279b06f05f1fc62c1df57c8af658b2e788744dc72995bccca4a843a00245b21bbf3387649a3614a904465a19c02d6bad4239222943e5b74418243ebf135975a51cf7019453a60ddd1eb68313a266720f3fb6ca69dcb875a26f464fbb0ba77c640f822f7e85076bd5892c2107f9108181efd56e152d7da11e2135ef215183e04e0340e8e30734c49c00c093c688b0106d8d2c50e049ee6c51b4eae27f71fac90af2a67dc89e6d18dc48ed617666d190d3e1a942501ac53d4c6e0001b894aa2fe0fc67e15158513dc63e931bfc13594cc1078a515a97aa2973c6fff1bb38e0b1c9b3c0d195ee7ff0e93d8ca57ee1390661031d1b2b6e1ec99a250ebf336fc4c68f1af6eb48d4f7c9caee76638c351585287e0cfe2b52e27801d845759866dc9cfb444235bb482ef72dc0db2a7594aba409d403c86a99d7c95fda41ff85e7b8177144e2b72a1d395dda85a06ce9836df559f8558ab3421d084351adf4177208f867faf6136c55f9f6dba67821bd954eeb526abf45bf84d29819f628336995f4e2ae3011537654913f478cddeb70b6f664452f1e58962c16f6b1b9918912e87ba6b53c9c7cbf2e587f065c7be079524a075bcbaebe38e21b0c3c48b9db5960256e430f5a38eca08740f362fa4500ff6665613aeb4bbac517cd4da283983ee8f399e652385899fcf0e043cdc6e1c9d4811b56baae5d1c13ceffe7e3bda7a184e1d815537a4bc7d87d7c0f60455f0dfcb502453186945564c1141b93b233133671d1822738901afbcb8e1d3b0eae4dbdb6372e07787e874b019088196aa785b4383d0bdb7ce1aa0d86422b834d5b37e3d4901f8af6d14d397ac8069404b98a873443b1bf53f248744791af015bf4081571549b992fa65048dbe96fd209b4e228729fe1f6eb07c938c32b53b33423838c19c17c044453767577888f52e72486ab91075da28a86047aa355d74c1bc4c5dab3af560ee7c937b78df01d828f166480a6937950b21750705552d1e85c2df02aa6168c8282353bf98f752d25e3f99f92f17c844df8c40d1c650a5becc793f3af4683c28efd6078cfce002b12f5bc0f0355e003214122850d29320c32af2003b5355a5e49ad767110b0a77203522fb01254baf2eb290f6a45688cec6accaec892a0536d96724d9ca274942f66c8c603ab316b695092c70d74aa0961a6421763092bd024014ff860bb0932156b32a39815275fcc78b4ef9a47d334161b9cbf31372273998bda3985bc1f0d6d44d66b369addcfa4712b2ed5495f453c020484c1d9b4f8a46d570a923d4d17d48812c3faebd77090799cce6d6611cec7e5b8cd0fc3640f8bad70b1447a69bd50a21cdb4d5602fe5d4f6128b9f6c10eacaa281609eb3d0e844f758a6d2a0063d42baa5a0df7c09c801bde26f48d1acbce83d33883235562505ac6c520fba8b7ac99df2820bd35e1c687f00c1ce601558ba14275342b69184b188a0c3abbf9faa2a1dd283d62112cd6f5fcd5681b23c3cc5c4e5969f6e360e83e0f25eb476d67a6347ef718b465750602b10dbe5ce3ab07004173777cdde3056aead6436acb193eeacf78f7abc3b621fc7b77a70d968806924e36627d6f7f6ca3da787ed373d48cff077faaa1feab2bdb76fcc4b883a3454d39730a7dead11ebd8c64b89fd948dc8ceb49db458c44b8e94eb82ac02e8acfe439b58d785085233d86af7c561292f06bb781dda017be72ad39554d901c4be5bf4007d087909a7d3abebd4f39ab0ce5a9f1e2857f8d0f312ee016457f09d3b4dc6fb0e2b732ade2cd0da510bdc72ac37763b8c863d147a9f61e8da4f236a486da979b549bbd7241b8db85cc7fc0c91bc036879ed593b6bafb5a2b6b935462f35c05ad67d2dc55c68ae7a2e27a1ca3bb0cce318921275caedb677d5e572df213f179ad691e04072eef01fc0170e411fe891e12b7f06cff8ffa0ab624e5ace757d93d5dba2b1e61e7f5e8fd7cf7ab77ecd1f759d5e77cd5768ed316d0fd2c0883bf7c64410cf8eac8fedcb7d389c2fb44cd27d434b7948af36e3dc521bb47123b0d1283eb88eb2fea9cc9a4b9b6b474da875b5488dd6425a5d436a448d58ec1f71e2d3bf5072d6429bd7d2dab796ad456ac7ad4fbb6d6f5a49abc327ca9d097f7d3b803e190d393df97f665d65b29a6a955b89c8d9b594a1055bdbe494a1d76e5e2dd9b376a06c6d43a169f76414376a3b1bedf5b05a5b34f41e34bde4110f38d96c53fb4a7f463e396e606f657d43ee1cabcfd2f0dcb1d8672fb705b92bb0514161d9cfe029827c900af52d3c7f4a2117f6bb86622d4e59e81d64365390d09a14208101f21c158fee11e64518ca1a8c01d14f063850b07a8636884cdbad5a7a4d1e437bde1ab646a44f9dd36386d536b9cd4c4b3a08b8b3890a4e20a48e184d46882c9b14738920f06e9b07a2de3ea79a1c96fbfeb01417e3dd0257c3ef2bf7bab55ac6014d55ce2776605e486bd3f0e97c176c90459f4ccebfad0eb5225ee0f8cf2bab27824cd99c7f88a3290372a62f4baed68ff3ea7b0095199c0e44c37e7a2e01a99c1fcf7785a3dbc9060a84a45ce7733f6c71c7c36f58e597a0a66e17b0794cf0878a10deb8c087aa31e32f17112bd030f2961169fe15d92f497de993a850b3f573a6fcd287529a40c4b113b5cf2d8df3649d101b8ebf562bb22b8128ccb9ddbd39a87632a105bf04607f23ebfeac015205115c5ced692b693bda08cb57636a73456bb1e93ca0395021aff1a5974fc4b49ecc87ecc65fd5d11849517185ac84fd99cb73cc7d13a10dea53b42d34c2bf4df4064d69e5b420eda2856809ed41bb6bcf5a59bb6e5e7ac80be090b4303db7cf4d5ec20e74620a7f9ca6c219e32b33438b40cb5ca15e0f399c8bcc54d3230ea58db7edc5c7466c1a47a5698824270b0400e9cfb1b3fad1ba4892d7ef11bb3578f8d71a266739b324295096769ad2d94affae31a4b83507974544f29768935a3e09f0932e0d817ed744f735379f04f8aa47a814690392b38729d9c2ef6adbc6d5a9c63f5018db5217b6da72b0816210b3ae8253de93ce7992fe99c8bec06559045333f394ed4200227b18ae668809cfc576f4e4843ab26eb54618285e21b52365625fb9168096a5f01aefc3bb020de372da8580a4e9e6c5eaecd99a415a7f107cea08217cc2b08c440831707036383ae0a936c800dc3c345260c616932a9797e079784efcf222147223f8584775ff098d1375a0ce0efd7a27956e64568995456120910ae00781893fe35a97a3092e6ed116ff994e136175cb24e3ca16765f6a7cc5795f1acd95dfe7504c320807483c395077f530aef978f66c2b06cb9cd506af04f49155baf74636ccf0e2167d73f2b82e26693eb4a1720ed0286043c2ee753111929098a21205254009d09f8a21140fd0137ddedd3ad4e567969e0cc0bb03e7f36abf8f58cdcffa2a4f2ecc6649917d28123d4d64b654191026aab6fe056445cbd1475dc994e39e1f043be3a88598b3a0556dbf894e0f42878031a66be13601fc75d561cdafd6b43de415056f50e21c38c80e95d805722f7da4e73fbc11883df950ef7c789b0f7bf843bd0222b7f9b861bdf421037afca39b40b0d71fd13fc8923d13c012670421a732100769fc29b3f139cd166ae3d5b0d4c409bb2c7fdc5437af4bece30226eb454b8752052bf91abb1f45c51ee744ad21297779cc27a3c8b2cabbb58859d51f424d9c58627a5b6b06ff419f1f28050da7db27722fb5931aa4e865952c681422137d31f0211f1a1164372dbb84f0e19746184ed30bf362a57efd2f9c1f0437d1028a7a1e343566049640d3178015080a544f3313d0912a0b7e84149b453d6cafc14e1a2547e167320f7b27987443022bc8f2f049a9e8c8433bd07605b3c61974092abb440480d2e3e408c83365a50acb3e12fb86b77b0c329725726d56b882d199d82814c995539acf380a117523d9d18bd7b5c2f361e09192ede1a3573f486bfa625daa49a65221517548b60e6dbf237dc6e833162bbbc3be59df41aed2ab573cb4aba8dd20c908b29e30961546fea57a2f57cb687070fc26d48686f973a1b31108bf7b5a89bcaf05ab75ad721119aa3829ae44cca0fd639a6fe64e9d849992f3f1a5b9eb20c8f31fe37c78561302de5844dab0220fc6caea10e8e82a7b087643c8eec32ac173aa428dedc0e24c7138a01bf9f57383ab7f9fdf77fbbf79f2d3347b27cc9635f29f8005c750bfa46e9e1e8f0e726551afc822f669e45c6b4c97a743b30ae54e447552ac3dd06d9bfb66fcf619f0d8f28373c87e2a605db71633ae50fddebc98154964fe9d06804d3abc5277a3cb6a4c8a87065940e347db0d622bb567a266252c8c7833970fc1842ae10b00cbc00e4ca6a0c77864530ced6ce1be5ff0da1f88826fc183314c4e954d90dcd8aa7c7e54203ac1b8af22a7f541f4426b8cf32ad48bb27a5caee1b306a3a0e431c04ff4c286ef60464b1964b1a123cc6653dbe3954e771e6a017dfa4a554048058a3c2d140104e07985b8eb3c485dfabf245a842340729470a7f8c4de2b95ddb90b3fc3e1b95cb3be2af561ae66b622807600fe357a06277cdeb8c16a8392d29cde82152e4e8e40848fb8704bbc7432b1ebd2de0c543ad8792d17f5d764fdeb1c8981cf913a93431bff7d5d090c59f49cef89cd4a518568a192a3c1abb6fdc825054bd4c573cfcc033189254eaf3ca651c46560adb0a86287f471b2edf1a462d0288f73450acba92af8f657568f896e6d705126d0d205162b31eba5372cf27245dab01e0d23e11eb8422fa6dc3608aae30bc49778a46d603dc2be5b0b1065557b84e48ca2afd2153a2b56d58e290557bfea3f4b5e2581e95642b635797fb6657792c66b16cefcb6cf31e768681fed91bc454b704edfcbc3069e817f65e52861c4128ce22bd2b7dee7dd20d96f1482497ef54cbfc610d503ba68cd6fe4809678be64e9f215a91057ca0dc12a0db24e28dbaefb3d5e140380022c3ef403f3fffbc6e817a82bf5458da690abb680d3f7103ecb65bacbb51a86d6e38f289a2edb763e1315067a2e2eb041cc64ca72538680a09e90ad10a87231f6ddb3076af7794135422118ab0beeb22f3c6820cf88dbbe89d91fba72d92b476df60060e4b5f43e20a59ab30038b0c15b6b7545477fb76f8ad20af2930d96e6418411644b9b655300e1916e39a5d95a8658a97890958a07616955c4620d205b1708b37631f86c79bfe4b3d133c1c5911234a3dc82ce29d5d01ca40e9a538ea043e5193a1fa1057cf04d412400bb13c00b00d2a4642f2db48610d29ce82e5cf9e9da9f252f9fb81aae537fff496497b80ef963265c802c432434a6990b1f9f2afb5105a56af86c619d0670f8dcf7b443e6d3502bdfa3fa86241c4dfca4b6da7463234df8ba2f6aa8bd5825b8e0aba27d8ff1dd16ba820e7206db36fdb11c8780568129077ad8c41d6f92f2dc92036a1b2d6bae6092179eb5950f93a6f32f7387c0414e87e82cffcbb925d63fe8ad58e6f164c704e442f515810852d3b64ffa2f18bc825995686d884b8995407a1afadee0c90b6dacc15ff944152faf00b465f4383dabc6d51bba8771497ca61edaa267134215427fca7935a3b69b8623945c121f31c2791e134bd2f27f4655eb04a9f2e612f5bbf18589760eb9bdfa31aba5e1c77d277b96783fbb1369a089b169812be5872e7e664930316976ec9f5ce23466130cc9ffb2e73728a81decbfedeb6309a6cce6d9c329b4f554b6bce7827e9ed715f8beccd19027034aec642873ec274ca2a0f3ad83c480193a82e9b64f93c60cea05ae0570ef36ec6b28654da989c2ba23d92a8e4d33dd0e342593529103975cc045cb1a2487a0986a964ae4f0e296ecf28f648709371b1f6cef56749dffe25f9a30795aebad5b5c9010f1bc047ee18ed33a27252bfce0d450fd47f2c6ab8aa639825e49dc60262fa4e687ff22512340a6f9ee55eb554f1005da0101d5169120f400020a8db9d4fc29ccc027da88d6e1823de7e0737c00863d560eb8647c253093ddfb325895ffe98bb85257d46f134edd9093c98c5a86c47985db8a87531ef088416fe913f23af53aa04ff36ce9ba4b5e875d07f7329d48be80516c8fcdb9d969c6be203f1bca5828bd9e3c15d693a0d1d818e164f6a5a8e92135b1e6ab8facdefefd226a481d2fda8f85393f95ac26eff5e58f6a8890742320283ab06ef742484aa991bb8518adc3d737183209f99736feb9b6af47c38580566a323c7dc83c86493e4fe59464adc57fe921ade491764a505a19dcf8f3bddc5d62616382333b2bb6912738804de0403817ee5f489ecdf736794a44f369148f6ee5ff86b55fbd811cf927d64d5da56ba0166962526b9b965c768d78783e007dbd16da08a9a2c40ea536295094b628413f91735b8722f624894d9826fb2707a7a96a08409e0d038b191ed390466fe2960c37939aaa965857e6a98d16d62b0e9e4f6124a0668f56921b27c3f56d153649e83800d9642fefad6dc3ce75839539cad08c8aa7e9a1eb5656529fa2e5056f2d6df57ebc9e6203f01c243c66c1254dfaf390c061c2396db5cc370b8b6f36716d557fcfb1d3157a20a0edda966d4aa8608ae9022f92993b630a9833942354cb008e5835318d1b3d5481248c231c96a170883d759495308914badb17ab570b9cf99258def046fddbc207c5cfa1a0ae27998f1ba9467ace564ec90dcd2802bb6c229fedea82fd1566fe33f0292a8845d1fa8108eac63475ffe698d790df940296d02c2867083f4acbfd8946725101bd724cf3d1abe2605dbe12f7a11e47d5f9e336f8125f6e079b8e2dd21063da7401316879d14156f55bbc69c957a1e1555c61a1a4309120ae8f45992f724d513d63a076c8ed11e65467df206ebfd5c458d0789b67a3df0cd0f58b4df1d390d8a274a2ad7a3bd2f7e8333217b023b8960a70beb9f28eca20b5fbbc91e14b7809bb49b7220fab838671f26c4314e971aba26e2f1ae632d8d68b8927908c14a09695e26d4649eb0b31888d140bc83c3bfb8bebf3b5e31ffc515bd01f7fa15aa8eec78c13490c25bdb24b51c7ab537e172ef932d598b162efd652e5cf40ff66c732b67b7015f2da70da6219841bb6c1680407f1cbbc9a87e8911ca490b15cf24d594c7ea0020acd3f7f5d8d4ecf1d2a2fed909576ff5235a024472940d377c635dec7ac03e201de21f7536d29535bde74cf35947d418036644f22563265cdaf8400a32591cd99225554030935af495df074ea6b0ff0d79991e98647a169ea43d2489dc9cf0862b78beecd57bf044039b6da167d7a6a74336246d413084b45159f37dabb61eac9da9234f225492eaadcbdc46dff2e404ea372f6cea4294c88369d4f5bd4e4641cea28d70ef6f0d050eb3d7910b461733cc6921bdf241313e441b1ddc07b44065b9593a5456e3cb587af1568f738f552f3aeceb1aae1e11857ec9e7fb0a4f956cdb16d9bba8b303afb84b546a9ac28f2bf091db83ee0691e62a348b71d8be86c3d3ca1f5e3860cab25be3b25262b7e17db076308de42f392d3e55601ae3f8854462c343310e4573ed5940710462e20fc8b351514a1e7058214db871ac7ac484750f98d8711fe14e8a4a2cc477ab2d2775dc15f6f8ac36c559a678313d97e74bb93e8b8816af731eade6eb485111b0157c2b254bb3c6729758596a3e244fb43a754706edffa34d9eb04a8743aeeef20d012a8bc24afffa0442b43e240b6091b0db882186798f699a07ab6dc5fec039e8b6802e05526c66b59c4c1697c0410cd89141cdccd8b989c279f0bb53182421e3f246a4df53176df5304b510190354654388a3d629e34263c890b8248a35fcf248ee12c554290b25a794d8e4ca046c0990ac8e6ea41e0dc85648912b9a952e13a3b7d29623ddf4d47ce21f7574ee80f24d56f4c554c7e2b2e9991037641c9220288c65edd16e0d2f2cc14cd956c613a77df4db331e96e5e84258b0bddd03c7e00d4c2a0faebc317006c7e487799f31ea0a047467022e1c44ab0a3540b0a6d0013c0c3c0c3c0c3c0c2c25e2b73e4d7af9da90524a8bd43b3c1de2c04529934c49a6c879c3ac66d452f21bdc77f0139c0b870aee0a310a854aa762d20892003207dd73acbe34c2e4ebd741e4a088d92d319f6495c491c741f7f2923a9d7cec32e1a0c834cac5ee3ec917f10d9ae456f2fcf725694b03e206c5bbd3bdd5bd69fb7806206dd042e652a68389bb8f61f0300dc2063d3e434b6d8d89a7533f7a74d90d40d6c0688955a3ff6b6bc39115c6c80d1ec90d7ca43ad6041035b401240d6ad222fc4eb824a8fc972c40122263e950c93ca6c617366c60dd4005c819f4ed7c5b328e92a43433090a6b006206dd5468083dda366efe560990328090a18c41cf9592ccdd1fb7416cf400220645d6ec8d5d856bb0510e1e61308f202c80844133cb7f5f96e498e27cc30718fe23c78dbb3e808041edf13af96df367d0231c593a74e4781fee3dfe0b9a5c397d0ef9985f5d738e0e63a418102fa8a779f20591c13783205d502f3ec5da33613ac50947d60d8306102e28a3f9bf5a1ff971c3ce00b205ddc2b505fd6515b7651c59c540b4a0c9e5b2a0e84bc29fe6d62432806041bf6c6964e85b6ce966844718233d6670ca868d30805c41bbac3896d9db4e92e11e09078815d4780d0f72378c23ab0afa7ff925a5e48cc8970a9a9787b757e63b49467a4718470390292832427e3ed19795c4947b20191029289b24bd212b2eff940847d68d1b3e121c685150debd47787c2c592ee2c8f21e090f3046f8c68d3e5b010814cac608409e5036409ca0279917795e1fe34e0e47968f19243a3690f5029026a8276bda52a54d05bdf0880d6ef84870201026684a496afe734a154c6084d163248c1a1c9025b00044096dfe3e7e8ce8d091ec0def51cc4e0e2049d072c36f65e5b9ce998223eb86ef08a3078f2a5c1024e8259cf09777dcf652ca7170f2858f3317801c41513e173abdec49e1bc94048811f4f36c9739e8f854693644801441319de4b4ca4d7e002182daa62f7cf25879b32d0e41afaffca9a41c1e5377425063952499a49312574a5977000982ba9f93ee75be98f01004089cd262d927a3a503c80ff4aa5266fae3652be6417ca09e2a693f77a86ca57d2fd45282de2ac1e3ef97ce0b3ddfd989f2b877a149e5efd77b4a9235dbba504ec5978e27732e349fed8ac144a6379b71a129794f85d2a5ae4f12be85266b2c081da19795846da1a7fc4fee3ae7192eae85ae497c0c9ae7d242773fb9f9cb7251d6ce42532a46c57de7e43926b2d02b55dd78be66e82b89855ea663491e0fb14987856e494e2513377deaec2bf4fc7d9663c49de833b94237edfb315f4a501ba65668b9742c654a09b142d1e13c8312511b4e08ad42b17cea243f13a942ada052ced1a6046d73a642d9ad0f319bf5a7c3890a4553790ede5e9e427dff9a93afc2e8fca6d036655399f76b47d9a550b4648a29db6de7a60e29743129732f957ca8d38d4233d1ed1b71a1377651a83966f8937193c53f149aec5c17ea3ce54e6a50e841e6bf5f4c56dee8139a5ef99e8efb29f1f3842627fc6ce3640db37542df6cd3aa5c194e282a29fb96d7d826d43c935d297da6092de6c82044c62561de4c686e1b2be4c905994e4ce8a5f34f85ddd28c99ba849e355c4abacd74b96f094533097a1793c92ca64ae8290973b127587064ddb861490945886f8ca9e4e42e773209c53ea86427eb2409f52d539b244bf75d9e988811095d2c7e50e1ce83849674a6e46ee1f55df22314fbce976d634ac229b523b4d1f3ac2594a811da66998a4f5a67849a33ff4edf8e129be38b504c4fc99833c594795184fa7992a753594b63a612a16997df697193252549661103118a9097192c7699958871082df46696d898ef8e3d9311310ca1c9aa79fd8d27a57cf91b310aa15edc984de69210eae6b0f04b8297709af71163107a5cdcce509e3adbcf59871882d062c85142b7fcc39529108a6f968c6162731266b3430c4068bffd9ac2de27b1242a36c4f8831ae72f96e017630751f231fca0cbccc84bbe190c62f4414bd6a137a8cad7797f1c5923bfa31021061fcc6e61f468923df438b26e90f4b8e1fe670c31f6a0e9cd202fc4c8a0bcc4c821861e14fd49febdd1d121461e142df5db69bbc2e9330b0e31f0a07dd055496c07257d6dc3c6d91df40afdb6a0bae352109f638a1876d04eb7443ba5aa734d8da8801331eaa0e7584acc9adde1f359e38be48b48c4a083be2789927dd93389883107bd832ce94a4962fae4d7430c39689a723c2567cf1bd796e2438c3868c162d649ee41377e0947d6485f1562c041cdbc93415dedeee78f72c47883ba23f325bda61ccb466588186ed0ff642bc6d80b6132598388d106358bdcfc88cbef2986d8a0689127736b0e7262726b50c3bcafa42c5342570a11430dbad9999843bd8c85c5d3a0a67adb0ddd2941c4408396bdfde249ca5492b8cfa0d798591293e6511e629841930df2e4922ff55d123cc42883769e5be393f0f457a58e1864d03f84be8c7349ecf01ec7188316e63efd8566fe14ceb1375c47ef4870941862503b75f68c121f619c63c020000c214618b454fa75bf259afcd4d6871860d0775f4eb8f686764cd71c627c4193b2c71474578e79410b11a74c70cf5cb2635dd0cf24f9ab45bfa90b31b8a0d56dbec60cda29a81c17626c41133ea9aef23c354a92b286185ad024fdb8a7d29c681c3f636441ff0e26ac861858d036680aca33bce43c7d05b53d56c99b51f9253231aca0e860d946553a121ce7811855d04cc924425c5e7e90a51b31a8a02929a7b798bb6497950a624c414f2a73c885b6d3374d0c2928b22e6f443bc6135eddc8418f1fa5cc8011230a9a8a4997ca27c3f5a9180acac62433e992bcbdf4c4868d3c448c2768233b9da73659c4b6ec043d85ec1376b931956413d41c3e4e924a774cd0e653095399742ac558821a3c5da6d0f6f01f39ce470e10b4ffe831e23e5260c34628622841ff30f661d225193a49d0ff5e4fb864fb61498f044d7909d1b9374bcd47d08476b93ff9ffb7736e043d2eeb248b93929ce32e82a694f68dddf21f934d04cdb3c7ab3ec443d0fee38d7fee08419b131774bcd0de650541933be1535cbf9b5c18085ad89f16d34157a8fa07ea499b77a3421bc3076a78e9747a96fee4d8f642998d41999e6b79a17d988939446b4edf26bbd063d6b895e4555941892ef4fedaecff36a12e95e44213ae662bc9ac27f49f70a14931bbbf9297a0e6f65b683a9f788bec6da1c91d6ef704192cfc9e6aa1664dd94f58124eb624d1420bfff93e252963a6529a85163bc5c9b15292ec5e92857a423457d60f2f56c742db54f632a35399bd0816ea7b2a2985b6e8156a49f992cc418968d22157e86ea2def292f86f06b5420fa6e193492ae497ce0aed7484b90a45e3c77d0cc25325a95485eeadf993aee01597ca54285faf5963de830af583984ee26e5fb0d23985229a3a5bd29d5726774ca1e79cfacdb94e29f4123cf6937462182588145ab06ebb581e4a8ee32894bf3f6daa928f0a1e8a422d5946874aff71627ea1d03ffc28b9dfb66684a0d024a5b2895d927892d8994f281647872939782649f784a6b4e4d16f7eb7b9c64ea89b426e68dea446979ca84c64689bd035639ca066fee682a609f524415805d764424b42c8c73b1f73bb1826b492ec94b09cf53d9c5c42d97039db2b7512c42b4b28ee9e63492f42c95a57424b196c2e3bc87639a18426e6cb13ee4b85acd22434c124933da71c49683a4ae4ec4824c9fc152b73ae4042cd549b3926f9c40ea17f84fe5ff5a6324999c4ab1d81926d11ee17021aa1f559ccc8fbd1fce96584f6d59f5e3eb34d6a8dfb0823f98247a54c427dec924f2c6313cae7d71d1584af09f36e6c3b26994ec7d94e0e6464c224496e5b4a5c0707323081d0712f07f997c421e312c6860e19969051093df35e9924891b541e1513c8a0c4495899f65839c9e96e063226a15858d22e3188a7934b7064f1e091fcc8480f12f8f831a2c3c7156b850c49940d37c8884442a61cf4bb32a50c3e8e2c0f2026c88084625a5ccbb6b249c2c7c8788426f75e0e77ab3cfa6f309805a57afce0a104198e281b25a3116523063218a1cb9c7815c3de245d2e42d1d029bfb28fbe5b5011ea8953f1429669785f3212a1ed094ace2bede460930c44a859692c957decedd2ca38847a61179e3ac9106a9fa04cc6a432320aa1be7fc9d99784109a123af7e710e56e9b3308e524d9ff4a7b0a17640842f913132659388fcb3c105a9c11a2275e1240e85f4a369be5301efef983f66e7d5756e149939705197ed0aa33bc99ce7bb14bf7412f31f7cdf01f3e203a93668cb933197b50dc2d3be68d952a147cd106197ab09468529654a88c1b84a60bf64987699091074de87676504a6df00ae14191d9957b4c93244931e601114441c61df4d1295f7938ff4eb71db49ffdac33425fda741db498cd5fb7ea467e121d3425e5d225ef680eeaa76022d47c5be82907cd2c74ac2d6937651c1479d29f9cc634547770d09364e289ea246c56ec0db95529b1f5f26e383cd69fa05b6e83266eac8cfb41bbc5c4064d25bd7d929cb5925c5a83665bb5259aa43d41a706e5d49b92299934baba34a8a1b24a9727b1910d1ad41c3669bef039b3c6f81994372df9beb65499cccda0e524dcf6cd2469b3f232285a4266781d3de92f4e06b583f26aeb0a77221e833e4aece0ad49e7681331685b614b3e53183431b9c4d47573314b60d05c6c838b9d942a73fa0b8a6e3b6529dedf79d75ed0474e32f94b7517b48a25b246cb8f884a73412bd939f5bcb988ce6f412be966d375da119fb5a06c68ce5c820967414b72777df6eb91f3612ca0ce37aee237be82de29796a11a2ccc4fc5a41f9182b7fee2b49967daba0ebf829d9bca482a2a32be67de4959ced14d424937c79620959722f05fda4509225e9bb6477a3a0668ba3a7d932fe29a1a0cb9f2c3bba4d643c414f3165c78a39bcc43191e104459d4abaa53541b7dc8d1daf4a98a0658c9f4689755a82664227e92beb42e7392941376d573979de943c494a829aa4fc5e2a49262468250865679752ffc9a42368c9b4e7abb7a4476c23a895eb839ccb65655c04dd6b339d8a39e4e88988a009eae5723666f724918c216879f3f6ed9ef86c492443088ad6c82b553229133c484610d4203e2595a7af6f2392010435285131c7db860b1692f103357fac2a994d92aa4629c3078ae713945e78fe98b2ec852247f8869cc9e185a6c3b89b263f49dcd2d985b21d7bf51f3ce9af8e2e3475274c94384adcb29c5ca8d9af63e84afa35e61117da07752f2797ee1473bc85224c16b14126415be81ee4cf49792a4fd6602d744f31279c9eaa581ad242339b51be751b7ef29b8526931ee557329c7293938526c444fb09a658a8d94c2ad9e4da931882859a67628971f9717bbe421375299868670c973c57e859c372f06b7f17e1b5420de3c9538925c751e1b142d3e6e39a3e5bd056b955e8616286ca9e2cdc6aa30a4d4e922a19aee3f5cf26159a6d8bcc1bce73f2924185223b37974a9d5d548c3985963f57f2ce639beca6d0664c5b3a39e860e92e853e722577a8203e889614ea87e5a0938e173a996c145a9724bc779844a18789d9741c6527fe69a1d08328ddcb95639f7c1928d42c268c12bfec92e7d427d4f8383a7fb4f284e673f2f535f394387742dd2e4f62cecc094dfb34c9b9c74de8a3c41ccc338658864513da888d31c4b44c6871e63ae7dc944eac144ca897e7e393b8dffe4e5f422b490675a725cf7e344be8a595736967395382be128afefa64a1eae2564aa18416468385f8be749ae94968bdb1c42bfdd141fd48126af80997e2999cfa3b13094d3a4d6d6382362569112434bfcda6c35ce611faf5954a88234c1742c5aa342a25a4112584113a74245f2c421113084944044210716301218770de31b2e386488821141052081f39701a302084103e3c470e1e186040c82030441035420251801040fc2101217eb87180903e4420840f28640f21217ab8918307066884e4c1870fd7211282070384dcc10e0708a90318211840081d1e1032871322871feee3461c6e2020040e3f7c8ce878030342dca08090362020840d387c24381a10b2060784a841022169981182861cec8d3398a10c3ec020c3c8cb08198318b8022161f01e619110307c0102215e78404817768ce4e01181102e846c814688167cf418f9e163a403202159b8410e1e18e8e134e831b202068460c1291072851c3c668458a10a3542a8e023070f0c3420640a52f0b18090282420040a399811f2041f32429c3023a409040861020d7844c7014296e005085182004292a0ec0837fb947749522624a89d4b10f3163f4750636c3f29269d72e56cbcc71508428ca008ade7d9db4614f43049042db8f1454811b4fe3031094a9874a72c2144d02b864ba7c424c6bb7221435053880ca6c438b252082142b82ae74f76334111b4e0460f4282a0a7ec0c32da0481a0c8ad6dcba23d8f92319fb88ec483901fe8169ff4b7999d9ca10ff181da9b4909dfa0ee85fe1aac64f39452cb563a7673ecb8918c00c20b353f637adfcc17e7cc5d28bf6757e9f45d07cfb92080e842134cdcfc4fa2930bad5a94971c93aa0d73d9710307ef487a6c550d147020478f1f3778f8f001082e948f29bca60a9d7763fe169a870813c284c7246cb7855679fb1f766c949cf45a682af4a9aa4d7a2fd34d0bfde4c81c7a631273c7f42cb436d17c52d92b0bcd3a93cc2243b5273b8985fedf713b097e9f354e60a1998eefedf8a33509df2bf4927ae45d083deac473857a49e5944975d989d8b44211facd24b1db58a1e67f73b3985cc4696d15da9bfacc1bada942efb6af1b1574dc184a85a2174f2cc9456997e951a1c9cc31c8cf5f82de703985221f37e265769f2336856e6eb2c8c8709de2684ba16752fa8269119fed5b5268212e7897fef6dc95c5cdd36871f9a444149a987b92ec736ed74d120a2d5b0a1f42971028b4a0e3c9cbb8be85ff094d8c9554cc524a558c7b42afcf8a59e64b5f077542b90db7259b1c73722839a15696f925f9839fd272137a92ad245c529a9729a9097dc455c89994529cf16442d70df32763f7557e0713fa5e7c3993bd3f5fe8127aac5026f97789418b67092d466b0e5bc1249584570945571e7dadb3d849779450540621468f2c7d7e32935084b02a5355b2e2e94d128ae9b07757c2c228218b84dea9c2684eb290504cca9d739217da96aa47e895ff317492fc74ec38424f5adac7e37fbd5605a4117ae6247e5bee0b27c6082d7d5ef0cd7862ef912fbc474490d87b844b6ddff01c3d7ea4085a70e302208b50e4ba9389951fff4a0cb3a077f8098c0d52116523116aced667ffbb51b9734468594e9665d13dcae37d08f54d2a294bbb089d1d0da1081372f129e3e62c2984b6592deae492648aaf0e211425efe7a67c131c800c4293bfdb2a36fee960158820f4f4268fffc504428d6f71728e38296605d9b081c347820310fae934275e09ee49c7fb07cde3d3ec75ee1b31fa41ef124a8ab1c4756bde3e2489d212258e1f3b0c1f4a4a7fb860a5754f6838b272b0374ac900640f7a99b4d9e289d224b72f12e500440fc7cd31d4ff7c32258eac1a2400418d1c02481ef6132d154a5ee57064f9e831b2011ce4f81f1cb861c3068f14e8486c3002869b60c7084860822f4e00d60082072df5c86cf2e71277211f207730103b249790ed41c60152072d499933b38df8c9325900840e5aac2fb92a1d698c95ed8e34da31a312fa99c536fba083501a836c9841094d8965f5659ba48310c291c563e4878feb61d63063129a24c74a928f093349d4304312fa5f92d118c3e47023c69135831d397eb0f3c081a3f2861991d04bb2114206a56297e6cd496640a26c1c13cc7844096638c21f0b42e67f3ddd98d188198c281d3316a16df8e9e624844a1d4f7064f5b8b16344115a5c8ad5a77465f37d80c138b88186198950c62d477f78539d7d4684f659cf928a2ffab74f0ea185373967ec5e5efa922134693c9dc526332f259e422816a7f93e7d5092d6f908a18689bb7af37751791c842685ad2ba94799c9bddd3304a1cda8f6cdef49c593c47768126604421d1f3d42eff38c550c106a752c19de22df6e7bfb832e724176d55c75f61c8eace30146f2c3878391c39c30c30f7a0e26ffde44449b3cf5413bb71b4f928e30830f9ab9c98f1d25bfee896fa4cdd8c331068d9952652a0bd6413c430f5a188f2987af1c0fccc8837e55f264c778d9b267061ef44cfff69bd96325569971072de5932544f676d0bf5d2f8941d8898bd7410bea3f67b3183463a6837ef2b493f0497a93da39e8a6217ec47e2f07cde2a974b22a1f074d49a9840f11257f901d0e5ab565d17163c34cf437a861fc7afc43878ccfdda0496249496ad3bc0dea98b527398c901f8bb3418b318c78977b78d0f41a347dd38a2bd10b66b51af4b2fecd1afa171e4f8316a676b33ebb68d04a9f9cb9b47dfb09da3368b2155bb69d19f4dfb025277d1f3ea9b60cfaa994e13bece5d12f193419971b2ed78e38e5183471e37f98d34a661e31682a7858270f933068e26f54b9a8246050f3257562684a9f4696bea0c97c25530a2b7941933663d5bfb9b799a80beaa63eabb13a416889b8a0684e6209febe6dc9425bd0449be0f6be4950ad6b412dcf1f3c8307cba4ce2ca841a58d21f245c68f492ca86153ce3361dcb4c4f20a5a329dfd35894f4abea41534dba045e9511b5e7a15d42bd93022d40913642a68e299ca29c98e915b3a53d0ba5cc4e7ba6a2c74a4a007a1a537dbc84441cbcacea5842ec96376a0a067adb11226c70977e3137493359db21a11154cd009ca8b6a934a99b0095a2a6d39f9e8e9b91099a0de99e778c2a7ccdbe01294374d1b4eb2787a62a704bdf43f6cdc14b3687549d03cb79cc76fcb265c0e09fa96e4c9f63376de6f8ea0c89361495f4ed7a61b23e8c1bcfda47011143b8fcb6d82f0bd96087ad09c7385097f4bca21e82264aeb11cbf84d0118226059b1d79b90fb7982068bb5f234ad05def0341d1b145654b79de74fa077a922f6c4efa7929c5337ca0982849d6a912eb853e72949d249dec9d4dc60be563124c4e72ea54776c17dabf85e5fafe8b3d9a2e34b9840a2d71366f36960b4dd0c9eaad93185449315ce8b5a97cb369cca14bea169a6455a764d7166ace774e165c2e4f580b4d8e38d9cc0493cb52450b4d9e6ebd3a9d472f3d0b65ccf7bf4653fc14cb42bdcc23375bcab261120b4dfc2e07ad8ce1e207165a8a99bab4c39db0ec15ba9ec69c6496fc217785a235a762b8ca1012d00afd62948e999b8395b88b90005668257c7ef68a9fddfa2ab42c63baee9224890422b061830448042db8f12301aad04d89b3394c38155ac793249d41b3466850a1c9ef687e0bb714db9f421384c688d6daccfa9ae2ca702756c7949742fd0da7f4f387149a97aebdac31c6f7d7a3d0a4204c7fe598b29d49149a6cf3b4593a9edc16874293e1bac49dbbf8d94940a15e12374f09a22d63d22774b35c428e9ed331959ed044846e9edbf2f0c1d4092dc3cb292194f8fd9a137a87ef78e2e41832bb9b5093e42698590ae2bf26d424348fac3862428632a1c91cbfebed4dd0a7c484a667fb4edc903d1b73095d932629748caf4d62c812eae8abd39354291dcb4a28b293d0b12ca7b8cf0e2574d161a595db9b8496414c94969124d49493c6a046cf98de98486c7db2894142d13e717b8496afa418324b786ddb119a8e3031c9f8cd1bb711caa864736727fc2fa518a156ba1894a758d52e971d0958842698a5b0a94f8ad03c5e4ac224e194dfe889d08498949f9d468426c89279bc663e849a239bd4e5e6cbcf0da157dc8c31cb6ed2a9c34228974cebfb7674aada08a1de59577e53ed3907550206a15bca783ff63196ac5e109a29b1b537c5986413f64068b245954ac265125ed380d0ff7f932cfd41718d493ef95e9377c90f8a8e9bd2ee39585e0cf7413b99fb6327311ff4373b4f9bc23d68a5c4245d923fc5b14e0fe6ec77f69dcae641cf9952f6a4743ce8a553f0eb1753f9e13b68f9ba52669d9ef4257650b3694ac2ff7f66c7923a184a8e25897739871fe1f891634ddd48001db49cc44ca61c47dcc473d02c276da52f891c344b4927d73a495292a01407e5ff94e0a026716c7f2f36492627bd41dd39b919f12508d9233728174f7ecfbd501b14b5a53fc33e095adf6483a2e5e4fa9c8227a14db906ed64c7cbec9cb3767dd4a06c9ee6934ad025a720a641d730c1e4913188064d36d9d8a0a772c7cc9d41b30bcf0b9a54d2261b3328f2ec72ff32883b212b837e498e79f30f611726832684be6066a71dd4a8c6a0e96062fa6352c11d233abeb0612337016250b67ce7820eed79e40e83362774dc7c379df2de0480417f8ba1ad4efc0b5a0effcf1ce4cb9cb85ed0c4bd7069948dce25ef82fa3d2aa73fedb275422e68a12d660c262b85cdde1634f74b9b93b6926465b4a0e909153fa524b2c93231484016f44d15c455ba3c16d40d5ddd2332c3c4daafa0c91bb48fcf5fa7206e2b2832b2c1ccdac2c9555093bcaa198b2f6993980aca2529a93c69be36944c41cba5b64e127b4f5097958226293965a65c924441eff132135d92a0806eda11b921db2768df9682de305ec27cc9098abe503a7b2aa59117d404e5332bc70695e674944cd03a336b77bc7f4dca5c821aab92149abe5482f619ba24931f93f49f044d9b684d39c8aa127f24a8d94d3bf7fd7f4a82ce11b4249f97ce255db992c7087ae56c3a164fbe7dee14411383face110b1693e61041139358b28c9f5071461c8296c13a3c650b85a057e78e977c5b39c8170445775d503949a7ba6420a8b136b7e4f67c5207fd009539967c429d26013ed0ed2441a5e4415bee8ae985764a8f0621175e282707b74c25c5b4a9b35d68a72d5c073bb55592ba5073c96e494ee28f8f4c2ef4da5ccadc2b949658c9c085e2b22979f2fe4d95958c5b285a5f744a952c7cf08b0c5b28b23905937f628f901735c8a88516ac24e1bb5c941021740119b4506e940cfab66983e93d0b4dccf8c83ecf14eb3e5968a66f4e89a50d8eac630119b15047334b598c5fd22c2cf4d14966ce9a3d6bcf7e85a2e775bf4eb8309a94aed04aa8bbd441e79875a715fa49d9a4bdb0b1b5c302c68d1d39921fdea314b242d9986fcfe4f555e85aa6e6ddae4d2cb755a17e86cdb4f14ff7254985f6ae95b3092d41859adbe4a04d104fa1bd7e1eb1db30696c630ac504537ae4550ae59352e22461430a35ec9496effbc9b65a2063148acca5831a954c5909a215c81085e2e6a6735e12a6849e8442cf7143a83f75cacc64648042dfa4a438e13447e8cf2712c332999262b8f0a799270a157c4c448b230bcf0e647402d1400627b4f8023974f88f1c386e30073dc5b4298986f8e8a493837682de9d8e7cb951c72193dfb32363787050de3da96465311a6f50b38406792989dca0b8c5b6923cfb9879b20dbac5e592c3a72094f86c507393cafcebbcd9caed1dc90d543aa0b1062da70fcb63b93f1f94d4a0f5f66fde24deddbe491af41b39569e3288d80c1ab47793cfebca847bb1cfa06ef0f1dcc1524aa3c49841dd7fd72c11d1942cc98d3a8ba051062db3e23f633f932ecb87839188c0d48d0a040d32684a9c3331c6207325d363d0f7cf84ef28f5f01ba6470fbfc1230123eb0234c4a0e7fb92c27826d1c1ac30e839fe8cced26252ce1318b44d822633415f8dcaf9b9028d2f68a2fcb7a4515692e0392bd0f082265be5b5c9f0ca40a30bba6ed6745662e4eecc3b5cd04b8ef915e3ec87c616b42bb55fc292a44fa8b1c240430b6ace494425d9f3c4895216d46457165e5ac7d2854e40030b8a5d50c2f8c6cf545dc681c6158c8615d40ce11e26d0a842e9c4dc7d19c6913e72a423d0a0822654787ec7fc7064dd701d33d891c347190f684c4193e9c4bc15962d576e181168484193b56ff1fe047541230aeafd8c987c2dca53071a50d03447afc297491b667a82268cf8ff64a3366f0ae9487c8cf0e0020d27e8364af2d29e2429e5679ba0de9e0eb541bc62de4cd045db6989490c9fe458db1b682c41b78d5f328bce589d9494a05e7bd89c6e5bc692fccc814612b493e56385d83ff165773ad04082324ae87810fa11b4fc939412b46d030d2368d556aa24993c455063b2aacefdd9a674308c113030d01e3062a04104cd4d8ebb2054d0bd7169c0232018829e2975886d10e3ef498560a0210465b4fbc59445739624bb1a01168d2068ba55c1fa24a51dfa03c113443e46433c347e90bca9fadb3a5ebc638707bea871a3060a4050a368f840f3924678295197356370649df7f01d366cf858fc83482fd4ea707a7eb2c70a4ae485b64169124df983c7be204264178a9631cb79fe614cc9db1e4474a1c61d13339f9d3ae4960b4db8ff70620a9627639ff820820b45868961a9c44b723fdee293213a496ee2c81f232326f01f232228c303115b68412bce2cd5c8ef367164e5a0878751835a684afb644a92f6b528d960a4070f1c81082d1479794ddf39c746a5e0c8ca1c22b3d0f4fffee5fad8264fb7cad1030533d851acac4044168ac921cc93944f495fb3482cb4a033f65472cd16fb24020bb553a514c3dfc7d75c0a22afd0ea4aec2c49363942f33088b842392574d55ffaf3ac39d60a4dcf7f6326995366f722acd09418df545275d7179bc82af4934cde2a0f23f25e52857ec9c5d49724c9a5ffd3059154682925cf6d9795843b2954689a83fdd8e8d315a2738a94d4b59df4c92b49396e60cc98640a4d5d0a8f2f6d954bff31a2021dc98f1114d4f8a2868f1ce8d0919442f1a04a744cf2a4d08250b22589dd6d6f3f0abda4ace17305d7b39645a1e80e22348b1b0a3dc6f7987ab4575d0a02855e26c43c2e66372b3fa1d94942d9dbc88de31d4f283fb715cf53d7092f3f6486ccdf38a17fdc701d2bde832ce94d68a7c424cfe8eb5c357a4d68724adcf426e68fbb3a138aeacace999d6315c498d0ce669387123fc6c7b8c825b41c3c67c5d767bf8f2da105132ad397d8754ab812baa8cc8bd3ba4ae13d9450b4537fd2935fe4c571129a077db1d2bfa8d3614928eac44cb15f772a099a4868d9f143ffc8f064260512493a8c98bbfaea72f0830718da3b727ca0c617353c0c1d890a6a7c512307fe8146a8bc20f208ed925516d7e42dbe7147e825979426b1d00e228dd094991cf1e7e92ab4ce08fd622cab2d290917165e841a94a62a9341c91c4414a157dcc6d820dcc418df4722b4fca43d65b16041891f115a79d073ae733984baed77a77233ffb7c8108a264ba599820aa19e26cd745a9384d082924bfcc87110ba65ffdddb174f721205a1ec27a5c3c92313087dc3644ee94bee181d40e8c9c42c95836566d7ec0feaa6fa12762fdcee587ed05476cbee1a2b227d504f25db50d93b6609973588f0418df3b02e11e149d01d8e2cac81020e341a44f6a09c4e4a86e59631f144e731821a5fd4e031d243033b4650e38b1a19b061430f5a6ecd22724ff897e57164f918493550c0011b360c1944f2a09cb79e0c3bbbf1438607adb2e4741a44eea0ff5f882729a72d13da413ddd72d7bdf184cbba0e7ae7cd24349e69e7c574d0468f2ed5a9626f3ca139e8314e6f0efbf3d9cd23074d535e8a3b715c0dd4f8a20609dc06236058a941240eea9879e7dbde24efac1b3a92ee24ad0c2270d0339f66bb8c77b2f8e70d8a2a25336ed0c3a8ec254e4bc6fc961644daa0271584d55e26ab9c713668e29a2c267163d757bd06b5aa34a6b34de14cb646440d7a7e0db29318f3cb09118eacdee1c69840240d8a52594b7bccd0b129354283e48795590b44d0a0987caa54976e88926bd5800d1b366c5c9d415359dc32094a689635d261f818e9307c9841f77caf5562f09c41a40c8af789b9254ac4850ff7c061c3860819b424f9b999b88c75e2c70a22635053d2b1b92fe5cc41867064f918e161b820220645e6a42e4e949c3d69587b0b2261d064ebbc9719b3fe6512e7f0b123c7221b44c0a0e59f580c2ae87ba592c817b4136e43a8fc4ac40beab69b92245562c8ac1dc408912e28ef1abfa4ca301c44b8a05dd2399e8c28d11ab41fc710225b504f763139c85538ddb17c94d28236e697b4286d725031dd238c1fc98d248864c13f51a344369f902082052da9ac983fc959534e572a82c815b47416540ab2f26be671c70c729c20044610b1826e25b9c711bfef29b68410a982729784b608cb53414b499d943c743261df0a84c814f4ccf2d85e2e16df495677109182e295b9597ef2547c3f0a9a9864386933f42971311414cfbaa727681df43a4686ffdc25e904bd3d67d9044d8f0e9eb5043d35b2668222536cae3ccab2681b97a058da13222fcb4c259b0a224a50bb933621771ff3f44624095a097ecae2e5bcdba20409da88c5c5af125ef425891c41711346948aa134840c1231823e7ea6a12a43bfe90de540a408ea57779c2496799ff644d0458c903fa2a487a076fd9d78d85908ea9f12de20a81d3f89db9c4d2953920041f9fc71caf265c473d00f3449653149dca0880f94cb7faa82c6ceac782ff494bf7b5fcf753f7bbcd0629f2468cacf4a5a5246464880bbd0435c12aec43179e92fbad0d39bd020535d9b52995c28d6994b86fe1617ea770942278b99339df88c5b68d226e1b4492fca3f9966d842b3f22f0b2d622df4785d735bfe9b213c38b28c47d26305366cd04213af4b7b94269985163f552e9d64076161862cd44da3824a9ff4b69e5b8519b1d06eb38df7cdb6553ec1424f2e3a7ee4c9afd0e382ef88f5e90a335ca15ce9cb964cc6d7aea45668a5e95a4fb6850a3358a1872f492f09d9599e3b1466ac427993b594ec3e69c20c55284a0795bb94797d70532a342f255d7c0925c9c89425cc4085163ad678978af313944a98710a4d186bdbbcd211334ca1cc5c296d76b1ade2efe1355000821add6384dd04c804624629741394c8519dc3eb9c1029b41bdd24f39b280d3346a1e906ad11323a6698210addf2c40eeac6467672c13023147a923166bb0cd3f1abe4c20c5068aaf4840cbb4f08667c42d3174b5912764c5737cc6aa080036dc346f200a3cd0c4f6829976eb1badeebf3744253b1c1736e903562c43338a1c66cf71a36df6383199b5093126d23229b478ef07eccd084a23aeef69618c6919583cff1636487598f199950f355fd58e8cc6d9e2f42f0458d15b4610626124f50713f9d97ca30e312bab9f8a7f6f976b31c1c39624aad4e30c3127a028c02a8b44f6542692c108983c150401000902967020314000018141a14064391501487b1b27d1480035024264834321a241e16141a140bc6815020100807c26050200c0a8401a140483c160514c51f2a0b03b21b2907336d4d86b1b3357316ff74bc3a89be68d11babb4fc3139e8b6ed9afb5377d70b290a7d1e78112f0e279636b09344c54a306e772c682751ffae301657f81a6bc2f6c02dad2a7252aa095e98c3de30d44d65925d58dc8144291b9ee629cb93487625f78486ad8e3d968c5e31ceb8dd112247166988216601ab2caee188600e0f956ece9ebc32a66054eb9a2be905dea7190e1b30a907f7713755db4fae420700e5638065575554f83958b3cac301847e96937039688df8d0e8ea6c2601f9da195a50c0d5c9bc39e422460dac55f1ed92207e79da3df21f25489c60cf81a3c4aac0e235bb965a04ca965bdc2833078a6b52ca50dc4c5ca93ab323b68b56732c0909d2846fe41be491912a5a31dd8607241d4eebcac1fae35caf6cfdaa917a83ba46d67036aa7f082f3647e101b3995a35b0d4408e51287333e97c85a87a23e86dfd3c5daee58d18985b6a013094eaee226b1b015c798bd426f1c5802047ff5827a5476ca9f178553fcbaae770fb30a8c1eff39edbe39b4eb3e2e4cd856ef2032dcbce2db8f1c1c751f369a6e66535ad76561a0d8d58388669d5b7de337cd92d3df4a80f4304e0a98dfa5ce08e58ef71d997a3e25eaf86b7ada391e9ba8b5211c3667ca574a8e4511d0238adb3e12c491970e0e32e0c0ef91f81de1d04a9031c79c3016ece8eb604c5141cc101861c2f0721a526d81b5cdc6c31ed2f54f251f27d6008bedee7decb2ef955908ae1cb0422a7465c2fbcb1214452a75a1c46e76d3c894818b12c4940620e50d5cef6710073566e967fedcb580304eb438e61d6c2e5609cc72968da8a0414aa072dd63632d97c25a462f8c4cf0a0cb68d67e0df97981b2208d983a105635546f26b2411aeb96b4387975bb0fa4b0b0ba0925dfc1cb8e4f871c8aa3cba8c78b0bcd906b41ea0b1b09472edd069933016070e3a7cce5835facdef99f242997e75c422344765b2fa015f9807cbac0d14c4e80b456a0bed96057194da3129d4b1d6e81b59f32347933b4cf1fc927098fda6a62ad940db909df320758e2c2cce080f2f434b3ab662a87a53d8e5fc48355967070115952a5391576774bfd5d64219e0dc8071a40abe439731ff72cd60b3710ab439079d8f5bfd57e5f2cd2cbed9036c3112f2c7e004fe2418b55ddb66e8afe54d69d97adcf343f4e61b6ede9e402925f9e1af7e1f5ee5e50c9c1852e653077e4694f73846600fb4f3ffd195fbc486fe395c8631a888c5dc862b449f2762c4aed3e6c496974ce265474f66231cf55780acae835de591e5c9c987d87a12c43703fd71e5ff03ce9c86ffa10cc0870da0184f4f1e93f2a252852d16bcd986eda0cbd6ffc0ac60ec0d32488a01712b2905ac750047e67a486dce893dcc7088d1c77624c955413b009caa123fb2168877d6970298743958d22edfea9626b0884450f260f1440b3d2d076bf91fea0c99d9bb8b53f7360d9ccb1dfc10627452edd4a94fe9840ca0716bc0421973945b8fd3c1a2557413a29db4c68d8963b45a3b251026d98fdec07499f72c4ede494bca1af83d7ab51e2f4301015102c4625390624da23ffa962c9e7d68c268394cc38d88020290487ffea81c3aaab90a2def116c0cfcea0bac18c213a0b1986d56f751750576cb468ea5017896fa9622954e285c476cfe3c3c51cae0c7a0fb6e81c166a061eff73283947493eea8877b3b21540959c9261fcbee5651797a68d78805913787cd19d84adba56a87aa6c9a1af312675670a838ff30e109e109be67db8a8041300b52e995173950849e12d9043d9c180724348da84052c746520dd18e455c6a9a21ca69c3f5393cc45ce943fc99fea851e49748e989c47027260374a81194493c885479a41d4932455279e32bbce50994f219373859fd4f781d36843fe59e7f4b52fef4f9d24d54921fc5e7dc9adb5ad502bc6e0eb284e9d88fe61c04e03901353d87e46bea3f27c71232847efaf58102c357ef42e6c2f907be8706c9ec44e295387f4951624656f773d064103fd9da6240269489245dae4e4f1723c6acca88aa3ac183bbada800a35d037c0d6eb334e2c57bb0855a7c699109495b5eac8b25dbfe98990f89178037f53e5ae8bbc596fa7f083c1a00105f84335264afa8774c3786615e5e1de817c44438e9f5f48e2ba203a4960f9f2e2a22347932c78d1675553b3f22a7d3a50cf7de2b39d1a345c3246c52b31518b12f00435ae20e65f80d13b44dcdb6837c6dcf97615c6106f793f549defaa95ef4f2d58b474b499bdc36e55f06cbb8f3996b0e560fb93bb777adf6ccb3f5af9bc8a2980ebd136064e51433b0af367a6b90ed417f5164c836ffcbf865c4c804e26f6108ce03237a924f9402f78cf8bd60d5e43a32e35e88d3d4263c9b9c36e9be996559a6b5bc7a6abf496280a38804dbf933312b64ad1791889b3396c25e3b81490ccc0550a9c190b5dc4e7eb20ba6764f9fad973d7e91ecc631b41bcb21f85b8cd01ebb60a3e9b285c5883e427da7db511eecf1d8d28466a635e28916614062901385fcb0ae8a9854d91b24d2cc701b86aadb80daef95da16f6abd15809733cee3378082e11d8b222f9351ef98a0ed9c1ed5e3e550c6cc201d8d80c2b6e304ec3a6de951cf812623f59b935160785de776820e35e363a8b22c3b2b6f08a7e6f56e8f2c2230f9b70553723ba693761d03273605da017bf9b41a21e68bf89886504cb77471404d6bfc046e752506fc16c57d0a433612496883504ca5da0c81514a2d6fff03ca0569e92bdca28390710af7e80a7e21602c8002bcf8f2a038511b708f80cf1e6be3f80ded122e082ce4e3ac0874da9e981b0a8eab198ee8938318f3e354006291945009a5e7a0b03a70ceef3ff9cf96aee7b5d937b84ac0e4f63891442ec4e5dae090804cc930a6d65943b72015cbeda2e47f8845c07277d1154dd4db9024fcfed6bb3860061272e21e1b2042745694c6f344d5309f204e006191207bc5693415b9ab550828e43fb586f1d42e0eda887f86eb07db352f56223a0896b2749ab01b5ea6920052f39132ed15ca4cea1a343a1f2170da464437b1b819620cb398589a6c352667954007f135b8a18f8fa1593cd0b2601a3e1a8a5048375a8082eb1d7a93c706e069f25533a1621d46953735cfd8e4f456ddffa0474ea1eb534df3eb1816168b2aaed4f8d625842d40af1e5e17b1a4b43b44e099e2d71502b480727b70c4711dc41aae6a2f143039415868ab8c3d8d7b46f542643b0cb30e4cfb04add480d9454e025e401bdfd26883a78776480d78ee463789022240248b7c84b3d5dff9ddfb939d13833fc8899746145fa8d9d405fe924ebd867ff8ad6cfc6dabd12c9e8606aab6f84348e3d76c8c790b9b004b390fd0483c3bbf1ed8c98058b1a9a05533083e45db01012a135f6cf1cf16d3e1fe92cc4f38b9e05524f4cbb2cb370fe42252f6c00980dae4d8831f0f754e68eb8c27377b00cee4e6683736259a94f2b06fc95761397ed241820995c236f7cba120170aad24e8b3da4958f3ca56d87274f075367221bba823c7cc95f15a672d8049040e1ea4c45b8c6731010b5cf47f0830059862af2f7a93bac90e61a12e0ac42c76bdfe9b79941645d7126a8531e3b96521bce1452a1f409130105072cf7a94f081579154704b5489a0679b382daf6b79630b495a156a82ae61413e22bdf7bc86822b30e1facf24670bb4de644fb48e14d9d8094ed02cf689334d73601ac498aeb4aca97131a7846ecd02b11a0301b0bb2d7556162a2cd728a721dad32f55135df965955f1ca31e99682093cbe56870c66666f3144247571c3e8f8142fed0ef74fc021fe823f88c7c3a29762be820917a41519ae5baa25c21ec369546af336ca86caf177a86c24003b02cb983df6484c6bdc1c32fac341856c1882318ea3d835813e2a47fe4eb93346090536889c11f616682154343420a9180de08f5abe4bb8d1ee23c8f3a358a53f6006655a24acbcbba2fc546a66f0649a8c5a0cb49a33b7504ce804c343a6bf715871b8096144bb7aa3a4328b9424bc0dc869b271defcd0f451d411c50c07ec40fe686761a00b9521e198556f2258a65191590e1fb8be71625330032b56d7815561768c89ad6aae70ad74aadbdc7c3c8251c85abe1970ce8db9eb7e382231e6100f542cf545f49315c6461000df04ad13f8ceada5a60b3e0b0b383ef6d9e38669201d2dd43d8f25f180c7e801327dd3d46b029abb31fe2fe72187740f2689eca214d6849a4721a1fde78c44373124d0bbd7fe0734a734f3ccfc1d68bedd02e943cad8200d12808ddbed06fece959c12ffbd6e54fdf5525d10f1702dccecbf72d8e8b617c4a1b227419b853342cb4384e2d89331de7b3a113c2b82a9fb025f7289cbeced3df00e122073a54bb962eeeb96a335c74e6b6b7f912a390fd6f8c0865b1071eccd433ae65e97e6eebfa75fe93df789cd2e43d9ca38a42dc50a6ee6d963b243d563be9fc931b34db65b845cfc4f6e28147878d41aa8a19420a8fa1f0fe31f93787acdd7d3178e4c224e0fb32d16d2c8e1827a864bc26961482a234b2165a87bf250fb7ae53522c3743436c8981c20a87a8c0ee8e4394e2efc614070417a5860956c64ecf698692f0f26d587768fe6b2cbcddf13b7576b8b7e175e23654a90a2aba0398066d860aeb8d4cd100bdf8efe8b66deec63044db3b73fad48ac600c506a40e3e59bb8c0a39ab92800e6818597086141f19b534190d0d8e48d4a0872fd6ff29b8ad3464038e8d6e1eec39054de17c9a277b046644f46241b4eec20e19e97847b6585b673ac30d71c1f52915adca14f9179c0ec6fb8b91ce717701bf9b20a41bf741e84aa49b78fcffb48734356c29266b80f6b12044c6790456d981712c64ae1db4c8a24e6abeb55b6ccd5010651b4a2bee6b286ceca4820de3397193d31a38a46fc500de80c7a415358e30e2e1e33ea807e41a7a617d95aa194be2668a096348535d8b68a24aaeed299ebe8d6ab50190ed4192060d28a0391e1a318a5be28be4e82a84267f401e582464d43aaf56879341b4d20cd738d5643a0d11c7aa202041e61142c5a8dc6e4e812b334027a8f5aa264d16c3481e646a3d18a065dc28b42381bec1595b5973559ed011aa52def1a5d28030a56994151b3e835ba88fe4597d1fb04a5260466da51b58b2aefd2986be9d62a6bba6bbf6a09b68cbe0346411fd7e9df0571062125a99ef58d55aabe5a947cac81e0097e2cd4ebd01ea38c3bf4da0ca0af06ce497f1707db8916d0b8074545e6a305c19f27b3d20e726e88d58644473427b1a697918704b587091ff7a994081a455909dd246e4b8e971d918e6c8ed81d191d811e613b923b521db939221d64324d2c8390a8255c9e731d09ba46b54ccff29fd28102025cdef1b1c023b2eb9d5b3e3247604ba8831cd384a0b202beb88171ea474ad20319130e9827c3d7a3608835a2da67539b48ff269f018071c1f7d2847187382ea21ed918c39000890025339079a430cb97ab45580c50b5a3ac04eb11cd484c30d63e9c53a008e0e004b50a327b797a78110c95192725d0980325dfca16078412d295adf8737a586f98bf7550d680259a96b10db6083a11647c3a3e7c88a7dd16045802dc0c817fbff28d8213ec03fe079f803b3284e15f0920228254c0f2e099c37be2380714583a85558790c11a32861ecd314883415367431565fcdaa07859f4b84406af7d276fa2efc5539b6f59936164676267dac8e2d80d0fdd4b0ac1903e98d8a69b8d4d3629eb74e8a61a4e96dbcc3656151c35b89945020c3e16bf993beae5e457b241dbc6c7c6b68d1bef66304017b5a5a21b62cfc98553cf26459bae36d56c727933cc82357ec5ae0d41de74939306ce2c35f4abf05163426d86311a28811b6728371bcd390ece2cad9a7f35356b3203d3c611ade3071122985c9127ae0900538819d1906208608b491ec169a610984b8e2b9fe53a551c2b01027d957c543a496904df4b42638faca11de353f304f16f3a17a288bd2c903cfb16fe2243d0346f5a483041f0b593bd60cc27882f6cf6d8cbafb9e634684ad6a72efb69beafb781601c28772c11a7cbfbf194aa3f8950ad731d04b3021ec20284b720b312994f52a1d4f8985674d5b82c6cab4fdc084938d1e642e861418074bf1c5f552fa02a97e42bb0df345b6888225888318b756788d28b1f8b6a4be3ea530c3dc928eb45eac923fd079ea4f56cb424068d3c349a30a5cb3d20f9e158f1c11aede25b180c7e428a6bb58195e94a1fc7ef0492015948ab5d1596bb63076b8ebb0a7d67a9ab35350d850f002552f19bbcf180f11053cbea22158215772abe736529cb7b3ada6f04764ef0b815401168a1466bef78baf7cd7ace53b5982e95faae0a5180ff08003bc880f4610c63ea595497e38a2ce30c68ba7d1c90dccf0e51882b992430e1165604bcacf7793cc191b5cdef43b4e27730a323c106116d4581e7fd292abe7b82623d912a631e60ff5a00ba69017e379f9ab6a4f23b98e92f8b0a89a7c93df06dd606da70349c0bddd32000060897aef56ad683e4e88368d3a8e3acec301b22900a6eec7c984e62d943bfea7bc240d2e82e374a9fd216fc5fcd35846d4e170ac181842208f10ff99b141948219a4b16a20c765890a813ac1f13f5c0a12553ec4374e6d09237c282aec5c8b0626989f3f4d4284666fa3cbb1ac358b230a105fcb5511347fa44ad5d6a0c4158b7d496510535f3c9c20618c729bb1050a0addee42dc74a1c8ce7a995b38f301570583765499aa65912cfeb0ec332028ded76c942901b3542788651b9c3d536a5c148adf45e94e39ed638863ff98a1a19252bd1b5f84c08be303ce0a51af96ba388504c7097f14978e5f010b1481debb23723645b3fe367d8dfd06d5842187b980aacf31abdac5e9caf7b617484138e5eede8620c71c0242f7cf0263c41db3db3f7ece3200cb270814069d036f0d6f91e37cf49cccd63f6f46aef92d195326005597d9d0ba384c10b1e72c547b5d54de510560f0221030fda7441b9adf7980229f9f59ea347b17b1b01f69b34e52dfbf119c682e5bd9a2ebdebd3a5777dbaa8ae267a1b21daf3300b0fd22bebd579895e7c7f972e8b8d6b28deab77cd5bf4d6f7fbdd38620e25f5104dd8038cf14a79755e8ad7cb4bf37a7a51beb28455c264301e78134abf9600ca209b57c50be9de023da2a9e2e90367c3034ecc43f3e0c21518c88681a0c0f7e810bdd8d6418817b57758b537a7d9d8eac51b9d8d28bc3b82fed86bba3947b432fe8d4e7c08b1137548e50edec1fc66abc029bab4eecb9e056ee3f8c33b24c90a782254d3e050cdbcd479170e7d901a93e7164e07970cb325016104261c7d72ec8e134e0c8d7a0b88a3b233deedd18ed13a3a7d458d08633f06ed19fbd7ecd397d9b4ef6bc8fc06822596db0e396c582009a9a33cc19b77e4d0ada023b2602bfa6a12eddc9d837614693a137acebbb1cdf3e1d7cfdbe2d18ea99c644b93f46613aab4dd5e445c34f72620c5a5b97a6c5f3e91f7e910623bd7c69d0bad5509da3b7dcd2fdfd7defa5c8fa940e53e483d0a1707ee21ac053ac32706dfee3fa3d6b9b52430423c0c2e626718aab7db6271cfc7156e24dc3116c01606e27593e49daccfd337470fc7f5f5dbde4a91ab67df6c199661c8632646106c6f093feedb0e6af37bf7ed664004f5346e6ccd8e411cde467317c945e5834aa499ca716b6f9583f26b81f8937be724a2977d4f341e097cb84a54f37dd87cd25d43a3f73b4a544b3c880c8dacf858eca3bc303661f5f881774bfb46185d787c1cf2709e91799b61d6c5b300ee18c0b64a9a6b6192f15a3405017deeb2ba3986f33e02f848b7a5b1a2555dc7e7011ca2aa4aba0970d6139071e0671a8e9e665a43431c345428ad2f6be9248d720fafe77ac636617c1410980664a0181fe9aa0aea86d804a3cb191e3e2b9411ac8f02cfd9e3607333cb48776261f90278bc63513de7926c2e6c1542ba9278ffe52637e78161b219b091146222f28996ac7d40d693ea8d49716de5b444be99b5ac47be0d58d0a7ab5d5c03a8167e401199f5b39214a01fc665d150d5a89bd5bcb63d62b25dfa97492ca7d9447b4c2f09a600352573fae1dbbe7c20c068d0969c76975839e09b0088eb3506bd3713079d1f3238d418040556640ad8109cb4a0e532861f4ea376ad4164d1153ac40e6cb50fd57903e0a1fb0049099bdbcc308f3cdfa4c28a037930627175f643486f472bf70e5fb5c062a2864dd23c058104a50a262a1f4c10f0bc6a1d30d519725e29abe4b15a461c91afc81cb29026d9b03207ce3e12898845aa911224b693faeaabc4ea807c88b8b1215d195123a151424278f543da2051f02bc009a480e21f1bba1780398cddf1363d207af8b398a53845dc098bc25f614df8799827ce0857c282f0475812eec7a16cb114a1d20835c3fd893c3004e197530804869c735561020ee78ad890500ad81e62664638dc634cbaa25bd3daa63e4b2892d802d07fcc6acecfd2d12a69fdde7a75ef78218447a39d9386bb067a11c352389f6224f00e8826490b709777967a0abc9cc19078446423d598e54b0564080b9169a157cc2c025a4f6079b21876ffcad7c9e811c522cb8723209b43fb1dce718882b649398ce1220e1a4b7445e76d4373990a04986e76897bb8fe10d44cd7c7def0e014a20112bd323b0bb5893132180b105d812d8f634a43d068d86e886f78f284b843748f57ff17184852627f5d402adc092ad5f34016904dcf928bb9845f4de6b4c8344912c3c84b18e25d6222d2cba12d302a032c0c4b4f8bfea1461b26b19b503cce78714784c9b036df4a79561c334e10372f08a8e744820e7a21b90351da009eb44a7d95bb47dcaa7ff643da2592fc89445f43f8b5e30501d2d74ee4226d225b2fe799ce13dee84eb810bff4f4d4bf0a8441e694d6278123dc85f1bdb757ad96b4739d91221125090f8dc87ad8b6db19f77bf3787cf695a3a0f5dbe4d384a547d6086b364466c87c24ef118c04a4b475f55305d5f6591d685c167e3cf14e74410668d025da5c3cd1f5a458f4b5ae676fc9d395356fd0400883b4c00e4b8b12612ee18b94ba03f8d37e229384ad250821e93d825d9fd40b904628e5812e8611e83d6065b077abc7246df0f814da40d2e9626e4fdb4692a6babd72906eb5ecdb6b80b8d74392ad90d825bb64a5a8cdfe4ff2e470075dff711c781e05065d1f43aad017fa74974b2a72b0621e52e2d70db693a0cf3cfe59e2f3a6b0379e0dd50c592f1eaa4087c4d29a04d0f2ac20a56ddcee1b694a66580bf246c3b6ea4e3d6546a85c668c3da391ad888d4030f78df098fbfd09d6d76e5c3c4adf646ffe866f1d7bfb1e8a5050a6f8338f6583741b5454388e6f40311001bf510693f294bacf2a58a5188b22ebf827a95d5b2413bf4f320d3f12aacf676d8a3a21c21824d6464860f8120948b7717c49cfd65d3831485d939da9bb9b799d206fdc85ab497590c467ee71ab401fc74154477a0f33e2d9d89a0ef734584b1a04029c476b02e1cf48a881d87837b607b1e81a2e5a50400ef37eeef2df4bdf5fb513b42100687b529948b9cba8676a795acb347a25881913d35bff2505a26ac4b6fdbcc7f48ddff25b83056eb688e197de7d37368f655579074bfe228b98aad3c8087391e0aa0c60eb6892cd5cd7cf95ab90be7a99675e524c3f2d54b5cdb31473374af901c361a5ccc01334b5ffde371079eda096ed64f0b02cbe7afc993613a2a25ad8cbbc6cf06c1985b193f9ce4ff43ad02c4cb54c5aa406798290170e11c12fa81cc844da4e22d45b27e16fa93c41c64ba525e9318d6bda0f2eb679043555479b5553216d0eb40588836f79a04351454db044174d514f2befebc1b2456fed8a413852727d852fe8f1c93223976eded7fd13e34709802c08736d6dae109bbcf789240e6f156873c3212cb9feb1d1ae45f0f131658e607f6dd93d3ecebc08da3d001e20658e3199ffe3eeef560af2f118b50203da4e53208f3962554d0ccb47563e54113e0216097f28f431ee6f7ed49938a952d403671a60d44dd015a162076df240136b22a9fa6fda13fa39440680ca19539bccb8fe64f8ad5a696326047093130c2a0013ea282c1ec457a8b6137afb957785fe4269b950642449ded816325ce8b3d00da1a5fcd06c66e7ff6b9bd00721ca422c1c226b1177223a42a8b4d0dbde28f94393d0dd295482735482e510d22d74c818aa5ec72d470d870859e495a8be502a0d754a54bda3768aca50d4b1a2742acaad8e1401f83a944b79d089381b3a0266ba90fe6ea835454211653314bfa2e89128b74e961e4fb52000fec40379d6803516704dcdb8faf870459a1156fd61d50d8605c94ec018ec4a1e2be885ef55e3298c92e1698f983c2282c2f8090b77dabbd260815c03d92741e61f1996ffaf859c5cb227d0e96014e68cc9dc94bf8dcc3f256d478783d7bffb8178fb73c1dcb046f42cab28264fad098154a90c33f43c54c1961bb6206e7f818650f3ec6bbc778cc6cf964586a45af6de16f5208504c80375c5179ee9d24edfc0c5a8f139a3ebb064e588bfac2e980935b4b92e266ff1a3f44b108eac472bf6aa232c31d4658259e9e098ae22cb3b47708e6c3649b483334bfc00c731f264fb9280b515a1d55759a922e3716560ea4eb315c755d49a122a3199a0d7c457311fb0b02a05d5a07256f03aea6e12d0c4f1a563a5cc213a51f74e32d0fb9d2add8af5d45672c4639284c1c7c3e0eac0740f73948be82091cd8de125f55ceb550069d9f20e1705d70355322c880511c2a8177bd84e6f385fbaf9ab2cd096b3469c91b87180595a0c621b3561613a388cf265c51cb14b10824e6cc1ea331dcf8c07852644d06cea3ed078146229e01a721ecf62f6da953c4d05fee4d76b300bd235439e57041fc4dae95b0c52ce8c52677cd6da8a30fdd302d7ba4ff6b7ead59a05dd1fc52d726cd3701c4f4f395c8771085b8408a64ac526bbb49c71f03fa3a6e2225ac462d58dcda60be753000cd9b2b0949a17af0b50b9dfe083917431477764e18436fe3195a115fa701b50b1884c6e698b9be83469417c17affd3959e0e064367c74fa746b44d335c56cc6952773d4925051b3f90e979361d28eb55438dbc3eceadb60c0e01da1ada008117099a9b81527492554db9c3d1bba00207e94eb1328f59b2d61acd4a2e157f8cb440ae3dbba744cdc38435eae167df2da716308abf45742f809cdedf32d386d0bc9fea5bf723404efa203851768c60766bdd1acf9afbea9805f3182524a84c82af9cfa28032dfd49a5d553da6a75cb5b8dbdb26421877b35b3d75374258ddb1d2411bb113c3dd6e5592d2e40566c35c8aee449e1e1e1648a86d01ba135fcd4362bcfede1387f5f5c40400c76f3fbac0e76004c1dd15913797764d795dfcbe3377c15c8067b78e16625d582c27eb49c5dcb5c1b64699e3ebe49538cbc51751c3091ccdb936c81d94ce666ba609004d62a9a90d246efa0175afae4f6500e8f8801bb0eb738fc09f181235a362c4bca2a2a64f364f3ec486645dd802170b2939613efc1ed21a326a34f83306fd0afde51ea7fb5b769f05d30a0fea525bbd4cab691858caf236924f8c1130b04f7a62218b2edb12f3496fe11bb4355e4adff858a8568e1eb8b645a532d084beac38d253fce7f1547debb5c4b3fe22c2b4614fce0d7de157cf93344ba82d0b3af8c08a05916958b3c5116bf2d47ece637339b35108b50f4e5a8383b20f1e81f00f06f9a56b05be0b1c8eed162ac3d515d24edccedde11f36bf6b3a0b8a631f7259f2eb5fa25fa558d2bf74d9952aae8e8261138d2b6276c22a94f95daf66f9917d1af074940025fd080dc710d94390a5e61811b23f2cc2f903e62673932377eea58baf5434f10949f7f1284865da1cae6e4b91d065e204a0e1b32d60cf54420b650bead31b41b47249cd9fa3b9c5051d6d913bce6ca23c426e9bbf1caea335807ed66f98b8ab889db91733399da871f5dbddcdc5a0162e6d07381e72a08eb505cee45c9697cb002335f5524297f292c6854fe4a64ad1c2c7a27fd4a49130279efec07b34235b922bfd158d435fbe92e6db700fbd359a8154620c66da75148dc17d00f24e282dbd2cfe05a4bddbd2170bb3f4c9d64fb3704f90694577618ede99d55d1cb38f360a6bc3a5d2295049f105a2be2f29786cc4b870f551ac38c9dfead41a6922bd2298632c207d48ac4902aaf8b3a13860b46439330f0f0f0f0f0f0f8f1c1ddd08a98d7c02a932c924c9921e4b2db325c994529229929ece70b1db6e7b98f87466e2d39989182801570a080a280a17f8303474e4809166a26e2953144d29d9c08d2e68a8a02390451635be2a081d38e0e2b7588aa7534c210483c60d5233504001a3808e1ba0bc374a0e2946f3aac8205d74d880b5329dcfd2422899ba7340470d8c1d94a753daf7633ed180cbd11de1173972f067c0f78996c8abb6f823197032c6f2bced343aa463c09f8a9713bc279592c180df9ccf36d70675bce0d815ad72f24f50d976b8802f99225570512bd80c9ed39584104735c30ade2fe6a9fd2b1399e52a98a86d6d61b5c93eaa6043ca2a9a49c454a4226a568d4a4a79083850c1f6a6978b5bffc4ef148c2acd0e4956670a5ef285124169a560d47b98caa7eda96291821d153f988d7dbe9846c1bdad6a5e2a192dc78882b5bbcabd8e9f739da1605762cceda9645249231ca060a36d7a499a193260d4a091bae0c260c0460d1a0bb05183c61618b8097c004600eec0f10936fdf77fd0bce9a17749048727f8f8dde29a8400b8034727b89c16d4c4ada0b2bb3c46707082cda9abf27ecf543c15ec04c726d8aa9821249def1945706882916ab23e4b73cd049f7fbcb2a4c5f4acc9220b0e4c307afd3de531cb2dd3f3392ec1e6c7184ccbb625a64d2dc159eedc9543568db89bb2858c1b5d7880a3125ce8cc7a42588b7fdc500b1c94e0947a9c1c6a524f3312438b548163125ca54922b783d28edb9004eb163bb3edefa88d158e48f0a9f5b63e4c24758cd210c18d2e68c0a8f13752c34083020724f878a5be15477f3fe378049bb9d61fd404339d238ee042a307193a6769897a0cad1b5dd06804fb93640427a6ff5490da496457091c8ba83cdf95adc99db41b4570e9e2394410c5d0328e4470d953fceeba1a1d6318434b91c0810846e46bc81aa24f57d0cf98d185081c8760dc93a8c81579b4c645096ac42041e03004a35450d513c1dc7d5365078e42b0d71eb207b51b4465afe6c04108ae64dccb5b7d1a049fa74a87be5504c16e578974fa59154d1308f6c2f3f37e4d23c9910310ecb725939d6df9037b3a44d39e34d7a75f86c30f6cdfe9cd1aa28e068e3ef09d22f4248d9f4608720e3eb06d3adaa592b68bba468cdb03bf9de9441051a52c1394006d0f38f4c0e56071dc425f478fa12f85230f4cf0a473da1b2162d03c2a78e0bb94da0a7529875111f8d0e2e3021f5a7c183b04c71d38ff18f3e5c8bb61a27124e3de97dc8ec05107768428193c530e071d38213c83c83a5f060c159835c71c185d13dd89571939701ed2f8e65ae7ac93230e65652eebce9b02074e7889c6985a938a5831b462dc9081827c031b5abd4ae888ea2538dcc04591f94e780afaa795bd4a70b481cba05793965c95bb3f071bf837afcd50429d8813df82630d9ce9ac5b5adb520c9d188d34438601800b1c6ae052c8a64b94085a3770a4810b7a54a6ceff914e9d0a00c2c081063e8fae47bcfab51c2d05709c81c9e693f479997cd30b963a7098810d2962869d5ab19c3d1fe02803d79bd38a05e5a71d1978d5094945edd06cb9bf81630cec9a6a939c83921838695bc254ed29256eb181230c5c85baaad20ea5e612303041866eb06a0bc172b4c1f10546994aba3d66bcc0485272ff745c4f9dfa337074812f1d6b3b948edc1282830bbc46494166beb6cb169d2038b6c0654b9a18e358b01399f4038716783f699f357c93f0af141b37686c6103f9c0910576f3e64cafd71659afc38a040716d8d7fbcff5bdae9dd457d8f35269f00e8db102a3f4c9bdfb8db4215e4c1558d72dfd112de94dd24205b693fa50b5496bc8949f029b528a5e5eb514f8ea50952d88769ed24781093945f95824ad9322287031888892495350efe92774193a98040e2770ca835a3da1fb44594a1318252d620a0ff5d7baa98183098c8fc85d00c1c0b10426779f9b6a532b7d1d871218c99a9abd429f042ea9bd9cea2ca68d7f41021f3ba61c8356ce14f4b6058e23b099293fe7efbf0b5293050e2370327a8a9147d2c5d46963058e22f05b23714dc7dd98f12702ab6642ee8f09e521a22130d93ce6bdd15a086cf2fd72ebecaec011042606ffece64135e8242070a6624bb677d30fb8d54ea50f586b8ba555e47fdcba078c08f9dfa45eefa9c703ce6c4b56b2242a16eb1db031cdbd5c2c6796a80e585b0da52b5a1e8f174281a402470e1865a783899c3236050e1cf0bfd9a244cf9c2570dc8091b5f6966310396cc09dfb5bb999f2b353e1a801a324866c9a216920e0a0016bc28350d125399f8763066ce92416294d76d4f148e034b6e800870cb8bba4d72353c8fe8b60860c0e70c480b1ee58a51ff9185ac80103367f7448f6ab2692462cc0f102ce3c77904909379d825025c0e1022e7b65d10e328790658aa1653cf0a2155cd24f4a7f0e1d224c419700062bf8bd90a35dec12321378b10a2ea395ca654a5d446b94a9820f79fe39e6f63cbafb185aa9e035e99a6a8b674617da8117a86023a860a6ef239e82b54d75ed1b5b9474510c2d1b68461709069a41e3c050418d1ba78117a6e034bf830e7943c60bda185afea82ef0a2145c56330f51ef2e2f48c17b58564b927e4f9df15cd080f107068d1b304840a3ec28385d2ae9cd1f4c7454ad17a2e0f363caec5d3a4b726aca5e84822d1dbf5474074191a634b937bf983ec1fd9f7bfe68a3af49e409be84d4f893532df2ef9d6023d5b9e87cadabb1c30936f8d88d4693be92de4d70234bc7e8d17f847257139cc864a9ff9dabc4a399e052f49893420531c14ab2fc99d6c4f7f4e512fcc62821bea6490cadb304779a3c6216e9c1844e4ac38b4a304295be982e4a1691934507b4f8d8c087161f1840c0ff02d0c320f689179438ef7b6825517a4fe8b560f06212dca87e04bf1064f4a08ba105a3b048824d7aa7d378a8e98ad987161f1f1988c087068ccde14524383da64255b07613df8941825fbf0a2aa748316ae93c823ffdd274a63a82bd9c34055d7d1d6a9d4670c2355e0cda67694ae70c2f18c17b5a64f7d4680c55418d1b551f5a68a1821a1938412d82cf2e31e7a07e62aa184570d92d77dc90f375f2cebb8c2d6cf89f00c60d194713c1c934d16b6236a152362182499ec294c823c754820ec1e6cdfb1fb4c9d4c17343f05152d24acb9596fe168297543ad72b8e84e0acf6525ceba0244507c1452aa13daa2b077821082e5f554e7a82a851eb03c15edeff4d6326bd3f258b2c00c1276b8b596a343f349545165b022c3c81d1e1c51ff8f10dd139ba882431c70fbc7b4e27515392d9d5ee036bbaee44b2cdf281913ff9fe94c7ec81bd49fee94a947a60fbfb4496e0ee1d1ae6819f9819fea3bf1778e0ee945e13b523ffea7b71072659b42439a4989eb731e0851d146dd749e5ea59cc8b29195b60e0868c0494c578510746857c36b6fe1943ed1774e0ce53740826f574f2620e5c9956ce21b7c9f01255c0092fe4c0a94b6fcb599b23bb1307f6775cd3d6c53c2aaf2fe0c05ba86c931f4bef4632092fdec0d89ad00a65e757229d1bc8228bcc176ee0924a49a974e9c545a5112fdac08d6a88dc3152a86b644005fea1c5c7ff023e3210810fa388176c60efce32c81695bc41478b176bf053e84692d47af27b2d3eb58d191ac87aa106aeb7b725772e59a7160c1b32ac108d09948ac08b34f03169537d2b4a77a930032fd080d2d41673a9cf258d1767e02dcb83dd051d748766e0e379f88e0c6a4706a132f0aa9adc75e2646062e5e849fae578277d697b0d7b0b0d2e607499e20a5170fa9fe139726ec836cea001c3466fb1058d0a5429ae0805dbd59162fe741af3bf4b842b40c18656980955b24424c9159f60d3d9a7f3b3d6ced35ee1093e0625b3e48c1d561902852b3ac1c4ca2023c69894d0ae73829f5461c22f879790e0159be093a84baa6c52aed004132c3f9e3e15bd086a74c1050c1aa898e08a4c98fdf783a5a6941a7339b80213dc983c0da121b546306368d950c1938006bae2128c720b4968548f2598541a6d6c929b0c3247aea8041f4276eb85549af27994e037ee8598dc4e05b86212ace7f6ead4c963c82349f07e2aa56aaddfe47b24d80e4aeaaddf0912bc05f97b225cb5ab4d8fe053799adc6772041b53cce9463da90ba9d408fe3d05ebb32d9d17498c606257e55b532675b28be07368c8e135123fa68ae0dfc582d29062267d2582f1743177a89986783d22b88d2523e4b38b69933f04fb1273aecc0ca54cf286e0e4afc91cea540856fdca74909bc4439e10bce44bdd35d24e643e086e73745aee08828f64ea52558accd10e04abb1a387582b39f405045f39299612eef9039742df3ec50f5ca508aed9f2f729ad0f6c886b1674121af388203eb09bb729a92e6dcffa1eb80e094147f6f4163d7ae093ce1d4dc5be3cf09f95d3932e1d0f9c7acb8a647f7a21f33b709d93b4b899d2d74adc0e4c90e631e55778b6531df8ac184c9549074665cba5155210dfce1cb8148b5e1aabbf4c39f0137442ec1db597db38b016e4b649ffe0c0c8fbdc79035f32c818e9f3b4a8cb710323422c11b3a4b481c9994743b65ca27236f0551a93e6ff77d3c8590393cd44ac15a564502635f0a576927df654b97f1a981083ad48cb49881c4703935a3c3d861c9243e70c7c474ab51918cd0f1dedc32e035fc97bcdb3fcbec22603933d548912cd92aaef18d81472ae1cc9e4e6cf5931b0567a225ff0b318ec0d031793599dbcb08b965e30f0eae321779c9c64b8fb0524d7a7c9ce7881bd2043f3744c9b57e90217227345996ed0967181efb3ed94bc82b0a0da2d304ad4a7bb9bdb7a9216b8daa49daf5f22d79f056e736a13b699d53c58e03fa9ec371621a778aec0a768aa9c533f8e69adc06d784c15b8ec98d62c260d1538ada46576ba29f01dc44de96e568f9914d8785e9bd4ed73d494890227ba2cdb53fcac3c3150e042f30999d784d6d23f81cb417d3ed18cd7277782e6d7ae368137a979934fba9ce32a13b83c3375099cd059ee2992f4c55502ff9eeed2d7abaadb24705b5a16722599b36a90c07769e48c5fe611783bcd7efa4383cc5c1a81b78b5c71641ab178c922f09354104d2a7b3c694922f0315a929d42ca10d80b25a647f57be92b85c04dd4ce6ea173570ac920b063675b79132b651f089cfc4ac97523498a3f60bda4a94dba2ab11c1f702b29c6c8abb9ae3a3d607465b5dd85c803563be490d9941c1109ee80d56ce7bbf9a403f62568d2185f4f257d0e583da162568a1fd47a1cf019736392ddb1c6736ec07daadc9f57214751db80cbb7ba11ad32d7c6d4808919c1b72a86067cf6e7fea4435cc9e20c38ed39a2a2464f4b940123938ea93a2f065c106e395b7d4ee3c2804b0b26376becae7801efdf566b694ba86a77850bb8949299885a933edab582f5dc0f4134a495ce8e1524ff1f95dead5b05db21778c12723295d4a982ebaa0d9a6f2d3c28a58293982b9bc4ce21c4132af88e1f256f6dd87ed229b8ca5641a525eb137a5330495bcaf6d43b32eaa5604ba7ae936ea7846749c1897e5bef4a12bda3a3e0b4938e41435544c1d9c59226e4a8c9d92aa1605483eadecc75112705147c59d0d7c97d82af20920e3f7929a93dc18b5e6477b7745af54e709deda292aa34125c4eb09d217c2b2da49d36c1259926961764aadf6882bbcdb425f96299605452dad339c730c1c4929eff64b25392b24b705a4c8876893c39059525f00ad78ea5ef4ab0fa9bc74c3c457b0c2598e0a24b548c981dd4493022a74f4a8dbfc71325c155c57affefbcb9ba48b09fc4ba7df27548554182fb8829b3ba72e7f9084e254f929f3ba6912547703769e37bdaeb8adf084e86cebb5c91a47b9a118c27cba0d29dd2695416c1a9d3d2e5a7228ae04d5b68d9e6fbba3c13c19788ef113d29bf1a5d2944b0a516479f521942ce762955a7e310a89c3f6d26ad37c18371c37f8b2fa6353a0cc1c8989bfc2b8a285d5b472188d51553ae98992d5a34af83108c14bb203762121d34a804fd356e60a0c6ff16ed1d8360cdccd5cab2998c95a41d82e03475f88dd5e7dfb004823d4d32e68a9a4ee507299047e80004a7f536c1239866670d091d7fe02769d28a9fb6634fcc0fdcc98a51db93e49844ca09ac0fac660dd53b1183bb09f9c06ee648692f84001d7be02a646cfdd1594a8dbe081d7ae037246fbaf76ecd9d5542471e18cd49be564ad7930836a1030f7c57ec8b216dbf52ba63e8b803b7f7e19ea38f9e6ec60e5cc6f16c5522e6a99246e8a8032792a8d251fda703177eb5495f4aca1ed473d037b5e7484fb1430e9ce7ac26a49655b84688d01107ee73c6ca2dd5bf1872e0c0c7586a495bd03a15d42e4cf00af0df401659bc8109f2534e92d3c4edeb7003dfeb39344fbd8898343506b2c80246093c05a5b2d0d1067e52e70675f69dabd10e36b05d2997b04cffded56dc71ab8ba2ef37c4993e518a21d6a60ddb2e58a9535a550ab230d8cc9ce1623648d79226da3cdd9053ad0c0887493a405bf4b4f39039fae527e09c99dba7733303a66ae7ca2338578fa04ce7494814b615a991e5bf25afa67a080060c1a37b008023ac8c0a9202db774794dca76dd1838f5710bda84b288a6150357c2a3897888c433191a37b850410dcf8e30581639820e3070d9adbc349fdcdf3f7d814deeb132774c27e9e35ee054d5a9b5f7a8219ada05464834b720ac639650ce9001e3468db761a353021d5c60b7af6b8324e9a34afb3568dcb06166746cc1d21a59594d08e96f0103358d2df423030c405bbc8cd4a105de6ef472c77893535a6368d1b821e3c0e0c206b6a0230be898d2a69ed6bf788da0b1d0e694b33d23336494e00add7699a68a6c21a36f5841bdf60da9efe26dea3baa6059165193b119339a0b1b860aa5ac912db43f8724e3a2048f0a283643469780064a10744c81bd3cf7d551efe3698471c3460d1909061736c8b1b1c5c9f0e7c2c695144a3d3652bf17c18caeb1828e2870e61252e54f2f14f8d3ff79747aaae45c660a3a9ec0c50e1e439dc8e9b4b74ee0b2c474a5496a3a9ac0291d247ac8a629d9c9fd025964e1353a98c0b68daeed3896534236860d195b9c2e96c02511bb10b2ab8848994445871258959822774aaae367d1231927602d2af0a1c5c7054af0376ca8000338810fc01080293a92c0da26e9292108099c92994734e7e8c9d51e8153114cab44a932f0a1c587063e2a10810e2370228db4ac103adfbd45e0f3455eede744e0f2928ee9cce347909b8e21b07f42e8a0efc6b4b60e215c1616840e2074fce054229b3c4b9db51e1b30b8b071dee183ca420f1d3db00e1e70d1ffaa72e5654b5ec70ef8be4951b3c4a4189a75b00b52a6d0a103745ae94d10030b08089941e44c21b85eb151594aae69c71082f5f3772bfd6339773a0826df5def9afd498a141e602108ce724d909793fa839653c022107c09655563dfadf92f2058d341db7fd0a163f2fb0f6c86a04fa8f02b9de5f98131939ca7c2b38230953e706d39d9b727496397e703bf9bd934c6b49493577be037fb4dd00efa19935e0f7cc8dd3af194fe7ac9f2c0ff4608baea43a37a89072ec748d22477cebcdfefc0283da12327a92c2aff76e0b3a7d98ffa5607d63ac9764f4176955de8c0678e2357d25fa648e21c580922a6102986c881eb984c569e8a395fb271e0277a3ea1467b10b11f0efce7a6b03135327a0a7a03ab957547fba75c5a5b37701bff2b25db531bb8ca6e5ba9e31f399b6ce026c620b455af6be0dca36b16a1d496696a7280851ad86fb5cb4cd31d9ea6810ba2e5754ac354751c0ddce6e9de3c31ff46edcec057c5b81938a5f58204193b62faa50c7c7e0d16344c53de7892810ffdcc154cf787f2c7c0a549d9fae6a546db2906762c4710416990a53d250c8c8d8e683a49f2df8d8281d1b912bfb4bd5eb9e40b9cada47d0b9e7981578ff93a396834937617f8d2fd1972375f26ad7081d1ad52e963ce6d01911973d56dd6b4c0589910faef192a31cf02ab9a8248d1b3b0c06aca513fc7ac89972357e0438520667bba2e4f6805fe3ab3084b52444b24abc09e77ff0919a454e05237d3d5cdf45afedc80c5147891ef21a4cedf5f7d41010b2970d9f3c9abbccc12da5b2ca2c0664d2b1b3f3d144ca521a5570b583c81496ff79e5ff357c57702afd1d6cb7bac2b60d1043e83bc98844ab6ae923281cd31636a4a7ab48b0a9760b29831585aca992955724f356925da41870558288153f913438f4e99619104d6ac9212c964ceeb8d085820816f3b114f31e890db2a45c0e2089cd614f7fd63c4cd31c908ec8f5ecaf51dfd6ed92270b9275d2c2f75501625029772e8750d323904ee4c57ff5a704fcb50084c74915ab9f9633ecf30086c48ae8c19520ce941580081499aa65468baca77610219333410e3860c0e7441a34601018b1ff09f4b259768d36f16f201ef7d69e2bd254fa5dc1e709d29e6d51c736d0c010b1ef0766a379eb2b403366b68d60cbe7f3af63a60bbeaab1c70218368ad166d49671c077c0e22ec93c9d40d7877ddd441c41855c4b60197ff2caa4a36cb2a3135e032db778a5731550a190df86c222283fa6c065c3c59b974694c6b6ec9807b1349e9b064c580cfe6a5c337b7e7aa30e0369d0cfa5308b194456080c50bb8d19f374dccb921ee63e1024e851cd32d9a23e718f36845ea57fedf780658b981072b3859adc12f3776d0cd7bac8211f5ba1e4baa7877ae8a5473788bed910a26c91494dd77e5810a544cc9f2ee15434b055cd0f09de1718a75842e75167259ce14edfee9312584849482cf8d9593ccd476b2871448fc5297acbfb2c551f0e9d7418bab77f08fed073c44c189bc976f7edbd16df30805ef5954f6156dcf9a030aae459fdb8518327daa57011e9f502b9648c8c172f0fdadac2710315f5afbd223bfd289fe56bf37c595061e9c285b099dd6d26a46b0041e9bf0d0047a6482cd29a851d142dc132ee0021f66000f4cf0a3552a098929e814ff127c4ffe64379edc94cc2dc17a122a6b5e51594d5e8963faba0cb1ee43092e8f6aeaaa20e396951e93e044a7b47c7b4188e8100a9c068c2db6904102f5808724d84ba22a7869c40e6524780bda216c5377fb4a23860d2e7a868d19324aa066c303124c0cc24d6e88cef6e6c5d05a8f47304a5f503a9fc960fadd185a30b46448e01cc16afe10ff1c4f0cad3f41db281af06804b76f2a552dcccc3788114c764927496ee69e1c5b0497ad777784167bcbf901c243115b8fa6fe6bc77c6851fce091084ed55a2a3d2948070f44b0bb3a7e1e2a72886b37622e0311f8d8337818827b53e369b1a25a083e664d32e6903323011f19884021047b3b62164c4a8ab92f41780c82d3b5b765c96214b315e9e021882e3c02c1a57fa46bd5fc1fa365e4e001083e95df25efeedf08528f3ff0b124a87aff3d117537c2c30f8cae131509d9d6c2cf220b8f3eb016a947877e6f03c6165bb40ac1830f7c458bed92fd74f218327b60d3e51482b688e9da84dae0a10736e50e22e790224b25cb1b3cf2c086286ad4861a6d89371ed8ae2aa544648c0d1e77e05f734c3d326976604c24e74c2fdd6b9bc43178d4814d0d2a58b54b1a9592c4e0410746fe9d0ee1f5234f486478cc81bfccd0d2194fccf427075e63dccecadfca0b82d1970a8f38f0a1995e5bd22d3e86d5200500a7f080035b19da2799509d949d6fe0d463a41054f333438e1bd80b2294346db5f95d03058f36301a3177be2c965254fb050f36b041729c98b2e6a0237d960b1e6b609412b947e7566a60d2e8d22b31e3af28791a38ab71d11b42ed050f343021e90ade2984604a68cec077bac82b315132f82a630b1e66e04ac57cf5e22996eea4f62803afa2e79f43349efc4c073cc8c0e94839a65a2c51175b1510a381c71858db893a71abd42ad819788881fff829c46a2c58e7340c5cb2cee295d524a7918381cf9ce0a2169e2ff0d979f9659af4029bba27d4259b5d6092b20d15fbf2c532e9001e5ce053f6db0cba390615bb2db0214f4c66114134a38b05649145c1284d7868810f22638c589ddf2f52b2c008dbf23f594ac6a08405f66d3f6d2c4d497550795c81dddc217fe7a474e8146405f5e8ee641ecbb792f4a00293b35987b0507f8d4504784c8151adacab0f9922fc6582871438d7abf6da0bf1b48aa2c0656d49771b7d99b74982071448fa3f9308315bb4f82014f8d0e2834ce0438b0f22810f2d3e48043eb4f82010f8d0e2833ce0a30211f84038783c81b74cb52649250b13490f3c9cc0dde90b2248fbbdbb206d0257428fbcd3715f4bed2cb240820713f84d3b4ae764bec712f81b13f184b66ac8537b28818d90e4785dacacfaf148021752f5e4d1be1d12989c2625966d527d263a29781c813b915d52ddd26e92ae11b83d69eef5dd16810b2aab7bae591e4458a3ed66cf69538f2130425e4a96827e45fc140f2170fe49d389085a6b32c42308fc6435e191e2e8999918f000025b5e963534a495547d0cad46335e040d838b2eee041e3f609259d613f2be734e4231b44860a36f901a1e3e6052927ea9a162ddc7b4075c27199205b770091e3c604cc8984dd74495e0b1037e3dbb7fb0ae7895643ae0346445885aaab26a6d3c7280fa87c89ff63ec60a1e38e0c44de7516dff98d972036ec54ca6a436670376847f753e93b7f7162c78d4800f965da2868896ee9b068c5453515284ca63065c8f9815020f19b0eba3b3d58807b7ba39e011034e87c79cf2e8580c2d187f83c68c6231f080019b34976b16a5c70b38113b2449b5a33b3f1943ebc6dbd81b1e2e6093fb2469f5bb69c115ade0b353c5646a7249af6005a32949c5e0914cf85d31b468a02a1b57ac824d972f42fa1f8f952a31b468a0e5e20a55707e95238d8a575992c4d0423066c810c19fbb2215dcda899979ede48a0aae40059f4306a13e7b506a3fe714ac5a89ce8ddda0710215d4b8a15798821141927749cb943ea5af28051f4787b6b7cc49c1d56fce12156c1825a8d15bf40aae18059b0d79e073e76b51bf232a95f0c006993a92a7a40bd2bf03eba1af6208db0edce5c574f1d25d07ce2ce9ef1dff1024b87460e37664f30efa83773b07bef259bee5bca15b5b397067a16f44c4b32cd5c6810d13d56b8d1cabad85039b52d2b3afd3d1b4316fe0c47e7783bc5e3bd5b8814be9f91144c6d44949dbc02955e5a174bfaa69940d6c5ff018cd43d093e95c03a742dc738a199e8226d5c055864cb2eb539b8f99062e6ed09e22a79cb4298906f64e2b338a8a67e0cbf454a46bdaf210cdc048ba6c9d39f3457fcac0fe77a51b2b61a25932304944feb4e8e9413537063e8af868268ff99b3931706de56dd1be0b03934a7f9a976a056d3930b06d31afb46ba8b8e5bec088a023e7d039b5798e17188f9f763f49d5e0ab7581fb53d984ca271718fd9e2a4cb7afe95be04fe6756eada0a3a44c0bec07d179962c45104f16588d316dbe1aedadb11b5d94000bdc55d05bf27ffffdfe2b3076d9b28d0995dd64c80a2418401518196429aba0f399be3815380fa97256acd45cb19e0263a9b347fb4a6308610052e0d247d446518b99a451e0d276c54f6f295a47870277e9b33e94081694a89fc0a964a372923e3142cc3a814bb66ff9552a791ab309bcfbb59acedcef51c304b6328a9ed610f9b404dfc612d8149194c9ac2b814931fb7fc4ed24a8edd984a61b91c0b7a7a495b4e83c41d7476083cea6d3b4e99f7dd6085c9e20da23a77b3591290297736fac98fa2a8d9212814df13ef628a58352691b02f7b14595ceab58a511022347db4f866ce6494160938838329708da64b2bae002088c8768d2bb797ff5f23f6093deb3d01ef29936910f18a1546ec4ad3c3a47de032e770ef6956b2a09f5f280b3dc14ca4305214adc1d70ca628e17216e74c08552394ae9cd39684de6804d29d45a893ce28011bf1095c27303367b907d4a9e0edbb3d8806d0dfba0ad6b74da3560dc7a2b2506eb0703a001ff1352e575d3a0d7f60cb8504927f9514d984618f05d6cd127c01d800cf8f6acc172aa517ab431e0b46753bd2e21f2ce84015762424a2e59d9c2c62d603cfa2eac1a30801730512c85770a52826f5c04351010e3860c0eec0706e002bef3adc47c71f2d10a266fe614b407510cb5ea02c60c1aa564ec083e58c14a9069e365cc91c9f2555416e943157518f84805139404d1498fdcd229523e50c1fac7d19899f2970499b2027c9c82f76426a25b4952cc66df6805d028a6c0d4894a173fc330c2f0510a4e0711f4df69ac48e183149c505a47638c96b393e8071fa3607fec5d3f74e2e48f8b820929b3291dcda6e3e942c18812ea5577d55e3a0814ac9b7a6a095993bd7f3ec195768922749a56d0b82718952cbe28cf124385d9095e4d37e207fd6cadb11d7c7082db7135d5d9442e31d5c726f80f919cf746f7c1872658d3f608b1bbb353ce67821092c8bb172bc5061f98e04446f40a52fb2a89d02578cd1ff474ad64094eed9b99eefdbd5eb7127c08da3ea55de91ca2e683124cb44e275a2dc6838f4970f26f928824d53dd49404232d8f5aafbb23c1ad7d0ab1ee36e60bb5103e20c1a90fc256bba4650d2139f87804a74e997a1e193926e539828b62f655ae57426fdf087e4524041d254670265c943e4b9d4570bd591f6fc7a208fead73ec34759b6c2d119c049d43d2eb8d082e54c7e837eea1b7ec43705a342695ebd26bb49221b89422c73f4f2a87e4ab106ca69ab08fc1738d6409c14fcefc1cbaa345d1f72078f1985bef7346106caccad79c64a7533a24105cc8197940f0ea15a286d8fb1fb82be9a729fc22a8e4fdc0d8a492e895b6496ed60776fc4f09d951628f88f381fff11033d3b949f4dc031f399ea63655e9b9463db0f1b22d6249ce11f39507cedd3e63698dfc963f1e78d53c2ae418730726c8bfb64fb264072e2ff7c53c5d06f99d3a707b497b97a8470726474f11b93be90e1634072e5a485be54175a44b0e6c7489f959cd1207464773ade9e8c181b1916a9ea37d033f59946dcef92a7e8e1b38cf18335f636766e4b481ab202d458dbab9d5216ce045861835bf275d56fb1af86c31a769b5a01a78f7b498be924c4969350dac7d94f4225a77c9333430a6f49598d2330fc13370b24d84a8f135035f3282d68e25722f5a65e0bd35e9ecf14b7fe84a062e64c6aed17b595fdf18189923b6e40d1203675fc2644ce139f461e0644e39a91271639dbd60e04229a52ed742bec06fe61c82fe94d62152bcc07e9c20316fea3c2ae5bac007116c33e89c74cc762eb0a9459dda4f132184942db02164e98598a916389dfe7792560c49044916f8641a3725ff94d2670d16d8f461b2b4c4d1619db9021766aa64b434ad595356e06b4c349569ad0a7c069534f6a6a5d15da102dfed962c7bbca7c0a5ebcd4da9475aa490149854425aae52f9826e370a6ce82e6191440a14b8dad2117472b2cc9b3d81c95eb5a6a7544fbecc09dcedc60b397375bb3d4de0be3a8b54bf99c077e4245334dd2cc97c094c48695d35a994a03b51025b3a064d22a734e2499204aeee3e9ae605d30e151278b38a9a297fc811d86c49930c3aa71cf48f8cc0e8e991e3f9626a6aa5089c0aa63939e72e917c1381911163f7e660c2c7ab21b02a2289bc2f3361a710388d185a82106910d8ca48a7828c1cc2f207089c88e74e0aaaf699dc1f30528369ce67a9a3f7e7032ea6124aef88b29c35a407ec9b10adf5764bd2823c602da4f13449a6ec8057fd0edf538bff1dd1017ba956ff64e9e449c2470eb8fbbbda943d2f287b71c02465712c5a9e99f8770356e4475691fca7c57d1b3029fa6b05cd7aa577d78031f5d1ef4d9f96c7140df8dddd12daa4a5a887cc8089b1e28e74d71c554d19f031758359e527066c9de80a06dc8a48d041f9a70c217c01273f7f76b1353f5cc0e6b825738654bda7b782ebcfdef696f5528a145630b69293298bd62a1c2b6d5a446dbba2a96094ecf7ca3d13156c0a7549c4763b05bf7549f76db5a660df7593870eba52b0a73a650a8fd9a1244a0a4e44d717211a44c5108e82b314754be95acc9d2da26057636b49dcfba42e1a0a4eaf266dce2e41c1644dd64987c84906937f82c939481029d9dd3b7f9ee03fb2a7d0a72753077d2798205bb332ffa720630a2738d1ebb89bf29a9278d9043f499ad03129fdbd26d104a7dc5643b3ffd8e99e092ec48af95444523d398f0926a7d1d2796385975a976094dcac7b135f4b309a214f361dda64969c4ab0b153e6355922079d1f25f8516e6a41de65a89c3c031693604496972691dd92ce6212b09004e39df43da4ba9160d4b4d2266d1016b46627304830a2566b2a65fa083ebae8ac4fef9872a53882c9bd7b3a3fe5b74ea6ed01168d602ced4a2e7d59a2df89118cbc189645f069c992d9249322f888e6c1d32389b6f789e03d7e5af1151d118cade82bd91937c71ca3032c0ec1870ed31bcb93d2d1d48660f73529bd078b59a8746f650259341288040251381088e162de2300031408001034288e4622c1601e69baf401148003512e1e3a2e2a141c221614161a148983e16018180c86c1a04018180a0703c100421e44399c1ecf3621fc13368bb43dc1793085894982986a70654067d06650cea0cfa0da206a506e90df20dba0c120c5a0863c981c2b691ad606df1ce099d0809062504334d8177b704c3b836f06980e1a11aadcc19884946d6f1d614d8133076594b099bd88c9b1323d63f7555b15d2800e423bf476563f2859891c3ddeacc1fc30d8bc0a504638208ba2fa7748601cc025c015c09380b3027ff78da2310714e50e4c0160c82694e5c42aeb259d0236e423d941001c401d401d403340e901fd0b54c5b0437737c0690600640002002c00600dd0c293ab513e02f0de00cc29520997b10184c326db53ab40ac005f0f60aa140307735f66cac75da310a07adfd85652bbb31e09124a594099c2384cd9801f7a8b048e3b7eb92fd889a6355a1b593928302fe8b983b113363fae1da64f4db427f1a6dd835458f880cdef902c4d9b5e415673361a887305290c1a94da7c0b14b46f6dcf1bf5d7330f1076c8b0646ff8b1801c68d10a5ba43048b39da9da42bbf6e890f567b4fd539d02ee507fbf2c83ce9185583072a16426b80802833941ba8fc67bf7a2f568d019eda3772a8f4ebf57125648eeb22a351747bfecb3ad58da24850709176281e0a873161770c2fa6b08415dd32926b91b7a219e2d995c4173e450c80257c1a2de2f537cf5166323ed1ab3060f16b7790d949ea5a1b6a9b5394db763335d74142bb413304c40245ebe683fb298cf5faf90ea6ab216c17857f66600669b1743c7e2aa7fb1c7e8ad0f3043e6e4600363158aff284e29e0d95885a2b5c8f05b0f28b6150bd09d47d7d7c7801d2ef3e2a7835a9780c6b7c3aaeadce158f5fb8011791151e1e753f39e32ad6123466247541c44a6528dec5f4e1dd55643a5d26fa238a3e0123d1378904c073106eb25326731055f4b7e247b6e38a455729beb20a1686b5075c999d07cfcec75bb8b30a61bd32458bb59a3a4ec541fa0f03f0a0822511ca5f2511cb4cb7c46ac48914d9430a902aa1c849a625284845982223f052cdf40cd439540850b545fab3bcd61110a1ea180ef44284579fb437bd47a184e62a71b4a18d427d415d415d42bd451a86b8b02a2c1a8908403aa2f1d6743d4826a6fa274a8e4ad890fd57194334f017b4674c4071430f8d5f5d61e8a769221e4511fd529350df500759a46dd9b1f4706e081fa037575d45598ba371457534d43d543494339c0a29abbf5d2d651ea3fd53551c0b2972edb10a026a0a0a112a03ae628da52f33eac81ea85b280aa868a41541f029c6299076a0187d2018744497da178416565d4bd6f3df4bd0a3505050785e251b409ee8033a55641f141d540950a541cbe953d94289413d43aa81fa82b51a7ec541cd98bc19838141b546aa82e543d54f4a3fab0a0624531a839505473ad9353544e4115ea0c6a1bd41ed41bd431d49fa38017121c701e8deacb78f970f2df14b301e54228e013f304a6734290aa4ba380e4105c894a1410af53be5995026d8102c6ce7f5c17b20802454301a1179d23e943019b9315d786a180e4b4f102d3a368c3b206ec0b8a3f940d5415542404aa6c85d6b32ea84528b050b550b550b1504150bd50b550d183d2d1bb67903002e508f50a14f00f4f5a2ea4c8eaa43e5dd3aa06b3dec11e269bf23c7bdf7f40183c34c630feaef1c0a724bfb12354a0e9fe1fb3f29628ec9bb754af1ceef1b02a47668ca534e370a78f886b610f65000c7704d3826ecf14172aa857c8bba7e076ef6c59d9296cfa0ed97befe9d67646c33db5e4b1b3296cc32e56883afeb013f98a145940e48624b6b249d119e5aff5f39528acd9517c24aec86ee12bd2018e4e46a7f1705947251e9acb299446846e5e7e5e745e745ecc5e845ef45ef45ed05e08f0ebc99cf85ffcbd78bdb4efd7f56f9ecfa37b4178c578257925e2afc5c7a924b6e9a5cebed0521d6bc6972582b3effe8c32ab1ac211c477f5ab0ca58a246da2bcb2e548fe9332ec54558a86160cb057c65f31608d5e895e3dbd6ab9d7936cf80bbd7a517989f2eba8f33143ffbf1621cc030d5caf35fb3511da187c30f362f02ae295caafe37652f297e8756cb2ff38c29c8abeb26fa0a096bfb810ba02919eb461e6639a95c2875d3fc6acf7122c1bda691862a591b05db357fa66d6d16117dace9a1236aeb3338223513ca8c2ef889320fb8681d180e1e5c35fae0c01d99ccb581d545ab7afd2d281f0e5b8d682b1c6379149fc701614157e1751158ab67c5edbd4e7ed9e782b7e4499a2657348c211c510f5103b9f38b8a5e8c4ea5273f9f725992346d7e63feea1fb81e99f2cbac0ba8202a304ae5be0c5fbd02ce420009d40e69c56138265692f72978717ba72a743389246019663f117cb39f9fc8743176f0387c1d5b25ce26903aa4f676cab19bd526aa8ce400aebcc18904b84bd39880c52953a44004b04ce5909f480d6d5840a17acf033a254c0e58d0a6bc6977d15faef13986630b26fc9986a108d99f16104ecf5b3f35dcb4d44fa1b377c498ca0443445b18a51bbf880fbfad91b8b3fdef860b0afbe061c173399c00ae791c9008a039f5094fe1207a6c08f36bfd9308b8ea376a1ad16768e2c7f0155b6c897a220741a13a496ba139edeeda09130f8da532091ed6d3806e3c2a0623f800677adf312143ac81e0762d3cc2864befba4b14629011335d81fead98c69a744547948f10d977500f515fd3d08badc967aaf793276e10dc199f78ddbc1d811af15c164dad86a708fd4ee7e42d6af1bb82e5d5cb724003113fd360aad505a9eb86c0ce861f94c113d87aa5a148569c455a53f252b7d35404a0ca69af4ac6e5a31c616eb730582b18be988440ce1501e795c0d0a16020f77517e6f84745c09d9816b3b6d63ac4e5050f0f0bc077188ecded05fc790e7926382ca3af3b2ddac2f52c02b92f82124b39956203e88333eda90f3e907137d00bcad1f943f48cf21b14ae75bc1bb9a78e39e9b34e51c866c6df82ee33a68069f1404cf46d41c22cb507b7fc46542799ae7e1bdf453f8197f81031a69725f06688384434e656d70817f1d6fc7eac7c619fb43421384f27278b3b8204eef7295968e0939fbe58711456eb9038b27d3719afd864427cd6c2b7766d9944e4736339f2db39c7e39a51946c04aa995430bbe0e74380b189881029652e2ac5d66a81e508afed713a76d6e9baa2ca14eedcd17481e1769cd23a146e4958ea06e6ab4aab00e90d31c47dda97b135a14fd67e993636af726f47e1967f828c7e265d9f98b7e5e1d374de306bc8c245504de9fbe8924ce83373ca3c1653e6fe8f0ee2e2a54780ec7d992b0d43605fa8c39d1c5f15414776263a3040636919635fbadf36ebde856d8c2c0e02cebc9ad68019631e9cc6894ea7c4da0c9245acce6012841c9d004947a389d7240177597499d9e6e1700a19a381edf59556101e5b8597d981369af489487d700fa9f9e2da10ab5f44efc86d16a34853f2fbaa7cabbaa3f084552a46d349af8abcc804260f6ce43ba17cbec89f3d528c4ed9e17ec57375c8ee42e72a4184a9bfbbb48e76bcb65916ccbc6838d8cde355e0e8be1459058195976d4e400f695c561c271b72fafdfb76e065423e492688b78b5a2d05671674700b7c8096dbc0e88d2ae4db209ffeb99eb4b9e41a1d71f4cfce865e0297ef39c2dddca0ea9f050879cab4af6212ff2c3bbd751b6e4549d959f2694ee4f252db9192ea0f13cafbddf1b0999103eb1e7d12401c480defce89cc7edb1ac00ffc1d11d55e04ac55594e7d7a5064c805e5a65337dbd495bba123c56d06ae304afdf320106ed5e21b6e8a23ed1eab0388a172afcc1dfbdf3a0aaabf17eb4fe0c7649210398b3947c7df6bce0be3a19affeabb5706282367b163403b1a6a58dbfa60447b300bb718635db3c6990e03db0ff36107f0d42b9fca17b40e499c8659f9b25238f187db8c41760684af5a5383412757422cadab5da0f59c80e9b8a1e03b6a822f4d179c0a6cf1e0204d63dadbd94628ec5688c7f1564ea7b9e8047122784151f7081328082804fc7d1a8b20887999f3cae091c54ac35b609d1afbd728cd256b56d5e6ed3efea8a66d66d8a3faca705da88435c1895ab0f5cd4e57c4160470f51b36a68647004de59d20abfe9685cc5ff3d0344964c6d1ddd9c01c404603ad2eb909d485a115dc1ae7c292b15455feb70af5ce3a6b469407efa09e1e52d591a3ec37d7de609ea64ad73f1d40f1f028531ad123c115fdc20b2ba5eb7ac14c16e36c8168e6946232139ce7b4406fa0a3c8542444b98499bc1fbfbacc8b45cc102935473ec3afd721d1ec74ed393453e0e984786eeefb6ad288e622d0d668f44b2d92f309f2c49ca5c22d7a7891ae448ed102b7b5e20ad5448eb65371f0e2b914cf9543e1c76bac6ab484d5f4a2868e87ecc97d5f102e3360659a935f1e040d82c33ab2aea48019506aa3d6ef953c5add18476f563d60072967426d756f1b4f1803e263e2d072377988fbc2dba89d3f58689b30146a084dab04eb41e98f3b4bcb2d22abd314cf41ffc169ecd2fb9b7c86a188bdaaa11df6694e594f6cb3ea8365eb28d31c95517f9518343badb38d06b050c1b9e007ee837fb1e000eb8e303780f161f5237312af388b2969fd2db42916e6744fa8104f54fb0d1146346cab827c8d6d7628492fa79101ede960211bf72390958809e8139d7bd4386a606a7e69059a9ab232f52e6c253eee181c6425dabfea8d79a75927d826b2f06ef10fd4628e809ad3914568d35629c7c656e2013fb06ca91497c458ec120d9585cdbf18035120101d761c0a038005d5cc1666ad98f1745400a4175d048838ede6c2fe7df6945d6456839dac46e6d9714cd5a8ba729f9e9f2272e1cbf0412a3782ce9a2bd965dcaa68f72e42cad2e9eec0040d6f9580148a14746a32946695d9bd14ff6910d81901b2aac38dee6c2b51a7ed474f0d020aa075c30920d5c1837693f27be836992b929b9f7ea21beccdf7eadae08251ade11a35f965fc8c17a7ab2007bbd46aac9fc672f299523e33bb845c678e317b93f4d2d868e44afa9663965eddc13e0ee06105f5b22439f82f998e31cf529588ec8749d98332133f90abdea3da267fb3008ba2802e90af13284385d9bff0cd166f5dc77a5e5fa4d7b6a0c84eee8780f3cb37e5c3f1ed022ad0039947e2aba2c9a87153efcfbbd87497ff1ddb1e06dbf5ca243c5545aac95b6098637246cd193a408eba48f021eb528a2cc895dfd53747d592dfdf5d0a8488f62a48c5827a3227e099d737bdf8d0adec1a2b7f446edd8b8bd99ce0bd966ffd8dced97ae45ceb4707c560f43dd2cbd6a890aefeaa4df71a01bff8897d432d45049448e51cc613a4aea029f28a01866016f9f747728acc2ea797688c747e2657d774cc819780f916b7d01db878d0f24d712b5f967397e5aafa90fec3891078e4f3f988643ac2ea713fe85e0bccb544ae490c2e2da36b64babe21628b32bc9e02af4179d76896f219ae65edea0bfeb0547ec2f38be18f7aec050d3954e86ad7c2db481d943419417eaad29bcbe0e5a43fae0ecfdf27c3f213f9aedd169e0947796552e2783e0c182bd13f59efeea5c6b607b2a8de9db3731b89d850981d2b444e45e7b9a68a8fd61448077190d2c1a8503acfc9de694211cf10b562958b501bd57cef3a453b7025ace16a001a3413a5cdbe815d1f9ba5af4dd91235cdbc459b9caaffcea6ec51027b88a71e9a1254d020cc8f29d409e6745030de01edd4a6ad08560831a42067087eeb86d901493d51787eaef6daf77f2073fb99eedd8da562e88d95e8d694869b36d79352ffad39e21eef1c29b8c128151209587aa4d2057569ac644ee884220cfb32280fe7fce417095ea64dd6deba87787579d5d7ad7ecc1fa09dafbb865e3a0a2a122b37fea3e2b322063f3c05cf9cce9277774c8b91743567ff195552827687d5321ead36aa8ded6fdb7d7f6ba87a6345e00b9eefad53e138f51f0625a3e16fa00d3207fb67f1906f5ea53a4d22a192df25ac1d038f4ead5b594291da548da0982c3b310283365e26540c7c9604351b5b4451b66e1315d9d7faed4930e44c759096811f19a305a2826e36e7b2448b6e477b86b9a48dc3cce6e4100279fd4c64c7693c5e05a2c9e2eaf85caaa88bc0d1ff4dd74d9d261416d3ec89f8b780a9c6e522219fed7fde73a831ac8b1a199ee9d411ff4c17524450bd84fa4405283e5c39c8348ad24d02778b7ea799f4998bc8b568308c00c01cd74a1114c59c583dc98c68bee81656303d231d0a67ee86554c1563177476c065d12500e10ad7072e898fd309b6960d405d91acbc7a31fabcafc4593f717439ae7fad7390b1e25363c87496cce9b4931eabc92121ce8ed653881634c47156c41c48aff5510e8da5378810c32c64aefd160c12340ce4455b6c29bf604133c9460a1092463467a37cd64b4033dc0ecf039686cd577cfc67b45ac58a25f560592bbe2990883261b7b39fc03c9c2c247418c11e18b72e25233261c7b1dc4b20938c0dc1827c33c6d99b40d581681d1158472e364bd8b3c9649891971f181dbb89c59679036e5c3f11f578f7b462a6cf8aa24582b632ac90a70d41a8caade04789b6dde3e4b276536af0f7ab6cd6587ed9707d335210646c958b9c8bd28c326da35f1fbd21d138860f3487ec9dce0ad3ca85b8ab872cbf183fa5118861939bbf4cd6d291ee3c353619b1ba9d256b87e40bbd10b142be2d3ed6400fc9dc4aba3cf40a056c5e6b021b9281da68905cb8b9e371d30f57a4528e960fa3e43bc86fc437b1c3ce824d53067e9c5141b399d2951ce852f0146cf3ecd96a4e22b6ec08dc0790b63890c5a0e6142190b683078b164579bb1d29f820c88c0dcc7bc8a5bc3aef229a8484fc7082370dfa46348c156192943a1f8b2412e0a0403e85d5c98e0a1eb75b7f4ad0422c5b7eabbb16c1ce89c71591a19c42425626b5d8066449dbddea5b3522b4f79e31c3ef25ff2f5330fbb696a2a0204bc9a7b7df46de83fc8d577da88c59b385ae6762a6675f2c9de66d9ddb7ce8b9505ce0727814cb06b7052832237c6c33c5c2207100ecd7bf26ae292d11d0184e170cfa154b3327b9360e0326bdf8460519a48cca6dee901a92df33b7913e5d0360a2e94dc175a04fc5b39e052f4945909a670185f7957a6964c28c35e6b3a250403ca2d0c5d61007c50ae191f8041149035dd831e6116001b51631575ddcc851b66680a9872a757a8305e988506062bcf6241678a6b0af071db832bdc174886441e1a40a6fc9177b8042c79d93409b17f15372670dc395b93184ef642924b13f4de5e0a05c798702d549b42a883da678ceaf96b0afb188301f9509e60fa8c4020665d553493c04bb496eab290e270b3cff361fb031e138a92a87714f9bf4dd6838a814c77be55fd7660c9318883fdea12da67f6aa768927f4babfc35d99395438cb7edd1caa1de02cdb40fd19eb29561b3e65b2e910b83a146ab3ad507c454ee67167ad8fe81a2e838796ba6ce2d78a382052b9e9b5a218d549798d6b5747d107e8a419a46276ad3b8bcdebb37c08d05ce48faf42dacb43e01b7637952c129ae596364879fca85bee6d8c7f5628332024f9c921060f8d3f5398f4d5d5d55b68fd263b4fdaf9f223881a0d0e9e574939dfa179a5987be194c7fbff03c7c9c7d7655f668f69e3cf1b3f0df59ed40e7b2d1567627503970225c4eb0d75f3ecc09dddb41fe5266139a3cda8978b33c3fc488d4d7eb3fda7af694c762044a016a8de25207edd8fd1c571e661061003b0a2618e0dffe08a3515d54f2103e593b2d8ad6c34eb136877476e6c0ca167cf2ed3ea0bb103e6e898361fa5805674e60d10b83ede3685b9c92d7c1ecc65e04b7a64dc046e954ecbb57512424a08f0f12d203bc7ba52e0a646c058fcd3b52fb202f01aea8ce0df99cc9eaa292ee68c4ef5dc408fa66c6e06c658eba4ee2dbc52953157be27e987ccc1056e75adbfd5c075112ee9e5c6ea844b02db43e78b835464df8b26c7207f334bdf8a23845ae6cb3ae0c4b8ea8963f0d0fd48311606571c4770b22ee910147cc825d4a204244d770120f796d2e7346c590f2cb9b28112094637d7a417d401505cfba9f0190a8aed59bbd67b4dc7b4b4e0fcdfc0c5153480976c12bd84985f43b99d13a28b989bab1d6016ab02461b453ccf8a05ad8173f62806fb50ab689f91ef66ea1f9b4f75f1ca6389f6c4f6e9480e312359a29b00a7a1a41fea454b47555b2d28464efe0ed77a0efe53b309ca6481914ec0adafe115c026c72213b20be76b16947beace79ff90e5c848e8c5c2152cf148c9b22bba3ee3a556c87005d49f268c7349306317a8f3f9077720340b5489b27e52274db89e6d0ba570591b5ff17ae0101e93fa9f1a6024137d3b079c0b312d3a403941348075daaabfb8c35043de75949844e2ba3b1529023bea5d8ce0f7f6dd11bdc6c1abd3a7af574709c256cf61904be356c73bd026a053f24079d474440c39339e2f0b02efba80a636bae759bacf9f9948181c0d60895ff870425cbe59e5ae710de2534bb8f3f7de68cdca134a7d94ff4469dea045fbac79cb7cf1b522ee2f90337454a386c4b097830210ea31f762daccc424cf4ac822548a98210ef61e3bd42f730da373f834f32b0f362784a85520dc49fa82c15bd266f30544ccaa66cb13ed2e3898a8a3f3aac826e94c608b497827786aa8c25da2f5600ca1b01901452fa8d87d3c587af771832e3b4ef3ee866bca201875a44cf54a0912a0dbb5d6a56d9d270e482528cd8ec243dcd1b23b53a3b11b1a2dc49aefa08095df45fdbde26ebb751415405de50a10d5791d10efd8dbe5bc9906f24a7394061ddce5513251bad244455199f503d81484ff11fbfe4e3c9bfe93dea10bb5812dab028f37ae5c39d5a645d72c32c53006881ee69555524bd178af4d4c512d283ad51c7f0a4c26deaa6660c93189d0cd4f35ae130abe0bc974ea36b919401409bfa28505a9eb5a3365dd45cf3ea9411f3fe74113a7bf9b5159893b0bc1e4a366245824eb8c02ed05f676baa6717df6aa8781263018af539d7b23320252e1b25b6e33509fdd9a34d67ab0f45f9d66c6e149a11941cf887528616f5a721e60e2397fd1f407b7bf21893d505c0b82a3bff0837489e74d2e56cb8481119bd8f5aa7cc167191d70e6718f1a97d8f629b42de93fa2284c33f42d5e44d20d39e2e147544592a469a8bc394511ee813ddd2887348ed23479973b1b62b58133f05f487fa6cab6382711cb3a351aa40f562b165bb17aaa5fb931897d0157ce76a9a2941a41ba08a36b816486e9724615223ef4fbdc49cd4eff68ecca28814eb2780a3293bd355b3a6c9c67a16c9634dcd73b8dd5207bebb8c4a8c95b02dccdf09e3b9aa39c5d5d6b494d3f8b2d1dc1b45e4dc0ecdd9eaf74f8fc4593222e68c56ebf8389963c41dc8d8165d325aaa11f0036808347ebd155fd324aedcd2f0a63e705526a15efd59e331ed97fb4cedd5796db744e2ee51e4a28f614ccba63e6b71ce4a105bc23269148c15f1727dacda23aa466f515231d4f26e1351da4e70c9376e4c261326334a614108941cebd7dace8341751ab44553d449251bc56da73f3b102d5adcc409da1b8b0dd6ba9ed841c4cd44e59b91d1f0744ae0befebb853dd42d4509df12f8417e1543d15c8d206420101fea167d28aa49f19174b435ba50f193615fc7763c0f60609af547b9e1b8fa85b2d1cb7124531a8ad8a3b8f1b8096ffa57bb1679096dbd13de15b1222467945f80427cdf351c4a6ef384e6840610cb0d22e88e420edf3629640c4021f3b3ec7b0e94c7904d150685164ab1069ee6f7ccd7ddb6b7397714b51e63dbd05dff21047de3356c3d85bc01ae33fda37790a28d2ebe69a7b1dae7a7bb940db87e4165840b3a0da3a65845ca72b802e6d6820b1dc2ced750bb970f98ce1534857a2950dc876d1e53fb5134d271cda1d4a2268820d14fd798d00950210dabf2cb29f1aabde0bd2f7a7ea71c36db020b54baa037406a10f290c58c6c04c9dbcd969c7c0c89ccadeaad5efc4bbf26f181f77384b0b8bca61227fa5aaeaa29f17e3cd7c56846cd964797fe50596d607d58894d37b603e7d2a6fd8c1cd9d0da9284e752a972c55e0cd6a5522bee50e2565819f3a0e5b9ad1482842bd978cb8a079e71f2b631f8c8ea789136797b119dbae23d92e4c7436cac1cb5caef920892d51a095cb5e301c6970a106cf76ec668ba006878daac83a3fed4be9db17cda7599232116638674b8ed64a2031a1ce04d744874fdf9cf4775eea52ee93ceef9e8eb998ad1a6986a243ec27055cf499da0739fc70f235bfdfce9fed2eb7527a03dd161dc23d89afdd25d77cade96a78be6d9201632ee86729864614166e49c1f0d047ab206ffbe8c7d918a13da212f2f810942b8cb8f775dc8994389037873c4651ead3cec31d010460548bcc127cf63f56b9eef8a7e8f9c0743a82f0599bc14cbcf1b190795a18b500915bb0201d8d7536e763fe40dabee31924ed85e8f09e5741e8b46c3c8b42865ab7c74b1d6a07fcd12690d557ecd6b9cdfa7e9a1075135e39eef400a23c83ffdf779d6b9ff68925c69e7584075813393fd6376e47b275752bfc9b76c364614358e98b9f93067b131b129b818d8ccd171bfbb00b50ff4da42d6cefc5262846a3f7287ceaa602b98f7e6c4b10083927625a49717256f1ca9e92d2b63c0ee50b6d757f742e04cd39294b608a5fd8f486bf0313f69af348d1a5761b6915a212918092d166e3246df3f6ae405618b686e6aa184ba5ff15e9dff8a908c31d05a053020067f3d479534507aa048e55ed86340c87627dcc015d7332a37c984e723ac0624ada9d6805f6eef8f25441d8117f0845be44339beec49fa8c735aa212892479c89ce9979839006d014ffc9a7d4cce3584692187e1795042265cb4f9672ddc25a01b849088efc664a42e635400899db12e577a29ccb3e1220b89fce1732d066acec716e60d0140356509e19f7edf6624cc8decbe0b157f3331774fb5bf45d1a63ed833c5e0ed712dde89e952924e96cbbe3d6743887c3b2350b86c8f663f9f7f9eb54d019641243279d0710eb3ebb255056a21b963dfa0ab51b25bce9a738c7e3ba5cc2b957d3a80b1db3525da812aefefd0ed5734899aa18147e8b740cb2301eb58166e969b5420d371e1fb1275851361b764f7196fe34e9f537ab6e6d835c2a1665035aa54d14d11851c138a2b3ec708a21e22e3b10761d60526639189b080fdade1ee52e8d87122e0ca3f37e8c32f6b5f1a99b91021bda98dbe51d38532f548d09a1cdb5dcd46658fb76dd36334ab15be947ba424c43386c7a0080c5f44b23da6fcb963a75dd223ea12209ad779f61a72246ea9ccc4540fea6feeffca7b9df83493d502feda7518226a359829ce0477311dcb99164b4ff958869cbab0d2df5260117797ac97d6d4410dbf8bf6ff38f2485fe9e821d6944542f52794dfb212b43cf865f85e844e750f6090589d6cc7e7da68cce627ca1ce9e7b7832e2ac89f700aca7cf31dff3736a601a9dcbc1ac5a4160ff4229701e7d163d2013e924964a424cf54ea74c4028f9813375fbc48419fe392862ad47a6fdea7e526753a0fd3424e84d57f0e259a74ada54a5abcc1b3131161d65f33b15265d35b173154e42d251119436b5816a8f5b3e924b36cd4ea3a85eeaa86cfd1cabc94b9b6fc4b7d0004cdc9c9ac7cd6c51d7639b5a01fc35027ace779b3a70eea4900330fcf0c30f3ffcf0c30f3ffcf0eb6c867010f2899864a5f53bbfbaaa12e07c5352529225e3ffcd9afdb58192b58192b58192977301c809ba09ec09dc041a51388a318368881355a537281ce4a489a975abba2a963ad078c281678a68e7042bcde128d070c2417f458ced1fe9734836e1c8ab8348975dd896cb84a3ac90528610dc251cbef9db55aa38f9bf42071a4a3870dded8e3192241cffc5ce5c59e3c4949b31300e349070ac72b1ba3fbdc43e4738f6b40c2ec13724ebd3084771ad315fd7ed5e4d07071a4538f64f997f626c79df9408079f534c44f53895e319c241bea8bbaed1df95c34238baf6fcb2399b37d008c29187aa30297badc518ad25d000c251b6da75d2aca41df70f0e52d9a494c2fe56bb436da0e183e324599e54e37c47cf3d3836fb0e99fa3c8fbf448307c753b177a272bccfadbb50fac298c0ef0a0c2cc08b118401460abe088302ee0ad8224301347670f86d5bf93a03c38b2eb8e8a20c2fea28023474705829931db1ba39f864061a3938cece1d53a64e1a2345c6400307c7dbdb2dd9624b688959e00b2f4c199e002559a07183e3a01f793a3d675a521dd0b0c1f10613cbdee9bf539a6b7098fd5cacfd3f06d194185e74b1c51662d0a0c1e169b0b9b0b9cfe028e594ffd2b6cdd52eed820cc380531a3238d28d17374e3a06c7a12fdaabec2777ec6170185c3527c99025636d1a2f384a5fa9544f1b267dd170c181e7be8d8a752b8e3cc22c44c6d3bd25597110fd838618e65a12fb2a8e3f86e8c857a9e2a8bb66c3654e638e792a8e5b3a6fa7246e39114105111db7d5f33ea720759c8b7c9574531cbf67f7596a67cbf629c5417c38d11cbbda181e521c4bdca60d369fa4da328a8318d5d6c3edde778e8be2c8e32f3f227abb2a1b8ae38c5e19aa5b06c5815fae10be2dc987463f7118249ea7f5ac1a91a3278e37c7e43421afe710cc4e1cec25ed4d2bc9737a72e2e82eddce972689eddc260e531a89ea2995ba99451387496e2fa4a46ca163cbc4b15d566baee9f1d462e2e853dc2cd3fd1247e672b7258e4454b2598ab1119daac4f1ba5ec9685429713cf152fb74e50d5fd1248ea742d6185583258d39ca82199238ca27392c67a9eb98934dc18c481cc5f7f017d65f636c0e240eb4b354ca39da8f38eacca056b69d230ebddf2f86d68c097d69c4a1d4d5665c488c388eed39e782c5b7757ec6220ea2c5f55d2eaba4bf228e3cd6aac54c7d333b1371bc99c973ecbbb890d50c441cd444d59290b3bbb855d630e31047ab9a1635db45fed28b2e4ec005d5126618e2f8e5365b6e25de7e5d8863adb4292d4fbeb9d210e230ddab425acd64b71c185e708134c61661c6208e63e608b2192e7d292988e390c4726d4d6c2e99e00e6604e2d03f3b62f3b576a42c200ce311b5152efdc3917dafdcade58f34d6e960861f0e3edc55c879b3a7caedc3819edae585ca4ec93d3e1c455275cb6ed916550d66ece1683a68dfcd4868598f1e8ef4ce3ccfa2bf66b9f37090824e7ccbabf07020dde942fcd94b293e7738d87c9353feca4acd6887c3f01424746d5787c39a4da12d4987430f579b3df5ae25324283197338928fc934989a64282113c40c391c5caa6fd7e8751ddf8a718130cc88c3b1ba94a5bed411fb61381cee5b878c99adb255e50d4726c9fad7226279e686a374e93ca5da6a660adb70a4417246c4325b8cb2e12865c4f210e56ae73b0117472e460a3030868b218619630334630d4712e2a41599520d475b71c368a8cd01c3c510c300291803032a989186e3b2b5dbd8de561a73c0988186e3eb584936c53c3191679cc1142554f2915630c30c4761d63c429e18f2e614045ca181321c65f78c776e91cbe292e1d826c56cedcc6c259d318643ef0c3df71417c3a15eb8301552864929010ca4c08c3186c111cc08c371fa178d27613fbb2c60388823a5913fdf2f1c680a121e36c69c1a572ffc51ff428ad9b40b076fe2997261316a835c380afb13ed1566b3764280195b389e8938a9dea5fd3205ccd042cec8c20c2cd88c2b1c6f4fa70b1953dbeda60bb2c10c2b582f155656d1aec271cc10cba3946dc5149d4185a3e825d3eeb7a156df195338d0df8a613d74e2c8b9c5dcf84b148e2a7bd6226c9414c30b858332db18aee17dc271fc93919c75b256ad4e380ecf3dcf39984d38f2983bbf8fcd84e392d9d4f8d12c395bc2a145da1295e99470901de653d6c4241cef8b5c05fdcd4a63876006120ea345b38aa142473892987c2e963e4f9ec80c231ccd5f4ce599725cb26d46118e474743a8a89d9d4184a3f87962c4d3b7bd75c80d3386701ce5d7c724cd62fe344308c7122a9475e4db88a6705146185f9041e802338270b4712d2e9746cf1872188514338070d0957feab33b7fc6bfa398f183a310affb21a7dcb1ac77a154a898e183e310d54a9164f454564bc58c1e1c6e52d51cffc22ef4b6d8826a060f0e3ca7cb4e69a3329c0c320c174766eca048b699543fba020157943106152ee43043074793bbfa1fa7cfc1919dec06c9d291c2a57170e89da583fbcb0598718363a92ef7fabd9552cf06872135723aead1276d336a7094aa43dce68f1049f2193438cafe5292c3b6e97bc88c191c7647f35bcf4b020e0203c6d20c191cefe5b0d9a12e5ceda70a4303553362709cbff22de494cf192b46980183831ec9e7912e58678b21c28c171c74b6b8aeeca40c672b1f238cbe805960860b8e55fa3e5c5ebe1469314a508693518b452b0ec62ed2737e168bfc75a144069162c18aa388b963ac74a5efd757715ca1f19db9557e2d57c5e1dae6f53f3b1507b1a5b37fb060db72a3e240c73eec36068dcf9de270e6d3f6aee62b09b1298edb737df4518933c9528a63f7d47d1a1245d75b52b0baf5f12b257514873abd19c2ce298a0399a929cfcd122262a138ae781d425bcefec983e2305d4a9a3a68bac5479f3876971855be725ac83d7110cebe724821fed175e22885a4decc9359246d06c83d60c1092653fc7787486ee2c0be3d9f6b7bcebe7b12b0d0c451d8478ecbd9629189a3f71d71a9aef50a5860e228dbba4328d5bc948c52018b4b1c458dfd69928f9ce62c712c12161b3fbc953848de9d327f904c11c90a5850e2a826a564b521c60d396712c7c92564fb5871bdabe014b090c471987c7943e62f4e2a2eb088c481f489a58b9ab579251690389098375de73fb7a78dc5238e937e5e0ca55f712a8485230e76be3ff67c52b77c5834e2d0276626a509352a592c1871b41b3fdf8589394d368b38c89ba2640caba08085220e364fb21039ccfa053711c7156ccceeb25820e228a78f1cfd439ef05ab138c471e7a78ae43a626188a38d1fa298449aca21195814e278ce25c49a24b1c6a21a032c0861b49887ebfa8e3977a19474050616a080086cb1051765f8180d46180820a3015b6c01868b208c32b820c3bbe832cc08b6d8e20a81c520120b41d41669012c02715c316d45962f9f109518b000c44168c4f88dc4d8e4fd0f873b3a93f93256dce97e387ea908093926e193f7e160bca67aee2d72b60e1f0eece4a34cb26f9ba6f7709c51b36c3e8d583bb51e0e3dda2464edb902c5d4f14206c7a592d2535e772306d85aaa7e083617611c33c2060c0e82c445996dfbe4f2e161e305c716e4c286a0125762aceab0e182e3ac96d3e3c4e83db915c73329b769635b3b3dac38c8d1f6e34ae73307e90e3556a14f879aeafca22a8e4362f8df963c99ea151d6aa4e2482384a94e91e36b8ea3e2207dca4f9f776ba8718ae371cb496fb255438de74cc52adb7e32821aa53870b98b14e3fdb4e69453831447fe1ff3e65fd653737ca8318a4379f34df1696bdf3936871aa238b4d777d9d149a6a146280e255b0e5972f5559e078a438d9d577721dd48ced5f8c4f1e430e551328e4ccb353cf1c712579b19895577a164c5458d4e1c6b44ce4c13529ac389c3fb2f359fa96c7241f2428d4d1c564e1f7b36d6f9e5790935347114dadccc2bcf52cc452a13c713baa13b84ad6a60e228f47b9cea9a4eed145f3441d5b8c4d199c4601236a68ebd5be2b8eb35fee323e5264f258e2b58985429ceaefd4289a3f0d3112a9ac673b44ce2b0b2a7dfa04be228947fa409fdd12c66240e434cfbbd1e41481cada59c923d498d471cc745ced92ff78e38e891e90d9f2fbce802015b6c61871a8d388ae8d192a43a31d5c8888370933d048831823118506311c7512521de8615711c23630a8bed127118b5e22df27888e620e2e863b4354971da620b2e680ca23ed43844b16fd925e8668638b890d917b9558d421c65b6cc38e177421ce967399becf40e151fc461d4bc2e2e3171fec3823875ccb10ac4e178acf06c31b946a580b8cfceea65d63f1c65b110abf553629e9c1f8edf2b59fccd55a30fc73efea163eaf0e1c87cae636e088f22fb1e0efbbc6298dfb49fd37a380a973fa887b314e39787430b1727630ef36b13e3e1b023844fbe361252e70e873bd39233bcfd556a8763b9ce29576c5e52d0d4e1207bf96910eb4c532d1d8e7385dad8bd8a7f967338d23cc1c77d2363ba723854977ab5ef8ae12c8cc341be9bab5a7e7038dedbe8d099e80dc7394d75c4c76bb8e1a04d3d9687aa0e95ff361c88f77bfa059f0d871b345b48ef49a6d5d770a8d97a13cb72351caaff8724a9b6663d69383a598b1e47f744d368389e9c2f597e7cce70109521449b6ff7189d828d6d88fb4d97e1f02396e7df6c93e128c532472a87cfb163c67010529658fa8d21846dc4701055634d8b59c2701cf9630e995a51fa5c301c556d76c6fbf40b079e5f2155bea07179f4c271ce8edf3bf18d1463178e92776b97c620178e63929e84e0aff6f56de138e9869c5a96da9c4e0b073962ea31454ebc3a0b471d3fe7ce28dff063e150f7ef6388664c86af7018f3fca4a5f859216c5638923cea9fc43f5d3aabc2d1cba46c39db4585c30b979496f348b6650a87f17ccfea3629901937d5870945e1305665bd4908b9734628e0841a50387c996c91ba50952dfe84a3b4f927ac63f4387e3be1205d45f65fda84a398653ae387dc92ae64c2519a14d613a992a6c8985063093594709c26bd496cdef06076128e572c5744434d420d241cdb2593e91021644ccc165b24a2c6110e63ec7d798e560d775da00b320c03b6c4302368400d231c77089751e4bb752fa70ba5d43dd4284241f466f334590a11ea820cd3450b6a10e15872bbf94f495d1c2ec8f0130618554609260001f7620c0c44a2c6108e72689e48aa1217ca2c01185c7c185c143ac0058c12033584701442a4d8926123d49b65841a413888b8f296d3e7f89714a10610acc60f0eff33f5e674d91a3e386c0b9749222da446df838308d1a7245894681b91e145a3c07970fc9f4683a7a9608451480335767064725927fad96a7661400d1d1cba46f0b8f96fc64732bc80805aa0460e8eafbb64ffd3f8565d5c5081c01c206be0e070b4c76cc257ba02030b2003015720e08a11340746d0284841d4b8c181ce861863746517ff9830be98000afc9049a0860d8e7ace3dbc2f6ae6e732d4a8c161ef7eeeff7618dfc5508306879a73d8c8fb35166acce0306454d1ef490acaa0420d19d488c1d1fbff7a923ca163c8156ac0e030e7c64af91023776a6bbce02845d98a7ad9a328d470c15143889938217a1446185d70e15f1c2faae440a31587dba6e19b4429d060c561be3e310f32792d3a739153a0b18a2389902d87c47fb8185d8181055c81802fbe30c01508b8e20a045c81802baec00004ae3842484315871f646d5435dead30cae0a2d8a1918a833edb7429345071d449ed3f367ec4c5fa1487973729f227e7943c6c8ae38db1a93ba5e9d130699482a49f3727cd9e1447616f8fe2e8628adc985b3e8b4514071be347a59a90fca2a1388c1cd594f2098a0309414270a9a0f1beffc461e7f348df515e040d4f1cda9bcd67080ffa7e278e34e588bf5f9d1307994322cb8d9b380e9e36e25dcaf915714d1c74b6f20ddbcf1cda4c1cc4ac9c72a2b59321260e2fce7aa60e5eea1f305c0c329006342e719031db8ab4b744eb8e250e5c35f7c7958694a3af5860d0a8c4816feb670c6f97824d8963d50916ae159244a52771acc973db54a42571bc7677a3295f6c951c89e30abf7142b6061247a7bf633753f5ee96471c6807b949a92cd5cae28803cb9f53af4efa5fcf36e2302f3674b46b95ad282390eff8f198451cf465b01c62bbac2355c451468a41b3dde59a9f88e32f8bca2013f31f4e44f02f751bf25e52e81007d933cbdde6d21007f9537db3536fd9948538ca29499d7e4a65a424c461ca8c7fd13e9645080771bcb7ba6a84be4b3182388cba4bb9914b547302711c1b2e4be53be2d20788c38d512da79918d467fbc3b1f8f7e68743b50ae9672e75f0b90f59fda64cf3e148e2be47ce3a27c37b388cf163a755ce33cdea81d2ac88112d9bc46e694b6331735a5a1a7938e84acb1ce2e3e6070f87dfd17edfbcc35168ff878ef1d9e1287f287dddb0ea70909eb94bf32ceee5890e8733229f65253a334c7338885e4992c3a1c65deafafbbb55e370e85ffbea9e63789e70388a8be1a266fd247fc38124af0ad3792923e786c36ce956a3d47957aa0dc777933b9494ae278974a1f485e93020a054be30ce001a6c3890dc2ab5b85149048d351c656edbee564abf9e622168a8e150a26f5f6ba64d1992693894ba370f99fdeb316d1034d070947749c25dd4dc8c92331c5a081312566e62de6a82a06186630b952a345f321a65384ae9589241da527fa0418623cdb952c8e0395b9e681f688ce1d83ebce4fcb3c470e861f795c9a3bb028d301c7a4c92942bfe5c555f78a00186c3b8e43b9dd2e6b8b5d41d687ce1502e877cfa59a33d5776a0e18523e9918ff943a206ff74e128c7f1e95c325924d24fa0c185e3d6c9dd1472660b473ddbb17b1a936c8c160e7cc2aa9b84350dab6864e1e0ab53be0db92c5838b2948a663d10685ce1e07273ecbcf217e5fa20d0b0c251d4df6b5ee9b0b81df5018d2a1cbef8a7b55cb129c5910a47e923319bc685b4eb7e40630a07e36eedb26d569a39522858bcceba3505ff08b562ec237b1c717cbf9f5dd45463da4e2308d1e5b2456eef9411c739c4cd9c38d71666594466771b36deefa688239b75b9fa34713c3e8697e105f9175cc89045228e275d67c7bd8f88e3b0103153f38738f0778fc1ae2b346537c4b1e7f1b8a7655196ff421c76ca7c9fe28734e631843898f73c57cbd11f561bc4a1ca464e2e270ae2b86b375eccf96ee90fc441dc1ce2a5a496cb920b88c309f1b7f442f787030d2512266462852cfc70f4912466f1cd92b61c15b2e8c36148e4d13c9bda436f3e1c5584cb6f2bf71e8e538c9242f9c5cb1c347a3872ebb1903bce29649187e3ca95cb37a7c6c9f778f823733e79cf8fef70d019b723a2f67638d45039bfa4742e3ca70e66d188fa91f2fad0e13866afc55c58f988f21cb424933fe74a9d28a21c7e491d267b860e9a389839ef62957e957587c371c886247759bee1307b947c51f5fce9a31b8e6d4279e6a9fbce93e342c590451b8e534cb66dbaa1e3f767c351fd5d48db4b9765fb1a8edc83a678baf799425c0d0753c942cadc95341c7bad680e9573f6b48986a3902168b29043fb3b7886c3087957aa524e91309917b230c3f1b807c949e2a9bde4cb7094f62fc242eb64384e1b2d660d97c770f479727ebb8488b7ba9085180e4ca34506cdffba97301c780833daf9413786070cc731c678ddf3ec41f2fec2e159dbe518c3b5536cc43023302164e1858378b1226972dcc686d403ae40c015b4852cba508aca87fe5c20ad66e58466cb6f61119da4160e5a15c92f5976784e16e8ce326bf5c1c293653d7c0849f2397d857334a70f5f5b414b8b1b1727882797ab80578e4125eba496af50c1168f199ffad2296471e42fcb7bfe4b2a852ca290c6c4f821426558a0c09d4b2e9f1c29f3e6134ad2154542e54caba1135eb58939b2c7bc3781e8f3e830010b51c29c47ffc92de1e80fb7c430114812c38c8050164ae824f24892a425d62661496732f3a97a4124f0ffd2b9ad53ecacfe0887fe9e7e26669d560c3302338215c483844a112a8dcde9adf3d7f94984e3d7dc1de2f93f0462ded3fa678cb13f11c2d1e5e4312dfa6948bf8390471ccfffe7934b201c44ee78994359d0989a1f1c73ce88ef1f363e8961a8c43023301464e183c310c627e374787e64c53011200ac8a2078719dca6d345b4f5869590050f0e4b935f8e1ae39f67548e90c50e8ec542dd7da4570707215d57ec85c866b63938b4ac97cc36d13f5f2c0b1c1c59eead8cadac7fa96f5017c8c206c712f383060db211b2a8c171f0bd903b711331d9343890dccc9a1dc52c66703819a12e6ad6d07b1bf1200b191ce5a8a9623e5fd765450259c4e0f03b3e46d2e225ef1f06ae86883291f80b8ef642c6780b1ed43d59b8e0f8e24588776561333cad38ae38ee12be66561c78da7b8fd7cd2a0e3504ef934d2b1131ab8a239df8254923a74fd6a6e238438694ac3e7bbf43541c8a465df5cf8bf7f24e71641df675ab62a638a8ce52d1f98feb77290e5a3a4e72d25ef20d290e4354e7d2ae7f6a1cc5f17f8d864b88f4ae4a14c7929b5fdb326e6ea62b104043d808c5d1e67b08dd8f31467fdc8b313000840d501c7af6e99308fb13c75eb9c23544d0f27cf1c451862db795b93a71f439447db0c189a35c21438b474ac815c1266c6c02f7ae1a8d6d399a3848371fb7fc6236327174ff5e1f721213ce6d7fcc921aa15ee2482da3dadd9f77e66f894f633d4f5e34a5b21207617b5248ad6da93713c30625485e492ba668967a0e9527c58e21ae863cd898c471cd848b6e1ddea96a0afc0144071b9238cee4f312237754c4c546240e424e9d57622c4d529e0bac2b30b000481cc4ec9273bc30dd73b90b2511981194016c3ce23842497fc4297dadc9011b8e403c6d46cc2a13361a4165c48edc9a236c30828a9418c26511476ddbd44abf4cd8091b8a38482d757f9d92a55bab0b2531cc09c8e0028c30d49ce002604ca0c060231187a9233605cf253f1e93820d441c7988202924d94fdfb00ba5431c7587b7f31cdd5b47c086218ee3b6db59f478751eed08360a716463a92b5134edbc49888388c1628fe5fafc772645606310074136e78a5e9f0c22f7628c32ca86200ebba2b337ed53cfe60371a8fa7d15af9b2ecd03c4f1988fe69c6270bb0f75a104c6182528c3c7e0028ce7620464981370e165981d60e30fc779bb32e49430ca00c38b30ca00a30108d8f0c3d16bafc686cc9a3378fa709cd672fcbcb27615637c38d670ad1f5d2112427e0fc75145fa639818212bb8a18783f81a215351fa537784aa4660ee6394c19887a3b0d7f119c52585d137f0702813c532e7247a33dee1e8ca5228f95f759d330a1b7638bcad482100034fd8a8c361e5930b66b7d77e5117ba4107fd62630e1b72b88d387c71f597434cb30b2513b805b6d8c2043e86d118658831870d381c24bbd408db1095dfe5c2bb68d36294800b118411c6175a812b10700504aec000040a895102118411c61769828d371ca54edf99899812c3e586a3149952c7b451fdd8461b8ea5e29378c4deb8e0b3e1f0fd6f3eba2ba6edb2b186a388d6f1acd06d194236d4709cb62a67cf29de85d2175f983e301450b491860d341c6fca1db5245ffd59772c60812db6d8620b0bb802ba28c38b0d7c613c015b6c7126810e701180196c9ce15036a6cbeb36792a8e8a880d331cd5879e44fb66888d3294a2aba628eb621c36c870541937e4c771af6c5a17aa63d818c351dffac776486c9ca87a61430c59a7541eb9c984c446188e2bbfe65ec9e1dad906c371089735c49bd8ecb869c4c617dcfa9a49d974ae0d2f1cd9495db089af8b3407b1d185032bff9c75593136b87014d264ab562b4d39c7c3b0b18503f7aa0c1bd2ffe306b9d0f262430b47be53ad1acfe25accc828c3c9e0820c343248b09185839c5233d3354264cbf062045e7ca1b58185a36c17f364fdcd9ec7eb42e9ca031b5738d2368d3ea562bb096cc30a47551e652d2419f53a27b05185e3cd1bff2a567bac3418a60c2f38c130c00615a83eb031850d6c48e120ccbd6fc4f5603617ae022fcaf0020c4346148ee44c3ba4a5c66ab31cd880c2517a5bcbb0b5cb30031b4f38b6904a8be2fe86138ed3e4911d17b509c729a55e464846974d02b1c184a30ed1b9db431e09f737967070c15add50027935b5f744e1b09184a394db35a5a26a3e6d01400b1b48380c2106d9cd6f4f175d0f1b4738ec2f0f71f1b42b1070870d231c7d8ed48cd9381d368a706cd123b5a37bae4bd15d010db0336c10e1f82f8c26877094e34f2cf9ae741aa7f2c186100eea3359ca60317c8535061b4138f61ad3c8da6631edd38552d960030847d52126fc4d48b0bc651a367e7078d9d61f924dd20c1b3e38966a5f95b6b4d29ceac1f1a66c716f721e1c58f0105541f42be244c3c60e0ee4b54227fee965fd75908464912ebb3595612307075ddf9b2df9e85dcce3e0705266518f7a51bb3b17366e70a4f9e4375feb4362b4850d1b1c746af0d9beb58b8d1a1c7b4feadf90950d1a1ce4dad98e91f62b8278c0702eaa9eb03183a3241772eac91ba38538b61c430e218e3a4eda85dc64d43f8823cf9f5ff553942cad200efd23547bee609d6a208e73b28fb9b2dc144a401ce67b8e78baf51fb60f1ef5c371bd9b59a69cb69ee43e1caaac078d9af626850f473219d2e9bc8847b8ece1b057eb5752c6ca13d74376bdf1e38770f3706c1722a9a7440c77119455bb09480402c0c391590af183d84e5c8adee120445cf675b57bf4b4c3e16699d998d4cf8dc13a1c764af5a73e221d0eef35cd4d67a227787338ced9fec37c7c64b9981c8e45fd4dba2bc7b0d4e270686a2eed49f33eda0587a3b594ce2ac525b8586f38c81432bf3dab7ffcca0d47fa90192278d586434fbfbe9afe39569c0dc72e6979d3b3e9fabc868348b969530c799962d4701c63f927a6cfaba7a4e128a864eb56b4447b091a8e3dc5599c8de8caea194a618200cc709452a9955de7feb05418045086a36097e29ee5dc8200c870902eab64ffa8ceadfe188eb3b52d623369cee28b21552080301c4b444fda49ddd6b407c3e17ef6982a13c2bec7bf7014736b887d1173b4b8170e2e3fdbef8b65cf90d385a30da51d3af675a4ce85239d57179fec9683d85b3808d1abfa43b01444d7c2412e0f1ffae349eb270b07e313536889aeeb2c168e3fa5ed226b854ce6150e83dc869853c888b9d80a073b315b16cf3199dda60a07eff37eb91e2a1c47ae98e52a2667a9a770a096b25ca572799d8b14b82080281c581e0bf36351a2d20285a3b4ae0cba339fb5ef138e3cd7d4bf7deb84839a3bcf8aec1b35679b70e89a1e524f3e091a2f130e3fb56a5287bc90769770147453ecb3144ff351251ccccf47b08e7d351d4dc2b17e65bdd67c22e120633d44ccf811729347384e9ea142e6b3f89da6110e425fc6a9cf482f5f16e16832b28789cb20d913e1783a582c8b380ee1b862e8aca9b2536c8b42384c563a9ef3e618a1c4201ced5e8b450c9a5e3404c271ae54f937e33f380c1d3359be5c2652fbe038e44ebf8926f3d7ac0747e79a576f26e647cd8343b7b218521ae66da91d1cc56e468b3f9621d93a38eef0f09250520e8e2d86692f7bedc9530802c0c171a57ccb46caf9463b3738d4ed4c7e29c4c9b2c906c7b1eabd6b9f1a1c8418fb556f7e1317018200687090c7375dda28ff1f9dc191c549cb46f60290c1c16a6cac4a91211db900627050377a393f2adbd72d00181c9ccb84dc506962620be00587924e3d7d9ad5bc712300171cdf7ec76b780a6e49d38a83db942e0679d9bcf9c28a834f51c6e723969ba9ab384e1b61f935a93b7a5015c72a16eeb2bfef44c3541cd8ece578e3f23bf9a1e228cb974c083dfa397ca73814d1f87eb14d71ac11733e64d5965aad1447e173ae7c0f51f972487190ab6343c59da5d0d5288ec7c2697e96f0db5e140731c753ca1fde452d148a43df9c8e6f313ae74d7ea005288e3b494599b8b93b4bffc4714cfb9669d1633eed78e2d8436593ebb5c65ba71307314c9af5b49f2288cd89c398dfa6fcf4673ed59b388ea32986060f6d31c89a3848b1c2f52c993892d048a9f9ee7dcf60e2d852fa2037f21337572e712c9f247464a994435c4b1c7affbb9ea85ad48a56e2404265980c7195a6494a1c86d49e2c6e0527716ce13d224e779238f233d3ca5e31a2a72271181b2ad9c7ce49b3a4207160dda2f351723add896af188438b5d5dc9fa71c4f1a48a714f377948921b712439cc6f366fa6998611471a3ec2f2878b38cc15e1a288a3a82771c3b78938cc39d23a37aca6fb1511871d72df6396aaaf8c1ee2a083df5bddd746c8a4218e6225c9187a8285380adda89dd112296f23c4c1e888c479ea920dd9204892ece7553b411c7d0e1ab59348758654200eec36dcec66251f0f01e238b537766eaecdceffe1c077f32685ad9b684925410b3f1c49dd5897c7b40beff7e120236c48be7af3e13866b1b1d6eddff89c3d1c8a4d8c9c7252b2183b7a38e89832417bdf2e375ae4e17066433a06cbe0e1208799feb9206935297738ae12ed942f2475623b1c76b0fe984919cb531d8e2356d60afa6d5d214987a32449e72a559cc3d159b4f42159ab679a1c8a4921c76474ffd20f681187a370c12f66cb294fc6eb085ac0416fd79435ff063bb3d747f4dda0c8c67aeadbb0b998f8ffce865bcfc42d89e5ec6b3827a64aa49025e36a30f676ae054f73f134e8298c7464d2d1e04f84fc92f3331ca8e56fe690c1a26d6e062a4f7542fd46b14f194e77cdec519d31870cc6892198e668318627b45ecbcc7f3d5a88c1aa30b739a7b71661b0bc27c6b9c140dabb87103e97fd052605cf0f963eadec0566f4829ee4cc1d2b77817c5b1d4fe6029e2c34f4cae9c95b28f684c7c9d0295f8cb5405cb5eb94fa353fe12c50626146cbe5eb7d838533478c61b3588ef93657387cd287b9e8b2adc08ae4f5b61039e4520564d52ee9bcd5cd4b05de6c3eee8674b92964b6f9d22fd8064b490199a45b9a3da4c46811854c23c7be58f8bf40a134edda3d398dfd5c9eb0db6d8cd709e734217872abe8952d4d30a56fab182ca6a58509e6644d87a73c31e525102635f59d9c89ac0422866db647db3c4d12f8efd8bfe322e1b0b3657a8ece123a5c2eb438c2eea17eed3ba56e8df077f028d94263cad416c1149235fee7ddd410216dcbee901cc1552d8670b23c8f3abef1a91642e8642e5ebeec99522d8270e65f8a9de4b6974e2d8070be8f97e47e67ffc0ac9a318ace87257d60e467448f75d7f6608921578ca6163cb073a76a3f679a9fa9c50eeebc4e99f37265a9850e9cb9b09d69e6c0eae41d9752750707c565d590df6dbcc11943cab72c0bdaa0d457e639895ad4e0304b56aa129e29895ad0e04b3a3197e6fe0effb498c19d431aed8976f5692183f29cba8ee5dfbdcd6911032ab746c829e197725ac0e014726589ea1452ac9c162f58626e4ebca22e8ba7850b4aaf3fbf89edd7b5c2d515950a413656d86f397a8cda2a0e5fb319b3dcfc97a68a46bcd24f07cd525108a94c156e6f2164a83035697a0c6143f7750a6fbcdb93ca8598e3650a33c74497938aea54299a1416e3666bcd96278569b329fd37add38fc264f1bcd24417855f975dc59365fa864291ffe4cbaccde58282cad50c5149f737fc04122b5d33ed7d4e21e4896f7ddf6b346f759d784fbd53facee939e1a4fbaed59ba0ef43dbc284945813c6e011424c33b1578a9b4298206d8c692e52c72f4188398748cf1294b44bba50258c6351f53743c948082576fbf288eafbb1f2320926ce44952d092ae73dcf712b7fa81909e37e3edda56472fe42e23869ae46c81334b41a8aeda8440ea70279301689c4e16040144861e171015314000000001414862281402c4b637df601148003512a1a3e2c2a141e1c0e121414121e100643616060201083c26050200c0803c221713132c5d503dd27811ecad464223f1da44db89bf03621e5089b6644bbc918837db09376505c91b648237866b0a960e9e03461135bf52dc29a34c8014f20171c2cd79c5ccfd2fae43303c2d22332e29cfc75303abdf04a0dfe0cce518315c246d807d380646066d0c120dfa09a816707fbe20c1521e18165091c27e449f0baf91168056a14d2ef517f27a0c79e37a55664b352fdc6d127d02f59c5518aa7142605b74ea93a9d3401dbc3a3a68ec89cb6701a9b91d74909bc2f4a48bc0987828112a23767da76e06fd2a7546fdf58bb21efd36fcde3bc95476f1039b82a685916490e045c656d3d0cbc2438340037aef9a856cb303e38336f70f6c02f827d071f08181ca824bc9a1043421a42aa81871f6c1e2ac9190d4d98414658e1a0bca6b7ec2143dbc6257b83f95a7c03c57530b909e26029379031b83760668035b822837d26a180c1cf8096c1d9e0f541924f1873b2f397c4da80cdc06070f50d263b4ed6c18c09ec08ea1f182108767023844dcc776b50fdc1a6657847ec5c2701200864ba64d9933823c844ca4194f186f100c68ee863fffc59ffdbfe0aff8b7e220009c078806e805e808c00fe131038aef12ea9080416d017b8362046a02d004ca31c3207bbaa1e6c1e101ee41ec11efefd637b5e887a8d21d2eaa1e861e4e1c9e34e1fa7c849c626351fef106447e9f18318e4018fd33f332b9accf120492569abe8e407bfcffe64973a8ad51448a510093770dba2162209f766cdfa23ee46a8f893f2919ef2518450f853b8d90a7079ca195b5294539c73c59f901455dbb120a5185c61660b117e70cc28702436153e0c200e619f05076eeae11744a488f0aa62f769ca46756f8b10a28db869e25302a61120856db1af0c02a48e8801f457dac41adc94b3b6529de4c17ea1b9922c3710101ef9938520e9e8eeefb9841465976d8d91eef24c1384a6645ef5e7a8a3a3f0e3cf48a4d16d703fa5a2c2f9d0e187dbe7e6decbfa714f730115f7686937cf4d8ae307a63e4d6dd0fd6cd9811f2d5264f634cd52d59f71e58d9313f3c2d5ba10bd9b0cb294671ad99be1aef8f27b3b2b83b1cf21ca9fd5f776054bf9b7dab508ea3bf45a5326092e26ee24fcd06109126b777f7552e9edbc5ea5e615aab5afb0badf3b5908219e4c8ee04b24e84e7ed72d7a1802b9996490dc2f59e5052ecb93494c12ec2e7700a5d558493808b37596dea30a74b96219bd170ab05aad9ae07590fef17c49d99567a4b6eaeadbc46bb4b58f2ee3e7fda11372933b515ac8be15cbec3e565bd3ce2507c481dffb5dc9758e82f74946f2c34863162375eceaf1fc5dc9e127b49fbc3fee17b9cf4c72bd0b26f01aa2c02f6931fc0899594f1aa9721cc124a941dcbb87faddc8e8d34bdd9b274ee9ea31aa473e81dfb0bbfd76ee1d16cee38e6325008a9c6ca2c74a1795139abe71e0d6890753c9cf6d92f6ecd8d4c46f4c5381737779c208cd219a422e6e2a5769c9a72b84c46da759c2a180e3fd4774756038896e236ab5637843f323f97df09fdf032fddfa2beffa4d248d7e37e3994de1f657a92aff65d7dbd7f34befd7bbc89b16ee79259fda4ac9e883d41d2e5b19f7e58e7ac9b10eefd041cf6719cf67b68d1332ee51439d87c0527a3fb8ca37801ecff1c6d6f2b9fb64cc641535cbc3c0a8fb49a111b74a2cc7a24cf60ecf3a68b795e96cf6915b41d621fa3d893f8e5f001da51187b51101f7808a581d22946a6f2901bd16804f4a1368529766b6f5a15779df16f7fa1c50578bde9910ae397ee16afeb241bcbca2f340bbaad7571c07262dc598c1b1e712cae5a5f593c8ff390e9071a7365e7a60ced4cb0b3f8b5d240d9757857fb4cc8cad00dd5a589dd7849a6ea10b28559bcf44331885d550587a71245c29d293b740303a31ade02ba5e367bbd73dce3aca60e4be3a3ab6c4b3b601c0113913e37ae7799e4fdad080d37488a0d1ddb8f69cd2e11ae160b42b65fc77e9726b1c82f1c327dbc7b7f87cc8742940203ef93e56fbdc8e0bba11465855168a01401edbde726381707b6c90098a27421e5bb004a18989f43fd18c481deb706837e1300d1dce765fd09b1e97262aabfd470ee12edc4c4bd091bd44618e9fc083a1cc5cb4c64a487085516390502d0aa0b0c35b2b975f331d52fd635f1a3a0d28954812a48bbd6c1b790919c6d0be6110fde1ae09a8bf42fcbf0e6745cc200a00878f0d4f85c6d82a983e24db7bac0ce8cc20f7f1a6413f5c353ccd22e6e0bb1b093326f2b76c1abb0cf2d077841abd0a11622305c3e88ae2afac8681940fc8d1e3b93428d0f860b6730ae026fb2508d3292a279edf4c3432a3379e4de856262cbe5a92386e499bd0dd9346c5e5013d41c20a54dc3edd423afa6c6b3f90b5e14517ab172bd6b7ce0c92740c41ce09a2661d64238542c267de48c5d8e16fd6c77dd4c434b644b08d0ca41f2f6160a99f84a9173aad59328ed18a7865b67b4093a49f93c776e758e6681024d4c196d13d4bf478d459b1546d6d3eb97fd3f84cccd55878c55c445b956918bdf068403366118861740197a832f57338d8c719bc188d596c009d5635871418c704a5a6ca00622ce610c90f4a213a01e848fdaa8991443e6f69dccbce6afa502f3d9271da449127959b25c6b161db1fd9ad4d2026f776aef0a5ef5a2a32a1c579af3ad85c6069109cd5cbe4c7f0ef15ea8bf4b8bcad720df2ac2eab5a43973fbdf9accb66d8bf6c7543c56c63420dcac4a58761815382cc091c8d5f156bf3048069f8177c1581146110c10fe1992600d4610ada589560c0c2370bfa0aaf113831d3f31890f290398f58ba0bc92b33de29035700cb5fb4d0ef66dac0252c2ed8e1a84e62d8df365dc0da7fc8fe85e7c6f64fe97f01fdd58b41fc6e59ff0302704a7e6d91048032a95028e81a4e9085959b03b74a6fc81f0ef4f460f388980d17149c4f99612f8a00cb10bc50898d9da235c07a5131242e6ca3e0b08f2e6166704f1fc477d463210fa4c909231d62c92c5821c57c157504e3d5436e2b9de0f1889cf68eb6c2a225cc6699044fab221f8fa75e219d545199aaf515c6d4a5ee12447f7aaa80143b51d4f01ff622a2d4af5bf20eb2fda988e25d2260d8314e5eae625e8d331b5bf7383a5135b6e09cf45c9835a3f3bccdf59fe9b35eadb13e1dcdb6653b4d9a94008842458d40f8e0dcf8446f4ff51ed07490bc047df61f5af3834ad28c6001afa4f62cc2169f8f053dd088da2760099cb9a1daa11c1f299f386725c2821b538aa02c657a346e259c60851d08a7c59d739e098ab8813a1436de750253df2ca4381cd60812eebf332cb7afccaa3e1284aa36c2a3b34f06614fda8fae05f568795a9378e31e9b274d40257c66d91d44a1f3e474bc00a0dcca899795c165f0921842a63937cc355526c78b06b10f5f2c17828acbd8296ff346606ac3808de57b8b3b62920c1cb71fbe8433f4a5a51976f78efa109a645fcdd04bffd17c04c31e638095295dd80457144c3adb9104ace2400896e813f27a2352f4c809fa5f458e4edd0601ea1dca3226202f0d628410774d66c426f217a48033d7a858bbc408319c35889f963acd33c6a7d1f213c079fdda76d30bb0e60e2691640b2ea708006413252dfb896b17403ca512394b0054d43f60254605e547e1e33f35d5edcee8f2eb4a81b7c45007872ea944eb5ebb12ae238dd0bac42380372b0cb59edefa12878cb091ad584a54bc12420778d9dd5836c8c485eca46f917c110a57760c3a1627aa1dda02d67d604972cf1ab771123311e80a1803b5de1b6b67536cf7ff4cba8ab4150254255c52cff51475aa03ec11b232cc686e7aba3cf5889e91f0ff29d847d52968fe6f81650828da4590d5bad1c9dddeadb786529d6108ae2f28e51284a1c0675b52994cc2e6987f014bf22fd5200655713e267463a371af5c5e7c8594f4b251c431a0cec258aa1dc4e63ec2d281693fc76973229837cab2aebe61d0cfcb322e65238cda88278322a67c954f06ec413c256ddef1e928ebf0319f046d1b0c43ee3c256f16d0822a1291880c8098b8f735895aa42c4badc0004aae48ca6b45f2001bd5e4cc3f7ea130f42d8f243502c62b02396ce759e272ee60c189c0c1aed80a36ae3c21778e3f07c8ab3db012538a894d5332b3ade3f7735415a5827afb2063b79624ea56e56e925cf7f80abe5bdeca6333bbdb10cdc9056d588b15e85490c869be8ea12a38ec0fd1cb87eb98b8ef3e76c15733a144326fbc8d412efe284b91c1b86f217627d2d0d9865606cda32bed71abb95d41e8992ee4e44d5c754b90a671701c00a45be2cb36c24a4eb95e48976332a56f1401f59a1b90712e9d9c039bb1a9805e1151dc55b97806f127c1092566578c3fd82b5f4578c1eaacfb52807a42836e86f38728abe82c2e3ed576d62a29908a353492b1c4c98e599b08e8d80b02c7e538e73e6319fe593f02975677870e5665485595ca0f6ee48d14c9e2333a6d50c989daeba0e80e03ccae9d2d0cc6a45aacea04a0982c485af5aa40a42c2f1e1758606694d39cdc504404064185fc16157b5326eb911827f41d7d9c6078c3b8723c657c9b5580c13169798871dc8cab07026dd65dcdafa36920192c5941c4507ac977d5a062e147b5a39fc502defe9fb049ca45e749d3093b95a4c14f6a3984da382fc0b7ee5c3c605f0bc4760aa80e3f9661e02700892590c5948106357d5fef4d55fc3830e518f1a6c7ad8c95953567e49fd23ab61e4e1f2c3e6b424c2404f95dcc39be5b25f81e0db5cdfe6aea333891b71a79f26956d5d83ef12fd04733829084258ac78f533c28ee80a0e2b3d4b94cd940e319292f1e06596feee67bfdd49cfa855428f6831ff20e4553a7f58d446b6c5d9cfdeb219428b4455196ecc5620142fcde9aa518316dc458256768e6e099e988ec075eec9f88bb8f3cef5bc594614cd6247b52c1b82b4fc25aac7479430fab9f8bccf0337582730510b7b8b469a54d1b6b347593acb391dc0fc493feedec1033482544641db7f7092a678a8469ce2895e8e0a352ae6eb81b23c51ee3f9ecc10b2f224bb8215d78bd799b2274a693d377da9fc52a1f80200ba6928c8fde84b4152ac792688d833b5a5052ebfaa15deca2a67a270881adb166a30ade07bb55239ebe5f0eb0c1e4a3f02a598dfb58f74b09f8399689346b9fb5c18b4bfa96756925c2665d35de089713dc7018adc788881a7c4b1033a2d24b6bee7ecf91fe829a0410e80bb48f2230d1b801b6360ca4eb88721918c8d0251dc8cb99b4ad27055fac3e872d634cafbf87afbb13e3e0923df632f968f58b60d8c9fc0c3707c6942123c0f87e3f4c8bc54760ab694701bb85a914334cb9a368b8baa9bd047af4c36a5ff154020f966688fed0d7a65737993553b59c0947edcb880374c9e1b972870efd733e65dce1329ce9a262a90307c592b0f2ebed554bbeabb3d994ac6f6c506b368b4b0c564a307d85a829231624060300f53ea0cdbc12ac53c7412cfdf08e07c4f367ed79f59f8f5e86a8c6d3f6e64b1641defa0e7854a42e8064fddcade5ac89ce6be386decdb7f790d823569fa985493be0ab5c122a4490eb249b5abef836a6440db64b82cb478e2747da7694ddd7209c7810fcf214ad4a74bb1fe939d4d18fd846c604f65674bba2a32d4a04129b1f87f6dd734ec393dfaf717ba9f97e403363d7736d7dd4640ac4fba7c0ccf2ec2c81ead9326e3ddb7a943a0bb0288cd9dcdac90d11efb4e177b4bba2d27b6d4f415708961a6242b703696b73587eff434b7fa373be9f5f724a90aca72b4390ca8829478b40e54aa0c0bca18abf53f99acb17bc8009c3218f8fd28856c7cebf337a5033928201315652a7eeb88be8e72e59b582959b3d218b61a3416fe7d39e6e69c24a8f4538f512bdea90b45ad8361a341c6548936bc380e98e8a2f452bc5d2a1e2d60748dea2d155b0267a3c1e15c8682d08a601646bd9f32b4f7e37c35e5bfe8cda7b019b9037e9319944e1bbd12cf7ff62ddb100693d708f77ee7ad8e217d8bcdb21749ec41d15475602d06af27fdc50ce04a643d2411a9189b8a1b28cb4467c9b87de20362c820b567cb38dd8d49e57e9d8d2996b0be992096d604cf2e3c306667a97eb69d46b807466876ad96fa26cc3e3f7f7b2fb9c9339aaf00a85d6d1a6b7c98cb7bb621831216afeb009eb9cde0d5a447c6c797e4e3e0493121abf9ee60b0826a14bfc39d164e259c9a6137a133cc93549eb2511261540a23af6346e62275181240f35432c51d92fdef7a195e09eaada63496efac97af7d8d7c7fbccf89bdee203e1909411b28487d3294d8fe43121c54e12457abcefae9c087c1e561e3fc46389544a4e308f63f67847d6d49b20e3f1eb31cc1e23b9d4573324f4f0f6d8e58362109c917b90668fc6f26309f9575210f2111b2127334fa90290933a008be2db1ea73be36091dd406b34e9c27198cb486729d6b88a8da31d4735bda1412f8dd2b479ac882b4fa379736b1e9accce1c1dea27902944685554e1191811f70475497f26ddc7816395e388996b7f80279d651f836a68c9024a0983bb08f4309761ad01682ae2ba614b8683bf1ce9623f97516600d282d36db8d20f91b0940e1a4d6eb365c29824bb20ee6f2077f20f7e89f84304858c26d01ac57265cf3504467aa693081dd0c5fa9b557aa03a411c3eafc41b138a0c956ee4f188ae38c8816ffe2023a59d5c547165c3f2187ad35f845695a95a3b76374bb15ea26336bb40524c506d3a8e091405736f1b4f6f3ff7ce871071d7435711b78572e0524a9fec1dc469261e9cc54276a5466c3571fa14f6bbd1679d819dacd2db3fbc178e916dd07074b3fb23afcec126313973568d944fb152fe8d5d17760dcf0fa296af4f33eb4d676ade974e103192ce317c1aea447f165543be8ebc11179ccd222565ff03c2decf3a2725d62e1f0c529838d9a0bed5b1e79e9cf316a23b4b39c5f71110b41a568f45246d6393f70419725757a480319703f587707a1838754c22c258021605f19d8b8f39f171cf93caefc00d3cd249644959ed0f9af9408ab6d210ad5e543ba8a2c0777ce23f3b1898d0f20eaa8f7cd742dc46c0e91842963eb78ab9abfb972e36c9a3e58cd10a4ef9f96c3f88f4229b0ea1538e40f934c8a28ed66ad1423a1e01cc703686f8325823abc051cb364eb4cc192dfdc89bc8a6c365d1fe3f1efa61f2cd1f981802107d39fd912c234f056808a688eebad2002e85dfba2fb545b093c3a1284c15efc8d0d576d770b7a003eaab3683b77e2e8e8ba3811f85e1a560b41c59f1ac035090534284975bcb65a8fb2132f7ce6e02bf2ddf482fe4cd25611d60adae3fc78d8df4620b5ec14d3e07cdc0336da2b108154d91ac94c4678d0e23c1d399d32f73159f06137d6135fbd14b93788a2e1fb37266fadf75bff099a65da7231078b4c86f79994281578788a00902c215f467d7dc280e877cccc92f3378111fe64a46fbfcfb9ffa4eb5d2c8eebf3b646bbfe4f04feb2415eda1ee0a2590f81c6cf3b7e71d84c61cbe2341ce681d854cc68582b14df18bf789fb4eb175ecc1bc2305c6c076ac53bbb9ef6b531589dd6505b0ed2044af82e049bb04036875e93b90b5bacead9ab1ba79c69992d3c9804a8c7b9cd17a561a4c35fb106b160b8bcf0d5b9e4a872e0326ac41e636af0695d8f6a52ede33b312479a6876003e84ca706c677438172ec0f5c5f71eaca8e7b4ca0e3ee6ca6b51546b953effe36de0f6553a9cb20a9c2aaaa6d8252801f3efb884ff75c494ff40a9587bf0e9c177142a3b9c78044cd79370e8c4f8a21f26e72c70c8f9153adcc0ee988e2a0d3c985c7c0c3fd41cc589a52e36d8cf0ccc69602f3ad49f791f1381b29782dfc11d227771ce62b9cc468136be8eea633bc1b92e9c890541772b7a97de07c91c35c5100910ce52fbdd6900314a516b561c878ed1a222b890178c1a1d23525baf61aa14358aed1b695988ba955087ed67c55e5b672603b6399e8e2d5cf7247b065ac99d0ef64d441ab5c7c6cdaf2ca9f5e09a0410f2826056b1243b504798443d4916795395dca3d61d06fd0c72677f412b560560d8c0b870aa05e41fb43f4e79a4c59e2e50381be8e0cc42d95f564c9544fbe55ac43041da584e009dec7acd8cac89abc76971cbbdfbd858ee5d84f159087dfa00b44b6810d4bd1d119738bb8f00ee28cae74693b9e187a3b4cc9ad7442645992222dac213ccdba62a11171c95992f53e5048e30a9d18b74bcadbc1bca24906b62b08a9b0ba87cdd5ac1d8f6ad414a0ca6e6059456ad6909198cd020f06b0fc83963fa88cfd4c9fb01307f10e0837de74787db13b62fab28ea3021396f2f0787e2f5246dda4328c01f7cc2795541a79f02f971a40d89e68897a092487072eca84b46d251a510524b186b3c5e46d64a9bbee03fbb7df308613424c577dad82d9ad600720555b4d3b3629e2d4d7327ed0bb8e3d8e0470eb8666703cc42841de9191f2f6ab237d8471d028bcc76fc195400095e1b453c2a399c4599ad299497f2c96e172075916f40453300159a7d53a401908ae4c4bd14f1f21484a29afd9388cdadb8a75729ba110a89ed641ac02363fc533d59f1d31f242028e3b964d3395ff0400d294a53d9a95265e79c9a141ae695483bad43710dc15bc19a1139c08e17fbc3bbcfb29adc241414daf705230b8a592ae295225ab0a8c085b20181c8a4d0910c6752dd06b012a89728cf3564ea2fdf094fb8b289b2c61d93b504f5bb67c050fab294ef779d33e473d489ae462a0488c0bc0c8015afd5f707b7022359588547f5adea36c432542a9b29b3a52da93dff8264e58200bf9435d888e532adcbe000cb4e1af7e7c821bf53ac63e9e2728892747621f833c328ac884e4504e25a69da60c85428307709e38eefeb6e97023765955437acd6234c5db9d179fd28339154dc6be1cdce57c6e9109061c4a41cdd4d3f8355a40d87e63e5d0a52408fc07176b0d90e10a37473a258076d858120a77f8a4c59cca0182b475bb1f5573d463fae8ebe634e3e2c02d3c55983dde1100d13540f3dc31290bb31ecd2ceb1d8440730ccc8d9082bc7a7b1dcf441c0974b5811404c080a05122b0f1c8bd60f0094c2b6c41a6b1807a0cee304fe13a8dc6f8a90383805bd5fab9944d8178f9d9a8e743f68074560328ec8008182ad324a1cd4801ab844e0c4acf421c7120b013f9a1ac188643063e7a46081d5c6e8e61abd5a0daeb82975345bd959837375907dd1efb5bf955a57d3210f2c65688dc15321872aefac90733dd4a394b6de8008a082a50629cc343a77eff84ce76389e46dcf5cacc629dd4cb28fbfea41ff8553f7e481017c423c91e052d8f1c9833c93874e15223ab32eca3abe39292b34691203f87f3332f5fadd98876428b242b682305224cb43e438be0aeb6a43e59d7bc35bd6c6f1bd090b9cdb282e42ae0dced789384aa2d01dfcca3e1134fb09af7908a4f655492cd59800f4b319d627f2dc007717837654a985319fbe59063f8cc1a696ebddfc94f71d797332dc919a53e186471caf2ab80a4b1a1a534c23eddf6d9ebf2eede844eb809ba6391da3de765e41ba888ee68ec55e603dd554d4150ba54880903ef9a602512abc2ae1acb2ce81bd6cf983004cebdd15425734b987ba603593449a4d9e6c136593f2ca3f92692ae0a3a737798680255d264f3c5a9349204062298d59e7005ed49881eb7a8fdb225551910630b00993e8a2dbbdf98d5dd98f5127f36c25a03a9d38e83a8c0b6045b3aefb95b8fd87a80b84486e38d44a0752635734c6b50608220daef1cef4bc9a3c4ca66ea83475e79b1d367a1f05ea417000d8a97428bcde4758e3a21050500a3855a003330d44279eaf051753b6d823c57d3d62011ada10b144c8a1977181242b2cb5ccc92566ebbe8b36471283dc47239f0933b272354e1a818f903a4e7e663ac8b72a911da030a4fcf75cb641dbe8b7285dbc5b55fbec626432fab2f512d15dd99fd0f5fa6dca6f6610a4642fc4591cef01bb9dd3cd976d4092c4db8621776e9ceac44315f38ef006dd47580454c068546ae7a01ab5f9486a58b81eaad422ee97739db1bd02c97e6daef4c4a11f5b228382cab1adacecc4bc11d85e1a399d03f209ef056c37953429a70fb81192ac00ff0f24d40d282239e119d6c06cb14bb0eee758a341ebc4236593cc74e0a1e115d634e56b606c056049897b94afeb0b010eb3a53cdeebc0e08cf5765b111970f493b019432f94ffe7318266fa1adc147138385d52c137194f76f3fcbee4e160c691ba8f0734931a38800fab6ad12bbba14aa516fc03246682a85c095f1e24e51cccb9ca453a602cfb5b26df07796a8c7b1701f791da2011ee4c3b6a2650b266501d9ac389e300db9e19374319ad726a84f9ca885ddfea18e38cf18e6b306202ee1da226de0e9c38a507631125ddc76da756c86f14437cd7bab541514abee48d2868046ac3a3c1c28bd889aebc37e9420a8d59a64b635440ceb44cd19c7cb8bc47b0abcf30939085a2248e5a900d8bcae36c93d9db60fe1826a120ab81887faa9243069e65c4e7a1cb70ac245f714562448aab28c6d8ec9e17ed82675f00cef408094df71563ee1106f5132f55cb6e40cbee7cb3ee61b6171f5da1ea69a2ef7cb08ec70c7d78295578004ef0bb989107ae0c4746d36c2c6913d259393a7ed3b8c1f183119f5135a37791750a279c8c4ac46a7970958c631bbd3866d5d89d476f3964f375156de041987b68a08290834aa40c7b8a74efba82e416b0d653c9b0a034d8fc14881480d61a9fbeeca975831c345346475315395d3a0c8e2bfef4c2bfeb1512390d0fb7a80e7adbeb2904b20d2f64f89102e81749b80491a1ecdd0f1e46042dc23de92a80b0ac8bb4ec6bb11c1ab20c086ab5b4e7036f282b65028749c6915c6bb778811fbeb9295d5e17c24b94d8f32a14ce251456db1c0a865c52b8a6db97e70ee76b2eafd42cabf3fbf3dc30802cf75335b100151cc14dc0cbb97f26a05b24b40033027d8b17d1d088dccc4cc62642a7605d3dc87a9ea9dfd23b276e96a60fcd73ddaca3861f77a85bf4447b25c7d94752468ab2f23b9871e3044c826680d5abc3b4fc7d72019ced1881b61b4e5cd2123bd7fe384409e2dd99ded6f6b6ff6a141c7704773c03cf017130e3b7db3df62487024ab02d3d683ca1ba6b865a9f4368d6e52cf63e7d1fa0372ef6f9655499b227a7414f0ca3288612562450eadb4b5f73ba1e265796183113d2129a9f5186b2e12a1add7c94414a39a0208046b6022657ea9bcf666d20119b086dc4cbabaf53c9d24aa2fd0855b0157f6ff036f359505a4920187c472e284e2568db416d08a32ba4411f0c2a0d6c06530665060dd06019e76d4291c8db544c1c47027ab3c7953870b0a490033ccff33ccff33ccff33ccff3a4c3f82cfba2012ddd95528a4db68fe4787b654acacc94767bdbc079d6064ad6064ad6a2972c173709e90906096fe0c326d323471ee89987165e7091812e8c1714d0d098e105175f94175c7ce106b6534ef5c12aa859693092944ce9a21a6d604d2cb8a7450e11181c34d8c0a69021c71392639cd4a0b106bee3fc8e27a923a93466a0a80d1a6a60eabb3dd6b81e4f48510d0d4368a4818d93a38f8310a9e921ed002cb4c0a2015868810503b0d0028b056881850282a08106c6cf53a447f5719c7f730626c70fd94166df0c7c6aba8a761fe4fbc82e031329a525c494d52003935352ccf7749ec12391a03106cea326777f485911aa1134c46059842af15055c2d4ac2255cacd62843c41230cfc5a8ced71a74ad9dd6980818f2d66dfbb0857e30bbc57cce97b3babc5cf16687881cb39770e0f935b5dca7581cf7bbbd61c6a25cb6a704135b6c0648ad261ed66010d2d1440230ba581056e23e55b09d3c8a0710576928795be9f1558bdf590277fd4dfe4abc05fce1d586a123bcb9c0adc45d85360b3f92611894b810d096bcd9fa28792de28f039cc2a2cacda4e5b28701d713aac723c674f9fc07814f247e6b40fd45227709bde92fb2c47d13f4713b89052eccf2815426b90099c9f5fc668ab9cb20397c0789c2c91337d68a239257015e3aa98c476d1ac2581cbbe9f36b790c06ef4b05c9a5287f67df162bd660f6254b402533ed03002df31460e42ac4e4d993f81171ed0280223212de264ae602499e782043370031a44e03aaaa895e81c4a8e1c20d0180253961a429d94da4b15070d217063f91266fa0902d36b19b1376288521d2030b93b0e2d6a073d99343f60cf527f9e6ce271a5dd077ac78de91e7039aed4ae46b7acee20b325692fdbfe76c0474cf3131ff1d8a3e88049dd2959c8154cabb31c301e07cfaf29830356efa3f4216add80d58fa38af162fa38ac0919346cc0791c4808cf8e7f739c1ab041cc3d4ab569c077f6facd0f351d3e03b2a48f21dd960167395a58e8e6a89cc6800fdf835a87390d18301243446b115fc187fca11fc4ebb882cd4c3e2989755ac18a7a9c232973c7c80c2bc87457992fb7ba23cb2ab868d93e2a91510513246285942226154c5eda8fc33899f5f247051fe5ab3009effe08fd29d8d50f5d93987e4c216f0a7e3c2da492a6145c966c63712f6a5a4f0a2ee6b4a6a0e3be9a8f82c91dae1ba17151b0ed5178fee4f9f1a91e0abe3b4ae594afbca27450b079ee152d1dc729e4f04ff0d51bc72b6bee09deb5725b8365bae674825bebcb99030fb2959c60fb737bbcf3d1eecc2618ebeff8d2de45cfa109fe53c8d1744727afcf04275231bade8b09ce5f6332ddcfaa8a964b70191a52e2c7d3bd61b144eddbc927755482cfa167caea37091d4ab09fa9c3f1c9ae14b23209734eabe017edd62209c6efd6362ce47ec44482dbe49fb14a8704b9b732f75e86b6d21ec17e18729cdd2e7a67ba1dc146cccf412a9fa021ec4694cb03db3082cbb9357e54ef4bdb16c1a7e8bb2966f2b073d58ae0529969f568bd552611ec8464493a36bd8f5310c146aa37dd1c07a631b287e0aeec33846e0825a64f885721d89a541ea79a7d9021041fc79acf23c7ab299641f061ff5175fcf45d1541709f226f8e730776b90e049b5e242b8ab9f77800c28b1eff7ba8903bceffc0ea76da6f0f2f62877e60cd7255faf4d79a26da073e8a389aee23ca07c632794e31276b857e0f4cd77a1c5c4b3db09731628c7439b47f79e0d424ef8744120fe46fbefe0e7cea28e8e6702547530f3b70ebe1244bbf60d3c1a30e4c59e705f12cd281f1524ff9d133376a9c03e71de640cbbb445244b453485aaf9b348d033b113dbbc34ba96c85036f9562471dfb062e749821ba7854896ee062ce1135d7f48510b6810f2c6c22a2a71c438e0dfcf988f649c8ad8135ddd448193570a6db21b35a2cc24f0363532639da4c13394703ab99d3e4ffe50c7cb486142d5accc05df6b1fc8fcf2b65cbc07ecedb710739b41e910c5ca6945bc8098d971b03bf9252c8f6415f6a4f0cfcdf5977af785c71b230f0d92dc5ac223130f071d420751e4fa5b37c810b413fdac3d60b7cc6cca9c374163c8e76818ff2a6a5df8f3a8a8e0b4c87529ee3fa6d0b59effd65ebd8a6ed43165ae052a5fedbe4120d992c302107962262d6ebcb63814bf13abb459fdecd15184d592dfee6a59da4151889e943ad60f5517b5015f8968ec96d3799b9870adc6578dc2b8931477f0adc9dfe6aaccbdf624a81bff4f1a7f40995d19128b0b1a3a421fae4654879220b2870b93ab61452d6b37842b9bb52fe68cb7702d37963ca802c9ac0fa76fa7f4e31223aca043ed2a94e6fcd8a1d57592c815d095539deecc98ea612d8e492dd512445fdaf64649104ce76d52e4eec0f621324b0f93bb847c8e208dc5f55be4c6963842c8cc0df079ec314bf3645acad0a5914814dad51ee5ad61e1137296441042684fc5635d92395854360bb628a9cd683c7e88a10988c979d25a7b3eeffb20802539792393615089c76b9b9bba959fc80fd1ca68ff4e69162c7b3f0011f5d4e6cbd98b42fdd59f4808978c1a7efdd93651546d217db45163c602bcd3a6d6cff20f20641163be0ce52c78ab9b7534ae21647163ae03fafb62e65bde6f08491e4458ccc22074ce69f0ecfe3d8573d471638e07fdf626d86e4a5d11059dc808f7b16d473678a13a92c6c4054b4ffa05248481259d480d33ad7cecf9b43c762b5210b1af016a2071d07dd6731033e3c560bfe6927642103366acce1eaed7928a1958108862c62c0c791985bee847538b1222d64010377daacd202015ec1c7ef1f378b672a893e1908e00a2e7614c7243b8e6c528700ad209a076a79a304600513a1afd3add722301700030156c1c791d346adcd174d827d0201547179fb985ac81f74ba54b89b5a7cd3dfc355543c659ff2f8e7b39c428f5323e8e6ca080f9ac2fac83b996847da4b81c4dfeb0e2d52fcd61d27744671d03595923253145b08939cfc21e9070142f178243629766619014041d6209635887ef009f08973a8f92dfb3a9c009ee036af064d1fe49de04bafe3d4714e1781009ce0573d2f63ca994db0eeae5193c55f139c87a196c2c31c9607954cf0ad1695d42b68ed07135c8885b4a9332774d825f80f4d3c94456d096e3cfac8fe104d21a42bc17ef697d841524ab04943529446ec8bef31093e8e6e24244991041f4b08e581e46f971c4682f1142121da7290e0f5aea3b60949bb9c47b06192c3d3e28ee06388901ed75f62d01bc1c53efdd46d31fde3388ce03a8ace91379245709aff93dfa733d18d5104e7ad5f153dff89e0adae537e88b839fa23822f0d2179ff73dc9bfe0ad87d18b3638bc101ebf1df927f9c2db676033e69645d9e728d48d980094956398888c888718e08901af0ed71d8dd92e6620b2206101a64e5716c9e69191625a1d5313deccae36e4180cc80499f4b721ca88664c1560191019772b6e4a569315cc8c8c01724067c90f437d2f6ff91ad5d1018b0c1637806cb1c09621819f90ac42f4ef96f7eae735dc16d4a6f3ac61614d868c5e9b96e4368c998333092cc062bf86076b92ba5420a9d55e829aec65455f52055b091b276f49f1453f79f0a267ddecd96089a72082a38f33c0d9fca39051ff7b5d84a889c2998643b9e9fd293869c2635818d52f021eb7778e8231ef331ba40076c90828d34c9f996a38de9dd517029512f744ac1df1005d7977ddd1ff6c12d9711630bd3051724e8828b6bc0462898289b7897d5eb3fca4b1043c689c0023640c1c590a31ee975ccf11a01116c7c828df61d42c5ab2bf4054692118162910106601181126c7882c9d17bc4f3e9956fbbd1093e4aee61fbfd6f7082cb083fcfe9b1a224cf26f85ebfff2855721869a309d6735a0d2d95c17dcf04bf6d6621c92d5f678f09d63b2484e46b2fc14d8476983d5c2dc1c6ae8c394f5909fefe2a5fc78e1f2c623092483728416563122b898d48f05148d1723c966024998fd1c5160686b76b6820ba610312b8f108b6628896db6fa37d593547602945f4844a6321193166cc30ee2798a1a131c388806670a1c5db09b0c0a2d409ba58c17fd1245880864617e68b2f9a0487d00074b0d1083eae643ee9283bdad812206c30829fb2f47bafd7d7546e2c828ddf1b35f95fb08c16860b1919204590462298d4396bf2b8330779d31b8860438e5d24f190ad51da3804a2eb3975903bd61c2ed830041da5f56eb2bbacaf22700209244001860b191950da426c1082c996a349fe21e6d0df0c82d194bc7c697cf7c34bdd862098143f3454dade3f991b8160c34ae2f925cf6a4152850d40307ac9a34aabac9bbc0346d2a1a131e30b2e62880001303c86176cbaa0400962c858c005343434344cb923003dd8f80357514435e74c1da60fb561c30f6cafb77e678bc8d63f8ca453c1461fb2db8e4c91c2879154ac88a560830f4ceac89124ff405fa7930058c4c61e38f58faeb4fe96f4b9406ce881dbf8bd1da5102500017bd8c803174347297ee8f883d537026f1919d8c00397a33a24fb24a13a856670617407267f684dbf8bed512723c6162da3bd283b3092d7e369cad9e6d92d62fc151836eac087cad19ee39a426a195fc4882163b7b04107be434b478e6adbc717f35bc478abc2c61cb8ced6105457425e955fcce04204b421073e694fb68f42a4b011073e45a5f562a59aeabc1e62030eac77b01aefa8a284d878036f593f26e96e491e39dcc0a97e5a4d9bd8461b180b6a6945731cdb6003a31a39954f471fb6ea83d85803d359faaa3a871e5954037b2bf55d1ef77f760937d2c07674c83144f3f2b081065e542be4be1472f0c8fc62e30c4cb5875e8b7d8e60c30cdc2531b78b0ab96c7306067d9b06a4c04ca00b0a6868cc681965e0fdd38bbd78a051e22336c8904f7eff30cd0e46d23962630c4ceee817f3aa7d65de328c08ba8b2e810c456c8881296bb728355922453f0c7cac13928859469dfcda1536c0c06e8966ccbdee9672c70a1b5f603d98d64ef6d3f1b47a81b1249dfa2adb326c74818bb8314ae68e5f3a54480c1b5ce0e3dde4c7efd4ebfbd8021f49f5eae724f639da68815fbfb41b3c859fda071936b2c0b6684e08416c3c7f1e0b7cd83aeec9450fc3c61558577fd1f4493bec5f34dfb0025777a9a7c9537288b0031b556033bbc37c1d5a46c60b36a8c05a08b1ddc94f818f42b0c82147bdffcd772105265d787e60daaaf98e023be671981a3fac1834bd0105462f871d78dae6474fe0fbf2e8fe7a188ca4de1c6c3881cb1ee7acfaca8191d404be3b9eb416cb41dd5bc478acc10613b8cd4c192c7ecc3cd571022f96c04b7a45d718d3836cb0a104eecc43750f546b435ebe3022a0dac14612f81cb9474f9a238b1f76c048da220612f8e81fa7183bfb47963730928c8ec055e4f31c2bfbe7a7b8451731340318e8820216803a6c1881cdb4cbea619c72061b4560f5ed5f2d5b4cf6f16b5c8b2d627c31430b0d8d2fcc8c197d28e30b2f0410870d22d4c610f8da2f8fbcdae2a8df10026731599846d9871add185ecc3032b2021b41b00d20f0dbb5298690efc2cc38096cfc806fdd501d45b51b3eb08d1ef0fd1e065df5305275a3801b2f3090010c6cf080d31c6991e57e606307ec454afb30de8729c109669413cc381d3039f4a3686a5357d2c148ca015b1f35a6e6f8fa5b53b888f1050e38a910e36be7899e2b3732086560e30666fecbc6f0628b2fba7ac3065cde5ef39c4306234941b05103c6247d7986fca17b98ad0d6cd0804b131dbafd7e42c81e5e703182193360dfe31cbb674b8191340263bc2094a5810d193071f2887bbeea70425e0f8f3cf2db850d18b039fe4bfd6ffd5141e315bc4e30fb4074a2ccc32968b88273ed8e3efcd257ed38165a606158c00506ba0250d068059723092b984e116f246eada0d05805275a9ff93a97879f3fa85ca1a10a76d27eeab84bea643434283552c176349ebfca3b54f01a31dd3354d0dcf147151aa76062448a6ec922962b33858629d8e8d0157d9b552c2224550a8d52b09f7353edd5be7d55aaa0410a3eceabb6927112068d5130593a0afdc1c3cc9e155170962468e84e87826d5d5f41c1861cc749894c7e82cffb358ff891c4c9be274866d92ab9e77acba14e706d213d457ffa40a5c2000d4e70b7e6414f4c2e6ab1b3096e42ec4b9df36d57520d4d18a7f2a69d0ed7c8441ed579420e8385164a1a98e0325f740f22728d4bf0913eb29af4b91c342c711a95300d4a70a3c1a2eb473c34ed4930923f858ee5a995b205237325c1ee4e7425df5c2e4023124c67d6bde0f1fb5d2630338a14011a90e042878bb507d6713a341ec1abfe4ba88e1dc7070d47f0c9722b25af1ac125df646693c5ef427730828fda3395e7dc3516c1b9a4b68bdbd1b1050d45301d7dfa452d7920f52a163412c17bde143c79fc89ed1a22b88fcf3dfc737308f683eed036ba87189ad7828621b8b158ed13b35d084e35a87f68e9d42004eb6ea6fa91466f4e798d41f0b13f487973491a82e03b538721e528072349045d8c8c2d62bc462018b7bbcd10530523493140072a3400c1afa70e3f8f04a9b8e11f98183ce8eca8530cfb9c1f98ced9e17d347a9192260a8d3ef039b42fb57d6021b80ac0420b2c52a1c1073e8c75da6194eae8b2c3038d3d705e672144bdbcba21898516584c008b0c44008b2668e8811bcd0ee3c721c13b8422e8820b181990612aa00fd0c80353639ebace727a477ed185713c709a3447b5531309b8281a1a8434eec076cc62a17f2f2a40c30e7c94a45e8277e7f4c84d83461d986831666e32cf1ea544830e6c7ecb71f54b688b188f7534e6c087ffc9c30f91aaa22107de63c8f9d284783abb68c481abcaecffa3954d42a40107264344a8dc4b5b12aa12f8060c09d664154612161960c020a8126cf4bdb5865676db4705a204f7217f98cb352f3387c3487aa3059a047b75925325b7c8b106072409f6aa6af3e5b7782221e76246978a0413b37d64676223081276e5bafa047a04db9f73cc1cb2b3725439c8116c889683643a21c4185ac3f0620b3a1ac185d0932ea9dc27530c122398e415762be9032d826fbdeb8fe95fb254ae0826c5bbaefdcd6c1828115ca4a4aa9fd2e6204508768110c185a60a39ba2479274e0ec1daa4785b52d519e961000a6408ce7b729c3ca72e8186c6175d981210d24230f16a34b7ba49081a4308de2f43c5f0ca6fab318106c15bece8125abb20f8f036bd05cd716416b740705f1ff880e053a5b479b40dfd81cb51a7ee5845223ff0d9eda3607dc93b2f657ea03e709239d99f239b0f4c5d4cb17e4b5afae3a03db01772b2f58f1ca407ae72182edab107e581cda17b300f2285d402080f6cee9876561e861c7e312bd01db8ca5b49b73e7790a3253bf029c68c2b96592dd581d1aeb28a5739dacbb61733b6aeb8203af01fed25b47b8ce6c06777e4f074729c8cbdd101480ea76039b6e514d59213e3f5021407d65306530d562e412b2203101cb86f0dfe1766bf81e91ced9dc8b46d1b9303b9810f1a1e8767394a09b8c800a281dac07de4da3142f0fff8fe19880dbc4884ecc177fa3fce5903efe6e52979583de5ab813fcd2d5e177214d5e3d3c07e89dda4e6942c391af8149196733b3d036fa5ab1fa9c6cdc0b47510b5b1d6831ccb32f0a271cdc6373742f420031753de38064e6fdbb5dc72ca8f1103a31bc93c92328d395461e043b87706d3af541e0303e337f1356bb06a0dd12fb06e1e6e46e51615cf626980bcc074ea252f0fd9247fb60b7cce22116d4d4223ab051c077ce12de30b15307181affc93317424a212fb2ad01698489f6b3d8ac8a142ad054e22e6f4e039d87fa859e0a7fcfb5643720b9fec17080b9c89667eaacc0f335957e0cfb4828690e3c72d215e202b3051272572471d35e7982af049bba773da1646125181cbde6ead8af9030a0b05b5059a02921498fab795b6caaa19341405367e8eac82d87dfa8d5619080a7cd414636e36c9a178f813168f71dc63eedc09dce6ce95721cd216b3a509ac0756bb1dc5e49e9d66026fa11ea1a72d2fba5c02af2e759bc3e2a8888712b8acd192a54bfb417d30097cec2ab669dbf2a78b04ae23e5cfc89bd53e6947e0525aba8cc00689a9515a5d3af668085404d6a3dcf73ac4cc39bd0cf385037c4044e072730739c412dda0608b2fb82809041a021b56b7f93b640fe347086cfcfad461c8b105cf05814f73cdd9de464b420c084cc89105bf8cff807f29ed8e7208d29d2c27900ff87409e96f17af3fd41ef0a92dd94fc3ab343d78c0e4b11ce610a364c60a0c0476c0c792f387398ef17733ae03de827ac7ec38ce1cb39203ae925d264fd36d173f1cf0d17244b3c73b594d764037e0f2fdc4f420741bb0796e69a123bd065c879419c13a9418834a03366a8e83befcb1860e429a01933bf6a88398b70cb8b0c9ea75d2bd69121728068c5f8ca9a3068b60c04a6df8c7397ccf71947b055f9635788e95524a7063405cc1fe7938213fe87a5dddc8c84002b8405ac17ee84a3a799233b82801ea80b082cbd2db6dd7b166f1cf2a989c2ab7f3a474dc9d57051fc46334a95495c8a4e2a83aeeb8e1b7a382dbe89837a7e3b8ae7e0a264ea5d8595542cab74d71f428c64f9363e6a458a5d8df6a2ca60c0984142403328a14053b62ee5639aba1e0fa92e5a0627c0b21a8a0c04a2bd7231b8fbe136d817c82eb94932677f38f90739e6082bdbe670e2b27dbad137cd6e6987a226a24ad38c1a5a9f6ffbca14db02946f1a0593139209a609358cee9e328472f9a93094ea53dbb4287470b3d269814db2ee468f51492e5126cf20fd2c7faee761e4bf0e1992da587a13287e94ab01235c3f52c071d7728c1c5d7ab099d4e02c97b1f8bebb892e03f6709e9307987461b093e489734b84814127c9ea85c5fc9adf77d04dbc1a33a67241dc17e9aac93af2467df4723f8d05b438accf04df160045d7b9a3d658b242ff0880359046b39c7328f2afc3f3a456c193950130f42f542b25d748a0824117c99e5eeefa86fba1722f88f3eced1a3b01c82bbfedc5dff5183e98660cc72d0da91466a400ac158471d897bab79b81e42f015e92445c871f4d39d4130de933427858e20b809d2765eff397a318160bc2ff4ff23ad50391e10bc76aca123ddfa07a6a53692546b5e44eb07263a8f78fccf999acf3e309ed9396d47aa18c4e4039b37e53aa6e71ef83843578cb13a3bca0f3d301eeba6ea0b1d218f471ed849269a25d4e5403ac403f781a5fc81475f9b72eec04e6ad4e02731a5aed881d1e4f133796a75e03b7a6cef2a9bb887d1a1adcab55f97b239701e927b11c39388587260d7e2fe44d0a4515ac5819b4a697375648eec8703d3e935dab93624fbdfc0a6bb1b49aef71915377096e6faa1a36e8eb00dec65ad5d30fb78c5233630fea1c774712f3bea680dac4844889ac34c1b2f6ae0554f72693a0d7c1029f1930e926934f0b17f7965ab8eea2242c5017206beac2b34eaa57c621f33b0121e976fbca9bc8d2903179a6df3c67ffba41b32f015bce2a4a4f2d8ca31b0aef7c1f72c96e4efc5c077f4d921e5ab680ef930b09725dd67c941ce610e18d81c126a1525f4c4f205be25236fb0885ebf8b171849fa696b24ba3357bac088e85b9547e5d3172eb09d5f42ccb14ee4b4f616981c62de1d0b397248b616d8c98db9fd773d472959e0bffa72faa7edf68ec502933bf2cde3df16438ebd029f636c6d8b1ebd3b45adc0c4c89e9022744871d32ab0b9d62cc7202515989ceb63c77cb5be2da7c0e7649a28214b29b0135288f49fe6fec8230a5c656e59bda79f7e0714d8ddf0e491997da80f9fc06ece3b81b7adb5e4bf9a3eca36812fcfc9a388fc69553d26b0266da9b652fc8fc55b02d3aa91d1b6b3d332a6042e48ca1e25f645f0cc92c087e3351d7aa890c08e4fe445e53c393a7504ce34b354f6d83202a31e58b97b300bf5a822b07ebd390c75eaafc1220297a472c6b897a287590d81adee5bcb9da5d73f0981730b8fd4427db25928088c7e106d2b59fee86204043e4e1aed393c2e55fd077ca6b10f35afae07711f30b9625afd383d6072fe9843ce69924fcb033ecc3de9a963cd79e70ed8dc716488e0b16f3a74c07db4dc71d23f55793960da0607b64347a6799fd717ec0d5ca5ff2c792cd8a769e6067e2f072155f5a598279583b581b5bb6c9303b3c869b6b1810f7e53133c5ef6a8ec05d6c07a4e79299ac5ba4d7dcbe80aa881bdbd0a71cbbcd353c6d2c0e49c223937672f4fd5d0c0a598b356b2beec0c7c87f6b1e3bf471d3f970033031bf3669a1ce68c905919d81c76f83132701ee24f6d5fec487fc2011b031f420af983fcf3906b17836252e90b037ffb418cf5b137c7d08161898ec3ae96d8914a8479b7bde7d0edfa025b9f3be5fc0d9a17d8b8db39af8354b7a176812dc979a382778e23ebb9c09e6b8e830a8fb242dab7c08aaef956eeb5a7e85ae02a8b5ffc30ef9ae64b1658899f7ba3c79f1823050bfc068f2f5aa8abd6745f818b8ec2229d8715f820dad2255e8c91c4a30adcc76158b6caa151819da01d2af2274deb9f4d814b165cc5f753f6d4a40093029ba274e728d6e4ef2c11c1a2c0586a53c99f1f94752814f8e0977773ca1e95c6d69ec06659d84ebc8934c1e2043ec8f464c9bb530e6d6b0237c163ce0bdd3381cd219dc51cfaa310f55802aff539d0948e94709c6e1eb8b6c761b6aaa7b687b4392f2b596e49602c7c2cf6a651bd5aaf6048e03ed774e4df7158d6e4da11d88a1d37c724ba29416246607220ea21fa9ddb33e5820b9fd15bc4f8a288ad08aca587794fdad3c7d685c188c0c7904aa3ff524ef13a8d86c08418cf624e71eb367721f096f91bb2050b029bba2985e5282d32994060e2a9ea4dc574efb0c37ec0c41cfde65297b0201df3017fe741e6ba18faa32911c1603d60739c25e4cfb7798387f180eb6439f2b55def38d11ad80eb8eb69e98fba9ce9804f59fd63771ded1c8e96838389e520451cecd7c943f4ec0dc89ce3b4cb91794808cc0649cc9167e7f0bc950f580d923a499390d180148b6ce95a216d1ea61d48bcb475761de26fc666c064aacef1338b5b45330726032e7fc7fcfeb8bfd67532580cd8fce19feb8726e56f210603ce83b879b173cc4835d42b78c9da19252f347baca4a15cc19b65dab1542e7aa7562bd8c9da71dc6aabf2f68a156cecb842d417d70b2ffabe50abe03d332333cb5f2f942af8514ff9514bb22a15acfdefa60e721433df4705531562c4b4ea9d72903c05bbf79a63a48ba66033a3693291d49d1fa44ac176e569d9644b396287144c7ec5b5d3eab6942ea360ad2648485fab28b820e26a7e7b71a042c1dfa44eb12daee8550e144c48e93fa305c9270889e9418e52cb924ccd16735ad66ad7137c94e891abdf5483ea04af5162dc4f95e6445e9deb2e44886d826bed382457ee9ee690d2043b31e40e428e9d4cf0df313305c9794cb011ed3b7d56e219f14bf0e18636dd8e2b5156b104a341f3a4abd7a7d46825d8942ce657d987f92b4a7076ed418aaaddac21a7a58f82052fc98824b80a31dc3222ad365b1509d672189da34f6dd341c78d0a1812fc4753176e1a4f53c247f0215aa76095d287acb412ca11ec4796f6524a5289508de07245cbcbd17a18c15b9288d28cf2e4a1bd50a845301de88be998ba7b7b10a008de62da5823798301265422f8fb4d6d1b4c63f2c85a150a11bc7d65e6d68b9f9b3653a843f06186851ceb86e063f4e8641dd5b35db9842a04b711f726ca2b6aaa1c02b408c14dfeb753cf4a6a1fba46a84130adc9235279a0174345105c48880e3faa0f2a76f431840a04973a6ed671be0aad1023238616422840f0fb6184accbfcd184fa03133b6f75ea4829b11541175c7421022e662061e00b6f2f4a10438be302e507aef7b6849134a31e507de03fe67a8c929572947580e2039736453f77f6e64c933d3031c5cdca8f2b3df01f4a76e532b1913611055579e0c2ca7a2ae55af9a7ef048507c6d5e385d0c922e409cda83b70531d87ea1511428d47d981bd4e698face3a896993a30e225da1b6a752ca7d081f1f03c5448e6e8ddef39f01322ddb56e85b9bb72e0fb27783a49691cf8bb24314a6a120ebc6fd20e6348d91b188f7eef501a5ab3a3dcc04f587ae574543127d5063e568485b0c9d2dc101bd8095937eb725a0317377f6cb1c2ed63aa06b6eec3fda41e5140a581f11cfb77544e9e9a0f834203f7a75521647eca95fa0ca4680df138f2f4282a06dfcfedffc9393330d522551f5e249d94920d55063eebdf674e9af227cd2d188a0cace6797abe5bacd059d518d82c2152a24555db5062602c3f88cc6d37b679f9360d20541506de2ee4cb61473e59db0203dbaf2a39fbdaf5055e720e4c63d4aabcc06a6ad4ec944aed3d2709d505363f0e9359b63c8c242e70bb9373ce1eba72ca879194b9053e9ee6b1cc315ad9335280a487d2021f7ac77bbfdca134ef2cf016573a77c7103554120b5cfec0cd74732821abe40aac787e475449b963cfb1023f1e27b65bfa9c737daac0874c3142b742052ef57853e03be838ceee289202372a2a11ea3a6349260aec5bd4f18b1c50e0d6b3c34deb717a079fc095c7af129af73fcc9cc0648bd1722cbf31957413f870a5e28771254877cb04ceed235967bd943dca1278cdb5b1e3f84395c04fca1572591493c07eb0315f0b93c89203097cf4b1f27d7497e33875476072afeebf685999a78cc0e43046f309a12a027ff13f56b43411813b314f579ac78d410d010f72acba3e42a83c0e839084ec1b53ee5d0723e90433b6b02b1410f81a9f56c93942b444eb076c44f2acedee0fb5bfb7987122e8e28bc6005941f9808f73aa8a1f73f4caabea81f93bbdf54716e701272ed2ab1ded0ef8b83a74b490a00eb89decb01c709b135df92f5bff3738607af2fb454f6c3cfc1bf0a12db6e40eda80b5d35d8fea9e9bbb5203c637b333feda6e7e2c0db8dc0dd123de6f6466c0c4a90e22cc3c6bc8910117b77348ffd1c52f47c6809198c226060b96275a30606a3bbca81b8f5770992a738578314db6cf154ce5edb8f3a51b9b94b4828befa669f2f346318d15844a40ab2055f0bf21e27d5c16a2a40211c042c6175e3880527118205454a1531899828f5e42f03e099ab9a314dca5be3deff28c2958a4e0442c04fb48fba21a8c028d828f6e9ed365845c59d287a440a2606bbdbfeed7fa0385824ffd29e8c79d452b3c8e0f040a3e3bf26065962aa4f43f419e6042d4d66ecf39ecc5dd037582eb919cd27bfb69cc4138c176e7d4c72aa14db0b1d3efdb875c2a129126584b1b528ad95fa44cb03f962247ff1f3d5b5a036182af5429657fbebda04bb0ef933b92c3bce3e593257893ce928bd0a8a45085f27824100904e2601c46414c721f73130800182c288d46428168248e747d1e140004522c1a3c342a1a1e2616101812140f44016128140c8602c13020140c0343c1b0404020eaa07cf2cdb1e36203f813c3de3996eb261d7ba03988f65daba5415ac7309a1cbbb53e1ccf24af984892e28bd2bd81a83c43302efb50865e1eb751907b48fba9e3ccbf0c1fec0cedd9d0ea3054529cf2272947349fa71ecfa108761e8529f6ebf5913097f7f1b444a1d8ac5847961408c3650bcc215cf4de721271cbdbe93a5bc45fc6bcc99b9bbb01e190ac368f6e7f6cab7143178dcf8da5346537719bb90264e98677dbcc8989fab2b497185428977fdcbcc88d178cc54921f2ce43419817aec350de4b6d6b639e4f49a4de4ac901bc4b67b62223cfc758a4aa373646cccd3f60a310dd8d5b141b73910921c45a8ace8f152ff4e396a3469228f46dc289b8dc1559aa9a29a413b4a394d50e98599d3e67d91039a5b80baddcf86c19a1825be8b4b2a4341b18859a913bee7a0bc82435eb4719a1710873a86ce199adc9792669ad9c035d5cc9019c0eb73eb95850d899e4d7123e81aadb6e9967016a91fbaa14e677602a06f05ee5e7dd75be5ab12b6a1b9fd76ce6184d4dc6acb1503b41754d661ad73b9af2965b00efc9d71f4a1913b3f065d9bdc77cd6c651dc5b3a146288d0698f8c7748ec4eaf68e7c0af30f71a97f02903231d93170b9f212f2477f87c9f017fce5e2293d1e264062e1b5664a62d63dcdb42d97eda47d44fe32ae8408130c866779cd82a46e32b1420722f62234775666d2ed0647e405614db73d0541f0a5f4c273f71f34407eb0e4046570629aa912ce4321f29a10b6121a86790d1215b4cd538542fb3255a76e4ab35f5273f052e1383222464eb435e407d0f88e90988a2ac0a65cec823f398592cdaddb2055ef7c21268fdcdef345257f112977fa513314faac5dd27636fda71a142d9e9409e54b04ea3c9a6b3231d8ad7a4a9c6ed3f1e672cc05422274df5e1fbd5da0e5c16978bdf5ab0715b11b58d2a3d41d20d3f3ac3b9d191ce62889065d22ce1ba3ce8e63af6a3be36d5ac6702c84b675f4ba56a77690fef264cb038cb9374d92908b0d5a1305048c5a28fc0689b744af10385dded6cefdef0c17455f5a45b351fe6a2df7ecfcdc0f831079e40e9433b69e7661a23dbd0fca9df94caa9a4b72f2d63ed343ad702ae261f6b2a10c69e322961f487fbf815553cc289ea51d441b67571a9b87201d869e7a823d8acdea099a00aafd8b40d925604c99794576d5e1e7483ea7dd07f93114ee0beb189164433d3930151b82fc9dd428397816d6c8fa39262399e2457b5cbd98b1bcb6ecfacc3423695d5cbc7570ad4a4b933967f8421cd53328d1ff908420e3c32dca474a8b432b6ad59d8e4d0600ad5e009e1d080c2c6cc5c5e399f3789f26df418c0c3263cd5bcf1f7acfe8d08a2f00e9ea5a35212f38227d1cea24f511f14a0440a0356ced3b2ea2c09ad4084c0e70d55ec642ba70edc676af39deb1f7868891de5c68d1e55f79d84b0fc1413cab8581a8f13ef8f16476d4145ef5636e31aea6cec40434b9bb331ed941bf04dcec8613868eac753c316b0db302918665808e6e1959533dc9e0a51fa0a6456a58a4a4fc5c6e70c9cd7e345eb819e113068e8d97d04a71c21d7e1d6eca26ea7de34e4672e929007b80ec184ac447668a4236c94afd068a6690ca66eceba90e62519af45bb513a4bd7f1c8e0632c8063c0f9138d8d111acc94e2bd4c06db4dcafbd844480c1f89e18b2bb70b8f1178f870b82a1099f0a3fa3b082e80af977b4c914d0d511e99442c3dcb14fb30f64d9119d852f8e8a9923834663082864ff4bfd8a38063d9dd2cd06cad1a050d7432d8b1558343059d99014d66e40b4795d54fabd8faafe7fd138ae98ff1b62bad29de7f5e2cb0dbae3ec5559e1b470cd5312ea59dcc331af14815127a397eb5641e36f4d38e441151ca2b458fb657e16629d0f4663eada38fffd37d144049d8f417a1bd157139c9c5b1aaf03f53a899575f029218e3b696911e0697ee9a58c335089e3e6a923f2a26a8805cf6daf014ea2672a234aa8b325855aa1ef4e274637ad7483643efbbe2dac0fdc1d02390e62a1acc238e83da6589b02fb1a0d3487563314970c1776efa4b271192fca7ce2e8791024673db82223765a51313f0a918f91a51a77706704b51931006d140fdc744c3262b00c1209eaafca20851b54778daee61cc88461ee872963cba644c537304502f80bc8c301a60a7af9a331c3c63765864ae0824740bade94452d706fe60bc3ead9bf595617812fd99b66f570ec37f62b8cd6885ee70e6cd09a42d54bda930ff9f765a0fb5398baf1aa92b00f63fd011c3b1374d618e64bfbf297692fcc29325ada3215968bea2ff591aa1d347afacc6da39238a15897490371125e40051ea7c524718062f0f02abb97a24fb923c818b1cdd865f22b2ea0b4fa36d1a823722b2f722e0acaad0e03236048216526a777e6c994db330e4610e8613a9b1c2e35e22f9414e0a536c44c860f03df8999021aa5ea8374c7c198392074a085e1dc9b55e1174ef144d8e06225c14dda309db2014591291cdc2240f06854ca5c955651d2c42f0392705d2d45d989f966d2583053c420658ce4a77cd320fb83f2d421664763968af5f36adfd0e05c54b8b15a80d3b072dc368b1105dbb8119d7a880813caa8930416a4f85db91bd927a9a31e6ce8d74f88bf4496cee8fcf351d066395b0464403cfd394274e3b192f08f781b89647b40b8303bdcc0122c7caf2423f32873e7d0fed35ba36939cb903a6d47795a88836104735f2d42b26c50a71e1baf2886ba2b388b8e1618058cbf64630de7d9fb910676afc24dd5ff3728422b1d96a44ce935569431b2ef5f0d674314cbcd9961d998ff6f697d7aa959cd02406012866b63a81ef468a420a050d13b21e2b98935db6697f1592ed3f511668eaf98abd09fa16471392c29f85a823a7743a7be343c1b6d0630c0ca730a99b54221df5fc758aca2979454a75846b20e9c6aee9cdd53a68c3381718a7e47488964125c87727c907dd1fc2a4ce5f20ef2af931f1d15a002461a3de26c92dcb3dc26e3971b4cdead392378be78b4498c941d864cfcff481e7c7d5f491093d9092cb0b00eef777070c1d3927a738c17a280af858ad63a8827fc7a7fd4b7a3e5a2a0dfcc4e8fbc7a57d8ca433d4f7305791205d13572177b01e3c1e738ab25d30ec1140db57c3a1e49a06d7718a5b193402feb69b5dda5159d22c2012e3a10f21d39ce6000acc3b7ddbad10779b32338f92789c790c868b03429ed1bf8fa14cb1f5f62d6296b5013d4b6d9f96118ee4a9afc2295a8980385ce5fbfe72541e06e3de475025dfc73b3cd11281ab2bb237cbde884b76f84183d823c927920238724d8d048803adb332eb8ce4a3f6404ac1c52fc1bbfcb933bfc31c0bb3cf81fc30079873a3475bf518de50411633ff94675c93d794ecd4289846f96f5fb7422c8dee710834b65f89f45a6895a565b8358244dabacfad2019d90f3e4a237d63e1bfc21ec358e11c1345c744913dde614a4e052d3316727ccbdba821a4ce84dd1f1981eacb1444fd8d6692ac3e2e5602ab6e50b081432f30ac86dac657e6b98da6e4002e830db0e111cfc7b9f22a04cfc19b70012928d186c517bf5f355d21ccd28872fa6ab05a204fb74b8f967a962f464deb2609b1b6e0c651e822c7cf9d0f91815a2a03f07a6f425e36e72a5a8585955685a26bba577e4c2fac1d38a0d6223cdcc5a17126f92679e7a47d6797c44b8a9c99531abd5561cc947c0db1b8141c0b89ca5d22a1acfc442cbd2c3d2363ed1d703f443281c96c96dbc0e8628f2b489adda89a3609d401161472a94c1810cfe82634723cb744a063ce9c0b66c9a0d7ef4e26dcae0a8e9aefff143db0e149b5dfdb6b248603e6ae0aee57e47720a77a3f28de98ed19992a28faeacc5919c3edba34a2f0b58202d2e6986c0c8d567b4149d61d2ef5cfb68e213c5d306f6fb4619cf87d5f99ace70fd28026c52c79fa8d6148c8eaa8314ad9ae46ec6611cc40ac6ec3023fddc932c3d387c191f7eaec2a61174bca56083d980191f4bdde1edb86ddc4891c2c2154632e1862df5a4b3f19629dd5344b0d2e0b14a6ca106473870d87017e5c21e791cef5bb82b101669e2b3c0a92440c41701ee378c2ede02b5dc120c799c6b35612a174379538bc7513953933ed7baacf77db4c88b0ced3c9c6cb06e6dd8c811f2310f08d761bdedc1acecc4c1b1c4056830a24337dd9b46dfc89c51e52c8c69cbf26efd2a000486bb4a40e9fb40ccdbae4ce94e168aab512a0f578ff421ad60a08e2ca775fe598f582d4e727a1cf6233a5bb8b20ffecf601220f7e3cb6a394a0b526e0202a44eecf8c31c7ead4e0ebe7ba719b21716fe0b20755f3706df507ec8360baaaa1459f55d34c87a60f0b2cf08bb3f906e9dbc393c1966d33873aff1a74c521d77513fcdfd1518dd31097dd25e00ce21b83dba07b48d2edcfd8c3d38f4979b61a68e89936527088d10cb4a7970450d9f80009729cd0434f56b08b47ddeb128c4068025704fb0978127063411483df10682060ae27da27bf4e4ea0017de723506a4152ebdabfb8af13853725dbacc062e84b137f707aba58f24e1c62fd9de9f4ae4ab81654f82121d5f1c581f96d943c39ac13ce513ab81b5a69bc6015a0a0acdd109de4651d45b220130fbd93253bf3ff90c52bdbba1853ee4569906916a325bbdfaa90a43a527cea257a187e7ca7565eb1601bf79a41251882377c8956e653048a0580352fd9bcc553da0ffe070d854771d306c81854e6e4736240724a6c7e3e82b14f1b9cfd87ccb4965f3ff8eb4bc0e8a3bf1d829087360343167cd9946391d02e8baec3f4adb718754a4155c520360fcca4f9db1c5a38393144cce0d8cefdb3ca1823fce4311433a48d849a533fc11d6dc1bd0d93ed1445cef95b1fa390f1f4c50da9f909499483e61ef0932ae1abd4966cf805597fb284ab487791528e0f41f0655f8519df190c4db9b56326ac62feeed85764400b0f40332be62e3499cfb60b33ead6f06a929b4362d8e7e32ca48cd75d860d6b6d9dabba9121f45808034cb8a02f0b767ceced61d4d5fe69199d78c9c1130f676f3044e95b0238511832996e2a32ca75a0a4d4827a8a1e44ca8cca42693c54194a593a2b865c2bbe59448369e82893569023bd89e44f15ef9531a1e5ac841e65d04f545bc114a7a84a031bc2e79edaa029865a3c797a778f79b5d13fcb93dd761624b39cbd684e2186b37684b4eb59baff1536c60e25258194aafe28bfe48d80063b156d2420593674d0343507598ef19c47584d2b68a5f07594f4105e19543d1e8c8e7289115acbc30279974b7d1785dec06ea33bcfc1cadd9c26afe23d670ec7a21bacde8ae0d9036bb896dd782efbde10c61729dc791de48586eed16e33755409e419b70b37a2b76691f1911d47be20f91d8bde308b3b62cf7a5089a01fca6ffa8f222c24bb2800cd9dc81095498c22f62ef6ec1dd22ee5f6f786b19fb877b567efd0bb14db8d9bc40eb19b608b0ad56c4b9549c8ea553fcb60a7223df41bcd38455fd5ed454af26d103526f0d4337488ba283dba862b0415ede40db42c29658ee73d0a5509536217518d604590a3072b6d3addd6f6f89345172098547b64e141d231a663837dab537b4f8a6d0184491e8f7b3e8a74e7da549a63f7a0f0e0253245e355ef891fa7d9212302d41bf8c75a8011eceb5a827e53c0ff6b782134c5d47d3f35c7d4b6a778aae084cca96732b5fadd5b3408801de52cf02a0057c5619ab06111df936484afbd192a537f4d03d87f0f03a83dba5cf490460da26d88b3b9fcde68da611f5f8deeddca0870bf0fbc73b884849c29f86514bab08064ed54f24df57c43289d4dd9101ba72a47aba7a3fbab705023e857bc6a445567d2de401e56e880d2e33171c0be7b55a12b6773d86394873dbd32850c584ccbcfb4309d247f50e400849306150b4dc58336c436c98d2b07f8bf78df1996998015fa3181ba6c40c38ad9f61ab4c08eec5a0e210090f9a23259a4cea55ef4c397b6679cb689b73ba8040690b473f2461bc218d582afa6b8b884d0783c0970bf524b4767e09e240ea49f3124aa82bfe232ad98cb655dc201346165344e27f12e5cf60cbc856913213bd44e51a3e950e6b5daec25edfcf42ce8de22a18754fec05efcee94f026bb8bf8b9fbe2911e568586d73d6fba54dc2ee490f60c0dd466785ac31a947c86d21552e96a496eb8a21eea37780a0f3da57230e5505d7639db0065a33c811b33ba3cf55fe3346d7dd240b3669a3dd92076c180926dd860689ebc87cee31021746fa2e2beafa94d2dd9a0197da10e4ddd6f39945ca4ec6c579166b67cc97c90a37dc2a5027bf477f061851a9832b9e1782253f213e14da4a8b2d19eb564374ecce2983af85bc1f17a9c58f05ec7c6de59c8ff5d1aef7ec120b1400d13b66b71082e138e2a13b311cf49161758515a6c5c5ad085a1b2509f92288134edabdb01758368847f33c97cda82b0dbbabe691569d1386b13fc95a95517a3d33d482914e1a87e8e971fb3ed20090951e97bb02f25114d2747c33a4b5e33af88995e7d458d8d66259ad8e4697b098679cc368eec48bee8e08838ab342edf69a15791c115a140060c673d4df3dda44c59f905b83b46b72d7b6845f37f82fc52e921a21abae8875f824142f455e21d3693636964c2b6451b620c43e47fc11451b4772159786a9c4109d39059f35e2d3974b5a7602e1fd25bf33090b928104e5307b5786d3ab73f3dd4a3efb377bc64898062ad8f15c4c31a3f30a374e5ba8911bd8a0ce429e4ca73aeb9876cc366292f74035189d8982c920a04e415975e8f6365f5196204d1096ed8355e0a3f4bec795e961a5429ed47beb70f6327fbd5be641f8e162f87c31e3a29ebaf1098243786e5940ce2776cb83006911aae69fe807bdfcac108f6dd0e4bccd37b95d614ab8740694c0968d0ad9a3c6917c2a26b6ab58d0e271cb04c23adae4bb58745057620c9fbd8f69cbe997397f9607241f2cfe3eef7902690c6fa77e1efa2c5d1d00fcde4f5a6fa57bac54a2b6d9054081e48763a84a14132531ee747949f95568d304ab5d234b0d1351849506d5c445ae589384d2a832437e11d7b129154578117339edebf9c8b0abd1b999d5bfcb742265683b4b9cde02bcb82c2d9560d6792d99d5bcf1a1c24d9f2f2a524631b02a8e23ec2d570b2031d5c3f5e2b6813cf0e2610b0cb67d17954f5845730cbdbc2aacc933a430854c5ee4d04a259ea36983d3c8c531c8049f3107040969c3f99db999082db86b7e45f5ceba337393569b6de994bd1128ef3d3d3589c2c15bbba7e2602d5057d9e70075438dacfd203b3ecf235a8518416eedb7946cd3f2c1773f4792264e7fab9139e9f5b7b609b68d53b6b637831506beb659824140154eece0efd13fa02f790a19f4b2fa65612859d3c213d50e2e8eb2db839811e20d9dcd1e5ce2489c7177f265943d2c15d3987542424e1da8a45606a86ecc0441670011712630fdc3fa7cca2a951cc6819da05916236c78c5772c29539c2010865a7468eb63bdba52904c065c0edd9adefaf65f15e755ffeae3a12e706d42d0e371874c1fef8d21942e7a0d37ed8553976821b6668fa5b4136caf77036f30856b9615b7571677d8dcf1ac3008a605d5b4e8cd0f9153400c3e31551ba0414a7d49d0997bdb9df4413ca586a89b673a6327f55cc6b5848289b7297d21aed8849564e8ff8544992779541b89599fc287fffec52364f0dd8f927693d0748b25a74a0c034410038977008e8401cd369967755a747713ea8ba26368cd8e223602378755757ec3bb1b9f56a933edd130c73f4f11dee373ae82409c1cef937c1cd080e1c326e4c4838a0ce49bcc71c879098e90d2e95ac39be8129ddbc0ac0f1aa31822dd8bdcc8632cc9d9943b2d8e8624c4008ffe565d0d584e378e637602ec268cadc8d6408515ad15240cec75e253ff53c8e7a5c70e092b0113d788628d66d0136fb430470c943835e061b4e865c1677d9e1ad2be0ac7354487e2e7eec5070e3778988315ca02590762c814db2b273742a84638a73f0459fe24ab289321a05c93eac64d65ff3536cbff66899ec43a81e080c0acbbc114d7414953db6083c1b0b006fca3453c03d03b89a0af33f0fc28436b3b4e33977e23fbf3322c6a939bce512e555e4821ef61aaa946bb33cd1a746e64ce9b910e594bb0b578e0571d5c63db0e8503e5efffe102221bc219cfc4be2f25411d3ecbcaeccf8c34a0c97111d89ca1c2c2b865aa18e71ea04957f7caed9fc4a92c9324568bc27707444153fba68bfe981d4311be0254185ffade440d93dcb2a50168859bc3365258fb31e275f8ff99257d5e903a822b12c963ab6b2148232fafff35ac7e3acff2192e95d8aa4c144c606f2862884f7fc6123a2b997794df98f1608335a5cf635e9a669b6aab023242e5f432b709822b542e6028347de19383f6b1098dd6a0071005715886abe00bf319abfc79b87e4474c69c35041d58815105e477483aae9a49d37714a8fdf81e2d463e0419a9df50211a7499126bad287c23e80c4003f120ac41d8f21ac17dd94990234de1e43ad28899a8837da3638eb1c937b0e35cd618c2808ff702d2319879ad980dbfdf110e4df37ceb257b99a769b5e5629ac52347ac0632353d25adcd0ead6fe9077a390af20a5e451b1f4916a0f51e328f8573ca98b63c86d9cd88141f8efacc78dc4c77e5aecf799f8e39c3e41e0489be672a7d5ae585ed0148759c89b8cec9c222910a1c44a0dea3dd0495fc7cf765b9c28d102d0719dafb6079ba36d1867882b8c899c6749e0afc9542f4d4656fab531974c7867bad5d6adfa250ecd4d826a0058c73e1276f6ff023c094ea2e1e47f0cbcc54e81a2f304d75bde5d2d5fefaa928a06faa114cdb7253307c503c50cde8bbf9eed8141d1058c0a936bfa2171d149eaab0fbca2f371c9a0d241b928d541a684baf8c3e2d4a942bb5c2f3fa5ac620e9725088130c7ac4315a05ea82c36aac1f64d65112427b5b8a21fb233d12aaf82d4459288c354601d5fdf38ec72c3d602736e0235a273da40c67aa371e3411c388bd6714fd18c3b97066b851fcf90b566b64f1ca976b725b903f0ef0063127f281f24f07050703d682d901474b5411e8564953c4082507d427ddf2df8e3d2bcf8c552a383c22e4061f083a5a983bf9fa1ee8a777d6579f4659b17762c2844ad140528ba27a737bf393c1a755c931c111ab34384943dbec967a282a19fb5e3f4f5cd5454e4db7cee10d9a491952a18f3a4c3cafaead3d52449ebb34039b45a0f04ff76ae4e0295b31e01da7ba4e1a748bce51618c3e349f4e96d64a641910bf845955f92d231d331cf229d7c0a84a05f12346ee5966c85aec3bbbce73888d145e65e4c7a5756a34ecbac3972de26fa4254b0f9d08e2850337a3cb5e77c1fb5c6728005cc87653462a5996ed93d6462f84d36315579d98d1bbafae3c09af6b2b8805891e3c832eb964188734610eb59ceec1266efab71623954c294e569d358d7d91e587611e4ffe7cb7d948521eedf7113b361f3283c75cfcfdc1dd2194c322a5c213c816cba08d5657c6992ffa6faeacecf0d7ecb437104fd08b655305c0d5a17c69870de6d2b1c526f05583e4d01580e176abc43fbe453c454c511310605d42670dd439180210130c6077f8e0ccf3251fc82ba3418222362360b7fd7049e09683dba978f45dce7844a885d555e46494b989639eec82ac2951cc165d55411ed37c78178233397ba3649f175e955e6c3315add70708445e430adde5cd5fb1acbdd12dc73e5e1f8f628361f749ac2bc729e9a26c229720e3dd927554613d48c5c7b0d7a83f9d6013c77cc799f145f1220a6eee63349409534d015ddcc8a793f67621176f575881c98f540b23d1387bcd10df0923250e53836a542bd287a7cb1d722da55a5e479e93645dbd9d7e9ddd131bd2788d658b405b887ff177a1f82ef3d3277e141bb05d7b5314e7eb13bd235732eed451a5c84217fb759c8c8c1a54d659b98c1f218100b5d68c403631cb05dc4db536802450a48b5770b0031a19551b2fba68ba105a897b9572a75e15178703d406f56552f99c288f68c43883bfcb00efd55938af14c65baa02d040c8214586081adc69821ce2d55181c068a82ca0f456e101ab3e931cd72ab6d93b9397a30d72fccd54855d9f83a1b422f0c01385e6c832bb87a8a9a8a74179ea5ad4ee4a01f1178dedf808360f0b4c6b6028ea1a423dcc42f599a27421837fa83b04551c29602c4e244a15a12540c13758df4c1f6f7f127457f932e771b26c345fd882a9e631f977ab28ef399d34fd796151de28da83a02b5d51e473514e8a2503c67ac4d72a276cee39ad6d650ea52410c48ea561ec1a547ce1d73bedaa2a58fc627ebd83b9f254ded057a5d497843f77349fcbdf608722fe2bee7ee4a2c5a9e19eeec49a44374ba3ddb632e677a1e50ed2fdee202c945e36b75178da7b73ba6e585bc42fc01a1a97675bf241f718f1e6e21242fd25ffa7a0c4098ca86c7c89506465d9dfcbe078d59da708439c619dbc0d1116e0574fa2e2fb39d4f18d79916115b9907bf009e8f811fdcf0462a6111850e18f84c9d50c3c80a1e8c73fe39224106fee133b2e1d59e9c051ae667d500fe2fd22534e5dc6d2a27f25069db667eeffa98b45f11a3c7194169a9e314dbfab7c245ee33e1fca3eab3d6dfd3d7bfbe5bfd29f479f599d20f02f54f980798ea9ded4ff757708a946da14f5753304f9f29c0ce3d5e0f38565b7270943e43e7bf81569a080caf10ac1669ed9642e75a4c19da6358de05f1e7f2f878d9309555fdf30d64b0cccf2a92ed49e623003e9505bad11e6eecd33e7f047fde970972dd3b90ea065ac07441e2a119174be267148c0e314acbe87b47736dfb59ea29f289608d72234d3e71c3dc910fd2a471b4d36ec5cc4043da117ccbd314dc68770c215d95b75fc56f5ac5e446c77b1ec9c6c5ddc86bcadff35fa1052025bf5fd55bf722334cb8a46eb616eadb01eaad5342d0dc290bbbaa378954f22dba6fbbfbc1d76ce44a491a7c556074973bf01c51c2e8caa80b541754ef66e33a8d66b67aa3b95759f62e778d5b9c45dd0975317507a8ee6b8d8bcec58c5deff0a2f9f796bc32ff2a6ade7a364ddbc49457352375e5769f05692be8f396d132c28544dfba9dbbc69eee0c6a3ceb235ccc845775bc8afb6d5e1b4d9e46b8a4d4dd8b5dc7d4a77d6bada3b91eff11a079bc41dc9daade7abc77ecd621f6e31fd2fb5ed57128d2e00e90d3aaac30720cf6bf19f74e50bde7e8f666b317d77014a4579f73e4d16ef38a87eeb9ef029563d7dd6cc57b5e3640b5feeef5c2de3adb878ea18bbad98a1a7ed922c668765d1774a1d76eb6c0d407fbd4bd5137d07d8dd0ed67411f811608e25d9efeaa5b4ad297a8bff0eb0507de7a613348f33abbd9b84012a170efddb6def8f0d6f5037c05efd3fb9a15dcc7e091de55f58eb757b3ded5797199ee79784b4a7bcdaee1e9cd163ac61b915cafab7ad1bbb76e8708a7dbd4955b1b844a4517b5ff14e1e8e070a0273f1dd011409233af1aaddd18f96da35edf5b23f5ce893798bf2b796fb68b672f05f5d6651b6f2b9e1c0db8320448386a820f65792efe5f06acb70214e00ae84595304a788a0f27b742551243b580d02331d1ad25b0dca62c7e2d10e5045bb31835e83346d716a4aee499f812c0173cf1e048461e1c71459e4d286ac2b424ae15a8830f7c27b3a90437fc3c4331f13b62bcc82b37c472bd19be8e507d2f34344089327c2a9e1289503b48368a4b55fe803a9b681666d953497fdf6f685a830e063459490d16e0521ae6699e4d3f06706f77bdfcf34055c5c37f3482b29367b1d17ca3add2d0c42b3ababac2822d49077e79323d866bb148695f0815319182540c326cbb40019c23553a683b44936c172f2742b84da9d32ec753cc6c776bca3487007b190edd78b026380b949b04b544c1cda4bf707b1a542a3919fb68d33d21cdb5b718d1ef935af6564b3a313f0c7dd1723a4ef034ba107465f92bbe1fda2ae0378e8e46ac1fde2789bb4d5823eca0a4421275d962d117633450c85531bea80b4b7c9f108024f42c1e9199240366b629a03202400c2426baf08b30474cdac186c933c6c616bcb05288e74cadd1981233a28a28c9ae611d7df6447748d284d0ede01f3599c23ceb0526189fb2c326fa65d1ef6d3a11ad483d656ae5b1e1180270e0bcd1cbca1acd1925cc565deee5b574bccb1dab4deebd6a448e3f6a33bbe722afb835da29133e39e61b84634dfdd02d982fd671510f3c097fca68a58aa4fd58b3e8dc461be3feaaf51de3879b2dfa4c2cd0181c089c45769d8c2466aa7bf8c051a2d8bb1bda9ee5892c9087b340f9e69832845f81e7440a37ab43c640e23c5e0a007e90514427e54323bb8669bbf0f9a3c013ad0180519145d2914001080ee63a54a530fb8dc9d9235657656451257842cebf8f3e86fd8694df5f4b8621717cdd51e70d5f5335c7637fb2e0aec8644de0404e36e64909b19d32d903dc4dae934278a6c198c89a10ea93c1dd07694bf83d0833ad42c428560c206f83195805ac96d0c0970e66842e06720502d426e349cf00b8b4e943d790a5aa8bbe84e5577e5288b0842708b04f831988ae2bf918503d83651779be604042039ddafc086fadb602fec504090c2f40b46439f003fc003fc00f00d546486ca4f5dea2943291872a34966a7ba794524a29258d9a5f618fdab7563758d31f050c890ba50bdaa5970c368472a4cc816347f14098ca938cd31910c42432c733f75031eb3469e8e817e81ffa0e21f3e5991f48d2acd4264f59ddb974f481a459713f43c9d0967f363e1074a99176f641b79cf88aee81a0324744c38bd012ab1e0af5b1b464b0e9b871d629d03c90745af114f91a97944e062b1e0842956af16016196c9d76a46163c7197720771062f27f2e470daa33ec40ecb6a05f6baf037945cae8a59bd66c99ad054a8774c996d12c22d5310762cc6d672a1a54a73ee540cafb5a3aa50bb31d1a196c757120aa78cecc2d2a3dfe4c3810ac931261e2de5425cd8e1fa033fa0d041de3971026be2dbb8944dd404a42b8c825cba715d536903a5b4ccb531e196c37cc6003e9b26fee10f6fa6f1b0a740d24399d4d1debf255d540f4f6a4e43be775d8d8a10307193f407b21d03410cf45c5d654a532cab841821a3570dcc071c3061a3a140d0cd0333472d49d6a4d15161d65201b3970d840a39861a6335033e4217aae745c1ee10e1d367494f51d66a4116819f6dab1bad5d3fdd8d82e8d21d62947a78d5132b86b1f3bfa1e72f1e6418c089d8e8118c46f08afa07245fd37524a117ce00366e8283ea851a30b2a06e2c78eaab0e09673ba61e0be633f45cc52af5e3bd3a3c6a4b3acbbb56020e934a1928d96fa05923e1994bee6e097d2a65e206dd820c3fc6dfccb942f03da05924c5e315367cf0572e6f914a6f4ac5b20266d8b265bb1d4eaa95a20accc55e768e65dffcf41b34010a641a8db942e6b778a05c2f59850531b446faef50a4419958416617aae4aa45620c59c938719b13908eb5401dd1bc4af54383c4fdb5e633bd5cbe54429df6cab383729ea1488731523e635533a4b3b41a54078df909ff2254fa3401c594ae62b7a5ca05020f66f7af2687f1eb38f0a037d0249f8860835f11dc425c960eb4ea3d509445db18ca26f25833681a0275bd1e349d19e7f3e823281a4652ab355e6740904551ea6479766e693512510a4e6c6286d49492088d85213d2458a0472697fe6ed6496693632d023106d456a846bb75c443bf57464cfb45406d51fab4184a618c4cd1a7af43abee824dfc0f18235238941ccba39ec37da68ff6f021fe430c815ed3fc7a42f6110df2a3dcde6d4bb9c0c06d1b29a8cff99524cf10706d94d8c145153e6d0f10b82a7f424b43bd6be206aba13ad27568d1a28472f8863e21734ba7f12b9b708c90be2aff6e5cd31f56ad63a84dc0549fdf49a3a999e6006367690ba208d75e62f9dfe2ad6290d3476a48102cc5cb8a24dd6c5f77141b48fd1ca6e4f6e32fd16e49c63ca417c3b5b90b37c686a4b41e7a0d4b52086986a326161faee4e5a1c35f8eefdcd3c8b62ce61a6ea74f32e8bede56bd6d5755ccbd43d6f3e68e64fc682d829998ca73bf4b452b0205958f65bd22b88c953e756343f5d41f88f31767839a599df6c05413b948d921ebaf3476bd45042b282f8e9978329a5bd348f70ece809b40004385a50a3860f70e4c8b10a82503166ad9ea40a62e5143206b1e184f4945490ffb2cfeba92c17640c2a08c275d5dd4f94a88fc390a720c7fa243fa5a6759694b990a62005fd362a8858b9b47c66214b41ce7ef3659bebc3e38714c4fe70fb2848a79deeb377e69aec884271ad2e75bb2ecdca34ad1dfb5d913114a4caa1d5b2e7808220e593b4501bfa57e4999f20e5a4f72d7b05336d9a43437a82a0f39da95741e6ebbe13c4bdbd38a17644e860d6a851a3061012420c848450738258f731fb687e6c46cd264863d5b677ba2ffec6344190f5a173b2ca4c902d74d43ff9204c103de9670ab364b2d6b904f9f2c7a07aa5640982c6783f7f67a9192d9520eaadbdbfa94bab16a684ab7b6d2936db21eaa5f3e92c934e234323c84910bc36054df94979e5daa69092205667f8e938daba8219099218194329d12a32fd270909095252ad499ab8171f4114151e548c8a5962b53b829431eebea74adae7fb834236821cb64e6d3ba8cdb859a34615921104259f6f4de5466ef8f8224849d5c83b5323db534f4510b48d46d3eda3a5211341361d3b67b8a86b0d890852f670b5f87f7974776dc84310de82de20f425cb908660ef63cf6ae4562dee435b3499a65ccd3d6721c8369a9dd7922c0941f4cea59ac74646093b8d1c04e1c37ff80eb58c95194110e5346f762ce15e0a044966d1cacbba39655f4090cfbf46aaee698d46f30fa4522f723ebde5b9a0fb812052e3c68ac80b5b671fc816c446e68f4c1defe303b1db34c57baff84178f640ee94a9f3c68eae1de3d403492651b27193f2f0981815335e8ee381987d76498fb8ef403ed3df9b92b8ef3c253b1066d447dfb01dfeb9ab4396a2baf795dd9917a759d51aa6b2d281346e2553326161addb39701f3776eef965395696ad927220e8471fdd70617ec405d1d071977120a9755caab89d45d130e331070a6e05356ac081982e624ff54030368050061a8933c8375c296a90634a293de07d763ccd0dc45479ee9450ff78db408cb54adbda7d8d1a356a241b089a8492269742caf81e835c03c1ec949870ab133f911a48a7f4adca8476f6f8c61969d8e8c18dd31bc834103e5abb5e5b4ca6530e1a083a5d5fccb4a92eb52683cda4a1e30ca4936b42d6564c11eae39166209a4af16ebef36f68dcc8b1434719bbe38c1b2ec8c10d0e306720cb40b0a4c26baac7b49a3c4192816836efa22aa82043bd1d67dc48830764e41808a284ca4cf7991103d96459ca202e571e3d4f8681e8ade3e999c49b868b196020e720e6c5733e9333970b520bf90592ef664ccbc9644afbf92da41748e9d4a6f352dbd339b30b244d5984322f9da593960bc44db72989921d349e9a5b20250b3a5b5032a65bab520be460b2632619c733ed260be4aaa062874e97c402514ff505ada42d6474f30a441f55eda5de6655565a8160267b3f6ac7d0157f568124347b92af8b97296f5460b3c43ec52a3566e53a4b4e88f6bc7d42cb9c02f92f55c905fd859402c1920cdb1f64d6ac3956a38617320ae498ca3eace949065b0f6e1c1b69e0c851972b82b6152414c8a54de624d355d2fba2b6b1847c02417754c8523b4bc2fb7402e964cc9d797f9a60b09fcf9cc4e74c20a5119d74f4ad7c749c4b20b727ff186aee5402f1ed636f688bcff7d10e641288b5bae18e347000a194914820ee75d4949dfb3c02b97565449385d30884cd31b798fe9d8f226423070e1b682260cb81ba1824f1a04ae9c89a12f71f3156fbecdee22976c320ba58dc6c4a16534b5a4647096ad4c8814e0e1c9c041406f13edc466586898341d20ee73ffa473676e4b8916347e7d8a1031804f5b24c2a5fb6a472f35f104d76eda68b73c9d3bae10b8272abba4f7ac254f47b41d0ce3998e5c5ef9e3c9717e4f4a44f689cd7d66dbb204991c9b53ac76845cf7207a80b8290c1dd2be5cfe7b9823ac05c9433f98d12dab265e0c061ca405c90ec842caddae06edb271d69e4b0a1e3469b8e326eec48e316885b13b62dc89d5a1e573389bea0af0529ccbe27759eeee37fb42026edeae2e16b19f7096660a3e02c08f79b72d0d739a65596461928071adc280ba2bff9b6ce8dcedd07e88cb558903cc38a9814259b53908c1d250549c68e82460261c725c282a0f2d354efa85a9ce7152725fa3e9fbe8f80aef0d2ce643ef5146cc51d2d3372e0f8801939702420ec4056ecf1a965ad73f65a318fd214fee44fc68e92821a35c8d851d0a85103083b6ad438347015248d1fb5edb327bf18a12ac8fbb1a131a754103669d337fb410549dcc46e86cd9c82b06a5f632384d40cb229c8a9a4974a571afe93b614dc99ec7db9a56e5a7dd6c659af8514a4b54f1e5b4c681404cbffbe2c3597621705a9b7c3e383e8aecf78763a8d96d4e442501054122aa7ef9ece2ccb27889d22fda456083d4192bf5277f59d139ec14e10cdcbd3aabf6a3419cb0139414a95e6734cb39ade933641d474b229a9769a20a86439c78c10d6fa5526087315839d7e7b519d8309f2ca8fb8f50a1fa62bbc44666e792e73969a15e484e798f4af328b96207cbe24fcb7f208f57425d0d8b91cd18ebbcb3a3a36479c8a174a10346e9cf0e4e224482767e572527af62c896d984ae2cc7b522ec5284682b4bda1c3ddee7a21a851030608095267fd7d0e13a765001f4152295c43e8ce5d1a7e32d80e0e336cf4e0c6e1d573412a3a821c74ca1c84144f9549acd80882f00f4f0f42870764042966d2a3ab821061a7838b2026d3e3a645a7db075404495b96b20b3d424c0459ed8452d2dddb032282984cc9a54d2b196c27c04310c632cc461bb18ba62683ad8e056d256b0e9ee9acc38cb3206f8c1fbe2b5cbe4559105cc4a5751363419e97ff182d68b4d2c1829869bda34e9ddaff5e418c319d1ccf5629beb98220ef3389d4cd2063ac15a4d3cb58414eed2997297d41855641b84c4ad367d1dc29aa205aa59196d5e43d9c0a726fcca8280ba182f4962eaac742a720e668d234d8fb5c523205513efe53366d4a359582a453a687b689535b2205c1437c5768d02888972ffe8fd2f75d17511035a935f50d2fd50905295e4c2fa92b32950e0a92959c4dedf527485a4d6cb4c69e20e776f8d5f67cfaa29d20beba9690bb4bad1c27083227eaefd904412df7e652314d105c3429f54da5396999205fa878ad973a9820263d1e536c8c49ab752e41badc9fbd848c25c8c9d572c9d5660a329520574cd522ca4e996528418a27db83be5e2861990431d9691765154990f6e2894bda8352a28e04c1a348cbe0516bd40d09d2969213279eacc4fc0882dddce989bbc691df11045de9831637cb7fda6f0429f7df722cf71941708f39f557fef7d45f0441cf7e88f051e3d97c45904545abd5b0495e8f9f0862acdb14e3daeda1840852e9e46341f9e88be910e4906f320431cee7e41b4f58f07c2108a357fff6c3299d79429044e64d1bbf7932fe83205f774a3957ae50b31104a9dc36ed69261044b998a73626ddb60104b142f7fe27fd67fa033975257129ee072f65b9784cf7816049df94de9b0f2499c64c07bd29dc650fe41fcd0b4ace7a20a93d370f861297725493e2816c3986f43842cb7a66ee409af5a0977f3b90d4f5b8a639d58124a3e379b14407f2aec630db0ce6999f0339c7b9a8a1e32835bf1c48c22f677378beba1863e97cf587dcc081f01d83d20b973710335569d695ccc5c50dc4f63a695f9b2c064b1bc8f37331ee92d87d9d0dc4cfa3fe548fa6737d0da4ef6b93d9aa1a8839b7c12ec7301bec3410f3560e95eb294bb56820eab847134a7a78909e8120c469d7e5b598819875e4a664c14efe57ca407ab9d24ee12b64208b985b870e96d35e650ca4984f51a76fa4b655c4400c2a4267514b3d161406f29526d3de4af92fea3e97d20f4289be40ce5f428eb787b7d37b81184c9f9fff794a4ad305922e95c5ff4f9d073117c8f977e64ea7ff52e12d90d7c63ca9b09be35f2d90b2adcef73a69cc6d16c8996fc4e37a0665522c90827fd063bd6d3a46af407cf5d94fe623f3aa5620c8e8f88ffefb23d42a9052dea4695029943ca940caf09a57f79c02e1bc2fcdc25a769b5220ff797acf6929c38f1e05c255f43b2d7b8bf1732810b3b25a786511cbcd9f403639b97a3aaf9bcedc09a43ebb98c6466f0261ec5ceed774909f092459d671f1dec4529640121d457918b957655202399b98ee11d77131ea53fef02081245c2fc6147304d2bac5b01108eb15f36c4c2906b992ac4eba6a71de420cd269f5344ab4cbc6f430084ac3e26c270c622cad619f95ab310e0649e4e2fefa0b0cac42f429f52fc855a5820ef63adfad2fc8e133abc8cda0e3aabd2059aa32a57a362f08a3936aad127b17a478d25c6430517abcd605f96e7365178f317dac7341ec2837f7a793f2f3e08268326387926a5bc2bf0539c8aa68a67a5b10ed4cd7bfcfcd94a616c4179391e1839552a205316809773d4d376dce82a0e9d932a3e96541d2a0c4792719c782944fe78b41ae8b186141f03b195b43b5fb0a62d7eab87509a91bb4eb8a3679aa309d7e2b484a7e8e9bf37ff68b6105d1f3269331b47898cb2a481593c95d564a5b155590e2e8f3d0a9f4c9d153411ecdae29cb4605c93e875032daa3997c0a82cd555bacac29c899642e194f952a9196822c1ab272deae4f5a2505792cc958323457267514a48dada4535cd0b6e48a826095537eb89aac186e2888d739f462e5161424137bf1544c6349bcfd0431d489ce14dd43cec91364bbccba8b712f9ea813a4932fbd65329c20587e5e55f82c1f6336410eb253a7feabbab26882b49a2ac4e75e6f2b9920683b33dba0425def9820fa584eee79c4e5e79720c6c50b15ffb60441cf5b67858f94712b416abf52a61eb3a7922a25c8696bf4de4f25b1a64e82742e6327835b8e6ba924aa341b3cc9b33412c4d6bf4c1b8388d7132488f39d2c5338354a7f1e41d2a3d47ffcec9fad7104b2ac77353ede088206f70af1d123bb2723c899f4c4b3d68b20c851df39a65db55a459044bdb68ba7d76e8920dfa6381627db7f2922c869b2eefbe2865df210e4cd9c62ba3c6af7350439de8f7c10195e55652108d264b55650b2661d42904526bdaad20f82f851b7f4658d20889b646faa58024112a64eaec7fced8f038224933653297cde3eff03f9ab94526b613f9035dccbc6a99231c57d20ebaa7f4aa53bbb593e903367d7a42ea8bc9c7b2006dbf89e643d90948ceeefb3add4661e885194ee381663951d1ec8311fa36536ec738677205c080b2ae9d881984bc6f486a60e64fbf0111bf1ef23a703e14f7e4edf06798bcf8194c462909ff4df4d2d077207f16aba6c3cb41c07727f901be99f729fe040ccd98446b3209a83f60d24bf10623d643cbc75034169aa8fcd987f94da40509596f6dfe19bc30662caa5f3a792b249bd0692f6b7f9b8d92b9fa906824a5aebd62fdf6b990692a6e67a10292a6f4403c9d433952af1ce406ecd98454689ab8d9d1988e71b833e93958198199ff3be2d9b1b19489a5fa6d3f87ee8756320a90f1fd9b97350729d18089b625c8d135739ac0b0349e42769f5f184fa2430903cc6ddcf31285d26f405e2787b9e0f425e20cf9cb0f3d4d1ca5117c8499f7dab67b9e0395c20fa9d572afbb740124df7d142c669d66881604a09cbe9f12c10adf42c5d732c9043f75e73b6de5ff90aa4bcbe19b7a0f2a6a815c85b1f5681dcad26c42553294d5420afc811693987b5a56c0ae47b791d4f9314881e2eb6a8d2890241c6b051cc35c62003058257fc98838ae8a69827105eb35ebacb9fccc609e49c4f8d5213481b4caf7e3d69bc0b13487ef91d57354b20b67db5e7ab537fdf73e2a724902b69dabda60799470279adf793fa7f86cd11086a7492799dd708e44d967490ba79b4520c728625ebda1c3c7a490cb2f5ce9ed0e33008ee2fcabb3d6110c32bf496824130e5315faa97028324638575b42d7f41b892d1a2a5dcf54cc928a82f482a05a5e35c455d737d7bd15cccb8f2826849d7736a53919f71dd057bd71e7b9b63e6032bd0c5a94489f272ec402317868bc263db4cefe4cbd66c4dffffe618bd0541ecc7f8f2259f6ab5da8214efb4e70cfd5e416b41bc94f547b3c5e8fe3c2d527396e459983157b173b1ad177b973d3aa58be1634f5c64b1856b95a959a988957ec6edb88a4c6341ca499c698a413fa8496141ead5242e87783f191b3b500e72e0488776fe0af2563ccb9b94d6a5ae20878bd97d2c08fdca9f6a2b4839a38cd00e9de332489515e45139ff294f5f259e6522741564cd244aa51d154625ad07356aac400438727c20ad0798e3860d3474a4a92ac8b9373b9d584a1d94a6a9209f9fc7f8d8747d99840a62d62d59eb9d34e6844e41fed038ffab9ac53ba6205c766e92d5510e5a0aa2e8bf5cd1b020ce6511282948b132e5912722578f827c26d426f5f3c1f26664b08982f06126324241929f3f86ac650c0a720ed1d9a77142a8ac92c186876ee4d8919f2089bddf749e2d3a3c41d00b23d4c4e63a410c7ac294527f49dee89c20955cd21a73b4c711ca32d228091dbb4d904b657c8a97452b658c26c839f6d9c3c2b7678a6a26887e1d378993c12a7f4931410e9e27729e847a0962d62ebbee58822422376ca80595635a2b41da0f955184ee1cb486942099d8caafd1d286dae4e0868e3b814e8218f24e9accf3bf4b8214642bd6c4856c073f12c450dab4546b4619d3b191781412c49341ca85f250eac67b04b164ce39e7583932d8d21104a5a2358772ad11d7e5d1ffe799716584ad5523662127f316eebe2e826c614b9556a7ec6da21ea03214410a9d3f65d3d8397a84a38c1c9c71230739c05146228896928ea652a6f67cd91fa073c60d1b6926504490535bc7d021df5f9774085297253932658d214c29c9e41943ae85208839dd99f67c44e79010e4b8ae146ed388b0940e822cdaf5847988af65c60a826ceaefda1a93017f68d978548120adc76c73ce983cc650812862639cde8e61a3dc1e53209b36153f684ee59d9692ca99f27a4421cdbccf1915fdd0b11c3da040124ae52cd67208956e8f279054c56b3295dd0944dbe42b9f723c9a40529e2983fd688d32e51c3c9840b8647aa6b205bf64992510a396b053151d5fe3ae04e2d5e8171de4ed91048236a59dcd62ca5979f3400231c920b6dcbd944cf03802d9e295e94eeaa9335369781881ac23dabda39ae44ef56290b265e83771f22da8d507eeff57b4d0518741d28f2f5bab68da4e9b2e0cf2d85a507f353a668748f0603430147f914e9f23772dba3c4d705ff49b2e674273017082f7c26ae0c07961356e17a4da37e1f5fa93c1375c178caee65d99d6ae89bc7b4ee963dda7f8792e482a9adfd66d2abdf9202ec82175e457fdccc468b7207d96514ff24188f8b8db82f8967b2184cc5f972c1d580b62c6a0aa2bfbfc8c5075064e0bf2573c9ddd4bf674e7dccd8274a64344a998bd9305416b1c13eafec1ba4e77b12086f9a80a7a3dfac3098be26d4ad3dd2b08aabd9731464f217c73e70a72b9968789c8ee5a41dc4e953c3c68ee58413cf5d173c7d8574110d777b1e4c54cf3f7f5a0460d55902afb63ca183578a9207ca6d92833f15041de0a17eff7e19d82982b2b2fe6309e2948a15c378c1ecfa6c388570ab2798ae756b7fd3ed639298849e6ab5c956459a9f10c1c67d8d071432f053e0ab2458f27377d9faeca4e14040f4fd22a7575a12085b00f55d14aa970f9030539e710fa1b534e8988c9603bfe09623c254ebce6d19ec13d41ead4902237293d26bb2c837782207432d1bef24ecae504c94fc82b15543bdc5661f04d903d89dd76136dfd5479c13541acd8121953c9f34c56f24c90bd4acc5aae909ac131412af7f0aa4f71cf63e60cbf044168664fa94a8515598ac12d41cc9b5375ae18273f9b64f04aa45382a0692c46a78df9fcfb240842c8e5666bf9bc7a3925844b82d8d59d99428e4c0f51dac1234118addaa3f3f86a798d69704890b7a3f6a57b6966adc344e08f20a9a826177b3263071533d6e18e2056ce6bc1849039f6834e9f0ebb813782148458cdd9a7789b3d7b704690544c2ded39ebce231d86be0892597eb8be9c4b051ba9c11581d649cf7162fee924024f046134fc49ed641592c01141780d3a5a7ab3752d49077e08925ecbeb68feacb636dd10c9bf564e23636ce085209dd4de2e5de153bcfb9d1055bddc79c89197b43976a041041fc45bbaaf3f9bd2665073ec40c30541700ffbb1d33589fcda0c0f443999a7fc1602046e5fa9326ae7da69eab27a1019447afc0fc4af7effbcf5f881a0738c5dab10fb40beb2ec8e11b11e543e10637d9c4ed329a74d7e19be07d2a9cbd822de4456ae5c0fc4f4aef240f0bdb5b4793c5367f0404aeb24c36626dd81e86fe3a7740addb4273b1045f34b3be4d9f99dea4012b75c8be1a203d93395ecd0d19a97990349d6abe6d02de23f2e07b25c75ccca1b83cf1d0752d46d8fe29fa1d3860329584e9d84c86f20a9d4adabb4ed16ad1b48793466d968a5e449db40b0e0e619326503a94c4ebcb5764635d740acf472c24c5403417fc924dd3c94862e06693a8e06e2cb7c979a8f0f3ae8fd0c2971196433be66207fca315fd920747a6520bc69553c15c5faaf2703b95743a8aa2037ba3f066265b58d49566f8ab71808969dcb6a4b13067210975fd5010371bb3f75f3abb28cbe408aee5ba23ae405f205d198be5665ed77817c5266ad820c17c81d5498cc9bf4a9a0d9023145f5f67c580bc40b9d4c8f56f317390b24ed30333a69b1408c9992c9a44aad97ae40ccffd0d2cbf8e361b182212c9c5dbc8b5781b461cb5cfc762a907b37e798694ea5a64f81a04dfc678fbdaa2f92025153c55c4afdc8dd942890848a31e7641528904fe59615556a4f459f40b8b09be2e2677c994e20a5f8398ce95c2c2d7613c86e9d367754261054caaa945f0251c5c2265d8fb2494a20e8092581d4f1fa3fee3112c8d735d2adb3eb47208cfc665d5279b45feb46207bbda9cf894c793b5a0cc2ed8d522a5f07b5192506b1332b3f6c59592e0d83bc59db2a6cd68be1220cd209952153fb6cf2381864ad34aabc030ca22597d139c810afdc2f08be612cbca678cff105297f4ad18467d90b92e9cbffb959f282dcf147a91cca3e9c7641109b44f6c8cdbea6d105c1ea93ce1594e5b44b2e487fa382b820fb26692ae5740b82cc4b9bb5185293c916c43816c32a3e2bcba8164437cd6831644cc1a3b420c6d45232a6a710b5de2cc849db94bce9280b82da4dda634aa7e962170ba255b0202f740c173e2c92ef2943bde8af20ee25eddd90c993d7ae20998c12d6b7c2a46445d6ac20cb96d0187dda2ac8c1f2bdfc25135a3d5305499c5ed22965a9209ca77bc614d4c7b951414ad77cf9a544b6cca720d8788e39a7cfd3b3a6206bba5e4e3257a520c8bf956d8df13da98a14243df22dea92d997aa4641f4eed3105aa2f7ed228af2b6acdadc5eace3433d9bcaa1a55090d365483f5913963cdda020e68c9e39dcec6c92fe274896a9b5d19e20c6264fdbfc3cd96745a13b410c0b29971e7f7382949f49fcaf6e7cd09b2085d2a1b7f671bd5ad604b3592f2faf9b2e2aaf6f898cd4ac726682b4a16abd52cef1934927c004514e45f524ffbe04312e6c4d98702d414a312f7c0e35e2d6ae4a90c46793b86bf19cc4f3018e0e34258e2a2ae78afd397a12ab97c6e688dd78c7184fd4cb2d0952bb09b19231afa7a78bd09120a89cf36f7fbef841a74082e4a9b275764cea47107407e11ed3cd74acb423c816f52abd424f295d3682b01fedb4debc997f8611e437f75251b2baa01741d2dd5839784ca92248192fef29fd9cd7edb8910306356a9c4e04d9e2aafbdbd998ce4d238258b91eb7b6b38720a6df28f770f22ab99f230d1c2c6843102be998f9a57d0f5d08c2854d53393c8bf00b2204b173f014f73feb315bead083207710cd38b2648ffc0f3ae3865941905b4f78aacb4d8e1d3a26f081154ce004d181206ec9146da25d0e52a346c9816e34208e13336b2adbe2a6ff40907e1d5ee1d3089da91441fb81e01a5fed93ae080dbb0f6dcd5c7797657dcdd8669ccf88695b9a0f84bf8b716d2eedf8a8f64098bbf0fe63592eb41ec8997fe921ddf258280d1ea092060f48e581a899e6db3fd56ee4e67820299d61d4c594d2d17720ac86d6aba03734b968056e0772ffc970a6da29e5f31884ae03395426f99af62342d3a1b6605a4554ba760e7c502a670eab17125a0ec4bebee4a2555f695b1cc8ff63e16732e74029848603d1a4881f8bf55811bdc10d849141b7a5e8fbb42143ef361047efdcdb890faa7ba341b3e192a541274fa2a45cd21ab8f33457d793cb96f93465fed9eee9154438683590cec2945eccf1a23e990682f2a45f2363644c6f2cc8c1193772ecd09146a381a493d8b4fbf3995b7dd467205aee60e97aff360341c74bf2e7531853e7e128410eba0c84194d7e229ff97aa6264363dade7167e53632cea69c76b374ea942007ca410e7094d163207f0e63973786b74a4d8b81a0ad964c4e3f1d0682f6125fd7f4f8643718482553faadf0cd17c89db7c17f562f103dec586fa59915d5cda1bb408c97b2ac4f27ada5c2058252b2bf6490a32d10355dd42066bfc9d25a20d6eb9c32137156a5d459488610c202e95c64573688cfad9fbe0279b4688ad3fa512af3b60229889a6b4e198f7b7557812c3ffb75bb518120933c19ddbe140f734f81a8ba1a3f6bd229bf342924b7612d7255a61d3a53fa7c263633bd1d0552c89f4c2a26d54d27289044b54c9697f4d2a12790d42fdb680e9f749c40d013bd29bd6f02416c2ae56926107fc7b2657e9f497d09e4bc37627b5d25903d9dd411b7ec717712c89b3129bd13238164edd69bf3db4720e9faec70aada8458db0844fbb34e333391578b41161563aa69e877391331c8a7e29cc558a6611034dd955229ba299784516eaed798350a0631465febb424b75b040c82a6cae5f9cfda72ce2f889ad2e99cc673d8cffb82f041bba6d3b1518fe90539bf776cb19893bc0c2f48f1c942bafd78ecf82e882766d183cbba2087951f13f95332da5ca4e46e161784f1a0c472465e737b0b8246d3ddd6fd0d4a690ba22621bc2ea5c6e8662d08326797b71cef61262d08673b7e803070460e6ee84080057460009561ca8e34cc58800504a003e548634741c9c6022e00800aa061c00b03787512487c47f77a282001ab715cc322f03b74a491a300010082c1800200b043471a2b204000500e4a1a3938a394810001e8c8813e8d8323071a09300100000000000000023bd0193b74a01d18481c484741c3010b581d37d0280a08c02700a04387a9410001941de5d4284000ca8e7270e4a87100000ce00109c8816cece0cb0e1d366c2c00000168c0018080c6a3016fec3838cc3803ded85106193a8a0d1b0918c30c68c30602c628c301c62003ded891830c1d65d8b0918031c6b003e91003ded8d1831b270d1b36123046188816d69470118d0ceeb334cecc40396cf4e0c6b17190db8e336ea8600c30a061c69b81cc30c0185f20e8dc79d39fc89cceaf1708a73ee5dc271bef63ba0b64994b1f362753157d339019bc63708124c49a6fd64040e3cd4066ac19c80cd471c68d1d65dc48c3d8c881cab8818619389ec7d802397768c6b31cacecc007563001c5c4185ab8f262b372f46ac618592067326d9bf4be6ccef1118c8105763edfda4d4f3635afb5f35cd7cdac538e8b79c1185720c95c5a4ec65cd9308615484a0579425dfa649c51ca48018e510582d4747aa49ece630c2a74a3f9b9b6adaf2aa6962534c69802d93cee8acab11cbba61d40e0c01852283eceeac4e958ba41860ed781060e1b65638c110582aa1653e62f1a030ac45b339533bee51e43378cf104f288fc494f3a7bae99c8602ba31c1a610c2790dcf49ab9566b9a678cd1047218d9d3b1b9a45926c76002f93f7488ddc564b099eb608c251094e672f5afd678f300dda317c0610c2590c49cdf46f7510f6ce8480249a5d116645f38c6400249e84bf5fa0ee618e308e44bda7749b6770ca192c1b6630c239052533369c88c63070b4e50a386192ac3981b677c148394794e5ddc26fd0f70181b3bf852867154c60e93868e3dc10c6c50e0831804cb731bfb339ca71171063e8641cca3f36ea53cdf76b63048a5f3bb3ba6390bf50583ac633a837a348f5a32609037e9b8b1262fe7f8d52fd017d88be305d12b988c9f847eaedceea2b40ef90c1b59af58d37541dad4fc7f49a598a222c881768800e5200732015e0eb4e3060d3e7241ce5a9b5a2cac54460817e458fbef93717fdc22f18e1bad4fd92dcf1fcb243aa9ceb388e0c31624ad171fa488ef9c4e5bb5f8e4586b78eaf8f1410be2596b4aca46d6d73d356a04e16316a856edbfb834c70e34caf89005ebb194de0df12c5ac1472c3e6071bcc85a958bcced9a5e4134d963c2f3c5ae2065f52fcd9cb5561065d49eba911b35b7fa6005af829d1bf990d335af9456e16545679ca361c67fa8821c1e64c95aaa956f2c15e40d5e6a541037c8d1b9449c3e4e9152aa53e5d914a98ebc9ddb7ab97b9669f7eb67cb9a72e8efe6868f5290720e6a6327a1270531ee737c17a5320a82d6f4399fdc5bdd7b51104b27f1a4dbd4342ea1205655f8133eb796930e0a62ca4d7932e73f3e41eebdecb94f79e9670c196c4038f30439c7a3e9649d4ba993a11c3e3a41f8caa1b4f4e864edc90f4e90d3bd46cb87aaecd8c72608fb991d5bf5624e7bf9d004c1f63e8648afd218692648e1a3417b4eda287c60822033df8cca89eef9a44b9092e9cc3949179d4e5996c0dd52fea6f94e06db1937ccc00d7c54826cd94bc89327b4107c5002a143b33c5968b4d828a3dcc72448a7bcfaa266d78b9f5b093e244132a9174bf55d1ef8880471fcb545456b360f2232d8b8031f9020ff952c21fc633a56c70e127c3ce2686e296f9a551b2a7c38e2a311c788fd580429e5735d4df946d59f1f8a305667aeea544d2dc5650ba11d94167c248224fabe4fb73268563e104132b7945f4944a814ef8f439c21ae1056e38310a4946336a535bda74aa7419074109de149853eb59d2048a59982f8abe823101f80209da650b927ad8f3f580d3f10fc84921dc4a898f4693efa6035f860353ef64092a139ede9257de88168f5f9c645e9cc29ab7948eb2e5de33ccfaaf24eaf9227fda50f3c10f76aab4aa86f131f77207c4cc2faa2ad1f76209dcaa4b25d78cd9fd50dc5471d08b316e29376d5581f4407f27ebe2d71154fe2630e049713337e3517a39ee440929babd5152ddd2d1f075296b1b958a247a5a7e1404e62ecf6e2b51f6f2026fbd7f87e354277ee06528aa2efb25b2e9552f7d106821ea135cdd7ca0692c8f4b71e9ac2f1b106625d2e5329cf5c8a22aa819c5310ba54b5f343bf4d0341c7abd3adfa95660e1a489fcf627dac31ab289e8198f4b48dddb6a8ac9d19180b99655c7efb280349a98aafeb759dacd46420c7d9ac9a4176a90cf23110542d699805216ae1430cc4f81f5e4259a792d13bc3471808bac13d4ded52a54a26163ec0407cfdda2edbb1b0bd7f7c81b8bea34bf8756ee80b6ee1c30be43c0b23a3a6743edd1c7e748161f0c1858f2db0e0430b1f59e00f2ca4f17105e2e69ab63b6d41ee345650def3b3eada3e3f5545db543e65f09c8f2a9063877c4ae541bc6d863ea840d41474780a441721c75e3c8408157d488118bf735fa768e2e7b52810454d9f7291660b3ea04050bf79a699f9780277aefbb26297651ee2d6da1783f2ccfc1de1c309e44d152c77877afb68f968024183bd09d7768c0f26240e3e96401e91d916febc73685f09c41621d52ff7ac83d03f9240d4a0e362ce8e955e412410ee4ce858f44e0f1f472067bda074eea9ebe87f101f462027d9f9b1ef4d448f6290ae754f7452970da5e2f02006f1d33586e9cba4b3591968987143479fc06318a4b469423e93c8d0a582d04039d03816780883203298d82453f2e4a943069b8d73460946fdc98312977f040c721ab57e49bbff054145b6b66c967d412acbbf5eb1429856e7d10bab8135f0e04542e325d11d2fc9c8f9051ebbb8e793bcfb67557f051eba40f374c642d4dddee1910b52a5ffe0a9da3705d1e082186ffbaeca32e5bc7b0b7267d18c97f79d3e856c412c7751cffd7baa345f0ba228f1ea13fde915a4b4207b101d57419cd0b1c6591063949d89ac7e859179c88220bad4e5c8a0c74f055d2c882995ced46ee2312a2c08caa4098b13d2f22ebe57103cd3cb3d43e73c5c415e8dd760314aa9cc6f16c1a31504959358f04f6e496ff36045fbbfc92bc5b96f156455d9b6bf96cfd8d5a982a0b1f4f5a83ef152417ed7b09f53389fb71415c4dfec9c63f46cb1a69d8218eefa4e68ec9c41a83c4cc17b65a6a59db8553625aef4681c4d7729c8a63d8aa97ad2a3a6f22005495c37e5d84dd19b725682c72848663d1ef62a03050f519036b869e7a02f8d672714c4142d544ca5336d52a507288817d73475cc6f63e16d82c72788415564cca42ad883f3f004496b924978a7453d3a41f6b9d2246ed473820727eafc2b9e6db4f6d804313745bdd3fedf53b28726cadefdb153d2a426830f356f7864c24ab9a284125f690b3c30a1566cce3bfb27f081154ca0f3e07109b2c655f1b9d936e119a804c88c72821f1413a481050f4bf4c0a3125b94207caef8f3a72fc594a1499c2ffe4207d714ae732441d0a699eee7f247d31f09fdb4fb3bd38951810449e7d89129c8683258ca2388f79d19c5e64437c81dd1c5daabdd65765b7d79e7ec7f41de3e66c68b4723482aea76c8ad476d9311445ddb4ec972fc46d78b207caf7bbaf476f192154116a554543a3bf5bd6c2248dafd728c9fca7d224490e257cee6858fa9510f411e8b99c383ec39a193862068cff0979385356aac39223c0a4154cdfc23bd5c47c61221484287f8242b5e09130f8268e6e94da5c84bf01004496b8ea174ca8dcaa9f408045145548cdc478bd7900720c8415ea520e393b65f0b1e7f2028dde953bf525e0dab871f8841c9a6e0493ece275d0c1e7d20e9a7a926ed0d1964d8830fc4f8f3b9298392b99dd380c71e8816542cfb7dca95cd71e0a10782ee5d586d0a3f56ca03e1c4858b3796c60329b553959081c1e30e045535a5e5fb82ccf9bab303794fc9b0f7acd37b9a3a10740a9584e9fce05ff2143ce840eceaffa43da7c8a0931e73202595732d737c10791d399046779d1ab9216c94e240d698bdf675720f381034a68c59cb2f99b4ebf106b25cca3699a2a653baf3700331ae840ee257b781189a733983ee3cd840ac2e95af4dc7bf51298f3590477e9af533a9871ab4f1ac5ab9d2b890bdefd129f622f74803414ffcf5c85c36163f0f349082ad9cacabee710682852ead7ecf3ccc402a4f1a32ca82d2e92c1e6520a7e7ff36152cc728150f321cc1630ce4a09256ca3978cc24f3d3808718c81f7f514ec8ce120d59083cc24010dae453a8fc98ff520c8e327260e38c1b64ecb8e1033074f3b1f7b2f99d9a21a3997764980c96f43370e44836d874f817481ab43b7aa5663125cd5176d8b88123f0f00231fdcb092927fb2ba7e82865d8d871a30c34747874012f612eda1c3bd0f0e00229e998f94d5a0a3db6401221e641aaa6cd6dc6430b2415af4559b01a3bf0c002b12c7335d9598cfcf415089f1ad393c554e2ceb50249937ec7c5038d29a8e4adc5620269381a8903e290200c6234cb0300531308001048260d85a2c158a0278a2e0f14800265281c32322622221c12101a20120cc6816018100c84c2803018100c0643a1504044932bce07066fef0303c11ff11f9d3889dfb30c4b3f4a3e670479edbc0733577a0c4bd77d5ee85e670879e8d0b770cf16223f7bc053f6b195abc85909870887b294a546888bf39175b7cd72b90f667cdae405902051c8365f4dadb69eea9403f2776c5704abb428ffd6f1c626b596a5e4bcb8b17aa8632e22fe70c1521dfbcfbc3af061037b4f467a220da0af29db8ba8f4a7564c1fa6d9cd901aee26bdd1ba2cc481814c302857da5619568ad7f1e4a2e75a200902f84281f602c92e46d636ebaac596af63c0c1da93cdd924970a4480c6655546a94a93b46a025740141e40b539b62065d686510d178f736baf1a7fc99fda72b77557b9224f50f4af7809f9e9e8d0d28da65a1da0c48cb64829495fbad0e112e280557e307863af2f410bc34b8ba5d2b5d0b1f5e3a96dd9121660e9f24fdfc59752d1424cb5ba63203741de0839dca5ac9a0972342732ab0967eb82b3fdf6e9687ac8dd4ec0276114ba00c5bc11c4327572bb3bd97d8c1a9f692d2698c68d37f4104bbe61c9a7303b3ad6a8f3914a2f25d0f105fa6f664028a01840da1bc71814327c36e8aca0dc813e082e1b555a3af6631a06d16202de3446ad3834666c0acc54128c381352d1cc02bf28a777740e82b418d1270261295e5eafb445276b01c269191be79b82c588e6e6c030f8c1da4cb67e54b6c0b6d07b368beb2d9ee1c1864e2e519d4de8d7ac2043c3604a861fdbdcc18c7b7f5180c9b936bf7df1911822993700952889173d61aa8f1a4d404fe5ab316d8473cd2e058dfe1fb231bd8b52810c976e243bb6cc4ad072988c91762f490cfc361a9958ca01ca611292c5fb5c115b41046422dfc4a246d3d57ff53bdca185b3044c0e7a20dec3d84dd971b2385e9916b654d8c334f8111b270c4bd58d4356fea8202b91709de3c81ef38721cee1730fc4b70daf121d56434cc08452a634c82720616516d2af59247ceebd3e4121b2c2f70d2c190cde740453be5b687183949117cbb135ae85e873aa98d7943107a7184caa1468a68c2df6be6b692823cf98267ea235d193751dc526e9804798dcc1c69b63c9206d5f068714ed37312519bd4771721a00b2215177291abbe7265b850f4d685e6f5042049f1e11846413c40edddb9923a4afcfb0ad89d9112a54fbfdb505339abefffc0bb7bd50c43e4719521aa8b2c2d0f3a2ae370eb8dcf76a1b78108122a1f994b610710cc1d5be206024814541c471b857a16ac0c00ae6baa4160b1f32593cdef769e5d642d45ae76adbb12e788e922062e5826bb7b798d89531413dd1d7b2c08305745560d4f3731d10609a1f60f24b5a140565355b8f38e0945ea476e91b71c99ec9aaa6868b74476f49054c7689ee155d5898f679f7ef830e44fec494928e6d9647069c7cc1f05e340d7adfaab8cf8d38f0f1a812853ee99c88af0f453d57e05d47ecbe2d8daef170d53ad76d8a772e8dcd905215ab7844ebf7d5a8a49d420548221ff69c4bb916be28dda17117588e456d17c22a35038c6eb3cbd9d257fc9f9038785ec4bd7df15d6a3fceab0310cb33ae23e760e52c66027ab73865a902a01134cdbe39b6ad2776e555b489d44f46f387f51efcca928070cac0d6dbfb85136369e55949746fcc81bcdd7cfc69b04616f54bd0edb985a158f181038680dfdd581619aa18acd7d84a91ad6e50bc7d8663b42a72b8c8ce419c624d386fab6a3a944431afa3ae1fbb24c027db5bab92767c6eced47d3e73a5a03adda3e99085286bc7b273f1760be7272ff2fdcc9a9b94ec28df682d6b517d0146767cd8e7d93021729d9777945fe2027fba39de8a91b146370c98d2ccb5bef184d85cf3ff24e3f171ac240a4594cdd65c9c443dd0d77dd53896fe0134160f9547134422bcc3287fdddb4481cecad4a51cf45feec3eff4c4564cc6b29fe867c7705c4907c86cce85a5e6ae79c799a569c5121848da4545ecb8ddc4cfd16ba30830ba32ebe2e497f034234b08990edf62351b8d700b2394347d16268c0a23777783ddec430992b2eaa9f40bf4b5d50f611dbe912799d0904186c284669b6912672ac389229047fb954d5057994670a618da7e872381f8bcaae9bffbe3d3ae97f06225fadd479e2965fdb4e35bb578809721ceda25a68c5756440baeeebd75a4d604db0ab993737ec22e5976b075c7581a7eabbdf34108ab28fae0a75a27feb878d4bf340013581fc9550915f98a3d2d6ecbeebe04c3975905267c75b7a9fb078e8d274383225346eec3ae5bc34e6042b9bf8dcb507f11e3c2b487e758ffd2583b9b2cda72a4cef0a55fe15d935a35abc3acbda8b7121c6dc054c465ae62a8addb82cc8c823489440196ef960297a90400b38d4c2b2193dc082cfecce00e4d3e9ba91fcb4a4920a63c0dc3ef60a72cb31806f0e410c99b4987165926b760035c66ccefbdbe094a59986be3aee4be51c4d16e53b2b5c08797a08746d5c000a7afc0c906e960896299cb0d4bbc3adfb6842c67dea212c7236527f5ca00f2ed44ebd53d27bcd44da15b6a18fa45496aafa8fa42ba0de9b87070fba47e2a87082c118cff77c54c71892dba80a573851e51700110d28c18c3bf81611729d7b7deb34badc3a1f1b4f358c0c2e6df6867cb9d752824dbb9f647ed1f5ee74f5e00961e77630012ae8360ee681524988902cf8239356bc613b9adc5d11f1b6f5da2c45e8b5da092d082fdc1a98ed5b88107a315e6390c596204f17b9533688c91899092b1ec76b11c11f27188b6dbea77f675b64f6e43217248769b8126141db2d7af336181c2f0c8bde9b2710b971e07445845712144f58b81a7fe47549e2b10c6fdfd0d545ebe7e21f5ca831bd0fad8f3d26b0ea4831af98076ddf6472ee2a532f044426a1b90978a5069af43084d048ee86a309e02aa5a26c228d2711461468d8b2bf25bc2464a2962500df72c6d300108d9ecaf9ca596b6029e5152742c9e2dc0abb22ee890b98a1294a5eb69444e46760c11ff2dcbb2190939ff2c003001b1946f7b6a82bdb7dab6a68d1415a822a8e6f5514b64e3e8489edeaf0cd5932f12675e1515631bf22911f4cef040f7e915da379964e66e9a383933015bf39cf4edd8f217debe0d1fd2411c83a5fb0c61df22c43c481ec2b7df0956b86e597117d26c75a4a3f934bb6494f978e8be525f4aac458011292dfc5a85db1b11b1fcf68ad2fdbbeff640bb60bdd4c881220c82d140ec3deea901a6db38d540a3063a92e2e3d8d29316417c39bb87d8a1f2e41d3702a1f0fd27d36d940bc6acfd16634febca0caef30234c79f295520f4eddf7a68be4195f569440f4e62e3a9d26212d88f4c73242c072a29e94f5b36520c9a9944173433b44e97961a5babb38a76d8f67aeb1ea973434770f7190d65bb56bed3786ad40eb248daf410e57488492d8ac7ed9050b846e6e6c5b99df6ea3e155110e218943b99df6a1e78a70ecdca200bcaf0e47b4fdc5eaa4f85fcb648890e6fc51301db6d4e6f71255ad2aed3eab5932d47d66bdd7a98965fb868aa0c27f811310efe56cc8e6ec7dc087a9b52584d5288c28d14aca24c3341259a4a4a68c86ca276f855539c81e9b65e22f67273d1c7e1eea0f7d609b5c1f420a5648493a7c82191e8fae335643f2ad93455dc95113c506ebe6186525c978724c5d8b0a4c6d9fce0abff4fcf0f3379461c111473a9f36ef9a5ac616368303861d648005d9b8e7845454ed5d4903e1ddaf502ee6aeacb4bc14fc2e19651355e6cd365239c7fd3af535a2ea9ded3c2b1a3fc10ce0580e9d99ed881fd647479120fc36462618259ec23dee403869393efb9f2a903f83902608212ce32daf72e7d6b011e23ead7895e7c90327e60d3b1a5da8323f2a5f6dc7de754373be5f383bcce2fbcac543dd3bb8dd9a8b777807868eec247d2ec7b01d517c9e33e3354e3445e5a85a16ca6bf8485aba962420868b8fe5dd17af3790127e95136d51b15ab0ffde8fc186d56a0a354d21882f3d086426e03711c695b5d5b2aae89422d9230b0c464b5c1e35753db9c7e6768f31a2eda8b1ecdd7b6277dbd10c7830f332e982867bd9191b10c758cadfc5f868e074bdd7902432def49522a0e442cd3e00fe22a3e9c008a8882cdb4bcc001e074802af8cd022338cb60b45064424c5667de87414d37fde9f97b656cf8a9e42b6e660709875103767455fb1ad31f899f706fd729c0c0c3d69b703087c6a43367989fd3b74a7c1807fa3dcdc677f89e650cd8ec4061ae2dfcad7183d00becbca6e94d0dffe5410eeec75335fafef9958a92cb51785cdbf60deb086023123968e0b642be2c0412f45e4021055db6a5966ce57a7db88a068776ad98e4818ad39c21ab84342d1ac04504b94ad97006f07200786c5c7022135f190ca6d7ab13b1de7bee3d47510d73cc42cbd487ba677d6556105368e74b02171d61a766b9e54ddd720edb2dc9eda484f6fedb874c0dca7b0b0809ade5d88598fa15a74a1c7246570586f2450e966109be4dcdcf6a7543143b3f1b6d942bf12adcfddd5e927c88f9dcea2b65f4a8796484d912f6e4b090a016b1025fa518c092a52ac34e9721b020f5892620c1be5abafe8593374e5892b3dbac34369326b47e02e88dcd10ae2f46168f814e5da8c567781582384cf57326c48e81730488de44b9a8ec879b3b1d0898409582e7f4c63597944009f5d4de3389097644aea4a8195bcf04f287d6d2496065902990b0ca9a3c21976421210ad5b2f3baad261a9912a359722935686a265a417d65c1340e41bd86cb8fa8b0e195769952739517549f02018406edd99564336f0d68e1114d3a1f49d023ecfbb056e13c886f3ace5985c1dbdfecb59bbdd33fcd6aeac504a4176fa0db62c29302885734a1d333c44b6a751c3a301be55ccba68b38b0b7d23d65635a1f11c7c1cbcc296b8ec0d864c1b158e36821b187ac835fc6b29b4461819eaade0b47415f181d9e576ae8946d35ef7c93ca80d6c619156a274d5099eb3d0b8ec06e473f2973f8dd74a398489da11b2622c776c753c7f96b14584c9f0f44def1e32a03a52e3fe4cc481ee7c19a0d0427b5b7ddf10df767c68210c7dc1f1786cf99bc7ad45e99404d1e4ac79d40cf56a93a83ed4d23c746a97bde8408f0dcc0566d3a2ae39e2eece61cbd32864bd79cca0d2491cb67c71f8ada966227e0b5e48627f6ffd45f9900d60519e3d3ebfb7d7e8364c91328dc963924aab88801ca24b4a56dc74a093dea79e319bce210f7cdbe7e91da78645369d5eae03da6bb17a2d3b0a5b2e6a26d55ddbe843902c2960683353a97d3bbfb2e41d668a7203f6549f4e205c6ec908a5da04b5eb93b93891f74973cb58ebc320f8d572090a287f5531d576fb3a95856105aed3f62873dba5ff7b8004d895be3a4dcf0aa128bd4eeb3911724c2746357b02dcb4c05901652e8a9b5fa03de23ecac378f438785171f3743a4d1f7e23d91c6bf2e94197665c28b574d226bc136e19674e9ee66b8ba29274997e12dfd0eb7a4d0218c5c6342261c2463e0e0c45fe1c50b8c64ead59f263f528fe46a765b1077a8580ea9c496a290b6da44b7cf415ca60e624db40cda020ff6258e2906a9c53988a1175a776667369348808b230b52bacde0ddc4901b6a98810ed765dc4ff669b2d3be0b5ac0061a707d5563ca126cb0cc8d44c0c04154d113f8649504e890306fcbcfdb1a631234d0d3d7113fac59b62a90d0ab8c071da718b97d8412c64a17833334a905b15d37e1b9e10d2e9a4b83840ae8490a338af30e7d6b3fb372a9f69ada74bc4d1579f478dc6612e6d9cc956a0843060bfd91c14f74b29ee532d805b4f483c0be262f471ac3ce8d11940bbd912694d94a6e3ef7357f0baee5f9322cd7568f1ae26c276d1631eda438101f0e53bc04aeabf6dc94f10c85ac3b522c60803279298c060740d402ec4cf4661bebb273669a2243b67ebca222d676bc2b99dc71112ebc4022bee6b70873774f23ba665a84631592ca7d1934ec8d083092ba95a16aa5d04cc250ec923ecc6173b05288d2e132791f66385212f80b7b66966252e064e01384b748cb4130b45513980ac92589a71914f94f549ac9e06dfc496926eb41be6378ca4841b9bf0cf7cdc39ec5ebf4024969ce9acae021c27a5c1f3a5d993727c471b29dd499d23f42a700d78855c86ce0cf2a6272c6ddff3331d3a3b0fdb340704258b95b4449af0bb474da3bc5818d2de2574548d208911e8ff18574347faf4f3b217d4492ccf1fc65ff75387d36ecd3a2498221822418cd149b06624deb422473d8dc30186eb066080f602511d444b410473b57889ff92cc84b3617a93669bd329ee5814df7facc80358392b3f149787eb8bb9cd68d4bac2f8ad8b9626df7a90c1de6ee575172aa93dc460227c6f2e01c7284c6c2840b93f3ded9d2b37ac3ed340dcee67f8fbb43e3aca7095c44861b888bce7cae1ca96374e8e993fcd4cfbf5ef482b804106d017d582723473b12adebdc136fbd40b00d642e7fd0c88e5b3ad36b39b807fc5c4f40178318ba682d5b26c9dce39e4672406b1c92b80b390f0326656444aa616c663ac39a5a82215ae784a3f0a01c05146140098a98d5c9cf0015ad791dfd48857b25f082eb6b22d89ad3a434ceb1e3f44d6b7d81ec12e2a8753559ea13de01cf7ada2699596203d14d2323c3015ac0bb948f1d6158922358d5bb3392f0a0842d79f2320eae6003616c63806bde99a45fad3d6cc0e4965469cf5118256b1ee049d7d398e863959878bc6d1adee5456c8a0135e0ff118f8f192d84e93e42ae9d3831522d5fa1fa65467a84c207b06fb66df9e7ce9d6d058c8e426705370d1564159a9ff8008ac239a73a9313feadbdae2a54bbd9ea472b5ca9f033c46c46119440bffeeca85081f94b214b69a3f64d1cbd82e2d44c58a9f4f031343743430dd4eaff2908067ef30b12fe24d5fcfe798577cb590afdfe632167973848ea10986f63cdeb2914d9cab14434c2400320083ea62ab529ea8a3bdcb48fe741c4ee6013029d7ab0e6ef3b2018b5255c5802805e9ee1e1ba40551eb7abf5126794a0cf87c9bfa7bc6a4b247ed3a7d266ca7eb731af1c98d9e0f4b365f03225a8182a6843d23f2b139aba2fd3bd7a72b6210d64484e7a2a23b5df30a7cb605de1c941f778f80961853e00bef583ee941f79c6ed1468c742662ec7ce6237096ae3a1e8cc3bc42ac31ec427e3af4ea5a355594792fcb693410b0a9f4b5467f683b90cbc35af7b601f60c6e1acd003fcf1841514dd57c6628c6c093b61f460fa755ea7ccf4c10c8ed88872dcc697fb3971e4c0f683d6a9758ea0eaff74d06c71647e59a418fce529d916a236d006011a4a7ed5ac5d494093c66ed378b230abcbc7a805d45aec33a552a0118313ef189c1d2a97572ec7516465c660bac060f45cc21d2b2882edbf36c83a22579ab2f958ab1a4b510b6dc9a478b3ca95e6fdb1138a57fcb0b3a387894072cab46753fa3543e28b2720b544c2a6fcf737ca0978963768f7fa498eb3dd6f177976c8b465438a0c9bcaf1af2789ca1787d623018a461f70687cafc4dfbba97778989012ebe1e7dea188c274bb454001da9be987c1b651c56f01bf50b7e49abca086c5770ff586b927291b67eca844ad9f523f1008b05d14542206646da77204b999afe2351a6cdcb08b50fbe4fa2d8b5d84ffae31e495d694bf248763c6a7a028e9883cc2a53cf62a2bf22fba16d3d6a8466f707107bbb9e1e7ff0c5c94f7e46ab148971b8ee2b8cb36faad4b63100bb6ed1ecf93e49e5ce419beb13533ef161913b8e657ff3c9c43da07cee679e77d190535267805851c9522f86f09aaf4919dab212a520fcef3ac621f7159cb1c6157689b536a4da9f766a71030ec5a513bbf1fe3656b53cadc6233e519e1e1d79a6257138b0c1c068680a9d6fa881dcf740f37e60a2fa95eebfd090a2afa929c930b69232a23b5c6bf93d419a8135d27cde5e5bcf8ccf24aac8fde9ab1e0663920277876366c179e60609615301dbcca487778607a4a179700c31e1749372b0a6f8dfc5309ccec1bf0d29425075f28e6cae7e32251bc89ac1ca3572901cac1c5915151c6b67e06ed234725c98b3df4e7e0c27b9e3ea59461664d0ad6e67fc5df815379a6b88f1889fb8b5f8bf338af5e846fad7510404928b335e8fd00a50464552eef3381984f0ee65d9ee6f37696dffb937116e7eacd39c133d46b8d9ac9e6e4c3301f098d5c90d19159204b8e33524954924e6e35c5af4b3d8f47284c143185debc63cf543251f6d0a45cfef84e2916fe7788f91cbd685c040e864427754cf1856dd7d6312c715584d036cbc9e529df8f78b58dccf47848a64a72813295df735af681bb848d2ee7ac85a5a6790af921d6fd8a3839702aec6958a838a2e5d830db461fc27970f56a9ff6cbff5e61913bf2b5e0fd30e35a17a49d52baebfdc09f8ab9274f461f497bb6eba4d225f1b27aad56b34d17e28b709217cb7db9029f59d4d15bce65983f52243fd1471061030e591eaff0a96c9107120d808f81aa76ec746d70c49d35d626254fca62c34f5558a688487d3cf19a529b96cce46c58261c1a58b16b726ebe0fb44e571cf49c5ffd53867d2c446d200c92f1d2b2f792627f3c1991012b2f5a01fec87c244ec5393d3f7699bace9b59872f514a9a9c2b37f22282083a6708e497137d0a5619ea7cf3a64b56645fad3f0134acf724dade07e42cf2222b390c05720d6d0a46ed6c0ae5b09f556bd1fb713dc70c4b7c075e49eb5c54da3622d652bc72d99871631fe10b2e4c6e2396cacff617e91d8c3eb05bf9a73c65069bf2293ccce31ab2d9c57ac028b246dfa1323de5b0f35429d313a760f956a5929c82600b02ab660acee4a0968f55a822b6967ac6253f0d880fe23dc5d243bcf3ec2dd112716798c51065c67ef965d46e9bb79806134e1aff2a839dd02fbe86d58bf46e245884b52ed46378c1c058a897e4bfdc8336814033dabc5bb8af792ec057b52fba2bdf05027bd0489daeaeeaa9ac11aa0aed9f390dfac6761eef6fcafcc18c3df59d70e6e1b975e3974d1af22920d3deab24f731ba74c199382151ffb9fc03de46fb77a68fa88e797f301bc5ff6fffb8c748ef15dc2aa02afbc66818e6eeb14c37e114cbae2476962dbcd66a9d8807f71f60297e8ca89eb7e23e0157da7f697d426a748adafab0bab1637dd3b0b553f732bdbd274aea1dc9a2cc2b8eae52495801df6ebfb4b63f271b9d309f3242c4900e494c1ed3d141f612713bff316c6968a0199a43549b2deb429de218ef86902048e1b5cc2944abc4c63eef25c2ba1bcb680ee3b7d78c7d6168973a32df5a428bd499244199c66a91ee9ee068263fa6462ba799a8752e723be31c45b23e6e40c73dad314f2eea937a635769f7da508f1ba00367264748cb68a5a203afbf3b4469045b9640a119101e242e7db682e77c367093b39bd9aa0f3be17eb095d4f45400a552141777ba522caddeb0a8aadda77a41b920c3561f9a28f043436c2dde10745e4ce00b74741aa44c94b67e612a8423305440bb54a067c35820066773643bd2655442e291b085d97f65e1ea864aff1093a7eec6eeba2242f82d0b9653f84179b6b6cfa1efab84eb403d83e2a261d31db7dadb0814fbe4fa64664eb38519571639ef2ebca2041324471a6e631105f338c23497cea88cc4426d64709ba2ead38d69931b32da2ab74139855d33247d9dbaa8c9d351ce3ad857bd1458e44583759d3fb50d16da62d508dbec3072dc92154a91be59096668a4102f6f09dd9199e4bd9dd15f04b2d9258737602584f3b7cfaf4fa1ffef459870e874aa52436ef1bec08e6fe2566b07c191fab2c019eff5191b3acd8813ee3551fea999863db20b5f894b5553b34f85fc9bbba1a8a490e39201073584fc4eed9873fb85c011fb80ffd5d7d6ece18d878ac0d565db715f84a809e2ffc574a750e650bfe2b26f855cdfb3b6fdc08952732e78e64c697cf041bd00d50bba26751106cf581dbb1bf9f69f05e9fcaedbcff378cd13ebfc4818fa10a86fb1b7112a15ddd19a5d1f765f764259f44ec92df0d18ca9463deb4bc5694f070c39d3e581b853f4ada70a353c00d697b684a177ec7e4254f2a497e45aca8eae11e706c763a5d2010bc9c53b02466dd6ea4df68bb03608aa6328703d0caf9b4232f089bd76c188fbe4421396082f4230c183af89e58981954432d444c8a345a463ba21cdfd067542e8ca671587e422431a2d581a7432f711acdc9250ca406da4e20ba8b560e4d2b50ff7942a5a2f17aeb66ccecbc51bd599efbf63605fb8df38300914f811c2fb519a1a182427bf9a1492974d22189edce32ac2fcd8e08572b78401b46753f0af5a9501342b5f73f4bda4ad8d6a1b8bb1c76c798206519de02b5c3593dcd1faf046be35d54ea47e6914d01bd4aa4bdaed451d0894a8c2ebb99ad0b174eec3e194e55dc2e5b2b464bcd05662c9040b61316feb3f00203879d90b06e05373433e85ab8a3abde181b123c625b2a7db1f2e496cd6d8d5d7173ed37ab833d4d8172d29efe1e8226f6907327f6f4b51876438bff7d61a121706f78954cb01adbdb3308a6b6c3db41282f70c9d3892c869dff43a3e91561b199344068f7385b08917c67a42653dee7510fd4ed25954ac82c1f2261f9e484dc70b525392a64dd4c3e260b8490f8207f7939e45d42ab8764e78a8d222e9d8f9dbe78ea57921b51b3e1828f66a1c6cae8393a159a7c705b43f3b479bfbc0884d432a45d7c158f2c59c40b1584b7e85bc2b42e0cad3467c784a57038c89cfe69d7bc99fe1b6be71e024844a2ca4016e73150a25f67861ca23d2c92ba0b6112218e9f5fdebb547c933843b9c7b6a9899179d2291850a40e7e88076d9f7be3ad8e75b42da4411831fc8c7c786b4c0076c26082a44b9bdf4683ea83d88ddf48028b1888ce18c9e1bccb9bd483c4a07b3f311788f3c7812111e63bd498cc0bc4dbc588a32ab218d8074c54fdbc6e9cfaf07aeaa0032864f0bb7c101424c504bdc332838642edb67b2d04a1c9ee10ea60a3e32fe51b5b7376de42f078b1ffebfa48378b70407d808a54b835f188f4be8d90cb962a2efc34855d66b93167828576ee54cf895a068edba81f8b46281250e09e462a7c4565e315590ec525ccf8df45cf9e55c6b1befeb1de10117408c3222ecc6508150b7ff4207b90e3d67ef0719749ece71440eca79f2af172738795e0267d199f76e81daaa19569323b64d86b4aedac7be78771576c429fd2ce8c86f338234c371499603bb4605a808783acbc38c4929eb5adc22ec3e177b3e4ad89f6bbf9b63e6e2d9d1f10b9eb0432fe428672ca5db0d7948d9dd36314ed7e0645c9e05d0e7940f2a748061bbd0ebb23d0c032aa9e01b13a099752d9973c9209963112a999e2830abc2bfcf2e9448a2618218cb9cb9694add0cb852fa13e86f7748519bea86fb98f7e8714224220a0d8cc7632c299ad6e1518037a6bd83266560f546d43c14a98e59d332dcc409f0d131f679c8708ec41eee3a57621bc9b1e78a5daf1e4f1816f7ce68692581b3accb433bbac62b18c6d92ee31c5b904db62af3dfe1ecb541eeebd1fb06e500e3db1e03901df7514447eaebac56bf0577039e89807594c0bb5879e2d87a82502101c4c46043582343149bf9d062c35fe190f329be6fca881252623f451d823f7e6dc6d96cc2f202a5e17bf8147584e82ec11acde393672cec0c7b60a9a0b86e99fafce1d61e8f3c6e11cdf109ce4b06e2491861feee21e71143c9a82730c81ebf045ac5aefb6d1748112203af1aeed4c06a289381feafcbea4a602f65371d4bb91920baaf105b10ec1d8aed012e98554783fb24f8c3e757b89da60de9cde2500841ba217fdf43d39ec66041097b6e84c20090c23860bb284a02660f080c53c13b9584bd1cac9e3dcae9d051a92704dd5adafe089d0b40bb7fbc537f892dfef6f22df8200a55a9278a93339c448adb0fcd6f190ebb814353b471d6293abdc31dd88d6008a53d69347ee9e411a10ed2a5b322aa0322e0cc1acd92d0c6d5a5bd3e5208cc1fa0b487b6fa2225ba454b2dfcb8e83dac4183f5b6311c96f53341d237bb9e993b212bb6170712ef5a21cbd1990c4fb675aa1c5077808ffc518f2a16dc253e1ca65a96c3170f338939c54f5c65728e7a608e41fc74c75c8c44ddf06cfe3dd4844a2b3a9610c765145810f5fde301700b690fbc4a9c122c01308925bb33a89dc237fb8e985d19370aa7fb5f54e94c5220f4fa297a8e8824aa41ee8bb675e9be80a66d3451db297ab9b4d0b6e973ecae4b014662e60df65b5ebe3e565af545a01b282d41e803b828a7bba8f4202a18c22531fbdd153ef08e99f8a24f433d0b024ad59213bf1d5150c849004b3aff41df0ec4a10f9a3cf213476a81456fc0031a8d37219d185878a6f90d0ce7b0193aa3e2d12074e16f4a214d70ca2142c85f50059f41a30e04fb1e7b988b2fa871969d3197dce3d0d47773d179d3a5f856f795c0d61cde365c34699bb2c673c346b2d75296b2e471edb09164e42a25e7a4b3564691669a6c585bfffba718796d0f64033488ee54b7c902375c7044aeb3d77e58f50e46faab5ee720acc6c60107529bc08117d48207f40773b5553e56959e34fe01640854564bd6da721ec652e9888ee24af81bbd4d0ca6d5278bffb798cd0c97e6bfdf922dde75de337275437f5f1bd733ceb98374e4f83900bdef5cd09063cbd02bcd4c0c385174b05058a116a2a0bc155ded02123a647b9f21044cecd3960424d70a66aef4b36bf408b37f49d00a728f5f7f4350b71272e36667130e789d27aba6b66f6e37a940b4d5a683a6a9716a123262f55d2116da74309515f25766a5473ea08ed1b8b1e417c80be254402a8e44d8ce8a96cac1207408847c547aa74114b483a682771ce5f9330424dbf8da2e2b306a8a31ceb4428272aa93df0b069bbb8cc7aa8cc2b6d94877624c59096111581540161b73998ebcad9ed0935bb06f2927a337dd763a1d95c2c4bb8c656a86460705594c6c0fc523c6a7829dd432e5e82dfbc1b0c4c858da77bd50833afe2bace65ea28dd3b5cf70f3a63dd2003201082f40323e9d103b85542266ce1da1bca00413820bbb0182599af116e00896a8a7cdf36d15c997fc03a1ab301ee2b6daf3c0a55e5f88df85989a1ec298442fdbd03157689aa7df5b29cc5b32c4502d890387c900888887d23af1e1b07dc0d4e8ef180158fff5f89d8b4d093a6aed2f3992a63e820fd3657f500b403dc7fe7b4a48bb97bd7e142d6dcd614cd67fea9b120fc57beee57136c945991c931ca9c4ec57c30affa2bce01f02e6fc34cb83c945b01faebb4c929a0cf519b441fc1870997b319ffbf6cd2884e2dd3734bae1e3ab2937b1a2a43c36c5e24850e446d3447df4d214d2aa8a29e3cf55f71e4d2742bd0919d0dcd4ee9af06b717bd71aa657e8075e0fc440706846812e0a0bc351bbac3fbce92331d37c2bb230825e880282a5aeff880f213dd821db2b37b6fb485e16872ea5190e1548df147de29c9d72f0c178944cdf86ff14908109fb300b1d57f78487dabeb62137c3fb6b254b2f1bbb1ba60bb8e5462c3d0e0f68c16fde1f807b0800f254b42a9d47b9e1be9f32912d149cc3320f6e6e69d52b19fb0d92d23c9fce91f1699a603e82497f530c2a5255e351154e91ad07bd0a683558ca681b9b874512c12ec7b3d2be9d75746a14376f59b6df816bb8dfc7fd7bec4ef79f8ee93b1bd2890fc6fc8da7dc6fe8fbf737735ac834ba99798bbc838e25506c79d048f9f656c7ca29496e7b6a816054a0ae46858ac9dbc89d97f967311540ad71508954d4d90e49c529d4cb3065f08000e747c88ed9db4a4ede9f042b2640698e3d2ec24b13", + "0x3a636f6465": "0x52bc537646db8e0528b52ffd0058540d061e1308c819541050e938e9005f822fc197252fa2ed5713e0ba46c46f094c0fe2307326fb057d60bbce8bdfcd175f1feb2bc7604d3068f26910799b2f5ebdfc5148bbff93d098c88f368b8ee8661e889a5a2344ad1142f6de72cbb41dfe175118bdb120c23497929fdc3aea901fbf5f6ec5254f62bd59323b7e76fc0f30180c36cf35e4cfafa724fca1e767a5f2247e3bd43a5ec62ddc3617c3ae39462e821cf3b8db150a63cb17f9629075e3b88be0ec6e85aac4324d45eb2b34294e761194ed5dc9ba317da543ad5095086b2a483a9ebf1e0d13163d251face33b2511d6f11c590cb7bd712be4d16c7cfcf8507e99b5e724e8c2c797dfaf4703ff89ac1bb3f6437c14e300b805fae263731bf4f1f773e356fc9ec166e38be7cb73ec2591317a0538ea782e76128cbd5eac1bb3e28798c16556fc11472adcee845f6b99156ecd0fb7de2f032df7f0f7dc027dd963731bf4711b91be8d0591456f2c88a40e53cd6fa13706041acd5e92a22f7e63b0a4e62fb7b6f327b7b2f3376e6df339f6926c75a34a0145c098b59d9d87028ee8b23edbd12bc05167e7629781db1b189b8b5e762e038b62678f1e95249359f34abece1e3d19b6b3af97649915761d3fc41cb71eade151d36f60b8f5f60c0cb32fb3b60fc90d0c6787f345b2b5af97847e88396e3d59c357cb6f60f8de9e81e1326b7bb8cc0a7fe8ede1322b9cd2dbc3eccbac9087de3e2425a8552aaf96cfc0ed0d0c717a9e8b9d066e67e0f67a34cc961fe221a62015d9f2135c66c5af9744d6c9acf8211ee2211ee2211ee2dde1fae4ebd539d2a23482db0b7c1b03c28b0ebfe6b3b81576cde7afb815b29acf07c2add8fc8f5b1b03c28ae6db708b9bbf0c145d214ef3b98d59be8d01a1456f875ff359dc0abbe6f357dc0a59cde703e1566cfec7ad8d016145f36db8c5cd5f068aae10a7f9eb29e00810accff61077dcdaf37787eb9321bd3a4731c61170bb13bef9dc067ddc027dcbacf06bbefc7a49e4a307c30f30180c8896e7b85b6ec9ef27b7e2f7eb6dcce20fb1043b66f15b5f68d3fcf8f9706b3e67c3ad65d69ebfe2566c3e0eb7e4f95cec56dcdae6af273fc4433cc12b396de5a863bd59b275fcd6b1de2c899f8f9fb528b6ac9359fbf592c41ac68e1fe221de1dae4fdeab7324630cc3ed05be8dc1c674b8f5fee3d6c660b0de6fdcda184c4cef3b6ec5de2f03ad2bb4e9fdee6c7df25e9da31891702be4dbc7af895b6ec5de4f6e6defb9d4722bf67eb9c50fb7de4f6e6defb9d4722bf67eb9c50fb7de4f6ec5de73a9e5d6f67eb9c50fb7de4f6ec5efb9e8258975a34a0145c098b5cde7a18023baaccf3617bb08c65e8fcf71b7ab5200116698b52dcfa3d9f8e6e5e3a59724d68d2a05140163d6365f82cb2c794e76118ccd1e7fbd599759e1d6f243bc5e92c92cf9211ee2211ee2e815e0a8f9eb25891fe2213e8a312281db9df02dcf6dd0c72dd0b7cc0abf968f5f2f497cf460f801068301d1f11c77cbadf8fde4167fbfdec62cf9218e60c72cf9d617dab43c7f3edc5a9eb3e1d6326b2fbfe2566c791c6ec5cb73b15b716b5b7ebdf8211ee2095ec9692b47cdf566c9d6fcadb9de2ce1cff3672d8a1deb64d67e3d25f15c437efc100ff1eec8fae4bd3a471ce30db8dd541db39659e1aae3b9de186c4bdb302b7e71b8dd541db39659e1aae3696f0c066b1b66c52f0ec7edaa14408419666d2fb3f6eb2599ccda0ff1e270cb5cd117bf315852efd7e356e88bdfafa9631216860f4edd83ce41abd13a68327a072da6cbe8a5f6a2c7e82c9a8aaea245d04a7d45b3a09f68271a8a5e419ba051d056b414ad82fed253f408da4b9fa053d04d74145d8266a2b168120c1d61480a4346186ac1d00986a0188a62688a2129869e184a1a126208690836c4652888a12c43450c6d1902620889212286b40c393134041235903c61c805487c80240b243d40f2c41009864680440b245420790112162099029215201933c4c51013434b2081028919244e2079634889a118209102923343251892c1501743490c79602836d4012450401285a12c5e38c10b2678a18a17ac7881042f3cf102140190c20b1d7821891738f0c2085ed8f2c2102f20bd20c40b5c0270e6052d2f30f142065e38e2852502308517b2bc1002a12d2f80c0881823608cc8c0481746b83012331203235b18818191258c28612404464060a48b910f18f180910e1849c2080e8cdcc0081246928cb4c048164658606405465460040b23293042032333307285112b8c90c04815464660a40446bc18a1c2c81446a430128511288c3c61c409234a469a30c284111118d18091238c64c04811468c30328411242129084141e80da129084541880d21324241105282d018a11e080d4148084263082141e8084261087d21048690184246106a430808425d08c940088c9009845820c485d017a19810164572504409459650240945d628f28322658a04a188108a00a108128ab051640845d428924611342217518c226414b141911914b9a248098a3051a489221a28e244101482a280248a201b048d0962232808414a415d044111a44610164132080a139482201f04d12068064160826a105446d00e82a20872220809413a08ca411018414b41610489116482a02f415904b1200809a02858420049517900a4045406680aa0250041f11346eb07401c58150174c40f095400c12a06ab180f183c39e02102cf10789cf003e907179e1ef0d48007053c38e0718327093c25e07901cf183c51e0c182c74c4b07ad25211bf0344128072d295046402101750454191796c0c21a3f63fce8c00525fcc8e2c21178622eb481da82c81b2e3c41c409750d17602e34f1d1c085215c08c20511b82044f5810b4bb8805481e08216224aa8648834a10ac10522883cc185225c30c28524178e28f2c505257e3ef04345902578967852306bd03242cb0700d0004bcb4f976f8c1f2454434841e1a7053f4a081102644388078418d1e241ab8d1c6bc82708f940d0195349c816211a10da819023841421444b3542103041dc087283204a0862031e292062e6071541ba207284202fe081823ac6852d41b8f831c50f2f404c0419230810829011b425480c809a20b20422653e190429838514e48b54526a0341c0d049d221426708f0043a45e820059142903782e800080aac20829c2088143f26e0e1e2c7169e323e4af041c20f08843ec003854f0e7cc4f0012386e1f3850f0e7c6ea093e54710d38a59029f297ca41842021f0e0029021022107183e7083fb4b0b0041694d0eac124830519f820a31261853456f8c1102b2a1b1f1741b4f8baf8624162f5072ba011248b6f065f0d5618c3e2c21a6285355cf8000e332b90b1c2182c2282b4aca0031c4ec0e1068e25e068c20a2c5841052b60b1c209523be811420f1b3d6bf4008195a5e707ab2d5a68f08029728691345a40c287831f23f8d1c68f2a3e227466a012824e0c8428810a03480f524008d9006a0c9d1da890e573e2a7043a63a07290030837425c042e2041478c33f121015103e5858e18214ba496a013068f1428307472a0f3058a0b14193a660849ea59d29141ca8c1e3474702064089d1a0871e21b42870b214a3a6ae4f0018f255065f48891a30729188f171e12a49c90638c8e0d3e2656374829e1a70a211950b1117482225d8474d14123a5861134844cc183c42304cf123c43f06c8027032b9cc163c40a3950010c0f123f849848b49cd032f393c50f172a28a1420882941094041e29a800fb89e2a7091e312a00a113849d2738072fa080c9603478d0688520880c74cef0193a3dd04943e70c1d1ee894a143868e0e749674c0d0f142e7063a617468a0f3021d30421ed081818e163a2ea8661089029129d424fc90c2052e3a42d42054346a11826c51d3f001061124b890258819d5093a5b884881c8997a847a860e103969d428e49c51cfe488a96fe4f0a04a21c70c1d580e1a750a150a393dc8514327091d0ee87840a7034156509f20c484da84ca843a835a4695811441ce167507f104750c1f2da82ea82da85dea07aa076a524522080caa0682b8808e01ae01022107991c43e05923958194065e30e22ae019806f0cbd0146017c0268066402e8469035c02404498347093c4cc821424e16392ff021c60520829ce1c38cda868f307c90f1d1031f3bf021860f1df858f2a1860f367cac71b3e5468b0f20f818828f347c10c1c70f7c8ca1f162b6e18307467c80030a3e5cc0e30394192d245011f858c1b7850f27703081c70644924084093dcce078428f347892702841880b585b70a0c079c247042a984027081e58f058010f2b8a3cb182014f153c3c3064044143f06c2124043c2ce03963c71ab3055c021e2b8034b083044259fca000350321483a2dd0d902e502941642885829b10a010b3d70818c1026503400fa802a08a830281c0829037503d45210255a6c14f900aa8b16115035f844e04211827c40052826098480691d61c7085a53b4d270c1084536d073860e135488828519804140f1a025a615041e18fc8015f1800b43f09941cf98a012b4cc407db1a30a1f6078be1072049e32563af8b050418a4f0539d40032a2550625c6f7448f194538803a83052f78beb48a10c4033c34d089f98801cf0a7c6cd11a426b8d9f255a40a061680d641142a490460ca922c719201200788206073436a0a901cd0c50b11f1c4c333c4e309ff0c1802788ef053c598814a18a09c2021e26e0016285c42a690531448cf06941a48d1578b0eac203e3f1658532563063c5019512aa107c6204694155a30e8105848f1c1081828f327c8ce1e38b0f4ced4145c21783cf8c8f8ccf8bef8c0f8d2f8c55078a8cf9be586d60e5812245f896561f5825f1811157f025a1880f8af480474b1129725890b3822152f0bcc1d3021514aa27544ea894544da89810c225f584202f3c64f068d11ad31202cf09789ef0a382203482c4f084d152a3452648972244f894f840f07529e2a59679210531073eda78a10924357081083d6050628286904283c708423f0842c19fd013868fa4a0275464503040bde0052780422089288244d099941b2b2e90d840a806b209159c10c281540f68085a67f04c1174c52a8c1ba41f227862b09a0190078a74e0e70b214de4c47eae6829c132008b8002934a4308172a3ca142132a28adba102ac20c41cb891f1b08492375868f2c7ec2f08c19c2e2678a1f2b86ae98492f7409ea814ce24acc0cb85086b9985c5a55ac64c0c3c62a8c0a5d540862688bd5172b1b04a9c0c80f8468f0a3082148a06c303520991082042439e03933a484a4053c64864c502489151873073c66e8fce0c7892240f020e167053f60a06200d401214fbc80444e0d82aa081a411011281df0986045831f303c9410d281a0229048114404432f08ca80500764077e66200404487080dac150133a63e6153f2ce091411130b80beac40f0d907c21048a1734304df033022149acc07c8919048329a22444cc0b53acbc102202236adc3c010eb1c2811023ac8cf879c190164243042d41052682489033032430f8d1e2c70b940c7e4280440c242e688901444c91a4202e48a658d5e06749880c90a031e4e587091d200cc160471143219847f478a1e38322301f12f85ce163854f1540ca40e245881a42a210d2864e179405130a730a14080a9b676810f38d1905fa654a8166092286e60bca058dd118b89084173e20848a1c19d02d80940002c18f0c78a2f851e2e9426805422ef8f122d482940e84d0f801c48f144265f8504a8991c3450e0d72c0e4d8a08523f050f1d3c5cf133f2910d2418b8c1f43f08c8047053f30f8d9e227c623841f46acb4f889c18f0b7ebef064f153039e19fc40c1a3c68f087e4ef07383203378c204112148084145085a419011a9314156041d91d345912a5e4812f2414e18540b788a60042674c6678b10117eb0e0e1c10b5f5059a888b03ab303881d30006c00001c08a2250897205b88c4887441840b16c06061898530762cedc8c10e318884217203223658018a15a458218aaa4415415da29aa07ef94cf09de0fbb283cc0e22ec18820a6178005104043c82f834f025ad0066051aac30838f042a7ca102182b7460850face00115622a74a10217428620a4084288507150bfa85e0c616288d290265a00a385a516c200bf00c300c1b801c18d123721103286901d0821a34709134ccf125a88410b5cb4104b4de183a5ce083933048821b016d66821082db041640744c41029c327083e647c84e0f3049f28f840017442a2007c0284c18c02dc6226e1d3850f181f19ec18b3c3c54e173b31d00ab004e0152d1461d5849513401e80678066ec88c18ed88e2d7686d8296287081e3178aee099024f10785cc0b3031e28f0fc8007083c3ae0b9014f1a3f88e0698367093c5e0885119a22688d2032738b900a261bd306431b9861cca529c60c33bb784189223a28e2c5ac628e607a1112420804930373035388893487104a825019d904e903e98664824443fe400a412a410641f64002418a91652412e419d20cd98654433a4192916bc82448366411a41939461a411e41f2400e41a621972089506449880c59027985549220904ec8276408e412720a49858c427a911f9052c82e120aa984f440113124103288d8059fe129b014f80d36023381dd6036f8082c045e0297e12230190e02278189c0436025701b8c84173cc038601d7018fc057bc13760308a84c151700c380601f6c22a602a9805bc82225ff009f8056c02c682afe02a780b4e014fc1246017b0146c05b78047c02828b283175410651081107f108310c1884b4422e210718ca883095cc921aac0872844e4126115f8a189952a0f70000e1250800d09880106041ca0061a6658420025321069e167c80b0100400cc20b828bbd710719134b222b4d26c0644a13221e9830e1a2d4210a111326271f9f1c15e800c5890f13b8c9c162898a9a1055c921869d9c140cc9410114284d728002a589004ec0431105a21041f9b244443b309152c4a488070a3821aa404f8e09d60a14274d8a8874604244b4c38f9c12ac941da2386162812a443e5061e2644a174521eac1024d6a78ce154b94431429519834c9218a1403e4d03d72acd0414a0e443ae4e49060ad5880e889150b102d4900985385152703683067042ee478d9c9a1626972a6582996871ca44c21bac98962abf84001273b449192031327539a68024d5c3872a0f891f344508e13ab831326454456aaf890c38e1ca5b542e484024c9c4ce926537488d2a44a0c3e729a28fa8128ca4e0e1316287252450a0f453e34c9c911c15ab14204a547ce1235394a84608ba2f8202507263b342182822307045ba5871e7a982195d345859c0fac0e445128e0c44a141f98e420e58a131fa810b5723cb0454456987460ad38b162811d888826c0c4c994b6c00e4444ae1c39496c911529509854913285a80a0776072952aa4c6132c5090f56aa1045a980142616207a02e66c60ad10f160a509142b4c7420720265ca9426517cc8c94162ad1015f930c58a131d72e424d51c0d2c5195294c88aa38f1810a5115265676b832452727035b1485a807a2a226455676b832859573c45a212a9272850993285270728c581eac34e181890526c0a4082b5088a24469c2430e4ca6f4508507263a44f141ca04a23821a2288a941c9850e9418721d64a0f4daa3499c2a48a14a495b2038f1c21d64a5114a22b44395c96a8a8890e4e7488d2240720395b9648072939f4c8d1b255a4ec6085c84a96b552e4c394221fa4f0e404d1830f56ac34512107886d52d444072651a438d181a8c88a132b5588a6fcc881ad15a22a52726062812227509c4ca00914274dae34b98f336b658a0f52aa5080890f1f53582b55a41459912243932a4d6a58f990c256c0c994ae42f4a48a1406d000fa786389887c20f2e10036e84044010a34b181051f51d82645527ca0c2c44a14264ea63405a23879d2a42801383ea0b0528a983c61897288d2044a9309309152c4c44a51142752767c98592b3a54695201a22a4c2810c5890e5188a6307132a5ad409122a58628529c143589e2a4072906a83e9cb0569ee440c4430e4d582b455188aa10f110c5c97d30218a931d6e7cb8b13938b112c54995a21f88985800ca94294d985421d2018a131f5c4f729002c585e363096b85870f256c1326383e92b03d306952d4448726454433a87c94b98013284d9c143989e204870f24ec931ca440990013a2221f7220fa8188c6c711b68a1401741b89a04ca04951141f76605294035115273a4471c284c98e19704ca17d21e388287a8fb88dc1601d8fe48ecccbe2658953a2367570361c9c6dd3c1d9b66ddb984e9a6db67c62668e94329572aec44199299dcc534a69c3ccbc316e8cbbbc91ee4e9632ca8d4b296566a6bb9b9cbb94e7d2dd38ee4d5c6daea489579bd9e4ac9392661acb93c652ca9394cc268d4eb9f4a3cb1f4fc99327dd9d3c79eeee049a508e73755667714829e54637ba946e31524a4d1ba554a6b4a5da04b5b92a497160c964aea675734e4955544a2a699492b2a473ca18bb9daa8ed967b7ca65cdc98c9200b310639494258d546ab31bc272638e41987723c0922c519297e54e6d71d089929287e70a524aa6a66566a9c91865a7824077dab873eea472b59573abdbf2d87d00b3a4da7633959adcf1d464c7546adaa63ac99407903959f260964c1d207969ec32a9c98d9b940db8214ac92ba92771ec763491294b962629358d6bb4c9cbccbb5152aaa2ecc93853cc92535288fc4e3b94019399b56e4ff3f49d16703a514fdbe44ee66e519379521959c3c13fd68615b0492997999929534a29cf9e7657ceb9bbcd39b739a3d4b4a9f1b6bb4d29e5f4a494524a1a66d624a56b434d0d955ac709c0a194fea09e4480644f4e8d0fb03f9ec73548a621ca3925ff0c611b96924e969272dc9d9e67e35596d5c6f33c03c49a1a49d7666d3c0f07087a2849a5dc4d63c92c375bdee49c34d249299d9c511a59f20c426847a746299d944a0aeef6581e91ce2092f2ae941a53a65372645e9e3c234f9edb4a161740d2c8949952ca319d94d21825dd6c728aeea4cc9a94332ea13c270e3997f2eedc9697256f6a575bde5d4925a574521c934e9f3929a59c993893b4d3648a67c63b774a6dca5d6d93bc0460254c2365197fa4a6e4c98b8399e6b8d965cea2b632f2025919a39492e2c8c19429cd6edc3565d9eeae2639721677974dcb6c32994c6bda35adc9c4cb2b354dfb989775ac8ed52179994a2a7923f326996764a64b99255d96a8ddb18317c53b98e58e1dbc2c70e48f23c78f25cfb81c254f2965a452d33466c9434aa94d9eda5cd6e69474ae9492512bc3c648a5ec2265d6a4a4b4eb54cc1d65eeb8e378a2db89c66da3943b1983a6ed524a25a592eeae64de9dcbddeef2ee6429e5943c254f2979ae9c92275366661824cb6d37c6dd8e57ca8e478c34d24d8b7105f9ff1b9d52ce69a3699ac633351b4d4ba269da00a63605a031338d52b28cbbbb32ee4ac9947799eed24957ee6e94bcccd44577761c378ecc94a9dc58ca4925f3e4c99ab6946edc297929a573cedd49174597eef25c66deb97432f3dc5d9e9a26792eed96e9b26439996564e6aedb9d93796ea4cbbcbbcc74e9b6514a7729a5bbcc734e6669c351ca96cc1c99797799254b5e39a5a4cc2ca5643a44a5ccd1344a376da3cc2a243d2fe4a8664e007a7226ddb64d45e9ea083522448bc46d53c52d6e5145378d529992945219a35c5e4a996e94d2549026a726e9dca4a4bb94f2524ae9c73393737653ce49b7f3a49452d28d9939e32929dda5dcb1ee42e658b64015293d10f59001e940548548872a5298b45c000091932a452bc41e767f88aaec90831428509ae0dc4ce9a1499115a21e9c14ddc7047cb0d2436485490f527488d2a44a455961b5582ee810a50913a22a4da6f42085c807a5490e52a0ac609252d4440727509a5c616245a7072745517ca85275ec50e4430f221e9814457152650a931cac38e90187c80f1580a8f0a34607284e78c8814911141f9aec40a443cf0f443a4471c2248a93263ce4b0c30e5288b47afc20a502453e9e34c92107a2272d1700f01c4100f8610200a2274da04c800905a238e1c14a131e5ea54991951f35567600408a942a3c9ee4d0640250a048a9b2420b4d88aaf0f041f48449d10f44517cf82822a2c08e1c45569cfc4084934971529443132b519a54296252e4a4871ea4b0545800fce06407a22a53aa8efd69420425879b9afd894234654a132644146852454a91151c00e800200a059c580169f6c78a05889e30c9c1099409f830855545051d88ac5821aa32a507293900710b802a4457a4e44054e5e749cb05004cc981c80a901d0bece0a40ad1159d223f2eb800001d54e84154d4a40a5114220a30696245871c889848299a62812a39e898a0105d2182c2e487263de45c89422451fbc3248a142756aa105d61420129509850208a130a50400a1426453f10edb81285480e49b980579b46d2c8c8c8e884c366a6a3686474b47538ec91917674448d4cd2c3e1281e9952464653e270148f5e47f275344d381cc523a3232323898351343a3a9246464646469ad1d1d1d1e4705823a3a3cdc8c8e848ce2323a323a3a368148f1887353232323aa23818c5c5618d8c38e270148d220e6b64746464b446468c83513c8a381c45a3233ed2240e6b6494e160148fe2913ca238ece270148f8ef868e2b047474712873d3a621c8ee251c4618f220e39643888bb1b7bb0d2640352203595545fd9b268645b86dc6166f4c573d1c3f27171c16030d14b4265c2603b666641d1c8d6d868249241a3f71c81d6b53f452313d60bc3a2d1f1dc6adbb66d196f9b8cdb4659a8f86c8c1c32465ef075534411cfc789466223e1f602df3eec3a7e875ba1101b6e853b1defa3e33b301dffed4e9c010505d71b93a24bdbe0702b81728cf0a50d24b634c18b0eb896d8c0075e6030c517d80c5cfbfd67d1f7718ba58035c7b6a9f2c56f6c29e0766c2e7a4926b3e29935cfd5f0ad7de31a16c98e37dd865b5cc665a7530db3d3e5b90c8ccd9dc06556f462e8d19359a66745b24fe7226f94a80cdce68084381d2f8ff375aca1c6c91835be09dc9014519be6ec1194de52d5f4765375ccda6196bcf6334bab0b2e18c6a61257f69e3b5abfcee68dc3adb73c90157ab8d3a748a3e0f66015163666f16d8c044b7484f5ee4e1861cde78094f89e4818f7c6aa78a363c7b3b724c27a6b18612d93cc2f7865f67e824abede4b303c6a397fa3e4d4b35249f57ecbe8211dee990ee579c1f8c5b20bfbe85179cbcb8ac3acf80803838b67fede8659f12b6e85ace687409acfab70d5f140b8c5c31ea7f95184696eaead9b0ebb0e57cddf1d8e1968a36b982c3aa7370645978602893e82b3975bf321abe97770cebdde7cc2970fbf87d9f95c59d627df9442d3059ff0e7a53703cb86e28d0ebfa636210ed727f294be5bc51ae5a3116e39c390def589f20a4ece2f98e619f8f2092c9a2f9f18a3f932353b09862b74bae9d32b00e5cb4f700ee993fce904fe34473bead1204f97dd3bf9d3e99203e34fa17c7ce62d603b96ad62d99e5d3b9775d25bb275d15bc0e6002ed1b51d0b97e8cab263c9aefd86ed58b61bb66b334a1074142dffcabc27926879497f7aa67aacaa676096edd929687472d1ef0a69cfaad1c995d580643aa5607499c02ba8204949f94ee7a2fd0aeeb0938b7e3ef5ed27b480514ecdbd03959c509f1e0cf134dd43f00914eeddbdcb0e8cc2ddfb908ce0360d181eb52a3e95fa07765faf00b1a6aa0f5f8713068b479d036f38cf092f1aec8d2969e18416bdd31b73a28b1348b4e3c01b94e7799ed671e00d87026f38cffb10534ff3967877424c6bde9253cbaf8780756535cb565f47ae53e5a23dba2815485a57b90f35adaf8c5e3365d588d2677f196dcf2ad25dd991ee3255a3ad22dd452b172424ae2d472e7a7a2d935c7da28023fa1b6e1a7ddbebfb81d61bee943ec67ac3d17aa4d44c695dd9b31965bcf580dba8e5dbd8115d9a635398e9ad3bc2ed4e38a4e7394edde806d7b700ef4636bcf2be5ad5dccbbede0dde5760778ebb194ddfdff0c2e2aa36b0eb9bdd7a3660e1f1ee58bef3f87a36f078575fa87ff4ebddf02919d1f24dbcd1f2927a36d45cf50ef48e02b1d41c75ea3960c7bd67a00d3557d517ea38be2b748e76cff90bb5e35e7dd5bc4381eba201b174dff11c10cb8ed71c0788e5d5bde61a181ef552efe88d3531a6b9f59268a7609453d36ba09253d3e338c745cf01a8e3780ac4827aea2af085baea1ff842fdfb7a0ea8f98e0f310ef0957ace3bf0a8b99fce691d5dcf012fd5bdbf52a7f97a36d47c477d7df772402caf97f7ef3767170d88e5f5ead695025fafdfc7552016f0587e2c3efe32c282739ae3f86bf5578ebf6cfe51cf06d455a7de0ddf6beaebc8953a0ff0155da94a411b50f4aa8ae5bbea9cd6496f01dd77542cde51d7bcacda50732cdd535f812fefa86a8445c7736ee86a961def9eaa462797ea1e6874727dbb42b486439a0a24d4bb6a747275cfae0253ff402fba6288dfbede02befaeaee552ea85f91d52750e8b567577d88b91a0e69eda7ca1e0cf1f21a18853efb908c59765c555fd1552b969bfae2f197ea393781db3b30cb8ee75c07f85a5dc7b9ec08a55e3092b223943a3bedd94cc47ac5e8d8c317aec2afe73cc288304dc49a486a02a6b48492154c9461620c134b5d47c19bad2e3175f6d8a7d6c8f4aea191e9ecb2b9d753b26b7416002db1f9832b609d5debac395447c11bfa0dbca155496737f5d6eb2911524617b0ce5312002d31250b4612ea39f5155d2fb0e67c7f3dc7c7578d70eebd4735c2b942fb771c4474bc0a44ba4bf51b10e9aeee29d028751ce7518dbae35055a3d453f7be037c1db96a2a1754bd820a927e126e14126e2c09a48ea7df8eae158874d76b7bfd8574975177ef35d701be7254a3ae3b8ebf8c688ea322dd85ba4d45baaba61ad154a4bbbaca4555b32071a9deddab595267ce9c39e30a379604ac632df26858313ad61e3e303aa4547c6928bbd43f526a53d71df5f995409fdfbc05a09efa2781b2a48eaa48aa7a45f623d7bce615e0a8b34aeb13ad2ae0c8f5b10bf569f46daf08837d3f6cacded0a3cee52ed4b387533aab37b4daf0c58738747cfc4aa054c5e2bdfbfc168dc4facc73c06130180ce5d9d01d555fa87728af33d271b4f1d7020e7c69f953166b7a52ea258ab2cbde5d7a34c89f923a7a06f0e1eb18c1a2afb573270f8638a47f7abdd3b3f0a8e3f6cca3e1f430f693f8d376e2c7f074fef496645e122a617cac9997844a9278ee9cd6450f86989d8bde4df7ce4b349a28534ae9a5e93b641d07c6e6d68be1f41de7c052cb9f7ee37120d6cb6d5df76e33f180c1f3505d8c3d52a91b1f57f2ddf8e8e1c52f9ed7c3f3c01e28eaf5b8a9072a557373d383c7b8b9a19937cff19bd4d7c5689323cde4dcdc809e4ade78d771ef9c07de58c1ad9bd3735fcd131e3f7d48d77830f0f8e9d45b227f3a47d331773d703caf8a92cec7bbef4a52dfdef9e8de7d35a492f2c01e958a51df3c8261d781b1716e6e3ec43d62b397e4e6d2a3813b3b0eb8dd35e56e4e6fbcafee2db366c7e8c110bf7d48ee00c3d83cbcf30077ec00b7573a40da8559f43940e906b33c100c5fad02c3170d18be5060f88ab40bb7a234d3f451bac163343d977527709bf34ef54689fc93cf6b5f4f86cc0a6e79a7e73ccf3b7b8f20d14d6fac8b3038308603653800db40990d8cf990ee7af79f5e5fef9a7ade8798f33a6f49eccd74d44d47a14ecfa11a753aa5fe755d1525a713f7eda7d3e95b0db90e4c65e009dcfe50a813b89d42a14cde1296f778af462b9845ff83a71fb018fdf5b5c27e1004c175c5ed041ebc227bcc3c1aa89764634778e922ee534fc79a69c12c7af66630f5a98615e0170e462f4977a31f3afe603c97bb5ebfd10b8a24da80b9c0c3241a454802e67ad5c2e5ae7fabe1e49e85f1db43ba448ca0e927509e03c31fdaf4f56660b5e94a4e27503ed3825ba6d3902ed1f42690979845c3ae69fcd2d4093d2fc52f3462d1d4a6e9bf7f9b3e5a71fa8e5ff8e9f46c00ff4bcf86ff55ff0a9ed62759ac57c7481eddf00f37c255cbbd1161d615762dff188e5a7bd1bcac6111b792f055e5ca76f9a2f9ece1a481d5a151d3f0870ef71b4825a7b7af4703e52e50d07207daed87787a4964bdb2550da4975c6ae90cf945dc374b9aff0952c9e9f8ea8c3e0b6546f7a0f496b0ae501a4eb08e9764421ebdb12eba34b744b19352cff3f87e8b46b42f2dcf030cb96fbe2b34a453e7d143f86e3ea4c3d8371fe25da19fe61ec2977d4887dcdba3b7e4e621b7173bd630f65643cf83a148effa6c47fce8c170d41978d411bc790a0c799c716678ea3838383812c707ce39d9e1e07c88bfcf870f1fe762f7813e7c9cbd243e5229140a752e762910858452cbcb887a8fe7e8706c8f21ab5b5d666d3fea086e60181fef3d25dbd0b2c767951ad1738b9c9704f514b8fd81db9c8e2e7af12b2e7a06a0b1ca40cf6d6fd01eefd1a3470fda23e7393ddea3474e8f1e38471d0785e2b818050f308c7d73e9e3a8fb088734cec39bf3330f06f99bd83847ede0c17128d9060ac5a150600fd906a3eacd121def711def11720f1e37351c8aeb4193503d7a703d7a805cd7e33deacd92d5b9afce9dc301abccc6f90d8e4d8645eaebcd103b3bad4743cf8ea7bee3a97329903b0eb87554ea70a0dec3ca51a33431b17ba062af97845b82036ec79b6e401e1f923cc0ed1da03606b3e65760f68559f33a406a0418be4e60f8ea30c3e2b5399e7a8eba9961d67caae2009d7cb2434d4ccf6f66343136a0938f5b1b835b31c3a2e72358033af962675fb8950a6952cf73920cb754aad3e9de921f7d22c3add327c7cc614e672fc9e90c865bf1f3dcf77de76217c1efeb0df1776e773049d985318afe2ebd24df23b8ad02b7bfca6098351f953893299a3e4de0b9a3ce2238c4dcb9254222a97d7a634963901aa83786c4d20696bad51bdb4097a5c6c122298aeed11b4bd2d21a70a3717a631a28a3399a4e3bb71cd7adb7d5f0d5db23187e1d0f824877815d04eb0bbcd1c9b5ecc2b69de33a105c5704e7b32d9ace759dc92403e532f0267efba86f966ccf1ec35663186bf8eaf8a38e5e92218e601177bce6d1d0d3b1de2ce19e3af754a546306b729fe7346fc98fe6bc73dc454f49fcf6e829c91ebdc7ac2eb3622de2ee50e7d64bd5d0a853cfc070ebace33db08a12efdb95d0dcfb726bab611525db5557f27dbb57c3ec347599e5dd5b6ea96a4825b6f7ad86cbacec5f0aec2a15a3ed0d0fdc4681546273dc3d70bb0339eede125673f566c9e9a69faa24c3ac79d34f4b70cbf4791ee1f646cf9bc0a8c4ac798e870e5f761d74d0e18bfd44fbf6bcc6c3c9f764fb7628dbe8792e761c8687932f7e6e356aa00f5f177d9d552a90ee7a31164a5f380173194d325c84a00b17160bbc8e5c3b1762888bcb10d715f1d4086ec936b8157b89de0e6599e6303dcf5ee848323a1c865fd00963143d1fbd5406536314fc42fd3c8f1ec217bbf476b8f5fce4d64d762a90ee02bf3759b5e183c160301778eed8f3cb2f809f8fe02a0a89a7208f05124fbd193c1beac14bcf868367ef00ebd2a99fec898fde01d655eb267be2d73bc0bac0bab2277ed627a779d4838520c1c9ef4e1895b865baaccdc617957a7eb778d363353d82db290e49b92d4fe77607790269873a4d7e77e22cfbb6fd74daa84703ab4ff127b07b066a59f613486b763ad77ddb3c18bc9f2ec1ed1dc87d486edc9e03b73dfa3d0a0c63113773cb6d1741ef26f06689bce9d2744e825a0ce9b94ac547cfadd7d5f0d5dde90391eefabefcc2575f46a92fbb70fa6bd905f9eff2f1eb296175fc23c8bd03f91fb8ae147845772e825e0d67c777e076024d1e0cd9e325783a076e1f92a7edf343d2b4cd6011776cfacc4b429f816111478f869ea6a713ec217c51a9b7a352c7d9105390611324c1a9fd8d168cea8d65404b841d41a6776353cc7950e0e3ded8114bbdff38d6ce60383510e92eadd3b4fad26e24a48c2e602e4ddba6b2edc06a2e7651a9885b2ef9d1f2546c1f625ac3a3a60c26a15d2035abe5ace1abe719dc40a4bbb66e43ba2b7b56c3f9c2565fdb8db42fbbc0e70fc9f946cf73dc31b8dfc075ad47836cfe1053908aec59a9c83367ce9c690d5c7621dc9813687411b712b756d2d0d3b24625ae5434233ea29c1d815be696396ebb23c9c3e3f69c16d1041dcff10824ed8d1911c5342289ce7a63461cd15e6fcc883052ad3756c4133a9ecbba05a3139fa9375644998ee7b46ec118c5b7b122c674b8355ff6c68a30a34fbdb122963a7ee3169f5b2da35372dc0db5ebb367265031a9dde1dbd810647a7b7b7ba77c30180c881d62f9e8256135af50ec7d1148fda36516e339dacd15a2bd9735943eacba68958155a8ec99e617699d9d93de92545389675a7e7d42f9ed5cd6cd15e25e25f43306794d86b143f9790dbc5942cfe7fa649ebe336fc98fa675d7477e322b5e825c6aa3b05ac6cfe9d1b0665a9ec128ac9635ae0f3ff392c8478f0656cbbaebc375d3e22401b7cca5e67727dc58338b5b1b4332b361a247837cf6e825d967e0cd3e8b4f7cf141dc0a7158dce21f01c240d1c53fb736568416cd746b187bc52c3e9f822c66cdbad3716b574474e98d1181d46150f3bdded810663a4802ed7012f692ec308bcf2c66f2bdf936dcda4b707b63bd3a4734ca28b8087cf1cb71510660c0883508f3c520be48e54de56bae38e0518c46c2adc30d68720f7fe54fcf4d109c0f670c1bb3f8dc7a0bc85ec3a3963772492f89fc905cef06ed597d1db95ef2ec921af83a72c58e5b93bf12287b58247bd68e597c5a27b3f8377cdbe16cb6c1c8c5e50a2a489a3eba26286b187b9e82a1ecf90cd43e2427b8ad81ec5acf06e98a1f62096e67e0ba26036d2e36e2a3c90c0306ccd3e370ab48b6dc9a8245b295c4f80916c99e31ee80db73935bdbdc6df492c87391ced3cb4b2f89ac145c66499039d949303ec91147e6c26df86d0c894cd3de181252afaa8d38eb567fe00cf0312bc5c5057ceb11e0a8e7ac310ee0052b05c044a2b1bc7caedbb9d8ed9f6ca562d4fb901fb72eb3f68b3121dae88d09e1c51442a9e5e4b838bd021cf5322b9c7dd491935e12ca5e018e5a76193d38bd1862671fe28d5b3730c4ce9e6dc75330f6ee4c19590ace00313e01bb8d18178605faba9ecda576550a20c20cb3b6b3f3b96ecc92979f34e3cb0ff172eb0606bebccc1e3fb915d23f91e7967cf68d5bdc59d7433cc44731c630dc2ee0e35242cc021ccdcf73a9025031eaf9f9f88d3deb04b86529a53c7f4e29a724e2965b1be3f246cbef7e412e3af171bd312e4974fca2b8dde246cf67400b060673ed61bd9f5c6a722bfb3e4befb95d21d439eea83b0adcf5e96ac825a1c21d0357436eeef11d181a75171b155a316aeef3a7ef0a998e5a1f540db9cb7b3781bb3e5e0dbbcbed0852d1ce9c3933859eefc0f0a8b3af0743ecf921e6c0ed13f864d62bb1b32be1ce2ebd25f35cc3a3e66f738f60183b5e7a3064479d036f9474f462e8beeb133f2487b803a9c433bd1d05de78316837d530b6e927308c7d3a978161ececdea747c37cf6f592741f626e89be8d71d1d2f3d9b9e5b85b2f06ef5c0d677392af6c8d3aaa464fc9ecec1cb71eaa86478d7a075ed9ba3b0786b1b9ef0a7535ec0e45a8777db8731f921c28cfc58e03e5d743552ab2b327c9ee8161b6643e5b30b0209a3b7d1fbd18e299eeeaae4fc8552af14c73a75f4f866daeee02315d9ec06d13189f81db1b1861eb43af81213f03b7d7e30ff1912966417097405b52ff57fb961ccfeec3dfb2e3a80791df3244fcea42be1268cb8efaa2b9e4f12d39e7bedf24d096215b747cc7f72b09b425477de5782af51daaa7c0e7f82b477da976bee3af1cef9efa16595fdbf6afbebe6bf22f595f5b1d22feb5ddc755f7beff24d096537d9dce7c6e477dd56b3aff71d6bee32ffe8efaa2f45f7d9dfefdb5e3dcb7ccf3a82f1b9bd3d497bca9be4c07b9bfc073f525e55fdc6f5ef37defea8bd29fea4bd6578f9ffec97f7f75ffea8bd6fc45df7315fefaae427dd9d81c477de1b8a6dd477dd9f8380e0dc755f84bbb0af5e5c3247dfc65daa943b06aeaabe63870fca606078e7a9dd3e93e7a9c4edcc904e2d89143253f8d4da71c72e370d014483bde76a852bc81da27bf938683a35d8e1d393630a5a2279349729f8643d57d394cdd0e95c61b9f5220c521298e1d72fbb1c2c7710ae4ce824a85d38f1f353b3869eae9f98bdfd363ca91a39ef56d67752bacf0d7e92bac006a5aeaf53ddde93d94c5fa0b3ceb076b4be1f85ebfc20ed557380b7fe5380b3d3d7f71ef51a1e72cfc65a23f7e70e0eb5914c759fce3c78f15fed2be427dfdf8a192674105157afcd5bd87e9f53d3ede4327070beff96bc77b582c9eab505faceba8f09ebf4ed7f9ebab3bafa9e11dafffd1a3c7757cf8f8cd7be8bcc75faaf7d8fee340fe4a1d481c827316fe4a9d85b8731d160ee4af1cd7f96b7b0f0b07a71ea7e7387f81c7897f71c7b90a3737d7f1515f3deaabc7757ee3e3377f75bf897fd1ab70d65fdf5991e7c75fda7fd417cf8fd7fae2b90f1f67fd255fff321d487dadb0c277eaeba6be6e5e53739cfae2c1e337f585f39a9adffc85e337f5c5e3e63cfeeaead0f6c4ef9c059d8ee63dea8b477df1788f77ddeb5fa7d7faa2d179fd8bab53b6279ee62cfc75aa3f6c4f3c0bf5b5421d22f67057a1be4ea7dbd497cd3915cefd65aa3770f575e28e535fa777a6777f81b586ed89c7f90b4795617be259f5f503c779eaabd657bd0ae077ea4be7aff5b544d0f2042fce8860091b407281620891441850404208b688e1da027e6847ddb6271eacafd7e7a8bb3df1397565cfde478f1dc7a9af9bd579d4d7d10b5250842531535401c60b5c3b8e9408c20c24bae0c113c434e1daf197aaaeb6277e477dadeaca1e213564f5fe95aadff6c4eba89becd9e7f84b561eb6273e477de1a84344d716d56dea2bf59a3ac410d716799afa52a19eaaaf2329a8900215529871c3084970c93da34c0aa0404209335d3cc1b5453ef5d75783b6273e555fa8bab227480d837affd2ea90ed89f7ea4af6ec5f5c71d89ef8aebeb83a04cbb525fba9be8eb0408b2398c00d1d942181cb5487b86b4b0e174d50410ccce0028522b8b6f0b5bfb6cada9e78adbeb2bab2c7a786437affa2f5db133feb277bf6fb2369d4c33e67b6c096b44471818f7f6eb1b815ce8f5bf23bdc8a2d6359c6b47cc72dd9b20fc4aeb0eb706bf9e5d67e4756e136227d1bcba2d41b0bc28d0e532dcf42cfa265d1a60d5dcab96a69264df0d2fbeb0a1b6e0ef20d8f7373751eb1661d5fc19a7f1dfc98f4ea7572e03c07bf86916c5cf34bb32c23bf34ef388acf3af5e5bdd683f5f5ddd4d710c79d477dcdd8aabea68efa92af32f65a1b9bd3d4d75c924b3975269d56dfea6bfaa8738cec31fd33f5c0a9af2b6cf0749c4f57299dc6347f934acd386ee2f36feacb3b8f8a83ece1e7e0d7d4d710d9c3d7ea8b0b1097f6aebee61759467e913dfc6547e5325fca569e8e9ad57c7f71ea2f3e4a2635272dc174d457f61c35d2d4d714d9c34ab287c7c81e56923dac84a3f2981d534689da643595e62fd35f48445c273e8dd1d497e9aa1a635f7dc52fa9fa8aa8fa9249b287bbca4bb0f86575008327244dce545f5ab874ae539d7c2422ae595fa61ac7c81efe7cc6a7f5c55be558cca030032780a1021c00119762172048218432a8c8a219710db038c106c4784309d7acb14c19a5b994b434631316934af38b2cf3a58cfc9255da658c541aa3442b4d9249f3212f6967ce4c810765dc4089a4592912c7e211766006109a0863866b5d9273f0811db440882f8ce05a97ac14267b981fcdf8e2430a6ba64bbd3a46e051e41c55701b1197961dd7c2a573cdec5c562e7a792e362ed68284e3d282ba162e412ed3a93b17968b3b971dd7a6694162b9b47009727dd7c265888be65c582ed5b9ac5c5ab4a02a97952b752e9f0b754f0b1796abe65ab86c2e9b6bd1c2e573e5b8162e77adce65e5d2711c5ab8dc35f7275ecbae0bf15ab2683b2a9721ae6c7fe2b9b05c74bf027dec4fbc0eb0c7fec4e70071f6271e07c8637fe26dc09bfd89af0173f6279e0644ed4fbc0af4f627fe0353fb139f026bf6271e05d2ec4fbc077edb427c07e6d89f780ec4b13ff127d0667fe24da08efd89dfc0d5b610af81dafec46760b73ff114e4f6277e82a7fd8997e0b63ff10c9af627de6815e506b86c9ecb74d12191e5a4da663ad1ef3b2aa594ac9d1d5c57b207a7878f9c2967e43132e9f5cdd3bc84b58cc15a1eb6ff7cc75fb8d8b7fa92b018c352f5b55d1bd3923e2bd3f2f3afaebeb80c7f9932e433a1945a6ee7bed3524b8f935a761f2fbd38e915975e1b936a78b112a7e23119adaf58e6f14b6a639d8499621ac326ec8b75434c65b42ff32be37d315de3b963beaf8b7bc84aded7b57d95e8c30ff570bf543daa6e4b5e57575cfd38c954bfadae968c6a5c5add5c597d4c5ad7ac2b7b58a68e229fbee076278c65b66b19fdfe12687e4fc14f705e035f38be812f1d37aa71699f7f5d614377edaf8c7bf657d29ca7a8cfd8e67dfb6b658f1235fdf4d715367c37ed189a3a8d4b3fd51cc75f57d840f39a3127d54f7f6d191cf5a5858b97e33ab4202171e13897e87a5d6183cd71fca5a3be72542ed18543dea64698ec91afa9af3846f6c8d3542ed175aaaf21aa3a45f6c89bea0b07d923ff552ed145eb2b2ec91ef954fd0b55b9449757a3d2abab5ca22babaf1a648f3c576392eca14b33a9a992e9618ccda5ec3b6688b6654e0fe39813fdbab2871b3355a31ad7fcbab48711e6daa40666200557b2277e82973d31da1c45d696b8dd09b5322dbf49a0f00b57e14356c7be2af4d9f727d4a5c974aa583cee7c3a71158ba9eb2a9653eab1ebd84725b616667de4d7b5a5fb0ba90557aa62e150154ba76566323312c8ab5b3caf6666648f7c57b7749df61846abe1b9ba85e3eac6620d57a7bae5f42cdbb79cea66217be4670dbf0e3333a6bac5f42c5bc592259e715d31bfae2da61abfc81e0dd6b1af4a767e14f37909e365633608d359b614bd7891405b7d6d5f2490b75258ca4202755b4c02719f7c0c23814ea68a659545562c973df148cab8e429d8b16f9edb1a462af31dfb60d8f5097d427ea88589918c2f92f1694a999950531213bd70875a182d8c048a5e648ffcb67ddf6ad5a116a6a5ec09df61f402d394b4309ad2aed161b69499c99600d06106cbbc6430fa858aa15f6c3a9c6328d21c73ea7026cd2c9268873226c9c82e32c66564973065580916c60b2b99f112463343222cdc7ac50c09b79651cc17cbf862f3c3e845db8e28a38ce076087165916366ce1e4102e2ca22dfe0b14790a68b8f2075387b04c9a6c71e41c2f1b1479076b49a3da2050900ae2ccce7126df6089286638f20a572ec11241d3af60852ce6a8f20fd70c9faca8ed4826b8f6841f27165916660f25c326f8f20316a8f209d527b0489e6db23483c547b04a9d2ec11a4155c5c5ff4482d647b444b16cd8534c4c5e7225d7b0489bae41124cfb4479070b8e411a41e2e7904490597ac2f79a416e21e41da788f207d728f20ad5c7c04e9ae23482c171fe1fa9a37aa71691a67995657947eb2be905a70c953a4165caf1ad7acaf2c521ad5b8905a7071fd8db238635c152977e72eb3180728051cb9f858e4b7c82a0412179fab11c773f18b9bad0438eafd2bbaacb072d4fb2b6a6c61bfa8fd99f34787477433ea0502b89d820b10520617675cfb0952798232aeadc2168ca4f9d0d4f2c77e3d07fce8a80320a00ccc4f701fbd2537d9570bd2e6da6eba06226d2eed0b86463630ccb5dd0472097269374aa252539ad51ab46fdbf0b9b62cab54524d2b15db51cb2109eb4d0357f6845b53e62420262688345df312b4e173cdef4a59a9a49a8a39c1953dcb1c9b5042ca1996104114c204d012df5c29026ef74c022b3a7684b55c1ab8e7655d303ceaa5125b7e376e808b1fe8c01757b2b067904aec573c8a1c008e5702690fbf4cab2b7be457f64cedd9e5794b72e300d3b3dbb05ddb4eab0da667f57505bda95ef6c82a3664dfeaeb933df2f30858d74af6d04c9e5cebd2d69581eb9a60c86ab025cb27b8d8219453cbcfcb1aced34a4536bd18b6a940baeb0a79e92d31f5ac610d2da5a9b98647a1027a63121c95d87cce4a6c537d126fba0ac6e890abc4f5a12fda9aca9ee97e3a71f491c3ecf42670cf2dd17cf735bae34cbc1e87a625f3dda3b7a4bbe9dceca2178376ce04769fde92edf1b1eefac490abe91c18b2e9cad654e4146061513cca221361c6f09b4a69b40a96e8ec72eb6ec021056166d3f81a6e20238f866471eb26fb90a6af815be1ce0ddc0a5938f0c0ad70b5610a30845b1bc3c24bd39d0ebb0e378c4e878bc672eb1d6e1b40d4159ec61863163766dff8a2ac37f60eb768957d51b68449f333fe462031c993cc2bc0573e460c74f617162c469b11c3c097a6bad5507e1f663064974bb28a0564ceea9278fe8a5bdae9713e9b580a943a03697fdcdaec540a539842af776681ec33309ee9f5600b64190644c7b32c63aa823b92fafee396f7bdcd0ae73b2c6e653fea13e85d038f38ee74f90ebcd16eba97d43305b09e379d5ba2d8826f632818d3d9977ade4341999ee7ce9dba0c9ce7b8a3286f3281948b1de5a8c8e652dc9fdc2cd94ebf6da6eacd70da4ca84d3b673a7ddb74aa306837ddd45d036367118613bde974a261fe549fd087f3568e3abbe6d1f024fbfc56c3ec5d353d8b9da540c95c767f5c5a52e7b2fb933dba8664079e2a95977c0a5c17c77529705d27703b3c6a0d5c62aa4fbccf244de6f31e7297537a4ab86735f4ced51beedbe9d953e2d51bae2ed19e9dbe69db136d06a96da61a7260d8fdc6f4bd315518e8b973f50476dc4dd993d3b91ac60e331ab8baeb53a9c433a64b2ef6c904c68e447ac3235b178d3010bd470d09e296348a4727ee86e038198327c3d210b9149096d3b55c2139ce046e8c99e34e762670c77805981e0d725dccd1e5960438d2406f340cd9320618ea2dd5dab94851a15112cb30d4dbd98b214a533152d2754e6b1d7b04386aa2b773b29b1e0c474a4d0587c88c4285464abb40c2ed994780a318648fd7b6eeb4d530ae8b337527705d26705dec29e167353c8546fde54b67ffc0cb2a6b283d1a2615d94fa456b31ae593f89b25a1059abfbd5e12ce989af9d2458629811bf159b69a96659a96655566670c149532b0cad6746620ad38e066311e818b54d504b7e06caf435da14979ddadd0eeeed230614abe2455b6652f3f7af2ae4fa63ddb9f5648abe1a63d5eabf1a78ef4cbd935eefd8906ae9ed68723acf9bb3ecc4034addf0f2d32175c6ce28be7b88d30f8e6a7d411ac4d2317d92b407706e33bf08917033f3e721b53f06dac045ffac485983e75778e935df462d86efa13e618bcf1d63b83dc9ed6cd5d9fd4e919443d0586fc10063eaa86913d18f8df87e407de2ce1a3ce4755f066c9a9f9a7e6ca637da4769640eb9267307594e6d170eaee3c56288cddddac8f7c5779a03ec411d6ebc5106154a83ec49f0452d599aae1d6d99ff04f0ff95b80a3189c4e43cc4d969e12fee9fb04b53ef2a9f591b09eeb235fdf8401d1de3913e7d5d4777d4c5eea281318cae68ee25e9435ca03aba052dd8738d51de5753781616c0e08574d3ff52e5569f56356566bd36a73146b4a70b1891280a09b284112bd3e2ab091edf5428423cca0144f90526e8c746bf8436f3c423e9c0bc6aa01cff3bceedc3dcff3bcef8ec75a388ee3388ee3be3b9c144c269369bb7693c964327d774c4dd0344dd334ed8b4800b9e831189bbfdefad08d59f4f1886f36a5f7562809af1019d30a25915f22dcc62d9fd6dab994bc94524a29378b6163c6ad37ab04c36dc158c4b7b11268697a5696813164533b53914aa550f7de9d7b2a954aa57ac071dce9a66fd7ce711cc78dc1ed0261bd0563586f7db46e7db4473016f165a7e1d69af66e85f8dabd15dad6cee08e66036ee50ea9d91d1cfdb31a76cb272318c2ad25e53ee5d45c8d72e2900f2536a1698d72e2cf1a9ebe9dfa8a359af6e9dcec38eb535d6651309c9d51e99dc04869a56c3a831c8564e766cc98cf25e18d35d770a8f99ca9a320fdc67a635744d1cb45739dccca321318ce0d0cb596d7c0104ad7f45992594d9112c129d13ecfcd6bf39ae9a6f0a8b38dd3a6a681db13d4ce317f7df6c936c3f6eca61a1eb569e3b618e3fc16638cdf267f8b317e63136fbcf1237fa618bc998f9f67f0667e82320c698f1c7771b207039578a64a513745090e0458200b0606dbce6d60387b5e9a6a152a5b0606eb229ade2e6551d7db4f5f8f862927b00a1524cdeb335f94f5e96195d38bb2254cdaf41c2a483aaecffc069aea2e90e9c1409fd5096e1bd8fb2ab36e9a1b929e93e7a247c108c6c5c973dc516f31e46f1294ac5d72a5f25a4945768cdaa9e068e736666da66b60a84d666d37691a95f846cf67a64b3094bff235940903a2c3ed54b4378038d35736fa649ecf5dab1bd8690fb7ad6a0fb753d9b404014457b99275fc15adad1cb5f621a981d937707bc1908a56a6e9b30ff156c43d6fba51126349f8191843edd919bcc2dbb9e9b7af07039557cf2434945103afed23f824560d94bcd5307eaf5d89ecd0ca51c3b0b33e91f5c99e1f332370455fbc92ecd933d37e4d5fd34fdf054fe067caaec4ceb258bf3ecbc54e7b778acd9d3ea44d8f5e9258c3989d3b759ab6243b5753a6472f32b17deb8a597b538dbdd94d3fd5f0a84ff1a60fc9c87127d3b675bc09d4b205c2a77381300cb363a5f26a7913287981f043021cc5a0e302e113e02806bd0b8467cb53912dbf26308ae053f231b8217dfc06dec44a25b65671c0c060cd4273b1db409fde675b7034a9e729fd8f0ee9f636d10a5519d254ec8f36088fdfad59d5c2c5c7951da9c66504b76c7a1e4ad30fe9d0a6b5648f5dbe301ad1f3e1b2d1f3affd277b98b0040b9a60c1973130982b7be432d8244106a008e20918b8b470f171c523d5b8f65ab8b04b3bd20baef80c447ac1f5bac286f8570db2673e2ebdaeb06148f6cc6bf575850dd9637d5df6cc6775c8ca9e582c3edca56d821036a0c2086654e1831cbce73b08dfba8e3ae0050c9860820b312858826b5dfb70880d87c15cd1086efde8199398a7135c0cc1277b725c9184154d68a1509e7f9a9fd3a8e5e31a3d2b0db379ad46c96a981d8a3c4199a635ca4359c35776098291d4197d68d461bca48772b4446b51168ca4a60f2fd09956a3ec1a4db32801d0126b5a97bc6c21a48c2e6af843cbc7fd74c01053f1da1ba5ce9c39b384cb4405acc7115224a154450525138481154dd9359a0a989032ba805d098096d80fb00523c9b50f2fd034885dc365aab05dc3b50f5f4d6b182f5748b8311294a08b625301cba1c609b20c0106736d7ded8da230e1040f80780306736d1516cec7704a4b1b543e50638a296881c15c33d43497809bdf9db94b35d870c3a2d1f29c9628cf0227b3e46f8842e46d60967c0dccaa41029d7be425b3e42ef1b04b2d2fa17caa70c7b47cf82e031f8d70cbefc8b33819576e8f3df94684b9993501ebda3e2f7bce5f6085e6e5719040a7cbf32081a24b7e8a04f22eff4334a25d9ea3bf991e78334fe0cd3c9da26b823570d7e834fd26eb7e93d51aba4d3677aa3774db4cdb844184d12c384a3f6e6ddf7f85342514e4be5e0cf4f334f272b35b2f49bc2909ade151531b908261ec2bb1c37825f69ce778e3f2449dfe245e5ebea867d881374a768de64ecddd70eb29d1c83457370a09b969e495a88d42e8e504a174327b569ff47edc1ad27b1338a47fb2e9281895bef815b336fb697bf4a86c8db33efb0dfc98b5d7c0afcfd6adb3cebadf7c83a3df9d702be3812fdc62316e699fdfc0708b3fbf85e1d6f6f970f3a2e7b928beb40abdb128909a935108117b9e5270ca37e5b76f60625b01e8b7ba858941b69804da92b8677e6eb1271ffd16db9298351fe5a3f54609c3602d6f0483f5931ae2e82b7389869542ac6985427f23c336dd4ebba8978846b6e7a6d4f3dc9cecb4cc4e03b7a49e5b5234c23dbf25c1ad8d450144cf6f5db8257b9e8b92a3443178c3a7020989cbf4d8148cad8137095897e937fc8d4501eb8d4171a695c8a6974d432322ac10fdfcb62481b8cf6f62245074cd6f632410eaf31b996864fb3c97fd86be025e740570d028f0863ebad8c58137b41e603b97e8e2fee8a2600ddd3730acc0179d7d362739ae9ca8f0a86f6a38fd46fb6cd93707f07ea3d51abc9a65cf98317d3677ec2196dd8159a28bab3759a5923ad354201171999e2575660a2e2ed165ba96ed54b36867ce9ce15eaf497c046110bf95e9d531ca8e286b64b4d1e1d6f15b156b747cc73fd89aad0fc7fae4d90acd31554451c51249324ae7e5334a29373beacd249964d682dbce5628da78b111a0d136dd08b068f9ef5ed89d5b1248bb3c101c1c66d9acd6bbd3f2dace3884c95e12a619cdd6474ac1450e7cf3f271031f9f86db22b40db3621fc5e8829c13a48f51a354a3944e9c3884c9f4138c3d9f559c39c1d893990c2e7e5ba158a3a841db304b7e5b21f97d2413d76725d765d626639442c66d85e8f71c95516e97d96576a95d7ecbe465762925a78138ccca380893824bb3c7ec37f3b1b96f261bd9a956719895d5b9adcfc69ee08ee41c70fcb9420cc6bcfca06d628d40e8e3ac4f8c6738866d2af10c8de05c9f98855bfab942d9f7748522488459f4637a08b3e8d70b719a5e86dd105d87c340a7d31f59a1afcf767a20dcfa98b59d3ea867fb0e036ddcb385371d03d970cf76fad5a243224d7fb342b12967027198b55da631c4df2eefc54baf98b5456ffb8d76a369df981731bd312f67b40db3b66754669b2a0eb3b6ba1a48d7677d36f6c623cad204dc52553c0ca766b99239d2c065e7b2e82539bdf34ecf71200c471d763f695fedfb0e0cb5c773b137e6658c5d1f0f0690ef81da4d606c8edbc0edde76dc1a6edf40de1a9ee3ae034ffd132739ef5bc3ad7fd0120410b0aed275958a95a3363dac4014a470a6adec929724886853ed6ab8dc72b4db40e63eb9acdbc0f3a5b7c4abe10fcd7dbbbaa71e0ca7eea7ed27a7ef562aaf0e659fbe9e92adb9fa643b87dbe312fe762af14c9b3e2487d8046e6fdb19b8e0e4e27c01b717f8e6c355d3efdca227c2ad95172b9a1e674853facf664fe937a6852bfa766bb8a5aa8e593657b8d14c05d291cb508317a459c798a7d7e85ba3bfc0973d486b859b0cdc0a3f1cb8a5fd08b7deda6f18a3b543805bb2b515d31a18d4da975b6087ebc510e3700c6a4bc410b4c6bde2d6c6a8e8c271258a4a3cd3fb714b5ebb0db7e635edda7747ab4fb68cf422a5e4cbe3acd0b67c8f1582815b1427e5630d5ab6605163cb52d2961aa8b1866b65cf961603051cf082cc139cc0856b650f7f59352bb358f1e1d621ab977bc2afa750eab9157df4933f845bfc49f146f36d98d57ca4597edd6eaaac76cca2b5eb8d4d9144cf6ac3acc851e06213df64d6c6afea6b09e42bd3f23612a7e51fc0c52d3e36416f6c0b2e9a9be88d69f144b37a632fc88192a22c653a3cd222ebd0072468d0fb54dce2935df4c6b248ea08a637b6022f1a486f4c056e442f86d317639a0a0ebd8fe1548689a66284eab0e8076aac9ae8b0c84b13dc0f3a2c2ae207b4432b3c50010b2e58ead04a164bbddf60b00983f59ee94dbd973be0a569195462cf7313a4b386317a4be4b9863228d3733e3605c3a39b25b48c9ea7657468e5a8e7294865cf9c39c347cdb44c73d1a5c1069be38e82b48c6630a7a317c39b3fc12b38622de2256ffe12f00983618c219e9154d61b25f1f231c4cb5ac475176d741137ad21ff4a6cf9a396604b106c2ee27a7f44233b81138ab03ead90d0a9f7bb46360a994fadd04a01288b3df1b3865b87d9101763accfbc377b8d0c71918315b23d6bc83534ea2bdc14a8123bde6473fab8aedb58fcf560e0e6c7c0cd1cc7651457fef2d5f4c6805044c7313e50c20719f001d298316e488e3b51374a642f2771cb447ce08330bd311f64d1eb0312b4a937e683273e36164c6f6fd017256002892ec840a28c335c14075720e14510471821082e1a7c7143726580db15279725551bb31eeeb0ea63d60dfdc6a6f046cb1b5a61889d49a2e7831848c6f84305b841072c9a596d4c181a415abc3230180ce6ba62636abcd1e12ea9e145878b4673cbde320a386209500143a0012a608831db4533171c0c47b1e5157084d2d1562a321c66f1571268e3ac2ef7ac54298088a43438353ab0a375b85cf4001688480d2bb57b01b4b9f6dc1e7d1b1333a655bdb132dae8f5c27c382194a0fe67f3312bda302bc665630b1b7cc006660c5103194c0604a14b14699c40074e08c335270f54d0f31db7b49e447aceb962c50f68734520dcc3925ca406dfaa01ebad37a6c6111dae3afc9624156662d0d1ab8034cca441268d35d8d41b4be38cde581a63a4116693698049c305d34c1a58f4c6d288a2c3d89b4608daeb8da571c4a46848010d24a03104347a804619687811ebd0f88246157d52f2d048a2eb8da181943273861bfdf5c6ce58438a30bdb133b2e870f69e61459f7a63673cd191a33963899a3392b0a160646fb8604616d101527c1b33a38dad3766c61abd3133c6e870ebfda2696fcc8c301ddf7dabc58c373a068de0dbd81963747c17e3eb3a805ba0efbdb50ea648ea556ca1570753c03a1e08b7b823918e5b871b106b5958a0550d1268ba76998fb4c2163a7e005c838f358408b742283b6d533b0ec1377b6366a4a0571288c53df1317b53130045187d07b42eca5ad6d668460900d0f29bfc3b49111c7c592fb7b2e6adcdf0926d6c8ee176871bb3466f6ccc181db2172dcff5c6c6d0a0d98ba69224462f3e34eae8842fbab13ef26154da317a633cd0a2c3f8844f1e6881a219d343243248b9da0a999140b18ced916779fa90d5d94321bd2b2444b281918af591d7c008c5b2e4658846a25214222fcf2b149f581ff9dd9e504856c345028bd6f05f7d5ce510be9b254ff8cb45286f46521771cf2bf301e8f596d09e55c28428a287c16045746bfe8683205e62074a104d1436e04050b70433efb43cb3c4c922096b40d991629ad019155c964d6e65d1867132117cd951154a3421082cb00111c29c717d1288a703496ce186185e9ac0c2956de716003a3b4b024d57f621b476cc9a67e2db9eef7667b20886e69c2b431007828ec42c0392d5d5764414c2f7d559ad0583e08b603a666d9c530cab8ff47e6885a6ac4f4c2d9121adfa3c94064405c6e68d66fbbe267c41aa8ebbd3f9c49db62f457342bde589e6f22c1aefc4ad040a5ac2172e98961f00b7ba6d6edb2e0f64bbfc10ee92935082fa74e92da189c2061be8d3a98d316b908100b3e29752ac15d17de9cd8e704f967537300b02ccca768dce5ec4055f18912212b7342fdcd2c0d81c05b7b866db4b44257a83045a6d9d984d4c11305f761924d08b7bb2675df6e84696fd066e75cf0e011cb8d5254332825ba7678f49d96312193ffb8b5bf15d7da3b36e677df8145c318b4df1095f7c78a4b3af186873657ff6ad66d7a89ccfbe3b597d12bfd0703fe79c73f78b4e90a19739f0c54309ea5dc934d8ec5aa869d9b5ec4fb48c6e966559986559f669e0c601c9d627d3b4a865f5f1e1bc4689accf3ecbaed52cab5bcd90f8bc70cb2dde5a2720ef7bce047212be09066606429d9347813bdcd2c0706b69bad6312b7aa00df7c45393f9b29b625866c9ba52eb6cd34e6770e7d65df8f5ace12a76df8e111f713c91c0edb6e6946c84f94995d845cc112ce2163fdccfddf0b3ee7a4a260c1665944270374a8a6687db43edd963a57d7aac8ff54609f7f858c31b25b168367dc83f6aaede28e9ce71efbacddbbca50decc00de4328e7bc6d56596090ccf69db766dab32cc01306bb3ec34639e40684f8e54f20ef7911727144edfb7002bf45a9f687ac8eaddc0c48744e404c24010e09e08b4dacf6d15c47d606cd662415a3d224d4df8584086706bbb96ba345d1b3ac2adedc8f6763a55283b4b70b2480210daf45903b3e253208ae5993a30b67703b74caacbd720af0237d9d36d120808f7c86b219196b18d2fdc303214a0061bc8f4e9a6cbdf7002e335309e879d63b21570360c04847be2379e5b9bfc46277ce1ce0908b74cf452d2cbeda6cb533d7df67aa65385d2f566dace52700bf4799f1dc7b4696f030315b10cdcc3f5a237888178e01ed351a96f00dca22b06ba41f6988064903da61731e3dbcec198a58559a60f71111e985ec405eb797cd3390f8c2a8e4bb4e9b1f9218649a01dee317ddbbef0abcb3b6d52c1a2e0469b1ebde01ac3c630dcbae16f8c81e196155a684338b008982fdc2902e6d31e8df0f16456c6d574bab5e906316e702a668e935e12ceab45b3190766f155e01acdffc2a486a0c02260768a80f9f81d08657df83248a03806f7986eda4c8f4c30991e61dc8a373d6a8948310b6e853b6df26205b7be700b0b6e85455a7ba7373d8ae19677d3e318dcea6e7a1ca34d5d8c15ca2eb5576773e0ec133899e5321d481003adcb04a64d5f718bdef44d02c99bfe49a019c79c4ad0f542e96e3029a57477f7457cf16210b13c05224098b505581f1b3a29a51f0476360065e7ccda775b125f7c18d473a565800b17640d7cb18a7cd16cfaad374a369c1d6ead321b4a50f3a12c989e3feaa33e6a2ed29ecba736c1b458cf9a358361d72b969366e16c1a190966c658ea78f6a2e3105fd8f56a1523912140e239a8e3975d42daa5950c412dcf5abeb06b0eea3965aacb17768d624f7693a3a7cca475365dcb6af3e1c469b37528df31cba667cffe98359bdbcd865bb37bb7a5c32cc0510d67cbca427cf147cda912ecb61d4bf9294f1f9f5039ebc6290c616d5a87524a29b3169a8febd3e17c71d29c5b6b5e763f915356c91a0476b240d9e9f92c725b87c383a03daf7949e6b729a59cc2407cf145b3e70e0eb3966a9aa669332c624e0b6ed66de92efd3efec9f225fdc4a1a7200e4d3f410ee28b9f45b4299db34eb9c53e7bdc6c9fed9f649359f24372ca6da50d77e05b1a2311b838679cbbf16836e8978242f8fe84d6d91b13814607e98d95614573a970c5e7d6c603c76b60b89aefc068f2c0e51e6aaadae9cde94f4cdf7e327dbba96e2cad863c347d56b7860ef75056cdff4e2c9562290ef6c58e33c48e5fca5862074b3bd0d21c173bba24360e1df7c21cdff1158ff36836be27aad3702a107513f8c5abdc68d5bb35c818438ee146cb31da6829b36e3d25a87f57729afbf7cca381e62ad54d60b86a93c994aa04386a4ef57d99f5fdbbea26d5516068f33d01723ca502555fcf00b1737c8855377d3ef366409de62a30e4a155cfbc194cffbe0c64f370b379f8b54dbd21c051dbfc4bfd3b8d95a34e551f72daa6de707f92bacdb9d46d9e4adda6b25235e4816553431e9ae634577d48aac0d0e699ead49321768ed38021cd51b5d9f8682a0d39aeaa4f723c559f74577d886d4028ab56fd03439a0a65d539aaa98650563cc070f6ead25be229e9ea6496574fafaae18ebacc5a7d326bf5cdf0d530b68ed77cbd1974bc4607181a758d0a945d738e7626b0e6d19b21a4b90a87b691b2a33743f89de62ad93a6a88a56b4e4fbd19b86b6e9ae13b4db5a9217d91ec9a87935926138e1a1e754dc5718ae3436c0271a8541554351b5f9154fd04164515c3be9b25b1691e9be65ff5cef54649fcf7f8af86a7fec027dcb773d153726a9aad0c237630a6b9e8cdc07ddb408e0644c56f6480e9eddcb9e5689702c355a76e03863cb48d4d7f5f6ee9f84aa5faf79b550dbffe9ee33ac065568e1a7ead7a0da8fa32d0cd73e4a8e1d6aa1ae2b8cd6b7e032ef7d4d470ebaf86dd531f9229706f0366c7018650564d732536cda7a7849be6d15b124ff3ad86dc69684054f40870440372b307034d0d63d31cf51458f30fb4b90a0c57adba4cfdc9779ba7bedbfcbb4d5d66a99e7a4d557d48d280dc2a30ecae35ea3420f70dcd9fa8fe9da63699ef4689eadf557599f555efa9ea29e146d527dc63d85528abe6eaf6fd3a24c243120a6b28abbe123b1e47c7af38c5846c630d08cc33cb27720a0e8da663628c310ee91a9845c5c418a31766ca340f5acff315ad9ff063dd3a49030e29c639c323de18679669ad6519a5fbf821e6ef8ce71863e448797e829c446a91720007b461d68a594af8429c1f191a800cdc0aa1ac5a7e2651b03bf3c96f18cde7ee03cb7ce1cf0c052e6ada762a5a6b463db32ed9e9cc42074be420a9a5a7647a200aa1976790ce24a2107ef492d0ca1e8842f812dc76c54b3e389915199c493f343d83f21c7734bb30eb888274562a5a4b593b666d31fecc8a59166e7722123e286ba63766c569c3ad048c11a659e88de9c08ae652bca56876f679fea1b7d5da744e1a9254b4de8c5aa39fda331085ecb34f709f816c441432b73292066e739cc4acade927c849e090a4a235a5d97c0652baf121d7ed5b9453e07627bcdcb4ae77a2a20d0e17c32f5c3557ab4c28ddbdc81e58d2344dd31e14b4f37daa237b1b9008f7f06b401af0a4ed2ca97842c149e1e353ba4b1d9332f06949f18ddee42e691915a60ff19e977bc2ad358e4908fa3e551130615704ccc7ddf40fdcb4a845ed282d6af7b477da230a0c5721ab8774ac55669fc0f05d34bfc848e08ec6d0bc686dd36078a27dbb06864b669ed36ab8645a7bf8a11eda780f57bd38340fdfbb4305d25d381eb26a1e02e97d38a4379cfd5181e3aa1ab00898cf74d291c34655736669e7d380b306c4398141ccd2ae0364e51842036e9f584324908dea7c9604c271be0a5c314bfb070e314b7b0a1c00b3b4a3401b98a5dd036f6096f60e8400b3b473200eeba31d07b8718fb6124806eed1cebbd41a0cdca72d8452350a4e1aa66870bb33bf44b37a634b6eb41863f48fde981856740e6062acd19cec681453492ec15d5ad33aab4974e5246669217d16cece1e72cdb44b0f86d8279b673544d13cdcbeaa67af5906aa79769b1a16cd4d02d55c16c936ddfbf71a70b927751a70b9e70b8b6473cf52a6d3371b1faa16cdd6ba83cdc6b7d522d95a77afc6f0247eb6569f74559b61d16c6ee32b921dbffcad61fc42db549ff035255c9fc4d3d62857e9a54703ed582bb7765a434eea2c034f52324bee304bb2ba556b8fdcdab34f1e1a4acf2984ef55873c6854626735caaa677d123fabfcfc102fadd1ef8d851184e62c3ef33c1a62493d9b5ba08f633d1b28ab61d16ced337ee91e462c3a6a9f9a119a764e9a5e122d3624a79784665996d4935b948d884616895b19e0246e694966ac359006ae93ccca485c6b153c723a3dab27d0548318892f0cda3616ebd5da275829277106a290f9a9512ab2292d83e2cf0b778408103091e5a46f7c479815631d29ddb64ddbe8b3ce8e749c603a7e88713ac618671db25bc3eff4ee16adfacca2aca659a6d5f0a8837af787ddbad0a6975959982028bbd43316e10b67470d15fed0cce5488ba737e677b8aee3c255d31a9e866a58d43284d2323d9cb29ddbc08e085f10b33ea0e553cd8e308b33133899a56535360581f404c35587abd5fcbe55c755f8eeeb59b7db704bfbf68d8156dbb6d5b941dfece8cd59a1ac7a0532aa20a3a5fc6c596fe48ffaabf9705504cc17ae1956fc0f122875d4c3cd7bf8759fd54c0d1228258f1ab37964be4eee929979b94b605d375ad6100aab23cc4bb2b2fec0ac08852f2ad123139bc4d0b8a465710a9f04c335c3140c174c371bdf82e93022f107beede1c7ffdc685395da4d6095d99c4623b8bd2d180d08d18599a6b3b9cff33b70b9c74c5c323197c165a6efb7cf3967d1909e6094a0e63ec130a86750cf4730dce9c87d192848f670500c0ae223beeefc30a853e76eb3f970563b3d51447ade9ba7a9bacc9aa7a3400f0c8734ad5566f3393094a1e9a597e454b98eab5076fa95451280e065b6095cd60c1ad3ab73848a530c7785f693ecdabbcec47135dc38300c6aee2f6e4a7345cd716038a43766993653f7ee0aed27f4f340d315bf31d0c660309816577c73e7be699d77fe32503cc2170269be693bea7c22dcdace50823af5ed747e0afc98c57d43811db3b87fe08a7bb87be06416770ada308b7bf4927075fb90dcbe659582b376f30afa1997f0853bf4bc4da99db36f91d20a25c8c80867ac60c98b61f21765c934ad4f66dd6a973103c1f159cc9a4066a6adb6ceeba8683584b2d3d969993599456b58447b7bb655d329b89324fb46c5a8e94625369ddde439e352d4aecf3cce3f66cd1a4209ea24eb456a83380429a1ac3ace56b2021955ec00ca6a367f8ae1b6865f6f77fa30fb66a010bef8ec3c39e9ebea3c0d8b66c7ef65c0452cbef85595e96cb8150e1912c4401f62a0bbf8321460856ae016377f7a914aae25d3928fc3e7f385acd0fc69ee7035a4c3aeb9095691af7265eb3d95f715aef79c04630cd69cec26e8a3b9d94d904773b49be0aab9ac9ba08e1ccd6ddd04713467ea2668d3dca99b604d735c37419ae6ba6e823fcd79dd04873487ea26d83597ea26786aeeeb26686a4ed54d306b8ea69b206daea69be06ccea6c3d14d909bcb61538323878e5aa5e86b21fb58ef969940848114d708b7f339dc1818b1ee76b825048c249a83f0faecf912e4f5d973d264667a45a02934328d0ccde4c586dac2e49de0947a82f33ad0c90d781b11a82f60a95313bea90495ca0734338d9a4e0c9b530d70c43a9ecbe1450b72e0b0a9a1517d2994d77127d3a6033524045c5ca3e3f6898f1f7d9abf5e7c69fee4ae11c0c5ef4e945f336474ecdbc7ba20958d1d591d953e1fc584bb346bc8923564f51823be984edfb69b4e9563646ccad0b0991a55163695bbc4ceadbc2ff59540ac146b662fb287b3903d5e207518cbec524fa42454974ee9a45446f59951fd3046a582915121a990caa892544966be2eb2879f458713298c14c270e1502da95435626a6a4ef31c39eab218078eba32d8d8d0d4a149435353836a9ee5ab79548a4a613892d9e298d3b7a8a218edebdaa28a4b1ad8b12f56ed31cc6743b314c38859da92e5bbaabee6355b54cff2d9542c352a558d64ac1c35c7d6875335fcbc1aae3eae863fd57065aa216bab4a1c5b336674d0022742c04612a0782d11b6641143461a3070bdf8096e4c0113023602d74b8291451044007bc20b5c2f0ec3a50d27106184332e19546490a4a04599a42e133695a6171920c1c5ba41970e27120e929a63ac301268c892040a12238186788c048a359f151b237b964c56c3ad0cade1870333b2677bc80b98ecd9fe82629a2db8dd0967acf746352ed55559d0d864f1c5e65f640fd3dca6a66251d5d985662ac52533a90fa9059a313bae834ccd55aa8a85c771dc2655b764497dcb0ae7aaabcedf0d8ec683c7cdf6954035b5e63c4c5f09b4a3c6af6b55b1a86a2a96efa7c7a4d87d2275de27cc435d9a913d66d84c1996316dbbcc62335d7e319d2ebd9c3e64db988c9463e6e9a598ef5952dcd7b5e5ab2b7bb2cbec1c38bbc4a52e4bcde71ec625321d32accc901bc4d88c04622fb287bfa16ab87d5e0dbf5557cd5433cc55f612615ea298ed5b5a4533cd0fd3252e7551ead2a54c98e632cd4bbb2481be94989ad3acc6d05c870e32aae7c8f12c925f58bee3c0f12cb26249dda6be6cce9f5d24d06b556b903df135e74f2509f4d251e369feca515f386afcf7974d8d4f9d3f4402d55496a419126e2a530dbf2f5c694322ade1b7ea708b97357c875ba38e3c56b1c1ed0ec79929135de18ae9fd0646d78ee9dda50ea598e945f6c036a42f693f6112e84aab2e5f12d2b67d52cc94528af9b22481d62566cc24d33cbd7c19239124d0962cf45bb46b5e4c9c1725cea4d4e55b5e482db84ce7ba2449a02dd9b350ad4aa48a257b566592440a2552f3a5981db391f9caaca41909c425ba2e7bf8524c128f21d325298be673920492cc5d9a3f2966c5493bf842f925aeebabf0eb188b64c89489b12fd14c982c604b3146121346f6f06338bd347f7a91406c050dd460230419b8818b3fbf4820d90128bc4145154f74e1e2cf2c2450e452040fce9839b303177fc624d04f0d40f083335cc0b8f8338c048a2c7802079098b001988bbb343fec22815ed1753a9bceac9d1fb398c2f17f9040a72a83ec61315cfc089340a65a83ec617e449240f586f36352c5a2551cb0d0ca83ece1f386e1924831ebc397629a2fa564c9dfa42bfb3257b78aae9abb903ad76a7be2797be22ca31d49fedcf881ea380a96e329a45e8ae3df529bab685ef33076e9fd72cfe66acbcec91a24d00b751da9d473d4e845ccf71d478d5fc6a82a97e852dda6d6542ed115c9d0ec55601cf381510c189740560d3fc81e79ee546f903df21b913626f1207be4c62e739796c2c487512964356bca0f99f334a8bb37743af72cf2f23268db4df7e2bbba7d12e8c5c59feab792402f53fc565797402f2d3eabb4b2644fbcdc5cc0ed4ec8b178f970cd7c3edca559c3ad21abb7866ba6654ce3cbe8b178470de1de05997e7a1895b46fcf22b1d0670f374c8751a94c876bc64c87514902bd5095257bf8de8b7b9deaca1e53fd640fbfb6bab247ab2bd9c3afac86693ead973d652450993264c88c690ea3d28a690ea312c77a758c4e47cc9305dcee8474a9f991075f48bd741809f44add8b04429d4ff9340b09949d4f6312883e05d2ec95792f0f05a2be9e02a47c5d6183fcfc4b96693e928dcb742190b84e2f308b760fcca26560168d8259b4fada2acd7c7c9b4a730cbdacaf59860b10578f0b81c4f5d5d791155d0891aa2f0b6c7101d2096e80c519d74b08242e547d1909610933ba7811c30157162da84ca8542a7335da584f928e318466684613001a63146030482c188dc843025dd4d4071400109fb0545a9f0ac42408720821438c2186800100001800184dc000a600c2c1d94553a2a299258205e45a745b0e0a532622fffa44a7ca3ce7ba36d808847f4fb94025b5514101edfd170a477ddf9bec2a9ff3b0fb520c84ba0a6e9bded66401f6c18b9d2397e62af84663026c1f3971e67e95202bca8faee684fd786305aa7e964d2a75de25ba76109d00aedebd41023dcf25a542524f8ef8db11074156b3eaaf18e433f3703ecd49e04812a5afd8875919c4c18881dd4dd11675ba62bb8b0576cb434b2d679d9430265fe522365e9741fb8f2b283296ae624a086caeb04516e678deefbc62774bd101702884cb21a23d6bfc2236d491e0716f800a0d8ddf2f1f87b9951b81df69dcc02e18c22c5a8afe2f6d62779aa69b59fafac618d224bbfffbc0760baec0050ddf8b682d452c2fce5d1c374e3a38c4f0fe7b94ea55ff4e3f5a69fe5677b39a40bc2b62adc6ec64f2994ec5bd6a646e78d89b02be14389d75a5d8504a423de9e4bb7f230c5d8534dcb9d4bb26214b4481a62aa2567ef300376766e7092216b97eda8b5c1d94cead18e171eacce317f79ab331bc56bf09855e49b85b458a2d938599e876c0d831ca0d289b69e5094a8d887c839b7df2cb755abdd2218c00a84f9699d528b75d481aebd03ba745b1321357205e85964dcce3f32e129e3306e5f0c46b2cef83ace0094861f777a27ed1205cdb559cc43fc404a260cb709773f47e730857001a8c0772b17e40d17ae373ec51f004da9f3f08ca4dbacf07090e2674d08731c485b6f5fb722feaa48248e6a581b194d8e1413f7d145ef591533b1efeeaf7a9eab9aefa69b615223a60f0b961e90206a0b20a1717db7bcdd458871e5b370da4adf45fe95527cfdce421129217fd7534f00b5047bbe274a617d345f81fe991e51d4c2ff500432c36ce02765cc706d28f1339ca8c2fc26b96a99b7bd50bd6679f15ffdecb87154da3e63878ac8963613baf92d77971ce201ad0f435de65b0cf6887558328e437dbf177acc9a1d894e7b39a5838d1a96e6e4393d77aa7cfc0ca570bfe220a4a8d84daa76b56f760748e6c80a734de07bea4fc44ed10cd97cb83783f4c442f5fb3d2e63cd8f93b03849139c5f40929c5c8f8fa8e8c3599b4fbfee879bbec1dcef2631f7843598056e5523c43c8a20f664c64c66eaabda986a8f6ce67fb2c7ffa6f4ee293266f56096292b981958c46c72fdc31af6a595ce4e75c813736124a5cc9840d877480e3b6d2b6b390b84e90ea6cf12e26740d102f8dc75ddef18b4171a7479d6580e7d9758efe5ae5b1a5c25c6e2eb19c680fb003583232b11c45b406ddfb1e2c28d5294862c8ffdfd336425cb80c348f7e34a012b41879f69cb0cbb8856ae9508019bca9af8e2041b6aa5445dd1d8d4ef9b9aa6b4620ef94c61851d4f9d55e866746257ce17729ee96303ea2bdd9bada05f9ca5bba1e707349ab2a14b4369e7aa7b19528a1aae7b3c46aad879ddb4817bf3468d6d395a96f159a23bbde48b47eb6a1c3aaf6280398e27363bdbe45fff1b96f053d687bde70b5a5bf2e4b643ec27dcd1c6558eaf4f982ddf1e0272cc2e7eb1b0af278e421a6676059b102c0ce9f8a36a88ab855dfaf808a4d5623b87be742ed2450cf6b5f707a644d4f4bc8407efafab476d81fed165a8510b251011097deaaedde8ef827dc37250074950b15920df1a8f28908afc9fea0163895a3761ce54d28385d384627ade7f781d819affbb9e3fc0124810da67fa5677500f5fbc7704c145abbd66a047d306e5af07c25847b3e2ac763897d77cac82b8b645c12364aa54e2baa71939cd679faa3130fdefcaf54e53394118f5763c95d7f5d167f8dbbd01c16aaf5543de4c563da6d769a69930ae1a34056dcf8901072ba252d51225cb1a76de7920c2052d00b07c46c31885ab01e8cfb31897ad8132248444b6444a5b62b69b98dc1bab790717917fbb5566789f062ab8eca12945d48ae1e719dc59ce3871cd6b0a72c64da714889571ca5c3c7e8a9e166978394315b7a3674af2c5483441e4834bb2fdadd570c4e71452d9969d502a1c1a3a5271f6ec07ac4d5b4739332d4098efd5cdbebc9c746136295494278ae60cf07768e725a22444e6d523e96f707feb14d76dcc9201cb66049c2b94e0fdf32a57057faeb2f2895aa9c5473ab22814395df5f31166c603b5e3de54c259891e1b283396f1ab1e140cf0439968e66fb364cf33e8328ea7eb97bcf1cdd13f058d750cd5c6e4149f5bd516927805a5700f995a35a3a3189d1a3a0c4c4f667cc4254cf2e0ddcc044cad15397fed22f81e4f7dc2bc1a9295ad0346ae5fc45c5a5fd9b184ee277fa462d59852bc661e5213d11c74e65d2bfd3627ba4c909a50da87690c499d495dc4fd7341c9c0b8bb3e27d0c3b6e70cbd3095259cbed550dfb406133a988a31bea2cbe5c20104d4b922b33719c36fa8c7164c5c65959d4eee0d69b1da935988c77b95e212df9ee886178d68bfa31e59e3f01c3b87d819a1c1210dd4facd2da5d425c48e3423b7b8bf50d9a87d8aeed26ccd27775812e335829d39080a3eb4dcb6fce58a4510e4e81340049ac22576c42a0562f164c880b9f32f6608424768d4491552cef8c307ee04ce8f81362ea88de1595cc00c8d9540006774816f9d7715d1ed55022d8ae809ce2a18c027b23b33b99957af39a766320af27903dd45244e56f12e4eb10dc0a56181a1bd967577b4a32313b23c1e1a030500a77d390e4c29721ebfeac3fe744a2bb91c6b34b328f010f2e2bc82a20ab75623d8e1d7b14018ea3dc0aad1b55a0235a8b1b1891b4343ff1971f9d6062075489b43c4085a4d1466bc4bd599def928bcfa5882a200549945d52a89cb84e6c0410184efd3a525ecaacc1248499fbe7bac0733fdbeded0628bbdde65a44e0f3d2e40a34fe80ee2091c9845b6e06828f9c86239d3c2207bd9ac2c7be7b49061ad5a47f9954c666505ffd4f1b1c7b27f4981790fea1886f4387096be84adce097ba850e9ad0eadff267fc1295cd43ad1464034aec41594704a559a2493324e33cc0df1b47238a81b698c012bd6e8578f6c20685cc6dc80c8598daa46f8da266b4897015ac9cfb8d33317bf8a564d539f8ea87daaf0bf7df89cb5b145f0f431c949429422e6317e586604505cde881aa913e77ad13017daede493cb069361105d735a49cd85ab782425dca4ccc2c500756ba4c1a17e7d763cbc0dd6c00366c6aff0e0c7aa8d4f51131c7372a6466bf93338c76531fb1535b787da4d3440db369302d4c31ddbf3d556558d5cbd91ab91a409b5d5492972fece24cf02e3c9b4fc154a2b9680f6b31e6c47cebcf41bc539efacf12a86a208eb386aa6b3ee2b2b786b09d88f7a542c15fbd6dc250c13730378cbb1be4e3206e5177fe0d43efa29d8eb407177190951563d5e0d67102548b0e9ad5b730a192eea74905d0e79cadbd3a479f8aab92d2709b1ae4b66bdb5ae27081c0fc858200458bff002db2269fb244e088768bca09eb693068363e2e3d3e2621d571b08c85b05e76dd54004099c979af73b74446c1ce5bf634bc144bcabc3887090722f36eff26dbe869fa016fffed61c2c13018a90695cc406e8f5f249b3cb07aacfa922ee5ce86c205239bcbe2b6616f82509a551f0d2b17832c7548531581f3adba1890312874136b7172c823fd47427d794407105c9441bc37e39002fb8196de88795870147e198fcd99d50e32d660b49b5fce164421c98285b55a21ede77da919df09563048614ef921960f4cd94f4b71d350b164ee2c9ebb5fe0484641fcbb87579a764a2c78a30ad507ed1053d5bf083cf206729a5420199cc0663fde2caaa4217fec92eb740038455cc29703794a3717880899667b02e8f5e82f40df4aa07a898ee484ddecad3ecee20f0fff3999327d85e5e2d91da284ff16f0a4eaa5c92cc48c5363e4dd90d2dc80cffa8577447ca50c70c7e2cac82ef7d0868bc3694476d07079b6ec58c93aa81b14f4c1fe8537997ff652dee6a79321c23f44e7f19f663656bd01accf39e0563f2c0bd16709fe01004c314dff27c85f9ee6de1a2a0778ccb566a0cd10b1c77e0b59ff901a8142d2a2273f1a8d24cd2d39b59b3b4d488b24dca424197569d81def01ac52d83986b9a2d4e028c0d507657be5f4942901483ab9cfa883ff864256bc3e7c452fd0b526ac4870b974982251c111412464622d576c3b2e497fb3e9fa4b4b4fe928d02f73f4e16b839bb091ca092159b6f625081fb2f38b7a89f98725cef1884b29b17fb06546441c5fa3aca4f9eee1858e2fe4974e4b5030d22c729b544817db2c9e287ec556a5e310977e1ee6a001c2f49801203be1ea7af19cdb50d920d4599d8096bd974f1dab3d1869d5a1a2b027dd0506700d07e21062b6c8700fab0b2e81d5242d40064e4c85344ea656b0a08f0843aee614d541d49b4d9eccdb6a2e553443a65c1072325e9f2037cd5f61bd4c352e93688348f5b47fb9a1567703f32ce309dd5267824fd7a402eafb8ff297257889f1b626d7449c0365cb3e9841ec278a52817672b9bc8521f859c74ef003fde958d7810516d1a14fad4d69db290d1d3bde7f394f057998148de17c9b704cf18506c187f6d610e6da0a1ac1aab4c1129c53c3e2bfb40fb493fc564ad38b2192ee7f58ffe3a79b17500571087cdf01b18633460f084b54cc30bbdbec173ed94517ccef4873cebc47aa3d02b99e6e190e2617de04f4aa93ba673474444321a7e6af1d474bad78be47abd5addd8dc5137050d353c123934d0926de88000266f9df0e8f5553b6a5e55970ead7d4c10a9bbd6f7930a95467fce07729b1ead57c07a8a5384f8fb58460295701705845c47646d6a7bf7dfb66ab5f3b1cd349a04c78f653e12b3e4692c5ac18526b9d586f27251f09b0ccb1689406b3f69dc52c372be8f53ef41a3d067d8dde47afd1e3d1d7a977c366f05b23b35684fa60de37479658adf4723896505832a0857973d286ed8ef3f536eac6c5f14a064a9a0772b4e323647687f978237d59aef8cdb8085407ddf3af149a5504d6f7bf663ba802dec1a5235403cf043c8c3d8b93101e88511d88b7480bd94e05217d4ad95adde27ca12eee5efecb42c25d8084585b96ba76117919d7864da9604ef33387f1ed823336fc118b210838f4f8ce4f98e172f48070aca1f277078d6a3558a2e8def2eba321bbb94af7908f62f0027650c893adf7761953cea5c4d34c8cb261c889fd7a8fa45358a2596b64e20c6f930433499b67c3f988521cd65bb29a5d9b380aef2aa0554176b211c4edf28bc403154de89b17e219864c17ccaf098c4cf59270ef9535c1bfe21e059be34ed89bf1c13622eae8c07a3d8514ff7f82373adfccd49c2c5c1a2ac85301e41b12a3c871461476979b278b294e4874ac86e70161b8b8daf838727c93d54660031d3b5686361f4be57955604dbf97c400d1452734755cb22f75542e2e8ee6ccc5fdb307476d8e1d7c9a4e0c1a87d79163cbd233ef349fd984fa682e5507b568de97ebae673721a7c87d8ac61787bd039001483d63c1ee981bf8e837a49e3f3f86a5dfd5cd639def58d81093c0f0f1e5efb0ccf9443754a8fae795f2517be6ce86736097e2e505b76b1d6703cf13d0ff360db06d890c3ea7232bc7394f45f446cf4c9d9c4780ec3ff3d6eb18220576d14353456a30eff2fe189ce334c3357ad2d6c7e652dde9e164661267e96435ab984a9c8d5d72732591d31e97f76029c6f7200e02925e975a95459d7dc901a56a53bb783ce74d140e66fd590e0c4843407826829f2dda521fbb9ab5e9d82f0720a542988435eb2607069a2616da17c4d8b5af302383ebf35593266232d222b40f47a7a2200fff6ef8f2ee3ac3a7e02b7d5dba90e13fde67999d916ffb95d111d10ddd853d8b0bb2d72becaf860a167a9d02ae0a66839e67c67ae097b43de063c1e7c0e838234c3b3004660aa6782df3e93561f4930bff0d810e1fc4675c0313f3a131defe4a844efb55e67f24f2cdcb15b16da0e8d569b8d310b26f89e678a2b82c60c7f5a803e742b77e5a30a5a95d9617042071c18a4e10f0f49ff5586cf6312ced0e58cb139f53b1c43878821d96b18395228adaa2241aed62964f5824012fd83a0044941c56a5eb56752121576d5fff7d8c87c82eb326da356af689d0087cd97d3509a7a16a81cea6af8001cff1dc01b565116f04b97535775dea4c607d2b6e24e594f624416bca0f19dbcc85aebdf0a3344400cd6ccf3751e69c236139abcd570515eba886f5ee3b602b1b6a98352366076c83fc72c13fa1c6ca9ca43abb684def62e785863db795ea95e855e11e9d6eb43c421cc51e807dde4a03e3030019b23664bfadcf4ef308c965a0f5b37f134ff449d10eabf6594e3f04814eea9428319087322c62633d093f72955234d19207b564906afc674beed9b0dff19078b17823bb20dc751b220f96329fe6aac63371c47bebd271a58a758aecd988ab4544392d0aac6bd9bc334891197f55b8fab42b401bcd2034e83c8334c35689ad256cf8ad7d7675024f372797e10a48a8f621d840f83247e8bff480b4bb613d0a391ae8573b3276430500cc1dadddff5d8fc584dd13804599f67f2a5cb1a2055000e8a4411afcdf785c109c3f6e3f9c7505f95232f63b2d7a1a748eeca382cc1a2a549d1393c440d5fd78c76513946297838b9a442c8b529c1baf587b6d21feb031d7cc91e863c8ccf86c61477de99b22870b500412de9a07037822327f37ab80aec8255d3725054796cbb537694d4356d81cf8c074f27caef892eb7a39ebbc5f52f8a4038f237aa90a596de82e2b1a2bd8c56cbe6bc8a926066725ada42b0cd139bd1acfebb46a45389902673297a9aded4c2a28fd3035b67115c9d67ee93834f03baa9d35dec59a73abd88de4fdd9619b0624c7971b7e62d32ab56a93a3698c6d25caa9c3b6538b17a13883cf861ecc74169b0a392991084fd74db5155736ba21454303d76e412a5962075c123fd8b94dafb32e30ebcc358084721a1541944c183b1b4e15e910bf4bb40eb395d3956e042cebd5be1ef91b3b626edcf7a2b11167c2c03af0050829686cd38942234a65fc0ea11db8f4f2bd9b80948b66c80e42d2f09d04f16fa2c49d3e154b125fa90d65216550df6a4f738b0b94c75734d54b2e60a1175efa7fc224244221c15334095f5b5d8909f876f8b31d5e6de6571d4301bd4387b3ecbeb2c495a0638db2e8eba1bf8e5eca4a23410387d46406cfeb07ff9aae02179dee9bd2cd8ec925fc04a21bf5d7c34a2fbee2b640a88c191355a0475153d894d65bd49b6d1a6b012551e51689f81862329cba2c47644a538a2dff90a768e9bf1b5b372cc5609af46a883473a1560189a62c284bf9631f78a52a02c0c8f2ff0334ea73e2ab3594f49a05dab44af17a4715bab152edbd1ba97cc33e404a639e53f9d4af792c2347926fc165543c1438453a982ca0c9b828a051efe27bc0df9d17a1602a39860d8b9b677efd588cf7b28ef71657f4e72507af59fcf84221f9e4131bec7a12b0a1cbd8833dce1874dcfde89200cb534c6ef2974a34306ac8668090f98ae4f37064bd1f919f4929fe882e4b13ecdb0a6e362c63aa100f15bc471f52bea26c820f4cbef3a187cce388354acf5cc243f6ab0a584ac796e4cded40a42d595ac4eeaf44b9b787c108359bbe0ed8adf96ef780c4ffc592ad4547db9263b724dd6aa8859f921cdb4545467ef16528fa8c960c15524046709dbe01d5a2b6915ab51943f9e95bc3ceaa4c51d6fe667d783b55bec041e0ef5944a2eec42f75a4da4e130e2dd9ae71de824e6d16bf87ab092506aab4b6537f6f59f3735e17c80271c173d520b12bc96838430e9d74063ae248d576b66c58d0e5479b210d1a3097f4e75be43977f8bd9b984bdb68edf60e76f5a9664a74fcb2d8bccbba37d7b13f1ea4007cb4a24314a5db55204f4c5b1c2f836ebfdf37af0feda52cbae3e4c4627ba5974489de886c4a44db9bafac964041712011cb28af0e5c5f8d25edcf170c8534e56923ce4e061c3556bebdf5ad0d8458843f55ad1fc19a0f4205ac592ba1be3fffdf6b1be62e745ee044e840a15cd80938369c6c7e5dad9e62639da26e60d206880f44d841fdc2abad2c2b576f4caafc1a6d8e8ccfc70dc005bd861d74a1dd0fd26c2294535114f7518ad18df70cff1d34f313408fb8e20875903bf271cfe99236b8a1e9b75931b8974c483c16eb91069e2d14f8e41fca9da15f6dc15868a0df2079f5197623c7758d7ca361026d7275cbb3a0d8046226d72ba19e63f1690d618046eeaf6e0721a9c20d0c39ede1ae2e45ffa28db7628cd5c665525a1969e85f86dca9a93335d1303e4b1a836b6484e4f20e351568738a109311f9e9b35a4cf1c61d2ef2ce22be58e1627b9330c1baa6d02d4e342ecd95c267b94a1ada8c80c3355b9080760bd49ad58c4806d92000792314f1a265412c50b6d411a292684230b94fd00f16af9c69bc5c7907f1055988b9ec9aaae4c6a5c063c016370ca982732ae4bbac36c96c0df0acf0ac2d9e6ec81cc2c13541ebc7f327b625fc38c4318985dc79502d60a4a6510ae81abb9d82332ae16d7a3b2f9238dd5ae29a5662c8d9b7789548c17b6a81ac47a391517370960e51a9ec7d524dd86b2752648aaaf57c305c7ae6e1e695d0455489ea8e28aa59e1ea6dd423f0e4048d4d3d740ef1f2e7942ffaa3046796c5c5ae3abac74cd75884a75bdd6da6e16c69b50cafe85a5a1688d12fae8ea5d3dc6a762cce599c9fa5ae9d4eb15da26127affabab60e7d1f765fb200333989d36786097f086708e35b2ba837ae8d8d20c7827a51143ad73c0203a005bf5819ac9ff8c18e949876d40791193cfe365441a0e6346ca7f0962bd208c3d16566091fb6af22d0a79ba4f81816bbe3d47498c195dfd0a8f4860bd032d6556379026fa53f71037d29918d20595f3a6826872efbf69fffeffffaff2f96461e27a7e7fa5b50205a06d92cfd66dc0b654fccb16f5b871c06467cec8ed5c359e9a63ea40a67924987b63bc777dc68600f2dbc3933b0076307bac4b5c2e58e2ccde36ceba948c6491030a489fe0b149ef9d303f9f72f9b7d409c959bf602fd6756ac5a34fee2b3541b12c97cd64005de2cb87021bdd88653e68b4564c0bd34f9085e120411f43cd6e6d708d6e238e44dfe24450dfdea6273ccd841bc111cdf390d1dab2ee1c2abd392e04f98491a462b3b56a1697ee050efd4c15759b7ae7a43b365a6051bfb173b739c3ac89b9a8df8c47e65ee8f22d258920981de746e780cb8c60d44890882cf30e4fff9019d11f4e482728f96fbfaf2ad2b320a3a43e02ebd04e1d72301f56f402371f86d5a13fe2f5e20446e5af2d0af6978da1e86deeca4253540d8dd3a31ad99e9cc778005fbd55f3183850c2a2262bf39efd2e6ea6fbc8fff02c7a6a342287f3a320897d332a200551b423063ce7f81c75185165d4ac0de2aa6c1bf5bcd6788d1a9961d385b6112880e4e9e334e9139465bd6ff313c42963797178dc1a25df12cd0fec6cb620ba262d81cb278568ace04ed2d63a022272b1565c33aa14c503e5e061032bb25014684eb652c9befd37920852c385a937552af17c79796c809ad25ca21edeefbeb3caec19be603736fa08b827eba1907199d28838706c42d6b34a9a75e28d97cda5a3cada69f78e3ae1c9866a4d060f84fdfb6719d48f0698e1d2d08160d60a3993698df5eb2e260280b5c31e2f010003255fb72e711152f19694db11ee11e522f2c444c280b651d01fead712fe2e0f49c6c467d843713b5dac5e6bdcdba7e09eb592b287b5163e1e80ccddf78d337960bce5c443953270bdaeaa3c03be5e616a87d2b6e5cf649e35e208d829f07100bb79c8545d53910f32cdf6f514c02c21aec8434c4a00ae43adda04e38ee4af64c89a0015db5a8cfcc8563cbc1fdf7945d23483505994698f90969fa8ec2e0d4852c5779ce720d084dcdbb4704a208dbf9025e886cf17e101de33148af81701a36f0eec0b66fb8929ff9909b9c1205c5d4a888674134068ec013c32158238d782ebbba488f2a39bf7b0566b3744e2a40b7b42d0c63ff3d14b5f70100c5686afaf4ebf4406099e42bcde4821b0623023ff06a78db3b4dbf0cab54a149c1d88d6b71fd20a499834ea207e66e5de6bbba14460a287d9a4e3814a1128e8e72988c81f05fbc3718bf90ccb33bc7d3e56bbced2ae6c1c7ab1ca20d572fb5af1320a74dcaecb797d78d035850d1d83c304b85dba4feb6b2172e5fa5722f05855a2841e745b5dd98511c4e44d82381a1658a0e0687c00206ee75ca97c37175a6e117d6a74258848c2b8b061caadc6906cf4e59c82b0c51fc4f06b296943be900401dface811e24cf35eb5d78d338bb1ca94c6328de0f5b0e1c1936a7152aa8b028b4a1071398f912b7f8b55c3612885b07decd99e05faf3eda82462010234cceb44239ffa22371b0ed8a5afdb416c1f136e8b7f4a18d3c9e000ded99c0873bae3e1d0251f1c301d6b1b0d69dc44ca61dccc19589b093a7901bc918ad44c508adc2426010a029df19aeaa4bdc5168e5a511dc7e08e11f74a1569a27ce4aaf1215eba3401020ca6f88c421246f7d7dcf71fe02a0f53ceecaf492f56b874883e299dd4e0f1f220acbebb95f6e97fa5b588e9338a73772750fa88bf7d0d5337440b87e693f8010c0f735d290b4987d66ad4b62bcd36c570f6a411ddd8e3fb5ed99caf5b42e765bd2373143face32ba12078bfd8aec4e07377b560afb020f4f7d983fbc2a083988ddfa978d34b11e774bca35b07cb7deacfa5eafac3625f90e8c766d50c12f83989302dee826d7a0649f1a2f73148d89f134c2443535cb35ce443200eb473708acaf1c10cf70ec87d816c53d7ee26eb123861d834e33e9713e0e42997f14555ff63aba33744820a5209da942470d46c47d782b693e0efd0c1e8aa1619637bf4f41f3e317e6f148000dff08dd4f1339e937e9688f65659eb16f243a0c3339cd47de46e7961cc92677927028121b37059b16bdb25a72878a8147938d9581b8f0b782d297eeabe20a0b3df0bdfa4455f729ae75c8e7a8edb34d14dfa09d4689ec6f9e0d2dd6cd658c20dc70e69ed2e27127ef8ec7e367b0c20ae618239fdc14f91115658e8d866fda06a15dba1ae7613bed668dba260355d15078cf22dd63490cdb8bfdb803d09fec65011c817c910f9a380c7cb8241e99d066efd42eda93c8636033adf8ec2e4e44ac067b80c9eade933bbe42537d33e71e193a908f2729fbaebb48d740ff23cac85d243ca59add0fe6c97b264a1ad3f44a0528eeea81a4e32c81217287800b893f7a1ddaccc19bdc07093cdd7a327beab932eb1962abe27bcf908d4ee3e4178ca2cfe45f5334f2e909d7ba5fc616c8974e0de790268f1a091f6ee9760660b5697efc305935e45e90a1540838b63b4bb05369f4656ab1ebaa388506a153dad0dec203db50d0fdbd49db126e1a5de5fcabfb894aac824f56e58038ab8a0eef60f0238f93f0ab3de711247aae2e5b1001a54690bfec2667b9dde76070ee80d82e9d471cc53a478c6083a5e5fc91219769ed87bc1afc5a417bb3f7d015136c4f997a0501d0da90e5130d8e00ea651c6dcf31198c3202c9bc61548f89d6d91f1ed300767b5811882108dddb0bfb1eb808e0371aa4c6fd3e19be1e4ddc1c266430b62e7e677ea8d27865313848e36ac68423b966bca5468c9126983e933659e4ad83f332caa278b4d42c05a34b3f26f4046cac49c1b47dedfab970dc013c53f2d59145304d108380764712c038cb05155750df8481e7989cd32c22596f3348672254890ab84634918f63347eb09fc3b39d82050a655090f5ce0bac673b5b529be849784f28e907ecaa5085f86f2e85eb212327f50641185ec13b5f43a035cf832e12896d63f24fac224754426230dd10fd69788c4f1c031b26f6e7a789013439f6d9be14ea8946302b0e0694f5c0ffeba4719ede724cafaf606543b07afd028075a08ac631a3921bbca44a824af5270221c024063f201fe1a8df9ef4769023d96b27f14f8b77e604ae5cd2be65e36b24753f0079277aa84b8a87e995349c1f2372a01b5ebe25b284ee825a0df6d4e4134688c58087f6ad9a7365679925c73dcf9c2457a9b1f363ff962f3fbf53ff5552ded9a1d63da4acd5693a853e6b089c2e487f9d7464ff18fe8af1f0ed5753c916853dfe7ac890b659b5ae5aa4874ab1c2349877b6781208eada1da28f75b6fae1dfd8d5605b67d100de821981a0a1047401eb67de32514974e11a12567e9da9c0ab3154e751ff87972d9677d06c73b21dc696d80fb5e0fde12dfe9ea47d816d18335eed2f041e680120e8848515dca74c69f637331cb9f0db443aa3deb69e981f1064618cdb770889eee9a25beb9e0428b9bb1e0194c62a5845944b01ea08e7ce1026a17f0cdc9ebad2a050b3306b4bb3065004f11ff6399307efeaeef2ea77f612c91c9e6b1392aad4205d0f7666b4b24373e5ca910bda3aec141dcfcf60d514efe01016d2f828c1cc01c3a61487c23673907f71bea8965ebd8d140cde667426707228a94d0171a71002b1dc212de099d6908e8c8878a4d8372fa48685d3aa11d785d931edaa552dd7c3687ee8d2c3965562981aab8c2b81258f207c1c8e459c6c65b4da6b8a6be13991a427f5b826f9993d2d9152c7c91b2e9e9475d52da8c2cbc1d40c2d0ff5c0012ae8db1fb9436c74c92f09fa99ff5c105e727fd20532b8dfe91180935558ea44d26b597a6c7c52ab1cb9bc4d47d9344e205471f4e0d46fadd966b2a3132967cd9cdab071e78feb8ef04471642c2761ad032664c0b53400d2caaa050b75e23b3c6391f1e8b82c78c0cc38d3d6374f613d1fea5ff3a98d46da12ff0aecdb5853249ad77ac54944d39ccc087888d8dde2a099c40350cffd0935ba2e1b49dd0290e57f3d6c79df1eecc77a3517745a8a4fca4c6652996406d700d7d17117d755f96e41925811770376c29c1c36de2894e59ea4c38f3e16234cf144a80ae24e11339de07208bbc02b38236b842b131338430eeab02ff9a6fb79deb51d8ea10a48cf5136a3960c2b46e3cdd1aea4f9d202cb82f138addd254505f741a503a8f221166072ee0a214165d6a99024e0b5aa6c3f3f10aa60caf7368950b5be5e9b9cc8c6a8925c6f8b7f30c8ea37aee239aaa248870af9f0c3d9153c08668aba2448754dc003bfded164a207110d23940fa826aece5b39af807b7a4339a3e2052bbb61cf9c61404c93f7a9d10a539dc1f40de3cafc38bae2ad5dcdb30b40abb61c36ac17409deea5da74676bf00c25c45acb9621219abe297451c325fe43f1418b3d26d52134ab0ba3baefbae8afb3b28bed09457b59651a51484e29c8f2fecb57d1bf2072565455e3f899c2df4d09a05d25c3f89f3c9ce75bfc30b1155332abe234987f882d469c0ff1a2d50d622f4154619e825f4491c876985307ad101c496a63767328cdadfe8f34c300f6fa077f41cba7ab69fc95dacfdbdf7b24b61ce901fd5eabbad1ff051cd3573695cad87dc65eab1712032ae72d74457df78771b114e1a61f84394b287594e7eee59fa49ca2f39823df67ad3d4444727ecf6ef509314969a2f14389c1105a5e1451a0f24b37d08ec8d738f89b50d6787400382a4325e5952911147028ce9cc5990691306b8b9c233727a841ddf9f5c82a3a965310d56f833d8d7963be6f292c41d7122930c30b041c16439620380b848d724356c21253100bb1c3292126196f2e0ae81801c8f9d10970e1669dbcc304b0744d8d12145021b4c1fac23620234063944a1a285f40e03c16b66a39913c8d5421983ad2eca9020a2b6594262c92652d4f9833986a4471b6a485f653328b547d105b4bca6e273d2ab7a3877494f24663982252992b5ce69258f836b0b09ceff610a350cce368d824a0fe4294f542b34aebc24ead0fc18ebb68d632b40d9028eccc2466872dabb6d2ac939552b7c296ef2473d3a9dc3bfda868324d6beab3d29e1892ad36c5ff5940e304e798c7ba554a2f1665d1454ac5368d4598f0984ae368327a277b2d010088e375df15a7b965be9413b63ad8a0dd7c42e1a6e1d107b21c2f39ab5005f380f4a3cd8f33019b26cb11b00bc8cd4ffeb87bbe82b524eb3c6509141f797b3d8c280fa26746c7e4b21071ce75bb170150f4fdaccd10e680b4a23ff1e38b565c2c0789a013cf8ad20bd0e1b4e353bb08893e1124150d1dec00943214c11eeb9c520bd4f66daa3ff7cf714c9080a3ff68846ac382793c474a5c57e359556c5f73e9e44c20fba63a236beff3c368ef8e0bba82161d9f59759490275c54ecffd58bbdb8d8afa833b8892af33ecad8e3b663c028b150d4971ee5e2a15c34ceef6f5dedcfa881ac772e38e5820b1bfa9b733bd0241a8a26bc7634512568326d78d8d81f9fbf3a6cfd302a2a6cd0b730032345db65c9e5f5715ad5a049e4f9809103474327b65b91e40fd3a9013f46be2cd0511af37f1a91ec7f1a2066c546644d77b8c520dac1a800075f4d7dc990262dd19aa7abd07333c5a7c50b62ec15c75e92d62848ebedfe91fec81812d937e0874e30fa0feeffa7cafadcf3a840c33599dde4e27bd065a0208b05dca334c85266a50696927164e058db26035fc37b43208254c537dc9d075049fc9192a7707600e05627ceda09d2797f5d9e7853c4e3c1ff0b1b04dfacf1547be49e80734aeb4e9955296d480592140b4b2625195a903f4a6ff37c21650d8172214a54b87c33436d9ba814cc8a7f92b7e00d6cd9dca21ae2f27bae9f784627f1420c1546739e4ead602e3aa183ffaadb26077c54495b4648c0170c2c933fa605e4b31b8c193ee043fde5001e74ff2ceeadb797d8b99b493c31192dc49b6f3a65bca627ef95ee0e80d2004a1f987809bb8043bb9fa293a8809ba369b03a2bfa2854d1624e48bc50f89ed899b79322fbf652a82335e418445588006a690c8310fd413d249f242a3fabb912d47b80f1275ed897ee6b1549bd6b3009483e983c6f2240197a8133d355fe98d552036e6e332f1878190bd9f0c55960bf9a8461efcf50ab6ab075ea82b306a3a726482ec30717cdba75c34827ea2cfd72738deceead79fe0d8e9090baa34e30412cc56786bf20ed46c45ebc5a677932b926fd01bf1372208b7d9068f5d3df0d36448852ecb1ceadab3ced064a6231587856b47e334400413683873187861652d58ed20adcd3b7bfbc199a64c60aa36119f8811a371d00481874ced6c2e5748c8bf3885f863f748e1deb44534125badf88ea4a6eb7e3155b641f4a5a4d38c0d54eff58739eebf32bce4783c0a9d39e2fd2b708c01ab34496f23c1aaa0c8c8c999d355896a22b84365402ac3ae28b4e4bb897fe72133bea0723a7a102523a3052b0780e6f62551fd3c66b45cf05cf6cb9e707fa4c4426974a6db97c355b9857b9b763383c5164644fb91767fb4a6fa731f5a056e8f9948ef5d91e56fdf6a610daa6e5aab976572004530d5b575c111270f9ccad17bec6a5f6bf4c0ccefe3ce79728115c788578ba521af714a923b841e99d08fd48b3570c217a8fa8c922b6c1ab8c05a754a17022de53d3467c5a75c2da6575e48bc3997415e5c307be9a83e5c2530e5080fe8eef911c25e8adb4735fd043fbda5cc3a45e239f8bee642ece317fcb68e7ef7c2d59df1ccc85c66b3b2b8131c37b441d97e4b7d6163348fc0bd0e72f515ae7c7888ec7d08a4bc87145135f58f47566c0d47e2b33b09c566aac2681028c20f6c735b0d0c442c40c1e1ed25a707ab2936dc52911ba73cc1f042e9c31860de16bade416710e36548ad37ba67df0d265b008802d13351f8a82602b6912625324b2e0744702d84f3f96bd4edc419ef00544e8bd49833db5152203e2314c91aefb701e3affee534af229ce0379f9f510d1602869a13dc218f1a87927439eb149efb53ff67ea6c53d8621fd6270c8f6c1bc00fb611a509bcce134f19498c8f985226f2015593f5e2c73c64da9872a822b2a079dcc6822662452c2ad5407bcd1a6c84381f60e9ea7a36b03da2a969d04732cbcbdf7d396d8b682ed66ce325f03f1f5e66be9449db8e0937c8058e4087b89947df90b0215d842f8ae70ed0426431bee794be4a118ea8a794ffbb3ae40528f9ea0431742898e4e9af8e1c48ea4a12c4acdf174d7245d3b9089b842251e7be0a0134ddff33f42d93820828e7d6f8613a8fe5520762d43f69af7d397c14bc55d1a8ad03d89e8774f895eb074cf3560b7758f261354e8cb6db1c3edf237a89c7ee3a515c50d76a1664ae862cbd45d241f066547ba7f962c2a7d62736481ae7630dc454fc4d950c7732e1be44c15d6001e24ba123c165ea4831d929dc65bb4a912afa333b59c229ad44de6fc7c1075d01851d9189ba22383e00675c1812b59f2b1ad540c6c5aeeb9ae9335fd5ca0b8e58b182bf1d458e11911ddb1f04552943483ec2cdc0b4493abc96b4c0db91fece11f4bf6a42231ce68b918386ae8020ca2f19753edde28905a0192c80ea727033af785dbbce56a71560f79277311daa1df66a9dc47825ca4c5100699f9b4aebb438705752600fcafc1a8c08c0004ec1201e2a48f0df19ff5d839abdc53f131a021762c5550ceddb59c5fc49dba4a363414e3b0f6d83c91c7e86f368d2303ae287c1c6e0c969b8ca7287ece25a0dc84f4bbeeb51f7e1073a534f1db5220c36cafc9f0d32b2f396d6359e6102b5c1f7e460d60108632cace2e802cf14eb10c826d081da150792b349560f4989c6b48ac00db2ad048a093bd122a82422a4b57f3be7249cde9dee199493831f0f888393b5671eae062438390dcdd970ea079b4806d175c1110fdb41cb88f217598dac84f624e01d1a2b1ad6400ee2095dabd5631beeca399115cae986fa5640e8e79803533fb9d3279d8ff8c63a5c99998d1ebf844e209960e6041638371fba1746df7778a1e0e513e6bdf0641680cf5c330b55e96377860d1527efda7697c37611a5be64935f0591933d96fa53b313fa43bfd10800a1f09806dab9f5f4db1448c7233b04e0f29d6cbf4f0de9e713cbcd46405702bdbe442758a934f28259899b5e28a0588eef5843f1f0414be0ce49f46b7594a6e030daa7b2c4fb226c057b8e0db8cd284c497670814c129397a39db7058a8f8e187b7f23548f90d1fc93398993807f69958de7d8c07fc7d6c47709e23c84131d33b03c80dd5e480685e55632a96d1136383ef88c2e44b39286fa1e3320c7223a004f9fcf1088037c51ac1058d6c873cca07bf9e0f29ba09609fac47921d4065a24946157a87c7f56b3416fa34fa1a6a1342a0860d13ccaaff835799cd3414cba1f07daaad66cb9dc6ea7dd9ae932389dbbec13ab7ac612855dbf8579e53e3b8dae13f5811c5865e05e772117ab6e9316f1a8e8e348c5ff74b465af58a8ce23bc35802a1ec64acad61f3132627058e68235062f65278d6dac7159bfa0980db6ba32a7066f9181312e4e0f85ed4c6c0c5c418d43cb0a5b8fd4232121e282d3a5ccff670949ddc03bda198dc608c7c87fe0dcc86dac8cada140244443bdc52322b75210488be01e52b7c530337cccb0f89c53d418d00ee3ab4e34be97ae8df7420abe02096e3b319779a982fd716741ab8ceb31b39a7083d3887f38257ef8b18a9020065fe8f3bdcab0bbabad8a07d643546070c34da088523ec9915427aa1a2f0dedd4930df81d1f3851404c5c8e8fb4f1b7139cf599a5e44a930dda8f4894e926e10be980020bca06de2affe6ad35e836526bb274a1c34d434d24dd5e94272100882363d3ca1b6039c530f8fda7ffaa46ca44887482d609e938d1c186929f0dd2c35d1ff8e0184af21996f8ca4cc3b11a04fa4d0581f8a989dafcd51311c29b7872fa708b37f9c2128f4063e433738dc80850cdfa01ce9a1ec87d211cb484f0ae49a0b8c1249d42201d4b1b3653351b25be4f0bbf941b84ff10c8908c85716e6c8af17296be3a892d1c87b2cda242d469a622f78771b962b09c08042b87a506247c19722b9042585375de00ef3f9f6fbe073be1916cd064384eba032a6abd9a087ce8464d25f67e09399e3051cabf10c869e54dca3e774c28e0e580e0d7697db4fbe61c769b8327d28cd595750695d729c5eb86466964c0e5a51c7d6830cff4a5bb2c0db40d37e9a9825b57d1e5a4e68008bb29b06df4e451c3cb608f07278c948c7d059ffc47f4ddd2212248182f6a0909b70e1cb8e157387bdfce15bb532189015256a0a53acc85269792539438872a5c5e992e3eb92b4ea95e45f99ff665cce546b66f08c4013a9575175a2089fe115c50032db4f7629e038b541e4b8af56955dd047b79abf2db6bf6d441ce208a616e7c8b9e44028f893dbaeab6ee88bf11eb5051889f50b5442472eb6e4a1b484f24c5b7b6a250c399d5c0a82c58e6b7942dc0041ca85685f103ef646591f8e249b6750ab6fb9a3cac145e484215285ebe4b1ea11da0a05235f148d646166cd17a534f419ba10f509a48a51b0066b92006da95be120f753a8a2bb606413c688992d78972a3e31e32aba0cb8e672255c0dca33fa158179cfe29e355c62813542474e683274c38debfa5b4146182544961e17f2ddedd491c49aefc53abf61f6a3483a50dc724a602e57b30d781750c8921b5cb2ed844b9e42afe90bc411da21f3154d3214878fb5616db361e74a0519456c927dc6e28e431485e3dd8895dbf86f7923447791d2368199009005cc515a1a1f0b1b81e956144a28fd647d38369c21b7843ebcfc00d05f9474be87aa63a086b3fbf3f931407711944ed1036a72428635e1d03e5f80b9e4145f5d0a73319205cbd5e431824b0e05a55f75fb11b673068e82c245794d5e96c6378d597b9eb0a8778086b20b06853c23433bc610c0ec51785edcbd7001866ffd70b40a31062b0a706215dd32fa97567052fc956dbc13395b57d7fa0d51b2ed35cb1e45fa701150af8c0da68f83123b957e94de757bfe4bc5a92efe21b195ce41dba784817c1ae2a3a1483a464a86c105c2d9047e8168b226b1646718d0d7599bcbe96c795a5496d45e48e150fc6182a4d819eb72080c9200b76525d65aab2bb4d84809342f274db4ccc00bcce8904017201ffedcba0c62611f072718e184411ac999f246b14c0a97cb6c9f4e4845e822e1d1d1d266743908b0263bc69d839e5a48ce9bc679abe5b85f3c10d7fc05a48a0ba0a462e336b79fb2d043a3cf3f22491d5ffa1889befbd3bd0b6046586f00f95a2b502bb9100a6cd6b4e65600fee17991b625087afc690ac27410a359d8d602f0c8c4899b8c872968944414db7a12e719c36f2e9c5f75615e4599946201aecafa34de5030dc70c7e74f67182eddd0b2d64ce5d7b72557e491350c17a8791e99d96710ef1aa1315d3aae40e68f5a4444c556c0d1cb7f3c446d8f9115ff875b7725eb70f689acd81f32d819849f834e3a30ddc55f292bda2f98293ba01bb6e73bd480e53aefb698d2f76507d33a6ead61dee820d181db9c85610c91a826c01dbe73929a0183bd695ec26883151f6017d776b108e26f32b8c14389eade1f9890861510485412e3a684999dc5c058bc09b4e06eaee0b4a24803047226a9b437761902067304c6032fd5555b621ca3990fc894de5aa3348c67d2843766abec6984d207819f890100a12c23ab34002aec42b1fcab63c252a701cdf08c119e3ff9827dbb6414229860ddb1366d02527de8691df076ec49ccbd0efc6005e48dcc79855c0c6c070d92b79cbbaed10cb5d5b5b1fc2c798908ef54f273bb8ee303a3ae7f45afe80a038c1776be59f7c331d3b0d7deaa45302b0e4f6956f4c4134a83a7267807253d72225f117feedc8c5747b4aa6fb1e3d022c2c357a773178f1462274c1d151d2d3a6b28ee80c381719445ab092779b34a9df97daa8857809dd663eb6e84078a023bf2890087fa9934a904a25e377b7ac4c4966c68dd645fa969f30cdca309bff1bb2c6fcd4977709c843d7da6d49ae7610d24823c381b0f512c42211a434a8256882b34575adc93c6634bdbc3ae20640240ad7e7c19e107f3162e671c7a8d4db51979e7a87dd9bac4dff8a7533cac3ca7ec9121a1de6702640171c1c395acfc64a7491ed81812d53460e4d31cc286f24c841442d82711488bbfe9bae6005213442a0424ff8de878c2098b42407c8cddcc583723d81c0a7e24cb558f38c5b88fa1cf2502ae22dff9c32d86b9c70b88839f73d8ccd63d3bca8ecabb8455cf53dd888f73944bdc361e12b6583d954dd12a14f43d71f654d119e4d3fcc2fee2fbfda27e8a30471d388b656b209ac6eb88aa025e9aa7e9e02cbd83a87ba1793e8e3d6cbc99e08f74794a63e94aae0ad927ffd060ae66e27a1a21b1994e19a15038c566cdd303954711ddc5f6cf609e4bd0d86602f1418120d3f213aa6761032b14d9eb242ba1108b33b65c75653236a77e6271161c3e158fa243085f8d61a26618822be0065c89baaecbbb8d122b206956197251738cffb6258beb53448d969b60f6b7dbe3329dc840bc4c578b87209fa33bd24c1991a2f24be0d191b80158b4bac41264a2cfd9e846fb510e6b37fae82fc9d560fabda67e2b29c9bb2a5c6b44afb3c0d28e0efceb9cdb58ebb24196a40aad70433e4b068cc695467ecc1c43d6637532a55f7b42f784a34792bde57242b4ddb72b801efe2663db5aa011de1cafe4332d37c7ee7f5fa4e526fc3fb6b1cd8e6b5c3cb0c7ac7aa789ea9d4a4d0b45c62ff16ed24695a760108496248beefc5f7d2f0513595f5541e0fc402592c93ea6c9a160e38d5009f43417460254670978d967c55e600640dd3568620306f5800b0265510c358c935d68b3a50805be39aeb44fe74bfd7249065c9331d914c6fc0213be24cd549d7769ed68f8ecdaa5c18b9d42559a1290512163b0b414cfc26d08096d582abb8846a191c7035281df2edfb85899594e29af2e28f269f6034783e939aa91ff560a71ddec47e43f2246191344b596edf24c5b3c96135cee105d1b63fe00d5ca88a3e19e49ef0c21e0e5b1477d966a9d3ab09e26b77c1cc2d79602643b4876a493d86e6fe61211e969755461ef008e1814c222b65ee5a6f64959fc5a5271e9871e5cea808fd05bf931791483a2cc86db3d31ef57505e5d293f73fccaf956204d88050023a37215f9fdf7a723bcc3530002b93a323d7c511593685e806a6a82c41758742f132ec3fe46f9b633844bb99531871516213b80f0cd8faab289a228dc90955464056ffae3fda62d7e78261d323c0d010320f84dc8fbcd82a1d66e77002a3b6b04e8652776febcfd400444fefeee08b11a5f691e2a0f10a99b11596c619a6b8799302c1d20fd27f3613d39b029832dbfa83f6e987606d5efa6ff05437d54088ed5e12eb85d190e6fb7491452136c53b39b8f3494bc111be9caeb9043bafa076b6401ea33beafe05e9373337e20cb60365e4644a4dc8fce41851c58a9027afa91e12bc9bd29cb4825c89990e9ef3e3e3c2a0f8875c921d7450736e449b3a4dcf1c6d85b477d5f90605e96f972aaebc740f57c5368b0326ba63a60330be901db8702c496dd55073b3556b49874b95054af146347fb7b0fcfecc5e560dec0a0dad267f82db0abaa2602cc90107972f25bc44d8336e340f68666aa720a2b3473a032642bc565066ed69e48fbb4f1b7b6b25a9209791d014fdab9f644d4929408271fbd39fd6ea8014ce9f8c73cc0d3eed727b58ebd6aeedaeba1439bcbaa1ba087b76ad83152feea531ef7fc04154d52e7ffb84688b8a32703b49497ba8fd3ca0fd935a40e80b4656e8caab2a661f8bf7f64060ea94eb8a017601b6b65a86fbdcaedf9f88cacf6c5664f6cf3d327ef7970da3a408dde698c9adcbf288c758baa3bec6c56e039ebda448a5a740d702cb51c124484e5fe067c9d84ffd7d74fd2c35a1ef9f85bf1ef0b19e9c4e0b7b56a5b0efeff1b811b8184c906e630cd6e3b0cd0803253dc6df6720cd826bc7968a4fcae01ac728500993a9bf43dfab089b957612a60946ff0a054ce8b8a22574a3a2a3741bc15cee76afb1a7c4d2fb30188f19a5a5c97523980a8b036fb7a73ca9a4135da9010e7687344a5696667371872d9dc7b0f573e83a306b25835acbd6d82fd4655f557350a5926aea9bc9001602bfef78219144125ed36dc718d8f68dfbc221e32826e75ff202b509f05d46223414473a1cef9c62401fa050253d9dc427d080e83f6d1043795b280659e014320041c1009b445757de9ae7d05094c793c065b272812ac2882be5d8ef2b24ec7cf5b0b19ebf457f7cccfcc78cf4717036c0c320f1aaf8329e4a1cc9918f774269529194a7c61d4b98b57817c633689d2dafa74b16e83152a5a4710af737b2a8bb218b88b217057be1b99f665954e916a95aa147f1aca11a7bf2a53981c16209a42e43f74ca03f2cd51a5ec3f096fb91637786edf52030715f8bb05e42ab005737f669343987424198f180c1b1d091f19ccb01e1be2c2f4dd81ff156da744c982db9572d101760b06ce8ec117932187011b2870b698e4741a255065a1a7bef743d7851f25ef7af88b05389afb74e4623af4060f27328c60862dd03f60e2e092e75ac8718b39ae3825d8886970e69b46040951da1ba18df44ab2e9184a5d11505e02b57af3764ad41d8baf6a09b418cbf1469c05a3dd4094628866246fc2acd9d71d11b63429fb630121f97290fcddac3ca5a7759b883a6f688c7738120e4b703000d0e90e6d01369fe4d4df01918d5c7ed70ec13e03403569106defd3e231153223bcd86911c860ac127f8c517a5d5e6ffce32ca921e301d2d93c30eb4ecc70dd42f42603ff65f32fa9d0bab10815d7781f08984d94665375e4afd2da520cffdbf405c6ee79e35054cbe1a3055e5d438d5cf0bb58ed416af6180618e2bf6961976a46ecd6767911180faa2fcff356cb86349b2cfb0678aedea53a41da34d30fc3ef8c6aa9a0b3482fc9dbb365d14e1350ffcb6260f91b6e18bbb4a7fd8d5bd2c1976a3e9d88254290ca81d90430be1dfe007c03982d30ca8231433003cdb5e674d10f0ee6df4c22daa4b8f059094114b940b509960be05ca97decc9959e3b919e28140d0770f62becc7820f6f955a57e6a2b222323eb77a54bf3074c0137e8fc4fdcfe08b02caa60af9c5aebcae6a4646b7d19ec3fb6b7a5e4c01935079c8372e129d66ee4f6e6160e04a940e3076cdc3ac60a1be15c7809ce9e1652829c6356d54ebf0481279d654cf244cdf22ec81295709c27b612b382e6a447b2ce161f648ec7a0333da72c7af7446b199c5b78182b65628a394ce4293b6e4b7decb9502ade7a252ffb378d4a9997044ceae7f16600e2a27e5f4cf317bf782698f5e8ab93b5909407df7724b8503ee1412a0eb6f9d54d1db721192f8d547cb61aa55b0473670133b46b2e07450761850c48d3ab4d40a9d43bf9a9100c3b424a3c5dad9900b02c94506a46b95685bb615a42d7de25c5e80f3ee5d2153cbcf14527fc0c603b60107c7a80adf718eb1cc96405113b8d02f07f16796434e9eec4aa4230f17aee99f3f88ac3171217c1d2c5def9b5e5d7a567c314fc5641cde8265150c2d8c396f836540a9631ebeb65158619a6cde19bc7a0917ee95d623130fb4aaefd70e24a0718c88e75711dc19983d1d00a9a1f8a7429072f2575901a56c195d4ae9afc1a0ac0bab0807938b2432fd4d26630230bbcc105aef1ea5c5965e0e537dc385da2381efe09da1cdfe872b3e57ea74be5f811a55a4369038dcb16a1e87122a60b3a5e8a219a6dc41a66abf6af59e4697bf3f7d924ba11bc8dc03614d14bfe6c70f5763f6a9779444a3f196646c1139f1c4b21a813cc9a80d39e61599850d54c002cfab648c852e85f893799f78d5e420e8f2cb312834dd4c82146dc456cb5d07662934dab65dcb35ebf1ca2b567c4940ee564854f6ea25912706d42094d6a23dad6a150ac1884c810154fc633670fa3852988fd6d563440cae2feb35047ba409286e2af782b69c1159c08d523acca4582e26f29043decbde4876a9c3f0c4ee5847bb9bc80d70171717f3a4bf8d005cff35c7080387ec65ec81a24e0edc11b2306a396e93e6441b15697d910d9c20203a970848a938a2ed07c67fb82dc2c4e37312de59aa691eeb67a5a87f531f74dcb516fb3e12c0063ed69b80da8b07a0c61e89e84ff62d2999f32bfab192b4a21b81ce097ee6f0541ac82a0db6cac0e6f0a5e2c8527fb7455af2a2d94f0e53f553ef4ee635f7cded4c485e0657df83ddb26112fd1499e08d8e1337572f972007b30ce47136430653802b04a1868b24be6f07351e026970b573bfcbe4e706c0071073a40add46ba4db1019dba8c3689ef64d6a401cb2a8099acc084652fb0eca614064bf2e79a1148e4bf7c79ba4f47c047f4a704ebd81b954cc8a17caebefc4d765c7febcd1418fcae664eb5b3840acbd326940cf0c1415bf79aaa02b7840a8dd9e18ab513a1cb48a006b46cd79b3ee72a0b3fac7715a40cae505f226d691e5f4b5e12aafc9440c46afa2ea1e0a9ae73c30f32063d42100130b147954068942d49ddf77b3397ded414bf3a1df622a8e4b0fc77dfb4b16f01f52f91e506b30c93433e0b5af633be49c9f40dbbc35bc7887797a99dfebf252680e2b3050277964f1a93a4ff8d35561f84aee99dd92d4087884d8ad1c6ab936c0ffe7cf4a939f736b42efb8186f97fd09a3dc15c02422ce3450ea4c5c191a9f6c4f856487a396b4b6dbb0d18cb939803fb918a757863b972be452cdb00066593b5b55190e52babc19e490cc40b635c5800798abf3a8c8896bac372face9ae3f40857ea06deca74542ec9afc8de3ae3a38e869704671437a91099995d0591845674ab567a6295a78abd8908ae2577df728ca7fa37e12017a474cf94bc48145ea3e87b24b7609101264fbecefa12dec3a92f63425ae08e70fd92063b04490b2dd1b421af24fefe4dbc6c9e0dbf452bbd94744a81d2c4ed63b18a2fbf9c9ee112e5025f13704959f5587398239b3c11f70ae52780d4de66820a366b14af60e580c75b4791b17a737fb79a008c418a93839abbacb3f2198052a2f2e86bb176136274e37291f48aae218477176a085739a15b92faba87af389986eda11e49600205a7219aaedcbd116d1ab4f4883460f344c3d28749520fde3c55ed5936b8e557cd12e74155af547b7f8101a0efa15e43ab49261055766b4d6e090e6709e41b4d62d72470f69456159b5af0b49b6182388fb8cd4337167da559e5e003b1974b01c8a88824f1c8fa4439c0199489878cbcc12147f38a9b9036bc53702c5c32bb3405a4e246433a279b67278ea2d1294b0402692e3ec064f7b24f2019e461e87d315692f0cd7a80ebb3d74f51757d9afc843dff3f4c8168c3edfa1c8b890d305b70a992cd91eb43e630dd916cf8c1ebfb0f1205740be7a7ae3d79d6ce6e6cc5f239ded7a8d1ae01f0517b10d4d7cfb41f5e10b08d88edfb7379cb8b14784d98ba399e24d8500b1eae6afe3b53fb43413624744a163239e73fce9ad202a3d965386babd0b602286480b07e59da8c0d6bcc71a1b0e0271bb596fa5340ee4758d6be1c2791f9d6d6fe169277f74e0af066a59ce4325365cc90df8c6ab7e8bc9300fcf3b9d33334edc38f224723d79a85867081c4ccea2ce550a5eb973c01bf037a69622970c357ead46b867bce4832d39e8344976b0f2902a3b06bd8cea4981ade0c8bded2e235a641a786557648f0b0c4da389a04c8281a556827949d03987eff4c32ba24ea2fd70bae8476580724035d024a5311b54de73e459528d88f20e70a473a38cd48a8fa96b826bd079a2c5910e3c6292cb937bb9804b59b836bcea6cee87cf35d74216702a3c5a90604d971c939da147fbab620600bf43f6336e6260218bbaf62d320ef1ea360df02a7d7df3b0f8c3e472b2912ea52fce0eda3208dcc5256a6dba43664c23abadce7cf6e906d2550c29700ca43d6b23b36845f148051c1e0adf85a178f3c87d6b9d01cdacd7aa8dea001ea9d1ce24591321ab518883b1e107a7b6d55b6bcec93356dd084e879ff22d55866397751386bd01393237825d30d0ce005c230e87e4fd0fe22a6a89eebd7a10d04d780a5624bb2657b5642155789bfdf0397372433b1c519532db2d2046552a13c574e64234e51e14ea2206122a069a638694d0013db363d50e6c5f0858ceaa9fa5797bce9e2fe96b3b07b30d7fc66fedade73a70717977f06947be0c539404daaaf7bf9fc07b24e7654da4951f24ce57a614c23c19f1b5cfcfc62ecae6a7f7b1db80963e802c7754f1532e53b4338ea1eda9e8975684fc2b7b5ef693c0afe49813b5803ff894acc7ac503fced347624653376263120f57147801c487b7d06b4a489c7cbe8a4d257b80e493c7581e0abdd1502d9665f6f7669a059a27fcef78771b153a3ef2cc2aa3c86d8422f9869962c2bfef8d8c35a9ac14fbf08ebb2bd74a1f0e58efd97aef23a37185f048fce21294de9dee17f1844dc39423e8e80fa46ba88aa9031c4b0dc05ae7810e12acac4399974fbcbc870eee1bb8c9737c5bd820c1d627e8152d1dc7c53f2e4305073246a70e38fd52c5dcd7e888a9ce29b4ea6591308ab30bcd61c905873b6ad781edb7c69fc33679f23cacd96f4d93fb543dff517a83452b78d366973dada30c3ef667f3b77180112a03a47ac61aa7561cbb1377b35f944cecbb70f2adf2090fbf36b355a4ba110ecbe8612680c2c4ce1c3b3d108c927a1295739eed73ad2344854d694aae5e3da8616514189cc45afb38c5c9614163f4d3b49381df57c06b1bd6d3b78f95c596eb5b4592e336d87a76d84b365547463bab704720a8b54bdce188f7a350468f80dae2bb90a4f693c8e59c3a06926611a94e6f7caa5c66de3cd960db34a7d250683e3ffb4210f0906b8a05ec02303377e66c236eb2649ce14e95cbf510a951fed229fb1acc07b2cdc8524da3b2c4da53c51c573d340062cf759aaa10af3eec1950d07f86f839e68fe1f2b7b1c4393dbd848c180ea8906036acf219931c7ab4b9537ded65be86525e3f6a2725e17f4d2ce1aca6388905240387c13b69b51c938800743a3328d6842bcb4ebb7694a5f67ad7a103ef716e18229cf8ef83ed27ff1ae9f5246285de14df42e59e92e19b543e9709a00cfcc068ceb545b0c3fe29c4e940e70e0b7c438e7f33c36d0496feea47897890fbfab388102efc713f78388cbdb800c07b27c7b3a4b250565407866b1ee8c1030d7807f21d00226fed60bb6107c39240c6daf0bda5737b0d050dd313c47d6ab2e418f9a858e2aec06d88c17176de2215065eda699bd94f15305e1aac8c737a89c682dad746e7719f6abab762eea51a7738ebc1b0595438f00065c7c0a6e428f3b42b6d5061e80953cc3ea3aba27849349b4d3c59542d59cd099122bfff13ee2fb9a512ac2e1d43c84cfeb06953960e735177d77ae84b3502645e06debd2c75a51fc6f27f0a060ddb6593a6566730f23ef57ccfe40dc8905d40104542a10ae070cf45a44ba4b20a3849f6bd550d52604359c9baa2720ee237bcdb6d8ad87ed0c53615555f5eaee554485dc77716eb237587d8d1624ddf7487e9f21512e5489a024092d35af1d9101f213dd1f4b8349ebcecf88fa8a51c095384b84cb8f951e445c55e931a169de92491f730ff5d7cade355c54ad03d5153e90575a3b9e18760ed877d247458c8395536316a5265b34e475f9fa0d8a3851eea3acf47b322b92d54c66cf7d1da10bc7d1b1b790e68c45cc1cce1f2c66667c603a40aea4d82b6ec9a8eee4f6ab49982971ae5a0d3d51b037102ec1e65cc9fe2d57efa3adefd13858ad4706f0e057abd0292a901850940faba635b0f4601c3cc47b17808fad9531972cc0098aa4159f7cfb67a240b216fa94d404b40624a77f75426cd7838c14c1c660374317245dcff8748cc5504f2082585bdb41e748fcc890100b5b5295a711f1a43b961a3bc63e59ed222f5586313ce2acc0957845b82464d2c530e18e05c0c80d37c83f014a5d2f52d7b3aeadebd85a392a8c47161d255c207447460724d8a09042f2463bfac902c4bb555a0679344246c2a38c06e4c62b3b184338fa586a91cdcfd195f8406ff99378ce481bd3846dec65a3d8984a2152070511d844e1d620d1a2e213822826a5585bc21d0f750e4236f3933616248930e35f2a7f7b5228c440ca9d14ac90aea63eb03259a4085e7944d571b3cf2dca973a37b3514db73b85fa396db54034c93dc7953708368586bf8c995c86cf867411a200bcf0460f7187d1bf4a433bc5bc3f41f1f84d1fe7790f2dda83d32a6ef038253f81fae9a1e1dd5da916ebb7086592ccbc00fe06046d9bcd6da41a414121c1cf135daeb76f1437adba486f9b559f36c90b30fd2cff0e41215c70cc5272d027e429e7bc70399efb7f638e3e91105462e3325afe56ed24f6f80709e5b7312cbc81b1a848d22325b8041185945e6aa623d0c5291d8cebf4197b5c6df2b8d3578dfcbb1b36e40ed9519107cefc1f59977b1a61484d64468935f94086f47638eccf9b8d1a43ea942caccbaf9ad423ff5630d0ebf8a5af5448895653d1b538032a12724b1e05046be492ecf54c70e1347fcceeb7bdfe9d40ffb5062cb125d42e3c8d11d16110b0b3ad5dd90e94e65526ee708da8a5ea4c6e89b52c6736ff2e83572e2679ca786fe1f47bff89e9e089c73d30102783aa15bac1a0c4f7d197ca09d4a03e29995fb331c4a58bc765bd021f5da7004922f647b01599fdcc1295e792d1a49c133dbf3022f4e44c9c460f20c5064fbb843667e2fe8c41a08f1f0c9946cedcbd0983401f7f0c09ed9c993b130681be3f18725a391377260c923efe3164347226eecc0c027dff614868e44cdc4f1864fafac190d0c899dd993348f4f18321a1cd99b89702402176d8ed08cd393737160602b58efb9ea424064588aeb9dcd3d0acefbccf9d2d1cb897efd089b92a9de53513bea44653dbc598a426124a1d28a60a849adcfd98e0eb8723f90948a50bc8a9ca635611b22a08924f28e82fddac4822b1bf4859f3114bc9a3006eb83edac35a1588056d143f7a2b1f182d75337f044500b34ca75f79a9d80aba43dd49789987b8113cbcb6871f8de7647a4dd6632d4c5431d84fef0d755a907ac06a2f112af8a9e4a81327d9a0fbd68d6045bd21bc680b381392c810224615e9cda5fbcdb9e5187ce45553770611a53ebc66adeb05a889cf2bafa71804bcaf0c98025ea2cc2e1ed4c8581f8b5d6cf7b1bf2da2f12f598af4650f1cf73c658f2b3fb0386b39a5b42ff5c7bbb50fd9fdf307f50f9a6fd33b6e3f7ae1a217b6dd2bf422ed17efa92a6014fb251f69c175cfac92c1779a5b878d1290ac9470412f1c197e74e92ba1075ba5cbd8da2a02aa52ab5fc21742d8b78ff2a0ac98b7aac7f0af54c5ebccd96b43c8b8a6e2e8e9c5aaf8cf1a0b47339a5bf4b1b24891607c0efb4af46289dd51fef4f8aa47a29ff177a5975c89270a0e7d3fe61bdc35b535a44d48873fc88ac5e422bfbaeaf32018bc96254e3acf82c67c3b0e86db87d5c868305eba5480a880b39fdb19377727ffdd30a2891ca8d00af120cce40432170e9be084f244cb31749b6e6c2ee08a23521cb7b3103f489afb54c10e0fddcc6e14abc47652331ba3e3fb99426e8c03c7a1f340e8ff2bf29bac21900dc21882e26243d8cb4522af1ca8297a44a715b50a3c6a8a44be3c0ca08a6e1a2c31c50524ac848e7ceed9cb9663a002e8a8316b85dbc59d6bdacd066e42d88b2c87f2dcf0e46d27f659b3b5d9a1f361eef4b6c6ad71d53d1812024e0c3ef54acab21bcffcf3f254962720e36b709857929ea4ecdb0bc2a3337d7abaac8ec8a0bf3b8a969d59c9f60efe919754387c3ec241921f30fb72909846500975bcd80325a73ae87cf35c298bad1899ec899901cd1c43dccecd122f6cd71d01d34b39f59f683b394d536cb5e63944fac5ecea6f48a6963cc43775fa1553b7990de54181f581e897d6fae6259a1af9c50359a0049543c7e8f80e964e0e674214f35978804ed669d8039de79f6b2430d83e91cc6d30555ae1e8b6413454a7d297964c8f32da9780b27f2610a8583dc79492cf66bcc85dca6567376f429f4c7430c64daa2bad8d3e601738c6f970995b126368eedc6500832f164cdc76febc7c70a9cfe1b22d37a9be0d22eba8e30de33f6759006c4049628df72c479c13c301182c9be1ffc85f8cee92d471f20d15e8e58cba5b887b271c2f74d8702a40d5dec0509cee3b491bc689733310fd38caac13b1d46328656a70d50ea709de4eb143e28000130b69b30c081bf6864766003a2149d3443d6a23059a5858e0933a6e2c7301c0b917e6af1eadbd919595e616726f5e3ce2d2ae38973ba31347227db324df30e3d9de8a69fee0c0a4e7c0d30538ead3398ed480636ddfb1f11cdcee240e9eb522a29c7da30140ebbcfe2a80978f048508506848778112bab9e3beee0bb45d8f9240628d74c0cab9a62afc18b87b1070c6473fd4cf7215c64371b1c51367b7fab733e287e634e7e8417514d61dd433334329da8c9f23908647fb819220b9845c2c9310009953f8bd440869605f4278e1fade0fb337a8f90fa5ca5c385efc069f09eaf672b492a3753d9103f7dfa81522a7138a9462dbe4a8493b1d85b0fa7e6576cbe37daac420624159a8280937b6ffd261db124ebb9db61df40f72be264e9697ecfd51a910e8601a0dc9eecf88b8228870f39a6f3262a4668b4774987fbac3111219cc38d179d9e2dc97ccd7d103cc5b9a82a2aac398041a47cc0134242fa21e7145aba04e312ac1673a17a44aa883625155dfd99c7775f06202c5bbb84db5a5126356c7aab42d88e424b1e10212b3c65c09558a1f7617809938f641f8865923d66db25127875d525ae08018351287aef06d30b8f1716242951b520a41e3c3674d78602599d137b6fe08407cc01679dde82bb8a229035c00c1f251c988bd5e26f52438901c9e95c1935a01845e2d030c21553be875b9389710830df98c21ea60a638e290fd674d208a9e08eccfb5953a69fcc31a4a334a142e3d56d6c47cc7ea08aae7a644484b8e7c7486cdbd54417dae90c8bb0cf056b36dd3dffa75d8c6c04690c2b381a7630254882a787ea7ef3fd6c094ec220f28f5a23777aa0f5b52940610ac604483b65d1d51ff78a03e06d2b265b7f422bddc8dc664dbe8bded1dca79075765a342021dd040f115ddd990b11e8ee06782788dea5f2de027116625947b120af12a513e0a71c7a6ac621c905d42e32ea8394e04f9c124bf325325841750f6b2c8c4eb0d46497e899d24f050bbc32648cc5022487dc70cfa02f314afd400dfa4752608c18eb261fa07950aa06457c50f73f072b122b9b4c435f3700b1d475d740b97ec925267e5268e479ec31962ae50780ca522dd44ffc8c58555f729bbe38b920c4c8f12be398773f06692549a0499c82356739b9097f50c4aa6835f2b312e243ddd3c44a7c7bafe1ee8f2e6d7c3202296288a533254bfa68d920d6148a65e7a24147c5e6dd22cf42a1f5809e764d5c699e83b23bec8d26162be87ad2ada6fd18f8dbfb53edb0b20a1dd16c66f713d5a09e1150a4fbcbd09703a511870916832ae9c7450d43cdd0403978f2a22fc0ae4b1f7f0b024bc1a2465708409398407f1bd3f8162b5de7aa20eff2022c0e653166c52b2f056f41ff0d9139e13666e9df3c0a7eaafd9366d3ac8d0f7a3b9cfe3139c710edb9e3843c153105c0669aab3fe5f416ab2e34b486d833c8d0b1b35d3ce46d9192fde2da681d6c866a23ce9341d9658795909ac9f5cba0e09e90420c9425348bbff2a22a1f3fc967e0b1e7de4fd0accaa1338c49e8dcffdab5504c870a6c224b2d9b0f5fab9c8541c836431100b4b9ddadc856ccf0086cf0b4afff256705bcf5f3d780893e6b5408708247cd1108977fbb03891655c26263182cc3672b47f235ee6326440431e347fd06fa85929c805bd7a867a9425e3d3144b4a48231a8db5a23a2c9a46c185ded954a911b2da6fd78e4e3b10a1f6905ede3bca93c9d5f5359ff6fec822102a2c3c00af0bd936e8a8fe16cee6ac8722b1356aa57b52cc2799ab7f8fbfc3dc8b5a4af253a45a077f857e36fb11540c3a58669cbeb476162ae49c54d67626be844425c540b1e83eacc14235201ab2f70404ef53eaafaa7ffa09c398eb8cb2ec6b408c5d19a74033c2d8187fe3ae1757aa901af08b6c62e36d4c6c600c466342462c14af56ecb965b5e8962933c44f84cf5eb54c7c66c367744d25acda01d3851d5884589cb8862d5f55daede91dbcd2108195f54e6c055d47719acf669a1b4c4ca3c92cbc1e573c93edfeb937350ef4605a02b486b3ba1e7a9e0fb6e01a4bce23c3cb434785793a8861019e06fcb200d07f329125265f5f7290bd654ff08a542fcba2255eb82539114f316f03f21bc938530837e75b631a02d6ead629cdbc20bdabfd24a0e174a4f6244f1a9c271e0284f49a6d970790347d8cb7109d1a846ab50d536fd463a47fb991e094680d6912d612afc50da4e360a3a360f53c559bc2d7e54b41602ec08927aed604e736ba57dfa84c1e898583d4aafe1598d809bec11d8fd83bf41f22dd054f928e1e2429f6bc25a5f90d66ed52c692aa7d130becff018460037a55bfb258200c5a351d575f5c2af1d94a6492bf661e4408bcab4105bead218333e18482f41d74f4c30b0a1c865e9bca379d7b5e66a3574ca74b6aad4657b30c276a74be5ebbeb03116804cae3131a55a089b6ddc86e6b7b6f29a59429c80a8e0a3d0c349f5236be42ec4ea45b6f72123d88e653cac6977527f27a10cd9b9c80dcc79b9c7ebcf426a71e977993d3cc476f728a79e84ea4bfbcc909f4a07c03ca252dfb4fa6f964a29e5c2b736d9689649916cb377722b38fb984e57e6552ccb776403dcc62eda07a931398c9da01759cbb7650dde966b176d041f576271b7d618def2b99da975ebe24fa52e84ba02f615fbabe74c302ded28d30ebabdf68df5b0781a99da9f3e92f677ae593487426319fb5d099c27cd2406702f359565c33e17c92d7996e3355b7b56bcd39829ee65bc5d13763571937425fba715d747a03f4a51bd85f7e03e64b37ac8f7e2346bacc6f9433efb9f1e3e334bf1104e42a6e08f912f51b35bf41e44b342fb1b861f31537a82fd5acc4b4b41442084b365faaf952902ff9f8d2cc97ac932ec2cb45a0de7f83fa12a5f95ca279f2e4f96a5b914f225b3ebd36944fa15a3e898054e43308289f351f5a3e7f7cf2499bf5e4b39ce5b32465f98c91f924ade718fa319f309bcf1c438f3dc7d0bff2d9be3f730cbd98cf90870f9758e4c993e7713e730cfdcd67873cbcf51307f836e708fa9a6f44f402192b7dc1c8d74c4462c2017ee84b05f81c34a146625a9a7d8ea0c7484c4bf673d49ae65bc55130846522d82bd762a2b7cb448b94c3e743a41cb00f9172d40f9172900f22e5b80f22e5903d46ca013e46ca513e520eb1916e769f46b2b9ac388af4a2b6cad855061313130e1c82306f1745d84be6ede448ca62de5ef6943ea3793b4df63e34c701fe8fe308faa5d9abf0f61af940ce94e3be0ac7713fc871d07ea9006ff376a22a830987cfd79c0907ec859c2907f836c7517f88890947f91638130ef1573891e3a8fd927d16de7eab329870c89e29477d16b9ba05a6ed22ea2bccdb45d4894cdc45d46de6ab8ba80f996217511732c32ea25e33c12ea2aec224bb887a90397611752013d645d469e6ac8ba8ff98b22ea2ee63c6ba887a8f597611f5d2ece922ea33d3a78ba8cbcca02ea21e3381ba883a69d2ba88fa68fe741175982964d6ba88ba68aae822eaa149d445d441d3d64545d4afb9a28ba85bd30293451751d76101b55de3ad324e1bf6fefab00a0594bf0eeef8f671a427b880eba2c884e38e641eed251d36fa68631dab5183f4a5d9bfbcc642089df45be471c44450f1349f2678582c9f3674487172d6189d2e00d451c3d70cf325fa95dea7394bbe7a38a7ca5797fafaf59fc0f3c4d66ff0ed7b628627f373bc7c75108c89501dac0fd2b7277d30749babd3dfb717dbc69982d5c1bfde4bb307fd0c9d08f339ee8335acfd91c6b08722cc1ea4ed01e5ba7a26fa38ec9918ba2317b41c01c31263c634d169b0d8c069024c1074aa705d7971c920e483eee85edb82940f3cb02902e4863348be00f1c40d35fc600506ae212497929f1eac966871b7a06fdf0aa22e109f889b5e5b2bef08a9652d0657136fa576d65a6bf319c39a49d6cf18474915c7864b882f5fe09aab07aeac3f7141683101c1355c520f825a537cf081a8e6367e98b2810b8614de5c99e2a5c9105a5b58729e184209130d9bd7191859064f19cff6b3c74f1f3f493f657ecefc2cfd8cf909f3f3e5e7e867e87e827e9e95e63f3ed26834ae6ffa306ce554106c744f8f564f4f4f564ffbf9e33e3efebcee8f597d3f26fdd107867d4c6b835ef998f47b4cfabc2eaaa992d755d21f63a4cb7c2449522693c19199f4c9126c0e068bbd5eaf11e6a48f3018cc4792e41169d287e9425ccde65eaf570983c1e8bfdae6428c310882346c0e5b6babeebd5436d74e69bb520efb515000e4afefd80897c71b81f2783b20af23b46f0744df89eaa0d552c912536163d0826649d27cb8c1ea2a8e103e298ee8806272c5051a8e0c61e60913752c135100f1a045c3ddc66fdf124ec8ea66ec5bcd2a4ff1b958a317f551ac97568582f30229970bb41c9147af3a767b77019babd608e6d5cbda0833e92e346dd8dc0b279a5a361242175dcc268c1eee7a37521206820df10573317498188a2efa68365921813201830ebc9d094e4d4e2f87f9989d5e6e82132cf4b05655ab97d9b503ac65839ad5aae26895a76ea3ba8d04d15f2e86a68d84d05f1efacb86db5cad553657eb15ae609c516c24fa75d73eceac68deb12512605efe748c6632d17cfc4533997e68f48a72a13e9f17cdeaaa3c8af5d4cbacf594723d751f38729efacf6b46565026731bcd4b1fd1631ecb26ecac93602321e63dde934dd8dd9e6b7b7209b503ea369acb5cc7aef431997c448f551763a2c7b20dc8676095d503651b3c4af5d469a60da8a72e33a7987e9c698904985bf771a62512b0bfdc271fa03fca75a6129a42071de625348d3f26d38fc7bcc6bc562ab36d8ee631d3e6e3a4ebd88d3f2613902f31916023013bcc61d904d0b1f72ee624d84880f9cc67d9849dcc1bd0bb998f346643e6346623e63f26fd8ed998e5ae1dd09859da7cbcba8e1dcd3c6b95cdfdf8086436a0774fd8613ed21809a0630732fb613ee60a6573d461d946f397d3b0395aa7b26cb46ce3ead8fd983ea60d9dd5719dca2aaa19bb8e1714ed11363f982146bcf7dedb0498bff7de7befb5f736c1c2dfebe2d55f27b3fede7befbd14dfdbc490bfb2bf4d30f97befbdd68295f6ed5b62cacfbe7d4b80017b3873e64c0688bc1004073748d880c399af5d3b4c0933870918282a2c4c905982cd93e2d107a049e41547dbbc6a6e2dde1a67d0b0b6664bcb84116f9928c2ad3dc25ab5183547fd9a3aeb349fb75afd568deeee8512469478aa815446caeb1f2f5788f065413dc96933df47d6e8ee0800049233bf213b8c59b36bef0edc1ad1ad5673d47f48224f1277d6d49288228939be24e6bc0e0fe814db915ed16fe8a059c9ba78620f4fea30ea98b4b6d62e7ae5939eb4e9411fcd137b08559388f36ef5d56b555fbfda1a5b80fd933acc5cb21484eb230e4db2ae50bebc17f072d05ff9c4d8a99275d1c31808972c69610c843037ed7900101ee8f43b06d6c00ee653c93a761ab38e4da5eb57242b8d99ba91824a1c1d5589e2d1086e21b839b97704374bb7aca567e8a2571fbafe7a99f74979b1f8620efa34df1cf8c14c86502b90f1882824a27a37ccae444e9eb746352b670e10394b9c20e785283966fee7db27878610899c2950725c7892d3e36374667c40433c72c91c3529c568f1f98822a20e981436308512375b45a264f8c126492c8aac0c8db25696466865a9287fda28067ed94a228adb8700d03fa02258a475c6cd9d29769ca1a18bf03286891b869022c51a3642c423974c596b52d2ca078c01f2c44490362edc3941159a24a03cbd918202cfe30f777cf8e10e474dca32f4e6fad06f18866158bec0d568255159d6fc881fc01564b1a8b5d10cf1e52d6ab71a91d788fc56731ea26acd6b44332c9803901934daf741cde7a356abc5d039514db446b717ed9b41a3e6b823b4fca9132b9e62fc213b478d74946251a782fc9226a62ca9d7ce30eb2a8e7a086e7f14a3e2e8093cc230745dc51d857eea62541cd5592332d485473c7dd8631786614892d8bcd14a93acd51cca53a73b2269442abe7d472cf9fbed3b82eacfdb9582ea00a4ca57a76960cecf44d1ecf72ae39ea108d7c3bce8a1115b1e2445b37a29afc3407cfd450b1d966d35c05726dd8a4aa1d7588dd0c5df2ac3ac143ae8275971b1048039ccee9928ca087aadca20a2b51171fe3a7623d47c8b6f5f114c7eb4b52ae3ac8e495acd4338ed933d0ff851956b5909f4eaa2d3b07962279d66259cad91a9f2bc4374089616c148c560f1b83d0ff8c1e5c9daf38028ae8aeb1f2b79abed5e6bf4e2d1da47049e9bf524f3c591f2e72dced39fba0bfe8cf194bed9fab37d1de6a95f5b471b0ff801e70765e471d43fdbb7f5d52df501bc8d2d007c6af38c7e51bd4651f69f942a0cd58c8aabce426936edae55e12db7204762dfd0deb993c5420f60b44e406277d6becc834d8466698d54b0c40c912966861831c48e96ad1011f6fdf37143c5c2d77d48f592f8f0f5b80df1e1e5e9e6a34b8f9b1d727db0f0e1f7cfc7923f75595b468ac954354f6dfd3df97e3d76e80991b236df6c73d47f3d1e7fefbd17ac8160d7df1fbb7befc5d9fa8831362a6b8efafd3d35f1f73a79efcd5197567341dfbf2736fffafe3d65fd59faddb2503ca4c0eea2504c8307c403f6d8f261a9d31d61a781dd460f288f9dc4f8621ceaf0edd86f78ebcf178f1d742e6b71fdae9539c4bf16044110f479aa4317b5878de4f31804bb8b28982b985b3473dd56bdf5211fe1f7af4798cff251070300749c0924b69c28e2de3ab54e175947ba6155e822eb95cecd548d74a9bacc7717f9496fb654f6a9f4794b659334525b07a9d1ef38d3392ae377ac695cff297b1bc3f79f3ebf634ce3a807bfa34c6fd0556497ad366d7b94fde311e7cf1f8f257f865f7f3cda7cfdf1b68c7a57fdb703cf53acb73e5a1fef2f8062fd8d8940c52cdd9e7e89e6a158d483feae77cadab7d3288d74833e3d8dd245ed48375ce8a27617dee6259ae7b11ae9ba15f3631ae9a46f33c5eaa2f6315dd44e756824eaed8d64f392db3cd66bff786dfe14af00c6aea0d7ebb69a43a82f7ae84715f412749ae82b6baec11a98abfe32c59aab2e86f7c723f3ddc3770c841b682b3de2fb8e5da7d8fafe7dfba698f2e36c6c6b34b4c2db6990c01a5d6f22efd1db67582398b77fc01a65e0cdc2db56faccdb2f608db277ccdb7420eff612acd18f3706de3dde8eb346427ef3f613582315de2d62b466deb20b87e12f3cc86c917bb7167e81fb9818e45e0e03c7b9ccccb907a3c8839c34cddcbb20bbe92f3383dc2b0af2172e9a2c720f97816be0a169cbbd6cfacd417345eed940b72651ee65a081e77cc8ecad70d059500762e1440ee6a8173b0bbc347b2c72948b5d4fe62c88dce6a3d923ca5140bb9ee844394ab6735f917b435eba90d91b6d0ee434b36703f2153e337b4039caee7a352f57f8cc61331f7d458e2ac2666f96a306b0eb91ce62cc51446ecb51b45d0fbbcd7fcc9e0b18394a68d77b399117e52871d7b36ef36bf6827294cfae17e4e58b1c45773d205fe12e7214b8ebcd7a1ae428dbae07ba2d97a36ebb9e90978e81c770396ab6ebc59c856790a38e76bdd0891c831c05dbf57e7c85f798bd16dea3a76377418eca60d7bb6ef39ca372bb9e0a2f732f7b94d9ebd1d3b1bbe52802ec7aa5b360e1b0dc03f21ecd7b3fdeeb711f6f91a38c763d9813e5dc03bd87bd77bde7668eaabb5e8faf70377bd56db9c722f746efc1bcf7f25ee8a247d19dcd2d307b345f917b517447947ba5f766de93798ff498db726fc87b42deab792fc8550899389b6baf99366cae5d8579029b6b0f326995cdb5039934536773ed3f660936d7ee63529ecd59d95c7b69cecc239b6b979917b0b9f69849a16cae9d34471366ceb0b9f697f9019b9ba25c6cae1d34dde6dab149c3e6daaf49029b6bb726ad26f5d99c4f8aac3fdb8767ea71d857a25efb5a111583f8bd79563084f6751781331b5d44fbf7ad6b233a6573651b512d3b6ba4ea35ac29df510dd75a5ae67d3a658d48d039eb5c535c535c4bf47b67a373d66bb5b2ec1c9d1ad24516f7154e7952adac2afce60e97ef1f2969a391dae6acfabe72a9e6d4af0f59997588f2a45d55c60daf443df4ea144f95712ac9fcc583f9f8443a0d2ae64052330f9a2a5d85911e17f2ea95aaca383b8f8f0f79f5baa4caf8719b535efb6c665d5271d587cc4a558dd429b34a5528b33e999547f1d02e2b213f7df4b326fa98148b8631a9cf8c99940b69c24c9949ab50ab8aa33c154f415233233e4b685e9d42295dcca7d8f3e338d7bc1fc86d2ea13a05aa6f007bf510e0a8de64bd7a87f914c77c85724d451010edc7a7a79cc964a76915cb94ac581557c3545cf5555cf51266caa5e2aa2f81995ed12d15573d04ea22504aa6e2aad737e5ad5da55bb27695ef2bfb2f5ea253bcbd51747dfba290f3e3b72f8a1f9e5a5519f6adad55431466678446a2be347319056aceaa91dac74ff12ccf9a10f6deac14f3985bf0ba0dc3ac04826e45312b85a1db976725d1dbc26059e9f5723b8e590906734b9259691cddd69a954827ddfa8b1bd563b96a559cfdc94a34573c1567dd3a69d62eb3ce31ebcbac5b558e59e354381557db08519ef5eaaaca962b2e5bbc70f17909e3c30a43062b8b925153652cd1ac24cb54cdd32c3ae5496995b74e9fc48a83aa46e45435a2515523a2aa6a74ab39ebf645c559a780ccad5f20e6d63f10ba7512c0dcfa0948b74e79a08bee934ff1e53df92c7df4329fb55916e10c797859a65a15d76689cc74ce9829172cd3ad57a6722acefa9298299c4ce3549cf5eb215010cc14cf5febd7a45d6f4aea27d5fa1e2a123162bf8efd7c113ae8a19fbad7196374988f7e1ec5ce2499cffc6c9f9f1de6c71beb6fd01c488507b90a6fbf425e136d3ee4366f27573891aff0f692855be02cbc9d66babbe9edb5169ebd85b7135de037bfc0db3d03c7c033f0f69bdfc839ce73379668565aa2796eb868b7d14837a82f29d96ca38ba8dbe8a2eaed2e34307115573d67e2cc5bc555cfc0c4c0bcc0bcb530b369d2589816982b4c229b39640a9935156690096456ff31bbe27accd2ac3e336531d2ac3e9e475fc5ea61751d388add707d755c97cd556f6b52d29760337b1d04a6d98c52a5ea7350a97a21c24a954b8d84b952dd428329d5ab5254aa552aaef6a954ad2aae3259bf52e0b1f9ec3c7984f0f2a752adaab83acb6798270f9e57aa612a4ea942a9b8ea5d3deee3e28f877e6d4f0f2d8ba437cc0a1443f2c2ec0b763d7cf1592f10933031bca08bde57ebb3445829d6b0125162c1f2298af92ccb309f354cbe782b2b2b2b2bcab3a23cca6bad1244b06cb1b588284fddd75a15d65a73d52ba8d3e9743a9d8fde2f11c49788927ae9d56b1556e9b22e8fe5b346d2ae7a73d75c8815a7ac5eabac51d75a556b55ad55b55671c92a52d61d2c779edc597247ea0ed4959d2b3b55769614b1236587d785a7cb89abaead6f5f579b2e345d3874c1d015a56b852e245d43ba9eea74d5915367883a5a75c8d4f1d5b9aa53e5eb2ca9c3fbf6d1e1a21387ce0f74d4d02143070a9d25df3e3a52747a747837843153474a0276e4d869f3edb343c60e183b30d0f142670b145c76f0d8e992402dab95552bc52e56abb5b7d62976a4f576bf36d7dce4043ae833ebf5627722aa57b4eef4725cab5edd07dd39817e4317ad3bc168d7ab3b890e8e8e9d606ebdbdf4995dd1ab3b61077b5e1ebad3e8533a8d3eba53473125f301dbc562a537f980ed64590673a7d7d8631dbcee84bd3ad4d06ee64dfe72a7d143f701db95b9070b596e7a855e4577b27e1d6a681723f398bb5eec4ea18bdee4841dc35e59f42627eba23b857ec55ca3bb26a7106c72c2d7c9d6ecb5831e1ace305e4b80269b430ded6c6ebadee403dcd925164e210f3b9b9b7cc876d6a1827677895edc6396076a6867bda9070b1f307c730f164e310ff21eb3a1dd10cda7948d3de48c8816e453cac69f594f2dc88756ca46a09e1f5a10adf4112ff80354ae08a2f9c8dc89f492687c85d89d40b75156d884bc86bd56cb3d58343989309b90903739c1aed8514ced888682683ee5e84ea4cbbcc9076c67cb3d5808d57213d4d04e456e7282795035d387a3fe2b5beb45600fcd8ee15a31687477b5d21878ff6663796434dc2c386ae5f1783c1c954d962c47544b8ffb425689457a69ccf800cb11406e5ab00411a5058b0f505ab090f98105873f7531fcb0f070ac00e4ea8715863c5169c113450c3bac8499618a3ae11437cb04be049162e6496f0923742764edf8d1238a0f688c807185f44a26834f8ca13bfa804914449e88228919b24c3da9818a891b3543523802c48845770485453324ee8645ca12a8ac52fc60068ddf55d7efeac9851b28b8e4b1e2049a205220656b090b555255581883cdc4e815197c9488472f5851229a79216761e19725c8dfd7dfa317c4daf7ef8a1c2c431e0d58c503f7ea77250e9caba5bcf286f6f85d61c3468adac2ad85a32a6dfe88f28af88af867e5ea31c64e9618e32857ae6aaeaf7011cbbfe28b5d29433ec6186317ac58bdaaaca0cad68d72b4c28d8c719434054b4a0f970915377749d9f3fda342e6cf185709152f7f96974a0b54aafec43d19ad3541b7d5c84e5646d06ead5c9dadbddfda4bc95b3b6807c1dc64a501bd33017431f3c26c853a98dd52a56bad8b40fd8e95b420180504b309b8180851dcf451f69b50136dae6957ea6475dc0a9619a9a71182ea85bed3c0c9fa9192d4b435a077369b0dec0de81dce24cca2e08cd4426312b0d398037a877313cee63a1605c94749bfc966e3c9e6aa779e3c361b0fd0b103bdf3e49981d4426973a2cd75efac503f4b6ada44a034db44b04e9d66255b1428df61b7d570db468928383b5919c175ead83b68a73110a8d9151785e7043a0671d417a166a5364a18e17df536c58a1b692cf3ac5c77b262ab71dd319d234244d14ae943b3840f74d004a1050226c4dcb91345431d39547820151fa2958b04ee46015a3a4f5826b0833d0fc3300c432fab8c30bc4fca30a495157793b8f7e22230ee827eaf5ff0a2406a485617569a2937697678d2d56bc38605345ae06f4a1021ade2250b657f79cbdb4479c12a4a596235e527a50cd4cd64c5a9509ea45873d4a5c420a5ca9fb7ac41ba5a4a4529ad4ea9c541bfe65b716dc3510a2dcc698147edef8bd5860b5cae93a2ebee8b2365cfa9b98e82a7e644ef6af4564f35d77f962088b50f410c9c51c20a95540c2870d99db537222ee92d59e20914aaae8ed85171dd11f653f73174f85a49fdfd6b35f5974e6924653fbd2e5cbd5c8872e1e9cf9acf4df540f983b2038a114ba0f83005250c11285ca4a0344922fbfe4199da32f6edd48de0f6e7ed9b5e1a0b4f08b949dd90c5f78f851f0b587fde667842c38ffa64cb094fae9e9e44818259e0f204872747509841e38327bc232b2471e44aad1084d4950a557cff5610b302973f7538c905729321d2171983c9bc7d9499743733e96eec1803cc9883a6e83393ee640710a919336326cc6766ef6426dd55b36d4e141d3b688a7e4d985f30f46bbe9c344ba21387c561df6b15677d88b7c2556d046d2088fd453512e2b21e63067eeb254cbdbdc1b13c282fde925c555e6c15956dd371de3a88ef2dcadb9f512350568f40598dc4dd5841ad1388df4eb8708c5d473a46073423c873c5449d2d4b84817265860d982d3250698102081f175e3538f1d204eb91d4a98108106c9e5838810a4308993a73c40c91ddfd392133a32ddca75f93a7c7e0fbd7448507bf7f4d8aa0b93d6c6b35b5379cf9a2e2e80834aad1dd65057dff986c3191f367abc9a11cddfc9974eb52bed4fca94bfa528266fe4cd2d1508e37fc594be202e64f5d2d862e7f26e970d8f2a72ee90c963f93745aa6fca94be2a1853f93745baafed4258951f26792ee86237fea92c0a0f06792ce27f5a72e49cd097f26e9d030e1f1a72e294b8a3f937463bafed425a579e2cf245d0d4cfca94b2a83c49f493a1de2fca94b82e1cd9f49ba353ffca94bb2a1873f93745825cefa5397e403993f93743360fda94bf212e6cf24ddcff7a72ec98c973f937461b8fca94bea61cb9f493a32577fea9276a8f26792956189d59f6252159740794a4aaa7066a04f7fbcdd702fa807ad03add5889c7ad0583bbef2ca937cb2a4510f3a871d5f79a529520f3acc8ebf7ee9e3fc4894d6ad63ec6fdddfba49bd1d8c81407f6c5066e7f57ac1eebd972ed11748a9122ebf2546b4b2aaadd6caac14943a1803e1d545203e40ffcd9dc54e61a388e216c5916f86016c3e6b6f71eff0d431eea90a5a54447cc76cbe555c9ef26cdf8c0f6820c0563346c551194e085f00a108c14e7a57c993ad49a87ae86a919eeec8ceb8d926917a6badb5fd2a40f1b1ef9f0a72febcc17aa8b824901dfa01a9cc45a1928845cdb622689cd15e21b620d6e303ebfa23885121bdde134f5ea0909381143d5049a105861f5fa03081cd7181073759acb2802409da8245052fbc28587260e1a219d3e48e1a3b4bc6a8c922048a206ea2f0443d099a6d1962840d5a9290d2c47767083a4594990a026a85263e3f346419d224895f90169a006235866a880a3df450d50408e9881454b44c4981b22601509858f383889824779c10dd4033258716be440184120f5678e3c4af0715dedcd08456c28f1e5a5548f020314502d24091022f081d7c1461c2c4023030bcd0c389154cd191c3011b9e9a227200e286c99226a00e2b728cc852044a0a893c3854f12184922b2778c9418993320f0b6cc63c05e1f1b3220122a898045901c91457123b64a42a8c0d73b26c5d71e0c312274a9ce061ce122a5413e01003d49621904ce130048e8fa8272431ac5982aac98c7493268b192e3c3c4ac48ab05242448a26e20481e4678c982c687e49ece092d268d2701541018e0a461c71c4c9e8e44413659eb4f1610a991756000495d6173b56745218ca008829425841e2491e2592f870b3460e9316de5c19b9208a45ad052b3c6a7867a4927852a6c7112867a058028522f8491220c45cd11066892998946922830f45d060040a112742750b92284f576c9454a1800c528e1841650c11572830215b4b4c0b6d8638a2cc8f2c0cb0e242922d2c4b4429990a8bae5000e24a1169aea4f4d8a27acac22407224c0c51d171a85c4922093148764c21ad2912c788ad3149c608e9090286168638e3048a136084aaaef88268c2862e4e82d4747cc963030c2eb0c1610d9808fcba7c3864c5604607a9262da2c4fe7581238313407ee015d16f58e841cad31c1bf01401c4498e7afdb89945e461e287993b4986ac11418b0d46144125874a4914ed3561aab8a9d383480f282228e3cb8282c277e7085413a7400f364ba2d810a78834318c10a9a3250b112b302730914521d9c10a8fad3339b8e9803703151588bc61e3820fdb093c7a5841959625a23cc94eace07bc383181690e8355961f1a8a00c0f5e0d539288c346070b62c844e941091e6ef8ede893bdd3e408560a6a6c5419b6d63627d416afd8556ff5f6f447e5838feb18e31b365f603f6f8fc3f90596cd55a1c27abaa3f2595babb89aa34ed57bfcfda3e2fd59d3adc18285f6f813d7642b0729a286484115d99dfecee369963344b4e441e18cd4133b03e850a5840f4d1a1e4a762fda2421d2840a1148b4b0a3ba17bf6354f76276749541c2871d98aca049a53b7252a0e0a2f543618528bbf6f6808c97835eebab127c24af171a2c776e3093c50e103ba807c11f92141e74d1c38e3556a2d8c2866b07f26c966a84942329b71bc298f919416344cccfc817235ba0fc49fe8c18c1469e605d45e414815324eb69111c7e45b61481f22bc264fc153152048a4817d753274799acbbc856d1174aea422e94fd230227d4c2fa53f47dff885cfd49f68f88d58fdf3f224c3490c2530a556cede4876febdc5dd43f2370be7f465ae0092dd713e0cf881dcb65a9fc84e07051809a32e225ea6e81b2d9662155a0a60871c1c714214e4e980206b9f3b3ef5f90ad3f7557c66e9fef5f10adae7dff82f8dafcfe05711284d744df3fa938a51a502a8c5495506a498b3afefd03b286c5f70f081721250d42ad4aa1ef1f90210f1b654b34cfdb6a8cf66d3e992c0ab6fe50a0a24a7e3fbc70f9fdd8028191ae500ec1f3ed5350df1947fdee229c9a1e71a88a212850994aeb62addc159efe86a4407f437e50934a29fb07c4eabf7f42a678ea24fdf9fe095182fe8400f11261325b0dd8b7d7ef7ca2e07f80d4d629a0cdb58a2bf20427b95144a0ec8ca81f503507a37840cdc050559e6ab6c80d6fdf3fa820a0d4884f63dfa88d9aebfd0125ea85efd8cdb5da87f1f2dafca2e61b91b2fff682a43d7501e4505af0fd83daf2f7fb0775f567adc280020a74abcab046d5c7e3f18cecdabbad111de98c6a04aba231c205420055794d9efc9d70e5cfd63a61eaff6c39cde543cd9f3de76bd7574ae901ee53a392f6f4698cd2de1ad1aece55dad7c69db5273ea3d6a200410a86a2188254cd0e9452300cc1300485e05b1f854b6234d5c208c09192fa2d12c5b22cc273f18b1a0d1874a10343f1f5124310bb4003861af41badd6124a138a391c088a2980d106a25896b59a7b0c32e20ba7810b2f58064e6023d98d84c1b71bd53870516bce3236d205df3493b1db0625072e84b66232f25619b60551ade2c694d4cf9a6c969bd8da1abf7675d1908f59692231d2c2488942d943e9e8f343762359f0eda2589617f0f04323c52a83aed0008592fa59d28088e8100af51774010ab2ed80d5022bfcba65032282540c85d98c8a9a908eaa2654dbe088032ca121156bb2b2c0af642acecc6188c43cd888808e8003870141bb3a65731b94212271d60a0b7ef274757d97290b58f8d4e1e2fa92070befd9c08e9be5195d2ecdef7083071cb8f8af5315c7811b33cfc460fc66cd9916031bfd9cfde9636e5b96b59a3b0ea7d31d1d7d0c36b905d98d24b37e1ee90080fbd37318f79a3ed3620af02f58db576e6bdd71baa2205adcc86ea4581a2a5f6f45746e179046350f9e0317a25896b59ad9e4020c48aef7194aeaa76390016c4d5611960c70641ff1a7b7cde0abc3f9db0cb89cd862ccbec1030e443f5d88b96b59d66aee385c949c06a4188bd21c20516ae0822cc083615896b55acd8e8b175d006fd14618e73a75c37b505d84b92bae7917559f51cd342f487ca62c22db7ecdcf9777066d0482b9623f8d1ef47383b7fa9aab9dba0529a9c320bb91ba08c60b182e34c8c1c06580c105306e2d606418304c87c1c2821544306c432a846a308260c0800144fb81e1d353ce60c862248c11665f30441821886fa595278311ebf7fd1758c8d4fe44de5da68dbbf8af0abe1d7f7b8d7517dddbf9da9d8d2d40d6ddd59a4ce014d003fd2932e1109ff606d871d41e3b9eb246b773422d7c15f9d8b105fed6306953fbf82e39f1de3e554cc580ba0b339eb2b9ea2e7828dbb1f51a0b21006f7dec0a82180441aa42667377d1f55b6554dd30f6ed84f1befa482b14edf2ed974b6751ba3bf3e72bcb5ffd8aa7f975d545d501c0654da820295619b571d81b4c416877d4634ff3c5bb9192a1597754e6d4573f85fec43d46986773f5f26cad86799f2bf0d6f35b6a6537d3b64678d73e86f85619ed22ec8d5fb10334112104e0411fdbbe603058552103737711a630de14235d214c95a6d5db03260a36128e7a4990a93e689e5746750b92167452c495c420e07bad5d6267f6e2b2cab058845b033b76259ccb2cd246ea5ba3467a0394bfbdf0ea97cb574ac3bd8e95b08b37f7ede98a237bd736168215cb8b7337eec40e8aa0025ce3be12e68075ecbf304b1ebb8e1f2f596335ee873e5e7c7102689ebf99886e501d8cdd24cafa2751bf9f2f6ce6a81f2ed9bf0e62b721dc5c823c46031841bfc6aa572a068bc715428823215eb75a4b8a179b295f4fcd94e2533365f8d44c095e33257e33e57d6aa6b44fcd94f5699992fafdb3e7dbaf99923e35538af776db7befb5e6bdf7de7bf1bdf75e7aefbdf78234dacf91bdf786f74d8b5d54efb5a7ee4d49bded12cdd3481463fcba17062bc10c899778b5bafb14c18bbbbbbb1bb4dd4855c4185f9ccf7bef751b8aa01886a6881dc418bfeecd23c6d8cd7bc33ae3dd61879af5eded2188af3d753bec9055713687106431e166ce1b25a4a8080d51658a246bb0a234f9cd99cdd0c50a4e133bbc3077a648b11aa720e22bc20992264776a00d3dba50190206227468e0fc59f365fd29d688fc66b3217aff0895b783f9081bcd271f473bd1a1c4ddeb35ba689a309304b606f4eee54deddba1407414bc9c83bf3cde08d4d6d9c62bdf6e24ea41ad94cab07e99eae3a81f45f4b16f9ab27f3e5f0d5c3e2e35f06c6c84cadbbd1c7c9950e24ef46ea428a29fd6436b5f3ec3becc36cf13fc0541500947fd9b45ff117d4615f34d42abb529c5ef1f982e20c040f10207a60921bf383eae1e92d84cc30d98df839982e436049822486e435c9fef1f981d0ff4fdfbb2f5a72eabccc5572f8a6595715eeb621947bc59a9661291299ddaaeebf88bf301facb2daead395c5b78babcf8bc84f1792183c5c5de8b310886e215455ba98841300c45f10592a128be5e30d8c885bc24692b2545f205838d2349c6e4c8ae4c662b9569c1c891246331996c4683947991f9665ebe7a5992f9ea3d583ed7c7c756ea53a7aa54353255a5ea920a05a74d1c386db6e4685dd12a5bae68152f5f1d73796a457978e813e5e1a15214ea04368b4cb7a16169add6de8bc10b82b65290566befc5180c6f18da4ac38b41300c45f105bb3098ad14168aaf170c368e64ecc662b6d2186c24c9584c269b95b72c6da5654c369b95654f8fcfcffdf9b195fef8fcd068404041412a6ab756b395d67a461fd29a3f443fa435694e23adc9741f680422ad79bef8ea41b103d0c7b58aab4285ad54857873ade2aa038932db8daf722aaefa0130949aab5e83a0644a5ce53aae82a1545cfd1343f9ea953eae5265742c84157fb1a05419d80b00045623017d754cd5487dc50199366daedbdf17327807322af859bb8a47940318c56e51ac06182f1cf1bc57dfde1edaa96f07dbf1b5f5c269b12afdbdeaa2f6ea9817f270a9bd6bbabbdb5c43b1ec45c51a5af0627cdffe5d53c92ba7bc770dbd724a4abf526bc3cb068b7ebbe876cbe8c6d1683f340b9257ebea5056f3ac91b55a59b6d37c5a7f6bfd2d8b57b2e6d5a1a46eadb52279d79cf725b3d578bdf5a69ff1c6eeeeb3bbbbed69adbd6bfa524b7677378f1fbee0f0e53744f9c507c35b17bfccf065862f535e967ce192c3971878e4f0c5ea4b150e3718b4b6142186245956bf35cc50c49fbafba5840161cd04b1e5912ec611172e56678d441b03551575a5489672aa6867b01242f1e84517e348862bf1fa66a0fa5314cb19a6ac87e6ad0b9b2e6afe749f0d23f5919a21c8dee6db45717e3454796bde4a4199ad06fecbf4f637c39cbf1405be2b8229edf7af8b993fef9da1acdfbf2e64ae6b39716f755d74b0ee3bbc75d1b6af4b982e612c132516c11786c130c63886ac570c5a332ac618638c3116b348c600e7318ea188c7b84ba35d22d84a015c3aec5095c5fb614b972bb04b0c3212c2e47027c9133e50d9da4229a59452fa7a1509c3300c43afc160611728252c555851400569626a77d63e8c41ce87610c4b7c08002e6dd25cb103440f2a3b2d40fc7e4794524a29a5e12b9ff47a29c3b0cfa4106788224bb6e8b0a4e90b798428c3a34c992670e0611782385f1aa82e88b7586981610b113cc4f2fa295aa32d3f44e1b894fd341aad36f4fddbe27bf1fbb785cb9fb429196eb37a2f894372528241aa7eb4b7bf46642d9212dc0ba426e5897b8b7b61d5f4ecf0789404bd3d46c559fba2e6ace32ace3a5255d9358b339293b22bae2bae2bae1ad5b2783cde0e4fa23182558c58d60b58b817aefe6c325a2f3c59c797d29b9194945c219cb16f484acaa3b276cfa8b125fab15ae5650ed26a1d69496954e69e34446c7d8f5ffffba535ba80c7cc1bf4635ed22e9091989467f9d5faf878758bddda0c822f1f1f43b2b48ec4a4ac17b04665024aef2973575ce93df99a3de679fdc74bf3bc6e4f1d3ff3d9cff51f9f398dd59865a599fb789995aef7388ed5b8dee334463b40e936cf6633d367a40135fd8c76c5d91fef07b23d3e3371d4efa1f5e4dacf8d2dd1bf31bbd6b18f24098b810096e609661cf57d1ce72841ded628287bae33efab8be1d66846cdd51e25e58d410d1c27e5cccff6a98183d4a43c75d75a70044dec1663876198eb62d4c7b5eaea88c4a414ddf7f2ea1fa8325e3027fd5e985ff33ecc613111689efbd6145be6336c2c9d17a8b4ea570c4339c91845330218000000a316003030140e0a85a22409f354dc0314000e7fa64c504c184a034910a5288ac120c6186008008410608c21c620e6e63a00d02f0f6628fe4f663dcb2cf2b3af3207de05498e9699d9778001f217d830512723901306cb869636d449e149918a201820ed51f456529aff2f2e9f5290f00dbce8b22352950d0786f903d637abb0fff842641e736cf9c0541f3338872af34e0eff60de850722d4407335f3b33cdb2c3bc778338c67c935eb776c5db453fb35d000016ce95456fdffd5d93cfc502cc194e54c3c99fe462027bb2deb6c7778a1a2828144e7e372dc3f9e89d95337101e8989e5f8e6528ef8772343058c6b631c4939edb9cd82f69e977c16860b601860fdf191bc19150a36e6b4b426b8134e0770d4a105ba131dc63560daf28803f90861c106da250a5eba2e71dbbad49c7045176598534010eff2bcbb7e2457df702f5290735373c666246780b6f847b9c22d1902daba78b0bea6bc1402fcafa03c5685da295fc53f958bc41ac7270f4c4d60a6f6e9b4beebba544a86beffb3212d9b9f4c6a3059f1373356c0a4f9f4cd59275e052eae2dc9efb3e76d8a5760797f62d14a3da3372d66a2406b4a7164b917017353b10122efb7aff10b9e8eae5cd6ee2e7961ba5dedb7bc0de788f3581d8defe947f45f453cfeeaf944a6b18e47f92a2ad001837c08db32e49ce746823214562a69a7f0b47f81388fdd242ec3a448ae6d92acea08f7618387d2568bbaa492a74c02eb2415e8561a311e696ba6bf6147481e8c299032e2531f5c3b5aadb86c2991c16c84f0340724c1dfbf5316ee5115341b5779d02b32126e380551b81ce828efb1d3c17f7fa723ea7bd00f7bf02faaea34d4f703026ee48f9be7ccf34bd8b7323a1363c32fe568341c484011bf76e3ea541c44218de3e015976bde6b5fdf43ca3065df4fbd4363c05dbf722fd706ae7555207a36c4a4719bd54e6b33ca7eb6b7df49b7340381fb77542b9a227787d3f02550b5f92df7af1c03104e024394d619844349b440466ea55649444c65a3251f4183153a3212c2b2f131094da15f565078b64dbe27325f840e2057d7809e7d6b6bad08ccd46c5345bc20acf29c701d59c518d84eaa3715136d9dbcd9346dab9ad850d40f04e176fcb0733acaa1d6ceadbbd2f8dea50e52c0e87a6248d233d7ed859cbd6527e0fa25fa0a90dee602e9315036e4590d0253506e33fafcf88c7a2c52be7f6c56d03159464453939c803663336784822c2b88c3ece3b063edbde959a2bc7e5d527288cbeb04e8b44c156681d07b86d708835e24440dd542a403e84becc903d377534d90988224a114b298919ac8660a14a7e9a47ecd4754193268bcb0185db0b4d7bb998973d5841fa1da9316876de27abeb10b4ebc8e9d5e5f582817bebca353a117d3f7f433ef3898ff47be9fbfc6791225a9484f2a0eab9f30b1e7368114a1bec66952054ae7b885ebad8865c4c50557687351ffd59c74f52e93416129ca9805a6746f1690d7ab6e75db42cc610a0660d7032426e0613e6cc1841cd82ba7ef8871d0131649bda1c5e663dbd3123ba9bbb679b3d192875f6d20136e80d4484f04918217ef409f93668b182693e7e068e35e0d5f9ca84fd10355b85182baa184db53465a53241716625bdf3aa5d5955a8627601cdcc7584d56535d4b7b3501e70db0c27977ce1784bab5b7bed15d5253ea77281642d8277940ae65c8f463a5b9e904a7930904fa08dc6015a304c04ad58b37ec9c972dd1f1be3ebf56d21f38b75a3fc5c2a90bf0a509750bd79a99922757362eb8dc1846e52a112520e30882411ed235874bce2b62e1983b39167073a3b7027f9194e0258ef4d8f97779eaa0c097a1c7de58228203031405a5c1c46ddb021469246244f61b7cc41dfb26731496f25b3803ec342d3f0a76ba8457f61cd7aae1ede0e10d61f071ca11c979c76397b7b644081afc3c2a4ffac03cb071a246728972eac0448b8c5b1ce28398461dafae565f67051cb39a73832f6534d3e20632de4a382cd13959bd7579beec91525bbf980fa2fe8ff20021602ce7c9ee03697a4043b6feab85431300c27d7f3b6122ff8ee83365dd25b08849c70a3eaaa350312286a96a1059e358e38346de5e8b3d12350ded24cd734a53b5a207275b0793efa1acfd86db90f9fc890c57aba3b03bcc8f5c019cc5f6bc584230376448292c4a1578735a7bf7dee671bfd1e6a123134823c14064f41c288ff1c360e40e37f54b09f4974ac0652b81635e07c8bf03d7b0a6af84cf07973085d3ba607509e5c6a9b4f3e329f54796efe99a3e3aa1532dfe72676918f4ad1cb688e2d0b51845db1b242137534104326726cebd6cbb9417d1060eab48f952a6dd64a03fe8ae68366a590cbfd810c062678413f97f7899788ef8235396f46a6e10ca01f7ef7f5d05256a7da26317b3dcb258d4b7651c58d6aca61c35d64f163ba9184d95759f57e398d93158683238bcf93a47bc03b08d485baef1688c2c1ecf65ff80a7b65c83bdd0cc83ce9ab8ff2bbc4aad31a7d5639e96165f13e5ec2b0d67d3465cd421b0495d0705dd8921402d0df71332122c71456e819b597409dab82048e684d97820b7299a5971525731726b751263935db05974c933e2828a2ab0b586ce17545df097abb3205dfd6f7408396a6b368a5ca130538465c97d784853686cedd0fdac5cce05a21a16ec0e65545a7a15ba637821fd415cd0fde1045e455a99587c08f3d0600d1ce919f803a243eab7ee18abb58356f4e6c2f76e3ccf8fb9f0442ee1d0ed3df7972fe2d57e6a0862b5bfbad58fe6f90a6a08c3097182a020e2e45ed1f3cd4b40db5bc0fe5264fa938985945db47a243f7cda9015f61e8684ed6cd4a7009dcf2d50583355406a9700790b2b0e8a6ed4ebe8f168570bfb182da75d732e2b7b95b40c21a603012e4595aed63b0821f79dbbe580c7e7f8b1410c8c2a88cb87e1e2f5d5d79eb730834a98892cb9337b4196123cafe97ace8946b06059833815e6029f964304c923f409b51889debe643db117d7e0d073627ad84ef712fe5e6999f54af81cf193371778730027c419117168acd3c691e0ca6f2b42bf651e8ade93a45485d9f378a4cb70eb7219387f9d9c18e2f4eba14b116e603174e3f50e6f19065a2d09aa86583639e3ef842f7c3e41d8500c35fe38ee6c5bad57dc9ad6ba01dee4b0298fcff38feecaff2432d6503e2c5462d1ac0c9d5e34b7ad5810160474034c4f90c163e68ebfea8731f07c9d682ba832250f8798cafd97733b5edd55e3285fed213f50030824ea5329409b9cfa6c2c070c6cad777bfe1f367c89b1855e32896d3a72f731e380bfb598148e9368a0ccf8b871198b3dbe60842d40b2a6d2a181ab8dd9f1faa76516a0eb0ebd06103319f387dff194dfd91743003241bb99f4706feae2826e5f6030b402b3f757c42f2be352566503cef6a0349d9ed96cbd27b02400c5c750e2f9ca8e4727018aff35136c46f07247ecb0ee432d370743d37ee83e37feee20ccd1103231dcf9c313ccc584736bb99bf34f476be212f218041276838459e39d2f87cdcada9d713791d30e83025d761fb882264ec9ca025821d680e6058679540ac983f705230d84a806dddf70d29a6e729c4b9c2dcb6a9cffaa05a8a5961ff85c47736417390f063ecf80721973261e3bc37dcbd5a172f63de00fc10996fac801518eceed60db19a9c9410c0d9a5b544d701d3480dca6bc4be3fc6dd02e866451d89f38eb5f81fd9a1ba3a3ee8d10c03c5c8b8451a0a6a990150cf5b437733549d1a92f3009bba491ac7b05374426b8310809fbbe3b149cb2167f80370f477c3ca4faaa0691ec79b05630d20ef4e0764a81454729a5592881d59b9f9bff01cb169a3203017f7a27ecc9eba90eb82efcd40a134dd521c33c089e76c3afdf057e410286d976df5d78aad852f07ac016c67ca12576bef27d90d7446b38fb424a8953df2fef9e9ac0c6d91f7622fbf6aedf7af15ef859f6eff430b1b8fb6733a0ea40775faae26c48dc9dfa0c89ee0135f99ee290b10043a23e22453ba0a980f9bad6a6995b3a2945ee110b9b1495843f2c5697c61f463e2788e071269c57a7019b31ef05e368e1dceed0ced29d9b561f1ff82043798f6a09c2a4b3f4d7dd94800ff257007bac758f10bd777697632ec439e20fbc6d89b5a7974472964f3f507dc6ac955e58ebdbc6e4bbf1802348fccb1161584fbf5870b38ba403aa5b3fd04e0d753da47d592bc0585c718b968c54b1955bea62ffea0532364677631106dfd7ec4a763069195830cb15a9c991970f37d9a3c9e5c182300500a44f39834512548d64132f40e6dd53840b25552bd7e8d584c6fe2d10b79dbb8935f2833d03f8bf04cac2429e2b8b7346dd5daccd0be49c07cc602fe1d928b2b83f4e44fb310df47d49cd2d6f5da5859cb3aa92812bfa8d3a20bc592a93b6d94b15ff6636026abc06b8184a80bd860efe8561fe79c0044aa92f4605d85ecb82043f5103f707be2b342597de812f54494d5978fff4ef08a00ca78c6f1dac0cd67a58411fa581049a84f78ecbfd24e8be91f92008d90fa0dde13d736cf2b20b14889401cd539b201303366c0145cdbba0d9fdcc936c970f683eaf96ea7acda96cfbf5c74b83c0b7d78420f52b882cf3076a74d653d2be95dbce127607569052c3e7f2ed168a5ed26d80137f5217197688566387fad3db31519ff325aee39e1377865f097edfa63d62e4ee67401abe0fbd05bae4e867434e3e9fae0d3e65c467401abe0fbd05bae4e867434e3e9fae0d3e65c467401abe0fbd05bae4e83d57f49a2e09e47806674424a613d9010ac4d4cabdc100f59428eed12dd8017de607c81373e13d77f1e31d9b390ac7f4ffdcaa5de600d65bb21a4d2d0dd772f9f0a27b1dfefffc9ace53437a82960d734d33385bd2fa6f905a8bc15064879ae49ec1ee127c04fb0e486bf9c13771129be16c24f5801cad86072f972a515ebade409e425b723929a2ed21223e2c37e031fbc319b79b8de88fb6c25fb5f5ff87c1ca18e5a35018d0bbdef2d928a14de10fd1dfef7e5e0d8fece61e6623264bcfcfd2c9591573b9aa931bdabfc9de3c6a5aa847b7a83de9a81d0b50015bf748bbbda368529882df5d67212b4e230cbc00d357a7a3ecb47c6ba2f30a74ea6031da2b10f68e65e8fdb18829a6282bcc18c39d292a0e3145694da2b004662ab84c5cf58accde0f6cfafce3ef3c67bf1dad7c233a324bf0cb1db4900b6fe4b72449c4e537021adb266f08b1f99b42b7313bbcce2a7c0a440d07aa14fbce95ce84c812161a3a66dba03a5b70790a233d5c7691794298eb24927d51d81d91871d7188ca1f429f64fde5ffd97e99e75f8ae98b769966ffbd89e05fdee1fa59da9d9fb12ec319cb784bc109102d72b6fee325aa48c58079227909055aec4f48e0f435590b427be9f4b0ca14ab114047e789ef900ab7adbe2c7163e9f7048de74e2f11cc95b9f7935c1d681da932702d78d2fab830b4152afe907fefd397330ebde9bc15406e9ba140b16ba3212e663b8154dfb49e73fd7ad98089973240ff37a7ce52d2fba9c0b5cbd4bb634bed5da3d44665300df1cfa0c30cbbb0b566df748bcd724655f8810f4ef0f15ef420f9d6b7c2e17b52c00c3acdd424d099374faa549116440bb2d699217d4c703ed4ef74a407b86a60ea9c9c50da93f68fb6dd9144d35fa40ef546ddda07aa4833215a2e062a9d501baf3831bcde74124c4363964caa29cac6f4ead083b2fa88cc9d0f1866f18fe6f134b059d78335684c8057b4251f6ed23cff0a7499c40dc707b165430e7d41a716f2d799095b36e015d5d9fe825cd5682a19a8c4445a13c1441286315c6760a87f8c1bfa590ce53a41c4fd8fcce51eeafbee8ef6fe32bbe4f0219091e7166d961cd4db631bacd8de6e2ff5c8374e2685bc5731db9b81adfa778239d68286db92c7cfa5bb8b3bde5443d9e64113d79a5a823a843f4fed45398c49c2819774497c0f456c7f4151141be7a5e9b6c8bb9c2d8dea9569373cd5b8af20012ec4babcadd72f7f2f4f29646ea2c728b58b792fd769d5f423bfb5afba62aede71a9d6fa20beed612da3e087124006b00638f1fd4b336b0aa87bc234e580b84cbd8d6d8fba5ff7632a933c38d49d6199650c9b0aa42b022fe10a54388bf561ee9b97e727e1aee0eaecb13481aab3394892a997b4d6b5d8ee3c062507522042bae6c18b931eaa330b823b1023d3364c48d054f279bbe9d933e4e705b21e110e005b68e07e610b7881148d6a76ba42d2ddfceaa681b55a80a6b7f70940b6ec0b25d062dcf142dd7a36c909fed63b684801e142a9af3555b7ce585af98cfafe1c77e4bede7db4d342a15e1739b57fc962164d1b1956010392d1e2a10456ae4e7e48f7ab1599dafce20a9ec01da48499a89e12792613e69dc2727993524a1bef2ab81f012fb3107643d51422c202610a1a1cb023730d56b31a37f8c46b6b6129519b45f7cff5c00616e477d0c377f81d55453773e9757635cb90ce52d80a76c39c9553138d7244387db211f55e868fc79da5d6f6fa80d09f561538b1397257216f71a5183621dbea5e35800b0082199a36d1b831f900ae78b61ccbfb32ffd1e6127a992187b2749a38de088f46886e3dfae6b25fc0397361fb16cb2a23df8f30a2c1b07183c4f2d805149de0b8813e41dd59e60b257c927fe5291b0a4d6c0dcbaf1edbcfa2a5e25fa02e9e36fc4f3a85a0b5a3dd73398854c424eb81f62354ebd15e58c381d499c9e533acd86005413568cfa39440e9327fcb797715e2571c2207f362b16c69cd556240e12a8a37a24e94752764fe693d98337c7567fe9c642197e4a37b231fe00fcc4eba8007ad5a3acf4f72634e5c13e6d9240afe1d725e1d2b9ed79f9fbe3170a77b637e0dc54887db3f2e595a30a1b4d7d661c0a89731a7469fc88bf1def88e7eee9761ade6d199233d4f41f609e6f67b96136a652c448f9dce358cbff35369745e6ce6578bffd92168f2ab91e735d2503cfc7b8e1ef3293e0f09d9d2e4c5588987d868031836d2d63e39e8f16a7248c5ac599c9528686a97cf19069f0da8586a9dd02f6e9374f486e4dddac473b3f3231cb1904c89288f366fd3d101108db469ac5b6f64b653079a7c5cfe9bc4b9e5b9fb4f577488048589313e7b94f0f073f452bc9cc93662cd2d7eeaba488d400bfdb09bc2e499779e2bfb2dc35b77ed272b82af7d8412d93aefaaf40d811a01a5ebde3ee68e3adc55c3fe997b9b2f19d87351005449ef769d2874463be90ca73444d45b61f71299742aa18fbd6be8f586554db3cd14668e0fbe2ed54e40635d59c0b99331bacb0aad34073b7eff0601c87b8daeb87bbbf457bfa432c6f4e5e8f0073196d05e89b760a8d46bc554cb547268e7948e5a00196e6588130f6b940093d5fd9c757afa824541e58057e306049da16956e811ee3cf72033d6a7629088571c77d8c629d29ad47a790a230f6106d08c081c76ea46eb692404a17623ddbf264e051056115015591eefae1795176f62afdffe6581c18886d12b014df7de7dbd1a7f88e1fdfb559a04213ce6869b724a3b313752aa012e91cccc02f4575118a4eec20c37ac2cc6752f874374b1c64bac3d0f6e6069f2d3b2a0ecbec6bf2a6da08cbd48f41a6874ba87ed35bdb2aa7c656b3155c8cf28f1265110a34042c3681d0a5ec5d918912f43e5a5a7e9c1a5a6b1956c7818b3fe59404d60038f498b6fdbf084b4681814a4b57b88c6114b9595699582324a12c4dbbc4ede92fbf28fde15cd54b646d68839f9ddd6aa689bb4e1182c335915175830be7f1bc5a1f5e5452d5360c496e75eed11873c54e740f55d479c5a3241dd74840d31f427945b7a2451d57086e70b7a701cc4382b332eeb1ef3b8a90e5149d310a52128e37c0439602a3511368fd84da029b779e455ae05a3343cc5a7b7fbfc2c5f3e4bb95bf13da8bc432306adfd12d56bd60c749c84f1796f472b5c6d106a119136b3f6742e0c90e7b1e1827c9367195b2bcaa83a1573d11dd4c0097d0de395a901f3892aa830589a8ea827f24cb094c5559afb57f3ea626f7f239c500b10d09a777522ee1ed1f7ccaf6930692abd3a349d50f819df1cc7958f406ae5fb3738ce0390cd763e1f79d4d251b0d851386becbf156508ac3da591b5a9a58c176a518694db4d3c5780f2b98afedb95a87565a37813a19523efb56510838f2c14d9ffb444c07a06211e5cfe7024199e2337a0a6cdc54c42d3a2a666646cb05a0745cd4747225bb60e87e6c6b773eed0591cd3ee82b09309a218f37f2834b6e119e2a55b561c880a251af4b759d7602b420a8662a8257c74adb2937022f1c69bd45ade89c480511389549cdb7d053e14e0afaa5576b5266f939cb607c6374e7fe839ae069cc3c669a8ae589d040c74cffac629f6c55467282e349107ee50678af8b3558e930248b591f9348ad7db9e56f059a4e0639920f80d90004e2860deb94ec34f09d3ba343dadd2f99c5861e654e147624ff9d6d844e444b6656dfb12f14ef52fa429224171b918c8ef2f6011775002b316ee4b9997f330355231ec4f73bed5b502c2743603b108be41f27000f874c79a3d784b819e8351c7fba711f6fbddc54aea1c4f53d063ceb6e21c4966e5cd86f125bc2273aae138f812b9d1f36dcd8b72382404e03c18fa0a400e00a9691a2a66e16a38e8ee063887afbcd4b22623124f3a8aedff1bfbc6527c50dc24f0042963d789e085a6c579107f646958f94e4c74ac76fa56a5969f7b415d157afa3dd653bc1d01f91f142c8157c666caef210f84adfa3dd9bda8cf807741aba9489bae6af0a91efe7c4911df6132b9284f863acc4bb22adfe1a433e6a685b2e6de274c25f97b031b5c15697bca983c24d9a913f6103b907f635b1a98d425c4e81f8cf10acc7814800eb17b408d44ad89e36d9ee144e5f000d62f1bce6dfcfb4ceff98b07cdf4c287f4d0d9cf08a34771c5f9b1d8dfca3804bbf58665370ce801dbf78abac39a19947a45ffbb6dd4ba30df162878d27212970c9281115211996b755f37581177bcec14d4735eeea98f55c3392b4cff31428d6732872717b365ad1b58d94a9fb9745768d10a435755090d5e14e82e08e3c72ce8b29be8b626a1b8b87aabe309f77eb23a76794bfec276ebc8176e6631ad018f1f2faca2712de2bc9ed099ee66ccc622f0f6f51a0919db2ca45aa1a390a78562a3d8d8904d37a45b22afcec0e66db00a95d934d7d2a562e438308892e8b45eafb1e2e6f9648291c3072f3b93d6f8cd2f13479f835057e36b4d9d11ca4273624528c69ae125a8e6630507b4ce2f2fb3d729eb23eeccf86ed201671c6b729424bf2e57b07b9df97cf6215a688ed4bda14424cf3c2048144aca11fb0e59d113e5887e9f271ac949cc6db545d7ba5726d6119ad5409f3db2c0ec4edadc68b6239a576afdeb8cc1a72cd40d971b74e4667e8c6a2b0072f9a90c1581f7f8e2e4b2894a2fa046d9fa83b01c932aa74469133912351be123e01a1f0494e4fad5a390a48c3fd3680e9f5e4f95ea7cd1669ed305020012bb9d18c22bd8a57aba0de504627a981452b1966962486ed70f9544214dd7c7a23c837f44aa3d9ed0f876b75a45bc04af9b803e3bf2e5ef7eb7dbdbacdb079461afcef21db2b2df3350959e04b8e7d8bc24f22797029581ee414cf6d94bb8a1b814fd162d2726bc519e91931b7fc61a2fd5b3226b88aa8f40e6888ee0b7d20736b156a4d44274e33e2df66f02025e35c8b6d109abb67ee256d2f0a5e2ca6304a1f236135a66fedb098c13a04b7b781bced541b00ce90ed63b709fc6639ce69e96181c5d9b0d592fa1d10ed14487b4763684802e9eac833ad59e3c3718afcb0fadb13b5afe657b355032c900e7d8cee78e62e1834d98d59ac63476d7afe1f8d4eeda2ffde00997aa45e0c0f2190be32840203913b6e44c9270a2d54fa00fb980dbc1e5658a53ca289e79b9c09d22b74ec16f5d3337220a867a5a0d01a14f068cb110abf3455b4bf62f464c3c15d1e183e161077ca7c8dcb27f80f209204582ebc22c948ea1a55c92e21fdff9dea713d3688dc42253ba8b06bb24d39e70cfaffda9b1a7a6efebb39f6d09a9fbefbfd01c787e751afb75566deaf26101daffa5061735f7fda381836484cf4853f511172d071ee874594bf113cac49474cbb76d20db4aa5a658a4fac38aaaa142ade4f6a2b0a03e5d6cd0400cb65e3af497761e4caf434c259c509115f4bf26ba7c7096b72af27f5bdec0021fd36a8c4ffaff9a3c74a35bba24c826fe9ad61b60402ef010787c82f8f19903508153e9c142a053601c859a491a3722e362dd9798263a1c4422dfe7186c4cbd1b3a63083ca0075f04bd6317a310f00957701bd1978607f627c6fd5d4beb7b1514956448a602a6e0f576209692753b0c06407613b7cf5df9447ea90665b091ed93741d0ee345662aea3762aa64bc07a64aafdccd96641cf50b2ebb23389dc1c801672ec7c3f6e292eee072750a2d968e40aa20c5bcb93e10d6857b0b17301bb1613d61576e67beabd5aee4258242045ecf4a9afd956b1b97e11f1e6485e0bf5e575f5d5b48884566f7b5236a649e0ecbd5a433c3576d8583e1129f22f6eecd77b2e3c4db57eb59608ddb5e4a507bffdf214a566e8986667a59db08596c4d036d95ed29542c642442e231a7a0a709f557f760e48116d436c6206e396e4df8848e3005faed501f3d0f262d3bcc9802bf03fef9eafc4d6e0352542d473bc87990d21403466978ffd29e800e8479e2886790df18f5d37f60b3c36b747b7312b7c44247ca05968e155c400211662cf3fc7c19dc27f9e15fdd65d19a991c319b4ae4ed7e918c0c6a100c328cadb2627a7944318bf732c4fd410fbd93d8a084d2066148b5a22cd466d0f0815412ac986bc89feebb14c80bb7aa06bc33c82a76e1a76ce00f3bc1b213c14b86ef367f0a92940e0aa61ee18615316faa81205278291bb828dd2933a0681d2fcfee6bad02e612013620cc6b289d7977f387e70ee5834e11de3029dfa50d4df6f0f185e70e69740f2477e5a0ee247ab7164e04e0d59651edd9a68d6e6c9def6e94285dd651d120feaeec55925f93bf0137f77bdd126efc9da4a21415497f87a317a202f7f7f14ba642ba1c0900cffefe7f351087d4d4cd0fe4536620f48a55bb535a7411873cf4d6cf40e24a81a616448127bb69d0d46748c6274420a89ed01013281152e09b8997ec2dacef645edaa6ae8ca360dc7fbf1002e60fc6b944b6d0e24df45ffb975250390ab53a412928a714f40601b53ccf4ba4beeecbbaca0d31f39dd8dbe5fc4d1f078644e3f9d6a7a612868ee1460746b4f69192a18abb1f7403efb1fc9db91d373f2f516335612e91a05bc563f51b8afd11c88b6d22fc668e62bd107abfb1144761b2348cae47c0042803bba41538d1907db12166888414c214a03d9f00679fe527ad525fbc0b7710d18ab696afc4d6ef95bba2af4a57f1f563e5aed0d6b2556cfd5e7157346b69155f7dae9c15cd5a5a89ad5f2b7745bb2aade2d7cfca5d29ba64591efa1bcabf3de860641f7a9727a973f674048a1b8abcb2863883358e096e5a3e602bbde2d2bdb8018c0eaab4720bb6908d7cff3835c98951863d3585d6f88da1447c0a8926a5cd559720a8d4b169755d8722f0d7e5762a21ef3b1d19508a6da712f1b5f38652346f8f730379f1d1406efd209cc55ea1d3e406ecd22beb1214122b0e564d04127df2722aaab0fadb96fc2313a5ed5189fc3eced08c787b5c8d11cc5b193210b615a0872362f17175622347c2e64806c6b20abaedb0df33b11bb71dcac47f28051913ca378612f929709453da5c71095eac0cdfc195566f07078a229babae5c68d56563d5dda4c572485ddba984e48f48a4650f2bb12cfa2d0d64059591981c3a1c7b2652abee88236fdad16d11d62afd1c7a4af1898df4eaba341c81655db7530979df4191f1536a3b9510dfe980a0787365dd1c618b4d89b60a89a4392b1ae1909c0457ee2da23beb94eace459aa024ee5745acecd1485ee23e6c3e6a91a2c9602a979a1b502d3fe369cc2c8dc8a0368a9a1f947de0ccd9bae7b73ce6bc7f34dd943c46d45fa6786ff485c6ea76e90b436ce4e0dcb620b28c8ed6de48fa7421a4b4296c54284b9f9a9c537827211a334ff7503ce126f236405ea0cec6d5f1d333504e656cee795a7a6b7c521834c2badf2af2ec144d7b86c81aa9ea262455d7cbadeab1195618725048cb61b03a9329866eac87a40c557918937326fa353ae4882cb5ad7a2eb81f83d7d992c0301fa97baab9c008b54e8abcdb539e16525d864f0960f133d4cba702f0ff0cd00981105e93ec297d80ed17125fd55f9b7fb16dc99a2515e8d0b47349896f103d238ae7a6e5fd1ec7a3dc43239afc0dd3347c5ca643aad40c5d07e46fa6722cc172a127d2ea60afeb235d7982b9a94509db7899b9a96ce9d66dfa0209b23f892945f598776d116ce2af837851cc595ce1f70bdba864289c44d6d3838baa063c874d5e43b64c77e59cf4b55205713827825b5846fb8cb75e803d5eae7da2f882bed0831180fe0d8380c01dc0df8819d665338ede81a086a0a8f94241682560ce5dc4a0ae044fe037ff188688d182a9b725091828ff9b1fa7993d8dc2551080a1492ccbf434cffe0ca1986012ebd2df789a02d0b2d8ec912171beff3fd73290697f020b2b6e7229d52fbd473939d3170d1012edf1d9ef16e92c6826b4362867c1355d4e94749055673302ac4fc53e8fa368bc5f42e24cf503f6c6734bb0054678f3334fbb4ad60672328601f22689550675f06f512df89aa1d18537e014886fd4f1a5aed69ec39d3010f39475875f8d2c63129928fb272befe097e71fc33738c775fba03fc096cc1c3a8021ddb1e3cb2d5e982b433fb03b99d8786f5b6a0ac3015999250cadfa87c3efdd16b4a55b945faffe7a98af6663c3e50052c4670e514e3ed404e77a333d9c6027d82436b854b113eca247d6e313c1402dbc54820329b881d88b9b32880f68810a6247be716b9ffdee1b9516bb0cf4b6b85f81d80e6898f6e4a61f9ee0db6810a9d8bad70065b699b07bf7600fadb4ddd2dec7721634f8015033cc1dae7c8683a72dd8d331d9debe06a2043efdf6372e272b6bd730bd37c8285a17b11be044affdf5904fd3bb3b8dc358a05bf53bbb3674f28a67c503d5e1c352a3a1a8d210708ecb4e1f3a982687bb92adff297c5092306b2187deb2381a6f5d47f061a91127e12473e3b415da5b5a0a1065cd332bd9904d60ce4e13778b1d096cd1747ee0abd474136e9bc967df0cbdb7c513f1f6c6123111a13eb79071ed03fd960be57b8a403e8eb11a8261cefd89b240663907364d866a1082cf08c7ab5f707f6d82a0fdcad678a7ce7ef174987d50cb80158c2ba2f06d2ddd68c040ce935ef855d33b661269949cc2ea799e47265eb389953d1ebe2e692075a57ecd26f13230d165419f077b3a88cf442494122c9929d1ed4b2aeb42846865977d7b13ef4cc917429f95155b6135e0692afee83000804c6e81d75881e52d9c0c482f165ef7b898373306f4fd4f6608ffc84c148592540065d4d6e3d5edc6a7ca2da8690db0f2921e827713b4ed4ad3e178d0b76db942d1474f366ef04c91b4cf8be26ff565dd66a18abbe31b9582a7c69466dbac961aada20979b3183139e7e43329219eb3575fde2f87d87148dcf188053315188556808f62f286795f0e0174dfb2c214282483111874a90368210fd62e16aad17db3ee0333fc420659e8afec3c0d10a45c212f424a5e47408892b7bf1c58d1831427276a0c9ea3dab34ec1542938c7a2badd253910b2218038ac46a00a23d97004e2a14d91c72af1c9671a2f39e31bb08f6465af25253d968522a5c645a4d121e120b1c057eab4e9dfd0e805d77b3aec96912526bc4677687e516522d353a56a62b768c650f6105b4925de0cfaff9143f17b2e4afb767147b8ba3a45c8469c23af2060bf212dba1a011be12f3eb161ad4180fb85686f55964284ea52a2ff03fb40c81953cf434ac082764f16d2570e3ed71aefcd423f7edc4d76c4615005b6e8f62fa9290cb054624bf58e0206a83b60231e6807e39eb65809f9f0a2e965587f8a61d1cb4043e7ce9458873a02635457daad1ef2cb99cb0c5935492fe90e25cafcd8b60a3116f0d5dae8ee56a02a9b76a9da32c702a60b78ba33809a2b56fad85b90b5966db8b17e7d86c7c3878b8ef450052aaa4c94c144074556a347b0d93c7f59e36b802c4976b04087a75759b55393a92c080c06be5e7ead132b56efa8385ab76a97e818d15275a8fa713a847b152bfb78a9aa149559e051dd417409e8f04c708c1d682b315aef29dfb38fb37ebe48653bf42dd0e55c708b6f415f8e9b43e74b7862fc7f03accd0c499c9e90d60ca24b1a8ded878157ea9d416e0abafd3c31568da53f979ced027e97d4be281958bb2acf534c4e95741b4330e93e86c2f272adb1d46ec9eb4eb2b064cc67cff0aecfab24ac7c9330fcc8abc26156340fd22d31cc8e34d4d68fa5ed306752af2a6c47c4df21e0fd370ae202336f331d9b3da7773699e68ab9bb28fb5d652ea603307625147875eeace403d1a4178b8971e7989a6e375d565eb0b27dfe9125f004e149955966fd4406cc2c50931564120cc8ec20a850d78ce8ffb8bde1d520d17820018e8d788fed8ebe72ac857a489f5fc022564736ceecfb5f9b0a47f2d9fca4c0101ac3bdfeccb3912dd2e3d9f0d4ec4003181029fd92892fc24c0961a8227c19c33ece671533f74e7d805337801b1078604535833f2bd7dc214e9d112a8544c644a786482365d1faee01a0d870357a4aaa92b757c2c2850358d3f34365eea5185de32b4c4fa8f35c7aede0a8e2828b51fd1085e21d8266569cccdd030ac50fe51240a7ab04e0aa4231fa1c0ea6a69dc4de1ac7b654e829117d250074395e0245fc5000f3f6ac2a02610ad9e21cfbde0cbd7aaa0725316cebcd9ee380123bb7e8d3a2bc6606c8fd03133f9af47cbe5b4af5fc1bdf7cfb4f41b9fe1f56fac7882d75dead1d1d60f7d65943f27bcb54fe22514b2654400e45a5009fd43fbcfc9c18be576e485e9fe9878ad6ab0c84147c3f919e2150f56fa10439fe736a48b0129f7a23e56c0eb70434b10e2980998fcf4e921a3f702482af9b3189efb8d740554290df97f12b444ffb7ee3533149197e8b741b82011fa6f73de4a15613de757890003e58d16dab096d4ae19e1d9535ba9bab4a94c6fd42d3a1d840e6c69cccf6d342c10c90ba2bba71566b91f4fcdc1f9c687d3ee922d11f0449ed25027206b215d0d4c8dbc32d255bf93148d3cb6f05da190d22df8cacb3dc1a0473bf33b968bf46f507ba71e76be282f15078159db617d11126b0f002bb268fb617f6fd18a535b5925c1a82b0da5818bf025aa2592ea2af10e29afcde00df0f82eff30566e916469772a27572231571d4574b330434fa1c01dfaa5d737b8719ed9693a5c03196e1f24219982664139bc8898961b80d4e8690a1f9ac52e24a62c9e1b4b096f65c3483dcdb5d9aeac09f1cfb52aea76bdfca0d491dd80e84f37bfb7dfb0464e6cec380b028f50379fd7300df4fa3786a96d564b39659b9b1955bd14eb785716196cf05c6dc93ed5f7712a73a2d14f8fc19a1e28ac475cf9829c3b4bae78e980b71f6d9e2167b1f2fbaa8cb7a507551730298c34caa1850cd9607c45055922ed0354663efd8be50aaa3989d49fbc90b93a31d78466b3d1cc18bfac9a771e9cc9d529df4348f875e86ece6cb21ae772e1d15f62d52316fa7f49ad89817401939582c771a461d888297ed76f78e33eeec23d03e049760023bf747a2010d9fb1a295c4328019093c478662446bafed8895449215e39824a570e11119c02d4bc1cdcc9de08c4951f27392453e0709a52e2e424bfa0b452626f9114830a176652a4ad445d6a776d0629113135050c34a89c35fa0f3d858daa9fbae007ddaa558217f262a633eed0298dae1b054f8f76e162f8fd7f84d98256c9f272052189475e1137253bef54105e5b268492d61fb2abfac306c870df004ef9e40e5b6c8f10716e1be7f0285a399c0c24f3684b44617933afb6615bf7f55ba30c2568d18309c2464b66a372b19053e0577eb502d83c15451bc7e2e5ac4825b7943eabfb5af27b428a35a8ced9414b65e53c10b6d6621949951bce2692323950811262d0632e4ad82391d92eb0da73062efb7a2e092790dc7a3bd2c07174554a279770a1ab819e81401069d60142d2d2ca6ec3623d92d354781e59636bbb0cfd39b5443dc51428b0136faa94530200f62683788f170d16ae765735a1af3373dddeee6e3f42f91528040ac8c7dcd3ffd06147a16d6bf877f01d50066ae04bc11a0251982b49aa31533bed7821f8ac87f0794c0fcb792d4ec086c21e9bd4cf69365f6c5c5acb825d12f3db7c7ef5ef22ff5c448642e8ed6e3faf2a51eacc5c7f788e1750659ac83ae9bc1605b7d3024800286d6d88f66950b0cf6eb9f9de8c63060cf804065fd4b0c76c1c59a7dd16cea365525244148a34688341c42f795ce19fa39ef8488d946caf8209a75b01a86277cd82c0b2b1c8d8bfb821a0622a68b892a16074f0ce0f0d80bb8b0c0cc00673e18bdd807e42767c3cb768e34ba5d283c0b1c53f46299d31af341d3e6b68258dd803e30c5fc24b7fafd0b706fe5c556e48a59dcc7e21711b37fcec6999e1b500a4e9f9b1b7e8bfa6c6cbe2d1a1b36c2525eb672af9f20e1aca8a7021649a4c6e78b4b859123021c570a921a4a9698d21d364ba2eb1b74e298c4458added19a2b1414e1d68d7d8c202d419e5367c25c736e038a9848bac0c94110e6b5cdac3430a5d6b3db1c8d917dba6897c233fcfba7e7bce0059c6239caf5bd34f3b0fa5cab70497d27ee137bfcf44c2799c7507867621b31abd02d4e45529d1e5dcfb3854569c22d4bbe0b678380608c5224b19b55f2a23db995a763886ee2a8abc4444f79401ede8a3dd3fc9fba246de4bd13f01499dbab03e568e3fbfd3d7ab55bb1458a7b9df77a1bccacbf27617d1d3c83531f0c2e9e50438dfc61e5352abecadfb111549c2e46778baf3f38621226ba56a12192cc72aa52a187c1f07c89c4192a5b778e33ac8729632d93350490e30179bf78eb12e8c75e6fac119dfddf827c86f00a4bd1c70fdd3d118929d07b192f10395240400e6d19381fe87a67b59a7143c768669f376fbf7b136e11db8861e904690f009cd8a2bcab93ef3479b0246a5f8b3ca5eebd079d962b29527965c66df3d6e085b69b55f3c25a56ebcbaf7fc97892719be30ef30caf0c4fe7c4dba4a0182c76175329ec66fc0b186e24deb63adae5f3c914c8dc032bab5cff962cc41024f26a7a58bc6202fe0fff9f88c21d576660c53499531744bd522e3ab84f95973abe4e392209f344a660397cc8817ed76bdc79c277374560a5c9c88a87143a3414e66a332d9986b17ad0828e62f6717288ef88e036ef075061e147be73e829ccf4abe3120e4089a6ea46dc15fee2d291e463bb3e035ade4a5057256e6bfc274595da425b3b1946b228f5bbac30fd3019cda9411d5086c967c24331300d7f3beddbb5527433540c2b83d7f834a85d7840362e61641687b06ecc7ffeef6216e7c18c92bf36b347463951265963f00657a8ffdc688306dfca6784699df62d5581dc9cc461027b20d0a4d3e1dc8b8a5bfc5b20351fd2c066a8f4785ace1a6e57a76c1e26bbda1fd9d2a19ab0f313f9027356c942e48b90eb1bdfdadc58b6bfdeaad6bb76bd72ef89c2a0750105a97ae7b358a117a3a397934947519a296b272e271d24a7962fcaf06f35cf8939655c6376a6dce9ed4a7399348b4dc669fdb21a499aeb8550e898322d0729339f831f325944c60945d4efc78764f74837c4ee21a43787cac3922a8b3f0018c2d952dc3c30dbb7499c6cdd1667d5c398798ea55bcd339e20c35ab615791009b15ea92966547c4a5cb1ea2967b097a8af72c2896d8bccb4376f9420fbeb16d854a48b4647a19908f812d5a33ae8499d35c1a1628c06f5130675bfdada9f46dc28491ee9fcf1db17056ce9a1742fda3ab481a038bd4c8242ffc1f7fe05ffe512eb16c0382a997485a8372f5faeed5e2e0ab3501f93d309d1c698105706af0acc9ec8e0a053964fbb62857860f2d7e7c2efd074b60e812baa4662287438a1fe78ff70f65ad3fb4a7cd4bce398e661354946f9379cd0a3d8ae0b88aa3ecd2137d57dd2007474334813bdfb6fe6ab7fb33e029790dff61c8bd6ba338ad0240084fc0b7e5f28c8278f02da342ac7daeab0b7f5e2a17052def621378d635d0647d8a84d6634c68ea7c25435a6067ece4c1c3d84a90e43a5fbd85bcec8a9a4d633d7d9d0ad1bbf2d0f6095051ecc6d28b3a333711ca9121b491986743e693196547abd14dfca34588776f21f198f63f0d1c6c23be0f2bc4ae733dac024c330713cfa39e0855192f00919d0129a95a766485258bfe1e9f276adf26ca9b359ac62d2b328ed60fb34cc6b92450e5d5a0fab559c131f081d6c8cd8315c9a75797e06edeee4c9e0a46e07444401151bf4ecd13e6da91c4553ec2265f2a917b69ffef2f1e641fbfbf018f6a1b8583300359c5e9e90755d3ebff63ce37289cc11738cf26249328887186eba367416141fbb4f11308b849b51e630710328f526d363f6183c20a2f4a67abbe170e343b08961cd9ad8f32be54942a3b0aaaf44bdd4ae5b0b179706f4d3242112436fd7022ba8a50997ccb191aa2a87b09f9ec01e341084a3c50ac81b1a1a583508b5ed344326622a6ec07be86d97b0c75e49788efc6b163cd6c851d9de03e2544401ef05a29416e75649c018b5074758ece25bf659d86110f72692f989763bee194b7f456cbdaf00652e4c089b02c0215b205507ef9c9771a6a5db52cbec5734c60fc4f957496297d663afc4941def1293cb36f29c517cf3be6795d3cf18d15f4676190aca741ca97972c0f22c24a44190bf11ca06bba843aaa9222ea9ee235b696dd28f380f07a0ef945502f9d898c21cc25689b8d6b524acd5e5ab1d4abd05941a3a6ffd217279a1ce48a6581d684924826a3b5d82696fc59b10c37c7d96376e7e37b6dd09db9472c086ea53bcc63681bb7beb931c37f350773a22ce4b6d68c80177ce51f8449aa88e69cef2d5e0bf83a1703ea6b617fcedb70018370a0833029779d0f33ca0221ec69b43a53139ffb865c0e5d6cff2783247446616274ee44989e4cc4be241631efd54aae245feeaec2213cb0f489e6724b8149db159a0918820dec1233149b7f5499b78eb1aeca4bdf1d971f798ba50445add82123267a85a1d6d2923fde7f6cb15e077c42fe2881de0ad6922a78412aeaf04e9e464e4a185e1ada36cabbfe391eee12d4969cca96284500a6c9a9cd7f2e45e6f20439a6a4acf7e97f240b5a686547cb80066e8e5997c5d586069e56a187356430706f0770c0d870a2eb25944351904ad6e2918022199d8243e3c89cdc168ce433d91814ca9c319efbaca316365d6a06dc250d6f9f49103ed158491243a4d0a60d8063c46265a14c061bd70051c97ac6373812b08f7f924797be2b72e1530d1c8e5621d1645489e06cbff39c42abec17181ee3f329124cfa9265887c99e44f06a119be82c9673b56f8a8208fba88de8a0876cc673e04dd825cab732c1f3ab9fd9e8d5a9192c7e28f6b99ecca73af7c9829f2b50b20a4325253f0463e415b7e3ec8c49f7368e308f46869ca416ca3541af0b506b76d64ea8fe0bd329b23838bfb44a66404726d4ac2666da55f2c09c3c8a1680577e80a2ca7fe2fea21c960adae0a4ac02413e4bbef228c3d6e6e69bd673f2979305bc0c554932e224758870671448811def58d9c57679043ae142fd859b824f96de33ffacee2a8f17931455a0b7ff98e50e8fc8e2e124d427460a60a877e441cbc837cff803fc2e5ead135a34af7c6063a16f356b35407ca40e1e4acdf2b0050ea3cb1b7a144c814c72e81b86255b2762e031aa60d5ad39af9aeed75869476735a999e9ad0ddd87cc342f783cee2ab638a54c1fc2d575b4f5fa1811eed27d71426bbb592a5a986c384ea591e6b2f294890081b38890f4e34ffadd19eb69b313f43d8a615860963d8852a21162d10b99fdca8c895eb510608c4b7e7673866e9a5960bc9620471f0708b5c328f2da64b0631322c6d14eec3584bd3162cc3309fd4c1de9964d53b64ab6b7d1e16418e438348466f62845b75c687662fb18ff5cb0d57b0fa7dee88e14c62f629315159a393c0810c7f2867cd25de292e34879818bb1db0538491579f658e887d6598ee6d2d31cf7d78d2707bb052036f1eb6c5a34f56c0b7a263723a5438abe766601fad94a2519e3ebd84c0b4e84df4cab5402edfcf6dc92bde6d123b18da1117622bbc3f4d8edd586709bb26146b740569944591c6b67b14d92712aaca06594faa0f17ee2bd5ba41e75bc062771cdfb85f5d068a9d9cb519c2320d35fe6ff5d392c07d64adbf5cccf499a5d1de7df9df42c8e39efc19d0389b94f4b0c74a87e81adcd4231f295639c518f9b9a08793bbd7634b5c0416fc027cc612e7d96bead6f2700bbde923eb5d4326b2fcfa807512faa44012646872377c16e977fe4c32516a11ec7ac66a77659993a43a871d7a6125c7cc29e4a650872903f0e703afb0f10c04b05a9cf60765eb4a6c0cb6876247c13c9ccd10b10a18d68f16c0584b94568c687cc0cd4ee6c92e7cc661d0e2fcd32f6d6d0f39086023da07ad58baabfd465143549e2f8f0c1a998410182cd21db5c63a77dd34cb9bc2f43c8b63d11f642377af89f2e662d76772ce121b112b8244285feb47d931c845d1ebc5cb6134dfc17e8bf38574c4436364508eb1ca9dcf81e62328ea0c11c24c97f0210e0086fa32f12b8fcab7fd11d44e890bfa8dbae9cbca7f1aec51aae008b2344ebe861ab0ec222388975dd5832be4e6ed03544f1ed43245789777d595dc3015044a09587c57d3425201a0990c0807e13828e350a1b27a22aa452e05eaa1b8d0e4aefb52b8c8a169896666ab22ccc96b967738b18d6557644ab1cf0c5519056f87b8dc7fc009b0e3949b41606fab20fc3b4e67844a7d6b35c782d6c515dafd12967a9dce80a8409c3eecd55036079a4d1795cb414a737cd8be5f4baa7700b7d405e5c488bc133c50326c66478ee288ef1b7d31779684d7861cfbe625dbe690ae06428627cf907209b35abe88e09b556f9dcfb1dbcc5b3439420aade1d0c0ddbb4e60795815a647486464af4a2356690e50406c1aad249f7120e785a631637759fe115f9db290079398d73e40eefd33a0b9d2e169b731516a19a65d35e15f31b4f6761c366ea0f077c2997980beeabab4f9dfc5d0421b79e1777340460990473b9f4084923008ff4932dabfe1838eafb806b6d5b01ce51bd57fa60fb374537e83fa1f597f05c118c67f946454d8d6fab9084e12f93d93900b191f8b34b0c38b34ac9a2b4e417726da23a2f1346fb192b9309a293ef30dd2c278fb85fb1ac5d1251fec9e5eb84fe14a404930d0ea6b473bf3ffb5af1e3ddd32a0230e90fc245c30130b9303d2b96b7c4663473d88073aa8b3dcd5b21a96115042779250274ce4f9f9cc08dddbfda35326130d16bfaa88dfb9aab99cd4f8673ad69ca7cf43eddc9978d06ef16307ef1c2f61334a80c7e9877a33401daac6b89479a0a99d6444de12a9fcb58fde7c702de0682c796a57731a26ecae483b4d890bbc8850bca88aea65bcaa20ef6cb93f8c05f28549022153c488cac41ef27ce575ad1048b543d14b086ffcc2ec798168b662c9e99c917d99128da979e88697f915550d5e142b61a651b1bee501ce9327a7fb0231dc1663fd11554f4521e3f05c2efcdc3d10462e94ec1d688be57f2719e689efad090f4f00a2189c40a6d4bc8296d1b50f1d6815a7e90f1d183fc119e054a8aa82e0f18d8cb30b7efd2f9b2f2d4de2147ae004f9834837066712e4feb4deaf485fb1390b7cb3b2fa703049c391a2b4b4b9165e9d687c211edc94f1899a498c4a9d9a63e86c808bbb99fbc5a66c08ea83945434b464f482a2044d45533b20ae4a3904c82544cb9f226a16ed72c78c7df5d7b1cc8214a840bac78218768fbe0a89520357880b0208d0d9072439960c52bb06d26c7e6b8380e8f28faf38d5ea7794f83858f81c878680096b1f074c3195d9b824122f89fa981b9d826a35db6d01cd22bb29600d51ef231b4c87f43c2d683ac059cc50918a28350310cf65c891310d6f67586540104aacd341c0ed299b52ea12dced2ba63f552b914e9c1878d0d348af31d5d2d38869ee621c327ba93284bf1b1ca2bd62f614f4688576144aa53f3f756de315f563676d80eb36d22b75d233da7cf556fb58c01adeddfa0bbb263be29b4d8a295e4919af0f9567191048cb57920e06011df526bf12a64e8154a4565dee2fe8cf23db4a694972697e9da1c3b5ebfbad712e5bba2e3ca54ccc96ccdc77bd9d57ffaf8d5bfc7eca9579e8ef92f8f7d88282f3ebf30c9c0dca655643589c015369ac5cbcb25a14b19666349dda0e5bf484a777cd48d8901701056d3ae90662914073a26471d0139790d3cc6a86dc59069a92139ad874832bde631b6af2d167060cffe11f4372c27364445527ce3fa04eaecb83007681e56935ca8d9d3f6b8fb9cb206524f187849747ec117e6740937f80f91b6659b0aec951259a28373af2e4c1b76616204d9b845c97496621266071212f7fd4a9b44ccf1cca7938f98e4478289cfc8f66e626aa2b7bdbb54fa94cbdc551938419e28272600a26ef42729623c87c5363294daeff93339e7a3f15cea2e5f11aa4b904de41457812501038e36e3a00a07167ad8106a071e75a8196c65deecb6ccc3257c3b8cbdd65b79af50731b5c145c58416cb91327acd49c96a7814f8d9db8de8c644fe6cff7b3b8afef4e093f6b7dd6eb4c9de5b4ab9035e113812a6131fe857bb7ef388dc0bce9ceb93e39dfee94eb7d3ed743be14e3d77ba668f684e2802fdd3d30254888b833ad1faeff6b1eb290d3a52c8c9716745121e2fd603b7e6c60ab2869e125e0e75ee4ce1e1e24c09592f067bf3a28d881917093e6f56e365e7012960011904d6ce41cec46a8f0591e465e79d79582c6aec393d5305188da746859e3da256ad79b21ca42c08d574329db0630fa84e9cc0aee984dd359d54ddba476037cde1f69d2c88fcb9b7477c8e05d1b6400ac8fde90b30775bf7d8b7ee74de9ab1a9f64e16c429547726de657da2694eddf5504f51e10ea360048a533318d6b4661990aa322d65191064595695c99abc0781e9a71436851ba8f5d6be53ad3fe8533b6fa7aea2a708d6cff936bb3ceaf879e8e938b79e5e9442dd50e3dcad4e7f32c869f1b9ae2c367306304560a2b6602061566f05628fa69b017d79d479ed9abadb3cebb5fa5cd9e3e9ff5b73503a613552710eadad8c936855fa025c77d1aaf4c46825ae398f562189e05ab4416185c2a222ad2e960aeb118fd357a299eaae4c73842bd413d50286df6e924e1fd54ada6cf3a6a9e679172efc567afce7929a3f75d24ae4a32aad50cb0b6b54dad2eab45487a617a6d5e5716258cd2c95a5f679d4e6319b3535cf6b1af13ac3ea04a5694d7aa2ba439c569d7ba45de73cdfb9475ac8c1ab13561973510f4fd7b9bc2ae0ab73ded3badbbd59d5be3a776239c8bdc9029dce874bec0596b802fba8c5d50da3612d6a726e58935eb49ecb4148dcf19489856950f0d42cb573ce7bf83944d3b0a86cb39b2aa6c1f3526e71e53057d027845b08660766312a69080cae1a0d8f679e61b4373d9fe5b4375da3e5b3b565f144d35c9a5375aa6ec73377bc9535dd5cd91ed0dad3ea71bde9405b5a6f7a6bba3b7bbdd9f566ceca43d3dfe0defac0bd652aa4db9818d998d8991918c6bac239b0f015d67ad3d1acc7c9bca6d9d6dedc4288f210651671ce5a9f278ab3d6e789a2e989a6692ea7aaba9caad3ed762c088cd71d6f5d59b6d70372b78a57dc629f6fc53fd374b76a4e308786569308bb4179885d21ecee1304c66d1e9ad8f1670a4f3d78542d90c703c2599f680a946341a4e7ab6bab638f27e69979b76341e45e359d4c732db2c4d5a278050a0d81b4d94d7607a69576bde94b4d5ad33f68734551b45928a4e65254886d85565d9587da4a6b9d85a9934044aab590edb1479ebb851ccd189b67cf349db2a3d84f3f75f11c7ad15c16a372ce49f94d09465513d5eb118805b1f4aae9d4b6c75f50109ad143948976143a9b3061682825222242894e9d3191b9f6b6083ef7b736659cf367d76d107b14ca39e70d50144dd19ac209194f30cf9ce7170499ae9010d0501e1ac2262ad4b6137ca6bb5b20500381198827b0470f6a1e169dbda3ec43434444c3a66311447ea1a2d6c8e8e828ca584442d219eb88888040e3d1431e9a5ec482c01f659a46461b1c3bc843d38f5810f983410aec71e8a3cdc2b4259af2cbcbc4c249b7b710661d3425991939c4d166e1c67dde1456608fc03c743597a2a76b77f78ccd1ed09bf35d4e28020b5ea051903d2e2169338a4d4c34dd748b8c888e82199bee5e4d779b6d47ec00cef628040207d902e0230a2e1285d5741d45d19ac2b642057737bbd875cdb4425b81e501adb147d39d0581dd56686d9376b459a8959494b2921256327dbddd825785162c242529295db8609a4b4ba98524ac942404c4c26190360b93580e942eb047736969099f6793c69031e025f6083414ee10eb635e7e37e7ac3dffe996007f0662628f39da2cdc2b860c4decd1893db64f3807d41e872c88fcbefe897637e9f33776c163e15190890212135305676262728d98988a9898746a2e45999a46782c7c49c825c07f9a4e3ca004e857f3d0ccf2994d40eeb1b1ca04f2359b8023adc20df9279b00a2c742f5b1708f809ee799d1f33c518da6e7899ee7b077b22086804cc081ee85a0ee80de8b1e4b80f3fc0ef1da07e034c200ce87c06be7edb22ef7f608de336fd519c5a69a4b575dcf74fc3956658f2ac61c985e02ec59e717fc693a611f52753e9bf04cad31d6da4d1745ae6606a7e90404638d3106a14108fd888cf1162ffd83e1fc79cc260008bb8ec3f3994d40fb5878f401d07bfaee3766c1ab9a4ed82f3c0f88c29cb83f7fb209307a2c544d27ddaba6d3f3726c02d0df23bc8ad901e85e553111bf6a3a9d2ff893031e900938c83d760ef263a1da53d95e2fedf572bd3597cba1bd1cefcced74cee57239accbe572b95ecf6452df14ee1184f2d0fc17e01139e73b3c6cfacc3cd4a7d01c71f6c13678f8cd93172604c6d19b61569652a6177bf42d2ea01c596d320f3f64aade0afafc42b8e54258d37d90876a0766312a28692884271c5156b8bad65a6bcda2beb225c0ad109887a7b9cb4d104bb3a7bd2ce4f3f97cbd2bedce66d92ca3e5b42015f8d3193f685785db58cc09f7f027ec097dc25618e46e0f592845955e26101858bb3118d81899188516e8c3a2072385e09191fb109b197fe7a488b48b6bcbe79aad0728edc65d5dca2fafa131aa7814f53b27d7e62c3d6865e5e8b9a6cfb89c6367b95caa69b3d4c8e5524abb71d6169756f0c8c88751c5e091511136dbd82c83adcd69e363c4ba4afe5cb31715a5dd3899c4ca7175e4c3e25153539415aec254e6af18d66e8cc4485c85a98e5aa0370df3501f6923ddb640a03b5cb1cf0a724d53da6dba916005228800027d689e1e040aad6ad26f6ca6f672b2e9cd2d84a99379785e81485d0bd1aa76e7248f1f49cd74f2783d374d1ebb735fce640fb04355b4598629a5cd610d732a6732b1b90b7738c1886fd7292093e9e7ebefc7fe4e1d17f7adf003269e1ee484f904f2d668acdde6f24f0fc1032134f0c1c88b7cabc0244cd4be733d0fb591f034b3eebcfa9387e9aa3be7f8d379eece44420cd9d642c8aea96ae14e7acdb22ccbb22ccbb22ccbb22ccbb22ccbb22ccbb22ccbb22ccbb22ccbb26c199028e998a89da7834442afcd74f0774e86484a43fbc0ccbe5c2e97cb255cbbf3d26de7245bdb5a9113f95683c03c648b8880ace72d11a819590741ae6906f3b4407315b2bedb55e8373633831e825cd39380bbf5011e0095ad1090a7a77cb70e87bb35e7d379e0434f1aea7cee0946bccf8335b7aeab4f888489a7bb9ef2c0f4e2070f3ec8439d04d3c9a11c5327b119910b6122eb3cb7cd439648686626d685acab6608a031aa689a424843304848ea6bb7c544d6f5145078662676ab392b8450d33069826bb6c3377acacc4cea8ad3449c1e040e0d0dcfd379bc74c52c8820d681c00c16b01893e9f49d7bed4741e614506bad7db74240de07cd747ecb73206f7bfe33d903f03ae860dd44af739e939ae9f401cd303184f0b57fd06e07695aeddb04db40d881cf8139a9a7804c268d3bacc2ad6aed3ed761b3138c38fa7cc295e540c7c5fd4ee89878fa073d85cd7ec29e10a881420f74f24f3fcf3cd05379295c32b968735696da45cf91a54ecf5779e94556bb2a26b2a8af6e12c835f71ae4ee10ab1e72859f3ff5092e565dfcba9f8bbf87df39507d1502b3d4cef06cebdbc2b3314ca7d377ef593f32a7f2d2814ca99eb31e644e1139eb2beea09398783aeb2ccbb24565cbb242605eea296ca6994e3fbd156ed5e4399070f9a7eb183e3f5d2771070f30f104f29d755cdceb5d01e840e654d16fca8875ed466ece6462fde76a73c87a910b6432b10e74596f590762855b04faac037906f2cc1e807520e19a875ae801ee00e427d05bf70977fe6d9af99c47e4ab603a015d2093493b906b9a44ed446eced4e630e7acbb0a75ed6f6ca69eae33b5ce0aca58858e104d7fbaea66f174ac37e0154de08877b7235ed379b915f2f4b76eb6ee069949473d2adc22d23f5de7bcfc28fa6183475fb04db7d7792e013eae6ccff770174df5c39fabcf47bc2cebad7fc0aeee138ae0f3d547bc3b9eb7cef3d67bee11f69f8f7881dc232c3c520090f7fc0320ef39f69e50842258f841cf7f42118eb0b79a29f5116fcf4538c242137cf0735533a5de7a90500411823ce837e205f211af9bafcf77fba94f68be2dea29eb9aefea9a2fcf1df1eedc112fea6e17917e1676e022bd68b52adc200f732e928ca29eda2033a5befe873c4c3d4f8bfae9a6d999d5ad2214386e03d689c79ce2d6447dad6538535314064b54d91886ad2bc21e567a70527c5a33003b374d0d7e9ba669f2d622391e7e6bd77af57d7a7a9ee7e9a85063605465ecadedd52905b42a7951a1da15438c73a8f4b5445c3b958256618a24a1b57843bd306185ca221c5add3124a2f568c74901b812b9048b56263723a315ca895a74b4b654c0e04aec43446185423301698d2aa30a55589dd482dcf858638d35d6588305e041604a0d79bdbaab9bc513aeee97cec2ea142597b4267da9a8d2ea6e9d17560b46b4d65a2fad403e6a1eae2e981dd35ae4e4c418d6a4a4d65aeb0c1884ae5718e129dce08d5dbd885c54954f3f857b1dc099334e7e36c1f9a759e74fa18833ab23fe09799e290ff866d09bbe375bdef3526c6674cd6e06b42231b935bb515cdaadaac05335a66b769372297ae6741cdadd9ad7ec865d697b11f9cff5793da0e7f9d4df1aa4e6527500bacfaeb6bde9277b0afd08bc4314b56b1c22bf3dce28ea1915669c5da5b376abd93de240ff9987ed9a5d2528be35bb4436ed3e7fbb3d7af4794226385f443ac1839c6b78fcbca13567f3343178a3d49b1c9e67eaf3e803f44d3dffc62f24158af082a8e705add92de268b79a5d282ded56b3eb6669b79adda3ac769fd9257669b79a5d263aed56b30bf5d56ef5c8349db686379de94d2cbf4f73cd9bfbc80353336179a53fe220ebde34d59e879a4e476f2d364da1065eed6ef7081f5cb30ba5d6eef3b31b65a6dd6a769dd2b45bcdaed9e579ae3e0f57795318621d91872e5ef3669bcb82c05f021cf73ce19a5d2729ed56b39b04258987d1a301e4ec4e781ece6b7637faeef34e9df1b9d7c7d9cc4a6b764190faee95d0576253cfae7ea554a8e6e75d58b30bf4d36e35bb1bbb26385f049a5bb4b747fc395cb35bf4a4dd6776f739807d9a239e9743ac26383f04f04473a6dadb235ee561a6e1d205a5240b1884ae57c88044c1348347464540222727f54fe11e017decaa3f94254ddd4c324d8df3f1d9daa407f4d49b4cdab1b87531c7b8cff6c174d22cd0f2d0cc56583b5f0358b0e5a1f9db04337d6757d5b6cdc847851d98ee870df2503bd00c292277da7da618f59dce59b0739f7abaf93a4f8f54a1073b13ecd50981c3f3ad3d85bbf866978e88b15577a7eeb13c20b4d5f972bf20a1094344c022a3a32005a40aee0a2db8c91e93fc435e3fe42fb138abefdc10a698ba0af101a5a0a2e6658a7d7d30c1e858f09d2b224db27003684b44dab5818736d783d0d5eaf9aac47ce4f0a0d58191ad82d12be86093468c6580a83914a29028f85883d0b6a4f9d4315514b6f2a0f8e6a8183c1ac29b400218125650fc54f841939ca226a322203b221f6f464234bd81307c231a028970e88ac8d824f9d4430831649b40129b09494313b6d4d43f0891941682bb05f9ce15810a05fdc87590871a08d6c9f92e4d859e873908ccd1ee24dff9ce933230e8abb30548c21243ebd39debc10d11fc54e801a01b1df07d3e1f5055733a9fa3ec5157f4e97cc610427650dfb92184be6d5ba14fcfb3fd9d70a7aef356e8db24281b646cbe45db2612b47078e70301a9eb8af2805cb3479e88f38180dcf345ac6d7abe7343accfb2ecce55dc41c5c4b4a7037e2a24b4d7dfa9bf7aaf042fc8ecb117627d96e7ae6c014c30248021e1d91e2b5cc1ef3c4db2725a18d2ee356903f599aeaaa3ebef7cafbf3a6fc544e14e1dfd546b2d14a15f5bc0422a3cd3711ee2b54e6bfa6fd14f698ad35c2ec5c00d33f4e9049c22aa6adb3af939d126cfe554b56d814027689aa1985375bb9d4ecda55fced25c2ecda93a9d9a4bb5a4699a53753bdebaf2763a35970ad991a6692e979690a6384d711c8cb3a48891e672692e979a698d934ed2e454dd8ec7dbe9d45c3a254dd39caadbf1d695b7d3a9b9b4469aa63955b7e3ad2b6fa75373e9952b655ac8942672aa6ec7e3ed746a2edd93a638cda9badd4ea7e6527c264dd39caadbf1d695b7d3a9b9940c4e539c53753b1e6fa75373299a3b698ad35c2ec53a9e2c6992a638cda93a9d9a4b7190347d93e672694e5573690e3bc54aa93e7b8a647bb4cf67479154cbdf28169adfe899dfa8197a86a6a16b4ddc7ea36cb9df68db0acef8dcb86a132546dbbbd12a1031ded020b3268e899877a3492024570e2d778e4489f16e34cba8ca8b2873a6b8e082f56e74cb032d6043926895f892e2dda8f2b3bb28a17401848a1a9777a3609f6798443c23ee731f8c7562ac13639de77972719d7df61399a5ccb026794e33bf4facae734cc4151a293ac0d8a851f6eeb32a45e364cc16728e8e2aef3e9321d071b4268176d36e703a6dedb36b329ca990e76f4d95f65b636d5de6a9a88173040f932158efd66692a0d02211e7c58dcbbb75d20340d6cc5021e39aacbd5b2bf7993d2aa0b069c146f96e0dd60093e8c70413f739f70121b3a165ec14d7c1c92462dfd8cfe72266c36e54bf331599df196bccef8ca6bed9339ace5f6470254984bdc96af2ee5cf55c6cc869eba28c11c5cabbb308686b3b966530b0c87877ced282026d3944451d1fefce5b0e4803260f1017795468bd3b2b7f042a8e582569d18602c6bb33d8e33e1b9ffdd4061b7d9c7d04b3036a12b1636933c66b050d275578bc1b2731b88073a27c7246ebeddd42c44f14b7253d62087937d663a7c656122d3d7f72bc1b6781e551f3b2a704197d8ebc1b83bd73bdf9520349d6931eefc64a31bff1589807f3bf3195d56717a17553b77936957d021a087332e3733efbf2d84b131f33246825d5e0c4bd398c5b111d52be9099a97877fbc6214e7e20290b23f6e2cd42fa8461d901870515b3d7a8a7462861c18385932279aca8bc1690418584305d7f926479817f5ad74dab8146bbd9b1c7be0106ebf5d83724dbcd663d7636c926c572eb97df429f73d3c4e7ae7c8e8b90b5cf51c9f2395fd9630ed8a4cf638f52b67bcd20d6ee95cbd7632fdad2ee75ebb1475d59af1e7b949576afc8c78ec147db63c7d0a3dd3cb4c72ebcc1137bec421bede6753d76a19176f3908fbd35d2ee1ddb632f5ad3ee9dd9632f6ad3ee9df2b1177bb47b97f5d895aeb47b57f5188b5a9247db4751f7a4a61ca5a2edd48837e73cf6985377ec11351a21dbad737bec4637daad437becad8b76ebc01e3b062aedd66d3df6968476eb928f5d89acdd2adce3f55333bf839f76e971e5d3339fba0ae453b339699f76f181e4983a0617668f1d438b76abcac7aec444d57aec4a4bdaad261f3b51adcf63272edb9d637becc2b1b3c72ebcd2ee1cd8632fd2c81567b43b0765250725d6eeb44ada634fcd52333fa88eb3573aa24733d2afc77e74d5ee74ebb113b3a4578f9d3886f7fc793ad093cef374f5dcf2c50cc3a39e9332c190f0a9a7ec313d9e462826688f1d4a49bb51b0c70ee407e57aec407dda8d623d76b44a4fb1cb13adc2d143b2cb3ca5b250696f8f1daa4cbbcfe5638f0243f6d8a3ceda7d2acd9c5a8fdd29addda79d769fefe4d66e6df6d8dd1cfaebb1bb38daadb71ebbdba4751a83dd6948bb4fec4e5bedcecac7eecec15e84a6b57aec4567daa425ed3eb12729d1f35a3b50bb27e5a9acbd294ba1aebda855ededeb2d8f6678d44ff6889a53f98d4a1933e47bba6a4e99ef6904d353ec123b919576b3cbc7be59b8c7cec2b17df2544b3683eb85ec92658362e37aec506d5ae09d769fd8816fadeba52d5ad2eef38b94b44926da7d7e528976ab8f01f27bc9372d8cd000673179d434158ef082346796c8b908454480be909c30e72f30d11ca142be2a7e4dcfb9684e7f54c030daa0277de820557ba1265d219322c785451a0506ca24854eba526445063a3008f4c122e94a98170f1349574edd9b615e347e17cd766a3c33ec8a92573f0b81cc26eca6ab7b1d9416ff067aec26909981d9009e99b4b105e126c15be009e0fd0d1f3404a0a80111004f1e9c3a34659001030c46a6a9a1d41207cf9e01ee7021cab36bf001778032c5bcbec2daecabf24b00efbba7bab642c0a0270d9b8a51460f1b34f47e434648c20b189e36486570fe070d1a00c043870c30304e49718892327ac01d36f8565793363bcbd5f51f02e09eeada0a01839e346c2a461935147bbf212324e1050c4f1ba47a01d00000450fc40e4f193861d064cc3085418a89c3306a09cab36fc01d2e6cf0ec5246dc4183871c5a5cdaec40595a01d00000eea9aead1030e849c3a6625491d8fb0d1921092f6078dae0a200f040cc0003e394148728a80d4fc528dca1684c624969b3b7575800f0d0c13dd5b51502063d69d854243ef57e434648c20b189eb2ebeb9001064f46a7a926a90c1c304431410d372c69f0ec1870870b45cffe54c41d88519f1d53593d69b3ffaaac3a6480817baa6b2b040c7ad2b0e9c9a9f71b3242125ec09062607492e21005b541439198f4e4d9578091696df62011301203e3947baa6b2b040c7ad2d0a9a9f71b3242125e109a92e2d01495010ac306260dc3e212d1b30b71870b4f9efdc21077701a6a1179a8279040c4941407f754d7560818f4a4a60cbddf90119230c7212ac3060d45e2139227650fc103c52e6df6210d78804314947baa6b2b040c7a060cbddf9011527689a03668c05064220e9f969c3cbb11ee70a1c9b323e10e4a193e9800f14a9b1d08c204a03668704f756d8580410c4cbddf905176550d45a627a7a62160307b071e6469b31719c0030d45a27baa6b2b04641af67e4346c427a761d35206cffe131a02e20e4cc1cfee6183296df6a30f1b109f9cdc535d5ba1e152efa7736a5ac2d06b858ac6246df66094d1a929837baa6bbb74a1975d0a1930787675873b5c187af65e8b3b2c8510faec494d606d76a46153060c4ceea9ae1776ec9add9d9bb8039367cfb8c3d0d51577b800f4256df60a41671a2eb9a79abe2f79f61477b8a024e4a4cdeeb6424bae8989d92fb81913b32bb9272666a1d0b39fb8839267612e4269b367a1aae49a9868a2295a8dfcf97a165ca1ebba5bc1457229b841f7c835727791bbcd312277c89da05dc8dde6db6b0f727fda7d3a99e3b5f7b4b3eec65baf7dd5ced31a58ec2084152433deca53e7dbeeb611cc44cb09b7c9e6960a3746566d8c750a37eec2cac74d633c338929461bd447ad3e85e7e968c6214c31ecf5e5a12822ddeaf2f0a7a7450fafb556d4d081218c388995e6284c9587b8d894e4c5156064d39f9e0e9b42e8b724608861086c491fe8341d54cd827f7a9a5bf50c117ced28f0755643008bc610422b78114942adf67cba88758bf07acdc3f5b5d0791a1979694d4cdc4329cc9256332908cc435cf490a5b6f1b5632f4609915d688069f33a1b0285069c8a2c2f6eca0841abe395eb52802b55945084845511a3c345cb49091f584aea14c999996e41e03861134be304c6082c3a2948dc11c34126a74e901c972fcaaeb01d53ec64a1657169513b03c4ca15313c725b8c4ab4d83242040d8c4f1bae132e5ca83111454f1dac5c590c3733625e5a902a7ef876e489ab31040d9f248c1c199a5686cdc91732435a14608f1f3b2bc8901c695167454e0b87195e71ca00b91a4b0209230b53478d8f11b43a5459be989c2dc9a2a3849517126ccc117b6202caf20f960f9298a86a41830e95da0677bc689cd07203881bb8b1203194907d9dd9b242c7d4a26cbba186c5151f66ea5c19d1040905c68e2c269c6819d1a46a0912155b5472badaac4c515bc1c72a8d8bb72156865cf9b3b5a5146353252bc04d0c6bcbcd881a31261f1c27aed658e1d155652996dbb2068e103960f60819c164cc59982f6caec66890a1f25aeb2cece1f5c6ac871cac2a291d59632f54a49153c2abcf5ebf3aecb5d6c53ca59a6a3be1cd30213f7e0385d2903c39c295c48894183c58250f56098f558cc7fac6637dc283cde2a182871a1ecbcffa44d39caadbf156b607e43380071e08415595a5f59587bc7ca6ea6eedb5269045638f382d0ff35b1e62b8b13c85dfde5e7fe5298c9699b2a3897d76dd95a7f097569ec25958790a5359e5290f648dcc5306c84cd9bf94595c98ea8a4c2b4b6d65ae2ca5cc62594a97a5789e3da765b6fc96bd54dff96bc87706dbf9ce6344be33d9e77c06f49dd13ee765916f53ec739b91efecf63bf29dfb7cf6252fedd967cf39c4f05512e7ace1d6977667e4db67cf56596a8b483508e62aac9cd36ebc86e6e6816dad0d280a9f76e3b1af3323d998590f6cd96ecc95a58ceae2f26299ec6937a6faec3847115fe124c65a9dacb5db7c6b5a81081178c3af76494cbb430c5f4895bfc109640d829e1d8410b25490670feed86310abd59e3bd61472e4167a1ce9d8a3cf4fbb0a31720b3d8c54f608b492d00ab53d574851518e3db24cda608e05ba42806ea1079037a34d4ad99d2b84c82df42042d9a38e2dd1360d850c0dad5f6d5451c88409ac93d683d11522e4c6d7ca4c396729db0d7ce72c0b3d5abd7cd3c20b74237ed937863f40cfc2fe84f961fba5ab3609187460d0f310b3958193e345989cab38644c6039a184a3e2a14647074ac7c786292b94e461f1c5cd8a341e392a30b13228b0ccf071d312e4762600606af4c829f103cb8f2c6e7c54a890b9519239d9e18604727be1418a04808091518e596d112bc01c1d5d5e36ecf4f19ae3a43767cc18c5429c2b2eecfcf0b224cc065a8444012386c714397d74734e708002743933b64ce993474cd90a33ce11232d94c0d8fab1bc726ad1f065ec2097cba93937ad3e97b32247c6477d0923314c5d8a01047a95b367df0cd3b2ba4286f787a793399904539319d8c2b901972d5a8bc7dc345376a05bce7552277512ec05606e6e6e6e38eb054b33333324b2ebec6acde588ac3387dd50ece6a66be3a6f65bddd2b82b89e5810e861809e7b644332b1a8140cdb6443353e3e13e8f273c77a7db1b9e69aa5abbaf1d83407b2e87e2ac9c737aa6a9a340a0aaa2e6f2cd344d4dd3d4a88f48711a8767e2676bb567f6d9daecf8c46606e7b3b56606fad95a3383fc6cad990106619a692e97cb9d39d46c7b5b84cfeea75d2a6bf19b53c498e4e1faa2dd182c4c88159d36480f863c2dd09bacb69776a3fdc2a2dd1e1664ecb79a21471b1684ecb7faabc9e735f14b2371dbc7492412d9e3c518638c3146c34b074b5d2d30de6c7529b3d02a9c6c3116f26473830b418fa966681ff2392c1a1dafeb893cd7e292166bacb13e7750d43ee56130531d6bcdfcd13498442249a8a58eb3305632758cc4c8104c93cd7413c27d6a9a996340635b1caabbfd6082b929ccb1c714ab7d969ed254398b994cd981cab64b536d01b1da645e53d95ab10f7a2a6b994c39539978cd64ca0e446bcd80c6b6b887409d70035b55b8dbcf685aebb3a74966644903a695a53497ca1ed18caa5a5a60bc51fbada9307ba6ae838ddaefbca6638125cced771653a19071f33b6be5d8236a8524a2222ccdef4c759ecbd4ce89b536bff1da67cfda51d600233e4575175018cf4cc2261846eabc6ae3a42e04d5b37fc8797687537d9b6c40b4d66c9b6343e3a3a703816d0b06b6cb7ac1128934978f8ec8423f9ceedafd35063be3a89eaa69eaa9eb5c751172aecb7ebe92c8d77342144d3361d44c336134a7407866d246978fe320df0483c3652edf046bcb7a9d3433d060a6135e407eb5327769b7aac419bee439d3857cb117f5d40829d85780d45319dcc8b205867cf18817e317f7ac78c99244be5d7aca24036286ccca8cac826212844fd78b3d636533cc86f35263c76ed8f15617567a404f69a566c2ae7ceca1058db1173b08217cd0531aa999b08f3d76a39ec24a33532735524f99afd9a2ca53a88559882e5df0cca4ad9147baecd81d70ba168e201c61849e67e1799e193d8b9ae9ddc09e500b4510a1c89107da1760be1a887507a47034e0e8d0318644be2300093f68a6b4272481e9cf060bb3f0147a7b3a906f172277d97711157a00260c41339dc2118a7c80baf611902f1c01156236d8738a855988939a293d5da7cecb4059d9518f40765478a473d4cd3702d88184473ae191024e47dd01a7a3c2118a7c805dfb08d94f77801ee1fd9095780c2b7b6ebe63471fb08e3a2a14a1c98b88da9315235e56847e07b0ac10a369a6d4311b46c3277498d042b2e349ab35d1d8c484e1b942919a294de1f230f50cb45afc1bc31d29e0f4ec0ed01e50b1ee0839a99952df79f9c882d3c68544be996b2b2b79f4818797750f2feb3b677deabc9e9bbb3453ea0fa735dfb14f3d8369a6d477eeca600e30ef5c818302f9a2ac5b91304e9e2491c897c7ba457667bbaabb00405cdefca07339dfe9783b9d4e98d3d0f29075cdd76473c27cb601acf5d4773efbd4b39b9e1281153715627dcada58bca908a658b1b31ce25582c49b6a305ac47c41165153f6a69ed9f4d4882bb3336331962471e2e5d5c8158d977a707afe23f5338b56e7aa9ba6699aa689d903e49eedb1e918638c716641e43ea7b11efbd639e7ac5910e9e7fc88b2c0a66badf5c982403f07f7d8cff3445910e7e7d823ca023b8aa62c08fdb96da2a5391644fe9cf3d435c71e5116edea3c5779bad57577c20d823f95a9ab9f9e4a10d8abde83eca80bc9cecb790842359dcc73d56c4ee75217820a4da190537814c7df99c59845323197cbfbb498799f3b7bf4a96f6ef039a144e9448bccbbdb575531afaa612bc1caca0e9f207d5e550b9857bd027b548dbe75b3c8b78ec41e5b35789405caa35a5864f1f1a853608fa8bf0dc173a7cb94386752d2304ff4c28a903d60618c6079d329596c7cea41f698fa117bcc2dc11ee8078a077223f60894e5e47beaf7c07ccf7dd8ebf950f1bda05e3eebf57c02bdb59e8f3bdff3f5f2979ee3a49e52df9e63ac2c657e0fed159148a4899eab7aca449b8125eec41f206a60de5e1b384a966b548c69827c77fbbd3278762cb9b30409901e1e2641aeac9589238145cfcd9ef7cc1c8fa2a8b73eaa3cea45ec11056acdf4da5b38afc37a70bdce0a7bed40f6a83d4dd3d45327628fa985cf65d5f89c0fb1c7dc04f6d833c79ee5a1e55917628fecdaafab975fddf594faaeab3765a9d4572f6a230faa5f3dac0e4296d2befa04cc35b65f9d043c9efcbabab971d5af8e93abe3ab15e7c059bf36e972560687ebaa04dbbb1a695164cd09581a20ef6ec15637b709f72b46fe1ac603c6abaa07b14775c40c307ed888093344cfdabbdb47d12e8fc68051e64d0a9a2661d05ef4ca9a47fdc71ed1a2cfc1f99cfbd8634ed5a3c3ca8d071821a7d96b192bd494e420014b9adbab9d4cca6b6fa5923edd01f6a903b1c7b4c71ed72df6782e5db68f7b7a07dbf841ef5c9d50d743e621d60959b83cc42e15d7de31de31c6fd36b2704616cec8c2198d4afa18b9fc366ef96d2cfb6d341a8dcb0c2471d165cc971f5761de6d6c3206cdd5112a5c92bcdbb82487d80e2d232f4860bddb78012f67cca4ade1b2e5c6bb8d137041470b8e14b73950de6d2c22c3890a275a64a0bddb6866cacc14cef27b6a39c536b59c82fbec53c8a9a9a9a9a9a9a92a5255a4b0fc9662c7a4d83129764c4a6a899514155697949494d4528749d411f799039bc581cde2c06671e0c08103599e62bd582f0e1c5e7020fbcd018b8396df1cc64694b0268d913125d09480f66e0e40f0c8b142430d161d5adecd21f9e78819202a98a8197b3707a5dad9128ec98f353defe6c0b688625b44adf91dc526a3dc3e47c17df6286454cef23b2a63f91d95c77e474545452db9fa1dc516d596b4b241c7445b111639de1d55658466c72d88893b3aaabc3b2a096587891f59ac7419797754d61bb82e7660c0c9e2f2eea82d1c65695bb29c68b2e6dd51ca3d6e2eb660787d817b77d41aa835506bbfa1d8a0d8a0d8a0a0a0a0faf4813afbec504b74405df90d65e5375495df50634df894f0e1b5b5e6c9bba17a79a8f09825c58455bd1b6a859e3b39943ad0e859f36ea82c5646520b8796650b2aef86da22010f9c1336555890bc1b4a7925c7878f3d2d5ca8bd1baa6c43d90635bf37986d30db60b601eeb36f18b241ecf7062abf3784fddeb061c3862587222adac0b42cfd1c79f786aa2d6dacd4d49accc91af2ee0d490b98b8b3a5c6c8599e1fefde9055420c956411146a3cdebd616b6dc5d50e1b5e7e2cdfbd61ce1d175556dec0d1f1ee0d2b1093b80289fbac61ddd2b06e6958b73468d0a0812c4fad5feb97060d256898f25b03d86f0d527e6b18ebd204cd94235762c478b7861e5baa9c8179e9ea7ab786e408f22c51c459ab62f6e3dd1ab23a50c34d5a1b347edadadead616bc50db12329809c71f26e0dca3765255879c930637bb7063f453fc5b1dfc515595c91c515592c168b64796abd5aaf8ac527c528bf8b507e17bf7e17c730d861832d39c3099f16ef2e569d58a621221686c657dabb8bc9f6091f367ee4b03823e6ddc5acfca38e161a5866d0e4797771ab4617136e41d04ca4787771c411382e4b5270ad2821cbbb8b604c2298b8cf4434221a118d482412dbda88679f9db8840af1c96fa293dfc426bf89639fc17cc9621624cc1334ef2656ed21e1860a2a1540acde4d4c52f95263e72ccc16ac77132ff0756487d51c2079dcbc9b3800146f66bcbec43da1f36ee29b316fccd87a542961c7bb89459e8a3c59f9fdc4eb7ae2753df1ba9e9e9e9ec8f2144f8c27f6f4b464ec49f9fb89c9efa725bf9fc6dcde28c981c3c81be5bb9faa3858d3838e551bdc9bd7bb9f922576f850210547189f773fbd6c4c7839e1a1054894773f1dc08513a4da9d196adedefdb4858d46f28d9d253262bcfb8967c324f26cc47d06fbedc4cbe1d4f6bc1c4e6f9fdda9cbd06f272aac2e2727a7a5139b1f93e827ee73130fd9c44336f1904d4d6d9a94fc6e6af2faddd4d4d44445d56645cf9f363ed8bcbba9ca03578b1779500069d3f6eea62490b41245b2909133e6dd4d4a3b4a963d5a78f940f2eea63526714ddce70c3bb60c3bb60c3bb60c1996bc6548f23b4309bf3320f99d2143860c567c6cb418c246824bf2dd19d8d8f073450c450d14efce00e58a4e9a145f5e5829f2ee0c59187c2d6133068a98225befceb09580b715253801334386cbbb332885cc6833c3f2058c8a7767002bc350860100bf31986130c3608601eeb36360420203060c183060c0a0c4242a89fbcca46452322999e03e3b13932453d76fa623bf998cfc666262625a5ac1b9d3c4879d3f6aef66328183c5902f5a65cc20dfcd5425cccd1909aa2246e8bc9b8958b6359694422287897733996e7c669c25bdf0f06af16ea6186e5f5fe2caa290e07a3713d84ec770a76398c1efe12e6bb8cb1aeeb286c3ab21d570381c0e97bb1326717722eef3d2ae6a6957b5b4ab5a5aaab154e4f7d2d2d2d2d2d2920232c2e2e0a9837687eddd4b5560b26eb40842840cc5bb9792714c629cb8cf17dc2eb85d70bb00f7d92f30f17181ebf70522bf2f90f0fbc2d867bf6076e142da85b55f2691209532c628bfde7da1ca4c0d1424eeb0513363e7dd17925bb4e2d468ab8387cfbb2f643db92ae3032b2bc9d6bb2f6c6da06dc50e356282fc81f3ee0bba38ca3a7161ec8cdd78f705304a6094a67e2ba129a129a129c17d7625264294a8b0ba9494949496504c2294b8cf49604960496049495e9f9386fc4e4adafa9d949494b4a461c2cbc48e323375de9d54b5470a1b3e38565ccd797752f2f3579d396a5daa78517977d286137ad66c59058181e2dd49402c00b1c0e1b7852d0b5b16b62cc07d760b4cc02c08f96d21c86f0b407e5bb060c1c252049858193a606af448bedb4255da18db962d30c844b1f16e0bc927634adc108223c78a3cefb69005656d0c4d97d80eb2775bd8fa123882d0f852e3c5bb2d2811804589999610e51c23efb600a66b21d4b51046fd16ea92425d52a84b0ae13ebbb04ca8f55b88d525140a85cb11379ea4a9f19ab2a68b89770be1f82023b2162606981cef1626ef98c43b719f5d3817ce8573e13ebbcb04cdfdf1dbc572b38fdfaeebbacbb2b2a49698382a59deed5691019b9104a245898977bb491467fa2ca9111763cfbb5d655b92ac2536a0cc38f16e174ccdd57cc36feff3ea5a6e7b75cddf3ebb3359e354585dee6859ca7c4ffbece6f6a5b3a94a2aa84a2aec0aaab282aaaca02a2b54a850812c4fa966aa59850a4ceef07e57e8f1bb42d6ef0a3c7e5760c01a267046ba945e24bcbb8201a49c81b1870c0d3a6cde5d818b9693b63437616aefae904565060d9a8e1f634ade5d814415ade5913d26d2b4bcbbc20f2b355c34d0fc20a27c7705b50592da026923a949a424929a4442424222cb53aad6463afbec4848a0df483b7e23e9f88d94e337d298903a29e4d4a87273e2dd4855cb352a4e9c6023c7eddd48c93b61ca12fa20a77c7937d288ae3137d494fd21f3d5f56ea4173fc82cd9b1670c9b9b77238da0ec08133e6152ca28df8db4c624ae89fb4c818d021b05360a142850e893eb43e1ecb3534052c0f19bc28ddf146cfca6306707d8d90aaa1443b4de4da12a831a2c303360a0b921f26e0a2d701343e6cb189b3c5dde4d418d989a373b5c288152f66e0a28dabca1b193a74b0e907753d8000b09144468ac0951f36e0a504c2294b8cfc11c58300716cc810583c1e0d95930a8c2e87710eb77b0c6ef208ddfc1b6b2146368725e14117b77b0ea8e8a651cd59430b57707934f040a181c3a30eef87977300b0f17b41650ca66c8787770cbacc2a64a18395fec907877500964b365c9e3c90d3159de1dcccd3089b919719f8f72584739aca31cd6d1d1d111599eca71e5b88e8e943fd8df4779c6efa37cf5fb28cbf87de4228a9d256653e67821f1eea3ad3870662eb8cc4c59f2eea364708c891c36c4800511f3eea3ac0d48d4dec468f225c7eadd475b31d6d67e5475a18d79f791f22a0755123f6124c8de7d14c724c689fb6ce466e466e4666464b4f6d98dc8f2548e2a476564d46514e3b7118cdf46c9df466344ceb0d4d24c904979b75195084e2489f3670e9a182cef364a6270828d4d58094b5cb8bddb284beb0d0aae3c7fa85ebcdbe845580f1e59d4d4497bb791f2023ec698114266c713b2771b9599c4b2b8cf45a9599119dc17a515ed22b6b6cf5e94965654a42c7af1bbc8c5efa216bf8bc66898a5415251c951e2f6eea22a0274894341024e9d296ade5d941ca1420c16166971b06e58bdbb28eb4fda893a5ec4bc64bdbba8c893b82376e6bce500f2ee22351751e2ca6c4499e2f5eea21488494c81c47d066e01b7805b402010f8f5050482a1bf8156bf812c7e0357fc068ea500881c18666d905adcde0dacfabca38433234fc8aec87937d00cdbf1828d96b7256bf6bc1b78c5c55595236b26a4c47837300e181e267aead0a991e6dd40250b2a3d5ec9333ba0bc1be8c724fa89fb4c9422895224518a2422222222cb53e9557a4544a4ac42a4e23751d56fa214bf89d2deeae820fb91d6f56ea2aa2a1245ce3c9901e4c8bb89929fd3b8e08c51e58081e7dd44599fa9d6ecb03376660a8c77136d7d7e83a6051925494ebc9b48f919c98c25666d64baf8bc9bc88d497413f779086d1b6afbb6a1b7cf3e543684e2f7d089df4354bf87c63efb90d9d050dad01a9d2524d27461f3c647cfbb87f6121d2548f8919c23e3dd433f2a2cb4f21c712b8184770f1129e2a2ac4e1a9a9f2aef1e5a81111b7d84e8d9b365f5ee213e6ec6789918f34325ebdd436028940928940945bf27a0601350b00928d88409132690e529140d459b30417936219bf83d2197f83d2193f83de16843c5933c6247aacade3d21051a3f4e58b85993e5cabb27246fa4d811a60a991695774f48337685c5978c2b3d72bc7b029aac2142e82c8b5c9d79f70405a81053640a9bb0af32ef9e30c324ce88fb2c846209a15842289690909010599e42b9b6d0d967174296f9ec4219f95b28eeb7d09fdf4264525ec0b833a6c34f9b770b554d51f9402ba3452dabccbb859247154ed2b4e29ce13af16e21245a676f5cb0b8a0b9f16ea1addd1d3841eac8b9520295770b29bdec8003054a1c1d2cef1602434f04f9f913719f83d0aaa01d04f7d983907e7e07f5f91dc4e777505050d052a9f63b882da8adcbb28a932b3f926d38de1d84c1922b78e2b2dc19e3e4dd4120e8326749458d09d7977707b939f2e6cd969c2b5669de1df40124708e587ded90f2f6ee202c33e47cede0f1860bdabb83cc984433719f7fe7f2f73b97bfdfef4796a7ceb7f3edf753d2f9edf9fdd3f3fb07f7fb7767ed2b081f2f5d5633defd83000940622cd798ddc8f1eedf08ac272cceb8bde1a952f3ee5f1293225f56c07003a27cf70f03a41de59fad2fb418effe69e15ab2a6c6441c1a5ceffe2931894ae23efb943ea54fe9f3f97c64643e9f728f2fcf6f1f9edfbe3bbf7d639fbdaaacd1da4182489e77fb4e40a70d123a7a528cf178b72f4bd89cb73e507c3c897bb72f8b429a3831b6a0d07245e4ddbead26557ece44994135e6dd3e73cada1b1a6edcd4f048f36edfd9c2249e2de23eb767b26dcf64dbb62d599e3ab54eadb65dd1befd6eedfc6eebfc6ec7248085042467705c7e66bcbbad223249d145d985230bd5bbdb640867c4c879f3c20a9533ef6ed98021b388294de0f9f1ee76ab03111c493a5fc2aa687977bbe683471adb9eb8175adedd6a200db4813450dbf7017afbec40318080808080808096406c6526b12cee73cfac67d633ebf57a3d36b6ded967ef69f5e8fceeb9fdeecdf9dd1bfb1431b8c8f4b9ba62f5eede8b124aa873c5cacd32f9ee9e0d2c7e9428911104489b77f7b2726481b186e32d0856d8bb7bc82a1438e2c250f9f3e2dd3de51e374d76a801c391f6ee1e10930824ee33bbc56eb15b2c9bc6ae7d76962c4fe9afcc845d7fb1679f9de562e5fc66e3fc66db7eb3639f7dd850d2d002e3aaebdd6cd5672e2c2bbce8c9c1f6e3dd6cb20538d8c68018f10292e2dd6cd6671663b2a898b4483e79379b876a4814384f867089f16e9645d7971a619adcf0827c37ab5b9844dd22eed7bdb2fdbac27df6b5499215ceeff5cdefd5cdef755d572956c4906c0943333bf1eeb52a4a143145be909044acc4bbd7e4e7ae3d389225ecc191e4dd6bd602667cc5b982a4aa079e77af5bca3c5957e62851d2c4eaddabf28d15b3b12835c40079f7aac724ea89fbec9bd7a74f66c2be796ddf87f7f6d9794e7854583c1e8fb7e4b199318966e23eef96bbe56eb9db89eda8d87eef76bbdd6e99254689064d4e172037debdcb425ad1852d2d8db20bdcbb775b4a4ca292b8d76d1d9b5297953a9d4e474676f6d975481d559bdf3a2c36bf756b7eebc61eecca8a85962b2ee0bc5b579585c8d7da95126469dead4b7e56c1a50d45dc902c2fdead03c18d961f3564e840e2e7dd3a07f020434369620f9a12deadf32165c68a226162dcd0f16e1d58d66112b38eb8cf2adc6757c976bf552aacaecfaababc93f37327ce7fe7fac0e5e0727070b9b4b5cf9e23cb53d92a3361dfb9b3b2b42cf563969aa566709f3d5d4bcfcc8024dfe04923e184c8bb735b9fddd69475b4c84811f2ee5cd6daef5c57eef73b970bf3699f74edd334287150503f60e846e1fe09d90e3f35486cc5887b775aa5b45c3384c4993044c4de9da2658921c18a4c942f26de9dda3112864c8f903327c2bc3bdd42011991396b685a56dade9d2a392831a3081824da9a14ef4ec1d4fc4ec7d2fc4ed53e24deaddba07ceb370df7a79fc8377f9e547f9e55565739fef4334bc89fa7d69fe7d6c9f5a7d79f5f7ffa09d6d6e6cf53eccf73ec24fbf33c43fbd34daf4742724c027b446253f2c1603018247a30e8c6ad0fae411c4107214b69f0a04f208814743318f4a08d3b5780488141624a7087561a9b3a24d4e013448283e406a9cdef28b62d8fe42792ab6e863cd29bab477ae3e79190e04c7924c743d82392f17c0d1aa6b065d96afb2db4fc1d7ca29f44221b374f6c03e6896c823cd1b110f6480cc21e8339c0fccf7fbf9f2735652929ff79511b61fc6fe887f5fbf9047e1d7ebfdfef47bca2f0fbfd7e3f0dfefb59f8fd7ebfdfeff7fbe968f316dc826320ecd182060d1a346870acc51e3550d021e42938fec11e29a8442291e8c3e93bac7d07c73dd8630724242424242424242424c759ec11492a87899772cc833d4a05836a7e5489d5592ea7a40583fac6078316f852a3b3c44a8c1d3f6f30ee838e77b0c7a00ef6f8c3a1e37d3e6de37deef3249f476529f37d6e14f23e9f0fcbe72064a9a0fb7c02bed3e7731244f1215de5d07a9fe32d31ef0bf2f91c8f6529a2fb1c93f9cede9786d462461a1f6ae0b0a8c1c5c99012249655d0d4787d5f57f88c91b9d146c2279547cd4419931c5dbcf87c3e9f9b3e2776792291e840a2e31cec918884e4aa124730180c0683c16030e8f8067b0cea1f8e1bfffb85e1a8f13fc736d8e30f8b3dfaa0b04e3c94e31aec114a7572a0933b7952767272d5c9e1de69acf83fc734d8e3cfe79bf23ec733d8a3ef8a3d3a199bdc04fb26c732d8639315af7727bcebbaeb49ae17dd2b45de756bb80e42964272d727e0fe5cd775d7c49c1324e08ed80013e39a91f18227c518d79531ee94d9ff7eaeb678fee738067bfc019190683c92ab4856b03c926318ec11290ca829eaf4b94ae27dde52799f037de8b3827cdfd7fb1c27d9a3cf189cf141578362ca0f3a7ec11e83ee823dba67c17ff2334b5198a1e59f1cc8e39f8cfc93e316ecf1c9fdeadddde7ee6faebe941183c682cccdeb674dac70a9696952e7dded8c1fef6e9a799f9f3ec756ecd1c7823d3a13993acfe478057b64dac244c6a3eeeea817b5f1cea3a89b2084e084ba4982268f9a6f5549ac271475bca5e3d11daa63a0a86333241475bc4483280c649672a97c28ea190b7542d1a0a3e80f454df8e8a166cb09103938de1047c0f859834384eb883966c259a1c2468c093c6d666f18182dd420b7d0507b37567ee8b1024cab4509384f5053ec4916da924a5814258aa2fefbfd7ebfdfeff7fbfd7ebfdfefe758057bfc0575f2b7f183242ce3a04902c5cb8d77b71fe483e64d588f2c7d9ed479f7f0836dde2469d322636122187cf1c1a0922d4be5972548dcdede60d071157b0c8251a1221646c517e68bf2f97c667adee7f3f9be50bdcfe7f30f675adee71da4789f7b80e57d8e53b047df97d589286464b8ba5e9cda05524a191638deb69ef4795d3785bceb18057b74d747427215c523597924c727d82352fbc4a5ea9f1c53b1c7270d5bc4dec9b109f6e8b4e5eadd7109f6e82a09f68866b3a2d1187ce36e7ae3efa8371a036034ba0a43cc1bbd05a678a37b0cb237faf0c51bbd28a3cc1bdd680cbbba7aa39b35dee818c91e8d4918df7adbe2dbb66d97ad1b5ba7164eeb206429a3b73e015fdb3a09dad6aa75bd757cd5b66d180c15dff65a6ca255dfd6b1599632bf0db6adabadb7ad970e2d566a98f028d31239d2a556030957d5bad9626552cd850ffa08f6180c4b6abdc075731bdf75dddcc3775dd7755dd747608faecfe7f3f97c3e9fcfe7f3f97c3e9f8bc01e7d409a0509da50014911c50c1e2f3f2d3ec080bda11225460594ac9db9e9dacae2c668d42bde68c4aa9325e52a47923e715ea3d15dc01e8d577eaffffbb9b983ffe3d2f43fffb9fae77f3f07baa8f23ff718ff0b7ba116d6e2c8ffbc054516b0c776c9cd37bfe42b608f4b450716dd87c522162f5f041655148bc5b65874b5380114784ca0c1c17903576c83c22b0f15b32865452c2dbe8825ebdbd655c01e5b742ccca39e02f688a2803d164d37f795d2f0782517c11e95ca64f934adfa344d5d4fd334e4a7bd34459aa6c1343563e6d35eaa51a4be2b639a2eb57cbaa63f4fd3629a3a5eaaf874283df11999a9d236dd3999010b295db880a541f9f3a64a4f82f001e2c64b9e3da90a301746c274ac9dbd306a7ca9922cd345459a162547d61b332ac4de6dc22d2551335206450f3457efc6c854c8981a39697cc01832e7dd98edd31e40be14f101c625f66eecf669dbfe0e367d1bb52cf36debaa1a8e6fd5c87cebdefab0f562eb27608f6daa4da0e80944dd51ff80ba3a6529e65137c1162af33ba8562c9e49f24507a279f14577346fbe6806cf17bd04ecb138443595e9e709d80917407ce8e19282c9132d5e574dc448f95d79439219533623cccdef67e27fee74fe77268c89305a5c606f30de9f1938ff7312b0c7dffa46a319ab37ba59c21b7d04ecd148a44bb0f94b1a8ef7b9ea4b73f13e17017bf495f1f2410f017b0caa6e1921ef7a08f6e882803da619cb5fb8e6cf0b7db347a19a14afaabac4abaafa73555513f62aab6a12aaea211455d54950e55527155725b3547b954305e3e7d5a0aa91aacf5515557117128964a16ae00758da18166a6c8479d52c7073b2d4b021117353a5a498f11137e5480e1f6a9f3a3666bcb519a35255d5e8a50459d698376486a84cd610794282102e3578de8d95afa2c124b1280f554c2aa87966c6e4513f5157d58079d4dbaf471dd8c5cfa3ee5ec01ef5e1dad5a35efc62e551379e553dea1fd6d01ef50e743cea1eac593eea1f608f28da8aa7f87c6644dee753c3e57dee01f6e8d3e0f71a80df42c19d14f6bb29ea530f6a983f9f7afbf5a903c5f0f9d41dedeb531f92f874ca182a9f92a1fad4c9a7de01f69802c5e130338282c61b197ca8acb87144c58934ed081d2e5068d9914c9695b5bf6fff7ceb4ee4db13a059a1d24406922f4bde764a181bdf3a07d8635b5473f545df007b2cfed258f99f6b803dfed40cb04715832aaec7c031c01e318803e3b5f6f35a1f19e720739fdf208410d453dcb84c3ebf31c6147ce31c386bab4e98a2df986bcfe3319d6a241279423b5edea981f520331592ef6c95b1f6e41caf9168cfca2cd5baf6fc55c17716cb6625f259667bedd92dc36529f3dd77eea3abe4bcd6567a2b4bf95cbbe6f2adbd5ebba95d83e9d1a1c5e07e6bb4d7ae97594ae8daf59a05dfba4dbbbd760d87e2b5ee93e7c43ab3f6a9756ebdf6b36b8f9c138ff6d32c4b29b9f6f3ec82ef334dfbc9c6270fd2efb3edce6f145995a596ac86bed12b14ebb5a35960a8d6db6f54f9da51b02cc5e4da51310cbe5132d4ecb5a3687e7ebc46d3ecfc46dd5e3b0a9722b394f9197ca754dad36492f4aa8e6e72eda95776f29d7e694fc7ac52b2d7e9f2b5a76c59eae7dad3b627dfe95b0ee9274745477b2e2bb795a5cc27face7175bdf69c126927f7e5f63b67f6da736859aae8da73691a7ce7d6726caf3de74602c8ebdcdb9cdf6ad56b57932ad606df6a8eacd7ae6e916023faad72c9f9ad82bd76752c4b41b976952ccab77aa6a2bd76756902c76b752d8e761d525795a5cce7e05b67957ced3a2c5d8eb6dfbaaed7ae53662929d7aefb9af2ad13d38dbd769d19d5db6bdd199cdf3ab6d7ae73cb5246d7ae7bc3c0b7aecfeb1db2cac584df3babd75bb4efb6765d19f8de79bdde295ffb0e0c8599d73bb137bf7768af7db7cc521d5cfb6ecd83ef5ddbceedb5efe0525c11fabdebe3e6372f89950500df3cadadd7ceebb2f19ae7f59aed374f3b0f4d03dfbcb4d75a8f0e145b42f8608933e5d54cb2a2f01823c184d5bb5b2a624ab47113848e1822ef36d9f0b0a3f6440a999b8d779ba6951b6060b8f8c95286e6dd269c9196da8d3148382a66bc1b1b60085b9a263c944ab377e3ae2b35155d6968e0e053e2dd784b959f382c207ae2eebc1bb3bdae1164481f27684594bc792ba3e5a54e6aacd75e3bb0b419437691f26e3df63a4d91316bc01c5111e6dddaec75559f3229967825f3bcfb44be0ef183aa4b8c136b5b62e833509a6c9992a4488b779f76e2fab859bb82c46dcebb4fb0d75b636eb4889b530289779f6e4954e0d972d6674e5c9c779f70232852c2d24e16b82247de8d6ea526be662873a0d5817b37daa5a48dcd2c4d151a1e6ade8d2e5f6310a38d0e9d332c9466de8db2bd365156c4080b257edabc3bc57a6d9665cbca1f2e593cde9d66bd4ecd5ea768af1370434d091f52ae3c81f3ee5cd56b1b3de2f498c5e9d1f3ee5c7284b2b7125925a81841f1ee1cd86b23ca3657702ce15202f9aaf598c1640dc98d3f64de9d837bed315abc91f9596ba37ab78a7c4d45cc941676dabc797bb7daf5fa4b169d1f79be94bd5b55565892c46a471435b6b477ab6cafe39ac41992a78e8cab33ef56dd5e57b9b2634e96e59e34efd665bdce52a5c41a38246dcedeaddb7a0d825615b03eca12c8b4bd5b87f6fa05132743ae9cb8f0f26eddf2b59b7b977ced3b2c13e4593333a35366cfbb77634f6061aaaa2455acc1f2ee9d590466e821010d173c70babc9b877cad33e1e6678d95951927efe655bdae9396640b7945c69977f394af8dd4a8a3a44a0e153eefe681a528f31af899a534780dfc02ec5103f504008a390f000f813d0240c5e03d68bd07b7007bf4a076e8d0a143188a1fdfc12bc01e3b38007eaf9f0195cfc0d52e9fc109179f8153803d66d056c000033f317015cc63e02d0661542c1e039f007bc420c8d8e6b7d1c9c6123025b4b84832e3dded1bcbc8a8a9c127489994770fdf28268f1c3034780881d2e5ddc5371ad9bcd11dce1b159034c1a2889d2c6e5d5ee39f37ba04d8a371cacf2c05f55353ca9ff208b0c7a9b67d2929074ab92a156682eba51c02ec516a7d0e7e72082b01e639c43d0707813d72689f3ecac947f903d863940a05050555e4a1dc01ec110ae937849148f11bbc01ec7183aa4183da6bd0a0210c19e335f807ec5103b0582c168bc562b1587406b0c72291482412e3823cd117c01e894f4ffef4f4f487ec9f5c01ecf109a8fbadf96dfc5f89226d6be43829f1eb61768686972d4ac83079f7f07f6a304ef4c0fab106e7ddc5fffdd6fef787caff866ed069c3c26dc7932aefef8f94ffb907ecf1e7e434f54e4edec679a725efe409608f4ec0a6a6a6263f48bec911c01e9bc83e431f319fc10fc01e33a84b8fc1c6637003b0470c5b4e097ce06459e531f3eef69998d43c93ab7a4a045a9890807351a4edc4cbd467c6337901d823930f877cbefc70cf0f9d00ec71d82e2d2d2d2df900d8e3d2853d3cfe8277c01e2fa84a4a4a4a7b68bc9283608f4aaee593f43cf924e7803d2661b120e62dc09dbd853c7ede821fd9a305a1502814fa06ec51e80abd1b7cd775d5f5d675a09bc7c6bb2e00f6e8bacfe7f3f97c3e9fcfe72f7bf4b97b78776ff16c79c713e3dd9f3d3ab0ca57b8a3e42bf807f65841cdb569da766c992306093b597ade3dfcd64d3d05a5e6070c1f6b5aa4a1b56d7bc7c8b76deb01608fed9ae5b7d02321b96ac7ed91bc7d2b7b243b341ec935608f48c025f58caa0e5f5555b5ce9c5755d501c01e55a92e177e277d4a86ce904fbd4de9a0f9b44e971b974fdd037b4c87bbacf636c17283c4923353bec0a8e4c811850b1bda5b5619143c546eac968fba57298195294d4e98585375e445dda23cea1dd8236aeef529380557cd3c852973924fc133608f145ab4dfeb07a37e0b7dd0cfa0ab6f1f9443f6c138383ee818b0c760f08fdaeefc911bd9e3d1147bd46c46635c6fe452ecd1482d72605151515191ab45ed988e2f82f3e886479d037b44b5d65a7b147bd4ce1e8b8c402b0ff40dec11a80a3d5146f3444ee44944445ed4533889442255bc44aeeaa90e596eea2c6ba85953f112695952d1d2244b169b77b74fe466094fe463ba54f8ddf4dbc3339530529143c59d15565efbd0c66b2fb250bef60f562a5ebb06f6a8c7720e839ef96da235800d9989342b4cb8d29ca199f32626264f1d36ef36c73420068f0c2b3442dcd478b76996663355781ef50f55708fe2205c32b8d8a0eae1f6a2556e8f7a913da24b227b24f2fdd0d0d0d0d0d0508d203f94e6513f517f628f288d32afdd893d6a6f628f431afc841b577e8267608f136c50bd90900385843c290b09b9d1869917f22024e4131012bab1e4858484841c5f09090909090909e5f900bccf31b0479f0e4551144551398fa2a833b1471400dfba99f5ad0fd9639b9a73f6f08bafb576bff13acc868cd7bea43279d52fb04755556321c30d182e1a7dc4741a148fad297cc27ce401f2a6585e9fba127b4c3d893d0aa57d909b5c1fe416d863d08e329f734f6a2aea9c1baf7cae9723937310f494fae63c8436977312707d2e2897c7e454cfe57cb99ce3ad2c654e29d3f1b91c5acef11826fbe5d03e77a4cc8a0c102625743979737ac020011245d9a5c49bf35c87ad3827bc547cd92acb8d808b131a62d6cc70e1c8958591c94203cf94322cefc65d9f9b42d6450915321849726e8efdcfcf9f0bd9a61da854289b89a37916635231c86600800273170030281c0e8a666194045914e30714001666a65a60561b08c469940331638c21861103000000000046461b0220aaed11c9557d1adeab008fc3230558a7a4264c52638115267ff94379473bd865f49c0f6976ac4eb694c7408077ac2ec38d8356af4b5499c5de89d6e9885e320458ea9010ca51b79f439e442d39881526d8a8a45b03a202b927ed25934db68358e7b6e585775113b7a76d40d5a1ebbd88111c226fcea58435b183911804b450ec404054ef77ac76b53a4ae27f442b933d95f57dec830328128d993ae997b1314926fab47417b3507d7941211642c8cdb21f87bdf9b825cbb8d7030d9551d956f9723c5e10c2969073f383f12ae64200d226271a138c435dc02d9c4cd0f58732071c13f1b3486e776291599d71d545cc021a7e2584d24ca3c60b814dd268a084801abc2fbac9136db0c66676a67038c37421bc72053566811a31a0c1afd21871b1fcdb985ffefdd7204ecd821f9b534fbda8d79d422e46e1a4c88e942ec7cc974878f7f2f98500269d50b023d0f471aadd00935249d27ed3260acef98362f68058fae17160241621c5baa04c6199f3218e33ba2b76ad5e5374a4b1766b36040201d0f2cc989f27b4579b07d7f70e08010ce04a7845bc11180c4a0eb1f131deed03c90fee1198d2f3179ab88163aa0502982330135c7204be17f3fc73e30394bb7562a7da9aa1fde770bc2b45e2e73bd056c0e080b804761b01940240bbffbe21788006ab2a9f74504dffbfe46c4239b2585f5760161c4ae71d9ec637c4bf36694a08ac7ee8e9129abe06c21514538f3b82bb4f3878992ae1e24e5c471db1cc2edf9c993bdce6488cac5b92918fef94ca7986855e8323e2e4c183d6f676a928df1b813d35f6729e9ae5a1fe1a36edde2bd6cbcebf5b0bd95469b83c09d92a5c8634baf15a8ebcbb1d2342c331249e70f8584f20ea459dd84125e83d21265e0e468d0f514e79e9e056d763947b1fa21c75609350a017785c7f5389ccecd3110bb637d8e7bb69576411233177644b859a97419e645d867ebf13d1cc4bfc54d16c81f635aa276a09572946de08af912fb76af9c940f086077caf0096e5e026acdb9c50fd9504c292d811bffe6fdb45ccbc96db4d584cce9c7b17331a792d297438c044636742a7723e7cfeb0591b473c6db8a630ac5ff95ccf364bcadb78528603d46e59d542a077e0dbf483cd69b1e8261502c845107e55e8d5c872a4b551ba8589698b805aba57c1bd5008bd13f78f43fd432f5cafb021859489057593183cd8d9e8bc3c306f0c35662312925cb0ceb44305072b0be7ac8db6b261154268a3338ac2662e2d95446770126e436777347571a710fe1987afd6d89deb436e7d04a186b23b2fd24637436431b491b515d90a816e33eb04d64be007243bc209ff012f1a0bb9830e4360fd1be2e311ba47463335a5730382adb522dc8df38ac4dde8962e6e1ab7859eb203fea233956dac77d8df2a09aa7ab184fff3554f611d69cdaa98012a1c26b13202bb627a11d8152ed204606e13a2d48f2e9d7b3eaa2da05b4b0a5ca0f5a5ee15f46a36c8fd5d4a2e6988511f160d50b31d0881766125f4e550594e2a0e4ad7a0e66b49db982bed80300058caff381c6086b7bce60135508037d567ca87b30154de23b55ec714cccaa4602af577fe3905800bddbb74208888fc0c0569114bc51977bc9b60c6c992457bad9c280a6d4ebc8ba14453d97c66b6629d0ba917cce8f045e5aa65f109502a91f1a4a9cf68d656ca9528c5b4448f7d17793c9d078c21fa21567175ef0f8cdcc8f1acf7cc2547488be12b70ff645d9f5321e4b32865a05169497150b73eba763a0df89c1e5aac82948bb741a360c97bd5a1034a39fc276fdc25c0807edcec56b32f4f81c8ec82c5a3812115de8d3387269abcf81be9cddf3fbd2475a43f3025625244fafd85d577ed18b6d2cb42249bd7965de60efe7ad4c77ec85a50079b6cb1cb7e5644154b28e6964ae5fc1f4c618cb332823bbe6bbccfab6f800fb50f867752b8324b72e819a8d4e675025c864faace2a0b0adc45b0c697df0b3ab6d28ce1faf1dc9805e476d2f9acd5431e4141fc5a5905a58c1649b35803b8984aa9070c697d638acd865a97610275ac57d1c4c5feb602fd085dd2e9cc57d1e32cff3c5c015ca958563c7fc3c53dda808bf0bdbc2ed47865e6d8463abc392c40b62cff8b738dc978f58161b028ce172b06bd24cd40901ac80ec4212fedd031fb1a80f010891a27cb30349ec1641ddf04067a62e06ab3a21d78cc364f1bc2a69c3a9f009968949c30fa6ac06714919fac86014f260bf1fdd28e3e6d09f981f9b3a61b3f12f9c34b905d9434237860a857d35ba985f6fb6bafff05b19899e34192aa3202b4cac692add4c488f14c1cf26cc9c58480f2a4dbf125e2537e8c98b05ee6b8a37881ba4d2d7976e10185211e7596c0ea87df736364fd38b8e89d7945859a91ecef9ead1981b50b359d743db1e51072104071302aab3aa6a6f9530b609dea9541cb1e53fe07bf42a7650e654eda5f11db55e891bb580e31e891e469f3a182633c06954a60aa8cefd85aff8156aee406e4137077f38509c96f608337e2a45d5084c589a839eb881f5b277ecca7ee9986c6085b357a23d07cff492702c8c9d1685cb8fb7d50b7d152199b548da2fd3475dbbce8d2140c73d41cd66816933a75f65664d21f6086f031de4fe5a70632c18fc6fcc5a7f9e09e600b072a6598c1d9ac22707323389a8d6b2143cd4cd00114de82904c18c9cea36bd52daee9a09a3858c16a545199f3e3bfc5392b87cd9ee1aa4587ec81d6dd240985068a0c6b9b5318ccd2a8316d3b08eb2dd0f85cb2b9f9510aa9b0cba8ba4566ff9a9e8950e9ee1d5b223f849979205dcb7c32dc469d8fa8737538574be9a648d1e60e41f7e77b5a02d28f160b97eec5c623d1d009cfdc82a91e8a8f66ef336d9c2fca84887a4b8d790d44b4343e52070f4279f82c48e84fea5ddc1618bf8d4971e189ac45d8cc6aa09a3b6410ed0fd54378ec14182b179fc4070048c9d3a6c022dc3d99bdceec148b83421353f40e909320b250fa00c567728d507700e0510b4daa1f325ce96f44bf77d1f332a721db8f51b358a5e51c7fd623ef3ce1ff89711dcf034902fe948c8eab202091f596c6444d77926e6b302cdddfd223097d9ea83502faf1a863de7c075efead3092db949d104ee633b5fab0021d05152e8161a0a5f40ffd47b66c8d70d2944a4e1867e3128c9d58f0a027750394a251c0d273a27d279bef8db0d9c9408967126a00774c0cb5bf905edc88f2998018108b688a52a722e37542717ec26a4a5f17fa3bba68f2a3e8b6be86bf8b58599f38b54e8e453a99c7b7b062d29f424b27893819c047294b196b3d4842c06cf6617b1498b48eeadefa58049f2d0430155bf22542f9aeeaa3e4ce8995d185c8b46b2a5693963c664ea98127d79aea5bf72e4e7779f1583442ef9bd3b901cac0e6965f8e0e35d02817503af74137581e4df7e157f6cfaff6f86c72712a9ddc8fc0e47d06e9bc85119ca963a37863e0882c32a7c7c5b29b54516f5c8447b490f8c2419ca13e6f329f742f853b802e0b7a2d3d3e6882be60a6fc161fcce9fde0fad4c581296805d69f7ada3e08a2f4fdf3fd855e5718dd08935d25b39e871ef5a7a097e1e6c6d2cbd1a2f9bf0dde18ac71a39c5494a6e86dece599fb5be2386205edf527ca7806811416fa19165aeeed14ff569f7a75613373ad34f9f45aa935d24ffddf39f86d92c608be41df6ee3b695db40b3579d88bd5c741eb4779bf7da2ea60ba450d8cc931a162ca5e9a87aa587254a5fc4b392252130c14407366209c65d0918879e086574abf0777dc04a0bdad365966a0011d87acc4280b3e57b9aef02f8f835f074018e9045882a7192139920764a58e5003a11fac16af287c1f0d6d0e38eba3885034fe1e676c57be1f71e8742c077630c098177cf66185c4226068a96e8b64bef8f07d7f81adf4d115f4deafb710060481e2a397ee0fb2a82649da69a820dd154b9fb182f0dcd4d9b811e53191317328bbfc50c0ea0162cd272743221be3009bfef7e76e588c6f58053d3443b55c375e391a280af63c3694044ae91fcc6fd20b5637361c6b5fc759cc2112d3ca118fdae049c8dfea75bd7103c705618d868ad1d04ad6607d1740b36580b2063d9820ed0651ddfc309714cc16b6c1cdfdae7f72063b767477863ce0a931fcfd236309f708fe7759034135c58fb7c0163f411dec380c506dd9652c181b65a0e42c5665c10cf8b4f3d50051714cccc46d637d514c3038ebfb4e543af61dff41c743b12e1144d1865664a8f89d5807e2c7bef4c64bf3aea8b6143f56e793ae6f11a0e1b472c3c278443f731402d65585d450953490a97878c1c02cc4e3afbea16b5d89ddcf0e63b5209a6086dc20624149317c3020f8f2f475c1d6b4e8d88fa681af6a8940acbf73d91d85b70d189e7abf1a5c7821c3407a2a5d4da5b4f9815a425eceda52d23510d081ee826fad14bd639e1b77a0f45658a8e640f4879a38bcce71c5fc664cb837d9c4c2ebdba479ef90ffbdd33a71de2ccb35387de76fa586f8b8a6379ed86dc116724274e026ac292d83e8e47e9773bd4b7e42619c900f5659c98922d041a7247c90732ba2724715abcbd80695964cab26b681ea91516df9fc823e227917f9b95c403ab15906a25284e1471c7adee8920fbfe06770c14f093733f3f8206d3983cc885724c084d514ff38453403120d18b9ef25a9207f29bc9727451f9bec1a838949eb2058f722f643416833515200b96a2bf7b87f57cec5e2c1ef4e10783a90e5886c0b9a2ab4404621d1e0c5e424ca488d705304a5d11692ff10f39936a71aba390aa7474e1e7f47c67744eb4356f65696a96cfa14a97e45e846309e9f0450c7004d5e6b2bb9b3c59dd3bbf5df08288818c0f9c55dd05063702e71e03c9d60964ae1820558d020830a664a1aa99271ec6d46e70dfa9781399d14aaa1c6d772752f65723e216a2e605e523f9473f3a92f304daa1e2f10e78e91457f167bdeb2be15c386f9dd3930bbc4e923850ce3d49c577a0e7b8f5c0831416607d93ed1c0d3c4a417e010de9e08823bead6943e2b4bb311c983cd737857044665f2dbf38389aff0f713665244b43c82be774bbc450a5da28f82601772378f0ca922d4480112e61d998dece437efcb38d9328610183c688410abea5e4dccc574db467c6741f62fcd8d37d0da2d6482c80c94a029d2822c5232535906511182b566e46a7874c8a55443f46e09dc36e1d59cd3cc35f61278907f430eb3fb2097a31306c637a5805495abc4f4c71245a368b3def961e1c70304a88530635e83bf276ae2024b5b3268b52c826a5710fe16f087ac69b3d44cccc8ab98595943156a7a86c8188ca5e5716c47b8d42c2868aa0103e2e10755b06450ec7e56e79ea9e11dc25c078df8a8b071f92faa292590012329d13794daf84249a2b553a462ea27ed1311122f8cd977d19943e92d9956c64ace13e67891b830042542a50e981f9ba6d3ad6862d514609bf21e3e5445f343c688b40b15e001d1588a7b3a92dc8348d196b5b7d79f561123bd130279dc9ab4fcb3493e597ad7528919e915a59a840eb600cf0818eb7d36ae55f9066f015f027e20799f081573ba2a8532740d11a7c6ad0bddb0dfc22b90db046a7173ba223a01cff8ee832f828e938eeb6629be25684ce8ef0fe82c0535bba2380c3c1f3736d41cc56b14df69cb04cd97737d17eb813d2f32dd5bdd57942aa90436e54a9191c25d8d27bbabcd6d2ec873ffbf67bf16b79d3e3f57d026fc1e0fb2850a14355585cfe67899b3991466bb68c1fc723c10b205f50323dfa86132e5955cbb183b54c582d2117d98551a05c3bf91feedf69411f9bad53c348c51b5fc0c7896b4d76701a0356b910b3958f6867896dec68a5483de32abeaf4630b43c6b05f49caed7bb4b308fb72399905aa478ce1a1338dc1e6e6fb80d12f1386d9904f4c39ad36686006aa25a01617edcb598794ac15dbaea2f12eb809560c1ba4bb382db68ae2bea91cc28283771c6c81ed4f86a42d9c7549466f571de7f2c6faea2b702608ad8308175ac2ed4de24e3893e612c8566cdb4fb99423206dfd303f83212df12df15004d1a3ac04be53fc92c96f592942754092ea2e9576a0c349c1c1481e341b16ad2bc4525ef4029dcf9b444a3e9283ba4ea0ca4196e3b396afd4391ecf221286c56fa6da07f6411c48dcd6ca9b37d9d2c5c59ec6502de29cc5a661806f4cfe0dfb4197b21b7ddada80de407ad6106181c61734136e75de6bc718eadd425685eb22d77234e1f5914ee5acac9d607f0325726818d2289e2c87bc1a368993af2c0b3909349c8cb96d5ba613cfaf9adab44551a4671a0d94ca426f539525e3314e58cc570bf7fbd3ae20c29a10fb1fa1ab3e52a5a2e475c1e3ac558ddca62ca40689f1941ee64a02478a17387ec47e8ea1c249a84f4f727fbc9534a7903e213e25cc489f138c49d6edff297116dc5d5927c9bf3e7f3b1fee180b5062762ee25fac08b3cb2a88e7e0ec36de7674e757f4f33eef5d38a6490ef61c354e86a143566cb41b09ccaebba22304690d50cf0d2b2dc943d750ac86e631209e005943c16907ca4ced6a6ff3c5e481e8a2e97b3177c48160b89989615f325abf4f1387b0de0cbbc0225d76eaa1d70d2b2a8a175592300fb0856101eed9673f7c0cc5d771613970ef203620f4b82577292419673e897ea31cbab1c721825bef367fe80490208c6c0931359f10ce9b6daa3e68ead12946262396bda0414c453e71621438d2c120b92427038f60aa74a53fa2e0bba59efabad83345ac8516cae55c2aeceb4c2aea7afadc86356eb5dda22c1e7970d6097bbe3feba034d934e985eb9a48b2109fab92b314d978e4c68f6d08796479f40821152dcf9bb7c7f5ad0db8c81dfbed7509eb04136c3c62914696a12e311c592572564f856e7629445a3cd773c91f857855d52688a3045ec7e53c2d0c4ecf4a4c4f8ccb9024017860e3e8e15f8934b4a93fa8c4a96bf081ca684d285f254ff4fb3bb337162d26aa5fbd7372fa01a0839a3d052332f15e7412c56651d9e91b897c124af94bb8803319d71e3bbcd711051de0ba36249ce892b2ac30caf7248076e5c67f18cc976942149fa8f7151196229be224b2a8ff32988271855dcb8a892c89b694428980de8a6c95609268ec4c03d6a10bd46943fc940433bdd67886219d1578aa9587e7c1d3710558cf252d8900b923dca7fc215c1ba006c3a98eddc5ba46240b374a1b6cf8a7129cddda826707388fea06e0642652f399325f49f0f4613e4c7e032c28e55e7c339386ad82c2abaaa007c2b19ba7b8516db3011e5340fca5666c7add659d2910af25349c51dbd6d322f1faa3be927b1057df640527af940c4362fd46d6d2452eaea02dce8e89ee925657234565acdbc236e032be56012b422204930f184d1f3c78251bed095b66014b1d40c56efe8816c78a3dc185ce5ddae8490c1093c9c4e6596d7f0fcd03045c430479047c1b849409e7677195f84d1041ccb821f7472db7edcb0509e1b6a1a7e138239c69230add20bd19f2f2b2069dcf8a07ea63bd85265b391b819d9bd55c4eb4aad4d587395802c6f5a5ad6e2a044500aadf6d59908a302aef926d9e0bce28c10f1c52087359d79fbe6cfd4cda070eff0e796650616f5f886a3160243b5bb0655ccf21e241e6aae9234f024f8f0923852672880b096ba468d194fc68853ab6b9157b74b5b4c528612b9cb8365d25fb5008ca963c8c1a09d953777e07d46b870456b6c8e3960933e75882de6485547024dadcfbe6ad0b9ec94f9df90b59e72276ec2a89576a2b822ef65d2a1e08a6e32ebe0a4c6b6082e0cd0014b1de9ac9e7b83874903b41436f33f15e31f592c0cd53e05ca364b35443975d8ef55ed84d04df5469823a81dc2bf64b681ca50df1f543c109ee2ed5d89c43d03067e2b949c802820a3e4f41e9c597f341a7d1c723085c0b144b84e1089000e2d2405c430421bfaaae8338f5ab49a7be6829df9d0405478b484bc7f916b0914342c2d039ed86690e2d55316e921e88f97723a582a0ec809be9bf47627e1af6723da952eb513afa1a27c4c44576aa12e50293a12255a72d54037797d87a4c6c0f008ea349e5034207ba4d9a0d79d243894eb4f30866ee8a39fee985a686e0db3a7327a91eba588bbc45767d59bbda81f8a8738d16ac024142fae4ea6c9612fe0b1ac0de951e19799d42478ac8dcc787abe05854a43320e2b2bb67fefd6553f33c87712322d7d2276efc313da859d134766790d6d832c398ff764d6db617a28d07e1b58e8a4f8b073cf331aa87e2cb01aaee4e4bef5f47791e08f0b118735059a7f453f2fb9679eb6bdf1d7e380a4f4d67bd44f20a368257beacb6a8e420aa2c01f080b133e124680ed7885a0ff0619b140a7a98320e4e4b5b8f62f292441eec41a6e9a41940fe57c518444a14e131162879c9ba27e250adf8c81c61c2a4bb888cc1f6e1e0363e91e035d761bd104b4ac64860663a4654938cfd53fb8513c5270393eca75b08d2b985e9a6bd06b71d9433dc9b5f531d099356026c05ab20a84fb7b6fc4d84d8a45df89f62a3198d70d8ac9d0452b2d91df5ba7b68d18ae429f3dba08f3aa8d00f8563578fe01380b00f08366a601c24cce7aa5dca2b49829a21b65cce9156789e41dd735ef99f4fa1f149eefb32f9e94c9987aac5fe442c708fc0c152e56d8a51f56cc44009aad093a36dcb44b092fb98b68a52bd9fc778d821003cad0c3f55770495b78aa2ca7f605cf5b77c39f1d12f1e36033445c00c081dfabba904a9cceaa3616249cc5876ebe660eab27f1f51864018d8ba41f3411a324c168c739848ad475a4637fb5464fac78f8496bb0a9402bf7ec4c5342312bd9922b2550df3826b7648cb480cbe21ea763fc3d48bdc3ce9963c308e037d8e4660dd95433e94ffb5b017a974aa246f217afe19f241b7f001ee7692d8e1e99b648cb8c7c3ed9a7106094c03db9298217213883bad9928f1eaa7d58e44d6df4e06bd521f1db4324df63c33c7ab8a8ac00add8d3ab1940594189f142391e51d0cf169324e000e3c93ec20dfa637f135dc63967f44268ad5655a37ff9ad9811b4373ed81c4899ff09f8319209caf2be0d10b36c8403e5305bd3d6aca075ea511f3ac2d68c2d91693ae81a12586e9e3b5075ea5f5c9c6b8917459f6703c774fc7620165776d7708505d46e1577cec9a6935963895b7637907fdb5f1b29abd952803e59ae9cd3761d402f759492f425df8d28d0db700016b99f22284ac81b3b3234ed0fd2d626501e7bf552e11f71bd43e0e38964c4c0801cc7616cc4c1a093c49bcda61bf7713a25be6bc17c299b22fb12b8a28c5c85b6b9cc88cf605921252e9c815c85a47ccee784679573b245da23c0f9e982ad417aed7f023d8c05251988f239d44b108598df12022cd8de8efb8dd824731697e0af87fd8fc3d2c9c3252526cc41230d9a70583c630d02fcf239109c795c02728525d4ab6d63339d605877f4990e1d657a6a9ca9fa62bc17d6421f59b1b8f2842f00aa7e99ba608a8b02e7c7710f9d2823b25a7a5d5c7e3eb0defdddaf87ebdb8d2f9fe01239041eb43ab99491020a0fcb60da7ac902c7cb58e43b8ed6075c07c1f2281ccd6bd074c2b733ffb73678d45b779b94adb93d7f7750e28cfbd20abe5e8d71691369367e72f4718b04353698582d1d612a091d3fa53da3f12a24aca13312dbe46e1612cdeff3d51d3ef48549dc425655e22a5a3bbf4b1c843ecaa6277c8e648ec2cf88726a0f98bd293e0c6add597bcd79aee9cf57a9758fe39d8727bb3ba4d807d091a25c0ae47584f3ab48e1c05157d0712f8b424e23d5067910371dd29c683b10e948e9c776f1e1dc0e0518a91001a30a0c80d5895492360786b138bbd2bc0169a9aa884989837cc8e6fc4ccc946851405def2851a4dc11fd7fdcf455086ea84a97ebe0dd467f260ecad51da8b5de3f149a7b5defe8aaa1822553dc25bd85d754c3017b04e2ec06687511a0fccf4242ad872e1d2078545ff97a78ae5440bdf36c0eb481f11cfc843f51d30d664f69727ef530e246e036a224e7277c54d32b2f7b01e61b74f24deaff65437d12fe3c7ce57241c1a6e458f0effb72d7a697363b256831fc2ee0aa11dca8b0b6d6e08d2cce5c44766d8cb1890a7174d82b1e2dcd9ac2d31df0e0d928b6f062ae2e693ed2a6ba8f20210304fb615fa5b12de22951a5e6b94ff2521760b85f31a65d863689720572f26b94fc2f4d78a88567df6eb6e0bec6b76d72ca35660bbe17dfe2502cacf6358b5debea86cc2f4c5aa8d650d3ef919d8ec24557e1b65cede2c4798d08552238dae89bc7cb494f08b7121d7dac0ab159ed6605a433f9d176084f9c364bef6960086b9c647e121485381e9feb4c77636059e4e07e835ee0a25d9610225a4b5c403575207408e4c65cc6ea6eb43dd319c76a80e7d639a3aed75a596cd49b9ea4d3e85e85ecb115876601f5503c48eed6937fd63e2d4b0f1c2a7762911e238cb96d2c5624bed1c78a3ac4d313df2ee46f9ce4bf0954851e4e41f193531b1e67937131b0c0a7daf115dcb5c1cf9de10af1edbe905afd94dc63c31beeaaa00796dee01393f8f0b977f3a8e83fd8e2131a705d5c6d53ca8542605b93221e291ab46dd3fed7c7e500ee4651aad014965b0127176dcf6471e08cea59f0dfc72465a28fdce6f8112f8632c20a7b7ef6f28ded4a0fb458649e90b8852414b0341de418011a289d345425c5b4da2f77ea5bf2cc2395f242edca700b212550ac5051c429876ccd5a8834b1ccbc6b50ca2774b33b063a6df9eb7e48149626c4edaf85b8474012f4903a6ce4a0379004f256fab66decc9637e52dc53512b5831f382751fccb0f4016771753cfe8a14b0609821016369acd263a9ae3f05dc3ac447b65cc1f914dc0d8bb724deab16666b6c6b329c956de5c4ab6bc4d0c646ad24b2c0f4d43d399c59529c88c8673cc77286558ff2e3371c37a2c5251f7a592bf350fa1a3d05a71baa86df1275a22718567fd05683199635719980e44d27932a3cd255cb535cf45ab36d9e09e24d3a22e2fb946097d91f052dc6e717346372ff0fa7cb590ac1a0d8c45bc1de6731c4110b1be8ca7e52b99f38271b99da0074f6607ee9ef9010fd2a60be785f595e38e59f0d88722543c2a410819b5168c96dd9785c11906f518b253c600a112447d436b4a82de12d7e2dd9fee34647955e482d664b7366d76e692c97aff602eaa50bea40c75b5d3e9eb93f7570f0d75112872cca092b46852185c73a8f3f121b56b6d1042bc67ff06ea6bb9c874bbf725ab6de1580863f05201ab48a0055f7616596423e66cb4319d323334fa6b56352090fd1dff001c45939a280a875fe65f45c0d0c4b2b0e099f4b6bc73d1791c161b7de5fa9c8cede97c837b9caeb318d404a0fbc8606e0d29fdb9b7819dac810aeea4317feb87066561d526812a05f59162871818b1af1db96453a22cdb7786e82dc98627fa0dbe41137abf012ee78436fa3d9a478aa00577c71a719380a13262d4e9d177d5efdb8bb952abf55346068a791bfe7793a839c08ff879ade277085d31db1db1b2cf93d72c35447c91318e110fb0d2d030ee339d60dc7f8107100aa40e47ccb8fe33160cc71ef38802e6c1e2c7984b41ded5ba4bb49523acc7ec3dba1a2956e5a3425fc4670d0007f6f25abd680592326089adfe0dc4f8a56a2a294dd519e4a17a68f141125944f0a041610236d81120cf81e47a5e3398c64096230b49ef19fd8d894d7065a68ed1855224cf540f5e3689955686db3d507cebe413554212dabbfd0517d4a6920605708a0b483af84261c7436388f63553c3f261c73ff6d1400f318d3203dda378b01ecd9b3c367eab7dc75da75342305af508a0665de0e1ff420859252bf9dbd6cd8177e6ffdd7864e215e3de7ef847890c1186be03161d8c63cfb02e9da888a6032bfffb14adce3bcc4cdcc632a22522cde4d98704008347c1e6750a829199212aea8b78689ec803e9291528302b708305fb3d790d9d852c8cc5e25a114e9c7e4a48224a6b0506a3ec08233fda0969ac9e64f75ed9495a50ef71e92c0104db383a12bb6fc3bc8b6c5275081c664c96eb83e33a112e9c09c7a972b747790449bf8e9494a910e56e6653422637dd339aee8b01114d8f9083f7f4b63a0552ff5998b0b4d40176a411326421a21c7a807095dd1dca12b1cb2ff44cd45bdc67266eb2782e0d26768eec38cb4d303cad38ff48e388e0ee3cf7a0fbd43efd03bf4827a7f6c9934f0cc92c9cc9769e6cb24f36792f933cddc7f66eeff676c9a919b6c11cc8550f2a21d4895e61df66a3ba1515a9b6e620d44a50dbb44ae20739ff075ecf4434a12806ad338e006176d273c550a66688cd096c21a6cac494b52f0a37a7e47c99ec5b76d7be04ac9a2dd0b2a897376f750305706815a08bbf31c11cb5f8afbcf72898a93e1ed2bbcec2962d5e6fa22258bde9aa4238ddc4562983ec8cbe2ab7a50339d8184d09137ce67076e913f45a31124b10357113095b7c460a5a1575837e348ef9362ab5e5bc83fd09764f2017f33da2f1d17d9e8e58dc669d09b3ebeca276e97502ae6f085bedab9306ea2ecd4cb0627552ff71d8c86bc30d04d618ea47e665cb8c4d0677a0d8c07ae96c9eba995e84ebdcd57f90440b2a4b4c54729b050874b6236c8c290df153b8790e1150f8cb938eb885de75e8a4c3423882e5a87df0a024b35abeeefe0e0aac5e8bacc29f5dcdea8f99c959c6e55a7ff2492a352313e5dc314debd485441c2219c3398cb27d53c78c9db093b0e36a21de32cd2115c17709bed8ce9b14b1ecb8684cf29533bbf901775ba5062a811a81cc054392590bf3bc6ef06f56794f9a46ad035084706e3db436e9a4319b11ff3ce3e3a0de45fb45c62b6169c89a2b711a79c5b3a6c0b8ee02ccdd5484df38ee090712f8390a033b5c622ecfa1f5e89dea9b40b03f4508bd37f8fd9e0486b3bc6c0dc4609cb3f17130d56767612190f9dc5ad740da851012212d08613f2239380dad0d55e458944a3ea4b5e161a245f71d83cd5f223d382535dff81644a11c117da4e6916953fec4ccc8c292294e93b51ba166412075fb6293df585c753c9f4fae18510c1041c0155614e5cca6ea673e364c2b4671fe8b3749be23e6ec339f9b579198b8c9e348b8caf8020686676803a0f73252ba23e14db12473d53976623953ae5c8dd18aa89d1614d8a5d39b9f4ef0c9b5e1896e04a58d25df73f5f25619dd0dff3d69cbb4b83647bde837f5195514b9dd42486028ac8807cd005e9cb1e4ad9f2498317a2acbf14e63563ff4d31521e6a2fa7c0b3836f2fd60624e6162954124523a3e9a97bf856df747079e00595fa88f14679a16462c960a1684c1a25634064347ba7aeb7f2156ebc0b4f4e9c425548c28c6e853ab0363fe23042d6f540637f2f17ac90fbd675efd5c09a926490f909499d45ebf4fbe817f53e63c638d1527cf04142c442e1d5dd5c5e0cb9b77274739b9827fa6520b438693ff2fc6a441f64821bb1ed444ace94a932ebe81e0e63897d2d2f91969280263ea207847af03adf85121c4075de74d60866ae467d9cb194b8307ebb20c1bbaf0b62950f40ce8070f375d62832f16f01c709ef8d29bfc3f8efee9affc1b9feb4a4ef323ac05b2771fddeb61f3d40d264453b64c5e27d4679f0100a8b0a38d0819f27c471a03d819abe7d2f0d86523d644b858b1b61eba899ab6506ce2678a4cae056ef3c7adbdfa72bc39a671dd63ed376468b63ab2653388d19794b6928bc4ce7c55cb3503d67c26b0b06593705d86254eac1a8ce892c8a56363a71ed4137d823230a13e64e13e015753f80d64de27f8717648e7742e9c046f426c1e477778c6d40e691eb70bc88eeb7168e44123f74ca238791eae40dc3ccd88691146d0864e57241847d4f5967936aae19202c752594886d2c501f43ab92a0336cf6e3a1cb2b72c381c650c12fcb65a5ea899bc0d2a7b1c3b41465a57908a4f06071d0677499a55e59f0a66b3ca0e37cf13136a9afc6c1805cba610ff10bf1e50b29c9386b4b11a5bb8e92260cd2b1defec783893e7fa59af4d325c1523dad75b4193461c500afff8238c60d76d52e93a6e34d94341e41b7fbd1c84628dde500c969e682ce428c99c3d4ac674375eee73e780eda124ee6b1f246a0ab6f1456f5ae075ca7de0a27717d3ff46b35a3c8b922bb866d79fbb0424796044b2586800f5d2bec6b3e7ab859eb46881cb6574470798c0a1dc616247644b597f14a1c3fb68a20755e57689360a3ae732742e48789d8cab27fea48c99c0c565b655c3d7e92be7bda3c12fdf1af302bd20cf779de2fe369399e47ef46aa89dd98902d0ce6282c585e7e81557218371abaeb038c3d8c841131acea719a819498155cd740795642c4a33fdeca6d3dcf4220639846eca18a214d2e31a5c6a34f5130529d19b1481481ca323c68e8f8b3eea3b05487f25065da5cdd84d8e873320db517a35eaa3337ec53bbfa3a7802360d653714e3fa721dc97595b7de1dc97feebf2c02e842b776e2ea9581b72076f87add3671e00f2bd6af8c348c2b5be1dd64a4de0b23ebc7c494636cd49148fde0cbc0ec11db419166ec43fd903fb8f3a578ba0941886ad9ad7eabdc4a92d63d1aea547d02d9796c44649f0b5fbb9758483fb4c2f043b12446cfc065c1f43071455c7e6d434aa6578a4f2ca618b096aa2f86f5d3f068336bcd5f8ce8651e28c89dbe147f0b1c1fb0faa003fe873734a027ee86cf873b5375245b9f42ee790279ad0bc7e152d0848fd3669bafdedee9c3f2a5cdb838aa0c357ba787dda554ec8e20342cd4fa19608a4864b2e949c3aab9ab0ad617d71bef6c5554ccfc03b38cb69a2bf7d605d95c46a4558fe6510d44db28a8cca0f5fc6f21f4099b5d38ed84935a74cf009b3c49a35bc91247cfed0c9cc4648f7d29658900fb36ef846fecd46f178bb95a64834e6d84f7a5785cf741263c13a016ebf49afbc90d0dd586643590c795190e2212707c785fa417144dbc9fa510174845d1c5eff259fca49f7eb7ac3bb774ee8357155dc35f067ae31feb51fda0f6363ef2cd922d016addceb1185d4bc138e92dc99a2f25a9f2cc04e990096a15317655c0cb7b4d8a167ccabd598e243f306d66161fd4baed11d47031cd6b4634342c9bca1150953ce702dadd083f115e809f84a6fba02c8ada3683493909a79b4209da91bb12cb441aaf14c366f8e2f6628b81b1b4e44a824311a7b87722323c723be5d874e13ba47a70e5568dabba48c81f4e67e3b4290e9461b809e9c4cb980f484757ddf454efa86a97d96f379967911e6a904115266c28da27fd471afc2941ecbf440f89975ed38eeb81a43f6874d52b63973a19f8dc0709e13468c819bc46c7ae45906c49dc4a8cbfad2a663395a0f71abd4c3a289c239d1f4643c7c28d6b34be4df8df18aa7d63b358c931328a4e338bbaa99434ea05d29db25853a69c5b1160b9c03ffebfa484290312d747c932ed129f6b39e83b9661015c742266ebfa61fab639cc4ddcc80ba8eec34db93c07d99e58388ac81036970324c22e31e20fc2dedbee00a7d7ca00b7ce7105482e01eeea6ec60ff3ce5883f1311871254f3a91304eb5ffb621363b9ac55af773cb59e14ef54ec0ee82927ba1df5c242cd7453012b03a9b60b915e36ec319ec83f65caea46d7001156c6c7f86eeb271653544c43658bdbdcae623c02faf8c788a1051b7ee0c30a3e21ee2cd1465be31d491c68d8a30a6f62196347be4acb356d8ecae73967136c1b258d275a01f954508ad58c5cd741a6b1c896c1334468e7dbcfaef757c3ea314a81c818026a084d1a2b76b9f5e2346f3ff11911788f83c71b98e59db85c3c3b62da6742d72f13fc4f9c1339ec745540f16cea6416a2ab45f37ceb971a607f6e22f87a18c1479f2063d1cd8c63ab7c1e0bf98e68b59356f42c5c4b4ba4bc41722cee69a4c66756f4f2df6c915c6c24c50472385d13515660c3eee88fb162039eec0445741c423ac616b0364fb942374ee7b866fa7edc4ad31b91a25e51e0e8b08dd36f456e807a9dd7ca0ca3f23398f14b4e979eecbec72d73ecbe3fc5157abb1c3ab514ed4b8ecd4b708e62bd4020028976ef425fbabdd8d2bee63b36b319d4437753a952b684e0f129c09acb1238e9ccfcfa2acb575d4be3d78bfda28c25d408a0deef4bd3491ef476c1a6a70b4cdb1ef5f941c3e6301ec95243eee3122c0e5b9007d86d503cdf4e693b2555e9b6e40d1b3cbd3f0291b402a482fcfb0a8a2d421f213b3e5e436bedce40cb1afed6cebde59e30803c84d35a08f1c70b3817d147de168089c0b8bc02184271d990c580f781c0a8f41580462272a13dbc623435f9eec665a7814502c0809bf0ab29f9607af6be7cecb9496506ef3101064e46b0c527f06c4d86583732b0649523b172ab2069f6e696bfc3de24b0ab2627eb67aae9d8f4462653dc943974154f7fc646c836efcefd9413a7d655195930de3604fab02a2eca1bfc45c9a6e48c97b8b8de289525c2326e8c3d0a483e5b15487f2da2e2b99f62fa752f7b6ad3e4bf3bb4e63346a2b4d4e6ac773a15352b803d9196f72332a1ea9cd4a98b4b26ecc56ec998b3a9b1a79f79ed1cb9a4e2ac6f780b41e6cabe870dc0ace0ef71358078a58dafe7fd8e851159de221c0ff02fcd6f65b85c10345c18d30970478d9d55faab1bdd569d1855077d7e94a7f37550ebe3fac23afbcb63177455bb56f57022dc148d2607ab64ee116bd45857f17ca94d08bfa27572e0433aa8704d99813ce07bb681f02ec350d5c254d01ec989d9f095dd7f8821a245421c82448738a7f10aa5d374d1a081c1d13f48686212aae66a767fb83165f278258ac6782813eb18980138ca3f0e2fe3bfd43b997c21bde9369bd53ac8dcad7c18498a9d7c024ad5d760c59d164a3d07a6df33df891b12b24d1d52716ffe3909057a7e734a62e1326268c38d96a4b162d16e9078b4298376f13819471d421b8ea9283ae96923966db1ca226e0353d4f4100ef9eb907a65f8ded0a353de0c157b105e248c26dd818e2196e05192cfb309ea58e7a8098333f93ca9eeb392543cd215f8c12a49619461d83b4e29c9194dc41a8e47622d045b67bb7d5d5d5cbf425cfd2d55c03fe607470321c19ddd21c11b0783bc38316c0f7bc11fd6f7307b671d04cf2b5a3f517079d28c6eff84742439c629f4f42e575cfb7a267fc2f9d16ad903029205aa06ee2fcce0f768a2017cede35e944416351e2e9e14850510cb473a1ba1619015404daccdce24a3404bdd2441ac8f5e1c0b8c1846bdecd682356531b72ea24a6c20430f28301060834d79ce098f1a150e5ae2c28c7f819db1db5c1e555f6c67fa7da3922e45c10b1b1d52ec700be3a4fc6503ec9d2b96814281ca4c4c79dbb88910613f324593d7f365447885a51687e2462ba4dac516d646d188d0936ae12cb8453c176228d239bdf152c223ca54a87231aec3e7311114d7bb0ebd6f501fb61afa1e52fa1d322312112f1b904b1d732bbaf77b8137d95953dbbf4e844e8e1d05b1cd34a297557a48692a855236edfd75eae9ef9bd8af414c1eb1d2e6f79aebaa6ac7144728eeb8f84a4deab89f4e76a21c52e29a972d9d9ea7852891570facd3fc33bf0ff28fdde5f61d50788c2b1e429e95b3efa2cbe1ea98f2ff692d82fb299bc08cfbe1ef2301da15f3d241a156945c676a8a71bf1436c0b090d143717b627186934b995e6ffdf6db86937a79a5a5557eb5ebb455e9930aa2e76b8050814803d349df5734957249448f12109110a88958a5e4dc5677525ec0340ee75e7a210c4d9a277efa725f07f6b70c0a0323354849193f85dfa39f930e3947395ea7fa042a3f97050730181d00631a753d3b26d73a4dc066f0d78ff9a2701ba36cffd7edd3cc50b80f3ec558fbb1dd2811320d384425b12ede53ad42a6b11d3bfc33d1ab589e65a34cf365626df5c5083158b802980305f731266b5292ac8989f06be43910f1a40978e2e0b28996e39be5ac602d55bf0c12f754e346881e680b63e528f31e836ba016af1e23e482b849c3c39993a9b039961bc675483184b5525e3f0f10d3cedf7e3cbc09b2fc26500d9050061597f73ca553711667ec9df5c4abb519c5605e0d896061743e0d6c0b9eceb8cf52fa833e35a9d52363425e30eaad62f5a81e1bebfffb8bc648e144302a60d4553a81124e7e003b8f63d0430a8472c86279d8eea8fe9b80fb00567e153ad6e8a6b623b85218340e8033802e766a87b53d0a52001133d4350eeb91d3041efc1d4dab7f09427605545f68bb48238783da2a7c0ed752cea01f94d558b47dc51010215a158c934b95359ec1da07c18ea002c8fad2903562202a82a78ac6579d9f54007b9fb82d6161753b4a70ce162a1142b0238385ae957f6bc0482f9a72efac0b7268b82e6f2c7aa019a847c3c5e21d3656a5e82853c420f7ec58b14f3f7f254650b30721da0f4c70b58674fad814a98a089ba7372f575ee77cacb618e1795a19bdf537a8ffd6ccc047da690167f841161890ae8a44232d767eccf538d8949e253ac26d8f2dd03712e62be88a117667401975bc29e03e5cab2fb9f42c5eac607723acfc644426ea09ed67a71e505457ada4cc4ec315c2fa880b5bef5a18cceb33d5197204ccd50a819d2ad5a746c1dd1c30cfa2cf66b34864836cf48b303564521a8be50091a0b15a198bb237118ba199e230b6d1056d2a1f2f4aa5b3940b68d18be643cc5cce552a6afef9a9e5c06f1f6fba97d93323b567e6a44058c8738839748d0fbcf338fa85c0d378cddf31b9093e07e5c43a46f830138f8398a93dfbfdcf49fd136726b1271884f5ca13983db6815313e6de49928608ab23967558ee2129914e037b7f42202b8ffa03b72b0abb3ca9755d177da097706c6631143f6e00dd82d7f4e3bb633c7c824269e0b2ded6f4d46f521b828ed3b0a10ac31ad26aba789743e9f2b8174b2299c3992b2225acba2424e3ff5d79a4d9f8590992911425a2c7b6c7df8f050bdab7c233a5a79f212e8c4da866cad637e6c341276750725f4a38fb80b9c3dbca2c0769467c036204c9d326167a3f354e388e29ad847e5fddb338c5d7bc9473873aad5aa1b2a1b6f49ab723600fbf0a8944ea1cda3de29f21acc4c109667fda338deb46a8f885b5fe6de90f02d9f1c5c44414807618fba68ff3da1603a0b025360558aa0566a9d03e0241b0a993f904dcc3aaca145670a03ac42ba5e70e423eae93940156393d5e3f4459101d1303464f9d28d05704fb4d0bcfa4b95ee90cd50186ad0fba0a767e04b4a4da214997200829ff7758c93e28fd9b71518a4a64f98104dc21dbd887b6c04565647dc5a6cad0b6587ce117a1e105edbd1aaeeb7ff091ba02bbd4e11040a5505bbd319235ff5056ed74e2b4543ca1ad7f9b94578cfdc8163b8f8322833971a56118d22c29ae796d354167a9a2263632a607b367de66324730deb3cb0af01316909f0dc7fe9c8c2ce78dd4de75370b392469acd17acfa462f5b887e4dedd24ce787e35c50bd6ca51d303836e5a39d9f470897ea19998b9e6b8a1d320807038f65598f45e329c3e2b719b14c62545d7072be81bec79f232631b5d7944d7699ce7d12fa6f93676e5e609a9c0926d37f638d0b891e3ff884fc0b72fb70e4a5865db8f8c3abbf238cb0e0bff6e5b84e0449c957a484ad3899e419558cf162ea76da74de927e6f4aec994bffabb1c5d43a249c91c19acd7071defaa3b45df9e6e6a4e26084cc8331cfeefe06dd7c8bc4f5f75c443350d7c5a2b5ca0877c5ba74489583888e5a3289d064bf61fe134444a08990f19d954ad072309ed1a0b6172b28cbea90960a75cc48892cf895ae5548e056a19ebb3d0fd53180e941eb4f3cdf087030de653a930b04551acdb9785d431748f7f62bbfc43adf982a55d51f4ae57cffadbf1249a545db35550f73033248ae6763d7151f8c510ba45daf0921f56e35e7367eff6278f0a80b59b5be4f1f1cffdcab5bb39d15e9a34110b884a978305bd80a4889fcbed67303e6f4d4b51a04ae15d7a901252e429d4f4830b39675773bb85d9a29ba0b9d79240c4b2590bf6d1d12b3fc4394f94d1f29eb47fb2bcfde00256f75da6f82d876d51c7713ad6357cf4815037f6bdf78e476893f076eb60a1eec66c833de97c0096a1f456633100555a789f17bb38e7ecf0b3cce2b480004faf23a18283d3a19b8ccf4ffd4011f0b9919038f618f1b1859b78ec6db4a3075fa0d9f84da750aaee3498584cecdc3da5fd6e6df52a7866630a4137f28ecb4c136f3885462acdd0a517fa3f30126a6dbbc28c3fc7f92b375dfe3c5bd0525d285656012aab798d00050236d476f571d5a6a2f74e6dbb37606a936dec68c87ebde78bc015d89bc9cd1e0f496319002c3a76d5f56250cc23b9514fe225747739a0e76cb628d71daf5019f1b1dad99df682e04b0819f3cdeb5217a8ebdb51e302b8a78b6cf1ba8f7a5523fdb276d45db631fa941af7e49bfe31e74b25501dd8045eeb901c84c59d106fdef78616d8774ee0623aa4e69a78702b903d9dbf00dacee17d244dc22c90102f61a8715722bcfcd64e3303956b50b4ddc8f756c0a4511d8cb206a331dabc82d6810e81a7c2d75ccd6f51414050fab644dca41fc50a1d7be7d33f4b4ceefa882b21cb6e6a62268acb2082f7c3cd5c6de7357fce74acf07bff79fd8f9d88e267ca3257ae06493afd7ab8bb5238422dc4d55fb64791f547f17407fb1e190703abcab819f12da3ef1a8924295763fb08432011bba42a983be6518bf266ba7ed2ac55b443c968161301b160c93d1a962bc84ca4ad98b7e3031320f84979586cdef9546808df05a5096f8e3072fa8a7ec53697488bb638c70f823ab7cf7c89742f65941cfcf07cb8d657cae622e744e1bbe16930d0f732e2a7ef26fda0acc668146e0d6bd5c4c7365772be7e850f8b63fe7c8e627d5c43bd1230b471f3337f97200b6fa4ef239a237762276867eb01fd04ffada2ed19acbffd6275892875e3ee87d74d826cc31656b84d83b53f1037135d33eb28849feda35ba86a3c05ec1899ae20b2e5cc6a6e9636a11f22bcd2a0135482130d9fa2e648b6a93e4e7b0d0eea204db28c432cdd11d0370eec50ad6799ed83241719aa8b2adb4e29d861dcf041b814a92fdb91885bc316c679a5f4271cf1dab3456085e95e8add95d3224cb689744b1cfd8c6ae9a3784d400c199ffc125a3863ea659e705aea822ccf914a6d305daa9d613077b9f17128c1f277771c86e5d41c526e0bf07d8312906ae0d3c8245537dc61f1c9c5972d9e66d5ef964537b88580fe445ef641b497371b6c589f5ce2b33c3c1b7bea9f8a136b17f231763c4cc5b433a00ac7f01e40dd14d78c5838c293941d2fcb98b69b6691bc46d9c628ff7047626bf472019a63ed4611ddfc4d94c7a2045cb43688375f548fcb9c86dc44e5a4edf7f058bb7b5c31120ee99d79e58ffe8fcc2e413d035fc9508feb3811f9b33d7c24d07022131fcdd0f3b90af9eea506f2388eec402e02ea5e69318bd8cfe28cd6a7d514e3c93c187302086375b203a430df22b6f139e66bd9620ee056881fdddbf7a01ebee2f9cdeb8c84223d463d46209ad264a44daf757d2eb3496d0ce8a1adaba4aed5ce0d8ad282daec30c28ded196f0c6be9e787f33bd1899d165f6809c71e3f19673b33461bd018524014f79de637ec6f1cd0a1798fe3e25b4bbdc3a08cebd12ebe31ff43ab9f01d64141a6bfc30159470f37a576184ed5e9b65612a799d0a5cc63ff8bf48d035c78226b70ea3a85b2769cd72ff96106e5da42f73abc159c0d6eff79659e7dde1267f6a4555fa22f3b3c562a0a538951d26cfac031a487dc8804f90e370561638b8fce47309d067bec80236ca2aae4b1a02380e3757a31b49057488e4528d6e34788f8caf7116d45ade38bac93039bd484ab10cc6d680cd111138543960feec38e2876e3e20efb3e7d63f4f44bdd269241780e608df3a06b392c81416c45e8f16c9b7c389920fbe9044b5e505172a45884a203f7d812064d191bb20bd78d98ff7615b99817a79457f7fb6ef5f2621b72cfe546aecc8fd2a0b8802e4d110e2a5852d60ef15a64f6443e1882ad3c721d93be1c8f6b400bd47dcc57f27350205aa9f4e689f2b1e33c66ed481f472e033c48860f52a15b145ffcf0027cda9848472a8543c15580c6f912dcdaf977e27a2c2bdc013fd25a7c3eeef874b0e0df4706c0b0cc3be4927dfb7ed3dc25e795eeb0d87bcb7dd620c264ed45c09b8b569d26b38c2d3bbaca1d7506a161fadda2dac7ef8c4d3ae1a2ca1bdeecc1f105b019f3a8b2c380408ce6f4a1f6eab5b290a17375b40bff549713cb6333bb873226759c16c67b98f66e4883b8586f3101e22eeb21401fe13c2cc657a553051ff7c741bb4eb73cd0f5dafcb732d062f0f3f6973a98fa895ddf983f3a726cb1763ed2975d3b58bc83bac937f96032c73f4904b16a395989a036c8ccb44570beac0863828ee35dbb7b83c433d111ac8da7e3eea41d960fc5fd826247bad5fbf241313e643891f4bc9883e3ec309964ccfd12c221bd4dd530ec333e401087392a2eb04ba93a675e25b5ba82bb3dec875b6e3439d146c51f4df859c47092b905cf05cfa474fa598fb163d66e360954adf3147ca1340d3ba412f34ae9e8a0c495fcd31386989b2c35b40e72026b149c04f267473648d39728b49ed54dda17bda716106f9fa949257e824d6558a52bc4f6a8cc987698c1ee9dff02cc9356d5c1f66a37b0a05fe535ed30557a8b9ca304386ca606e887b53b792b7347a26f69407f51ef9fddc6ec8452ac7316762e78ded474849c5e265ecb8890414da9132aa58c3196f24d81d770feae1d8d02d74e368af7783f79409e79a05998f598fad93eec867181601aee4025504ca776eff79489eeba834f590b53b11cf9cf241b8443e351b51eff901dae346d90dec496c1c5bb4201f32090815b61184b510e2bc0e07aa8baa8f0cd222436ff4aff7792c0c96a62ab658dc41d399b804c65a403954aab10025112bc1997534f3c3a3ebe6a3b673949a7237c8981b5872ef00f5f5366c7c6a05e97fae62487531e06d2245ff8d221f8e229052a4ac36c22f4e14a53a917308c31d7076d2a849bd6fd486c1d1fdb574f42748606da2492b4703617d5d9d7653222e525d81b4b5dbaaf812b05121535fd83d4ed0b1a8f11ba3ff22eaf4e93be37faa8d560ecfbff2af973770279f6ad8c2e97f5dd83833141b9b07f22fa657eacb365b94329b73522639d98bda31b514ab174994bf906bb7aa79e0b6e3ba45fc2ba1bc1029255a04ec87d18094e28f2e119d89add3c8df9f3d92e1118470e7049d08ac573d84be47e07d13ce9cfa091755110e434d83a2c61a3637e52ffe9ebd53e6e609760e211eb0c8be42f57f572f795004fe1b75ec11dcb09633377aa77420aa05435aae574c9cddecc08470f22d25e447c25b77e93409723157cdb35239a825ccbeea699e3b7f7c40a4c61b5175f819f99a8ac0b82140b9d4c9508898d3197c54720d8ce097f2f8850d81d28424819c0c3bee386dee91e24acc61b261f91c54566bcbd63f833d0786539dcf4e51c1c6042eaba0fe51681ada03247e61ca2614abf2cd74c2d38cce4dd0b78d162fb40029e033b8b8fd33cd8a7a6816558745c7630baa4c255982dfd20052ea05006cbe74c3d018000ae0597f567679d8665905842f307664a83862b39d6bdd9a51b906f71d9bae9c06650e9b52d688ab8101d9703077632017dc702e737a7c2fa9bf012dba320e73c34b9cba13fbf8078292b2882fee0014b84b0c0a3aa04b88f8cc7e7016b1217798c35c8bff9422c423d703b996d13ab934d74b6816f09d71a168f860ae7114905a98bef343cbd46fdb4b8698e1ad1d76ecd19cd658c7fac99586fe4ccbbc7d1cc36f606878d1be673dcd70a460830cd949b9a5ac9143697cd987659133305b0963c36dda85d726e4c1e5e8dca64044aa1d6da3eb0e0dacca948f6c52322e6704a1c00ff8baa6e9b63a4984a2d5be1468fd26c2aaa6c0b0913e131b02e8c56ff2fff94c5c4236f9bb725b347841fe6d71d97be95d5d9072dac89ae92e68cd1e3602ba9d109dc40cb9667c682f547b026dc8c720f365ba6eaa1d4f5f5d271c5b4d50b3b7a344dafceed8a68783f6fe6e564e04699cb44ad607cf80fd8215125bfe511070919a07111f20e69094c508686104e380c12766c1acc924202d253e7348bd9896425c96deb25343f826e2fa7f666f2ebaa9169759f76d0d7d7b82eddb865257a747fa479cefd8619c7d6d2c4dca9827509832574c11c6ff347384af967c4bd522a2b7a7ff06b081022c51886d3a732a2056550b99d8167256c285a48bfb8ac90ba22b96ea08f87a7b147c4ab2b5db9767ac8e57a88a222e29c0e8bc1a81914b978eaa9cf77148e66b8ca0e8ae671f057a25ca3c01568558d279cbd9602725a354e5338a5999fa3f57abca0900530bf1ecf59efceb7763838286440e02e930ddde321d812fe97969ed38de228dc6865241764afe740ca0b59fc5b1e09c3101e132b80ca66621d3df6982d6f0e364375002fe945ae6f886d98e20da9fa7003795d70efa0ace45606a56846861b6c2ce66868f533875db4a2c8bd99a7db3b7fcc1d1a6ab9269ff4815279f3ba0072ee595d4ae9a7827e22b32f72fa47adc4b21631d7008e853d01bbc338b36e080d7223ca09c40dfa5d6e216db0c230328d215fed59da0f574bb53707b12c769940994210f36cba7e4e16589616956a7388bd840b2db541c54fc5609a9905dca554966d4ef9a931fd400cd2c3bf9a02ff85da6e20cea059f95935fc402cdd6ac7e6bb96d54e3666167c18906f101cd6cbb81d0d647402271378d20de5adc0d20a0b5e918c3b028967fcceda928555850c8c5282d44dd0eaf853786b678ca0a9c15a66ce55ad86763f7f82bfc4dc011795e1393e388f87038880f9fe7e78cdf4ffe5cdf2d16fa2dc27d17fa30e2fee973b7046d11f0d602ecbe8a71516481f6c56bf92653ae50682cedc3b8d001849f17f5923b3aeeb0aa5ec81ace7224bbe204137319e897a429849347ef17ed3320d2d0fba33b2d0f326dcda1d3f80f5e151f6a5687453fc6457a06cf0a716618dda400cda78cc7f0932664756d02a444509ad83d4844adca85b787d7e7aa7b48ee05dc894e163ebef76b82d4a0ec177137d412b7b38b2974d74847c467c431d94f7e9f04f9c47e0b1480df63a3045a8c7560d0d2152b0a820acf4700e8ca884526b51540dc5f9ac21722e5e76d0e50a35e603d66ef6a5507a8d06a077e50051f7fa417fcd527ae91e69ea45f8b85fddd941ec049a597b54932f7eafb6281d472b9802230d47f1a4ead80372f68875e60005bd967062b44f6164fb3d6a201a33594ce037243005533946894678f0969e5223fe7f07147c2e249d58e39671ac56bc553a0a3ba3530e7311afe3e0da38fa4735c118a0ed8ec1a0b8186c4128dd9f26440fbedb1412e976ad51e55915bf4056c9f642c85942c7d1942c38c31175b86adbdb0b3213754ee015089dd53573597e5958cbbc4e60b60647174bd11ce6620fe9f51bac81d193daed36145e3b034930e02771a19a0c4434a088f3338796b25e3cb389a104b07a4c0f3d096f3476bd198407ed08ace09a645f30eee1ac53bfefb3f388f0ae00a54f2008087b95b6e4f176a8edb8c49623293b010196c4ffc4c7ef8cb0e9de83c7d4401b8649992bcc1b89eaf82c86eda14517bf7a5a1585f603f1f4681026c0b3260ce95fb88daf287ccea9a36394acc10b3984dc9a78f789d79355b65121df43a87646e806afb54cb642930e8b1c784c39a12a0ae7c417ab17decbe4cecb019f457a86cb896a5d062685bf112e01da507880620d60b81df79c053ed4e656c4c52e13d0beaccf2f30b44f91f447d9c395370cb1e6b9fa11e27424b0a66c4bc51841b0ff2024eeb093177a01816226662e85699d74c7200469e15d533a23d390754515715f603902cce8265fe4970c33cf8b25ccfc5b95d4b17eb778c355bd07d32b3386786f336b03bc2cecea2609559c0ba38d2d3ff7d79046bfb3c4f10f55844691c49fa4175c57df3b49b4a37d329e8642c52c8c19871c8deba48db52f8caff1b3a06cfc027f72045a13b85db6d1858c6b10cfc59a0d9fe9a8579f81a379d01d214c80a2770fd4185c4f22bfdfb64a709cc6a41cb639f3a91a3b3eddde0b5b0bffd59991fd5d34d1f11099c9aee4e60731b89ce799a1551651d4ae222469eb8459f13495ce90d652342222b78427e4c562488e328c437bffc65053a1bdd01eaaeafda8fc395dca9435cdbc6dbfb17ff391b2e304687ed336aeb09f0af4c5e2682a57ee75b8039f4d6e79b4b0c39bd04df84723a92d37941742e20f8083fcfc77939be849ff1a37c9c3fe14978323e0af9e62225f3f7453fbd7ec25590091ef055fda0d578ea3205482f253112fd07425621905b9f9469d69515e4c868296e41b8166d921850b79d4c2c52e83c34ef3dd3cb62805b93bb6ed5fca37b0deb0a624237804c12f4ee5a31512858a2b6ad958a01e216cb35b8f651ccbee816aacd558589076e8b7bd047ff1a6efcf00c6018220989036e9b7b5259752057dbd60bc5007123a871cb43c930c0e51cc9987810976382315c31511327bb016f2d7d5231406e810f41d52856945da800d159985f85dd069043080ef992a5341be64a51859a1afe21ed41c6b7497e9a367b75be6a725c11df1f2051fbb6f0d4a3fbebc46f633c75232ca0e117f5f6f3cd6b0e1fa9febb37b182a7fdf22068f7ad0f32889b95e06b48f8b7e7f5f6e0b04147a64cf3ebcc227df5b9883feed8960dec068c4e259fb1fda3ef81fc0813a26c188d3e495ce5394f073bd1a5d0822031491d7ea87c15321a4386cc2615e90616194092b82e63057c0104972b7641702a7eff811277b8f74da2449d323336b0400eb7812fadf98654fb63add759ca35937e4a541c6019f14a3ddfd429183759e40b180a75d007f22ae09bb8a638055343712ce5bc244fefe616c2a1ebe3527319e6d320cf73e7858638c678f249136896cf663a1557ce1fa82a06a51c7c252efe7721815d554e5b1982d1d39a66046283757cee56cb045725b49ae4a584dad68791041e4f10115fb5c8775bef0af5159496a1695541b5f645ccb43e93b160bff3215ffbac485e8bb11d028e373af25186707c684a2dff8d00dfc6ce3166905f5940979180a38c98cda9d4147aede7d82b83c89df1ca0be5351596990fb602b657b20416c5f3a016a5ea21ab4cda265738ac357f1244e5755f1bddf75552e858ee1beff11714b2bb98701b80d28c3f3177f346ff4dfb47c6116c3c5f7a87489fd3d3c14dc88bb622998cc6498d1d2b2d1fd7fbfd4c198a7927ae775c6923f2d382787aaabb1816402a697c4c49e303e5e37a742d3000893482f263091e93f55550eac408bd26759f0790ef3094cf7693d1bd143c21245ac802e98f597c9873279655db9565daed00e69973d41c796122965ea717b61249bc4dad0c011d34f4131a1f2b3dfcb4100ebe7a93c60548251a1e286bfc00f9bb130c7ee526080b50251b1d55d2e881f2395d02d45514bec96eacac4c8a64532163501302cae4c68e959edf45b76dfcaa7df1d537765049c30384bf3ac1f42f3683b080efb892c6c74a1a61fee027dd188acb990a08d90f52b6d04f68f048e9f92cbd4c0d85316513ba89e78fd2eb067e03416d9f7d2babf375a8acf181e7990e73f07f298802b0eee048a5fd13f809cc68022a05ae745630cc249e03330468f56fa1ddf1259837991668d6e5f97785bdfb627b2ecd7fd70fcdbc332ee493aa38ab8a30490b183eba4e35046755c42bd110f40d7266339020aea480d1da4f891fb160eafa2db2b79432a594640adb06d50677072dae3fd389e07abdbd36747d130b5c4f36c1f5654f0aae2f42747d5ad4c5f566d00aae87b22faecfb383713d92bd0b5c2f16e37a39dc5a703d94a38d1d8e777ddd2ebade88d1f54eec645cff7cceb8fe093bf45f9b0bae871b4261a233721aec30b8fe2e7f68695c8fe7a347d7cfcdc8d5b8fe6de79ad4bbcf2114263a23f775eab56f31703d5b7f6d3e77ea1b76555e10d6f2203dfb9c9ee6bd37f1e5a7abfff5dbc881f08617086824f71ac98d21ac0099daa555a66ca4d65aeb9c73d659679d39d02f6bce55ce55cef7de5be7af89daf4e3fddf3a07faa94fa77822bb24165d3efe699db1d8ede69ca6693af30a917ec678e8a7a9cf0de0481559e1857b8ee41e5961efdff106ee71b000123ec61b3ce8e92f70e867bf81431844fbb3071ae50febdccf9ec589414cf8d90b87bc0799eb4820152211ed8d733662239b8f3963228be460ff75d32ab79f77aa91da2c0076ef9ceed4a835d5d71d8348fdde2a8c5a21074a53ed4be065554e361a39d04ed32b15e45218989d5d56dfccb021b1c7c9491285bcf98a3184646faee09ec856abc597d518427a87c2ec0aa91279f10502dcab5e3586b08bb2903c2d6366d9217971176521719044cea08f08d741c9ead674b1aeeff1db7a732ef4902ba0a044057b7d215790f611bfbea9015a0242b62ef14de6ae13e358d8220658fd852166df0a5d19bcab8f975ecf9f1a4190a1e260a2bf5b82eb777038d1a185cc100537c649079d0c4f1cbcbdb82c7c195cb9c0edf0d3e1cc424b11a7c6d4157e42e5a4cc32ba8e92485eace942d251f53c91bc38b33de419b94a61aca01285e445163664bb36c582cc90bcf8a2876c59774bc1624242f222cc0eb2fdfd58de125f8e4b49149217db22c8d6bb58df8480f9d49c3c902bc8435548ee43903036865c415009921b71e6001761b6ea542861768716634a646b74b1be7949bd9eea53f244663826232fa931ad8187ac6166809a71659eba8c0c0c2ed6370448cab547328d8b91d8f7340021a8267ac4984b2257003c1b42ea78410076fb2987b36512d91e5d991944a6feee8f818b41a9779d833cb28a71aab5d6e9fbc1d0c8e6232641fa63e27a93cecf39bf198ad537331aba271261f211ab9919d8213714c9f281fbd663dffed8969fba00714dea81be4ddd0f0402811adc28be007df6f9bbc517a00ffa8d64d1d9bb3e457aa06f62f0ae4cf09ce871820a32bd6bc223e9a987935b1732f5363840a06f5b230b90d5fe57dc3e074770e307c7144765bffa7711db68b0e592e178d225e5f4ac5da06209da911b932a2782451c5d937ab76853f4006f48bd0650baff695b524f0b28d024676a48100cf151914591bab144a649d69438a488d11921d32b393a92927cce6a0421dbccedd83617d7e27bfcab36fe8a5e9358bdea3dd06c91fbf5f8b7d6b99880125f1b3f387eee35ff38a835b0d1871f2fa9ecfebb7b166bb1c73369dac1c5506bad3108ecb377c11fdc7ccc427ccc43114503e00dd90b9907c0c7ec626308bc8106adbffe67aebfdf0fdcaf436010c05d45ddbedd5eafec0fe8dfe36f8d694eaed91e08737c71d4633aa30672cdf6db5883d4df740928dd2910f73bd57eb73a3822fd18d0376eaed97ec8c274a206cd3ba4bc84ce9b459b6e20a3f6695104c577f8b99a163568d16f5e989fb3cf2c51fa8b93375dea695af4d463a59fa61e0683c039fbb7ff14df9c6049b706858c098909327b22bec155cc7c9ec8284a319502993dc6370a8806cd152599c49ec8ec597c630266d19a143ca70e0f64ce416d1ec65a07db352023b1aef12087201f53bd37c6183bf5ec658eba703ccb1271ecbc12da9f9fb5b1c3891ef310f46f96ed9d65896c67bb678947622be7fcfb47591c36fa59cffab4e9b3d1bf89ecde29ce670190fc2c0bd04f7d9a020720b88739a41e07a9acf84825969234b97043db295ac2454a15424f50aad0a890597b58ca34352662d829d5a3c712a69426c8377d267d8d4484f1141f4260496b70744e1a1084891d123bb81452382a994cbe40e6d5f8d8638c86c6b4842485244a847cfdc7744a3d407445763a9a486c63021c32c8c0c0a0f0889006d037b82ded6ecfe90614a92f244e3bd156e40991125f091f203faece945544f690d8a7391fc0f91ef885808210e40f9ac6c7471f7b0fb0d1c7be639fcaad40c964120bfb17dbbbdb0ff387a0df9e987dd73e6af8db8307623a7f3b319804ffe2320ca4f8dbed6fff62393a0bfc8bf3f66458a53913fc9bea08fd6d34e3ef250afe4d9ba088fe4da9b64f95cdbf53a68b7f5327d8df15b64fa36d7f07f78e4a269345c837a5fb3bcd4bd2f87bebf418fd9b8586947fefa60c75c1bf992a1369b17306a3f16f2edb3e47c9805b2ed3fd9df3debcf7b7d749a4bf75cedf5ae7d53d35fed542db6ba4185d7ae96fdd04f577067bb7db09a6c1bfba0cfab7d7d11b7f0bb796fb3bf998b6d90d5babcb123f2384e53976110a7409b2d39c6756e49c73aee0d28529059ff6cb09f541c8df680810a71c8b3738d5d4fc8dec2fa7586780c283900c49facbf2230eff720b769583969cd31403591cf6afbe8048ecbfff8f0e9a1ad558fe41c8bf0311a8040dc6df0ef7d0655f38f1b7fcebfdbd60509ce11b33b1f3b7adebba41966030e8b6c05f905d555ef33b74007eecf597c1b8033ff0bf2040ffec5f4864a2fad5dfea9d62bc7556598838e786b87d10f2cf7e4290040b933925bf75d95f04e91511fc6cc45d980966e4c2feb682de5cfddd2f1d7eb129f3d35f560219c9a6e90765d62aff6d8af7d67be7546bdc5936defac5bfe1ad8f80ff0ff0b3f85b969711f0ffc1f1f361fa31fc0b3fcbfcacc138e33f56fe565ddd5cdcfff8db9f9b8b361f6fe8f07191dfb66e2ecefcd66d81c01fbbba2ae7dc6d61c15b6faafdd20721b37c6c7ca9f92c5659b6f04dff8c8e85980b605e2e547099215290e94263d16348310dcbcb0168b2f11dc12f91d39636e090970bb607b8d7fbc74babb7174cca54fcf7f8cc693be47535ddc5ed99b2ea57555d55954db9067eef09c20f35fede4c7b0539ef26298ce8ae520e3f4d27a06fb6d1461f3db1ab2ccbfbb681423ffb6d50f434e7654e4ef8411c8dc2c0cb514f932618fe344db7cf46af895d6b9f72a87992e6d4488b673af89973ce7ff6af0be71cd7e41bad8d1edc68ffe26c4fec2ccbaebdab4422f77e1f8f78cf0317ab9e46a55963b5420c8275530c82e5479bcecf5bb6fd45f8d8eb2d3837c520f857ddfee57aeadb3558805f041442e1c79ea79e25480283087eb9ded246f835614800a67ea842876a30f56eea23a418c4faf19b15918eaebb2048e69038d8008c27057502c7d363b90489fbda7bdb79effd87d30c5485db2cc34e7fb7db161c0677fdd5500cf0faab819a403078d2df0d6d5ec5e0534d821f6f89596540d15f2cd75cca60a3bf5bd93c6ad15fad1462c24a7f798a268ca2081f2f9b28aa60cff251c959f36e74277decdb8bfeeabdcf5cd3d9ce1aeac74b2674afb14e09cd171958e981019854fa89b9f407f0f192cbedbf4820014eb49c27766aa5aa1ab9b3d58085918ad8d6df6d618ee5aebf6c06b822517f3771aebfecc74776c518ab18638c31d619638c719a3d5b3b0210d8bfa37eea5b0d74fabb53e3547ff7c720145fb01fc10b369260f9d8afbffd20b0ff8584fed888dd6f41ae3b002337926b1628fd657786b7fe6e0e827af6fa261be59a6ca4a3fdb1457f5d239c937f1b65547496070b90ff7aa52ff9b39128a7f2755df79aae352caf0a7efe396a9f68d5d234e56a4a33ce384d35f62f5adfa45c33fba7de00543ff5387d2ef5acd164329944eac04b1b62fff5b0647e0ca67331023b6ac508ec443fa436820548af609c66af7fee92c9d1dfb6938fb7dec7dbcac75edf74a8bbe48f2076466498ef4eea47d18f281d71298822113a8b6212a995301acbb2b29b2ba2e3844cdd3a60dfee125a543e57ce1b575d6d2282aa7ef8403d71f83051597295fd385908b97441213b6bdbc3bb824cbdd6421f0319a1a0f988bd0b507f37d8c77e26a9cb40e91d90f4772b3ff6c29cfe6ae5c75e835c7f798a8fbd87b7fe6eaa8f7d06293dea63bf9bdafabb8d3ef6febffd7b7d83f7e084c4b9452da5b140a6fea86f42a8533225ebab2c4d0959626789f2e7c69a8b2b360b00b9b165649582eb0532f51694f477037dec35cc75ec65eafabb733ece79a8ecdafb994ef440e7a22eeabd7cc4792789665dc6adbf9aee635505b085eb0364871a112454666c35f654a9ce9554a1ee52dda595b9b81bfb69d241939e92cabd3d1a6a1d0b208ece2eb146a054b0be4e0177949d957395fa6af71362db7e4c4531829092fd27c4c275f7c8cc49dde93f29608ece6601933ae7e250facff9f6abeb1b8833e95c49d5a104faf8215991d8a675a7a5a13ab567eddaeab4fe00c698fa1d01f27062d77ecebe42ad4bfa3ab5ea7496690398d6237cbcc432fb4df9b56895542220d5d24be957c483871b7c2362c5045089ab070f1d74a25f3f5e7aed78dae52e81dd1cabbafd6f57d7f78399df81d1c38facaa0a30abf39ff54b88e9e3c88a139814968f2c57860f2ef5c987332bee848f3c1c7d03f1bddeca688d3a57628574976a05a26c7fc25c145650aed6db8f97567a6c544ad8acfe4bb6f50a3bc0283d68c3adb3516bd8d56f46e74aa1ce36815a7d0d637ffa5ab622e96adaead57f4a78aea0a8517aff787945a56d7696c5cad3d9a5150b0baafdd1d7a9df92ca4a5dd1593936acaf1f2fb1ec5aa9fefb78892505a8a3efe40f4767ffdb5b2afdf75fac647774f5e3e50f18ffed9f55f9d61f8c342e965d7cff3d7ee098b2cdc7f9245ecd47f147a07ec9cbb2abebf7c29e3fd733f15256216deb7abaa1470bbade8e8ec5f5635be8fa28b4bbdead0d6470604f1aa95053cb5bfeba62326d55b5f055555555762b8598c879ba4a2372e2e24a8ea5233c24cf153e655f1d73c223c29ecd31b709b6d4f388202892b687b3e922d9b6aa95d6227e9e4ca1a490450ff1da11e492953f162e7e4a751dfaeb1ad5b597f35527a91222de6b9a0d51ebb1c4c6095cb60364c59415a4675d9218560f9e1c2a253c787c7c0da564930a0d233cda30af918418239251450b8fcbf973922494dcc1c3680b8cc4909caa925d690b7e74cc886a7a2b92e25382e22b8fac876f2fc78aafea2f4c62f9cc31c683e8ed6e6c0a5757934eb8c7ae40f9188a1aadd0445c9a634cca829a46564af8d041778346598c2a492467ee25837ac8504fc9247888ea6a386f40796d6d3931825326b19155e5cad9b48690223705698a532ba5341c3123a9aa6a8acd5c55c522904411bf0a1b7f5d7df7d2572c9af2afccb8236f483f5288a879691075a5141d02c3cb62a2a56061a65d65e862c2e0b1eb5aba7ac539fb39e79c8b50b1e7b21bada719e5042487847c89ff4452d5d1f13994831f764bbc1c4796d468b65055555555d589c46ece1cd2f40680165d3a38e79c73ce7908194e97e503c239e751fae4104786ac381f6e1fce394fa1e3b22a9c5a058f11ef31b222cae7dee59c0f87c3fd83e1852f07900e95d692a0b6383a232e3c2b396c435a290b9aba5a78354531d98b3bca18a231a5b4d493e39363f5f97175555555555555114aa2ece69ae1e4e9abdeed790da94d00337097978ee657b355cf4e459f216b0ce8af2eb992a0ba226a25f99c37935a9f73dff39bd5eeb2ca6ac96e7d5dd7352ad760e494ab5c83ffcb762b438055e4dcbc8c997c57d86595156b8a82f3486596374de268006183eaac81e0450fa0b13214534cae1f99e55f99cba5bfae5f51ecf814aacff9ce1a4388e305454721e76062e1560100414d1637d2bcd29804c0a90f8fca468c154026fcfcd5bb5b3c4c1138e79c730cd4889166250c2c4c6b03a72c1e153e685e5fc89ea0600f8d16ad446b39e7bcf905c49eb59c7d4ba2e333b60605fd7a52327d9e9c3ca1d4d85c3e4012be16c2133681ac2ebfbc4909b5cdf0d1f32a8183a9432fab8e0d2a88abc7aee591026ad109470c3da35b3b537850986ae8205f6291dd57d5222a5f2d56f57d2d1541029484d44170082bb908f888d2f10971f2e502f912bfd69a569b85cfd7849edc9c4f2c21231ac8052a2aae8a7c15f938510157d199dd93b1233a905c3dfa5c9d85471c191af6755dd7755d4b31e7c6c664c9c98c11594d781481564187348f20f5e6734ff8834b858ee61aa2e166b5ce91b4882b251794ca3a4588908985f4390f72ce57960b3fe79cf311543abfdf5a6497624b954bea08e79cb39d757b92260cb7cf391ffaddc3fed6097f5dd7750d51d5c4395bc43c3e96885e3083902ff107116309a2c6723169d38b4665fd406a7d83c9cf5a0f0ebd173c902f310a5d320a5f16989c9025a190a9962bb5073121412868a539d0d556b537b4f343a985138a243eccce52e40809922014b4d20203a102cecad1dd971e5e0917615128526cd1274c419c44087265820ff68e056bef868a3c262234b439235f2f54e080c252a2975676acba6ae5d94bbeb220168ea825b135253423a0bab3a58d3126cca5be255996cac5c2ab6b2abf9ddcdda5b1154941ba3253a737e3ac89ab68acd9f3424c4f4169585e31c16aa9a3d70ed357ed7252533a5634c5270849919c0847509aaacc50265bf4384a45404199507d2d53c78e8e8a1b6107c4acf2f3d5267346cfd1b7259859cb619941f267dfa61e5c76d2ac370002015e7d9d8109bd35d0d03b91e8fdf168638383c37a08b27907e19210c9c38fd1c11b32a071d5c605aaae1cc09cced5c373cd1f32f8d8973db313fbdb6054fa01357429609bc1a5aecd1f308099612ba0708335598dcd470cbc822c478ec10b16210d9d9c5ccb052d61c79039c4f5960baaf1d9126186edc0c3cc0cccf0d73b91e8fdf168638383b36d8c224890112af3114cc2d058a5f835b4a0e8c63f8b37bcc8b06082172af10623132858184af82cde50934721062b3bb0f170d43003e3c644f58d360a951efecb6af82f3bf35f16e6bfecf0bfacfb5f560b63a25a1813d5c298a816c644b530266a63f3f30641882e1780f5142e1560d4a050a152d770b052e1e5c52d1aed5fa84c396cb0e4a5c2c77e2b7b5883b94078f5d97c6cbb2086481ce219bc618394180addb5b1b14f85745fb4c0c3e4e3062445e3b06583d2887d8598688c5b162af58d3676ed5f0b463ffbd782d0cf167a54ff5ac8f939c6bf31793fc7d0099d2c2b540a9542256785ca97152a5f9cff0a95acae71512283f387081f7b3528d4822f54ce68cd5c68c9c7a70b9d3dcee01b16ebe21906617789430f739cb1d1e0a1039605d2530e58c062b6501913152a6784ca9ff3070e8e34182eccd0c8188b9ec6024d0c0d0dcd0534343034341368541a0b86126822b474210d4bd0a561571abe696858bc217b9a20fe38c862103883649a3f00b52e2c760627de3c68b965486b73411be2a188f3c968a34f0dc0c5ae830a3938cecd010642c70b426838c85d301699b139c2b041186b2c82c5bc0ced0b3890b130357abbc2065a2e5d0591431f850dda580b3cb00ddd7aea256cd8738b4bbbe55c1f53af8dd9983d0ef968ca3a345ad5da10584e9ce492203d494b50a20811538594ad2d39573c6b7a6c616cba6f5dd7755df594ba06b31b376310116a362faac90cbc2e27998da4b6271e54583672f0924d3c167fb5a2b73434ca51be7833ca5b10ef070645c91c6e4a36a4d5ba21d1cc993566371b95f64eec4322e744f5d9d2442e4719b122bc9c1e500ee92cb574b08010d9012472f583af2aa9e307c78e94aec2b99044da15129fe65ac63361148f5647e936c51a23eba8be32a12939e79c7b71ce3906241617f28b0b802a68e077e4b4cb5795428153ea523ad519e9d9925992e2fb7962f2a449f3d1c0f024774188c98b49c857e51c60a72407457464a52fc31b19d4d294269f1395a3f5a84918e20e4965459848aebf169330a1a3769900fa6aabaaaaaa8eb062c76e5555d5561c31eb510666a5fcbaab9b32b28516036e6bcadb0eb9e2109f996ab906bbd1fd4830f388bea5eb9ddff317c147a975b04910331532964cdd95a8f2993284c9d68c2515abf7d6755db78442d6301fba75dd54a99d9be4a77f743366b06956c45d57b424a111b9156a0763421d7659f9d14ba56875d947f753d323960c31c0079228a3a2a11d566a06585cd591f1e89194a3a53c81847832fbb0ebfca47efe2ae684ca6a3fcf7770a0e46226df089e456df0a2a3c1236585d21021695c4894a5c885d65752db1226407414eeda907811a5b560a4507012bc8eae2ca4772e3f4efd0b8a8a0892eb2774ac423f5bcb2899d6755d63ece91acc027f1540f2646c4d2bc60e2b1b08c264c95c185a5edc0d21d58c5e84bc1b55a8f4709ca81353a263a4026d48df1eb4452bab256f840a1745a07665307040493a5740b102857536f78bd21a6f35abc039e77a8b734e5c9f0ce51a8cf4a4a913b5d4a2d035a1b1e24a4e9c06aad47eb49892452cf45d920e61638808468b9efa82ba2d77185901079d6ad2493d7774884e008fa21a0ad152d02f55855d2b0f904ea6aaaaaa467f3f16362b39224ba743e77e7aebd0ee00492ca21cac2234641cc08a330c480aaea792a88e8bbf6abbcea13689264fee0ec958bb9c446118f668556f31a9467b739f73ce39e7219e20fd7e6a5d8bb44b1679d188cba1b4421504f912bf5af6d724123b1e70625d65c83a352bf75adbd2900acb27bdf3356489e47e4774c11954d8a191bb534582dee2d941b175cbef26137e552c1bf3ec4eb6c2cd820fa70dc4ea274c47af242f995ca35555b5695dd775ddee66dd2969694b533774ec9031f5465454c3a70c4a3b39ca3b4a167c411aab6e9ec8fba551cdbb1fba870f0ee116e57048c0ac3d34caaedafa33528b49e79a2ca8ea63432ddac674f2fad292cc8006d9d0ad552a8a17909113cf3c253aad6c9a58fe38e711deb20836e8baaeeb5af64d409901d1e36164eec7f53472050a2a055da6d22497d08152650a89cfd29914852a623f4f369660cb287433a36a314c68e0353bb5c5534e18d56c016da36c3c3726d175d5a50c767585b5e8b9b4078d0d78ae5af0883e25e72d1d98817579c56863526a3732aa2044694355b4dc2a46e61a896a9b5c96888d1e329e7cae98a0827c899fab458c15779f7bd7c934c4b682a7e9461cdf493134fa49434093ab05205c534878910512668134ec3555c08e98181224ce0af225fe3bde6421c753438f2d67c86c091c1d930cbb2a9e24455ea44559477a7c62e84c81295151f444d06feb2a952fc068d2a9881aca8dd71f52544a43d9124f4ea6b0a51c3c33921c4063aac80e8ed9c64246f2c794b103e3c64492fba92272aeb8cee22c51214c20ad3472189928c2c4bb71a285f0c4515491b32a2baec85b0cdd66021ae1869c067a0926d12339e7b254f657bff52fafeb5aa53ec9017f57cc9d1b3d6b1e50fab09a5cb4704271a00d8d4d2809f484a9e3f3d389a1a4074ed5c96189cac261f34f4caaaaaa3c3b538e4ca0b0cbe103f729d17252b239b7aaa235ba94c35ec249c76a0998912410d195ce24f2534287d511ac1e41ceb7156c48cfa825689126460f484bdb1b7bce4d9960aab15d6b9948a80f8f2e08b46a860a5ef8480b7ad1e42468089a508e42120a4cc5e9c1d5f0da49f204e36a4ccfca8d3a3eb51c620a2b254bef6b68d446799ec4817326e3685a8138541e50555535441fbb79ebe502c593ab98a7270b2d26fc8a00fd70b88e8435c3645c794282a82448663479d4fa984da6d993d5696c67dd7ea6a36b301faeab50c310664884c9c70d4d723e8449bec4786a8dc3451285dd13d8724995c4886965e588099cdc5aa5860548f41b7001508ce4780a515a3d594a325376f53cb15a8611b156a22cdabaa5e6b4e40ee088d2978625e3ccaa04d0195971369c9a74ccb827130ec85fa1ebbaaeee1913352df183ae07c555901d38a910e0008a33e265a4f404c9741a02c452e2ea33a91440aaaaaaaa17dc006cd090e961a28fabe9a96345280a05a6ba68482df17a426126a28993ab2d2eab7457744a358ab38d4bbd6ef0f9d42c15117d72ce5b968c2d79229bab73022d11c447550b2a4a446e43f4913d44a8aaaa1a426988ca57552e9d265f557559700d8ab1380312a1808263c9cb0595285328ae10617b63a103b9ae6b27fbe0a5e4a32637a5cf24073ef2a09c6e705154205fe25ff1038271058656d0d6d99214521b31a1dcfafaf12605047481246f506761513f448a4cf56611ae1b5da48f6baf62ed1131f68c3ef79b7331bf7952b1ad1d78673df0f87e6ca802f684892f965da8846c776639aa0cb248200020800083170000280c0c88235118a6599ad91e14800e43a85260542610c96381401486310c02311000010000200040210cc3801c8a74ee099c04023e740ba02d7477029d8106b027b3d2c49c1a08ef0c828d294f402640101423ce81da13b2e24dd0f7ac279f7660aeb7cc62cf4c1769484e3f435b0317489b959c4f3a65ac74feca770db9ec1e40de4e1e7c8ba1e05148dec5263105e540600e8316ffdbec659f3c04cc4b4184c3687e1b9100646f638608dffc4ac0e98196bc21c97ca1c8035de0907dcfcdf0ce192e3f0e439324e7f1ec54bfe88e76b5c4e99cb850793cb6ac3c719d9f48d0c78b405a4a56ca4d772927ca75f26a8ce2455ef3e2edf74591c87a19f05902ff5404be8cb991c51b5d281644e9f86769b1599123d504ba3daf8b3a153fb37763f60cba5a0a24cdebd29890040af1571a92737404b3a36eac8ef82921e49c4ef4df427004c48d643b5af78680de0e68f7008a0e0052a3029b7688c9258422c6392238bdfa8c4e9091dbb938600c10a647b40695a011e0bd9431b8e967cd7c0a256583583b37576d08ed9203e316c929784b213ae0d528382400b9970035576535095fd01caf711fd8403610288ab5994f5591de604a9dd8ef491892b83bf31964c91302ef064ef0d4269fe954e4903f27f8e3f070369223803ab40ff5429e156b953d2fce96b85c1352d2b1d550cf1b4a4398d29a60413f1593f5ba2febd8dfc8badbc517df90adc3f5a0c6dbb448f1d3d50ce15c41db4a15f11e38115e5534b636e93b211aedec2fd83030a153cf2f7fa9273bdc97118142074252115828fc65c5287e1d2bf97105ccf2e23667dbd23b9067913b89314dd35a77b2074cd38c57ec99f183a17d4d75ffb9436a4b3aea963a478a3b32bd08da87c66422c75ddc24331e38170232ba4c9a09e028e4e93063e033cb095b64742901131771798eb7ce16f25d7b57389b54428b1981e0b516787854f284357e4b0351609b34d0717f84a3a1e22a393308cfbec2d337f032095c3c9a99ddaca693bbb3c8295e127af5dfeefc43cca13a6ca28628a50ee5b20da45fe90a1020d8670bd750782d46a08135e98e3851863f898bf16d1ed7afdfb0b2b27126a5dc4dbe9c75a6704b449df76918cbce615fec354b342f9480cd10fd108c21be0f3df42f7d49069bc594e2ddc66ce37538539ec783af3f6543627683154fb445041cc03b987525eb7885539696e6e8306f0593c5e262d98d465d0576639617518225d34406d1d29624528ee3f99388592c58e1042035a0c4390c5f1c49ce04395f5612511d0271d6167fd7f92ff1c6cd4445705264a38c7bfb13eb58a79fc455a5cca6ab3ef207821f9014b58ee3e39716e76c4342b86e956a1dc3165e54dd5e982628bf6ed4859d579ee387032255588717465a0757dd46769e959415c0e9c9aa3350b06ea1c70a63a021e0f4a47a22319cda3b0505884e4b2a763846bd0c429be5199ff92bc0d5a78be9c9b599fe045897e6e53a145d65e989418c3378be13ddf909c3b40a40c041f80b79a53d32f2c8137b98bd4e48b3dd74004a086b6c7432e8d04d6e2a885f2fad0b02a070a680b8abf52d9daee51dacd9bc6970fb1719a2df53d7b4437970e65c95253afeb82e568ce7b1e761ff4fe4bd3b7a5f14e58c629ab3a22479a0714d05904101489eba24a0398d116c8a6d7bf7de68931014a42038c804114aa97ac3840edd9ea3448a389ef29bbadbe0d6895e3ad7c982838eac638620f8cdf41bec9ba2e2668c0ef72022ca1da33914fb5817eb8780794e3b069bdd289f10370fd63b90c38ad752ee6e1cda39b4b39320cbc5fd7e8636b3c292ed435dba68ca0567727701251d33f2bfeadc843737a7b1b339b7d75f58729297099a334b3697f41762dd3816ae5cc817affab829c6df686394fa6fe7fee0fc085d9828f8ce9dd0560c0cfeeb4ce0a7dca1919016b4a6178829b8f3d7658b1d3c33832b07fe001f5e147ff2441ff9f79ef53140b1c2c039d9fe091c33809c4d962481a2253c1b00f2f32b8d94130852c4aaa1156a2c93d21ffc6e5e3c77df90688d75ec2f320331f0b044b65c9901d419c7c7f73baafa180d6fbf9225c2a506e6a230919a5be9576e809afc03adc15d833976c70b713c21f51ddaaa659c53df6d842a84855ae61f2c7038937557cdc49f83cecea08ae288d0cae750a00c22832f7be3974b971c4814f570ea006f370227dc550d60d2ed35c4b8bf361b1f9411a53696ab70b7449f13721e2bbd3fe5f0f66caf628dfd28d1103be3e227608c7f378c2b0da0e66f8b5d8e8543bd31aac3f34c20eb6c6283644f9cc64a97392b5aaf77146882811c6944c8f1bc98d96108ce719a551236a24f30d7c8aec3dc6d503ccf322fff67a64d86432995c15e6ed6c8031b59a1d689ac9a0416cd1d51274a2742de84428e6465880fc3d0c91fe79157b7ba54f99c852adffd15ac30d08a4fbd98b3cfe4c57d5e43ddc8b00fbf1d1fd3ba13b3065e55d948da094018f2a509e9b68b86eddbe206940b4a93d96cb005913882491ea0c69510b78332e8d44fb304e3c7fd7686d340a1fcdf0c145fc4c0cea3f3239a660ab8405c83506bf5637bbcf7ea80cef058968c6ca4cea422f2a3df95e2b76c546e120a1b95f67a28c9ec3a4d0afd363ae28b86451d3a13383407ac0c647b48f4a855c3b53e3f8607e9614ca87288cc78a9ee4406b0e47f5bd05864fc33d94279221a753ca209d000f8d924d40b67f02346540c821631a1b9ec38f654bb35594ab0339bcf2a77508be235ec77a6eacd25629b36c94c377417b46530973d362f47b9ef6303c5a91430442c52fc6fc533fb52479a7c1ecbabbc334bee909b4ff901463c794bf4f689d1374424cf0562de6cb05994c655ce41117a519461a26050f24cc40596118d35e94fe12e81cba4afa000d8bfa26aeb8b07792b8ae14278294121c742809930969aac872aa977b2aa2092d4861e737a20cffd5a6338e79db4a949ea615cd4292c3226e9b4ffa8c086d2df4d4c43892c6826baa890c697fab37a0ed853e45bbcbd046bf94546b1f906a40eb3a8b5bf1f9453ac0fab3799d39c7c830859e7361fef2cc0e678b6c6b94a9ae50b67ae59695f0517ac55b60a2e5f1662a58603b0cb23fdb06df44dfde859e6b7556aef7732d2cece5ea31e0941409afc2509005774fcbbe08ad888c89c50fab922566651e4ab2b07664b7bfb1f057cba0049b419b6b4ea8e7cafebb8943393de443685924cc72425389a7e6a86bf5af3727521f8465c0c5d065ac4694a5ca1fc4dc06d999d1d14a72c97faa5e353ced3a00eafc7cd40be28e4cb2bd600c38a7568280a811b4ffade3d6c87dac54d9e7144c080e01e4dc3a066cc368052b1423be208bffe3bc701a12338eef7dc496f051f8a90aa413e1121d26f81165b62e8ab066bc8260d9ce5aa9938c190dae2c2f9f31d70665a20c60dfb41bb85254360f84a09d20f3f1c2e86fa34bf46c30c2c9b8d1bea8df76ec37744e9c230382988b6207e8962f22bbd84d25cf898017c51620c97c516f225cb54d0a13b9c610b70ec101747d5907546d9a2a2f46a12d8b411c77e43cc8c162540cfe91a6397b68fab1116b7c7c173314c3cd8af051fe6d5f1f3e0cb2cb6b91f4730417df311013a600646b35b322210d3f7e262ff9b635dfc587bf7ea17c839f66cd05164a2ea3bbf1c809ad3000c63fb3bc35b8ae4310372f18e07d05d4deef8c807fc59408635cc6322b2b911f72a76d4574968c20f5ac3e2729150e889739435497dfe004e5282a1344bbd0e47119fb671200b6ee08978ae7c0b1e3a0ef728d383f6a441ad5a64b3adfe60e22639defd82a8e6c57d87ff16429eddcce5fb0b4c263d179c4728166bf83ce7244e23a76a28c2bd98cb1bde56c001c5bc4ac32f3065ee1364f6511b69f0fd7d7982e0fd69139ac429d46b1a86fed3bdf6c403de2c41674656e9b8f694e77d92a503cc86c36f5bd9298bbff1c08a9ff49801643449a8f27dc87879fa96298f4556568463621aa1e829e7968e1417552f5f79e0bbc191480eb1ed1126ab5209b56b7c2f8a3de6e5c5938c7584a0f35477a1ed498d38bc377d20211d159209d861fc971a63c5f53342ce81eef79462ccdd12d802cd956cd1df881ef86493a82776585b8ea160a68e94171f79c13898fd843aa48c73ed4448e285a30e67866982c7fd2cc6e2130d2ae12dac7b1282c06f538bae2553ef4c4844dad9bc73f2374cb6e876c191804aec326e7f487ce59e9d90ac00b8cea24945dd05a83a89eb66ff25ceb483ea340db81d988337c45ff0206480d95b2e1c79d9d533acbcd0cac6073490f6373b5b5dba6406da5f4e04bd41fb10106a2f81973ff4b2a0bf4f9639e1c72ea02cde605bc5ef5fd7f6355b5aac77bfd7b4f7b6c2d3a443bd5c99d88b04e2a23d5cfaea32fda8ea7cd54ce4ce32d95f010ccb47fbc0dfbcdf51ece489d1214d767a2251c481f0f1955263b44032be5448b1dda3d70a923762a64422b54d2ddd3004aec9986cdb28697ebf0a7c504e692eff9792932a30b9f319e4f413a98d508f233e55c93d7d1179aa91081098a41e66c4da0cfd878516b1ade6cf41641eb4e75d0c3f3147153376180081588ccc7bb11b44e7f0b9ff99de76a9ab2d7211fde321a7c6d332165334d3c83f8d8876c63e7aac7e71ea299ad58a3569cdc31b72f0a30abe2ed31a5997b5b4369bac38d18823e0f121d91bfb1fb1d5c4a05c377971f333e207c6475bcc22ed2609435df72303e9a323c97d5683883bf4caddb32105afb2d111459dc602ad2e26e32e3269bd8cc01b2a33c972da6d14f497e303859c4e9775bf9e07f20da772f449fd8080cd1e4b1c87a416eba517d01beb062b0c8c02d35124724525f0774acb3e0086079fd922afee1ec3355187725d4ae9122506dcb8efe4cae810fe1d9015f1e26101fefda08c9d9cea1dce89f87349eef6a92841ecdc5d6054a7522a24d667ef96ddaafdad2461e39e9326c912ce6fd35198fee79e30e97efd4ceb455409b135bd0934e173a056ebc8515a623d8b149819758725c2e5e474fffcba471737f1c616d0f4be1d4c6fce5f4405cd4bb327bf9073282b0f515156c050eb81a43f59318e98aa3a9d13b681d4742e7f0e3dfdaaff0e8262c731b4ef3daaa34342d45c83d2cd4478a11315538cbecbf01dcb2348a69941f5a76597164efbdfcfbb7188d7c1a01e60ce453258918b2419ed295ec09c0dc8886d00c9057651c284314e26beb8dfadad2e15b5973b9b4a97f6866fdc6fb46930cd3c82cd6403429ce9758d12d2ebf780ab872a0e3f86fe49d3f26c7a21dbb17b2b8b5b6575d09538d33fa146a93faf3bfcabae8d6304bf67d23fbc3cf6ed2fa0ccd826be035e352b3e71241290e6f2e894b8519cabb38e35c2f110a2f2e3f5647c62c476bb78f935034751cf6e96acea5e2e6d914482bf6c7c27d66e3c7c0cb527edb8d476280ec1725fbca6187339104240a535901e0b7a5e95b2fd901923ceb19cb7e381b43aefcebfe0c3add476a00aebcc447b1b84ace25321d85f688e0ff50dd6b40dc2fa77ff281ecf52cb35735204a643a970e2babb69c19e0ea92a4b0427660ec632e46d3a24515cbfa87784b69b846f4e0be4ebbc11c9b3e49bc99a4e8b94ee48e859817797c695e82cde551c3901789a1b6c0cead10621c73ad2869d9568710ab109856113ac2e74b63a00cb1c31bb6614c52ba9652876c98a6e60385bb1cb5e4663477093a6c5e6777d9631a5381c6a9da5f528566277dd3a2f1d40402cadd2f7444d87047477a6ddf8a37034914f7899c832e861383813ab7053caa06bdeeed2873e7a5ae87d1625bc0f49eb24ebb6e776eb3c07f3196ea4f1495163a3bd702716e87bad465fa02477ce4000e92f16343ab18402daf8dbda70ad1aeafc05bc185b8af7089fa4e04e296ab93000acef50e6c52c2a25af13b5aa2414a9c8da4e5da0346825ef9dfc24b15fd6f9da04dfbab52daca8f681d0730df784d6b3ed0eb3b281626c966a8d9ca09667dfb5dd172bea0fd872fde9131d896277e24e81728d2c551e328c99728038bee1400af2114b9eef0134cd67a081b3c81295c763b5a87069db37cefa83893c86a4eced2c8b3b464351828e1562f5cd19f26f9099c7bacb415fc4245260abd7a83758a37208e305d20b6baabae7b1bfdd3d918db915185cc066f68ef3f037d790c61f2716487637f8e1bc465b7bdef133c191dbe6cfad55da8d0467e4268ddb5775a5015ba65556b6d2a03a7b1366f52da5a4ecdecfd7e11c5ea72a4f4c1c69359bb25bd0f2efc97bb4f77c87189bde59697965c62567f726d68b3bfca034abbeaf2f544e36f8051c41a1509e0c8ae69bcd01410266065b36a4b1462324b976a170010351175351cae0438877ce207e518b96d752c5d9aa81c20114b232a642c804653a9b14149574dd5742c5e2631fb987334404fa842044ac91130ce12dbd39377311e2964f32798d44155188c2720d480107643d7c0f41055008d228fc149426b8a4fbc414825c4cced3799c49c036b136236f9c67ad8cfbab537c4528b236ddabf457e54698cc81208f4ea0aeba1a4af172e0ed918c98ac045be0cd7cc2a1058b65c782ac117ab63db596e400948ce63f604ed2667805430fc00b5877a0f671ab3ad98149e2af8c8e173a31eebb7d7248a24e1895f0f689e8bd04a959e0ff11b0355c0460a6ede5b344f98d0610cb44a89ac1dbfa02aad4486fb371d2926b84d99afeee58f0a5e36ee104ec1374c0056e0f5709408dad78a613f336158e54c0685b875d8caefdf9e2409eb49dd742c7047402e5d74b2152be20007b9a80489fd2370306214825ce6b96c0127cb744eb7184dea121091de869c35f2f2600eacdaf20af049ef5cb7ae1f4b467023b9cdefb520b09fae1bd1009df78a272ca58ca6419303a803806650c57a79a998ee9cd50d6820bfa3047cc8c83b77414fcd865a8f2782c94ceb6d6c68f5449e4835f9ea7450221dd03263bdd266dd7b76362e0ebb0e8c894a89fe82eb259ba0bbbd0fce9fd8b3817353f938a9bcbf4b3f22bb3b64a4d7fe18d63ab9e41f20a0449d5441545a623c6f093222de8d455c60b70e39de811e9e90ba0b9e00b385abbd6b1ee597208d0eeb94b44c1061eceb528260ece507d41ebe087f08ec8a935ac443651bfef5deab2044d09f9bf74de4ca273abd7149198550fbbe5563ce471fc86fb7c13ebfc08e30ec454915aa777bb27907786ec86300316febc93fa07c86e64f21a78042cdcb2941bd85af3df1cc9d4eb0daef49f006347904925318621dc021a7f570d92abc99926db61cd434d00186b888f1263fc1f84e693587063363210b37550e0db9b72af461822a2ba80daadff3525148afeb5f1d1ae30c6b710ce90603284ad4433d65c47fe469431461a838dda6197688beda6155231bebc8d08b7f38d334dbb14ec44364142c54e06697680efefc177c12af44e6c775af32c200e68e0cfa14b0871e7ad7a121f45041e8fa63a198550175ada68521a640cbfe6cc0d1f5940ba262dca7ba188806705b9d9eded26905f1f62053b24a9b2b50d3c2f910806f9b2380c5d70a2c99b5a2c1a41805f788f9499f6c9412b88e9be32eb0ed0aa22e8080bdb45945ca22c5369b36a0acfd64cf33f4c2e54ea4a5dde32c5b9cdb3f2fe9a3f6f3b04be7587670ec6bed52740a15943c885b9cd2701db582af88560a7853861615221108793d878315fd49d00c47afbebc453807a316e5aff08417f3ba6141911fe323567036c37488296006d0ff943199c92e42fd7423845a6bffb80adf92a7856d490038e516e9c992933dd7fb80bdc4249725e40f16422fd38d4f9374adb927918166b21c74913eca3c74118e662160e8347da56b9fd6fe99dac63a96a0a01ae6a1e381a73bb124869710279ba323503676bcc1251e1e6703ec9e85c3635beb7bcdc045ee51c0e001181ae700d668647b6772ca0fc950bde1b962190cc935143a145fd755054bc1231edd493643126580b08a2fb2b781cdb8b9b954e31d1ce1c7ddf6c30b665a4685f187f814055395df50122db27e4ecc482f40bf1a58f5a8d5cdcbaca3be12b637b71e41037ad6a6ca7edbfca626d742e8891ad6d1c3c2c7e9a2c98349921753e78288e20def0576a1888ffd59fc6c4e57364c43020bb373d0445fe14d9322e23a1de58080f9632ceb57d1e0beda4898317d5db2d6641dc9af10da1e78c2751ba5b51b0aa7ee1496dc41fa1a268a481980aa251bde11cd56fa14ff24ced58ddbe33e54674333b69a4b2e23c9db94018dd14a61d055c4b683c155337ee6fc380db507178b5febed59a05be00c3ffd0148b69e2d69d8c99dd9acdafa878c2cd000370d09efceefab9f075ede159485d3536658ada15ad3ad11ee57f01c96709ee02b26accd699faa321889d175a6741a58020bd8a9cb7a63ed6ae125965ffc97057efad0e551107f492356cb8ab212e7d3084b295525c3a8692ce943171eba2855e50b981e9cb30ce8ab22b072f62df474aff1a5b44e928fea3cfddbc292dc91a996867a23a6e3cff947668978535062b33701771aa87aca7bb1b6e7280b90822f361366ceae45c504d8d30e2198193b01f5ebea5abd19d7d79c4dfc1b7369fcb14f1ae05f5ac14b0cbb3d8dd5add0f506bf0bd0d60bde5ab470a871c717046500a45f4fc885017434a2c42708306e6b7d14e92af65a11e257da280bb41fd154793c903b392a3ce12a9853c02c3b5cad3019d32d71093197da5b6653bb7dba90d9e27f62ff4ff58c790dbe8f8e8e68c90b260c670a2bc01b19cab53f94a91f0556d832f5a7454c5cd5d1e401feece89ea046c5fc2b20865c1b6a32d9000a286db83bf8ca4a35189f2b3c2af2b31aa24fe5d71f3506817ee551475c9cabe668fde3e28e1c91d910ea08163a3276bf5591fe294f9a36206d8ed6a123378bf7228a79c05b1448b286856025f091183f41507208abaebac280e6edf828429a1fe7e5a889c1930481571678b82e15ba1554f71a25151591aa8a0578f06e732a7f20982598c06cfd2958252b9025174ac986cfaf35c193c74dc3ba523cd0e72a4d36def94af62d42da754996a823ebd6aa22bbf47927c2a6e60a98144eb23797c0073d9e9ea5ac1ddc2d0a2838b8912e82242e77450a8b79aba01394dc4126e948bc808aff7c07c081ff28bf821fd19a660db88e2ac754b755dece8cd67330c6e0a1d634f2445d3f4b078ad614d960796ea12ccbf8d752a89e9777bfbeaab41fade4fa759601712182c4d10a2a9031ea36a57ac146b2272cba79857ab8a0e032ef2c0d52a8633304ce5905dacdf0a18bfea83e781e6ee1a1328103aeaa2645dd8a4016283cb1227bc5fc958ea68a874e90089218de4db70f60931d8a2c46c79f5bf04d217a766cef59f59c29f8c3ec3527cc80c71a2ea7f2c133e297d5b440fce28d7fe66393f9e0611a32203e194a8cfb2b19c16fbc024e58f9b8971a26b36074ab85c1053b686756eda4cae85874b9df112160f640571cc8341fc96c3c501c9fb1c280ffb0fa3ec36286916aedf61b3dae4b459a978e510127898157b3c86d209fa6d12f73c88ec06f07c8391c2f1879263d09c7ec6b2caec6f04edce1edd409e0dc594e730ac6776da81d4b054abc94b5beea8d751336caa5b636ab8e40d31176b2f2f85012efc47e20baeffca04c62decc2698e1dac14f3e0a58d7456e3d2db393efb2f6ae286c0bbe089cccbd0c7499d6a49345e7cdae5f466423a497c3c3d7212c68603d5213fd255be703fac3119d031f7bcb70eaa3278c7a3cec8e4cdff640d0a5212feb5d175a7aca6c3042e71ed4d0d219e6570a901226c1b0a3bc25de01886cfa482cf470879557fd06700c1f3d4e90b0f8984eea3d9127d6f9e7d5f783068d7108296329b04914a537eb6f428c8b599e19387f919c79f0f8e01661eed53fa799f75dc99bfe64d5908b689bb3daa03bdc5f1dab4b9baf80d0d22ede36b4be93e1e724d56cb0a185045484bd0a351d80e4e400c40195d287a5bc368b1eea1622f43836d4029f31ca23ce27567b4d82605da006220026456352a1304663036517514eff8d336a3530f25bd5a3a532ad61c32ba8639eaa93e6eaef8973ef3b20583c9dec9bbbe4cac2379095b36c79d55f964f7c1a2928e9982fb5dfd21d5ddc649e55d79323889609ce3ab9892269de9a0c922782c7b13d032f406202b124b2d0a1bd694169f1971725787a658713f1d5d0c4d52df66a5f0901af0603f49013c4b1cf69e4c8db9c06cfc0664b3bd01812d76f10a98f0c144525b11784c9cf9a0cd243606fbc68ef5f5a285da380460d8f4787bcd9cd82df8f539cc574356c4b1ebefda246e3425d58b29872ba4c9ba1a0b602c16d63a75cb84a88605a05f5cf3a9b21119596031a4e24bc7e33021295ba6c022222f31a0d48646c3cddf27be23a9c89c994d03021d0016372dd6998b260a636ba4ac6eb1ef2fd6329da4ddef69ab42c3c5de12f2a5a35c801dceaa38ac8a18065c49f7dafd29bc1e2d49441c54f4fc0258249c250eed3acee1958b8abeee64573738e96d0b7b69c2a7c0fcc89bb69538277c9ec76c7c723c7cf1c90075f3578a25e20bfc4c27593ce4687554189806accbfe8669dcaafa871072ac84d3918dfee84b878a79aef7ee9210c565d62ad48a0e4dafae0136abbdf4a48b083d82e9ab4245e1136eb026cc1e9e784dad0933340b75ee4579fe94432fd659107acae17337454e1488ef103defd2eb4ca4e6ff9d6165eba53d3c48415fe2c6a2d5d507fa53beded45dc65585a74ef4b6451a051d8cad7d865192064d289743083a224bff64702fcc323ad716257328b172861b9ec86e1eaa20f212e31def9be0e79757ed75609add853775890b62b3f89f8ac55a7b254462e26bd293b00549f7c5c4fb360cad29da9d2ba39b6bef041bcb224cb923638f7a9bcb0048225382bdda6d4fa8fd0238e6ba2a7561d273b12aa770d5b930c7e7ea549524bcc899af2aa243232df7608e712ff6ec7121645272618d67bf99ab7f26f2459e1e017fa96c46c4669ddbe6153e72d56d4f6a4bfa81b7b20954f9f1fcdfd588e5bc75ecd35c70398ddc5fa0352041d48dba7580d711fcc9024cd1d9db7a8dc997ab2a054fab250fbdc115bafb5f43a10beb16657dd69efec0d760a3dc82656bc361aaacbfb7c5325bd078eb09d7bacbbba8f472dff24999f73ef32d5f8f61b67ef0fd000bc525f38d22f2571a7780bb7c37d5781d65204a8757e9b6ec05f95aecc5abc9beaf948af45909a9a3858be4e5e67f198b995a03cce8163f55708856ffa4f64cb19f698d1adcd7b315831bc9ba17bd7a4ca5801b982e679b905026b4dda98fcf8f657a44e5fff7ad33b6a985d6c96a6f0c25aea32200ea1722eb116cda658a1f5a3e325b4fc65c08984b886f5d822d60b3bb17dfe97309842c97c6d5f388ee7f8c9b2768a997855c73bfc1b3f570447a9536339fd2ee17946e6bef6d430989a04125232a5ff3b7ffc648953122a1d64d7c0964263e26845c36080b7b8a5c8bc9ef1ed30b0d2992100e34530c690459381c67dd0504a2abded4c39703796568179fed1d35f8e1ec067a61a7f58ec0c69d172795fc2259fba7da4509503a0fc83b07f96c7b8b564b5d9505a152eef1ccb9f1e9ac56a4e2935306cdce0d0e18ea00fe86b952f5cf262111cf2412b5e430a27fc63722544f32147dfdc8b4c1144db3d82fe6abf7384bdd829599c3db011690420ea4d947b602593907a0761cb886c3f4b232790aaa274d18205f9a4a2ebe7ebea660715320a126d1a78244ec9c8b486b9d73209bd863fefa91ea32b85a9650ba3347ef040bedc277e6bc5a63fcea24df3d6c96fbe613da1ad6cf77765d162cda83a989820b18a39435ac11190a04fbf683294fe06fe7b450daa622d8180e67e7d7ee09f52d2754e2866f091488560b7b404eefa9b32da9f23b3e7d151b22a01832363623100f7d043f2a0ac418d84dc0a7cd450622ddca11f9bfba739309b1ca97c935badd37fa7c1de84ab752dcdda39a37cef2c8c9c625b1481ba7d5666526ffbaf08344cc43a26273b4a92bd1392af9bc42cd14efd58dc91d6cc6f5514dff15c5a2a93bbe59cd003a4bb0c267b8a11e1ed8561f16cf1f94057296f811501c6707e690afa07b61a3201210a7afcd0db04777338635c84679e262169563dc14bcfc4b7205731e98287b1d0053df4a54a1b94c3e5abc5adb881a61e8296aaed357feeab82a44ac596f521b06e8fb52425528672e08e9bd9cc1aa8f534106335b15687b853fc15cad6cfe6271379f952f41059773330e8b1884439ea519ea0323007bcde51d36b70b94c910f1705277d2acd16ec81cf3717d247d842a48929df91ddf3c925ec5fcd57555d0af1c22e787dffc7ff6f0235c4ec496e9d4c859d88911bf8c1322f5c29aa3ce851d3ad7d850437c16fd65747e2fed6285aa68519b9bd3d070e3dc48ebb4bbd11faf191bac8501789088f27541bb7958d004775f5f6e4b2f507082915b0812fb71a8342f5332daf767033a75d3e10a7c8939c77266757c8f22fb33903658e03833f5cd51fac21b51ba1429d32a4d1f1aaa9d28d54c3ad5b5172e06b150312d3a8efb5b228877a30f7f76a965f28f39ba8f1472a14c4d0b9a6fbd0bc4226c7f864da90e51ef1a285bb0de66b30bdee34e89021b905ab48d26590fa6fa532215779c5a45710596e9f09feae82796c505ecc3c30b6f8fdfbc73ee568c01d201a2a2384ac2a35fb32c5696f97ae08cbf5e77a0fa1a5dafab6950649990555e33159e25a5739ea086b324d39eec76f24ad4c6068c684feebc15e2791df19521b02cdd59408e59e8a35956d063a295bbb200c448d6371ec41777a80cda9874dd4c74e9dd01dda875a53789f78733852936c33f689be47692b805b8698241fea8c4d00abb14150a212a2b687a4c0ad46a8efc4880a54fbb8480a9f06dd6dbb01cefdabe1e508b1e3b898451225c49819cbce815c42451f83e503784e83d678ab777214661d26a279927acfc9988d2e18fd95d1aee8c573d417ae262a20f2327ca127968489ee581818e493f93903d7c7112af476c1d48f673359deb96288b0642d841f8ae88406b2a2e05b8de44733fe56125e26cdeb9550e2f5089b64a7be809032684304d85c6aa6bd0a19511cac79a0a5d96ce006c0c044f16dff59fc8e19f5cf559f0248d031c0b5e47a499a41fc8ce33b131b78500cb9358ba7b5de3af38955ec3cea2836887ed673732ac16f007d13568d9e9332e75b0913185a6f4ad48d0aa4814b60df013eae193509cd60fa783426785b4255e98d7e928cd8b41e189fd5f2c4bb8cc7b497ec286ebb8f7832274086bdeea8d66990ae9de9cee2b3e0769ff8762ff32796bc96b2fcd41a2f5a49068684fd530bb0a08b428b11c4e3addabdfd5b258a04bfe51eb2336a9f3030ae47714bcac26c20480d97915a705673c46de58ce8783a6a4c38510d6bab4957e434ec350ecc1763710e8be460351c4049bfe876e9a9408515f8347c8e39351f5575e00e13ed4f893925c65064fe260710066dc1bf020f74597a1e2de87648896db04bb969a5a9fcfbaa9b62cf8879bc56c9a30d96ba7950fc940ec9914260291eac414a0d5b8b5176a7ae2efaf7be17f065649ef6823c8a6cd5233515bb4c474d3ec4add7cd42c22870f5537a190a660328b13bd83f93ebc9f379b25c3f743a5cfd557930d45e03f8f426833a85c36cd5e2cd37dbab582d08b8b8f28648310b4b47c084128f4e2f30168b27485813f69798482ceb9e08c2a62511a88cecd8aeecc1b06115b2d1293d609319e511a99ec607fa256a2c9206114075d82b3f10a2ba4c0dbbb24c95a415e986c383b5a608f15494222a8550e5656fd36c2fdc69822469e154bc4a565d5c39a3f3868b89f0cda1172982e1784144651a7439ae32a3ba980def3d86d57452f112484a6c860cfc147de5d2932923792fc19bd464b0ae89021d9b8c9c1b95381e8d2f35c8ec5a53c82c60573f93f64cf51957f029f3d99ff94f7393a1225e482082ea1cfeef3aae9938a23ded96953eee4f3868c33f06ff8813c495158a6b5385c9999e06a9d391ca392bd20e1e88d689a634491a7151956064cd7cee4bf9ecefe6f8f5648ae7cec2278ae76ad6a1492fc222e0077412459d18d6533f9281970cc220b150ca0e6547ac85cdc133296c35e624d114a8f1f44d9ff47905e1164aa6fb54b2827dc9d40b18b84d0b4dd9a56cd6bd0f012f462a9f76e78f16a29840db216d268314088496a4f4890885423c88224d47cccfc7e43a7317a5b2abae7d603bdffe232fbfbfef23c24d6a9143203628537a75123e908011a53239e1942189434342882eaa8165e753cbfee86c63208d7eae1003a2ac323154dd735ac83391fe2aed361bfe591227ce8629cdf2b0722df0b00afe8df8ad7098e31438dd3e7b9a6169302a3e728b62273abb8d202d690f8cb2900d9e59f85588ed4294e1e32e98479f14138be9b61ded19e57ceca597e67735619dc0550e6fef43d2b9354f99ab88c0a6ff93daa29731247a9474b08ac7be663f74b7725fc352a7ed757e8c9d1f867fdc248aa3952eddc547318ed2d6449587ffadd8bb2fa42d7875ddcd3750f120f0cd43e0d6a85472a7504083a310b2f6e9c65af60d66bcb7ab17ab2edacda3a2ed8c405b30c8591845baf43f01ffb10f9f7bd745c3ed8aa7ee140232bdbe48fc4af335413d93e649b14963c532de96c03e1a79dad415ca8907eefcefa7ab15740104b78b538ec5bb2243b7ed26b9889f08e535492d1aaf5aa7b2a90baca078fcb84557a539edf5e54c7141e0312736237c151653897ee481fce1f548e5e580879377abecc18c882697a5775c0e914b55e9f7b9e6f75b46dca64070d75e83a31a83e11b5bef63a0fd59e81b56cc80038ffa18747ce862cc3e532953196d233642f0f296f0574d83b4b4ae39404321df1f47325e84f7444ce86b222dd1da34c1b2a6fe83e48508f58a3f5e14675be470a2deb4db01553c84688bd904b4e74ed59b33f8bfa9ca6c267080286c306720f3c1f3e92288b3faaf171af1701b323e28565e26df74a42301a8be568dc0d0166a47704fd78f6d5eb64b85a0655d6f1cdfed809f56ff91496fe3d19fba1195f1d05d2e15d09af310f5c849c9f4c06c2d42c84c9f0f3f08ee073007bf370b13e1b432f3884e55a254c980b06f0ffc1545414b907c3ba80c1adc2305dc4d13ee8c51c509807630e695a02bac5093d13d69757fb99f8dd7c48ef108d550f6e757c6bf67b28be7f518c1b201334712a85aec3471e08fbca221372186c7945f0561d1a32f6e3d34b5dd4e79f9e9d52607d24b6b0833589c7c2087178b226224642908c4691b3da4efeb56b16c586154e5a1a95ea1958c0da2ad59a77349eafbd1c317e280a43f35eb07186eb86024c31ddcd162e364f373b8cfa0136538fc436149166b8bd504805dd7967840063871072f8f258301e4f3cd6fd3b8c9588fee3fbb91c008d27c536c9cb7052cd26fdf018274452e490d7149446fe9a58ccdf39d49cc2a16756370bda5cd3d9c3e0228c2e17c948dc5f49b3d81f1ffdc159985c45d7debc7970f1a00fb20073ce364333167dcce5f3a8c2ee5a1d7e94e69798d47851a7e5b197c32ad35be097168be7b946fe03d30b3990abf889c101e17055d8c6374809bf16b45a0f7678729dcc5ee905004cfd4d860c9a954d4f20a53a8959f8b3c44866b858e6c5881386b94a53ef33b432ce82955a355ea0b36b329ae2e731ed6cd5f9cd74973fe4bcc76fe94a542d006e0ffc993bf76c49ca199ab855e2c450e9b5a88090645fb5cb5ee130a3e82ff523266ea88267a8249a933f025f010b0780ea7f4bbae8ac62fa6eb94455879b3436674c2a0dc69962c71de2f0e5c742ec903d73d15e312880cd03da7890b7c68c2e6395011c48c70e07fa2193230d3a565f663f18caa574625fe8a7e3a584133e04cfd1dbf49b4a1dfe6666f3348e0172d852f97c66583b1ab8fdf9a38f1297eb0d393ba52bfa0107f7f58a59524acb4cb240f4d3f5c8393946e94e0402e2c4b92593b2fbaa0a427cb56b56d10af30d6f094eed88f727ea13249d0465711664810a60e01a5e7d62a6d7baa0e465e157a7d82f46c650ab85ea5b11242dad7a674e871aaaa0983530700a6356b7fa636404109292e6db063900df1d2d308de276ce8516db2c8602305c587f8f89678127e7f8be4e01f8a1b09217b958d9d6b6035a25bc5579d090d4c62516f0b66f39888909b325b9213c3dd113b917617c5aa81f0d68e47251dbfcc0021bbbb910686861063e9469d3ec11ea5cd27fe82750129a30c2cf74e48e96f3313ba9a95a9374be37a95edaff2c4ba3fb7ebf1022f734f5b5f4830b292a748ca41266e9ab0e90cb4ea4c0fee740bb44b9f27772115cd7398b3e10c52bd8c392ff15f5677ad1ded937d9be5d4118323a9b7549498c585ed84c7979db0d4657235afd23b412754c3f4d1b15c50a7ef978318dd64945db8a194b73115fa7e6df7866954600b279d588b771e0dc68358a03bc5460130211ee2ed69c92f23e9c3e0488e3d11dc52d5ecb23687a8a6cca36e9b3503c1266bf8d42189a2f9c84dc14078544f86873ed86c3c0d31cb233cfa80e6a54ec32399d33fbfb7b9aceb7bf0ddc94bf80556dccd23b423ea33d62e31a429879699de2c61eb4074b3332207653a9a8804329e150890987fe373fd0e01b2de141483fdf1a1e3e11bf0147e7a87fa0df77035fa8eddc524d3a451ea013345a02a055c406ad1a324634cf1486218218bd4b3c4886f49c15a8402e1c1a5a0a2a6f67d46c9ce42317c6f3f1ea7c08b552862a149d9d5917ca64ff13c66e85704fe6de7e07932fe6d4fa6d58c8cfcb00c52b9cea4c73334730420e05001d7e4ccccec47dcb10baf928765d17ab1c4a806a0450cc3b194cd391c739bc4bc0f19782f47f29622cd9f95b2da1e3ad8a0052bf4f0013cc3cb99eb21716007abb27327ac665889f3eb124692c802c64e9f10f293d9c620fe01e4af983183dbd55817d2cdf7ec5137dcc115939b3ccac642f0a0af5b4f41e02e3b4c419196464da4142b1193f057d59d13750742d1436be8053882651abe9d8ba68f3149330c0482e743dcb23972de8644a83d736cc15f99f8da99f2379d8648f2b53c719610178479f0bf0c5829e67e22350d153bd7b1c1e6e6cfb6d4a5b81cf3cf7492ddb9ab11ad0ed3aa8b6adc4bebc7608eb3cb79f4c03cc36012ac6602d546010a9e9e73900081921e3ffa53201989880240a83e913ca1520fcbb611a191018a10010fe6fdb4040a40cde4efc41b22b6db85186bf68179d6e8752f887e4c1741f87a6ea27b4c9a6a5399fe786b69449eeed16bb02ca02c102dd0ac43e19cad8ec2c84c645a1870eec8cf6303a1083ddc09509c1b94a99db9b32aa43dcc5c163508fe958120799fbffeff4ca2036f06dc419fe908233498ef1586fdb9c7327eb3f39feff4f6245b8a66f9c73cd763ceecb0fd5b5edb787ecbd7739aba3c3d721f1e5165f7b1761dd5e03645459708c2d57cf2aafb4caab4b85eb6c39c42cdac004526cb76d9ebbd1db916bf6aecbcd1ecb4fc922b1f42d2746ca21ac24675eb2ca1c12265a615c5e30b9c85b0877a9e33669e306f4ad3fe79c732d65105b9386ea8e3e5c3fb032c8f3b8b2138020dfe8de7bef1fdb6b13291226e53d1d0ad31eaa6a6134e2342c8714bddd73f7ef8099af0861f7250966ed71def1ff0f04bedd649c35d5e8e4e008811e19f16c108ded2022e79c97dd80315039a35fa127e0af8594a69ac95368269479ea64a4db846b7b18690fe31130ba9c467db84c8d21c5cd18584fd410262b7138c46067101b4d3dfa74fe5984907db933173b3e23a611933555935adb1ba92710ca9fe7746d49f853b54adbd8263ef07f7e95438642e9f0b89f1a75e9ff316b650f261f31da023f5051b26f18f2b9245a7174220a7f4abbe4f8ff3f223d92a1fab21225529631a73334556a16553581c26cc6a9c6db24ff7c3be28476816b350ecd7059512602d712ca8aee11699232f46ab8edcbfeff7f97b76ff3f6857ea8e9ffff8f857268f0dcedbd77edd10c62a3754bf557a7627979948bf053b7280cecc54f082a414c35c1b29619bbc48ce51c4b002b4e55071373185106b18d842169dd9887109fa3e98e73ce39a777103a161344554336030dca9345b80c1b9b41b4e3bbc769b6cd8d9919a3222388cbbb13e56524a55d6a614c01258b7049ebc6bcb69b1ebadcccd63a50d57e775d0e216689db1d17a1414e6bbab802d69c680731b187cc14033119003cefd5439785fb769fdc35b757881d4b7bdb7bef3da4b8fd97b97137f4de67310d02325b6606df6e26fea3fedd01e630ff7e02873c85b3c78d7ab8e3bf9b9ae8facf4310bfb6e69dbc8a1d7bef3d3b83d87aef58c994df1dd93b27ebf36df39a0878d487563e549a456840be8d4f9d8c7bef5d0c4a06b18959d1ba11c084a25f51d3a8b037ab41f245d3c422b48d244e5b9a003e4203db09f0d5789dc8c8de7bef50539b29ec889dda2316d39a8fea8b2f9518261d6db530f1ba136bd79d5db862d5f99493e7979f9517740cebf312ad951e108027ab864c926525280684b5074326c191738e3678cc938b050ca5ac284b48d88576672bec2df1ac31383b05ceab08956b35c0aa3e9717469f1d1f4277fca3c6e96a0d4f88905036b1f7843153c29d15e61496d2ecc5d6d50f698b6cc7374c9c150014d90ef3290a9545a521b9ebcb27d3891331c0fd32361ca48c5dde7e78d472d2ba3c5fdf162e3125358e8c50c5330e54a7148eedb26dd8bfd6563612407ceb8170467e323bfc8067189aaaa185c74a5a48cd2cbc20665031a5d4955552bb74768b4c0405f667a1e26114d9126e1b53b42b8a880a4a43c760a6901595d2ba596162c3db2c25b2bbde37c400e7743d8654ddf49a89b819d8ff3fd8f676fbfff898e48a19e09c734e026b7bbbd5b0e09e852d558f5c5be38e57b73adba79427211ca6a5bd92a4ceb30f0aa1f12834b4b17d9a6ca93009e37d9faae8f2d8c3e34c5c63f9ffdf849d416c34ff4de227bb9535d4945c4e665a0cd611ab066b46f70575cce7c016763022e75bade01514ab157a8145b9d07a368f532654aead625b0983f43e80627cc5bf7c414e602b54ca70172b065153ce958a8d828673ce7d7a223e401deeffff6b5aaae685ac71e2fac698923afd7e4968bf1fefa75ad0ddefa00d4c83da04c3d0b07d999e55777d58c27559b39a32b9bc9d325bd93483804ca8c05793a0aaa26b0a9f13c1b59f7d62c48c89183ee215f68584a798cc928f876c660c66a3c8f5128e11c55a124e540821a18bd9114c8f0e2f5cc9434657c60c1c95d763d93a02be110bfdffff0067101b3d74d3c1d351d5e2c805cb128a198322ad52e33e19317572c8af19d3c06d6ed79bae434e96ba5967c7246400516002b14133195e972951c95fa5d810c3ca6ab1120dd93037ceffff9f00630cec598442339a1ad282b1e29712a55a3ed22db794bbdd76cd7228887c6989c27281a9c9f21aac7ad815541c8a028b12db4a9e69950601d9c939e755d9db4dd6729d386bd12a22cedab0b98e30232f2c49eb6afaffff49e862cc831c61053e777c4c3e2ad73e62b0052c33265634dfa9aa0b788aaa50907c952cf78dadd9b19447ca809cf3ad98012e5895d70b48a5528267870b2b48050a74db1c6d59c8ace58e4fb372f8ffffff8767101bdd3fc7c3144096c65664c75c25d4a648b52e1dae947afe79928cdd7fee2c443c837b39feff85353df59afd8fc5b19a92e6cfaa1931deb65c69447befbd932d9f47d6d4e59a20e4162386cb598b73edd4d1da4b3245d4c98385d3a43ed14adc48ede4d39d73cebb5a64109b31a9e3c3a293e89af6be819754ada3699aa6b91c7665629242caa2c1f4fc14457f9e485ecc5c5df5ea55b763d7e8bec606586fcd8aab24d85480d6040a78689d91c6e352e78e6f9aae02acab37f1f725e2909fbdd97bdf39b9a6f73322626e06295f309c911f624b4f4e463b62f74f4b5da5b0fc4b9072369580cda445b5e677e924054544eab055fca8348a385ed99573126f0357dfa49ea41419a813e03e49015123a160c9d9aa2ad1b4914fb34c2e698ea7ab6d04092aedbd07771d00b294183516a592e9c609a8c6d7e3ee9c18410d6b2899dc9ef9a02faf51f6850c3c2bf9008148624316651b77dcf85ebfe69a03ec3af7a8ebad8bec2ebbcd2eb47bd4bd76b174efbd772f052ac239acc63786ea6a4739add8a7c79504388a852899bd840b2410bc4086e9dc1aa893e7e66e6645a2c81ac686507a3e1e27a4ee620015487e6a30365c9dcb9d44d23378dbc07ac789b1c99a39063d535690667f325a4889cb4d1403151dedf8c7e6263439498dbe5fca359907eac66946486d6a0f7d301cca3f1e50b25a572b8b5636e243a3ac820cca6bdc2a3962a5a39b16d5b0e1bffed8311e5f40dc83b33db66ac61cac9f55b59ed2c692552a74f94cf4d0444956783b4c670b6de4703ee122205c3316116efbffd756b14c0e6a29a2652b77756ac051aa649520d9b9f628739e5cd0823c36f416838c802aa55d79aaa1a9b2e2f42b533712925c67dd24199e951df47151194f55c7a0bce22ace39e7f4ae8ac3ce5e7d4111aa85f4ff9fade9ffff3fe1b0d9889f6b2b4e06588ac150dcfcffbfac6914a654890c16d78e782b7cd8852d77d895530f56f14c39c3db405fd6c4950d6d6812819c73ce390f7981d2bb82a8710acda854f185016fc0a4d5625adc9cf00b116aff6485676f4701c21def92531a48e2b2114bef61562e6e0da085227befdc2662d48c6aeafd0049a95c6d4970005391cbd912571a0c6ffb346baccbb319af700827b0693b5098b52523a8519480fd9c91b82d18284e843a69e1133fc3ef0ae32bcd9835b1c3fb2504db199440d8fcff9760f7ffff5ffdffffdf374321e218ca6138b7f49fdb5b7ac300ddd2a19ab24123d20c954bb26030480310ba6d4942a22e69a8d6d5d4241fde7be75b9cc80f392f6531a1d8762ad6dd787a9de687dd12e7a39b7d2f21b8ced68308b7a3b46137e32dd2ffd3ffff5c2adc1c45af9245d48428fc43031bd3dee781856f761b85a1d104b35770dd9cd3f9ffffff08145bd32b33b83ac5a636f4927191c8bc6a5ec8b2524a757550bc78704ec0790538cb0f04c3fca3eef9e63f6e9ea5e49aeebd6efa62e8103b1fc0326b7140b32682c7e683e27c6a1c34cfa917369a345b74578a26bd37450553b44d45dfbdc39c6d337f8a82d83a5539b96f9501760e876d03608e76ddd3c652eff1776fef018d21a8d48f767d3300c403b318080400c44018c9034d11e50314800315b488ac843438303c3c240e06c36040101006080001200008060340814020082687c88a81d9004b7892e68b6ff32ca233a401574e9cbdb25ac87aac7a9c21a03282d12944e83a9fc24a51229be433fce0d89646b189f012a5a2f16c622ced673669784eec24c0b1b6bde025317cf510454dcaaae98b684312a9dd408b9448143ca452b3c0d2f4c66ce153d40b5b1c328c1544349f36478e889c4f550b351d0b1d0506b1a2a0a23b5bf079f7294e80ab1375bff77fead98d6fbbd32785fb34c1c88cb1d7832b8586bced0411dd7c0cca60a1c6e007e8a5a22e5a6326973b47854815fd6a5de5202ffc56c363f431f6ab1ce4895a02312848138f9362e39ccda71b15bee048c3a8130b3c73c5d84656ebec0431ad06dc409fca8aba16e5ce3c68dd0466ff8d747c1c2f243b9b423401a6e5290728d174f7d1a1bebd90a06fe82816f2dd31a5be458573851e407c60da24a33a3921cfd8d621fd7efb74b1fbfb2f6a2f092f0b2229e14831a9d21d242f8b4805b17e2767a9de813c8d1c4910c5692f9fe23a189f24a22a913bd8837d59ba9f8f9b97e5b955bf9c9734442ea94c84a79b9045b8d82da8a0dd2d820905a278f718bf2c3f0a985df55480699d0401a021b34ba93e84f7c06ab3faba66f71835b81cf6b2b30ccb6183712b44998c9f6b4233a114c2cc7acc9d4150d413abf13900808a8ad5b86a946040ad26a9974db9c26500a338fd221a9f1e2243a35ea4a56645642638ce0e4721f55c5e648e3e05289f5844c926364a16dca6ac4b1900e253e5cdb1c854c4dca11bbc85bcc20b82f9bb3a3778714cacbedd8dc8420d747e034b44f60f2a72e61079bf7e1da036530929299839dc8dff3f4f84b572fb991bf5dc2a5b146bdfc4d8523e418256ca1ee5f1862950e6c896a609e2f9a36f31b9448433e0fe43e83a20b709f0d8e37a57de666a4c73a3419a0319e6499ddcd5590c2bfa8bc7ee611046539002dc5ef79911baa20a8e2770fd54897d4413bba0112bba4cf35a652fb31c8594d8f068df5c64bea435cabee2dd01ce1cc825e2a1c1ca1a2bca4073db489e81231fd43fe4449f74fc1974b8806dca4c153541741bc2edaa5081fd46d1a1431950d2011d54cef26693fbac08ecb4d310f14e09f73cbd26adb9f28d5172ddec7614d23cd22da423a8ad1eb1aaa62c21bc1528eff46bb4fd396a3d3f53e70922844c025322d57d3b4a14859812c9651148e2d2b0133df606ee2f3ed7c48046816aef724632035e48f3f25823ff1068664881129da7009641796fe6edc395bb75289c2643ea60e2d501fd66b91198b8b14771e2cd93e5e493c4f8a7fa00299259edaf1c1062a37d234d00d2f5a6164610175eed87d9b5e157b306b8da8badc48f10032805e6970bc654692380a23719e4d2acaebed1fb8c9b0cb236d4a8365ad56072d74ab6baa84183d17455ebe50dbf2e111fab084ddb7968cd8a5a0699070748f4372493366f2b3aeab52aa514c04807fd32cd11294c3e42c43b03640ad413bd0aa6a21bf8a3a6feb2cbe05458a57aae6eaaa26c962aaf62d273122f5a18a2ef8be1988174de4ddf22c6bbe7919ee1a07b3361a4f2c64b22d972659b2d30750de21e2f47870b818a0db48d6b892fb7aa8db9b17019b72ae2f9869558c1ab69f1fa868d44a5c227e4e3a07cd8c191c85f5a264c9c41694f4b36a69ef0264e818c62e5c5ce4bdcc27b2e60e67aff0d17d17649fa2a7af302ac8f15afc9cc14009ee9a649ea5b81e2b8fe2410c8fbd71c03102491ad601e17b02b658e19e1ec11e0a822d1aca9d5d3fdbf94c5bb0e4f92b8132208fbada6b6ace7bb449f1aea33989aece1f28e521df3fd4a44f4595fc34dd82e17f54f27c7b291aa8f82b4bc9fec76db016ce9a6e4869b5a566c900c45953ac70e8b87791e413632cd8762fa5adda1862f78c35c8a3d33936845825454be6a77fafb61a922ac44f0b4eac4333962705fa1932ab3e6929b3659d95c127582d703fe67218d371981cf59b6f162c18ba2be9fe18797081de33e5e9cea3cc7c4f600f9b9710174368fbd3762d3bcf5596c10cf45ffa128887041c16273274a8745bb6fe8a9e6cc44fa70091629e3104ac06a3ea93d52833e358594ee14b4b82ee07d5f4cf963c5bb397c655e132c3ac6c30f792e999962bdc10c684862d560f43eae627b43d9245645a77fd48c98256d0cac7ee83d5e2a2b1d10653763c9f6c82cb807845ceb8bb9d4ac4f5753d2a6ed4111b1bf1dc871403868fc66e13041f2324114e33c8b5913a109b2872ca18a6c17018bbebf6bdf94b3cd73ee83c2427ac3adcedd417bcda125b429465ca2e63b8a81e8f97ec8bd84327768883e1187ff9dfcb55e04c66333407868cd9ced33b215ca31af490eec94634c8e5b8ebdbba5f573fc5fb5727334938cf78850c60a2c3312f7b9a9ddb0cd75c836d077a5b172890ca787a88dbdaee82e60b0c332ae8333df9259ff8819a61990ac8e716f5c2804d814815b7667b8ed87173e77fca0e1748907e272ba3236f21fd1c093ce7b9e351c4054bffc1c90ffbce9a85dd6062af5c75c67cff1a77d9a1db7ccb8aa048463a75c7b89469a4c62cbd82c3c4752d0b1b1826955801c56d2459996982720df1b1d75eb9d267753d23ede4789f04b2b9af258021a1ad2184ca83755186364fdaf9b2ebbcb52d40b4d10608be2327c2a34a6e04e862f7ac2ac6944e9b9e66d42e1564a4d615179f5d04adae7d27760b8cbf23b9b65648e162aa3b76db3cb72f9d9ead24c42dd61763f86f399e5413d4405a2c82c6383e823f1cc4f5f2c9cff3e3c51dec51a9da30adbfe5c19b208d0700ca87b2ec40377493826d42d858e274d3886136e9195636ab26b822e2015ed57c25a791ec35fb66d588ebb6c3df99693065e1e8430929ad402fe22ef6643f1d1890f628d152d7a3e0c655ca6a6e1e28e6adaefe6601e7a373dc2624ed5d9441d7d4a4a6a891dec10177150413c33e21739b4d75458134df60d1c453064988d065dd5fc4fb83cb0f59d3d024f33c01cb50b26980963212aec4a9208b0103e0c6630f81aae9937a8a6dda8a2a18cdb3b04913fa97f0f9358c0719ff577650a563026120629ebc5b679239b8e6bffebd45cea0ff9a0cf7edb56366e5e52eebec1e4e3c3456d4a91bbb617d5fd21f71354b409f9e00a0954249793522e7742f168b73bc0ad4a346eaf573086a56de51369c51f2b090d466d5cc0ad8d40c0487e8743238ed29830e4f30581a863a2e0843d160d04ed0c5fe7d5540879d1ce333a6d509dd9b944d6cad4e4f7557323642287a78a27f621ac3a105f4e8f052743923345f6281e41400a5240b6340a8724e1af63824044501854d62c560d6f842d03c630cebf84633c63f451d8fc3d1c7bb8db5d033c93e2863a22792c800116dc1efa1449d6e952f18a0ccd9c2e62b21dc2c70d03379d00f0cfd64f37eaf765ddec429d031dc5cb0272043a9b9b872f76d8b226028d069520495a64e08aa87a922a86bc299df72e7befe7eb6165217e2d3ff1da59fd13e16005889234a480ba3a83cf241b49a219a308bf7a790100e6a4eb72a41b779aad4699bea290f5e6e4a1f60f270f4feb4c8f54b353b807bc551a99600b28e648c7f41c8167afc60b2bcc99b5337f5f538dea09f239c2a25257a0a9410371bdb522f57d7882e91ee74ad01d6d1d0a13d552c7d111ce38878bd86156c674592d5c14aecf1cc6a99af9064ee5c448a49242fc27047e3ae0998518ea66c6ecb25827f3e3d7befdc64b016c1f1f4488cf1c93515513a78c7cf0c23139cb482da0b9f8ae47cdc188801f031fd857eac932da7dcd7715cbb562493554a7282c711cfc3a6de89994c58ec948222d1d9bfae130f4df8c0ae96509099db8e881aa3489d392fe1578acf5e7d7cebf6f5263d85203fd072a352e8cb2fe8995b56e65598b54eb20d55a25e699f86d0cb3313d04105c54208020ed87e2d8c35240913628f8b206046924def1c11683c69b5ac7203871a9c6602a9da37f7790365cbcf13bb5c583277a23ac39a849bdef6b1b9499842b2d116e8348e38b961d2ed4fb3871cf4292b8a43d3da9df6a6293ab8cb46f24e05f988ea42aff9aa350b27e9b978b04fb173f8a44cef6c1749fb26a3a18e98d27e1c1b798db7926e643dbdd8e31f7e74bb3296e8a435cb81d1a036cca8d04eeb0d62af2426e64543586409037a53888af18f69b50e0d41ae959b9d2f098fcfb5a6502454112890d078baa5d68bb4a8b8227d0f6aa32f6245725380722065413f7318089c8c7f5ca16d0a4dffec0a88b65e203cc72940d2ad5e7c016b6061ee0731e10e34d27cd85e31f4784ffd6450b839fca3cc5a79b1c29ebcb0427655c074a7912d30b153959a311a1ed3f1d71d321d781ba911c865c7fae6427b5e38b0b70204538d439f22476080aa8c0a5c1e4b7e73fa085ccbc639294ec49123e529592d8b291a09022f003f7c85d9185e407ea848fc87501aa13ca4261d832f4052c4f9fe3d9296adc931660964580978fcc17e8c7f492de27c668ec7e9192f11eb47fe239be02a7e185ad48a30254954e0203c39a06028ffae69a0065c8109cb04d90dbf94564917efd4f249c687d37f321bb8e89cf04727c33580ff74c394e6616e7ae9890c918dea8e7c250b2c85ef70d443f24cc630bb4b9061a8fbf2a19cb89911ad099d6ed4555926ed648b5d117592b2246ac6b0833b14840b763b6d2e49ec5641cbd58f6e63de7dbcd55fa49322df99798b66811dbd3f39b80089bdc4f7ed898c120300cd65b098cc361b4a28f8595ed45e88cc0b882b4601848dfca70fa7c7d9249d689a7177b3fe20a00cabe1c2ceef3c2b0261b30d620b79adc79dcfa48866bd521890f83cc1a5a0cb0d4319bdfe854bb12efa800cced284419099dff07840a2e6e584f11c1ffc6220a59bb9dc3e1a2b4ebd9de3e922c2e7147776f1af89929c9a88fdf896fae040063b1f3c6c3e4702e31b32e64b078282084e6ccfce4d904299089c532db8c7740119a459aed7870e9f5f3f2558c8e5c0b80b47838cf848ece8971347e651193a7d446c4b879deedfdf6ec08f25677a304724ae3e3d5c6ff94af6e562bb2dc4eb2ad6e1028d3442d93aaceb4a523061a8751c49f81f06caa1986a78d50039adf280218213d2850bc6f363d21c0cbfb70cd4db61ae90a7ea263e3694ed65b92d977c7355be5f4064c82ce2f42f103aded94785ee716bc3eca69b86ce396f045465bb5783019ef9dd325e18bb61271b0517368ad976953199a9cce42fe5e220761d0046eb2e7f877b9515250ebb8c7d558d929dc3c60ca0fa4d58cc4cbf58d785beb2780c97622b0040d565fea91fb14e70e380740219360c0680779f25a8fc139c298425dc96ebc3336476818252df5a72648f4ca153c40ce2ba749ecb0a2bef726250149327e6439f221b69a32ba1c33b24281c6f4413766da06907243a4df10ec811700aa5fb2bbed239a13557555f9ee168950821658bf84502d1a9c6d7c597b2d510bd35c7a2eb2b2cd19461ee13a176fb133400b4dfc6bb13d4443886c0222081f168048d3e3a3a2fd2da4374bf2c63a550725227c0409ff68451562a289aa812fbc310969460486254d68649c08f40befe4faff6c22c18464ed5d20b84534da15ad70be6c810b6dee0afbedd72ca9589c6c5f1074a3809b6f828f5ee50f5f89a8a14014c44d91b186d097c6f6db83d2884b07ebf6615b60ce4a7da53c2aa173867c3f01fcadb3698db343681b765f58fbd2e7d635270a6431cb893c7fdc01b824c38586090ac14da51ae45548979b92494190604b6a2a60d2ca31985c6c7fe39791a04fae0205ed93582369ba480b9c030ca53fd38e53b02dbd5438cca5b221578f949921a2adf3f0401c4ef34cca520c2925cf1fb52e22e737f426ce5488c4cc4d88671485455d03ddca93e0d947598a29e34af95b1ffa59909ab00819292c4222e2ef84726d815e410a50bfc2af8ec196a026c1012b16397a74498df975c013d956550f45c6d481f311db6140b0173b4b24ad46638f4c381871c7cbaa179b8b161baecc81774a8e726660e57977cf1d9889dae0ee14a772add93c4bf4188c76f88c5c6d0244602831308ccb708dcd177c5064c1e758126dc211484ce6bc7d66464b1c51afbfacb297ec8b4819fa768db583a72c32d678bd5c71fbcf191325fde71ba728c795634695ee646a7a366270d0aece502c23c9fee9b3412487d0b6ad7791a9819a2ce6da9233a20b44919346f7de9a0326a41e2b44ab6b53006b3deaae56db9d5126dd428f42e23f4429c3a17cadc115216761e240b0eb1eaa8200e93e7e8d4aae4e2cb92776c27f07b541b4fb8be97baf4f770e9e28b298ff02540d74aacb5bcbf4310094996e864bd69d919f86c90f9b39a3aac584b3202474846769378b85918b2d3c9b963c75197cfd9c94a4899d2ab54c61b58102c0455d02ae14de2df6a4b16157b3ef040355fc2176f86c2568a96b406696f308e8ac4b81e9d247b3f1d02a5df64dcbae3fbae5c022aac8892290dde1813ab4f74f196ff5f242243690f05d0c09223f03491c0bf391339f695e23981140fb157a4b7a4de2db870e3038f87b8e3da61ce1877c4aad8b52d8b031cd628909eaaca0a575ba97011f8d2e8581b5f626ad5a333da22a3d56c7a4985e7bc4748c548f2c6e70823f617c6400b9329a87df522a1eb71f6a3542e3cb71b233af4d3cf2749702a7ff40d64b21ba55b2850af5a649f67f6df8c93efa433092b421f2cedf4afd141dd21a445ac9ce2244d5e31303b556c1a02e646b0812f0db173ba4824865c695fd67b478c73c0acd5689ec03ac538448b36856e077b848740d72bf8edacb3d73d79fec4839d1998bf656e923ab70088318af0aec1672a5baece9738e830df0f7d8b2294dc7780234916b76992386d8e65e1e8be7314b8f2efde416b322241b59a3bbea4e8ba3da242c7df30aa876a5163029e0f227122723897344b1912e6dd3072c07ed0e624e23cf83f478ff02d81632b1c4ccceec7d05d0dd8d9fd3782cd9c599aaee6664ac4d2b2c9155a5c4280f518e7427b7b9b99e4b1deaab88ff4ea48658ee24f3bea8ec01683ca8e78456901ab1c746fea953cf46e1442b553359d21f97bce1e4de7efe00ab363751c7480ed133c67b43303f8d10e0c744f3758e345ad9e81a7339df68124a9e183242420372e30841d64687745b4934e1df6260a9184d2ebbe2561940da2c08c16cec52024a7937e5372d996a4729095c01f2fc0c02a10328bfbeb2c2150e44fc8bd8f683778704ddcd0481bd5dd33b745b0bea50cd07510483671b2c6a7b1cb2f8d6e201609d4879fc305b7c9bd869fc80b190c7df345c767907e6bc165bbe38473b8cc326d32d0df37172b50dcdff74377cd7d462e8e36b520dd00d9fd7303f3bf398e422318ae80635c98461488b727080cb42376a55270e61285e7cbc1a6e458b9e3bd4198b30f124a939113216c53d7765b298b70563c9de88b37adc6c24f1a186b5f1acde3dc673bd27e644689961226b0c2148a94404b2cf4d9dcd9db2dc26d15273dab6969a16d5acb99b019d56e90b1d3c0f6597cf4c39ee39ac71bb62eada7d56093636bc0a2f4eed30d8d6b5e33f37b93a7ff29fec7c0f66257ab170011f5f4913b5818dcafaa85da21ff1c3e4bc0e9c0282619e662007b26af72dc8faee68b64574fab6b57094d540896b51ce1193adbe85688938a36f56b48b2e49f496481668051e391635981dfdee04c39320262e0e76186783e5e4cd8771cad996a20e2f529fdcc94886820d4397bdf72ec43e28a842472385c0e3ebec541b7a716d3f2d66b760872ec9278814620360ad8211b7c43ea1ca6e480c8e62000d9252667d05e0ca53e3a8e05832025849e193b3194dbca864f66828fac6d182151a40a4cab1a25ae48c327f3795d115c001c3175856ef1260b9c8f7d24927f72ddceca2190b4b055a2c11390bb4ce8a34a91b6e63e364dbe65e6331d810edecba1ce1047cfd3ba5a05f18a7e40ff0296627b64cfddb1550e76857fe675f97e738a0d3cdb27c746c08a8342885c0bcf324126465bab36dd92e8341c091b4c5371e0341a3d98e561e47a4bce390c7130f0bd812687042874551f1593a4604c31d1311c093f19b59c4e7f4a49b010a163652c73492ebc02f30b5969bc3948e9120061d3ee4e69cb3a2e3895f0052820449408019de71f33b9000d2604398859d7db099ce0a8f96d44065af280ee09a0e8a49d9956bef3f49b9b1675cd77611806d655400a3b9f46c0fd75a00efe2f1cf5498067d550a2c88b716e96700f504bf6ed8494317fe28af0daab259e4cf13a30605c8d1dd04b2c1019d8461c4fa537f1d1e5c65d77f30d9be688d11375dd9a552fbf32b51a485248b84e28ad4723488c5ad945be417721d1531294cc4d7cc17de8db8c344f522b7d0fe3cb15ffb9f988a908724a39b35277394355c70ba937bd116e39e89932e352763135b427145a20ab2f0d882a0e5f349c70e99428a5e2c00ba48730c23b08e80404b145e696e41796262c1b3afb05372df764eb110df660c8ad1a3a54f9338eea2aac89c7cfca7a635842c9c7c692be25e0ebf56dbf8df28cd90a4b84a866a183ba5c556c07b4c623a6613b47274866ae12d62023d472dee8158907a47199f1391c1dd7ccff60281ecd88b5e8eb8e8234b2e4cae2c52d2ebdddbfd14bb5293903c63b5541f6c864ba5214b52ba97555980d4430cac5b4c4672a28e8cb0baaaf8766187b0a92b04029df9c076ad25b338e0a80f18a9792f1713b8e81d75e7f85a60faf267837baa2c61a981bcad46dd2f3d85893f57133130089f64c1437e398357a6a01436b74712a2e0843b9af0636a41901b02177045019ebb954fa5bb4848e1ad4db26c15fa84b2de35c454d279ada346aea4dacf10c3809a4d5a1124b09f762e235c6868aa500e2b35f5fe7d4aab3df3ec343907c659a10c22cb743830d9137fde32842102674991424187d59b2eff88d175e4d9d9136e48f5583ea5f0584917e30f4bbaef97b98e5601996589b74e49a687d90acd469a198f136f4b511e79bb292fde23aeb86b98f4cbe404776b5760894c8e61e112d22bbd9c901958306829af23ccba61090509489f9f74fcbd24d5d35b988cd3ffae2663fb7a2d8c8754ba491850fe46432eeac7600b254e93e26591a0217d95c8ab08f923c91e8e1b614fde1cadd45e1fa98fe1e4fcde0a321721ff55ff36556a1ca017a5c67e464bac34f1ad414968f847eda2f793d6d4c8e0a60558a2854acd31d9da0063824210bea28ce0ab7492a86feed13d6f56eca94814c6cac92d1d2ef25422703eb715d9db18ac7d4274906b0fa1d5f96888422118bb78d48a3585857ea51631122620d74290d969040980a42b11a5e75378ca1cbd88b3a71237583a6486488d6791246526638a904cedc548bd90f3f9cdc38be18fa617b5797bd6ad3291f92676f74dc098d39d15b74b823f3ddbe86c9d567ee1b52cdc45d48a9369c2a2eeb933046c30e705c872c3921b11685021aff86fa4ac98b0e8f12e1eea081edc51e6a53c345c9b3e4045c00ea3361ab0058031996935e20ba25627338f69c5cd3438a291e9901a4cc2ff939942fa8fece8d2bdcafdd537cbb5e9250fa85c31b5c0e48bd0fd34d28091d1082e59d89392438910b85e1ceda1c867c5930a48e832abd31c8af87738b1cc55af8df9ee173595d2b69ed76e26ea7c75e528886f6aed2403d86017e6cc023babd01eb30eff338a4e237ad03aba699e400aa9eb55d1411d93f270c2d2070c974e50c8509b398835c74a6235379c3849cc5cbfb89039922847c72c721068d6ce2c9500580a4320d181910912ae0b7a1fa36121ad21359c2101daa37c2552704c6d751430a4432c81e1274c3608672689c4270a4214e175bf05579c84f441749b403b290023511bd8b5640185c594a80d964c3c363c5e5a74507693df5c4f943cd2b928927bc69d65fe76cb94a4dc7b074e024a02330227482cb09f251ccd97a67a5d8ec3bdf756669116d6f1f4f5de7193b064e91967a020ff934926b2a498a8532cae495128792ec2944aa329238aa89e82feffff3fac816c2d18562a1db2520a8a555d13992630ab2ae755960de42d2d06c8c9f2a553e870e038dddf83a4ee0a3d04cd683ab1431842ebe7bde05a931315224a3145d0a1a10371dcc212a1f41b728246e1e69593fc9ab430a5c85db128b312ab45151c17665b28304678b440f4090e0e2fcb4c818409fa21dc2d8ebf3c259ac00805c388a5cb057577af2263d8ddddf3cbe10cf9c6bca6b4cc38a794a823600f1f19e4c1cca0bca9b0aa93ca2554e27f2669dac8eeee4b310cf55b825270ffbd1bdc9029dc9470eba1b8d9f6de9b4ccfcb52845b4ef1d697c6677c1105a84a6103418007aa3da4fbff0fb451666baec0476a802377772b3686bd497724a13856429cfa43c2ee6dc20abf7b3bc0d386c0db7300518c0372de9168b1c22759d86982b030db116b910d4a8e492dc471098308e343c7c61789bd3714442713fa8975181e82fbbd83d9a36ab916e2de7ddc61b519f28dc5d6504c8c3a09c66870879d8c80110fbc344249c8ffff7797d1ad5b181b9886355d0b0b0be3bab300c5cad972a41a4bca3211674509a34a30b2341d81b022fd6000756375aa613a99666d7164adb80015f38157800779672b7b73307bd7d68595151e1a3107e9830fac9f5cb4ec5efb0e62bcd970dd81e94445b3c5b0102f5e9473c0360ff74db8af5eed9012987413d0ffff7fa26c1151a8c153da58105d1ccc882912d5a9b0a7251214cbc6e96d8b55aab923b9e3dc5c360b160444231f4cd010b451e7d4b013c0e24a7125e38461624477edfdea90872ab0d2816de3650124f982ba37fdf86bc528695a9e8cdaf5c94caa7a9dbd58d1bd68ae9d973ad0dd3d1ac35238cf41c1b4bbb751322c8509511f6e8c8ce7ff0350d541c9431ce4645e9525d521d58a7856c6ba3e584be8a815e84300502812e55541f4b2b7935c865821da9c4595e85c04b15c4d477ecf67436f15fdffaf80fa7c667a0db956c2ddb57223500434c0ab6440e6859816cecd8f870f8ccb4c510b1b21ad950374e6d566f35789dea6f28150dd5270e362ca921247edb0e2e1408f5d1d53da55d26a242ba9d391130532f394cd27e7d616d2c48954a2c179d5916039fa32b40a1d9b20905ad5a605e7a7aeadcb59d5c633d3d61494cccaf8d058754b2804dc17cb7f1f559d943b1dca46a3bb09ef53aefaebeeee7145df48dc5188b73bfcb64c33bbca8d0e6d04e8ab1c64081cccf3fcfffffffd5fcab648f46d506aea9639f5fd8640a4c6debf3723b59709a975223ad1fc5ca4285331f86eb062ff7f811a22d587a611c4ed221212934f5f73753bf5a4cb5228ff3a83e8594d8c5e15f3274cc58a4a686af584d664f53339a226bd198f592b7c9c80645ac4489d6ab04d153494c90cfa70f7feff7d1b88c09703dc21cc160d6114dd2697facd7adc1cb3b5edaa92745dabbea8d02702284585372b934caf2861324040c714a314ea14a6aa69d8d11995261b333b9c115df52f0a6ad587788f4bf223d4ed8f5047ce3e563907ea826be5d0eeee2561c8185e0ac394c3268cbfbb7b490d3686d95c76ec882750acaa4e684cc9cc990478c6b51752371ec6f074d99b464472a4158579efed91e2e2e592e3150804eebd7716f98ab4ca91ec12a923e7a510a2bc1ff2d2b743b8f7f0e568aaba06667702b33e1a74a14a6a422d6a50d020a1931c1dad00c114dd8f1816bac4a4c9bcc405fbcd4c4107ecc2dbe1ff5feaf3810dbfd64ef470efbdb77e5e91b668eb483841b7315298855af1fbd5105f4b87f0840f08dcdbd7625f9fc6a4e6294602c9650dcfa8fd3a5aab47b83916bdb968063d561454ea0c1b1c518d27a2f2764098b8a804f554c94dc5103b52d052571acc2e06a87ccdfcfba6ba84eeea1a5e72303b435f36503acaab3717d91d63cb887bd4438be5a87b0b77bf90db600e4acbe6507fd518e2eefe5ad257a4ad5e9f440bfbef83e3bdf7dedea4b69544fa90e584a6f7c9ac3b2789272c1f1dc6e1568da7ffff5fa7353384d22664d7c15a98de4b51cd0b9906cbf1f93cdf78614785cb079298f7964060cb5bf3fffff215699bce6788f446cb6465fcd537bb9796827b67bcd720d01de8127df90de18ce689864dc76a0409475b62331f52ec14f184889515f417480d345b59aa46993d652c025f777726640c67ff8d687d657dae12f8ee0ddcfed36f03758f83ec1270d57e90af938ec6026960d79c59ea8e1667b1b684e9e8fe5a41bea310354d59314069332649a5f2e6c9a84dda53651366c10b76515ca1d4b901d8ffff95a0af481b9556af254ad8dd80317677f7bdb770a76cbc2d3fbbb8f305aa6691160ebaa930ccfe4d1c40eeae3db21f978cfb11eab6e8c179f722d9e2166d04b9fac90c10380c6f11263afeffdaba23328e6d963bc09c24cba8307682e33473cb03b35085a54375c4bca9c91982936c1fdabaf74be67c39d4d5218b2be43a987150a40a81e512a7b4a3b26878ad26a47bb2bea51790d798a18cc40d4c1596aa6204bd9b131c1dae3c2a9d96f31efff7da976072a8a747a716352b981db9f770ef8cdf684407264129fcdcdd4540635844d69da6eb48aa4bce9984e7a537745606b6c774ae8db8160163eb152f7a593774aa33eb893b8b4bd9208d57ca13cb94d3224bbbc624878eeca6655c1a5ea331ddeb34e8ee4077f766166961f796a88203f12b465da6224e7f99834aafc7a55bbe8937e381ee06b9e6feffffb7c39582e6b71ac365174b24c1168570fbec292ac82eca6d4f6fd39430c22c9d00a1ab3c4cdf9138f451dd51dddc16332532d1b702a2c6c2975b6595fb90ee49b44657ad160d6331c7281e4b1c2a5e54622c9541a11b58763d2c2a467366672f86a87ee6fccd29dbd234fc3b958927ae1a5e479de1cab1dcc130e74dcaace1cf2cd2920193be0960925834435e8e109db585782eb86bcb5f100e06774c8f6c497f5dd70d6dd692e77ee68a60610cbbbbbbbb270518b2c21093b1b04b4c057492b7cbb468c8dd9dae18fffeffbf18ccedd43309ffff3f9cf793579477d421d47b19be47c1517777777f3ba38f807a089fbf35a7c206cb523c9b52c731ae1aaf180f78d434b1144dddf900a126cbe335364555d92b827bb366ad30987316f47479008ff24d2eddab6ee3ec58edd370f303c615ec8f044f269bab5499d74b8c96a8c41038450291ec08a31808040d0451248ef348d0391400020eb478bc78302c383c342c200a87816020300c1480c10000000c068383813020440e9556223b03e123c2daa70b1357dea207bfe8115cf0e05991b2004ddef243c08ad2566aa0e788c1f03c23a59aac2edca5a0dc78b97d6331b10a4e8970aab7ed65fc71db12d4ad783a1177eb172f2f3a1e190ec404a9e64dd93443ddb31370aa378502ec08da93a43309ee4e829b753b90d439241ad13ccd7139a4c6fe50796352db5ef47c17f262d26b3ec7f588fbfbf51e869224184b2496a014ef86b5209e3b56e844b1f74b7910ad4f1881d15469959588e43458aa58b3d5a40d3d7557d32767c070f751af6188e7c7505a1f0cd48c1dabad8fe2ab776ea515de522483434491468eca381bccda871885913f280f3cadf518ed0d23d0759197a9b213542b6eede1a8c3b6000d569758c848370bf64812bb5908203149205cfdb95fd98535dd86f18c19d779674397868b8c5aeccd78f6ba70eda73293a95e689430af3b447a0276a9fe124ee6b83f44cee75490fe5f425a194e196a6a580d2d4b654105649481a81f5843b6e656e719b8f018774c50d3476cd5672a0a1bf56b75f3d68867d69f989368f483fa26caaa4189ed9c7396e4070e8568c513b5785ccf0f1c0c14816c9099fbe10bc9767acb0e530b89728f4b2c2270d8078786042bf03a759dfe20fa311a2b6eb001f63ea618e47262f84a75b71cbb471fa8ecd0982bb8452f3c2b90139dfd51bdf0f18e3232c4be073c6a5693f3364a1d332abf5a902d0ba3e070302592c6326c7ac60baa671b169f9db2dac29f60131ca109d58e4ea2013e3b335ecc9acbeb084a938cc5230e33075b9229bd699948cb85c7f4821710868fa1e42d6744dd743e32e9c97f2dcabb4e02f663853045019284c9e160fbae6fad8c8b3e8c97b432ebe34e5652e659ed8f907d4fd623306edb507890245a46acce424cdc8f32bfd768c84ebc23a8e6c692465e69fefd74c170e5ee35f2f8d433a00870ba6ca2818312c604c6824b3e48004cd96b18d1b6a359c8d793559a3829e032a2c59d55e25a8514531c9cf9d69202c682a9d591126f1e5106f80a77fbd9c0fe9c89e5dabeec70e587f2a5e41f90918b92c831d0b22e56675ffecd713ec4a0061d16ed84bd00906e2368b219b2eee5bfa990b8f4f81565122e566811f1d747f3d00c20a6fc2d08786e70c1a71388069453738439f125461db5321bb2216448fc29c9e7fd284956171c3e408b4007a9bb9a4ed9c8084df003c028a9115c1b39ad79411364bd8c053e82db0de4c522491bf9eb6e92f32a8295e7d0cde0d24db5c734c16e6c8e42180ef4da844a72d4ab717fd90f820dfc305349f94a5fd2e7223d303f7ed023fc8f562082c6c3af042b628935add9d3e4b938dd2c11468cc0adc423cbf05b253d6e70f6b1771157785f929e2682873114a1bb6b52e3b810c360026f310b5db744dd3c16367d4015448bfc216db1375bc4e283171d082c90a64664042d5dcd5e442489820c0cce1065771d573e6f135cb23f5ff43f769803285488385edeff25319fce93b4e6b28e78ebc630370079ef10a68e498b236efe1f11843e4e4310b91c16a73b9a7b6d0479fe11eb11b2b420ccadaf5302359542fc6c62cd248bf34c936a0d6ea3c952638b63227f4facb8ef2ebb23fbc5a1158eb5944932992382f0129a9af435459d296f2b484c915956eb8f5497a3f765bbf3c1a64fe97bf93dafab974a82978ac5f0464a14c6dd3e2302fcf4bd79b985172bcfb94d0fc50f05adf5c66cead0127c2c2287e3ee063ae23b36900afffb9b2c46207d2916ef72ded728f6bd68e04f2ace81c518d6f44cbeebe4319840d3724a258fcfd398b056c85a420b617b252eb00bc55525e650aaa7c361ee6729f9cb0b992c096f62916b838ce1c7272c4ac6913aa9d32140cfc4999626f5ce2116c1a4898881619635013afb274d1ea535be1484e60e9648515282960bdee6d648cbac63f6ba05ba8b372e95329f8c5884c6103546528c4f1eb45e62048d1845684c4b7aa0b259c6fc53a619ecc11fe1003d2204a38c79f71e08aecb0c18b886fdc3d4420f02741d6cc7db41475eb5e67aa8dde1444c2301e60d14d7e0c04ca524010a582e9351e416a19315fa79f3c20b71e96a02094989ed832caad3be3382e6b5071a2f344359cdc0e65e6b3ce991407d099d1070dd1b5ad2c755e0a0bcac5a1c18eb5f2af84c5d39959e057c997a4d1a18f490155d55f2a55f793e64c30e1f88842db2d5fb32f3f6fc282d80b405fff9a1428961dbb302c940f774d6f03431f575fc8dfb5876c4840dfb46e4f5627bc3f9b8ee9ff1a06f814d00d1c4ef757850e40519d68e5639022ed609f024059be167b5e909fb978099c7f2613f8883e7a02cd466fbc443dc9ab4fb3bc7982644f6660e960895fc505274f579ad05b8b9107c2a10c6c11ee824aeea0629bd244ffc77bed7367ef435534c5c578923db279d0878be2493f9398839df092123df615ab25d6ac34a3efff966e9ec0e498a0dc71899594f7ab9613d8449ee63120fd38d0b25a7496fa5fa9334b3e418e581150eb0c74c1cdb918b782a04b34cbf9c54bf8866f84f01e9f427ff319c52944b6f3455d8501bdc3cc52cda05cea0255ce2c0c74e4000e4ed402aba001220bf3ae1adbe9d086ff6aa6698441e593789170bfb5990a2116a1a4ec732f7bb89a9f3304c086e4ef70953830870dce8da135fa79121d19e4cb100a601723f0b0e5d88fa5752b5133fed1006440fbb87fea2d33d8403fcd8512a863120dde812edc6eb1afa50fc4e941581a9d9fb323e77557baef5ecb7142a87ad8073c7c23e52240e256389303870ebd9e7a21a2faf44004927b9c898f8d063fa1e14b72b3fd081fd076ace5b665abeb5a0b1df67071f3ba4dd1877ade381015e8570fba5088a99ca75ba85239af944fe27e844608565b81093d41828d448ba2c3d768f85aa2cd31d1b30a26f22884770e47fb2c44067c28c4b6c1be924be2cce91bf6294df2aa7a2c8979969a69b7c8f24347b783dc8bb62a7a1ceaa980b485254506fb6357f3b59eaa6519466b3bd240e0b367ce4eaa0897f7464f9b60c084c6b43b43bb0dd3a190d5a72d95481855784c730ce63ee508344b4395b5759eeec4811a24b05ba535ba6f0b44389f1a93b8d95a6ee87a7fa479aa74e37557d6d60bbcfcc516e003039922ad670d58a9e6d2306c20ac8567f0cf863dd0dcd0981b98658724e72b51e6e21204c6ba91f77dc6b8f30adb4969adef72583dc85aeba0c25546df9e36be311ad5f474300cf3a1426d183f8bdc45662408571747818552c1710bd695f20506c18a312616fb6c7a2b6746fbf52b9b6eaf6199c277c934118e820c8317d0a1ac3d17891b360364ee7a8b4349e80713876ead37276449e9c8e30bbe4c5a8844ab83957e42ca7b9a2290c4d697c61b4be4e8ac47befaba086f6551e371cf2b6bdb02cd267c544e67b9a35bde49d3cdc4208e78e06ce07ce543d31adbf44247b3743269c8ffefb392b40509d768588051474d13803bf907382ca91aae5fe6b55b2960f4b49c820899494e8163fca3fb7531186991c47943a55fdc34c5612f9da7fc3f338c7777dcb503541219c78c9ba3e3fc840205e8447bd1ed10feccd2334d4ab5e901ee5631c24fc7f37264ff92c87239018fb30a47e26f70aeefda49bba9ba951faee6020b65cd297dcbc209dde1e908180279d38d962a4d3382a4d58afef8dc8dcacc597bc7d2227da090a6df5481c5d2d1b01cd9ba4c54647c41254e469a31ebd96f99c1e78296c2f6df4f19951571a070c2dbdd1377f67e863b178cff157cf0e03beefaa4ce04628a515d35bc631e36f54f4a0482cf3f3fa13f905c1f585f2bc4d2a8c37a660e3f3707e389480b456d3759ce253e9708946e44a0ea62a89c9469ad999f1f5cd48feb6be225e73dd4c12c8347e3548a095573bf961f5f3054b6c5818417fb21d337451cab517a20665aa7795d0537d07ec738dc8e97e7ce38af1b3cd7f524af8b2c8a62b2703e2c2a2b562190f368b5d68d4f60780e628496c219f6bbdea6ef71f1125350c4356c70fde225a73817e8e99a10d3d190b6abebeb5068cbcc3682cfdff96416dab13305641c5a0377960ed32a836b1500029c7368a5149e741b5b19683e5798aa0306ecf251a6394d5459d97a3e8601b4580d74c3755e0d3231718a99c6c4c5cab58d1b7bd50765726e0937e6355db47b487aa7076e4994e00c30f94bc33108f03b0e85d619fa6909a18f273f172ec2f22b0eacb50444b4163e629b988fe236a38ea11135a525c3802736dfc24890e68774a80014f7795bde717ca12b07c0d382278f858f64fd384fe652db83a5809004a6b5ecaca0ec85a26143fa3f24ea6af618fce73dfb62dee545ef25bc087c40fb5c337633df50b006b2c91921b8c411e4fd4b6be920f94c6c86ab331271bd6316dee1f8bad07e4c1aab89fa666724191d8611fbe27ba5aadc7398533a8c8e587d20596fca24043222ce4a9b1c68a91164ea433e8c9f690300c7b769935b0310439d67ba44e52e0fa8f15f69861a717ad7c50071762f67db6abe82cc2efb3a9da702609070922d13c309022faf3f2e4e601aeb38c2e34e86f3da2c682646421e167a0f990a27e67c7799c103338457fac27f8eb5171c574ab3d3989c3514b1b885f10c221acb742e7cba15a005432383653675501d4e5c0f05b2b78dc94e06d911d791c3597a4878f1f2466bd36144e5e3188cc3ec3c9570f81a8b962c73e94e6a764ecb0323e4c090e09612de265e9b9e395d86fbc824cb25576f46f444a1033be12e9594cfc76c132a82ec6e98ceb821e611291bb3dd645b367449d29bfa85dee45389881a02efb454e8c9869b0c5ce49512b24ac3f73a6a612104d4193950ca81c46d46553bc043697c59665b185ec23be33e72f1b6820f6e1d895e0289cf2c7771136c122021c51b59ce9431a35c074a23026edff523d82c9bb19c5544e9c77ac13741adc452a5b7b23e0d4b6171faf60ca252b1ecf5d728ffa7e707bc78d4760175fc270b07dd41b88e237a10ca041e299d4879072596f7c3a78e1c12688085e66b93e2d3cc89619c99b28a65a46933d0e62e9fe422b70530a67086bfd4451f6a898212296b666ccecd5500f4106daa05e3e7c1f4ca40dac84c8c5fb65a3116803a651a2b761113e24608411a33e221681464a6b72225aca4876de70cad5f671588a0e32a87b1195c9d9af7cdb5346394616aab76b201e5b33402660ad77a6e00f20392aa46500d12933bcd96df3448b7fec3d08004b231d2ea70ae863340e2140829176564ad2ea98054236e6c8acca6e1500014903b137ccd06e3e8a710fbf9abebb274bc69daac9a39b32faa2ee64e5733bc04df589e286b84bc8d1b87a1274d60e132390080ba37dcb0b8f1f67654b345429d84b136055310a565a2a6af2daab7b4a3bdd6264232a969ccaf63b7b7e2d61c70e166b7acc79fa4c380cc8dd2f97abd212ed20262a849652fc6519493791998cb3941ad710ca8c584279966e508c3dc210ca55e7d052eb07ed9856e49b403a2641708f2b3863565c514a98bb9af7902171c55a405772ee57dbccddc7c22e99cc940f8308a178c055718db6adca7dd24eec6875e42417a4190d914d119555941270da2bd320c1a54c090bb23269396b4af4c2c3183330c5b51469840126444952b7f873532769a116ce7ddda9d47356167235e6834ef76a8a509b5612b951eb98dce0107db6414ac723c383fe8c6d9633afde69af1c639d2c6f257061d92b0f0e820b78e8b70fd01f3b561e3536e776e4abc26ef97690366724996c113a24858aae813a2a130bd44fbebe8f9819dd0c1245c872d682096a4cdb644dbcea80aa29d8586bfd494c7cc6aa0d97c16d681faba15cb5d7c12a7feb82e236fc8ffcb335928cbff6ec9e9170e3a239f95478430fe52fe3bb3d8248b1a74432274f3e667447e9e234ae1e014863c5a21f6cf4e6cace9aff2f36aec04b407b1214943147fe0631a93c58d7329c7f145862eeb663bab852019a4e67979c0aaa63eed49178549c3c21b45c306bc215b000b977255f8a422e1b1e01316a4249bfa844267133f6a2d296285f1f1666c93a45edec20bb76a944516b5785b1543e49083a84570606b258bd36b7f1d1da64fda5a456538d69920c9078775422822898db91a42c7b8aeb0eb9232257871472796ff42cbd10bd25410929841e43a26bb8c6e977c54b6c41c2ce025269c3ed734d6505e1e1761820bb0859f1117d29718216a26d3ead6add9b5bc25024b5f63dfc10baca5ada81598b100343b3caa751a24879216646069b5e742b1692292c3e8de194ca6deccbc1581abe04003d916bae9376d1df6f81757ae077fb11a866fc60b9e80a0f3d6589de3efda9606636f893b39beb0d0e5dd615aef66db70d91ca71c2c219c2886e6838c0c80cdb46d4df12bd481af94a7ec0d3c2294cc80a4778263fde87ce7baac11fc37ae724d6344f7e55148f35c3414654de8e06e80c29ff94eb821177347932ea528bad86f0157c3c1e9fb6e1da16be60425abba56e730bfa2504a62c42001272d80f10e158851c416cc8695121014a71eb6c1313758549da66121071193c9d8431c00929726f82d846ca4e0c4f7608bd39e38e65fb2ff379a36307b7cce32c9e2ec61ab10782e53228ef99f9c520a5b016cff2c0701083455c977b8057557507cd4fd508a077ec0651f5dd527548e2939be298e6233bfb26376c89a96e6f22a8ea659c682347a0c96edc9244a2249a3c341be432346a66f68f93dcc3e3cb8f408780f11d6b8b5e9866ce75770bac55a49f4fbbe6106c76679409f273890655ec021735f93ea7c525b924924470d2a380b0ac35e8b02823271a863f97b38fd1068b6a8cd67e6655c8cfdb4b5e55bc5755c39a482af539c64814363a1b0804e0c77ea50206a3b1ad62960232bec88a22f24e83a116c05f04dd6dc0aaf554980244e92392e9abf9f76620215cd42c8f2430a4879a539f3ca08b7fae4debc3fbe51e5fe9cefb25373e785072b0d86da235cb28e161c2eed08deaea9c7a7576b11d6731113ceab7be9aacc82efaeeb0c0a71b334c8c2360a0cb99b0e4266c7edcc8c361ac529562e89be663820500e3ce64bce23cc3bd425f13b0507759a439631d011d6cc21eceb002c7e148db683e692b90d0651c89ca6fd153836a0604656a8dc0084eb3ac39742d7c121c39b373ab569bcabbcbb2a7511045c8504188e31f1fc20b72090e8e8b73d2afa4f49a2c7118d6650ab6c3b104c5d9b0975c04e1e774e61eba0cff4ca81370e99bba06adc66e81dac3862e66fe4be49282805dc655be0cc71b9f828723bf0c9c656297ad67ffc75084b9c1192e7d086dbbf9eea58f1f513409734909009091c97843223ae655a0b72132c5f7bcd136024a12e1bb8974de4b0160ea4a6f6cf5bd5bbf8f713089cbb082d1041b9d0aa836636938ff239debd63173ffc0d89f6b2520b175456b3a71130c704e6155e00962ef8bcc39c729576120945970ca367056e64595534e0c821d84c5ed7e3bfd26b4d3461b5ebc8cfe7fc3db5e164c0baf26d86eb5fd9b8dcb4d4f25b3b968478f03af5392f801af3723a608762ea7482b09d3a56552beb117c52aaef5b944f6383e5650af8ee68ba0a4f934ba1113c22fecb2769220576e05bffc5131ddc9e854c699eae93eb6208451fdb82713783a72eac079aea6977b035961f3641c07386646f98bfadc789822138beaf44531fdef08ab2a55cf5d03258e0853f7c4c49e260026fb95a41ed4c5a2f85fc7679eb46312132d6aab80b6163e141f6a2b48b319ba83d08aaf8888ff874e87e9691f18760ebf156e403a031a425978603e046d829c12c06b445c6499bec40f0f88c859b334d0db2686230790f8d94bb080f417583e51172a77aee6cc33e2ff002c6d0422e4fdbd62c22a32ff7da4087026154d884dbbceadad2603df4197e74c912921db3f4d90277ab4783ce71108c0671167e5c93eab4be09030802a336db68dd5c26fcb183d157fd8d5c0ed2d14388b8ac2872482ef5ecc7cb36105a1cc645109837d91872b0b8ce364dece481888fd1b7213f702ccbc17e91497e8ae268679ccd640d5b509bf1a030c9128802c66da888b7a46b1708e605591909321386185b2184361a60fea2ed267491289dae241a5216559cd5eba06085b5cb61f684a231bd1bf8ff352892224b93224a104f16fc221e9fb2c2ed5fd9938349bb5a2e929a47f3614033d5a392e331653cb253343c652eca24bf503822ead70e33e6ffcbccbc608dcdca64bdc0d025031959b2cd132cf049d672b2fbef33117522fbd938b482af261f52c5e72ce54f4fbfb2d6b2669ac223109f4bca1c2ba614eab7c080a57635dfc64bab893d1cfc3ac94b7597f1bcae2859f82a8b632b10aea13b787089a1995c635a015d0186cfa10f1369f7a7feed0228a4d208aa23171877d24b77ffb440bfc87995c631b461bcb1f9bc42228c00d0c40fcac7db415cefb58152c20ab941a765eec0302444b526da15121e6ccbf526d64ad5d88af0ea7c299ff98d9139df7371cc1ceda08b6c125c851b494b2aed0d28f8c1ed0a432c1c24d2a60481196eb8fc6df315828fa7bb3089d0359aff30a28012b83c44dc5ade7010a501fe8b3b81b8d079099a71070b594693ae2f8dd6cb41c19a0d1154dbeff1468f22d84e7a55d94528bf6089cfaa447667e3f4e3634ffb45c39a4d54793273b36d4ae76cde828207e3a3677b0b6d68a6cb7d95aefc2ed8d426772d4d96ba346896c343ee4dea8e87d8972d6877bf6c3c08f018eb0bd9b02e729500efb742915aead894974820d0c5d32e3f18fab0846f4f91f9e938a76b0e80621772c6ac849eeb7d0078c932f03f0142256433c1a53d213dba6354f7e749aef9119337ab0bd279d39814fdd2a2505e2a4ddd75955e419132534930ce026fbbf88c25d9bc68f200a45fe7f4c1a314e6d9276574f552badc3164cd8004a4b8aed5f36993f15b3ebe4d12ca36f3c31acb9b6fe1674db82708bf3363400a1d16010e8068f4bd0337dec292d383ff7e481e9e34859bcb144ca6c39c974ba0921061d88312120e125321fe7643740d3e2a1a665e8d461db94a28e1a05e67a6e73424c50102e034d0de3be44d7fc09cf991426a8ff3942e408193f367b63833e15aa98f5ce0aeadf7557d6da4989d42f42260870a3c546aa35346bc4e53b30e0e7187e491fc9288b8df562cdd01e2022f8453e6e5dcbdeb8d0791378f3af4bcc2b7759815e95c4b6fca31733ee7283d6d8202dbc3abd05ab5fa0782f45ec962b0ced590d2822504ecf18f232a36c1d86ae97a46b345f935269dc7671097d4e42e3b145db93ffd2ae132e447c6383f97978a5ca6e13b00f25ae1326fd00ab536215427dc5c5aa4902b80f8512841df5630394543acbadc8ee1547e9261949db0ef008dbb145f442da081518cbceab58fbfbe5ab2281a340bc43657cc42b2947d8940495c86f06a290e3dec6393e41fd0ae6c99f052d4a5df0e4bc8686d419ca198e62e5d9dded41dcf345560a6f0d3f081192683c46d0dbd88e9eea0642136a15757985133286fe988d4435966be4b82b17ee90ff08549b48d815e9dc01f4d4024a023e61594056daa4030568cf1d9112804cf091fa34b5b068932f27d255b900e20fc1b61beb49f6349b1e72e3030f1719bc40d73374cf46a2b9a10cb4f42a523587f6dbe20529d77037d0b25c2dca989da7d14a42b6dc7b4b99529252ca7606ea05b00548d8739e758ffe80aa29de92ed0a698c89998df163308a8db00669a828e5142aa7971646e1a4a8ed88c9223de5782b5b96a8c73cc8eb8a320f6be6f3975c7835d633134199ad0a42f7dc39e79ce3f80e8bd70379b19960a187897da3e1afb012116afd8bc01c1f85091346dae0f2b913d2e353799f91a2b17caef4b060969991cbf6f3f4613999190bbeae2a503aaef05b93add18e13632c343635bded220f086c9633f65b6db9324c42fa104bd863f9f9e99042dbcb1a0601a158864f288639bc335e0df479602a34027b7c007d1a4208a14fa9041f9813ac57d8a48520509803ec7951a638813d3ee450a27ba173e012363c2147609830b6067f1efc49e457ae067f7eb6865461c2d88b64c912cb95fd2b77af41516b3c9865bd4a22365fd6dc1c0636a9aeeb753fe7ee76efd9df8da48ccc2ad4f4f1e554ab9ef1e5b37523a16496d6cd7bd87a30db8a848d750c41f999ef63c26ea8076e0c2616fe6b3ce0f318d4d5e0ac1be219a8a0897443b6c1a12c3e329699e57c35193fcbec65315be1066d440603323e4343ed5b427f96405852938ff4e1e6934563393439380439a564ee6766e6e6414eca5f5e115c47e6265472c18f38ebdfd8f5321adef68d57666666669679999466c7ccfdae2f924c73c91a51359c5dbfbfb9172692edbe42fbbb351a7f0af30c4c586b3de2b325845a89c921ee65eec9d9b11a2159f7e824cb353ef8a4c976d98e3b63bb5db7a43105db31b627db6a6c6c281b528e1cf6da58af570f1b305683b372d21999238a208419e93a0c212925a5b731c1b61f2ca914725221d8f8d7b1cb92a12d5752e3017ff4822b62b7ad9c94bf4c61fc3044fb225483217f422517fc1d762489ed775d32327d71cd431af8ed959152970b3c1a2090063e9c2cf032f8330a755006d431f62deb7ea600dbf840207d2e620979ebb535065c249952a90d391719e363e1df7cd1c1ba6f3ad63548e3e69c57ec2f59498832146a40c7106b858541dddf2aa8b907e4c5e0ac1bc7e0d30bbbf16aa4bfb89e16dc60bbfb4b8c8f0ffd8ef432c8ddff6e1cc6ffb02349acb347dc25d3d72523c3af26c9f4fdb3deab3199fe7b5992cccba010b75fbe7b8ed27e413bbab50025aeeb64167a68597fbf1c7ed61018c284096303bf93aa9fabec49141e004aaf9348f7ac9756f592a87a7faa40b2de52df0644a368ec5e7688e4e6e8f800b65d570c1cc0ea3018d0cdd6a4578234f0bdde9cce6037ff9bea933596667e401bcbb6a181600fd5c8c6f2fc5bb29c597e12fdc6f2b95e230d083241f99b15848eeab52995f8ad7a33fe59ef57157aed2b56891214d65ae65fc109ad1b6676b66be397c1d9ac2337d3cbf0ac2130b075aa5e24b6df75e51fe84bec87261f03ad127834f001016842dd0381dd806617525cc038843cae186840965f26643d8fc2423d8e04194190c1240464ec40869306c6086ad0030e5da000e8084c04fe616e5c8064163b58022125d18bd4fd32064f081fd865441df1857ac26405a74513e10b04ba6289185da4cc408a1fa4502268b2a1620a25784045075f5cc1627012767aa62980785d8ee86e4f810b0971e7e0eeee3b474876bfa1bbfb67ca257ab096c841774b1a3b0d27fb544fbe8c62acbe7d28c2105e125c05a5a57b727777c99e8319d3093de9ee6e1d749964d00117f4044da028610b21aed8210b332c1268e1431155c4a8010f1cc67309bc988e80af0750670aea490320a2602c4480450e4d2fea63c4cea275627abe70a482070731880098285828e14a0aa6a8428c2abc38420a9c0822038c18b8149f254c469c800026d8c1871b489d1bc824ae274c0508312a09a63d11aa557ac240020e54ec7006efe0c99719214f84d982090f3e2461081e42777777379992cf78c2518085055488f0ae544834594118b1db251943287046e8c2c104e0b0e47a620306602295ca9b881d22fc528d485480464ec8bdbb1b0848d324cf1451c830234a16504411ad38c3860376a8006db1224c9428f88b6e17d48472720d35092239f1815edc508c311e0169da45db083176cc8b4af468e131c6b804d234e7eea28c2ecef04204a48b32e10535acb0a87725c61843f0b18c2d95114a10c6155ec0507152f2928326549084162652f0206710f325c618c798f2689a12318c7185c40d325551e76283fe9080255fcc20020ebe5801451548dc2084df20e5d241145caa0ced4c414116f622c618b5e0e91b2d80a04488f9a131ced643131b53254690439fd2d34e069e206f3e3a30c1142e3ce862045660f0138130450f152a50bc6009260083bbe8eeee36e5c7ddfa6fb9f6b384b9f010750a53c0dd554ad9ddddddcdcc2ca8e0e24b4eca7d6551a3a3d1b0161d37be571a00175096936160e73c23265a507e968fc91d59f84f07d6f00ea4812f9989c6037eef3031f10eeff08eb39799783a4c60139684714c2cf3b0c0c7012cbb607987e5bfd0f2cfb4d99a0ff92f3cc0f5f8d962f300f7027c34f069bc6d8ba46750e81ccb206e91341ef0cfb0f0278c02455e06bd4aa0f180a51004715103cbe97e6cec7b1bfbdee5bbaf66d53de52789aad44e5f9aa5aa1481408eef51d6463d16a3ba2e67f6e7cfbd3266ddc8382d118ba23b24d0f932684d7f595153b3ec2e928c9c5eb44193517a932c851acb29ce67d21664993967ceeb5a0011d886e655c4a4d705200da4b982c2e616545151658716e47ca014cc5d45776c010cea8953d5f3673b5ecd649692f2bfc0a3c97618b19961014243948750fb8d26938094f2b9114bbabbbb9b999999a96867b6b18c820a5a37ddddd463eab1bbbbbbbb9b7dfa79faaa557176733777bb47ef89a393005a37efab6639b981221331324602a78e20e865cb7cdd81dc657e05dee3788080f09e09831ed25104e57f172ee1570616949fe51b824b465e3496af8c2714c408f895d1434d22bf6392fda954d3d432ff6669c0764f1b702d73ff80edb6fd1537f744536d8d87747666eb30b8ff7baf36c02db2a822e5373619c20cd658dfdf24ac29d9f42895a6ca31fe0a73315818d668fa270d89d4020df46215108259fe8a6368e951bed611927236a0b6c53514b2ceb9243ad625d1c1ba2349ba61f2b1d77b4d497b2027bd177d19b45e1d989927a86b0560ae81ed7572521622e3ba785eccdfdddd8cd9d0b17de26e4b085bc76c78b15e25925fd6cebae1fee9b9716666253d96954cb1fc38467e05bc9a2290063e84b09a3efc210d8482ca592403b086b690a4246a88662539344464d402dab648a0e6e9e2121e6666ee2e979c94b95dc9c21c9b99f95f6466666666eeeeee1e4034cf10f1780750b316099778d690185f3eeb86618396eb0d4e369f16b3924d8e03814a797d562ad9d8c4d0a84104d65cb5068944a3d6699ae2bb295ee923b75c45afc99033d9cccc8e1df2e9f3d1333baecc643bb067fdc0420d4833d90e49faa26a336fbeeabdf71e5f231710d8d527ebdae533e9c8f6c8de8c0527575f72527e97e51e2a08d9bae7b70485dfd57e41a17b10c710f8fc5c711872a9d7c8b7fbec7bf79a1b7f63b225ad2227e9e272c94999a77d11543ca79224acc727ec254df2c7c6b885c618493fb329026b622ab5b119954aa22cb3fe27895451da2e10ebefd3594360b01e9b93ee5dc6cf7cdbfa63f7039627bd7e444f8e28c28fe5ca135f0b61f6bc2bf51a7940de3cd63d087aac03c194f75a07db6f5e2f83eeeaaf91cf95f480b8e0d745620de5d1c06f9e2d949ba75db1b779ba5818bf79b8799aa7791e94c805d56407eafe524d2c8ccd33e9f580200e39ecf0039a3d4c989ef925ac8939fdc48449ec590d8831c44a8234f04b2260399d5bc2ef71b1a143f90871292a289f1faa098a8ad20e1d289fb6c51338503e3674d8411dc9133edd01114803ab499660f35b82128132ba642ff2b6959e2aa258ffdb562cfc16ba7b2c33618509cbcd3d961a1202c7e96fb4f1afdbf8b76d7c6e3fac8fb0fda01fdfb51fa38fffda0fd1c718b111e61a8f7e11f61a8f7e0be3c6a37f6215d64fb96d1e37daf6ee697b8a1c3311ca6c322a5ebfeeb7d9d125cb2c8e218c836348bf3f89ab8c652fa46cd079bbf742dd7b6deeb9da2fa8fbc6ae9fab39611c176666666666e6eed6c14333932c123a87b534b611093b07a2e7709368894634a6923ee6d3e8041543ebfd6c546f26a256bd3693086c94d60bc4fa4ff54a29296dad46fe636f45ac4becbe7b741e39bfc192c62dca89aae60c364dccd07eda4ffb693fed676a3169636943030a144e6c96b013efab9110ef1be4aecd61ef9bfdf75c85ce3da123bb27aa9a16911cf767c9cccccc369679d0cc3a15104f25192bdd0d05b74c172e9ab9bb703c724a495b9776c5892b5d2ea08b74e58ae361d2584eca2d45c78e9cecdd3d432e27aa02b2e30839bbbbbb7bd03b5098411939d8c134702cde9c67440cf0bbbb1b7ab7373fb8850ff898beecb90af9212491de7bd2be27851f14ede57c159bfd5776a52f931632cb4983b8eff9bbce775c2f08216ce6e607c1cc18089c80e7ddc7fa167e3ff7f365d773f5a2ee65ab91ef9abdd31a32b2ee1f5b3771c224d620bd5cbd976d35852ce89312c257711e08f7c386d1debcb96e6fefcb6e09de5cab934ec7f14aa3c705287197394cd5a463f362db7cc89faefb5da52f6bcd820de89d9649a4bf72a075bf8037065565c0c25613bf2bc571ad71bb7fecc57b8637ec5858df37ec5666e66feb86ffb9f658c44a1c063123ed8b755b6efcedee97b5fbc2b5756f491b540512009e475600eb10605dbdfdd44b4cbed72f3ffe9d9e7ac9f21f0eeb5af3d13f6192e3bfcad175cd62dbbbf2b2f6a31dfafe0109c16facb91eef7141ed75df5ef6d8ba7f38eef9658f051b482c66acfc4a3e1faede29b68ae34ca8acee63956fdd7beec9971969571e0d84b21999cba6bbbb999979c70f3a2bc306d6888890d223e0c2c420aa2d349a36401069e3a8bd5dbeb6f24bda3bebf83d57f80e0a61f82369ccf78db6dd76dbf90d473f44dfffda0febfb49fdc48b4cb167ddb08bfc2dffe95ff95393bf8ccc0169bd73b4f5b80a33337337172ce7735e989999594eba855e2c67bbf023c4cccc2c677777fba0594ea0eeee66660e02cbf90333f3b39c4098b4b1e4e25c73ce39d78d3b4adadc84107657503d2c5bc7f2573aa450156c8f9df3760f43587eeef125ad63450f16d2252bd8aeecd378c04701073a84bdb459078b1721d0a17a9ea0735eb2d136311bdf1d9b59904824ac02d8a4971bc16c87608809cc7205426376f7be5d1521f81bbfbffbe68fcddf6c377333d7799164dce342ce6454352d51cf8a12593f64006828034343436644eae48ff8fedc7c341f7356b16478363e63d637563db46ea6af22864306db53e34159f5da609b8d3df1062cbf831f68d7b6b96ad79e487a4f2c5e56a0a308dadfdddd73c4c5f4d95872bf32da097e7a3d7ed7ddd33e53a1f40494e5642c26aa9a33b890849cf4875e2ca70b3582b404c18515382092c452aa2845275a2a954a2ca70332c33d3ec2ec830a6335c43f32f9e4ee2e7bbc24ef07a1eeee6666662f8de5135353dddddd56b25053777777b793d2df795b49810c000f94257377773777773777777777b733bbbbb396eeaede91b9c1781302c3c02b90cccc3cdf647e5f2cf3401a58e10f6cc205f248c84372c8635fd0b31a0063a0ea1b8234f07958417a609a68897243132adddddd72522ef4623979c71035d498999959ce2d266d2cbb2483c81200b6df7bedc7f434c618e5aca8f67732b09dfe5943a46dd9eecd4c03283dae59c80959fe796d31e92564619003e3c0f8c0304ea8fb0b8360100c82611c98492f27c4503881e284dae705ddefb9bbbbfb1d49c28dbb4652a1a44703ff7a01cbd956d89b64794563497a6198999999bbbbbbbbab682f424d46395136fe2cbbbbb334960ce6e57b4b24b38a32c6e891a3fb835154cdb9eeeeeeeeeeeeeeee66669f6eddc8772dad85bd230b7a7a8f11632dd424a5fc67b5c6839da5fb3f2b880ee912daa047961e59584ee61f2b1cc85d26874f3098e11231b22381ce9004ddcc3cfb5d4bf3d0dddddd2d279d825e2c2763e00054a094040066099631b3edee9eeda0a2da5dbac7ae0c952099a9ffd1f797a474d9484622f6b6b0d6deedae243e4602ca14ef4142e66ff0619f192b58cee746504103586fc13a8d75cc7a0ad663ac4fad86481614fe45f5d21a55bd998d9fea2d9df05ceb093636366a6b34b7d468b562a726e4cb6870fcd49ba618fb45d9ac581f0935c10403cd8a8ef5bc898a7d6666878c5389bba710f128ad1f2496d580480472a006ca66b21d4a30bb5fb91c78afcdc7002dd0448abd4dbbe2840dacf12ab2e8a415a5a8dba902793db248a005fd19cf72f23811eeef9d75436af759abda45acbba95eb6cdde39bab99211e444b53b3333cf04f10c8442b66099c63256cda9d5d01f4e849c5a0f7ba985d6eb0c8d077c1f415017d3b713e8bb6ae37abdceb28288bc7d047a3eac1ba7ac9b5855a3776cf41426820f637c20298afa988592188ef54968707c29df291a35a216f702f54e23cab7e255a3de67adbf2290f577ce558b72f2ad778f42944f551cd6c31fb9bf3ba4dc7aa1112802595690eb7d5ed07ff4707455b152315e237f389ae412d96e2dac59e9eed05d0992183f66f18fb18bbd23d127b1d0521f7f9e8fd1c38f593c6eb1771481bc277a1781461fb58ca818eb8d4076f4145571fc451f5b14b6ff4eed478d8ff51a19895e747346ee6f89461fb3b81efe6e05113df523cc9df03530fa2860369e06367a91086bf187a3702ce61d8da930ca7af735c6596ec8f431e6632a0ef9a377e70327b63f6a712f60d60b1dbdff84d68d5ef4d787ecfc1ed5eb78b2a3bfce07b69f62b2f118fd09588334231ba2a825be55a316d7e3276a8111889ab066a35bd9013b7d0567d4028d5c230dc8883f252bcef4f1a9970c881456e5cb7cc84e1fb1698a51cbe3a1cfc61730f66dc332441096882fb6641b16228eb0433cb102b00d4b14285decb439fec732145b00dbb04c09c3629992c556d6fd8ee5aa3d1fd4a2be7d35e1cff97ac9137a4f64d150596759416e3c7c9e9a9d7476a675f37ea07533d522d0468dcfaa0abbf1a4136c7c8d8f79eee1f4ac03a70702a79c87e18c2699afa68975a6af1e94a97e7a20efb91c5fd5fbece87354de81f0afab1527fee8497fe5097fa90d068cea745fc5317a5804d2f4f70a9fc23f0ad88b70fc45830142dcbf770f7faa1e08b45ee8f40effc6b482e4f857e5805f4485bfd2e2f8f66a7060f5bffe0af5cab7029ca8a9e6f8a934bdcfb1820a5584424d41fec4b623b7a3db01f7defbaa55eda6c94dcf3a4c0cc55eff9c8773e393d8875d685da5f37ce8e05e700f2f3fb1d727208f2d1aeeb337deedd80b9fadfe4e53bdbc63bdc6e47eaa38ef6ffc346b4c35268710362137fedd9c86d875f606db88bd77160d6ddf8f6ee8e07ab88f56901b5fbd63ef65b0f90e73eb6f60cde2c0ee63cdeabcac3f857a25a95e8942bdf4847aa9a85e928d7a4957bd5fa3de2ca6de8cd24855d439e762c5a17e7a473d6d817be1ba7bf08dde1b559ceae34fef5f41e71cf5137d87d18a437efcfafd45604dad7d5b1000fe7efd4b62e12f9df9ae4ee767aa6c166a83b53638bdb375d5c76abdd0eb3f3f5a41dce354a3778b8669dd3b9deadbd53baa42d6bfabca5f875be05e68767ef30ec6cd4e58bb95b70396fa8ae7344d0ca86ae51e7ca2fb014bfd845154956c25e6b805ae8777c5713c2a3c15a218c1c57bfd9e115b8c08c288277600b661a1f2e5bdf7a2f7a27ed17bd11375fc07ada82d1994587b5bbdeca2f62217895cd45ee4a2f6221cb6ee0efda1a81e81f3afe8db379148d43deb15bdc8fafe9bd376f48ee32fbd8657d2a5fb5f3ebd1c5551a53c06a358836d67bd4aa86b8a9e8401123e3600b6614142075b8ddaf3317dc5cc38d71f7e12f667aef8ab23d05e675dd47fe18e7df2813ce8e4a7afaaf9b1aa6255dde92786437db30ebbd0c6b72e5b37fd8c3f2f7c62eff439efa6aa47a0ad6e128b339ffa2bed1dbdcb69e76abc73f5beea6f4ebbbfb01a188534ee69383789eecb71b4e63c5b517f4735e7d9e85e54af55739e9d554eff9ec2a013d763aab15e776f93b092d18b3b5482a8f4d86ac44060c3dee73ceb2a874d51c266b66199a203151eabc3362c4580b155bbb46129e28b25806d588a9862ab56f1bcae5e254892bcef0b02ebbe6b831662384790d8fe661b76211421d0f2bb23d0769b6acebb70c75a51fe55effcea658cf16b60edaaf16d6014d244d15b396ff4570dac411a1a58830d62ed65a36ad587592f74d6fe5751ef4160c5a1ea757d73daba7f93fc9bf31e17d6897b21561cf7fefd5eeba4615aaed73dacd089ebf1ea95a4958c9efb5041eed2e213db2fad2c68b316161487bfeda5d33a713da2cb9f813bf6e63c1ba47980362c5280480d8b941febec834e5c8f7e67c50a75b027c4962b7402ed0c2a1ced71c8e0acab479c75f6d991d5ea03aa3673a96b3f468dc77b3743d59a8ff70c5f90aab51af85a6bef5e92e726f0de7b0f42c8950ae62e0d039d73a8146d5aa872a788060000080083160000180808844282f19024a931e37d14000d6a8a465c4830140c23922409521845318c32c6104000208610631052101d07f36a525cda76f6833a87e4ff3e405b5ca6ff8147162a2ae847b235868e6c6b3c1e80bd0d9551084c2dfc1cadb00faa9cbc93a82e8d640c66d260e544d97e88ba32fee1282b491ed31a7046de09a098fa83c3d12b752b570acdced491e333bba026762e6b2d7cc199d0f835432041aab2dddb6363fa72796451bdebb1a5b6dd99421f5c81c9636cb3b2ef44df5ca0652487ff57872bcdae7df5cdebf645e8e456c4bde46234b1e3098df2a7b80b88b5013bd1e1de6c4e50ec8b913c809b53d2ce29be28072133f8d08c4f9381335253108b05f15a8ce01b5c53210b41334c2be26b4e194f268c7694b1b04e986496e801b1a53d705ed47eda370ee10c71a7fe1234089ea5c849768a1fed418288c2f352a4bd4c52710b2b97625d8195b0732fd8dbb166f82a700867f721b89b14d988d9c5c5c5a07a15abffe51b5153ff64fd98f5183e04bfdf77ac527b3497e25ec2eaff51f851c07f52f42124e4546358f5f2fb62aca0133a0028ce3cebd5f063b21d5b9377d62ea89f1d8a01a5e8b66cf205fb605cf4323b3247a157d3eeff2b698bb8f7da9fd1748d56ee0d435042eb1089e57f57030d9ed5d86551c1b2e1dd7bc1d3cc5966748f4d4cfe51fcb078adae8b757d0d8c5a32a547454467a1b45443bb7216172eceb8645e7d6f7d51c438553cc978cc33b6468a5240e9fb55cee34a6153e8c689eed18ecff4298cbc7073644fc32febb0fbdeafa4cf9883b5c1d4c01022561aefab1057dce53a1b69d97d8393e86a48e6fc444562a4deb8e14ddb078f08964e5ffd37629c75c25dd98838d50f075ab48cf2bcfcb5e5cc7380e0d818f132b1471fff63b8c86373cf3a74851801d82c0f2f8a9bb7268d18b5645861edf1425a3758b934bbc483ed352c89fff1426f117be779b1c8cd30e863912b36b0ee17ca5d483198eca501289f0438649ca5a12431aed0a1e8abc1a4c72b997c2b3cb2ef7336459568d36d77c7fd8036713dbcaddd545657c227b23730011fc3c5b2d8e094fbf3931b086aca6901670218a0884968dcf3fd3d70bf4e6a481de3a57cd411ba3b08693f42f169a2104da1a807e1714aadfe6f295c9adbb118a7fbd294f7d0de8fb6d771af8e04753dd1d5f375539a41ec4d0729044912f432caab7a5ee893024806b72dd43bd7e14b40aebc2b1906d2e0e14ee06a6156690062be4733c6ef525e632f8030435f2b0a49bc91e46a8100448a180a3166a708d664f5b0a6e824b2c351e5d8e70f07ff9e0fcb9667d41647d92bf3d528eabc4ef69b80a1b855bfa367fb765e50985d29d6a9f640c50a7e3b0d503c9aacbeac4e17cc85c5659821ccdafd12de63abf43397b70dfce2595f1dec2854a1ff1651ecf8bada494025434ac41922ea61584c37d134951cc715f96b56b8f8693abb8976080701043ba38f5a1094ea8b9771b1b9bc0496db7d6fdb16464bfbba1c80c6ad1db4e263d6a8d60c6fe1169a3dd716df6654ab6c194315148984b25f9358211c9676ec116f873d0a2c153502dc2a162d1e0f0482a796db49ef52d8069d6970a1b543c9bcf8cbf90dc20b6a3f3307a98ed7058a1e9ac1820be1821171e0c6fcd0772362aa8a8276f9d6b3da1901bb9328918202511b8fd59f51a7b6a7f38bc6b02fa3c69c3a8fea3eef508c7a5eb86e343a4c463d9042eaaccc493a872648bc18ec398e5614ad811f0db7e87cb574548787b29c6743045900694e24c117884bfa6fddd5de2e0378fa7d88d028a87be7e228ecf6b2a39aa5c12e911020589db15f8be64db95b71bf0c4756775b239b787ecba9a8371518442569b505e63227f5db5eb0cd2916573ddcd7de0afd6902ad3ae8aad4dc33350eca218be0a4a30bed231e88011a2c3e0f35c53276818983c688d2a8ba498f3c1d11b93a237ff16d955edc002526428031d2f689c4e22cb8533c929dbeee9f5b88101c6331f2cb986b24ced3444dc88a24677661af615482a63d6917951b1c08c0ac9120fa09b32e161ba8eaed15c7e3d4b3521b02476805a23df89bb8b703cf47f0e5d0a8a417f76c41191ec6f8a340a2e4df51084aebe051df8d9d4bb5f44e2eb3518e7c2030ede6c2ecc3a0da05eb38b467f22d1f9b381a237c37243b7b1dc0759f317588e823e994e5151a7c0768fbe8870ff0ba8e0fe6961ddbaf1f118332fb5a9de6e5671f87c24cc1bc73dacbc0bab5b6a1dc2bda45759de22e5d10cd6fa78e2ded304e2a288387ed3b51c95178cc0a06fde85150036640200007c581cfcc9eb68f704155bfc832a3b462e94076370f2799d75a8c917700194dc5b184644aa8f091c417e7d0771758b685621f7e516596840e8b836e8453e8f8c376d660c0bdd0d2706085750a2229e966b3f36ea71afe0f6eaf2b50a6564b9397e4cd32a8ded66d89a17b9e601fe43568b1faee63f128281c49c6b3caaaab67b276173d058e578ccbfb3384b9597123aeea4592d85e3fb83b7d5b54f614a89d279fbeee00ab515c144b08e29337cf51f3e275641363bb1c4738919945332bfaf2ed61a03186876713f02ada1df41d798ab793bd2541b52d41a009862b53767ead53e6eee18535c65d01d1422f6509a599a72ac7ed80c94dbbd73930859e187aa9c1a4403a338064758b76241388eb7619c352fa0ce999c0d62db27fe2961c306c1422f17eaf7166e91355e2aab9e68fe25d04bfc9591db373fc12e55ed99dbd6c433dc7c170db92f65c8ed2c540438f26b6a77b7f7a049b63366d78af1bff0f418f1105bdae699ae84c2254af9d81671595f23bf62a54eff2b40075df837807c8f428705332427c5cad915d60e03c1b9f0d57f6a5ade305add67c02116bcc39be75e09fa0a8fdee7a050901c1bdc18b5c188236a3fad2656926754e89ae2d4077f54faadd29b25eca800052d284a8b314e652c4fb0fc130c7c8c8603edc9d5790aceb3f64ccab86772401a019b7de4524e654aa8289d77a9faa0e2a0873b4d1bb6d4bb2b152b6e963f24e0700fa62743fcda5a5742ec6407ec4614a292bce57b02a4608ecb483ec38d243d99e095872297af9e19a9046da6ef416c6d4ce7ab494e18eec3b8f9360e1bd4062a343dfda09445323dd4cea18b92f462b38fb3f039b8a6494e040c83cbf6229be1d58148c641ae960f18969dfa0dd463e8f44716af7642d7d72b1f3423aee8faeb671e61d49e57c084e3035b3ecb05be6077cd748b4eb0273c0b04140d10ee120ea5ee235f21c01f84b89a1a18baead5d875f149d70484f01257dc522cc7172d185341dc5205c9150efd1154f529166b8a2b5363a8ee430cf8bc509116a26d0a1171d157488e6d58a43e3101a948f37469414839154473bd45c251b1e7f6b7b64534aa41f34a01d11e36f7c9531a11445511cb41481ab85bd6e9ca83cd0aeb5502aa2ca0c80b4adc38a4ebff4d33d827824b84a58c606f62dd38aeee14bf1f452449a6e3d8ef3f321f141af4c26332964d95daa64d2c82ca8ff919aae5527ab394ddfbd455806614a91c37727f0f35a34880d8e0c11c54a6e72bdfb68b975fe241cc40a704c4dfbe11784d0812837666a8fcca22e63e9068e9034f7651a7fcbac79782e3ed79ac6e0715e4fbc1dbc67e81c94e6522692dfedbd3dd3ba712e5aa7501957891354df1bb7a045ec0463dccc23f8086bf46b08f12fe18b9b5b042b2989bf4a37e5c73a25ff4e59e91a66a665573506196329ae472bc9cc032dcb2eaab4d1994a8308520c535fcd2a345285bb25c184fc6aed6824b1a0bee446b92ad25f44c055c38f74e486c32f83bca7c809710575fd882517cf70c09c9ff99b017e50a2670c84e068fda2b5bb93e89875a53411e2254d940d074ee1ea507cd6ec02fc0e073bbaa4fc32f4e8eb25bd5bf394b671d8aa74094c505e686bbfaf9bd0f13ccaffd1c1e7c8cb08ebcdde8663882675c9a9c2434b48fe43914c702f800ae8cb50fe13f107ec9901bb23b3182e8842fda6b972b8ae095e89bec34b68d7a0588a98e26f2b2cbd536449e9af0debec463133e1f1f90d800758a32618a339b081bf973ec0e908aaa2633ec07092d9baf9875fcd019aaf7052e79ae491d25ad053dc1a959ba65e2b928d30e5c6207d0cfd496eb76297a6b216d4980d119d6ce31306015006521ba7a108b068811db4c1de0f1bee778780a3b80a270e8e28cfdf2c8c827ff9a2b6f52b9ebab5a8be4af5c45460da3cba7e25002123cfb522631a8dc828b39790f0019d7169d90a1cf1caa7b853a0e880337172bb00598977e1a13180e7f418336b5cb7eae541e8cf1b7540d7686139a439793c57400703fa3fb3238bd7302b6e4b52d55e3f0416edc6faa116f2beb75d17aa7e694fdeddbd7e3c16ea6385f50d08894783faae27826e84e076e43c858d8643740dab7f70f00bbd608d8aae40121e81e34840f40067a244b4d2712848d039275771790f17fb2330e80522c1a1ab40ee43762c4c2ba387da1ea2146dcfe5e091902af75988bc1907596c8b59363b848cbd999f7ffc7a7d98bdb46e87d54467c6615f1078e4a2b78a151c420d727c7e6579c2fecfd9990e04c106c60dac3cfde03a27036d0d1858715fc6ea581c75c53ed7105d4a6ff260d88f21a03b4a9ed3361549ec19d0cccb93e87a04ad0fb188a35b3ba25d8b700b4861a6af32f6f7bf2015d5fdb506eb9484aef16f08a1f3bc881ed03122968fa130dc73ac4fd123457307e84c94346c5c6e18947c14924a1a6e5ef303bfee0634445e08d90acb6de5e5f5412284f568653e46fad9449c64fcd295a166fbda95d7eb408653ae6ee44b1ade89a0279bbef752eb7fd47d2568a19c2ebdeaf4c0fa8f6b76edbee727df7818a4a743a7649d8ffb7b9fa33fd3de70499c9da35250315bac60c9a298e76069b9c2e928b2d875e6122400323df30533f432077ce8db4e502b560c1e46b36a7604a180817918294a9c7515915326a77be53932edeedb8157cf08b53b60c5f8d27701e6fa53eb3d98e4c17640db818d0606e5a2725a7f56b19428151f6c9a51b8531e9088f38329973c6e6dc3a8115ea8860ce2e6523403e6335985de31dfc63957c57743372f0de9826906f1c94dbc3d9642d8e06cecebc6436622a50fdb5bde07c00025f03b98f00aaa16e8f153839caced58e9a28bdb6271cbe0c2ae33454b7992c8ac11f88bb91959077d6f3bfa863fcbe86ca6467585024322802b461aa671adc8e159f88c0d622b12a40a0c2d540abb620e7dc5fd8b11405af21ae7d065d1ae8f8f7ac64d9d3bc28a96174d34db59709d6f17b260d0e0a0ea2259cb9a8f91f396caefaaa1c12337b30a66c7b30fdacde1a3e2f859e2c452b8e860935a2da7bebd0323074ffda3a0a28a270e760d9312a0a0e6e19bef5681ae3cec3d24e33641896e08283e6eb707d2bd33f128cefd6730020cc68f9e47b405f2a282df012bd10fcbc67066d5ec9076d9b507371f63f52395cc6577c4cfeeac4c8adddfcb6c10bffa85989a2de370c9ecf2f8a1228d750da8fd45b1666c0311ec948245154b5185d6e8d8f18c68cbecaec76613e670db01854518e7476f1505cd128d5b44d811c5613a80c16ad1af20fdb098e94466b47e414f0fa7d486a7d183cc49b53e66e9a06dc7d2098ab08506626a19c027f076fe4cf5bab14556b56011ff18ffbf0489cae60323a49ae2ff2a4a5672f2f2c04d72e7a45ec30fc9523cbac4e57459668e870f9a91d0c3e6fced15f5e9dcd843a4d32cf0790497df230c05ff39b1ffe8662cdd9376644d3a18c272c13682d06af5b4e6922b9e97fe16a39efd120fc285da3602a7cc2d4cad7e186c829ad945452c859b9940a805fd6d63d8e592508e35c14a55f3dc10fd44659488f972ba50ca4d4fd99a1b55bff427c8c9fdc8c805f9048b15fe79c79054e54de102f1808a8e0c2139ac649b38505acecb79903d1b327573d2ec021f1f7c4e78c4dd8174315e9a8d00ef90ce45a8b014a5899a782b7be3857f07cd7fb6994a3987c0d452fb63a3d42b71dfbbbebbe394b90dd8ddba65c3f0b00a2ae8ab4a9ede564f69ee85c300e68b92d3313d5af261be446292850446af2ad9f2418ffb6ba3a268fccb564efec9bf416b74d0f49a42a355b200567bb0e7af7b0341a888813fd30a44d183a7b5afb869652de574777a52147fe3254592f4b5424f9015992612ab933a447964a71a897c1677a0d5c030d10481b210ddf1f5790f88fdea3fe1b1c964d8642d90ac67ffd613075b0511bfa65ad0ac8572578e706aab1d0a85802de6f2bd181d55d91abeaa54e6009f1129f2123f530111ebc4f0cfee23bc5d1e9b85ca335a024687db174893d47a3ab5cbc63ba63de460983b0c72a09e937d8603ec2034827caeb01ada8bf68e0fb7552b5c1f4966fba2c4c7aa4016fb50ac7eae5a59453d7296e75e9054ae38f3755110c338d109434d86c36dc8dfea4029488ebd06b6ee7a7cf40a53b06fd785ee7109059a31ace039ccf5e440b7b52a5695f006c8c95c5362788e62adbb8f105205ad8703ab3debe163f4a8a61902be91354a625124cffcb22ca090593f5e08c937c1ecc4e1bdb78f5504cc4f934bb7b78195ef0aa07c19287e8435a56bfcc115f78692e4bc790275fbdee1c8ab3ec7b98861b6700a0591899ece597fad9b871cc252dea684d7a6801b81d1100c091e2330a9e2b0d460dbc0cc612cd519c0ed87ee541e29a5c3ddb142903909d36c172d85268fcbaf1468fd27db30b882ddfb06a50d75c1e351ac13282a97d2b8d258f28cd7d1c0a202a1716578c1516b25050eba36d163f6a3590f01533856e5a66fe4a208571d2dc2c774711be4557608746e56a105571409ec112c0f13608010d7ba789695e795196959968c8cfeac8efff2625bc3a17ca33b0811511aaf213ae513a2a554496b9918a76c13d9dcf93fbc30ad034e4073138e84870fe6cc5372e485cf9e7c8c5c0ef114e28b0959e206df908cb2f69166ca623a540092220e9354a886e2cb0440208abf8c4be2791cc491fd8785c622832daa6cb207c6f520d05dc82c1a92ad18af803c1530e3bb0d65488e2f2ab3b9a33868a82e949bbe378a939ccd7f16289127b5a81c29ff88cda2d91b8f923f8c908042faccdbf3efd7f13adbe18e505b945d2d23a6b0bc23a63020c920d5ce36e6609190151a7c901ff7f8ad3ed744ebb8118a353378b959f025cf7abab48e81f83c2971b97d418672df9ba9f0b6c8d8d34fd285f8d256d22ac660e0081639c1133ea7e7d3d76ddbe8c36ef3684165b4db8674b7698a376a20795401e2e141f884712a7102fa553545c73bba36991a7afe5012d858d6a7fcee55c7068161de500f384f6330abf0de7adcf927ea3bf090978e55045eb9e5bc1fe394ec0af31788c1f210d880a94abf08dbf30de99aff1e6d10f2153cda92741af7cd0c569a2c1d7c7556b42496c5a543751dcfa8c2f8d801436380769fd453b084882ed318562347717072c68e0434dd84e42776d8424bb3a83a49831c26b0f65a32d13f1030ce083f557447735f572825476ab04d48bc55ead286d3279521079879d2e5f29d8196c0a97014fad16ee4940fe71afb19f11e01a8df3ea2265fe42dbfdda51c7d08e48c0bcefd3f42405f8e087875e40738c1a6ce6b95648a120e03b21cd5944d019e1032d915cb838a58c7ae0e41d6201c1593d8be5fcd1a07d043b763b0493d22108f758c8540d2f7a3d04cd151fc51b281a3a1cf57a7080947f10773351ca0aa6818a48a40cb1d9db4c20e0413b10c4a7bc3b31f218d5ee0c4e8764c7ed3d0623f8e6542d0d92b4c27e67e043d0a143c8b0fdc1260b6b9f4631c39ad48eec35318ba0781321cc449bbef00db253054e397e62961c03b03a619a8c27a4147219e0c19b359f1ed06457f20e7e57e1e881bc47a289163ae63053d1aa1f624bc094238b96dfe4a6a36ebef02cc51a4412480b81718d48466d44c1d284166bbe35803581a449696b1db2eb05ac1adb83a41e1d4c475b7b2e9e4600d366166568cfe21072d2c9ea363555395913ddb9c2f63aa5e2321aaf71db0db4afc5c71402cd29d4ff7ac5d959848ea858090a0b72c70702a37727d6573d6960c928ed0135146f6c1da3b1aa7bde82235db7125d4114efd6dff72ef9b560940cf2f6711666a8614ef573572ab3c90d2d7ff761156bbaa6cb1820f03baa2bfdbb9d33ab69c8d3eb7a50c862b88d1de38ecda5c06de0e75cc40adbc9d47140fff4c6b7594c2aa7a89a4e207fa4c1eaa7b2934d68ecbf17d17bd0cb51bea793ae65af27a97c01b5a45ef8cd7e0160b56dc6a7f7b9d5b29b72d06c54eb0fababa570fd7f41aa60174f6d6350239240216488dc756124b6f2ae1e0729e3aa9726943b286b6a6331763865a54e11c48ccf85a26002070a90b4f506c16851cb76a30cc969a4088c1d2a63378a1f7155b2d2cadd1b559780e70a3f4fa1a170d828edbd6661db80e17524eb5d253cb800dbbcc021b1ad225c30a6ccce4e2ae72cb3088b686741f0dc3d673131336d45d172c161722b0a3dd0aa912bf8cb009ba09ea1a81087f25a796db497c6d6ba2d91de941c2b9992d07f274a36d5c40fa2f0e0e69d34520ebe13d27b2a17d9de424493e4edc8a2e4767a78a4e227c0c99679b0f9d63926f6090732ac2c7edddb4ca8d3f5b41d9489884cf79d059ee24001c5860810da49194d8879c047bd606c3c7f70813c9333f3a618c74cee5078e250586b6933da4377f0b51704ae16762ddf52592dbca0f62ff6b80a03b0ffebd7a39472af8af96feeb628e56f2a6ab2bf71f9c750a6b96b49f410d043d9da4d596ea6ac0592f076a5c5181d7443c39ef045476f74d07960593883107f036c09f10383b98b3cb00fff8bd0b6ef8343d3581dcc45f56b1ea1e54f5aef1073995a02a69de1820e06494bcc9f9554ba5a469b3fa1c00b77b0839ac08cf52c3de4a4ef9844bdd7a342d27854cb20d67b03041c7f79fc649b0f5a81c083ff586cac7237e3ebe035f5a9103ef10bfa09e81ff832b80a4479056154e8cc9b06493cec914cdb66833028fff31de86b834545fef14271e3d30c489cc83218381c5d672fa4714a8b1e380e947d1cd64814238ec862a870bd8de5223979bba0c74e485d9d11a3752fc5b9e1fe207b41eccc46acd9f97cb0561896df97217ec8bf8d750a38e7f1ab0057a5c62eaf2e1eb4103d90608ff34945ed7a6e941516d277e278bfaff87f41646ec0cabb95257980cded5ebbb8cfe734da1cd8bfa5999c43352248933eb67368d690655091c746ea757305f6c764e01f5b6788661c58400ef3597952438547f91576800f023289fe0985e874c7900356b7984d26f21e11e11f47352d564c806d75cde7beab408554de0f29b9acea0dd9cb71609c986d3807e87eaacfcb4ede9e7d737e24b6e03c1b0f754e041f5629500f40e5cddc836c4af7383540c7d29eae388b721b15d490e72cf9464c90cb353f3eea0f8fb8c1bb52affdff3e06f10dacd014a78c8fac9cb862899edf663514e8106f001fd3ef92a58c6c09564c15a07e3e0cfc896659f04656014760d787547446bc56ba2930145b1779611fe55588ca1414db3c828936004fc4884788685694b6e745b89bb499f8e4042b7f9d5827a547614efbbabcb51bbc26008fadd7507d3a35ad6bec76b246796795a0715ecd445207c29233d25fce3aa8f51bd706fb728180980d8f017028b2e8b1cad70c5d1f1782e3605cd88476736e168a04e1be77268116d10e7b2f53c1157bbe4b7829ef86f21f916942e98fce7d12f7afbc80fb515d7acaf775cba1bddb5c4e951e9bd8a8e9afcb618a379e19ae92359088cb7236955cd20cab06c41f8cc46d79fb0fb3371b1daf7a70f9785921d31b11e50331eb2444afa7740e0211c22c67fb48421eb5a319f301a152825eb06a0ad218d460c27bdd93a7776297afe638cd49200244cd10faca433ead78af044a6047e2f6ee9c876b25a041b84f5c0e288fadc99417fbf536af3394bd6f325d6d9901b16dde08d732efe5e174b018729fdcbab7253fb7fbe09b0090f6c9f8739a21e0f42b4a5af8a11c52306c8304657bd7312a4cdfc46eb2ab0f5f6bf761556bbfda86837fc3bb999ab89f10a8be58dbcc8e794d37ca91a8008093c4efc05f8fe491cdbfd7a1b62dcfddbaecc291661a4576f1cf4e97d700c1161e9ab2e310a570bdee4ddeca2954a58ee905bfeb8a90fe1f6b639e1bbff8cdacb0f8155a1b9fca187e44416df75f94879f8f27e9d9a308d2d06f08a41cb15ec96ca623ab094c2e9531802d101c4d48f63033f347ca3656c0129bb3ea60850dfa9e411ad362284f75225f881794bb663beb9bfa4b980019963dee1d6efa6fdf1cd86f136d80dea0c9d0a939518a330c60461e590186c57b51fde283d30f9b42b1b14146d11eba2846f6d3fe13e32585260f10ad3ef77dbe51d947696f3721df4f52f34b930defe50347d6f16f8131445a92091389aaf760e1811d94e43617c298fccf263580dd5de2ca5cfdf2f52a2b6330626e63afaaa8bd1a38cfc5070678e6e4a8dcf776de8ae6c9e7a053b5710ba205c37a1d1209d492868048541da5b7d6b5595720bf7147106931a4b8e818215010976bf6f52c3a65e83e1258601b9dc19692188537683066c410b2243a0ccbea0953b7866df2341fdc2edb6028d14d1fcc29270a1f5ac2f15ea40c20f33013681f75f05a5bf86c902570c2a2acba15de8875fcd397a0c7011cf5ebae802fbc59f278b7f27b96e5126af88c5914806d579075b4f61a2315ef495d46c496379e4486e07686554bac8c5efcf7eafaeb32d09efa08ac83adf7fdac520ff349e235f2de6ed6d3650f6390e74de79130a562fa53ef23e771d3b3249ab51cad6832c45a04ec50f362dc00ae353d4722e06d8f86b258b7b0f8c48a523f60185eea692386209d523e64c50a2bd6389c00a695d37c94fbea37c194e8c646e65c87721ca64ab01209b0404df438f2b535b972e4b2bee3233e4800db3f690a5af630861578a96ade9ff28e5e0379348bf1b78e7963cf9badc6082215c9b90ea2c4dd65e7c146cc0020990102b4df4c28e2e903a87c94573914e4c1542624b08b9850c24f4fa04dba9921a48876592800db17bfc93328636ba95934e96545b528a099dbd90d98aad25b7d55d0027cb12c3fd860514096bd3fd10924eb9ebc76c5a0d89a0c3a59573a74a9358d311f3fc18e794220762e197edf43f5b55a08502945e22bb64a04677abab6742ec045c7eef5d9f023f79b0ed73dc6a3eb3c9ee994fd582f0c0e2cda8af7780901bf89460109c957527d60321bd690a7aa6866b6a7d17a74f2737fd4b3e4b9be6593278b6087d8c5991dc35f0430d49ca006534c2de610eccec78a00f0dfea3121cc91fc8833bad69e9ea11bca6e281e4b00fb28f3e386cf9e4ca9bc324d5976d732d068662525f1a59d467ad62401a65a9d6033bf29d6fb57f67b19003a03f815f95ba582890589ea5c2603b13d5610857a66031fd12c2c16f405e5c22e16f669d98827ee5df5bd474f5ccaf70f0abc1aeb55b1b5cbb231a0ba8f4662b6d622d30de2eb3919d6e8a542276444b674b14da542d9f0ca5fda484c1d65479a001317a0667d130d74ad35f1a6994d96ee4f6521b408b858d7faa33479272b9a7bfe952da009e55fb246f4ccc91a290f824e4007d71906885e7767c918983dc9121a8c7fa31df3fe7134f4c574769aa92a228a161c47f52977cf7d43a0f4b8418c20b2057dad18f7e73a6006e45f95ee8f0668294a9ac8b71d51a1f2d8763bb89029996c0baf47e1df20e67034bb1358088ab0b2af0e816229fd51d36f64bd11f2810d8182b7c59137329efeffdf268cf93bf5c7563a0227a1fd2a141e332a78d58d18a71ef8308dfb8e04a14d4c768602f50171e2631bc000bd3fc0dd56c5b7c879e0c4c0c14d7b928417dc87e0be4aa34a4461f0294cbb70d9e75a26c8bbabfe9cb745522c7355f0672b9067c8789f66048b88e13e5d833869e07c18f837057228c1f121dd22ef7f9cee33c6d52ddf13133c82ef89fbe658706d071f612cfeac7993de28053d9aedb529d1c54342374be4506fb4a9f1b7d3af71425206860023a3a6e3f280aba3fec42b5ab10831205d0246c1cf0ebf039d4d1aee40c6802ba34f558627d6af9ff5bbca31014e0b48183f1ac40feb5fcd63b6e6ef70ca8c4ec4ab6a7d28432237fdca6e426b5a787eb9069dd98440bec27d06f0cde99ead295ed872659e3fe3db8b3a8fc425fc557b112b11552728481c52603aed4929d2b1706144d0028b73d0cd98183c09b6e31b027aba0f1c6a593a4e4d46ade17b664c0d826094cefbe99276ec92ff721524ae689a933ac4014a2fb89c4f92f3f633d4e5bf4238a7bea76622778a97638d08009020152c0e290819d42118310030090b1f8c8eac8476f445f72c09b82043eec9b81b4faa8d838c06ab9c4e7578513f7c203781edccb25d8948dcc5d5165c9ee90cf4b0c6a8238f4efd5711392a97fa1125aee05909f80c5ed94c251052c816334e58a5cdbf67d8118f49c15bfb00803a0694cde08d29931797dcfa09d4cbcc393011af2c37ce134bbe8daef2096d19a8002f86e823720fb200b69af40735f588b42c85d2cecd4dbacd25a124f166f142d94cb2a600b9202c1686e8c28e57884d268209f185d9134ab9a1afce693dbc58585abf5d6435c98b4c4a172ae313dc3f5dd606a927ce3091f08530b0da68c5f1b8de90c0c5fe1c27fec2722a5d546511b394232e74046a0500b31aa438ba4f23cb48df590d388c2ab0e2d1fbedbad31d29d5e77a832f6bb222dee79fbe81e8c95c3ea6f917f0429e611dd89aa4c0735673bb68b264fdf180f2f0bdf50100956d3d071c4f0ebd9d68157ade97eb697244020570248b2c48f0ef9077715302f8014f85c8614b8fb3a5edc56d1aaf05064e69b43eab7138241103cd529800e9909c12ffc1fa82af7bd764964d2376acc8eb4b3e32ce0c35d714aa28c09535c527aea7581514cb2120719af385e7654061b365c796df8e714d4b8b8d79c9db5e2701478f4fad6580d5843ca7429d652e753d0c1344fb19e5b422bf7adfebf626a9c65e800ad1e6548284b096c692ed1144c5d88c663143a320dfb59856559a9384b2fcfac1b73dcf580082cbbe7917c5b935ded98d45404c4a0c6ee93f470fc2a2bb9c6248e0509771798cdd023b1ed2bfe02dfa31ad1e70881f3c7209404f6d4245f2f39dd71c95b9a11e659e4d7bd6984021b21c950a8f4890cf689dfcad99257750be0b9fbb6a127d001493cb959c7ecd80f54e37484f0da000bb3cda89f59bc80968339b3015fb23413abe72b6747c87d86c98d9a995b438796d1e0ba4992bfd887397032c81ebb3eb4fa977ac3bd06f60586e1c8ffba0e933835603f91d326264ecd35c0a1f591a0743b88e08be2944e8231139f0ef65b962a50a59138453be4a73e945b53cf63140f4918fe81f15bdf352446d9628f81ec80a66755f45df32e2ae8684f190762ca45f2b9b001570f6854696d8b9955775003fd619c3698a3fc30418e0271868c4d34456aabe2bbad348f3ca38009687130149990e3477c27c97c93dae522f911f6a674cf7de3f8bb635b7d2b76b0a78537e86a03aae1705ffcfdccc562b2ff9fc47a7962ca24a328dee7c49076a34fc36bb7348bed581a94bf29896d018a39979905590a69cc57bdc8ea2d3dbb027670f35237267aab63e664fd09945b4353985c7731177eb5cf7357296c3e10e6f2120cfd9307ae06344c53fb8d1209a91c81a60fc591c4bf211d23c80f6cb22099a92ec438cb41f36bbdb0b1a8001576f66aee22a0e69ad535001456eff2d07f846bdccb5158dede05067eba8505bddc7cff614b321398e7f1570e9f27bb65594de3bc238596893d962b7e1d5dc9ff3d47833bd8d8a274c82243e089817176f177737788c61dd6be2c774b2d3beded655f6e9a91dfed754e44cd285c8a0a2722abfd3908440742a04d79ebbeb09271dc9c30be8c55819d972d0c1a4a60d424e1836229241adc7ab572149ac2e5a01417c68168f66b5d254dc9bdc44c75504b0cfdc8c6d188fb8f70b4b0b32a8c54f13a7a5cb30404c84f5e67ed80b615d9fbd27c7e4b0d55ee08d5556ae0cb8502030fb101a7eb7280a5b263c2d94806ed0414b823f2de1ae964a52633303909240520befa1336433b46a24c82b249f5f657785225fed5c35a8b17bde8fa07d6bef2b1c2945aeffcbe25c6516ae10353f8fe54b1289d1634146a856623b894616873fefc5a0a42b167d1148eee22acc72927cd98d2278eda90a8e57f62e407b47d3f2866f2c57e93a9682f575c2924803470eeb19a36f71bd9d6caeb174b9bfd31afba3343adf594f9145b5dd00448820924ecbe6a6cd90a78bdc26776aeb90a7669416725d00593ec32e5d12fec7e6003939543f870ea04efd4ce321eb2bf65b1a5e4c19090c00e3d24c5d4ce3262df2d6668bd69177a0d6764ddaf371c6fdfd1ffc914890e2b62eca127b5d57c45bf323012c544e6886a40bf425c04b344f9146711ce120d7859f6d3e7bf95ac2c0a269ac69a7b0fb7f81aed86cf0d154d43690fa8b56a5a322b0041bf7f5b62fb239c4279f211fb54a868f3e7c825b383bfe660b4fcd73fea5428913133853fe98363006651a1f3f7d1b1ae30ee909f8c3e71b26add2174f164046257f19c3cd1011b60135dd615e39712ebaefccc04254ce28c7ac189d493ccd4c708554b9fd1c04885abdbf29f6c101ea21f44f3594082fdd2af92707611c01a32f443b07fe90552143124364482fdb696311198c20286d3c843eda4e55109f81cde1f4b87ba51e1d53b19f0a84081d2743c364c1044b7f175116f825d9ec4d0ecae0b58f3f255c439d0358415150b5c0c250b8f641433454dd9b801255512a1b550b5fb24cd38f430b6c58709759209003025236ee189a4cab30ccfd93f9d1616717505e6cc9ede3a4605f3426c426b07a38924dc526b56b38923fc4c74a4a0b6708c9d5d6be24d46430cd3e5a0350266b4fdb5947939c48bdf495f1b7f09f315d1040e2f0b7e974c027267cb40b8d97b7a9b36948424c01fec371b081e82b4fc2510c1c78c70167a6cde6fe5edb12ac03ec2825bcab0165680ec59136270e26b7f4b91c5f88b45dfaf97fc54d23b6bd615969acb7483eee8464afc294f24815301eaae2b10d035268379d61051ea874201c9d9c513a7c9651bd72d8851e68fe2b17941eacd8ce7bc56ccda8554f546c56d2bf6bc84bea7c338322d2dc316eba31e1e92ffbe8be45491f51e08dded902d9489ca8ada5f49086493d5b92484b1384682f69982bf14976eaa953c884c39498c7bf43bea8fbcdc77841a487948c56d7a90cbea9914b701a5b36db9cde1d5593ff6ceb3606da2c05ff6d6973f545c911796f2c8944cd5b34a9fbbdb411d40d1944f8e01ad03e31291de9f2324c7896b064fc143f7e1e4611216d3416a28708d9091891dcf1001f76754416944b532ef29e6df27aecdd6e517f1884286afa80f3f23d8618801acf14987152a1238583ac0c48b2fc974703c7a4267e815bf7479c635b54c66be3b4d0a2912ac4f961107e062d41f31ac1b6530b907bbd7da073b011c93702575e0916bd3d6219fa7645dbe442e8e47b00b55c6bb1c63c5e9427c2cfede5987237138030316f884840c05be7cc558624051009af289e0ecaa5f7ec70b925d80296b05112d71b124669eb27252cbc2ce2a1fedb8b7ea6b966c9a5399dfc44afb646f4cca1862d6f2eafa9b2d4ece360275b7fa38296f6156aceb2341ef33cef30ec6f0ccf260e7d2ccd5c22066611a2b74bb11298094f8825ed71c8cabcbeebee0b52cabb821de6259736e977b4200e6ddafb6be61653375bd0ef6c52267186e62a65d2952887db5728ccf0ff98d2a9fd05742164ed1278ad4daacde6e4e1d9dfdf68fefac97dcf6322fa2dd34b6ceaeceb4180454434d775dbd54f3fa0737ed0ec846194938a01f1edfe282b66d05a019cd293f1f685df5c851258fedeae110bf0d11ee0750fd38466501536bbd7a07184b77d508f81d9383fa1b37d190e7937887aadc603a4432186c5f389b700d548a519b9c39fc3ad97b2e9482f987359a54360bb15e70ed0b7c39b464d5e4a453dcf3f2524710e85339a72404b4880c448ee7fb5ebcecca579ec0920fc3f82480c95712038c23a87961b86fc4659df9ffea56f473089ece0fd572449c045c6e9244a56e6a4ebee5915767b1e41d78e10ea52d67d44177e7957b50d344cbe0302a1c754c348bf5eb8f2ae0ba731cc0a56c7b3d361b017d0f730a841a4d4542eb317c2f690b5e39e5bc2c6ca02b177b0db58d3834c0a8321537eefad0777ffebec418bdb78bc06d0633b1bd7fc01f9eb7d14392a0f144ac4f43cbd8b5dc50dafbc7081fae504813150fdc98b474d5ffc727f3ea8f61b3b0dfee6739b07d3270a0edd59e8ae523c42a92f1032ebbd481017549db0b26976a2d0e55174f8707bf9b71e23d7815c4af21a8aea08bf516365c7e28fb4ce2c34166470a0b7512a2e053c5fa043dfb7eeb3c0fbdcce71a561d3c36996c170f6ad9fa0be23cd1ed24252da3891119f5d85200d5edb2bf208c95d454b48575278c3241b25a04cdee9b16451c585d5c3492510799821e25e1d6730eef477192c5dd9b382c914080050e0ca0ce9043b742e61a7b7960874571e5fd0fb82ac8cb4aebe992e6c33c30250888bcdc0fce2c8ca9f096ff188f12d77dd290ab044242f03e4a0df9cbc5972e2539ccd60395faa26300ecce36a6dc8d7fb86326a57322b99fe28fbe20e566d1eba2af5a162809a2ec6b18521d9291b68e48c59575b9b617aff88e5b239462e0c0e4b6133085e4317dcfe231b1917d462b9a4412d427869e1617f69848d3b1c34ab35df6ea2eb0af028ec9c0936ca0de6be0e6c1021cab7a764ae64ecc48b52b0d5460d707b8fec7fccc05600e3b4b0a8689e8b73bf61c300b062d3aa232e0839aa49be154363c34470b5c90d5c58c711447d8d4f726b401146e39e06ea3eb27021634058e450648f98ef730f2e4fc89340718a7a4d2b4a25149755429f8cd7e9593cd47b78870359ce6a6608578d927b5e5c10734be9165ec4457d11d19719eca517fdd7795490effdd5891d35221390f649adf71741b37751422ecbe4ed1696bd2900535f08783953b9bf0c16e6d4813c2bae02543b105888686f8a48c81f8625c61d07b783126262fde875f00ea00245e13561ef031d41f12440ebeebb0e4fb4f560a03074701d490ef3d5b662c639edef8375ea5269e328c3e9f4c0928aef10f8139a792aac67ce1817d6e26ab00371101884d75e4f60146f1ab45a9500a2e470ec6ae39c01ac441c52040b1414999b555477617fd9d01c92b2a48d2a479ccfe38e27d0ac191c1c07c326a09c0c05bf0dbf6b1898ce37f0472c45b6f8232d03c4cb2838dcdc4d6e413d3b6780528cfb0ddcb18d9789bdfed9e79fd2c3059bb82967be020e566c68f80acf212396da752e0599230e4de788249eee0f098696881e887dcc9bd8acf9fcb1cb90fb361e839b84ea38b793263e797a2051732dde839658438d6f326a9c86e9ab13209775415fef87de7d3e95b9ec5cc14aa3638a249031411380251feb66526664fa35c06e212dd3ff0c007a5d1655589ec010459a86d33d4517df62604b025b9e1d4e3bac73a74251ae617bc23f4bb482f79c65c355e220fa45f4b737ad5584c44f1f4f347d75000b738e631474f079d98f904b1f3fc44f5ebd1e7242e095402ad59348b5b6e4a818f222a7aa91b312155dd8f4c369f874137ed0e26331d3b064918ba427d3a4f6b5a7805e76f395b1f8fe6ed0c9b7e895c251bfdf98fe024a1941ae6664adc18a7e15be210d4898eade7c6162c5016ac51e31f93f2c3c660fcfca0c351ee88221237589def032be44b25489830aefc2107c7e57e81af3fd4c42fc064fc0d1bacc4fdbf9ebdad5afd80b35ba97e67e370f60d83b73e6453834fced0fdbaf26f497c9eb9c5f202e0840de55ddaaea95070d8753cf3f71c13d76a7f21d609234319579d97d9d37b9683ff5f147fd5e1aa96bb4a00c64f8f909b246c3bbc1427ce5633bb9c676b37d212673b5e94da0790c3e379a031bed2bccc8dc4fcdc33fad9ab7308034394df9dbc860db70ae5a909dbd858f5b3ca58617620f6d46823783903068574bce3859c3f5ecde8c856b0ac16e1125ca25feeffcb8ce75196489363c6fa810019ddac7a22a3cb74af4ada7b070998d1a1b2142b47c220315974b21bc0b698c5fcbf792b6351762638be3e631ec2079dc29689d1c590f0e37fd2606c69a216c96376aa6074e376a63911f723115f657186f330ff1f2bbd3002a288a7192dd698bf1d7f63c0d02cfb67dffd2b764ce387a5be7633314ba9b97dc5aa53c28f83e81341f1bfbb1a49de69225f0b5339e1775494b5c62072d0116a4f495de4cb77d256740fb60f69a8338776958b9b1b1d3a8c4f842632c25e063bc826012f73d7acee438d42f9d8b26823e5e9a043bea0380a186de162ef8cf4774d46a9987f9e18c5c31fe204fbbee3f89338c555c89cfcd2e074224c00f4de4fcbeeab83297565b4410b6907974fd08a4ca440fd8e639263d60faf48b793c82fce79d78f6b4294d7cc1c6cd817facfa1b0957ecd84baa2211d6d067bf80772ff5ee0918def767e0e81a603f65f79c340f39d2846aaef8e004a9425d16aef38d1790b3a1bce27ecd0c59dab8118caaadcfcb12ec1fe222dca5f967bf164ae70134f1a73e35fc14226af4599b72f028d6a105c02e8c6bc27311581dc5668cf6e8de3d9ee0431385458450396aae22de8e16cff61cca3d9282aba7af182a9c60134e7653dbaa5cc00e387e82c6dc0a560601cfa921851fd11d4fb58495dfc2b9c1e9f5dd4f618aa274ebb113f4239e1bc55ba616910ba45b9a90a3dddaf686f874b1d29dc4398bbf860da27e8c2d92bbb505ac70bcbba7038fdee22733e925f4bc04187dc9020151ce20a9b849e981804b0c41ec9d0295adeafe159ccf52147aac1f8c508bcf278b14ae74cf3a2bdca28d38dd904b14acfeca6df13867f0c5267ae008f2dbc2346b63108c4222c2828c923f3fb98efeb487025a2fd9f6d10b7e47ede102c12041565d5ad8497c19c4467f9ceba4ed1c28d562bd353c3a63e702ecb94e2dc2f3a952ea5306f346dd00f21e3c488a567e7af2d01aa6c25e4bace1088ab416bdd2d3c30ec34c4c1bac4346f31ec0327bc2873a68cfbcc2edecea080f57b8491fc3e9213a0b692dc065f18f593e0519c9cda90bbae747db901b7c600f954da873fdae73391e3528ed4473fceafc557e5e8080a51d43f1d63c862aa0b9f322f4f1f100238c157d3fad8a5ca0046a3359f7ecafb1751e5af381c106f42298452fe9b8a07e34bba11fa2f8658c45f14a4ef7f5f3b9c33a236c7d4592a82a85fe4f6940f08fe19454b4026cf79d34ced981ca3a3d297dc95e599492e27b7eda4460f26d6a98c9536fbbe3c8b9d1f3f6221d2d39f2e573a83640de541df1ed3a0ca6557bd4b591541058a409d2fd80ce2078a9b1f261c68ce16342596cb66407881087d53ff3e39e27b5cbed175f2da66114e5cf4c7b507cc23d14a7c6945076dea6e78eb16cde15652099c572b903f45d1197735057978ee58d45b566b4cf94c42b21c97ab94c9f2afc56238f9ac9b4cc82027b6c58a39e5593dc829351bb04a508614072d727229ae15cd1813497270822b834f6a6eeb3286e6edc250f382600c69751cbc7b6b4194bda9afcba18a752aa70407fc26fc6a803b92f380f0baa4f0479f244f044e68b96d882b7cf9b9ab01f35d2b5f227b1907ce3e0d422dbb1ca5eff2ce16325bc348a18ccad2699a1557b79b5479d40c876fffee443cec9551012bd18abfed611d47e4e1428df0179a933ff275e625a76911312ca07f0ba9723c3561916a7f108d7356366f3e9469fa95859a94dd58f649620a7749533697a0e32e0d39ba182b4630295c190269e3a6972dfd9c04b92878a73a5c8580c6fcddde569b8b122f7b45c968eda2729f0fc878744490876e76922e284b1b4d30b83d0d017688cba93e06c0513d203577aac687b4d05ce454b6e7a5db41251680865a75fcf6ea4ae54270fff9481f052ade9ff2b20ec22bef9f363c4d0e1b54fa4e8defc3537b3b8844ea37195222bdd0dda06389b477f5ac815cbf9af74ac44ab40b38604e55fd40ab41c4094869ed5f2dfafc2e398402b2e48519732d01e46f15391f947d8601960d1ba4a2c85bc9429be9d96c8e79aa0e5e1d685fcb7c20571a505e5ac49ec63d75c1b628eb53489cf188e293db78d160d3538626c2aad4cb8596366bd36d9bf84753f138ac50d0d2dd09e850bebed26d97fec199850f847356cfa4d1b5e7117b8b4eb33027c621cccd68ceb94b92e12203c9b99591b71fa12bbe87541aec143e56c763dc3aa65503552e70b83f0c01b77406f536914a48610c0d62d182c045637486ab9c884d3db11646b7601112892d3a04c04bbc33b755d6b6faba642d8c5f11a680c7be8ced62d8534d18e83e97c998f9f0e8aad6dfcf4a9a2320d4149d6f5892bad5d4361cc2b0f442666a06766ea7646a6dcb234ddf0d5a4a620d6749be239cc26e6a198d9caf873b9ca46c95f66cd8c032c10e71caeae035581964d7754f160fcdcca0166f439f9877b7b99095c19054e8349a8d46cf20b3ab92b36286e34b9520065c3ad670abeed8784c262b37a5d809282abe4cca798c5d4d4bb45aa7a95079f4c771f0c0546cbe86b63b39a333b38a2942654ab03c9134385bd83412ce3455a311aa41dcea6fb6341fcfc29b53f4bae30d4fcaa085a254a0d007770be24cca00eb702d28fa0545cd8214cbd7c328c4bc6360b6b293954fd9dea9517fa61be42a3bd61330d5cd20ae716f21392f3cc2f2733e1aa59b3d5403afc04c26ecbb43e89442282540508f0c92770def2056ff8b8c873863f525bcfb21324f6c31787756a891583fadb0f52581b454fc20603dc3c91e74a9903cffa48b50441e209a9ae399eb997ace63a0952e140978f6ce0621f75e9a190f6bac6c05d5a79a272bd273bc27f178cf1a958f572f3cf929e2debeb5ba7d65fa6d05950210dd1f33a21b3b59c41c8a69ee42343e31998af52ed399528a2d911edf1cf3c93745818c398f5ea4d825c42c24cc87e2a3d147b7f12750a8d6673938f1e3061700f019c68872b8836409e97df44f4784e6a4e71d3c222505c64692b1718fab92eace095038516b7bf326a17266ad5dd85e5910d11c485a7011f344ac838942c5074cf33de88981930a22a70f0b817c40bce24f133569851c54034fc8fafaafa2ee96cf47e736c6af5ad883c1fe2856e2238d05f9ac6c88c16e4bd2af9a2c2cdef2011133dfa0c224c62e854df310ab939e8ba4dfc0c84def387d043e65fe1058c53e3d5752227cfe460dd2b228d4ee226f1f8f84423121fee033162c2da585a819dbda929f0226c532c4fbc391a6e19a18a1cb609374aa794bb1fbb741c8b64aed42d5cd8948b6c712aa13d10fdfe34aac230d53c1c054dfed1c8526aef10ea93de0a8b7d2e8c32e02e571db7b8b3490168a60b89e67091aa6775788d5b6babce36478c522f15bee6e69de2dc9abbbd369e47f02718241124a6193eec11385093e5eea094b2049f015c9b837583d413b922dc43892b9818f2307c1e700c7f203f9b1c05f775979890e958d7c7503037ac91e2df6cc776bfa27de419a8ff61e064cb235cbe4976822fee08db83100380ed9b4daed97184f1ee484852c68ff07b3d327e261183eb158c82315903f2516d5b1ca19798d4c4bbb3cf37038e85c68645d3fc18e9858a9fb0739f2496cd7cac4b4a50e2d8dbe8144370cdee3c4cae6996373410d26e5f503ad2b4a3498799eb91a256045086cd2d15db9008b08d5f3146d5cd1235b5e595e7a1435e7fafaa17ac2f18830426f3822c83a201c500408b25e024e1e98f10f20486b89a6f861c2e4d26c3b6fd488caa2ac8620a3bcb44c21cbbe72a14067b74603454a2d5d184449b35b20fa31bdb1dd240dd2bb7b522584db49b943096a6440e4fe63d23abbeffbe08ab278d376f30054744c55fd7a75aa2e132346249506ed15c2e6d2e2fd35b9b1e844dcbd11472cb2470b5644ef7290295a4090d358653d70d8e1e50b569b05f13b1b67378ca21fe2419bb8ab7f78bbae92b5ab56722f332d888031776e94fd8b0115876288669021a23bb9cc0ac118652f1117c60e0b04ca59b8514c32f3194788d0ddc4feedc5ea0715e6f85bd663a56e681904a976398b8369cd8052baa1caa8b2ed5dd8933ac15cc6a010252614ffc5c3f155a6966c22fedccfa83ff9891e16bf0edbde97148dbc1002891220e63c7f1f994574fefb20108fe46fcde97d7365e631f1f8037aecbef1288571acb04d67b336057ddb9a4971dc3e28ebbf7d2e59c95355f07f8831887174d8b0445b835533de205285f0082fe8054c200e8acb6645806f3d8c0b46ac93e37459a974654d2e19171d7efd6185ae4ba459678fc025ec8d3f26d884ac32ce8cfa5f2aee3e107306d9abc502664c3878924ca720decdca8ff531ac0b8dbee3107844e5ee0dae52dd243e21900b0db14157bdf01730f28208ccd4bb68304cd052c030a53c97a5bbedc69c857cf213f1677e74aa0c0e727ce57a2c959521b104fb3300c801e75902caa34f0ee3293c9bde3a49c407f85cdf1c59a2827364d7d6ea56609cb9842f8451f4b44d2acc1d2523f4201b0a81ee1dd91d63caaa59be02cd30c6951148f4003cccaca01369e52a8559b137cffdb6cc3428d9db8c8a9de9cd34205858f9335b847cdecf36708f4a991d41b0b33a825eccb0e2dd6b6adb43a4948a68751860fc0973eca05b6824e07a9aef0f6f184566ff532316b399f0caa21808ba50383f28098026e20f57149722c03055cfead293c94a93fd55774004a9cd32f795fbb2590fd749d9ecca7c2c5c27d2465d2114023d899a39bd0ef10d9e28d2e31612c7ca599e5bc56370e109f9279e32ccceb5c002177c11c9c545a4ef667ae411b3a44e7db4f26372a8ddcc7098d30b3b41c5eef0c9d8855bf9529a58230d64553dc28d772e9410d5d711d4c2d0683e04629a2198b24d43a8055f819202838ea1834d8be1f259e5cccfc90d548a3e39e39083bcb158189a9a23c9fd463586e2a4778e9d319c98c6e88d462eb797fe32a6244d402f204c459e751a2f241af609c3621dc34059065fef41159d2d1e58682641a450e1209a72fc990df9c9d874367f2e4d9d211527515282ec23b306b29148a0486fbdd92607e2d6bed4676871aeb9a37f29fe55838fafdb95c7960add5c1c57936d3e2761a056ae92bf2ef076191d160d9da16d9b683d3e851c4cdc5806c23cc6ba89455f3fe5fd0d229f3d8ad7cd0a571cf40a5285ef51820c56cb86a23ff5c2dd85f5e0f6c7279199805bcb9d59c007983f2ff929139507d42ad5bdf7dcbb938fe6bdd18828e98de5c67686cfdb204f4d3762101f3b939f6ce2a0e0fe507ec583931823885d42b0969eaca1409eddd9a37f34bcd742098171bbabc998e2150b6b89bfc390b4839ad2ed4772d314b5679347ce93cc6f31ce6631714ad41045a95e48f0c002cb1bf3db8c6d487964d93cbc016ea2048fc55179ec031f8f83eca2bb42a2c287d99078fecb9ecdcb001f5dd40d1bb355c8c29304a73e8d7a9e73cfc980e8f8f4d09d9ea930f87fd153c8054e883f24634af512fd97d4e11f9494f744f4c33c52edb604682036f117ff9160334e624ebbfd019744cddee1dd440708c7c8e6126d2211cd668c79e68d4d27707a9f33b2e92272061ee2d23fbd2de3ca407bcf941d454bb712434c5cfe037af10a895a801615251dc336f09eaeffb4f0b08228e0b4134705dce0a6b58445a34df8bfb045ca637248d771504b8192450097d3e628ce85bce37c0cf8fb5103276f55c17f62baf2c10837330f2dfae2ffd65a2384ecbdc9de9b6c22a524010f0852088e084de3ae711ff728dbbcce735eaf73349b495558a3a11ff7f876894559caa698dee6e52b288b745eafbfa855d19e3245a6eca42142e752364505d58d97b482b2168a14be2e85d3a3607b9fb0f768e6269ab2264db31a25306c1dd96bc9deab30cea365897c3c8723b4ae0cd47c5e6213f00c03bb854df0641aa3c43490ca9516f0b361c0cfd0f50c6430a2e6847019e43be552bf2094175c0821a493fa75f83a2fda2c140855e18c5afab93eff264b19f237af919af966f9c4b2265cf5dd0aa12accbc0199dc2c6c59ad83ba286a32370c7e9f58482349e6f7391f4b8de610cebf47eaccefd6b75254f2d467ca9acd3487d4a569189acb3f4bc246de30914fd8e71d6c73a8d1702aec433dcae4e470260dc55ff391e5dbbdfa44fb52f95edf8c879f8f93433fd4f70ffe7db1ebef96e61f6c7e049b17c1a22e99f7cc8de6da5b6718ebcd6259dd22231527fc5613ab2a2c5f8c147c177754d0cd319c4c889cee7372873fd83a77d3da9a5f67dabd0266458c8ce3e60a1b79e4798cbd7cd7eb425597e85ed1a7b604b5310088e712675a8256e6ad914cac6e586666e6f8eadcccccccfc806adf74e9a784c863605e01435132ee23558f6c4c0c17d90e806b666666e67e88721d801868bb3939462c51028bb21857c0f057c0ac80d920788429e615309b8267b65926db186a3ff2be013eaf53d6af0d867723f1dad9dfdfc800d8fbbd1c4b6c0ccc9a7005006c9e629b6398e6c7ae93c0400e03667d04f6711158e71f8c73c626f991911557c8bad3107e314c513ca9578a233c877cb190bdd8bd5adaf3201f9d3d275a96a2016c0dee216aba8c9410b329dcc6acc9f4f9151bb3329219c2e884004e45ca10728c00b0a844a3ec11c28eed1d55bb4ceef1710a42c6110f323e40465280cd2b0a767222a5e593766113eb781904db7cc2aa3bcc723c3527625a3d9f4fb49280ce390e7514e21c04090939bb6fff0302211fb4324f520642dd344d137c7f2299a6a999de807d421e5fbd6b7ea21dcc7bd03ad7afe22d6cca090199713c0e7d2202235484d6cb43a7571f692ab27d0f5f8389c4a69b531160fed464fc8ba9e7fd6453c5d83b604808166510c6951619c0610f5a1fb25a4d7c9ee2419b821f7b46b5cee2d776c96af5934d115fedd2da2e59f5fe56e86868baf5e58f490445b6a08dac4f8ca164150cb140d6dd2b8cafa241b0cd3f30cd3b58bc8545d9c4ac28025dd27ef52b89ac92488ab37904fa040e5dd2ce21e1a968f55caeba38bbbb5b55bbfbe8644d38af6845c938f4f370e813245dd2eef15c1749fb49757d625975dd7a45c9e23758140d60afa91eba6075926e1410ab28d5c99a4c8f8f4e62bb38aa4a13c4324843af3760d93ec618e3de80a16427213bc2040c776671802ad777cbdb90b37bc344336cb88d711e691ea364e6bec44233ea30cb90377768487e76f6c6a6e0f7079410a4034217c7bea2c896f6b976641f865015fecc3f4208bfae99abe7d339988c13022e7ef3bd5141aa878684c087d8823f83447acbb99d91534ab7d2225a1bbb8310476268637f989a399cc3c5b13736858baff37d5a97df4d2b281bc97a70deef1b18c0f972aaa47272d6c69a40cefb937b07b30e1babcee1605176ad3cf56be5ee0d48eb0d5266f1fc7996f3716f48d97583bc418232376fcd4b5036ed8d49f7c69a4cdf1bce2d8e2a9a506252b637da4a673f3e00f2f71886e43cce392fcd9368ddead2a5d7a28c61b089264d1a1a8d62f5181f8d2b2ddea57d975eb491a47d94e07e34786bf3b7a19533788691eddfa355a525abbe7d4fa22178ebefeddbc7ba74f7defb4a2dc60623935e817c2308563793f6b58348af4912bd300d06f21e6ad2a315036fd2302184ef9d5df00e8f79c8aabbb4efb9e01d36c5bbc4ae451a5ae9e34fba6baebdc5b746db5ba735e941ebddcd1aaac73b6cff81cd7730cd37d875c642de98e70f7357d1ec82493812fbc04759ac96b35b715e6c8a6d4bdd23a41ad210f527c5e67c310efdc06feece2f36c5bba3d6dde73dd8e62158d4259b77775d83494c72d1aad2aee217efd5e7a461c63665f0f5897efc039ee49e94c147f9c59a385eb9b8f3811d9a1d97a24d3155a6499abe6362e6697a556577777ad235df487dda14dbf81a5a1fcf69d269da214992248364a9044bf9e951a6a1bddc14d69f54d9ec493a49d3a6d8e59ddeb4fbf64dd3f46953eceebea95a0b08b8bd838e914919c3c42ae4f1129be08e111d16f268e423c2c5c8b15d5c4307ef46c4503b91f6380fad9cb56704ad2adc2cf3c1d1f40747d32cddf1d355f4897749fbc8474474aec2f0293e44ce1ae039c228e29b9183300c74448423a008faa12334f60eba3b324cc3689750886398f88611bb05867c3b867bed8e914d97878e42da5485655c48480ce910da2c0d23e44e0493f760d5179be6434218e620f45d1e66966916669669967676af2c9359f06e722a9ac5d166619866e918149cdac88adc40b648062593b2ea9d922aca7ece1ae437ca5edb3d8a9c34eca421928f71626656e1090bc5c8629e367f6cd1d0f468bd9dff9ac6a2953346c9de86aa7055e1484fd6e47d7af4134f5d6a5f5a19f0a57835975e5132ea1293b306f9a52189d5cda89f540d55e14c7329a959437b4843ebc2d6f6f24d1a28992c4ed3eeb7adb478efa047bb4a57e1104fad51076d8a760ac59b6868cf0d25ab2a279b82fa7b7c959f93c6d09eff5e2555a16aa42acc72f791e9c99a80d6a4ddcd1ae4df256c7f61d42d6cbe61d255b4c4f66453540cb1cff4288b74abaca29fe9d4a54b2cca4e3645bbf4912a65d42726693c9fb4c7533fd914118592496dcaa6934d51975b03daf749ee0d738e6653a3276b22596bf9a0f372c89edb913d763ad8041002efbd5e12ad9eec6dae397f70fed1c12226e1d0ca321bcd6555521f8662bf599aa5595e38ec6248af77575abcf7b5f1a4d76d7a6d5a1c59bff73af5418955149ccb47eb0d32bb5e69bec1a4aba21c2ce2928a56b44a93ca9044eb0d0ddbfb7b63533cf7c94d928627104430d234b198a41e908a60a6b7e51e69056555251d6d4923a4deaf14a4292929296d05124a14a3685a69214520a9b3698a5e26944699a669faa31e2fb1884922ad5246d12a4d34d4f4e4e484e34a3ade88f7b2a98a968481c42bcf7453524a8aa274c8ddc7795848c423e5bb1443e2619e3d2c428d78221f31972f45e48499e645a849844a28a0e647e4f2ee2ae429ea3d271ff246848c903c425252d2aa225192fa444d54d3112a2dcb9a22225894cd29298aa25cc8a328e9a81712e271f2ee5194a37aa27aa27aa2288aa26ea2266aa2284a4e11f7ee30be07b3de180c9730125fcc556e9aa6698a2fca4743f1948c4e4a4e4e475114255d3c75d10ffcbcc7735dd4dd47dea45913dcad93c06078f47d929fe424279526a1e0d62518120aa4aa6590c2a60c5214453da9d21c85c5484928983c3cd243253b0633d386ddce757777bb6676aeefdc748eeb88b7e3f6c4c89abae866dd6619d1f413efba1d64ee118e5d8fa0aebbbbbbbb439e81ac596a18dddd6037d80df2f6430edf215f3963f327acadaab7b5d69a6546ddda6e6bf2d674d339e7e6ce0846643d308801b621b227af237bd9a68abb38b2218268ebd225edbdb4497047dc938686bb282289119f91190212a3831072e88a0ea193f03424ddf77c710c31341dd976bf5fe1b157778c5686e918e4aff7a36ba45b0f24a45be23088d08878403addef86dd0d4f2286770cd093595766d59759b700704aab871ea3f52ad19f6278e59778659818282f8d41c532ecc7a011510286470d004ae96234c636449bb2abbbe179078d0821129263de4103028973d3f1a6239bdeecb9b4ba6fb7edb6dd56d2509fc4f73552953677ee6498f72e0690784312e7eeee5f2468ebc10e48dc1d8b67125894599b03092c6a2f4c02031d41eb1341af8c8ed0eac99a8786d04a92813e5e50649b8d3bbf6e3c926e5a0f9a87c898caf3eb6cd9f46cbe587574433fef120588e49b439fd8972e6947016a92cc73bdacf5c0bdee2d49b3265c8eaab42cb4328a5a0f36856c3d5893e9d1e36977abada3eda5f520c6a6a39a2b69eb01b6580e627c40bc1ef8c5aab60508183b60e7c0259099d9e361e629468e5c1e8dd7039b8871d210a9b42f1cec82ed226fe48e7f2edcf1234af18ef247bc0a7e34ba690f19f76643bf1cd91836c366d80c9b61336c86bd3424cf79c7eeeeee0770f8f1f3f17d0003facc1b5f0ff5c959433c4f08d8107948bc5e11bca6a2a8a04a525f3d10320c1b1d356b880f393821e0d2671712148611f036348cb4624004ad286805f547682511a1f51e5a3dcdb0aa1e101f1fccbc2b2de2737933e2b311ba2418e3737933f6f900fbf59055157e34faf590c56f3651a545860c193264c89021ff7af40071eda84d471637f1bdebf2787e12920a82af28e27556995a7e5cf4d17833d6a4391dac7a73b0f9ab462fd10bbc983e1798cc7214b4266a3d1acdcc557b99a25ceb11abd6c2f489685f3c2d170c76810205084442f27b3cd7d5fe688cc8d7f692393a4dd57b1e496b7bc9a6dbf068bc428102048a1106e6d3737934aaeaf5302347d1892823a4e0a3f19245005811b125b6d0d299899b4abeaa3cf3fefa84c81fadf241f978864dc816f8e49bdc841042159e58e88a3810cacf29218786acc93c7627cf64921bce57f84e474eebd72b94927eaec3bb3faa82a19cb3f3e0f7bd7ebc0369d684ebd58f0921adf0e38356d8999007acaa16cbb2a09430f22c2385806f4af9f7dce1596653bc43eee1e47ccc434a5a792673737ed23adf79adde91af15959772c267b1cc9a3c0e569d319037167209f33cccc16c22f681affb6b63ed37afbb791bfa81bf345894318fcf8b664db8a4ec229eebee219ad93c26651e6be25e9d619847f59d34543392c7a638f7abfc94b210e51e157958cc4981067e767c5c46663e2d6da487d3c07523331f191f1736e1dad5a683e6ae7bfbe38373ce7d5a3685036976eee3926decee8f0c07d2b48ef4e8761f978f4bd6d7388da6379b35e16a9043b89acf8e766e64e6d3e23e3eb4732333fd4f4b7f66b88f4b6b5ee3c7259b3eef2eef689d9cc6715cbb911efc6971b2baa64ad906d38cccfc20a95f9571e0701f191d3fff9131d2837f683a64ed1f198c83718cf4c8a48338b27a03e3f8c8f8c81899f9c8f8b88cf4c828f891b126138ddc0b8d96cbb5ec0c75e72877d5889961131445a34861974461f5caa87594a3dc791d5551ee517f9d2f573454bd5357c11cf766e51c5d577dde3d60561dcaf3fcc93947bdd7f9c4bf30396bb8be3474617533e6cef5b136dc75e82e29b9a5aa2a5e21424f923bf5a05edd99798aa275672877bd53afd35114f5aa9acf5da738987c631f973010775d9a578da6aa621ec7769a2f5669e8c75515c87551573937e320a4163a8b3922e0c854f20b431b420eccd68090575ac0ad0143f119c8e05c9890afe39e8fcd71c6edf9787817a7a39f08b235984338cc811b07391cce2104a19c39a7ebde1a3041b084706bc0cc4866991890d7386583448979da9811466e8d98bda683cc713ec65d8bc9296fd97031315b6363a494591b319ced7881332d8c4c92348f110b286513289b68caa680d3c4024e2936b009d8139c24c8dddd2acc58c845b39b99d3136ea6e99a1755c1f01c5a3987af9c7fbcf63f6087ef5e3994a6ac09fc04a769fa3e6201bbfb2d420e07ab9bc5a76c8aadfdce445598f38ffe47d3cef410a7a7a76c8a89560cbc494384c18e7982109e058c7a64b55d050b49699ae2596c8ae9319269b02398acaa70caa6e8b71829b46ed10a6fb1bbe05b9413e4c68ec59a4cf00ddb6fb0f80bb33eb1ea13d6022f41348e1c2f3f348e1c2f41e4681c393cd8e6d025240878dd4d752380a4bb9b860878badb43a32e897abb5f72bce478c9f192e325c7077f0c21ba96ad076946bb300f992449b463c8f8fd34d10632894cbfae4f22467ce4ef9ff779e72244bcf31198a7f3771158e71f2c8a46b00ead2a4d048ba29237ddd3b907c47378a96520af2acd499732101a7a076149a16b99ebd0d03b08031e05597a5592a3cd32f5547daad27777ab1d642c13817454340bc3348c8e21758c666118e99b437bdeb04150b8371665f57aafcf9e0b2ee9bf47146ce28174dab60ec8bb8a76b7e1d4a3ae7e7db37f5c1b05c075d125fdbe28f5501730f41ecf75b9809feebe2edebb2e4f7d4651ccc0247d817dcd02c21f4a9066260424e9e8dc98adb1305b636376a6656b6c8cb4353666675a36666b48ef715ee10a4d6f59bf472692453eb0c18e96c95e598fe4eeb057337630eb1cec7a8c6224a55983fcbcc320a783ed54c0e3dcc23a57d11e0e167507036570f36b730ea6e9682a40d2b90870af9bbe2e8187d8fbe5711076f5824aca47730523a07a47ef257a639a84458e53902c796acf05ef10a7e31d56ca85352a39636549ca5955e417fc825ff00bc993163e2d5d4d1aea7d5a28d7de9a57296935d2432ef58f8c8f8c8f8c8f8c17a7c365cbb699a4a464bb545252d4ac34575f4b7187396cf1c64dcd9234724aeacdd22ccd62044d6b6f8626724dd3ae71d3d368de0ccdb3319f86be477dbe4f6a6a36b3331fe5a676c99c8d4676e7ccd950d7b84fedbd1b8d55c9ce7ca498c31bd6f0c5164ffa2ee9a3f1683c1a8f069cc1c2f06c578c0b7349077f5d516ae24c9322e7f17a5591e226ceb51135f01bb3311bb331d31522080402bd440974721223287a89668ca038e725ad28d5c9c949d6ba202549622125295dcef6565ab0887a8428179db3dcad95d75570dc285f2d9857d0379a6fac6fce9187b5a25313af9d935699929292b226bcc2d94907936cad85aabb14b96e979ca921754af387d56ba585fcdaa03458283e8a9ee65d43ed8c7f9beb92b2646b5e67c8e4ad4716651415e5c84b4eeafd88ed8d35a1e0a3b54ff0d6da14a9f7f1da31565a304cc3b03496d530dca5b92aa763b410908de54236b47a3eb6635d1b0d5561cbbd599aa5599aa559fe7a900f3ab7d2626decc06afb03c8ebe2581c7b63a545b436e2dab0362fdb4cb73aaf3364d637b48232eb92d450107a636fec8dbdd138eb9c60b9e01d98074bb2a44641078361f00b7e5159960bde8179a8b0d0a4288a7a355d15ecbe4a2e5a43b3d968f805bfe017fc825f3820348c9e21350f9ad72c16c3340ceba2a85bd665715e5fb669699d0f9090ea21201f1d4bb39ccaa23497d52ccdd22ccdd22c1990562e764f883aedd9e8ec9bd1793dbc1e1e8dabb3ef74ae8f4ee7b95c7f33aee7c3d509b90afeb8426ab3a616f26a518bd6f632d21664d7932d49b6a06ca7b790eb55f4de87e4c9a4952a2893f6b2e8a3f1683c1a8fc6a311bd503934f99c73eed3e21e1bf5e919c8dcc6d8eeb0fa99110f5f3f2e1f19779d9516d63f2dd5bd8385aa78c5e8de89ef38ab73157c55d5e307e79683af6d7aeb58b73e6249f0d56a1f5485b30ead1858a91c7ab9f891b1266eca482b056987493e32a6266dd61981aaa494124a591d442359514e4ed6445e5a2b2daa83e4a3abaaac8364754dd7452b4a2635933c591319a9e9e4e4e4da4908d64a0b163dac0852947516562413c1443029299b9516967516d686aa2ceb14457d63559546f30afa47e775f30f4b433bad4a4949494959e9ac8b61031db27d91453ea8811059ed7ff87f8cd54a8be994349d122254e15b04294a9a5c0fcafd7a92dc98c74855d5c2549c285b8ba2389c692bce55b0b59fd5add7cd2b5855b4aa7040fe515daf95c4b92caa524d8f818f76be316bc26def74cc6e76ce39762b2d9cfbf8c0cccc9f19ce398692efce705e7146aeced31ae911619242d791ce0aeda268b389369b68b399369bcd4a8bcd66e3e222b7d9dcb986d1d266b3e9189bcd66a2dee69be9b539df402755960b712097fbb05ca772d6ab0e6773bd83455109cb58d36d18be90a80886df4a0bea2ca847453da8179da2288aa21e45bd57b9a9f7defb837456af904638271a23f54a4aca2929292973dd8b76dd2b2d26e8e07bd14a8b686decc045ce39c95d6a895a1c0e4228a977fd72af34bf5e1de5a83527ad8e35f492a6db447a83cc28ba373af262d7857f9aeedce42637b9c9496e7a8fdefbdbbddddbbda35f45bf2f61a1f62873fffbd22fb514457777ee6fe71cf5a81f92f8f4f7e38bc4f9d85ca0ccd1aae9589c8fcd554d08b2b99c7320ee9d8dbbe6729a5fbfdb74403c23227e182e803f007f0c7f891f003ffd69254155a6c34047d08ac28d50115a493c21b4de75369a8b56f5728dea48123c9dc0efb5f7de7b2e7887c73cbcc73b708cf7de7bef8f9a9ad7786d3493dc4cd754d2252d8aaa7406695de1179dc92e093c679b73aeb498738598937bcc3ae7cecc39e3946faf5c7dbef86855e9e9d7545d98452385ad8d37d18de9c8c90e09cc5253d1b53d8a2250048a4030828f32d810468710be400842012b840c217c87f15052af32d2bad2aa949d9c74e454035723731f9791994fcbc787f79e3544e6dca3fc9239ec7d8a6f29bdfb1f191f191f191f19ae46db42b7eb7dec9e565a3c97a8a347d973d1ebe151d7dd2f9b8fc81d9037adf2ee83d68b3bcca1d5a3a1f55c3187702c1bba6903221aa2ed888278b446333f76cea3e804fdc7a3e804004a5ce4517422867f1e452702f011ef241e002c8a4a62c0a2a8a404f60e002c8a4a2886615154722c8a4a1ead2ad3495018684531825610e8434568fd432808ad9e0fdaa1f5e2d08bf6b99a91721da25a7b91f6d178341e0d1838428161b00bde817958d7ce39f96769a8cbcd4777cd34fd72b1a4aafc45aa2265ed0c1fe517fc825f486e4c68cded4c738e9d5b219a9be99da175b264755db4aa486b63cab8362489633666637ac5e206334daff624bdd730daa563c4f75ec8eb03f978f5c843c969fea8e43d4443eb0b4cd22dddd20e3dd9b66992a4f648147c550c2eee9631b8f82dbd26751462c4120a0a8a949d804e669c74504e50665c4f5e3fc4a844057164830d0d24710a8b12222a1774522e175cfc2a65d293120f7e517486e118866b4cebf223f30b17bc03bf2061926eaa6a01bfe0170ca305173f925efb418c4ad4e6f2c226963deee3f271a1ed6e1a99f9b47c640051e5f591213f326070f123e9b5b6ad87189568925a8843b74c2b3c31bf761851d49f631889bd4ba433263d562cb8a437cb12602f5d327fdbd666f7885970496f471b2236ef71688b639aa47349a3fb6c6fd85893a5a0869d49ba049734777ea2450572c821871c10e08123606f2c01305a573269ca405d69342e6ed7f4901023d536203dceb4a34f76c151cd2d09aeba2e2e374483f2d46e7b33d6c46d738f46af93680b26c9617568c126a4b83a4492eb82e4dcf3c179605d7041073631c4b52e1a0cb83cac0b9b888fc69ac0d78383aec7bad81d36c6a3f166b4f85c5c4407752c1094f4ba3059b7695df47bd7e5f1fc24241534b9c8685054885189ea5e64a4238b2e42561a5838a304576d30b2e0e23c6c3b3f2d23331f1994816012253010ac0436216122a9551a8832a97d6674e09a0e044c16ae8dd15a1a0fcda5cd683db009f991f171a90e08198c16a3f1f091f1699123330d061059c368ad32101f19233ddc0e58044952e2728d465295438b10c655a3976c5ae10ab9371390ba1e772fd8b65d45af8562612866b06688aa1c2ea9b5105cd32bca0c56b836539180053820021458d1316aa404150960130b04ca5956bbaea9d23c50878867ed8c7bb1858df0c515ae908b77909a3162f37061d664b786c43c52c406aee9d116a416d363039494f00a949431338d6a2f21430c8c935ba3c92649d59336666dbcc01cc4a884ec5c273cfd28e985853f5c1d115c1574097185a8b7ac82320862132ecea022010ba80ee9daa0e8de982548649832445e8832a9ed0f20b8a6d7123208712d0845450216b0381ad580004299616facc9ae0d17cd1932da286e9072c715247c3b7c61a5cc0e55b8422fe551540a8b94aaaa3850555f905a6b1cb826d75e55515570ed55d553d6e4d197f2288baa4a717f92a650efd0d1870309db08b4b012451b0115ae108471ca865d52d09a2ca427dda8899a1cd5282d480d45d3e19a5c8b1405a9e05aa4a8933589b49d80d644a2a44d511b3d91b20743c4b34b3e7ac7131960772e8da4e6c2524b2b96abbe679461e10abdb7ac3ea3ce261caca8f741282828ac728f264579075e3a318f88ce14c1265a244d5c90a689634c2eaef6ed889858b836ab25486400a1b00969be695d79d633bc840cfc6287375d482f5628452b95aca93d29e8906159e4031ac0d4f0a145d1b328f26cb730c9d2a5d23cc2b5547a6c42468ea612a24c72fbea03d7f4cdea252712aea5e2fb2f4112e94a77bf331fcd481bc69a4812045a6681fec21724a9c226767549bbc4fe9e44214f4b7839793979397939b1765f4eac5b8fe65a56cb4b8f5ea401e6f42a65271236814c4852925e2c0974a22208e9c4b2ac130b6c26dd77c21c664d8d08d28e0602ebd8aca79e3e725d7a577ed3260fa30134ad28599d7f7c8f957adfc2a247da688b5ae593e9278e86dac99a48d494eeda49afc3a48671b6b386f7e913b60d93a2014c1357350319759f307815fd9e8b06f072f272f272f272f27252adbc91ad588b56955ef1152bda8a15323156440dc6f99c3ad28a152b56ac58d1de3587914c3641687d6a958e91d6a944d2780c3e823434ef260dedad6d8e924f522b22a3163e36095f612fd86c3a99fb355f705d05b73901cd39ef4983bbc65d45c7495ad874179d9cd8744a029a732e6c1329cc7de74435924ba83b78ea13ab9d8c3af5893d26a1bec124438e0e3290c17b345f70dd6134444cb222287871c94ed6dc207613420aa27bf0ccd46f3fbd4fb44a779fd1a757a0ecd4f9b0f2a747d8235a418eaa701645547ebebe4fd7955c4a55389b769a5a94b1987ab6364dedd324b5d63a4ab1a1a7d6d19be48c7f7cd8f49def8ad8be3d62fb87b5b7af06977d625885cd9e0a707f190dcfb5a052775dd9683649ee04c24be38234440bc141c8cc3c78cd6c5e1f888c3a7fff7807c1a2a8e471b00d959a936888a2926bd7a5c30b46c83c669887c433dbc2332d140ae6c132cc83675a9807cb300f9e69611ecc03459fc0215228ae78450688b2f678ae85d4151960b3fe290edd8f8ffa849cdfeb51d4e0540075771caccf47f04e63555301d4271cfa443f3944a43dbd47452f7a4c69b2feb63033f30cf3d8ccb4b4b4b4b496d65a6b992c3a5a7474668b8e96161d5884009610ab2448d860110220f61ecf6bb0c725cea9689e0a781a8cf30a03f9857d9070b08f974847b4a38379cec1460e8285fc031389cd730d36f20a0bf985892c0246443c214cc2c11e97c07f601e2e8120d8e62a1804abfe815dd76c1e0805c50c4cb2d76017f62ed95b2d2d2d2c7325f28c11a53684244407c13d5686499c35b7be5fa736d13b07d3bc4fa7aa45f7d461559168083e421a726f59a41bf322b8321b333549461e11d2eb90dc50014f27ab3774245a424646464646c63d42402606739489212313039361aa326420cd1057bfca9035f32f13c1586c25e1a4b5d640281bc99c804e50da49039da09cb4d61c15a4934b7a50b2ce3b9955a455aa41d2ea2a3a9a559aef11eebcbc8a9ed87b282727d0876885ba39ec0e6cc2440cf76e591d9a45a3d16834dbe16c56c5e4d63596d168341acd898f7fd00f904fb4be2e5910caa19b6f0e0f5225b2386ba87eddc2368b1eaca21c38932bd12eb39643bbe29bf50bab5ec3a6ac5b58844924328050f6d76ed8ea41ac424a8b6026c992a248b2a2261966214a4d082988eec1999336a33654f2edeeb5baa3358299f6f1b95b8f4ed11af1427e5ccaa291a22148cfafd599abaa3d1aaa2e2b4953aa943591a87bca9a383751555555d5231611cca6442c526ca852aa884594624355a52840debd611ddfeb92ae01dbac61138d98c4bd5f70d1884b2605bc68bbabf80953d1f249114cca353df05e2382b4a381c03a7e681c3fbc745ae7e55d8f11c38ec8f4918a29a4233a9d0e841d08691475206c1dd8ddb9ee2e2a7540dea9ae815c029168e7903a47bfe4782f395e72bce478c9f19243922f5995bebb2bfba583f054951c8de387c69123ac38a8e4ec198a6aa968400000000033160000400c0a060363d14494043983071480147a9e50685298c7142589410a19840821040c1010000100121200000db1da1b6931cf903fc47be11cf835387576b7ac08ffeee476bd26af6401ed9f15bc28a363a326ca55347ce4bf19c54351c88dd2cbcdfcb1adfc022a5e35bf64fcb1998a91447fb9bc3c943705b2c06a15cc963626b6325392fc1b62409129c8f4a37ef507dd4086cb28876bc38e875f653ef9b39c3febefdc876815249d5e4f52bb64d4517bc9afdd006a6330c02b136548463291d4951f9126ce87a2662fac01f0fc812a370b94268685396f934703239b70d785d4ca92dbc6f2320e909e3447ff3eeed5ca276ee4ad780d8a447751815527468cb0edfe99ab51a14c68cd5a843600a1c5841970109a9d45843c3206ab4d7e3fe61a1429e731945940d99249294407e1e6d25c1a7e8551e5a1c00705107a36b1a87d14af5d1be2e1cc0210d55c1b446c83e61476edacd7291d609b2f90162f47967465d36b399f77d5219f88c17ee28d07d1fecc578e1ca8729550bc8d1a15272fb26405669e321927ac869d77e16443897755427f5c5a6c0a8461517bb06d0ced04dfb456c5cdeb7c3518bf01b39cc1d26ba5b00e4391843de8d8019f0546ddfb1572194d6310e0fb7ad988cac250ba7cd384f612ef67a40fb21c1c659f39587dee1732a735f28f89dc4274bec86097d90af6f8c3930c0ad9382378b4d273c34d370c7ce3a77198bc268bf3cc053293c0e4a98cb89799f42724d6adeb0651b7273b8d3de36e163d282b1e56987a8331d2b4067059088b1c60004eddec21f5f1eb586a9dc1da8cb06d37b4e686d69bcdeb1e49ff685efccfd64ba74c9a1e2b5ddeec4844ed499667ba016cbdd2dc31558edbe681a577c28066546560a3983b77aad7ef7f9f47b75ec6195377a73e7e6168f63601a5f83c44f81f946f770b663875683fe5f4682025ce60f61159c5cd1c5b891069fc5361375d8d2606d357be57c062ea4cacc3986c98f939dbf1030c2ea0bcd6a7a94548e2b90be6a26725b1b90110ccc49cc6cc4fdc6dee4a2f98f6bca912937412e5f2606858eee0d44ef21fd0b6a885fdab10db6ec3ffc27f4b5afad5e25bfa924fe1d1eeb25ad6fd3785666d12626d93d6f3ef2ae12abc9bb2c9a0036b7731ca82b7c93e4e0489273c1a69fffcb41a2bbb9769bc9ecbf96c3d1b96e76db1982cf7a6df66efa6c4ed9a4049b1930d1fd307e74729f621711e7b0e44e329a77318a1f77cbea58361b6e2740eaecc1c419bfd5ba474aa6bf0a354d32e53c8b94083b0a2e23be2c0ac5b7686269730bedeed8123474aed9a732c87af4230fab334a7747618b3fd3803e8c72a827a93e803617f5353a83df5be1f14e6d7756b1f3a40f4fe0f283ca3fc61a5e468ba54fcaccf29a4a4364bd3417a813bf869cdb61b627a448378b4e517f0b2a12e461b6912067928433c51d60ee8f58728c6e241b99e634bae4c87cc946fb8e5dd9db83cb14878a889236e2ecb4cd78d669ee25fa3583774ed41239805c4b3f683793a0af6d44f6dff93d9f38f9009192cecca2fa680c6362aa92a9502e1a2f22ece5806f2026093c2e5640102ec0a1a3cca301307130497a3cd3ec8207861efa00739d99474a72613014fc23c199d44411426cb1d839273f023dc5c52bfc84ffa94f800146a11c4172683270df33cba893d842a6e3f5c76ac309fee12eb5778d59133985ddc7ceccac7738e6a5885f19647c8834b382d98292cc0d220efd235b0c9e5eed18448a71ad4387a39c5330a8b4b60fabe7ee5bf571dc58f7e834c409525ce4f42667da7c27221a762cf92a24297a361b9a1c08984916838e2b90ae59912e0328bd177f85cc6c0105fa358b5cc3c3ec7c7ca4cf5594470de845c2a0bda887bf06b102ab4d4546bad86e73ea22a8ad22bffec041e056ab617c9d38c9b9ba05f25711c0113483b8499465f30afd72d24562e5f06ff0c18076db2e1625fd1dcb10c47150ded4e39c172dd361629b7fb8eca0b11d6ff5f753a012b07c06140bb8a494fba4189c3b5554bee81c706bc071d086eb3a708003e46027566d7a510c4a32d350a32c38d2f46aa1d0d2f1bc643b728d2625b8e8dbf60560289cce997c8ce84195fde66df9c44e86bf465662a5e14dc459dc4bfe52e5e35a71acb79068789269c5d9a6bd569b9e2fa954bbfda3b7e92a3c0a0888860d87e82ab987299250a6ed9f803c918914ee886524999c89e62111445b8d7faab19c590f20924bb086bcc8fc13925662c0885885f90b4e01d46d27e9b9728930040804427acdc74a4a000565c9b193cd6016b1c729c20253a5604fa73414a179d42a910790d78f302bd44c1c0cb72dc1dd8735cdafcc34ed50086570360f1d14a8e1a859fff88a7a67277153464311d8a2e75c261d5dfae5a72f5c5ad1a1d43f59606ed283536914ecf2db04056886f6e4bd3408392849fb84901059003a3b4459ba2c28939b05730cc5f4436058318e6172691532d400f6b62feaf20f6a76d4f2f3845f8210b41a24c9ab3a482590bc51a84a846114b3c18152967b7270101bbbf62f1971d416f15e3ac9d585c195d5087ed86ac123629cfbc3ca195da92d4994a981dc975b6d16e641b2f571d5b54e4c1a6173eacab89b6092256cb950aaed94828a0c12ec871fde102cf8e24691eb3b8d0ca0eee9928a4a15c1367c289b0c113d447a10e2ee0e174d840631d8f7e397af6e3474cd373ea18c56549b6b02339a2ff69a0a75ec7d4d6ace58921fb64d6edf0cdcedc22e1b83b591c4b07921c0a8fa5461b164ad7fc22b7a5ae0544a41ce377521e928572437ca884d9b81cf2b3ff2f30666aa34d8a5950ed879546469101a2802699c83c203327e98a64aaed438903521d9fd124d025592c9f489c1b5e4c747e2443adfe1250764ee434648c0229ac589924c9f210d2464df0499c20c2834095e9163e1108858b7d31591892b7099f16914ecc032871a3032640934c2eba4a3edc7cc1dc220ab421e3ad17b432ed53cbd0e2fdbac8dbaa3e7a2cf272c99c8e07143c01fe0701551001935d972a825781d8785c1d1346a9aad4bcb500d13ba40c456624b6c004107b369808193e73f39c78c46dd03938e0059787ba87e86b6d564c748e68c2f56f14343c6280b8f1f0f27ac36be9810d3f0d58457020c8dfef9eb903865bec315982a9d5b46f6b8e4925da7a352aa46743e069e32d3c411bd5047814482e8fde00644d8d760ed233383ae1917581a52b07dc8a6580d3209abcedb4f17c283a1624acba2be17705ff70708b9529187591b4a322bbc550a84255a1221dae3a5b04d1b96638a8ce029b034b28b178fef4e96d81b1fbbd76f382d6e44afb3d61183f5ffb4234462a1f8cebcd048ae1440d04cdb6839b90fe044a95adb1cec8cf40c57e6bd84988c2eacec3d2704744f756958a6d09ad633787d7c0ff13f3848b33feea64d5008f18df8d9390dc066319800e12aa7bd3e7ba36dc7551d27f98f6245b9c9ed67278d90083ca3f84a37c100bc90261720e2137a575eddcae26cc9d63d26c31b75235e251eadd563e185f179270e2c18d9a0e8a8a79b03f30f52d51dc338456cd42609998c83eb81ee6476438ff07be23f18e6254cf8ce2a6c5cccf15f0822815983d2ba8f2224715e930ce1a20afb895a5f6b02f1a792c4e93e2bff8c1630255bd8792d24e16b35470c5980919a716af5ad41678280d5dc21345bd0a12d072f99022275f5d0aecc225e592a7be5269d3bc4545fac58c2c61aafa205a0feb619aba5f6885dae185ec3929bce58376b47e323d290e2fd4a16bb5b6fa341986ae029465dd54a1b9a6da4435c59f6dba278f1c8318c7aa3dab486e8bde7e6d5aa62aba853d1cfce5769103ff4bed30b55017e65fc350b60f9180091a9b0422cabc2b89d1e77ad433a05f82dd98e331327455878ba59b60c0fc29df10b2b9024beb82fe4c47769ba127d6477dc5f0e8e7580da6a7d61419224b441f12ecc69a907371e27f55df27a1e81a6f077fdb99ae83221c297ba593c5e6c175e98359ca45c18fa911d3c898a14bbd217c094512a437616ee7c77711cab3b778609bdedd1b4bfca9f4d6e33d9a4b01e05e9826289872ea41f9ddf3d6aa5be24a94e0cb1b4a2efcb9b298fbcd9f1b249ddde7507897253fc4607f593d0fb20ebe865f04a4b417a9b7609480e6e2582fba781871718ef5fccd0d5b18811f2b8746f55080ad0e246a06c8a9ac496bcf994da5369d84ceb95cb9c6bad4dc07d33d2126a90e47b8c015fc0dcce634985574f7c7078ac611c52343ecc1657b53a4449e2c8c3bc55153d0b320f2730214b20a3e7531d4a965dc101eb0ee38142c69af2ac49db06938061b9a8707df3d95123c3645b126a170452a013ae318a164a835b904248d66a1d856048807d598c67f4046736356df1632c45421fa8907b2205a9173f6b684427325ca9aba322b8e45700d98c1465fe81aa5d22834cd799c463f9c2cb7f11ec7035aa591d2b01d0ed9bb4741a1508fcdd3e649cfbb94cc6a4603231dd2cd87552aff2e8ed4ff0554948be6e9bf892c5afad1f81144e0192d50de89ef12172f3dad380d4c36643769470c167b20110d0490ddfcb68b37ad2e0cc7be9ea015b2ab10cdfde5f918568704cf6420c3be754030a82e44e9cd779b5143ce2b7b97df0ef24a39dacdbbe5db7e2875c0a63f4a0e9246c19b5e2a0bc1e6768d902f5ac759b94b8bc628aa2fd7a0e27f91e7e28a3f57472c42568174ed3aea5466ba0d141aafbd08fb97f33d1c1bd6b078906206371e73945e973074b2ec2e704d9636e939e86f59d4786d70b95d3aa7a717601a646954c6fa29bccbaf461c871374295fa69b0fc6481dc209fc97e95c3123d8efbc529411260adc03e0795102dcc59d4c42a968fc44cecf7b10b7d4b6108e859658964e79c271d4e80d8c44d085fe2b412ebd911effa28dfc176a3480f946030c1a1130db3060e8a5cbd6ccb77dc180a599aec5c42fb9e79ff8f55f96aa54d10fbf64301c9785bfe05cca19cf6777d5cc024f66a4e0ae9ebffbfee8ac50b0e26286f757f2cd690f8bccdd9dbf1a521152cc37844cbdaa379e2eeb9219d5bd12aedf7de2f1628f7817ddf5e5ebf7652c45ca59c35c1523ef77b56c5a63316364c4cee28639c0855f32e25af5b01726e83062019fd603bea6dc99461ef15fbf0042c2a20fcafb254dac172d63c07af42277d31de8a50580c0a9477252910b4fc2dd04a4f40d1a97d7ca346097c75e63cb9e22110b482ce3532d7f065fe78c6b0d9f3aedc819a82ce65ac62c305d66f884908de6b50be2bb6c4529a7a7e1c60c29872d564b1f4bb973e00512f7b5187d604e74f5fd2172cd3b614995e3ab85131f7d4a730b5ccda2aceda7616dd062fef87526df3efff82233a8034702f07a86206dc521052016d236353802e0f5110bb16d345cc04aa921731c7d4302c098b30568419a273fd769a2d2c3b2e00eb671605c735ceaba0609f9e2920c37a366d4c2913673d03ecdc010ada0f9fa9210625d90bbe4d6bf514c50eec9c764287f1d6cb51c125ee247720402991129e918ee5df442e6ed64bb0480977a6a481fbcb865eb8b22066406ee7993fc4b9cb55c88e597d64358dce73541d5c60598c7ebc0f66deb1adbcaaffe3413001a5b8cd927140646e0305940e87a98a96195ae6a0cf2d2f1cdffef1a5c5853e4472731e67e129078b778fa65a362a443369bec1e28286e1c1497a69159243b5c8431079357e5eef6529c85009648ee58bb520caab9a10ff5977df54d995ca6fbdf9c98525781428c597510856bc8a7f4854634d97064a8ab2635e1996ec44258963c6a2d061bed92d12d0a75e8b705e8a45686a377212fc1d0d81f4c0568e3076326f02cde46b1197130a175395c4af1ded2685c9227043a3742132ef9edd7a893f7eaea605048b086f37e296080984a44de5c391766cca99e37cb05be387647c007ac8cb2d8b78a5083b947aaab72986680c42b41a5fa4fe9aeb04d37cfd9cfd216f005e2aeeba6a5a5b72acb98cd66293f03ab5effc98f70d5a114348f58499d4e99fd4485e2d20df0204e0a85ab63366f5a2026bcf5fe6a0bad5e00ac2b49aed0350c9900faf24452c6fab8034e71a54a430614428b080f70528346456c4d3e22663907e95c2f8dd76f1038bcfa802fd109d202d1aade0e3ab940f488830c97e17524d568c782c0956259a7b84ead1d1c6698b67fc001b1b721409fe8c35ed5b21f8d9cb71ed728f68ef883bb7f225aef60a343aa106c73acc476722a20e371b85c4ee4b360ba5731a559108a58f2d1cd2c51d7f9e493708981fc2bf29fb70518c63c133dabd53630dc7695d4fe5e13ce216789f2055cb33e43a335a6e624ca2de3c8700ea9463922eab08590c281c517d9e73e37cedf497776e0dfc8b2374decca073d9f5da7bbad3c8b45a6b21b65b79b35a8d15c7b06c961e822639200c2925dfdb168b5813bc251f22e6ee530eb95cd10a295ce5c9cfedc1f2e2c718f3b45d82b97cf9db3e9751817977466ba131e37112964c00f6cda91ff4cad0cf45a813d412c2d39c128380683a40f2761dfdf5fadc4e17e47f876bdbffd1a92764051bf0d32c0f4f1f635eaf3caf0d2e81ccc26780b9e57443b8914360ba4c9700d7788b67d8c346ac2940e3413162cf431837799e80f2a61d141c2fc41beced29b0f3dfa8337e18e7a74b89f809ba6336df23a650a539cd9c41f8269461a3633c1bb15a8d9d05775aec94441586b7ab41e34d51cd809ee39547ace9e502a2d298e79583d984bcbc871fb9a15e797bdf081ee3ffca60e816d07f52478df161781dfa57db579425c161dda48f37a824b9c841b1eed767f0f72d81c8b5155a68c26abddd9a3eb59deb68aef2564120887b70a276d0abca538efdf01bd10b2df9359b47c8188f4743b35264202fab56348ddfb6e53023d254120fa423bac7b932233e04d81987ecd36240f8b13a51ba5a5cf90ca1da5d2db859b72b5851a69d5cfc796b5f3128a35dc5eeb4f7cdaffdcaa2a67753cc62a724499c7f30bdb5998531235a2f28fb7e82aca7cf2f6f66963663a0f0bb3aa6967da43284be65bb67b459355d505361b56f5de41c00d6bc2c0e1e50f2e69670c6c2510b0b78fb2de505d14552718de048154e25f15ca5d601d4e5709152f21442aea85d9f9ecce541070319701486a5b6de6d0b68fc019f4dacc341944d01881f35dfbb5db15d5d536407cdd48a00a08f6722fee9da62ca7d5eb1f79c062e37e6043ebb0d574a2157687047865819842d0d54b9755ae819d94f21a74d49a11cbf1fa7f46c7e4a240790f0838fa277ee526300a42bd639211c5c897e27d3dd62f0810419ff91d736c7705543aa6970b5906a00f0528c331ecac3d65132252e5cfb738d22fd61abe59fdecb47f2625f71c0a7a4e8f2a35ba319710dc1bbc91e45b3cae514b1d35e92474ba5d00cbf58ac81b316c92c046a737ab77ba3ae5f427f5f99875a840600f3a251889c06c69b35dd93c0748abf2d840221e175b59575e24a0502379a81d1993f2385c22cac6ad0352c5a7b4569fbc8f24e33068b2069ca51260bc83841394c7c70377419c695a2ea57830fa920697fe773af9386104b5867e9fe77dc031d23d324f5f103f8918cc0870c65745e92450363c9441d1358a09e980a3406b492e8b56034ea45fbda1d2a39d662d89f30571482774596511a76a216c787d110b0818357eba85301346025a85bc7510f7db4326f8147dd948b7990e1c4d0f417a6773cac38759b84ba54571363b141db3f00ef6391e817846440e79bf8b6a345e785ee7c1c970c7faa7a83f169aaae45778fa236f0910ff93a9ab30b450b06b17c4be38edf28ed54beb2dd8b400f4d7149ed2491f086bc73bf4ca10b2ddbc54e0bb7a7da0f31ac09ef3918709c175e124808a3999ae3068595913533fc596adc97de00fb0fc60127713d3a753a259385247cbb4a8d2f3e9e6337e04743302cdc05c3ff120ba03b172d83bad44bf9d0c43e2d14fa5a4dbe26bf3edb7567b46439cd5af8941ca941c9f00a78bcf12fa5ab04a7155f7362bb1d7d70881aa6c49d6a84fd9d7bed25cf12b675a580188b96d7f4148c032769bafcf4488e9a22aee8cb2b223aaecb817e44fcc186499da0b442d045c74977a0182d657194a57d0b79022689d5c4032cef9c47233adf373a370598b61083019a09061e14381e7b5de3675e5951c2284b91f1d536c01a96b80d681bfe1c7342cf8aa13c58f7ee588261cc62d72ba03608d4a6c09017ce6178f4d71cabe992f1720ca6ad41ee7e1a471fec179d122fe70ffb2ae91b7122f7fd03a19eaf171852a7f2f01df6aec0cd211715f88ee26c417bd4f755bcdeb6bb8af7f11e21d23cf1412cc40fdc5249fb91718c328fd791f021a569ef2a0b4360acf1cb30477152e6e8960e73215062a5469d683e17d5c9dd428e7617b9f2b286d873a30aefa9616cd6a50eb45923b145d2dc181656dddf352848363793099ae70b7d148f076f75c876e663d67aec832da9acf9cc4e6ff47042b61f25341ea74cf75e05d6f6fe1b2c57714a9ebc86bb83785c384ba7f6ffa5ad508bd56d661077b46b122abee5efc7d17928b7d8c9f438d6348344fa852fc7c6ebeae4ecf73f21ceeace43f09bded1111ab9310ea9d110c7aac70c95693cbd679cccf2f415fa98a68d0b977d788049a2acd1b32492184c7307c59bd4ceb7938e29e7f2228d807cffe217e8f8425042bb7b8fd1d39c1d104835810ee85d9d002691ba31b315d7dbda83c2488e9998caebb5a8214d5686eb343db95293110d5a403316c62a68805c4b110a7a0f58cfefa6795f55139d461eed8380395a36a9a81b5bca5745838ad69c8a773c5dc9bbe52cf4f41d968357383b1011eb6c8dc9206c453698d6eee7df569dd3062ed606c41201d3c9cd5fafac35c041c6dba1639f679ada6a6050387bf92da6283f65a6b492ad7352d0d6e60c07e82d965416bc58bc7fb9c28b32c53c142aeb741583ad852539fc8ca7dcb6aab73d58048aa53799b4e7347ab61b99437722dd893b3ab8537192d0b48e1a6ea5ce035161fbae233b09ab3d7709a692144b7afc5c086b75c710890652102ea8103c36832e3af03f1a3675ed4f468492037845fe500071d6c78854ce9e5035cf0908d42af389a7279857025223b5129734086d9fa073e819f579612be1088baa747ad6a04482593c80d7b9c94fb329b6b584a22124b0b8f4c8f1754d2b62787c9d45b2802e99503ece3524a8e6c937ec76378eeb205aef19180759a8ca585e650cbcad607ecd1e2852e64c944555872de4aa72ecdcf75e070ad5036d5869c2dd6e69d3a49d1abea0ad63e0da33874de31e7be95287e8445ca7d1f21662b2b521284aaea96060b7dffb2c53d4b48169ec0ad79ae4ab61903c4b52ca4c9e5b780fdc11436f720199391c2a152609634fddad933ba2e5d9a5cb2b9c74df4bb3d24614c10bedf6054156908f7ce0a1734fbe00f94669951cedd5f840e9e35115584c20f83b5c32564db895c83cec66dba0e755ddf7a879263f8217269f8d9b6dc7a5eb9e036e4aeaf81376c352c9d856b0bd0c5da5e16f240c5397997d0f91c03a11e58117ecc94183a38bd9c499d58963f1ab53ab527f205f30b5a470e9071a60c26fc104025d13332bce4fa8612fa0c08a5ca40c59a974a74b6cf415cdd1ef4d8ad139d6a698140381a0773843e1ee27100ee834271691c36f6e5fbd533154a520ddfcff167b6814c80cdba2a4d5c8046605504caa6e68f58fe91331c6da7f049c47fe801a059685b37a7538468e141101b320aca9b15574e3cb40c0c4f63186251d7b357c14b3939ecee0e8b06093368e31ac552c4beb14926cc567df061d557efffbc3d23fb9252ac00d98eb3e859f0ca224b49332b42e8ad5f48ed5e310018deb12e138838782634b0fc921322584eab99d2b0f64e812cc434af76ee9183d7ae3b2277bd1c3c8e40e38eb47153666be33b598cf20a631cbf7d4a33cae5df5ad6663932200ad1ef8810274f2f74158630f448c0f2784b9ed7d4dbc9246b781d75431ea1d5b24b9d4f06c705e26ac1564fec6a56dbdd40971d2ac5bcb312d1e7df8afc194644949f963aadb5179e486bae8bec3d3cd9e7f34eb9265ba15ba2d418d127d10f5bf6932d9dd772127c402861284d219b9a02b5604c5a63d229ed490d86cb65284701284d66da7ce01061ce67e57c776ace4eae8ce73b12d28c8cb3fe8c68b93760a9f0ddcc57576150cb9f1be5500aa1ff19e29d507c00d304cc259f8f78ca64e2d2a3a6affad81ae29f5e02a4a75b63452a6986e01f6008e8bcd2425c572da25d6c9de12654d30925c0211cce093df0e3306b306cfdee61b9b6563457dc5f544e8a4313ff58442117d00f965f4caa82632ff86ecb928b91b573b826a911268bef3e737767a7481fab72c8847e0c91990a1be7f9026d23a8648d4b292ff5d91fbc31b16447092b4cbdc11869da3331c873b4162775b7bbf8a364dec86255a0898a939af086951ec2de9179b13fb1d9be0c61a2c27f443c80bdc5932ac03d8e54f63a32251a1feb1ec64926eefee9c00047723f0405248aa58a009480bd4fe0789d28fd2c20f73ed4cbabd2cedf5bd6a01b5d872ecd8ee3af1c63aa598aab739ac6aef0a472fc30db39c414fa2dff521daaa0a0f16ce0791eeeb11c2691c14613f13c0ca4180ca0e36a6a241c6bbbe6aebd2969cc32b67a761b52387151423981010abd9a5cd265b48a891ef8d669b78365aa825b50ef0e939e701b2480eb5cdce5d3f6a0dcc5b40b850db4a85734abdd0a9c84638e01c9abbb63ff533bc2c1795616ee0a794693855013eb5267093c36e1a8bb6de3fad2f23a9a4293348659ff86d3485c371d42514626ed59909cd260175163186752c5c96065ff548d6872f9ffd3938d5920a0f9f62478ee723664e3e991c8214584d5497ec0680e9a1054c7202dd8a91af6639130b17b8287509d6b2b67a4d58a99e06ca0f8477d7a58369728625b20a2d9b34c75e2325199e5a1c95832279ac6afaa0b26fdda0a29c844e387a124e0bed0ff36ca615e4c943b08dac0b6d81b052e61c2689410f71d1a73aa3a0d98b497f3ed46398ab9e50f117f6c14186930c421faa6c36e027e783b7eda66e846c1c1bee85bf4bbecec6edde2252172e9eec97e1a0b4778979e17bd7cf3bd7ebd22c7cf6f141bebc51966ca6b614356e2fb14f68344ae0b2c0a6b63567476ae568ca02352381a4215cceb990014507c8d8fdb72395c10c2241fbea96ee2217e1c84d02ec5b9ddc3152516ee5e8d5db8f8912d878d80be9dd40996af48fce439c096b3f8a98243e3fc5a4dc5e3de5e395c07dc97f1aac471e035d8e2bfe15050b82d429cfb94ba3159fab44c6ab47da0a85250d7c744106e30173eb1999f7c0aa744e1be5c48bf9a7382252131af09378e7b30fa0dc931b038640ec914560898d67672be58016b46744c26f40665f62e3df19d8e06c678596e003970d8ef27d4ccad6606c604fa35ecc1307b6636dbb9e2e0bb2655a2e6853da0405b46b34c8dd896efbfa8232fb76ca72e9f81019cd43b90f17258c83b2647cff6edc9482c2bc70f8f06f2b5f85ada409645c2004e4467e860bcb94d9515ad6ec6bdc5805e64fb61d370c78d8521810c4beeace647044caaa1029895bc081fbf144429cd43511a617168e6c284f59637c3e5a4f5a54026c7b41fc033ccc4a5eb3f5e755bc53c78a242485470f89a75d3886e3f3084e2fac63687d909301750909e50ce1d032517ff3cf74394c0745fb55b9eacaea755b49ce3d7ffbb5006e772e44c515634ed070b3d17b12ed00bc804250795e366acff3eaca9fd10253d85a7e42d910a04aa4a9f6e4b444ae9ad38e8aa55c7c98cd28a62d77d6c2f8e11e68256145969a64064afba6907db245101e8697c7ea13ddf006ba009a0317ad1f13b9a8b8e093295b36c4c60b63f69201bc9f80b0dee545dd1424b7b5c6b9e86083d9944eb657fb52d3f31b9cd685fd0dc7b1569d32363972af0fa79f9eb594703db03666a0df809543a49cbafff6ecca44f7c4b060b0b0e26e82a14450e01fdf93721f4426f6f0112b8c6f142a8e2b36ce592b71722872b97f087e6cd032de86d7d37ad077239ab59cc4fc1fab31b1707b3475dae35a549257f9ffca6c91803436d1578ea785983009fb0ed6a260a78a369808e7d9443ea72db6064ad3d81dc570c439a75053eca6c2818f64de745bd038118e9f8ad1d9c121d6b9692ec03c357664a032601f14977cd42fdf80b1ad8acaa4c2fef26abdcdfce576767b43392acc642596ac0d703a36f703bce422a882f09530e5fabe2fab72e532ef80b191d9544c2ba5945c7e64bfef8380d8443a19134da2ec89c6ae51d0a3958137b6d373281bf2f32295307b6910cca3cd1a5017e41c3aaf4c86755dfbdaa48c63bdfe69c9cc5c19f4f2ffa2ca9a13e0bdbf65915d7dc51f9915df6cbaa72f5b7ac449d7631252862e91acc5bdd8e2c06a45add2858dd1ffaf624fc6dd02a309d596aee95761ae64656e98223cdc0a058aed3088c39825e494cf737f1b08f64eb123768dc17677965a736bf361b6db278bb5b94670f5b80ae3d92b718fb3257f07746ec6b973a5b9ac9145aa4865755890c7341e800c2bef8f1e94018eac82ecf5714797b646ac8d641daab482d364b1d96ec139d535fbafe990274e5c0906d33fe54891fc8dbb44ff5c0a70d115368b53bbb8bd97ca1526e082e4ff9fb2ebd9c69453fac817ad70a4e6d6fe3695678bba6b33bcd554e122530a042b391a5aaa8b7d842fd5cf6c85a3a48b8079ea9f921872464c996acf9291a799a62506181441d713e408fc49afa6cf72a5bea0bbeb9eb092994f6f2b7b61258c81d96b3a88e3c40159c42fdaafe69f74a1270464f13b9895f265ea42135da7d756f5a0192c29fe74a98f30f14e80a86f84bde46224561f4c6376010a0921e57ba5ae7bd5cc91f91e90255533da8b6ce3e53c0f6b61d4f8e97b29f10f32940890ab7eba61b8d8e5e9750c7ac36c947e5a273d44911cca3855801e7aa0587fd597e32fd84d509a7263cd8b877eab153a602ee62862bb0bfe81df77db6c25b1af86906910bcaefd65e5910a14f04694e004afb59283cacf30e35b8502fa462c6332bf3b8eacca80600a2f5c6f9816f267960f456a5cab919703c4a90e7fb79fb246cbb2d306a94705fa00caf84fe8f9027d24656a9ab0f5f9a8d4964c463a0af65943ad80b8da53136f2ba348a1e889df41c6192d228c1f7dd862d0cd2a88314ffbb0b4883176391d5db90df09755b1a78ee44e57cd62778b075977a671130c4c442f075c55d3d4661056262633fa54aef6e3211cddddd7f3c05d1dd7ecb42eb713723133807f5f0ccd79c24e2a83f2c61c42e6887d4ede88567403e3fde8731127c1c40114013f38e7471b56192a7351237a6cb9a8f5bed52c507d1dec36719f7610f6cece89b34b29b29f469a8bc064aed9028b4edbaf02cd3f67e8df868b0128c721e38a1b878f6c111a2fbd5c6eb20860ccac7d72f6e4522f76c5b03d5f83a46813febad77e7fd3a03f24791edef1224963674b91729ef6fa7a65f234048f206f0f5efbd71e447881bb6ccfe1a153f2cbfee84d7c0e48bd015f95d2a8faf1f31fe37e185c6ba7ea31488f8cc2c5339f144c02c5c022462aca0aae16111cf4ab7bc363f25a16829483a562f48d811320305c2a702bd85d25e0ed2ca9e55adf352f9c45bc1eec570d7ab822484329406b8cd544ba7f6164b817e25f476c54206218db376b3d2a59bf7ca72bfb6223900c96ed8f764596fba8e3b03ded4f924626b7a8612765af59ecaad4d60e18766a408d48b8750e0012f6f5a9b552063dd685012b59fe8d470a059b4755db3f25634f0a438082a947cb09b1ca8005ef53bfb2c673ff9c91bccb6071c4d96b1aee2b2f8fcb05e6223520844b0f92114109b492f0f798345417a3ba0108b57da5f5025de22c44c2bd53e8fa66e8776e99aae07ab72fddf0aed78381e39dd60b3d5bc140022629c4150e5f2c9bd4f5e0ff5d308a36b6bf91809741b0b246f9784768b071ae995f18f5524645ce2e3388b61d7f457f1ea0fbb74b829aca1c82f47e2c1b746477f3752e24a1ec4d3fec588af7437cbc54e4f15d30e55df5344fc100bd01c72e47b383c16e097bcb6974ca55f163dac2fca4689e64d06002e64c3b85ca910541237653b1681805065f43c77ec9d58fdc3e328057a4e098a932877650c890c6537aa2d8ae022dfc7075232a87fb999dfca52d325340f62a9f6825cf2f57634eb1f2484b10d72f200cfae32bf77c95d2940048b5f89dbf461c5b0ab32b936dc8e76c354cb8bff1bb089dd4cb71fc78a25afd5c9b8194ba7cfd68af8251276571fab9a2a214409fbf8c4f9f62a87e9925e049594af8c21e92509189156c2628074bd2d516c83bd4c4329754cd0487cdf6ed75498e7bdbedc859a730a7f7f132646d50e024c7ce42491062123ab455145f3900626a70c65e9f71e78104c5177332a35d4abc3d3ca7dbb9c09967e326be7bf06889699c3f08f2cc57f313398a37072d7b775f3f907158cd7cf26e81020d1b79d8931741a107853033d403217af97f8643a4472b41e4124d7d2dd66e9257952e44c62b97a6a0a41018fc15bebe7eb92c6253f3d10249e4e8762d80598af47692f0408d88142698d222e0b7ea34fb48c73e554814f7f9c305f996d5cc9d74b3a5c7d221f468a5f6b427b9cd618792a25f97e520e6c2d9ff1ce8c6028991b3cf79ed0daaf5880af5a54ce2b5180b596cb2cb56703e5b373c704b8f813a66db036a332e2da00d2fe3965a789789704436f755ee31a2f7245368a0bee5a17a62a02b325cc0b1ae6119998d9a3fdb2804e401333484e4b67c64758bdcb45c67a1111226e1959b538b30b3e0a87a12d72e35d59f0893901dc1826385fdc6ba7b628137397a6a9304c74784252a6b688a83c70841333358e07454d202f735bef6d4ceb38b744aa22a1ae634dd144bb1d448d325aa4260ea681735afc3ca06d71ea5d44c9ed22f3dcfd797fff7441fb8a2bf7740d2a5b6dc4c7f31a5f0d12cf13095cba14982e2cdddfd3f2a76b98816ca788465737183214acb6ea27dcb421ae7fe3bcee22c953cde01c3f3bb3f2e6033c7fd4eb766c9248758cbe7446d78d7e73a10f144f84c6611104e4401f4414f9c2857da3acad1be29c1d53ff1c1532d70f60401f0c0be24f0ab2790dc11e4ddc24b34add8a1c1e4435f90db714d19fa5a09aae39b1ce2572d09e836e3f5461383abb633e12b9d2ef7b41688c59065e8503409531f40d1796593b6285dfc8eb796c680427881a3d1f3e708efba17a82072f08e100029d60020c1959abf46fec4d1e09e81266c34bf2c7a868e188b43e06cd1d00ba7b0445830c5a7157084772bd1d78a6f288d50770585704e608884f81084a1314006c7065e25d5115e19b2aa477f93c7c3556741b841365718e0fdf95a9e359d1815586752d249d50de19d180262c0586532741a2a5b23157cf22ec71f6434f390cc0bd9b964d5c4d4f771cfabba4835700121850592177247c56f333d78eb708a9ee8ef1db354817688a2d390f8174d9b25c900ed96c4bad95ad289899722f83f0c67524c93728eb379dda7975af1556017c247e5aad3200ed05abdb845cdb14b5c8d8a3209ac3abacf3b876c4330fcad27f6e38047284c8d36e442e887a87bc6e043cb40bfab7e74585fb28096dd12c42b09eb6f9aedb0656e75d33f5adaae573fe2df8af5b8ee3f9aa74358729ac1ef63b31217e589b53f3fd86c6e8280ca412ae09278de009871e1241406138638e82558efcc1aa810a86489bb6a459d46e00e8b47c182b42d536489f049499daab56448c33c9454c05a9bde55a23da8b2b27c01a900588b311db1f700106c6f33d05e8eaf5ca2af61efc0270ccb94882fbeacfdfce810ea082adedadc1468baac0b6bb1a08108ba165bc4f71707edd2448e3bf2c011fdcfa770dfc9851a347f8367394d507ba466f6b64562178af752408f4081c3a998c9c8f810caaba2cba021783b75df7237ad0bb4abb161403e741e6259ca8c83d6106b0f007ad5818999b45377e258539507504c0f8454a97748e950b6fba1e08626aa0d79286d44831da1d0c7c12cca8ce0dfe0fd426922c3df06a6d6aef202480f38aee00a8a8eaf49d5cf199a59b5cd3f9e30e23e806c22bbfc339c64e1f2790eb708f49720d0af75c330751384268f5b6e712ba0ee2a4288beef7aab2469336714dd765193976ae746218e6fc2b75a3f413b2468a60238c6929a5e9b1fe24813f95b8f03de93c79a522d4d9261830ca04cb7e35317044af356e6940161decf98494cd3d82a23cd4113e7c98b8cb6c9ed36c24546c1eadac466c83010cca630e1fda2b81446e70ea1effb5c114c93e88151203f4bb4e4c2e895dd47310c80b93c7d8db44d9d41860072c71219e7651bbf5d3f5cf6ca4d9c871de7e50431f87fb2380690704fd11ddefa4ce3044a57ab90e9bfd7426c61195644ff724004b871ea141c721a6ee154744cfcc36c85774c32196df919d473c7e6ae145ca47f29c38519553efc5386ed7139d30d2765a2d691b5e7e932ee224d24d1abf58ec8154682e1a245a3adb6fb24ab5c453385a4e3a63d46a2ed7eb923a86df782c74e3716f87812da472c91e04852b7f7002ada2cfa32c61561112ab25b45918a7c6c161ed42dc5625ff670e765e643267aa1e886971a9bf70c18df3c73bc1cf864321685047cbb565659a208c7a349398edb48dc8844d9f5088fb1d0a60a51e1d9596980b9fdb1ff807c03ec024c387bbf8d8c86d4ff4f51dce3507172c8b1c4244e16340560465bc75062ad451ee64ec290abb8919c0e257c886e8500b0d3042eb4bf07b45bcd25d5d79691469522728064267fb81d18eeebc05e5a0df6712cd2c6881f9f23ca4ef946af89882cd13daa03f30e669e1bb2d48289bc3796271efc21dec004c2984b3e3deb33a0b4a3bb574b7d300f7bd89b6d01c72e7d2d3b391f0c9209bc6ed207eb8fb03323d9777f1b4228e95d9572670ce165e71363d040bcea587ed209270461dc84439a8f8d6225f1eedaf5222f5e4d4342aae9993f1aa64e6c30dce482aa7582278cfb66b4eb071f258f163371561a1693b0866fd0a6bd1a87699bdeb4b3787d7fc76fb09b6608fde1886d0a35488b0866f224f6f1a694d48b3d2281f42700f1d847070f1186bc846c1e737d99d51b3a38778b9f417e2823f1702806fbb555899912ed4e5a0ca8147efe442f4dac3832683da8d87230e33e095f21d6265894f002272419cdd48d6c9809b48bdab975f0a93382c230d244cce03181b63590d6cb61785ecd01b5b3487db762865583ea813c696a0ef9718e79c7c0caaa6488a45a2ac8032c179d105fbe85606ddf96e8861a48f57866b6ac0ee0b04729811c33220a6a4e25f28209a2e29ab4aeb30172de98395774f1556ac756b86348dcd37f86915b4bc7ced33bcb30b56066ef96e6f4bd650775617a210074fce1adb1b480bfcfa40b680a2ce011676e4f34c15c16d205affc2115b4a1e58ab201264870a5fea983eababbe62e5818b757e1c7c03b3e71ac8d702ea4a24f4952b485f8f6bf21be08e3a3ce0ab90daa8bca833cf1eaf140880c6543daebb9fca75efba097f7cc69e12480f2f02b195a438f412ad4a64ce71f623c5c7fd4bef74793e3c43c7768101dfcbc81eebbddb6da996b69332edf90b2c20c1a8486145951f07e3572d1d749e93c3df877168d646ba15e596dc0b0a5b3b29052cfe8bc97130370f225706c6e634f56d78f48aa84be647ffb24a8884e7ef32f5e4362b2a12a173507a6c0d8e7a5d13a654ed687836489320109aa34fb96b7895f7cfd36845c1d4d740d7f7e3d97e383f6d1662ceb9fc3040d9657dc39ec6ba8e5865bc4902ec3ea1ded22f605687fda7c41a9d32c64d34c739fe709ff85b4c6c29209199951d6938d3accda101d5b98ef332a495f532ea1f948cfac70b35a97c6a9de484ca9f88753bbb6330ce796402b7963c2a0e19d89265961644fac5c4657a9c5a2f57f1bb797caf7fb8a93cbf7c36fabd577281f04aca21bb4fa03f3fb44b6df8f0d073835c4b9c00e783e61b27d983d1c0e3d98b69f0ccb3435403a4672fa9815626259326b14e2196b9be3c9f065c5e541bfc5baf006694fdbc4471707e5cf9563e8811c800f0fe1826b0edb1dffd7eac5c01d223446aaa790dfc1de8fa379035e60a7a4d3f0eafb19cf858ae34fbfa7c6c177a45bdd92df8b8aa1365c1602a810c60592ec3ca42cede09233a03bb118ed1dc8ada103b7c11ce0f5bc52d965a67cdbf566e8e48bfc5d5309ffa6c2b445d401fde66abcc420e08b80842014a027348ec764003d4d5a571f92859aa2d3cd92c24852ec8d30268466950ee32de8676981d1cd7f10306381c17facf004a75e3c8f990af28d3c93949e026bd5d0e106a5e22d300c300d6ba3341fce88aba86545339c439533635d23d7f366bb3c30dedd3c5a9f0cf582af0dd58ae02d42020efbc573e56566b5082dc896301f0865891a696e940a5290ca8ae72a64ef7b2f68e0579afb751e86b8081081d6572704ca4547c142950c4b799671e9406b26aa120593df506b429097b17bd14f69d4237c239106aa023271626005749a69420b8c1e4d1a64af4586598243e364acf86a96f2dc482727ec959787ef8709c37f67fe7047a27f03f821ce91c4ae6f8a9e976eda6481d3d334a65f214b12565f4e44b4dd9ca99e61c592ee194b5bdccbea48990d4a3e6b1812c7f4db00c7d220d7488276622a16c4bb8959d211efae018b3b150145347b0076c2bc2d440aee2643401e32175e1ac0d46e03c180288a30cf18d084c5ea95568eab186fd3076156fcfcda8c61d95a6fd5fa5158c4f468c4bdd8a0cdf3f5dadd98fd4cf56d990882ac2659adc70eea0a515b8352e55cbc216cfd3f2f3d07ed9d3961a8d2514c12d8424da5f64ec041ecfa86314066f4cb822b84038bb6e9c1e8e981cc9c32d80201f60b395fd2adfb9a4e7c865729f8aa2e945982d83d76699ac55674f7a45de18a48f7f79f02c95d05ed06a880df3aafef0096336ec9a4023fc518486b068ef272345e24b35a85bf250ebfb159a51a66c975b6cf99f146b54480cbb642ccb54be44fda05c0db63a35f5d1da873dd522cbdeaf0e8110cfd342fe6a04f76d9b94ca8e12525f52fafca091fb3baabe52364f19f4d8238de9aa34453cd16c97b9e6a85e295b0df0bdde411765423e54f4923462bc4b91cf6d5e746d19cd23fc15d63fd5becf50072c54214f43817e6e4d957f054cac0e9c24b93b665820ac208c3fd388df7ec19510e4884fe23f319ee2265aacd350ee937c72b738741737cc06ccc86eedbd1c77ea9679f9342a259a07934a5e0053225f32400cc6bc542b21965957e4edd091a5a2d3275be4da9cd22b0794ef65f2ab0fb34fec7a42f5da64f2540a3f0baf66f29fbdda4293ffe0bbdd6999689edc50911d3dac3c03950230fbf34d84d98e9e8f00b849bf9f7f9a78cba53988f3cfa3c97ffe0dafb10ff114d6a7e53f9fe64b370a7d690e4c5ff90eb69f72332aeb73e0018dbf32d7ec1e453867fa810dd089d743714388d1cdbf555dd6a7be07461baa16fb81914dd4a7a629c65fcc69623701afa5151ced1eb80420a903921115c9111adcac37c4d8940052bb647f4228481cadd93b6b7f226c9008a1a0139403b5a84a4c89076782c4468b19dd9fc87d9bf411fb3562d5429d18e0fc3a46a58629ed7870008e8a277d306fe67528c16dc4111aeb0f67130652e430cd5c9a035fa86f94a5a7c8b4e6401f1cfe55acc9219bcf9be5a485521116897f5cf538d06983ac1ca10008b0c457824952aad8e46e923e1b183d83890eaa5fe593930de4f9219cb9a84997d39e04ae69a126436918823a273b8b4293eaf1e7cc31ec558e252c7bae682db0a0e0a8d4aed7f591e90937a22dc916850669e32686883f18b0ebe11dd21a988200ca1d3bd2f2d4d805e35e61534ecb9338cc45df7fe7f1a7872d1400121f4405505bf9f1ba2deccae23f2015de635718b8ec8d9af27e676178fce24d6343f8020903380c11db623b88179a723e3df799ce186e592f7ab0154b063e27533a2ffce79a4d3bb7f044956152a0277ee2deacbd5786c55cc0cafa4e0c21b6b3ae23cc57b30a6ad04a9c78f733d4236c846ea0e5d34be3798a345fb23ed6ce9c41509f1fb2c130fe383cd424d21289cdb16f7543b0fddfbf68e4f619f70b6db8d77d89c83e547503d00ec32d0b5f74a2f127cf14280451e6c2f3d50330ef64c18ab92e5d4dc3a05dea43d2a172b1a6d369f9249f0dc34b890eefe7a89e50de7c1337e7dab467d0c7c4e7eb519234bdc7c39e30c573e0c2fc9e2497ed1e4c5a608f571d9b49d02f223e75b0614a352e3e8500821c15e2a8169d75aa17f7d49e3dcf5c6cd99ed7dbe311efb4f823baf60c463f6541d0c1cb0cc3992ed7b35cb3bd9b8eea10efb54baab041c39c95f533198792ff53f161f970d9e7d763272c9768f3ea7dc3fdaf6700b93ca58d107ac1224e2d71982e6a7d4f3bff62055321b123cb052d433e0ed0682e3d6935688a344f6e987156fe23d46968f26e32fd3164afbe1747852442f85e41358fc41f07651d6b8dd4714adc6ba495ca2a8086c375ea30ffa28c0a4cf8fd0c70b8affbc42e88d82f8a9eb559644b097c876cf11f01b472b9dca501f4dc945f82806ac739b8df1a3ade6ad9bfe9258e92fcc5aad4899ae86b495646f40259a0a1c890968fc9ec0442fe42b466297790252475725727b13587f50ed0d85c28641f235aa690641b15e9aff757eeaeec12eca4bf33e753fb84e3046dde71ee355074ee7bcbf3c8a9bd6af28d6f446b80b7abb929e4b800a261f399beb1eb5a1cbd44767a2914798755fd611f5afc6667d0b9a20b6b7739bd46dbcadc42719b5a72861a5a041f50584eb392151473dad296466827eb8d00f970c7185c426b5bcf52033fecf822b0dad49b93b04baa7fe58514108c2c0fdf49880dc0200e584061337111a2b37e70cb6981605a2ed8e898c4ebc2455832df02ae46c161c74086feb8faa3f87010b6f696fc375b88b6b72c63da9edcd2aee19d29c70ca5a4bab65d7343c6ad3c6be93ba709cf8a45bc393b5801e12a188e23bc74f71cc7dd25414758ef11791771781f8f3b08f20a84d32d76d6e9035626f2b2fe85ca921f9b489eb1e3b72df0133c002dea815fd4ba796172967230242c8c6ea20575b3c31de623cd6a279a8905ea59cbf00314298a72623f4c4ab7cb9119dfd96dff7f8545e75f6aa99e835022a6c01706a8a306e6b18776d5963de4bd0c61785b84cc160bea3562c2e0360960bad3689d5981db4c93de2cddead492351a3aa84ff36dac7583580527e9de4b58d89bd8664b5a7247a0c44ed38cef910576e4a10c1abe656755221cde6565d20a819d6067a1cc81b4c8762c70d2646039005f96bea7e60988d99f96a7e771a0eb411b9cc5c4037bce68d08c476f8fcb5d67c71124854b27742304a5177e9ecb39851fc845a956572b7ab20e141888e60e8a9051bb5af1fb8ac8a855a1509b9b84edc3ca8a3147d67ec02e6c42aab232a9156a78ab16f50999e079246c2aea5f63e31ece0438eb2f86ad7d62d8ce13ef3c9bbe56ecda1f151a56427e93baf301beb005450451ac890f5547f80de79a715d514ac155ccc2822869c8f5aa1bc40948551143745907b6f508090100b041d5ba2385be169dfdc9e1714cf5247cb76c506e7ff9a4c5feb6f88b8c1f8de44feb61d495871cc08d821219127d1164e3846c56f7fb89fe37952f3729ba436612eb3d43378662a05a3e7c65dc1cbc44acb179e667a99c850b94e65779db71f2c2b64649408d686b50b8e0d85700db58d1e8a7711638aa3f9e12a89dc61408dc52f128c09bf390a7b47c42423b3a839a23be96e606c959f6b849dcb95324612fa29dae4227b259131cca219bc82e8a6f83bd1270293e5591dbc1ca8e727350f51d361bfa9bcdde56792c1812a62f0eab2dd069cfbe9e480a02cbc52806b08e4d216ea057eca2cd43ea0e99838a982f65030a81b4610a2687bb66f959d5382646228089231892973019ac82e42de86d414879004f5f2382f2cbbf922341f41f1e28ac565bc455c9ac9603df8b93b670b0506576f4e5aea5f499d8b0ac7da7c46cea32b2383042e4290d1f6e7d900502f960188dbedde27027a0d2a88332c2b8451ef2545f003aa03c3f865b28703509fd6f5da87fb022d2db44cfa5bf2132a8fbed6588259607ddea8d401d667fa0ff16a8969fa16b527c796921935e11ab9cdc276c417762a655b66a1a24915089733a5db389b41adeb15549cb13ed77446cc81433fc56dc7b8d7215841981a8304434423e2b09855c11db6d85c0ee20ab8939ecafcbfcfd617d64236ebe561efd5ef17c91b10b72a06952a9ec717dc88c488b5426477f32e2a7b13321f49df60d61a016c42691f6815adce1bd0f3b42f3f71ce07cae44bc143fcafbf13656a9f299e358fe82df016496877e3bcd459de7b87815e9f88d5f7c09acf6cfe8ac973fae0530e45dee997a80af2fd0418bd9fab6e0279c16cfa4e0faa9db0bbd585f58a6042ffc700f9a77c8e0c3520f5e6c073bb426a195e67721be4dc61ace8ced95d7be69d4bd59f445788b4012c2aa77e3c76c1878b6624b40ea7ca969ca0570d5f528798182a2c5543025d91a5f91865556561898358e7b3b567242d5718f4a4b836afb11ea1b05981d463015f96e293e846038cec21a893b2e0535b18473627161e53c67378614ba7e0c16a2d434840c2a1db315d94100b552253249cfa9d944899004160db803aa86c92bc07670fd0f82f6ef2f855ebd9eb287042758827c8390a8739091dc50c28f401c686435ba6324294feca9249e75f2f86c09e77c12daf6c9d0cb8c625108408794d8230a2d7ed032694b4536c4c0954603d1f22a8af9232277573d12f29898aec7584c8c7dd574b7e6c5f32556c56db57f5f54ebda419ec1d00e4b38de54403e71cd560754ceb93a98f7f0f8e1e355f9798e7f5c75627b0f4342a660584255e7175061d637dc185e0520559d8ba899311c521dfa0cd338e50bf32ec50015b9fe7aaaf26fdfe03c20442e77de90398dbf8a9152990968cc23ab344012bdae77346a6ddd4c2c4342c3f759ee8b22910dcfb713a9f978d7a8a8896dee51464762cba19456ecd68e42cf0e3f9edb34be38d098e1c6ae79a90cda1cc35df06ca4a777b4f99d88fb062a7d29079f803a241ea39e86d67d7847e21b4eb2f28e04f075fdf8c60f4ac20dcb69770911f17a27ee66089f5b9ce5848b28139cd60ace09a77a5e1345542a4b08b8c9f8af41354c806155e7c49e98255733f24f0c039b24a4af454984788548e74d8c45850aa5d3ab8c4681f3f3e1f074032580f9164288f160c069a356276e74e122aa4bdc9a5a353480582c02485a86fee9852802d02c4e3f9a92620b65ec9d6c88225276642cf6501dd69bd898ddec94671976d740b448cb9a68184de73d71eeac2ff1d2c2bd03a3513199738095f404a5de21a9314ab2b5b56def8ffad7136c56e6e0ade750cb7019ca7c38f8e12024c179599d01497d6b683a1ea029b381cb905033b3b741a6536bfacd648e91956139d4fc3c3e162d75b087de5111936ecc2721efb2e1018b577fbf6d340793efff042f45e564aa71415dcc43dd8eea0a603f9549372b77ea3f37e8bae26ee8cd1b03a8111e7eee398553df187740d7800e2387eabd03bd56d422d1cc5640a854d2d09c33c5b41484d1f92c00974c79c871c74b26e98d944df014215ee8b0c368d7fcbc6eb1b38e97e46cb715d12ec6320e021c95c2d11a51ad287c2f5335027138b18c635c1d05815585bbd900a95134321588bb6334912f3c61a079bcbdd57876fbe74b98577cb89ac88764586d4f27aad7286cb061d95c358048e37d54cfe004dd7872551003dfb87bc498db894834cf6f984bcc2c1c3c10a5fb833339be96e880ae009ba05160a4715cb58bb690333a4107ccf11f1d169bb3518c523e8704634ee4d97b8e54376b5d9430029ca07b81bf2fd41d0afe6883461ac54117ee313bec9a588c2c76c168f6b125183088f880f91cf212f87b52634a0a8a4f4df997657d283e1356c8953a6e14326d5568a5b7beb61aaae162c335165b84fd43da6286a558c33082df6d6473209e5bec819141e17a16a7ede2f5a16931c74189f0937b164ead88f6c5a23153184a26605eeea3b522b1a2612bd867b90582577844b518ad65d3fe7737094ae6ccdbac1312b920139c7d2f8ab687643ddc2f1c1e40363e0eb613273a4548318ae8d46b08d06ddc5014a3f6344dd608d724135d8a473b806114e7c7927568358473dab37d3a01711a6d2af82cc7f4cf4bed760c16500bd56201cf6b956d773f586b28be21f1e3cbdff8847efcbb587f1d5dfd62e6ed8ada613cd0a6b9bb1d3d77fefc81de6030c6e7fac164815a6f46535dc3d35ea8f52c88d7fb124c4d6028327576b976c186c725762fe3da8ff3c5b4edca130546b6b90205265641b514b7c8720cb3d393a799a41b7a7df37178dae1e5583c3ed9dd419823a1c3b015e7d969dfa87e90dd06f8a00e343bcd969a3250780e8ed2d0cb11cfc5d079fe169aefe60bbb1c258a33aa77dcab34070e49c5a3b6ba5d793703b2be43971a9b5ef1d21f0bf18c48a4104838d1e009a9803c2e84a9a7c6f3cf9efe86c773b5e60681b6f430552ec87c1fd5ab34ce44e3bb23cdeac0c44b0fb0155aa649f50f604c10f924d4b4b99230af81aef428c125ec0f593ab73415b1e1ea9e080501f21eda37715a05231e15b94f3a75ec9e7d9103d23fc5889bac737b1fc8e25ddf475ac05fd388d189846a14eaf18b3eb7f64a98dc0e47305b2660c91763e290e43f9487e4c2a6916348c2b1ea16ea2665d411938e399b63ac8b7f98f7ac2047928096d8f47af9dd0808b7564f161a33bed9672b09739294508e9805673fcbb3075cc48ce410b9588f1cb181b047fbfbb94f6704853dc6ea969d495333ce9e549b297c900b8248027def361ddb84f318b5484a2713cc4c2ef3aeb792c7c0274e69e8b42b68d8a479fd0433931702bf5493f35d20482b6a950822dccaaa0bdce7d44dc9bcb501e1c87885642bb69de76abd57978c7fae1ce09792103ebd972739700ef805c29f45b92ccbf22f42a9a260d96398825e70c0c2a9798acbf548e6333438a0c4220696058ab0329d9498a019f79544ab79d46a1aff90f8ab7da8d1230bcf1d01c844e63459f2a14244b531bd37987b87d065a3fdefffba6cf010cc5cd5daf91211a03df5f0d58f3c8e47e34ad9b34d0ae2598c3583cf0aced862bb3a6bb022337f6503049b38ac1d8805eb75d5fd2f81439b00c4a6078d2829313306ecbeafd4e34c5a0cb4c0a33c64da91845883a36fa0c3da5b9909585f84ead6c60390789f9e160b09a469091fde228f07cb7ba48a59d4e1e6b202c6868b0a8998bf021e0e433cb2209c9a325c012b9545cfab8da300b51d771f35360d06b0efc8e41baa5c9931a4f1ae7710177516a491f566dc7f6ea6197740547968c56ffa4dc65b4fa594b8cdc8a39b72216a33ed41c0c6011976808f3e52a59ecb0e49aeb220a6f70094a4b80738fa0005cdc47ba6fe53cffa942c03be48884014a480361cdf9bab9dd21e948c600208a59e1a98796af00c22b12461afc11bac615f70f87b3909773b87938eb6e650ed8b553436acb8e39552aad97ce25e97e937f6fcf60f1217425556031c875e4333c9a79279aa67f246fd9afeb9b1bbd2af95dd18be074bc008feaf1ffa298bfd7280889819769f20a8fb19a65f096042a0ad2f7c7cbded4eadc018b67328d1a994e16e8fe56e651806e586ae5b6956eaf646205b2b798370387ce4b6af691490f287992ad4b65f6fe03d09c087a8e0d4e74aa324b5bd45992315b018376eef09a8805836a53491542b2dd96635c56441a70ef476ee0d598e550925353a565459ede45ea52698dce3dbb4344b24509dc9c6f9317c8317b2b7aa41e33ef3c4ba05d278dd41726278e4dd0c5c0aeac6490efe4454954904871d508b27869545ae56fffe3ac1d6c201b2b40c48de0465fffad239ea660f40d0c3fbcd732399c28840d3da4e0ebd65d8f3f1560cffbe65eabb539dc19aa9743dbafb1aade030fc5a39ef220c439194d8f42b9be8be8f3a241b8db5d9509b579911b34f7110d8d33cf98598fbd09cb3341cd9cc3a6647ba8185929d7dcd34321af605eb8eda08ceb006550c30b9f6aefceae20d61c27622c3dedb861b3ecc50119b34bc50f8bfb3c178a0c2b91df8bca15f269e8562f1388d0d4384c5e03af3f011ec666e540af879f11080a9cb540500e7472a639464d9b14ec360f6b7542c700da44ffdd20d07a62e107123031fb56cc3edcd0da6bdeaa4e5342bda43b1d9b032db54b0b6ed68eb6c4f75986bbf7e5bd6183a65c49233ea6f76a5ffa68fdc9181dbf558ba158a9c74bf9555be17b47085dd4c8424db1fcf060c0c6b3211eb993015a635bbe1a40690ca4a216c0df8641c76e62a093644309222942edcabc3b4b9b6558d29d23d8f7b260b0435d31dc7efbf9585316119f8b2bf7410ddd37aeaffa137628786f492572748221b102de55610a09d194191948f32beed9ef51e28e0e8428d558b7ff630e604ae34501150609b3fc26b3d8fb9567d447dfb4ad5aab6c3f949c898591db5f95b7cb41e6565a53273d054a8ac6fb57724740b9090c37da165c7047b1e57b67f4c04e708198cd7ab052b5107f95ad8572b4934459dc58d589393a2a600af0c810ef03dcaaf15dbc7cd32685c01c2105430611cb92466291caba299b3acb998589342f1de55ab04ebce3ac9b88ed6ef1e22c3e373b50a19babb773c6eb0d0abe4c00a974f8ebeb8c8256121a9703ed659ffc759c8bd1423d6460881f84156095e3672db55e58052622951ac52cf24c141fda3e45c9b2f71e0afe8951bba2ba0b74fd6f135efbe28c9114594afb84a678d10dc33c45ad3c8f112ec3ab791df744d0f79a64cc3b05b38ce84053b35873bb73546f6691f0a72d2748c3ecef9118247f88ee8f7e868c7195c1bb14190bcd96cecabcea97c9dacec40212ee0a6505a4fbb62bd2ad6e24017a863b40ef3d5404bf189880d74ca42aef662769403ceb83bb409cb4f08b7234828b93dfb19cce424b7a8e0528fe6f65e8a4f74f78665a11fd57c4d9e4f13f38bae878a1887aa43fc41b190ce9a7822520747abe2531666e9d40d85b8efb3191d9d10c375f729c619a331e4caa851a197b860efdbc64db3048f58d796d97e82389e40f3b8a8d4367196e3d4e8a614075e87afdae2738c13dc35e807efd3b2a27b2106158828765cb50fed8eb3f49deb0d22dea1298f69a8733299976dfb8804226c794551d72cdd5af8bd4b93d3dc2e85079d4729a01763ca2e5a3b291f7c87810e0e57f32e4f0afd7338f130d45cfbc2f8c670674f79f30e7689d798e3d80a44254aebc81372bd4794c67a0ae6cda1c808b2e8deaf5dbfe1c18ba77cf0d111a86b0e4eb5d0599376f94adcd64a0e9c6218f87b750f8628813813c82eaf4aaf9b826ec39f0b4d34435a1aafa73c343376fc66234df4e4d7e8dd9e9b132498e36384d2d87ae08894027be94521de3b174f99fa98728377c49a5e201134470481fd411b72b5ce56533c43e005840d4300d8305715b27497195c23020ae989445360b88a2f135758df50793faf77edbc2aa35b007e2536eea3699f593787e9a740cf72b24fd0cb37a1d10220c7227e96df98a325ae2a65d705ab449682c1520e516326a88349caa752bac30d81892fe490833294df5b22692952bae30c3110a5832f7792ed010f39b90ca85a86cabc316ef5844ab3f06311a8d17dfbb340650c26b89124c90c5ff85a612e265b0f570224ed07daa685156ae5f782fc81f18221360cbe47dcd2b221ad969fa16756dc953aaed0d51742b30f6d3e8a5d13edcea43182f926f97cc5465d6ece253381011d75f476c4feeac01a6eb39b1cb4c75b505539d3947a2d2074c8ee08365f49e29faa7eb6c3435235c7383753ba320efc81a3bd8f29f17b824ec40cf11ad090e66f700d2eb21b6ee947f6206fc038e89bd20d871fcc7909d9a93d7fec29bd82bcc5f75a806fb849deaab841fe8beee9a6907850c0e18656aed070d34e98e6dcd432966259a4684eb46a7f90e70f457eba8a04521c3862629e8e46896e920c658e721a2e8beca34c8820c391fbb764b980811b553c6f8fb90a1927151bd4e0b63bf970c2751834e9f415411d8845291c3ec6f4fd643bc4c164105a2826269c07c4a86b5872d51d4294202ebad99ef7fb7b61ac2e8a4d6801107f0e249570e698556277c9b732f1faa90af9d913e539525728f8a919ea6a6efca00cb1ad9a7bf819052d8a730fd6609d63c3ab44633145ca2a86eeef57ac0ffa96b4e1a7e154ddd80c2a2fd0e9276160c0b0156c28345a462b30b27c169cca40f52f67f1b6f704fbce0bac49a910c30acd6762dd0254e960109d47ce79eedb45f9317bb8420b86efff6d85ef82e66f1dc7e62afe91461fd9cc3a300624307c5894e2dccd1d7c6be045f94df96b23ce022f60ece3311d022f4f405fee02af5baaf7a536ff67299d151696eca5d7d1b55d6f01090ee691b7c33c1f36bf12948e5f64fc7f3a5925b26f2b802dc6dc48d4a62b9f85ade5ca1808d320bb95703b845480a6bc13e46f48b15429e9bc97540e96d68d8594a3f03740d9386e0ced4a346370ea7409ff0ab1233b38e677daaa31c16c573176c2e0c57a1e1bb522d8d80e00b6fd82790b608885720e1937d0c3d275c235b48c50ad2ddc8c70a753212b49d1bedc487f86993185e0d00b85dc5920a62ec9d8591e7c9b770ac9d540aaff0cd83156c9f448cde38efe9e5ee6b356c485622f1c2058e8bf1bbb7f6c30ce29fb1d608c833d883ac017e764d5f5072dcc53ffcc338e90c2cb5769e5510bd99b16a99a6725b43644aa37324cf60df7ff07fa3e90feed231369d7c9c7b4a74eae3cbc2e269aad4c5198f6a1de7cf9b3267467e3526454bf95dfeffda0298c97d3a28852f9b04fa74554957aea3200a84363ae645b3f5a28f17f1993fb007df79cecdfb0a1319255ebccd5115e9b4ab85fce317e912f9cc4d618aa558ec3d4d26cb9003ed008a99feda309629af55440a26d320701589c3ab4c9ccd9fa01d763c21c1cccc25a5e7aaac806a2ffb5091b0549796075148ac7edfc9588cdec24dba4b93daf6b2919119fd74a0def7f1693b58157f4ebdec4035d6e28172772af1d19a18f9cb8cad148c223fe9749519dc78c9d1f03bbad70c8a97fe79d8cc888fc898a9ceb0e5527bb8a2311d06cd4afa51f6c16efa3cb1386a150355e7178964dc3238d21fe9bb2df2f8034308b85e549fb741c74496fefb4d936a3ff6e161eff437676f8e39ad449311edc5310c9cbe66e63ad804d201a4fb20a5c74b3f4933c29a30adb127c46d6f0f8bf3ed7b17a0a0a67111c3e1d5f4fd495ee85e1d201d257519dd721727ed424623f1fff1e0835b910657d30c778feae630eecd1250b31838a329d5d476d9227cf92c4979668f351799792616d904620058f579cb9f81391adda937600f4a58c8cfae428a4e22d076d0f467f8d22df75800767d240f063868a1a0f02f9550a76ede5fa3d874108626ac07e3f6e87bf0b616f99a9fee2765b50bd4c069e477db200de6fdde3c9e6d88c4a3a738c880bc3b448d3445f3a797dcf0f7f28251186da79018d9c70c62d8b102a3d9281bd578d4d398e18ac4857be3307ed37592837a21491649fe500732ee5c720c513e0f30a8ed0d11c4501009fa74cc14c5aa9de24c9522b20ac139e004b176576cc5ebe8153cfc1a215cd6920415822e97cd7e36609ccb795e98547d458eb19f5dfe7429cc698993de36d030eaceeff63ec1be8af7b415bde80106c968e0095cb57f61be53374b770b63696fa376de105977a411fa39f450b02c78967ed4e4de52e4919d64d188458cda89c3a7adac8f3870b394138656497fcc52d88356ee3735324ef6afca03d405ed87162fabaeea47e5dea5a8b4075888a6c89da771af5bb8f53cc8fa8f5e7e8551757fedf58777d6f7bff89fffea055a0d27d6f8d341e314a9b48b832e2516dc069a6e57672bd110a0dc1648b7cd42dc710ce1a82dc0a6704e93edc6d5df686aa2bb14f011d6f22d94c6fab38800eed191cafb554afe73769fcd14bdfad2f907fca4a80dc6d1412612f083003a670c16376e183cac597b774b05fa4182e6c4f489afe77ad0c6b599d852d9f22feaf4e5e91eb8d452dc5956b7fc5b1874dd15659fae186debf29ce5d1a204125aea3d806e48053f8b3807048e36ceee745883549953f06411d3c363578d1bbbff77027e31fd74a3df182b31392334ba8f2d3248818d8d1e55272a63194850e30a6ac44adc3c83874033e52782227e9f516cb53e2ab5b47816ffa5d7c7cf001ef6a150ee43ed03d17c5e489a9e8bd9ea088074d07ea197b648835fa8f8fbe6c03375a0ac9506f4c920e91bcdbe96c312b94bca04856a1e72a289d1261a5647a18ef91dcd7de532a3172ad468941ec2a7170812fab196547f10c8e3923b4fc13658903600c57fa59ace928f6cd9a5e1ab4c342699739a087e79874ab29d16aca42cba088a0233cb264551416a0b2f3019a75c525840a8f0511a060932679801e34e646938af8ae2d99162517e301bceed4c31b1475ac1f2aaa84843c3fa69d58d1ae7f3806594020d6b5ceba95219dd4c3448c4dce336d561fa5d10c097d1ab0bf43eac41365dcf3e460ad1b3e5131a61270fc2154ea455c94806f2b7e64ea1d8bc4b772c82434ef0a4f4341ca1131926824fdbffa90d634b096d02c2e8a959a5c8675dde1b08426ef988d3a6a495d3cfff33913bab086cdd0b152b96b6cca79559e9a59a936f69933acfef18bd016d7a8030c0800c8c6f6841f7c3040a16e42b19db86c854e41cd844527ad2a1256cafbd7fca4fbae8aeffd3b4050bd568bc38c45cf7a3ee903c2356a71f4156329074399c28a1cdf6652beccd40ad19016091c64ccbba18be77644ddf3fe2992a49365f78dce2b0e9de3cc393e454dccc4a4b6ec4ec5942f2f3001249fd8f68e8ac966be8453d804dc994f347b23598a76dbc9ac43f372376220497bb0d9e8ce3d8ce4e5aadf27e121ab693e581c3a34269b25a3ae2155346c5ec4e4f901b4090b2379b0491be512238dfe0505475ea7250023fd6ee73a11a236684721646f86367bc1cd91a8bf1aa1ecd5d919dae8348a285873d6841d3b297fd95c0f8139ee38577399f07829d77660b0f7d2a037604c38d271617974e4066540a382ead132105f0d50c69e7e4c16746ed2cf0f570dca216fdd7e9b1edcfddf432ba3cec537392df37f0dd464189974efa5bd74fd77848725b0ca992e6886ce6a718e1ed00c040050c9eca061c09996a066151b541b2fcdf63ecee7ee06748a6e4c190c5d2ee038dfcd7ecd08d93732f4879a33c322830bdbc8255d5d22643b61205c95e29cfc18d90a270c6774b51c1a68b64c52f5d39adb85c277805d97ad3ca94f3aa14f9b71357e2f459eb1359cf2d6b0cc2f0ecbc041dd9efdeeea63850ef7ff77d7b08dfee9205fcc0f67f1e159ad114d83dcaa4b922ae4f661be14f51360339432fa2c0bbf80d47e3ebf4756408971c0c1d6076189e8f3f3ede59075a50d9d1089b1e1eff662694eaa492756a71005a883c3363d4c594c13a8669593373fe011745028758f5e4795b5bde3c7a90487d4b6e1d860be6ab62e32c90b4a6814cd55dc73c2c29557dd2f06c954715c1128f1333bf9dc7dfa3dae02a4cc6872f19c2d21a6a1c62bff49fe195f6a369e17292289bdfe4372e82da2efbb6169d64b844cf2954a2ee9661beb8129a5a7a43133e8c03eb04c12e17999ab4308a4db67787c464550d4fe2e4dba0c0cd6db66270a62ef9230eff0dcc66299c11abe69d8fe3a50e29749a1f992bf3f7e8e9e25559b1597d2ba5dc32167e000c905ecc6671b561b241beb9bb003b57dd00cdd41c724776b70e57b995dd5bc7c26d1040e9ad221ac096cb6e75b414f72e4f6cab26d0d695cd7862bfb0d976a097f5f1009a12b0d6944d5a4f33c6b472c90087baa37b2502aaf8dd26f5405722e546ae01f2d12278c54b6bfe8ae2392953e61fd39faea2adef2cb7c3de965adeeebd9c83db8061adc851e706186c8f7767be31ed4147f910993ce7efa51fc164209b4306ed7b2722f30292abe3fd2c86540f6ed78d8168586510dc14088c7eac6b9bb5a863736b112f55dff93116812a4477a4b33526606e58d68c1e232c79a540175b8f021905a1616030008fda52ef258a7a3efdcb5fa014f66481b4afaf445c4f588c28eb62fef15c4c92e00b0807abe92edf500b99613d34664808f1efd162845b00a2357bec38a28aecefab7c7614423fefedbe6f125788c2421c1074b1ef6a680b9edab258f8a17503a4c40364d3bf40820d4746a3704f0615180f9e49d77dc37f8807b83dd1121f095300f0463d2e55d680fd49cc390ba09f667a0b1e3c4b5456f157972012ccec0db1705dc46e9d2da009261fedb9a173864dee2b63f009c253c25fa4038affedd379a16bc5e0e4c020e66e6d1b849a0ee3bcdc58426146b025ac21cc98648eb19983792fbbf6a6420cefc0b32f065d763c05ace59d13e6fd02f09c2becd2d78ea1f919650e90155719190377755148bd81ca1f8806d7b71b51afbd388a881b4a1913b873f2db80ae5ca065a76ce55d045a61ce15bd4a438a210fc29707318ac4cd2c27c3074f0a3dd237fc1573d03c65e08d7cc510e47eebe326501ce9bc7153250baf15eb5d9fc6ee4e6ac816af919ba262cde569c950214e76c82742082704f8741a45ef2a42097d0c0de681e9d57b86212e5751045c87522551f7361169418efc47a807c1238611c9f530000210b2ac7e68786355ab34c390681dfed5f7edae65e11b0a08a84784c51ea26379dd8e7516c1961d530049a20300373266cc04048ea964699170f18a2c424e50daa7079d30b0c6455e8671f201cc4ef60ccf5a193d61d8015a2d58b536d1b417f0439eae7601277dfc8f75116754949fc439d6fb2640d4813cc8922a314230aadac86c2c8181e72f5e5bce4ef04de320d35b59457060324de8000862aa6dcb9e59a86f7488b010953abaf7133cef51eb55cd054dea86615fcb1e65d76b0393343263fb4264d2693d6ddeff27659c9b6c7123cf61efeac10f4665eecb9ec1918a20c1d055a175ce015e2a58621be766d0756ccfd080943909ec5d87b748dd37e8f26560c642c3fed849929cb2a1dac6ba1a0feefbd6cce3e51fb5cc3ab352d8efb5466fd4591038ebd238dd7b7bea6116ada4d7a3f40abefbd6e7f7816f898195189797343edf92c1ce3fb2e1ee3de904919f191cd66fda77b0d7a37bebdf3ca88f871d90058cbb8cf047f8011669de472c64e786f196265281bd2e71426c4ce531ccd4e1e206d787cbf424df1d3bb76f118fe862fca54f7b9f7e77c1313955b6bf922c79e5985e0b33487f8ad5b2881fba4452a25764064d5ab6c6bdd9d9d3c761213dc231c79d70afef8dd6aa86b502b3cfd10693dd595acfdece9b1dad5c386a6c3b38d5cf55e6ffd1853680c8d046ad69bc55620103b4a0702359eda575e176e9f6709e78c135b30b4e2883dcd189c9d2fe0b9ede1fa6afcf521a19531eab28aed581093d93647ca3764780f4c79ca08e451839c6a34ab7b691f160ef6ba4942b6dc7bcb2da59449ca380caf0c4f0c0d5e2da956a72eb7482e5af5cc35dbee9b90cfdcc2e24f7c81e1a1c76b4d34c5557c8d4312260bf9ac8bf2c153c97cfb64ac412bb960d728cfa4a16bf8ae67fbacccef249706ad5f4f6e69d0bae6859d63471226770ee443b9e5ed9406ed0b1068f0ba6bc66cd08dc555fc139e80211491c47f0206505c4520afd39907c4afa7f9e645d1fefa149bf90b0d4e69d03a0b29671068d06e5e0caca752657bedebc0f63714f2617da15df2657d4a11fb519149170d178bdcecdb3c95f493c717e7a150d84f1f0d27c7d9e38b06ce3b5fc0e6f9a301e59b779bd360e39cc7577c71d8bb4f25bdf39e170f76d4c739ca5de01ce5d2519b771f0fca37e7b171ce7b5e3dafd8f18839d755d27b5ed853c92f0617b0e79b6a21be4e9e3f1e9e987b5e361ecf17176c1cf5f17c09bba07c01520d27ae80bd501f0ce5a8af061ab0e7e9d8bf3857f77a984bb8ce2ae3f4dd47a373ec9dd7f3c25ecfcba5178228d39330ecddc7c3336586b99a1e430bf165a5850e7b286171a9933226816241b17e893d94731cf5e41702f9d435cf4a3f7594278bba185c40f9e9e3e139f9e9934353129d501e4a94ce44c996afd8c90f27e6dccc331575b9d54f45bf2874cad15d22cfe999f530cbb28cc812d4299125eecd6d836a6ba594d26a29b5153f51049d5448d22f4ce13ca39db95b1267b6e2f48d119c734e6be328a2592c16ab084a299d55055c2cc2554f291d2549892e2973d59e3262b198e4c88a2e168eae3cbd196468b01d2365da60337dbb949ed43a6b66b67a1f2562442a9573dca1e7ecaef25dc95570be22252949a196f330955d6b3d1c5bc4b1e224b2c4c6598f11e765902238aea41f79e9ddb2737a159cafdf7dcfcec8134eb08fdeb149bb3c217e74b0e2574e05f1092ee1925b91cc1472fc4f57a15d60ec3c1bd7ee95b2e699aba84732512c7d2453f4c4d7ee89e62afa917929e62b67b1ec76b2d83de9bfe192c35804c618c19d1d493904c1d8c4faf4556c527dba91e89a4afe7ad8e45d609427dcef6aedd9678106dbaf37a81373a65bef63cef4eabd62ce7470ba081057d3e3163fbd4c1c459a091dd99f5e716df03407afb86a39e33c853d37888b21faf5582464bdfcebd4d2eeae5570f4b878ad6bf1a3a5b3c198736223478faec612d7566d460790e520577e59fb11470a60e06588312c388342153368e2287683d10daf36c11b15f6dd9def96ad3e9221d3c5134f918c7c246374c39f969041cc645cf098881366b54d534c50d021839453f9c84732465ea230c1876014edb1488f5a6b8c35463a298d39e2e8c5673eadcb9f5d141f6fbf50049f519f5cbd3de69c37b3746adaa6695e7c75eee288a9c7da757a2aedaa3295ed5a29ad5405653a9d1e9d4ee7accd029d597b8247f79899adb3efd5ee7512e7784aa72d720a45f0f4cbe0681abb7bae6c2dac94b46f7738333bfb5eed5e54fcdb2d948c3d3d4eda73564ae7a45305e59bce399d91d218959c4211484d561bb40cad4feaa92c9d9e6ad36e2629f5a27d2a67f418bde716ea5546da196756da9e1751214afad453d9aed6869e6ad3ae6c6badd796cf49e7384cd570715e99f46a890972640f97fc7423b72360be4e62e4f8b18b277942c35059e67efa49294737418ddc2e3d36d97e3ab7033c02d636ee97d5e4305037a920293276b8b1830d9bdc2ddc753bb4bd193dbc9d93a8e6a95b354f274ee724fb54516cf624bad1371d0bd633df2e3e8512f8ccb9585b4eea9dc29e243ea36e2beda480cddc2ea7a7eada2de5cd2c9db3e79c737e9785adca4945c4b5568f2d7b7a19f5785599749595aea2b2c6e94d3ca58c229db2305d7a6ca7d265678018aff75c3995accf8be5898c9c41d9faa35ee684faeca73dc2777bec6fc69fde1d6d6b9db6a79a6de7a435f6f4acf0b4152f5a9ca3d3e8338aa6336d7c4a5d7606b853eb58984f58df9fd7cbc2fca8262d15dce98b7b9f4432de8e99d6a3fd3c5231404f95120cc7717d3b0fcb0c6280bd5fb16b407c751f0dd8e3eb155f9d979aabe95a3421354598f93446e6322cbb273cd4afac2dc4ce05ec3629c3ce69586a639c8c70bf50ca6b1d0bd5ad632f94f2d7b90d53b72afa7642d158f88b73966556ce38382d09e36cdd4efe22c78faf76e9dd2b668e73ed76b22ca31927559aaa3357ddcc5ae1792adfd24cd228d5a9731dc6de9776ce53b5f7c060f1c5cdce4924238ef9ccbb7332c26f99f5ac7bc2aa747b833b25652a6f14ed6ff52cf3ec37024e8590537d4005ead60b103f30030886bcfda8707e4f65e4ea5236bfce79a1e655b6e79c935d94ec492ca30921ccac10cb68428832cf6ddb6b9b5b16ae77d36e3a6dedc6f9e6a938bb499ee734155555d5556576e33cf95b2633b799ebf4cd5cfae44229f68b2cdc6e65b1e53c850af84c665cb8ca99a06a1f023bf648dd524f3e3733b719956d3d49a9ab2e95d28b99b432e35bfa7515e85912027f47748ee90e95d54d80234b0f2ff690e81c5311c2b84598a69761be6d306090e809c34c1b58d0308aa580bdbb02f45020c6980276e23f603f100c79ea3406d36391cad33d595335d871eed6c9b13d792a8b4f217decd50b3bd73aec2a0ebb6ac3aed2f0e9ab159eb727ebd8da479dc2c854b0532a377621e6b922eb787da95ec3f68a525b10e2353d762ffc30534613429829a389a017ea94740223e348c6c7e0df51c14e9d43fdc971a6ddcea97a2aa9d513cf9fb017721e6e1e5aaf9e8a536d2aabb94a6af5e4c9af9dfcd8759f0a0af6eb18bbf58bb73fd52f94f29dfc10fb46c53a75f93d9bb471709b73b85b9c6f1bb785163e1cd530c7d5df7c763b1be7859d73aa6e5accf39d4f8f8b1e520f4faa5645159dae3a4ddb795678de5a99d7332b5f769cd72e0aca9dc498d339e7a1be50869c57b79cd37047eb9c70de8e372af75345c99cba5baf93350d773fd38f5dacaeaaef5ea8796855dae764fbe8aafb39d954d9e7647b95fd9c6c217d9d29ab5b5141a94ee5f75cd934a0756ca08b34b420c3670c184478600ea135ca98a2680a19b841c787b18887337438020526282222871dd62c051104c5134a3485b1e80da7830cccc477d7e143a5638d1d5f4c6aea018d177c01050eb017a02022882ac42cf102a63aae9ce00862089d23051556901733fdac5112871b5bbe6cd14112610861b18231ac38e328a9891ec422560fe4f830164dc102209a804881183578854c84a0c3cc17305003cc165ebca4df8f9d7c434abf52b248d04ec0299c71584b983428e1c84116a20794c584b504378b0539a698e3092c583831a6670bd10c9ad62893c31b4d3449b13559d1230e8cc122381947d6122628744b5e8c83f347325a78f161ea430c068e68c5098ab0388104130db0e880e6a80a2e5600461725b6203383684ae1064a3c71c49a1d90f0e2d5832586268e2622bcc08e5ed253d2a3f42b3d5585bc22a55fe929232a86d10e8cdee8410a3396c2a84087184c213d4abf6e248139c28833d0e8208bf902328d86f640288d0e55a441861a46f8d00507242272b8d2841839309a56488f577aaa93aa986d503746c8010837d6a891861a59f4b0800746a851820ea216f0a093820a0d4a37e0f8763acd7cfff8b64276b78c356831744cd15da463b3b44023fb8b325d7cfbd562ccfbf848c6065e6857f418d22f655ac096164c916608a51e76b8c01452c8e0cc173f24bda0bf901eaff4140fc8b4c0c31847cce1461354ecd0460a311042820932603ac43040d9d0c670c30d1fbc70b1820b5a82971ea5dfb803a39f1f6cc00108c6032358193556ac81454c163e6b3c2009130c41041d68ac01224b8fd26f155d80a0838b3137f8f9c9d274090a175e9ac8c227082176f08a1e3380a2d54ecfbcbbb36806893276a083a12c68de7855b96105455a9811a444183fd8204b799072385029a4322a603f5bcabb334fc3b6f1dd73e8bbbbbbbbafecf6c8c537f74d833ac2f8eeeece6ec6f22057629d145458a15bb20893ef322c9928d4e8b44ea73c4526066b5ef5914c1465de7e2413c5984f2ac39da0c8d163b6f342831202ce43fe74a4ab209d259d89741007593afe9ec423337eea25c51195c5efceb9f8a954887ffd49fcfbf57c9649eab5877e12e8a95292894c8280dbd432b560ae3b95dab414cc4899ae22d914c2d1a2458b162d5a84b6b64953ba253d7e335ca106b32bd4605669ad538eee0fbfd47b64d4534ddda74be5b3e7864f99e2ecf83c9e3cf6173289947a7bf5bcbe5c2412ead2250b570989847e12d63e3f5d1e4dd7945ecde9f25e4d07f285b12995fac2b8d4633a8ff9dd7ca9d317fa077ac8ba9f4ba0155c2570ae122bb8386b678a529c9254da362ac14831e4904c92626c6017298652175b69edfa6536a765175b1b7186eb6196413a95732b6f46cd552c92df8e183395a76ef3f517defc65d4b703c2b7e3c4f293f85646b19f4e8ff9e6389c3232fdb04bcfd395b51ed690c1184d00c9c1f492fec27445a31ad471821fa22b7840c58b0b3092484a020d3264b0a507054234a9a1c1115f986e7849e7a8f5f627f60be9670f490251d4c783f2fcf1648f47414f3d297bf145bdf6ccbe70d2c828cfae33c34c5fa8d9f2d4da1047a9f5d88452b75f343a22f645624eec6ea7dfec12c4569474ea3418e9a45ec1cb6292722a29fde2edfe6eed6d882cda5c238eabcd35ac0002f5918c153e6c2469379e89455c1a5ab7866626751453836ed6773c325ad21a8d8e111c49698c90ee12178b843f927e3a041a9cb5be50450330743b28e7783a7af24950e2dd8a45b0d329db525fbe10a7b5763bd9162d68e9c9cd98603e945ed8fd7170ba90b86421f96427759a9f309fec3a0d648d0ca48e0d26a5b6466b6a7066e992c32c68c6a62b894797d1e5d04f07e2d153d15241ba75728f2a8fceb557796807e2d1873d434f453aca69ed197a94a3aa0c51da97a9bc6ca903aca7729d7ea1f4b00aeb35bfda1776f5aa0cf23b10931ee5d50b973cebc39ed85b91df01d6a3be50cad78f8a74cd4329afa19cf552fa75edbb59ec7e5950d6e30a0aa40b1339bc423fb464290024b215ca30bfcb8fbf90b8f4a90489b771e9d5b779318245a63070881c5ed8756db1c53c0d164299108e72b8c5c22c4c4861af01a51f43c8ef49fcea2e3f55fdae50835e1a9c242891fd7fa42067433f82c886a8caa7f6851b989fce79192a93430dc605c8123954b9a47d42e9f4855dd810fbd8656c658edf0099d30669f8e884f6a365d180342d5a90b6a5c1b9c309a32b84d228fd5083d12db60935788532237ab3d04c7919a2f2ea5529f241be0d48e56d3f5ae4cf6d7cfbc0dd2913ea1a1287cdea1ff8100f7b39aea4c719648b4dd517b2c02de6110422d3069d5417e24ebb9d0f847c55e2d1bb676afc03ff3226232dc8dfa7e26c3c53f3020724896c8fc840cec8d4a53402030f332ef77b125faae4a735d56f8335f803881c6eb11f0d662687599812ea08a9979f99fcb2a031d93f7a21441b434c52f810c41a6c5c01630634b89245186abca6f7b08117b06661504e9f876b1f9789c9c4047989633457558a3498892113e667511600334c4b1bd28fd560b189f4e99a0dda0df284ab65e91bd7e92c4c51833353235bca98bcaca957537e991a2f4b23e64ce7e2102143ee10a7a793e7443e108a00c0b334621335b1c9e9a7733d98c8e1f643c59841cc8626493ea4cf24892cbb871199ba01a8e3f430410ef37b2a484df9705fe621f22624bf2df6136a30a6ed4788991c6e3f4d5f2505d29a7ca69a42a82278ec76565e2b087a1b503d528fd46fcb72e4db7e402ffecabb47d74c83d35b4864f0a6e9d574d0d3981a9c2ee9cbf8f5bb6bac68f279113e1a9d71e2b9c66a94d21485210233e4e5c88c918646436a503ba36dd182342d1a909645fbe982c4b9d8b5108bae0c200986e4db6273158489ac39f2d3372eb1c998d8e403393e42f0e1c363f4e160b551c00e3f0dc60777f8903526946b30d027e8391fe8216830d035a66eb54faff55e4ffba9f5d6fb693e0d4e0db67169359137210d06248d4caf9aacdbb94a6990d0983922023314e61af9eed2656af0c70fdb505193fc8d8b90976e5127dac2748b7e97c90be7cb207f8bc59ce935899833ddc81459f584aaa0f4873d2a2731474c51984bd4e0bc601a1c1202264be7a4a73deda27460be2a8a74eaf20bc17ceaf17310d78b616713da912e8250ae397cc5e173fcbafc362e5b0c05997acdf96ed10d1344a6df057387ec1b29ca424cd4ab12958c4491a5c37e6eb14d75bf2d264489e80f19f4106eb76878ffc71502f23357d37f08cdd57420ce5d6f2bfad9b274cb884fdf80bab5ca39e222f874b99d20d7d9edac7c7656768cb813f937478423ee447e8eebb42a8af4117c848fca57afdec625c7db848e88708dacbc2d0ceadb62d247296b3f9f066b7047960c7e217ecd43f8c223af79a8c136a406a703c0dbb834381d046ff3e26d431b9806a713f136a206a77fdee6799b9806a7bbb71935387d88b71d09f1b63342c0e4fe3053f3c117cbed455cc32acdf17d556664f4d3815c18ce8717261443fd1e5e789f8774cdb3a26e85c9c474cb5351af1ed33ceaab52e4b924e9dd8da7a2be29fd0e4f453f27fd5b4c8369405a9006d37e342f0b924f3f744fe24d869a29cc90aafb87d5ed3a5d6ba54d60692a25614912bf41d392c45351b93424a74b094b4a29599e4a52cf85258ec4b94befad26c0681b3eb7d22cd6e0cd8c342d9422f17848f0251f3857499cf5f128f1241feb4b5642a45a00126739eba3810447f28149bc251e3d2126d9d02246846e853408088b166a5a7eba9452762f207196c76e014b3e3af4d1a0b9f228516cae2609dea6c48b7395054dd716bb468832259aabd58449a5b99a1a6c22792acee5739e3d15e7f17109b0edcc6f48a725f9c25f241e5e968739898729252490e0c55e29f19278acd8ab29471aac1ebaf0557e457d52a9c19ebfae2cf216f3e45252b7ac926d9aae243e3dfb99aea8c443bb84c4c30cf61910eca3128f1acdd5f4241e3df22812cf88975cf4f7362d015a2368f322251dfa49345d5f86a64b83cdd5346a707a51130cd6ad3033f2e956f5a194d2cca85be11d7a170883c16c5882c15ed3ef50b78a60b02701895e2f1acc434cb4f43325a7f4d343cc35fd749a4493daa50446992aac6601f3d36358b5fc54439baa4f0dd260dd0a31914fb7ea950a94c32d4695681a255fe41c0431a44412b138a21a441c91830e40ace162044d43951a4c52c2c59431b4f802c98927704064c21a686039c2044068b8206ac1c5193b24f150c70db4c42b7af0218e1c52e0458c8bd774eaa55baaf82834383f8916262b1bbc800131268b1338b14501451731639cf18312d0d24f12160b766613035bd260d34542bd61ba90f8f40b9b2e257ec3879489064d170febe361790d9a0acaac61f4fa723d894fa7b1e952f2f120f97890b81227e15321896724065989f7a50ed52f8c627e8b19d1816b3c43833c0d522aa5f6cdf049989aab25b196d0eb55f3ac4825b99492414192c8fda12bf1e44b76d7b758b724de62dd524191b77ffafda634e8bdd0e0a41489a77201c916eb12a623f19e170a8d1c6e3196a77281e5493cc9c793c459def3da62dd4ae2f1e02e6480b8e255438f1e72c0f48a5d42d8699278b28b0d329843e8a5339178f1c5f2e24b7a1a6870b2bcf842423f18380a9b2e9ad4ab7961ddf269577c252971230d20242fde48438c1444a8408e13fca4f1821b7ee8e2d5f373c4450e673c61822b4dcc90868e1bd830e38727aebca6f7e022cba60fb7981a2f5b6cbaa450afa60f5db911659cd2cfa5a69934cfb40b174d9f683ad6ada02906cb6bfa34d347d345c5f8027b2975d274ddd7f4e9a5c1b44b13030683c1c2b44ba6595a82bd310419b0d7f409d442334bb7d4b42bbe846233c8a888680e31fd5c337d7efa168b2f5d091a9ed1152596f0d20333c0f46059430d9fa3352710428828460a30571869f146181c72e0c0e18730aa9001134bbca6534f8a0b0d4edf86a66f44d3b7581b398c4d5bac69ba3623e26afa123017fc9c1b143fbd69bae20bf6d3405b8c2e4d170758f082344d148105961d5ed369d374ad90450fca3405e1c68f0c5ed369d274aa349dab5b6c8bb5cbc8d2f44d084cb722fde99b191ec07e86db999fb8c8875bece766f433dc8e7ece57b821fdf44a93ba155e21aad4ad5083fd52b7c20eeaa06ec9a506d3744b760b06fc214dc2f9904a4a95a62be5b109bff023e9484b1e7e5a4aaeaff4109cc816ef745f74d612ac751c87bdda9b6912a8814e4c99d3a2bd20e37b3333324ece524b83411268892c53d50a2e1609e912d0c7403feca1a11eeaa31e6a1708404dd462221935621da68dfa4c2375520cd6b476a5a442d3c57a62882c3028811534587a692a4dbb4e8dba25d42e000cb5d3a130dd3a436368ea501a653ea460be5164a870e385d218fa909a0159f215d2a46fd7aea4b16e8553e9b974abdaf02d5551faa53fe99753e9de9c5329f71e9a4a2df46b1acd55fba90e494474d116c4557bd315c8557b3b5d816cb140bab6eb2185410e1f765dfbe635981873861a6ca7238753e97b2a754b4d3883c4338da669fe24bee63d7fbdea85f8eb0caf94c9a899e3a7f4c4f08638930234ffe3e3991414dd4091e5091b6c471a597e5d542ea0eaa8a38e3a5ed3759a873a0d374ca79f6a01d5a9d38f06eaf5fba2baffa25f9e2be9b29332bf3b572fa925fb87398ba32f6d30c1030e57dcf06a07a7abc7cb14368062091b8c41dae2d54127f082cb1a659c51e225821d04f1c311195000ad79b5b364770e5c3c3232a2e9e527c3b48928fce0305f5fe417f65ccfb1c9132eba329097d6a38c2e949f3cd4320f6d3e7e29c4953d7d666e04c378e685e99244c495751bca2da1dce2c4d20c62d3181816f2066fb794602972094cafc25c31d94ceacc4b342f3dac60882a50afb25c2d79cb4b2e2f6198ae8eb03b8f905e1ebd741a4487664c88e8e52b898c97f22553a9d71cfa5738895ebaa43f2f815efa646a977cc9352f612fbd12b52bbec0800153b5b42b4a2984c1e98a2f59372cb89934d3203518d11c7577d3331fcd34185d32d1222ac6cc51d114038648c8cb161a036a30522d47dd1dbbbbbbbd5a91df718506a3ebf834487f9ad67c9c430f66aa6930cea59e2a2d8fa4b7ce65de49294bef9c93a9286577dab4ec5e89ba281bd4457d594bc949e1acd05c5997351a0093966b8a0f6fc30a1989b14836c9e6b40011867cb0a305154e0f1e37794b9a2e0660d70b4b9aa6ab014a5c0e60014dd70346d8d22e08ac20345d1110e29200ca052db33ab04b3f52f71a05010225052ffaf9f9f9f9f93132d2604b9c9a6c6340ff09bfb0a401668ede3a18cbe10e336f8b1ab43bc4287100eb013e02047c8508ec18d24502ce7599808348641f539cd368b773e39c8683add174f188f5359aae9ba36b748daed135ba46466ffdfe4cd70ea5fb737feecffdb93ff7e7e7ad14eb5607b175c34444ead68d508336c90a4d178fa299f4f2f022c0c37c002bf4d699b43ca61d03f8f01a3c8aa6eb001f8fa246c0d7af2fbc79073d6e72b5c1998ff3e1a5bca6e6e7a48d7d0a6b7817be4cc614dbf970cdf3e1239fc123c6834bbb26f0c55e9d2e66c2d205719dee8adea67e781d11100f33290d3161c26281a07b2a9583f490c2c50fc575fae668ba70d35c59ef84582c10744fdd20bd85f2e1a51248c0e334ee632744f38408f130131043bcd8e0fd3ef076c0de7a0b3e6f5de5c506c3eea713e1c34b396cdae33562ceb6134704b8155cf3565821bf01019c7dec46709d1e61842b0fc04d6f9debecc78ee53acd7558f3581ebb1d162c3be0a404cd898794e2c2110faf4c506072a3c20a46dacd0d8fac75d549a148bbc959db01dbe123c5eb32ee8b291648a2e011f0050820b196b01ab0a40b1e12061996f24c054969a08a52f622fe828691784898f48161d7fa399bcd8b6fe784bbd5cec0a3752e5feba2f8f8ee0b45f0786a5d330ed7690bb00971beb3e1a668ba30d39ab71ede18bd75db39a18fca321e52fe64e93c9315673bd9e97463b7736383eaee3de5939f9cbb38778bf322b55ef40dbddee9c4692e9fd3ba9c73c631d33c73dbed64f79e344f75d2b44c3b69a7d377d24e278ece586b9f18e061a65ed9fecec34c9b8d17376072183992c182e9a3512ccdc7e7bc7eda65526a9a952925aa3b6d9e159e5741916e65ba76513bdc7bb3c3bebbfe363a882e2dc9a6a95bd7ef186fd1781bdab4f1d6b310b1b5c11accd2aeed27c7ba15c5ad672edd5ac1ad67a1e962805bcfd633986e05c0ad67a26ea1e0d673986e9de0d67351b79ab8f52ca65b26b8f56cd4ad216e3d9be99613b79e8fba5500b79ecf740b8a5bcf48dd52805bcf68ba85e3d67352b74470eb394db78cb8f5acd42d1e6e3dabe9d6086e3d2f752bc7ad67a66ef570ebb9a95b2cb79ed7740b895b1f6eddc6a75b4adcbacd4fb792b8759b2c3640dd5ae2d66db4748b04b76e13d4ad1f6edd664bb75a6edd26d6ad12dcba0d976e0171eb3642dd62e2d66dbc74cbe5d66d86ba15c4addb80e9d600dcba0d51b704e0d66dc2d814d988b131ea9610b76e63a65b29b8759ba36e11c0addb9c894d566edde606f10415dcba0d0e62eb895bcf41b1c90eb79e61dd02dd7af6e9d68e5bcf3fdd3ad2daae44d07a98b7bc96b7be0529bdf55352b712e0d64f69bae5825b3fc5a68b1b3a0575eb03b77edad2ad772648ac23d068a868e84434741a1a127aeb5dd274714b46d38585d0744bc7ad7748ddc2ce020af1929f60a9a6bca4f46177f4d6f152b7f27461a2d90d75cb006ebd03d3ad03b8f58ea85b2cb8f52e4cb7a4b8f5aea85b0870eb9d986eb5d0398b09c87230e539b57442234b4fc526a1ec3ccd7144c0f10fc8ecf5c72e868ec7083cfc03f2513d583dfc0332cbaa4839719e655996659914e74e0638c093feecd787121ffe0119bb187652fe01f9f8470bfc0184c9ca9fc407e23acdc56ea789ab027044156400ef4fe2c76ec7052b4e3ccbb29bcc9fc4d8edecb877b743c45b73bca3715eb839b7c5d738ce6f76efb65d6d43656210010367c3381c2782173f7622b84e779e13fa1e650547793b3c7878ec7646701b6fa7470f8fdd0ecba578ec7610e09cb7e3c3a5548949bfb914d4f685fd9b77ce79a12c7a0ecc735c447a8edba478d7420baed39b15f92db460008fddce015ca77d2871eceda4dc63b7b3c4416fe787732d5f793b409cdb61e2dc9113bcbb9d267ec48bffde4e100f80eb343700e712e0ddedb8e04e766e5e0e229177bc1d21ce09f1d8eda4e01c0f5c00280af03a588fcf5d48c00e180c0683c176c08838e703ef50e252f8a6c8f3bc05af13d3a07504785d5183d6a5785d9806adb3e075440d5a3f80d7813180d70d1d11b93922727344e4e688c8cd11919b2322cefdc00cf0ba15bc2e4b83d6a378dd0f130070eb374220b8f59ba1225ec48de0a00f717ede7ab805bd756e68ba76c0e6cafabd39a752ee20c862ed80bde586de3ab7345d3b9426169aae9ba2b943895bdaa1c42ded50e2967628714b3b94b8a51d4adcd20d167aebdb951b261e134dd7cdd15cc1ba75231441ebd6b79fe9ba196a2d69ba78c46e4e397873f41613dd0cbdf57b734a4b0281c3b8008ebb1d284ec48bb27bc271274ca338615fead68d5bc74cdd7ab975dcd4ad935be750f8c6068c2728ee0607719dbee97654cef9c03df0102f7fe01ff887c76e27a5e254d887c7ee7e4efaf307d8c693ff01965d0f4779f26df0ea773218fe09e976709c0b01731f5e79788d98635d050fb32191587fc22346c46d2ae56126c223f6f623c2a3082fc51ca510564694e9d58e134ffe7bf28f78f2579e7cd0938f51f23727de0d7192e73062141b1ae23abde344c09d5cc64a048d0660119c82a7390144c0428464348e60215e3c624414425ca73910f00b37d56ee7c606871c7ce3c59cfa914c1754dc7cf09ebb27fd1f3cd0089d0b3e709dd67154f7a41f67c9e190a03e1a197104f601789a0b00090e12440b0b07616991431095178de000789aa3708287d734f13a98d7f934683fbcf493939099420e95916e47fbb21c2178f259ddaab3223f04e744c04c3ccd5d4a301020b90908093b3e1a19f103e4086e799a974002fef1c3e7c7122323603f72f0124f731296e054ca86540945a8498d8095789a272901fbf081a6857db4e0f0d1c2d9ebce7d744ffaf3d77998e90b97518c8dccc22c4f73242edca347173d98dc8f646e00eb91048fe0699ec304f3e0816402e6e14513b28f648ed6f0709de64cc03b3cfa448ef88fee09fd1d5f078b39d68f787829074de847a322da78224e280958044f73231e6e6a8271703ebc64e345ceb813308e179f8827ff644696aed3dc0958f3b218d97e348aa979221ececd89c71431c73ac8238b71e15658f3788869904751ccb15eafc8b8c9431e456f7dd539e9c74b98a941eb26c8917d098733627383b604754ee21c4ebee79cdb3ccd35cdb76e475b610f6d1cdba03ad035075720f7a9a0701a8742a15cfab471f9d38643390a9583f36b3bdaf524909528e732ceb911f0e669ce69db46679c93fbb2f82baf1ff4fab1d71f82179f02c00be783f0859d0d6fbd88170325e22dbdf5cf0bbba2b7ee796167f4d6dd1be2f50bf1e27fe0f507f1e2abbcf840bcf8b18717bf7f0714cd37e9dcc9b7546c723a75ce79fd98f3ce65b7d36d7e551ba77956e6f3fce68536aeb24175270ebbe6d835d79edbb20acae69a6b7743a1b0c78e05cdb1ebf4e661bf19b2d2732a3649c51c1c1c9d566e5e4e9357d3501e761e9e3cdc9c73e9a950dd69cba4d60377de6907391a1511fb900718b47312e5f84d07775ed7fc7ea1945ebc9ea671dc178ae0b7eb996b1ffd78703d525aeaf005a7886638611adcbcd42ca3db903d218738611e45d4adae3a7c3b6a48e9db5160ba25bf5161be1d270c188cda21f7b05e2855d55e8a3de43c547598abf6d24bbdfadd503be44a838c2bd037ddb634b587156813dabc6c431b182d9db9fceea2f8f8ec0b4560b72c0df606f46d5a42d426f48d42e990dbc32dcbb787a8a16fdfb26c409b9676e5867d6ff9768aa325f60cc528db63b7f7bc2a0af8ed2d8768908bf227472314acf9688402352fc247231dd2fc4d7aff681454f4dccca44f6e62bf2a28d46386abe717d72c73eab81e207e3be9d84159bd94609476fb8159b858c42828f6361f8d82b23c277167d6ab7399a779cd2147e7248eaeaa4e5d551dfccc6dfda2809fe94c2f7329dd3af8f4a36bb8a270c8d56328ab8720033d1f5f7650eea5623f95f5ea5465bf28e05707bf7e6083311609e5d0cb09460cb18b3448acc0082213d8200b971258a1822e6de04046092aae2852b3b0987467403f4e5cb921290d2f4cfc840182074f98c00b2d5a9ca14676861bad5a82254c5000f2918c165bb4e0e1816068d0e808498632ac5be2f4c9d23d15140a83c1b0f868e6630745c2607fc5112b7eca2c8b17191d2155a121a22d5ee5bb9265ad48494a52faca182d4b1eb1d9adb5d60cdf9b69b5fa90a48f9e752745acd382896c0ecef842c59ce1023a7900f3edb4c374517714636c0eb208e37b4716519ce13854f44a51a7ce4326f1d334edb331327d8c696c98658c6b3cede981d3e2694f0b7ee62461017b20c415a53909f809c2037e7a04c3fa94043f5dd29f1ec37033906ccce83166769b51070f7925856e491556c842a847163ebccd473259c0d0483a9bce59bdaffe546acd497a98924adddbb3d2eed94f701d593863a6657b6da6b6518371ce8bd44773ce39abfd12c5a452da3a6f967977aee49cb251e0f86b29a753fa517c69c5b3d3542963adb54a4a294d7537f8b160f6d79eb5571ccf1aec0eab809d71c0b9c3911966ba94525a6b9b075c8c2594c1328b34d618e7cf8c69add44bdd3461b7dbe9c984098b0582dd03a0f48752a323a4a44c68a8bba8b3ac6b96654a46f2288946876920ae2cd06043e08adcdd32ce53a4e16f7ae028c69194a398d654663db670a5e1e421de0cd30ca76badf5cb33e3746bd669bbd2254f6f984de7ec76e8a4f35e2abf3b69537ab34a7d6a6165a419b5b6d2ccdacc567abbe532e644ea74465aadacb5ab6c154c195053e8cc1abdd4fc22d8aaa0d8fa55c1b3082ebaf28e974fa76d239c54e304411206270641f2210e52def121ce7bc76030d80faf7982b83243444412cd9820aee2eff81a3f9c20f40b32abc4100789474ea968d974c545c69ff5a67c66b1a595524c69cfeb34a59489a462f3b1ab36762a0bba108b5ef7f3b992b98da034a3d7d6fbdd23567a2d12579ae6deb3e9165cb76d3aa3adb5566bad4bbfd37677ada8cb4d3a27fdb20696e6fcc25a5f48fa486d5561aea267de0c0d46d78278f91a87e9f4a61fd2a792468cbb453bced3749da6b2e2eba2bd923e35ede5773735d9b1e9697e3dc5d4d8444a9a533127bab59987d6663d1fd2d983569a691aeca40671183166ced82d5cbcd09a65599665a9d4bd2864d99af6e92cad8566dd68d2a861f221613eba986be6cc47efceb22d718df49159a8ec8e34ab99cd325b977c741a64ce944d0f95d6196348e367a404b96b77cf2ffcc254df2cbba9eda66d69a5edd9a75a4a2995a19b055e69189d46b79e6b74ff2f080ece4fc7b552cf7f4b0dfb696d2991489c18e7a45efea6f58ba1c7cb507fce9e2fa8d6668c837132c6c1c138631c8c536666367af6e1dca0f530c6186908627266b3cc33cbfa6bd31eadac3293d2d66ce2b6dabd338bf5d35aa3f87ead699bf751ad6a56d3b2fa31cd4be974bae2110c06f3e1155b521a942e43cc913e6db2228a32a66f85e72f7d1cfb5501ff0bcd34bab744871cd210aac8b87ea12ad259269323c09129f6b075e9619659cfac53c93e9c06a9758a735be1d568e6797a997c51b75eef871b5c82ade70627cecc387a094839c45d1539c46f371ce73cbcb7fabd1f4ec655f0636b8b7c54156930fa1115141bd20f65c0a1def3b58b4b37f770f330a5dbe6746edbb67da1f661cfa8a535bae86bd28e437e9657de0fd3d487f4335ba374cdf9c5336836457eb4d65ab194d265a8b8521d709c27514239c619299d9f9c7376e1ba5cb7de025ed785d8182594a97352b69cb3ce8f31c7528f42d0c8d9cd19dfdccaf7e757c7ddbab9c6a01b93434ce91453c6cf868f5e5190716aa52eabb40ddf4a747e58ca0fa7c19e6d6b566fa532469b1b67ce8943299d4e854edcad5a67d3302a9df299d75abfb849a933334f86fab2bea4d3059d14e3c4534a4a29a5544ada30fc516a60aeda979462d39284c5a52897967e989ae4921b59f6eace7035a0a4a494a4032efacb4c8232294a59ab9452ca1865edf0db7962cad14309e4dd8a2f7c07a5d65b6fbdf58b111604173d19eac7482fa5f3de54ca87f8b044872ca991121c993670b75b32ce8c02e72ad2e90ddecf67ed56419329634c399125cd6a66b3cc566a468ca9318e0518b240f8424a69cb3aedd82476bb9c5e3799ddb2e79c937ac7e3834a2b75d9d309fdfe32a9ede003476393fa418c5ea32b82105d278f391fc312360f03c07918c7600f23169d87f1061fbdf8e827afc3e0f5c2509e385dee5cf44f023f7f7632e6549f14cb8e05af1d144ba3a4f494d5b9432516d9ae5966b4318bb15614a898b984b21a8c4eab9dd99c5fadd72dcd94b6aacbae421a8d317e617bf79d3326344454ad56b5feb90d94a3df8fce3953a939bf5073fa454dd3b448354dd39294969ae69c3395a2b118a3cb59358dd27b959672fda6fce8446d91cde563df2e93baa5ce238e1863ec21f821eb1bcba2798dbee5918cc1a65ca121a21fa0a01c97523a0d9b11e9c82815d440dd5c421a4e1edb87863532cd965884bf507241f3934a9faf6bb64431618a7c8540d6c9ec081d1d9d6e49d796b9d53c6e9e05a6b020969a79aeda897461cd55bbf5ba8044ba64e93a5dd433c82ee3ab697ba43dbbc418bf9ed6e56d0f73a594c65863ad2d1b6bf59942aba98e95b4886b189e8a0c1453b13edd0af57086cfbe10fcf87befbdf7b35281d88c91a3c7ee5a91d6fbba157a8e84d967857a68a54f9742ddfaf4ec7eec5a882ff9c5b80aed67a57e5da4f758399be0c2ed0b6fecbcc3e95628037d2ad8e3dfd377e574aa7e1bb4f8b3a279c89dfc7a3d9d4e1f96ec1df759d11c86cfbe2e28cfa84f8753d7755dd7755d773a9d4ea7d3e9e4359cbaaeebbaaeebaad3ee743a9d4ea753d7755dad5e6f6dd1902ebfbba5ec9eddb34a99654ea775dc6037cfe334d85a72c8faf6cd711a6c4781355d77aedabbdb639742019143563b4bd64a83d0a86599a69a4eb5ec88c69a5e9110a41e16f93088cba52ab314ec23cf22cad2290070c8451a948dd3411a0a2e4f17fd4218be37a79aadb5d65a6bdd3eceb50f06549e2e5b6badb5d69a655996655956c3193ec412e34a7a6c1d7cbcb0d450b32ccb28a58e039317752c3cd3adb5d65a6be987857af6ddb98ad65a5b6b751c98bcea87a5bae54a2821e4f9507ac7488274eac59824ecf9f08b318974d93d91df5ee3ab86882434079633696e40c79717cf97f63c57d17b640db7372f38ea5ea87de195dd8e148ee7c3c845dcd8797a5ed8b9eedb60fda8c8407ffbac84607e9711e0d849c1df951ed8eb0a4f0d754801060fde90638e3a5ed8b1f4bcf087a5f3f859096178fbe12ed83baf06092b8a01fdf8dc60c3eb4aace3f5f3e3853f1db063a9014bcf8b73cce485bd06fce5b99ace711ce7281f72fb7461a921470a3296a0010fb43802e9c5b94fcf8f8f8fcf0f9317f61ff085dde727f5c2fe735fd82b11ae3e30d80b7b10b017fe6ae8e982831be26022052bb0c1062f9f4b85101d5c5e3e3e38dcd71554130c967a5dc9d6c0602fce7d70005f57261db017e7383079711f962245e4408b9f2f597cd8e2f5a56fb28831262905539421e635b9f8d4c0e708336bc6387a4d1444b1050f6240d1850eaf944d818f7c135d3ab248d5ad25e5ee231933b025717c777777dfa08c3f9229a3c6b7cef8f679b5639c6e7d61952259b3954e9d14545841e654e63e922903c68720124958a42d7c7a90e50d159c404889962b5e008b030e2038b8c091a948420755dda1e22acbe4a0a84c99bff948a60c9126c4419975d0f1566697301f9deb80182058f3ed610864d02da554720a7b843431d14c16df552c7dbb93c88619b18c30df0e46115fc851860c221a2fdf5d7c116b00c53716597c7b175e7c1187956804b3e16598517062f085096098b043add9298432c68888450d90d40064e3db3f31862801ae01044b0d6c503024893805cc8697a171bebfd0036728eb14c220854d10ad2fbe65f78453f3eddd39b95ccced1482e0281be3db67e7c49ee0fb491d621215c06ab937f87e32b9503a29a5744e4ae9a4b206a7f0e713df0540157d37f9febe67ca2c0917503be43012f6f2c99411fa48e68a18928f64ac58fa0aa65bddcdaf82a9b5123558adc815a85b6105f312f69212f63aadd341d3c59a49d2a99ad824be7c8553493a3dd32efa6a2e625e7a0cdbcc4b8f619f79e9316c342fc356f392e9e7254543d3c8353edd59b4bcdcf23294a1540aa823a8840c7765490c32a5660680000008002315002020100c09c582e178344d04c5e20714800e7a984a74529989a44910c4384a19638c31c000000110019a196d132af7690120ee74a835c5af9be19f9ab647821b03d6d8c93d81b6b8d0a8cd4c6d06fbb4a2119cfa6c52f9e3813a1271ef9647d05724ca87f16151dbd7b7c4223a63696629984669c69f38f53d083e156d27c07cf1ba6b95d53be78e79bee2b2fbba80362f430d4e537a93c49ff6ce71cdf2536ddd8d394465f905d88135bc4899a30b62666d361b0df7d8b20c7d9d7e604d99835e21fef701cf4592a79c7a7550aa12ecaf725b5b1990148dbf1cd14390033ad09bfbfbd3845c951a6de8939708953ba52750998ae77c3363dbf1f2a8e9b66abc81b66fc3f89c35b100a504cdaf22490b2fd49351382b9d2a5367e802e0c204041202076b0d740aa0a2427b25af83b6616c3e0f5ed9fe3831f54627a60243204bbe87c0b96b56764e66d2f5bb34fa6f199040c28764f7f35fb2836d16bfe4d90d8aa8682b59a6fb6ec007d3ec2a81d310fd79fa72f3705c7873489e78e4feb410b23e32c4dd5fa10089d3aef07e9bfbdf0af5d2cfcb3d3156276e003b36d60ffc1790ec48f603a3027b4fc10dab4a76ce11c6196c33d258730f982c59f912161f982796517da77221cd58bdc4959def13f8238f2d17af2d758491137dc458c6b324471f094a206f0d69d77c890248013431e872a448c9fce8daa3f103a58925a134a39f51046fe4c9809b1834512982b978f672d4002d18ca576fb014df75328b1c05a223ec62997637942820fd612f9c846968ffe8b9970c908da5a001d724df66ee82f6ae9c349d888dba18850782f2765aa6b694decb1444d696d17ac1f1778b0463bc48c0dc70d48a7179c8452401994164ff82c706441e495ca8f72df575626788b30e498145e43d762eaa2b9d8e24a90176dd16053c79ebd0e64eda77f59cd6f8b7e415d8fd4411c73da76d92def7dd538f09a508dbd347eb7a36da4ba1283f9eca17db05bfda0ca83f5174ec83a1478df6911c362d5a111468a3630229dcca4d6439c8d08649723aaf82c8c5ef77bb7737ec56615eaff9d081144bbad34f46f1a510131f9dd6dd54ade4098d53914e03868f61e4e657a8df940c9dcc7aa1097d2e492afe783402047f3fcd7bb37120492503a0eede32aa9a231809318e137624638a56f4c3d8486df41840852b7ce6d135e143d6d03a4841c8debd347441dcc0c3a01c62f3f41a110ccac370cefc95c89580f1868c07aa9d59ea58e15b456db3e37bdf3929415e405f0a0e26ceda283044a413c53c2f6d8c33de84e25ba8a0b4658d3d7a0cab6f8d82b20983404bd71a76ce813686217ba15196a01c82b9a517a1d1ebc6151fff856ed13595e67117d2bc05afd12a8724f18b7ee874f61bf95741cbfc8f22bdeafed76f2d672521cf64932d487c223badf4e917dad47c5d0844b767d9f6a2628a55577938f18928038828a4a28609adb24ab8a320780015226a798eafb9a769d6bdd287cfac5e0cdbc431e8d116cacc8d3011759d48a46802d84c16fa4570ec5c55e47c61d600f1a7521b5288dd70aece09ef11532042cc9de3fe71af8403dc4381aa0e1c3ce178a9e760d3f9b5ae0f9c6d267593cd9c87ea02414d9c62d09f0b20a073c9cfbc6fe0529743d3f40ccb5421d78e80b49242f4d8cd1698f520e7066ed94a4dad0e44e998afba4542eca6586511c070b32ea39b8f82c55128fc020dfb36d0887fe60a796c88f39c0eaa8ae0124c4dd2255239b84d6922ea65ac4f0f1daa3554d73b4954cf6706f789c5d7aca6a3d2e3ad26432e829ff14176ffeb3913eac1784025a7033c49d027485b7c0e6a83f8a493286164037c23f3e35913c36db6ca084c8430692f9f950eb9930cf0e66096cdc1cdfd68d999b6dd11bf18191dbca081647486c6c41d74ef55c0086abe80e3cf7af17dcd01c8c48a04d2c77117dd4ae09358099789c9a319b24d816e4a55cc9de288879e492d11870b4679b7c71710953c23fbf628dce27a4d67f851ad6ab9273149f52f78f90f4892f9a72958fb1432fc4400e62f589f21e8547cdde573a5273921281a46f2fe2cc9e132445f6553f0daaef0508d4595feb40256447cfca5ca7f608ba108acb9ae03d39face9da4c84bf32fdefbc3fe47e63ba65ce96f839c3b25f55102f805d039a9389d3cf117061cb2bc9fe5678226b5f70a0183cf10f0eef96de4b81b74ed21f46d359b9acd31780b8c9a9f879abd7d2e67569a48a7f1c36443518dc02cc5e05920082a2a8df06c9cc5610abc080fe1dbcd110ac256824b67358ce09a130734c831bdb4ee9815b9b4881d8bb29b06666bdf9c5cb0a999354841eec7d1cdb09777560b07cfee03435c606041af95363db905b029c620a2e1e0720edabb218b9eb3773494605217ca8ec544ab0ed64a9d7d5fbf161f1ab0bad61ff1409b8686439e4d678a866dcf5c95e6520087ca106873465e682d1d45527122dd0c2ee1116b23e1e7b7d60c5a9a7605f5815fb1879a0e1dcbc61327008fb634d82c80a3fcedec5aa513384e66cbc0fdd1bfc804acf24c1852037e66fc080ea22481ad1708272fd01962ff051d6557fc3d2f1a6226d133410c5a903a03f6ec4ee542b27054b4bd2b041a98d81c09b6f0017b0651e328ba7333a32de00de561cfce4eb75e407699ce0aee926f6758bf491b3580ba16dc4bab64fdf641d2a18e68e3aea0d5068f1177c159fdc0ad58f2d0330f133a1793c1c100cd4b1589f172d2d1827b2144d26fa79e8a7a2d33de7702a11427efb04cc60d309743dc7882f1d26049d73fe9b57b39f5dfc9bd503804ce207e29948c464bc469853cdbb5d5aee8991657bee88bce4d3773b33d0faf8c576af72908e1e80b50dc1261c86bb731815f4eb1db39c57850f3f243ee525da8dd5804920ec4efdb35453b01db8b5477c61377a59dfdfc49e377c4590dd024190ac6ffe24727c677023f7f507990843ad5a936440c2874db33c4f90b084806ed1904896bb6b384795ff54fbb186767cb4073b5be25b6c9305902a8d8fc1f90e4a1f29782af8df46815621c486686b8caf86791bf76b036fc484ad0f3f3fff31b9303775e2b6465d9471084a295fe4058d7fd0937fb02ac775e58f28b44fb2af86670bc6447a392d6527492b83ca34affffac9f49a4949c673354605f5beab7b13fb30cae04e4d4c67f80bd0b8b6396d03cb4243cad90a5d76ec6ed8f3e0401fd1bb16140c7bff5d1843047e0d0fb727c8b15f48b768f356abd6767d3a958148198ed40917290359595d8ae6ad1b73eb444fd36f92156f7735f29bb337efae7103b209e690fad4c51ae294ac66032d014498ec7fba5684219b6e4b1df0bb6db8785dbbedec9b3193c8d12baeae4f06e720dae026e61b6d5b68cf282021b50f8685e0a3228f2e6a63c0ad0cbc7bcd705704af91c88393246aa81896955f8e431bf45b2aadd7d40dc188d942c1e7734dcaebcc34e922b1d13edd3d674bcb6f27db6efafbcb088f9b374f329702a38de9a5d68379e9b2c1dd964e7f932604acf72de1cc1bd0b8d5c29d6b7853cd380bf6d4727cf94643f9a44bbd2137b747ca42b71c255ce0f2f483f4506d4c76a5539b905dc8fde9cc5a3a2d40c3e4418013bc935f36a24a50ea45c626d2ee3c399986d10420eae5a5de6c92af31f2366242c9d8e2fb1c600912477390722dd556183be27327492b5befd4744d5a0d8bb5a9aa3466e8c32a418f6aae1bdcbb01a8caae310743c2773badb0ce818808af43da320c1fe1aab66304dd0e2298cc2c43a0070ccb04eb265db263a195f18af9dc2f87411972c4de59d871db004d6c234e0674683a7592ec67c564b04909f6c4bae702dfa7d656ed4ace9b3a0795785f9c45a311c9853020b82d909bdca360d4541f634fe55ec01e0282c11f971c4ff69603370f8f84c2118adbde8ca943595eb69ea300d1388bfd485979623a3846189d8f41447190e5007f86d2f3f9cd9ca7da0ceef708def0bcd75763ae857b560934d3aae1a3d5e5d25546eb4691431961e61fbc670727cc04db429a1cf320e8a2ed92f6caefe2e3b4c8a09be85dd7720d472cb8f935f6b3ccb1e1665efd1333c635a1c56ea545513348ceb295bdeb66288dfccb26c4d714266d9fc883bdf888f22d8bea17c3a5c74106d8a413645827e313463ddc29742216f2d2276dd41eeb6dde40b38353d8ff78216e11acd9c3e290d54bc13034a5e39c9c08fa7669f369b4e39c80d985bc02770bea5f1167ef7da95cc0c175c49a1b6a912c3df508f7ab7c931a4df52570b7bb2dd3abb79b3bcc3a44709459e9cf8fe2129ffc21cfa19216b1a33deb94be114bc67f34011ca99dadcb0c1cf411f10b647003557b382ee99ce1f3b2cc19fba595a24f33bca5e12bdb78bb361f1e1a9607b6acf2d71a1f10b6205211b9724ae51a1b07889606b18e4dd312f3cf6b58c26482286915bfc9041c6f94d7ccfc019134a0644c5c6df12a7728e8c85c24df6aa038f9efa566201f891d0554c78963d3ae0e674145f47d19ca1f9f42ad0ebd529873fd38b240b295400ed2c49b4d22d3a589cf8fbb841aa7caeb0b9c0fd74e30f398d15205d31deaf11f0fbc62fdd326d22da8837c0d8eda902ab2c84b8b75f8bbe9cfca0d5766d534c422158d35a2ebbe16fc49f690289f467a478aba93258b5354d5754b4dbc9b54bee2034b6a0e9f2b24f1ca016d018403415c8c6bb5ba0dcab708fa588a86247e63545fac311529fdd6dbdf769a6fef1426ea94b7d9d8e153c3f0371358b364b4141a7dec54303badd439d3112cfb9bc067adabff78974b4cd78a6176f42415b338c1e7a8513bded7ad95fdd612352dcf06e8b54dabe7fbcab8c1801728c6641f132f1a3f102c936d80b2c488d45b8212a2d20f2f74e3672251b0fbc9d464edf4452692aaa47b1d227ad14823d7a936feb014b9cbc3ef6225467039b4b82f52895ab09734393003a266bf137eb7989c83091f4d9978cc9228fdc959dbee22e3ae038280c960b20887067d3bb6d6dda33ba56e455ccceb4fbf62dd7b0f7bd3bdf5c2739e94e79754b0cb8b68282a30b2ed11b60fd1cb00f2f92b4001a96f170498089cf61e090abc3313325253c3bbd7a71a672d2ddf28493d2d923cea6018c5fb31e756852e285f0e99249ad138e66d23fe102b0296b46eb315a4c5bb3ed4defddcbfcd1b1b2716f525141fe4e405aff7ce31dc60a3aa489bbdb337ae54bc2657b6ca74134cde0277efd6a5278e26cf53fa0227f05840b48070eb8ada4c6e6bb2f0ad5c5f04a8689df889b81517f35668b9fe339bc0bd7db90e8a4b7de8f832d79506fb98a1499b80bbc3613f444920ee2b5125147f0418d2c6c81e5d58322726b39aeba30a3eebe2b13e5b7b741b84926db838402f68998e06e91de091fb037cd66cca79fdf28e70d186b7b04204559a065ea74ac227565cac8d94519649a1f3e794719ec2e5a35687f2c3c28d1b825e9fcbe7c7476b61da07c3c08bc735f4ca199f3f88327bc53a1276eb8ab9902a8cfd166c2e650872b619b70f14b87aaf13efb09c8300127e92178fe41f54a94c24b61fd4ba8aa6889022575d117853126fb0c0918e7223a677652a7b3822159f45924b4209b5d7e52e8448e8bbfafc3485d50e2b4faaafd4d7a44920ac55474bd2043c9dacbbf817dac2ccc008c8c9ca9a07b1ef57afc3a19678d2ac74572e6fc46a5d6c769a3f36a7af78a039d0020ab4e63a0b137d7b3099fec9135247d4424e316afef94f40fc6c331d0a3cafe121c50034d2584028d24dea06e7ab8f4f9fba1f855548b6838f11080832aa540311b90ee97a3204eae1f6c8edae815ef312091a8e3126d88e6bc7d449102a6ece9283800d8310dc789d99282b9e63df4167371d23d27c0089de42a3a398bb44442277aef469420d1fa4b22912247edca2994a0efc8fe4a285e61daa0088a24855ffd75cd38a46e265490d3e2a1fad8fd597a291b8d3dafa7c30f72ef6bdc9e6d64beae386a713bb5f8686dfb9956c5052f04b17990b70ade29c60d88da320915c5d2cb0879765258b5ec304f84cfadd3892da0e8eac99997163964d7c55e9b83a793415638b7391002441b7baaf3a5fa59e188b72856f481e73fb400e50c73e8b5abbcf984932cd4a2bbaed26b24465f9020c3188274fe2afdea5c6dcbd5d351c1e7ccab740e963a3e51e9515b0b55cedb81308ddd46c26245a978a9fc3912f02632526c022e3e4ffcd1ece6fd6d4b1d5207e11fb73b3e428ed7fcdcaba102ed7322f214d6a83da6ca50089546ac1f5effd806b79c542529c93de198298bff596fe3a722bc435f950f3ebcc110e561dadc97ed9a486b18a138d38a848d65256f5fba945b63456b706634a76e9286006829eb4cb11067d0826686b3fab5795d27b102f3faee22c1d169c172dd2f5f85cd75f8041f6a92555941ed226d38be3864297320f9239f77d31fccba73d0c27b870e1660fbebb85c7e47b66cde7a5a5a66937b8bd671c7f362e88973cf62596031a5ff30677202ca1bd00038b97ae1b77d15d22c1851257937c256f41c87f633806c2b9153df6464320987ae2786055320d224f5855741aa3c4cacbc6eb8c15b0a108dd3848ebec19197d3e576c6c78238fa0a3919493f9246ae7e54c43c81024211884c098625ada13addbbb381792a8352c1b4073c8cf0492e1cefaf136999ff7dbfd3d58a6c1ae3bd83c0d2aea164cba0f6ea3161dc97283fde0123967f3f8205d727b2d908b148a3f043b0842b3aab7250c4c90f33726da76180c10114e1030efba4fd58a10adb92e68265e9c13ed1f5e842af22b3ee2efc4f5e0a990f260248169b70a2b99c4d883c8e7c122177a3b85bfb4e7a703f68eb5c77230b38207b826bb9e9bb11047088db8e2d588ebf093c51c82d82783d008c5cb11dc309e7f6e394f3bc98ec192e394f23769ad60e1bf1370dc0787c3692d9080b63ae4bdc36350b64c6738b5a6d53278a928a619cdc9aa8a2e2a465b8dedc2605188a616a6596a537c02c31486348889869f90000e0457bb66c2715fefe69a057681708f4060296fcae9de18c9fd10b1cfd2dc5d16e8fbf3a98718e51070136d283a847aeea6ca7a30c70772cab0407062f1b6480ced76d58eeed07d038c1d72a4b57eea93ec11e47d1b78c46796cfdae727a688e9808f1d32fa10b93934f0e18c54c874956d0f9985b05493069e8145377567e429db321a933cda4df80b80e6c66bf72ff21c3b57da471004e49866c5a195ba8336a239919616f9259dbefeee94a16ffc078b5c6e37764d6c2cd659bc67e2568f36190585bedbc4170acdd50ae05d5a44a0be9dd801b8a2854960839e67da4c8e665ec69e17f9ed54b5b762d03881bb25ee483ff5e0723436a516a65092a18c928b26267e5c86f91807bbb7cf13bdb92b3e47b2ffb424da660644770e6527ed7386752328b29aca840016a929bcc1e2b1b2675ba001627f61863b99a7452d3f83383143807c85375026b93e52ca050c3bdc151f944ff874c400aeba31c43cfc851fe1f3c0d72fb65409b5b95e4619d9fc95fe1c17191fa86411b38b1b246465435499f36d67b415674aebd38d6d41554662ea6fcd88d9f96838df0dc68208af894c8117f46607ca25aa07ecb9be2f208f2e21a3bcad2fbe0fcc11694f89c8c0393722db074b8ec0db63c6719f6f2ab788b2a82288492742ceb883d4f1d425ccfd61d9917d6b3b62d3aab62fb78cd96c8b1a6d2e5a9bf4059196e4941186b7b4674e335139b95c6497ffd885d7eb52b7596d44088a86a066a013b958108a251b98bd636ad100a0cf04540b398d8731a24d2a7629b35e91deb6bd09127214d47806d1695221db08583c55abb7dbeb84a8804cc1b8c606884fba5dcb783e9461e6c49581a24d263070e4ee29c2129da460fe876614748aa9963193cc04c29551825253fcb710b8079c802431eda07ec559a4b9071a5362838c0bc7c2c350430322c4877dfab0a2a1b0462684b4040f5ea1d3fa1aab374927ca5b74d8e9a287ec700d7e2f3a610fc2b83b3dc3e8a090390b25de9ee9633b16c146b11b1129a20801fc78892f2462b3809166c4b38470b320450b7fd7b178e5c83da2d6ac8cb84b34fc2b3c40c858f842b2bb9efdbc8ca2c250b290b5c222a3d47f056d8297f44e1949205685c238c6a984240c7d18b2a8731bc0200a0f46ecf4fba91f499cfff2fd83a82ed2d83b66148e2bb2cbbaf0bbebecf15f85810af2c53f9a37265d60cb11984132b8c9352925f24bf51e7134eb1d39df76dc10fd0c661502cbe42e90f56ec22d68f796a0771caf230a306f1d27712647d0478b156ce46509354663d4cca6aa4659acae27b2a2a78e45de4ca732fd7177f4749dd3e45e2d435dc29100357ed8a07db50a7d8501441b8808558dd29165ca95c8ef7805a8951241f0d5a898f4c6400093ba8e34e5724f515d58aa83a21a8019dac09c94f24254b483ae71445a8e6f8f886cf04383ab3058419217eebc495fc21f5e101f994f512b7c36cdf91b3ee4e7f7877efc5bb3ba610172f419344390f850d87eceab5e14b67bac4542619b30084198d724e589d2d12685aff460a7d3dd08232bf227544aa536021f0bef6e8cb584c1b0b0e35f45f3ff117fe5d00e6ad1cb487f0fe289615e262bb74eb64d1d2f6081e15e4e6b875c2bf8af94f2a68a20e238959fe052eaf8ef5eb98bf607010abcc757b32ef3811fde6fe207f918e88ef397af786ed769b0cb24e94eff0a0e73c97a3540a886b9ea896ec190f5e2f605db1615408ed911b6ad7353919cb3dd99838d4ef22bc4ae30d3aa5bf6bf0a9ad2219fe8ab3b085f29ea23696e27d42f92102007554ac752de923a302822e932b915960e9a6c1403bae166596e724aafedcce84fcfa06ad1f94da719815fab4cc516ad7131fc75508f403ef0d78cb8875c640c433180d6cb43ec011e0fe5bbfcc87ddc6763c067c5664dc773478ab976247eb2a3e0d55bd1da4c1a424927b860f93ff5e66aa4e194bb65c676418e2929280aed8b4a811c8cd1090ebdb6012fc406c0486683434dde646660f5e4b20852c54ba9e7a3dff1e2c499c05b8201219a0dc2e104a63b998a87abbae24b6b76da59a4da5fb2c1c6f62f585f67bf6810f54b245c4db5ab912a494e95205414451bbd5f3f901fe9887529f126618173b04b962227fca7163a09b5401c545eed4b408ae5af042ef8f0c083447c4d7475bfef383a558c212aaeb2a6e816653236bef7f6516e22fbf9a788b89e979544e0ef1b42ddb773c1819e592ba7c06297e22de4a9d9c03fc5d8f52924175fd752b0b726e4d4dc063d371c879759c35e66cdcab8dd38dbc61f83bdadd49a6b563087f38c79260684e5966453fec96d84782fba5829a4b3be0e69ea5b0a1a282be5042268e923b6963d03d6f70bd04e8c08493d7ef03762997adea07a1680f4155c2870ef58600a1c314841f28ba9590f345a15c0b0de396b9630a6426d65ba63920d8d9b774bba71b7445d987d3ab2369e767e8d3a9eb013568358e403834065abd2956de49a18ff0d42200144aef7ca9f59f3bf84eaf7c20f3818d1faac373c99bc9588946df384595109522a2f14b61b65ce12063062b5fa1789237fb10ba4212d0c365ecc227a7c744715d77073ba8438938f6209421a80a1e72580f93fdf6ea55b8ce91111665c65c3f20cb3df35c29511508592360e0cdfba0de6d40967a6e92931841eb65ffcd53e471042251fdba03222f77fbe46030db11434e287b4483a1fa1aff58bc46d79381d59964fa48120720f453eedb3ff7df18aa8ced48fc7087a092f0481df97093a637e978b3eef81d165cbbdd4fbb6aaf48ce45d6f9b2402349d66084ad9063b7372c6f33819c51329f55a13a4b1898776a697d090a4ce4b37e6a62500ddd2c0b103aaf48cf4a15675319f91fe748fda8bb10456278b0d4f6b03ff351b31b6bfbf68adda1ad090057744acc58c2cded3a9c86ca3e4300f590c6f4f373e047278e3c8a2fd195d51a4d6884af682ee289ab2a37dd5df5ae758ca418fdc10d78891798fcf982c75ca8400cc49175bf32eb95e354667a70ae588a4bce6f06c711a01f9495d6319e3e4ecfeb94cdd88b228ad70b79260ac971a6eb571e5c6061fac598090a9b5af2952ce8dc21f7403c10487045c33a55fde73fcdb5a55567addc5281fda44d9b2d819fdffe692cc576a17f83309376d4a79a60499e7771d28588f90b70ce9e2ccceab27110385707fd3a637dab289b593a8ba147480ad7d8ac0664db15f4d68e99d26457fbb31e512ca84a70cf9322c7f0026e12bc3b43e7c36440c22f5bc895153bc6aae9ea360465885af52bbdf92a3c83986867f8e66537a2240bfaf665fae04ef1cc49b70660f5197290dde1ed33255caceb0194905c829566907cd21e6360bf2d681ef45fadc7b4535f65ea3c563b4a726b76e911a87e4576a8a21e2d562b660d6a4e7ed6e5d11238f8e050148df5b4b0760967f3a8911e69183213b87b82eddfd97c14855d8cac0e186a36f83461f6ec09e7d556966e54344b679f92cd8d64e304989e3739ddd13a36468e0cb1493cbb8aabebeef8d070420d5c318542210b35abfce11a119d6add007a778fc998c7cd06ea0e1098ad7cc0ecfb79df8d1e1fc356f17d433e31a886f809f7258a779dda564be03fd9c0f5480dbe3e43719a31ee4bb2f7a775a4fdef485b7e54524d539dada14fffbea9cae32e0237ef987185b6afdc027be89729da8034a4132f31201883360526fb645c68e1ad04ed15da738889832bc4983da197ff7b1e351b503fa61a319eeb348d8bce23478dacd82a1c78673412517de7c6dbecea802430c52fac4ba3a6ccbb755b3258788da50cf139c22abc413448abcaf0977bba9ba3649fa0bd5ac8beb76853dc30b5197a0b5b1943757f8514095eaad7b1ea65af98b4c93c039a69bf44c801ca72d45a1563dc0edffaa956abf126b25432002574334272e4332e637b2cf9e2b150fec429639ee52328de55b6a206b85eeef673ee497e71972b5370326a166a0792d3c7c294a801a8533f89cc5ed0bc9401465c0790c6d9ed358398fec184242339a9d2e6b5f5c15e86bca0c4a482bf894a174d8445abbbd14bd62c1b3eef0ca51a0001536a5c9a596181810c39c4ee0a2e1236d1ed57b809d02370a904fed10bf7dcb63a4dd5701433c9a6ba7ddce5386087feb1931833c23b1fe5146c7a9d1be6ddca03593be8ade5e7747395f8063996feb66cf369e3a1431f77b2442ce82ca6d6edebe0173f67109c73e044118b93e77faa95fa89bee0d16e5000ec26e65e255c454a107e44f950943947aa455d2d48c6fd1e17df870eba241ffca0559e4497d82448b31783aed47b8f5f5581ea45ec75f4cc80905230bcec9b973f3081a5f60e815b328c9327163c380183eb2ed921827e11deac5588655ca22307207a2817cae4bbfdb24f4dbce02a2374e641bcdcc00a2a0aa3521b170a582f510bfa3a949b265ea67c321b276a4e71cc33c5f24e6797ee665fab51e6783a0de5fbba61984bae89a57931abb558b990daaa48d8e5e1f5f7f22fc3ca5492551b3361b31cce1e931e61d9cd755402ae62b5618308b343ad2ee81e305a87d1f255c1fb502d2222f2920853cc54530de502e33a084cb4dc66f4eac7f7eeeeff81efa57c196aa6c514c5d9bb10034e09fa9e4853292ff718724c7c7e43bce5116e0c7d27be3640407e9152a5790ce9dfa90a7de80b26851bae693c91bda9a93189953167543b802d3aead4f771b83d72e902ebb117c04570a47f07033b1726d92cb7625b017513e32312d03e9cf2d211a0e8c0e1e5169f92303c1191cd9872b698ab010229f3f944a97de7f66ff3ebe00da58c5152866d2e46730136fc9896399ae3b48a4d00bdc2f289dcf070d42987658ba4b34b1eb2dbb474aef0098a8a98a7d5e35d0aefa1a6033406627201c0112bc1d49562953de61e06bd6b4b6312e00d6b831863ced0035b6170e081c4c5bcfd76059d76f9a61945aba429ec60cb8101bddaf2b301e449ef452e43e15e2a5ed93667027cf683be5d181811ab9bdf8a20e55203a1ca404de2ac8596d845100c2db1d07ddb955e8c5be5acccfb8bdb0ae6fa73d3669ee7a4877e88cb2bad19446d7c1623574cdde4281cc35fb24a1560558e6009c17a60cb1cddb2c70a167021b8e45a9ec57e8c93a8a7116f58f02f7e4c7c02e8dcd1d7f1bcff997943ea2ab5ec447747ac271632bc1ef16e84797bde38f6ad08faabba60d61057fcf4273ae7dec10457cc47c40eb07e62d0176efce8822914b654f43691300ed12d42d1339d59eb9bf3e0dd620db388482cba7469fc02f016eca6e5d294d4cb5304499f2340ccad60509ceda35aafc66ec2466fa4ff3ff66ef2144b1e0119d73e8e2f18e6dbd74f4eb54548ddc00e545ff20e34204319bfbdd8a497a1925d7f2da10f6da8cfb63d7919f364d24ba5ae6bfbed356ed3eba081f815e57a0bde9991d8df466839b8dfada5822d1102b7c6e17f08f57a677db14894ef3585d8aeb0a2201647228eae687d7240a891faaad596aab5cc4ba1f352e9022e87d17f14001f0c8dd9bde3957d451192323bfe110733e3fd4bc59364817dbd23480eab0ff2d5d485cacb2535e4e110f96134e1136a54df0196c866413ebcf544ae065a4eeb2e1cffcff5f7d18794a2cf4d2c3de22458f3461a9af3dd6e0b4a0da85af499caa9812d45570ec307e6d3c4b0b4b82ae35a28a42a30dfa7342c3c5a6e8770c328f296ee085394925b968d1441c6b8489652921fae941037a5ce843ad351f25db8512ff2d0939696722f35906392af997dec2e67df027e0c9c20189021de533a2d5a65abb80c0ae86e8dc6c258f34030150c273dc4e28a986e93e9907934a1006abfe0409f930de4fa480535403504adc14fdf08989aa0a65ed7e464978f15a3292d7a0a4e3dc392cebd7a83214511a3921916e8ca29c754c01d174ddc5d24faf236007527b1a1657e5aed19a6030ee42f936dcaa54e78652df7256a5f0503a01a6e8306872aa8f4adc8048a2f8c1feb25eea77a29feb6f3d036320711d470bcfc0b522265c2b0e27f4912e53b357ccec905feb266c1478dc7467d85ac233312a917e9586108ae7db9686e60b1179547191e17e9e5b2565e96c3613dcef67b18cbeb734506436c52761ea586a816306de4895c1d72d1fd6a08d31ea50fcb05d4d28924d66beac6727ee8fd5b69fbba12294e87e82296224919e2c2aab48364bc4458e9c32a2a2baa318e0c1fe909dd33f074aae47d55b5820f42a408c6da1d08ecb5929b634d9cb19a3cd4663c1870a56cf4efb86f764e753ee9c97eea38db806b6996aeb8bc375bf8f9dfffdb55b041ea254ca94b771cdbb88ad9b23c3604d0e67c455a9c7b9e6c856a0d71290f008736b428e5ec90bd2efe8aadd5dc035bb49b6166197c8a81f66e66834f1d45cf757d626ab116b075442472c1cd1e4985e4d7b474e5f39a87b2bbf2fa99344f562adc9ea126d0b6b53ee6c92d6a214e33fe483d7a772190e4fcfed5de7058fcbb778b536f2c1dc7150ce7380fc590284f20f5c0529489552d0636e210cf7024bd0563101f9b8e43ca31c1654b53ab0123384d0647302ed108bdc14988a5805d513c6cd2be02b9949fac87064655e6e2d5a907a8b4cf5a013e69e4a324e12d275c96dc8fff666d5ccea35e6519b0790a64dfe7ff07395172b724a04bdb6b1b75f85c3229bf28b7a69044ba08493158131f42b96f2c0c3c63c6218ba52d0408aad955fba0a05afb0ae5140735002050ce28b3a830c2634a3b819e5bcd3d699f13ccec6118f0be5f4a8e04462a46cc1a4b2d284b4bc3b3dc2957e7eacc9ece4328060750b818fb0ee09072a94114731f3c5238a2b96fb5f9c4f78b9139cb21f89216fb5ae556f19d3b32818c3b46f561cc932e75fb30aa314245de5a8cf51bf2ede6f10bc6c0a165717337904dca8fe5d38e865491b2ebe4987735879711d929b83afbfef9154954840364bfc88eb7cdee9da3fe618825e2038af73bcaa3c6d6531842d0508a1e8317ff7003b6a07eedfcc014c50778c0997d06795dfb2a3d19eae0d34c2ebabb707b47722b43a9d15e164efda5e19eb20b441275b9fa5c79b3774419f4f7051a0baf8fada50e224baf6219dd2784276cefced07983838c30b31b2215de615c2b1e41dd8a575f0c4587f4addec0c1127775159303403c2e328415494055a38c860c25bb49f5173924a229a37facd6a813b9b271a96f0388a773654e8822471e4846d02571e10070cc9bf1a3aa32c8f92d318ade89688b0d380002bdbc7dff1dd7dd61c547493388e215a51076233b6946cd235b8ad40d0da77adc288332cac6d8f7816d5f1b00782efed00e973710fcac08ee99b0f90e10e7bd55cf02574538947be99f0d4d084a72d00ad1c99237c59155851d90dc62cd82daedfb261354334610d546f9ab1e83370900f6e8054241f6026d47224372dc60e544e0ef81ad94afef1ab86712d0cf524141a38c109500657b1dfdfc4a2b1c424409870b58817bd7f850cdd68948144142ea037cd37b080aa474d5fe2c268f5bfdeb580335c87725a367ecc5610192c88fd42e36aa56ee091ed6305c6c5dfd1848b0a52a2a051d644e706f644880d3df89e265e080a4f8cf3dbf64ea4790f84238ca73581e8ee206fdb6ee8361d44590a76e67d10cafb6cb0807df95b27d7ed8bd79b23ab56ad5c0d5196a45eaa5487d20e59fe3895afc05f8c78be87c40a68022b5c155f4643d51f67a54095370d12e5522deb08b426d900e91c9b408a529017411c6ed3d62f2d26614ea2077e0584f6e761a92d8ef3b56eac0850686d83912d5d60c4bd0bcdbbbd425656419060c4106a0fc145ac74071bcbde85f0a6ba08fe161abf6906a06c6afc1614e06bf952302b9457077dc9c1033e76780266d3f5788b805404277e585588ea20cec846a99c9fb20fb82329dcdee0c57778cd3b3cebee5f407762682c5c867eb9885b4a0ad441eb48043feb3cc1c04bfde32ec0096525306cef688fc37511c1b16a8bd1df78a8da68467913779aa0f8d9ee0452b06dcb62c8d25e7624262f9b40bdbb4c04e6ed5730a526c060b881dca532088dfba3b43aa12216193cb9afd58a964ab646ecee9998342420ff8886d893c02f648560fe6758e57ee6cf9024117d859ba3e9d7766bbdcc4385347ec0d607d3623a15a1d1739454b4469349daa11b993f8f922f12e3b1b70d14f6e0f974896d5a83aa00e5b8cf48eb6b7b3a961ce71768c711558aa0152e7a405925d625b44146582c2615a739a3546fbeb3128b034ace74127901b2eb69f335a9ae21eea5d660e89c105bc43e172c5b4b741178fde63fce44a78004c29e106fba7dee054fcc8d556e3809227e381633928d1ffb12ceee68c4e0aa403618bd2ac25932dd1c9921ddc6dc16211c558560beede0fb900ab122c2bf65067b4a19923858b3e6c32f64f70c402b2c421eb60b5c02a048114b4005dc28278fdf5db38ab2066debd4ffafcfe59cccdd24f9d5d59ef0e17efd7de66afc62c070c2d2aab84df66311f1a01fddd47a27d9b043fd86bba4ab8787ac6d8dca13399c36f36aa8b7f551d9cd752b81e8df5ca42c42c7becc0198dd97f71868859c7b1fd4a908e3f95c43bc24358077cfca76ba724dafb765f8ba350ad872d6bb81f3712d70324b51a92ca7457f9185aabd35d0c9cd0561516972afc7317c34cbe865eb011dd81c002e8aa4bb6701e4e8888c9d4e1b303d03703874f5406fe1f924e8dbf39dc1de98329f8450e1fa552671b9dbb8e216139f4c3502881dcf352eaf38b014f458c8a7dedf05f9e371bc0d9a280863023d8234805e211df73e70faf1faa6aaa081a7783f7a782fb4e8a55cd7f6951f17ea456471a15a934e765896e0d1707d35c84747c094129ee2109c420e2288c90d19052b4090147462bc845219f9e8194f9da2820cc51f6ca9218ea9a2026b2538b0803c16665f48a8c23c55ba8a43178e2f22deacaf6334199caa8f72c83ead47f7bd9c85efb2873db88e1bec855ac3b1dcccb8fddec90091ee8464cda2dc392c352751290fa830b5a033bd6da14dc894227889591bcaca45ffeef989f5657d1b76721a7372328105b9eec537ab5be8a6d11ea66ac8eb20786e3ee34bf530a33e0152662bdeb1264c5b967d8e05117752797f1f1f5a02518d074a53fd726dedd6346bf8a502d8abe64a2c34c752884cf203c3769b136b356e831530923e9f668879b8dc91887fa614ec4eb15f0eb578739a762da68e17a9bd58c663fdad82b5452566a821aca8d4d64f82ddd98cb62a14068558c7e4426eb973d728d8e89300313bd3b57f87eda94bc7ade937c7f8aa1882927f73fc1d4f1edcca1ea3970903c46162114ce772c2ee4f51c81311d8018138869af3313bf3f9defb11dee59d993dfdb4d2c42f029170425ce101a53c9730c98d83bcb37f261b48e836462fde36a6fd40901db6aafed91c9eed1e347294b80e92a19356397cf56417f2065a9451b4d87d5b1eaf0bf33dd36bfa828ea5a8bcf4d8c6fcec7bfdb2e7c2722ba57cb1f536bcf46c9548ee4621886cab0327148ce22336ad7b9389558c47d16b479128687cc1f1449192a516625c2ba2f884a58a296cdb252a24c7acf62665dc22d5b5d2e10f1f76a7fcfb697c7dcd02012d2b526002a1af26fcb972e70e51103719830fa9e6e41832cfc1d3461dd9d7a720dfee77905448d4d0ce45fe70bbaae09334f855e859c7f5c5b07bc75ea2c12ce11c7f8de0c8729e99fb813d0f7aa98402f23921a31f06e8890f03ec13fa6f09f85e53b0076130abf08f5796fc6468f60ec343ea9044c99f023aeed78e1be38d9d8cbd2286dbe6ce7e59e0f6bcea60af2d3888af0ebc5306adad12b868af7208917e1a2110e891a3fa9d80957423f2845440b908d4bf9db3a49b7d60d78092c5bcddd88d3e2ba58cbd1993fc116360c52a6b97d3527c4365e81a7c94adb92680c3fcab470908b951ab76435726cab7c37eab48e72259f3c2b91a77100756af2b57730454f6c704da5f3350503567d3b8f2a17f1c4b45be8499802fbf06e9c2e442efae4bafc000546290705edb09708047504687de1467c0240e64b7bf24a050e775d062a969bae4ae57c3644e1804ddba60d7afa59e16a4d998054f5b55d167d274a66a95f6fac44f09f6502a1d1ec1139489f98ce1b853b4a705c49b4dfdd8a38e485560412bc87c69ec48a47f59651408d96692df9043b6aff030a39e9b3bdb8708a234d80f698afe0d7fda71531311ff32b533b107d84dca8b1181d3348d1af006337cb49fac0786646b51389bdaf8ba2d8dfc4ebca4dcc7546136b907e034c8076060c30d4db4ee6c3fc663507ffebb939f7a3be06bf7da45bd9cc514c87ca13660c9c59edee3101fa6cfeed58208e23069eab1f64654311b786e58116e9fe9c8f5c42698bdc6dfd8d4dac751018b2ec418df31a109338c1c8fd0f7b8efb125c59c42889a8793b0fbc678101f8db89c753a04caf3370b014f2de400237309c542abfa3412ad89035c1c1bbc687d4f22b38fd2daf44d07b469b1d3502818f4919e675bcf501b71120e807c9a9e2f540a486f8140c7cd15a4c68b7524fbaa92c84912a1878e87a32824dec1e9af3e1c8f70df6058629bf10d9a47be50ca3fe588a02c5c84f06a21048c4e23e0415250a0be221b7e23cd2b0635640639b6970b8d2bc02062b040cd3273c8604f37c203745f8ceef81afd24effd90daacf954013350e504f29a66a0831463e28fe684cf17c38501fabdb8df1f0d8548028d0ddfcd2617d1703ac2d73da00ebdc1c843d18ac355b286702ceaa13a795449cef25373bc4770d100951129390a58ff558d12b31e74a7c66ee07ff9545aa5b9be6706489b03e18b337914da1f91b4c570931755dd0be6411878bdbd8fac7357864d6bddac8832d2056ad5b53eed93d0ae048ddd2b664544617ad267f8c04795fbc1ebdb0e3929a8912e53c216445b00884f21d891bd194d2d22251ac7ef11a6d9376607840682f9a3fd9e6c990b78af8fbca90329d6ef999dc8a1d092487701f553ebbbd2b2423c478e11e0879eb26b82a01fb3eb2735a16fad00484fd0aa25b1386309ef3d73cad932890f445740261a2fb65a6bcfdf2b3f12c571726f2e573f5637deb9a2f14a23f0cbeb53c261f54fc6fcbefadce97ceb29095cc08648b4bbcd2578a9a65b692eca395a48a50395d5fa9167eedb48f7d7b31ea4b183e87e1958b8eac9af05347c4c6b67a73303f15956ad07fab6537f98153a2accddce3270d2c6fbf4db2de80661cac088a708bbf80a39b0297d0eccdf920a7d5cf4ac1fed2a894c49dde6a02377e183c382a61010f3cd96307c0c7ab5b6b70850fb07682da3be1f6201f4b223367ec0b6b46a48d2d98cd425c615515c1e8a114d00e96af0225f214f2786b2a524a49767b0bcb5aacef0d1e296b6e90869e5c89dc949e913c7d5058dc971e78d10cd681522a880cec6a41b28574322b9c9e2a714ae20159c0d57ddd8c4c0c74580fea153c2b085dd264da72755d3c33186bcb2bee2af021ee3957a85c23f77f7b862f278c05699757f739c05ecd78d5739b58c37e61b2c915087924a563d352db8f25a5c4c85700565508363e97ec3c25e152693df70d7979a32a2bb09def87bc9406821d8e53893405f24cfcacbd296b60414463213660dbb201314f439c5501acef7c0e72307d08cfbda5388e9ad1c6818169ff2e0bdf1133c2cc59e7c2f112acab35daed1a22f103ff3c4a49b0a1a2b7fa0544983588d9df3518aef363a6e7791b717c69f679c5d7008e6436f0864f9210f78f4155c0308712a41df17498a96a45a64f172189acb840c606a91ac09b51791b617a60df676523f699fd56ba0fdae09273ee6fdd0a21e32b57f2164a2c547f8b9c612fd1314548d143c3516b074b57919c025a037389b0c949ba970e7d6042ca8266b8993df4132abc031cadd2ee6a6f5a11b703d074172581e2ba3b2e72448ac8044e3106dc17b90d134e0995348935c922535307c581012dc7beb8ad0193d640d5211af1a52d19b26fd7b072116a1013b8758e1793566a409dfb7cce9acf0e92065274ee90db7e7499f67226141822a31673eff2803138e357c33ed93a7bbc1959655ccfe3e2914352a993415c6b86ea76ce9650afdf411911ba6b757364c91225f52a75326f29bab8491aaeed06f6d7b2b380981aed75bbf416183c40cb10cdd518f7338fc0094f77f26a515c155949c7a80e8fca0f62db6e328317c02c78f9b87de0d75ac0bd1d6644161613c1014c96f8881d3999a8faad6ac1598a145ecb96cf3bbe125f54c617a3e32971f098bd8309aba2ada623632828435c1b86a745b08ef787daf349c54262b6d0747b5517cbcd962c9d9fb6cebd485eff458807496368f16507e4e714b2bb1d35ee831ff255c99d23c770aa62869ff003517632fa552cec3105ea04a7b0c01919cb73554739e8ec18ee444e6d639c4723b121b42ccdff9118edf520a26c6cffa10e25dc11ba0550302ebad8eff1218df35b3cf1c10d4fa2e45f0840c32949b49654c94b921d36a4159cb1727b68613d0a73eb18cbea3c13d6863c96583943d94386d5221219943ad6ab8a95c846fbc3c2363e0d3fe14101232d236963b54247a8619806a3fbd1b12e5390cf40bb45c32892811a0f88b617ea52c16a445056a21a1d0d1131c01080d09afed6870779a8d152c0ed0629552e4be780f7612b451b05c8177b6534ac99709f541b081168a9a94db448ced9c8e823b03e77410be720683f3ac40ff39920914f12b80341091d41ad53956d9e4b69d39837c11394f66a7fdc65e31bc184d18d06c958259cc5455390c80fde3b9a7bb743c40458556d6db5695ec26b7d351dc1761965c7433113ea5b3b7b1007ad8a341d41bf223e95ada871e28030d8870d83e8a0a8eb3b9e491bfb6bce3c0cdc78a23bd4c7c7138765cc2ff3c00335184fca90568f975d432c0058db419816ee5d6caf4d7f71ccab01aa5f2b5320bef6c66acd525dd0b0a0f9230f755788bad30d77b13bf2871b26535c02a88130323d469b12ea9b7f9fcc3e4a47d03e19bba35078f37c57004fff591bdf86f6d7b990f5dde86d16eaf89380e0fc75fd50cc5ffa140200b42cdb20204e32bd0894653ed5438c2b9db023359f1b3b84227c660e3d12321f74e23c45d0860f9a33352340455ad70354c638197ce0e2b07b9b348ad190e7ef670fb1cf11c2aaaf73b573b180db98e65949e6009f6d944c8e623005d168e4c34d5b00b6cfe48d4840896862e9dda1fff7236fcf9c207936539b9834a0c602a1d19148faa4a42d6d7e7ccd20805ac611803d2b3de0d6ed03176be670f75e88ffcdde348714d803ec1e8d93395f9a3837d18b26cd40cf813e96d9d670c210ed67d617382423f0a60dcf7eb0bd0ff7814527bb25a905c16c4a097d37c01c81fb16ab4e586eb82350217eb9aeb7056102d8755643148e0f7d46a291004c7df1f466f68dc45eafdbcbead8c680c99309be6a380045101ae0c0fe8759454e77cb930b5c3950ae85daa46c0f022c21493740c89b68505b781eee929862d916025a137ecfc8ae438c035aab9f9a84af1de8c3a8f0c55334d156f250b9d3944c62b39b4df81b0c4f7671c7a4149cc512cc9a0972975d936ae5f7f9566a0156661230d80a4e296e1737af851eeb7d495aef218ab755bbf7a41225265b0ce6ed20b4632f391f8e42e1ad0ac93f107426452d9344e0ba8d4970a1d5631aece246e35851027673577818b6284c905ba159507f0a14eb8d3570051fbdf00cb6383214561cef8c928e8582b27dd8b059a750df9e568740cc5a9caa77b249b00a5ef0eeda6134507b1a9f19c6fe2709a5d49c5a5a484e549f1c2e1bf166cca16437112dea3696936f4490c6b6bd9a7d6b1f53b6c1bb6a52328113e2a86681678b5ad640d3452dc4d2232fd10e7d27235e876634d13528817a21cbf84aca3d91634276a31b1aa01c467141ed38562c47f516cdc6bdccfbeea2bd0fc8886911163575ab7a5ea555b8878c9a4c6f91639c0cc94764a3200990cc5614f77d165c09b21150ecf1b0d819b534ec0d25522bed28cb2d5618cf8220887d7ea420a90f906843d1068391eb3c5982666b03a236300dc604ce9618ad774a54ab55d17355d05bb3123c460c261f390b864f8f3ab0f206e8afa40615e5904f0d4719c0e9a628f8cb83fde4690b751e609939a519c17cee0f8c39939305f5e83ac9d220385a9ac4e72ecf9fc50696250d625481218c5f55130769c83d85c3dc83e0ac0b445ee7bb589238696dc2fc2a12f41dac991dc1b0693001ec0250e2a192aba0a93e0d1e77bcde246a915bff1bfbefc05a511fab98d425055073c3b8b337211d83564b8fbb93351ea3dfe77f70d67426070611f470965d9f3c21ba1255de19e07c3b90ff04f34aa5468ed81573eee83ef05b6e45461783df38691a17ad01ea8703050a007b89e350d920bc796702ad234965c6cd3f04e01ef5872a1cb3a070964ebc4f9fd810c80cfe2b1414aa63c21f0ce4dfa5a36a195cbb3497db7ba6cd162463601b170a3a103259114871224fc078f746941ab0b5060d155e9946684a95ccba37d4f9e9a8c8dd3a8ea8f08b4928bfc0ebac520ec199e5193cf524a533b6acfc83b38400af369c815d3831a941f38b8a86480999b97159df94cc4a8e3579a0a3603d78513c919d6df2d059167597a24633a00214a115fad22b16a03cb5780bacbd4023960c431fadd214ad3d63152a76ac98315147ae924775087c7332f85564a2dd6c4a0c9b8e5a4ea04b5f68271634900eed27170e78496eb2d2ccaf22148200de507de429bf94fa9cef36485a11c8f9e33ef447b309447b1d889c5836e06127a688e6575688e47778a5ee38e1664725ac2d243d0d4f2015e2d31b6f2e9c7a442f73f887e9f7ccfc19ffb1b10df047815a791ad1caf6a957cc892a397e63b9f1ec2427167f2370a7b51d877eb3e18b9481a6fa7278c348bd88bc99f5f07303cbcba09d06a8ccfcedb94c23e5632d63d683a9d72e973684828efceb0fc9040fb7568eb1aea4719d93feed0b02b54652efa696ef98d8560135e5c5324cf641da60e06f1b2e29bd04f97bb4810eab6d2a8c2a0d0664ec5e81e6e95000fe4e894d805fccf811503e6097d5169360cd9b3d8f266d77fc04cf7bc35a355534b1c543331c0d9d99704fdbcf8b7c17440a60f7842a5f62a731aca2dd8682d2ebecc492ff74fd040f09261e6c69eaea70a01cde5b53fce31a9bf2a7380e80713be8989b7bd0c69c3089b68218b570b026191948b6e5cba7feffe0707f8e4723542771dd54c2509a1f0ee916f2b43a52e06faa0edc396a17bc7a0981526f5c58e9a03221ace1ae4e302a33c47e33d72658a96e2591d0c63c10ec0879ff0b2545e446ccfc7e460398b672c077f9c60b5e937f3d0eab5ec8b9114a7f740614f40c59089d19b17e400f2ff59120c17c335be6ce36ce6d701142b8786cba3e5745ac796aa167eaa1ac9e855678c9f856a41e440b9b2fdc671c53c382e3edea8afd10bc5d7c4b679c2f0267e47447a60709f26d53eabc2d9c7413b2ac4795d92660f3edc8db2587814ebf653f337621b71d48a438a1a52f16083fa9446351b2445cae8f949085edcd8304d90a628ea2b17372823d75fa57554d68d3737abae054a55f13d79191f6f25973dd4c092d9dfdf6cacf932879804c50a373db106c09138778db4d70455fd3c7fc5a5032d8105cb40b0cb2bdb5cdfb18b36d0a026ed81d5963d5b7e1ce820c6845c128d7862835d123370867ffc444eae70d695ddb3b5db7ba4ae1463868cd922818098401ddfa7c4537c6bc5d3c5aefd8a8c569c85a3eea46548f71723c1efe67f517a007bfd3da97f04e3c04def39cfc20f781d7c8d0305a322c2820b4af80d13047f9af446dc5e6dd4503edd4c76b09a310f6ac3f281aa3f089237603f2bf13265fcb1f9f2a93e1f7ce57782bada895ebb5ab77edabcf047229910fa9460d6a7a3656df94dafe927496a84429b4da25d03a52f733cb16f962c0bf5536257113dba2621f962bb661f23415ec5cf22031d0dd8cc6498853425bcfb1545d3e3b6a7076a15fd4a4495aa94fdd94219f152ad12ab3546b355fd2469535c41547a4c05998892120ade3c5bba7ea2ec26473cc948d0117a372b0f6bc59a58ad8713413b5c7fd86b909551422537f53de655c9941f4fc800e3fd9f9b062ac3f5677758362623b7e2778b83a9e59182f9c23a5473320f638d2bb320ff329b1d1b828897753a8540c035c9bbfc001fc322c6324f98c2792f620e3f0315a20c7c11e58346b810527c706eb6057b38ba4d419ca2473cb42b69f80242f3092c2f84392e9bdba2c017176ad5206ab0a9990a58e0d02c6e5ea50edc02c1994721e626f4e06cd03f8f2db59f3cba2f40e1e95df322aaef720535fbf51362862556d3cf4cc3d0e2690d8892da54e52a37ac5aefb91c76eacfec7b69354d92bbb51249a111ca58dbd1600a0ce5f9fd86efc7e3766ec221a03fa36e2cb6de37ea4d076b225151e36f7a9536553a1b6428d43361591175b572eef8de9eae8d927f806e5465acd0e168898dba18199909a91c96b23613eb79d96c90371be42dd74bb36f06831c53975f8967831ceb1654641d1e293dc49b6c8b0e679dcee7ee52c1b644944e4f087dec8c5c5cd27997dbf37f7643940454c81847b5ad193572166434727c6aceeb3dca2a001898c691f0065774597567ee2b39bb8686fdd2887c627614cb5ce9df2e7f43f1bad50de049bb5d290df9544a956c290769a5ad94ac1ef1db1ee0714bec59c3ad99f8295952e30a61db3508cbe8d2a7292e7186cdeee52c9d2996bea163290dc11614bfa216d58ca3ce6853f1772f378caae8565cc14b7f7e3221808f8316417a1c84010fe113814acaa516651944fddea5221742ba0816eec085d41ad4b1e9fbfd671f83bcc47a9b78a19a9749cc22d7e4bf6e619a0d5e040614fdf752743480ab25a13bee50011ee1e035462a19223ef3c521276323e1efff70a9f37acc69c1ec18e1ba74e63e8ac56f1a2c5f6cc2287add9c11ef4f7e0c35247d46428c3b23b3211fd8df7154a8d1d09bd050bf6e85722c2217e84e9d75940cce86b4d6d62511ae6b2a9af7e752cb04113979bdf2003f6cb575eb9cdcd4d2e6b5c98768cd2aa2321dbb7b508dac3f1a9af362211298e54108ca5dbc7447388cc268a1010d2cbae40640fb937d65557927fcba4ce2388376d95b93ff7d988d34c69531c1ddc969af4227e0187a142b0817851ecb4a9decf7a69b04fcf9f5a7ed40a0e738c2b45a196dc678a60923cc20f444a10f77715632c74373c5c7c0566948802dbad78995ae372bb9909efb615cad2e1ef140f2c1a15afb616a17db3e64ef07f06776cab33b57362f2853102d758c2d25d051bc990470edf97c8869cb2886e860cc73596130e1905e82168088e54f1450e65a125abe5a7afd6489296711c9c3e35b7a0831a23dde5c787e2c101b9e66bc734c71d1551eff6c298f151c91a23ee4c78838e48012ea19c5627ca4adb5ef0b98307f0436677eb1d0ebd96fbd15ec7989144ebdd4d258221d8ebb8edddeac278a62954034386529c8e2f80d752a30c53e1e63d120ef23b079cc519b3e02916a50a37e1292618b47ac7b0e81983a9f200aa7773ac502ef48598e41fd8bb0982a2bf7907c903ad765aa752f2dbbad340c0ed2f2612495586698066b7211b95314dc6adba2f3fe6e48c829d19658a83ed2cca0abfe5881fcb352c2d5a4020b888b4a9e18fbdb449c2f40b32356e6fcd4c92ef744f3bc0f95cfdab2a54e454f63a41100ae67f753b39843252cd8ff221e9980942a75d966946a2b7a268ddf69153abdcd0ae66082bffb5399cb666b7535c67d4c2809530a39b51b1d7a761cefc9ba19200061de2bb429da1b1d7fce6f1b0b4cf2aae421137f3a79791aa41fa93c70f75ec8c327779c394cce6c0493c65590b3ab55ea40b7963006139a8404e3a3c47ec7ea41d274705647d198024fb1c874e650e67e77194f2a537aea28d96d1d5f4eafd7677d6f4ab031380773be4842d550445050784c1d910a8a45ca5e3ec817ea6beedceaa14ca0cfd923370e297114cb1054b2a82352f412c9ad5e8ecc59f846797f5bd6a16dec1eaf39cae3470dfbc371191852396875c2d33b8f143d8ae1778985012fd66973313d08cd319f2f8233029cf4b5dc1b6088d705ecc45f0a0879763108032ca54a99f7e9b6eb56158b924fca7414adf9dd00d91015c789d5c29f35e00d6ead7efa074a74fc0333fcc0c2bf4f3ba3d60afcc0a2b2d755472813dd4af55d5337c417132d75d7616657dca7efa7913f1d89c141f797a4e31300c647acf9a0446864a5f868a67fa87a90f2b73237adccf6f544a7b9308af27960173efadc1df4dc134199bfc7bb359fc37d4397ebae6404d8b272c6af0f9bc9459b5a2b0dae9bc93db1b330d57dcbf421f28402dfa08e0a456c64672f9e713fdfd46905e4faa09877b1863043136626327a5e742cc0b29093919f9159b5a383d2d8c515055b75563bd49b281ce9ac8675ea8a36e07a542903ad1e4239083ce369f778ffe63a0357c455449c397e135025874f6c099aada8d754363af018779f072f9b23b1dda55579e5d16efdceab115f03c054b34e588c6376d53048763f96b21e24c1515c8cb0a72c09637c85ac805b06287881050aea752e527594c75788707907af7a8b9c3925c888a08773c00c832a96df730c69c771420cd54dbc83e7fbb1069ba86ca625e279df695c3ea214f9ae1a8dd8414b8e9e42692df84fb5c3aa4de428c9a60e9f8efc38c27af1cd39e3284c3ac70f07701c66789bad3b075173c3ba994451c83e3761d8d6936f48e7c2aa6f05609a060525ac94bd73158793efbadd086e8e98c0808dffca1422537c70688c84525590021ec60876239673354931f60b5a8eae939821f69b9289c3fca093edcf7fd55b060e57b2b02cdef3e0236d5a2fde2f6cbd104a148c449d292b99cc1afbcb70f77c2524b97ed5a304db10a1eddfe935048e8449fdb2210bf87dd69bf5a63a0eb53d533062bfccfba79dfce0f222b6a1ceffc617fef2880334f1f3241a09223ee3012e32b1f6ffcef1ad568ece0fce3569f6cf9696d1078d01a3bedc4bf7420243b703faeb87528160e5462b17075db83f53bacead30442bd2fb149b77ff816e4fd3e96674c085e5d790f160371aa1be38cab229d7a10822e15e32d2c476e2e8e832507876ba2f4e0436b4bc9e79b5896deace208f21239b7e67dc653ebda0d107ad8f0a3132e0753411e1a073c030da578a1447cc8ec212447c5d8256c405b2f1755d6103c175b6469bbd0bd32d0dd7c7e17c24216cb752c337bd9a13b67ba181009a72d5d20651b121769d457e470e751a572575c4a5297f9d60cad0b4f408e6c1487e2ddc1f31aa24729fd68a7cdfb9ad269d1caf818a6b11023b7adbfe05e225f468d58ee4600c11ea40fa1220818396de33d24bbde5d09a340c8e1c276230a74cde00e218c81335fe25fc6aec38bc0a27a539196226527ae8530be67cfeeb8c365c7f5c2685005ee3a95208e0e25aa6ec15358a4cbc7ec17d337b1a893f30e9c85286eff545e9c40afe815abaa788e4c3fd11dd917fecbd69813b2a00d991ef52883f17f79161e5617f346868a67a9e53a7dc8eb5df303b22d1b149f1af2aee0344228e46628787d2cbaf699499907c5eda0019664a133cd27b9268e41ffb94cabec9e1fea5a3d603f968a6573783fc6564ea4528db127670e01717212443b50da4e37b5de4511acc403ca60282ef5636b816436cb607d4f2dda2688b0f9dc2cebd3521c206936ba8e69e3732151e5d331bbbf75d029f8a9113da7cbff4988ddc29292afbcc3fcd3c733c480bae4b0432aca9923a295df83f14941570ce9d579b083f0c0b6cb98c7a3d0da7e012e9d7cba9d333cd794c82c04716794a43a4ffb11efb93283a85e903cc9a8f6f547313b56922b5e0613b4a480a0e4ef27bf2432844fd058504b424ffea5fa7f4bc10b9ab909d14edbb999981c3b71e854295745979465e068a06af28fe6c21fbf6bc35b5f6473b076e5e203a57b3fd6be2ef0dd22d9697146a4aad422c9f6d6134852ad8464f32331f8db8dc0dce839f93648f6e7621e775064cc7adf394033b78751388d7d1739cc13accb3f87b03a8b15ced82bbd6339485f20a6b8a3eb629ebc32a96341e52643cb456a41308c8691df54e358b41f1becc6b4c1c94d979253b382ac2a32f3529539acdbc950694b01039446228995b9db4d888221ef6847e05714fe892a99595eba13f599fa2bd26fe7709e15cc51f3c5460cb3ea68a01fa4be64cc627f04c520384dcc7f3d489544231e8e1b93ea12d537ef1acd010ed3fa880f6bcd0cba26e5b44ba6d8644a718a48d914a6b5984754a6a4782723cbde442e37f563a7f48ea0e96acba7aa4a880010f01c258488f6faeda1ea47f0cd196d619e2432f1241b82b77b6839b81c6518092e41e1a8ae0e403843d02151c3ba5c80085931a93786704cad33942350b1d0670109ec03bd5551cc9767ecff7dc055716965db6cbfbd0fc10d094241b98680ba2c305271b0a27bc0569dbf733ac98a20d9e7e42835bc4da05603b3aa5dcffdbea0ccf0eadcfd7abf0e0cf42795f5d2f6c2546f0a2c12141fe19775cdb1c8b758d59cb764e011f3d0e365610fef3b3effa7755c34b854905e1b1c6d98389138ea56e2244d779eea56b124030edcebbd197ebdf145a4f4bd819630236cfd5a0b2e7779770a981d2076040329b23291379630683dbda37b4c88df4393ef27dbadd1affdf0ce7ec9a088c49799c3080b200429570430e4cc358bb22b0aa96549e5b37d1fdad1af4b473c673ae30dba5d83da653212bd82c24fae307c5147a15817498b2cbf5ccc8501c329df3728142032c8240687f471ce4f5b0a7652402bcd363c27302c0f0e71e34300cd0d3c3f7c52086cbef27305919cecd3a8e63604bde1683dc8366ae0800a90c9334edf58d44d5fca73aefa22222434d0e54b42322d0ff4b7cb349633fca6bf657f5d447ad8d88e2f69625bfbfcbdadfdd16a9f84bba1fb1f2eeee378bf75f823793ed1524003ec4981571149e14f0002c9540b82315617416d3d3c753ffcbf16d1201c6dd4e2aee044f56de03ad5a1a323a16f98207703b620d7a2e833dc71b2a3e8d85966c69fb00d5c2ea9f85970ee7360bc2f72141d3bc375478deac24f500779006e7e9b68493b2fe7ccc8c1f68503f11c0901a75f0b535282a8924ad306f1029740e205c80f9a061a21d572216702abe1d10105d1704adad3d96b09722182c25952b48a963c6bdb522da53030008409d644607eac373c126a3cc0868500b41d2c5136fb147ee86e9e18504f803b3df5bd74944b527c581c003eaebff36bdb9e029e4b78aeaba9830a486a4c23464f5de075f504aa749444902e62be651a8c8c70ee5d53e0a24181c7b9f8740863d0018c0212a8c034e4e538706be532bf0988013a4390a076ae87662af24a649a94a4099086cba361288bffa6a5196f2dd2150a0f8c15da5cc36cd8a4b68482785cacace7330f1bf310f4e2a5c09daad65e3c9e8a8a07d80702724aa59fdf66583b4546374bd533b714dfa5d325d24b18af6a09516686cf9a24585ba5334c7b0c894290e6b998a55065a701e32eeff77a477c5c39f9d9d18284b3cd7d0431e068006ba39c21faadcb0a6c1979bfb65839d4fc33730e8694259161b9f520d094032204c61766bce3edc00948d5a06c21e6c4d1ce55660dc630f2bf27aee3468404222d9744a9ba8b915b1c16505fe704135e1b661e6b45f4706f68049a798cf6972dc068671b6d68d9a11ee5e6a2b2da6a2d8195710413544c74abab9b2d47ea0db00ed566262cbefecc40bdf40fdf81c874f933c3b5147d088611c8518e97daeb8d5e98cee6e2da9147befcfdb6d5da8696f34e86e2e425ccdf3b25445bc808ae796f34693bdf98ae2fc55dd92c9adb4994785ddf52001d0f781ad170b33fd871a286c261d77eb1f1f5f9eb4ecd80a4d7e6b2621c16e9c1e0d1f888f0ae37be9c15fb8c1f7e25f1b5707119b0c715c50814145cc3f0a5cf85b98d59d79cbc6b3621d7db2735af2d6b7912722aaabe5c5abff19eac601261663d4f1d461d5a09aa3c069e3985e07870de7f13812e885bb062857219d3196b12ead18921612ac9d729da6f3944bc847b82a92e645e4be94c0c73191de9fe0730d835a68487fae920ea71172263ec0f299c5ecc67dc45575c681d871a0c1d6c59ceae77bb0c9812fd33e9060eb7639934a9e3c8be70590c24e853d73a0aaf9cc8cc2cbab38374859f807dd50509b01b0317f75185aa08ca6b86df69e2dfbc46e0a76483698d650ef3c3d2ea2e6c6d69cda49a2e07d84e5e0f3e4828ff5d2d4b3ed42039e554f702649ab0dca9c223d8c35df2b4e89fcf27cc67e6ee598ffee9f2341e99cc07433eee4db3e56a44c639baef00a6a84850ecf0aa783ffce73d0ce7c06c061299f929d02151e9f8d63d26bbf2c7f542165ef19e876e37f0d8d1f167c531c95e5c9285847b5d0b3894d75d6a378859b9f2596139b824ad6d5add27ff539969c92a3d24fdc1481113d7627a90f9c6bd2591703c0ecd1f15ab631e5a53b15848ea0b3d087584e3551a4ea58d0b08eff90df50fa6ca5560762fed23130aea97fea5be9885c00d2e7a1dd34e0ccc882f75d85d8a664556e56269b18365ad5e6091450fd3e43aadcd4c0d8af4e459c01f47badf539a0699777e7ab802e31788bb3b08ab97c8450f05a50f977969a276dc31c63ba0eb91fe3558327225967f0293f05054bc0ab1c4c92669941e372c0d5662697433351ffcdf2d1317476aedc296a72aa496645c5cb08eaf81e05cee8aa3f4df8b1a6cb0023fb35f77b4d9a6cf2e72221585c11b027b27b87a0bcae4ba87337f5a5604d0b4d5cbff6c5a1db325ed3fb143eae6ce194954a64e3c0f33adc2848cc3c4e212031bb95526dfb1422f5257b49c95c5f93cf923aef5e0cf09aab1487f9ce742139f99601efeb696112a7417f301c390cfa82be550aba7727f303a93bab1d73f2341a920fc89721aad8e9fad099ae10afd624ac55141a58d5d8011157b5ba92ad56807a4b93d88c9af9230ecaef20734cfb67214bf2181fdbb2406f46c4f159fe2d6bb1a1912bec2a6f2ddd6858ada309b65ee30ff7757e5459d35862a5ccea086320c1fa80fed0a1ca75f5eb57f299d449bfcd3067f4a9655f25db0f35f10040ca00e73338006f1842ec1c26cd279866f0f64aaadc8f30b3abe01a585e8202ba2c5f0a14b8c410b36c6273026f8429ffe97a53e7ef3c3fda92c42bc698e09089d97d8e35dbb5095883c7ff0cb55bdc83b14e54f40628f9eb06ea94d21d2c8b686a3ac031967c845e4eceedf7fa2fb40a8e4fcf48c98bc40440f239494ccb3859ead4685e6802819812fbc2c99d5e1689d09fe77d08c8c1990b39e1cad52685dabbb5c5aad63d3386cab88fd6b90bb7bac587c4fabb1f6719db715a8776e48d36a58f07041cf2e024384dc3e9e8dc2f8a3c306d955a9897fd7c11e68dfb3d85b823dd074cc627f239cd31e6a17c7c1b74be7eaf265d718e35baf5dd4069d2049083b396828c6cbb830f7167da17be2528b4f45612aae4d55fa1d1107807647a658d4896d6159237d6a4276569509c4ef3b525d03b5e46ccc3b639db21314860f5c7206e37a840f98802284892209ce430ccef53b2c56143172bfaf0b1a68e808908585ea5d53c25c2072e27e1bf64b145cc46bcb4e43a43184bf8dfd98c443f8539c932024da3f704d874d0a872b81cfd70009be24367598a659a33fe58963af77af1b47bbe4e8de703dcab2a8e968c15eacb08d08c2d860d32f3b7174b418062c8a8f6e5ca4fe2367a175f21051733fad91ea7c19b1f324db54b5dec80b3e7b23eb84ab71088177dfc4ecf5730e78f8406c928d0085ffe06e8447cfdd832cd1078f0d19b8f608344c789908fe2c2ad5bb609b0af29b87f8713004bbc07d090f25fa6ba75cdcf490712520dd9ec99f6d7ae79b1a4ab54e69fb61003c8a58dae8ed3366c841e1dd0a08fdfe47423538e1a32c62d4d5f03da59b6a11d7f6dbacf956e9b50792ce6fae8ff9204a26bcab53d87d36fab885031d8df8ebbd8107e4cfa1cc3a4e615bea2a2e6d0ec503c326480620847e10edd83883a4e16b064e2e2dda1d420d37dca596f989fe058e7a9a16c49dfe4ab02c109b2f1f6c36926c178dd728d87a41be66de0e1c0c1095e90aec3e802a0cbdee2d59b0207409493c1a96694ec15d359ac8e2e032859d4319e41553758286368dc06153fc5380f9c95731e9669bee586e0a2a415cd5496ea211593216aaa70d8a0942a968668e08319335cf4512a430e4c75c185cb294787f81088ef350e00b407dbf77415d493b2e1a2ed429a68596523c186152ed276fb92f010b9f4e788c82401954a9040ac74f989172095c3a8836a1d93be7f2f0c367dac2753d47bd1ea63289b2a528e3b8bdc80a277ee4f6d58c4c8a99de4521761e6c97478edb0ae8db06295231b3c37375fb471c565a301f1ca77083a69b4755ce67282fe639aef7db2e7edbf1293a4f2f8578b289c0bf931c37954d826ecc7e1df63fadd8a6f25851739963f120cb28890c0cbc56086285f8368c8b646bdbd4ba4ccd6ffa0d13394c2451f4e04181ba2be68da784bcb2d50a2353001438ca235407d6a9201e1a9887be296d44d26363d70eb7643ed4f7920f956e6950e869401210c2789b9eb3353f4e2f67e1069ce516a2cda111bc9b3ea9b60af809d932c5622103ede20f634ed0dd6db3be47f38856277a74c457da030357313f218e1ee4becb38747b3d1fa4135520280a7e5df2b34d43695179a485820116559b8209c953eaa7d07b9136e597d5ced59be0d83d6afed47eca031c157f220d6febceca633a7973ec322752988fb6db084bf36e0a025f9aef5d24beaeda03cb9954299450f3e7e1d04592f1957f5740ce940ddeeadbf114ec54ff569baabb2d12169fb8a852315c68f0d7f40f983534c623ac3ce0bb9262d40e4ad120f61b122f686e2851c10d59c59a2bd485ff1dd872b172bd736f974861b3e842ea994792b05a3b70240f56efda2e686774f4640a694630ba149a5d8b5daa3eeafe985ed999faa9880315ef5ba15b90880596bd7395b1a9d7f3e1f428f6feef9ff605e9abf69e48d452b1c18a1b73d0b8cf0cc6b2cf267f9fc7fb0d7e4110a6c8f656a68d1b713b40d8606f5057029b6cecf9949df2991e800450a02ee229700fd93adf38ea44c793cd2929247b2f92e2f4d0136f930313d521b6fa3185a6b2e12cdab53d6eda9febde50a1ebe92278b8a0326cf9efaa2047bbbc72e14438c3af0377b2cbd5b36e9da69624e8a146f8add316a467f1079d83a3d44ac0868cfe1375bcb588fa46658c28bd81569173dc46c7e28a9ef1ab6dd00c521e83a029823e779f14ef818d6b45ae6adf3cf04401d5a8c52345fa29cb8b1706d3c14c81598e9db1f2dfc90cd237673a9e02e59a3211150e25b5bad75a1f30b17637f6e38b23de6af1158ee2e3a317c67090cad7f3313c3aa2c1516dfa556573a2e04c64598809ea67bb54050a21ea6440e31c6cd028facd78147a2d7fb01fe05dda560dad74b1128aaacc875b1a9d37e3811e53401459ce997b10888e551c8cb88a1d04919d645d1dc6433a7cd18847bf551ab68679f5542957993bf2ab8bca4313b19d8a4860b54b2b93e68274d79fdebb9d9e32e35bae079eaaafeb05425a5071ad77c47cca4fd9ca4d4c72f0c6ca4f2765d452c930a230e40aa97a42a2acb8492c02226417715209034bb4092dafb1f206502adf63c02f08df51f83083f131befad2138b60469f3ad3510e2864bd5643a2427bc3f783c844ddbacebd73427430c00251b5c9ead75239454626d7db4addbf0e136acb28201aaf3f8731448ad59c262576c82659e8676a5107bab09cf0da6b0a536280387546f6a0526132e0db582286f9a83076322608f4d8bec94546b203fc0581f94379dcdeb42a9384eef8708861c503285024a728b132ecf7b6ae47cd1e866322c42f1e08b037a49c30a8bfc1f7af4ed87aef77ca050825d36c3391d4794dab2179271b3975ce6098c54069c74fa35814246a943e13024e84b1a1b68e1f422b109cab7b29af34b189be4b0be2649052d701ed7440d32a9e59b339eeb8ac2ec4cbfcc1a2564af823d17cc482af8d7097382459cd14678cbc9c2d51fba31d8d57983c6161949d5d66ed439389813a9d6ad1aea06a2ca7d1d637f5db0e22b825324ccc59dece9c5d752e1257a6634ba8ff0de94dc7df0f05be5ec3bf940d458c3ad56dcfa1110fd2d508c651d9db6d45aaaa7662a292258cfb277d40ca46cb44cf93e10a07ee2d66babe552365762b0b419213679ca101a7b0824d9890423878b5f8c94b65a8e3dbf7e755ae092f7e4b74bae28221197a333c937a203856f15c8037d61730f3519d856a339d001dc311d08fdc83a8f0fb170df6e5951c8061b74594ad238d2161b3ccd71df512c19b493c9c71e66d2e1412e55486b6fabd6a5c9577b352851a4f363230e0547e6c4d59597af8167349cd8e05dab48146b3334609c70dd6debaaf53cfa3cd5232de0003dcc53ce31e12a8ea74366d8c16f1326c886ac69664386d1d0868c64561bb2e22be481127e3a14c6569ea92a1f32af52be0217d52f4661b8465f0841cdd16e611b5482f2d6d2f7e4d00caa1b0168a501db551084af4b9f372c10b741f4a2cc7b52a5636fcbf134a6d1fc2984a0881e536fc2cf90bfa576001a398f7037f1c522721b6444c206b4f74e24732b8018ca4982065591046ad21b61738263c837bd4f307e27a82c04f1f9c941c47151ac8267a8023dfc452cc92e8e61f5034b5ccb5c310a402b910bcc16b9515bf0cc423c482ca8985d7d82f582bd192d64c8c3f36c61ec98d1400dd1d8f2004e25f2a56690bb30324445fcd41e03e6d2bded16b5e90476c66df8bcad67945827d89165513ccfe637a2f2f6ec5f6689f39b3d4517459f4b2ea114267dcbaf8e78a622101ae0a88a939f19dadd7a4807d32c3210df383a25bebaa2583e957792a2e4fcda564e86b7ed3979a808f2bb0f28694f478def40346988dbbfaeedf94439305c3e8e9642b2b6bbefc4e63b58805783ad9b580555f6cc5fc87c31c83caa7adc63a79c9253064dae4b2c3264b13be455ba3adc91352f32b2554d4418f94689ab9ffa3397536cc50f284e80833ccc6b0b1329ef2ad0384bf3e7e1fbaf3dfcfddb157f745b4e0a9357803e7ebae1cb932b8c1dedeaae5d460317f03da0a9389fac945ead1d36e691b5e689870d615bc3224e35e601f7abd7a9b34319995bc8a4f1cacb7bf0843bbc395eb751697a96b34478831b45e3ba6c70e747940d397170d4885850371ee779119ebca1f777d66d8acce3da7d9c700c62de872b3dbd11084b6b0fd3f28701d9e85969fa743c2577fc55486793455b8f83b3200cf38bd5f767ab931bcd3f2bf62c9207e214c5fa31ef4f712f53cc057e84d3bcbae733fa635a47cf593e56237fe9843faa980af2c6df976daa3f6c731f761f985203597cee09b7ce86b0ec42a98d2a01d41e935a9469c257e80a318bac2edfeaa1fe314905f4a8030ad10a925820d03a4e070f470cf6441978ce0061291d62cd0b043060d28d7c9ef31c7c60edb7977f581038dbfa6954361b179d4f83602e40bbee081b180254438fac6147c6685a1eec214f2e64bd1385dea390b6f7de5bca2da54c52065a0910091809dafffae7057ba0a3152978d2f17316502c63dc31022cf4fcf9f3044b628440cf3356f204bd5525ccf49c7fc14043cfc74a2c8561869e33ce982043cf3792421217607057de4d2ede82a787ddf18e2f58a5439f3aaae36f1948e185f9fa3e86f94abdc35a2b772eb4ff9eaf70ee7890241208888118d6bfe1b5370cc33338443776905f4869613114f249eed7df5156b5b87fa1eb09e2a4a82df7983059b1f624f940954739af899e2f2593c874fdf6e004c58a08bac061cd125794c01c808828485b867802c10be0d0a2cc60a71e39a5a69a7a45133c441a4429a3b360d8a0fd7f9c56bf6a3af304573569e9862d87a6898cde5166b96842c38d26186c4d5edc702f873b8ca3e35213154d4be81d6a317a01a9eb47262db1addb053205f6af4b38cfba735927d35b6dd56ab5a17eadb022307d49209ac6dd739cc194220345db1813c66a1923c6d620368c024ec88438020a24941003b45b5f860842fbff17233070822a6040c41059408183ac878e4b5ee2f0420649d232d39b9ce9086f67d25ffc15c500f98f6f97e9ed21c192a04ee5cbbcc888c98f1c698c5f29e34a4f30df914f65e62bbafca23133e6f4c4c43446ba7b931b35791193c7664e57c62895c1227f32bda21b311dcd8c64b248e9e94a19a431464d723b9374a632364a17599fd0f6376fbfed87ac967f2938249fb4cc5bfacfdcd9d1522f49f1e5de7ce08e59f4f72ad5c7ef5adf0153f050d3f11beff87d6b4e928d78a8ed683b9280107f77b071f4dc9f9e5fe36bf533e75e0e30e6915739c69d379282bb76b4f634fa483d59b00220acd0f3e9cef71c8031eecc25f827f729d950b4678fa0fe533dce4f90be056f1eb29a67be0a1cb29a6e19a6fe84b81f926b74f733c78fdf446d03de14f84d621607e3a1fc2dc3d4f767f6314356df21abefa76ea064fef609cd9761ea1b99bc286bba8c316dced8620415359841e5061b8517322eb6a0220d1a65d8acb10110a110372842aac19a2f40c052b003154c4ba801476cca86456c08560d811735a67b09b3c38e5b354b6d7704972d0cb6d171c98b1448e0948e4b5e96d01b6b7aad911492ecc0c20b117a877426bbf152f1d5bab2b5c3be674f65bd0c6183a75af2705679b8059ea23916e0abe392971cf4f628d0ed8109f154dea6e3929798de2c59181a23adb5d2e9458f8773b624a5d3526badf5c6b09032a3153f2d2b0fc368697475338bc5fa11b23c2f58c5c298b6c6e86274554dbb744a3136d9762d32ed2ea34ed4893ac9e6ebde1966726ad27e2fbeff6188449d9034a4f9baf70a56d21ec3a2fdb5d87c59ab55a7f9b2b656d97cd93bab48f36535a71516ac64eb953b069759694fd7e93a5da7eb74efdd2ed26f17090929cae2dcf20ef71683ddd88ddd98939393934c2693215d24a4b7b1f9da6e2ca61f48cbfbd26d8b79e8aeb8c95254743e72884c2c10b3e80da58a26318bf66de72091399ff634e7734e9f5e355da766fda6afb69a553b58f5138beda6af05b52119d7acd1feba067937bd5ae5cc9a5fff4ed3a6e7fd646e4f42fbdf2f683e12775342bbfd905489744589ce26a731655c36639251cb53acc86842b1f2fb40cf6ccdfb7bce2f0b2cefbdf7d6392916d98ca922d54b29a573de8f1ede2b2fecde278fcddbe434a68c53199d51264ae9f7b8f75e2a69934d518c59b66b8379acc0df09493861dbaecfa6ddf952bbfe99da6e322975310e4606587e1ae9cdd975f2fb1e77d118a2502f3dfc7ddd36a5f7f1fbd4cbcce4fbef53a8efb70fe565cafaab9970c4ff0f6f63f31f186103b2fe8d00a38bacbd71de6315f7def7cde9cdf73c4f6219f1dce93c6efbb48f0ec69d5c8cbb521f7f686792fe05f4260fdd994ae04c5a496f67aa3680b153805609b44bd8272c162bb35aeccc72f190c943b75fc034d92b6396b0e14a1057b4ffc6244517598f557152eab436d1669cf3c9c74e937ac803db46bf20ef7ba6acf6765e6ae3e2b7501f5f7edfa7c01f1e3aea0b3dec68b4823b9697c5748f9187fb1f8fdcf6940be232f510b4825ffbae604d6a59e5a115fcf383223018fa4e14acace3e107456047b915d345d64639a181b793f1f7320ec69dc464307a3b19ed5f67dacc070e954b65f2d0ebcc43ff50092cdfc9b84b8bbbb4ffa277f53217a987d3e23bfe5c98be34817112f31c9970a6399987fea933b0fccdc990b4bf87345f28997745bba7a4dd9f93cd172a76f1eac3964cfb7bb1f9fa9c9cbc2227cfc8e948fb774ef3f5c9e68eff1da3fda37f27f3bf33cca4fd3ba4f9faee15ac8445fb7bb2d87c795e93c774a4dd48bbd715c91c2543c5260cd66a85e1ff44c5262a365131fa439d9c9c9c6432990c090909e98b7db12ff6c5b47f03de73f29c3ca7e939698f15e584bf4c5adfddbe7f434117356d8d61f71b1187fa328d3c5dc701bdbd0cbb8edbb64c2b783d1f45fe74a4e34f305525c678efbdf78787f12fbdf56af7e66d6d0fd5d5a1de1ad6743aade6394a9f30f22891e608944cd39433d33891a68d1b3520d0e166166046044f2f400204559238401b4a3138c81c2131454d951b354c50c9824b136d5861a3045bce6862cc0c62d006136fa49122a5258d16a8fac3ea572aa59553c705cdd30d4ac8d65041c59738c6a0c2ca137144d902884bc4aafa0045972b96e0a1862fac8040031770c18229045fc2a0a1e2d184d1be54a7a8c01b812d63c2b18ac3871b9b3360c0f183ea0d1bb8c301850d1c59c0218607471a374c9d84c30a4aa281061642e440022baed0208a119b128233669c40093364a05283538d5677d5ea02c6c700a30b1b2b27d419ae32c325470c66b07d2146cc8c0b18333801105078c1218d356f446941980d099bda039a0f785f6e1c2af080ce35d674c1c28a33639af0024a15613851023262d4d00414606e1c62b82a258e373ce96e8da49064f5ab1b1d564ea915442d2d1eba2395193d30219ecaf3424b14676eb089801b656851461955886164c21561a401c6165600610232506cac2a0f0ec576a6053a54cb8f91948e4b5d54f0c4024d62a0f40194d22942162c7fb7f40fd64f6bad55516aa7101ded4b4b3f7e4ab817541d4e357b39cf7aa8b75f90951d71e5e18bfa68a5e88176fc8f8351bf6491cb1377a96268f3f1a34d0c5ad56159e18f568fbf767c7c181ae0ae1c1fff01eebaf9f831b84bf5f19bb80be7e35b400806b1aa090ee8610ba8c0eb3db901a94d0674ea6568833fdae054ea05df417d81bdfb791e0bb0aabeb081307c411608ac4375802f7c3c60d6fc8fe1fd7861b0f7de7d2f0c1ebe065f70c17b4154f9b64537bd68a5e881b88f8feb476b7fbbf6a3be4f9caad081ae915ba95a80e7df7fe215e0148286d90cf407da2d8ac270427ba006060d5a98d14afe2e79bbc26ba01525790609a4e42b6865499ec181943c05adac906798404a66de7e45c74f9241f040d14df0bc7d091d3de6a1db4051c14160818d008eb31dc0c889a46ba703699b9ac6e5ed7f5fe6edef6fb7b9e948026f07e32e035d8b87977b47e32ed7f51d8cbf3a592de3ae222cd4c88bde3e4657544c0b35cce8ed66b45043a6f78c4d1b749d5174dd12c7137552d1f52f3741c9715ccc3ef3b0fa875ef0762ebad61c24fe928bbbb4afef5fbcc95df6ef77f153019c010a90e759fb9eb3f2650f24e1245cdf7bff9ff94402f265b6e2fdcff4c024cb7150f4e6b87750d3f2b79550b483da6f2093a10cd821abad7d3d6dcc5d5ee4477ea5e6fa29f0c61d7f1488e38e073a185d1fa41a0caebfaa1febdffa3a96f044a2375ecaeeb060c85261cf53e968698385458c7f29e512a64b0890c082044c18e0065684f8c01645557801aa24404117346cf980374bcbd8d272e98c10da4d034519377429cd174f5e687f8a552afa29f898277cd0c19a1f288185b84b3e8c15fa8b02fd78a3072bf4d21b66dc484f45b3ca1535cdb981194fc5351d89da498c74e8c990d5fe5286a93d6ffa50a674d2f9778e81c0df122633cf9f40600ac5e50addc7958e50709c519942ebe838a382a4af87573aab4b3f29c170e80250344bfe0f2dc19f1fb549ef04736e8c3feb103a7e747bed3b2731c6af31339179c8e6cdfdcc4372cd548132994f33d5f170d3d7b28e06640a6c9f32a1afcdd79e097d4bb92dcf3c64f5cabaf64ce84b7f979321abe7123af3ede105d8e59c32473ed552c6d471c04117589a80066f8a753cbc3947d5f287f9bf7fb8e58997c5d331c650b2e2f8183b392b65b98bdb3e7aef2d8129dd401ac3aedbba958e6aaee08da5285780b1850e67d020c011465da678230b188c918226b4287a5423cc701d1724f0b84801126ab248810eab6ef52b379a564e9c957ba7b8d14523811b4b493abcc29f8e4b6eb040ef906905115c451e475a451fa7de6a157d9c6eaa95906b51cb2f484aa1f9f32f93f9dacdd1ce396bfd822aadde25338537eba41b26f098b4263cac6af5c0a2745b0d2a38214595347ec892c31917a4a011031dbe8461021a82f88e5855a41e99755c72a3c8cc13140048026f4b291d97be60f15106c7f7745cfab2441c68663ddc60d6c31a65cc7a689acd7ac07265d64395590f51663dd83093626626458d9994a69994d94c8a1533292b9849499ae9c0349372058592728a60524aa92a877ed59bfef198d7744ee43bb1177ba81afa11863aee1a62f1fc8c5c48e1a42b381423cff65ac83337d6f2d659591bedb7d72cddb4fa3f5e87e8365073b2fd93a9b7cca4fed5b4cec7aa7bad0c536b79d73c64b50a5c3efd4ede8f9167ebec094470fa9e408c3c92462da5bce04a65b19cc0508c3c3c9e877ea3b5916f2398538bd095081dbf9aeb0874ad72b504ab08741dc282f59dc87f327590cc43566726f46f7d19661eb2324c33548cfcfdc3d90f487adf4d312b94cd7c50f22be7474d295d22bf66a7fb48d4324c2d9f06aafa61068dcf6babef4ae9cff92ca4ccc0f2672ba506963f5bb0b0f5e1eaf1ea524a351f3bec4969e4ae08cdb80d1ec5dd5d8c3badd3dddd9f05adfdb7247d4787216807c1a97b6de2d3571d88a2e9bb7f6a0d37e33e72c0f23d07899cf16e51722aba0a4a0d8e3c5349042fefe3bf4fef65f5fec7b5098a00059eda7373ce79bf9343f293461b28a95c0f05d8bb964aa3cf04586584b1a4e23b958dcfeb988b6920a5b660ad1ed8184b460b24289346068b0f1309a992294208171a818c9289f2832cc248a88823c76bb42184101157ba355baab0b618d1d2d4a3c197d62081f6a77e2fa5d2094d9750a3e91b71d7d5f45348e2c20b346a4a29a519fb441986472ff4fe1144fb5facc692f65f19a1fddf9764c0a44614eddea2f2dec614cf35a63b6da9717efddafda9d31be3a512cf977c98874e427a3c9c9f52ea49925ecd2adff157c92b6230d148e948430d182be44c97e30b8a859a996a02b1b53c89fdae745c22830a324ce0441759db46e90334b88cbb3a982ffbd3cdb85359e960d58c8baf74669e4f391f470a2c1f4709cbc7c982e577c0fefd0e24d5ef80f6db772004a6ba0321b0ebf864c4745c1aa3cc4bc7a531a2d0b2cc7cc9d92cf2cc2f81091c3d3c42fab0f52367393487e69c0178cfbd0bde734f9fcb3324d1ec02f75d9e81cb39b4fb193cefb9870274bd19674869cea829010c8c6000259604126a38f104155888019a506ee8218d152c29cd5c60051010142c81822cbc60e28b2320960f587bfbd5eb4008ace958020a300b120d2c5f7e3903d07e7b17b4df720efd0854b30bf66fcea13906200b3895f1d87c2f9a2fcbcc974ff32da88135c0f26d94a6774a9dfc8b29fd5062d54d4bc7ef71a655e386610bfe600fe74b16aa22d0cf7d99ec47f6137de22cd3b30496bf7770aaea86ca48e79c6428bd59aad2c05286dad3ac812aacbad93ee59d2fe3ef39b34499663267adb55aa1239dd1eb2229ad9abd1bd7a540d3760eb07d4854da1ed9db513de9474d9b5fd0dc26cd94bafec008efa3c2deab7d484094d761c18407e2c41dfa1d48b55a2bce7c1c3dbf43a5eec65933342502362777330c6400a8676a73540d5229faf8f8f8f8449f0b024e7cdd596d2e09276469daa2e3efc0228fff8f9ba0c455a99aa8886887c520f175dfb33cf21d8f5768bff2e88322bc285f51ee6c498403e44b1ec91dfff87208f99245534a1268bfeed193b07c58962aec872466b99452242f57cf145b9cde3974fc707a7cc9a3994d60016c5aed6103702013a200b105b03c9af248d54453242a0d14a3165ee818c3c8a229ad42d397300d5667d462e4a1124a964a9aa3b848737dacc1dbd34b5d7000400d38fe9547a6981a036c755c1a438935c6954b63bc38cc1abd574f17a76ec7d91b2dff5e57b560647ea85fca4c7bc1d0278d29caf4e2e43b515f2f637c27ea8a6f4be6175f0f7b31a3ad79958c640be619f6c5e8de2dccd1d17df7ed15f405cbdc89fabe7f41374769e37ff50d63642d07b21e7bf7e255d57109cc18bd5fe65191d9195f2ddf99b1e02ecd3b2ddfa7e0d043d984a56d6679d8748591969b9a2b74b820c09e8e4b56a8d1f2b51f30a7e39215663817584183788f80719a3b516b17d4f11df9958ae003f678f1155c68aae3121820f45ed129a4ebf88f1e774530465588f223488bdc888c2eb24ee001ffffff4a156ffdaddbde73e4781c7048ea1c9d0d7a7a4ca22963a69b6378f880f7535dc1f953f7c0721c070c0ae7998e668e929b5ffdeaa6de804e82c21b473dcedf645645e526f9c5c39aa38732bc5f4339d25df45105ded3e8042938e7b5aa71e6ebe7cefc09c2cdaf6e7e957384a8bec931f2e4448df3db8f74ba1b5007549d20027c73138493551ee264549338a6fa6801a6bfa79151cecf9f54dc75f3f3e7d1ea77bc24d20cfd2595e6cec4517ad60d381d8babfea6db015224d46fa9e45f908ef76f2868c70b49bdcae1c1c10b499df33fee47ee8a3bc01f0fe74b247984bb76fc7c79c55d3a7ebe944fb88b839f3c1e498e0a9989c6c1015921073c563b401828a4e6d714c7ab389287f371b21fbd2a6fefc70b2cf047ab0726043492c23db259cb3f3ca4a0d7827da8e32e241d55bac8eaee7cd990443ff5d13506933acc7514d45e769a77bd97e0d4184c427d77352d9f7027bf2393071c787ba2bfafe0f6b65401f554a39f0af62df800b0011fd8c4d3d7fb54a81986fb50f44d1534c72095c8345a03370251300713bede97c0ad0bf5860cdedf8d3c1e0c30ad4a5ef0507ad3eb07bac8da93e620b19a3ed51f084a40039629aaf00014c3f5a3ded6d071f601244d6591bb6addb2280619658646d7298ba4a7699e4a180b8e1ef67848bfe521fdcdb23a917e4825177d7074ccf1ef893e724be4a95fdf845886ae61e85abdd0f5f7102d6791a7fe0d1b78fe963369c35dc21d8ba63f5ff6c46c0aea51fc15231997b359e6883155a8e86a83ae9b34732fb7619aea38e56cce970748b1588c0630ee1a23cdb82b7641a3a4ab129aa9a4d4869c7d485e3421456fe9a4ebc7275d6bfd29e9c4e2ae3d9ba692bb6297345874fdf984bbea11ba96602a514aff88d4d4a38f0e2c9a72a015ef5347e0ddf30077755f1fe62fefeb1bf11e77b9ecd78f61bebe2c8be64e0583ea49f5a4ee45619c8bbaedef5fddb9379bdc1567344cd1f5271877e9d060cef6dd472d8beadf5b6f6880f76cd25506e66c59c8b5742a1e826ee461fd00ac81bfcaeacf59fda9547f62a93f9b6c7d7965be2417dfa9ffe582c1524cf4c13aca592b094c269495d2af4691be53ea4c1759db22598dd6fbf51b0ada3e1fe32ea959ff7263e8cd7a5cf643c9db4f74e2cb956607522ff43aafe3b87c2b4553634ff489a2f9429f3c747f57525262516991b218f18497b89143582d8a7270340b2d5040a1d8e80eab5fc5dc28630bd31630378b2daa10749cc5bad01ce8388b4131b749a54ffc7bc1c8e3946e795e77a7ddbc52834127bd48a54f39371d796830fac8fc91c7dfa9ffff4fea72a23ef2f8ffabd1d6604dc7598c09ef8722f46e69ad068c759cc57a680d71bbeb7998c6872b7be264f08395c936317ad05aa0745b774b6dc15a3db02aaed83551f84085b260d15ad78ad16cc15a3d30596ceec4bb468a104256c4d4bc118450154d6ac218c198c7debd8e6fbcd436af1a2e523c4fa805314f65eda6398f8e4b5918c9a81b343e718526a50bac40410b9a3569b8a89182468a20ff1ae20be2a0d2258e33347d5aa4b51041d3bf35d03446e1c841d3a7946228b2d878b23366b47f3cf384f68f568bcedf63eef2e934bab6ff8dae3dc3d1b54d70a95eab13a2eca36b83208216d64ea801f043fbb7a26bfb3cecb5f4f83cccb57df29e0fcb7bfe9632ff9fe08ff6d87c2df9105ebe477117de2a1494e419e46f1692a3d0c20af9778f2b390a2fdfaf380a2ba050f4402be4192890926c83924ff2217ce843c763d8635abe94492d72e6ae0f5ebee4e22ed6cb974cd269abc0df2b9dcdf2e077f8a3072644c2f032012f5f78e9c2cb974af3c5c223e0f7aa003236808f3dcce7e5b3e0ae204fe4e55bc05d455ec86fd50a85df3a3fbf59fa7708f4fb8791df3d41bf6142bf85e81d65f27bf9362fffdd85f33c5eaeb48e96bf593b7e6899f31ba6e52b01fd8a9b107f09e857e64ef491b73f113d0cf376a50fe70d45e37790c8c2c02020911d02120189ac068b8044360824b2134c401640de45be43923791670d09f233a58714817dd2cc7bfa804416f649fe30e414f2eefe834c748fe44de439050cf9f2f67957807f12accbdb7b4e01dc0f51401724ef21ef09f02e135d2eefee5909f83e894be5ed4d4fc0fc2447e59dc27f09f8a42eef23cf2580fba4cecb1bf533f5eef3309801880cf9203e79077998cf27c104f0453211d6792379229908b33ee9831f92b7f73e9f1424efef612f044440ee2921b7a089bc109bbc857c909ebc4bf820dd82f64979c82709c95b080a20911df24941fe851c80bc733c98892e097917f9ed00fa266f143ec801827cd2901c79dffc7680edf5017210c95b7f1003dcdcede6b01112c400423e29c84dde01f81c06f8a42d6f125e33c0f6499a4dde395e88cd0741e1871029216fd5e74c7483eecd2715d14f0485bc89fc10143e69882aef9ebf09cabb842f923f097c9db7ea51f8242279dffc90ff010b905b5feb7f26ba403e294847de45fe2713793879ff3c91155a79ff03c944b8e60d6485fa492dbdc20f104864f527117917f208ef4126ba3c79ebf89b89aeb64280bbda9137d0132100914fd223e4bdfa4b804fd291f7fd2002ecf8241d45f20e7a222daceebd3a707ef22ef2445af8f92422abbc47781d2d7cd2cd9be76b0bf9061b922a4ede3afe07e78900bd2ef2dfca441748deabebc127ed0802cabbc8eb4ce4017d92febc5bef4126c2abbc81fc8e4c84ff933cf8a0bc570ff44945f2def1fa8d8003c83ebe470f235fa4878fbc7b3ca59fe443c92719c9db88104864833ea9c8b390c3bc55b04b2c0fa12fb2a4880a7987f03613619d14e66dbf83251d7c52cee7ad63798470edcde191893c2399c833f249453e84bcc3cfc9445827d9bc4378ba42bec17e127d0ef2e6e08d7c128fbc797c914f12ca5be8833291cdb93dae8f9c4ce40965224fe89382fe47de3fde4726c23aa947de3ebe834c84b51525f9861e9fd441924ede3a2ff4493979e77cd0ff4c0180007824e0cea7008af04740105e083ce183c0d71b015d5f0434e181c0135e83afff015d4f0434e151004ff821e0eb8580ae0f029af03ee009393e0c7c65573621f78000f812c09d0f0028c2930082f02d10000f04dcf91140119e0704e17f8000f001ee84a0085574fc1040108e747c16d8e33f003bf80cf67810ece01fec91a3871e801de4e8a14e0e073c563b74e0a86e72d86090d32950db214b9933342a5d96ba7cc08ba227a1168accc430ea18433a02a327ea2e2e41f00e5f98b59a60087ff8a72083dcf717800c2237eea5fcdd81d4e1fd46bdbedf5af7f7b7d32f877787dea1dea1f7d5e0d4b2f280eb4b163cf4aa69da6f22dabfd3fe6a6f25775fdeb71c98c443e76e76f25277dae42a275fa3ded59685bf3f3cbcf287879ec4437fed65b7ef6b6ae09b37145bb7965b39d461ab82add043ffc1b90da36b79f8fec2b3fe76ca1381f84f10480cfd7109dadfb7088368ff1179fcf10df0fca8fc6e7a32d721ba0a0ea1a4770fed2f1fcfef6a8d41734eedce39a7f676ce59516474b4e1ab2925053b2977cdd9ee9cd372dd47ede39cd35aab596ba596e766023318072145baf8d849765ff86ccea64841675396a853aaac749c4da9c1b533d6a84c9440e24b2fd16510ff18444cdf97413497415c172007311248d45ded60a503a5e3c7ad59fa9ba678c0daac71c71d47fbeea1a7bf056504e24fc1198178de364620f76304b2fd2b137ffafae631b06727afedd7a1e84776d6f6a99321b9e6c9d54344f4cd32f2d49f9e0b008ac6c04a3f5955d79ebee61e18b5f701cd0ac27116022d9a7eedba6d69c61148fbd24518a6af69339e1087064a55d4a4a649a9792250d23ba5fd13e2416bb0e2b17dc41ac4870442dd453b6c03bce3171d9d32e0ae1d9f6670575542fb8c0a17e9cf8274b564e8ef32dc01d0fef7028940fc7d35821c413b0923e0323886df23686fc00368e024a5fcd6e8226bd3396b8d1295c6044f98018eb32e8c26b5e27d57ad37411c06c7252a9ef47c79efbfa22ee058aca332d289b2d23d9e0398405d3603472d5f9313533aeba4b5fe9cdbb553abb5524a41406da269bb9012b381dddd316766153da62c9d5e2af53f6e41141916ce9fba362814ca5a6b8352a07dff52788d2e05da8e76ddbd369fc7711b8e9d97023119de87b76fc9177e413865e3c57e29ef46c725309474fc82b0f7e1c7e9eef7e1df42858aeefc46c72d3fa8b9d11d8742d95cacc2dc8d8d4d8edf3ec74d0ecff3beaff33c2f8767f3e1bfdb97a3fbc08802b7a731185339529f4aa5501eca4bfdf6a99b9b8e4b7deaefea0b4a712b2f258b1cf0a0f352ada192525ecf5d3dbcc763738fdd3078febef183d03cd4e76d1c65904ef3d9ba8fd65a8bfa716a93427d9cb49112f51d977a0e0cba8f028fc4d57cbdd0d474af7d1428356a0dcebd14eab34b32305f120b96272c4f118c08447b1b508a1143ed259615c6a9df574b7c032cfff36c9a6653939681a6f8a4b5dfbeaf434d1d9798ae78754b8c8abe6fa78e5b6253b4d5374b270f35d90406bf86bd14eab3f9ed6db00d0a65ad27c9d0da63707b4bb6e7de7edfc671dc97fa0b1e89da3e0a04b95fcd170cb6b2f63bce43a1c8489d0265e79ed4b0f99247b7fb302410ed3950dbb204431ec926f9b45acda6c883ddc058e414d1476a2fe5a80fe5752350d25bae991eb481bded6d0fd4db03bfb8e35ee419e3c92034d69a759115252ae57d1eb7a1502914ca7ea7799fdc40d41af3deaef352286f43f2dd0d7aa9516c78183c75f442a98c9677069afb0be67c1f75a7dd975abbdb6bdf922e771f4a0d6c0646e9b8c485167d41d75f775316c44e58ead805162efaa274ec020b15287d7328e43a856decf5eec5db17646d529f427ddef6d806775de779b7ebba1bef82aeefedeefd4e755da740ba6ddb16b47d41db831645c6756797b878d2516f0fe89bdf438d7506ef95f63ad1476aed579ae7d92a4e7a0391dc5b9487fa3c4e4a19676bc71029cf438ad1c0f4e9c471aad1a1a9adad740ecda07354e85e9b60f53934b5cd41625f7b5b6de5b8aeeb3acaf91744238f9c3ee7b4765a6ba7967317f3aaf667fd6cf5d01f23484069e953bd4dcf46fbc71fdfe675ac9adadf638c3400a8f97d3ce2a7020f5d9f1e69929f905b1da998e950c7a529b2e80eeff85b4e9c3446ee77fded2798d371d5b75ca796df91184714a3e3c08e7b50e52e07631463f336ef3bea7160fdaebed77df71d8969f4f673fb2e4ee979526e997a2a0f23f71e146de379673b9bcf334a0c8edfd195ce4a731d5575bffd37d5f6fe1a13cfaa0ec7a35f90e713d6609c9b4212ed138a6740b169c30336646ccac03a389810989667a8dc50d9e0660365f80945329a83f2947b0fe8f8843ce7a850df7ffbf838df92fabec3a3607dbdb7cd52ab81a80d0589ed6a575e79af9420500ecccaa446ad510f274a0dccc1142947528a78e0e22b3d67cf8a872b7abe4e122d3d3dac2a8a2d776d184c88bb260f4557424a2925a329fdc8a261f0fde18f9fd0ae0381f8e0096ce0e841d383e018c1a8a71ca3f38f2c3c06de57e3f8d38a9eb32854f44c62035dd4d75ddb3d28ca67326394f2e76c4212a6db810cd5b4961951b5b2963a69d2d2353bb9ba8933e9ebe1964863a434461a69a431464a694881f183564df3136fe2e5e829f06ebc31c6e8495974851ec6a714ece2c47463e8f07cc54802a8e51849d8914b6a0abe9f63ffeb9c7326dd9c637fd2777777f707010cc8ff8619b8228c8042881054b10512d00c34e3b92329a594524a3ddf101d6b9aa6699aa6cd1d39e79c73c28066be21face84e21ea8ce05d1e9ac9ac4f88a3ab31b9a7440d271a68391de445cabd4eaf810d37136a58c7ddd017c8f323f7c279402fb0dade0faabe979185d7417074a4de508eda3bbefe8f7f4a3f7fba8e739a59e97f7b7a1e82ba3e6985c24ae75f77589cf9737f7f3e9139abe4b6e9683961cbe68fadef77d20121fcdfdedfed24fe83ecd51e1ef7779fbd7edeebb7d7fdeef3a9049131fcd650af868eeb9ec84fb2757c7c833ffdec8b3fddd40f9bb9ee962173d07a96bafcdf9f96f8deaaf8c962147ca7370ea4f064dbb13e9a465f0b4ff7c943f8e69d732502f556cd04329a92516d352c10d640a4c3fe608008af687a29f487d5993e2e0051b61a4133c3e6cb57492e833b57b5e8668424287c524ab34e0bbc84156e9131b0c51460a96e9adc381e401c7990e4a7aaf3c79a5025dd4917a6963a643472f53a2c8a1a31765de50e9b8044695c8d2c1c405a068fa51d3fe21b937fed6c202e88287f203b0464cbe17c9974f01a142a8142dd784414b15aa1901000240015315000020100c0704e270503424cbd2921e14000d789e486c569e89a34910a3280842c418640c01c010000c18333343b40eaca079ea411373a8415f7a3158055e81c354fe32567f3b997988169e0b612d73fb3b113bf5c122e364fe9743ed6869712f133c18b206823d7a961684d70f9af15f6352d16855c7ff404a7f6921179e806cd671a4c4972cac046321dcafc5b6538a0c3c97f03abc9540d84dafee2866aeeffcf2f159b74fbb4e3b47d19e304d68762a2b94a3415013303cd9c4465387e715bcc4e330bd514014ceb02a80c48c35acdced215636be8ac880cb0ef25963253f0d6bd9b95e6386050438a80eeb426d0775acd1fc8a71002360d1be1a1865a9a5d953ae243df2bf537f3dde6a7cd91993c7a2cc203cf68bd0b50cff10492b61a02df9d5e8e3af1ea9ab1a9d57a6a404347ab0b83e8a3f4a6d255817814e8ba8f1716fad58e0d5dce9174a1b0eb6175b4cdc2138b69918ce3db1d40033487861c215547c9ea5721aa4e39f681666abe3b875376b62b73c0e0607dac702b360e2e1f6d992e67906582360714b0209572c0b91a8f64aa5ae7069cbb5f119ec5d31ad498c93477fe80dceabec21893a24e192fda31b53aa5e2808334d983001c97f25b1a0adad898555b4e2fe8b5e53423276ac10ce2e06787324c55ff7533281c67d7f0111b2f3f596fb5ceb4eb1e326e1ee2f4345073800bb1cc63a8450558c1e46417865bc92d9aadc7e453a4f6895380466be0ef71656f611efb69647032cf4fe2d467f002d6824369cebdbb72ae5cd929486d752c73c417d7890d6682518127a38abe43176a3902b5f8849b1e21555c756c8c443e4b28ac7ae042362677e841d459a3de3506a854b3b211b0ea8bc728f22b65b55f44140c252c0d3bb6e9e4f6d97ae2301fdf8ae81646ed40356ef9ae54c6c9f0dd8530b5ad14c6e7a388a31c8e1f2f1ecf1fb68e7bc5e1a1dc67f162af5c5f5dda8629ec4abb37bde1dc43d18608c29b91edee03d195204f88c5b21fae113da21ec3e6423f6313823073cdc4686eb92d542c5730c8d7a8e8da72808200870641f9b706662ca4d0d5bf3649bfd52e8b51c2b669dc96511c66cc25b1535128d730ef694132d47261fcd35f2aa7a8172c2e937c84bed2c6f639235bc673c0193e0f8fc2e6fbb3b5ff9fa5a84c966bc237932abbd5fc10429b51985037c54237189a71cbe77bfb9e4b1a7d3670c96e5666288786f204ad76e2dfdd1aa393ce047f47c40134c479765a9fa66c867c0d3dd62411ad34b521ad6f511a9c6ae84d64260fd78a718f1937fe9d19b184cafecdf9bb30b8f80c52c432f63427fb97fdefe17310953f4f0055321a9229992de80c6445385d31ef7f3012504a8125b2ff83ebe37beca00a25d5a64ccecfd97ce621d05a25a62eab2e92f01bcbb6be972302eb3bfd71b44ff4698e94ba8030b5505735be55a70959bdbb59600c793ba996ca2d7e294fdb426a2ce41dcf7ab36aee388d2dc6857e904c0a0bd2ad313a90daae5a545763e4dcbe4703c996a06285992e712a6b1f2ba0853af30942350705222f5757a8fa19149209832f6c9e7bd23e73a06499404f7e861af9b72f99770d12c30b839a6306a08ddcc1ae6181a039fb3fd4333f768e3a221a2c565a58fd35afe72142b561fd09dfd232f33b7e842b9dba04c534091b742dd95bb2a576bfe55a4665018f8b198ce6f2431dc35ffb8555522c6a84fa3092169671a0a88328a979394302fca1541a5e760e7fd46b839236e59b207d1b6644284a4312171c9e2c2d524ba38d0ad6baacb4939d05b3b6e060b5d17ebd611daba431b0f4377f126fe76fe1c8eea6a9f7db18a805e2985b409538bfe26c94ac7c850f93f90eecfb6b4cfe0fa6b25d31c838a8a75e2c27fc2700a753ddfe57c76c2cff1fff10329d7ac26280443d67fb0adbfbdefe3f40e3f7ebaee1238a21aa60b7e1494e98a3cc6b0f45b8287eda556d2389db39a51fd2d5ddc830954821c88822b7aaf82ff6ce923c9c0367e40ec4e57387f3936f3f888cfe1b778a3e70fef45a3607be1a801a1e361290c15e9e3a90a7a1c5cc4e84e78b7004da6b8cbcdd89fbdb6e3c2179458003fc5ca2c701f387a173ca5edaed9c0402126ab16796d4b7c22f985ddc1aacec113af10a0fcbec5dc0c610f2b66f4517d3bbdc6598a4cb3ef90917d95f124ac5c6e32144a6fee24fad77211eec626af2b32bc83a7d72bad75286be15dfa4bcfead4fc12becd1e51316fc2bc2c5d4a49af69f42d24e1680ee12e0546a01fc22dd4a3c2b6f9ca4721a17783f446a6d71ac68c2204635482ceba36e95e83b3c11693c2af7f499e9be762817c1f9b08dd065cb2c8dc3618a5ff81ea7f7adb4cf7b9ac54917b8d3201b41e3ed181d9457428c9c16cdb61307dca0e34b7388610bf92d5bad65a1827f840350fdf9a391a32d0ff28f69c04e5dc1bde6e1d799c37fef297f2440ee6093c3382b0a9b38d24f83fc8d0162708b712f9593eb9963e142d784e3ee6c397fb5029b2935022dc3bf53ad74881e7881cf357f7648da321325311e4cd52ad7a40b1dff98e0acda01e450040446fc875314c74d7f502c06d6935f616070e4b96b1bb53e67633bbad763a6b950232de14746ca55684c724cfd5b9d1677075645881f5c344b8f1d4101d5e81c830876218c38af6c17c91fc3ce64964ad588a88e158e541e1387306c99fedceb0d4734221b8caa90a19968740db4deb8b6d6853f123a28dddea9c16c434d0477a0b3f789c3b6b1a1eba64fdac4812488ba88ea2730e1b4b0d62f9405618ead415066c188807809fd21cbe55a2c6a46e37595803e2fd5e4db387c04cd8c77d5053569b8bb374380eb9043a633d632f88158d7216c6e9df7165285e4790f6dab0578a8af8d736e42ec354f0a435535252cbd95dff79220a144925ea8a103ee40b0c8bf84f723dc9acb0859770a3763710aba80695fa2a33255433efaa0a02ded7f5153c7c5e24eaa947622fd18901bb819c5506ee9f7200631ddbdc38e0e83dfed239b8143904721892d49cfb104ed392d141977a073c02e53c19e3cd4b83ee32272eca79d9a1a763c925328e05e7d5914c08883e5625eee4607c567bb336ca26953345f3077a86326271226167843b2055f10cfbc7cc71725b9be7752d6851721ad7ed0523ec5af9c2bfbd848b06884c5442147716dc63cf30096ebc1007108449f4c6988452b087db4a60c81aea93efd6d11eaeee81ea2bb94ec0214e46f150f39199a4f5f28c6abf14198defa338e7b36d29578254d603fa3c9fe289c54fe61e0a833f73d322709b7f30e6871246799c31d39d733e4e108dd3a10a2db989f34684aca9ea90fd9caf51da571c4c528aae66241e0129d3acd15e9da4e164bc378b0f6415b091bd4b17064cc6e91a787aea7fb947e83c75a5fa9b3ae1b34f3abb3ff9592714d134d769aef68050a44a88b2b6521691b9ebef47823b29801654208562299d8295134a017b26210ae481627ace698744ca6e664510260c8b0aac63ccf3f85863ce1f3466131e581446b191fddb4a1052fc08f824298deb67f07e768c2bb7e9b2ad1459ba95a646ef1c64e321982eae620b55fec80c46322eb786546cc5d0653a9f32901abd9cd9adb10dae342cf772a0849d73cb475488991ac5736a2bc669edc4dc8c9440e91a86a4ff52e670655af8efffe8b7405180019f2227508f5b188283a21c778f6f757f5738028ae51adb643da9d5cffd94439e07fcedb0a3b385475fef4764eecd820d68932660fdd6cce3a203e7af54e616938e3b0f6c9a9b62a5081146f0b0cf2ffe952adf3330c608398ec1f0e13e8b5ad890e3c265183a58d8b99daf4324692179ff0f1f3117d8c91a62259d5d67ebc34a5badb33659f1960d472733399da66320447b7f7bd200d12e09e05d409418053f5d91d00d8ea8f9f4674d2d4362a8a45a4c40c31798c2d4097220e3c68226062f145c7f16de80748ffbde87fb8cac7b90208f69181be632ec856ab1d77d06ca0fded02f2d3e9a7288d3dc6e3c6ecb2a6e993b972c193892a83c281a951b3940be08e2609df2290f8a227fabebe47de3415b07887cf6a0c16e3bf0048f8795ed14fa534256be747aa6e2b33247564c8b01f7aedd0dfa4b1f76733f25eb5293f72c40978831e93fe15476dcc8157538828c9e63d76b623f3fdff3c19c793ff1fe86806ec662ab907729b03ce48a8bf44187c905ca59737e8f188fe73acb40c3279123dcc7bc3e3417192710ec71f1a0a79a33c2b037d0ae58622397fc398ba539a5a2125d21884ef3ec4373a95bb1241df5ebf89bb85a8e4091a5766ce9a8d0aa2d4295909f58a2fc9e0cfed8feedaea896534f22c430abf0e0d8c83c5d9e58127aa9aa4b803a22c729049ca98f94f84dc0266a4db194976659ea9985cbdcab1e9313f00784bfea99281c41d5e0874c326d76e30f41dc7f11d72983bbb5a5083618cf036137cdf30c4fdbfd1db0c03407b86188407e7c12b62feadf018bb8fc4b186a91309648ee97604f483f528d4900ad31c59751d3caf4e6aa070715eca56cdc5ec5728e405d2f8529c9354c0c3177232d64e174a43ab9d4b9e1045a5fca2baaf4ab535f5a5b0c077cd5c950b20d07ca8d916a98c296274a2c46cc6dc51d93985acae89a24682c5f2858e4c052bf7c9f2c5f6133e3dff6c51e499686f1092859e474345093482d4611b1cce760dfad2e93c2d186563e1ca6b57d06dc7927161918cc86a8942460700daf1319d1585011792b703b125067f598ade0ce686db2a31855612ae02073d891aa313b97ee34e5d842e05b70e545f600691c87fc864b04c8703f5e5d18ed78f25b85399c505a3ff119588e615f63ebb19ca80df2917cd24e1c88ba3b4dfdc4056fc1d995880ef807a9e2f8b1a39f39d5dce2ea46a5868bb8dd88bfb01aa2b41572b30ff05059b367e8cb37172502edf6b42a8d6c650bb0272ddd16e62f17a8f506080c30247c672461e15e710d1919d9a171e692e1ae67416d2ab0af03e2fdbc9e630030164bb3322dfd39adf5e254e69104fc0a88f7bdbc9cfc926659def2f9d65ca2ec3e47a1312ec03f6148d8515d32f22ec7743fc652f77e006a116c2a5d0981226fddc6f82caa94a301fd35349a8b6c4e6254508da5f20d08de3a883fd100bcbd85607e662e8e63311308ee288950d751e091457652d1307432e81d6e843b02197bf72483e27127b019371b344650dc67b30744035bbccaadbfe11a2da1eadc147c8d42d63fa3becfee78e43ba69a8fbca6437acadb90fb15bf09c6f6deebb2926f2162892091a60ed10d05f9853175027db03e234bb6372a421c24a83b4983d27da6559e8a3604ae5e9c92a7b23b76edcac62e65b2829e0981021e35376af9e09a8ff62966576cc49fea9282185747e538b53f069b4f8d2db3a49aecf95818ad4d02083766680c734aa6071b4fc0d1f971ff3f038da21d415919d41bdd4a1d0659bf515846f11099687aba822f52970fc53e407ff333b5e1ede3a5ec99a548138ae028e0d050be137577b97621018a7a53f0122b9c7ea47a045c04c946327fad53a660d416e913c62bf7bc58ec93f6bdaeb0f068f20200f751dc3812ca003afd185ecce5260a64d7b438704f72e25d2cf2f54858a70b4d1e0eada3480944c772cb25bcd449dcc1a941320f4ab1557e7cd47cb60f9016d49f47529fbe06874e9e6b84d8286804f1dceda9ce718539c09cb654009c70ab09352e15e54532081fdbaba52510c7edfd4915bb61f52cad058320734d24c9534024f6da2beb53c7132ab05204f1aea45ca5f1bade3870f5f950d40f26ebb868d88489f4e340aac51be09423e5de01dea2aa4b1fae23ec0d91ba032352fb179112d6530d22edfa1e8b29cfc46721b3956296f489532f626ace3d138c3dba10f9f6aa2efd2d0766b0c6e59a49a285d9c03217edad4f07ca229f43ea38009228e2c5e3340766990e7de0b22b927eacc100b1e6305a2a34035aaeb286001e2b52500a6e9b8bc24a8a9faa1b8f4946c67e1c3342a9eb08d912fdd9dfec9221a744860553eaa661f25759361fec2210878f2c429969357068328fc918eced434e64cb1cd7ec56bf06d753a369340147eb90647ca9aa4498525da14daa649635ac31ac8f883dbc6611b2e99d1176259b1327d4b6f4e2845a31e52caf2eccc0cb82b5b1d8994203ee28a77116d46e5abd585a47e4dc0a45efd7d070f4754e81a16a66fcd84b1c19e6e6720e8474f7e85b4013932bf0d849e67f13415ef28ed4e7b337957cdfdac8d8dc4c70d0e16fc6800e24a7359f47517f06a8811263264c722b4ccff38c0ea58cb6eec2f1a057552655ef9d01574252a48d33e2d8e8173a2868b2a5e9a7dc8cd469478e30652263b27d0570d91a37d21f06ac3ade92f64efca46daad3e26c4e978316bf23727687257bf49732719408ae446f45f738176e3097908b96f37f779da0e54f4c52483e4276ada9abdb965883ea2acb53edb061efdcd1e5b1f35a07bcdb843d5cf5c61e3dc646c2201927bda56492f0db2e4d0d720d1633691f8b0b1acd1e810963fc954a6fba5e98e7c2e7e1839f75434cf25a5ed46b0e6b70797a0b371c2388663b27061fa2fce8c60c0aed457d668d907707d776193483cff2e143cbb4dceccd85b573ef16e1c4af47abd9e84669e1b7a113cee4191198edd3dba1da8a661539c037eead686a051f2e9310a7bde4eb6170c06165b5304c85dba59d75f8da23736c475239f6c9ae4a2859d8b5afd0909f207b732ec62b9878b62732a8c1e2699ed3c016eb65511fb0abd5bfe6b55d3071f30433d1850e101bc5bf37d8acd90421bfa5d5d74e0b80a1603fc0d30770dd1c5e077e206c93d8af83b351ce878ae241c39cb70f2ac25ac70559fd7cb690e093d67c782ab40ab0f02fc4b67aa406871b95d5175f43ca0c1ed827d9eacdffa715c8053607ec6c42d82bac1d23eff30f39ae21f1074001d3620bc1f8951794f3541c308d6b0bfd8ad841427b9385e6d60da97177ec8ba81320bdf463c2e8a8fa43818b913d7a3132a6c2a116574cff87d7363f935e1fd397157a3f38d06c5725bd20f54cd4375743445997132a22271b083af3da3d500110085d92550dfcc7aa5a2f561573baeb49229c4c16f194e4d52a9516f04041eff082af02a077fad4776091490b9864e0c8be244ebb54fd5de61acda4964a1b0a981b430565346a500df23c133c7a3e25f510b22afcca279dd1ea62d2221377a6c0f3a227b877ebd71da10920df4734d1a8022c6ba266f3e34631e5ac8c24ca3338e706f646f24b3614e5113a1c51595182087d2c905d8e70c5f21ccecb649a5b46965e5557fe42dfe5b2dc3f090ece67d5bc63cc2b3d9408ee5e1ebbe2930d196d65e708e333e9ad06dcbdd1c4889a36b8225b4df7f20223393e26a2b7be90d00e26e078f6692478798fed0c0e400e751c32a56d0a602b948162c165f6f63e5f6fc61b19c41225c8ee1829ca954c2158d3e23c69b2f8b0697863bd898f23e336431f2fdead1473fe0c4c64804619b614a4cd447b9ea41611a7a217fae260457ca33822f0973e60853834d300d238ce205aac40d87cc97570a1a25490644c21201384240a4b8fac43f0a21cd930a11b1886616315fb81df6f0f127709c83acbe4266fe30ed0b7ae1d11b9bdca33e634fabaa4fe34491a5583bb72144e05fd06561cd05cdd3223f95bde352b1d8b37519db577536a4a2eb9722c7b305df63f69213e57c19c413f814cac103f94b970c509ce81de1f55a29edb529dd91c14a83c0d57f683acf620ab6820f5c1a450fc387d5c27d47bf5bc066aba5ab2723d9d6cbde1a713deb0778967e48896ca2333ccba1f026a1a69c09d7ff0db5604be753d2375a4e77d0fe5f7bd2cae027d341beccb9439333eb04314d6b4218708ebddb8ffce4e5121a4055716ad0595b0231cbf7f0081fecb53d99a1ceb9e5201134b43ccd4bfc9fbe88230319fa0d8f65bce32961efe8b910f414042220df178cf1ff27144b6736080d513982a774c5b3b644f28e8a4d06a1831b7aac18c5ff06b04f87a4c68181eb83a164cce65b2649867d9619d15deecdf9eba6dbd9e6794fcd7c18ae69f3a1e57738da40379a56d77ec4856c284294cb677e1c55f988a20d236e2de787d5e5a03d05b2003327ca0116314299dc66c798bc4c817d84b13c65cd6a98c4f67966ab97ae1bcaf136de59cbc9f4a8b63607cb268d29df134e2d7891fa94a65521b6095b26adca8a89281d265b83ec51ccdb0d2149b71a868c587121815538f4a16fb4a58856ffb2260bf0b81611f9fe6427cbbca665dfac3eb4031dce115a0297c69b621814758b5ce0d3495b6f5bdeafa8a9cae189d66831b8c2b4d285e176b0bc02f8184f7ebb9280dea8b64dc1a6edfad3e7a0e930fd6634a1eff84264bd47c1e050d0e7c6ab7a145253e29bf9f42878f0f7186d2ac2e9d919403c85c71411c13db3e9c2a03d34190385a1a636c85f5183f31d9a2455a7ce725cd931c7ea2df366194123f09e3f6b445b320582b2925f5f3c77d9ad941aa63dc8defae621d68729ad9f0d3446d70feccf7baeef73972f39f5ee81519eb089915985d08ea60a166f9aa972c5bea2baea722f4468e85c725b3c20631748adcc1b678fd824cc586e9255173476a642664adff449fdde1516f5c0a8691c4f2d27c695fb262e51b7699d9bd38073bb3e54bb3b7b300bfb15cb4d3ef387ca69b9fea6631f0e0bb4823b5897737eb15f9a799976023cb70cc5cc1419396fad7e6f618bad3fd9d216e8e3c8db18fffb2264c4a7404f1d7d0d1fe3e3b315951972825dbda6e97e26900c9910e2d23c5bcd4f22490e8b7d90444bfd73e9d0f470806a123e947d36553b11b7a2963dbbedaafcce3ed019211760553aa3f06b29e25435afa89f5263233b76b019edfa964a041bffa487cfd1438dfbc92daae2ba88e8a3ec7a413d7422b8240d0819bc3f31f69bbd8715baca7629ff8afb1abc24362c5b50cce633d6ac193ba0de3cd649fc1f981a760b1893b135dd756e9ba404c5d179560f004e27c9c2011ae3c7f08370a55028c43a83ba9057a57de5a5348d326f27d9cd67d40904d3e40f85d9923422049e1b114834464a5411427575d94735912e458099f419b945f8cbd6d0bf827b978f4c2d25f31a42334b92a5ab0e544f0787351120361070a3b1077216381a1a3ce5cd3f8357326fa1322773d81b31696f98b3ed700c5df1f72cb4ec094e4522c65e54b5907023455d6615d67c1b106fdf4946d28e926f031c9cbde98db1e17cab70bffdefdf67f56f6295b45942ab9990ea7439df2d9c181051747c03d4ae6481751f7324e2614a0eed3a7225aaf4db4eced89b453c06e6603075774aee161003fd2b361edc64c566f1159079b09cb426c895f3d685d0400c240f40ba8ad7c95287ac3b8bea0743fd6183d8ca087206f1209a204d574182f9281dfd8a78660f14988f23f85c8bc208bc9480ec46105c06fa1eb27bc6331ac7951aa94aef9ba5adab7e5aecc6e02ec01c54a84f8884072867a8c27ca76b52b18df1b3a1e7fe91430c303b29d75ae9fc07395c3c50d879d286bb585151e3d52676039b2ec1ab1cce3f8900fa89b78ad51f99eeb9cd45c1f9ea625886654a167f7d5b57e14b6bb685186f40438b6a1382def289e9fd2e877033ccc6982233c7087f1471c29046dd26a5f8db2e9ee07fd8bd0668346b003f98bbe9b8d0e2d3f3452d060e9ed77d2b22d1e719d36acbc817675f16cbe8afc3a5f617a9314fdbb504ccac592e671b2f72284078753cda99cd560d55846b89952bb48a969d2d614695dc704d9109f56c6aafdd62eda573e269f713eebdd544f0f015b60e07893b7fa634758fa57c088aa34f4224cc408ffb28fb1ede1dcbba7ba88e740ca186a2d541d11f0f69c27a73536c8c1bf404da8dc875a2e0469166bf25971fbe0aa63aa2781aa37bc0ac26eeee0ba7f7aa88efeaf22b533b0fb59025cdefd2f3d94cf87e7061e90542967f594eb455c14d24350062d6a7a720bb353790227b710d9442d9e2f40da77ad47d844b10f7da5cded178569ceedbd6346197c942ca7c3d6f8f3fc71499bd883980af57edf8381e37a876065d278006b4e4016ba821dc012ced5d88904605a2867a51d82bde3683f91df1135a9ab33e536fd6c8b1208cfd7dc2a86da952849a0bc5b1470af143b60f9dd905ec114263e4086fd5be5df3c5acc49e978b40307725d289242ff52410fca6cbaee4b02eb9b90b50909a84fbdb63661a0e057ad8fa5472a7d08082609d47c285d0986efc639601925379525faab53243550c2d6a5c780f10ccf66354062c7988aa07c092eb7528fa9404cf8fa542cab18fcd4800388219006c29679d2c7f202e581e44acefe237e68c2b5b7157cff28a56bec38035457a09c635bf3896030b27ecb66cc4973de2a93113f56ab71e3afb815d12cc095e777fee1d30aba518fe4f5485186d623d128ac1f2d3e50abd9e178d2f233c9648dfba742c674739522ce5c68822e012cf419c7e73ae2e69b0549915cfe5b478849c2e24057f71f11e5b50e56606ee50fc7ea0a40c8c140c9dc3efb250d2b25615057d9dcb4bed7ec33a3a88dbc013d8433e231735103e9adb319826b6a36c943a2773ece080ec2a0de6618c3cae96d0fc80a9a7ec09e6a3a2bae7718a3d7ebce40ae448590763d13464ec5fb63fe95881fe655cfba41f8b6c8d41dd1a8070d068548555167b8cc80062cba75416e7e6bda10d8ce21dad4d4961cf24110266ddb630a4905e4835bd2b0c049031b92d96acdd7b68fd9576d67f662b60b0399e9d28f1abf07e7d6e801aaaf3f86b2ce5c8290ab14a8af5016032b831ffd3a8c40611b51ef3bc1e02dd4e1f4f240104bf94ee2889307a1fb3f30ce6f36dc4ce9a712630d6a012cd9b835b644d8dbab899f48e1b083e124173ebabe2df4258db5a2a70b3c63d439430224a30ee9073cef827b474b0e08aa7b402098e402414110d1e9585c9ae047f9697bafd00f584d6e0fd899167e5a2951e782d1946f94fc6ce6d01f572581161b08d8c53f6d8a6f2716446baec573d3a4871dd2e5f0632189f8ec73988c7617fa2cac9a80b617fa042c4c4c6abb606b5011b43118a36b9f4aa36ec555849027939d15175ab5082ab118edf1e485a1f671f3aa64ac3b695e82d2137936137d844fc1deb58aecb54f55485bd1417e39ac68a518fa610e99ae440f9099806bd0e21990e1f7b5accbafc76920d0684ce16bdd336665060b7662c929734f706b2a7742cc92499056de43c40ae7d2a64fb5a8d086c72ee43ad4b5d16670d92906de02c0aef00be57cb2f1d99622c3adc41e7c5f33c76813093db2e55e04231d4129adac69b36ccfaad26c49764c854e37833eb5304edd7e37545b30c101777c8e93f4ddc00480b563a4f466e6e2ce3170a46d3dad4e916ac80f1b1aac22b58ec1c8e28f3d20c3cdc173aacea127ff085c942e283c7dba50d56175d5e3eb2acc04fb73cadc500a33e85ff510baa5cf6521596f8036d133e9635788b94dca11b398263ab0f348d1f32a9eab8a38f5b894d537d1d1d917377582bdb1102177a5615f2fc4963bd700f80d533179be02a5b691e8888dcc8d37e8e588336a3fc989bfe892492af2a92e901a093402a2092c21bb919de6d103c1ecf6e109ac5c4ac7a8e66b4a3054db091d41b1ecd4119dc9f40f0d7d00343343035e72b44b100c54878d519abf57ca9154bbdfdaa037921e9eb8e7a8f8512482609dd0ae5a99050017652697a77529e53c334a71f040921bf293600375ecbe547a13c29088e4d4bbd5c53731732801b7298036e30ec4ac7211b36c7f36323cf0ba201f6d4ac50c837e6299bbbaa384f17e3b469fbed4e2425ccc4c7dbed85943256f9d30106d6c99389894aacbb87e184ed9ae612a38f24b6fc8574444ad897b3e98718ed54e5245dd2b14dfb49dc772a73a3e4477a74bc15efd4e88c46608cdfea157c318975b08b499a3c2ec4bb2afb6e2acc09e454b5abdbbf3274c3d8e22d3e5a880bca0cc1975965461bdd513e7d179536408197c10b9be6b4c7cb3fb39c6821bef344b31fec7bb42dfe78bde77e36256f2a14cc744809a6875dd8998e6db09510036c362c2c24e277d1acf0ab72d328158a6f34b9bdbb8a500184cd4614deeac719dccf416838a75dbffa29ee45bd05c505569d8d96cb1c74f866c96da4b0f344c2d71f251104c684cf930b7101a6b10ff6776cfacc49bddde43edb65607d971257bb36d00a67e4cbfe756fbc10c08ffc07cbfb51c56132fb0862b94c37cf1fb4282e36453d1d4ee38a0b94cdab63e0bb9a08956b8cf03da543ad9f866a59b590053a53af404ee35a26683a8811792b5d76df945fec8690100aca8d2d0015b618f9e6c17849fae1b13fa2b7dd1ddf101f3ca6127e647c2bfde3d96121dba7936e031c01c70e64b8cb0c2b04fb4503ff0fb0c58cc0f6579fc5129368156a6bc534624c5d07e4eb20a4ac1e15c468c0eafd8d544d55bd20483b36096c8be5bfb62b03c07e1d5f98ae384a29f60af25893ff80b8814c573ad61ea9f6b8f557294713f0fb22143554280ed3a3b34d4f5d84474939b7d2c9f7cf205c4ef228cd34a68768c3b5017dff75560a52b948d85be50d4978db3323269617e53554e369ebac14441a683f059f055744b6e6170171fbdec7755f7705c79fd7ede47f67a9da7d4c6dffad7ec4f64b83192273203479e42b3bb004c91c19df282f5c57944a3a5cd2722699ca258a156c84a58acbf890ac0fec296328a1d65e18f92229a2ded082312eb29d1dbada4af3f07d66e7670f679d2a2d71a45968611b3d2ee4a530c76ed29d3c5bbb42199fc83824d11ed71f89c38a8e699ca745684628aa2f1980d547d20fb4beaadea7fd83ade331aada570d9201cdf8ff4ccbb7b2cb518fff63b69ea76b957d9bcccae01cf6f64fc403ad6fe91e9b8a766ead699a21694f077cab4e231424be8022c6ba1b2ff52fdee1452ddf9cf9a4fb42483895dc8fbefbf6db171bb9bf4eb0270eabc66b1262495209736bcc67be467896dbc27e95712d9f3f209695271cf6166e3c8b03a6a6ec3e84265098769f1b1bc5c23d67a4b3d34d781ec71f60fd599531c520269cdf52401ebb17499cf9d965af15c4636b260ff6c120b0ba951f82e0b25c94a8088fe014418044b8c8992c757bfb20406d43be1f6707e6bea83a7883cddc26628d136989b63922f3cb25916ec701ab671eb1e91f708bc9f28e2806c8085f4c9c82428f8859900fd55e5af851f9a8a12753942f3f13a07d704f4c5bf0da5ba5a0e523d6c046233762632605fceb6a320c9839714d0a1c950dd31f39dcb8f71d1bdc1041a100ec28a38563492f69399c26fe632b03fd381b7aa2830b6c1210b24d0ad34154b22082b82696a025ef2a14a8784b9cb050d62b1c4bb44e7ae09cd029b7822f792449a2cab0ad0eb80a91ccc70245545de9e2ceba97c50102264833de3498694d931e6628ff6edfdc900f89740aa6c919f8bfa439fd21bdbe73165433673a6616a4d6b40b56688d0e3a0c6e0d4f4070a9337c99b6506e1e46242bb5171fdb6f310415a5bf466f480ea6cc8bb7b220308a472c999b829285afaf33e0ce46d073bd9e3ea117c5e07a70ec21ed7611ef58769c298cb6c2df9b23282b427fcb91fc62fe82e97cf3d7846e5abe50f3c30beed49de6a66c45e42c013168e2743b85d99184f982a2677c699f99f8f9d2704b1324c1b2308cc5b288f86672b1b67c8dfd969ac24c64efd82600158c6b50a4fbeba067f29270155aa2c03fff3e8ddbaa72bd5dc9dbdf634ad63a0ac04daf04dba889a2ff327eeff1d4f697b2a86942736522c03b3238aeedef5f42c6f32010d4d412644c36a8257fa3750322729fd01b6c79a25560443d349934bfe7f44da4a0576929464bb5e356f7f16d113001b9b90ffd61574d0a643197a36d7467afd8a20ac223d0db41dcc1e8991d6f0c969207b593ac3749f89ee61f07a7752fad7962a1a26d622d501cfaf6f29db67244294643cdf47a190d4198279aa348a07c07a1683022c5948488e957244752264b46a813ad6daea984d13ff12948dadb173b2cc3a34012a03d0aa321e420cb1cd8f030e4308583411b885dd73b10ba4e03910db10198f94191d2dd1919c5e9128a800cf050fd8d82db0b3d8d7f7911db4445b3654867a3ab0d0bb2126ba3235e5c1d3a73c32794a999d2c90131c2ef344a23e52ff8ebd7165e2c62214a127fff6d28dcd52c214a33934062114ab12cd7d2a7fa2ff983e900cd626e9f9f15f0127307b02205e4614f9bb7c3bba2b2989e452b53277b1d0b86ee62038cd4c83eaf1f6d1c4ced27dd351db6e0c808c8af606b44c54c6368a627ca0263a700a3dedf47b499d2a99b20d88521039e2ee0eed524eceed01d66814b20cd43612cfe6a388fe223af18c0c28d253ab7cbc109e39acd70ae146145863af286137aa820853277cbc056c75bba48b8fcd64f901027d799d0d52c833c66388acb9e65b2dfa8956599119c064fe85fbd9cf651dd0bd3a5827c5d2f88fa54eec05a2b93f2ce6d547b8c21e916fd7f6512c8eb63b907c37fb9c288e13e604df58aca8628f47b1783c1ea85b8a6887a651810130bd8ed65c1b53bd705e9bd6b72ea7d55938e78fc5d215b9a7d1c9b3237876e4a8551953e636c4e8e94e92d39c2834142eb927a186305977217f157c750fbbbb8fe054d3146d99f883e8695874916cc3b41139ef74fe2e11be3ee34cc9ec7eefb1d19ab4c0e6741e3ad4a0d642e12679b48f907de26af3d160f0c925dbcbca36f8c62425f7bd7ddd549d2b7745582eb00e9c60ec2e5c1b6d44457c6a0e340934f4c90a26df0c179933dfacfe0e8c94aa1cdd7e220324d24bc7439e078efb5b1d529cb6c2d48756e52243bf11d1401c782a1b4d3c100872b32088285c751d8e31588a6b0e48dc91b46efb78324418ed83fc543db089616b6a701d2cfb16c8626997c1662f9c745c1816300822183475551921547609e0d07ad1273886d8b34160a031e628426b1b8cdd96a0349baa81b728e80302d985519847901409e47c6f4470509cdecbd93e3a1bb491ae52685bd0a482a26cf441d4546a7203854c74c5af04e9fbdcb81bed3370b1425bfd5d8addc2b72fda93f08b6681540d71b3265715f88c6a588a12ba0f9681de65fa550007715ce561582271248088c25d1b1428908c61ee7c46118e9524a4a5649c38faf27622ab018812940b57de913bb9c88e070cc3ed39cd7dbd873f6a5b8d39edfaea46033d2538947c9307c0270d4ba493d830cd84112d05a38c1dcf2e231b9d0ac427bb27b16dddf0065b48db0079df21f72559bd0a7379cc6224f35510c1129eebca4e5874e2702323a8a1686f304ec843017de5b44fc6413385847f7b9f162473cd17446583333abb9b946b9779aea95c250fa5dd78174af9c3b8fdb4d18412e09ea4fd29959d16e4e8f240d541d2de6df3153d91abb55af8c8251c212ccc882cb8928096b85fbf4a7412a1d8af7cdf9701e677a28a68ad138313453544ae1335fb34cc9e89a0d9bcf800fd62eb49283127be0c9bd059ad64985f337260d54530576d41131565ce9e8db98f666f5e46553c2b2104ed52901194da3866b3019c968d664a0b8ad064e51614a8089e15759bc81541a6a347216e2a36814260fa66bbf731c4f79521af134d15f01a8e45327eedf90f27f8758969f94a573ead6dbfd69e4906c8309248ba802577c5ab5726ddfce1620ef52230f2b5693b54d28d237f9046f57420dadb5f111f37aced30c4b4d52808af318afa7d29d4de2b0784803760659202c8b378b59efaf5385434199b82fa7609248f7873c51b573ddd96f1b87488fa0cc24ebf2e65dc53a3650ece109045aa9edb601f2b0fbec20bdfd2df163834b11030d2f9e91cb4569485f18be27bab2085f17ab70afea8af990b63118a5483b8614986c0e149502ed955fb858e49407f2681caf6291ad107173e18678b668a3bae97f1e52aab8a6919aaf532c6ae88109114338914c083692a0a71561dbd1414a7cbea0a3f17c7e797f7c215197a3e6d6abf5eb240a2e0565eef22256b13b9b5db65eefce834388e7ff9dca30bbde1880e390d533be1a3044a9d74db52ceaff674841a3be82882c48c6ce3b95c7a5181caabef92b3ef482c1d03ecc70b852a550e621b2bfcee9100485701e9df4b901cb8c0114e0a2d50ea52272fbb2c2694be36d59634aae07ec42afa2acb26624787251d315b8d1aeb5c16662a1629bdae25bbac9cb943eeb27f84bad5636f9bca3aadf8401bf97afedb26315632c9640dae2ca2c88ef20839b8bd7c83efa31a749988ea897842c35ba66a1c4d40a551d652dc900ecefdfe749d033ec45727c9fe52d083403140dc507e7ef8482f1fbbe791004f435edb045d627f86de1bc4474ec18a331b7f18c76554e724fa10ff20a47a3495898be773f4bcdbd5ab44e50bcbaa4aeff036a048a3057936e14f96040656221dab8dddc468b4fb1c2a5689a7fed6466e01ed1f273c92b08d9d8c5efd84a11c5f7d51da960e5466d9abe1ec4988962abd9e5140c966574d7030ab8f68f832a18836c5da52589a493dccd0ac38b77fd806ebf0858db00d891640c4ff201da001147d67ab1cbe8d7a7b9ec8f5f8b66ab857bb7e13d4fb758fef4af9ee804255bafdf7a687b582e278c2061f320a17d4abdb89708169bfd9ad1a45c432fcefa0610e8eccfaab288d2c9153530471e7c350eba6a0c0f807d85deb847df09704b000ee855a52bdb09365999cfdd5631e4c7c329324e29b98c0fc7cb2f45b666b1322789f024a0913a4a98f646c5da44740c8e6d7859701f47a2582c77011fc424c2d5a1a615e2887e4f8792452910143a7eb43dea250436e1d533140da7297a291913135db96a81e7544c7c6ef6ae18cf92c301db82f6fdc52cb19ea77128e237ed22365fceaed0a7256c33c6d4389b51c1158b73bce170cd561876319854e170d4b376e9c5b8c4c2def56c1d8753d053d1ede3a8546c58158c8b47b117c7e02dd151322dcf9d5b2825cb20ebc729d2fdd680152f91d451441775da9174bc8e45924237a28a3426547e028ccf6f7abe9a8c674af3a2b60ea89c77f4e5b7046d567e1a2ce19fe09759b6aa2f0bb4737a6cb1af6a478a9206402bb42ae9907a053bca24c340c26a846143968af0a6085048304d63391ab8c38b18eaf60e5c8690713d0e88f7f32822819fe08242609afb159031d0eee7bc61be5354e3a962f44df86ec5c3374eb336cd8427c831db65084792ba95aab226531d0856f2447f54e1db354ce46f168a69c598d797701a45ee476dc55949c372600ee40cb7634ab61da140b010e61743c81ebcb8bef82d4867110d545f43c584de29c19e53c87f477f22ee2c02b10def93b5bfdc76d3f869c2967ff304f1ca7079184fbe1bf765643e6833e4f2c6e04d8fe2c2c59194e2f18543a8c90aaf3f8a0c747e905b79b7a8f70912b905a5a68c1eff23e8f219bd949d81e67bcf0e1582e5a80ecdcf278c6c878127d7b1cf14fc90fb4a3ed817e1c7b45a6ba452b0d2cf3dc9b6919a4ba206027823abe65887bf5606b814d49848e28f4470322844535be84eebec4803c8c92c49d562858ad9c410330d8fcec67df637c75fbe6efc5625022c008275dbe62e3c6552f33c6b05038451486b1989ac2467c4f13b8261b1dde81c36674dbd5220bdadf24cf619f3601bfc3951d869d505dab7006edd41909ac3996ecbccbf1a0248c8da4d140fd1103ab88732624470b0977d6353b2814e09b97c4020054215dc73ab4d90c9fcec30bfee714e0a7a5e365108deeb9792e09ce8d5fe763495ae979d3140e974003d8f26118f9796a42c4e3da94fe9cd7db82b484f640d315dc1fc21013e9bc3ac2715de4a077d689b73b4236fff681b73d05c25cc1aac5b99bcfa0dd5acc5a4188d91a114e6c01d29628528528ba803b148bfda183df75be8fa81a7bed21d6b6bd9bb9576f4e3de1c423acc4f043e0c4adace62689c0624be3c93d40dd3336c7eb799739a46f1205a954d2dc7589b5b8d3b54559cdeec2d55e70a003f6c0cf02a65452a51162a055e08e87d444cda692e2cc26ef29a94f49fd622a690f3a1b0110cacde6383d76280cb00940a942a76ba10bcb53da2696ee7f0bcbf1ace8a03c743725c2ec7e8e7ed34e926514485ffd4248dce08fa9fb8cf3a4e200d1097b20e1d73c5f817042653f00f39eca6b0eaa4bd69ab7804d59ee0e9a9f76598a010adfc910411b05cc9b8196a1b142433bd6b164a91566ecf1b087eeb6ebd0236b6bf57f3f9d250cbd118888e763c276c3368b040fe9f3fb0f60dc178b36a7f624dc0ff00cdaec6a165563b0278d497d508f94fd697a0ae6f35b7388d30de2d2149967427e123a82804d1d78f6172e7abe0756835893b935c6e81943aaac79a3c800731eb22658096b3d8be5bb8bc987deb3cb24b99609a30766ecc524eeeca67c28a5f95767a8062ee660005fad0f973714cd1cb0f261b62ab7b8f08bd93e05cbdfeba2f2f268d9f14a850335fbad7929b80212cc079867286004039b5d64c066bcf1af5909f46b76d05c2bcf21aa14bc2e034c55e096fb36c101228659ee8c656474ed2516393de250ccb55821ec72759eaaee5e50a0d5c459e653118c07c6728e9cecabb9360b5ffbb0b66dc2fc235925656ec6bfab6a87137ccd4ff36d0ef7bc8880171bb935d22959b9de72da8eea9473c6734cbf236734ec9d3dddf204387186fc0c5b816a423676c8b578c248e492045de3a687508d894c8f4421c75677e9337f94766d7bb26063c6bff59890666afdfc8cfb82b58ba241dd15b6e0b685517984a5ce762c439cde5c2327636385b27ec203039b084f5a30ab0f9512a2f0442639d1f5a258b0225bc3937fc34e32bba3338b270b0539c3341213f3b195bf4ea8bf12e45e77882ef16b1e9983b7051231bb4569a06e9f3528a231b46e59b966ed961262030105c5dad3724e6f4afc030d05867399c6448a1c9c7de5abffbb942c9b4ddaddec2e8f341aa1c539baab28e2e960973db409c1275ed80341266c038096e1bd2c34d34d620c0d4e2e9246ac066ace3a29f684d293bb396009cc0700af0b2cd6068705512bf2d4b80d76264b0e514dd388e5c04f726bccff16157ec35364a093297ec7e56e3dc55d86cda3e44cbc54ee9ff3a8b94b20753678f47f2817f9f0f1578d52cae6850387138774ed190c313ca90acf60d260e2f710fcca03c568ea2ee3560d741500c7ba9ba66c68b171ecfb24ebf98b0e6c845cc22eb4c0805445bb1b8a1895f4f7b8c37086a55c34749edadbcf0d472b57a037dcbe0717b2e99c246a4bcaf4bee1eaab70c72109fcbe9cc67bcda582bd1f5d65583c32b3da4751bc1c3f04d6eb278837b3d066f5d80f4d3866172e4d7993f6a45ee15b55d116b034fa83daaeb57352d52a8e1f43776a060d10b6359b70b691137178fd89ee9e7582d9c44c583540aa82832d09cc096e00949f8e1ce35edbdf95331604d64110d61f46dc9f52c841a07b10e33dc67dd9a25faef39c9eeb701c39cae38f9ccd84ec7d2d897794a6e172907e64b287e0b7cef9a57ac4deda862cc215213acd21d0dd7259ee634232869506b0db9bea7345de9eb90b280b53cc23d57cf3eabe0432d5062253c9db53e11d5317187c86f725f4478368e2f41d4dd54c3e72135e86f33914a1ab23cdd57396ed553028350a3950add4bc30019754b47250744c6e6962453d06865cd854cceaa9ca7eb26709dd24a4e2a118f9680da6f1a7fc4c920a348cdbc43a21161f256dda7fa0fbff9e27f56f806403823a8de2bdcd6a77d08e74f3c1843fe11c9d958ca25d9521ac4ad461b3b3be22106973d0d439f0aae4e3800908d279395dc1ad9008b138962dacce90572cdcc41ccdbd96a5b5de3382ddaf951c7720f34d1e3b792d9054ac1d0da4df0158a3e5b3aaa277d4e3de52de7319778d72471d1b379a83e514e5b7ebc01d349d70029955f958a303506605a5d7d6bcdfd0389a6425db9beccafae4ae7eac5e27ff5756d9158d6b72b828081efb41dc7a71477a8cef2454c133ab2bc469a039d47159a941ef1573ebcb7f04666c0f734cd01b21f2ec9d4e4cce8e02c58c1a6e07f608a76dd11dd7803b3fa6bf3ed0c9402f32d8120c3f6646ceb454293b484a51d5deaacf79722f7a7eedb8cf9ee8264d4f97241261ec3ccf4a7e64fa070afee7dd2663b567455084c13d58be4e7cdeceb658ab5eb7e4575e4e5434e83d098afc293fcad89f2cc6a1ba53c441e48f940cb6211e8604915b5e6d869a41462418a7b2869314fb16f2cd2405291d45845f9fa9666070ca79a6c377418d4a36ed8cd23ba5aa5602c7d1fb7e060d8608200ddb1ee1a1d0b4748a9cc684ccb2450dbdf3c50c1946f4286184d8bb99c6b2e6f6df21ca4aaa4369d48fc1cc58cb7a997d1703f29a1e9a3a4c77e9999d84ef63f12eec118427e0ee572489cc7a851af96b540591fa3548b6a64cd2761df07f870bd60c51e3249cf327be22938778df74498fc9ea5ab39d3a997cd78ae13ae3976e52d63aafb04c0b89f556222d8f38f938ca856e0e23aca78ec01fa148cd0bd91702301679634b2a0fb64a64eabe2437fbc4aba08e8c9d2f839f4b10372b911aba1840bab2d7afdc6f80852b450948f234d0f80c0d62876caf69e730dfa8a46b49c94a92db439642f2aa9209bb82194b39a11b57750da38215f2eb48a7598ae9e0d5bf690865d8b692bc109b07e5104c7a98ae8982d5c8a6e887790ab2ba67201175c3524cf500b5a2d906b7d8a4085497773516ab50a0000df7838f81a6c9814dac5859efd087f0c94bd2c8791e7056641caf72eab597a600fb4eb15c3f85a679b8e370227633873ba1f1b96b040aaa3730ae1e3e76cd46ea3415e03b8c23b7c124bed0116f3e6a16364a051d5553b9bede0726b5b352177c71a59b99f7090dff2850a2eb5263d292b7c96683bf0e244231ac42e6c1dc61729c4f4c2be8647f8fd0a455cdf63d6a00276f002434b110d1218bac2f310ebedac12d9a12e6310dc21b2ed4e6ad60104fcc517091274e952c9ea83858fbd48cce056b22450d347da1cb4c80ec50869abf3a892b4a2344c209e374fbfa7e6e217f6ae43cd05c2cc1351751d8bd92a6b43d8975acb7e323d6a791638e6dd32f864d1b46bf5ea48207c6b1c981e5b1e9d2c1ffa9b1d90c21d57af296537ea2fb2aa096da8fd09772982b25d0967abb1feda34d09c504cba510876f50377e12cadb574ba501447b701a0dcf944455612984dc5c26142a439daa2ee43f70528c55e1c3462f428491280e34d7859ff103f3fd43a5110ad5b5c4f6e732c4929500a4e0204e4e387a095bfb506e616be9502eadd3811f9ab3547284a778f9d630d58324cebeb2128a945fab89f5b88203175ad0bf6e193d1827402c0ba48560b24405f42581132a5e499b2411d8dc17a151275520d0a28a61c5d86abd2ceb0eb70377e953c340d616c183cec0e944624a06b3759e86550c6717fb10dc5dbca1188e4689edd35ba6e17c97fe6a6a496ec8b810d186f8cbec7ffeab18f58fa161e62ca4e1ebc5b8c73e611bc625f95c51af0c88ae3bb5a037c907ea0c4160ead7cbb0e56e741637ea934940f46637686e18aa9afeb06c145f608cdfdf164329ad1f3109e0bcf0cda9a8c1565068d2c3a16e6607a6e9120b88a656b3759599a0a267e658d55470315ec2656e9063d554c84248440e751fe3f070a139f433953d9bef24e11f5753c8765d8c2a08ea4677c75dcab8a5bd12554de8f3c6cc1c1efb96d00f5c3bb09816854b4f648ff2192e05ea2c4a2bae4615efcb12ed67b93493d11a21f4ea9db8b287730e1284f8763a61fd8ad34e711e1c7776283ee49acc11049680308b237dd4d54e7267025a34e42aeaeebabe8b3957eb796de2808a9cc37cdcd6846b7aaf2e4d035697da175c28cb3039e5c6c19c86e93996bee421a2a67d0d6a767b90ae1eacf0905d5e6c8e7c7131732425d080aaa5a10a00480b0d75517c6ad1588938c6aa2d229ac377dfb1074b0c596100b59c3195e55e49f9c833518df9a533269f2b2eb4d3d88fec5b36802828088b650ce4a8d4410626b6d2e96b4a3e7e0ccaa1fd11966a975df49d9ccb11be1d695277051c1f54c14dbf7dd2fcdbbb60d26fde9609b78862e1d9dbb577a2d6931bc6a213492f9b4a0130946b4901396a58cdcd633930c9f88ac1cc7855c86ee235ade11bd9c5fbaa05b2cbd12a1d5dd3fed496793b325bf2fa48118f032e98ca7d3548fc90f3544635d5766c4657be37a2bc41d3e6817257f1ecc1823ab8b9e22808756434788cb186c5c3b64abc2fc197211c97460894f3aeec1eef0cc1054290359d98a001637a3f2cdc25cf7ac5f05fae5a11878bf4f4717b3bebdecacd925e95857764de181f95108d52dcf7ae3c8309669020734eb2c372ef21df6ec68eed31db6f8a351ab7f95c84398dc7f8b3626c4f004cb3a1d4e2b254e4a807ef0610ec8b099c8a27545e57146022206291df2210474339ad58a0101532d1757d16a8a7ded9760370a7b2888fce5f70d94a44da477a07d86556568277e01d1c24a458ff563418b6a5faf59d7c9e62f9b245c167beb5a2a8a16626aec453124a09f9e6ce0993ced93d08f7757394198938a00cb7c3299e75c46880820e23351e3395109644e1304c46c5d661ad105e2954cb7462ea00ddc76a9101dd748cbf3590ad4e6aff51545c4b6eea9e6e684cf3021ad42eb265a620fcd593aeab2988614827774b37c89b24ee5f97e5a103029cb7ebd4b94a085c138b20a031e1f08dc6581ccea4db9750d24751d092a00881a5b4caf770c5181c4110fbe4c5240841794c8c0cef2493e4b9bbe4be35d8f64ca4fc9bb839204ee44b7058035eb6584742dc47bf36b9de1625e4cf170147c768ff73ed0e26026865cee0675a9a7b70353000df263df23a08f1273db4b31df8a95e459bdc1481b181930b2c0243aeb0dbab931048f9166b82f4f2c0264b5a40bc6312c5a7fd4ad75aff1cb25568f62bddcb2aea60bcaf42a67856266e7d4725ef9ffa9463cf8578ef9d4baec3c4431d1d9fe82733a580a479068351c4af2966d4066d3d6b03a8cb5350073f96ed1a3f2a16468195018cdfd4b2b8e07cefbcadc6d7c52c9a44f69df2e7b985b423073bb02f051534923a081940b1b3ebc025c3671ac1a5f9227773e4878cf8d20b0d028a94ad0595e42d57235e19af81ef512855fb6d3409502ec25ba0ac302985daee5592dfe953c32da885ae07e0d0ec7efb4329279a4b25a244999085b8eb4409c8ef6fa552211de46f17edf326fef5344b28022a8c2110390bd9519fec17430271df681dc811dd118f48a8134c22bcc6effe49e1965a39465c8641641b2df61966352f2e3e74f883955d078ef65e2a908d350c3a7ebc7d4124fb79deeaf9784dcf27a2276c84a11789724f76a66f956a89239b9017bc71683ca2a593b6028bbab3c37bf2e11cbc5d5b32a084e16e6035ae6739eb74f365d9abaab9b98ddb4ea8c24976ed6df7e635929ded8ea2d82af3f8a36258820771f4592ce10e1e6cb9a44223c06a99cac9a4307ceb9a3cef5806da1fb9c575f5ca751f3dfb30f7aa445710bc3f22abff51e66ce1ac5ba6a981055bb542066af9a3618317dcb2776da3f4911d41bdedde3658d68791fd1d4a9801d04a81f644b8991bdbf0f9955c861f2b6c58b1e9fb39c6e35b318165722436ac9c68be56240b474e26b9ff8cfcdfefa48be864e23c0adb7782916757cd05881ab73f1f650df36018901838073806e07c708420334467f04710eda98ecc16d0eb027ec2ddacb4c1a5477ccb907f0b2c719bcdc6323b180e9eb2e39bbf19d2fef8167a00306800a652a3b01080369c2546d79e06fe028e4b97b45149d3c18153b649d43df9cfc74b4200c4f5ecdce2596e9c25c53885966cf637fbd2c1f19870b22ccc443a1f0efc7188748ec61092a8c8db62779ff70b24277ade38676e8a3a5c30859a293d4a5be2fd9363970b35268a232c3dc6992bd55b7ad5f4390bdde56516e1355ef179fe15da6162b98c4a6a6aedf5ac8c44d0902cf203332c704af1fb3ee41be46820227fe015831c3d22e484fcf6d38bfa9575e36412b84d4d82a8cdc4209f8a1a0f1c401ac47d83a65a1fe6b0bd8752491c61a2726918d8b02ce0dc053cb396b3c7e4dfa8c9b2b99827f0289a7fc0ad44c49045a7910b7b3e03df6e420ecf9544cb034da3a3cbf7008280a65fcdcefd04a632e80b93b4fe35a429e5ad791f5373e43af9beaf011a588175cf409d91be14b369409476dc604df51d2585839eba3832fc98f663929e0100d59edf24c1acec5ad046ec80946fdd1617d768822f2c8a655c678e338a761f85f29dd5ae340793e9f8d003ff9fa2f5cba2072aef710820a7baea8e0a7560030c701e12510982c7cf0590c6380607542953a9b1d4856c26cd7224e4f9c19c0ebd227aefb02ee66db545841b9e46a3607b912229c791b9a41ae17ec073d5c592188fc82af09aae5d7d3e487714a85ccf6ae4daa405aa60301161171ac209521b2aa123a4e59feb3f23abc461fd0ef02a10da412c76b7998e8cec5e8abd08a07071bc44eec0c53c68aae23b7c289c180ac9c697ca9f9135cc5887f0f9ba8893145467d7aec832bbc741fb02c5589014c38a4feebb769d8c5730e5268845242802d77594bb2bb6557ba362b6eef648137d51b40214ed5d5ead733c99c0bf6f0c7b312c02d0d62ce79e88dacb8a8cbd5e64de26c6325dcdb0ca42f71c17bf41d70a7f0cd33267b49ca7a48bc40bff81f6a2985e6587af0b86f9640348fd21d157a7a10f1fb8a6b7542bd03b719c8ecf4f57ba35507065ef9bb1d707729b3b0a46d782d391f47156603d7f08aa3cf3883d09b4e311881fad1e06ce3a150ccfc47227395ff80214378d681bf2c1511b4f7a01a9f5c2fd7389ab1caff10ae424507b75e7e95a83b07b0b4b93fa051e48ce8312507a47d3d62f3ff8612dbaa529682cac115af1874a193533ad22a60f3126ee6c17e4a505d26f07fef7f1acd6815360ab38f4f7a374b95afc09ba80aed58617476b0a535b845c13f298105216edb737d870c6a7f37ff0c9f13701251924c10272663d0283978d00634da9ebbd4acc1d8a20bd1a324ea623ae25afa2d52406833c67e9734910cb0bf3882ecbdfc86c81ce47c0366fc3ede48c88114ba6c76fc439c5485aecae365c9de62d77d61fd40116e0112636e540c90c031822035c47e104613caa34285c90e3d0b14652e390ecd38e1a94af82ddc07d13f4c860a44385953bebe51643806a16ace5d43b3d72e24f6c126fe9031136ccb3017831892067a53e0e88e8c6bdae0da06a06f13c59b4704a85628973a9b16522cf884647100278f678b9d0679fececcd576d61391f04bf78839e6042859271837e2e4455825cf1b9c105ac8d43d3d165bbf239e0107dec7fd6e9ecd20ad1557d3452a85568d2968fa3491a4030f0ef90eb8a34e17c4df69fca9a7060795cffcf5a5cfc5b4617c4bd79514eadff1871aa8474e266953fb53817bcee77682514852facb589019906b8e870bbc62b8c350a4d46ed550614a43625b02c40ebb14066ed30cca9f651fbeac760338821bb7a977b7c54f97a9e32b57d2ad0feac00b707e298fda3e6650149fd65119b33036dc718ceaf23566aff6904c3551d3fc193bbf4082c9314c8429c023ca19e2043867529a1f2e98e9b244e150b8568e1ae45f6cf5b144325b72a6861111ab3903e37879e060f5f67f88b5c4484dd162fc2a05182370ad0d094463fedf3f51702e2cf9a2379cf8f1103357098b3e984e92c42f813a9acb5f2140076c84314c5b383783bc17553417cee2a700456a0b66770c501ab4a63427cb7e99f296c09a8322fd1a7d7cc7fa34df50ff034f549ba5372e6ea76408f542b354eb0f0e2689f24f96bbdeff96d8508244b41d0fa6a62446dd2b7e1ec75a22371a6167ca6b66c3b5890eccbbeb255b4c554660b897b1a98686db84fd271baac2a14ccfefff541c66819a3a4686889cef325221f99c7ea59e7c36b92018716702fe2f909c98617acc3c18e9b8106120c652985e00acc36fa946d8703b0f4aba35ce2caa56709c09257efc925eaed6cc9c283ac3c712369bd338cc58ba08fb328bb46b67e74e0878dfe5ac82cd9e54cc30306c7258925aa7f5237d3d729b303d4afa799d717c22a09d9d1efe2cb78273d276f91d8cfba78d38fcb4ebf8d52c20811188daf8ff1c79a576190da947d736e0d6160e87102db4c8aa016ccff392b0df52ab645a15f6cc210465286bd4a5f9029b50cbb686f79fa5545ea7f3d18e61e594a5aa56203d99cbe86c57edaa20fae69af552d8a67b6fff4accfcf1dad99b0203808677a682406c5331e4ed916862856151023b93acbcc8867cf333e5ce8f2a52b1cb0e380e646b1cff78f5447cd003b0a0f01fc334d0523a82e40b543eae08a1a8a1ac836f9b53a9d3caef151cb6b35dcad4c686cc994bc641c237f09cb04e33d276b79a5c982e3726438c43b6c4b857161afd452f7853556bacaecdbec355f10f570286dcc730876798d59f138cd05920f680b5feed60757d50e25b435edc80ef485836ff6337037d09540a3757af938f12f140e086eb42041331465ac59be6fe5e5b2367d396f692270d0996c193296b87b268ae5623f28f6c79b4045afd9e8d54d5cd3496a529dc8f05f33f1e4858099b2e854e24a4311341cc10f5d190f2149f265a7891a3f2725096d8363504383677a5036ea8d2f31da5952a4dbb29b8923d76cd830c4fad417fd25b4de8ac12c6bc6d85320f1040501a5535eb772706c6dd6d631dc867caac94fbb9343aa1492df7bb237680d9880bdb01d99b128b8e449a73baa4cfc1b45f0ce75517aebdb31358eb0c6e778c94639f9102670878548e6fabafc29932ca5f928455ec5d7bf467dc45d5762464538e1ab27aff825a4ffa07df6716e2c0a320d5e5448d95a35c43b2b5d7ccd1192d8a1835605b8a1e3306e83b2c115a155e3842d23fe74830f928acb1e98b61cefcdcb783a1120553b675050d11750cfadd13bf5b601ea0f71f84a542d7d6b337502acddd7b4a33b05bf6724fec9af92a5ebf56d89291d99622b071394bc05c9d1ea4a0c61eff09441ae2a43ccbf4382dc9f8166529abf7c91d5e756252c541ea699fe1e0bd70b3bb938c9ad2ee86d50256b6effa9e221c75736b8c86772eb0fdc67d48dcddeb8ccd6bfd0d210bc2d9dd7552b8c75b30b201dcf5d60ba4ffe920cd4385087c91f1733df89339ae313f91847123919b36f45b4c1b817f789112940397852096ebcbe45f801a0c7b0bd718413e4fd2e200525658c5bf49b1404530cf3037efdbd43b70343f6585ac80e0d9bf12c26d4250852d21e3d27db342164dab1c90967b7f584d34c464fe9e2e911da123ad11386a4210246e189a4010c46af321488a1bdbc78d8484ab7bc7e03d5849fc726790482df13ba7b7222cba280ce2b5fd2068f2eb4e6933012ee4d6b3902153b874acb0a46def82344c360dfc72a5a1e0fb09b6c252c397353bc08fb6f3ad1ce43f323c9f25f69dfcdf4f00c06a64fbe38e94fe2ad6a32c0166d0830c59e40ac178dd863667c8d593da4c804d9c7e8d37d21126681becbe56de1cc15013a1e502b0c63deb08278cc38daf1dd1bf70078e2d3e59bef461cf21f3fc84a6effd4a1cdfc5fd9b6866bafe0f48afa90a1b09388cc169ca6e5ffdc050f195c812b03780ba101734003c409e992857be0c9cbcbc2ae575480e6d9ad334e847f6641ada5506fdeb9e225e10ee23fcdc572e6864e0161eef8f5248a29a801af8729639813b12f8a6d04785532144c3daac17eae820476c6100e9ea60eea31b373fd5e894f01b80defc24b6c45a37b9b81eb9aa918ac1b0f83266909a21bf6713ab982e6583c8362e2e853dbb5c7d2d8242f48ec6041f84f97614f0173424090fd0b24ba3a1acb49bac01b3627fa6dcc0c30c5e012ad424d8e6e07eed847cb99cb0f23652e350d105f7716a59450668c1893046e847b403f19d98ff5346207d13843ab27bcfa331c5acc6e174f52e960e664067779bbcaa8b47699336bb514d72f048dc04ab132b536bbe181fea7cb7cdc30e8c4c377b17c8baaaa85ffcc9ccb9d7792e7d06e3ddc484a0230dcbb5c4f89bf212b4eb721e694f17b8f6b43c5b81f815b6036e6d36b8487e30232e5e77f580f989d9988b8843ffb9fb8aab71e98829c26d2808b38993ed66802858636f4e13af5615367ea0c7312003a1af03e093780bf5f511e5719df5bb319cb5debee0278272c1460b069c115bf1b7c1412af8c5dd9d02bcecddf5d68c0401282ef71ca056f23d79c9dc354770194ac709a4a3346cdbb5e3dee121c6b95016a5a2ebdaadc7afd0f519b04027133b3ed3a258425cffd3d93b8f965c610b182a89a87efc04a2360f3e8e915d088442bfbd88977db16612eee5400f3ac543c28460813d2b3f98c7ccfd9565f7c11d29f10151916523039766eebcc19f3f59f5be411027183a1aa9431a4e0f88f8054a198355f1becc27b02ad6b599bb6ee66776b81807368edb64e3038f68da68b4ead5cf2e565fda4b13b91003af528f62ac10c34ee57bb803133ce04a3091a02c3c84cc0e0b915d1127207e29f1cf1634bde55452b2088311bca41c306f53eb608b919ca510ac3b1a909dbb8b3fff5745556e51750579b30ce90eabee6497ff402d641d2e40becc2856bd2b9937528f235c275ef147520c670e400d069243d91fd589d732d0405dc9554ead18b49ba7ec944f87629c486e0616c681e028a03efb2ba762a76eef2d4e67d17abf15bbd03d6fa25cd2a9b13bda55fb4cff8d69cd6b32d82067f19da5d3641072bf83c18da031c3cc0778f8e2aee0970a77f2cf7e0ce5721f25a44479db6e820baf11c384a35760fcba5f25d791d49e94073a75a610e431904b88f00f50882fbd8bf06e51277be9873063430890486d48c39f9c1d02de6538908bada4d5ae7e56eca04740b2ae4c84cbfbe2b4b668c1a01341f024a80ed4a5b505a15a50d39c504355366f199948ea23885f50c9668723cbbd251e5cc8584ceabe00a25cf6c362eab2e6e0d5a55b67b608062089c64c6423555970abadf88a838f5ae51c30362b14516510ffd2a43fb4d6493c84d24b2bb7bd30e6c049e04c20436b896f92f68728c8854234452915a0ccd45ce9f9c5dd49ff3ab7ddbe489b49339d11b8a7632a159c96d2feaa28ae8f3c117bee15a1c976ec0cf5bd0b5175b283f396b179a26c827e55ba4bc8e9759f12c344d90fc3a5e46f42a9a46c7cba8c8e2d3eedbac3eed66363c6d7eaca075bd9d411909cb6af8e793b2822261c876dbbaec0e5e37281ff31af06450321264996fcf176915da3d1a9f0c03226fce880d3740173bedcd1d790e7b3080f0b497a14883a31124c1cc2343086f0fa39c7f0fc6f75e7c8f44720d39ab38f8ae6d031b6622cc88bcc5fd36ba698683cb788c4e678cd5cd56774824820ce373e9c13a27df424dff06f431af445f6882dc7711deab6f408f1f8e94f4589e0dc209cdef49096b9554d62a2b29abf516a5d37dcb04441cd0b25e4a6b2ba6d75f5f7dd259ab6a5e4bab29a7b6de927252907503ca488f4593228c7a624c69bdf0521a4bd8b510466c5575ce29e7b4b2d6789abd41c818669713190a49028f5d3976684d2ed4d8477dbd3531c125ecf311872da6af6c060989ac3f27528b01bfc235d02d7392874bd75b78cbac463643939ef6dec4b0f94f7bb4caff7c26a552425861098adeabf4edc99d5aca39a1db1fed6635eb8510c20927fe146c5515d229259d77ce89b17d6bbf82e6db0987c8d9db8cfd5e7e2f4e7043b5ee70777fdbc35a6b2da85a90b515044ac282acb5d6da7fb8e292ad1ea4dd067d6a0581fe56f75a7bef5b9d92b10b5b6b2f080402555012950402a8aa2a0afaeac7a65f6d37841e3e76f5b4c2409fefc56f2fabaaeeb5aa7b2d7661cbaadee4abafac1bd238e0be6f62dd6befc5185fd7c51883beaa2a7a2f06b29f4fce39672266548c70910b95301deefe26183204f58319d8f8c18d0f144693ef1588101922c48f2142a8605b1f29ac87517d777deebdaecf65bd756ce5e7fa5c178cb884c37e0d6ee380df82f8635e65dfd2fe2caeb2dc44f64f72c4de5b21c1c8c6ae52ccc397e2d2fbbe17ab187e9886cfad744e8284276cac3d7fc52e092aecd85512537862576f73a5f6f9bb360c6cadfa80b04a4f2e2e55d775522bb56acd6e7faadb9662fa57576f7d573b3fb6db17cd2eed36e643c56e1dc24614c51345f15f78957e3276fe96dc84def54de87128a4571ecb7ceb184a0565b3a7b5314fce0fc5256bafe352fe7cdec60bf1e76d57e4083451fb36c11f89ddbf8e987cd529d8bbcada6b551ffcf9bb9d10546a63176b0dbb54e7cfa88c69b6db0951a2091b6f25d96e57c40850d8f42d7633fe9cccbb5d11233cb1e9db4b0317c8e482f087d65b41d704c34c40f7deebb2f7de14f7047f7ed614f7edcf473bebdeb729a5d785d116f0b02841bef7b15c2f5c38841551e728cdce519d726d55297598629c5280e9bed2af9afea42e535da5acc17921046fad9faba7150eb8b34ec9f8da6955d7d7bfbe7eb53eae3ead324f76db2971d3c416d1f0767e9a7c8a12f3223600caf5d7d7e7725d55b6e5d835bb9664f75357f7dd475caab47533916b71ef78b6abaa3cadd729753a5aab55bdf5ae9ace55576bb5eadbea2c2bab545e45d8dc05e84cd80b6b856e9f28b203ae6bfcaae357f2e54b2d0add87f960f9928c6449deeecd56522a2584904629212542b33717fb59e83f5dfa7b8ca116d83c9989218490cab7733a3a350f4f7b3e03596e4096f723e937b8014f06673b6024b8015f38e02cef7dd84f04fbbdf42032920db896b7c3147ae4b4d99b13512bfb4e7830ca272c5eecf7db8a9c85eb6eac5bd97c465f4a64b4ec36abea134af8f213e528bfbed4a59861ad22d7f45a92614662df08be40c059de27d9ef371214b6b3c27eff00d7f2fe866b91414672e369ef311fb20d1b5ee460287c3884676f2e8afd1ed2e7ea7b2fc405218ed8f3dfdbbe3f6b0128c90e9758829043ae11216f23a723041222a89f7b95952c060c13b27b98cde9b28799e8e1743038b89cadc3db381c8a1d71d0a16ef939ccfdf684710cbe6f1c2e8a2876cc82c84113e5d304f1d7a1c177ef2285dd1d88cdb1ddcc2c003f3e8f80a5d13192d1f1321ff0286482a4d050778e9d63bb8f6e01d67daef8723055e790811c3b071c34c776b814c56e61e30abb425f46a41a310320c001eec3fa06c8c2e369b092318f3aeac283d3f88ea78968763fcef7de93fe64b6c392bccd4851c004f93e0dba6d460c84fecfb3f8b419a416c4b7e3f178a6bbe10d39ecf05c248cd5e501b7d7a326d63ccdc7a301dfba94d5d65a6bad94c65adf5a6badb556167b3c0d42b13914faf1781a7cf854bf9e07059c793b3e2fc89b4301c57371f16843737e64a763e231edecba9d8e0965ca79808ee96402b29d8ea9663b13101b6fa763a2d98e8047dfb3ec2fa967af5691e83d0743add9082c243f67d91ad430fcc576f0dfcc8c3f25acbf00a4909fc3253f226f2a2a2ba4183566bcb84c10eb48f0c58180663b1d1d40f6cb763a3fa4b6755cb2f15c66c418f1448ffdbe864391f63bc9c5e5580109978385d47e5fe321b17fbf8fe160e0b6f2785e129450a2081326ba5d11267450224e3dae18a37b8c1e9fe83d27d3f7ec629f33c619618c32468ff2212e418ff4cedf28a55f69e51801a3bd8576b2dba34d33774397cf1963ac2a95d1b2ac65552fbb8aa841581d358561a12cdf39d4761cc83231f881d66893a025c0019e4b7e571fe793c1878ee338f46db6917ae83b7d8aeaa13487441a8d34ed5f34034d94866674e6ed4b3f17b6dc1d6bfab6d22d2a8128facef1475cc2d8e7c2f1c82681a0f69c3990657ead398b44ff9a361a45257bfec47e9340e890a7cd0f69aa93536bce22d1bfa68d46dbccd9f37186049ce48817f6491561222c58b2e963222c70c2c634a33bf00ca5b1ae0a9770cdf8ad09f6b9b0090863ec628cf1a4a04bcfc7f446af7e17c6d87d17068152a0a05cdc8299bd552ac09ad24b48ddba4d10c294e505f8ee8b4a26866fa312ecb6c30ec82173a38d430ae35c22c24a90e16f195a5978d6a9b4a8d9ba2aece2dd5b2f819ed2bf35484fa381827c7f239dc87a6b0d3567faf97c3e1ff328a59f9c93cceaa2689761a13225ca5b2b89b522ed322e740bed3029887a234aa16b5c92c5d4a1bd4ba43090f67dc17741185ba26757fd40263530c9e40221210454df0a973e353ef6b9db8c629a5d4e647a820f5d6267577f3056d6bc18e05ae6a35caa53bc057ad0bb5d99bcc9bb6d750a0dcf6dbb628926ec7a23ba4179abe29ec4d18c94894b01ae09d96fee09a1dfbc07ed37ffc0ca6f0e8293dfdc0530fce630d8307ef39bdfdc072e7e7320fce6426eb88ea37678760072c2c9a9f11ddb4d355e53e3364a70526e8627efeccc9e9a9ad90359660d64c93a86cffae1e03c9c87f37620cb7c3d9065c29a9d9db7e35e53536b6a7626dc812c13f64096f9383b383b383b3bbae618b4db5105cea5fe5481d366cddb812f15b553513bf35f0f7ca1a9d4eb49bd9ed4eba9812f1485aa41d5a06a70e00b3d9d704e38279c3d1feec017ba03e1cece9e0f7be0cb4c411f0e26fffc87d333610fecd95906172fe4b6706ec73168dff461475454ce343b81018676216d85a660b8e0452d8626c3c7bcb8610ee593b7d5fc95af2a19429614a9884e422193d7d5044e9b9fe913ecf9a819ecc943d260229f585a8d5826263aa7f8ac2d3d813c6d3e48cfd7b3e669f3353d61d0d3859e2fb40ea2ad3d0cad8368c3f815ad8368af3ca67510edff4ceb20dad9575a07d106d9d8ecd8449b1e9c8bf6f3e78c8361897586c0b9c0f8f973878389e167ac354f209ccbcacf9f2607f3e2e74f153897ece74f1738977f39236d204b8d8381e1e74f1b07a35fb463338b702ea09fd2c1b8f8297920cb7c51ce39def36a6af6ac3adb7b5f126aad24d626b13789c549ec95c4cecb42fba6299f21732e4345fba6945294542a95aaae088542a154dc0b97688b98035f280a9583ca41e5ecf9a719f8424dd206becc13cf89e7c43333434d33534e69939a2f73e0cb44491ef8324f2edac0179a722cf35139a81c54ce16e52c796acd34355f9e5268df2643a87c4a906233b3a2d2024abc8248d36460d1301ca0a05818876f160fe3619cc40063c58aabf236c5e4a668dfa1172ba7d3e904c3052917c6e13be5adcaa5ba9a5668df263064ba9a9ee69ee8b79c0190b9c7830613d955f28ab72c2ed5ff573f0b16208cc337cadb16976ad05b5cb20ffab800b56811c2387c8bdea6b82ab4ef79822f1525caf994d5d3a5ba456da1b315f20c79ab50a4f6fcaac773d9ea129ae7b2553daa9af9d58e0ac55ce22eb504aecd9f9504ae9ac0b5cc6fa1abc9b5f915957f8a72ce6fb38ae6699347a966158a6a860ad9e7bb50c1387cab785be9556be05ae6db4a753da29e50906b8f141ed5948287ad9f900986d94a5d0a8be1b6187571be054948aa413a39c93e781ac9d3886b99a1b72737d7fa1597aaadbf8d422626b5d66ca29e36ff444ff434ff8230df16f4b6630cbba1266aa2266adaf33f5695822ff5345333b5ffd2156bd326a289ed36095ccb49881a2406f534c49e4fb37adaf33fb8f29842de26aaf2d8f3276a1a91a26b73f6561151bd781008c2ba95ad3a79f59bfb0112560001d86e63d1121b55db39293c1dc8421a59d936d2b47fd1c8079741e95b4f25fc410a3bf2401f7c06e9c365bc278d469af6af13757c90d4f2c8035f68cd5487ea501daa4391b817a94375e08b0402a50f9f4122e132de8bb690abb01f75628bb204a2b39f44626fd2875cf2c312f6469558b287e06414c1e9b89619509d132852a9b6a23287b2a45a0ccdb2e40fd7e2b8247fb89657dfe29b1dfd299dd24cda3cedbd0e7ca1447096f74650024dc2e3da396da349ecf7124891fdfe5122b88cf74ee420a149a043844087407564903749757ee0cff5246cf656d12063eeeed5491309d54a77762d32d4bc4aeb0f36ba751d8eea631e0ef6e9c7bcb90b283e303d762def4550679761882cbaa1d0cbd95b4889ec60721332dcae084e137b3e7cd485f115803304c6874b49885b49aeb62b8283da95ac605555959cd7c6c39e598d8ece3985b0ef3d0d8c60c7856f071fb529ff7e942564f7f006fe25172d58a8a4ac4011a9487112320161f973e16badaad229237c37f063de7b306382cd7492557d5b225186d57b3bf8c0a384488f144da4522929638b91f6953e199dbb6c2d52b8ab34e67db6d50de1abf41d8b9307e38a9311b37f1a8c99b6e98721aeac38edff35389d8200072719b3f25eb06b847348355aa5f896045f6cd8802f375c8b83f5524bbf3a5e3de95fdac948eddb7232766aefe1b675f3f9aabdc78e97b91ed3343a5ee6fa07dd4d19d7d43893efa00ec6a5696f4e032b454fca9aa59c9287685da758f92996fc944a4af7397dc619e743e8526aef61ef68c6c8aa2eab0a7eaa164373298358c10b2c106e32597ce5909cbdf9f5b14fcfe07a9f81282050a8f836274b581b2f94a3a2b382723c970dcf657e7cf9bc7b6ae303389628851a7c01fdfbd7b411696343de8b9b4059356272264c4d60b566a953eae44738ce63813b066089377328432861bd55feca57559da2593fda7120cbfb4bbf93dbc059de9b88e040dc06aebdbf2107fb3d911d42d88f07560d4e27223ff6e654a0369e0b8cf6b1f801424a2db450baffa63e4cb6aae857d423a5558a252774a7d42975890d20afe0811c4b3a50d50a4935ab2aca5955b172277820c713f13db0290db54e1e3ab0e97b759f6bcbb1825d1f42f798122b8fd1b2248455156315530ae02fdf2b5adfab62b6d19945602b0c22b2c826db53c69d9c5a2bbf567c7f817b166e06b77119efddbbaf6af98ee7bb4b49a65fbd755195363e83077132de7b90fdbcb20ebe256e63fd2a1dffdec7a513023cfa281ccdc0de5639630650611faf24a90609b3277e43023b6e7d34d243e79452da702859ab472d86267d56afe3651ce7d128ddca55e002f2e9ac247ed737a0bf380a99d2f8d661f9b69dff6cf419a729803fc631cb4d64cb5e0cfb98274b9685a120bfd84e2705355bea7ce488dbf6e4620dd23441b0fcf288c396d7c0b5f8e9942da812f2b17e22311d3f6bc779daa341ae70cc2e2732b5212f596fb1102342767cabe2c4dac16347c65b498e6f3107310cc3b047df618f3a2771894bd563782bc951668ea3c2e9a36076071e52a4c97b98fc3d951ce35f5c8a37e4f0b4f7aeb32caee304f8c78f568cd5db5535010a5c17684efaf46d8a1bebc3ca666fde8308ed73f8de8c260ee445fdb6ad3456af799a0fafa966742097e2527d3a758a4fe94ee9cf38a7fb74777fea3e8f78da734933fff1b49891f8e9693b2fc99bfff01fcf055af7d621a7bd790f54541ccc8b70bb008a8074a5e460e65f98c6d602512f9c0d29df8fa08df73b5ccaa1523484c88f4a3921a4da4f4f7b514e29b5185a554157f1055ccb2b5da05654cae955cd625681a7bd1d3630e960bf1fd83c41b1768fc6e63bb08115f06470e6181037c01737c206ae6dae83192fc2b53c07e244de9c920a5c007fae3c626faec48a8359713070db97f281cae6de19aec7bfc18f8bf51b0cdbc5707f733e00fde68080fde68498fce690fc6f0194d3a8240d5a286a0a158d0400401100e3154000200c0c08c4c170482810865d6f0714800f6d8c4a6c409b0a64c22487811004419031c6180308018018008c4186868a373ceb889ab62e7f4f3c07477f6c2aeeb7cc32c893a3036b6c62352f04bca0129a77ef0cabf71f802d43394a46efbe749a06bc366826e0d686f21a2b406e1d3ccab70c3c151127c916cf3b8d4825ca1bb11fae046b392cf563366a5db455117661bac5b6ac3ddd3dbaa744009e24489406c87c29e2229b1283235c40cdbf00d95df90ed7001157b4011121876bfabc3ad98811cbb04d5bb0065327b485d198a4e5a9b24185871c0f8e930ae5a2097228a321e8c082d6436a0d0bfdfa0e041b1a9bce2e31462c78e425bfe1e8bd545aa1144f1db7159ff8983626d49337a1a090b2813bad3483e8002fcf8ce3b4e833705d26778b037caa71058d0e33118419c4fd922cf84dfa1163cbc9ad25ce4a15f6780033b133f4f598c2067db1f9358004f6a8e88f09b2627092807604c9e7fc7fc67b5d3be0b696a4d9d708ffef83bda27b3df82a9f60fd03c83a7cb24fabea80e999ce1502998adf61969f98fa9459011cc4a9e24c66cd572f4da29975db435cc4a94422e732b3c0b12ae69ee21d98e5e50ecc14082ff08c3328410ca6f2ed42d7c1dcd650dd25c2dc64e40de4605d86681afaa6fa0bed45f1ed026b274ab37a169c80a1a1049e50f189e75dea84ba4487e2f31a21e07bc0e19281957bcb20d71117ab83c644eea086d73e3f4e754a04f037c5c425a20a4158405e43660eb97e3d5c0149f24554e2b379c70a88a4ff0370a9f5b9e4b1529ec921b0551f503a485a0db694e2ac3d20fe91bb6239be4fb544204ed92f204dc0997b80b4e569a689cef3a963931a7f4efd3ea0d9d83a019314f9011081135c9348bfcf6d907a7b05a2b37cfed4074d5ae5ddb3e1f49c4a0ccb2bdff94bf1c40c1a82b6841f53ff7f4eb138b8a07054ae1b9d829f1db0329764bec06c334e1b5f6dfb9a9446877912a220cf18a8ee39eddeab0fbd1c37547dadaf80fe88652ec950e42aa20d7a72c4e70b65295c9e86f8fed0f0a20534203608a21fe93ffbd436e35b150e431ced0ba822272813d595b30dcf3bd3e9f6ed4381c6149421bf37dd148cace07d2c66a5a82cd51eb5ecd07216a4d85187bb23be0c6926cabe8f80caffd7a7af5af062e93b237901e02b60fb756c5addbe3bea6d8c1e2e95d5f1a1e08ef0824fc40e140d13e78c4a7329ac513e017adc30904607ea2dc5ad315f11daa130e4faaa7fee644c59a19ca17151a913a49d9fe7de933822722d90848c38bab2475bb50941c661c08f6d0bbf73831697b0636339951060e22625d483ea343ce33868322d16ce53d9d596e100c661b8a51923d8236aa45f2688d8d4ec98a8b7d8689caaf837f8781e36fa7387c79099991bf66138d5ee4018a73b6ec84280ebb08f8d6a5f17eca4d1b1f08ce44368e829bde845eac8bdc7497bcb20af037bea923a621aedb60d95c19deae399e99cd6c1dd64997d661c0706b43b1433dbc4cd0cdbff3c2173ae084b7b010bc7118aa108b039dd5b61b695779873c0b8e5319b8ed65c36a00637f123246314e5cedff23659eb47dc9684c868164733f1f96e84d211a88a66d6c7d5ac6db0972be4cf9384dc20b43e738a3e769d0764304be9db95861325240ffe5a01e73c0416d8b53580cd977fd010ea93c427776f1a71fe86c7f9db27d6ba38e30b449c376a3814a5cc0a9f72d1d322f8c9a1439cc418b2d34ada2ea969ff29fd3ec6a84556caa597862a43a5b47439d1b15745715baed5a4708aa1dd5f62532ecf8e22f05bbaac09279982720ca2252fd4d3777ae479ce1da694fe75fb8f98c07a8c3528566869df9b9e5f8c6197d42293a3c305b1da24ba1ab842516b480016070d0c2296024bf3c60b52fc377766c088959cf70db764a2bef9cab5ebd663ab646cc73c8d18cfa647029ad8a7bb51439f039f50efbe1db43533f01f9fe09bf60e90fdcb795e7f3e9bb1743c023d47e9f4afe8c8f12a0cbb5a2c556f3f09dba8370d18c83db9eebcd8b881de6acd0c1c6c3453a7cac00c3526b138e9683351f00d87c1f71ec4b967c181686348bc346138dad3f27edb4d1bd2f267748e6acc96514c5a61743e926e1e933a62bc438ff37dec10bd15c15c6f0d92238c3b3ddf412474c4f1042b6b55e6a0e111f58a8ee214bd96ebcd93f191b5b0fb4ab3a2fd0e813e28a1e94ae822131f2dd48ff6b017579a49405d9d2d4309f845e161714b681b1c37b507cb1332bf3113588fa8f71999fa8b903fb3aedaf66dc0d845f27114eada909106ace09a6b1579704ba14f3c326d9f2e33a0277b2c9ed0755db45635fba783c1c9d432356bf11bd80136c0ae7ed67e1f95f0c4530179ab126305c3957b51b16fa70afe4786c066465f59ff707396e508aeb5b30493036b031f7f125ac0f9658b86e0019cf34078e109192a2a43f3bc64e00db846f7f41651f1a582273625c643f6f292d0a70091c0b923f81ffa14cf83d3187e52bc5419cf8922b2fb1fd72363eebb7486aba1f1fd9b2f7a7d3f96ee746df7486f4b73bce5664083b7df7bd396cd44989559293f2a0734cc3d77804613c828180efbac6f0e69b2adf797fe64710043ce58535fba064bd5c980a5f2c7a750b155149322c6eb361d2957486aa1e94b7044d5510898881ad0228519ba8b808057b38f9e2aa09af7e3d82140ff7de5a56f3379c91a62b5c3e53512a1d3ca26e2aabc21dcee7c2b68935e993b2500784ab651afccdc1ef90f31b3a7c400058e5bf36be02d07f250dcf102bc52fa921377338c048420e4416e40a7f83a7373a2f2ec0205bef7d0b663ececdcd9ae78db71f886757c41f482152d0fb1ce383961c435e035101b998782a7fb2b310463894b02315f1dcce191795f026986d08ff9d415d2dea7223dcedfc0a27dbeabdb9310fb8bb11f9788b43b5c187889705c826a34d8be826b99c1f0ad1b05c155fa63d4d853185abfa69f7907f0979954a83d2d589d73f8980379058cc71be7c2ebbc5f6a183eb5565646e0453dd386a6bcb74ccbfa7b052355b9077e1ed2b58f156fb455691b3693923fe31f365b932b2d847449a3d89c0f589a16eb476cc9de8c09311fc40f988ac8c6d7a87aa8319d41734106a6921bb207363fd9f77057f39052e9f0846ba34e5d37a455e836fa964c1894aa3043ca2041b2f71523648b7283c7ad32a1ca1d010630db6d975063bfbafcae09261544cd3bcb0a4314cce609f42060c052c2141e1d6ac7b1da40549fbf893d07ef27a3285b355e2e1c78cfb8cfc1fbf368538e0d73b567a0e9f1323f244178dcfe53c46a906ed029758c18a6bc5343829c7b354af4cdc9c212e76cb19f871a3432a06f4d47e3406ad98299b60a238ccca64829a9aa0a66d0fd834112a00c0bfdd4efab4c10112121832f79cbf614886e9ff5df8435598dfadb3c551ab4122cb80f250ec86b7517b445fc5b4945eae6ba08a64545370a6e25ee7aa4c51c19c68340ab610cfaca404b4f5b4aa0a032e46d641f36a6233eb0df827c1b9d78904b482096cd9c747ea3a03a1e1ec89613b572fb8ef406704971250f932b8a89d32fe8834f89c22a31745a177ff0eab68eb8154f77a23f4d8f492b5194685237f3e8824cdb901ccb0ca719e40d849ab0bca44c9a8aedbea6b0d480fa23e5d0e8101cd7b06cac46c3e47899dcb8c5d48ea10a9716ec876b848b53615aedbb78caac651c5c80713b9597ec14911516a5701741f2f3a541a8e6799e13f931c159a382fcc914fd5b3160f31ff247d4989a20b8517f0ba342744c17cb4f567e68138e736d0462a1979cb8744398e2f5d81b1a28555847e2661a030e4afe5691480f364ff3992abf4bfcc3fde743c11e35a4cb241f721257437ccd0f05d151bc1becffb0e372723d358448a4ab4eddedd598048aa5893143a122b00a28a6deca0de8023bba1ec1184fd846448ade72335bd62e80f4ffd6f28cc1cb3740fb5a199238ddc09ee424d6b10f4fa9a2f5ab923c927f9c3b3b2b32ffc45418c04b41c5733c61e67b3549697bf3591c67a73e03c6361045427f4acb495433e06889880086e4baf9b44f54b6775a574f68b3ab9189091da6ce59843b416c636e15ce52eedc79afa5778723158ab00447b2d9011bab3a4ceb2e156420c85b7cca6a804640b318f8ca5bedc2ea9959de2710bb67f37dd36078e7be747ff41cd143273818c4d9004b6e15a8d8f513e2621a8729177eb58dd03bcfe7eeb346cc3f20c9cf762df8afcc32afcbfd38aeac00d6bac789f9745d7a12b79bc2cd0986cc6e5a2e8db8a9b143b2898fcced2b83e3c5ca4fad55098207553c0b1f6cce25b0d102fb3ab1b1d339062b090b36a46b22aa1082902057474d86f398c9e49cbff79037a39d398b2d290db17b27911bd880e047eeb49c6f3bddce26510e50a76647b4ce67b897082fb8964ad672455198e9e0ff9a147e29fb1aa88c825e88c40d3a5646d49dae200a24f9e1c37523349d592e7ed226dd8cce74b31a4420d410af150471a475ccb1e244b3767e0d28d0b1f5db56ef34847ba9bb1b035cd6b607e518dfac5fc84160369bfab727af3b19d3a2055959f4271b11f464570441f28c09907862ff087556d78e49758c0fa663c008f9707dfb250c00c3c8c47c77fd920885b1b3638a036e6700e4db1320de0f5aab859c5cbf18b4b77d90c7c53c31760b7c142ef9f1c08768f3768c3520cb8659b7c82734881a73d7e2db4ecd6f611e21196d6098fee9584065e8a3dacd81a0a95ba39553f2ba99aa5e111ab7975a30a066d2203a08076863ec77e65792f2dbcb713185a718bde649c107d178d777d3d78230eb6fcdb205a56cc0b4ea91f86d4361790d13ee3ee647cbe113f23f6083c20cbc6df6a2a464a4b868e469f313d1b4793874903ccb86ae5e593cc6744f5f6920b20f71d6834997eb1d9cc2c89c11444bec61de0c7dc710cefe6909369de4a8a0e43d578d08e7b628c84ddeaf99884b682ed9607d6ea5267e92f1c4273af73ebf119c3cc4d4f010de64180962566c1663ef7c322eb567da0f96e1ed12f243110e1f90bddd08c0d8750e45d37613718171b7e7061730f66c10b64798e1055422065e3a33b791e7d624e5432d21601fc81f61791f027bc0fd10a0a4ac6b3a8809d196261188039169cf35eaaab489284d7cd1ecb14cc19806345c308f532022dc237ad8a7b3bc126f06fb25f2b99348e6aec6183a2c97ceefaa6496d971fff5f2b1940939bf46b06a2cc455e255f9c48ecffeaa87c67480d42541db3c4fcb47136e9c179263c5d0980be2283993c928a05a495c44cc6449338592b5741f6f3c9344156ff1c791d55d766c4724d807e591cb6da38d1cb70366dc4733c91231fbe08a134dd97b36b706d204d45e3252930d636f0789a5148a1679f80a8dbc4f08d926c58964c7e5385c0ac95b63c9196ef1b1c65724aa7bf9e983012a64ee8816cd2f4ab27e5926f392bdf145eac6b5f9d1a8751647f927ea7b2bcb79bd3071b71c13347eb1c09ad8693d6c865dd88fe8cee09d6dd88b7ce38ff246f870049b7c5b5af8c8251b62370088fd8f208d15f9e090ed8e2e822fe037087709c320d8003ffabfed9fa68c2cec12302df112af47fa053844034d811add844d2f7c6614cca61e303173b59eb96dadc3db381bd824464569a69398fe99537bb57f4320fcb6e00747c2c752860fc251701398d37b3e9e8b2918f06583f6bb7bf43d9644706bbb794d40c675b1d6e73e6bd347fd4489ff9c844154c8a63748e0db0b177aededf5629e7b7a6b984ddb319eb83f852c1328ff80bba0fbfa40ce2ecd0d10f80c0c3f31484386b08fe0893d1ffe7dfde3440ea44df8caf88f99fc802349caaa7863b7f11031042a930c0cc11f244de108c559033e0c8cfc4ec7a3af8209f305cb2144ab66316f8e8595659002040b2fd6eb629b051d86645666ccac6866f2bebaefd86a096b3edad27012bda6ebc5d62a6afbfd6540ada5e235721510e34825a8f72d67e23836cf36f505c011f3b5747e1ffb4ed4846d230ec82ec6ba274a11e7180ae1ac3f0173efabb17b86105c52f05ae0e2470208b9ccf444e0e952791956e3ee33ebf1032fd13bf7fba73b0cf57a7757f1f84133f004d229bfdc63b81996839f5b302492eda84056a01a8649f81400d0070e618dd062ca6e15e15b425c2ed0f6b7c16a1c35e8f45f529b0b65695c7a781131d86357924f45ad0ba70c89f5bf9c9de118258d112775b87601a33294b007a28dc4d10f217ce233a90230f72ee3661766054eb2b4e891a13f1e211bea653749d67e4e1e916cabbb19f21961c2c8b77aae9172b0df7e2c96e59cbc70579e442cef270b281a34ea4dcc4d7a6e6dfe7f694c447b6c777e8fddae9f45da0ee07068835c4bba751e8dff57e3c399c13d7f7099fb3f1f6c9f49ee71f6df7279381f9c48822e72d8a11e3930fbc05a27e1c2a9aa952853e5ce6cc520bd4bc1071e821274803a3ff7e04823ba2bd4ef97c4119ced7a551522f3cf6ebe918bea12d05f80763e16e18e15b1812f2348637dd3e6cbb5551d8e43ab12507967561afa534d5093263f612ee03c1ca0ccdca97331b45bfa78135669d4f56efb6d6c5d1f0a2b28437888225c2f2e8d3f320aae8f1715cb7d8957cf8a6f0ccbe7accea70b08f4f3b86a23ccbbd29cbb34086fdbabd0b1c5159a515972c3ed1b33f8557e21a89bc15a9cf05f4a86b47892d7ef40316ed426cde968e788caed2171098f8eccd818b7fffff4644ba0005dcecf0c1c0b19eeac201b42283ba00b1b0e11cbc58b1d462b0f82c92098ae6b1c0025bd567c878eb6d627b7c0182002149e173561d0fd346103366ed8d2442f8229a16f9978876537c37588efb28a4f35bc355a5241bdc69c0699caea0a793227b41548c91d697a505cc29cc258fe06e79713483a94b7579e9606607faac010654efa8b2638f65af4a0af25c43d556e61eccb60f4b775d5e6f2836d6c4e23d33919cdb31270d50792c2de48a4e49cd60c376031e6d3214935f1654e2d48bdc3c05a1f19fbe7656cd4538a944a6651c5f03944de7034f76d96046119e5afcc09373ad7bff9c5bea1e7413c26cb86db3113c048f40f3383c695020950a7394d8276c917157e14db269b110bca63b2a53f16d46efc227ea41706b1115b9766058cdc8fcda5907b1ecc03cd85fc15ad95c357d33cd4a6c9ba7da08d37c280e2d73831e9d75b233cff7071e6e17dbb8a6999029f861aae3bad64edc143a553f8a93e2521d547faa2e1a3a4ec0050dbd03129b27e8216e2170f92acab6f40d55e578916230449616379ff48e93ba2097755bb7ecb55168d02df29ead7dc46400c48673598654c4c2ddffc8be8017b83a264cef84a9e36eb874dd59ccd28ccbe4d8382a8840add548c9ed8464c2a78a82d1d8de07fd504282bf02539faf085d487ea7668085aea8e97342809c3c7dc3d974b4d1eff23cccefa5d06d13eed781079a79581273f7d4b7ac3936cf5e6c66cf005586924c86b43f6f25c7e947a13e154625a11051ad6a0df5f87275cc406b502a5a73d7042258c72f1a105136e51c99d9c2d99a2370298263188f1724406d380a6c12dcb1454785cd67cb5804f07d407f0b66e46f99145eaf37ef114600df27abf703f0ddf2249190f1240b81c48bd7bc7f1da8c82368d810d70e3d5ff3778e21b4711ee3fa5403b214235a663cbb43d0d4581f06b8137aa2029433a3a2483101a708d5922c10b7941755fc67073d64c7f0ad49a4fb42af9242d05196651cd0c8020ec54c40a19330400a199bf867665a14e8bf3c903fe1c672920dcd3c08bb512ac50fe6b0174bf0ff0abe4e3201ac707c619f344d652db3104f3206ab99d6f9cb3808b840651e233381ba9915a7e560f09cdbbc2ec153453ecae8ddd478c2f3166db0facfe5c5511a5956445e756046504bad261c07571cc2e221f50660f84c15193000dd4ce367953668d453aa385921966293a14dc63e0d5a7be42fa549df57f7680c1d110ca435c558b48702dbc83ba44096ead39b5c2f2b77df54d29f88e214b1b3eadbe3dad7cff04af8d0ec031ce0e24bee0132f8e31c1c2d3bc86801180d474c45a4acadfd8e828b17ce6ccb95d8590cfc2b5cca6abc290b2b895776ecae31d9f082a440380a8589dbf21c53498c97ca4409cd8a780a1460244aec8d4215a42a8db6242a80af43b9944db18b5074f11ac54da65824a8f4d16a59605e5c90e1e4ce393fec98dc6ee49f214d638c6147c7c181803fe1c4382526bd6582734d264434176f0fbbd67d22f5f76b74300794ee4fbb0b506f0439aa65bf83b4d0abea59f338d22f809658ab12af9587e4a765e34692f79234c64223806e0e95ef42e149eb15de4ba434cef498b8dd3babe925120fb4f1812a27342c9f76d192885a29bfd164230eca0ec6c04b4dbd6d43857d6a0255b5009201abaf38c09e2b6cb05c4c0ad4a87f53587fac32f19a66ef9841e42d195ed08ca0d931c4c563ecfbf5ba0396a35123b4f29f6c6bcf92deb17813b6011dbc21567eccfba2a53c5e378bd42f33149d69dfaaee0384377726aa0bd87f266dd41b5c9322db62842d30780021855e9638255d979579c765efc104254a9bbf04d1a8a2d1249aca311e20aaef558e5dc6ecdf249988e94a8c8a15827f012151d940a2f1723f16fc6394cca2f420fb27c004a10d129c659e82910058b8ca75cf65863df217665e00ee3052af4effed34ce36a3638d7b7d45b1c1c0a8063f0bdd196194589957147fdcaf41e19b704e88bbca560e6c0a2c3c51148c184a49ac0d87a1229be9bf5801bd57aee47289e78751391f40b74689b9b8e7064d2c4bc337d43f316a9069d5ae65d35041f3d4918845a048c4226182d38dbe05d9c0db78a6772e9cfbcc4b946f578acdbcaaeac0c8bf89e8e355f68c9230610be001b5ebb082eb6e1890e350d45d5868c047a52a6bd338bdec1a41b0f30da0f29087730e8dc2b35c17436d4c97660bbb41481f6aaf0845be71b1603a702c1a7fcb2706ec3a5bd2cb7ad85b7eb7eb39f280d2e7fc1ca497e03a0b63cc9f81a6aea6569128bdc2969a99db0d06a5900ef05b5ec459ef5f3b3d9b5395f219c051fe28b09a86ea992341c7e7d0ce58938ab091ee37b2dc331029b5567bc4ad1e9d139ba1b43ee93fa011650a0a0363d2c6cd0a989bb2056f44bb5de4ead30875a6eec662ec85fb93020d82cdc135a00775769fe8e0e6365234a9c7e37a1df9891a7d838802dffb3c4bcef6e6167ce93e4280ae49cc9bef5983d9bffa43037ebca40b072ffa50810a7814e473b2b6f63d151736a9f9b63f856109e74fd254b863361db2b279437b7c9f5be594f3458eeb9bc3308b66b98f8539cc3a801bc88cc54863eee84a847b046dcfb5ddfb04f76c206eac0ab0cf071e01e9d049433fa23f4c5667d2cae9304763d52063eab41df92b04618a48e957b291a72d21e793eb282a32c32f416242c606ff3046d1a3603ab3c5db715fdb138f1172936e7970a240e4562c1ba186ebf677f35b0214b1b96ef5d7a0f940b38efe025b7bce767c89fa45e05f04b80fa594b2817a7c4dc636fb709cf59b1ab8e1b6068264b5019b21dc76a4c34d0d28be8ec949c5d7824e46f7812ea852a9463618b380c4262949c689afd35dbc5d48949a3a6d72dc98d258181e2347a4822d93b2ce23c944c99ce26a8ec2d23ca25590717809ce943fd4d8a164e19d739492782b6f80a31bccd0bbe3f88b22cf108c5922ee1ee087c057c55725088fe3e73fb6fb152d3581100c14f32614554c69a6a47cc326c11c902149ead27c98dbdadf14ee513345a00849b93181c9a7a7bc4178dab5a97607d962f8cbb0b8b848b270e53b84cd3f1ade4f13daf224361464988de08430cbf16bcf48f0428deb12d31fadd5a3a80904c874a910e4a302550e2b22cb4dd8439f7998470a58b07d758b56c6f25122521f32433370c74b5fd402844279ea1149a65aa5e4cfd8c55048a4b91cbbede05e60aad7fb5a2e069def983afc61467b55e15051c237a1e41b207a618eeecb8f26c248449c56fbbcc871811975aaac57554645eea191b82df5991b5441c4c4234ba4e6a4604fb682b127b49ed46228ff78dc8035c3a71ba87c7947947780630dcd5b59641e3ba4a67803d1191463dd7346f518a077a8c290b9c7821b49233f83ec48f5fe1816c31d839c32bd37ca906945c443c0b358647f9abb779a8d0439eadc95f8cf2e1ee772671c814f0714e9c04ddae173fc7326e9797c42c93eb0f7b7603b6688fabad86680770a4ddd154de100f8dd7d005a361f64f590e671e1e1e6c1a5eb06778970c0da71acbae2c32960f4850fc361027a2a1683fd8c0342682aaf7354af709717b97411089268a0224285ad14eb60b3e2575ebaae0e6b39eef47cf0867c2f3bb1f288a417e722c102a6ee69bdc612cc34ae50444546a1feb8d4312feb81f5170067da4c0a6602e0ca1d3a32a91ca9e4247403242a14718e19b9531410a961f52ea04283ef1312f7116ef3769c5622ee205917b74e963dc75ef34db98db726b3d0c292a50388083174ef261c8ad0ce7ce702fa8f9cc6596b810df4c5e7c198c867312ebedbb4c07c22a4e8f565607328c20fc8b00533e2af267e93cc0d8d6de3a639961d2a7d0a0f5201a3dd578378c0985a6dd73228bc2ee09d46a2dca9def2bdfb12d414488deecc65e9c27eab1da3f8254c31c1004091d900ec3057c3153765c1c43590247cebda1c4717b009343e32da4c89c134f8153ab3df8ed10f030acc4d56e961532a8470b55400cf20068bbaaf5632c4114245aca0ce203a9b416e427575c0b6c8183c4209846c486f63d3f7900090443afb6dbfd5355c48764fd07176e7f0d8dce8636f03fa03ab04ac0a054bc26850497c4b601e1d889ad76bbd27630a914a4c43f7742fefc2f0ad5cb1e93caf1cd324d2a17135cfe360b57411036b6f6c9054951680941a90d95c070caa52ea64556e8324bfda4970c5de48604acbd1f3c73b6975002e3fb757847cc4507d8888df3eb24755bd64ca9c755be3dfce99bb8f7ef5c1cd5af786a163ca146be3b154ce807e77db1e43fb09da87653f11fc5dca7974807a819bd7bd6d45f5caf602b84f82a7b233a3b5739040e3d5cfb5090914661db9a96eb4d584c9bf2f570e1098abd7cc142b679d8790be0277d4d2c9b26bcc4f30ed516750e180cb6279b919b75cf56122a74dfc98a6b1de782ec3856baae08452ba7d23cba17937fd58b7d40039346f83927ed802150757c245e5f25ac167f7ea239c06896c7ab5b11121b06c4c4d32803094d4d5ca4ed57a5684c3119e5ee7ffa48c2c4734274cc116344d90edaf5a3c07fd48d808c1a61f9650429121796b049e735e16385375597df28fc4c54726137af58d2ad9bc403669ef0d55bca87952f13821f71f5853b8ea2d984b76b6d9d4610e8571e40a66493daf581e78c7c21c4e6bb1755cfc51bb1f6345b4833c10d127aaa897b8ed7ca349e79821074ba88700ab49ccc59c76d38d4845af4d5d4ca084c58146535846e96ed071d208c8871161ec4089abd1f27ab48fadb2df76683d79b564822a2b04d162b39de19dafef42a12475d43ca72c42821c10712dc788643d73bcee71175191d01eac2551dc0f52b489278ad8de395be3f6b9d78e68ada487e6b14a1ee143528d44edc57eb881b79c2a7691bfaac26f6825630449058b52571b8a599eaa9ac34b1ac412f8d351423856a89f723ade9dab383c1de5bf93a7f2508cd1d9adece7cde64ef179d759ceb4a5301d7e22e06c205ec89f945dbc5d0b9aee8cc48344a43dcbe2386a6ad65fb01d9f6c964ddacde71356fcb745412a58b2c5f2253607fc53bca00727906b17a3771f879cbc6db2e150e08620aa4d02b5723a3dcb213da62c55da46226a1128373ae7b391ade590b2486cc308bbeae73593e6e63d6d6dad535126aaa1d268838b44f2cb2780c4b2f54ed6db7c1c9457d0da34c2059cb2e2729586c1fbeedb34c234eb7559614aa215c2a63cda0fc99bc275d39590dc6e8c2670554e49c861166c9b99361a0d358456569f8efa10ff52a72c229e5ceffd4c51577bd1b30f994c9c3023c2c2fb620389e7ae1264c758cdb0573a7d8200526e37381e016092314a88f6ec188220d380c32577e1ac499f945f8194097212d800c060328194ec6ed66ebf27f910af889ac4d6fe492b6cafe95305c430d85d29c38c1f65f7ee8941673f39981cf6a27455780a811045e7ce44a029f8c93bbd5b2cd26975995df3382ed2717c993ca1c7854a703fd74d937b0b38028740bb54e273690c9f90311147aad506f3b9d182ef3270563139422246ef70daba1d93358ac50f4aca492adc11e09abd0a48be88e249e946b54c3919636be54241229b08e18917a33868f42f405c7c5e10c7fbe00837ea73ce3705f94b0189d9d280f580838c14746e28a0d350210dfda3f7eda8d395099798df9c38b5df9554a5174bbbf3ae036a01c2c892fe5d59f1f72da94f8f5b717b8fd4b3c98c1ab5869421f7a573f2bf145e6ccdff0465770d236ea52e2bf671b6d59f2668231567a037bd425bfe8003fee661efef2a41c247891688a43071be4ca0c44388a8eecd78eacb8eaba49bca04e05dd0f41df8e7393612033588ae338d13e4f80536b0559236b7606db3022e552f5d4afe27f24cd4103a1849f3f3fdc81ea90ee012a218c9ff49d72a3691cc4bcd1f8e1dfae4770b9b0a25eeead38cf3b7261a9af44b89c6f7b11b8d9a5ee08c50c8cc940dce6dca0b56f0091ea60c091a88e8bbe4bbab21221a8f1981f1641ee216cd361e7ddd8f60bd5a2e503a3d0086d583bd76177d0d4a3404b35e6604793b71a2ba924e543782d64e6853455e1be6253ae9caa71490f98e96bc9e8b1bab77460602a3067fa907c182d6d54104881f5c68b203b2f2082301863169bc1b60f88e945a721a255803d4ecd13411af58c45f377c0b7da53e578ee1f9c6a2af820da589d15eeab56ed20f3a4acfb43547ea8f0fb5acfbb01cefdc417e0dfdbe91839786a760b0035065e4a31c730ecf766f455bbf666ec2a083fd8b10c3500856306ad916d64cb365cf8c1dcdf70fcf4e3f887ffdbccb15e6d45b02c22de847ae2b69878c31c7cb8cffcd8f44852bf397bd00859a83e47e8bd440247a72a7484e02fe9f1494fe2cf1ca021c3c4e01f7f1da4e11e014a22bc849194dee1a8bf64f9f41bfba24cd7926be60253096d699f9829c858a1c886b12925e649607b2758d9af60a412083498b4ffb0b3a751228a10c0ff48d3413653751d1eab6e4f51030c4796e404ddbf6c227432359a4f8b58506d239f8f843955429e82ce6d69fe123ffbd7e9996a598c2358e1b503e0051fd024ee86ce78bcdc84f80f0d82b8b96cdf44968662095f7091579d0a99710c10e5e42d1e3d51f031b343504f6e8bab35273c7c2425ae8b596a899238e062fcc1d993508f4ad5a87a6c439ffe836b7bb1bebc797c91a3ffbc06c30e8f5caa221bcf866731f3aa1d6f96ef8b070c358d69e308c6d0b8525f418b7ecc60c36d06396b07d7c205919cb33084cf95931d222ed7aca250a6c768a7cb0324de10b2a0c44908f4d7412d1882b4ed00695b1d36ce56c52b301377f967f29aef7690af7c6be74402d670f96cd37fb526cc9656340007db472f8d8478c388250c5bdf9f7ec3665d23eab78acbe8b9c812d18b4243866ba0286d6012288f1f7885a43791d206874648aaa78189c16ff07148341e12c7fe6a962736835090b849569b1019a0a7d569d978f304a1d0909b2359eb15fb91cf27932d2bc8da820db5da6f374b0c2d349584a3857bb90671a6fd01f0d77f673442493b54651e53f5c0470559cd7764b827dbe8f2c0776356262986c46ce2756a58e646e71e9736ef344803f304d026807d412c583026e4a7cddfa33f6a58dcd527f130502726d2add09f53ec20bfc4afed58f4af89ec685182ce7b581dd6500d36ab8817d066e81ff87e205382c6337a67254aa45efb9a626317144735f8ae110f493446d1353265e8699c821c73bfcbf41a6d2dbcbfb3c5bb9fe9c1ecb745e20be2a9c074159f43f1ff10edf9b98c5ae58abf1bc87b6f9d1e0130774dc484231d68dc8135246e11111e1541da664c9b0e92c2d7095b9a0e6830ce630416792dc87fee6f8e125771dd2b4998fa1c773eed2cc0ffa15798eb0ef59fedd8a51efa85188d22b22ecd9c5503c51dd7913d4424d2bf82d9037ae83962be5a6c588155796366e0f07f085221e57134fd591c6ffd7234c07493adcadb793e5470197c0d167ce0757664040374f65e34298716ec78c71042654260239bb2152562e21e70fe917397db20c65c23944989d8aacc9812a168b457cd40cfe718b7e45fa6984f277ab739e8c241a2c698228a8f1f2b73c1ab111267be65cbb10fa2dcd073594896c96239e26041610e1559d8ea070944073099580d9de4e18ed705928d5a1e49db585f04acac3c75b8540fe93ce46d8065fb4d92562a8cfef54c4652a44f988149e82452351645f245e610758e00664d1856ccf10af5baaae296ee6e68c8ecdcb8a56a2102fc18fa8a5d77144381925084c8065bddf1df12667d5dd8ff157c61c722117179d748cc341228c96b94a85cf280742e398707d34a812cf093171e25900e6d57881cd90b20b080e09161581c35c4bf57f5deaf3d02867f296809a211c76d9142d43dd297eb33012e59741a3386f7dea106162dcc5d8a641534e6ecce5f98ae889d1c4fa5db53883862342f40cb207a3a7701f9956ad16d2490c91ab1fb45024e12de63e9a9b96105d49ee109aa9f6de0aa006fd12909203b8396ca3eab13aaa6416c3d24fa77dee93126ced603220eb08ec83ab9bf5f05b1f4f177084a86085a8fa109f381af96f5d45371ec77d5a113b63b9165c9b123da4309c8565115b5ae002f61ec9e7e1f6698204a8204d74d90ed26c7be4544bd766150f061f816adca1ef95b158ee1ac3ea372c62be6993db0c5a33d104741308c09e3c33c5ba4e958f7878f3790ab435b3016e4f66a64b2f54c2552c05b22e848ec4341e078b4c3c473e6cbd587e28adbd5565cf4bdd57dcb3356f0660c958c61a330baf02a193733afc4c50862bc8ada4cce5dcfc23d8274421006593f8b308ae64323f6a3acb9f8ab229b1ae64dc24c5c0805dd46a8c7eee3534db20e780e7bcd1d00c570399038b0c933c04f0360242bd5f7057b4da878b6913eb417139275e8267a013e1568ea21ccba77f7003de3b6aba80a49b98a63961b2831a81624103ce20b6b985bed2875424abc416c0c9f0ef06c85222bfe478eadd6f1fbc6c4f23a824861108f589b9765b26500e87db1e4fd7137c794d76f86c14201b194da9cc73cfb1ccd2c9775ddfd5299560134a191cc0fb2603a13d1aa350b2c11e90d3c49b6015e40bde0e0cd296efe443bf097efe1204080aef5fc675e89b0447a647f113086d92c368e1763eaebff1a0d26e346f1f5900f25b8425ba3fdadb1c3bbb252bae8694742c014dd4e7bedb09dfb748a6611a1181b3890a1f11ff1524491c928d5c02fa6e9bd17c34c80e1b0043d13d02f869f74956884bebbe4031a7dd362dfe4448a64de96c8c7844961cfae80f1e52b3e1d930da057763a1eb46b3421fb35e4f09d4958fc111ffd368bfa63e10d59761ee94272dd1878075020b017ec52d5b017ec351a303e2a167d15d486348f72c2d1087683e7d7e52402cd8b046a43d0532e7f9f9ae5503daaa70fd9758e6b8b0147d17bebb8014f880f1dd6f41560c422a327bd10636edc096da433247d26117f0599e86b020962d2c35fcac47c374bc5a0ae06300cc610b2db265013d932bf194cf64a0cbde1a7a9653d5f985395d16b96db8f1cb5b3b6cbb3d9f335f5ebfa2170a057c6476903c3953312a8499e65e6bf55e7c2a75e9ded541bdcf19653ce9935a7a9f9972e55f11d3e71eba664cf8d9bc3f768295293f7e7143ef2eb24e6656eaaf53ad2484407fe974a3356d3382b0d68aaddb437b23338573425e3c94dca8b47c242ba9dd402c22f712c08c54674feece5dea7421a498e9ec4937f54d60ac7126efac65b7284bd297549dadd1839123e474c29d4424b1052cad4baaa4cbaa2971fbda19d3d18b5eb6c23cd93a9cfab399d0ab039dae39c3f7f299602a93b25d9230c2eee7aa39d91a76bf80a572e661f3b87be529ded59fb32483ee97c6edccf44918c477ccebd5e31dd72f308f211b6e21685b0a1ea560a1391ed2127b3c4f63583c17c1eddbc3cda3451a48002fa0cb2e32a3f30d58309afd375d298548b30da6801250cdb82bc926c69b6994b50e50f1054191efb1843a54e32df24ce9d7afa2fc4bd6ff015fc671677b4fe77f4113b5a988f870eb6650401050a847bb7efe4330a2ec7e5973aeaa632d21b11474921a2bd4f836a6f474607a3fcdbc20bde9fe6c509d28f8ad21f73b1e0a9ef6dd6643ddc84bdcc0c3017163892f91eaa7d37217a02f040a27e0e594436b541b516cfa434566e1075d988016b958ccacb70adcd6514babcefd5880e4aa20c291dbdf6f603b247995f524b66aae22d467b7793cd504ca1415fd04428d9e3f6d001522b0d9b761815e393fcda1463693999622e8ac9002370f2155d472f617612524b8b3929c0dd21b551c777719f6c7c9fd241ac91ed2906f29f825fa45874a8801b524ee428960d59225b5599a2c725bce4810a8ea28b41fbb66d13eb7a32420648091d41d14f4d62d90da44324973dbeee1e1abebb4f0d00a10d3af309fdd3fe4e4847f68cdb4644ec86e10f7f2dc64a7ee4445856752a1c43d6daac15a7fb130246a827261606381b43c81bf2a7a389bf837839527f9922ef5f39899b6e907618b780a6277d4bee5b3e0e8b1ec62b1761e2cf6814f6385ec53ebc915e34e40f8d5ac4d1a1a58766361fb37220fc24a4f1a1a5c9f75a4de6a39e56925ebd7f3da6a38300d9b313dad5ade83dd2ae6ec02adf835e85483b5224f66b7c25efac203b062d115e2eaa70abb4e2a0f991dbe1dc7a91880c08a243c699eebb47c7fcb8846f00ef031a2c99d0e87b90737675c4ebc9e27560bf3819602f619d06cf693ff24fa92639298ecf537f51032a8053a1611a651e2af074ddd8fab9f0191f64cce9409ae808033414da46da62389fc708bf15f0a066e8390379d2e21786328695587c2899f1858bce7781adcd77940a19091944850474404a1415940f3d8108f8face2ef22b42bbc7b7a9b46415f888e2aac114d4d79fa317a5e6020bb4004944312191279ffd935ff5a86aeae40ef191e91176bae7993fa10e0dc6898585a71024f0c9168f80d9ae940bc54ec89163a5ce02f19491860bbbd8843769a8bde3861190487da85f41f8abf5625bfea049c4207d553ae114a575f97341ba9b7be28658ce7c1351b238588cf82c70b4e1fd1742c3c9d0684130619c81e93ba34f34b42763dcb1957765c3e03369bb8764c2a6ae64ab9f472b6e66636f1240c3307963acf819dc91173cce1c45350ebc21e2e8aec2550edace2102f6f9ba8dc5a4a240538c0badce0514581aa308d6d4aabd4400662f29e3740bf4db90f81559722ec0588ae7b8c7968851df89bcc0569ec6e3e7ada8c1b734929e7fe0467711513636a9fe9567516712ccf17a7c9fe2216d35b2f69ddc879e9ededab83706402c5acd1d190323fa3cd2dff3a889d5b0f02d9b950a801954bb02ea5bc2795820d855693af915f34d0ed387460acb8585a001dc3f6488f7934dae9c26dfb2d230f044011e3590fbe29f0d4030fafaed3adcfefe9b2ea64d4dd702237cf98d548267b313fa7b79befc65eb6fabb68d9a88d052237bef2d03d9075d07ce0739c8da97ca4003b9848a4ca2d2d9ae03dfada440d4095cf9f695d40a0882281408822b9eb59d65016bf66e675592265e5e969bd7dd9ae5077edf497bcd1fb8d28228f9258190d1b80213985045169678e890052074ab7377cb325d71c5115660748422c4d082229aeee04150fe17085281cee65b5d4686cefb420b983a218a2546cbfb4353c7e57d59248da6cecb1be61df3de797feadcf765125307bf67de34ef9af72593a933e32dbe5b6f1aefcb28a6cecd7b86b78d37ce9b863700de97574c9d1ade97594c9d9cf78df765d3d4015f17f2be8bee0079bf9b936e59e8af7b773bffb4629e764f330057e65316008cf25c99438d2743551baecc286b83b6857655b09e2bb3cad663539900aecc294e009b4a1bc09559d50d80c3472bf6862bf38a7743c7a201cbe6736566f97cbc185cbe32c700f3b705d88d57e6d57d38e53482de17274fbb2d1e01aecc2d21014e2edfcf95d905f513d214c17a775732b35470a05250a8f470e5f8ba400f2a29095c390a092281d40beac3b192f96525876a0bedc2a8e8b832c3b0e85861f1b41b9302ba32c7c4006281812286a7dd1d150e57e69d55a7f274eea728e3f293c13244b06a82ccea2c05b832dfa5002d37c6876325f365e5e0821201cbd32e5e055d99f14b106b85c44ccb876325f30c8c0e2fd8091a17035c9969620c0053f3eeae64ae39408c8cd7dd8ef12670e508e49eae902620f315cdf8876325f38cbbe3d7d3ae18c3e3ca2c621e177bda6dc9ec70656ecdec80691c0157661a340898f1b4ebe3423e6868b6e86209b9bb2da45d9bfbe9983901d8e6460a6abceef615125023c3d3eecd4c8f2bf3cd8c1e325a42ccf0b43b038d02aecc33880a98f1d540f4b46ba3660157661bad0588610f5a9e76716430e0ca8c4383012d1723d0f0b44bc38c065c9969a8d1001a6117353ced0240e4e1ca0c001b1e6ad878daada1e5802b730d370eb00187b8f1b49b43e30157e69c191e7073246ed480c095f9860d086c61c3d32e68f3e188c00b8ed76911b0d11444c6f1baaba3b34c37c3c675de079e42944a4ab5c21263d5e2c27a818991f9c53334353266882d1a356c6e6a8037fa26bb173dc81d8fa75d1fb742174ac013f0083cf7145e2091fb83801743e4fe1eb0fa42eecf016117b93f1e5c8c90fb6b40d883dc1f03be1ae4fe16d0ca3d851584c8fd29000443eeaf87ea07b93f04b4c820f7b7c36a88dc1f8f2e8a727f3b322eb690fb439a400b16b9bf036027727f06582191fbd3610a5c8820f7179455c10a790c597e05b83645159a90fb9381c93d45157098c93d45155600c492a2638b2ae48ea50a096c0105520f5b1481a3850c3fde17045045615c0d21b368e083734f4185a31b68b818408c2a04b0f2440f8b1236b854724fd18424773c0178e7f2b0ac73e50821bcebf2af950d99f5accdf96f7cfb8d9c1b356a0c40f36ee822703b43e0767ec0edec80db9987dbb901b733036ee705dcce0ab89d7bdcce09b8330bdd9911703bef703bf3b89d77dcce13b83d1ee07636c0edacc3ed1c743be7703b17e076c6e17606ba9d75dcce396e6709dc1e71dcce3fb733016ee7f176ceb7b3cfed7cc3ed3c80db5900b773cfed6cc3edcc733b07e07696b99d7bb83dbaaecc6dbac9c8d840a41eb45be33b57bb8c8bd4c3757a38906b9424c302af80052a7021d72889a3c08350e0473efef8eb1a256d13f80526f0231f25402383f7462b47ac6106006464140868a8c1a1b1313303beb91905820edb3c8761a82193c330d088c92810b460c497192c242007af8c7bd725039161810adc9e376a5a68563984321303b3dc957cfca2ca3ddc54ee4f4646e6864025774d513121cce905e4380afc38ea045fee9af6709fb9bd07bca2ad6c0212b83d6f70f865e3b1badc3575e172d7b4e553dcf21796c1c6d058b2154c55535465a264e885148b5727fc0282f09593b31c57f3c88c35c9af1b346bed66b5cc23e26122400912452f2bd58b76d50b0e54ab17d54afc0dc29777d58b17365181054d5f2815e5d70da167c3a963431b53582fb4deaa562c031b765d3a220aadd73c950ebc50e5852f3ae69257ad49342dc114e508a52d3425c9af9e82cb86143b905f301d910455e8a9848859bba7228217aabcf02b1d84afbaf254d5326d4ad08e28c2344dd3340da394524a69d530ad0bd6064644d142925a6ba55c300226842b180981054cb5663f59599b82480b986358f3e9ba688b1e3544f812b97e911e779f49e9edb1cb9c615cb515b514cadbaf4e8d522cf4407ff68952ee6cb5dc69d826b1ec5bb5db0776dc96dd6edccd9e5d1a3e9cbea14749114a10048360973a60cfb06f57669be6e91c85239ad82cd3589acd3aace3366b33db988661dfbfef62c7ada4ac5995a0e536cd76588759387c9fd5b4d76aadb4dca65969b59417a7c6acb5d6269124bf4e799b5996d9ce6131e6819c1da0d267dd6d1bc35e2ffaac6a745a6b3bbfb2fe9c147fde8766f75583d4776eb93151fb2a115e47fb90bd36e885fc76e9e757bf5dedf4aba2a8bdfb4c2ff3e6372390b85c3838a2f8af5661a8dd20d434f1db618edefbe321470f9fb69c085f9e0fe53e10254a7e35175e56aa7622801b99de644a6b9aa679b4d3534caf9a224e13423a5f54ab7b206bf827297c7997c915bf7a08769cb2ced9248a1d2c8f86d2240a5580818820340561ec6e5926b216624ba660d282cada3405d315b9d64f8796b38f4767a10927241d4142055c308dddad7a6a73866db5b3cb1457aaa4eba9c3a24d710e62a6a75894d2a60586248aa4248922050539070f294760db462b0e54c4719d865ebd86bd0e7b7debc86efbd617c9b2fb2a92e5acab41341d341ca4e2202c1cb063580cb64e62143c358f3d9d40b07940f0fb9ae7fb3caf793cafeb9aa7eb38ae79386edb9a67dbac6d1e6b9bc7f2685a96354f966158f36058df64afd5d2e6f94e3f9bc7e36e7968df503a9b677a77f64dd63754f60d9df22a52b7cdc33fb464efd672c71e84db2c6abbe5501c26e28561188661185a7b4ff73524d377f70544a638c8066edbb66d28d4c6a15028d4c66dddf5b31f460ac3300cc3303c9d408628140a8542a1c2300ce9e9cd5e43f23deccba1293ecd18473a9a2048d83d9dfebe63180dafd2615372f8ced29cd139b97bde766c37fbef2584e8f61235c9fde59053b2ddba13a91bfea1256f14079b89d46720883df620f6b4ab5d67ffce62229b15a13c4ae5a22ef6cea7a2dc7d13e21786e93bdafdd4bd9bdea78328d7bb64281de661efbacd039966465d862963ea411c69a31044630a376d514a84665957bbe1a039eab977dcbd0c10657a6b33fc438ba559ea767b766b5f94a6408c1482944aa552a9542a952a954aa552a9d48fb8c6d43d90c2216d49954aa552a9543fe21a555b28a4993e29a57c7f409dbb6d5edcbd1751931c4437c83c0b872dd30bd1f20f94285f21dc2ea764fae1e0b2036853a64c09030e1b7e59a4d4e78774f431853dd04c63120b875cb352177090e5ed174b594a89012d6727caf3c301cc19ce302b87ecf4990e3fc85c2f44cb19c59e54992a35e830d94c197c678e3b91ed2f2032f8dd12e9291949e52ff0dc3bf0725b7c180672e7301083dc7610bc2fece07d2886023111fa1d7ac43e1c20f6d309c33cfc7d860f77a07010a80f118d28ec5d9f751241fcda91c1dbd3e927ac9b64300891edafef3fd08cc401d43b733b50a80b4134a2b010a9871813a1f788c829b98a2364d91afe95a8a754f051cb88c221405d88300cc3300cc3108542a15028d48fb846d43d80c2216dcd300cc3300c7fc4358638b422a43b73ce09ce2e041289e769ed042f6864fc256691026d0303da4676159817944c0ceb7d1f3f9ae754f3196fbd3f334a629af66d1b0c14a47b9fa9ddbf139384afe6e2bb2e67ddef3017e9fee5b6ae511258e3628d1ff948e333ae5152872f03ffc8c799c75ca4a38fadd75ca3242b9e46fc918f33b8fc5b44fb75c145b61c8601fc766d9601d6a071d40964fcb7fb76b52c030fa12d998bd47a87676ecf1b1a0632775acffe63eaa09ebd75c3c8ae17b0560b0fa12df10ecd56f6194675c8143d1c4269392194d6d2dc651c076edbcb8ad3ecbd45b40f6584d06a9ff5f1c5c4645f77edeb0f07f6e19039b86d208eee1a9885bb1d467e38640e8231a8cb097a27103caa2b456029a50cb4427bb285c115f95657e64f7e38b695a45e4b91212db7593899571ecc07838552d6aebcc75d560b6bf5ce5d8643e6daed8ce2503131f7993666d3de8591e587343305164f727f4858a3026ac3c28aac21dd18ef322e9c82cab72258ee33b3eeb86ddb4299235a40cffb50dfb61dad3e73e5d81243951833ef420f5f39ce90814ab5e0772a0f2573b7c75c20a6988560d478dc8c4605d4bd72acb940d056769afb0d41c1cab7bddc77a92e86b75d8f25e6cb21738c772aef7489f44df6956f48df646f3921860cfbc409e66e7fb940a8a8e021458c1072b755b619de8605135965bbacb3b05c99592df8cb2133cb3b176fbbe1637c3886ac1471a1f972c8bcf2aeb9cd7620056256b01d42db0532c51f7d937d061684406457195224f5a332a0209617cf637d3beb85e5e23263b90bd2742d33cfdc1ef1ed31465d79c9a21e53f7e565151438593e3bf367571f8e15c86d2b9f0f161f2ef6fb34cb6d9b64610253eedc31645350c343425ca4b5c80ef02133837d608df7bd00497e49137444acc9f384a6138a27b39a651acdc2dbd88783b336b01f13942a9050a4431561a8dde994e258b815efe48228f965a3080b2c8ed00226412d40aa2e40d28442f5e4cd06a0c58ce3388e8322a90465b697524d7616ab9b05b7efd2d971d672d6a2ec59271668cffa6cb769dbf65dfb770b1434c5ec9b0f11aa8042c18fe3388ee3be5d8e66d409fc3ebbc5269bd80b5eeb4e53e84f07cdb53b8137f74d96bd450a952b47d505a2adeca9bb83b6b2cbcf870856e59d4a154d647b69965f6e2a888842d6be1c5d85dca1b66f7ef2035f4419e8cb31732bb178f6524ef45027f00bbdefa35de7626956b93d56edfbe8ecba8f66ca945f3d053be7e6cdcb85942714089e4ea8d3c9cb49a7d76831eb70f5826a9d7ebdf6524e02f8002d41f16e7891587e6239015aa7032d663a4000751d90380062eac82624132368eebe4bb39d3adbbf0fecc0203ad873ff30fae1f8386e0575fa40ee6167b10fc767b5bac2711cd77520e6bccfda6db3a8d307721cc7711cc7711ccb954a662b7b27514b082bf6811225e5776d9779dfb5ef2facb9cb6ab40e0fe2d459c014b3c6b1d76ecdd7bb3577dfd540d409a45d065a478ea0874c1d7934c54c22914846d034a79e758ba967aa67aa7f2b5836e99b4c264141c1ae5c0a3ee4a175241148a60fba2393d0bb724944eb782167cf8600312ff540f0d34e5b58395db9c4143d2c9348254b487d57fbe77da90c4ab90b4a2c1ee1bd0b85f7be87e043fcf0de5f218b87f7ef49dc87c27b58e83b8887bc7f38f4c29c85b0476efc0ebeb2b89fb6ea89c6f0b238ec8350780f0f85b45589c6f7080621a78c491c9e7d63bfb02a6daf3b7035a161895692fb6ac92f54e6b473df7a671edd364f77ae489683cc572be5b09100042979fbdcbefd5524eb70a284f2892872fda69dbc1bbefbf71eb9ee7b8ff01f3662c4e3be83b8694bbe47162739cce2111e7c8ff020369264c4881ee0432c91d0563d884f5bf33d4eaac94f2589701e8576151e1dd117cea703cc128cbea98f59124e3a2f97eba7039dd247383b6835b959d23a8370b9c3ac1cba6bd7d1e12c73f835ff83b69dbbdb278e0d2b3d31451d5a964ffaa67e5e2ccfa3a227e88e1deba5927cd23c5aae97452f5984c4089924d7375d62462122ccf0d014ab58af72040645d20285ec2708e827a8d63a2bad35abb36dc8548cc0cb2d850e5a905fed248a13356caab5d65ae79c73ce39e704aad507a8e27c4ca19de2ccf9c97985d55a252596dc4b544041a909e342a74416842f9a9c14810a3c50a29282706a35cb5eb3ac52ade7a747abb5d65a6bd5324ce585248ac014250b2665f80cabf5263683052a6900235c4d71aae457731576a6396032ad27caf5062884f206a6509e8a393d3d3f3d3e383f3d3f3d343fb37f7a7c7a7c7a7ee8ecf9712109e72715214dd602480b2d1c30757a7a7a8a10444f0fb60295dc4b54206972e28326273e403f3e4073ce39e794724a2a65954a3f800861526aca09cac9f15152b25628bd5a290b29817e82e69c73ce29817e82e8fc09f2c9f911f404c8b5e3c9132054247d3138d24433715c52bae47b6cea33978feb72d219d2d965d7c7d5e3922e9f29a974f9c81cd1f52ce4a4227cb932b5f1c9a2c7e6278b2c286d572af752116890ab93298b706acfcffccfbc41f3af76320f34451af467aff5b3d65a6bad73ce5ae79c13c814e9a30c993aaf76520488a1a9f39258c815e1abda44e16207e5e2c7121542a832c0e9f9f9097202e40afa0972621314f403e404e827a8d29f209f1c573f79b515289df9d556a880b4a1a58d79fa974d7605ed88e2fa71e2a408443809c5905fed249b828d6bc7a762977fd58abdfe27e7f23e1748ca4c66a7545249e5059a22bdac3407995c7d1a87ac3e40b807e3f850fa3175800861529a732afd4c1d20fa201aa5fa748bbe69f7967b890a2872c54f3c9103da447772666be6d44083509e4ec144965b0a2854802101401898f44113ac9837602288237c10050998204a41156068220a4af8c209162cb0718515b658f204282c5002510e6030022bb6d0228825444939618913453041c1020dc626e4a00627d081133c504209511421b0020eb0e8a288055890d244144b2862a2044c4f2021ca8747e048810c4bc0200462a841113c04c1648215dce003433861ce9b01397db0215f64956de81b99cd39b10f35007d2367005a949f5f569fcd895557dfc849a79497a73b338270c4122a5c30061e1c511c84010517bc78d2832d8cf20a5e30297af282112021490eba60833208f1052ea68cf24d23595091ace45e22c20c686e29769082fcca691aa2698818b99786c0045718a5525969cd04c02aad35579c6bc52af5a918f66cc55c3f53aca712fbd0cb79a0a983ad807c7e5aa9522a7d8070cf14a9085be90710215387a9befa7418bec225224021531ca50b2a71a8d8fd61fa6063bec82aeff40d2542a748c9724a2642a74cc912fba0bd88cd37fa66beabf846e38065792bb3ced8fd61ce2abb8239324b5cbb33965f39d9956d5c53942fec14e760d85f39193bc5b0105b6118ee8942f660393d1447ac79f615425347e6746b7ee6d89c55eea51f4891297e85399ad44430bdba6d9d56b55f0b67cb72cfde53a74eb15ed6532d5b4fdb9e5d95eb69bdf6752fdf7a82a4bf421fed54bb210d4d94d21d7a349a97679a477434808115f54d7fce9f66b0408bfa664e1d30b936e99b29a70930d9042b6a1e9a84fcaa4d34911be72ec2da04264b5c69d842286172ee22a4472b7932cd682194af4db0a22f388079016b324469f082cabee18850b4993bae1c2861bd2a87e10d4d84af9c1d9b2932412795147c11e59cbe99a7776699336d9041615ba2598145a7a4c40aadc31fa0a025254b5db8baccbda48449ee722f2949227bb9979444915f22d3096cb05841a701254e29d3d7d08253cafda61b60ca9a64faab206b92fb9f0e702a865f5e2c8e4f11be6cb0204153b6993aaf1a353e5f46104e99676e9af981ae693a53791dfd7274ed0a2dd5688a529ad26c778c5ea94352eddfc524b6344555941ee05295f2a1da272f65633f6a400aeb31074cd15a6b5f856461ca455b99901f407ecc1d397e394420cbff002244c33ea07e3d4bece3c79190a9f3924640a6cee9d987482317ddf9d1adec7605bf6c9872e54c8a1ca01220822753eccc852a53ad6cf7b6abf272164e31cb56b00aa7f0eb2ab7b73b9683fb77f9e9a057b964e5803a3deab4dafb0af3abb978d58c7aaab99a7f4969b3bc968348edf57a59a6ddfa225816ca300944f342f57828a9b1d03cc543f443f3444d3ad6c86acce2518fbdc79c98d546e62b66f57baceff166791c7997fce545daeacfcbd444f8036e099c4eb84196e5b87ab6c98439953042f684252594a0441319cbbda40413295a5c51832dbed0021464e0852e884ee00525902085214409c210c67e03e93134a1a088221d0c118512c6453642092ee8c20790306232f6db02f26d8940c5d048c822f7d848c8f28d3384bb1dbbd9b1eef56ab7692a541802a6a3332625ae2eed18ce9962cdd18e69b856ad6a5a4f4eadaeaa6119566badb5d65a5f6bc52a56979454e045a70412ec5c6677ba2b3f1c56d629626f0d958010486c73e19c29f6c85b4cb3d6f64c11bbbd3918e6c26ca665d87b300cc3300cc3b00ccbb02b744db365d8e9d06c61ef23681909f034fa761d28b6a1bec1ded57045f89a46598ace349a3a47c78832ed1e7ed9305cad7e511c6a1e3063efa617b3249cb9ebaabd8ef983ccda3fe93df319d237d87de88e1db1030d691e2d63b7985d1d2763328cbec1de7d9b4753c430179969cf82641fca241269238a103332c21ec3b095b5525e8904cbb24b4c66364332772496467892608ad85bca6b1681cd226611d28679ec5484466019966559964924ddc28e61198665f8157e6050fa01648a4aabb92486dd5e3f934c2553e784ba977159b530c9e2e5af69c4ed7115b324c41eb324cc668e4fef4386780657aa7224c3905296d09e8862e2207515251ce4fab9a4752492d94cb25192ea473edebcd2bc7e2ed13c2b97f1eabdb2c82635f8e6af79b444ae46349159a8344d0952e90b02f879d76e912cabde498fe6d278cdb5f9cc6d1ddf1a5fb9da279277913066cdcf9c68545da41997317321fc199a63ecc9a8b98c138d98358f4f341e7d9c81c5e30b891f9ab9f88985661c1fe321fc192752a930d28cd7d49c68a4a1719a0bd138cde7696c5e83876a6ef3219ad338d1882f6b7e86138d33ade30bb58e3f8ff150d2c442353e031ec2aff1a199b74e348af7e61a1d7d9c712953946153e3d2b0ad5bbf72b52cde19771611c1642e41d284eec8a6244bd8ac65d5ed2c9bc8f052589240054b23a5d028579a9ad70fa9a19939fecbe69acbd22ed25c96867d10a279cd6bf0d08a0687e63de2bf441aed3dcefcb50a8f67be7fe6c61cdffbfe40eddaa62df95f991b766b3e861ee6764f5ca728956418539422a314dda9648af52e5736512497b36e53ee22c5f87671cb3dfad8f2550b6e7af43106964c4c96b496c1dbf9b3b91b5d6e8f1d43c37309a515516aaa0821fb084152ca9f29ae40993adc549a3a53cbaa161d2d1e01861b597a6cb93dc2dc1eb5517e3ac01cd437558b5912da9cbacb7bb4fce5a9bb9ce526bdfbc42c1c6612963251ee1eb4a35e86512f9beae593fa956bb47a8cabae11eb2c87b946aaaf787289d55d9d7593b6b3dc231f61be7255f7e823cc3b23a638b398629d5ae079c514ebbf7bd781227cc9a62b5a473671a2c5fa9984eea85e2f9fd01dfcfab9d43ce1eb67135a59c0d7cf24a60eea5532d15613ddb9af32af471f557fcd25725d527a22ff749f2cbb1aac085fb2285f36350f1199a9d03c2ab78b64f9243f918e8eb4824f1769e63567b92bef41f315961b89390d7e12f81e2ca7390d36b27296f7588359f3aaf778f47106d35cf51e3457cddc48ea34ef3173d555d848cb67de63374f278c34f3bbf21e317ecc7bdcaf60232bbf8fc1469284567e6f24e6f83dca5cd6bc8cf7f8cb9a98c5e3af790f99cbc0465a2ef31a6c2449a8e5323792fadf23cd3dfa4873d5353af291e6471f67661220cbbd32d8fe366999e6cedc9984b6eaa5134d9ea03bb38964a23b5309df1eefedf1b74799db234a934c4cb99e45e61a88083f2c9960a984be5e1ed19d98d7cba296942cba96b6ea636ed3d45b58f362cc654dec8390ea2b5fc1432b158eea3db6fc25aa70927d8fd62869ca03a13baad7fba03ba9d70fa9d9bee5ca26da7a22a14c236612534c72535746a1adfa953b8b68ab1ea6fee5ce26b455afba4deb596ed316eb32c9f52eb7692bc60d62c80a4f1dadd35d5fa968b16a99bbdde36a64b93daedc1e55b7c76db4782ef54db5d9c7259b5c2aa2d34481a19fd1f6714db16708217cb9b087452af6bd7b07dfc33b887b7c07ff1d9c180747dac01d47dca8fc0e30bfdd8543e422ec2504a129f7129cc8a2ab6f6903c3afd99f4256f22281d8355bf47473d9ccdd9636aafde69a224d0ab567363d33c32e1f17e683613eaebe3dae79978fec76f934c699e2ccc2aee67401c10679d6fb794d5c0b3a7a6bedc67def4b8efba6b5567bc67df3b1c336b17868cf2ea461234915c3421c16b191ba35cdceeb3aef1a0eedf6ec46be6befedd985b667f8bb867fba63443bf7fe777de896dd5e28bb15b5732b1c6c2449de883ddd31629f5dc83ec3120b6dd770485bb3db6edbcb92d80721fb6d685a8b93e47bcca2d4a9858122c91588293e31451c6d73bdfc42f368afefa695604ca529ce287d534f8da658ef33e911a64553ac3a50d0a28cc9a2790446f380b99e8649c8cadfc1cfbf6811dd69307610852aac308621ba1065ac57698194a9c3bdd6cfa34ea42d7910b3b4a10fb3344d231a59f2e189c6efb224e81df4b40b36f8cf7effb076ef4423a761ed43a2878742a229c1ee1bf9cdaeebfe099e8e3a0985ffc20f7be7b010f8fdbb3e68ab1e7577dcd3e9df392ce43dc443a87ba71f8b07087add245614f8f9fe0e5ee83bf8590f0fe1d056fd879bb666f7d39dd3673deafa049872a8a46b1a277b20640ad10082001040005316002018100e068322a1400e4589acce0e1480137f9a4a5e3c9709e3418e433108a230631021801800003006c0d0c8ccd44a002c65dd041ea83b2308c735f364618eb383e89ce1e02d893be5d87992424f33ec1546d066acc7fdc730d63f792b07f19e486d8f8975b7da02038610a81a703bbbb4b4d09a41550ca7b0f45d61668531d8bd72f1185b83291795d18171c4feacb5519f8307d99d8d003b1a63a47f180f481928379017936a5dd81dddca24755933f9f7cc0084083255281776248218ec974ffbbc99f69bd0b24260dc94ae21e62309a1332ac2a8756b0e2d8957cfc7fb4e0b6e3bd4baa95a77ddec4395a552afb66f7b1d6ce6ba3ae6a93e476eefee046ee93b516f4971ef5bb0eed8e4100f3a2a9469f30b0c0711ff8a482586d9192b6b3101cdc50c8ec2920c2ac8fb7eef6f2a5940491e0fefc1cbf2d753ff08516e6a7b81f112b39980a83a5f10481418d5cdcfef5e34ce826fabba8bfdccbbe20e79d3f1c8a8ae0db05b74b69976ddea87349214b4cdf0887f45342d79998b234b2dec0cc8210d9996d4b6d10fa62502a580c8e7148b259afc9f099669ec19d7d506d137e44a987d455af236bf1bbfec23667169b994bb0b254a228f66422b95ed16658e23ddbf65747592ec2b61895e8ddbaa110410459f827995c8950e025c04175d1ec8ad316ee9b164f9006c81924c91834bc99bd554f0fd5a432d8c76e8ee3091ce99ca0348f15586ecf377c4670c01dec36ca0e8cc0d786db1d34243a1fe854239ad8f5a5d3b32ce656ff466aeac9640081e7b2fb22ba06f3492be069cd984f3e501a26db07f156c8630fe8d9366b6b6debc38add52eee4c3f172765eaeeae385a860b92959483c69beef86170b13402f15219df76f6bc8c8326bd1e6d9fb65a82e05f25e97c2a9691da5408bfa53299f4ba1999765e4e2e3cb339679f2f16587d014a1959249ae3e462072b7148f3ea1b6591de41ee8ebdd282c9ead76c0d6af053ae0a314be355ed18314133fd2af0b9bd4a94fb54b2e9dc7939db1ac95b4fb5106db533859c8699ff9e10dae3d199590877f451dc69411bbbed3b957d8e16f0025d54c1c66b6a36ca200c3c8799ee46c7e337a1101f5e007c49ea6b5d4ccef4d2c51c62bf47e40d00f1be94db968259363f1f7ad6def77808f11a64a888a60c288cf18701aefd8d014e69c8752843a5227b154d27ab9a3a1b70733474562dacc8f76af56b9b15d25f05df375a6d01646adb497dc18c55fe5b5c5f4b4825d1bc0a5b461b7d2a2e2e539cd10d277fe32f3cc81c9fb9e9d77a49d870fa666a1a1c11b43ea520475b3b092a37269c1bfef91159d97c9838e50cf38a56489e7035d48104445702eece41d12e30408be05528da907933717341ccca5af76955d67a67f4077ad30d5250bd5e9583b68b46ec106700ddd5190f8106c5631347a001a02500d225d1db5c4a71f1ad35f8ad939f06d4e6080bd9a8d2bfd92bee95b6e6f20a9299f29dae41256df1544835d85fe6a131c85aae022dd5ccb7a25d026dd393d1a89124a92ba51b560346520a29253fb2c0c224258b1d747a0cc741933ef0d02b3624139907ab89b90baadc0b609364b8ca7c55d7ec80f590948cbb4fe8cccbed92a25ad4f74f520e805b50912847bd324dc882610b25fe772e15e293427e967eac6a27cef7f1f62de1ed22499941e072a50900f6d43dfd210e5c1c91f63593e7c37ecbc03b6b7faeee63ff87d39d44c4c61df86fdde6a71fb2b8e36b150ddfd3d31873fc10e3845c6b4a08c606a8c248a08a67bc3b1995c284665793929aa9ac17deb02a071cbaed4996f12856913475b29072856e168c9dd56f20d2bbcfba1441089afc097deda5e16d4f2cb029338872099b77a099daa446909fbab09f61f9ad0555fc987a7424e669810d633f07ebbf3eaedf83dd92b36588b442786176e45a04ecec797739d0e6e0798c1f825a3d56b2983b590e42d31da286e17ee71324427199f4fe41f938236634ebb96b394398001204a998546eb5eefe6f825a4d5828999c1196889542bc9c30bf1cf224bf5f8a1fc4768f7d6214843d189b918c6e0f7840c5866ef3eadae8317c60afa1fcd82afccee472b2747a2dc4adb666ba92e490c2d50a05823feb90d2e2491c12646bd6579c91162582070123a811078c262839a8603285e2f9d0871218175d13d19c108c9168c6613202f2f52e50545ccfa416c8e27f717b087edcd84ddedca25e4a92e451a1b856f72d15bcf1b0e76a4404017b0fcfbbae4d844e77093b0f807803bd9435bb1346b429e761417f9b21dd4bf916ebebe788684a75190d8ded16b1f6b7ba456455fae21dfc1d355be2ef69db9c3101d9b1a5c29979bb9c7f7e8de125fea325c66ce689555ce6f936f04ed3cc699fd32c432939e4209bc3f3347512c1a7ebcd87e3ef5249fbcd8edcac926425e6a845386f5424ac6426d5b047a62945e4a17a72271fb0f7215e43613840c254a73b974ef3c205eee795ff454085907167e711e8a6dda2fbb9a1b0d6ea24748d8ea0e6c987e730288c81c21f511c0977b4ae550db7915bbf252a7b0de300bc602afc7d5c7a2494dbc39c64486a64a412efedcb37c8f703acf3eb848d5ca42bc13feeb302e5029047bc7a2ba426479c1e1a6fc65fcdf90b8deb9cc199cbdbd98f4c95b861fde76b99eedd482ea3b407acb3dac9c4ca027771729c12ff14699ea8f827dd504bf99e592981916c39b10c7755130f0c5dff71c7420e1a0160d39b7da0b90db76d19315640b40945d4ceb0ecfa8733cf2b18a4d81f20df4bda6411f8cec0c5ef891149aff4327f52dd0d2b44c77932119a38482683cbe195db621e75eca548db2315fc8761643819127b238c5e95957471d9f692e715abf7e66ab77346f1de3c2b28a2224a22695911c1ac251f099519c42ecd6e87136d19d9cc377b0c0a38c3c8d736bd6ebd16f509c4c5e1d6fc12a75ff8a1534a0a717425f53a7161b4700651981349cdfb4383e475bc393e9eedf705b2b5608c261ffeecdd70681b91e146cd890e3d55307e4f48f6fe5de0167cdb49bb87f1a4768838a71a6943e79994f3e6b68f9752194e19c0910e2bd74bbc134abb556a90e12b2abcf962db5f9bca26aaee0233858b52363465525eee825da2dcaaf1ae96b39e6f58d3274f351221e966ec2015ae0cce0341e68efe50037385ce872451ced3bf05dcc647121b5abbb982c51886213acbd1ed18cd8a7b5e64f4246c2e2e63ccaa8a2dcb7e096bf540431547dce602887f3b060d762638e968ab5f294a191e847b16403d7f8abe42e22380f205b1f42aa690dac486aef47090c4ea2e34e82751d970115f7c98e420ac404b2cac3809317f79524286acb16ab6882a7ea00dbfc5b757b98661b20ba6a764636221937d16097eb4907178f532254b19b0df7e981aaa2c364975b579182aaf425f418e9c6a3f9fcb00d7b80186ab3238a61b020cb9937e2a68953007d4a5f249a4fac27669c1742d6ab54c6aadd248462109f7cfd2b6c91f47e9c7dfa04fd644cfd00e0f72cf51440106e3838235d017e33210270c58c6727c1ea419cd7b593aafe7fc224b60d92ce6dbefd4467c14b46445606c6d350d03db69f2ecb133e5e0e75e675249ed783c09bf0f7ec7114c36b6d5010418d07b4c61561078403d05d1172354dbcb54709c2ca970bced56a429def50a3579668743ff8a657509d4d2772a3d2dca74a6f2c090869a09769cf34d6cc9b1f42a2bce795fca00070a600b29d711253f362ac9b491b8bb14c3935851914f9276060fdff20ed1bbe6677655c1e8c25df96149df6cbfa427d108a9cbefa1e0650d56d431d1dcea367df3de3a46e688208054645fa264ffbd5ce4f1e93d324147aeb597e3600988115a6fafdefd3041976ff62248e814edc07e61256251f1a59203abd2f47ca9a305b0a6fbddeb062ed1b48f1f2d688c8782cf6da61065dee82f132fa143f0e499d9825468f0e27aa70c08aefec8fb6eb481166e7de376d16a507820d06545dc62655af9fc2db498522f6a07a33e3200bde0eb94d48ac74b582e5c76891241775aa1b80375d3490ae526ac7fe0d03d4428a6c07f4764507ce14b8da1f00f7763afe0b3f61600eec22b9e75c175efc2d7a9a27401b36faa4026a289014819a61dd847531f95f53d8fd856b4a206db52ec134ad8c7a1872a6dbcde2d8d67631b5ab94331d63f036191402274763449b8b4dd5037d142d838d6207aabbf68546bb9b4d9b42e96311e06627ea809343f6790f6bb2afe5544142b149efb0f1821dc546fca108af61ac02f205206813d6adb1265c6270a78ddfa19fcbf55a84875adb7be3ae07874dc49b386b2fb9c859e6420492709346dc90bc161fa1c5e04aefb4410501427cdfe9f1c1cf530af46cfa7c50d4303bf3f60e57c51efc207dda0dd690f71d30533e8299a1f3fa8d2d9c82eef3b8cb4c9ae130fc21a436b0ecbb02355f16bc250ece3f0d8199f5b5ae1226ac71223c2fb7d24edc80d108027757068e4fc5e4e9c62220ecd0d2365feaafd47568bac33d742a161da93749bb3cc0b8e0dbc6a97876c3412f7774469a3d0067cd91a04c5d935f4f63606b738f854a61ce6308e9f6f0ab4cfb91cff06af9062889b12e8481705c4b1309036e88064188a9235571760d3d9100a2e7496290d2de215909a59d915c80a52d37bb6f5ddb3d206e7bb42d07673559ddd5a8e02c5f955bd035e4eea3d6b6e61b8a9376d3db6d6218d4e8a0c9df1498c0a0bfbf26171c4cfa01de43143549f4865b05aa479ca3a2537390dd465d8fe6a4507c57e08f6ec09dda52460097b008d94e0e5604d48f1ad4a8803d4ff81ab2e560efb95d95c3a5e717bed480591c335a4fbc01e68027c25bc1b80cfe2956e3ccbb8053862e647e8eca6e9048799449bcb356d9538f1e3808d0e4a9d7df6e55a2c6d573e7c68e95968b01e4ff93b100b96745b344610a1d3f1a33e0ea402ff2484a8e42ec66f014502343b4ecd7ea91309dce5d36d1cf00954e3b21218884cefb38e165f8792cf589c8c9eacc9eec721e5f4423506a02f99ea9f3382f2c57799cef7d715270e568276a0f968b6b82b1871acd05a4ef5f4a94598811083bb26b1c7766f08530c496e90635dd045d9b46083636e9d714033bae491840638e5a9f814bb82a807d403daf6939c810d350845e2dd7d3dcdac3a8881af1b9b55e6eb3bbfb941be4fef7b02488a4f21c40179eabcdafcb9d60dcb1492385970f03a03cdf2761a94618e81c633188c6d2c33f88ee94087d874d005c41d3f969747767b0d214c05cf96ab141c2f8fa6e6440f1e0b0c1e4652bde956f88bebc699ded1bc98c03ca9e259b5baf92d96a82557880863928e9292b8c564f586296094396c2f1696c92cf317e9a6171bed72d258eb9a447d636ecd532580693ab721513a37e6ef3a13322e32c88166cbddd36623095f85ff2baa6dc22b3028211b112069323a29a011fada08194fb2bd78fa5be631afc50b8ab33df24796d3a778ce1e9ec99651c515ba2714c16d61b79a2d7cecbf7a7fa4b8ddd243fcad7bbec56ef897308ad3054459ab906adaddcf3696746a52851ace3081c3b136cb7ed7e54708b867a1f72d32b87507a70e1010a4039305b3a196b74a5a079a13af8c7fc2fe48f848fc0464a045c982ea50fcd0248b85087419d6f14bcffbe02c5815612fcd2cf1e586312c33681b2f18576e6b7a28015daf6d5acfa8e44775c97464a633c779f28f9e0fc135d0d15ba63bfa65f1b72f526a690c87d9a1ba47c9f905255b6a022c4268a0ff887979aa2279516d6b7d03a30796d2c89b1d9e8df9b914417932b170499566cb98f3353ea723ebe69b8453e94b802980e2ad5dfe543b24b11d8515e441991b28aa02f6c87ebc52d520709e8cde6ac8b5b5dc70f44a9a9b969488f45a8d3459e4aee655c6cd96a5c023453b24a15e73e85455d1681a6d2ebef04149a6e65000592ef8f06c3f0f1b8a3be05f12653348b44a49f925cb44825bc318e3c9076e544347747899eb2aa23ee7a58b191ad73f03a9e3f25f61190d1746c658d59acd44dc6ef32926f4902290589ca18867c15c217df504d750028638aac618fc8e629571908804f7eba38bf53b5ff21f8d5f1743cfae96127a4d8d249c54811827671d0e00121b11d199b328c53c822169b80d2a3b490579063dab849c70b28b50d8a53cb9185ad547828fcf146e27ec1b3e999f39c8134d67287f930b37f976080379d5c88f3c1bf84465b569013472f600d8ffa9c3dd69923d192fcfd1053e59e7b590cf08a3256f01e4e5e9070fdb329f5b6618c53841e4ce87b15120b1cea3eb7c67668f74e5c96a04d44c5b74b9f9edc434b8dc1d714ba6d358e7ff48a950c1332123e5b2e846571a2faa6d42c3a8edd9609897a04e88d4a19640b746c155e77a332996a08888008b06ad988870fca59fc1802247b25c09b20ffc0fdbce4b13fb548a6c14a68a590be0bc606eecaeeb7bd3cf989fe8d38a5d769b40e8b1ce201c23f17f057c01ea6cb747e2c655d2ae7fe891403d71a68124da323785c4a2a321f9db972200dc5890dfc566b4e83455635abe4f13823f71c80e45dd091aad9341dd899e959c74b9f6d3d3263c251ff92827b6ee24c14ebee653331368d961f0af052183b1354910b7d31ffb76d2897569cab6921599fbc54bc980bb3c7f8420fa4541726621b144660611df8b828e8ced6540c487b0275699e37054c52b3f12be37ee2a825b36f5627c0aa99958a63b7073c49d5da1e0572127c3abd97003e8864465a051fdabb8c38254751bed478073192bde038597b32582874d5aa5935831e1e8a2b561586ca61da547e9f1f35194a7414ad90d34bba681d5e671e1c066fa034a8957d40398b99759657fe67a53c2370fe86cd23448c81a98dc1192a7ea06a9483d9681de3f5a43a10e68307a0b77588fc140aef301c59babf091e21708db785fed0d99363ff69dd4aad16e4494d5696a2eab7910ec70546f75e548990bd769f725339b81e2eb408a0b166601a4f302e25e82db5a831070484e8e9b35df61587561439f8949feb5809ada43b0bf5622052d8068be5cdd20fe0e052f08dc2a37f6a25701ee978364547223b95a87594ba341913162ec5682f874153f43ee93bcdfd5dff376323944de596b6c67cb2c01675c53f2cdf89529af70fa52e171f80b34c7b138f210ff262feebed9a356b55bed9f83d5ce8ad2478345ca8b761bb392d02765f82494406d4d2060ed066072c04f55cac673935c500c49c49bb1ae4423fd9425df2f36105474b7a4c862cfad34246cd299987cab93e61767a2510636ba9e4f59d249bc0dac773f37b04fc14f244e0bd4f30cf314ebbf8e5768ed92c1c7b9e2e42288446e3791bdf2c1fc031a0e3e4ed5b3001fb2211c0f02c399087878eb0c4bbc52bf770034684c002c58caaf75af70564a8b7988299cff2eee35607647fe4d1f087dccd82b2b003f3b38c20ebd11f8f4be5691c9282a2e4a762385a3482b33195d35de78f42bd8c9b2851c5f05e67f305053454f762758727de1cb3f610540efda703328e0013139fb55a01d2912b2bac3ec85b9edddebccc5e5c81d1244ca3d0a0f303988efc28d5a045069ada140ef6065fce485c3a57b2a7ef624b91493ce65b77bb83f1df79e6922541ff6931fb8dccc8c52778b73e2c556829caa5ef396a273670ec86ecf0141aa49eb2eba6338cf56ce53bbc59cdc81dccea8d1236d39696bf8cd781484a7e325cb39b60f4fd81734a3680621aec0f3ec25c337bb34a31ed516c7fc437edd92ae9c2d67ae9cf25fc99f251d7450d7c0d283e9828427d0bdfafa64a8d2bf094907253b64132b77a4e9cda3dadf089e70675da35bff0757578f3349b748d6fb8b61b36ee3e662ab98cbd12792d623f444d9a2e04aad858288b8fdb6527b26e55a2483bfe7fbb0b37f62a83699eedf5703dfac6d0821d878878c2efff78ca4f35aa23a3d5f39ef3ba80fffe756d1b784b667e2a2d72312f5f885a1027b45316902844a45dee201dcdf64285658baa847a25751f3bbb465de7c817064369e36629a9e0203d2bf92e937c05487357c07e5de84dfd50140f3c97e1ab891d33016a6d3ab675f30283498ec5be96e3b73d408c25de19d136b95736b565980081f0b94309f0913707e2339f0148be8634f7dfbb4bdeebb3a08dd88adb915bd26eccde393ef53a758f45424fa172656ca40445f4598fa52f22ad76259dc60b84ae6ddeeee3a3a391e588f8fa7977d702b9dc6e84377b38de729c81a52703db177b5233795fe4047c6cbf0e472641f5a3af955a4362c44226fee3a94b34d9865d1a06d68f0962216d4551759bdc2a3727a50451e87e81fb624cc2792ba6adf222f07cad9e327a549fd03986a069aa16b10cb6cf2d635a137259460f17730f1b8d495c9af34dfc0c00841fd1fc12179a8c3788782ef19b2b0a08dd84b673dabc8d887d9dc0bf1f812a9d979884ae836640ebbf5bf286142555d31ef225cbd0f7ee8007575022a707f6d5e509367d62f1ea34d92a65075dbfb3368705d09d34c9063b9519afa331f02c00ebd6ceda9ed1c92ec490988d26508fc13153f3a9084a593c55ca5135032cebed1beabd130572bb286d33538a0d748dc0a44ed023cf5cb8798f33353f670e72dd6f415c830fadedfd91418180ce0fb931996901cfbfc409192ffd888e78ba20e3efdf681e4399bf5d86fc0fd34be9e06a478f7dc4d3afa58e1ad463bccde5603e992ac5e08161679645f060038188514b73419d8893d31265a3ed0d2499fb5328902b6c2406562a43dc552ec020854e3843303c7299fd70c543b9eedf779452bd89ec89f38e9dfe41fc2b47b1e1108e32a002556523f083362491e47324087422c0c0ae3b90e81d2f683e0e08197117ea7dd5ec9e90e2a1504c9771867f8fdfbaf222162d38ba60ee7f282458cdad3f56e8f9c482629167e64bb4113e970a8568fd1122911d4960c3d08d91216420f72a0348942c986a7c4d24b35f053a53457708854bb95cd10348c5a529a2d53df38dd440a08d57b52c2e67de1aef2d231c0d1fe9bc0d0143b88540a3d3251283e59f3298815d2e1588a90335568a50f85cb51e5c95856702a609fbd417aa311db7b5e50b0d8c8387f4828af2f7d7c92670629e808989a1db3ea050626536b4efa83572dc5c21bdf57fd58a509f845b3193fc9a7756b0816c9ca0422cd58d4050eaee09260f66d46923ebaf037433da44d6a5566ab849fb7c225157bd487aabab056c972cdf787b0c6f6707bc74e66d7e60c0140f7f2b164fb3269bd7b798337a1343c533f0231ae3a105e587b65541831456bc95b5710798ba23f069a25ac08ba7a998312262a70ccccdbe0bb3076ca7d6ac58571aa182e6228769102d8aa1bc2814718130a62648c68bf8a1bf308fa8664fc490eca53742cad34fd8b017b8d0920821ffc94cafae3493158046113810c058058d117c8ccd918d0bd180416fb7f3836ab92282de3f9014847bc53c35e08ace2973d45ed5f219cb8297d2922540090593b3f1165365a47a61505a939e88da5e8ede378ad366fc5906ea395fb72edbdb5315c543f820002ec4016d45fbe48dd6e0f954b408ce48d432799041878b9c0cc0b84f2882c2a720d502b0bedb8310b0bbb8c4c5111f93a299cd433c74945232ca5fc6d666146429cd938487cb6f662d037c8fce78d229be7a0b7de41b2c87e69922614934fbe2841e837691d1198cac4be85e47a27f514746f4387087d9be411b32493a1046e876a57db8a9f4ba7bf2a21b321943a07a000eca90d5ad6e4bd905d428690648596499ac91174e24ced6f4e03948a9a0cf20dea612e664e9c6c7300d4cc680951f3af1adf087b1f0badd715c674e33b90cb48d57565a3626aa905992b7de543d1fbc2d700d519f00374cb9f24f9bc465fbc2f125e4a143f1b5462b934ba3b4eb4c71897eb57990bc4348936069f643bb993c495eb4464e9ce4d307d80b43c3544b6863f384adab62b5a0ce23fe7316934b42e39c7028a469bf09cbe4942ebeecc0e70f8783e85b062681dae7656622e8a415530a57edcbc90610cb8ba51f6c00925972e75087362a78243382a90ceb91ac0defb19bcf033f7404d08cde7638d749877c0dc6e8123c8256953c5b93a083ac074664a3aef32cffc780b154f638b3e4522b05c36e5e3894f20e9b4a8f42f1d95640501cc6a6d18b02f88fb422fdcca874792b3e990289b870c9acdc359a6cd835a531ec32e9ca9a07d6ea8244ba30e32c41978fd11709be308d18efbe258290d1bd1bec064569bd43c233e22f3e7c652c4e38adefa9ef6c3462fea67d40aa19d7c381416d7efc6c68810c291143a4ff17f98c2a88bb64fc881921a3aa982f2048b4adf6bf689114680240665c0b44d9cec6ff97c8f2dfff50cede76026ebd3fde72e46dee52ef645fee00bd00aa239bb6586b6641d44376190b6df1d4e8d324f6bb427e4a7d1a07ac90ded3e4f9d5e4656ee8972560f8c3cd59abdc5d089686dc5124ff3eb58119320642bf7eb3858fdb8906fe222f8190f8c0c1a3605f8892c60e454d79624e7bc0dffcda84b20a3fe0ee56936f2deca16e7bcd081bf3c9e8cd35f54ac4b754d3dd2c8d521fe49611340115b42a3665a4e8d246c4d937918cce40298712df09077432fac8a6b747c89798b0e3fea5efc368f46b43d83413b019c62cb8319c8b4f56d7a0bf3ffa7cebd6202b1da2ca6bdc296a1dcd758f841ce58a04d76049362542e4d21b83093823adb341df7c13ea334cb0177c591a81fb0b0219bc108bfcdf3163fb14834f19c597151f1fc749e17dbe2a2ba38232cce656c4dabc50505c6c1ce8ecbc772eaccb8491f80054bce0ec627de084c7c1d8eed2e027d60b715c567ea37a064a1a219d2af8f55fe6a7664cedc11c25ca8c13690f6d4a62593163cc25de10b3b32a5150e0ee0c628b07649a820eab595003a58ba4ec0c1f73aa4278c79fff99839a59e96e7e6d2f6bb9be2ba2d72075693a99a59555b488778777f5855c8268d4f783155b31224054bef0b3f1c0bcedd00a2caeff16995915465b3d22ce318c367e1ec185ea7faca9ca9326a95999fd967a98a53dc60b8f3be27e2128a947abc3fe1b1b29eae227c18f70c6394290678531a26b0e7328e5292dc471906fba4e2bbbad6e9d831efb5e91968084822334e0e28c63cbd007d66846c72cb6b1d70d4d3e9e69ee70acc37cf0829c5f22f08060145b81c811dad918d3ed001eade417ffbc88f3a9695c068736b6425fdfbcce410e4482c3450945ff9923e5af661ddd249cebfc76426d95e2cc22e3453f14d88954172c731a8347db10cf08f077d81a5a0301224c09f060945b223172c61be93a7a8f503c1ebab3085260e37cf7ab574f821b058b03cd90372bdff837e9b016d9040a037ca1a0d3b51c9a4683e09bb28682b2e2acaf865e413c570aa5d70bef9358f7ee455418111cda2bf3ce15f4037420942d6c0fea3ee610149e426a43c421356430d280d190b6fcf101e1af650aa84ce49d108b6e31a7160bf43f680853460904aff046c9712c642646055e85dbc2ee9099f48db546a600e8cfea1d8f95e3f15c35652f41e261aafd41053abe55f96a2ff901aaa2f733be85eff895ac15c8dbe23f08abad1e3d2b1c535c4d9edc06956ba63aff0533d1f6347927738837d70a83c713b82fd9749ff990d0e72dbbb2f0817bf6dd5019a6daea339ab585aa4b666965f4ca29d416d685278d1d653edf9cf38d2be134c4d5eb3692c1caa167c3f3a591084ac4d352f1c602ec2351b6184953b255b9049ce7bc6bdd44355e042ab8952d503896c0011a3f61012a7b83fbfcc2dc597db5c60b5c3702dca0a4f5d52ab6474e559adf0e1cdd6f74cffc4ff4808432b8868f40c7bb0319b6e622da1d67ddcfee8f88a5c250ce6595eb9aa15e46d8af82c0a7d12ccb4961f71683aad2a1ab1aa5a09e6a3710b0a555870acb2c251cd292bd2ecb35b46e10515996d0783fabb82db59ed2fc45a5f69820087e5d9b2c1d39644121735ebc166ebb09ff7719eec1827a6bf518d62930965c4a66274b79c59624b14d54049a2e5a21c07c777ee968c2d298f0f2dabc43657bf0f4125b610d52e3e5e503156f2875789ed8ee4035b832c9203f78681445895853bf7ba3a506f8605081148d4b0fe803d87ffd669f877cff51036da7273d1ad6df22ea8d13a4408bc20098b7615eeeb968688aa7922f3921367d2288a47db71f694666f361ff40023931d40ab835eaefe46fef5180c9ce155ce39e4aada4115ce7ed23591706b159887b040d60228c0ef718be24af9417ab8a91df82a15083196f93f3a0a9da0159abd7e6b7c56479c9ba0bef692465fdce925124da45e67fe5d19a2860b23478b9b476de912089fceb0b5d39f9c68d85c15fb1b36829801be101156eaef7b2eb1f9ec48ed078475cb0ab92852a0e1f70fd2da22959d571ef4094ed29c319a2833aa1101bd03292d827d62ac80288c2777b9ec3341ed1f001f9c0901aed5ade0629834bfa060d2536c1d84c77ec49fb6517925a8aac57e793cd3b30412e3f38715907d5644ca1a7d617e702a5ff7082a6ac3970938d02c5c3b141ac92a2aee7a7abb4197be4264193042ce5c541391223af08adedcd08463d6b5f39b1065b0dd167d24b62128c966f5fb74b01709d647893bf128116c20a2c077da435317a0359d4127a730c1e93e14ebe5cb9076be301c6ab90cdd6c0a91c8124e385868333884c160734a63944a9e6dc64b7fe2eb71fced92dc9c990809bb052756a66af59248c75a61b28c85bc7e90e78457135a53336271188030d150a239e67e74b3be160a901a73dc564d6ad6146459acbc05e6a13bac9a577347e35fbd484ba3d49805b4e4a1e67b2c897159cd484fefaafd1d136d8e4c9d1ef2c5f0178e9e4ba2e54f0f801cef0a8659ed8c4a269ac3180db58b949249cc523340283ab083458cea6a050ff2c8bd7b5a16507e2fc0d8ed868bb0d8417aea05f65899c92881b3f22a8714e9f317d0aafc01f7d0147c76452c6240fb55de87f147997f64d32809edef7a24eb9b5017d941d8f57216c4d7449800672b2f63fd7f6f2d8aaab0edac40e05a3ce7e2bd6bef3d6cf5c12a6c32c067cd20e7457d884bee1fc63615bf7653c12d1387ae02763146d0a953f71c7bc0bee12ff9f308ae1aa101cbb1a36016ac927811c8be7a7a93ae6866a426d0942ae66a99c023db1b806d424866ad91881bfe29f016701f536f3b2955fc35be3dde5a9e2f0fdb3402cdd7795b0fd09bd2e5b13f24c9674173dd77fc86dc233ff0e97de3e603d2192db3dbc577e03363111c1ea3c08b5147ac37da7ab8d33f3401abc72a77bed5cd48f95322290c4038bac2ecf1afa143b918aa294324d9396e2cb89d13df16474cbb40a23b8eeac420f9e1e23ebe9ba4ca083dc3427099b266a77cac8d21497b5b81a0495aedaab8708c0dde96a0b9ca2dd539320ee96d7fedaba23acc805f12db1fad9083906fb8e2cd0a081bed71fa9d285fcb8d599c5e82a9554fd366936f1036042fab798d2bb2decaf863b8d23672d6802b31da34e502796d153a183b40bededf2de388c844ac415236e01100a98608f0cda0aebecfd68b33841716105b120729df3d0109fefd8ef4d26311b1df4f63fb37927bd0dd191494400c4cc56d18d475a1f201a4e1f6a6c80b0c411cc172e3005732305fc460d333d680d1ea43416aa56d8c13c8edd613af0caa9946fdbec410361ca699faca9a1768ab65ed021d905cdd8f284a1dafba0095e32a100946fcba3903699c1f3b1010e327726aa5971af683ee49b089bee4c5a6a0f786ab52bd8a3b29d559e78a82463af18ada2ac1a29d1fe1d670d476d1473c4404e31bf412eab96340730d2be7392c29ac557050d011ae9976b3e17fad18bcbea0bfdaf36062a36af88e56114f5108cebef2ff71b47f0cde528428cd170237b95d52f3649417eda00d198a9ab376ca406bf8e1802ccdd2f6d799bea21a5161cdc4c0fa880d16fa274eaec35593e780396438d62633a909f91396900b16d4a1610fad1cde0ad2794ee9e2b724e933144cb3e746d0be377e3689e15b0cf22a5cd3b1f102b44946483987bf022c60b61858f08dced8887d28f05569caefe1457e673a77685710c75d0a05ed8073933d8808d61fce4dfb609a08b3c9935a8799c746379e352c07481f3e7aacf401a06d5edb84b6f0660b0da68baf5c0e38942ec217da7e46881bad5ba5caae2aac0555f3b17365b21cfa0315a89d858d8f1b426b2bfb8303d7c18b8f97dd20160916114ed8c5fb36af1b19b9b8f50980a1ff270ac8a15e2f5856afe94845a27243a9be93b471c4f4e4aa1eec402c7e26afc7de69328db10cd9d618e2aeee6336ebedb49bee284cb3a4a91fd248f03b4145f8b667ea705c0f0ddaa0d1af8c2c2ced6a2cfcb77b595b675c5f5b1bbeab2dcda0ef69d20bc4e34e30d367bb6cc4b6456ee23b22fb54fb664b49458589c83d730e2af1f9350ec119c04029152aa698953d4abc94e2b3c2c47899aec4d17e77c86f0a3f8089b675dd60a13f963feb0a4e9a946e3e4fedeff365d3e478c9449fdfc5eb72a5dc936ebca4cdb85b5ec6c0217bb9ed4f21ea778933b573a52e8f7ba97805bb205f632677b75ca19c95256b67149a72e113492f533f721eda144ec1b2be49fd97e79aa12c7706ccb4f74ac6c99667088352a5f98350dfc48d623506bacd18367a2ab973d06e586c7d5eabe61540c9091f1c591cb689da4dc723f75db4e8a9207c83d7f8e05c487b02689a1fc867197a0d1d38ea1ec5f277033961f3658962aa51401b3b2790d2be9d117879431097bec3efd6df76cf06928b000834528a6dbe574e532bb80c8eab0db8e04a8cb9ca3f81dde363d7f20613c7983bd5b6e06c105ae6e2f535624a1f89bfce4312ccf1334e4798e15f0aee3752b9a052bb4e72ab5ce629db24b82fb7da0c7f085606936f01aec1c103bcc7c4043ebb606e55c5d874867b32beded14f55b25fd6b6a9057d16d1e5a02f349962ab256499bd09bab584a4037d6fda634c16add62758c95b9db7d851d8aa4d4ade0bd8760bec1c94e017f49e46e5b8a363c7ae71a9a3ccbf30b6f0542cf8029e94566f42817eb3a0bf06db76c7da1a5c62af838ecf67b6fc6232a378f61856d65bf8aa0acbd6750eacc0044d14b85c831b1b4367a05448790b96cf98f4478398782e1fde71837c881a047e0e872c5e57b3b337c5204e42ef3d2cdafca83de825caa66981b1df67c1b7191524fd0b0d5159a0608baaf5cc5c9b938439cdc8e20d3607b3005f677b01d74023e5aa25df19034eb4d914095ee1a468db53e23dcee53b53ee136425c9332c7cfeef3781078d03fed60596cb77664e4cb7c6279a7fd137fab0406887efeccc08d419825620c30d0d1e0d30c58f8ccfd0c42e6712a82ee6d3dc1cd83162b7769f6a3c9e2161e83901df99befcc576aa2a6e0e17c4ef6fde84d5bc27f03e8f0ca905e09937c95cfd21bc6ed7e43af57c93d08371f8f3f402970414ae23e9cd5d33c5598a6104daf9fa3c262225e4a68bbd30c652560d1a4c5255e3ee9cf5f3095005ceb76c9aaa76ca83652bc4adf0bfe1e64804e11626e1ad83e43e6643546c4f9a95a5ea3c05b029c2f8d9585a86b51dccfb66285a28f06acf295191b4da83beaa53b43221ecc30cc60bd1553aece2e8fca800d01844387c9b98853229eb329a175eb2e6076962f058ca597a85a934e941ca824a7aac76c718163e76c86970a6a938956ac028c270c9dea4088b5a6fb2c65ec14651e330797276e760f009dcc0ffd116982130f566470d44996db7b03dae756d4f341c3c12fea3893aa724ba3d7671758540c8e85082d4c00886fe482ad065d42b1b9560f59e1552eb3b2b800a1c211cc8b9d197a8668d398db495807f5b28db4afcafa29c91be82f269e43167cb1d987c93be826a758ef807387f73e4d279d4de01d87002427d7dea254c1574baa7a2841c99d1ba370112c75ecf29be4edf44627de91265d5237abc86c3585328af84b0211d642efc2c6db71db8addcfba4dd665831de3fa975edb36a28bcf4f73b9b6f1951c2845421aac15e779b1f3be5c60d3391e36c8e827efd5d1c6858caeb93b0f1d14db4262934d14068b31250c3ba83379ff38e29f1834bd458f8639dd8fb3f192503a858689b614d824f647b370d7ef1cc54061ff07d850422a4e5c76854c5dfeb0c9dc1a84415f609085af95d25e905ad9a4cfdd435ae6cde60e67bfcda5eca213be2c327a2dea209eda6b6b64ba99ebd9d85b1accdfa2545f88dcc673ee2fe16dd32a32a4c6f534194b8f24f3dc47f74cf29fa6245cd73ca3d6e9962bb889bcff371209f8a1f3068af50ca672e2e2ba354aeb74ec7415739d16d23ec4f9cf7231ea751e0b583a39edf92f447b3fd90cbf2ff6a3fbb1996bfc71968ecc8bda32559406dfaaa3ac03ad425efa67cfd884007a34723d272ae08af7ec4cbcc94de0064eb6737340be22c3af54bdd3dfd5f8affdbbd94c7add21dd89ab90d3d8fb6a054de0fdfaa844adef5917594c3df70ba36b1e1684751fc97e1ea2a4affe2bdba832b09c0eb90db33a1361e58b390f167fc31a79d46e0ca41348b7dfe23c00bfd8c51af14b12b2cbaabd28f6233e7c2d62a0a48470f746ded6875b18b5f74c33517843d964408a6209d9d1f9af302cc01531a963d29b24cffd7b94937a4255084bc740cc58bee5043832e36152ce41b8ced19a4e08312cdeff31b3d1ab088036ef5a1edcb7187cc6c554c04042cc1588cdd43c6aa77d16b285d8e55b86c6c09bf020d1061cb951a479f2758189a2ba1b3ac30f1332dcdf411bd94630af229c03596fcbbbcdca34514474ddd33a68e3dedbe35a58d95f82a24cd0a5e0fd140ea49f56a2b34fdd50face58aae05d8e2d98088a5b3c934bca3edae61aa93856d4962df7467483793d0f3bd517a2084ad383e3e31faa23861dea44d1a8ab4d6cf56f791721e19cce53a5ded0e272d354dc8d0ca6a17b47414a9dfaebe5c57ced0c60a9d27a9c2962ebfc7c958e3adb3a355c843c401df74fd683061d6aa402f7b5db008d917cac217142f588583aff9cd76b957ff322c839154930c471ad0c907357163cc5641033457ea7e08f90bc6e44e5958fc539be9ab1339ff3f381db7d037e224a601c61c1a41325bf04b1ab0099dd15e224de0cc584ac081c611f333353d68af554ebb394c7322a4875977958f779e709e01ba22f675d2a7a7c8fbe1fb9b5398cee09b3e2a19e55052334ec048df70dbcef2e4a3dbb318388ec47e560bad15b8c1871380e12a74fd73d9e4fd687de7061a4ccd181f7477ce2d052196b72d3008afa94e3114115d01331501e715b9f15726cc42071368649e8751c122303da9a2ca7a8f6f262508adda9647d5275b5c0b11e22e16da65f48fd3859e5029706cdffdb7ca110b8f82727afd3e6b7e579ac39a5fab3c9a838ee61ddb206336be51320fa018b2b9d248b5a0d7417b41e43d3bb4e18a5581f9de36891b45e696d897763efc6b6f12f0fc26b9b66cf0cc9a9f9b12b9bcea97bdd920e02362fc7840549b99052ec9367f5b955d578583e37f414edaaa0493b6635b1491ebed388b1dab61aaebb9235d4c5439a23e7cc4d5dd2a4ad02784c50ccff74fee83fced5710f83e5569dfc905cfecada97ea1acd41fb2818252921e43dc751f99a0c8d0d8fa8638be4cdb2108e812eac6362af6f2f0af4b48f9f29c01161a1f96bd9e52168baf475aff4972794e41e0991b8b1bc974575c6e607661c607983f445e3b93b22fc4479ebb0d17c1385b987a80e86b0e1e64e0eb16d8e07db89f34aac4d7a2c122bea1662bbbab82f5333add2fb1847a41b9e944a0669038d1c136d72461d4d8fe02d9e7930170cfa64ccd22d6c3c465fa419649215069da16fc25ce18a78ff47fd2ab8ecb47baebc96122bd7da2a64826f9319037f566955f2b8b586d363312aeb129464fa2d4f729410da20f5cf64fbd68cf54d3458060e3e0f4d5c88446e0d605756b10975d585fa3b8d8c5fa1af9b80d680914a1e86b24c435e8705a59da6d11259fb17742a60aa3c4520b7e65b7d13e52e2fcdcf7bb8288f528e1cdb4f1265fda6d5dae6bb67d6f6a71c36e6e4b725465c4571a725cf082d5a8b9e07952f4c34d43529322faaa623ad76b673d7b23bd78b7de2547d1175c9359fe2f68786ad351a39d1e78807bbd05d1fb82d3d487ccc57548e2a9520f20034a5d0c408afd21f7fc1c3dfce8a393ed11a38129837bad0c99340a24e744ae27deffe76620b4954192605b2a5f218020eebfdae55ad9198a4fe91fe08e7aaf06b74bca749a5528c568966cd13e092ba2dbe1c02d21464d12f4318c17192884ac2277bfaa5db5b91b60c17ceca47af58e1acd01ba9263518f1f78ac7b3de8f6b2033d095dbde378f30ea86571f6b0958453fbabc95d4b941bd66035813bb9107f23853ab7a73a16c64ec85f2e9aa81bf47e4c53c9c8ceeca4458c45aeb9264f46cec4f47ca7a36d07d871c0115a784a2101f4a338d54d4cee20cbd78a07a7cec348f802bd0b05b3b873e0a08e79f55e873cc3ad1ef47b45253e454568b08428338abcac7dcb19a1c2d62f4988426a64bf82f2830ef428b3308c6a13e96361f369b391eaab083e25cb8304af3ee1d039abf49e748f00a582c29e46804a5aad60421da2c8e9ad21b5c5d6a8caa988f9b050096a24241b6d8eacb41c916563ecae0581693a7662016b929e087b8ddf9d067ad05c0361330c424e0bae5625a42335ff5e417f5537d99a3b0db616d23e657fb6bf842896c3731562364c6849891eed795510875a4b08905a333996475d4d35e89539909d1c49402f1c74febac3055183c59c2d1459e98a8c320e82c0488f496d7536237fcc31d913395bc49fdb0718c0fb00c688a777ae222e4deb7b30f60ecabb2ee6ac41e6113cab25205b186ee94d7568c4b2d17480e1b94a7c0ad9d2774df1543306540e6e00134a42f83f711b283e8661da0ced3038fc2cb9297a25b3ff083c0f4ea2a8276ffb5d6a33dba50573d7d2cc9061cd1fddf895c9f7ade25516667099cdeaafce4827b00f81776c68c2d9f9a57c2e38fca382255b78e116f56142778222aae5efc11ad026963aae8380736688c19a98c0d2f80af9a58682649094e6a12b13fdde99ac447df5e2b3851eea35142fece8f192c3fb226f6d0e0b79874eed9c125a002a34cd8bfbe33261284d3ba119cb34f99b0058a4d28bbab4f3b21d85d0687ee8ad65c3348d28c3413b8264e9f0d31106069fd63511c90682cc75e5d3b6b0a43602f2c6c499796e54e6b0e54417a6a5014ba38e848b9c68be11a323efa403b82a1a652222e63dbf37bd0c889ff8384d05476042a4ed217cb0121f1367df956e509cd93dc76f693dec52abb4680e8dd82089ea47cecf3cbf0c2b4e2a9ff2008dd0ebe706074f69d0d0ef7b1b9046a6c059902385931bc62d30f2e1d42657ac4509d8f568a93431520f773103e86d909a4bf109a11f34f45cc335b82bbed95a81d038c916b745dd76c6712bb78a1601ddb8108cee60f7215de7d1a09caaa8c319005cf8b155988b1d68fbeb0d4f3a63b1eda07b63b07c37aefbe58fdce13e933178958d6b54c43ca0e477c5b5f037a0fefa10dfacb8c3b1342defdb04596c86d027bd457ee61395ce9963039ede4633d158796f64dd3e4751d8acfe38e1323ea8f61661b66d84621920afe1b055d0aeae63f6e96d4b49705e986b74a20b1e8d5db0adbcf3103df7a9bba87bd954848eb0317a1bddcf1b87364555e1c5235b7e26c02812feab65b0de35e2586fa2044561b62a9be3c35713bb1647e0c6ab194527460b5986f56d024ea83fc1729ee2eae0b6aa7337e35c74000159b2e73e100ca0d12bdd04a80998b8142e6146179d49cd1054ba0a2a41fa2abbb0aa73f72f6e36225221f81c4a727ff90a173468b2c236d5049493f5bf5d313a63b292a66721d12007ed8b2951cd0322d1425c2aa3aafa3f09ab0c1b68176aea8a92e615e43463275a88d94033c85b07f9c81d5e7dcee5a0f2cf76199be3405d79de8fc316f54c35ffee6868e221989a9268bee91537487b3fed06e04ea66c90858e7660036f5a3d070a60a1b19d62af2647c6e57594d2e42aaee152234528a87ed620cefd225b1e1d8f1a70642b3814609b14c7da4a132803f76532ec57992843fe7a90662259ef7733e5298de50d64e2698292d8a38515ae08cf2f237fc1f520c4ba20630841a2b2a3f0b8319786375eacaeb60723373e007487c2a3fa422e04c472ee2830480cccca2342f5936851cfe7ca4004a4e5c7d154a5232875610611a813c4a98ce9b698cb50bc2721f08680863d6935b8bc45962b2268f0204ce4c058364797b0a70f60b716d011e4abe7ef60d65cd49d49a77724f279715a0530ac621106aa63d425b3f3936462df70ba25b0dc6ebe4f0d0bce762c70cb2dd84a3111ddbafb631422d7898a097d768c5cdd7c6b4235cef0d6d119fae78300df0c0c03aa1d566a5a4058555107f92bb2e84a0782b915db14579374935010c6388b820e7d29bc8b1e7dc1fc761f3ef00c4431ad76d790bdf2e2e276c2b89875c61be0af819a1e80f691472a8342094f5960a4ddbc8e81e83f05c4ee12cab6a54c29a572067c06a206dc8bb8ee392e94a9dda1666ad350559906fd5d9ef29f28e6efd47f9af5d4cf3d330e0fc6611d28540b90cdaaf8db2c0ba8facb5bd5fde577d2b24143b6594583ee8c3211819a3407ca5ceb1656e5c0cdbf16085b28aa9696abd592e26ab95aef72b55a5a2d2d57cbb502ba5a525c525aad95f3e53308dc8ff2dbddddb8bb312e689793bc32899eb147e886b6eba541f798184364603162620c69896132994c31626486c8c4c4888901e3d2fe1ebf6dd4187222454cafbc86c95931434ca621439ae342e736d480969c20c2f6c4e5a0fbbea830febeeb832d0a663f5cdafe4b4b830de3bbff028381c174183f97af058389d99f93d25d5a7de955d83368b4a5a5a05bdff9dadf5f51046d29d181b613a0e5a0e84e2dbaf22f0b07a2697aabe2bf8209aaa2c4051fe0dfd8a8503e770b143fd0094ab7af73be41b05591fd4c83ad8afc46b5b8d096859483e23a3bbd9a1fe7772f12c97775c772683327b64820a2a3b62c7ede0431685ff2c47da717dd7b0f23f4a2af4654f32386fb7dd584befb4edc475f35dc683f57c44783f241fc758e2c07f4cc3719176b594efbc869103f37620162c93932e69e06a5ac5761f7e0a357e16c9d5e85b287ee216753f267e7744e4e08d5eda4e4d2389238a2266ac512946bb9c5a6488874c78e1dce6e726766c93b5625eea8718aaaa257a7c511ab2108474c36a3c9765cfec5a54dcaa66d907d9d1486a0f2675a95f8279ea92695b02105493cb16212abf1651efb917da47f6a1f71f5022aef2ccb2e0ba932cf35792a7ea76c81c2644bf3d967a0c11935e4f09adb7ce6b4fe390379cd83862334f41957e33b2da2f04045dfbdf771f633fbd9d4be16f49913a97148e5a8c043149ea8fe71dd51281a9ef2024dc5f82832e6469ecf96a59d87d3bce6ce233441a0191a85f3c7dd791a8c338f1ffda656a3e3681e9e6ab5bf69c6de3b734610efc8ea9e471ad51eea33678d7e6e08f47da459a3cf797c38bad06f58f13b12ef88748efaadc607452ef492771a8272fd69c1c3594ea3a0190fe751e3f3a80557fdf3d9aac42f91cd6a7c92110b1cb8b62dca3080eaf19964c422ae8a7f17e2b8a148e2e78f77e4c73aecc324c6f589743528254d7e943722456eee3e357a649a9434dab22cb12c8602132142631a6c59ba4ad04bff9808ca0fa884f1a0ef0403fa53ccb3c4600839b3d80bf4d9f811f6b0e117e8611020088fd7081c8063f60a010182f07881be1a93a7e4f4942440101e2f9115441fe829e9001cb3d77a0af4cdf9e23e1cb86e2485372af7c15c5a9ad6c23edd9c0d1c1423df3a15a5ef4459e59d5eadcea98512ea4e51a38bb8801a472e40b75589a85542ad61597353feaa65e15f623764408d38a0079de6697e31df7d367ecc2fa6fbee3bcddf17eddefb4ef39baff835dc28f7205b83b1082ae43e343f0c3de8e35b08c53db7d08386f4c43929e550a8876f0d16693072219028c4b7663188fb984883311609238e4dc5979978a0a8a02fa4dd4fc0fbd653df04683c155ff4ada7dc7d25497e2a14550e28385c8b5ed0dc9d121908dd8fdfc21c3946ffb8c2bcf139b6377fcb323333f3333f3323c153fb0ba9addbbd110b5b75556e830d687cb6f1e2a49371d039e90c9dd3a393f20d8e8e5eede8da9c71d6f4de9b11474c2e88c8956a55be7cdbc7b51fd2a07c122228db7a551b52a476d7296a1cb920d58ead8afc13113454c38ea9962596f8a0cec5b8d39e6e981ffad017e5d79083fe801ec47d1d6b50da3c274583a0dad6400fb26930860271b3592cc3128f2cf154f9618956e597783625a5113b6838423bc75912a5fd4bef3ba42f7d8ca7f932de8b5e66f45d09758a4ff2fb22a14ef14bbfaf0e2506742b85c1419f747a21fad2c3107da9fb1afa9de28bde7bd1c3e89ee4ab217da7f89de6f742f4dec7743ffa47f981aea75887a724dbc8121e505617a8948f8418c0a076f5975308b1038a1e3528420b3e2ff93b82c04a83f24fa6aaa26355368efcd621bf63f2db46be775e53b94fb52af297a0fca5a03428bf240794524df6c805a61fd425865f26c64caffa6bf54ab732a25b95f82a76a08c8a953bd7b274ad020843c7cf7334e87d1cb120b5f4aa8504041a82f4e3d3f48ae4e3db009765324ad68ee3baef74c3e8e5bb18bdfc1bd5462dfd8e986bfa8d7a102a9ca9f45d4e51de93a0485fab41ff462e7655f6e5a845d7ee73ad4a7c46795d41848a40dc216e7e2e0dc6c8450e55a3c1f82f31ca28638c31461028c61863f497a86a30ae14ae58e39517296031d670893246f985747938e60541da5104ad2526df8d57e90ba7fcc239e917523abfd0a46ab025042a9700d686851caba4394da10f26b180830551c45edc772a42b9861e04b648951face45bf7890a55fc025dcaac90d1485f6030307352fa0e7b81890e833981cd6266b0239a409b49d47069319226b1a05b16ada1726576f7f89cfcf8bfacee638c3554b9af16a1f6e5f2d03a13d46b382bb82df7d9fc7cc63d4b191e37e99ca1b3d9ccc51c4bf6a14163c486bfd7323067b3399bf346d58ab139ee5d4efadd8821e86e27ba65556e5295391ff3f81e98a021f360752c168bd55ebe02c955e8bd565beeac49e9f6d6fe876f6aff04e1e02adbd476516fc9dad2d1d272b572b8dadba78bbbd5e2f296ab7734d8396ab77ac8f1d1b5e6c8d114bbbd5b2dd917840879e9fcbb1313942b9f98a0f2c315f282f203253dc9777bb2d2d2b2663cd4fd084557c59f04a5f2947b9f6b554aeb05545d1f0fc00a287044e662b7db6d865236b98dc3c8d4f866c65994dee82d8891ae413a9aa30d3dd024800409c20654567b51b1daf0f3d26354ac23a7e108e59b04d4c681e3acd2f3ccddeb4e4428a9d2a04455002fa0b1a4464195a657d185fc4c0d9e34c834ab52517e404bbe9a1ffb35f449bef4d59cbcc96f831ec9c7d06f9de4db2fe6e49bae2e79216006943678a3556537c15a324985be4451de0bd37f073a8bbebff7f68b684253f7853e17beefdf4fafc196683618c62f3688faedbe55bd8f280cf8632014fa4b0f6542851db811fa1ec5972889fa2868fcd06320f4fb1808c55104422ffa4cfdbd3f2667cd10cd0b28e839978d705fd234d8b1065b7e4bcc643299686cfc48771a8eb9fcc48c308e7d9a6e6f5a901354effd918d9a440774561d74c3363fd0f9b347e94bd4858623d49f7bc0ac651d1855ddab3fab6059bc3729117210aa3303c1a41ab20d9d41f55fce41e94b3e34b9b4cbb2f0fbb35816a360531e0ad57079f843f901adf95163f2251f7fa0353f624a7ff235256ff235a53ff9f827fe18932ff998932ff1f7c2e44b1e86c967e3474cc9977e3d05e3e4537d36a4133f8660137b957c9465f0a308b1d7be7ec4ef04d53f3c40e537c036804bb00af0e792138f6d4a5019002b06e28b9e3f0423103f7ef75da77a8272157df8282eabe27f5a0195b56b66e98d2250802a7ab6f137996217a50bd2f3f3f70dd28700c9f3bb2079fe505685fe8d136c2bbf8badfcd51efaf4037f43f44fd32bd2b7cbe27de0cb387f2f42f5287d87ea51f2efac928f6ddce69d155ffea0cd113a1ff432f4dcc7360d32ceb373df9c94721fe3b00ddf30c736cd628f363978649cc5369bf25ff724865023dbd05909122c159be25f9495f8940a28bd9af1c4c9dda896a5794e934945e55e81292a15bdea979f424f50c0e92050fc628352862726cfe48386b1ca0fbdb9208732a84f0c6bd4b6e19e3b8b8473f2292d138a6aa565c6136b2024e69c3070829260089cf91d776c240f510879ab52bea36057209b0689b45c96cee166c771c88ee4b4143cda888e2e329b47f0a043de70bc5b0e39aa4daf463cecce911c1d38b319ce461c6779453c233a3c297878477270c86e767066de0d6723fb5015e0cac9a7a85a2d4c823373f4b856bbfb85ba0912b93a358ad1fe96fa81aefd1c6dd47ed912f878410982da2f2510bd76ff1ab35bd2ddbf5d99ad064128130d39a0e14a48d3d2d22c128e0b4c8c19b421b722467ca400adb4ba39d9158a2099555992834a1b892375b8e4f12d0836285fa6f4989e9af547a61bd01004439a1a7fc61eb9b32ca0972f8f884e703855ca77217605da6950be04cd3cb5b32c364438902a7b746e3e40b51d9ea3234551e587f2889c1a8e681cce68b62af21935c22162473c75a757a32316942fbfc7878d3680ca7d249f55915f830f6800153473d62847a7e4efa0f550f361ab72a47303d25365ad86a2994f0b192a7f231a9ca022546955b8a4f24b0dd4e69e6ea005f5937bab59d4c7f52223c3a7653c9e6cd644911a6e6d36859f1a2e1123eb53e57beceeee26017be52f4966de211fde56a8cbbed59d9959f2102768e61218507e67b9ebf2fd02a855d877c178b652eeee7ea174b9ccfc5d5cbb1edd05f3964fe5cecece0e5658bb77777bd7963958af4eeccecea327bbc05e6affe7a6065bac8ca0fb735166a7dcf48386a6ea02a8d139dde4041a9a5a856fe566f56459fc5710a15b435ebfcbcecf05dbd9bacc981f9a18e0ef1932994ca650a8bbdd05db8fc647bbbbbbbb27df6c0fdfdc5477cd4ca639eb68d07974f7f6c6f11107473cf58b3ef453f4d1f0947fe87b4ff977dfcf8d39faf930ba0ffd7aaa6d8cbe53524ab9c33bd179c7e78793a34637e8298973526a32fd833ca30e9007ea5bdb9a487fd7fec29adadf44eda6d71f8c111f40117ba9745e21d18f8eed4707068717fa3c29dbf6d9746c3f3a3622fdc3a2e8fdf2ef18eba08819c85e215531c42b345596a5a18bf4384b04d336ae8ee6a3f040bd1f3dff388bf43efd678bb8cbe929ffc93edce3a9fecef3f8c7597b22828ab8f3189b3992fc1d99ec40bb6156c57f6b4788d86eb69b73cec1dc6c446c362237db2d66fbb9f52aec211efa109db6d96a355bcd660335f5318d405dc029321a74d088458d067dae66fdcd0a3dc74967bdb4fc5ca1f73ac57b84ded51ef23ed4de871e86f721cff3be137de7496f5f3b92b4c1d30a68d730451ee008b41f8492316359e6fb5f60571e58d0bf86284423fad48834687c686868d4f0a1518386064d911a5b84c6c616a1e1e3d3e990040f537662fe7accdf17c85b60ecf2b23cad1793c9647a6917d88bcb8b0bacbf5d7878bc976787129c68b3d96c211b0db1ba8f7fe76e53dd2405547e08a771402f23fad1cb784f3a750875ea2f39cdd30c7d353f62e887be86e4bb87117a9337f96ae8877e5f3e24dfbd0cfdd0e9c5e84b1ec6e84bbe9a1f31a1277d4df79dfa472ffad1c3207de9ab097da7fe4ea0efc5e8451fe33de94d5040e553131b2a3f9ca1ef3e641f12aa6b253ca0ac2eb0adabcdff04a6f4ad7b647c9cce1c91acf2ec4484ad3a086aebf490aeb5ad6b2d6b9b732a55dbbad643bac6c5aeb5ad777c48aff8bbb629ffb95deb5a09d75e918eb198c335a609c9a121d316c522a89ce3d150670dbd877c0bb927649f7effa571d6e8fda4f687a1124aed0f0350736ab15aa36fe85ab34d54cf5915ff8e080a1ac5741f23fa913c0141630d3947a693594f8144df0c4f71557e29f0c1f1635a8d99c63187db1a8d8534e8342ed63c76a4358b5946635aaf8008990d01e20364377e4c8b813ac4c4a92e2d8814dd8d1bb87a0d396801ead2788e509b6dc081967d3d55c38d4a29db69ce30b0179a6486c1b08bc3c4f8f4b8bbbbb36034dad2624b9f968b0bb602a39452988b5d2e306f17ac65013ad09056531025ea7e396ab8b3a8c388279034319d2069e247d0fa81081d422411c40f52e038ae9b5684175020842042f4048104422841841140685c7fd692339abedbf4b329fcdf1c2185eeee96b31f44756941d082b3bbbb33373337eb08d90891820e777bb77bbbbb77777785a0b9a0d5faa1882882e082266e20057fb0bd511a8cdf52ada87ca5d551d5f22f05a657fc31d8fd552a55123ea8a40e1e1dac9c7cbf2a7a7bfb8845af9c749f3cf32cf13f7327d0847023052472b013eb55820722ddcedcfbb55cddea4d71b598f7a3b75cdcaadcc2ccdd6af104a1455237884e13356cfd70abeeeedc7152f5cbda9714c91df2bb3fc9eff462f4dd57d38dbe93ac19bdf779bf2f7f1a343333481e0d9a991923148a8c76ef3dcb422c5b16d1fbb30fcb72c94a3fb32afe1e8a63a18f715ccea2c08d09d5c3bddd6891071777cc70ce39e7bcbd8706fd7907d75cbc36c3b7ee26461300803e19484f325a77932fa133944c9f0ca86df0e433416d83255f0050eb43bfd6f444f30b7f7b22003ab444175bb865556aa8614b334bcfd5356234ee7f59a7f925bfafd3fc4e2f48bef430e8977c35254fbff4d5d49454cbb295e34a95633962c195a0685a96854403c507ca95e4c404ed1ab6d4d824184f45ce7b128aa2485071f4a9568537dc2bd4580aad80224a3925b74c10a8063337ca1941dcce28e3d3e855ac7103e351761d6a41c74372afe86d1fe162f2a7c120e87c297fe4112ed6abf8827bc9174ba186a1464dd1c845d77ea9036551d7d9f48abf3003b2a7f2a3e48fa75cbe767403e334c8bff5847f9ef8f32815e87c297d4202901ff7464ee48ffcf1b813e99dc8b0cb413b1d61974347f5ef72fc38cbf3e4cfcf0b86b8a9a1d7f108e5e852525264cccc2877e3e68cb3e6e7f294ff9c9e02e32cd1fbda5c292929393af50175693d72c414ae614a4aaf28b00af0af61aa15581567c908f7c68d5a906afc66ba177d4de8e7d7742f7a29faee6be687be46f4ddcb17f3430f43d4f17c18a19f9f8d1f31f3450fa37bd1fc4c9ef2ef219e108357878279c910eae682b970f97accffd6dd73c1606c333aa0dc4d25839b99714b99e19a3123e3362363c6cc0c77ce91c1393332e072d6cc4d0855b6d7c3a22c890e0557f653b5548bd2f26da9561a6cd54a6b57d5da1a4a8c4c0cd5eeae6aa685ea5f485542c4aa730c9d1e253067fd9c347f1a53eaad8a77f7b2845810589ab79e07b32ca0ca3caa87ace3257d1249a8f4277fe3e5df6a9d4adf6902257ff231262fc3975e86cfc68fd21753f2279f8d9247f46081d95f858fb8d3f965ce8d73e7c690e39c5b7f62094b80c10da0312114052d488b58571881f6efeff3f42008ffe8ecbf82896e71b97477b75a72880d31a04d114488219c0ec02477f765462fc23c1004412fce18a717bd18bd49631231b6125fd0820d39463e3f9630041138b1d88a1e4ab117d47cc115554bc5324a299da5bb3b0341f973fca0e64ff8200733234fe0cc15466294eeae069bf3158e7294a31ce5382eb6cb05165db0789b7116a514891800b1439c02072b92d048ec90851fa2c5e5e2ad96d4814e1226f8cfa13b53392723b3777b777b93c0bdba2b8e70840f32c7bad8da5e9a0df6e0be87fc960699bfe52cee9b9de297dff69c3d9598824cc28de77edc8d2bbe40bd6166f4e28b078220e8c519e3f4a21713e3f4e83ee8ac18410985b8e38821ac2c41fabe226d77c9e8f2f66e978b373b3b3b278393931545281898883cd8590c34ca96f21b2699d991a04be341edaf3fba6005102c8a52b9ae680245a9fefbbfab5d30be7b7b7ba3fcaf1137d58310410d3f881e31c6821ef0ca4aab65a585b6b2b2049e952b4361552d2d57cb39c535e79cddea96b1dbdb536a7fcbd662734def6eef6e1a10d55b5330dbb0039dedc0ae524d5513343e3333333333d3b450bd85f883e00b09896389442231fb832a6701e01d87ee6bccfa120121b1e6e467f81a19def4a697e16b66f893af31bd0c2f4f7e868f91e14d273fc3c338f9190230c3034086377da7f8fb02c00c9fc90b3b702304abc99b7cc7b5a4d4a4a4c4c444e4795f52a2a865e1e15083569ef466bafd4d01abe21f512aab007f0fa542a5ac8abf0ca813948b50e091104c016fb7db8c0a142244c8cced769b959a0485cec77dbf1510743f3ed713ff8dca1f2a2e8b951be2b7cd0b4f58c1ce11729c607bf5cb38cb460c083728f464e1043a2c14559801e147144d38e10baf0310a1044cfc20d18348175efd3cea01fa9aae9002dd6fe96ad92b3098abbbc505737971cd66feed2c64832e4a998cbfcaa1b521dcc845376a21bba1a672a8294341c83c1cf75cbd61a9108be1a080f8354c957fb02ad1b98f7d5830fefce6deb90f87f93566651f5625be73737e2c3b414056ee656519ebd41b3c18212748167258810940dcb81162930228ec00082e94e0e5322346e8600b498ce106af48811ccca004b49b4c0a9c570c55ee452c3b1121fad0cb88bef54f8686a7e2b38e37e964198d31d2e9cde9d149673de2c57884a7c6e723bde2c9f29b1debbac0370901ee438f001cb26bab57cb32bf189f55a0c829ae3927bb38e98a1edd5d2ed13dba3ba703f7a568848d486ea765ad23931cc7011e031b5916ee8965b50f46506c4446431555eea7a96d306779274e7eacfedd87be43c996cd68b21da6394bf4dcd732d1271275229148f4d588befba8f75d37db71236ca4e2c051d658bbed5d8ea4b0a6caae339fd691edc88cecb876643a3299ce8e6c877380f42a74f7ef1e5ad6b296b5ac65251f507b4ef0edb8a5bb68214b70c3c9691e4105b11aee1154507b686863da4a66318f754fdfbac8caef9c65e9387b9822e7711cc86311e4b5ac45a1d08b3eec5bdfda6f7c87e7901e8dbb8b5ab605ba9e8279ca1f45167d34e81e731cd7e1b11fa8cc53fedfed06f2d8b2748ec7fa4336259ceaa1eb60e1ce9138a788e3f098db78ec6693939393e3361e731c1ef358afb8e831b7e969d0df63319bdb380e9bdfd83c16cbc9f1588ec73c36a35168204080d86a436ab521dd92810001c238a827bda2cb22ab7f8d994d35a7f99c9486be292b8f4c76a0dbe08a2a9d71a41c81986ab55a2d728c9102a9ce3f2cc5890a29a460297ac55ea3b150103a9ceaf2ff1fe51fa64e4f52fd632c0b57ff191901d0a1a28e6b44916a8c3146067de7916ef52571088002da35fc9f2316a467d4c6186344ad93808652472879a851e2ac4afcf842bee8cbd10bf922798aeae9550cbd27039a39c59fa7f8c9c4007df731bc4f865ddd6f078a31039299911112e374c136d8806270323336d0cc8c4c0c9b4c8c1999199b4c8c1919cccc32369b8de2d01e243e0820c18e5c7415fdac4b81931a326d131609bbc4748246517d8aea23166984daef0b67b8c8a81ab2762fbb6f8a6ce081b6b4386e398e736f71de52a95c2e31c618497ca6cefb542fa9cbe21d4e79a5e108a9faf36c59222f517d91507d9b50dd3b76733af8f4b8692e7a8c31c69728528d28ae3c63204c00f1e79d15ccc75dc5e77eae37472cb85768fa741c8a6b8fe2fb88050e1df7a7aee39d66710e35e7ea4bcb81109ef5a821f354f76838f8410db986031dfedc533d6423d53b11c71cc7712199180dfebe6c402537838134e891771af4998cd90e90086416b91d9e6540f28e7c199daba8b46d1815b5546a46000000400043150000280c08064302b17044a06b6a520f14800e7c9c40664a99caa3419643398e72c61863080000000000c0080c0dc0021c90f1e8fee07974591ee883225ee799f6579c7b8f4cdd3b26b935214ff30cebdbd31096a56a1aa7349eac75beaee90146392ff22aebaa3fb1d195164bf88860526aa4538d73c3e63873c6d43e7f12288a3237a1deb9106b0751a21bcbd23d8d87a81b3f2094232001ebc36d346e4a4e9c77334c3748a862a4e81d71c3e7981acfe211d620acf10ea9a9eccb93009a9e9b8b494500a128c366fac18cf497e64e1c983eae22553197621edcb45437d14af7c09b8ea869c0f63a0c0fb35f98b9f5d4f994fbd7f1cf54abd8b108e02f6da714b7be8fb7a74c298c3089c295ad24516212ae91811311d2962245d3803855d56de92ca55a9045ca0990953229b98c0b90823959e4e8512709eb0d762edea7fccb36870d4bb8f8bb82227a8900eb859ab02fbac8c39ac52cea57a805e2c1d6f85ac1d579705649a229141d600b8714e056114968937e1b5335855f43373d883e01390c0cad7b67cf49b9eee7e6cf43017253fce404b22fcc4e4714139424a29097d6db32bcd6739b05a14592b58cc53f56f4e8e259c3a8218b6984b39e813e441972c5b2403ba12c58c7001c9d78b55a9f4090bfcfed6fbc11e023b839fd9622fc8b5985ad396b846e71890acff747859f71ebf20f10592bcf81863c04322f76add098960a5d987e4a165afa31727cd0d23ba617f55699cf01af4bd8f72e15de2aed42b8bb3a464295a5ab0a9659e184f2ba07c8a8820093b0e64a55c25da4d59c84b02a6feaf245c5a67c812735ff179ea41c31a1bc8b3dd3f5d2fdff9a8f9c9239b37f3c0bb32401f04071baf142a03cabf31c97c625d79734c0f682a6294bf45c18b2d40dc478b876d452f55b8e1197929dda8323e66c6f6ecd2181a9adb09b5fb4999a7664c4a1be44300ba51d39a12bc0f862bc7e9288edf3f4cf39f5faa56ef6bd1b47de47e707ea0d3a04aad543444862c18beea801fd19befeb571e64ae0a3695e0ebb8f33f5975493fa35e49ed5bb1726f5890c96e5a25b4aee7115d10a832a36a331e1f961a10bfd7260986cf2d65fa96d21478bbb8c20c74979e300950c3d880c4afb9b214b9e1994bbd09934d01ffcb6c86adc53637058d346bfb1322528647d91ebc32088bbc57e53d28a650af6403b19f5cbd8dc93b637da5317dbecbf3b6d0e657f4063f794726826185a13050c95ed3945be82303b39a304380aef8176751172b05197b633ecf06e49490e82185a2e2101e4a3a97911185366c67ea1388147afbe82db0792a7a9d59416f772532a4dff91ee3715001f3343aba8ea618fda22024fd81002941c5f2fcfd350a64e3a703c8ebe5d435414b8ec405826a13baff13b27e630ee1cca1ec243e59a7f0e617370851348b46f88e4c85e0c82812091443a61727794ec719b1dd01485dbcc39a6d63bc33b17af7a3482bd745bcfa890e4328d6140d01d49398c5cbe41e74ec261789f7a913cd1a0f539e0f2668971006e8d06f8a63a132c965e1e12cf5d0b287faec8ff7a018ee6a2f8185cc6c653a19bc4454bd09ecce347c722aaf54b44feb4afabb8eba769d2fb2bcdff49e65d5400929a7b5b9ca2216edb7c04fd1b6218a948378bd47dcbf8ac447a986720a7916bf120438a57a360db1978318b75eb71dbd94439c8246dad54ad19be49e84bacc038617a21a175a86392e42332e1bd98f7da43ce607ac58801e29fcbddefa926041179abb5343271f5dd9bb590db070e870aef63832b971ddcbef8b82ede2dc74c1afc502e78cb043848560d70abd35af4669e00a4d207c0d69555a714be21c0416e63d2e00876c760611846b0b067085da947e7bf4b9cb3e700134611a8c7f95d5cfe8c019ce36f265a23fa4b18162b9ba37c33ecf9215b91432334c1c5879446144a7b6a6860d2738784423e7eec5b340ba7802ef7d52b57f73f6951a3015dc442dee060770840244805a2764bceafd0c3bb8b78a95882d8287b90fcba423192af9612f52b8731e9ebb2653e7829a067bc0bfa6235194936f36c85d565f81a6a4d15889af37e70c1995b74372c57d881ec7188283068f763cebfbb7744cb5eb87c8c22bc6056e310d4d4b39f5f368a42a0dfb4ff983a793cd6b56147c9dada78a235f7e0e773611ae56ed3dda247a8f1c3932e9497fd3cb4b68e41e1a3b070025a214479da89da37e2f9f762762cbcd8904d6a4dc6c994e7d2a362b1bb2270a1d29f5190d9ab67b06d51f45962bb2da5f1e411b70caa7cc727cbd1c74ff7dc079987d20e07552c75c0878d63a0c32336c313df77f70a48c4b7ad30920a196d4731d368ac6732121be1d58860b650ca905a886245f905e71fbe03e58312f31cb48b235be8fa570b4ef1863e094738419b10e660ec7c0ac6dd508f5a6317a475a5a7a082ede93938377b4f6a4f21e559b01c074243dd802ce9eac4c514438d627b78836068f2c7c61f4bfd82e6c89e19636ba7653463ce79e6f9c645947a71ccde1424666a314ef1fd28157fe9a437c58399e514e7643cf5b2cd8b0647d6e5fdb241756d3c75c2de27eef9300d8385eac217b8e0f1a10b76847dc0560af83f53381962a3fa4996a3294c30d43ddb887da330137b940dcb14bcb1d2145e73e771f101620b9d1eaf2982a918727c1444c555bc7c850e0118bcd0496d1d011df771c2bc65592b5277abaef71cb768d1aee8486a538bcc7146e8c1cce9364d13d58c860514eb7e041e9dd1496b3929daedefea8bb950231387d5eda9cf8d38c916751d7d2ff7d608051728ffc0df8b8801ed507edb02304d5b746d032f69fbfb2cf73b18ea8c6f8b21aecd7a341b76c423d88ab25b596d2a47d4749f155b834d07b7533c039608314c79b9e2edabf1f21432945190c1e0d381123485baf7614a5e97363b9da925a408f0109591c7ece4e721c3331b08891c03caa6bfe5aac7b88b684ce7dc010ba56f647a19f6f3acf8ffbc164b9208a0f0550371ad286a08bc5e93c4ce3fc910927a6820851a09993e480596297132493058c56ebd8f0066298e2d545a5cbe9bdd86371ec1f08337f79047f8c46010acc50769268a7c93d2ce158360465a1c026115aed6a939b0caee1c6f33d6cecfbd0d545a1aa23ba10d2329a4f8d7eb32875f2f19458af25eadc548b3cd170d62035ee17ee30bec2b31dec48a8604de49cccd56fc29cd99e20dcc6620361fc08008c957aaeb27bf9a7f957ca8557bf936329dbae16c52b661c0f1321cdb2b3bc4c4d553d26b7e1390908a9be35e7d248de215eb44ff1a1993c1f7af1b638ff320d4877895e8419bd0e516f383297c4a17147d3a641ce89798738c7b1a75ce5f819cb73ae4ce87022a58d2a6e845843c03e4b49d1512cd5faf8db14ea7137c1521989694fee10e76f070fa9a55186093226045e70ec84064e4eaabc1785272c2a220b34bff4d4babef354b4bf23f8ce4ff87f55d9f53e14621f1d5319309a460257d89d680a5625fa9d4de003b74d6353b05b5d3dd869a8a9dce1f129831c98275d32f170a89d7e43d5fb815b492b0984fd92877b231c5d342ecb37a3df31714d63f187e2ba7f0519729c038ede486528e08c4876d0928cc09e9e60a0b08ae23e3a316575aa56e35f6b2e0ba0e242305f222a834416a8bae459f3cb30607cd6da56d3b8d86a4455f14454d7a5306380892756d142feb31bd934ce097a39485bfc1d6ff64d6c9951d9b16e7b9ce38ded2b9c94de697e69c119940410256b00d1caebaab90eb47fa979035e3c151e15f4b00c91e91eb979f8c06563e1ffcd6a5f4b84af9105f092648ffc6fd0e5acba03408826af7ae784659e1b7c288fac7f2fcdeb809882c5b57e9e58a58792bb421d9db27e95d35631a9f0df826922489f27060df65f74ac80dd62f78dd0f7def8943c12a526af1d23e09e6d44745ae618b4467c749c6673c85dd04ce543455e0c193462248350fa9b669ae16314a3b4f21e0988beb86dc787340d9e4fd0c51dc2c0c5522562e735fbd033d5d917f7bfd371804425a8cf789dea45002fd2c21bb6160a4d0cca9f36d5780dbf29b97555f398c6c730a59de9e0aae89c7e805fd939d0a58ce3935c7dc9c9ed763d570d3dfe42fb679c603011be00c5795343e350b554b061a2034c86cb86edf7ba76d400e460037f2f1653325efb4b2d01b8212dade81b1a2acd3241455efd6691375a91f2efafc527ffe7eab659d861e22f3e614bee6f4338550552fadbfd2939f9610c4430667f721bdfb3a91074b13d1bcbde9a53172eb8e24cf155e643ba3dc04491e42cbca31ddaee51e2454f7313e965b3b60d9e40c574651989765f2e480240ccf9d18e28975a75a0b456e54c13ab16d78f67ae97e519551c5d30d23cb13e92031e37a5530289b610ec811ae9748dea94581cf50022d38d501388915bed35a588dad6e424c4346e19c15d655ccc0e5104d9424815aa0191d75ac1c42c3ab415e884991fa750d61fe836f94dd92d4f83294f41e5874faae3a46fa4df4be90930cf9d10c1685bb3a20cefaf575b18a15e20fa73388d1c22317a99fe3db20f7e508160b369fa0f1f70581823ef13a5f84f15991279d6a591033bb586fa06e8365b94ab9d08942d6e454cefe5d2470d3a07a6f2d19a0aa8e495a8d29ebb4d20b0728af596721011c7cb2d94697bd8e2f09de010ab6021b5802a182a7e8b647e7615c0664f5795ada322b56bac7af01717a47a74b62acf5a0dfb1945e3d68a08445fd04b8c0caac26fc32e518d93d65a6a18315120bccc62b965931ab11cdbeca02135a329c08425e4027411ae65960cee98554a53fe5c1541e8dccd47eeab5f902d54960313bf0c99140e76a0ee668616a1534ff9df555246c10762ec1ccf828dc202ddbae41b248e97a028718bd4ed0e72b3cf9356bb4f7899d0916e3470affd5e924d6b346e4fe88fb512631f4545654263d91cce8677d26b2f54f923a5db8f2093a521da1a108fa569f79e173601128c2646576d835395cee8620cda02a4e2019d38f202e7da348350e5481fd3c3ea3d72bfa18fd37851e07d72980e64de8678a715b38ebe9b747bd236e1019ce3e860b3a2a18375137ff17f921067c4b45225606261ba0e6ce37c6f144e3b306886ce5506f0d2074b029aa1601d08e3f66efb240a56e02ac8484f3d7763ee9047a749ab3ceb6c9033226e392bd01574a0c51cb92cfdedb0f205b46df13f5086c29d8eb623482373f497408f9f35522dd72997e2ecf930cbfab184d49adf211fe5c6496e23a8b0bf12974d231e2015a52d9bf038878a8c22bdac75e71d2c302de5f04e141a6b095dc16264261145ea27a07f6975dc197d17e48d2a6386867679600257a83ce1e50c63d572cb8ef8295e21a0046c45991c9ec13e1bde69a89ad0e584778d7c9825fcf25f1f7bf0d1425607903ab9585bb806bec74e41b790057579ef6067177ce910532364978884f9aecd5aba3035fad31ddc6de8a0304c2f814428128a880a4cf8362a3351b4c48935df994f99cdfc0b476203398c09b7e6c765c3b5852b6bd4660f3ae7f460049be6c8835b962d09972813efdef2c9df450851f57889b5f94d1380dab47a2092d7b3609c386451900f28a376fea555e622292d17d1e4f7ee6c909a7a8c5b2452b165fb634602d0d26fea17516b2c19868d3e12f6f6a98e980e49147d67912bc749858d5745440b899794d178103052c92715f65c3e70459523d118df43f1d3560f511f81e25747bbc5ebca841a479f9826de86285ddf1707e058c8ecc63bed6ba30bf9182f9998399abb5c4ea45b3d2ab3417092df78dc93ff9a574a62fc59056cda0164616870ed6afd2bf2b384e390a7e0f222bef784fa2082e1b4751ac9ba5fb1291db08f2c4052b029ee4fe77d300817571cd067e968c81621f8dbabf4c2a0c7a6a99a71cc74ae64673041891b7ca384cb0aed28c4bb34e69e0c109fb34f2509b371569282b1c1a3812e009c2f33ae5c7aabce350381f15adb4e91e18eb786d1f7fe86f2c5bf059c1fc96930f99b8822fd493c37dfff636474f6ee04e1f63c858614a4332dbfb8522761d0106799ba457570983611bb213cfe71f520428f443cbc750838ae8c5af6ccd41f15ef07fda4591feb7a2bb772a335b627fc5ea94cd674cae8afc06d2c420fefaf9ea5b5dc8902f9370c4f62d90442413473e07e792a0ff6639bb292092a5db3dfb4de2f1050bab78865c9899b3ebc38b8f526aa7460d55765287b72cc8139b3c67ee595a004c769f073575c52eb61236b6c9a3df5149348ca97425011c2db014c7fa91be3e588f801a8900edd4c9f1f8b0c903774f86ff6d29c42d7d37c2edad7bf8ce0827b4fc9c154ce43439ddf95f235b220ef500f345a234c158602732aabc611d396b4dce134b731ec90bdb33bbd17de45724998ae91872ca7311be87b9f33839639ca73626f44c86e4c5bd048b03935ea58a6d6d78a83bf5195d888d77e79e1ef9dbf2ccf89d650135defc71799c324aaa9d84d34c87811478ff157ec001e5070c174ca1aeb58b526bc116df0a27772d810348e8f18f080adce23e6c5c624ad4c37a3b8259f112481ae8bdb92a12c344753ff06cc7087d0e859488b19f060df93260e96ef0103ab392510171e77187d1ab450064e262d9482d5619fd003006a5d874545425c2720206a970b92715fc33a13ad33257e5303eb85a89c62adb16da62ce15ef5a7bbbf122eb76be6a81e0c568df064062310a14db2d2872ccf8380d53fa32d3ca11baf15678d9aa2c4d30717a12dfe811437e315d6490b58219a2dd1e9e07367b46757d9992d7d3ae8c00586a8a188e98a366c242bd3673e2fdb75bd7b636622b8e608b77d09f1407782446696b1529a8b5966adee225d26611ce5fd4ee4527adbcc58f79930ce17ac5f68bf5e6d229f8594177f85954eb520dc9a1c2ab23e1eac89af85a1bdd836f1367e78ea065d22d2c246f5b2abc90f00f326c38a642048928840e6651e1ac2d7cfd3bf1a12a616de8ccd24ab632878df21811454f964c0abb3b321b37326c32f3378ee05ce23af6a19a4ef76324c4b26d6c8c59e9e63e6886896a45dbb8346094fb19a21012e7ec7f115ce8f522b32529cc52517e0ef5f1eda8a9f0f8b83aaed64d4c100484756e0a9785ee5cba47d23574ce6dbcfff9f4e78a7b0d8a4cf45222a3c9b4236a057db11930650634f3f7516a2a1b7f7c81985f6c7357032a38dbc19e3778d1c0e42a84831e48e763e7146e1ef7d188fd29fa01043d52003fb14d5e0acee4c1881cc495c5dfdd85bda79d4f993c4e5a662cb352990adb151761c26e76ed1c7117260b4d77dd607d95ad1f0112d6688d07f2417f015afafd6666e3382b4524c464f0dcc3b35d368d0b86f1027b139b7ae6e2182d84d80d15d7e12cec3bbd8ff3569791efb1ee31c366e5886232ae3e3b907e131cfb60d0b6e23470f67140ca406431194c8526cbcf3ca1b8c14d790f26636bc8c16117fa40b17d732c1d0ccc70e5c29214ede0995e43e61eb9579ab034f135c09a62c3219b6d8db0b1893cb7c8428a117e51f839c6f3a1e3b02de240ca387a556754023c6fad64e920acc285989ff92caa73592fce5ff296d9664a29743680de770d46c9d0d6237b7549d329a938986c9ed5c71d1f9126cea5a3908802c69b676863b9fcc64a72f30882adaf35001e7e379b5d3d7293a0df64529eb16a4ec1fdfbb9d5cf07ff0dfb1943903001d4b4232f623d500f7a9bb7e4a4b73d856c3ceb9a17a2acdf78b564062d6b5b8d9531d1bc68c220f3e56c46a2168fb70be437daebaca75109f277f1de69e39fc3ba0bcbe2d3bc9cbeafa88003db8d870144e049ec05b40679382a1fc206d6d6686806464ccb917d219f131bf63008237ba481692c90129a055e925c62bb932e9cb60b7c5a6542e1e62de9d2c4190e9da70bb112edbb737d6a644be00f1ec90476c2b2a239d0dd66dac72dd29fd607154b06039b59f5598cc4b9f7f175d0f34d6af9a58a0dc00e542aece3870c0b72c05e7e144df84839e7f0077a566f6d05b48f39eb63615ff245114d3f980a2590f3dc0810754a92412dfc8d99a2ef59eadc85c6e59d8ad3b3a498dc2c974392f072a4489d5a03c13f4e1f03f17887aec9200974cafe05d91a1cb3f2aa4cc8af4e22b13f9b233eafdb82c31c33fa34971e8ec0b94355197db40ed217bd1c77419c1bdb772e5a104764f4f63ef011c484ac0792f0fb9399dc48efc9f84ec242c290b8a188bbd66aa0c9407967bdf0660e360dcae56fc88a4d835dc21b5f8c548c80a222b66d518a10e9694368e01f8ae65b7d611afb2d4dd0c1b1af0cb9624031146b7d4694564ccee23104aea52c03727a2821ef78ac153e9914330aaa49887b11be2b74c3c80525dfb3292ba8152ca77e933971698b0ab42f118500eb5c9484cd45722c4cb52d32839fab815a9e4c2465b002c8ee76faaa221a838f5e07c88768f80bfa4f00bae766053c43480682ee1835414721ab6c7bb113e3f58f3d7d779ffceac9c52860f0399bee76aa5f373b52487c97caa98153418fdbdfbf29d80db47789c5caf85a1404d91e8b17ac6fdfa754b3594ab693a9d9ffdb735d59aa2a7907cf2c4eced31cc7d35ba27627e58d4a9e69a01dd5c8ad292dd4d6f84aef7922aad97b4d1771d80fe710b806fb2f957fb2b33f7cf02f109550e6729d5048f318991cae3aa1c5e045fd48a1197b780c87d5a0d94e1fcb15604a74fc31011e1c643da09ed356708f44fbbe4d138c31e03e0796c3b13c77e7b3cbb9aac86eff3eab58b2f203ad6ebb405432abe84a6c075a36018ba0b75d58a3ceb41ffbcc99c191dd575525f2195a6f38c95224560898101d7fbea8cd0ebf844d03d19c49139893c6df14419c3c10a4983511b5c12dee3f5abd0e9527fc8d4f45bb526016624c160ac63861b7123b5965d08b2c4143634307d639eb0d23b093875f1284e0f51e8c8636681492d3e11b6598038cfc2da167e4e8afd61b379127772b71b7714b97a78dcd34fe7d6a107ec05efd3f2d8ee531354780ee2a72afbcf1cb0c93872ccc6b160751e43c2ed4c0e110dd2059352b3ee04b7a57f16a4b7ea86676f5211aeddbb387b018d80c60a17d26d9ed067efe108033e7d0fbc3e0a13ee3deaed2fa9be486043a37431d7e2073e2d8e256ee5ea9bcbcf495a5aecb371faa94f40b96beb7f648fc9245fa7dc3aa7d4100960a25b9b040e2c4224c89e08f5883c41130f3a8de52447e1846470db03b1508bb43ce1862e4ef835f17e3aa87aad222aa01a624cc271af1f8e1171d7414ced8afe5be04a40967b6539ebcc2bd9c10b37fd109a57cc44823dd99529a4affdb545e73c6d2f3f423f123e8533d894e52c27c4738f6c0c845cf4c19ecc15b6f9fabb851e7ed5b83f5ee54b06406d926557c721970dfb0146768df6a083fd7f57e152f887eb3941ec873c14cd6536c09209de6a1241d3783c7af9215f05e811f751c50651b7baef491cf6a73d6a5cd870778f945288d467ff8fd2af42ee0da397fcab7a9ae01909e846cb9545b7a89386b90063878a66ad786a5a9838903e03c359fd7139b4fde5393935a11193a379fa08cbd4b06d44aa3348e769e3456758df8ff24a6f07914a734787f3ab8c7abdc4bdf24dddc58925ed72a322573cac38468718faf90e435ef1107b2eb44355dc31bbbb67a75439ba963202e31c88b76a95d47714210b1e0c9281c9a4afb104e584cae58fa9a5417c83fa23ce084311ff2a540938a10d31711e1289182c20e58448dc97f87499c4184b8fd72e16cf95628bab0998cb938c234f1e55c506cb5e966ee897302dc7b7229629a3ead39c540f4fc103d7b45a2b3f5d4634ddc730277ca6404eeb5da7925769d6e3d36c2e8b972257ae5a48d5b32ad027ee7656f11e8632b9d1d1f378faf5d3aa5e236bcb96c25b0ea400f9d12046a95b67b50a5e0e63dc85d2c234e6fdb147a1e3eaf8bfa5427fdcbfdad59303e4b3560768a3639d91a7f7df901ab13a2c9dfeacfbb34ad953bd144a851a9b45b38e54d1c308ca75bc5afd3a31579c4d945598b8635725397d7d92f2f208a566f1d4ba092aa5eff9635041a31184f1084c010498126fa6a66943ce64f24e603e95663684e3b4df87d0772793a6300d10f7672a0d1f0c386243bc495722d9005401c89fda6711f824437c786b345d8149818ee3fe63df89f50dcd943cb750058dd8ac75378f49b6ef76f6f9acfa36263a0bb529f1f2b76d029216e219b0d8328b14acaad2da8daf8664a8eb63796d6191173fb5f06f51670c6a4614b91aca0cc0fce69078cea471da2c4cb0f04140888426834202d56c4c51e57d94170408629e6db1876027804c2f9de2b6114b1970fe84a1a7459624230b077ccc063f188f6d798d7afb9b9f5ca0e37ba54b8d9bdca9e5ca93d21493301daccdde07d1327073f6acab331593dd29353d8301a076a7a7f6515044590455a50686ac28a9b916faa266dffb2f7d326a0c09621cb22cefa13f9b91e051167b847b1d07d6e7753537a02814b995f3dc69c88b3fb1bb0395d7a6930cebdce54af6f310cbe3b4933579354ff0883c32dbcf9e9c174ec9aa907214e8ff7a61f8549886f32f2edc1546ade10c0317a5019e34d98e3ff247c917f67c1d148ccdfb6246370fab64dc677581485a2f9d2bbc53b73b484e865a1c8914eba1a5ae58a0167cf840e809d12bddc610685b453edd83236b4fab33ebc046ae8ca9475b2162a393ab2b15fa271462f2151cd1a65d8c462ed5114832cd10499301b86e138f7e6ff59f7d786224de16537b3ea87c50cbd6a0f74c1890a503bf82fae9d28d905e8a3580070ddc548e973baee6e244b433e40616b38ed93cb2bfefe65e2e354346c502b47640769022633d38ac59e49b7088df7d62d715ad538c6f6ebd0a32cf2903d04a3ca01fca37d77c9325136f0aca385df6e4f043a3ce0b9c5f1158b38b95ba9556e2482f28d76d3b20e908f948eb915b605eb57ccb6a65f311b5144ff400c767c477c761ca876c6398ac51489b177f0e5f5140f732607e55bf832e93dc7474867964dc788d85d3506342ea9a9cc0abf8476042e17754450ed80af37969a7c390b4bc5cb84a629eba4ce661f7d3b07590f34a85d146d363e717e80cf3740bbbf88483eea031a81da28d2384b152a55b3230b8b44b60bb90cf392157cb3552a999fd1c3ce04252639e831ce98a64cece0233f75c7e80e8f5b09f786c2219c3d997cf34713223f808ba1b84fce73f2b37eb396497872bce81c7ce47dc353700cb4f0b8babc3d758485b9bb96aeb0f094c262392550e52d269c18a9c54355864a9c7f39275f9cd37bbe04f3f7c511ac7b08e81b24ac236404468888e799e3d3efaa301798380a21e60a7eb1822082ba0a3d522781cdc39fb6ab0f3c8167b48a4f146bd187d5cf79bc025d09cab4f5732eafbb9bc235664829b6aed467a7608b1345bd600b9553cc2bfc5f6dc057a56fb0bf60540f3f4e5157fc5b269863399de0ab0073c914d24acbdec43e49bbcf829933593c07e7c475d486965defb71198973a46875a414e643de4b47d76d0922748c5c66d71e7a5c390205aef2a9346e5cf3a32db01a3816a462fe35896cc86ba92869a3a4529461410dc0efa8306e9c421029d63d703a565f1fd42a02dc26959961715d2adac1bad478a10445639d92e8e67e778868ea9b931076827bb3f6f984926b439ba695b6180a59d6584d45dc025692f24c0915af498ef213e6295bad86095a72249c2ef3ac8afa8a1c5b4da62f8f3abc1013da360b06e9085578d758251a4032d461ea717b8b27fadf3410fbf5a8b7834c656805cd3d1cab0b0f72fb37176381927cbfb006571323b5afff363437d62fb8f56477ab7942fe5b4284a048c7d8b42faed9f834c20cbc2dfc794dc10026f7e6b5a551578a5ba310eadfc8dce52eca544e7e76c4b2a4f00d21e42ef516efb0d14a3c6ace7ecc52257444390550daeff823058291a9116b3494c2a03065fb32cac431946e8d1e2ff86258c44a5dae9354eb3503ab8b1882d19c50432b6c7faf466850bc23daef631d9e249afec64767a67c556a6918f17271fe01432444d560a65b07446c1af7cae3c4ee23707ec07fa238bb8e4ec46b69c2e8eb1b205077b2c449e4bd5a340ae6a2ba8ba9e44e72f1c64d38b846ef074cea723326b8ed75ff0a09c9882b725cd3e6e0a8ee265e2fe77de86f9ce8e3268869a00b50e021d2701639a24d64d55bbf45d40088e1a5a8138264a4b7cd0abb773c75cf09e26ccd79682535edcb345669391c58a8ccf34bc37054cfd6a27ca15725023efb3c369bd93262dff7e3438b7158a365c68da10f45bde9c929ae4a60a8c25abc4231f5820858406eaa3f75da66fc58bd2802062bc828ac2b6d8e49cc02c65012c7c449e3d505b14136f624bc83e761f0637b7f429dc97622a48cb91b6ae91b6a485179b9633333ed505e4709ef13f9978991cc6b11318eca9813b750a9c2eade76fdb3d9bacca1b0bbf38ce40ed9ed6a32026271d36afbae4d31fd42856e2437d848ffb85e2f2958b311d6f08cfa56c368cd0d37317cadc65a4601053468f80f00c5e574f66394770cc542c6c38ba53e9945ac4f7ff47f0be05dbf2bdfe1e3ba91ed002b2aa6cdeb86d7eab910fd32d891cb3389d2b4ef7a30ba956ab3fc6fc9bf874a1a916d68987c206a31ee626487c8363be5e08f7b53654eae4421a0695dbd8a5740bb028952f6bc37aef7212154f52ef866e2f13a6057a8f8870c3609a00a4c1fe261be988d6e3d3dc8e1d14051c111af9c1f8c4783e87c85d0f45e146a3a81a0d50145ea87cd0be49748b82c5731097ef17eeddd0e900572cee64a2b1e5976583a2ead3814336326052c460f5f1e617e5e3926cded1548b6d76376f226102e4f1befcf860269d3e3217cb7a9cd5d2176bd84b98e0deadefdcab62c58448ae183784b703bb67012691e526cd1f28d2e8b7ac2eec8816872185a735031b5433fe7d93bae4a00132c561f687c60e311bbfac831e9157281b411bb567e78a38db08294b2bcd6b9645a779e06db5fd361d06978f0c8623e56c5de3a9ffab652774134c0ba6e0675478fbf78e482efddee7c9dc5ba02ac4efb0c49735cc0781af6b9343173cf07745dc591a213fd10b3eaf179be30d023b89c1638b5880064b510922e7300dbb947fd6e90802dfd65194dcbef30bd62a90a9e3c95f86ba13509d5858f8fa12145cca8c6c8429c20b502a29690936c34b1b522071a1bde25c6ce7f563799efeb0623705676d31e54989e6396c0f63984f04b548ddbdb6e62c7df17b8c01fab4b51fc330b756bd8bf9e0e2780090df621f0034a5986ba8ae48ff53069c766febc5a2d80c04567e42b2a37f98439286b02e43e4c43b6823d0997fb0f941376af0157e3e659c1bc364bdaa26f38af055cfde83d20aa3653963fe116108e028f983217198f670f832111196c25884cc5cb153de0d4307e354a4aa0c5cd5460e7075e1971193a63e03e92f8e718905fd93a2c557ba7506eaa91b0d50cb0379708c85a944dc910ef3099a600c08f5ec04a3804bf3092cc0a6176a96612d83de621fbf06b8175861fe81121e41b8bd11c81312f3a720ccd17926ee463d8328d8a9bd131cf22c441090cac99aa101770a93403c4a7aee939fce5cbf9580ba3ca11517259367b1b75a675b8b284c15404b5118473551a89de3bd775b34d8748073878bbc70f47fb07d45f5dedb9833dcaa323b34a8b90436c0392b1e83821f6f13265b86b435e495376683be1f1e357772e4c4935471d5fb5539b39ea38129f095307d679ca6d593105c4ffca1cc532381172ad40756202cffc86405079c452b46c75099b01a4b6711e75edfbd2f3004de3b73668e801057b07c58e24ac347c30db4e59b9d2fffcb84c85a2bb6020f9894c9ec6fa450ce401c0247e1de475f8e91208a86f878239ee948c253cb586aaf9a70b15ab8bc503b40c07c887d9cbf4a8b4373f50e7a85433baf4cba34e439e8d57aba48a3062d1a9fab4ad6d583b10049a0efe2614a858c34b23f233b61b21a62f09d91019cde5a0f9b38fda0689afc7144c54c7e2ec683e27e6008fb4631e202f9e3a02e513568c15500e292014a41c3c48107ad6396e80ac9207323142710cece4a57efb103c2431712c352ea5bf26954769eb61d109a0b48a36d7b1179c57845442923d0f53886845545b03692437cb5b1046b5e0c2b782405ca801ab9ac9d3c879ba5c4a28ce072bc7b29ac22f5e470f6f186fc3af4b1144391fd15b29b9564e4026d01dbd66eec5d241d0b512b4b6feadc25a938f1f37d2b0278f30bc2a4b6ba60d21d6e794c553f736e2a292378490e2e344e38dc7849dfedc1fc41a1658053c795d922e22e8b4c267cbb4f68d4da7baf878c3a404162a6188feb1a4c38bbbf3be855e41e28f9f4745e94c9fc6f8f4f3305d745cf9c06bf8eb6a8c796e8fe98c49f6cd3fd7154cd0a83af3a072b0d9731e78f630761cdd921446145a2b2b0952c90930eb80e2a538f7b9519fed2327c829731067878fd11f6a507f0f1310094a1d13cbfc33007b50c4f357e0daf584227fa366c0024d5be72598f1bcec8fa89f4eacede7e6c6d1a8c157065088ca27c72f197be5e5bec5289989c7465088fa634e2a42b814c52cbf019f7a7998ca31347d42e3e308d06fe8cc5cb958b2def8092ad13febc73b4d62e28d338d4320805be494f927b18037c0c488d587cbb259e852e9d880ce01fa3b0f4797c50be65a07378c5f4ab97897b97a5bf47e71b2d467a68c456dbd4c5caee3c2776d7da4968a1e26db8f7bbd4bd1b5622110fc4e32d9d974a12f91a52c373278e5b1dc68a6dfad218a17c23ad922cfb7f157df28924797e439726b8695482195ce211057a9dd966a48b5fb88b785f400233799f48e1097c76ad773f1e6e118708f3663528a0b7304e11bce009021a806d2fd3f11afa2da6dd167c834b55da3136fc83ccb858eb93ec46a5c2a5183ee0770bc02a4a316d18a05d9c1c2a9e00ff6d00937f54f2a6346255eaae9123a8ab33442558606b17d54656a125da03dd539b8e042301d5150ef32b4df0e99d70b781d697469cc3c878500d8192fb07125750928432d121b02ed2409247553492a74ac7c906ebcb971ee4870fcdfe84497e8fe34c16942c7de52f9e890d8c5e8004aaff43a0496b87b29e95f893aea82542f055fa015238c48bdaeba5453c0c18d9da4b34570a17a0dd9f2e9075f90dbf551a8d98b764e86699542e94b4de2580c7edd29d801164138eeea66f5c82c804b4996b0402892b1701c1abd23d207a345fe11c2a431055b4c2f9c3e69dc64745fc00940ec40e68db90d56e2f1447124a907b5cf5e99ea2cd6aa079904962201a6275961601c5fbd22712d265097fd072f216acd4456947cb15e2a2383477a68391e79f3368208ecb9bf1f1dc2d36dc6316a190dc7e4437861f9449f737de6d7c5caa6a68e5e813179564e1d97beaa94cada7de34d595378e5747940c52120e323e5149c1a5310dcb9e19023b5c2e51b9c35667705bdeaf688029d4a9843797d09bd97277bd7e483fca6d2b0002f71f2c114e6c1b7ab8b544bf8f1479e013bfd762f942013e933955a4ff7a6689bd2b07aef097a77724a3a537a1c23e7ddea4942ad47f9b4474682a2a83685ea095b71a552df8b6b899021aa7921e89484687809f434441d6d8ddb3b159f55707e6259dd621fd38b7a3b0321be76970a281e293e39ee8746c1e56e0c393fb6cba15de64c76e97fa77f68ee47a321456deafb4ae25ea6c1344825d6e5aa2b8553707ca32729c02afa0b432263ee72ea3d8c86c6b596cff4d081db8b85d238262d298404a440bcbf296814c072ded228a1dc762853152c1b7bb83c01a83407c2ce122dfa9f6d2916f0f2bcbfdf1ca5eecb9e8565d10ca096f0fd1d2595d8af1d9befef31ccd0567dc1f8a20141fde7b84124a42d6e6bf83e02b53f9556ec3c086231733ee9edc462e0b412dd42b73658ed290721b4910b9a0764b90fc7b4c584e0a3d3e50319d531e0702b1c5ea7ab0bbb6bad806328c9394048b9468461c24c78f6d562453aef6e121a47e0a416b637d966f57fc42ce0c1be6e9aff70ed7661c0b2b8ac5fe846765b81f9289e58c2b6170b09d6675f19d01db87ff1eb0be4b5c6bde49fe118b6dc13f6e766e72466cf9ce94eef3315b46bc6bfcdf4c59bfbe3da455b901ee00879f13428ba34fb5968a7823af38e7fec2a9925c0c09c96cd6532c211dc9eb0ad455474223bcf2e2dfac8817937003a9eddacab5a215b1f457c9b4ce1370d0b6afca5c1a14eb35fe5ccf399af6921819f304bf35f04dbb65e1a5504e42b6ab38e912852fbcfe92d8097a248cdc67e90629456a9563cd342486f1dd48e52be159bde34ce3a623770c19fcebae6027058e3ad610f11cd1ba04bc919b190b2d7ebd2af4bd64d2306faf0715b918766e6d798f74a9650a035fc0bc9fa892f528650d7df0a47c985906a17b773d20bdee9c69288a1e69389f66a93f74ec1ef8e2269e386556a2c7fba7b5e70f78ca2c18f15a709043ab7f418f5193b4ce6676379b2a59b241606cc57e9bd0c49e68156f04af8a80e5fa32162b3c73f6340eec9d7d54b5c54c54722bce84ce4de6fa1375fc5dbbb988dc7cf31beebbe29d7249cf23ee160d4f526c844295119fc053e6943425c956d30f9ab80e916f641fc4ebbaad676ff829fceb0660fe47feaa4c2d0e8b38bbb99134dabc296ce19c5da630b5afe58969f791a87ef38420518fa8e2223ecd18d0d2cf5374a0becf646b899e60f4e49b78366692130cd5cfecc1dc8870c933bd0b37d8ab4ae7fe6cb2c0414a9d44a41cbd9b347d67197c3467bdc8da351ba0ef19c7d315e732197f0e8e78491b53121fb0d6c4f1407b05c7e9b9b6fbc47c2bbe1d8803048de943c9e45d1514131387a847cfe6d915aa1e098c58891e28dff4eff314f7ec516485bc6b7111be681a085a929817299a8f2dc735fdc18eef7de0befd43096aa504f3b919c47180b9158901bf4a2d91ecc87bfb6f42897141570f4d014908c326beaad8f919b192eb72f1f87ec8c7cf0231932c24a1a94b8012521db5adf04eff27269fa19939c6be411dc23e50513b8fae7b7da464e81b8385b52080fec931fee04c010f489a5de4dd1f329c8a1f4a1dbb0ca41fee8d77f95855fd73040e42692f189378ec816595debb0a10986abeb056cadc819d531e72d51397aee59579fc9e3f0df13760e4c073d93d818d1ddac1cb90b769fa9157586bc249cd0935930132a3faf91daabbb2a8d01181f32ef073e732c6fcfc3020933a86f4082b964beab248c7883644b45263fa61b618a57e2775745812715b1fdd15e6932ad02b2c0a90302482ca2c38ebf15f06de22013918b159198bb2c9311bd22930fe6510f2c3a173c35673b0bf1f06d8ecf6a873f05c5b860b85b55069da36b1206e750ef5a7c06b4d399f871ae70be66b7fc2508dab98c631e66ed37582f35e4eed2ab6242cee46203f35a17171ba09817efe88693dc15980f0e38eaa48332bd0b2eea763b3d5349c58835b826ca37c22ef0084e0d7161eba50a1fe19bf87157fb803cb81c7f8bffe53115e40f4fc19daa81ea10ae58d73672f6052f2191881f41e3f82dce1a2ae1871c32f909a6e7c8cf4e53bce22e38ba5b9b123c56d3737b853497799f60eceefec083cca118a27554c04736acc157f8eff18c41345f956e16bb5b07779952a32fcece1ac76cc90def49afef160b026cbcd34b4f57b9914ecafa8c2b9494395861b164dc27dab3e892526f3305f8f9ecae458cc75179dbb7134006c21f1a829f758624d27bdf96d88342e6500306d26b004c2cc9467e29eddaee7804618927037605bffac69cda460690318e1683cfec2e5a44b3158c539fdc79fc64c23f696bb3bc9a81282f76a70d4da94804cb2b623b19630e61f5317a6d975f2cf9429bcb6d3074c68a9f32cb1588aa46181ba56833dd8b5ff792d428e8cada61fd1796ff407b7d7cb870a37b881a4309867f03dcb1f89523b75e5b6a1374d168a042943b74f6438e0d220b0dae13073914002e049b984b70250cf8a2aed9c9432cee6d520038da9e7d9c74a18d8615a8e72dfd8b54c32645a6acb09c2a02f6768b2f56fc175ad0fc6e41d082514acc334f8fad1a3092a22478f780d3fc3cbc9974407c8cfe65554624abaa02dbe23b3e80295154257ebe0efa91090714bd120464c9d52efffa3421192804e510c2373267d7f7338661bfc125adcc77dfd66f09092f82f43010d88d89fb9ebec18c021aa3bf9688ead928ec17c78132256bb88ca3ff7a2547c1964e73af730cb69ee116937e3a211bd72c91f2c57d8b864fa1aaba099a90368a64d92567a5c35cfaf06e4b9b81812c95a4973cff165cd4f2dfce100dc0ad3f3625532aab05cb29899968cccdd5dcb4782d2d8e3b20295abaaab3776336e8c476a54bf4a32534a118bb25c55b26db6b9b08cde401960cb4b28ae9c0b3da2bc75418e95072332096a0f8a94f146db2121132c82d842c3a1290fceb500d8548218e9875cc98864e261a9f1143812302386030a6f8b6ea8487669f455d0dedd3aab153c169d3b35fdc861dee24cb993e6bff13adcec278db4a390717b997d4db6bb2ddfbc33595989c9f44f49013e49eb093c03100000f47e90901ecb1fc64ab2c9e20f812ccea1f6f3c709729a0a67c3ee061d62e27f4a73a0ec6e624ac1f466b851e3c9b049fbb7c13827f036563d4e991362486581e96f03485209a1d4f2611c77be257a4f8a527d278dde663e8aac5889f919a2d8ed342fca86ace62e41f72f3be6196ce18eb7046682fbfb6e50dda64b916ff71f45a60e498cccc4e63945b5a27a429dadd1ddc9b8494ae9822cda57b8c7996a22a2b7d0f7bcfe3c324706597b087023cf705ab9e38fab9e30c6f3c40f802c421d3a5e2a0a995a40bea71704aec7cf485cbab745b426c1d6056c4299acb50ae409275cc6b368273a38e0fd859f6d54f616bdabab70ec60181ed4634c12065c3d234aaf93b20b03fac204f19998de12bdb52cc00b2bba006572c23889e518f7764c3ad8f97c37647c295f77776fba74745571bfaed8f738385b790d2fba634a30c2b8501cb9869288cd072bfc6a042824b72af9fdb0bb5b9e6f8e62fb4607362665c91680815880300b9f6033043ae76427d878cc994699ddf000e433d069366193673d2d029ed6ef2df3248df53865abbaa76d19ff4b0eb05df444d58f79a89f69b288961463f05aa23932c8782682a02677c9811c04d1419fd475ccde64cb120510ce3310ccacdf6e589da10bea368f02709988015f432e489b802845474b4140cfe4c521fda86ba7f55119162ac1cd46909a65bb9a3890f189438a5fbd5690d6f7d02763b5969c2c52f20591d066b216ca16459be1438f2c87d6b4d7c27198105373d7bff656427742374e9555f59bd5e59853e067ce05ebdb503834e2e61ee4d7bfbdd597ec466c343fb4b75791fb2735d5cae446e27d9509e049e2ddb30a04581d6e4fe01602bebce9aea7d0284e58e714dead15396da25d0d042527c0d1a3445b67f8170848046c7adda93846b866670280a24523933014baf83b5d827d03d40189e3c21ec30a8cd02caa84e108cbc1e6aa18ab53f43fc03cf9c20867482652d2be6004d30305adb7c2b66d949830bbbc762f2692254d0bc754fd477c1fd1c41cb3b87985364b8f401d761fd8e2377069468f19861d91b9ba8c19d8513dccb936e84fad23e84fe5efc7ddb5ac517d0d53bf6d0e3d123855dd2221d6ea0192d33e0c9163c012b03dd174dfbdc691100f7e150f548ed892633ce4337e6dcf8a7fb906e7ed1cdc03c96e8004d784cfbb1bedce2ea08f4de9bee27dc56a1353c72d9cfd2ac513a708c93b1e458cad2971c7e4f545b99f6c6dcd38243a14829940d264eabeeb1481b61625e25b087ecd136513aaab326e82c9edc45fc3c70dc670feb69f5b56fd979bebfc4c27ff8da39c0eec7c8c0aea74ce47944abe3d8a3502a7479c448f30ec87e2c954a3fc5ca9abc2da005fd68518019732cf8e6cced8520a5486b0b98db262886d29e2da08d8937594a565b05016f31b66961972b6a73bc82a0a8ff6e45953ee701000421da47fcd4139e39381bc9edb5152d3ad4384d411a7477fb4101f14ef0b9a5485e7c34b9965faca824c99298a04fff132b885660d76d6affb474ba33c9eea8d9a89068fdb29549e2d401994af6e97e1a47f1c66ff2bac848d642597a02b3dd757107091061bdb2562b3ccca0fd5adad56dee5e74587c553fd35432aad4ddadb4cd554f29ab10980f201e4f2133018dcbd72c86c15711e20077ba25d349d233b18bdb0d8cac531eef12dfa851fcae46bfc54124e17833cf3923048e9e385e53c5fde45cf1b8a04b2530676cb62abc745f17e4b10cc3110c8ea049604ead62be6b98b8ef7dc5931ee391e4cc2b14e616d85d9284a5755348bbbf1e68b8899864ef07ef7957a8af1b1573c607e2a957b0a969b89be352d6848042bd33e7409803af668474164b7b7fd46dd8b6e385d1bebd92cf2d537ee9b4f6d322bde67d4e01c9f34fadb3947da22610e2524045ef245a56a3805271f18779f700d6089020c3cbd027a6119f6853b5c95c58ad0d552802f86509598499b328cad70d4422c414e41db30dc49841e8d0012e0def2ad4233471be412845077bcb522592f249056258ee43c147bec5e56424413dc4f5ea133b16c474c8c6b699db1d3c8134adcd24f6e518854689a5138f71c1732a2696c8ffb09e87ba24aec05a4f149d37b0348bf71d377ddcefff8b3170f1c693e2954ea65d875ae1abcf0c415069e6a508ae78b0dc6aefa5c4100724d49f5bea4039b0a98cffc926cba78df361bd19fb95e650393645279a713d89c604513bce14ce24c08b06570a9e98731174dc2bc52e791faed47fcb9b3c529f07d06e8e3d687aff4120dc0f637b8fab4bde341b58e4dfc70c0b8f634cd22f4b600607a199d1ce1e06ad6771208be15810b75a39dc02ce93e9b6ecc9b3ba00eabb2a60a6de8828d0e758a02a02210d56f9957a5ed573cfd246efe1c2d1e868b5838747c33195758590645fb4a1f6ed056db9d1f2be3f3309113eb667cf571365553f243a5812d47a58396356b69c9f2ea8e7058fd1d926a990ff37d9cc486fc1d8fafe2865c6f0e018da7d8677c6fe87d14fa434b1b59f246e0f289641212f6ee0527913828186c00e1582c52438e447c1457fe5ac8b166ceee0070c58d786c1111410213d5b4858afc5a496c78b8e8bb91566a1ac4029c3a2087709c9178df19da41a958cc003334396d527b9d85bd4721e2bf396209353b2fca04ba124b886b0c70f3eef2ae441479ac1c821ab16f30d4f0f3752341d61f196dc2e4b5d94478fe7bf0cc95ed1b7f5d3281518c1088d42aecb4eba2801c80622fac520f4a556c353b107ab2a27a581f1c2194cd9b0f405dc689b55be4d46f79e82e85d5aa812b11f5d09e4e3a215fbb560f6de903da5ed4436c6ca76800194c0340ba0fdaff4eea81c332a093481f9beb338eeef970ce600bedb83ce11f39f9204ac9a9ee9ef3fa926a3d67d32bde059fd9d120308601d405e9eadb5167fc0bc42e4d10f3ce99f5fa84a0463d5412e7f44c57b63c95b08d2149daf056f3953f02969bfc2bc80dad0bb1d3604dabc03fe5c655ca52ef552939f07df4e1f097824aee755bd1f2f08e67565eba22f12b0fd9d71a5c7aa82b2cb671d0ae6c535303e2cfc9d58b5f1aa144789b295c8ee212f1129a6537f84a8e7ce5400a25e221698c2e06ae4d934ea08b3a1a2dccb5e517b8432e25bfc2f5a5b377ad9397f4d91a4250279da3ac19ed6fb26cdbdbcb635144abe11cb6635fbaaff39bff9b0a818d5e1c98584c6343ea5090e49af7a49a730931b9fa644796195bb013ec8d9a99bbf5384784b91b4a6f65355797a27f7b8856eb8e1855f3c1807a4a9528c0f48f49986b1fc31c01f68f5e4ee268234efa30c2bf7191fe49b8cc80c9c936b4aa04f75b654e1d1ba549f63e6874daa948449cb443e4369cf2eb566495448fa52d3da8468eb0a2974fa99b9345d327bc39dec6fd25450dc24efdc1389246410173735ca780829b2fe88ce06ffc04f423ad607fee7870bc303b64ec0fa828b6cf3d1829903c7382c83b5e04878c34d215db34a83ab2b4619bbdad94313fce97bb62a1864324710515ba2f1a792bf06154d68eae99b0ecc66b1ff55f68ab241381580bc19a73ca1cded0354e42220edec584152b12b098c82128a428ee7885e68f6d66ff73c834971523b6793be2b86cd60ff3a66cea0284d8b972b32db9888887ae444fc396a55cbc259c9cc380c37641fad6dcd9f14310d1d265d37d08eb176e36518b5fbadf63960e2abd901cead710ae5e680e253dce0ce0833475eac3bf67ee2c84e07f5c9972e05a4a82d278d3e288362778e9a730120d19c6180136201b5a83eba1ab4566e96f2e6e18a15ab8e7f443ccee43d462e9f1a9ab190ce9668c5f45f70b2543aaaf00f88a9c61aac89d1519fb4d22a4937909e070da6278a24e23c4e36a12aba73ae110f0273a289b6cef5d380762dac269694964488eed71386e7fae4301ded599bb2f45b828ee40a2245c652f2a7c96d51ef93da0aa48b47180236e30b2d4606e7f155345d8a211a62cd4d275188171adeee6c6bcfeccb092cb8a597cfece96a1d4ec07ce12424887804bf1fd56a285a474384caa322a7c1a7a54bff48a7920a8b179d14022dc8f395971920ca2c35b40b65204d83867f7b38c8a0e842dd16b39743dfd2752657bb08b0af965fff00442b120cd81d3f4d5d2e6d9a14cb8b29c97226188d10332bea092a4174ac7bc2e75fabf87b4be1ad22a2fc76608c1c1fe8d7875822930c407fda01e1bbd1e1022e4c9fbc229c0375d238b08e883854bcf3a64e5c868365dd67199852d579d64816144c83cc5a35a9b91c55b1c634fa4d1a05fa826f4e63440d90dbfe733b41922bcbbd892e999076149b73bc1401388671dd5a2b194f12f9b259f4c27913191c3fbf483f26d26cd20bb40e4f10f120dcb0bf1613a29d665242d314fd71d64252be28681d9752545748ba7806f8459bf04445f1259204d7cd7cc724b1f029c5ea135f3b7dd7f7dfa4cc66fe843bb6216b5163534252d3fdb2ef0a290754d545eb68b69a373cc950aac6617845b7c3892c0d7e6bc2bc09192c4ab2a646f3700edc4dff31921e76e74ef58448a2e3d0826d63b8af95db75704664f97f6a54486df5d8a971724757aa3fcaf3a38aaea79e02a6e2ab28288ccab5c7950cc315e396408dbf1cc338c95faa86620394876d0210f06c70a5d7593087632908c4bae40d80e889f20e7584545394223834ae253327aa8b157f39fd403d2271eba3cf1d9869af49ff7c888d638d09af319e07d698d27c6447563a01c5ca55b61b256d1f54f523a2f7d443397de84dcd3e97d678e95787874a682bca9bbbf127d2df4716e892ceff2656201315c3393b7aac4c9580184d542c7f1ae4802503d8d41ed44009c9585b99eedd18a4b5a8050d4bf9f6f19f00e718949bd53105f651e51b6831b40c92319fb2b8283825c3ae215be1bdcb0500424247e0cc65ae34b677eee7d79e2b640fc14bb731936c6dd34f7fcdc6b0d02ddc3cd7f57aedfcccd58ac9201305b9a0a02e3117e7338cd2d4fd63f1089cbe5b364211a9ae5e236f137fa4fbe5562e22c05a41158a98b7bda158c0785a9499de69cb6518e305d1833c8f07d5bf9f2c845d89f2e167a0aa40ce474b5053647516e2c7c353990fc6611d882b4bb4eaec189e8d2a4473d73bcf588054105c59d67f5a61249efc49ac92831c1531cee0b4ba1e957e036a3e24dd5d54b50188ffa8c214f8f093291b89207a24e8ad72421f85e1bd50811a758c4489a29388ed4f136a65f0ec1f9c1a0a6f7f0e9c4974d0575fb3a70a6f5d6254cba74e92e486edd9c7738db622a6975c3fc0ffd48baafe90e814fd622adf7894500344e046cb7fe5806904a7b0632d4e84be99e826e5272be06213c6cd8dd88ac0cb2587275f6c29da42706850190bd29ffba32ceab097768dd72cc3bda0541dd221cee1609b9ea160525cbc189b220ec8d9b22d2b20b2ab745f4692601758efc6f2b30b99d376f47825b3c7f5b1c5fff064222f0856c9d27d29669d70c1d0b706522982a9b42a7532984b6481e02f204e80db79921e72f4728460c7ac79e5acdeaf2f4e9239760d602a299aa3b592aa97615da8b82a59c2c06232dd12dd7b45a7e03f685f22f17cffd2099a0600eca92967d4a0c6bc81404b1118b1f7abacc5794197ed61ff830cb6864a216d313525c1bbf18526d2de58e3c024bbb501b7804198f168be6ec2094ee02325f9b00179725c4c3f3ad4a0e34dc0fa2f417a4060c26553358114e764c95a78c818559e2481693982a9829d7b5891d7992450b41aa6e7a57d05298571b6e812fe4d5d85a3d10a18437e68517015666d399c576ab8563455ebee5b2339009620a5808b6ea290da2b28b437aaf084e0fb8eb2f289eed640690f2b1867d4d3dff2dcfb0d8676e0134d3ef49a4e2e524582db88cb440f53877cdbb36752e2cd3adf0c3126f889e21f50e0ddedba1550d7df95e2ab5ac55ce1389e9fea99fe5176a587e736603a540fc1d4f8d6b9ea582c7917062454a3febf650412a95149db2d5ba10d4bb475041f3c4f4e3ff684b0c14b1cb51c50b2ac459cc08a788afc17325f79e3aeea46839fbc44809c877e3058acc81bf2b831d164b94d3fc3ef00d8ef76af870f3ebe1d14b0fcd5ffb32e4ef370c499827c76082cb174c3033f3734b5605990b1477e1d9f99ee9e7ce2ba9e906f55736a216904860f3fd2025b01b133bc51d835d0042fec47a0e5e89830d20dc1efeac4fc09eb86bb46828ff809e7d4dbdd8d8d809ab2381290dc6b50a6ddb1dffcc43e00b026401e871c801bbb39278d8e457525f88866d5f50e60a05781ee25f09fbb26a8b75e27ff1d37dcf6fe24191d3c780ff2d5f1b7ee8295f9ba1e0aab96f064c1df0967d43c570622f39a092d256613f69ecac4f0cffa453aec8e0964684c5a369cfd0a3495b1389791a81583e9702abf1082d701b242267f4bee335de714c8b7c1ae3f3f29c6fbf29effb4827ff69d92eee3afd207896125f35527073e11bb8e08390b4469b763aefe12f1b7590bd0ea22191d7d51173764fa8f14e6274f58e13506a0741a6dd8d61e49b40a9ba83795615dd95ade32c80d12158df6964c76eb8e37e2ec52f29f178179c333017ce4f69c06d469a728383c7fbe1b6cdf9d4bd40f0956edb7d0e16c4955686bd60f1c0ff77aaec3c725292797f9d37a4eb0047021c5de3593cc64c761f10d56d12d4c7156077d159e837abfe058b14fbc36c5aba46e8685182633da287167aa288a852e2f2768e9e6e6bc06ac01f1cd382d1298451bf2a539d7c4da6a9881c69bf3a99680ae77f31ffde16ddf74f11481465b0bba76c2d43a5f2fdf329f7a81d076e10c2bad04ffd60a72b5958a0d17074c4c5bf31d02b651bae51d14d18aca473019acc3c2650709c51d2017e29d1b6921804d4f73200ded029d99aaa0528da31ab5a116ecff63735ab51f14e7e2404cf1b7bee886100e1e5657ce7a771aeef51009dd6175bdcc6842f321952901ff6166d42884c5ba693023f0217023abdd44ca14cdca31a19a974dc38803a30db888adcca20a807918f2b908f930f08897af820f271a21e3e7efc273ab55a58ab496c69d775dde944a433cdebaf72afebdeb59df777a889f252a8cbaeeb5ee0598245de7bccc8865f5ebea2f905cdeb603167cbf33ccfb34eca53792a9597f2bc94ca53755caa5b711ce779adab89106575f10ee4aebfa2628c11a654abd4aa634dd55c01cd1b1963645d08152c8c55c27583116f3bba68316adacd0d3c7133d0a433a5539ff2a7979aa913cae35428146a5e50bcf5fdf6c897ef9043c518e3f5bd0ae87ac59bab39638cbef226432ec5c2f30e44a53c957752459597f2bc946aefa938cfeb54abcef33ccfb341490806de81a694a7f254aabc949752fdf25410a23cae9b1e8487107a9e0ae1d9614a92eb0679c995abfb5c2eb6596a59ee569b6db6d92ab5ab5aedf52bb5ba7677777777cbd0414d6be32c76dfaf5fa6582cb35a35b071c067242b58d0b0945c1f58f196244934d52b4df09830250a105a6248c2c41dd51d75959d3b0e85ea4e4143184025140ac54a824245d9218466faf4aaaaaabf4eb1b1a9a2c9bd7e696aa31db2dec4f5708021355cb09c6212ed74f289559a38394175ce4583e5c449eb0c6fe179a10a0a2bb851813a20c38e2c5c98b2101e4278588447090b09033e578152c29627a8805103d6b02cf502e42548c88b096904237d695d3a21840233c5e01ce73293fef91624233119770c61324913156cc88dfec45593884586081e2253da9022e6ac84346848af1a9252caa12021a520a1a1a021a032b42025290f9576ca9c4b9860f105163360d76969751d193bc428729465092fb03461247bb264c507c5a19742851a8410424d91ba703c00ad82a67451814704cdfb4278ecc2300c5b6c775b443e7a2c292d0d5999e23b4c0285a5b76fdb77c17495c76cdbb6c9246ddba4847c94979931fbf7ff9b8a09737201611761be635b03651de6270c7629e6f1e9677f2f3722dafaf0f881f23c364618e79c930af82dbcad8327d82345dbad0807827f973812c0ef52877c0ac2672e1f8e04f02b0af2ad0fefa8b4fdfbff1d4614b6ed1c6f69b5a4759c6a75dd932b05205de9c284866ddb1393cee9b86f759dd4af0c834abbbbcb7128e0a0d530b9ecb2275f6c6c3efbb76ddb66ad5116adc8f499ceb06ddbb6fd833f6bf10149cc10b6c4eefbbeafa3d23ef23aeaa35d47e542d8799d4f5ef420e430130cb8a299d6a839618a858b9d3a6e72d885619e1cc4b0bd969b8be2b8a5a9d42d794a4b124a6e9d384d9266f91dbaaeb561b87cfa1de3a22cfb28cb3a2a919094945a2d28509a6813b5c13e2ac43af621b28eca252b29e793923e97cf98fdfbfffd39670c930edaf80186a88bd0d22ac9832716d7994efe15479aca035cb06d779d942c69dbb66dbb859934da08e3c492521321989ca0464a82972f5d3e5f31cb944386ffff7f0d725d23b661415369ae887669a9b66ddb4ba9fecb79f550b344337d96119ed4b66ddb595e13452f086d92a020dd3384dab66ddbb6b568b66ddb3afcaa2aaf57fdf5ff557f40abd55a86c64867315b0f18b7cc86a80dec62615f5aaa693737520e3dd1ea6cb0a839b191524a4ba57fce29e5e9c4713ebc03e7bc96148c3a09c83a40de81495c109050124a28c618858082928082848084bc99529a4049495aa02439290b04f3f9cd09460b13982cea15370f31d2a5af68fef00e3c5d7f35053ea61f6882e2f365adebf56dd5566cedbfd8ffe7acbc6a72d02e69f90dbbe63c02872e74ded8ae90d2b68989a2454e4e01f6b921c03d36f07469f2399931fbf7ff5b8c19018e6834101cb0503e4b018e6834dafa01530e785d7a5d00e048f07d2bb2e0ffeef76bca4113418e6f8bb5a942530552502bd90a18d1f4feedff121efe3fd4abeddfff6f2946b48883c532f8ccc1e7ef230245d8b68d25e90182bb7ffbb67d39ad00297d30810f34b56ddbb60ddd08a086eb0677f9d4cba72d0d2208f2e910a5d0f51337201efcdc5d0eb7c0185a11aa5bdbdb0264681deaf26dfbc64898e94a98292634cd99fa6f33d05acd667fdba2f81d7e0c9694ea936499b668391be857841394491edff5e14c78d28cc777f3ffa7e1216896b7824791d979dd5ad7ebdbaa554005aed0541a2a5c5deb7a7d5b555555f50ac2f47863f6efff373cbce968618f11da25b4aade6a55952a67acf00a151ac2efbf48944e1d37cfddf397cd4ddf1c77ecb76fdb8f21ac5cc9fdfe7dffffbf5c37b9c9cdfff2dfff0398f1edade03963cb299ebeefeeaee5ee97c49a27046c41a4c7098460d8323bf6dbb7ed5ff9d7c63b31eab84c1c3c6da8dda3b80ed519f5c4b3b8ee818f5766dbf67e77776ddb46038123e662befdfbfffd8502456cdbb66df714b160a24863f6effff7ff1fbad02344969a1d6402449653b8de5dddffff7ff9c4b74d45c6ecf874a4a05a7de3990d4766dbf1e9d0f16d0ee71d95d9b1072ba020f855900dd28a05c40a12621d6a3370a60b29a52a4d9216e129ca296d9a07fc1835ade8e601db11812d9e38fa316b66523555c76cc3545555215408a1c20dc156abaaac91a215715fd4bed130a1c33a970c442adf91f8fedf7049b82f53abda6adb9ac6ec9c8607260c07b0470bf88ca4258c4f39cd60d0b8e1ac0cf213e5b30d67b72022be1a359044f30f0e2981f02094c91899c92885646236990d88cc80384affc848b9d98683c9191c6cc3b9204a192994c94c629b5094325266030200122df0e0c60f488408f98932c88f7f62369c5ded4072041e75004fd75ed7d1d5e83a7264747421ff890c5d46f898e9c278845d100321cd214f27296f4e10c26d8756ad6a21ab23064556095555f5590c361345a24a942059a35476ed36a7a6d1e856248b668e8c9cf78967dd68f246cefbf8878544817f667e66d4e8105e5ac96d24b66d2646488c8e1cc960db323933a7490665bcf8cae818b56dc7c82b47030fae817e5b638416b36dd47270449a08e2860376f7d9d8f1d8a05d62d9b11fc9a2688ee3f837d7b0e6544293a499f5d9b66ddb36a1e5845cef7777d70abc20bce4552f6d4971d0b06848608800470ad062dbde42b07df81fc24308e75c4283039519ee2a1a942a55555555b55aefc11f4a10420855c110c19386a7503201e462fbf7ff3b82d1658d36d3c9e97c2a3b2611e7c28952bf1c1def7847e58561d8628bedb5dbe55a923a4f68453335bd0c82e778474a89a4fb56cad3cadded8ced6a6b23e5fe0b29a1eddfff6feb605a2d0acd644b850a55b3394d39280595097b6cdbb66d4b99d921261b9b8e0b079169a8544e1e758a0600488204331808201008825018c90239d133b107140012455a3852422c342a8d04e44069281a4d411c07510c00210060200618a510724caa3d3b743183769bb60ceeb26d0534b614e6ca17022556e12c87d9abb9a859603f2c4621fd23cdda98cf2b80e0061b73904f2263353836308114d1efd6cdda80f3651cd9aebae0b26375be7fdbbdc7f78c105f917fe8209398c5609d4b273cad4b2ced0aa1fc6fa55748813f872f731939ff76850a762ecab0e0a436cffa1925ee152b521347224774edcf18fbfdabb9f2e7bdbde26728a0168329a5d6af17e96337b1294293f39b456b01d4d281e9b3b8cebd03690b3e6eb93f8fa60195aa2707d881f255387860a9799bfc93650945f25c3adee06393046580c56dc46035365336b49d68f37a8d3e7a56b8311367500494a149a925bd1566d8c0bfad1d69d9c950d8d913b9a4e9b77a781f2a99b4ef35d640c7c8af5c002ddad0bce233ba1a67213ba3622c080147a10cc0c28eaa81ac207bc59ece3a8a80806527b6a750075e65dbc37aa67a25e178dc0211ae40a5ea6aebf8445d53c9fbe961318fb601d831953db8a44104a24ddba21b63dcd2f5f54d7f6800168e744511b8d8f8bdbe2403a157ffee18801cee1ddcf578d3850d7fbe5a0fe8979c25a14fca4635289cca689472d2fe4b0a773467f283600e9924f18c49c1734fcc3683ad723279393d133b2ef01b343599048cdf09fc78da121babf6757a202dfcde9185c1e09806a5d2e782ca3463483f12b43913abcdbf4d82f977917886deb650f50732bd2599e0a5094f449d4a08eab119ca5f3af50b43a90a7b0d535b22709bd693a2db2dccf0011b5d37b2fac0ff1ad644d8d0d2a27b45023f8f28898ee5203a514c629aee94a235c48e81b33c09f17501881ac3cf40ba5ab0a83141b33fb4a237d6ac5f21d5076ccab886c68fd144786fe270356f1c36c4a040be477c27554ee5f7b26cca82baae92f204324419b0b1a909dfdab97591b2ec4f269039111b98f5f57009243175c2a311d2168086f70f132428a72ee0c7a141cc727c236771b14557bd211c800475c8454160cecee0e278311bbb42f2b78971c11158ca0496b433660972bd85ba5080b0983c53cc5239662128c83e48d88d40ce6e139ecd943357fa0743114e7e25321b67d2c23875b4dc5df2a1aee952f35297401614154376d9fc8042a62b47dd86460348b40e00aa9fb058a2bf06a31b27accaab32149789a91e77cbbef41a7b11eb8f3eec4321903764133ab2bc782d43182e2eb5773248ce420498bb7ba003d6069bb820e553d93029ac9bae1ccaf4ed218b8eadd0a34308248b85b88b64cd93d55f65faf8d4ed9369d5a7dfdc7ab1b7935701588d6df8d7c63038dbe138a5acc77ac430e041eecc236118bb20abd6de11a466ce36186cb4a352a65fa33a88bcbe056a371e7a0a9a6a284ab28ab0a402d5fdb08670cd17a5c9d94fbea404755db5c4b49fd78d6b554fdb03b4bdbe0cb494aad3f7d29da7e7cca9713d1de2997c499628ba59b6c29fd20dc2a9e53011b9218e30eac35543d811e65866abb37e178af99a8b5e2b650b4f2b9d9dcccdbf20ada11a7084420d4745418b0285d38dab5abf884affc7893e2415a1dd0424d3499b50f32c47e3a3b03f65a9124311cd74d0defc293d36f70f7b93d4032ca8def9539ced1a33d9ae1c608df450c7b781dfeb698fb275e0fbae56af03bb394d791bef25d7d93f15669a06caca4aca109d1ebba42375da71dc41e1d7214b290093bb6cd49de04582c43a8d7df9d8cabd9964dd8d6f74fb32e5e9487e31c1a5f8531576a7a38330980ff4ea9b5dd330982b094655f67c4cb582b79bd3163350983886c072feedec4f1230575588732ae1602a5179c6cf117713a008f3200fa6bfd35e6b2ccd958edb28e02f7ce1868394cf95808b8fc18e85427afa9920c0cfa41330ed4c7e78fda9d8511e772cf72ca96158ae3d3b28dd2a64d0fc10ebffceb4730d969c425ae140b25a467d865eb2b10c99cb6b998fae8f7930227584332ef1dc085d0f64c63e8ae6f34321f9e1006c264fd877fca626be00032f5ecc40f8505e5e8cdf740badebd5117033a075f6bf0b9994ab21024c1e251b37cbaf31da0c8f05cbc46783a70aff1fdbee7f483c24b973acedc9ddbb7681d71c8fa9326085b4855988375114b292d34263ba087e96e22e4c3d994504212c2d50400ae6e9ab6c3edd115d4232255c881722b911ccc422fa1b0416b148415702a1beb3c4a7e7b6a938cfdf2d869420cc91947d847ce3d5656f6c458bfb74cc77ca247fb10174531dc431c81a2ee112f3e7af059b6103e8dbb73ad494c6cc50ae6fc35bd43163ae8e8b7e9efa9d2f4d1597fc22152d87250645d99843589eda17fb60b4ef935e8cf9e0406dbb7cb31198a41234868a7f7b28816d7783d52ecbb30d041032f3451c8d8ec1976c02d08fc3c958e05ef6c5ad4e9206ab15dc81bb8ec76712f69d3e7b25bc7abc9eecd8ff7f2646985cd1d7327119ae6c6a35fac5bc892ad3c0cb1bc1c6f9a11b3ff9f3fb2fe92ca16dd803aa9c477cc8fbef0e04fbab11133cec3bf71500786d7777e04e61ca4335635afe12d3f2611df379e11fb203a930f3466abd27056a88a5e8b442ac3eaf2044e243118d7a7192919a930c4c294522c90c097659ac5e324e05d5a173a02a2347bfa8befa4419aec6780c7919fdff1d255644ca80cc1c0ee4b569595ba56ccf4ee4fcac6dea1c7cc4567ce7c028607ff81b1df21516a7c83adbc30c03c6c941fb4cd598bd9b88c6442f3dfbbe277116476a60eecb5d0d593cf18edf9bedce6fc91a99c42fbe6e4c58c7afeeef01b41addaa2f569ae1b35aa4d110d2ab04688ac9eaa941dd84dac451c122cbeee5c1a4901714e20c40fcacb0fc34bd8601e5d7ab5f061e8a7833a43eb71198c61e759e2d85eea2b35a79e9257046a8cb47dfb4926c985a2451bdbc6d0f574cb79712685fea63d5393cae17e5ef054e1901876fafb1d444fad7071a369c0a3a6008f96556f50c4c35ecb29de3f0b93ed25e36aad52733f20d64266c11b7e278c4dc4b197b7ddf91c9d476ba9c48b74664e8175f9cca64e59e784b661544f9f5f2bcd8244c44c15b9061988b01f01d81f48ef7523ac4a6c2e6081b03aaa6ad3252e6af69c7b50dfc3da48934ff4b3602051b45b84cf0b66c4d07f93f96db354500470a8584a56f6354c9cb02bb9f1bdd0a2486779e60a576723971e8cfa5ba8b2ff0ea51a454210a1bc73173b130e8442a22939d18ef5595bfc3d7676cd6541f7d0e2ab82342153ac428c80230d2ccd83781acacba99954c63a72b517733b014058dc404321abe93c976e8b98be8c175931d65791cab8109dffaed6963ba3c1b751d51caac761cb660396c7c08b0dc6c30df4dbb60b516045c0ac6ad4de50c57e521b0f5157f44e30e6bf9df49161f1670bd3bd415c260176a3b2a2bf72242b9d5ac06fceffddae16ba49b0237155fcf6d8185143252afc50f8d08de8df4e44b770e6e14894631611b899f039fb8c7907584b06527456c1e69160ff517f85d847d61bab35830900f98568db6593e10f2474f060f034a411942a93441b9221e8bb3a3a5f3c5530bc56191816a47a8865b67a2d3caf5ca611d0f2d271e1cb23ed10b760feeef7960f530b83c2995f9ce870c4bbf8ad980190893f3b163efa746dc5f84e7281153f8667db8d881044d609c901d1ac02b1bb353cdbeecfc2bec312a0cd0940f52b4274ff97d83824cc4340dc26ad01200a90a8cb1b74f70c9f5e3febd05da3440b45484b87e9b48fef10504a44d43a441d4e5b7c848ae48966cd7a81d5325e3bd3c4bf0dbe5b64060cb0c4161054b67dab965e0978067479ae7aeae6b7c5dcabdcc6dddb554a158dda0d6de51e7aac45e8cc171e314067183b5b5956da4c6056983ba3d4824c503d52fb304b30de9eee2a1de79883c8e6132a8989318f538968fb6855bec8e1a85c109b087c43d1bc0699ae5760ee8ce7cf9a3356955c3efee02d4412d0b4929044cf09c41eb407b7c878a527afc37baed98cd04815e314439e587656f19b7903ecc7d813892c05f38b8b820030f785d66449a6ead43401d2961a2b13a4252e1858a58f907ed9a6001b6c9c325f4753dfdb966f4e4edf304ca61605993993b83a2652d9d36914fa763a01d11ea53d4d519b74bbc8f50b3034091558b0cf3724f1b5d5188643177ad6667231c4faacff0e2ac54e4591ac6e9df68820fd575d316f72a7e7a2231eea589c0c5db733171f65f0067a68387d42cab69e63750ee62104c4be27c6b8d297921710990d3ca9dee5239ce6e2351f1210d88c6caef9c9b38582422d70c73b342f30c8aeb94d4325c80344789e837ea337811f131e4cd9a0b3880becf6b1a5df2ac188fc29a04934dec44223aa4c8289a5bd7e051f012112009a128f19d7ec48a6e881ba4a65bc95a19ab647cc8a246be503d7b5b0896f4def0140825fcbb792e6c6a3706d8bc173f6a5c7bc901d002313ca9712a901c1f746261ce549594e6292f87231366da1cf29381a6feaa5d30a7d13ce7c06a65ea790511aa82a617646c99bb0e073489ce6dd6331f14e250b03943b4effdd840c867a32d28ac851ff4c997173608d0f0215169a7a902917081a83175b3d55000421db8f40d75e078d0303cca5a7783673e8450693647f6f213d540a741811b7580ff2188e615645d96fd6f20cf315e4035eeaf8e15afe0557dfba0c1275012b3c993b26456e0134def41f02c42af7e63634d7fd0c4022e030b34bd6c2eba47e1910d451c3e00699b794b05ba1c93f46e174d2371b201f9f99a4ac20b79934391a751c577e531d0c40fdb6292b442fd9d90fabba974242479900a4e7c9feb27aee6df095608d70ea286cffa02f7d902eeb3e401381d13f2f5b55be11a6baacf1aed75c1b47e2e94c7454c290bbdcbef35a977f3a299005a2ed6e292d5f7aeea0ff2f79a8abb7ad4d6d13e72abbcec3ad9f0690369cda670bb43a353c847cdae36a494614e4d6c8023f05362365835207fecfb51b53a47464ccdd2aae0b0aa106ecf33c370ff111ca1710f3b3293c33ce83a9dc8d7f38b549334ebefa4877dc97f7cee578092c1b4faca8932338495805f177b4f1d2c40cf61cd4c5e7e3f5e06d4ec444bdfaec351a98a4ca21ac4194695710eebe0fcb6291aaaeae00d1768186be6f34815047c2e3b9abae599194c6621fe48f25bd2c9d7e5366ebe0360d547543fb96c2680c9fa07d3470efc9b6dcfe2c29c2f4cd78cd846615654e6180cbebb1864f1f60113cf934cde3f2e2551da8214fb664d2900e845e28e9d67fa49f98417674b6527b96959d9c4ba5631c471454b21d598686b2d0407d2927590b27ec88beb57e96065133517e2cd6300f63495ab509070d41dcef79d8a97329a469bfc25cdd2aeee30e24ee4dcff53238717309036bfb869c933a1fd93cb49cf4dcf0e1e464db639ef6ba38ffcc157887d1f2beda59896d79b81e86bdb76b86ae7dae3b12a910b875ba10eef53360988110cbaf0319d0fb03ef2e578143d6c29974b797b4605475020033e46abbd89aaa22d232f65aac96240a6aabdc829bcee4e8167ba70207cd7017645580e06b23391c9b12d3917a8996cd020576e013930038a046a155cd7196e981adcb81d9e623224fd850e6a8339494db256a51740f360966f4c4712981827c7b50780ad356d6df0ee1a1a87eb92c601d1e1090aaa82a0b70bc22fefdd92a80175a47cf7310688a1447ca212ebe508496d854a8886a0d3e518dab2ef7331ec191c29873d5ea9bb36afe05df3705c329b9341c8098a186b9d619c0827104a21084d72b9a4126e51d3c3fd273c127c06366e770f47a4a8fdb9b19b38ca4762ebca8970c819d1f8f3437e4adf64774081db8b3c1e9ebc1ef26b60cd48ba1e56c6eb9055ff03e8751a8701bc6a43e7733eac5a2cffe3824dbf37726178496da00c5235fa1ae27201037aac3548552263e73b342f6eb34a709d5e1f6e1c8f3afbd1e84c4acfced9349978029f677704340bd60a6cdfa7053715c5879d0896af55b36f364f7e244be3359e766d13ba5bebfe9b6ffd9cc12f9a0d6d0c42b851ab735170b97f9ddc1f68acde38c6a542b19ee711d7de94aa003ad27cf7d8b3af9644109b8fda4c21dba6f595ff53ef494bb973780481aa12ade54defcdee97e55c094eb0c9d80d526bb52bf2bf06345091d730ee7aeaeeae7e1e543bd6524081466347b08ea98bd7cf9a26b0989358f520be685e2e93df711ee9a75183bd7b596b0ddf85956197efc9c04122fc80374fc9abb8f96f734feb1c9e05c73c1612127646ee8c6fe4e6c799e2a695161353f8195222675d9896c9dd00d09e738da2a085caa856d5aa52cf047dc38f4f0c95dcd721931ec4e56d98b02c6e1940e78d050596f603ab22c0ce19d015c55cf1a6a9b3c7848cf17b63bd8c1f4bfb438af47d15a3f35785acdc0d771c0bc7ee28b1d6df80040962253ffb3e7a4669b63b2b6f2f7c4a26b13a4dfb30fee23dca204449022227fd81099e3bc70a489809301cce27015e6c33a9dc5678a1f393bdf9f2933db396ee68cf38b3d5714cd39c45b37dac783f14dff0f2bc54adcc546d617bb631aba6b787743e1007c561476cc4e9f735d4af50c031edc5078bc498eae92cd40449145158b9eef94d6ff93eb299ebdb35877341f67ba002c458b5b129466b6382691f55c181f927ba57e910707355210e546c01e8fa93510bc523787b34b65ac0a63a406b1b2feeef7880721c5fcecacbcee3574ea1eab81e10a87cfe1639b156cf40c9815cd71eb0abdfe7739151d960d7b398ca821931a582641ef074bbe961cc7ad07da493b57be7619736b2904c8054c44739090e72ee34be5116277e24d00a86087adadae8449394c4d743b459f38de05cebf0c0c9db6d1925c30bbf95a9d09225560d9c31cb8524f014522abdd64ff6b6c226542e597f8767fc2b266a4d13f4965d920b75b7bbe29b23a5f17268e5149a202c8800f1baa96feeaf186d0ab4390e4bbc97e5c6ac3a4fffe587dca6f56aaa6928db30e8675b03e238872693bf3899ba6da8ca1967df35968e0f2373e19c39b6fb8d0c946fa9fbd172db13f4f90ee9d68850fc8797e7a582931ab4c5ec628d285dc06457bdea10318110e88200445eb794d81374fdf79060c97400770468fc283ca4ed7d3b891281015ba2c3a45ce76463c9cd83324367ac70e36a52ef4ed6ec2d7aa14a5e317ca3b00d99dd6914afe0eb956414937f093549f18598f21560a75c23a7178ae6c4ece7954399ace62ff51b22933c10228d9b32da1a2352283953c731577f1d384d53d9f92b3e85229d33356baa62b813e37f509d1127959c605b0dc4eaa121dc243052144151b6e6225abee6c8be9d277546daf3bc8a8dd7ca442fff8ef355e2a6e7a1fb78124b4e4d0e9ea35a5dfc4824a633eaa405bb13044875c912730e6887e647433cc82459f41b03281fcc627b640d73aa04ba5b46e15892fbde12217fbe835df90ff3a32be3355e993207f82c1c114cd0bc978a161529c5043137787d4b7da193ff87b6eba2b55e1e32e31423e936af5519e7f07a5ffd77ad31cc8b10411ce0bf92a54cc2652e9f410a35a18aa299babefc14613a3f107fbca52c6a76c8be54c4e25b9d7069fca4a7bbd2fea6a01d1cb0ed2f8461559d164c5b9b5ad733fc0a7dbe6778d8a2ebac5eee54ab23f7f0db36b614a3adca4372c08e4c68d9a1ec7b5602572558c9b9de9bd96f0552c5bdfdb8103c83cabaa467e433dfccd83d053ce6ff42d818a4eec2cd89bd57fd4913fe9fc83fdd1b6f90ca244f5062a556e3f37da13b6d396edfe28a1a1722127beb7e10b229649b7ae6b6d7e502e86633882709f09e2d4250efbe4fb42a03e765dccd06094ae7003762e9620c4113d8725522a86847254bac28913d397a8f1f03e2572b0a3dce8703a2ef3b5be8beb930c4266070226b2f83fcdda6b0ba5b31b062f8d7178f12140aacf24c297e51d20f4ad8d08b62164c76a96f3b0a2c3089b057d6820769ff68505acf3a6d0514a16ad91bd43e5a11c312c04e1e11ca2a7494ffc5dd3754afeab1035b2809ede17d0fc4c35296ef70377a91283a17371e4c9c308cc9f130236c8fa647085f14ad0a96016a1fb6cc211b3ca3885cb83f791170767c39e48b5a3ee6f308aceb90a1b4b338140e81e258083a098c1a13352361ddb735191a72cc05ce6dd42eec4589e176dd5330fc140e750b4fe1ebc5b5a7b355e91a519b90865d3aad1fbb34db8c410011122195205e92e58858c8670c4bd75cc9865e756c53163ac70d5863b85dc85c6e9a2385714f7635add098d3a80203fa047d0d5b0f360ca89da93a2f42c8a46585c5eca73e145364327649c97f20bb3d5fe40fec7bdb0be5223b535e1284da0794665663027f7f6400a270b9e0e5d52311b02f8aaa941efd44f7d119d9183cdd0231e27a6cc1dd0879facfae89e45ffa70b64615438aaa8085c2e8d2afe9d6f775fa3ea4d5c6c4accbbd326cd038072b15244d8f2b41ffa025306b675a88d473df8c020a2636a490c58590558aa2358fb03cd53afdc9df51ad5c9fb51e39d4d6dbc25dcc4b46e0a67f3beee0816a078db00c20f64c04eb2a88088b83e4a376b9b693a2633297d309b63d230d464bd35f07897a746917d36598c2b8e8de1df4999209ed2a3a9937b38b24ba52d9a24598b248f55e2e5b4d9bb69dc44a704cb6a92ef5e0399e90528c377e45ff6fa5ec0837414ee335437e12f84cdf879a90686feafbbcebda632d85ef11b5a4505fd6e21333f9bcf9dfb55a4a30d5bf3d9540578b569bc7c077737faaaf622990a21c1c5589f8d5e574ac1188705d10c75841b3e9a8beb8227c68f27b454ea4b3385b780699b68a40f445f89a83a228f5161875ea1e709c24087f541894e8f70e5996ec38ad7ba9407b6633a9978042731cfb9bad3b4b3f4d2812a7ef205b74c3556e6d2e5f5ece6916c9de230c5cb5706ddef4de0d7d18c7ce71f198f8d070482e89c77c82ef50a20e0db637f91a2249cd707e18bb4ef7630a61441f4ae05788d773eb7d55099e07000783dcc6663ceaa24a16a4c0ebfd9995702e45d9504d885ff599848a731a91eb1c4728bb824e6f15201d1b21351b2cbdac2eecae29acb5e04b7da20bbc6d6fb0a61112b742452c17846ed0961ecff2d0507b724a0860fc5d11a1866a5c1a2a2c5372304c7c2d161b14bec99cea6cf4ecae8340ca26611439b6e6cd4d340f70b67fdd78b30af2b87dc080faee824f9e3735aca389ddab03238a51693dcb26198a6281a6ef3d8350052ed549509b4cb8ef11fc776fe0cb2c78dc7683c321f233ef5a53c65a54eafae4133c020b181195dafc7b9a790c2cca1b9c6482a0d9d5cababab85c184490c11504b8221f3e4b55f9aaf062b3315a8cc6642983b4898f64b523166dd766e5fa1309a0ba4d5b1ba4b1c259a52bd8c6eb2bf9854ce6937106b3848d8d776bbd60ffb1801d97576c71fdd5901fb5af0f48bc97755052f498d30aa03bc46e0c8e81c582c8c1dc93209cfe067372472af83fd74d42731eed17ceb0e9ae7de0cba8698eea619416b32b44a1dcda5c0f36ae46fec7704027f08532bc4da5fa9ce003ae93867be82fa5b7fe3869b6bee779ad6ec8507f6ac6488926de9010ed72f9329e1573cf42eb720ce2c55502be1ba15c8510d863e2cdf1b95c111002cfaed922424b99b67e1b8f3fa215580b9b6a85724bf6045924af3e7a1ebd18f233439886ce60d44a2732f95f67a1919aa1751b37378eb64485cfbf6214f70374d88480d3ae7ae39d0560f31fd23e0de2512c2c468114b7403077fad700f59f7a9d932b4cd1a3468bd8bf97741ce528f2310a426f9f344ac9dba51132163d4065a29082e68a822241110ec7053eacbed56cc8a85c885efda8e316a0e31cebd767a1150b6bbdcc8ff400750c9bada2066eb1fd9753b61aa3eeaed879b6c1b99627678042146395dfb022c55fc072f7eb27bf607a69acf4d58f3c09eceeab4ce05a9d799f3725b8f3a5b7425a208b4256bdfa64ca3cf16c7c09eea0ab3c7af9db178b1d6ba879dbd624b1a796ceab66f98e632208a80d5decd66f7b7e234ec85b842d496a23285707ebb6cffcd0ab479555e1298b72432aad10d708ff5ad575a9917b0e251ce5dbad4f9b31e43e953911d747e20cea7455a5dff4beb57b8a1a3f63a7256f62fe7b777c34c19a985a25e2837eb3984449e79beb013a41e4aee965223c925e59b6357df5d8dbce34f012dfe75f87fffd8648bda66e01fca9983cd0f38971dd9b79eda3c253732d8b786e5e094c7da47f57e2b72b3cd3c93140877ddbc99e7837c3959d9bdc2595f0b77062802c071c317953a17e293d72fdf925d5cd442592d8cb7412390c428df0bfb3693ad6ae6ce7bcf69c0d56798e20cf8e95df8be95165baea88c73c62811d41f4ea19dbd16f74729a428b465c255ddc56d03e543d5af4923925041222df388bd882139c47fa5ed4736f0eee2b74c5e7986995e809caafd761d7c39302b215024dd66f7ec060a78e4f77ecfad22eddc54c6a16753a37f3550d920c140c2c4ef42d4a5cce8a1889f4ad9d30925d6791731d4f36d87719944981028c6cde5a0876c316b85d3c7f1daa223ee6c0ad5d8dc60f203a7a3dd35ca52cf3efb6c37751db6f37854436aedea3aabbaedf4949aee82b7984d354a5d7f9b0daa37cd62be4f9431cc75be154a1d4a538b780e28a5549a32ffab9eb4ebf008a331c4f917c16f95d7efac6e633e4b993c0b8607888ca43801d6cfacddcb11bbdf33419243011299021426844cdcb4bbe936655dd342e12eb339c0b508053bd875b36fe494a7f09cad5c9183000478d4bf5639c0b0b04c04c1b003903f993be019e86384999c7a7f9f203a6e31db6cadadf4acf80c3a20e400d7fa596cb6dda90447fe8d721405f8adb5ebbe80da39124a137ef10844ac2e488cd1f6f9a1616b10f08c444ab513f6a6f85c9c23e68ef6ce3efe9078d7830e1a3caafe73b54c17e5aa0a6778c420fc9b26ca3aa6106bdf6eadcdb3e7fb53fa2d7c66a6c60b2fa0b93dcabe532620fc137dbf97438f70c68e4923640b5d647244464e613f30bac374e9fa7fd9a996c10849887da6f952f7b4a09d0861265eed0e6646764d1fdddb532151f105b89b1eb160751465ba8e65a920a5393fb91fbcfa3da53c10fb4460e14c9cb0c08da1bb40298c6dda9521572f0e1d1e1c1e2b05e99a4e0425c72624e538553e20c8ec66bf2f06ab84aceb84875f8b7a13020e144fe4c1f95e09c7240a8191551fc17ca49873709760cf8bc18ad6bf613cf2260f14c60f262b917969ad08267ddc0eebab180538e79257d33a79a48746ecad0799c327af213187e4d189779ca117470d2d7a3b7163936bcf6e6c3e8ce6377ed696b017fbb548d8c464f760aceb231afc54fcbbdf77577294e66b1a82e9722942f677c0c39a3c974509925b183752b7f74c824c48d52b6c26ab11e6bac3cf4407086e703fb84efce4d13b26a64c2fe015c664f77845573b7cd91f3d4deec393d224005d56f47b9b428e09deff4fc842a30bf60bf8e2d16d9ccc72791f42576b025f0ff568eed1c40857e8ef4d55a1e669ce8ba0ad7674774c15e59e802e197ce7f1f0a9402838cda76888b6de83cb2ff6aa43354e50a38dea12ae84593e6e28fe388b495eda62d21850902dae53bfe3b666c57d9dd75399fa64ba3e22233c05bd85dccb6cce610f3e52c2cd8826199f00f6e7ea9e6c4dbc13d8d49eb3b0aefecc094c94fcbd2e554ba41f2143efaaf7f2bb33f3cfbaea76ca696312122e46a80d8f2a42c09e89454aeacbdf30cbb1e5ea4d0eac1a8d8a8cd1cc5d71012f7c0b2c0ef974a71cf15b6675bc62302bf8f4e6671ef019e5fbce26a5c73cfff307f40e1a7980cc4abf3de5aec3cc86100252934cca592620a87f3cb2c7531dd2adb42a5c6ca5062d5c8505167baf4bc1194068f8a12c6f0a60c4831fae4208a2c3e8f0c5b847bd6d94196a613d6101cf9502231cd05dbbfab5812185cdc37abd51407c26a766ace8c46dbc43d287ab0f178e208dd3975853bea23223bf742c49388d42cfff2e7177d28e260cf8378cbad06a75c68e9df0ea6479333f35bb397820ac12047e9394382e89644c51433c921b4bf48e4528dc47f175658402bc3b26c0a553a5a615d6f25970af7debf14b717831479e399a25d88280a2bc9db5693cd1ce74332357af2c2237c6ec71557990cf984b3c76971cfa9919beaaece107140e912c54272fb710e9b81c7e37efd27d4099f15d1ac28d3b69325e40cba3d4a3a19ded3fd2e31dee35fa2c87517f118b8f587fbac4f772092c641183dc1e6d2296de8f9a8736af014ff4bddb1527172af22e564eaeb113534302a9b7c0ea3672d8bbf53f12ad4eb8a4153b7e289ca91a66298d10209dbb47dae92718079103eb5cce02eb53e208b4d3902cefc9f2780f5e85cdd00754dadeaf9df18275c8703a602ef68827b521063381087213eb3b63a77906db67ca0fa797376650e9fa1e66f7802d7529a154de8ba28d7100cdc427b01830401640c63176486803b593a7ca2e95d98cd9b8c3a7f50800de9cf10e1303765e971cab953737ee9457766dc8c98e694fdce30bdf0abec527c21813a065e0fe5f2ad4ff4030bb1a6ef485921cfbac8f109ef58b2d284e97c9872e0606c5319e78a0c8eb2f675b19172b604cfe52f70ddf3a3aa323d1f0438b6475ba88559ad0f26db4f83c318728331d2c0d0f095ec078a498d5e082a34a008e7a47ff515d4d7e88f4270dfb66bf45d013ea6019e1f29ada4893d213aba1fb48c863c5be505e1ab19e29a81bfb9eebe281ac778b41d53019964cf0c8f735a6fc634caf8ce4940dd767ac860a14915b4a4ead0a9d5777742bc2588d92c1a4b0cdfb9bd12e1faf9c3068be90fe3ad020233901a1bbc29f952773838560f78c5dcc6eff2d914aca5cdf0d336444ec1cca5656dad7e2833326098041b28becfa9a6b3c9c9e99191630e885b68cef7dc003db52a670831e20f106e8090a6c942eb6b30eaaeb9ad0f2212d2d4c5fb53f05a1df46968303b8acf55a92b4bb33d4cec275d9ded49f53d76e813dde1d13d861372a85316a2c8f5c791a8a0eb2e04e044a4b35265c7a09a7f3266c05813f8d4162490d1d47c55d3a708120d36001572fabd8c2040043de8de891e086787ed11d7e3118432b81248501c611d2f91c63967a0ff48f96d765449f43c41dc70c2eda1e03796c04aa47b1dd7c64905bd036124b73a1a01942f034a2816705a20cec24a079d0e0e5889797419f8857ce0caafe084fe7efef64f02aeb1a0fcb1bbfb9785e5cc2173fd6bea4a6868dc4970b01b3991e4630360a1a68aa26781203857e92328f8b2732fbfc2892e5a9384ecbd09917b6f99524a017606c6069f07301ab087ed0b3d8c46c71c06fb5dd8af9922ab4648fb2c0c464545a689f0b6e73cee7b37f76eebf6411d2deebd754792adf73850476b2bf2afcc3db3bec592d2ffb503ed64dd386e999979b9df4dcc31eb5e72b3e3e4b6bcedca5d76264f8ad7e2b28cf7babbdb84ca7d3310ae1c87f35c50c7bcf541ff481abf5e823a80d0fa7ddff77d6394202b2716bd1e7ca06e105e0fbefe0b9d66d8fc8d38ca7af3deac7d5a149a821eb984b8c7d98ad439e158cbd97e07f79bc838af818cae55192152570dc41bdc01ce03794e4fe388b38ed1b709698b2042c7663c6fa1bc234884116684b379a8283bd6e2eb15b6de157eebfb40d60ec1016bd6aca9df4356a18ec140e77793e3faa863fe43ce718f21a1a1203ed4c3879b99c160b01b1572daa5a66da0db2d116159a8382e95081d5be25f5187c728c57106b50f6f36e2bc7931c88af66e906f06acfe2c8ddf95f002b8f274c1c2dd19e1ee06ea60673292f1bdc10f073fe3c759c1dfe620dc209c35cfab47a4c609c75ac529ea5e46b8cf20ce7b2cea046de57ec7564eac57b5da85a390da79ce6b50ab5d38a4a96a10226d354774258ee3e277137ec76c1e66f36df3b2b109b7a76108641da72b1c259871c768a7fa6f22344f7f10ebe78f3b25c214833a26d475b0eeb8eb1e369bb339e7d2d2d2d24e69d0e0557bad321fe9139c68121284d5faa2edd71be2faeffb8ffce77b90e82988ffb87ec68ed683398b92415d19f7ca674b73893a42e0f731336f9be46dacd55d21495c24240297f6dbdbdbdb3b7e902b9811d1d155ced1ffff1191d11591d111d1118d2b222b23ab23242ba2abffabbfba6a6af567b5becdbdbf90ff74ef2f9d26cf28deebdedeebeeee2ed4834aa8c790d090081d731ad5ddbdddbdfdfd3bce7b73e2511775ea15cda9fcbf8d5f7120a11b55e576524a29e5a6c43a956ce2254c78093731efaee4f52e2ec5853ee552de45caa7a438eaf0e8ca75abbeb436fa39b19f78894f6dbc2ec5719ce4bc4bc7fab940718182e202d53e7e2309da715f4f61bed257bafb4a3ff5d6577ab7aff4e852cea5a7b47371a9daef5cfae98979093bb804a8b31fea2c8b65ebd741e9b3715f7a72cbb1c96df36df3ddb027078e179879977777993f6e4de16f3b96cbd97706008202712c5227974b8c798cfb421dcec7d61bc12ac76df5852e1708be5cf45f0f12515104855cffbd055e50d5ffdbda2190bdfa00ac8e44d508567d3a4febbfb025c63a26c17069b2f691f102b8f77751d631e9524a96df8345dcb7604644232f77e0bd371ac1aa7f91ffe621b77307fedcc1b666cd237f630be6e8a494524a29e54c4a8ee38d67409c434ac9cc2ca54b295d82e1eec8d9aea71bb57778f5df9ddee716c0b5fbdd9ded8dcaeda2cc9dfd061054b2dcb93d3467b3d96ce5dcf9a3632c472661c666aaa4ff8edcf9bb33da34d55e1b26364c5d68b3c48689894df75db7dc87a92b72d5d77eb67af06b34ae13bb8fdb3eb146db7e47095de7e96c986c98fa6d96b44fd77e1b26edc33d94f378d0e07fcfedf7180079691d03deaf8d5e9b250c6645aeea585bcd5f1b26ab662bae623055555673bbadb2b26152c554bbbbd4fee72aae62ae6271a45572da34b18e903110bd632bf752284804111aa0f4b4d980c93eeb9352e729b57989eb00d4d0a11fdcdcdc1d827d399f96fce8ad92b40db776770f394fe380c201f918faf1a3bd7d0ef5d00fdf6d877eac94de54f287aaaaaab68a2e7933786b02ba4b4421b50498244b44b1c493845aaf4381a5b5742cc04bce2354c4799a4a0f5108159d0974db0bd98488cf494bebbed3d9664645384989938894ba93b6efcda527291d2529b54f7f23b50f735292f75c62ee095bff35eb6b75c3d66f61eb39dc9698c35b16b78502b87f76ace7fc5100cd975efed6221dd67ad0628eb5d1d3c2fe30c08789238ea8e35a8d33080630604e3a6f4441f7d9a348d81f44cb85c8d7776eef4a4d79b7b856f388d971bbbbbb1b14192ccb56e8a945fc2c1652d75638bba05c59217011cb4d8787fff63bfc37f14be0ba7d8be5e489b2f6d39eee39668e7997777799d959dd7d315708e7dd7b55dde7362d74dbe64686762fb9d9719213e3ecb22ad589f540cd12c511c963dc0e94fbc989cde3ef5372322b590fc7a26cb63377776eb9979739e6ee2198a8edde1d7925d5e6bc59adefffd13e45435e0ffe102a3d5eaf44e442eb01abbeb8a9d1ec0d2f5147c8f53a3dc0e787f5ae580436570fc76710f6bfd043d6ef58ab9b8f1f2404394fbf2b5c5f5a2bdcba81e1d2380c8184f56cdae250f71c9d1db7df064d7cb0e14c165b48e0e9f06f875f980026ba28740143112c44b658d17ea491210a244e50c1428ab6bbbf3b2b16c946e06dfdf96744421d5f013150231288c410c8fa5550f0a32cca62ef14e6d36538509721e054ff8fe61dc3f232ffa9c1b0c4952f2be06206633cd1e1b483982564b0c882865653a18a2f4fb0e041064fd4508226222f3c3922451854b419e5a7088d245ad338819600261a441762b6e080e50c184cd0988b344c38a104102b64c181c64ff9616728fdb9aa5123e66ddf7ae0aa2da41631ebbdfe9e7edf16bad5f1ab2d2b8f0c02f7db3196c8485db79caed20cfd3acafc67042838810aa8a622a0b8d0fa480bb8d0c10827507ca8422380132f0051e5042c663852c322832d686090064a6a0b5ab7b02db1de262c42c5c56158cf51fd7ddf5b3575233f75cb49df7fdffff8be0fcd4ec16654169b7317e8fbdfef0b53e78ffe048a5dd09738caea4f234bf94f6c7958cf2c66fd93047538d9bcc7415201a66a807a7dfc7ddf074ae0eb3854c16729a6627e96ea1fd7127701c3cf55e0547e36c3cf67180d3fab797ddff77d3bbe020942bfd7a1f4f59ea57f8a482b1ac8742153f9fda97f6066fc0a97f689ea9f22ae27a929aaf62940e57726da67a768a8a2f27b9583e177ab7e7ddff741d19daa21aa82ff1564a9b5c1ef74f3389628283a293ded46e4a9e6e167d5fe1677e1a98eb1c8524bf83d2f64fde7f1671336d1bef06babd562ed0f50982a4f5078028a48175aeb61fb53c3a2e5892b544e38796181d6faddd6cf6db5586a4a3e5556aa1c35fad3d26b8bb73b5c1b88104e87e33677777777afdc26a5949243e81a0a0f067bd9a572a1f8046842c7492985edc872d088f5cca2a4a6e6d756f8b382ca2fa14770c94356094a406ee309bc4ad9dcebbdb1ec96524a29d5c8624b3ce9aa8eb09a43b7d0f1cbc9c9a111eb01fa1ab31c75939aeaf2514f3ab2b31ef4ce7ad073c2601f4257c55d1b1c182d98923aae733f41959dc81b73d93d1776389a50e57bb79d2f27a5d34f203afc41e0da75864edc3327d203284924a49414f6b3a9e3caa9a0fdc736362908b10a44486d1a474971773717326da9b8ddca92e4a8e6cc82facb2072673b5277777372e5dc29a463dd494a3f545463ae6c6826b01e4c0007116e9aedcc646e1b9a202ba7f49d1cc599c9fcdcfd83a0e91fda37b6aae3a4b02db3937c93ce56a2575757bd396feedefdb3997298ba99e655fbdc52904bce5445d5239bc9a44b297b65cbf6ee656e666ea6f22ec6e872d8a0389396dd76767777e666e66626306a7b671f0005f1524aa95ca00f82a40771d36eee6eee4f06e62a66287a7aa89a28a52abb6c25c7706f5fdf755f77f75d1f327777676e666e9641c6d42d5f61dadddd999b999bc5f897deddcccdcccd4a5d0e5b0e1b949c9c28e666e6e628ff6226c70c6856038837de80663ccb0104d4fc838804a3a195ddddcd4ae29b8cf5b43337b73333333373f3f7ccdc67de2ceb61667ee666e666217677767c7e999b999ba19ab9a7999bff6689282c6f000ba827a530d8733f1537594a4a4a3a41842112a42c555e30959939acc011abd0dd7d3b1c6b9595462f9ccecccccc5eb8340a7b1a2f6d99e536039ab5ec6eef5eb940ebfcdcc44fed33c5dddd9bf9caecefe99939b8e1856ebf1c333333333333d32a951b0c0598e1967f179662f1144b318b99ac074d888efce7fb21b8c0b4502a95a5384b49b94230fcc239596a3d70d120436db8c5023d10f4c0f97d727aa0f716a0a2055e22fdef87bcde0543c3521cc4feb013555cc553e4aad70ff99efe10d7bfdee63dc926943af37bbcde254e80d2773d2854c4c81b112a62848a6fe4e5a22b240a127356622e43688151a92e859754ff25d63318a3b19fc53a62f91fb9b39ce52c3f2232ba22323a6239d191134919491d214931d1552c7615bbba32d3d566db9cf18de2a66fc7519ad6eac9c7faae8be2908feead1a5a1bfdcb8469a8aa4989a9a9a9a949a98ababbbbbb2b24a9c8900f1264b1a029dfb068f367f0c6dbc25148dd18673f676b759b7227168bc5aa96ccaaa9e289a2ac6f89e34769b38f2ae67e4355357c0cfda88afd686a6a6afa31e4a36ac8c78fa11fb2aa213a54d5d454d5545515f56406a7e22691f3152ecb1533504657b25c11b50fd7c9f302dafa11666333250ad1150765cc983ce3f5325e49aa06dfde0fec6703193fceea72fd06212c9c394fff109521ca9b1ba9c1cdb66d9bfb2671723c1cd2547342a4ade2c88e754c36a3fbcd689853c7bde2244cc4f302da12c79c3ac258221b9d214222c7eeaecf7aebadb72322a32b22a3a38de808e88ae8a80a8634447475c5af5c5df12baa9c76f5e01dd7c3711c3767cc0705fe31ffe997f5ca8de5ca1613ee9a767b3d90dfb4eeee0470de0e0e30a107c3190830d8149b2abe48b2aecc49be6c1f9fbc62c454af3fde9f3d62a93ff091a4f657c1576ea8e39734039719a254b0d2967d3622b5dddd7f47573faa4872c78aa9fccbe2ec41c5c5759e6f9e5e2c7e36f00517637e50a3c44c0e34116490020c9e9c5c184384d6dd09e12d6884bfe4c26f19946119ea5cf77d044f32b7cfbdb75dd7dd89e37e095cabfe5be8bf4ef3739a879f73243fed580f3925f0f085081b64a0449627de8a0c284c31b28408121affc73aea0af0882da4d3e34046163a7eed35b46d3ca1f259efcded37bcd0af1068e2c80a585600420b18224823a587291da86471c56374023fd1041a95222307a3055392d12691821924d5297ec00324af45ad47f2cacf7a8f7545b9b65aecbd7b21ccdfdfb13f45afde6cfd0c29d2563b9146c76037b2f4cf723a27e784102011f58220d094b1020a9a16a0b4900393941453b4feef8fcd1cbc0d8810657444924febb675635ffefdd83edd87790e9efc1cf187068df6019db675031441c7a7f265fc33fe8fb511bb321668095e8bbc56e76ddb37df6bb55ce1f69ef75f0886e128a4ee17b63644eafaad19ce1008af59b3664d1d6b3b1dc3d1847e182cb268ea210c2d5b90d0d806344d5e70e5e58a16a0a0f1efe46d89fbf847e0d1cbe258a08ec971dc823f591c377fe4388e9b1cab9bb3637120f8afdf401d2f8f2b70a47a0fba7a74ccfb97f7ae1f5f2fef5fe2f8d5f5bcfb7abdc4d1f5e07b2e7e90ff63ef85da07fcef5de02734f48922748cff8c0f24fe39619b6fe1c8bfa20e6ce44aa363fc3ffca7264586a51f5e4015059927b415e3258a20c8a4a08b2d41d0f885865e4c7df076677bfe20fe23dfdb429dfded972643eee55b60fe268a4358defe707025d603a48495a5de238e5279876c3f5f864358dfc9e71e03db4f2a3db69fa2cefe76e110f99ca8b3535362a254198105c90c34580c473811c55496a81a36c949de720b6f777eb2a0bf6458e92888d1a46f01f92e69cfdfefd109a30fdb96a580fe02a1448b105da6f8f2250bad5df01286852d56d8220634b4fe9d1cd2b5c1b28bc7bf3bbbcb01c93d776d34a089d7d33ef29b71fbd7d33e630ed9e21c620c949835582001838d160c41e405342f8471268c8ef1bb4f9ffdb0feed9f34785e2d567999fbf34f4a969b4b87476571bc409d5478511d7b4971cb6ddb36261cd74d281db08d4b8df23c5007ec0375c068c7c23147060d74a4513aa4ead60c10857654ddb1355597353b6e73b9d8b5325c634d87c78c6a535b1c3950abeafeb6ed6fe08e29ab368f95a3a3037774386e97ba3fbdf975c88271abd5dacdb5dcc148ebb2be1b26ca0277b0f65bddddddb52cbcd4f23e0ffcc0d981dc06822028416f061700aeb104d5c558cf00ced0b1a767264ed5fd761850314945ea6a05161fa05861460c1a922e5005981f946c40e108171afff24f0f8a97b5254fb43843268c24aa2fec059429767082a48b134dde4b4b2dcbd392192c6a564822a586e40a27a92d62c084164c30e1f18eae085042796e800a628a181958e9729454a5062952383c01066f1391ed7fe5d8fe6cdc921953a5091d9a7ce142191d4d5990542951418c20ba703acf3eb785b15026b4dc0d03f7961c6cebe742202600e169002eecc50644f0c3f8772af175abbc3efc5ceb6cc8957a3713c6a16652e69f302b74a4d5a351a37d3a07b6f3de0642d0ad11896246490a5f9cc810d1419a224ab64461815314099e92445d7183164c98a868d2e187309ea4989cf4f69649c117464ca1e0490d5d9ea460050baa389284122b767b9c2a5d1d21f960dd2a501b4183126084704a228ca9143ce143154638a912a6055778bb138018c48821c45598316ad4d440eb2d549254493ac207275a3fed87d552f0c518576bb48872a18b23be70a2a4431659ce3cc10fe35ffe6924db38e92648d92c003228a022713765b438524493224ba664d4d3121ec43c4963c57700013f8c7f8d02a0258c142a294d588185c65310d14107196e1023860f788f04172829446145ca1315377021a50b162c5439020a8d7ff927087a7bc5f840d5a62c59e2062d5fbc508184c62f043106922bae4c4186c64f74b1a4872d569044191a077420a287215cd04313332378dd401ff0d48255172546a831c2a40523a42873050e52a468698a8c918598334f10e1c50601c6952d479ac8600505bc827eeed25dc3c59d5814dd8979b7387906cc56fb3ce55cf6596aca3e6799edee9252dddd5d3064ea7e10333533e128fb41fc6769483dba59a7dbe7fb20f863fcf4841a961fbc3c89210517525c416315d668e1c40718be709ab2544b42010a199ac4acc0c8921d226298a1082d509e589841c50853154d46b48c792985c1a40417279eecc74a388a326286c9551229581ce550068a1454584a03f52f3069a18b28b640edd06450a024c91054656e48a28b24351c69c2821ec2c812e64bd31543249d01631f26822f42f0b0f4e504235fca487169b282253088a85014802c505145a001e2c9548d19b84085252e3481839a08745133450ba817c028e322d2650b31495ee02109c9db9d1b52e853d8cecf80b73bdd228d3acf972d49a89c547171a40c8dc348618111399051d3021affc754b03e6441424a150d2ee49006cb155140d952658c9125bb33fd0067c600428c92169840e28126b808838553920d6368cc636dcb115f5459192106aa0c6d9fa47ce143176028a939523bf2c58814667488a2660a087c214673b382b739e79ccf2cba5027ee079c92a8c9e2b6fd722a7fcf4fe37bfffd3c4f6c85e3c60a61a10ef7b272393424751d763bc9fdb6cfedae381a75dceeee6eb76d5be77289305fd1fbc0b592f56cdf77ad70e6748c5920277e40b62b8ecbbd64715dd775ddfc6eeb58531c856a2716ed17c9e7b871c551268ebb2f7138912bbf9617dd73674ef798b3c3fecdf9b27f766e658923eb65f040a728c59f322350fb6c536edb16823feb77f8d7ea9cf2b9ef6ab5b995a253eb5b22ac73b834deb6beca45f337ecde2bda9145832b771d0b74a4b0f6e11c1a53dc7eacd52eecc465fe183fe587455dada0440b2f62e800c50c3440260a891a94c240620cd7b1621caca1deb736f8773d0e8ca0523fb27938f042f74129b21ea8d78614747c56a8d3fdac21ee58b975415f62bb2d38d5c6c1843907b908f44154f7412c96330deee06954ff01721abc80c951fe63d79146e54dfcb5116b1e5e40b81dccdaaa31b9899db8e2071deb9f951381b06c6278b11a3bfe3dd6aa8f22a8cd108a582c166b6eb5eacfb933bb151878e26824abadefede9f75a40b87adf216f6fc7de09fa39727c3ccef13f719be7f33acf6bbdb3def33ccf33a1cef7c271639a0f84eb94eb846a200aa613d24c09838688da0c2c5cb1548507335167683c0417303b80015565cc0f566871a40a19682073048b9d408045d07f193dc810f6638b300f8b7a47fff61ef6cb20374e375228ffd651264324affddb07997256242fea9723b408ebd8263ee730a6b1b34edbc1b1c28e0c2251377421051a158cd927beec30a6ca1a29860043e397cd2467b5edf7e8d80e756cbfc7898ecbc450057969bb3a1368dac837ce00ed07edcbf667564c54a1a1d3cfb57f96a6d3e20d2ff667fbb117a868480fc012f9fec926fb407f7660bccca596048929c67c21c30a338c41e3c00b0c2a38a1050a0c5068fcb2a82bc87891821037d0f809258c40c19234505a20a1f1376f5b3c6e652c507e0eb61b08fcdb6fdcf672ebba35ddfc1dd299dbbe0bb76d73626db2eec4d1e4fb63dd4df41052eb21a4b6925ba2dbcbbaedcbae464ceee060429f99e592c7624fc7589664ec798e2b92dfcf8d30cad2c89652226dd2fbe5f6344bffe1e62bde7f826401f5c316458e58c1131aa350c4911c7870c116595841e3a7b01bbcddd9b6ffba3ecebf6d329c2f9bedff7e2c0787d2bae0440a1469b834c9c2a5823552699cc68c1185b6fffbb16d2d56e07e7580424340419e8321703be35e5c1407f6047d5e8bee7bae3008e883200ed4b11b080205f1ecb69f9fc85a66392b1c69e8a1bf0cb75f50023a3c44252a340414d48de1bdc422718bf8a558b4bd73918b5fc7645b282bf1605668cf2cc707e2a42c67f375b8dfbab1bef55ef87d32de1bb9e6fcfcdac7f594fecdd3df7a238e37efddc8e081be7ec11df4666c7923787f234e2aee8da820d90cc92b9511ee84b1cfc1019148aa5f77cacb14551cb9de6cf0a3f3b0dffee1e05daf136ef3b87e9b07268eb3e2fc06e1368f4bd4e161f32e7194f1fb337e411034b879ef46748523ad2efa74a76335e88f3b35d631c6619c671c9b1f6f5ec6dbfc5617cebb705ec6cf9811da841a843a2180bf0ffe3e0ef8f4bdfe70c21a3838e288e4b21d282f28819b1b1d1e383feebb1ee7b7d2d75397b81dcb11c76fa76bb86edef52008e2e0e0fc0eef71be566938ca4a5f37378f436f429b5f706b756d5c4f5dff0ac7a3eaea1e0ce7b7c29182f040eeb1c211492e272e8e16d0070a92cd26ac41229ec7157122d2c6ed76ee2292ac45dcbb3fc771727fecdf8ab697dbcbe7c4227f1edbff2616f5fbfbfb161b07b3425f06e4bd42da31df699fad3de04bfcb6822028e6746c0321e83873e6e751013e17debcbe7d3c195c28cef7b76470a1e0f7b7fef3e9e6013ece4d48c3d9b1d74b1cc16f89db311b719c558e00bef75e2a17e654cf1b5f620876b45ec73e0dc7a34adfe33e2e348013753d0d912475895bc4a247bfdfc2223a02158b582cd2e1f15b59dc8e7defbd0e4fdcca5578e158abde37a8c3a3ef51512784d6d3dfd17afab50a86a3aca07c815cab1c3215dcc1f76028c3f1a87eac6f85932580ba853b758452951df316d0af32ff993b950db39c6c5d8d36fdc748cd488d266b349d0970df7d0fce5f480ff99b28a4a1bcdf80887e6eb6473989be2c8aca0a4890ea3f9ad055174711d4ba6e72ca6240b777b1c8fff37fcff9b21591eb3372d5f1ef97bf5289929084152f447a28e2c51ada4e91840bcc34e1248c1c54a05dc089195018430542a4608596e5cb093a8c41c60b2824fedcef906d08951edbcb1fd23d063ab131b089e2d2a89a072f3d90a99dfc8d7b3f43b9f27b7b91fceebb0fe1bd7b2e44f2dac91a1d63b9d301276bb8585305c50a62a0c4b0a58c0d2e88c1520cb2c98e86db3fdcf981b6079dbfa8848ef7a31a2a44368380200123150000180c080503029168401c85a2b47d140010818c426c48164aa46116a3414a39030c01048008008800c8400dd20e70b7cac5c7e5b16ac6b9267016a00a732f52813eefd2ef8b07dc574cb4c391fa7652eb888e1dccee86410de60448850f8985175dd12e9b92d863c5d74038a3537bdc79bbdc00175d456b5c962c5c740fc256a98a8c15a78e5a0a6665e438152e18b110b22dfe9f7bdcc36c5e191552ba22a4f8e30abc8ccc2b929aa3a52e93c5221815b61968575457534155ce6b6986c7e24d483580e06dba886dae928b07cb85c73e17c351cb68c6bff58ab1b177fb2da9041292fee536f41b52e9192b80bd4ba93669322afb5f086f60bdc512aa568180445959940cbeac1d75f984b415832cb4a318b1a36a1b8950aa385262d5133d247f0978febc704a15d5e750a876941850159381d1d3efef4ad6a0d9b3aada1e61c42c6262b6a54c00bfd406bced2630a009b344d20ff4d1b76a5d7abd7c66746458c9da96985dc445f7c5705f19f2c8360586ad890bc0dc93caeb6ca77f42a1ac90502452da5d4a38acc5f32f344dabdd573a257235856139fc90c093ff93e04756c587d817c2fbf52ed2e082360f78336c6379cea95c1338d2e152cef68c081ca9a836cc405fd2dfb2eac3698ed46e448ba232c1aeb372fbb0945f2f3d672f768c49f90715b2abc4a69c621321689bfe6e368c200d6ce8aa0155ffa746137b99a6c356064c46b6d27a7bdf077bd86497bfaaca51adbcbca73713174fdaf03ffe8b164966916c5996cc68e5e5de61fc10237467f7276f4ad2aa7712a703253398c8d8bea52beac0a95ff9f6aab53e49b749453681a2b26f4831510b7104d376c1ce986383287d53ce7228877e5b20365516e53c1ddd56d9ee6e1b9c515276befaaad007a4395968d79b4f8b50cf2ad7c5d522cc45296baf521ec46059c7de6e47bc6fa10cc761e4495df9ae38a6ace7ce312455cdbce62abffc65433b4a28bdd87947bed0a59c53dd9851efdd1e1d2a334af18597d06e1359d32cdd11e5a3c2575f21344b824e0b11fc6cfa45f30a4625a79fd92f7afffba66267c2be148448f11ed9bd0d5095aa7d4f7984e6b306e603a7a6f8048a2ca83152e2eb403418384b089d62889bac320a9401efc6be5f7c693db4687f320ebc3eb40d0bcf5c56c0aca02ca19170e760af31d1d7458db45f22cd77d1d362d4fe459cacaa0a574cb71a82d982ef0174cfe9a43b0b8771947ac4614b9b79d41fb74b50a99fe86189269943ba98cc225de0cd912eca26df426ee1983e10f6cd831a22533f28f9f8249ae60e1cdc843f9252fd484ad406555ada5160c010acd2bba7d030dd784755ca7cf23eda3d704b70e438626cbfbad6b0d216fb5b3da91730bcd37b5d5509c6f209857ef1e3c65cb6e89596efa05633fb585646c731607a6ab107eca266df8e41e27fd113756d124f9984c973ce19247b35c204390d149b5f23b5731e5ae0352a8d466934d519ebe5fd2bdda131d8f7372dc352b6d2bd86d8ca154a2e065a63ca08b72c03a90bb83405ecf71d7b39b78a2b42f92741feec1aa467b597985e28fae05aa84ce1da125d0975a6fc941aa8a9edc4db05c9845655d79e5fbb5fb2ad13086d5d4d412d896e92daf3d735032223365175e7d369fef150c72482f1396ed8231eee73b0d1886d50c8ac8374d9c98e260d85268ab2fe0c5c30ad85d60591f44fbe1232f95308eef0e3882bb8b2926073bffafabc1ac482eb9ab5c44df81a1fd5c16fa649150dfb6e25e00c22d026e284aa7e0d847a4f5db78c0140819539403ce8045b472b61f50557cec9746fdda4b4bf67f09fb61b1f6de43955f3fe58217135a06022dea638442694237e270d3c35f2289f34db282f8a020faafb761e9c10e3717956677eb5ebc5c0d2aca1d100257a471d8ea3c3d2a4164433dc20086eabe5b7aaa751a032c0eacd0167555489c6ca510b8626d40a9a2c143f026de9fa1d71371dfb2ee113894558d828173e6e6fa117cde76fc845a887ea0305f9fe523fda27790da90daafaa911b0d43628bf0381963f446b2a09f21cf819c8c62b79784e4ccea26500c73617f3a2c585f3b52af09a28ae9b21ed24614c2c2093a0b31953cf8c06ab51c6d338bb70313e00a61597d9014f837e464f75efbae1a2167a58cf9f6a92eea369d46483d6fff3f547c611154a7efa8fd4c26a036524175692f533ce980a95b28bc6318d81311de5c116d7d590be9e3337ee3cd2715de86f8426c20b3abe31d5fb47935f2c1dd57a47ff197c0c88fb87340193d564997ebf892bde409615084d87bb88114daed9081e124f70bd316ad41782856e0de16a24296570d33fd016bfd23924cc1a31ffbc8c1f0cadd586ed1ae3e1b8cd7ea1b7bdceca7b886cc8f87fd4f8a9b79ea5d8098e6c5e8f8cae319d92c7ef6e5d9372ce86110f3c63e8a744f1059ab6354eb55cf9456aa01ced2e36303872b00eaa6559472f4f2a6412bb98b75561be11da102114990c1c59356de57ebb9966b22bdbd63ec618d816270de5dbc089a66a859ebf6a65fdac6460f70fc1c6dbdb3cebbc74b42eac7462f6b5ac79769db233923471134404189578cd762e53228d37c11f54e3a51eaf9ed584c7d0fab13e8362e60347544ade70ad32410597e6ad4cef6f9b2d6b9495b6bc51c5bc7d16c0755f0ecef11b5e5a83ae20f39a42f2c61457f8b66037b8695c74b1cb1061b454aa5d0c3f71d1e3d24524a06aad67afd4f1011ef831e7152a1a9342c20ce652fbc1d182d1dca6f6d120af82f115fafdaedad776abcc8e9ae7fdb3fe47778f838ff225166aeeb7b5cdece2b383542a4745e7d9985431270123aba27416bf0c68f4b017e5958cc9597f991f914307bae7624339e87d54d5052634743cee9475694a8b8230fca6b2ac5498c75cd07cf6d7a5e54c3ef528c4687c78dfcce05d0d64abeb4e7aa0b9d60e0c5af20c3b3fdd8be7a73d8cfba11259a6e8748d0333764c0fac2a8e1a7135abd16a4a8b652d10e52c52017fbe5727f86ed8c329f76458943dbc5c6fff8e85e008befc058ce8ebbd56774dd1b8368d11eb05b0b5f70ca0495117b9d34467812b92ba20edda4558ce6b06c94af168c816ae2554c426fe1b7aaa53a7b771a687d2da74351f76a2b712ca6a0065d6c6cbb0674b0b53628877da827c23bb3b48339123d715efc8b062262f76fa70d6d4744ddc82b7d50b3d527b4399d6bbe98689ea7133e2857dd6e97e80e6ab9ad27715e6a9f579d7ecbc848a5b4182d7a2f5aaba71bab1a914846c2ff1a831418b21a9a8e786a8d7e81fef410aeafef6769cde4e9b11b89a68c19c09dc25a1c4a98eb57ecae9addcc2313bcfa9f0dcbb5aef84780074ff76ae6e19a2a79eb75294463ade551610897dac7046a4e36905ae49d9f6d27160becafc1a957a2e2969121b5e4db194003dcbacae428ee4f1cea94768c566e2404ccd188e85f7c9037f71ad0590da8fb0839bbc6c385e77e930cbac9f0ecc026b6db8eb0860fd6ee07f18be63b9001f8e884f1448cded68309de0c507a631bdfa4875b305937b77524dce4b59dbaf827146f0f5b826fe07244a3f9df9e468e531b075c81cd95052d602a958911978c45dfb5d44455bbe02cd1507d49bbf280402e1539cd5ab958f3f006c6115a548d2ad9bc07431d2b518829531afa589f2bb05562e261250ac3432ff0b31db06fe40d4a7172b4383d17ab44f096a5bb6c5523ec5901e2af79a441bba5d4d78a3738c6ba447d60954e00c93ccda65199630675c03100f62ef9c3aa4fb75efff123c0d8194712d8e916d4b1b5367655180661b20770017ccb7658d65054fc6ca689663f19b6bb49ff363e0824db998db9407ecbd8280a710e6dc2efdb4d349dce54c7f36b0425f9b2d3e785e881e6b5007ac28ff51285646b1fa8d53beda19f562cb9a831f1ab567c9e683dec90551e0d0d512039705ab70f7951a15a388bcd552dd94c884ed3ac60bfab60231c6db1dca227d67a2d65624f4db647c2d871dcc6aff4c7a1d9bd71da2d48033dd614912f1a045acf97c6e667414ae7284d7ce5ba9e86965ba83cb25895638c8a56cf823c0581bcbaabea49b7ec5996e2ac9815c8e1a0cc7a8c03f554ec9b28c35697a8036cff7e24b874a973c7970fcc7cf2c0380c9f2be9e5c42a0934945eab2f4479d438c8cf2545b165afa1289943c05a2944d30e65100323ff7f2f355e25fdd2415c0b9a2a13a5e43f83d3302b0fde4d2de851d89e04daa38f4e3b8bc45cb486d1093ea4553bb1d1a7a839bb65dcd7490144120126a4f30f9cb3b270c8ec7aef71630a7138f856cfedf19780983ba585a8e813faa331c91e0adca3a68107d09383b8029684102dd96cae36adbe33af974a0872534088418f979bdecfabec46500ce62d10e50b16da148cf0d4d91220e78b77a5b3ba4e33eec261a8f4a009a1719e468bb4ae27b7ae758d8aa18c8eeb64d379191c50141b16aee47d5b6b7073da95ccda5532e2b6ca5c22c150da580b5a552ab2f7192213c531362e1c57ca6830754f95aea5343456e1f0d629360744917462057bf25b13ff1c404867941de5413dc8d1ec74bb6d152037dbeb07f7a3e0c6e1661edf102a8dbbc1fa28eac2c832f2539831485857be5ced2f6b768cb4e35c70a2553f934c084cedcfec1b396a8fa6d616a0e7360360e4bfdf7f814dc3cf99ebec478a180503098b9c2f6c9117bdff0431f29677db0377b13397b765565044f60da13883f59b15c37f856bd166e8bec06112e2fac46f6c81f89a666fe8835ecee5746950eabfff856c1f98b67ae7d76d0325c637c77f4aeb5078505c5be4e9035c725f64997187c3705e17058a9d4cb2b3f2a759d1e2920a1c6f1e15d052d1c40c25dff5b27198ea7948950f14e648634c7b714c26d0c4dd057091caaab282c1329b63f49d92dcd855ef60fdb4f90321feda8fa9969f5e709e1aabcbc1f898593f64334bb04bc712c55093f749d5df0f5028d0513704cb8091d5b70ff676384108decbf64824792299e97a71915438b889bfa0ed85ba558d9f8142f3dcd0b2506486ba83c8a7c288d2e49b63194ef7ee77f35efc44412c4ce451f29ef0f50c94b95ab1f62a2b4fa35a629a29e070d21b2f4812a7f6db8a1465731e62ccb589eb803b3df9b15f29d684e5cedcb48bec4701c320b776036bbcdbc02b22687bad9585995c396327c62c59968127d6d8b6ea01cb690ad9121842c105cb2747d016fb3c8af87369678bafc0411cdd6af9174153078417ca9ea4ca0fc8d59545d41cec6ccdda3a3a74578c63c192423e8543785c845f1184078685f09888889d7ef351ac70688e539f24bd570202d7fc48851b64e87844959f72b533188211ab6c4478b4a83f8e61c60e1d136f6631acd51c8734dccd221eea809bb3dace0aa92621aef8e459b76d2f2956c63719a60490bae9702f5be136b45e7a42e978cbad7d803a50d53ab66f030bf0903700eaf1c58ed2c7ef6912b0d12ff1b426a8a603dadd78518cd6ffed315171f2bcc054c7cd32f991fd1d8b4973ed1dbcb71992048a51d805c3a32415517c1e1f1c74b0ef3c15772850419ad3ed1f47c28cff7b3800d5799ae91468fa8905b4f4324a78f1a588eb182f3256b80cb92bffb8b8cdd3ade8df81dee1704f56096c765f9dad9c4e0bf5bd37524d71e12d3da133a93fee2064813a05429acc4324390eca194725c3a5e9fe16b3a0c4254c50a74b624c82bc6c944d5d2a13731041ab7e35115910c94658820fe6ab31c25973a6503cedda15710cec55506843213fd3e1f28b3342806dc42415401abd064dd01f6641b62473d60a91c846c39f42333d1560d662a84886a8655a34283ecd6018f106b5219590db645e4c682d694d87c5cf941ff6302cba872506715379c5ce4861dba3767ea247bc6d634ef416d65550c6cc0d90378706d7861a9b73829d7b1574665ef7600a757d2172aecaafc51ef78dddad6e5da2071b32b5f40396eba9ece6700e301d0d01641221746e8f334c6f253f8fc8c0b688cd7c5f73279d7cd22e05264ed424e443f0ceb1f4112fc8db91078ca37194b6224cbb849e38081d58bd221340e06d5912df301ebf093e3057b594477ae9751c4c61358bf526e3fa6126b95549f2d757cba9e257ff83fd9452ad0ae5d05ba2674881443d29bc5ded2070c60e6586e6bc2a7dc5ad437bcc191434eee60e93ad4251f5bafe090c3a1178e1f4f6b4b1368f331ec6cec8e7b6519f57c0f0a585f2e5ddb703fff10bc98a460f8853d08d2f8329cb845d8b9ee58e80f075d6009f9a1f7556522b4049878f52b7ebecaa1c74c1e199d46c91cd98c0f2733c2d6d30cc5713830f70017b77ebc3b078b2b1e53e98f1f157402301b9795d06085f7f77c876bc4316180f6a7189f4611669726b008ee84f197b5c71e7837e62e776e0d86e8999d0f8d3f97ecf91b9712d13a74d90a60eb713ea60a60743f600e2aca1172d0b2910e7091aa494e7ade4fdd6e62eea62576882a702be0b7812873381f9a7359d143bc91dc6ef1e95e89941e2356f1ccfc71c7d67a0b8609d9a247cbb4c1173debfe734b331ee66b5e8095f588dcc7494b61e8f5cfa47bf630cf2ecbc12e12cae4b944b25168214dc248912fde1b204b07c1d54cbfe01d303f5aa4c321cfeb98301334d1e5bedf12cb628f2fdcde27a6778d33f2709c66605bd070343ec047fef84018580692fd814b0c6765760e09f230303ee88996cfa8700a5dc61993e84d554272c676648355b946f3e3c6221213f65d54de6580bbe1163633ed82e20d845a8f90de17084bf1025141e4c0361a41ff0c9b7d463c6610738f2a9d8327dbfee74f2517da95309bf30f184b8e96ef7b835a6d9385d5c7176263a8c7a791d024d3817ac53578ece2d99ca449cad90696231d918d23822eb8310004e28d61eb2186168be09122f981ba491ae97536a7990e4a2c68ad9c9569144fbed18e41ff4fd625e298a4450dbbee6f342b6e9629d442c3214560fabb931cdc51e00f3ecd6ec8326b025439597d0ef4fa15f113af074d81496d96295ce9c6edcc251aeca9ed4e2077be0d215e2cf1370783f8c6edaf0652ff0efc9b7dbeb7e1312a780a35323f76478b676b626fa6f3302aba5222adacf41820f7f01c44e98d42a40ee12b52b475106948c14da5db3b3d591316b1963a4f1e75b00f8e28419263d7de38ca248cca1ee95d8b4775b459029589201a1bbe72402ea84ca1728b623732af6fe01fa0711abde6a650f912d5b0a871bb5f9376b74650937897c944bbc5e6b161ebd869c053a0043e81c755a9b317ddf2b9cb608b67aed16dfc508aa4e9d45e9f97d38c881d82e581534e6ddc6468f3220d75e10e7cfd0f428ca5f0a79ccc7229eac404dc3982eace869197e7540be81743bfc37881555c81e6a11591196a83e2c122d7d197dd0779a9775c45d15d79118c921171f27d4e35aa3333845a31149ca0eca5d11f2a22327863d922e53b3c20cd233fd18f558ca8b25304c4aa801728568d582fb511d6002c418878127010516c7eadc3b49d4e984a9b48557966ef8ef2046af07a7c725c431561812e02912cd09595d9eb11f827fcc0000ca1677fade4f04d8e98c3dc380c3cf32a86394cbed4b94618f6397062e9ef05878183046370fc757967dbc93593024095e2f25c933b0bed52be69cad5080bc2b194415dabd1ae60c5acb1878991f43c5b102c778e7ccb11b9bce5027c319f8851b8e5d7475d7c6ac90a29db7aa19c3efc13114296e3681e9d5a7f1f105caf2cd83ab360f0425520b729212f8c87d70d1c319662e3e74029f21671c6ec55794afbd1a7572cd07b1f7475ade1e927bc0cf402b9b3c09e6ad8b67677891a4533e136ed5303cef7c4a2b82ef00504215d66b1eded2b7365cd81a81a4cf3a7664222a7d51124000b781354d2c9c125c6a919c4ffbc6f0886d3e177327fdcaf59a1c8ecc9b6487f3c0612637b1db608552b169e36b171c09637dcf9729bfd1dc5608806d60a5fed581ef53967d759eaf4289e1779b1b2c111c41d2329dffb52ac6edc516f3af40a935c9fdaf121d8e3d283f6408927c6077ead2b261bb86547122ae558caf4be9575e2d28b35c4114bf8ebc3f9b9f90932f629a095a5989c00e65c3982cbeb1a9337802f4c5844e2990579fcee5224f506f7f02e042a9381a197da2a5799b54dc185d8e882c7a99ec919d0fb4a8b0ed999beba5860c2b335ed909b17b8fcea3fa0bc2278a30c1d96a04bda0d447d198e1a2fc10dd80d327f271564a3382a927bffd2ffae149a5a487dcf38ed3801568382db9867ee564d759abd61d774e77dc2bdd0b25599ec6332a52e53514ef62d304bbf7739d1e66d35f7bd62f444266e98ea5d42819b2d1701f32f138a1a8284c0841d7394d13fcfbd09702aac414c3b396935f8390ce1ed84c357f1820e9f3d7038c5ee8ab2f8367546bb5fc72e0574f43166a16237bda7d322e93fdcb76f995421cb90f8be3459849279e417b68b84bcb2ff2cad267f8dc55c53aae47f4fe0129de12b4e7aad63635d1413d4a121e2a73a2b00674a79a98145be392b625473c7aae2035340c6be23c8f2124e4919bc3c089d924e871fc2754a9abb505f982ff5c974e8a40993c0715f8f8393bfded8bd306640af082a495bef6d0a95e547fbe72ec21a09c60b7df5f1e20c19870337df580474c415b1859964a41d7e607f665c3a68f48a30f530aa06f60a0b32134770b7d95a98def19780656b97df90ee93e837455fb8d530e10632d0ec881a0a4ba143268e8161031a48adbede191824e0fc1676c45e3cd89f04d43b90b21594ec23315fce42d459077bcac9410b8b0a87e4f3399e0294d971a4f67102865f78575ead19425d0780d8651325028fdcc4ee812c9215f8b04868a0d79098d6f6bdb8990a7dec3e2d2416f86dd2b187aff013822effa1f577a041996946002895ffdb07eed1004f8ef247135d33e80794cf1763106c160b3e7411e023bd97ba12ae982c703868dea717ed0281ac8fba7a515fa9e8106450f41bda049d04779be995dfc9057425834bd71b8d15f7afcb47151b569fba9d5ead7f41003097b61ad7742590e4edb6a29f7aaa90f59f6bbdadfa4b74a9bcfcf19082eff6b209f8c7d28cd0a6ccaac2a8ac6915a382421365b642b4ccb53cb04838d8a2d8dfc20c573a56d14cdabfef4820515b830a6616cd29fdb65a711db1ee6710ed441b7cfd0987810d68f3760020fe7e009139ff19240b63c1515f84eeed439cdce057e077ec797a6673c4de376a70a61fe144a3188999f17812a803fdc009f544d7d8a43592bf643eddab61f9a586bca94102e146006b79b8f831856a1c46ddce831faa86210228ef717fdcf8e0693802a9c6eb49977018cb46e4b87cd33f7b740caa5811239b2e5087f20cb649ad30a909218b59d5d9b119e03515269f60ecba28fffef959959f40407b6a8d5a39c2e6875b80d00d85969ada0992ec76f459719e29e4f35e8a83d31409bd811fc9ececd13ee0a31e14535c3b2234d0743b3a331561f8d08a36e45ae81a804be4d75930df7373090744d6952f817146b7ba3a070c9f73baefc6c1d2110ef300529d771c9effff0b1b3b9b7390c1fde8c415d958469dd8d691aaa708dab674d960c88242e23ae9a5884449cb474c54d821ffbd8beba00614d9dfc1e05d2e40d3778b358eb05624ce8adc33a2235ce324503dc74d6bda9bc1ae5b0419639de6e69e86d1d076cd97be88c119e6eca22b4194a25b9c9602002a0d51013b4e64807ef2b90b3d80e84936888fdaeb28a07e8430a6fb97af3b10ea27456ab43c2321d5eb4668129ea7633ff827c4afab6b687e83e82cb361df559588fdecba713ba0a928b2806488641f5eaaa10bfc2ba139bdad94be64a837de738c3839ab14b0a906b67c95741a9ca1d9235d674edfe1d82f150ac0c775e38f53559a6ffdd4375865e47f8933a3fafa58b9e5726388507e21a52a85943e93e68c299d28cc484f07949ee2e06f7b38a8f976100ed65b3290825c1cd041415451dcf26178e3b51acc0bc147ad7a03e4b721bb1e2f47e5943a6ae25a5301c29f494d4ee3d691d0f7673db6235f58c85555f42cece7ed95a926e28c93b6e2524b851c515a11e432f1c4e30d223687a3ff3ef64c46222c5eb20f2a51dfcbc654ec7d7e7a24fd20ce8312429cc10e1fb05ad0fc319ef9afc48b63067c09d8974f0f0ac177088fbcf75092dc222370f2fad0f5fa94504eb69701fd91a0cd43ade34118931daa0da13ba5c05de9ae61165af698cae050011cfe0ef6dd31386d02258963d9e05dca44a765d66990b9f4020f1e63cc6e6b198c0c25f41e43bf99d9ec9e8b7e7353bda953b11de734c6938014d8aa9b9b43f581b2fb7508287f73551d0181a70313526b454a483fa5b1c4d89801b58c791821dfc5e61e6a9494f0fa4e5201b5f5dcd4fce114340ef2c4c31c655c3568d5a4d5560765d5c4c734f81d0f69c744683bb22f9043b12a14a7177dfddb4523f5aa189d43840e9ab39662e35eb6231728cc828374cb6506dcc01497347d7c792c4d17d8337b44661541b03054d002f91d35ae90d04cfbd56aacc9090ca19d597b97da773b9c114baf24ae96c8357b1edbe2a9f4b2a2d6fd0e105887ef6e04557a791ee4fc8dbef76de1a21e3f0d4079b195a33c1210734f04dcfb8d0977a4f02bb5fbc117d4f34a5ae03cc9fc6268aae26946ad51d38401a3c2c45c44219feacfacaea3372860968ec46efae4af8018e7b2417c59d79f62e37bdf2f234ba82b36c6ee974844eac9b3fe0a6c33c7294af51856a6e8b7d7589085dbf345714fcc70bff94300b2c90859270f58c6514f4c51bb630843a978aa7f311b4d007873099675fad1fc02d4d936b4fc5b8716e445ed42fddfe1202326e8809dd553d7945f10c26051660128a6b40be6b032efa012fba4b342eb384156ca83166105b17cab6d617965363321672a46593988864ac6a942d68a04e85a2aa71e8f4a0795609842868dfb97e21282d013445a27580df6e4514a419a8503d68cf466b00998d9abef06f6e742555d88eddb624e4dac7ddd15b8f2d7dd2ff20672d7c00c6956789bf07165d5a76981418775a1da5260b1f5c0be3a2da01a1aa942809beac2c06a7696bc10fb4f438002896b11660d2bff4882b92249bc88d9e012b2c726c972346b79374c79be54fb1da94d1f06f62989a2f22b6fd81f33c9e1877c49adc9f81056dbdc5793fb0a902caf055ea01004d3f563a122dedb44cba1de9577023da1d55456e8ca4a109b063739e9e2eb3ae16859f2b5ca95076c957dc356c94d87d82a4960ec07b6456785a55ca0faef5484be05d88a4a2446f4463c019030f1c2b9836bbc91954e1394cf405a423719600e197d62fc17da0732ee978f577257a0279c4be37e4d098a3c6f4f0bda14244935d709d2670aad028939d70c47fbba12ab0616b42b9d065274270fa225d8dcc671fcf08e80bdb0b548e4cda1f245f59df8d07ba5bb6b38e01a5e2b627b0437f0700cdb89d50b20bc2f3390d1b92dcf0c6bd7dbf2607f28840391d2a306b71bd42ea89b779baccfb93810fbfd7f19585722c613abfce35b4e3b557dee7b5f93c98cfbb6826b183cfa44fbd101bf0d8a563896355b652eff81e7aa2a811ee8de30fed9411b44b887f05a3e91633c29e29dc1cb9bf203c1a2372cef8baabbb98903ddc3c1c25a25c44ea1c2e6fe982ea1a324f0f22256200f5272823198f2ea1cf7378513ef16ac5a2f4ea7b28be02736c1820063071bbe8a109d5b98cf9d81b55ca83d4b45e7cfb194c5af2102103d1ac7113cea1fc6fc47906385d168f1abc346dba98c6d77bd12fbb151991c643ff235508abb4be8c74b91d3fc9f8692dddd72c30114d61e8273353ecaed08383a70dde745b14cf48ba29817b029f4e51cc8ca3aafdbe807a20319c4ee61d05805f6e14e09f1a1d765419f13d4a6a75093e7da94e364f124d534502c0893410b5852779c1c8163c1e2488c0529c7b6cdbdccdb490512f23436d1d8577ba1cb81ab47eb22fc46a69dabf3ae795e1fe4ef344c9bbb4fab17d8d730e59fbb31cb70eb2005ad64b79efb703f69d71a67d1cb63583f101d13aa1b4ac20849a44c663595dcd6877841a40e839705b5cb041c65cecf5222f543b9dbedd4568791535a5a6eccf7c245c706b42e7d2a3dc0396a739a45e870443c9ce0c6abaa52a960ce1598254ead37c6493d30abade5d9425ff810738443e9b5e623d3076ed4cde42ebb96f0af75626b87de20af1d8f59dd2176d4a8a5a752d0c5b4c17754bd7c8df0ff14f57a0c956ec3a54a20517e11ebbc6787d8cc00cf0fed904b25400cb35ef52535af4165fcb61d8aac8567ebdb8e26cc0c376bcf7ce9e1de7ddab3009251d966cf886f192dd229c39c8c669d781a41dea7123f93dae416a24d5bde950ac44d79ca171b5166754edbb9775cae3a605cbe5c4c6479b99fccc5dbe265065c94e1356dfc97f96c718dd584bb433b78a4ee5bfd53e072baeedca7a7b7e858739aef7d5eb0a758f0c5351628ae11235c7023cc5e30567f454bfa35390ea3386833d6a6814f05bb4f02259751ae01252eba0b41b7f6f5ddac1266ef6a4c947e73766506d8ceaf34edeff75353800b071f1afe84aa90f2c2328076e763b5199ed6d44c10e5fc03e094995122257f9f5206d08f81e06b0072358b882dfe958b59aed0582ebbc793cd95983843eda693c7fe37e4037acf3d8544f02c9743f36796e97191d86f0f6b2fdc627311bfb85b62922c6ea815e59a14fcc151fe03f4724e96758902f47670703a651885590b8fe616fbd355a5cd306beaf183214f6170255a1921713541eb436b11514531640d1920bfcee682d6fdc1d681a72e83d2d203b787b16c209cc10ef7ed7663af9315536e0859b0816cd0f9be2f0940f2a5d57bacf7d75505316332aae896f826a10646c6eaad36e6af7f70e548d1fd4944dd6fa77d9c618e6396ed23f59de5bb2805120a0f87907335b5e58674e56e50dd7a7d6688160e2177498f2cf189388566b9ddfc2ec31ea84b612a00e24ddb2c3761e8e216ee72657e6525f88cdfd0b284e9f9b05ae832f8fb4532861b486229d84908dfef4664499692a720517f21b2a91f0f6501442f7224849a9603960f0969f7645267056dcd1ce74172a6b60999bda6cb22383e65ab2ab22b804c1833a89147229b879754094f09d7dd3a88581b4e6d26505627f3356391db00b73ab49ea7722fb8800203f497c1fe9e4211eaaaa0bf5ed88943328ea4a4ecb08ffa77c708016407e8f185283d4b2751dade4d08b6b9943786abb2d1e801d4a0fa851d74c0b87719cf6dc3602e20d2b469776a33fabbdb1368c431596bf8a08ad0c4926c1407bb6146d7cbc908f2099dc9d40d009f982f81a04bc781facd793265a92e8bf95313cc39dd438302621b0a2436ca1ee9cab2d4e36bd8520a13bf0fab1698b29ca1fa0dc031274c9ffb3e1f8302668dac477cc59850ae1828d2be1afd13fda4432c353fc6e189d02bec1d948cba98a391025f9523e269c837ab48ae97c356ac809c41e6400615d778918152da96745cde8d81940817918378a7006653c0bca82d948c0218434aee5f9716da8ff8c3e290681473dc6059c1a485b5b3d08a7a87076aba8365d6ed068e29a761d1380a26695a7b8706994e79e20b32e2f5d1a0fcf71fa2a7d29f3a4a7d27f509d47bb63a8e8eb3f57c69e00f4c47941b17d4483accec9c0fbcb9bee1c860cff582af199587c7b6053dea41799a19e82a4beaf00612b09320a66660776a861613d120a7079b3315737c94dd6b99216dd2c8cc42cd7d3008a2a27ecb0bf2c36c6724e4e0b29a89d1d6c228771c132a94b1bc30e8d585533871d3cba38c1b31639969e584455b5e746409b99b251919ff52380f62939a55d272fee34079ee7fa42fe6bf1313b31853dc0d56747a0b35bd2376880f36a710441b9d0ee1f51b119ca78556b1dbd0c3e1c86be2bf464577d0ecb8294405e9fca377eac589c89b874611415a8a97052b1a2dd0caa360cb2f818ed9749b8469c0d3a78e0d963fea781b8462e51f88de4cd79017268a8e1f63b650e6e262c34727a767a036a995b7adbacaafbf671371b7487c6c09904b52541daad10e43c9a973242dd5205120a07dc509d72d254a42728b0a6621e364c22abb1af64711677e9c51a8b999a4cf4a90419c8a0e5381f9b25be886aa7cdd325313006cb28b78b5fcb879119ccefe5ec75ea80da6f20403d17850fbc2c42e1183b008ad7a39a792c7c852d911f88560b254e0b377bf0eff5c2ab29e567fba6ce5bb2430ba68b23bc63879d649c67677fd866939e6812e8fb96a23a6e293a9f070836b7264f6e0fd746326af849fad800067eb378aadb8a0ad800f8224e7267a5043e6d931126a2de27be6421830d06c4fdf70cd6b6dca018f2b8310b5279d2bff58e320827205bf93abadce2544ef0821accec66667cf30b7470ad23f1aa8b6636cac137d67dd08ebf4175ae4bd05bbd688046975391017b89e8a94fc60a061306621f44d564e8b673330d7a5e0855d77d2e09022e02896b50f99229d3a7a35ea381ee38d5378631383c2e9cc8d95409f21ea287d79c4302aa3ae77320267b20b4e089689c9f1696d45a4b679b4109794ad177421e6da072a6d23ff3cdd93516294ad236ea04af1be64ac7f48354e75827d633ca65be5542d5429c99d66f3f734ce123f03d4f9c62d98de0ce4fd46c0b965e2438f741f59b982f76f84343b0b739be82e9a58c06e89041e179918e811585ba8a34fd63a77850bebb1007d8c713bb183322e066bce3d2a2d2ba06712148fe9452bf040b3c8e03af212ad075e78763131410ed85b5f2e76e5c769165207e1ad9fb4781c10074ec2184446b93f49fcced99593f6cc27cf598d538331c9cba4c76a8117079e90469863e01bc2ca667acc313b46dc8b5acce21d1befa5cf91b86d8b5082ca0017e90c491f0da0c9a3a26b8fdd30e6190a5838e15d0c50788a618100157652a4f11ca0ea48089356a7dfe6044d9ed6b241372a13c0686aa74101134c04c7d4414c9c985d5228f5782d4f871b6605633f0d66486496672eb886d88bc521dc27f66551b70ffd77e0b0a531c36fe532a593840e82d0b71418b31aab8841a7a7e17250af9a908c36923e65ecf10b4734852994b2fc71be0f3d42e5d854de57e8c0b9cfc0ccbf53db059b51df6b6a61fb8b7f5e23a9f91c3340ef66e3f51f8584b16fd526796837da741e7799138d573cc52d4c2e8629dc056ec6dee9301e6422b5f20b45c6cd90dc690b7f13f793799e603aea3a8d05d743ee9a510db0740aaf8cf4b93f10a9606199c175ab1352cb5ed258477c541e8b76fc3d8743706960d12ef6a7dad04ab03cd217bfdd3358072a017465c0fbbd3af26a7abef5befe511056d3ad97e99290e9497e919982615a4f7695f4df53cd02e975395a37a2fae0e2a0bea78458904961dab2b52a8dd2e3f3f9bf9b9ba403ef0a1629d1c1758a0e8061411a71e42e0c5725550b07bafbec1e4b0ffd2eea64de54070e3b9f854de9f5c3b51eb1e050327100c84005117c0a2f3eabfb58e35636a89b4a653075273dc967e031d4db9fb6ef81345825e5a3b399928343d061b5a1981b577cc13af025057d81aa79eb1eadbaf58c3c7323caae34c8fdcf8d6c70260aac18c84d31cf99b9700b755ff945e42bf6af31fd61fa0d727a30552c19d0dbcace52172bc01ccb3074bc79d622656ecdc61dd5958fe7dc366bd06ce46e374a959d9370401b524608b7c8b9fe726c03e07102b72cfd1c8e9e4e34cd405dee8a873364131c80d908b9b5df3c31512786cbd922c31d6d56982b1670415e4a20bbbf755452b62e507f822aa41b5fcebc8272563d3df22dcfd54629d8e2c13b9237fde6e785d84d9d2a2bdcf137459aa6f978706892a3eb59fb4769bf7048c6880382d8134a9edf4367cd8024525f64c69302c7c792609521983cc38dba57b4abe3d01e111f80fa641ab2b9ce20a1cd667b7ed00a4ebc1cc2b2c91866d77e38a4631cd8fe3611e28e015865a71a150acb2c2acc17bc2742f146f8b9714e1629a1e7943997211998f00e7a17fd8593ab901bd01707f68e64326abd67a63d263917b4c62f507c470628afbb66e0f1d4a735b6ef5bea2495c12f6590c8e660a351f80223694405036e4508f88e9301f69d524c9acf6a998513d57b470201fe03dfe2f2279525cab36e5522e44d2fc1cf5eeb8147be1924d6b03ab41a2c97e83bc4415cea546253c62579cfaf0961b80b1be285f92ffbc99027e77054eccb291b8a86b4b28be20436b5fe4be7dcee85a2885784ec68379edeebdf11403220454361228241b2ae957f5fa120c1a2e2f51eff88249a27ac72ed712b7fda64aab4080351b1c19bbbdd1e471bbe6b44767625bce519292bd1f4384b6bb31afeed7fa5161f2fdc47457854aaf1c06b2db1343abb0639dea8cabf6a4c97fc6067b8615fc5eeb765102d03242f412ff0f29d79154888050e7622fc234ecefaf1da232d75b1060f94479ecd7d26d2068aa895a027429d904a82f68252619d4d42ff4f5b4c14b5ef414bc13b5aff3870f8caf723af789d44e1a237250efa0c81fbde9b7459ac58004048bc79abfe86c05b95a2aad4f38a56f7babea0fa02592959b15ce1563a9377f5e61e8ee27a889ba13f63d0d115d34ea13f414d5c6bab253bfdff039eae43292ea240cdb08655b30e78fdc59e868de700ba9461a96076074868880afde3762c91d5ebac59c7f9f73df366cbfc7e2ed43b0521e71fd76e488eac76ad3ca2d5b67cd09adc42f298ab91faed878b4536ab9b5b2265e5fb5a1ba04f4aec3108c09086e50e97fe53eb9a4e73830dd930c26e734816ddbb004570e3293d958131421adaf0672182a90af76130849dcbee5ed4819db49883605fae220057953543c3258530fa85ec6ecf3bbf4352c94055837288ba2d3a650aa560fde30385cfc1bc8501e6990f2d0694ff4605b81acd11542f4fa911d0d629d41a8e0883ef46bcde64409ceaf45be9ab9b1767b8f928bb09f16684dbb57e7f30c76f6257209e577b00fd20f4ef08ca76009e9793c8321c4f45ea407bf0949445b8e73442ca1ef9ab4ad70a81a5c5b2d9e29475d9a7a9b8653f98910ffe8e62d2937f948eb34065f4d7bf7c0a2286d22bc219926d86fb9ee7fa88af7286f803bc90136fd1bc99776f550d501be79400816999e1e3f159ebe022f63f4ad8f8066b073c297e4de78f0d1440488dde5d387dfb3b053042f40d5e2f3c603f733d71296c98d793b9bb479ede71f4816d497e3ba75a4e52560ea5d174dd4b2d9e0229d0caecceace270f22a4335a62dcd3fbeb46137952e8af2fa9b801e2024c31332ec61fcba79e88a2919f8a10650fec1066ddc951e15736d3488a500960769361b3a990c50559f75bbf4dfc4c21379dd6df7e6409919c128aab0185230841627ba188175d3a668d4c2d131b5b2688f06f9621bcab650dcc350066b2b12a9c39f9d8a724ccb320959a0ec978c43c303d91924328c031d67cb3800b03bcee78adb2d01fe180f82593830679c7194f77877cb93033a7821cbf098eae16a01afff29fc2cd7e6326216bed6ed8d76d0278f3f5e78d87d091fa320c9e2f5e10d0c3ffa053993351231cb5a05f795d63e998645c219eca142a7b8bcafec5e7372774d5f8192680305fb4e847f07522ba1bed2a5407409008fad1165b8654b562b41d9e9958a49aa9ac393a6ff74fda4ae1a0b2f07ff662283e1814532a7b87654eea9cefb08b0a01a1ffa09c3f2e190eb235583fa3af816b1a43d1ae1323783ee68588e23323faab1a1e374a9620d2886f3c1d2dace6aee833e8c389f102db71a7c01d86f85f2fd478b0b3fa5996580c632940889c2daab7d051bcece605288e0616c9f0e4fad067e7da55874936bfa5c2bf22602980074ee13a4d3827b3809060fb61a838dbd11b92d1864a6a4bac180d42729c83319a38f716a404241c88802818679bccad1ef2ba024e69e0b5e7dfea0227aa2e068446347fa017c000a3047a71b0dac3ae263b9a7aa6f68b240c84e2ba74d8551813e9820c023fcb4fd8469fd3c91467803724b451d621b919e4a9c1673b5b15e243a63bc9954f64bc3157c9eb8e36cf9b6add7bef3b77332bdab69295138ce68c6ec0a277fb0405d5053c608ba8f81d84f3f43c382b4d71dd4966cbeb0bde3fdc5b9f26486c0e287cc15e6a546c9c612fb4a11c511f34a42dd162b14483a5299bedc465969e4cfdeb2fdae3604e181878d8cf19dfcc6bfb5d32a7b83572d630b45a1e3732fc89d8fd4176ad3d0d34e3db4f330afce9a536289af8151aa2ad6e4cfa4efc62d65f3edcbb031856604d753cae2dadb5ff0d8c313510ae4ea2532cd31b0502a03c2f5d430c91dcef8379cd0af46223e50773b28de32cf08eda958577204a517c829b10ca6643f0a07e225aa5ee4774bdbe8a6ccff95eadfb4c3e27e47a39b2ab7e277616b2e4a92ac0ff165bb6d211d3950d94160595ad65b41c15fbc7bda859511eff2edcbe737ee15900510ac3be64d2ef92856f7c5033776ab9109501421ba255d3854309cb95640daae4da8c8f9762ec5f7f0809aa7faabda4e9d4b86cdfe6ddc4e6c94c9d6b1b85d41f6ca208b71c08704a70c2629ad90c2eb3f207859bec92947ff592f8778d711c346441969c294ba477022d6a4ac9d981183bd2e4a8f01166185b410ff70ae1443464c415613bbe70748197798e21dde6d13e549de481630dc0cb50fec79c1a6eb28aa85ac21a8a842ccb3fa204226b28f89d2d8e9b788a91ef9d842062441e78affb52068214278ad4cd4a9c01d5b1f687dd958c7453bc46d3cc49dec2c0b75e403d75a3d0c1bd3413e687ce1d3e4823ea24d62cc94a419fec122c2d2821e103dcfbc94e42add44e1d905003c0281d7b459ad2384657d2d59e34be1fb6568d203d079778a5cd38ece6fe5fea3f8c0072943b37b638f4c203a2a702e67ff80085d604da00769ca6d029e3cca1dfb09370be3f596efae809c83603cabad359b05f9a1217703de523a75f05fa0490e99220037d90150c1aa78037a9f8da89a74ecba363b8b9c77977066eca2d62b30cb63a83dede5af33d0bd21af7b617af21f6db5e04ac545a3d40168ca63fd3ab5c26e9f02f2ed48898b79348341be501f9c317202dc3d2385319e240dabdf9726a99fa501a1a42312d496b89b0c287562eb7f16eb128b11449f6e83a41e3c07f67437aae25d0871502a0be477abbd34651d7ce76ab7089f7591706c5e215230751bf01bcc36294bf899131d55ed94aab32da5ae1fa41c2b3ca2df5babbe227c62ab48ec8aace8255f1a6616d16cf0ca988f8cd2a53b713cdd73177ba693f15253395d64979e8fa91901fb2cd72b7a534e6fabc1e08cb048f3c789a46e2f6578442a5067cdbc85f7d692f7b8e293a6f88773ef44fd267befc30956c686c60382093687e12b2b15e5b408bc5a389ca7be42a775f46003ddc737d1a266410bd8d0c8e9792dff60c2b5e36e6ee2b315a8405a72ec74be332bce234420cb3a3bae8389affba5be1f93ef9b45668acea1cb6bd12a02e99685625a27e60435ac6cfe6a19afd0f473fb5d9b015face7c11e29f6ddfaaecda8e7db92b7c32dd988af0c1f6c2791b094b3ffb4a289f1e84d2acf685af24ad2a0cb123465c180886ecfa1cf00fe330fbf952c28b176dfdd63e0f21c89a4366bd2fbf10208ff0b2b11f4f2afb4092c54b48a083ba1d0999c9e0baf176de4ca06f07910ba08fce73a13eea8ba653f331636993eeef516e1bd2d69f45c201bbc8f46aa70421e1099d7218b09f7aa7fba1c04af17d1aba5a4b6b19a633c3b547edd0b7151b60a886180edda3757b59db336b9c1ef3c50745b53eb454221dbb49612cc2e5c9df8098ad9e559e966f081a0581b5cd30735e6976dacedaea2d42ba7c8b4d4dced584b6b14b7e457aa453edab51472adf693c0310675b4d52106e0283cfa090d3096d63b52d124133a7e1ff80b442ac64745f6a96270d31b15deef859d126e5c5a22091f0104737edcb6b25dc4354c19400d44b7494108dafcde3d743af8875fae8227ce9161fd5d0e3987054be149c69fe648879bb137c157ca4ca180cdd0b641c0e67aae99fb461b530456e2dc64ef81ef95e29d148a7d7f4dceead5ce1c320e7855a152a1452541a80e5c2ac758d1d6a1d6532be6aca5b642fc15e210c79a9aa5f5c238bb514a3d40b0843da12cc728c89b74b5cee1fa41473d430ff09cbeec2d378014ad5f326741f1a3c1698531b0cf04c8757b45a2022dd9d03d72e494aa702e5cc4184c91b49b4e9cec8cab394531a5d45033a5726442882326c8c75da0aaaa061b4dc1e7ecb5d32a011f19dd260d8b34607163343f53e67705893931c4837465efdf48cc195d60a703a45b88798406d1f4c9d8226751f5e7167a262b1b819cc1bbb3e129dab0fae5c21a9a91c39c71aa52b695955fffaf53fad3e5d9f981b8274b7c951be57c6afc2efaf052a9e52051057f9977840fb1c9963f23a207106cff1b6b0bd01fe910d873703d517d0bf7a0df7d321b1fd046750d1bb39861fe1467186f4596119559fa57c651ffc718c6e063b3434857c0f2ed482cc35a5c1108480efe74bceab60e2550d90906cb53c38ba6178dd6383931d61f4caf440c66ba118f6bb8ce6e1e1982bf2ac85e0aefdfd4756d2de89e87946675d4a5e539072a93a0eddd0b4086a75651e4472e994a31e5cb4179e714ed31547e9007c3dcfddc775bb945978c6b16000d261242f46533d2c50a091c3436a84bcffa683037ba10750ad2d9c65b551fb8d093391e27f84d249af23cea278efb55802342f880365d44484d7d9a1fc8261bd2400de81843d8bda241856cd2952b644acc4c064e64132a7a4ade7571029d3dd39513187451d7c6857d784a0f407bff64abe9041ac81b28756c15ad9b4710ccf57760bafbba11910e52544aa763b530376fdac83733393a9c3c9dde4c4d3839166f36a5bcdea627eaa06b4d4029d1cf5f102598ab6165d41336a1e796dc905d18a2175b89768724ed962f8810a38cd8a9ffd4bac092e2053f69f42357438ef04f85a94196c195e461996fde2a9d00b8347adb3cc97efb27feda1ab28d7178119cdf47c78f863946368f9f0b0f221b378b100bd833a6863eec267763eccb79f65b804cc2395e693c0dff4c41908250299d676731cc554b1bffdefd07a93e30aad0e6827339c210a51202348bd0388afea15fbf62c82a7cd9594617d501e5c0b398861b2d8811da950d7b8521570e4afd4287d2071cbdcfb5caa98e1d892c0a12220535a5f61142f9c1ccb71c525e378bd9ad60d68e90c302d69b42baae3a42271866dc990cb3a0a1488f1d76c3cbffd40e67a20b406704bb34ec9413f124d80037906af94ec16992aff9ea68bc8f1a19a878bfa03f511f9b39423d1d898f858277bb0e1c5517da404ce02f28b9088b9f7e6ca525012bee2baedcb3d802e10fc240361856092a1c49ba0e86ec9d06549ed17b26bb81e8b55939c3408aa8bad846542fb2bd1420093541e99f317a405ba5c109da80c3ae22e2e603552b88223a68a6be7e2f290389a78d66b19d57539ac960c5ee4f27d88afa5a5664bde325ebacbdcb32a20e22cbf30f45148f9b08567e8456f9b3b5668bceba53e45fc9d8e17989de90a976e70a7dde904d6951a7107478dcf2870315bc906344b0962e33f971f119b895aecec8673bc3d0e06d9fc0cd2aee106bbe61a62050a87f1bc4b596eb18b2a50dc2b6b0fd038401bc236ab864e250cbf137d4960ac3e8a6064908939f632b916aabac854a3a0fdf44bb390b96ead9c1d9d204d71fbb8279e523297d07c26ee5f5bfe02f4e229b2c5f08fe8035b6bd12b10a9d2b83e3841007d8b8528aa8e95c6844464ca9f482a6ee00438b509bd3b762a3444279dcde278f4c4e30edec3acb28f8e8a70c6524e1f8f8114b3066958b2d3ede32599f01599340d8c38dc7880f0f81795fc46bb241ff11edbc25bd13ff3cf0da4dcd3e9ec0f1b2e9e1c3ddbfd54e48b7dc11c910377230e6d1438d79f1852c840c7d6a546b3b968eed1b24ffea6f235409f34bbe0dd30e9d62fb9e112820898d288d2addf7c66b47b2659b753316744a215384abed31f08b54b4560d6fb4716be4c331f69f81e55521eb3541df8fa1e5344c90f88e1cbc14106d0a0115930aeb97743821a2be361898a02d8a2904cd52349e5ca2762f537582beb4138231e380bd1e0b2886b7e14581fa5bbab094195e1ddfa87d089cbf558da5494e9e6f07f17af2073593a5cd5f7e827842301a90a5b45dd81dcd1302d926b57347eed2169a3105b995e8f47c9b96181e1b1ebc5b612eea9106155c1b64b09517370d2d9c1ff854869f243f59d678194c0e1500e7087690de76117e947acc999fb4bc91d080a1989f20a78a2383e86e8ad3a7ffee8bfc7ad1118d76796aecc96651b90b045c2c312767a3ba681a63e7a8bedc9f7dd6b2fdfe037ad0b56cb8fcad7cad08eab61a5380b6dcbb56905264707949a6ac10db63fce3d7fba9ce85135c19a017138bf7c90744979c36ebbba72cd7a00237005c919e9a2439b7cf38bdcbf06db4e32793d950b30f45d91fbc796f7c5cb13258d60033cf1b93b643a800c551c57e65e4eb8a059a8ec17f96e15dc637510b0ea4af6cb372920c5776639508f319896d644d316f15a1991a07ae33051031e1438eef593e7b32c4e558d269f0355616407b72b30f9e4fa81250a10cf23d57c20880736345f72a357c191cae15ddc88fa05c70254eae07690830b1d9029393fb2d4e91450260cdb9527000d15879f023758a4dcc294db0a4928878f7c062f7d934de64a9ef568c86f5940cf977e61b53b2a38448a690fd41484626b4e3a34d4284f519cfb3200a82908c54b8b36bb13d80cf4d22b2488fe75484828162ac59a51b198fadc3d5894fe10883f06c8304a32e9b4e39511a65a1caa597ddba78c6110f3ca20c697e8d184122e0d983fbf8bfde2c701f6074cf9b18bdc2d8b6481aeea117e19b8a1ca3423e7aceaceb6d007c3bd7d54968ab990cf25c38b74a194c1b833d014b5165d4b524b30051b9698f51dfe014b27913002b0e207c1cefad5b2638456f0a23c0fc5f25147869b4ec6e3012d9b28d995bbca00e555ea82d198cdccf1c30dc2adb413651366ec5da661ed30b48e0aaa7835379523c0645bd96458eedf255b3b703ab85851e8fccad70add31e431b80087047b85de7e982d8bfb00b249d0fffade98b9315e0883d913b234595ae1696426a869406a0589a34ffe525115da3eff13fe1c586e3924a5dbdbf18b8075bc5b775753a8ef79dcf815524547e52e39529b212079dfbb5eb8592bb7174771cfc3ddca07fca9076ef149a7872511bee599f3028eb08bfbd7668b762030ef45fc21ea73a1bbe55cf8578e0085176c987fd99befc4ec42674fdb3b5ec12f12fd553663740d95a7b0099b228e129b56fee2708048b4c6ada085ad3eff5567502877966bc75620b2fb5c27cf60b56add8d9127b1b0b05f6220c3d749f3671a0fc431eb534423189b3530cc43fd1d10843ac925d8e1128d93328b35f60b5e5cca21fe15ce21f98ec4423e4b9081454fb20d897964ec2fdc5df7787412d75d156f130e56af9580a5e6d5a18dba0abde020bcb5a64cf767022ed865162379976e68bff59dd97711383e38e1c197ffacbbd50e5af407bb921628815d654a377388b58e8990b418a52d94e17036a55f6759545ec8677e10c5bcb7d9af8cb1d4481ec5599205ba8b0ed720be0d965bfedbe6be864ad3ce306248bc1e872c938a158b42c2a65ee666f2c1c405abe2709005156dd707d7a9f5d3a1ac319602eb989b9330a8dc7ef8b5b3ce1bd068ae7e850bef3dbd886544e4ef88258a54d2f1926e1dbdfd60fb10df356092c13f47efeae4139f72b4fc48d306f4708d61c695034c3e15d2683c9fac20b12268d699fdc313099819e35c00ce78933923e674018ce26cc4cc50c52cf0909b38069c08a02aa55e30068d1c0af4b63d069e1320f658a9e7d06fa6fc4e9cb3d9f3a6483c726e0de7c9949ca991e0501c528519ac2be422eaeb7767272d5c4f29c9caeeacfa163a5c774bef65d798ec2af9600d33a31271f7d3a9b4e435ce995184da4b4b0c7e9c1d636fbb610f6e3720637cf8d83430a6d9c11becdb9e01bc681ad5219cfa8eacf46dc1d8cec9ba6ad58f7642610117ec5bf62d5ad6ed1240af0380dc09a93ab7078cae8921f86f5fc01bc9ddc6ae48340c3705f556dc414fab792e0dc5d9df7ac614bf01843e8b20bf68f0b88bc5705ab0d8c5bd9925b71730fa9e3aab241232825ed8c1c52aa5ef6ccaa46cd324fb22e788f8fbc732e0d6cc389a82468204cc867ce9e816a8494d26ac329ad77475519c2ea1ba95acea301c107eb4eb0d7f78217e3ae409e27ccfc88551982de028a601989a9b470fe7181fe4223ba6037260f2fc2ed2f34659a2f5a7b39816e2da3b942c08a8f07c14f85c8a251f09daef01290def624ab9e44a3145d824d4df9a451ea6188715d18bc26618eff3f0f7b0e402cb4635023b01a9724ce5592823c250fcd0aa627721105a1b72d1460b9b25105419abe527ab8b18f5cc9642ead1d3d8b47084d5942b0aba48a030b0531ca537b056caa7e8693d5bdd88a4a2338c02522c16f1bf3be07688df98f5a58562c180d8bd66c2cb4b8b06ce96c8fb92c4122390cb158a5928cfe79ff07e49b91b4bb3a24d09485eb4c7c15c06d94d104ba04179ebd13a3b9385e1710eaa4139e95a0d96a978f9acebbb7953ca4290e07ec08d7b3f08956393d6a29776bd7d07ba4e2d0076e517feba13af3ac9440961ccfb515d64cab4a527cba88b668682d468a5ec612e4c8d76f91a8b6f159244d9dc61a9e3260610c107df1b214f178b77f102740ce050f391ecd24252f371bd5167d6ee1f6b8053130c06d6660d1520f52582c8f2f498a35d1259c5fde573b5f2f64107237940b3edd45950683e022fec38bf210c309d2ff2de25bf1c9e4ab9243f383d82c175b1f49dcd9dd381ca36fb1b14ae078b61347c0502f716702fc4f42e2f8a077c38bd6481978fa8e6bcfd41182e08a8936a1766066e21ccf1ff3893156461be608ce85931bd80fdd1b8200895d5c90400f792f5131d3e8116ad4fc3efc77c8e23457190c3dcc6b53293fffb5b7a794f08de6c0608515667bcc08d481704577aae225034912e9f3b10c047f309a43d7bf8d2f218ef92aece286dbcec82d23e3767a959635038d74188ca9416fbe41c46457c88f87633cdf1375c505101e6a78e075cbd40e170e4d958e0a44bd8e579baef1a9da61dfead9059012d6b9da7ceca8baa4e00adeb1448f3e602e76f8e920893443227e2f2edeed5971163ef0a68a7f6e9fa7fb61e1229f32c341ba6213704ae4f67e7e719e4b9042c50d8d9046735f4db92058328206d2d3737f1bd9602aae85a4afc561a404a95789371bd8571579c0948b09db8283de6d368750b1333979dcf6cfbfe1545c338846b6a51c762e7f2d9a5d7a7bb2416045a9449983f1436f69fa4cc85fb19229cd273ebb645682404780b0090630ca1bc0fe976d5eb09f729394401c2282f5650d058e5cbb0fc6fad1ec8cfc5eb0bd26b25e16df12ea4be23ff7007500b63eb1e0272bba354a5a794286e0e97650c7d9577b9233196e61fbdfb27496f89f0e69745fc2addd12003798e0e0b9377ca19f0ed45a371001bb25201a0ba46993e1ef792b1307cac970c8ea0b6fa51fa611855961bd5d11ca1d8743df4b19fd82ec2e886900b4ad639c2e43b8fecdd0916a25781ed387affd998b95e8fd228129137163786e20346f942462cd9174c4ab6500104c73da75199892eecfd1ced5fc8aa195f8f23258d6cfc465042b3ce75ec423a49ad0562fcc86f2f5bc7a96371ab1ac3a77636c72f75acbdc6bb487e9b9c20ed5353b3d41e1d01e6de48c36046eb0efc907e2fedd4416fc7d5b7608da81c80c332c5e95c070a7c73d118b67e4fb8d30b0d555a96b07babb9f5b838d2b5654a834634afea92d278dd029abe8e13b58c16bb7327e07484e4bd969862dfe2a3666287a9e65998b7bf775b47dc2cd7f105dd0eadedc7c4dc8d20e6d358755b5e7aa38c812f56899dee7d8fc18538b44d83b2aeb968d332c40f7928a1233b5eb2152625a6e02f51ae39b9887d2128a6e668ec99888876e51206d7be608762b0d97ddacb59366d085eedccc38eec938ad44b84286dd479e6675c56c34a11133ef11116f23666800ca9bec9514bcf65851054f7c0c32d6e5ce0ab95873cf35f9dba1d1d26de085cc4ae31b6df5fb99ca45e2e4fb3c5c983b6b524572d3fc406d47d2e67b47a7c55bf41c11fddee634cb88df09cf317e26621aa2699108b6c26a55b7584b98bd19f143db1d7900886e303d56cad45a4db04ce459c58d261c88880104b0de021b60c60b6f18dfa554b0b146d866507815e43434614f935402a8129d0f3534dbf5026942f7711417e28ae5b262d66f101e15425f4f5c53848b9dc32e8a7253426b975ef4ca8fcbe37338981babb66d628180240d249e68d512912097c68bc761d820bd6e65a43c6125d08feef85f4186da636b8c5c410b78c3e09d25a18856c8d2e0d65a0c2c4c03ea63de8456200a693a1d6f4f3550a4a3ab45f9ece5db33d8fb680cf6db769deab9587e43b89582bdba62305cb792d97b8e80800355315cf575d7ebb64518ddcf954e52d52ef46ac7ac9af6dd438f80b3b4192242f6de5b4a99a40cfa075008c108404a68332047ae4be2e7856b6d87dfa63f0ec498c822e1f7f97ce799fa3cf8f1155924fc1df0bd1211f9044979c70ce63469e04b6b1210eb9c4b7ce69c4decf26ff9ff1fdcfd547ba45f57c1d69ff36370808d4bd5b1bdce7383d697f2898dffda265fbac09e01d8da7f8f1eb975df61bfce632d92bec612092a67ce315263afc08d4471eef69aeac818a1daab35ead28ca028b3dc9b2275525f5a844c912d7b05de59bb433e6591ecdf0db4ef9be5395045d63acbedacb56b5c01284baffddd1dbed9e36ab41deb0ca0487f4953e97d4cc21edd5d6a5b3b34eebda8ae3ccd5d4fcae3e9f95cb0f03bcfe5a9e39dbd10427ffa9475729e67d927200bb463978f1a013b7c60ed93b04e3e6f9f8412be34b44e16de5e78fbf3f62f9775027afbb74be86d76a96b74a68bbcc725f6e9ba5d0ffe187ebd4d2cd3705bb21adbfecde14c97787dd8bf33ecd3e5e2ba34b67d139cc984b92bd4807dba56566d46b081609f4a5c0f71964a1353133eb26a143c89703db8fb9494de5c0a6e5ba7da6eef9b5010d28dc8a7aee97adf30a8ab03a9f7ed7661a6fb668fdcef5bd7f60078fd5cf85d3822d79410a2b6d0e331e15acd7df6497b4694e0e9a9ab0bd730cf3c9b44686adaa9f7cd22f98dbb700ef4393ff2bb4675611b8be4bffa7d0b32f4f89714950efd2e9c1ff99b9c14fff5b68d37f4487d98b2696312e180b4e1c2e50b08d90e1368b08061cd7952e462a4c7ca2bd57134b45c1e82b3748f8ccf7cd172634d8b355235a0a48cd9f2a1044a728913b12f263a2a700a702c82a6f37d91259b37c497ece931c7a70dd1a7cd0ec6af3967b3cc399fe745f326cd871a568c1b55618abc819a8a92726683cb13241c15d6f38ccb71ed4603231492295eb6a00d1993854bd23e1679e166fbff038a6fe25e7ce108e3fdf08a44f190659da435f210e29606cc8e9514b24829a610922205102f2e2699a4860b4b0b2bcf3819343c7a2ec993c6c60aaf236d7344c25cada1c1a2ce1b0a395d9acc974eb3c1666595538c8c16d3b671e37ffade8761db23112f44902c76f68388b05b8454a892808fa446283f7fced9be098bb34dee8cd9d458990d40d521ab36a07c531dc11111ce377f04e897df007304e79b7604aa0ee1b7c1b2fc11a73a84d5a460d3904da69f0445c34ef1c794141c583918b0e2c71d326d7c78f570a00812fc4df01fc1ff02fe3abbe733b4e747ea8f3e1e7a10be3b512c7faba3d8e59db3cbf2efdb2edbf67a93bb544bf38136ef85d41568af1fa4fad4f5f4f9d2d49e679aaebedde3f36d1f1f1f9fd5b72ffcfc9aee0b172e00010161f8d5b781327c1666611652d7f34c539f0a026bfc197eeb672faed6b85a6372b549a1cf6fbdc26291275b638edafea66fe026f77aa2b8772a899bdc3aad739d6e4898a56ea4fa57cf4210b801caec59ef320fef4a9eee5d0bd43d10f4d6aff597e5bb99bde84b6eaa3953ed326569de20435242cce4451f52bd38f462d89c276c66aec4702483e8092cbad0e824f15223e86fcf6490f78456bab876def668458b0147f25b9ece4748e8278880d004232698608209845c4808cd0ec40074c1f720fc16910cbdef8d3448f0f7af962f7d08fb3e2eb449d7bcefffd6ffdfef01f01dfcab0fc2ffd5df590ba4d64cae6dffdb1f007e83ba9e7bc3ef3c06b27846e68d07795c239eb5759d95a142adda9a7bef0bfddd3ceb3e5608b5426a07be85ee7d14e08a473433163ccf110d7985507bbe596b6dcae3e9f1763a146a73f80a82d0a0a00acea320f3fa380f879eded1dfe1a3dffb1d879fdd1c903a704042e280d48103070e1c3870f8590b44dff68e5410f216528378b8c29edfa5bc2b74e07d134cf852875f9b8456a0b57604873f52d75348eda0aebe8da21cd4f5ace08f844448ba6f79475f41051fa4aebe0dc277a845ff56a0aebe9d1ea96bba5321753d777a3fbdc5bf197e8e5ee879d01fe250c15f355f4a1d38c441edc03707d428140a515c2359dcb8baaea84dddb1a32fa5fb4a16e3be98c983f73954808ef0a5db665fad26cdbe288abe0777a312ec2335888707e1423f2507dea17be0dd212abc52be84fe915210fa41e81ffd1a1414f408403f03412f941474040ca2206882a01141ea7af4f677475608b542473fbb712f8415ca2024a4167bdea26f1f68d728f809ee8607817f6f7b1e00407d0dbfe141f86ec34fc317fdaed12f3b50c3ff7e1950ffdf7b20a8ff7f7b08f8b7ea0ab555f4effefffdecbe3df577ce537f42aaaa4115fadf61de3f083792e0fe86df8aaa25f07ef56aa957c8865fdeeacfee9fdd451a7e7917a943ef0b22fa5d1f434241bf0a0909fd7a8b4241bf110e1452d7df414240424242ea1af4bedf05fdae90df2d16d1a0103ef4d15e01a036fa4c172ddee25def70f7d7c2dfe209a4fedcd3826a1de8f317bf053f291e2415afdd7387bcbdde61cafb0d57f444cf94778bf76fd7150287e44971c62e280ebc503b0a94e88cbaae343e5d972ea2ba2ecc84aabbd497eec6495952bbad52a8ada7b6f9c6b80ddc564d4a97bdcb3c0b56e9aa8b5bc3469116e9be4e48d100ab6f877b1c94696188db0bc18158bafa6ecf034cb448f785db7cec01fda7ea4191967b50948f24f4d07f41d0d775615dd7b985ecebba1c78df2bfdfbabae6bdfd75a982948ab0a9027288c8c4d09ded75d988902c413be6899b2150349f0be2e6a213d46b3b8735c96f93dff32b02bcbcf0050953484b3b44055d2fbfa774d75bd3d03e83fdf96b683852bcbb22cc3c01139f02621e9c083efe9206028fd19e87de95f26ed9c73068640b0bfb38a2185f4960fc27b97a7ae4d4940f4d43f9ecf77cb1b8c73ff83fb494df9843b5d600f39e77cbe2e9fa735739975ce59c629e745d4e59c73be0f04125924ff0e6fe44cee44d6c9cbed70f595c30e15952ee115189752cf304b221543ed8ab8541604cefd02a8b84026ad68ed98cb70650d303034c9cd0e1dad373bb0eed81f7326e5100c418285c894284c989c56605b6911e2188e3164577c80f11549f31bf98ca67e9a84a0648a1531868d619a920658d68fee82230c941b5c6b4eb2c0e1a2829a15ce8c39520566a3a473ac8186a402e72c8e0ee31c0bc816766638d131943344c336e30d1311266cac9c49ad10e639d272bb85eb419e0922c7828a161a2754b1e5d0f85642e9786104489537534bb458b04a579dd6c681833d48b66c1ca3cb80acb4188af18b56523ad2925ed87e2f58a7aba8206ac86094b541a1820ce3d90f54d559933750b89445bd8d7d01dc5049f912d5560687f19d184626161099f3866ac8962f2419117398020c2770626f725b2c60fcf05941ce2b899d2a29607dc56d9fdb0e67915cbf083aa8551327126006b59ae223ada09b434cbc1a02586866cebc99f34ab32595b146cad6a66d47d6989c565b30e79cb34eff8608331e91b3a548f10d2e5f1853407979c1b1250173a638259873ce39c4080ecce0ce0870be8d9f643552ea980f2c3728d61012a74c9c2d54b67421c58c0665642cc2bec2c84df9945ca4364e595c01e478a3ca1014650b2f3b0c6c4549f1c6880c3a39c2e40c5590d1c21246c6d4f1c204a4cea4a474419372270c123165d28827541953b29002669ec61365c22f618ac4e902b3facef4937c6d1183c71b22374e182b574881a2edf18a8c1833516669b29290bd173ac8ceb478ed8071aad83963f0821627ca97953039c19c73ce5a2ce32c29392e2c65b4acac15e0ec7852272ab8fa4a296793627556006ceaeb881a1634ac385d4d440ad507f9d4d934262965aa525fdd22148478895971720c3bc944ed9c7308881ce370c11882f9ea60f437b3b836ed730831b3664a853227a8c16c658a371590226405982e3749d81045a52b6fbfbba56dda783c7f1a4ca9e40b264a17dd522ec7f01327689964d3dac0d952bcaaa2d675264b14517efc0465f05003244e05acb160ce39e70e160945bafef8f6c718bbf06d3037c9554f7e2099cfd96c5a94a80b62d7e7388d9b9d9f001ff812cea73b14be3e76af06c62f5b389eb06989719ef8c57ca149731a2a589aac708c01e5c7cf9259bafedc34e7c981ad06167df3bd3f6bde4dedfbe69a48abbc9ffbeb4fd254bae6bca6f8ed38d0f5fdbb81ee43ed134b99ee3e60bcdf418b4e3fc67fefbf8d526b63adf5d66f55124359b55a5b67dc5875a3d28bb2d65a4973e661ad15e3e160bb8cc7302fcd8efb76f665adcd6fadb5d65a6badb5f8ed3b12eb2954cb5a1369edb51a6e973f5b5cfedde5afc98ff0557213c2cfc6ef4718e824e5b9f5b21db6faef25da5aa8927be56d1f1ab24ef6c879d9813c3fb1b32fd93fa313662deb24bcd822eb581476e9ce092962273a763626cf6f1fabbb4ceac8730a790aedcf44de3aa7140a216fc429ada25a6fe52dda2e649b6a1bbe11cd38d38e16ba96554de499d4feaadde6ac13ce484bd34a4b4b4b4b1bee58efdc852bd27053a0bfef52be24bc76eebdf7de7befbdf7de8be1afd0dfa1bf70d77783ae4fdd0cf7bd8565ba6b336eecdb75bb6ed755bb6af74db8f7357045b820d8a76b753d34318d48ed930897ca8ffccf332d52d794485d7d6bbab7b5d65a6baded49793c3d9f0b3f16848630bcd9f3a0dc434270f7c96104c1395506d5a730784073185e63fb7bd61a5000c0dcca870e74a29a90ed5d6a16dcca874e74185c3e6ee543273a0c21733cb7f2a1131d46dccead7ce8448721a4c96558247feb5416c9834820c17b404bed4bf0f3a17f8f2a752aab55e4e99ac538d5586b3fb2bfe23b474f39d0be7b0abb0be272d63f346efb69ceaa9f70f736605ccb3a69f8f3aa53d6a97cffdce5eebee6eeeeeeeeeeeeeeae93bda1fbfb77d91142cc2a8fd122f95f00577ad1f67f236e777777771f1ab76b959774a0ff0634e9f5ef1996479d316720199135af3950926b82ab6f6725585fc813c298a489135c9376ce397f3e3dfffb5229dcf9cece5f613be74f31d307ce68115e3161b2c5cd003a946051c58093634b30e79cb3968ecb8255ba46045db34e1ab28a8ddfb1ae05142d29921b0f2d6a3ec834c95a018a140cc02c4329722eacde7035c1d293c93c31f2dc4d55e39cf5e75f0927cc07e1a6699aa6a9ad887e6aa4ebcf8f8e91db34f9b241152f852246b92a4970d45081c95c062a6c564c117e0df101c682b7302ba927708831ec2c89db4121890b82e62b07171b50d25762e7245242142e5e459c34f131a44e12373e16cd0d181629fc4042a69836c4180915171d7147ac1c31c674363edb98b7f18fcc56968db82e2c2e8218638cdd5dcac82c5d5dcaa57cca996e5ad0dfdeb40dc2e1fcef9c2f25b19a33f18c97ed8e31a522ae5b900b8aff1d3a930dba1f8d4d76a4b48b01e8107b826507961460a669ea39db04dbe61320471c1972c2315da438d0ad593ecea6697eb0cd026cb33471ceefc062ba85875b6cf5f8d9f84fde65ba46a1504815b43899218896b129727265c839147894503bbe20e162c3cc9db81c2651cc47d69a2c3bd804d7749b3f82699a72b689246b9b3cdbaca282551c92264474c8099aa6699a9f4dd334cd131de85d002521a9deb82c8903765aa83946c1b2c143cb99e9413129b3238a9c1634295246461484a5ab9111f0931e3d1dcc91a16ee31fd4fc715baaeb6983d889e47d3194176f48a215194582237ca0e318316efc04f025a08d8d71d8b498231775054c10630f67a90739e8deb563b32e42bd972cbd578403adba92d0d65a6bad75fdb784eb2a093e5be9ca5383f88978a97067f4f970917db2d6437eff214a9a92ba5b4b74550d2c124682b100887829132fe23cf6fd9584f3d8ee5452f75bc4480c6216e4187fc199f4bec5d62b83135277777777771f3bb7cd42c449db8f2dbc6d16246774db1e8d30f92a66235988689dbe64ed953e4d3478fe2c3efa597c14b4bd10169f28a1dcafdcce62a6e0f96bd2b6492276f957ffdb775f897fa7f9f6546d26c1aa3708854f64bf5ebe4c3da6b9ba341526fa7defa3b275a2208b3b6292c1b1d2494d1a50a9a2c282cb8d0e30a3c3ca8f386eeec4c151a6c0f9bd19c9c0c238891293ca6817a7b95b53c45878a08e822b34b8ac15665c65955f53903e16582553309ec9e195257fdd0c8c74a46a1cd95c542d29a14c2172c15641c1666c455714b0325d599e928307fb1931695832d820d940115611b2bd99b90263bd9e4ca1f1430a1c154db654a85d5160869a28308a7356b2dc84a52726582773bb2eca8d9a12e55da7bb1bff62e72ccb49e4fb51e291ae3cf7eb1050c1432a2e0c132c686ce9e44c2c851bbee1906306a78d7f6045a7ced61a5b10336557ae937e6087962a517260e25411ed0e1aa8a9cfc8635a6c758624e5dca40df1c0480e35566e70518d9d4d983c41a990081946f1aa82834630276b0ce3921c6181268203fd4564a5abcf976c4e3a9b1e3b5f63c125858218323fcc96e438430b4aec8c4959a203cbf04a052bd2353d9bdcca93ec86142fc06ea040a1460d990a3518441764567429b9949cbde8313403a284c5dc1a152c182672ce9044905ca1f142859fd959a37503adadbff7e3d9bdcddb1af62edb7c3de36cf2f0fcac037b28dbd65a0bc832a51508f7b9779ac784df621545666ba9c89923e279fff16ca535076ab6ad937af888f4abc4ad7f552a6efd4a43252b25a22fa1af5f29872ff1be676bcdc3f3dacd81facd817ad7b583b233eec6eeda5e5395a8e640fde80f5dfba16cbd0ef0eea9122053fd44fa3fccf830b44ee73781edf26d58b5a5222ba32bbc5f8d90bbf745595bff6a8462f78c84bb57f4a6b67bab04c8ddb3b1f5af121c776f2801d86ef7feb44f13c8d8bdcf5d1e766faf3c73bb87dcbd07125a270cbbf74052bb0734b57b2f81d13ae5dd7b251a96c9e747faf56e73404c5714892251356d3ede10b7b5966e6deb74c9adfbb56788dcbad719ad13efb8756fadd31008fb96bff624b7aec8d6f96ef4ccd83ab7b6ad7bef85d001097b15087f4844faa96ae2067b1e2aa85fa9a8244469a844fc61eb51874e076afd4ac3fb64e54b44c3ad5f89789f2690b1f507e2d67b6d3a6ebd0a00b937286efd1750a5bf83b6e2f038c30685478aa07ed40d3341fdf082ec827421a60290a07e14a91f5d1b3a8f7d81c6063ef62a802b5b5f70dbfad70fc5adbfc8ca978e8e0e2cb261978ea858305694e52b7a3ba2f2e1e8e84b1f9ac094869a078505631dc828b2d741d146551ee19794f7631a5aa4a28daaf799864d46eb54b4f57310965edefd1bdb6d6b104ea43873f67a74eca068fbee57a4384d468b84fe6ac1d8d6cff3531a3a50bff73c00da1f8616493f075ad21503b81503380ce0ac9305a09d8191832c6906c60d9cc323b44efe46f67a744491bec4f31a888722d7bcb557a5610732faeb4006dab677faacd3cfd6ff59fb2eb8ad1be2b6fe5337b5fd2fd0b0541786ba164e6e6cfde5a35c7b551a22b736cbae554fad4ac3bd811610d5ce73c6e5eb371a0a416ffc431d6057873a006ebcdd5abf99c76e0e5de990d3068ba4d4933b6da492bc316d5b59d5962a38608eac389edec6b3944bb19c764ca1b7948f614015b86171244ece1492305b47263c5ba7878f355165beb8789059a82ea10a51418e5829b3460e8d2340a2e074b12ab58e45761d9888a922b2266e0d051e951b6788a4a0030d94343f822057a8da96c4d88a43e19823ad4d4a95b63847be9cac2240eefc6b36ee4ca444c38f5c956eb8d010831b52ec2a911c59f45040ea8eb0eaec0d5c9731364166499e309d24064b1595112c35407079c44ccd96592bd3a6c59b2e36362323a516e96ab4dd48073deb8cbc70a7081c206bd8cc61193133eb79211246eb8bd7132c2268723cc93a6de0ba8055b515310b9b33a3a1359c7332b5269873ce59e79cdfac4b775dace8cb961d6fc48808f1824b2266545a59c7e49419526ee0c6d2d51aafc294d1b15036c6a7cb6494792983d860a9c271870d6deb1c92d683ba818c11258e8835034d09861aa43532c94245650e07181642cabc746d6186a898525206488d744db974389776e4b61bbedcb183a6cd6c0bae8d75b932204044927857665d5fde905153074e19a42c47dc0b3a5d6441aa98d508e69c73d6528049227e002942260b96266580944da154544d6688c9f106c50c599c0b2ee642cdc71829b22546d27e90ad918a71e58d155c922c453df668c0b8b10109620687e5e38a768b43e64b0a3314925867e7f62223ac9d59612385c6160b7b02d91417725f900c7db85961692c07b5dc7d8a8b12272d880b2662650f32283c0ac08226ca17911658aec26c5085afaa3239d4de72f020db2a8fb4c048a25d09b3c845e0021649c9ea02d6c91dbfc071642b764a3b4a9ccc2ec850a019637301034e74c4a9985206c7c4164d0bc7b314451c452e532ad0d676816c83c0a3e7aa312b122ce5b1b3f2966339c3cd9dbd48cbe103e92467cc56ee188bf253a56247199d3228bc84cad2d58e89f0e1a31ea90deae4bdf86b0c493a3636448fe53063337ce998d027c582d45a6badb5d65a8f59d24f005fd2b0f5a7fa815a6bfde98fe7ece3a566feb384fb19acd0e36addf861a30952c68f3358a70e312f960c052130846b7351327ebea4ab6fbbcf22292149579fbd5a63e04cd152539124498643cc5886a31e73922dc280a9e0f5363f114301488958a241fada92a5460b285574648901412d1006470b878db9b2a9eb2e2686c5d3629e1493b10b8b1b5aca9ae7640b2c4a49173a67658eb77389d78a3637729c41c172b12435276cbda82aa230c6a5c411c6a6d545c441e58c591c32df91710a782dac0c83ff05cc585119434af1888115b6c4e7490daa2c73595d5d5658d2372a4c4b97613b7caed6b0d5597bdb7242bc01c3020f39315d82a851f380d02a0b0f38584e48814b62180ba82859dae6b418d2c5ce132816732ad4e0e6e6cca84a1b701940e021650487d98c23584e5793b1e5316ee75b64ced8c180850917ec2c66c2ff6b5a423406fd47d42688d1cc7c990afaef022541acb6462413f45f063a8226ee8f1f3fea044fa05758fc80044ff464a52f1853c113570d931e557a6382277e849870925194113ce151c8be6804f1fbcf040f9de0090ac004b19a4b9eff4c10ad099ef8911134e1264a284426c3a0891317c6540f34c1acf23c00f74f5caa38301541574f0fc0fd9de9c6095cd07f1ada04af18211b31e8bfa215823b54c7b3426d0f52354418f49f86a9e0097c3decf24e7ba32ccea5d096d9d7665de5302635beeff7718b70630b1b4305dd480e6ab5a5fe213aa0d3e9be84126bf925987bf73ebc75aa75a0ee6dcf003b95c867b1d0af0f08dcab6f63219614fdfb740acb379fe7c0a635e97a85a5ce58602bb658a77c73f8b5ba5bc49f1f381083497f97bf10cad7ea90ddf9022be1c698e908c517210d322b3596e0bf42fc774a6f7d6267f50216c9ff26d1b89dc54cc124f07d9998afb2551ee62b8c71d63ae78c71d0cc4e4ff9aa87fb438c0f535ad649c3872921bbb92677b7edc9ed6ff55197e9316dd46549daa88ffae846b796706fbb636ef26ad9ab75db4eb875c25869af3983c8399b468c01c64918600c02638cf10e449d9d8934d34c34f368a6a5d6c9cda3893491593b5752c220090325254b42e84d0f610d1185dc4e5fb2426e43451cbbd3f7dfdbfd4ae8f3cc1957e1a1273d89ad4e64a8d3cb333b7b9fee937e7b3d64de79a2399f6b09d7e5f5f0bb1efc7af0d7af73ceba2ccbf75ff90e74cf596ea78531c658ebb73dfc74753de8dfd3d3d081ee9f31c6daf594752a9f9e303eb3fb2d51e81e0c5929061ae99aba181fdbc5e4d8febba4dbb6c7e4da5e39d8fe766cdb63d26adf1e08250c1efb3e10b8ff6d06eefbbd1082d0cc28d9f76f8f77be3f30f5954ca9cfbe5b0bdc2edaf6a805b9773d3ec0d4e76aea4b21b5bc6def8429e2240a0531a499e0f561c7c9141a65aec4a811bc9fdef75d773f628c31d65a6b5d426f2bc281f68fb6a4173fc669979d0811f803cca47bfb9f04c26238672281041edc451f552f0946a3f15a0953cbc367a6404abd01487a9f047bd574a0c2203d1c770aa19ca55992529306676906472c7e792d81c2864c16d9714b982a1f69d47ef891ed17b63daa55a949a51e3c79193dadcfe77cde0f03a8b42c932fe1bf976780f37939e79cf308f4ed900f03a8d61c688fee9fab897d9e2a91aadef5c71aa1e4dd110fdc7d5d9766d38a74b5c702e07f9cfa8eeb276d1109c04c66d04f147d133d81deedbb92964322e8a0ee7daf7707d1a9264e0475af9ea5a6080e54cf5237833a55054bd774631e55d759eed881a8d2f084832a1a8a5a6d831c07549ae0e8284b5a30b4359df179d393c5c74d6adf9a52644c197b98d1b22565bcb2e1c5a5c40757591914d50d322e78b419526709932c2b31266a6538b290956338eb09d79db413904a56a880c54acd97569c189b768c830667cec60daeacaf1b295820b760594992460c5f8cd9cc563032040d2d6ecc15a8e1952e3fd08c4c79890bcb6ff28bb335498997fa988c9a34d8a67ddaf729b04a575ed35e49346dfdf87fb670600d3906c16233125c7d48beae92a80d21c32308b671fe71e07d5e586a7753921fdda7a00afbb6650cb514582d6ae33ff1b957f763163adb4826f4b6d7123e4414721bc2d2a1a4a4b48284d62acb9c9f884f564fc3a7ab27e2131187feb2ccb92c4becdc1fff92ae878bc1f570df04100ebc2056a89db399f1fbd26716493e82042260253082037d04205a7b25a1a73e0c3f507d98fa10e3c3f0c3508ad63affce7c74f76b7e9daacb59f72ba1b7f9ba6cb5de69adcd37558dadb495f3f4256d9ad7d4da44511445d1f3bc497ddb4ecdc468ccdb4ae88dfef9fe3aab33cfb73d54ddd9377f596713131da8b369dedb2bf3cae3a545b93939533dd697fc72e9df5a229be6a9b53eb5763704e0cfd9df4dc88eb3cebd9ba3f8b64eabaef6cbf267ad7dd35afba5fa3bb3f56da5abefb1ea81ddf687ece79f6fd560fb6387db3dfee5ab95cb526b5d9ee763476fdb79a2f887cbfcde0b917399b37efd3bacb5ce658b240a58051021c28fd7910a38bbddcef6cac7bff24cce6d73d8f6a8b664e39ebfc5f857969ff5f07ac0183f93cd7f96bd1037ffcdbc6c5ebd0657e2ec3b92ae497b63bf1934c8192c92ff051a11f5d6990c19ac93f564d6d8eade8bad1c57f90f0f3d89abfe6737b659dfbc06eede22f75eab111118a102463bffadbad84a0749d7a4db66bbcf81f9e805dcc5fe2b5409e676b6fd84cddeb69cf36dcbfa8eb91eac4d5e0f778403af6ebb6d59dfb82b5493bf6f48d28e07e4d99196247ef68831f729b76da6af744dda61b6bf068a49d7240ddce23bbbb3b9e12e819d0a94a0fdf43e01f18fefdd77d7813258a48b811ca8d7c1ddd8f38f45ba3e35da64ca46a150e823e8d8c8df9a1fe4ac6dd6596b6db56bad33564b0861687b60b70f9d32ac17c21f3bc63e80c2524bf742941763a7802d5d7d3b235f5a49e88cdb37d09f43d89d69ea8c3ece9c4b2d27765bff24cd63678d560cb7f19de2f986a4aed3e9743a1ed32d9a40eff06aa9e8799ea5d6ba9d4ea7d3e9743e2129516b4be129075e2cb43b30a6c252f85ae5c070e771678d76bab76fc2697928ba966f5ed2b939309fe7799eda546f7247da76dd920ee48993e227e14bfe4e72ce39a7256dfc249248249148e27277f726242e893bdc9ac41d92b1b1b33bcbb3bfacf496655996abd65a6b9df6ca377ff8b3f9e5af03fbe6979f7ff6f50f3f5ecd6ca6088186a32d3681c45adb069d6fa854ae341631e80cb26800000000a3150000180c08068462b150305023350f3f14800b68903c6c502a134863b1480e23218a82180842180618620842c428e51c232b00d2f69bda36e9e97ff6aa83ef1534edbd7ea56fcff4133fbe27404419cf8bf8e5edef787fe7a78feaf14ed4a25be9dfa51044a9279cfe19240b24f5d4dec95babe6980d56cbb18e46f7922846003927f9dd388836ffa46e5f59b22f019b01d801fc8aa65e39b522097b95f318ed3c7d205725e5a351bd15024ddab68ba475d1513044e9a6ebd55dfd86c085ec5a8ee5548515957a97d12be50233930ecd6ad592cea4c37a7027a2408f012599f7704c6b04ce309512a08816f638e3f007fc9118006b48f6104352f5bfc82945a19cbb8f5d1f3de297f7639076785b2053abbf5ba4fbbd5a1d5e5ba185f89f9ba3b873f11b9e2c9f7c34aa3311fb10f6b334bf2fd59447a337f601f20bf16fb045cbfffa6ed80851b1e70797537a616abfe016c3ba2d5c053c0c1fa1411c470de0404515f212415dc275c6847cc1b8b81bb133b25e1cb2940580be013a8e566c23940c5638a7e2307da34ace83e8bc97127f90656bc9ecaf946b856f2ababc75b177bb7e8976412e02845b5790257e4d5de1b732a84e829141e195fc0ca64b9b6f2a6998133e90298cb2a634f62ab2a432c26188ba4962dd0c8b3631b313e01130aa13d66b0618d98447411530f22e242a23880aae1b9249944f26b84d16608284216df64eda96eee26a064c3166ed845cfcedeba69c6fb77383b2e65fd6c87a89e700e0ff658ad8fdec1a9c3d9235d5ac50d539aa103f0afcb160910050d95500b837550820df01fe604673e5cb2ce7e297cb03a445a30113e0cd7831d769207eac47c5b5bf9ad121d4b263efbd241d6998fd3c5a3741cbb177efc0229ed038486102e42e26dbe3946c9dc6a41b815883a5040e100ea8e46a5d90f2d9280aa5de6bab5eb0713c17221709bb9688669faa42347088b97f95c554696055216067157b84757e7103a37d1d1e98a6ef7785272dc7721ac654a6be96979d26c92c42b170551152263f087f82303df4ab6bfe63c16008b20ff2b7251d64f2cc94e277265b5bbe623ffd9ce7cde5db88963398aaab15748769bd3e7daa178899a72a91da03fdc522e1133a905987b62cfc1c53356b35284ff9334ab314f401c2202f02b8e2a606278076760abc2b32efd2d440e6318cd3d52ed858421ce3674542591405d5704b80686786491ecf9a1ea7bd780bb1abde746e3fe6b904ca3e56604f7eb68371a17c05e40349ae700566b22b3326bbf404438a30ff66b4151b44641aa3bb5248893027a447b64294141caa4d1a7e4f99f4187539c275dc1968bc33f49134ccfa325520bc81ce040de9e5150d02fccdc603fb7d26e4b107b980ec2a79e14d69421898db8f69f0c7cc928ae9e958748ab0e59099a6b7695e71fc9805c6ac81224247d3fb5a25cb58ccbc670eb5e15fabbfd5cf8e261868c2141872970c73f5dba57ebd48f884268259d6fbaaa9567e72fa9fa1384be2f7043b5f87ac7e41f688e60e36979a9774a9d90a8236f09ecdca20776886f8df4da5ca1d11a5af9230794a77d7be06c368549f4b4e58e28b7ec94f1820a2da872cb0278887bb1e42ca61363554cf23a69e0c5591ec0c8ad040ab27f0a4026e9d6c7d5cea7c2d508aac5f460a48d370d1d71fc260a330046b0238680baff0321d9787fa832c50b350fb6eb7d35727a6069ea62330209055adc5ee9d4316cc260df81e5c082d6fad794053edf7d04bb532134f4cf389e5e0906b3146e9ecde89d8d071ff258c44bb72087ca74e6317bef249690509f8807c5b40829592d16d8b29778b8d86f7907f6d4b1e317e121b3e8a714261f59dab011958919d88c3a31e1a86c94b339c5dbacfd4081b60d58e5b9d6aa7a9ad937c5759755af9c931067b622abc0bba016e86c8088dae14ee54dd76fd38b57876ab102a502fc87917d2f5e331eec59964c3791dae1a4e8c5b05951b9b5fe6cf393aeb8c0e70dcfb39d6515070ef5d9dd299372538445c558e80dbf27fa172fdb86b0c57c9869cbd22a4bc15f079dd8024e26c90c229bfcb6b3a4f4b82489ad34e8a43417ec714c5d39445bcb43a725fdb0021e7501bc94155aaf177ad490059c1794e17cdaeef798e902feea89100c39f4c977a8333e1c861675b373ecd135c4992168fdbd51bda4e4d17bf03837ba9ba3a26c7385f674e740b602e79fc2e22f3f5c85b8973ebd8d94bbda7f51f552b658b7f7a31fbb68149c77451c127bc3fdf3ca5ccecfc07576c48f105f9116e824ba4e300d39197c8d009c1d9386e85903f6ec2010805ab997c05272748101e7042e923592725c7228609a33bb213bef9163d4c5e0eb64590d1433b09aa8a9073f921b265bf8a53a2112a36a0250f421d10ae80fe7fd714f33829620038b51c2f16b21241f402ae106dd676302978141818f894c81f4239e0e8c0b038ba5e9f8b95908d4386208c0001547279fa39cc7f654dcaadcd21fe2c69aa9fa3a28b299f23d6ced0afd38d70ad699aead0c361bdbabbfefa1371b6fed32ea051b199b0a7f22e4363d0777e58f5c2d8ff5781ee04ae50e486b15870712de8db36e6ce854a1015c461ece0d8508955bd399e6c441ed6a36016b3710a2fa42bc944f4bbc015c0669e54b4f6c1e57c669e5f1f0901ea14a66656923021e3ecb30ceba4eea20ac5f95616c70e9046b9785f97363b6d7546a4ec459ba5a78f2e07c66cef9e6b2e064f084e019bb00adcb7e43b6928fe6213825e413224a1f31deea484de7a0cccc11f98589e66723df2a345084f014175b045795c25bbec6c3d68a76d9f31bd4fdf9e569762a3e1da9c150ae15ef4eefe29354261177a643de3fb761c7dcb60dbc809f66d9f43a4e2e44c4f4589af5291f584a29bd8db276b51f291fe405112881a159746f8e03901c709fea6499c5dc619295b8e96cbaa180f40b06ec06d8c21638724997aa1fd74c9f1571da51771a0e881285979d55f9e952daaf24ad6033c4f8ac6154dffaec4608b0e3b7226af5cc223feb6a34096c6fffe2cd7fa56eae7934637397347ea22452ec83b3098c7c71e1a98085a689d220a6257e652df1ea95bb0304e9c3a6ec8e80b21f70d0d0fd9131afbb552f0ced40eb37e257c5427fa94912596b100a847a58167e6d18b2aac9fd1388ba7d42eee645badb6d9aa09a0dcc5c956008d8a62bbf5543f6ff1599fbfe2d7cc8b03a3c6be9d68578174f72dd8cf4f66ec078cedd1eb99c5d0798fc71921113f50ae0c4434970698bc52c89e493ae516253181f9c23efec9835d450d717b2ac8be48f49a98c8da3ee7ea48c9b518ab93492053b88c273b0611fd59decd7aa961381edee7cc481c4b9cdea78ecf5d4332c8cd2bcf1544be7ce008de97a87b37db6f08928fafcc8f693e0ceccc61ca68f3fac7e0d2436941b9d3e0fc6c3a3607fdf255cb4b55bba38e43e7545051a0a9e8cd2800339bd747a02c23bcb5ea51cf2c0ba7e19dc50bb3998c7e5d9b11df4f30bd884ff0d7ccb3e7e9cde62d44976abee45a3453c4df47e5e3198536b5b98928c48bccccc259c532fc7342959ad3306174c6ac904b444279de4a5a59a99b7595a4d36d7363c41a2ec4feaae4cc3aa2e6a5665ca0d7e3c4ccc0df2fbd74cb61e901281fcbda60d5e326b69565b32af5afcf6c02974574d0d6ee8c15aba6cd5480c7ccba9a36aff3c31d5b2c28a8944001c40f8da464593c9e0dcd29e394def83993db81de0607ac82752b62daf02b8064439d32ee202884b5081b3de35c50fcd72e70d6d9d86daf46b0192c9bc677cb7a1f322e82d4c1a4135bccd2ee4abd7d7acc5587632aa541c9f142f186e91738d3420aa11283409e347dddd671015daf7d2e187c528e1d980fd3a611f2e0f2e503fdae16abde6df9527b440e373de5b2578c1abdac08c8b81bb6280d7bead2514c7d3caa0d598bbd82da1c7e74102bcc09cd69f944527a30f09b3ab52697a5118cb45db67a897f9fc90afd741ae58c97cca1a06a33eb6aa4b0e2bac05dd7cfe103d215dbfb40a83d11e0ac30a64643eaa000b8476eda0c2dacb1340682ef425b64c12ea9c2998cff586940985518b4fbd9899ec1aabf2e6bd966bbe312b43eb3b5eaae0140bad8b4264a324798259e28ac6599bdd6ac84fe30751dafb53143ff924e14f546788650ab90772846497a650f5e4433f98994e6c2be785eb03f409cc7b80efe5cbce3e3e7935d68f98d8efa689f18eb6ef9453e8516dc5667fbcc07c8c4a58249edca72cb6a2b35b4406206853d2cf8f081d3a9f3a04a5be70e36eee75a0cc179e0341ecadc26984f3eaaec908209268d6c01e81684581030b99b649caecf7c8c71ea62362361081f7e6dc424902b40d9df681c1cf6a0de32aa2347b44301b7f9df5dc07d89c5253444f4a60b98cb2c4a701f010295df27b15214ef975dc851861f4b8389e697e3366a1cf8f05517d67741b923db57ef4f45623f359a359a9b4592a4a0422bdd15673c857225ad41190566b1536a57ad4bb21b4d7b287615a04fedfc85a4a70ece7cec8616d76e9b9a185a5cae0c17081e5d24647601533949f6de5e99ede6839db96017ff20b2b1bed0af5bad5d32348a22c03be8a6f561b5e12ca4d200b57fe4a5ffe866561be26d3ca54c983a48823e2fd90539cbf9310bcafb29631843ec9c0fe9226f19e51bc1b6961ff922412f1acf5812e717d301283707d11a4360b983c5fe0faa73c9ada6ef7b4d8d63bb9fecf81558974b75657928612c6b6d6e0d82737cc55475fc66b1a9550e7a384e9c041423b07de743b0ff94304c45f77e6a91b6bc25e6590ddd4e311747505d73dffe9eb131878a5e568928633a03c240cf0f49fdf6e4258505a24337f650f367a9e8d17fae567fd436ebe3afbc893f0a1086c45c4d48f8588380178d060ef4ee8cabf70aee0e1a2830cae8dffe8fbff830a1831287dffe60a68161c394846ccd499806d8ddf79681f527660655027fdbba9cf01cbf18c6b2ade0e4e88070a465130e72d901d279196787c6e5d68a15286a71bf16586fd8ffe1abcf8f37295c484a77d531548aace9f7541200424dbbe50aeb39e56f819f099d53f17f10a0034c849502f0dda532b4d47c974d2684aed50aeaf2906fa45839d8b8e7c19c27227bcd7456ea5aa636956c5306394408b2e83ffed42a1e63f1265064eb6d740f243f5bc5bf988c23ca2e3eef078ddeb7b17580e74f58ff035275278e05de501e55a03dd67c9dc4b2778ded8296fc14445913a8e35232dec0d5dc48ef9b1dbb537630c9ab05cd90f0d569c25ca5faa9d3fff1d36d9a1a1a755255fee582c2c9df0d4000c1ea813489204d5087fa04ba94607faf297a14ab01e0408851046a94dd9cabe1e5ccf0ed56e749aa4b4517cb67e0defd92f8bcfa897c3835ea8891acfa6320c110fd0b773109f851258518aa96023249719ce01ba2ba1e27f30fe4e655897e2f151306eac37a576c776e011b727d6844cbe9a59820cd044c365c3d7d28040639c869cb77a1d8cd1bc1f9f03e60d317591ff1348677c356fcf5b131663bcd1fe9303bbdad57fcfad84460f3836e35635e2f965b8c6353afcda6128857f5d604ad7b17689cdc74800f819e95a3949f9bfa86849035d72fa3a6ae2b31e9996a4ebfb813d795fcdb42eefca08fc9f9489133514f9a9940ccb9b0d336ec8b98481a21f7d6dfaf1ac45d60eb8fc666353f8c7d5e0c11b00c57f3bbe03bf8902b5ff9e5e64643cdc994cf0eade6375cb31df1ea5ff2ec4bd33e0f4c2cf759cb911f75bf601ec968872e4bdc3f0675cf432b66540d841814eec6e47d638dc89156a9c20afeecb74dfde02f1bc0cdc4e277c74e239055faeb4aa59430c4d709371fc07ee09bfb5c65afa97dc1fa48431426efa2a1b648741df92a87f550e2380f671e89030ef2b9212ccb63bb4380416f1a22f449d12c8232035fb4c03d98fdbc77b285beb6d400b1417d4ca6e9754c92f948d00f61f34ed562f38bdacf438a9c9a4bea63e786290e1841cea579991a9a40c146ef7a2e35487afcb8f8159af90128d75399c271ec6e4c01b55a215cff61b6db91e1496ddbd4da786d2b1b1ec11888e929c52241d394927a122bf20832d9933a62a64f057480e77160d882095ebb334c81ac4fc669ebc96080e77d4efed75e83f2bceb26de1aaa08136b5a5ebd36b26b1622a843377e930c25823fcf065a925d5f11606797105657f9ffe906fb08d58daf6843943755b4e5d60bcceb648ed04d2d9b15be30b7312dc0d3d4d433a9328cbb7552cf8b451f7f50ad4b657c71c47fa704b4b5382621fc6fa0611decaa8e88a64a173e65aca640f60b12032a068808dc7c4b83d009dd7bbe8a0dd8360b819e8f39446c215a580ff1ecbdaa4d0179a0f31cc3e16db203e9e33e8a10353e2142929372ac40320d2b284bdf501ee9c6d294c6845a8b0133f83230c30a50c465256aec27187481c5ab8a1166b746b82c413b83f400dcba44c0733cf9c3acd3946e37a6936c9ac1d9ca4985d7ab6b108220587f19ab7519fbcdba85b459aac42ee355aa62f25b7f4f1ed92ca3bfb48176a9ff5b49df9b8c570683d2366bd3021850844eeecd95f1507c6dd58ec6bd37330bad04efb52a7defaefe4a6b0949d534e7090b334e732ec510ed7d9b7f00b8a86153e4a9298bffe6a5e320abd21084eb01222230e86514b1d8ea4a7c93ebab263c483549e0f63992d2a72604be87379769ea9744493136fd23251b1cd81dbf2a0f3ea51700862a5271af583b2935b30b0ede4b2dd442b68d1065594b2f62183218e6436a94abdf4b0f2b4401121468ff3af6e7ed92377f0edbef340432ae11c63fc11ae266551e2f3615a7c7688a13a7b445fa74e79cdf8b31f6725d200b7dc66980a1c445c6823e2b5c2aa5b535919ba916ca10e1e27fb863955eefbf7a7340d2c7bc7262fb811d7f71646eb656684bcc8e3c87fcffd9661e7a887a8f5f9f1b1328ffc36d9f9f8255774663387f4e6902419a4a1ab3e5f50012b007d8cd4be38d6695c2224ceefe73f6b2121a1c1a5518c39de93360b4c0812d553601cef05a89c64c2b4deb24b0d27f96464f7e31e4074302f95b4a5c2b9c0e485c6bda7d018c93a426fb0e36b81d91c21cfc7b51a42c12098e8ebb802279447c02f66faef14ae0caea5293da252e2f287780fa612b8f6698964f89b88015fc264ad5bed91ecaacd579d039b207c35622ea4de467f4049da37118057e05100406ad9a6bc0e24820434edc94301e245f229211faf5db5356588bc310171090a17a9911e1aa5a20e2110467c36abce85f7ec96aa850abe9f0638fe9ea19d5429beaf250154a546b90ee98e1a9e99d6835618ce0e05e16447438817562ecbde555d3fa0509dff55e6baab98e29c9bb8324aa588fb421145cb2c84482f46e893f8b23825f089c9ec2f382d986e1c4ceb10102325c6191e416541b724d3d7f39de4603e0d0f8830490968341dc3b6d065fbb20bea814c8c7cb152517a0c213e78d26ca967a61a6287d53cc67eb8e7cce51f2a5c794ed5a750243a06d1723e3d11ba2ed6093f3b623d4322464a54be29f7255bd7c2052f5bf6b12c9817e6a48b9c254409d95fd8c653f23a69898ed89a4fa0161beb18a6481bee7fd8c9fa121000303d5e30c76a0503bd8593411cc8ed6ed0881ace465bf30af430c9710c35b3dc790c68ba49031a0c6bcc51ba97d7bfa5f3440fe39b2b2fbff8709d798cce4a9e79ad515bcde669e92c90ba2a06621195d520b16d87177044a32ed703d66b11f1b8b37a84b8505026a49365e40b0bc68c5a4cce0e2ae407f51a4de4d28e8f76bb6ef68497d9c621d2558976b004d66f8e4a5f0d2480ce74b71d14719a5133f553e0aa3e29851143f298412251db983e3a8756063594193472595ee2dcf6d0b8c2a55c7184074fdf070c911ce420245c7f98514fc94ed4794a766827375b8a0c43cc798301ccf982780ad17410e1605cd677e52f23576988317ead5f71327ca7da549b99ef61e83ce1d6029135a38b6ebd3f91ef73617e2f2978a9c75e8b0c530e42e519e9d2791ed4622e8adcb80d17ddb6b94cf870cd27aa80458a86acb944cf00a7a84414814912a58f5d485e4cfc1883ea798352267ff639cb3636b2e4aa2be6c8c63663ae4621c7e3d884b312e6dded3755573aac3c397dd40128c3ace7fd8c1658ef67e7825cd0aec802a471d4cd49463127cea865020737e0a5496bd010648c05c29415964869be13b01e0e15fb5516e0b86bb130a31f5a44762833c705d2b3244e9398741252ac9673e9da982307c4ac45bdefeafc6d544ccf7bec4063f886b44e8fa7069253db855bb1d1d935507c625357118a0e73690533073585686b995da2ae8844d30ce14032a3fff2cd09fadb82d07039207d1554e894099d4caa81d0f49eede612b89665d0854dbf21d08c2243e30b0a2acec7a904722c59c19176f97b55c6fbbfee33c34c298d11a56c341e6d99031c00ff826d1f7029968db2beaa0f17279a65d70b57d991e0d28ea9754b2a7cf79b78bd2c817be699636adbc72163cffd17b48a81a5ef65c55150527fc412c6f6ebf3b60d3970810f3e2f49adf626d0dcd985fd6f283ec28659c55738dbd3eb7ed3ada002cc232fad04855bf8fe6595b71421fc5df6917884f4296f083f0e7401e3c6897ee45fa877d383309013378dcb9f41ed1e5e4b792f5b0cbf2734f753e543b52710b406ede855f4a55e8330fd0d3ab562d71b9da4a104f07aff30423dbc4a23a6dc9aee33b97b84e73c2bfa585e3b5ee154e516a20f78a2d1fe64a7b5c95573033c0206065d5298957aa3931c3ec89f65b651296158f95e2a0ae60aab5f2d410f44943312ebd8b75cab82d1aaf961ca670b48bf82907cbccf909f83279c7fa8de25792fde8222cb0f4b2fc306f77939cdc96375217a543a811581a6d87b9f89f0950abc29d84974f70c2f96fc22962d3927e447a4a30e53a25a53a9c74a2aa8b5aeb585d8ae1daacdfd9299d99c30b224111df1a2280a11417319bc27876db2a26a88b0e3e0c52c88ca66143f4db7933dd1d7a63ecfe705f15ad26c8cd936d3d7e5bed5bf88e7756ecaea205347a877cc2e5c8f255a3578f45315f9b74785859ac74f8f6e49ef692b3ecd49f30d790e3edbbbd206207234b1e35d297323119357608d94315a6894f2cc3460c82908412796fb2b0d071201593a96ba01c07a5c7ea21d11510c9c954df28ee8b3409c019cd5e56ed094b79cfd4051cee78a7a90f3518a7e5785391852797e27bc5c358a4e109dc464f9fe3b712d929df990c4c93b8289ca9c27950355428f3706801f3e43a41d2e0787653fbfd5a7d7cf8d88992694802a522d0ca5cfaf99efa405c93748de63723833c6b18e92c83f7eb3eb87c08b60048f1bd959e611ea75ea18cf2941c995c33927efeac4aa08fca284f7bdcee8c0b6b7f25a7baca1909d56eae6a1b5a135793adb1dd11fcb8f9cf728ac3124722d102673e79ed7eeb43871fa14bcefd00d95252e7fcc4b357c781d643efae1e9a655510a1bf26d1f103dbbb28306e82e9b517dbe21d24da95e048801a180d5dccddc4e7fb31ad0525926da69de554b49901f47605066b8beb16bccc7dc83ac3cc75a12bc8de55df017e9993cc309d9268599132c8cb2c8aa7f3b4936edb2b0c873b5655cdb56d2195efca381d5379c596f6c7509f8c6d2786f7787eb86fc64a23cbd78ec14aacaa056ca3af4782dd533b955afde331b36906bec0984b008c121055993b65a31c5ce4972022d67546d21759c2edb20471f5c79f0b0bbbb3a7be0c48fce7a9edb838fad3697fe1a7ff5a8c45917e6c1bfca202030fa6cdd5844d9c1cae2d699b22eb81b71afb3f20db2498a0751fa4d123e6a30f9192041debbffb427c210d9cb90d290b354a71b19e306ad6f1b1d25837db2f55ea714271a14ae420213bb00b20c9ec04a2281856c6926a236b50971df014a6e9823fd183f817dae50578adae19d0cf7ba66f8e5d5728aad8816d79173640140c35bb636ead955106d81f9b7dd8f8239aedf1524205371f4e34a3f7d391ab14e1dfe7c8c03f7d28f1437c749ad8146f9f899f19445c86e458160fe29c57ad32327ca8d77343168ab8e03aea68bacd803056a7cafcdd4296bd8c5d8c329baaf852502ec5d206a1d6d5207af6c54427f907fbc0b12cce82adb00e278e313abcf4092e4c03b06c8ce93a169cf10a753668407c47e0bc7b83949a52b991ea115fedb74a0984a918b96a9712bc9bd124781db705d3c18d9046cb9924cf9258a8464ce9c77346d763f01f36022685dc386d3bd85757433640c88537ba003ea02453a0f1683fbfee47079ff366835f480789584b01378ef9f07bc7f5e382cf107af825fe9452eb18bdf0fc2dc0b027ef00d9b49bc6e5712c60a2ba74b669a917744a894298c8f9d3f79c59929ac297a22f8719e0b32cede5e8b46e5e6d0a803b497fb7e22e2ec5a1ae74370ca7dde14eda18450b5c7d157cdf03fa0688fdaa6750c3d9eef2d048a39cd98fc6b8e8268b510058cd0800b3f0f158c959dcd68e1d0c53bfedfef9e1d2e487550bdad2191ab4bf424a21b551be3ac5b868d899f58360aea70120ba374007e32f680944aa52049c4e65ade61f1c4584673acbc12bd0494f7e7f7709e03414c66da54d7cc3efb529ba7965f6c4da75554918595f03eba481e0b72865ba3d52d72230cb67b5590c0dbf0ea2060dd351c5ad3bd7d431c971434f1df7a132a4e284f1b52e2565eeff67de9faa7d93c56792ac2b69da92311ff9c76238c868e39df5d1ff61c94ca0e5d64e8fd6f19ed1d9a502a5e64865b18feda86791b6093003f07759b81c4ae371554464175f2be47b9a90760a1bf69736f5ad6d5f433380d56e630a9e46e113fb9b1dd1ba651cb41d3ac969f9f167399712be667dc404f296f2ac4843e3efe03bf4627c74f9ebb8bb1b656168c20bfabe5838771a4822272f68cd5b989fccd26af896c2d5aef0e447522ebc63e63f43c2d950ac83246d6bdc50ddd9a9aa06cf6054b4d11d1c9aba49859d5566d57b9eab81cfc6adedad6e19397c1c7fcaf4087e77d320b632d1c1d43af31bad522a0e6accee80ec35b531f2d7664cd48a2210108cb894d80aae626dc063ec40b45df8eb166f490b3f0293557cd94decddda0b44c92a872370c65c9331ef388b54b47403db17ee30a0b6f97681398e76790dfb2d4d1f6d256b34ee4ee7b6f4094c411cbdc70d18c8df25a1cec1fc4372535df2a69d555c43c32cff64dff5dc2d00b6b84922aeccbe979a1bb22661ec88a93facbc237fd35c1d13795cd5d3ebba6a5a8ca8c9d6f8f62b3e5faae76aa4211242f20f424d8eae014a11215263de1bd14e04d46f1e862e5e48ba355c843082f002c7820e6ebd834a0f33cf627872599eb081914b0ec26b666b7dface2ad41f8824ee36328b1002460ecbf6f4d5affe08b849b48307746913c67e058a655a9aa5b848089d3dcb9e9b644acd038dad392fe89acc480379b1bdc6ae154869b3b4ea47ea5648eed70a86355101928f9292478ff34fd06b33762e2a6de651d6794271f142eba5c8c16e6feb411df35e64de23bd251ca009d0c6bcee8e750388a3603d4743c3c998a11891ddfce1b1974c9a8aae280b1b2a96cc98d471c8a53b83e5370095d1c5ec73e456e427d695646e2754ef807834ede1f16921549e2675b43ebe5919c24b3088c0887ba89fe0f19c8ec4e416de2384cf7c57be610edcded406cc6d337070bbd746c7654095bc04ada2d7679940e439bffd9dc0edba590ed68fcf06ee328baaed9852d19820211f9b278422216672204bfcde7539bb9f31698b959a79854adc2737cb553924f900820bedb22c604f71a02193dc821bc4bb8e00b381757d4520a4247fff15944b16c6e2fb5fa100b7e879566423ca6d55dc272c0e218644d78fe443d4be92b8d765275000366949fa5ec6b682052739274f16e19700d3fef394edcd0a2e3dc506761f68e6439cc9176c62eebabfec879f64557561dba00d6c8b4c163971842aa0e7f5003498a8043a26bd29a4e87661525f5318d80f08e97afc6ca239f2d484f3faea2ed10dd744f07c51354082cedfc2c1f99c8480a940bde7f883c9e053d2986962d6c5aae7e8dded4ba0a52aa5926c54356202020d4f97ed7bfbcbadd84606ff46039dcd8781d5da741926e4439bcaf54a5f3d35816affeca86d8645744e573d30b863bbead3ac28f7a927c87a6b5dff7a0d723d601ed37551fadc30db9d27318a51cd1992ce02e26982cb77153181d7029992aab6139a15ffc3eec640a972a24502f07d931311b3589daca8ddaca8ca53ff8150ad99cc80df1de4fe594e0c76921b1c11e543b96ca7d107e2a5061b76fcef96f47c4a726acbe81ff262357078b0a634fc8b6f62802140f90b44f5be0336cf67a1a20e4db9583b9a41bac7071135005f6cb851be4d2ce173b0669d710802f43780939119ff6dfc469296c7dec8a4f827077f12bd724847d2c366f6d50f3583be400fa514a83f35ab4edd5c239565ddfb9a877e87bac002306d5771a2ea9df8d0a5ab4a1bca523185db467641c8c0fd2f4be1b1c0425a2d8c80963f514f17950c6541fcd9b78c0aa4a9955ae701d6ac16fa665f6571f36a98ceb8390da545c8846121cfa0360348e5c4fced1556e501a41c651dc1fbc7090d5e98ed1fe2fb4e74833c1a9d1c10eec9318c133d293fe44f9d83ff7eebdabc8426fa1e23889594aff6ede906046342078f2b07638c382507515e008ff02dd7afc1d3d53434cf9454030308af7ef48d152bd14032a16f5d3f4d2fc2cd3a5d0a16a902b7fe767926ebe97372b1b93c97acaaa10f4de1c9a4fdc47dab741dd740017bc223c9b1168a809369b129720241741d27edb8de20b4bc07f3102d62cee1ffc664a10d29a50fe4b70b80a34a9f5611cfb013e6eab85fd9ce6fe6bd7f39d2cf8f016f121a993e5ed9072fc9ba7dd66395cf720be830587ab4ba63686b3d29241821729c277a8b2345aac068c11ae7f611c9b4c87f21d9508b9cf6ce3fd3879aef59e3eeeba222c1a5594c0b5174b536d144e67c507f3ce978bc8c4ef000494ca69ab72af3541b68310da348bf09e3f3edd60c81978e9d52a91546d6b49c2c58dac7a204456cea9c64d26049e0af81f6eb2448b5b8e90e455efa434ee71056f0394adc8c1e470e677f56cd4959d4d9e9aa84e0d88e15182d744b6f64662ed6c4e4a7cdde0f1392ef5c9ddb7c0f4a69298d69e1c7cde1d4b744d4ef299ab990c2eb1b1a7ff93e16fbb146941012173f03f988d4fe3481d6022a410131f798ac94448f86280c6e284f14cce178afa1dc5d089d739e64f11077125b496128434345bc195a7e64b2ad17621f32c9f397365fdb274d5a33ff56aa51f9fa24eae98074263adc8d9608bf4498f97ab7fb83198fe298cf8e7fc64367c93b51899f30cfa86c2d415ed8b3e9f41a3af31ff649667656f0ba3ba1248f6406866d669a4cc6cf390a8c937eb255a546f37e5a7318ffd36963ee64e7fdaa2fb999ecf0142b3d5975856e54177ad9c9b042208ff0fb9075cc24374d5b732444ecf8e96b3505d8f6301a4237a08f260819d0ac4afdbb97e873d5f42b4e5284dd71758a642792722592d63634c663cbc23c9688cdc37a13a26af9500cc24627dc06c7959a13fd847fdcdb3890d967399061224ea19a3203304b52d16ba0ae932c30183a089ef350fda86733f958b24f3bb4b847126006b70cf1dfd000a0ef743d3bdec348b5d6f92646511b62b0e5068b8739f7d01b278d080b7b421b064e84343f1e67ae23a2c0fd179271740cebde4464ed0f420d664e99c984dcc47f89f1d55e74fc44746da0ec77703ad06dfc08016a92bc7f228892ff87152731fad85200b2bea75cd3d1f5b1dd420bda641c2f305e0dc0be25b1013d2c9e328f9e0b08064dec0215410c6b52db1553a5ad99c330f41ddb2a3e9d09e533ce1c90da1422c636da61c8e77abc7905f51c77cb5101745a052f6a97b7fb5913346ab7245eae4f3242fed9d61735bc26f5318e7b04dab2640c56af74ccbefdc4c2240580a6a959b25e8b1d74a770e6d1ee0ec941efe0d595c3fd26cb61e55dfde2ab9d86ef190e36b5e7dc7476c22a4d0c342891ffe74678cf1b8f3dd808d1acc42a54e76ccc2233a54b2cbd0b6636621dad79360058fe92f593324442301cbd062a46b036769af911e44371f7d8cf8e168d14021699c7fcb68153c18267a0b144cebd5ac0db96281897dd262e0e4d9d40f891d1fcabf1da1a5ece7b9070c224681b3b99c539ca2aca60d1f55ba8d8d2d1528c83a64bed8a592bd51f6b76391367324686b4eddea1661d070f9546cd69d1af8ee764b5fdd58dc5c4dce097d440b70b0b02f6b5591bfc138785b914ab8cc8235229fba7ac292e27db40b03f9c249ea2d5ecf3201d09364b4b6f55549c93dab4edbcf509fd5a9ad4e1592e9972b3448ea88a6945336559566220bb11828a785e982e80b8a61946c39acb91a9d6454dc37925ebb047e53ffe354b34ba6220b3df753b81fa0af558b3587915d993848b0256cf0a90f64e614a8088122fb59497a39002f463da93dcbb769b4b0720df287d7db3e22f2910b3bb29359e62b8df7f93827a6532833bc5e5c859b403df66531422028976299aa4b71a797dd8edb31bcc599a8e369ff530f4ac7769e24d7e452147cd55835f52155d8fd4fb75620baa3e04a3a049011141fa9e75af926ecca48d6913a152a309926f6a3a06c4778a849c9afddb9223f446ffa161718bf0237126a0ba4be80dac1c93b1a25f1c7b88e99517924457e04aa7c0a59386ab53a13f63e1feacb6edcd41e2b22d54b39dd3f584f57e33bb7ba7bc42aaf0017dbc0567315c86ac28ffe6e798c91b0c6bd8ee9820884432d927dfc2acd87ba20c39322aaff8b11aef8054e4b9eb89d5078a0da13e52c271d31b10d077e3c5ae0a2845754d654b4c8ed6f0168649972f119be129e36d22008319d36b8b081c80a3941dfe08cc876a40bb29f2658006ca1bc70734e04db3aedbdfa3b86a12e4bba870e9a3dc4ae8b7caadebb69b442f8e183e9c19fd35b5bd04e77d8a1a0d8a38b3a20ec2162fd530a8811b15abfbe8363d24bbaa31359c5e251d261a0bf0714cfa3c6039f9aa33059506f11d60b7420e3aa0faa5db2bed6ae00bc17934e95e0d2ae08fe2fddb990bc9d2bd687f558027ac5898e74fc2afb2c204ad1b01345d74fa2a7d0a84343b5bc8555668fea312ed57b8cd3f376e06cbb372df601836bd7c2636d2435432390c5b308ee17613fb5784518025506711449e7c69c72c7e2b46ddf2b35505492d4c007f1ebc0730313ddf08da9e5a18bfa936046530f5a701a16ed068a52c4a6ab23695c5b9a1a2f5118515bfa45c7a93c1646695d4970ed04fb0999f1cda7d7d923790c0e2a0702a8f87d39a5eda9eba61a4dce03aacf8f9b16c1eea53a58bcb9c8a6da0d1b0506d938999badc73f04f6104bc8a70e29cb7811d125608b8f867ed264730ac1ffa4a5798075088092348a08ee948ae1a84b68aa66700f7e4be528dad6b5d912dbc2ca33411b23ef921901e640c75fa12ac4093be2fe4acc254736fa7dbbee92ac9244a01e258f127c8a61d92e2abe4032bf9e292ca76b0f0cb854aa52045b756f442253c03547fc9b2908fe205c344b3009a7495777d365544751fd753c6e7967e16bb4e77fbebb22e403a709d6a348f46a7c2227793a15ea648a3f1b15e1623af0911d8d9f093d3694db00e1cd4a573df5933e27d22f9bb450be8dfe5ae209448eea4186b4b15e91e4dca8d5f25c01a991f086bf2c7c393e3283895445487bccb51b42f83a4c65dcc3a01e50258e3084506faf29b75ac5370ce1c7ed114cff5f69f705961d671c1516261931c6c8afd804b594d242ab1ace0d260582926ad954e45ecb9299fdce92b3df8d40f85cc8c46e2dc0a0a7a29324615075cc01e1d479d60721ec50f217f46e62e15066cba26fcccae93209b5328557a3b8de006dbe7f7f75b530437d86f7ca7c46a247879972b624448698931211c6354117c82cc29251c828017e803382955229243f0a6b5659bca27fdee10a9314e96aaa29efd945ca220d7801e245baf26b234b08b90eebfe66db1378cca05f1221564273f03262375499a9107566bb7f3970d2f2a295067910b8168fb0bb6bd382ee92ffed8065a0d25ba4a6218be9b0a1e362fbea3390c9bb301d66dda3ca33bc0f585e3f6ae1ea09c69378774e0cf4625448a2c08805ff13b2543da75237133d28d0dd53d8a15582bae7542a8c2b7717801bbec88fda388521ad87a61f5ccc8e8fd550865eaa0323c5eaeeb63ee7950e70bd541f97b6dd3f7bbf64e33da629bbf9a4fbe0a32fa5048d12ae9336b3a5a7c302e72408c80eed5d26984ab1dbcc5f90f4e474d2e1f284b9302cdcb377ddb1037497e617bcaba838d9ca96e2970286a2a0f67f58e36f638e03c21fb8f93769cd5cad40d7fd41e2b2ecd64f2a3044f74ae41e3ca0f2cbcb2396f64b1c7dc5e76e2e60b9f8e8d891a2f2b1ceb54b83218989d695effb604cb46a85f1e74125fa3f909fb3e428708c508f60a7f6259391dcfba1cb84bf04cf93c4021402df6e9679194476a6206e0c3e115728fba5ff681ba79e7078113b27313802367b01dd40a69fb334e0898183369c110a38ce50610619646d8a66a51936fa09a3b21115ba041214dff0dc7831940e4aa80f0cd71b6fe2703d75d72d314471661d5de5425039d72c194fc6f847824a031616b4464eec74a624526dbb48439e07e68356c4137fe66414f2c767f6a7824bddb5860e0f6299271b35d5d8ad5f005f3d4fa18919fac4b2adb5e682de0365268345304b2b35eded08c8f31643dca6028b200a5290a2bbede788caaae4c8d84e94d6e81ae23263614188b503c3fc6b1d795b332c14b7c63c218c7dd174b35d6ca3abab323b6e69f7c7d0449d0e554ba00b515b8b8f1c557a3f1721b814ea5e2523f7afdf0b31b6d882bf049d6196d3045ba66255f427a79a3c64546df59854b1fe87d88a8481752b70f847db5da9e125c31a2acfe584d5df41e2b3db2cc9e88a8e4dc1b741eccb872d502e6f238ddd3c19da158628e3a92a222bd66e948259408a4f0b548f87c05393b6b6ddf75b7c82e07838862425c52daa026fe5656cc13cfa7f7c5922df6c9e896d3a4c15e9fed1ecbe39e5b3c607f19dc8eb5170bfaa3ed63714b894a39f372660881f1a195e1b3c8e47e8e41b1d4072429313aa0c8d0900539fe830018161e66cdc79eb74eb6d740a52ab230f71cc0fe1a80be1ac6d27de6e214a2554cb5900efd9fc7b2e576801b0df2c32e014d9307940b551cd988f3fb348e309a70d504e4d49d568347bac6e20e15caad55d037b067c8b5e029d587de825ccd8dce8b96ee9e8d82c7a1dc77ba277a75d93c3c551da74dbac62110d3c151d873bdd926299e56a6b5c06622f2390143e2eb28496227f796551edae14e45b7d07755c7f6ae0f9fa735646ead498d424a46bc89c16814f765a3327ccd2416266aea9a305f9d8c9292a8fd26c9e23a6214a373eb82549a4de269e5fdf0fea2b4cc9bd884b57e68c3d655893fe36b5a57125906145ab940428859e1d275acc38ad2982ebbc93ad7ca571473aff5295bb063cf90f120551423dda82a84a2dc0eb0f10f45b1b58754d53769685f14e538a3e8bc50ae8f92f92e4a2c24f485ad5c7250b9a1cd856dbf57c72ccc4ff145d9cb69f8b5a46c4c7549d0b509f69b847a7d6002f1db9985025d13b26d6340550da09c8bf3e9086eb5b87092e9047923f6b0b44b2b3e24a61f81f1ad3084c3d2bf6658bac443c09c37e31102227ed2bb35a14175818ba73fe90886d21efd49d7cbce2e9dc3ad460abe63c3b6863fa1c0f8ac231c65c6b916e886505490bc39cf33836f3c4f6d9120c93c8da2cb30c3c704acb4106f7d14d306a585d449ec32340c6277dbe5f04d08d0032e073568725e210690963b114c7c5f846157d0a4b3e7f7afc6769f34c1cab04bac40b98a941b9cfe8ede51e7712f06026ea38758196a702107cad2d58fb2c5218f7e7bac0cc16807ac817ca1bfaa86845c12656e2899ca9726fee4efde3a3f875a5947943497da40316465046afa8318430e06500c4f6cf830b46b858521324d133d931e29325c4d132f0f8a618774affb9f752986b155ed2296c999869119b73516eabe1a3b91396ef89d50810e3a27c27b9566833e1717ec08ee8c745812c5ed4f42d519c563a9a8f152a00c9581b788ca3897a8048831628255fab1ae079e9525b594d2ad5f3edefeec8fe8a6684751d7e8244d007ec4d9bb69bb48c2b09a19b2ca28cb15524f57598427f83f8147bf547d871a8f3590f8f9bce7e76708729dfad14e03344fccb0ceb694bda3e010ff86a7a5d01f6637944444452ecd9e7029702fd97141cc4af01c648236987f72a3f29bdee8172b0ab8cba548b104aa3f7dde2253df8e0b8e0293300b8cd0f2c0710a0f99e9172f9f6f0065ad8a8c83633bdfc0f0cebe9e4c8a45778a719624131ee3a6994f71f6fa0ee8a0c7671af1c89773a859d008f5bf1c0a19ea30f55351101e60575fb1c3c9a60756f1a7582bbe3fb82a27b0805add050d2e6056978e72ff0a396f20b253f8558aadb0561bac25118de01e09e96ddf68d05b8fbb884ad24e42070da39539e44225209112096d395bd3bc9cba647f30910c2e3150065adbcebb97164dc219fc23e099e4944134e029477469c29d32e85fa2c523fe5d32f9afbffb0c16c13bfe845e8314c94fd5a76a1f7d9985d09774051f2945fb1f47b5848c26a2f416841ad79bdd821166b8ee63a106859741f60b162fdd12722ffcdd7e089ec182fff838d7d6132b7baee8255c847ee79822c7a43b7bc0cd5edde3dd7ae0263a327416162d448712743618f8ebf0b034cd59b213e71d26d01b2fbd5901d3bff513e09b9d003a9f00b180d9086f043ab79d419d5e9eeea753dca1c4640c5112ca7e955c4c3ce0cc9096a9b1c41893922d60e826fd4aac3ba5a7b49b212a8186914136f98e4c0d3fdfad389745d884c4e0d8452a509f2a39254c683da7718a4b31972283fe22571f8c0b7d857b43f050b7da0d96d72658c2245769d48272b4e3b05d199f67bda37daea8d1af79f1e8d27617db01836b6441c28168342ace009a7b2c190219523b15e1b951d6bdc930a8726605a8528793e36ba6ec3b04ac9c068a37b3cea9e465137bbd1c7ff23b07ff92832a64b37ebd6c4ebc87595f3acb9d21ffdee8ac5ec83d4befc042de62cf37d3e9e1215dbefb95bff57175007b4566ebccf0d4b3011fa4578f0ace77143611c857721a84f6e1ac6697c8c97a2162ab142f4478d7c4988e1f24bedf8e4ba4e62c68d7f6814f96768642ffd9aa5465bfcfd890c48d3cdde8dc9ba215fed86e52adf9fd540fc5aa624e998b8f67a09fd8e77247b26c84bc2e31bb613201c13c0b2de9ef55bdce787ad1a42335b08ccc4bef58935ec6d978bde83395014a2b0359225ea3cbe1e7f325e53519d76474c181d2e505c64c8293d38c105c2d08660462c7ba9f4d518188b9ee105d5a602ab68eda64354022d264b8dadd649927c676703309013bc58056282951c700eb3da1f73de6fea824cae9100fe2a059f2d3c912f0a31f8f3068c372bc9b2fe94c1f05cc6bf834769af7622f0dfb8543d3e0b01da2a7393ede3eab65f5dcb1c2d7b5e4de0eb4735869f7029485d8c7c93fe78ba16f080c40e48f81f781c043609ff4448cac8260df5bebec17a5de992570de7d2bb14fbcf07e8bcd4e48bdc66f03cbf8138ec314b04ebe069d950d34154418347b3706bd45f642d290f02aa430635c8e3b91c8e3c200e4a38536d6d6236446b7f51346f27df28ecbb2937e647482f91e07db04fa3735797413e97b732b4e3d69ece834be42a681922ed406c5f67b5950e2e40b3237b09a827b6af0d4ce51dbbaa4671b3d586ab0f1f4635dd4bbb0bd61966d1bdb9eb25e36a9413f7df3990047c81b3736e049cde12e79dcdc9dacc14b38ef6832a2f8cf9a82b3b66b9f9800fcc95fd3b5e047a09979c76a0cb691dfe9c4dd4bb0cc0f6846bf54f9b666252874bce69fcb99ad7d7a1b8018e18757f91b5be7d50986bbf452b938e119a4189b665c1ecc759afe06e46846550b07add9440e698357188857796734a15838c7430123193ac2374707c3b1b7b61992022c333a4de4b3ca0182195a48da7d57a08a4e6f1524a015723c34b8f07ed21c7e18a547d230083fdcffb0d09a054fe441d475331f1d9e068070db0cd5c6b54b20d81c823bb33ce19477b2d19650f30a1782770ff33c5cd448265da07e0a8c8a007bd5a4f2a227188d382ff1b467346d780634cf0c3087ad0c9f5b14627e044071a41c71aa150d82586fd7e62caf30da62058c1dcff576096f890023a3c7d4716b3eddc368f941b30d6c2fed0719f452e3a09a5134ed0c087f6c4222ebddd115ce668847f107c4d42b1b0e3b22ff60bb86e1d3bd3d13b07771b8d3f7a33dc5459dfd4d77293a66ac3a1248e4a87a19872816b36ecc7a5a6e63630b43f2fc1dab3cffa2ea858de67985214f213644b40728007666851882145803ed21defb3126c5c0de5492deccd2b34be44f1a3a0d0fd04f67c6435bb41d33e8622f4439a088331c91bcc456886cf5d1a544b7bfca7cca52927d43c0f72599e41bcccaf7702bdff63102f6085ca12571e658e51b57cc078df03c67fdf03ec67c5609baf4bc7ce5a27542620bfc650d4d9492bc5b485d533d87f70a9dd174127c94f4eedb1ddb3df7ed5ac5cf6f528ebbddda04102628c7d6004163befd5f9211063c5c1813af98549f8cb475ac18e32aa62417862d385735af4bd843f435ee739317e5c0adffad88e5fa787418dd33ca4b545e75b75cfceb30bf11545381504ef651150e606e00ec210fe0227b45fc4669aee42f51f5a011c28602c5208adc5109587bda4966b19b97d64f91a76b08a366b8d357d9bb44a115862ea810ce4bf5282230842fde044d1879550b8ac0cfb5dca4627947b6d2c0415a56d01d6534834ff923fb7a04d949d358d463a5f0cec78c9f44ad870e92293a707619bc43176e4448facbc47a65b54d4c7eceb97319e0574ffcfc79ff811a41db9669bf2d63b2627bd5cdae254ec317409f9773382c3706725bb2a489daac5cf10a00180a661ebc02dd337f85a9810316c0075c173d0d50bf81b6c3d5ff0a1159077c5a56a50a2c1ec88581c1cb7d3b5591fd6ccb4f5455480bc59dd58a5d3e1df557a910934775307b6f9f0c785b062f774659470dd1ce2d059b87337d26d4a78811193b974296ed8b031f05e3a819fd8d0f7836b84a02f1986d2805f918e56a9119df0b6cc0b0c75c1322beee6d0ceb5a15115f080c29ddbbf027b49702d7b35a2971f87d75b4cac10ddb8da0687b5ea9bd68326c30f901264453ce8bd241c7dbf4f8967fd25f58b9d94037e67b5d09bbe6b64367b99d9ce7298d1e532f03b4301f89ba095c452439b24aa8baf0dcfd3478c6a2d30b6cbb3ce6db65db5fc487fb1d47e951db5617506e092abf06734d244f4266a52472adc07f0de2e58581493cfd5f5854c33ffccfda601a1a9ce10b3d8605e0303fb4448715820eeb24d999f2ceb82dbbf5bf0c57be6f2a00f20597e38f715b7762126b630d4a747b2b55d778d6b34e956d4e9dca1252bc3e5cdb17635c67381b7329ee1c22e2f98599a86531f2d0339ddac19cdd024eb63a4c37a5fe403099245bf3473f4167430b4163943f4b93bef6082e4f2a1906b06e778f383a7d4da702b1c1871db52d3e6c389decc373963a53153dd4bdbae5c4bf2f5e87883669840662d10134477ec1ae32c9a45d00cf7c34bd2c258016a1d4b8c647e0024cc4ec018e115d975f95da706149f7ad3d4549fc0f5c275fc9e7afe6ff39bac0489693a1bd4a57ba7e566d557f8496cc895b4efe234261fe1f519a5c8904543f4db6657b6af538295ba6bf761d600dc409fcbfc12f2f7ed5e83ce21a15512228068fb8454539fc10d80956049649b4a4a34ebe39f15c49200556640798bb1725cc355c61a4e19b47880e4080eac53658046b457278c2a50fc844118ec355c3794cb9134ae19aa2846168847707bbc8049f23ec269d79389d62c19356d93790c090e873090d145350b3725f30474298b8e13df8cce75fe736fdd9ff597e525083d5f10e89ff03fc7b0500abfb8ec40e717972385081b869d1f6503f23883c4e4e81b799648349dbb5936093c8e91970269fbef7c25a06a4c65992cc62f0b6f6b37539dfa193d41f069f55d24b959a8171032f11d4e80c524c171f72baf8428116075e8b0ecfdf19941f4968e339a73c51e6bdb5d8a1769753e04fb990bdea69bac48f99dd06b86413b811c89bd9fae304f57bb2524819e38911f20706ebe9609bb5db4903547edda05802816b72adf97052991fd02ee8a52c2af5833bdc90635bf6cbc473016461bcfbd8d23c5ea91f7c845094d2caed964dd81fa84c0365bf45cd1a4fb310d2baf92d7de3fb6ad67b3d0ac76841fc2657e75c2220520672c7fdd7b07c283cd8c6b4ce4efff751ffb616749a5c572bd77b956e0cfc37f38d3ffb8bbe3b845981af0431b5d62aa84f2b156d01912f465c538624fc401d7dea24f4d82538b8f17b6cce1642d8c9a409f81b526080035e0cc5a9a0e633f5610620f30183d80e9bcff9119e003a6954340dffede51cd032d5ee06769832fc4493af0e97d4361b1ff60fe962701d57e3495ed0e57ba453e3a08b2623c7bac66832cf0ad8ce9a56e359b547ca35d74098ac89541219aa447d368b3136a572cb7bb1a425a3d0e245b5319be360cf88bba0db18249f8be1c1e8cb62a523dfb8c49b5e6f883af47b0d72f540d61cfcd8ccc96667ae1f91c474cef8236a389a9d100d48ccc95ee0b823645f0c5c2456a98b34e351da828f7dc51d535695f4c5a8f201ff3c7796e968257806b2307d35c1b0235ca8c52c55ba3de6b0ba58668fef800999484f7516c7e1c41c69644e3acb772445510e96f9a21ad8d593179c5d3cbbb3c779ca5552c29ab3aa510a9fa295135e880749a391ca36c8d9875031f76db684ccb21601ffbeb8fc4b64d94681f912a09d0080ae50c3a8a08cdc99ceda4d5f5ff431a203fb80c3a0742da698bd663a4b9f757622d3eb6d0b66e3487fc0cb3479f12d1932cc62c7c2ed9cac3339cf1e56152b07513241d7207f8562c7d7ae33758f3185cf870b62232c763a93ec7e14d2e8314a611d947c04df369932ccc4869fb341d452dcd1f618e75b4b5251875ac9a70b19b7e31b6459eee263f81651d9c782cee8215268190da4e59b970d89c56205188266e37f099f9b6d427b78cab992c1d50f78c3eaef8566fca228e6c16a7fbbdce2b8e3c12449153b49db843ae5ea8bd45ff5e4eb876f492a0e15f6a0787b49f170c4717cb92988e42bece588e4ac24485f63e0b3e67acab7b7a1bc5ceb863d3267d05d0606430b280179c580ef468cd002d54c08d189a6c3e74019a299b7b30f81df90fc132fe5051bf1cc1704769dd980d4739e0d09243ee576771d7c90b10fbb26d004076a6d80535e90bc7ba484a7564c08acbf0eaabe6b9d85441f8146c0ee927116c33417f03f480c68d9cb500764ed62a1078d44109b59cc43596e1224a3bfe105223214a381a810c6c7bf5ebeb1b8d1ef008dd71dddc84f416a539d3f0f56c26c91598e3ed1d00d47db09cf0dd9ca4f1d2767864b4e72956d357e485cd0a6ea6923d928adad258cb8fca79c4e63415c6942ac2721a6de4811f7eb6c45990820ff7b9a3f4b1d0118f5d30ea73545ad2c7f8e97cd93fcd8e8572ce9c65371472b2d85ed9eb930b59eae0dd5d6ded3daf8909c759b73714bdddec987dcb9a181c354449503c165a8605db25c519a6a07b19c4f4be80fccc9b96fd00b1442d5493b925725d0e406380f5a61f47a4cc33bf77081a8536d635f6ed380827c292b9ef20fb2e486473709eb975f11522920759692bd42b35cd17a08278c076cf5646664de9a01650d225bdd8ac1a44103b40fe1ee82f5ad01c14919694ab60320512ad2a909995282e18486b031539f50e6081655e634be7e5506351396351448389cc8e8b32dec3dd40c8a6f67d2a710fa9b24bbe6e211790a6ffb60e8c41aa1fb8404e520af1d7f40bc2e0e374c6c98d959c1458357f3ff8d4fb7fcc1cf5cbb4bb0299706d1b3205320a1c2a283207b8776a11b900c16535375bc6e28cddb475f89afd25dd3c159ccfce8593b6fdb3989f5615f60a3054d8cbf863fbba8307ca1aabb7f469baff061141a6be60798c764be691b076d33dd6e3f6e2bb26d5373d4be3196f4bf12cb4104edfdd5b7e166c599c30b56c2322fbbb66c21e9161d143353aae68654d5605f87ba886d1ad7d39e9c48564cc98f4fe86854f81bbb232b996a332048e1fa3b6e6aafb4b740396ca46bfa38f675d6cda008b1d9e23f50031ecdf8e9d427887f8e419798931beb3df7a771963a5511c52f6f439e91048cb9345cc3a47cde3959aa837f98f022f78eaa726d1089b8026fcf2e42b267be6246af8d721fb986618693a15fcd0d4270a91b738f8e540f22221d622778bf20a99184cf6ddf264702c19d46fea7ad6225a18ff6c169344046ef932b062459fa9419a70af58ad979565759a6fe59dc63864ddc5d811b9e93b18c2c7f8549dfc0ba8c18a0ffc093386b8589743c223416473cbb3be5d16b90c8a9f170d1848df34b650747e5802227089052a02e11dbee52bcf723999e1ddc2a4ed7762d42321de8e067d3055e836877e1e8b768b58be8d0f1f6113f5fe434c4f12d39989f37b456a1f71fda15e6f6768b128c8ef4e6d548ccdaba6733ff6f97ad3b4677abd77684a0377c6fce86de6f08289dbd8475768ec2ec0e9ff5782f03ee945ae40f71e4f1ff03838f980cc6ea091e13a7905c269e8bdd7341725ad0ad9cdffa57564f235e391610b6f4c0b85cd3042ae39f17a6ddb2c34991461c56f98900db119e474710ddd7e1bd4cd7f4bf51503849f939c203d5c4926a8a49a9b27db98ff0af7cfc08251470c8e1cfca16490ef644cfcf3ac63bb3ba27ebeb2e9adfb48b24b3bcd0846f302762ef3212f33f59afe1dabae57a3925317237fe34b501526e451d5b8838cebd1b98b9919cacf9782288a1c3c9ed9c015237244bc855e9b9acf9d8dc9dcab85aed56dd71d3e15be15f12f3ebfb3878638a75e422411834fa08ca6a66e6aec30bccd0bf8e13bfa25303134b16cdc0c04ad579f8d7420728131efb0ac977aee8a4e8a2a79d68281f7d38dc4d13a37a8e1f60ca03b68cf98bcfa6d2e693b349ee2e735385cc0f57e9c0ed023aa8bdd9b4fc12671dfcb50484e8abef81f8f16d1a8c8b5c22ae6e3de1f84e4fca2299995a8d4df7b1d584745d7c48b6a8e153be6c533add27a3231e30fd33e3e6b9c0d52e07320a3085fd89c1f63c031014fc5394e83a08f3bc708f917d780b2ce929f8863a88d1f3f31118ea734bcb166944b7a5541dda35e256fca538b3869d6812819bd8001c3e7e01b0b79181b3d2afd45ecb6707921a0187e407574b7cf6e4ba8875bfc4d5a70b113b7a2143c3fb1afca6c92a5c8e522fbf389f0d0b4aff2c8c0536ee8481a59dc981e78706a2cd1e0831ab5ea239c109fe1f33800d13819e18d6650b494f503831f2b5c6157cc8d5546199b3e6ce12c31771928b550245f4da6f021e905273a3b5ddda9989ba9ce6cd4a45dc904e2965ee6c153412ec0a8923ecc66c320cd9b545af167ed88970e644222a2b13e185c9d4b3ee8cb1fd7430576ab1e1b85c6bee88fb2383d26e0d98d9a7e11faf90593594553d6e3189c6c2bc2d914f83dfa78254425542c421d622fcbae093f537d92c988a95098d41a99eddb7a1d32c987e208dfe7b00b43a400ab217e25ae8045776e34b7dbce26b514ecaf8f257680ae2198e20c72850ad6c28465204fcb80e257ff57beae6f33634afebb99b17fee3f062c240fe35bdbaca5a69bcf6e2465291becb26f0c14184df1ac6e5a26f8a2933b080eb4ea55b6043c820289803d0d304419944ed030afb369c5920ccc29a0e7ffb4b1139f89f88ec9015ac404149f11fcdc0f3a9f715ffaa9b8ef6436d01283ab8013b9f0ebe3e786f60f8c522375dc0782bf7bbf858388392bfc74db7a4f0cc8e75df010a55711f21d1dade7bcbbda59449caef099e098a09b4030e4c0dba0318f4b86fc7204d98a8a334b88b27e7fcf482cc0e4ca1cebbd187d6f05dd218847ccf351ec63eb6f6b1f9f868d094a9631ea45cbdc2a60f99ba6ac6e143a65ee6eaa9403fc8fca1ca966ad68ab38015db26d7e4e9f5e74d56040b2e93bf9f37190c209a376d7cc8556fa8b09d13e73750d8ded46240c00b543ede3cb57218b67ac828f22550b794bb9fb63744bc17328d9f36376a389a1b3452307982f3116c6c68bf4879aa36b438a4a21b281b420196f4751ea447757c85508f1eec1e2d589bcea34bad0b203841db6d6951e5c4920bcbdb5dd7757325572d8ffbd54b6cc5d2fbda5388e58cff66538e72524010b6a6290eab2ae378c96dc0e943bbf62c6a8ed39991814f47036d3f0f7cd692364893765695ada760adb5d6ca39b6ad300ca997214e5f8e56967f477076d13167fee868e0ab5358ce06bed209bbdc07bc492bb5b76fade40fb93a668dd124d2ab607bc8b4d6a69535eb9480211fa1e6a7cd4d106038a0210e9abc610989c9e64676c3d41413028430d9da4031210089ca471b1b277a0eb1ad8d12ef082826ebfcb4b5a1e16b927b7edad88461858d14900f3651d84e3a8d7c4fccc588b73f6d6c66f8d255cb015b8c2d959a27784a7d2af5a118727e9a0026c89a25585fce34dc12ed6d6c5a784a9d3cc55ef0a4d336abb4bce7b68306f056f676fc6e0d920e7332d03efcdbfadbf3b7f4c148fe7a2643eaafbb94fc752fa38bbf3eb178320054318babedcbd6d73a46ed6bd50b63b86c548c0795fa238f7665d06cb17d0b8531a52521b3ad1d31b46cd1f196030fc2b0f2f689b76994dea6694a93464d1362d02086156fbd67c5c33e65c17911411146121855bedd463e6a920317525096988c589961986c01c3182688a8e185d8ed0825e0e4a1de6330a27ca3f9f2edae158fce4aa4c135ecc4724547105513aa32689cde9e41f3d677563c2cd995cc770fdf13aabbbb69e02b0515938a2acca4c04c1829c0724687b73ecde0f0d65b2b1e96ac5f0c91c30c9a5b33a8135f86ad76fcc59b6fcf65b07c91c4b7ebac78b45f11e389165964b092056725cb96334852b0c316313b395b11523890e5928c512703854c18df9e6382312978ebd67ac64eb4702693c986e0d8b2e782d98107f38a0562b24cb93085c50bd21499314cc68811d3f4d6592b1eb64609c4ccdeba5dad78586c8414182ac539d65ec30b32be5a314874e1b236b76894174abedd6b77f5936fffa0ad10a5c9643222b1f6136e2b1ef5cb568f8f01bed431afbcc5e203f0d6711ef2d6ba2fbd75b28b29de3a500dd306262acc0e6f6d6150f0d63b2a3b801c174e7cbf517261092d573871a22156e6b77506293e80d800362e7a00f3ed35efb8c965a883dedebea54294d0f2611a5b44f10903de72053be7f82a613a763c1a8d60f600ee5806f9b27d051ef782d7762000998e9d84e97805fb1ea04f9da49e5d4d06ac3e7de8ca01ed75ce497dc6daa7ef9852e4a345b2c2a66fa05434ddc774a02128236c5e4d389f31ec835267c188ae4828f1bb44921c1287ba2d206eaafdc0df0e44fd46c5a697f969fb6943c192072910100a967e9ef969cb82c983363ca10af9a830ea18d3fa260461e1040cac40a85f347fa8ef4033ab42139830ea6398d0d0c8784a29a54d27cc1f4a9dce28d35293b32682b00084f38e930ac202f5133030c28cddd188c62875a9202c9c8001eca56ac0467d0a0540aa7d09362ac68d4634f62a811b41e7dcf86a52c50220d57eae8070def5c4d93991f40adb31c5891b4054698a4d2abe42a04d5e40dc8e23f0a377c01d5f408c6c54ccfa516c4abb09d7ed68f4f2185961b6dd84a10aebeef6221ff50a70fa800250d30dfafc7c66db00af1246f0ba4e634674c626ce952a226a8c40e28490d83ce2c1882190a2c02287375562d3295d89784e994ea98b06b63061d387fcf4223f8fcc2a34674cf367beaee3d7f5797b36bd99a67773b3919a68d974ffd07fb82a6c86e26b041ac33ba6642f6a5a2bc7711cc79529b440914e55d8f44fa45415369dce3c912655580aad150935864758552e5b06820d624809ac3cd7897f53687d259bf46972c6fc89ec3f9b4e99a653194d22c1c6a8acc26ca0b22a6892b400c40c653029e36b0853c585162da4886ada4a4a1732493fcbf8d965cc0c25d82a62af12ae57afe30838bfe3ab89f5195b01b9ce8d46afeca2362a3663affe41dd04273750fa41dd04ea453e80c41d53f20fea26502ff2e13293ab0eeef9bdedd44f4deb262826496d1dd4454c0ac58cb2438b132aa7a9258e28812186202d84ccc8281903cd2c877a636fcfdbed8a474b7962d3443ab6d3fc41937d727152a6cc1151415491431762da1cb181091cbe0c0115e52283fd5e7f62339a5061d729926ebaa49d7494bf48bae99276d2519a664c3b4de49d1d32155590da18e74c674da5a672cce415f0bfda8fbec71e69ec3afd32df42456db014a40a512e1376dd8a317fefbd146afedc59bf89a24b155074a1854decf6586209544d4d981faccc98a4907ede7edab450c288c630b043432e291447a3b0f320efc540855ddf39229714ea557d7e57e713329b164d7f6d5a3885321b172c487f6b779380fd8563af1f9e7ba3118de50d947009cc341559b3c6898b270ac870860c97304eb520305085f028b351b157092378b96218ef98e23a4a42cc932fcc243931839879051432a020328312b42f5624812aecfa8e29a405c090d1a1062eca04f14206a4b8b2660b106eb08cb9de891ed41168b9c28b530b5b940123769d4e55a10b2081c35412a726c86013bb4ea1aed3a8eb265cbf6067bbae76d57e3982ca5a6b81582d45e2072d72423b332acaa68326940dc9426571f313ca56e6465125ca9734cd771ceda64d1b165afe3a5dbade4b2e9d3dfa20b9d47a94ec0891a91117905a782cb035b9a783286d89e06a92d28795917bdaada5e0b4755656b533dabb4b9fef3105f24370d6f1fef4a15c378dd642369c5a8b1569eaec8a215fb693d5153d7cd94f56b0f9b2afacbe6cdb2cdb4b5b0ad690ce0e3c405e276f1d36832e1093b47e671566b91a6ab1e99dd84db35a2fd6d25a9aa4750a579ab45a92c84db38dad858aa50bc796adb75fa6be4f79bc4f55c8424d226ab34286b747319bbf022fb2f5a2be6dc919387b6ba57269a55e69a595565a69a595565a6975ab855ccad42fa55e69a595565a69a595565a69f58ed24a2b6d06f40a07700ae54ee2645f8117b93da90a35adad8b09d35afc30f9caaadf79a994f3cedaaf54ad46fd2269a1d934eace28d49dd1a73ba34e4d43482da53ba34b570bb994dbed0fa82a04649d4c4d49494545d96cb5a156aba7c7a7b4b496551895aab0f6a929aa1e6dd9b4a7499c8c13038b824b2dd6e2c441860f34aa588b946a0c07554011156bf1c524e6519e20a24d911809b292186eb1c748ac8a465489101c9c8891c06373b390614d9418663112d0d0218667ac8a46193c6d998a91c04b32b17013aba2514745c1a485180974c2c4f0ecb86bb175fc257d7be50b13c8622d7ab045ec8892a0bb8bd49e8ca4a7636c9cd27cdd690acbec407d5c7af8ea447cd9a3044d0f6dfe54bfa26da9f6d4546f40cd9fea1b5075778756855e691a56fdc5a609c949e9e9eb52edab23b17de5a1417d75fba26ab2f28839f387e32ebd33731bf8bef49b7dcfb0cd9f06a3020cc54d06a52c5fb2f7f326839030640303e9d3cae10c73191db6c2f0e74d29055ffad4aa28ed31cdf20029272a4e4db208c309342e484106111fd0d4f0a60c236a704fd42f5e130886016b191c55d840dcbe2b4074b9941652a4ef6e3a4ba28a6f77137c7b5114df7ec215df4e6561682011ab336abe582b5dae008b7073bb7946cd19ecf597a20f7c24a093784d383f6f4ab3c73f6f4a49989c445dfff486a21d746353510dac5b6f2926511d1b8cf9631d29770e4eda818e0c8c5ce9ad5d27b91bcb29055561d6738ba9c886aa426d73a67a97f5c6cac4db2aea30936d94266dd7d5da75e375ba4f38aa72799d5ac8761095b57e9deeb55da7fb842f188be7bdf7de3be7b5a30dc725f2f40040c973d4d1443b2b8c6c7b249728ad9aceb324bf9e3a493dbb7c641904544f1dbb7a6e4ab2a7e18b004e1f1c45e4e9e0ce955c9b44fd9c774e39f10584c315463bf105a4738fce55ce6cb2c7578fb9a549f72ae19b5ee25f61d52da250c7570844df4ef4ed28dcded2446645a2afe2dcc284e95b0c42f4d33ff1554238820f8baf12b8199b2b1340efc61790cef38e1b4df83ee7c617100e3b178eed5461d45def409f17eb620280a1d650d43b8a7ad7dad652b72d199eaca41de08495d6a4a8065626111d9b8bf9d3de4438b5c93cbd342c357fb6a022e27bccb7535cabb0663d0e37b9bcb41a6ec297869fe60fe7458d6bd8463ba8de8ecb9844504ca1fe62c2aa680775eca9f10302ca20031c385eaf19335a4a079a5cbdc44d4ecb4ddfdeca21e79f5b9c74f91277ad72decef425f9b88673ae71639555d8cf985ce237df493d3acc789d16e01cca9fd36e6badadd576df0f07193b52447571818b1921ded88022250725901051a2862f3b5772d95ffacb24ea7f0101c1f1052474d0c1d18885e347e30b08e82b5f8d462b07a9e388fd34cb25d0c415461d0794acc37154651d62ae30eaa0083341aeea3438c25035550b1540298818d5d30661fe4fe5fbafea56961cf9b902e17e019482f896fab2bf7c91e5fe52c4162e5c94b2343942060b381c0993030d424ca1c5a8030d51c7b1267b1502ea14c0a1a17e2ed34984bd558031babf0f8b5fb93a817aa8cabef66c204223c2649d9e7a8bca909aa4159c9e83989629b48aea87472a6b92264da82160867cf1af2906272f4364ff8d25d03711a92f2d139128bb24871779de862cf9d232292d3df5f996a983e62de9e9a95b241d44b34b5a68f230c9a5556a0310c92aac90dfea307fa8db2378e99394946ed8b2770582e75f5df1e038da752050bcfaa95cbd498c572090abeaa0adee7935002d7bdf58e676abd4413dd2a4a50ec2a3cba7059e2539741f59fe3e1ea41ead819af428b4770e7e636954f51fce5b1e1f726999aad0caa914c839967d478d5063abb1a32a2872582c5d65957aea9f98424df250f4608526670c526f999e3a759ad441b718a29e52cbd441f5732c7e58fc92be41ff7a889f7dce8baa1d833439cb70c6945c1ec98e5e074f0f795aa7b059618079a230c309740803056cbe300181335f348961e2a48b2ebe3863848c10244d4c64a4a727a2928af082456cfa340098a7d09cba21298a2ca40c518a21832a4c58c1c5ac4c952936b22c31051a318c5cd962819b35557811449a2732e601c03c8bc03ca7bbe6f439f1fc1b48a976dc2d960db96c91d513e0f2f1a3d54f4bd00ee6778d88eb9dbbf097ae0a8e650ae4473db716ea49a072d656d6e6385c811ff5f6dcfcd0973eded2eb2288e088162f9adeced7c0d0dbeb24c5648b985a0000055255d4ca43fb841647a0a5ace432dfdbd47a9fecc18b6bb95aa762e7dc01debc61f3d8cb233c7ae03ef5403f1d51b05e6f1f51abf5b45c3d3a38f0dbd372eda885b75cfa1f00e3307fc9dd5e7c147d4081da7d586bb313398aefb00553ca611ba9d0621cb20d2d8e809413b9ccd6f3fb1d2dfe9c86b3a97b8e02d7f5e0466cab1038b368b9cce50af53dfffc3ff7404f0bddb217e4d61329f53ea72b1edf58afed61c7b142014435d8616be50009b035459edf8222b76cd9628c318d1772254dd8e036062a561d08d7d96a5d9129934ca9ab8500798ce41e0f481fa010891b0c696e309479fa27f014c9a525eb0d02bc3836abe7d94e2877ed1dfdae1367ac1b5763b2ab0a85de6a2e746eb55a3908edab951fbd27862bb1ecc250fc1cf4a23efa6e85fe6ff46c9374d5d129ee9e40a431dc41378b2eba9a74b1a0b87868c8399e1dfbe79d6f364cfdbc2d95f902fcbc2d397997e77849821e3ab52b1e20cef812013b8e83801dc78fde134ba3f79c25aefce83d7185fed548b9a01a805e412faaa1689bfcc610fc7193dfe8238d92a953ceace6868033366badac21f2bc5ce77d843dec796e048e1e38aefc288647ccf2a398e7b30ab11c08e8acd168886ffc4620a0b39c351a81e351cc0bc559419086a018760b63aeeb3a0e7b1e65003931b6b8c72649ce894dc019febc5fac6c7e4965162997f9c3495455a05f65654df3ed354dad92512ba36e386861d16582214edd90cec9bf7ede64b75ffdbcc9a87801821c38c9d44bfa2f22ac8a02b069cf6943e7a777dcb5239d44768573c5096b9c6fafaf21eef3a759dff5415bab1a106c9b26fb3439451a0fd24b45f1c17959d5bb667b6bd33b2fcbbe42e8923a68ad9d1546af7bf68eb8c226753599265b5bc7b906042f11b0bbbb5e2f6abb33d65b1fc499f58e19a4e012c9d45d44ea1160ad5583202cc5f124e3789229b66a32755793d4aaa9b5d66aeb9c3f15066bb9ea9db5d6a78e41340082eb30c6def77918880e7bd85b92a92fa11db73a733def068238b4ab5df1e8b0e77d383838383820d8dd79ce89f3d5964c07c0943c6d48c76e1a34582c9c9c73727466b45a3468ececd4a8e1e25c2ed775b97466b45a04e1aad5e4eceeee6edad5ba5c5c721d694c4aa3eb462312b05a3834728dae5123d3c8d9d199c1c35379789a6787c7468d1a2e170f8f0d1baf574f8f8d232cb0c0e5e2e1b161e3f5eae9b971a3027751aca2288a3caf1b53b4312758e3e5ea693ac5320ca758ce3274e29e5508f6f1fcc93c5a20d01b2b117a2ab8114ed102718a2d529167883cdd330f71ec918ee3e458e5118eaf78547babdfee7e6f52145720d01f71b47c702e58f1e021f75831c00083c600038a010e1f9f0b2ec000030000802461301f9ff0020c2806175c70c1aa477ddc2406380058f198244952cb2a8fdeeac8a03320613932d0f113000d6030b771448e1b15e4c86181e7c89143b49123074f8e1c3910f0049c3e6537d563ceb9ea7342614067073e968a85157c024a28556295dc6b6f951f943851a244c90f4abc900b9076b597ebb0f781d97b8ae2643b88d29ca9439fe85393e410d608671582d599c119e1ac58a84262ada84ca6449398e8aa099d5127b46946ebae1084aa4523b4368526fde9538555e004fa54b9d14ff09d59e3031f50d3ca97f4a9898f264510306146d5982eaa0368a84b2ad2a7096b9ff469feb40f4fbf5a611cf6ac70136ff2603594c4655746ee19265f027d5d78c8210c1e96b00d3cb8e041c91e1b1d3288a66bca393f6f3b48755576884a92c19fb71db65c2b72f7f3b683137709679e1da6c8b003c6c9b543132334a26aec704391d6174d3b3b1099c145158d3274b8806a4d19c931f38587193033b21534642f643a5b9470c8d072aacc5864aa32122356535138487e500ac3d458488ec8008ea9ad9008b9e11b330bab62f0cad0c02f64c065aabe2a96ba2fa83c1da248e26878892297c798aa8e08cba38b280e08df74c081a9020d01713024a65661938d0e5e4c7571248c4c8a225349196797fb04c1d4420e37844866f8a0b2fd796b81880e2d94200d1bcf4cc63f6fb2344964ba3799fb799381c9f1f386a4830cdb4c3fd3263698db427de8c81a0f7a66021c17b63ca9820a9a11555ac43e31d4acd12266e9a685ca7220f29ddb0e2200eea6ac055f86f8cb11a44c935062662af3bcad8e99baf8ea9389962718247670e2c5912a605035fd5147af54a635294678ada724565d0e31be9db34864796b2d0dbaf6891b0e4ebedde205d850440f3330863c01e648072e45543de1c54c0b266254cb116f306daa42ae3a96f85d549e522b6463d4863718f99ee27683986f6fa32444603123c614267a8895407f5402284c9c481195248d1431eb449b2a8c42612d0740e4d2f5d4862a1b5ffb9ac210739cb7ac58027d99c2f7e4791e7ec2584a14294f2ad815ec6d9380f943adcb8531e71dc7715d11c7dd3b663cb1d892e8eecef3075b970b634a622c86b8c3d8e5c263d8e4ed2a57dd76d71f4d7626ad65e1337eef3bccd7aa30b71c3d1b10637a2fe62847db67938dc50df2d4a7c8f3445ec1da2d6c6da7d57a75b9aeb52bdcc775cec979d789a11583a3fc3def9bdefc3c07c1e779dff8dee8d7ef987b2fcf13fb1a81c66685e1eb9605f5d15e2194f46fcedff115c2ebfad101b0c8657ef1ad78002c72b64edf73ed909b73dc643ff7b9b5e1fd3e90e33eeea3d6fa5c71debd4e29a597f3aeabb6e370bd9e42ebef1820772fa594de79c5ae78cc2fa7014a4c2cec7db5fe24bb56ad17f54f215a5368bd4bd934e074ea2cccc98685eeb6b68ecd8325cf7176e5fc35028d814e82377ab649908566aab0aeaa304a65733611965c52aa3473a6d0c2d55961e4f6924e551a9e3af54a25f593ce3a2e67720f793afd79abe10bf8c5f54d864cf51c5bafe23ae6d872e7ab3ab2c64cd724eadcce4934bfdd7610eb4bb6dcb59575e7cf12997a6941e0f9cee7aaa8b995083c970148e09c44b98b5c7fde6ab8f2f4f5f356c30f4f6f46da3c9d44f4a7f28d9fb71a863c75d04edb3aac72856f4702169169fcbc19990a9b6e46aef8c2c8383f6f46a0f812e8399b9126b82319ffbc199992c5885308469a3a2336b860ab2a6c3ebe191162e44b54191c6660923ec8e2a98897d9075f6638bb3e29c21872eba7adcb097ca8613039fc69eb12054ceaf203909bccfdb475a1dd3519ffb47561eac2051408ded6a16300b64cb9cbd93b76d3f9a50169577bb9ee76d872433a3de9bd5c7fb5d1cd9a0745385f347f9432f6a2cc793769b3ee5874e924b245f6032957648b662d6872459368aec6507fb092187c00fe08e357f8ac3ffa1b08d6db6edb2da8a48e9f6a32755c0730459e60141014490cbe7ce9f070f90adffb79391a05ed7a391c2ee7e4ac42cf177b393a2c0f8360f819e5f0e4501d5bf18c165edd7beff57eb0d6c85aeb27f88c704ea256888d66a536ccad496367de11a8d67a2779af570faf4210c15bafb61bc91b827d9006a79382aef676d803c3152be7e8cc6871393a198705b6685cf05bb13e70b56285e02a041aa1fd39a708eef8941c08b9b5e08a87b53dfa819e64ea259038497bc103ec775d2520d6c01d74bd0fd049895a1d040484b1cf0e14bf495a67a9f089dc24ade35508f63f0f80dea4cdf2c63b7fac736f43f0d5297939ced2f20d24d5e39f4075a8d6fad28326bd61d469d862f53b6ab8af970dbef4f99b82bf6eef9d1df177a6c4df2234fc2577bc156ae9a00187afd5290ec0522e7d92f516c994eaed09a82b7938d7384245cfd731bed67a9be1881b0d31bc94255fbb7c75d5315febd7f925c6b14bc34a6e35e532db5a6bad53cf29a0b35e8680e9abdb9ea1459e5e5ada385e6ce87f3e055b4c64cfa9635c2f96efa6ac03fcbeeff3a20eaa53dfae03482a5faf07d04f77555c5723dc18e89ef83deebaaeeb3aaeefd48ebf23074dced022d7f9d362604bbb30c41dc518638c31c63e5b52e48e661d878e3d8c31c61893d83db143d2248e558b31c618638c31b621c61863c718638cb167b177d829c68e31c6187b517352185f7c1dfb2d3389e863171edf368fd53c2eaf99c71f0631873bdce10e77b8eb3a6adf7a8e3dec55d0ab18638cdbd2ae2bae5804ef55fde8abe747ef618c1d638cb1cf954e984cbda871a8c30eedbb16027d724e5403912bd3b08ef538d87061a61037ab30309388ce999aef9c93eaa0dcd4e63b8ee93b2f3933ef2d297247eb40e79c3a24524e524e524e52ddec85fde83b9ad821a1617550a4312cd2073ba62ac44d7533927477b9a46295841a03474e6ac6986c43742173b3ce3b9cbbd9779cd4fc996ab2f31639304eb4036e8ba941e75d17f3a7f33a969c11df2935d9cd9aec92e64fc74935d93927726048b831aeaac23a2f6a28b924af540795e1649844d6bb0be6bb3bf5ddf5fb54712ddb2e140876d851a0cc9feea9619d73454c0d3a9fe5517fb5b80a618c39ceb92823e7347f3aaf6048ae5f724edf757b1ffdabe3a4bef3ce39aaceb9aace39a9ceb9a9cea74f37a2b04303afbc2a1892bbe3bcc4f9673786b38c43da5b07977830bd0d95265152380b973a68f244c9ed208da95c825358defa16aa29de7a0956bd05b378eb65287bf0cafcb1427275100467f3c7963d5c5215ba9cac0a716e5df44255a13b5561d6f385d2f2654f395585423a96b88e535c8c1bc3a40ab351d93a277bebe0ac83acdb57ed2a81d30714c9e490c729f7bd4e238020061b5718b5549a9cd6e23c35393d478c4cb3b5384d15268034158c1ab6468ddab4c6a481591df8866a727ad300dc5001ed30e4192297df0c841bcf39c679c2a182d3548540c771faf9cd683fdd46c7686c257a1396b301cfc18ae74f38c93b59c0f61abdb538b349d4792d594d7c75560b4d91af1e8269a19dd56c124975d0ddb129d556484f014a3a4c2d206c058724394043401c0c5555d86ca24d0e4f4d7c5122d54492a9267ad0a1879359132f20e91144546d8a87592d8b921e4c6a352190f47822abd1d003081a1354497a08c1c48417244e4c3cf9e1072626663cf46892b484191f7a34412d21450f2292968092a4c710b52578b0a1c70f511690f1995962081a2c5730b18291a812442dd7f879ab5203b843ce3f6f55844c41050dc84576fdbc51b1020c93777edea89800f6f326a40440736ac80534b33502e420c242c7942f572421e596c419258e7cbb2bd1e5db492a4fbe9d0544c42cc3a7a80ca608e1d1b9bb6d7737162abe6b7c7777dbaeb466f252a85a6bf5a15a5d5f6badf556ebde8a87a5378b071554504e305192445923fb763fc2f6ed24100ddf3ea4c3b7174939f3ed3e64f8f61f48487dbb0948b8795ae2dbf154186043b1e1e7db718662e5db3b9719b0c70818bedb7136e2886f774121f2ed9c47d1f2ddf3dddd5dfb5a2fa8db5a3d3e3a3870eaa20826be3dbb9c041a9a028b299e54f17d23028ad30cdf5e5d59a868c289986f2b86c84f6ea0c20b21664c641922848c7aa6c9962db60083e444ac3bd60e81eee6f22dc5f6ddddddb5db2e4181401d423cd1e0dbf14d882cbedde544866f274cdf3b687c9e76d4291b30ac6095d42485f2d2dde83ab1a1a29c9a6c6d914bdb64422593cba64175108ef338f59ad4412ea75e953aa88653afb30eda71ead5cbf662c3cb7e6aa15e6a18f5eab9a3b0e92f9fbf9c7aee4ad3653aa586cd1b5eda3975dcda3aa82d15ebc546b135abc542d928fb45e7c68d1b376e2c9165707ec397540025b7acca396fd5903ba90a59a60af5d371ecebb88d1cef115f3a3e7f86bfc4dcf3f9aba7e7250446d14269eddbd6506ba27ccfebfbbeefebe1b9a5916e72699b9c74d08d717ce1f87c9673ce8d2f1cb78fe3158c2fec368a6d7212456c21db70f1153afdd03bf115fafc9583363cdc71def9c7b9df70cee7c4d3e7c60ddb5485ba671ccbdcb429af690ce0fcba0df125c24b041bceb90d9f8fbd3cc51d2796aee7388ee344ec9fc80112ccef460ad524f52bb6272aefa449eaf474c90c5a9e5f36ed8e1b2c61aa2dc04c619104161bde1c1d51c4cb9b29aa195c78a1913ac8c668937844faa549eaae1a228da24e43a4524db644ebd4a4689b66e8e4ecb065d13ac16189d649004956a275b24da0689d8469a27e65c8b752d95af5d37150e54c6697a5fa89e3a8025a011617b64048b4806343288268b3c157e7ac0842c9971eb27738b3f8b2d5748287358d01c495af6e5d6148254cadb5d69a66e08c5475f10515628eb450012b7c8061cd0b61242113731f55080aca542b57a11e1c40e8e8a01ec7e2cbf0bbf58316dfed38e9bb4917df9d1820cd62cbb4049972c09f03f97bece100fb0f54beb44e6523f9a70ea25c144fdd3a75d0bcfde0e4a9db281dd4964a8d7350fc5ae5e53c6793789e73ca83a3ff812429688640419b3350130b1750506dda2c29a18109893775906d2591973c5d8239cec5f992a55698bce472e55ca92a8c7ac7d4a4a565c91c12b7b419497269975e7883256c31b57df7dc73cf7de765d33a913e155500c6e4924ecdf879fb41cb736e83eaa967a6550c2f64fca5fdd9654a565d10c3e64beb54855ed46d53157a753e63d9b5815276d22b5515b2454c18f529b5aa0999bd3da5aa423356ab6449d57730e97eeaee26ff2abeb0d36ccddaac937d1a81c63ca72b8ec3188f25779b9aa46ead9397911b49cf3c20cfa9d353b7316fb43658279d2ba0b5d65a2027c5d43acec338bbfcfaf5f943eb12e844d6f97963f284cff8d34685915a657fc84e239ed28692c96436c4a8630ad69e027ce953ea809a57707c39bdd0a83ed3cc3a4bba84842ee1a1ca572a6a48c2c357f72468be3a497bf2d5815af8ea43455cbeba0fa9af372527d4f0d531d0f4b587325f9d851dbe3a952529f93a6f3ea8f9db122d4c96d04aef121d237a906244c89212c862659e630081e6c815538ac8a214e39098c2aab576d84161fe1a5544919cd0da1c05524f5345357f5c9cc861f1871b55108b9cf86af7fc286634e2d167e5381e3f5c3c5fb21df3fca977c63a2bb618eba80a7392a9d7cacd86aa10c9625d299637618d97ea4a35c8e17e7a2ce60ac3ce89779657e227be383f8ad55a85610fc51737fe40727a18f6a318fe516138f43c6cf7da71518561ffbed108a8c2b0371af568e41586cbeae43e63d8df8b1cfbb0c78d27348931506118fb8e25d95faada2a764f64a1c2308b8cfc02e27963afb50e7a9130634898265518f6d7ebc7e724ccd83796f079936fa44c1586bd5ea11dd0c76e67d5a93e592b846c01159b315a0417225c28d354d2a46bab305c9d1e4f6e46bb636381e69c33db19446bd580cabdd67b1b020f54e6cffc1078883261b6b2013b077b462711920e6aaf0e04f4dd532b0890d4b1d3247be20e917c456fd64526ac03c1731d4d768f9dcec4fed50972d9b39ec9963aa60e2a3b29a98356de792b7550e81d8d6a59077d47b1ee7581e0788e5fcf198d86b823909c1c37b28ee347b1ce7d96e49ecd1f1f213247bbf3ea0b4a9e0124432ed341ed9dd3a91cef9c4a51aacebb889129d413369b442c2722dab123478e71b4614347e7fbebe5c7ead9fce97c2536ad6715d67928760e8a9de3889de74ce99cd2a80efa1ce72794bcf3f339b8923d24589783875cd2272135f9ebfc13a95293484d76ae817923237b6f7cb97a5ce0cf263b7f79939d774eeba69e351394fc7d093963d5778ee32504a9b0ce338e7f7e4215cade395dbd46c8711cf7dcc8fa3796de0804c7f368541d673ca1c23a27754c22cfbb185e85fb2adc177b69fe7478ec2f72775032fe699d049a8412336272a0c02f6aadb596b5d64a6b596bf5a1b83b8b2d67efad96abb5eb5cab75d55abd6abf4c8476b59ebd1f8729f6728e934eb69debbaae92ee6eb177bdcf7e6005c3feaa0bc8dded6857acc9fa3e967b0d24c2416afb030a369d2358dbc75a7beff5796e7cae0ba968829f569e3e948f0f7048451c3f3e7d0ad4e4f49256b7966c4781bb0e02ce73ac4c667dfeab8e3f7ea88e14f470e7794f14cfd25a6bdbed74ebd65afba5b5d6da6bedad160710d65a6bf1dbd9852f25ec64a3575e3164ea969614480710a4d31010955acb82bad5bae5c6177f7e0351afada3ac1cc78de4cc2126cf2d4d66efeaa0b98589ecdb7bb6d0927ec67e7c3e1f48cb62603bcec162128e7dee89482f0cc5be117b128e81a3d77d62d250cc7350447a01c73c4f1a8a7d380cc32b965d8ed3cacf267e7e69bd7ef0bdd7711e08769cce0cb1b438de8e5927b43a1e86f2f101d80a3dc79d7b22de0919d07d07709e738b0237e2ce41803ddb6e058476ab971d7fe0b11b872a8cfb5b7d9aac628d708ae57d1e3ccb23a0db3948559490552e8e13254a94fca084d2a2daa8144d96a5412b95b2190000080315003028100c088522814024ce54552c1f14000c7a98407852990b846912c328c818638c318010620c010680d010d94428106a4a255c887fb0cf0ebb545c860ad3a8aa843968fa20f1c07730e5307ae4c04f208fee18cb16180ab9287cbcdf58368678dc43e092447eaed8450afddc60d9ae429f5825d5c02589fcfcb12b209d4f3da258e9fa248c5ca1e8cf12eb6d81965c97448ae4f513eac9fd837b04daf30a2e0974dbc548562469e446e390fab418ce0aa6e4e1553b57c4f6aa696926836b6d05ba2a33eb6c617115c6026c29bb15ff0e979a982d7e90c9f70af49303c2586a564ef49c551cfa9fe68dafc222f1b76181cff814823d4c30516847349e3dae3255344535835ebae7b68af8d41b277808e440ff283af4ef2455d34415bbfbcc453fe8f69d50e21c255577038dd0bef298b7816359a68e2f486a03e8fa97070bdc93e4fabc1fa5ae26cfa9b4605ce446bd51d58d9439484a8029b1a2cdf7a23574d7b9f09a194cd8fd14de73357d9a3abc9bbd46026a184474d88f156467b4b4cbb4d2224259e1388fb1f12b151a14d200aa1caacddec06b719ed16bf8a2f75bf8e0b386a27ae21cb13ceec03365bc6a4a9fab2ebb64e9473c069bca99472ce7057d7631d517e61191c6a3362ae0cf42b32a327f188025f22b5e716d11397b16e2bfa5798db03c2405ae5afabd44a732ed2849e42ead75e5579ff675edfe7abdbc80c8190919972d1b52ab098451968cd5fa6812f19a9596dc2f2c420853140a8b942203eed13bfb58399636335d215c79aa020c2d8efb35596918a2367aeb896ee71f492bf491d5ec67ba1ff0a6758883e41cf7be05ccc2eeb1a7e185b395127d1996c1cbeff998f0a1c0fa5617d9782cf1de44cda76c7e75bc586f650f2638e10ac9aa5a2b026328cd0f7729b0b84e356a644688d01b3ab8fbc3201bacd876aee39cf1c23211bcfd7e06677cd1bd35f038b11ed42144254fed530378b117c14d05a65b070f15a8c0872bdbd1b8d8a0412fb4fcf6d75d855c92b1d51f72110d854e16e426d05a7bfd878dc8ceced32ffd39c4aca5bad1774880213f695bd0aa8a2f2f9ce8e2e0500ded7e1d0580de6d619a8fd25102550876156951909e3c2e40c4f072d3a2842dac57bcb833e36e87d1bd95e2544df25c25b2e0ea02b38abe31fa0933758d2ec5959c0136b658ea36ee29498b7d266976f92e7d0c00636e2835672f36b2bbb190a2fac46be3289d22fcd4b251a5218845eb8f9388e69c9a20c439de733711c3587d194884902e5ad0af330e52132c7df40548fd36e294cece5932a939daebbee47f2ac3d26cc925182afa87de7385813daa1a5047cf070726ab44e009263b42c11cf98bf443e7e418574b65d1c4e77cedfa31fd3bd706149c4d951559aba57b591a3cda9de7e8205e89c31ca4a3b3c4952e844b43a8e0f3f7f8bf1700efb599e150a786cdba8e72ced6d3e7816e5a614536c0a1eec344cfe6d6000a8a313c7beed013a2f8d7209a1d0dd5d1b98f5c9fd8943ed5bf602533cdee82c44408d1e8ec5bc2ea3084ef613e9f743aa6bb2bfbfd1acb3f5493b8b308b22ec721392a83ed725186a06c66f3b451dd3558a8c81016e18275a4405883f432b5726b32d20af3f43e93915f9220c81ba258ddf7c5eaa38a7ba26a549cc643f6034674d7b3323693d265a83a885a6f784b5eb801ebd8db6f4cce00c8281af8f81a5f6f2f0984b15fb695053bd6d8a205e3b02c138fee08db5035f1627302d60962008252daa3274bba62890f0be715705d9da047d9471a3375a005930e7a303425e608bd6557dc41270295a06882fb0eb2a03c68b658ac4a3bda0814c1f54d85e59b84b6e2e08874e126a54ce0cc887405f13da70aa9e4895ab8be435a5d83a39695dde913c5ea226304b591f75d1b00fd1380e3585fc6d201e072e724ea1cd4c1c6435d9c7a86e02b13c0f08ec1141e277b3cb4b4cb50f832c2c439e975f408f33afa9afde3d528ef3ab631859997ca145220de0c3ed0060c4afd6c97ce9f491ffe3adeed84b99fdc4ed02773c55265a36a09536ae808d6f55053211357bc01bd3887bb215617f9dd6eb0cfd96ec8f6e216abdd10308a9664fd54d6d0f29c6bbeb34bc24074f72494a9cdb3620be99d176d073ddf79c78202058b11303a8743573c365ca5af9bd0c85e4ecfe19dab1aca1d11ef8cc7c43bc79de29de5f51406c51b5daf096c26264e7f32a311bcd00cbc6183b25a8c2de26059438ad2d09e0f4399279877525d37d5b6009f66c16b6804c2e2db79c4e8dd2052d48a4b2a4b5646a44ac5179d045f3f7572dd0b7641d7626e18c4ada231762935923b64759287f892aa5895066d6b63045547c531b0b923268f6d9847c78166c4a6cb8f529ea6804ed1cd960207072d850a13424eb0845526573cca80cbb68e18d0175ccbf3ff8cc980f857b4ac754ff9f200e081526538991d42c42adeb26cb71aa8ba76d1de9288412c6b99d48e305ddfce5af619d60a074b19697dfd50dccb86f245032c01257a31ffe4088a84611f2ef6063a5f5a9b4b5720b8910ab7de49a0989f46dd4396c95101db1401175b8ae5658551b9f295a1f8ad298fcaef33f4e63ead7e1c6232baf748be38632bc32379af2393910ed96aef68e7eb62de52f8d67ba086388dbbbabe5c385827604b3b81e9845f396365c28c75aa6bfac805826fae06ee67fd87e356607db2f90e5eb562997fb0c24a63913a6d8b32f2dc1ce135640d024e2a5aad6d96191f1110f9cc3fc6cfa832b2f3a44a206bb8e14dd8a03065e5e444c673c3ba8eeccb9e6a712ed8c0a105690f344077dddc4dc55f7bb09360d13fe63e833c995b588e756e0121099e0703bd1b3038d3e0d7507bdd2bb86541d9bedbf33f773be7a18f12a6030d5a07a2fbd9d923df4ccdfc740e5cc27341f539803a8ed52a93278ca02f98a3420b825adeaaa6e1935c1685690c2c5bbc88076fa66813d970e4512f10f3b7dc4f3f0e76c2dcafc8d5c20de3ec9a3e118dc76192c0350b4a600f1f8fd5116ef14ddc52fd38db8c6b744bf3bcc9533a6f76064497e960c715f1c841edec7b15d82f641e1dc4ea3a0771a1d4023fd016aac9f189a5ca8829d15eb4f2529fb59784b31b8cca083a249ae1e4a304d41570cd47852a375f1e4185d08d9a6f392ba1922fa9a78a330fd44fd2b53b25c0c1918fd85268da0011b74239650694d3e401770bde933349642206bc41ae7ed5501549d6af20887f301b3c9d9bf0f978f0da9bfe4b0329a4f4a6164eaa1ec7d2f340ef50cd5b0c56057f89d1f38092c8c40bb848d3722ca1dc4414bf21932872906824161ef65019a30c2ddbe1236cce7c9541c409508efb9bf1131b065643314212e9595a04c0f720e603c3153e6df4ae8dfbb1c0f7e61edcafdbd7def87547118eb414fb341ceb68ea6572b907c9f8753400454e4bec2a4a89a72dd70825eedc4062f3a990187785189b291c24de61c4a52894268c0a286a166851ea96cf602c6697e72c3a42d0413a459e2bf90d7bfd35a8654fc87c724eb17f5a8331e02c92c45ced17092deb6a757d1b7e172ad71ffb87c62a5f2193099900369c2e78db59c1b870a8f818d16600091a66b0e28d612bc32b2d710a23b8d744df730a8e5038acaa235b9b74678e7ae364d7202c2acc8d2cf7da5f0af7aa498d2bd04c618e621683a3c3a9be0893414e94c9e065326979776fb81f36e0c3af613951e8225c34e2011fd3c411d4c3b4ce9776579b1a9788a24b095a5712548246d7a0c13a722e0a4a80efab9e0d5d23560c43e7c3c1869cc14217c555c10603ba826b026dd8cc66faa70828b5318371213e878b4f49cb291641251a7083f2d855690852c8b8c905ea85dd1514e31bcf12848135c36e69a111dd3f6fd8f776678563ceb71367a8bbfde26685ba1ce83177ea59dc76b535c82a1e93d4e7dd2f576945b5224fa4f22912d79eb94189c628b71cd96169890734507ac7e865eb0392374d2eaff0070dadf123cec2dcef5334c9c16eb9fc161f53f92a2bebe2ff27749c06e27da799aa9a18061ff02ea69e1c0ead2cded3f700467ce2e49894eaf995112668d988ebceb20435101faf5329be16def2516afdbfc3b0f9a1d7cb393b1a1067aec5585b00a070ed91084bda79ec10812d7dba19a924761c08b3d748422dc961d53268f4bd887a17bc6f9fd572836bc2c54b58e4eae4b1b0feb996a0ed1f7691e1a0ebfd5c9139ccaf7f185033d382715b0dd66f5240c3a751da1dcfbe12da78be81c00b86f0b89f73f2f5dc9a04c25f830553eb8e0954e6aada2dc1b8ad7cab2e157d71b46171eb3b664657519c67dd2196aff766caab64fc788e580606b93ebc5832ef29076d78223f9ba48e0b519e4187f3a4ac124b5c4b7631a9238f7731901799e7e56dcf1317e48cd826307ae254b3d9aafce3ec7e6b3b13f75e110e302a43a6ed8b9992ef1844f34e5c42d7df322dd7af62c439fea08592753218b22a2b5173bac46956aacdfa14efea3f14bb8df39bd1a814ceef2d3bf4cd0f5b05b672f39f90212a2780e754eb6cac5eeddbf46f21bdb75f46c1905ebea3c3084c5fe41802dbe1897bbcc17c1113fe4e351be7069b19074c8da9943768530259f8c21e2f31c23fdc3c09a5d380654a7c00a5624976f62309efe2e1903188b2a30cc19f9a8c7803ca4cd2314b89435022f750701bb4dc010d4189645af599b9980a80c87f4a83fe230c98b5d6c4ba02a92ed6dbd51abea17c0f8dba0b78fbb11befc3d0b18b2dff8b995d7ea498cf398e1c002a80d148977b0612e4a0cf76671404a05ff0bbf1dacb2453eebec041662b2671d3dd19d15220633149699a0dc78ad5c78594d3d5638eab996734f358060099eac2890d8daad07e92a96599548da104bade2f92a62efab17c4d802ecec47a50d74f056d3fc7e48ed4b217c878624df6ba54985829ef36ecfe2811296d8c29dc806193b52cdbd6e675d4cc6fcff5f1f62e244dc70767e1fea5559c57ea569b4fc168f051e0ff7856beb4c4dce5ffa8ec33b10312d4e14c1b57120768336719e4d9376e055cba2405dc9909d2c2fede9749bbe4c6cd551c622533cdc47afd68761451cffd612521ae5668e56c7cd326efd367499667899b4202c5e0d48859a9a8d358cdb7bb6140427f1443e4c60beaa5e58ba1e6c67e6546ebd7ea9191710f4c8ed47eadde5f954cebf83a2dd8942d0573823c2a2f8c364741cb848eeb6876d6c787a5ef3fbe849a5d4f1647e8f1de6e5e4359382ccec07d1a98799a6e4aacc8bad91d9ecc60a6f0b543139c74dc8e272495118bffdb6371dd6c256859b092b282609ebbdeb18ae3044e593a9fd2d29b278c8569536999f6f0e8d6c45c46433d906daa315d7d30be1692d0a2f81ae0d18cd8d7937adc8c4d62a35eb32a665564f73f3b99bd803f88ba497ea4e1354194eac2241617b82de3c7d948898e106bfef06b91410db91162806291c080f215c99d4ba5007f5c6d4d9d6ccf2bc16cc465607b51acdd096b8abfe654df22568daf7e29486c8aa80eae8c6e13b809b6df11311f4cfdd282640ad37baea58fcafbd106e20990b2497888892d34f6808382f11b465bc013b025d16f7f6e65942c80bc8e98d744bfe9e547fa996038dc5aced740b0b6c7004550c494f104779c1c116e59688724231acce1d5bb87042847faa62deac005ecaa153e815c263946bf6a22c41c98d4ed0e34b0f731b08557cd315d8950d62f933da82c95a46fb67bd95d43723ed792c21c0fc09b584d05a2f629dc8a54bd279af7057ad5e3bef80d86ce24091431b9a51707d639509632958ec9368dd93ffc562e00dc9a0f30e0246041f85311d28848fd41c162f3b93ec8c1f473b42991c8e117b87cc259725422a7e84eef33bce0f213ded72ee3e8df65723f163f277f52f4afe03c7773149058d73600d2b279c9f0a1b5866a70ae7f1740f363e5567aec7ca74d83f85ac3216cfadd6b73f4e53533354148831dbdf724be86d1bb2c8c49d59d8d4036b7f61c6ff42578220ac589abf7876bd32025d0e2ac0bfd2406c8ec8c5a81a9d13fcc296d7b1d55ccc5b671eaa9f4eff66b0ed6049055c736f5ffed5e0800b1e7728a96fa2d7db19885972a43d8ee17280d6d531308640f2ea35a66e66895494ff719f03b676a5d406ad3017d177c253c576cd16784a475e7f84e74fddd17414758195a1e75e21c0ff0ff0f1c41bb83f1b0ebacc36ddcc1725353a062a1efb093d862ef035a6d56f2f489280f86932dc81dfd4670c35612eb263c97351f1b8a9b50be7b293f8adf07e3c4549b8fcba031d9060b966c52d6ef19f126509e587f808d6bdf208f2444cf0553605097420a70f3def96992806eebf3e4bd063d5c4ff88aa58be2be3598dbb20fb88a4b7650aeec982a6dde9554d08542522989a450c4ae002047d78ceb4ffcdb10b930ad76746b0d105838e44bfc167fcc757285d29b0d41af7b117705c5bc0ac18f79a0cc03081616df43d80ddefbcddca7a29fc0f382c6988cb9f91e28821044f456ddb18755f3b6946a7f5b485ed6e01f4365983c3c8331d3970be5897b52f8c56490c4a3f313013e71338f9b82d56e58246b69dc8a1e76b36d4387769ce01f5bce79c5e3991c4550051dafbc81773cfec5f17a5b10b6a2e467cd51ab72954bffc76194bc896a40449a6dd018d0e7b94ac835233a3f222b9ae0827140e66ccdd723b19b0d0c1a69885549d2543a424e017c63227121fc5fc82bcf42451f0828fb44a59e25fdd4164779b76d41b997ebb4c4f526b84a34b7bf36aaba28be9cf529dde84fc85a6e0c8251830ae74b903579368182263d446a1cab81e33a45c585651b90d6e77c5526679ff4adba319535d53327b667fc272f2d5442100357da7d6ebf2a3623f059b0812abd98b4d3c713085e6bab22759ac683af9789b8cef20dc7d0ae9d457dde0c667b6e093570899c1b58498e8924751074b7002f2c04f8aa6974c427f2af4f2b6c5ef2aaaaf7d2f04cfa1b6cce7f8f834d7a694a6c3be7372171f18fb973778ec37c2673613adec0811a74fdfd78bd683c81148b1728d6e040a6b909921d36a2420a45402d62fe372bc2eda5527a5e661115d93f8f88527fe6f0ca5a2eba062c1d5d1aff6f001cb05493dafbca39ad28ab50f96442645d424afa3e6ca88af0e5ae403351ab36fa1c1d4413810b491479bd2d28d4e5cd31ac3b1ecb9c6269704af944c8e198f26b336d9108b7edd904c26fca24a908f16f068308dd884261835805ddea978e68adb3850b3c66e5cab0fb422ff3035dbb12ffa1b88480aeae302fecb7d2f92847389a90cf1f6b27af76aa09ebe627ed56633273b9feb945ab049c8004214658834c0e6dfbdb15b55242b7822da763083025fe30bf92709873df1139e1d4579206539ac0a9a9b9eb9905688346f18804c57aa5773ca4ebefe8a996e9a0a6bbe84c83d013e4fbd2d1109a30bf9000fcca8a258a707c7ab56c24698fedb5a12e0cea2db19ac57f9af9e3f5eb2e269a5d5a813913b922a3426312cee950bff0b8a0109e7f3656f315c3711581f0bd2723888e55a9ba6a0c599c184bf89af7685270e72b3ab38b8ce5508a85d4f78fca8558c4718ede1e6e797648dbeca36c68f6824d5c0a01430201bbd570dbeade7a3ed7c61f1ce384aa39997369aa1d769338b88e05fdd0fca7f87598b85141eaf38eb76607d9635c79b0432eb45ed969b5042e5c4e325c7543e7ee24ff5498c40a1f8b43a9baa87c9a9c67667c731b8958f606a98dd6c2b687c980f3341a74cb85de1711ae954e2cbf26bacb09b7e6270e0ee1d183107e55c436a689f62f6f5c8987c944d0ae53b7ec722e93c4aeb3ca0c7c504ba7c9947c2ccb3a5a5819983281d0ec5626f3b854bb94fdeee735915a3b6d36cc4d27a78e9e896926e8b29396397d22b78e7726e699a8d38e5a36664daf76076a264c4d21b74e9e894926e8b0d36562d2446aecb0b93037a59c3addb99805d3cd62ed28815ed2c4dce469d1590a5e2922dfa74d9d4805797754679a269157ac82e97af9b9f638332813ebd5adeac45864963a27eca43bfbd99c2674104be95f1bc7b985c1942297171cfd37757b13b30bd846a186fe146e11d96f86689e41731ea129ec05f28ca8fefaf02b422b41c7b63ff212d4e8f035d715d0c067ae18a74584eb641840dc0786553319404d7165b00423f939adc327a2d3a10249237b7c446e45db03cc0b43d486eb4494c908f7114151163655185ba17f446e652e44d21968f5d02b6142ce2b3e0a29a2a3c926cf65d0190123737ca396a22f30e2bfc7e1ba8c8cc4eda0962e6c9550b0219d14d52ce07a6f583d71e72cdf5ac84c37a205ec55d4ec27d62257786844bea5ce5a2a5ae1b94dfba998a9474fe838e547aefcd2098d03437c8ffc9dfdd2f64fda2495cd86a060e9b17fc3ccee8ade3e52e8c0557811eaef249fa9e8e0d8bed2511eacbcdad200e9cd71bf05f195f7514d8cc2114b53f02d570928f841e2592ee460c5280f4631ab7fd689854eebe8c38cc452421e6466ece862671b2d1e6f5119858adb634993f9186239934897845bcd08ecf4030e771c411a9d22a74119a27c032bfbe0fb0158ec5fec85e6ada58fca550f042b4427238728309ce25280e840b2ee27a478b215ff297d30403d9bc3fbc883a5a17342b1eb1439b2f7f45fde105660a77a7a577b6b579d97aace681b06f6538882823022b2e0cf822855ff5aa2d806e3f3342d118e3a8bc96b65728ef655605fdba1428e8638dd63839c9d08940fb4daeee52c2833773aac613c1a9cf1642f663d6898ba258ae45a0764b8aa91db971da8fff79fe80517698cffb11d90b18b00a70de10585f5d604dcca4eb000db4f8d5f06ad0c4545bb099e154d452ebc9f59e9396c2a3b0d074a67f03d8fc18ab21aa4722f58e0dc10d34f3390639cfe0df26cda27acfddf772e6df4fc241386148437efc4d9623767565d93280ec3d946043e4e8807a8dc207a6c913a323780521163117274a0ba22556f213b183f1d71170734d1456425d1521b4c0ed8a447bdbfa82c5eaa98c188c8c07b7886adaea4dedb1d217c3305e5984d2a5c11846d6faedf58094302cc593011ed9d7b9952f57758d5d778dea0b90bef10084bd16c6a363aefbe0b669bade302c24f8e1d1a367a34d13f00fb7f8a0ab1c67891a8ad359470ac3760350eea386d5e7360ca5023f72d703c3329595664e6fbae6ece273bee67e50e2257e691f82b69d71f67366130e9c41a664440cbcb5e444b59e9c553f8fd5c72ad2bb7145a37237cd9a48e576cb589f8e240d61cef0a303562c493ef0b3a3fb1daf1af2b43b5dfbc545b40ac3423a967df43907ac66c59508bcbae8cb199505200becfb88360105fdb449f2d651c0e6a165f6f53bf9b6001aec9e323550b87c9d31beee459e72ccd09c2f134188d90c5cd1bf41bc66fcc721050990818dfade288b62ff14faee854abe3dd997d9e8836f23cf4b79837e42cfa78613ec29d5c19e9dda41bfa8ff609fd3da1bf999bc511cf6e6eaa2c70dc0d20a3c254c7438cc80bba4e81ca45be86e2922f5758704068913c31c9648b9e3d11ba2e78ad06aa9af6478974ce4b83ad3c1e9195c70a16387d7759c39bc6869b9385ca0cdb8aeb0c8ee509f3c71a2996a7911fac45aa5892cb0de5aeb3d937e4b55724ae29cc3b654f163deb9cd6c3724794506e644bd6ff223a0985f1e25427ef586393de000141d5d4b293192b2338d52f23ee2b9c5067eb5de4f2977a078b9d712e6a210625c8809755bf13462bd0a7a69b812d42ebc50913619c22af86a5e94fb5e00a5491a63e8e2183706b30fc68939ddd123caf387ccd53a758300b4de2ec89fc97a91abf44aba456dd7309be74594d5bb6004bc82272f8dc2219c522039e822e4fe54bc1fe89588b4fae7825aeed4dfd790aa73bc2ef0e90562571c6f9b351d8f17784894692c0e812634f4381fd143f800bf71d45570474de61549bda0f2e22e792d8a3779807fe7f1aaad9ec22310ca23805b45dcf62f43ca8f0cbb3d539daca4d8539deefd97e22ca93296dc9d4d9ff268fb43395216192a8eb8716bf82f0a24686561600e5df760f6a967218a9b4129be9a2775896a20a312dc59cb69d9d0b2048939ad3214692990cf41ffb4d0ee0b61d00b71980592403a0cc647201aee8b12a18d96eff421373432a35b9d820555dcd2a60f8ab1ec4ce8039b5e8f5f0c9ee9bb8eced84e260c02f1fedf6920e51431a30ace0f911a09c04e5fd2fb567eaf9014dde998bd4666e6b08fbd406667a7fe852a3b4218ee7524ac5889ae18bc5d8fe219c554f826a117222617fbc5e81c2663643a0381a58510847e75adb7e4b95a2acde6bacb72793af71ec60022b68a68f062fe42a834451c97b5351548088a2b7c8cb9ac40455321977d4a2c1720bddeaa32f05bb07828755acd6f75aca2fce53704a8d12ef6c171d8f9fab2b09fefb2f6c868f3999f199a3dcb55350bb6400a6e2b9f744a944479f8a6783f6bda75553c6d50a104780180e4826bfd1ed3e52abf172dd10bd4b0d90b90771f331f0904c682a41cb06625c721156b9f3746b56ccb01d78bf62a0e92b696ea0f4e0f9344aa8535aeebcb9dc23f9884bbc01e9b9c2a1e01e1ff2cd2628a21f3cdeaae31feec357d78d00127e2b275b74856dfdf22debad18a625d8599aa5fd8578584d4388722f3a16fcbff1f432037acf75600fca25e2df587032ce9246c85cbaf0c976a5605db108463339275ada0be1aa98c8e59c57d513b3e22903a0664b33d58298546353d9ea058b4bdf4a24d8f152986703727fcf4c9e6ff17108c3af1eb4bdd6309f13afc2035331b242d01c22ceecb33c7d323875271b945cb29aa037231aac0c563c162f57685d894c4be16502bcd99605f54c86eb0c20c9c2ff2a3802797f811e38e4baf451c58ba106a1235118f31ea60ccf0c8a2513a0d52596969b5195ddc574dd13b91e88a3883902491c850a1f5121f5b5858c93379563fdcea0fe4826b73ae8bd69a3c37af0029034df87ff1155b5960967d1b4c53ea6c51c9db23b1a70dbd3d18e6910aa80b26867e5328129b0bfc0ef86d9815ce756c0a6f766f6296fb1ec6c730411b6c74076ff6cb7ef416814f49aff67fd956efe8ba4a65f4222dd4d4588e91a6b61ebfc83870b801b5cbb6cb65c57606c8352dfba89865dd82b6a11afce1c1f6353324919766163a90f6137d71521dd6000c28854069c4cd8b6302e438abb0dcfed13d2781e45c2b411c00a5905b939273d291c2b2f3389b9571f0f54ebebb0349e32032c4737a7c9bbf23d5c43e802c272dcca9c1e382396fd682b77916dc2d2c8aa6d9a941e769b60981ecba0a76ae15c6fa56e01abd322e0abe1d894593decef5f23a61cca2d8d80570b18a5dbbdabd663cd726649d9dee089cf52e0b563838e61b588dddce8553b6a473ce1279476fc18f9fa680c583dc4c3407c14ee3bcd27de1ec5c7b4ec093c24b36ed0495e281554f0a2934c3e301f3f7fcb841960949fa88fd5449f228d303831f6d6dcfd9d94ae035adc03ecc726a2cc12b2376696728f50a5cebe99cd15fea6323800a0613b1f186494dee0d1d4dbdb0e464896de94ca58a6e44d6fdf503a3c5b0c83ea67448a80098ce35809b4efe4436bc64c15c5cc1565100610e8750442265dba381b38a29af159bb5f3bd4a2a268c01881a921daa84181796f7cd2531e46b802969534274dbd134ae91a0f13358d43b97a3c3e7a3c59a07dc2f60f6d72bef582dc602f932bed13d5fe00d9d52763550cb9c474336b53fc287517e81aa8d1a10c9f91f5a53dfd947a89bbec837a811eee62ac7c89206a8edc4721ffb4049f5d03469781050372610f1a337709799bd6fdc5f5c015e86ddcc7fc618f2cb222dc7fab5fd4225417b5d797eb2b891f143909870282f2e8613122aab2ed1bd36c0a17742eebf4e0734fab6b09f93f5b06438b8dc74e24b0581cb9a78ab19bb068a8e5c7d4fa7937dde898f586db2bd425e001aa91058c3d5cd49d3db05867df997655d8176e37286b0247eed9855f39d8ebd26a0463f5694afd68ca8f955a409fa22c96f8c3b77184d9b6eb09ed204b6d59eb5762d48bad9dde94b89875983af96cebfb2041f0ccac300c78146ead2d462ceda09c235187c4be385f6bf716f1762d60bbd4e81a625f7611b5e2a7a7abfca0ad36e61c17158ee47d7198201cd49dbebe1419653d21709ec01dda4a69ea78780c56c8ca6c24e10993bd04a0d258e42ecb0a280b83d8b74e315130aba6a4a064cca4dfe373612c15e4befac27472324a2ab2ea59152162182b17f627ceef0a84dd13ce2fa11b8c0996858d50bb048b28156290654eabf39fa2af7eaada34180755914f20c6d5f0fda33909cf19e177fb54ff32803ea1bf6e928181b884f7395ebec20943ef1da1be1824079da31f82ce92109a201b674de763845cce53bd52706ac1bc3b08df0abf7eb2b5ed1c6689b587bc59db0e827cf64fee229afbbbe13600373a424b42f84eb405590f5a009f1ff59eff78347aaa43db7139093bb58329327d29c073f27630a3d32010e558201654dc2be09009286a4f0c1efa46727f9e33bc8e1e298d3873c3fa6bb3d44824dae5b18bce37de0a4e17dfa2767aaf182079712005702470817efd0f8baa75ba5debdc40d940dc0c99dfbae0e8da094e4b02fea6245cd7027140df3ff0c0b40196a2a0f429d27eeb5eb6c5fd00a2a2e28f22fdce21daa63e61f6392a5c2a285c53a2d28c2d1d6ebb89d8330be4b82dcce9f5abacadb320b6c0d18060d39d68a59b12cf74a9c99f62d8034700c91de30dfc5b73f0c526f70d09e259bf705302db20eb9c57e6b9823ca14de5898bcd7d08d77246670cf2860719669243d2e170d411567b9e8e99e60540152fc280eb8488def9733a7da4226ae1f0e74976f8381b47c49c9bda764f3fc077a138bdbb648a1d6785a28c75debb9e5384636ab330babe919b058e0d05eceb707b860bd116954ef7275dca6406935690dc6557e4501b485d3e09aed589cc15c18b8e1d6067e288af2d8c0e230f6431e1d0dd43f544e0de39cd221f0cd8d247c52de9768c266f2fcc8587c7d12beadad04a4fa58298462d85355a12d6c775f1187b88960609789e40da5fb00956cefb3fb3d0de3b720f9de840837184a0248249579eb6d9c0b387ca3772b6544a96e799129a8c0602421707c856439fd3bb15de65cfcaf161b6445059a6323593bec418a15166aa95d74e29930aa9322463a88fe533b524614517ba14b7da9ed89b76f832232d5f189a4d18563eb1f63182f6b463ccbc35f12c01849ff1865d78f3a2f1532f84bea41637e826c4ab223c7a60b9ef4efcce2435899581d17c4f699b85dbe845f10f97c06923ff5d19e5fc7b6d2e1a1e7f60ed35f81b175a351045473a201636f1c2396c534f884d62b33bdbe28c77646d44d6944e894a49cf07bfcca12fc09b2af606c7cc4f095737d0fbfaf3261ec89a6d64954ee0cb4f2fd739514fd4858da06cbd2ea665027e143412702a5799fe4c20b524ceb45a2154c8309b92a719286dd016f3510e8c470a8fef2fceceb615b3b44fac133ece4fa3a5b8e8b13e1b65984c1b0f432d5b456ab05fa13da06814c1654e904d9c3c32da8acbc712d18bbd2852c5e310c8debb7ab8619a117b55665454e50cd7f5a43331ffd10ef317538abe9a54f3bd44287bc550adfda80f368254b7ec50ab9a234103ad1c5f461857ecc04fc4428c18c35fb5306f39f74018391c8ef12230f8ba20926e9d6db8699da12f8d477f00a4e265b1dcc5ad60e8fb8d519bd6345996c3ddb15d4cf8db07f8f7e3c198135a5518b76c58d4d56bc5bc41a0c926505242d51ca75b2f9b102429bd32e0e91d8f886daf9caafcd9121d1d46a141b6d195a13e1830ba027e22851efce464e77e4350e4da9cc7be0e08f5548fd42c58ef566b8c6a352264ee359a53719e98bec0b2397f60c855e676b58a27dd8d44f4060960fa2fc1544d0784ec5447871681b011e530a44f148a312a41964a0981de7794b9eef78d8fe2ebc90676d1309e85e51c14dcc331743be931c955bd9c14e7fd92df93d3b839e623060de8bd056ed1db03e2fdab36b7415443fa70e6909492c6c0ceaa9325df2e464fa9821805761e7652313b2ba748b5550ee03c80e8ae96f0a6989ab7a49271efa6c0e5f7c44b0c9b3154d2447c55aa4114da4bcc4a2ebf1b2be40ecc4c1de5ea22a1504b24beef086661043441443e4244417bd33aef415c22f2914ccb1905d729b4280e1e7e14eeb278f29cddb68d9f094dfec97d1dc1f327dee87a7f9f4c698d5e91def675a7243ee0f33bb79bbb9d637d4ec5d8c1a72588643ea8e469ccbd6f047bde415fd9f1ff63cb473544ece9ad910b97e793a89e1ef1dae04e7de97b72de7cce341d6229875b00dda95b9a5f7ab8131872478f3322137c7393a3cd6f27b4a3c7cd3c1227a36b435b33033b10f45bed505b54686572cd335612394ca863f9107a593b2ad1efe64394af5eed725ae00b50b45da4ce328ca2ff3ff1a1435a7f17e15bb17c59b6c5521153912300214355504456a0f0481671d745cc79ebfbe2ac3553d66444786202db8106d4d1129cb2861d87aef057ddb1758195f3a82d1bdc061e4c9e8cc5c8d0d63201bceb5dd0f151f018d9c8d2daaf20b11be6f27a8ef7e36cce28c1a60723015a65f07eb716b2fadec22589b5fce71c208175cd65b1eee8479418a5265ec33508eb88e85869490fa9e28fee1975ee5274ab61035494f593e246dbcfa4cfb4aa742a1751f8408a487df19b68d5e07971d312d7783539564911fad73ee47a81e0533efd3d23be0e1ba494829757206d1dc5726f4e443c935ee39991b7b144933fe8543a62f201bfec2df0a1816048f16481a409b05a9b1244901ec84e4fd7fddd53ad2b8851b0616212e7343b17d56d9adc4400c8b2b53d2305e28418ee48d79eff3398e7861ddfb245b40ce34f3bf4ed9c619dfa03ddcf2e74819b71c3b47714c7cf371fc3322fe314dbd8811a722b8e51f1150bdbe172c067327485869fef4814fcb5543e0ac46343fd730002f23b2853233a39d417b35dfdec6ff8148f38d5b35adb736f326118021ac351123a171b06c7379618bbe0f23ea02a34b1a1c8041f31d0b759ba2dc659fd7b0cd5103126562fb5c5856174325d2c7b57c192d1b047e5769648e0948bb9420f68c2a8201c1f064ff6875be55238e402ef08a7c808203ab2aa1bb24dcfb53469ea61abebf8738604d0689b1bcccd98ff42fcaae8b773193015b9c305dc9c8d6ae6ebee154a8a2ed593aa803baa41275a28e787c52e842c49331ca0c10331a478d2a849c3e740b3e5663c6c7ce995ab07865c324a123aaa247d1e435e357c5ce702c6cf37a3edde0e1e92088f5f054c926f47b4c5b3c2a29198aead413922196db265787c6ffdafcc359b0d95dd902b4632b5929f93103edb60906c6e5cd782c841e42a20f441328cafd62d41dd483c83549881dde36d96c7eea9b5152d559d52406768e5c2f758ff9a19b8e32fe0de90cee25246917157fd3e2f863b3109221b0550a6b59e30f9e46d3846702f2c359725cf64b5f9c973531abf692134eb7eeff0020c699d6891316d2be60f0d1a44838342eff6e7f7060f54684f2854472247c97a5308cc3e6d416a1083b16214d93894172c6a2b95339791ed30e7b41ad6d33dd40e1b964f6fbc2a2c439a686f986847e771cd09a46feca3de94e1b39ed2d3f535473fa97b97abb2c56fe2f77d27083dc1142d66c9ecb0ea28c80eea9bdf266736393983590fba2e5354e0d2e2f4b540de0c12fb8d2fffa259791e21023c2988726116b4c9748063a204d91958e3d2c33334a477aa2cbf1b7e27c2dd295d551f127e37b8e765cec48a2b615f0952aa99f8ebc859c68bd32aa19640285c3d9e56015b9b36dc1deb484b28e886afd7a40108f75742451e75c862e92ff213501445f19d15d4802f242a4b9de70f048f504f79d0b6df5ca5899b7bdef16d2f1fae8dd2a5e24418e75d7d0e1517e34eba985c2e03e7649da7f38dabd442f9b94ba06093340428e7f02c6d95ee2ecc503fae5bce11f91281e7c1bacfd9f1500b6688a1bcbf918a73bb10b04add32738971ca65d344dc32229677c2d8958e9d9b79cae63f270e607a1a560e8963efcf5a8dd7cc1f3a28a85d7aa3fb1ac4b5f163348abcd3432cf554d1ef65f085911a9b05d2b1498f2ce1a1ac91f11cb513b4fc5f98c3eb353d627682a0a4a5101061fe39f30861df3b1addcb07299afa13b565e598a1da1ba522794895a841038268b645e2e0c2433560fb2d12af7e69be03e7fe5117cb94888a7d269de1bf03afd688bd0fc99c2f03638bd5f548ec671f4ea185614213f121f3c1e30135e6d8a5967c56ad41b67519e3604de5aa10878b8774de3de2a14bf4c51d10112434128c7b68471338895006474ebdcd4b99604977aaf7cd54742bafc32e1ec5269605a149a0d6461d454949ea1b632d44d5446e12417a16c08b2c2a8a42d447c71a1b9b32d2a10892e4e35024f301cca654fe75e6dde06e71eb3b1a32add011da1fb11f576de5d9a5b3f95dcda833e98a72a03f2947acb9568ffa190d429d233be1ad125a13eba89d619d418fc8440a79648ac6fd0cc63b997e4a0d27ef35e72149ddd8e02f8e518f95733081566da0bfffbbcf91ae0d28c611fc3b7e1981a73b9c8f232843240d2e5b665d8bae85e19d95d615ddda8e8a1e5d4bcfe0a625b4dfce24590be7771a9961e3205260c9ee48346d31f6a0353f5c5b984565d9f4fa73d6cf15b9a2e438d1cbe880155dd4ab20281713a972028fbd2cadb37abc3bbdc9ec01aff65991dc8a2d8fd8d49a04632c4be5a50f50a823671232e7008503fb4dc0377813000e8f74695381e54d154da5b891b48d135b3d5b61a0d106605dd0e21fa405a0ff208bf84eae2d6bf4132bf4445473a9473a3091ff86d3c1ba734c4b7890eec7d134c4a83e87f818a457b88b8da374ad110d1ec80236fec0c087d5e9a8a2fbc4221ec8f898314626387ff65837fe2727dd37f1b1f755951c66fda0207600698d467546f4071741e809d67542d3edba8c238911a73f64590f1e1e4e4dc642093cff7568fad0df9128544c2ccb9653ffc64011ced45ed855b0ae2852e3d3181c1c1e2cb58d2cd7af7d4f00a993b7587eff48500be3af179e7844e969e123aab3a32b5799b48f99c0ca6a7510dfce9e0679ebeedfc164bd1a56024564c14f81c81855bd519b42cf04e11255802780cb6258d87248ee3ee5c5f197218cd07b7af7618afcbba080acafadf492c70fad2e682d7f23135fae38ab6ead387d2ac8f7fbf1e5e71ad6b5fbd4f272a2af1e7378e25a99a2f343baf4637ac9333aed06b470b998ba9c8adf7904c6e71745700bcae8031ff18ef0c53c830235927eaa3a6bdf07b86166e8f5c01f8ff2cc7eb88efb50f28d7313b8be0931cfb940a0c5515635b55346882233ddd254bbac7000aee373c3b773ca50fb68c8dc4294f1741fa3f2bfa6e4beaf803f7b4550e5938f17c25538bbca0f21bc885995146a5564ba560d050e7b6bb1bb40d1fbc549328b47016938de00148792d6f48be26d2f8801e53533c338e0ce93be3427c6213a4507bd01bb9203ad6c2d97662e65bdeb76a89f1a0598c4880af365f50d53a651bf2c531fe009ff6f480aad76f4d58abb8f022c1676b5da7825e908136d288fbc0c954197f2cdb268b414a9bc1f34082b7af971b5999291149cd6318be0af50950a9dd35ba7f85c63430e227d0222c84301480be87fdbc57c247f62e3b5ce21e3ccc5f8d5d32e205d46ce81cd275cc9e4f082bd132954f0c94591fa280e26fbd0beb73ef6ff37aae5acad41efa4c643ff790e0b56d05c277011acccfe0839270c015bf9cf80f946863afda32688243a206c4f698e5c88f428afcad7ec9f60ad17ef711f6d61fd048c25eead90fcef1f4789c4bc4863eb97e0bb9833cadd9ea2ffcc5a45a49b760f4803a6a0e0107ac9a7cf23370a0658832db0ddb914f339a1caeb9cd516bcd75462d2d96ecaae431547affdf04dfccf003f6c784e87ae6ee31884ecc99d6ea332fe4488f72659e0db23868ba8e1901ac37f88b10cbb1fb5b51767a402e40950dc387c9f701dadc89d3505ebc70a994ff1fe5c1e7be076f884239b7883235d87c9778655190aed1a4c14e8b939bcd5890ffd44e2ab0ed8c9cc01dca669448f6588eb790696ad3e397ea6426e8aead32d7da32e54ab572531fbd7f39fd48617ada910f1c7122d21f9c952acbb51387c13c2f522b629968261be8497136feed2973feda54b5e1fb9a571378147b824ec7451c999d3f2ac582553e0492d9fcad5a12591bf6c40e40e843023a982d63faaa91a5e5553cc05ef9b517732df5179e7810c10eeba1269fcb2acd55f78c8d703491f5e2342ccc1b58e42a775a7bee40a706423243304b45794eb5ccf550f4cfdf06bdd5e1e41f98e8911f81adbdd68b3569831a30dfdd072851775f0f7031e14f89ed083f8a8334c2c6fb34b17f6f9b7c6c67835a12e5aa890c4e6826993d067428a8f60ef8ad030739b7fd865d023f21415f3a741c8b42cf3ee80670df9b3f00c3b6d83e86f48d0af8f43ef249b38674a024e7a5f74733be4d2c62a6c43204c0ade1ba9a5fa5b3ff3975ab7c4823a74d8c7ad3c2d08bd19391b520316d15c456a76a9285bb3c867a481a0aec898b4735f3b70dc550aee9cca19fa94269c9b898667ec22ba47a850993257b4a94bc5ec3d895dddbb44e2c74a167d6ba707d7af18ffd264c15589bb31751400a2da30d92239001b7b651616324b37ab99c16a4c00060481bc16e290e6f967854712e5c69c28640d7f0d8c5b5184b4a04f9cc2071a9014e9829a9116b63a389888fe582ccbc706f2280119ebe199a0242126bc056ff78c0e6807ebec489b86a5afb8347bd4442ecbe4efedeabdd2766b4d5295796f9bb5799988beab20e8015d3912460d7465a512a812e47effc090efb6a22b09b10d20b2123b256921dcc0a0f9932ace570d138bb5295e583fc35ed817e99f20af681d73d379f56a1a01489e53bcd3b1bcc63d43d152f0b8605448585a63650bdd5a3852a2972b29fda1271fdbe22323b05508bb3f6d5c272c1815385c8e94a0b1a0f2f69aebb44c1e60c854877200de81d079c0527dff955503b51af4c19ade9bc8f006efda7cc5e3ccd7b4b1c6a305ba08db9f0bcadbef3df2cf0506dade03e719cfdf317e5652c05e9e2b4cf78512a557e71f4684a450a21e41078218e081ec618a74a48018f784eaa873935c95a512bde959f22ef4f11e97afec5fcb40c3bd621a503f6918d17095b10ef285411acacaae7284a5a3b69fdd18a77758549f0a1c63a1f2c63372eeb7124868fb4df1922f65ef3d2b43f411bac190518f3b7010cc901dc114ffc94f92995411d731ae758a48e6649a06a8aa6692ad9289bc659715b56dc024a1c613f2f853b20580dd722c07391fc9adb72a7229345b5e754bf2cb03545b654ab908e28ed8b72eaf69d9c9418e99dbac1bcef06c1558536fb92a52cd139578ba4b1b141c8870f5c8cf212a1abb8329090292fba60abbc4cd85b5a5d412556daa84d74090dfdefd26bb056eb3a4084e57c6dbf4dae0610b1be1e0a79831e700be0d58ae96b6c27645b8aab24fe3caab30a03b6af17267c9970b3c2b1fa16a1b3b6d0485467c6e6b75755658dc9805302c4d9c8438a8418d7fd0f18e1c21c51885101cd549f6d61d410368ab68a005db029d3e70159d0b4f4b0f258b083e5d0e0486184f58be182d8832cf145d14fd842b697034e5b2c12709dcd22514faa9b014aca4246557ebfa73c02c92102b67d96bdd3a986bd5df291661487123ed12054f5a2c3c7064a116e2b8c907edfa4981ac4286a1dbae2d504273e51d3c41205baad4ba98217364701e085bdfeb59325ab68bbb5fd6173a6b80b4114ad63d188f04a1069089c12c092c6dea5abd028d266c8ddd9cb59d32679ddb5024de70b10a772a4c32e789013a766af3b8fa7e7b62af719641a3ca52c16872a8372319ae0cfdf01f521b184c0ba1c35f9710531d7b610c27db4bf710c469a5191121236dd4a5e39c4d584abbeb947ec263510cad32808aef67cb904e77eae7652ce5fa65f6c5bd30450677c20c5b7d181e16a044ed7a712f4b82a1c44363ab587a049ac7a6aaddb37b51baa89b5347b7403050fa90f3ef211415157bec92a385209c8a3a5b28ab7331c1266cbe00dc1b24c68df04d4a6d95c2c080ef4ec2a5f24207b6e55e8b4dbbb8b40c61d9d9b63b16603fdf49bdf564e27866340cf30af5b3626369612250c37b51f0037fd72cd12dbd7f9d106e91f16af44df18e767e25b9c8d23aceefc8355a96740abd36c644dfb3faa0983cc5d3ec52bbe629301af5dfd15390514c0e5eff2080daaa22dbb6b04bef24105819eaef5280ca9de7d88488d9f7394e92073f0203a002771268c666735c1956525dc1a12b7c50751167a5ec9cc6a4cf25a5060ca579822ccec1259518a67821ae35ede1ace053427c1302e0cb5f4dd13171561d0296290d91712d857f1902aa84e311ad5070e806245e217c5fd5a1aa95cfa42f58accaba5a48c61440ba3daecf44afb2b15522b41314d82a4a1dc860213d6fa05bb00096808795b9ac55ce7188f8514001f6d0d6431d88160b7daa963fc4a1be434613ad1d6ed1ea484b1a2c6aa38a72b24b0165042d4f12b881577eb91f5a34818f09f8f7fc225902e058e5cf89906f844cb44a84e26dac457d74410210623693c1dc9dd5d6dfae01b41f9789705940b37f27531aac89b7a014bbac4b4e1b48f0af99a2dc513dae6d13549754fdb9334fe10669330fc78669b9597823f04354c4b366c0eb93658292f88d034fbac561b9547f9e8b5915a08c95dfd3edec9d598be98288f6ac92cc2554c3a3059c547a5d095e4792c28e045c8e91da716501e4a28aa1e124ba03439f6af9f31a096a88aa63a7630468f8ba05191ee9aafb5449eb4be19091fbfbf5a5dc42ff62c203fd8b5387caccdea246b2fccaf97fe51c232984013681ec0108f5bd00463e1b21ab052fd9d5dcb1759e44be8b280c283a76811a08ab146ea5561a76f9cec0cc369715ed86598e3da81e772d70d2cae6880428256082d67342e1653eb4a95d352ae2f7240f97738eff9747c2822ef19a40f4f0922118d9d9b8689f6d20d104b2034a968efa0fc9a58a00d0d421b008e0ac3737c4a07c1ad0c138135013030c17fc4390fbb2cffb9b8dd2de25ecdb89c24d5b94c39b2f16164b145e6583aa76616b79b085b6effc249ab7f7126cef4c06f841f982a2113c2e370bb024d39a90587c52e7b9c8bec24ce8c2a3cda14e556c3ed16c9f1219b225a27e45e19ffc098c12142104e38accd84d0273bec6a74ce111777245e35871aafdca1be13941a86b9e45349e0ea1580ccbfdb3f3bbd9e68e7712c063b6a4e79ca7fdff420610e1fc8e854625026d4cfb23f2621bf54bba2219ba31d0fec9ef41712042c39d62bfe42c95e0ce25fefa69ea5ebf4dddcfef837f7bc0e4dc850cbfdaaad3b45c121ca4edf7cb82bc98e056b0d0d1822200d252e88384d11ea307c62b6b30c54d5180cefcf9732775d59ded3dab09f8ec81825002e15416abce455078453d08d7753901c185cdf8eaf6f8d7466d0beaf83424c7a79bd28b78633b458175564715b1126c5af8b2eb6fe99d60067cbb03298b66562ee06e82a8f8798a2ee662a72df7cde0bb94dd408fd90443097321ee49a6f8920be8a884843ac702abb8c690a85ba4a891b80a4a463036e15f50ade8a47be6019f438c083b5e631cd67c150b784580a02bcba9d442569da632db2a1a02176bd2d42102f15243eb57f5ef2dcd4d15641836ca8751f159e5e3f8befa49340cc27e66c7d53053c005d70df3317e5760a0a195f823d4163a984503493b64327300edc29abd3037e63656a9a7e70834c8cc92fabe1b3e0a9f908210181c448e3824cc649043941bdaa3de1c595ab14587f587899fc8d008216df2c10e979759322dd7f5c14220e97d4f2e5bf3c54955ac8517aa80d340acbb8318f82714681d68e17cb51d2e08548638a5c84ed4388d582a196e93a7fe9bfd1d23bc7f9a752407508cc485b1febdfe487c5856e7170f41b36c817f6c922fc7dbc0b5aa03192eba184a01a159acf7fe2affdbbe1c0c183d536ed1485bfeb8d14f1cfd81c139b7a3f6d5821944da9ac9d62664cec9d8486be8d7794480b4def418694d65f0d1a85176eb19ff0cc1b3a5f4695a7b54e34ab8da7e2b3422b35b19d5b074868e601e14b0ced83093a15cd1d1d7290c8bc0d8b8c52360b715592e34f403f5236e9ccc219ef9a85ceb6637e8aa889e024aa60f9f853c963ff396f20475bde40f3eb82d7b9561cc1a899920705903943828a1373131837d2fed5dcab43e26fa89531f8c3fec33d0618769ccd556f027432bdf375e037df1e709ce3fdcadb905434333601d4e77153f19dfa8018f9dc13a28f033b0f938b4cf4cf10b21e5a92d8bca7b1d73aa6aeb8e7919cb7af258a8c0d7a0a9127b4af4c350b2619d79bebf28b0101448d74fc179edbe2c9ea21d318b436e789f4e658c16a03e52a53accf60b7c8913fd8211fdbc3164c4811c80e1677a18784be18ac962dcc79c3aa2db9bea074c243d4c5d7724d4cbc5e44587e7ea772394aa01140a2191be695aa05e0d6cccc15a3ee1def279fe2fd3d5ef7dca774ffd112e4a1abb315e5b3cfedf32073b9c78e63ad400014429064bd274272fd91c675526ae1b46839e5b3425805e3a61921e6c8fa90de46229f03414b8607204f679751bab5a7e944a7aadf0bc5d35f9546daa029af1cc4135e1e60a0149bdad4527a8d0e97524f430f6e287212abb69f952ba15807811db36313ab00e7d28960b6fade2c417ee1fb8022cf381a358057ee010fa205e095a9f06e26dac320e2b83321a2ae228e979f5b72a0c533d352c5ca83daf3ac9a2cf494fe2c602a6dce0bbba40c23e98abc2e7d3ac628b9302877349a129a440bc18754e0517b80bc52208d09c85075dff8c2e34eadf60701b58d7670c793b35db5b26ea3ca0b5d6bc3443ade064571c33f472b48dcba79f634ff2d9a78c937a7f3eece0c9c44418e826b6d4f793485cd79ba51198b886070d7ac7b6f3290251a5912baf62b426d5a4f323b3213969b77bcfe7bda87dfb878f88bc16dea05e7253fa4a4c1e14a759d2680353cbba0e8e50be696e4018e203b998138400b70f909395742af9911c248e309a03149fd932f6c6f0f2d6ae16eca2f23802a45ff429e7e922f0dc4ea3db9f2f73ddd975507334b46670cb02d3eace0cf93542e3afd40f8969867705e681f6968ef314c2d6e389300abd6ff82e0310e1c993dce44ffe5ec3ca1b0b5447fa71853d60e7a56e033f44a150cac479e57b2482fc274b0a05544b582297c2a527a75e42b4543168e75ad96cb6b824d9a19cf22d1468c61b72b049e2df8178bd3e833799974fdae30bbcc9a7d5ea2558d8d5cb815f3b04e4f35e0b6591a889a2c494a1122846ea9692836d0eeacd25a905b0d68afcb7d444eff1cfb81bd7782a8c20611ab7a4e41ce1b9f30d2390cffb21d75eee24e6f8bcee82412e52f61b21fc569b7f3a17dbb97b4c5daa59f3590d34f1597ced42a41c24b90ddcab646dd1ad759c650571225ad89d69d763870dba1307ad75058721a0a871ecb04cddd0105b96abbd4e53440258351871a41cc9254ba79ac81d436b0af77b468038629808a963f5582dab8ef55d1c60c78ad3223646f2be49eae40c196e6e64adca43dfb16a3ffdbb659663d34c4651c51c335990a5a78d1bd9df15d90053ecdd1d8346d1bb00225f3cc531d4181bc8362f0f8be2b2935259fae58dd972665ceeab8dd3ac6153b41e21ad1f2e22a84fafbe3ec9efb593ceaa959b13039acfc33c38438953a67b78647c75824cedd84a346c53734caec92bc81c304d063aa16abd99b47bd1b394a0e5f64b321cdecd663c70b7572f0e0f5dcf3cebbf927ddc4cbb10abbad8033db244e0fa26a36c3e8665181b63361df2c23cb473fdcec0df7e0baeb0c46e426220a2b638b9e4a1633628c0dacfa641172ed80db384751ce3d0aa8064f840d64a4d16cf185066fe07c46e56d992db667272f69ce5a9f253ddcbc51aabf20296247e9d6f7778584de4a94d3d1971d4f0499545bc7d770f5ed6109e3851a74b56551c1cc5e66f4391355a7c46894acd00aed1449d4a44e60b7ce737034e819ea5e3a2d00318340a0f21600e7a0da0800382186e204e311623d81b99c9cf0f67e3fc107c79d758355fbc0f79240f451fb1e3b2c7b89a4ee7106766ce45184dd1f468d81ea69f5742c7ebe69931e99f2f79ea461108df091fd2c5ff942b0efff41177eee511fe9b146b30e4ad64385400a4e8e34f70075fcdb411459fdf2f61f6bda7d88ab057c974febcafdfda88793b14d53f0b7da900d70fa83a58d430580b6d35e8fb9966ee09d2ecc0f4df50bdd55dd406389674c2c8979a17527a70746ae185669ef224cd3aa17adbd576741634f185e695ad4933d6f8019b937bcc00d1126a5148482b646c3be54feef6565b929b8338eb54358027476b643c29236033a00676740b3debbbaa14dcdb40f75267e24dba38cca4650e9522e96cd146388ecec6f0e9cade0ca26abf4e943f0acfe4700ee38c0c292cedac00a84c4d78da0a1cb5da92b9ce09983b9bc83eac518dd7e29f23968e0b2afd924ebfa8774fdce314634fb830692443eee4b2e727474e4e65008e0b12b4d1f307ff135d8f31df277c6796e85f3bc4057dab665588f94d94c01c3d2278ce0fe31c7226c2e06fd5ea4edb008b897938a3b8a70313e16c215de2638857468c76d4804b4e3aadd00b8755f826b5a3aac350a7fbc8138e0673e0e76cde780ee05a4b837a16b4071b0870d83ec197721af033c7007ba2a48f89ed981dadfbda795a6a8d736e2aac4804070a42cf1e6bd6eb303053a5e0f0a8e276d45902252d5cd4dae7c5dbf39e9221249de65ddfa247a4aa1f69c167b4a3f141d6f6fa73fc19b08a3480956bac18790c35cad0e8e92e4fb72a405a8342ebd079eb6a7edd87dd4754f7be06cff00c182aaddd26611f12282be58fab716f759f8eb410bdb88c68edaec07460a58ede0a3aeaca53454c13a6850c938eec2faa02a5704428a00c3a1671e5d7d42d0e4f6b2e67e36b931574988d9e432c908b1861c8c86a79d86eaf5b7cff15c4abe0cf670d30b7272b112cf3f964ad4b07830d8a1dca0aff227d05053412c371b435ba7af31c2126476579a5d141b5f23a79e36a0207f2e5995292da2921433737b74426b1cd1ad37f142de1e48475075049acd98cdc9df8c3dce187d501c0e7fb22d57656cc33c6858538a156dbf24ceda25ae0b6af456bd7d964bccd1dcd9e5b7ad70b0f4adc02e378c2202f435ed3a3f7da6a3c5b12f8245bf6f0ff634fe0f1956cf00941fd94825a9305441168b7d1f1f1d30e0d1e0b76e0d6a7fb400b89138e8aa8304440090f590b63400e2bde94289e8f8e8a5828a1123f8340db955632ef7bdf4c3dbad4a3380096026c897c3b15fc67e58320f307e518bdc70f29371399c6e441c71b65b074257139ce2b6983f0bd1007a9c74545fdae44eb3fc24a41301f75d48eb3912feb3cc9d033f11e2749fcae8e91e3ed05e7fb0d9669fd23a01569ab54b884edc07fb88a03a0ec1580f2712590929eb7789eda91c49b57e64d3e54fbd778c74a371657e38cf4aeffe579c7e32b31b04d4fa7e994a0eed280df53033ef8d21d60b8517d40ba09097afd3057146a9a7108d1d5494f96b387a6a76bc1944b23f2773df55c07916c3f4710892a2a0ebf0ce4719bcc373d31a0e068013552b0f7075b6eff5980bba3ac25d2c5f98d12948bf63be280cf14dc01d58d22885c2b8abc51cae97c064bcf84350b52dbabfd6471048f54307114f2c98d33230446726b8850aff7ce2b0b41447c757d196f20ca0d3a9139fcc2e2d536c8f8c5101226c288dcfe4b5108e8611f06e2165d1b512e02746426ca8d66c87fd2dc44a1d96ddec9c4c4a2d6ac790ea77c1ed6ea2f481c37b70d6d27bd7fa298e0a8e73343183f85a416e0ee44d9675ec6c1283db0447527a9383ca2629a05498ff913899569edfee763ebcc5b2ac8def28665e63a936176cb1876e640e58d66a312aff98b6af460f91cd739eafa53e825c87720814d9c8d0eabeef12feafd29e6f12a28c43f39f5632890790924871da6f0b2603a7ecb6d49e01865a7e6e37a639be29bf4a428f46aea3934bb82f6aa0d2f4524aa8b5d1f5111bd4fc2f6a34dd494e7a19cac0bbb6beada9be9cff25c92036b9c865cc252c72c2c68fe2a340fd0b3bd02408babd7f2e043496c4c1e157bbf1c7bb0f904c5759fe8b1e34bd65a24dd6c53a2c0fe2114dac0a6598195292c0ce49249a108611c052205c417100612a6d418224723222617267cc752288880a406872a7b019009369a20a2959f842008bc6e7701fc5b81365384ac018ee8990918ec208adf14f0430816555437ffb809bc2d337f6d5657e586fabb953603fcd0b507f57c94bd14ea7fde7966994258ed4a84d20a5102ef51a39afcb7bfa0bc2143db8e2f7913b2b21a2b1c985c63522b16786ce2f03651f35d79087349025683f6f4b9eff3a170902994176ea1eee284d124ec7e0a710d51342bdd1c181a56a0cbdd165f9c3eb2572c83425b343f701207b68b883de259c869ccc601d0e73ef56d76f7496ee073410690c23b6ed325694c1eb437e90424af4586a84a87be4910fe0eed07c4794b50b0ed3927d68d74501b2d1162a6483416bcb14f6f85d393647633d0f3c6c8ea1c5f17376cebd1e762076c97bd43d66e1bf9d212705a5149854232202a3d9a38bd1d3952e9e2400be1d96f7cedb2af84b2f2a9e971daaf63a38b96865cfe04a75296ffa7a6a5d8aaebdb0dc550145b93814459964264c83eb58aa3a58b676ecc2e38bb3e30f02c15dce879363fa86d8faf69b52af83ab70a4ae4a31d3abdaadaeb0f9da450121d19fdf3509027f47e01d33a66ea1f970bedea7294113228a907cef206068fa48a6e00f89f795cd1f1879114b1137effb28788799073198b4179ec84db5880870bc5d36da34fd8e7420821ba73da895a8136a017b35235ee5253afe3b1b638819cc67965bab711d7d2e70a5bc0e45bf0d4ba96b6e7d42a99407f2a4215edd164ae38e2358902c6eb0572b69be44d855f168e19d84a56eb7706fc5a1bfd3a6f340dc40c3d00450b36a8e21174343e58252de017884f1ea8406e45ed71c5216a65a5f2393a9615b1529fbab84f8d794cea865d3998a8aeafe06929eaee487ac2ed2f6944f066fbffa186a328cb8a26f146a2fb10144cb7965ad010116d0b09520148c1da454d9119474165715187f467f0832b8443147d52a4ec45b27596cf67a596c79c121760b866ab989a6a873aea307136a3f6dfcc61e0eb120299373711a5e1f9bab6573a4c7c4ef0b39372642ef768b2d8280c52c68ad0a5b6a0c386c86852ec5f749a12c53b516b107b61d69e5551048ac9b921113d10b7200fa1ee3afdaa8fe750639b60ee2b62c37483dd90f0486ff0856c38493c281cc08a28de2ecd58b09f3b30a91e402173bddbc955523a499927e3a73af96d2a20ba95fc53cd8d40ddb060ea055e04319de4200f323339f14127c687d003cfc1747686bfd39452a1ffea23bfe53341ae754e5bd9d8a1828b2ea146377b0952b2b89ac54aeb3b9da4d29bba3f8e6704aa67c365cc1f1339bfad5edf819eccba82cb7bec6ffcc21f695de61f2160d9c0d9b98f44dde66811dcf51b4cd8fc52c7e27a54d3043aa43ddf784dd0cbdeb873fb053518371ef0221a0d7c97501640ade7c0382aa6f9a4c18af7870368be120d719f65adcf6447f06ff04b2bbb167e8402b2cf5666705b2555cb2943a346b72865f32583700fe72057facbd092f6625363e0e4faa0fde8fe7769bbefa8767f59a142973ce1b610ae2f227884cd2f5e289a07d93019d71789d681b175afcff7f2100fc92e6b953a06adc826a9a893dc2c50521fd73c4f0a65a81298918b1287e73e2aa69ced155ab1269f352867465402ea8c36361358598d03011768b6825f32909eb25327b1f542974e28aed5c5699cd00bdf4bf8c1897afc217f335eb9e46deb5a5445dddb645a1f4c05ae338588c693b6ae74094aab9b0dbb1c75fbaff94be9b214164343384ab6246dac508158a906c8768961a6478465134e05708c8bc9353a1599d4c6952314fd011b35f1750a6a3f0eb849754cc133443d478026f8e1708d9a07d64d6aeb2248cd93ba4e21451f8aeb13488e9736593ba074cd11c27060e51959b5dcdbed415a8b28ee08355587b1ee80d7918df41081c62a754b379000dc610d8d79552e4136586e56e6abf6a0e5f8afed73fdfc1d4d57f58073c051a871daeadc140e70a44dab8f7a0278ada4235331b849c229d94573d5d44e521fe6a712c25bca8ef25baaba6271672f51278ee5756aaddc8716b0a3ac8d7577863851356a9c5b5762c077fab9a7705a1d3bf8c5c742c28360be5d1488efe441b04f48cce67cf44bfa556a1cb15da43cb06a54a1fd15ad464446edca21a3eb280845a642493b4e0841406c1725229438ffe89f1e42293047e27709b916dd16b6d4928c2ef2f960bf411074f1cbead8a65023985ff11eb840760848427bca7b12d4f4c2bb9ff57abaa7e901d46899b57ccfc86fc0b7eda3bd2aa253025c276c41007f081e962faa032319e7ff5c1d45af7b1942f0258fa09587c14e41a5bacf8247d93cc2c93f8bd7c36ba89aa080f088e8d8de75fe183ae603603a183841f8e7a3f28901c1911b1a2ea885f140e4afc1957290a38118aa1188faa7733ac22a40b21f89e3e5b8e2fd263af3eef8a605695014effc9001a6f0de07462052a601b920c0272b7414928626a2bffd7bfec1415eca889d820b7f4f882a0d688fa894720a61fbb51daa8f05127eefad29f8cb55edd1abd14f3c1d1e44577e9b5ca149c3908fa81a3331e7e734e2b770b8bfe1b23401695fdaddc1686ee6672d2ebf43e2742ed03af0a280945de2880a13b3307a2f34603dea01fa530000901a6f29dd3d5793f7d9b14118a9422a855cbe972c9b726adc0d754c0f8259c04922cd771c2d0c6d6ffcca65ffc67ff61dcdaef19fd1c519e323e493a586b22838c20d0ade18d66201a1ca1b34f966770b893b113b45a3578f7f037aaa859d65d1528a4a4a44563b1348f5a015220eaa319936f7601ba1750c09d348292cf3ef8448c20acdb25345ec970d3ef3d7caaff6f30b7c522022f4a848019a9fa16375ce5f0996139579cd984bc38fc541e889d70f7a2f7ecc52314e00f40461c4db3e49b9fa34af3e5568ea067df5e80268016a8f7b27e9e11dcdcf629d027b48fa04ea579c2c246f5f5e4801e0d4a8ab87ce45d6a539797fd87c889293cdb6050e1dfa8a8ca66e5ac38bc73af490febba73f392000777485f67afc9fedec3bd94f1353b5b665510de716e19e27c25964c2a938320956d54c4fab34628b7d42f9fbef8a344d7ccb2cd3e35855e8d2d5aeabffd1e1ddaa19d97796816a9d07c655b555e09696161c7adcffa7afb90bd213d793930984fc83ce5f6ddf9b6c2f7345546a42f4e225b0fa9f3b7ba54fa523a9ac7733dea907649310b5b21ffd258dfafef57f30b3a84ab9ec4654ffda0fd5d1a2b92ececa265335863d402b8cb153634d726341d3b31a2dc1db7e5538cce76031da5af8f01244db702084a7ca68777353c9fc47dc1b5680d1de0365e7b2af7fa43caa4cf8d50225da7a2d9288528581327774e4d49633fb1fb9b5d5b543f0d7e154f00c48050ceb7cbccfacdcf617c63a38f5202dfd11d7b7b27f6234e14bdf92e746fecf3bc5ea437db2a4a612216f09854065b11868fa3b82f691c5709de3e8d7c1225c313d7f1847b3c2abbc2768a08b93443619d3ef88f96c54e0dc53d8382bd84899cfd2ebbd32b95a42b434d2af43b0bdb7cf8c5655b5f9658c1535cb62ce6dd061749ca5055a6b24436687b7b04929d85f06f8af70d25b309ba0e3f608883ea538c41079d61fdae854b26c8a167c99b56bae587b22efefe7bf456478c0a90c4deba949bceb38671d8e77d071f64acfddb870842fd9daa043c120d41d7a91a67953584c0eb0a980e3f8a2e0bbe74fe8c5ae1a09a50acc1473c990d4513b9657203c0635a77bad0c91fbee9c07a56d64c4da129c2fa105110c422c75925fc31c66516f023e71df978db5d7db1328a2ef257aa1920b3a676f7f725ca4fcac5d9214276bb767e1c5fd690e907591711e0ee8fbec8e28ac87e8d877c5a72fa57b7403f8c38276c02d1b4a0e6d73b0e9c2ccc4f5712255b601bcdb1a69f5ebd9f9ba01438f1e2658faffd3cf1f1782c256bc207aa236ef07e09669865078534464536f02d932ea2b9f17b35aaa6912348d74e65614b1a6c70f62203d6ff04e6444070592ed5b78fa0a39f4a4a064a26cf8554f6ea585b5f9756d012e4701746aa7d76a01eeea6b8a30cd37783251d5d35f7016acb7bc138ae77f63a1f1e09357fae0e4ecd05f0b14604e84622bde5cf710f425f22caabc29420c2b1b9e0f4fae5aba3211c0bcf04840fb9f1047c1eb8093810809b521cc69daf9f02c1229258aa410e774b038b52ba88962b6e6bc77c1cee02da87268e88c046c664e210e103db4f59d7cac68cd562ab1462a379f4a076961fcd16d1cccfbaddb58165c6be1790dc29b14c414f3466c5b8b2a58cbad63125b838a4319e077493134b931aef34e2ea66f61247a0705be162f342f893d95b9aba95ffa3e2d6ca582b6eb939972f55997c4c946e5617fb46f92a6605272667fa28559343f9ce21d195920421904c138a6c904e006d52372d69ed4c1ba67ac0278cfb4d936412529c76a9802d86099de8824ae6288282178ff6afe37327c06669c71ca0c91cecdf9b5a3931abad1667c6575cc276c04ab4eccea7f7396d63e1fe5b77616329e406ff6863153823eeed606ad9389aeb73143bacef9175a00ce7e39fc2b5d0ad6125fd95f2584a2c74618b3660489e759956e5af7669853dc3ac6a28429a44aee246f2fd2f78b5cd3514fa257ca9d9c9a11fb75e34c56cfc7714707add3f881eb31dee8f22da9b847cbddaf691892bfb6debed9b75962b92d336e0389dd4ecf2325d4fa035adb2a935920d032930ec46212175c0749db10bd930a96f85e5e0f981f3e1f3085191e325ea7b301be97c42f7a4b11cdcd29ef05e07250805073aaee09c74707f04725166ea4a9630aabadd9b733f0bdc4828f24217b6fb2e5de52ca9464380918093a099af676be8f74b396bee526a77255d79df7ffd6ae5ee2341996653b557778a5a5043a744f94be3892a85c90e4a1b103f7c45257c5c82a29a99810626b013706103d682d58b263d490a43e31b54de5409f28d2ce60fae2c8084f9c7018c189a217e030421353ad296bc410839a86143190a82206241b0d628861090c6af00003152650c8000312150f3ae5800ddab728a8f62a3105e629099ba72a620881fd6910c696d717e44a3c2b601c19c17082fdc13072c0feaebf77ac312ab158b2c1ab355f90e7f882687fd144059e0fda24289a2fc8a98f075d7c91039e7fc12c4ee0f9335fd07c777757e207ec17bbbbbbcb7c414e3d9054b224f1620a3cbfe5d44117319c6f747a40b1f284e5ca1357ae60ffc78204f61fbdb801fbe7c48062be206fc2abbcae4ca1f2822faa1c5539a28ba2a62ebe80c11330e8c20a1254a460f50202152578fefd82e616f04a942d9690b2c51b5c7481fd59f74e0dc134ebc10c365450c414614a8724533cb57184946ccea97191c464ce39e7ea0b9ad96bdd603104167160ff9bc515ec0f3a2161ff9701fb8f5a8091c3056c4da9827d8b2b8ab8a20deca04c19292081110b8cce285ae30a2b5af0030b66479c685b90c0eb971e3aa740c1f32fc805cfbf57c6a81629a4b076b8b9d56ad933df5e2b96b082060c4af104fb6f56a42019b17bd114033b850537a8a86aca89a54988a62398aac0f3e7fb20441c6d38c5d186ab10731928e102ec8f80d8e469b562fd2790d0026d80e7d3f96d8568bda2485501c4184711d4c51c6c5cf932545c39fddba9383a4cca2b1f94728ba7d76b528a375677e2ea6fcb7ec70122b8fb0bb22d76df3d2bfcb19df4cfa70609d335a0d5fb73e210eec2ece1ee57abe7bcff1ec887f0170e71ec89eda47570df85d906730f34554a98e2fe5a4927d6838b7d8b60ebfa187365d5da16ad5ba0ef43b876325037a6c8ed8f99e1b6d014e5094b2c58364529829ba8e882a927f3c3b53237dc6f31b930dfff36e3f7df9797b2961debaf749e8f01447ef8d8268c00e710cc6957b259620babb005be42f9c3c7165fe2f4c764b95942750671cb28dc2f37bf30310df2a3051194dc87d274e85c32a2ccb7be250ac93ccd0f7d63c8845aa22b85d6ca06208021a3f9219a1f92c92266fefe26e66043860a7a67c41f0ea30fe4620b39deb82d13ba6644999f81f921592b74a5d0fa988f11855e68c8845a0f233671bdcc884d642f70bc84f6869e1bd73fc70d36995068c7490f32901111e18836a26434df0a853e1f644462cc90d1884da6f57e25668b5731456e67a3c485f998db6af98faff532392f39aefb99504ad8b63d953bacdf582fa1f45126cc09250a2d1c6ecea11a270e716dbb415862ceecb2fede3027f6c3c797d0568dfbedef775ba8ca89e5e8c47ca4f73731b7e02375c1dd7e04e9fee56f98a910defe4504f29ee1b3c255f8859f7d2f1ce278aac22139b11682f88e0cd2c20f1fe98ba0040ad307a24f02fd1cfa31fa31218cd4cabf1674620e36ae8e0cb59fa1d60d998d6b684b706cc5cd07c09a3876b93fc4b18c99baad229934ae7c192657ead0499b4e7a4f50ce2a6bfd82b6eea9b5dddec77c31fb7f407bc588d1c2944ab976deeac43fa0add5faabfe95a63dc5dd071f7ccbcad7b39aae86dc4bdfb1bf7a6a57331fdb68f52bb1ce7cc70a739ab8ac9f79f9f96089d29b0933f5617fc8488cfb7d6b56594f5a4c6eeea49f57eb98aff2e06dc29fdf4fbe23fefc86923efd2f25005eca57f772be9ce06cbdf41d98673db9b9937e8260cf3c6fbe5703be9c5f1697f5abcf2d64baa43a780b7e370c73e3f0c530b35efc97ca46cc8e55ef81981d8b611876966e3e88bbef40cc2000440ec4e9b2a0982f8d98ef8c9841993cbe8879c45dafd8501267b6ac8fbefac24c716e51e918649f61f6c1265a4f5a624a529a89eeadd1491bafb25fa374524f08ed9cce7a3eb4a759081e42a71c1beb9860c51b31c7c41c1f1df790383506885b5f2c817e8b417ceca7172cdf46895ba42826b34f8395152942c3cbead39023d37efb2232741cb226f369b0324b1fe4ee0c3783f4675e200375f305250e7d1be690304a801c62ba23832045c81f60fa302e7bae6212873e9ddfee6474d2a69345dd4248d8acde8bcbedb05455ea0dc5d2d2142b50547081e294e5298a8b149e4f5dab4a4c949e58dc33899b1b57252bd2e78adc017d7442f2bc2b39b93c0b3d923873723fdf97a63b75cb09dbc41f13c672dabccf558c59ba2f6edcece1f94a4b4a3ece239a4495e8114552fafa5d59f07cbf22c7f9ee848449279e263c5d0a3c3f8f78b6e85624cefcdbea25ee8b96c1e1ca97d9e1ca972fd374e577364a5cfa9aadd4ad1297a88bba67d2ed386172c268b8c20c577e1e8f9c8d4eb5b444cef9203871db874eda647a84eb77b27b71b934a86a1486ee092c9ba058c18d8f9c0aa41c5d687ab8f5ddc895d4235c5b02b911d78b7c1cebb7c0b8d98deafcda4748ae247d24ae2d246e6e6922b559e2dadfeaefa0e1b6ec84892e94c072c22d1feb97c072c2fe391356819cc3d2c8c59829de0b1c37b7b62940dcec452c96af1493e5662f52c4bd48c3f21bc9c7fae2722b2d617e2b99583e88ab918f9512d11935a244b48808ce21906d579ae846b81a71b98d9b1ed91fbafe996509db99f334d3914c7a724467505880b32bc1734524c311383b12142457c27342c19309cf77d9d3bfa01c145cd708d282b0e4f6d3f470b3cf90f88e1be1e94b73ce1f2ff8b7d57d34df91e6bbd17c1ab6aab8d9c620dd6c59188ac499dfe10ac700f1bdf4b4a74edae4b62da99b6387bb0a85fa061b2029c958dfc9cfc12c42520b0f5c1cc958437c9c9fff27d32463e46609f5d482ba56f010874dd985e8a3ee6ea9f8018a3f11887d6d041bbbd3f3fcfdf7fd270e117272ed67d9e5051fb9979f099e485dfaf8c3a90d9287d01f3e0e1112e2638c969ba515895558210556b8f2b0e5e32a945792a08892c9ef82596ece4961eab8e8e35d2edac89ce0bebed0fa7ab6fa753ae99cd4ab47676b7775a57dd2aa6d965375dea77dabea75aa158b5615372deb4e6aefcb7c698f839994568e5a6fdb569e67b574926b6bfd4edfa667dddddda7d74a35cf52ec3edddddd77a6e65313e974ebeeeeeeee4da9ba33303a15777de7a3f5eb00f6ca51eb59ab39557195eb2a0296e73bdcd701ecdff5819c0341270295ec5422e5b4d070e56f5fdc1a2c9b5eb0450f97a60596883b33846acb0b8c9278c10c4b6e0c964d53aca1b1e0b6b06c9a020c0a86b533534ca124e649660a27d803fd04d7231fa5704fa9dabafe54a5ea547daa51f5e9bf3e9d418968d1949a539b931597f49086b23f27f623e7ad9626a59473ce6c3f88f6dbcf1226d6826c6f35cdf3a4940aa05f4d682c02b15f29f6f7a762ab05be5661a6ddfba77a0ff36dead68589e5e7ff805c06d99e03930342787b2efc4c105bd60a5f4f5cd932944082d4d7347103f5299d49c1cd8fc719275a746d40943e46f9286160b82a2c664e20b9bce73b79a83fe923c52ad1fac8899e8f9c9855ef59cf7256256eaf0a7d7b0fb9df8238778edbace52cc75465c969f577798b221021c13a45f742b6774a55e106ec7328d4b6a0777da3a1c46d05e7c0b2a98b14f6cf8aade4e3fc4d9c51136a3e31dd77229168be17cd6fa9f93d355bcab6d47cc2f3a5e6d47c9a5194080a44e2fa4bdad54e4a1fc71df73d170ea1d8ebc22c04e74f94cf8540ba211477df710fa4ff13817022105709dd7362277e12e30d6af3feef8770988570f7b6b96e6863220bc155f49744f84b4bdde8a44d9e52d5dd7fbce0d0d10ce2f8414a065548a144e6370d282ea482b881890964fe4e24e54a50293529a59452d6de4c6805501e4cf7f1fb8fee5aecb8f542955d9bd2ad583675394387db62adea5ef076f102e7d1a9e6a0c57cc1104b9a8accc462cb1b559a6801850f6ac4105eb1822850da408242a20c55942c335069571a77c1827d005836155103abb06ceae284655c8a1581657e0289379ce0b04618455099e2e4040aaa1cddf084ec5a6101910a44e2e61bdc3dfebdc82f19f0d0850cca685a03ca0c7c98011bd8f39d2560f0c27ad9dce8a481843d8d26d43082fd4735a0b07f8ed413d85fa28105f677376ea6394e39767ab0cc3dcc30d28519639c3144d3196c7039c2050a9737b07f7b1e5417505c71a5a80434500200368ab0a031c31860ec209bfd3048220616082eb8f9e6c679a8acf5bad1d952e4c5162d5150444d29238832a6b053c704fde123a533236a667736121fe957d105828ee43337a28f29cda11fa3fff447fa8a72bd9ffdbf384d2268d55699484e5799efd835845b58ee7c457945b92dbbbbdbb7551ec23f5eb0bbe8fa04d7b16ca2410db85faea81799b9912d44d85fbabbfb949d83d645b70098e8b8f8e8523e7ad4749a30ff7e8180911b346e9653d469f2b84c5403bbc0e585198be5e48ce3bf9cb24b97c9e98942b184fd9b29c7c8dd7ece1348f0d1bb2ebf0ffaf2971c2999de487cf49ed51cf14d25a55271ef33df719e7eb24444440483f477248efd5d8913f6258ea4e2e609be93b9969a301f4fa8e2cef721a5b50c91b562067fc4aceffae8e81671bdcf3d43e23b8eadd84818b07a6b99f07176b7a53cf6d2b760b859b6de5562b63053cc604b8cb1164614bba7205eca2c608a80133671489d0fe44c6143f1d1bf4e5cf2c27e27145a8a68d66ecceed2535ec48b1a8af7d2e411e2dd4cd2ccd2554105145468e2fa48e166268b9b737a96e323502ce76c6f6f66de92a1c6c8cd2d65edbdaa2589f346124b4eb47092c9e2bae1239154971c3adc5e7298bfb5bdd456248e7f4c979b6f96bc89c0721ddf21ee8d8f73b6a4d4b7d58637f1e6c677a4cae7093c54865fca89bca8a5fc7b2ae6069716f9e84b325b644d0eaec444fbea4ca40f0a2a0091d0627ab97d6b87ab34ad28717ebda25c7fe1d7119542a489f642449ad0efb8ff4ce8d7c49cedaba2cffcc8917ce646349c71723325ea50154ad7744fa17b4f14bab6135d0e90b297d1d0b2eeb39532a19675e20c969b7dd6df81213ca7d84f46ec4e67fed4c89f12f9d3a2a31b5e51eec42c4c581437cb252019125c97c4e210de81e4beff0bfe2cf8fff06f61b98e3bf786f0949e7baf28f735d7fc1e52710fd7147570cc47e741060afe2af80391708132b0bb3f0b12c7bd27275c4c14242959c7c529064ed4b1f62f384f9b21a57d1361ad890c2358d3344dd3261d1aa13d0dc9174fa46476c2b4afc9e1d2d780a6f6c2b460100d489ffada0bf19dd790192a7e08f9d60d6e4bcbeda680422079dec280b56b03d674c0dac710e1305a6e7e61edb5a58d8bb7842bf79d90eabd97ef855d3461f5bbb08926ac3aa1e03bb9a51b2a541b212e6c3496983a92cd4c71fd97206d4abc5b824bfffd0bd23cad3e0d55f0b152147880516d086ee10b0c62490b24990cd1b5b66aaf7958c813973a15c13d90a350dfda9bafdbe41f472bd4371c0d4124abc1a1716e226d6bf958bfbbbbfb0b8249c3668beb9f6dda884ba7fa5de43b8ee485731369978bd2491a0aad5ec8fbee55a1d0f7aaef565fb4ba5c896bb0441c4cb22f943299248c9081724121d57f52f37f93354644297182b868594ef3486b8ad9138a79996f8542332f24b9d0608b1559ebbb99b091de28c34876c47d6d14c786b81dd6f19dd6f7affe763356dcdc6a8d71b5cf2dbc69af7a4dccdec3fcf62d983a13fe3081a348860437bfb6ed7720b91bd0f6246c9fb37d6cfb971b37671a21db3ef6225e31dffb891904652865ad50ca3cba7d67095d263896d886398887e94f1965794ecd10aa595c6144920cd3ed9779e236086454316a25b9937a7ec4c9dd63407de54e67a3d1dd2d65b56b97be9a620c94db3f77e8a44df70611540ba95a4bdcdc4e0e83dce9263912499f9ef47574acbd1704dba999382d4894643169dc4e25e3e4e6d6a40d87544b35412561fa459852da7445a9d6b391f84e23d1aacc39e713283b14c9bc0a289e5892cd64715b4937cb284c9f529129bab98b90b44562c31f326ae6889bdb8936154c7bb410207bb4986e0c113eb4105605988ab993682389433fe68ddc464e64b4b8b935bf454fe9e656abca9d475e0a984870988bd2159ca7951cb52044a88ba0a860e7827313893e352a24c41871f338c6f01643c4ed16746638014dcfaccd6aee558a198b81a0b5e214e3f66f729bdaa4da9c734e5ae79c73cea694ceea5bdb39a737e79c533ecb0d5aaba6695563c15b686f6a4635b491a390c9b37a51f585de883515f0f672d46c56c0dbb79cdbb77d69674b9cfab8d3344dab745220f3a9a67d37e714bd6f55aba7fded392bebcefbe2491551455067df96ae7dd2faa37f489f8e85167e3ce1582c27671cff41f0dac891be90c9d3b3d95401d797237db902eed96cf69a46297dcdb66cf9633e8feae5ff50852d8789d7da1f5e55799ef63fa44f77e98f2d047d6c0551b17eabb9f27e481f57899e83c4b1bc1fd2a7eba4151a214c5df915cb26244ae4e6ee1bb574d649e974ad4ba076d50dd13e69dd6a4f3d9856ac6d7b56b80abfd0a1fc69eea00af30bd3bf79b98d7fe29530afff3d5d7dd6c1540c7f22d1348d0489bdf721b1277a9b2acc8f552afb9caa622b86d99fb4da4435082a7d67d3b4ed73b4dc4c31a5dd77f46fad9ee7bd0f7f4f1cc25ad885b971c7bd6a48c5d5ba512a5dfdaed2705a6bdfc7b4da10d61c8a05283afa43ddfc21bc8551d75f9b3bb40e7fc22e5ba90c373a292a2aaa9fbaa39e3a2a0a0f608fd1240c2b9e8c8c8cdaa8710d949b299d12c7dfb3f961546105165a186d5edfba72f338aa71411f7d6ce3e6f1ce29f5c6c80556822836b01cb180e096d302397a77fae85a4617b83bb52074b979c4de63b4d267250611a61e8552ad87793e61f72e431a6f603e615fc22e85b3d011de404b61959889cc302702a10fa4be96a9985b0abf70c77dd775620ed252b87beac3e654b9ddfbe7a325829e1433fdeaf1d8f99eefd0365a82c0e4563147915bdffb828a3009a97f419ad74ffa583f6db32a8f864c8290248eaaf3be1678bf4f5382673daa46128786f7ce240e7dc1689af612f38d3494f98242a5279386a669e83ba6629600963eca78312d1a4fe6036540106cc5c080e0cb05419005ae3e10044140eabacec5dbed3e370d57d14a9caa537368d5b4ad568d6a967a9bb7b55a177cbad65a0fe9f5023f8a9b46787e279b5ccffa38e95c652078669bc37ade77bf567d109cb817fc9597a3c9ed2ccb86354e1f2f7c5f5e606aad55d3aa56b53ae2189898971bc35a7d5e4c4c4c4c8e9596c401189df42e47910b76d2a54030d43748e1ec7948dcb62e708025176760c1c5194434f160460749d8572f57d0a44b1632221d84162f8290b1fe0b8542b0414664662663d11a5e0fdc6029e5607f2004e85071bf5f7df7de6f3c8e2e3859525abf277754df1dde29d7e952f111c97e419525e5a33fc792c29b164a0915c1128b5e76c51e2e8b2dc5bafec6d747d625f2bf45fe2c297fd6940bf3810469e1296e802a11056e11c8fc8f25c543c9cd2ca90e9236d893cece4b6fe63b948adae7c891e3b53074b97ebeab046d7e0be96aaffe829e030e5e402e33c5d55e7e0b682c86ff7960f372f2f47cfd0f8178f012d3305b243e56a3ea12c3dc58f47ac22aab0973e39aaef2abc9c0954d3820c11cfc374093f5f0f89e509b4dd8cc36df6e7a4b7cec90fabffbb0f35eecbeefa847b3c4471a241f9de2ec587d08ab17c006e3688e244e68599f61660da8322fc71237d794d00f7b98986fb2363bc2b0f7bf09bb29b0b071e7747323764eb08ec98d9a255fe35f33c577fefd6b9ca40fec6f3eb3b08af598e60520e6a7d9687e87982fa6d9baa909f357bd7f23b076ecd8f106f81e3b441464f0f9d8ffbc8ee84a41e77bdee58a00cff7e83c90775393076686d34ddd889985736780b0000f0b6b8a248e3fcc6cfafdccc2196606338b8505789f30f606086b60e10afb8839a262618e028439a69edc5c73348bc2fed5c9cd51c4c74714ea21c2a4d0f3b18f89423f224c8fe842c13542c3de6d584a92799126a66443329d4c3385bd2794fe0e82f7d61cbdbc7c070b1d77edc1c2c63547d3da996b8e60a16714ba604f4436d404263a40ca62cfe363bea35e4fe8d47760a2d613b6cc9b4d9e29f3f78ca40f4ca4b3ce95662471bce7a7ac471422228b89da4c2774c1be0726ba10019e8f7d0408f03d1ffb1dd84b99d0eb892cf63da290abebe9115d1d1589e3dfd323ba601f135b459c00fe3a5238c3d04cc1c4165158e4ca7c8699ade0cebcfc8276cce47cb67846c7cc003e837806fcdc019ef98e8af4c179ff8ec9776edebf9be23c3eefdf2df19d10debf43f21d01bc7f77247d60e367f0c784f97ff0d9f1f752fe7491d6e1ff3d8fb0489b4d9e9e0f01f6a9c0f33f2f3ff9a5b0f33fa2908bc70bbd9ec87e5eca765e7eae9b8fbd503b91c1248b89ae1d381f7b21d81638acc862afc3236c1c0b3b8e2225d94fd84484efda1321dcf13c428963a190a4410f7044c988783390fd884d767cb7230ce1bb96de7305db1116a0c812069a3c950a09ab7f05ae9f23665b05d7d751bfc0f5070085eb838f53df27ac4f1c56ffa6be00c21a425861619d499caac46145faa7ea2075d4f7ca04ae3f8a1964826b5400c4ca03aeff8198dd46cc16d7aeb107626eecc1d39e07f2fa3de2ffebfb630007ffa2fc46e82004f2df18685289c3f0261cc21d841900af13baeac75ee7774257155dd08982451832219d271243828aac09fd9edf791e15dc5c730480af39f29d0c0b0300e1983362c18168f39238268cab7d7e4580e77bdebf0810e063ef5f0a3bdf230ab9154f643bef5f0a3a1f1385a4942620aa90e93cd0ac19c260983b0877c24e0b198d36ebaae43a6b85d9c67830da8cc3d99bd5d8e0cd72855275f0b459ee98e41a2daa910d73d5016798990b75d61cd5244d1e0c4cf1031cb32c69bc5103997f8dd2e4f1c00c2827888cd020e58accbfe668f2c829359488824a0c6e48c30532ff1aa4c913022ccc4041142d5a445de9b490f1ec8452d6b5b73301118ee0424a4600d1ea84525675b8d9c2ba211ede01101d929b5fddc4cd3635adc39559d89094850d47b89bb832e69249778d8e5553c4ed9f41c1cd39d84e3be382dba3cbc9c989494a424ecce783af077b68f5c1d79863336dc6a26beb9ceeb286b044b1ff0a4bb043d12736a4e01980c05932b1c1046749c58a7caa74da60a178be0f8aa78d8d0391901323b20222712518c61582e76b21902114bb4ae8ef9f435cece1a3fc29c67c04c3b8ed53f4f1f29d1c9d988ff2fbe682d22eddc02a018890fa2e1380489ca5cbbfb194924926f948646f8b12d1a22935a7a4947c2792ef4595467171239b60a1dd022b58a059b842b6522bb59366a25b899ed1f992ea2b134afe648653e5488ab835445ceea7b8050c94600160b9c5164cb3b18c16df489e6c49792c1d21752db22045104c829111b37c9907721ff4472a7e17dec984d2c7980bf5f2f761606062c27c710c7ea12f61ebe52787b06cdda7f763c22c84af7d98b0aa24cce71bec3b3916e81f09b3e5b67efe0b7df9243384652865440bb48e97965c82f412c2c0c084ac971f9d491c0f7d899111937b7f267d247e79f91be6217cdfbfa0eb32617ebf8ff92d524a5f6062e4108e09db49eb7861fd0d59ac59e8488e543dc586367f23021137c9958e906060b8eea1bb9f9113fbd1c2105d9ae93c34a2cf1ce63f23d21913e20c16373fce74867d47da16133540e11e2c998a889c70bf277d4a98af79f6a2f9c4c77e2042e6bb4cd0dec5bdc456137303d17e729ef52221dabb4c70201b56f231d682a0e87487d289001fad0541d12758a526664b31085a1bb6ffc8b7d31b0399b2d6d112678a58bebb67c7f27bce39e79c73ce39a5c491cfcad2b54f5a35aa6d53d69e1d58c2b0fc50f2bce4e4f4264ce5152c1f4b1ea07f51cca0682bd7b2fee9077d2e8f10b07cab0245076a1d2ed6a3db6fed573aa95daa73d4f15836f51481802ad0d63749e966a9bd4824295fd2c76f20c23d9b3c2f876dbfbdf04bfaacf0f6364adcd5b366db03396bfbd5f6ad2337e7ccea17e498f36eefe65e12677bd70e5773f17073cfb20b6f9fa554fdcd5240a2d03ff2017247f5db4b40cacf69cb8db374f25ed2879312c6799ef779dee77deddecb0f05570a53b6fa295b89424464abf744ed0502372cf92871cf1a0eec899e7463b05cd242021cd69995382ee9337ffb4eaae1afa5234b9271d588d580bb87cfaaa89254fdf484fb73431571236e3404ee7725aee44f1c4a7626dc6f3baaa5fce8fbbe9735c0dff7fdd58109fe1edc2106fcbdf7057dfe8417262092795ed7c25df7b4eb6634e06e660577393c81bb577d411df705a92e1786ed81b7233ed8c7f40a2b05d0816b353204ae46d6c0550a0e52683002d1e40a22197d2be75d9a6fe7df2ff094420220f0bcc1073c9fa796d1444ad175c25f7b625ca5a533d2e82c314829d2428a0d4460b7d771e8a4cd7ce9ffe9913f614c5a3145112c7ffc2b79a4cc913a72677b26099309a8c149c224c618c8431a52293544592f8f17f4356a9892020a14073636d287c3f25d3bdc89a5cd2871320858fee7c8f1923929756c0f9330faf2833a9fdd540173f30bf2dea98a523afe7c2075f4081cee441b89d3af0ab930c8c8612bca2b30b5314338c5518392144b6660ea62446e6f5540df77efdae5ea67ed67bdab1924c7a974c2167f5ecc819c0837647d36499181084a0a26fc8a4e8a3929a5f4007336a507a8417476d610cfef3929a5b4e7fc0ea4f4f9a4f43a95949c757777dfb44a3d1f65fb4c77efbbfabc8e568d9b2e8ce0788a2cdc2db258da665b5cadf04afac8954fbfc42d7edf57bb764a254ebbb77cbb5a751d35c10dd6a8437cbd841127049d6bf4b8584a0c4ad6c0fed655584a8961079c034b2930b4b144b734c670cb4721a602dc2f2b604491130e35d8125582a6389060d9148794155836c5b104ffa6e1dcc274c98a28a0e0290e71ec0110e717888888f01010b356520bee7c549f3f2c5d706188c52ed4df24ce9ccf85744e4cb710678b359cedcfb5b871b6138b4e3a0f77b91c58c70a86bca6fd37b1316d5336a60d8bcd89ce26ad4b5d70ad4c354a8552976a94caa403954b40404a452fd2c72afa6ce647dc48d1119ff98c09d8a426aa412daeebc8650297514d94cb04aea319d01935a248e88c26a1463fd8238b64912c1176893db24448d81b72681e1df1c8e1318fe6d193a9b4b4e4e35c5a9a50cc275369423197e6925492f23b20b7b4da8e29293961423a51b2ad55d153d433eb31d253d473a46746839fd98fd10f929fd94f921fa39a195cef756345eaa317f12827c3a19c0c8ff228992457a607efde2963aa48cd1997fae876041da8ef63fdb6d977ef569ea554455fdbea043c714c47a5038555685c4e07dbd7ece64da3e82837ea3156abca71ef514adf7eb92bb54f3f1f34a9c7a0e0eb2b0b267c019aabfad9f76c8fe175523ff54f9411ee42cf72e9286aed10ef31fa87b355ab3d46eb481a630aa91f236c7f98b0fd49d2fdb75269bf127357edb9ef7e663f493455948a0b149eb92679dfe51f25f8c708d79f24dcfc9fd90f12a35a7f983077c6b53f460ce8923cfc49d23aea7707a9493f491afbfc49f233fb49f263e4b566c45e4ed4b48751bd7cb6bffa9ef53caaa59f0ffbde77d282af7f118233f7f737204c1f687257cc12ca5d8559276f39d2bf7aa167cdb81d100f1efd935b157e3f4719501f685a1d5c5f93a19336597584e777b1336c7b96b0c548dbc7809e23ada331eb57abbf5f43abbd676f7bcbd5209f26e6ae3d475a07f7b43bb205b9ca4885e4862a25af428267ad1ff734cc3d487a6698fb8d76f37b8a7a8c70dcf72ce12e2ce3aa7a663eaabc086f6f27cfcb7362aef673905a84b9d7eac3843264408739b1e7c8f6b3937a8eb48e7e20ef29ea39d23fb26786fd55476774d226ffcb114ed830b9a0adae148456475896649a6843570a55a8434356c55b995c6ae924c05311566435ecd090790f33e963ceef292c168ba6bd6f5ad544397dba947b31b7d7de7b0b5bd6ed39d1d484c9747871e5e79ec22d61f5053ba5987492e7d6226c71287a2187eeef0f4c7912a40ff79e63ceb3facda5b7f781a0776f9757c0aa970ae8800a61958a7bc9d9489cfa1fe0fa5225e50a585239859ec0df25951aeae4a4554e3a6b9d5aad4995cea426f8a3e1e176104b7a3f55e3ca6f15b488b013899a9c445a984ea9260a854c98908ffdc20e1257be13612087c10bf4d93da597f8cb3b3969ad9ab66dd6725c93de5a85d4759ef77d5f5077f792debabb59fdacfb051519c1dd0261c96d10cbeeaea6852dad5fa65fa667667aa6bee3daad968ccc8cf705753432343434ad18181a9a974b4343c3a2597d343434ad5abaa16b4cabe851f5a9d6ae7508fddbaadc77773767fb35fa1bf02e18888b56f448d0b27b57ac7f9a46bffa2f5c2971f3060501249cb0bdcd54f934a2ab8992473ed28e42e24c6702679f8227d30a6ef628963c0a6bdfbb56777feb4e6741b0fa5dea58fbab246e9e2d1d55d81dfdee7dd0efc421ac0aed7343b8436981266dc772465763a5a629d570a9897299a07f5a7bcd8c6ddb680d174bb3a66926681d2360da5c479aeb680ea1d9fe6931ecf3d0f0b226f55fa5125d266caf7a1fdbab44d93ab2c52afa2acb59516b1db3ffe994ee70743f436b7fd57d278232b8b576b5ab2478d5a39ed735f6669067a4ddbc6c9cc7de1eabaf955559210d2f6be26ddbf67d9fb51dd7bd8a136992d6a139614dabce24795ce3b0145fb0cca1cd6d73296b3dcff37eeec0026541471fcba752a461dcecfeb8bebfa669fddcfbe8e7ea6687301de255874ee98e86b669dd6fe10dce1bcdd9229facd534ed7df86ba2c6fdb069f5becc5fb5aefbdb691ce7cf7157e344326ea678dbb696efac7e7b6a552a158bc57a1ffe2c11ea398e7bfb792ce0fe389b43819848e4a67a95083edd0c62cac2b436a367a8b46d7585450b15a201000000006314002020140c8884229148242293a54df614800c8096407456980a644912a42888318610830c210401008c01404343430400aee422c25c1b409928e20eb26c467c0e4ca6384123f21e09cd806d82881b4866fd25a7fed23b9acb61b290098e018edfb5bb9e21cd89d7ac1df6bd3347ae61c535983411fec740e701ce8e3fb0cfa34e2b99204ac9a302c38dd8a259c5e964b56bdfb10125041e50fabeea92cb5638f112d6e3873caeaba44b0e20b41cd7ef3330bfc28c4fa9cd75cf28fc109b8af91b5cb5907c933d9978380b3b4887e7d2728d18e87772fb6530beab6a59d51a72f8d93591281cb80ce7fc0a04dacf3a727aafc3f0399edb85b204f5c549a310d11a1c9b5dd6e7c60e4d358cad0d4a5f5a3cd33fda48c25def7975aeecebaf42ab3e8d50893749ea7ffe0b6cc64e05019fadf336e93d7cbbcee33491f23c0c47ed758366db341aac0d641b4fb8ba15db828c9412bbda9a1cf476b9ce011151c04ba06f966686a4a6ebe61f2b2940bba816e0b097b35df63cd01b5643b928bf454e46a412eeb093caef3b0b66afcc3c5643cea24a06056b9fcdfa2e200206261a8c55cef1fd4a8083e73ecb08876a1b0e590d302d5a8055cca152aa29dbcea115a317475ebd858c22c0f8e0101d20063efd3b15bf4189c1d696647d9dc16b69e31ee078410370651cdfd79bd7eaba7f00e486eb46568d16c967f040c54f215c588c8b9141876e9b2161733610158167465636dffc128422d80b4d1ad0baf3e46974ab82c18954d0b278e48754ad93f5606e8c3df45fbf7e732995d52053e372620a9fb041067f5b490c2905ed1766eaccc06f07868c18663c104ef83dd33a60e59aa4673b1d18a572c508d0aa2fb983a8db685abb247cbedcac8c08d53bd2187d30fef67432bd233578fc9645ff8651428ac1ef08711adec4267c74c76b42c9a28e40bb44c4ca21145826192e130cbacd09015225b02f4dff4fa4def57f6a3ae14a1498beaf29cd5c58ba9ddda438c7e0a8b18b6e23f43bf8be5fac35a57db64802cdf2cc494353b67b446a2d2af8b9dead45b252671aa86feccff95a8d56a6fd35b1915c9163a8c9851cb712e8b01bff87e93019fe2bcbb3aa243c6195e46bbe92dc8208896d3229ef1bc1a7369c056c73b272cc95544a8d001ccc0ff817a96916e667ebb3b1f5cbdd8e06a90b81c6a022225a07e826f3425aadbd8a36436f78e96077010642e9cf226d2db07f5a48d42c895d4669c2c494603b60f6115fd290434849859b3d1056181cb7778d112c23fc04aef0e956f05ed8f565773d2294992e504c1bc53209c0d928843211838d22a03a85041b11196ed8675977bfd12d56a5e538d96882458d6a4bae466d354830b3b634e47dce4a20d15c55154b21ea646ff767a085cdff7cf92086f4c8e943fe67d4974b10ba6c28d49a3fc88d11aa48dd3ac3654ef6a51b5834629eb151865858997f3074d67b7795c2b78f7fcba31abaf0893225bad87539905d63908c9d79f3520ca655b4cd85a4715ac94542c407c3315295104458f2ba05c4f8d4d08e4429def6b97f83ef2844abf2a67d29744dbce9f04dcd950e150ebfeb325ddb6606dcc98f16203f30687c5fa05936aab142fedd9e42dffcf696505a4a8c76e24652903024fc2ce065ba9d7560f0984a920434378dd8d28e783bf809d85ddf2633d67d914eca9218ed7d2b580f3b714536074b1481e0743c42bfd2dc6741380e01d697c2b5415bf2578114c3bbe1d544b0a7d0911cad4ccf1ab60f2d3892632851816d678f036f7e57967a52b43c4934ded092c80ef12fe14513f0458894230aca858b3c194b35f23fa1ba520523f0a49d6816553c27ccd25537c2586d8cb8eaeb1cd68320f5db5528fd1b055d11e892134d331ca5c985967ad7cbc70b5b5567516d119206b66638cd70be91a4875b7af422ae1add03662c3d9d6c849ece67f94a56b8300a3d882df4f45899ea7566a67a6216a74df40ec019040830582e17cd7275a5668c2871e0936baff0d52fa4e8e69f58d9a75deea2116157237ddf1d7365d682a056db73cd62550d54290b809d1525597a9fb037fbfd4cd1b80f1956a692acd31f89d0ec09e158ca6aa665ecf4c968b47e85221a705932383c4a37869b088b4fea63ae5ad8deb1097823e019b55b9d4daa4beb1e6514c12575db7c674fb4dd2afe1a472dc3c002fa6c2540c0eb92b8d91cf00bfc5869260cadc32373791e8902814afc644cd34ed76df5f8b1b644fee5e142e4d6bfbc0fe5f265a52f3aaf0b7c5fb0dc41775bd0e958503c2f151743dc6f82c4fdc409e6ed5fe69d519c434461d0bf58010665ca1f9dd567c9819cfba2b90e40932dec918212672edbd42d1112db18c64021298cd19a7c92f55a569b3b32478087576e2b630f48311f526cb00b5a91cfa94e7546672a84806c030c3da0e07d1d82dc5c9861ea6f9b1c59caaab286728b20a831034988d6702d03c6f17c8d2870fc0ad1df150dc470232a558bdc887a744a94919be00153ef2d02f02834a7446f198e42e201e921bbb00252fedbe01347ef0b2cb68248b713642484827323a85fe07739d929ecc90094de9b45de055d651e4f97c4caa2e2468dd42da3a803a24e4ff3573aa4f050f6043f551d4265647bd0d8b1e9481375274c1464a1ea1d3fe4b13ec3a574fe9df3b53fb48980cc2ebcc06956fed453d3fb16d743fd4da5082e1afaeb3e817422912ed3bba69834bc1539217d583b874ff4c8d1eff11133568ebddbadc7ad813a9ae5978064bcdf79f4ce3a971666696d907754148d3fd07c6dad2fb831f2f8ce83ae009b00ffe8763fbf180823d755784853e96450dfaa90518b1b6fff2053c4d3e987786e25cfc962a941ecaca1e8ca51e65ee51037cf8b31e3c4514581a3f2065b3d174aa4d9952551d83aa06c220adbbca35ae8039840bfb0044ab0ba205e1f4c15b107343242f34adb20bb7662a1aef18fd68975e9e62310082c51c093c34465412a7f73ead062e09b90f3a6e08a0e8e980cea89a662ab1571400caf84b803b1028eaf2ce6eae6fcac5cfd624cec951b634f8d3d997a2eabefddcd302c7e3995f76fee067faf772534f42f199161e940aadf538cecb8eddfa562feb9d7fcc3ad3b0848943c2414bb7896d9c44d6828c1e07131f229093924dc94785a1e6a6ad4950642c23dd6510e9751ea8703dad3b5a9c9f84b7cf50093acf6cced5a7ae14ecb4d61f2df8ff48003f171d62eddbb3f8dc27de10f5a13388f23ff4880f7b55ecf0ea045b79be4c886a9e070afbc84b2bbcc63d8b821079578561ad2180ada681d20603b1caa2bfc11d4bd68e05b40b363fcb86e5ab7913fcd82d94952c7d6a6892d806ea8ad1bfa2059b55f26521635fa55eeb034a9e2e915c4e64e9f07826570d51d6aebc25f2377ea937a705042fe0565018f7e98624fa6b2c71e958cd3f587a2b74b64056288f8492a2426cd04e093ca272cb7743b7760b71cc17ecb1b7092bdb604278725e47cf74776b05928854b1615cd5586c668acc1aa4bc4b50e3608c6e73768f81f7d9571a9135c18646c2ffc514cc139bbb90f72d73aeae6ef34c252bcca1b1cff21ac1866e7daf216636f489eb34150c73579b6270a8dfdbf5abba30dd237a85bd71aa448d7a0acf0e7d7d398d14d5314f169c6e5062ceb6987180f30883590d8c9741ec84eea12fa4ff6640d791d999a948d6ef5beec0a82415d8689c55e0933f5004c327ab367527dda88912b607c5a15eff1a7bd4b854ecce72f51db5452de780e4b978344dc2b381c44ff774a80454710d161431e74c3d6d7702e850e167c0debb2e45bf9f7fb7d163fbd895dc86771af436641f81b981bfabf82c5d960736d798b9c7983f6e8d910d86ded5d11aa409f503313cb0db36ef6f32925aa9171c5740b9804b53d9eff0ce06571de0c3f4b5b8fdc8c88688daf418731bbf6335183e399d655f4217c994669ad17e52a76f2c586492c12e51baa4b3b3fe6bc4e90963305e3c9a989db7762d0fc0fa47f51e85ee0f752b1e2cc3970b5477aea6e236661567a1dd698c456b4bd78cac06f6fe2b6f32cf2eb1ffa02f420094950fabbc3b4a69383f49fe2172d5287d4031f99a9e38c805c40ee340ae710be2a85634dd7683dbe9c15d82204e46ecf5d9d490c6d1e182ca6377ed318b693798ac8d81d7a1d3bb8a83980e658f059776dc90aee5b725cc80668fda78c249db8a8c0841b3bf12005f9dfa3598bd9dc81ce940459e25187078bdf572154986990022df610ef65daa4c63b967c0f43e0ceaf00d2df3631215830e39a020cea26936834524a697d39a942d8948fd8940cd9b4403d6d7e7c736dd50e4ea9bf357d2e849cfbb77ed13c956aed8ba06a4d32e8ce4e03a14443d0010cf8fb1ed113b29da6bd1f6b5e533692db9d789085ed0f148305232a9831d89899b16fa2af2046f8b03ca4547aff8ebbd528083941383c979986cbadae1776afcf08a15ac6042845f5606dbbb695dbfca71ab2707c0ed69372c87cb3e41a94a1c90dfc8675bbc544c4df9ff119a6499d0b9904f4f42fa8ab957b855d4594cd4e5d0a6ad61bcae75da6926238e1b8ec604b7a7cd2d180830bd0cb19ad4b1512cecb9aad4c572f1353b22cbdd14947be4a5c33a0a8ca9858eab510520fc0dc34d12438bc542bf1acacd5ea413832a1940d3a03a8e6bfecec3c509d5d99caab6f51b4ae2d274bc1371ac6de195dfb49c82a44088f01ef443c060b270f5090c59b1f4010c7c002b89b10818b1a06a6842824797aa02db251def55a77b253fb3e4726d80726ed7f7c731dfd28de177b51a2da2ad053c6bac834b5a0d0a77faf3ace420908064b81473e4dcb245d9ce5cdff85528101d5507c00634b9e16c9bc75378c34e87e4adf8645d93f469a6a23894c6d733b4217db0e9df422e12275acf9ee458f468244af767a94eafad59aba631e4cac2b075c7571ed58d456c4489ec37a9890ae283eb948e1a3b89d5862be3f4e8c862aa99cddef698b82c33c15417ae0a255a1ceb96330b392799802d8a46e7c8b261ee042e3ad724e164788d76040acd0603da03294e2508071c3e530fcb8b58da6753788aec434c12d3419ad3ff8f8c0e170968b1ba7138b5cc1545845839b332e50871575ce10bf160e0f41fdbbc0384eb43928e557d38707c0c13d6b7a6c099905a8acfc2b0e89b642e805554a922460cfba5f068ca9e023d75fd5a85c3388ae01c747417386102a2e7af995c6f57076f9a5f9bb44b4c6cb3e151bd707c867ad32a9fa8402496625b0ed9228d4bd25c12cd1b7b1791139b069858b4af5d9cdd123f08f104372830946c62d6c5a005e66a71c8ca03f4eec93b5490d9a4a1c182a4216024b3b6c727e3ed8dc95811074b93ecfd9b974ccdcf468057b21fd6408aeaba20377614c9b51db9e9f8cc89e9d0f436b332ae5f26db18d9cf42f5159ff5945416a5e2417958d6163b5271a96f80ef40236be2ab7db8e437a2d2ac96ab5ac70bf393edc568d822b927b42486289edc42d159d5fca889949060c3d7efa6e0c400dad4466a2741bd18d90ad59a96f062dc3e79c0a39dfe53ad5d984bb41aabba11bac60942c21f34519942f3398ce1e7aa20283ac9858c0521b0fd663d13819fa3375f57187899b0167b0689ffe8a5c361a55344e0f2e1bc05c3bb22d6af9b8eba2981502fe6699debb8da6cccc85e825ec7402ecd86df099debaaff7fa142046869cf2d1152dd1efdac35e1b001a0518bb88567e1ca99d428e288a57e0b5a6b841fafff2ad2c108fa2fc2523dd871aa26c94c98e16524120fca53badf3e8b00e968a4cb587200bf61283ffadcfa5ff56ee806088458029716b83942e042aad8227ddd662b456cb15b00cf1cbda8ef12a5eb17cc7fa6f9246c4ba2a04bf2fc249c179b025898d31b98011443ecaa253e1cf1a7d0e0d55ff67e3d1ae2227235c541fdc5fb31a46df1b8c46b521cbb95f6f5d0ba830a81b18ab2610a8ee82499512540f17a40b22386f581cbe0bf23e611c72c78aad9f3abf7d85c019d4bb62c868bf2806a99ba86ea292ecfd3c6cfde936a26f9fb950f90f5288764957696109423796ce9963d9ab4e19802bb65d48cdd56152e5f643f380c4894aff50895998446461dd5301e1d7f5e6f58bb334401878284220a76f03daa3171ca1ddf8db8290cbf05ba75b3b3041283382c86471e6c5182c0dc7b9465cce2e561e91999a7c51b72c5304ed27f8a1640d0d5c8d9d9ed983bd7790559c1e42db2b2619e78b9d76a3de1e13296d5de8519f53518902b672424412815e61fd93b6ca60bd698c20016c22df33fdf9c31c3c52e5a662206e13056b9e3a4183fd5d4976946aa3a3cb6657ab094217ea73550b60d192d47ed7cd074fc21b6bd422e3abcfc3962dcc5d3d646dada5dd159813f73574754881af605dbe640ae465338528e8666020eddd7bf68ff618ae46df250c4f3e95614a7b031b61ce2a08821c461a786cdceb411bbc8d04a8f07ec238175fbac1eaa1afd6fabb9a3f1002f44aaf1b124da9732abc350a639f4b99388f98f44e5a2696c7040cf5b7d506c19016c77c52c97c7a3c20fbc95b37f7336ceeb3674255157c051b3b2d8914ec9f6d149f2f6fe733b2b3eff5bbb7ae9d546f4719689d2f878a812a465c02f0141735506285c2157f1be28365e64e16bb71548a903e6da6529df38d3ad94ef406a251b8493df64327cd325aa5726ea516347ec64fb68f216393c283f37c87150fb657197202e92137395a4b09e8cbda36b43bcc692b979879d2e3b8e42c96844299792da3ab1fcfc37bde9c39f6dc171f4a33e65a1983f428c670535d15f77ac26f7fbfe829330826ed5bbcda628a4c19dd179d128e144e91e1bf86748723666f33d06a59ed409f2440f29ed62394d3bd0826cf724f3f411a8e0843387904aac233643eb07e2fcbc5374f7fa3f242a69d1b861e4c4eeef8d3bc11ceb00d62eceb32a20aae06662fc05a56d85926e842b2b0e289b03661725bf5325679685df8e452780458fa1939b48ab338a43fed970976b0366ecdd566c6b7dff6ebbc0209b8e6a8026ade51a46604a35556b0242887b5adec84049ff69675593c3b7a9f9ea57f4543bc50dce5f8eecdc7f8ca263b4f513193111cb95d4eda3e43e63c63a63e018d9dde38d1e0b839aec759e98b6fd0aa665ca5b4e9b31314f3a86f5a4939d6bd237f7c71fc4df9187e7ea9136f81d6349f7e8811ecf9364b1cc32d6d1dce58d580dcffed40912f6e77f6d38edf1966062515fdbc90e90e0d589cae75202c7f71df37eda04a1ebdfa75db33b06730d5f2d15ac19082d50745f0af0e379fad9f45e50de691fe3c97ddf2921897fcecdafdafe0f28376e8e7ac0898abb3b4025896b504a87e758fbba6e94e088e825aeb08569cc191b3c76ff25168f9ce5064c4c7d4b4262a2c25a6dc483a910316781e43d102a9b46c89c3e45570f11fe32cb44bfdccee25e729092819a5db246a6983e2693391236edc243fa36c41f09ac49f17e54779e5e6c59fba3ca25fbaf76deef123278e164c2a2e512181de16ec1e13df15cad237c8050bb325080019f6bf9503fef2c349447b0a219740b9dd0dfd59ec9cc703ebe1766c30e7c5b9c5f698684202a4f810c175c8a82a8315e4b943032488f1c271d4e38b991b26593e4213819ba9b6a8a94fd910191dadbc9909dd208840a8f86748dbc38525a045b34feb36119da90c53867c842a125a75315f7f72cf03caef6a8403a3ac80f7b13435028280989b1b27bcad96a69fc0ac1ad7144e6c933636ee03cd3c2406e18084ba14f35100b8b93f764ced4421dd39b19e8537adb5b92b4bcdc12ec2510a0175414b949dd184ecf8f5a51bea43e01ad83642eca4450700fa2ae5439389dd2087a879e6437e211429cb8d793ba0c7a8343f66271b962ddc50df45a5f4abafb0a4e422bcf343dab330db7cc8956b3339c573108a3dc22084931bd78f30c499bfb4cb83a08b634831b82bf1c289f0a6353516839e5699a11785dcd86432ad2eb5583b1844c1394ae606f037f63962b6fa4fc111bfc2fcc1a4addf1b160143758a482826b368f0a170676b5d6af0e99e9abdee8127156fc8ae5127d4635ce9aad329a073ad3415dd3ad5cfbe3f78ba0fc466a8e65e1e0ced4191f5efe946bdd44690803352a126fe0517bf702fc8fb27be6929ba301b743df3a248dce1ba2a7ecb0e3f28dac4790a9930a856b5088117658161be4be3faf0c3717e5364ab5e985c65360c50b3e0e5faea08977cb9e0ef5edaa9e0e6a66395fed0aa99c1c1282ec66695e26edc6b1ba3e5541c3fe8be6564bd99a2194d8294b9e47c1c8de121e466b93eb01f7e95bed99b92ed747ffb574914d383ac2dd9fdb35baa30c80dfcb109b841855a592e904926d42505f2b32d0bcb2b197ef12be832202f3a252e4ba7a00062c876b0e8a04d248d392c7519cab561646b742a2b4d82a441c59471facef7b7c9646baef74c462645f3f3b9a2a75c0f4c337205baaa817411190715325bc2d487c70721d1cca2ae134521bd37aa4d798bba709594a653b0e520907838ce9b1e92dcf5f46a965fc34d14816fc2b030f2107c41014928710974e5626d9f6750a1e3ca7e187c99018424f2085f012bcf7cc8407146af5b71c924709513a1a39f5db4c52d034386f5b88ebeec20660f507275003791a873f0bc1930c9969a71fec72c5126d315220e185cb8c0a98d4f122f3098b863b3dea7c210735e182ca33c3b904320a831521f490bd039520ba8af33cd7723b1fc87eac7f388f9db5765d446d479611e9ca6fb8071215708a1045cd8da5aa543084f2d151b0fa174aa9227005f32028306a813fce3642c56a29c53cd81a14acd56bfb72a744e471784c7cf6feb345f98c4d7d4c328ddab567f041d92a739be86a59a10c308777d229b4761224579f0f9f07fd64ec6cdef699e7454adcf10c6c75e2073b49404ba2b599b40f45460adc241144876d5009a7a49617acd5e7537852622ce2d245bdfa6a4243f4a69722852c764ea56204b2484c0c0b74dc2eaeac48c848b2271d90ddacbfb335379fbd9cbebe8cde3ecc51f46249a1b4a8f28bb73535d9aed296a4d3f7a56d712f9566d8eef059b3116e2f9a7ff71c81890a776f38769b5241103a93f1738d0b036516bd2d8a9c23b702e4c8765400a516ee70b01b1db4c04eba50ab336d5abef645a6e1a6fb1c402ef812358c3b2ab86c4981b140046337f47b12c51438da2292b7e8e80a22db7528eb425191c9e3f47c1b245d51334962d66a7c1a3d49c9afa955b2f983f00c3f8abb975d8981b85473c7b70ea2cc9bf639176d5a8faa700226f5039a806ba157a71c6a21cd1af0d2fd40c4f03c3a3404f98b1d66b1f7f68dcedae8912ef4961e13a0a596484fc30331e2b48c77d22c5fe401f30c4316d412f6dfed24d31ab1210c6bf62ddbfdafa516c17b51cc8fa9f6949fc53f7a87ada6432210334038243b8a43d5128ef6cf12c84fcf483cd2497ccd6da4551eff76c3e3a5b2980286cf94523d43cc294adce323eaac5b73819125449fda5a315c002b0f528a4f714f0daa2d217d6024654ebde0c37bbeee862e24220cd43e3040fe850614c216a43db89a13daa22bc2daea7e4abfd96568dafdf958568e2bb636ab03157debb5a2ba74820a8ead9736c2b2edcda111922103505063e746963aff20235dc77d513b4422ad97bb8a373cb93dc3b8ad720fb70897bff6a518cc3a05bedbcedd82db38f7fb61e7636f6aa549f4ec7bea03a6ff8e42c862af9cdd34246a9e46bc2ae4cb75f1c6845c4b014358927bafe774add24f5e307b85dc649ddb78d37804abd3f39463bd6b66717e44050fa24cb7d2794deeef228ada03cf70d3c6bfc0d2175550ee119c021fc1d70c79a5fcd675cc19d1a2a9e509809c884099c780a0c354c13b581816727c9f45f2e9f4613f33c62f2e1dd3971f7e30e7cec9a730afed221dfbf73d4b6b02bf6bf40150cb5730ed31541bba4a8bc782c3f567ce0d094882eb2d6b1f7cc62bc71e47b70751e25c01dcb8ab49a0616967bc702b18e31c3bdfea34a9d3a3085b8dfd7bff0f141d7f1bf0160fd6248d94168c7aa45faab5d9108af951b764daab5cfed09719b05e8559dc2b0bd2f915c94fd8de1f9be9daffebd1df301dbb1c67601ed83e2df9b15d33549dd4907d7c86187735b3d20823e787558e14e66f5fd4da8c327155bc181c57227c6a60b3d2169994ce20925e003ee08e2afcdf41285ea8c75a12973093f65d4a9cc62027917bde4b4deb5bcb1363fe016251a4730039ee42302a5416bf3e532d3ac3e3d39bea68a513feabe57f3d61741a45ae02437941b33331ff400646acdf7cc1584fe709a3eaec3761af5d8b9772384f7a5b4f1b24f25b5f60d8a7677f0650a28aaf15ab90387f12e1e12e5c7b44fa5c97bab3224a5320e2c9f2f57f45b3b5527c9710f742e2eb62abc9beac2623227052ee8d459adfd83a6dd2d7c19405359ad6aef4be51335229d7c49b1ad27b5ae751a105451ed0d06f0e74ffe6459907bd29df06a433b86d2f235d4b36c1dbc2ae3f8b8adc1b91e4dba5038106397575f086093f8a06d50ab3b17c563f791e9d8ca79bb3415b5a9ec4cd082ef87735dc5a9681ac20055bb03e6347a1e33ff0116872a83da120114ce9851eff87b038ef558e1bc35cede5c7ae5c48d00bf5a66dece425a0c8229d3296dc57b7adccdcf8672b936a02c07a8e5fdc7ba1e864bb9aebf215cf825a1b5864c8688f0461eb4b412a192c475209ef984f2a9112db1457501d6d78739db2d59464eed9d1c1752963d7d46da2047d243bd7da79906a1d7c9178e6320eecfb4909940ad4f25c54d398b69f004e018dfb95a8a57d34245d9312990da20ba377e4631840280de6e8514c23f5b12d2e0b721a7e6750cd11da8f4a4a1654aa27f7ad5538fdc4d2198d63a8552cd7355e4ba8076fbf4e70d0b865ef3bf86f3c598fa2544dd51a2e390b676dee7eb106cde76634c3e6429411c60ae414c8df480fad4d951808e6a8415119187f4d551a9230c9ef9bf8be08199c6c8d143e0bdeebfe81199966607e7ea44e15632b06857188dfce1b5faa4abaac8962d54db08bca769d49b0b016a9036595ea2127dcfb24abf8b5a2dcdfbd42780a9aed3b8b24dc850427079d493aa4a18a21a7b177c58b41e1592dea920c1f7d94ef5e596ad5229f9f8ef63baae55b8b309d58d00eebc9e33819b990d9cc66a7a05cbb93df6b584952db14489b28300ee6306c633b78313ba23feb4d5efff64f61090ffbea52c957d132bc21b35d0c06b290c7478b3359f5eb30687d2b9f4942bc4c029876ee70e418b5ee639bc2aa1439b28adcc0429b794e851c62a7d7a89deb2dec1d18b07b245544c6f4ef7da660a880120b71c2efcdddf48381b793b2a4cfd757efb0d2505de7812420fed223180aac2eb3a11dbb8b77329f392a78aefa4e462b4207ab417d76d19fa52b8969a2641105139371cc99cbb095776237fae3b5a5bd45ff4e8733dbb350a5ce12d09cce8ce5866e7021e40a1f19ac2c62a18265ab52a4018ad825f0850aa5b419ce3048b1c017fe22b0409557c2908692b49819a56ed92947f0c714a000ed6ce05ed055a54170649f4e89cb8db4f7d40a8be6c9805bc5bc43c0c53462ad3d16ecbba7f8b71334e667eb37b5fc3e425ef157e80d0bffe5adcd0f9a40304e703a1c5322d1b26f78a6c973322d93fdd9f15f4569680ebe64b350ef44065ebf5a5bee72e695f4d666c9409a9f76653fada14c18213b94b43d5126b47d8597b3071f1fb81cadad7339f50556fab0e5e96043417adea35e2c36df8ded1ccde8596ef0c3f2841aa0eee481da7e4f506bd1338790b8bb6b7c8cb63c461804ad72ceea2e753670e6172e96990c8def287183e7ede12f904133ce74389e9cceb8032b31add1c0b1b0c81523d3a4103ba9c551f67877597ea9c72680383a158fe3f46dfbf53c468f1d2ab480e74b685d1a75f725a01c71bdb7b85d5e0935979e5f0aaf37d46aed0d6c60ca92275c7588f2e5f5d85b5c44e291417945fce417d641ab04adb30afb3186d3e39372e56caf2dac77443ec2eee7854ee226ade8c564c9f38b5371d035f4772ed7b6483adabb008afa78cb7b14a27857e2fb2f7deba0c45d36f9063c2ccc83eeb7eb2d3fd9ea678993142b1bae166b457179d99f9526744cd663746aa949975200ff8550c825b3be630c91dcc7aba7b7bc23ddedbe6ba2d8ced831e2f697377e315bd7a1cb20d484a33ae78016196570f51c728e73e5b958d76b2ce32bb1bc6a42c406f71f777ecb03212de2c6fe107f5ab56ec65e1c067331292f29a6bd37013ab47b9c1e08a68bdca526a2f6aa91a88ab4bbed003675564ceb2645bf7122885006760a60ad29efae8b15df6afaff56cc289996b2bcb8916c4874594215b9ff6363332ce1aa7a41dbb08403893d472644d095a0b8c07042b1a985b265a6709727432c9aee8646052d896119356666ae01de1a3fdbfb56dd31bb761b3a496503313fa5349ef7690feb4706a374a706a200aab6aa9b3250b482799f4f61cb30b7a93f969c5581ede95a75fb7c03bdea398e8a1d3d7f158d46fa82a6261188c5ef45ffc86c9aa92699423d72f037168632f21984cd2cabd2cc3b7d73513653e672ec6bfa756a4369db82ae083a1cb0be5338f0d77ef1f9a2fba5b6c5d2daf2c70dd686ab97bb9692c22071944ef011a9c1809869dc625d463d3afcce057a9d81ac53904549a9a0f81e2083b59c79767ec759aa1806729cab141e0f956c90aa31af875e608502ac8d30e1f0a3a2ff5c1ee736e9016557fa52b2de80774c41a6806c33ed42e2206712fc1ab5c5cfc1ec15ece64796cdec08d0a4930ba79f3884b195588a3f6fe5fe9f3832a1b7af239389136f9a4f13b7e4a39ae151e806ecb88d0789a56087b1b57918673c0042867d8e165c14e771525022744272dabbb0b690a54cf75a5866b1b99aff5b9171cee724000267e8fd5641baca9b165be0e0ec89be773148de447e396c457926fecc0d268097017c6309d21fb2d9ba4c51a223871e051d67b5027efbfc1b6072cc49b2aff51bf45ee43790c13d4b3200e4b4c63e567ab068a97f8c2e104e60aad32cc26765e6736c1bcc5dbfa4c7b7d06dd3df1f0b2273a17d1c2ed4efe319af4c1c75b3e9db9fa091f16916adee9dc904b7d098442f04f6903be6f57c0ff02b64f2dc64fde3847867f67b926a49e216b0b8a7f95dd06889afeceafb764ec59893afafebfd29a729bb316342132edda6b82acc900931afd7ca5961a71d8f257fd2146cd008be2cbe058f0eb8c0ed7412d5717129d5ab894f36ce8d88f5ad98d88f38801776ece2f5409b6e6a60080714d758246adac7616fa07442e474759af259b90e6130c8d74173f51b38b7acf4d7304dd4a73b5ceb962ba1c0eeefafd8004d16944b764ebed35a661736bfcf126391696ded0ddc1cbaceee7341b3ac93a92ca0e0389a9133383eba74b48ff92f661efa6009e1ad7f577d85a364ebe7dafb4ace97eb81f40a0b550fae8e7d8bf2f82db0f5718ecaf267d2fdfae7bff409de286136e5984b6ed9bddf1dd90c82bc51b60fc677c4452406cd17c22136c6bbfb988b124f59a8ed28b2afea11fb1019d989a803ba6933ae28b46291e31ed4497c26e75446c536ad57e8010b931056c3db399fe1629bfa70ef5ce9798e41a096dd92266bc322c03024a8e7fe08730ea24731447a8bd6fdaba5860534e1a5a653db0fb267cf727ec22727489c6f0f928cbc293d9eba86f9494a0e75c3513fa3417a2b1e73cc517b4c8795660b849d2affe8c5dd6643bee971f460e06597392ee3d7a3f55cfc0f0bb47549026ff7e7d2d71277f1c37febcc8a970f6bf97e575c59187fa440131fa061922660248c870adfdb904cac8087fc31555c23e0e2b28cb5dda57f664d9bcee46ae9cdbaf4f6720dd332a973e3dc4b4bc24ec00a2dd2a104112f8cdab0c4751bf6db2d04074f3bc172a45bc672769d6734814beb915069308133d3d54e197c0c3beb90d63eecd7f07de539d63c038a12c2fda6d190fe1b366b35c755584ceb151943debdacad43cfb8b7aede5fbd6df0944cc3de024459dc12ab7d8f725d9652d64155ea037b32c516a1150a92ba052c780cae29d00b38a3f14ca4a9d5fe5dc13c8310b7ac7b5d43d6e5922eae8545e663157aba0a7a3967965c4620207d9ec45ec5866bf85c4d5b327692435dd744519b1249d3e6cf478705f009edd59b0725110ff521c35c0a274059e64b3183fe2dbf596a9e08c92404852448920e351a0772a0f9d6ba74d9cf80dd0b3042f2bdb267463afb99b28e48695ef3f6519d63559950b9784cd299c671252ab59af537158baff82d7bd37498d82818d71e20d95e851dc4f639460c85160ac8d2adae230f4dccc3d1ee79e197d0a56cd2216d1b7bb8f0869e02bd2ee6770ef5d4653227795f6291421174e83ee423635ba6f80f4da4cd8f940580688807cfc7c08199ec62af11d52e0743b2bb07aafa493b36c7ce06efc63812abf34ceb58cca7a356fd977895a3701ac29e3456a970b47c133f147d3d24cfbf44082563aa93bb200d61e1d64baa996a5d44f0699a4771962028e1f48ac572ceb8728184eb501e26295c1602e05509b28583913a8595361a165f83d6c30e3f24ea5bd533ac28b9aeeb49443291409b772dfdc9489ae4ebb91be91d7775c2531eda23dd1a2b16c0a3768f692ea8ce0eeca52381266fb0611124e5f995cc1cdd3f6d28c627d4db13e7d4dafdb8cae1c72c18427e317e17fe5f9cc82f8cd2c7639c288344d8cddfd44e5558636f806edbf028b0adef454ce98cad30c6137af05be0b26eea1984ee84547aca7cc72ef5ee810d90ed4fb7f20e5fe439f96b4643d2ddd22f4dc2315e2bbeca7c45273f0b2b88977d8f521814b6af96199f1be19d6f24c55730953202de688361c21a1be0281e358fcc696bda63d5bac35404fac77acfb5ac9caf2a5d4dfd8e17ed5649243177792fdb129061c9bc0bb9ffd63f8cdf76d007f482cefa996b42dcfab15ad84d2fe4ab3048a044948eaaa3c23769982df4596016a9414a30379b3a4721a6963167184573d1c63a629137ed4137d81cfe34666f6e8a0430ce1401e5481a5b1c135ef99dd37a739196c45fae34ac4d52b8065a9d2206543db42ddeaec865650bc8706b1eba88685209b8177241691c9861d87d5fd98fe4222a9212379d247bd6963779b0d76fa983a5cdd26a077fd60ac2e930b8a6b651cd7028fa5e543cece6b7673fc2d26b2bab24381489522f9a5d0871b8226c91a6ea944ea13992e41b1ce7194fcd41b60ed84cc73f0b1028c9ccd41cf7a6198a8eda1a8932b6f86436fee8a1b3302cb29625f1d4733ad61b47422f2110e56ba29396309b73f8b8b57303cd740dbe149178ae6fc773d355de3c96f594f027f93608f751b2e6b9d0b9b4926738b93dbfd9ade89bc4752c02227939a8ed400f8d6a5547dc2adeedc65638689da9ec4c7d474237da31da7f4d3d5215af72e68bd44437a96aa3dca961004bc3c5aa73c6b37cea15f9878e4294442db40a33315cae36aabe4033672fe140dc5606212e01830c69f5f9420c7ce2695673e362fa6d0dfff07082bb13c660f8c89b90f9ff5866ca1cac1e05ddbefd3cdb9a45d24660949156a8ccc11296981325f33081e9dc904b891f9615542430b1d4a8ed5c48c8ace2ecb400f7778d3201093fbdf95c4a0b69e68b5355632c599d14c38def030e9da40e300859f391a2b243a6decff44b7d4f4c5f919d539d9aefb8d99e546e5b5de2f8a3890f36574d8370977a7068bd05559001ec588d2454d9e5ae3313813db28ce4dd862e61d48f6c22592b460111b9dc22d1b2065894e216d2b1a4ad7f9b0218dbefd9e92dc1da75644e2f371822c4366604ad21dbde36d00273c6e822667d3718489974a4b612f731fa42d1b65955e936bb709bb518250ce3bc9e1904c3ff28fbe4ec73c6388645c3ccc9021bbc7625356033a63305d99ff977ecaefef92c7fbc3f8ddf9ce41c79aba760c8ac6c80768705730024491c455de47537910ef656a4f42ee0948424b4d4b85777a46beb431bfb50b884e81743fcda2020d5cec1d8386718eaf2fc6e13bf07b3604d8920250e8f007bf5c0d5cbdd60e37647d110747578bd82ea60debf69acc45e19482d1fc3554d4b28b9d038d49ba255f2adb8311f0960d2afda5a51644442b4e40aa1e41b69e6c7dcc5179b0f95826153a6ca9486bd128aad58b0a336568773eaeb86a2bd692ca20e62cd5e038c39f3c94a3c9801288a1a88dd18834250f6d15c9435c1c79e84edffe718de1f35667d6f2a3ae7f8a4b92d8ea5bd6ab04b8050c9f96beec53e651b8a7b93c6488b9cf54a042da39288c16cd509b0a432ea019b5e86f000f254526f8b0b5cfd81baab0557f1d3e9cd23b66a632f6d7469a468b7b706d54e07b6de02dc7ee18e8bd010581db5fe1f704ef8f096e472ad6eb6ded8ca5cfec652469d5b3ceb6a0cb082f8047fe02c4f07130be996a5ae60ff6c26907e953133483d3add1ff4b225db144c1399a04f92c3f6a898e7c7419d635a49b9ed30360d9e28331780c7bce7d4e144c5514cb0c3d585388c49bab4dd60c004e6c356d189f7e4c050128bc1f68ba4dc7c38cdc448fff26dd1a5fde07a2e944895c691d93ad751cb3791ea7f2a765ed4aa0a80a86cc0ad60ac8f991206527ed17744d3455179be059593a08763bc60d897d52601e8749648c5ccf154c9ce391fd0d471d14dada550208a7a13c7b494c1be566e9ecd80e2712b299b8ec4fbf8f3d9051266fed96ce7daa366b8018ed4a4ba912be0a4a836e97c5331eb903875a6c0769430ee39a64e41f86978df19fd6db13d5d2a4b2315c2760daa13af07352597978e644984326de9a1c9cea04b1ee64723de5f04cc04bc64f9e9c8f68ca2cc0ed0f9fb183bb24f3a52bf287b9fd15abce51e10b41a63044a7a96957b5233689fcf7fd81d134f799272b7721acfa8ce57b4124c2ba32fb6fac6b4ed6e8640cb28c7cb983cb0cf914c6439decdd0089e3f2ac97cf3d8b3031cec86ab8fd2ccf2d88a7cee8c0e4439ff04c46784be4150842405f53208cd8566db055e3414c39707ae11d11eaf7937aa40835bc5440d71826f6d6a8901e122b307452c94525d009aa8e34a5a2d6726b39f1383970d20545b3959638a33cd9898677cc55f51e90ab63da394f67420942aac0c90309e28870d286770927707582295f4328a24ebed40758d469cbf79449524862cd6e882ad193330e91f1fc4d3b55893a67deb7038d2617b389d5d01178946ccc02d0303c2428028150837a573ea31bae26d1b4ccc0f493d427f819ee9a27914fc2af7e1327d90bf8f55fb62784123778c7e217abeb49b5d7c9855013476c801277f1b940192910d03acde165dde32d5566d05d23a27c29bc470cacf6a624a3b053d1376541630ca3d26eb83d69e586e52f1c36e3c77288d503ceed7683d3c03426574e7d6fa6ab93176cb4583ef3fb7ee8b78d2ff003dfe8657e66cca04dd07c47732727c2a8d9e86a0e97d17d96b1d500631462391992257f5a338231d8b53d2cb8b60ac28eec36e09e4d118431d6560d4ff682878cbce4136304b90389c70732078f16ea0f2fd0a5b95f565d6316834f5a804a846233f4e050ca770cfb73c7e2804ad15c882440dca6726d567b0560111d47b16e9a55e56274d0d3d83150ca198263c5eec61b6b0b74632f6594faa551ea6da3d4eb11a88d03289dec191b23a24693e8dc5e001813a1fd839eaa00dbad5f63f6da85c911606eed051a21b09c1f5aa01ca12e3498cc9276842a090e1dbc3658be82093d029cf22849edb709734d7db1c3a335d9d31012b732644a4c9e8be9cc761865f870e2c783b0ce64d81f967b5c81aa742f75cefd9aa1d4f49eec1725f31227178d28d7185ff74c7c68d125d908b50844d1f661bd09f01339c01f6c7c4b7b6777cc4b34e0f3c0c131fb1ba7185807aafbef88e5ca30065b937ff51a12cd70d840401cd6f8cab4b4da2894e2f3c565d83b969a7978fe1ffc340774eff05c8234da9fbaa15d74840f0c5b186d6dafca047f579b72c86541a1e5ea8addbfc87270df54c0f846ae655d1f3374a75f03e32d60390bd61b4b5db276f31ce9cfcdffb989943f9e2c50d896ad37e8e65b47d5cd2c1fa2b8ea33a0e53223f97b93ed240601f243b18245ca9a612ed240e778fd746b1bd5f27122954c880106c68501289f13412c21fbdcaec8b67d46be201949d9e7d5ee716d1fc54e63dc32c40e2f980202ba52c458a0658b8a79244ed32d88738bd652e588b88b71b2189481e45f1bd89b0160872706092373208ecd8dbda5863d6dfbcd8a779c592d94618d6d19b6059d0257c6156301a17b658e1db3f9ec11a7b436d4059e1e7bf6ffa0c4edc58fdaab92da6d1ab2534edad60459f8abe3fb40866c327109cd30ed0c4d96c2e4b89a91cff62a1e6d9d7d95d0b41b205c02552a166d90d5a5f398818388fe0d19f0b49f19c5f1080fb22020de7236d1a7175e7f498aab30bd917af5b797f4c3952fe777153c6eccf15bfea8bb3e61956b18d2c8afd529071aa5948322845506dfd53553c8d8919950bdd8eac5a7c3a6bb82404566825b031d78441980c0eef0456c5d3f94a3876bcbc9b3083c7f4f510fbd9cbc1429ae5e8090b24fc688e022c42630873b17c3a05028c6e651bef0250676619d0f4f215e9aa28171a194e41729de1d980b9c5ba441f6828615728955f1a25b5f68a1f835dd58e65a8c7427aa85361b96b39d9e29d1f2f27fe30a820e59f90ab5827215dc4eb43a3f9686ec064cb73917a807bf656bada45812abb657a124a3f2747305a03ea86ef6fea4878885557de88a12139ad50cac4c021953aa55bc2514b000735dcb1745162a8fa94b4c849ba76728b34ce6a2aa72d5fd5195fa2e62613f03df02d2356068751636617dd0fe2118e32052a6313e821d36b79c0b0dc33bd5048a27a1645e6530f6dfe1c8fb74fa4ed2e8288cd50b02aa518b1895c4be43c415d8e226ebb0d3bbd21614d74df1891cd0c803e3c98330fe3f630202081e58279f139fd9c24bde714f84a7804ce3433894eaa3ca9064aa876f853025672c5836a82756556e143dd921508bd012efaf2c2f7d80d5505e830dd535d8eae2f6314fc961d294395035b9e8c07e095d7a208437a53d919079607900f1471be98a0109a4b4299267ba204de47f1aaa9729dd0b59fa1c28118c7c1d73b6ce368624df781d44435eb681e673690a8c0ec88745403e768c801aeb55a2b5f36790ce318548afc4131c03c8aa78d027060018e3fa7e0857db8342ffd1fe4ce84d01a46923d845dec3888cc1e1f1fa0f41548b637ac6575ae2201d2329baa1ea6a12874116a7f3789b91a5d9fbb33e15ad7e8cc38904ffb936442a4dbc4a787202b1fb2a6e1b5dbaafdc8837687f839089c4a00e1c86b97a3f1efa4c84deed87be85473da9e2b6922f1cdca59a6905088eb492aee2b5246fabe8df73078138640e3433b07bed3ed6fefb616a45355009df14d561dcf25c7797e6dd5a214722523428a54cc0924c766458b4f10b2fe9704d1d01ad4892162d4b190edcce66125e964b062306a451fee02dea0b0b3c84a0dd6a96f632bc7c84482cbc3cef598c62bcc0fbe0a497e5344a45627f177ef6e03f74539d8abd2dde11be08296b5ac9217040b20dc2b5c747b789353b695c5feebc25b351e4c7738cca4612bbfa9b94e8c4839d5d445c6cb210e46f7d447e13335667812add207737e42a93d729f0607884910279696f4e0c1a3e8e72943c1a0a62e8239543a9710892d1b6debad168a91406479bd84613ba414a73f43cb8be1c7b381e75f67404ee2a29eecadd95e8bd1373e8c5ec037f74e413ea16afaa197daca028aa2190f959543091cd346dab85aba379a58c7461aa9926fa2ce062909d48ab1185a5fac3e850811acb981cf6902e278ecb0568a8771a7725658a19bf5185adb46ff2c4941e1397c65ea126502ec45e59449e526eca96586f9dbc5c2f998a40e54cda1584d9f9a47c6d3b023a8adb019ee77298df9e86e8d1f8e19b69e5f4cfd0d662deb057662275fdf147b57d7d66658d2fd2102e3eaf3106ecae7c4acaa93f2a09bd6054e7a42c03f95b37d48be90e571f383553125e4c00525dfc130795d02b1a640e02eae025ed952e3a39883f3f3507499856c13e45c5d73d1a4d7390d7b8ae1ee1b82aecafe446f0a71abddca9f188cad6ca24bf1f6c598a38185f21e63e632a11ea2dd5181c76246d75c68788748f2848115d9220452cdf5b78fa873960586d32b1dbd380b89c0a2361dbac06b46dbf8350f19958dad72db492a0157453c2700a34ba5f71359e880ee34a347c2d3919f7802fde0331850fc87a7c40d7970fb013bf931b788531334d5921cd15dc6a15364da84684dcebbf5f77d3b30aaf460a737aaea3c6a03cfc96c23be01105abea4d8b195a00ca5957e93de26d65006bed80071646dc92399c45f107a701cdd63be1b791420054f18ae27079eab21595ee6fbce7d15a322b7823fa1d49a36a3b8e6a0a8402b614091b24bfd49e595b08169a84197d59a1b4a52f5aa2f4f62e07eafbb0ce727db23ed86335c035e1bf402735534d5159f39ee3048a4065bb3c2d9ad72b01db78a52fed5162244ae10e642cbc8dbae10da7dbf47b49c77781941db7a1569b0e8f2f831cda4c35228080d6cfa588760b9a599632ea579992a3a228ef485c96a5e82252ab38f0205bd526c1af1342d73f491db7d79fe1e8b4609ec7fc61820230b175b01893e04b1456d97d6420261e10bf59c60ddc8bc5b52e61480663592c7b35c66c4ff8c0f84e289a301be70e4938d85891393ba12710d823014c911e134ebba88bc42febe7b01c42d1288354e33e60d29d20bdd45b81f6dcfbe0a15dc57a0736fe4f898219ac5f042a30a9be4001863e79e741360f9408e17373b759b37cd2259b0e90ef23680f069a1fc45fc0b83d100a756d241f444aaa2ce751f8139cc7f96713996aa7a4cd091c16bbf09742725bb78ea190c12b188f0d85a4dd1cd8ea91f07a79e4f412ea2729b0b1e2d3b4cf16b0b95899499eba2333e3f20543b546844d58782e0811bcc62ffd31310afd184dc223b698fe37017b8f9695c14ef710710dfcd948d62cf47ee878508af643ec0d111af5c3fc8fe5de6c2c6d62a9cc55b67bb5a728180fc0b4d45380a480074a27879e5531d2b38e1ad3509bb9acae8e21355f93147ae979281a5b940e41e641b27d79d7c63e5c1a88de36dca4bc1316ea1a52c4139efaa8dd2cd93ee1d33bc84b33a72ddd88384eceef5a154cc445221d509bc0f507cea22a77be90818b2f4ed0c437f2c8972fba1dc56b2e9c2371546b2e453cb17e8336c5a0e9ff5f945646b83aeeac41e527209332c884e94f651b1494c101b827dff1c1961ae2429e045e28a3c3c72e44c3ae2732eb2b6ec8270192b5f48b51b12c8561f37dd2ed3437075302a8865c82903f38ef3dfff9e69db5d43707a5402495147bd43e36f1893c3e904c8f8611a3e6909ae71bbee8b8da57104eae2cdde453e97803d54926982abbd664a8018b4b71541a7b47d33257657e262e1adde9632e1ae2bc02cda831d081fd128b72a2c073e5c34778e2a830cc7d515adceab2331bd440ad5b6e6348fcb64e377c4895ecd1a58a28f435e99caf809002e336f5e91f5ea9bebbade3491a9ebea2161ef9873bc2fc9d9171248003dc832f0cb538c28c5d5e45fcb43a4c566b610a1742b0b558e5545fe61e4da34bc49033876c5d1a0678a47204bd1f1c7df98ace9830252ceae23c8754998c2e921aa80f727dff3651b1914adb4826869230662998ea3ec3886e1e27280128c0b752e214e9abca1f801e694f4aa2bfc447421f04ea965715423291f85a114f3d9e6c54e112be13e84e07181c87259ef427215d18932aa0051fc9fe4e393a5d5c3a7129f42ad73e7a922692e2c408f8d07bcd25e43a498a85c43cb26a8f8c682954638365b1e98257fef9a31d76011c7681d296808667f104379a61938c12a5b4147976ddd721578dec961ff6d13135ffe97941e26b3b934b853127aa46c931f6d16520a2bb8a2ec0a2080c7c2598c154a694f727d3d8da49a44daf78b70b46db05e2089d8b93589c2f8edee8605599f0448c6c58731c243c9db33b52cca9448521be3c3cbe0d1ee736db881b390eb6a0e98403e9a1e2fb86b43e6a9cfe957582662beddb9e8dd3b9957776e632199523a58c4a602da3faad1897be8da9ce4cb346a4e08c5e4c7884c947f0f2ef0ae453d1356d9dd1634812223c6aa0ce04d9be5686b0d0c7f95867489a5e2a7f1c46780ea07b92531db73afe93268658a4a4d83adb71b4936c490242c938dddd25d31927ab8031b85d4db02acfe644e1f1407e5ded7a84d419d3aef2ddada878d43edaa86f35e07266655f9f17c9c92c4f34e44060b5a16ad16c57abf238c944c9939b3fc9004274e33b031ebb8b853230720da5ab7206ef1a966fd1fb26bcda339bca3b193fc419c925a9ab417dea124578343db4dcfd62125552b66ee9212150c956913752ce0b8c442b7edc0ec616fe4ebfb0bf7fec41cd5855d466edfc94d5315287e4f947a64ab3ac42e2cb305a872af516fb32c8150815b4ec0c6237d9d43e129412365732dc86f41020bff4b60a5eda911ba91346e47bf96aad9221f54fa7e92ff467f5756a98e6a87e4dc2504414dc51e55899f0e6b4510e747193fd2a259137a9a5a28d8927c1c92c27d8b723d5cd7bb2bac9afc487b1fc5c1f2a82c79c062a5c0b64ef0fcc36a05be9df004b148f12ab9a1ef65a7e133954a1beaad6c5371ebbf14e5bb6e7f3ffcc783ea1b01d22d3acfcaedd70edef3314794943446a9f0729112306021d01e88aa8c67ce008145f9c9ce22248d79df4f7fd5bbed62c398aca0a93941c241e91434f1f1f26422025dc965b550ce2078011b1e36a113b4e1e2b44cdec0d5af558637cb76086dda1e89e8c8882a7d061b4e562e605dfaf8286643c460dad8fa855d73f91e01d33ae4405c8ae20b993b7d66238abfc5664454988e0fd5f21e3f414494447533dd8a012ece713b3a7cd7c0e3decf35919ee2941912b3df93c92e971e14366649427b7683e21122d31c2797cecb18e39b74a1f29a3572e93c73c625db802b03451f5d52b4debc90b5295eb2a31650a67fbdab8d27d97e13183e201d3a8e141f69309344c66a0dc003c7fbbaa4ec6fd721098edb3e63206f074edc801eb23e1b799e5e6c242c782060660063622ad49b509d089cfbfa923da2df5dd632e465f91539df4e2c5d1f0d5a210d13091312f642790b355b3b7fb1aaa866cda9b9e019f60a30bc9f3b8677a18c103e676bcdda0b5ee2453955aa5120bed97e8fafba11351cccf1999c1810a9cdb91be032e486ec4dba1ec0a60a77ad63d3cd0099302a966a345c6fdd2af3231bbc06f8e44deb7d14c5e9daa2e701a8e2201384570b740377d1e60fa7919f5871de87c850de6a6c5f2ba74f9b3b3662c876fd7600a24878458acaa3cbd53ee9f6a90beef21c0f20095f349ff192c1c9fb54ad566e08648e029354536e68931ac1bd4ecdf6f907a870ffe3d4fd0ce9a8608d06c0481fd63af169df45e6253469ff237c551c7b057e9c16cb05b52de7f2c9267d1126b7b834b086e390e08e9ee2f72311fa86378ad34ef223006093db18efcbd94b445ec0ec0f2ebdffce8d82bf17b3010a89bc1c3607cac5dc831bf99bd409e03cf4615664dd6c7d6f663ce6b21671065d5507ffc6396ca6e78e5cca1a75cafe1d483dd5d78c36ab28413a7fbc97cbec1921f5086a2fe1672d3a8794df6b9ed50031b561bb219e652801f645b2b39a35aac3f0b99a99bb5b8c3830f7799a2ba93c83bcdd2e0584fb8e2c650b78b40e3aa1a478503c044a8fb13ff231a39166591ba09431170f46d058b7b245549427a8049a90a3945817d32f73b26c34a70d25e40b9dd65116317f89549c8e5d0bbc0a078f05d853925aec2523785b328ea93701c3c6e2f7603cc62d0880180c7518a86c0d4459f0ee9d14df19ef1189ac07a430205d9eab7710b799bf6b2ebbfc593e007f9348d1bb2bf496a11bd3bde1053d1f83479c77f599cacd37ee8d06a8b4d9d98a9ff8083c02f6446d50d67854b1bced55ae8517458f17c160e71465ddeaa0bdb3c1c0dbcc4d1187b2786f5ada2f3e1290f120b236fa99d3413e523e07667d9724e503e59decd38e0f0f2208edd2e0a6cb46037ae0f608848fc9e4e026095e80056682a1b4941b70b8fa2e2de689b31aa331af99a02ea6f4a961ddd9d8f4ba04a1c109e353b6e366f7c8206bcf2d2edde14a3b7a553efc74cbdeb4493828c08d860b8c0203d7a5f0ac375d7723b0fbb1b97d4405ce2d1e1a9deb70fa4bc0e4a52b9243f9af69d9b03436f0536997d436a4cc9f8fe04ccbaf3494a8e5836ffabcd35df5983aa9cd0e82a1674751c095fa0b1eadf3fff8972e2f26dfce3779f5f28a8f1d736e26242c0839c87303f89e10c4dca456f4db1c4411aec5d6f77a07013b8c94c50b716b6ee346364d19d42fb2c2fcf0d74db3af0bab81b69c40453bb2bb4346463792e7f8beb0caf2b53e692fb3cc2443e10c45d031fe7bcba3e7b9ab9547a730d4f15fd957f8ffeb2ad49ff2ab787d328e9da40a370ded07245cb9d60d9388b8349527d40a23edb7991d0524cc9bcd95ace7fd91d23055974af3ab98eb98743f3ec23a5b748d6d7434346ea80c2478763d060c3df89043c901162b384fdcc699caa4ad95e82f2e7533cdfa78b1d13be18d42cf4399922ac91d53e4ead67e36218038c6031592a817f568fd13ef0f3f17ebdb933797c79478ae7f75ae371ceadcb9cfdbff8de4b06dcb866f8b8ed2bc5f4324909ef2cbe6883db806eac29ba2c97139ea72591d8bbf83a54e11dd46535785d32c3c2a7fd18086c6db8cb06793d3ae79b5bd79f617c5580847ed3b403ee97c2abd8e1c531ead760651095afb9f633a42521b7170fd4e3153a8a4a289aee06b9b8fad26058845315f5a550aa29843c9af698e084f7f3a2f341b9d05738a15893a87a80bd5702be85749fbc493912e242532740865e6b5e9636c979f66549f4e76e1c48ffec6e2d46ab2a4e7e1f9e11fbf54375f34f4a23f731ca0e950890e5a44e0997e029899f9f7a782ff7d41f075c5f965d1f419830fa3876ba15e9131bde0954ba108490190b5876d78eac45d8a605481f9267592554afc5a42df4c0b823c1d4300c2b38b99045d80d89b455d887fa1c737e10e30e40365521c5a51ea9dc61a222eb7c22e2ce0191458642f0989b5e72761928afc169fae55dafd4a41cbe4463e438b6058ff668c9b76d3fc5bad449faa756af57b817892ef631a29818771b7cc79687a91a19108e00ce916c195386c0862749190ab7808e23093215b640863f79328581180b6f5264a86d02283c922043f508f09c9290616110e81ce03cffb7b5156af6c56d5b03f4cd49eaa2a48956e8d46af19cc7486ccefad04eaf22cdf58550d02c4e7bd5cc856c413f667ebacf5b1e79535480ef0c6537c2474f7a9a8d8ca1f0ce40d9649c0c499a14b23382a5df2e9564073992f73a632fb97c933a761f56b057fa4503bb9146a7a34369bdb8495614f44c0fd8dc075341e10cbced916d530405db3ef8d43499364ea36b1767ab25bfbeb1e6d3eda65b2355e3a4d9e09d3eb9c2ddedd72aa154ef00cb3d5602b3060668a468f30059b01ab1e5a4ba96cf937ec927ec9ea678da72142331f820b3d2d2c01789eaccf9d6b49b0d8fdc29ddf4d6b795fe1c2e05fc710c6378312fb422692a0723b71001314ffccb20f89105755a6ca91e6365dde2ae21186bf0973a2c745e016684859f0cfffd9ea4f0713d456919a658fe0737fcc17ee47b386c5f29da1c0ba94496b5d86f63261bb80d755fdffd19fec7ce550356813aaeb56999f989b74d82a29c257e2a169fdd2014ab53ea4e04c4b3542acf2ce0ed8185d5275dcda4eaf82c91a613570ead10d18e9ec78b078e9501dd011b22b8b528200c57095b2915d80865adbf2ae6dc2482993def0f1d596960e7e06ef535eabf34f0ef2dd18c08eedade7aa5d284c94f9af90b60695e7917acf1a79286baddcd5d396ce35cd8fe52c6a12ba7609ad77f9a4ae5871a74fa4a878becd33586b492af82a09ebb561cf2458c257ac1001ae25379ea8ab0fe7c639ab216040393dcc64efdc04e7a7fbc31db518cce84db20369585d46b1655a95b8f1750a98217417ac2c63ca6bcb84a56f55b58d84536b59e387d2e18c96df18339aa59f65c94b43ef67d9d8b72613a181fd8e096f0506d434679cf2eaac9758297cefb58355db95c484c2c16b8c98192ca39db549bd6f60b7a19848cc1326c34c72de374b43bc034c3dbfdc9e6c5471ebf7668d657aff301395416e326e510c14e8abc6f4a8ac12380a17ca1e0b54aa972fafebdd79ae8337a813630006138e6f57f07693ed179bb1478f61555e80cfa8b82a8cf25c78b89ec5529fa7d1df547b32bc647e4b936c821ad50412adaa015949933cab5224a7c128125050bd2b78afce7756a2908f5a627b5302a25ebad2611c817828f21161c41ad80ca669b6410ef983926e5ef9b7729786169a07327929054122ce05acef4fdf6c1aad90a307c0abbbf45967856987e7ecabf7016129297b10006c245fc2cee18b1c0afbc1af1426218df677bc51aa98e5b514850f4ed0c1a0a2288726c08211dc6169a6ae27f7c65aa10470630a0d44f828282fd1b9da4f80b8df22a664b70036534e0e3c934aca71dde5ac130c7e685fc752775ac05b0eb2b82ce7e1260a4c84cd16f4e26c0ffa15bf093bfd15b9b54d330cba17a78f7d64d89b6fd86df26ea086477bc04326b5e0013b8cf7ea8ec731ebd32056fbbe76d52eb05d4afa9cd8417c9fcd3ab1d1b18d7977128c10155d0d44c4f9ab3f6f7ad732976b363d54355732417d7c1a09b4239a1313756c22b668267e46febb93719125c453c253f2503c525733e45f9f7dbf3c7ec7039541452ae04f1bbc0d5734d8746853dc8eabf7979f0fa0c8c7edc1462ba0ca35e5db90f15073c5e5cbb82a260158a54a7a9dce719bf51d7a900489ee970ab546fbdfecee29a04f645daba667cbacb9e72e1b0b724d2467c900d92453e43a804da9530c6a3398ba3a3f021caffbb21637e5070ed270fad5c3e548c30203f878545be7a638e37c7261c90e790f4c2a657abb11d533e082d63131970636c66ed04efe0f539a4fb53f7663f6ab61f1e9740b7372f56651f749148fcf9dea59c113cc0cfc02147b1463e4442244bebf82267b1a8fbfa79305cd21a9ab40633e261cb6711944880543f82e18878e11a6313232249fc1e84d56110c3e1f8cfeeed4731754e03f73c1d41c4f4034b2c865be2ef21967653aab2d4ef7920cf2301b01b4d43f4dcfa157f6e85915303bae4a8c3ef47bba44e6297440d5cf2d94dcf25ca6190aa1b5c9c9703692d4127397d110bea856bcf3430b6579d21626b0bdba52c1d224570365a22e5846aa8e45549629593c9d27ab91279af1a6c22ba1ab61653366b5c51cefc06784b24b9e922552599a74a5e8bb22a11f89b924f7ea90b27ac3599e42472b62731203b50c539dbd8ce0133d96569ee84d9ff887b56852e6e2ab6b8f682f9cd1ed9cb582b9446f62ee765cb3878f6e86dd5107f225ee0463bed900ae57293365f83f2f09eebbe54a44364c5f1203ef3eab19882fffd8e82ee8a5606a9258c0b82350e350d81d3ec9215a79b920aa7f6a31773aed191cb7d789802cc17db4373e029c2c42c1630f47eefceb6ad5c821420f2b65b47ce6bdef77688cf07b721c4d6a323c0c6f5e86bed55a6521efd25c241e6ea5dc6943703c69998efdbfa06fdb039a08c824d7f0361f874c671003c986c1d374f04bd830ad753d54b3e5a87f502cde3fc2c9e14b9465faa30a74b19413b44cfafa35efd7adc95a7f4ba1edad324984a00ceda21b7e3786219c8e1887e9ca51e1f22b25e687a61028e4930fa5e8d07af39807a68ff9fff246c5e470525ea967bd228a23448ffd94279a7904d07e18c899109a1c3939962fa3a2a2679e82054c5cbf28d19be861179cd3f5d1a8bf33299a6cf1c54a74b53b17ac314e57aa250789f24a7535744a2c156d8743f0a2bd6947d9a64f1fda6b92470a46806eded6a35a7509f4949df79b737c93ddaa199a5d7d1659767fcb8743342aacb8f57fef73de58418be820a4b16861014a438e770de85ae000c14498ab2cc7e0e0282f73f33a36d8d87f73e2b3a9960e628ff5a953e47cc9470f3033b858d2d4688fa83cb0f903a076a99ec46fecdf6b072a3f6e4b81c66adc255c7c5bdaa2ff992abaa9c6ee964d441b7c38639bfc971c2a11b4611ccaa186bfda4772caf9ca60e804b1ea491e7405f62ab1bc25ebd83b462eea1f76a695617f84da648c90f4c6f69dc4427efe1a12b10f1f6e70affdc70aacc1c809c4c8c050af9123b2f6ca3d3b187164384fbb72b2f4d911d3268c74d98c547124207893f54a39f4cb64181133f04bdc185da4d3247ec66bd6d6838b03704ea86d6beb3e7ddd1c43dd6de18bb7e69da7c3209c20e7cbdc9d05dbaa6ce7487b43f4089f32f0a0925b6120f10f4ba818a899c079135476bbf4955350a5dbb33d262491cde7e4e7f2e1b4a6d2af1ff39a1b7584a91fca0deab246afd411da56cf30dc1776622b5d207aee1e8e863d957f11981ef1694625c47294d7c7031d06eaedf4d56c697483c822c00824316a5d631a72491657c9d8e6161555ba53646e99413a2a34d3356fc391207be6b206e02a0fa0989789fe7c3c4caa65b98895e2f70e18a7ef3e92d42e91736465a10279c874ec4e6ce66941629921ffa64f2115312661e4e4c9c24811aa0933ca1570b2670823bbd68c3280b8a7aaf3fa8cc927495e9f9cc07e21058dcf590ff8362bb216a31c212f026083a9aeb61f9fa82b21c34b77a9fd409fe44d4bf134c6e721c5b038c9a5e4c2c1051d38bb5cfe8286a053739c78d98e2a71036441b79aeecc8185382eb79201b3186f05e81ffb5b07d3678cb8d039fe8ee07e01c1bf1e3b4dd6a6154543d6829ae7551142df8b6ad96660294a3259bd8787bc59042798d99ea84bba863590cf635df7416225ee8ebaaec3ab546c074261508817074b90cc64afbf7f58960f723729ab6ccf28df458d9a6ef7fbd41d32a361cd63a45c3e4d3e50267fdf830277308c36801e25ce42fb911f098af53e7b640ea42a0e67d9b36389531ea644ae57071260442027e1ba6fce909b1a7542348acc07240ae31e7f51951e12b410f1fc692fa463694ee1d9d28a0fbc7e849c0915c79cb61dd6a994b1f578e1cfbd72958480ff629ae15cb1846148c29d42000ccbc9331ce58571220f553b4ecf598e218f93bbe9499c50f539eb9a2fd69e14536ebe3ab672a2cd52abdd182a444e31bf00290eb380d632c995b77ce1b9d36953371f34ac2cf6b8e190fdf7c122bc8e4381114fe7508946d408d529a2296293726a90b572771b70ce9d3d5eb715132fe4829807db98e5a4d3bd7b62900f7b0efc56d2de7fcc36281927a182f2df492b66b6c93af8bbfb5275aea97ff9842309369d2f05bb10c8c31f16d02b7defa38d8e4f0b284c5da31f2d020bc8dfcf232528b383a41a6c3c94c88aee81419e1fc87be4dca58b411395a78d95ca9e25311a5cb0ba727bd5361149d058d70044050821b927f41484354aa7f54486596ab417889d948bb278cd5a2f39b2a9f1e876a012c4ce4718eae9ff6d57485a44fabe08c6c8f9293f5a863ffc990ac1ee55854c86cf3911fc4620456e31ec2892ae7fb154b3abcc57c5e7e4631f4f4b4aa801ed8b78cd73e43486556c18e6592b5adbe1cbb939aab698883421d638b2526752aa10ee724a80ae04fb21e1316a03aa3f5c09dc61aae6fc7919b156012081d0951ba23f549c0c092fea4cc52c73d05db53214e3f083c59dc76b2e8d7c9a2f6543dc0c704eb076b26308c66aff75ab799ee2e5910f4d941e5ab638a231927d90df446db478ba68a9f41a005a7bbcdd26699a903e16d8159c870b7f695b5f4f6ebb8ce3e8b3902080ea6c0d6f72b908ca8e60a3aaedbb897eda80b45f8fe7916d3ead00612e46fbf6232eb36814d0445b960f115b627b1640eb42ecaa201360ef60b2c5c0426cf30a5871d1a11ab0b3516fb48e7d97c71e4b549ab361fdc18477c1b2b080580814303f638a2eae917d54530aa5f2c295103ba488ad898e778002318f34426223c99dd65179d6e4b8d43221404c2f11a08ec3c0d4b36fc491e74aa40f93b362a82bb81cdb71bd622a95083c12537cbdbfa972c1e3947ffefa7d0680ce882d44a8811b47c5d8624f472829a25d18a8d3d1adc4aa7047bb2691c3eb6eb0e0b1dd5ead171dbf3f423562888dd0f66be52ec055514e4c745b06d0f37358052e1abef712f4a26bcc7a8b0b895220d14faa8ae7a35042daef35d910fbf74bedfd47c0e51cd76840ea24b9770646865e0e4c3c415cd7541cd123ea765e6f5c98a40997f8a4ada5b36f9a8f705642f71c8518483f43c0fd2052ff5d7036d412b2cdefc02b3b6bd99778cdcd62228f2ec8a746b7ce18dd52d09000bc99cae49b85a9e3515a45a4a04d1d72deea9077b70709d9918885b291091fc4c51cc30e29f63f382d3a1ddc34d7e5c1f11128d1f2c5c8406809d63411e3126175e522f08c3e7465da6579290ed584e8af1f89f6fff8106e70e84847b09fa22a359965846afc0e94df61182e2bb8361b1d22740e8ae4560541a5a6744af97bf8bcd29d24961a8c59af70b5d2cf072c074cc0ff37d43a09163bf28a94cd4ad81d671821d4467cc34ed69742a1e255ee63281cd9b34f11d9a679a82595f8ccdd895d80fad4f538c18d36ee7eba11cbb80f5098a1dec42eb3dd885d6494486920351499e0afc5a1dc2cc6a5b160ed4be1827633d8336244680291c84b182c1824860b00acace00b3455f717bc95b01ce12cb5578fde310717c6b029325eb20cb94e13f5d64991c39fe6ad890248611e52feb74c979a201f202d927b0bbc0defc74e69ee18e950844e312a7a52839430bcdd0891607a1a7c0d3f6d6b9d01c6087f6f6406ddca4122b0c6618e10d552301ab75f3be8490d5ab4787234a66d2042116487cb3e025290405e4e4c994f28b6e082aecdb0eb015862e49d343d45bd7d48d6507a2dc06ad5984093d46410cbdae2923982c2a4bdd489516b23daa8e77c509ae8ffd785f10349bacfcf8ad60d6358f503ad980506fa045334e7e72a5b5124f9804b45952040b562d1471f07c007f7110a1cfa104c2b6fcbf53913376c538884731926f46f8d46319767d3f9110f1e4021790c317166a1f9d8b8ad0524711d210b3f8ff3de3750edca8cfc560c0da978d05e7132483d755ab8792bd9bdc019e194f3061d5e9f77143d2f4ac3aca93f0432958439da2d155937d261ba5e9e8ec85e4a9816ccc15a0181226b5607b00ab8f73f6df0442a66ff98650dd633c88cc2eb935acab12c4b63b7ddfe6cb2d29c73f027b3dda52c8b6155dcead499d4912a56773d1425a781b0725fd2d37148f6292f50fef0be74156a51f0dcc738babc3dc131a46ec33464404386b5c8302c5c62e15e0522dabf4d1c034f13e15803b0a3e6ed083876bf84c35f63898cc7deb988b878394eec03456230abbc66eccc680cc7c3adac8ffd84d61b5279fdea0b7bf9c0ec6d87d87ce496d4c12de7be0948d0ac59aed02af5d03f7a1df9dfaf99587160b7f07d9765f6cfa51905bb0d190cf5e0ccb007ca646fddf3a9945da5b211d9a15d7b7c1987d709a09f5ff02698bcbc81cddf1e8b25bccb0576f4f6c55c1068eac460ae6ff3294635a68d78e78b458fed54049fec6ae5a22e508ad9365f268fc3c518f6e0ee62ba7d5a89ade4eb2872899ac0e61854fc6874b650712a0eeef1c03c07efbc28d37e794c022900edc4e2242683c416dd61bc484eba0e7bd9e4f2990baf692b3042227cc146318d43918df95b75785cda6dc4a400e14969be52a42e72fc39de61f3f985d5ef89f26ca3a2da8e1c2164719ecc3786939901eb74c5dc49c41256a23931f0cda3c286f073e97f36f0acb318fb6c34e23e947115007229472f1828d47982b16c7a5e8cf4a6bdaac8562f17399405ec7bbdcf4a7ff0dcd4f07e6eb3e9b99cd49aadcec877b56c7063f23c36c5dd69f083a9b66bf866b8fa89166e1252bb92707581907e25be8402919becf3463e901c6b97773ab1a08f52c0dc1a0a7efce4c27291889490d8f7d477f808d3d5ef09d374d94569ef0aacf6cf091098e2ae693f99f2b131c5029006ae9ef630827a06071b4716fe2fda213079478b6f2a40f0def79320152d6d86e5aea6b7fed30cac9b3a45d61bc19001aefb92bf63a93a6d7d53426515884ab75ebaea4a37131d744cc17f309309f785a02d4f0f192c0d19f69b80447f840cb5e0e44e515d81c9528187dda1510746f1bcea23ee1f5739fcf4282026c811aabc47612b5b4d646bfc8d715c476eae62b671ff2c58f93fb4c289b04edcce9b1b32352b4cb2bb5ab54afff6be133e2190cc6afbd3ab8e6f77e8c335b57273da05bf64fbb6d0c8b4d2090893773c0ef3c5c034a4cfa765a3016daa80309f7fefdae7bb055ba7f3f47ba44b63af77f502ea15665c62c51694d0500c7624cdb0ac1b20cd867f318e6e75de71b635e8de37676ea238b1a1abdbf43ecfa8f32f77393b9266d1e1f3fc492bdf7de524a296592293d072e079307b9698ccef9cad40aa98550968f6bb48d83352c5883004de0f8ed2629b023dc146337741605881814ab294bec0b2cfb0b11d963ede545d9b75bc69a57f36a88f404df89021799d6a919ff2b1c651b3ac0a4183c35730cca02dbf880c387c1e264044ca5b3001a6981adc8ee57b2bfc362dc14ef699d2f1ae50179aab58eebfb1def5f3ef416fe1bb2372104ee40f9815ff43ba17f0149f1f38f1b2e227a542911b8237a0c9222488a01e65ffe070c0825be0ddee387011bb4e1fb17520cdee3ffe13d065b9e5ec05893bfb291c396dd8e2ba905908d1cc69e924f91b9498ac7dce40e7353ad6d5cfe21898a5f74f11b7013484f70f41e2c701857abd6895fb44d91222b4f8118d9e3ca4a6d476cd2a8d27f185f0dde8b3dd65a6dadd6bd56ffaaf732e5813b42525e9dd16b2f30ce7193914cb7c7c9a078f18bdf1ff546a421b0d7f0c13403ec600d0f81717c00b4604011311e1e6891422523cac474c97e2fc6a3d1bfc9d4b2d7cd8dc9e492e404cbf87996bc7dca24eaca3b6553769f82169c60388a60f85d89f4e3236549755e89f4e3eb2027528848ed7c2029bef7dd0bf9ae486d3f24d5518fe4043748e71cfdd7c30729823178eafbefbd47810baef1138299e54aaee4cd8dc9e4b31196abecb227bbf4f16e8747d39fde0087324bf62c2515e09922703865a329f315fc290b648ed399d404cf1c9a60b2c8248a87057bca3acf1e70caa6b8299cb2d9e338b239a5dbbe1ef33f080c995bb0c421060ea7ac25a32dd994394e96517daeaeb7284b9ebbe9cd792f06b6b85a4432ecb0e367477661070358681c1a77c4b62277e4a65186eced7bc170cbd137ee5e4eca7b6ff732d5b5785c54ca8e1d2a6bc5abc0b0443b69fd5074ef0d6eab02cb422db7dd18c1d073a5338c9e3d87377757999393234fafee99235173da0057598f29397ab7951d726166b084050e73b2b390e3afa319d03834e6d09e1c1de4d44a6d8fa68dc6b9ef1f5d124393e4f8a14fdf2ef7dd9cde9cde9cf37b99fab612e591d236323ac54d31476e45d423d6d608c83c1f86d8f493436a8c46a80fa6b9ab20c9c26ec19ebb0a922baa2099a2b391bb0a122332931c9a66496cf2de2b3d2677cea88289f1daa8e2d1800b4323c87b791e7ee7fd8e53fc24e3014fd0db89aa163089e29312225b10ab2205f34ffce4df4dd9cb3b11987ff918e57bd307c70df7251a2214f92f7307dca997c791b7ef5efceb21fa2159966e104c7f8a80660cca25dc4754da521b18dffbae24839b9c03232cbeb8e06d6ee10c38fc659825262f5f99bcbc7c0179f460c9fe29d4701855dd7be738d11557339b94601cb9be377db2bc91d2fb62fdbe1e3832fdee899b62a9e3138c599e0ce190588ee11024194b23592461d8defef6f631ac076fd6bed7849f37969c9265147d2c6df6ebb16d943e7def43a570061cf9035f00792801875d0381087c012fef5fc38ee38433340d7503cc7d17462fb27fe4894bdce49fc21538ec9f97529cf9498a8f0b8830252895c9cb6fa517304ef1530090e0f046de8c84c03c242af2a41084c3280b5b369b531c87f648e138db7f815ff7fd08fbac1a3392e00d0c67c871589620e9da18c9b264073aec80a787942ba1a2074c088308294029ff28a39982c3f8f28f3d282236d58018e316638c31366d8b607cd920c16194bde4d706d8b8008751166535005ce942d03dc7656e8c2e27ad934a8f76bacb51b4b9ab34c79f2418e20fc9325b2c59273331a74471cc39e73b0e4d0ce59cf34682352e2d9d73ce9177bbbbe577774ff9a416b6900694b2939e3f27a3c805778bd7eda4d5be8ded25f62987934aa74e7b544a1dee31e67829a50cbbbbdbba94f367947286b1c214399cb4941c7e32a9bd75b3b74eaac506ae30e55a5b5f745a8cc3f3bc6ffbbe2f7467ddec7dd559e766afc7754d29a5b36ef6be2e9d777610b173cc69839cf3be6ae7a0df35789b683d41cd723e4c8c9c3535e67dc5cc8f91326e639b6afdf893d6ef795f95caad52a9c536e7bcf3a3bddb9db4ca174752d29dcb49abbd1bf7f5a0cf598fbb37372af4e4708cc3a675bc80a375ece33a71482e832bc4f076f3c2cdcd6667c53836306c2010e3f03cefdbbeef0bdd502824aa691d69abece6c6f7edcdf04a5d69464bc12bf244221c3dea98d7f4fd232cf3795be7d87e4e6badb5965ee9f2fb85d0584159e584818991356c8c171323657cd6b0218e94d2992738e9b437524646867b594dc3f4cbd4efdf5a078e392e0d2c70fc8e1bc1288b6094e54712c8975e6409c6b6d9b69742b27dd96db3fd967b88fde1267f207e8a3a22d039fc8124d0361c049ae0f8dcacd588810ff672574102041798cb5d05c991cb83b7dc5590ac381d7097bb4a0f63541ff097bb4a0f352099942bbb5c151d544cd08c30a2c4c7499197121d5808c20583150b3288f1b062c1355bad726041c92a76f188e6aed2032b871fda625b6e555e77cb84136890c39b1a0427b02c0e628c9105be61fca02509b8cb4d450c2d6ea888f183160071371fb0979b8a1851d822e02d371531967001a6b9a9889184037a5859bb552764725379c20cf2cc5dc5054be47024f33f9856cbfef2c399a0ec4f03032cc3048c672b7f23368224cafb07402dbb0d57f6678013f845830b318da3c90177b13b1402bf091c5618154564b3eb9e87c724ea0349dc0f4985401207fa2082679806f3507e841effce0e941f2ffffd0e941fa2870177448fc11d0c86c09d96a79d0be2d9157d68fabe53f8c351e83b85411ff224f2c94c5e98e1b0ca2c886761956d205d65cbb1726822816d0e2391a7200986fb348850f1f0ee96a69b28489a611ad0cca7abc8e18c1225539fd6a913966305a3cb0341e0012238c4b31ce99478967d36fb3b64f3d010baae096f72dc56b5e3d18d2e787e389a738e7a7ce7dfd7435ab035ba71226326c30a8bc5922f5b9b25518da71437511adfe6b2fc842feb22699d769c52f6bfad248db241f2e42f7360595a9044592d6c2d071b6465a14ca5e0f0b264fea244e0f8a1bf2eebb25a27d2238d1ac593ff4d620aa29bb800dbecb008de234847f065657f5b6f08e004d36f5bef779decf2b8c925e5b22e4bc6aca32263c2137d737e736a11795b6a5990e045169157040e2bcba7b61c456b2e47d1203fbda02bebe5a8aaca12754c9022a11e691cdac5ac2ca0ca9a4059806240b11ec464b13963b1586ce290e7e343639e4763b14ff4bd44b1582cf689704c147a79997ac11f6df1b896bc44b2cf4540885ee7ee34667870a446709a6791fdbbd7dcee064e3ff9cf58cce1a47403d3a685414043a362eb477d43b728f530c6bc8a2a7208620e636c1459ad58eb24e98e41746c921d0c3939e7ac776b9b188bb1dbd3754d68ed767dd536be5ac156b0150cbb0c870e5bf96ad53a455a27be731c0c8cc3425f7994b681b58dbfafb655f6cd9be80be25602123c3b2ce18baf71be0c847fc8fe9e2477f1ebd14dc80e7b997429250c6667db6cb2260ff2f290a7573b0f594c124b3b4aef25c168b210b2c72064ff1e2d7f79ec058b32727f30f80d99febf9c732e99ac8ba5eb9ab073754af244852497fd43996fcc510ac9a863c61cfe977a1ef53c29dac63f447d2896ec33ea88ef60778e90f620fb532b9e494e3085f9e9097db9c96bd039fc99cc5ae992b68982435aa34b821c4567ae7214f5f15318adc37b7f5a6b9d95a328cd4f1e487bd039be681c4aa54dfe6e6b1e487ba664ff484b38e0b0b6eead50b27f786a55576dc9d34b2601cede87312dda2512dc5c1d3bbe33f43d0fa7318ec6fab349016e398efc2a1382f9b1f3484e7004e91237d51a2a79aab66aabb666f2a51fcee4f07a200db14b0e95a04ca053a2da0a9566aaf3d8d467e803f1cb14067784a44460cb53acb4457996d02044952be8c9d4ed5c9e8b6ea032cac47dbd676b7c29df4d2e33c3e1e714ee2a32909269ddeedd6e0b170c672e6d381c42236bc133b44f0e3fe0fdf6a252034a107053fcafe4e3c1d00379c8213b5104ff04db1c7ab9034d3b39b4cf8122f00cc3f3c39fa176d30686d3beac4f30c531060e3fffcbb6264b7aa260ed200bd8c3e383253e8009007bc14484c1226cce396788b16b2df94a543cd291e512c5ec12f5f1e45f5393e329bc81f9e867e3423051701861eeb2b463bf7778efcfc307ca03232b8cec5fbdb73d73560d6781cd8594031c36500c3625186130304c8047a153681cfa08987fbb39bb299b73d2168f0b06c39c7f58d4bce8afb941a174ede6a9deb95cb608ba9212d23db35510a9ef77280f3fa484d0f841eafbfeff4a39be827f4729e5b81554b82815dac65f052df00b3d366470ae953232054e66768d32b4bd731cc7711cc771dcb5b1e785daa57516b1e4b9736f7aad5a1500c50e043c812d9018631c8d9018624a952754b8c4d898d9b0722fc6a3115699b0ea656a1d77acba17e3d1e81fdb97610296a9ba5a2b0909d21038e468d931171c62152692046e49bbe50cd110bb641941d882d9bf09c494fd58ea7217bf0788b8b8c9ed631566e11656e195fdf838c85885575f0c326541ac8a3102abbad648a9b42f53d6b6b00aab6ccc3a2b4259e51e0fa52f37359601008cc3007df24f0096c9883492e048bb06d804b79be4cd121d5881658ada14489acacb8bbbd7788dd7b84ba26a6abce646eb44240820a26212e2c95f47c71c210c0c97c3a825aca9b552afc6889a2d77d4abb9c9ad43f38c11b87d64d4c2c2a1bbdc6ffd584b31b2e4290412208d7a8030d9004846b058ebc8f7f6f1256de3ae9c4929fdeabdee72d70b8dc3d275dda53b55bd3259cb64375f0c9eb29901bead3ec5a7206cb66c1e4082584a2dbd31524aefcbd4a591c7a501951f7bab9cd48a946c7d20255b9006cb258bc03309868fc9160c517053b0b3caa7d6dabf17ac74da79c150d2c85d60097e40beccfd00cfe12de19b6dfe807ce9a62f0c65c73563e0d0da4983185a4c16aee9f2e9ba9e6bce2953c8fef3d53a5ff69f4f1c27e2e8804397655acc966564c6a66bbebcd6413914ecfe04860390437f1201fb71e5268f443c7e192849f6164dce8d2282434e6afbd54d71bd835bc0ea5251c0ca94da3eec1eec9099aed284cd7881a5576bafb5d73e0fb7d66e2f53db666fdbb4785cae181ae7444d4867d9638c52461965680ab8c5ea0267c115060cc95d2b2527f36bef95ee5e655382787155b68bf7b81597b9cc652efb524edb789ffc7ba8134a7da4038b85c5a2755a7e927e94524a297599cb6e9499c9587975ef0d812338e7e380495bf64838e0ce336509124086438ebe7fa8266aa27168cc45b2d6994f9568937f289a92fda913a12fc27a84ba94689cee98e3d0207a5ef96f9b982638318910f51cc90ec604b58d3f03aec0e1f7489704e7ecff5f660646ccc28b2a57b090e477952b61e4ae72254b6e09b610b9fc92a3e8b1f264b665266507332b2f77e18a9eb451376a664d8dd609fde444fa618ecd398ef3f9f89828a35aa5a452d29c99edc96ed3f7ab5b5b6bbd60e9b6cdcca183754444498368175a9327a735896a5af320a29c5a8e44d12ffae44db8550553040ebb5548578e2341079f8211a38e0892e05225346a64b3aa2ac84ec80e8246511a061a95237f64e81db49f1c2d8274abeb5de4442183807e56124569ad5b4590d6b69c9c514eac31568992e147f64fffcce0e8825544b8647f5aa34134b410f3d35ae79ea23589eaeec5b4d6adba55b7ea56d9493ebe1f921292a235afe44cbe4a59485a3c355aeb60212b2e25597e3f6ec0911be4608727331bec9092dff2af942d7bd428c1d29b66d13da303a61fc1766fcd5c2aeb7944c016c4a3d1bfc914defcff9cde9cf6fbf3617978582535b21a265e534e191b05f30d03de1995c8ae6c110ffd382af2b82ab40abaa12cd9b5f06cc9212a8daa301f867cb287ae20c9317263e2f2aa19fce4aa504f9e69cda86656aba8a333c292a80f47a20f3ff4a1e99b51792a2bf0b4aa19b0199544d1947f4131877f9df9c77af06ce4137eb4ecefbd1439f4b4783337793ede8f476b9b2c406e3a228796c7aedac66d913ef957207ba402654fc18056a5b22ab72b1818181870a6070e27e0d68c2abb4a5523c3feb1a08b5ec4185f1e6ff7918d9403ecd9e3129e6ddbb60d6582eda6071c76d0f7f1efbbf44a343e60d2f643f206ce2cd9c01a6a84c09d5b9e24d841b42b3f24c9fe3b2bc0f27321b298601ba0c4cfb3f7a177f06385c06e1fd412b08fd740b38bde73c088c44ffe219efb2d79e2136f90d41c601981ce92637868495202c7fff85d25b0ccfeb124f30dd99ddbb66edbba7bb7ed7edb7697b058b56f8a16ed092c4f004d175642a3057905a179b41fe099438f526a6df7352a034dcb2f281e316ee172c12056e00cf4001e2cb8f003e9756e5f4a29ef9cb369415c56f8006146162870e15c8e638051ad7506408de49022e1428a2453249c8b7b15c1e1e55cb246090e39176d39e7e25c33bce8bae676bc6f77c0be03f6ef1ca50d1538942a1c6b6d0862fc1ead5a27fef6f2a58ffc719cd9d336520a2c59ca0c20933819a0749a517a912a227e922f5552155525180e5d4b8f6bf1da160f7254bbf7384e15a2881343c8f28796fd474ac0db73cf813648c9c30f9004f6211f887c1ef25f903be038630a9649d4a66ad9b24b49c0e1c87de52c378244d25e52d5257b772a55cec35b890621f93e0dd15a6badb5d64e4f4aaedb46dc6f922ee1728320486edb77dbb66d9b94dbec400ea4ad6dce6d4e54c93f927c8051f569d847e5340a95bd398ebee4699b735bd23e4044b2eee4cb0e58e143163700197179c1a50a2b74b08205136eb0722943edb500fb01a3053ab07e6022c8185a544065084e7228522b07ae5c8905a18758159869095ab2588293245d10c1da39db41105114d1042798e4200564f645cf154a68222528e58f47f70e40268513ba50828b275452fe9364892f546005079e6ddb46577e602d01450f530891f2278ac0250c16912955ec90f2c723514886da4d5c177aeffb3ccfe35e4fdc24fbbe28220b0f58557e666eb06ef090fdbb17cd7788c3518679c13460cb1910cbd30cd85de1029645123533ebee9733b30e0c7f66662998230c4c676a3333c72165ff199fa82366ff991fc7a14914fe0a86a61ccecc2418dec870661667b0e0ae71a56d10e08345ff7d38338b3839b0a8c3db81844c92d611a5883978645c32add6b93e0022ce423289aa41f2e4219a44e10fc542b150ac445304d7a090128d82016d0d92600d8a6090fc7a70241e606f147eff0fc5240a83333ae8933f3dd1506c060a39339b91d236fe3546e017588e8fc1298e78e508ce605b52b2bf6dd99628c797128698239ca18368ae250f9c81954439865b8ee3cc14114d334864ff7087911cca2cc9322e191e99961451874c121920a214af1c866a1d92c9937f68e6a11e4f613014932757e53014e3810c7ffc2a305318637066264f0e846766d9dfa59418cfcc666637582187d981c543f692a750e012ba3ea7ecdbcb8c2e658f5f0bd5da3a67a5a54ec592e7990f9610a4e4f0e60891f56f02aa02d452dbfb8c18e0b83d123f37d072811d19b114f71b5805074b72aae040851d5ba9fde569248122f860d1c40b09134a8628f10418b87a8083289a20d25fd3170ab060852a41113688c2e3a2010d944839ac5523e20a26c4c821e57f2351fdc5117c48820b1030c8a1966a40911911ae2574b1c511523eef9cd7c692676b37f0e6c60b9195394319fb8f6496c0b76ef1ebe6e45ea6b8edda8ab1e807114d94050a5c70f804485929bbe56bde3b4ba71bf94ac0f6def82fa25571bd92d9ec1567121589109911f948a46dc2f8722721812b2b5f22ad13494360e786b01f4622443016c73e3815f44efa0c712f53a357cf775b7757f214ed91a8d188f68c68cf88f68c46a3d1d679930399785b4ba646dcacfbe95e2aafcb9128af8b2f7cca893c9073ce7ba7947b848645c343adf5e57526513535b39ad956aba9d26a609589ca8f909bca185872ac3d8e1356268e13565996394e53e132c5715e4f1cc75fd9b1c8a197c32a933132691db73838e0b0ce6473c659673f5635ab3e5187df6057b5d6708ae05aab5b1c67562b97eca0040225904f9de580635eb97003bc8104df60619f93df2a5d90fd7d148151b28b4e02c1e45002d5c82e1a55af0001ddc001bb116de36f0120bd83935a6cc145fbd4993cb98f042b2d827506f3f3e5b086db2ebe75566915a8ceaa0fa5b4ceea8c86f53225465595357aa25010891285704480113ba6571a1e8d5e60800276b4ceb6835433a37574e798604893d4e0deab91c3d1684e17bc73617edf37e7d7719b6c0a8d16648bb2c844500d3e673745333fe09694f825af2b47e6c4992d709863adad350bc63c1188053ac86734f2d8e209a2b3d2597fde6dbb96c75543a7c2e19d9be469ce1a1b26b8ddf42d6bbd773665c24fb775ed096822a703735480e2c3518c3196bcebba8e7b8d5af0327bb1e22c16cbc462fd777172397cfaf5f8deb276e40b6460858b9410a9830d5250480f0073e80e059454e8af96b3bc0533ddbb6854f42fbc0972e5efa1238d22cdb8476992637e2381b1fb91a8b1b75aa7b64ef7fe1ea5513126631a83314fa28968852533b3c1d8f08b5f9ef529e4d0592990ecff90f134ff63f4314fa344f3334a311f49a4df91f91a323ea6347a99d20e941f313f03eecc7cccefc83ccd5f89b201ca8f9827bd0d34a00d507eccf8d1db40e3657c8db72106b461c68f9ef4118c41c6d33c10194f03ee40f941fa98dfa1f1354020a38f0177663c89a644e3634a335e4a1a33420fe490fea824a3d4f244533fa6d4a908248160700a3fc2581481640e90bc21fbdb985cc5f22c8b9b68fee326c7e2ac92cbe4c95fa6e4475288f24da4b39c0504c46a9d2eba811a28da18ad8d79998a017784a4626c4c696b9b96b39cf532e386bc38cd1318c360b0d78c31681e9e39a7b5132651d3f18c47b44e18918a1b342a27f41db287be82ec611c638404bc45bee2fb30ea207b1f462878aac0e1080544721ea74429b0fc548f5a688a602012951331b8816164c5558eaaecdd411f185e0f8ca70e8ce104ef08e6feb5b0453b8329889b5c861ae0308707954a29a54b0a0c560bf96008b4aaa25d62087ac88f4fca8094946ea06db604c90193e88724da5c40d5a12805f4c97fdbc21da4ec240aeef05cba82c3a6d198529e8254156562cb1656dc1cf7e2dc1b1fa068e9c195430ec6480d59c28a105c7001820ac02092f26fffeb7ffb6edbbdf7b64dcb4d3c42749287ea75b2966e24ca036536461965ade3ee9d9451b6e326d8116e72e130d268d82cd1e2389116b3d0dc80b7681d241865f961e422cb5a470a1d518bf844eb4422c4fe6078c9b20363163f398d86123874200f729c30c2f216c701d2e23835c7a130898a341a2cc67680c39b189afb9335f9eb01862ea594b2dba6d2dab57685a13e4d0a702cd1e45a9289304cc0e14d053cb0a53c5520d2684037ad533f47d976d3ddc892c8e291cefe059239449ac768add3c4a572f3956ac170f4b9b0d5ca551b5badad6f3f6b294bb6786834160c96ee87e613937244b758b52d33f40b5dd336b755918bac42860c79b1cbe5baaed7cd8dc9f43f1a614caae159fa1a6621c93c5a078646dd20fae4df24bbc3a84ba26e6e4cd7e532c514059fa0810c9c480941a10860a43e2a9c90922693cb715eadd3a45141e4c9ff46c149646f22fbcb20c1e175455587df86eebd173dfe0a881ef3f0eb6a1bf7ba0f9b865ff440bcef3eaabc5254853e3e06af2bac2a520d4730bc526ecc85e42ba3140c5f4a2925f8811a8a954a4e7292fb80fdd835140eb960289f860aabdfc592addeeeee5d23cc4d6e2b18cb32155712d57de81ddca16050418518aac86acd2ca1520c0eb07f2094f8a94e9ab2602f77048904a149da28779dcb55876c0e0386d7bc10b58dd1466e8b92b3f6f6b5d6dacbc35dca6bbb678c44a3156480c39ee518cdb0f8749ee32687aca78bd147edc5881635a9020d879e0c4f1453136d4829e59c1d3bca392795e2f29c00c382e141fa4ca29aa652a98448fdf8152b683e63838771dffdf65cc94717e5cf7ce62687b9cc7b645813dd64adb5763683d9ac04e1ff5fa23cefbdf76450fa42ce9b22283f49e93f115d177ba56d197ee1ca645890c7152cabd6d6dbc2aa25c42e1dd4411d54430dd2a54b972e5dfe67598344794abaf491474aa9055a0ba01b206de36f0304ee1fe57e82bbfb5b8cf5c438cbd131c127e0484e0a7262ac602016a0bf6d2f2fa4488a209408aa6e5c8135f0701821bc5a4ba5a4f276500daa0ecb9c4d2b2dd305d3afe993ffbd18cb1a5a12705893e5bcdbb710fba3a147f72dc41c7d071c76adbefcb026d36a1ee43407a2d1dce4b5a88a2b10d4403323050e6b5ee07cfc00e2a6201bf00018d64ca95e9c31ce393db045a3cdd90d820d7e7a884421a5462422f48540cf85d67129a594b6a99594058760a8c0918806be3d03ada33b47a4df3ab5678b2b9f28a8a44dd725b5758a4600000248b3140000200c0a8603229158482e9645393d14800c718046745c3816c883490ec4280832c4180089010400408000293335b40100d688641f47bcd21826546ccab075a1a8e40fc70265770515f872359336cdd01c4069ec4512aa6d6c9d8a2fe940a17ecef8b88f24e73888aa5a24f84882a84692489607e5a92705158de306af000358f94eef8037ac760cdab4ea0b9303d82c68f994a4ce9026c3534814d8bcd0632394651a9c15e4773e0e76d863a1f6fa40427bd0feb955288e2f4129ced8f99e55c654e8cea9c3398e9b7175b3f08741a35947f3319cb03ced39d26209ed2a5373b90fb47f46eb79c4f82b89c48813c0534200edbb5ba0e354d505de83213eb90dd4381dfeca8a305a3185f5ae37a595780d4f5976c372c2a5e85c33f717a3e530ed7ef514a9b609c56f270f4cb9c909b6630b6a148c5b17a8e9989a410fd3072bf135e8919a5490a075acb95b41803674ce6c29f1097ea3299df8217baf260d87221483947083f36f59bb5f56072ad780b5ce0286bc067481e51777e485f89d3b9885231b70b51eb28b43e9f1d73460707f2375cb40432d07381b5e500b9004ab20e41c4bbd71c3b5f0948eb01c487d173e0d3590c167b31d09612f3a41ce37bada04dd82a7cf26359fa1b354931b378e347efd7770f0464f03d0f36a14a64951b529c4af6b7dad80d7db2fe51db636beafdb62f23bc9dc58e542ed9601f626f9cab44b23e7004178f7ed87652e4840a779c03b41e4e5862d89de647cace1fc23993553b173047092be24b4b4c3b88072c01923c3c540fa1108566432f9d0b540843de44a893d818027dbe44deb39f69164761e45529b4c327cdb905b3e711aafcd5b6d2298110b73002d6cb15fc5b40a766eb8c3c2a1ec811faf3127fe9d8a4e7e7cda067b28d7f8d28cc78167a5f84ef4b913112abddee2184b99a5cf4cbcff73290ce1206fc2b399af441e77e709dcc439584153b32ea0f24b655b7c579958836853d8ea4bb5728a60842b7a9044de041169f0e11d0c81669841f9302cc31473090855cc9a0a94d149aff24f0dc1be3ce582e1e8bb0c2fb02499bf19a7a48ca794f4195fa1923f36e90f817fe442c45e5cf8b14a4b69618358cb6688c960d0a18f7a9d088c968e059208b570dbb8cc56f4d6d1894a712ad1d54a6f1ba29f99e7aa63d28a2cdb754d180815996955d1add38e291f516c7980c60bba490c015d1e52af1082a356b92f228264128bf33698b00251ded7fa4b78cbfb1bf0007ca1339b82e0812655b7ba5a01c7f14d8033570ac20f25ec59e6bd8f41390d5c918321796590de27a2f72ce0ba2183c06ac310c80a4d2c1363b3c69783c741299b4b2a32e6b3d27f77a7e9879a9aefebe08e445f4b6fd3c326e342f8b4e7436afc39e60a2502416567f3f0d922cd12afbca64fce52e2eedbef851746e24cd2d92367bd2018a3f8eb4177caf23a3685ecca07179b0e2779baa8d05f6a0026a9e19395732ae811b3eae3df3086d3662e90ff19a58c44114850a6f2b7917e91ff5c763244d983af00750dd93c582de5161a933ad14f44cb54c73f8934d3bfab484625573e191d85c2a78a7d3a7cc991ead503853329dc6c60777db4ff2176019f95f01bb1865994cf0ebbc889c5ef2a079db676b1d857e736bb810ef929ad607ba33c48539d9f9b4915b9d5d4e7b424c2549afae460f37938e8245189d8881f4a1b7e3f7ab34efe09f94e403fa02139b6dafdb5a03d3e19535a8d6afa4f588e45b780acf615fde77a73c4e93a9fd2fe6fb802bbec759cca4859609bd035c15556deeb8c60d9e7600b3b9903d0693be27d5356d1a11bc9d1468d559c843fbd53e00c04033c253ea97d2bb6473a50685a3e91a8145347e0e5a6368ac60b1a1abbb278108d6d2453b84496235b07ab788a64bcefd24071189b312019618b18711b93e0a9064c327c2af049ddb845282695ba6344e612744af88e12d2b520fb388e0c44f26066fa81b8a410077849baa3836b7165a248090819069fa37f0eb0df6bf39fc94d311a8fe35c40e9943d108c39b1f8d90e753219ef567662e5c138164d935c5740b81b15a15e8d0f934cfc7bb347b39cd40f4305603d10e143b023009ce32eeb8779a68b7c28795a4422af7c2ade61d02c48777f8908876b6af88d36beef580d523978b34ad114a205846595704d75112cf03cc91267038ba05b0323208fcc83481834bccc8320e69e62d27e6381c5c9b5230c6188f2ca811ca1e262edf937485928ecd556bec2f6e2aa213298efb33ae2b93f64166bf2ca8612882308bcec3a56702292353c471bb9aecd489361f250816446782e3e344a5fdc39b38b58cf54405eb0e40f814714de57c124bfaa5b22c81ebb0110b084469d0f374b8f7c84d3f3c4cc7375c143a98a0ad931278f6b984233b517539d15bf992e21068f8b94488aa924030161355afde2b2f778181ac49652a4a49ce191d188708efb3435d71215a95995e51eaff4ee420071a8ec4b3fff48e95617483f45a921a6718e9a83d5b0084e14a403141f92f86244ae54b064eb2fdfacacacf5a7227c9522446ccf6b13969c0344e4b208d322cdb0d8fbbcb64af2ba80f430f64708a344e342a9bb7b884a81618fcc60dde9b2514943659de373f426c75ec4d337a9b68a1ce57bd3d1381b835774a0ad92d061d12531a4a90f19229f1443bdd01a03e923e85decaccec5bead33dcfd6b8b3a0a09cebd5ade4fb1f5ea80d68916617df67f94ad1a9e6f8fde251208f4e788e3c82c184b88d08a75fd1ed2580708fc4581d7be87e2ff9fc66436be4573a51301a14234c05c6a827f05d010d43b506215e6b8e2f472c35a58792489892602a16782380b268b45fc9f71d4ed213bf295e3e1660f6bbda389614f4d72ddbf1aaf7a3b2ed65b53498e575d2cb17db6d3f04a445e597beb4c5663c3ed2b2ab18173ce831d7f9995f4616239f8b113a61d13cab45b6b6e6f042ba0efdb4dd315f49f072260e0aa6b46717b3984594e181409d48e06ead633a2cba1800ab734c1208a798fb2c853d5266e6d02c621e62f58bebe25470d68feee9b7bbd89a29fd465713042c223061fc736acc6d329886a6e06e4c9f556033f17220821bdf3597ac639c83a6162d5225ab6402e71ecac874221040269c0bce25666786d29801576a52cd3bab5c19006b716d166ce9cf92e30740d82d49b0d8aea731738553b97afaa97ef39fb14ba08824eec8b3d88e9f21b39ad3780c875c3ff654b64d60fbf87431a80db87fff918b60bfa709080cd22c771df7a985d96b2e5025c04699e8959d91d5fdee18241bcc7d548d8699452f74e8314b062ec8ca50fbdc77b6b9c47ec642461587aacc2c912dca872cd4ccd1c7a91cccc5be0c8c9826c9dac57545685b7922e8bc33d590ca145234b45a6522d3f60e369c0295508a84e5e09dfd169cc56dbaad13ce5d09c80628c78ddeeb964111178e9920b8975612ddb44dc8b9bef9e4f7abb357e66ddcf7336c963390c189ab5ccddc86a8612cc97bf1acb91745c3b41976e8268751ad627f33947ba0ac2d1c08c77d65f72a28ec45c82615bd5f9aa339937aad951ce0c0903d4e0e94a0022f3c24536c49041036603e2316f2e80635eaf6edc8d7a5853b8b8a121180cd97acb32ce297425f7a3823a39ffb52c8ec5120a6f8f1bad907491fcabdcac761b99340d167351636888c5967f2ac38235cddee24923e1b8f1b08e4b58102f4dc2dee028c10390c92f6c022fe130d7d78d500dfce71ca001506167a0f48f0b8a21502c3b0038933bac40ac41fe2b90e8ed15944e7ec1adf1e50250368882bec25c835b0ee69675f7837786774ae0790c0f36f08326112fdc5dc4e77e252310d776de7f6f1f7b039b644b9f2e30bb4159cf2bab1418e05800eea487f146611611527d285f0b1bc11585d4c90625bfbc9f85ecbf05fbf50cd069bfd319202bedd47e5fae40abf2b3d8d52eb9e5935e5419fff92b7afa98de79a3b8adf422c05764d4f3682799caa088b820de2457742812656994556fe6131c50b4c7743cc30d0c0ab657314f0aa65e1ce1cb27707cce9e6411860b3a6393bdfcac561736c1e201d300b3c734972e7fc037afde6ce4358b793e91d58782900a258172f22b058cc4b2d0aa4b68688d7449477435b6603e2b57003a210688024c2bd3d85847c5b70b6a7835a6117787c75cfe2d74a4fde455dcccab22c0985f3c63432ca8c5559c975c336512dd2d209683c2707cd0cf16b726306accc60ef6fde709b265806b53435f894e224a8855c970c32b011c97605fbc24a21cab18f0263c6b14de5a0ae5262211021072d4c956e1fcf3745ec577f6a94367c2e51c49a4ba49b5ffc266d1c28f2522602aaa6197ccd41f637c356038f5ab036ce4525107d5bdb5dd39b7851e7ec21a804fe359120f958aec48d8b7bce57f145c33975b7c45471c9a4c3844f6acd9a8aacac254d6367ad6827dd29bc8fce414fe40d193df5171046ce82f8ac06cf62e489c99685410efa245e8cbeeed9021441e6fc322fa77559f567d01b3957f436764c75ca6f5334b151860421c6c5c23ebc1c6ecbe0aedd1c9fcc692c0e3b26107e654c49b983c1dae1c358a83b48d346e22dd9626c44d659da1bb5d30ded39d2f4adff0c4417073c9c2701096302ca5d87a0928caa05fbed61e3770a3ea5f8771b19e09c90d27211ddd494cb89474de065412fb280487665e911c85a014766239b96d104429d9e269cb163ed1ea6a6bf6e049cecf20f0cf3318fa1fdc34136ad1d7edf41f1246ed512c29c476a6bc5b4e57e32a160d13e16191c7455dcae89be16327750939918bb4889c297a71d74202b59ddf4107cc08088898db44471757681c1b811aa9b10d1c31677c5f799681ba26449f77a8b62c9ac04f7234d3e9fd12f341ab7ee46ba2aae34ba28c0888a30016f00870d63c6dd866560d5f2b48f1b99477daa210573e64a16334c7edba8fd4ed8c8acfaf056250e0578f51d049f206909e128fb3bc6d6d64d33711dfea90a717fe79c8d80e1e5fe97802f50e9745c3bf6d04b5252bbcc2bf72672bbec909cf52f8a008003136f07cc273f51fb55a0a870f4be318aa72bb18ede2ef44f68cd4b876f8d63ea0d8baed012c0972396a6862c87b04a9982b7d5e3bf48e10f4dc0a8d6fc07ece1c690a0f66c23b6fcbba495845654bbcee635dc96b41c66028c327c290575de131145b240b4ab7557dd3a54590f3b9343cc3ce84009873188908fa4b43caf240d2f3d204c155fc10021ef72265e613607bf8507b529c13b14dd7fd52f2e5853cf27a314384030bec71985069820b5216355ec061a3aa884a85ca454dfbf55c925d61840bda63e294314910085d677c14f933d922397e999d98c6315224ad8ee47a16ad0cfebff0bd74706299187546e9c4aec563123c5d69e357e7a9671b38d2c654f428b6a6a148b0e93c285759b1dacb88e5972b4d0a9a635bde211de3ebe444eb0a2763e7c8d19ccdbce9a7577a4b53fc1be40433ec23d481da24c6d3369ab34be671ab7f86ffb246b6810abaf6d6872729199b1213f21fdba4854c4fffb38507124851437f82b2d58f7a4d1ad0412621e5377d420ad070d853d823508beef3b1ea9f4730ceff30da57dacdfc3c4c3030fc5a9b9983da21f48890a9cc9b21866a482763fbb0bcdeae7ae3bbba26a5259ca6c08870ebc4f3d71721dba03ee07995f3fc6c6e4e06636de8e79866fb8af308a7f1b445396894354f23c34690878f52ca5c41bcdcddddc81a7f57651f2c161c8964484b37a26de3354ccbc02d0e0960714fdd3064f9626cce14dd8a23cb03f76e9d729cdc2d164c93e4c8631de5b008ea536b96e465e0a721a22e8528daaa2f1f3da0b353425f59f8c779a09781da84539eb642bf446e9fc27043366a73fa9b1f0586ba991283c0d43f36d8510445cef97438fa26c2f606954f231e63d93ecb06648e3eade6108a4834b13c047a1d5b8367f268d7db14381f9ac55aadfa95ef728d4292b7ce17ed3140ffe1132177e59cde7d05f67bc3750ecfcd85bf22509de4fe6fd346ee2d3cfa99d196a2c768e6e9a62f13c225ebe0aefffe26bb3e6f06ab0eade9a1fbbd6688aebfde0cb7f3b48b094431c03a75fdce5f4cd5dc61c76b963dce72fc16ba82cf69659d30302a32705450d7e4c3710a0e756c816bdec780dbb56e747cece6f9ab7bfbf4cde77dba4eca72cd4ab94c2cf278ff05454a900317799f23d0e97dcb2a26f6bc21aee204b23977db649a4d6730a9e720bbe103491126ee72868893262ac452d236c1cd53af46d267faafd5811d2a004a4f51e3e2203d5998921c59badaa7e865dfb6f50e8ff5e613a6f1eb000b06a7b0e282afb0136315fb54284dbe72d4c0091f3e239c49451a9884afc2d7b792480e9478b075bf21f76654f752918c01d9a5b9255bffaee98264f22eb7d15b91e2262e5ceb941bbba6ecc76e8d580a04a1434a95827ad2e00dba321d7829b6b42be123213a4c651e3484b5a701b29d84110cd20512a9de8e0e6516b192f9302f460b6e609d1fed27b90d20ec8c3412a2d1534fcbc41a0c764626472ef9468b8ccee473c11571a3feeb54d43665dff34433e375d6337e605b9762d5200025d4e5afbe76108d361167d5f830320ca325d8c89de0e101e588a4f21dbdf35a61afacaf2c8fe0f020b131f4fb28a88697d52679800c64f34761e5cc3b03c30fe0da15b12379cff15dc7a602a912e1952a1dc154299c53258294a0cb824fcb494be923522db6849990998b220c8832997feb10aa0da6cca0bdf369db6d0c674e8c7bb90a89411cb2217ff8fc6e44c13e31941762d6cb1e58c80e549ccfe3662569e2b729b58235abc658747bd9cdb6cc5cf27e21871ad63f4917f75b7d050265c54904a17cf4b337c06ea40f1767d3168246f131b0dfdd88a79cddfe09cbb1ee7ed428fea281b8d9c7ea2016d988ca008b273e3882a8bafaaa3c8843304f315021a2d423c386bd4144efb823862325774fc60426c10633f78f7aff77b278258838431fe020583a823d13465aef2cfb3aec561e4e2c21364cad9639a316eccfbc75f3d46f8a7b0613d367eede409c9cf4ad06f1d20e5a757f827527db092d255b3811ea240feb85e63abb86264325d34a7786a613cc13335ba40e8b86934e95f78a4f949fbdcdfdae182f225ab3c5787e45f7d1b46c347dc866bf237061d5c105816612e5ea3ed07840ff11368c28ee80b340b17429aef3ca64e647245a97c889cf51f60519449fc617cea311fb92e5cd64a6bff03d70785bb6efca340c6f15d912b93f2a5c960a7a5362cef8464569277bb1134efd42fa67e0e0c4e3e36272f79879e520a7663b03e1758ce4d1938bd17003af7725fe2b21315d242a543fa2d29232b5383ca260e78e5714cc4c43837ddd35e71175c9cecfe38c037d74e4cff607ddc1e4362f879a5069c2ab147e8888c4c8c25318bd76b24d1b5839b484c1a4b446d08ff3290292029e56f114a4a6f00cc5bca94ce4b162e8051bc71d37c8e6f67516b5f19214deac66d24402e59e33619a8cbece4b81651ebf2feda1e2ff9df438d93c0a41945120c536de9bce40b186c9c59af855ea8c7f1860f86f627cf6e8ac5d702ef34653bd30edb2f4017dfb3f0aa5e3983729652b159ba9c406d9cf5a1194047bbf62a795b9ce36bf68d336f005b6c9343c7947c1f31b7bbf3db979b1dac18a2a833e84ed431265fbe4ce7e94894257b5363d90a08afe8237ead1656c7fe28e7756f2812db4f39598f66a5a6842247fe00e14262c72194106f9f4714bb4f0367b9e9a06e99521921866e126c10498ba6a0992be6c42539b5bab5d462273b96aebf0c424d8bd839f8346e677c9597d2f15b5f342e9a3e371d4e4a27b559ba69a1ad12e797c52a8d06a79a89ce3c45ec3218b75679bb16ce1a201478cac04038839d4d9a18fa3996deef98a0eca2f042c9fc6c3eb18ae752aca0c7a57d7a9a849f4528e73d95e0979ee8eede93d6885aa5fca332392df00983d1a3c34281a005bb229246dc776b6d0cf5be9bdca415a16a48b4ff5e32520f4bc08c045e0777ad675f4cabc32b279181dc196330d570f8d534bc2cb242cb9c4ced58947dc957125b93de256f88b15103262fbcf71968aed0b29d7a684090fdb68382c1d4ee37ce8f0fbcf1e46d56c9948f287452477e2744d002522008147643465d08f55f8f0b835ff173d51a73bdbd8fdd9398a4b38151b566ade04a4ad25ad3e407579fd6372cd1d52c6368389c9671aff9ad7b459b8c3c226ceb36a0d313f04eda0e303452fd70667f3c31991fd10f0f0cb139e59c7c33d222209ee5583e920844e0b093177f642cc38c1fc8622f7ccc86d37b41e1ad9c73778f393220cca5371eb690116c6a995bbe65711b0c278f0a20497cfebd34719a903d64947b7edfe717b04b92d88f98fbf97ae58c35760ff88faa918cb922e3d2f64d3db176f9cbfba579fde38df7cf5aa6675c8e039e0b51d01a5f0d508649e2d3c01f7e4fa61ea049f70a053a6891ce88281a5b9ca3c5d0e2aa8d6dae142cdd121dfbfed072dd0ad92354c162c7d95634ea3f24081c9723124dbc9b40278a475117503c88c9297045e76d5b374b4cf3e8d2449c6e5bfb136ccf60723ebaac162c1f60583239e48ce08af76b34fd0979906f3cb4c645a8b042392fb7986003d1dfdc331252ed3f7b8e27bd5944e4c1a0093d7a84b8c8e600c8fb7381d009d06374770a930d55c7fc38b4a7138f9153dc801458c26fe0c30e91ba400839484f73f53ce391401fb44a880e6a8a681d0d225040307da4fd27bcaa72d47d9edbed3bf5e66332e8e411b104df2ca0de895eef674a8c05125e8e51ac6c8c485881a6ec0180a78ed0aa8d16fe1014de8ca714c52d424cba4c0b3b279845e10c0867d14cd742ee89ac125b078ece78c6dc62f3f8fe16688d5ef77a20e33fdc21a5effb6fd181798ffb285d20b19af70091507e23dbbce4bb92339fad8ec89743539576603da2bfc84be05097b18b7517d45b5e9ac027a1e12ddb4bba17639762ecc91998fb088418184fd875752e1dbe33416c73d003fe75723a4b64e069d46d57e9f46b4a81ec7c4c8ed19f017bad320407306f74e78177fee8a78490ca4c66cbe598d28fd75821ac341ef9a0b20413a787d2dc9abcf103370894ad864ca610ec3f3fd312ed91435f6999416430db1f24201416e26c9c1568b62daade78588856e3ce2fe3de78e3a6931539e3a894b91849d3b819f821f230f0a6a72972775adaa36818fa040129549ed502448e3e5fd2b644d8041e7fefa2ef3e769102f5cbe20fe84605d452a970c19fb9f161c349b4caed4db91944308c1eb84e31ed9e59fd9df479b91fb1b100ff6ab71a978ca5597fbe29f41377ec4098b5e6d9fbe753badb0ddadc6251722c4a56c761175ce582a2beb707c14986cb61abd1752f5339dcd3b32be5eb4bd4498f124439a77e333093168c64a26981d7da72ed46ad6c60b3ccd190d9db5f264e315630e2c0f1b11e811f31d442564139b1479e8d7eec48c70902b5784f423d59e03fcd963606549bbb7d2bd065550dadfa28565326bb01bbded3c44db465232c525be3210eec93ae4864dd36ca24e837c89e12bf0441ff828574358dcef536c7bf8f0f77529abc90deced0a46310e1507b80fd22e0d46ae25f8773a66361d036f3a686ef4d1b79f246746306707776e6f30a19151670a206c7b1dd99bc074f55310e4b25ef963a711bfc546ca5c8d949ca93c045cac4eaeb8fb619a8360e91bd5550462dd5621e3af1871af40250f93055aa3b064fe56c9ae25324e4128dbd30d1bd24b4ad1efd2e90bc53ba90dbe0e894e77026af546ed5d7de087f0fcf39710ca9c51ff8990a9567532ecc905622abf75e2a44494b7d788d3614ba0360da9a7313fb06c9202d5f36a2697bb628c1dc280d0a5f90125a9dc6ef7b1dc954b05691e33e020fd643bf8332bbafd4f602eaf68815ec7acb37728627d339c478346cc7bd53d9ad1cc487e27ccf11c24a6ba398219ae5ed3bf7da3c8f68c0040184b46f8ba20b41277e0592c37037075202b37bdaa3ca0886f3688c0c89e7e14c77253bd5c7ba380283a43e51d6184615120196527c9cfaba4b97c5f789bb5f143d19a15ca97e253b98ab70a2f616d7cf84692a73396e8762a3360c291a087f254d6015b48b225973123caeaac90f22161a8f006d43207c03c2b1e8f3361c4d6457004296c1cf89a474d7a271dd856b28beb449b040331aaa8e337ddc922716e7c51ea177015d56bc6d2ae3cac952b025464acc398cb0701ceb4d5e4f1a5a0a0f4ef51686034ed49ced0270b66865c9742f8d30e3154a1817e2f30b6e9266e6f39db00e0955e8e282db33a3ce3681d908f52734a9df924234020fd87faa8ef81789649400e16e82a993e7d983fe4397e4f0e8207f64a3fd4bb12cb11f9451a884b7ac548450ab0c34c6c859a64392c0e4728b48f4c8626fd307e3005c4c28f4d80e518bb17f64f4e4fdce48804299b066a5eb12dd15c959ac93f8983c6bec5d07116d642469edf16d401ada8ad015604ef8520966551edc4108e1f91c3115632edf254213e732c31f992e01b4b2f55d4f3c3f8d92cb1298bef25861038b1a7fd117aad5686df02c88b6a46bf51e23f42bc66d58300bb13dcc934cc04182cb20f505b737c1c2d0fb73df0c795a1d9260bf88739937405d5ed460e051da10ad722a98fb9821f6022c5d8b94f49f46e5eec0c8e82e9ee244e35fdd957d9eba441efa6e978cfaeb7e51f350bf15c4cb1aa57eeddfebb46bb5e156496f681b273312f20e7754bb5bc9e5d1caa74da630515461673a834ae574ce96f7615462651be17e026788d1f9129dc4711dccd849fd107b24835c5d6ca1c67154ea6f7e5137e3a8ce2a7e1deec25e6f82dab9a84970536f2b54fec906eb8d408362f5e0674c3dc2c7b7abd993e032fbcf3d096f9cfbb0e3a2844065aa1ad76071f5d04dcbb7fc983917871ec58e5632e01fcb6b4a3049d2d51d89fec00eccf177841d90b72e9e0fd9efb8dc7147df70419d9fbb0002518714144add4950a9040532ab222fcf903c0e70f2f7e7f91a55d0d6c99f441077561c67dedc5d27c5404cdc439c4da3b4544a042a04c91c145914b2ddba8861c25ac3027639af181edb7a5e96cbdba507392f439134ba936ea1f77173244126aa0586aaa8d6e05ad1551a769c7f9ec09e6f8687eb4a469f6675ead15d8a1df2ce8b44d43b5d4dc6c3abcf061b1c68e1368794b39d396f2e26d731092062a1e01830771e46d4b718a72bcb18aa6bab13689438db2f49fc95f90c1e4c6c63b17c01237b660b9405f241ef2a03dba96318b4e9608b0fd78b2c9955f2cf61b69594739e39e8dc904daa6264453bdbc2864728c3b7cf705fae7aff4eae31be7e2f6a8c52bc25218b533a0ac58f3d175baef3c23fd88acc030a3e20f91f8b2a7f85a1bd620540e40261ab5e2f4337a2e9c30e1a861876cf0c14e1c110b0b5ecddbe4d38552e90800cd65a9eda4c0f3aed860866c6a59dce7753372108d88ee75e99f4c70bcc1a746bd82cddd6d74fe985d78aaea4a01c1824847ec7bd49ae93e89e35b618ffd89371bc3585cc97f3fc90a69a4237efc4c2d44bd5d08c12291a7867374b129e340fa79e6f7a94cabeca2aa98e16a7bdfdaa251b337b9acca3dbb375c2f6a41088288e8b26d56beca5c309bb4ce9e95c8952995f996688f6cbc037535d80249b3b3b73afe245d71351bcbec1360dd0b524ca9941023f82037ce005d1fd098bc4b03a26bdbf4d0bc0a00761d9e220b033bd40023e29656bc2f828e4546d94c105321967479c7b41203cbd07a5fbb67f06c4b160a5a1b4835e0f96c6ee72d8bddf8ba459e630d0eaa3994c035537a35f41ce20b1e099053c1c24ae6480115e5f9397996a3d5f6325c0300c1cfc7f633427a01c1d8f0db0f0d614096c168af85bac6ff6f5aa68cb83009225139c1a199d62fe6fb19a06d016c7b030f3e60e3f0ccf5d947a133d1d731a7c1f63735b22c67085744dfc9223d5e705eac1df42346e2ecc495ee249572c821e3de0bab4f551ca7e92297e7eac6ea4f9e6820a82122d053d7ff068ac6e88254ca4db6f68b088fbe30dc843a45bddd3e5732a4d4288efed41422a347fcf4e8576818ef1c91001cdcd0bc4c03ea47061f7411c39c169b8f239e129457b7a095ab0daef12f791264a8ef44cafe967633b9eb1f6618e0a22fc725fba4addbffe71032bd333ba130e89d19b95a2a2efaba7d5797897f5507f13f0c421843017095829e8407170621dcc85d4927fd5041f69c0e0832896c6f08b41a14b1fcc199b37729115026d41426b2aac2a9045d4eebd3aadb9cee94c86d44ad4466afc881060d9e0d91c02ca953f52564c94b81070c10bb94cc4825a672ed7bf4ce899e850f37d6ed82e03f2645d01c04897ded0e271b2f72426d474b90b5f150c57158d162699c33020146f0e4604514ddef7daa0d28918c80d301889c4d70a979a15c51612283b8de293ef5283bbdc1a311d92f5beadb7b302a4aab1bfdda8e8ac8370337dde7c7ba17cd224cedd7e63107b3777bf704b94974ee710c4701d107bfc503496e0ed125ef8f81440cdc0f16786ed165a7b9baf59f5e3a0295e4403e1cfa620ccb23329bb764cc7efe4578bb0157f568792b876f7080b1a0e792b2b34904807a453c7c61d2bd6f117da1a2c7545bf9ffeddeba528289e1ec21c2c991c9b81def7cdd69130d44c092874022a67614a0774cca98b671b1fe5b6430654c03cf54110ca75efbf08ca75ffabd6831120bbc2dfd46b74e8b0e4276a4d8a12753734bd29c027d038211aa1ca8f96907ab33131da0bee071f8b07b8e68d7f41dabc615ab8362da4b77078c65a3e41386bade378936706a0b0cad2d9560de02030ae6f01a5a715b60b00628de7314a0ec3841c83d5ca4b550aa85bd1eca8011498c0ff4b87871a60872b07e521484bc34335546c23a529e6c8f1c2f274c9a9847bff3a8059271248a39a0cd8a0e6f6fd409b8bee15489dcf02c126bd1622545b1389efca129fef2525f201d3b33e3d86b51513608d08e9d2897ed685296eb71697ce8bd18a4eb1da98f94e03417d4d815f3e0d83f6eb35aa7976aa9a08945cfaa21cca2f20184a434bdd1999405d83a6d9254f915cd6e47be0f587259342678d29987966501b3f3e89951fbcb2d83a90d90cbfd54daf3840b29c791e1833300c6402d5bc44db09620e750bb5eaf64320a768c3701904a1a09eb0a9ca34e8eca3d455314097895a86967e8b3b701a859843b4404f76900ba411bba07f33a2b8798bc15b0340c4dd3086bcef9189abe8891e338c462a1673e940880ba2dddf9daa3851bb85262b4c06efef9aee82198592f24dcd25111f07512b05d27ba4f8822e3ce4d1fffabe84f75fc5de1756e7a0ccd0146f42c824925a47343ff86e8ca65c793725f18adf1d7226852ed156702715bdb6470ace08869a07a9c085a605139af7f98012bb94f2d0d5f27ce0436ba8e3dd3205d711b3140e38434e8649e28f0e8c38831f20813ab5309ebb50a6e1b45b6807a0753697881180c189dd15751974f0b581f631e15e7bf38427305ba7002fb79fe912298e4129203c047d2b7033f8def1158a77b355d87245f8fcea097252cdfe7eeffbb84d58e4785cc4fcbada26ecb44bcc5d51b626a9b0094a37aa4ce32ff2c5f2ad5d56764670cf40894db010360d32b898912a4d541a71c42b6903a8d370b17e7ca12913a3f9a06ff930681d54b718213fde900c5f871071f92e4b96f6a9fe76f9f6630e56c01086e3e0e3d1365f65f9fc99287cb855092a8e061af0719106ca03dc0232e491803a89f2ac1c8d0f40308bfd125e70099754b5f0685b8461987913c4ec9d1844eff61c7c2a96e0aa4143998dcd132d0adb0a3a440e60a1ad40e44efffb01601fbcdeb532cb48d71d66e0706d064820c4b2218567863272a3268dbeb3888143d94ee6ffc5ad648456205bce5aee57ca39dae8fd48003423380a83b2508658281534596e045c08900a7676c42c6a556b08338b8a9511225de887410f61b0b49e3c6d6a987d92ecdeb04160f6a1aff25b62cdf2fd9fe91579d65e36d19b3fcd3b641a907b20e7026c686a0a71776f0e105dc13e927e2396d725422b3a29b6e21147246194befcdabf90dddc51acbfbcc889bf02f53fc434bc0820b8511211fe5c5d8d1b2afc82bae611dc830a09526baccdaa7b0d274cce381ae1f4f245d356b596e74719d7aded4473105a34b9353483be76db5bd2897b091d20d98cc9d9c227fda2b0862fd23d2db863ad6011980e89ce7aaa0395dd4643a7bc600e054db8f9ea98c6529210b9097731cd8843c1166dc4bf4470e625150718b38eba91dd4e335d095658dc13a7480186b8760c98ed78d6037f8383abb8b2c39fde64cb2d2318ffc8c8c8c9257043056cd9865381f8c59594843dcd916021c9740787636e0275c015278044e92e5f3fa4ae2e710d66a382461ccbbb817faadc2e706c3be9117fe2602a7f840723b9f419ca809e71157ef7e0a7136b5f8308a07c4663f59f64bf075fe0f5ba60b861733820aaed563ef935a4d1c3cb473ba3243553c7bc588a6b3cc6a3275186b39a24b1c9fd3723ff9b5a0b20b208e99b915888579cef5eead5e4da33f1b26e826fddd5adcad7128352b1697fe3df7097b3dd5992b4e6552d9a979091fe84b7f2bdb2331db362afdebce4985fa14470ea29f00df639d19f8372dc0d3b298c7512b1677815e2096a5d05d4df9672bb13b96dda81e2033f2a9d14eb8820e88610bda15b2a9e1d1be360939b0747ca10ceb725d46bc83c04c523103ddccbd04d81b9e68829d04d70851a2f83c2f2dac16e04f29b0254d93bfd93bd79be4922075a1c338bb16e2d326353f0fb90915da7adcd8238abff15b9657706b6a110ce66f0b41c41eb140716f279764813bea80c11b56908c8f2d05f274a26b1e5a9a2c16ee130a832a7cfe4d7fb56a522e905a25c18f2c4e46f3d259fd8758d71d8f81c771ca906381a00873fad7126e9fa51e6bebe22b6c6a59f0e040323e3f7858b40e2a587dffbe3b944d50beabde1f77977126c37e42952a3929442941d82dda8050a03541ab980e516c55382556ed0157c462112a74a0d52d184a2f3a3ad21c29ddc2ddf4e1fa088d60a10ea4a912d52065457dd4e9aa3bc0eaee8f9c59b52bb1e75b37f0d16d7b993c0d26a1c4b3198c3d94dbb91a3cfb672f5c830796161422422900103afe34379d159b35c1efc11e6ed54a122b0278bbe532a5a4ed269dfbbd2b8fd489047066417775e521210bb260dd2c2c6fba9f11762ecc0c3e7c0f80f8aa9418b0f1b9bcbbb4e0289b57a606cc10cc23b46c1bf1783513ad73c2d97e809bac4d00e341b296df1405b2a84b9bf09885e0b5277c40e8ecb3f20ab23dd240b60a641b893f298466c8513ca7a7f7e17e4a63096ca28604c55febffe6324473a9788a1475723b0172ff81ab0ad220d4714749ac844e4383e177525156338736881d83fa76a56263ce655dce8408beb78f63d2832f80a1c5c5c2f00db5dd03745ae10604037e5bc3b23586ee8553636599e743d28a33ac8ecc03a071af5cfb35de8aed732134395bfa6264d97a2fd418b15f139a955baa38b42fca0c27ce158b19feb308995d2610d752aa603e582b8d80cd65545eb90e69813694edc5c96c6e0698bd57169fc0508772628e31d1f73451d2112df135e093f8e46439d6bdf5421080c1424e7963353ea1d6dd882ca51179b6a05064b5b51681d5d349bb27eb4571d12aba2257594bd8f0a9d894f08d344b8d2a24a4a69c2a6b716074381d4c715a18969f819b0627f3626d0e330db9165b952e6fd644107a7fd8d422b75f7df9ed67f5035485ca617c482d514fedfe72da520ccce30651851412baf11f83c6670e9935d1f4d2f563a3896a6bac0c5171206dc4a15c66801c8e546fe11f56009cda2d2b4553947c082800af5ca23a7f6c162777511be088a4921c003da18bcc3c5977e44caab915a9a1009351d7b9ad43fa58b6dd17153952ad4d14911d248e9e6a383d2cf2c3cd584d188edd097b8ab5f985709e79864965f7f28e7033354e11e851829fb69c06d460ad2b0618b30cbb2893c1915ac3fc5210ce91ae004f0628f18307559037272453bf4a86b7e698e6a7cabbf2fd47d111253ef061182b5b7a598de0303c6a6a56a750ac56b03558688ef65495a6652fc3839a65139cc71c8c428f279cb5109181f3b888483d76c944ffd18640a5a748cd601e36831344ded045791c6457e5be7b0175f4b94d21e2b93100da21e43c5f9c807e98ca7555d6cecadcd5d7511f0fc30e60b4029fb416f8ce3aa69095ec1ca996ab0f432e8bd6c988c078953fa19c2e9b30d5d942e6518d7779d5e42929bbf4cbb985b923086928fb2577d1ac2aed47834770e4286632edf825c7f1a4995f84abdfec43c1a16c7b2370a62e33871e018a1dfe91c2410bdf28419ad05c8e0cef4a1ec91cc19c53fcc2bedc5e8fc5eb196c5d5a83c14b0f3163553499510150f7c73f0778646f046a6507774c32b70e5c921c448aa24f8188940bc7bbc3111590b9200aa969ffbffb67e81f61c2037e25b4b55ff2927af8e21ff380382ad309881afdf57a02575a240ad3116af3ce7af927f256d51552831356e650f93ffe177f4dfa6790f2ebde9fd60634942c606c78a233696d33fe481ec1e688051d45e6c708ea24ee2a30fdb3a70ff3eb6e7da9ba1110f07b9ad929f22904ba8b6157bf476be0e6012afc6edeccc80f0111b5099d123431a39637be9478300f62f1a3652262d588e610753a9b386d5073114f2c75a03609ef1d77c8c6b428081cd39ddd3385329b358179237d13ab2f2f76a4b4d05a7cd9c5d39774cac0e35e36badd0baac2a011a18e18e473da38c7c21980185e39432ac11d930beda0068fdacb35f06fee7d8c239bff62552c3923c02f2f029cbd682b7e8341f772efe0c12056eefa017fabfecefffd942ad144ccf51f753a99995dbeab1fef220bd34340fd83e6f1f7e696d2166ec24440d9561b18a91f76d4fdc0329aad13e685267c4066b153f3c02255f0d0a5803d3d6133440246a56f092b9a9831b25b213bd426cbe20353616b6a8cb3ec4351cf176613365c29d74fba8ff53129a81113ced1ac7a9e1f2ce08a163837194c70fb4487d8a6f27f22bd2ef43ce7dd56d2316ff719b2ad6c30f928cc1343e53eff34db527a41b1c8e64e99cfedd9e9b56476fd2bc8f924c2bd80fb860cb43d12fc7f961e5058a792aa3eb4be472c23c23cefd8bd8bce633321d9ec9c9dbb3bf151e3d4528da096ddce403ffe32d4c9d71d6b465feef1e2e1d75da70359513f16c95480cb64e3fa15f8f91278fda44e9e60f8c5242a84e4cb13144480955a28c8c69472aa71aef9a502f8f6d8d27ba928fc1ccf7f7bfc0405b233aa337620fc4f6760de018510e5bd58208b59f846c0a6418d05ca47f17e9cd609ff63efc2305065d7bbc4c31e5000aca1c915398b211f2e260adbb80a231184d94508a0e97404bc228f38ba2a5bf6788519912b06eddfe5ee325a800ab2cbffe338f4107d663f5b4c2f02036c6a782c7389f91b199cb5a28ea28dbe121cd022ac2cfb7b2a8dca633220cc7b5964c91f6e25b82373da1431a1091489f6e6f372f200211c86c4c5c5c29d7e2bc017379ea7d2c49170f30b466f7dbef2c7bac77af5f099a518c4eea7b204746c14dfdd7a288e92a7e13b63e2677038470c45de6b3015f725e3eaffbf8e1a0061c59f15b720b180fccc817784f58370dd0d8916359dd9868f8523c9372318a1bc7cc5d1a63a60d1c7108a0933d901ec4a8acffe79a5cd1cf8334846f9f9b2284a815e9be0200ebec58ec0104422810f33a23121e5344a603d87c5012d40c1e59243431d57c6583e39d6e0536ee92c4e3e7c289755ab13c84271efe74fb5358d1cf6202cb1ca6ff206fe0002c8445d9dc1e2b306543776a61a70fc3936d72ecc69ae4310122f94a939b3512f427f1774f5c90445c15aad436e7d5096e99e674418ed6e98b7e0885b4a7318c88523821e5fe8a22348420cc3167f0a7c3689fb7fb889a602eeba42fb19db0e28302cd086389b2052f769e8a76dd417029bd976711097c686cd587982259b9db509a1bcae272c806f7349abc70746934ee5328f25583860948afb098641ab6328d7a63d4bb40508c63af89228c06a69d8018bdc9f00d4b256cd26b06de55ac39ce6a82384fb410bc3a3bb151c82baa607703eba5394b97b82954284df5a3294e9e7e5287dc7096b510a009332f8899001508c3160166ac5e41cffc1a0d10144f24e92beae5178bbcb75e4184c0ae90e0176d544abb14afac751caa5d2588d97719f9b1e694e245957a404321cf18b4c8dc9b66083ab3408b8fa07480c25e75d5e0c5bd4429bf17740978b3bea30100dcff1fdb0e173a1ce5155045699ff08119ff6349c69177c5067b4422aee0932d85b0ae60422bb8ea9e423d5f8245bb304a79648571a5c5e2011a2092f7298e6845e311dc6590377bc562b7b82adb7ee2e4047304f27b7a723af3a0e90fe8d5f039fb2b731ac0f4c3c457f370954e620e994c7f8cbf5262e7eccca5de199ba3817912f4aa7ae1e067981e7c4ad81f2cb3a644e367a43278b09e923106efab35b9af5811697a5eb4799a58e2c064448c6a8435d23fc65e49831f3cb8159431cc55be89201cf51b7459f44cc25a1cca1319ad75786db0caaac92ca2cc9b647fb0f0b3058e946763ed7aa2822f6463f11433ce16b5158940ed1bc65f98dea47dd75b63119d4b2ea7d4df67cc160b304a44d079bd8e45612aef6c435292b32ca15dfaebe06173e67c7b41e4829fe63ac05c11732172fda5bde6960e0d9a3fc9845fcf8d405cb7b1d37a928f0329a7ea1d70333973eda8b5572da2bde8172324c62eb553580b0c75f2341aa83d672831fa3ccad0b2f9b513681cc72ff75f8f5f4d8777590f51f6fc0c76badd80c664e35d0f64fc3f6c461bf0dedc9d802f2eb73513c38dae582bd716872e9d5f2866cdecf628adb30c3e7432ec36be6c70fdb4df2b5c7a954d001e913dfa7382abc451837bbc2680185b6a76920de227f2be8d5ce5ccabdfc57aff50084010655c64a8c6d94ab199bb45b9e13fb33970fe6dbfd2cf34f3da8713cf2663f4b7796e0a02558106f4321a39d5ddfe42c9ac5fceb909ea33f870169700057704e005ea59ee7c3f3987ca74c85dba3ef9f78a6e752df0d9b0c5b26ece3fc2c1303ecf01021a1fedb5c25f9b6e0ee810675c625dfdb5304977deb26d401cdd0a15211235f0946aa8e3ea1fb8296b98a1a1aa62d2460598d96f87a4bbd29707497b0d4a3ce891e6f3ef5b5f5d627c1bf37106c3ba0e4fbef9ac93bd4a1d1263ad37e5e6b341ab92daba0c840741567a1e8aaecb3a30961e2aa6ff24a375f33215190840837d6f1a879a71ccaa187954e6f4965673890e1a49b7b3a5148a36447eebf8dbd302b1f5e54869676ac174af1f17967b4374010347e31fd9a0b33de35f2906ac3e9af21656b3363ed7e07d7589f166e3f7922c9acd47bcc603f9eb6b0f7217d9df23dd59451f49b6de9b18536baa3ecb2cea8eab09e589be833b308390f09d4959445aad5971793aa7b721060cd47f40b2384cef1226ac8b6354f5804a0c77c946c41684199cc05afec6c9b3d6258c0a893cb83863fb7f5e848bae93baa31b2af8af538b25e2a74270e1f1ed9def763ac8b6ceb6702c8f7653e3a8296885f6864ef8b575e7c028cd14eba96146e85fd4523c8dfe8ee3705c3bd858e454b2f9f2a7360b628a0375a094614c4a0871433db1ffca5de7965b16c9af62e0e089891309a664edd81316d815cdc145df9e80457b3ea205cd656c2b244b4e000e45207f8b2c702b33213624862e92ff447df3563b4b8b3e6085a0bc5c1eb461d005583f9adb486e648c155e74ad9bd7d525af5995ea01b9476a0188471c9b59d101aaabeec00ce5ac54c861d5dcaa1cac7f300bdb964f89dfe49846073089fbe91b50c6194a98640406817be8f55261f7654e230dc9d3f4ed626ac32542c7b8316f5d488d3f4f14558df9987e1cf8663b6f2e2ec2180fa1404bc2895f04a10bb43a10808532aee42c45bb885b03ea6b5011d9d766c0891f4059322d50d660b4daa89d49d3f4abc87e6d6712084f2e38bc412d70c1a4bed0bc618d1b667afda510a89e741af9026d2140f852ebc4830fc455331a92f1b728077138007c298c6c9c94af079835f96b1c8ac4118ed597e7e8610c63e59cf01b919d98ce0f60134171221706d1733ec449a24ce58e63cd4604857710415ff19ddf0292d8d635fe2c6f7e3ee51d48939c76cfb79658623a2d56c7682556661d1e411f4d9e16b0e396e79011c5881423fd5c673611344d3e13e2576e765ff0ef8eba1027fa33a63043b2ec6f7c655646d386b27a59201a908fa361644994b2778c56e196b2dc80816dcadaf1f26d1f6cf6a3c2ea9731332e3fda0fb55c47227bbe97d551697c2a8596b9bc15d8df54e3e3393986743d2b64f4426a6eec3bdaff83e5c8e57739d401bf2dedce296c4ba089d4f83034e3fc97a198ae62c1c83724f4cac58b5fe1e57607b218a6d51d8e980dc30d4b06bb94a8ce4a309fd995c423137453016777dda588844c7daec20d600b2f0bb4783f8a58ff37845c0e0da958f53812f5a19431dc80ada2fa244febbb93e0a0317f904b9917d594f16d4832cf1d36ae72edc70a7177e68c8d45be1448fa0aac7d53284da693d9546448fb9fc8d86539a9b43191679b6aa9e3425d5f366a17ae63cf5246e699a15013913174013e657d2bfa64e0194c94371e21e499d0e7a17491513bd255cdae6a4b3aaf9c503aecb099f76e47906128c1ae286539aa1e383f520759fe8b507c69a2817fb803fdc5308fd38d17fde3e4aadd2d02394e54deeb434e981e981708180894af274006efc79baa0f1eb988303623af8b6c7c3529eee506e2f60c34339e29edd83551f78d3f8a94a6f3f6cf7702c4bf7150ca45dc2769e8359f7e54a87e75ff5e7ecfc6937f02b1352912bb3a75b07646089a01cb1ada9bff4a8a7cbce50495365746914938de43ce40df78d6c9a8ea7b6c56cf68ea0f107666d7977d97f58e7b49ea0d8510fb01c53f2e0883a45c7f1bb48b5227233859fc342b562d0c9e017e4171f4f990cb84ae8183ba071b9be6155c540f409c4652d31764896be1fc60173a1506912a16ed55f2053677529761a6552fc3fd2750645ee9f9c1cbc07d1ff2ad47c9d76cb411e52950c8b3e48b5bbcfdd45a4b4c3603c86cbcf4777f092d8456cd24781ee7b76141a7a5f9816c8e471502502766331709ca89453d9d7c647c7c25870b79d86a850a356daa341c95569d7a7829e9d841954b5a2933302f5a1aec5b1e505c735e29deb228a41e7139f80bd9a5a06904a0a2150e411dd8f7b277cc25f26724ab15bb2e1695695f0466760569463856f9b5581dfdc3cac46a1a680c2224bcd9679ab3fc26e41ed5f9a9ec00f1c38a754b6975b58a4671cb17b31cde36469232be39e716d8e516292584415a8169dfe1a139d7c7b443b4c19e953275f71d0808b21da44b14c997c8c26dda8234693139a34237c036c41030abbd380664b9015c23c13052146963c1ec209aaf3df54ccacadbeb536e73bd272ead969ef53c1c0669f8f97b41ddc030d23af660ba9cdf40fba3ff4fee588541dcab63fe4528f3cd9c7cdbf0cb171103ea92516159a11a426f2c35f5ba9e0e6e7b95e7bbf0e80d69833468b062b8696a380cd96fe9e825d1abdbe04adf7aa49d03b6ed4b3134e494d0022a48b205ec3bfbe80e0167d4f28b3a9af1b7ca5fe5daef1343edee89e1419a5a15d6842b0d0e8f5bbe0280e6eb420028bf80bc396012361aa18283882dba30e3d31e0dbc2f3aee7cbc63619657beb2d6f606a1205ff069f5944ee075684ee78e6fa239158ec93e574c00303901efbb89014b66cf755b717dc97304eccbf61fdcf849146750169b326aa342c078c52c5fca30c8cab8642918a453c0b3131f072f57cf030044830e1cb05f3e1754127aec31155be62dba239dd8acfd218eed046b6c7e8b730eff745cd9a91f6f3efd798c9a017a3302819153d394711b740da18950ae6deafe6d5271269e6485e7dcd5ff8b0e9c0bbc6452f868e7bc36d157123c6bc30a92d79a4541190fbb1f2f3a93e936070131e06d78f6f9630a63968809dc0bc0f8a63394438148da2c3cff385f1c3146f13672414d0888d6cd6e78fd384cd366b88233c1ab551917df64a43f9d533d7a7431b7d0e2c6b2ce18a25e7cf9fed4a4db79f4977923832bb222f6261ee4b37b733bef30f18f58d64c2989aeaf32c618baafc0f3fa5e6cf9a69f4676dd5dffb1035a48a34cc824cea29265c89b320025bf5e90dd1f8623497815d48faf5410beef9419856f9b4de99db63748b438294f331d26d7ac4cdd2e70fd5ddbd6b6b77bddc89bd61a7347cb74f8d06205ac7f8a43ade1f7b506cdf095355bf0e0368b83f82182bc2220100737ad1d1748f83df27e35f6c0a5500641b28c0ce953ac0972ed45652a12a7fd4d6577247126a56f1ec00a11874ed580f3c0b43b8b87dfb6a53e94a018765e685e2fe4b95525dbe9c121a006cd1295c063550ae9015383ab0b9e59dfb170b6768f89c4bbcd372ae866cda6646bd66e86fdd0045fb98dba0762eb8c7a687a550ed8167430e8cce6f3c1338e00d841ae449b1e6728372b525c43729750c83c404b6adf61bde2cecf2ecee863d0936ad0a3df61a322c1fd840a5e2761234033f2d8ae01c40b64d6122cdec28a864958e007522326c14c4a96c203485a2bf9ca347ac7386f015a20ffbfb87a7c30114b813e339a6c275cc0a01d7d771c00bcc69ea178754ff90b19522de6574af3d9575134d6baf34e7ac4a4cbbe4b88a9a39a1c90df37c4ad75734fccccd5c865926a87ae2f98a0133a02a716d8be849e741e37d81373fd846d47962468a515af689928cac866d96278ce189aaf40dd95d768d82340477a339d2516445daa8c30de2796bde548cf212ea06cb53abe29ccbb817cd18147e10b99b2e39a489193f2c7096ce7cd6a4c2600b5f6597ed28e4d61328c8478a9ac8a40dc84fd491547dc72f83189b7a9a50d8c88ec172a5a19afc195de790c7846b517fdd99e9c2ef160411b3a27c9b32ea893ff2fc78a53e105e1a7599e8ccb0cd2a4ba7bd1e8429f812f1c7392b8d79431a1f3127f78aebc1daa8951b6f3c9247a9f6023055520b301ded9f8b3dec31bc389451f35032f0ed274ff5543709dda4eb2170c567f6514bd278ef8ce12d1a3fa7b410167184e76f033f3fe118e771de2327570fde39936a28db0b8740bdb1a00d20765ff65c5cba1ce13a410bde982a33aa186d99036fd8af60964c29d81beb4650fb946087b032b6e636c0917f76365dcb7ca92942934da4ad7574468801f0d21c93cdbf78648e6be8bc9347217b78dbb0277192bf9bf88de1a2e6aa6146aed44ec6c1e5b51f65b413e39bcc26be9deb02dfb68538d3b72c615bdd5a1124e5be0d5404bfb790b35532cde77997568e43b434907034dcf67df178ebe672f7fde44c0436fdfc1aa6849466273a1907d269204abb82a7b740d9904434fe39ab255f34322a07a7aceeb7767a5987b7ca812c62b0ca7be231db6d2fc7733b531435da5c40f268f81053226cd18c2c07b500e6573d48682b83b2d231e67db5d8bb8d62c788e63b4c4a86bbfc55b19293852603a4c301a9dc134acb8dc5e848251b894ca7bdcd62a13c548a591a8c7411d26f46ea1ebfbe9d2b13302e66187be23dbbc52b9d9639f216bb3223110d7c8b25a2a769e9a2ad7813e269e19cf82cd69980af979617b9cd9c23e21912903da137f1c7cfbb4524b071efba69ac2e5a5474da937b514bd6c73c130743f751f06081fd67e16d3fadfe25c6479d222edfedbc10c0d727e5ea4128c57c8dabc11fe0efddab0fc1ae3422c33fad0a01cb1a49bab454fd4ec40d00942a34e5f2175b4252ead4c724cb4b5b4f15dbfd17f263ee229fcc6e007dc196af3f101126d512c3387f87541c37ef67b6353c4b319d890ea7e08eec8ba299ad0ad118c21ff772890836514916e006a0cb68eb236bd7222eb89b0f96d5a87d17c19e5483d94dc43abce1f87315256cba2a398df75df6a79c1c54a02c0a7c15dec7122c70cb6733c532e02495f7842aa858898dee72a8aa8f2730b8ad915c6552bec0b189e3d10a2355739eca4d52f0916b96cafad63c2ba29d0d65bc14654a8264f22c9aabe88216fc1cb85826e540a5170dd723e1e58a52cbd8217a7a1fc76f0f09b6b51f384561d142c66cac9729f0678b6657dba4c69286a768ad74bbf46ee6164e6e28df6efd445cb4897a02bec7b71a415007903d799a87cce321cf1df2a4328de371af7b233351c6f64410d170ba38391cf3afd6339b79d55154f7c9a0461a0e5938b60cb75ce8c96c35e0ba677f8a50114c4e3d1b75250e199827d9a7e874420582ec0d07b708f5b9d67483f1d7c3be26371a02c4ce7d52957e1a888d33dabd77692da05f86dd1c6ef1072f96e43ee3683d4240412836a9b1b132c27ec07611ff8edf033f97b9e237b0f7a33d50847ffff02fd2319b58d1cefe511d3b890d56070195cc67b9928520f9619fe6f0ca2ea9ef2b4df61123265741e527ee29f7801196fd7030acaa53ca291e5c1e02ef5a0f3ae6b0f88dc4e89383f8251895f9711160dd19a21e89a7547ccfb0fec334917389ca69c9f716518771ae2e5491ca47c75015c3360012fa8390594e584214a9f81560b070e11ef643a075c14fd77444174dc27f442e2e208a755c9ed85bc43f3dc008d22ab88ed9063e4e6d90448ba513b95858561470455b4892ef31b9a5770e96559685f65c288aa8f2cc7674e064a81c8ca08f0f7198f3d6be0092d8e084471411c85dc3c9c1b21e64bbea575e846230ea321b09e5c7da89e22b48366359d1df800136c9ceabce4f0371ba1b25f1672d1835787762a81212c2f9abf5a7542bf3dd8519a9d905c05edbe77d7a7ac3d4c4fcd74a0c68cc86ff4fce05beb02b918784b23332ef3605adbb6171cd1f0ee005cc0e59ea8098a5badc84837428606df50d994b3e5621b24a19c1dfd21783d74654f4f1bc310d358f1d3e13beadec64e3c22f42ecc8f766defc315a463102186d835021ad20e7a4b376913999d594099575ee1ce9ff33583522ee319f535507d629edb32f4865d5ab397e820c61e4c6cb144a0fa7e88c49d09416193a18dcd07979574559608432237e5ccb0a3cc598509e8277bc414d76a324aea7535042ec64389b6ed1140c2ebe5fac75dd2188e23e8fe8ad90f5fabd0f62de721e602e716f1be5f4696b8d67b1852e505b1a72c4ec58348b6c7817a1c66c61f36b18104768a31344412a3c4fadfb0a6a3ee6e56eef23f2fc799676c57c5fc018bc4caa5fe2502a3b489800d049dbe21b41da7047eba7156c3626d873c08d4318d2d164ba0c80bc81d3243c5c87daa071e2a2abda153462bd4c7c605d8d4966204e26e470783af856c10bb4d02032fc9db8f1ea53f4f8a8c97093318cd7ac864693774926430855344841f604e8e1c54cfa76bb702c06c8c5b1312e1a926e4affb3237a6de238d1c391251be8c4f79cfc89e9872ab213c83314e7ef7131bb707747a663a08bad44690442f495cd14fc307e51ff4a75f60b850032905a55267705fa23c3081d67031f710dde288553655248308d519dc6b4504390dd89b17f073d8041cc529c7965dfdd347ef8f4155e749f9f8210eae7413516a1100a85fdba766011a045aef4a2f1f3875c9c89e09af7acca042a2239f50c0934a42951842f5979fb76e07eab1c201a10eb47275b0843042d9f331a276fd7e085a08450a25f284eb4a4160f6e4852ecddc57785004cd2122767eceaf9f83862f2716934b5861d9d1f8492ba7edb0a05a996e8cf95fb7c06537524f1795cd61c642bfd9d03fc2c4eadbbd7ab136a34b1a7e6dde2913adfbdcc63b5e154def1c694ac40f7ca196cacc22ca23b18eef385ccbd4ee0de28bd1ac78abb450c6a0390fbee387db63746bc178718a4cf60cce4640c706db6173616bcd83c848b226270173e224172284980ab5925f76027cd6682fd266e3d2bcd6a2bb57753572afd7c8c8da92d94662f852ccf7fd667dc23b84197a61b4b087d7f50413ab0323e173297f449e0eb76a0ad406f497b57bd0d6a9af93602ba51910dfbdcf8cf71406ffca6087aa97fcfd4e15875e59095439bd3a02b5fb1fa7a4510515d9f93d4ce3280c72d7420c51d8ff1ac021a29f0af1b75c4061a8ee95b2d090b4ef6bd579d12f9b495335d1c15f42c77f6930cd68f348356560c14ad603f696d1672772ed8fd984b439107bae355f7ac8d9e3b20b80e872393aa088a3ef2d045118a0a2210a07301c12229d76e686434f6c87673632ae931680c8240e5964543f5f7db7586d75a7f78e8a208456c405842ac667be2bd4ae27e7f70904f09edba3d936f311ac4ffbb6ba1b0943a6eb8a46320ae66cd5cc62c627393e59210ac8cb739a4298732f90ee20bd9a9bad00bf14d68c96f565ca62b18832d13d08801ba6d95da52e56d1336bdc39c87e128d84a1df0325b035f086997048b2fec79dd271edce0c07033c17e4059a86f1c054c5e0bc33265026f9b9a2e8d4a6321feea8332e0a8c0455c12b3e4cc21883086ab86db9a311dc2520deca68994482ff12e1faead46569926cd2a9bff1631833dd53c49bb7a0a8cd8ccb81a57fceb2ddb3763b7ba8992247d1795751aa219d200c641b3ab350e03b5f1e5a044816073cc4bbe8b79fddfe3207fdd0acccb24eff3b0c4771a34c480bcdc4d87e3b2baced9b89f59083293918fc14d75c049368486e9e035193c5a3b90b339e8b9a33f87a1c48f7f642bd5934d1c49889e9aa55bd46f09f1540cc68d9981e17f076610cec0dcd1770714271c09bd720454aceda4d51a3ea1042a0fe91cea0851d36ec888b7c33a40e1a7e18d356a4953aa3ab5ae6a23246701a42a41792a01e442bd9c44aa328089d48b02c9230f924ed47d30efb5aa5adebda889234c955895714820b1ebcd5dc29674f58ccc74614fafde12708c0e04bf9919c69413fb4e9062a8e69caac937c09e5c4345e6f53167c4ace8f56d0485c0451a7d9bbc5255f5fdd005ce5bf062fa967ff305dd287ef56cc966055dc840d19eb11046c65b8b5ef9ed8d625933f0d619b38cf5b2791800f26c81b0d9df414691b4bf286e3c7fc8078d598e790f8ede22a35a66966847ba728dc5e1633c340da7f4bb5f76910f1201c39084d01ddca78c1c86415874c675dde890bed30782d811882ff5574a9f2feab062179bbefe0cdc9d562e85086f54d5161ee320e54d82b418a605479e33129cd4efefe8ee3045968a812f6ec30b8e58df3b3aae725d5f6df1bdb47092c56a5bedc83cbd38c5895d824d2bf19696d07d274ad573653077c3d7ad3d62f8331e79f7dfbaafd55af420fb73180cbdcadf898b1e786fad8d87cb67e304ff5c2d6fe549f4656b6c2b5ffb5b6e784592dbbc166260b330c1ebf51b0d6e164838e8b5385c73b54b4d96577123a4b177ff9cc3205223f33f46cc601b18a0ab69d0130647d29745682a9637336ecd9a6eec8d98afea7163ddb0aa4a8e70cf3b949523e0c5bce5a79cdf65898996f3289ef9d299077e8512446c30bb4c698b52037ce2013f6146861473f600b759db576940c9fed516e8fce7abb76a14e2033e91f51792014b2845cc5ec80734a134319b421a9084d2c696a189753270f8503c522c8985267329d2d61505f9343e372ccc7c316f820f446913f423969fd79949da5020f51a7f69311ebcf43b8667dc53b738e6e5e0a2d53512646386a6549c152ef4fc1f0e858645f75823a0428374d7b15a460c8678b2c71ffe92b7878556cc68cff2722d94712515a77cb3e1cf6e41d2e3102d96d7da0937411bc01c4d7798270dfc9eb7aa4077fc6f3f578235a52d0c8ae86ad1ce0457ce600a2cc303ba92c6865a2094aa710e392e36aa27a35b8535dc60d64c5f6d820d5d21de671df986511ae59f7ac0d7a5067d29afe88c290614608c113031003a3037bd7c45014cce4d1d05a1b881705dcda730408e3a3bb32ada5e7a6969932449a44c52065d085008600854242dd16665b2ad7513a5661652b25f51b5bb6f9fb427efeddba7b127f0edd7e079ed4d113dd9d2e2fd96a43fd113752772f53352fdeee04169ad9c2851519b8ad2010b91590d3a43604268c907a5d68cbbff6ecfd3a2bf6d1f8ab3eb09b038a356282b272c4f0ed893254b16d64a898a4938f341e1b880899224fb068c01319132c44db5a9a88ae4f311826d81868d0e58eae995eaa90391d995ee8504175c69e20a911a74641c115256c3902a99874b2b0869541922e4b5692f21331407bbf09032049399928f188d8868005fc8e08b98120ff2e5b6d4ea62c1177002b264c9b2b5bc60b7dfb61a1a8fa00c344b962c59f6762fae1ed511a28871450c1e23d56849cc3bbd983de5e024bf02430e14c6be97c310b5da545c711def69b138e926cc3ebbe3a4bf8ecc8a9baeb869c74d58dca48df6ca2ce6a4d5b9285412ade5e0a614ea0f363e20a84c10badba0a921dcccc1c3f637018b36f38ed7728436b995c9ad3c19191acb69e3260de5a68b24a5ddbc4a1842c7193aef38e9c59c0c439b79c7f476dc54b9959b38272c282d37716310baa3b8dc84e3a61c5c4567fbef6881c65a0ce1b2a76eb43127f9df3163978db9de8b9920ec8e17e5a47b310ae3df838f5d28147659b1e2a48b119af2409b9e59bd98e98a366d2c897631429b7575a34d2f66639eac965ecc8b7da9eddf8d954fc93e42d31d9bb3d6a2bcf3dae8421afafece7699cc49ab59cd967cb8697b2d265ad90db4f63a0fc4b5d1ba8c74d2673b3199b5e2a66d1c957cd8989bb28e9b46756677ae8d9be88e619163712bcec90f5605bef779a5592d9b63613b2e4934b74d7ac5c5085d352d89aedba4572e0865fb6b9a7635ae251aa1efc8b19cdcc270ac295272abef4665a4f43cb1133fd4a87ef846cad4a8d63aee78324bf2ce9b6def5ea0f16296e4f8d50585718c5d6f7ab1f29bd026b7c25eec888ead38969bb61abaee6cd38bf9832f37d519a8b2a7eab224fb3939d69a5eccf462d6a5086ddff462db77c61d68ed5d92e86d9bf4ca101a0b56a0fb2cb44973681879a0fdb91678e0561ca03049c4bc993d89608e1cccc0850221dc10a3f4f776ecc9e4011249d4c0066fe49ca04405a9dba6610de3b18bc554e2cafe278a41055f00c97ef740e9577f38ca5a8cb18dc1f400d521a27d0788501d229a1d3d407576fd3a6e76a3e20d2138098349185112b022c9ffbca2afba57a512498a4479c5b2a306be007ef4d317dc1f48efa5f77aff85f5d3b7de5037485219af244a6ab904a1f1a66068d359a7aa43ed48290c3ed5952539f71ecb4b4b624a2c90a417653673e0bfe580fd7e654f9ec395379a222c75b584369dc9f6af58ee2a673f2d16b1ce2cc98a932b0ab3c41231b6bf5932eb2a25a5a2ea15a229b6bff51759faf4504838d71e1d86a11e434dc564e584e52494d66a157a888d1354272cf1c0ae07664ff77a601e0fcc53a56a9ae6b7b6b86d5e1a1e6a79df7a6214c66d79470f0c0a4d9df4c03cb0ed1e9807a64ab9acd8fe22d35631ef2cd6921369a9f78d96d2ee9fe90e26b47b93fcdb6b9beac0c916b4d65bebbd177bac8054a025b1582c168bc556d66563f6148b51200ea4e45c7534452e8e867014074fcafc464aef7e55ac1450a4ccca2c521c3c291d84211673073f27b5bd75e33197792ba6c568e9263834feeec1372b6c8b022042770f3e11eda44944b4eb681ad915e6e448b44d97ed72a41347d8b31f101a4633e8f77c0540e2efe0419b9f013fc9dc14862158419058127720d1660984459bde02c5f1194798c6a347cf08be094ab38234e168e38d23fccdd0bdf743c0ffbcee034203b763deb2a77a73d3d2f541b1e67c75e63794e4bf737323476d79ccc3f0588cc2b4cad04850771cea36e9ce8d0e14c6653ef318ddd19139e9b11c1dc4b155592676659dd896c766b87a93b97167672708088259b5a38abbcbb57297cb55efe85e979f5238b7a96ea742c6b9dd75c5b2966c1748a54a0db6596137bbee4820054aaa8812f8216632fd8dedef944a1533b6f9bd609bee45add5df98d2022d62b6bf47a4e50d6d56d78fa0365e8711d0535569ffaa1f8e6c2e37c3f5ae1b0ae32a252895d1685d82d62748d87634bb5d2ddeb65a3f25249c596470c2f6df70a80c68fb6f399b147a7256ab0b2b602249a224ff182b5808a9d0e6e6dafe9bcb5979c378c31bc61bc659b39b6b739d98ca28350ac2ebbc5164abe8e5d512e8c99b8292fc8ab6d54b7b658c5d227bc24e70140c45e4bdbc9707ab3fc6f0aab8e97e16fd8ee6de0bd402e18072ea8fedfd415340a91bd56ab3b6ff67c79e40e7f6ffc0ec498b59927f8e69d96776f371d993d7b2a427e80f51fd40f9b43e2c2ac3bd7e6d1741f1a1b67f0b63e8510cf8bf26e7c66fe4a3729286e3a46bfbf65e1e39843635252d7ba2b695a3b15c49ecfaa609dbb59b5dcd123e424f78094a65b8c72ecff8c42beae5003f0c7673235e893e68ef4565bc7013de1e1b69de4b8444952c4e9401a5892ca5bf27b32702dc208a39c65083871b304a7fef654f1bd051b1808d23676c1144e9efc1ec898231440eb8c051c112265a94fe5a8c097aea46acc5f218c3a7bda3d7a2a589cfd39e34978b361104eadac31f8515e82528c9f113dba770e12b5c78a5d266e9b5f25ea96d47efe5bd46a9ec202a6a4d81bedb6ffd5099fbf5397adabe7ea5270795fc63fcdf9fa4d9349086267b1ec61853984a35df8a8899718a443179d476bc30d45ab91b5815312db4d0428774e941e36d7edff28ff17f7fd2771de96b71bebcbcb83bc6be7a797979799142db6dbebcf0a0fed8b8a0a6fbe0c75630eb940d26d12d4d36953dd172856dd2170fe06a8f10b0a15a80a6fef8464a234029404df7a910c08d3fd338b60f411403bd8d2c977fcdf1af2ccf5f5eb48b5fc00f7f0213081f880bb127f0c35104da68b3b2b0766dc743f7eab878154422b718bf9031ce5150a141f1685086d0a608caf6d7726e2872eefa9e28456c7fce3b627b485092b7528213bdecc4d190cec7911e72ca4eec62a3215c17b324501c8d9d6c549f1ba925914c2fe5bd37763ba377763bafb5ec9bdd13daf4581eab0015855d47bbe22fd11fdad70fd153a7e90ffc2e4aa2db013cc8a1245a7b685acb49fe39772ead55df268f2c279d654f5dce2cd6c52107bd420f93b4fdbb9d2bbc14cc743bde89c510e4110df7c2dafeee25164390f7256bc98d2c8fa55f9f163a6df8884224c21b683f4b0184d53def9d1151273920a45a4ac998b2512ef6bd97e3369cdf5a6bdd5aeba23040664e9e965ab07683dd77a43758b0de5a6fce4c7cbc61844e59e44611a5e4bee50640802ce0003309d8f18536e96b48deb6bce16dc31b2712c9cca0329ffd36fd8fca6c4f4d107c33dcf4a73cf1fa27795019cfc4dabeb8a57e0b95a94f3e8f142885a12e50f300228cb3159f886d3ae50936f61547f6bb1dda95f3bab03e58ffb3a28e6b69f97147979616af32d4d1e503756c71320cfdbbe41fe3fffea43f0f50119a8ee2a9b58bb77bb77a6bbd1ecfdbd273f36ca89688b43de5ac75cebf901a3880b74965d66b0e804519acb2a6080a66a0caef8b80c6e8a27c52ed68adc8a8ccddf53c6367ccc6dc05d3ba6e94ed5084d430432dbfcf62deb5e5a63afaf69de77941bc0d77af891dae2a1c2a5371404fb887982aa68aa962aa188509d1409bf5b4e769efbddf4d2c16522da1e23297e9bdf4de5a39ee81389745d287d830d765babd5a6bf54626dd8b860bc3b3c10b7eb0445984e620086e0851e64c5d266cff05bca0838dbd07db5df05aadde915b6a8f053829c449f5c7a63d5c0ad801a4051a012204d41ff7ad365a1127aa3000714dbba93d5c40687004385ce54b3e8f86c2388d7dcd5e3454c6dd9dc69e5e9ce4ef03d484f6cf34987b0f87d4af570a6bbe6d9be7511b549c6f59c4665e38f102c76459d689d96c369bcdce3aabb3599dd559e53ecf03f1ea02035d35f0058c93a3e05cf2e185a1e78521f670e879a1e781337819f2df56f49d31f6bc307c2f0cc3300c4593484bde4adbfbaec64a3ebcf0f3f13cd0b3578f40c49899050861809343f2fd883438a9fa1b9b6a6d33a6be2cc93fcca2e568cf870f7e87e4f37ee34aec8cbe927c61458a1459a881064d430d22a268410517aa98874020d0bd20516b694f087e4e58515c38b399657dbc04d8533959df142c387bd32946a0c1aeff794e4508d736331521a0d8f5fd3d6a8e60dba7db24c1b6634ac7b4192ad54a654fa21b6d52570af507960195a142657638d1fe3554c66eb7410710c862b0d7dd210e7ac17d6f4cc99b41c984464dd55a6b8c0bf4473d6b8f3306ee895dbf9ef5c74bede1ef2ff58701680fff1fe2b751e0aa5478c04979a1b9769881ca939a62042cb6595b3bdcb8595f1566c267e0d8363f55adb5d67ada930f254aaa510cd5099d7da9c95b46b6261ad9140ca26d4d61bcdd4212aaaaaa2bf0c508baaa54b1300c1d35d0da533084a3b5dff096f3b66dfa1a1162859cb033fbb9afb416894852a3c1ee59a94492ffb3d968a66b0c909acac40a30d2286b8a7c33e0a2a4ee826959dbbfa60835e33584f249f745c82da20042f9047fcc5319b7a1ded39e409f6fb4eaaeb03d79fe3e0f213e3f1bedec85e522d96eb35dfbc44c3f7168124b871ef4356cab430d5d1f87c49a2743c2f06b42e158e3f9cfd784afdfb3d566fb9cf785c41ad05803fad038029f9635a11f81348cee587e3548edbe04d554558950a84cb551d0132e8292fc9f3c89228a6dd6949d45d9664df90becccce280c4e4261b0dc53b4334bba36a2dd62a34b60c307a808a8e9ce2a0f5f0c0d0dda7dc1a2fdadb5b310ebf34f6ce5df7fef9f100ae39ab6c2a3a0424cfdeebd77c3410058017062369b9d36cff26c664fd9da3ccb337c3a19d3a94261fc5d2d0a93294c389b85b3cd8513859af90caf50191aee8472d053080bd7406d0f5d307b0aafa024fff015ae2125b65d65495174a8da6e7228fb26870a6754a6e2d3490f83404f7825473de2f9015ba1308ea2302120b419cec2999b4cbc0aaf5cd97193b925f19c6e32316a6371531237edf841fb9f30459bf8bcb2fdb1159c634f6ed01f9e22680fb7273c8633ed2a6c13e7e49c399488436dffea492284c6361466b6fd3114b2550f98708208a2d9ca8c15ae12f3c744e06caf3fa60082e220a8a96a5d88b408d9603b46d9aab5288c47a99a56efbdf86d8965b35900581a07002e005811ae6a78da534b4bd812d6162a1a6fb3a5254412a2ea0f70fb87aa30654f9e0f37d2caf6ffcea03f6a94da43e7937d312aa3d52abe343621e809c72c69436d29963d793625b66f4898db4967a0bff73c9539424ffacded87ed9b101f2a414f7ac4b1cf88654b6c1f71f8c4f611c75169adb46e7f6ffe11156f3bd8240c471bfd3ee4327c0adee0c2ce6134442bc1a7bb0958f70ec5f07d2895e07f926c336425240be984a2d41fa133680f0fa551ab506d33747dc4f007ea82bf16431465c1ff8a618ac2f87bc4906549de8219a6805216cc3008336ced5088551c4acc4224647b2bbd310cb7330e6d86e1199e007071de4db153839b4da7d400056ead860708a592b72ab924f1b5b0fd63c0510712da3e599a694c8c5c232bceeffcbed39ebeef3b3fed3b3f1495f1b6ff87c44df6cf6ff5b176cc49e766dc6c937db4525a29b5df91effcce20741d4dad85face6df69da318c61175d2ef38aafff9ed10fab7f99da9effc509a8895609425712bd8fe38b3fb79617830d30b63fb9bdecc9b7957bc2a1ecc9b79617ce7959db11dff404f363ec494dba372995174266f323759218a30f111a87d5a927f9a4c93691ac61efeeec5e0bd39df798e5c3b4ea587d8a6546cbcf0b129159b253bdbed73d6fa867aa0f1d337c1842f34fecc715c10fc96764fc15a3b77b99e4952bdb5b722b65b8dd9d80791187749e1d5a73cf0ae1b869a65d38f560fa98795c28041ec6e7132a31942eff9212dfff996ffbc595b2940a14522b52900a1452b73f21bc951f588a35afff3f9d058a3e33f5fd3f29e375282c411f8a137526a71043ee88d949e0eb164da9918fa7b4f8708c4923c8523b48e6f79ed39eebbaedb64c0bf7d10fcdb1bd9396f36d7907bcbdd244e7ee31dcda01ff443f483748cfaed3804f4a1b1a665a40fc47a445a7e8638a9bf9146f484362f4cb673abc474ae952b6ecaa3b6372d89938ef136ebc971f6b41df921a6dd1ddb322c8ed42354663b426176a8a76d874af26d88213614541420d1f823428fb4ed4c21058eb233bb130395aa0a29c26d5ed576a2a1abe751b9d43fa3dfb7ea79d38fd8fe266ca716b7d3b39ddb55c5dce426f3c22eec56d9cecd663b2f4c55b771abdbb9a5b69beddc50b04f2da39e5ac60d6549fe177661a18703247ae3a3af0ff4b809609b8ef28c04d8a6a3f6e6449bb555b1686d36a0266c0535692d2a5b0df6444b7a636facdd72ce51ce7307e83c80d05aaf740b9571d75a7b13daec725aa4d0de4265428fdca43dd5721b3d338f8c043934b5a49725e57864e7b99b6c5f456e3bd800fb1e9d6d3b188367b390443f5922693e4216ab392edb930628c93f032a6dd223509c225bf6800504a1325013c6a161e0e0e7b8e79efbba5db507ce02b637622a279bb8573363c32d14a605b7ac1045932db464e2a425c998f6c45f8c311c78d3948056b8f695aa6a4d65fc5e8e033dd1cfddc736d8158a2a83ed6665a23a412d8c067bd29fb51eab2726537bba80159d2a1586abb3aaaaaa8a8a4422914ae5a15e5cac8408c9c9114265424dd384f4a09de82a0e20087dc2a653ac78b22f38032d6d9a684bf27741479396e4a61ec80b5092675b45545fbb6f456d67bc6d993661a8a3452171f22452dad5a6c649234839a033b449abdc7d010c5035dcd070f06d522cdb4fb771d23de5249222f554af1015b1ab0aaa0ff5aa5494844ed583c60b70b2c2baee6b9d614ca3f0a414c7d54a53273f1d317ddfc35fce3953197a02804bbe6fe6aeeb4c980511c3ed6d18e311f4d22d4f34c5a1277a1b412f6d9676c94df72975a92312d18c08f4018d9f7f46ac6d5cfe406b631466db7ea030fe2944a1753e0f4a5281a83f9cb1eb7b4559b161031aa0a3a951b1896480ca743a0c5000f8fe1b7cef41eaf278acb5568711740db516b18dfbbde0e7752e9c1885d191398942b13a2cffef5e7815d721439bffff78db70ce1a0a0f569280e1e40b2c31396b2d12fd97ec6a9bf4e5af4b8373d65a24fa27c91291524c3d82a4885859aa6d90512a69b3e670855e513dbd42721c07d68ab74b0e74eeb6a721d1c2aff94a3126a84057999329b8a9497ec70f3b54a0cdaad2426baf430bade995c62187baf36882c0deb0edfcdeafb0840e81dd9fc7517e70d4c1c93c76633dbdcedb267d79b57a09cd7d850125f9f3e0010000e8d0016e935ed1deacaa92102a43376703079c8c71e3e421692485d11e30f20065e062e046adb29084ac29e30af66cdbb6791e887b94a854211ee6f06d7e9aa67d0350c11cd1d8ba987871914aadf40b95714f79f57b7192b3a5d46690d217d0365f464e7409db7cd9a69f7eba8dcc4a95f9b98329596c2721fb0f9ea03f429077367154a676e7f7b58b2aa55e11abacd153758afc668502bf8be67d2b6e6f5eccbd46b1ec5a6fb0d40b2e07dff91b6065a05ed40ed8d134e2648f23fb1b88a770fec61137e2c6511e5b9e835da2dfd0d40eb4495db782201f50cfdb86f1d675f5a39050b41c6bcc8090b7ad04400a2f9b586375d0022b9a288b6c53881145b97d166b5880a22c52db28b747010b7589d6e612e0d0d4c9928d43bbd050182f4355b4d9f2623d376849b5040186ac973d81a3b39ce4af3deaacd965e202412f0aa84c67841c1116da0650885ea093a0f912b1fd2d1bf5545752a8fd0195c154a6fe0eb60842109da1c5b05d581b7b06819e3c1fbee972bc114a65f8a66779bd6054460c2ab3bdff2d82960495b9277fcd414f3eb363d4938ba0684e5e4c44446820e84ce321a3a1d9a85708db7d664f3567ad45a2fbb2a7ba5abd56afd5cb59f6547372b6ba2b0ac5e19a7fb5d59c6cefb328adb6566b64c4d29ac6c244e46ca995266005b7eca52da1ad3af1e5b3993d77c0034a461a75343f99d7755e8771f714a4f17c6213f03b51634344e5327c8f6853833d612028c95f6b83927c6584178892d044601e5073a08680d2a468532ac95f5b8292fcd1108db1832b4453e43cb1fd6b0ece36afce7d85da7863de6bc4210885002dc38e13b532280c7e2ff4aa9759bcf4864db03d69665052fd3844405803d4a8a0305a159554df594049f5c1106da1651185e8c9ae30d8f5beeeab25e5b94beac5c5cccccccccccccc0cb5e00bde68064ff89ebd335535035a4a2da8c5ac33b7838bc807adc5f790bfe3d42691fa3214e08e772452c7d103a30f275f2801a1cdd2c889d6b1cd990a82b08806a030feb40063c40ce1e1062d8822832653e880fe6007702c59c3060ed715578e0b278b38b459555b09fabd495d9e42c2896e735e213be28cd96c36bb51d50f1f8f2afa518563a5e078df8e260934f6f47a7ddfbd1f08ba5cfe0ac7c042efc52921bf087bdf077eded77dddd77de0e78d4dc04ec9e7b5c03b3327e2c61dedef08c8f75e2cc41731333acf136bb93dd15b9dcbfc9d37f3f35398227cc7ddcb2951fd6337ac68292da5a5b49496eab6a9b13c6a5570a2474a2fa5f7daab8213ad891acba6b4950fda6e0e1f00457af00cd63e27699f0a4fb4de428535b4a9a5546e32bb2d947c122de5a69b6e0beae415b393ee935084be6f764decdb5a810a6d6a292db53da5a5b24eb8ad05b1d8d2a6c8b7a6699aa63d7ee1c065c5799ea73ddd7bdef39ee7e9f7c8bde789a232dff61a73e3e43d535081488894016284dc5c81831cdc98f3bca95a6b5572cf7bba5605f03c2f2e36bd9e08be584b57e2a41669c989b4bcb582ff89dd73defb502ab9ff3c21a80bfe57f46ebc4ffde479f3db38f88743b873c89aa6bd4290b71deb0a79fba7e2deb796e68d7bcfebecf5bacf8513fbcf44b8aabbe4f35a14e61bbdd5f2688bcaf8e76a5a0b4608ddc2acfb590a2ab75aad1cd35bd65a267f556b783c2b6a9f2b71dbffa5e5561d3b6f4e9a77fb9b83efd1e6520057cc939f4de9b7f19a66bbcf6d7c209715dbdf5bcd9c1bde729e3967662c7e8bb9d79e87103a3ff737e78dd69df5eb3689b59fc1172c97b7915a92595755654926d4196c7f1a7b1e41dbf33c41aeeb1b0fa8dfeb59a2497e8e4a153f08430e1808e18bb213429322aa280308296b94fe346bdcbd4b745a5f38f162c6c5c5c5c5c5c5c5c58a0e6dd3c5a58439749d43868f1cdabeaeeb3d1d375a7bfc399f2d2a1d245404dd62459b1a4c83d913d65a0c6b30bc82d1e0d39280d0f84d7cbaa149de2423d1f8bdbb39df9cbb9710219aeb4d727f23104bc2288caa2004b4b27b2fe5a6246ecabfc63649bbbe49c227ca9eb8d17c52f475b316a370b5265e8d55094aaabfc4ae8f4f7c7a6f78d4f370303a1af209fd67d4de48f9f95a6bf54a9bda534be8037afab90b1f6653026c6af6d8a68b052559a0a6eb72524361d3bf5850d346497f0e567f686358ed187230b19620d1875c823e24d6781471cccad0db80bee543e2bdadcbba4e9c5c5d308aedff49b1fdbd4b83227e441584f289593d5067bb03f6efb7885709ea823f48b4f1e14b4a5b302f0cb6bf0fa5925216ccdb64fb6f378a76a7a0a4ff121e7ea25f9eece65c57f664f6c4c138984cc6c1381807f3ed9eccd2ead62e9179324fe626dbfdb64d4f963d99b64d4f86bbaf035fa0bf814cd89df8ed2cd2294b76b60a4f68bbbd973f2b7a61ad32999b4eb0021a0d09e9f888a3219f96ffd899ddb1241de268c88ed7f13b463b1be5d7f13bbe451c0d21e15b9e84d1ee8ca3fc3bc67b634924cfe30c5e821e345e1de34d695468d393ed5c973773934c832f6490e8e575d99397939373bc9ceb12fde3680ffb5e4ea84387d6610ea8e5c3176fd9d9b2cb14a665a49634e360a69f9f7dd232b4bd1639f3db401c82d00d015abe27e250c50fd44c2275b6b52fadcd1d17829fe862907b71ee7551181373d7c571a359c79b735dd765eb174c6ced3d5e170addb2b365170ac10d7567e76077b639770884c1b9f17ea0f28ad97e1fd14b6b4b99cce326ec407b2c0a7b3389ec694bf957e846db374b3125181b6dd988c3ff5ffc7d743a94d0f8fda9a5d494bf86907077ef3a777b6dd8bdf679f77aeeddeb390903cd80c062b1582cd64ae4d68a4a3197654f22114bc412b1442c114bc4e2b2e8e911b878e19435454229382575178a9054b492289f6c229188e5a61695a93432f04dfacadc0602813a90a8811e1c6bc0078d23fcb4ac01fd085f8d96a00d021a6da867122a53043d695fb0e88c45672c3a63d1194bf3e2655dac6c71b6ffc662bd686a7dd5577d5d8c354d0341160be4b94707206badb5d6da5289245dfabaacab5eecca2e9b75028c50a206654d1102a8008e12fc2234e78c1394611ead2b0788b52e97cba5c3b92996dff60a6aa5b0605fd6a5f2549e6afbeecb7f6d8eeae2fbfdfd3e7f90efe66ac355b929af48ceda5099da033d696ab868cc45632e1a73c5b64bd3a18175e5d75e188738f8000ed00cd8ad06ebb22f0bb32e9b03040495b85c2708e511800046308145112cf8c1143908a37437c8d8218a2fd26041a62559cc8cf36a9ad644df3763684c4c4c0c1ad9071a5a2412514ba9a51cd7e56ec32ba83d70129fb77ddef6799f77efbd1709ac6db012444a62e1debb6dee39e7d699f39773ce2f5d8666063dfd095a19f484ed5a1927686550193f81c2f88b5de8aa83d5f97d1f57da5b94162a6ca7f9e7fd847958a2a845bfa9efce72a2a241088bc5c3c9501bfaadd7755ee7759dd76db8736e0665cc801002855c2097f775dac579e33016b712d087dea4302d5cdc35537bb8f77df7da25efba84051a132a635302ff1170dc4e0844030c36ca605f1404f5408320f8e007043f20b6c1281004416f4bd0db9366c54915bc824593e97433f5877606ed9163d3d8f54d04c05ebbbef6ef084f90488922a54a973349fed76a4f5ee62c837d424417595e6cb23d052ba0c7f349fd22b64a1b49cef289f6d788d883ae77db31e4231f103274def6debb713f884422d1b52227a55b6b1511a108a150a94492ffee34c4d0702fd8cec301ed181a58ce99e3a6ac5c1e572ad5d02ca8108306654d11179a6095e017f914e1086518a3c44df786ca68355549fe358b52375553ac1c77c11facd5e524fe2ee7a69ed074d7f1f367c780f74608dab49ed7dd4e86edb90fb2e5a0ed8e7b23f86b755167cddc34c3970423b4379a550b2fbea0271cc54db16e8a7553ac9b62dd544da536b86517a4a196c4715fff820fa8adea0580227553e00cb5aca92488a0a623a8697bd790f017ec54ce9b0db36ddb6eeaa642af100e4e489d10c4e7e379795e1576af73f9b561f9654fb8f4c83c2f0fcc33dbeef545615a7ed0b60530b4e969797fcf03a3329ae78a13676cb7b25de511c3b3b3412d80615bc45a7a60f644c4a4af17f8e1a71e378dea8f2fa61f1c4dd1379a7f3d2f8fadaf577de5df3ea7f6f0dacaa89cca3759955799b5ed9cdb9fc69eb6284ef2c7c95a682f44555e87dcac94b62b2d168571b2da54300ab363495ec5a0f5555b9fb1be3caf0afb7c3e9fd1f38239b5e979bd5eaf94c70a591076b87658b1adea59830e292d89b69df6542a91b18f89b6d39e59b8674216ba060ea4a0a46ab19655a45bac3b85261ab59db58abe6a2aed8a9b049044d7bda14c4755a15e6cd35174e352b5ee10a1038ab6b9aced5f738d983d29a32c12aa42555277e1bee904bac2380c33a1409bdbb99daeed486363f336fa53182257d8b6a136246eaa3b4e7a6d55d2a66ab9b4711bb7d38ef7841a68f3c278ac40d3ed1947f643eff9cf38b263a299a8a46d562641ea10890000000400b314002028100c85c2e180583c269a77353e14800c738a48745a3695c7b32447621c8490318438430080800080cc08cd38000a8b4525eaeb47e8f032129f8262d28602a1b1d6e8d68c5d56aa8de1a39cedd5a79988ee64d8591aeeb0cdc4147ef14ec4a68dc9f8af72a004680f2a2e8aab5aa6772736adee8506497ae966b6703627ad85ce7f5a8d575d1ef8acc33176e7d5d762b2c778f9cc43e03b42fcf6253df08b319c5ab8529b57b97960968d772b173a6b49209c12bcc94e42907b624e295d2fe93941c8e5569d022731f74a106cd57229713a763c73b59ec2da2408aa214b329eb0e0764fa1cba1b1dcee5cbfa06c412c25a273db4ce972030676995368a210d27ba79d6f2aee3258d47d99755c8394cab454a2682da31f2bad7510c11f134b8099612b549918fbcdc4a71173a4e517dc533325580d18722626c6725d7be107e15d9405a711339fdd60d15cb55e41aca131423a6fa7620085ac586feadb908960c50cb6dea0f178a29f9a22013ed6627262d719a941b105f5cd43637efb08d23686c0639b806afb5f80c8cca9d2b397097035f25281c0b50716159c50224a8c775d309db3c63242876474e86ee73f8151048b8221761c8b54558b0476d1622964aa86c5d058b30b23840f86882392a5f06090f8810de482604350746cf22c824d257f7141dcff94190503c01a38156f61067388eb28674a68952da4f1c1c8b33da925a8069010d80acef82baa0e085fb20d53ac17dc03b8c09cf01b56920b477518b687184159a4fa423e22cb393b0ac0d288ab5c55d357bb5c6a30fe2aa37678d0970b3b08548c6aa74efce3f24a4bc42ca64051e96b1e78a6f9972d6dc65deb11e06bc84725333cb3ca717bca6c04f4e2a68be6e07bbd77314b4772d5754c81f0aaa26da5f332b9b2595a590b2275e7c2c004396b2780bc58420545bd1932375ab5f6ae6ea45999e4268e05d55287e1e6c5d00163fc6ebfc3350712979aeeadac5a50f9decfaa4c8df88929bab2001c12cb378c567dbe4b672be54f3bbedc20f357208ca534e8b1fec52debdec085c6d84fbf907b5a26ea2eb6a7108e819547024048dd545e65d7eba73d7d4b00fe30018adb4ea75b48a5585fb1f22953a07955aa709f2d8ff1468c9463a2ff80d728ffcd76cfce577cd4f8c4462eee1ae8e7c2dcdd59ec90014c1c215a3c2d51e91aebb2ae0957fb88dfa2a000804339df7f744d2952bb5d7ed40f9c005cfeb14c3787e9449c8555eb86203de32f12dac1a2d4ce29a026a54ba9d866e484c4257adbd79ddd21c2a9c161e793b40cccb6db3d2fdcbbdefe337ea26a26e4ef6cacde8d63183c12dba0114d64b3b0135f453732aa7d6f2e3aa21e3cb7a69358c0f319f4ed2c6dc0cca99c8fa8b6ad9d8820cffeb4abf0ce824606618c2aaeaa7649b8552501a219718c62bbf41613134659b022f09306eb0cae28dba061dbd09b753828e1166f52c9b27ce060b06a9901116fd9e647c46bbcbdc5787b833397885914a9d10145297f5633cbaf87026f92b664afa5127a191d2c2d2d091a71677801ac6aa301f5c7567c096aa597f1312e83ffc18be44ae3ec0cac0c7e133f4f3eef9f5df07970713222c945c7d43153f130eba49a79d90456b975b66f98d6158bacfc0c8edd3e6383400d2e1eb669104e5552945c93136d4f04cfc9289dba0ee1d949e4a2d49f1950015be8dda18338780c24ce4bd3ebda1c1155630385a454df2ad695bf6301ea14132b10629d911acd42775fff6368a1a0e685207b116a91524e6514b272498d5f43a195b932772d1c02983d2688199ef76de83da4fca5828699f5ce373f983ee57b841c3458ffa7d65fe6b64f2bd2542c8594aebc80f8bc853d0f487f27b48c2b8b8f07b4c081c1920478febf4523a8bfeace61e3ea8e66747e2f82048405702dafa3354dcc7f359bfd8b73cca41c4eb7447880c5cb482456668cadd77c90c8af77fbb4c49f8eaaf354860b71b26bbb67f0918798dae66afcd34d60bfb707b65261251a339e6dea829d1bfbfc86289b0057f59680f5231ac7487d1d9f105892fd4c3ad05ce99541f4f43d859b66c05dbd2288a743a325c072160087eda2419bccc43d97d7484861e95dc03f952a686c086202b8be0db8bb3d706fbeb323e995007bc1eed01e09639f978afd1072e19db8e930e0cb07a2a13e08d4d9e702400cb2b10cf0dc83acec01de2feabab5a0c23725a8785807d28a8dce74a8886f20961c6df241c090787f0af50289698aec7e850d6bc22f7cdb1e045d89ad9f39413b5811a0519e2e165f5afd92b0f5932c6cba1c0cfc708b40ab4e3914c92fa8059db5081381a34e854b1220c14d80067ba7eda8f4264d1cd3efb92c7a020c513976c93fc7c7702f608a7580a9d6596098fd17acfccda529b7e2295ca9b8bed23ac751c588a59e2849ae69e5537ee30ff7a1643ac6f4972492d74da0c178cce36157110a57c065b2c03944fafdf3bbd9bb9e0ae8b0cdde4b1b664e2aca6f0c74049aaffd612cdcfd17121af82fb1151261e99e7bcfa171f4f3bdaaba77cc768055ce9e50f6aa94064a59fc25fbf1388316b9ecd6262281e8da9840cc4a5af8a5b70dc46710a0c4f291d8a157a06181ebc3ec9df61d9bf35600fdf34250f46e33e73924bff6b3c44eb0f47b4bd83133d9fbf8b90ae112e262a4c8cc45fc8179ede1b9f33edf9c8b4d96ade11839992fea9066f9012be3f744d624ce78a3c71a7922f0ad3af6f2369dd4fc5629d06b63a390dc3d11145a543e34fe6e659f58063d93e8b04c0de63b2782800e27825292d517ed9a08acda092c153fd395022b2de8261ef7cfa6818a780ca6543e24945a219741112806de9222052db63be6447fa345b339462ffe8296c5a8d084a0b4fd1ca6cfd3892b72d069d3ede803bb88265a4e360834efd52aa518608b7c51f019b4b04e440ea8d94e8ba7876a9e2041006a97fa51500c58bfa2cdd1e370f0e5dc49cd8870ac2685e61f99220630acd9626737d6f6ae6cccf7880d84f4886b24ac00123c707cc9077bbc4296247cded7fbf4dab0d217ad0a5ce12d5f47a90152090c93f810fc53585c6cf9059f236f5c21074e72e7543b444608a2308b7decf6f54e65f4a47561fff5c0efb58976e113bd7be8aef436871b1f2b8d99beb6b588c01b24218453a2e8eac59ce85d3ab9595c61f099cb2c819a0eecaaaf8785fc05d612a897533c02a6a4fa9a3ae34d313e8d26fefceeea4e52c6f66782d5c1f866e7b4a90bcd98eab6c077479dc789db3aa862077fad4151c72f9230db7bb32413296877940a84d759b45b6c510265b195a5f426da87707c26bfe47214e9faae25e8db70aefd1dfac0eba3d3420d3be62924fd4f00002182b41a2e031e4fe901c66dd93e3c253e03a7460384beae8129ca5c8ffba7e1a87ab48fa71c2bbd61cb1622984b518f72e3331245f9f178216cf77037cbbdd7f47255f2448993bfc03ef50a0d541d49a76ddff7b3591d6ede8f96f7b75cfddd72ffce7f0e3b109e84897c5c6e134dd00524af49e14fca82d32669ff0176c6537bd81ea4df573c1830e7c4861bbd28f41fd89e66d318a2b03dfaf8029989f0d7b0d6bd86fc05db1389eeb1bdec390c686f29be49f764d9a15ee3a2891621dfb03dd29cadbcd81e66638d21333c99a8cf801a8dd33a1a5b07c40811f9cc92edf173d61db2087bc449655bd8647b7c59d59d320b1684a12e02656b29998c97a6f0ea3162e9a001035a12a3f288dc4240fc5777b56af541a8ed969a76f792f089e8408d3d73c1d996c3555cd6fc5847139508f3188df179efbd139e4770dbb3687df87759301d3032b23a589b5d697f76696a4a43b5028491721621a18379b89e37db9fcb62ab4699073558730994c0b994601e664c2f7154028184956bbb09127b8b464c803205f2c4c6ada9095f0c31ffcb79d47cceab82bfa4c44d68ed5a987490a34fd5b94258e0885189b74d73b2a5830dc7e71c709a00f8ff09ae543db9704a735e303c5a50392bc6e1b3314a148a312a94e15f681dd10ded96f7a5310ccf66ddd510b8c19b1ae93ac00504f361fcfa478250ae28e5c7983a8ad38ac8203b28204db16f4078605603cb17d3213cd404f274f1c8fed346d851c6202349e2f496910429c96cafdae5c78655988ba004c2b052003de9ddf40e58419ec0f9674f3474de01c17d27f1c10d4972127f644e130b078961d782f9ba9ba416f1a24e557279a417767ac112a0e65d7b1bc9d38fd12113641bee88d1aa7931be1fb8e4929a69d5083fd347de14ed56064776e5e1dcfb5f44642d90a1bf7c0aa3df60a99ecb943a3d42bc23cf6341d7b695e4953027e47ccd3395b0e88049ae8f16c1506391a59b64f19c28d021be8488d3240992724b752711c45250f480b1b89abf0162904f8418cc439fd63692ccba73ec37ab8bc0427f867b628040afefd705ffc6cc30c17300c6c2bceacc2b972b83fa31ea5554abc238d416fbb7ff672c9aeba59ce04861a1756d4521521d41f4a2a3749a5414a6cefb19495947da748e23e921ddde5f477119297b09b000c3c5d24c72a6da932cb3ac93c64643174a7cb21eaa1a533c1cce791d62d3da741a0ba96c5451dd096bb7700e1ea99f79b335988bcd1ba88fc2b554e805596ea68c8806238370589ef991ee3bdee04697f10788899bd5a36322471433f5111f013bc5a83a056734ff81c6d26628a1e8ae9c4f03d7d2b35391e436d38ba639901f38bc2961d6029a6c1aafa628f8c3975ea647d856c60bf90030e02304158ef4f6da275379c474a0120932c9a1c3a49864c91f885224e7901eb565b877d9ec48bad0dbcab5c8d6c11491c8540fed4f2fa70c6d9f00a20a8a074814edb1cc7426f0edb4847c528ebc953bd2e4e06ca7c5fa9fb5ceef6f00632946d75c86cf4b89575244146e657087535a6c15cd9d1e5d86cc2561f0d021f982d8a74472c3a2ba4949934e4243eef53cfbf3bc2314261f63a94b091f21bd20ba9e2a020e92f63a7a58f5bdfc8835c64dd6d8715714a6561cd884ec6d1dd1aedf81fe819380126456899dcd8578c8a1b5ff7813c8a48ecf4266135caefd255ce95c3abeb59c6e6c5508169646b09747521ce8f24fdff328ffc68f9b56db1c7b818b87a3e3b40ca50a09eebc136f391ba85c939f507079f8da52381494e1f978090560254447ab5408ede163597fa208c4b1fbbc73b14e920b2ecc7df6c11f959948a7b280feacaee5fe7ee8b93e9019b1c875a1effa6a29212a62151b36d924b6b3a923691d55f26903f3f6488470bbeeaa87f5aa928cf355ac116f9de752ac3e28744624fbe2b814faae3460319023465b33016379d63b957196655816ba21775e9ce088d7b589a2ea1f1005180e7ceed609a744a34fa820eee916fbf16573a997d8ca2b2bbec6990296f1ba036e3fa53bff763f31a7d4910f20b8f0b558e78092693193198a9d3d49ca4106d834a3c24a05320254b87ed1e85d3cfd025efd948c4c1a9ff210ff21b83efd8af846afdb8aac168084a05571aa9c156a19cf7005988642c7bd7bcec260fb75ca8be00c41bcbcc4185a928a85e06422b61ef8d153f8783fcfa23112244e1008771dea0198e3b03ad939f4cb0b5c56a85ec8e29a0b0ee1cdbd29e0b35271e7a122a01f840fde62f8fc6a5080b15e8ef6ba2786643bdd99fb8be2878fc35251b017613047b1d2273b0473a453897ac52f964ae8e693485cff825be993c662649851429a982f33f680a9dadd48ca2783e21b10a7ae67b284868702ed75dd1da50c3a6dbb0714bcfd83d3a3e752b100c031701ef0e1e78f2bb24fbebf344676ccbfd4eb2a8b74080f29157cb831c01a498b476dbf2c7d9087da7d2556ed5e9357628271e30b30517a3caf77d6f4da3b2189b05c24dd8704e13f1f84077c42f8de3f446eeb12b469971882ec92da2e386f4512c37b74cd822e6138abc261c809306bc684e7867cbb2ca8cec0706efa1ccef811e3ee5c19c6881336d2c6af1d42611b456d4d5af83d725f03869200b36094cc249e39eae82a30c09df4021a7ac5054100dd6a39940294d54c822f0f6784087bc528d9d89a6f8bbd68cba51a22ace54cb860ac15275bd86e5e3bb83e3c01abd20d0e9bf89534e2925aa5efad3710e320f9f8ba700b133d3b091cb86c34cd80b1b2a2a0088f1153a28d9368d4aa870110667f20fcd04d9871ee0b0ba68676f326b8b656ebf834a0949848a73acff723a2aaf086525dbc21fb9c0ac018d5edda965d332c7e7ab1d6da50541e2095402a99dc94aa321605a79b9a7f56f67557aeac4fe89ddf102d91f9120dcea59565975c32668439f166b66f99a5b137f949198678cb3a8066d0726774793a8d5d336b45e919f91739e7ab66cf802b43e638ccb6c29e0055f2c4b5c04cc82a97b8b9fc7e0abeb53517708ff009803e7f6c3e0f441e68d20afd2d93c198db9c09a9d9ba7302727517bceaa43ad32d24eb0214dfa099ae751bee13f2cedb893382938aaad6529f0d882e672ca8b967d233a1a6964c24720aefe6d4e3e11bc8020bb044e66e45e2adbc0189400558230df19ea983d3557de422e467918a698142439bccc9945a358640c807eec9d7c118c57231e35050c304c6ef74fdfea1b4de5f0ffb11c6f0cdc106acb374d9ce23a3e8d87518d3e51c8f22d1f72fe8d3c6098fbb151cd8dee0816990a57d3eee4b31e93ae7de71ed91d5223ac2cada623454c369fdad3eb87c1a3cf1db7f78a5c18170a656f4042ea5ddb1292366bbfe86d4e55e03ce6bdad59bcab0e6eb346be8315d2829780488ba7b396ab87c0344de50657fb2d01966c32dbf2864f22ded43aab6b75907e7fec0102211e2207f5e1a2abb9aa7eb07d9e73cb173fdc7414c47ebe1bb8f43e88f849b72a18c8f008eeb6fd286dbc56a462a630e3bb91e686151579a8359c55287b68cc6e5c3c388f8f8719db4c38890df3022b444dbecd96930860463357cb1704db5a96df5685b5d06775edd7080fe92dafc0aefdd464244f051d5884433133025ecd16cc49f5f2f15ba3f21df7c0d45df5cd6cb6a957c58f84a29dc7b16e62bffae958d511e39dc13885e5c0c76a92f2e7a943520372495bdbfb4444c380fb0270f879f61cf754d0a0e8405ac72055c8e8683c49c60fd36207e0b7bb262c831f2e678e21c623ec7e0997dcba3826e6f9183521c8a9ecf925fc52a3502e49667ca7e26f883ca22f080f889a5160db9dbef2000f381992f43ebc6a78646ba416f5669c98fb55c4089b586e34c8005ab2fb8dea7006133e5bebe8ab6db1dd23d2cf61f7a61bf0491e3d7dd3a38b7435c2ead79eda483d2e5b63e0e6ecef724f3f18e2b25dd31d1b3348592ac4763e00a628feddef4898004af2f93fd622ac1c2f0b01c6a638d50a391920d7122c42aeb290256b0241fd94755e151cb65af5002041626c2bf205d83ac52e1e1b435de33a63185ac57e151f5e5bb38edeb53cc9f931e7f0a003e49b8f04072b41d365c7f7d4732a332331f6031da484c8053f6f665c133fb7295769a39795508e0f11ea0baa2b7a60a959443c9b3c9a2283ed90a8251b79ee2cd836b7b7ee3740662cd13c0c25c560d0a28693bd8de717f06be8fa333640eac6c438265f3a02f2452945236fac092693b645526c354faf4359dc7a478dd5fd3d27f327e57fb2efae7aff4f83896f3c1261d812e9ae7349794b5835caae21baf0bb5cd53b40a0d2f2da4222467e2e31438c2aed97277ecec529fbb487b5da5d106eecab0ab856d29336b2c1fb1d4b48003cb245c1548c129be12b4a71b689c7a315c9c32a10ff5e6679d0a5b8018dde18b217e72f0475b5135a11062352e8842bbd5d12e0ec66176c7f4ffcc8c6e6c10551a1e1c9d3d3d2d3b3ca7a30cdb0b876da1cf2c924f17a60b6328bbfbf2a543c04046871f87aadc0f540190a9a42f117d4124087812267ea6abe3217a9dc9490ca1c957fdbce3a7c01ed1810db43e00d779c26046e0b43f816045d4d4aef0a8852b22d1323d8022114ae89d0ae51ef461af8aa304b79d56aa45cd77ef72dfbe000886caa001288e4930899d89ec9f83cc88a6869e7e7ca220f19af792ea7104b8690e8c2aea7cf8c860cd2f5acce672e1e208889dc172975cc575a9d3724fc2d92075bbf6337ef14be43ca648f7523da2544a4861776fcd0c4aa715786aaae79c467bd97785080fc817fcc586c7a27482973d54014a93ef3da843470fb0347bc9e8cdede180545ea9671a393006529736a24bad61446e8ff9a1474b65476c04f5947ae94a8d43cf861fbcaa894f9d3ec51f95d6151a1044bc1f8aeb090c593d0b7e57399d4956ac977b019fe077d291b78806d3d4a67df8b7fcdbcf25a4b040b56cff6c65e6ff4acf4cb081e78863ac0573218bff8625b3b4fef5e714fc8e6e7b7700153130e27c6a6a3581744c5de88538bb408b3ebaa2974913d2d4278475b394248179b0ac78831d90ec3792b2139de4d69b3844bb61e3103268ff6e308591d1ee5eeb122e672993a1f3c3d18a639c831b33a3d17ec804bac91589df0b545fde721e04261120ff8e9953845635d38fc6cda562d36dca09f412be04c337f792fd5dc2fbdc90d5e03af88fab2cc325598d4bb80e1099d8be1a507478935268f51b2be2fc8cfea130a72d0cdceacb7db274587d9070606e896fde04263180caa01f4cdcdaf5c5303c8d06f5eb6d525588aff6d8a39acb135f59b79ea8e1c5946e190a5382e4c544dbe066881b5e57cf225be4b9e182f87c34b34b88c535ad483e981f8dfaf98dcd3ddfcd33e20d7c4f8cd78c6b9bf7fb5efb663c88b6a8e25767407eeb56c5859c284de0c67e507022e2f6688c7886bc0649772bdcda1a2953f396d57528c78015ed3c246408947b348ea49ccb8326be6380a8395fa7220ad1f24c9dbcc1708e3d4c3b7ef36c6eff074feec4eb45317adcd0f94db203820aab3402d7bbab4001741e2419d87166b7308016bb05e968c783822e549ea739c0d8bdec0629e8a6180ec50514326b8e1c53872cf034ad11f9136d474c4a231218b88f7fd1ca29a3942558ca859b53b311ba1f60f36ddf0607042d8115819de7509889c85a55636b2e93742b4d6f35e9b58e5ade70ff195c8c86ba4110127627567ca80fdd452a54e2b3ba809e929e9aeadbc1c5cce766fd48b7a04f70b36417e80baf317a1906698975506155d484bca9d2b5b168006fdf53e4fc18f4ba4b073045b25765311a90b84d35d0fd6e7a744937ff7b5d661e754faaa261b98d85811bde5c1c5ee4d3147d6e66b6af4a3074e87c2408c6bfdd89c78a7181832bb5da0762814b2e93a35382692bcd7118d625c955f57a604e20857ae03f3e3fbf3a9b214c825528cf743240023c89820ba7d67bd5d8a44f86bf06d522deccb3bcdcde75ff915bfb5f669436f5c47365b99fd24a106fb1ba6ac4ff6541b1ae0a0f30d22699eaaaacdadb534986b87bf6180502d61b469d6f45b4c93789782e062e0b10528a92874e5915c657955f28d21274cc5e7ee840e75532743d6f2aadd27b795f0e3d22055a53460aa358e8a340389f56c68f5418c147d5ea8612dbe89cbf88a85ab66a88cdc750bc6b4daefc30114e594bb5781ad23aec4bb0c23edef2a7235498ae6dc2434361a1a791cee111c161808b40bba571b791716719b15bdc449373d6f4733221efc0f45dd7f733534146d98c00f5fa1264ec69a349212ec5e37d7fdf4097af98b7b5726b8515f9c466efad9df2a060904e00db2c8975abdcedcc4c3da9014795753615d79b62de1534b448cbd0b98af27d043e619f103b4c22769526d9af2b70e29514eb1eb9a13300961f7bbf7be07e50b0a16d5eeccb7b9dfc5601d8917e63513e07e18b278a1673c07c819a04b886177cb73f9fa76b15eec6de26e8b383044c5dc257972ec1f03a4943d54d2968da7ac10aba300c6fd7c87541152b5fc365abbe4521cb69766639ffa131090f2e1716f65bdfdc1a2cabb38d0df3739f5f34454638562d3a4352173806f055449aa426b4435bdc28dc62ddb0a7da28948944b1ea2f0ada05d94e92f5d868a290a416c397c82ed5315133e764b7cffc5693322630a854a3fac7816150e7993f49b0ad81f27be568f043e2a11c54f04b1194775e8a31d148368f19375ed564ca3e8b5b33e8860ff30bf12d4b575fdfd2cadb0e2acb096ecf50a41814bb0967eb0fe2905c3ffab6223a2aeee537d7339fea1db1ee5e45ff5d2c4f5bcadbe0a0ed5e58da223c5335cb6a113f62c72f60b5503d0a56a418d7e24a6fec4befee67c9ab6364e16808a7dc679d2b862a5c26e86c74482ca18f89c6458355a649bb3a90886e3b0ab79b354c13a2a51684de8559433dff6e53a234d9e0095827eb10049a8125a477cf8fc0c1070eb1491bf3bf8b787881c104bc19030975afca95e9567475498c003c6c09efde7128aeb2985567c9ccc52bccc6ed26425e704deec189ab1185fd52a125dda2f7475a584cfc57186544107715d27fb89b69514a218230fb5a87fd8747538cb0fd4cfc92682d90247bba4faed5ec872c90ef1f8cbaa950047b8b6d53a3e762fad4d75564d464ef0a2e684e43d63e7fdc0309431b6881771fcc032b30438c92a41fe4112be8923ec9080b270fd93ec0483e805137fa5f849111eae65f94d60f68cfc89cf006cd2033213747d0739641229063a4e9cb01ec47b88492f3469f66e11de40da0c2045bc6ff952e4ebfc130a186ec5b539f4e33a00ea4819ca5a9ae2027ec7a734e3ae9823a541750ee7d909a4c48ceff62844f12798c621478bd353fe04ac48a013acf20eeea8bd1b3c3f15ef59ba7563a5150c553652c7bd1e06571f72d8f9639cb1c6465052709aeb8213966dffe83d5fb4e4b978ed8b4d1b3aedb82c1e9db89cf2e8bf8092da318d85d97a7c58270b20fc4a2de71f9982501fc48599db76a52eb92935e392bfdfad1355e018647bb4b41a527a74c52e1895feb704069b61210697806f32fecdef802205a50a79601c9e8232dff0052d2d61ceb6775de81aaaaf015e04ced6ed1c97e8b1ae53cd716835c9d1f424a8dc6e03268f8b026e472b561ad500d02cd0cedc571eaa3ef1f040ff4becc0a554ed464aa283566d6293925303723fbe7b266799f9a2139f6a5f86a39368f3c2e126ed1d19ceee3c9c2f27dca5215a3a5758b5a5417241030f1537502aa426651adfe8d4f00f6867865e41c4c39367e4a242c2a254030bb03ead777eddbbd393472fe972e736761e8f8ae2b891a239359fca35b83302555289aca9a6b59c2544a3dfc896c98438464d7c123e503d50dd13b952badc182a59d085ec2af9c257dd8cbe8725aeab26a0712716989c5fd4ee5aeadc606a192085f263ae14f50bbb83c5c1d5689bf812f2c986e011085016f8ad71cae6a5c57efdbb47398b8a14207da32606979e898e1c96f6fc593760491e4a091019bf576b7ed07bd411ec641e4d3caf259bee758d144644f3e6e9a943da71402e3c6176f5ff7cc0b02974a84d9cbcc645009461f49c35424f115fa125d5e29403ce9be9441dd37343f05c6d8a8f56cbe59fcaedb96f3306e97491fa69291acdd5a80d016220010566a1ac1b59da677af3cbf33362ef681d259694614f842efc15065e6a50d93aaba93c1fb3eaa406c27132327707790070cf8a1405cedd80d5178c325f2f9061f4bd9dc501e42a1f43d92f1ff1d41eebcc18f26885e288a035fb0d8ebebaf32127caa264499f0bd22ba565033068d8654fb0030b28949dd0181be9e05ee28a9efe351ac06ddd854e0fd4a3c63730f99bb234f0a721004a9c443512fbcac416aeb704a96c70648bc54da1ea91e6022255b9a848979e27582844bc96fefc239e1ff72869ccf0adc1979e2797f82a495df90c078b49048fd73af50409f1c94657f36280b6dde3dbf442dcfbaed2749ccf82a624c4bc450405d6fff7e747e1fcffdac69cc3630bb258e9ec3a61574fef4128cfc848c11c7f852221cf91b344736890722d5ac2dd591861c020e2e951ae71b91538a6283e43cf0b0eeff658b4a7c8954b8436dabefdcd2cb6758aa485cc7eb9fb941e6fcb0a6273f23a4ea95b355c0ab035ff5e54230bd35ddbe9d6e074637ce90535871219a8c21062c6fe8827527011c02275794042e7dbc1f31d3e2494877c5f48f2aa6e42044d3272307519ead9acc7957ba030d2da91229d80dbfef18c77eddbe133e4b4fa54883df2167ca20d67d87951be187d96a8979f39d6f8e3b4c82ba1afb3dd308b4a8f75c5944732992908879bb84d98a108058903989b73cdf8ffdfcaad7ef2231cdfb5e46f7f53491c5373339fbd48bff4459f51545b70d1f4f486b5894bb9b8255fe609e2473009d70de4fa3276acb8fa28234bd3ec00e886127d3c9973ae11435d30e1b0bb0451eeca81a28f41333b84614e980af898533249b9aa75534129dc92c6736d5159e9ebfba6e5202e9b15315ddf09822eb4f229fec984d6b4b17aebdd31e789256fe4c7e1d8ad664f390879ba17501f0152863763df641544c7c74c09950c89ac08a02e837f28d69e7b147822f500a3b5d3e0cddc673e039f8754577e62336943aaf49380316923fbd7880837fa5a7fd3a2a41f83f2658e0998061dfca634ac3eef0e839a64df2e5fff05c41b1c43e8d022a5c142e48352e65a3d919d50cde624446043a89d714e2b1b6b472a423e9505e9de0edaa82e002c800c93b618b7fb91be4e9e95839855f0deb34e863f2e3772bcb01b96dbab0609955db9c1bfd9773b891cb154fa338f55316d7c1e4b358f071dc0123678930234fd289c8bcb4b97e2ffa53c1427388ac297025258b756aa53a103ab1dce7344c649c421b90c24693c06f97f224cca6a7007ad7a7241a4f242b766561f05b7112e31cc7b085e35db0135d40a13f1666ab114dd7cf807963c5d0cb3dcda3701208e6c0b4c309fabedc28b458e45d9329e678bfc8910c98b78a699a6a60dcb024743afc1737c8c0742cb9d737ea1a8ac4ba95d972a97bc855f6c95316f77c1be3bff036a50e1408ffc2cff7fc172aac49e13c9cc3e62cdd50330eaad62e72ca63fdd0bdf04956c9762f70b6c4ebe09cb4a036fce190c93844778e0232dde4ba061e97ad60e5d9d48cf14a936a42f5d90a82f44c80e451a60766691034a781d4d86fa0e90501a40c0065a1e793379f876d2575051da6da9c3fafd551309fdaf2bb851ecba63ae0b774c4b0c5079b7be7ae46fd7eae4b3e53a9534aeeb14da95c7b7ed54bc2715d811b3547952a41641c17788c54519519b86a86ab1c8ac8081822b75bdfdc6e99075e33b7e0b799faf2b0a6798324f2c202f69f40862593b66a6eaf6a46c2b9b879b509b4398f12e156bdcf138b2666c5cebd973f21249e5684c974489ce803d56b592babf0f46d031e1ff65ea02b33f10b035959aea39c588774a28743f8410deaab34e799e34b1d380ef43e221ab40513a246d9ef060a2c8a8ee733147f9291288e2a507a03a2767416d37e992ac8730d315b005609ca90395d11a44edf0bfe378001a6932655c7b0cedf47b166f456d462ad46523df05346a098a617c5519fd93ce8a02ac7aee9d2318f72793623d579f6d9f4542e6ff84e674f0c78d1192a784fef960161b7442ffcfb523a7acbb5ee5e9023bddcc8be8d7ac308a96516892cfef267be4fe8675deb5f48e7b0f25cb048088d61cbe7cc2bee32dce5deff28b1bbc52ad481bd4f07314853dad43f6090f53d9f5fcdb355f3a3093c51909cd617aa4558ea67cd2a59e83861892a6b7ddf0ca24cd9f3280ce56d65e509fdb25d7d7892cc423131f18e9f42e79b09d026eb946e34411020a129f3e51836f9dccdf9f15b21636cfb620f2b5422944d24fb589d498377c528b05e88d1f17922c69ff54e3dd1ae8787ddd5fa01fd52d8fcb3827bd529092c58c2c7ed0c28bc56fee8a7e97856dcc65d25ecef8e4881574b5dea26040cfb2490ec1990068882ad608c935c2e1e94bb481830af925c4f99a74880a8762a125f9285be843c4ebf84999513cfe0d9c7491c741e0069f613cfa10a23cf8db69e66f8ae46aee89795cd8b566f4073b2b37f52bca4579e00da3b42d03c71ebb0462e4756608e18d1d38c1d42e67e490c07532b9923f55d33ed87dbc2513421915d5907f18ddef17671c140ddf11a596791ccbd74c96bbd03f9ed597434f728274ef06bed38129e176b4a9825b9bb5c03e14f5176922f58ef8f84a3a6b575ade0a3b67a9de098f9a41bb93b3d4a1cb9088c81a7c811e8f409550bf329e418b5d5cfaa2ff001347e839b3e0bb9ea30c687999e36f3b7cc54e6ec2de021e78a1833d1cfb46619817a5ebe5483058adceb47ecb89d2a30a98fdd4ba5dc47ce290ac3335ee4371f3858a16c02653463c6642ea7752f9cbee4dcd4d1a6381cc957c3b10c5bc53e4506b8e474befd02e514830ef8c4b1975f64c413f514406a98f42d991505e12b567b4401f5d944d434fcc0d1cbe3c53a8d958214667c6104619d330ee8e1c1a8c10379f120d2cb1cab07e060e0361a48c66f5a794c141a3ca92c9afb255eb1d4e301047892fabcb8c60e051f3c240bbde9965bb9fb360078126581e0a9e98d77e5090421bea07b82477a22ba6b30eec3917ea049636e1149eb2223679a5a8a2dbfd7aced3064609b46b37b0db25898b361738f44886c486ec392feb5c6263c32344f6e6e008c3212cb99ea88bb703850f04e02870c00129291e84a37812cd8c0f0311a03b6e2d67230632b7a0db409a20b187c1212b7af95e6f6cc2df0bb64c4e2f8460400ebdd6e461d22c08cadd35378402355a291a8a55c1ab9e67deb50c541ea32348b626f7b29dd89390140b324e39b5d61891326c871688f51456eb677c86736a40e75a442cccd9b70033f224dd43c6162cd217960e350a43cc443f53221e50b4d3e6e5db1326da4f2b9a9e5ef89240fe3b9a1fe2d71249c5ed36bfa5746c4a3677c725533dff358363305ebc45c89682f68bb4ebb38765cb80dcad025daa8073c5a8232e50998de9a87b24b8d0e297bcde9625b3b023cc098b8ac3d7c30505272e1ee9c06db6864dc804dec00b39ea1b65c48dbb76ebcfe64d8be30be11eb5c67d25bddf07fced703ee5fa60f7568b2972b8172d629fb2bbc50d323156e9483f2f55cb2af2965a6403221d45c4c7452c372f437e046069a309593b3ed9de10ccce36ab6bd33d019b77e5d17c9f632bf4390a4db51f043c62ab0cae15bdd7ccf345cc8c6cc4ad4c225a02fe35be338bc8332460909cfbeb0f731d6ca873d04765f51ee11c0f1c6d09d1d166aa1312bd900ae4e58a9acc81f8c3618d1c73e6299887fd1753589f23e2ad6b987ab1e85d0cb5bf9fad4c71efc6f2056552beef494cee7cc8a8391bf35087e1f19a7a318c27508836f4ed57cc144e5ce7c5e1765bc0b5734dbe5b25ea3003308b863df36349445cc07b6d955d0b03db123b597183d8e429c463c2191af5974c2a327a383d59324df32502c0ae674eb489bb0f85ffa27cd03c51d0771f0292662a78c37ba782571c37dede63935bd87357d29a23f72882180f2765cadf7e650ef9ee7462ecf427e5de3578304406c846ea1450a9449e9017a5c2f8881a487fb9f50a741b092c88400d3f909a026b70920bd253d54bd6a13ddb6725c9c0a49c9d0c0eabd2a3bae4d48726dd5f78d2d4f8da4ae343f976a20c57690612579a84bdf244c70ece9605a050869ef88250e96e0d1b651447ed0b05ace5311aa4d9ea16e6051cce3910448aaa176c28b323bc84aeb7ee12d4103ed260713a13d6fe4f099d5d7c75fc8edd33989844f826f0c96cbcbd908cfcf4e50afbb4dc0ffa8965a87bd41ac97bd3370194e871f7c25e61d1cbadbfafc6ea9af8993af84bb11bb07c8c53a904661d759b00b6c2c35e42301a8c9e7266fb6bed8e449d6cf9e96809f7ee0a1d1248a37f7dc5f5a1c22f0292ba9cb5813618d2233ba60edcde041aa5740e9143177e7a80b294f3fb8ce2365b1fba46f7db5e0e0716f175a26834bbab9e65b081c932409fa31b7655adbc59a8761f23fd461b85298b597af60e55c8f8a74c5f6239460e65679959a46458f9a1d0eceafd9217a9059f8d02156621dad1675b5ca6a89334dd0eb00bba5a3a918ed0c99c83dc9eb28642a71406dbf1bd951ff0a5c68493997f705691318e361be28db8ef1760f4495573e046bfdacb177d8bba57080ce71fadbd56fa83a3548f48e369fbf0957f9cfeaefac252150146db31109b3bec386ce0ef85e923b6d0b65fe622b1fbe7888133665cd4f6f745b2d1e7937df6440117cc6bf4c92b59fb7fb186fa2bfe96e0bc08e02b8d553576d1e29740d81321af4ad1d19503cbac5e9a303239e0c96fa0e6d41bb94d86a88006f13a7abbb5b76aad09296c90fd33ca1814c9d50a76c4713656edf25f6a495167cb4e9f0289336cb6b696df2d78677f6f26c91010321efeb0b5e77e73bc6d449667f03a47bbc9b35ba8c190fb2f958f4305967999be859216354a1c47eefc73390c72921a708529514621c0b647381cb090b015b3a6953188a342bec16b22364e1724e4176dc95137ad43717b19cfd161e4b22d0842ae3239dd5232b24ded9fd0d1d84acdced0c7b41d5625552959611e5a930b637f0b1108a52ee1d920a87ddec2fc180d55adfe8146b5a22d9d60a2ec8a9de2fe8c1412e2cef3dd6602cf1da9ec5dd190ebff6efb0c2753bd6260191dde8b04cedb932ace8856c6ce1123da802f424b840953a420c89f71bc37f8f213a1b41f6570ba84ff344565667ab499bde75592c8f377934ff6df4a2c4d3685465475f5d19bbb0bf8c907c2b05a68b3aadf6722794b10844fc6d1a3d9398a04872fbbe9e8a9c2457bedf0793e8b9a6bd6210296676f48e289d88ee88b8a875692088bf8bbd5d20497c0dfdf3577bf93ed6b933293db90ceba7d59da45abcc97319ab5dd53e8d9355746edb5ef391678c900dd62eb77429144cf7ba788d81c98a476428b12273535689448dd8daa6589d04e196da8a60b931b8d2b61efe1a637d884a96ba67b716627fa09bafeae308b5aa700e4eb86a1aeb8b72f07c9035546aa6e5e6a7cd39a67c0a907d02459c2f2d3139f0d606cc41b77b52b51b09e375086a05a2b1fc92219c6d6f22d56193900d4524c96a15eb341b7a7a5f2a8c97a71761a62cdc8197c59a77743fad27e339aff9371dd02afa7497ccdaec03cb9dd2324f3195e0f5b7355d60731b4095efce2a854074b0b6136bcca0fbdd5d8d3afb86c34c402b73981be51f0a522ba9060032869228256e6689a70ded1644079dd165f6d43f516c3d58e20b91acea86af7ed4bc538c154f7875b2ecae03b9db0392119b2c5430d409239d4c130dfc4fa713b2a6ffc0cf33aca05767c062c67768428ee18206d1512f8fc5de4c426130defc0a3fd080be2caae2a9af6c471a0053a40d254abed0ba8c5d64397500a6b4aabc4ce534eea950c09f25ba4668e95f9760a0c3bb402ca5a7aa0b3ed10b7e62f97082722102652b3c2db324519b03c016fb6e6835d29ef813d1e1e19f855b72344b61afe04ed05ebfdc467bba2aadcb9d60cef71575e621fe984517acf85c480471fdd1b55a30be90248aa488c2785ea1ee7fe22a083e24ddff4c80d48341253600375f72f80e966001a3579fef16d33b667abe86547a59df6febfeb5566c7fb950a7db46abd26480c2fbcea41fe30e64a19ea97576684c9411acab0d11dea17be570630179aa4a510338f62d82d8d6d31b881c61fbda0e6ca8414a21b53f905618d47e63131cbf234e2a2a51fbfb3d7cc51baeaf81330a3b67ed6ff86fad2cf3cadb27aada5bfbb3bdb75092bc6eed0f31fea677f236d08319085c7e8d01d332b45c50eb8d8e64b0c3608277e86dc4abb5836025174081ad7c5b1f1b3ba352ff8d09a991defe931adb7b0d6063742c848c80f4bc91611094e268cc7649be95a223b6856edc05e30d3b8389930be65189a22d189191b338a24e4c11ac84a1b6304ed18c6953f8054c2b5e26dd0f68684d062b06ae7e1c5bd00c1b5a2b28066f187bfa0d1b7b2a42fb467d0047c4e889326a846f8e96333a22a6074afe04100ec5dd700c0df2128aa0e4bd7df719241d794a138f6d9cebb7cd959703451488e8e0cd07b02be9e000c4b484f9a29b0b18c7c79fdc6a9c3e0154ee9717344b7a00752f41cc80505d193dcb5d6a61b12b7dedddc3bb4eb7c0a79988f4ae33577da0ad11b8a33db4ad19516d2690beb015b3a0515e336ee552a800b605e0ea451ff382a57ee1c6964f93fe58bb9332b4423f48045cbf6cbd544408465177ea8068caab8014d4e531bbf19235c5a6d6d25c6371db453ca5a4816ed725dec9012b678d37be1b273ea55a5eec141fb4d0453d106a3e8d2767541ad1e6c697c3eb205571f37ceac7e1b90d399a8c9567091dc463dc232f74e752d71e1fe3c9ee22c084beec6c9c0141c07cbd3eef41da0e4981be88c6d230d8e380a450324e20bb052b8801a783a241e34494ecf2fc66a203c7ba4db2aaa15e708511975c9271f994f78e98c86c498548724eb21bd9e601c00a56ba45c51e0c4a554cf47a7c8a19440e07ab89706f9f5c0b8e0d30a4ab4100b80dc1d8e5c04615ed96d582c769a0e1b88c3ff3e7caac4e9d377489c24644e371d5176f6007085acab6f575710fff0dcf09bed0b0bc31546f073d56d102d3345ab7f89cc0f232ebd80a279ce3ef02cc94133d428a2cee016efb30fbafefe0552e7eda8e46f7f0f24c4e387e10ee0fa43d7818e870b600365596798013071bc4a5802e06aa87240ef6c19731edb252f6d812533f81322c08f13bca256ced7c968c6e63f7456a4b4879b642fe6fceb8bbbfde65e0c8358ed70c7ef5f3a3a540b34c75012e8eeedc4cc7b412d8f2424c1815fdf2386ba4013240845b08970ca06e0b61e2de1096375dba9b8e4f0ac8ecc199354fe37cd269d8dc038fb43b737c4712bc930b30505d05a7efc57efe2a3dbebb712eb66a5458413ac2714a7c0f261360bda749ac4a3f305332cb75961c3ee7f5c0cc0e99e9fd42c5470e5959fd9e287db6c95cd2ced1db06ac3de71b5899b7225c506cf17c51403a6652580143e63b08813a1e84ee9cbf590c69226589006528124980a50c4ec2362004d9aad05cfff3bade72004ff900ee1b49c0dd6bc52b90d08798274b0ec144df2d01dfc488772fd701a9ae9011d7fd7ad5f538358c1a2d452b473fcc8172023d3f8ba347c48f90ed2637231b6650dd77514ee031f0943a3c90add59907adcae2182dcbf2518d5f1bbd41818238a864cf9c70d0d63c3ddd86222cf410ac5fc9b3d3a3694ba032f649f8527ac823253c2193928788c21c31a6a3195bf1448eca1c54f7725c04670034117868aed0a87cc1a806803f15dc9b1b0be3a8f21672299b514bf559f8f282c27dda1d5498f3a39823f0ac8b9632bbf163944a4155701d1e2b61013999cac463c0faa74c2360ca9df26ec8a02b1a117bba02e41306c52cae6e90b5a561fe4d7d66c221c94442a2d3117f2a4d73994cb374348edc18d6d66b91b2415f3018175499ba6a2041102158964b5e529c103af0f6a189a7d169c92bbb08b4006c6d86593280df41d893030c1ade3f3511a55f996c00a1478030ea60593cb17bcb417b589d18776f49c660f1ee3cd94dffc2d4c3a8381a272cac82940091e5efb083e4b942b90c430d966cb0f05a746522b5827becf98b724b2b0fecaa72a042af4692ddc1a884b5ec80e1c3fd14c5f34929c98694e3ef3943552907d90e8c47913d89ab0914f9f2c2e5c059c410d40c3a30f170b969e1752bc5c2b6a8646014e45c85806a56c3c09c30f3386069917c69410009c957267f7f498e5cd88e4a5cbd4a2464ca3f8717f4c2db1ea3abc3609b6c4773ba65f0c4c7c77df42b4a35e66179b52fd97a13f5fa01c65f29a317820c6b183a9ec2558021bd7d4d8403ff8239b7791bee6e2c9051454d11fc2c6532cd973cfb0c60cc23c0f1801520aeed6bd94f109a72be6afc9225e656cedbc27492662503c71451c63fe71100eaddb63f4fe69be4e55b2dd661c1c1d7810e1d6a33ef60ca8ed8d10a0bce5ae0e685a6c216b962aac687815128ed6d353b511da6d722dc9bed419ccfeafea861248b46f83dd5fc6e4ffd5d24e1f99f0fdf19ab339d2bed9b9fde07929de34f096c3a8857e95fb14cacaed37b2aa986febf6d964769a3633b37cd661404576cf772639e1c5517ad0da147c5b83c371a1bb129344735feb8fee4a0e48e7246943551aeb21c85fc6237c255eb7928d3e1b282ce77898494bd62caff71c098d08112680fd2f5c41a6e455c541e2436d56f613221b2b1c023a7f88ea7ef335a5507e260b7a4ee1e1debd9f1fadb1fc194fc16360b4b808cd28aa53b5a78b314b53c051c0e9ad92ecdc8bf48ad8f61db13d27bf395c4809d7274b5fd987fada5ede07fa875f63729feb1168cb76caa687c2a3771bda6143af57da4dfe3205b205bd2dd04b977960d03117ae20ac2e6b93dd94a819c6ef19a41f257102bcbde036257d05ee450884f6929a0c8db55621d4513214a4d7f2c19dfec70cfa27fdfd7dbfffbafced8d8a61a25b1ff9314327bbd37afab976d3e7ed9cb908fee2c33f21d21166bf95f39afc7a7a6fbf30b04abcb8065d8f8f5f643d5e80cd0a581b6ff5b3e82e8d4c4b6f7d8a065f81eb23ae69078e4c46c40524c5c12fa1e0c5bb9c01b4806c3d9854898a5fa93067823a088d9813f4de91492826b557d2405f53fe4859963f76864131f3dca2af917215eac07cf82224eec45ff4e03ace03879952d921129521156459230d6d58222570e066aa62929dc3739da080d45be41694ae8522c5e043b365062e5efe3da39d8e0bdbed3108e533e629af25846989dfa0a8b5ae4cd012cdf1c2f8d56ec2bd52603370f146c7a591ff98cca777acb7ceb8d47e0c40645bed63b1f97bfbe7b86d35056b38fa00b0207d4f2849521c3879b7935ec887f5a3d23ecccdd721d95532a3e80f924e40ee36f98bce7f3fd052449cf81f29e6bc2990a5e9c38901d69a456ab45e4a0e0382e6d3ee83ba4188103a33b62cb014560a7be500b347143ba965b670ce60aab16aab3a319ca5e0278927355b224d315238e56b742c5e7b7194733663e298d0798f896d1ac7c15f53df53e47e374ebaa2be94aca9b81ea9b1034db84889310ffde8003f697244a518073d875fc77b4fdedb48cc3654e66f9ca48bc155a52d632d4c94c14b1383ed5a781db47818582e984ee3b725813d5bbc609ad217fe7493b1fc8a0090deb67d9b67da0ffffa6fc031399e2be29035eb721f9298004c4c05efcfc3d04b1f79abb23aaa05bcec24250d03c470c74e20923801e10215deeb93e0cc819c6a698cd04f92a84cb70561457681816ab64b8a0d1b94ee43ada447fa1fad3380565d40f553090be8e130c38530479435d5c21e71623a18fb1f6dfb603c1cee8942bc212c8f155622d4a513380ae526ace371c74bc639599c86e1fb69514056b548c2bfd01472be1b32f8d55145746137ec212cf35b5dd86b733185ed392020e408701db55e259fe459c6cfdb1785dcff245010cc8282b6a95ec61387df5ac4389aa06976aad34e80f46f84d359e5299dea960291d3d2cf5fa8ced9ff6d178d8a1fedd5b3855dcb3d7c76efc88ea2ab503af5cedaf3040ea8f230b97c14496f7fbe5a1336597b154d367ab063028b17ff52b020512e1b920f3041c72d8947006c914633f506f14cd231b60a24428844a420c3e92d233e63d98924b4933a31d253348c3be477d8cb1ddeb35a829e25444c86c5a086135b3e16b8bfb17c6404858f899f1ce1d067634b78e4e12160e8189788a0f9bdedcceb965ab52a88fdcd087634eef8893b910c48daa02b50e655aad6429d34536c6d843b9f43c972880f381916aac7331750558d1371d0978514519a25f5a7e3a9c203ef1ec3f75fcb45bf69ab30f06e6f250c1858769bc0c1c5b7888eeaa69e98a3c742f97d6ad90da4b96832fe3a1c764285fd755f0f73c465b6d489d62b26fd1516c2db65ef292128f85350b70857be437e1d9fc85501f19ddd1a3671a107244672575042f52c34fda088a779a641da7fa9c801a2948d2bcb7f6dabc88063e9f34792c227b6c405403464df0b706091599c20dde2bdbc730c745aad03409486c9df099da4cc11c3176e89f8b880d7fb22244f40e5c24c6763964bc399180b7b6d7c2e419f021fd4cea3930245b9f6773ecf78e647b102efa5c2a6220db6a66b823781a7e4d8f4f6dc56c0161fb3a579c1fce6d9bfd4ef4434ee6cdcd30a3ba097e468f5ac5a7f0102864e31aa8a98d1153c4f892fb39909b55510940c43dcc98828f2bd097caaa7b8f9cbcc70c88917041e64ee753a70b00909346764d88ae5932f9ef41af0a4a91af00ed60a61963c2503feb4b298e33680b7f752fd6b2989fcbb0fe4cd655e8e9a6043e1645cce28598d454d058f6b1719e434755ed730a1f5af865ccec639db24243b5bb0e0cc86338386519a7f2abe5b958004126f903b3cc3adfc18a0c5c326f4c9908d13fdc46e448b1f230aa889e9e54ef7cec56f271b9746b53c96b1ed2258a96db84958986c83ab80f25833113851abfbdd3aa4982f82069a010718dcb7e9c6a02432759e17bb76dd19ade07866e3fe7be251531357950ada085840391731bc7338c3340912cb441ee128c6eba3e2ec444f8499698692e626f5b3ebbaba3a123b8e065806ebc388153a5693fde82a823ba5a9ac802342cbc8c2a38ccfd64749750b0b4f560f4418b0234c8d63ed0ba121085311c0191f88b668f79f63b644323429e7f1b67112e52d1918452b04c41acf1a88973142dd24da4d767275c78551d5c4fdf07e8d10eac582f618b7a15b899cb02debd005df96ce5a379f895b3792b204b9d51dd34121cb0d410263aa3f86d8d0e470c6e9d473a75bad3dd8901d939781b72e7378094e1544572bdc50b7547cbed1b73b4ad10a5dcaa860501a74d5082e019bf78c8be41b8d3ec38dc8b23fb0b5870ff8c7e925e0ac8d10f8a782e5a7ce72fe99c2e2011df1365c51ec1bcad618cab67ccdc72ec6c81cd830a3f8856c7eac5a15be7ed1c1a41b2e89498a5f13a38d108c28c75ee5125670c39f2db485c8f168090e40872319437e09e423d7b2508b38506b5613f2112cff75c2d18e019f297189134853879051291dd96bdcaf29da9eb6791e55b05018e415e03d0cc3da1b83784cac16b75f69fe0d913c37ceea456710d668e23b616e3aea022f4d9359f4bd592ae83de73297116ef4f8f447af911f9ef201010a21a178c1fb956cf9e548b23d6d1e5e1f1482840d0bec8ecdec88f8342b483c566881395a5e8f357664e85a9766f6a1f92dae615d009f0b6bf92d1c584c8dbfbf08fc08db87f2bfdb7798bc2d1722b1e21701154b109f705175f245f52ac467de4d43f59309dd457582f0120f9d1b5c5e65b2cb6dc0e20a52bf9b043e9073c2030adaae3c64ff00ffb5ac16d2ea0332eab40ac9b19ffbe68b2fe816ec9bb6b0a89fb3f93364ee03354f8e6d1ae4acf9e0cc7b2e22d10a8243bae41d3fbcee19b4e7ca87f5a730b1d8f393e158b7cfb3ff6ca28ee70fb8ce0ffdb0d388c60fc9dcb1e8d8a96bf139231e95945f1d2bd94a498eed689894d9c293c88cc5f8044a16c0c7cb334624143beea6f74924eb8664c4bd49769a415564fc4c2cb3849604895099f12fdfea6156264e8fca1bd4fdb8ebb5de7bc990225cd7a269b9dd8ea299cb70abe2c93bc90b355b3c99b60a40364064ba4e6d9383e6780a07ad0a4ba123b01673ace8f4ab4dabdd85ec6caa2977e8087f626b59258edeba40937a00f43280acdb9fe28a2ae53361f41856a01628584e02cad10ac745fce64506398a7b4241035168c6d7918e4883c7a47c8b0f0ea48f0fe6ae1a74ebee8069516f40c66772952e2dee3807c07528b49544a5a0aac4166bbd48257d29b9c6151da45501e852bc0289946bf49b4bc0c5ff15092aa806096539133ed3e05fb763a1968334cb8d52de7de04d17b33c26147860822b033aefa7df99d18d9b1ad61d30b6d2dfd27eab4c20c5cde4c583320d562dc0c37e29a74d6dc2d2143829e5803adf99c410e0202eb38f82831339d6cbee8046c9ad0d4668ffc368f2f417c30db18e2507a937c014024eb930d82f74f8abe096fb84b2724abf59dd9632e4c6ce056790876120af347f03d6dc2ade35dd573e7e6f301e849990f80071abf5ce9e5d0a0d17338be01c581cf37cb758d6cf525b5dfe18382f48ea7fad37825abd0cbb61cef9374901945f48ac2087b13d6fd8b2702a528a3f64e69a9bb83abd9f162d1c2dabcfee73dab21668e8dde52bd2d376a6b8c8083db605d703814033722d3203cc4956250f1b09fd1f7f2dfd3b2627b2ddba7af8c61d6f3f71f7be3abd5e7082127ad300ef1750e382bd8ba25458671cf4314306420a7ff204aca42dffec34cb1e0d9c27cac6168d664ca651bbd68125ccbb19a86ab58c641130cbb967d33888959adc594fb00fb27d1044cb0b0a16477e36892223374ffe480697e50a47311e0888e0a5048b6b65e68788740d3168d7e5600400aceab072058e69f5d318d965cb2dbe84b24d660197ad2d94926dd5053a00908c655031876d5988dcc5b025c40390f2072bfe0d7ccc520290943b23e045c51a2a5201782d46901d1962f0829732b2978c5670d79d1280a7f5cee7756b45fbd7c55ab581f13902e6e2df1f9280b1eab4edbcf7e09ec2fe0476cad96437921374ff352554f8ec6a41f7d63548497cba38d4fdce8c25df524abe8c521203259eb51fc6b5b55356dc4115ebe09aa962fe78a699c005525cf33137b3d4409e85be537f67c13ef82697f1bfabfee76da875b47b3db89cce289cb791f6287f30807b54e4e83f642910d4f67aaa0b188069f7b6d781414ce6529a2fd7144fcb7e43769a7f2e67bb8f5ebea63ffb1413424c9c9e23971b177e6bc74e4260099611809a291aa797fbe2e34d125f5c1d51d934cf1d8f5f9e92bac338abc48181d8ff1983857b3ac2a50fe24d2997c0e096e8244e34a9692393d6d068650ab4ba3bd37a39f6b6c0c215f39353f82c70269202abec1a19164deeb2f03d4f0fa9d10abb01b8921d3e76f5c0a7d7e915fa3b9d8afad555ac0c94d7c7b4c094aa55cd1c633d869b5fdfe0f7cbb40d214d47c881865b4626088d2816fb9e838d60515dc88d09f299d83784735ca8338f1997eef4a0a0db1c081323080f6d3f99baa3564a56b2e701b64a0ee5bf8a7579eaf30a670a11fc79df565025608807f721282440179e282c21d5c40f05a3f89939655c25e387e179f7fcefe94c996c34c1ae5b4d435a6ad59000dfa508291a8a7b6a4e5032ecbd6a391ff5411ec93d09f0b6bedc40e97c4d53c16b682764e6a7aab058ae55cc9f5de1c1188e291abc7b61ce7246b758e4a8b00b0dc94ca1e6e685220b8202e00dc8bd42d995855a4d1a3c9a55e7ecc89aca9994c68a2650caf7fe19d0f50749879b95de07f15a3fd3b4f380f4be2abf5ce8f5e00aaaffbd312b770ac2c0a4445ea7e5bf509c8b70f9eb3778582c769866637c5e64cec57fa4444c06327415560e7356d86c4fba446f5c23b645d3671a5c65e27158c6cd8eaf23e7da6de8af49b0760b0c41540cd271d68c761861beb5f05a022a3e28cdedd6c7166d296b4c9eb224b5c67ad1ef5290f75467bcc62b72f51113b0d74f9ed7eb2270d476faeeb492352b1bafceed3a3820a82e1ab0b6863ab34401b5cc21c69fb8fcf70db0813356042be382b3c41328b0fc3eb23fb4051f9401b0452ffe439dcbecd929058d1e6bd5e74c86f50ac0cf1a6eddf3098fef1d09f95d755abe75e83595c11f18143db2fb265aa4681f4707027c671a04ead6c016cfef1a3a98841b6ff48f4de90383a2aa2b2bb077f95bb300dc08ac725c7b4bccf7045ab535f98884350920cf84ec6d54aaee5005aea38cdef9c268af504549695f9484e65c89931cb47e2dd54fd21f948f4da250ea66e6a45eddaa64b84586467dbb5b2b6dbcd7e5bbf8b30f0fbb308f6c62c5d7ab9672a00e4c84ef292087a83de48ad29048353ada8449e7e3e80b4ba7186737b8e8d379b13944a1ee80fc27147ab509d2e79a455bf7fe6132fae14cff4af994a53a8dc93608a24b608edb8a5561047cef37643486c1d4bdbc495ef58175013146f893cdf94b756446e0a7906aa09c8330a09853f71be04c8cde8f6e715673ad18492222aba28c65a10a4e862b8fc998d37663e9522eb07211d2ee7807ab8f4fd89cc182fa98b0c6fb87e35da6b6af8dc9899c32e9417d332473a85c526a790be20189c2760e76ab79a6bb199a088fb82406415eac19f9bd9cdce712d4eeb6f8e2b0cdf9b44b817672729b4edabbaff34bc020fd03579effd6225b88b6323e43b8b22978cdba79169bf008ba0140a16c3eab599ca5358a678821731053fc5b9d7c45a38bdc6959ae270dd8dc09f2d28299131cbb347d37f38dd3507eaad2d7e8079c4cc89120736f5181d16a1c9066735164db6044b6882de0ff4070486dbcc3f9fdc3ce70fef4551b9f2205036beb8b1dfe3a7031cd94fdda66417410269687303fff3e8ca12ce50ae31bbcfaac92f391c157953471d537a0fab81280c61290e4130184d8e612ee609ea477ecdd055b80c9136d9de5da9e04153b5a5c044969c9610e5ee84bd48f735994f1b51a7366a5d3a649337337f14ef5d6779887e4f4909531673ee038b479832c22b145100b14e8710364bb6a15b5e0f55ba3f13b70fc19b572ccd89328d8f0f7477c327cd4a8dbcb784929be789bf425f8afbc2b89b44982d71301f39151dc7101bde94b13526f439fcfae20709a3d49624e81cc16ed487921fb6ec0228473aae5af9bdf2a997da9d705bb57bb3483f50386123dc809c33b5b5589a5af02f6c53ae3b5f5deec43a1a5385fb9409f26a69f65cecee7c790810b6da4066c9da9a33ed40f1dba7951b1a6bff9cb6bf5bb19227bfb727022f65a0046366385f278c88b30efb514bb6c2d4064b5e7df8124a1de99d8d94951fa4781c377892c7e0cb596e2af1fec729f713e6171970373a0fe8b2a07cc15a95e70fbcfa8a924a05889709be1743dbc89d445997b71af710fef22f122141aaa5c4fc9cdd219f74bd6cab9ed95eee4e68afb19765c67235100fb59cb6faa7e71d1595158b3f06d166dab9167b519f7dcd18c75ff4b123308040a9e71bf128a55a4b6dadaac9bd1765a705e404c0bb25a7ad42df4488adedd9c2102264c9d1fb3e99e54428a89816b90deb51fc42aae52328dfbbb0a3a23232af757f3fa981a43d3de05d0c0d3b367e7476c422979cedb0948143e61327fbdae48baeeddf9817c440231ccf7f94b5113c783a9a6100e120ade1474b286b25233dccac40e96763493e6abc38fd1b199bf21ed191655fae7e881c5d01b96e1439dd2eed9eb44d78d908b4534750840d7e0552a775fd9d3cda3603b1e46e1b863c9c257b3b1cd6491390e5a2bbe9e488e18f83556d01f658e1f359c6849ea1a9b2c21bae829243392fa52e4c355c0d9065a978e49d521e93869efae57d11972c26195798a9f1e96abc7a87ca3482a78d9a9d328bb51ef9fb24004d2844904de246916810db876d3757baea0774be0905a13726235135195461a13af57b7b9ff6b2f85ce18aa9a37eb27a54a20039f931f7c3c4ca928119e5c21efbe0ace3d19216a8706e1d6d180ae169a3c24e4ed1d3fc2236e207aef5bf611cfc79910d482451a83b5c4c74c8ddc8cde3299c37d089ab0cd86ccaa4fa214d15102245b5e81e202044358dc06b2344b7bac05ba3588d14635353e59c6a7c4be1209b282405a62c0dbf36053a4883ad704f2db3ed103782dc4cddc0da565de13c490fa190ecfddf623854fe84e668e9fb757345b448b2db6eec6d337a0689005063dc89754c1c937f88fa3fd2db0f1836efabb297bb66b48bdfb74f59710ab34599e151632fd4d1ef68243c488c27c49b42ecf346f33b7d05f6d79633d3264add091a1ff9cf8e5313581b582353b5737730a2652ee49a83609052d4a36ca30a70f4cd457049dc13a677ec7ceb03fcc93d2a0cd480a247c5967d9b3a22be882ef0a2d2c5efb1b061a51e3850ed127c442bb93e3e9e4baafa2298a70049f41b668b93ff5e711dd21f7f4f9c24d6db84fdf29e6dd22822a3881f68c1dcb00da4b64433183997accf134a66b2c63b04e9e52cf576a8fe9109644d4cab14ed0d60812058503a09953b25773579355e17f03e7a5708f2e0b968c980f033cd3c828987468f84d8a09046a74fe3d6c8e5449837c47917b9d3419bed6de4290841aea7bbdfb70718e6131914e7e62e5ab065f78968c44a06162595321c1ae3692642ef7acb2030b52d6571a7d3f8f0399ac2f13cd4018ac9c780b93b1e8fd24493ed16948847c92c681e34a0bd34ed41baedcd00b35ccad2efe797bb1eb2df05fb3a8a8a746c4a6d38b3209407d1c0a19bed56d1d1d3b93bc8fcb88c6f4a3ecfa43dc7c6686ccac0a585531f42af400feb2542b989bdf276bf27f0efd69e5773385661e6046efeb0e671f581a994ca74a7053b003845990e4dafac24d31ced919b28184b247a4c17f89cf798433596b81b380c9d52fa5cade950909461672d1488a733bf64c1114c65914dd1d60b28ef9536dd78482b9837a31fab3e3a0543897c7632cdf5ba266c70a7859a314e2d76729b33705f9b63bd581531d493c8d9bfe63caa589d5953c1cfb197ef4f648bf228fe70111921330aed6abc7ce0955a0eed505735b3abf2361d3c18905c80a28e8ea256b65e0157d0e35431c312266739b56bf501192c73d54bf3979836562ff2c0d230882996a5b2bc037d4c0b13846b13f68a003a5968491275ac270e048f9de9c614fff66d3b27cbc7b373880cc8dfaaee65d0fcc4e0856460cbd316763e78cb5eb26c48d341d8e66b9cbfac30297690fd1602f61c6d887b0e0d047c0e6558a295dc6217d82d131c9cf100abc7ed6a5f773471e2b0e44886c533d2468d3636c0729745f463735a9674352c01d8610c34c905b1a9bc2377e65c0a7f7379e5559a5227849a82472dabd997aa1799ca10e60dc0a334ced2700e22688456171c92c83def194293ec651eb5ca7fe504b842155cc0a4c96a4701f694c2bf31913e61797058068cd89bfcd92b01c3247f9e6e14c855ac390be838dc13552b2d7ff664e457595cd5c375d0a951d1fbbd56c3aaab317e8b89e8acebec4a047b8e002bebbe514b3b35c99c105b75cef2a1f0cb7ec64327c5321ad8a27e65b116d8482a0f28efc41e0c1184cb24cae00548e4c2b390c8854ec0495665dbdb3165abb1c98ce30e018be0f70bab4efaa590070a17e3116873518eecf0e565fd2543f9c4f7602a038d4484323cac5e2c985b1d2fe0369b228d454b1e48c1402b93cd5276e20449d4930634edc43883aa5418af20cb0bc4c1a9a3021f9a160ca6f95ecb23c95e28ecc962e134a845c7c015d919d2f1be249cf35615943a64c0eb841da8c7bc97456fe125e5383988a3b1613aee4a0c0fecc379ed2ab36bec83d5bf506b42b764c263208c1d190e64cec73dcadcab74363d3e55594546d3c4ce80349e650559a95a4ac872a8ae1d7d4b941cc0bcd8e3911ed3c463aee6e08915914562274850e762d14e839c15a24d0f22584dd7065a471b09fc012a5f88db1a8fc64154fcf6f2c0a5a21e28d336fb94cd4430037fa515522e3ab880208ebf3c28ca5abf1111d674ad3acf741e18dd0155f7b6dd151f20389b6692881bd7f651d6db1e47a91a801e01af2a4bd7e607a3815e19f7d3913c3f13967a7a94f0d8d6771a42fa3927145192111969ea8eb0a08e5cf81acf09d3c748c85201c2423ad4ac5761a885b221d3dc3d3c268548d318012f5062e0c7f2fe9bba66416a6e8b54d89443b2d5b19d8da814a3c317594fe90bc32a90503447d97e2bcdc249b54ff24f3f9c22db59823146098e402ef5e25eee64d7bd7e1ea190515ec222cfa22686160ee37c052d79fb5db7a7c73ceca70ba7c57b9ff9df2f916cdb27326e8b4d830260e4143b3b2464f96aa5697c4c22ce78b685f7eedb6e35d5c61645f993891846192c855baf1f27a17d1654cab6f0cdf5a92c42e94717057d590aadcce33d70adce701b4a85a8855a9ea43d9ab13ac64ac0f02ac2be9d2454ef3e0c0b388a0505eb5bece0340f6b5f99462c20098315c4c4f0b359ce20142dfd0a8f52a4b28d6385f6408bec024fda35c3e6222c1c21119029e689b8b120eaf31cd5db975e214287b1c0d77d6b14d87dcccb2add383ba2ef9c9db10cd1c7e6205c424d183d06e8d0815e708ecee1a0a57a883a2f11c59b2fa46f07006b2eac16c0424cc7ed99259a3f02a49d217e1c2923a3dfdb49974964979427210f63cb5c187742201feec3c552e02f3ba753ac5657eace354f08725688e2cd6fe08a29f9cff35ce91d77b9a6569f4c57ba99178b90e78639e809fa9ffb8468e2dc8781b2ee9783e79b2e90e69fddb1d26041926d9b6bf701230477f00555c85febb3204aebf09154ae221683bdfeca112f270f15f8a446179591f61f37e0ae23b9f6cf0d80d9ae3b30755ffb73e384593215b874570f1bb53fe6fe5de38255ec08aa23aa025a91045e8f0dffc70498e7427882a1b268a2598cc5239322ca469c44008b39cff9dbfe04ea4c05f4071eb34d6acea10c0543f953dceb5ee6b3bd5fa71f4efa256859e3f414f6c98455e43a8ef8f5689096043acd19b0c32aae369fee88a203eaa869d72578a3b26a21c910234493ea5d1f8fa6e90bb374e7b85634201aae0451d462caa17009f1509a057ae60c772601f82ff5d3c02e54da05a93ec09a6b2889bc38f543503ac9e173212121dcf3484d0ad4e40b2d1a5ba290806aff3653e2ad27aa47aa3df12d5432915994349f69bcbb6a9d608f35bbba38fee8af081763bf22ca45d4130c32a8c80aea4405f43f4f59e03437fd2a8770a122ad00e0eb49e31500a71d507e98711475c02216e5e37076acdc216a98746e7ca6eb12d1f19e741124efa4aa501601e8811a94636b1313df1166cae179fd12fe69e62182f80b3c14dd0beb731589ed532341a1cb8a355931aa65ac9c3e13dc9e34111716f19c0e69d2867216d9841b5ead5e1fa742721d437c26cda8aef364e7295e4a9a6123424ee6527fe166a14aa8dca3c9c4f95b3998b3a49b99f66d50109f9b244e9762f2084f4d7bf24ecdef7e1f1b726a72376a3f4ef58c8e745683065e1d0bab5f401ef311b701ec01a40a031adbe9615d3052325207693177d5b624c9ace738100869c0fb925a8154d2415847acecd17903a6bf52e4750042c726cc718e0e2062568b8261b8000431c68c55373ee4daad9f7b800f7ed4ec2bf7c3609355473d1146c41742f6de7b4b29a59449cafe05f305270639a8340885be1cb9408efa1de6a1d0d3061da7ff7d356d40fe6c0dd0ffbe096b4b2a4d5637b6a4e233dbdea21d8fef29e8258cc159c4431ef99d20af98f98b40316f600667de7298b7bcd53295423f5f15dcc077eaac9049ac51c4f6229e9a2a17f3df1d12162d5831dc21ba106e59a5940b9029c7419efc7968c27dbc05f3425c5ebf909787f9d2a6526663082d04ca7c21fa5d5e08ccbf3c0d7d14f4bb3c0a30fff2f3a3a1e003f4bbfc0ffd2e3f41297bfe7c584acc4387e119107d71ceb2f63179eb89a43057744b859dc5dc58582fd4f12d4ad9b843e948473ae66dcbd85bde1a432ed31384a0a0209f1a445395ee9c99c29131a23dc109933645489b69c43cf9a4229b49c4cc946ca0c51974e3c3437762a65288800ca7dfc0add8ae65cf94646248b32664ce1812ff264514c9cb4b398269b144a2697106ed4993277f39693287d2f89aa201d280b4293361d2c67720233003141d8c1993c34c2e63f298c97f3c947968c5431f439efc47a0b8c180627e018334e838bcf3e04da68fbf66103b68266d1c260763489b221c09ac06186cd2640934de7f4a215333a5492bd16a5e2cd1006bc09aa7aa1a30c80baa9aaf090a9ae12226a8608932aa9973ce49452460f9711b6943751ccfbfb3829e3d9f3f481fa794967449843174f568c4a0c5525e0dd99352dc2a958e90499860a92bede05bf1a9b5d5e4db6b80f4b0ce971874ce94f6b844585cc1f223d45732d9f662032d4e99cca9ee2670b1c1d85b66add49bbf6503eddaaee99715912991363d5a9459382031a0017963b388712dd689c5dce3388f721ce5a4cddb23e48df92824643256e71e12188fc3a10b1072f154f5a1a72ecbcd96ed412c164041aa202effc2dc8115245041b1dfd1a8d828151666144392523f1acd6fe887ba8ee675b4afa36dde0e41de8ccdd5fc7d9bb7812190a1697e5343e6e8efe55f5e462f2490028d9ef42f2f1ff3421ad16adf8db450e8be5eb017ecbe3e98480413c144b04ff4e27d7da2cba6e39b97bd50f7dfeb3857f3766f94cfebeeebc2eeebbe6e14bbf9dc683496cc1814887a91e334489b94d7e03c9ef378d6da90f3d8f083edfd5f96b0bd9b209ef28b36f945110f0feb82dea23cb5569a81b00ef4cec98f923fa948801b5b26b19d8b9a1c3af286bffc1979034486feb28815096405bf991f273be9494ba50815bb8b616959db7e721cdbc7221ed38929a259b095048c319e3be7eee3dea3a6997fcb5f75481b7fcf76974eb04706757474cc58066243760059a27df8a7e0afe3df83524aef9c79db728f0bc86783680485eea93d94ba7b16b97f18678c33c6b86464c4f2ffffffffbe49d838303cd053357f7e3031e8698bac6aadf4e3412b0dd5061380f853405dcdd2134eec8964826e02d2a4933aa5b487d548da389e9bcbf71d76ab451ece37685f1f7af21a4de9510a0e03c9300d327565dfd7bf62e000d5f0aac4830c87fb9ee8b58579e9401718f0fa70a0185a89a1950b124c424fbfbb1ec537c4bd8e4f183607ba6c2013176aea76c6b7b6c5509036856af414020ac942317ae2f1a1a99012f2e4a1267ca4f09123121b26045093da2843b2fd03432b7a9a9d7b47843edb98d960428b482ccf33476344d388a2bccc80c91c496ac91cd84c6d460c00403562356435acf80d0b2de4ddbd7f8d5908a3cc018038828550850d5b14d5b8b2fd6b4ca9f103801dfc94ed3fa30879639d48d95a8ad8fe241c644a34c43cf91bc1c316254162915e222144af0124a1c5118cf59a8144dec08c33583227c35c3123c9f6d73265fbcfc4640e7e124be66c30bff9a48c62211313d17726263c5925eabad81649ff3d016a5a9ccf855e8776a610a80217dbde9f20ab888191cf03dde9b7a308cfd6aa24004500a1a5044253239afbb8efb0273289a2f8c9452f0fa3789e120d8a60a2d708266d569a348291449fc44d10915a304e0433c25c216f44302da2d70c3923c90c2472660a894562491b237a1bc144afbf18ac3312abc492363436066762d2867b85469963ed10db9f7b0d795997b471273ee2db2186bcb4b1609d8d308616492c126b3b894562d998b940e16eadb5d65a6badb5b6565babb5dbb66d395b6badcd39676badb536677cb72c3f8ee3b80f4c2114147a19457cf4d07196ed7886b1cbc4d2bf6bce36b6bd9aaec53db8273f7e0a6410e3d975e1d90dc2b3fbf3310ffd6bbd413485310bcf6bba5692e0191e710dcf30cdd6fc660b9ed91abee2788667d6e65c63b3990ccb7ae88bd5f4c939833e6849730d45f5e005cd5bde72ce79c31bde72ce79c3db26b72de76c6dce395bf9edc8afe33a743e3e340da487f55e4cf1f7d01dcfdb199368fadeef009939f22a476e09c81c1fc815b82ffbcf51ec90f2de7b71a514bf9d98524a29a6b6ab9fad4f4da14d29a5f4dea79b10d2851d2072bcae0ecacb0fda7efd5a4b25d4113a983bd06829f8d41468aa565aa58966d0a2a4956416dfb2c2913974023429692e84a1c552a954aab5a6e0f2813bfdd28f74a075400c4e3048109af9ef81414220cdfcecee9de9e26ecb79cb5bce5bee9494b20c3a29e93451fa939a686cf8a0e9cf9f94deeb5e9db3fac81a0aebe3b1acb56ea7bc11ebd3d8979b624b4a62021bec20032a98d04082f1c5e803145b58118413242c5858800297163c3c146822082b341d6a28830995e37c587fa83bfdfa97d27dbf821b53da938db058a49452a2e82ae71c0b513024d0f36bad3c644c676475def44c72d3792fc6b6f3bcd649e7a4f35a2c6995ec2a273ad3e7b6a462c4caa65275719db3ce59e7acf98f48593d8e27a694730420d49c006aa2899f52ad0664e59e47299d3470a05802f2e47fe5ca2569a1c5c7e00f3d830652a3a1f284165b528102884d3f1e19a4a13f69b0e7cf9e26bb61946851d680c899813d79a004902db4f8b424f1bd78ce5903b245f1f1b0562aa33355b69af0bdff8ffbffcf6d195ffba2278997e8235a26874077cd9c755a5c6bad359760022dca9aed3e8072006abe9a1b35d4877ef14057e98eabb43113119820cc273e383825fbc4da27ee3686d0f8f3e328a1c7e8881671688d310e8e748c29258d44a31baae3f0123c87e1ec8b9cff51ee212a0cc3102655f4c90b7b52c671dfbcbe0099e303efc92b3cf4e499a6ea0620aa0852bd20c74802883054a11a542fcc2354a117650c25e5072dcaf1c9cb9524690599aa907ed1a3f0bd07cafb9487ae3cec5ea4ab94c77efb76ccce4433f5bb88fe0514e2bde88790efb54abf54694d4f795cd9508116e90aa44556df7bbf022af2bdb783d29cb5f6189d6daf43c5e9a2b4dd7dde0972502255f3cb201d9d68d193d028574899397ca544741ffaedb073529887f495c47b5253e53f33859e3f1e26113d0905668b9e4efbc5891627d09432611efa4fd0e399401efef9a22f0adbc1007d8d51404aefdda8f7022433e546d1b79463321c59ad562b9aca7995577995b3ae9141d32de69c39849ba919c32aafb81a19b4ad91417b8d0c7a6e31c73ccfcb5e9639730e59e5551e418d3cf9d7e001d4ae0d6b0e19c0165aaca9bfdd1a9489013a53470925acaad062cdf6afa12182cd8b384a983313666a0e2941e1b2c44ace80262f207736566bc5c3597c2fbe5d776ff75dee72db6ab5857ee9208056f019ad4084c673d393e338d26884da416270d0dc8f8ed0a2049a337c45aa62402ecca009346ba56d2249a2082c5c2b9518ce201dd1a2044a85a181ece06278f406fea03d590f99d30179f22f955c5caaab0b5102bd0469b9800d747f6934a0c2f6dcd39cb0bdf71e28c2b0377b4227ebf69886084d1bc081b20049f2d6715cc76d1bc76d1ff729f1d1afd00fa37184c55aeb53adcb65b758ad7dd19a4df34b8a43206389556259608fb050b6ffc8099adfd4df68aa64a97065d0baec68a9a8956e96e6a187e1bfcb25f7065ad748077c5fb268d1ba682a5b57c9ba00b0ab8c8816adcbe5728d5b13742502b5e8c125fa47f4faa74a7c2f77cffde67ddfffbf95ae564f140a856a0d5998140f633f320fadccae3c2e238a6e35827971d1a2900b34350261727ed1daa554d2ff4141a62474a6a75a08f2101a906c19ffbcc1e1e4fcdef7795dd77df7e4e582e7dc0a0e20a5960818395151385bb246852ba8e0a15b93aa9ae60e1f0254754194163d7f8649063ddfa250a82c6ccc22b1f24c44bc1d3676a034da6ab55aad56cb5b396bfd7fbff396b7bce52d1a96c23044914005ac2654415e2081890aac50e97f219c72031c5450b81771b6931ea85e1805db9736d29364b66e243d0c0c284ed20b49e63d1289f4544592f9b67f1d8f3149d5e8c524765b9b58b05fc8e712d1752393548d6246a351cce8a96a341a9146a398a7aa18d2e8c567940079b17d7e120504a50525934152a677576b9d4cbcff613f53d625d383a1e78b25397e53648e1ef3fbf9645f4ce6783f56216d9c03c5cfcaf6ff64dfcf179b39be29f2867f319054681b83630d8ff4540bd568aa93d8d66ea8e6daa21dc7d48de2960a4b454dcd16433520d22603f2e46ffd01aeeac01d3cca9176128ff4e48fc731040a1a6bf85e7c2fa5f776e34802f2010e0e0e0ec5c1c1995bb43d1907c4c1c1b9257baf9d73562ca67071d921f48d3535b3a646e6d0a7518346103aefc83e4fb0f0efb30e74186544013a0f4df9f098c3a8bf324bb7e60b640caac89729da85271e72df6d5b7e3c5af070050fbddbd3c76ff0f8c453dee327ff2ae40f0a753a994c33332e2e40de7a814d29278c8a88d0e21cb7cc1cdc344dd133e3fb359546107aca79637b1d474d9f3ec7d115eac2677eadb556d408a8191e5c8cb3873d5fc6bd1763db79b59248ab4e87871eeb21d61200162af13729072de78dfa9d87f2c675de17023f14ca0bc3ee9f2b9542336b6dd6343308245c40aa09a56502984afc91142d8642339ad2e1a1d9bc6149704287ae8466215a141a7f68160a856837a8a3748b210c1b08045c95411c9add9c730643169c6d175528e59d046bb7e0db037ab7a0f7dcd1c34390011e8e9ac854f140992fc918128320222af93920843d41396fdc9b7368169a91c6ef08574d065b66b09af1e1e383a6729ecd5c32d95e6fe00f3ff9e723f4cc59e684baaebb0f98e5d9f6ed60c17e0b795f1286d09b0f1284d0e25cedd47ef878693082d0fb954e9a25206ff85f5314dbf7a40ffa50428baf80ffdf388e9b5c4f192f2f8f628e6043801bdbbfcb1eb47910e741b57a90932173241d22533b9486ed056bbbb459803cd1641361141e85cc91d34433bd1663801bf1bda048c19d39863cf90fc934202905fd0a2eec00c939db7a6f2b28e8e5e58da0bbb702992ea3a3444f5034db342788667bbe6886c53780131a86189600618c2858f440441720f8c1902a5a7c51a489162a989a174f64f16305184838913501230748acb89841e5ffff8fb10e500a6c9db981961bb43d1ed24ae79ca552ac3561bed033063deb159fd2aa542a95acb52514d8160e8d26a104fa53e3143b3c21810f230d06188801c492297cd0e28a142a7f148ebdd7a25062f4f0e941dd6949da03e0d870c864329963eb1f8f4c832fb6b29752b6006973a54dc807ba6644a98f6de17c6fbef9de7cf185c97a70394c19b1a0668840571b61a5a6528d0fb6cd676e31cc7675b7c94d2838d080a50ab281f885cf07d5f6307034aaa88270a0a4a703d8ed4610ae595a0dd770ed074d770a999eeaf740c1d2ac145d6c167cb3e05bb434ac45da34b145b4959accc12f716d33d9be7aa1453cbbe2ab15b6e226f0bc6a0375e8f4a05fc674b6d123a265f28723b827f327c8d987cea7ae3a0eac5c2d4d12a2e8104ab6a2068083d78a71758cb10b2ff9a188124564560090b30f8ae6075d6529b77aa66ff1937b1637c91c5ec515d2c65f0c61cb79cc4f3f6de5f4f922ca7b9186f7620d13bc973b44f323f41f13d14b9d1ef424c5f60ff1649508f4414fde9ba62a44f3c39305b954ac5851bd808d5041b9efe974208e8f403840c040903973038d596aee592e25428b3e6e1103614b2b3944d9d43d8be8351fa5cd148ddf6ef1b36c1a41e86aaded712919c7ec1225b1d1c2dcf469e6772f55a1ef1e859010d18b40219d88b33d4702e40ce374261a1fded3d0a0d0cd9587413cf42f12c231d1e4ff5eaa3c134d06691ed07de851f8defbc01e29d0938352f5e244fb8b389b6f2c10494a25a52924be58a2882c4a54e0854a0334e0c0e48a2f9e3c91c1bf9bdf8ebc7978244fec8828b60d0f77f8e0e1e111b30f1d7a7aa23dcb9e3225b14c810410141c60314209d5fc924c491d70b14a62072d56662d5091b660420921ca606141453597206309d0163aac7e604435bffebda00ed78239ef3522c3923982673e9b4d9c03eec13dbf6d1b49e650fc6e1a51e137409826731c3f0ab57150e6295d174dd1d0ad7b14b8f74021a010285748fe4daa28e8628416f10ccffce65af17089ce8fbf9b14c457f02c3f7e29dea0ebe2233341d05512d1433acf6f5ee8ec5cb684fe0bfdf75c6811b585f8a3424f33ff07cd045108819fb5b6561e26940bb4f81ffae83c10ec329e93e68df6b8a46c4f6c0ca16b6a027093318e49b72de38dab95e36ae57a5c526a6ae408c67167671c7fe5795e08b5710664ea817c3f93572cfdd6bd9bb77d14e9de7b0fecc0d72147f976d480df76e3b82de79c77b830b64933b7238010420fdaa2076d33d4799f94d7274d3a9073e137f029a2b8d7e26da3dbf6dcf6f4f3ba8d524a73deb82de76d0b6171eda044d39cb52e95fe293de2a3c37f7e3a1d728f9868717e2efb3c57fe14e8c989d84ef2ec61ae6032a1cd15abb5e2b1d6ea68815e3dcd8fa7a120d8fdd318c19224ae95aa03834011a99199aafb0d8c36930e14f2f4e42b6a64a6fadefb509b0b10a5a3d6fa1171ed40bf445fd2cf2394a1631a091f6fe579dea42981b65bf4be19cc1c72de9041e6f830a7915982816ec1f609c45ce91bb6ebb0fd4751e898afec1654c48062a5cad967685d3d1efecb16bd9a37feebadf55a6b75ac9ba14e5a27a594667d8dbcac5c823063b1582c16f3c9f93f0c51a8d116bfc6621e933127aa699fde7b572699f229d29538d9d8cc17fa825336a578e8311c9c982bf682b97c4e1031b1a50344b3fcb2eaa4c0af20b67fe7b3b2d582a33a0a4797c743bf366cffd14c195ab4612cb4313bb3341bb3b219830ec310bf5c70001800a106d50b9309263590b5e98396555849b6e8c92aac21db96558e046d59e5486dcba7ed6fcb2a47aafc9616880168cb2a318c3270065a561902dbe2c3a06595213ebb0a11d6965588acb46c5965050320ee5a04e48563fcc993bffc648d08bbae8c903953c4b4e69c739a6297e6def9f2940c6394948a1878642dcbeb4ab8c5f9c2c137e27ca242165bf40a9044f682d13d9f07dd33a439cb50d6644dd6646d2a8142fb4b050f81bc60356a555630d8aee56e1867bce1edf6b8b4888771dcd919474a69ceab5a79bc2ca14539fa0d0678644eaa8479f2fff112c612e8bcc55a018bef74f79d1b5e41c438d1b685b344d3afb44afbf22bc220e5c00ee1d9eb2c8cc26074aa808a625ffe0270629fd80ca93e2e3117247cf5cea3e716b5afb6fc982bd9aece59572b97d8125b24d1b242460d7ab22c91c2d481426fd2a6053ad393e76da394629dbcc4eaa083cc99ff03319e98610558585554d2891eac50a20452c08acc308974368ba4b5a0c9055ab43dbeabb5b5d6190d80bca03e967a54baf73a0e8344c73e11e8b1ce03fdc74f6ead9452d6ea811ef3f07e3c421ba55ecc43ffe942daf807200b2dce18bed34a173247ee9c3aff5d34b8866c8ea5e6af55885d41912b556babadd552ebe204c7076b2da594d65a5d3838d24847730e496fdeb8b921053e2a6b6dce261c334701e40d7f12a48d7ba82b5a943f285de512d66aad35a554ca8f0e12199abe0ab200c202592fea07a05429a5292b853cf9db2a6a15b43423a2a5ddcf826586b62863b1274cbe33761aa2db4681b6e4bcb9b5ba46cc4e4d4df4533a46107ab8a8aee427313b8cd7e78e4a28d582f22cde0836db081c37e347cfa77969fae208dbb970d5fc66cc32d2dac41863172782137d5db435572ed77585d7e63c8e738bdffc589339d46ef1b045533b1e4d7d9f5de21d293862960848b4dd027e22dc405fcc40b7464f435c9adf88d46fc43bbbb37be5baae92ebc2e2ce78467a1a434b95dde2e11d6750d1a2ddb2459041cfa735a092fed287359eed348875472bf474595ad342591e7aee759d54d117a1061d02290bdce23713b4218186e18e3f6891b6a8de27fcf3c5f2d045a0e175658bb4f6b252fce4ff43afb4a8c83223c88bdc3175ab00ba63132dca51033b37d78e5f70de08dbb6b9ee78c718d74c136b4ba539a70f70e0c08103070e1c38240d0e4fe2ef38644e48e6e030e3c19bd8f0a079c86db3022d4a19c6987e0e981fb3d2d424b3a7c9cb64e8ef04fb230f75573f9a0774e04461d4bff79449996c0a216b72678d3583b3a44d4d269b4a34b15d0a59ce39739bb4f16a10f323701472e93a4a7a21913e7b5e1763a2f15e867bd2c3a0eae676d92f2d65eabee4c95fe79c7fc4bc0c1844e6639e33fd188dbe9321c998687e945ee64b2005a2d95ee64b3ff3a49f0169509d0ea8648e97f5b45433120040100003150000180c088542c17050402698ce7b7714800b62723e74663c950764a1248a711805310c8348c600430030c410a39431aa0e20ebd607bd3235d551718c8aa92791d51b3be54e6dcab6564a94dce821a7fd53f80f076c7b64e10cf5019dd0de5573a176599c504a9dfeb5e62ca62e5f482ce307270933d5a21da101be627c56a7097015b953d3b49e8b140a4b2f20fce815ac2a70b1768bdcc4fc3e2853787c02fc7d0c86095c0e08877db08fe49f514f3aaec8fe9527b0b7fd8039db8c7adc4f075130ba2498ebc974c84c419a375a9fb8dfd9cf810c8dd635acfcba116e4e5737d3dd91b5e0ee93d7f1287e8d0199fee1f4bc3c0dc859b7ea4f7b40a118874aca4affb8b1082405d538f8f8e3118c9c4dc4a8a68564bb1445f0e877fd462829de885fb331b978d4011e56004a6fb6ff83f62814f70f77c5c04b50c5b54b7b2c5022962ab0aab4b2e6436bf7a2c0c250216fe5fa7f6bfb7bec15a934d021c11fe504aff1ca980e2c48208c5f8f88682879ecd26c3c9e28812444950071b1a334f32b9d4af095ed5c48f10131906dfeee4c30263a8ef9c803021367974c2ab3a7c89ac385d0a15182e7f1845ae7b05616251f6c4c1a2c32f2b032bacfaebb303a880e585badb46e0a5e8588211c46e4960a9569266f637fce04de89f95b574408d220c455718753177579f7e7531dd11a32a9f21879d99fb3e883f0c878108375246f11b79282210defef477cd7f68faf62b44f35623175db00766b193962464925bed1b3b671e386fddbf61eb64fcd921c57dfefb3ec213539f080fd8bcf2478841cb2b608035a07c6093b04e3d348330c6a2f6062f70c368621fbf78fc5257b00dc5463dfca2ac217f7708614cc68f671f6fa42cb4fe73057baa550cea9fd025ac4445c2430f623a487584376a99a181bb3b0c0225700a982f82eb30942e048f5c21a33511819add08b0fc284c89de26c4c813a293250888b8cb62f72f79049a85dbbc1136d83a7b26f10ed02d20045702de0228540c7af483db3a66b96b70462d93e94b59d6515444258d55a91b5b68145febf38d648e5388b16bef71fd0087d9f48091ef50cbef7c46cd3b3a275df9d29e52706b03bbf86ef3e88f734918bf5f6e4566bf81ec28fe4e8337f2ccc23b0a6d89052f4fff70f67aaa70d961f3f2e80f4b750160dabff91b840e6fcb0df681f77b37c1c32f8ceaadedde4481f85d3ccf80d54d137ad73935c232d5bef58b9d394d2bc874ec81925b0fdc000b2e1ada860988523eedddc00212c38281f60621662cc65aadaa735ce838b98e5181f5c391b54e3dbc2e562d24b498d428237469aba32eb847636938424a4404bb5b792f6eadfad80caa812710ade98b86019c7383966d8d3e47e2673d28c660aa09176c1acf454e2f38752b98907e3570709f4bb08058eeb56bfcc811f182e8dac7cda147e41330df2971509024ccbcf7f720505757436bca927bf17c5c4c4e89a34b0b052101fc96289fc1919ba1364f29aad3ff318caca9b79bd3137a602136b91d974f5546f728bd28ffbef288ea384ee50368d9e978a32eb651cb45f6504e21454ba75c548c65af592d8e19b1c44535000d52ba2929c344c70701c26410b44c84cb683f9c245cf8a2c58a110e83d2c8f4084d52216f58420b76b915851feab3772352e3aee768a20d199c1ecba30527810f1dc9a6fba7484646b4d553872bc34c39da78550f7d02a4f29b14ec12e52c1c5d147664bd990698cde7300b939ab862c663dee5d280d5b55f7b87912a992e3aa2548394a97a76104af37ab5f79348375d55c6773e3ae4b137b4ab6df723af12231b6f4c12635c4e7116e630be909de6fe7291d1db0c9583ea06275f5909af14200ea3c3d0e50b8b6646967355aeb2c01a491216bb99622d52c6ae1fdfc606043c0aeee245130df87ba135f8a82f3101e77cda6801c39d77325cdd9034ba5d01a5688461700d61631b2047c913539a92b7bcc243997d52c04baa49b70e84f2d85d9bda04879c441e995fef27eada4cfd8ab6dbb18fbb94869e55e621fe0b50134de830b11519c864d028492b785d75c0727373be8a8cc3722cbf4fe11f8a25b69dfdd82c42d9f80a2359ba2725aad1ce8e67805f8e5139efedcd78c3cd3150dcf1f0d9dc020b3a27367002f87569fff25521a7afff2594765716420856e1e4807fc9be1fdb6cb3ba666d1fc6c4240de60dbffe4cf342c6a2e289e0002c45d6abce4e44d01c0e2f621025ba97ec0505e4c9c876056f66254517d32d15f73955d69492ee1b19b893905add9dcc1bdfa72f114d3fe1931f812ef302199099f04dc4ae97b0298f8bb29b94ef8588e29f7dbc424305d1d9ba51e4bd1d3facd03a05d71d02576a463d86f71843bc517e8e4b820ec393ee44c51f5b17f4aa9116ac356180665945f84108fbf7aceeeff3c8ed342041c0995d06418015b83328c8d8b051edaed4d14d9750c02e44bc833ad6f2f307e7545fde814218c97ece6d6d2c6fcbd5a6d29f09db828cbd138128f655db813a3572de2663c6bfaccdcbb506a81899815e8563d2282a4468ec7f7a57d669b527f84bdd08902c60f390c31e671be7202ff5c808bba44f562e011d77bb83799e0c249501ecc54ee11e2897a96351ee994f54da41c51595d081d3f08ec53b962578d3fa355e722a0f233d1f383f9d6f227bc3d29623615fcc95c4d29f0e9aed8fc14dc7e00cc88fe4f63fec7e5d438ef18c77225dc1176f068bc9611a4cc703a1252e79a0b961f80cac8d000a99734c48ade9f4f82ac7b53047ee78da5f4f1a1828b7175dd7f27d7a71866143393c2f594b20ef443d7527378057de297279589a96e7b342e46c74de6a926092a1098cc022321e9f64a902800d66a1d50e19b333ab0df76f80acc828c3ca2a0f641449f959548c08c6aa81d6f4ff4fd28707a3cb8deeeccdb837b957dc9b4a6b73c7eb012ec1073d6220a5c9e829605d79f1e4046d8e58b08cbf2995198657a409202616a824c9d9c7dd900758bbd11e000e615ec3935d26b363b4eb814de83769c9acf8e5759eb75639532055315c73fdd47ccd241a5ccf3a712d350717b52b2a76869621e6f9532955c1e0a3b8ea44cd5a3ccc49b0ed7ce4e36381d92d113653664a86eab7ce2c19d97312dc5e88402f1a64699fde244d076b15512724e9d6e212b903225ba2ab1e06a2b9af1c9f623f4d86fe619ee03c893e3448311f6a601df9ebf3c90de6c663bdeda79e1093df0748162417d416645e20e4782844555e1e222af083478eca10809699b4c62e3226ff1ed8e642efd05af8df5884c34e63471898e2a04de251d2933e74734b9c47a66da294f3c92cb8b38d40367619a891ae8c0c07f1537815af3c0294238f0719f2d1f9eaf40d9e91f1b7122f645b0163826bfe31defc41d55412a3ed99753678560af0903cdf7c573c98caeb8d03d2425bb36b67295a6f359003bc635df091277d086fb123e4cc5da0037af61a95039c8ebc8ab653b3f3f5cb19b02984dc3549590971ffb09cf85a6e6e61144b550375cf74058325fe7492bc161b50932176f9f1aeab5c3c3763ccc2249e86ed3509e1c23ff5d1f1318ddd8e1f951a7acac710e9ae4bc2542833f376560c299a23d686bdc5d46809b1e3d161faeb1dd8170d1497cc4cd790ab63f1c77aa8af94dbc178133760726a7ec12d80ed42aecf0dcba234c878636ada9d910ad00992e98c7de892ef1d9a1a61afedcd4fe1a5ac6813fb86860040e41b809a4a6ac27a1b2375e1b1902a12a9f90396b26ad1c0602f1efb10ca28ef200d5a6cc6a5f1c46abd07a46fa32194ecef2af3ccc4e9c34b6cbd4b6b7caddc52632a40626f9e1eeaa4b6f3566dc60c28d0a51e7ef14d7b842584750a1336835345849845aebb13502bce76e90d255f007375cdcfef003fa4bff59757f89f9381c2d97518dbd440773f53b58d1ae6f08873cac8638a0f35c177cb124dcfa94d28d344dbdbe2d0134bc6da537db839f2220a9110575d734d2c3d2d76f9ee3fd7d13cee580c3164e1ddad4213a8bf746caa350ef31918a7c20a4906076e7221570591d1c5b40ac12d0a34792e61fb6c97c17074317d3b2f67cee3cecb69fa71fe87aca961c96359b00a6e8933cba4c0c42315ac6c857973a3cc79f7720ed68c0b19afcf5012b56b0bac5cfe6d197da2bf26fdfe385412cee4f1439c58da44dda452a757ee88b45aea1347e483864610efc352cd36baa6864f98a857470be1c09d7c8a217ea76aa0d92b351ac0d6c1bb5b22d38177e728543f8d170807b6ad0ebc9a8212f30460179d2fdbea56ba86647a48cf38c18feb5806959c8234611ef6e16b14b03af73659f6ccd02e29818f672d722090cfb944ef65891ca00fe0b2f4adff2ae227471ac727d139895c3622bf89a805a79f2a1ad6c83158ba0ca680d500116c80b32944b658c2c24d1903330e85c2e68a81235a99e83c34f075ddcbdbf262d89ea76dc642442ae62f639006fd86260121efa9628da89a04c9cd77955b259cea8041f5a73097151e82492d425d89362a7ee4a7d520ef2da71283df44faa5bbcd54198f5398f23c33ad461a484734f2910d6fbc1de9e3bc2d496970265770f46232b303abe4950e921789a8108ce67f260643046fee6e7429a9177b8adebc064ecd5cd46c2c3cfb7ad0e24b87da4566980b0ee4e828ba85bc6f7bd0870394a05b12f64d01ebbe3fd8b1e4100d60fb91eab520f829da82506e03d9b25164c910288541581e76c43e017f80163e55f39a6c60a32fbf8053862b5860706c9d6bbb426b34d3fbb9ffa64fe79a5f80da6b84dc707f9d525277e297913170237d5d42de2805b2c65f3a21c4a92b3341811eff7eb0c9f7321a4d5b21e6706c55c7e0407f4f103bcc37a34dc326a2027d6f7b5605765e138365310b00be8781a566aa93e3def246300502b9eb93c5dd9ccd572344c8bc8052d1c00cfa8de02b56e45fce2a10f8f39f12e302fdc93881d6fc766fc342551f737c9ac546ab6dbe9958040854531e165c153b9154d2a7ea827fc0fc33215de9af328069f891173d07173749a30aab5f31e2533a98248f0e0a1b99f5af29edb3eb70bd44186e5f53ea2d78a51fe611dd64e91eb17117439b8360d33f7f5005b8df42ed13097e1aad34adcb02f66c22d199018758cfd447eed3414bbdf68eaa96c0cd5520085a49e525160f98abf81d0edee5299f3dc6ac0a6d492bd9761ff7ba86145179eb869c80004f582d4df9d29ba41bd4d9b7dd3c7dbb098d6c5527faa3ce14621627da5f140b196876b65f6e1c6391866ef62dcdca14f10975bcec823bfa5e9c9c247efd2a22fa5a31b04f569e318b6ce64f7c134eb63fff8eaa4c153e30857c5973e49b21e3c883592c8afaecebd62cb85f065053e16d64c3cf97271bef7a9157038f4c669d7c7d794245f49b8adf82c4da7b21bda4ceeed1189561cf19b3ca6b9a3c60cd84d6560610eec72036120f7adc1b84986bb16a6003a265f9f25813c3af63fe0cc7cb48f29c6168b7e26a0b172a4235593e893879a90a8c567b5676569b414be3d8da9ec1c108228ad50779d0e233704a9e1135a40e563b280906726126b216ec3e8bda48a2b622eb69cbd01db3b742be3b49c05ec6d775a94eb5952488b08539773d44c7985bbc41eeedcef77c9b842a5e6eaa6c8175c8569926cb75b4a03502e82bcdadc387fe8c43d6884f3ead40d218fcaf4fb7bbfc8f5b8db261f327b521d365b6166eb0e2e55d0cdad3681f32a942c2e1bfc0d22e46f19c23783a2bcee008855c94cfa13fe543ccdf21cc0fe10450b20fb3ff079c1214ead10746c73fc1e10b345dd051348e3a2ca5c1507181b7a0c2db5e97d813bd6b6c3a178a6b0a51a9bdcd24b1772366c1f10544bd0da28c15f50bd6d09ce0171b72022cb8bb5af78a3c7e9b1b074135e1bb4e5e2b67fd0f01eb7500d0b9eb4486219e3033d66741319fe0bd4484e54f845a8155c7e8f1c87bda8cfa958c8d39ba4a4de062c3a17f4375c07801b682de69d8286acbc91ac943dd1edefa53466e6050dcbf50a1622de008614707086078b6d7d7927c798892fba63cedf29f27a9801e578433e1da7705295baae73673330d3af02d8bd37f678305bdfecb53747bf545b165165b92b42c5669c3ee3b4301e795c73722aa8f95c2012ec285d32ea34ee1e934fe76bd9a0112b56c36cd8d0a7a08485fa4cc8f6c2dbb495472150b5d154be1882fb25cc32e8adeb96a5c8a39098dab6aa613eb89d839afc9ad739ad6e92e897d5607445362288c2a1af27ef21b87debea04aac61c862ea3a7dfd6867d0669bf4d42b04363bb6313db7548e99f693cd9061e9fa55edbc96115148c57d3331819e2368c0eae571a4c0f82de830f6f60172ee9ffdd8b0b344a1693c5e8da02d755b581e43897598755aba64c48b49eb1984bdca17eaf94ee430236f636ae764811dc3aed210a782b20b3b91f4366d9eb648256c342a205c1e9ffad9e2d1e64cf7dbbfb1e76cf385c2c3fc095919979fb89317ab23d60da4f2468e141a0a1bff7de8a0e1571dcb401ca63a7c7b267c795942b6e8b38c88e37fe10f33c94cc5ac055df7ca5aaaf82f68a80ddc0378c49d12c088847baa8827413a1a245d5ea8d712a4a5258c54a38384441cd230302e3805ad928a9664f4c5bf527426560f2009a6b21ec914daa411e33a86397987a199dd07952e5f283f57726984e0e30e524a38bf4a6b5787835016677a185b673efe12b6c658e6f045409392356b118835450c72bd8729cffd9ac257cbfc5a584f1b44a1565e43bd7df63483da1dd2f2e482834bc38fad800be39ff127048af019812ffb853e5cab853f680d18f5a2833f92df0b4b95217b97c659a2c030b1429acafc793bbb884376c17d22f23409f0f08cf609f0b7bb232aa0466233c16a14fa5aaa8765b8b73188f51bb6a519e87d0cc06822e760c0c21552a95c85e22d8f7ec0bec1f11b93cf2c1e61c6f1a2396761383d8188ef0e8f66a1ac3ab6fb0e4400652e2e56630bc4c0df68df2929c8502dae36492705075f3181611a071dc9b58b37cf1806f0bd0ce7892f7da028c0c8c274b6f969a63bd654e7daa59bd5a1c21dad54262a013941b311ef0823eee6f1fce7f2e2e24a2dda5d7058a7c5ebc6c735c0c6354806329774411617227f683267bbf96741853cf6d4e5112520b30becd88c74c5e1f9420191a7f5f1d99f28f07e58803f0ad2a816fc9c4e4c155bdb74dcc6a93de49d47e7273d83b994720ac55f11cdc1e211118f9645d259dfd9e0ede232492d233ce49710da6d392708e8105a1a53065658a92ab8a21e4468638b5861932054aa35130307e05579eb392b8907e1b9b7c8122598067e61fd96e04964672be3c3bea0dc3e25a8233f757b8b1af88562362fd103b47d77e47824a05469ecf7057b1a68e6ccbc16d1a9563cd419988e4b0a8b4a1e6fe61e82cf6120b13966159b1017e61e19d2f81be5bc9bddfd12fa10078e0412a676356c57252fa0bc4583c458aec0e199a1ccd452cc7d294dea9dcb0c8d50cad4aeea71b7e0757856df4206b2fd80a956e73cb5e45679fad8be5541b16298f9723f16718e8b27473395cf253add944e5401ee3c02af10abf3615399e8674672117b3559e20805e95535ae1ee1ca6b9b45894035352e4f92fd9637afd907b868c4e48fa9ea87c2357cfd1dce2256f348605b41409a4bb2a0c0c744d8e04b18b4fbbc9a973c11d7ebc9c3478b4101459cc5f88f728cd4f4468bb189f5b41a4935248a9b54d96ff7b88c2a63ce119f6e54b6ccfcfc52ea121b5565df062c30a44dab26be53e2bbb89c4cbf67e6341e013b5ac8c268d626a2895bb87af4a45db5d143daf45019e7bb9bab3915ec79af5d48261bc6b2f07154048e51da648108c464b2973c031dd1efa4b17126a11959f65348ae60ffa57aaf9885520cc53ec5cd45bd24a4fcd9559cc7124ebddbae4c4a47ca895569bab687f2ce08e963f76d0a2bb8a290e681a9941b5d95da0546d50a220ac5c58330497fba3e055c92ac5e9ea47ba6fe2588620184a60c64586565f2656df23990cb2aa6905e416d6f03264f53630606c96f843d1be4bc16c70caa95e01f17bd609bd7c1c7134072ae9c9bb98c2f480afdf8704d4287a5578eb83fc54a75e4c9bd02072127df62f7a4abda593dab59a68201c9c62e7ca55c71583c6eac5f387a6798ef9ef4ffe20ed0fdbe9db2969e1238aa73c6572e5a041286db9b76a0840c06e0c9daecf7121ec0a7133564fc03978751ae4395fb536ad7a48a8dcad775c8931b7b514fe6d37b5877b04a2ad9b3bda5c65194b4f550abd733c0f03e7dacb3957702c3f135470ee7bf55398747d31f55ae875b8bcf00c885b23d92f090cc17d7bd65afe77e8a41a6832a824e41233cab1d1119165a00fc5494556d5ed03b80fe9ad0ffbef2ea0b830a430f9f8664c60c995401ae684e18f9851c7444566bc5b88e5b34dd4e581aff5cf93f4a11bcc9fa43ba0a4bbd111bb9624a582373b23cefb1a0507b779a4088afc2a630fbb9361161303c74a75af79b541ac8ec0ea6b88ff14aede1277ec8fdb44b26380b209b42e200da83d7da344ddda3f7388561df297138a0f6714c6f5e13d858f6313bfa7f9ce9ab111eefb31e6a776668f45eca2dfcaaec43df9aa9f003036a6fbf8aa54fa5d6b52d13d75d01d9bb8ea144c29cbacb304392177ec9231a0fddd5c66ea173decd092c6525a486f5ba6a219b7bf79f497d3deaca34c3d20d6c83e050dd829c01a66469f469822efd349d7fcbc4f920bb1683083dd8519d02da3135bd56134f49f07b9ea5f0bd04dbd065955fe9bbb329b971a4008089c523ee7bc5e7c7bbba9ee3c159d90156655ed1f69c8fe3f06430dfab5bac2216e2a9b091be77e89ffad8b7e1274c2eafeb8d78a4e05c75806a5df8918912af742ac66856092a41d398234506afedbfd92cbbd282ee1acc85ae53226c68a8498c894c479e4ec9d010b80124257636cf34caf56a16b5af5bceb3b7c6e189637c24f709847cb5dde39eb26287e590d0cb4a19f6ed4490502654a6179d1f24bf6f30d1c7b1a67d149cddaede626d1876a93b2d43988944615626eb4934181844bde9ea671970fd9f16df6d9d2ec7c4b0ec1e27c6acb830824f2b43bb8aaa416ce43142dce440eae2fe176a2aaf5e49ad2fd948a686471879614ddf4eef62e841d3bd030517d9db15532f0c4bd7257f88a81c18da23c17781d528a8cbbe1a40472195235fe950c8a1a3b65aa1b1ec8229565bacf9504b3ef32c69cfec62bed0712b9085919754c8d65535552a1a002c5eb8f180efcbb5051d855312e40f2eed3cdd68176629bd39aeb823b034f07d08004e8c482316f0be7dea02c5134dfc6779831026a0d324820a360c6b89bb4fd9bc8e2c70d4fe4bc9176a2e9f70508b91a6cbfd018697608c403334e3b8a05bd3cb0bdca30de368c07e79d9501804d9f996e3ecf9c78291980ab3808553c798da3ad71e0697eb0c9d6cbeaf3aa33f7c539ed989fd4a8e02e7229141849ee3015cfaf765961b16ca7ac7d73735dbd171bea3f94a601e375f5c1fd681436a2e76b065eba1fb22d655e484dd145d73337ca35f0fc2540bae22bad92d0dce064b1f9b268c72883819254d16c6ee533af5561d7b133e878d05a6d4ff9427d8d2033a65ab1472da760cb5e2fbf761a56470ca9e491aa955716cc59376947e1d3e177a3b422d1081c66fbfe0a09a2600e33f4d43af7b1e9fdf2174e2a681b374d2b94fbc7731999f06ca9a055bbabf71f5085279ae7e273dd343e3c2fc3979b19f9dbdd6ba5d5b1dc002b97007a7f63255a44afc920787053643bed61c86fc21c3d7ea9a215c23e9407001766204723f17a614137e6ac4c49efac158a9b6937a8b3b8349c96814c7cd3a423faa141127a4959493d9c4ac0afdbf36728d25546256f9ad12a9c86cf57f4cfb5419a699a84677e2d289102eb0eacc75272b47cbf61ff02f7aae149ac02eee6e486b90b2c913f7df049744f36ee9633495168325b0e38d2b14b69205d98dd70016bce1436cc1aacd2fd3a245c508718246d4df4d63223fed6b5c204554442d84282d50e7d3cf5d75bb55a09c73c03581c95b3e036faf30d1116a8693fcda75c77db6f49102e09acf88eb764da48fa67ecf4b3fa2c0aa5bb42da05375f7c3724eb718c330c8373743ccea1a5e27490d90f8b0c98203984e9055cb449c7398d3a4fcd95049413b4812762517e0e7f7a248e9bb62be08a45d4839d98b6429e8e05ed80db08bf80f4cf178b3cd01ec5f385aef04b3cfd8f3a651aa97551a5c68b5f22646cda147cb05491924084490d65aa62a8d40f35356a510258223431035b84639098d08ab7a32d1a64f3d3f52092c72a6bef56f3d77ef9f974a6fe2bbcb9074f7eb85f48a400d2f5f4990c440ac84dbc9d2014ff760de64e7c537d1db240e99dd1e8850eafd7147a3d0228379b92154b4626faa607c7aa83b57d89f2bf39a1b5379a49525b3e3f88f2afe5dd5e52e2fa340302ed00329d58d807262587da641b9d586dae10f1dadb6da2f45c5b29b2377c0f74f3482b1de578deace421fafdc45aea21b0fde70aaa371cb9206406d78316699c549048848a47136d36ef17bd47ba3cd2b7470b1c231d4183d61bb8f5a1fd203e38fa84a152265616809425a54b335495063a809e33284068535af81dc9ceb19afae83359442079cf5bbbcb74ac6680516451b0ed8f891a8dc1724fa5b7f950915592278385d4e5cb828f92920ba0097e7938034a2b3caee57c16e6d6bfcbc1a87209e03967e440fa185ee85fdde4a083354f164c427edd2274279f80e150f9b370401a960478c8381ff13bf157f10bc94f62815ca70c7c0ffd59e39ac7bb7ca572464396e186338ce88e8907f2792320585fd68afd45a8d8fea29aed3b9c81c1ffdecd6339ebdd2e159d4d727f3130fb68ec8bee94c70ecfe53813e60f591a9ae2ac2fee5aff1cb84824ce10778d903cc3de37725f36afcf9eccfba08701334310159ae0442ed416dfd51be8613bec3e8fcfe2912be7bffee29a0942418612d7f50675c2d24f30a14ae9c0eacd62a3911994ef8dd32cbfedd04de9e26b2b733025a4dd937fa2989ac36878bf5b4a72c150998393392390b1502e1a29a8ec8f5ff0c6366805bad9e3c0d97c80064eb2d5b955dee05a956605e0173d094fc591515398c146d42ad0f29f2647ba7873247cb4ba50316339c02a4a30325962e447ad2a512cd0473a367a79de61f4ec0a152c4b50b429a6f4f2aed888b04010330bf2511011fa451a25bd6c731cd2841d801175a5e8de3caa24f50cc43ddc862f83d33fcce8d4008ee055d2c3357562e4e1cf6ab38506d7232c66a293a1f4025f8e9a615856548824c69436bba9d79c14859f96f7d2c2d26b7aeef8efb4db4c55f2fd89ea498fe0aa9c10a61a1282ba54c10ccb46c144a714aeecd69e1f9ebec041e4e18fccce4bf02b4089fc67864fc18ee108231cb855aa524683d04e7c73b069427cf258fe7acd5196c32d2a6f66dd55151c3bd80b0549c0fdd462710b7abc45d141cc910782c10c855f590136ecacf1530fd635a70ae6943376f461a4fc2c786346d8a96f7a4ed1fc49515fb8ad65be388bc81f75d1bc07dfaec0c041d0def06bbce1a22d1f1df40b6680f0dc9c0e064c69b78b8ea2445362b4caabfa4ab12bbca983b8d83ecae9f5b76d5df3b21685b75df3efad88fd29d094daf9e63d237819353e0b2054e86bc1be658df7ab5099f2bbd607e7071e9c328f09ba43c8ff942b352ec013fb82961a465fc43025629e6f0154ea8025a8f9281b5e561dfa9b9873e517cb1153ac49e820eeed498036f71f35380e80162230085e427aecce36614951d6d8d56267acad80d6965d9f82c9932137e88d5cf7f6f67b0e197246172f91f4909a43f136e28fd49d942961ca30009c1a20e8abd753bdad12908454c4bde0efef65b12dc4e368b856e742c4b2979ea021f12d1d2e4cfe44d8822352f9367113ffe25fd6601e8b06b4985bae07bb69ce2c1b49eba02106f26408f1cc4a4164df582fd48a555d5245cf2a7fe5724577b6806bed037dfd6ed2750f06aed9d784e5a62c5390862f8847dd4eaf728f1bddaaf549dc8309b392c4eef8331d0e814642e73d22fc35c117cef534077d2b9477447f11e6ea6f8960f47196d07246f5e478623e3945d48e7853f688570fb016d4bb954094dd0982720c455b174a66303d41afce39ca28d5aba0e3e96d256e9f28baed12d9d16a47cdd9eb8787eeb95cd4c22d7b4fe9a6d3331d645304fc8038034b53585d2216617366d8275fd9aa7279012f45beb92812624430779cda7b7a0f333fa915045c2acf254de1f4906b17932716956ee6c032e47b61125edac4aff728789f439e58c08a2639645382799615d3ce2a66e5cd2a0d157e60d7d5260b6d992a69b3ff3d416f3fcc1a07199013431e092374dac69eaffea68c714137c1f802ae1dfcd2dd8a461b25b4fd409c2c49bad85f15792e5a012822dfe3e97ac41717f19ec810ea44d13195ed3fa393a9598483108a3a9fd1d59d16829ce669aac768ecfbb3e2097a4bb6fc869c5f02045d2b84f746a44cbd6a9180692e5575d0608ae6155e8736fad000a0dedaae147b8322d4ffe60e9e3f101daa7eb53b27fb03c0bd6571e53d06456797821e7e9cf3ee0f74e11d7ea0403fbc5c2a81a24f274f20be08143f356079a5234ec5f3e574785a1f0a1b20bd498e3546dfa2a30fc114cab7f92d1b68182c06f4cb05b7135e1e4d22e65d02c0b7f4413947f9330d5ae711edc7103213599e3fd86b8d9564fe63de4d0e5aa33b83a58806ce247c45ebdc43482435221f4b19e6eb94ef6a75e01a0ead12368b609a79c5da8c5bcd36988c5d461b8c93532888ba705e257d80c72aa8a7346c5a4a3a70eeae2f5144183d35dd6cf1b98560da315c26da50b40b1733aa005df964563af47af1a339fba68b08c2a79c6b3fe72e24ae3701111216b9109bd69602092b26509eb4e11671ee128b2c8d7a110f452303f6f8bed62ed2fbaeeb4702765ad25303f8223ace36fda70f87ec45719ee6fb14ebf6bf9546e4302a044500b24322999f2a1ef94141b1baa50aae07a02d66a4f3eb3bb5d63d771c205ffb6516e46e7380db0eb4ae4936101d538add84d5e71cf47dd097a9b7389cff9fa7302dc8b9637c8948a0c27e02f9dc08e8c3279c2dd5c6772af2e564c3c6359aea30cc4b4f870920d9e8cd0ec82544fef86eef5eda043aa1454c1d95bf5523af4c83c3540a44cde031cba846a7f039a7a568e546dd4a3b765a5eeacbfc2c8825ab437033c0c7224114db24a101180806442094a0a972aaba04b01f5220d154f5e0072222f2f0475fe228b2d6122c516443af8634ba505c9b87882efc79ca4644d7180fa08b78f6d2ea5d1dffd507f3074cefbe7c2b9f1209d436db68ed711a1c228ec4c47865adb8e91d12c85569518bc95db2a93fa548d49ea8aeada5be1ef5db2bf26ee41a9ce020a506c14d4ac54270217389c8150924efa1a621b278712074897e2fbfd427f9e24f9740640dc4591e490117fe0812a38c9c212ab3295d17cb0a22d2b1940c3915049225090e62beb7f0653a6b4c254bc1bdbdbc9e3bcc2c67395f444c72f1134ff75e7820ec5de3383a84822067a9b17428ae30dc2964854b2208e842c68f0bb5f35b88c2420bcd72f5b126fed5e54fb31445c6b4ea2854ca49864fb887cb932ca296a7b828be4a4918093709272e44166027eee670dfa2e24b9dd197f5da311b7ae1e0e44fb0548a19fa98504f53a3040a7526bc2211cc6c99ca4f176105d5e938efac5a561bda53e6132e2fea8bf854d858c54c43c1bfb3c89b3233e123b33a80982f3b1a5d028f868b122675d2ad163c180afdf34a5ace7c870c8c3071aee4271914792fc1798a6b53d4242da40e82e22170a326abe8ea05a4d55085466d052d2f35d0ffc8dc1af14a998ecb8a015dda554c9cfad2a4c821d2a6b888821a7011e9491e56af4e7e7167b1a2df1e016f46439386aae0cc36192b3dbf2ca953c07c99e89b7546f77ffd128f0247775f28f69667a86438e85e438780bfb08512a08c417165641fd2a06602b850518325d00425e5c6216ee448e0c9786d258424a9979ef6119046aa2ff3d2deffe899f616b1112485a5784f595932c4dd4989a327d55f712b2f98dc4ea2da8e3298946baa8356873a22d57e282003fbbfa556a4d96e4c2c46814e1a58833aed0939acffdc9017bf8434e3b1d01055de9845be3c13417fa9e4619c4c96e6b8d1a262756c1a54dd9a43d5e7a46a2064e144e192354939bf50607deae599356c6af7154b619ce06e525c57b7a9f2d21f9d018e300b5b5fba2eb31bfbb04a32114a83a27fe58219ddabd79046903006166090124dc13c7ec4e1e2a69e70f81002b1e03462bbd73f79d231199ebdf3d9dedf3c236494043fa87023c6506f6e42f5a714f7768c5baf6ef2937513871554ea05f19106bc34b0bf4b03c21f3737fa36dc88c1a66df506252fcd4dd61e4d4f182e5e76bd20fa3bfb2ef8e75c206905a8ad874f4b6e4bf40e9fbb41b785572e308193404e20b764f72699032fd9d06930d4fc49d2b6510bbefee9cf056ef290c835bde607910d8c216e11386f67d26314487c22660487355233c6c42e0213c5c45ce6e8679be87a7ea4e6ee0cc343b1603de47ee0b7c24a11e63129bf82d5fc8c30afbc41341002b687cbf854e45135698723626f6a6d8b6c36159e07a90051fca4d8aa3bf7fc4fd79df284c23cc478893b57a89e74aec937b00bad88d9b10525db93edd330152392e1e1fdb1aa83841b9c212b3754e87b38e8b4b8bbdd93200f854011f4e8ce8a2e2acc44009ad4172df784ea0c6cc298f24ad52df0230ee46cf984581cc8b1b365e90709f193b2e5797b0ee67676f3e09c8cc4ce163c5e4a8b0984215236b490d0440e0c140cc72fb652555f7a360ec882f8f0b7687daae36b1fb2f6fc4911e1bee4af5fb291660b640af442342053a1148bc7eba71bd6f0709b7f6db17392f5a0fe6df1f15470b21f761f13394b6484f9ce0fa2b948cd7da4e3b0605a8ab60b388bee517f2899d513d596dfad290a7c20d49cd43149ab14c70ab7fae7b8096d2934919b9a23a073ecb61a074e51332edc3cdb6371c3a0effa9463380ba486e113ccfe40a52fee338b123ce4f4a906bfd041704ff987306da8021479e2ececa9e2a132182f5b269d1cd4103ef1c40375583d2967a5918cf7036fa61cc04035da83327210d6bfdce687e3c020e8842c81287ba0666943404f73955f09fba46032fece186a2b8bea3e09ad5e3bb37ae59f940dd66bf4de5ef7f48aa98b8ec48ea62407ad87be29d45df0af873888fac2821bb47a2cd6d58bf4909a3a3974959af21fe1691a0ec011db276a979e7a0d224358788e559d5be6496596ad2df7efff83ff00b13c973e1b10e150cce6c1075fce00687a66b2923a012e8a550a7bc155b6820466a415dbff6fa964134406045b170ba4651bab35635c1db4777c05ca49b67224446a7046a43190c2347e3d7122544b68299e1caf638d509749d1686614ae6c80b37f8032aef12f6ee584fb8c25bdb3d6da6fec0e86b38c0b4450e57f6e6f9fe7baadd658ea168b78b3c14ad897bd9a2d561a02125f4a6f8b99d9352f4fd39ef6a8ba4e79695cb557e74f9de05c2a02a40489e18c0770ab38e56539be8a3f58cd0eb3e75bf71547661ab7c31d8ab4890d0efa0db58552a183ad3393f375f294134f735cd6f02d4a294a9f9eb8a4dd9ae2e368d689a69aadea891a1061f19370d0e4e34f4c59587e5db33767b46708f9e6359b4f4375f4bfa6830b49754c4833630d98a5d93d2b76f515176584bce76ad3a02bdbfff06e1813d881d7bab54c9ff04783841d480527fca1bb9336e407f4e6c7629406226dc426ada32f2071a6de80e7aa7fd45f926d24512dd930c1f83297324cacbcba139738cc9fb7ad030eabbf1c658298e3bfe3b83c3e1e30a94c3086fb4ecc83f954f0690102670e268489f7b8bb1acf0c04cda7ba025d0bbbcff294f72fbe9ea72b4ec6cc8ca3eed92a9f1eb438de1462758e046d60e79abb3038eac89b919bd20aa3c600d430f03335f8add1fb9ec0fa6a348fde3197c7464a17e8956eb3c647085af686c950d91e3852cda94c30d532a0a1d607e8e2df5e393bfec5203f457d0ed3faf7ac80b150ade4b0d9a071dbbe6e5b4008902112f0ad4f5660562f7cf259af996a984812825f89017d44373ee7e2bc92a614e102b170f5bbf23344b28f7fb1c4b53de845466d74852dca9ca0eb434935682c788916c8d84cf5197fa148b50fecc360089ec9c5b3d799eb0fdf459ad723b4b09b26102986797850fd6e5c5ff134f86a8da02be7024841c1d3e90ad3f9cf57db77375e2660e4888c554bcc287359202b7c092cbd0b7756d0aef29ab35ac0733106b3d9833bbe9d609a177a21e0e919acc2d954277a0b5d610868720a4787dc08808aa389da7818cf3337c629eab05059cf2798c557230bcdb1aee62d3d7787533e4bd30d2816adf984aa5a9ed9ec3676f5231c5ab31cce14a74fbf40fb28e1855cea16096d489c2276bab8af3e41e6589f354d88b1fff617fb4abd2e890516662a56d0e99539be48a3926d3e131ced9e8a5e69ab9b520a0a643e6c89e4bb5c7ea8157f2636637b996d7b128328c880d5964906d8076f1372c86faf3736e67884cc67dfa42ab0cd65ab343229744fe807b3d8ccae5d7b5fee044b4b2acbe613c17dfbf7edc7c2ae6200cb275d2d8786a91cbe3d27e1c9a3704a474bde95d8adcfd8bd22a59c21cc453fea6a7456af6c2cfc7f28574da7b99f81d9a0e259f4d65a147ecdf7e891c0fe282a2581bf4ca909c9740e6704f8921c9f19b4e236384eb7d5ea26e44d70738956c58c11c6042b9b108d25188978b12dcc816fd0d3ec3459e2d846721f226da00085c2508fcd0ebdd38c01a3befc08c261511c0179d47ef70fdf60cf169cde401ad3d6b30ac7d4feddd46aa54d0912683e417e29a9eeab31604264c9708aedfe53964609454e57080eaaf5646f8c0ce31c1815747ea2bf752d2ac1c7353f351d80d1d843dad213eded5a0114163c08ea0fe95826dd69811b02462dab1d37d9b134d8e61a8b4fcb679cb2a65f634459238c71f5b86b401f32ce4ab4f81a372328984cb48b677c380657d3d3a92515d8a2af0b3bb98bb57e8ad9af79fab0055cd98965767ce1d639bb624f89b4c9bc0b62517248df93ff9a782dc31a40aa133618693386aeb84461e5dc2d2361eebdf764ffbf9ce0dfd9bacb81cffc7fed089f96ef323d3a718ae876926052eb9e9cda42cef5451eae41d216a1f1d91bc6391a76928986f711cc3280b68afe1f4392bdd8a1a0db7b33ae3622346e6530739fb2499cb24daad5e4d871ef148df5215706f8709e489b1c1759e100dd2a0c275959e7509b024b0716d6fe5f33fb5d4ea687945f837feee7d7e688c2ab35c10bff7dd9d34ed1e14fad98694c8daf1456213c48ff9f16f5de12d0883478c783159f82128a839279f3c0809b98e12be76a54cb0c96c0d5189adccabd075c14c8d045d43a454fcaf60707703c8d4b7ebe5f84e8ac1029df4a2aa966bcf7112b2253d1316db8322450b352ba3f78e164bf16b94f9fdb598a0b01d5eff52d05d54df53c90bf6c720de73c50455a03d62d65326c62832dfb6e6a1434be9e32aca355b605245837d0a8e5f63781e7b3f75debd8cc5905a90d4f4b59f8a7439bc071b5d5aceaf9bc625797d76aec43fe67fabc95a5e7080d5d58d998317f68ff5800c14b766d3376c2a22520ee727a8ad8143dba789399fc494d1dcaca6f1af047092231ee5095dc6b1d528677cccf0fac6fddcd7e7b09505ca129608b01feb98125bdd7d31136283a76ada0bc6f06bb5f1b8ad1971610b41cc625d0f636138435f399a1f49d75378dfe0ca7b29101443476b872c48181fbc918c632470ef9531781a932a0a28770dd6f4140b3bbe6beef3f35558a6128976d16ad2bc474ec508e26d6976ecc59c1fbf3f45f456e2a1bb7701c8342397c34a9b9da4bfb740eb0bf318b9e57f6a9b5a5ecc059306adf4640de7fc94c237b77bd67a02d47904fe45ded690f99531154a68cb2f13b180e0d134f99ffd2d5a182c16938a4ba0f78f67c937ec722087b52ced58a37c0b803f42a9a9d0f8a922336166ab61096a2f73fdba32d369dd764f6ae798f76bfae663bb06a52ce0cb83c3137e87c1a5b3ea70ed5a4ef804daffe90283ee3622217b965cb0895cb6f8b0d38fedb8004f84a04140f59c3967aa563003f05f7a983f8c860b27a8781e5f19658ec125c6087937bf25e72ef32549a6843828b94f68c7068a084ab2fa8ddcf7792ed25a97ae64f71a1b999f66a8b81b7e6c4e8579e1d9f7a72c066800977a6059a210c684d1e3a1e368e8e83ccf8dc434c70637758c46288c9bed244e09e62531a50b227d7f2637049dbd6b26296d5c88ed5ed86007723c25c11e4b206bf9bbb1978d1dd5807d9acbb698611f66478ff28312f03246e270ec40898a26ef9ddb828c9de127f374a50044880c1b6960eca6c2de6c416b339e329ec63f022c0b5d629e8ba71acf77e7b716cacb6d691c97407934555ed8bc21b4be8f5cb90c9678837a7fff06a458380f1069a877d9aaa800d287c879199c3507274ed694e34aaf803b1d65b22bf43166dc37fa7e021c56b66399f675cd4442eb04af3d551dab581cddb768cec944f0087f94c996b06c2a8d32815389dbf532ccd50a5206a3cce97eb86c8ce8ed2104c4654ab1db3b3b2b8c688e1129594b169d195f0279e38540fe92dd203d5e919268045ebd5301940cdf8a0bb3e3dd9fbc7d45628ef6dfa7b1fb370513ca588cd10f2483e66f33a2f3fa25eae63e8e97b70bce0db2efaa5ded6857841e7965b4fc221dd8ecd2d6b3fe0625ba0cb8ff45119fc8bc7997ebbae51be2fbd61de4d2deaacc4ed868e5d29943afe2cae6ead5aabb3211efcd5261e7336b6f50e5c8ee09f6a5fd312c108429c151da96ebb4d4bcc8f7125e8565709666372c85b26e59a085c87558357a1c80344faa06c4b081631416dc64e1f219ce7dc588fb653c1ae4bb20da2ace4826cd120990058903ae0bd6ca84de534ab96eb2cbab2498fc11bc1cda4d31968a325c9c56e444ba20e171be37d5374b300d17e4b09f9cda8aff3651e43451d9b69e44aaaba50d47f21c225437040fc76988c4b69c3cf051b44678aa5d3300ee2c8084a3b0c47a6fbfdac8ed808f7d7494c55c241d3fbf945e79cdec1c1313b1a69e4c088dafe9540dfcfda9184ec8eedbc892e3b89b2401e3d54008d6887239a9626f886c95f3f8436769e1329ecac033b24e1a1936f28c37f3e7dc538c19268b761e60df6439c6d7a6eebffc0572d992e46e1febb82126149c15416ca1a11904366109102f293e2e65e7f0579de10f9940f0d8a3014e2d5713ad12270d5ee6b9317c6373e561d27eae04deea4bf3654f82dd3725f6764acf42bb7e0ebc30eec7c9007377f970f22d113b14cd58ea92f452603cafaff8e4c69a319137d6fa331ff8b238f9065a10ea35da0ea4bf3037c8372dec0252964dd6029bdc339ceb5805f3d08dd529cd68e5641c203187188f73e14585b9864de54718c3d5a7a3d7bf11e9c7714e463a444bec9d3c37879acbf953fa74162201b4cf128dadbb23e35907cc30b77217af6f2cccf1c5bc61573328cc314a3583dae9d994c23d7e06345572cb86bbacc0e1896f662a108dc19f7eaae4605603df340e01db59418d91a52a9a882b4aa6ba84d50d15cc46363ddd1ec1968818289dd03314b517c65a56efcb906858c2c565176d5a266d09403fde40d7ba8dbc221f0dc8890ca247dd53705e8d6973f580ab4abcbe5407fa5f891a99d05a9fd4480653e9beab2ff5c581f1c76d26115dc7c52699bede9a84f0e6afb897175313ede3c4753a6bff6a21fcd44c7eba37ee9235a7722bad4ef86790fb53a4950386deb399d9bb3b1376a0d94fd40bc2df0c8f8abc446f78bcf2f85655cdd64fa7d4d195572a61db5fbad944c4ecc48b57014e167afd4dd9703d2d0c152d5714e818fbb97e69400d3bb1853515575cf6bb88ea954a903125f41e27b393cd531bb21e76e4cad82744935ee46990c328ea9173e816d5034e32414eca8231cc2cfea3ebdbb01562c982d52265cfdd764dde54884a42817a58ce683f0cacc1410c2523121ca28f20df29477b33aa00556af5d4ebaa4db8a98edf82aac26f7d45fe78f641c25c49c8eae831e22d5cdeee0e8c852351c92dac8453072863a9ae280b005a1020e9b9d547d1077d0d69683868ed8af520499f291f1c9174b7b6ecc69e9ef594b24825e499684b247fad9e1b7a3a7d221bc399da37825c95c41956f7784030ee13db9e1ae02c8b752151504de7906234c74bc184c913e700ba922bbf3d28d8ee234d2455ac1eaa270d14001368e558229916c0e0eea8e41f6adeb81c7af267d63736507f090521dd2565f68542aa86d0f3d84f045a178f83e4a52f11cbbdca8376a43e48ccca8f4a154decf1c425fcb9ce5bb1e16afe09c5871bfe3ce72099e86495143f8abe4e7b333cc191f13cb17675aac42eaa0a9f06b49f056f5f15c3d419b3d57f68b81b53132a9cf4475bcc145e3a403910f1e5d27ee3aa34567c2e86cd3a3fe60fd6a6cdf74bf7b58ac0ca6ea34b53a801fb11a400e3d4539ba7c7ae808e3dbce0a180fa644336e79d262690b404fc537f170eb2742d4291aa9d7cf8d549fa7da8cb0dc9b922570da1f7e3fc6763688810ebb203d675b9cd0cb570d5abc930c4f5299ce294732ef213820666e327349432d8084feeb9cf37541dfe09728b9d641a2de0def843ea87b5be8be64ebb99f75db72b1126f38d452f85898e0e4f79dfa58897891064ad2d4811401482998295c4da114bb95b1b08baa72cca35888e6950c16d8140d13da9c5da8d1158b1005dfd043b6513855371a13a2aeb02bc6ebe50e0ccc2797a3e51c5d227ab135c78753dcfcec24ebfd8a6a0b0f8ab104e3c1f107523b064a2e566704a741874738d5bb2dd292354e208ef20792f71bda3ec05bd6c64de40255aaa89e3644eb85bd2e1b30f035ed1042a3085d25ec2fad5f256e11167a31385b4a70ea1203cc4b5562b8eeafb4cb87dbb0d13574aad2eee5dc8965c29559b38ce53cae58949054502d2384084fdea675e56f73ec6209a993715603866062f5dec4903ceb38c5127633d9aee5d4e6caa0f1e8c7de72583316428fae38592618f2727199a36aaea3c2f3b0139316cb86c64af7ac226600ff63d71b8767f811d2bc86ea498a389a3a41422a0e75550e12c47dff341c3d23431a5c56a188cf3cbb9110411bf4442a04e0619f0cec11d6410b6d13e1b33163422b80e10a651e772688da8af68576f73a9e0ad3e14e537b1e1f0f5dfd84f8c03d9a75aa8932107fefee5a6f8e422a1790627b81b2fb3c03d3e9849c793359e408e09bdd0360fa3f55812f801b0d35fe839de120e0b76576818f5514b4aad745865369e49b3c8d2d212a211ada4ff96f98bc74475d4f408912d412c5906341e4a0111fd7bafa648b3f097ef7dda6d7151deaa0136cd335de7e49183cd283aa330eeb09cd01757ffd28781290c5f92d9132fa73bf42d7ae09ba32b30431a5d00afd85775b4228102c90d5d71d08509e370b37eb879bde7dee30d1863a1df493339c3f41f11a6d0a775afda29bdab2683b39a1c4c4b4fc3cbbbfac7aaf9ed601fd7c408a0d9f018b9e9e5c7b2b6f61e9b0bcf91d5aca4e0df3ac6f869a46a5537743b050c7eecf43c13d6342ebcf2fd69070ddbd0a94a5abb7ae9794850bd7b35ff822c3d9d15a146d66c27b5c996c36b4ab3363f67c43c9850813be3a3c4337fbb7e51c2259830eb14bf758c66bcf81ac2df8ae6dc86165845f6176f782e8c9aef91e1eecb01235f025442210318bbadc05a2b47b8146e012f7753fdcd9f20920f6e86a740c6d2b6bb960107b4301970db1756bee7c36dbc9f90f01d29a88ebcb33f520afd390a0503d2d3c3c92808ff9cef03d3fdeeae84a08a2b94f33564470b3a5e334635692b621ef170b3a1c105656e6fdb128ba70977c699b38e09cda2b7a348737bcb2fdcf733b083da653be2c34802650c647f909638a45654517d7b20ac2e8e914214d438f100828bd34017975721157d9ebffa545e18d474c5b52a33ec758c4d2661a46e99174064522cb242f65682ea9162c4c933cb8faab73ae869ccb2c92bf6882a1698a04245ba59a449fff117831bae4ea280fd39c458ac8f3452dc288ccaecd4a5c04fdf375c4ac0e828460838c7ce416e08741660bdb20773a481170b138e2e3eb1c8c02117cdedc5b96b64d80f77631ab1b5962e5f02cfcf9a4fd72066079a4a0cc6419bf115b1ca3a5a6f674da7ead0eba9a49e22d5ba537bd52090e47e529e2d66318b120d9ab158f3735839be1c58b5eda40a078b8545617fe254172cbbeedb117b5e757738e0e62f2a022e8fa3b97010ea1272782371b9f86fe4791736bb642b55e9d4ddb96fbd16c23a37532acf2af85c6302bec0d72ef8c2433067b6bbeb7bc83112fb4914c194f119780074e568f7048366fab700addb8b72d9364998cd7c735103a540ae543387a791653c81f598b287e302ebe204bf4aaf4dd6d76bd485ab822ac5e46abe2ea8006640284ae648e939fe8aac161fb360524fe827093644de162808d9fd14f72fd522f0ada81f694a798b4c57242de1e4df4c85036815bd78c0f58882faf4041837614faaf270f20971bcca4d652024b6a15586218803d18e15391d921113087e452eb079642214df6992922db3729dbdd5234255e9be0e11a99ea04f66dfb25159a12895ed1549c70d48cc8aa9ea4290ff7dd552049c67b81b0f28ac6df1a375cdfd411c6e834a146cf6279c80af7920cd22e5c3c1bfe55500294b2fe71f275c5732d37fe5b95b2faaccd1b4519b0785338886631bd45c28978175daf953cb8bc6008013f536f330c66524392afabb6438b6cbb1d2ee6bfc84e87a50882c483bec8d0546720f10bf8d0a030a2e9bd53a851b167582b1f2e3e5248f13975300dfa2873402dd56fece6e82746b78bafcc364145c871953510f36bf4a2f250ccf96da2f297dad300637a2687cb929a6bb00c6d7fdee7e9d93725babb9752c38ecc69de9d02722f131314ade9b7ca86b838e4feafcdb052440b61e5a524d636b37511a38b0213d783289835ecc4e1f86d6524e5c893ec0904cc7f59915b2e45670cb29c11f675fd0983f894ecfbee05df59943259f160f2036dc5d10ae4225b896181b110af612bc2463fc2b1c77d9763c56cda92fae19990ff8c6168a8f6d4cb03413a4a286c6518ea34c44e672385f845c3689843e229ee2141e4e62fc69cc084c55fba55a7434e0c01cc163aab7ed0ced3ee1b9882a75fa61faa6b8400b65bea8104300775344c08874b919405598aad29e7a63f8db532402a99e1cbf73f58009303fbcf6c4dc4094be7d8eaa2e45a7385343fcd37d4a16d09605cf4c733730ad1e17be26120149b8780ac058d9ffd452a91737d033029cd17237fd42985edabc89097857e9c1a22daf8b53a7c639c280912e0651f766cb0bfe424026b78fd9631431eb5b2bf142356e7f9af199d512c7372fccb793d7abf747eafb287d2b73c45f8fa5919d5be9f0e8f7437a9f5e7c24a443da67b49c180c3a1bfcd772e15c300281d33dddb252e0ca61ea6362fbdde01158dbcd41c7d2a1f07f0f7a4d1ac42bd83af7c30d16cef0679a847019934a7899a2c3e44081150dfa66cb7829772a51d22e1f0e2895f2b7811d4f6d97a83d60814f7467c09cf20cfe18a5c5ce83626b571c0d501a1145fc1f0c4d587755f424976423df5881f7a840112c1e17e70aca484b4cd3b8140af7b48bf9c088299340b0edf2c5dd2d2d2f891c636c12807b56c5a1868b3869b46684c1f61232549357c471496d09bd809549146fae886287f61039c973862bdaac4b0d3292c585e2a0a267acf757220ec4f069bcc95088a070a74812398b476f99ce514d42fb377391055e2f5f9562513a645e81ea234965cb1549bef3b1c006d815649e0759c8d17268ec20e4760a54c0281259f05a834308425a77726ed5e94bd877ad517121269a0ebddf51b4e4481600f6c4edce636b22dcc1ca201520b5192c26897269b2d35ca837856a93da56f40585fcbe5d147bdc1730ca10b7aea24b7aa42791eefdcd81f4b61c58281d21590ad9347a60836623b784cb13f82838142cee91e630b487912ea717fa84c9012467dc5ac7b9389f7ef467e9c9f5c4d18f60298c3b9a5017523989c3dbed73cb0b74402cd92e98cea67556f52cf4403dedb412a45acaa1159b33a52f38b646b2364112769110eabf2705056ab6d24d2d6eb41584ce73569c83971335b65554178ab4e5f2d2ce1e91901126314312debcec1bc826f7bff39caa18e65af03227217cf69ce01e5941e64db04212712d18fc7cbb8eec7c98905271042d1a50618b1b2cdc44cc581a40c6c2b77a0f6cfbef19a1fe81a75a2ee2a890123240acbe06f527505a3f7003602fd6d77014d8759b2eea6edaeb451772075e0bb7b3704915216a68423fc35b208ba8cade1e54f579bb33182ce357e6cae01dd2ad886794fc8d9ac6321361d62e320468ed70dbc502c3934b4ba06cf7ee8c1227e690ea69922cb32c2d71aec1a13f91c1b6c237307c84dbb3d98ee108c8565a225114ca87e5dd101d7d090991a0eba9fcdc107a9e4a9d89a01d8c8d2c43dab804d02e21f74abc90345a729bf98278b0d2e347eb712129af33907d9fdfa44cdf4063c9c58c96b12e99c37aba1b6fdb016e45062eb40739b8e1f12194e2f3317813481e6ab3bd8eb4d230ecdb22a9ab3a53bdcebeda612c05bebb53d6702879d93ded5cc6fba1b59a0c755cc830d969b8c9abb821ab6f4349e6911deb577670f8a8b063b589746092bddceebc79e94bccc548ad8b8cb4c76b08f1074b1c5ae1f97c9a06be85be71251460ef758cba438c0d01db0467e505e9adfaf7f9d7e18d7123fc96c001011689a8f2c0389c15f573134db0ecc36509e832afc99578148019b872c1568420c77c301846431abac7ca217e009356d79a31383476bd43c53b20e9f9a2cc0640782988470e64073699871401e65233d50c703d7469a7fb0c220cdcc2586ec6a6107b7d127fef1b8bf6a65e4cf225cca96330d712d13950964840bbb5687cf4a2bec9027e04c929bc8e01a19b8e53f4e0c43fc6a761193b42e780467bbc2fa9ca0365a696ec2db3bc41697c722b817075a2a073ca567b503c33d728d2e9a557549b31a2069f98e3027e332573e0a8d0a38aa6d0d0f1d6b3d5435ccdaba2f88cccc5866fcad3396fa85895270aeade9d7c8842d603e1660102ef1c6cfb9690d01b6604c96285ec2ddae5896b0cf10fb9426fc13c8842cbd7c73adb130df7b60294e4af7395b08539bca9b92995043b3905582af7e44d9858757950f1941c1bda5dce6eed838f6c65ee6a16280a95380fcbb726e3eb6141112247b7fec17e45d1b5bceeeb9e843222fede24a209b9aeeba2590beb884220538c06ee61a263ce277a024f2a27f68053f4980ff49ef93e76cc3aaa75ca35983a780a3f5346ac772b606f071d20a4aeb9456e9f1570058a0b430acd1b3796d71ebd6422da3221e15bdf508e2fc20069fcb120ae2511dd44161c5f917961106e76a2e4a48613d80c6c0c45862838388c7c95d224a88a863fc0bfecbe768c98bfa45fabc814ad80a79a92f6de4b51c99c6ca47710f24c05b10bc841b4eee2193a0df2fefcb54559b6cb9e0d44a6c5c7e9e3e9bb82935a1e2a09be458ad04c1fa83473fbbb66ed9a6c832de9cea211b6a0281b45d1ac0d89b67a02624ac83e17f1cc2baef319a36fbe6f82e3147c2ba4678fc503d2c25570ce43cc72d87851f436f33e212f199dafce14f473ffabecd10e549a587d8667cf472644dc421b540c0198268744b88abb06acea4e2815152f407557c79bfc3675584c3c15e70727d069d5191abba359af0438bdca519cee58f9cafeb83497fb2568ea58f1137d0637f68acae3e79a4ccac94924f76834e8c260e54b5836705f328e298c0aebef05c99dff94dfe8d38a318c709365e05a324f5bb7eab9e3efb41787e52c2c536095f32c3592737570ae4538c41f88a4d1a6398e54b6a090f7d88723299d2e5716a54db126b42a97bc6da366dc75d90a5c88097394c01b95c3e013cad048a70c3b05b30d2a29a0e4a3aafa070053e978671bcec4694b50d395beae8fa1cf56dd4990cdf3a2c24b84081e259e5c92cd1f63a5b61a208100c83e8f5999f9a2be1b6bcf2f15a1cac82aac5dff7668165a01a2b624837b2db9adc524a99a40cd90aae0a0e0ba947bdf7305f65ed5969e552aaefbe9c424bc951f955ca21223af9fd2ec55b91b40e7998dec764f2bc0f870eb14a8a4a8aca0a8b8d254c6c7aa231a74f578babc5dbe5367d89ee3dd91dcbd321cbef273fbecb0d971beee297c794d99e7ed91f0fb43a964807d7a60c8737d7799de7811ecba328708858e3bd256289388b0d5f51f114ec28698d7828cfd33befb3463a246289bc69624164459459202024dfaeb23a58c9ea746ca6f8743e73783a36411c3abcc14b293b5d0a11b993722425a8f39c2224738c7cbbd449214a014a198a9f6dac59f59f92620d8bcb0d67b95a5acebde77d5527e6988e83a7facc9d9feec34f9fbe52017ef9c1e1a2004fee02f25fbe2c7f5833bac46eb8ecb8dc68b9787cd68c4a412e976769a4c55b2e108c1de2a58ff5ddf013cb0a5652ca293bb14393cb7c4c6fa6a4245171a292d4a1dbb48f29933fadf2c40393727854967454a0ecacf47ca358983f41acd4e14e87ed799d5b1eab83e30867aba3633b5367f293cabbee744d9ee77376d3519e2d915bb799f633a156e85426533fea2ac557fbbd8ed58832abd3af769d1dbe3d013e3847a5efc1d91259a28e998ed492142df1bc35addb9cb4109ffccd42513265bbf46d13049c2d914dd232aca4b4e47ee7320646b9c933567aac447309037b3e2751c7e209cc79bcd461bb47fb7693ceb7a3527652b0528afaacf1dcf4cdf7fa4d9e0bd157b7691c620db5ee7dd964f2cf334b8a184e221d4e1c306e1d8729fb40ac341d54b2d6b1d2bbd2e3f860fca2c01873786ed3263fb9cdf438afa8152cf803f58264410b58f0dcfd0a461e224b34e46a0040a12ebdfbd1b3f7113712ad37274a9d4f8d8706a7a5a3531a349d269efa09c8b3a5552855a92e75cc76772335714105e24cb63692ed496dcaeaad22d120c6aa0eba5a3d9938ab837a43aa4a9e57e4c32fbba65e7f2b2fbbeaf5d76af9b51ab45e77bb6c10487f0d42cc41bdbb9dc9ebcf7bd99dbcfe545e769dd7dfeae5774249b0f3bcfe4e2f3b94273feabd1453a90a25e6a08e7ad9de21a52da99221e55eca55a99453ea26d870bdcd17f5d477eb90f660f9fdfa57aca96608c0fa906b9e12e1a9e713bede62505ebd9d804e3777a94a393c3f46806c50bd591ddb637d2c506d09d4b1ec3141401ed3b1c64caa9529741e39d3c97ab516c4b2e34c276b2b779b520f4f26ea1700724fdec9fb5631078b2ca1bda797dba15aea9582243c95340dcb7597568fde716e3f12c2e740bc62b938eeb2ac779d1058d7c32b97c778d34d6eafdb56f50ceba4b436e9828cf2953ee92a659ee9ed87faac4ecb57cf058d18a57bacb6564b931fbf7d3ad63fd2635e7d94d99c7e51cfde2a529f3687463b8179753f9a85d90177763ea9b70ae5ab4afdea01674bd38935d56927f4f568be80c0883b4f6d9d0f1dcfd3cec7f3698aa77e1a8a35ed94baa5756c67ca5ad5518e33931e51ee813d529ea7409c99b4491d7b42a58c38f0a2460eb511295dca97920598bf4146f1a47a6b599cd5a5a7965693ba821163758c930433c5010e80de04669a0fddfb2eea1b83baa5d524e9d4724dfe16bdfc56df99acf8ee6484d0cb6fe5bbce935f4b7a091ffb1be61ab49f1e991481e4239322cef8ce83810f0c76505e75f282235fc11b6e3e032c0f247586ca072f3fef3bcce453bccaa4a7d6b2be7ace3b150f052fbfd3772b9eb4de456f1553a976263d50bcfc506f755015f46c4e8749a0dc00d4003506786a004b5bb5c41afb019708660b82a74e5bbea5e5ed1029f687a72d4f693107f5ef088c3ba4a8cfab9656ab9f863a5aad5e3f8fabdee238eb3ab23a3d16c812b1462ccdfad8204a2dd153e76c1dea18a5d48a2193d44fba8757b757b4a87d7b2a45c5a3af3aa60a512cbc48782cbe512c842f83e85bfa993e88ba54441d1e29522de9b01e4155a19390cf49a8fa4c59dda93bd5a7f3ac1ae26c4fc77275e9dc4ef5fe5c77beabd79d8e4df9a61bf37c36a59d0d10b8f314b72b36210f1cfd4c21c59a14c79e1a4a01576c9de72a3463f02a96219fe30eea50ace9cac34b1e6238f13724f4edb20ad529aad037d29b9c76e0e853ee82c69c472aefe4877da6a478c7771102ceaaa18e495751a98c101de9581255916a49c724a8226a954f754465e44bf95449544528d5100d778e7295c953df8f3af49ea3bed6c9e37bf64fa6bb62b93a540da986ba257a4d55b450afb6eb3833ea35c9a5739cc9afdf586ba2f48806ea3ea8f3a03e43f8913a1733042cd63020e6a04edd04ea61147dd182a73978ead9004fbf23b0cc0a700e5f565aacb1f1d4eb51ac894fad447ae9d25bb536eb4629ad4fb7d879ea91d2a35a0fadd55440b500b241a9ce53af0da34e7da663568ca7617cf6621002547dd015599f145927095f3f9395b238318ef2cd9ad3fec41c2288397a091b857de2dbb3cb0fd6a104adcf4b542a8a35479608cbd3615b9f23d40dbf7341035beba3fa30120e3c4474332a7545f808095bcf5d510f58c75a0838c360a816605ec5f202675863a4eaf3e5f927306319442638e902f27357945955461ed6e411d6c4265b12bfcf0f91a06fafd6c7fa589fefa2a2149a6906247c742a533059f96a8f2916d7df8f15083c5dae684270bd81eaa8e85b75b44a00133c3dd7a25b51ac599994620d8bea68be3a76328a61c74e451d76f55621d19391eac84f456006a5eda9fd766b8476d1c5981a59df56ca6ef8b439c1284b6052c6ce472640e0f9027c64424693cf928784efe867faa194c69843b2f0fae94d847317e59b665abf3432050b465982f58c59087f823664008a0682d0c435503ec021502e2e4438bea56e72ebf9c7046042c0d4fb7f9c6a4f1d023470f1ed51666bd12289321e7daa59a3ef04f8e0dcdd5e39ddede790c927e8a3c30efcd161bce990490d885c024a1b21e0e9d9d66252ac59c51a966ff7b1e25ef22861f952e72fe7f30354ab79b435905842b29484c774440dc90f12a24e1a2d4122062f28c1d04c0713183d44b3222d05e00091d16f4779b4ecc433c37ce9373d4839d4a6c5672f55c4185f0491cf118a6ca48ec92cf3d2656ea26e2293de841e4c830f1e33c8eeb6d1d0b23a7e2d81adc3fa255d4a09837d6d9b2b34d2007e80a58c33d912ff8c22c55977a7f0987551cef828a10a0c9bd1d131f983970e4377cb70c6105668b102152831213b61c81746d0e0a1490f473776ace5316e42cf110dd27d48e731038d89b9d203a66dad9c1cc782d13ada298acd66b3c56c5346ad4b152970aed4549dc41aae08ad2463819e6b0f72fdc1d313aad361f3f9e968a61c84f1e2ae876f73dc1d82b3f3521a6b11cca63ed57aa25f159a7306fd00f5e907e3956b0401cce69cf109d00f93aa0408547c9644c6f8510284a094943b3f35982c31c03bf2a7431d9ce50ef501abb1485815ed88aff67b31b6110467b9e3f31d5b790257cf247cbbe5388ebb3e3f384a9cd169f211fec69858628d990e750b20bf9452da4d3dd337bf15ee10154b68575d6f0d4c135df5812e6c00d960628437a974f4e05c6db7da620de7240d0c25de27d27305e3dbab17310509ead0a1c38644b5504fb713948e99bc9f7c52c7b84fbedb4ed53665b556abd96ab65aabb55aabb593ad87785d8f8fcd6603c814d42d431973d898c336c7dd304c43e8cee963ca6e775212f53b512bc80ea0c344fdeaf0919414c618c650ae0485aff00c137cc4b85c93e326c755221f506a4a42a95bad9d8a33834b43e77e80e7fae0c3dd648c4c7e7574faf6b852bac59b924c21f572ca68543e3f06cea9db8d8686c5a29ead592223d4778d52094d393b35c4e41125839c996e9926d3b04eefe4b30b8953d2b971b71ba5b439a536799b4c263095bacd396b85194a0921e4b9e79ef7018ef2c0ce7f788f4281b94fa7d3e974728b3aa94c28e7509ee23a581a18e59ce7d50250600d9cb3ea1723d3e18e8f470fd081b0e7d9236a0157d5aa1e5bd35d9debfac98154571af8fabdf282524806a9e4af3a6672e92c170acc27b78e02f3c94d2e512c9cbce34c40ea731e7f4a2129dd65410954001e240a6704a1054c00b1032a8066b22646104f4c7044e4036acca4571a0fa5d348f77008b747d4b90cc1249081735cf252ca1e40e84f67e2a5c75a8ac0b565c396057fc4b7417e8c4b2fa5b72881b34b107611c2adeaf25d4680bd6574263df4aeccb9e99076820de292a43b5d8c716102b7a6cb5fc9e82cae8a605e8732fc61e58958f30316800b3c2a5796c0b99ffc93d87d9357745d6c8e75432d6769647528047b1dae7c045d10a1c1120d96ac6ee044064d64a05464bbeefa0de738b3ce2425cf743bdd9abc47e726976e026f8a9cc01b13d89227bfe93a3739ce4c7a9d4b9fd347c3d9306573f29853fecca09f92abb5e996675249a9e469198b2da8fe7479e428c94f8f530afd9444b5a29f4ea3e431bdc79c3b60b043261faad71eab8b7c5a3aab6536805e051b85e98835d9d48621c68d14888c8e7a8ce9a49437c004e12b89e2b4f58309c217944af3153d9c2fe972a96531de9cde79c9eae99f9754f6bcf46e201e6c6c48e6ababd0b1a82409edeb92aee598af49743ec3901c7dd681bfc836ee5805c257fad15ba01f25184f29318420a943d80fb85667cd70cabc1944273b55094db0741a1b10ef6dcf73cea9246f20d3f8e9d27f649024e214a434b765cf204738b74c519070517780b98f4a90d46c54d801036661efa31224463e8747b196050b7e08c30749ca98e286880f33a8e248075fec24e13da162c9906992c4104b98008c309c08019116216041953be4f01b86848a1d284172826fbfdd352548964022240d7a4513eacd273fdd156be277372bc678a334416cfd80e9929e07d22f7ba82fbd9652d6a674d68f764879f8d59c93fb8cf3d187599b7e656573deaa633dbbfbfa9c1c67e76571d65eea93ae565efcecbd9c35be355f0ae2bc4703e9cde913eceb9efca427636c59eff76a8b036f68a15da05fc11bb20e3fddbe7c9bc61d84ce75c41c52a6f8e0b06530fdd20ea78f00059e9ebd5ca9b55e1b08cbaa76ce39adcb0e25a53d813081971e3f182470fce17a69abad3f5c2f5d9ad1b9e43c82b7434c690bcd571cfae898a3b70e6d4926a48f3eaddf28bb6ec1cc7195e3bc82b5f98a7ebf883bc68193bb9cc33edf8f5a3c077b7a068e9e579646a3d1a0cce6e461e950a5e851d63ef3159d7ab4699d2eba949c4b2b4d2e4fd28f7ca6b50e5d46e02c6b3fa3e9569fb6466c03ce9336693f387a9e343ab1e822a55e673a8c968215d661750ec4b5ead03d47b0f32c4de35187f32cb1632d60a62d2d3c3a64b180f9c70d971bd2da8fc20c81ab5327a1086759c653bfc1c2625b5afce62526bd75f716b0078cbff80b78d3d26225ce9d3277e9d23bff70662fdfcbe75f44add04213b2ee0d25087e20ece7bbf6fc8bb397d802667cc3596eb41783e2a42e4117afac2fcba1fca3fa912518347172c5128a6281f3956561b9e12c2c6e33652c0e63c3c55b2d073dcedcb3bf74b5c016035efc7319dc4130071877ffc01c8af48071f71c70f88bc7d90bcc06f87d36f365dd3fd87c5987f960f3c5e22f9fcd34cfc272d9e22c2d2c2c5f75d697f15b1bd6e2fc44b1bc637d15b5028b7fcb8bcb0d67913e2abee2feb5acea06d8b2200bb2860458e53430fe3975697b71ea92baa4ee381cf40c2b02bf148f287a3bb4200eebd65f3e0df4dff068d3281650dee22c5f8bdff8f2cddf68f9327d16972cf076c8d2b5907216ab05cc3842dfe2d6fa6571e944be931e8bb758dc1d67f6e22e37401e39381cc65b2c608b012feedee3c51dbc2972c36f70802d16c799b9dc001dbc81015b2c208f1c1f29345fd45f1c67f602b280354e60d03f8f71bf29d2c31d87df14e9f1e2ee37457a8ce02f1ee70b06bc29d203c663c09b191c077853a4070e87016f7c80fe02deec982fea2380493e9e6391e798e4710603b21c84cd17cbe3ec05f4f962798e4a0c88b31cf09338cff296ef47447ac9627dd5593e93df387917512c60be7916d84b7ff1ee45eacc17c5fe63601c0ee31fceec8a23dfb587e3c399c17c3833ffe44ce28001e37cbd7c7136adc959bece575f966f035cfdca97a593a7aef26579047ff9beea4b7de075d497bf7cf31d088255de5afa4608bcf77a6b7762a13a975364d6e84aa572aaf26ef5f97ce51f342f3da216703b44b9c43dd8555454babbdf44c34befef935256b06337e1942f7baf026d7ae5b90af4d487571d6801993f813554e7bc5e535f6f99cf3d668316907909d670fd8231a1d721f51715587af5ead9955961c7ae530ad20e61b8ed52173980a3122b6edf450fe0a8e4086d4aafa78c5e0fec2a0caa1c3b066f30ca4b812d06ace4e08132e4a002a6c4190573b43dcecbd3a922c905705126e726ca5ae1f00c5cc1fc23223d0563f37054d3278240512b620c23762006921a0b8488a090628c2044927cb0417c760c9d9a24694815cb5062051353ca4725562079eea3122b8ec498574cf1e9311d4b016193d216645e767e0259f759a1b7773bebbbf1b17c36beae3f5687d46146707bc6f45b39ce2c656515fec953c07c7dbe4ebed211e9309c8e0202ceb14806cd39a3f4f1b13d75980c4be995929eae6ce0305fb52d640af229751bdfea8b71e58bb1e82f0e53c606159f0e43cb6c388baf348b8d6fc77cadc0d9a8dcb5cfd451ed1295f24ea6a4a4a4a4b84bea285739c6790aa4be0aac5bc81250b00e512850a6c31dd3947fc0e2bd5f8e4b56ff24ff9091999147b84f5af44cf4c053679a51a27cc7b227bf5fa743478752a660bd7a94329bf9fa017ef52f70f53c43b3820559334a94990ab4a1c6098c72cf559ee245522957798f94abc09b22359592c27196721c25ca2cce543278ae027dbeaedb7494286f3365edf182d34fdf0fd8d3eb204c103d20790ab3d65ab799d77fc0de9a6aa8ef9e3ce538b3ee3a0a6c9dc0937be04d911378e3f9cd7594e3cc6ca689fa9df4bd057447f8bdd54375ddf5529ddfebb09087b37080be73d529eb70fbce55dc8d1cba26b0e5c2f56e8795d6e460eade7d19766d66077bceef674da7fbc1886886bebb3a7f5df575b7f3ccfadb5dbf9d5f577d9df4fbfdc904847e5fec44bf778a6fed9b3c4720e31c799b71927819c4e4363d5b2e608f0b3ca344f9bc9ace72750cc7f465f04dfe030472ddf465a9f3f7ad75f2368bb72613f51a6f98547ef747547bfd808c93d21863a4534a4a9974d25afbc5a65ec3c0d461c079ea281728e84d193b25ab6c1b1839324a628424a9ecce6e856225c1322a3e5809911e3ec77c4b29654c8e897987b5561a5aa6b2f90032697a7e2a2d154d1a6966502c2aa9edfca48931464943236d38bf2e43bb047390de7ec11c8af490de397026d86c314a601edc0c53d68aa0758ecbc15e8fb3f899be70bee6b44de73e9bf99a289a0ea7bb9c6d991881912d8ef454c943a3d186cca4db948eeb7285e901abf88adb9830aa2fd7c3712b475c0071aa5896b92ac0304fdfc10459b98acbb0721550061b2e69f3c52347c5573ca25a0c507116efa1e22c2ebf1c722822411a549c058cf375af09ccd7e4281083f3a640f91d98f1d753d2143a20928216d8f85a66ab2fce246a458527d6d868da292dd36d994016fa4d2d4bb9f9f811652932c706cf9baebcdfbeeafe887215602ee5ab5f754a6faaf66a43df9ec360de173ecdca601c06f47fbde752c0c0803c260a15ac8f1e92e7753e915a269b36259a53f4d4e3ce533a979e52da534a799ebaf7c520e4e78bc18726b658cc0ae1e9bdf70ad10ba81cc87d15ef8074ce9deebdf7769e5fceb3a1431c688ecb08dc49419eec3c4f305a4021cf6508ee514ff5d631937b2ea174ccbae752492e75ac730fcc55a84506034e21d90bd8492da25e72d5725c8a9eb680473d1348082ab88af07ce8339e4d4ef79ba19364803de73c1baeeb9c3ca53db83a4d6cd7790bf4bbeb9d5fcfa977ded7b25133709e4815fc1a3cb0c579e79e9fc01607be209168b4e79c02381ae940f9eb9d0467134ae5d0199509dc7975ef400dc8cfa7ebf5e321b94e5df7bace73ae7a9e9fbcebbaaeeb3cce4f9e73d7797438c30268a0e1ebf1eb0f1f8d7a68f2f49172b475f2a9910f3f4fa7f79ee7790bf4bd4eea58eb85ce3df7c01aae77e00c1d52a72e98fcbac96fe702dee490d40324662e37375a60940417b31b188f28195afed27d5d44f568f1229ddfd60b26effc012d7fe9fcf479eefa8a74ce7d8d62e17ad749940b2617ae5f9728173cbfde59d40c32b4b8cb7bb4fcc523ea012dee026f5c5c873e22891fcc5c6ed31a9857becb7773038b1344b1cd60401d547a20c6cce52fdf8de7c5ec46070ac5cc05163179903a2b62bde56b6d81a99b3e1c3aa4ce83074f651329bea84f1d44598bd309460bd849f3824927209473bcd2e1afeca4be9df4f42710096be00944f3e48733719d73ef3d367127ce4fa7dad42f28511ef6ebdd07d6c0f975aeebc0ec79fe21f327e764f7755dc511face6dfa640199af60eef11d5883e779eef1553a9865debb1763164be8c20081f3443add7b6ff49ccbf4f344ca15fc21f3d7397002c94e80b314ea72bc75d7e5b506ce13a86329a73e835ae6e2b163f4652d38c7c55b52a7947b2bf92b4f29d279cb17c467455cac16bfacaee5b258ce9970be39ee5ef73aaff703527f82730893dbcc667db1c31b5e4d36dd62c32578dd66def8327d16b06dac3ce52e5f4ecb0ab480ccaf8035a43cc555be0b48e7fc54bd937b9e075a40e62f58c3c92f386dd349ca1773027c3de5294a533865f2940ab79623709e48b349a5913c53c60304ff497ee79ebb2cc19de78994c3894487b8e06f488b9b3e2924691dcb710163dfe897c267805842cc413df5d9744869a66c36e997ac05012da014ea17f53c9f3c75126ef807751a26d0b119e4a3337941dde9c45170da93df7befbd5647cb728a9c3c88cf8adc1308cb323dbe73981d1c3b8c1dde6f8252e8fb21f326500ee500f3e8d1086871ea3340405605f69cf389d4b15c63f074024da12e70cb37937a3ae9907a4369f1ebf422a0059c4dfa756ba589d42195b4db24620375202a7f28094a387bd46792938ee51f348f349b746c4787b68e5d50053a919e529a89481a0ac1d23b1ccff33c10ccd7399726fb6d397b64a30de003893fbaadd6d276b52c0040ae6387170317ca054b62f4123a6590185d8cc934d65b6fa5392693775de7b17a2e23701775b87c1dd42fcee56739eab64a9a8d0af7729ecb75e1bc3b9d6ebdf5ba4d535f5529e5aa5beee22d3758408f20487324389528cd05b8813af68269e8af73de412d9b368f071687711e6ef80bcbdd7968711c1e7970f1cf7968b9cb6ddae6298e111c67e6eea0f77007bd3a88c347006f46701c7e03ba3e07bd87cb47f0cf417ff95ad5631c6706f3b52ad862008cbf78f597178f016f5ad5f17c7137ad0a5ea0478c03c01b10673977be38071d00e0cd0d001c00609c2fce637066308e33f3381b610430ce4010e6fb70e4971d88fdfbe1c0b83e9c59445dced621e73041e00972be023ba8438ef3950fd5403044601e4aa3391d3b798a7776e53a5df9fc32f8179c6e3357a0ca57befc037cea534505cfd5caa2565899b3da58d958f95cb9cd5c7d9eaf7c32afe22a608adbcc94cfe4f8537da9af7bdcd41db8f35c873994d621e77408b879a68cd2fac571d26509a6ceb9fcfa5e8ea643e5ad3ba77552ae23707c5973faa97ea7438efbba04cee1739c7cd221572fa551de94963ae4501ffdbad29479fda2ceb94ca2ce717ea5b73e59fbe27cb548677d71be6ec4f9aa511e8ca36a98d8f506297b5a0bdee830b30ce0661664f9c8c3e7ab8f563d40797dcbb02da41f8d820031a9439f65be55464176f09926465b8c75298d65d8e4fc7e4cd007904859328c83db205301ce3288170d67162ba4e12648dd06e1e900a4a8c227670925487082d904f20117459624497a810aa6df3827d0bdb54f0b49f07b80dbe767e26b2a0dd18e084da529ebbc9daabc33a5519e0bd0cf4d448dfc6d4e97608641f5797cc517f55c46e017268c07eac31eab566ee8bb87aa12587ae686bcd6d9edf2766d361c1943a0c962e218d143133288a01c1931c2250a2fd41041101143a4600b5b0bbc2dc8f8c286859204044584706504d199a66e4293c59dd1c6c51c91623ccae1f936ca39a26d321f8d7670f2f8a3d10e4c4e48c418639c9f0a88a6a3e8624b5a777cf5fe32cd3715c0d3d753991c19f6349fa7d34f664ae9f4894365379192b375d2eaddb04c1853065e75d878842666123aa2d319bff8735a1db1a676281db0199a8e4dc7f42508336101a9cfe3eb3aeaa33cbcee641a62f2f90d617957e095734dad388221a1e2080ec91430484d284e78d105120b7ec862073857404146115ca421c60f0a2c1a2968d064714d9e3d230741ac21c50c867e08426896c3ef3098a0608b275bc8008bda2cc3525002ef68071beb63582e67b9fc8ca218c4c00659202d1d8133451557b4a00a1aeca084892e38272a4a021c2b5a4002237888b400028d9803244c20460dcac841171f9022050130a3730c4d11809ee5218a882eac8d745a6a4bb2965e8ed28e72d5a957b0063acfc0713a994e2f7732791df8c1626867dec2f0d4bb90c2789c3e1c5fd64d9fa5818bb2a6c4a475175d17e3ed58a6f68bd3ed9c94eaf00dce213d95064433c22089153915091485a2bb78a28b28beddf359d3647177c0e0003282e8e0054d82708312cc322ec210f6f6383b22e0e2a70647d4d01941f75149117ae09ab83e2a591ae306934ed2faa86449682ef9ac3e2a59ca8952088e4ad480825d3e2a51030731560009e9ac9689d66be708ed31363bb84f850ee5910fd366470b2a803b7080ef47256a143d974590182e402c7688e182aad031f9ed4ad4b8a259cefaa8440d24be7e54a246cf67d810643e59fda22bb0564234705efd8a83df2bb1267678fde4b565d775de42fcce71fe661aec69fae9c3f93987689b373fd0c926702bfae9bd6f45301a0d01848f46434001422aba011314ca38ba01cd064d1050a7cbea3c3aac0e4b034f9735481fa2e333138f1d2d43e01d33d0e8e8b07ef261e041c3043ad696da7458dd4e6be91d1aa3c7d239e79c6ed3611938a6baab63acbfad7b7dec00526badb5c6a5cb755b90857609c2c22f308d8e5a1d8535b0053390969ebde7e1a6441a9a6930a12195451c1cc174ec50428439eb8d084284aa2333a4f81c6b6940f91c97bcfc53a9923fcbf81cd34294527e0330f2d3e104ea704eda7c4db7e9962103e7f0e76c3a2c8c350178f93dc0942ef958b323e6901e3387a680a9a48e0e27cd844da129243bcedb8412639c13a8c3391304eb700255a1ca537d826093086c0acd29f4d32bcc66078cc68bdb4f289634f13322a163466fd84c944921e20b96bd0e36fdde0c06d147253d203d013e2a01c3873fd5ae7e35e9667d9c15939e34a5599faa549f5428a99a948b96fca44af549bf66d25caa499446693589b37149dc118734974c9fecf9e9b0c3e971926765099c6b524df2e9d7f4599bacd993474e6f5510ae8e7b5aa60a7da8c3698dfcb4c99e7ecd68ab493c1dcee93cd487d2a80e0d733e913c2630df3b39b02681b70e674a0c3f0c4dafd33deea6e2a28b31ae2c3fe5285ff954be942f461a1e0566ce81d44f79ea93284e86850cb46740c328b0f0e8db65666831eac30638df7bef2da3eb1cafa4e74170f67a3c2f3e7f38778ee4bc3d7bbd63c50fe792a7773aecde894ce0ecac1896eb26050b36c35a812b26cec88aa201a689208c089c59b22a7d8521d5d5af66c160713543e7172b108a018c144243580c0d19112262a466029ce950fb0011e908e1949f9a1115d46e4e88906e3c984ce087116699719329c03419bdac33b014c2354a816793a443082cc1b504f8032788418307273f78d7c1c232e1bd3cdf2ea58c5f7c0cc84781089cab9252c7a257ef9b93b9259f29cba94a0860e9ec54a5ba6473ac4bd40aab0e33ab2ef5ab9598c0b977a8ce4c5a1ad569409c55a5dc3ba6bc81f88a77f60ecfeaf258185c14f8d0e2550367576d892a88c4099b2a174081b317c4c8112f42ed04459c07f159115a2d06ef8d36f37af29b325c342b3a3ae10520c039d68608d2b14d800a24b963028f0c22610832fff0de358f626e8a0886e80d5c3e4d199946c70e2a7ebe1d062654d25813c1160ba7975508e7583491fa863bb8bd291891073de21449df4ebd98b05d32ea50c107dc43b08ed6118600e799191a5b0f4c31ae298c7cbb87924746596b489d2613765c77099c5d352764aecc50d1b7c368661a8576f0079c2f0a9d23beface64628e367dfb094e603f41099cef1f0581d2cb92c2c9b7bb622e653965d14b592e168bb2288ba2006796ecc6970c7d862583635e3706527c670a4483a29114404d443e81330592350f4b66864787881013c59295cc142708c1f9fa60bd8893389d9bdc178f628cfac4a83a5b15bc21877a82162166d19e6449f483c8d2b7dba0647b1652bfa20267b984a846d4592e398a4e56b23370f63c6c23c24be2612772e4db63642cf6dcf33cc6555ae0ec55e0ec1e23d333adc389e45cca2a82b337f3d325c1988a83cc5bbf710bdc4e82109cbd34702865b49ee74d5f0a62021f1b7ed4925427408002cdcc10387b302238c312009b2981916fc72e5c0185126cc707305b1138944c749e71549ab488c4809882fc8925b4c7964b7c7b1e002ac4f7b27e82a211143a42df493f917c963f9289280be38bba07663984464af14d53f08dc50038798398cff30c311ffd2378c3cd4f2965fc9aba7c3abfaead0e8464e88d36d84c9d78b2e89d537ae52ad04fcf61e8670e4664edf9ca594b3d2c02675a80251cd64ed3ee616d92000fb38634f976574c0d7b2cf7564ac062b1d27019020a2d2f6859633504e8db5949c8d0fb44135939ea7845595ae08ca98f004528e38401e725e8910067fc981a3d2134e373b5c0656419c44b9a5d5996872d0dcc9394dbc1f9c690e78b95134491a3dde4a75d2265a7bac90e9b300bfc1252b3699af6eea2cf0620383af522d7237d6b28414b2c670b3bc42bea784531ad74d222e04cbf1e9135947eb57bde6ae572c5c4c8c8cccca024d8b71b9e353a0b5252eb2cc89f3d478ae2b7ea7009dc9e2967bb5f9490afb70ad2f97696cf89427b01b4c0f9c29800e79594a00e749080c9f4e9e191cd070db66f9fc0132c057084a5872c1a6030c9ea155626f0e049a027a2784810180110be74061a78c099c20ce119a6cc756b2166c966a542134eb0276792c0d98399024f1a73543a832682ac4f223fbdc6395f681c2292862d880267fa8e032023dc9cb45a9f93ba9521120c530467fa3e91c8143351f4ed2b97fd300b09ec853c18b284ad56c677c76a4b1049b284b33799991829ab65cdcab2699a59ebb06807b708e16c8b2612f1d5dec41114738aef8cbfe9d349f345002f70bef86f32a0de97906342eff6ed98156b30fc52d2d60baab70113e14ac00c8d2bacc90b002a70d846ac2819af5822a07dbb2b064700fc803d8cf1259d7a2fc1d5e71b9a102a8456e9a7e8db63649a26bd355b131c6225bef3355ff3058022a0ff4ca2cba99eec69147e80c0d9ab4138378fd4699f9e1e1e267e787a7a7e7a7c8048003484aed24829250aed0420024f100a3cc20f9e09a70cf30c0db67dfbca05055ef5abbd5d982584f3cc0ccd6caa4484a2845011ea417c763dc6b4941cc7711cc7494981dc340aedaa17e04c5b9ec099d282e87282f8f46914801a8576500767dc42023c654a5dc189a78f0d9a40d3e767067d7b370023b89b76eba48cfbd63730b7d24f1a2d4f9f7acb41039c6d9067877c304a42e7db2f0ee2b3fa794d6780fb46a3d1809821e142e2474aefca992370be66dca4cf2c560a4cb0f418eae8d09c7cb74ea3d05ed3853423851a900067499b4d04080e73c618638c52c6e9d52b0884b68c00e70825d208453a5919f9d064ad94dacc3a25edc3e1064887ede4caa4ebc99b139d9cc598962670963a4b9fbdef20bebd958c8e903d1e6b0498e65f4b3a50173b80a3d1113b7149343222c9cb1585c9486983427b4c0ecef7852286fa1589708d55e4472152bfe20b45d8fa65d3310801ea982925861014755d0c427e6627bd6e62fbf831f860eb5864a253f4f1533108f9e958eb049576b28a25a210824c167d860e1a2c98d18c28702002ea4dda1a2a1032a39f4c16b3ae224089a423b3ce62f18310b38ef3748461c60766ddf56000e5895977bd8864872b9a9855fac57c114f0760c10e7698d12fe68bee16a3a763ab550096c0392669cf9e0a71464727835934d650d54393911039dfb567b231ab558738dfc7a11d0ad1c92670fc485d2c21381a8500cae75514e2a18b1e6324907ca263364fc7f264e2a54b9f3d1db343f014ec0a677c66088afc30c41b8500e8b30c8ce6a58e8f73f6fda5a629c51cb26df3755fca6e9df98a2efdc61adb3cedf39108dd05daabd3be3fcf9359daf7d7f2bc3fb6775dd7755dcd3f56363352aebbf7defc63c5c5d8f909753dc618633cf94549153570eea321232400e12c87961c69590c02110e863c61021fb2f86216cb30d2c58e114a5cf1248c5996495ec6d8349942e7d2bbd6495a26a12c894b1a045226a9902fe9a7938a8a8b0b080a4000279cf0b969349fe5d0cba6c9215982fc8670efb42ce5d24320706e9d3e7dadf3c53645bf3f5aeec42c7d7222573ffad9d0210e1dde504bc49eb3e5a3cb185b4e2f210a2ca7aca293fe2f65a2c0511aa06354d801c38e29f34eb1430fbc37a4a1f387fd6cf8804cd9bd76de6779057d9c7005962a47e01c06499de9324a389cf14edb958707bd1763162b4687d944f7648d26647928e951865e155846d9612a05eebc7569c5cfa75c48b11c67967a800d67f11e379c750394600f1b2bb761897c44ad2017703d45b5e22ac718a752296f217eca71dea6a4f8ca8a0ace4b1595a7a8dc66e28f76684aa5be4fc211b23f22129e27cf4d5726a52f149d44920406d2e8071e263b3821f2d173c0e42308a45f7a0c832841104c9c3e1a055144103b4ba827b5c9e9c81a01510382880342e802210253ca472320764e42968c8408e1a57b9d173f2321647842bc403579e9de54a283b1819025498c7cbe443e1a09f9f9ecbd91909eef3e1a09f1618ac07bce2808a28f46412479e971842efa8d1b481b59f42a8a39026a44f53e1a0df1c34bef6cf7d14808ce4808345eae7c3412c2f6d23b939110472d174e1c781e3a181960e9d1730918ede43cf7d18888a18f4644007d74fbd18888249ee5a3111139df804e3681551f8d840892f1a95d5773c6cc09baab89f0f4e4e8a86081775a366f4bb126526ff1b95125990e512b5039e78c3748fa03c443959672d80053a73add4b5289e65328d6dca66c3ae9179d3ed8a713aad321dde9900798ea7c431141ac699d2993ddb5f7722e1aa5d11e22ce4ed9bce9dc564c80a353aaf3d17053afca9f2d43e02c956a8d712551edb6656d75aa4379e80f1532723bf2947a54fa4c89d0214a446b4fddd656ea589e4e6ed427143a6f2dc8ef08e5b3cc71d2b1a8c40c1e5e004f3d4bda53181138cfc8cac0d9f5140535a4924ec71a6ca1d5de390dc6eed941210ddc394a4b1dabf488a58c941876843a8cff7af9b33567af78628cf107dac718638c31cece2e57ec24a531d1a78b312779a21d06a88aa8444d3576492c95a281000000000314002020100a064442c1703c20d3335df80114000b8aa64e78549809a4248831858c2180103040000040000004b37103ee0050510152ab06c334aa23d61a64546111202742d4ca06e3cfaac7a90344a8f04212d80820e20f4ee00126ae7d959e5b2c0de2c4a99fcfc2af6d2bc199a74a112ceba66362a4c6692c2b464700285e1b5d2c5caa73e1fc2b447c31b8025c30e11d78ce88e77b68876188c5100625c7b37dc2f8ef21c7b3d7efe63ce4144600e2c0b128f45960a10407781735813125f7025d69533fd841f2141cdcf403707a14ecaa26f3673b7ca4a6f1738fdce599ff8b605585e5d5bbf431e98375945d3a542a263c214840501aa76284d45218498c0bbc25d9db88a4c4e42e7370c88cb609ab9e6425353864c51d250e9f711dd3909008baae98d7747ad8a04073f0770f6d39c05b8359b9e6c009b0808199b5a985fe988c654613e662fab8053de07659379d31e6c20a8f5995c9da06e6ce0449decb1e5cb54d17c5c6a5be6da08cd6f42a841a772ac762bd011b71b5f2c0603d4bf2489691e9613efe665c634c2afc9c7f3e1fbdff9471c6d2947208ec35e9bf1823b90e219e0dd02c9a9d4832958a43d9be00395ef5fd04966a95bf49ea63fad357b79f70bf321723e288f375997f529275131e00e5641c4a8a9de59b9c1a758231767b99146eae5daa0980e58b3e391cb6800a733d64413222feee04385e70245bae7cf54816d1faa02de8dd4d5896f9403a9f37b3dfcaa95402b7035ee707782a509db6e11c7ee08d83174bb352bab9a11683b6bbb8aebe31e80aab5367a98126c254ae02a270cf934ca401ec686f36048802fdae075a3ccf348506364c44b653ff0f5f4546796b62006f312f2d7ee830e8721bea310344b6652d41ca221d55ea873cdfcacb83c81d3d064d6c4ddb0101414105aacb80321737ed9033c41d1f1fe8cf78cd50e3c0ec886d0d7861c992a081d7e6e44dfad88d61f5c350675e09d56695a11ba3730ee49567a11fc720c6af0273dd7f3d67cea5397c254e1dc4eeb130906ee318b18320f86497313056909acec7cbec1a65d69c9e5e184db9108108281efa1b2d7a2d2ee12b9e56ceaf387a72b0d45d2df7a8b08c01f9cb92f5668101ca2852ba657ad9c2adad6e93601f029592caa243d8823776602c36c391773654c78148246ccd12f73f9bda6a597cf2780602082520f7b5b7ac401aa68714b0c69862d6f16fd67a92610eee9520c9829aa9f69e94ec0c1563c849e6d68d42530a068e62fb8a6326406183055f5dded58f34f077e81171fad04315da01065b5c7ce11ae9988b11d760593cef453239f68651b203ff84ce05062cee38463a0438ce4b93c6752aba5b9c0c023e42cce57014ced8c187d6d670de8edde4a00ae52ca037d4a8edb868a01b26bcc6fcd7c8306db2e9036e938ce735c7327bb934c1ce4b8595c441ede18bf79cb7881dcb074ff53b8319538201accefed1ab546aa3073084d3c7a227da1a396297438cc3365cc338e3bf5213699c109569d419ff32fc462ea1c311fd4bd645d45e4a5f3973e447f242c0767439b8c4684132471bd6cd64cb5696d4e590b356d8e2a08c6449362b68d4441fdf3da16c093cfc225f724b13d4158d570980de17060bbf7cad3f8c67437b47ccc0e72802ccaf54326c048a442092f5628b768933c6d18605b1f6d273e112ff9a9c73be1de17e188fe293965a0a245568b9a01b4b76c0c0fa5427591ab9526e5dc1d62f2cf9c0ca205359f1b1768092db1eb9d3588c76d1080b46064721661790c5d09428a0eca93b977b7b145fe4889eaf4031117ac0b453f97a8114a5da362f1025fb04d1cd3503c491d1c6be2baa44617d60c729dee4cfed16f131d669f5dcf5bbc4d00c652961e3db9a8ceba2b399869fd52f159ae6a4a1047338cc02b153feb0904d14a73571ac440580d03097c2702982a04028420bc91037b26891d1084cb7539653767994e457bcae6e0ea63a00c65acc52628557b223384a6c4b2034c3bb17878f65e0d187df755e2b6460ce0ccc2e00cccecd938911a8516e994e8c3b0920bb24c7e2ffca4c6075ffc904db334e92f3482902010bbd6201fd48503c558ac4bb12d0e9d2538534124655ecb5b6e8a72c7df1bd7f87fbe98873035415235cc78805fb255c6d28fbca8f0f5b40080f1e9a127c855b34f9aa6fc46b2a6e697988bdf0ce7428d7a6bb9966df413cce8facea4a444000f7696c23e694213f082544587069820387238f2c894804beb80b7e908713bd85bdcd89aa5e91202e167b8eb94adc07c1eea8910e16051ca767e823c44eedf40eabafab2cf84b137ccf5af3538a3958ecd5463e4ee1417ee285ff7175cdb4532cc83625c734bffd7bb3be61e3f285efab380eaac44d0f49a331d0641bcd72bb3e87dc444717de83c2109a5af02c712bf80abc1a2086ad3418a9dd0979098163102caf714fadf2711b271cab8f375368715fcedc1a9d079934f2007d2fa51de76e577ee5b8cf05a8be1f325856dd0dd339d471e32f7472eec9cd84eb2d52ccde5f7cc7b2e033bec4a3ae5c96dde8cee2eef8090ed2e24b3f71e45d2908e3a1056d92d6329bb354cca141eb09c1796a336246b7c0e73fb1f29328267246dd18b2c5f75011d25e5ed878d847b7b3305cc593cdf880c6fb49dc17013c1b36890e9c0d94ba0e80d1c2a92ea9f6603bac5f690ca49eb9e58473c0e76f8d06ca4d8d25b311e3b6ff5ab519a796058ee7571795f7d8e1a54130fb45b72b3cd18bc1562b56d2814ad3af199a129a4e4dd90a337c3f341ad1041f60220acc8c89e17ca2863d2f6c39c4183883a8335881b0308b09fdab82fcf72190173b211eeeb19091f2c45c5a6ac3c68e7593ebf2b54dffd25c4d30a38d31466eb081417f577e31d4586e7f51c5d09a5c76d9c7516b95a077ea4642e113a68935ee7e033dd886609219db905d7ac9cecaef18260ad6acb097e18c89833c4c1250d6262bd868240ee9187afbefc3d0040210c233181857fd9095989b0405472839ab7b8cc19c55615a7f43167b1f8c4ec31957964f958ba4e1a1eb520d891e1875f408f45e551b148a3d580ab017be918a9d6d17250de757c37613ca89d487aa5d1b9b766d6b15e776caae3fd9f997a67532ef9fa13db9782450388d4f83d609c72f2d30c4ed8da171dd920b66b44a1998c7e2d2970c2e3706e447e1dfd20b2017ae68dfa0e55a52f8e857322258e918cc08df4465f61c36e439bfb974f9ba97018a9f10aa0b28475524b6f23e4a293579df6cb49294863ee02f480aca2e94c19caec88c582db19d02f1530bb042659a4c55094496527cee65650e01b35838aab7f9661220c06ca8eb47c7b442e53cc74b79ebbdcecc23a39128f46485365d984bb5b5c3787cf5f850be7255aff7eeeac9f8f486618ea1161394aa4cc05d65f4203c0fc4a96f69e29270a612ee863c4cb5e9311e975433fe6323c87001d15d960caf02f091a49f3e92ae46ea07761e501acf07abd378431fcbb1d59a1557ed3a8d5bba8b12bc973a466871a4f276b889577f64198d924c48db0d8cc9228727cfbccd64067035c66b98af946cf6f70157bbca51038b0b3a1bac9a08cc4e28e791420ecdec0c1f9eecb1f6d838addc70a46c50c9d776bcab2003254338e31cc43a71ff4f0ef3ab47c64560829bff6561ca4ba26764eb1134ae41aa8cae0d43098522c22d8aa26daa3de11546bce548cece909984ae6091cbea58a942207a6c1115093e023e15f9a7b751844c08c63ea5c156235161b9981b3f269864441002772b2c0aee031803484531f8730ab97a9e0208e4464b7df5a719a8a494da4797af23092b30aad71b47b0113ec2d5e259cc66bcd3df2d0478db57d4325c85aace7bb6c7eec74a2f3c0813efcc425e04460b2f18a20e44d2f3512b2159c750364463763335648ffd7151a2cdbcb203ac46a7b3037fdbe2dc6d47cf62a83fc0fa83eb0804d0a05f2e15467ff1a7d509004b78825e573106ef4bfb3af903b1965bb0f1f596898d22217e2465893ac3be1c1bcdae629fcdf952750368a32dcdeabda2675a3f4c4a8502464b33514cffe2ac59ddc1e97cada82f4ee2da428b51390916be4ea29aceafc2940626e9b7e4955a0deec73ed1db44e36d4fbce1fc4b69c99355e79a9a18f9e8f058db6498f84193e9617dfb1f552b2e78c75256000eb1c4c678e3d8848eb658483a652eb1c76a0f73554ba2d6ac637023d56b3dfadae89204bfb5b52945b5d4571e0c08e06db55700cbe9e8f2e8d175d8e915c821e56d2252411583cc4830491e6955733804abb6514739529b653dc673916416f2d4c468d31831e1236b78d53c5c69fa2c52809784892984983ef5e864fb0f3c09359a8380d80bb7b881efe345a42b6a0896cc84c1ce435ab9da8aea5c67eb78bbd3fb19884c10011cfe723fa460b342c13e9a588a43d7fb4858cb45be62253bb128d773bc1da5a379bc701258f54998781b3aec931e989b0dc7ad654f0e65c179d560928a845f8678134d7b5180c90a2a977bf49e7bd5f4380bfe294d177ccc8bc1c737bb2a81571b9da00fb5f239f4738b9cf21cd7df2664a89c17e933905784afe36d9d2f118266dd3594ecd272917a1850fab9f98bdaca79a58889a4907dd26f854b036bbb6e9e390bd091778b398a46de5e56cf23c1f432c0c7302fb9f8350b1afe567fc755ac097649b63695be4692298252f80b5066ea769c4b4dc1b1bf44527fca7181206b89a64239fc1ec9d61d3d9f921c1e63c8e5c14d77ead88d5e692d8403edb2794c836017e9cbda4b58678c7462451392072e63adeb2f0f62ac3c5d7f8ec695299871e1eabb6157d5d2c784260332d2e43a25333a309ef325e83e58ca0b887dd38e7c99056f20afb85a88d2a3c44c225fe14ed11f3984caf237a2b6438131715e4605454345426984b1a973da1e067c807fcb0289715af2c2216d9b9e954017a5c44318a518e9fa1ab14ae7eb4b850ecf55ed0bfed1ad3011222340e6335c22459e1c275bc3d7ba9d481b23920cc854812872c176b3c4e802884c8787ac493eeac6b13ac65770cf3b3dce24e20bbc1cc9465daaf5662a61420f5ceb9aa552bad3f5c5ecfa1b90f1ae163a043532f09577a1b9dfa26301a225382b0fdf62ba372c30fd94396e072b0d8658e66859cb1c11ef884a6ebdbc8b252e9b2d8a93582b52e5c3a0cc42cfb1a27f3971d257750b955793f3fb1dc4183fd789b8b98f2b3db5806dc3738cfec46e1a60a7d046aab4ee6d18089213a3ac84b7b38073d490d44e9e50bb16da1db4801e9f86de6700eecee467a40e69d5977ab238a4c5e02c643d5ef99821d3059e4fef732e78ff704f0b78ac2ee9b8e91e7d01c3e7278f0788366b82e479cab3444c365053937605e15a1a3a8fe424ce16466d1de658630229131f91ffc2418691c636071ac3be53bc5ed47a26578b313c5c45b9e0ca4a2ed4069dc0b6791041cd9e33ad45cfb400dcb8a8daaa32952a7eb9781b75f8d5f3b7b23274ffc1b040d77f469aadcd4a3122ab14554e2f97cee01aa3f057e23d65b92a96135e9a86e2430e8d25236de6b62cd50530d472c983735ed2423bafa68b5e93ade1e940fe34e149c9a3163201f5203a696192a9dd5c02864e8e446099c1f80a77020c29eb971be91c6ead19cb56c4b820f8ddb653418531df01d473b52e81141600e820702fe04e775daa18eed528e96aa7ce3ccff2c8869d33d9a6d5e946bfb90a1054bc738e247a987b74e6edde584a314e4fd3e53a8b781c1b530f70c954b668647c45dca929783dde731169104f2b27652d050a09ece1c355bff97d541a14492bb318c4498d0a8398e2dcf0590dff460b9dd1c99952bcabbab0b6f472f045bbf578b599552af5d0c981a72f5d0eb76c640ae5f1f6b9920377c0705d66e629dbc95deb6fcecc10df296f8c0bf807ed6370c403dc18bcb9bc7def68c02d7b9bd45ce79cd250b5a52c782a58238dd8b6ebc502bf6fe30cad61e0c53f8a9625ff34dab8def1f4f73e0f4db2affdb8e201901df9201a174a9ec27282c6702ed58477d88036d0b13dc4f482e7708f7e1ddc47527ee1757de3966291e5fde9d8e5600ffc825d8b40e9e6a8873b4cb3a24214be02edf12dc2b5a7fd8f7a096f99ac2e75b09604fb4c79714efaa28e2c4755883caaa182353154626f11528ddddcf1e948e643a754c8a7b24ef3fa3c95497e9fe4130009c3f50e8214a554656647747b93855879e7472d4c1b220af5d4b1babea26b2db3819f7fa5fe5843bb6796f75b3b854d5021e737b5da6a9125908836a8cf9e48987cb502d47230cf9385ca6f2a53eb13f8081024c605a0482c7f324bd9842ebbfd58d2d1c3595e393caa1673dc72a801392a43751f8494c3b5f0608bc61e209afb6c2d5430cbf37e0558c2789ed2b5daa481f02ea09403facaab28255dc5177bde700d5b061aa18e5cdb3db53938742b531a933f187b366cc0779b100d8a88b31b92b48bacf02c33fef02af021829eccca2512b8a4eee502943a6c9f8f1e2bd3ce0c22d24b3b1a03e957072c109e8f4fae7ae602e1408454f159256e0ffca1734d3c381c01c149742b59505f221234ee667d0d7032f8612370e02a019ba30e7c05666425e1053dab3a442dbbef54797f44855968db2cfec550bb78f656ec342f0965f04f43a889457424d50c3209fbc491851837a8070648b4999c7e7b47677d10c37ed2c5a368fe2fea7deb7aebe712b3b3a7b2eb4ce23cba1d28c9e5e0a35892bd05455bb63e0cd0ac3863dc3625bb944460ddcf6cff6312af02ba738e9d234ee32256ed904b3372dd1be6814cc9880cbe24bb06ae6f3923f86097688557e8b8ec44f371275abea94b8a24fc353f243a402ad6219f29784f9b5e73063e441579143941fb28940cdf34df8b65f656a1b5d5a4b19350b1685b9897595f6a44116e617beb2fb8ed51af594508bdda9bc5c0b396073460124bfc01837ec7d3f992439b8202caf4741ec692fb1b48361300b8d8878b49effeee0e5841162ac3978c71af18ec29690751da2c81ac0c359e28c6c47101cbe743d95fd735e332e9cebb849c5f0fca6c8a5b2febc401e4972f23ae3bcc94b489e562f7d7da62711d240c80d0594bdb77c13570386e329c03731c4c633f9a7a5758dfe49350b3b4cb5a930250f49700d470a36db27a0900f745b126c73c445e8bb82eb88dfd89f4ca959718138096c04494304601d28807fbc47c9930d6bd0143a541f1161312a8c70338272dc20523011bbc6df74d3f9448f0134fca516ebc466076322c3c48ad9f1763f0a729e52f1e9a4dcf02a6e0da28de962193168bb5a2da89d9daebb4fc6f2bd590008b34685f2b79c1fa2112680f6079b92c0d81bda8f136d4d68f0346cf594c4fa916e2077cd63c6b43ae37d3fc7715028340896535ec42ffed9c6e7ee02765e6f48ec3a55250564df0194cb089e6cc49ffa38735618bc5d219cc07be041b3493d95f0af0a8f860cc3360538861a5f04ba46ea1cacb8c14f5c9af6036c4458bf58a6701f3b59e04911996b81e49f71d37a27b8cf00316ff9a47458cb2bc45e133871a15aa91a0e61cd3214d650ef4c39614f48d72d2e479f08b3ceb4756920d54103490b09b57650c680db320009961528ac23b9043da40bb283c2d110bda4f9c0e85abcf6abae02e1872036616055d511273b3710174af3bafae5144787c642583b506c1f5c171484e02cdd2e23779274e770ae4cace91ec3f0468cde38676ce1d8f94a1982bedb5f9afd02415bbf0efa5f1daae01ed8b4436de4a5a2479f7a7c63d171b9075bcfa241877882383879d07d58cafdae8f3193e4b45ce0e7dcd098f0cb46950ca25d6d7b959a312b66e1010e895d1e43d7380951a96dc866aff51f03958ede9795a42d3b672491c91107c6bf38b65301913911042be013c89018b498d2b8008b53a81b1dab98ce75cde7ba199072defe5fbf8dc0035524d6121888cb54d8ac4aeb9fbc7a23a45da08fe1870cf284d60382cbc3f85ed8d3cd4bc5e8da013611fa3b06624eea6e9a4b472e012b6f5f7e045b0e4319ab1d3ba17d497bf1111622c49a5e6e1a511b0604b83981d1efca746df8df15a39d67f32fda5d0b9f17a4f4a933d793ae81f42c2137c7893831b02f3993e2f54c94db7ec75842606a9aa289e1dacc8809dbe40b4379ccc5109f895251fdaa7f8e64baba8265dcf9090710ef063d6883024f8e8c597af5dd2ad58dbef63c84dfdb54aabacf77f52129b90c98a6be76b7bb76607c18f38c29952c9e5b6ae2e6f3b59c7265103ad299ef7d280ab3b116db06078bfa3b4fc83088c155113f220abd8278ab24a0b6a412809d48d9d80bcea6c1f4e16a66f98b6ff0cf056d99bd63f66fbb41e524e4f92e22dbf96cc17185333027c728046c5748f40da6a6e64c8fdb8df1234ce8658c28cd6e2cc0a5ba4bbd836e292a8eff93e834d79e1b9855b3d764f292f7c54ee80f4e3eabe06359eda7370398e5155d0050c71ecf27049aa36715b30c1b7a43d0175c7b6421724b2b083435e189a3127e92b5882b71339a7ef047947e287b6c3058083365ab9f0620a053b77604051f825f80669b3baa2b3218ba59208702583bea93f18a790287ddca2e7fbe82d086281700abd6914e4df5796f38bbd5a1216fb789dd94a55e9412280583ced63f477f4f7709ce4019e9dad6868aceb02a1601459e93f656b15178756cda9d782a6eeb379fdcbbd4b31eb1314c839a051a6f8179acad58feb33c3488a60da715b7263479f46a14254616cc2732ee28f926e4c5f561928d9817e49f834a71577d21601b0e2263178ff4b067c1df21ceeb28d60bb24ca61f9defb9081000c8acafbd0ecc7300e32dbf7e8c52662639e486f3c4854c04ece8cb4a0ef26fb97b8c53215de44f63f8360e61ec23450fb099870d098bf9bf177d225aa82b42182adabb53d2f880c9b03a21498c56c2af0ecc964d3468fc5f14d4356793c3c44dd43a83429e58ea51e5b62674b4486525a0e2cddef739483e5159c9220efa9b0749a13892105d895ae709c026727a828b0eaee1f6b66f182908024270406000c7bb9840c0396e1852576418cbbe3e40161d29a541804301b29ff444a858d9c3168c9d320629e166c20b5ad50365c45200f03103ac12d62f884817084c2995f136d6bdba131417aab20e4a68ae8314ae72b61108d89a3e821f14c15941cbbcd939c7a53646c7bfaab4ad6cefcfe8da4efefffec02b52c2385cad634f8b11608cdca510c2e47d737fa785ee927cf8f07750dd325219fb4411002fb082e8760bd4879489a3a2d8135fb7686ab0b8a96a633d29d7951a6015810123a82115f061c0010e504e46f99435b809a55534582aa019773519dda85db9843151f9bce7631b94662e433d726bbae06c6e1f60bb7f3c436a3fa43811a5da0a925ffca6487ce748d4402a8b42aedab7877f40d5fd45cc00abb18db97ea372acd307545cca183ecbe7a9297e765c29bc119749a0499f9c3a5dade010dbc06e3b4892ec8ffa2761be6c8074fb804da63de3f9e9914feebfbb06ba629c87a193a6df4beda7097d23f379f5be6dade792b79e61a5f4fc5004df95c07c2cdca3fed2f7f26bad6dec8051fa5e499aa69947fcb02e90f23b0ebbeeed329713a3dffd4725e7b540375b031c2f2839d05bde442a004ed7cac8d93d89c160f2035c3d06af0567b2158e5fa0df20b4ea5b1ec196443ac6ecf852512f8665c311009c3f428ba520a2b16a18bf5a1076f49bc8b3604b9e7debee2b1697936b0ae0142824f8475c8e99b062c9ef3e1d6351b738444966b4840f8fe78c03f94442e4f24494ce0eb6d8c49c2f56b53d4ac82c734a2d5eb3a325216feef5b5c9f4c44b0d168b32f0d691d8a82bb2d98f5313df9619ecad8238eedfe7aa206256fa36b952cdaaed548bece4c0a7d6fff029c5b165c4074d0486aa739336b6583cd0ba62c20917e19ef7d118936195bca71bd37c32ca12ec861a4626a31e8bf86c87a40857697f4778ef4855dec802f44414f9019ffbbdc18733d4999f0ae561f26f5debcaa14ac5211b5c661f1f233c29aae603e0df3862fc5af0cd30991593f4ec39416f4b09083ca0745c07064c9acb924cb716bcbdd31aeb1714d1839b42c37693f830f09bb23e0d415ac2fd796dacaa276b4272bd7cd52c15de93563046c0b02a39e982d03d74065d17de7f2dfa7bee4d6da88b032ae958369a12595bcbc8a5aa3ddb93de9209f1bb60dc0bdbddaab98ea6610d6c05c891ad5582e9b94dcdb3552f031b0ae69fc48c4c574715ffe6e890a8d623e1222d45b2ac03240f98fdde005e25a38f43c99fe21140facfe2ba817b42777eeb51295c1a8eec5dc16d070f61b62b58ca2a4904152deb76e9937465d596232a2948a9ee36b919571125e4520a16274e11c5f2d5947593eb52804c3b5c801d6c698b85beb33f24e0f1c5c201723d0c7415c8c0f3c98a0d89711f089e6c6377dd7e3f90bc101078a46565d46d1e394cafae32ad1b20275a44aa0e7225ef7574f0f2ae4004eb5d89217b7ec7b17414febf6e4748ae328324d77a5488973592e538fa62067d8586df9d487dedbfc781ac65ff5952134cd730946d7183901a26bf21a828be2384e2b0c1dc8565b6a30a1cec0abda730c0a3c26bbc037560c786772d7bbf17941e15e67fb31fa9290be891f8677f6411bd6b224bd57061263ef083856c9cbc1d310ca43458daf4ed2a85d807ac4003e55ed4f49d6d0136c985132e8da9a099398bd51c860db1b9d06357c16f577efa798f00426d81bbabeef053988721568a9eaa95afb31acad7a8de06c5f10d90697ee1e364293639243447c669f9be4f4b2a83be33b1620ad1a551e34c7baf85b0cff3107c77b6a8d6239171dfa8fce0a878bd139a1419d5705f7160b18733bd8c49a015e827dbb531140fcaa12a94cca75009693007edfb9d1c2b152449c0dc8529bca6421e58b2e31e7064453cdd7de8e7d959c701406c0cd03f8a9dccc21e5e5e39f5d9c06ad90240a44b2d9ff30749c829c20d9cd8d20999333fe2cb4620f8664a4c5fe1007df659d3787752778103dbe45e812fc2939266a8f70a63fbe188307ec79b2ac9fe8373054a4098229249597cda0cd5f31044fe176d25b575a1948990ff6c21b6204f520fd7d504083c39ddc319f60a6d40c09eb18257418271107998925120e988b395a036f42f8b7e729661b8cfdf0fff811903cdfe118aa73af7a2a219c1d1ec131c041ceefd93dc82be0eb230311cc70032e71bdaebb5375cb463b35c1f0bf29e72aadbb829223d50e103c07392c1d10d3c607fbd0db7e95472abc8e03a5dc9956861ca3237c3dd75fa3ecc644a6865652f63224915fbee0e08aa8eb09dabe0eb3cdc5768127fd2f2a15924e7767bd5f7b2aa822a6f59bbb07547fe728fe9e94cbce232b18685e1789df02fcd1d7107be82f6f5e7f12ef17a74e058f1f00aed4e3cb7ec68354ea579200859831b8dbd269a56246804cf9d6fecbb6b611e8660bb2d58331abe646fa4b10fa7b89f1dc5c5951c77f9a7b4a058e146e63e29f47a63d92f69da1c773ed518f297cf6e95fd000ff73481e74e5fd3dc55562beff884cff13705ccb825b77cf748c6958b3e75d00c3336ab4dacedd0244372e50c0c454d38a94f9491b615b89205632f78ef76fe212aed33ba4c692aed1f980fc57b2ef7fca402e1cc0ef75a49cd9df92c3af916865d31dd7051696c94f7292293ca65ca73f9a6a1f14e5664f8e9f44e829c879709880f74f268f19d9276e36fac9a2d823aca9ca62d259704cac128172856fb23886681fb460812c457e388596020114e66aee282f0dbcc6d25fbdc6838253ee8ca3cb54b9d36628f3d41eb6af9629f5ed27dcb513b2d22dc0b52b00c254c3d39c19aedb5b14586bbc54ea825b035c5923069cbf059aae93563779e4bed2ba0ddce3a2452b075cfd99b441ffaf83f46b7841369d99439c711aec3efd64a0181b30fb88486982104b13846525fc87132cd201f4e4948f3e5f86c2982f0312d1ed7c99b71c12af5da2be0bd614f347d1f28662c20e5948388bed461378ad1602a88fca31469175bea8b608dfa3b31b6110c6576188c8751f9600f72073f8c40716390bc14d0be344b8ac1971b7e1f698155a21e48afcf5f817608e74143471987a4a3b3a9f45cb59545214e2bcfcc56a8fc89ba02f8b8c009beb8a04ba392340c8d1734db982fef3b3f887c3b85fb85b848c33e16127fbf015a897225198bd01b744d59a9598837f90e0447f103e1b83f62b7a2c95fa9a7379fc29ff94c2aca436cb796cc038b490aedadbd6e4a7a003e817819708cb378e7913b1533f5744ab22796a6f95c6864a49dc12c260dc1956014335f51ea84024296d80217ad083789170877e04e2071b12ff2c5e13605041acfba96253c463e6b427df16eda6fe2bcb161af2ed99c72909e6437153a4a633304583f10f9609e62669a7f2c8f84abf164f1f97234b526299453dccd1930f6e532ab3f636ec48e1d75163ed1b16a89ff83a8e112fe9c7e64019cc8279aaeb0cc496558b1cb95d5b4b74c5b767338cc58c76e537c7fb607be9d27d73086290843ed4751caf00162a08c342c327fabc44448cf7a81e20ed6b08292baceed0d728165c6a299e01caba5ed54a3963a49990a0e0950d0fafac2e10a4085615dc07108220c75eb60cf001fc00285ed75d804415f50f20439f0c2dfdd6dcecdea95d0a8a8618d802562f616a48e82f761ef0e96a7042cace0f08fdc6f9a27c4ac58d7678fa537ea60060839a6af0c45e57c1c41339a89e19f63ab52b15eea97d4a7a15f2edd37001bf8feff3449b662849d4441897882855b2764734483196990d9ef5e3ef7589e6a94e00a8811871d90b1b784d5bca59663cd0477486476b8ead193501c5062b761c4bb57079d16756bc8866ac1ae1b6c1c358d885bb80f3aa84672eb43a68aec5e1b003ed7925cd2d201cf3acc1501ac099245df859d3de19ece73de2bf6c38e09e4fdf6aec516134919012c575e88a3cb5cd1f47d59d0b33802b2f4769de57dc5424a8120807ac76cf625759dc0a83485994724bb81c1e4f0d92043cc4fd803752975cbf14cd70133e08996741d5757b3ba99f9bed4d77ea58e91da5c28aed608c60358024c465a9ad04046e27199c22e402494ee13658873d350fb23956422d5d812f04dcd98f3e9b8d2bc4c69cdf2112ca9cdcc95d5eac7bcb240c975d8a5a650fc1b0480314b5471495429b68728fa1bd71fa2ab9ddc65c53ee81a34914952878167eaed24f455c81730d4f41ebef9b3614f19b160c9b1bfb95ab6bb00cf461d786ac24e31153d4da49715d814e66eab10035ad257701704314b305f745ac4725a086efca6cbc14c08d25de4084228109ce68e402d5c9a896a708b98839e5a0d12561c1e1603e068f54deadbd6082d179437a22824f458ed212a5ca93714d21a763b537cce97130eff27b89174d9ef18b9284c795a9cb8b33d0840cbfcd92cd34a370ba967089acda6f2b2656e3a6dd4e8ef91ce8f62fdaa58a108f62d7abf4a7aee4b7f04b6f5d6ba9da347ec125066f19d20d3b42dc11e1bf549bc5ef6b363bcc573e91c4fd0582b0a181b7e4dd4fde85d716765592a66deb055d4a8e05608f36e67a1f1acf64e2034dc07a9f7c0a146c0768c421d47d1ed69a3210929e7ec61b990d770bda57af71b1ae98f8dcebdabe235096476014263d05b5aa113069e784097b4d5031c828f39840fc38f0d7a69b51109e0f8c441c7e33ac675aabd62c7e23a662cf55c15bec234356ef6bdaf64a854e75393e97b08fd6ad8f9ba57f79282396a229a1ec68fa906f0b5a6f49c182a94f081d02392cccc1ec755a4d103342caff80fa1898ec62a0171c0790e84ef5f39af825a0db528bdf97d4b2540a5eab0cc9c67002830db4f8c18456d1d79823a56a93f988b9ee943eb3941c889551e63888f4c264a9af31194f72e579b4e66b7cce12f0137b81be33e5b16bafcab0d1f635bda31e4867192aec1dccf6f17dbc2dcf282054e145cfeb5e93949dda5a98222a849dc0563328c3f6ca36a9801094b8e88633dc1eb7527f8178fe08b1c08de287bcf16c8a56906f40c13cb2a73248ade48879ee77c3099823db9a8ad4030ffe9612463b1e9e0a8e53e9b8d905d2b3c8be8ab321aea62e327a7310e24491e6773c66aa92262a940b2fa1bb2c626be2b05346a15d73a32c8947fc1e71c5870bc7a48364b99417b5594641727e5eca9880eb3c568ae4d9c437d1e36fb90b0e4cbb44035b8a602240eca9223661df00508dec3212e0e9f0a529b70cc1041c454d5252e1893edf46af65d7a647baf089ef73e3b6244e1cde6c9eb156086c26de767b123e75b40ceebabc1ba81d287782027c69e5a807e7840c0d692200d236b72061be52ccf89838fbf2eb5dcd7082ca0a130765d9d114727950346c1e0bf198d290b5db1d5132fcb9dc596891bbabdeb0ba45528a529dbcb4f66909179b11742e9feb6cc03208a35a767f02711cb5a02ef1bff0366223d155a65b9a03da55d9dd92b5e56dd242a4e9346c4158a98dcbe55ae41a524177e241ecb402e226d9447b36320ebc1072660f90932f0536e0e75c11bec8340b59c16e6f68a9265a41ac018d0f75b896cc45b883257bfebb5661ac85ee4db40a5aa1258e209540bf4d24bf68a9d80bb64d0d9a6f5a15235f81196e38c11cbc0d90fb3e8053a13a90b3438285eee6bbd741271ca1b733215e941b1d46b9e9cb9b308f1d867a254ac35e6e84cee3cb8d12404c12bbab5de6ceb924c3967ca420b31818ff29539b0c6181818037cb7557844758895337e5da12aab8f21b690c352a9de50e2fbccf5be993b4c05a3a700655926e33139ba042f06003c981c189a56325bb76af9324b469bcb309db3539b5c37f67e7aabe3644bd152f0137199967fdd7c2bc2285b0e60a3913a923e530e267e142c2f6724b4336b7baf2a9217f4417d588296fbe981a565fc9d591cf85fa728cc4d0fecc9c537bc3d5d8799548be41718feb39e28f21aecf3063b7e3dd562bf4aeaf5336651da86a7b02ed4b760c6033fae903045dd6bb7621d3963f3843d6584c24a4c6afac14454362949a3a05d137f91129e3d12cbb6d61dd3e491486c2234b2d8e9d0ffb99d9420fe88a8344fb6ac71df9e8660e0ae8fe3efb9c4ec3d1076b988bd9cd57bf03ec6973dfe987b0e21a1ef1433c00d17c6b1dbaffb1213ed87e49b2ee04e6d9aa9e55b8ff12b09d24ada6168b550cc38641829bee8f0da276688e82a91742af49d39123b65c08d7d29206b0c907d41d8557cb06fc5056f7a2e149ada448818e29e95a69be5a79753d3e1c310c700b69e95f4f9e0f107d4f742e742b69a8a3b7bf3cc5611646ef8cd74ea514a30ce08d980c88747609bc8bdd5663e1f6992444daf2ce3a435a5476955352ebcc843f8b677510cd9f8fe7c86b2bbe5daea3fe845b5b5ca0fc80e0e857559f9b4a7acf740bad3f73c0c19def9a165793fd44898e040406a800a58cab0d09469452e655b417759b3c746abb48461384ac95b41973c41a034620bc004dc4ddc8bb60278baf7e0374cb893a2deb86c1479674ffc41e33b8d2775fb637ca6bdaf22a807a33b9a0084a45bb631494c8ccb3e9b9d641812f35e1c1411623b02f639f4dc94cc3adb094a99f7175fac687d1a8f2b1c54f27a46ca8fcef8a88b997a84253bea8144c5552b7a43eb4905b15650f06d4ed12a8ab8fa2264c9ec840e1c4a8481b24de699da72e160ae9157cecc5fbb5e8f6ae6d17ae8488649bf6fa8114f0ce9604bff4dcd5d8b33d984d1d87dba02b09396a561177c278061f9092e857789a2b00282b8265c105cc463bfa67d2fe7cec0a5867bc6bf18dfe99a64aeb0cd41f784a96497244cb3339960a61d0f5065f8632b90b7dae69bae6268cc299d4fa3e3414150c5d39a9e9b8b0087a8af49801beae2e92f69b4504b339bc25850cc521bc2f8700fbba9d7935c6a515f8ef27d9f6d6028a55f08bf1b736c4c40610bb9b149b63533c27ab8cf2d821c6dd33bad3d0460458ad6ca024e2b06b458cc23e5cf041e46c4dcf9954caf885f1b9e7111f94b9a8873318837c53321d54fa5395e0f8d4e8fbd11a5701e370e486cec7477c69f68148ea40aec6aa1e09aa3083b09fdac2967129f02f92f582ba2696a958c42ee394caf0139945dfc083d4ca900ab58442095bc30dd483b926c9337192e1c09bd0e8e386389e896e803b5df5c64f662a4a43d251ac83d578b92c1a863b5b3d23e2f6b705b8bcf05de701e9f1c6f9e021211965f654226fcd5cadcbb393a28edfae34252c74ca4e4be46181116e2f9f53b4ff77f1cc108c0d6919fda26743573b0f82f1671a2ca0fb960ccd64ddc15c152b8232527f6b60311afe55cc130b01c31b85f30b585f69410c9b17e77c08ac005f16873cf3ae6d00706da08da07525eba672e8b6860e58488860148ffdca0112cdd9519db09f83a3935044d8216cc55c3d1603bed2f14735413e5a43438937e9ecfe1833bf28eb4d20979308826593f12eca48ad6a0271a821bd2dc21735330daf9a9be4a5a57606413755f0d1f8e9b11e9b7fe47ef0c252f83d5ad0c7f05434c582ff5d90ef192d8148632e437bece15a40546829b4b11aad6de0a2ea67b61405a2d88242c357bad8ca2cc388ce18acdb974ef3b4bdc17f3e9e76d55b2095661f13c2b94387663c0af76e8f45e79451d865e6dc8ec8ef0a3ce8441a46bad96628d2b60d614cb5523bc2fed4d111ab1a1d41ac7fe45d3412591458733a3c7d23b65cbd1fedcd0bb40d6b4a02ba891c71a147143d50028fabb05bf1d906bb5980daccc401eadb35915221660647c3ae8fa23928d7758b7ec530aed51462ee49bb8ee672dc25e78ee2a08474bd8621cf28d022abd4ba9fdc137d0fb14d867c9eae2f2fbb554eeccc9685dae37b5e93d73ff667b14f09b4b435b2aa294162a3078c8d7097d4153bb1dc17cfa65e575af652b341f11e2d6fd954d03745937c35a7f363e650990a447a15f39619f257a5ccb9a19160edb73540f58f4b06461bf96ea3e28d49c38549adfb74682d60c1fdcde7c05e363bc0d6a5458c96ec62b4e90ef8460483f33725c047c35eaadb0849461880238bd6bb12587d0fab39ee58e51eb0eeff26342354afe03079a6091de7b3896e8e0f42bb10798af7a2d388d581a98a5bc42c35fe986d971da53ef0be7a81128a97c9615d0b1b99403a6109b1c0b12fb356bdcaac5cc30152ad4ff1739e56d8c508171abc20eae9c17dbf36d72bda3c945439beded8c631beee7193077006c6d339e35d09c407619d796daec5cea3b1d1af56174befa69a123af057550a1f488c0c9bae4dce3726ab727e83a174cfc5fdc0b3456cc06f3eebdeba42526676a14aeeb1807be8f25e91b906157d7d01dda5be09f893dc066a554f865cbdb16bf37f420bfccbb6db6274a82383c6cc0c2663bd200108c7344862f4690e92d7c8f00aecd31d8c46172a1e64af0e72fe9f3185a57a71e814ad5f0f0d33f7db151018ff3cf7144c6ca1b5654757449ea57d9c165b0386105717498d620839c39f85b1d01228153bbf43bfe1b51ba9718f0108fe1c0a09aa23f9c3d83326a65d280bc6843c6dc4a3aff32e86443923dee6e21340fee839a99425694bf86d3f27490e877f87981767acb3c407200097ac2108093e6069b0c65fc1c8a4622d8f3553ab77213a68b8a65a53b2ddccd69111dfba6c35ad64f6bccc50c664f65cf77bb85edaee120162497022348d864873679d7c6991f3ae7d445e467dbd9dcb45927c7dbe358b5c31449ecfe0d217f7913e83497fe781e4d22554577eb1ad0b4162bbb27f8a32cc61b50d4822e493bb0749448100c30102a10e50ad2c2b443654187f34322280292a444e6a4f5e38a8809d0f470cf721e29b46be30e59018c863b9e33826395679098ac5285882fcd6b6e90d0e3b1cf3b47cab42aaf44111c25885dcf068e4311efc18606a885415c9befd0ce3144f427825a8937a257d529819a237434fd7b7593e567778962b9a195e0b489f86417d63e2987306850dc0b81511acb5b605d5831861dd6685b79b09fcd3286e7a4124989648dec074f41cdefc3b6e6ba2037b3956ba12766682f2663696e53680b2ad68ef66a182d721e95d4055372b9b6f0cb20a5e0a93a9fdc03e8ea9d90c36e5c1de148378cc8441a175f7fa2b132c8739abd90976904982db0164cbb92ad3d2a8311ef7d7a02df5096383aa043cfdadfa0decbefd8b1aa7be45cb49a9b43228dd31f45018d17bdbaa7baee1d7fb6a403536d288a72aa4a277ccc6c24cc44ec1ee699e7ed54bf465bcbf458b6b5abdcf988adbbe7e7c0781b7e277908ff99487d74ddad48ad6b0f1fa8b4084ae851ef522b40ddff9c43f01b1d2a7247ef8706f58e397a444afa382ffd05cfa4a6c3d3d3e089d9e9430b8666ea02c5e458deb0c974441e73008e08f45f678334fde926d4bfa5c3e981e392949b415e67eeed162ec6e9c23a1767f33f74b7518a1868f7988f142417575a151096074d80a48b25014be6e60344fac207ef408a087a7f76c08de33b718128de5a81cdd11a3428eec14926c49d82c32a9198c5d237e62ef6ab5ff73d6e746cb6e5dd22873f7e6cfdd19a9c3175975da1abd0f50319c20b78fc1134084460c4aea6e687913fe590d1af85329a8a8c48aecfbe909287b1c46efe93b820c2da46d2d77c6c39ef309a2248c219771cf8a138e448ec2a5efcb89f01044d6bf12da439636671931b1cd53eab02d753ce8604850a5999f4bd05547d5cb57e1081290865be4854ad50098b2c8214c04a39b7ef77d64fd9c83ceca301058494a1722bda91dbcb1ef063588686c82c4de671fb2e2b093e40ec616f5e640423f96bd3fab2b15f9dbee2000294b473e099de8447d0eb5309ea2af755c6023379bf91c3151593bfecd2c0cb34a8a97754f398b8b0a4bbd231c0bf30bbffa1b0c908dcf5a4696a517d7f144fd8ef82ec784225466c9b15f57c69449cb13652fe15378ac979f895e06751ab406b440662ef70db2132facc6ffbe80542c9059bbac35650ebd7b222d98effb024a8f0eaa81f52dbe2a46282a76159e1c2bcf1a6cdf3511bf8967aabab2e6ceba80b5cf16aae7f813c02d7b6890bd403533c24ab3841425c05bd644f4372934c403d37ce0cabc570eebd8c4db011860c4212206ba48589d8dcb418827efa7f311d2076566114f665f5cbc00fa1085af326100154a905e6fc322015ebb4d4e0529c7a703834e7eb6485dbb687dbe2249e701a27bcf42b49d7e92ec7e7cac3c53d4f82e89ddd5273f96d4ae5264923e4c91c049e46d16dde1ff21466b22012f1359b3d69000d99dab16ba700c752888dd6d8db2304ea5aa4994a52aaed08e5a6682f390e6154ad1bcba83d5688e90f8d41da8a872d9c077a97247a435b358773246143daa68098731c5d8137714b22e2454a9e8c27bf21a4680e65f1474134a99c1242c5b66e81dcfd3d2f451213f6b0897d09ee24f6b4d5bb0913467002d682a11170fb622f36b00406181636404ef7748afbfed6e0e3433125871840ab13386f79c6f3080600cd35bb9468eceddc7d8862506245c511ec4951a96193b4714357307cd78b18c99d4663fb0747c57cf23cff60c8149f56544503002668dbc16f59f2d7d01928626f95b92a35ad016c0a075cba16a5ef86e24ca79f634d3a9e41159c39747a101be661771895b37f7bb58b171488000035e427f5b24bbf7dfbb69d13685029e18a0ba5222d2994a44521865221ca64cc482e3911c8f2fb71184964c22cb39d80e638253fee90ecc7a0ba82215e32f395ed11b2dd140f393e53040ceac2a926feb8311a00f26777ec2df32f3670e486c421167a83381934a6d17848171a72f3feff6c20b339bf3764e2cbe20d2a801b3da4aae68e4994523288bd17f29113b1f26ea448002e71e267b94b2739583a05d7fc32e4c33d1121d2e10d2dd344af1e97602dd85f7215cc3132602c5540eb16d8738bf8b3bc80ebe629f16a887ffab31b03d06a7d0c05d876aed78e7a344c7058f51034e099ee11ad5c3ac1fba0e2300978701e420143426046c26309d6905509ccd0eb99257c728ab8aa077ec3656ac00b6707252557dd9fb5b4684d6cffe08fd1c3c7f5df976125d71fef7918826dc7f94daac9dac60841e078217407afaed550acf9acd21a8621087b5686134d04bffb6ee1a3979dd1fd0080b2c0c4d84af73d03f23d1538c82d064627e329d4b3b33c1763b2a8cc4bd944d4ae0921cdf0245382bd5d3b1c3b18bac82cb3c12fb9980eab3b4c4c928597dd39ad744586c2330d7daa3a51eece85c80a38db0c4d47f71d1d24474b33909a6d13d33944ee01303536e3d3e0580077c71d72ee432b3170355bd10808b4ede9999bd2871f99e38bb5c818a2a2959442d12cd031984288b41aa1474d06ea129a55a5dace3b6319195f370d31d9a3099e123e2be5b4ba7e123863f99615a26b9b128f7511dc4f8591c8db1142bf5bbc325848201de112bfadd85365c70ce7d2c96ecd8334c2c6efd6e3543fd153434e9815a138c1243d61432069b95d1372611802edee333960c0ad5e301285d1a02c19cf4255aa48f20ccbf0b7386f0221761e3463f442ce99a6d9ea3ded47bb8e9d246b5bf0a86eb161b233ebbe35414cc6cc56f6f912b47027e02caef7cc296df0dd66c0c3c83ba075149a27840610100fbb6e45273e6b6fef9a5f5158bca3a796b7c2d1ca67d021db0d13f13f5e07825aa682520db76db087efdf9ffb36f05686f3da6cf9ad6fd4689fcabe50ca238777b19f973219e5870eaad83824cbd7ef103ce2f584341e7f7838402d5d572cef013f2a6af1b4b52cca8d062d4d87509d2dec2857ce2653b5847a3eab69aa0d0daa24783982f44934cd93c1d56a2746f95859f493ca11f0e3f2cfa36e72315c7f1cfb46d40bd5ed9075b87814f1ba4da58936c95be06dcb2f1c3d547431da185f6d9615057215424b1b562642d47248563259222613ff2bf6da4d1e1dd2073dd0fd4834c4d6eba97da2f30115dbf022107afece16ca59efeded5fc8e981159c98c4f4ca87c1b04358e4c50d9469b2ebf56e15d2d2fc31c34213dfc4e2c26b516c3daa0a4f9ad8e5a5c8b4a9e951e35d3ed9c93cbe743c8ab1a773c80e5ce7142a20a88a3fcb4789d6ef10bce4071263b815777f61adca04903c39c886cdd3cf7c536c81ba01b9e39e2eea62d6c85ad44233fe821c5d9839a321bdbb0c6da9b40308e7dbb65ad02d9a64c29df75d5e9dd2c75615da99d7f6a41564d1c41d4a6ee973c68dfb255659b500f4c6b31961e60c4be5903cfedfaf316045eea71061fb05685456e8edaf4ae6bdce5e2bfd276d6096229136e53f3d003c89aa71150557b39b1d0607851f268a42e83a700117b927966166688129284d107f9a8c54911232e573ede366ad571171ba30952a23cc2c6aa86fa167c8c7917cd6e9441a50b3efce0c3badf71bf17460bf019b4e658efd9da783b58b0fa85213adb7f294795bf6fe87614a6e59656c061ab81525528b223f063c15866c1639126c0ce60424401591fa2718e3bbd620b8ec0c1a3506cdcd800a017dd9f5631cca001103f42a98ded3ff7b635544983da1cc032b8b2ff8aeae8f950aed424472c6922a141b004033ae6a66e80d3a560f3b25ca02c4395f739ee76b65d5f5dc1bd76f449fd6d31a71cd8d27500fe35496e7c90d543d1641a5bac190cea8933429f83d10d86c8b297ee817a4f625667ad0a4df32ae5f7d7e42f0fc388ac1c83a7a55ab5377a34e74335305145308f017baa3f01e0d7da9f2a3c4c645194612a7939ffc06d4e6b633204dfece4b7feff7a3302d7067d57f0dc2f1c92d22f7371f21387146649d900e79430e61201ea26f16190e7b23a084cda3ef38710568716e1828c30bc6ab5497a0fed01fc18f9673bca9c423ec9d12662062c835eb1d295a61b86b0699bb7696158a55077e55edba4606bbad29cb3dad7d61ac94c7b4b8d68218c25766c0162021720a8711dad58e3137ec5c787e71e39824a626e6b5bc45b44767752935bfaffb5ff2041c77d7350daaea85dc0d5b3e559a1f595be77cf275035c57050cd282c2289ac3ecd780e13c9634237d14452ff5980f1c8cd59129ec947b7bcfc14c833a69404a4fefb810c3c90d49cf4d7a20fb057912857511917c0076d9b114921823166dcb73cbdc6a9793162531fe61d22b95a7f51d7bcf4c16ce15c57c0c080974d1273551ea4b3a20f32627fb02630eb71ad75c0caa82a952eadfb7432025c3e1eaa235baf75936ab341448a3639a22e1d7478307b7609befc96bff395b134ed46e84c444311e7e59b21b858e73c6a189187eb0c587732c1dfd1424b07a64825a2e849ec95f052602e40d3db65a74bac04d965d9dbe1a7d69b9a713596d0b9109589d303cfd13734c518cb136cf0b745780824c063abe94da2030f8318648862b5e8ed633947c9c413f6494473566420ebc0b2851f8ca80d4849867d36ab36921bca6577421e43f5bcbfe9426a4584baee3e862df16efddc897c74923d583534587178b592c1d5808c9a340fa8f6455a0de05d79901244ba71234e5a8c54bb55978e16760702e67090975c35c281c1f91af2226f13ac16c8551672e342c68841dc1ad687073233d4c43c57706b0b21375371cc4d1c070d0564babe6b5fca49ff301fc9e834b0aada02c5e56244e30ce6bb97d0f999036ab8cae735cba4b7cfbfe695c454ca258ce2168121d214fd00a51e7c2ea987c6b50d8337f9505710b001a12c7af0da7537d692e74e93f984b364b26771cd2c5f586a43b03951c7a3c074a9b113b38f3b1c09cf367a9f0945eb4e641a8c1a7c3d91d2bbaa0a3088a6badf5b3f71e4c768408a3073dc809c123e01d1c325669c57ee0d35485e395ee628e60c60b5a4549c7729c7e7ffde6cd19dff46669b3c3e99be0282ab2b1126c352a98c262e608190926434e8ee7fedaa0507d6e72bc2314c5e5743591693ce3f4c128c19887e0ad31fb8b653771b2b54abd47e03d135baf6db7feecce315f493cce2f0c2364b90612c2e1123230b26caf1a1e76a20bf05b775b001329be18ebf5341db6e1fec7ded1911594c16711c6edc8822b9927e9cfeb10e16b64bf250e255e82404010108c5e79c0e9208a22c85886b9eb653cb14a3db395401e0be09ed8e63051b761c0127d8f741379f0add898ebc84370fd77c1ecf153a20a1055f3c353f558116e9d464869e05398a5362741780eea0a2e25330a2c97836a46adede1015a60a3450d62a5493db240d0e9074ceb3d61a08017981db12c3268eed50dd489e3ed72b49cd2ff8915689f1a4c43c5a12544eb17b03681696a7280c39f19b4f67d111000fd343fc8c63c290b694f3c1fbe9b54aaccc1043dd86910a603464d4573ceb4b1f3ce15146e0c2b3baa9cd910b42f56204286cd931b834d2b43373a29b6fa5eb80d092b32f53983ea42e744c3adec58303a2e79b29954c1ea11c17be2c3c2b4577fca347e2e3ae94860b77d092767a0d7ac56a40d88552ac658d19ed00f31bc1c1b9905530746242587a3a9fd8015f48312294e9494d88fa27620a22f81bc294197384804db688b3c1bff37854eabb9110808715006ad7a9c8e4aae3cbb66f10dc454800692265c7f449d6312be4222b5e3e2628b6deb2f68131b3145b81c6b95434d698715eb1226459cac362b2af7445f630f2a93ec480cc3b81bfa24bc6f177c2e60174f4a74d8c445e5151b4499a03d40171277243d06dbc5d1d064c4e327d158cec2c5cc2880d3e4389849ac5663b94ca976b991d68fb600651e62534aee4244a8044d87015611e28ae08211b144fa8662ecc0ae7d05e42302492884c645b76bacc07d3f141b56d9782b6d0d47ce7865cdd603c305bbbea7fcafcec2efbc4c0a8a8145cc0a2aea91a8717ca74b0e789c3e6347100126175a3b3962cca3ab08c7d3e13c051ed3f77bc39e0eb6781b7c0468c020274f56052787cad6b00b6309838122e651aa6082fa78f5f468ad81c27cc1fba672b8b5e51da18de77271fd3f276a31a2735d61b50d978684df9b33ab023e83b36c35223761199c003113ea1e456369640814952ea99c279c9373721cb49491741a612bdd113225c66c05fad8d01e00902bb56690da46344ced576d81e5322509537fea6c36048a7a0c2447ef63679f23ba7b8233bb02e00489150a6f3b3dbecba976c05479ea8b949d4865a1910f978bf82e3da0c2486a14a3aa69d8d86188783e7bcfb26c621f07f35cf1480e540cf0f63a1a2c56db2fff45bd8511588b4aece27319d97b0e429e5aa5d3ee7fe13d5c2ff69d54289805a1612a30c35e6ac093c1237e25bb5627296d052acb2c9e1ceb04c2562dbbdb544dc79ccb13249ea9dd6652117e67bc88c530e0241a293e0577cf91975c0cd3159366eea876346c3c730482448f43c9c085ba5ee3e4487a0e3481ef8acef9ecf26c21074c2669619c975dac97033d0e8f41156e2dc136c7111a653b210f7aaec3a00eb8d4f768e595c087163366704bf9da2d901c2e59d011d7247362edba989a0c0fee103ee00a9a7979d5de433565c2977d641ef2b53c8679bfa79ad2f7e93910137945c7dacb1691d3a504ebe826d6568cd18dbd4b09a4393aa5eef59da91aa777518664094a302d7def6d91eae00068861a6a4e0dadb30cccc2b6921121fc8c4af60febc7dd2c6e435ec19c446a6deef9c5000a2464c6ce96c0ee46dc9c7cdb05464e2ce575a19496753ecd83987b3c93f51919962b3195e33585c8c4df5389ce16b26a0c210fb9cc004569f456689c09d28daba2bf045168269b2d9da4cbe6f6a47573b14130adac730623ea4d19b05080c5f665e8173a1a310cdcba25fc66e7b84c7082611a2848bde9a8285162b82033fa96ccc8dadf3413feb59a44d235a4594eb0d26675684592f6f2028c9f2ba5e66810aad6c25ec8408cd7a2a981e215d525938d5aeb6b5b3b390e2faa109d16935e9cc44e818494830eda4f2aadc7819cc94b2afc2745ca9b3e105e4e8ac29e8ff1aaa16be53bbbc1e94d0ce4b68c388b88adba45ebcddf65d30ab90a7d89151d400772300446a21523aac9cf318f7ad6553d49cc61e494ffbaa46bdc42a249386ced8b53d2fc537222340333fb5e16b23defe96b0aa20110602acfb6b42e1886d89c33e8d33818c7028f41ed034d356dbe8f77db12c2ba6d55b6f2fb0ec2ad868e61e1a9abea62e7e9ed55923a5420baecbee8be368087c1cc8714b93e1124c5666d63952dca5f4657f249baddc6af4f5b8e740979505c15a236815524c0e973b553146ce727bcdfe149d499459e8869021ecaa96c09d0767cc2142792e8ef683885b39139424cee3205fe62bc6f0aa2c4c73a0ec3fe6b6df201a4b743af57ddfe377fd59268a14b1f7799f126adfc03095638fefe06716c10b5258e67bef3d268070d14916d1d7c66e7eed9cd7d7a64edbec588494aac36b1eab42e2c3bcfaa6e09174e4f87307b38e9db98fbecabb42db94bf635f1832de016132fec5c5f40fef4e56d4bea65ccb7c04ebc47404c6cd995ef6a54adb43e4af6793c798513c10c490cfbe88c68e0c4f127e9263cd1a92ccf2693313a061c908ed68b503527c96c0d94bbc689fc60f12a529f3f672616891b5dcc6f489033a571b8e88f589c6383f546adca452bbfd3d3527a4fdf14fed1c175169559964f8ac27aa2257fa5644f32e72175cde91fd69fc6132aeb8a14b831ba2da7deaf159442509f34ac8b84422a2c122176238c235549e07103d30537197c5bd55d928f52ca147aac94c7eec846cf6985239310c6a5c17200d2422f6b724858ad113c50adfacb1c6709d05229ca8ae630c4a585729919ff50c7362ad0620e94e1996f04ea2713a6761fef95c83d4b7cbf7c4d26a4721e10715c8423366befc4f01a2349da7a1fec9215640023e1519a57b988c60fe4c11dce5e99f12922385b5743ad71d14123b469f7409e0fe8f957942412ab48e4a9c1d6f381861083afc932b710ff069cff1e470a96abc4d2271a9b23ff22a585c4abf20a824574d2eedfb5fa1c3a56e3cc826fd7cf0f9f9094a74a083ebeda3b95641e78b72428a89fc7785043afddc3421a690066d27452ff9aeff9e4ca57d56509acd34a9160ac70c1156a2682b30e6904100ac1365e107bed84b6c0d7feb747822ca2fcf3efcc48f43972ae5c2261d01a24e62301b37069e3afa387c0384643eef2fe0b9e239b4ab44c68869e30ed057bf7859c08b8b9ff420a0a6d6b2f1996b18ac003da9d0cf18acdd44a5e6f08c2579a124a1fef977fb2efbf435ca65fbf069abf4691649eeb72f02d7c12976a1daeaf00f0b30d0c5dc084fb4553d8b28056db895b51dce5194d1d676c7dc46566b4152ad6d5c513ccf8fe19277da874d71e58cae2a3fe25a3218e478744bdb2fd7cbd4334fe8f29667ff9a61eec9456eb24b0fc25d808b22e7f6d6849d9adacc4d6c8fbc89dbaf02c06a61f783e8eadb1ea39eba30e5040dac0ec555e13ed8dfe590c008c0745a83b7b32d9a46f9773bdbe2a95fb96a8d5d2edea94015512393708f7b99f04ac04c31c4c2a4f51aa51ac3844930d3766cd8079ad56d7de2fcf61a2b1c84594b6b91c58bd37380d2e4abbfd10c82cfc6731811eb93e253d26d86db58fb9eec2ff3675e951321b7ac64d428f5985d6421b6d3618d159e379893543bd88946de334823e3af6f525c4972dd56f1f4b658c04ca5b7b3108eb379742d2c52a342362124968efb18e627671b6114e9de5c89a3584190a9a547612c8bb2ef7a8424757d1abd2bb3fb70a537d44b1cb1e666475e93f6b443677fe669351e8830fc56622092e0460e9c7b0345e45513abed7763655d44dbe0da934233a353b438eb70aa291739753fec79b17b7af67a5b2e978f6d42aaaab0d794bdf8338c6dd82bd2440a4a07b9a7e5cd4657c34130149c428664607c8eac8560b2faf9ae910c8aec63a623d93d9266a7dafb11d5067c0f40f2976a8582afa64924fb6e3b5e38baf2b80c496f4e3e9f7d8258fd1fa4d817ac9910835181b7b31afc0af2233d1db89a80b13cf28be3c6db99f65e7469e3fa7a5c451682f6fb7e74e5a0f7a4e8e2a63b477bf9d7f9c1a8eece86fed094c97a443a418d8b93ce92db44a6ddb71101a9effafd61f1e4a5ecb6b76b76388cb58d782c268256737396cd41c7f5981938282ba7eba85888307134284465c8dd257a9294e188e36a635c7bf9d08c10d26355f368084edb0111d6337755943ac840ae3a1f64b465b69e87891ce9c340ca183960fac0f3fd697e5ae11f28746c60f5f96622bad9f2547491087b6ea2186f75d66070d519ab8fc92f30ce1560fa3ce69c77d32f20ddffbc1121dffa66506037f688edf92431ab869689610a99239491bfcee6822f1bdb50be68d3a92d94b62683f371069700c9339a9f243c28c41e70e6a2d2bbb9cc2f96b52e889429189086eca5539f072669870c7c7f1831217df0105c59d558aa8c805e216bd97a978f67fd225931e7af767f4d922edb2e2ff0a651ab8eb2028675473cb13be984f8908f35511717c9e8d1e0bfb5861afbf94ffb06c94ae3e179a87ac2c56b6cb248d7045dcaf1fef53908051193d597c25d72fca44255029c166a51a2d3e772f6d5cd0e08225c3fe6569d01ef7c00c93fb9867e21f7d5341501a297247a44517fcffc8ef3ec27fff0cbd1423dcaadbe8d80549712271e7d668cfa11f694184bd0dfea86834a37fc0247b37a07f83982e884baa6627d2535068b5798b49fcc2462bed110590b26a4ca37e8a6a5438c8b6b0694b6e49b564778af8402aeedc72f554282223cd98ad21ea5261d33f78a20ef408a9310e6500ed6116c0ed32c8aa558becc934466061589791203e17651d9c0d0556e948b98b95664149306ee82e3662a5758bc79a6948f8ad90d0bdb843cd2f1f211cd426147478ef968b628cfeca24c483b9baec9069261d2aa5fe35443d67318af3d4135ad6781d2f94558eb5ed60ed21e0c52ad871871301f1daa6c4968b00b5d3ce97002287de9a1d10f9104a20a0f82f0c54f6268c70a0dc0716f73fbc75b5c9162671dc2a4052099ed2278fc9b147837089afc35f2efa973321b712f973494c1d6629995a8cd475c42f3b4034a57432c1b21a372b83a58602fb132c3edc154df331e580972a88923dcb73604123331855d4b669569739b6726609ed87e666f48f5e171359e60b8531621f6f76ef349023bfbe57b96b2a0a334c5af08469bb750bbf56424ba53e9fa006b2a212c0cb58b4f3abcb9c5c345ddfafd92f1a9d4242d3ed849eb0347fd64b2ea68b13bbb3e7bd98eaf03e0f539b2a5cd2aff144a53d39beb3004bfd54dd92a4ef71edd02e1f92e496f21435b9afe2406b058f79fd95626c16a9d483edfe2030233767ba2911fb73bdd535995af3f65088f73967d3896c7f23d31d518a292a2a0918a24fea0260d455aa5108ccb8ce48f28d7198d255eb33ac5be87cede16f3f1fc0aaaecb7dfc14ca53cb8a1826e0bf5d2dcd9c397e98cdf8711a8b78155a09995fdfd909248b779fa92874b15bad5824eaf650535afa1f72c127bb87489958834a4111bde5548004fb2b2c907a89858db4fbdf5504474baf96b3f81cb1da6facfd2673e74ac735cce461215dfd358372661f306d89f90a6018fad487662ac08a48cbd52ce3e726804092bab24accfce86e0065cddff1789c532cdfc535ee8b486ef845dfd8598e68c08086125888189334e60b64c5acdf117abcefb7f48626eb797faa96194221d98886b8a2948308d0ae6e4fc6926791a32194335d7e99f782595088c3fd2ac255d7ba820fa7f97361b63736c6ec9092e58ec815c756ccd4ad9cdf271213ef314fe2139b8c2ab8ab301a88f83d649fd6d5317d48f0fd6c13833ec0063b9a3d2122c1c0c73927e4e9b82e616ea41cd275ef6edc513ac495034c6453a9136b2a64167fa7e1208c5b79f085405698d84b31eaa2e9f35f2ae700ac2fe0c60d866eeec321ec709636fbfac26e11faa83c830fca5f8516938b7a198afa14dcc4cb1320f27a97cd2864c494241942d35ae298a5070b12094e51db52088fd06df52138b691f4125d7696189f306778d5f69eb378d888f76c76378c0ba211c98816826732584b4e36ccd712b54948a2c9d0a6923e4a3dd6d939bfdd15a29d576028e002ea5b2f5da4718a2a1b6c936871bede6f97c01f6f882aa959b00b322c9be72b4119f283043a31d11682af482eba698d382b92dda710bfddb41d3e5a0a5a6110d58ea595f03c46f604985645c7fb00c7a0e268cedb855e2a83c44bcc1de0445a82888d5fa07ca27cdc529b8a522e5d0869edb4f8f0f0bc5bc66b18e785c9b805085ac4866579c3d353ef3aef1c493b17d194c4c93c11971091f84eb2cf5e12b5edc3933738321043cdad85e25e559c628d18c884f015a4e31e83371aec50d68a52e82d8f7ffd5a30597805ed201fd2a268d231af0360cfe7ee77b8ebc801e8f3d9069088cc620740d39a9ec66c3d55de44ba3311f0c0c3d997f836e650adaeaad4c0d636222d9af3ac383b39841043044ae7a6ebc21ac4727fc58806776d48ea6115462ffcc47aa27d9f7615923ffbfbf266bd7e348454859bd16abe15f360d8f1baa9954447b9f72d3a342b2bdcf052044ae1e5ca403c011a1bb2164a1115e02afc985ed3d48596723fb5a905fc7394864f02b88341d5980da87865c7f415407dd24cead9fdb014799b763653b404e2b4719ad164426e7523473deaae54481c7183c25ca6852fe34897033d11afeda232f86d8dfce04cc22b0803b64fac10ae0cc2d49fa13651dc972101d11a52f732375a7c4d73ff8cd88e7e85546fc9720819ab37bf0379bdb37eeb433b8b5962f6e73d8a355b766944d2b7d1c9c4b444b17f3f6d80001949d5dda926244af2a41de1930a02375476c37954211ff04a3f91dcb362ba78f5d001cead8ed8f75e7666b723d91cf90d8cd470ca123fd776b80410c4f309f6c110df84ee160ecba8dad3b7557e9edb303475af673d0275df206ce474e7823abafde1540a16655fc0cd0211728ecc972ab0d242fb0717763d291d58b647fb5aad98d9f9a95037c128954f54eea2bdf81ae066f8538216edd0d78d2c218e924dfc631cce150f3ce0d9aa4634abb68c2d4be2554e80025f300fa03d9581e6b0df005bd6d5d8e010981f4ebde5e8053f3ef0c326278c777a9c3f5dcfbe3edf76c8bd7a6bb05d9f2ae10f46eb7e2311100135927db154942055d90b8739a5df17314956243afa91112a01d7283a2942cc394db810973806efadbb63d6b9003e91ccad622ee6d41a91ad659445fc3f44bba9b5f48646ec48782b14936d02f02cbb3397f70ee2d9dc0bdc23be46bbdcee4ec0f3c064fbc5940b197315e7b11376e9fbf5922c1d6b927afa24e61e6e4b59d5868644612bfd231a8d673089050996e1839aa9c7a1ca9f0f01295c7dec2cab7654ff4243bd6575d22aacf0517ca09c5748c85273a99db50232e370f8a3163508e267ab5866ad6452f85a8487c235c08aeb7e5c72d92d57b70ada96d249046a14634a1ff27e1741a1c96a7a932890b544f115fd355527dc7caf3111dfa478bff6630637a73790ac382596002ceb8fa0c6188f4f011527be1d880410b0751c94bb00f577c16eeff0f5738939610c7ed38fa77078e879480d2a8f6715212161cca47675deaae401c75132766f1edd2709fa7fcb8be1284e40a4996ff4d13d9eba4fe3b3a4fde1b48f5477c4f0124617a835e53f9ff27e646039029ff77afd80fcd81851c97d4561a06a0e021775943338c7766847598f329a6a0f45c42c6ef99621c5af1e96ffe70d40f3a0b80a5e083faf7e04fd4f0b08f568acebde7b0572b891635e0cd1ee98b53ba15f24c5edf152aaab9700eae722896f5703b20e011a4f2738ccf969d4f5694d762b925a8b93a1d57a8a91c41419bd23c62d9a28c48b3ff13746079354f17d6815fec59bd07099116240335a79d0ba74f6f7c1998326b2225188c849f3af89ade934f763ee2e9ca6bbddc81c3a1510840df3b24d1624d6354ed10318418e4c1d12420a91c76c68bdf46baf1ee459618524ab4de9a41296e791e49915248a4bc9c2454f8223be9a11743c36276b25cf4faac3d74d2171f63e4dcae9d48098e24c9904ce446b64b4339225f523537526700f85b66e391e04a8756333586cf419be957ac7e5ec6e16669427189ca21ca34fcf70cdc7c2a8f31c94a6e05b60673f0ca6395cad71185936e064dfa746a037a7c567407ce27128d35a87c36acdf996373ce02a04fe71b19e7d45e88d1f4450b8d25d98021029ecf0dfc41dc352dd5377ce488ea2721b4a66cf1ec55189d50a972667f0ee4cb3504a7711a0cb5d4c4908780bb341dfb767b002e6ec7ac289e10dde285c59a054e82916229d798134f058808f5f9c6116e895a676c30d5c41731874bf0c93c1201af554aee52231471e887cfdc18f317dfb908fd2cade1cc5e81cacaa0a457fdd8968a42b30b9d934434bcc61db27c386fe8bc7c00ea36c56965b9f96c0dee97879a67ea3e73a216b2f568cc8ac7732b03141376fb6cea78e03eba834939cc38aa3a0c84bffe6739716b79589e0f6122284b96baeb02452b5b76c8ffe4200943a10297755e8595a68facb63959a281d9f44d16f4cbfcbfbb70218544205d49c29e0df3e302621b9fdd8efcb1a741fd46d30dc6de233d602577b616b49b709ecdb3954cdf9032a59346b0239320d58ffa20d2e013d6b0ef4f8a41264e6af851ee7f46fe5b62ec9f2df684edc0555d8cc01113896231748e61541992158f735af641ef7296d6979229444e4c0815d5358a94826281944f0659a688264da578b18003f7ca2ddcf9f47c4a89e61f117146545901ee419aa9e1c78427b9fc35c5dccf93b28def3d268f609dae10fc4ea57ff91a81c0ce6480fdc2e612e4109d7977ee33d763a7767f937f2c79d80cc00ddf2f3df077315c876af8a29e6f103ab791a18914d2cf60970c2968c184d38a998ab1dc9c091ec95c5a71ff89884efc42f85f6c8558e5bd3b67d008f4cb3fde01953b2652fe16b682205d700d249e6859655e742b620354631aa6ea5c9d88d6f6728a55a41e8ebbb997b9d6b622dcacf0a7665c285978107fbece7af277881b73e82b0e90beb2a28c445b789ae742181a06aef6051e28f4cfe5d05c79a88e6d310cc019ef3d227b126bd8f6765e7de0de30da94f91dfdac3917a2e3fa2a19d13b6a9da74a7e9dcee3ed4b7daa794e0eb91f126ee9433081430ccc898d31067a4080f0ca7fcb6f598514d6a94718318fa46577eaa0f45a605f14231173840a3919e4e1d3f7cc6812d6d6596b702738f76d75bab6084a2faeb1ed8630d41071ccc705dac06150d7c262a6705ebdf71e5a5b8abc76ea2d53330d345220e19994da782c2cef5444a08a409236ad95e14a08b39ff1333b9a26feca38d76f953e480e87f7f7bc2c93323863dd2ea6169109824cbb3b009128f2df133940beea3c061a6648b2944d9f30a6cb5a81bb212260aeb59435aac706f3ff96dae0ebeb125a0261b0a123e412a44897c469b840a55ac51b4603147315ec1957e3563c679073d6edab1cb98de8fc254c9204c8dc18e618eab0ad37c4faba786296acf91e4babbda2df8cf3bc8d1ec547b0ebbacd1e49584630683391c714466ff7574a4900f5f9d51b4f8006347733de1596b7b6df8ac885ba64858e8d9412699abd7487cec8a41d83b2df2e8e81e40f1fd436625baaeeb50cbd8f1fa265e87e3c489cc0b66b8216cf38128eade0a9e00bf7c68bfff3b712bf832085420bd5c122a1fc175a06253948f72171221aa2dffcc2b58f28a50df2e55840441b211e50abee33ffed238a682328a7f6cd4012a51ea050f5b242591a466d70974762f0fc101747cd0987949848e30ea59d93570f3221491084c127682d18cf98c4b8e3f110eb1f51057505728ceae23ab5040abab6ad51eb68a14c4dc2326a1c5a575459f436baa1265a90d9c00a58d322b99c519359b764f3db6358fa8c8a9b310bcb2bc8ff8f959fa6e3748a931e6dd7294ec5db657528ab0a999503855e1e20b98302a654261e0bc1dd2407a9695b278c19234a3cba31fe60ec8c4474cdfd0a0707e3a95d0ad1d128157cfc1c1ffbea222f52cd0f34b4fde233a175a3cd82aac86083cc140510fb1e1c8f01bb21cb57c01e18ac8f00530eb871f52b55ae7649d64e5fff0f88926e740d0c993d1540a2bfb4e8c9758b4ef6cdf7567811970b4e94faaef192000200b49888c862fc9d65bad7c6c0f8d87be27f50b4be119042ed4784a4317845436190388670b22a93c645fc0657d2f350ea1c239a2a90443f74ef3550904e785cb362855850c9969bc34c858224bebc1bffe5242f04ec11ebfd534bc5f88c316c591004f1875f2bc596889ef0942c06d852537a9570ead758f490ca779c5988463902df32a49454cc655ea44d586b321a1251b42e1a02816808b58edc664ced8187b5876a73217108fa93c4357a00f689542be9bfe050e5ddb10e5e40669b90f7b5c8c86a0ef56f0cadd6374040906d7048b6012145b3bc6419a02f30ea8ece23e602c03b1daa205fec288fcbd07e88dbb8be62293ada3189e2a807cc3ebe94e2ec9d3818a8d4976016738815d960e783a10d00ff426b815b541ce0b2b34400c4c501471cdc8eeea03662ac4a7b9f5a6a32ba6a21580c258e1c5b76778970a2c897b767e31073b9fb804a268e9f18a3f23d1a8c91fc606991c664b14206c74acc62c7cbc5375d9a0c59fb9e42f1c4455fca840e2f653f0cfa45ae86931b4e3fcbb387e74e2548143033ee232f28717167a03ceaaec66557faf5eb19205770738e286a51f2b76a90aedbbbef373c06b09cb3a6f7689af6661a824153ee5a8ce3b067d6bde74de6a9d5e9474ef6ef39adf409ea131dd2681a7abbc493a400ca1c41530ced1e398ea860cd337ccdfc357ab9fa53f29f0bf1abbaf02e6158d9cddf7e211dcc4179e5f1ef000567bad7fed739d7c074384173f3d69dfd14be459d8f00ee81d1009d568f10e0702eb1009faccebabd0def3077dffd13ffc61af309aa88734d869767b867632668e8a14cf8c9acba869bacf9a37b5c822b685df296d8cd49f16f252f3eb06a758f882ef5d599e84d2d23e8025367afc4dd6075e6f59dbd1120defa08088f618051ce1756100ddd5e71622b27b3aac1789dc1bd4963b3b54596cef50f64795346f39448c5a47bbf8bfbe0c01c33b31ca57aa8bdf3b98505f5eaead16c0927f23bf99b983a3d84212da3d3e8571967849b95636df66103e9f0a7c6056def0d952c2d53a302f41ab2ce398176e8f0837a3d3351f8c3f218e7da70db13b34611077651bdaa666f426f767413d67f64cf675950af654987ae977f8198c131c67b56ac155c0e34d24818464092c39eeb9356a0b6a5f1864fe07582d3d0f46972f9a0ec46cfff0f11db38cb3f3ea594fdc50ba944ffdb0daee7477414e7588490be668d7f229fcb6fd50ece42fe3733e3f1f7f59c2e7e5101f3f60f8e2a750da42efb978b083f1551321e91877adddd203004f4397c8c3c5f4e97935f40e8fd9c63b5364d589d3cbff9c97ebad6b8af2f19de8d46978f817fa3860dc069805e1ad075f56274db8817641c0d6f3c045a877bcd037a0b9ff61f593c6fa2214e97c2dcf5ec292b215b9faef226a0962e4d4ae7e9bd026de1e034786dfee8b444773c74c94fcf4955561355472ee184871bb0d42dc7e962384375b913b6a8655c41397ff87e46f49b1a4c518d739749ab5d3f641085cfd85a2515073cc30c7ee354a980b7010f04acf742226d45cbcbf52cd785fb69f199e9c5bf243e151efc081b3dc57d58d9dc2722940c771586f0640cb3ef9e20ec5ffadcdd9fb7700a99787c5a08e00de42de32a821562a733dc6fa8bafb8021ad91030fa5bcabcc6b526fbcd50bb9641e0ce6b5aa15cd5c0a9a1424903e7dbed9ea411769a1a338981c2c6f7784dafc972acd76e3a1170bb058b989cca2ca66d9d2a074c606ea56522771e84070438bdba07749a4559cc04bd3b6a9262167a6ea67eb3e61a855c61c4a66d76814ba91747b24cd87199770b8a027c08f777df95c432ed4a556b7e99ed9101c287df42651e99371968a58eda98b75853af3d2970f0c31c0ace6eff6890a5433b5c928744b0adb1feb2bd0246fcb330f26727112c63cb88494a83622835a6f0921a087bc7c163df72b7c270a86f5b059bb43c8ef3f391744c64131e2d3cde0fa4b95c89cf8d91114c117801cfb835c2b9b066ceb7b3efff04943f17d17f7a0055991ebfcc6cb4960451adc70cd6d8199b4dce6c5d2d4c00921c4ef7f56def575acd0ae18627423ed4d2ee8711767ac17159a05c010dc32a429ffa67665aeb3592e63e1d519239471dc678af4ef3b926c30489b3bcfb7df57d061cd75c6ee72399fdca263404ff1feefd9ecad79521ef88397f7dcc2810a2ecedb1d6daad80614c53a80aee3aa9251027e7690dac000b9b8af8705823bbe5cc754c6df5e93dee6f3a0f4934c99be72e64eecc623d8b4a38b5812896e521e6076a59b0ec755a16ecb4b47371c2b247e5160e37afedc2d5450df0a649d8fd76205c45bec967ebdd4df13e3fa89600e6d16bd503e44eca8a1aab90e2981bd846d4a684a5b21a92d4f0fbd2e22bd9a63c336f9148f26568b77d71db85115255be86688ed72fc074d7eff109f0e8fb46132b916ac0aa2da24e372a959676dc6393b5dcac6f12dc0933c637eb223af65b6bb1393f149a78f904396477a76007bb43a16eb655194a48ef810e5961edec68978f5524fdf79367679bde5607fd4090c365fda7a64526fbdaf9ecdb3816f793b871edcf2cc656c72c2b76f7c1e05dbab30071b2dd2f2c9827239625cc4da1ce4e32c474b3ce900e1a4ad99fbde4e1266f0650cac1dffb0f81d83cbb4c7c997232a489089e2d81aa9de5ef42b7d5b04526e9f33d1a242d663714bab14464a8457756144c2d7e4f94ae0c7c2ecdf41a2ba949d756fad1710b0b341497f924133a6a75abf19bcb09430c38df327968b4a96617c2c88aef61b06d4342d1d4088f1a931644fa1e3da6ad3529e5fd332684c8ebc8093c7ac4a88d04666418bc03fd305a54a15fce8eb2bfab80b24c840453a409e419a2dec1b808a82c74d701e155229792a7d3cdae09f7fa766b63b140403f3c674a0bf84c8de726ac6613b4453e53159ecce2e7bdde49ae9b2a441954320364a252da4e8b87a1b1c7c1b3f886fa94dcf119fad71f4ba1af2cdd85fd68adcc9eab6bc3e12689383749ed611ecf2ba2821ed58657eb7b76d85ebd84b3aeaeaaddd31eb59f28d06d86662b8cacf759693f7ffc3eb36721a6fcc3d02e4f301b2a12c6f85f205b57e1e6d80aa5e2c9471157d5d4864b70057c1b134f301fd300fa1ab09f7e8e2056f240564a72276e08c8aad82068c3c670d97aaa626cf16ac1296efa217423580200eb643f972df16d382d217ef0452428823a965e2ab22653faffa73c9c25a5671ed8da07d4c3f7b1d69608c946a17d0049ba97af303da6b82d581a8b0ca62a8157287eededd1e63829209499d20959da9d9d0072926d0e42c3fa41d4250db4ed50241323bbe78d15b20460b998f136e07ad676c8f9b48b76c924c48f199ffbfdc836a1248418c49a38158940a49523ed52b9d02cca6110a42663f1ab9877e54b25c9e0145a0be81c7e65010489501de75b8ff76454ac3daecaa2176662e3023678bc47916db0c6b8a6d510223543e77246a87fb67f6645d9f625435039eedf9352ec56187cee28fb37ad07590de40a67616201d82da5a24dbffd31d051e9e2a960c44b6a406a0cb753718b412f0dee75fb6a3ff8d09ca56fc2c0095726eddff1c610265cf8058d20ae7f517495a0190302a27280b1192d96c133cc064bb797ea5eaec7fe9ceeb3f861e87610a0e0d9030662423d2359e5aa8fa3340808392961ce28f922d3dce0212066619665d462461a885fc6a04b2575a905cdc45a55f8a3cd31957229eb152bcab7675867d4eafd2fce0f1c6ff7e8a3c20c9db430362c0f8c788b7cf93f0d890a608013f4588e55ad39a3dfe07e75f3830f71dcaa4012bfa2d19fc1388dc008b47766718a5c17a8681a02cf52a918706190cd7fb0f5af7db3644021dfd0d74d8f2eddd6f21f250f375969b97e2e93a4530d22c82519aaa3860e914b0571b22cf35ff6622a506565a1a7991f64311724d6971652f92d4a570a90bb4db8011825b77d441984829ddbb6c9e378b4aa26808de7c0f7e2265d7b334ac7b30371a0d7bc7e0c72b94cc9c491f264f2675b38c59010d36a2ca7125a99e6e9ef31cc682900e4ebcaae3172a8119cba582e2962dc58b9b2cd9afa2af651284ef3803be0a0ee45f36cec000016ea3ff19e43c4a0ef8045f20f54abd40905b5d24400ae7f18fb3c2d5e3fd4557394d12f68b1379aeca5faffab70e12ee103c99c71dd40bee6deea798c9d7ddbddb5bc7835dfe3ce56a12415bdcdb43d500412b053b4acf23901cc264cfe3a0e5a569c7744666600de1632c4060b5a8015439b3cc42f87f683846025ce26d3d3b4c9ee597affb28705bd8c34ef0fd3893a65f255d807afcfc1efb14794072dfd3d111b1d3fda6638220f56763cb3b39d6139deee05b6e4b7190a730cc500ac365bc749ffe48abd7cdbb6b0f3c03208f5a37d33d29ca0facdbf5070c7307055e7bfc804152eb8622d286d2fe49de4e73f48ba5f5c6d6b5279d52e5c459cc934c2bc3445682bf5ca03c9bc0a7a85634d801798acb4708cf747d7b5bbe8f660e8fcafa4d10ac723f52993a0b060a9a5aaa1d168dce390e7fe54812ef87d7ce451be865ccaed774db9f48b26ae3e30d10b255f9cc2c10b2f979e12f6a0882682e1260d91044245df4c91ccdf2341d19c84bb73768a2130eef084520af779906ab9aa9594088f2ebda13f63ed0f4ee6fb1166174877d1f94c8b5f30af25ad8849c676d584789b04625cd272056bc63021a9429555f3010baa20e1bdf5bd0abfcfdc9e5f1d65cc0ab06e8d24e259fe54a60cdec343aa26c349795f33733b74af14506910f850b5481b8a66339000c4041c16a0a616b74e8a2b27b34a853b7fb166b06584b07d79b01e95c40ac6cb2f79652262965720529051e0516e7ba524b3b6773605ca99db549e9681cb1c954527f9e4ab229f313a1a705c73f7e62b80b2e420f0c2777cfd19d161d734ca33bd40797dd452ba54b9d2d1dac7f0bae7a9be74b80c0f0984f45df2686c3c4b84258022486c370fa3630ae106a0a250001eb8971c1e8b0dfeaec68ed1097db5698d2d9564a67716aad3029add3bad44eedbd374c8b05af61d740edb2f2f175cb3f0b989e92cd81d131ba63399167b66e49775842becf0689805d51a3c25c2490d6eb685b4ed22941523a6af3295dca45aa7aea466c939e9952f24c8b43a3c400a83ff7743647ebdee6b9f54ccbf50a078c60c6613a8d920315ad7badd3f5afe1223b60ebe4e51738d9ba6591c3827feb5a1bbb772e96425a43ea59b73c1461d03221ba734d24d62a25254d99727b525732583188bfc99153535333c526738d29c90cb7d81d52012db9204158d8995b9ef14cc95784afd4d4541d39ba73317e614805b49841821cd964ae79220b3e5611f62f073daf47aef9a0483c746bd3f1745eb0c95c3be9cecde11d6d56d2ca4ed25cb7d53a96e9590f7b050c75f2513adbe407cf2b8b266479461bbdc1c64938879794bc2742d8cf0a0a4c88a802556b8748550666b4d30a9140ce42aa58832944f7406aadf507cbca0f9abb41b8c6c355aada26738d56cb65aed56a5e4d68e32c8e577b9b5aade6d562b55afbca9ae7aab11a116cf2abb18fe80bcd150dffb192d8648619599ce7469fb95fb06f8a4d662253890eef6c7933ec4587f4f8de845d170f8b872dcb309b9e4264cdc4686dc226318ee48f69a213427615a56c3a31755284fe09f1a2ef85625f9fcb5b97a9da702252c02e08a4190e46a5e8a73ce0091055bcf0c410342c3521c9ba6b84082dcc408512a830c20635f8e921c7229ed84a1f624448e992a728123ea938d8103631ab34e9410552f4b0d4a5e99a1e0b3718498189932351bae02db80b1d62064744984cb8e0882894f4c04005382891c31250a030816152bc2596e8a40e144c90b083104d1c2142861d1c9078c10443284c51225344114438a460490d2d5c129c4a47546981141a8c48c2a566fc5e30faa5e2192ad8b0bf53245d50276b7a0d7423e83563cdff9bcfc58a0b66b05539f221871e3a050c2314d9d1a0430f50ff7fce4fe89fbb8e84feba5d84fa029a60e2031334784283ea84962a8a308102292b30a9095f3802c0f90c742e549609ac0ac6eafb966c12e3c220d8e700d1afd97abdbfb272c5183c5ee57436cb60c9d3dfb777385a5e471cce8673f1b7d161e9d3599ccf1fab08c431ed2cce9ded5052f5d2f19cc481ab3ade85837660790084c8e1d6f6d416c9b9f8c426314e67730a53a40831174c419bc98aae57239b2259c975f2ebd40a52af3158d9a157fe8030a4362affd5bfa5316badb5d65a6badb5d25af9f68e74525b6b6d487728afb5566b5b70eb72eb72eb72eb72e372e372e372e372e372e372db02c56dcbd26d8b79db82bb6d39a2b5460d9b4363def020208868d6a04f286e4ad2d788dc5341fcea1725bcff3c3b9e7e3d2e1b921146e28d594681c156399511d6a27ac38af06749bd5cb4a335b25f8036f9cab9dcf21e8ceeebf5a95422e5a107a01723d8ce6c122bb331d885edfbf3b940d62dd731dffdea79615fccfe5c58ecc2ec8fa517ef44509363afaae5964677be070fa1729d55e520e6403e8e39e80a2184cf2542cfb7df854f3c85e7c23bdc73eade02f5b3a9491275fd497f3669816ea7aeabfbf34f12eb4ebca46199a809ad3e1d690f5b67754b3c46bb6ef98edb9ea5a6d82b20f8c76af523f306d09eeca26f93b90cd965cfb7b11c48d5517b58abb3b9b779bdcd48b4496ae3d941ebcf6e11b31e888c6a2fd7d67fd8307e36f9321c846318089736548e774a36f9b2981d650cc8b6207ef6349bc3721c289bfc3a0c23f6cb5840b338e4cb5e6866042352d280efb97125fc8be1b269a73de18ca15a2dbfa8da4772ec987fdfded46b71140fcc33e7791e8b2f30a27c9eb7a8ebf320861dd3e90d28d6c9efe365486b485bb2a8a0573a79eacf635cd8a756ab85d49f9f401afa73f0ab46faf3cfd3d29f7b9922f5e7f9d2e8cf4fd4c6f31828bb721bb64862d7a5bae31dbb7c4e2717596d2d2415b2802eb2ce9e8021092b648535a18285daae8b87ff77ef585da23f87c9a12ef5e736f6dcf27e5de40773b2654a8a1420ce4ea5f070eb2f3a95c24351165a9699c692744f8b4391a834f5caef0ecb945ef965aae00da04d3b7d71b2b9d73aa19e9f38863d06fabbabfc9e9587281c448c426c7a5b629e6e903061d3db9227e02703884d6f4b683d7b34a4c06d7a5b1294b3aa06fb9ea3941dcf1cef98666cb06d4ed8f4a6644acf3c5fc08e90b50d099be4000e435ab99755fcc4c1d6ebab9f06ed50adcb744f3b569ee5ec14298bae77d02952965abfb9cfb9b7c9ecf547d7abe77d9b92dc26e91fa72df2846ad5ee22afd722c19feec14c70aeb033a2f38a98576c598e9cc05d2aba0f1cca28a57b44e850cfd3f15a96d3d62984fef42fcae739b52b1c60a45ca253242d40bda24eae6b2368d74eab903649a73c946991c24ef5bb63416593b6bc3b6aa3f2992b9bb452dc9d15297ae516f7d5969fa3a94de5dfb77725ef0e85a2deb7679feea3140429583b9d28a794f290d2bb7bad354fa552f4ee765cb7486ac26664b55513d6c9bbeb95674d6d49fa7ba9fa8249486b564e564d487021c90c36fc5e01f3516ab4554b4c0b383fb0f13cb9a1600537a8c416f0e0461b1a5408952aab603a9c1d66b23818e7175a482d0e06ec08dd02b4a656cb4aab330babb5d64a820e5973b823db4977544763802ecc453510e28804c1e1ceddf943a4b2497cda78aa082cab0413e37bf189a9c06295d80f9cea9ee789f179be4e7ce2338a4d628c0b67a82239639c63f948f6e1d3196532c7f090cfa1b4c8e8c9ad9a407e3407c45110219fe3e178541dd846bf87c5662c168bd55806bed8901576ed53e2e1b0a8c7b0cc3e89c562b1582c9663b15cc32673ac88a8eb320ce80a19de624884563e6e2743d031c72e3ca5571ee25e5ec8b99e508d54181122d4062b86cac566c5a6cff9478e0133a072c49379a88d950d4cfcc4da9ca735ea571cb2d96a3897cbe55cee737ad88688359009199db5cf76e4e172a66ec79497708f8725032446f8c9c73aa2a481349c44a51e3c974311891f1aeaccc972b30a3b4f199115139bccb973979ba572b95ccee572b95c2e97cbb9ece26962933977c6cef33c754c9dcc39521b754b918e40d22dcf495969a756405e7a323f7da007bbb0ed15835168b338a40e9f581c9273bdeaa281cca3dd77c2807ae5f9c7e6506b12e5b250467214d4adc89a313799694a46b6239cd92b3782b1ca4d661a3fa21d99baddc538080d0245ac00d7a3c7d2a675ab6328135657beb27e50c158edef3b619fc07b307f2ce36b8f1f0ebbea783cbec6ef5eb18a4d62d3b4384a56e35c3b5851857854c524c81933e8cef36b574ae85e64cdc468bd128248378ee37831d6c13a01e8c8d2ed8847289bc43a98d6e1b03c45b1724227e9ceaab802fb442c7c5c7e38540f8bf3c2294740d5ade094d75d65b2322b544ffac136d0a7da5c35f2d7a8b35fff03bdcd73f235f2076d0de7421750f8fc3ddac945aa5c24d71ae752b8960c2cacfd1e592751b5fecf5f5aa8540b55a475a8965ed2bbb779eed13e479f6ff39cf67291e38be4a38a6feda2f5d28ea8229c1d7f8a1d13d0c240e51b068375ba6593295d4a6771327f174a2995b3e39f6c4415e5f1d60c26db5a2e030c7fd1c286e11bb7a70432a81e39740e94cf9723e3e41f39cf22c6276eca3f41281eab9e5d1996c122b06647ef63a07cfe2606eaf59ac95806e583513a3a38364754e5e8082046072cb262074bb0ac5a499bda1400e6b43bb165faad7688ea34c58eb957d77f533f8ffad730dfa19330287f5ceda93d65273d18ce45074fa5533905ace1dbbf630a306691bffaaf027157871520add6dabb81765169e9cef31cf0a79c95b37256ceca59390361a50e2c7113dba73f7defbdf7f7977be9342bb136345a75e5a25b24fb7439086deb9745f433ac628da49362a5e5940771600cb481486c8e260271d906e2b20dc4651b88cb3610d72dc72e3d0371bb04631a3742dddd52faffff2a3bdab0d26b4d54df58976578c9e6e026a69fa64e6946d22da533bc9bd158e7a1ea78a7fb21e4236cdd29cd3627ff7c397e397e498e5f8e5f7e795d19f6e5e3168f21bf11f063ecb8453baa4c0869cde3df3f18732f63ee65cc69cf183fb5d60948433ec20eeaa488f9d3f2135493ad3dba93790e9894a4a4b4b4c4946dd67381b19a512e7a5a51b7fc69f949b6c5d8926cd00625fca7d6fc18ddc99c72ab649b96fe8769895a269207754a69b0e49c33de9f8ace70bd26a85fce9452ea1540ec98bfde9fa379a79c522e5a1c4f87b815a39f5a958e1783e0513e70ffd7cd073c3becb8ead895e306b17f9eab870d3b07b136965b202fd83549b695de9ba2ab4e5b23e7e6b512d21a129c89ab992ebb72f19be1b22ba72f3c17dea775a03c04f5cc96939e690af54c155acf5081d23353a4f4ccf9a267a4d87a268a152674529567609d478b8e77345842183d03458cd8e2bbb4859e6172a1679e78a1679c50e99926360c3db3db756557a2d812ede5d7f5339ad92cc711bb72f2599ad21db1531eb2c4950c0cd50b172d626058acd8628a521bcf2938fb70105933315ab3b4e85393c521efc5b62a0a59960baa8e673db9e21098063967f34a1699844cd3cca6699aa6699a665e05b1496c9ee697b379258b409bc4e6cce25c9bc979e7bb5049b758e9eb64085a3859a5c0cca970fbe86d9fd212535365e1feebc3aa8efa24fc09369961b60cb31df11cbe2e534461b7dbed7641769fa3f3dabd7638bc7bbdcd2a072bc43ba1f37aad7ed824debd8262d7f372edb26280c522f988c7d35fa0f37add609378477edf6ee784d2c621f98b8ff8089733754736982658fc21c5e757bc59ee42c1c6744377563caa8e14ccb66e3a1d9ff3ca420fe5b935e46dbed6a0d1fed8f18378d80f54835052361913532980830bb7247070e186444f76ad7e642e424fb5b5b440b1af6da4366a6d61776d376c435acaf212435a8205a4259ccc45401239feb038de0afd6f192022e43fa6ff8c6edb1fe98ef55184a21e707bca6f16bec7f377f9ffff7ffdfcb5b063389975dc23e0c1135bc810db29af595d7e826d5f5f9551059511b4e003132756e811e248175914508860d0a16e8087edcf0ff0fd43d0dfb5e291559dc7f258fed2e1232c8865c325da5527c3324de74f6059513c8b0526a3cb5201b398c82c2426231cca3e27c3322cc332cccbb1ac425e0128c37086e936a983ffc378a7460daed961933a3849f67919834d211623599651213c5996cb321d3bb2926c32cb4a8b437edfb6ba23db2ff90b03169b38cd1d66c22109fac14ddd28d7c864cc78418c89e961935936eac870d6c1185794f1f560b884b486c4ac1dea0b4216e3978d0e6a442c46b16f181fbd8468331c5e22db6cd4464d3a64457b7ed6f33c89101942e4737ad8a88d9a94e7864dd6d0c1dff759242a8c554460aca8f83efc19d9243d797037cf42a11b10aeef1bd051af5c87383b299d7c85327042338b92a24801063424e087235424a15284922d25d071934373769c68276fc6aac5a8082615826628390052c10d8caab060090a27546179484615156f6e743ee041da0181b423ea2f9d22ed76e8df29d2ae68dfa4f0b33833313ae5d4feaaab72dc2076caf5b8756e5e7093e4b338abcfe2cce0b7f5de2b850b2ed010d26a3f876c579e6388fa2b1f7702fd9ff2da439cbd4f25034ff62b3d7da85dd8955f8dbaa997fafff4d24b2fbdf4d2a717638c6fb5ffa997d326c16e01ca575c16f79f5e7ae9a5975efad4d6fd36947280c4a6515200d4a310d5be2833a04e2dace7546b0bece25f581586a1532f2b605abcb0aa2a63573a869e71e96f9199467f8bbc35fa5be403c0dae84bfe0d2dc698999999998921ae2effa72ddaa22ddaa22dcae94dbec9f181cc6539470e3de39f8e74a4231de948675096b8a23c090e38a04183060d1a1c88ab1a5ac7c68d1b5a001dbcf4a5aaaddae64befe0f0806ad5566dd38300c8c0e02aaed2dde8db0a73bc8faa0ac9cbc97cffb6f0df6e53a405fac5f833c7b8ba5ef4ebca759aa36f8bccd1d1d1d1d1c981a1a2345a40d03c18e34e29a5547f18db3e001040000104100620ae64bade81f2e9d104d028eea369b4eccaff2ff0a5edf81f7fb8437bad15edf15c403af6f5e3e55e0bfcd0473fe7b1600b68f7787c87cb03df65f880e7711914900b83c140a95040a8adc7737d6f737bf4f0e1c30049ecca6f6800940fe596e2fed4007c8792165af87fddbdf7debff765c2ae9c7699fef8628c29e5f7f2fbf6de7b2f79efbdf75e3e81beb3a2b406194a378cefaaee0b4a73c62ebc0f645e829cff3d92524a294d0df56d3362d8b457fe351c4a7c303435e09c5984a7153ad47736eb1ba553a8fdfdff63dad354a95496752aeb14078aa60699de9dd264a121a52c4098db9f6686a7fce9cdf705a7aa8b69b2eccafffefdf25ecdc2ae3435e8dfa10c0cbb9221454e7eb4fe8b29970dc22afa8a6e9158218b04088b647fdf6ccb0d3720212252e19c5b1b7fb6e70a114458885ab0028b93224360c6e284c910967b2f2e3274f50cc4c50c612901cf86b00441a404516c6868686868e865c51a203ed5db10d157912125980cc540098fd39c2f93a159f6fef38727f0cb1e11d8a274bcf7fab85d86907f210fc3560f8f874cc7ae1f2f1232ad56e67aad1b1d3bbe2ccf074c3e183ab54622bc033f82311157e19fc93f131ee32970127014781037c247c04f508203fd0f711378095c04fc8717c1f8bf0ac6ff55fe1fe3ff2a355adab1c88245600d2caf8659fbf7e2ff8b71be65b65f065129d1850a860c2b869e9131736f93dbbd8dce8e3a1e5adc913de2bca5b24facade5a2716154abd1d4506c6da929dd89910116c9006bdd721932c012cc8149604ed300106a7c82252db4b3590f8f2d5df4979cd2aebcd542f96825170d0dca472bd5cc60019616c8c26268982ef54f529292d2d212cbca5822cac668c6154de7298a2b1936bb32ed762b0d5bc9d8d8704083460d0eea924e2733d2c0a7064bdb64cf5ccde1c7377bdad39ef6b4273eb26755b2e357f3a50c69686dd240f968a51adab46103e5a395b44e9b375eca1adafc94bea58fa94ec1e153f51dd5c0a70d7cea56add5f23bfaceef667392929494969698b4895d2fe5d7a317a86a0b6ddcc027ac8b86dde8e0050ac96444b3aa84f6c2812486437be07da5492acc8300e4c83122dda19d4b40480686ac2ab56143d03dd07c841b7c3fd4264841203f5e72f44fa9cd529ba5364b6d96da2c35ac5ca17cb2ebdaa687d9539ba6c5f91cb0082c230096416ef40dcae7e21cf87eb76fca97844f7ce2f3fc8ef295414097cea8344dd9e62c64a30120200843160000200c0a850443c1589ae689e0e20314000d5c7a3c7254401c4783f14810e32808832088218418600030c61043185286b200bcf080c3a348d7876db866f6a26794e6ef248cea1d83a763c637ec943c36d68f0b39ebea55b918891650f9c3225906efab33c0e64f440dc7426f6e9d7126712937f6a1bf3f450f7d390acb105af172d3ad4e87d9b9a2388069995cd65978cdd5f0038ec7a6a88fb9aa379639c482a6c9f84db5bb991e417416776e16f0656da0fe626d0726153959a14816423bc979f8c5f060f21d0b4e1e397dd7c4383e6d686126fbeae6952489d050f8846f4e9e2d1261060b9ceb362b6a3ec027e47ec777d6db6b9b127f642a4c63b06175d2f782681322effa4a8a8a6f6044f133b85384a78be12ad50702fda2244670dedfa227d847c62e2c7b1afa0fde99a92df50feca93714c85edfd76acd7f34383b5c417fd087835b36e3c8e965e8550b3993e04461353a015f086a19a495f909ab742875b119d0c4a2fbda75b70ab607c0ad8c6e5fb8392e5f0ebdc005de02ed24ff6fcd20c997b8f6c6d7db1e430a5779f863d0c28e35a8f4cfda14ee368769053a2b5825a55b2db2d098237c808c0deed3326138fc21a9cef8aa72ad5f0ab446863fcdc2e2d35bd34f48075a2b45865145eaf84e9a21f15193e5755b24b519d2fbffa95e51a80019c946fc84d272c1482d221fe40663b2205feb86ab6ca6f1438bd2a6042181d17a806b13e27a9dbcbe9ee9a3e1aff829fe5fc6ce48973ee00700d57068d41e84c160fd46fc05168306816561adc4452673c011093fe32acdfa243db0e4272d120c1b4b3f83504df40825e786eec4f13dd0be0d5ecda3e5e233d1eb3318f07ba4a8022b42f315c3d2a6d0667215d52927eb4d770932b3912142194a6e3a3fe5325eff06575a673157633491f2d49a737288c49c1c205792ee1a24a1dcba011429682ef18e2ac93f8d6a445ee0b01f10f58c825dd6ca0387bf4748208b49e8210a353e1e63f30478d9b47b3085f6d50135cb902c22b5acb91d62e1cee1d8e698b2c6194a453976ff23b31c6cffefe04b7316a6eac62672fcc05590aa246f98f5ce98085956b3b02abbcd8fd26f818da0f33eb5e0c26b4d739ce0cf4714c2e17b816e7a6c5352da7126c9fae82b21043e2702f1f3448116b0a2264f595320db095ff032e72bb884a0265f375ddb5194c09e2bedf78fe98611ef60c5943c71ee658406540c315271e2d4c60f1652386a69cb9678cbcb227831c8c7c6eb30fdad87e477e5192392f90a078f73bc7cc4aa23798e5c9911240e01b995ba0a749f7d0984a9463209a6a9c8a3c63fc516638baa5fc221bd194ca915e86dc1bad2fc2a7891d22e6ed90e84903f595501586914bc7df38a91224b44888b404889bb49f2ea0a6bed066f725c968254acc2d97812b670acff0a1545d25121250fb2105020f84a3793996a62691a200d1df95bdece1cc764fc20ab3b2c5c4a716886e3e4300b86d628b4151a0013944c99c2b36a4ee63e08112e51a3904f132fd3b7e3a54cca77c168a297c6e9435e9e1d6871497179086592fa15cabdbadf60e62ca2ebe7d6c2e7fd9b56d407e71dc0aaf5d0455f3a31406b0584a63c3758cd0f354cb4ca58d7530bf3a28a9b52567f03e61e1b8984e89cbea6722e61b8de3d94d646684a442839a4dbab3c753d41e18f8e0facdc3a140b528eb648931c481d8980bd7a5a7b11046265370814837210353736fc46ac950747a3ff2d987aaf97fed71b791800fd82a04e6dccd5f12a1921367b3cf07496cabe7fa3b0d3e880d5077123fc6850c5482cfb922937e33175b72236fc3f1225555057e5f961344692f637e867b8f6ddf723a3e03472cf475d518eb58d46395b80f8cc62e1d61cd0da3ab79782fcb1edc0cf4db20db6bafc205cc8db0b13ac87360b9b61d0bf684151d9bd67de3ccf595306b2cc012ccdd444e169e191d3c3f9582a8bb17a0a68e171a3e3a414113bcab73c90039d36853e97b7fc9dac6faaff01fab3af7aa6d5989d34b4b6e2f8dcba433a11ee55170343d8817ba51d659e17cad5e1fef210495d559eaa64b2b651763759cfa6694705b817ab987185cb6e0cf024b229140c71dac1d7505efdf30a26aae4bc76eaca5da74e95a83c2de77032179d7697e54581e2a4c8810e566f07ee876be73237f32780efa1d0295bf16bc037a53ba0c7c853d5e85856027efec56927c659d8e2914a34f5f524985f2fdf49b4223439fca239facc0c81e0cda34ed2cb8695a7ab855f2460b68665d1163b259beddf852a4caeeb3808bfe8a7242f0c3ac6809c2a196182e6e377a7324230ab932f5553f1a0d3fed1c88688bcd156a0415ce8c8823b4a2f28b9411ba8d147f71430c1115bcf5845cba6156d88c9460e58f8b70b0806233e29a6c934c3047d5af46065055fce000d83033d4a7913c08bd6192c2064ce92de9675052dd4555a4828f236867597a9a888afecfe02a2e4560b696a2a74a947f5990cca3ad239bcd8384f6799cf80eb96b2c63cd1b372c6f1d17e633b6ae4778698bd040ad9e92a70ee08a0ea58209ccc39d9d9cede3037f1e63a58c9ff2914f33c5f14ce79bcb83dd90bbc0e5358757c1a0808078b9dddf23724bf39f877983ea03b95a57081d3e8751374de01eedbb87b072627070bd329931af602355e62b2f68a5514a1dd8d653e52ea713cdcc31d372a9a91f088b8f01314af0d6642343f8a9d05ac479d81bf27c14f1deb5ba9a9c99fa2a5f2ec7dfdaadafdb17a614934280e7c821a9169e5a60674062b443123b556ebbc7639f49bda8182409060a97101fd43e60f5e64877641a562f7883d322b809e2040025f91f1c999b45b9f2bd1258cf6156bf60b1f690f14533f96a9340c2c2c3ac30c3cb7ad602cfe012a428f4ea0993ff6682c3a2f3ab8cf36ee559b90f63a2c675baa47eb8d83ea691d4bbfc63d31ab67a46f385a46b5a0923197614e0ed0b6b6b92d64ae4f4843346767e61958ba0ad38c3611ffaa6f4ed21496ffa968d3ea1e4c6fe4a2ad98edfe3c5f84b6926e9bfb3cdc5fdb75a8da3a20c2d3182b647ce204e185ce291a7a08c28308d9de83f5f643e854b0f624da1993bb89472bcb84e1915620fdfab79266c70670daed2208386be883848a1cbe7e54ee585331d25aec45106a60c4add2ea3ecdf9252d4ad1ec5a61f42206f14f13ce6cbce5e370ac132b90e4757cbd9ed617db8b797158d1a0b5e476c694813fb4897d0f44a91a992e22c94d0fb97332b3002b7f4b249d48d6bfe1fd529d26ee25daad2c97a31d84cc822514a8a013b29e81dd3e36c4991cf21777d2ef38d426a178b654b849e4712930354d1dd12c0b3ca78d49c346bd09a7659528ae399eaf3537e0de931019d1647b0f12ed2c6307fc8390852c48cb1cd1e5efef4c40534b41448bca1ae5bf4cde71ce6803cfc02605548d6656410e5a182e1af9b955c35018fb4fbc115d7e5fa19620a21eb4d596e043b3ba7ac346b1acdd211c0c059b86d6ef80ef11559c0d1b3dd983af460dc9a3214ed45d2084551fd0dcd2c4efcc3912c0c6b3cb3658cbc1fce893a3e5625a8925c4658ffe46570e9618a95efea9fd47b76462415c04c1c3ebea66d163a1b89c508b02bee2aff6945c17cf7a9b6f3ceeb0ac277754fffe7c3b73994e19cb537168486fe3e5adfe3b2d3c212a70a4783da36c23c15068765d9e6846302be811e2bb8fb11600e45c54dd5a14e8e42b9a220a1b0d386cdc7a0b60d3ca1deef8eb32012f00bbf09bdff825606b1da6e995f43fb9cfa439b9a86f29c9be8fd50c6692f899082418d4e952bb4cd717a5c2bd9051e48674cb04c6814497468a9cfe568d3430c6781cda719d720da97d5c5211b48288bee2ff63caf7465eaf16780eb42ad96d70d5f5ee568352bab429baa2f7c6e89d6d9dec2ea726edd0952e7adab1b09d39b9f1e213e79a46cb6974523af05a116fb413d98acb1b3bdd583011ca6944e61718962ea982d7de624ab114eae4e3b13584f38f3a4636ee13de1bf898751837bb2a6e958b0eb4383369e99bf1c15c5371dfd90ca549f4fdd6cdae19d53099fb9b11cf532e0f62d2a6a1641319250695712dd124d9ca9618c672fbff0a60168d0bac4d915a9343dea37b632c90ecfc60ed55af7fa9be33f3c17ab562410e9deab7aea4fda0674080f3177155584f4af7842f9b98e4f7c815a2c8b75017109f08525f71221d1b03a79f37a96547483cc2f1c8b999cb5f4053c708181c194a3fd5c009495c3b16c5c65cfbcf8be71ec55b18a0df2833ee28d40f01b9ca4ca06fbf6fb95f68ea17b22b09891af7fb09ffc4bf0d4e5d8e817e5ee8666d8ed0207b2dfd83e3dce647c3a8447a07ddef6137e8c4a58f5505b02a7146bad60f9ae35e4727935271527d88c4a69acaf1fa9d6d96328c7072993e6d51fe052a0d2b91c31228f26f8c4926fdfd5814d5e2571b7a88f30bc5291b2a5443f4acdd325b8e8fdaebae0bc10eaae791606e6762e691f7c89c5ead19077e163dbf251b4f97894c842a97cc11168dfa6826cde37e89978763a841817c97a89d104fba6613f6057fa94928c58fc0ad60292c425061ccbfaed88e92ff7db1588612918c3a0fe6e3f672331f6506128b358c5225e8c97c34c3457bc4bc68500e0f56b367802ab40b5daa5e4674eef0a689df0c609ff6da39b4c53e9e54a628c046c338016ea22c38b62b3d953ee3138afd1c2b0220024512d1e45fc4c634580dc0bb960ce3c6fcea1c9a39ca97a1280402902f9d231c46036a79c4e60dde8385b0e75151f75d13132e38e975b9cd86367e30021d2910ba589198128e59018f88b024c19c010ca660dd3280d54358c718c05217d60d0358ad1069a1645f40f809e8940ba86599e2ef3ca8d4ef7507dcff8a9e1acd5827cafa1c1a826973a91dde5d8ca69be2e6724d55b0880e869d80374d601f98c0d745b1e10931d527d1cc6424f0cf74c5891f010c7e62fc38461b2cd372efb790f51007b0fd8021b52b41f1c023579af7b651eb67c899ad6f183840dc8216df717d896982102aeda7be0baed70d848324ce63bd92abca2ef024b67951df39e117026d4a8a9e887131b02e2e83ee0a64ef14f288bb063e3efde72c49f2ad6ae3d28c1d4c0649eca88ee686ce56380c24b809690a573f8b0882396677653081bf2214e2771d5b31ca10f09869d84e36ee7b519859cdf4adb5f860292c78dce3e45da269b4209480b1e945569978b566ca861b7d3fb9b574a1562cd00669ef1467076e3f8bc344da1407ccdd570d8d8fe5c9e00d4c582e1b50485df4b08b165025b7b54e3db41f7d3d62b3e248f2820117db23bf97a6d45ea2fd9bf736f9dbfc28a0c1c25c5db3dd9cbb9df965d75ee912d03468b049ae9cd8f5dcd3d422a36792ccd3099285312b5fcadd3a246a69d91232ac6a12572bbe7fcdc465bbcc5d3545436ea9e8b8002b7aad3316d5871d2f291ec80be0a67e5e4a681443714a3e14cd5076a59018468e48072a6c84165614919ab651addedc4b946035004b24871fc0b62b0d930d02b789856f42325d5855681c2efd568ed1cb21fe02f55f4379f78e49e02656a43d0ec9aed01486af0b460b7b02b805f77c4980fa58d27185507627c771a687ba137d18a4617bc8fdeb5ed501a3662baa64203dcd785e68a4894686f34ec754cbc869024a96734af951ba0715db1281a93872ad39e2393b08dd96fcc1408d07c9880c11a6c6dca5514fa585efa84c13a8e04e272c9c5932cbaea0018304e8d5e15dbb136bb85df35a41110186f303d78cc780a48499f981ce5c5aa13fbcb0c381c3a6d86953af47c555aefbef33bf85016cc9b09f07976f2ae4200472ac360d4acb7c565cfa91d180be99358b86ca51035573de782b9e810a84ac541d475705a0d68ec677d14c8e2120392069195971460f4ed1fd438cdc74d8a02499b3b035c59818062e85d690315bc0d9c304f48a8ffa2871952f628ecde5d1222be8c05fa9ac735a62d6319c6b716927864343c42d1fdce1b687ff1bd08f5f5f4edf150c05fe82953f8491607dae024aa8af6b1567d95eee63168b6b1e0e89f7427195788dfd90c8ea2d29aa31a249b7ef461da7290b657e73b33e416edb17b2fe7bddff9e13272140a1f7ca5510e224c3f94547567ec66f41ebe0df198ad23a2decaa7d1ae52923d05504d05cd985a7abab18fe8d75db8fdf64a55c9a68f367af7844e121f33c08c97807cae070723bcab10ce3539971dcb62201c0af114d6fe22e722640227b393b88cd469a51d9daa3f1b63b465e4dda1d1cf81a4327b97a9c3a114a18897a4afb466fe3f7680445f4cea7eb465845cc0c848c1f3d1b690b4cfdd42031585c5e976b2fba7b93d63eb34369c44b764131efa3412628d25601f052c3e5f084cd287fe6a52d0d16186a9b81f58b92cc02b88d0d73372897e15894781e36a9320ae27651adcd7d6beec5cc257f5109be5fba8dec9bcdae340802d45c01cf2f0c6d3098cd03848b270b826d0583bcf7730e7c622eba1a663f9f783c053d7f5f49a51b5e3ea185f2cac929f0f1d499011180520fe6982f96ddd443a0b4d5fc3d118eb36217866955b3e42a625349167e8db8b20a84615f27fc1d008030ce9eda68375810c4db3dcd0c1add10e48d1971841bf2414d2071fa743b31940cc34caedc32be528e533f6eaf151454812f5a398312d08f425209000fc23117a6717409d93461c6f69f9d90cc2ad43ad6beece31ca6236f2608e0db45ec388c19b343689bccc8fd32a6ebdfc9fa9c83e0bf6117178fe3351442865d4fe92594c3c1ebb60bf490c3508608a551bda22cac694c245e77d2ea1d8da8595f3d8884883dab45fdc0a50bf0893605310bf4872610dcd88d21e1f1717b3dc7005da1e939182e50fdfc874f21df0f5cc184c02496ecca431481010c164aeaac62b652eaf3c02a28ee640e3acdeaa16b6c6ee6c65595ea15a5aa3f02b1adb4478060684c365ddd861533d0d527bb3144365890dc3695235236049dd47d43a394b9a762bb2af0a19c249f50a75a42e551601573f0b96eb3f131c472f3024e2c4c917426af892c08882c82550022e73a0dd0b256c8af8401ea6f129b0086f8c38a1191817c8980e7ff314a4dc3775b2da7f168a18484d9d6708d5314b7431733f989085183a7e2b8c9d778b8c2eed8143295161b182258f976277476abac09c35770983683fa576267277a7dcc1990bdb86055e3b26ded5ab95b50c5f582e9f32d803d781f2079af5ff9be5adc6fbb6717c55562ea8e6e9cdb6b10f30f51e320afbd3bb3ae2e8988af3cfc2ba10a989817320e8dd0158e5898ac782f3f9640fdbf6e0454fa4efaa1d884650068bb01c002f943112301a575a1a91088e897989a069ae7a3066401cec0e89d835b40bff34931dd9aa5dc73dff33ed0d46e90e2923586a23844302a3dea333911854535cbb8fc8794be1d6838d171ef24fde35ca2baa1e710c476faa9e425033b3b357da12c7d451388ee46fcdb80c4414f26c24b70ff77f1f052aa6868bf97b503e5c364db2881dca2292caea2bc1e638de6f890b4926187dce4ce293f67087dd8232d1b8d522375146e3f5c25e4a8315ecdcc04d8fbd952fc5740aa1249033e89b7bc5dc15318993dee5a32e42a6532c1c6feeaaa642fb36e1d139aadc8073f5ac7ff2da11fe166dec95e2c5751def14dd1641464736d52c828fd137abbeeea155e43f534ffbea46bbf211564c8d70a5a87b4972040683e838efe101959dda41519253e1326f743e03afd56181e2198573025717685a290403ae800060d30b7b4e97021d6e7b5f66e77b7b4facd27be27dfb094f6aaa28074a7acac22d9aa5ef5651c818d797a41eaf47e545432011ae42131ec7b308a520d46f0622c53386abd2c515176729a61b722f7e6657de0798b00cf28d27fc2ac0583a0747cdb1e4efb2ee341aba3cc3a6e0e71870c9e1ca7535251cb99015df6871059f684435041a47045cfe8f6b699989d734e71175695c3a4048543174483e16a83b41b434c4e0262bd0579eba24a6fbeea3d0ab490b797b7c6e4e545379ebaf4ee621b578cad064b590aabb79ce22d2b68e8c2f75feef32a773fc5a220fe66478d3aa5deeb59716281de5390a39e7dea169bc91f296e934bc2624e1bc3bacf4bddadfb11544f41dc5eed26b61d7e5ff2d1714fc4af81c1a7b20065cfd81926ef1479719711669ad92d0f810c07dcd1c6709708a659d915965cf6c91c43d9a0618c9d63c05fd172ca8afb53eddf14d754d5c3e186e8c8e58a72d49d9a5aa4566435848261f4f2acef5ced9fa185668250fd31321cbdad7d45081f7ada37d6f1a2d2e9a8150afba07c5ba569819ec1e4419359eb9db10737ed6bdacf1e6618c4bee8e107a2ca0aa7d990942d2d207177112c4597616648c4f1291b6b5709d65bbc0bd922f4f0162fadc1f8ddf830214c255d6849a00f00dbb9ca3f82759dc77efae4e90dd040d75ab095a8eda050a07c98c0f3775428d686c83047578b2cbf94e4534f946e629eb87c5f749e41767409a5bd99d4e6eacd68d020c7a980b97bab13535fa8d2416fe6879a445f0baaa10ae95990e816509fd4fbe22c988af92ea5e2637cd19b7a19314e0a31e41307c4d028b33a27d1abd6442539e6843f6bc88ee5fb50fe3333d5066fa08068817093c7229f4dd12326234f92dcb6bc17eef79da276ceaa6d72ed1acac3dcb5f45faf6e2c713e893dd1ef87537bc19945bc22ca8f5525295e5e3fd04463fe0bd4cf13bc12cb7839a26b74c07d814c14bbc84eab315c09651a9607379a732818034c80ceffb3fd8e2e8be4eb3e6a3136aa0b1a889865faf2ed089c6c4f49ea302f4cc7f96b4fbfbde3dbc2963eb48eb1790670555f404fc9c290ae7aebc0fa01214754ac1db8e7caca7e6e510e8ce73a03beb95e689a548f12dff351238610eafccf355c091b07c929d082b5fb57ff49c2be674c34d2fd9d72ab0caf0c0055a023e6613082056e84c0dcab0dfdfa25719b499e15e4ebf747938c286aee8c5d4ffbbbfc0ab1c7b5541075545a368f289197481f086b00b40bcb20c2b2e398b14157c9b65652c31c3f85af9baba4f6b54410615c5c95142318a8736e01342c095e2be0b997fa2ca674842ccc013371d45403b09657ed14bc45e17e74cf25aa16a66b838564798391efc42cf29c1b72ea88d2b3b4d5c280a30ba8250e86de255b7b29c8996ab67c56e9c0066de216a5e086206533b3df17ef16ee0432d0fbabd48c5609a6b761b18a27ae4ec061367a370ceae5dff11b159a6cffe83efae41f1b0e4a8b3226a69d35b208866ec564f0105d9186743278c74178424e57e435cbc0931fddf70f00d47ec67c9150cb3046ee2fb15cba64d575d09fe71551f9a540f13c3cd0ca5fa8978faf650ba5e7ad2ea23320c6739da8687a6919a7331732e199e8bae0c932a4dc6b9d0036620c0e83fcd9c373c209f7e9ab3fb65f5cb66a0aba028100fe28f70a3300eacc7de46821ecc03da9b5889b179e5a01f885887bb4cce1d2bffd125fc70f0de79b2a3e9431f693b4977d394be415536c4eec417804f3ea40245e7d4d1ead55309c7803dc1820680f4e1b0e44736caa2d08b5f240ab84be2ded11f6aef8a53c9ed5992513b851e3ea2817043ac02a2aabb62a40541e126e1b2558151189c63f46ff9e735766c89442299daefebbc0c4f388f24550498a370ad14ed2ebe9d5af5594c6563ad40dcd5c92a5f806da52265d59a2279dc7b43393e756c0d472c108f9cf775edfce70dcec2b9a39bf98e69e4b066cd54e0edc35fc60c2703093b271e894b2882281faeae34112a3040ab5dc5c815cd17f4eb3de17f57f1c04b3e980f9482408dd5c6478685c8fac22514dac70ce58afc3bd27d7f18882eeed6f15c1c7b8519630468bc35f8ac3ecbff587db5048e42717bea2124340d4043845b5d85c03c2241117ded9a54cea2415a9f3a04330a8f3b61d1bdfa6c70c04a533ce4bf444914ce8618cfbe13fe05ec9ed13de4725b2892a9b672a1dc19d5d48fb9c1402675b1fd740b25e2dc19f147e1b93291253d6e36d9dd63018eaf62df462cc168ab2142ae1db8155e8761a1b6fa827b854e40af44efd52342047d74cdb48a3d1f4b52b983107806ae25f533282f4ea83cc22d0c34cb9575fa97ca73e29e758779c195ab3458ced87829e8bd1cb0ab1254900988fe6fe1c21dc03d393f3ff615a2baa0a53e83b15d8f54f97a10ba9589366c53bcad4a0152d62bf3895c0a42b022a01c71cbe83c6436c086c1a0a080605f5d87c71b40c4c817e064d96dc7339ee302d7e50640a9129806b6037657523c18351cb040d1267644feab24b8aa4e9c91b0057ea248103aebfb6f195d928f963eaaae2587362b6905c00b95d7b398e7f564c46651c023feaa6d7bffa9ad29c260cc2ae3ba97162ea5ffcee3c92ba3dedc087309a98f4964591ecc4c9b00e709b165f50f887846dddcb9d77dbacd610f11f40b800df282d746b46f48f2f61fba194cc4226c8166e0ae23d391b942038ad420a808b8d83a83544af89907cf381c6853b7e569832dfd048b6f2799c5a927a548a297afb363131daa53e9c7340ef43951f9fe9cacc1e4c2d56a8538bb81bbb3ccb383a3b9a1a787d9d8ace31af5e26e70783453546ead4be58bde577e472ee5f342076487a1f924df20f76dc3baa13b8fdfcf3187dc76841d2f9e88e3525503de569ebaf4dba27c060026aa4c2d85fe90d01d4679c07a02e10e045a4fdf883c592ae094f08bb8e95f26f7052be60a3fe15b5a492f03feebeff3edfcbc676288bc17cc049aec25611d9925b92a479f54c21dcb96a728ee436c6f052e2022fa78f4deb310a340986e90be3d1f0a6400ab14bdc131be914e2f90dbbb5408b2ec28eee610dcaac02255bb4f55c5df372e109d8e1720322593c45998b2166a76624706b3e8febca634d50f041c99d2234deb8be3a175169c732c6c063e99a0cf420e11a7df152e7d8fa31b3eda9d484b9a83184efba7553e092475afd771905ddafce6f43d2c21636358018c437d2d6106b646f7603a8477c1f44c77d1121637d41b5ffff13c4951e84d1d37a22500218986a17bf2cb5792871d42fe25af593063546e3546ac573de0ba1b7932eb14a521bbc81cc4e50ebd3269aaaa8d037659862d08c6523d8c208a153de1c44d30481b0505694c8e793e37101c9dc19f54cc4f5f4e9891cb113ac3045b99b5231b28a973729d2e80357467991b02622989ed63f3eeae89b2fa6d7a5eb47e679a7198cc8a28d5f4e921bc6b95e3ee58e1648201812c50a0802558f183ae7729cbdd4a0d5d60018786f3b935ac1a647213a3704345a539cc1487a7a6f4a3bea06531e171d7285c1c8003b3b68f26722e686e7e42df2668367b7500a705027c07e36b6d599e4a5b0b4f3dd54587cd40541031d25dc098b362cddbc8f9916e69646af2b22c2286eaa09fcdac4a6879b76f30be8e43e34ed444ae3664e606d7179acdb23f12d8fd20d77acb623f3f046126358b2bbf051119693b4a95e21dc8cb4d9fcc31368c519088f0a1e77ae89418ccf9f848f01dc6dd4285e0fb1050fa607da20802294cb54dfbcc70f2b5e448315591bb2fee855d5269195e941870765a106817ff325edfb3f483ced20bfec8926427d56805d7c93c5dc212de9c6b75304519520610c9b0ecc8a3c7ba7dbd003f6933626c3b9a2408da7b5c608c645dee3575043529d33d0fbba04eb7b41aef96e0da0b84d4cf6a18c3574581b46e4141aa462599d8c3c08ba8cfd38061ab68d57c84669e5c2923f08874e94c49a468c0170606695ccfcf47b27aebf1131d2eaa60685478e1a9a65957685bfb10f271569f3fa7a3cd584a7a1892ad6705a786f59dcf3a2f755c0a0986b2f29da81413677b51c5b68e127b5f86f51bafe4570890301e994c4cfe197ec5988d21208a75658c5f4c881b0a326310deaadd2efeb4acf3a64266903c054e2eb49dfe81fd9fcc95a6aa6ede5e4bf79a35c7220c78bc50158b96251ff46439315a280df215b5562d8c3c625726e6b507cfd26cf7b4180824758516e7f7ba3ebebf41aeaf0fa78304ab9831efef809f284ca2b2f4ce62e9125332198cb834b21e7f554608f530f3b539f555b37523a9fa7e3fd58f9577c0da3b847864f906d4d7affd3eb09d36482093bb78692d107a34ab364a372815532017208e549dcf82bdca812e405dc817c3e65558131c6f5b2ac68a6923c57be2ceb1877c270b0ed3a93bfec1c2afc569adb86034d9d2d98e364442640dfacd03e8cb0afd310af177d77614db45ed073658ea3a3ba19de4bbb4009baa8f61df86fd8d38e8b1b8fabfdc80d2a1a08d9cdef185ca35b6f5375fd07593357621b54010d0d0e54c0465b3e5018bd133172d9ca97e09cf3b3c2f42f9b494a4fdef461fbfe653068aa44d312b1ea0f26998e1e29d4e4ff1b1e30a814f0a2a15fd3e377c10f317bbc316cdcd41c028053a08d9f786a8a77315637ab0cbf54aac9241e488b7fa2951505258426860e64259401082636db4b6cda76bc23fb281a45b56d21b6a817626b0e6689ae1e9280752403ef9375dae2e39d04189ca24b78e2fca09caa474123ddc334ce045fbee6b2b05e19af7d25f70676fb22fce14e9fe754790ed1483c4e6a3240826ba23e206d32206340600946aef7c1071109ccabfa549b7431721db42f7e4532acc22dbc230d9c1b26240c7f6da57354141628edb1089a339b287954cd1f280caf0c5aacfb57cfd667ae6110cb8a623e07781f32cbb26c6b4007444830621ebbec4a950a2f2fae1ea418250c68614ec56526979a81bc80189e615d0aacaca2cb9fd5d74439b4a0210ba05cbc8726568b31d2eac008ece7634cbea298c69f5d6f042257b6ec6b8d018eed9876cf22e923fda3eccc313a7bfda08c82a06261377667dc2452914a04b37246a3cf1405a20c936109597886d6b03a7ccf723580a06217dc8093cb194e5e2ad5cf3e97f964021ae3c84fd1b7e911b224b04cdf4c0dfd2e41bc403f37949ff9757732e016ce7bb58ecc1ac992fa24606b4c5e10b475f495aeaceb8f7fcb7ccd01b2095df7b31e4690a3955a5a116e634b407dff34228732b070af1eb3acc53de94300031af1bbecfdaa84348d3402465bc6e7fe5ea3753cb8b23efd30fb849a9b0309fe1800816210a0bbb9c161da0d04dd6300e2e9a4080ba3700d84b4d0964aa1627addc007ade4b1f826fd1dc2c0528da0be062a26f3cb0e04fac27b2051d712dbcf22ebf0bf78006398d7cde5e3973533e6fa5c43d20b69f6f0d42b268c703ae535e407d71967eb6e929e7be04e72d831fcd436a2ce97ddb9299b9ca9975faa96747f8a772aa0973625d68fc91ed68ca165c4895bdd0f00afd118d9632dc57fb3550006444c20f86ea2135c45c92fd0b52c7c3311bf4b11f2eb6beee378919ada384eeff0dfed63b966b091735643244f45488074b2a9eed8be7d0f6658c8d158f2ee010da8b9f97dd6fd69dc2e82838df10ee2d72f449bf5d58f2f6c670444ab4fc08207f6338bc6fe23a30fea1c4871209161206473b008b84c256df44d6baea0823eb5b313ca80d279dbab5d91b652a0b2abe56019aa2cbc8f836b0f2d73baacd6d37eb2074ae9f1fe33a6bae7cd5ef0e4aad58f8670dba3a621b4b913376b7ac68f7e8b430e7149002d29ef521002bd6dc193cd00ecde3125d4b2365c763067b7c4c4dad30050ababcb7f3668fd2d2968fc069aa0071d29a888ab92ab2f1269526f60c1d7daca4ed2b705383022505220d65bd570b156eec26a1380f5b84c1e7e168864438229f0ab3ad5da0ecfffe72e274b6c4937417dbdd7820558404cea8de4ea6f1ba08867584d0c924a9722c73829eb406328858e56ad7d3ca2488f8452df88d7b80aea22a52f6f9e607ca9ac500125aa3acbe0487c6ff988a58943272ee31026b9bec8307a986f176139eadb8e449d1c0ee231d4ec9d239ff5ed192fabc4e36095a6f5b4267aee36ce98f8e02ac4ffe963b93241d8c3d52f00715809c4421a992ca2076e87462b5a2bd03f3062c2ad3674f79555aeb16633e6954d647e2db5668835125702b4a0ec7987c8541a512ded1e13566bbe1b29e4a01cbe6b83bd68572588ba22a8cf5a656a1679168ec01d694b6db18014d292a95806020234137f4e00f4ca3b06a7f75fd905dae5b9be25279f0a89c32a3c5c4a2e5b9199174692eefc10ab5231041363c17f83aa9aae8fcef7a87673025722294ed4310e72bab51fb7f8547597c9eb65ab9d68bdfff4b8899f226efb753b80c262715c18ad34b1a5d6a77aaec1ab9c523d15b96659f4ef108ad860435d80ec11c57381d8178f3b8443d9b55c1b10af7dba12be9eb21f32e54a60a2e81d0970c3e27bd23d4489872141da7cd068a80a5061272a58f94e066ae0b5895e9a1d7cda616025ce00e1f89b6a19451b6750332af182a7d04128dba1189aa7e95f338ac94d0802a201abd17b7412d6fb1aaa8d21459f53da8d41be488c764f39a1395ae03580c0ef03a54bd276fcf0fcb8cce9d2f99bbee1b46de60e04957252fdff54e1dcf71bb7052d797b7dce4eb75aa0c0fd067019a06308222333bdbb88d547339b7922636ea236e6d5a375415742c33a3ab58400d06c15d3fedc75ef7946672b0b8288c4fcca8edc00ee4bde260fba186bf1d34efb6bb1eccf17c80664f3cf38f4bde0e1cb9300583cc1aa9880c79fae2ea5ebbb6f73cba464c9b62acf385e1da80f8b49eef19c6a7b4807533a94a47c6fbd2924dd6ebd1a7736a98b8cbd209a662e0124da9c07777e0379ef8421cf10aa70ed9ad54fcf8f8f6f202453ca53fc30429089372fe56560a502d85f8b762550027c2512e8b024e35f682ae62db5ca47c9fb38653369bd9adb756667273cb63183c1681e5ef5d8ad88d0091d2e6bcf2a2ef5c6a2b00d623970e769bdf147d7fb3b4db51271df1baf2bbfb093b10d878b139deca873aba98fe19c88499b140ddb9d8e70d49c41b1f198a1f5f772930a32e7dc93376b1c2b4891e02faa0cda10aa561dfcf56fecc06ba2ae5085b7588e3945179707c66e9082605024e68bf9fef1c0431b18be6b65a53a636464f62318ee1fce256b545e374c4bc71ddb1d07066ffd3f501b934ea07686f1dd707d24d0d71f07363ec8bcde2e5214d8b3c2a7cbb2f14dfc98d82f7df30baf8e935ab7f1adcafa25aaf726923ba2ab78262b3dd0d34adf7844975e3d89f3f634e0c66497adb27906dafbec61371ba0211cc184655083c10b3e2722b2e2b268d30f1165fc7a31fd9f5de6feed7c06e7bea0703f95a903a2dea63daab366e6c70d649f14f36755022f033af95c70c01d947cd305147d0785cc8552a17d35a750cf872f5be86a5554af0390f50f31e99eac3bfa8d2abd7ab94556d221ccd2ec95d568d6fd20197a309bb32123eaed30910a56eedd5b83034ddbef2b02cec1bcb8a8e914c22012e3626eca5b472822e5949cd16791220b07897a48a7997b07dee474938011fe2c4575a8c5c6dc6634eaa9333a381d24c1ed34f688913380e7a6efdfcb226caa2664ba3c90f20cffcb2943d5a2bf40d42a49151eac1747b8d08274a58f93ef4d1097abce380d1072e455b31e96c827664d62221e3f6f5d825c83c9dcf491e60b1d78c519770bc7a43b20ce74baacb9ef70b576878b8bfe4407e075f1a041a03cc82fa114fd11b56873776c3d685bc961e9ed03ba4d4399696ad9251f95815162f42bb50f9c31017094d38c520cd78ebc10c051935380f7217e43508f968c5e0faae871ff75439b385455de3e6ce212d89964c77797895570ca790941f8d22041ba6d54894140737f2c2e3296cdb14815232840233e509cce401fca0ff78440da93dcd9374284430a504c65cd7ed8e64827c2661820c9103f0ab021f67e1bcd305401f62d0fd55d44c4886365f86a0e5fad49794ec4e9a08d8b61c12787cd2de3ddab6b8483b0cc537eb1ae05d5b7e044764053d6505d5e6eee82446fd3c161e1f15772ffceba092e241a0f7a93cfd0412a91751422b08f2ea198cc645146884ba2804d3e5941aabc82ba9b879831178c8640913491d2c0251ddd5a3fed3daffa6778328a98cee0d55133cf9cca66f2a53638f23da16f7c8f330cd499b2821bc377f20ff73c45693f364b0e215ba46d8d85280acb767db73b12a793449bf38be994003428a7286d9b91e40b84c9fe83274c66413e2c8ed3cb2fe826fc8731c68ada09c217fd61a49b962d54292c246fc11ebe7c821e46c764ffa9b53bff79e7ad1b3d20e3bf1d447e5b7024985ab7557771b47c8e518512fe86a28e671b8bb7d2312d54adf0c8213a6d2f6d3e1ca6099a5100bd610c2ce93f5bcf4884e3216026a428f8787acfedfb0c9f4f401acda72df8ccf64d088bb4df4413dd365619a107fed82df0b4ab7efb502ed5a3296452bfb9f2f6fb153766ed8cf42b15e741925c01441721b6a3e9d875738f58bb68013b47a7bb614c80860311fed3e58efd02a0362ab0e938676db6aad819f78338d2130f8d7012e8b5c5d9a53e843c7179c20d7b796a02aee8c448c93832583c55318b00487e7e2dd52c108eb5ca88722450b4360ba58de5bc369c11833aa22ecac51c3b21ec942387ea008ec02eed9b2c945b078262bb741b43471e8e6578b0b81a87a20ca1c9a520ecbbf9e77a9adf5bde8a123910fd80608890c301b7d4aa9e5b0a6120437e3e9e3024ba6a92bfb67451f6969578e639b8df8239a533af34e4cf5f7963412f8651507c231f46ec15a619aec92bd7063892ad9f2f902d34f0e93f8af976660d65ee0f5eb40ce94804bc7cb23b061e6df10a6e872034e33e3db4c4f5c60948aa2f248d388df7096ee98b82f2b12d8e2be1d7ecbe8e8ee5b8c899b29df04dcdc6042241388bd75427cba62de0e45808f58ca858a50d8fb623c2e4d53d93e8b932e2acb2d96ba10a632c5e85387d4d6b3f3ce16bc69a84e5fb11e26bc27581d379c534f9f260118ef9c41b73372ffb342cfadc6e65ea6041249a8835fe086b6cf0b0626ad710f437477f1a98623e81c1b6d54dfe3d78a3f954f1e350b38037b65c31ea13491666765b9748c0d7c402eca5ab4bf807af0f21533f5b8ffbfb3cebc4283f7ff63e943b91238f5d104e68af485ac2b237cd20fd092660f4912f795588fa561f7fa12936aaea07c810615088259321f542dc3e2846e211eafd7e141950703868689165323fe512de69ffcbd56804836b7cd706a0d6930e4d2b046c430a934618ec8b83b387363e241102b6c2cdb42707ed6a9a05d1d2ea544b540d89981774fd38591945c28b5afbe896d0e027d307bf6c67c5a97a260b7550a7b431a04e43c12f056df9d37b655b52352c93d0f88b6950936e9d89dbcca6a6628599942e3cdbdd2e31634e42772b9904b9c3c1902133f63556ca40869e07ea6cc34d5aa0c70973266190efbb702861660242523599aaa819b50aa820af018557f62092ff08b2e41244df95694fcefa67a8e4272c52a8936f067523ae14d72b88ba7710980a1f819f9a90b3426663f10d830eb6b5ccc60537d6d47350cfb6a3f5e1d20a843645fabbb033b39117e591f0cb5013f7092ac3336bd78fd3d72f72476811a4374834451561d62132b04e9137ee33222bbba93b238f399c4f064101cecc20ba21da38f5d8e4302d16421d2e574019ab61f4a22cad43c44d9e977d39f0f1c6af59aeb0e98d10962bc10c0d6d8caaf2745a43e7b4e41d938cbfba3e94f4e444eadb0758ae6acbc3f73148f8c9f37b44c42dd089368b326e5d375872e2e75291c1271d2cda4231e62220feb1187cd2a05154f027ce082bb19a734f22d161ec6b6f34be8deb83cbac3b41f4c8b6f5cee37c98b22503cf2f1908cc9b9f3565a9742fc32ac98e44d3087f6c7f729dbf19c9f96aa116111df2836b7663211743487d270129e17f4723ea2ba3972e006ec5b5010299855433fd8a8990cf9ef01ae8b3991ae32b357471ebf6b6bc142e548222bbaceb532a9116018467fda32e4c04f7fe75f536ccd634d8bd0250687da97eca9ebc8d44359dcb299e367d5901cbe25e9d3ef81b7a1c9c130feb324e34ed9c5ca328e3458be6aa6443c70accbbc85b7ad19356e71269df1ec94ea8fb0b401271feb29f217c7c98f63a012819427046b0fbd3255a30843e8cc9f3eddd9da5e9966b6c4c594070e49c2e9ba685abab044c61866e1513b42b677812964433631556e3a63e00cf037104009e6e68219ff10abe0678f6a65134be557a605b381be83d4367d280e00b579a2a0982286bb2e2cd32950d2376ee90e2fb793cb1f2cc541b2f8ba2f4eb3b225eefe27f4f378e76688132248fca6db21f50a4f3c6b22d43886e090828f77be192ed7e77ba2871b284d3e843fc9761ea5347fd79805362ddd592d186a4bf84d27dd0732789f421cc9e7da8bf3ec6a61b1c27d0404e4d205e241b177b85349f7e7e70d55c05e621b92daf98aa6b11dde1139c3dc01636266a5d317e1c07ede9216be2401d53d6ed70e015ede263187c6975c7f32e96615370ab382b64114993078bf5163a45bca6a0edc095278346ddc067255751ec2435b052ed190d01912698bae45721098a72d64db830b4567eef158bedb4aaddcf9b411628daa40166f033bf600628d9926e8b7b59c1c63d27ec2b99c11b7d097ba7c6a2cba050ab403e987b474105f5ffb7ca734bc90e2fb871b0fc73f60a722cd9a05c162922281375146c4ed864ae8b3ff9a896892c3cbcd06f99919e9440691be191df467d3ae89c7f686537961ba101a6cb5017e0bb1e8e3d36c089bfae85f85f26cceb7ad01bd8f5e48c5d6f0b6e3abc5eb3fd2fcffb9d6504f62f97ce326b93ec51a5b0d1014c11eb0980cf965d0431d6f70cd8e669d39d885b56ea31f223a95ce721d2b7e6d089f457b31142bf811c99bb7b3b7d3585a12ceda1f62ff19fe6894d26d4044cee443217fea3923d1951e330101eef901fd346d0f94363630b86d57821a243abe293b8954821361bf805c1be4138fbfe295d4712c11777386c3a2d47450c4419c88dd34a74990cbc6590d24763d4ada8bfe25c44856ccad9e96d7680bea043151d935b1c2b2e30579d69c6026e43cc067aaf6aea5d72008650cccf68b101a0ab12301c50b2d9df7d9b6cfb4d521a3295eccf1794e8bd7dce5c269d457976fa87c02ae6a9c3eecc851c88ab4bc75978937683e9a1735917e0b8c5b6ae1e463f94ec3266350b2b57c9b228aa2206f58b12f11371d11e067561695776ea951b54b467e3bb55e12b72c092abc36467197ee0b640d4ebbc873bb2c7004820935914176913b82ac0a18d892a0105dfe0196de2749b52f63e7643b1d38af662b49979b9bbb9f33d6874d987bf083bc3e8740b974334e70502b4c88350074f6dc6a883a6d7e8638b2582636beae4adf7f2b601fde96aa02ddc875807406456ec33874ad3b2a5d66250d05bcfb172ffbc015f49c2973035794fb5679c6ca8ca86b7344e2e1065085a9ab18e00ff26830998d4f84bb447c0c63581cdd838af510a7b90a0522af6231469f670295d5f3b80f03cae2d5db9b8e65154e4910584ca0e6fea84f5b945acaaae242183d2d9d794690333828c30bb056ded4a5afe43192174158dba27df9aaca985878285579220d4a6ed25d1094d81d45a66d0128b3d31749391f55d923640ad893fe99d67708b94f2e8c46fbab3d54d0a109d25017e961d73e078ee61213e3d291dec5ca8b3bf0e8bc2bda0ae9f69fe2f9e1128856a7f60b89e321b1a5efb324d524880cf68c8b1f77989f7a5e747f7a67542cd67a2d6460bcb2641148a2b07265684046632829d7ce05a750d1802f6929b6b1c94f703ae48e0c53a81a1644c6f5eaa9629c10af02d19db01ae1199047133012ebf03cc6a02caab89585f40902a5207bb9a143c715b05450c86029288cf7a9644eb1a04a66f7d169cc0a8188849c07bb10fcc71187f8f2427d8fa9e9c2e0da8bd437f80e68755db626b25a0a3ea214a1a812feb6378157b43365bc01e3023908ff62e217b4b299394324c055f059a05318fc90f7aad4e5752ce0b6c772169eb85a42d10873641602fcb2abd6c4c7eba6d82e0d855ddd72688cbae6e36dd517a361575d80471d1151b9d304a2f9b2038d6f4a244890265dbd226084d8ee2a83bafbc0c8ce2f052a912b266fe4cc43eab8d8499ed250db22b52798e68db56d2dcaa1a902ad315af44fa12905de5b154926077c9ab21db89114122b3abf087223b7f69665777e72fd12cebb6f297481e8dceae4e19980cccae4612521be4a136f27f4f777e1a2776e5c5b0f3d3ecec2afcfc3461b8ec4a8473e36557e0e7bfa163579e0972b8252b59c20a75ab902934ba9d5f2457b8fb24dd56c893c4b3493f3bf72021c933d24f9025f13869e6acaf957f65e72cda9209ed1c23d176cea4d7cef943d8cee7e923cf994db2e55fa1ad3861326493786de715243bff89a4add9ce7f82e513cfceb19d4f3f3bbf77bfdaf2fc5c485b8e12a81beba80dccc502704b06e631d94612f95b9ee57b58339f32b09d1fe370ce59f8f3e31a8fc98f496ff4bcd2cbb25e5c25189e9d25204b5bb2cf507409c9a0945e3b0bc96cfb2c11d9b924db799fa5d9ce25daceef559b6719c8ae3c1878663b9b609f5968671ececa1ff5986c005900b2a000cdfb8fccdfe71288f93140f45e09e44d2045a0ab88a4ad4f8511cd694bdb1504fce950eb9eae8b74d65afb23d8b4d01536268403c50ae1dc2c68edf5ea9560db6f6443ca7f2086610ea04a0aad417b9fdffffbfa34057cf1bf3fd955f8dfab3c154fc09f227a91bce4175af3fb14925e7be369d032be1202afe4747e27d4cbc8630fd1d3edc3ba5aa30d81d7d712bd47e2bc50d31295f95f5f6b547adf88c479e16b79ffaa6989de71f6c24f34f2bf1863f0ba7f6158ad5f9c4d1f4a34f20a789fbff7c8fc39fc921238e1a7b78400cedf5b20d3af6671a4658f5cd2fd89264aa9a63793e37bb97cd5d81937ef67f2035342cffbf28bf93df2f3f2e75c9e3ce65e8cb1c99edece5b534a7510b73aa59452bfa15e3c638816ed1943f4b7670cd1de9e3144e71943349e3144df3d6388f67dc38c21da6e00c0a0ebcf18a2ebae1fa54e3ddfdb81ece25b2fb571b1c954325dfddd7b6fa6949ef4efbd97d2ef746fadb5decfabbdd52fad18e31b28a5743c80689f40b6972c2e0025b0836e1b449fab7bd88578425c8827c48578423c21fed62fcede271a858e4742ea50a5e2c84b8bb357eb90f7d570298eea8dc07bef176a930aa6163d1a81380fc118e7d11088b1077afaddcb5f73595fd6ac2049f4215dab5b7a6f0a2e2bb58173285651a403bba2c79e7ff98a3ed20128a8e0fb237df4703b83dd1f39428e1278849e083533d4b807e69c73ce39b3108119745844d6d72d2b8e129cba5bc022af388eb3c35182231a8d4853f4fff3b7d6118a522fd75385eda65dfdfa7ba27c5d449eb46feb3aa0a8e386b9eef04fe6679db2e22851b9657ebf8f7d86141f5114ef0a3a6c00df3f879f77f7251bf023e6fb9225f0a8f9e8f1895033420e9266e6e2944ff46d6fe78d3788434c62d237f88598b4db2355105388e92ada209922eaf0544629f8da156857a308380b2cabcbc6d8ff9cb5e987e483a7d3575dd4461d8d3c0fb53f93e9f595678581e089fe176a134843188a2be8f0deefe3117df347e5595fa2f2acadafbca4579cfa1275e0b2d6c0b9c45bd66f57979812d3f54529d5f5ae1a13a7f06c00e64021588860cc4b9a3c81d377d3234d9878a109124274c045d4a4c90ee1abc99026250862fa8a34e9c0e7850ea1d0b4ae810809ed1205165a3412852ef99049a0431cb2145dc43ea02e4670a48b970746a73fa1fea54937f896d0a52b3e1bf48b11ac85fe363dc245114db85801e882901c06173b5074cba6477450f647854e8bfde1a0c54d8fe892e41881470901214e1ca7484185402565831e73ff7925b50112aa033477cf95683a93ae8b910b7d66ddcb74b29a2d7544a843715c1b2d630efeb34bce395759aef5a6f3accb355799c7a03c701a71c098a67381115dd45995555911facc3a994ec88e0d7b6ce8f303916d6b3498d0e61647106d2a99c83a840b3fb656893401d1023d2cbd89e505dc2a7d0bf78696e9594820e5e925e9ebdfec95bfd9fa6fb6cadfec94bfd9e2dfecf06ffe668bfec6fb9b9dff66e3bfd9f76fb6e9310ab4bf890ced8dfa2452d7106de088147d3a3c25bd2fc52c2c267246164ff0b44a246df9cd8ac52f8c52d4140d76fc8146035d9da7bcd8dd9a9a1af48977b0f3ffee304a097de2ddd368205bedc632c633bb000ce089f9f84724fac4bbefb1ab539f3435bb9a99ccd31755bf8e38b7300e737fb9a78a5dfc692e613616f4afecf324a0d7aa63d6741ddae94a599d6c7fd516c96811d446fd15188a29a21f8fa9225a05a13efd2aea9b356b925d3f87d5e44c0aeeadefd50bb3ab4b82b55ba5c79af5b5f6d1a528a6528a78ac198a6af56bedbe6e485e976f415d09f52ba8db1c89df3cc98fb3dc0634a6082b76fdfa225a0dc17115841a457fb1ebcfae656562cb9befabb269118f8867fb5fd87650969ffc8faed6fd7ffeb4a9bbbb5b7777ffb16b3468dc682cf7d2ff34fd197a493d06054be3fef7699de36dd0a60d5fe33317d340038d6babdf9e19947ee0c13e29a594babbbbdf0e709949ef3f9528c62805a2c251844979513969979516d67d8f712f994c251652cb8a8b3ea9bca4c08863880253a31822d5f71e994bdcc195e11ed80f424a71544a679829d69a6460d619f603f7e0cad0da636830e9a0dc94a4aa510c3015a2c4310546e5459f565c482d25966f9f9f5d99362db5905c564efa4505266544852930868a3e8965f807a639e3030f64745092af8a9132533e6ac37eb45a6c00d9ce0f520f6aad0e83dbc1a714c3b77acd1683210bcdb0cf8c440626032bc19ad9bda463cd5c82edfcb2e60ecf56edf4a85ed654e9b8ab5ed6cc2ad88669626fc4f0b1d6c66a8feb2a19238c1b3b3160559fbfe9ab6c255b2a9156ba1bb1124906a6b28d400695cdaa6cb6c4534bb19d75b88f4b5ddea504f2d1c8415b1252343aaf2eb99d1f248d24128dceb2686834bb1b383760377a78b8e143a3bb7163e706cfce3fb34f1add8d9f9d9fe45599b3f48ad9d5f9f292d9b12b0f0527d867484f199f18b0157c768ec1b3f378020b0662d43c263fcbd31626c7135a3060a32d01c4a0f19f1e3c91a3fdfb2edcb45e1e93a37d9777e1a6857fcbc046191e67e187791ff861de3ecccb8f2590fb2f2f8fffa675f298fc9646975f060a346db9d076fe1b63b6f33fd167e915c6f69967cfa384fc20c9854b92eb66f4e152aeec6e5aa498c7644c92784840ee244b92824824216b8e2c4922d148d28c0444a259d37e064195d24be5a965916e1e93ffd36fc9d2ca4eb7b223b99c45da952497c7e4bf6965d2cd9af97528981d90b825dd76fe1e92ce59e3e727ed9c05f3f94b2ebb327d7ed2cdaeaaeac763f28b0f43853e55403bbf25551ea9aa59333f38961e864667cdfcaa9f14abfad93918da4abc90ec1c38d92bb67aced66a67744e98d4ea3647c3c4ae3c1976feeb2c9aefa3d191606e1a9bb96f404bfa79b7b5d6ad4d90975dbd563b3641767cd0fef489203a9b8a3b6c82c06c82ec9c34b9cfbeae68bfd034b69d3f35a3d1edd09735e9b97536150fe045896213c46513c4b54198dfd804d1b126dd364176484fde40832339fa18ef8f7fd38221471f308f1f97405c1ee66f5af4e57139e33ef0df1288cbe3d2f498fc3470d0e6ce7f240a111d977c794cbaf8b8ff520229f1bc8b3ef0bb94404ab0f797c7e42745a05b5866c79a2d1a9d5d4de0667b29d363cdec42caf0784cfe17522645461778ea871ba56666067564c685737337e47abcdc9254ce057d804ee08fb32cf6da6ca63693ab999931c1ccc5714b230d31129263ffa811bcc7aca9c6e26224bc3755833e71edfee09a9b585ceec5429fb876bebfbfbfbfffae6123a924fac4b5215cf3b1313586793c66a41b05e1ed704fadb5e66aeb3163daac69333de605dfa7f5e9f46f9a33333516f7e5b46e67ee1a3366c2602316faf445e1b8053e398a5deefe7848f8d4984dc89026786019466d74a1cdccc426daf8bf16b26bd7f75c2c3b23809254940dac12a19750acc75155d080846841b53beed083ff3fffcca6599661afd7e797c78020e7ac027dfe2bf67abd6640fe45ec13c38073b89c3f671960affcd2d1e70701d568766591d8f32df5fb4276154413b5fc302ea9387dd2da08b656ab793c78d46a351eb51a8a96637233be3f0e25d77397e0940c326a0b1fefa37ddb8bf93eef83813e692d6804cfe3418d7cdf11faa4b53b941bc162962a888c60bc8cd3cce1f7beefa32daf9ea38650ddb63c154358635b7b63a0dda162ddbab8c3affb1577dc7bb1b803678c31cee28e9c73ce3bbced0faa943bfac36dea3087599a4e5763e58e1611e08970f6be941d5ede78cd2e8c62fb81d094d225f4d27bebad746b213e10fabe6317b5714b039080521b4e7180dbcbd5463cdfa5511c2cf6c3987535ca140202f3e058088208629f1f048ea5ad62b8c73e8d8964506339e7c172b91acb2da9af4cab9f041352cc20071e8478bd6ed8e1000c5d2e5701203c15a82e6b533ce8b3c692a4e0af14d8f249953ca047f55c2e9773393793c5908213abe0f2d4180c32d414c05eaffada395763390c8315af2530dc050f56a1e2fabda61949c07be2a07b468b918a9aba613c138001fcbf119aa6a686efdf98ada6b3167853a111ec6ca5cf72b1f1f001b4ebd32bc301937d86479e80a01ec14192aa6bc5f72b0edaf5f384d8f6474275195e68fb57c5b61540758e9b31bd725c006dbdc7d43fddb4469b9b96f737ad176acb1bbfd3aedea22daf1c7d78fffd570249a144c163eadfb4acad7e81cbe518c14b3a3fe20593333ced697d5eea5f1ebb3aa9931db3abfa2cd8d55823428f0636cf754fc163eae7b0b6f2f01eb565eb9f34b7ab1db32d52bf5ad64a8ce25cdc0976a52c9c94d80d8cb03e76458fdc00c7ae5e767d0b24b333cbf256fdecb68651c71ed6ac66ae6e2f04d6656196c7baeccb5a6b6dceaa405f955144571ea0975d7999ffb3af2534c5f1cfba5e2519b4f73c5eadabda95bfb76f79aeecfa03840de8933ad1a9cf420528a5a7ae6e6d0a28388b5a1b69088a89592c168bc97eb0a0053fb118b53103bb05e83f62b916a3c55037e893defe76fb31f3e376a3b7194522f7d4101c671c179c8134b006da7e4c3142a14f7aabfd7cb313ed67326ea507903e7d5d43a040680ce102acd582080912d544cb49205704300c99b55a2071d12269eb490f41b096254718f80baab061d6b2248d0f2d30b09801d7b2648c1cb4ca293290c4ad654954182df0da4a3d51ca79b33b90d500cbb52c995ad26ac1d62a7ea0a684be2f8f3a14f92e0a8618ad07a3a498b95e19658587ca803e33ae07087b23112700620a21b66d82076a24075a040d4350b12b18553481628b25f015476c1c9d9d9e30463d4c70a29623c728440b75db7eb8dbf645d70f14743bd125be2c2bfc4fc481e310383ea11714c715751ee2ec9424e26b5b7176d2db496f27bdbd6eb7db8d07a6824a6228e3e4990fedfa4c684e6a383bba22447c7a362cc3340e87cbb88cc3651cca8995271f29550b7bf2eb76f9052b618cb30223a1cf8cc3617c2fce8aef7be1dbfd408105639c15d8a5779fc6b58830d18d5b964fea8a540f339c450d5161155663a0eb0401010e1020a91ac0ecea0c8bec844784b56dabacce9c55c4b2446f3f04b2acd1db0f8fa021d42c0b7c1b92208c488f9662028f59fcb8e5f1090b7e664e7a957d403e5f65a254074632d417f6e947353d81281ad8023df4e0a27d18638cf10c139b1863ec79175fb3868065bc140efa3431be33a69b9fa69940470411395c0e87bbd574301ad0608783cd66475447f4a967dfd027c383199f0c0f66a04ca6b166fa3413263bdd4ea7cbd9643fc40ff113fb89c578f24b16628c31c6175f4cc3a1e75d7c710d8f883e290d9fae084a1659ece8171bf26837e79c2bc618df1a3c88904b021880a6468d5413354835a69a278c99ffc44972e05a0eda6da99e6bd7b74f6a4ce879817ba007bad96e365b4df6397c0e3bdd4ea7cbdde8379473ce39e79cddfdf33f9d4ea71c7f729d5caeaf3ca13ea0cfec028914b9d7dc97c83ea92de7d9ddb183a211514491c3e570b81bedd34b7e87df61a7dbe974b99b6b89256eb69bcd569be99a682287cbe170b71afd74432a9c0aa7da42b5854e25a412cae17238dc8da6b37d101f448d56a3d166315b1135e5c44ae129125c54101e7739e7d3cba8bffca180f868417ca82b44b6911370a44198d289231329291f95510b9df3e757e2bfafb682720129e56572d3a74eecf35e5cc3355c136dd03456c11283962f5c521938217941ed00a36464821a9ba4503f317c50a55e8f620199828295634ad40f1d8c41326cf00095830fc63066a09e30472f6250379951063484a811e69c615e83868c8d041cf919fc0c9450e28978225c5860714522914854452291e8ea1a149c75b21a2cb5c7a490645708bed5c1e0277a146a08a292ec805a71d220695bae65da7edfbb8b441fcda140715e28f3981b1a893da17a429f7a171b1afaf4129be7ec9e73ce3e9373ce39bb995d007f3a4da1cf995a0d77775c33e333265b123415121592996c2693fdc068b697bd2cd7322dd3f22cc73e6d5be2841337dbcd66abc9622fc40b9179322cc3f24b175341a1826297832951b2d3ed74badc8d0926b00ddb6a33fa61dc900a062a18d00f36a4830ea2bb3bc63639368c437777cfe5eeb94e3ea72cdb27b5d1bab3dddd3def5e9cafe7b94773824459e801d7f96d93aa06fa3c611dd69d26d3a75d4b32146ddf26272827284768834ede6bbb51176d7284ec2a476875b3c9b1d9e4dceed327726c9b8a3b6c72909434ac95a66b699323941354ebdbe404d955cd09cab1e520b126ddb5dae4d8ac996393834428a7669353cb09ca09caa165974d4ecd9a7557499b9c206bd2bd332c0fe1cc202424c660c40813426a35951d74dfafa10dad3f8eedd6fe576aadb5d69af6a54e6da595524a29b5b4de276192195ef0022d72405f30fb012816e78d7fe301a2ec5c9ed94687898d0e135a2dcda58d0e136bd2ad33e4fe363a4376e53a435b47a7e3c49a74bb7b9edbe8d8e8ec3cb4d171c24427e7363a399d219d219c356d7472d6f4d24667c89a74c772908b31d6a5185ab37e186a8f3cf9a0bd7ab266d51f0e3d6c84b64f2bb61897a0f751c73557ba6badda0bd8fe3648c5fc3d68057e9397d5e57939cbeccb7e00c3b647fab0a63f0f6be2bf240b16cb9c35defc74e5497f42cbb33ce9692b7b8f3f87fb398f3019ae9424ff1cce1a61d1dfcdd236b7619c688cf18f5ef477f4e5b5a6e8a9a8c3a4365c54020f6bfaa7e8a047f565a6bc1705687b8f4fa6fc609541b7388abff237a637a1e557de478bf8404adf22963e564e16eeae2f970f26faa4484c2f4f5a0bff86b37d9ffa5b9ccd22b747201580f4fe22d802f8d7d802b0bc7b25c5af678dedfa555421fdca9fc0f22da45f61f9962d56fd54dc71b32f0b77ebd2665141a8a1187e0e2bc3aec227a1e06c90821e5e16d2449248ffb72cda727114c51acb2ae94af8e1001c26ae735541c43e298ee6b68bf99e262ae4dad934b6631fb1870bd463806cef47f8475f4713fe845f006de1b860021260c080822739fc30d422b900820f458021144507224ad0cafabc3ffa50c462693f504118bd479e9508088e6ec213ca8e98c34bcb1bcfbbac1a1be35fc5efc50b6b6992323206975da8e4acd92b52c9cc8c0000000053160020200c0a878442a124c8d2409bdb03140010648442624c361ac782912489511004510cc0300060000380310019439132c407151766a0bd1a507a78ba24b1ef75afd4550f328e8ea21b544ada45587c1a8df7afba5a1ade1ae76c9adaee32c2354ef53cbe6494cc4f6290bfc0c3b8e3f445ef1093793757f4f87dd7d626cc980706064007f5befae2a5e18451721af138a19076b86a17a48f57e0d9c40173aba6b7aa8b81b3ce9bea96724772734a7561de30f6ad2a285d3ca1e1deebe01b74d7c47a6000fa02068f318927899d8a7f4a33a7d7800c88a7a9278442a4d2cb8f52df6a441bbf4504ee7353ac0b48dd278268fb0fd3acd823d8ba3552e959eb3f08a03df349aa0b7ba3a4ecaa0b01461d1beb92a52fc764f2788013a59c5e6ea9c45d653160a86b73eefa270d626eb04bc304a196cc763b82e28dc8da6043611930de438f4aab3255582e372f0afcac40e71718f974b147a89404c35457005d7c41ca8856c478d68aa67caa1f4023e8e9b339adec689cb7ebbf75e94bffe046b703ec53cb411363b9f047fbe8f1ceed31739010aa05b38f2e1d617b5031f7e90897d0a01350a7fa33b1922d2d39800e3b3769b3b1d801754cff9852d7fe5d3303986ef3d4cf4b7bb9997adf449409c08eb0568f51f374b93e63ecc8c6e01968df87950eaa239fc7736d91b02f14f76090a14c0bb9a65cf2e106c954d6ee2521d9cd76af6c0c34757b5d1a15057532a0886deec76c5d7e12f4ab88b9319e653d5ae9f1a13da886e8d17c839822e631497533454aa6eb455dc0737c4eb3f0033a2761d46c149ad7259410a6fa703058bd896e9291d49a5552faf105bde2f4aaf80d834c5e846146cfd797af3ea21386cec7981657a521c3544db810ae6754eb2901097c3449492fb64ae4d0bd63e0b8ecc3435f768710d31c77e4ee5f89a56fa2c60b5894271d71f1c2f35e73a7070974490c4bc9151a530b55c9518002c0cb0fe4b48437eea66a1d208cfba57cc069e7464bee8af0a182e5e9c4bbd932686df89054aa0000dac7c839c690e17d2c72022e338b7aaf430ac00d8cb3a69654de904bbe70a02cda3b6aa5c46189553daf6aa771c8b8371901380fa5e635925eeee1f1ec52f45e4ad4708cca4187735467d5c6ba9584fb1ed264c20173ab1076d585c0a1ee0d74a84e7a27b10ad3071b7dd5f554fa1ba74cbda4b9e77adcdfe635e9d697b76a8dbde9a7e5f4da377b6fab079628d15ec5aa1d8f8abb71c8c86be3c12111d41c5e1a95709cca7138b36693eea3501c088a53530d4ad3acc135b44d8b3934403ab286c268d60457acf47369d830ed3bc9c24e98bae6f0a4e401c44ce054b136f4f36341fcbbd48dbd08ccdee11a63c3b8c0bcb107429bcf0e6c888d360dae5168b67487268445d154b86e8dcf1517ed438b2a1174e0042c4633d5630f1766a80543535f6332cd0da666f327684686936de1539910c5f224a17e0dea0c928746262e71f888965a013a4811d5dad8a5eca2b222196084412306f1c79bb889c1ca74122cecd5ebd8f581ab6e6bb928c9d120244abb1db722ac382b2ab12d2368cd1326b13794acb7f17b004d31d736729db2a6d57a9b1047362a5d8f26d7d2d4b4badb08e1889aa00461b150827cf5826b3c1db886d8fe230635473194c6c5ef34667bb439b52b341bdeabf1e3609ae2564b93e3b4355add5d136ad14d562a1766f40e0ea643d23e92f03f7024bede7804412c5b89fa63a52f380e6cb0ed93f1fc78af51e75b7bb0987a6722a9ecafa1d4fa2d7d6b058bf4adb7bd7b97527afd895f1b253d415b4b18a1670de3b1d7139c0a7324e4e58d881a5d873d1b5b9951853d506a4a9038f1f7109b36e638ebe54901583fb3e4fc63eaf4d0340090c90919e795b768c7c47cf1c8988436e65904d171065a20196fa74b0e71b6018f8c3298e319268b2c9e376217774520f725d9f92bd63407ea9cb287a7a6cc14ae0691ec4d7694d20fbf83b6da1ae90574d274668c6c1f167f6f3fd4aea762fc13b1e219f53df5eaa7e1883807985726d32d80248bba211eaa758c5fc06d0dd5e5320b8a56e237706d7889e3f26cdcbc4c139e9b5fcd762dd560cd101a7e4f917ef0359497477690e4890a79ea0eaebbcb66a72c9009e44f620774fee5e0b2e2af3f6d326f424f2855517f94e7554f20ec854a2653376c1c7cad67a3633ad3705e88a094cb0ebe11597819da7fe0e6d58b6fc834cf429063bab198c6f23eaa26ce1039553a442bbdff4135beaad75bac9df39be694ed20c6e2bbe802337282c5713b5115efaa8a1dc0eedf8536a7ef8bf666ba0a7a39d0a169c57bb0e0172498301bc6aedeb05d5e9361d2796492e0574d25620f134e32a95b7f5dea1ad3f928d4d42e624c3ef42cdac9f0254e82ce0fe1dc52ed340305bd97523500a7721dceacdcacbbaf6f85d10a25fa8b18a0f9f60e4ab5412ec16afb4da3a5427b4797689ca735a73ab06e29f4ae722d60d66133dd421ada99e6ed60cda3387cbd0523518f96541ffc93aca6cfc683bc5af61af4f1f4b4de36d30d2ddc451db3a903eb964aedaad702469d37d3457ad721d1c4767fae4c695825400ee831479767fd2ac00f89d5cda0a7356ca180a14f8f5f00ba2e12d48ff9290d058169ec6d715abd86f0f2ed8082e6c2ad8979711ceb00163050655f791237f4685e38dda60fa84de87a8b40b6348199ea83cc304568eb11b1023d30f78543696182e3c7cdeb21554cf7e80133f03d6ed597a0f054c0afab8d34cfba362c75ef604bac4a36b7c836c7936eea087ce5d71cb67814e97ef72ac1e968910eff91515b83c77cf88727c9a5e034c9a9beaa39ad249400cb7ca4955beb792359330292dc9da27f36f4a4425317d3a2576624db503cefae55ad129f7300fcc4067424a1bf7954cf5f78ed39685c6627aa129bbf25fbd4bc297bfc20f1df146e8f415a998090deefe43afef7b18d54c156e9888d5b335d9a3495d3a6f13284493291c9c341cca1f34fcaad318a1a0cc0337f324fc1e88286295040eae7d0a17cd6d81bbfd7b968c24d104049e6a0c8b233b7a92d685db3e31dc311d5da41c81a01688cdf31067377075df45fe955563162dcb8a30e1c021d20585b1f3ae875ec4f65215c2dba68988397b7cb5fe51e60e9442501d677ca3c41d8f6d2485e09f726473b48db83a5c5fd991050a6f96807931706436137ba810fbb137882947627e172b0550af3dc057221a4ad8ba65db9a688af68509954131f392d852d8607534cc0e4d23bd8f8f9c7d5ec8a8a1c36661dd11093307ae90cd788d89209d22b021d06b38e35430cca42085d4546cde9e610d304a93688dd14a42393b817eff06f49c9bd6014daf255c4047008964a161530a43b8ddf142bf34ca735e08d7eb1d0cbd5c44e03f75240bc1594b665a1bb6ba9aeffe53b1f3ee28a9085b9e26b13dd8199eac284a32bfeeab5e4f3361ea3f67865d13d1473bf771a84e6dadfc3dca4f32d6c1cabb917c3a0eefc11781898754463c44826b8aa0484dd5400fc8d385079f5afbd9c6c1b9c9e302a1077434744ca98fa6670eee238e136ae64ffc007feba28263c47e95e535697a4f9343600c06e526c43c0926deda280c6b3bc0078bedd7a9215bf30ff0120c998f7d4cfa0899353e0496c1da6e3335963ebc660f23217234568752f2089d16420b485e525af88915d18075835ea017cc4b3357a04432bb6f131486d15571a46989ea28ee4bc802c946b3f0e09d937d342391dc1777375139e4d5819b487507df694d19ebc12565c7d07b914b14cf7afb99b5988a7dd0b4a0ce13b0319f48cdbfae55b31f47fd18a324e84d29e142e2c904e5dfb89127ab48332d59f50a6650eddc27dfa028aab5aaa1f3abd968b7b622dec6dc1811dc05074556f9017783ee8f6d1082941a07e9b1cdea1b7fde178d420f90cda12cc599f33e01996c36b2e41486207666b802328f424004d9e2712ea0da7f8a3d4c5ad31fd2d85756a7cc7d19add1234834580240814dcc419b4e871d169001800a8f0e2442610cc8c309eb215f51f2ff090c09c44c75cc955947c4f864704da90935432e0a6808044d3c9e9440f0f54bf4a5a71b3ebc9b091fb256c7c402eb6363385559935599c250ec62081530fb71f8e203a96fbe6503d887b701e7d3f2d1cb630cc0448719cd3cfa4abb5875c033720d5dc7e9e40833eae3978b227d838c1278b4725038f422f3c246b9e7bc8a402aae697bc2b0418f6a528c8c8a3a8eae38dca8124cce99910bc6b12122e3c4c05b4ba1e506d05698e3318ad661fbbad2fd489a4894e4393e097d913dbcdc044086dd51978acf63230286a213583fcb1002cbe7800d845029ab20dc9d7d707e17fdf3a10a337a98edf2830e9ea608119223967ff6a71919da3452130b5c2ae46258152a2e28b8fa61640fa7b6d3b04fd943e4705d2c7ba092d310791ce04fcc303b23551e106f2ae360faca308369f4ad56348869e4cb58b23f6c9ad723ce77efc6a1f4bc5a7b2c5d663d87ad367c5e513411e67c61a9165e612accca7b3895b6ddc37f49221ec4d73573284b82f7c386bd737030590f94098b3a35acf39f730f43e21e0defcd0d7895c2c81de9dd2e96cc4890e5eb3728553813b11f6cf4a6d25b59c43d1a2fae33a23ad6076b2029ad9f02e2f58d0c477481abdbfbf60a2bdb73ac2aac3920d624899a7b5214fd3c940969b54f46583342240a51fa908c76114c537040cf340201572367357cda10f7cbf178b850687bf23c2b2508acc0a4739aa07fe93c4edcf3ab136b7d1fb9f0583bb69c353c4fd57fbe2ca80a9a33e8a8976a9022b79e08dcd8239fd089826388d80d2e542a35bdba874e8618819b558ec2a83be682454cc795a2806d8c010738106c192924ccf352623798b0eda9115a0c33736c5d5655a30adc7f9fddc452c56ed576f0e727b8fd84ec2aeb482b07c0479c4bb89c32a8e42b9f63db211a8acf5bfcbe25efc07963be0f2e01f085bfeedfa2e8fba1c89e7ee590a7f4a778c884a73ac05d05e42515742e084ea1e270aaa2a1fb4a3b8b0094a5a46604ed863166411bbb3ce08e909dc6bec72411d2e1540130b74fad735d2c1f7b76a30b7c026aa17fc993d550a0e75cd14688d325d3bdb16456ae49b6cfdfa5781929b0d6ebfa7787c7f4eb659894ef5a3711857a27bc19ead01d7604e74b2ba82057253d8c6bbd33efd9154b42f8431fffabade9891342e8b8e85c2a3adb1df83eecd46215e99aece6a48f7cec2b0547c76520cca666974177d09ca54083144e0747af5db462f4785f71b9d45e4db5b57a350ea2beaf6db199735f3751a73c246f6e137565953c468a16a638d1a49207a0c6fd3246cdd1657bc8546b8e19e4c0dd2f152ffc78ccc3846a5a303a76925ffccd09ff143796f46577a68a89c15e433133e9dae2e6906c54a621aa178a235492247bc0bce38413f309a7480223f36023a23ac6ab8c345333fa904ec1caa3648f4720524db3a2e993fff49129cacd2f5694b2b0775c9da4d4b04c32d500a379828b280b90d6a302bf5e70ad0c96f9858a9bb0d3accfe295d6d721da54d319a6b89942ce7a1bad609ad92df50c0a8544bf9bd0b265bb859e6627a096f1cd347f036102a650866c581e843e9982f998af9ecc72769a1917e8f882feea796e142bda35623b4c24fd6fe4f40f38826b938fd4951cd4aedf89520ba214d4ee6293e5d688c40b52756e7d95eb670d15cfe4a7886b84af11f3e489ea7e6b7abae8c9bb10a967dcbbf91b631407a5353880d41888851d94f24537439ae4facf3b8ff11ca961e4376a92511b0553d55cfb52459822123815d9fefce80c8f4ece0d7e7dd4d0954a006e7ba95a7118a3c4cdae1e9fab9904bd8f16ed2795d063145eddee521626f210749e3f89f3cae85033d54c09507afa0b8e7c23b274bd98fd5fd9b92dfe6a21eac761a4f1f65b7f44164aae6112613564164337b958e59e5bf6c2a4e21c0682d025ee20892cf9140560e25c8ab226c6c5a60cb3c155abc4ad745e01827e4e7b7e66daeef0e0f9de4c9ec529f73fac67e077cc35c0da0c477d1b9ae3068608e09c2caecfe809ee7dcff248551a77dbcf041e4b32c2cf34388a5a6ae075b4326f9706b44658c9dedc4d50db5dd45f70b77dee5d7682940c0ffec054e56f74a9d1d48c3eedcecfe1ed4e55209a4cfef61486522abe798fbc96c7844c8dbd95e52b45a5ef8dd8d8de525893f1042e72f970a95895b5ab0fcae0a4198a2ad02f0dd2dd7a046064c60992109ae215cdccb1b45893523c90061597990f0c584682953a19b03fa59835f086a88d6322b669625841ce2729625fc091fae3cc5519bf55d87cc49164cb9240a2a87606a649c2bf4a95241ced6e160ebb939227ae25915798c3de46f7c61c0c59126fc3890518d5d58dd4a7b4303627227cbfa61d92dd232f13121ce968555fc8e0ec3ea53ab8ae5c718abfbd7e1f444c10c38e1632cbfa3484f7ab8d1bac840cd659301201b4a9ae82acc3e9848492b1092e606a98f910a94d10d7017bf12a84851eb3a4bb58a5f726275d2aba6547bfc9dbc4ebc92082f9c4432940d56ffb5b8f8c6873a7b4aed19b895a4c687245712d010aa5ee4d6a948409c000d1c5bfac1b83f5e4b80cc44287ca9abcc1ceda603fd4a02ae61212b2af64473ac3d522f7b628c7bec8b12fba44e40ef04d5f32881d62f13c76038c951cd2983ffa8908e54305674f35b05f077b8dcbf91cafbeffd7bf6bd2e3719b6bf43d142c0c3eb3a9098b369b0cb0f7911d49b163c32f344d9384bc8cd3518507fbf548dee7f590678b06e297e9d494ec61b9f0caa5831a57d0c473178207a186612efb34ba880704e82c156fc90f5d50800dc58ff40e8c83f3b4855f221d2fd606574ea082df31d135de8372f49281491f7f41cfd6db577cb9964680483309637a8985f6f77c798e2796d435d2dfb7de1a3d1abfc1dd9f6a456660c48a86018c84132873f67c0087ee43003080a74da97c6f1cf8f29307daa10594c7607e18f890cd1b51cad24b3fd87240b78f998b33a238b4a1be6d9301e2cf3cc6eb5757bc16af1a1a57b9d755e51e29d7ff09d743b951f427f8c3b2efb4bc61f18bc04ee1a83a818027515a092e92879680a83292d9cfe8ed956b26c0b596d824034703e687f02adf76d79712bdd2044e1c91d466a543bdb2041ff6359fc3246424d6f7f00a78bcc7fd15066ec202f140d20cf4a744a5dc57c8db1251bad43e44a1f3c0bdb64969ece4c7c085f7d2b4fc472136a1d305e1591e0033d4e2edf442fca8365e90f9e5f11e1e6bbe54780ba17bc5e171bb501040addc459b4eb9ec5f21509f9d00c1f1ade7e86ca2e2f0411ca25e8db0c42ccdd4f16aa47c4225943c9f0fa2cce07a1e2f8a4823abeb2e533b74bfea0bf0bc4b8589260c79062bd4d6966dc3bc054b126e96fd0b59947b6217d811bda0c4f4bc8a527f2e8fe8168bd63e913847d0cd9eb81a5fb8ddb833dba77f133cd32d92038486cbbfff9e4993ac61c8bc30d60b45067c3ac7ded4c37f72254ee69c07803394f219b9bc0577b573a77bb71d8158a3a34dcdd62168dc1ea5fca809ba9a8f0bfb3a02f0f539e572efc995a0cedfb554a16d5d4ca13cc4b86a3d1a8d1cce234ca6c6ef54935ee20b6d0f5adcbc79e16c60594f23c2283df098acf7ff5f1ada25660fc316f7166a0347e8abcbcc2810f2c65452132104555140b3e3c80ab5850b6f5d5bc059d636a0b5c8aa1939421f5eaceea7943658c807a0dae66d85553af2ac61f55b91efdd09b779c80956eb8719c101975ce3e7263e086bd11741da27894bc2252039e50939dc842d35920bbf92fcb75ceada9650591302abfe4543b93e984d5541786954b03ee67c033016c0149080f80403289b3ecfcf7f1f47670d84a7c01cc40d97b6725cd885d32735cbafa9a68b32ba7418bd9105e1cd586b4570b3c99709e339ac862c7358904ec6cb6463dbc227c654e66936d1927f9282598088c632463d88ae1a723e6bdd506284081b5455cb199e1c556caaf0520391c2ab456a0ef6c3622d31aa299a7a68dc996137608a4e10107a83dd929b8d2036720abb120c79e007cac666a99917f7c9bc7175e77b411e77597ee1f8f8433ec979c402888a4a955b17fbd2a619a2db5a55d6308ac5d3d5b9db28e1c525cba61b7ebd27a09c4aae0d559d6d5c26fafc0d505bef202fce81bacf21939c9c4dc70742a687ca305def397eaa90e7c26ce017e2bbcc30f249e5cda855e3945a339619f503250347b9a420c244f8c6eddb865d445f47ab16a31b669bc8d342029d0f524d4f6776854cfb3094ce7ac0439c11ff89ed96cee71894ff71e9fa7a2ead17e68c11379ff8f81369afaef9d8caf268128ff92777d21832822ccb3e68ebb47a2527b956d9ef8ee837e78cf70c359397b257c7973e1f95327ce7cab2d0e7fa9361895ea8c22453490b3c76c3ef58f93eac1c34af3b1fce73f6091f90fd30ae63c6d1fcc087c4ab3d93b2801e673a369624671587295a6382268312ad1ec8ad46a79e1cd20f7e231096232b6a1fa5ef5749995e470087792b2d2e4c3ce8a896f6c299b5e955b4f1e7e2a8d1793b5ba12a4b70f1bc0cf0263e3549581bff44e1d465ce724e26c0cf985c05ec56f34797bac586e1572e2d3f971b51e09ad46c3f6c81cfd70f28a667ab2b1dce12e036d9ba5502686fc061c70c5d55a3fde15f6b2007cc386884742df27697d4027ccdbd8b5dc26962803aaacebb5bf1786a93674c864c0a802be7b580e3c99dbb83412b74003be39ce9655570b7d34d5ae0943d9c9135c9c27a8859e80a7bff6d58567a75f1194d7c29622b6d7897bdff72da9758965b7ae95af74e3b9171d76a14c223ff29a05f7ea821f6466bd98391e9a7303a3b2dfbb42b06f5630804ff4a4df61054e1d8bcce2eab23eeb501474739bd0c983554010dbb8b0c8253a732fb17b7b7bddbb0c7a248ac92ffe7b6bbf69c701dd696e27d9c4b9c7190cf13b69ffe57f1394bf2aa918bbe0081e2fde566d7941d20419a9750abe42de7f8f9975e62aa4055bed98a24321085849586becbacb4a08f2f38c409269ef307e7ac97d99cee43aa1692b5e5217ad122ca15bbc0f8179bb6b28b0a1c36b843f6a110fa4b6cca5f21d449ec4744bbebf543a4aa91a1684815e629db98fc140075590b65454e06f6a83317d14f0a6380b3be392887e4af815f68ab348d9493237ed54166230c3aacb4d5073afffa620cc2cc65712b429b8ae9588062c7cb3e946fe5c13793443163c1e1cd8007a0141bc0e112786164bc4a599632461f3dfa972d6befe36aae8ff40023b0608d05a92aeb1a2fd145bd0366c1d403cede68559aa86fc0e8c32afe8cc9a9a1af7860be6eea2aacdfbe6c36356eac3e13bdd2a8f6ad38e67d1e579b0d03e8a4e54781c5f4ab8dd9ad7af6753b08f7a30a7ab53f364dc51824853ff2cae44a3cfaee0990a5aa8adfd6bcb8edc50520ca901cbc4d359fddf5eefcf93b7b32a68767c550fdc7c8992e86d1723c3a42b34f1710dac4953362bd07d6f3d5f0965c55b0bae53ed2f9ffdc2747368519d90145c457436a0b50c42fad71c103c13a1afcec81d0151ae0a582e3d11eb803e6def3ec07a6000d6c6afea786a2530b7490af757d8f19b8dcb0a56beb1a708812253e4983a1bda9b83461493eabf845e56e3373ea10a57ddae5d75e9529a8f57fa658b568158ffac501d2a67cb0f53d1b605312b91c986afed84b5d150a2440fdfbac91fcd60781b9e0a9b3476a50584983e5c958e2a6299c5301f04bb57f9fa48dd3cb6001d2efe452ffbdf47c9011a4c5c77811f5bfec4acd15db404dab6279cf9443b82e47ad32de31c7d324d2228e0ca43405a5ccb8a1fcdc3011f0e3f20ade5e8fbfb0ce0d8c4d62ed9446aa16513ba14bcf2db6165aaf919d4d0054b9eb4c5c82d049ae1c738bc3d38beb63baca3927e25319f883a2d77faa6451bcec1868251b1b60019d0a6b253c02338a49016fed9df05b0b8043fd707a59733db7f890c69e68fa439039447d4648c80e67c4dd5d8e97672750142a4f3e2c0846dc2f4baba20b0ffb4272e04770b1ad7a24c35fd1db3366abe5b9fa3197057a86bea278a531c1732b324d5047c7cdc8a47f517a0b8b48d9d57da702137c5fa358332232800bd4b5abad435a7fec438fc36d08a71d173bf9576935b53f4a3ec7e194d3aa88a1a06a0bc915fc894d76300b09f00065068bcb54d62472352d991b9294109b8d59bd966b338b34be412d2b80d93b1d062db7a856d6b725b05b2452e1e1ae643a1135b298806f04269fc4ca26bda9c87c203a9e775eb5d7ddd3a0ad487ee30b42993511ac4bd32cb7edf62051cf65e95f45bfb24644225d66e908f23c27e32fcb84c8c70db58280270ac22622d6b39f993935ae33b9dd8a9f21ee765293149b816d78ab56e11323f593b94a6464a05b25b7da80e9f609f223904857abb2d74c1956088780a5c7b6ebd0423b1ffc5cc3bf472b382c03fae767795c283be78d807f7ca777b70fd9e5333f7b5ff39ef83e2480856be53d2530d3931e5c4d86b246c7e45dd76bb212613a5c3012279dfbbda691fc50d9acf4b9e0d48bd7f65be63b5a6724c46124e2c7eddaed0ab6b9a5199d714d32168f3020ccdfb59aeb449bec696788c7681b3621ca3817486c9b80150b1c6d2c2e26ce51a98f17338df26c64178124a7fbd08d1218d68d65b9c846916a0bb11ea4b8a9efa102fe40c966f745d44a89dd690bf72b58e7cd4f91bca81555338dd463678c89d31dbeac0db0508f872e671709b89d98fce5816195a8198b5077236f50e21b925bb96832189a1ce3ad5699d475bb73dc1386157251478809870d340c14d3e45febe1490aecc2d71526e5c2bf168f34d44367285d18974d54b3ad46cd6a1d2790f8ea0166012bc9687f990578a1b5f16532d73821281746c4c0a0c06628bb12851fc70d74b7ff737fe4906b3679a64ec44b7f30078b5be78d849e883c8b7f404086e31f81bf98200c9bbcc762cf7474b0f2be93f1eff10d11aa02e94031c3287c9e6acc1ca389b1f3085123a6473f40ff185905e51e6391b4970d21e8111b28695d623a0a3522d0ff3088a2d8debe5150cfa7a995322695203b1f2ac018a210716650e1c8a6b64f2305480e39c06ee2657f9e7020d424249a0227480c07bdb7027d1241d04832a0fd53bd8e1fbe06f84445c4f6be13ce564ec4bde41fbd9cccfb108c0cdddfbfbaea0a224e3ad2b25b5a1417ba0bf275af16abd3e218b72f1145ed558f02291f3282ea2e41d2c53e0853ef7094879edea105d17b63dbcb76f1aab0406ce285b93d4b11dbd4493dc37ebaa59c87ccc30f3a7733d86d929a5fa058cbb38b8c25bedb2a80ade9f20376990e274c0ef5411208bbca6810e923f677d1c68520792d444ecaac95df7b8952b33285bc859b8de1039400404db644e043c86f90c19479d8c6161e782dd1739460d4b76f624685a3670d0891dbf6f8bd3a656e4f52400f7b01b147a8536433f9faffee935c33e919b05d17e1128ef37607d9acae33f9d8524145eda3a0d59ae5a20bb85a6cdbfd8f10bec9da7f14d84776f974a1be30e2c52d0b4cd4ee538846e2f22143b0ab820b3de22f4f6ccc7691a5a729d67a41f6b3b005513c65f5b83f166e8d81a7250666ee781209536d6f1c43cbda864afe098070a84ae56288a6a29e30f436b5a24d9f3c6e2ef9d1d0103eab371b365877226953073f7943cae8ef76aa0d2de8522634159d6aa4de2238b29cbb4baf913f9f2b0f0237012aabccc72f98c9c68c043cf58f338393af406e683456ea2dcc3738126aaa05f6fb8c2334825c9e350be024d6fd6f7ad271e4c89d5652384b6df5191bb3fbd91e681f788c0d304840d20ef0be2c7e17390f6feb34d730785542507f722fffdda367b0a6b303ddd7d73592aa6b6aaf14e1d2eedc654b06ed992280254ade84df76b553708fd27bdca700639d16b87bf4ff7a54063a7322b1dd919cf528802b61438b771298e9035137dc59380f8e828d68652298d75822e76b375028d6971611b627c3a8332d90601f7c7bc4107fa0747251365a62f6aa099eba421b636bc6de2eceb926c2a9bb29ae8e1f334db2f6d0a1adbd8195e82cfb177176119ef43df257e743467dc6a431f12a12f2e6461b9120d34dd1acb273c59a6903a6f1471ff5c7efdabaa324762f655b5ca91ea259e865afda97028fbdc0109fd25d9576ccd7357472dd58ae275eef01b306b8a1eafa0b01c958de9ee06f44e8d0096c7703677b90b672610e54a5d1dc085265aa06a9a86010b34dca3ef925420521c10443cc4443b82ab598439c2ba714bf808d3eb3cb6370089d4edeec0a8ee042e9dfb8a5677291bb9d430753b386c1297c6cc16c1674a90bf7b77dd41fa49237554a523442286e5df89955c39a733e11cf6add6310ad5d11b536fd38826317f8d1147e7d761ae7ad634b82f6478a4eaec042b718304175fefe118b8f7e61ecc1277eda64030be00ce20b8abc360da007cc6a7b993da71ede9262c5f49461e464b1117cd17d6aa3e88f7b0c86c27705c0c396af60ed3f938342005cddf0033c12d7612350e06bacdf307b527567d5b6cc46bdc533b0e19b8d2c44147f50fcfde8806ebdda4376fe52c353634946ba08a522f7248095800b5d621663f986828094e696c2f46f8a936c62f925a1145f68048708dc582cbe712af887d79683f946e345191ab746ca49b761fc894c9b52e74801b333eb7b4e115969618181ebd20fe8a355d2bcd804735e6fb107c050cd2b4b5a3123798094693839a6241ae80369a6b5c7d65c0593905eb075a315ee44117439ded624937283cf5afd8caad20cd61df2f9bc5473b7e70e089d0960d1818950495273c9cd888f3227cc22a50e16127b0eed5a1c74fe18453fd0351e1b880d9bef34b8ae9f0385e369083ad83bfc2ce7b0d212d2c37bfa00122c6dcbd83b4e7a3a8d872f8beb748cfe9c69aeb8d6c381d0925117adcf16d39c247bd7e43892d78af980fd4821d65a2fdf7e65ce2397a8c331cc575bd58eed1d14c9c914086d460be161079b6e194562a6b7b9f168a7f1c4ff083d991909ccea248d8e0520e7fa09d7cbee24858a55bc33c760a44f5010d8fc3d00ca7627cb110fd43679962c7e48e5fc7642a91c79894ce50eea1a7a6c529a94195e3f2b8afad2acc935dde1ad8a337ec2f7f668522520e05d4a432a10c837d0db98493c3414058761e0b2b696fd7265f01d96384361fc1731d43e608559a9b578c555da003a6f367f8d804eb8d982020e9f3986b7fa267135a5dfb72110646f1aef6a9e2cb51fb9cd1f4a9a852c435143efe89f4acaaf2f68987b43cd8b062eab665696aef9360cea1036bed788d56a337f1a7582dd34b9737c00033a636ee016e8496aedc139ab763c70418bcc8a97d3f6d0e9e43923f782cf169603c8b4036418a5b0ec03da6dc7455b0c74d2525e1b3cb038b73b7e1142182823256edb3dfe1eec52d750958b2381f116ec95d93eded692b31f764bfb3f729e09ea554269dd418225dd0edcc67675e8a431ae73109b6b010f07a9116436907769b4bd769605486c095c43c32f18b3a48b5b4a15071be2b0e5b8cd04702c9f5f2a541c3cd508bbe6022f5a0a058299867241b007c8059afd1dc8873f81ae1a7b9534b886bb1a3a8c1f62bb4c8b96d6744d5ee8c835d8f35a949e22e44a8b8a728a69948a28f32662611e28308b8813ae74c205085c594bd3a4c44fb90147c3a96b19c2dda1b43d3224b243e4e22fbc0aaf0055438eccc5fcf0279b8509a2033a0d9e664411d984dabc2a017c711219b26821737342f8be46b3b77f2fdaa75df14856d753be6e0b95c0ea928da1a868ab791bba9f6ffd5a32f8638f23f4eb4e1c2c54a6cbc993ac96eab4bf4ccf66cbdf1c2051395dee8769540f29764664999b3f166c51f587cbf70201c5f7ae4b03ece704acbb938bf5da4418283348bcaa6bdb67b5e373a41e1224a36de9e2a79172b4b7accf6bc9ef1c28289966c746355f2dc5796fa3cfafed6bd9622a79cc8177896e6f46927eb3c8ed473c76382507d1943ecbf475e3869018bee4465281cc533a2429547053a04ab82bfe9c9508007dd8d6149b67d0f287ce0cc48dfac771535a82c5ee22a0c0422140443c671541447c5715414c71e617129b7120b6471ce1242f6ce3f79b77026d980691cafa0bfd9168b6dbdde97bf61f0e96e90c3247e449c102c069901803b13b8ef3f0ada4f06ab9deac0a792017ef7cdc27cb1ab707e0e2d7283eceb08f2f67c6f082787ab500a0a8c5da05ab62cfca06c2ea0e4f06f913db33f3111488e676cdfe8c71c3aa0b3efe37e78394bf1b6918b8bfe9d7a35d09adceee3b3d613e004706b5609b9069f1ddfa240e9db8163c7d1bdb9a0a313bf2bed0dc99f1bb5f3df37d15abdc806f37f259097d989c064c37236c829f40feb0eb8d71d00cae5f6ca7240cc48a709d80f8d1146ac899251b89602d8df06050e566292950d415bd47f31e431e8741854dfb9db95d3be9f31849978263b2733125028beb38d1f2a8cc5b89f398bb9ed7a14045ead8d1b8ce36c497a5d3067708f2caef9b8b51f2a3993026aa104d46408bfcc0cfd9b41e4806072b7c8db23aaf006e22fc9e87a98649c53470df6de4864f41cf62f5d399899ad6f7480a489fcfb1f1a2f0468b8d43363d9464ae5a0a2e8dd41f4eee1864aeee5fad99469d898c4d562a13b5c1c0fa96afe267b66e60444800cb58d4ec581e5637f8cec7b8ef92340d5bbef65f6786e6586652d81d2a84bfc57ae02fa28d73fb213b9802862e1e24a6e43032085aa061a0118c3c89570693634d59a5d81bc8eae533b3f3523b35a6ff2a827180f97c7e0f48020c8eca925c6c3ddadea689e21d7d5391a15aa4355374c9444914d4f3e6843f109437d79d58d86e5c1916b90734c5ebf39d711fe1ab915d16da418976b828bb6f41f81f594798e3b895c28ac96fe6f8a44579cb14684bbef1eb978518e0c237ca6dabd2f97d93f4edc2744be33ce3aa3c2f88043d5368688facc82660109ea7a938b0b29f8982c03b1559e7143517f1d5114ed1a08dca3f8dd7a985f8c405d30312de416fa136ca21a9a7a1e6f45e2412c88e831c4e586ca126bd734e2b342c413eecfb6107504df82b243db86b03154b26a9fa93a30025c3807ad1d169eafeed6a2ba3927651dbe8de72253e9e3780e650613d0bca56c2eaab8d55d45065d8d74668dca2bbff28f469dde16b46510b570a7c32b5741520c351c9a917cc1fc025e4d1b36ae1ac90823107f666f43127ee399db4740ec8b01afe58e44b965caa190bf3c2b58d17fe9fd475e8848aa51bf56200b260702e7533687c6cb43ed477d0aaf8c59014bf5df6e0378d4aa31b36343c5aa7489bce9ab8f65232893543829ec51bb9cb0978e8c91698e468e97d550ed226efb2be4c8c5512df6a380fc50b1d14c796785d03840ed887b7fb5acc6366967c3eaab901c49fb98c616a4958deb658786f43e795ed6d9e7c23879990fa51d48ef72a8f8e125f340de2e0a80155109280973a54d15abc6603515ea702dc5be5893f63b15edd644c1ac160e64954dd29ca9e8b4886b061d8a581d694cfea916298aa18e9b369fe9e0e21e1b147131368fa817bcf307d5b30c8a65ce1df244fad50fd1e07a2f7c444a2758686bba1b4743bdebe436eb4255e5089f7a832cb98a60370dd58ccf5fc4885501185c4c00a50262df5169b7d47a241fe5f6c6add3dd54ea3d5ff40c8fb060b6950c3a1a071fb8b9801aec3e8ceb23b097b6b4bda01589b7623f4095db591f374eb92a9fa7e5e0a218065aceb39ab6ab5d065460c5318c5d3529e9f9daea6a84aea8e1a3bd6468ea842383932720f5d37914d08b5e80fd366af677f8fcc69ee522f0e768f9ad0864cd3d0b8a9ec66ed66d01efdcb1d695743101e0dd3bb1e8d15e0d11353e95070b8c0d2d36a93b99fea38cedc4c65ab888435c69b8e0a74d1decc5950f2b76101a42179b6a47794fb50d1675ee6d83523be606d41a47ad37d3699198cd415de7e5e359e86ca55648a47689375b3323ec31969d57cefd7bfd06c4bd70ad6e06fbd475abd222aef32b3fbea0577ac420a9f1c2cde1c97594b4d13492e84c911d573287d1f0885accded3b4967a7b4da5b78cb75430e39cd36010d519d0ceee7923356f3edb1cd3e8d95362a110e4f2cabe2d84a0b054d8188b4d080ab718905fbc1eb4d37f19accfcf375b654ef83b2581952ec86d9df5d5eaf7dd30efb5550da32e44e981de29f83139966e91101e4c1e19210a5539491148369982c3b24b63f996a92453a978e6e3cbc22c95b80c45fb625f5dae5305cae8b93e044f74622ee72e6ce3b1358d6d135686a96b993dcd5d762ef498ce608358c0a6220d9e0b8b496fb4c87485afe6105e75b172712ec2580334083da918ddf14d4777019d6a1c73e18724f7d042c477bfec1b98e6a3631b81c98c01a39418ae7c87856dd44076acbdbe04867cd981d1ad3525bbde49e72b2e1dca07cf95f3a5979c6198e7c91040ec60e3c7db219625c1540cf112cd3976e7c332780a8d590577a92c4c33ae84e50986f50ce115e3413902499a18e41195738e1f6ebc8aa7b68a6f53dcb78e9591ffeb90b86d8e502c90b0b0a7c69a1c51b211851a4296e5e1bc0699ff452f7ed2ff5872474d4a241cc97adfcdb4810f1ff0fdd088c0484780c549a08dd131e7560dc715aaa0c8d364cab31f04bc1f0352efd9667cffe101eeabf8755e63dbe1ac240abd5bf447d96a17ecce8ed48357d3b2e69af7794fbb284061bbfc00e6037b134821b93cda26d9e53bab59375e28e3cc9058aead2b62777333a56ab2233cd6cf99da16a215dc89a446af23d128a0bc5ce07e5dd2e5c99063a40d955ff0224577e240a949ba73fcf6854e887f46a5f5ca6757ffd826c6ff3a8734551298febb0adfa7886426d1389d83b2b4bb38aba7c79382f3a6977cd2d4af3c15e8550d64723902281ee7e8bf0335c29518bffad54064330ee24b3c5f17f1b38ba95fb043254e8ece2270f5a14e6d98aa9ef428c4e153ed402b1f7e26eb70eced661f8ea406c729c41367de0c05600206c095d3f6cbfbf72aac050bf1c1a0a7de220955ceb6fa4a59c7d0f1e664a2f024625e256aa88f338905793dfef6b34bf99c1f1106d9d9b759f23c7e863b70471f64b16a963c912b83a4d759a863b2cbd3e5506ae34e82c1524508115e17bd9c25270b621912e039a2a1c6af21341f1a1372ec7495572f01b84d34147e3b809ec0e9485ed692893989461a093cf49c7876eefc10fe159fd50ae8b96a7e21d0318758a9dd2cb3ba305444cf493936747f890c5f043f502ab964788c122e61ba5a510562319177b87310513902b1ffa4b3e356a5319c5727cc02c3e610fdff5d87f35ac29ede364021a3cb0718345033dbe405e6570fcf4ac1ea785b48b8bf1eee78821c85dbd1b035a5bfef19b53dae894775e40ea6d322acb368e91be6d49a0a8362e7c766258b455872d41318ab979212d07b2a617043ebb8c27003344947e1f7c3690ee123550822e94c284941acdc87a40e0201590ad5c59f150ce7e4d346113513a882197f4ec058a07e2ac97dc47b62ed27a79bc10c5fece222efc858eedf7a6e894361fba6627fcb2273715ae4fdd260ef7e9f02f2c7402519422813ade3c764bd25a522d93df478b4037434d388c53b2228a6c5a56b4f23978f55a71b0d37b79083f9be8f6edc6a7bd0eb1400551150459c172804d03409d629dd0096e9405a4e18fc6d81d2f5249bdc55f72d51443a38872b27e0678dff67d509289b03be668e42182043435c60c4d89948e1d4006642332670192a8886b91c91913c5b5206b69169a17e8d02863c422d5cfe29a950bb424a5d2558937c0464f25735300f2482cfb776af8d9c0e3e701de5018197d2ad70a1bed091cb73bd84a543ef764b3e494f5696a84af8cd0fed7bdb16abc56f1cea401f2ab0b0f82ff82041826bc8640a19d5c13b35218227642ab02cce25bfbe40bbe8dbbfbabfa865a6f39bae7d833b5d266b27004427cdea9b59fc6c37397ee2907facf64f7d5e8cfde026b57aad66356ee2bc5003e9661258be3074ea63666515023d8916e199a3bdbb3aeeaa7d8ae021b312e31f20a6bf133105eb30f98e265e16519482bbea319c8adfb1a41b795914d83c007b0c252a9d7a6e0c67d8bf128042568f46def4a199e58077f0462af84f0b462882f71308695e24476681dca1428e46e5e44faea6c3b03ea0838aae3c39116d16374c8a297649f2ac8b75647f626cae2bafac8be2730c3135cc795ec72a500c14864fd999b4a6ff08e537be2ac8c6250df8a69c7f1713e1bd45967abe42147299ca514540bd3b13561df26cac3f8e0bf7ed07f1b29d23f2ea500d3aafbfe6996c08bec7d6a1353497be43e13358a35d780cb0bd10a5eca74dfe29627ea0fa8213626f217e102a451df549225910c0d463967beef760e1b9d657cddf02c265774fd7441913c616bb84a7ddb751f9daa2ec531581c453e4160cd626de136de02f6e9792ec950863ef2ebf75c7c5189738f870490b16c672251c819edcbaf3811709878d4029182d30ad94ef7ffae71058332689b9d2435805ecc532d60860fb4f45b5b301f784d9f8f761bd644b2e7b289cd37753828cf200cb19d6a02e867fd4871f3bd2501d3fa62730b190cf66a9fc9fc8c84d847f64b135827ee02d989b0ab301f058d954b65717fb44ba337b43f8e6c827a2b74667bc54e739f5dc40bb90d26e195591aaee6456d9c523357dc0224f4752e9f021f5084602a00e1a4dc56f5b6d07a3e46cab6fd213954100b4371cf019df217fc8c2ff3858f5b646e0271a8c3bfcc7174b97dd346b63e47ec276487f4ceaad1e0e22581643da00ca3f45842d1f773b35ccce2a8bb8fe337a7710685cb2e87dac9302f2e20d3f6b3e8c0104bfc65f12595940a88c0e9c34a8d93361bc39edb91ee62da1b8dd5a32cc32245c847a8d19681422a0cae410d6f9d930f6c77a54cc1265763a6752f90b2fea7964eea19ed557f3ac25c83bcea5c8582abe05236fa0dd1fc359f976937b2b8970eaab08236282d30414508d0fad6580a0e45806a0a259403bb6afc1206dc4b04d40a2d86d24a54f17a179924c9fd03d3bf3ca09946b79d3b8a0193748d26b97454204aae9b556f104052600259b21a8141b08dc76748be1e695b1d99f4be90298fb39aa934f033c2d894dcf2f05f095fa84c7c58f6cfd135accc172ea010a7923dc4502cadf65f019ed39e03970c957e50b2e6efb627bbb5724ef86321eb25d0d6de7dc138c94882e3fe3bc060b5fde221532c6cf4679ce55c9ad7085785efb17e07c7b30a07caccacddae073755d0255361da690196753e13bc4f5bf4a11a2446c85405b75380d350ec66ad1893d4fcf001e57571da8594d66e6f5b2e0896d397f9e44c2a81442cd7a5b0be046801cdb3c13517441a267f86cde7a2387fae6ade2303c47fc9f810df23c5481975ab267ac3d1eb42e1eb762962d51bc28d424c8a691319c7862874d19ef0fd0b8fe8775e160cf80ef23015bece2503431a10dad9df89897facef26b29821f55170bd6feb804e08fe56130f83852371d2e89cfb69e8e6365ddf42ce9d69ea15aa06124e0d0f039b714226b1d526df07aa8826fdf9b3dd24a5462094c092c81e4fe0a501afae3061c8b24421dda61d03f386851cc6f068d6fecc3e513d8161f7d3407cf3510071f4b6f2f91ab733616ecc1b52b8c8558e2ceeb1109f47a3c7a2579b34533b8f9f957aaf472b69eee61bc7c45f983b66102311b6c0b5fa537264648b10ae43f57ea5d37d823dbe246dc5361efcaa7666a51aed1f159c918c44704ba29e7a659200eb39a0e9503864496ce0781081397a373e5081f626bb48b486970138a5cb96c1f63b32061d04ae55502e38aaf28700e3ea2bb58f8bf5e46225c181c73a808d409b8d5ccce8ebd74442385a7cc32db765b937b4b29934c01a10a0c0a280a14648fd209b2d88a24129226cd8a24994eb5f26e56aba094af564be84f7087f7ad7c6e63befda70d95fdc9f2853e4fa100a278a7b37029a42286e880343313a479234d3d4d2d25234d2da51afb1355c12b3a4f3f26214a424b32e4fa89fab979f97669f92cdf437440d817986d893bfa3cf93c81f1816a1737bb9f2c3e3eceadf2f179fa49d2496a25f1ce17306154610729aa9c4e5290229b5510e72a0a4a70ca9de0cc87a0cb365b5d6b625a2272597115b98c5c472a2c903c1bd5539b2ddb6cf53cf580e909e3f3949412737315b98c7a6a638709c729f41335f6d47ec9c7501d6f8fafc72ae8f31e419ee37c1688033597c4847d986d9502af0c0100ed068019cc067b8262413d7df9b1fd64f951fad1f2b3d462ff84f931e387a95bed62a6cf1312da10d0076afa3ccd964f94cfcd670c122155f893d4d99a45cd537da07ba0abc9b5e4d2e252720db9a6b8885c565a045d4edfae2d2e23571617524fadc7d6f3a5078cab480051dc4183a09da017068aa9c9a9e605cc17a25b9219adc54e02658a2afca52457dc91b724cdb6240911b20a52f90ae454cae8b2034d063bcacfb993dbf543f0a1a266eb8977dae6a57684949445a9c52020cd653fbe17835fcb8ae927ea47cc981f3db59e5a8f971edb2f7d14c7acb73f53bf5c463db5fe02064c989e5a4fcd0b5d45aadbcc0df60566e37a535f06aba0ea6210d7c1877a30ffa4a485a9a9c577fa32e4c526190a7f6e49662d761221285ff84b5780d428950f987e0169177733c19902af841e04fc899aad0e7fc624110af236fcd1e18eb5168240403b5b504f35fe09363741c9cda0fc945cc97f0bca9f01e55f50fe7cca3f412e0794bc2383f8b3666b82dce3a55bdd539382abdece37419cf78c7c13f4f115bc127a2a0c7f8077b62688c157f00a10a7a19dad09f6782f4810204080ac827a883071b9ea3db616bba716e4f3c43bed44be5c1797e2b894d7f34db0e6bd23df04797c0abc32c48508f10a5e11d2f10cfc074873d910129c609104a5f679eaa991b0345bbdf4b67f1a02fec0c1adf620e04f1ddc6ad7c192420a4d6e13d64f7f41946149a1c97d1c6f623fc749589a2f126addaa83633ebcfd870e8eb15ec0310c38d6c3db7fe6e0d88db7ffc8c1311edefe1307c76a3866e3ed3f70706c87b7ffbcc1311c373896238663f4870d8ed5584a0680e642a18f495ef8f624b3fe09bdddcb00ac1624fa0f466692f2ed243059f976a6222dbc6400529b27df5e13c3b7f390e1db6fa07c7b8f28df8ec10cdfcea2e1db7d0c65004e252ef04e7b0ea8e405de69c70195c0c044cb408913de694f814a580095b4a04488773200a5cc07c8bc83017885c623039d055ea1c164a0f7b8096dc00ed8dfe1356007eeef701e600758bf23bc02864a6842cc740333e5f0ed4aa4f007cdc9d0780620cb3cf90d0195e8802ccb00ec644168422533986dbe1eea8928dbd7bee9999ee8ad7cd11b75e01f91e0043fe18504a5763d163e4ff3f5484f68f179e227b2f83cfd44f5d45644dc91998e848055a93f900e04649a55f08a8e539d9084da6c7d19b7a17e84dd848030a8d96a0702c2a266ab3d047f40f0076ab660361bd48f833f35f0c709fc69fa296ab17d06fc31fa39fa419a837fbe7c7bff70c162cfd74f961fa6ef1f2d473e4f41409f271fa8a5f9f209d3adf611f3ed372b1058df853f29209e24899e9aea67cc4f1b1c83e2d7601f12967ea248f0d22f20de4e42ad5dd6078355900d7d9e5a6cf725eef8e3f3f4ed3f51edb2defe23e6e7d6ae94b7fb1cf9d838b6f2761fa47e3dd34f14ccf61305b3fd44c16c3f5130db4f14ccf61365fb769b1508363f6d683e68ac5508fdd5395045390a5e1bda11d1a7b2b2a44395259b5590759bd512faa92536ef85bf74c51def4fd4b7ab409b59cd2a84fe94736097aa6e67b31f6b4feddb53602522a156a5bc74a9456d8229d83741eb01e09b60f71cf8f9784574848460a53d6e7c66cb199b1a1e3b6864727ea8b478c2e909c0c0f365bb5085ce55e1e55c15dad99a1a1471a55757819ca7c0ce2938aa964a4879374b5039375d05d6003451502d51ef40967195d9d9ba5236f30e8fd205ec7ca5aedce0697704e8a909ed62a716ac3c759e35a40d9eae969c5ad8f223333da59752ea5c97d32e4adde919d6ca6fd072deeddd2aa8475801056b69980329470bfcb47969431a16650875dc3162e0678729d80ef45bf7b8e77c1b5ede913e6660a4611e35f073862c29c350f5f1d6280e8dd910abbdc5f9bab3d5c4a45f3b861cd004ea26290c08494b29a5ad1cc29d7df551e7439cea36b4ddec39ea6fc6bdb3e7a7b36a0357bb6a6bed38db2db99043f22ecb6d4f6f97ccfc35c82d82cc3e7d82dd056d174bda5d1a86e05f736f0f4c2b651e9a84e7c9cbc3239da77926cfeb088f163a5f4891a5f369789c07c64d3c3c1ce31a55a2411669060db05c85c04f6fce59dd73c9852fc40790fb66b5926ed18388940b6b518e28e83c92233c9cc0ab62891f794965c4e59e9d5840e2c74bad122623743f3c9301048d898da7a727bec81ed006185c6c4e78314518320afc00450b1f6420a3045ff4a492f410d022c61a4a4059411b2ff067271686be7b7662e1c98fe20cdde1153d13abdc0e4739e6ad3bb9cce1061ede6ab10438ab9e773cfb78762163aeb422776089c57583f8294df0b3a68a2b9d73e9234b127936988ccf954fa9346d187a1e2861f335a594cd5a8b537a11f4b09942d7de84f552069456baa50373508577a653a973c3fd42155632a19d53be0a949e02e5cb70b7cc9519995012cd965c9a26ccc9ea887898718958dc9a6eedbd4dd64843e8d9ccc94b8b4369786b511eeb80b42bdde39d1c1edc835d36265f5e0f9befd6a4bc67a7fdf3f90b56e621a1b1649e8bd22715c224075d43259283f69828f340968935d2e7c88dca84235ec864a66a98e3c5952f884334615680e50b6b4ca625dc0a04349ec6927dee8126cc1613d9923e27480ec698e241e01679b5c4b6a4a9548a53a9a992a1de01fb743a0abce3c5956398f00b20c0ae06b06b8628d4114401f6e8156fc69a2f2fd4408b4d81d9e2396748c55ce929323cd6e9d909b325bd136652ce66b33eeaa429ad04a58f5a4b85323485e8861ca6bc74066aafd3da13a4b35872850029b3ee715fc5a91d27a594525629a33a8e69ed925366527a9d93d10fae0f5eb64ba66e0dc13ef209e640baf42e8263320ade91e1f81d7528977847bace0d37e59e972517663399aaa12cb10c4b75e93ab20868ca9ec9312dde5a42cdd6944db3257d494a6f6943b954335bfa25991e3c3129f9fc63e60f97b6d82dfb6f34ea8e130a8abb4dcfd249935ba60b5520814cde66cb8c5b38ca97344c4d16ae71050d74fe5e5cee398bf96ad9ddc2c2820b16e339801af989ef313700d29b99b7f8b6d1e25697365fae742efc40130d00756ee7eba1381043e4a20b61b016bc20c4c212627630da420a07a0c0ca0db53a8ec6c4c0a3163a5469c289349a6048c24b5c9801650e315ce8a2040c08e30b972da20883082004f004d2196e08c1041c5bc8180c2a9ce078411d373c49b1c21139ac11154417562441e1288028820d26a12f9ab4ec50c336431162aee0c18827187218fa820a1a35c470f905eb22071f7c6062a826a403061b54dce0a40553f420632627d0486ac110548870412ec941460f4852d6a821c98d052968019824232f6250410d31e270828b172f7eb8ec47547901c905221664982531724245e54c32f18d0517be9dfa0bdf0e0483130bb49f3991672727603ccdb393932edf84020232a1cdb25af2853309f4de4b7d1ea87a5e7193b50df5d677c07047d85b13768029c8b76e82756bbfd0ba97e29fb7f992dcaad55a3a649578c77245ddb26e6d5bdb379a903b0ab9a216ada7a81b47ed4ab9f5281573ad12b7ac5b96f599242e57649d33e290a44fbb457aeb32be0239a316adcf80f6572157c43be013775ab74af60b473b5e2506f3aa2055e82248f93d8084f1587e98dba4be05b8d1ffb2152918f3d439a74e9de3b82dce1f475c0982f4ce53a00553ee71e028bbe7952d807c1b3ed41d61855705d9b13a0752bfe2b5151f2e3b7d76dae18ae77914d88187236a3bbc9094b4830c518eb85911930312332b5050926a569ea0b03cbe99d4fcbe5bc3e2811d69918b185862904644592bc408e2c7efab4981a24ecdfdbeaf26070a9da55a4532b3770e926df058879360da55571ce5264b35be7d5cc934641a73ce5a7f31a3985b8e215f57b6da79877cf5ccc53e824c306026981fdb49cf7468d95c447a2d1349744054a9e327143fdd3b4115db4f223f5db50a9adfa7c1176e28d581858d2cc0908d37044384b102441114242064edeaee6e2dbe8d18e37bc777777777ce4f9d4bc5879fce8afa5925053f9da938113fea8da81ea86041152a327085051eacb05121860e5d1048889914f6e32787d561cbb773af263ec890d4850f34081149244c3065453f6a3fd9b282080ba216be4f8b14493f6a3f1705924319dfdedf37e714e304d19c73d2f9394c11844a9917fc90e3d2679ba32b5b00527145c2406b286ec3823b368d48d3ba879e7eec1826d84f7887c6e38d3b761dce744aa4dd7eb338c499449a9cda4bdbf8d52c1a8cf64f336a467547d1a1ea8565117ed9b0a774177ad0463f7d8cfdfc21c7ed1d59b414dee92063d8ef871cb73ed33c95df5e5a9c9663f425269975b697a62d2549fbd03a4c30eeb4f65e7ea2468063d8c230a3c5761f735cefa9e5530c4fdd75e785a7f9fac6ef8d3bb27870aaf36f5043b13dc8326b97b328260b823f5aa6d6b27274eca555f7985f945bd5adbdf4eb933bea7c757183c93f9d4a59571c8d0262b0f9f850d72d077e191c37c20a3ccd1cc771b23d204925ed7898f5ad2e0b36348a2b6b79e41a3f9de5d06c49a516672893b2c8a4db62538b1d0fcfd090fd7924c303b45333b5387de469a5a3d99aee8198db473f7d839b5c835b330e25274bfda4e96714eff0fc9176cdba0ae228c77194b955d09139eef8edc8709dd6666bba8caad566cba89651dd93731982485c6eb1bae4e418a19ffedce5094bce233626271e4d8020a73399d361d3e91465d73337172e7bf7ec84831c9f110e6ad8271ccaf094b8ab67271c6c38d47040b2b6c3018827146989c381488659c451b53c36b4008aa8511c64a0491e18cf1118d26db6d8e230439acd165b24d515b686cb3d7379d29252c19531a223e38908389e7ef872eb3397a71d903c6ef728576b77734d290d2b9dd6721ccf2ac49c7336cbc54adde7a44e27dbebeeee4178b236538e0eafbbbb69f79cdc4e99b982312b576dc7a52c08d652163bda558ed53f2b3787a8568a4799d6ae4c7987e3ac4bced659b969b9d592fee93a39cf75a65c322b15eaf40fe6a0c79cef20394757b2ad5c5ddaa2c1ecb27bcf4e37e8308230430bca5f22feec9c1bed779cb596c50a298b5043ca230ae257e1cdaef96a3d79caccb086637c6fea861670e0a02c8f3da3f2c0788ec084a23acba305b5d77e97e3e1b14e304c010c71545310a5a3681250e415a32b48f6da94d3942319581c8e164cb758004761bac53fda3bc294227b59a32fadb8505dc1250c2394b839cf5cc2a8c10530ea18c186288eb3cd6c6f9eb99481c3d367271b86f891b544a97896bbbbbbbb656e4080f8ee3680fc906249e160011c2c984f4c3d2069ede9a38c2bdde352c0632db5541eb10b2f9db64be665d3ca0a211b6e640b4fa3942e59cefec79a1f73bed3f96e83efb6f8ce69e7b6f30bc47752d4f8ae0626beb3e1858ee748c6d93a6403ed41431a4f6bf6227df7f5d8f2d5e46061c3467e642719de80e2f4d32f0b0a0b7eba4759e2a78b33c4f0d379dac54e3378f1d36145fc74a0e944c3d2d79698e393b3d96c469332dac10abe6590228d3b93b87455a78a6fa713cb0baa9fce6404fe6abe5b13931cc450e5dbbb004870b1861b5d68d9a10b91981d84a26c41e3020936d272b4d239426b1774f0dd2570810a1b5892a0e2c60a3e9ce1060d528af062892519ab03a209a7fad57cb766a68927537c3b6d97cef757b342f2a40ff72bc8ac1621b58b296a0906da8fd5680906a31f6bd20bb71fab969f75a9368dd5a9d67e7a95b222c162a5b2122102d2d96c55af44b5878f2c236905e469c2ca125ad4a2d10cd31d2b51256ad7386fb568be8a78fd562991887bbe0128ce16750d6ea18cf37c892191301c2dad4e89e68b978a263de2d8ad5decf4c293af3ec7b48bc757a7b3f95a415665acf00329b73a5057a26e55af4dfbead5a85d335eab8b33549f017b1271d9447229031f65d3286ba3b4d5f8289f78ec70f970d9a3b4228d747c9448afbe319830427c6431a18f3c06f4510abd741f2594191fb9a902f111f653babc2f6de27c892d97f3368784a3cd201c6f0fbf0947964d387a4d388ae1c8b3231c61932af56dbe2ad16c4ddfe134e16869aeeb84369970b45d385e2e1c5942c2d1c37014c170e4f170844d6a2be2d3e96dbe8a8441c29175812815f11fe1c8d2c073c2f13a4e386d1b5cab01eb160979b66e3fdd479649a963104e5a7bea3dc29145fd261c9dba4d388ad46bc291873a8f7084fd386f3bc2d1d2844a371c59d35ba008ce78b14d284f5d261c614223cf18518c8779eaaa4a94aa443624eac29105a3b69f4e0494b7d9a2b3a9d3352e704d450961d878879f5d2584e185457ee71ac7c1c40e462821c30d60bcc826bf604d3516e74aae56b4c5d45d2de1c17d42a6f3789ea4d96c5684ac84304ec02dfec9c43fbd57d3ab061abca41cbd4053dcf17e09612cc122fb94108613cc01ffa521f05227bd84b1c49219eaf6298784d7eecd20c09b097aa8eb09b01304ca94524a5b5a99e9ec314f2ee4e9d1fb5ecd7003a6830d29a1b448e4873b72348e46c7b773503828ddeaa1a7c1684a9fce983bc290b48b9d5c80fa76a0179210a6c31d391a8d630c73a4bb5ae23df34e055334dc9273a664a8cf4f328701cda79ea5b473051271ac470efc944f6b58674336cf9339ab208fada5b4560ea49ded3e09526b6d4a824841aa2395e77ddf8a995982942733b304d967d867d8bd994f829786e7e4e979343bc41a25769b55d0cd8dbce15153632399886a8d31bc196f86ca9a642d9e70b8d23d29657fedcd49295d055df76aadaba019f738ae53492965ea4b7deea93e99b30af27815b472ef0b026fb82b1999947b333333771574efcc95595d1a9a7befbdf2bd1428dfeb40f99e07caf72c28dfbba07c4fe69b596dc04bc1531ddf845dbecc4a04d673d3b3cfa3f96a28a5f912e2ec937d12cda2f9029d7b8e29cf3ea5b0ab6f43b30ed3af399bb3293469f3e59eb3b7adfb4bbb661a4c434d225ba9f3062f8425e52fb8ec47cd710ee27ddd3703cab7df0cc81c97e2b7b9093a52a5f240b62647c3ada9a2ded404452ce601086280015b1a5e15087e717d74406977a7522e59902f9611989ef2ea408a5854660c3f398e9fbcc64f36e353e8388eabd2bb18c3051501f22be726f4ab278a85a6f3e43193a3d3bfe9f748cb4f4ba9b5264c13240064c723e52aa803de9975f4e0a77354fc984a8527d8ac71533eb2eda74400eff0f0cec7ee9ae18e6c9b73958094ab5c054a2a9eae20f378250268011ae284385d58423b145794bec97cea1d904d5f41d9f4d4674bba5c69f1dae9e3b0704739a58adbb927bf1a35eec87a8e712e9de5120810168b4e6f9a02174a33bc93a3dcf2d2050f32142f9d6513ef7c71473945690a0e3bff24b252245d5298992b90b22cd6bd4ab3d54a526e792999146935f84ae38eb0974ef305fb40312ac031e935582af787970dc4052fa5523fe11d295df2fc240b068d72ba12e68d3c3b5d41819319a7aa902f29e980628d71bba04350225a348f381607738c3aeb89cb44188ef326c3d4bb66a04038d550a9dc078eb1209dfc205f9308aac3d720690c1e78108bcde66d36cedb10bcd3de93b6c65585923667f247861a19aa729d074452078e51a7c06c4924a424423e31995466b85b3826fba88fe6d11117a655708c7a3b758174cd30c6b85e502de6bccdd9c48277daa78f73d63e87f8764642124d209d7caa61d3e64b9cad76d6e570bc14e018131c6b4276d1c51863b8c0053f3214474581f3c63b7dc43bed524ade60a95b32731f716c7efb16de69f7e6adce1b53226a34671469dee810b5428be811ad724e5abbe614ea39e513c7e606641d4e57a67c1701c3b8d27b65c20e0e977d07872b7d9500955b9f340bdb051de39b4251225a345bb7f9a243f08c835bed4fb09840e2dbc378f2edc4824089666b8b4dd465a751377380d2f28ef520c62dafb7704c8aa258857cd9d97281744936a4d8ce1a238bef37def851deb0c022eaba66b852cee4ec1663d6963b02e0e5ad83d88dcefbe215cc664d3443eaa72937272188f8b187da9ba5931050bee56c7291673b5bbcc31e95eac2b957c205ea2baa2b296f96e0a5dcf3156474e52a57f90a32ea6c53a0c8aa3215c879389af0b7650dca7721ae8fb0ba346bd37ca99cf35aab5e6cf385453ae7558963501cbb796e62b132ceab05dcd92a61e532a10a2a5f852578fe852aa46c8b1cd06c715c7fdc079cf3ea009c33e75e0a14c262bba65bdcad1c9690d522c7d525dee160cfd52518927659e71c4849579738c6cf711c076b91f334eead4f5c944acaed9e9d82d8d225881f2c0cb73e3b05c1a4061514bc605b020625420c1561b4f4c3d151105468576c414489124452104ea05c19329ae305a3a81e6ab400cc161d1177c7331730513cc1054c12528031ea7cb8ab672e6072e8a146f7ec70054e760f2ce5e4f913876e907a5c738a06033955950c97ecb5a6267310034d0e6c529f2795744a2a29d7ab12c3a3935a2b25183e50ca75573baea31da574d290da5a194cd341e7ec593fd936dc6aafdea1cee4a96f44352164d9b8e317ebe18618ac68c1ad4989159c10e2045778684389282e5ca1a2ca9d615a108061228b142ea670c30cd9c8d3b2ad81444443125120c9a833992f6aa75321a6902215c494499f462bf86aa24ce0313347c32d91b572dc9492f3c9f1ea00aa1e2e916c59259a2f1e6dfe3d0ec6d44bd0e6fb4e2c15b416a4b21a5ade9134b4aa90676bcab8e6bcd464713fd040136ce14ad92465825809c7fae79d0e34ed741b2dae75e9365fae741da22b67eaf8f9ec40ed294b737b82fc629fac4b33bdb854f69c32573cefd5025ae6b90a94b314a8c20756200542e8c1c5049a338e87540a2ecdb39391146b839391134e0988353a2c8060c1b5f6bb355c445951399aa982864f872499256cf074b8ad801862065595a38f071952569e3c9aed61a60202075ab743510a88166ce07838b269dc5095ba1fbed440955819e2782c172544514d485152c556040d4a76b0fd50654809955a0f5b0f13743c2dd7dd759dc70417328cceb8f7990b195356400614a5316e3d6cde9c73cec9712e274542e98485f408a5b48636d353a84ac3492533f39c734e50ceb9011a27d99356aeb32995b72395b2dec71213c601fc922c2f486a729674300045168b2539c62c16cb729572b5e32aed581468e9e3f1baac940428d0aeceef91d7c161f55c0d847c5b2725fc92338eabd4b94abb4a674b4b4b2b1e32337276c26cb5d3b05cce582c564f168b3579b058ac1b38bc310523cfa16ca794d2eef64e811bf2324c01a79bd4a73d52f7ba1b47fa946008d2670ef72934e9f9a540bf497dfb1e9dc3fb5acc69c7f1163548a31dfcd6cb265574aed3ebc6595741ed0c8eb4bb676a154453df9c93520a9b1ffdba950d9adee0d85f8363fd76ef7e0d8e9caa9b2a494929a5947295e3bc725cc7d916f9c894e29c737a900fb4b8d23b184fc74472c09f1023725a64ff408bdb1bb871a5f39c94ce1f57f8192269917d25474faeb32aef93a157a552a928e77529c9a24da5c2f1039d55a9c0a4869fcecadd93a1f12c47ebb74a7568a83c4ee5ad40f95dea6dcaf3bed5a74ae5b058f672dc0e8ed62ea5f2d0b8415ce8438c2bdd5a9756655daa38975c2a64ab84abe180ce11fc0c61fe746fc78e5510c763d20904c4834e24ba674faeb32aafce6cf0f5f38ed4a7a98e997e9ececa5de52213e9c33c4760488094f088e25c75ea047f95ca4bd91cbb62b19a04dd2a840669973a92f99ac9d940fa4ce7efac4a9c016540200dcef05495c554ca69751653de7929a7e12882b72c5b4615a642262d56da4df3d57fca83c72a88035a52d262af94b848dac575920c92a5accb738bac786af820851a3cb3d9ac851fa2c8481fb2781f06f33fd67cdde2eb1de354748545c4a5e8824b3abfc1153ffdf210f5b387a49f3d8cd9218e96dd2a68bb9cbd82dcc1947b9f9d76607ae9d2c5cbf2c1ab4e57225880ebf8d0c726f5bb5db6a4e2b1ced823eaada72aafe812feeb2b8f3d1fbd53d639b672f60dfac57146ddb240f08ee57c600eac733bfb136f7d6cd9a6b74c70cb7eee813466cab20234642a9060660575cc0b66deba7d01f30d1c85532e7cc1760b961b178d323ecfce96f5e96fc5bc0599ee68dfbe75eb06fbf05b0b470d6b759d246e17725ec314f102d1ccba7449c4a5682663590bb38e3a64a98fc3bc751b10a704ee832ab21bb7be82ac03714ab071ceb950059c1a767e13569b500576c30b3a8e642a90404608d51649322c2a5f41e6cd8fe7ab55f0d9c26549a602093e346458689c041d1541c8b0a83ea8221b5942c6dcb79e2a4a19b54bc6b9653d055fb6786bbbbc4dcd88e6b54f162aeaed0d081eb922462e09ce89b7be43cb1dadd2a5b3ab55520501b56b8dcbc3c709456fc832b9ba82b3c339b72e64ccd562c5b44bc6addb28abd4aef0addb13f08b2b9a2deb52fc114eb51491bdcd54d2dbd451d1dbd4d07b36357b6b9fde32d45b1aef58e78ae68b7bc22deb473c27e5adef0811d0322bf355cb1d2bd45b9b83cd816392885fb0a27bc41496f4d6ef54f2289440daea4737a173bbb45a00e75669b6ecbc793f8eb8fdab760fa4ddd12a19c0f30d50dfe1293fd2a2f50637b0849fa745eb21782118c5954ec3a8b73ea1783ecfeefdcc550278b65a7395801c9f0f75a973394b68ed2a2bd75aebcc9101ea2b39615d22ce24495e409c7352c02f2061cf8f1ea8b188524e0f54912b7e15a402d362f74085350ca1716ce6db716a75be3c9b746bbda1587c755ae318f5ea3a5fed7c01f1ea77be82fcf0ea3e84e61579b3cff1f1fb21b4f9fa111619422b3284c2888a28cd9711a87b7f3cbd48247d7f4246a03cc9ab03d070c79ba69b9a8f1bc76e3278f2ed19ac96fcf81afe788fd6ae9d6ff7a0f42bc7bdd9951ce75509e20ef7365f39fec4d79c1cffe12cf403f472c08f365b35f46e2dfad072475518d5d3dffc294cbbfc4b8b62da5543b7b578c40db224aaa0bee78b93b17fec017d40df33c71d69929e7867da7020f8495470fd29039a37a65bc18f548c21be897828f792e73f9c2fb20fa756ab0f362ee73edcb8952669cca541a2396ad7749aa490a349928902f06e4bee8d772aaf44a51ea86eb55f1f6c5ccf7db87155292b65eac6a95bed375e6ebe7838b5f0a609881036145605a78311f9708f769432c1a007aac8d2574469ae96885f1dc7a6f4e571c2343d0e98a51a10a776e5725efd87371716db6d9ce72bc775d3d462a5fe03cc096b5a6c362ecb7db8714723505f71bcfec871db0d979ba61ed3c70cefadb101c7f95d9882fcd1bb598a23716eb39c2938b5b0068e35cd178c882689c8d01d87c088be1d66054634644abb461452b42150860c8ddead5697fcf26eeccdc12faf28c6407dd3e4b90dead6ee63dad53d81f1a85a8b62bcb4d86196f0571f4128a0956f50c84790f6059c6213e23c8144e00c1cf26e351c6b8edd7c6d7ab71a9c1acb47ef46abdf38adfe23c76d55882a8b89db03474c8b5dab210ba756dd71c071be8f300589410fd48823e6db3befd6ae1a2fb676d1b88b87b7e33cb5ab265cc20fa65d50eda2f1769c30ede2111a0913d5ae1d210e4d6804ca4854e38869d7c5a9e18cf191e7c325fc2b1f738472683950bec33bf41de2ac42236272a67c8f98b007ca5385630f948e27b98c0f36eee86e5c7ad3d4adf6be69a249ba695aad085044c90854bbc6224adf6e04ea8d44d16431025544895be47aa086d0e20871bef4cb6db3d53860bedd471a5786a337e5a7fb50e3d670f46843681c0379a7076a723d50df411fdfa3179fbd0339ae378a1e084b24131902911f4088100942848848c44551048988a1105127031c5114451f434451148910c969c96c40d6f13821ecbc7d198e2378ea46a08c44b58babfd58e346c4340742b6d1081418ef667b2366b0cb8b838d8461973786c5761a7a372877bc69aa7d7b919b26907744f87ed40115a65f3add8289f9f611564134599cdcd1278d12013430e24effe1409cfae8dd727c86238fdbe6b4d526db1f2dfd00e7abd6aced29071447e8c0030300b97147ef46fbe94062eee8365bbba83fada47fb0128103716a38359c5abb3819baa8019e18ca6d0d8015019ac8ff885a9c374d2d22f1eca404f5f56992da35de34d1247d3b8d52bbc68fe89594bebfce089aa49b261c9b37145b4dc7a9cd970e8e4d0649007e9200bd6ce6d2084049d00e1078d42c6112c20044188100363705e8c15a61f0e5fc00c223e3bcd3ce79378ef36efd0a4011137d46616cdfde6d09313f7e454749dfce55db97767558be554b0a88426b578d3203dfb89200aaa7ae8028b3283350fc0a8ef2a908aaa7449e168556c15aa340793ae78c0225ca942843d2a308458145f9682934f3665876d0a495ebb06049a554df4a4666862fcd8e8f87d8b36bbee661f3754d8d8d8db4e1513363736373737353c363c7cd0dcdbdb9b999b99159dddcdc7c461e7b17274753ba3819fa274f4f6ccf5d9e34757982825f3d77798244019a7dbc48f7a95de3b5c2f7cb45ea17379445a95f4274888b6fbf4b4cfd12929925218753bb6aad766ded62a72496befd82b17cadb4cba85da34ae916b5ababf2edf7a85d1dd2b7f37ccd4041cd40cd40d131aa94ea139512c7d8bbe7237e944f78a77a07a6206bd2cfda69124ca5a4aaa994987a5429a99c545e5830f472f58175484ab1c1362e7f77e158937cb431a7cf94acb476d10a65a85dde142bb588d6292dca0a4555692d8c40b3ab491b00810708f2a98f95f64a1cb379e92a1ac77815c2fcf103444fe98c77643855432ae8e2444c172750cf5d9cd89edd3e777162c573cf5d9c34bd2480c7591f6d50eab4eb3aa9722e65bf7e798aaa4e2d7a21c7d4620a6c5f4156fd4e6f2f617a872a60a1ae42fb2ce15361fa175ebe1c5ae99686e3f71fb7d42227c71dc55fe29c278fc831ee39aece9ee35c268edb50965b9a2dce71700e303d012c9b21cfd6f42b33e46ab3c5491ff99c7ce6668b736bb3b6dafa95539f6a987ae3848ca87150661219b6e7388ee3869e73dbd5cb39d7e5f0d479582a42c73967cdd7e4a22c1c4c38a958548aa7dc534aa9c400cb98cb85725de71cd7759c4f9f1ebf3af7b0ebbace612eaa244b9972550a044885380890322f88c3e15c3e174aa32c3c3017797cb664eb2629114f5880e2ad03b5edb8ae03a773e088c2a350f35586ec4115301753291a094aab454de658226e109ae2a7bbae60b9e08e36057a53c41d91bc64630b14272fb9fc0c470a64873b5a7be70b0bbb6c9ab4b40e716c4a25aa4a554bbb3c975e97daf5b9f4ca54cb6065b9d54a5729ec8344722045edf2d2eb162fbd7ef132fc326e1d4240955134a46cd933a83219010918d8171e01f04e3b058ae1727cbb1d68b258e057d9799213038593189c6dd511b145194534c051c5172a3c4852fae189c8a90d27b87041860b1b329853f4c0c4048682a1b4b4832915452d8b3a90905c08c34516968b2ebe33e804c38a55470493e08517b72b6a6624e144c654544b32b261718615d9c8f36d83125e48b1e1080d29b215a84ca1a38d3027b0994007d9c8a3a4c921a4a112d83004d214a41e9c9090be8b583eb2eeb313d2ec53cf4e45c0f14f5fd3c7d3698b9f5c627f2e59f14e4797dc25f327c771cc71542533fde39d06f2e4f6eb34922b31fbecbd89437af9b1868e6fa75d04102c21225420dadb3bcc88469edc1106932f1f432648a0e8db67444c01fb6a5c58c0c38f5c234269e427869222cf06a2943a60d043dd9adab1fe6bcfa15b5d86287c3f9d82f4756c0d9eaca9e12693529ff6520a345bde45ba9c4de94664b8302623f4ab88db7e8408d41de52c47882571a8d3a7614d7bb07400e926480792ce04470496523aa5945740bc233d0842c7ca1de56ce90026003151a3aa916ae266674e3ce9288878f8582cd6111ecf6159254c4660b9489f9d8600038833664c501162020b1e7208e1054d5db4b810454d8c265a40a3a0d55033a33ad611181229bff86a72e6b3d3105d7c583c7ea69edc52451674522a93fa254651228e92609264d3104d3fea48dbcb465935f081cb426ad25e8d386a881fa5d0d147492b2b34b1a5f6c20f6fe8c055c4811486972e63c6b041d60c70c20b31509c1145136264cd2f58811b4f5cd0a20e3590640d85d251bb52b20bf91a806c75acbe5adc6a19f3000431c0e0479954c310425126d524c79c74eef99049a91038c62c9578a7bb6e4e0bcc1087f35982f4e91d903f65d3cf1d605cbef325bd5d0c4fda38c6b4d5d79ef2ee880be9a2e82cd69115c38c708d9792c62e59d24e982f29876c4997cd824d85360c895ed2c1592080775c33dc13641c1cab2e9b8a74495a4fa7520ec9420c61d7f0f20466676797b4763515294a97341c9b0709e5280ede911df05cd999e171a52fa8d44d9476412c151509008020006314000030100c8784428148241c8d6479f80114800a779a4e7e609d0ac42488511432c61843083000180020002040333302008b518c381fb575648b30703b5ee744a59546db74d9d1680bf733f87f1e3601945cdb4176ee8fc3c1864378a8caab7e439351cd30e563e42dc5d7bc721c30c2e5d886c7497f712f49edd65e27620c715b961c7804cc881349cabc486d51bdaf249f885d7455360a1a15d24fc665a2a620cae0dcbad7ff05b14376fc9305e27f8c20536ab8f5f0763351106c2bef84155da180b3275d54432032003c97dc740085d3442b41d4fa79d7741c8ac104efca4f3f75288badf45322d3c37166d91e0eb0ed6099814a2d7f29b181ce2f0deb1e28bf3fb4fbfcbea345497ef50cc43ab4629ec02d9a1034100f8d23258b796aef7b8db7c49364ef9d23385ae0eaeaabb8330da8650ecb996038b202c2b09c80dfa2f4daecb695bc483b1f9a7e70bb00ffe87ea278cbf085ce807fca3bfbe28d9eeda4ba126029a659d9a83a4a10a6ca33062e2ea31132cf1f420659498932488a3ae3c7680ce447139240437fa8b0952025524b8df2a28565eb3d2fd6a79d4c9fe0d06211796624b54b3e27eb67cb1acee8d247ed87404919d320a9b37666aa0d5411a7d52c408e6a1721314a1d5b7e9c7c120356f48c2dd307547f13b80c65c73428eaa1b2fbc36d70707c803fe4c1471bd9bcd6d46327b314bc34d5012c7af524d755789b82c40ebe2c43cf65a699a82be7491b3284bb190e30205dd890b39631aa5c64245648fea1070d753de74d3e6c60c072b71e813259dff4676b05a50db9d510bffccead67337ffa3f973994edcf03497af8f10fa36147441c313f2fdd9dd0189c5be3874bd9fc4f8058ff468c0424d33c681622bbf9a624ffdd28526e7a97150178087f2e6a3ae17e2fec2c13752e0e18cd903ff0d8b674fc33b51eb90e4820e3b12299ca22428238187bf7f018d929b635c7168d76be516da95d045b94a7a0fbd8bb65f1011a318e8a42561960226dd76a307476cab967ea18d8b832f0f3eb0bf55d2d28680f88c5c8e66cf20ac78b10f042cff1abd4add7cc7de0f80ec48eceb222c4f68aea21b9043303400a421fdf27a6993728edff5e5a2d0ddc144350787878f49817ccc8cb089f60b34a9f75e82781d69b3088033578f09ac3b0e9a86ee99d2bf5d312591549afbdb78a6ddabdea1fc3673cb1dcedc753896b92b7e31c2a07f04c4ad06754af0d4997173e57bbd1884cb64849bc892b91dad602e3d8e69fa630de71222e9095bd8139eccc84edb0691ba2a8598f9a5701b5ddfc0164c1e869a33a6d62edb4cfeb4f5bdea05f1c8343bb95381fb4171dccc61134a32a5a6d3378d0cc7c8f520815ddf6b8ef9580c90f11eb0c0d41ec0af7f22564d55dc88a7841ea70202ee44ab9f36ecc3a71fc98e1ba4e7b36353a04cd03baa13c74edc977ee33b6545ffa903112be92018d3f8f6a84bc59cc238241f297d1600deff980f65902ff87b23f128240e20f09338918c82a0d138136443d12472ea1c06b831015f7ab0830bb082948709d9c972acdba99888b73546fc48c3b8d7b4c7be3d0520efdc74fd5512076777e40010512c797a362f2772612a077e7b7a0b21873c59c32ffcb09a6ab5df8e3751889178dc47b6aefb98a20023e861f4cc52095797a67104310a2ead57bbac1f66c217620a8b0f924ae8f3b4eb2a8b798015e67a5bd0bf020427638113eaafb85e64805e8146765503f12ef0813714ed1feac8c97cc4a1602c41e8c9a296d8b32bb5ab738302dd1c6d96a3999701c76b8e508f042d0be3206a00283e924d3bcf29d7518811961aadf2143d400478159783fa6d7ecc721aa341b4ddebbcc91d02d98b3d68085f7e26d1a316053ad4a722d51d02ab360df4eff4905a38aedf6645bb427efa48a3afb8d93640c59967d8c103d9ba4733087c83287e1fabceaa0a1813f3feff3fb11042dc2aa1978b3e3dc6f6827fa1c1814b9a9eff829f9eeaad94c471c58427130b39d47e50c93e5f30edb68fa9c64058ad1076c079dcb9dc3568f946c3a06ffa50cc7942e394f91b316106f9b5b1fd89668a4312897b96d3016aa906fffcc68d37deaa321a2d090e5b4913b924b0b1d2b87c2c7380f299d4ea7b1efd85398dfad9a5e68e8daea39a22cf1838742fa55dccdca22d613d8f07b2e11e9a16cab5089da8c8a6650f33e3df1316659350cd836464a89d4acf6f4a090302ae1bcfe0a07b1cd75241d77e0e0ba29bc05987d0b4f7b1bc38f857722e1151d5cc601f99a9b98b976e8cbf37e88a7ba933d14eff275faea39984cedb248691f10a30cc08086435f306fb013a07902514a48cd42e2cc4a8f5ea4c9a6fc26a224500c0ff4a7aa0687659b3121e0d52ad403cc7e07d44f4a1c9bd3967d64da8d49d0d48c814ceb42c9ee902ba614e4c7dacad87fbc033388aea1ba93e81e543adfd55689d8493db581b6e42c7fcab4af7d512e940dd74bbf31f49ccfe89bb430f39c918867be391871f7c0d5e8198cdd1156207c40038f0d918547ff130820a2d30df0807cc193b40a9b5301bb6e3dd01a66c0532e383c2f108092e113667414f1c861b0fe490c7f8c1b4d888961dadd61c961190974e65bdc609071d042741045b4d5a40fd9fa3cb3ffca31f77822b4cef9d748fcf6e39f01c7c44069d14d7d29140d3811dba7250c7ecbfdb1e40c96849867093412c35120e6f706e2551b92ade4efb6d7b56558fbca57aebe7954542178793951d8634222c39684cb75a765caf4f7bf358a4ae676177565705b23c1e3dbf975ab208dbaaaee2827d79af1803572e3f095e52a701f82eca6a8d2ebf9a15c641e353280b217bcb2e6a182300e8d61e276c5a984f25fac986652576ca6d1b76d0b47f525737474baa3bad06fd40dd0db8b4190c76a7eeaf9d9012d299e35923d8635f57ffe46513df484b70797b44e04b191908432b4bc3ae6b1a9f670350965ba230a85080b5ccc8132d0c2205cd1c719238d9c724fdffbd9993883b2a98257d2f6057ff44fecb1f5184159fd28276f6365c0ede7bcfecf14f7f21d7d9b669f6a3ed3d02115a234e847cfbf5668f77dbf061df4d31788e6cc7855acd4218ecbdc3ea7451c27aa8450c6311041f4ee8a9996aa600d5fc9b268273953458fd24a78d63d845bd5b4fed17663aea245554a7cf2b70f0f5009e561ffda93e8356d4337e2fadfc74ca1733c587f8052a77b88c1879a915a8ac8ed394aa8337c9c5499f622906f7a243eead027c01f3397d436c1f7e09fc84419fa04f803db49aae79db8722a2a1e8044321bcc86441d24a6b135dc271229e37a2ce57e823ed331d9180530765c547e0bb005be0a1d524410eb3b5201ff638fdf74ae59f458ebfe0cc6032148294befef8310e53e2f65508ae2ecad1ad9aa2efcd0acd9b94065c704408847a6d9d7968c94703b56d01a8d80b97404cc5b01872032af06846e6e1dc00bc59c45060e2f3a62826ddb64edd1046ed46acd91a8d527a6541e8b04d00ed315da39e9fdebc4c3b721190168b0dfd95f669a78b9e6d863a4d5311d2c8944399fd968605f66f670a732c471309e0d57c697818e7b499b086257a2b736859f8a170a9540d632ab5bfe4fb2e081667d8213bafc2048decf45ff073d157b0905179b700d7ba80d47cc91e938b4ecc1b44c1f8473cd5057e6be8bc401ecd28f50cc3037cbf02c697a82b9da0a3a41b9c8afcd657b88863499dab8e032cfca1b687d1cbe31d3693bb669a90920f0f8a5280f34e25a38141b493e9821e421406a531a45126ce79a8721f1d64b348d1843e3e44ebe25bdaa3e7674aed49d9b6edb77cd3bd233fff2768a878770f1685e406264d865e4183db5d6f356485df6c6a4b8e67e91653dc0d614f76b6a5cd7eab0b3cf32ae6629f406e40ba179a4e0610845becca99385e1b02c55ac1ee93edd17a4a2eec2ee89b0f2c89e6c30191e82ae6a34edc5b82029902688bb6eac2743111d6ac4d9989148ac8160709c13b0deffea8146094ccdac916f2982b3cb46e8b6f23402f8924b69287e96a1ff62a4bf8ed959413130f5fc82d61966372b1218cd2ff048fec3074cab143bfa63d4c7c39e624979c21a3fe029fd5401f6cdee3bc08c0791ccbc0eb555cab49921f68d635efbc208a50a2588a4e58d553671f80f49bdeda49c006f34f06f5cd7aca013e5dd9a65daa84bdf6ae631c1ca5f212f8dedd6cf5a55ae5043ff57f613d1de01515331aa3e4a120e4efcfc13eb2cc4aef5daa5d8145b22d257c204351aa6deacc6fa743fd7bac597320f84238371cc46b3394c405fafaa13d9d6998d9fbf143c24406a8e7ba6ab8e4791f8b3188951fc4428bae2bbddf31ff7845bbd9cf0fa387e8e5f2e84482ce1dd105315571e1957a0aa2f971d064939053d8521c7cc99034006052c4b1b612ce330b6d6b5a794bd367fe147575403eaaed52dc3043deadba8bb9e3050faa93297f1d7194f65d6e1e70e03f7276e6e236b232743fff06670aa4cd42384f0830160e56b14d08583f09e8cc4a3b3bce508c005c0729809246becf504c45edd9d8ffc631b8ab76fcc2430b7c582661fd3431bf8fa4aeff2088d8c781da06acd79683418012813b873b8f84af120fae40da5ce65de42c7bf55750feb9062c119a0503cebe79273be5d027bce0f774099343d200b31de35b3dfa732802d91dbca4710747911288003f4db093e0956c556633b32eb16c5d4fe55a8551cd80a2e3af64a72a17394b2a05f61e02be9a5e1b2a29e303dbcd3b36a550674c1aceb18a193257a610235a547f292e13510491029855f343d79713cd3f34e756ce49984860fdff86bf8d47082da31cd30bee9442482ee689ff1ec39c7fa0adc12a5a3a21454a994825a4aa520c5d2dae3a5e2e6fe90e1d2b39168cc9a53e042962304f903af9515678058985f91baa35198429543693495a53eec5bbb102cd3647b1e2da1cf13ca4de52b6392dad2634c59a616b204f8fe4a7198e01cd4ea6b7eeb32af60e1905556e9aed64680f94dcd62f876b721e5beef7544c8cc6ca4223c6f8239ff319108110a2e3e37adcdea025f7f18292d553a62caa96fbd132e0981c7213b630288528fb316167d1dfff83c3d46aa14029458cbaf8dc5873a159fdc8e5af95e358af66b376689549b7c1363bc3357eecced98bb3cf6214bcc610379ec7850728a640e898348060906c4086623b6d066e09d27d78680d366d0b98e10a2a3a97ab9de36c9b8b6de5f409ef0820fe4b5cd117c915fffdced54912e87eba972c58ac39ed79568854cc93b40200e1ec204b9fb46fe2451d904ac03155ece641d0f94eb99f93700ced0c12e5d20e349e3136c2e6e7f00e2f2996d28eca52dbb2b9308a3b483ee7b0b26a744083de9896c64460dd2feaca3c3af0c620409730d2727412113724036c7629493b04b8987d1208efad90669879a6161a5e2e09be0b8e3664f4ca899679ea8e814f7e335db756eff0ec5813fa3971a83062f2567918afbf43d2b19755dc1d02832649a84678ffd9eb6b1433a77b1d62fd0fa55b360d64c9f55aa990021468884723b55e66b39f83e6cb7575ca88e41108addfbc1f55f5daae97d3ed267d7649d61e3a75d152c18ad152781a39a1acaaf7d02bda7b950f7bf2856650fd9ff5e180f5552496984650ace359010c982a163bfed4a8914badada2efe7d7cdf652dfcca1c1e1d41d35a96df65b3afa80ba3877d0bf4a1375117ca9220e63ee003c8ada11d06e823d0a34b089a6c64b5a7e609502b2af0c05b97597d2b6354c3eb0d26b24253f20963269ce41d5ebde401ff2898520158bf403228881dc1bb54d5e8f95e7b2332486b9a137a8e3d2d83a80217a1c495ec36718aa68ab8a657b928e254f7937aa6ffe95452ca59e4d40ded5023bb19c1709f804fd2a0305580faa4aafae769e2d090156bbfcbec546a1b306b3739d5f175ce3eaa13deb1c8620a6c27d2858f7122e778ab6ea01ed4438a2b22090ec64c53f769539c98fa5d11411aaee7e18f3f1829e722534c16410c6fb7ae74e7de1b1e58422c0780f803446b150570e4eb107ff8320194523ada88eca58df744a0b9780ab8c24582cfca2479ad06118de95a0d6dfbb92a9fadc649dce95df7cd0f13b097f9db0267160efe0eb5e6cc5a38dc6ccea865549b3969a3f6ad987243fe14f47363d09be341bad273ec32f2453128642d8561a5f958c4b9a9d32c1e4c6825395127f7eb209e593669765c6e335e0da1503b9c8114cead60dd90fa0a652539dbf8ee8d5aacd24b0e77c6c5e9daef4eab470f954665576fad550c0e6b560658719f80d5ecb462dcbc2a92ca68be4df11324187eafc09d35b2d10ece461e613482b8f7064ec22de224d5bc1933741f6b76bfac3bd9b3c27cf7f325a4d1a4e8e3118edc34724a8eb0420505ed289fc5b4890791b42d50e4cfc39323c8f1d736271e2eafe555c63f538ec4995fd59c6cb1ebb5f4ab9f09ae0fd0ecd7ade199d0cae90190428dddda1bbf62dfbdb41d63cfcc5916d98eb18fc59ce571395b69f76fc42859bb5c020ad89cdcac7acb3b9f05a9fa72564f26d500d8db411cef1a91c5f4db81b8f2469ef4c177a55cdc25b912d5b54bab8755d59c2b11cc5d82791a022c6503cfa493821e41cd4c234f6c25609ed8ece51cd9bdbcf89ac5b14763a971299654f1bc773ab05363cadc5a33b8050f17535988456f87e40b5e23b39dedf3c7338a1e803830fb00a59a992a1dbfebfc77bf6cd07eb1472bfd0b3ba59839cdaac31030ffb254c3ac9b2190cd841259c335a3a2d7e1a0475d37f51feb634cf783d8d3be463c6e83d6b564438227959c1740bcb80ecabd6a4c56d4fc2f3be7be16d4889a9792f8793e7f6e758385a253b1a04da51204fc7dc22feb5853de589cc6c76345218418ba6f66900f173facc88673e2ff196e8bbec1269c1e216e5ee25a64c9ecb8588bd6a7f8b7b1d8ae17f33ed2f9d92379517cbd523a7c8d23d87a689f7543bd6f467eb0435071a4c4e33a48520cd82da8aa1a3d7f837982bc4a5479bacf90980b75d1b88cf5d0c4f4956264c9869f2b7d0d3c35f04c561dcea846f56dae809a5c82185fbcdb33c40204a222613e7e59bccc1b992a73e7e327d524c00f43824fe704bb9e99ada040b00ec1b5f30d0ae1cf5d5a75349ecd79ee02c6425045dcad1ec999470422152b8b9d99cde31300e7514172ab45752b2a81ef0e16259ea7cd56282e11dc7e5487c9f14d37c4c776a00fd0097afcaf7af67bb184e6f18dc9a2ed25541ebfee4d79a4e2d7252dafe153cd9754637ccda7e565c7c30fd41bf4847bb43ccc858a9a98c0f78f4fdbaa9c5adc4700217c7465119c039b85f1185f58b434d072667c13a63843b8d2d9aa20044dba5d7cfd6f2e0fe5f51c7c8830763333fc6673e069b38d55a45b62d5162e2a1f04ad1012759ff3b0d8067d4f0feee6ac478171f9addc89995902aea1105b26f8cde8dfa1d1ac8074e01c5c9a44b1efc89144a005b0b2751473b75584202b6ee1ec15dcfd1664fbfed5ca77e2373200811fe9b04361f8931bbd1d8627a6f69f7ef92aea74d6642c8cf6c9b25aaca935aaff6ef55a26d849f6cffed046224cfae279cdc9cb7f9e350a30e65160c1ec58f720e6b412e6521533bca98f25b9884c038705879d274d3a6adbdffe8f244764c356b5650a2afa37257ef448c686568ed15a1d69c726a95894eb7a3369df32176102d06f3c419ac6635e7becddcf0f98c6b614483cd505ecdd225907a781374469b0a8b463510f5226ae5538de21fa2e09874a22084509f6994bd920dc51d4015d903f37c1663cee521c021204741f09b7ccc41c3225100465f7590a73c9d0a53ec527b366097c1afa20c511fbc99189b5d8f95eb65fc7a93658a098a5d984b3f5a460437219d65632b1d59aea4968945c0a52ceec277fb7f96398dc700efd9adad510f48d5434011308fd39fab81bae86130c874b56b09f95a98f65accc344441e9b06db7782f5658d0e40fe9bafbdee7d7537dca463734fd2c89e91d59f33b69ac4248450882562b9a21dece4d4be001c12e6b981e1cccd36d23d1023d9c090c65d9557c1d3d4ca618ee390caae0c6adfa737dd02691b1654369895bb13719c10a473ed2144b1ef8094e0b7e012a895754246e61d48721e38035e38ffaf33d2faab470d961c2a8469a89817d2417e7cedf6d37f32f078fb89c4f02bdf621952cef3a0a160ba8579d8cb6d48dd6f703411ad0f398141c5578f1f6e31b51a37486b9040357aa69366a2c0401d527e4e3a704d825129ffa7dc1e5ed35d7cd4965d79672605202da169eb538279185a42b7e77c322fbd558abf5a5e15af4dc602ce605063165643d1af191c97d5fd1cb55c8c0c71f34030d92df76c0a1f065388396a9628675ab8671e6aa7af8f9079cd5d34b5bca18bd514ceba8304c31112ca021da5a74a2d8a33815f54c6b16960a27bb288cbce20072be0b2aa1caf32d3c9ba139734baf1d8a16b89399af1f1bc27ade37581d19dda85e4d1d03c144a35420e6adf0fe0a524d8ae74b65b3e9818c3be37d780e11e78c11bffb93ed29bd56de3f22eb2d916ce39c54a5d1c15a2d0eb18c36966248a559dea227a5d13530b836a887729d3ed77628203303562088a0f38f08b103cdf5b32f6de0dd188f3455e2ccd02fd446199e46edbadf56bdb94c22f052cdafc8426b406afc09832f4b0da9990adc5249ae3961129f1339c583940e11c38e46d70a34fd74d6996b30ff541d240b01efaf2520fec7410409dc53cca0ef8519eccc7ad71d62af948ae96676b215576e242ee753fc0037f7ab69056edc60e08b255a0775275c6fef5fd3ac9edb4145cb19417d265d7887e3361bb3f70e9c938bfc4f752e09be832ef5da349742f90cfd8a6fabf66ab4ff9808a143c57baa2bc1164044015903142eb427f0b61ce29e489fc5ca0583b3f77f184954b8160d5e3af6ed867f1ee8e8ff7d9c2e09eb61884c21a95b5b9009908a4ee8b43a99fd5fd099124d434ed189563ccd14cedf91542f3000d31f4057905daf5c7cb67e8d6db9b76b83e02eb09023e706bc96071232d16fa9f99867df2810cd6e79c7acbaccb7f39a5f2b984947d751a6607a8f606420500026470794da57d035622ed5fa6bb5df52b082451da24947a9cf2f1ae61f875c149854d77c60449542093d4f45cd3e1901a6269046f29b8c20233024f5fd368424a0b1d1f47d103cfe136cc08f0e765961a6ca79efb1c713b905c4b62fc2f6bd9969e432c75d33544e70b29b5b3e5b1be2a88b19bf55645a930c426f6b3c8af60e876fb3a4eca64067090ebbef8e8a2d76d511a0f20163ebde43f5ff80a5111442fd7a2fad3979c062ac8e88e33936cdafcdf6b972abf9e37233c3b425e2f58590cff84e12d68bfa923278026e3c872fe345fb63c3527f58ca43508b8a58da0302a0ad2a9b544af999cb4cb7e832d450fc227341df53b52df19d81dbb6db6c3e40d9134a99012ba0d7c0248c43761e8bf2117e8bde4050e6cc8686493698546b9b4f0dff7bec57a0e078b69b6de87318cc45c3f0994c75a7e93e336944f1283e5bf01059a4d5a013cf9beee9af4570deec3caded706e836289d0a6135262593ffed843c629831acfdedd2843d87baeb183297ab14c281f91cc2826d4ddb0aa6c536beaca7b8f03a9fe41889644778e866a471c3fb6598ae6e5ba3b9ec49920989fea34e79e414d4f4bbe2c6717b280fe67ec7515b037a5fe4058e2a8ca658a71bb3990c577496f77d74ae3a3c32d5c28c2b6de4a66cbf1e000afdb65b5fbf162626c5d0745611d7852762ab70adfb1994b64c3f463c3b09c2cbe9a5f6310c0e5ed9b3856b1bd6944ae860417a5dbd6c32402dbc2ede1f800e81728dd2e54f167b57f8f8dcc42448f2798e39528c1e13431680a733704ba5e12b21fc8e5699abf863054ce46c19c0ef6b2066f54ece4fad39f4ef07fa8a5ef2900fff2483a5e5a869469881679bc46781bfe0bc7473a0ee7bd3b0c6d8c8a9f279f1a387396cae5715a2c0b9bf2327f3eb4f88a5b95cf077109c25fcb3360cb18be5870abaf2404a3610bbfdc99cba86ffb3a1bf8e790d0edf98c4261614fdc035c1c7292692dc26c1b690d874f4fd07d7395a8598481b5019ccc3b4e67e95ce8a61fdbbb710ea6f559f3f61810b61a8fa1578bcb5568a0f6c6dd4879208452afd222e9a15b78ddb334ee552d1acff70596f6de43508199e9b0dbcfb8f39b1ad056279aa8e24ece7730039b391702bc877ae05d531e621bf9d5975bc9f3de0a679f72984046691be6e87c713f227baf7ea7ba3c50c312d7980d62028b878426610a077dc16155dbc808715d5b95fff773231fd1ed3427865c99b2708a4a75d89914ae17a714cf84dc4250cfad303068741d2b023d38a36bb6f478a91b9d568675321119f984d913607aa1d5c8be3efa6e4b52635c222f93167e9750f7cff6c83879da80755de54cd5234e78967371559ed37fefcf55fd2e27c63fe7cbef4fe00949e48b275ceb293e0673113e3f666703727afda784cc641bc9b201eb3dee5ec32fe7ccf51fa32d5cbb0089c47341f9a61ece4167ff0b3e6708ab357fdd0ef990821cf71fb5db3916f945b29311de050d740df004e02d8f2a344320bda11ec1b2bbbd4c9554b6463b2bb687d212decf1d1b4a1f5ae9f6abd1b5543451cd4d3db9e7141ff80765025050a9d69d93f75f0468502b00ae9217620628e80ec5f15b4bb0fd61e27f47c10e28c878dbfe7ac1bf16ed4eba8d203233ba14ce744261be1b143d3489386bc4869346dfa06404baa7de5e1d1a5fd26cf45dec6e72534a3582c061ff9b56c8aa31bbb76e7452efe5a6c3874a2d24f9d103adb259dede370ebc2cbcb9fff9a67086184d88a1cb98bc08cedb19144d5fa6110101e605022e1939557ad4059f03665471b3c02d36837162a6c7a94e128037a3a60cda490b47f92f8eb5953c616c11357475d2c505d1610637f5a9f95413de165d8bd3bca2ac8d5db03274e9da1417b89c674be7d5e68c4ac52a0c2e5ff16dc08ebeba8847be84e29578451af9128a7220a80a37b4ef950d7e45b7234a465470232d3252d94d5499110a6e365f2712459fa84a2b3a4a4dcfc62ff853b1b64a8eef8aea9a815854a358204b74cb641884ffe5350315752e23ae0331006279c76b6277178908d4834bd64a31643d77238a4acd72917023bd96156c15be8439594c7855c5cca958c324417356134cdd43bc2b03e766800e0dee2a17fc40654778fb2fab0de10cdcb56f3c733b8eb4d8b59b338dac4971c8648ef0efb3277331539ccfce9c35a8fc546e20816a8dc7aa35a4ab3596cf371c80dc5c5ccc817f51183d43e22908c1fec301e62e01e6a93dcfca6a52b2426599e61b3c035e00c70d147220500a2a3b9f4ed359d622561160d30cf22c060bfb519be2b1f73ae62685d26f0ddd927ff1074fe2278d44b70239da95b569d085b20a5ec6baddc4efe39eb73c98952fa842927aa53a61a5c590bacfd248de306ffd67df6d4a64aa853c8a262b5707d8e21f2e0a021c5894cf6c46fdf3a93341447376e21e05a45509d34ff3fecca8b23832c3c7202bf7f7a4910fd7ee561ec3933f1ca07a86966a12f207547c0a8b48e2ffd49b00a6926e0432f25f26e0820d14ebdd66a779b310e51ce4f8356af93b7f279deb3b10bfd904435d724c6a8360b0375b0ce4c8337fe7892eeb6977d979929b535cbfe099490c9631cd16d13cf4d72d42380aa404ceaed6f19e995ac1186265d45c350513c8c98bfb79d016b119178d95a5751b0abd87f2aa2a6b47b7c560350695eb5bc998f5cc16259b2b76c49754ea164ea3350628d7ab053aa15634de1d5852aad60209bf9ff1452da49f6231453c8d567b7256a71f52ac28e225bbd4bb5aebcbf0fd6a2191f1b1914fd24e2d888f1e385f5122c3b40554fd565759be3d356ca67b252404c673e3786dd2c403b88f75e1cf6900ccc23d66cd30361ffe8f70521fe93569b64c710896aa6ef22ca3158e9d08c7928c33846741b869c6f30d087110bdb873ba59776aa4cba60c1198bf8da3a272aed5aa4763d4f683d3b54cb7141f38afce25e696f119e5dd15d9ea1cc8741c544203ca02a041fe33444a64d53cf6ebcacd253a9851859c2465488bc180a700acfb82ba821b5700a9c0e4f794a00948f39c17a239ba7d3f2fbc26954fa1b26047625e867c83e5a5f0e95dd0bd0837a544618dc348d77499c23696e08a1cdd02c8a240104bbc0c25589a93809d9a1125687f8a04c615c1c0a1c3ebf5b6a61313aa116d52e466ce6cc1170b5fc3bcda137c3246d2e393b85817f81e2aef085040d30912f3a548eac31a979ad6e108ffef54e2882669ac71638d9c045e7870d976729c3ab0b0790926f15679a19d26bb8c121f1f911cc900543e6c1851d4b4aeb63047ad8c86b09c51945db01269e5e3d8c1a13093b2ea8afecdf9e6722eb64f81457f67dbd4170330280d9aa1a0a1f37e500b4555b88ed83b3c13ecabed3f48120e35a3ef3244e23fd4cc2a31cd51d1f15dd4dfd41d38941ab80335dbe2798ab1e4d24762e7ad383c9464a5a674d6dfecf6b8c390eb4b92f1a85409dee788d4c72c1152d3c0bc8f8328aacd9aaa6d6ddfd201c283004366a0f2df7799419a1ae4732df08ec6329fa63b5a021ba2fb5c682099e0258a88e4e40b2e4563515ae10546e94c2502335575f1324068c5fdcf97f2aa6184451ca2a053b2fc60cef117e6d8fce906db061cedca027f024e1c815d7ac07d44fb125a28a735700dd4b5abe1985b1475c821b64ea0cc4755e3446373a21ad1d23c2eb202baa7dc2241fc23c3610514322c8f6a5186d227622725323f0008a5dd699849295f4be6484fc9be7e7834d9649be5e9560a344cec6912def95be64299aaa85eb1c4ffdd4b4d4f1f6af021335afd6129ad5e5bd35da1be8c74d3935e857dbe09cfdeb7b15725aaa6be55f56ace7a8bc7eac44a5006784600d68d8a34c14e04561a1739818a68d86b4444081a71d869588708964d95a17f0b6daccc08a08460bd311521781103dbc64498a013001b8d230482dee2c4eb7f1a95b311eceb44bce3e1d9140e6e599d9756422aba21f553da12fae86e4a2a964a6bd9a194053eef89f964d12022aea9e902ea08e9df13638649c749c5d9828fa64b9b56f3fd08ffaf386bb82e95f092aab42ab333d28c205a3040498ca6be240743e6a0aba4e514bc6b1c98a71ca5df880a1e68b500138c6df8983b1cee74d85c5f045897aa54bcba23bb47c97337ea301440e1feba9f351bef845fd184d3a1bb6db19dfd82bfaeca220225be5e80d129174cfa30aad0eb3be76b9f86de448403ccd50a369dc2f872fd75435bac3c7e67e35981f5a59406c94fafc2087fa44fd8ff0f02a2b78be44a699d08e7671bd19fbaa6edcf344fe41a17462334c2c71c1c150caad9566398fa3bc0d807dd51995ac21ae81d0e410445e0ee588e008f59e3dc7cea095b3fcf2c515df224db5b454d755f4dffd09ecb954adf120acfdd1103cf741c0efc7820c6d67d60c5bcb36f108c5e34b6c7d4a650d57c7d1f9570ef8cc302ab91a037333ef05e7b34193f60d443672c3c14d223d2fad42f646520700451430dc803aaba04c53bc199200b58840765ec4e38e6f19e9e179f67e1f2512d603a3329a6ddc391633b5510f61d36c8a440825dd9110458d50e0ca12192ef24b099dcaedacb90ae5cf30701157e781a1df0240b9acb74f922017d0d9e818664bcafd88761aed9a853bee41c03fca0508080ad895ade5b01ceb27caba8aab3ccfed95d2cf525c0d241c73f8192ec02d2e3fb474ea35e0b3f3e45d47885e58f92af559c779c70f90c77bc3a3652e2419537ec854b8f6515d447af0ad6be9fe5d344e82d1ab23b551dff7cb20cc013331d1b10aaf736e6970a18ca62e291979f7a40d7e04e777d1424f1f4c2068864103aa141f709438ca9c58e57f130e00bb97dcc12e72bab3c64e48723d2605c839b089b8fd5b330a38c9fd9016ee0f9280512bb2b8c19113334199f927f26962fe52bc39e1bed518f785adf0cce1e3587db15d32363dd281125db9b507756be3f67ccd0e95133e3e362dd52cc7961b2ce69de0a415876a23cdceda53583518852eba74958e9a6a3d14a4b12068f85bc619f27f32ca9c5d17fd9e6f0006357c430ec559a81deb1e177a16601e3efe9e8473cf0fb5688f868412275f4bd99c0fd927ff639780ebac27f75b04dbffa731892f6db2e0d905cee153c9178ecfb2ebf7154ed0380ed1b4580e6c424dd1d34eb2c5dd19e4d1bdd65b228376d08ea35e43f9152c840003b46c02848301ed9df2e340a8185a2400436c8e2e226a6a0e5cf128404f51cc141fe59b2938530d415c8cbec91e151b7020705b6a7e6029ec15b328ec62160eb2008ce202a7f1dc1a6e2bc05b4786cc461e959722ee86a9f07113c2dc109e128deaa69eada03b7f077ea028c59bc4533e8e43ddb1a1d6213d2384c62c26b253b351038764e5afecfdbcfc90c961ceeda12cefe2524f8d1a46aca15e4d5016aae6ab2eb4eab74b1266dbb95b791728c65b97cb794f2cf1fb8af53eabe027431813370c8617e0e7bdec37b5d6aad66ed02eb1f10572910561561252a85df1bdfc259d23d46e09fee0635d7b6ecd1d8111169cc126734e042cee72353f9b782b6d4695e2226d43d3ad1ab630b6aa73aa1a7d03d2c2ee7ca3e3f3a86c971f436cb3655dda71738a1a10b350d6778bc8dcf4662f3906f7ae8a7c7074465dc70797b09d74ac479a7a2e812ef2bb029adfc370473d31388a55e7d9b1a23297a5c2714c47c00497bf08c564f60e633ebba7143ba2f1071f2215bc0b8ff67da776443d6324203e50b9ccb87d683b0afb06da05be1f23994d531d3f1110bbf635809e7b5ffe2e46633d7708f0338dda6e40be80979c1d3d713c2f21ebfa0f8dbea85111476407bc13172338690be177d16a03b04d97433a3674d2d784140046352b11056cba60def56fba7bab5aa7d41fad2f1c6ebb4c3fdab040b920dbb15427bf779e2b5e85f2f2fab036d41a6117bcd258a9e7be6ebf29bfdf064f39404cf2117883234cb8dec315dc53fdb801f1309b7889725d2734514b72301970cd9a663c158f79a9a2ba2b9e0d13feeb7ca25982c1f0d768845cce4d71768e67b6f2b0a77c24e0fbbf4706b94bdaf020ee1173277ee5184a430aa9237d7b4b905677a8fe86edb77a1c40be06e8145fa2191df7609d060d0960c886ea97510beec072c321e6629b2c77bdfe80ecfce0d2aa2edc6bd66a6f1b794c4634aca61e3dcfdc7ab8bcd76d3b00fd0102b9604ec045b96bd81575b491056aaf2368d80e1797f60e8ed4be81cb0ced8e5b32f2302f5b6939e02e83099a6536510336c3b8c6f0248824972b8335322741e8642c7c9b1c245c7813afdf517e081d73802d5660f5c35c2073a1318a6800d19d65c222b544fe1a3acb06a21c2462372ca9c1f14d6627d690a81167b167770766f0cead1b2814b71cef3a0b555f391f611d8db3a72d80b03c75dc5a9e912f0067395f88cf39f7672dbf6f02ec125846274e674d15f5171edb0a1dbeb224422b55ad0297fbffdb453408cf3eb058a04a85d6e64bbf9114b1b5f027931d063e3c049f214770d9a42fbb9211651f98f5dccf06aba7f4a31c93ee92c5ecfe9988b203896ada622fc5e4680fa4b4537cd99da23cc0a837da0431c4e809aa9e4c1c22ef301a3a32258f62018eb6249d5ba1052c89500eec777472d8fcd90148001d3b40985ce3ec3d43712aacf6b1ea1a458a5553d1f1ebdc1f76c6a80c87b00b766ecd25593f8a8f10dfcfd0688874efccb4ab83738e25ba8f7aa769c1b700365341c70b0ee067ac22d4cb58cb3dde6ab0b670db88567cd765b7a1cac309cd3341f8d97d10df3b07503058704fa2b050c11a2edd0eeb71cd187b0bea5cc00015e3f870497906d49bf4b114054b546e08c5b782360119d30f68fad369d18072c2747d597426aa20efc1495259121c312a2134cb22386146a0249e37ce94bcffd2b3fa1b89a32872a450c6deff2b284eb15e789d6e5568df3a5937858a6a5df30ed6edb774f2faadc77dc321f499c76b7e80a056b914fefb64fdd419adf8949057eacd4a54b2e4ea7a7c2f44a480bb04415cdf10d7943e446fb873f598404d0b2ed35c88b1b95ccbd1b7e9c20eab4321a5c958884989359675f5bbd9ae0e6f71e6d9d9a4507ae0ab24e8aa450346e0522ac5e1516c742f25c066ae83229479731f8133b814258d935f2dfb57c7f95a8b644c1000bf372adc559530437c868aa721d50431ad03923ce10db9a09bb2f92ccbdbd0e47cf18aa7c6fc933defb97ec69e273258c314c56dfb1de01be3a41f16b2710a5a717f10fb4bbcb9fdffda3241b3ec6fee00fc125f6f96204ab52a7073a48748111e6c12447dfe790af89ed0fa5b6c458d9a187d56fb1ef72fa5a2cd425efe7ee771e3763d4d7681b4144ab0bff10b970d900eed35df413a9e182552f778561f1654a55c2562ee11132c471f588c26172fdef763ff6d1e25953f3c132e8dc0551af6fc3cf452dc62fc2eec3a49538c9eb4f4a304c1eccf7917164598ffde51bc1a227a64a4e43d5464be455a32173a0431aeff0064646ed02c5abb6a5fffbe024d71f3840909ad6bc26a4e8c120cf267882315804bf52b322b88925d0b4dbc9c20af6c17e90cddccdb4a99449ba08888ad1b74a8504582566984a7e9172b322c6e5e11a1e0fe9ffcdddd34a8313e7d55d608909355a5059b423747809a837ffb9688e950cc4935922c0c37a95d4eda52e998d7ff1f651a1c40fa66f10061fd730847f2fbcc85e70722a07ca26d25577c28c48c9154f52c78b49c4911b4f650218e08f6f5f67627270e103d4c7d41b1098b4d0b8d2456d05177a54b00c48537392163c313242f659e1612032b8d8d4649785b19bc301eff18632327a6ab83a34f452f3782d2286eeb88e95e4a14e452c6a404716a3c1001e3bfc2d7d6d7e8c86fcbced271f617f813e266ac4c4d2fe2200af4088b2ff2aa712e4fa58ca0092a37ef9363414563be783c60250f59a06876ce22d4e48b5aa4562d55ecd697089bdbbe292fc2ea9a02cc5b20bfceda679172e06fe7f6dc5dba4c48435cf36411ae48c8514d25870bd847d1a105142ac6747f5f4af371d80960cb6017318ecf0428723e717e1c37f3abba461d510a8aa28b6beeccc2be818b039236990eb7032a6e06aa238f1c9085cf19a5732534acc7a0d6f5917a898be430120b1371b7a1980f7eff251b29401d8fdcaed811965d2fe4080235638fcde074405616150762d79504b8628e4bb14e813de9a29d2291749b9c88c5ea71b47aabdfa53f112d4111278a88b25291975c389fe0a1f3e15d53a2171ae12086e25487a3e20f23e35f2f73711720f523141328580f675b00959643f1c007f0e1fbabd415d6ee16a329e5bc66b8878111445dae6b03e18cbf9de750929738ee065c1e57c582f6d58f29819e18648479b5bc63bc1c5697ad31ef7823a30f3c8caf716f7d431a59086bc174aefaf6ae92841f97f4ca01864174ec3a4e9916241a761c04ef06090fdea1d24b193a2bcd3dc1fad5d3d567fb944a66b40f5175930c591c4665c8c2851543cee6eebcdc0f298b67ecf15d965ac709f376e3cd866b203a2b8d3bcffa505a54384ae1d25b4cac916b8083739b3f67bb39269e431064b003c2f00295cfff35171a7e37a5426a9a623ac4cbeda97a0dc83572a6de8cc2a8e702b4fc07d0c6f71266260035be97e8bc52c51bd25e180afdb2be4b6a2845347c8529627338587be76a07d71573ae689c396c70120d290148a7e2133edb133fdeb69ddd94e7aed71dc7d1014081a7fd597b2e24770b62f178e4c17b624d222863335c8677d95e99a7753a17599880e778797c0a918867319705a7a55391871f04f8fcdc6896e19a5d504ed06e21e496daa8273c80cfb64b3b97f3400f6117ff92931d0989f3d245f47d7317f9c1596121ccb66d068d3f3bbd68056ed2684f2369f705806453c58aca2bbeeff0cb01d5672739e0884d03332f14628650b33d9baba59ceea93de55d09c44082a96622e52865bab581f761cd06ef79d9b07f7f1ac88f3d6922fff02b8f7acabdcae6863c39b18bb26fd4bd76f6dd2e2b8d3c6f076fc3cab5d0eeaefad4ca34a10c9eda4d04865b7a24a46567093f93b914087b68acdbdb0d7d4bf0923267dc8d90fff83a0f0de507888a077acb371c964d6070e8d6a72f78026b5531dcf2d61752da83596f683042e898f98d3e8d10c8d7b14c41b3656ff90e5fc88f0c560a9d2a21c290839a0bc5c0c0c76f0fb429b5f945474a1a4cc93cb90e29cdeb68b05b29ec09f695976af2ffdc9a5789fcdbc32d34f41db47557f6028279af185e44c8540e71e8a554e1cdf7e2f1d7046993e4f9940b6d106049e97ae68ad832b186dfcde54e0f183ecf0dff2409851674b3a78c4c583985f911382442f209c58df0e8717d541fcc58341772ad8c9ca46fc7ca58c407d217f2646bb7a340f4c62763387eb6853eea19ca865b4cc23e52ea1d3db602971129247f1c9f6b11b0fd4962caf30c78209142ce1b4baed82d38161b75ddd99b1da093dee5a2a057f145ab4f53198ead5912676dc86a1d049536e85e11bec0d635da4a90d9b376a722cfb08a5d89e6fd094377526838d6761b8a548007b7eff8d80dd2e476965091f970afcfe6b013edd983a7c4559320d8f4c202d721adeeacd9c8d30b8bc5d890c68e059a8cb08900695563f1ad9b2be836c28a2776f31dd1e41f12559e2853fd431a9791216533662db178c83a97761e3e43676bc0ebd0085935fddcd0d2d040f6eae94ff54fb2237466a6cca6831f48eb2ec4e301b4004691b0378a043c5d317356675afdea72fc118fb935c96ad3628890edf39a0abca831a6d5c2bc608626cc33fe93b6b9eb41d074d4c5e58da5fb7884e091f0ebdee4919a28192ff7b791f8e12ede62771f46cb43fb1fdba9be67d6136c539c4576c17703432969334ae42ece264d054a52000e8a856a63029be45750a83b25b56a800cc3414552a34bd4c251835bae6f8bc52825c4066f7c56e7f63a67cb5f908de97bf7615f0d0f202795f1fc474b43be08868c154ca2d283a5d16eec70cdd4f26b796b0514db3c30a6d81013e62ab456da1c14404034213a25bd53f41b8bcef94c958962f18ac1b11f8d3db4f63e45de81b1cfb50fb296753098cd5c1ec97c923d407cdc300e7ce0f8c0ae00582b7c3e84ae979c31ba1bc308c014e23b633ead6e2d09ac7ef294257d247a6d53791a2146311f44244401fe217115d517a72695ff0a970ec62cce029ebc9898190ee04f777f6874e1d623522153e3b8e5778aec72b55ea5dcb22afcf3d08e164e8c6b69eb0101e4e73d2a8d14d238ce65f03d0088ef9bb59e28afbae5f144ae231fe3a81f833fa70e252ef9c79ddd22bb41ce073e4b72b10004cdab0f4af623988c9a616e0827c25233b00bfb113ac468efbdbb0216b1c3c63996f76061fd5d5d47ba2448875f033fbfd255a2ed43cc50ee9c66ce51a42d3e1a1c19ba0d780f5ef581f214d7f4112e98cae546d6478690a625fcdebdf0501945a6b2cb9591dbd46869b9ea93f8d04699fe8eb9c8e98b0aaac832722ff1e50628b813707176e3171cd54306213a469433071bc500e8d2a4d0e1db813186a8a0fe505b91031cbd04fb10e47cf1259f096a341614aa8dcaeaeb6b2ef901c19a9179e48b2329c84d00bf37d8cf9f3cc5c09c9074314b3a5373d846a095e26c8d6d707a826626442997d3ae7e4db10995517c7ccff02019ad9e772763306157cc55b34701bde2b3aa62b9a4503cf26576c8376eb5d1da0a10f9c3fd9f9ef955fbf8abe46a02e6c25d1eb38b2814a57345cb8193a30378ce3f7191156b163edcb9669f887ad270a4518e909a774e51b8dbea046c439ff2b94077deed438335340ff22e94dbece15a216d39167a2cc508f2be081c00167426341c2bd43f8f3abd8276ec6479ce1d60865f048b6cc46e58bf466454d48a6cfe02e1998c683aa069f520a9db44c3bee54baa2c38537e253209e5a31869230cd9905b59fef48674bee95b16506f856ba4fc38dd23898e0b9384f6d25c54af5b05babc9665e7e0efc05e4227496d3367e9134da3ecffeb400bfa469230bf8d49afcdfd5329a7c7824ec19cec22b8a642dbc12a425c92d2c395f5036a3df9e4154f8261a02f5f70de4932a27c8823562195921c97bf0e31fcba2d00694e92545b6ac7c3c166ccd6c80b6e5b1ee47b7fe0241f70c625c9872f79aaf8687adf3a1b46489d3c1c0cd1e8841a54a8133dcdd03a600165d6ef53e9ab66855c2ef3171c1c1bb3e1f127d3f082247a7adff52c9f11ec93ffa7745c6c7137677860a82cf2468fe0a1bcda4a7a5ac4b69b28a85597038f8ac6b70eab1c8b01179e9eab1e0f65e838124dfba2f4ce421f65821e2aaf2105aed22f37c17c4c231bfaa57b857ac9918d48cd7619213052ae5446a0c30ec40418a02672d228d1248c7f9d44f08e6a863e9388f811d6a6c4eb34f7b9a32d65e608e135fd43ea13a51404d838a5c544bae9713ac9d2c0f65de2b924a1ff5d9a0ca548629c8a6c2266f9bcb6a0660d8aff8a75e96f11ea6045ce21f6be7f37865e00b94a422f21f3493aefc485e187c3d463d68e4c18675008a9edaa04120234b857c92d62e872fae61704ae4c3f3bc6a977a638e903173e1bc81cb9ac36f3ff70d5f8d3021470a6f8177960b1a53e4122f274c34647635f22d0a38efb9ea25fed7b81389dfe5b8868a0b90eadcdaf307d049613eb52b0e70bf03a27752b9a2fca3a3cc24c580d389cbf314ccc29558188f15bcd0e3f869da86693741535363a94c029373a8d2600c1740d5017cd0698d3c56ecfb4ae0aaf18e9c57fa0ddc30eafbe51a9bae206f495010b4aeac0082bb582c0f2513e66e3003c13dfb6e306691960d9c3b374395df6f4c52ed7951f70eab39ddf89618e9065480004500ac0d1171087cafc438c57d752298c0510c9ead219f85fbff7b3a874e0967b73346299926008dcfb3ccdd366a263f8daeaaeb252a358767397465f5891a28d6f29315590753375e669da4b7b3ed37dd4aad83e982c17b017e1f02643c01c1e054175512f0a500297fbb87fb135ab93b15500e43e9e85e3b29e3afbf463287ead63cbfe0f3e2d1e00f3750287e7d296b0681a51e6e1fa739b8f1797c141ddfe0505067d193084a4f326b7edf1a0384f90ee8af420cbecad1b3ce01f59ba381970166ff37d14a605bcfa68041ef04259f6ba8bc2129e093f7f165e66e1a1160ecd0b949b8cdea54c41cc100176ef5ea0321a3898010c54806787be889d545f89b8eaa3c040413f04e32ea3478061eecda786a65e55af79d613d2b59eb88f0044abf279ddb91161ce6f289f9948b2ce8772bb89c97bb1effa559eb82895777ca26f5f097d6caff039c317a2357592f469210a999d229d63f7eae16e233b2737ed100725ea58dae03cf8a4a54d6879c2af78a98f757a8eea8e464b46a2f7662aee33438509235fcbef9ecacb44fb9f77a2003d785539d7ddbc6edb2f07062d1115ccf470f9ce5ebf6250ebc9e06a327eb875ecbbf2cba3ff9c4464f655b451acdfd7dd706834dd61e7aad2576294d4be9cb89f6a34942b2cc6a01cc326fb159c44de5db37680b1664a152c3d2187ee17641806a9e6aed01cd1d70094354511cb8608bf25c3db5a3e971081cf95392195f49c7a0d19e7d5737a062c015de57c7eea22b2de46e79ea9a3857b6949449ffc851b50fcfaa9265e26ac89a61f0c16197e7fcd0f48d7e62af70e0f5e98907acce959e8e7030f5955e9abe495b3fdff77dc579cace5d65350df78a8d48d9782ccc959c92c4eecbea38a3776f2b806efb1106372a51bf49dfb88754a51212b99f5aa41cc798f7a1954afedf53176950e0702cfa08c8d786ed7d59db6508731b3e04e8b040a52926736857ffd4d1749565c39388f9ec534a3b677c4176aabff5cb7ab1bc4cb4fc7b94a90b11bccef63125d4734d48d846dbcbe91265bf749dafae9413fbd355f0c7460545fdf4f703e867252cc924633df9387a378dffc635c995d6c2d1307390a627d3427d76fb4ae1d4fe5b650fe3a1bd1b6c104ddb5316048d837e1094ccb507054a278f81b050d6bc39433443dd7644e36f3a47bbc3d9c898db1f2ddc7e4638ee982eadc90f2fe695c0a6c72f3a409d15c0c6155cee4995f6505ec1b196f0f981e721c5c79b75e3ffc6568f6eecff7639d860c3d4a494645a52848688549747cea90e80fc9324fc0bcbd077ab101151043b63163020848a1c562deeab235cde257ac2fa7912ad78e6cad8ac395413c9a6defe22ab802b1b738269b4186dac3eea9af1b0b45efe34f4d4a7ea18295f330df5975146761169af332d19ecec237929ab539a3a9507364021a307d884e266963b47a3e9cba5ce203dc616debdba5c032b9903cd61bd40a3f3f0bc477ee30a8ce09644381c4f0ce393c3407034144e5898b4563bbe9a2c0f3da73165776f1a1c9965bcc9c937ef3b5edc9a41c9240dded42e9904ea551a367d995de82caeff834b4e37be69dd2609ef05f6a17aa114a8c61702285f711c61cb3ce209307fdaae621ae429de4f5b53801048fb783a1a6a66d7b69de9bb5b3a6379bd5b19349571a5407f2dcc50dbb0734446f401c19af29e04b1c6eebc4cdf436a0b48ca4fc15c19a1e69fb2dfb783955e39ebcd06dfc178d97a8cd06613baa89330062bcfcfeb4e9786d9297fe14b23bdce39e3d60614ac2462e9ff4c4b90777a9f7286df16ad7b3677a5b01b26b1f07897a4e69f98899407bf7edc5685f353749797a0f88ce71c6f3aa0549db74950d77c6c4468cde5b0e9752e06ebd8ce7fd14541b4dfe5da0a9464554aa902e01dbb59cfb7780685a79ada3f59c6af7b267f77c393119361254ff49f37005f9d698887f52dda5a5e09b812848e57e4519d4a92393a73116b8e9bd2e3add004a30c17cd2d20baf24ebb5587f056f37a32d8825a9d5c40f44e3cf83adece53b04e134b00b51ce4665f41ad832de85cf37c5b560d2748d0d7d60c7e54f0fc2e918da1cafef4cd93a0601ecdd30390f9a598870144a524fd3c8e4c72b0d1734e2ff603635879a9c24aff68575f401f2993d89a75b94f77a948d835ab73c89b3ff8a7dc022c888a8da34dd1b0db6958c43ea6cd810c2d71d610f6250a13fc125f09b3b7f410ef80670235611555c8a1a61b62bce732573a20f8a54d7e63714451cdcb973fd4fe2fd994b0f10506588c98ed9dd3d0e5bafe1b5ff04114f9cef3e79bb4516513076e25ab780245344c1236030714bfed5e619c9e9890bf1c49e45e6972aecc285db6505d75eb7188d0fd50727acbf42e4d64c6c5969c1e2637f782c37d365780d8590ef73baed92192b887aff27e13c91cc30106fbd5fe46a1d285e1429645ed77e369f0027ead80f8ebe28e0369dd89360e49b4788d3f9488d973ea33a37ece84226ca61b72b73440f8f0e3a3072e32ec4bfacd76a9604b4e827a4020c2d5170303e8fec3f4e467ebb9f5a0862ebc240044cda85bfc20975a5dbbe2c7809a966186912d05ef1a6036c8c8ab3c373e39aaf6c76c76eb3e0dcb1897c625e8a305e5718c18d40461cc51f98ed9f1f929c3e358842b4b951b50396baf710c128959afe77b2f4215a231504bad5c17577ac59213847acb075ab7ec046824f9f4f080f0545621df8bc252d9e11c870ce15847bf1ae4a69aed9da89d7eedf472397365a778f5fdc2b03a87ab5faaf5c117bde0bd7501502631ed1d268aa81822aa9f1ea6bfdba6788329279d6be06b03b704a1c4ab73077149db4643c85391f3bf153b40a49003942aa98e37483b960bcbdbde3c49a0cb1cf9678c68eadcd71176331f83a03d48eea90752ffc7139ab2d9b0579fc67d158d2a680c68a5c4877ce7cf759e949f1e248c2fb755222117c682a33ca6304db30b91c1cd8abb91d9159df83705e22db6ab1186f7bc2f70832daecaf6910ca5a5958f4dcae4da5c672e0d35c8e7cc95d3d7446cb86c8a941b266710671aed0aa5cd00e5412ffaee559ba32b5cde89e8a7a95f32867b9e533dd04cfcbff4d56c21c277669ff9de73fd0b41c144f3f8bbe4a097d838634c4e6bc321f74cb2079ed48df74a2c0f598ead37b2389f4673404dc9e8fcb5965053bec58ed4d23e0171e577699ba5ed7254eba8d129c6734923e7ef46db96509164b348243058b6fcf490d86836092bad6da5647066185c16f77c28d5234205b76ff9e4c44829202991c6381eba973db24d03d45a26748395fe0852c63071d283912ea79647674b1e9add586900a865838495ec735e4210b29d4609b63c13d65632eb1f6417f728fd6f712f9a82c977731d25f992680a861db4a0a0b8bd9542e1adb906126612598d0ae736fe79e6889a7d8754a87088d2af2df5dcd356561ae114e0a974e657fcc69449ced3d4577964c50b50f9510a25e1b26142875d937c48768647f4ca5d0e899876f47981377ae451f8fff17fba3e817524a9c58233c70f7bd8f19a60afca05633cc9c176819d6a91324eebaeef93be8b0fb4ec7456bb2f0f2fd3bd96de054876f7182d8b98c40b97d3c13605c2fb68db7d468d42dfb5876c8183e61dc59fb44efe9e01c147abbd67843da6568f5030128b28c39c68e45174751c3d438f62e078667656d749699adaf1760e1fd670e1207d51a298508398e2161ee1023fb8b4dd12001fde3a217da2758416f1674012f1aab8affd7c7742a128771190df8c045fde00e9ae270adcd91408b299447dd01f9a92fe5d47da24daddd859c0ce2faf24fa10af842edf854bbc91b2b2d733f663bfb037492b9ec2c6e229cc8d734513bad64d5bc45c91dc17966de21d73245d9389b18ce9f1f0c06f3bf02ca4d2317d259ba16fcb474091f092e297f074f6ea0bcf9370e70713f0c5709522e83d6feea4f02c98315eeefbf8c91017ac5e790e6cf6c9ba89e518630c2fd8ac3a2b5a67106f267b21c7f7b0b5efd6dda7432c10fba9c71484308e8054ce1894e125897b1bb3f82166104405fca7d313172f92332f242887e023fcf9209adbee5bf7d47425825e4fb4792de6ca5bf227887ce331cdd8432d83d5f74e9b7ee1fd9eff8aa2f1a6c8ed657d827688675cf1eaa58618784ac438fa8d819b271865539d5cca37a4bc42b66d8b1e2810d270c0b9b4c6d02bbdf6f1ff0804216da50cdf5b7747fcb61308db3bef45b8794db62063124cf1468075697d79df7b3fe7d4cc63d4943280c17b7e092648f67565bfe264267aeb04841501ff612b32fb2d17bfa97ca05f6a70a4207c9a3237a6ccd223b5a27ea3688484a80bcd15491127f40f64fb899a8e8ae2caa31ccfe70f110dae72f30ac851ada9b53169be19432dad8f2c4d7ac43b9b2455fa1b6f51604b0fb03317e95321a8bc0248837756ff4a6741af7eab7c18332ddc33cebdda78629f818f0a9a57916f01a4fead34352ba9849c7c2c8cfc4b5902a17b7d69c8bd060951f8791a4fac223b9dc8f892c9895afd65ae0e14857deeb2e97161acb30aa5e5a5f4dd6564c95525477c426c99350b7bbd0c7122744063cfd042858e645065b0f65bc3e66e82e9121ab8f1012a13184400e1513bd028a08a96a4ad5790232452dc2fc2dddef73139f35e7ebdcbebee799274da9e98826c2d7c18cc8a94f0455fd090a014e3750f29f34a99cc3c96a9d38b4901ce5a9b0befa216a89e1736fb101fa1fbd28a18a68e07e4ad362c8161a405e7c764a2056fb6577664422caa9266441ac66d35083a0c358113e8568b417eb27fcdcffb174705a2fa7531cb3586f9aa218e31ccde59c9fa547034de7d8a195a0fcfd7b26c5c78049444d13ef1bea4f9d9d02c28d133857081864ef7e7385b9d4e527be93217f82f2b4702b9f7101d1d4e9d6311ad8eb0c3275217e126d138e33d145beb5dff8d7e36afc0b27e967e1ab36162e25e885533e3ea024fc648b89e21a230b62991399f7fdd1b388c86145b406be8e0d5c654a2db42ff3c5b7ad38e9610720667890297f3ccc8a9af8516734629c90a5642bfe94194be048e9408f487ea1b12865bec082a02e3cebd5627e4c6e2a1da1571f653e04805f2ff7959b6231b4177c35797ab4dcd14e9d27c8f8540bbfd31193725e56ad0cf36d71b7d52f63af17e95f331d6aee734723a9ca4d846df093537de4bb08e6fbf67ee8bc6e4090f595c8ac11c795a7190dc04d6aa88b281fa7da78fe254f682232d33d5f6bb002a5badfa76b8ccacb26cfd25ebf325c4134b1a213a94147c70f1f770cb697d75578a5f61eedcfca91285ce79775463964497a02a623a499ac0a58bdb9e1f69d93b1d03a230a1f9080f6cd5a1d19a768b43088b9681efdfe5d117078a233157ba54146c046d73226f89260c635f2e9290ae431154c914fe74f833ea4145f3f1fbbf9b512ee387bd41d086eaabfef892250a9a9876a4542c144e27d87d4d7e2fb859c08d3e9790765f9c11df0a5df63f2a0463d8a8e435a6600a329baeaab9dad680c6cedabcde889b1a21ee8f8e1848bf74e52e01bd0872574d9967bf1274ee175febd389184557fb1b537a9818e2a3005f630fd4b84cd9d0bdfa1c04a945d5bffaa0d6109cac9bb3823ae369d863291694e92e4f49c871d833e7194734a71f3d9ad3f27baa85aca9e4823b5a9e6dd6608a7be77effbf05c148e7b5b010c290e96d83a508b428240c25c95e598c31f78606d091e17584b28b80a290382cf5846cf131f3229ffee2d7c56ec8ecb9c360566dbac1d6d51b113634c3035aaac64e6e3c4908e7a8166739a8c72c36562dd4a69a1754208c74c9f4d2f2e58c868433104d80973dff93124944502b5d88b89a8a2383536744f506dc39734325f062d623849f0509c08995ca24be3dfb8da5a9b20bedb97187fd3687fe2c7e047805ba4a07574e3f16b1023417d048f1748b8af5f227b21ae50dc83a178b5bd14d4b89c937f38a601880ab6bfa8985efe2dffa1c6db3129642876050a65deea0ea565b931ea02a226db02b535ba087a381557298dcabae61eec6184235e765a06c6d09e4afdc0dac69be58e0beacb637b0b5f505b061b0d50cba8b1fe2b0bc38649effe16f575efc55534a4470d405f41fe84e93bc808d8bc5e787a5723d6b0e6a587a6a204cbb46fcad7291485a1786dbdbf9c10612a0aa7fca1cd221f210faf4d921129e5b56b2474675b9e6e083f4ec6ac6e6c15cbd70689a047ac58c289933381f74dba862453b7e87126465a8d8e15563505e26166eeabf9c8621d4900efb96943753521c8947e97e389c65d6f2f5a398e710bbd030403f0a4887c805ac2b599476d332a33cf1ba1c15aca6b45b269087a85a9e479faad8fb04ab48c703cf7810db853005af30502ab3e1817bf140acda5067cadfc3f8eb66041f774eab31959d06c3e9507a05caa0e9fed4f0c08823e5afcc1175ede85aab90f3c3d7c8ec78d885d717c59677cace1bca655714287cbc7edd6ca8cf564d14bcc47fd1cb50e1924ad4e197db515c3de42226bd0931c4def10d1003fcb226c41e8338dd124be28736e500fc510d2d70184ead50f122f4d3abece29ea3726de9ae50d5889d4f4f06cbc10dd4e30b38693528677ad16b185159c2c7b682490211136c1fd0b36671268e18caf2803e0f6f91a8155e96100b57feaa816b78d427b4815765441d0af7152227bf2348ded07f744a8921e1268343c790c49f31707f098a8416d5ec5bc8ac1fb0b742f1a3db0263757456879e23aedbf88d7bf50d41a3839a829af1b7c01c989bd898ba4b1bba05309f3e9e2c40df701712bd6ccbd4df9672f1d088b88f306b1777fd3344b22366e2c4023ae20fc5a351f925d4e988c9d0a35fc9f2000dacb064a6e917aabb8bc15a285eaba2279295059dbf7f518f1f6d59008a2c09eed1751eafcc8e67f11190b01b8b26e852e2287feef8fc5f826bae828b8a0696207e56410c78f7a7d981712296113edeb03d44226467d98f18277f4650963df60681b72b064e200bf99bc526da604b94bf86dedbce8a1a556e8622469a2d00950f17f2b2c652d872ed5aed2981eefcf2941147bdfd078feab8f70f8922a7d376a424ee3b5e7aa9efa94d74791cdf6d98f3a8d45aa3c6c2e3a88429358aa3ece1cdb3c5a113c7a5486308cdcd07258dafb00ae835a7ace6f902f7ba71637d2ca5d0be8c1d6b5f3bf928eccf9ea7ce0df4b27004033a1578a3a98146a55773a438ce7e35ff638ebe6fd55c986012b84d295043fe0f3cfc3a6f80db9a2dd9440109fe09e0e29e7a63461c2ffeec7ff4de6c8eae5a9b1336ddc1fd4495015966aa47e904a03e032778fbe13cd478a901d5b2267e480741c7453e5b37b2e9ac234ccc93c0d5f5c85c266747328e61e06d14250a0fdf9e1014031e8a22782d0581ed4a5d52c487366e6bddbd6d8004d040c9d66f52787b4894c3e804ef658949bfe9838203cbd137319703fc8f16ef74958a525a586c78f438fa36e5ecdb802d64ba186503b59dbdeffd5ca2b2430f4f87c1100488e5811fa0f86c31d7b40a5ae476235ca74a6c518532c0903a1f4a8840347dfef721c4bdb3f7307aee0df66b1c895796a0a533fca1abfe289dd500b7176af94b6ff826e46770de9ae967fed5b6a059936f2f52211c11e50bba834370e7f7105715357a86254b75d5a253a92ee55fede016c9f817d8d001e78d6594cac5f6cee303aa8c8cbbf2f4320f59318b6ee78b71603465a03d9dc9e95897940482496f63777c8e4c19a9c34bc416e41f8df00ffe374504545c15c2aa0df20c78d918d0e6feeb4cdcddc1e5d851dea0fd28ca9cc8b35fa16ef0ab36e2c100d5075b505602488bec048c9baaef2d0c79862a1fe8beff0586eb2ba9796825839a877667a12cc065a6512fe8764599b7816cf024228dfa82beaf07b21520eab1fe3aa3b7aed69bc728f972572a6af4aa42bfddcab243a24045f99a6468d5395d4415b85fb08731c1bc24111fd3a82c66ec0d36541a154e22bb69e87f72a5463dfe2d9975af030162520b0528acb0bd68047a20cd30f5f0a0ad6ba2b760755234c16b44fc9e1124fe029a69008a1c76243e20ec04fa70278dc50fcc6f19323462af2f9301f49cc57fe21ee48747983c73bc8608b2906ff9bd1ade4d7c340b572be512744939f0ac6ed71af2ba26e7e41a1cca2bb253816943dbca1eef436d6035454108d62fa41e2649f24bda9fa77cf939ea63de88ac44ed14b1935d8c4122cb12713ac53e1c22a48b5c86e60c526dad177067be6ba6a6251e7c36f39dc0b4be8fce1e6f6ce884eaeb1fd75b6a2a472164d0714e1d685aac03ad264db767856511728fd519543fd3bfce2e7345f489488a155b0609df03f2d6b6d279eb590423b4d6129897bcc3e7a69b925df95816cbcf2e309ffc73736d4a0500ef1355fdfe1f17cb20ffca8dc5614dd46a079ada661e087b9e7e057b6b7843daae14dc94cd029bd0e8f79f3819338bf78bb848324071e7f0c14aedb33a47d17ec905572474456a83de1c4ba8b08d4ee62a15a19e2704bc5fd1270235286f10881f1ac596e6340376e47998c481187860a9f1c2136cb62a4ee819dd538736ff63b7707d689d847080289f13cc94db86d9146247e40d8c2718c769097d0d1ea5c2597222c49d5b5d635ae872f5ecce559cb3a95fe350080e8b15ac73224114b327cfea6206d203d3cf1fce8b38afb81a966636de92e5dac4644f8f80152784b0196457be93c3695e371789d55fbef341918ce95b17c2c32cace05da6b5fae1d2b21278411e392253870c1612617b88f79086c7f29da4d55ad678fe8aacbf9cf3cc9ef68643d901be0339085a44ce808198415a8666f2ae9de242761ffc1bb08684cf0a7346ed74bb575fc309f2ef548bb822c2f92c0672515b80faeba8472c8b0ef2b213b6da1a13180caf34fa52b6552562e53cd2da016467f059bcc9012fb640a32f72c6affbef380fe78e51cc3a630ce5c6dd188886951b198862822653346795bbc22baa9e1f961765cf21879eed082ea85834bd91cdc0f114ff061a5f292e8e95ffe33b46f9f84bd92c2442e36807bad35d17cf40b18678faf867ff63319b7259efa8f35e16a313fcef963aff8f91aae8587394c63547cc433c51fa7334a0b359e170ce13071b2bce6e9aee4d7d657f73b458b0d14f349e4d2104cf20346883b614acdd80e7f203303c61b06f910405fe7b8d51401bb325c2f5dedabb31901e3c9f7f1cf3a866d11f55a10f76459177ae751b6feebe3e2dbba6158ce43d885e62eb85ab9cb2230c6b62d78b7ebeda5612c5b35099a307db7444f1629446210ed8c9bfee46bde04842f845b707799962fa4d4ccd024e56d3024ae2ec5cc43c256b4d695de3a5186eea953d8e9b2488f9f292cf21794831d7bb2e9c4542a7b70f1eb11dc16f3e1b27b5de74b0eb5a1d249df21f6c560a60e900b92884c47863cb0af07ee640d5b6fd85e69e23d0b64f2230686c3d03dabaaab2721eb39c300c2636bbeb0c7eee01ed1aa06394e358c410c6dd5a176165182c804e87f20c7393a8d653bddf7de529b66c85c16de74cab905a013d2282c2ff801edfe01d4dc64600af587ac32c92b38b8c07f6f6f65f3e0de1a1bf1abdf42841a0a07288ecf1a13a74b2da6e71585cb7388a337effb1d87f6b81cf310b7cba9aa85434096247db94a63128f6dcb35758079136c6fda1c44a8401a6cd35b4c821104126b504ea351d10e215ee7dc8df8a300cef9e0e401fef306a815148d8b61286407f48db7e89b53b3340b5f89974f392a446a5323df58c8305887e4b9ebfd19e026cd51a69a2eac6ab15913d19e71032c7d6dc2ead3e648b302f388a104bdde9ba22384c2794bacc534469a3191fc244c1306c87368d8dee453cbf798916b84d490207cd761073f447da5dacf9e22e24c98215b49e7a5a8e9932460be451ced725b8205ea662f1b690903c67f21d6c8faff97ea2e0180e113968e3b1216042512a271437dc4f2882de49643cf149be2bc759305899968862979d4b3336461c185f9bddffb765d3a9a82eb4aae07d4549d2383a3418d288757a587afdbb7c268aa914b91337553896c944ea0a2af3e6ed483ec66bd6d74a37868bbee605cd4a678412a40fb2487d04c452f95002c12c2a0d0563334655e4acba32e61d619538652cc92b7f91c46eddfc2911a3242b77d408af90407a94896b7de3d594b57b465c194f58ff49429a9309d5229cba6184ae95cdb28cc268d173222a64f2dcb3be88d42e241ebded9f885a89d066e6eb84b6f30007d0e312949a5ce24afb08810a1a687722c58e247c6d0789bc896941ae648be9f1f8f05d116f18d4a909036e0d90a448621e99ef2a527caf4b129cdccc883fae651a6f0a9a75c2c513426425215b191297a5e27f6b95367b5fb027c27be96fee784490c640b810e41219c80551ff93978e902dfd4d1be43236e4627c57fca38420bd8a4cb4138cb509b114641a8a81d085c1da6199a5ae4b88eb14649c9d402c2d12a3242b58404b400be1f5f5f59603fce1590dc53ff6535a10eca8509eddfcd04bd3cbb556d07cb143ad3afed916852db13b51c7c38d53929da7156331100f6f18a283c61b66d70945c995077d792d858eaf74d1f9c549676a64ba956799c83777dd5ea04d1be42edb4fc1891e33384fd1a7148cd159b0b9e369dce4c3aacf020bfd5e5fb5d4ea34541220bc5eda3d2a2112f69756e6f84cbbcb7678bfa55b5bc9e77d1b5a739375b3cf01a486f3d76e31fc143e605462dcf61345635406e7f21449cf4d38e0c2018803432181286dc34fe0f3e28380529a9f6b08a9532bbcdf61aee5b9a78e9908100a6981d2132d4927e90063d1e718537bd638ab864562c8c800b426df9f68104846df033e8dcc0c2380d70450065f7a3f2bcb8c9d2e489061ba34999dcbb44bcd993082519fef9d83ee3988fe53a8a2e489069195de37095d19abc7498ac379f561273c865cc773d81e9181d49318d07003fb4a4234ab807c1a11d6174b3588c0651216aa0d4e5ae69b405160b2260630b4958c55dbdd48bea813e79c24c4b1002a0820c58b674844e22f911ce7005bf586466dd70c3544b76620d528927552fd99d94b23ba3bc86c5c03d69c2ba902df9edd76f495304891a1d161cd2f001eecc4de919ce68683894552423cfab90f112873ea3d4590b708732c62bacb10468a54bb20fb43493a6dd229bdb2829cd1a17a1e146493104599c1367bdc301e58b0267922d474fd2c471f566b28c7c37e3191b17f6c6d46ba376cb48c4daab96aa2cffd552eb7435b78dc6a710e70afed632959f5c38f5f970b1612421bdc73f57e1457db186cbfaf36d060ca7b066ebcda5db06ea550b6affdef73edadf1eeca7e1706e8010815e3163c81880cc9d4d822962d67a295f539608c50e8ee900a2781596ac2a241d9bfced15c8803c0c01839360ca82854a78eef62f6b02c2d4d668ec25ced2558ac9e098a669d4f74b389eed8c51205ea13a83a947d77314d13e2d967acd710c489ad6518ad65ef286c797b6fb056b7e804116f1c1fb604f86f01132ac24846d304ba8a192a127c2f1685e288568ee3d89af90c51b176ca7a59be4605f245029b2173876c1fe03cfa260650d2d7f55bb8320d0df0697c778ecb66572e3e6a823b236f5050239f41e04369acc03f6f97eb1fb9b32f0e72814167c109bd95cc6fe5f6d3b3cd30a83fbc2bb16976ec526e5c56a9f7c2d148feac11d4d5d144abb1fe45c6db5249329809961618f4c030fd453593e0f9aaae8c9cf7e9824f39698891c2a78179aa8777c102ce7cad13d35ee2a2ae14bc066ddf5ca6c0db7ab02d69e4bda61ab9ca750a8232e3e8b6deb936d153587101251df99f3daf26a88c1a0b373b7355400c59761375b5224cd2fb983f38cf5805e6c732f85875c33be88c1e1a335762b4a1a066cc7c98b857a6b9a810b7849bb41834e1cd0644f1ea47558b066f8cf141e5bb7abd518941420d9d47ea821f7d960552586ab13ec64c0f2b4c760fdd6eaca17959049e8868b5af29d7b30001b039f2aa3309f60af28b2649cf78e04d6802756106783049b31b962f6129a9b81f4e66985401c93ac92a0e5a3a2035e532cebfa5beb057a563b821fc4e84041551bc9520ffa326af11e2385eeb8015020d3dd76384f426defed15084455795b822cee4733c7a88a217087cf42829dba38bb6d1b1dcf7947dd4d9dd2860362041d4a35ed7f53786094886dc7814b3c7a10d4770e2531c79986006490eb5299ba99aa90530a92d6fe7eeba4f7a129d3c7ef546a08260e1e7aba282d4fe0a7285efb7f54b965ce168cc62f398cef8f638e147eb1fe329fec986102d0eb32ce414c6f78b1c13f9435d7ec72eea79ca9854d0f47f5e5c199c69a9daeb1d1ba052556233732d486a050aa047a6e9d0454f424df48957f3719fea6a77c4277a5ec8fd9aa6b6dde678a34d7dd86d42e3e82994c37b298783abf8da15eca2350c80b63ec3614801389d1e17f8480f63906ff8a4ec091f92f715e24e54d1b2df793e29dd7d5609f794ef4f897d7e1eaec50b469d02bf50246c09c077a91f4b4c16fb9cc417a9cd8e4eeddffe40095c11b0b8b3a92f87d657bad5c9e8ddfbaf11490cf0eea2ef251629551abc752217dcd20fbd3c8b88d7682f9a2b0feef04fc9798ce23596542e39872819fe0f8277073c47db9b682625b5c3ecb2cd350f82b317ee756481e0191e107a7b155fd0fd767811547ee2482f3e27767a5f3237670e61c884111052a1ae74a460ea8e9f7406fa9b9194bbb3c8e261d3cb0d87ae1ec1e6bb025efaf4df6ec027a5b6da24bd35ba3e1541a0f7cd592601a4d109cb6d32423537e632008a73b08f2e9c25d6ad282976c15e896318ac59a0923d28daf1217588854ed86882c7835e2178d8423b8499b85be95f38bf5cfbbfdac3e345880d4c14b47e808680188d72d9933c4cf5a236f0b285d6f694c51ac6a0540158828280637b60259691f3028005e9dba410701fb9af08e222240b44e80a39813410316094f437802ae9ff9e41d418c1b8f86d8c0386b17668f8bbbac866565cae278eb10bbd07e61ff88a51f0464ca113af95123b3ce90fff8951cfb429578d3eb727d2c30a919d1b7acf27a98109d81264c9e00aedff9e275d009fba6ea4a756b7aba5d90ab4b2202c801e57f48c6403e007ed5bb269ca23741f16803d23980edd92c343773e47b6de2348e2b0fa79d23c2179862ff338ff57ebf109496134d12fce1d0260b2d129d52da40f55f21b96510a5fdfee264bae0190be6fd34ccfcccb357caf04ba9897ba5a20d2aa9a0eb1f0b0566d2d5601cf9f3ff79f1720583e2c8f8662124bf063e69916b5ce71d016b5202793ccd4a68b47e7cc85308540000749d758d36d00b6d1080e2d7a982046e5cf7d1e366d5d60da505bb2bb6db9b794322519bc0b5b0ba90b40dd923fda2b250840c4a42c09b164a349b102889a14287e76a6c8a43401ba4949e267678b996ce78a26294a86d8c942465b03881d2c966ecca0bb9d3485d1c48de9c2dbe1da2d6493153dd41d2937eb99e07e4527155c0a851b41930a3e2a9a84ac0b9a96749dc735cecb296a1481a684bd9289c6048d8c972af2469342054b7bf064baa562898a15dc1c40a060c9ac99be7b2a4f34a857f144eda5ed2bdff22eaaa2a2089b82cb3e4a5394e05bca143df876150c60e0b529648fc35eda840fb3252c1cad3184c403176f5f22f1900510252b50620225414a643f82df4a707876d087332ad759cf07a6298e363c0ab4e75c82cd9aa89dd9df897e6205ba5724e2561f5b8c9ef3ce8d5a6afdba4374529f74526a9d8e364fa97f4e9d06e9ef649fe3a290f2dc588184d4b80d1c9e039a2f954fb738e76e057ace7ae2119fe7dc863662f286f30e5b6c41dccec7165ba384e47820ee18b6d848582a21247aaec5136ef2861b0095dbf94843f49c8f25143de734445207e639a729923afd9cfb92d491e1688eefc251f51485ee0c21b459383893bd39cad5c059520bc8c9a1b3721874472b64c8a94f6f694a0817f1d9618721a1bc610fe58df5504384801635845d288f3ddfa186dcbb004fc58013f5a87f60832008822c6d0b450db1a2957c3ab554e744296ee07b2a733a38c9f97d3e33847b1dc7d99bd7716847699a456d58cda2a816f796d0678b3a2a54cdd6add1e1563f39f7853370a770c513b533071074a9ff927b61548ed3ae1c20d2f6940ba95b7943290585561c77fbc53c30a96c70a80389f2d4a5d1d3b1c75318d7cd5a7b0a0ad1aa51bbba163cf52a025a133f562adf11fd589586d420c4861076296ea5f665903755488ee7f8642341f5cf4e708254526e3a69d7926afa0a3a3be956f54a3f75e54df5b14e13dcd183f2d551ee41f18ada057a752f4abb3ecebde9abd3eaf40a17d121cfab53a27659af4ea1b4ab739c5bd152114e11abe6b4d453910e89455cea4c6514e82b0dfa8a866c55af59beeaf4f0d56f38872059d553e10c8264556fa9aee21ff3c629cc3150e14caa0e56ffc259a559d5695dd4518aa6cafaadcce4432cafba0db989b1348bc9a659b59b6335abba337d759755f740f688f07116b51c78ca51087c907c88bd4492317dbf449201415685529513744e14286f98a538723f03d883295d4adc769e05013d77cb9e3695cbce602c711ce7c5650e75801eefa9b82242fd472aae888c948a3380dff354521619cd1c002c3064dc3b3b0552a727ed44d099b2b3145741bac10099f96748e50d3768821294a20ed033d61f574474ac881c992292f933806f6708260a5edc9132d8f4a9b3d4a9fdab9590ae279250d291a758be1e3ef4f0c1d2396ba6b83c5d822e3bab6688cbd58334a57409b0668a39e7945d4c950bb5a1387b38404fe5953d421f09f7ab22d655f85929a59f9cd5f3449e24302bce2e6a15a96d166bb6a8733ed28f4efa53047db6a4f770025229ab78e4feb8a21ebe94f2e107e905c81be9349436737613e193f255e9a5dee24db1a0c5651c1d2c9b66499fde2ce949baa77b62a1e374e972ba54c01465900218018569170555dc3072a499dd50661075808109225d061a707e2c3203ce0a2f6538aaf0b2c74bc93544c2fd9c775c59162a6a67f653a7744e59a4f315be9ffaac4f9bfaf81c579d210b4fc3713aa5655cebdd89697c2979d3a9027c15e5b659d27b98e915ebd1130deb7b34b4f993f57e40c398b79e5865ab7ad5400cfd8f84f95f09fd9f09a0174a58cb84d92c59ac162a527953bd76cc226d82e5d3b9f4be095a13fe9b25fc4749789bf7420e05322e03e0bf4efccf86ff79a711fefb6afe0373fc87a2f9af2535f3dfc5f19f8beabf171b32ffc174a10e34d80ec4b08c8dff6ebcfca772f90fc7fd6f26f5df8a06f55f0ef0bf9aefbf1140fb7968ff13bbff00c0fd6753ff23a104d086126602d8ffb558ac962972b5c57ea2bc74d44ba49f273f27b84838c490624d2f916237e94a2f9162472f9d7b8914bbe24f2f91622fa8434688b845c4b5d391ac143cc106c5129f98d8e03abf9932ee78818ed01f6f4cfe49a84f4137d628215f1033ee780a623f059d8498d854b6a4f95ab9c0237e49432fa7e880c9f35f990de8ded4ad5d724a0e62df9eb2d2ae3953b724ee5d4269ca365fa7d96cb507a592886a41f8f6d451bb02f0ed21d3eddcfa780aa2af7b7f96b8ea0924aba9734d48579d35ab9d3a47945a82521f321f41f8007a095d95ba35ab845b54fbf114e5443bd59a053796baf1b3fbc82967cbf301f4239206bd513b608bd7706c098328ddea9f7be3079a9ea25ca268cfd370862a7bd489e84fee85230d7ffa79f6ef939d824e3329c794946f61fa14edbb4508b63f41d6134871bcf9f625be478ef9b878cabf5478639ce7793540443f29db89c9cce714f431579aa2d2ae8e09176fbfd75f78f19b7a118b9efd857b43caef4774830dff662b175efcfa8b5f9733e562435cb9e0e22977f1948fa7a0d3900d678084d9b0e14d6c881768b69a7ff0f37cc9beb1efe51b0a53b714530e22268aee29ca89369e8268a5b19bac5d63aa768388ee0502ef12267ebc42361cbfd9b3a76e29a6540de7afa73c15aab853d029a85f269c664eda254f4646a7a3ef53d0f7e9e809a51f4f51c613ed543bd9be9dab74fcd8a79d6572e425e367bbe2ca45bc21e9d9af084b89ab1752377cb6d9624f891fed12ad78d083d17c39e5f6d30393670b20f1f0040f27e8ee25120f4293879f9797483b1081da00a3b6247131e876a8c222ed1085b7031327ee25d20e4b7c3b240122ed008442f2c182e423860e2e172e545cb1364027605080e46304924f0f374035542721e0f06e33322f9174e862a5c314cf21920e2bc8a18350cdd11ab69897483af430022a0d4fbd44ca810c31a6060000b7b0c1f112298726542f91720841094839fc98605f22e5e0f3ec9d10394c8ec59534f8c1f29f5cd956549a15a671a78faa5ab3648e384f6a1846a100c5ad8eb3e3e64a3b6ecd6a195bcc4b47418a3b6b3a5b13b2703a108528ee748b7229ee17b33365dc2044a09e27f368dcd1937ce9dbe9e71f6aa7b24f54156d747c206a07c65708a881b3bc0df75d1c85c3c5651cf495834e6ff88c735ebf180fd2b3863031de282197551f96af8989d0062704c2d271c369eddae1aa44dc91feac72b6a452d75e171eb716794c1b343034df42f00096dc71c70d86479033cdd7d7245d3bc8903790ae1db766b5d7f9ca01c67690d1b4e3c689636de2a938d65a259237341750a8e5850a62fcf421849fed63bd818489711819991b39dcb881daa98e03b5e339825c99b4284abb5649cd725bb3a8ec70c7afc957b6fae50043236e4dcdc73b4430945d11b523532b6a5647a1d5788d8fe0352e6134a1d3388dc8b37a81c673780ef18655159bb8d3485828f6c0ea374208c6400fbfa60673842e44b3458463ab1638f6557429eaaf51e256e7719bade67173168bc7cd431e4ccd42fb083c9a7ac478dc5a67dc1d37149adc91845b0ea711c1188dd7885fd38e5b4d6dfa11e69bfee542d4ad76a1b9147912e85323ded86ef51a722cc56212d5028ea73ef6ecd45042a35aa8fd3d44c01f799e8a2b1752b01a3ffdc8dfa446e4f1006c07d36c354a015e0772a89d1a988c223c12eafc1caa85160b762805d41f6f78ce3f0fb42805f48f1d78ea5ecf5311f45043bcd3773a9d4e1fd73226798e08f76392df61a559206a88cb0a3b82b04a5ad976a0b1b2edc8b2b23511499dd395a9f1e8b10690cb0fe52cd08fde836381e31a9fa0974c6db6642e4b9e631b1678dc503b3cac34abdd85887dc68c9be367cab82e505ca2b818cd947147f0c7952d478d1f990b5050514e4e8e0f283e5043e8bb10c99bf61d396e163b7618c1e3b6b2edb89d7830b5eb84df71e37165655bb251af3247cdea55154ae323a3d4ac4a65a834ab65929a15448dda8ca74cedd3a132351e4d3c9878dca608c69ad51ec48ceb52e4f3faf99a98ee88f3399cc6c76fb6b2ad92bea69a99322ef51933ee077e90a62b7f0049dcd19364a8c8d496ea4da726e92cdda64f2c265bbafdf8f12387cff9354da09f0efefca414fc59f2354dda57237eb4d99a353e828f20f2c8d91abfa69f5e23f6c0a8387eb59f9e23046353e640503bb53ef1a466f992a32029004384e4b843f2260001f65e95ca9dc5c2c1e99c6f2579237de502093c49180b2f5e007be26e8293e03d309b70e5828db39c25f29420d2e0f28f766667583ebde5322e4ff0187fa1e0302edddae64b874bb74956a95f372edd5669d78b4bb7b7f9dae1d2c5a5db2bfd4ac1a55b2cedba2edd8bcd178e4bf764de4fbf5470e9de9276b5b8742f68be5670e9decc63d22f1e2edd73e211cd570f97ee157951fac5824bf78cbc9a67f3a8f4ebe5d23da576590f0120860000404813e38e012086d2bb8a0c4371d5027fe843f843e91e7a288e2eae88cc5126c67b1ec67bde86f7fc4bec47687542eb23cc09656c0471b435e278a55d89e39d1147150e717416cecb84154bb362424e16724b426ed62ce92f21e7a459d25d42ae28e48c42ce16724a21770bb92b61173b859d17764161c7a459d25f6127d42de9aeb0039a2de92c849d4fb7a4f708b9a6d992ce23e4ac744bfa0a21b7a442c851e996749c90abcd96f414422e4ab7a4ef0839a2d9927e13724cba255d47c805cd96741442eea75bd24f08b9b05ee9967456586fb325a78f76f6d25269d7d84b6f67fde241148bc57070d22f9f2a7be9164abb8afae593a20101ca4bb7346b24ddd6da75d42e79f403a6976e6d36a95f1326ddb373a967ed5ab1ac59524a6f57b7c44b6fa6765d6957f704cbe424226a96749aa03bda9e9f52ba9dd958d968835e3adb9909218f8d2031966cb02437d2a80246829710f28035180f0f15f664c52e9f04f1c98ac57aab569ad52dbdf4e6a10367b162205ee22c346326edce4eda05a55f122699a6c212069a61650aeb2dac569a259d870fd77fb4b397d22d91745b24ddcee6d08d259b6605f149f768c055ec154dc59c2f9194ec80d24ec2461435e093365e3800132cd9c428b77dfec75fd0b66072616e835e38002d884882d9f06b827d62948b1a3279cebab4d455be5d76cfca33f014e10269e58182623218c429ae18457cc165d490c9a114c048208089f0113f2611e339141146e239ef5008609f3570961a384b92af5e032794d060365c8500c6853270c7b158bfe40e6c5cb50862c2434cc45cd52193ba22a038f1a3a4f2b12420d74a45a3020a8ac9aab812c27df52aba0d8f243c2613572db08b37465c765b4b13df2a9c33e1d25de187a525f0eb51e5caa327464f8c4ede67a3c675273894b823d398496b882b8f9c14fd74db9170c5d010576fc6b8f2e8c9cf931f4ac6a52e8f9c30fd7494d3e9d2579f4bd84c010e500b8bc0608ba9208c0cee8c339398a2cb932409b60ac39533ca013c045bcdd74a5c5167d88cc8c3b0199f0955f3fe5c9610112ef59199f053f99f0c282353652a088220f8e1f4c091ec24c504bf937ecd783b177d0ce555322ad50d99be4d5dab6ec8342d7d83f1ed174bcbc8c8c88c48b805d0813ce8f2290e521098dc7e7a60010ef206409401032d7c482376052440b36c49b4dab3ed0b79a8594ea8cbead2002528d78b4f717cf1396d0b659acca7bc59ea5c87b161c36128c501c625bb4aa57215fbe4c9939d3ffef863ff18649041b07265675a930c93cc4d46e6c68d1bb48e795185a34bb9f4238f3cf26ce947a6c18833340e6f836dd8105fc20ef0342ba88c3bb2cfc8414640ccdeb5783b07499d21f2f98756bc0294e95f480392197e9e77c86eca53620c237be74e85985ae2c4e10c8dc39fc2b17178b6f6de3943e3f01fe8331cad4f2c89a622987eb8713a2ce540535223c24645908483fbc01a82b9fb6ae0f9d3e9e421a97ff2503e3b69d65019d79fc98e1e6e0c566e0d5768d2d3840438b0810850b04609964820044c5c590ac20c8638818c01102fb5cb0a12bc8444d183444b55fcc84943cd44273369d7500ced5a19a1802d8956b372d957a184cd8412a66a1594fcb237b79892e28e94b2f5da619123d4bd3a5b9b163d8ba422740214d8a0a90a170c414889357c92d8210536d0e2b3d96ec0d8041288fc3c36e7b6ab7f54f211ea421595e611faa3b4b1ec9622a3fd51da8ab80043bb58cc91556c9ac51d8e2ccf47b72ea7ca7a4d5939cd92dec3e78b36dba7f747a72b604121a0a48c2742a0240c2b4c4029c20a7eb81d3103202b174805ec9f6490ad348b995c76f93d3f4ad740cf374761669e4bf366639f494c1dc43f658d160588090b17fcc84253d4c0e1471e3ac222e84786c2453f696c549bd987f4f38fea2cebe3a7cfd1a2e0833b32104399aaa31ee2c8d2d1b0e946e6f4186808228fae70f2f2e88a297e3a015cdec64f2fc064a6729374d919887f54ef17fb3011fc82716bfae9f4f23233238a279c2069413885397dc642eda23e819e82764e16a5cd1212df11e9eda18dc55e86aba719dd24dd768ef10f9a51bf90c823f6d3e9e5656646144f3881711807878611046ad7a438cc62db17b4564ad33db83c71980892564ea4e92aca6e8d9686a600a27422f24705640aedd3e58f34536a3fd250a680bc6977a571e7d1335f7b8511480419ad1124248b1a8e35ba19317172707ae4684113a245ed1a515952a3194929424890901a13c8195d9a9753b0b0c086e36cbf5e4ec1b245930d0375c30546b3d016c10a2c576c3da44e1b0151bde42b5b278e1512b9278feb6c273b9690fe4edeb4b3e0c4651fbb97ac5aa7d34bc34f9f20929fb47680290f6511f41af7c80a2b3f761063e986b822b4867cf16d3216a9c3de8cc6cf0edffedde66c46e3db3f21d3a588e38c4bbdb2d84143b8541c9174f755491b13e2556fbda3cc313ccff06c257731587e4fc480ea5994a173e698c5917d9c41f59e739e385a6bad373a11d58f453c1103aa1f63782acac0eef918c37be20c2ad0db31026d1f559e739c2855b26fd660430d32cb4b97547e48f7229ff048daf9670bf5bb45fb4cc327bb99c526d24f4d272c39dc4ee5cdf495d2ad3ed299ffe25620b073fe1b5503bfe735fc3e47ead4e93ee4ab8a215bd359ac30c4e1e27190bc996e0308b77dac5b481d1beed7f847f5e9758ad439ea17e873ce4ae5a7abe60b146bad265eefbcd66a35d5f472e6abdeeaadde6e95e9a74b7913ae8a9c722609cfdc1f9d5d7b3b38cb19246682aef41134c027bf94e79d3c3f799f943afc7521ac0b6d4fd44e0d9ce5bb29694b9de069a5740489af8a4cef812581754ec386d9d006fb5dd88921c33ad1c2aad864e5c284519f302af224814db1a74bd23dadc8a46be4d2d8b4e04e8761beacbd37c9936412eb8bc028b9238d7d0983bc19e2b2772f25772d630f0cecb7ab7cd2667cb1bde7dfc46996c79a2dcf69e8b3e57d2ba5dbf9c73368be6e609ecf99ece9a47d9c50a2bce73345dc2ad42e947ba07b3e99b4eb73cf49bb4eeef924923af23d8771e28ed25664bea464cf6998afe99eb5f7769e37ddc56fa07efd86e92ecece0569cfa5f30c92375e8bdf709dfa0d2e3e9da9bb70fdc5a9b7882eb8d8f0c9b6667954dee379e2c28bdb10795ec43b5b9e7b4f5c78e17902fa8bf8e4b4d42ccf41efc2fa12d5022b35cbf313ea25ea34839ae535d37b1ef37cca3c6f26cfbbc9732e4485e017b2986790d2055fde50c25c42099b45b3e5f90d574af7e4fcb3f67dd0f4dcda7b552a77d60c7a8f8be6db00c2ad2e6d3c518617dbc908a5db399c0fd96a02b4c762b12730ce83b4abfa91a4c2398c1397f3ca39ce7c4df738ce47d67339f286a3e2aa7309ebc42673a574fb2508b7a698be4a27372b9db3e76cc9296be9a49c19dc934e4b6b4f59294739dac9abea2aa54b7cd3b2a4b49bb3ab9474ce39e7b474ce39e7eccead7c714ec520b3259db356ce39e714294dfaf8f45e27b99f21ad9ccefb78b9bea3dd7e7aafa3dc77684f56367b4450caf381dc92a2f44ae6b88a83d3230785c3f3a1bc3450ea469ce3ea1057873c1411fa1e191ff7a495f3c09377929fbdac0a820fec644b6d49d1d4ad41e6cbba6c97afcb72d93838383d725038382a481665a1859fa16c51ef401411aac25305dce7fc9e5c5c503bd55fc091a6734927e75d930b13aa28a59e16358cdbbd3caaa20aa46b5f1e5521c507c5055f1e55c1021754c1e45e6bc10b230225282d665a0ca56e1543f8006251d452050f3f7cb5194a0a16252759b7e45b0f768a5bdc597b044eafcda1d6fab55d510349e79cf40b07874be26c1d5027fbcec9b7774cae7c940ecab777b376d574419dcfb777b11260c9c12d714735317e8cbeddc9b4cd9a2cd6b4e89b367d5326a2a1afb7bac4cdb820ce6756a3fab344850a4da66f9f55661137c4011581fbf9a661aa4a494c3ed6a3ef995af4ed7506060e558d7d5bb98561821b3e52255bbb646adf3e522861b4d3a076c18c1408cbb7cf26267c9c56be7d2eb5ebc567d2a47db1868b8f138ad20fdf36394f0091b67f40956f1a5af07d45b684856661dcf8919d7c3ba91d35956f4e62c2553e1fb079a046aa9ba8a85da836b24dd15498fa4a63910d7dfb387f7e851fe79535d93483292668da41e90627e802f62384ada93603201df45027c971027d8f0a9238030c28b418a3960556e334a89d1a9ac357a89d1c545a4e8ac59ec667503b34145c5159395ddd72f8d5ea46c4afc270c1af1c076a67e51ed1cfb80ab53383a3e971f80dd40e0e95cba0765437a8f81b1e83dab951d36882c9c8380c6a47e68a1f0306101fe336503b313030187f41edc05c2cdec61750bc0d7741edd8b02f7e513b2f38dd72b1810b172e2e24bc8b8b5f1f9cf12eaeaa82f42eee5f08bd8b4b19bc8ba7503b2eac1d4bee28b1b89706f706e002f9b1c75f974afe3a6d978fbf77c98abf5e04fdf542087f8f7ac082bf3ec0e1afb7a0766e4eca51a89d548bcb167c8b83a89d16947fa81d9405611e1c691e74daae9b07c11dace04157f140870775508407fd84da019dfee7a753167fda39dd9a2a66ef7987daf128b53a58f256cadb5b513b9d52d053cf01197cc4cf49bb2bfa1aaea181e7e0a870708a7c98b9740926a2c4a04e72c78f344f9d52b74e3cf59b832970a0b443fd061183303f7ea4b1d1d123a9881c4944375072031c90e0dbbf9c2c35b51f75d020043938a2c1951a1071540320d860ca370e13321c0c148bc57ca09452974775f0230ccd833fdae8c081ac41007e944634198cf1edaa2eb2f8769fc1ecdb593370f2ed3954a828c940055dbb4209941a6c01c60e52469083e88927b448220d2564a8e405a3a8e9f610e28e2e039f123a5577510f74f2093fc23ce5f194fac581ad491a36e0020a8dad553268dc91ba0d4c0c90beb9e042e85b65801b1223b035894959e28812475c2102880ba618ac5994ad700289ee6ea9d3473180c1534b290b822ae59fe04a070a476a7cbbcaf6ed8e4486eddb250e4c199ffcc0656f95ac4c8e6adf055042a68410d7780bf812a89f1ae9ef10e6de7e9e1c63c078927031d8f5242ac09ea09c874e61410d6eb02430473b803d697724dcd7d8388e6327a1f5c47efa749e47f94c350a154a9844a18c748b7da9fe6783194fc162413b81548b73ff004243b3d8a768648618422c965a88d641940ab0a4a221800b682a20fc43023205f609c81be66eefa779760ab48b3d15caa316287d0ced72ff8fc1499baf6062662766283133731b69177b100a4cc19ad387cc9f2821fc3d9a85d32c66d903a40e09cfce321fd83bf9178487903f1ec00c45ea8c5cc4b784ec2806e21f19c7e40dbf78493f807f300eec44263113697b1de40dff27a4ca1ba681bd03ec4662105f706932694091f2c60647e56a77d7e6222662286c9b2d9ac553a649b642beacbff094a7e2a4cd1675eacddd9304a0a269ebc9362baa95052795698bf2e3ac629999278d326a487d8e226fa88b34b8cd3463b59acd96943459dce2b2e3a03e6df3b500d9a24e5b9c494ffdabab5adb8688526aa5a9e929a594ce504abdf69c3419d0a4b56b751f867d28c79ef2929b44ab519f73ce22f3e5943abb8a663281617c3c69ed2c75aea2fcba962cee031c5318538ec254aa2954f7ba4c8562cb09bf420250e10b38234640b6aa9f4e44ee1379f9596154e4e24ee77ae58fd09f35512e6a67825fedd0f824c78923128ee3388eab5cd36e66912709ac26e16e223a9de9d2b6fc90a2b5f7aa544e6752ae3caf63ea5738b33e16c80a11c18893592656f6bce439e899879eddab9393b56bf49a80da15d4aef1e4f33edccf13324ee899e98ad8c3aded9adf577d7c0ee83374819e9d135667b2b17bd1d86c55f983fe48396d36896f93c97ff8870e8eb5f8f38cd33af84777a28ee79367c38ea98f54918b3b764c74a85b4c4b204f206f78564104a00e4bbf28d06ca16186fc41853805a6765de99a96dab542397f3d859e9f1c155e3a9b2d8e8ab752e95757a444ab52b362bbf2dc25b17b430f86de9257a559ddd26c7167a58a9c387312472bebc2aea9bb226f3a2cddb2a2d75979066a21fec1f9700aecdc5c399f672a94fa19a6beb95addd66abdbbd231713e2d22162bfc638a9d193205761f34e40dfbc8f120764c5b5ccfc7934fd3b39f7cda253bfd784dedc2d2ae239d23b1a718d31c4172555812f3420e089902bb0d39a090fbe19670419c50b338213859b3788526aeb3db9895754c5dd3e9c6111ffb578015d092246576427465b674615e702990460c3e8c481d1b462420a518529490f1fc35536e170145f1526a944ab79416202bdda464eb66a0a96a6aa2b3900ed16894679a486794ce26ed59088e9f744667740929e9ac9d0e499d2e92375152229dd15913a944462d40a4820757e6f43175ab461c6ac8e7f3a5381ef93ec2cf40f3957220e940b439345f29d148f751ea471e62252c4052cc39a7d4e9170f4d289ec643f3454bb0042582e2d91b2504c7b74867f2865dac420da59f6217358b3de512f50285a53a8cf98e42722d5207e5ec7dd42f3ab32707dd480a355f1d4557514d254a44e5d93b514a299f28e58eb5d6aea37655a319561acc4b548b358a91f9eaa2ae89b46b4402ec6c44eaac7458b9239de1f8fbcd4db17b552a77d6d746c8a533a018b9de84e35b6ca29a2ceec8b416e794b3b352bffaa85bf39512bb688aa34a1c6f0f1d3a88ae55dd1651a4e28e4094465035fab1a32c1d9d51063731db19bb317879840653d14c1ea971f4dcdf519ebdbb66cae5b8a276a4caa5013f444d4c673ce3389e4c9a25b53083e965f8f2144544fa48a51667e4f032accf280448d690cdcba334869e51280548ef161fd02cf61a86f4b713a1dfedb24318e40d3ba594555087508536ad543450544444fd92621419b54bcaa3294bf8979e6fcf2e67cfda3532ed87dac52b960ecaa48be2479045ab111535cd574bc320755a5c09e1dc864712dec55db5f3113ff2113f7d9512795868066b11613d709a4544ab1109cd60ec41dac5473c6f01e5a5adda7808e1b3fda29667d8e36d288fa630f9ea759ded746a5eeac09158c0d0220a18e860c8033a4aa45d77332a4c428fb8c1500e86497298c104067a906631019ac50ee40342443f4cc1848a2647c098032418ea410553a668620918337b8d15770442009c2646fb643a183ee9fcb361ce27830148ce1066418058b1484d15362c1dedea2923826b5d2689eba9429a5311a68f4058456e9e73115dd18fe07b27ffc2cebd93b86a61bee743e67beed95015bbd3e57f4fbc3c3a22fafed17f0402839132849e9f1d880bcc323edce9591fd26f1130550790a8163ca2b722b30e34ae8cd175184a781b4a1a17b4b7e298e4adcf39e79c6ebb2566e28bef4456b3d88688570c16da4bc2d8e9f41b87a1c50a07d2acae11bae395f5b832a9c38ec330489dfa752584eb6fa78053b73a42989b8491183e697bf1132218e4cf6fe71142510f1f7a74f4236df226afc8a6d8947c34ea18af6ca5a269560e1b89a1080c0768d7ca6d8cc4500406a903a793c1d24b9731ba3712dcc6a57f9452fe611342acde40696b2fadeda54d7ae9947b1231c588dab5b2d58a84e247f02b163b3323a275912b4abb5ab44c8824936649918b7b032218dc6024780fec7a4d9a2de9d683f48fb0d650f2e4724279d0bfa176d12174c60677fa0ca687cbceb59670ac4b2f1d158ef5080d8fd01f12db89d84335585c96f7248e57e589edb2b24a1366c8beaf41464d917dc86835188d0f301bef819970040e110efde1b2ebab678e98a0b46727131b4f76d168eda241586242e5a5cbd1b2357ae9d966d2ae713a79e97205c303ba226452d36f1f42bf390b138cb846664bba0d1177d5fec37b60ab16570ed0711fee428eff10799eb4e7788b2ee8b80ff721f2e8780f6cc987fff0b163b37691f0d2adec588c65612cca04ddd96c49b7012cf3b28a27641006a770a04073c987443501aa8904a1a06812c98322098a2fb80a28cce8bc18cff8803a01b5445c5469f60aa48e0a97032fc6281282b44ae40b114ca893289c60298c5050a0381dbdd480edad638a020d49636c7da86cd992ce895554c5bc94c10c963c8be3fddbcb2aa430e247ff8e5508820090621004e3b1518c8660497c28018410409d1558b104d3220b1741302e8a74b8c1b0c4e08c2558873850609ddcc1113cb8c13aa4f121059f942e4a67ff6879849f4ae9b3a5944e45ca3c7bb096ebb84ae7b4e14cdb4958e79d8475a15fd6b7e7d65ff06ce793569f4ece16e75205f74a67c7b36b77f7cea50e4efde193364faa4bffbe1a3ee9bc864788d0efba9025ab82a0fe3c72f2ea1f47c4fbc9b2c579e51ab5b35a00e89fbfe02f9c3e8c5b836cf25cdebe07d6036bb7a7d0e7e437f4f95cced603e1d6209b1ec9942a74f30b25ec14da70a25ae0f1b6a59413d5e28936f4a92dc771734ecb71f3642dd755af539e4c7fc23ed932e57c56e7421f4e85f62961954e2adad033cb9c9653686f94b5764e3b7520ca233e395f4fe84743fe279cd3f0c8c78544ead3d005962d8f03deb7c3207b5243cecb8064fe74d6f7c0ac531491cec591abdbd0c73a0f4f6ac879245305aea74349c331c9886ac146d79629dad0dff9cc92a5a3b47b427b9a0e4169486560a73f82dd0c7d4e521b5a03f3d95be8ef5644e6773ebf73ce2702384e61649681bdabe2103fc24f19cb5319aab338d66f7188d409d168018bf4ebe9f38f58a9431b011ca7d0f4a3201fe11f394eead01ff29b2915abbc69afb55d934e2ab264d5dace36b44ca136536a4353dad350502a44459f22c29a2805f0c8fa3324422d8b473ac911a1dff927398a2ba9100dfdf41b26aa85ea53a4cca184f44cef50be9ded9c28a902aa4f47c0c81d4f1c6495a75fadb82a18fed1b19f16f54501267d40bf80746b3aab5b4c439c664d2041d806a72888055924e1822eaea896b8a3cd4ff9853c4de36c51851faa28510ce8207386297b18fec1ff5f7cd2e653b5cbb905e1b35f15123fb6162da039fa9635544f69c3a838ce30653f6b70e5d7265205202ebf2c6c2eb1a045c62465cfa21cef8bf3e0b0272e3ee27c4c4ce7323eaa3ec63f86f5313a3e06c6677cccf918496b8939fa989898182b8fe3468c4bfe91f218717459f94bd864756bb2729aa6679f59c1303d4b988d2acffe727b76172b77291544d1b3b7c49e1de5f3ec60d0b37f42cf7e9a3dbbc764e8d971c884b8e1356c526b72c355611049cf2ec39ded654209e36a4741d09ebd659fa4eb89692e069fe41ffc83e573884482d823616e011c4ad8a40e1b22ebaa487b0f2c090cf64db0869c68e50deca373d2d9c28956c2a8d864fa84cd9e49ba1b053c38725082192c092705f183046c7a873cdd0e60496056009b229308b034c1b62841900cc6c3570c61060c6049629ec064b33082ecc410c6a0c13a5c553182713a1bb290048c474a51c389125892ef0651c06cb3f06ebd1379748e502308968453c304b04e0a11866ab0245d0dce8075a26c167a602b172c0b49c0ac68c5d50b9d7bded9d50bb6734fb49ea46259c35efb206a87a3576e15693a950d67175a912767c91342b0249d14b0ce7b60cd6a16a67b9d22d8839b8e2b450ff35dbb82f1c92124256cede291f5c1a884516e211f8c0be56c75e0dbb977a60c48e6afa648a45d039f0c8d647e8b2b22dea20df36590cd923839b776b2a351a96c5bcf9eacb5765a18ef5e0fa4e049ea506fce3b799ee78122b537fd4f4fa75927451199222dc1c9632b032a69542aae61eef591ce7f9dbcbbd5e0b4943a379f7e953ad2ab92ce9652b2d7c3c82fdbf648fabd6ffbf46f7a336cf68f63b17fb66493171ac6a29cadf6e25b29f1ee6e969205194813a8eeb4b32574db3b1858df8939dd6acfc9c949e24497d09c3ddb324d27509245106c50de345869f8a53ccff321b2869d0c4723d6b9e93535f9258a6df0cd2ad39bdef4e6c9e769ce53cf13cac7fba7132af47a69fae9743a8d343fbd0045fa4503e87382e275024c7082d46bade2e7ec39ed3cb7968a2050bd22e8819eaa747047d5d34061980e8a2390a43bde977d7bd0de1bf652bf823aa791edc2abe5255bc44b0095f4500690cf89e07b3d3bd07bde32178e3e72de8527ff3c48f7fca96ddf7990693b09d4c52673489ef32f65802f253df7fc74623eb1683d4983e63c9d4e3e4486dc29b461e7941ec12950e7c2b1959e36aa793e2133fa1194e2adac05cf7e816fd29e7378cb56056121d0c9cb88d2284789a588ac49dae3348e9e69c931e268659e6d88a3eaf9451cfdd9451c59cf37258e393d6be19a7655cefa5c8a4b333667f3e5a2ad228d18fa4a1ced8c385ec7218aae0a672eaaa4f352cfa4df10472b8e37461c55d261c4d16d8823eb451c715caef494385bc4594dd834fe79e9a038e6f88c38585857dc8aa3aa6b5a4d75e5cc1172d36c49544f1a4d83b3a08ff3393b9fdcaa76d1cc4e1ce90ccdb5767d4a89007183643606ca745ba2485de55cb670584d0401c9624544433c4bb2d568f2559d631a2eacc9d9d3cd459f7cd938fcf41936c3be992b57baecbe507655cddd1305a203d4826c966a30f831e7698badca8fd2a8369354a452d3b02c70e551164a3f9d8a2312fa7532285a2bf3823bead061d3604c135a66edbd23d39666cc331396507fbbb345fed1849f53ca9453024d2a9fb481d1e2b6ab6fca7e608b901180b1f47dc3afa82153861863e9142269b0599ea7c2d15b2cdf68419a6f53769bcd21293e889283a774064e868a8882868664440c54d4358e0d2db58c16d404c4746b4a62baddf85603b205258d3da3599beac4b75bbbdaaf53e71b4a295750f9c254d8e21f056f88029da2860c6104607871274a8810037043d8a10a18dffe41662a1c99360486a30c4f2192f644292b118a3f293eb6c22806394c390a41d87405165c6451cb814970fbe5d11a3e9c452d070120c57e62b12c66bc952299dd91b403075618c54009e88ef46733c126f8388b5a0e3b6e00341365b22865a1f2f2288bd18ff4b3c0e0b99747598a5e8b2dba60fe2173f2124926241b42f6d34396670727f07113179481aa0633f0c9ea02360be63b8232460bd2cf0fd20f6820fde0031b4cf9810aa41fa020fdc004e90724907ef0415272e5680d19d2cfede5142f925efef4e0655e22fd1cc5b8b86c6b6a77c539fbc8ec3c7e82a6d3e4cc17ab5b2b3431e784992c9bf3e7688da0771962bc2f7b90bd44e2a1e9a5df78c8c173043e6953b9ce7aa70f44b5a4ae0b3b8cc388e38bb3b82202e3ec2c8e361cc6639c07f462c6884fda25b530a14b78433642b19f3cdb711cc5a5271adf8a572c828e12794011e529e7f944d05bbc07f6f9f51e9864b2b33583e5d2349a6012f664ecf1956b0969e0d8fc5afc890ba827ab057c0efa93aefbc41cd6e7a3ea1347d6d7451040a0c560125680d9a2ae23bb9daf3c97309e2772b64ee2ca138bf8d0305b54882c5960a0c8f3891c9b2d1d145c0993556012d6a3c407b5a51a173315962431e7035315ea2ca34e03f50e28c142d281322ecf382bbeafe605352f98f4c5d59bb2b325bd86d37954fd9c5f3384edeed6690780bc912c6f6c144b1cc74d8e72955bd55afb25cf49a728847fcef95f0d226fda69a5d5b39fe385416ccfeab35269d9aa58f3053a4e90db5f18e45a00481df6d5db7839654b1d2a049574f9e5b36f07710bebc4d172a2e46ea16290ae05fa53e4a48e1764896bd4093a5bab156557abcfc9d54a75d8d89871696c542450b528c005c4515bd44f2175e1d93329d8ac5b73c4ad36055ec775371a3f68d2831fccec123f08c2c1f98192205a5a6aad38e99684d22d6b254ab7e48f770c2b44b059dc96974756c8e83a8f03c28a0e829059e9e287242b4641dcac3c116465760491151f9010e2031b19690821048c2232c210e2c58d8c192c899131c5114464b04008213da8916144088454591a238d248ac6581281902f646324755d87746dbc3c12630d31d0f0acdc1c2f8fc4c04197c65dbd3c12838acf8b9b7a792406918e9753ac8cc1716af6491b9ca9f2a99ab2ade470323333b3b5ac21b822d53f0b82ffc56526aed5a60da90aa894add4954d2c15a21101000000009314002028140e878442a1502c1e0983a67b14000d849e487e56190b942488510a194300018000200400460006464c1300888517a3e66db21ec41b12d1b522b31ccc48973e666ae4411df104f1540d4a45ddd62aadaaad099a605449556d95a32af669d2512d70a04ac7de8ecd48275668daf4ea404931aab268587520bed8cbba162b292f95ad772c633d495951b4b54755ecc91cacb84f938e6a08a76a8aa76a532ecab610b5c140946bb75273d24b7c231d18e5647e94c281aae228798fa8642d187628a23e2ddfaa698f1436b6ca4d4ae9d88c7b2ab9011c9ab7c746d2842165a564eb0ecb784f88836a9a9252a9523bae514fe0b08c7e823e60a605cb0d723304880e2f1aecfb409402b8763d793349f5187ddbf390151054b17f57a647baf31003f89e9720bcc8a162fcc53ca44c0bb8b050fccc9dc0ef666fe11ed00f2a051200deb32994f73bbe9455380dad85af97d3e09f00fbd6aee9e3d0ea0848684c99ab71a7598513f395dfbe2f73b288d0362f4855579eb965e710b86cb744be0a1e88d631de9c78d92521907c2739bc3cc9b0d197707e2cdd6c68953579590a816825230ad587f7158243e14db61d4ff132cac32476e734b78621c6862dbf8b0c2262ab718766c4e23ec9f1293c520069d9576226bb92b24500c3e8ac6582b445caa26139df6998286d102c2a7264357dc5df9130c3d0d982780b2cb89de192be91c5df18c65bd39d0e6c8af160fb000eb2e7371289cf161f864ea8977037058063acbfa2f624f641ac7cd5e599203660a449a3d0358fc21526a768a31402bb384dc51090ccdfc77db5bac80902d68a7d8f05414c207a027d5b1ff0dcd4a57e4550c3617c9996b5639a3ab414ea0c0910054a6e6373a7b77afb9745921dcd784790401ff8c841be48a58b136bb2a41c6956b40a258b6628cd8c30bc701ed45baf74267e7e515ca5d67b28e7604d147da84b7dafe3976f06065f98b242cc6a29a53836b4e763753b6783269ffbe9dcbee847b36a009b02a676990dcf93876a4c99cfebba9f6c71598810f1a648cbc483c48c442dc4d6427b8c6d112a831a9ac1bb90f1d66f2a842d8f0996aa24798af4318fbe35857d39b1694bc65662d828a23f29e9b40e1e67d48b869f5082267542cb55b014c7786894cca042f9600b5d9d8fe5a7ddf9b89abd72d480aecef6fb9d19e9cbe2f7adffd261e9143cf600f137117bccefef1f8545f28d19130f01a056cbee1428b3bf86b82412a8e0a50d339fa302ad8c846df9a3910ae21e9ed46ddb20242f060e23257c355d860dfa926007d187da0647f65a7b446016344203c352b20848dd165711aeabc78470c8bc3874d56912b001cf6d166271237768ce49f59d5a1394069388cb191d2d1f6cead1d9e8e49c951aaa5e68eab198d19970ce5dde9036a80102dc7f1226735bba63cee01a1acd84099c87b58d19fc04d9e98de96af2b5f405b82f2b4e49fc9b05351e9c72fa95e6ff6d45d7bf0a3e582ff60aa4a25709c8ebca78b760a21c28ce72192bc3a26461a52d1f112de3ead163fca7a1b8eae4b8062456b40f32cb7fdbcbc9300fd80746a4ac30e39f3f57fa2d7318195e5bec37daf2f1cb8c9a3036fd5183766b231f4103c2b0efa20ed0b8f7e91687982ca4fffddadc2abc5a012897673f229a4d2fe3635df3b9930dc81791d79a6353481619f245e0c5d87fcc19d6b49b56ca65d9c3f793554bc7e3d39aaba8baf708fc7083cb74be4a1feaa74ed14fe604d3d975dd9b8528f892b3514798e54a0d15878c4a0a4f98840ca649131a77c415976232d0ed6939fd342dddb83ce940467d32d1bae117f9d032371adaaf5fe3136ad41de9a7ef69c4cf40839e961a9a1c20b7ec80bb7265bef11bbb4246d725c1ea27d4ab9e6cc2ccf8219d2a380bd7205808393f1ecde0b7b69e4531e91c3ac74871d236a45b658fb942ea6bcc2b144b46a62c8c04cf07fa16595695ef997c314ad8165539f00235930fd4eac972e8d9111f65d96654b649a4ea9d3a80cc8ccac07447339e85d0368b8239020939361b67dbaa8b8b8945a0d8300d8dec0848c5277593e09ba733638e16dd8e9fe1c648dd980a323788895b6358091929e45fa6b4a091b27dfe98639dd201308ded299ff83cacc45ca32c2f40fb0864df653867e730f6913901edb30d979228885eaa174fad6f6ae785993606acf7008d5e9840e2b63fdeed90b6bc6244f206c3bd5b8dc6a219616a23ba5ba86bfb96b5f92687c6404add9ed413885cedba61a1c2292e6397ba582ea393d88b42449c3092dacf7293180a8d8cdc35619e45f18741d8bd40d76e215417e24f532b6c7517ef2cb944d2c297836a4bedf5c7297254207dd560aafc07486a33d864941da2a228462b05efe0251da0439ba712a3cbdb91f217213dc19f461f04ed2843ea41f0ea7f6e41688eeb528343f1ace2db11d094dff3e08861b22ca8b88843d79af0f9870e6230727d92a451546fd97599166ca560b77a0e8c0c7d05a1de3004d8053770b9efc3904ab606005e07610f7d0c3f27343f4b71baa7a6b860592515ee85d7ea262960d0ec568890a0ca4094f54ced73ea73386475d2dfab8c60d37d257c54505ab3c89b0068283eae1b2248c401684b2fb931cec5ad90528754c1d51079d1538954b9128c56490a35ff7d3094ad88c0a0d1eed21f25e911740baefe18ee0f245a185aabff10d5a39ca49cf91bbad27dc4f054204f4ad8cb87de799fef1553f997456670172f2c2b1ec72092509b930b91c3b5097c75ef44851831f434a4ca6d0c10b48fc178282ee30faa5e765b13e073cf191f9542909433401365c6ec3ef996b2749fb7bac5a61a0828d15f020e22f266b860e015630ce0000c0448ec83b756135c305b81901fa9d64eb16ac927b3af19d3a554fe4e0ddbc862e40ff739b8a44ddcb6cd3b2744ad2572bbdd5e5d6987281ea64bbc0b1334500af3e6037880e7ceeccd6267d1206394314d224e4290b3eeafbf2fad7c578e827b72d9be48743c2ddb72b33ea2eb686ea369200b57d84ad53369098de484e3b5a6ca18d6d60ab7d8b97077c45728d816c211bdb1936ed19bb8b96bbfedb9670c9fc6902c026dc61790a280b7d145134f30ad90be2129a9e365f6636358d7793ca1f0105a3f136920adb9fbc6fd09a95795d19a7b083aabeacbd5812ea5a98baf110a90fc94425ecacbe4ffe18dcc2f044fb01bd02feb8036e52910e0fbfe5fc82bcbd72babd90284936b4687b2aca12dcb8a02bfbcc2a24b056c5ab8c65b4f3103dd85c2b7c89ba53e13d713e832099b5e8dc78dea6fdbd57508ef8d32874fb7b4848d6e83ad496159e33143bfd09df877b48cc8e97e389760f3d53e50b74b1004f18a190b691186351c1cdfcb40568e1f0ad05671e9fbb632761cff1a3df281d5b057fd822de56a80abf6c9b4ab2fc2d8600a9a5fc7f7e406581f13fe401e14eb4f80e6086dd703d62ad68bd3b41603acf3beaee98f2f7de55972a65d5be1dce18aa53b04b7d2a0a7c0e8bacc5d68be11955d12e6c1a4123706b370fa8ff659192ad7c817253034b99db8ac123129e17f5ff8af652b7e180ee53a532cab5d6547f84c928c2efc8c16afe9a10b3605de247603f81a06486e21e359fc29b8179f6243a237c42f1ba8d6c3ccbf1fbdd92c0db4a065e639b5fdeb19ae56ed0fe66ba7b4900b97336a767936a8d880f6366cd3645bd3e572bfeb2c861ec4b1c94fde4da41888be0e3e17b70c4c0ddf50298c4744bc9fb0f2de4091c060e1018501c4470afb7a027a6c96012d9c2da20a989fe9839e7b1e831711d00b4bdbd5fedac2239bba70d6027d66a1fc264a14228ef4e3646093434aa91e1b812f0e492b195d8c410d428bc81db328cc1d8f971e2838406dc33cf9aed5a03652cd66284728b66dfc5c0cf6c5e59d660d00228fc1fc5c6ecd4d0396540ca0f0cf4ec57f44554274b89873418485d01a1cbe605de1039d28d01caffc43c575a5d556ab5143fce22d1b526a272800daeed621df2fe76725b73eb8c5c3135b045526bf84cab024fc8bffccdd51193b5bf0dd0a1fdeb1f9df53e7204d7c72abfb44079fd0d8bda0b2d3fea91f41939fdf19f0ab15d3cd416c0c7d756a68ab01afeb5b0bb7840ea4aabaec99aabc444bab0a65750676229a19bba05188accbbce6923ce372d421909902a7542339354aa8fdd104a880b2a60963460aa6771e9f4931fb6aa128e9e295de8aecbf0f359d0d5dba0790e377cac700236299ee396bef6b280a95dc2378842b099c180834237b823ae50eed35eeffb52f206a50ce9ebd62478c72c7e904b7e1a6123991c1c4d9cc07b580924774e958768767bb131cc02827bca6ae60d1d578d6d4c9c5d27b7cc3c8aa0190de5939d145b82e6fdb65a013494d6b5da9ce3af4c15932a141623ab7cb1a6ce846d852730d8b307bb3d9116c22df16d3006345880d8d249d823dae98aae5c20fda7f19830510163c18a30ef56c5f5101fb9f097022004024e624f598b50e48b500dc09484918cc44dc21f84e367d96d0d87632edf7490c221680cbff0db74f1283fed42cca94a8375d940c227261085429aff708a04b59247095fe91ded7ad5b601ead6cf3c151e7b96bbeddeed96e1be4b114dd4a1b5324c35b940ca267992d1aa8b2fadefa714e4f5f2d5b28227d8bc10215e60d59dc8e5ade6f2b1ddfe5f5609c7684f979c6aaca2ed1cbf4f01ec29cd3600509c97ebf5269ba05c6404188cb3e07deb9cbe574ab782a9201acf306dd68463d2fcc6aa2758d72ba9c29d39845b9ddb4569c4b804b2a0881a7947b6a0adcf425ce244ab08e41d53a9ed47f68ff61e806c0391fd35d15872f0574fef71030f40c2b312c6161f451a1420a11e42d8433906a4da6a02356c75de7e6296095c519cf317b89b99bdaf99d734971e12e18725c9266cab5c86fd05be0954aa8a38d247d03161954e31f81d645b85a9e94f527d34c43b0665e7bbe9f5cf2173a81f2d0628e429f080a96c9210a6700ec548aa9f4547c31f59bec4aa30afa4decbb856ad1839a29440f67809fa2c1160f0a780b37ee17144ebfb2fc5fd5cfb5a0e64e90551f5a7036b8426872d34d089c521ff84c7284276ee01b1dc0d4f306c2c65fe020c11af1a67a372828c98d375cca15c2373480aa59288f11c099816a1c8b94738370982c6c47a6ef30a2f1179fe0369a48c35c227d97b12b61225e74396a4945c60cf9f55bf241d1c0d4ae965e0974bf68c0044634ec220cd79e0fc1a8052ee00a0361f3babcbfef0b420a15d408d9606a8bcd37adb6db1742ff0cdcbf09441b8aff167a9c0570211ad7a6001f12fe8aba55772bb89962c0403cea22ca928a0f3253a45ae78160854d59df5b4d35cad9ffe6ef1894040f6a1900b583a9e82afcc34738c70349bba2ac2372ac61e0f7574c947548c7c39cdc6818d03badf6cc7bc961766eaef1addba5b0f360892166c9787d3c453f0f22549e35d96a5572a0baf046fa31229f0acbae46f5b27bc60157fc889f5fecb13a6a36e258af987ff01651b5bc245b76bd3800dc7fc5af21dbd1e8034651edeee084d15158cff786f715153c0d04a5c3f2b291254c1d40254557742f06bc3ebe57edb90d1c34d5e238580c55521e7ef7775b7b90c15dcb741b30d40c519e10583cc7aab1415ab10b11842e0b0f5cea1dae18ec130a144198f1f333f652e5b7d1843f74d469ecea158f972dd7bea4265ff1eedb57b43cf42b166f6171293a2c350d8bd684ceee1d36540c441cb00fdf606086667460e00b00c01f7a5ab332f0e1d0fc0e2e48d509dafa3995b6f5f39d95ad9f05b06ffd5c89cd656cf7bcd2f2db65523aa8dced179f938d6fbee0c57b1c77936805032db863231ea62261e1b3280866ba8db3fe16632ce783a86788cb96eaaefcc35c5dee4b25886732f839876990700c279ce0384b7385bfa287187a8b572c90290a8083e12d741738b0baa42e0b05eea64d1a7fbb88f58497179bab9c2b034500a7bd2c03fdd0cb8a57141b3339fafee71a32c21c4d2b1c4e72fbcb9c0bf9fdcc6f4ffd55264b717f26c0206478a1e99f2be997c9e5058e6097d89152d4a0552725d941cbfc9b1d6804287de0069a2e603f624bf18ab24c332324754d0dc71e4ab0c36d8f5c884d060fb79b4050952525e8160347c43008da15812975ac4108f4a72c6f0bd109aadd5071541230e4515584e40fb0ada325106bdae71e97fbd1161badedc6c6251b720503ff8bd0469fdc00a2c1570336becb4e762205f40c040c77d894fa83ac9bcd7ab292cf75ab08ad7223baf2ee69069d06c00cd932d7a43d63eab42ccdb58517913de44991c5258a9ee6f6af360087d521d62f4fb7a2b2ed7081c04b538c86153a3a5e56b711fd7f223bd12c1b34f845828d6f83957706d61314765faf1e6bc891b22483cf74def2281ca4fdd442d04722e721d3ca3c967bbd5b351ec7c837c9ea29323dc208a127d5180db016623fca41801cd8a25363abe954b2ff9d3a9261f23a664acfcfb60ac1e57fd1f59702c0c0b797fa6ed6d4742b245cc2c52924432b42f6960caeb74da1b5494e6def334fbead4dcd2ea996bd0c3896fa39d4e29c7cb9431058c337cb6ea72cb63963edc14e05f275f61dad01e31d79175efb82e9f75e03814013adf85ea508b03b41663e41604f57890732a63f487fa26648a5015b97e6606628aa17467f4c487c75357ee39dc423bf5d1d373217c590832c900cd250f2f89e15390e391813ad124789acba20f938f29938cb061f9c1eaa665cdae754d4cb7d049d0367e62291b0635f41451d7564140fb550b5fdfdcac4ca576f6892984c61b7ef47d0b81c07f2c96ce02d574de790919834f332a981cf3efed305652c6fb37066b2fb24bef9d8393d4b7a5d87a9b1d15090c587319dfb5d736b5665c60e389c1c57da02c0682f599bf67734eb27cea41ec22c2a6a7f1ca9ee0a21d201688b3b8bfd4144393ca866ea5260a8d5f43f759a5b9e6063218b0bf287e1a6ddf92213fce3264e25e87913a18a0b302c5c9f98b26a8944b4578d24942592d60d56a784a70d29868bf98fd46c07c3020f8372128372fde49483af402c1ccdf1de3643ead44661915171ea340602a1206976a2402c70fd930467110815274899215ea54081d368b884ccfdcb7dc09f0241fa7206c5eed39f067789ddd88a9044bf0d8956268c2558bec64cd60544ac46016a8c337a1de4239f9b0dc322a4c7d16333dca6774efe96549b01844230908f7f2dda7b8eb2980fd5cc10f00ee1227442a6b39193d2ffa906459b8a7c31b8aa546e307b15261308ac7ee46b545b42f632507519d4216eaad7c76c9c2cb47b55a9266d12c184d6311128c7f9812ee3420f07d86f57d50fa2b50d918030afcd9a1092c0faa6d89f63e1341c2c60cd553806be9c9929ff436ecf00365a9e46e9546afc375b58bdd34130c4d8fd7bfea6b2ed17be4e9d9209c5bbb2451e80153551edfb118247477833c18b821195962d883a76a737a0a292514bd786af41a17f6c4a35b0008c81999fb9f19a7c934686fbab7a432fc5c54474d783f06b1235cd4e24a8f81b707807d117867dd638dbf816809afb9b02890b5bc202d0d1a900c4c2633b30caa7e2e673dce091e0819358b4e0194903187984bb379d7bc0083eb6673b1caa99470a1120c146579304e7d17822ac84aeda8a17f46bfb950a1e713c39c056f201113bd8ac3ef0ac0f04cb119f8206b0e18ee5ed7daf2bfffffc0375aca9d29dd781e3e314eafe3fe4af0324f3c1e9377204e83949eefe2dd790c8304b8617066a08b84bcb703611412e9e828e32034ed593471411e25eae904a70f0857a16a8ed8be04320354b11aed154fa96bf4178e9ba1bb00110dafa27a6820df1351a4110e001e6d624334447e00527461ee56d80260517d1ba67fdfb83345a0b3f83e343a69a0b4b459a9a89ae65fa73670a6d21b0c9240440b587794b9ee8f146f2ae299aa8a81b4cdb61e102e4dda834f18880eea3fd1958010a027a7367d99d5b8978da9f1f93d400be2453998e02d78bd11d284fe35e78fede45bf95263c59706bc12c1d8acdde9f5ae8e537b3e550e74c1986b0607437e33c58308adf98452f19936088241b2da1f414ace17f502eda427b63e526f76c95d8652948416c900cb637d14b8f0fa34216576bbda3a5914b7178c8db41cbbfc78f14e7fbc24466fffbeb1dd082706034ccd5a764722d3188fa390f21f9a036e8a33a18d70ff89df4ae92a1546633a41095706be76ecbb14a245542b9569fd311f6b28e28da10fe586d984769c2aa6241ae4d1e108c8d9e51d611b636704995e833ac14b0508af0ad0e04e3ba3b42e13aed6ce968a066d991b212cd43295620becb94849e425bf451fd0d042a72dd1b3999292c65d166f48c5246250e5253a9cf4d471d968e6c356b0e7a3a4986ecfd99cab3eb9702a37b8d4ebdcb98e96a48270987cffae022b2cbc15ce8e4806382d979288df70227399a4b75e3867bc065414575a801c04c53815a1c8de1aa5848ae3a11a35d2f1e59c0597a72ccf7426779b4b13a9c60a715e092420f12c0cf153a0dd38d059cc6782aee46010229cc75cbb42f39111498d56f55a343e425971de9f0be4151c935541f29238a6e45af38a2580e76e30d6a2af33191b1e6e0314dd78f1d64da036860e0f7b25871d041afa9442195bfa0118b374db946865814b46ea2805dc5585587e0008641a351ad5c2be528827ca242f07e70b4314d206f68b8cb22e5c9cdba8a6d945e9537d9ddbaad811608dcc4c079050a4a243402255e4a8cb93cedce066634211086d3f0891eb1e5c92cc0a3109b4b7881dc1178fd484b7611be78d71fb38dcfb60bb46fa8858e6501299c5af399d595dfa9b8f451b52797bb23dbfa01b5f89c3c2f594fa6a8333a8ef31303baf77e7cdfb147f3f35b371e8e31fcb9a944c793908e4aa428bb52f636d72ecb6cec3e308a829215d427ae9678529688042fb619411a86d9b9852d1abec15363b533f2f3f15e9e67a12a06dd1a3f779ddab6167064834edb20b14b152dd050494ac17349377c5fe96f6358752f24652673265b009be0dc059635195834bdf412e102fb5db7d87721082350a76ba2e648ce80e31213789eab5fa6eef9dd7117133e9cbeb7fb591560dc604d1cae8248e5b3ca4b0a4b23c080cb342233a7cf40bc7cd828fc3137c471fc8419d07d14a052acad07a3fc5dd9dd394843847680c461f26614a4749d50ecd3c715ebde4afe039b04241b02b5181d8844f647ee7e58b2a9aaaf775972012f295f619df3db7d6664454d099392b3692cab5bfc9c0064080836e6f33984080cf5df470dfc0defb62eceeb54e97117405d918aa8975390d24811254c19c467bea6b79b01e560a5be067b8a41ba2bc2c1e367ccae68c0e2cdd9751ac284258d3227e016ea2d37aee07a3dba031c473ac4375608b4843f88ca8c447b2330b5b4c277a8d5f7432468b447420951860f496b76b4834b3debaa44eb7ef15ec2a850b49d54771c13d465e3812d1b15c531e6a218eb6745c4f83d54a2fd51bd503a62a10b5a87883ab09ba240ba8617c13cc9cd6fa164c3dbc82b5c031fba4bdc8e10306504563dd438a233829a395c57a8ef185b4f90ff1cc9cf5d76c7e079a9457786f8fccc6c70c5cdecf19fc470369246e3906439a1a5568958be75774cbe05684bdb9663c4554cd1402788c6c499c05241e0ac53267c0f529c3ee879a8d038c9066fcfca39d79b8be2d1054b07dd20e2491213181890a8a978343a04a7179b840a73c438d03fc407b472e6aeaca2bbf117c210c6e69d986134d8661f91861f0b03bf6aa4bc42d4a3be7506fc592ce5449e189410b0cb8bbed792a123fee2ae564c9177cb43a31cb1e4d6b7efe00b1834acb934106c8bb8c726c324ac9d5b19e0fb2105d035054872c375bfee6416330e833e421625be409f2d2077846307d2ea6c341088f03dfa6d2cb9226ef2566d8bcfe8e86054ef801da316b5fc985ee2d419027a906eb6a707717522ba7ad19046c3e7ebbfadb94a1d9d7f442fe9d419023d085f27f7dffcb0ac78240e37aa0fb1a867107f6f9995e17e3774240363fd209851d5e1fb4e5709a8939baf08d915a71754777a00d51f03b58014141c7146830fdd4f453fcc44820c2660c7afe3fb2037f6778c237087611b297a7da48562bcda60fa26f8b4e73604ae4e5a62f023336679f390c2b24d82adade5592ba2c09ae9edd36070131de1e9d83302fc4cbd252a9a4a656d406ff7a0d0a410d3116bef93d96ec19cc10f6677fc6e6333555d755067b52ad88c9441e52989c7777ce3cae6ad476f3f874ab8c972d3fca5f04da2e3fd093ddab0d2416ca601452100b2fab147e7a8ca0504231310e906aa76b5faa15567fdd070ac89739d5035188bc31cccb99e40c36e7093596879dd2743d302cdd30ac6254dab8119d733291ad260d94e90cc584eb3c4e448eef0d1ba8308b1e0650b474bab78d82a35b569450da5b840c7649ab15ae46969d7f0b8fdc2b101270642548d12d14ba38a97eca4f6c626c94882ba535893382fc227894b9c3460959267c8c93d0f5380093f3f2682dbdf8fc78ae9d1f4a9e899c8d74251238a3aeba8a31422eb17cdf62bcbf15b4c1a97fb1a2fc1ce806908fdf2af665a06e92f3d03ca39d06dd7618f1c04eb9672cc66a82abf92f06652f5e4eadedfeb077eb2e01e602a847d14f6eb1089bb221d3e7e323beb308696e05b24f339087c1499bbb1b1325098e0e691328ad7e223c6af25f89048f98b1d037da05f8456b6151f002f22527b3bdd89777c914e92cb23a80b06f18586ebfc2546228625ab19757133c034b8ea4d38be00c40fc1a95bc861d373e8c5f582a1f42aff06c021e1f910c92015f735d35f4a0012e7a0586da9479a634e50bad026c9ccf3a55adc28ed1d6f4dbdc7ea038f5122cec152bffb921f0ed8498af31b60ae385bf9cd2ab615e2f9e65a5797a7f5593a0fcb31ffd9a315f5f0a9c6968213a189b2748fcb9893e663cad5e6db633bdc2db566ff1e47d6d9673a4cbd1145c3725a66561c8b0c24258af92422e62e96b51088258fe0afb46c9e8e3a1089028bec11e8997f7f1b5ddea01ee8d537b5b46f718110203494d42b38a6e4a226f013483a0b886b628f516dd43e307b1e156bf0dc9788c78226fec67b5c3a1684ee639908efeaaae5d4a8586ab3cabc7f84e6b3e261294dce739327a723a20e0fe4b97eef28a7d46f5b7e8c0e97e9b45b8d9b51611f2146e251b7e2c3bba652e7538724c048838670f6a88123cf4f0812982b36525d8630fccd62fdbc189eb4c405941b652f769c012daf38c8c917920db4f527b0d16069aee1232e3c486660fe6f2fc82a558d63830da08da6a0aa194848840e3a1ad99416f6a9108a1c6ab55e1c1aebe63b5d7d8acc9a65119fed6d17676650b46c8b85ee09d18c67440dd4a5db38405e861918fb4801fd140e313234c47ad0f94c0130f1f2083b0264ff4a692fa37cc78269a6c723692e3a8eb0890fc76e70efc230334d935fec8494cd1a3ef246f80abc0b242ea80c6aab0422102263337bf3867bbfc3f11584628096f4ae02fefc7fd93210e6d41db38700679a1d73744cf1302d719653bb38185fb397f95d4104d860ebd7175b4051a7c6ce30674e23040f22c4d8368734e053aa6692e1d2c482676a58447d6e7c305d3e9d6fc00fb8931450dd1a66541e082d5e8e69e85a65e02aef1b7c60119be4672b9b192cdc38ee0b6b94d59a6116017706ca236fe8fab8522741d0e993e816ba850b92735451d27fc7cc007bdd1a3f0440b87ab75314f248cfa754d37603e1ff4c408852696cfc7a6eb834f8c42e4deaad3f50e6cd6d796ac640df5cd64f341153b3c54ca0d7de309f895f15ef5f8f762b9f11802bdca2d2b4744bb6a480a0bb2cbc1e178a50c6e7978d83f85587daba99609946d5f8bf4b0a0c4c39cef70b699035c28ff390eecf89a3442dc9a35a83d91deef9193b8b10cd385694b18f31b4c0a261473d741d83c2b9341927facbfbc8c36503de0f0f79e00b77764ff497e498438b71521096ba2931bd1c3e559ff6c6ef809f0901446dc5223317f3f703134f2c43ee9e0feae99b020f17e9074bf2b7da823ec42696bad8ecf04df413456a48a02a8190dd0272e81e3583501279ed5f14192b543b3396c44fe8957bde111dc0b651e425d3e9b52b0789bc13ea02a50e4f2342de4079e1a019c27b3a12f0ce538dec61e303b4602bb8386e4cbb590060e55ed059c2e1d68ddc19c9d86d62d2c1d002f13444672177e95cecaa496cd617bbd87ca8ff46773d80ce4e8a2bfa8d252bba051c3eab99bb26e78ce88776282a6173fe3fa8a6d74df3350fc1ffc06430a2fbc900e4851027c1a248bcc09ebb61bcf6938e26b533a75a9abb32110b09f3e984c42d5c5e3cb67ef4b0aae60e670bb30270b039f6f22b6c714dd0e223910895a8713662f2a07e1e7f213fbd7f49100e33e0793d9e283568ed88a245cc3912c2e1318ab90d2daec3843d7f71593003bc96641f7f9b29ef122dfcc51659d3bdf267349b1e4e285ff604c26e250b56de5d5be481bbc04d35d5be3516711ae6139ed61b88c204cc90695590dd04cb8c4b806df3ce24bdd08ac345ae1d11490e60c234bc27e23349fb42123bc849260a279333c53b9ae6ed4b7f06249a4010edd1437028aa2794f36af787a48d969a9a9bacd7ac8d75e8130a81811c183504f14aca65a08717e9d516779a523cda9b34d99bd75c153c5cf1ca14a918fd699d55ec4fc2e566a4df8c2449f113f53ba1f55747bf1866732d375a903d82564230cb0aac0ca99d7da6ac3aa094f5969062a712393fa8d3ec51d1133992905aeacc447eca6cc8819c7c0939022cab076679cfc2db66efe0fc865a43350f61e9f8c2d28fec9e59eb9d1b00c9774b7e03608f45e5de9890e5749590144f482ff5af6871bc516a810033841c1b85f938e4cb70a9ceb66105fa2a247f250fce5d53f1652c60bebeae4e6b7c202d88764ad2d9dad4d072015e82b4ad3ea90d28b9b0e327f97fd1f133853a075ae2f93801b5d6e2431e81a7d524a2ed09c94bd31f51c8467070d268c2a090f3a067806d4bf2d0a9a5cca65b7a52da9d2c1005ad9cb857a2f3557a1d03467ce2c0adc0ab4d3145beb5fb302055724ac2e5ab5cee9e326624ad7383c127e1aef1bda4a2e70af8cb3b97bc6a3049b274e4989214169b115269c598dee13ca44c460faebf69b63adafb644cbf33ac42256af3cfe3f95f3a24950c770399ae411dac24f9d3b49a592b4b7e120df7e6e4c6ec434d36a2de53b92ab2df48af7c3396f3e987a8a933b4ccd846aa05024f3f1a5a101deef61d135e97a4895d88edea0cde5e19669a02c98cb33e2dcd33784638b5fc3e23de1bdda2c340fc149ec7aa906473e7ed729027673ee5eb03acae8f9be3f6c1cbd9bb5fd3289e33b2fed69f358421b7b90194234654a2d291e628c3664860908493d829c08c1694190bd25df66d4597989d776dad0a1d90b4bd4f771a2dc965b74a7981966306dab42a7a00a73bf0d23e20ada99fcedaa54502189056b72d9574206650295ad7ea22d3adf8217468c99dc54818a0b0f546d8185a2c1a45c561addfca143c4db91dab623623903d8688c68a9448cd13ebc236b72681332fd50e1a4b38ae3341fd06e72281e58a968fc71278f4d237f715049a1887198b6b308abd62879c170469426b4d8f76ca204114189e7a08e3fda4df8a501c017358c937a1c156dc22c56ad41ced06397818f3e84e1777b8f8a589154535c639617ab3672ee936ec46a1fcd5020df466c95654c46ee491a454384c37eb3db8167cb229223090b95ac726d24d722cbf37122fbc38f902c7592d1081cabc099a5aa8e283d3b7cc37f2cda7444af66bcf709d16c83981e62bc63105ae35275082b2002019980b8d50381d002c42ecad38dba01b812faa2ec31cf3ec4799502d0d163d0710e163da30342ad86a436063b1f306f35777e3210f65f55a829786668450b3488be945d79bc5d520b2432b710e21798b8a833d24c76bc4d20b96562ba5aff4c64a411202bb736ad760a04aeee7a32af02fdb9dfb77a2e365db308646070a3e6424ae8520f20a376e1e89a4712a882f8be27e0aee02cfd1b0f77a1054e5f2cb25f5cc4526a12c48c55bdaa85d35125ad74896ab9a33898e559c4fe6d74c6e796e9dcb91cc4595dcbc9ef99fec445aff59462210e9762f479aff3a75e69a59d9430a4c389cbd59d503cf05be9cecae19643ca0aeeff2d688a8c0865710196f3c78031ff49fa927e65ec4db4520dbf5ef35995c993f76e09cb27ca02527262de86eed76a0cdbced5a49e3ad0ab79913c74455602bc3aa120b664d21c9a6f1d3e8420edaaedb0ff5fe9887b580a0759d2102dd493baba07b00bc3b2a7e1020b96b8b56e607d8ecd7d3c7a1a1fe7277a4378e74d237e9947e6a3aad8a5b0ebf16cd654443e9b02402c2de539e8f02205723ebf935f9f39d3494cee7bbb562be7b27a1c0e8b2d9a48ee819a03ba307a98be93207cc262b0f99593606c058adb819b675fa6b32fb00948904703da94158bcc6ac3850bf45db51a77a7842949221dd83854ea07efb91afdb18ca5d74694cc7e32da6ce5498b8cba295a4e06d3350b0b1214d9bdc3aa244486782375855fbe6ea4c7bbf583003fcb7444f39ee95cfb6db7ae793daee383542074c720c6ae7b421edc076718b03b48811c1f5ae65640ac5a171fac34778472213462e7ca2a2873aa5d621a0d0c835bf69481d2fdc0ac72e898d78b607c19882fd4a7d91632c2c9c7e0d3586a9e26f9ea63d9fee2a8342f09562d9863793853d93eab0bf734aef65d98b2e67d004e530cacb5740a9daed3d098620fb4f00076af249f500e042e6c26c5b0be5ec7c52800b0994ac1171cc02092a57a66a27949c729300c33e08f70b384274bb5dee00718610ecef8b49adc871e469e491cf1da0494881bc5f02dfed1f97ed21ee460b2a73639bdfd9840b2a7cac693dc21645a4be4149db17b97f4ef2aea10965beb6f896925536c0e4a22b050aaaab1085ec502d3331eca72d5d37592480c20c369af86fcd2c79374fc48407028fdff8376dfa426d43336227e101d731582344e2e3d182d01b57eb215c94923223e23226b4644b2d4aa6daf632cfc045b01a72397766dee1d4f4a81d37486f87ee67c24b76735df0fc772c81a7f005ca2f766f8ca2d4f01d46f73f5da05323032f4391448bf4f666d2e6fcef96fe694c910fcd826ee7b8eed24c86b5b49df3fedc74f113a2870b80d9f66cd6edbe1a073777e030ca94fcbafb9b32562c851aee4d80c32bd1e46f5493430d8f5e45994a517c120e354b54c742e35e5b00a5a56b96458155250921551b5f21124cf84a35920c702288043a276cce5962d0c8f12f672ef6696cf6baafbdee75c57c104a5208ba36cda031a104e1f6e9c427da06d270bb3257c8f8523b2bcaa85e789d15b5bcdbd464cf2ae02773c2513f9c5025bb918e82e9cb70375841ef67821e3d0824d2f5639e6c155ab433d5f40359c8de59ca9be8f60ef68857418a2690411b654565520ef75a6813aa98222ad05335a6fa6f19c8e1510e3cde81a47e2846b92e01ebc81688007c519b98c15c9c40953ad3557cb8f64d0c173f06e20fea6e2a72fa9f84c25e5cacff66ad51713388e2c4624485a7b01b20c6f336ee4e7ad30604fc252a018a71720e7ad6dfd16a831a9941541301f1ed4414eb26272facc8b335a99b0a96742330281e5662c85620e0b0df719a3c3945ec96423170dc473727f7dffbd2ad005e5a54bc81718e5a7b909b6063c22f6dce54b25bb3893c58c29c4f9b05152274c0b42b426a4255d1f5b8b3e821b0c55796ba0ba50303d390c6eb3bf0c175560af43321e6fb767c764217507423a619fb4af33884c7a363460893c36b5c47b0c1ac6ffa99892158c198018640ae4dc960231dffd42888acba5ce7174d3fdda9e663bfd8b667f2798386a6b8af8bec937d29f6c85cce48b719c278ff48ee2b1dba232f307b53ea116b4620cd934d3e6807042f0b04ecc9396f5336fded6e7759c757ca84c8d360281723ebd15c64a79c8f656a56c85792d75213cad1f2bc9c13bccdc8e065bd2d762241f3252f8b56f126a94bf395a3a7c4226f756b6a4ecec291a3f08474ddfcb1385750be617b06d572c4c59052a96f5a117fb3f52470aca6edc7d1c8510fd0b022f1458c21c04a125bcf619c1e0b1daebe5d7295992741b5ec080e2b9add449d72684d5f411c558a96d92fd18c403f22878905c20677d1c41723da8df53a5c71a558964519937f1d053c903a4143d112dc7f5732da330d957d7bbcc2bd293c2a293ffbe5cac05cebef82fa6ac0597b0d36e16022fbb918bcd2ffed4607156d09ed04000ebf9460025bffd50a97db7da978a34783a3d8ae5fa2ed1490b190216eb1ed2498efb26295ae4cc83f6d63374c3358062a16ad1fc33c3ca3bd5a40ac7ba9ddd55a654b30f64583ca42c364af005be5ae3bd8b04e928aefa10709b62fa2076b7abb47c48094a2d8f7be6889f46a857c79b44a489aeb6ba7fb142e37b08637ac907b3280aee05d6c25c4e780dc5b40a9c4c1f2b944b21e58ec0cfff2090acb6c679d6684e1713a14463b366c23c9818c633d1fe51d196a8f4810f10884b9d653c77042ba5cf9c6f595eccaac5d33826b558f308bacd0851837b9f71ee0691f0e5677b26d833b5eba10a8f6bcf559a7fdcb2bfb6313bd00c8cfe8c2656eb7ccf7d5a0c4c6e9f1aa89ab3a33070a048dc90778a4b2521132b77a112d4f87971f7c40fce8126bc76b70382a1ef67221a4574f1ddad2b793bb5ffce2ddfade910c9dc47ed66f029c1253eb47aef2f113914da6b19fb901d431ce9fed465be3648991857e76cf090d4907302cd10749bda8486f0464dfd33f99ba35121d73c6e4408b57441fbe1b602b4a81a6fbefe2c057a609bf42e5d2ef2d43b64cef1dd21dcbedc0732c93ada3aef2e4af8e342c5bb4a6d4aaee59772c31c9388aa5963eed2170a53dbc2737d1ad0b38e178159488e82350801082424a2638a1e250920906363b4da4269a7ec4128cd237c58fd79c413b301f3fde8385da3589a82bdc488f7bdf2f0263fe8041df7ad1a03feee4779180282d8013a3225eefc26b377c4188d85e63420a7c4c4ace67ef6ec0445449325704fdcda06d20239371f6033a103a3c014bdcc49773d291411789adc58c4033ae258071f185f4e75b5daee81c0d125dc6ac2364eb77ccd17ea23bbb71c0338729d6a75d02b5e60d53db4063b0eca65e8957adc991612cc6756221e3cc42dd12bfa6872a6708b7ea90e30034bc5c89b209b40c83d3421a49607c49506ac4d544c5f86b02c628d082e66c694c6a59f8610b7b82c68e7efa2a1fea6a5edf84ce827ddfccafc092c4944b4b06759675b05c60661425e2ef429b155d1fcc0a5fb1429654436a225948e906ecff1c0d1355595ddb2d0d43aa134c04021bdd82e8a88efa2921cac91fe94672df20415e0914277024b40d066df069134f261ede1987eb0b5f1a83e9cd0b60da3c163ec00d1ed476519186df5814042b0a3a12e9e00ec67e816380b56966a8125989959c6e83c971534859eb825f2a8cb23d9b3b0e21f6f66c68e892557c39fa8257d64f2865ae8d06e8f93969fc452c014a1d83060e41013258b0b4c4c86a9c8225dc2dd38150bf99988545ed0d551cb1b695a5a5eaa36d8d9759ea5a47d178574d5e81f775a247c4b20df1be6801421a59059a89303631965a7ce33212faa904d8d5712a9efb2bbbf401a4ea6c32724df0c12684e66efecd6762aa430f5cb6ccd00d348f3119fe6ebf2c97f9b7d6ff697bb895499903cd20b1e428bc05f2ff363c98fc076f5b49e55e0a7d04f3e946b308092c1abf5ebc597b62e2058140b0496101cff2a2e69a185b24101f0f6a203b64af517bbab6ca0dadb72283758e696b3f0431780ad37d848e5ec427206e57b803953ee12d451f3e4c93f2b3cb4cecdd6a09b5023f972be84191d20940ca70a0053aca81de7019ded1fc8dad376ebb08a5f010320a9c898cd461f9a275b7f9a49e85ec800a192e2f74695e0428673115a65fa5d951167dc3e5800cf760c938b17f486dd4fe3a88bb055c8b57cfc51f384056d3d490ab284e39d3272b8f8637290d91455a3bebf6f4f3393535313b1c65c01f2f6ecde6e0b60c4f14459f2e1e4831df14027e30facccfb32ea769d7ebbb58b59d814df3809423bf302ca992a70ef63c591ee6c3f3a1776cc57e5f0faaf01b250f1cc76c38f2561ccd211a490c4ef4af2b0920a624454aedddebc5525e3ade80a02e2c20bc670ec93c7f15159ac3e620ed208f594be6b78d0679cdf55310e1a28b6d0be19684d2a4c2a86fe717abdfbf877fe231cb05f011f010f282a90f540edce257a803965c2b1bc9852bbe49999f4e127aa1eec7776ae9528285b0483d2c1a90606ac02dfdfe05efad27542fd432495078e5d2adc1275fdf74c53fd1ced6c8457f3bfff77af026d5136389c9d36c0ef5e4c0936b30bba4997bf1f0d489a2de9b8fd13672a1c36e2d042578fb8d37a888ff0cb5a143717851b632e41623d4afae28f7bc5f8d7adb1e6bb2f53ce596592ebcedf55981fc50811d28ab7c3fb9aed84983a103fa657b7d3bc6e3641649b8b55178350e603092b81b4da44a8c9421a89f8fcc2987a9a09ab312852e30af136749ab6fac2da7293a0be3fbdd4dc2b8b99290471526b6d5620d31fe3e4d0d3df4b8f71b18704cf2c849d573f1d1acfd1fc0ebdea8784f4b3e830d6e46d46f7bacb46ba51c9e93b0e6c1b789a05b9b8affd4ad96d907a5fd5481e31ae950d8b7e05e2504f3e5125e701a22dfc2f795bbac83fba7db93434f5c9508f6405cd4a250910d532cc5a3039173feae3c47ad8d87aebc186387aa096b4694a3ca337e57be1bee6d0a383096d50fb2501288fa454512c126866588ae341dcadb421af8c47cacf2b8cd1f09dcca94aab27615b586509f3ecc562949c163de07309d72423b58b4e85719039ca949947ef28db32e67e848dd6061d04abb86ed9a8f60bed69e2e9c209b8a386bcbdf1973b103aebf868b6318503dec4ef6b3b05d369a3ce94a0938fe3605e809f56f5ab37625821aa189e0125604d05247310db3d407afc36eff936fc6f440f54bea23f4625e2da5a127c98ff492e09c00131071d24be5e2e1d1bd9ded495bd8650126932055b33cf45e21888a74c3789a565f91664cbab6af344510c1875f816ad9f11f6414b8fecad6c534e1acafd7d40a249b686aff933fe9e6d7c7ba705f2638567c023825bdddf277f3b52c3cd2f2dd79a82faa504eb09d6640578078dea329725855bd49bac4873ac65be2dff8a865381a20959909ef158918225bc37933828cd11b75342aa058d3d193fbb0649ec3b80ef9a06c279cedcb09e323abab68eebfeeb484cbfd9714f96020c6839b9d7de028bd90aa2b6557b5cadfb250c54f9ab44a799286ec82cf371051ac2c6aaca0d9f82d4fa778532418827f895527be2ed3a271952b2bc3cda45c4253d1e5e987e0e989331579e15517c91a1d430d4a8084bf24a6fd0d7193cb48692f919893d51f74e27ca86bb1d148ddf80151a745a4d1df077d626671ff5a26c08433b910110098484df5b4ca36f23c81f5a762c35d9e726a848c8421252ae31c18cd4ddcbbff70920a79d594f4caf806aa8717c69403afad9ad3a40c395e086bc2d46c3a59ae2cc2830901ca75db62cfc5049fd48807e1c7ed8d18d920263941bf9971bbf1bc5b20948e1c55f175d38cdcf14c4f04d4eee8e093fc8f984ce00cf53ca1e596c7d8fe80dfbf1d38d105c0c1043c987d6ac4d46d44a4af0488278702023e72547c2b1625c448c5adc4ac395697715fdd1f5bfc145135afe8f1c17d2a319b2f8052d563e4100d169c5651083bb2e4439eabd3e5185149a85fabe370afcdbfcb38c289e84a8ea0e37c43bdf00a775ec10a77e3ea2a6e3a95e7c14b7e924ba2c1f6bd5b7d8c13c4543a2dd9e58168b9ef0f10669d778e3be2ed48e0933a3a0f9f0202b3361b3ef7dc5d10301bca670190ad3e16d09c78efefc884a42ea1d99b32656e271ed50122ede7ac1c00202da01a51544c7809966e32c6e147859c9be82080ca9d0a00277ca6ad78c7a31d84435f34623725fbbab9e3b95002c48e891dcae1a9f582714b23b46aa704078a7e6d1c3f94a03465bbd198f96c9a536ef6c8930cbb2c9bddc4da4027bd918d0c471367f615f9912513b5981a4a0617869091c2cfe635e76e18ad0c3e8f6f2546b2a26be637b9402a953786985f008d70e359fd977c2e0c88d950fba85e37a1926e458d40b6f7e4e4856aaf1ca4f4cd3fba2972dc7918197afbb9ef01db2446cc8e957bd8ca61bc63caa95056b542982e012987cabde8b6d7ad01304272946c2a768a96c440b39ac00d7a6f20d3958f3e6c9f91b03633b6f3489b2bef9751939af7367446017b0e7ab278ae6c94df5e763af4a3776f1fbdf3e52134d54606567fa054dbe5459ac84820f55f9703f64980daca11a1d697f09f69fff790d215d2e624a1d460f465a27fce65cd1c4319dc1a2a82ab1226a0cff3e61fff88415550fd3827f8d9338309d1783ec4cea0266d9be8b21736568289bf4f90be914d0502dcaf0214a403c4cfd159055120ceb8b37a2ab33c0e8abee4d4897518990d5637b1675c18c21ac9bb57c561e5eb32dbf16667a1036cba855308e3ae53ec4dafbc63aa93de44000708f728ce42e8e769e11ad1d28104f30939f97fe628c33fbc00ad626f5301403b0eadaa3be5ae8c2db0e500752d5fbdd80cd2c26dc983d7b92bb5681d3fdce474a3d48abb98e2fc6a7a07532f704905402b73e24643f68fbd95557fc127cf68f5f3d281736302a3f7a3579b41fe52eda066f05daa1d06420182cd7b64e454472e7df90b786060cb1e504e98f0f36d6e1a01b5f9a78b92ed2ce0610fcc0dbd8d0dda1a4b6bdd32594a18288d6a9f41ce7ad1e44de19d32636f38fc5fcf0320a0c15eb004e105ba8faa25a4735ea29ba23ca05cd8d856dcbc84153cee318c8b4800e9f9a6b39ccd3aa6e1ae6c08948c4af9a410910685c6f24889c3f18ab96a03b418f93a4fe4cab3087c27260a7ca779fdf33ca5583a017d4eb85eb8089e512dce1440eb38cbe5df2c8bc4546d98864fcf4ce3da92e65331723bfb036a08623f037ddb0e485ace2c46abe7eb4964091d2350c23a3a7a370f2bbfd8d67f8910c5175bcabeaf05103dd7d14b97bdfdbc863331e0ed5a9bca5d28ada8f62163cd3a4807613d89cc27c934b6708f9b6683f6454bb8954ef6459771c9638461dbc6746fc3dca5cce18d8e48e77ac1bcb164a9911cb649cd5fb19e101b5a8e09bbd6ac3f08fd97c3e513c4a36686abbff4fc8d81a7a084042067b88055fa00f85cf34003d5744563b96c9ec367744afffd57edd032da8eebd47b029610038408c078ec1a7f4047209b47584f8d68d99613f0ed6ea9ba455e804e83873560456b45b9709dbe1e1c9e1620e96c75845da3d622787f87fc3948ccbe224d937ddaad216c15d778d73c2f87c0a97c07e05089fc1f81941fe0d70664ce465cba8e705222a5b1dd41af0ce44bfabc793559e14ba47b638a21ede9585ad8269a003bf7d5496e040f36ea8165267a5cef36686e8bca9318a6d28f468edc45b4cb8f00be37a5749cac14758926a289f54bedbe12321e2017add6dca76e44f1805c0e5d7ba2284e53d6ac771126d3ac8cff4f79a63027200d88e6ac1c0d6ad3de2b1e287b91d667127bbefcb891aee97b0e0ae07b3d8e4f700fea72673f1029de7700d9815a57dc09795a38f85c840a2ec0848817406c66f143a88436d9455ab3baf296a0d2f1f7c66a0be153beda2000dfcfaa5801408f8573a6edf971faabda66bca9adc70441acc7d4331f51292cf9e124f52470ce3f90546e2090c119f5ab39350522679bd148a646019f9a1af6c74eec41e0ce45f5caf505612c5217360f7fe330fea411c39f79068b206da524c69c8c240bda24d79a4e812927c6db00b4777e0ff956f746ac816ada50420943ead5d1792c4ee4d0f56ced0dd80b025dd39296f6902d51f4258f0ea8f3dfdb82d7bd3a3f73caa536a0db2fd931bdbc4d42b2f4a16b3801efa3c6fb11b04ff2477633428ddd407b69097d931a6565468d32dc6ed6017f8511956330c748ee5af14469c6fb5ca298f4224e88b9f46470b696735b7ae90ead5ee3c2b968756faa9a9daf59d35fba14f6d4cbeed8a8934572d137e7dd90b13504a8a5d37373080b814b6e961adf0e88fb235af26335fd40b0f293480eeb87e86868f8dd28c7dc35038e3cfa3ebd2fc672c919781782272018465c70ea8501f82efe316a80961e088c81a5c786af218b31f34e53efdccfa3933c1a11f92c66d9f9ab4f56c29e8c4e287450f8b34bcfa9cbe00c218d58b8eac4fe5b69cac1d951e3a7e1a7b8f39e1f0dd37b9721969f11deadbb9db7e366af43aba223062ff6f4e0e4deafd3d023c565e621f81edfbe4fbe4afe32df17767ad0a73519748fedfb5e3d287fef5b640340838060e404dbfb8731bd3a813be976976fb97de4d6a8f406ef0373012d44e8079af112a1bbad98abc5e9ad276459e6cf63e631442acecccf7ce457eaa09f6116d02195d2ba271d11478cb7411ccedcdbd9917320c0375d49b9b2dd80c75c9a8c5b369e3b8dde6b536d109b2dd0a4afb980d567673c33be1d33db4b96e74496fd41b0c09c117bb428a53b363e45bfa0cf951e5b8a72eb18334a79b986b7105260dc56a6bde6e16d103980af9a2ce625a82ce9dc7455f0d5031a7a1cf75a281131748746be22892c444d504630e6012f4139c29f07a578fc367cb507a6a48e5c9fb9d221d83a8962690b137881dd01fe6fd3237cfca919df6bc256e46dad066e69885f9f6e50fa906d4fc10536cd89fdecb7a8d299cdf7294104d18603bf984b0b847201e2e077994b2cf0b02332276cd09746193efa1aa0bcbbed985b184866d8c09b11e558df43c6483c72ac0e046b3b1c4952f823e9dc3150ef0e3740e9c5127f4282a82c577d38029a282af680f89cc98119200119a11ac5317ebafcd82ef579f7a73974f42f92060dc4099ac8d862c3cfe45a8bdfa867ac49ab7c30645031d995007783ed9e05b41778ce5954395a01bec72a4039d018fef619725b7085d9ba3f2d7971eff2f9d79c8da6be5fb9fce1f258f71ffbb3fe88b7da546aff675ead04e50e227f3130a4cb79b039a4a4abeb65f0949e2cfc7ce44c28194c1e81504481f00b0be0ba11b8c1affe06716123d4fe547f448f749425e9df80a98d83d5a93f33c501dbcf7f5a57dde1afb9d3305e3f442ef33ecb5391c8eb075f1b5c229a951b119e62786f58ea828df7fc74d6444d6d14a733b2aba1b27cfc1999ae54b5d26776ae2010b39dac00fdd90ed2b0089fb3da687f3b43061bda79386e648dfb5ed4e9e19cafe3a6ac3b339e80a20004a38ad34a1d8856f6fa1c9e1a3c2aec1b64827630c949bbf3b58202e673cd76e7c6b73be345d42f4faa48046431e2bfb399d59dcfa2b11c131f951eda8846571cd622802b60c54ada49654e4cb098ed72f1903bfe04486e2616bbfe96bc6adb05dbec54e61489f748ee6509f0e500b0b9c100ce8ed3c1f6e0f9c08c387983aaddcd65b480f4dc8a61bfa7079dd09ceccd68dbdf80cfe74dc3f4c49533a120781d6f50700832e0f20289b5e536b564f991c78e04c6fba920b5402c4b782913975b945212e88f67265827a44fa34d5e4b1a31046fadda5161b2ae6d1166c81fc5c4f7305b4c54d42267e36bcf392f50a4866d631974899221e0d15f0f0da3bb4b67bf396b2c0d335773c34260dcd0582f60f25cdd8f612b2d4014191b2c46e871f0a2511fc7bb54e3ae236b07dba9bea249a6fa848f33adc147ebfaca03aa208162fad2f7445fe1bbcec61638107aef4b909b80cffea4f1fc2fed3df13f36cb285e5207daf93c18262df658aedc19b8a1541f7b06d0c02e67e1c935ee3c3b38fbb310d770b77387fb845fcdbc15999b99afcb6cced866322f90e1443158a90e2014312f1bc3d76b2ae6ca69d40e575a76e6a3b8a34d19ff6d0daf4220e38e251a9d1efa0c2ee9f98a6cf853d02e2cfd20988e0693d1fcae65aa162ac7ed3c8fd20ec9ec41df5b0a3f5d11f2963bd563f284eefd50fb6fb6ef77313eb03cc8ad4242e4ba805a83d6712c266fbb55b37a63a9b6e6042fb423659c6a1b2fca03cceed44867ac958ac013ce5156cf02e2f7b479548b0a2656a668d8d2e7b5639d722a0b9c918391123bf777dce8a3630218fd4852905e83c40e51d511f534ffe6877756096e506a7e58eef718b41b43ba8928ed3aca4531f7e19db8a5512fcadaa573e0a86c7b2587245b7bfbd684447d2425693656a8ec02ed3fa040a73d84d07fcdfef78334d62053c3bd4bf7c068df9fb4840d72b20e8875012f0c8d7e1aa8759bfdafbcef27a1ba9ee5e84e0926922eafe31e4465699f1dbc8ad3db34e026dc345aed708d99793a873d43c4c641f924c5e01510143efbc10448e3394e7b53b194a8d7ba10c3342f6aeca1566662e392e4deaadc760dd7ff7aa2f821354cbbec8887bbe5ea4f80178413f24aecfcae532dd851a0f5d18c5be586089eb851cd866797b9a950b156d403a92a7cebaa266f27a1cb83dc7a5ee9207b9a6bbc4cb0fa3f08299993c7e6b8210f49e9a9dadcffb2c6e798072bc7bcd431cef280faa25101b2ae7452aa8d5b321fc043d22a1c24e45ed55730cc61171941f0686e56686cb3048259bfb214d2b0065c497e555f4b70289192275334fb07f665020d72df0315187025103149f59fa3e693cf310a40575437a47a2b1be8e1807ff30fa6ec034ece84b37042838ec7e01702ac42a191ab45d6c8bae238ccb65cbeac0ff81073aed7eb65daebb60f31b90fc19e3ff7ab03aef8204835b3f89b2781b7a7e56e10c55e8f40b04071d7e825882f19827f1cec72e3fa145b1d55591d608ace3687d7f9a0ff14f03c210d1e23bd1e7b475c1a0da74baa6774c67a46ccd6576972e6638bd6df17508dfd5dee54fcff26d20c2ee402cc4edac2c00d61d5fe255a1444f398c2428908d386a0309207e788757b88a0cb1f9a967980f8d0a770743aaf99875e4136830292c454deba4bede22360b3e33088249a3a9214a0f00a513bcf3d92b42e367de85da578fea53026aef2da181b17abf4fd014805dd99a3598339994f974382c621f1efd3cc1052d4a29ae1677ca41de1fb7427718a9e1faa2734c9a128fca39730ded316b5919be13d30eef11e0ad1945716b2d12ebe240efe85a1d21284c3f268250ca8290a6f86d8d8258d9d49c0fe73985cf3533a49fdae2073cee9aaebe5524e5359a0a8b108ef06be12437a6e351f2f0adf953e26e308872c136de58337543cfadcfafed3ea27682b1e8d81d7e1bbcc240e3b303f1967eece32a097f2ef8be1fa25c81b9ab52368930f003809a0ff87d5d13748deac501937e5a3cfbf0023a43b0221ca4213a0fce302dde1dfbbec63554a2fb5f8c7c134effe875a6d2ef74d76831d2d5f3e06cedf9141fa6bda867c64bae24e7cda7642bbfbde96244e6068807c581395ba0d8b5173900f9bbe1541eb5769f1c005c73cf1bf5704e4595943b629662b52b138bceeb17ac2b680e9617eb427d0943d5dd739e7113f34e57ac0d8edfcc30fb08b982681239d64581b8bd3fec88ee0b1e8916de43a0091d0d8a263434b3f2f5a5d66163d144516db906de01f0b2f30b2e08d75971adcf85cf4f14cb4e8b2a6ba064b43acd1bd252e9e082ad45fde6ad3b52269945c370f76c9b41ca1ae862c030c54640a141857c3733c45bc71bc5d311535efbea29d0deb556b48e7c9ac3232ec7aee209269becbbd44906842319ea1c7a3cb5d077aa6b997aaf4648f1a7e2ab60d6f6497ba728b24cc2fe17ea2bfac8b1c256b09f95957b82301f4ddbffc10c903233edf5e3f1bdc7d97f1d8c834b4ce8fa1a5ebe96da5a5daa0320a0b8c8dad5a4a67701f12582f58373c42a87c24a430f7f1b6dce0420e5a059617495a11eea1178aa2b3061d392b1c3bd61461d0ed564271379a054789a01e7df97b794b159d5d77183363740b7e8884bfcac70cf0dab04c00111ebc04490b1560bbeb0769361008f566ea81ba03c7642d2700cc5fc63210eb1143e0b0c0b9cea37a25cfd7cd7aa35a61b9f76241d44e9f2a54c38ee7804d0d69014c3caeb123b0a53f1a12120bc34f674c82646703f08540fa3dc44017e319816de8bc242b03a3e433273ffbbcc9473542fbe793f789e9ccddb173e4d7e9f14adee199100b310014996d1f3dfb14915bc2a6e64a60b29be9d07b602d50d6807f02ffe8598aa216931f9fba2a685c92e8ff296558edb07ae48e1aa563c1a305815fd30014c3deeba825e44bb5bfc3ee8f4fe3ca7a70008461388f847f3d1fe4e7f18a5d3af9f94383c9bae07073698c2755e0acaa13f6b7ffb1b12b3fe59bf87848b1251f9e0e1f7bac863c615c9c2cef147c4972b1a658a4d4bb8bb1c843317928862b4576aea7de2f8dee9846dc16d08c19829c249e88810ca4a5fd8f1926008ff5fbfb609bd3f8358ec510976cea954d71d3ead794291632fce19f029761812e43c27ac8c99681d777d51e2874b9c5f428858d37155cd14aacc5875b475317a0f8c3d9dc3c5edccd26b48398587c1e292d191b18d193afd0912feab205597cdb553b58d1ce6e04620d74d62962869325c1a8f0bb35946dc692758b0f5fbeff84a10841e071bfe2f1aed3c5cc183404fdd78346496b97ae11502eae63c48dff6890688f2eec9f89c2b209296c8bf8ff282d6ba71a0290c58b427ff6f201ad90879b8055446366adb94384e4098fa12ec8ecdb795c509395ca701ac85a685600c1b6e8c7f2cc484afebb6efc0f354ed5126ff6db6f0954ee15e0b7c03188ea4313e07f5aeb8c9892ef3f1304512288872c0969a7c4bc5703240e472e8861cc1d2cd8e6399804dfc9ff7dc98f88e199e20b709771a803cd4338b1480c2a573f2092bcf65c8b993c2d98600d80f155616ea0e6be1a010572ad2e39a2c971d72fb326dbf7cfbdc60fe64fa3ff01f8da1e0270131be924363cf1cd1f22d8e26ce98f2300a6b440b74f5cd3edc5b5ab40eb52a5c9e1183a02cbd27dcbbd8436d6db18c4536144b7fefe45644f1837dcc6ac9ba5916117386d07be0f21c4fbb96afc99d8bc4419cad98811d9f916169ac39db16d635cc9866ded4d5c41d8df193251cc03f99e268c9f2adc354fb07002c4b76595e8a3c5586709331fa9eb5a1c5b910697f57741c0d255af2914c0e2430a47225071bc7c549bb4f536e0641f4e29d61b3c1e34c86929f7d7ac10b5973b8e00af1472288504e572effa8f6b9c415a7cecbf4695a1d6a416297c7043ae770ddeb3338fd5f13a25c538ca67f9c6e5aa34511b553ab9098a11474118ce7a6c984dec83b24ee98c62e38750f56879b0ece76fc0a9b75af982f492424a9bddee20e006a266257fe3629caccdd0d120e5222b2e9fe2da715f42a5edf0370e1d657087d4f8a127dccf32b867c124f208120563f0dd09514062b6f3d87f2188e74e9b670e4f158bcdace9c39e08edf9bb7aead1c55658ccdb1093fd3df4ad1da635af6b47caae356bdf6980ccfb0420f5b862ec4aecd91c530ed08b02bd6c7ff07f9e9eb91308ff357aceb9ddf56170e3fc196322dd326fd21ff41865678214a177288dc5c91dda6c083a7270f389aa7fe8d571d5d99c483146e5f4580015524aa9eb4f547fd414aabc077bbf6fead77fda191c5483ad2d3469612e713e3e175149c205384b3f5498b4f73a7c529aa061791514294a153cacf59ee3d1e8c0baba839eb080d556c7ba90d6e0dbebdfd65ca78eced8d65bd092055d44d1ba07ee1c59d512e9bb597293723bcf884ec2b703cffab5461231be0aa455f1f98b8523814827edd379437ae8049130e036ef6f80fbbf0ddb3320bb1428fd1c5949293e86286e2f8734d7f7a64ea4f91bce2d9d5191e29e3b26190c63e59541cddbd630552387d6bbe5c7daacb46136eb0c97c20023d5491a8fcb93ac198e326960c555c869895f03d5d2fd6b1d22d8cefdfc6a64bc1c52e5d9b970596979a47954436a580855dcf0f576489ca36bb90ebef30ee97d0c9240fafe8196741c2399c663e88d62135c8a5477e45ceea14837d3d77e68a9a124386bb0585242c692301cae40f01adc2c2a84068647178a3298536b93c8b38e4b3d47752e5a66b4c0d3dda75fe997a279c74eff449134b382b47a3f3bd0e709abc6121cb0f75369f938100187d36cc60f3385d7a70ddbec011a3533d9f2146fe2def40cb5ae675a88fd67dab40628871b36229d3356576b664666fa0892437d6450c988e99e70b1aacb5c7e92aa2945743e9f8e032d6a6c8fea8c2a823e0fcfa83c3b3fad3fc610a2b81cc6342002dd7aa6aa7c6e255caa37c065a55cef9009052650eb0d5649bd9b6b15b5bcfd5fe8115e09ac28580934a0c0570a0570b2f1082ce46af4ac0418c7ed74183ce2fb3a0cac9c0d3e8cf8cc74618c59a8a30596376d8771bf2ddcc0a093e29e973ef3b37a7568fdb355a44fd329eb12729888819f52e9a6af62cbb25a76e11de4379d1857e6ad6878df538b121220582361969f4c64485817bb583c524d5fa70a9487a2fe8db58dbcc9a1593ebd6ff99848759c79c343009d95dc69573b58635862e839492590a4c222df1f8cd22bc854cc1cb3b66598bf636c16e83b7547c19892881c140c05146af28eeee4e79d45511ff9c56dd509243944bcdb2cb3e7a83c14921d3a28a9fbb8c8acc0f500ad7ad35e4121afebf7939a0778169268de0ad3bbfe75335bc36b1d9d684e30dfd26b10f41589c18c3d0805c9ecf77e8a66520672d28ac62dc0cc2b2b8b6f09c690e62d0b91e2107137fbc8ffb8115d813c4ec337dd568ac9baccde9efa7ce3b6cc749fdd2f24a80daafcc2827bd04077bc2da04787c02e6e8e662d38217ef345e056269d8f17aba22166c61f5133431708c3728c79c9d898f874e03c5246926419cc0a5245f9c3203b041ab5dfc4381ca369e7d04fbe310081a3d280ba028f7301190b1f044cbc3eb83157aebd88d9b43f00f51cec55ab46a73482a8f14dce80ed39af80b38d8f06ff60ec6bca4f02f8521e759246c20048742a2ec6032f8a13286e5dc469c0e7360e1a133dc3272c79d8783e2356df2b8bbba0664a94b6d2fb5d501deefecb181d4251d9515041bf564657f857df4ca2714babf30917b223fca1dbcf3ce933f3858662777677147b1369970968e698d24243847110f6732a9002340244ea0b96cb7e11e8270478d8b8322f17082d6d3e92b7ebeafb20333fce77da822c67ad7f707fb0d0092c6090e7671df12089ab4cea7e57c735fbd170eb1390f45958e98da02e55d93f62edb00f2e19a1dd1c48ceef44f330330856099cdfd44a869d18fc1412768a7d2c79ecfefa02c0660f1f3c104e40e6df3bdccd7a830a09e11b1d7cc621a09874a6e9a12103e20c5af88467bd408c510c32b4a813de8dd2cb08c5f7205b9ec90fe0e37e212cc43eab7298d7f828170d300fd448df92e3c86d471221095612b0e8942be580c23889781fda641390d32ab7829f65f3107af6971b5a064a7adc58cf42be9266ee21ff009c85ef15ce07b1496542e2b49b0236a740b091082f21c29645e5bf2616d983b033b2b76114f54dd0aa920c9d68dadd0dac336900f95569a8b064069cc5f4b25c4204cc5afbd9b1fab7269d346e415170a69a5721216e5dfc8b0656c6bfae9d18047f4790b72de1b3f91e4b99353c08d9a90674457729d3c3c83bc6bdea64dbd8d023569fe30b7970af04e5613b9004b6b1592f5d7b6fdee7244d1648ad60e1cade6182cdcae3a7b2a0dfc5ae9d815a61e75f6cb69723061c0f519e8bc065288bd9aa27e065266cc9e98b930906a022e24b14fa35ae5ebf22254acb4faf4e795d02e39b51c0017bfab684abb33c719409112277d10f522e31174dfd5b06c97aea490212667c8f39407508988b0b78fe6accbe2a2f055eee893e182f40b3f7d525914652342948331f2e53a0bcbad8b77f89528ff8c1119a22df98699819ed1c7ddedd04ac2c2e95a7502625a0f31b8405b58ae690b8f2a752ae149e32f00c34ebac6a3df2c0f96409c39d6e47c641c8e942b288708f7ac4c516c69a96af2c5d4e650f8dcf1fdf060b2bb0ef1295128d5a6eb5494dbf78096058d147086386c6a81bc275d9f286032576e5c312d151af62fd8e69b1fb4bc76aa699b5e14142eff64c2fb3f9e3decd86eaf4eb9593bc651c37c7f678b2033dbe1efffbbe430cbfc21f089b946c66aa0e5cce9d1b4f2c4eaf94685418d8577ad37c2dbf9d85aa855d077de7f94fe573f82f0cc2651b2971e342cce9a178b3b4fdbed3c6e42ddda70908688115d4f9ea70253e03d1e239ba7fe49273fc3edeba73972327dc01705576b1a3d3b8c9edaef97146d9118d196e408a96f934965e4266cc2805b4f77557576567946ac12ec0ce5debff9889ac8f1d6d90bfb80a15f9fb1fbab9eb302cec9d96a2ac566b1a46ad57f9c465cc498898b6ebb259089e7ad1a14aaf422f388fa0e6d4a6db3c27b0aebfbffd87ee75291d768bb32b20708c9b5f019e4f8d27170027c7e48325a05110b312ca9274b664c84b1a343e7ff8c83003ac3f8437ed3f0b515958efdbf02e54b8ac3844d41dd44fae1bfcc186a84589271cf91c707dd8fadcec6531e0f5d75ee69d63c324ff0342117d5bb10d0595250412b175cc0618999dfa86ce31b401ea184c064c67c66832058e186cec39c253e3e686889fe9bf0a863e131fbf6529e08869cb7abdbd8999c9df98b0616b8afe3fd8e714afc8fcf2bd941f6e7a1b82afeae204f6364e68bb8ffb13299e218e2e8ad6b18c64ad0c9a9799c870006cf757a4240ca4568c71d1ae9ad5415e21deef6c3504e8e8aaa9dc68d744471a789d939a5eb8a3bc0d8d3dc3ca087b0d30309772caf87b29233a60f24e9bccea5b9eff34367f14514fc0b3f78fba98f3c8a3b13725cb8b05ef8074d9a7e557153d8885e3fbc26f402c71ceaa4dd42b54790ba983f4d8478f784628191bcb12ecf45c391065c53959e6da1159a2457065c101e3071e1df8453c63c639c4c0edcb116889f249c2156c9179091b9bc26a5dcb1c71cf3946f15f175048fd41d7a756c85122a912cc7594636c1fd7b9adeb0b94009f3520e9a6142ebeb1160825e85112c82e210d4a834826b7b4db25fa26cda3dcd79c5163bcbfc1efc044f1fc8b6b40a313fbcf45200bd25013e1a654cf764aeceba1d9a2c01a79a6de5af84c2e55370eb2e15a87a392a17e0ba983ebd0faff136a77d99b723ecb935b4efb787e66ac65fc0b2beaba2368df891e4c3a4b7c2fe8f7ec6a608ca638f089f95c26d6f60561e1a3b245453be3a58761e85114ed8e725c18d0c8ed535c6e5c1af26008892248d0ccb7b0c7806ad6b0478486ef8a996072650b9647fd466ccdd725a714a447874ffa57b338e72f49ff8be1a3a004d9fcea039cb6ac3130b0562f36bab64c7847a664319ff9ab6e89f70e31deebd887af11d40cd31553ccb3e1a4173137f9230e50ce873f6c9c2edf71c145814b71d6e60659ac0ff5da601015e5eb838d8893289d1b7516e559187b12d580d13ebe8066d047a21553cd95c73cc8e8df004ef43e0f6db1eaf2ca7cb0ad2d03d38fe7783f09874ce2beb5de7a425bc4a2c23cc334f5562fa8c009b0e2808051e43f76af0451458b199c2d43441023f9f8cd1a2d337c184719162e5a80ee1e469e14f06e2f86b242c76c64f199f61a4b407be136a436d4330fc13abf363d92f98fa86a4cb28b16fcde6ee35b5c38911b45565f8cfa0981dd3b2b3d7821b739f49a96e52c1daa4b63639b1eff5fd4a4b6ac70f0e8219e43fce7c005fe3254c77d509963f9f2886209135710f192595ff03445c95d1f4f634ff80536d286098e55ebdec72692337d8078ca536db91b9cc0f5761c17e2530b5a46b4b612fd89ce25400f0c6c509f72b09678193a879e8b9d8c58c3e7f3b83fb911562486c6753ad828eb740342a5fddcd92f49ace9874c800ea72bd7f66c9dfb826eb120bdba72c9fead5fa0adec9b33fd5298eff041d208b94c5ed40645f1546f02d594ec3a7ce4c6495f85f180fe5eb8cf6a023c8384d2a358aafd126e6fd84d14a89bda0d228177df42fcd0c2dd01e1edd2b280b2aa243d9dbc48d543a436d487e34a53e3790e7fac9882e7e15f77435485efa65f35807b8260cb5a8f733a233d2d70aedb4ed05c23a19e265a492ec2d06612be05209b761cb0d30bfef4b8c31e1cbada752039f9c361baf751cb817e51020288c198841ee4922f0c1e57802fd7fec2e0813b64ee5096e92e06f6f21a250c687020b4d9b215a6f337a23a29705d2e0e9787bf20ec44feec3527aa9f69de989b454b51069da8391ff4deff6c1fdf6634a57d1148a3a7a9778adeac3c4a5fb036b9a4dbf507f45ec7ff40ae0380e848dd7b11e07ddcdc0bdcd6cd9dd67336e78332b75f0067802bf03dc10889221b025cb33186b6feacf88ea9e6f4e732d4661499994909fd8b2a591edd6424c077d894dac721917c81c6683bef68929c09787622b9323073d2127217d5a47c22a6c6b02d45e12512af6c195defd6d440397f6e4ed3fbad7af57dee253d330039c2f2c7d124d2838a39f3a9e5d5265b4f77ca61c969a2b144df534d5512e15411b3e15eb8ef0b32ddea1dc4914ab2ea3ad8e9e299b9b700a8f3bd422da95fd130bf5d7cb3141c042ab601b8a448d22bf96265564a25443a996da06221a2af6bb20c3bce71615c9f1cd6373ca12a2249c7da59cba2e6bf453e6c0083f6231f41c06b9bcb0c3a08c9285b898b2801ae6b90854dfe9be302768f520153e75f881833a8c4fd5fd627d5a46308d37634da261fc639ed6d34825a039988d6ca3eb5028471e346b5cf1daea53dd0a235f8600f88f11dc5f73e406b7811ec23b2fdbe52b8197ea05831f73b7d6b2b3a26668e25084ced3603497c2dd835ceb88b4b30e84ee6d3e0bad096ec0587523b002f9e8f18fc9341fb4b32a7a40f81262b54ded7d0d52c25227928c4579ae2d92edb470ecaabe94cd0e4e76933ad8cd817392c646c9ab45edd24d96fadec1c883727746a9098ef420336131712f579536b5c6ba76d2ca0ae4d2c60a936e99705f2d1e90403f0f8a23c653e0cb3835c6460f036bc028bec530e6d8f2808e3e01a8f2ec0d4296b65bd9c98b5246dfe9a2d74b990e9a49fc47e3c31553e809512f2c3d5e1a9decbc377338c71494793eb6d4cecce6c54d162dd9a00f2edee6a02149965724b3a11c2b5ece31b1e91b10047ab03e1cf16ff005ecb2278a05ed7464d07234f22ab7baec21349188eadc92888816fc6ef1206c10819d192faace854c0a59dde79e7481d2723955c5909b2924038f24ed1b55bfd2d6ddb6e256ffad58ddff825949506f9935316108b221d6ebd457d8a91842055f30909396cfa1844f921e15d2aa7c8c1e0a658e1a667d6d3f23a6f2b74643e93b48ceb65160511703e9773e4fdc8751650bbfdb6aea7433dd89979aaed059ad78e0701612433d78eb2bfda370a5580f731f883a4a9a8994dd5b7cccb81ca6bd19f3e01ac851949c58a1b36bc4399892c7b9d8ce1b818f93f00840e05a11e02df15e8f7e0f6be6ba9eddb5c286a70d66773762dc65a32c1812a2e263e7282b3770105704022494973bd562b2594e8902edca5b424cdd79aeb1d49f447c057f3f2743d5a646493b1e5ba20a3255ef6016173e0e0c502519a562045b24ab535f6ba81f25496c45857f8c182b1e3714c718bb5f605ad24d21da803b09fa38d610c9d85d40470fb6d6dcd1601d190d830c6db9cbddc656aa221c66c1b4680a29c9eac8c23c98cc84211078c3e9a035c8a752681ae4534a87d3ce2c1139a1d514026950e9cf3f2c93212f463c5348afd51811c2098042c4cab49b8c039a8be850381692806ed7eeaa71f12efa0d0c743ac95ed43fc1ba21ba58538d1be5a69b55a33b90e2b0ef273eec0db0cb5523833c9ea3bde3ac495ea8dfefb842075048b65a4a27f815c3c7e61a984556e2c981d394724702f5210ce51e716c55d8dd5cb2c1e4838f4385cd1c62c1e7abe9f96cde42b562c7d13fa635575778a47e73784d1c98284695d5dcd908ee7256f7baeff26d8a1383f482afab04d46d7bbec479aac53b8c479a82cf617ce856653b4080dbe118fdc03da6e1eb6089943e8bc80b145b1e7f06fc56436266bd6e9802098b51e155138aacdba834b24d104c46dd1964f7b11b73ba51a3b7b6087c01dfc677ff3d2052f9cdaec41929347519a7db8d2590f800fd2354c0db458958e81521cceae5539d8c02d189e226e9718020c04eb25bead0b8fa4cb4bcc2b3b4852c3545a34bea388ad347159c3f38beccd4912313ebbeaecd8e27cbfeefaa3a012e4196161cc33e646d78bff0ee66147322f118719e888e234b0092bfb5e18c8a9e8f2d8f33eb44d08337b51c33ce9cceac0ed6664d0452be07cdecc846d38f5fb95c2106d5dbb41439959b1b0604e6c8b65f700ef2ec29ad8237a76b3004ce0bc064e40e71cf7bb62b4636099f556380e61051d9a7971e5b075a68d1b41f7b84721d78ae6ec462fe7896b3fe7d1caea38450fddc568d4b81a142e565fa409dce678fde3ceb13e4bf91654746e250d4c619cfd64e77b78c94c1a1bfebf29111cefb43056c991d7b3a62bca56b3a9cad42f48184f961b6b30c24cb50f5f821877687e09167e193b41262853c31419890ac53cab3cc43258ad8b8b624508efcec98b1a90f7b2edf53600b75d1741df381286c02ac66e71c37bcc75bd4c521b1e707a1232e1191ed4eacfb354b2dcba9bff6a67c7bfdb211715493819577b9fb34d77671dab4aba43290987a22951134ad9f0583ecd760498bc562110a5310ae83c977bdd0a50c8fe2e36c7be290fc3db2ed2700955b56574010248ee32bfea6b43209f6ec684f0b9cab24cde060bc70740ae610335dd29ff06aae0a9fd98b9eddc89f2482190d47c637906e6f7237414f7106f4be4476a6e707c0c1875963e71a087554deffb12357141904ee97c4f0886eb1f872012e5668bc11fd515a2ccaddf0b402c74a8d372b9cbadc1c6b220f14e80e7149e985773bab2824d6111e8e65873c8cbc961916b6004a574388557ef48b6604ac67d72ba9628acc5530a726d75d6293b913fe7fb0238da293dbfd241081cea28e937b04d237071307bf19ee33ec1bf5e91ad1c3dd68d5d5e83e1088f4199e296f69453325a2d88c3b023e11636346b627ab02fb3a014e6dee0a9c9401ec289f10170ed995930912b553e7ce99262578953a23383e174bde227f63ae9ec2973de5883a230a4886c89b2fd32b8327a5a9f764b442ab50951c9f48867a4d3bac6100a85096c80b080403e2df351a6c656dc88d9315522d10f5cb8f22ef865f6534b114172e9560e2f8888b8e6bb81295cd686f8fd55c41299873ea825a6ef7e491825b1e58a8f356e87dc10a6d4046a8d0d7f1a304950198d45109ac199201e9a5be78ac3651f132870304d52960c0b5c349cc1438d4e234c40bcf830956e731e8c5b3bbd3cee5456010949bb103e3030dffa55b5c8009fb8878f2b0d6803305fb899b7b644343e23026cbeefe63f440ad3640f3b9439dfc5141a3dbfc0913e917828421779bd9c58a59920c400de019725af3cc8bc91339e79bf376cfb04cc31a4bb5bd51476fc0c921caf6f35dc5115a4a31a4e047a921c730122e14cc85905948491f6673301897baaf52f36e21a9b6cb9b71f505a792db74930fa51226a465af3b708cd12482c9eb163721c63909fe97c0d2dd56a684a4a390f5282f52d630c6aed1723294ea45e30bc866beea4acce1a9f9277a45070106c43934cb4f5243e8051c89e4eed61353f0f9a0c04bc8caf4c78058b04d1f700d81ad8de1764167f608494c0c18978e4e0cd9c05ba2d8709d80a9ba3645a7e4720688cb7928063fb5e2c0d692a0e54d8850398262c4357b625fede9d63732dfdebe9867e4ba097de97af15f49544065177b1dfa682a71a387675baf505fb2fc1ce94275d2b14dfbdedbd849e065f9c02ca1832376a8ed2f42c06789f3d6f6ba868db29703b15a9db5534184b0484119fd390b6bf95af105dfe87f69f70a1e8bf072a6683bb755bb934bfd81f8cbbea1dab971f50224200388f8dc402e22eacb625cc05f5bd8e635022e0a092899d7844b4bb4b21a026932113001c6492d812470aef2c6d5d7a547b020538d2b69147e1319a527ba26ce8d80e40e71317ca5b830ee0b9202fb90ec8537bb5581561b3c9650ca347da253e793ac66e0c9b150f43a2f149201cf85a3bd681f43cee746db3df7da8dc2edbcb3f9327ff62d6f1bb6d3e1a90e5b8c6236b0a603961d8a2016292a0caf1fca81740f2b7f75452f30a0a81b8dca9cc0ae44add3ec14cd998ade906b16b77f38b63d3a67835744c919ddbe20f42cf605a9e817c9dca01391d4ab187c56e848f97b4939593038aa784863984bd2c777c33b173247dfe5467ee2f2a95fb87f5f44ccad546d065f020c89cbaca5d5e4b333f1571fc5633cd8f52bee1722422c7544253b818b6cc074551c900370fc19f43cf585327f6be536a641262eb75fec04a17b0c58047c313e5dc08d939cd83b4b6399c6eb8dad15b057079c7a06775906d949f91687c2b575b7d6f5f218abc1663ff1a51ccbab6de95c4187dd2938ec22cfe7d8225a15a7403990d66a269a6af507d472ce03e9e6b18a54431448de3d04cc71c14bd8cd9409fbf510ff78790cb03e9f533f50dbfe1dcabe4b4c483c8cf132b44778cf49f26b664158dca9c568aa7e2292256982fa69414fc420beacacc292a95591db1c9d5435dde4b7dc96ff7fcb5d7f22a50d8f46a378389734016461e61ece058534d2222e5b489b2c28ec80d7b7e18b3582990e82884258001a136b1d22e091a4f0ee7a9d15569c207fd51e6e20e3907a62b47efcf8e3b4cffbfb1832ec485fcf44a16e559163e1d23617cbbeb10a45e5edc48ae4f543d9090b1834c34abd5228fad07ab9fff2d116fd7c17d9046a1a60a0cd1bfde28c936990372f08212e781b49d9039f9174be1f973a32c4e120691e795f168b92e4b7e272cc602ea38327a5a304c61b53989c58f799d0c0e0faf22e45190a5b49dc6a1d625e0652686cb5c0c7d9c03b5d82330b2e32d4030be6a6cafa44d152c14180847054e84820065cda496c8d3230d60753513a37db5cb35d182d7dfa3df429b4899a40c96070f082e0766880f619a20b83b44081d82ec521bbf08538488a2f0ad4942ba2d094edbfaba451419f1095fc48fbff0e7496e44647433baf1a410e41dfe72e009c2fded10ff6311ada828c4873fbf5d28264f4a3d09ca932c192457ba2158f619766d2ce6362673c4b74fd16963f149d49da29438b5f117850041100443585b33c3aeda9be1cf6d22d3c66f9ae8c60fe24a59c7934e10ae2fcb93424fb28fe25bce958f638fdf9f1cca932678db3fe1237cbb608fc9c7753a3cf6b94992097978fc7789277df8228cf1d0e3d9e357806ba2ff128febd82c7b759473f836e6f213be8db69c26513b3505f96944ed9ce1718733d6cca876cecaa2da59d676daac9dbafcda59ce529c6f5fd3ec97a6b6d257ba3781a9d3e4f04deb75e3d7524cad6a0ea69e721bfe20534b7530b54e4399fac96df87f4ced24337593dbf00b99da83a999dc86ff832966b94ddcc247f8c52a3fc2e88c4bfc3d5de9341bbf9b8d7f668aab29528130452233dce336fc3433e4721bfe12a638858ff01f99f853e05bd8254af9a0de69d6c46437cdb41b84a9f79069f7ccb707d36e21bb3b98770799777330ef2e4ddf31d33750d626cd708f26d09119e8fe31ed0c3fb4d0fd322d99749730c71ccee270b9a7a727371b5b8cab7439863fb761dfa009fe19fe46aed1376e85e69835fac62d15cac72fa2f826569111230e96982d3438ac22091b1a8ac03065061a70f8c35fc8e5014a09224939c3b7f0e747f8b59e85bf1b54096e4b6648917d863f99275912a5c0476859c5b00273c52ac67ae604ac7dda954ad799137a57db68f420449b3b3cdea8a0048512c294b0e629ea4dca02f8d65a8b8ba094a7bdea00df4e24d064aa593fb29f575b3b4120da5e3b95ce99056b2278086ea32a5b74a0828507ac328983044af889d055f3c0c19a076ebb698bfb1ddc57719fc5fd1a95d27e05534afb368c806fe0a38052d2f011cd6b1848954342ca1a08ee0d1b8323e56310a41c8a535a54cb8034237a235a0bfd7673e028ee35fe8ce66b7c6dfe9821bc5e1f804db3b516afdace75eead91816cff01e850144d8750d2c8f64f4163d684a96cffdbd0d00d70ddfe493d14457164a7d7d5f617801351107285ed8f82545114a58104cff60f0094d7151ab63f062f1445d11c16cdb4fd2f88d1056cdafe48562f1cdbdf026dc6836efb57f09ba365fb9ff0a128aa036666fb9be8a128dae3452c6bfb0320cd5868d8fe2574288ada70c234b6ff518aa2288f1ea338046cb2fd49fc5014753a02d3b2fd29f0a128ea430a7966fb8fe8a128eab4c2e86c7fa31545511cbc91ea86ed5fa4a228fa84054bb77f0d47d62ab34c6d7f131cad6cffffa128daa344511e706259aeb6bf883c435f59e26cff1079455154aa041059f46cff09f28c084c4b8fed4f9467aa5eb2fd693e14456f0cedb4162cdb1f04eea128da34b4825ac46cffa11b435ed66cff998ea7b5fd3f0ca511b5e8d9fe1e7056217cb1fd857e288aa6705e33b6bfcc87a2e88efb82d863fb77f01e9ed792ed1fe42b8aa24fe516aaedcfc15514456fcc68e82d69b67ff92347d09638db3f964a6da961fb035dd584ed0fb3114504b2fdc91445d11c577e906cfff1a2b32a8d65fbffd810c56cff178eab1facedaff39aa0d585ed2fded8d230b67f68e327e6d8fe20d2ac069aaf0e45d11b434c1acbf6f71444d34bccf6bf6509c24c4e79774dbbed46e2fc659e34b4fd6d88429bed240566b89600eef726617c44bf264b19d66f6f4ee38ee83ff18b38bfccf0c50e88e03bebefb02d8c838ca2fa55782dff00438c2f2d3ff8e287262d83b55c0a47c2b6fc38f0459b9be1c01f33688622f8187c9cd338f0fd5a180776b598e906a54548ab33bb295da34e061a4b9fa830fe9ec040a5098b3e277252244ba8dc00a34eb842c5e995b4a2a9933e548290413add939dd1e703a582e4e521d501b16243840a94d72f0bdd32870a16ad75590b10181a5d40f287d26083ba67a562f5c2ab88b2598afdd85c31e3c10234fc758999033b01f6bea440eb972c54f6c0c254468e181a4646972a2f622156305d020a0343499514d603d11e9e3a799caa38e110652306e8c7a64f951ea3aaf3526508a851a63bbd3031821c014ac330515d6290428af8f9c884c91293638da960aaf4783981678035d461e191b2a30a160cd4812a0c3d4daa6895413d7506fa65489518c65bf5c34be2c0a670488113933d71c10efab260d2b5ce0b258088fd7abd5f183a3b22b00fbadfae6b6d72b5534bf487b5b6c0b4db6912650a63c390307cb0c2d8d074ebac59e784d97979a1546dc870f991e152c50bfa998172c5646a97a6c34ffd81e942060c971760baec762a843d1878903d3959705ededb89a99923315e3d334676bd3aebee0591c36ae60a941a6787e7f5e343bb4cf5ace8d8f5293fac5ab0d61f3d1a3aab6c563e3982449c5042af471a29fde3f106caca92133d2d2e5144d4ce0d98cfce932b3fa1ee0894962a71ede1325aeec07465806429f38425a54aeea57360f8e64059b9fa218166dd9a1c6ba4585913d4e325a93164caca16a8fa96a82c5cb1f21383502b335396cc287132e3a467650698cf55335050335e5e693b49ae63b2b8fc3746ebce3a264e94315a28939ea94e18b542d342cfaaf7646506aa297bce78286521b5afaf5c7844d6ec13c5be4496ecd3ae1ef669abb0cb66f7cbbb44b54ee9426f58272a419038144b05cb073eecc33eec3369341ad1041384082142c49bd934b15f33e8a6faa9d4cda65eddb6bbaeebbaaee99aa6699a5eabdec5f26dadebbaae6b9aa6698a732ae24db3562b2a321a91478cc07e4770f000df40dd96fd71e5df6fbda9cd36cbf7e94e5d755dd775cd6b51adc8c868c4080a282061cb361bf66b2b91748a729d597d2fff3cb0d9fe67b39fde2a7f33cb75739f7f6208e65fce3f9c7f4646d79f02290a966c7f125324c86bdac86b1ea925728912d86f090d44d3e0e562e31a18dbb60d8a1aafb807f6c6daa94bb007ea6cfb04c1de098e00da165b6c61af2b298091def324a197068e40c94159da20b6e53dd97a6266df10dbf29e4411b12def89136d5b9eca07948a6dcb535fd822b6e5a96372a862d944dbf25421e26c5b9e3ac3890b591719da96e7a4b72dcfc9bacfcc73126417008e7e916af610d54f93243bc4b6bc264d3c263c2677b69a4c32f942db96c74409886d794c7000c1c8f1270644d30068e307dab8769620850bdad1da27ea80ad956ec3f82db6165b5992f537d6262d21b36dbc1f3f285da2d07064007d602ce53022d5e6cc963a3aa440d9b1945b53aae0e68d53112d310c19b5eeff083d7c68fdb8a1c48ace004d49f6fdec379c91d48f2ccec893dbecf6d7a5079a40c98a22841783066e8332328ce1e211430e8b4cca2e75b9bd0c31339526c90e1a5e7025520b303860efb80fbc616a4e0a679ec849b284c8951b76e840b1a460858a0f900d6e6aecf4204923058b9b13b25ee843278f962724b9861ba844e9d284478e9d3e67c8e0e8aa91a686902b3edea5810e35bc3d2c1ce1d28252931974f6f4518247891e2e180d5461a0cc4026059e8e061a1e18363488e4bcf4e1f3eab3cb13030d4c685670f244043b17ec3411f2232523f2b9a5a00aa131a6851c5242392d36ec18b32463863c2417942a43ba84474756983725b0a0ba51edd8a0c347cf807d31745c6c6c39b9c1e65962ead36381c7025428833ef2940a89015da304e1012506a82d60b4cc8c31480088d49a1c8e1856cec4e498e0a3890d1e43f4cc10dba324830d9023768abcd0d5b4802168b46e5465edd070613d575db2b4682c6561010912f5898d3d4650d0a3fbc00b797649d85ce9a304e7d9412faec4a981c99e364d38fbd603229e385578c0ac2908794203777e0aa51c1553d7993a582618c1dd47ba7c2c990dd8c1eabe5954d0d3654b1b2653948a34ad3193828e1a5dcae0eecfac2c98771b8c2c210c43ca8f4b6c4832b325204c7240c048532e8981c5d07234c64081ba602921974c0012c375471767eb49d52f0344563729d488e3630d53950f5551258c784986790c8d557dfaccc6a52cb07149499078e7c58e25ad5a172d3bc4bb44063a9ba185c38baa9810a1d19ba431724688151bd8cc888acd5081f295185113ccd05304036d46ee45130fe29d18363a7479628278474618a318738648fc82f1ab41aba969852b15d8c127090b6564a063e6051ad997177382dc05183366a38c26b4ab3563ce496d4619a31a1f988608c978f2f005069f204ca62a0618302e6876d89249c145f3f2dc3096d896cc102c9bc3b6648624d9e7cc470014f4c2438ce825470d286a48de14144819d1876d7978aaf478219d947ac4b1618a173a63d4e0107f2a5a90f1650f9b3e3c2021d663df7240bcb34fdb46c0551e1b51b4a8f8ace0ecec2ba74a579e1e2dd0b0410b97012976d8a07af8b8f025012fbc98b1848f9116e47c09abc008d9f24d5941862e4c706729c2b04d6429c3030cd31c1b7170f6ed06c0f007b0558e17b6e2c84be92b94767f3ef252fab6bc24b91daec8be45b8fb8619add119bbe2873510b5197400e8efde5a25fe51b5277e1e016cca717c0b5b8180144ad8933013015825d0f823698e3f5ed8eb0d833d90693788da0c647b7c306733f03dfe6bac6dadd2f6c087991ef60802a9f604f817f4294f10dd3fe8388ed864cdda13632dfc1faeadfff51ae86dddf6faf031ad01fac3308cc1c1375c06b14170806ded090b7b80c55d742c350fc9d6ceb6766a18075a07d65a80293eca6f410ddf6cddb6e6842a4cb67047a6d695002f9cb0bc8821f3bb34e8aca0832125630ae7e6afc18da1a8496c7a972d79b85e24360b30038c16eefe6ea02137926e4ed003874d17564f0d56a6702494088223496cda352a6851716e165de14618894d17fe864f0a707024fc8841a1a9e80a4742072c1cae8930d851c31523b1f9fa71152609ce4dcba50d6e04140e9b2e2e9c150a8a23012351c281c46628f5dbe1c38d412436c315507831851b33f60bb31d3c842a0d45509c9bd60b131c097e71960bc2b8d0c3e5cf79c482c385cb4a2f255c4c09d7e1957042af84fb806b340ef087f89570fa95704ab8f2957041af8493bd12cec32be19470f63f98764e69ceca2d5907f3a1a4406a52c64c141db4c047fe25d694ef7fd50f40e4287fcc1142d895b95b8194f2d6aa004086f2bc4f4c3b250c6536af0e1f4d3129ef9320a4741dac61b44627896efc2fdd7e49ed44aa3abf8d715676e3b62eec42884e695fa84d695f05b6a63f688ae0b529a5ecca909c1265cab0967d19cb6d2088944ee519feb83c4936c33f757eb036fee9e199d5deb3f1e752944bcafbb21f5fce9344b81498cbe1dbd1e307d3b02abc0ad3846196dfdc9da96b8f8a90ca6fb7cecdba6ea4fc76d384507ebb577e84577c0b618fdf0060e2f183597e3bf1f841377eabe0f1835d218a6f163c7ef009df901e3bf9ed82c71f36f90d83c70faaf8168047f1f82d9843da27982b013e9529ac50982df011fe00981ee023fc189897ca8ff05f60de2abf3bd302f3aaf8087f05e66df223fc274c00c0bc527e84bf8429e2adca153fddddee3aed2e14baf167aeac991bcf585ffb1f58c093ec078000dbbbbccd003f03ec9e71b0274216af84bb9f9ed6fa364d8b612d9f22601aae41c07160cd621d762dc368afe374dbc74e595d51aeb015f9b10529bd76ca664430d8858140340dc2edefdb6b2705f68e6adbddb6b595244992ec6d24bd750fe73420a841321cc3525fadb50581f4b5800213caf363ba768290413795d4ed4a52b65f10942f52afc86e1bb53886e09847ec770cc10f0d11bd1a4a0f53e5198bf576ecb7af88ab7d5fc49527f9fbdc16cbaaa1b4e7dd9ab600bc633e7cbbb1ad55c676185429ef054eb15f8996b9d82fc625a2978994f8c8aeb877bf3db2af758994e50d12d2c66a810f9a3133c8a0d2c0d91e94122e19603c695205c93e0b6c1fc97e0a2eb41b25be37042b2eed46e93f922190019a946ca0df5b25b82d17291f9b167e7e70db17ef25c7b7e2b5f80133a258ac4614012520ea0b3d3cbe3051c302cefa51f9319343ed24776c8ba675b169fa479b1108e4c6f80510559e331c9e220099d9dac211b49ee11951074898b9b54af2c77f3df976bffc453ef9fa4752fc2b661c92b56b6d200edfc5d79f10dfc3c79a7cbd6a44e1e3d7abf0d9ebb0d681fbafad55deabc13547e09704e0b53617efe90245affbe3d349d8e2e7fb27f467d88ad75f2dbb1be420811a2452ecfed820be8b567ccf2fae00b75b0c14be0adf59b4f662a0b06641705b23fc63b4462af0b3904929ef9f4adbbacf6a4b1a3f0b1327520d9f642c4989c465e3478154c40763fc4829fc5ef0c568952eb616dbd8bdf7c6624018871cfc31ce3309d77d862b26e87838a979b3a3078e17aa00b9a2068f1a3d53422c613ee244cac53a25a6284d2b9ae7776587528c2c53388a3c95c9c2b2810268e30ba8d199bf915a612a47560a2500915a75dbff81ac329c92e099928294295a098ffc630c677431a1cf6882e64226460cb75104ec62230968b43d9cb1596802478bcc13115e0bb813694a1130c976725bde14de141b7540f0158afaf57abdb4183ab8ae29af2dc59081c245668aefba0840149e1f8e840f3edc385ae1481871638d4978b7d5faf5faf9f9f1e7e7e7e7e70441b65f9fb7ce4fc334fc79e35a1653fe3ecbf7b7b9bb97315f4b34bbb2f28ef75ebff6defc17ffbdf7cb59c6eac881df6c15282b94ddbe9f813abc2853971745b7efadb32fad85c54779c4663647f3f15108024f79e67d5b6ca4a5f2e98310cd7f963821aad2be85dda92025a57d1042374afbf649739c990cf04f7a51826f2ff9f7de8bdf92a1f92020ed35d42e6a2ec6276b2ec87fd54e25dd6eb1c3578141e062fb5bd21d04a41dd69099466b74ea1819e310d44126948584b05f21215208f47d00b366e0d610b867fb83007fb44ca361bf34d0973e39413da552ba300dadc2aaf02ab40ad7304dd8739b876bc815ee09bb42aef027328968f813a7442971893825ea4429a22aea442c318de846c4127b6296e8137b8e3348dec72f6cd2cbda7aa8cd208d1ba47bed3a82ea0e5cadc01e964ea7d3e97461aaa538e8f3f97c2995ae2aafb6a77103dbb9a696333083a1b8aeebbaea344dd3f405fa7ca00ff4891849180c0828162b39640e1cb05f0eb20da2600e4c9f401d38a5b14adf6ceb7f36ae704d41354dd334dd812b6805f6402c1206145bd7755dcb344dd3f4833ac86442421e3c7c98e5d90cfb9d75e8652cdfd68f4ba7d3e974baf0b782e8baaeeb0ae6c0147c0275e05407994ea7d3e9843cacebbaaefee66c0804081a8d88688210394408ec3744368376d64d657567cb563f2e54d485bfdcfbfd32d6d68f6b08844ea7d3e968e12ffc4d104284887fd3ac15e5a222ecb788c3fe61ae9ccb4f62afd7eb893d1d3e72dbcf74659eca6adee5355b8510a1d3e9743ab3565464643462040524320912d82f09525b95bd1996d8c33f9bed7f362b4b8db94a74ef59eed3fca4355ad3aa188a3d50ec6523239dd34cba49e734aa9d74aa51b7f9c7364e718a6f1a4db1d5c63d8c857d784ba3f8a6cb99aa51add56c026d15f886d3355dd3355d29c0a9104c42bf80607b029cda13fe384db5ef4472bda7343e91f2befdd8bd37ebc61fa2b77dfb620866fbd87f484f54adb5d65a6badb5d65a6badb5d65a6badb5d65a6badb5d65a6ba3a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2ac8d8a8a8a8ab2362a2a2acadaa8a8286ba3a2a2301e329a6e23b7b5a0ad9d2ef6bd42466b445e9cc150cca288fd8a98c46028ea577ebdb0df574886faf533929924b15ff287fc216140b1329725f65b92402587a00eb22c9361bfb21fd79e2eae1fc804a2bf0e289387dc87593a948786b0df217427856aa756ad2adec259b80edec27bf00ffbd22727a8a7544a979a21c8b7caafb63fb6ca39a7d9fe60ee85390cb1df30af455be5e81a28c4388ee38feb7cca555fddeab75af5b07c5845bd87a2288a3a966fcb7fcef552555555551445511415c18103070e23643f7db94a7496fb74b5ea61f9d6755dd7354dd3344db14f555555557d4af5ddea561afb54555555f5853c146d95233aacd7eaf62e966f6b5dd7754dd3344dd39f8fcb51cf79fa24a6699aa629f6611f0eaf5f0987ff03fffb1cf8d75c30b1350eeeeb9a8bd75f17f7dd5f0987bf45072a5858539b17f8cac7dfa203152c1c88665f84bb69e073a0efa6d92f0193fc25f0d75f0226618d03f1ef9740bfffcba4d91a0dac41c05f3f07febac6c17df14b20d690b0518e12098c1ac58b3fe79c7588712d877fe69c33066dedfc804490d25a9c33061d6b51e3238c31b6d662077d3c328ef6832d82ef0e5a533441986dfbe0db1a0e9f06eeec38fc138777abc0e40ef39f38e70f901bfcf1c424789e25185ed80a2b92d83cc18db17e91d83c1d481bc139875a7b2e8086adc09fdf5e117f075e04c31063ac01aea1a82121bd604e4a133631a5d1ff98452210c439bf2c2c35bedd1ce23084ad087f4212d4b157eefdd0b0550548f1396fe036ff0ca240ca6058a53461b38121884269f41f8a9948a6f508aef7558002aaf68f167764b739ae01e08492c7679f796b9b010d1b5b4055de325a8333f0f0fc542961dbf278592393f2675b1eaf0d8f5726eb04f4882a63dbf278eb0b8aa7f2a644f1155a5df2784cfb9cd1d1b3b2e46a0275e8448de4c20d1d5c6b74f0c85909e239d2e4709323ab9c09f9e194e554877795ded8b1dbb1fa91dda72e1d7095e38d9183020d63d4ec13e98718a41a25b92d6f8c96a63151e68c81a252ea6d79639cfa8c9191a60cb7e58d411d20864bb62d8f08179e1835cf78de7dfd4ffc77e6e669c9ec7a5b84fb72335b7c947f0caf9933de2376775cc65a6b6f17987736d31a63c7a05b6bed4df251de17d98461a85f76367474c100b67d33e39cc18c6f6a45f2c60bb54730eccd83d9db8e4a1ddbf5adb17d035cdb6003249b4d458a221bf895bdf22d00686f308a64381ba2dd9d6b17bdfaf151b88b8ae88ba2afaed1bd76e66d6fe6701dcc203b0e63f0b567a6bb2fc9190451d81321ae2181b593dc20e8a0e313049206bee79208348d4edbe70fc19d419d1466ed201886b59901bac85194e90fdf1fc4d63ac9b7b5d9ab70d1eab3745b58b30e82423bd794b6d661dbb7f49efddbe5b7991fdd77a6ed7eba6e5391beb3a7ab3ffe64647bd3c672742edf26f00b5028f2d07a867e6d11fd8cab3282acc0656948956ac59560b0c0864d0d17ee4ce9e36ecd9cc101e7e7c2963d5170e7552d60420d3eca700913478753b262260d8fce12a7a52ddc79b74e34318149d695b58522b8f3fef689ad9f1b28415680410ccebbb459b22225eac75b42669f469b7cfb65934f5afd361946cb26c5d0b011a08413f9cdab8c36cfea84fda3994acbc548ba4faf029366bffe46428e9a279c7e6b57e8f20b1e9df428f8854adba48ca2e88b1f8ae2b657f9d1fdeba50bc5c67f4d283d1dc7e8f2de5ed661a9512a3b802c0db6225f2f6d367e109a0993d95010f6628567e39fc1566099ccfd3ec1d225743fa0a93a61e3f720a24a4d1fae283c1d6694a4b4ac676a7052a78707a763a867dc662074d57409b3f1cb602bf06ce3244f55b45c69e3a34a8a2b6d159123544c9cb4783cd160c1b431c618638c3bc05660cf77441a3303b0575b9cb6f3b6acb0fdcbd9bab4fd7f5db3fd6d281cd9fe489687828fc785ca765e971256b84c5605cdcf4d2ab316391b7f0cb602739527791f0c8a7d121921609f28b6535929a9e06cffd9142f8b9bed5a8e6c4f8162a9a1002bdc430c58e0ac702b51e14d1a33172c423050860e93a7262a3876b8d27a890105831e1c3a750ec842631e6094c058e0db0cac152129cf99c5ea604694f36bd88a7c7b1be317a98878579250b0fd43bd77494a524696b2db6bb3f16799ec0784c79b3736943182e294d29c992954a913346170fe98053ebaaf616caf5264fbb8dddd3d694c79ce66332bbb8db14c76c54cc6a48c2c65b7828dadd0d06bca939c11f176bd0c9ec8686faeb4bcddba2d6fa7ee73bcb3ef9bd896b763f2cfe36fdfd956e9d3b292e8076bdfa7599126da6f616f63ce1e5dd2de7eb0b4146b91b4aa776ebbafd533e579811b365edab8460b7b3f5dfb7631fd98798f7674f27c57d5201925fea98140eefcdbf36a55b5fe60e19bb6e24361df0ff3db170bdf2cceb7b57f7e5ab5273028a2c729bfdd26eaa852a5f124cbab02a533dae738b5efd81bb148dc39fa9aa652d569e763fd6105a477b13ce97436fbfe3d41a67d825bf6fd7b8a7bb693ed44bfb8ba2b85cae80ac53eafce4dd65d3ab1cfdbb5cb2fffc5f5836a156bdf17b9342a72895c2297c8a5519dd3a9c8a5755777d5bbbbba3b056e41425281b4923f9ea1bac31db85a6d90c9934ef009cc813930772d2e7dd2812a9b23b087d55ad0292d0ef6167b607be304603fd6682d7016d60256a3f9cf6d176bdfb43c1d4befccd3755b876f7a372bd5b7e9f0cde2a6d4ddaa557c74417005ad808420c2ef87cde003bee29536820bcbe5e3033fda45996cd676d3666dd429d7941b3ad2464612de0e15a6ec9d2a223ea87435e9d9e169ead4e449b4fbe436a87b5f6badeff8fb37fab7d28b247266c48931c38b2c383b7543093e186cf4aec01870f7ed335e30564b7c42f01fc1df830f3cf0a45ba359b779f62fea2a3df8c06680b10e4d6aa2eabe28f998c0b3dd843d724f8005f6f63704d88cc5d8ddd4b4dd84d35da7f870e75181f2983bb6265e6cdf12c2081e0499a8a8946c76672d0c91b211000000002317002028100c0744921c85712892d6f814000a58923e64583695c8a3d15010c2280aa3200a611884100300320629a58c328901af7673563030c2f6b076330d324136a376ba9b9304684af80ce0f103a650f70f95e22564701e2664850f830cb688415634633fd57b2eee3515ec04789af8ccfdd3804ec1b0d4cf0d6ab81bb4d058930027f2c593c422857224cd21e9b7f9b3ea989b2ded11b102e6893169e9cc544da87b485ecaa1513937be55046e12ab36a1acca56ba782d4c4cb8e1655b630711a43308ff1c84fab41bb597163235b29eefca09c712028961555003151cf3ca4c90bc591b6ee9c40b4a3824f61d61c921fc85ec5b45a42c3547d36ad9de822bd57af288e2d62273da847b2bcfc455c4e7e4cd5e4b0c4dcca61ddd2c081e3bec9a328928f1119a0d339bf8000d960a58889eca166b360242c18532e263d0acddc801b433a0c6b238d9dcbf35850e16280e0bafa2d34bba69552560d10412e4d1dafa1049c80631c751615c21bd10d0cb08e6e8bc1095326abe0df23431c94f8a87e45faef0a33a7d9cd519975d3ffccaf666a8113f249e889dfd3c36bafd3ea16abac94bc79dd0576062206190edfa2a404a58cf3ca9a601bc0102b250076983d23dc4a34508ae39f6e38c63c3651ebe1f205c9c7581e8ffb142a39712a7d826a06120d25116be90fcdb22d69da1a4f6eb1d5c966b74f24350867059aa168d1d2cfb5d91b1872a926107a3fa258df44b17e71c035b8cfa05f837c774a1707a835c3ac7b1445866e8d4a594ffb83f341f611630171e50b2cc01dd686cba916514678c5e6560eab089590fda0903b96c8436c9a004c0856646650a935e3a477186803f155cbb052f2a827d9cd337d3ad58d2611736325d151b9fb188156c2ea49ddb027afb69c9ff283c4e6fd168607c385e36a5bb79b919e612573b6418b450f7540f90efb0b2aaddf444c562f00c2cfc0843f68c905603fdef5a8ec062f3cdb2457dc0fa6807dc06de588f986dc0573bf943c53c3e4686ad62fc8b06b857f05f2754df1d211d8384cf25e13a5c279343f583ed275946c8570feed57c789c2ca2484e306642c5749541e0edce16799d1a6b4c8581573dfa98d0a8961a9d57e6e6e1387fad4a81ed1848ac4a3c105e31f686f03adae7a3dac2ad2298aab7823fa073806be845bb93c9e4ec0257c0beb96dc5d54036922cd5bb9fafa0f70a40ee6b4bfb61f94a699ead97e783c8a4a62ee09a932c7410fc5ad880ca902949260bd9bd800855d04bb632499393b35d12b03f15d0418dd5326287abd2dd238c763dda5d714fe19984ca996284a5691065abee69940f504c4d119ba3433aad9ddd2cc887f54c3ed17525d3403c46b8b1e79d991dc38e80ad1586aaab48351102fec2bac620424638cd3ceb30bec919651a6f2d10c86cba92994f0ced44fa71d5c9a1130b642e8136733b604819614e7372f8b8a3ead549bfbee38f83ede79757e3d15805f08228117ad3953f18d71dd6bd68e4c0e14be6b483d1043a1bd49c31c07c33fb1f2f225f083fbf154bd8f4d7ba60452042ff6bf00a62c4944c341c122c4d4d4388b6619b4a5e1c3f04f30ec82a9dcb63194eca31255c563022988b42174109316d07a6e68f219caafd07e56b1ed11ddba1f234d3a29b31bae08f9c371e013cfd2dce73e41a7fc79b552703f17790ba1cfc8f3c67890ca4914fce5bee283c66e73ebe14e5bbe879470c0a0ccccf77e8ed0586ae41b97b487d009c4437ccb80da946f5cc879f1e80625233f39fe1724b5df828b606864df9c6334220bcac5bbf931df973409d026dc05ae24fac144cb5c342c114768603a4d85b566bc796f36927ccdd846f3544dd050142c098c1ab40b1d6eba265b9890458d9ef40975253870d6c0300f8b8355a05e448b0ff79bb1958b099e982b50a4ba1e5e910956fa9015e882497abf2e43eac1ec588efe2c6d64c915eb132899086cb0339619e8ad0e821bae267e79a284eefc3e70b7aff3b41f07d16bc8149f1340cd72da77ce93952e35f4665003e97c08682f87b42536e729e28b7af1d7b70c9e05d583dd82cd4b02a6407f8f4b0ca22e2dc18fc42799c189e7e52f912e12fa9d0aea620e8023c900a833186250a6fa82615252bf0e24cea1c7345b4da26f863c269fd174bf3f95c1185ab0182e87b26ef6d8d7cef79f043f1c9047aee35ec41208361db52b709e696ad768f90a7112286563121d007f01278d18b88502011373c66f4537aea02077576ebdab3f11039f099343c2f7ff764df96bced34937675e7a713f640464654464e077ed3d91b3bce01f0b309fea23bb04dad7d3c3297aba80c12c5f30329ab8d4d152122413a7ba70087a88d890fd286f298f8a00060cb27ae859448bce52aa0681435e2abd5329d508c11ed075537744d2b21d527f310e43e40cf8794701eeac7d94467eabb3e7ff7009ab418571852d60a54aac8460791c96d94d98126a9a44457751a883d305c00cffcfc44443e4f2a9b7b5e85c827be0b5cb69dc11e4535a1dd6242166c5f290b63e6846320951bca5a270e9bc9d7b2e6b918bcd3945b3651cfe6f7c802b78e8e74bcb984f11314d31d56b2a00395510b880df99fd51a7d986218ef16ccb8033d7ad6301582f822c74b92492e990ade9ee78209d619e2a140948464f3c82a1e1774004b1ce11a20f83fb14663c7ae70e66ba7749a02d8a424956f3a5d99094d770ec41801fc113690f21eb03ab6a04898b87c517d5c08fbb6fc9acc145274ff4ac530b2f4d3c2aace493c87ab860ae1a0458f8a2f3ec562ce83114970f6212c08da54976f018e62b28107410bb312f3e2b48b444e32bcd591246708fea89cb5fdfb4d6a76ee7fd58dd3047a4021da8e40d1a27d86ce5f8096a3d49033ccfcb627efb896106c2249879e6375bf051d0f264f9bd3f5239eea72641a928f2aea770bc6a574e7155c30510dfd9129b2ff174e330fdda1b193117bd5366dfbcb600b8c664e810bbd2e58cdac90d63389c5af93f3d6e452dde42af0167b19f82316e3a5a7bffeeb724de2cdd3ff2341ae45c7f57e35edd2e695fd5b735ae8a19ad9aee1c06567b2320f926b0b463e4cc953ba1e2c0f23592080e66a387254e499e750a32c0200a84f354c33dcf777b114ae8a35de93eed8e378aba20c535d5fe4507ea73339169074f84c4270c7eae51d3ac8f42371aeeb4ac66e4022514520d1937770b21fa63bb01306504793936ee50441d8afd0f572dfd1a6bf5c95fd8fad8c7b19304e37dda57f3e8c0716207f3ee548e0ab714cfe6dec63c35f013d15672f93b5d94aaaf389dd7605e958eb09c76dcd4fc0fee8679c4fe35eef478fcdeb0003cd5f03339fcf7b69daab971da7aaf3da894058077d4922a6f9246d4efea9879bcfee9084075e60bb59a761900043b65187cc9bc561f8120c00437d4afc882598895a2c0835ac29ae007c51a5b79bf2cbdcb316052db5fef39e179ece3f6533298f8ba41fa5981b5fa4e986c5419443181ad7c2c3362043210f29877c74efdf571b86c5a17c97cf6c62195bb6687cf0098a9b3d66333f7403c0ce3f71e8c3c7c537dc54f3280c586b1b4151c875261bea7a46db9bcd8eedcd5037ec140a327d79926afb8819125117f0fbd011745fb9a1d719b800bcff3bd52ed4d9155c668ec132a12f3613ec843a6d19de06c64d55570fc68764640df1323b4337186063f46c4d91aa8a4295f5b73af841e66ee5d585555400f78076e76cf3c0a3f57aecb93aef4a5f27c4b2522ddae410725e0dadbfb01f8c362b50a809816f5d7084f0f1e0363aeeaa0cbf423e9ec3a8d2a34bfd07a9ce289f9e948719a04e8131aca29f61e9bbe75852a1ffe8515cb569f06971af2942d4682dcfd90481a4ecb5d51ef55d4a8338364cf8a53b9820d848da0da9498b6888dd270e7f6dcd16c8a601d3110b198e82e1a08527241e2289bf706c21d6ff693b9d0542960c6a85a3ea2deda488c44ea0b2a0620acdceb3ee0529dbbfcd5ba8e74e6ae139e9ee27ca9ec99d317aef6330ab33fd3d2bb9cbd1b354bd41dd3f593d09534fb1be5ff9987fe37c78946f8520d00f5c0fe87fdcbb6d11c6a751c4f75a8f9ea824fbdd6b69d6024ab19dd889911fe4be2a7d8e361ca8655140b01cfddfcdedae423fcd6c843086b61b020f2f0f662127f40d1526c3b39c8cc17ae9002466e1e13766bb029f1560abddd7f92575d697d85ab91ecb34c64ed6a09d987017d66827484c52c619e2b62674f67a511d80c1ab9179faa0d9dcb1cbaebe3127c4aee7e1562a5915c1e8189855adfaed7ce4f93649cf0e4a7a2e92cb942289c4b4481ea04751ca9a21848b15267dcacec11a9bf960afd30c53d808e3039d7e114807b5803fb36c059562362f614fefc6a97ddd87522d87198c20cd3c0ab98df8b69291de94e8c7b8d8f164fa0d5ae5d27ed12e530fde7517f319b4ec7344496f4edac324f63cc4e5b88f689c038cbe3622938d6fc1c6875824fac87b51d961f1a0e2162b01e98c1671b4af027e4cf09b82d6c412087e681acc5e20c42279191e39a024126c1a32cfabf82d58b3dcc3726fca5864dbe2ce05b9c57f2b14ac192ae22ab47f240abb6297dd02c34486e4f1ae3f18ba6194359ed925b316684806e6f4a4c89c5d5bafe2618251650eaeaa74d3d9ba6d5dd95461691dea287b33ff75f2953150061281e514374823b40fdfbb9efb019915bc011f98ccd4b00b1ab34610bf07f8b67ae38b92671d0fe7705d3e1244e4030f5d97b379a5600f4d6d5966c53752cd51f83b0633cb508fe9595afa33070244dba4e656c1624bd57430b0c07ff281c484bf2f544d25583d40b0f065a78158228c8e5c63c8b89e91f3311e62b9e796abffa9a8c5aa0dd2485570ab4852941d3b301fa312ec400a20a3a0a1c6ca86be27afaec883e4c620f47c9a9b667e1d839776790ebef81b8226687f4b81d10c84bc44ba941e839c30c8752f65f948468c2263897c5f716ef60d31aea0694cb152b518f1f38d9e363eb4370c54cec1bfef3abdc29cf8f5dc1daa30a3e1783879cc4b9dd39c58e6a2a788868dfb829220a1e1699fd5bcb1fe10b43fbedcbdd2a2ef9adedf498300392bd354c6ef1b587aacd4501808e308dfd9b0e50487f92537aa1269f056d4370f4181c8cfa5f98bd0ff3b1bc56b3eaa0543201dd4d03d630a5aa02f7fa6121268f8296d326a34c330e841c65fea35a0f1d49c27950e78453c13cbb563afb8ac287d2dc5978c4a8b471143f9f2fc99eb60eb39f220542f1a2b4b3b0a807893d86ab35276efecfd96df727375239909272e1d352c15416ba8c1b4a143192fb57104d2bd4fb05b311971b9cbbf3cf9d50e1106628e5b007f3832b7ba300891d9de5ca1968b9c7f9db39bd4ff2b51d054436cf4b89e5d2b1f4aed7ce2f10998c4cab03c51b42a3d716521230f1100f0d914b42014ef796669b73c486a04d98247cca0817ac5dae5b64c93172f6c2b9c2ef6de962fab4873e2b641a714d4a7ee7bfa0558eee87718d5f27bf794559957304022c0992940d84a7aba99b898f023aae30ab0b1538a4d95d2a2dedf1ecc621ffd8ab90be424fc2d121da63cea8a74c0ac927a5df4d36a38e054381095a0f10bdeb95a4b36a267ccd2e06b184dbcfffd2b2611e085ab33167089175ddac06f37c1d871cd460ed6b9683869efdd1482a95cb2bb6668304052c64ff9bf7ba5d102cb6ff09ba82df828120bbd28221089d0137b582e3771f62e8b8cc978f7dfc54368c15d661475530ded50008d1456ea26317b93f0b49aa653a6e5d58c282bd9ce0dc16a596d02966c5856149f8a65de45f381a0172fc13c1959fcb532934c5625463e4e457f9ee4a9faa6f5046c3a802dac71b2fb550ab665547bd9549fce3a498d324f232d1a76564700c97deff80fc669b165c1a00526ef5b593b970ed661c0f687ceb93a9a683421ea1cff828d004cbffb457aab8583e71022a19256011298cce5323430024391c0e415465fbfb13110612880f895327b611c6bf6bc06997e88aefe730e8152086bc0ced2045ee9f78ddaafba496977e2837a1394f126ae162248c3580e6fdfa6ca24968f319df4c111cb5f0c3a01cff0ae8928e6b7dee4a500a1f66fdc8b2d196eda6e3e6f310bbcecd142ad019100ea14abda0cac0fb4acec566026d77beb77c61b20875974540cd112d87e1a034cc69f4a1f4ba8ba6f5ccebb53579daeaa6438968fe82418a15ca20d527516600d77eca800faa6aeeb72e09aeb44407a3f969297e7a9117c8bea70e75655cb49fb77b3295cefbb124c62184e1d2e109c0013d2112877d4c9a5c376a9344fa2a0f83562018830e1c2a3404eb3b4604afa8c6493898d0d96a812b198304072368e89378198ac4d3ef7d2f31a157b6a04039e34f8009cc19f2dc9ffc04493774a83e10b3c1ff8a26a86b02f419f4fb3e0003cced74475d6064db2904a196000b044e118f8a6c07b5a273e51918f375c54920498e5282598e3a7189cf4b4807c46e407110535d8a54398d62bca35cc1cc66930a1eaaa6883bcb27b0511f65d757bc73b50fe9344624ef1bd0e7419beee6f08951e6d82b52407d74a38cad30db912bfd7c5942f5cc697e04edec337b86def3ec42b22bac75e2c1e4557a1cac08b2001d40e40404daa3a7b30f153f7dd0bec58e01ae5a7851f2894bb4845280cff70c77cb52009cff5aba04375160e1811838267de297f934f819ac4442585fe1ee9a4e16f4a62d99ca2fda924048e662bb7023a67bcdefb03d038c64c5f918e2e3f9e2bed73224142d4a8623dbdd1f2c38ea9a8341e4a227702d3ffc818277c8a3aa91f12c1c5197d8204886fe557402303adc0c70460cb2a0178fc9e31230d54e8251cad2398529f683b999a5ca8bee1ccfc4a1ce2c10ae65ebc39cf1d913ef1011ac3222815da8a055dab5688467d1b9c50ccc57a8ebabe2f8d45b644e6befda3356a2a324dd68d052640a840a425d32c5981e143923cd03429faebdbcc399e1ffd7d329e81508715786ac21213364dfd4a44aff97cfc11dd69689609ac8d52a92ba13c143cfe7b51bcfad78a48efbeabf5f94316fb9df37a326ad38ee155a048bad30b880bc1519abdbccfcab72ea6cc6e4d1f0d75b4d8572abe7bb4da8cd8378530774bae6c6bb5c30c9158caf56feee6772e9ed5223aaed4a0372782a4353e5780c32ce5e29cbfff652a4402e0ce88060f0815b8628161c04303c3f2046e4d9f1d30079178dce7f46cbf710e12ed3f39cfd4cfb45143bb5121390d1483b5546edb5200248a0295d0c243750c68e9bd4dd52a86a833d30013ae1c20338c452d3a990228824c1f4d288bdb8f0fb403ee493a2502d2ac749e1997355e6c670bd89fc4f66a3c5b033687e3ff0511965d4e27c0695d4d710487b9e586af0a6ee35c6f689e4ac01457a1fb59dba8c293ad7d953d1456be27d5704dd73e84ddd2620c655cefffd2cab87d106952fe9362fae2788842fad2c9c7c9f31e4bec230635ebe355de17963306bbd7fd810a7c343f89972e00586912c8c4efb5175ffeb2a48c4e677e9b84d9a73efbab812a23d1c4ba7c7c036ffe48a4140f22554bb52cf8959669c1f0c6c1c01ff10c77c6028e2f0e0eac58865842ca6f89c12342d934b626067c39ed828f689dfa6d6e5b8723a66b312d695d35c4803ceafcd8dcf6100de6f61523085aaae9c325694aa26a431d2bbc6943beca5eb819df0746fc10d40e514352e020e0477b6811304a2fa6b530b8a7206f1896bed0bf6013528a4c684a9ae63064a2c0d6ea8c9f2d90fbe311fa738a05ee280417e826856a5d5a846372d90ad1deb2c408413d7016ff341fdc4f0bdfc07f3dff6cb5fe11d146aeefabab18a57f464f92120ee0625f0fb6d5008c7c413efd1ff30fcad20e42c8a191c2dfcfa77e82876bac4a973c2edccbaaa99a9da6feb97935b4fe7d8a37fad1d19ba1505bc73fefcf6940ebc97f17535ec4cd7811e6131010dcfd905b18795389856451dd46c02ef80ed0e603ac612c59a6103161c69b1af31165ef717358f280b9bfcba5953923230f466bfcf265a2f28728ec515d547bc0c0676d23423623e119a24ba561c20927320bd0c780913754e772af2c51f63b575bd4d92c3c935a930e195bedc4d2d182e7e178ad2a8fbf4698c71e0c593d8a6d97f7540439fb2ddb9374fddfd677a3abd47c2bfc3b9788c01ed046e9990cde562c2c2c320331858054ca04f9406c1083819783bba9dac78e1d9903b62abcb3bfcb79be2da018c0240ad5871dc3943877025bbc80b01ebb25c5eccb29c8bedc5b6e2966dd9c513f25c72ced22c4f7a5e5fa803a5a8a956782665c13882217cbf6f453012ce4c5bc74a81d4371716267dcb8c7741d421816794109f7ca45e7ff0f20e2a1246fe7f14dd1b62cf9c138afe5440e79da1e06023c87f4c090f17d436d9c4059722cb0be64969d820fdbe9ba9bc26af21f4da3cae9fa4adf00704f0a439d5985d83b33400eac2cd77a6b0726a13e34daa58180e127a76c5b315702408d76b4cb2c469be91d4fe83a705d627003163422810e205c213a40ae22cb9e7382d29153a74bd8bd5eeaf01f0d0b7a1aaef274f85b95b46e6e20fc85993b6d29e689fd34815253e9d9fcbfaf37c3880f12139fc408f68765703c595788ba2cc72a2c6a112dfbb819f2060dd2e419de3b681fbe6c78e622cd9e8f1581309b7e4bda2806ac10558ddf6e1966cd6e6c201ea0940ccd9781981030fabbc3c0db137f83b78aab2274827db274fbc26a944bd2e427bb88d476af9541e1bb0ad0c71dbd4b9af7057bce609df0bbae1b30d040674115f713aeb02fa01b286f075909dc3d0b1992e8b884fa0cf1814164ad593ee6dd03f58141f65e658fee0b973518440da9efc3f7a55d23128993b9fe081c3c9a8d6160270c66bc4df56876669e301953e253eb9f86d8e5c7974c2d60b7e2b0e2fdccda253d1858f942ce06c079225a828c11058751ff0a9d158b0a786c996264884e702b11ec56ff67bcfd4607af19684f3ce3cda6c69ebaf94f1403a5cb61b00dd508b9152bdf3d4f830efc2d02b6500106caee61eb580bef25a64420e5c82f52f42de075a4bd9d2d2cfd8065c4fc058199791ebd85323cb1b0d1a3fbd2fc7b902b1ab449c788063f25fa3dfa1dece2aadb517e61f00c3c444e675591456e992abef43593be8342d6f6166b6e84ba2b57af398c6fe3d5cbe353e5cbd7e4d1227a3c085d96832a4c9dc01159106553282aa3998a2aacaf425ecc4363fd56269850f1e55891e94caefc71582fe869fa5e78ad19266f1257a8368f6505296f52f9aa120d2ad51d41145778d0f880612988cca37f75f2014197104750ea8f352e1af45ea11b686b20d788fd55e1fb63332f00d8cf8dfe031eaff5e825aa94a5796d744e8d221ca8e62801340c7da12073bbcd0e94a1c4f3876799e73ee3e01e5c05374046a9e72f1e645f1dc6b93d03fb907ef83ee99307cfd96f5d336e5f57f5648cb2f361424808e80043ef26ac06323fb459f25001b0d96e1c4ebcb12171a0127ea4171a96b375e0d1e13a17f1a41cda2bf78197c59d1a2e8d951a7998a579db9221b1e88fa80d467a3a3fe0fc85fb90a3a784f5b53ce0e09fbb91e1693799ee8ce72d2707ee30c9ecd33e57951ee3d41cd9ca7e84d77ecee58e4b0372062ab7d99f3cfddb6ef196548e067c082bd408940201ff47a89d4438411f21aa1a2e8aef2b519a0c2a8bac3a66d02289399d62a7d2ca6090090be58a4f6cf4c32c29c25e63cd917b188cd5c720780c889def9fd2c1527eda0540b6393c75feb68929285248f10afbc16b62cd0ccf68a907e6e4eb18c089e5ccd91afa7224d4d4f15e63ca4baa20c2da07483b50d867a6116809a347201043ed76ba111beebd4311509131ceddc41dcbec5132d32b1a5deda77eea81182697efe7bc4cc5ae8bb9e23ace1cc750b5b31a4feda7265ba5ce6cb354f64d29cf05457de7ab3066cee831914838d27f59cb5382c10db495a1fbe3bd628e61ce5090efe5418d9208ff587feda431c68c76fc7c94518d172d60e182ff3a8008f472171695c405f081e9e89ee56d993ac6010f4d83bad0a0b18a13eb891040a29cee8007e0e147ce3082f96637f1b8bcca0a2845b92a805047bc7d6154f87ba16a067794dc0339773506c060f566ae79a3a21c867e320ddd109a8e6e88d2d82e24ed7e194c0741fcb568d13009e569b7fe0ace5d7600a14d936bb0c99fe09fdadab7b8a2046e58504ba728d50f7ad0e098255d95fa57881f84d3ed697de94b82014cbf603c4dfd1cf4ff00d74ebd9a17606639389f526b42a91551a0a80ab71f7f5d6392941900650a68c7f145dc05499efd9c9e269a40d3bb34998b03240040185ef1961224fe3e68e448cd41030ddc1e9372af9b1f79fb86161ed1cf5c7e8b1e59ee33a028a91f64d0e0f125850321dcb22472e4010c3586e554a4bc0a22b33cc11d8fc3bd18012dc95d3a10b4a2ec4818cf29c12f80347b3036605af69f692bd5e02ca3c5b73858850aa45b116731d199fed789bf61cc4f6cf3084f6e93d438cd36bbbb83ed56dfedcd46280dd297dfc9e68dd9430791d03d1e7e13052639d1527dd10a9ce0551c9125a0f39855546ac7ec38ec1e9835d2b8d99ddb3cf3baeeddc1467cc796241051002a314bbb5d6c436b56a13a521a9f9081a9b6e74aa5095c12599509d24b40a00486d21edf1cb6850ba6db8aa68a7a1c76010e5b54a77fbe7da47a54b48f394bea256ba18619d665d3805c1abd6dfba9e9cd574b506f47193b064727469970519c2ba947fd8a5e5725005e3917e9bf0ffc53282af5071830088f154503edae76122defffb4954ca7ed10302335a5aac1ab423aaf6d1d143f56c7987b50dae589c18246a012345ee9769ba7477c0c623588a96aeb3f85b239bbc8af6b7a2f5e9751a826a74b480b11337bf47107b3e0a4e6a87710ef21d0153064c954f3f09eb408cbc490fb158050cfd9ca08a3c1e28ec310fe399c67abf4e67a27dad57b38f2d48995d241e0060112313e8213126d6ecd36980568d59a6870c7bfcc43a3781e164ee6d8b0628401dfa942aca5601aa179c55a761665b9b728c2817827e114bd239136a4573d666cf3292821449be2598c1e352dc3bc1dedffc7d2deebf2291dfb24ce0c199fc97831d99acbc3105de8644045870fdd5c1ae88362b3213c646a701bf83a193d47e5a73ee3c9ccd76b4f3b25981c7f475049b1c1a388a7ddf3a8f32f1a48007baeaa0d8eab14a7db0ed75144dbecca7d4c154931bb9552758c79657f355507d70d9d46a30e57b5ba7e5a322547b137b159e0f555a329fb00caaf994fc860ddfda1ff3927ad62734ec19853fdaf54d1a67c274689f03c5d293172573a7578af717c7748dd1699879471b73470664e47f65970d1fc929de22c2a1a7fb81e284b5035d9346dd1ca9b611f6a816ca440dc052450d32cfc8194aa2b365767c0408ed765bcc97994147bca2fea7ffbb5097cd7b7b8de5fdfa4c328d680fd583482a76103b81b241b2ede57cf652ea4010ca34452fdac7cf39d66ed37b70c2f9174b191eca4b87c584e352086d21f012d4238c9ac51ab6a2c7695609e93054b603b388b18278bf01e7f827b8e9a77d3b3734796f86d052b587a43b919fa32cdd36806c40bd6589adad364401a4aab394d147c9e918bc69e684e13019933e26a82ea6505958b09baaf26a85c4fd0bd9ca07b558792cb0c2dd7097a2e3394b84e507add03f6547a534b74bcca1029572dd1d838e39da1a2fbab5634aeca8a94da1a9e6a5fa51189ad3322255f633476675e052dd2af9aa2712a53afc37b8fa5af6e45e2938c5ca771bf0221d2cb138b66eac6b21e5c37409a8305f5b3927a3727e3e7d0347713aac4e037eb24f4744c64cf49bf2b25561bbf939c291d316a1d75ddc42214b2db6dc70723948ecd1e24ad75fb7a56e3005888447d3734b355ab6c245e3a22453c744e9ef33404c4f580b9772b6dc955610810e901b8db355ce13f58840a811e20ebdd821d98fb2556851e152a04bac0ef77eba0692e9fe930e4e21c4241443fb8906e22a89fafb7edb76d7797e4fd2fa5da8929f6105be93afe9e72e92d3759a3c8858d5532072e577aeedcec684ff8c8992245e1fd147875df2c39b1038e3a91d1c09a2690b5b1d11542daadd141ad00aa30aa45c772db4f2926fcceb51926f57da9a96e442246780e94df8acc58c472418b81830497bc146e26aa4e238ff34f63b7a65087045d79ebb7ae51dd241d71688794fbdf7a5e29050c86c247a26407ac3455d05923d6b28392e2f6013df021f3f7c4539fb212818490c87f1abf586f8c17bae4856156ff8b7a331c50e379f91f9e91ad7e0203fe990ea008b1f7a880d5ae632424e4a0eef815c8fda7c34bde802f388da249ef85a93acd604a313e0c273b5efd812d4ea4a0052fb17c8a51a38c8c31feaee1de217e543ccd1bd29438f51430c797480bfd11fca5a69a2c485675422d3ce91428820a680176bafcc811478f948e9800a1048809bd0f96043e8d2f5b000d585b6875284f6d5947c0715d4116640ffb6d39a8aeb371bbe3d823e73702059f0cf7c345c89bfc41cc2aee52395fa9462191c92b55487ccbb9bafaa22ff3f35843043abacfc5e2c4468c32c2c6245782e55d5f134365227eb6f3966363569ae4f56abaf75ee43a486706788935676ca364ecbd19d2c4bca38eeab95f19222015b65c947217028412833169ed7e4e316c02aef6b2bbbc3c06d00461d1dd1eab5865be7f7eafcc555204e62b53f09ccdc8d6311c4b7fd8c78e20b4c4dbd2828c405e47ee1874a32676ef91a2762b0477079c6ed19e71f4fa657d39329273581a6ced37c29d623d696d6b22df092a0604dc06c740f1f94f44c664fea7c7a6d4bb102094644033ee4f5513af3dbfd5308f52104445ac480e54e807567111857eb903deb178d2d8334a7cd3088d235f95d1c401911e568ffacc42d6394fa368ddb8b11ee656ce69c8f1a4667c5efe8b32e4d334359c128d022eec02afa6a86b0eb84a0ae941da6735c03dff562daeae2cbf13f58e32a7bbcf7ea885d2581c25d32c2fe620c45d093c1a06d839303fc96b8cfecafb391cddf049518e9e72ade8b8dae4258295bdfcab04f7b6e4ef8bc5cdd51834d08c5121ae4135195aeb7bef916a8fa6114685001c6711b0b3517d3a8781879c3283d1aa7c2a63796d4290fc8fd597b11aef808ced42b1d5d32df872a64e1b6f236bed8f8f21980b932180d413bf83db6de4c888f8e2a27b12fd61994d5c9072799de8f94433293f4f39c30e73ddb00970cb0e81d26885c9d3218026ea42a1de2a199646936c801ac384e9d07c479a80264be6320f192d054e5ed40a24f93fbdc393609fba626b7d4415c62b8110dfc84bf48faae20f12743593cd54c85be78684d72fa307193491b06d356b22f839e2207089931f87edeb7eb8b8fcc7f9ae5ae001aa05ec84a166b62b662e04be89b9c52632ce593ae69f70c2109e0f84e77cab5f8302290db7a1ce809f0c3f12a323c27afb46ad158c74d26436034c8e829af52c378d4b5630f2b23062152a582f3e898c841d8e3b381d3dc7e4fda8f6fe60f154228c58734c033206130ba61bf18e70a1f61e7e96f0e62eb460528955d8764d8c5ab5f9dd1e8d1ac603b1d8f470caf88ac75fe24de98a37e538271cdd6ffdf131ef75bb8029b61795c94dd64334b7c0b08cf4dbd7158011e06cd91401e7be9b9d965a31dc618533ec13b064d13a254bb374ff9883f07a2e4b3300949d532bc4fb5a81149c70a5a557c2387d754e9f2c13ea088b4f8bf333c11011da1876681f55719f083eada573b8a4bd7dc739530e35d87fa764a2541b77a2cd847190a8981e258ce704249490088c19b3d02024c26e6f75c38f08dd2af2f8e00089a6e773386e77a34cac3c26fd117399fa23781b2585dfa3bcaa490807995c44e2710ce33dc89bf2b0fe52d070a2b23b3c92a81b91568da9b41bbd981b75ad8162d7f95c06070ca090da316204088550740b623d8f500d15bb251d7b50dfb3b96c71338199c1034a831a850d3f960c0cbbdf64b476d7354dda7b0313b22f91884d8783a08fd112c400bed11a3fb1cda4243ce15ac2b53a5e8e369766dbf01746dd2c6e71c0fe0e69b66b887775ac1673bb3799dbcbb2b3ad75d64b41bb12e916151c578398316ae62c83c61f950ea8af429b10eabbdda51f7701b63a9bda236a1a92a5f9024d703238fec44945c570d0a4c2256b69e7f56cd677de42c83ef80957087c14b2c1aa79ab6097493525312a36784f798d35cd952bd40368e00de1d638371a434e13dca8e7f7ecc07c74448d1278877114e20c9cb256ce4cd13bc6a51e7760dba88b383d01bcc3b80a71dae50175cf981304b7345f708a1d6f7538258385bb5985693979461411f854e02f47f3ad1025e00de3d638572bf6c82428555c4facc9698548632114d3b63f489bd10f6e4816de5375433ce9cf1a2b5006edd76b5719431e5a0db600a8e81f2f21cd1acf9ffda8e830c4be512de9808f07431fb311318a124b62b4df1e088e7356424235e1850b1d26d2f7309f78c487bb16ed8bca196fac3a5c8c348d4dbde31715aee0e14d2cbf9077dca22f1d219333bb2034b6a1b28861102134abbed21c907e806be77f3a81f57b0811f393665affb5e3477cb1f0a10e161a4bf5d209fb1768cfc4f6febcb81f848d4ac21666de8f6fc044d6982a7db008b7f984a94c9bf120175132e5f04d0048605ae58f4d4b587a4b8cd866638481217ca9153cdec5238dbc81e23d7891d7a7c886abed97798cbfbbbae9c83831a699447fa4c91a693180d7e93ed27afe47ef48152c1f1233a23ec8c39e654868b0d76e5e7519b9955a4a8e1493bd4d6da81211e67de8956024e8e00f7653a5a00add733b92990fc6b5d32749a8738bb574c079b406d12b7918d8747b06a1d83c4eec982b86f1cdfb4457a06bad03aa862fb412a8b79eb42fcf41236d10aa4ad192097b4d28d8e470621782f62c2115dffd1d6338f0235b1b308cc00a22c5d613a61772878f2bc1869286248ba8df22b0ba63a05de07a15c58e669c05327ddc9b9867bf285e566b892903cf2ad17a3bfe5e5406b70a29e0fd71ffd2e0634a199321a6430fab5cb75920145de877c844f98121d611888505b42429814062fde62fd38d78ed42a7dd1a94c0acefdaf1c61b36ba175d3a4719e4cff36a45b967c2948cf317c9986b07ff593e1c8627654407261ec1c0e513459af8bf472c5982397b6138a384bb48d35a6b79a5c9149423a9eaf295af9b9dcdae64a125cecf58613fabf4d87239a494cb062d5c6753b74e8d80aea527f4c67f2fe5f23f632a72cc1d8b2bc4002dd260c704454fa843539b90d01b635303e10753d8747b38a8c32a06a24313a1a9ac6c03f065ff5bc13ad2d1a6cf553dfe33c4351d1555f8ce65a933c50aeb881644d0e402e62f37345839afd1d3d4f97afa2d6f61ff7e490affe2581655e91db5195f8aefd3dfffe6612596ca9d9a11dfa383ca86351984759cda113744a0be47974e43943288f113df55a6c13ffc7549543373ecc54fa9e297685431f5bb608da3652ed86944fdbe8ddf43af646b87590335a535ff46aceb5460920ff197b572e91cb715b76103fcafa11961a79f562ca282050c9ec6ee3c801163308432bf1b1d8a5159ec3f341b8d3f41b582fa36d0d839201550f2219f2f6943e74486571051894e6454bf69938699d1da53500f59ea79f66eefe6162d99a1e8a7285eb36f44de423c959a2b717104a8238641dc0cfd06e55f5f8a6912129d40b0d774a63370f9a1827c1d146245b5a45d2b35d7a238c4a7636d492c71252102338b9508e3ad036aea28a61f9860a02eee51424567372eea4698da23a6c5b29c76688c6339cabf8843b4abe73ff7a1ad4d51880ef263d1bb5d5ac0c0fff78dd3961c5043d11163190aea13c68b98df2ca127707c374e3fef59d7ac36b74359146a68326f55d4017b9e82f9b105ea11479089450c8d94a99efb10733ff5ade1f62b3ca2c7336b4171db68e55cdf8115714df69ea6c6b9da505959734b51af822b2b2a8680d11480899280c4db13b290dc08fa9818c2a7df854096a0bb23acd0b7599ec9acfab0c5bf19b851d4b291c58776cd1aab3d2e4b652c71c47e30254c85b43e72f214307743c3b7337d9ad2c1ba6c17219c00d4d50e564c2c7b31c7eed6b58ede1f4b691ec27a2d63f998ac83f54aca1b9381a7e35a709a5c601213736e5ed4242664140d03d21252c066c862979751091f54be60563fb87c50261bb02b41ae5ca937f2b71904bac695e11ccf149231a66eeed7afd56bee1304c2c4c0868db8e08435aace174bd95d68ba6d6b961dd61a042d74fe604002dbd601eb874ea1ada0efc9a71f0bbdce6673f4d0d479325cf725f695d173cdb3175908821d46c95d69721241416219ea45f479c9a079a10ef7caaafce6b0e5550c367cc369b05084d27c40c585f85fcad256784aef4674a95f2ae65eeacc780ca88d5c59b93a1b9007c040a407e621e1f03326f54d87dd6c94e7936b93d6c83497a22b64921635917ff09b38d666a58db4b4fc0125de676a86c190992fd0472ba28a1c40c04c167ee33a723cc49d288b5a1e73a4c9accc11b7b49604e65b2b1ea7974899225134c5271662bc588f5041cca2e81605d4e3f68ba4d85822cd8b68468875d71c4c432ae674db8305cb3c448b487f7225f5c105ad8d41938852f09d45dae89fafe235c41af68d94440be6bd52baa3dad7baf4f5af48cd65dbd1091d03591a322adbe6534284107a01850c1b2290cb9b2c979a518e55bb9cbc0bb5815cc62db729e84244e8d23574dd85e8d245d1352e6bb142476054e8382a2e48c5341c6bc51799019cb8dc080094e6784bc53a4c05d1541ca31e4204890e6b30cf706c0bade5c96bfbd616082550a493f1f94598cf5545c68caa3652680782a716b4189782d66ec9a5287e35c76c8caa460cee9c82cbfb0865e34313c6d2f937220dd57e6312876842a3ad17187460b8390a2752853a92fe262414cf677a7324ce63d7b983d7e847eca33a720b8512edd6f20b5fdc196aa01ab049e7fa6673a8bdedd0732c2d754f1a9d2bcd4271068dff5f0c9497c25531bbf3b5e758f9db509bbdfd0874e376e1e8f60e21c9c6d4d4397d2e2001a2fb84d59915591cca9be99b7e7920ba5ff9fc9c3201c8f0a775cd91040452fbb8d92bf74ef469b9ab361e00197427b35ef8e6035641b8bea77f5abc77649469598e4deb3458537a28876c9c6dd369fb81878cae2436771f8dfdecc7f7e23ebeb2a360692f860dfbd17f1466c3d14fa99879537d334aaf622b6a7a82daf0c37aef36bdeca4ff0a5335d53883baa45f2be7d342a373eb61a0b3d84b9297a9cac643884c398bd0c7ea645ce097de589057a88c0be8c08f49bf5c1c7554a43f5189d60ed49c12030fb7e4a3563621d453c2791ed3137add191c6a72b091c1323ff3d8d899f09ec5d9fb15bc2964c7e8f76de93fcd7eabfe71fc9fb85f81ef25ed534faf06a78d609569ee0f026cfe5fc7208238b6e3cd197ba217c4da3ed2f5407af1923d172292c456c640b10819a3e3286e923cafbd2b8d1072bef183e4b8cc42781c1ae12ffe83f87f2d7ac636db6e51412136caae4563ea5eb47261f55b6b1c58cef7b1744718c699d1acc0be61ecda18e47298b988495b785ffefdcaacdaad207b6833ef67e18bc28c32b5b3767295e2827bc2ef713fd8bdced73e4ba29881770054ae909fb993db56b63af88ebf520b085b2507aa4dd4c87c5b9f26f0ee281317dba6ad4ffad83aa2b345b1a3057b16be3bdecacecff0c396358c4c96bd240c08bd77aec748bcf33decd8b3ff675f5ced2b7fda4996bb4079774781a4ca0cb75b3353786e2dec9fb4b2a10e2448d9f16263ff32be0acdb18a7dc0206ebbd0a7a2fbbca4d21dbe05acbdc9299436639faf57ad728b566159643df0e4b8886831e33833f1bca9437c2a2e82950a1fee0eb38040ee5c832a26af03b3da1433c02453688cfa0f977e3c599ae2c674258e4da33755bebf83d693188acd1b863798906ea159702166217000661ae0d336b1842a0522ba08ca7e8532c5b598b511b2b6ccba89a88cb405dd9e4f0e550e7e17aee3839643397861635a91a5cd22ee3584f041887921605fdeca9501cd513381603b2846d5114e93c3d550f85b50bb36e6161933c34b73f5c65aed297a7bc5208dcb016597961ce99a54fcfac136ae81644990eb764435bb5dfe8a76bbc831cf2d9863b5dd2eaa7d364cda888c22b20be3c90c17a3d08b2790f12802b7e0b7a25c3ce8450a4c254597d0061176728bb3822b39faeb0c4799116f7bce0c090ec195549a7777154aed2b4df3415158d9b54cb6bbfea441c9b900b0675385d177d2aae6e49e597189400a94a07ce6c4a9ef54bec2d0a4ade5b07db344e28f61937bd3eb44417f27532e24b0fdb41a519a7e1c5eb1681b99f065bd2dae9edbc8c7d71d6e6f11521b0ec3e10f9b35b1adfd70c5149ddd5fa37abc412f91225fe50c61ffcaa857cd105351962c14fae245b9942fc512f1c4c1cec3805dffea236f4e3c81d0e5bcfb4b5e848bc52450b5099a6478837fbe09a0ca8d274570b930fe44177404e9357b22804017dc7e1a60ef0cf3a418cb4fc04f3850d0fdf546e87454be49e46dcacd043147f0af891fb59813d3bab327f448967213ffc8191c37f826125fe890889c106772c88cc4b71b42676f64f83776e26509e5048bf99ee0438334e504bd3313134ce8d14d034422ea2ae5a6c18885481db6eef8f36308281284bf1a43276f9c1f16914fb249f4d2e51363a1f78b049b10f02ec1df4668ea0341f74c851b114cce8db46f392418c405e0913d7c05269e20e54bb1e381001293012f06fc6b04a0ccb2e9066909620edc3f719f32a8823ff45184ce14eadadb47222572c246e1a5203dd1bda51374cf00917a4f3a03ff8143445faef439a57c0dc25e82092d86f7dd827b90ad010c303aa4bb0428572c843807c7eb7f5b3084984328be651519135620cbaf1054587c3bde8539d82feb9f045707f17eaf062c23097ac437e4334237b43456ddf19268a8de0e9596ebe6e71f06e818c87fd5e6944caf8891ad4aefa1d6fc0fa8991c4c8471accbbce8fed271a4e3103a5bf355f694216708d55b5a4a1af0a2a605f34dbe1cc0a29f862f3c98223c7a5ea4db5d9358f2ebfb0327fd53a0d06693a7fcd3b1d1a78ff18f60dc4e26f2b0f8199ac6482039bbbe4f2c8598a4fea455fa94faf3689c72f8a634ec4c3e435e6a8d8b1f98d8eaf514b5c8cf0b159e4daf401a238812034d644786aa54199d770a0b7d4f355d318b516a0a7336b03a2f5e0d8f4b3b3d20a287da98bca3add289f9b0635c657d01a9866f6ae6414470e1a92bc247bfa6964d38d0bb5d60858e55347c67a76cfb7e3f5c02b3b87d3ba427592ac51c85b5240dbd0f92b2cf4273ab6c8ff1edf3cd0d23ceafb9ebc1307186977eef8b31b4649f284e0d51b53863d145c0d1d020abf49cef4f49b43ec8620c51da0c0452c00b31987861ef32f41c4e8d6287246fe2f5b4d2f57f3e51ea6724b6f89d7c7329792c0755b8a1980951219472ab4d8fcf12f140905f39250aba0ef101c6714054bf5510cceb9cae00fbdb5f24168eea8c2667e16739ceb0fd996aa88ac2f17aad8152e6b402d699b8162250fc4c0838bc612ce609daa01247629081c1326357f1713cd2d9e45b3c92a293d5d0ab740251fdad5a173f837bb7eb435e44ea7213ecacff8d14513d08f37aa8afd6009aaae0c85da92f6ace9f641b94294a4d0bc6b1aa46c0f373126474bd2d03d8e7b9b7fd601380c87e351d368fd4882146fd06489d2dd18cfa663d28886f7f49141dbd55f9ecef64a05488d7cfe1c899ce44d42fad4ccb2e12ebbf2f526d109d1e77f2fef74339ffb261d36729396df661b25cf44304a7bfc81e9892c224e189c069da45365c9966abe8b00228699aebe74446aeeff77e81105723887940de3990a23f383c58e2784d68f8871c90d43a2e03f77030083e9a6e0f0470c4186c103a31cd427be5b80a8316386c59d8001b88e40a69fd3b6bdd1e639481512ec1a10e3f2289fce648ca26e210689f1f48420887cd99fd0cdd022bfd0f9e4419dc1a8590357d80a444c832e099b3e2b3d10e20bba8d9324847b34c80d50478675354dabe433ba8b298c31ffe8059f25c6aac6acdea9e11f54371d73d21817f6c699afd3b4fa0f473476c30648434e39d8159b1518fc8ce9dc3572c2aa1651f786e4e8efe81eba7f44077fb113b9cf9bacb9c4dc0620f745b9c10069cfe00f9b7feba58fc806dae02c819243e58f9f165a4865248708318b6fb0103225c806b1088aada03eca72ec04d4a55ff8d08bc2360dbcc1f367860572d72ea3fc682a546acab578bffc0b031cbef15b7beea751062806a1b0007b078369dc95dfbb0d5632cfe0386c9588ae160fafc9200397f8801577d50e8f17d54087110dfbfce3522e5733fa53ef96f29821a7fb81f6ca0e8a8cdfe61fd1cd7071cea0af841d3a326526bc6399cce161111007a1c346c0eb006676300b00dff8e7fc004977038de93392aeb31ba25c2e132898fa5028d7a8bf183272a2dd670a69a7f05e987269077c0919b640b730c7f464485db111b1ad2a2c4f9f4834174b5ec61717f88ca2613ab6bd0c546d390a7c1657dc493c05816eac8abdea7d3b600fb0c44d5db23f652557673c706805744a7d6ec4f63161e279c3772bf24153f8f8e3b0e5b8674bc56bb9f1f1ca31c127c4695c5160245180fb810e4691b82a1e2452c7249d03c3ffca4740557730c10bf7af8d0811e9088c19531175c77fcf331b56ce0136ad9f2e93828711433b375bad54a1aa2d36aba2ece0c1942b50bf62133716b2557b88f8580f93ef6dbcac187906179df65a28be3964d175a5c6a038a0c5f975a309a514d8b016d064300769c1dd6eadad48fc022cc4eec8d78213a8913a35d076a8e55e231bb025954413456dd7f3bf55500240c7d4b1b1f6985a519b0f6a8567f2348ced5268e942c486970a89999dd84104288442eadecde01fd080609950937abeb665f9fa94bcb7c20d389828621ece18b165c418229e47441480ac21914808113831a2a5ac082245213f8118330b4d045133e80410a1e4278f8e2155199f6d73eedbab22b8c2d8fa8fa55cdf6da2e7efdcb09da90bbbe74e407721f5d0ea19dfb10a18f38fdd991feacb6a16bd742fadfdcb557bd7292dce5a95efbe823fad1ad56699a5ec5711c37bf5d24da718118615adc43d7a6847176cf5afe302c147a0cc73dc4697a4489e07070d76442d7f40af7c170a1430ec3b44a7b48cbcc6b3b0405969ae430113b2342b2c81a2a596ec56eb324626b58b6d7225781ee9a9e495500ffbbdc55da39efdaaf568564400f7d2615b91de4de81e30215463b17d2acf9cd6eec1aa6bf1ca36b8f195d0b9d2562690f1da6aead693be4a91ec705e4a9fe831189b48f42fa13953f2bcada478f099da459a2873ed2ac1c9548afe89789aa995d79c95de5aea2e7f469d76ffa7657ed2a7a4d755378a2bee2f29357449bb9645783784dbb3e5355b3aedb5ffd51ab3f96a6afdbc764d959f6fa933de41d13158fe5fa883d568d699878135590c056b372e659f6d7af66dd67d7aaab3f69afc2f4278fe97aec31f51876d6f6fa18ecdc39cdd28e65d7b46dab988d3d7695d5dfbcfd754cabaefd7595bd0e53f5577ff3baaeecfaa40e221569604abb88c427c8537cb4d189369225b4e3e30db4916d18e3b1cf6cf92426325bec4bb6240950c40627da44abe14449bd8a37d166a2e205b1192ab925685045a3924552ba65f9935bfea4fe72d0cfc768c7340bbbf6a95939ac797a98d2585ab8fece96ed75cb6a55410253483fc4f6c1503d4fe79c496521282495a88a9232de50efe352510166e55c4cbb7cc5aea2ffecb1d363bf5a35f5777d1e3bbd4afb7cad1a16b55a230e95880d3756d22e935dd378a22a961d729ab65a856959e9e7a1cfe505940a68fdc0a9f9966dfd5849c9d7e0d48944d156cd4a6afe074ec9d38f8ca01126f417a9e1f084a00d28eaf121e2e168df481e74fc6efac4225ce018215d66d3b95c725026f9964d8e73e9a19cc383e89ff7511689dedd13fdf344e700a4413b107f08b1e9352de2e0049182a78a9f27e0ec08e9f12162eb11223f5efcd45a2b91d9128144204422102211480452b3208ed87f372e1175608033834d230e4eed519f3de2206b76e4ec23f75d0de3895e334cabc57dbe057a2acb3c8448d907d375a39b324c59cd84bea475b4489d26d13a84b4cb489f4e5a26a75e2674a965e443d4feca9312b08c38dc1daa67cd77efae9aef5eb54a3ef4171939ec9b64f121fb753a7335ed03107467af5fc59d459b7db0877b6babb8edcbf4e17adc32b3e4499f9995a392fac348fabb971f9df561fab357a9beab3fab73cc931e233ffa3cc99e04479bc808a21c431994234ff49928daed10d978e64a90135483b025e7fa8f9b9aad1a97942ca5e42925634beb874b0abfe6a6beaf2e05d4dc14fe8adb107f05ba51e392c25f89a884b087135f84a1c1a1b1a174d6d3c79aedf431c86c29991e6d4c1e79aaa0e901cdcbf92e4b8e9b9cf4bec1140576540072016661d35873044e143e52d0dc34114467e72222595678c7e7093e12efcc961f248a9ede9d4d7f8034e8b53ab22b8220479b284444d1cbdcfaf1148c065875f100ab38824d69686e8f7b4d671a664e790dccec0b679856cbe4de5ba56fd7220db4d17197b93b96e3771df89ffeeebfc3940ed0b97f8fe1fe7567cd738fe9fefdd32c994b6eca2437c9a497b2e89a6749177df42d7b87a37bf683e1b8ee5b86292d9a324c5d386a8926d12e240d676b0427aa25d2a7892a751a94bfebde610ae7eef831dc3d8d7577783f1f0e883bf6c8133d8e28449ee853d8e35221286870912b3d2968970f791f40dc5d0f44695b784578c3759b27a4b16d780fbb1cba2d5554708f5dc73d3693d2813dd39fa557ddd3f922352c85ddeb2a410ee64ed4055590c0ac1c7b16bdb2dd90c371ab55f39ad5222344bb23477fafa2bffab3aaf9cfeaecf72cedd863eeb76f9a956959feaec35486294cc389baf2d7a1caa57d803ed7116c7655c03cac5f611589d2b1669e66ac59998f40ea6b6c429eead4b5d6479c18049f7bccbcd42cf9794eb37254f2933523876f34127d2291d9c2d2c2587f59dcdf5fa406e791ce9ebc3e56d26bc9eb65cd6c31798d45768d3fbbcaadca24e449de7c3025391e70eece65d363e4605a43cce30f21cffd84e4a46b23fee07104b1250221a26a68afe214a13845a69182c49802c35b2302d81299107d6a7c208deae3e37a0e3d2e7a411ff75fe603d36a954ef256c9498f3fb13e16992df2f59108b47177add527e5079e112736016d68af8f31802df10710555f4f845deb6bad4ff981657dfcaea3fba7e3915dafc3f4f83351f52128f00783b943eecbb466e56467cd63cd92e772cce3abe6f133ad92e7bee551e825d9bb468285ee65d049b93b04bdfb07833177528629b86f869b84c38e349c2891ded10a6938eb5b200d270aebfa96a775b43aadc344d5737a038166aac44f6857db3ea35d855dfb752dfba66564667efae356cf430b02fbf6988c95a3d29e6d6765c752d8cd3075e5ad1eab3dd4efa887a9d7512f7b15f6f95d67dd5ffab33ac73c76d53cf6ebac9c4babe6b15ffdc2c2f4ac31a57204969146caeb0acde4a5c36b3ce467e655dde7a596297dea2fca98bcbb7816d1a18f3df451873eeed06b7085e1102c7e36bc62c321589c606b736369c54e7ff79f0a665e83a68f9284d8893da3d34723b345741a7d480f414167cee101a65adf4d9719a634b975f9bb964d8f1c8e2fc74caa3b0f33a94ecbcca4647254a677ffaeaac0157c764090eab44c05aee0b34393325de698d262c9490eb9ef7ea6470ebbdfbd42240b4cc2155358416dc43ff4d80bc97235f1c363b6c424289549248135805e6483e3e3bf4b0a8263a809389ef3813d871ed87380f1293f30dd3e28f5f15d0df3995e8f6598568bf492b74627b9f665949bf2c94df27c294b9d4d1f7d429b3eeec85f22b1c8aad41de5aaee285a26e75e66befbd52aed275a467eb9bb296b37c93055ca30a5559822c93045ca3035ca3025fa606c49f64e92b79332fe2873cf72e8a20cbacd3cc054ab85efbdc57d7bcd8fa901a706460823a5c1b45a43689856cba3ef748bd32f1345dfdaf4ca278a86a030a9c800c7797910cd68a64a4f06f650fe3e26de6a16f6f8ab59392a162cfd830157f6c89ed922e3f5d24716992dfaf5f267b6a8bc7ed2cc16001ce52b4964258dec5a67cdaef30879aad306e5a6cbd84e4e4c47315d468ea9efb329329ef218fd4fb3bceba7e8b3f0656c875c4797d08181a4c10c340d07d2a8d247f64e7f5cccf20892883cd5cf2c911051f554366157d90369d4879a60add6fec58bb0e7c1b3546e80f1bdc7d74beeba66b798a3143db27f9c8641390f3085f2981e30ad1aaef24d7f39f0655c8777fd3b5bbedb707bcd725f0e1008140ad97038be1ca57f5795fe69991ced32f8a56b5a25ba0d5ac6bb08e732c9f900c87f0d39c655f2c9351919a65262fc24a75ce7eff0fb60504c00c83055438629950c5332324ce90c53598e1bbb595f4b9a181a4e542b45c3598fa2eb5b273afe7c3a1699a87a938e3eb67e2779abd502bd74d25badd0452f39c824479cd9227a15e5d344d5fa924c92759448a7513eed2aed419fc7d93bbd0aa43f7b91a73f2bc2077d166b49e4b3a2c7e08b342b7450484b9096462e3e79ba864c6630693204af4b75dd76d063bc779ad5ddf3406779df36d0268a911781360e04d29f060281fefd45721f7602da4a26d1c80473c7720e96f7790d7fa2832287237be4342b0706f434a4646652a09fe498fa3236cadc478fd91ed2aceedb479a956198adc7f4a78940f71f76eec3be5dbeea1e302d93979ee9ef5ec73c771df2dbb1fc5d9d83fb54618d0b715db77d3022502c21218d44a10e84618acbf35b96ef30137ca0afc78f22bdfac0161de615e4599d562b2b971d22799ee7d1733c88b20ff0d5835b48f415de21d157a51d0a1d8a34097a791577bd0633a53948159322a61883401844f1e1af5fbf9aa6359aeb218410c2cf4dcaa393e4f992bc45af99de835c8ed13d910733be97f143f82310a69ec484e4601feae9b50f6cf87b5aadec95cbbe5663d7b497d53ef000b30fd7a98ddbbd3ed4fb70d9bc8a0d8874be4c0cee4b8aa4606214fa459a357a8c8b468f7196e89f3005125d3f6674199a158395a38af1d159bfe831e6173d26c6473a87e87fcce831628c51089b2a048918c43ef2c17544bc39890a1cf202c3386769c3e86b73cec79b29e393e413e5b3e4337f9666ca344dd284134e2dc334525121b9ca4b2a24979172141d392cc6a8cd39e79c73460d9b734e0cc3b039e79c7062775e64a391c009678c3a07b8af0634fd22454f796b7494431e515ed12ea3910cad72191f9d54b40cfd6997815da43f6d0504dd7487b9b91831d15f2696b76da351affe6197f1d145595ff418191aced1b5168948f9e4397f7f363d462eb9969261ca848792946c72942c32b9e82f72d7fcc1944a24393bd19fd661a2e65b2d936e99e8926e956897899af324ba3451f32f920427bca8051856ac560d0d34387b8278a210a861f6574a0e07f6afd668235b486ca6988773ce3967d5b01ec932a7c0c49e3fc15560cf416e8cdbc1005bfebb6a8fd006be76096d80b6afe6d64ea18dd0b9afaeadd5ad7d6545a14c210deca02cb187bdc3b06fb3046960a37cb3a801f537cb470dc4b525bc9be678a8324333589acca05d2a39d83bc8fb256febbeba6b1b777ca857405cdb3be89a97b79521e0d0577487becdad37706d1f40f77e857e890eb5e61d5e5f9d6c0f6fef269085cad36c29ddf37e674bc9bd6b35e7303aad59ee92fcd5cb979c247f557f39e6491e235ff27992d1719e7b947bc430369ed464c31ca49732498ea5f922bd0c3acca08be0412765d87d77ce6ebf0eca387f5f8fb829dc5e865b24058eef329725a491b3bae131bbe1ef05319617156aad2cc0dfdd46f0e30f776de3324cf5609fecdc63b46f9a6371cff417214e109b1b2db3c10962730306fe2c366ff2187993666597379167699fa7263726719fd87bb79a8ecd8de93b3c3d263615e53423299de2f85861432446ded3ac2d661edfe61cf3589ec57d5ecb79ccf6ec383e4ccb26cf7470d7e251724c45eec3748bf491cd4d133a5314116213448a1d9e1e6ba4a708164566cf6c9101a3078c9e4d2f65c0b87587111f1fa6ad8d0dd6a3fe9a9c0798328169b5483eba297ff7a6c39449d66ef298ec26cdda9edd44b372549bfeee4d2e9f9dc5e9edf32a13fd61ff6e76f94d7f98a6f4dfd55ff6188dd33e3bd049b287334c55d0b68d3e182dee5286a97a897428b964bad4e5124c69f25bebb6a2cd44a128c80a8f7a9efe2e8c4b3ca251c76d9a9761f1070c9d2339602af41c1ef0475e06bdcbd8f3401efee8d2f82a9b9668e6674bc4f13cd975f9629e1e9d1d1bd10690063d8d3788a14cea48eeb3dd357a9d461b40143dc57468747462122df2d4de808e0fb9cf6a180f26a45bd9b97961cfdedace25117190355a26e7baccbc87b58c7cf717a9cdd05cc3be65e75632cc44f5305134af600e67e7d863ad831b7428e7419af57d7e2c944b5dc4880f11e953c4880f91b8bda6b391b2d332292797b288111f223fc9fbbc88119f4ffb268948fd6171c738287ff629ffdee5cf6a904e1f9bbfd3133139a59735206aa294a39452508c83a6fc4d37c1a68c71311f0cf32182c50f18201bd9f231e2c5114983d908aa01d9808e00d9c418639c628a1a3ac51437480c52ff61d2c7c77e3925b3bacba36456ca517e925927ffbee59879d0b59c631ef42cc7c877a792fb300d33e535bd557293a76494cc9a07fd24e7a8bacb7f9905f221026dcc4d2935792f65d14b323e974927c923d143aff98301812e12fd48ef10b57cb0d6a1830be702c219cd60126406dbc1d7cfc7d44ffd89b27f911603da046652f432c0e80177f080363af8058c50043ba6e2796438f04894c2888e91a8c92812318e943008c66922e2c0523c845f41985affc56079eee021875801bd88345408b26fa684251f6c29afdf4c07315171478e35f147023045b5119d3b33e50583fe7a4c3cd42cf8c8822ff8e637f597831e5e75a86572a656c547fd4d9978aabf39939a977799f29fd205945215235cf4743f48f5b7838fd8c4a61a088a8550610246c78b0e25253081b357a5bdb2e3e9e5293899b0d9f1271127b5823f7b477a47b0a308f66adb2dd719a0c303246a6ea95fe429dee50a8c37e462110f48b7230db7638b3f681b7210b8178880dc5403816dc839609eea68c5954158a80302914715855029361975e4099e07dabcaeab5e578d39ee79884d786dce3b3fe7fcea538bf19a578c33ce38e3cc74aed0a0ce8e9f74ce9803bcba70f68503bfba6ee484775e37b3e54ac5396178a4d261811e240b961d7ec70f3c240b7778208290912ca143d1e1e89074485272f81d3ede489693c347987218e3f0318864f9613ed4878f52481693437a883a0cc0a1000e1fe163159285c6e1000e6f385c397cb442b2d8704880c3ebf00018c952faa9060314e0abef03d470992d2d2c04c82af074ba0df92a1658c927efe1865c3ab9c000f2a8b48346c63fcc38d970e2b16bb84004e064c32908d4c986930d353c1e0099d6a0a2a10c93be509c4c261d4cf24a8d07e83c630526e7133ccd50b5e4124499ce924f3af0f5089e4ca61d9b3e7231348627d3e88794bc611e28f96e409c646a0ae2cb109e4c26872613bd92d9f9a414802470fc6a740178ba8ceceb8624f7004fd7435824912d004fd74145704659073c5dc756347180ac430d8fdb8112096280ec0251d70b90214475b0676647946b70dc0ed84587505ed96a3c009467682b30389fb2192a2fab60271d7b1e53b100974fee7bd872c99e5c60544b3bb28c2f6c458696b0d64a51852ea0903101df212930828604c6806087c075e706f8ea5c1ce01be4fe604c090d0b5c57a0832b0aaa15be00e40c5f686161c0160d591270688b6d092cb4600ad91070b6042e8ca00101df0d8778810acd0a6c371ce2851d2fe8542f6c5ea02902e38211cd0b20b727db8209ac163e18154850bb7073b918820a2e2347ac0e4a9045901364f1c3040ab4b8292205467686705144178e4c14bc5b1c49c32644109a2c30de7088133f603881856cc7092858c10921645738214555021e6d38c4099c5aaface172037e0b9f1990200c4d9b2351688224969eecb84d96b44c62d74af939b50e3e5ad64bd2295de68c134a49ea02f0850655a29c74442fd145e75543d582ecc517f3eccb44e11e2c832fd067432299c669dbb6711ad7659d8779f85e746290bde80485aaf480e088e9bc42a2eba25334a223d2bce8249148d8035b3ee14b97aefaa293845412afbdf6bae8bce82c2195e0b5d7e27fb6bcfc90075e23752f90467c2942630c5abcb6c41ffccc867a15773cbd284c8d13a695ce73801e44696864961b523df509cb1929af09ee95a718e5ac9f7a35e79c53df8982aff994ce4b860e8ebf6106d0fa402a2785d75e10b5d7bee6a6327d2bbcc7728d4bea3ecbad1a9714762dd3260685b66cb45dcb7138e6b96e4e128610c28b864a23ecce39e9a4934e92c92ca1d742223013057fd5a02748634e3a29a574d249a1d64a5b10fbb6fe66dbc3b499a6ade780ad56577d228934afaeebc22bbda7a95e96d4c4a5975e6aeb15845e5baf2794d0346dbbe8b5f57ae2463ae98df2ce39e913975e6aeb15845e5baf27ea652fad970d72d57ad927e8add713975e6aeb15845e5baf27c42027a5d5621896d9da838e0c07378a1ac096ec52f3883bd892c7f683553f9aa66d17de188f8d3dda6f5c3cc5b1d45a7ac3715c375f5c5c5cee553d09035f43b6449b169b1b425602d83f25bb2f8a4304126f90f53c62cde9bf805c561eb1e6d291e727d6781e87e3dee372907b1e6fdae1caa58d3617c48147bc411ecac0cab82351118798036f90efa901a421af3d758c02d290bf2148147883d0c6b5f7466cce2b455bb81b0830dc828a0ca312d5cab997ff8153d967f61f38857d1e4b96280a1dce6c66fa93d1e42f32fb9cf35a2c71205209ee4846318acee59049cec9b073397b29478ee38e71190e1ff59f3c4c652088d59c57bc2e79c928638c71ce39a7bdee9cf49fcce47c9cc7e6bc337297d4305867f395354992b95fa9fa2269a690c3e171c7dd41879c0ee1eca2839661c43f9c0f280f96371007a1c883ab842bb63428dc215be4205342e489316a71c5d64eb5671c0eedeeec188723c3b430c1c67e391c98e5705c3a846db308c2b6af1c0e7b69cb5e6dfb4ac0beb210c20811f6758a894441c65ecd8037f6dd82cf9e5c90c19e5c48c39e5d78c29eb30b65d802cd9e375b8b581898e796e167d3d3df2ba0b029bdbd4418a2852836a5af578b2d0b3918c0a643b2a005ec046d9934315399117fec558d1b14422c36a547c426aab057310a241cd9f4f417977e5a41c3a67779d101e60a23d8f43a7ae8c1a6dfc143c8a60fe20a26d02ca1e60a21b0f98173052e8214e1d16981648143b0b0854d630f8cc058075b5e62dc050faec0a92ea6130056d86c27c06fe5645a87b78bff03a7bad3d36e643a363936390bdf14510ea96853fc93c77447d12c93773f31797796e998461a69a4a6e3c798bcc3373da6bbc9480c380b1caf792f7925a0efa1d2c80a1b222739076594f141b94b49f19ef2508a7794929c8120705e756408c3a6d7b4b861dba66d1a26310cc32266354fcbd10848831e3b4167c3824d1f69a4596643210fbff456f7924c5b41f989cbb5a71c45c35a49cbf20a880d4b39b778c4339cbf0cafeec6220dce464e7e50b09fe86f7bca51dea5a0e86f3bcabb9f60c7fadbf497e3e4f83128dd4ff05f6606c6c65d04e6c6f42a6e4cf758007673455270a49b40d74a19a644201c0a792f49959090462210f6608aa39824e1d0eb7d037703a51db513ad1f5e1e49143d2e51c9d2c2f16ee2bed9b9c1e1787a7c4c37f1e4db4b27bde4418860715324e397f2e8337dcb9ce771f76ef2b89f944c3d687cc0346c0acdb06996591e3f2b08c2821b186cfa78739359537d96615a2d929bbc457ae9dadc628e43401a47fc6815b1e95b90c6a5a67fd761d2ac1cecac79ef9f8613a583d32cf9ed7167a2e86f963b04058ef46eee26577137e17eb56af49296911ffd457ae7f27693ccbd9447f3de55f3de31ad92df3eb7a685ae711dc7719eb77dc48d442110f6f4cb44ad6cfada7dace44c20e5a73cebfbbc82e8ecd0d868343435104339e950ae14ce2bd901451d9e2a687a24e904a650cee5ee11638cbba7e498f232cb74d2419995a3329d74d67792ef924eb26bb2d68a558c8b1d2e767ee022b358479365d7300d8382a281995d7bc0b44a2f39c975c893aea57c2685923facbb0abf3bf64ecbe4605ac53d45cb98cefde433294dc3342d33e9ec44205147cb30bc438fa7902c571318673fd1329ffeb0cf9370efb48c497f98feaece314f72953ce9f2a473afb65e23510854c25ec7d14c54ab8888cefa151e49543d9e2d5407314bb5255b5e2f235be8e7a314b2656a1b5f4f73ebc74a8abe06d36af3ddd7e69d1e3f66ded378c23044d9845877bd6402b471335bbc974680a7106608ed95ec8959d062d7fa8ca58541959326524a1819524594524252d2a4919452824026071d0564722d6e3a839e9243976172955246b9289b5ce5cb6c441b7420b6c41be8c0233af088b558a6a30ea4512fb2c1f241401bf7f51c802df208d8912b7dc07cc71ee201a664fccb2dfd94cb4b181414130d532a99e4883351f528d96a5ddf2a794abd8cdc4ab949343d25b74807dd24b74a1e9246648ff4813688d45a034370c20a32a4eca77dc81e54a279459eec71765999e1054ec14c94fd953faa754859d8631f77ec238e7d0c02533557bf7d88ebdca5d7bcdcc344d977358c601e6716d91a0a4e9482c73e566167cdb6d65a6bed9c35f66a62db4e479eec5f643c62db93bac0f341cc964e7ff4dd61ca9ec76cf1b6778fd9de7167d56f8fe1debdd3acebdc11b225e2d847ab57775b7bcdc405ceac5691277aef6e233ed8f173da5c5283c2a7833bd58ba43fcc820d7ec0e026270c653822d4853078010d477040e40b8ab91da64ade45fef2272f34eedffdb43494fe9e52ba7df7f0d65a5930640a57f448c13383548d3636d188fa0f0a6c836111ecfa036ddcc363950551f55206d2a83f1102ee997508ac02da98bbd62dec5aaf80c2aebf7250bfa8bf185e59236eac25ab63bca054bcf79b96c9b95ab5ddd332dcb7cb74f11ad7e5bd05f7ee2bc8e59954976752f0de7f52eac896183e71270aa94e08419023110b2af66ae39cd0a2c25ec59d5aabccaea5912c2b08463d2259a0135a6048967b825d2f97bf7b972e7f57fb5071ef7cf000539fa8fa1e3cc094f64ecbc8946652f32b977998d2beb980616a3b4c5119c9029d20441176ed3257df8a417010e004b6893bb385c7d2d89a7ac43b7e9195eb323d97bdfc4581b35ac190a7fa2c4b9c6311590369d4d723d006ac5fc096eed58260d7ac1ed9b5d31ad3abbb8a3d31c3590fb7d4b12ac520c01698aab7de4caf30a657a57aefb5bfd75a9c4b8a6ea0419528f0a783bb0f4695a5f616b0decab4764c944419c1ab4805153c910a385de00eb06a8a21a59452d0246d18ab30bb30efc518c693665202bc2a9524cb6afb499cf341cc9b6b66dec893bcae1eab6fa378a7fcbcd1202cf263c5968fd0c6b58dfcf4ecc8e1d8467e4ab023b441b7911f20ec086dcc6de42767c78be3018a41072df0c21842800521782105212a421b711bf9b19795d65a68e9b471eb62165f6c47a21045036881092360b085125841848a9e22499c000462c0f9a204dacd486621026708021a7630c4901c1021899d1f1c0143128828030e8e50911d81849ac184084bd0e2094610210934e820878b18bce00948804113864ec8111a6e1ee164c3215d80610b9f96991364f153861a1b248290020610f9c20812d00081e78713231fd8706d90b0090311459860051262d0050c74963085163610528622b432aca0bb26a0c2dd465b174a48c3cb90051c4f6ad470b9f1824b9864c3215d54015f44e8204fb5c6084738a20233f84021f3e20c341883144ac800c81448ba88718bd00b88c20a5fc8a2082668c10512941082186460c50c7c308531e888c630045309565fb8c119b6c00152869d511521a9051b9418e20a42dc5ce1838417359e172ab8740464a0c29409e17384204f20020d3b2a3facf8c11658104184119061089010322081ba403e800384128461070a5afc80573043088cc88289224ce1092facb079a185c925c11524631043954e10e2851226362226386e1303184a861083266217432200361cd285135d2441e2026b74cefb22471b0ee9a266afee6e02c38b361cf28531ecd5bd9bc462db34d21e854038c6df792d5efb15ddf2c6d8295b9b1b9651b646372c9fec6f6b75c3b2696b76c3b2c9d6ee86e5d2d6b00dcb255bcb362c936c4ddbb04cdadab66179b4356ec372686bdd8665d0d6bc0dcb786b78c3b2b735d086e56e6ba10dcbdcd6441b96b7ad8d362c6b5b236d58ceb646b26119db5ac986e5bbb5d28665bb35930dcb756ba60dcbd7d6be0dcb746b271b96e7d650362ccbada56c31505262fcfa686f79bfaa7be420daf497dee19b7a2052134c196f9a1197b6937a096f9853671b62d1ca11d553b443d8db67e2965ed775ab1f6315ae1b5c8bf72a07bc7bf0d8d7f7b5784f4a5f5536d53fa86c284f33b20630ea8ce58942781523e0d5b6e9489e288d7a244ff487f873422fba7fa0515401d2882ca0f252fa604f39e79c73ce39a7ea003e38fe00463840153038825774d3fb65d8e3ceabefae3efbb8b1bddadf75926d63bfc82cb2007e0179e44987ac29e9e015dd13428d336c9bf717b660bf7a456f75cd2b950db7bb577425936113b25c17a5f033218841b3e54ebcc7235bbc88061c39af4706f8e260f8d5f57a0eb0bd4b0a18deeba15e8f64815b4eaabd1e48c3ebd9f2d0eb8136600c1a1a650b54281658dea0248b70c365e29c489f15214ef20b2f3766e0526322b1dd2033547e521a9d8e8cb09ca2c68c93ca4f4678bb7402b92ff84969843715225081d2cb524aaf8b527b5da5aff858122cc184baddadd6aa4411945e96527a5d94daebc2a393252a17b28cd62ccb28cdb24ae94f2e45a4a818638cb1e7799ee779b5eb3a25b6c8325ab32ca334cb2aa5b874aa46b28cd62ccb28cdb24ae96985c716e1397969fbe874c2275c3af1d42d507a594ae975516aafeb86102a8accd82bdbe844c5c505bb6017979f5c6c50bf0a75b7ab5ded6ad7711cc7711c57b7ad564b2bdd6ab5b4564b6ba5d4da4a2ba5d6da4aa9666b96654af020cb68cdb28cd22cab94964e5494e0398247e5625c2a9dd2cb524aaf8b527b5d2a2a2ab874a2b2048f1155dbb8ce2b618c31c69ee7799ee7d9aeeb3c23945e96527a5d94daebbaca8c257a3063c68c3be3ce285d6586fd4196d19a6519a55956293dcda861b930da7075b3af32edab6dfbaae356a1aeebbaaee3388ee338ce6edbb60417371d6419ad5996519a659552979e2b0297192f3c3c3c3c3ca7151e7b4584424affe9b4b2e2c2002157c81572855c2157c88a10971b50c81502a597a5945e17a5f6ba566adc58e202f1d1630281adb5945a4bb39be95aaba5b5d65a2dadb4da4aa9b5b6526a6dadf88a820655e0def0c6defa81b3b77e3c158219c68f95544e8cb4d6bac57be966376bed76e9adb6daedd6de4b6fb576d3348dd2aabd564a2fb51aa555cbacbd97de6aadb5d9a5d766b53ed65a6bacb5566b312a638d1b4a194b5c8c042aa76d748267cbca0a5ec12b5f99b6881bb854fa4fa79515972ca335cb324ab3ac527ae3c68d7be3deb8374e2b7b7563a5c60d1394b68f4e272b2a3368d421a2e47b760f863d11f6ac6c17d843f3e3e4625cca325ab32ca334cb2aa52727f7045f57b5af7a757d758265b4522ca3b5625846abb5b6d26aadb595521b6b1671c6af6a5c8c4ba5c7c802e5e94e54bc945e9cbd8fafb15a38e5ad1c8e1a11257f2ffe5ed588a7d5699fb81c66ecaa571487fb95dcf630e280ddea55fdaac6bdd9a5f7b2d7cd7eefbdf45ed6de0c421af7d16e40ee206936d53d6618616c7af9817d3dfac01ca08511c65ec9507a2a33af28e1bc34ce17f922a1d5022c62059127c8934f153d4278e02f94c22548133849404a730068703c0582de06488d3cb5e4a9ae946864e0e705048f1f765ca0070bd0a9439ee0495800218410420821dc21c61b643c7184943622102c179d3ee40642ca7803c481521a81905b4a4a6984f106f8c905ed4a16083d88e52f4ae927d451473d2509a494524a29a594524a29a5bc4e3a5401c0e1039f16a8042b5bc98a542aa5660600000008006316003020100c074402b12ccbb33453dc0314801277944c6a549c4aa324495214648c01c61040080100000308102846201b0050b7b852d72d16177ccbcfa856c15a7ebe85802eb1b02341cf1e049cf7f3672e4be7c9b0bd6964c41612f4b2287008832d7b10a111cfd06f9ea0f52d3a4a881fd4141bbcbfacdd972747f6cb88a5b6c94312fe119987fac4954f087dc82213fe4f5ab7745c5cface1b1ca0b5859f8c8a006c5cbb0cee25c59a71c35f1e43ed0cadce7cadc3a5ccd398718b857cd21e717c73ea1a88ff4a8622bea4b4cb1ab99e5497d2467eb9f219b7c091b9610d788749fd63b9b8a2e717a9b1396e25612c80968fbed8dab93d3c333233dae7e65d223a888d30edc2e86ed380d319cc1e512e82221b70bdb08b343d380a3758d10ac63da7852b0c8c63828ee864416e96fe8b1cfd1e0d0029858f2795107b54f4574bbd70df3bd6e1ecf6865555495b3d3dc4694a04920b0da3443239046790a4c6d5f6fbbb256a5c2c9a8714dca363dbb343326116196daa5711eaab1adae2fe2f4e8baeb3d949ae14b520e58e1514cfa0c256b7a45144c6df748c099e54c8fd3f1b2c2d8be5e9d36dba4f39ec1af2ce261e38bccf6dfa71ad3145b4a1db464bb36a8a9ce2dae10f3da954adab68fac30478a2aab7eaec988edfb7717e901459f70fd64a331447fb6d5085f325b821ed7bd4dc9d2ddfec0b0f9752e9e5ed7d1f995e99639c6769f3513270d8df9275be234634a068736063fed4d514d86abed2715991cfbee53268ef6715c7ad7081ee33c652370becbbe7cb257ab21dbffd50a4900cc757839fb608f8db99d54eb9c62d8a4ebea53fc283489adc1ec857176d13cfd87a10618abac8797dccd5cce09124bf5459ccb3874840747139152298637adacac766de6b374a1b6ad6e31086ea7040254e84dbf8bc65b4f43c1ed17434c8f036bbe928e4be9450406ffa74d965841b56519296d3be92b0c300d6395170eadafb3038d3c834a29b787f46a7be16750ff002502642c09db0fb019710820056f3be0806dd70c76b0d5f69a8624e25a96097f5370e7dcb4a3b6f32e829c38737d3524d6cd374650f5523c0ca06a0f1a6465be77e65f8dd2513f1db100b7a2384e1db683f234d48948057533d2b70e1e43900c52660781d6cfa4ac2f730b030bbd35fc457ca312fe4d71b7a6df2083d4fad4e4b4e40e355f74b0fe8e6cf911d18446430a543202f1506f9d745585ce61b9dd8b0d3826dd4b8482d438353b2c51d700d49104d099f1c79c96c026cc71482d75e5694a5d55d6f8656f10c8f9523a1d75196617ef8e3fd3b36ceb3cbc88bbd3d7853db93e80d1d8e4273ceae154f6994a73dcab374aeb1e4083ee8094e64a252d95ab77183b9a07d1013c269abdbe1c559dc58febd61858e1797d1611d79e1aa5c2e3cce1f88936ae906ca5ee7ee219dcd3b81cee22ede8a56cca33c84aa3acdf25bebb049a4ae80c1e02ee7d108cc0ee125dcdd2338a4d2a6acdbc43fc460b2bfe5fe695452edc56b8d0abb9cf2fd61aa8029c5cbd36fd2612f663e45f742862f1034b7703a8e30c856f362d5332f0865d837a9b15054e61ccd4d83a4b5fc481b0167ecfdf5565e8ed3458b5038824a643d10c8136d2e9b04f019b7be0dad3904aa91df9a2771f36d79c2c80720df310fd8a3d644e4f149a5a040f882c782001de590cea0cdfbd966c24aa7e52494278fc8b474571ed2c612101ea3355e70ad3c1c8fe43f4498f69cd9d021f29c2abd1bb503f55b79c53f62704496b7b58e31b5bcdf15df302eec6ab2ce30a7ed5d39692200790cb068da0dce889855f168796e469662456d512dd326d3cf528fa850955828717904ee467ec8df6f8d5ac5b80bc8aa472bc9851740bc67ae7f1826fb8314a0cbe952b93eee394d095bf2b7e87f60d472a10880eacdc91655719b8f724e89b6149edc772e1d2624e040f8f6b5bbee5195a9911b2811d17d8b51fa21e6bf17b44190eaadf2a4a6033d8243e2669a0401ce2bc80ce6ea55de4dc0e07cd3e3e0823cd6d25b58b63ea1eefafc7945d335fb424ab283591d0cfe735604162bc9d211a7a39079af1296043ac1bdf9cc4c4752dc14203bc496a55b92114d00c7e39d2c5e440989667fb7205c3dfbf2963780d589947a7156983151973014ab66abd25569ce83f8206aa4f385626611fa4174470ae6a434a650cbd8c555c680be0fe160f0d7e1dfb64098c406bb130c9ede8c95c9e02ecbffc2715e56206d5c305046c2a43adaa5b258002c5906d3a97a380f61d2b631d0c59b4f70152e506e636daece96079386beb66a588b70daa24bb6952fc41e88e02315a198265d62040f392e6a1023a98cf396b2cbb09fe0bb51615cf4c5043a6a9827d3d6d10e347411a2810b44f8dd7fb4b372362216af60cca3d149d476d969015372f6822eb7cc4b260a59f392d95fe8a9a0c523cfac8cd5028dbc6bfc4d2c28d84b62f2e1c52f59e2936e9c503f497694dcbd04ffaf9d6850cc2b34ab286a5e691f233a24f6c4097eab88123d11ab904c101c9cda5372cad2d2587510dc30dec82f1045814780b70a2e3993cb9e9426c86ead45d740ec1e505188947a695054bc5227c8e9c88db6d40932617c906126f66c74b26152a8f414e0ba13df14af5122c5499964e88cbbc37e6478c10799e6d48f4d40f1ad9faebe170704bcdba79ec0e0268c83fc5b9cb86212eae97aa14005c808a11260c817358089cfdc63d7032a5b87cbfdc2325111ac31b5bc6fe41bfa478b3c2993c9c7e71f51a5a8c878422f85a58b4482a07811b2d7bfa0f26fd9949719e85313d23548e5a2806dd4b12aebc00be1bbdddfdf0f9eda963f97d0cd4035036c15816dec3e77fe8bd679af4e020eee550cae59325509205247ddecf70226ce1c146efecd700f354f996aeff0701f11005259a1ef83ec38a8ad069da0ccf4eb0209911f694977101c8d08bb883ccd5f4f44e1efc83eee81bbd53af1b718d0d450ffee29bbcbfb7a34be6d9c850e52be61e1ebf002e422fd85d840fb6163c8e1ec1e4ff0ce5c14a08e16363e0e0d9ccd5131ef3490a8f7587ba978824fb0fd0f7d9151f99b23496155bcd65860ce7dd7dcfe62283879b5cd585abf65d0849964e90874f02853ef295c7a30c7c2314a06aa591f49899da98b190b71474355d53c33fce1cd83e5f595ef928f4b8ff204f3ef6eba78b17e23024d984465ef2481980183f04ddaa73c105537a2f3ba39e5506532141b7d5bc025bee691cc45a9b87f469fba82543354c895dcbb372eb91b3a4d0f83a886b1605b61293621fa7d19291a255806b6ebbc24ba681f5ff9d28120411621791ef2350a36ccc8e013ebe6b9f31e872b605e8e4e03ba1e21fc76b8373764bd4829fe60071beff0282006116bfcf5daa6bc8d0106db4ff38944d924c9cf93b2100b21ceaf2023c7724397a36bc8a41affdbb802b94ece0668c412eef9c183daa15aa4c67657c19814c0e00c5bd622d2563a195188b09410421c95459488cc86430a2f46d451241ae6f69deac8b64ea811182d4900504b9cdea7c9f49cc601d396452274648b19433de94eb3bf04a52437b25458608930397b8fa6c94cea80dfb0941987ab4060cb2a9d5bc8505556943e2a51680bab128f0d8d2a2ad2be8a50aefe7b657f86c95566530abe8c37640decedb79c4263e53abb2fb9a614c3df6892148ff6ac84135a684b1b63184746894c1a1f215ea0474b187e4c296a61b706739733fc80ac093b2cca1f5aa4e9104791988a7cc6e993370eae80ba85af50b732434f55eedee8e4e0c0bc9fd4833238cc4cf01d92bea433aff78cf20e03379516cd1cca4472cd79b9ce0cd64a43231128cf69809ac06d3a85a10c5364d0df063909c5c056504f67b8edc23d45a44484cf08235363af02a201cdb66df592c5b248a5b3b391aa0c103f862c04671a434c230a36748d15e4ee333aab7ee8fd1dd4095fdc1a9fe698c3b548a788f5e7998e475afc90dab515ff6dc43a7ade910292d23cbeb931ba134fa90b64ecb4f7da6d5d969946f4be1cbfa79f2690cfdc4ecbad2a0e63753d9d0116511a9a36fe21eb04b7745e3e1a365d2afd7df4abda62012a3adce91ddd2454b51b32b233174f6b2fef3496e4fd60937ada2a6321951ed7a93fd1073e8d1b2f36f0c32ec6ea2de80807f2d23e1624160f612b2db7c823f3733ebe1f4d30dbd4e53d9fa9338f6d306eed71981556a5d31a41a3af9ba4edc25b1a52a00a8c63e3f58a4ad3c835decbd7c05b4bc13b012d13808f6f843d4df99a0150e82f6bd54c1761058d91a8697e37a61e70ea2e4d46e1e6282d04fe09dcaa94b1e7e5d65467e6a761a50374b8fa00f70714755e5082e132a906ef117b62389c1afaca726878b25a855d7af1effaaa7d0de5d1ea324b9cc7b0b97446735c43a5a94d534a406b90d534cfd71968e0d8bf7fbe0da013be04049df76e1ff61c330871b1d2452e83caafab43f1d04a4fca113a0b17ff1495ae2502e08950009e91a5e1089ca2a75f6e68987c569a811ed3144ca4639f177c74c38c618e570c8802208d4eae27cbdf4d4bd95207850e5b10ed579fb27214a6f62edf353b0e52e9b277f2fbb3c6b6d7bc1dfa78e127076e18269ec2002e6c52b637c662de88f79b73aafaa0984fd5314fd81a5b65f3a7b032f4775646ff6e2b830fe21d50c4fb81e32966664ab0d73512c940b5abaca0addd3edba0b4601c5304710bb881f63f69c741a83c464ca074713bae89218807952ee712ca9fdc6315b73a997829421c276b0a0d6628206c1aa0a12871b880e2a60aa7c9771c80301ac7cdbb377b46b6cebc39c1a378d27f39c702d18dfe317b2ea76ab033b60806f39367de12004aacba460ff7faed70dc96e7d0b03fa8020dbec7655639407c7460b661c6e92c482df2474f1f6f1074c11fbdfa1893d56aeaeae5b7af1a5eb20941910f9d026a30fff075ee6c429181697d40ac0a7cd1e3f0bdf561cf0606100354b2808b67fe72ed156d5b9917cf683686767220ee324b0ed305f81db51403e153d66fe6b484c3caaa87d7eb792f9c7bb0c8f8986b39f8386a677392abcd7525e103d3ebf121a0987c1c81311f4da4b85ee11c100d9415f47ad0fa9c3850cca2c4807cd889ee83b9abd8900b2c6c58a4d6e4681259834e93d5ff08674bf9291bf94a96a1ec6e7c7e43ae0139c918c4aa6a411989801b7198c0a0f3fef6c19e73061013f45213ca08123637455787dcf189fa91de7a0176317fd66e7bf4bbcdb0dfb736aecad21cd07814fde5624d81f7a79d6602ae8b2947138897ed048b04dfc108dc5919126ff72da714e5a1c4b4d3b05bf1fbd0635b57025ba7cdd9fdb0b2356218f43a60e7a4310be511237885f04e1de503f95ffc97573ae19ab1421348565c4da4cd9d63db1c689d8cc18a74fab59a0cc5a8ce0afa6262f771df288d294920fc74c1b6c5cceb5808040206bff9ab42d656c3945ef735e1880745dfc65ca3baf552b7730468005e37227c881a4b9f94b1c9ca709e536f58d654ecff336dc011cd89b5b94d07ad8f83edb9c6beeea9ba2410034374094925c67310812f0f2bc02370c1247b57e6dc2b7edd2b2b67b957729273861f487c7d001d164967f07eb93132abfe7ae6fe2ec16341c2adf3d27f0a045228962c5f4364192203b79b245c91da88b01a76c873d2bb43d10d1a7eeeabd86f4e28aacad56ae22419288870955c05025384c2585a99d10a5dcf24247a416ebd4d08e32abf19409113238563aac693f44b7b0d114430b31d1a495ac1b33d336ce60dc702045ed277c38d637089879886b7e2d10f5d5a564d2ff3f0c8d5105e3cdc23118a44d538fe32274a9c0586a0c82c81ea5e7ad76e766ed03ee1a53c56795f9aca30d43542462ed4620f951a165dfa11266ea93a3d96cd1818017ee69ef44ddb9e959c7b0705de269d5abfada1dd324effa2ab1b923d51ac9f75eae2a6a3d24b0b0bbffe3d012e82ed36e14cb2d12d0f92fad567038bf3e213189a4b6064322b21007eba61d632c76b06202cf823ba8d07c280345d0ed8b47b0444279c2c32e0ac40df5dad54e1fb0b546f9ac17d76637a73066b494e80b9eb89e3353a03cd8767b4bdcd1e370f3214d214ea8822aea093857dcb50e39c1b3f55807aee18820ba897d4696e0500519f7f4563a3b9e71e10eea54aaa23fab48faf22d5643ca1c9f58a3deaf31beb33af26acc45a1d3daae05abbaf8d1b289ec445fb27bc2371f123f7b6269441263c9b10003f1d106399e33403a66089faa79b4d43b1dce4fbbfdce34238db88c963be6707f71cd98b8ac373320770150fa91e6226863c00c972026650cf8310f4c526257cb7e0ce3f10a4dc7b6cdd6921c5ac5e0ba35d5aadbfef3c001346d8329658f9d086277afb18398846276069d1455a1a971a25634700da92b9f53cb99e0fafb84822e0fa2280fdc7c6d306febe80552a853d947e50ddd678306ea68e23ea754e235ef129b714a8ac8fd3451976085eac15a1ccd364286156be90ac86aa7623c56641404ce4b512d78dae2337b25dac83c9f7146957a7b5ea72f60e6ec8a13dbc7c57fc03dd94dbb901b38353339c33fe15d1e9d0be03e4988681eee433471797e3842cbd3c3c972392e90cccadf9b96e0d013a8227754ecef510f9ff77850e8826b5c4162c25f6b73f3e381914b185a63db7bc1314e53f27e7894e4e19c0f89936b0cd778b1ed5234c8e8827c6321bf35489c5fa7bf4c861e83f0d0b7f10e067d7ded8d922a5461fbb8f0eda43a8a1865a34a150924c478201d513d5b0588ba15f8f85539b3df889231f42c72bc24082669938080ad221fc51cc59a681881fe694f8c07be2dbbbf4f1d50c5eccfb1ef9ee4cd4f8abe862c07340ad49f3dab86c04e301426919ea8eccf78519355a183e46f8dff68a0b1d42d2533878877c4d3077643238617c8a6c836290ce36c4949b03fa4e5889d3d05373565afdf77b9394af52386e3d024546a7b14c85f48a14865e0462923ea509d183d6a06fe52b4d0e40e57ed33f07836862dbfe738eafbb625597e923d034c11a9395a0c8047163430ec44be8c87a77af9f7a42fcdb893d730a58ff6605ab1d449894d13762bfbd1c74bdb1f72feb34d3b477147010e0dda67a6ec75ffc5c20f76286e553addafd7d8c0f73994b9fcff0a16453f056e6c1ca5c659a626db5078420dbed190c92684985d0b174a80a553efe92a181273071cc06709c23dddfcddaac2721adaaa3fe221944470064c7ee6d37ca4abf19108b6ed3dcee7805226ba3cc7ed8b74abd6371ddd466d2843924d80d4364b575233c12731a4472afbe3b0675a32c13d7a97ab832fc5184db35c9597c3d9ad255215ff493dc0723692632bfbf78aba2c96b15c1859ba587a27e9c54409338a2436bba9f131594054f0963b88e98a28ea889320110c4d7398d44a6618dc93b1bda8b48ab35cdfe014d4eab9bd4559456575420bb97609eca4b88347848fab34a161a27bc3c031e7a0f75a05b381e1d7a2d8fe8ff67a0a3cf20c32bb307e26dd4881de0912ef24c39d05028dccfd09c3c0319909c415aebcf1bc64aa415fe6911cdaa409f5e1dfe9268e3f9e1a3c6db9db661d298ec3ff258fcda44bb751a90e5690723e83a8274888d424d7e9fe66b6e6ef7558f1553bbc4a2e1d25086465f6d2ce9a17b09d47342ce5c06b8f5b11b0d405adcba565ae5f8be0ddd0f25499e9c06fba34eebd3a7f40f72812011391814aefa023053a2fcb0c1b1545743b1ee85a61195da35429b949d72590b2b4a817e53a3408f667d966cfce1047785e61bed858788e2287cdc1ed8be1f934ac2af88c52bf4a332915fe4e87f62f456ce84c6620308283e22fda0c7a54db219c00b33128bc288cf8f476ab6acaafc2598321389ad6bd9345ad13209ea9c1ca60fc47eaa46d8bea5e773fd248008ce5e0e8023fea4555379515ea4441de46b970600a8a2053fa2e54fbe188e9e198e938ba359f9284a3c1892c514b078f886b72537fc6a08b066b412880dcb13271c80e8a99bcd334e3d912a737198394ab662e98e1c85ee6e725a0e80d5dbfb5a07c58c08fd2b2fb93251b824424295eb621d63a7517416b41739aaa0338718d7c348d3a7f444f226f121e0e510c48e8265c7516ae18be42518d0789d87251caa2b885e00bbc9235c719f778cbe806b20bf61be44353fe1b0c840d440d4deeda23966910e236ec0dd4b8ed5f9f559844a6bb0a0be492aac6901fa27a9d2b416a45f1154a61a16d467095ee92d1a1644d8339e8110f8c5087648c6ab8fb748fb1c2385c39b84fdeb144703a5ff984b71dafa3ad012b80f26893621b6384ce4368b9a101aa38b2e4e6c16878377eeea41e7fcc824b559340aaf238e0e2e03412319b93a66963a57242a9cee5d8fa8428ad89d657ee9353c01d79098dd7a84283c58105573498a85feb194a5121975f2357be6c88bbb2c9738d487008d67fc387b39b378cc058944e1d7503090e18349f027e60fe8b5b1b9997b018e6cc1f18a8f5602f1d4f4a9c02c8bff57fede1d2720dba9d1c3fd8d3b5c1cdaae47ffa7fbc707088a5e22a748aa05c64a82995080fe7d16d90f90719d880e7781f9fc57378cbb0eb74e75541caea003f78fdd7102d25e1fc8cfcf78bbc39672556eaff0a059cb12c86213a3d12f7ee8b937e0b2c328d8705fb3be73f5e0a690a29857b00c467630dafefd6f8b7bbb8d9472ef3e9911cd2bdca0c6fca3f33ec46b0da293623b06b43f2411708f1afbc8885eab26389d6807037a1363cfb154902b9d9503b758a36810599ad81e329592d9757292d1b09ce6140499ee208d070357fb8c8a1ded74d9796118681e490d288627065a8724039acd5303dd73c94e0e282c86186fd7239cf65e1ba34383861b255d8b4d5be0d5b2a27fa5407be942c9ac50a9fa2a2411ed749502da1f0c146e415e8d86f89795320ef24a350a3adf83e017259c35a260316ab8792218683e9774ba9fc2c688e9767af0de90c5dc63c11dc4060aa7eb050dd1b13c5a61b2280aec65cc941354c5565080bc71c75b1d3f5225573c76195e8778dd8485e7af210c612c18a8696d350d844fb81f0eed8978f4b04124b18d8596c4954e9dd994f490f2c86846cd2d6ef1b04d55bb17f9576401de5c1ac68ced9b197eacf88cc77a709cdc014a39064c370304199ae3c026f63aa2a5416f9a23b4517407c1850ad9a2242cec0ea8cdd4b32179cecc60526677689ac72be21d9095a1888d7359d2899a98029da5f25abed78d370dca24a1c32b2fa30b4dd37a5b25c28eb4386e26126b65e76a8c28b54363cae90e703878d2c8d134980cb8d8511f82020714a7ca4bb8c3f4680fbb2054f46b9302253f50848450b97fab682db48dc60571cc1978eab65b18a6c642d45f21252ea9c7f96d06c2db32cceb31621fd41d2a32ca0f5a33a48157c963501dba54eb331a67df940a15be7b4f283be5812a60a47e43c3211c4d91232343e125caea5136f80eacb30abbe899382b96a1c06a9a7988774b4b2af892c458f111310fef1a88a4c2ddddd583de6795f665826fbf77c20a74277d14ba90bdeb450742a76ffb04adf837a43b70ba376f4e167f63226b48538b68a9cb4d7ba799ca44ca33283e3d0a28f6cbd8ea691ba7d630d62d03657c0d286d47dbb8cb0241167af49d89762c78712d0668f96a51a43a46828c9bec1eb6faee4ec250e1136884ec85d3ddea12c25524290c94a222af68ef1d29dee19954147c62937b13911b67c5844c25e7dde4a81473ec9c424ca3ac24849d3c2a09001930a5e38838b54b363ae2e85f2175a73a618fec399104a81cb2ce43212808fcaa66c3352fa971a73d18bc458d02c784b48399c0c706b875285091369b7cb72b2dd34b29379ac7df70c069628e042fe5427ec4a69ce248e88d00537d17a22313bf8281b52b42d33d76fa5918da989367b06082169b1a0515e890cf7d95e5e6df1cdbce7e6810997218ea75ebd22e121c40b12e3314f5b8c9b2cf603099e5a7f4d2dd303b6228fe76b1f39cb866081b4c008829fb6464d314e49cc3f9e0dc82b7bb71e5982e7103f6797cc99457087941abe703fd597a8d28de0beb28d63fa5a39001800d0c1e0382df853734a658c2a48d02177e82f10f93c47f2aeb41338075d529f93d7eea5420d7b00215bed716a9cb242c90e7167fcd7ce0890ad46dc37d0ad8fdac14a2d5941d3fd9f5f49f194efb005d390f2d98f93095c42e71e1c6f78186c48a02e660b617b4de049f0bef68ec58de91f567b86c2749d07a438e776c46e07364ba2ef7b86d4568860900db054defc3e78a37d4f87b20ff8690144fd5f3e1d91d2aee2a1f5802dca4eaa067af74f7eeea8211be87d6d5e0f3542df45e961c21880347963322b4178bb0963dc7120a2a6985705ddfc473b248ca17e43c7d19c7308d77fcb4d07e41ce934fdf9058fa4809d908725f1c2f3487565a291acceabcedd91003d93d3e5f28a6047a0a11922dbfd0900a8a2fa1129209f571197e8e24570029df4a01fa764f8ba01b01f5f152a29025b90fae0295c2e736b5efa5fc6d680b979818ea948407ec26be939cfc8edd596ca2df7c5c8e5648bb9b8e606f21655fb95a5f73d4924fccd54fde6e9fc82a3a7892e5b613462247d27514a1b0adf2e9ae7903265d88659707a9c44a788af13afa90c8af8229214e5a846a1560d208739725cbe61975620e23e29dbcaaa8393ff4f5ed4a6fcbfe2c555b9d26a6e14e6b7f49058532a8212548237805f464a71227a7b246532b49b5cddc4b384b6081954f6ddbb3c4a6ce21a6d7b9b45696919104dc20cefa9ea303275aebe6fe4280916f177b34197499a06bea35c194e11b0d44e5b9a39b06a710fcd9b3ed9d8ce4ce8a7556cc29786f5a34e8c10f0ea9b0b645b0204916c5fe0214d3dbaf500e6dc3027e92a99d90775dd92d644551294f56d203eb720f79eb559e16aa152f228133506c4b117c8dd749018ff8c60b90e0017f33aa436401e88f37c327e99f18f23da94f4b5ff952eadaf9317fd109367b2b4a0839c18c78018b20091b6cda5a92749e8a95c457b7e7d2916b161c9fb1b1b615dda027a621e054137d34a967a4599bf0b0724cc4be1634e7d84c9e12a202336462db2b28ea3936d694d6263c63322add833e0c0af5493e33030d14f177f3606b5f9516a20d6ee81e514cb2fe167d26d41112a3c9c066ee24c941062abd3433dee00dea29df0fe7a1802ad618656c1bd620d846206b5c39fbb416a009ebfe5cc1c0827106bb8bd84bbf9361ece1be6646d5e6d611af53c5ead1c36ab39294b21e7c6fa997f90a61178540200cd6e8d90b8a0bc12bdf1b6a836d2f88310c90bc2f7020c952f9280d0823a6652791241b81b80d44b289b8732fd348ff8e7802f41d40a61fb54ccb0477a469905fb4a7b648fb7d34164e99e3a99a97758a68a6ffab18e2f035c6a8673c509e443c5a936cb69367503cbbee25a40440b6328fc3e59e6225a8573568b4d5c887c59b421e8490eabc94b296af4a57ae49255a113ab9c8a3862c8c1b8099d0494bead9243b6e68f73c01563a42053d8bd156b79b64b10c0c99803c224d5dd3dc44111312d2b0ce7d7b02d6536b4a2a754b13f85ea60092c49f77cf61dbf575c6d249207b16c40653b4c9356a82e5c83f280c25a6a94db17fd58a0ddeab41c3dd9d3acd0e6b0d12efea746f428548c363fc5c1350b377e0b3beb2356b71260dc09d510d67d7f3d8cb4780dddcaad5024a3813e3ba064d4db33ae9cc44e87d64d72cebe0595753f0afb50f95647fe89a6b1c188e2ffe55ed6752322482062735217f1a89a8f63775c14495225b6793078b689ca4c1eb8fdf774510fff6ae73b0b5d015477b2a3d3117b09d8a1065d34ba2f29a80c28a901e945e0e0200c4d2c1a8e77adc1b01fa30ad0511b0c9dcb9a8be73b7d6d48c29d92ffeb37861a33f21a0a918f30753cb4b345b1ed6973959dc221a62ef1351cdd614b341927b156123ee3592bd97307d210b43b3705819435656d50b05cb0775eae1811466d5969c45456a746d108906f6d284302d5f0545fdb4d2db695f9ec36869f460df2e5a16d71a3424539a1c0ad05c723bec9e79077876878fd7772cc71b39e4cfa88ed33aa1cd4fe4f4fc2aeebd61c0bc8a0ed08c7eeeeb3add9c29ab60cab2a082da1e03514d66c91fc552f8d3e3a6435f859dee669e05c493cb606b442b77d0789d7f017f6ccb4028a1a5399cf9b364075df598517db7c00aae86cce9ebea1b98c6e22785cc05cf3ba0a9f173d90be48aaab52ba39fb0c2e99c4875bb8e3de09a6e4de7750cbbcb4882f25b333cb30ce2eb77971f920c2dd5ce287cfb0d87ed24aeff2f939b21a391080a0b8bac2be0097a38f88f644c1e8c8336ea6856ee682c7e91cd0aa37b1d497834aa5f08fcb13ded80ba92aac9c2908b37c28e6854446b80201b7f2d345ba02cae439fc1299889fbbc36007ce4a5197da56e31b231dd83a018d17de98b376bad8c4fc11b03fd0b1d46042449d4c300f25a7025a1f16f57f8e8eabf9a2cfe45dadb4d01ea02922be7255e81aa43d841f2cf78a98c6640069fb277ba7356a7a0484826f8f06c203983f441c72f1b2266cdb23f0b8ae1bafc17822f6f8d8b49d6d3c79173a4666f81b6795cf08c0dcf5c2cbf86dc0c35418e1d89d28bab89570387015951c980f75e1dbc7ecd9bc3bcfd5d5a8b6829bd40d0c56662ede50176a1008f207aa6d5e635073193aa5e3f711807986c079769157ce4f9b414bc372d3a94f8ecdb905e1d7fc4d6cf0087f39870304157e500b45a10c2c558af2c1ac24db5b0c4a38aa6cf4687cafe8dc00c7ea27ee2f9b51bd04605612234cff7521d68a3b4aea721a6075ca3c527998218e04414ca1338d810498836054d712d542ca80e803887828de80da8871fa41ce4e88da259229a68a5916986b242d7f0d8a22822b3d744b42a8c19b68c1528f1054517b9552b42f5fd4fc0bee98144a7c2af66cde7979acd6339285cddcfa44ec52de3d60a39bedc2f983b0466f6f7df732b38943c9ac966a1e3f5eb332eca2a3a3e1725158826fb5f2bb1f10c7beec06b02aa2aa41eede949828535ab8feafed71b48342e9b8765564b41b96b7f2682df90cbe60fb7e572361102834892fb6ffd1d32308137c8361ae67a37d562c193942e1bc66dc6496940a62739c76138656a13344aab3ebc3b7725868f0bd2fa4f86d3bfb6cc08d47ed39f6af9b804454f79f72fb1960eceeb032767113b77ccc4400a2bd1acbfbedb7c9eced1c564a5ccc5ea24f649690f0656cb0a63a8f81ca2618335acd7cd8fa20ea11b49dcc5350fab6e201ffda2343e11e82a4bc085aa30f4df112b962963fef6cde1bf71c7cebd6d487c84f23d15854db0017ac4e4eedc43c50d8313e5b150021fd10df19d14c2bd1199a0486f7c8057499139438dd905d40cd73d85787c591db77159c45dac3175e21de763183de2016ac0aab4498596b0b06131f81b47a3613f0cd9488731df9f8c313a6a5e37fd76bc7d13e0bd0ac93df335432be0bc6e70e19781a082ff5be3c22a5a6625594cbcb9ac65fda84afbec1d8fde25968446b6ecf6b86010cda390d2919c053edf82e594477bbe79547911082e6b6f85821fd1421ad0986dc7738d8656fc0376860d1a9c42b4ddf7d232f2dbe96dbf515ba971f7d41a538fba46e24dda489e0fcea5338f73d61bb07ca8bbadae77ed2687e672852c6245f6ed771fe78dd8382eee84fa9717fb6444bd6a7852658e62a84d327976173c0c9f8782da56121ace03b6e3f5039bb0b56cb1759af688ac0c8aff1982abfe31ac403c1fefa0789c2991fd81d3de958936f2885652063c282791a1dd7cdc367a611de5dab895ed17736510c2d9da22b6d408bf1b57f12ee33c35da73ed341b3562aa9635a699438558e33d24aa3ae2138ad05252c5a434250f1f3a25f2bb93804e621202b0f443d38ba7edcd4ee523aad4300768bc44e81299802f0b9bf6eaad0d50a84900352e604b4f131178663ea7dc06873b9159d8708277c4b71feb9e9b7c4af1886a8beaf42191c799b2df4c155a16f259220369e56c79423816887c5b3cd070ccb4eef9e4f5a67a04c833436012195c830665f14cc626c3eaa5c6b9229e34e04cea8613c9dc8f075a97fa70d5c8f02f3bc333edca3fc10c7c5c6ea57c0961cce55868010c7ec03cdff29950af9243c47b6cc34a3a0ff2d295f4dd251d101f6dcb7497860e4404767e62e97cbb2426449ace2f0b2d33bd4a7fb7c0aaa615c7bb8561baed4ce10f8c382951db1ea75066c23a2c32b2e23c1b8cba0773eb029e0164f04dc306dfd605514879db322bbd1701156dfae9b10936ed01b59f236485fd932c4772db79de0e8ad10923bae9b704fcba9555d30a7812151a61adc8a9114cd26df665db09adcd4f7dc73edae10ff70015f6e27685fe60b6f13b5b2a6963757b83530140791c93b81b41f593633d2d608af5dc449f27692d3276192a9c652b252116b4fded9a2f4b79739aa96176a0069f22195066560a8d6d4cd55a93012373c8f7855c94f1acc057b952e03906960a876a3025b0154ae460de9c1bcd6c4e096cf86f6e32b0aaa146113fe10680bd7c070e2fa5031294a6b82a93c4db2fb53b7cd58bdb1b5d547115bc827d0647155ebd4ed4d1aa6916cb0121241f5b65122e36cd260b97f947a4a9a615bac3fc11ab88e122cebda67715d69cf3f8ba81b7ff3a800c96392692d310f91a322f908fa17f499e21ed23012ac0684c1b487b595a5d9e230daa49255cbdcc1da23e4cdd1e6df4bb57db00e99a24e28024a0c56c252d221010f2572d01ed9024b706c20544a9f58a0176a10a92a2fe179d3b5a6a0bb3f7e587ee420ec7c7c47b4df448aac1ec50ed7d54ecf341f1d52a4611312130a5da7d8c73ee028f2b0c9ffc2671877f7bd053f84201648c33b8ec85044fdcbeec08b47528072547065297a10c854176c4be04c70c6015ce82d55c9f66e880cdac5f50a4c2fcfb5666bf020c0c6ae59232c2562c05427465af3dc0927c05e0f107b9568a73db521accb012ae8e6d75be02763b361f42c5187eba614a70e364d8977267efd50a48642249021fe208b4df35dcf3a93a4550df09001a801f3f1dea62ce78083b9fc9f185f10ba6cfbdf2c9f9505680413eb5ef4ce63314b9c7a9735004a842603575920bf681303f2cc17b717cd766f7bd90726fda5d8752b50760f26b5b7530bdda43372f0d88eda9009af635800dddcf22b1578dc92b61ba8f80dac1b6edc337d125c0b813617dd856f30f31cd0840f299c490248bc0cf6b5bc0382d5881dec6928a41014b2d133b06c6638cc9a2d6eda4204ada02b63e0e5daddb70fe6ab4e5ac7d4a5cdb88e0b6f526e2c605aa7a09a784a992a90465c8fc8f2895b2b6e75840e2a1f1e19241cf4933442abc96f1ae6549c8a920d25682ced4a2f5f3f52f8614562a0485881203ea0fa428037dfcec2cc9ca5b861adf7853d8daa279d2329547f9d60c66bcd02aff3fa559705c6ee1daefa3582e5a0120151d3f75e4c0b4c5b9835c8a8031abc1a6de4e7975dc4c5903bc27297e739a64b25d4b5fe2eb126d18421dd8c4e301d18349f4ef6b8ff59806985079219176f185713c146ee0323af22ec506a0ac23880ea55c5519b495701e6481ae8c0ecd9ae7ad1a9b219cc61594556a406939a26e4a0cbce6df87d51b7d7df434d9cd6d023785705c7059c9cf84df60686a3e2b57f542b53c8349e382350b31f209b16cac9db278b1222d4b45b9f2ed9444483c90c461561783d9e480f95bf14b243e858572d02c13e9b8124832628a4e74350de0e1d88ea1da1e159358119e21aabab0ada80eecd4e6d850353267ab736caa8243551a580e5536550494a588c2d9e5e22215c148cab5f77bcef7f07ca23c3306d353c6784f094a6e28be1d4a495181d766347348c5052b92dc54c824095e1d89372c27ba1b185acc4d13973a9b0b37c81070ff7132598f40dadf6a80b679de6221a6f34a891bf395220c7d6b19e83a8927bc6f7cc51a28f02676b7b774d645384c4cf1d805000d9907cb1ceb02e843433707a86698f1d0430f8a1089ca82693b9b130d134f0cd778fb8b614ec634d281a66ad44b26e6d7b0f4af362828daa2daa43183a92070b49f18c48be047e53268ec851c7819904f30f2941340e59e67bf191a53c25cbdcdca56867d3c8d3acdebebd2940dcd6588b7273689019c696065c43567d90fc4fcb4c7172a8c50989074238e2ca7a6eb41610e29f0e0e49101cf39798dd89050315760b5e9b3872c1f48162f5bcf224f26eb978a5d23f9c07bc5a331308d1312b7fbc2434ac27cb3da76d1a3121626e7cd5a89fd4aaf6028cecb1aac29ea88c1e6fb00e1166551e3e537e160da039dea8d59bd4ec5847f5898176d28189811d289ae154fd655f1e1a2d3199bf9f2338cdafa8b9117abe48a3b7aa2fb9c2b4411ef334e2904085d30c67cb3d4a91b226d27566fb70761eeb67bcb3e9093a787ec9340d1ff88d0b48d1e8fa773923e623c2329ff4353d342d806a6779c722d933309b7af8f39f12c20ef0ca5c99edc7828777d031d511284eb63db00878a5b44f830a9fdbf377daa85fb369bed4e04de7455755d16a9eab2ab09e9ec8a85e6c214ea72359581b459103c16b77106e29febcf36317ea55ddc419572e62c4eddae1d537764adf8ecddbae0d72748614496e599f5022a71c12185014a461ca2ef0bf1613d4c8a484f9021e5d65a4bb1d2ad925c8e2b79adae5d30b6d810b51030d4dbaf1879e2bfe0e994ee2a4634eb7ba7cf8a917960863b9546ca2d292e8e3dc55afad1d1a8d6e9c644dd2149ba4f5f4ce772b28be474b23cd679312f99075f1175b4449bfed0fcd316bdd2a46ae7175357c422ecdfbbf28eb3fc24355e8251df72c725ae1574a3005c558dcb8d4aef1c84e9bcca9a2459122644e5951254adc68c63401563546ccf0d57e1b7bd17ade4f0a762b1484340055d48a2897b0d7241206d4e36aab645bbefdaa2c749b1076ba8b999a5600b86dad35ca209f33c5fa056058c40b1e3e2ef92a3a5b3286e845161452f45e9958a1282c4b86504fdaa08e5afa2b9126b9ae228995cc9b34f1f5ac5242e6a93f708931627531b3f3b99f63aec31a297d633660cbaaaa9d8c52746b25cb5a59009a96dd05d57811094d010fa78d72bc756735d189de8949bb7aa92902cd10427c03694838048aa6d95194a6488d85c05c0ffa01d0cf415956a6b91d6be4f341a4b81cf4dc31408c96f39e8bc3030f366096b61c0c092a4cc64026793c10a8ad33de854a2e08e0c49ec6d406a8441b69016d257a55dab12c951447e97db10dccdaf15c2ecc5e4b3a3ff058209822de356c91e287ea140fdca172419cbfe1a62bdb7d76c71ed00f6c5d46ef6e9775452752e847c1e74c697803d1c657cbb5a3ef9d61ce357707b91a4367eeca369dad96cba23370c4020a47c1b31837d117080aa1a7f7982d1e4ded0d2fac318dd9964b663c045bba76bfcd3d3a30436e1860193330a3689711ad8b118fd6b05d19162ce233fb307b5f0eb532ac480963e7046e2fdbeb721b0f59b3dfefb6ab4976bc06aa842f05762cd0994aac83438c98b2705ba4a437184a05935c0abb7a87de8dda06afcc7777fbc8f149c2f8a22f0e304a3bd73152c68f57de1af080757be4ec8a537d259879fb62d5145e65baafb0f1456c4880f5ac2812ed04164e09ead69b21f417e2be057ae91f1a1209ccfec2d0605a61db35131c580d9f8aa67f20b63b8531730d649934d65071bc58a1f682f1181c133c18cdffe758a17121e04da159f00603082a54249302930b8398cc693f06a067ef58adaba4334601d0d604e072586fc3313217bcb1bd32cf67fa07f622a135c5b1dc3b77506d10730001c2a7050bb28c38534173ccd310fbff1ecb963937fcca6ec5108cdc0e041ce76b4c0637d363eea7bd51ccf2449359598962bec8a422366aadeca0d9d0c15de42baff5e218de2de89a3ae3ab492f06a00b2b2b5e79fbe0c97ecf1d9ed7d05bd47669c82ccf8640327a82da323f596b48c7a02936c149a6b28140f95fa872d2bb7b847ba3c6eaea96ecc1f1b3afeefed9b67bd03379eaeef62338e032d55b00001b79b276fef90a5422bfe74d41915618d29a9f2e7ebc38c6aa79852a4d1e9e22b5ac1dbeb536b84cd0a7af9174714120bb7dcb4c51fe8b9893e3f50438eaf72043ec4da1e9fea120c15e5674206aad0d0668fe6dd5ff05473f06f4d1b36163bc2b56eed10429179903a7bdb81a5a7a3b5e80d6ed31a8fbce6b1bf778e2a0f9b98536a20990f4bbe9a4cb266de4c668a0f15e375431511f0b017cc151e440b039a77ae09c9c9c07741c78821b14404c06f12ec1016322b4b9b2b89f74297a614954608a3812032f95f179bf7ab0a08bbe1f4a23d885b6e7ca6471a8bd5bd381107a16650b4292c0c5d3a75f8db5f16da411843c2297f5b4318d0479baecf2d46fe9eeb6bfe7a35fd078fcc8c4550fe2e0e6487e9d5337bc5b8ed98c6b70ae596ea7d825e3fc3255bcbf26f7eeab742a66586b9c98c631d1be17e7599ba3d4557be9d1f1082f543632320c25ce93f4d6f0cf45da113488f1695416d9da844a64183bbc92827d88f45e5fb3d8f2b0070114be92278fb1464d6dc6e4112c0aca78c1e644115390415e717ef5826b5b6bed04e031753b98341d31d90113d2c8845309192208d34f61d98d883cd0be120f9e1617a611bf59b7440e0fdd628649469486c6d6dd92ea4f359e058413abe22ddb786632bb0ce6c64b2d8cb6dabf41c90831f820e90d173a000e6613b29b87573be08c1b7106b1e606558a308f3058c26d4604841f424c19b12f28031fe9b9572578e9951f5824ca5f209b13ccc425b537949e288cc556e7e0867009bca2d4fe41099d9b84f2f0fb72acbf934ba43965e48d11a6be396b313cd623802cb3c063062902e78188a88f1a826cf88458ebf2366f14fce55e29f6c65c33957e4b0b1d61df7af63f961ddcb6f3c03b06c428e2cb3bd3d0c07bd9314428edf3b9b00c91a64907dea7fd55028597ad1fc29d689a8f850d77e1471f0467e40bbdde529e9658f799147da6e7cb1d9e2e64263c57f4c1388d05068cea2a02316e776ecbbb02ece56f8b4539a45a0258bc9150e80d7e278b3bcb997ca2d8eff8f3852e2ab35462fe893ca4485dcb6e009d7edeca2ed0dd4655ebf496311f14be011988404e220f584b8cf88a493ea0e86a88c9b4dc636d67ef0f0df6e018d33fea8138c330f2ecf5a76a1a8daad65f654a04d62763071ad23766dac24ce70c46cb5d37f40a773045653b073b191b746f039555b2a91482a7d4bf44074cd051533a84a350921908fd61668f14e54d51838e6f8feee8ca560646c47e5c44fb408d0489aafaafbc06826ff1d37bc2f0d1a15f0cdbf2636b946c43f5d1a7826e756e46dd608f4b8714c223a94d0f305de34809bd3df540bf4eedc08720b97565ab2f4d41ca60cb19a1b21049db4578659f782802e0296995e609cf7fa347bf4118e368e9d85d9eb78acc5ec018b8057b1bc458544f5ecfb1adcd2432bcff35fad4e281cd6b4e5136b8a2178f88ee3a08389e3e07e7eda314dfcd1c1ec0016d332ecdf32eee6bce52efbe5078988441e40c0e148d00071e9f1fcb1f69ec1f185ec88e9158c38e49d67824b73834f820de70522901a2da668b9a51b3797a5c6a957eb78eccead487513f0581061923c2344af9eb78cd0930b898dcb6dfc2e6c22b19852f91678ee43bacda41daa0f72843bc3dfd448ae60185320055ab45511fb200373608ad970579689b34dc521f87ef664abe0242d8a9928c7a1dded451d110819ffb3d0a562bb14fbcfbf81f3df763a27caa87cbc4ab2aa007def6c023983219ef5169fdbd3fab9bcffdf0379b9ee4bb3029a9195454a18095d6049a071cea4fad3436209d59f524bc1cba881673535f00e55034fbf1a98eb27bd9916d0d5ff3d072993437de463c94a05b9f8d791a2df807210fd9e8f0c62a2a9528d4b6196c59052dd53cd89685a601caa5c5718e27741a0b63e2185ae93fb978ecfac0d70b5b27831c66269011f9d0889000810d5fffc30f90c219d0aee31e50c1d71706f7c801f7a1640903762299b6750cc00f44f53dcce7b55bcfae793ad18e758cb2c851a57b6b4d47bb433b935658de90d8ec4a5b4c88a4c9064e825356e64d82281d08045f6982448ba94d9c5be9d48a1a264642e0390da4c220605737f3ea9c71923a5c5eef13ef71baea0d742748267d40e95adc8f1ca65485713e59b2f12597a26e45591636ec7a32099f7c3687cd2844d5ede44f4e0a9809e16c6bc9c74f6fdb960655916491a900e7feb87716b4aa5c7a86723bc3f4f35a9fe8624cd9514b9ec3b63abb354e4068b368383c1febe80ea1c50d069aaabd3b7b935ef569542e14054db77baf3eff82da02af6041167fe3029b6f8a8ff22846d2b472a9c545e317304d65c2632ac66345b3dbfeff0a86ef8049ab4caced584a6010747904a6c09ce37cbef590187f5d941c9e0673ce4251fd58556109dc386cd528ceead6276acf025c148acfd69807cd991cd07f2b9b3dc28b6e6194a7b0bf00b2756d5445f8a9324fe31394334a2c8dbee834a7faca54c5c68e9df4668a97b326f4309ff79e9a646cf6405983cda08108d00c10056084ce11602bd4e45c7511a43a0a363b2af34f44e6b3199028a62bb1f061da705ce4c8ace6e302f2b58f02c7a1e5888b91dd4668af5a1bac79030980b3fd38f933ffbea14a5f48dfd48a28745a763295a0c8eb67dce8acd28791576522609ed80c1073340d4db19c862e0ea2433c484188dede6242cab41ac63d596d25150c9383c0198cf16e8050f7a6bfe4353bb8c6c1d48464cbfa3963aa9ec46686024ae661c03855bda041e14d1aeefa624da4c917d650a64a9c094a3ac18038efc2acb71a0c6f3ebddcaf66b16a64ab121e322e412185de21ec3b2bc94b73167d6912f02fbc5ccd1d6c0692a9ed119b1cb1640887d0e16c85a18daa7cf7ba197fd201ce738aea4ea07bce80d44542092d154c6e6b2a1b972fc81950a62653e4f978b03f48a41814e59955f13c05e523fc50a0a9f9aec5120f99d88f7e1152e9dfda32c0663d5db7602c0035e7500554904d76885c18d35094dd2e56d7fc8d218e8b4a533e87e6a0e5c3c0ccf7044862e263ef03fca0180da65a531052e0e6687c61b050f3c7ac60c3e423e48a836cdbcbf33122421f9ec3522801ee33c3db8ed81632c1589497ae2cc8826346489d0b616a67197cb8bc8e72911b815643939d983aab88263ea71add156f58a1bdc7b2cdae7583535f22fe9c1a32aefdf5c6bd4d13c66843d5e2657b54ab22ae83684f49ddccdb73730b194de1a792018d1110ea1463d6ff31e15f4be92f5dec9887e27df76964e26f4212b476409644ee42ee7b5ca1c816e64d2042963afe941d37d01f38ad32d793b40da07c2194d64f722e10232695cac3618c0ab93499aa70b9b806f89d7cf694a1b0e240c962804c7d2a43ada48c0fc32303a3d5027d465178fd883896f60721ea2aa53b85550ceec32596557ca5586098a68e6cceca82d2cc0025d5d3ae556dcf78bc7771898ff37484eace81fecade578bd3f97479ce9e247d855bd21cada939705258babaca90ec1ab6db44c818352826ba70a1d2a0a791456aa552cd0e0636c35e38251b8cdf27d1b2951b6aa14a500c5ab2def521283bdfa184a25024b2379248ee087ad96617da9cbcecccf46956670981589bfbe912e6d412625f30e51247410a25f50370a6e83a0859a21fbd555b2aed5fce5cb76dcbdafa7272152be07c927a6c20dfab9cad2e3b69cd4856285d2269ca4c58ae719801cda64a6ecf55c9d430de08f2481d72b079294cbc9f360c912be3cbcb41c2d1e18c857c3da10ecc5bc897575e421bfbdf1b26eb68e06f0696f1cc980446a4b48f2f9769e3223619822431abe91d69fa5d9dd4453598c64aaf9f7a1ab89f0dc3fc8dd915f25968dc7a1d9943ae81a48044ac91d65118b25d040e32d8ee3f36ba1a4ccb483a3d2e94d49451deed197e895dfeb57c6806ba309225601b2eb7cb7186ab9536bfe1c6fa21c4824fcf21165a90779681cb9fb9c35a33cc868c4c4dbd138017d2f01a75182440cd96d23b138b2df98358b2da14dda1166c16f6fb5256d6d67f58eb27cbae19782236fdabd2e17a05da4152b66f873345537c9a0853c0a3295c49e7bbb9ef482845a0e540e65322f01e22179823125ec9653d02c0566009466f8721137910ec8a30b65f1276eb88d724a14f7d9f2fdeede0e6ddf5bfc5f105046ba8129139ab6dc6d39f15bb7aecf5dca63e2451d2a9e43a804921f984d95057a98c0428888dce06b97db6a30db2ef2ab2378a46b92c33e0f383840318298182ad131ee607a375254451efcaaf6e62d78753ed608b17f0196ad6cc77c2b0277f6bec4736a61589be6bdd0ecddb30bb5e3a3343c0a51c27035bb4c7c76443960dad1e2bfbaa7b1a3b12455e2afebed921ae7eb98e84f8975a82eb9c71cda61b268757f1d0a97e98e4af67554ab7e1fb7c6e0485e965c0d2cb8557675a71b4dc8ec496486e223ee20404a0918a84f84f02af5e0aa9bc8e5d6b2826432361a455d3295dc94faaa01b224e5321d56db3dcb0a69934911a693426daf0aa0e110224592c6303d6c6ca6105d84a81bae16dad5e9f3f6efdf10501686f5dabea414ab2e6329901971374f785a370a85086433d0658d3a9be1b98ed7027b9354bf59a2fe4f0746023b4d8a5d8604a6c4576f64cc504519b59d8671ac9b0303e19b7f01fb955946b2a4f36ed0e19e6dcb07310a0e0127a93f3fa56f1967239efa2ebb5b29bb97fc38e29827f3ba9a2b43834868377f84a06261271349b441d8b226ac06fc5a34b809f66ee87a61c80a9a2030d2bfd21a8604b3b38e518cd1503b2e67b5581840be9f4d732a907291a069133d436e3e7d318444a4a858dc3306e5ef6737ec00eddf75e2b9ab4bc4b0409011f04a9bcbd78d81ee8a38bbc6447fe6be96cf8b83519e550f7309f0b11351fde20d89835a6e0ee4a8cf335cb9006a7a3409a2e419e66da1ba3b1fd2114429926682eef8f93bd9fc261b57f9f10311b067c6c227d7e4c34e96d57de0693dca3e3b9e9b5d8dc91c9f65c628794f32dd8a525f624fc87672d3690f76b5b67b601bc47e37e1bdb609e7c6f292383c613d0aa06160e4aab9415e01f00500680660cf0370e4e30e8222393938d37733f78a3af139eac64131bd14227218f6c0602018ef0946ca43d8cd940cd0040f53c7c3c1f585b15929ec7437c6d3540bb3abd98fc081d15fb1f3c953fa3f4da0cc422f8bc6a670c28f7da3a89241e9eab9fc6121f674e9a5509c7557239a556d77d1282580b8941fe13d5ee4dc031e19fca686d6b70a372303c6f52be0f34ad422b3baf680c499ab541a0be6efb9e58a3aa32a7411e23a1704ed660603baffdf23911658f3540efc86ef5626c2d96824acb403822da22b98ca25ecc945f338820c4c7a1d7782aeadb0542a6241c65ae4973905b9fa314cdd0e8b61ca9465d7c850c97bdd8b0d6f0b95bb125ccb6a9b18494ed928e394472f122f6840c68d999f5a3f9a91afdeac3912a5a9d0340f9d7b71e32b84fabe9ff061ba48c37b3eed9da06942636a93879dc4707b7a11cc2b01393565498db5b76c4be95dc766074112e321825b8887729d6c5079fd44cb98d641f559fc690659a106a04d6ae2330914023f7b1a964d85254597d94ef3dd8ed34a9a6e0e8c16667845eb676ea1ea1a48348d0c04dac6905048d9e78ff2c6d268a02751fcec5c044d193078d9ad8fa92008d59e94375a0096f7eac56768fac893d33f2e67e229addf7cd623f585f4dfce1fe3453e3c82e338c9519d09fafa7b0b5f6bd2b3a812f1796ae64c1fe3217668fed517806feb024fc236eff7be4e1fb5989709d48692ec9f4b87208dc281e42a259814cf4ac165ebbb0e5fc2502bfb2e7c5b1d1fc1d322f177cc7e35c03c64abe17c3fefe001cdb2d3ce6d3663816c1989e261fd80d7ec228a4f5d58e8500207804432af6ea5cef9b51865ec10a6a1c9450ed3c0695ce3b898f4dda269b045a648f70da7b5d131bea52ba56e9fdbcc1ca08aa597bb8be007a829dca37534e2ea8a6f05ffccc4aa5f085339cce19ca84c83044c31cf9b4f937c0affbbc43435fdf249255a0521f825b6e254518651853bdf7e533a2853fb8aac56446d2020ae53d74a0397e353e385b20b4b5b88f80f7559c978a9fdcd2fcffb20ed9ba2262a165598406448b4c3c9cae9b9dfa998ae39effd010c8a9b938e93d02ea060c9148def39178d6f4b5bb57c8a49d578199d7252d12b49f810b4cded8446d3a7e04feece6df158b85e235bd6701de546eecb0f977cc3235422aa323580772b726fd152e9821689acebe36d674f5eb9b3e3d4e55946b88a656bda7c3e9b00a1ff5136d2b7c58ce718e37774f6676b2aeadbe7435adfddb6ab245e2a354b72202df042f42dbc6062d4b485c8ffe442705bcba0fc4f356dcd9262bec35521e3f8a786c02a2d4b4d2ed080a6d544dc9c11a5ed624d0c5ad429cf7663b208103648be80a8d6cc57d6ac49a47da571e9659db3663251f553502edd8d3febbbc16ca136e9b522236af76480c69e825e0e478a508f8a4678f4a714c3db5ef659f5527dde35264d4672e1bd4980e83e00ba90fc4431029981a900f26fec3a858fa51c3c0845b41c75e898a7d93b807d32b33cd6c43afe8896aed9fcba580f369001c5fd18edb6996c24fc046fcaba41fee550ebe138b9714dfca582df4429a16f1823b610472aa0e3b9f1a6e267eaff4829415bc64a44a8851f4f94229370d91541e2459181438d282cae8bc05c673391da5f65383129373c3e0a740909e01ce06deb1ef60575ca5c56b1e65eb87d2224fbbc2bbb0fcef23db256e41349cbb76cec109319f3730f84979f0cf56640ede63318189f7bee37f86f5c8117d2c6770c2fe3e307a4e297028e61537b9c461a1e69d988999d4609d3d2c112969c4a080b51821f70693c4c2dae1efbba4ca75c2f262a2388a539d935f428c140271fcce8b91e3b65fdb95223a88fbc19f0d8ba132036355b84e8606151e6d6db8283cf660638d27c717c47d91a6e89853d7a64c034b4d9b7a105fa1d2b76dfb5f105b5d5d187f1c0108f535311b63234fc1773441fd2302de80e3d26897f32bfcdf475ef3721d9cb84bdaf69e3036c454f69a5039b5f60dff1509801eee1d79e7e65e902b51d4af929b1a8226a65268b2bed89d3f15d67b8077534c8bae525eef1b0603e7826c4d410d36e2dd1786535a011e39646301d225badc608b664849e4a0b90529d8b3e7d0649a2041a04404ba05eda44c4d65c5794e9a325ce1abe4976e252943b07222cabeed2e89b0d1d7ec61eb81d6742d8f27243d94ac68194678fbbf19596378f1bb20ad709615310c5f832920f18c5baed66005370eb9db5e78ef1a05ae0d63867b41e32785ed06eb70968c71edb502d67382fba37d0c94c65eae00defa5e058c18ffc09723ff8a0d820ed748633ba775cfacb2767343feb2667ab10af87352fc7adcf9cdfd8324b0bac725f378d09a76cad319bc796a7efd6b9d7609f95170c6c872934456f5b9754c5775d9996dd8d29d60705e33c089dd4e23d884ae4691ffc60fe02d10c1b064726434982ca0543926b53fbfe9aec864cb7e20c8b684dd01d01a44a03ca73fe805d30d2a14907796c6ca63bbc8cd8787e73623b39bb8a55e76cd01aec6d8a0df55b5e6defe2463fa2bd11730f1960047e37cf0004c00554310c5064f9f892bac47d9b50083e8c139a712c946b9c824e7e23846c49c8de7b6fb9a594494a19f1079a07bb07474fdcdd1d0c9a46bc1553352a8063c79c73ce59a9271d211db9bb1760ce2f0004340d3aceaf41795cc74ad814a0da00b286ab48a6652525d804a652a593f22065fa3c41327d9e1f3fe5943e27206752e693ce294b51e080a34d1e16326d36497d7f7fda70d97d8c73be9efde9512c3176dfa146257b24a9dab787533008d458fc6e8b7dbb7db7bf0f765d28312d53ed2b51284979ca72b77d7f729954743681aecbfb3909ca639348993d89c562518c75cc84d5e337c0eaf1e7a03d51c885da7f4c1172979dbf13693776fe1ff79e257e5fc595684529bee8a8331defc39c64daecb1efcf1e469ab4c44ff44429c5b9ff1e214da5fbb9a4492e367cd67377a8765c765d35c8dbcb9820d3de868ef7612e1b64f963aefa282885480c37c03e25701013e4895801629c1045051ca0aca006578228e1a143e988172931c032a44b1021ab2033f4e0a40d6c1912e5064868e02109246c82f0c85b3e2582c88087205dae131ac82e5b72a85ac205253d4e20ad1ce1430d3cbcd8b0c49624b8c9a64e58888f2b04bc547aa660ee450f0c9b233eb82adc75d9c2ec8089212fc05eb26f09c5440cfba3504cfcd871f382faedbce88131a39860c18b11e785f95eecf4c0f85e9f0e9070ca39e7dc0383f274424334e610322f47fa3b7404a7ce3153f8b265532a8a31fd31e71212c6249760d397935222314f9b605c4fa33ac2a751116c4a7df81129a31fa369f8a569d8a569b9a56939d434983ef2c595a48cfe126ecad48f1c813dad554a597d31235629b32f234a29936f2b90292823ef5add1f8f9b25ae3c2b47cb7160fbf701ebd9043817249074ec4e4f39f7e57cf4d9c4788e7b36f986b3ed0336d6538ef6a5fd80f51705b578b0a63c6b86b9ad13cc0eb6b06acb11dc5497904a10255ccf14fc13e3841a7042fc00999ed038890109292160f06283130f07555b74106181123e9c785244c0319c608b110f4a5f9408220739708152132f0801922088201d711e904ac0c2416ee0c2911ed4a6a850e5052924c10088244b4ac4900548121b10265454171420c609b01f97c0a6701121f0a065881f3f8069824101498e68a28b951198e0079620b88a820b84e181071e4e6a27c8c107238c40c245cad4122f39d8283318e9f3b17201d0602acb0d9270c10da8108009090ba4e880840492231d0d2006d23305ff1420c609ac2da174d003f703f93418423ebf6ffbf92fd8d6021e98051d40a91f4c074e28b725940e9636edc6aad0b402257def3b4fe697ddb37ec6f759b37411d310f8df17adbe7b099403082432423222a96a3d8e9294786878cca9f5de7b318e8d1b385c56e5538caf4fa38e366ee018777cd67dfd9e3a7add7fbfca9d88aba55689cf7e67b9b7cf81df6922efc127fa62f7fd0e71dffdfd4e13315d3dd4bd6b22fadd13b97dcf1377361299fbeebdffdef3c41c409f9803c83332dab3de5a8dfa12a872eaf3c4d8fd7759bd3a0343de7f19a8ab4f1311e51c40f469bff2aff7ce1a0fce27fec4705915725935a25fbddab8c17d27b463e5ef89f43b31c3a6d4ad12e2df7ec67dab8becdfdfee176d967e900484b6b7d6be7dacf15b31e662ccf1cfb08f39bce99dab7f28b54f0160ddff0325cf7c5781377176f6597eeec39fe17d7eeec3e762f5b9ab87f07b9a88fba1ef39d67f5ff550077e27bd9dd773baae9ed33b2e931e8c734d348f7c66c8fef4bd773dd3508bc9563dc4bd4b135909c47d7deead048a558efba297b62d4dc4445bb2fad5b7dea577ec6aafc41a085c5ff4e3d24cf55bbf7ada8e11ad9516b2402bcfcbcf7d9137a328ebcc7a3dc41181fa2736893e3df510d7e9d735720061f186cb2c4e90bcca41e9a6c45fc83939936a528d37377494374eb178f2e6a7cdfd1c40d67efd21fbf5af26aaf3c7730ee5f1df3beeee4495bced7136f6591113fe22faae97f35b2fdffb2a7db6d29b1e7abd83de0c73c270f5397426ad54bdf83981c6125472f6bd2f8ddc7b3f5c6d36f7fffe8dd2be7713a2814126e037d19b54d9bbdfd6390872dcfff80465fc97fffb1abe01ec879f63af445addab07455adee0cebf89a128a904b71f9ac51c7b1351a09ba5670da608df93fd3d28d26eecef7ffc13b9f7c44e4b7d4347faae1fa2efd2580fcd6fdddc8fde1fbc980c1ddbf4e938c28f9f740ec1b0cff3dfa9fd03ccd8b6d9122c2187fdfa06b03af61ae1470d7f1bfe4234fc7ecc044c81edb18ec16c360090a46ad810a2116bca28b67caf21b125d4125cf6dc34288f0c48dbbf004b48d9fe423db6bb749a73c230c104147b88f2b88e9940816ddf00f5adceb1251854a5acda7eb0a476854179e68ed51f336c45983cb6d8f561d2c7dbf56dfea6ce03f85b19fef67328cf68b36553ae49807f0e1d47d0047ffb06f0b73a9663ffc85febe7fab0ca92f2c18b35e5903a91276f62d3a757f43d278166e75337fc71f8d7f0b7119bef719eee34909c52d29a269f53d2398bbae7de01de63a621eff17f6211f53af9f3cba80343a635a4ce74ff26539c4d35772852c7959852a24ace60ee79d318701a9612cf39ebcf598f3aa3aefb191cf79d2e6292b1263906a54938e85fb9227da49d57e4e5c418f952fd24e79c73d6153c79930388137300c59ae418be7d0ce3184210b081c2c59b14e5994fd3cad3fd182eabe1b2fb3494e49d012c8921e433fbf7696ca9a0d00ea11df4a7fdfa463de8782f0ea5797f569133efef9544ecfb31ee3760dbb66d566d4c9ebca1f9d1dede93a1d9f2ab8325cc3d44c7f9fd0a20f761fd0a9640f72cf242d0903a730e2175e6f6585306b7b4bf7a07d85f79598c09d930fc986b8975acda9f9175ccad8ed519adcf3a07b34f4ea449027e2969c0d744c2400974d77b45b9b92a69545cb1a6c06baa15a56a7be6dea9e7df38fdc66e75eba9411b7e6efbb97d2bc2e47147fab0b6ff0bb7e04847d745444c45dbd3c69810feaa67fcd0aa3d16151ddd63254179ac7dbfd7be674509b2a82c8b95041d9dd565fbd3152adea1e3887d0018688eac2d05d23bfab41d310710b54ed6ceff893154a302b5ce4be544a954eaf439cc510e73ee948a26713f2a5225972d51284dd4e927861095eadeb3a0d00efcdc7b9ed889b126f947ead4cfc0acedb037be5c3d93a44ea54ed489b2a0d22abb4eeab4ab10bbfe8f02aabc57ee1b8a3f95568aa7287d92fdeb7f18851a95657dfcd51c3c79233f943349c3a7e24d19720aa86cf9513a50d952d33ee0e37a159dd7a8173a3ae569b1fd3d49faacb6d3f7977ee452aecf11f3fe9ee44a32dee4ee44f343f969fe3e4df8e113d5d03ceb67c8bcf734cff2275a4547aff9d8d35a56709a5a565a507236659032ff96152732d8de02627b8d8ee9d8acf9a1ef6b50fcf7530f8135138c2960e6697e68e669e6cc5f3d047b194d44f343aea7c9ef0a61dffdd0eabbd54fed4a2ef37ffdf49921c7bcccd3bccd330dc5be733d24f5c774f79d8ecdefdebb9f41f39deebe088526621ab2f99af79a9a9a8fbd8ddef19897f91ab106029b2fea6c3453ec6b9eb663444cd7682197f96f246834cdd7fc0c9aafd1aca799d1794fc3e9a18ea8d3314cf343ddd3b81eeba1ee699e461375ba3535234a97e104c9f43771d6fc47f891fd5dc997fcc8938c4ca397e82e0f45ffec4bdb5dc99ffca9e830481dff9695fa2d2b74a6d3d4ca32d54aa2f5c55db5ed2d2bdb5b5db6b7aa5a5e5a615c3bb6ffacd461a055d4cb0c36edabb5568741faf891eb06cf3e11736a8aa07b230c642461784fe5637b1018b42964fbd114fdc85d893ecd8fb6bfeb68a379064fded0ead4a6f948ac317d8fcba8cb153e91f6a8261a3511511e33cca3f588b1f9dc8cd573daa58bba5a8dce6a8c90949a504fb2e44d5096241035b2e99c45dcafba075d1fbe03b85fcd2f4c439ca6ab07c52297962e0bdf863f047ee8499b3eb8d2447ee432d7e7ef9e69c80b67a83b4d1443dbd0397b1f7e1111d3f79f2ef2bc9a7341024983e0fba2904aaa4d69d3e8d34c3119fedbc7be4ba259c7e6e7cfba88a9e8cb61f719b33ee7ec7dd64baffc2fcd6d1fb7c20992a1d01fe147764fa2ef353772895e73a426ea44a5445af5894b474b2e19b25ec2d1e904cbf3cb486915751a22d7a98dae9278f286866b5c90b997358ce73c3c326d9bda3be82c87ca6a393c21c8952a25d1d17bb63b9efa82c324d3a8528ff7542b349c653b978dbb6c7fdab8bd26b17d3bdafef54bd5ae606cfd52b535a2e317a9e3f868cb155e3c79c3c323d797952704d99fa7853ca76eea44d2b4ed7b9ea71428b9ca67b2c5b63fbfccd5db9f50c25ffdfcfc96ea90330964e7b3de67b11b7ed6e3b334d1eab37ed6d350d39acbaccf0cae0fff0bf3d067ffd3a1265a816068c11b8a39bb3c5ab383f2c8236ac45a6ab42d45da96266d4b95b6b5dbb53fb3d45853ee36adce952816b9be157e7e07ac9ef53fd425320dad74fe965814eafc141c5addcad244b426abaa56aecf9a88e9e66b3fb7b4cd4f934ef7e6fcaf7fe9a256eb5b1a04af2f9a3597bee1324b9353df7a5d0effbdef6ae98d44a8635dacd3454c45d2c31939873fb14e872151a787f2eba9e4323b8fb67d0a0aed583deb718264b7cf59fb23fcc8b4669f1ad99f55f6e717fb2e4e9628c59528fd864d1bcd603ccf16b14d6c13fb84675a2376ca36b154ac94cd62b9d82e3609e5a1d922d68811775b44fa7894c2b8d3be1106ba6f9fc6d9a781f669ac2d616c3aa9bcea4bcdc8a7f674dd90ad6cda0b864381225216a48e43a1339d2677b2b2c5bb20d9b44f861da873d9d4a79cca9df2d0280b9bbe4d8287d029cac213c5f85223e6aca34fa7e814f73fc0301e6c99e6e0b2d83418966ad360381497d126506c553725a6c605f96f8dbb35796b4bb7766b94a785d124a107e5994d746cf299d7ee5dda57e6ddc377194de4efd2b78613822c5ea3f088faf47b74771805e97bbfca23cf2de4b746c7fb384c32cd971c8acf60e1d3fc0cd7c33e7c9aa7b9536cb27ed343f95d9ae8f5e10fbd3e9cf9d74f3dd48ac9b1f9357f41999f2fb3fa1a4d24f32bed44361ffa54d8046aa27be4d767860cfeea5d1f7ba6a19a0f639a08df3084ed3b653efc221b4dc434147b99bf355fa38b646464bee663ba4702d1c6d5cb883510c4be28464c33c5646c3f7fd331efbb9fbae6659ed663448d962e93d1345ce6d2b1f9322f8142ed7a999fe17a195dc43404fbf08b687c46114c3b94ef8966bc2a363f3d14c668a70adff543e1bb5e3ad4614bfb962ce210a7d13dba7f93eedfda35ba8fefafc4e934a5a4cffcfbdaf3c8ef53c1aa7e4c5adad7c35c1d4e9bbe1787864c9f766bfbaef028068a362d874b4aa6ff43639c369aa3e6f31c651e21794ed1b1c59ef36f86645a569a3743f2ec52038304e689ca229c7af0e58bd3dc2169b86cbe0d97dd10c972c7eadf9740dcd5454c43f7b72fc2f72ad1717e4c08e37b5f4ed170598c6271fb6e7b4edb70d9fccd35100da9339588e041123d7842938c24a1e3c4e1b2599b4d52677e7eca4fb98a9c8d3eec08d143c49eef49ed200b0f92a6a453475f94dca967a5bc44792494172b7b7e6ea23c126a070135b02055430a45b24b89148e5862b2e5fe6032659b92ef96504ca43069ea51719010251c95bb2da19828e9b8e4ba251493126c1b779b14e1b4f9c0f33265ad28a59452f073cf3b4e6ff92f9ad0f0a61ba594527aa985e13c564a29a5947e86ed381d29754a69c594d270f57352aff6e6bbb136bcc21cf8551b18ac72dd07001ea1e7c9aa9c61a30d4a4727ae7ad9ca0fe4b86a2357812b9a9c02f3c90170b1e5eb1f624bf90490331bd286d49992a58c3ed6b42f810a604a9e3efbd1ef4edacbefda4637a58f5cb1b2b4f137c33a56be6e022775e84b5df31c7e362ae59161abd671276f69852ec73d5bcaf5a23039fbf9eaaf3066ee6c1b9e43f9e3326a838e756683ca0695a492f9e47be1cac6db903ef2288595fa6d8c65fbf7dc31a131d78d005247b41b476fd1e645fb32102b61ee3ac61430817eb8eef3be29660067f99a8b504fce0be300dddd5ff84829cdb4522d646fb84cfeea9b624cc6fc1cfb35bf29e2ede5af565bc36f8a31a11d6eaff54d9102b67e07ecc7e0dd02ef6ed9bc3d57abe572ea19113325add35b02b052c33967ad355fc99a7867ac2b2cc1ee0ba364ef5ba1a54e1825cfa751097cdde77d22a8e03f10f6ca9f96fa4347f940ec50f73cafddf7b9bbfb5c7d12b4b6d65aab05c120f912afa472f097cdfd138189151198dc8c6de82d10883cbf05922c678cbbbb0a2492d6ea3ccc49296dccddfc695b30d79d2075e4bf18f3adf327c745c8ddadb59616336bad55dc16b7aab5f6f3eca5f96745cff58aa9e162385bd271daa0a029c214e00224d0acb5d65c5f14f50a02481d281b05bab5d491df64a340f7943a52f46ee894beb27929d151226d14e88f6734d251caa7719bbc7bc69be9b6cb8032668d8d4dcc0b478affac48b3f7edb52f30665d60cc6a21ac6f586bed4b29e5cbdab9715ac4bcf066ad7d9adb6a6d753a41f84000a58b4f82d66200b6ed7b399fcca92fada640dd64b68fc13a323b365caaad76bbd8f592b11cb8ad06b66fdc9d23c70101ace055ebb53596e5bcf5d6ed5b1bed02dbda6dab77c9ba63ae6eada7f75e8fc0b6e2b6d5a7bbbbb86f0440192217545938c0ca804131785b711d68ad15e7b6d25e0a767373d75eaf75a5a99d522665e10576adb745af7e4f0556c67b297652e77a607b90e670b01fd82eae76e96edbc54bb66e7749c97671b5dbc54b77db2e5eb275bb4b4aaac55bb5d756bcdd25161fa63c568e96db960372b41fa8d5568bb7abc456bcdda5566b5b0b6ca73e95881004ae3fabbd1be636ee0359396cb95e3232311f95feb2b5562cf1588966ad152669a472863d7d1a0590c3eb9bb57e9667a18be16e85a294355f2ccf582c66c3b2190a9d2c6c5aebac3febbcb5566cbb34c9d8a09873a2909a00301246582167730977b905ab29809cd357aeef5c5a5a5abaf7deeb0fbb3418e31923a327a327fa846bccc0a69cfe56060cc2313e6b7df8c79f9d183e8ba1db7b5086eb9538f79c7352e9be5a69297556bf5aad366edbb66ddbb66db3735f6badb5d65a5ba51c2b51adda25d20914f37251a059f30d9f92ba0452f11e93cb54b19352674ad18793a2b3f9349fc61a6654a8008356af825b81714060888602e40f5bbe90f4e166535a11b67c1d49c2ace519ad41c462b1582b70c7b7d4e919cede59333292a9411423b465498c4f8341f6f576b3dd905f969696e4548d29027da31d783e71793a81cee67c923af62ed59824cc2a4b4baf2dcb8e49c2aca2b9ece859b2e332fa37373738f786d69f46528e1c37ab3c4d282d16b5b20083eab36851710df376ed52283e85e199a54a974d7f5be2b2e95f4d9b4d30703dc9f746d997734b9c53469e40b5569974b1a796a188a50b9919991184680195e796504c58d8928e43b2eba9db2164f292e5e3195c24919126c63d08d1a2e24493541608abc2e66cfb625bdbc2da97349965d324976db1d817866cfb420eb6b530b8b02d0c466c1b751465dbff41daf663d8281f51b67d1a944746fd7061aadbd5a35ca061bbe31c76da1d1ec36033cf3c4716961e47b400c4cea6d9b4c0346ba14b8f146cfa319ff37ec203af38e32f7bad2f5900b3ebbbc0a08a43c0420d5a78470f22c0e2021692f26c05fa191d09b3699ea940a38c5608a27866946978bf78b020f3f001869998706dfa314ec0197f99f60a010ebb7e0ec10f561862d7ff603ae020c67321b582931ddd13aa151702961d275081885d1f671b98c038e32f6f610ca254904a8107bbfecd394401ab6ab51a0f2b847ea143470ca27484d9512968d954884dbfeaf004a594524a5bec1a55bb61d71aa54b9e998b969b153fc8e1891f4f50fd00c8a62f696c784d6d0cfa9275da6793e0f7dc5a6b659032cc3de73248196e01bbd32481eaa0f85784b14a94a7c5c66f97b6ff34cd3ad9a78d9fa747de9e664f60956af611594a6db97944609d2c15ab6481ac1525c78ee3243be84a74c4f8719ab2d59e44c795689794ac121df1e3f0c8da2a491dfc38469936a12855cd2f3b680f07227da03c3d7242b1489fb9f17b12e5d91e67fc94093983399b492efb210693c73e7eaa65f2740f6bc155d8f8a5f4c14662e3977366c4c64f80d8f8a90ae40c87cb70903c29903cf5f1d31b260913698a801f3ff5217be061e327780886511a5a5cf274dd8f79225ff1c348987e4c0864b140cdca1208a66317fc192bd6832b6fa563f7257e8bdf8e74c49fc51d97e1678916bfc56f95f0db25fc57fc89e132fca08873bc649a55daf867d27d72ef4cc2ef4d5be988c3035f94a696b278a9d8da1b303589c740e48dfe0f9deab29d0682a42de356f9573babf6a6734c6e9a63030049a6430635203c5c098243b7430a96502902073fa87074f9410a3a38e2070a5498f4dd35cd5e77f729ca5d2b75da76566a05450a59be4743edc9a64654260fcdbdec1ef43dbaa46a29ccf479546b13e5a1b3c9c4a956abe9482265c9964d2995a1d569d34aa54ef74279becc1a5292582b58826fabe993f5293a52eb3de848add740aa6f267100dc858ed47ae1b6044d985fb573c1f4cb26b7d0915a9ac56e093a95ea5b82de14802559095682f7c820cf2f49f64caacd5a6dcf1db856db4432e89e5ee848e791bc61c2e402cb40ad474874c6fdac7beacdbe19385b3ded5b759959a6154ea42245ca93274d9a24b1498c3cd53074c6cdba99677758fa95be3da23cf72d129d65283e0b775e2098daf5e52d31a4329628a90cf430d4dfeb222995d1a497ed55d3f0acaa47b24705a8e692d24c7a7aeae58826d19ad7a88c3e1d22d3af4bf4eb514da26f7343ce40dd28543cf3f6ae87374ab729372641f245bc2537a5bb6f2b69b7577bb74d63ceb75a7d7a1cd7514fa4812b560e5baef015c6c8ccd0d4c46c50a450f152a4e915f50687458b51e602841c1d1bc28ed38b39020d8003a0ee58116eb8a8a150b7fceb13c2aeb8f2e8b8bbbb7b0e0742e7c26bf1e180372bcd12f387eeeeee9ec285e265131393a19981c16668646a62622f1b178a560a968ad5832f44a0bd15dc0dc6d958dc1676ac327741dddd3d47e680e0424707c8d4f11caf2054eba212d5bb8dd9bd489563adb256d97937deb7e20335b81257ac67651595a8e630450b4525aa2d974dbe91af9437dfc8af981a199a19d80c6c06462343531353137bc56c5c36285a28528429546415cf7a71e538380e37de0d4e87c38263d102b718b75176652eac0b102a08399ea34375429828a24c9d493dc72b08d5bab0f36e637881f0fed537d48511c982eb70e6f46ebc6fc5076a7025ae586f3f505959450e53842d14f603b5e5b291b17d69794a990d2f905f31353132343233b019d80c8c4686a626a626f68ad9b86c50b450a40853a8c82a9ef5e24a831fd62b3efc5501d4b0e2c6bbc1e97058702c5ae016e336caaecc857501420521c77374a84e0833049d10724070a1a3a375c4d7d1d1d1d111c00ab602a41c55c406df2b3f01c3f79560c4e97b7d2f9b9bba03244138b999128412132d4dd8a06506b74a0b0bb8232d357446b424f5a0a5e604105d361be49b2da18070da840061025c25b3d8120a08a39b822c534064714ba82c2bc060728b2da1b22449f901ccd6e3072e4c7e9872e4871ab6177ef8d1d5208f5b4261c1c15582e54a0eb0dc50856508a743ae79a24322db14d11d5db944e4145b42f9e064073e8ce03ae1430fef87ac43031ca0a648452992635b424929112165e445c928b684ba828409ae5cd97145074fc7952558aef8087245077e22aa6a47541047d9664ba8a825b28a2da1a28cec04604ba82d4b705d2a062b0a6090a9fe55fc4d9d5d5d0996199ad8ee79089117dcb0c4892d2500a2e52d6fc0820f2e406a3b38550172774cc4061f5655cbb74545121d49824852c40c5190d46053da23e3834cabf36d28cf44d214802d8522525c5653b26cf93026f233112b32aa482d5751d9f2c122643a4869428407134d43866849591a82c4854c9b4986e8900f3b22dc526522253d119259331c6df9f257d8407eac071a27a39022375dc26cf93430f8917513545bfe8d969915c430e19c5cc093b5cab014856ddb36154a90b4b32554103df44c4f055810e08b2359b428319141870c2fc840457ba234d53a5f3637392f6e2aa546b26c3a82116c4a47d0834d49f0c3a6479a8cf4b029b82b6ec8b4d7deef33fc7afbf3ef532be299e911191764daceb62f187476636fc87bc7be858d42e4faf6472132fdf9c2fbb3d65afb3d443c99bd39a50f9dd2c74ee973a7f4e1b69cd2a79b734a1f3da50fce9620ecea62d7975253fa8c5b4ee9a3624eb0be578b4cd9f33d19d9963f7f53d996514474d8f33d9a164cf67cfa15a9c56e6c58142192b78c2252b5a7b7a2ddd834c7566cf94ea408d0e69bd2e7b7149becf972b565141112d012644478ec09db322ac80af674265e60d0a68a01057b4a1f9b297d5040d920b5ab28f7107b4a9f9a297d629b6a48d49ee00e926202267bbe87438384c5101dafb78c0ad2c4cc117bbe8a39a54f8c4cb86554d2961d6efadeacb2278a155b4609b1818b6f4ed696514933ccb9616050d2933d7f0cc224a78562cba824a33dbf7a9595c6ac6818d854276ff92e213db0886d19154308ac2d7f3ad9730518b4a96280c19e3151428cf67cdff9a68c902221c86c19150469cff700f04de9f36df933e0a6caf465540c5df6fc9c9b2da38268d9d3b3d57a1733ef8b82d65a6b676856341436fd9b6f4a1f39df00e0a60fa6d31186884c530497428e89c23b64153660a50cdb320a49881726c76c19859402c725bf72f0bd90bd226e11416c5319ece1db91bf1d381e3287438725734d3c221927e1808c6048be5b4601110244deb68c027284002046f7626a84331e71167fb0030615478cde892580a468f2a4c2892e2ea0504ae184102dd898400985132d8821a684cac6892620354aa0c49cf841021a25463561c00c81d920e53438cc10249899c10916a605493248aa66c2341112c3f44586865961c9ebcb25588aa1e283309bb673839609b6bcb004099948b9f00e0b7c649cf197912cb57c708217584e8c42bc5383d10a67fc651248e51d9c8407b8d3b3f3a2c7090c419ab640f940851e3524f1c0054a2995810acb5085731338e81174640bc63b426c8cffa3330984f1c330c68f337e1afeb0ce34d4a84c1ae1a3241a947edcc14f3eb620a6250e053e6e90d216bc836978c1eef4ecbce849e2254998ed684865d283091295c94dc3b989da519093263039f81154822f60b8fc08b2a10646aa475053ad5291012dd4e8e8b453c54a93289bb6637f906b68a2898f2dca13dd0a79b5444724b768606d905f30e076e41c6505d9e6e00dc1a46baae1085e227f5b42d50064299ec5a874ac18ab8ad6292a0000001000b315002028140c0844029150108789aeba07148010719e3e705e99c9a34190a2288a6118638c2104100400318610470cdd46026df88771fd61ac7e604c7f18a31f8cbdfe09bbb12cb252aabc2150e1559cbeeabd05b0e33f7d2f4da79f8bc01796e461c5c52a51db29c0da3316f8732f43b7be04fb8d302868e8fa0d9397c1013e2277108e27d0945c3e0fa13f79dec76bd3bc672850015ec5e011016dbfda3725527b8a3ac97ee738a368def429800caded0d271bca861d5780a3860be1ffce07d2d525778274b95ca57b0eb5c0936ff06ad6446d5fd2e71564e2135d6fb2cf36cd000b84882f851c0043debcbf52b1afd3917eb937b43257f11d1684e9ca9544184a71e8e2d880f1014c1e905f4ca1c350aa02436249c88f116319257bbbab7baf949a97fddee402f4700c62ca2e38e7d847c2fb0d336246c1132fe0d4f340d80d8b892c6b92c5b6696e611a88bdfb4f718c0732ce528cf213995957c2a9b9219448ae8100767a821fc7f816e8517e5701ba80b87f60bc132f63aa389b0b0d47395e8cd0245a26a852f5d128270535a71cbd1c271b525d6c794d74a659274a56a8d85cf82d7b38d8a475b33dc95578c42072e8936475d75608839eeb71db6b4d1522a67ed5467682116746286723393815ab5470afc850e2b101bf9a16333a8aed6af3dde058656386afd44fc222c489ed330f1c24c46d868bc978f1b3dd4b6c03e327ca303d2f3b8933b88883bf9f639d97f04eba16eb9e1d982cdca4cb4a32ee11ab1be31eeeb9c6b43a1efd40c5a593726dc85157b91ac0a1ff7318eb25dbca0c0ae82677da3165a0d803e939a0ba9f06cda1c53aefd88e20e6afd03f2b686ff2cf5e83b6eea78bb7acf565b178feb3eba9817c1692397555caeccd3781b54a405a8e0308ad94635a79d14716372b54962d0958fa976833a4e426ef247f0ac97a5420d60919f9cee5ce3b98acae3b660868a0c386dcfc00c5ba3a5b1446dd287f4b0006a29746ae2aa591be2a694427771d31055be7326d22d4f8e20fd1d156b63b2b79aa31eb016834c10e021aa4f66c34c13873c12dc6e4f9f35af1333d1bc9281f41e2b0873740b62554652d90543a9dc98506896157e70a79b2ba39dc446041e5505115b140835d82a39e57b2e3d7ad886985bff3b29f114c80f3fda8d5b00f749111333a97be208aa4c7f63a4646e123daa3a6b071d0a0ca527fc0147d544d496e9da19b375f55b5a3ce060cf49d933b1ce3ed44c5fcfa7639fa18a3b33b2b387411edbc0a133c033d576521442f73c748ae035a420b66457ffaad8345ecaf5c1cb95914fee88e4ae5ef025d92eee970a1b26e8819e9b5ccdbedb0bf418dc3076d964ec19be258a7ce413c64bbd649c16b28bfcb3fcba3a6ed641033c971a461389a28d65386844ee7d0c487e489fad850342b5414a816d12009f3b7bc54d27d98cfac434b8c8d0fd65a624d9e8ed40a651fb5b7bc14de5905e3a48b81014b02f42e4a6aca4299dee96aa057a893ef2d1de7f8d2ac70abed835f1459a484ebfb8a35b41a655957cd367dd2126d5cee32a41a243bdb774f7beca9378f447f7cb952909a12c2df1458c97c001ec6dd174416f2bee6e58ea9c420ae0a78a2a2ff6fb6c6f15ea6c2ea88ed951f52babf2cb490816079a459be08df0f5a8c8933278d6f4c70e0585e4e7c37987248550a5cbb1cb8bba47057a970af520d47df688aaf04ccb284d7bf49ab2554871c5ed4f9073d24051b2925bc1c4e382c289558cf091c60a1107a0cc2070e5e832658d8a8a35e6dbf8294bd0e01253b7cfe990d234e106153999475c5594b82bb9482732905c7520ace52129ca5149c4b398fbba2c96a7a68a725073db10194131363966d5eb30dd9b3d744debdf380f99ae102deda26aef585f22a4b11742d17d7522acead1cdcad3c385b2938b772706fa5e06c25c1d94ac1b995837b5b194fe88ea9c7c903aa9434004842b62438176dd5a98ca08be30bbd2c7b66584b86b0978cb02e19615932c25a3284b5648475d9ccf60af434fb9af5d31e9c15b71c20010e28d0035b029effdb0dc24ac735e08fb3a54edc9ab04e7a4999df33dbfdc705090d04609f89f3187e07c65a6edfe65f4e9d21e1bff02558bb35f5f9035c104ae89d0d529364f2ffc37441950e6f8454eaed53363371d69536781f99e39364e6766bd7f2a95a129c6647701e0a2ad24ae7c4955f4eab7fe378e11fc84b3d9025309a231f25e449ed4ec492de8d0fb0e02886f6d295ff709cf6a330ed8f20691f87d37a0c6f9a0b0e2d848cef9b614cf1af2ce0b4e45d69b1a2651e83a702306c1149091a81f1ea5b4a8539454cca549bbac1c0c8f68d53314fde369a2ce702d95f01f09a614cb95f7c720697b6e7fb19ceff639cbcc7737e17e7fc1d26e7fb784eeff139dd89737e1fcbf97e0c3b19ec879f202122603a83bc8182c1d905b37329a7724dbaf8112cada310da8fa0691d09d17a044aeb6898f64750a3e54d0aa1d6db9ee2f8d41adbc912e58882bd6699c67159d34048c488f8fb847315c65ba6c1c989a4268c81c8d95f21672ec4fbb256844b6e7a5139d6c832f66c2b462f217ab806d6f0e979f6ddcd89dcc1b6452179b140e8859507d85a1e59fac7e760a62d012b2d30056c27e00c6e5ad65ed976cda83f685d6ee73e7a947a314bb9c571d7b002cdc8953247aaec6c136023a0e950e68becb849cea106c555dbc4ce61bfbfec0fb330de5168b0317e16be952e79d2d182215ab6f923b00151fa8bf6410d09e1484151d96da4f6ba6c580e097f1f3e68f2995475370c340fe2240c62b76836c71345abe7d19b1fb28d1ed26cc84abc784944f14248d105a8d29570a50b908a0ba16ad740151784942e81ab5d0829daa58557a044321d1e5cc442301672cf7c49a263bfa6bda2ebb10cc57f950c8797ac91fb2afc90ed40282e802a5c01515d0052b804a27201ace00244e90298c25ef1238aba543870811d0f051d5863edede2311388eec9418ac738d665f9fd2ad06fe9641c3f0e200947cb53b7ec5da82b15dc3a068b3b1a5ae115d599c3010d2de98759a19f21394a2c3106345093074a40282672232e7883c15dfc145bfbf1c56125134c620b91c2161c964ad4010d962103c012ac80d74d27c5738b8443952ec61578ff25619e38c7a8bc25a6ff9e2f1c958b8031bfbef08cc1b0081ef88d405bd316e719a475260153f8f4cbabf5bbf4166ebd5772523901dfb9c3f4e14ee5912ea5420f5c3c0c999647bd2039f9247685c202dec2424546085d3c94b7c22dbf4c712adbe7d498b9a7147b198f84d2b55402ff74489b94d08f6356582541c0b0d042e8f24f2b56a40eb2a025eab9b0829cff9cce40c242db26a1a51114646641454b3c88263cfc4d14a284a3dd7263321622f31e5edca1c0d14005cc6230b405dd8b06f9cef525bfb300012cbe7ce7477eb0dff5e4b51c8ce11a1395e4f03fb4044af91fe1b6871bdaae4c750db0151a5f451a2f035198c2b8ced243a5049b400fc9fe4d28667f126ba19326080936d1a8ed7cd777121a32457cc3d393c1beb2b9b1840e4ed208d6e561639054016974eddab1f0142f366a5887bea6e0c0aa4b125dc113abbc4fce9e11617b58fbf69cf8fac3d8f37df2c58ccf1589b410fab00d29df9948f228bd78e19e7ce205b47e73636d9178a4e949984c541b41d54e2a5a3d77ce648957091832654514027896c351d3575ba2b44dd77d88698625f8b3a5d5b6cdb812ec62a95e59c64dd64afad6bd63859b5ed5d0695863f9a52d559939ce6a942b4946ee9b940a093bb9f61aa683847cfdc859568f04ec6c013edb0c28e8dfccfb52da18deb9f4ba85d79849b607890c337f7dfecdfc60ece4637d6843631740bf6aa98d496ea6d291cc7cff8615743319cc59d3fd67886377dca2322c9dff8bfa8fc8b093bedf6740045a8eca13d2b4d8a0c8faae9262de56b311a2a65790c6e80d9de7a0a3e336cc32ed78c5ec8fa3c23f29f4064dce2180510c29e2113f364cfc322414716b3e80c8fc96f1cd5b9b18b2933bbf0d38c180c63f884b1037298ac107168acffa9dda73a56e39c06d0fd3c4af576592a5fa1eb8555b98b42baa739efd3c0638afadf08e3dd43b429afccd89794503b33089b037b2947122d966b30575b84fb481cf4290155d63540a9db5fd052a56d6c4aad41df0209e940dc949d91b2a81a43e2f6ef2f1614bbd578250ea2a566f1f9081bd6211c438a031c6a5c412ada0b166b013f37f6cb0afad3ea8f75fd8a040180ae1465cf1bb808c41284af3b83f6048bf6b3114d3c332369bd4736053b52500cfecb6b3bb035684409375bd842d2bdd140d1bc4269d384f7659cf522be606c3df5b9eeafb459e47dcdc24eb514771ffcc7aa21b1baf8df5c5489b0824bbaf1542482d11c8f2de3e22121f0121583e4a1643938995c17ded1d09667bbf09407d01345425a2c0b526d69247dc7527e6fa2ab84836af7639762cc8f769312f6b8187573d6e2749019312c3dcdc97f980b3a9a1ead348076d7050a07431a51880a65fcafb9025b64243db061d355b246a299c3cf5804b8e421370bb7f68efae0b0dea1353b695eab51cba0ad13c30a8af46ca68b462ebed2e5b57b6981404c103043b669badeabde968392411b20d431bf7107b7aeed99bb66235b48b02aa9312048826ccc57bd02233ade4b59e8863095e18a949839af0e26a99b5bbe7590dcb6372bd70013942ea73675720eba019e79f34a43d4017d2d75f6bf05fcbbefbad7c6227fe555865afbecafd3825746ead7e57803abfbc05d8d8233e2c6254bcaf3783c8f91e724e5e63c8699cfa46b1353e9552b9a19a8abad68451635c7429e36ae37fc0bab548bf042734db86274afe57b451e4e9fc7253066902f326b7b33bdd4fafea46dd521df14b14cd3926fa5f258eb552f57b61bec2dfca18084bb5ea7d893c50e3e95341358618177d4ef9809a96f101b02263e87146134cff2d6169d61cf623311fd84e39516de29dfab9f7b8c868f4c429d8cd7c920888cde890b1fcb633a959d131b39ef3841feeae88dcbd8b477d9a20be87393646a454ff037ce7355223cdf933ce5892f2241a8ac15f0e56b4f7ec472e03d8f0e104855d01bdc17bc775dc69ecc5dadb7ea4df8af7041d5343212a4010893034bc307864acaebdbb3ade2e34874fcf0e7b1a84c8f2e959ea4a5d012de92f88d978e96e14d5e7be78e1be7f9f5a92c48d7b4b8020105ef82a4e7742c31a250df8532b8943b30bfdfcb6f462e36a3247fc0feeddee1a25b38cdc41fb8cb98fdd8ea6f417d78c5b5112ed2265764b7469c4a260aae450a8da1758153815454d05a52a4785a86d8154c519116a5830551dd13e524557e33452e337e6db8ef322ac561c356e363a9bedc3754084da0b4255ce09512b8880ce6d1fd586af33490ef5a7e02030d030fbf2e93a651b762c8a5a83a98263217cad5b22f2a4cc85a3747c0f131745e210e66ccf01d1566b0d44fc491a84c929dc06242c8ac4fc155328df60c3325d87aaf916b399f26ae985b70445f74f0183952bd8cc87a6cff81fdbc154523421c2bd58b3f0ca991583614e0b308cc2cf983be05d4bfcf21be15327850e79504226847df2f40340ed44cead255616991f39857de1415fefe76bfd0d5d62154517646cffc5a24dafc1b7259e5bb3ff0b7d69189e02f331d8f2afd6bf9d93927a2d06878ee891320c9fd1f31d4e485c1e6253c0c9d797648aa98fb339accf0d921cb723ae9278495bb4227923adb062ce22dd69aea9121af03f7b722b1bdbeda912ceaa1251d14de2d1637d93f9872ec99300009e54422ede668a201bc72315be25317a56f7666bef150bdfba5a660b90970d305f9de40af0497f29b28d4ad3bf308c77cd4028a2730c49386180c1d4fa0b439b02403e2cfa0b4385b08a96dac080bcf4c32707e6e9d776841fa591777dcf0671e09a07b7656c0c7093d3d71123cb4bded2b86050764291cf10d08a2b5ad13c829099b039603ae7861c0df47d1ef36558a65631dd94e405ae14d79e709e216eca51d604fd5823475823739a4bf492b96c0d899da86670bf6b032372662c54fb1c64becf98281b500044c839bfe684a253f741a19d3f34cdf95febdc11d5608485217817c8e6ff49a3bf9f7da122ac797ec66d64b03ef0d1ae298941ddada80c9159b2f75972b28d6f0a78ebc2b23cdcb43ae9431a173ebb54d377d2cf61011d518763f5df8413574ac07b9b5c3e946bcd8f7dc20d841985063bd3497309d744a781367a0238b68cc3cfcd386a20c98aeacf0168066f5352851108310552de8936fe1458c49409d706f378253920c72d05ef48a4f08c1856852520ecb11733a01c90cb045258756ea449335d5184077ae11b3c457737b1c5146c631c8508d2c799d4b12bd011c3d565779dead622aee0abec64aafe786c79b4b8e1a973e455edc12b6201ac101be75655d7b86404a2c523e4b1844073e05d21266caa3fa413b4ad60926be891ad2828612154ca891117355ce130ffc83b475df58b5de0f0b460224301fde38a4b2ca5e2ac8addef0704c12fe0fe55fec272d042e95dac413cd28860dcb860b982d4b67e1372a01b65be33f814a6cb14ac3102ee0c6e7a510c4e059ca04867ed04d448f5e1c602ab127575ee246051295c2c69c502164235db02c8824da54cc2f15623091675d134a62a9a41a7fe7150941aa196892986caf4d1a37719ce3ad69532ec04f7a4337c81f77d1e60315a0b3f446e3fb4ef9941d508828bdd1ad053785c9655e08dc269ffce3eb09913e18b6d8048c66d02ed61611bdcd2a8be4654c6e6e8e5f45fa8e0a15d08ed8712feff7184068224ba5d32f723c2275ff072428eebcfeaf7fe9cd936ea1105bbbbe5d83e0f8f948cdc84a8a2282d6215dcb2720a5113404e024b94571a7cb4cce0485afdfc2ccdca000b36f2fd1ba29fb4407fe44b6365cf4c092f292ab9385a06add3fef9d86985851adff20a6da815f40098a1740b805f54305b9a482b4dc48966bd496e39de51198d0c37be5546ae2914ae33f6cf3c0e18e8b0f82051d4f1c979a259e82c49b3548d39bb1b29da993ec062a7082025a27bcf2150251872bd5ac3db38747b66ca6710d5134249fc795a68554e24aab4f2647782b27eb954b8cf8cef0618840817c09aa3a3010c2854ca9769a922d6eafa7df67fb8b64d26d98d4d2464aece2ffa5b6c9d138df5a1644c2114ccc8173b18c7959db44278a4d49cfbcec06a5e1ca991e83a5cf03874c5e9898574edd507f3aa5c28410186bf8a64749c740f46a1cf4df2486f316179267c1dcdbaa9b8dd3ac0aebde226f4740cd4e29e9b7705218ccc3ff8467db45403de8ce6d2339823c2909a2e849fb50ffa4802c96a5d4ae609961146e89d18641fc62327637c4853073a6745a6f566af9714623e5a699f799affc947ea3dc8558cbd72b678419c6a08e58390df6e1202616c4af12679d6f02cef39001434b6813e1153b6a39bb1005bae9ebcc95eb730b4fc9512255df9fd077bb155ae041662ad6261cea5cf2729b935ef45d209587f6d8eb2991159468293c3c76d494ef18a61e6a7805789b2525286f30b48499df75377bc609fa986b5cbce2a70d7f7e775e5c67fc16cbb480719120abb55e2442ec6f48ad0b31060902ce6e3784b96d1f7404293ee961c9a045be6ae3461c1136a16b5a192c797a7dc51b2ccb6c0a7f0912511099ae29943c6f4af77441c79d30612f680e9e7eb17f4b3b0d605943099015dde5f29765c22a8db5c04a0c4764e055cdbe3afde7fadb380e930677bfd9fffaf28701ed459e4fd3da2c78fb5b87786041167822eb0584952c3d37578d0d34896292b17982899f974cecfe469ba931b28f81962272ff05b2f54e932f7d65026ec3dc5ed4ddea8f8d9844fe91d8d85c0b1c025dda6802a6d345ebe3abd96a3e9b50ad9b3893ef603d9a86f41152b8c870addd544d85f84f5b464fce4050d385d1980371ee9f2e3ef63d46b12484a82b2e03e17d9fd2f2a8abf77904480a21e78141812f8bdf7bce2a6cdbf90251d77b60420809c4ad058d1258ad6fc1ea0083f69a25698320004dde378f8207f34524d1c61d65f61781f6069edb599c9830b45bf15a2d288d1b8c325af0c3d6b4abc8d13e95eeadb3478e1e318cd94b1a6a91629f6986cca2e3e77c6bc1ae722d51c28d23fc2b0635675f01f11c0960e6c3f4b10c85fd11a9d33d22c8e01cea8758319dc49813ab7d3e632fd2f10e168383295e13fe1a62e0da4e0ddbe3d0538488e1f148cf73a42eaf681c64e52c1b53024f93c080682ee26b8d4adf623bfc2568f9d7d5af2d2d4b9d84a9e566647832bd2d0e1cd16c96313680bc410c5c09f82a708ba55b1d5c7b34b9e37f212033faa2c6a8c5ffddb87256927bab1495c8433c234c7ce58a19dd5b44447222dd3e7190779ec217f24121f70ea60f4e4f1f5c6bc71cc2813c9f6c9debe9c94af0cc2dc8f153508f9bac1c9e8365a7902c5e1c72ee542de1354ad52f29b1b0134ac8e45a41e86c1d7e30c3a1f19abfc0f34b8f7ab5be311bcc3b55ffcb0586f1cdf4b3afbcfa7fd2bc56a5a99410380f919f421d7a86aff1bd1bcddcc312bda4e557f3dd4d7e97f710fc28b382848bd33e47007f16b1ac1b1d316ca866c43fdfc70a386b6f1d34f0733d5ce9ccb8eae7da26c7e6f4833c40d059c9c727db0bde4a3b3ba6ddd3e45c0aa75d983ea3b050aef3501bc90651b4fff32708b42e29eb5a70e842ac53e3350947f0d69d709cee0a6bd49c875de2f64ab6512126b9f7c764516394504d189566da312d6a6580d563816faf874f69616596954b7cd392355e33a5d6bdd3f12a423853953de1c68a3533af3ab154447b71de53e5801dc5ab4cbe4ffd9dbe19175f941dd5965fce6a77dfbb61619611bfa81df2a0d1e0272306f644668356c80b0c853493a6d2ffbed526a4395e328fc0b93afa7122a3377356688507600a4ebcd107023a01409747d342d70cb60d0609cacf9de288390bc913bd4cc183bbc02ef310cc12d26043c34e85bce529498fbd26452ada6b096f68900f921eae6c30837cd526b1450b9fce84ee4c1ff43051f742bea1e499be3d231129c87a8f67158f0e1fdbe7be401123cbffef94c7daee296099489f3ed21aabbf9f760b538bdcd48a795fe61924bfa5dd71a34f1d88fdca33b63e4af7ed7b5d9cd6095dded2b7e873133433333f8d8bc3ec13c10e1f361f56d88b52d7a0de6e9681b4d0a873daf85fb6875915215f24c5c3fbe84cd87ab6bea1d0fae7f5318c210eef4ff656d869a1d22185f7078b185465cd2c026add78de0e474c5432a0cbb4409aa0202c9bb03ffa03c7082927267eb5c71a38b71421b2dbf54d0cb956fa65df890e82d52bc4f41f43ad136f76e12ec85274915889d0da1138ee6f7eeecfa4c4295e5161431d9d6f82bae75c2715f23f195ddf79242ba46a0c50e889a913855cd5c9153e90246ce6e2fc1f5114f215261750f24543241899aa948657839e149e16e42d3d435e2137eee17225a2089a72a695b1ab709d4a4593e93cd278297e51940787dfc7fbcd580a6d746ce2eeeac4f8885925eae3fe03a6889dce585991300b1fe63b1e4f7f17db2ad97bd10d545a10cb70a5e22239ad6d4b818dc21c5d830cf7623502b1ef500bcaee606b256931af849c7a6ee4d40a38d0942ee72305c41ee61f01bbf24ac0cfb35ec3655d8d6c2be26bd0b703820c0eab42c11bd31f30c31bfe2f2ddf6d5785c7c0f94e39585f2f5752a4ba03b62229aff68b3ace0019be2bb4188ab8249fdd0be080efe10e4266a4ab5923f2e92ece497e02eca228c922f44d4661f363fca9104985045e3832251a3b21dfd2702b97223a3eae2ff55cb31f02f738d63828736fb23138923ef1675b2c488b8ba5914aa04dde4e1abae93d28f1f66170743170f88238ab11ebc0cc0448868e9a0ab391c2f97cc6d997ef4e83e99312e5e7ac5e43634384df8ac2bbae24b987207c1d4fff8083ed30c4a1adac46d40717a7c4e1704671b719a31bdeb6ea6a98c3f9c8f719d3668da11ae8b3eae88010bd2225cfb6360fd4725bd84d780cb678cd9f8b9cc0b361c1758a546bc3613de34617f500b0f93ddc75b59813b126ab1780558c2c443af116a54a651d8d0c157c10df318ec2485f6544dc1a1ee9ced48214fe293351e79e789274d4471b26b40c80cc69c2e1b2c09c33ed7ca6bc78db5ef391a76a547772c0f3e0ae8d575089e2559e24b17c34bdf08ed35092ac4b483b176c60cd64e7a3a92b8df9e00f0b76f0baeda0519f5e3ab6398d403befbb3d2e0129222d1d456c3ffecfcd54bef23b770e82c5b7639a3813dc2fcd6f800c51e7894cae39e5da87b62d16ad8bdb91873ed3eea0b0465f239906ab6abf7477324051272c611e666e7f669c7a689975010d5f431222c874b7bdc905930b4448cfbc40707cf33c83b912ff1cb4144a778b431c270c19f3dacb193ad71e960c26c20180441b3302fbacaa8a18725d23b28b42cb09506981a2aacd53c6d7d092004c1e12ebbf9ed96906494cd5f19f0a811394f7215ce9f7f1e2a7198c4d8ce3a20c3278f2fdf3a7158c0fef771bf601ec38c26196de6686999e0477a4cab49b87cd4ae1444febee2af3250369f177b22efb02724617315d81ce104f36a6206f3bb9c64e8714b04ea0061fd94c452c8a6c031c8453f93a09d4cc91b9202c12d0f88f04d276ef45a107aa6e8e5a6d880b1778ae69cfa2eca31179c1be84dc8f65171edfe2d5172e6ada67b76ca56f56a5a5a764bbb418455a6c266f151b13a52f38bf72b31102697814b7a3fe18dce388934930dd74861c73c210f25f890b40854b34dbde4b74675375af1c20c42918197144226d9c8e39b1348048cbd5822007b25f1b90b2af1421dd4264abfbe90ebbe58d6b77252446bd609b27a5d2c918ba5742a68320020f496f2b666ad49e384d04eecb6d92c220720d73d1e0fa8ca1a18be4cc221db4b0f38fe3b4c1dd100459a378ad5b23011ad94c19063184ff085e7547800d1c6a74b611e0aae8b3dcf0b2d80da503124f954e5fbc2bc27e4240002e1c42f760711c42094cb0083dfb05286960ede5fe071a72dcf71d64d1138bae6126c2858e7e449c4d13c6090a7e6ffb402747473630823798364788a2575682b660d942bff8e8613bd532a1fb0820b3399059eac423e40b847c18aeb0b858ebd07595a9149cc62a3249b97585b646175c603d906f40f1f424d167574aa6b6c2fffa84b35a4081711d8823bb1388b7c3c815f60d1455ce80d91307e88c8d69a9e1da55ff15a0a31979591ecd8225883f3eadcded9895d6123f899a55529abba553d5325caf0fbdeadb02982d29e219217e13d9dace60f1e65f0fa451866b16df3780c3e5159a2b095935cce1c9d18b25f21aea83638b7beee78a0eebf13a76b546c4dac83dd5276f7759b3089bf3b0ac37b8a9ede129e0e508b9612628a2483f4902e3aef27a4e8f21d586c1be009f0854e0100dbecd704ed9b9c2a447c1bbeedaf4a7c2ba84a4459d39f2228b0a022b688de7709dc1ea5c17f91b25a6d220442348198c5d779208efc0138695143f93589deea370e57790b06824ee954276ca676abfab2d547909de81149321becb213e3cd4e9dd8b4a0903e50c4e8ee1997af48c02789ef8b16e2b55525d6962f95b206a15e03c91f0d8c57aa9cc1426121eee97b69004098988174ba1af6dab07a903a41d22af3944fe55cd72f2028939f162c4546280725e559e91e003e362c3659b97d91dc72508b06146cd930f5d2328daaf3d616544d350350bc82ff574e00b7b667af248702e4a668dce413ca64a5dfd74b4d056f609609c73b5bee156641624316f0c923c0928bd027bb3f0a1b7ba101675b5f1cabaaa462037ef9f4a68a0cc06b70baad6afec034af021061862e0f0d920baffefed9ee60379f34128021e811460a7a5fe5f02ec744bfda93f21c613958c237ea387aebd9f52a52e0459c11cbad2d512ca8e2d58854a96cf22d76600d5775deb5aa550a16d79c6dbc1b25f96c5238869c0a09a444eb7833ec182d94730babf742da93dacbc34f638a38263c279e05bd9c65c0e87bf665ab47b3b3e852544db661fd3b0005e5fcb0869936d1cc7827c7ea8605f93100944c544baef0f14e6db637543208e292034bf34e4929799c44e3c443806c2b0ec1c73b506af764c9129fee94010102458f9300e3f1a157f0a6fc01658e1467fe407917b9d8938c162a653fdd8d6d4d170bf01551f363eeef7be1cde6f7374a2a40deda5bede6b50227a25e4dee27f0c206419b17a2aa26f3ca880185203dc652898707db2d57f5b33400133d1a691cac16d24f73999500072077e5e23cd9f7a20c308685b872b4f579205bb3e65b53b710c6ad7b32d4e587d40aca4bf7b99c4228c003eee6e0695be3a6f728e3f06c3cfcda10034be0573081d14076fe8ce22d5931f45792095effce4080a26753446fc7626e33617a053a8f9746b05d08a628677e7140357c1d67eb9ef25f26674a5c47e320130eb6b091c7f61f527d28cd36aae9f0e6dd559457a15d5bb9de86abaf770795c4b79af052c820e11880a00c44d40c4d29f1a9ac2b8af48ad9705d9f44c7ac03d72983573b327c4ada67f534e8dc7b9d652816294413d6597978823aae03fad16b23275e919817da92a4b5494b52557c41a78e47d1c716c8fae02c8f6b39d382667a563a5cf195f58a6964ca8407ce3e0634d70bb0c1a348d77f3fe178c8cb09c54eade6b3c2e71a9686e85557f8dfcc28706e802b8a32cafb39429ab5f7452aa9d4b3dec02dced931e00f2f453c71a27cfd88d2fda413cc32ddfee79a97fbea48e8de559b6baef3c47ae2ca6eea68ae5b4411e070c24f10c875f86c0fe0cdd36bc5933610de558953ca25365281b74f07a2bf321086b1cd0d45f1e9019be01b7671e34f3d40a820d70f4ad70216dd3cec6c1796262d00199c4ce449f71acfc8c52f950e1760c1ebc2f51e71211b004d31f77c7d76ced806c5b763cd3b7516603cfa7b60639c174cf2811316084a2ea7311bf3113d0c819741e8eed154a54a0d32c1485a1c98ea172147ac59d426c68e87f829327ec231ce1c3a11a12c080d34500f530764f33602f71d4b8ac734a4e1c0365207dfaa17f1a41cc5d7ce81b700f43e2afbe761d2439c99daf624e32770892b07c6503ab9c868b79c8e8e9ddd997c895005591d41a7c28aba2c493494d6866d4ee2041667febc9a4fbb532e4d957a14bc246d34e22ebfc354c6ddbd1e3e61e6114772cec872573c938c661caf49272fc96992a291e46c7a032c8f0d5600a8d8a798a531b466380b1ce7a9c4510d9d0bdfe40c73cac73cdf2cbe9cb65de87d569a7a82b971bef6ef031eb45d129f0018d1480641b4e91ddc5da99e30e420a4a018963600b8ae2f849e7e2247bafcb04a41aad1d23b627d8ffe29848446905f76c9f118757ba9a907f16c26088f3c7a41b5d3f6393ed37cbc43bee52bcb3717592e6ec4f4eb199c8ab1439e3654e49d240909f6ae5700fbc8c81d03e28a8c749e11c8a41e291fdec562549942d8d531c902a4cf1e116efa6c3ad6b86643046cd890c6679a05faf5517a934843a1f43d72c4a23815ae6cff4182a4247452fbd29b0e17da5009b6606086b593b084e60e1e07621c3d828d27a311f9202ebe69eeb06ea90da4d372a216cd60b041d8cd4ed438903c05042192ec809444fcc3d2d09ba411a18f35eee0b4f22fa985bd98f63a9e16d43318fd78c6bb7d88553696316f5a28226186a8b864d14e9e3c9a4198b2cfb11e80c241cc7a15835f13d2ae7e3d3dfd29ac887fe3945e57c3c8c2d46be4cf45bf6c41f6eef18f19963ce5661142bb0d982d0bc57c808bc61ac42f7892cc47a4504df4034277191381f8fd47824218bd97b49de4c44bc221ba900bf1f4b8f90b958b442b3b62c83bcbb77addcf84876f71025d989918d4242e37f5a6d0473fe7fed92bb62b28dc11a741e43f4413665da01d0cb4d9fc51bbe3223eab33dfe9254f9e7efa564ce6aca7eb44a5a9610ce8efbc82871c64982889434be3530dd6d84d5fd3bd37648f61f795c232cbc1ed0338abf4be12e17d878c555f1b3114783b2b0c148b1658dbb7ef2623cd8023f0544827f3e84be4d69621c0acdf87e06d27620dba0c7866a03233e0db6aa5a38860931e03a442246a98f4893bc0ce8c8a93bcea5d0e7994d1b9081dd695ffc4b4b4bbfefa324595cee0215d19480338c2bc02286a92eded390cd4df76b1caca405351525dbfcad4c8866fe7b9b9cc79ef585d74765acf4fa83bdc332adcd1d8db53f011ecf6e3a5863dccba6ec0c6d1032a49e3f65afc35fb867c15efad46397b309c0de591856f86e1f812c3bb9b61bce2ebe7f178ee9f83310e97bc84783b186e49e616447b6518874d2b6008c3109e84d20294572ffc92baf0fea87e17d5c45b1ba8d4bb44e1412c55a5daac2f23c4e60eb88aaf1d4881edbd4bd23dc36bef69b92d3706b8fffb1864b3a0eb01d4f826efbf7783a5974b2c80f3cf2c06667808bdfbd4382fe34d1d215728840c3fe843f19a9a10e4b59bd42ed0e6c86694403734e1ac8209856a2c7124c59f06909d659ee309fee37c1d64a1bc2404325df63fe507d872770a3482164a29c5941202b89d3e4eb15dd0c2e5f886909710903e7278aae89bbe39c988051420417439e6ef9d9b29cf721ac3abce4b005ca2a7cd3f129e9b17de5cc9191fcffb60165d6f1e81c82ac9d69044a3fe5f4ae2d15e0a74c3935f0f289de8d940bb9439b8350534f2d4b06382b2b01a1d118571eac4ceb883874db316141213f157973be466bfa0ad709d00ec9e0210a2bc01754e93434eca855f3b8b5ee661b33e256f837e8815016211423b0cd080b22f2f7a6c170c14ed47d85a58fa5bb365d0cab255abd8e2eae31881e0f0d6a9eae2409da22865e2357b957da8d0274cf59a35b984e821a9a3636b601cec1a43d267837644c5b97eb2b036a9df9036d2698b494c6cef6494fc30006337c30e61d8423fa40eacb01c10eafe872df6bc17fdc66244698c90598930d11d4a42017710865125e3e62fecb0f02929149f31a982ec6f4425656b6cff89a4eb0228505bec77c5a866bf100786dd8b6c0e4e3851771ef59d45b8990fbb5c0e5a80c1e9caf0aa1375aa3bcb648217ec36f01b2612f4fdcb06b74e8ccba2004217d582a997ad2749d367514085cc12e2f2a98fd14c49652a275c355b5db1ed77f6ec848c1270380ed0bd1e547793078841b408063bd1ddf450e32d4413d23bfad47eb1e0e3629603bb570f600ac60bc84a882709be053781f0f918b08f6925e0d3bc4d578c0daf619c3c4d2b19e46afddf088a808b4017aa7be2800fa8a5775334eeaccbf09440e0b7eef82e4b160cfe1add551d0d48b8f1186a11b11791cf0343ee67b79f0ca01514003ad3b1c9187c4a20afc8515978afce26e731fe3b7b646ffc92b987f30bfa19d3d80132b13a409b900e00c554d0891043768b20bab5095b07166010621a9f8ad088fc28e66e152ffadbc7f3b41448bd8d5ee6ddc6bbb1af7e0b38c4d570c23583792f96312d59631fa008a947a6296bdbb43f2364487cda71578aa420ab19ee3681208d5a9448f02d531f5d6548ec65cb08e08fc549d1dafc7badf96b66fe08fa3c08516b7a597fa4c21d35dbc5aa5ebae44293c5dc97c93cd51d4894818728872d3faf07b8b5028765506aed73965857de83703f3733779aac41af9d540b8a5ec399eedb370a3fada9ac21232915f60ec600ebf181177ed9ba0e9bb2f63785b29f894dd13022aa58fe6af2470ffe6d10afd80742936ba8ceb69025481eccbe25810cab301011da2ed095d104e3e8256bd3769c3f33daa04c1eae7e881fd049585223d2a04948aa896cd0fe9198b42d934ba2a33c6a677632a7b76dae85cde84d0904e85cfe293e7bc048e23657b6d10b2cc3e4c7e5e51f20835d081f1a280ae86e220ca9f48d42b297bba456c423981150f1d0bf12732b1968d2191a9cb2b81af03032e3cc50a6c8c055b27e4d8233293aef733a98d0bd7f15ab6bac6cc106f17ef9f8c0166f4392b484b76b590a8192e6870b28d975ca441bff050183219717015a547232825fd7723cef8b33f069955d28a92043ea8b22301a2429c81d91c442a01764b0306b92e43f546439fd4c2979cbdc2e5ac76afb0c75b18be57b321bc1c9c5ef763be258057784ef80f170eff9fdb84b70add0573633eb877b1999a052b4a377bc4a1b061eb6b1d4ae48fd8833c387a4994237c79b9124cf135fa85fad28c4429c201ff75ef2ddc5163c6d2bdde14552f2db0d08a8aecf7049f2ee3fdf04806e4ca6a1dc6f2dcd128f234c1c0194a7437fa640291498dc45a687d3ceb5206a9df39b91f9f1ad85cf29faeae669bcb0fe19623b3043229792f469d31b96798c467e32be76db2b60600f7e737a60c658a24455924db0a845f2aa448dda116bd2dbb3018e7632f3d9024dc51f126225ea9ed079e9bc0a74d51f1709052084d81608695b1bd401c43e7300c8d03e256336534749d5a08e981aab841a88ee39fc35ddbd8bcc8c2a4ca2e594de81dc168bd2a6db2eddd018808e5a37d8463b0b4047a1698e25cb558503ad2cf3e6f344c95ae19fa1d615709164453d7100c39fd3e64058940fe414816fa9a3389968ac16d244a67740bd32219993a2e4c0cd9221f43748ef5d6af3afcea8add791e382bf5834659e67f0d4ae89e3418ea270727b4df5fabc9d85b5c58bdc7fee0801c33caed5949dbdbc469e0b6d90a191bed22fd4a4f8c76eed69becf91ef53c828f58d5db22d69b82403ffd0130d097cd0e93ebc4c89668fc73f3c9d45bcb6968a66e1d400004588bf39e2b2b79b9613d67d89380a3773edc4ed1a5431ba7e4ff994d3b5f186ecbc73834749025a3c084f9a81291bc6ac89671e5ca374b09a8b2e987ba2c92b09bc8e32ccdd6d575df9471bfe18aef822ace9d57c1aa45b8603dc3a6b6a19963e8001faace675109f97ef29fab7e831396586098cd194b32fa56fa0de927a0ca8e2a51c8aa1e80bba3e391a0a516738c18d050cf9cc63e26f4b03ddc8e6165f903a3ba43fec22e3cb71b66e7ebdc75045c663133a3f4f0d85d05bbabd87d68dcbb62897121e6431faf747d2bbc341a98732f9fca8cf4abae1c8ad3863e27828b9daf4003a13d704d07a5c4803d34b48b078530de502f16e50c65a979fa5d1ae38bc2d2f7b07885409afd302aa185ef98202e9fab102a258ec1ebcf8a6db3dea579ca2ab5214e7803af7af64c7bf89332ef8041a2c9f973cdcdda215df3521a5d17e69b64661ea805fe2f12e3be5ca970c1a7cdc30f5b2f063601667c5c8ee343bc0e0ff683675881c6154bd0190ecc61f99c2ff23c5669b4bb2246f7a1372bd6f848b0aec2044180b9a57955ea3cc619f423544c80a32c3e3477e0712d9cc163c3296818ebe447da0280d65a706b327dec589031b396c58c312d9320b753054839ce6a375ba6e3fe31fc79f1e7c31583cc1fb32ad5c28f43de328af321131868861da1307f395d7ade9b9688e79a835f2e58c42525f42e1dd861f222e92189529bb946c575d888d369b1222d8674fe74242461e7ae36db492330e03e08610fd9d4129744842f7c4844ccc8773dbe414decb178fbe43b2bd7190931befddd3cb69d95edc889b2d593f501cc55bd97fe542727c1812461c873adb21b1c706eb9a7b5f2f0a69cb6eec50490d1d368edc8bb6ba2d7586fcca4f5a6a1eb3abb18775b9fe9d4de2e63db7aea2b63b86d95446f77be0b9934d7325d6f88e516bb48a9b8cd4250ea63f8c3af8d315453fdb7eefed59b4f1bde267fd216ca5ad18db6ffe5b0342b20aea568fe55ad098e822933817c52d5917a9876a1e600a4619503988ec47b5ce1abc575d4ebec3762a4a9c1b335cf24831935313a9b02cc1dcb3421e48360ce06c46c666c2f9c1a7d03744e4d24e4dcbba35bb9f9beeba61c5a9412da4e7699144c5f4200e35244cf70a2b1441cb2070b965b031bbc04572fe85524c38a5b723cd43e39a93b87fbdd57561a2f3591be6adefe1e11a4ce0a21517e646d51286ae128f5cb2fab8bbd2572a8a97dfba8fdee241fd889bde1e32a6bc9b887c57b41b0cae7f9e5303e0d1c25e36cd669b5cce6aae4d5001235d1b80dc631a5cdb0649573fb842950b42bc8e113677b94059ed169aa99bd82d86c6719af285d71dad110a4003697b0c876cb36b499228a12ea66abb5d7cdc506dc7eff1476a425c3c806a8dc5ba68532ea8038219747600eb2a816d0ee0f37ad9f4ecf27085e8250c0a5cfdbb8613b71215b1f9c36ca949d3526d398e57b20ded2e77bca9b58fa21897c5b9186378b9a7daf90275bed0028b17427c9e84bddb684091743094add181b7e1d37958b0efd40edbae350a66b23d78dbab1e8bba7b9048eb79999f9d7d03b332fd3811cedfbfe2b4af95a3f4b6e997fc403e65d5d524e403eeb7f422b15c5d2f9c9bbeef1153a076eafdf2800f6157fba54b4bbe568c9e1900cdb128d74e993fe2a65ae5e311426083815233d25b1eb4af21f3d40d16576bc2782ca545306b820dec7d6109c8e73f5867f4be31f38226250d5242de88ad54824299971341efb5790a083d56c04c23bd8738649f1abceaac563ef09e1ea64d780c9cd782abd4f95d2184dd2ff159735f96a27f26c15d089ec4f07f38611eeec5cc922c434dc888e6573942aa221382fd2080ca6e89afe1a2090e00c17dbf69c40673619db38cd20c6bc7c9b6f9d4e96f9f3fd8247fc74ceffb5b180867f667173f5e2859b3a830072fb3430fb06e1800dacb9d98790cb81abe8536ae3a10b3bdbfec1d5f8d7149095a9572f90f2fa7aedae02d9231ae0ee40a649192f190261016f386b8f4c878136bc6d5f6d631f4924c88cc3f1543c3c4ab9bc3f6b646fff4a803b4e2ba04265a12cf6745288fde4441a2c8f740d715efb775039d9ff5b7465708bf1d39a2b24d0bb0cf021ab78ef6f00eae1f635bbef5d4013074d1a8a1af632e7e24db923d8bfdcdcd579e6665b08ace019241c9c06cd6f4dc4466ed6d124a88eb440c923139953a4f9adc3ea4347bafe7c181f7df3d696d81e99ebc873c949c48a922aa4e359ee092b84d82a4b1848fe019c13ac630a79725027fa1f4eeaefedde826e3b6fedd9b7fbe8beed1f7e560fe4486d7c4bb19669e0dca7d31117a1b2a1f1b428c0daaccc84aa16b8f19754a7bac74dc0df9eaf7a9763ef6dea9d86093c627166f2b4fd2939fde81f51342b7b3990b5a1666d58dee542aadae4e5baf12874a4e4499f5475efae89164ab73775cd133560bb9718700a1973bad5704856ec3a1bfe41cd218e90345e68020fa2a561a1c23b7905a00c7dcc1d471da9a3cd360aad7b12f465dcdcef4ee8512873b3e7b68688487737b02c3368be84a6a8e2643dc0503051142f980273a19dad9c9f940a2734887db7d74384a182db8924c125e7fce19e6197d9803b724aed1e99154c7776b6cf95ba571d20fc5e670c2d7ce6c0cc4742ac8e25e6b2fa89664c72aafcfa6a2810b2dddbaa4d83d119cd9fd53f5e5851eccc78eed86dc52aca0072a615077d393d6c89f147758885f62de071f476872f3da343a5bfd5a772e4c29eed726285b00ffdf19a310f23016b6e0c5922fc7c4ceeaf579072946af901cdd41ea3d8df4af3689dae90f0660a224e5e46503dbe8d02c3953bc0456977d20e7769c656be321472090431d4a67cad40f0c2a1a17b68436cb407b5c58ca94c4c35f3de5a9037685be801c6e4b82aea79c12f2d401f94c3b4eb8ae9ec447315307b6aac08909aaf1d243a55117ac1ac8b6da80d5174a317bb272155177709c6460b086f5c9e3d5a5468b410c423aca339d4037481382d8518fd6ed50b7e4f44b11ddd9df716e7d1583a3c1781ba372cad7bce9f94994960af770836452d2b92dc7ebca87cd679f9f3a05f81a62fcce4d908bf01a95d0e0e5e7a397b72c70f4c904a37bae3ebc140e8c0666057a53e88e52e584c800f29e4cff349e3f2c2bd38baefccc788c4dc28b0f8179155d70f1a78bd268d979f120ed660102b42981e9d7832fe5b7039d13c7b7f1d43040135837249c4b7637918eb2e9154d0f6b7bc40483cfb90f99b14a3357d63994de7d8e223ff6386247d8738c6ff4e39ae760285867820016cf5faf778eaad2f6cb81d1f34769824c6b26fee2620bd3e4af145f1080f6d642ae201c7ab6d4cd3222aa48f61210594b0e4a42d759a9abab4f290708416bc62e2d40748e73bf40b48f2af8d15a6a7116c8b50c3b349abc94f76f71d6db5d1e43c912af8cba16f9957ab581b055adec250652454d9c5e710e53110964582958df19adff42b63250b354e80741ca0a85bbf15e648aa130aeebfafdbea76d3c431c7bbaf82bd4d341e76e9ea1fdb32664b7c017c5c14fdbf53d50f10f3a61527ec4f1bbcbfcd674e667bdf386c6f7c29ba436584c186187ca7f6c79ce1fa5fdce207123892fb99972b4c2cbe2020d501b6a1f4de73a542b87a25933d3d2a39d8216e63dbae2dc99311121c198456e8b8b904a4d38d072c73e631ab326e510ceaa3748e7f286380412d9be74978f822b35e5f38255543f0d620f82a1759f97c6a6927e4e43da9dd81417c1337dfbfb0a4b266cbe8c5ea0b43efd63b476d20abf141f5b604f6ef27d353b2cbc8e909a7df2f185bf993392cf785f93cb4d1662214dc7c668f952bdf1a1494be9540e2c767209936fdde5975f58d85606aca68950431a6f7d85f272ee7e508ea35cd2a474348fa0457e199cbc972b2e381d315e3ef7efd8b41a3055f9f46ce0abaf0b3c108b17b1a8fca50b9a131e6fcf5bffc9da113f1d5658d3eee0baa7013ee0be477c7ce9a51d124ba176541127fd8c27121c6dd357b8f0c61cdee1594d22dcae3d789e8c35298edcb615b4232169848cf9ce8c040d5fcd810c9df34cf1bbdfed497353840ef7ce43c128acf9a08b1fbd9bd4679b01eb16ae5bf931f4b9b9a53f37dbb96da1f2411f0dd4f13b4b370f3b650514b15850930de0c206329488c888879809709cbb67d3da86030ecca41a8fc3abeb6fdbc49bd37f8475e49885ad530eeb0c24b2404408696bccb11d05045c7b6ac36a08ae42f6a613c54837bf092fb8cbcbbeae85ec4abbbbddfd40021d5bbe99217bfa9770d2e93ba5e8996298cf6d843274dbf9428fd72feaffa3b20dded6ec92bd8e59f80adc1646cf5146033865f4eb85792d6a91c1b35d3e3e2b1f7ba96ff6c53884359b6236d566420f73a6e6f1f2c6e04c2f5c4916df95ed51d77479859d8809160a5016e43892933c4ba2545819d84a802d0aa220f498b496b600e83a9244663e3b382e9e1d8360240cba91b1dad464a04bfff04b1563f47a891aae3e5db1721358ba22b97d81e1482b3b423f1792b65b83440e472e9a246d48fdeb7b56705cb90f6a20a0cb5eccce4b872ab8452bba6a80ca514201deed30c10e9f4efed9a5bf735e9e6f771ec3ed220cc994d4e494a9347a8661ccc8900acf3f10cd6a1ca26b3304a544b7c7285379fe0d9b0077320a20bea8f21642eafa4fe5559ba62cea54c4a247734209aee7b8b41a6582a237cc30158df83c5486ca82fc881a644b110f0f04a4038b7184e951146efd3d0223fa306e526de35c9284236bf3231bbd229ac512c850ed995f7de7cc8241aff537b846d448e84941d0bd0c796a65a64bf20b4392b279ed74ce9af8bdef26c8194347732e470073f011a27f32e429fbe00ea237c41b85f89b2b839df12b3d575fd45c1501ce68452be791dfd481a40a976f8a05052c108e1e8ed2fc1489b993ca0e4b633304961c3b84d0f4a2223ecf68785d5f789eb8c532a0c52f6df0b651b96e3528c29b469a245bc4c0be280910a562487e63562afe344c5809dc3660b7d5e34767d185cfb16a53b9eb63f9d8229fe73bdcc6a3929161167aaf89e58fc2e5702b45bad99cd7e88a1d755bbac79cffb3f063520c577dc9a1fed3c201ca767d66a196cf31e4fe4fc33ce04d9a32224dff0c3f5afc732c5417e54c796b4126db25a4d5356d68a939d9ff9e37f446e98e638c147bf9c2fa3d859697ecbc29e1ee600355a3ef6dda8e809e8f94fd07717216a4063def1802192e6d36ffeb523ee155cede0932f5c833b5b82064a0eaeb828fb48c3ba6916f6d23e68b441819b8f4dbcd40df0e346cd0076c1b9a2ffdb930454759905babf1f751f6cf9575deb87e01e515754ffae70601ea631573fb0a468c5e93b94b7ff7669e326e65ab25e357f22c2962696d25731cf9ab7c594733d917fff69ebf921656062f936a38f8883061077732936e916c26423473df05cb0684c87ec86b3edb42b27cfd877c4a409f34949bb7b7cba110f8d02b9c16ba2e5e47fd2c88bca29f7a5757510496810f746df0fec32734ea13f33a170cea6254a51159b05381b46a46678d0bd0910d84a2242f72600122c5c24a9f6e7430a95bd20b060b2e62cc287d47bb4e7772808eacc084e069140fc5e83d2a837ee30755830cf2e8ed0f1cdfe212b17cf705df210f046d7e1e1a54b8e9b14e5e4e05266a1d4564916d6641a49c540cc275c98358f2e2e6ab41f41b66abce76188f91c62cbacb1584236d82642c6bc07a85409a8f16b006af7aa8e06534322b618e2ac364c671cc5b779e3292ae6ea33f045706c361b440914e0f57e7c52aa6fafcae330d27a4511e2b4656cc282b003f0e33af05aca2f97374361bc121bc702f2acc530bb8e8e67fd1f50ed595eb273c2606fc46613f930b6047d7250eab41f17a36b30f2c3e8c67af2ae731d4fe623b3215161203a3afb03dcb86111fcf56bb2d659d1be0b567ebd06f45837f2542537ccd6f4cf7c4a67cae921c4a98335b641e8ff9016e2edf18b57298a294ddeeda4f1bfd8802102c90c54374c9f0d264272e6073551a71b9cc00216199bf29785a812558a6e6c269884be63faef05c04fd03949053e361d6c4c2ff40d36c544f2402fe5497585c8edeef4906969d61dd18a350523ca6eb96fa9916fff58449c0e8c53e20d46279d7c01c16f04fc806d89c9a67c14cf7a7d45874daf751c985047dc59b9b1dd9e0e7c1dd8a6bcb9ca2eeb940f86c9b78334911075e88c979c9d813d0f692d73eed0df839271a4954de6b5cebd83c150979fb1adbe15320003be166bdd6a02adb12849bce088bd7da5c775bbf5a66c062a0271fe7de56dace701578542390b393667f45e904d6bb1eaf241aef406557b6cb8bfac573b8efeba817265b67a0dc8d284ecd0693c56dc683380243296fdc041b41949185a1426f2949e674e482098135a2cd508d3c722ee25c8193dde180c1b8a8d5af962a1c7cbb08862de930632f028fd02e3c0d20ddf204779d6d2574dd5d8d15e23760b1a89bf276137b8827b5728b51d72fa40c6ed81f2bc9640b916a5e6a85457d4829a95e1517bae6b856936260d77c4d53309fb0c75439d37aa4dcbef85440b5d16f922043a7d9b8227f8762acbbed62c0d8df79a313571bb5c900458b9adf39ea455aea26fcd704af5242a243e45e17578c0b455f168d53bd3ac47ba33b3adf08f6eee7a69166316596d999a6959cc2d7d00ed080916a6458c943947edc8d839e323d7f2ed49c2473147db8840fa0b806a26c8d00751361edb4579f9e5a0924b978b37276d1e16109d5ce5890758063fc3c557b69f695eb7d432af97383fa5238d8a28294a0dfdc48a52aa01a4a6c483562641ed4d4a0813ec9355ce2e86113afd9a0443548e9599ca9d82bfc44019ae9d0e9118990fc6ac9a3ff0a8a77856c867b00f2f5499cb60c1f79c4f6bb4cdf59a396490baf0838cac36ed4b657de97bc69363bc064a9458512c5a563446ef82100958a3f29243a7a183f3ef74b25e6831ed51d3ccda91d881e17cd6a11076554eb5271d98b0a4a211eb13ce67d3f0a7e82f148c1d68be812021608cecb1b21c1622c74fdf54dd9560cbacd4254f0842beacbccdcaa9ca5d4bf4944d0b0f829da84e438a06096f19d10bc985e4fd79e2f82afaf05b2850d902cedeb8587e94cabef3408eb816bc29330b810ad200d73419fbd34b890393ac34e8a5b8169d34c251ff9b176e09002757b847c061e35ee2bf3644cf3e235c0da0f20068c644c9cf218c76e563ef3da6eab0bc5b37b417f95b6611f877b21072dc9cb51d26c836287195095d659492c0b87a01013b3762ce768764191c7de3ba43e84695833566ee7c1ea4b2854cd9477c3eb0abdcd6f55f8ec6bb844d228672ecdc5f36476e00621a168fc6ffa6296368ec4a46e934d69ba19d8428f162d9cccf977d00baed34921c318e5e4f4f3fceccf879ae0bc026b8520ad12476569e60bdd4806dcc68f47b61e89dccdffc5f6c1c782f729fdaf08565f7618b3a3dc2123eaf8f07d011e14aa6fee3e91e9af56091319fd4a7785d9c1a345011a7545b0491cc8af3588b7fa16c4c4193fd1f14116aab208a395784655d9a522a58f622f9cc2aa89221672660428409593a6215b305d641d9118506f94e516b6b267ea13c6f4dee2fb2186b3c8586a2704e429a35a950097f2856074ac0ea46bf85b9effe982b976203433d74405787d541d8360209c9f205bd7d015f00537fd3413a7b4a4f50b012b4166a2c6491a03c04c4c660d49faa9218abd1ac2c56770c67c8c682f64ab4404f8cc1295f6ee2aff2374e69e3696458dbf99f96aa875c3dbe4955ff55a1db25c2f27f1bfc3a312bb5e286b941c32c22e7558d333dc914da107cdb074d84c1be861dcae173c37d18d668fcc46f70aaf7ad0438859893798f35a5553dd9098aa1b66577583475a75131723e3733d9617366e33659aad3c65990427234a9c542381f7c947168b0e8c455fc470cd37ee3f90caa3ad7b4597f7114780c369d2e3989bb0a8b582cf10af6b572d16df405637c91316c1064b8b35002f42bb8bf9363c3b7ddfc6ee64693b9bdaf24f89fb98a4e8321fd906e0c970771af922bdfc9958065da479d7c221f9bdbd3a66c4e9ce6be55d5ad9567c4eef2e12a6cc22d9162cc6409bbaa559c8e56a2b6ae3bc2165eb243b5a66e235db286e2af9c5ba4cafdece48d46c1b8a0c1612017c4c04ec9481a61a60a4e589918f14317d4d83def2c2903cd8e1491d7f091468970210872bdfa0927467f6970dd84537144363fb5922709cb95de0b613110e9573e4aa5b119d308e36720356c605b8abec27ccd87045f5540208489d95984b2104d7d84d28accc5a74bb0ce62d1a017f7eb77ef2f4efe3b8e51a66325fcef5c1a75baecc618761b11a32ad41c63714f23712258187a607efd529801a7014b97024d57a015f3a8501deb017b929411b419af2f8605196c1d48556db2f66f79ea6f455b7a24551f83660621d50feddab72653c4805c29b6881ba9186df1be52099d59914b3a2511d828afd53bf4b83f1f837574bbcbcbb236396460531c7dbfa80607dd6446e75c560db6838d97f33b8ec92c01c981faf6b109b38ee38e2977a70473ae3b85ff370d0b9bb19f388906725e8ccb4b96c8f8ba7cd42998d96c0173dac32fb5780cfc2cdd602c5d452d80d630afb57a6ede7121eef080a4d234321d2e3def2a8a83b9075b9802ed6392c443b923829517c8054d342744fff3532726f4ed349a111059021e081bb01079f4e74695592b7047b23035d6c86da5f093c7a8e615b1bfff089ee4b3b68ca1d39a6ee540f87f0f443dc4cd372dded616360bd6c4a091713a4fd1f3acda800f0475abe2c034a1191bdfee56e7639cf2e19edf252473fdf86bc5a597de0b081c125eeeaa11def2839452d8112811e3db2dd33154a6ad1f966e9d3755aa9d8d1cf2d225526f4ff708cb2f88b45747c618be60780c51980236db887f4ebe6af21f3672ef98f6c817c7a2688284ec79e76032212806e0f4f40721800edafee1bc63687ece56be3e4b9d647380124bc2d56c2b67580f96dd14a951900f44f019e3aaaf5fb58f16417945b316bfb5441ffb11b3c9493607f17d3561ea5ca665a1f471b5a6e23bea17e5e9f89e19d3b4a74fcffaf3d89f6b091e36a0b09998706601215009ee89da70dd486f785fd07d37340a4c997d072f0196793fe4bf85942ace5dbb5f06a47b7de18bd6a9304d1aeaa092bd0db722558d678f7141b75126a70ccc68afc0640f4fb922ffa59c5f761c42312552f334500b3855740a91e420fe22e22fa4ebbe9813e8a45be37246e099e62891de04f9286d274722c993ae899bb85fd2ba593dc0dba65420b3be21071f53742b9bd26126374b437511f655e05276bc03ddf07f0f5e67ba3bbce5b61bebaf22baa65f9d298386f3ad40b0093851456b8dc303ae9e17443056a7527389cb8bbfbf4e973cee93fe79cee5fddeb0da89e6e9072c3d10d3b54a0dc8082932e35a324376cb9e1614ea8dc70c3c98f4f315245796e48e2c9941d484d6e207292d4748070a890ba0391c60fcd1051751260c01890c3188421b86108108481087e84608720621002b61fbe60187baa276eaaf52b54c817e2a07e918a50188b8e321844858da70c7a83d9254052ba14a3e29379b03c93cee96f607c57e5eaf421c4a6af1322f54400e221f64402d7458f2d61bd5a1b31f01c6ae0de424369a5d69d6ab45dfa5f6655a7a6237ebf524731ac1792d5a5a9208c89bef1fd7a2aa223a81a5fa0a9e8630d0654c8854055700452911b9fabf90aa56216e7c156a8b071076b2a0663c3181833f9c6f8e5a9d8a353e157a3627bb18d91d21250bf928a138963e7eb46851ee760820a6b2f8eae98ecc7417c4985a0c278a98206ca15be948a60fceee257a508b31d5e007f24cdc50ec0d7a9008c35182b386c3007153696c19c8ac0d85fe22e1ddcba03daceea9656204a6a940e3d7545ea3345046f03ff95efa2b7a6a78d9cd363897591e115ea33a7a83e9e407958e0b870fc97dea2146d5b31aa5bc60c47faad9c23eedb924763dd01459cbc8a236942e19784ecbdf7967b4b29539201d608530b80086dbb0946d8b690e9ff6bdb51af3e9da255f56d1deda724c5a56f2b28a349d99d6dd1bead7db932c6d390e91f84c6c0fbfa129037baaf3f019984bfce7eb44a14d85ff1589c9266df13a9689f02d1fe4cb4df89f933edc6efbdee616fffdb380b000a7038c66f25a65dd77500fb0e17e9b7dfd47f394f7ceb5bdc2a268a9e0800d1df38ad3e05a2c7716bedb72776feac1414264ce8149d6292ebd3294fc2af34fbfaf48a27b9b0a257b48a6ea161289a5c1fd3295a855275b8c3f11804ec2f42b3fd21b06c718b7f8b8b74ee4bf40dd5514c46984af4691e5591cb034f6a3c7a5fd7243e91cef83d9cd9dc913ebd11451a85450ad581552a9df2a3fa32945cee8d1e4647a57aaa725f6b9dd5a87e66739bfaef37d128a7d527d2994239adcaaeb9be11ef67a25ff951adca2c7e743b2d55bf133bea49ac63e7093c3c82d3ea7f8c7ff1453f82114f924931be7e43d95082c7e12fd22a94ca6995863d427d7b670c4ca79c56dfe861fc48a790d81fc1935cd4b003d9dbdfc21eb21fc1935c7c7d23fd246ff490bdedbe48e70e8f43a2cc138832c3108d8a5e88d2692e6422751afd162296d94b208e771347caa27e4c1c41227194d55f218ac00d895724d2198639705a7d105e78b435ac607d1e536986a51fd1afd2a577bdeb7b4d3ecd8ae114fcf06d214ca5160f7e2dc49647f32510e7b310e9d0755afdfb444fb9dfb29c4bf45836f4c9a167eecb58b77193793d27f6bfc41ddcb78ef935e420d4416793f1a419fef68e64fbd86bdb9ec8ed7d75218766f3b6b12823a9994fe5edab9ddf526d25528c8888e8efcf0ec227c2453ac7f0c87dd3c771f48f54b6d6dbc4b45610c1361cfb421194348f0267d733c82c170de9cc7d119afb87c072ff1676107ee3229db99794d3362098fbedbfaed3e18eb470fbda54ea2b3fdafe65b2bb3519a76d2f83caad39edebd3d19fae905162f1db7b14134f82e2553c298e2771b236d7d16c3fda98da92b72a0fa80cc525499b4fc74ab6a18a53854371c969369c36bdece68ef48ba03079fb4683f5658b49defefbc0c9417914ae396d620ac8ae74baeca7b9f148c2f42779e38a27cd0f01847d30d8b7d8b8e6b4c61458218e6d416e68e82596973c996edbb68570652b7e7b1c338685c5c344113a8ffe94b77f89443a8758034e0b6103b7f1667981a9c40253a013a907f33d0be613dcf9fe935f83dff85906f12499bf1f6183ef7df86af9fbecf77250fe0871e0945be4b0bcc4c9f24f96585db4f2d7a1a54ea3d469cd8d36723f0d992cb631dbabacf669b6587effbde48662585dbeaf1978d2787178d26be049fedff390b2a944e5513f68639fd1e7b2fcbdcbfeb66fbd1fe51b1ef2c6ccdf73e049f3bfafa332eebfefe5ecc34dfd84c5054d7e91251617aa5c65ffd6c1e7be324cb8d469dd2d8f1c4b0d5da6a47089f34d302b9665943543b2832e252483faca24cba8ec4fff78d654eab83aaeacacacac8e9007c56342c783b2d311f29e8c6476e8c8b29cd6548ba2b9b4e39a47feded3bdb22ad5714d25aae547fefd4e3b2ea71d97d3aee3a27d28213a88fed9f179f6d98a8979884bb1f4fef926cfab3cbe8c2577fc3cb58ec8dc91765cd993bc4dd6d240de7079c3e50daf72256f78d496ac41f2864fc91b2e6f7896dae02857324ef399d36853b5bb943573daec0600240d51d6f0972fa3854be733f8f74a06a94a5529a32a15ab5255ca8f7ce64a5266f0d8bf863bbe842a59d62981491e3b2e245ae156678c87bcb9873b52293a5d767d51115509cafe5528cd93bdca8b6cc4ad50f268f3b4711af5a48dce3a736cb416679b7087cd14cf2ba7f9cb70e1da3eb67a9ef75be4395e79345fd2a6eca69f69d350d056e59b2f3b7b63e02fbf31f0fc0014fa740d3963c07865b9b91316217c3c40286f3f1639e3eededdeddeee2e80d7e854d5b5d121e3ccc9d28d20f9068b8b54b61fea904df8c9dbd350873c024dde9e082b7aa838e28cccb345de915865a49c39f2ce08f44cb18098193d0520a2004bb8d7b8810e3148395835b0684de4ed319f1834d09878a1046bc8851822601a227178429289788f58763c76800eb7711bb771b5d718c29aa11692f4e48d863bbe3f3a6c1079fb4f6e9bf71a3d90c515a1638bb2a34ed131c9e40d4ade1460ebe4ad863be6156b396b2d6739ce5a8ee3acb59c6dacd7981530c728007695b7b7e10637f2f64db353a9ca23ff3086a4216bc81a8e474eca1ad6bf36cdb2c5487aae63113e735f75589087c8ae2af2f6be63c49913a1c896ed13f12108a0519f730538650fc83211d9068e2928db3c25c933a62bb16aa093e9d7d9c83dfdfa2fb29fcb39c517fbcbdcd986753e2916f590f9ab60a55ca593fa9c734ab1a93f4ed1f673dbbebbbf226b41a425d996dba8addbb66dfef43ff0a71e3642dfbfc3462693af63b82f2d74b0b4c041a3c58b16aa2c57626991ca02857f1ba02c7d32105859e8c8e142e8fb24d6f149b720864ffa273bce9baa2b504f5a79d0909982324850569c2d5551507db4aed05499e21a4427ab86f4c7bf3b64ca8ab3a58a42f5d1ba4233ab700da29365b5c59978d4569f36574dd5550871d19191c2f59aa44193217f763339b67124c3c995f555b4010930299f94948a5621c465874e18ab293599fcd97ad3e68a53f913a13c76c88469282d2528888cc363f6c948e1caae673ea9544709549675a0aa2ac8b24e12429e345dcc9e4620d71583b29003a70e6bb28a6334261d4b2ac3277df4a143a84deeba6957599336af647f6448b979f2d85aaea524c5059de636bbc85d736bd5ae161dda1ad282b29434c6f6933be89e6a7912f7be256fc81eddd3b7df51b14867cb613b0595f96444ddae95ba981aa44e232448be8cbe912715d19f4eb7a66236e276c834dbb387f3377144ca5da7fee4fe427794511953ee48f352924b9ba9df1b3f1e9768f2c690ceb4269b19c9e742a66e3aabb7dce8d34cf148820addc9367325561734b9fbcf1fccfee8a2db721eb6edb211b77b1b32711dd740e40dcf96035269490a4abe62225b6bed8f8d6473b1450d38cd620ad021d069f6abfda5d18ed6b970c7e7aefb4ffa10e8342edb0fe249f3392ce0db8fb9b54ff31ab646d9e259b648d97e536d855c64f983145502ed8981caa097e1caab26dae4ab27b676d05c5ef808f7dd4fb148e2a21017c9cff1e10fecd33f427191c435a779bf348fbc59965bf43df771103832c75af6b8f770935c427e7d08484a6553371e5010bae5536c44d237d2fdf29d72f4055afe3cfc6b4b548a4351c8b2960e4296822c312164c972561422daef82885f57abb8d695ba1322660e37d12e5289d428ac2d52b92964969bc0c9bda5dfd5b82ef75fdf7650a473632a649637dc44bf6230856f04837857d95fba5883e20af1ae32c54d1337392e01479c29f3f92e93320d7c8238684cff7e8a63adbd5726fba7d16ab53ccaf2d2129305490770438386a4617f8a967adf874799ccc3b56239b936639829a64e03714f9047e6b9000b0bc329c80d8292467f96b78453c53ca95f0cbaddf24d9825ea5435c22c4d3a5999e60fe6a38dec7decfbeeeeeed9753b7f9fd8d9136d6419ea186532bfe085cae1d6e2f15e99ec7fd63a2b874c3488a4e15f834b06d5052544147a610d1e297eb404c240171af04891f3c211503ff4fc98f2834515c70d181fac004d61ed6025490b3b5c3d01998008ae8620f3860956abe9b1c40b5661a43841288c0b7aae7ed872441a3e7fc84c6d519102072a5f8014e0ce0d50a41043460f15253e1813f582941b1bacfcf131850d9f32649ee03a639320420a90150b770a5155a9a3449ead14903ccdb17e2aa045cc9c255c02714539616b4a1b1fa65a18a26a2b4a146eea84e91a225015201c9441a3c218282c2a6c4122b6040e9f3f48e24481460615424ff0305941891b7b44075896606305c9172778f081844b8e9f207a78810918ac1147599e206307871562c06206aa091efce031e289e610a5844a203d73921402b2ad3026cb843550e030031e1dfa386df141abcc1d364a06d10162066acf1327a04972854c1148fa30890283952692fc6843c49c21968062cd98273e4f9e7670c3041aae27c6b0405327cf160e53434cd9b334f524a84ba11d8c00e4a30f57151c2e3f044103212d164b04f1441515345f7cf8138750117c00ede08225424e0b5b2c389146cb0c0e40aa2042cc953957dc2cd1a3c78b172d37c839c3268b1240560ca2028a9a2f4c2ca96104554870c0c18b0c54dcf9b18547892a4e7208040550e3304412384ac8704159d90324a985386a9edce0820e29e471ead2044e116b9c9c60e5e40509da03c4923d46b0c1c3831049aab2689132e5cd943d2ce0d08298292e280cc1a70c0c4294f1b2041c1a2f6cb9ba93c3132af2dc9162cc15ac24453821052109a2ace2e83102100d4bec3c290305104c5460a2901c0000daa1891333fc7043109d46831eb0a8a92384151c02ddb983e50a950d43684d9955fec8c044ea0f15415c7400b227062dae30625ef0418819a63081a1d00d83d450d143cd0b280cd252c84f1b3b630476ea58c10288871f7c10926242171a2850a460a18e9d2d40d080a7093d44c00122076581e2091f700044678d07d1c2891b2c535c05d1054e92209e88400452505ca0e80e40b2a2283923454f145498002167073e7ff698e943e7481a2e4ad0407581d367db0148122552cee880670a2a0a081f777e70c1872b774a68f3ea61047874a022850f95fd4109354738b9926213c6078d1c4a7052051a289e18e383d6962e1eace080e40a9f0ba4a801cc1a2d506cfa64bdb1128513564a602551c6043349f460f1c305500e76ce076f0a29496347092b5e7e5459196444971050484cc18240932d490ca2420c201b7e6c4d00e9401329516c4913050629e4dcb062068e1070e068b1b1e1470f422c7992650910535871a4e628c1e70d1933492401e41aa1254f9a3a4d34f1c56d0f42b6207142541329292cf848428a4025cc0067061efcf49a21366ce2f82113c70c0cb3850ee84c61a7cb0c43ac00050f439e50014686334f30a9c2879e4048fc00c40a55bcf0050eb843154dc4f8c12225a7490f63da6831c20a0a9437960a8a0f431471821e263a2b3f74c69099a1ca9e1d02253922051d6840814b9516664013c889a0428508593745c41046100c6b4e789203a4cc1155d21402d3650a2f3ac0d8a2849d412c8871610bd5f2044316159b364ab46101072758b85089e903050a1c252be4d0458d09960d0382e81267890e697af0f2c3c91a3f82d0c08082191c68144f688591218624f2e09903e40a134ff6fc8064892d390052c3870b9541223882eac70b80a892dc50c54bd50a388cf98245cbcf191124e902f269217184931bb268b1e10a8322e6b079f264cb8d161f51459450e8496b054153d644000917b8d2ccd9b3e7ce0f0a5600c24e9c1e8478b262d578e0843e80888052e64f1d1f0e3813a689541518ca98a12b845a604c382206139ad840039a142143a127c0b059429dd0c04cd50c3518f18402950f1ac270818288264db26cb06924d7115dfc747121cf1428a7335855ccc961071bf6e84193c60f9e126a28a14fa142406aa012870a0d48f830a162cf18604d0d3524c9d2c29c273f68dc9902a6cd99398578307381416500b500c49a1bc0f8c8f3c3698998285200c2cf923c56fa4a0bd4551b3c264c8d800a2e13cecc41a38296327d6c19273356528298d2d503143976ae5069814fd50e56b42c19a63c764ae8634505191f477698e233821f96ecd065c7d8c822c41077a874f1f285859f1952981233a544d4f6c30f1ab034f1439504cf9d1b762cc18a228b55550a537cbc680250559799276e5010e3264e1829fc7839b325cc8fd89a2853534831a1cd9b30370a2d6ed858d990c64e04deb890248e134468e962c140c0c99715906811420a8f949baa4150f89026ca1e6b8304a8f0738508395fe6c0e045f8d032c5091263fc6c71a933bb80fc58820c0a35d4d9f342962f5ac63cf1b0c21a255b757e64c00426a25062c21159aab0da9202a50741583f3889f263e4a2439620608072c58b17a727aa29e4acd9720288259c6698e2ce141b84887a628dedd26304666488028d151425ace429b4f507082583f070696a33e50ed6184037f4f9c1c19695142290507206cd96a4a8ad13c6f499a2cb071f47523cb53015a609992c5b039e4154628c10c286207c98539c528062a50d9f13b0743863b5404049951e3e4d9e6c699343befc81e404892f3bac7026cd106eb35cd0b5060c1059c2d0b0c5876f71fa656ea8e8e2421362a202b1a1c2b7640f4de40153f5b4c3133d406c95d3131ffa305104d70b56ae36212678226a08404af8e86141f609428d9c3b5151a0a8e227853c2a10c1248a931228979312aa3c5370bdb0e5294b833a348c9181d09219465084152e7bcaa8d1e3678dc592a1a8e20915549c0064056ad0d31077e444c9c14f12a9278824415cd97235680559e8cc9592262290418a13c69ce9210c943242acc9d1364b382de47e695db6992d4c4b0355972b3d4be450c64a8ed62346047ce658b9d2849a6944e62587257290f0cac1a36ae0ca418200a4a8012207fd291a9173729020dde4a0984b51bf53eea9a40527545630d22cfc119483045a0c5b5410270a513f60d1ca61444ea1872b07095486b6d24a3c2f381194638a9f9c1c2e7626c19ddafde93671471b18dc515e81c083029e64b16c1894fd35a875d26d9a77ddd0f8ca0e9347fe9211e5f270da0b870634d4d0266fef7fc5026c5d19321de970631b0f77ac65cfc09324560d7464db8ff2a7e859bed12c6ff8869e7146df7fdbb60d8f14bf0ccd7d7943047995e50d118ad85c9fc8963d6f737ee7ad070272c543645757a698058ee3c4a128977baf2092ecd8f5d497b9fef6453a6f75f44cc2551374b20c37702aca76c2a359b9cebe9948c29dfd27c3c91d25d74ce4e23979df851c3865af65683f99e7dccf822378df775354dcd1df510ec7a453553e501f09a5547e549f92c9f5311e65b25ba95ccfe3b4fa6ee7b79fafa4d4f2087feda0f0e34e1cc188f81f905f7f842ad5df22b928e47a6b1545d840cc1ea6390d3f8bffa4d8795847dbc7df33a7e1ff2608b683f85bf4c4a7118c38adbe8c17eef7db8f6e0763698740a77ddb7f2cecd0751a935cc5173196d9b3103b53265276acbd5726fba7d166f893bd95bd7d1add6637d9b66d2eeb2b7baf0cc41fad86fb39ec4f32dc51728d30dfdad943de4dd1dd4703413c09c46367f061433f247ab50cfef7df276ac089db19fc51f631c2e583f0afb4b6f3bc877df88effbef07bf89d66556d632b50070ed700909f4aafd7ebf52f4cc2fd2338702d8479e4ff7d3e02f6e18ff20a73e98761398f42ecc13cca4a64317d2f311443a85eaba059f1386bfc1c062bfedc2ab99abdf0d8f9d5c25a5ad18f4bd9b2b0af812bb5d1e3f0a4ee6dec8b6077e85b88721ead780944398f88a4f0eb6bbda084dbf9f5e32c87cf0213e18b61586a8976d8793f7a955b7baf4cf6e1b49d9db848d2272d2dadd748a92c265ea7c9385bad7529d7d720897b1cf5ca936ad3ab2688973e3c2ed53c3cd6bc8a96477975559543fe17725829864b9d8b4b4acab9a4bca5de69be62ccdd7c8bac430f581265855744b9dc5bf1e98e5e953917bfb5f8f1661758666d0b2ce53b97ffc98e8d301609661260e94731874571a5f4bdf7d25dbae7d5b297818747ae467b5991ad73d7f2494fda6a8e7ecb7d34547afd18cb9fd1fd7136f42392d28a1f6de42f83fc7d78e47e5b213a4c0c45ee277d4e9419734e9e3b0edfacfed1f92e0e2161ecdcb27da0dddba1cd8238e610eddafde779d498db3df7f641df823df8a1383ae5f05e5cc443e6fb3b64beef943f11f69e385e207b7f45ef61a253f6442235bfb01fd13540eab45aa1b8dd8f1e15259365f728a7f9138d9a822697e8110d713b1c935a49a5ba15e6a43fbdef6fafe3da58ea3fe706b247d77425a7edaebd886f0ce28426d7a72edb6cb24da6956ea2cc467c3fe7f46f9a0990591baddfd71f96326b8eedec7fb3d60fc4d26916c7ecec0c31b7fe273ff949a9f5a2dfe1f75f7b0ffb1ddec3de29879b08cb135ba06b50ee3fb17b4fb493291e83f820e9b457531aac6c22e26067ad37fbf60dbfe58c85db5b0fbb5d5bfbb57d4917c716148a94d26fa23fa78ccaeedefb3bd554ea3744efed5155a34779149158bbda55eea859e0b9dedba9147b222ef644ff418cc3bdf55ab9ca1c3888e45c0ff7687b0e5dd92eee83f2f6e10c3177fbe9715bd8893f6788b9549499464119ee702a7663101f94e7dbfadf7b6253fdefbf2a8ede831e2edaa07bef7774ef61e9343cd62fd2d97b6efbba754c15834d937cd6939a5e6423ee18c4a92ad39fdc48390e8f41a49d3c5f8a4df367c576b287dc4fa810f2749a7b11df900b967bdb74d28dce6d36413729f1b83d7761d67250b54d4a9aacb9180cdcbb6bbcf5a48ddbbecae72cd78944680fa23fdaaf23ed05d05aab04fb096bb9e7383ccaaf1fa3d25c868fb31cf7dbe3704fb498c3544a79fd846f48caedb73df108e6cddd3d46c473f7ac3f7deb2d0898299eee4bc85a291ec14c93c0918a31799d366b4c56514e2b8edbd7ca49aea5c441c05cf13c615239a94884663ae79cd8029a01e683dda66ea574972e5dba9475932de54bd952ca96f26798913230dcacca38eda56c7987a46c39f4c427fd82317baf3af08233acee0c3030f290eea2595f1a779fd3a7cf9196b53edb0d360ddf27284bdfcae334a995256d466452fa37469b7e4f4ac14b9b522e5fcff8723998f145c6986294b39df7812153f80a776cd96d1efb8f7d8174522b61b02be78cc562b198b7bd4cb11d5cb69286bb5f29e58c1aee18d9bde1bafb0bcb6df5850712b57b4fca244a4a12d93e0422b10dcb68ed8e69b46634b56a36e810239fc9ee1962ae3f8ee96db3b2570a32ed9891ad04125c26990b17769632b021ed30151519196d3060c0a830e8f48621c1d768c46bf1c95cd0240df92e42a64f83fa2ed62eb7c8bb48d29a837b272174f12206337223a396f5c5bd4543e2782798604e30814fd0b66826338ad918f455b4019dd9c808068c092688c5b8ffa2286bb3d9f4ee60c098608225a618e18ece36fcfe6bc0c4c369f2c57087630c0b99624ef311b2f7e7d1b243064d9886d252820605c9e28134eb7697349a50c7422699d364c8983264c890e12d5f1fc07270efe5b133160e1bf9400e3b8fc25c163124f816226e21c347b215250dbca371d8a373110066a20c97d1322a0514c898e1337ac60cb9fd873a628831dac769f265844c33684737007646431a6715cc0a2aa8c02ba8a02b9043af1104b490e9e8280001a8a0021b4c483468582047a77c0406a02b90f3359230c3861b8000843a8eb60a645e2e8d96fe1a9db245a21132596081054d41705ee01774b52064aa218350998bf3ab388484ecedddb2be400003b041801a3566d87025375fa3532eda60667f9ac7ceded808466d8218b5da8bb55a0d17d56a2f6ab51a9dde4847722b408aeadedd534afa0a12cbd4b19b4f89195f261e6fb7cfd872251e29c83467b8c19625b692067d49652dd7bad1cd52902ad3e7406e86196b2d68ab64732ad39f616606183a030c9df1e54a496978c3d86695e5cf2873afec6780b9163683d1661916ee30cad269f70e0d4929a59492564a444444b45517af20db4f11af48f2f99cd35f86b47b8823e5c9a90589e05d6579572010c76a459569906ad55ea674aa75dbb80ff43e2969bea1bde19ceeeeee33884fca1b2da534c097b7e7f0e7e1a9b5d62af308d6bf75abb18a4167b3b9d7ae5db70737dfb6bf314fdaf0b87ddbb96d1b6d4a2f2ccfbf9dc3c6c44e7272939bdc52add8c869dd9c5740dbac55722ff1489b626cfb7944a7b518c49c384a0a802cd7a862ebb4d8fc2b42cd4168b93ec573cd000071db8f1cc771b4e380b5d6da740174e62ddb721c96b567edaedd74d6f02f74526ae7ec3ae70653fa56b7ca5469a594c6e04e48cefb9967485f0e5a5ae96cfa331441f1135dd29034ea775cfd8db3b3865aeb956fe973a2e5ba9bebc6d4ebd30e9ed68ac109e713c19fb2f4fe93a2cc9efd0fbab7cf6123f32df746ac94de739e671b49dca5a974a4fbf9ded7784ca5cee171f9a0fbf947b8b70fe222f9f5a7878ba4fd0feacf9776b2f79ff745df5b205389fbf910e8bac9bdccf1793fbd0bb4aee7799ef733f4807b39bd67f8afef6cbf3fd23df7470281c6a80984c13bb4e23524def0b65488fff5fe17d6ed75d716c360d8c8d8dfa3bbba7253102ce41b07e9c77204c7ebfe8b4bff7dbd1e067b7577e3ae013a17c553eda8ccc521bb669687915cf1388d02197d83604198b563998a4cfda3ec925b1c0702070292052946a2d1cadcf9a3eca2b9db3263c68c41da9aebf0e8ddcdd5b7d636c889e06675c1a7a3a55d966a366cd4963af728351a1252ad7347e24f5b85618b24fbf5f145fef3baf78f84e05ed84b1cbbec1d95c1efc1b1d9234872c5e60cdf7c328a6222ab946a2833da549d1fa36faae96f9f62aaacb65ada7c0bcab77ccbb7b67c6b4269280ee5491c877fd2be97f2538e5a9af3e9eceeeea53cf258ca8d9be8b71d97b2834b1b763b78eed856dbb416d3a6e7c99e27bbe75bde37a73dc97ee53aecc9c0db792d0a0173f77352da793d12c9b47a1d2d75ae644a339d42c04c71d7530d7dc29c53e6f078c1d3edbce9a03f369cce556c24998a1a4cc9c39c933e8d0dc782df95dfc0c9fec6cc9c33b3e812341b4b195011a99b76d259e5e1bd91d24a593f7737991ad4ace4300f8e7be2f1e6cd1b9f4feba45f6ba5df37d6613b9147fe2e582bd91f4bf6ef2692c6976be4a549f6b7de569e0e7bf640098ac5b051104792b9a756b12962b2179b27b955532cecc47db3656565490f43df78527d2b83ca8e846249da96623971c70dcbda7baf40bb657992bde3cd82b612b8b2cdb448cdf5a5e5b619ea902512922339924bae3877b4ff3dec250c8fd65e0a3e8ed93d288e5d9199ebc76c0adf864e0e75d03cd626ecf5c223cd0d1365f8f77bcb819df79fb755599f8432585aca9f67032983cdc973cfd29eb78228367495723f012406069035fcbb7b297b1f3e8b18d10a518622c80478717cb097372260eb6bc330fc9a27751fbe0d79c37ef853e97e18b61628d6e651dbad3bb971db36c58371b6e22d391b71e7963cc68e68b8e3f6dfab7aaf508c195d71b4d9e796ccf5903103135979a35dc57986595221b5dc44bfda5aaed5e616a2915824ca7954f495963b7bd1bdc057240e793f369104ef50ae3cef5bcb95e41b2ba90435ad547025a8f0494dd584e262911d2b8d569e4a33873f91f80015aa880f40218f96278d4d25b5b22c13565076bb0414ef77ccec1579dfe2650ef7701103642df09116dfe25dbcf8232e5e868bbc9739642f73782f645a2da8b97aab85f8a29c33ab6bf445ff493989621288a3f744efa10eef593c0b31482d7ba3d4d29a47ae75a575e55744af721a11762aa7798d1beed8542bdcdca1d7b1e287acd3bc1fc22d65f4fe9e7881a9f4e28bdeef0b8fb2915684632abdc072bac0e157cb1edebee977e275da53ccc2432821b5dc248e4bb97ef49b8577e8c7ae336c68e815fe0c757886d9cefb9738fe0c0f72f582ccf2d6030475b4d491ca5448ede57388eedef3de726fffb3816e67ee476abb18d7d65aeea837bcc4bd5547ff6c8364e5d5a0f0ca5c219b559a3b7a595e96bc61b4595de0add9ac1a172109baa38ca2ab2ce3c9287b5992869755748564d5b5d92c735f414f0ac11f3d69e8c71192ee8f46727b20371e3d7b9b82dceffdb0a5dcff9a91dbdf54f967c3ed794e50f2168a433a7b58c82c8f4e64f2e6a18eed5f864cf763fa682352fef018e6f1de0a32b5529643a21c7e32c9fbf03999d48fd435fcc3f00994480e233b9245c0ac3bafed4b5b67526cdc4864cbe15379956161f8afefee70488c225b86e111476e02c31f41f0e977e2d8e328af8e5cb8fe1f2c0cdd7dc2f0083ecd2fd1fb501c6d64975979fbdb63032325ce55ae3677a2cc5d64cb153bbd9a1a8134a3d1903c772454464652eae200bf8a46806e67faa31155dae6cf0e294f3103f9602cd759375c6ba502d249143714a791d99a525b524ef3a33537d66bc66e2e50ec7dc665a5bb7b924b510aebea7a5db18154b3519d3cf72816b8b1c04d4b650a86f6b39ead59db515b0b6b5fade907824fa53c8b47bad11e8da5751a47ab924f86e04aac3468f207b39e54c473d3fc6d6bb2d66e155baeababab6bc3dbf7c4e086edbcd845db4ee893b3914645a98bab6cf3f6f8fbba0ba06e67cf7b1c4e9b933abaecdf752ec621242fc85c21de556e3acae18edb95bc51cbee5ded80917bf392ed8f43486a35ca8d5b58894fee08a3855586a1a5a396b72b4963dcae44e83cb6b0cafe34aaaea8ec5a366c8c4e55b9e9fba6eeb7aa5cffcb60c58f76e85b29f6df18d821d94a17c0f9f5e17fa168a386848da50b785a9d966cfcf0d83d4cb420e85dd083bd67adb417f42a1ebfefec7f1d1ea51d1b9e14beff52cb0eff1b83efc397ad14865138baeffbbe8f1385483b6ec741f17b1a32d9eedc4f53a9a9ac1d32bbbaf287b10cbd0c8b2030bbba720ce19f477ee3caedbce2873ef6443fca8a18b00202434f8471cca3ba627675e5a69aff345aad46c569bd6468ab4cfb8ad2d7ebfb1c8f9dc3b7ddb5d735a41c3ef81f28d2246ee7d06b53c903afab5df928d8e10e91c34df5e1db98ea8ad3bcb7b8d7618278efdf523dd5fd9c084277673d68b13e8e19fadb59068d32083a083e7525d883a0d554f2e05eafbfeeafc5979e074eeb5e864c1feef0571d5588d4aa4af4ab61e3de124256cfc073c75a761b4b41a41dd954f287892f82f081d3ea8730edb493f3c0697d153a18686a55a96e3c725f6156065efba240b619260ee9fcc242c03c02c9163771df545f0f9b5f9f93b5ca727777e57e138774575757151b80792422372c04ec460e8fa015bd0b907c30f05f8413f67a187ee191935c3914472af55c7b5a79cb6343a9228fce82c5e1538a052a95dd6914ec875ba32a133f40d4e7b8987a6739710473a555eae5168a4f2e5d0b82b6f1c7d9ef3b710802babaaac8dd2c8f14e066b97153a8e37b6fab56ac6598b882e8c7ae5fca1b314c64ed0a7c63c4c8234d1c67f99347dffbe7638cec9ff7768737241a51e2940304437f2404436f42e718c246ec5bf05b0c431cf660a1a58e9610c4451bf477df58c82c377d58d664b175da9d9b0cb49fcd84d0a853e70dc81d04bb8e28c6428216b215405cb890892d44094416626c840eec80f4d50a7c85af5e922be4e2e292325c97eaec3d6c7b6de1066edfe66d019ff2a8e46d15353d0a15c34800008000b314002020100a8705239150349ae49046fb14000e898e407250198963498e032908a48c21841004082100008088682410085491f700f761f90214093768167e13d7818a9dce5728a1d0eea4d33d539e5af3f86fe2ab72ea3ea375bcc69718044e9cb57d12c6d6e9f74e5e5244c01cfdcbeafa4d056ee2042f659d394784a1b9eb1dfcc436901199a54d0bafe1d64c75e3c4d27e61ed97e44933596a8e2f68d7e304435c2c6ccad7c9895eb97c39f1d334ee21e86c89fb21058dc40e21673627c65201fcbc1a804dbb430e914ebd8ee3a057f78b78eda648f4037e988bfb933885e94511b1a1ed9f0e54835767bbfd7a9a8e66eba1f873d9aaa5c001d23eb2be19073e2a9ead1559020c939937f440dee58016153a9cb62e027552f645a2185cd1172ca1e2d6f77e1f5b3525211fee1ca97e10bf96df8494565a65c7e255367bbaec84623cd04c93d97a8d034d3e7267dbd89fb8dd96f1bedbe70334d50c560dce1077ca6291c647eb6c9f676577ed75420dc5efa1e68f51d3e951535add249b0406d2198d62bbda087e933ec7f0a8040f9c3fd62dbfe875e04792dad429505b4b0c66c1b1910f6275f58dbd520e1b34e7f93d0bcd6292b53a63312795a2c1b511deed9a6cdf91667d258fa661d3f75589d3681c0e568f89ac07f20afa2568835c4e0d20deab2eccad939953a08646eff54435c7360fd627de3cbe411fb889ad59e02cdf0841176a847f5b122f6f1b10cc8f800b049dcf5235c78614cc0c96515410fc10eaac550f7b5506d936720a308d018f76ef56a83b8b01f293f723ec5e8b28250c7a7cf4a680fd028136540f934ca25d817b36aaeef023386b5a8c06d1c2848068e6e4462e5294c41123e1f1bb94c92ff0eb208efa8e230dfb2fde398061907f4f9c3dbbdabedaaed0eeff8c2b4ee8b4e5f296a882528587eab9e262573ebb39932564bb0622385a96b7b8727bf9182bc70be69f2b95250e02be993bd26f21d5818d175b8fcc2d4c37b9cde1a9088f9437093766c7a7b0fd65a19410533b8cd637564870767d7fd210d6e67e4ee7042ef2fd27e069f2b0cbe4c35ce2e087c8807811c717fed1907ee3c9f5fdc73fa2368c3a8b7a12c4310abed7c7b5248eb7a3b1aa2a99d6815201ca2a9dc5d0f2d5ffb03fb152ab64469200c32bb292d3ef23603d42d005b0e97c24b6e214f622bee59839d21dd1ba216c33d7112d6eaa1fdf0e250457b89cf6d69825d452f76f90df22f00ebf353e9ba39b83cf4df4dccad8d0b9fb133512f00f306758c6f2e21d627b75ac7b79a484d088643794f9e19e70b796574b81de1d37c63578a2bb1cc5fd3de87a369e6c4b39c9dabce7132398d3f1d95a78b6d4b42abf33c46482971931eb27472d40312d7e182c991e30e79ef29eb5af6b7dc6a7a0588e2694ab3682aaa6f4d6eae1c5fc4901737313cc31e681d7980c6829b7d2068807ac1f759c7c4e06317afe21c83db0ed9b950975671236b4b19b0b279dc57da8a4d802d2de57a64c3f0e896d6a2bde56080a466c917546812097bd82c8e5fee073c010066790a50781d7fa511b503e2c483b91a5b17b084eac487450dc4a98eff57fd8079ac07c9a706dc1c6b85039fce975c632755c4915f66607b9a1cb8de64c937f3b0f920f3b80806aacc63c1affd5384e452a0024cc35fddc5aa6894767aaa192c9ec063466a8083fe8a0b2bd9abe2f8460d33b3b828205337f1bf32f0c14c7fddffb1a85ad0e01a514fcd7f660f1387826a86276dd8e82685ec7705c5414dee0d3ad18d8b0c0dd98cadea144c4810b5285566b156c9896eb5089317bee137fb480896dc325bd2c8438335a087d1d961e8bfd6822bba8ab53b33a70dc2e216346db75d27522c85017d92d55ec21575954f0249a98a9f60bbd347233a74976ae6ad7bb1d5123363e4a292558f4b3f4b0260318d2c1e49006af73dced302fe9443ec8704b6597cdddc8e622bbeed3c17fe7f5a41105e01c5c1caa018ea4c81ab2323ad58e56e50c576559800ee394f56cec5162461d519d9ffbc5304ed942b4aca55d624f98cfe9864ac3598ea8ffea72b9e3e40784dd09f1501c0ef86e17b9c222a3cf2b69805d6966dcbe7eddffdb321e2ff3f6272dfdf99076ee571c60f12f4eba0fc9776ffe1ef94f6ef43ba11755f89a8739f01e04ca7fc1873a5d4340f5ca448821a267f229b9801fe11a1896e4f05684371c31884fdc111768f03f1766f29b2560309f2bc6d03c05535de86e16a035017886f3094c493cc3b39446087cfd13515da6283021d1cf52e4a6d56c283d7b7a34ad90cf42f16aec102403a0bb4329179541a3431de3849cd505eef0ce4fd95d1fc037b5655bee76460d19add5567a050746906efb399c48d86e605db91c4d6b7ad90d3bef8a8af32e0ff9314074c705f9ecfe12e15c3101a63514dd694d4f393fad5e3774b1fe40f7b5c4b8410b2d706448df69448475afc979e7629573c62165f83761e1a28a70820d9a7a250ad91f7e7a6905280d3969a49f32358e5dacc8848073d4bd9cb96431d2d9e6ed9fa492525a17c6782558c8caafce5ea37242e75a56aa98ed3c64442742f269a67c7a233f70393cbce01678cd31cd4e1aa9ce12669a083073025e40d05b0f7f1bf08047d2581f877000cf70e6b51da920ab287f30ff836611bcf651a05ba1c9622c9775371c617347b4e18591fedadb1874e4fca5c0020780d595465767625ea4b3325c5c7066a6b63a802ce0e64dc3cb9692e0f0a380ed1ec76d05f407e074f55fff3b21dddcf3642ba0480feb6542a84a3f0cdef047705fe4ad4ba3c584bfe2afe358baa8bfaccfb3b5ee12c93990e7d17a703dbcdd7ea6f4327e58789aafccc7b866ecb560efff93d1a35398e44c70fdc19f0258f08fa953f34beaa3fd7800ed522a998dc5cad3e38925b24f8c4d5902a32bdf372634b2a0b4e884bd1b501decbd0602c0053243410224790fcfc68477cfd59b4149630bc5ca81544dd2580cf9f61a24a4bd929691acade8f06a59535760a8305238a22a4bbb61a5d8570cb6d1af46608c4c0a00b898aab8f4a0f633b538bb47a6576a99ee7fbc77f898f27b3c80e0aee6ac93e3f2e8335bdfb3cf0142a7c02f19d654d8043bb8718b6e1f6ad926ad8d893af93afb6856a33359dee20a7b65459fb2b6f1e12beb0dc76b437a09a23d0004944e8a00147bb14b3704606477e80a1fb50e80fc416e24a58023ef3ca0347741aee562bb22d268ed6fc01ad1bb61b0af07cc487d551bbf0d069006080e1f47881a379308978b7be4afe51dcdf5874ea15417fcb60a94f15c8ee0144f60041f42c77a34f91819bfa9505ad3f936785d7382a090aeda2154fe2b4197ff4f1384ce0f577d625032ee4c7f48d0016a86ba67af1be268e2e3864c36c7051abee1e225df0684afd3aa09e211a3ca05c7d5a755f4d43a226d80a5705fb565675657ee802ab524d3b7a476caa1f9183e1d0ca90c2722ae673e4d9d809055f21ab01017528e1fefe519a375abe522d25be294043b7ed2c6add163bf29c6261701fceef8f9ad5baa3ff13ce0aea3447422937c04c416ed68db7f6cc7811aa6f8560e070ac44a6fea506c612197db0e4f8f561d498e330665bfa23ec649ba810e494d38a6287e814cf9dcffd1575a440516c78528fd0d5fd28a6de3501db3b2daefac84d0147f1dd0f39166631bc3d177a682f06a35acc9aed7b0da55c72a0dd7700b9c8c1e96b3814a65f284812c3178937f4cbb781f93c4e2b9879ab1e2970be648f063cedb2961d2be34d4ff89d2e5a77049e00417123cde92f0cf26cde02857def5534e69f32cbd4f7428d44982bf2404740172d6bfc1cf997914569a1d9a3040ebe24ff2cac31b38e82be1e704151532ab15e913b0e8e5fa18724237f0b0f5762d7f62af081c2b189c0c073b9197e29448eb0b3d953e04fa456b8a5308369a6a833c3d83a72ef260d457bddae69a25275ed5c3070b01a5547a61f215028ed2981ac97c975e45dff23e8d9091380fa1bdae333949fe1b51dfcd909b6ac8730033646c32f05df8e8dd65a7243c5e689b0e9b7b02e6d206dda03921c6034c2f07d4155b996bfdb8355064738cb41607b69216e76bb4e5727c1af2c97f1b29297d1d104466678c5560c6ad0d523d2042a7450287e8fcabebe6cd10993600a545cd08f2a9ae3376f39113706ffbd4aaf510786415da0211d196f140333da3fe9a767e3ff4f04f6587a67908e6887a6fadc461eb82aded5174db3ea510418cb1876b28fbac36b497365a3723b1483bd9cd670d2c452d37553bb3cd90b5bdbe0a7b6a0d2e89de948829c15a1cb6838f9e0fd5a0517d4102d0b0baafa86aec5903b5fe6f94d68aa28a549cb48debfff13102a57379c90e84bc8b6697ebc81dcc762a9bf343839071900e9be8cc8358ffb6212b315a8f878d0e573064afd99b613ae8e2aa7b2d1e84abb72b92770504529fca68a903d664fc9f09d05b34d78374b1080df9e5d837f3d97c932d50edf759b1d8fdc331a444d4dc00d7e2c122079a604424ef8832a748663f113d5e3a3f10e2365956e11024c04d8efa89ab4709dbff258121b48cce784c3546f664611d62441acc8d287afb0047c7f189260b574ccf7c10c62a3dd564d111083feb094d47bf5433a09ae04dab51471a65846f59a18c590792f6dd7bd23efa20b5e5da47e872752f8770c851e215ce04db9713573d65a2af1335f4acd03e2548c2877c4ce371a1a7d9a1cb306212179c5b8f08a03d88585550d31f1355ebb1a688e6d33207a3b0de5e25224055cf27916aef30fe8b8e4227298e5ea91b90a42b0faef525656a4f9a04cb089678e413151a306d663297b6c72fc811fff594267fb22fd5558c0d53438f29c0ebd8e1e1c87d932deebab111b3fdc6f25d9629f4025dac5df29d3c6b195e0d94508256dc030059d110367ca1ae6fb306f5d17709eda5aacf31a7299ae5749f1baae8b8c26c8f9659d0ffab876ae685759451257ed64300d5c3ceb6519f3d66476d9e606483b0e32d5afe8ec35cbe68084d8c4509abeb7267441555797c7abe464a33b6f0114bd181e292e02d84df8b29c53a74a0baa12ce017c56b529bbd02dec998cca69d72fb69302395c5f56937dc109f0ea83243a2f110e661a9c4ff4890a9f215a8f34095ae8ccf38858b050587fe7aa152d9ccde1df032b0e22df410afe2b8698ccbf77c6f70190117b1e08abb7206667ef6ebc4a9c3d3d3618873ac098085d78cbb530f62645c0233a27d869abd5d51c2f189e5999c7615aa50acbf3d257526e9ddc59c16a4206cafe831e8aedc7abbc194966c9ada9b21b26e6360835e82dfa04f2ce444382fd22a51121c3fa73749a28488ed32229d8cf9c488578a3c63b24a108848c8da66899fb489d334d9ca52e48a5ff2a03837a59a600a21e4919b82e9d42244eb998d21ff952d47042e1817eb56527558f07eae6e6e29bf2afdc4caef9cf20995333f1775c8e544ef0080f640f4cc231b134a3828d0918d782ad714a3c94a388c242980a61a928f5c63a37d61b966fa9ade68b8252b9d15413b61adc35012f620e7cd7f01ea120809a1eac411bfbfeafea6cc95f373bc65bc67e8699906dd61fac5ee6663f6a39a73111326ade8dfea851fd1cee18ae0da7124687ad19a6864bacee40b0f2a407c646838ab4a7e13bcea756ff622e15971989120b0fa58a08cf1e22c3db7f2aa5ef531ad75ead1fb3030600a7ea44de0a986094b20b1d52e26943f9f6b9e3058efde50c6cdf21474025cdb0546a0d461f7438c23f93a81df08dd5a26ef67c73032218e6a62314bb8aa07e68497021ea00d471562ae3403e2a9b6ff14227e0b9f670a4cf5e7c5cef89b1c26c65686afbf97a81142343cdb688f880b748a516d4dfb214a1be9ae189d4b630cfa262d991b2a4b2a88aa5e36a2572711014ee66d0b511ea8f2f7602042fdf6c9244e89c9ea184dbc3ab6409d44af6ef338d65662cb5d5a85789f36f63d0c89708bddf035372dff0fed3c6b4af07815407b940a963005b7bf91e1dd2b94acdde3586407f2f5b37cf25da46fdd0ccb09adc516175cd1a788a7cd1ffe21a4837618cff70062d4ef2a6901c8a1bc0396c32543f4bacb7d840c8c863152573d8c2a81e9ffef116f2c4e7eac2159f6df32dfbec26df446a6423c321ed99e312c216f6734223a6173ba87306810d4b8bc4255cde6b4c9fcf79460fd439082f26243d4650b850504db98b88ecea56b6537b8a9c59eb4045d2587e594505c3ceb7cddf9f0ab2953b7b2123e1ef95f063b17c20c17258df2480b9d45ca9e11effc90328cb6060966a009e821544c6fca709ec799cf4a4fedaf1697ef0133bdb63ca9d2ef66abc1f2ca6f581ce2eb37e26632d0a7c68edef824b95527b87d7dd2513ba9ee7b8d93b0885ffa42620fe3d2888db85c59837b3861ca49c8173b03ba74a6064b5d70dda7b09bb8872ed11e0b9cb089bdece9c35bc5fa409fdcbe09c2bb029d652791b3b70eb45d1d354554f8afee7564f79f582b0084593682385a7cc423ec74a985a1bc9a9bd61be9f40eccc8d906de825288e374b64e79889432fbe4b50792939d9b4bc57114463483d6c983d80549ad38567263bfda8ebb83cfb310278bf762864c5b42c43e172c9f7227a6a07a60656be4a43aec7da5f56876a4d82c81a4e0cc3a3b74abae5f9b265288ab263fba603d3cc8cac23d198f58dd3ed162627c5b402d2e48a61602f23644f2ba62407ff02854008769e876efab4637fb0b5af4a64553b65c21cccafa32256b741e75a1c5045fda71c919299ef25d7c3d48ff5d69b9b76ad658b6e717907b8619bf8bd5bc881e71ea94216161730651fd4c4ffb842ffa18411b80952a2a1115541c372e1968028b94eb6e95b11269c6b03f9fc9df1e5423bde64769a0d45974fc08c373e59529e8ccf4c1c762def1cbd770623ede0e099e963709d563779254230895190a2a2639e00332090d8ab65e3a80d3618d159eb499e6ea0e07d88d13b01d9aca73054ab70975ebef54ef74eca5e918845bbe4be1dcca54d86a3aca2e748eb4c5eb9d5e6d93176f66f188308e41d94832c686604dd02c5e77cd295bb09567f132e486f62496ef2e9e299801a34ddaeaf9f159e800e6fcb707c3532f04c28cc99cdfa95578547ae5923086e8040b2cc103987256583f2b4c33eae8d1a166db842282e9f2f3b6514edb0a520bad9c1d6a9824a091e946d8ae4547b8c4d0f6e1a6eecff43acd47f8053349c396f1e8da336cb9df7e80649499d495729163f92760786816d064cc36bcbec36a3b80aeaed13312166e1a06c52335102cf26b17c114d1b15075da72b7b40cd87edbe62040e4ad16318c999f36584d363456989754aa8db5a09f2c2f0ff98c75f8c9f89789b662f000e00efc554569557fc0a354f0d97c9c1518ea4b51f718d40b177b3e28fc22969246297acbae5e52ec00780ad57343399ed9d30cac5ee9486010c93366e9625c18e5063a6c94ebd5e1e7ff3a8cc7c085f010505f6e1d31c184b26967c0a6ffdbfd634bd7b2301d7a089e26fa4049f0a6571c9174dade29a7e8a515c5ca06e2b96a61c5fc186c7b7218d907db8a37af7162e44808c06af56289c1c6d81ae8b4d7aa26644f0e59647ce709a8ab06b185354b1f477ec4bf6edafff109be2bbd29b3262b52e68cd03440c37a8fb3b89eee9344ed59d88013cac98ed45517ee42f75f911a4467c29285e5d70049efd5c9e831cae33dda29d9cbe508c5e559e16d156589523d3c23bf04aae72db7967541a42b921471fed7b55d6b97febfcf09a024885f771523f7e494e6a0ed677e8b976e92dda987b9f016c44b543e93f5ea9f57770a0f9badad6e2345e6ba89a68a3b14e6ecda5499a60d0c8ad95c92481b552c3a835177e99fc5f32c33174420be706453096333fe4f410148f5cf0f93471612f987240789a3804fdb89e19d072df2ca3e6673909dab79f46837aa2b9ef32d4fb5008f1a9f71738f4bfd0ca01cf11ed2984629c64d2b8400fb48e06c13c3814faf471988b85f5ad0679c35415527d5f9947374b413bd4ef8c1ecf89359e2f8f33a8f070ef06efd284b82423e185fd86cf41d34f2d1353fba6470dd437a129b6286d9fd6770e2ab96e81f17c2afac05d1334253a919b5c017cbce7ae2ff89584bd2d06c3c5ce497090fca027a540148e8ca3ba672c407455ebe69e4f87824b9d64b6b87086bf1dd120d0828d261ba8dfc3159550180c9bc3101dee34f6c4ebdd61647fc9fedcacde1c1d4087488470845fd5f2988407ee119e2e0f2a72d681c91e4671c0367c62bc250e8d756fe3c5d08eb591ac0f2cd0a199d8dbd278d136b18b6b9ec38a34c64a848c9ecfc7a89ab33bb51533d36b1672b5b1cbcdee282bd979b7f854800e94364e3957f6b26626490c9c78086ef827ef70efa71ed00ac779a9e909799d3a8d52e41c8c8151ec311265395dbc01c10f9095ca47b00f4788f9664911b1a0402f02866afc8aadd3f53c63108a6574e840d03e8b779865501b307f941aeec64834382f2256810e6b30ee27e6ab8d31e89420e0447f002fa3c38531e0e4fa3f3c37e4a20046d8d71ac7988fee083360e8369188193ffa2d84b521bb872f942d2052b2437e7fa2bae000b9c52a2b5b3a7d867ef0eb38b15b0afc4391adfbc11885604d12e768c687d3585ea0e82dcf5eb691536d1408250fcd9766b98b1ecef1808b4263d9e4034af70a7ea5197220020c87c7c283bf209572dc768e424b957ae78e3ecfe47b6f21129c0d15e440b3f9938ff9590705a8c5d0ee0a8278f63cd0c6e4650e88eddeeef984358df0d891a882b08cbc5c6fba1556b416d2b7aaa365ed59478bc815d7a3baf244291e2a6222e28fa98a5c7e2ad2c2b9cbced97170384750ae3376c9c2168dce6fe9f169f59da91e2bee3eb3ccc1d9c9a678572bef7461ea48f3ab404d44a3de90217490a7cbf645ef31da0205fd6d81ec11d9b9809bf009280d4a05ba4e6f761109a8396eb0af5e2118e581eecf22bd8d9bd9e828cd5e3cd309458478f6c01760e22176282a140b8de08dacb7f1fee6e15603cd58d64309441f6956ff0ac23b5802701427700d50336f5c26f020ab6028a80c081c7af9f67816162775cdcce6be27e939d452da3d2b08eff76a0e276c54c52d55a3c002ca8e9fa7cc0f8414880d763302b650848ea980296c759d26b72161e7376ed41e24c71be16dbe939781e32276e8a6e6ad4e38605986733bc06fd614bcdae384bcc8560861c2f65cebc746ad0ee289e87d6b097f4929f080dc8c2ec4fd9954c8fe6fd7a3e9715d04539b812629b762f1c6c30e734672671801d2c900e85a7b013bd30df6d47dbed424fd2a5942a12003e60d6d20c34ed5af7d34f6a7ed1488d14edff0e822a0ef48dd6638115cb2d18efe3e19857af7136cd50dca3763c1d5afd6dc283ecee67bf290f7580a64bbbda94afe5a59be9c8f847abb39a50963d2e3b128ac72b9edb90602ea0af22c579cc86b84ebbe19107932d8267b4c41f8c9a38a8ac59525e4ff406e31f55b86f791c0ffdb29817f695970d7d25cf749b190bcc0760479ac4b502aeac97649529bbfdd8d1843715080ed6158433fe94f9fea7e7cd7f50968d32e8eeaede9a42c53c63f55818446c7cc68899dd6e9db53b3c7118c39c493500a758decc3831b6a93ef72ad8cbd1183b79e4478c3349295fcfca42aef5ab4f606196790089325b605d2191b4b819a7641dde6b4ab483025c15f91c5f7436c3036dc30ecde2968f47b905a5f62f7f18115f4c795835510b6caf16eedd8eb672e2264f4bb5c31f15648fe31f8146b811488be9599090083bcd08d4d54b88b34e169cc82c8706078c62b42b166c556a9c6d90c89f316d22ad501fba7f97c7456aa3f7451b83790b2dbcc09bc7054b06aec00f720f96fcc87d61f51a3a65e04315d07471e0df43379412c291caf5aa42e50fc3b71e5e8ebc24cb00a009b29714621293383d54822ee9438186eb8024d56d54195dfe3a3daa81678f4bf9cbd71c523e2cb303c24c25aee6f7626a275ee1897b099ac9e35fd2626efbd493b00c23ff73ec7188acbca8dfbb96809a5ff182abe1e0dfdff91422091acbafaa7c9a164d28c3696741c0d67ea06176e66a35b920a7f001b5f984c8c893a44a22479e8d279bb40eb6e432b30d050425d8494eef3327499824cfee3d204c6ce6603cfc99bbdc2578d79bdc66a38c7f076c77e1bd9dee578077ad433d2a54d49d80784b3bc7293cb1303154a0a90de16b331930d866094ed1c9944cc14ca0d82a7ac9dd4bbab962d8f07c499bc75764a6a5c46f8319c2f5920e60dea7daf427614d5cf330bcfd0e3c235bcfaa537252646675c4f5087e7a722b58f8fbe12c8a8fe97083e83762fdadc9f4d72fb976aa5850f0151fec19e2cb0454ca83cd5cd51be218517478c39364301879aa1f8c811e4d5cddbf1d5ee5af1dafd24dac2fb11465d54c53e4bc524f0cff7e82368d154ff9d6f4a56a25794b5be543a1906732bf3f4b7aec544e1f203fa064ce626768ac71af7cda1da859530021cf81386d5532a871e84caea62dc222d93a39102f0f281018a3b3f8c1918884129d2f2c12ba747a4c98f96502bfa1c65a6d68f9afa61afb2aa7aebc9a2afcc6c5e2e5f563cb22748693044d5390c521a4cf25f7fa48f595e3c7b7a715d73c5a9ff9de56581c9ec3e5988a5680b8adb1b5a0d54c506c0a50c8a282ad3bc3d6f7ce2c11781030650a629ba8f631587f4d4845a0f59e6db227989d0dab4a210311e93e75223df5d2b898cb38b55800953f357a79912fb107b55f08051a38dfbcf52f04b7c4645d3ef76af2e9d06bc45127559354fc40b9b074c1be53bab35dc6f4df4e6b6641aab0f46cfc2cb747df329728c487c5c65027aa8ddc95bf3512059177030b941ffb4b1a211efcbc4de8ec10d04b5ef959fac8204e01c7b39dd559505b7967439e2d5fae2f8b31566809315a1db10b37b7a7e51abbfc524336d0b98330386425a8b8322933d8868e1a1526a50fb56ec67899cc8be0d5a19405d613199437ec3ea70287f592615b4e4b101c12afb4c99801fd3a0cd52f9e96f7d7f278c4b5c66d9c12bf6db33c1b270ccd93b650bf22d010a18b587d4419c28861348ef7ba825a369bd3157dd0e2dad35858cf16a735741f39b4fed40422d7d8add44c09b02d9c32eba184905bfa0ce646c24ce2515d933550b162f332d77a05033c5715934141fdf158f82195510252929ba421625faaa788c797c0fab1247bc732b8edbb2d7cc407629b81a11ba37f4bcbe34ccbf230fd614000b5d4f5203f8f1fedb214417f14b3ff83b5d9201caf8f3ace516b27e5762473b7ae0c1a9beb8c027bf217fa94fb118053ba840ca63950e69f4b1153410f636367f33a7f04bcde80ff075b1999f2c301d325eb4600a566540d4a4a8852a23605cd6a7972cb085cc35be069ec54bdced3b991231e988b23945b40c7d91c0da7f50110d8828a2d07669b3e63dcb256b508534dc1d5fab67fc0010215f820e8924f4e0f9e4ace6e5b75a8f21d6bd9dce41693900fcc0727e672718f5b024e5a136a4151bb272e2aea66010495690858ba9941806c99b8a216ebf1f5c81db9e240e4ca6284c4947fbe839ab0414f7dbdc8ede15b1cb45cc7015d812aac631e8676e4a018319c071f74453e2077c5c67ccd292d612f85254a2b639b5f6507210a335fb289575ecf57b6071b1d3f00d4bc60354be0d1983a8629a440577ad036752f1a53e10e7e6ccad4e6291c0138a59105b92ab8188e056c65b84870cee00e96a7ce005b11999181d7533536ccbce4b42526d9243dc49f1abc9c16b78ad45219e2a070088d3f0d219538dab5d448b2053e123ed29a676a2f5c3b9843e556782764a4c491766b57061e3e0dc05aed42c893582cda50e472463b9b519cf56e6bfb6ee9ffa8febb1a72c28840adea8bd100b902fe89bcc4608d25276eb836438013b2d485a181d2cbd1f6a11a3d46caecb6b6cbc9f59bc01f5931cf27807d6795cb360b72a7b4d50e9fcfe1374b48d2542b9d75da3c23f922412c3cc18993ef464c6a1672296f6e3adc54cbf8dc93d28d9c0873b6c252950d2989c54b2c02ee67b4de7c2a730dabde33a63ffbeba0813585ba65c7fac9346cae59e05c6ccf8b7cbdf3949434cf2d982fcce3c7546d464b2a79eeb3f0a2c76efbe67b7ba50d616aa19eafb1e25285a802f16f8162df1849ce78f8499437f29ebbfaa7d06a74d615d691fe5f0b888c22334715be2dfc8781ad934284c63ab1e472d94ac547bb397e0417c661cc0986cb63861313f8f4aa80bf8403548689aa07bee6c93b2e199d984380e3633b6a2d5d1b5c1a6ebcfecb567ae67c746c3a50d8c357ff7dc03bca9561c34a5aec0a4f16346f0f39beda949d1ff2a418b7b9ad8cc14078d44802c0e6f943c5834a6a981d34c231bc443b6e8a5141a299c576a15a3a9cce5819f2281aa3822c8d222029b7a0689be2212a9e526563df318d316a7deb884f7e6a5775262fa718045533091d087abea6120c13e149290e635b70fb972622bb5993514d7eded16f9ca3c578f6b445d55c5c82ebd2126ad8e525a7ce5e099c77a907089ac79ef9996e44366bb6802c7ac6fb556e2cb4724cefa0b91530fe08f24b6f038905a3e5fc4b4f265557bfbdfa600930f1ca00fbc1307671dc8dfb609f903b480ec969411d47dbc521bd701e421646fe85f8eec16d5893262cc87d3f66b0e61b0eb2884e58a7975934753f055c035e81c9a954f17f1b85e624c65f7130dbf894d7955adb39e35ce08888a71120436a9cfb1a7226c7df5c5f26048dd8d4eb324eb2efbb0dce30cad2da6bac9d28751552d919d3907c2bd47aa98356e938ce8310102a115f3e3ce37095a187afd09af84a332535e4202e64d69c0bee6a9a5577d508b2d1d467754dcbcbdfc6eeae2ae996931a211394afff6b2ec607a40d44ded114cc1f96e1b97c649493d6a7ddc29f4046193332733d0285bab0fd5a5439e170f0ee51730460685e452a147915474e64ef8fa069cd78b58d43f5c22d076a62f23e62ba0fa67c43d2c1f567f2207fcee48ec0a485feedbeeeedbdf0fe3624ef06cb7f148e89e400b48e526b1cb56b49e5c32e26af394c0692b4941d82dafda91de2bd19743c65beecf53d223c9d37a26ac61f03b79f9dc853fca55fc75d8080d1bce884b36c6143291147626973678f3a746f32fa7cfe6537180a842046af96f920acff2876f3b386e99405b5389f140c0429441e0085c771de2deb727f5730c764643beae9b1d7a6256089ec96c1cf2f915d68c9c5d624c6657315050c609497d17240e5b25280f5e85c06feeb25a9d665a5c0d33f69006337c9717fe9e5d875f0b96dac989b5d0a4274a28bbdad37c613b97565562faada5c32ee9cdc55a841d332369eccd096bc856095f537961cf65a998937b5285ca109ff624bcb6c19c700d7a4ef2fd6818f3d9350ac1d402a1d929084ebe6c122546f6358bfdad958bf07ae2dafaf57a4d291b148b6fcf5ffc112a0a86a3681e53a01d44fbd7702c98ebeaa646618bf02a6dd1979a3155962cb152c56970888b296d7f895319c65838afe8a3596b0f13c31f6823242e24ac58dfa65dab72a162c0c3223d6b9261bb35cdab4e5ef8db69fec8af91c44f17e36a98575f39692e18c19d0d2f50c8d53c78e43e27b4f802bdb0638f1fd500323e2c7193a7c939a506327839c8571bccf6b8fa495b68534e524e95d2273e323cdc2c373a7aa563b307b545dde933f109414708f518dc97d74e4585b788bdd925b22105efc44a671306f5babfc6c8d5a806b871f70c37b7e90ea91fd92ffd2dea308be57eeea689a417064e9b332c37b502da8b890e453a3c3abf533c4211cc4c7492c756d42082cb2f051808a7e3299b6b4907648e62bfed19b66c95733af37956be3b7c86238062c51c300b7691c144e45e00c1a20164483f9221191ce06c490da3a3aa329ce8d91293d591f34af02560391d7179d8857e936ebb479b7b80ab635754800a09545e739a20e47857e8d06deeb162fa9e64ad6748e14db8846730a6390af0ef0267e3001c1e8d1995efc85cafb011d37d363bdec1f404cca8d3a1cb9d5ffc7a702a0124ce4f4cd68af25dc31025cfa11d59c789f2a790c5712a9c7335a45d1ef3ac59ba0b2888c6dfedf6106b477b444d02c002658418e12b9883a500e898ba5b12b055e799c5cb07930c60350572e47231b5aed39c757c7ff7696ed7e42790b72663540aeed29a0e44428321b5691bc78c84a25adfa1f724d4625326d36135cbe7a97e4257b9ecf51ad3878060313900506e6b7a4a74e2fe9a0086082c32ce73089a7d15fcffbccadfd7608bfeef0f1a0d36a7bf6d777da13b90027fb6d267794318786b44b2648128d50bc802f40d9c1a20d372cf4169fb3ba0999abce971ff0006487a33d764365f203d7c1f1e16e4bbfdef6de58569237e2cd55369d0c65146057963f060c2b9dc98061550b635462baeec6ee049d8fa131cd3a41c3258750dc1ab90b4f7f98bf6ae3ea435a3bd90faf71caa33980402b1a6e3095160a8da776fa27c8f6751935fcaf65adfdad94b60cd550fdc4c64af2ef64f1458ee2cf843961101768215dd06e5bbf8bc68b5cf67b6b3c4bf315875e9ceb3bfaa327e73bf01801dc1a09e9ee29776d914e558d0167a8a24ac0e82d36dff92689b18b532c2fb7f647adea2eb071eb9cdab9dcf42ee1f8f4f113f2a77692c6ba104ae36508fec7776ee1b5d4e1d978c4113718f302c54b654274595f3a761cb942f616160d3ad4512958062168ef5da7dd2599ecec0f113479d1bdefec2daf72737214933037cca3d2b709727b4d9e82d10a5db066b152340dc367f94f188955976e243cf913792d46823ef43629152be0793446bba58eb29871a6c06710d6eabceec43eed628fdba0dacf2787382711847c1ff0358fbb220eb7af6bba75d88e1c926507a3435623968178867064a7e53e5a43012771d80913e89dcfe28367c294685b9184156f201b143de9f7ae76fdfe061d9cd33cb195535e5ed2a1c9ad7643256b92391cb8d3a9ab26d5d7024b1843917011be53bb0627feee642228b8c3e8b04906da7b5f5d8b040cd570dc9494a8401f10e469ab7914bb08ecd2f6e46c10116021fd2751e74d178c32f141c6d70c8278fd2ef1f97efb464ea219008eae4d9dd40b0d311d2c47e8c2a05ffc503c1fad9661f468ce826c94ecec9d17d9240c80b0582471e1ea020dd54757c025fe32a934b92651411e8d8af5d69c07aaace65b031655e06ff1ba57e7a0f4e58448e67051ebe298091adf1c3bd01da657649c407b6a91f692d05eaa00d5f3cac5b759b75303def943898c18c8dd1877928ab1a90cd9222bdb4310072bb08f27157e05bd19ada79dc41940755ac93af66239442680d275b0378dd8d410243d9d2274d618933ed2f973648850d53ba5d79c584072b62b6c27d382a6d855a0cc5d385ae0cacf387ae7ae682abe3fe49c0e05000853c866b7e716687ed0b0e48fc5d1ecbc1dd3547aa590418317ef079de6e68c03e4d70e4a069f068ad0ff585b31cc38913505519f0dfd4ee16a17e7dbdf0cf01b43cecfa8c883cb34bad37c29bcb4893619474600027822f4ff7d4ffe45039c059850bb7b72add58493a3be0fcb81002c83b28c9cdf9c03a54d9630ab534d443ec1108dd5e3543dad8f86db82837c4b7a5d2db331065468147ecfe8a0c5da88462d5ceaabd78a921f600d7a954e9c263274de8b157264eb5d383933bc1844045e86fc6bdb6ff6113eea6b43e04026546fab68f335ea60191baff11fa89bc7da90c490ce24ee9a4a9164f3a6af0b2705c0b19be6274f1d3e6ecd06fcdebdb09c8cd68e305dd21d89946ee88ac1c8e14a37c27ba9fb3ec03c2fdfef7938f3d2c3832e72adf8855a3ea42a33df4e9941d35eb5131af12bb81311f265eeff13ee02919dd10eb8110249da88f509b9373b77055dc06fccf17e2951126b773f78f3e26f4015ffc76970ff015078c265a56bb06aa775f0c9f0b755dad3d9218b0220b1894dfea970b1d2b828be79acf1263a3afd40e0b5a813b0cba1a8551161740d2161bacbe060023426c830215c5f2e6a8af60553b4d9c20050d7a64178ba7e50bf01dcb569615119ce7476eb44880f97947c92a4c9df9a32281f83398801fcec38413e366b30f28fa18a822845df53fb26bc94b1e737891032eab80be396e28aa3020e955920a346230a828eb998a269c724da8f01f5e8fede998294b79e40b7634cbb50ee8f2c5acca67942096ac1ed9a952282339832df40380b82b209a0365e9029a8d8aa19502eea67c0fe9f68bd49abd989cf68f827d32e97f6f6ca99e53d9727c3285a0aa91bc1e7f6b384afbd761131e88c45ac229c4507f06117f6c9f32f8122d1ac3d413356bb337e0e1e7f07e03acb26666601f7a4fad84acf80a61c94988052d83ea476dabb2aa9ba1c3605389d8a1c8a2a6c94694f6cc90a95d05a066a69e806566490a947666bd408205e75691135dc34fb5224c1ac62152483d9cc73881e3d8288c9c2cbe4549a6eda812926fb14cfca3302b6ef1e6a590bb62b76618aec3f1d464e1cfac3d874b839035cdbcebe295655d6d558b8506d30cc7c42868729524401ebf72e6c076a818f7996ec128bf49292c9ecec836da684355aa391579d52ee0319e25b52263807d29e4d4cb16e9f5a589c4a014128955af57861163531004b7db5f1cadc17023c5e18e2cec35287b338a5374767079124f01c62ae1e8b9c06e1efc8455269d698404292ebe3beee2b3cc4b3411fc15230c42775483118ec079635b511b180ffe2c40b352dbf3bc278ed4b28609960d7ad5b0e9769321a08545705e9dbec0fa1dfccb844beab512da1211a6bf2d1e8c650b2be80d47d3453abc1e27715fa89a94b146bfa0305040ebab0362c24d2dab13089b42913614b90e64126809bcfbe12841231cd99ecba8ded0c1fd530a066828c1e23db058e61d84c104890795116089ae61b325351fa722022076a82a0ee28aa2648c045bfae8ec90558102021c34e5330ef928c024868336bd33652da7f0ebb531a804bf31aca043c6e23e5b8487d2feade901e44f56f5b18e7a641f32e17372bc243e06e2f6d2fd6a2444853ecb6cdb9f5d72b7135219f12e1732580670a9626563c10b8194f49868b92f1256dab3221a251ccd28104c053ffabb4669eba230d687debabf39cd67b79a6b5a69c4706cc513b7d4bbfa6e4a0e1bfb8fb67aa56c2cfa62ba24d565c01097eaa3133cdec3cefa7706d0adb173d0eb9523c2b81d35ebabb6d7b2d71b92fe40c980a249fe26a427e512747da3f59a610d3e9181ab113b9d8e24751ed81b00ae2db8a2156030dda4835468f04ad16f635da57fb3687e9f1e9518e5ed5bcfea78daa1b46889f74d593c49c69b92284c4d09a939f8c88b62f556f457257cfdbde1cd78608d13f9a3cd1c59f5d9b62b41b6bff4fb3230184ac40a84f4901ddb78d3dd378ba6940b39bbbfba7013027dfa126ea0a6d28c124ce7cc268deb82557c38948469e19e4a1fb00cb41c35215e4d8907e0f54588f61bc6f01b208347d84ee1e54f0c77ba0ce2a32c12b25a5ba91f693a05edbd8b2de0e62b38d81fefa1d09ca590981eb2714489b035c05c5a6468e8d036b6410a74882ab75fb71cb337137968c58c396a90a51a8690b661e33d3088bfa4a49b120b2c55ef8c8d2386c0d241230ee250bdcce8446b04049de18e4eb47b3b88f7cda48733d9f19c92b2b0a07a5512a83430d0340a389298ce6ccb07b6d27ac413cc4cf0e412f311241db342896532ada2c9b6bf43c86c75e891b45bdb5bbcf1433382a73a82fd89f91e1824339ac3e7eb39e0dc053bdabd6cc1c56f46cae3bbb9d197feb88e10ace164dafbd736e73a4137069bf34e27e28dfcd9b0507975b7a76339a110f11365393611740eb879990b5823ca52576c70b459548a2ba21debb02f7e781bf70853983db0d8ae3f5f8ca050f61b08c0d335ecf807e09178ee5306d13f7f355bbdab4656aa8edfce0a232b0f1d8507ae27438e79f02d2d532fc318667257409e15101cc3141ee3409ac9795646bb7ca1ab62c30160344260cc9469664ad163aa8f8f0b0b1c3926c6d3a6caf482f9b2f46292ce56558c0d1dc1a7dd012c25e460df25edeb868a9fca193173441328613fca8667a579fa607f4622fa43f1cf5ba489992f3b0788ae01259098b1df06a97c8371079e0578f2c12b3ec1297ef63f6376a844074b3ec5b0520df743a85a8239d82f9a72ed6388a7b869c87f210478f4daca50939e2d463732fbc58d36dac4ba5e371f5c7941a6f925961f56a2b3c3a0c5d3c6d7d7964573435b5d3b15fb5805aac2f508e598ffdb33bc7d09cd8bf291dc52c217c82ea969036a517c723ed8182cea8c902cd7ffb8b3d7611c9ae500224c7e7cba10ceea11aed55e3641493c4598282eb96a0e00c3a4c9c90262b0a6e1b1f02250e04ea34a69bfcb65bdf49aa3fb4f58196f330a099731e30d01d32f62441651b019c0894a2157db531b86e2dc512eb3af1c4d97590e944326c9326722364a60e3ea9fd41724843782e2a861b06b927bd5f81257adfc576cd1b18c3ff05a26b35c85e83028cf92d0c38b30b23ce04e37c666a1cf9d93763b1649bedb8a7e5b1b3235536a19c51ffec5f7fbbe26d080334ee076a68f591664f108800cfde21ed3c76708ebbdb7f8c76300a2c3bb6bd7f3f94f36a1856c5ccd4fdb1d6ade76750a15b5246d2aaa8d5c20f828fa75c49db11c64fa90230909d640211c1d4a028e67b9bc12bb9be765114abcea1999f1348a50eded358df3866ec187d380ce8a395cee20300a12585d40c33126c5a1099414f2948b03557545002d4953144801b04d72f49e8186dd5af27e72b71d85014cb7400a28846f17f4dd7e1b516cc69b450342f8425b49b4b659d89762e637fdcd40352a36159886d28e920dff4bf9c84646afb1213fc7f7c78d7ce5ce9789157ef251d52b66958c90029f165abe30903106652bccfb8a3298a74fd81b567ec120469acbf6226eb0e3874891115302a0d946449cad8de9ec4714c97f23fc493586cd489a9780b7bc3637777ceedb5e83977bd7b32ee83028b4e96063b353f5e7690aa6843edfaa5221cd970b27cdca50cd535bbca7b367a1ab196ebd432804b058f83d4be357fb57f403023ff8d2dc7ca8766166b44bcec418d7a91e5134bf351de6110a43d4abbf0ccd9c59b84dc51532defef252b87c3b9e34c90b85f05ab34233123704aad1c442c40692e67e014fc41ec637813d2556c574a1b6d798af94d84511ce1630f6f680c31e3c37737f15cc1f2959097f169aa63ef04a110cf689b8746c6abce0aaefffaf83378ce6700931108d5c620cca16064cc81480641895e14d054a0076a855430f676affe0815453ed688b83a52744a1fd2e158f964f4cdc12e056a11d2aab52e0e5010a3d60b1924898f08bedd80121d2190494ff61008c44f7630c0a6acab3e1f23ba2eb14315c3b803d6fe02ecd609ab568b5e6bb9a887728dfe85e4a4f44ee32b4f8e74df3ee74f4e740ce41553f1be02c46d401d74603787a4c877ba460705ac98044f0b6bb1e46c9f6ff2c04d285867de31c3a86c0a3e80be12a228a0f5389b2396ae679b0154742f558f6c477505de9f4b4f52153c219942c076b8533b218c882f16c7b0e49c23e1700e6c2a5daea865ccd0b0e051642d49148831c1c2475257f8970db1f55776cfd9dc95cb0d925e327773dfb0ea0fdc61cd3e62304c8b4768814bb08ea63e52ae2d3ef97648dd224f01356b522a0296d8ec075bf7f6504cf2879c2d464af2a893843be09baa746db35982e60cf06dea25d30e6c7f2c2f645609899235e899a6029f87148232aba441fbadc1902beac337e88a659c4ca5c1d841f79221c5d8a2493b42a7c667876faf6bd4d551f2c06275d262db1ac9941c57ddda795932830eb6a58d8c54878bb16d4f35b07908c9944dff3593c310d01aa4261a054474f8ec75f33d504ada1d939bb6ae21c2476fc80c458dd2ea8743b7a72ecdf3a3214b12997431e17ef23096fd1a983e0175189c48f61eb335b104d80635352e5cae800af523c8250d4f846c26e04186c31dc1e052cda859a1c7137c3c3fbdd2ffc261ac526168fe373b1576fa7c0ceb5fe2a820f2d86a55c03671cd8ac9e1ce390c5612bff898e738f40456a850f93e5b9bbe0e9ec33cb0522a186a2468a6a23c4911659563c02ad6a8b59fb9ae618042920aa25a9f14166c02196b5fb8811b144b275b77683b2cf12b9d338a4f1c247f1b12f16496a9804ec182220a5a911e29257fb08894c4a65e12ee00db94f4be780208b64aa20416dd1d37f456651d3ce494a38e3e8e5e7f1e5bfd4874dc8e2705cb26cd20def0c13798013ac94056e604d781b2487a8786e13f1222100fed94a0506eabeea0ce080a484fcf370fb4b0a812db87e836ec0ec00ee36841630f10a81b8fb383d1a7588a5c93318335f9ada3057b66b035e11f36b4ffb3add14227db11e1458eb6b4d17955228c2df836a99c684644354754736a3b4bb2df092b95cc594687e7439ab5260a95f8aceb899c3441a1622a1e9eee609b5fc10a4932471b7ccb1b64c841c2324bb44c2bd802f6a8aacabd012f3fe91d0d32a02ded28c46a14c5a73a2118b828b25db5cbfe38d72d07c0653f33c54ab880ab26747bba3b8d98a02518542f2741785fb1a37327c33d1425054a295a86a4f93fd4c8b76180d0fc63668bfe8c34c52f3e4f232a25d0642be3cf62ad9edc12040fd0ffa904a7dccaccfef349e31ffc1f038383e3ffbe42b2175879907bed15ad76c8f662feb88a663b8894c3adc5cc2bf794e68ebfd0692eb5ee479f877d97cb0dd8f3520381170859a946f7535da5eaef45e286b17cd279bd23ff664f041da320c26100b25fa0eafdcfabdf38830884f29dfc41767f887bbcb4b14ad5a4165f29c06a28b810c650af2887d4c957dc766dab6ebb0890c68ad2686c666f691769d0c1d882baddadb14fa380c7c928f6d34084c3dc865954d1c8d134f40ba82c22160cb60bc37487e31ad9264dd00209844fc017ded4435e231024ef721acefa2353a69774ca5de6d8ba7e602342bf308f9c85ad97324423bae282c42a5f8286aa658a8cc1daf07ff63103cb11186e39c8e3392403b5022955d91e7b37f34bfe0a3f838253433760a13a2f38ac6d2a944d6f6fbd7c6f044dc4aef63a05138745cc712b07db79da40ce669067a9cdfedc47f1f8c09c29d6e5948445b25b0057eea8b01e8a6ad76b2991396fd0fac9c1ca5e904d883b361d0519286ba5f92009684f1c7e8a44fa98229609e02ee450f667a2f76489c25145237171d0f0bdaf78a1738385685f408a403fd37c8af086ddb08e1332490e2c06bb338c6d5516b4e13515cc787058ac70589dccd3cbfbcf57e761563c94f90dc7b8b1986995b8cf9ad07bf2457487dbbb55cc58cf5d72d3581e3277c860a7d27d3e61b1e7a3a5028d68ddbe951d062ccd8f5f57568b3d2f73b1dd903489e96aa7bdca1de6d9049a416bea60743f1fb12b7eb9125e6fdfd871f7e1f2ea85811dc523a8f5c6f50a13f8bea7481bda00734068f67a7375c5160e245600072b051a5b7cafd0e6a6b2462de1b1842bc890cd1f9bc8080ea0f8a6ed25c07b2808e3c71101c2cf57c8c903203c9b5ed03b572674793f61122a9872a250707d12954cbb0966438a7684ac789ba2e99ca4b58521574d90190815ec9f36e1901633b6992e175bd9505b1a98e513924a8e4cf2e5dd1ddbc89d5edc1673840f49e19f4053b440849c3e075c13c3cf608acb3cd3e3fc0efd5e66b274b6e0c55b9da1c998488906a4db2c8a1030e7af75ccaa557fb2de9c2453b43346621960fddfc11acdc5fd85835b8238db37eea2c0d6c7ce95df772e0c1d1a01caa4a26802fe2bbf91647f8830cc069a1d1483ea01e2f6f83540f168ca78bb1836fdc94d96269a0135dc748ea89f3c4a8232b2d498a0025e58d378bd2b8575cd7ca830a9d958d3991b4079a14ad93faaec8828c787a2fefbbdbb16c925e0bf17ac8152302af94bf711c34bf483fd88fe87873e9f5fb09ab25704807566c8ae80b187d8119ca42d02b0a946884534bbca8897b1d54358cdd301ebd1beae3c1a452d334e72086bef051e0433a0c85d6504c3dae0e031a918ee0ac10dffd6dab3f903ab7100cf70f41997c7b9ac03670f0d8c327f6172b7290b43569eff185090d35f926b1893d9b8b294f341e589c4d985af0884fc0782d4c82558d5dc3bfeeaba352f24eee7edda4a1717eccf396857672f154df328819b501c28faf33e342ee4859760fbf16c2c9b298b9f63c7e2b6b335310c38d974072f31a0504d372b9ffc1e672ceffeb49cdbde72eb455cad35383842d5e78190c6064eee1a7b22105b078a0431f64f2d1ae75724b32da7ae762f4c2fb172f86c3a511f85d427847f928c178e06f176dadeb3ec33bf25c3a498065249a70cd060f2e885e9ba1dc27d3ac1af197dad3ab279edbe2b46a39f4297a694cad66db4c6911baaf406ec3b3588dcf2ee2bbe8c2f84eea89b0a659c46a2594bdca58aabea1969e29882bb7c4b2b401de32f5e047b9c9bb0ddeb4e4ebc95b342569ca6790ed0f9a688a5471c46c7513b24a951ef6fe01ca8784d967a01acea5f79d4f2d56035cba70ba2656fe3c75cea1132569f3ccb04bac0e7ef48c195c6002914da7efe3a65db98b9b1941d9253b3263f234eb199d77415d2fc44f5007009b781fa1058cb882fa8294f423cab658a805b459023eae196acd49dcab43c1d96d68e45f224499ddc1daa2cb303eeb786da4cc6e804d0c1aa8aadd11da881b41da00fe9f750c2dc2a8c96c072394459d9afb9fe2db5b09cd1594ad6ae008abf13fd662927642be29771aa801c82ef654d62c00afbbd5de967e6ca9ee419c825a461270e5807a4c12b31b80af5bc9d7d4b9412c108c6a6fa18286d8ddbdf6b8a91c1fa662c8f5387452bade18b4bcd162915c295f8c0bba6af163066d9384bfa8c65025165d5cef60f51f5f7730e90f1a46407da5ea39fcf78ff67b6bc8386716445a69a15c7608070c7187f57e945622e636cecf6a4d1916f0eac7aed16e7caa1e6a98f08e90ad7bb4776a2ed25d1593f566a2190fc2658262a0b815453d7649aa7d8b34a0c884ed693bddd946148173ebcd66be6442671adbd456c2c1b68bbb0ee3d5d620be5d38ab3d2fac6928a930275ed1b60314d0420a526711bcb3848a846ca4d744bcbe7bad3dc5ae1a7df4539779058905e3158c3ac6906f4f62599b979932741851b1c68f387e096e541f99a8bf18aef7a85683cfc7b83acf5a798a2daa4b0c400e579c2bbcf569ac453f8ecca0ffc88c7c8bd3a723e4e98fc25fb8d7a5fe10be4c1224dede725d44ec13c993fa96b34a9605f6cbecc5653dc8143f7d3fcc03c1a83242ca71ccce5de83e463a7c51a2280402bf410a92389b0ec48332ab244ea38656648a6b1bd43424e1b820150299574166b8ae53ea58212362105d8e1528047909d4d9680d011048d0251040e759b87d7d5ec2f073afe2fc82037cadec538bd50efc127597d3f3ac43dfeade0256630c7bd612382eeb702306acff4ffa25cbb072062113414c2f4c9ef5626fb7068af1032d02afd007d1ee01d59d6fe1c4a7f4022ab466f5b84d172b30f94b3ff47ff2669efe5583573c1ab59afbfc1000d94337b9163e5d5908c8b14b943aaf7d8c505dfafdc1b93152f6059c012ecec83837b47bea694870f8ffad767f8ee3989222378be82f0218f3876bbe0ae836fe2cc4091dee109391acfaea46a61c05d96535935e5bc35beca27a5788a5f588b522ec952d4e072293273fe171e1d9150a5a8ea8ed5aa4504f08a75f265d90c8812d5b721ae9aa7a597902b496909ab3c9dc3cd27db55adc269717cab23e2bc610bba8011b59ca3ed8a99c94117dc8dbecd3d28953eee33a5efc06bbd419ccd53fe90d0ee09ab0051e7beae39096815dbc45d72c4fd216a2928b0a49158c461ce47278da81e011571d85db24fc25f155b45b384318982913ddcccd0218c39d54a1eef171183b50fb0c477962e72a0adeaeed186f4530fdb2fe22160db0079d802b4d835111463ac3957ff16a8943985876fe036058661227a9fad69440e5f11fd47bff44dc80a7f132201adee560bf923fb86f13736d144f3d2d3dd5e9915520a0dfd453da2c51ff0d13132624f03a743526554bd0bdedd48258f29d904a262b66275141a0ff03ca3c5674dd90477a5b291796e953e9448815b7b40f122b3323932db73e908b2ff0ef2679655b85fc43e5cd69c0551b8ae29f851a8450e86fa42b7ec4ec9783cc91f850d15cf18d5b5421899d12699dfa7be6156adf6b1769738ac3b6a8bd6b4f7100a6ec9280462290b48472cba3e6189136d7d62afc15e92f5a9ffdea41578f7724e80eb891863a4a45cb1a37b53aeb518c6017cda9b546bc585dad01d34dd0b931d90bfecdbf5001dd276ae1afbe6d1bf519e1195f28088e25c7d37dcbfef778050154ee2cd3c5d828e9803fc4d6bc0e7fae79231141796f43b25c86e0b027cec4952844faf0b009d77428c34bc40c683c443428421bff4fb0a349293e4b8375c418ec42daa850ff11e3c5b8fab05583c9edd53dfa2a7087651bfcf675f4a2dfc422b23870fba6c694509f3d6baef5b7e7d2ee1f18fb2417494da50fb34e5ce329e340b391588004488259ea5ae6f89c07b9279d281348ff8c4ca112c608165043aa1e18f0a7b932be77668f7ebb922634f242950221845a90e1d5f690046887b717b62ea43f5d1008052917888007e68739f4ab47e2671e2003e7d90f1587d7987a6f9c064475044fafbae7965119e7131767bc59988b709052b0f62fd4ad4ff76a7b5c2e1041b789afb9c116f7033cb36f9257ced4ce4e2181f9ac48eadaa694b5a5f6e8c2e3a05a7370bfc644a65d4c49138cd8c9492b0c0a067d516c79773410faa7354bc15d24acf1a18f4e59f07730ced5bfa8b1f58715e29fdac20b341af796a5f64d08ed527ccb640084af3e397d49011448cff960dd5be91910c12dee1f6493607827a69dbcc206d4c9d9297e633b813c6ba032349e99d84948b32fec41ccf20be0d5c0be56c7bdff859c252803027f4f18db81c52b60a0f1693fbe9e23efcf0dbdddcefb8cc405ce7b2880695e905302f726d8e91e94b711e2eddefad0605a9f146620e46a20d52285161f307829c5390146f04bd3572228b33a01b9f2b3879176eed2d9c58d5c470704e8e4864a3b08fc7a8f60e1348414140549123c3133e3467df0d558bcf5a5b884b16ee71e6f693bf60425e726d4819764deff9b628a63d05b0341e7fbc22a64d82ee98db6ecbd085302a8b1d63443a2c290246938eea2cd54dae5f219eb614901043f7db806e87eaf26c102e0c3d90ef73ab192edeef6b14dd0705bff5fa8ddc577321f816450c9a07aac3b2675b81af878e640bd4968817e8f82b25d8486c671feceeaced885322550de0dfa801fcc727cceac73d296dec602ddfab1ac15ff5a75687408fe710286e88ed27f82ebc90bb9fc0fd2b0b3e992f11b1a6665e4d05497a6e539e25b3ab670ac5ec317b0e2da203124120f960c434ffa87321fff19a2d24e76ea75a5ed2e4de819f450d5d3a481897be35d492b1f0549b55128a237814a29cf3c851c0630562d111e424b65f6a6982825665d147a91ce45531aa11e49b77c3a0c579b27da9fc7ff0ddd9620cbef56028eed380e5250a1864f89bbb07376590a2e0bd9e6453ce00b6d42b7ac2e66e115bafbb5cfbb0511374aa1a9a127ff23039ed60d89195cb05eaa44695e19de40378f97d5383bb9920cac9b1ce0f181ce5ef5d49d14024aeb8c56c54db593f3ba0b86751b56dab1784d83eea7bc660a2f0c939f6bd4733b1bb86b8c7f3cc836437e5424f01cd370416255c88cb2ed46f5de8f44747e04d94f2a077be2a321d0388d1a7da44c957f45d35862de7c48f1569e8358ff313b0b42b27fd7f62a9cd09d92603cc924f740c58518fb3f4f9aefc8ee1bd83019ebd4d46429dae9474b528c2c94aecd8943ada6fe5342a98eeab23a0d459c0a47c3181b905be8973a445c77c2b386028a42131d2002b2457999278ec182482a52b72b4e9658a31e7b82274872f4c238afa2a4c66c6528389c0077878dc396e10c9c5e61c835dbd7e739c0090e5c9274bff7d7f5260fe27c53b3986552d64868bfd96a5af039c5378186d0d4ae86553101225b9c38e630d53ba30ac6b5215d5ef8e459a0b53723c3cedc8d290719f4b1ae10b7c8b9dac72472cb1b129702a0d1418e31cb103241177e11438ab9e6d061078db1abcc045f4cd51c0d1040ad3533fb7899edf6ae20afc160e8254188221c937b6166ed94f1e796f3620801e6bde8abac57516efaaa0495c4440bfcc81b05e4040e5158ea95bcbeb90dacca9b4c9b2ca7899fb40d67f09750acb8b39c7ae2ecc0daa3a78e89fac4fff9d779ee538a3a6f03da04193153e904a41e838c03cd60299d3d9a297fe1baa03dccc4ea5d6c3a9f6c395be653056623183ede22e3755a1c3a706c9966e3b3ea596246c6c3fd4f35f0f343a2480697aa3f6f0b79ae605370754ae28a850dccb359c36970cea0d8ef2fccff5d29986c6f8095fc68d055c3e8fcc517a4d6c0a46962e8b0a9d47525ea951e4b10a4ad7d269a5b22c0af7fc037a1d968448b71c5b77671e32872317606618f380b3a7a3f8c2cfb3ee7848e354a09750adee11a23703c138567fce766a74879a716cc520302532c4e60882d04a02bc3336c03868c97dcccf6a9c915859894b6b5083b8d1465625b074a92d27a89c8c9a5e4cc0d4fdfd23f8c6a6b2be8fc08c6148711db919d7bd0d20294214f4f93f826e7f06bf5ec209ba134afa25e0a8fc5067bba35f31b3e31057a2dabf0c47d43b1157d6a13339d40059df9bbfba48c61be010674183918d6433f7a7389cef21984aef684a90724791b0c4d9a4f0d428fc3a753920971adc5188885113c689388be4d315fc4c55182407cecd3446264a5499efc17e542e18526091cc9e792497f932cb8f6f664ee3bf81ae2b0c6d44d58201d0d099db14ee2506207fe0c4900dce8a01323b29877cf862e92b408cbc1b3d91430fd28470c26c70e59309c1e9f90d5ce5aba7c061db49b208440e6a02b7b1edb523d573cf6175c039b85964db9ea2e0eebd74bbd9089c9d926a5b1538c31fb998c4ef318147d4b7c4ef482bfa97c1e46c5bd7e4a41d866719a7e10ddfd0defe6f14bbfa62cc69e0f001e008e952cb00aaef3a87f3ab2526a135dad3e8b583b606c800e4ee6b63c5e0c1e616cbf834a86331259dab09a589d23c7438f4762e4b2d2045d087443cfa8a84038a9afbd80550f2fcce72a8d446a4e77101854284ba997411675440c623daa1ce27e9f04fda0eaf0fcd28c724685bf7cda67ad8ededa7fb3ae6c5d610a1e7cd488f8d06f06786d2d5dbd44a48f95b75f9d8472035f0d94b00f5f2674720eaf1719f406ae0638f80eae1ef0e81d4e1d3be02938169ee0bc01f411d3b4d3e950388b97f3c40c23902f057b880659d4c625481d5cb07928cc7e3d1ac713b608f404046e405e805b5bbc0f5f0b18fc024c36681a30376083432d50c71318755bd2521678cf60f4d04c21bf4a90c78e4772c2bf469b4e7965f3b2278e3a5f1f2729ba5d6124e69ecd94b512bfd8428463774d4e21b8e19002283ce5db0e79abce1ba8c07204e4a3c8f04092f759f89897e2bdf8622d95ea993137d0c0fbae868761edcc4d546ab7b48b32104da4a50db0c6b5bbc7107a1b616d256c30065bca850d8b608b16de93507c2ee1e82a180d38fee36606cf68b93ea0ffee6cb542ab0de5d5608363bcbc6857ec7ac09a40ed2db34b1b4752cd33afa1535e80862266afdf26a2da00096f3fc2099d2bb570e80b3e79e05f7d9970c1836d8526a18b42ee62744dc9fa6f3af91c8400f156018302f669d851cc1ff5f6adae0178a2d60882c4fe1989e2052a640df69820ef6cf9c7be0f8eef67409d9f31c8e262b4defa187394ee99095681594e95b04e823d208f85cbe3d6ca5e887a3e14a4cb7ad7ca4a70a5c972e6e0f8bf7630a76c41fca7c7bd0f57a8fe8d08016b16a06538229bb8fd7b4d33911761e2a1624454297d5cf2b8f6ab617f06c12b98f67b8a045f338a9f419b08b0045a52ff426b2c4edf32a2359397d5e1a99e53b48f84272132d93ff30785c457a850a480b6bd0d32fc3cb085746533f27d9b2c49d8689a6e624ed7b7d115f3dfbb444da13ebad3770024d1e0816d2bd0d3d0b18b76676b940bd95a8e3aec1c8f752c59b53efc317cc41394e0ebbb3126d5ecadacb4eb6e308841669485d988ec8c5a357ad8eaaff722a0e5af468b911568f0dc982f0540b34464778472998a09c12a80b4318261a445f66e0ea23a16dceac3fac37efed2919f91aae0d5f07f664085f5f635a875e115140daa1a6191c7c8b35eb88ced2cc3e717d1865831dc93b3fe796d55686cc2cd1ade82f8281269cbc0d1254146fe2e14160de452d7c155de910a1c9d96026fe0060ef3b4dba77520ab59b0422eabfc3ed1fe740647e87e6e0417321c303fb1886d664a4405d1c260ff29255b26824a51003610d68e00ea96670982aa22e00ffc45b76f39d390f2a800802c21caa1b36c52202bed826b3e23c7be8c8ff042557140fb73d82a6bedf06f54531c08a38e804e88e45cf01237a45c3f10ae991318880ea458fc2cccae5fc669b0f3c3dfed5e79c8878a14efffce582afb2c488828db70c3c2729930a11e5f93b0e4d459b7f7bb07cf16cb93830e0df89776b803973253597ea3058f2a56443bfbb15dcd50807004acd4a1579a372e459f91efde0c4d1b482bed8f29874aab0289ff84590a295851c2a18adc25e3e0743d2b6ae59f640313f4b9e59f618fc59e30f50cf8f00dc20ecbf04a0eb929c1f88cd82005e440bd43d058174c501f100c9261b294016dc51c78b14fefd421663559b772b10db32762866b9a0143eec5e055197299e22310cb45269f68c360b22b368d2733ed1a173b4f17e8fd02d7b15565462219f90a4dba08a399631fb60bb60af58415122877ed199e8511803095f79f3a8433d33b917d2e981628530ef90e96ca2e0c893a6a07776a7a163bb6e652e8c6a42cdce43cdbb5c70b813b9891e8ae315c35d2895388af0fdfb222a3c6359eaa513faa2aac7d5b29f356bcef85288d5181db0a79addd81ba8f96da9d6af59f8c5b33fa2d9f3232f72ac7084f27b09919ddab3332cecfdebd5d662deb4a03d8aa8f4a60073b453365b597516d3bdc10319516bf27d32db215aa3024fa403e1169035fc447372ec1b57ba4687c096ea7954675c95d404d840802f371f2476f02f408373ed6374087c3b047afa36945930d81da5034547c684f9f8c9a995816ad70acc8e3535e10ce19418ca874817958fe5439a81c23941b0bac81edc3c41004378ace987a3c882ab29d84854f50f7cc10e8b21ff926be2d0e1ac91922f09d97bef2da59452a62403fd08bf083e0942f5796b4aa9a3a0aa619cdb6730817dcdd5e8cd04d819655f69b1cc50d3d12e999999995f9741e95146869e9a42faa6b3724ee965c846ce912adec78f240f1d48dfd087453f4c810ffd0253425884a4e8a19f8a8038f2b0050fbd7828a5941a0ff8c5cb47242525451c78c1b3c3238c686490007ba82c16d2c4e7b86eeef9a1f3cc7ec824b0d1a2b25818c58a3be83f41df057d0ff4ea19a53473be42acf4c1db0149cb298d157b7c0456282dac3adca8d77e53de6a7bcb4ba51b9d7fa9f4b260532517fa1296b85aad56ab8db48aee249fed872d4f94565e481fc373e1421763b55aad562bba4455926535bc86892712a9e42698cd0af952c6c5904c8b9d56cb2bd25243ddf1e18668f169e88e4269d1526bd09a36611b9dbfe590643592935657b029920b3d09d28cce6975e0e54f372c10ce3aebac33e6a1d74a9da7c79f37355de8833407fd358cbcf6f4702410840b8daec651103e98670326de23730a4a62d45149b132bb1d9df3b2badb7f6e44a2bcb656081f8e4fabda6b68553bcde9bdac7b44a8ee11559de65452a4172cb33cbe1b514bac75fa841b65e9cc506af17072ec484426554a58aeb93e410821bc9913327b5914831e8439e3789f37309438a27b6064b6566be7ed9c571e04e204b1aabd7dca66261be01a4a58e6a199042a44577490e5dd892327b07cd7400c8b9d11e958dd2c17fa09bd6640e817407d66272fba8c7998a3841a4f046abe3ce88dff3e6b9cb8c3be447dbfdcdab28ef17616152c3f8c31529e71a2feda7ae20dd067dde253598e6d96cf5bce7e693d4a5f2bd37917106fb4f103597c744c76b7a7a6437f0b98b72b111f7d0742df5070f9f7ef79a45e7331361120eaefd91499de1eb505f4023aa122f1dfb349554fd50b7fe8d71f7a43aa07f7313e1b762ec22e30ea554afa66f49fd24ba93d3365962d2bb367feac140f6f920252faf285741f54617e6d9957f80566bc617c7fb8b32d7ee5c16e6caeb7023cb1506a8c6dffca50d5d210a5946e693c11be94f5651871ea34d478a263de96f3d6454a2fcd2d8f9dcd1a1fe348f1805fbe5c995f9bb6fdd02f5fbe78817fb9757fe0e49fdad64f3dbb71ab0580627fe0972f3236fbe53af0a20ec4d5ba66166bd77f718dcbd975e0253de82394fd71da59840f1b45d8b071d448a03c196ffc2ae34d1173bca91fd11f144c856e7fdb11b69b237c45df7dab15b1ba65d552146c97653f4f9cbddb3ec51827f4d9ed32468ed10a4692e82c573a4b67814882f09d9a29b7131664c53fefad834fbebdd403eb039f30a31e73845d7c1ff8e4dfadcd3d8ecd59645d2041940489d8d11f12578c20e20829da0f47645220a1354142fb0012d916249080c40db6c876a05119ca62a0313982e3e4c1326a57c8a6d09ac8a2683e1cf194f090d0c11e4fb1ef0a9196a75e136f268f866d7d60a3f74ca7de4d7fb0a3b76ba75edf6aa75e2f4fe7d9dd2abf60422fc617e1f50163eeee6e5ec1ca0111a8077befbd07018c1b729378a8ba75701f9f0d8c35efd6486e12741db0b3c4a07fcfa66f4a47fd1795603f9a7b523e8a153cfd5bbc0ebb9d4fcd476fc8fdded6cecc5770ef31f30f00706e61f3f8298f2f6bcc3d799cd1d237345ca4bc1d1ec9fa0675234386c77077bfde420bbe05c06bdcdbb91258196f2dcdc978c959c64f2edc4ee85d70669f310306ef0c1083773370dea954de6d3278274300dec1bcf4ce7ae91dff0ca7719b8d9f8a9dc6f69e4a00db7b2a1936d5c6ce6dec31ccf0ec3018e01900ae035dd85298c6430380ebf3a0f85467291de9c0874fdd2c5e66e83b3954b3ad9a93f117361bcdc9f8dd5e0bdb824be7165af0a7f1b470659c06d59c8c6301d890c0e041f80e0c170afb0ce9db866d3436796b666c9dfd19b505efb294bb70bb191ec3e5d6d997a9540b72866fee33626c1728bebbbb8ceb340d8d4be9820b00f016dc85db4947f98c198e518da785ac851900d85e73333ce53a906693e11a0f2a757db297e1dbc523e3d6e6645ca7515bfc185b7c1927aa452fd3462fb3e4655cc6498df2327208e2e43c958c6fc931c1c8b8354215591997b1642c4bc62d193faa32323e232323e358142743d99297f14c46e6c9c8b8e63297fd24a19bb64e1a75b2e8dbedd675cd25a7a57373a95a8f3e7a0244ac475e689b04a753830da7676424436626064a062ac68c4cd12926276b0213292875ec226dc75f2bdd24fcda32a3dbfbf9b219f615f57a171191471f8016db5d445c89a8544964f99cd5512d90439767ded5e85209c4215de9644a4b27d809c7e475757a5ad0474679c844ff5e805ab087634f1e5fbb9dd06b4ea36f601c2563462ae6c6e4a692474f6d59abaccf38bd7519d651d63ae969799277f1491e838467cf8640a97876ec49412f67b76c9ebd3e95939c743be9321ee3c667c3aed327d781339bc9652779624ed7e7697993f5a8f5b0b868328337c5986e6dce3a8de6acbdd24b1bc9bb9ca78e6d1df7d4afad433dedfcc84c4b1f38dbd367cf167b5c37d796b3bf9bd7c23a0f6b3e843ee3d2f69ae3b62eabb177e3c2489abdb28ddf92f835ec2a61d7bb61bd1b98979ce45956d27cdc7f6c7bcfe67a36efd9c4674d07f509afcf496a3d0a90022b4d88b34ab527c8d90e2bb71f1a1c6763390dfca97936b239f8ae3871f472fbc1696ba3d9fcd9407fda47a6415198e9964ba7cede4deaf2889746fcd3a22ce225933a37b982972af8a7d149c47220f83cd6fda1df63b9757ba4d78faed3ed95d61def7fe84f2f027fde4ede1f5a047e6c82bbbbb9f987e415c25ed9c8e91bcde496c7daadbe544f3233ceb72b79e631b6994d663b6db0e424d78176d3bc94ad5e8b9a966382d9607da059faf2e54ba963153472cfbda4f9abe6af9babb3d985ddae66a3691553bfdcb228cd5e0b8b39f5ebc23094f4d82e7db86fce1a36e98e35c3312f1bb90650fc8e09f8f2e50b13ee1bd8d95f379e7db4a21579607703e1fc9039c63527395b1ebd6e1206c6544dd5544d25af1acc46728d47bb40f249ce91f86324bbccf9aef107ecd5607276cd01a9b4deb368d8c0b8c9352f79392eec866a95086c6cee543fb38f68c8b32ce368798c7d332fd9cd39abdff74fb0d3dfd3f8f159a33df8cb972ff302750ff8e5cb972fcfcd0ea37840c910d40794f8a08682704218713f561e88e2b3d279444740530315d83c40e4b3054521b6349010ffc011200cd8e0890fedc5c4352cd73082651c3c836bc0d40f8de21a46404d417483005abdb6016660a3773927ea1dd7a0d2a4fa93b789e53911858238f54604548fb709757a1f070c30039885d481935ccc497eeec06e6daed6e99c246b6d3a8661da8dccbb6a7186553ae5914a2754c2b5e5638c2d5cbe9f8d31468731cbf30a0b35834a1a4b63e9eeee2eea1b2b7d63d438995fde58fa86faf5ae6b4b27ad601b79c09f91a8b9588ae2e3163f8629f6cae2d27271d11797e6daa378e99db4a232517d5d52dba5588e617435e54227ad74cb4adbed12ab3f2efa65593ca365bd28aabb3fce728b5df459425cfe001e0d65590362f4ccfee8f272abe918391eead2de84cd9aeb25b161107238dc5e15ba44ef72ecd0379d8def14bc3afa618ec611400d7d0324160db5f0ed43da7da08c3672a2ef881f69340e8d74d286044af4207c8794016dfca48da6699036648cb78b3c7c65fa1a6f426a0f0f63760305b8c6c62e3709708de850e341011e846035cbfcd4374dac6b1ead6b9dd2d19f3966a9d7e68624ea762bd5a8dd505f3a16372112dbf8ad90846a18f6f8415275afe16ce4b48a63246daf6d5c1bcd71ffe56273bc0d2c7b737d03c4cf239dfdf22262d0217307d498e6c5c60f352d73ebaa1702750f186f84551ae53b7c04fad804f38e878f414de2ed284a0a281ace628c357fa1681090c45fdfd44600e6966571adea586fcd127bb2343621e396f117efe596e672905e6fb7c390197e805b8a077773c617f6f2a7a530a9c925720bf64586a5bebc7609167b798729b15867bf3b3b041fbb9d4d812cfacbda28133e2c318f9befc656885392291eb083ce4fbe5cb26428c9f717167a433b0455ed244a0a1ed796c9b74f991faf5df26cb058e81da6a4d6c01955b04c842921cadaaaa9234427666666ceb6e474998590e89fc6d3a1ee95d2fde5a539723e2ca58ed41d9a6b471dc9257c80e46bfe5d99228c6fe9c3bf16f6c15ee2d9408f81c2769d648987de496a65e9bdc9e0a1d3d9f27d213ae2e8231791514983514925cbcca45aabf5c62eeb9636d24629bd8f560a19661a51b6590821845c7b4a1a548f1cb7ea1bcbe2da391addd9b081f1f06ef40ff169ae25d09c909ad5e785394873ed4127eb9de5c17a598a9e9de32cab524a8f2ff49c03e55637941335a09afbc1421bd8cec6f79c2ef472c3a4dc80faad4b00ae31bd4a1b7d13bde1edb8671d44efba28bc3c879f1ccfa6739aeb326d6ace1e69645b0e3f369e4daf9e8d2635b9a53429a5a65dce51c6dbfd50abfa8bdcc52cc777e63a9dc373e817ec2e07e8977643fc1ff831db72b04723879ff76cbad55f573a7bc749785d324a282fbeaa3b945e044222115e69dd538c1003414683136cc77134563672fab2e617970eabee4e2f662754664fb5ae5eeab0fa1e78aa1008588cb7db210ef9c8458c11c63829d163357314c42979ada7a7b29cb4595ae6f3b45ab5af9642440b63a42fce5a835ea4300b139bd745ba48f572d29d53d2984d76926b7cb9d571ab9945d1780d95934e3a9fe4d3147c3adcb28661587ee622f6895407b2ffb846e75c699a9b7ef96535e328629f083b907dc6c1d6b906ece7bb6ac2428ff4665a5e673f70e2e8b108618c50b0fcb3a5e487e506fa03aa007b8e392677488d873a73c7eeb37a1d56dfc377c673617d564fbdf359753e2b4d87e5d5a7c643a3ebd093f90aae36193016e6312698cdedc6d7f61e3b7a391ddbaa55371d56f7915a7680e8eb4b4b6ba55ffc98ab269675638c3027ae886a0d1b581f70562259524622c1c06cf10ab17ac966505e1ba5902b8c85c9604830303a6d49b262985f8eb1b5d67748b72ef45989b475414ff24cf3a791849e4400ae8179b675f1a95f9be575eb3ca32d68a287b05a3c58165d3d8107585f16dab59487ee99a50ea471503fe66c2972c651eddb519a838e4a8165ef38890e6c1fb0d2ab610e8a5dd0f700f5cf1ba2cfdb6540e83d6a3c56fc193b20cafe9e2d8c728a87e51763f4b230aaf1483adff4d9d5140fa7737af5e9357ae481291e74def9d99cb2aaf9abdaa08fb7bbba60714ac09a2ebc352deeb3cca2b62a6994452de7e8c2d72b73102950432f62d574489f5a4d73d375203bb3ad692e42d85c3efa23428d291f6c67b35aad45a12037e31776d5c51a57cf393f3a6badb5f04a1963ca879a835ac2dba21f2bbd2eed3eafcb84475d6d2d93b7c4eaedf2c7852f5fbc3cec8480f8db75785dbe87bd99c05e0dd6d1896dd4314d5a3e2d9fcd1abcbaad63886d9977d4b11ff83d1cd92fbf2a46338a39bd1d86f9d3608feb7b4ccba7c7ad56fab3359ecac3833a9d92533d64cf7b8c66ac65f4098fdba9037a085752c86c0c29b0d43b145bb57a76c5eb29b02ba82443c9c076281d1416a7ead9d78ac262e660e66b838f1a749a6b14caddb2965b164a06965d566ef6a47848ff796b220d16b6a390c56ad4d9a30ae1500c22389252a2a1a9a1f1c2b22a952bb8e87611a1943a466f4ff5fa985b971781179bae557f5fb942cb67bddd35a9452dafd5b24818e64fab96e5438858d78665d1c8216d397a6658d1e0bc5a955e6e6d296a5d56b5e8e5f5a957cbbadd4569dcf2ecf2eaecd4a5771c766d29ac5e7cd58d48add5af7a5d8af9758bc0bf3cd60c0a4b3bcb7f28e74560e4a744b07b5d3e9d2757873e6fac570eecd76a6fc76feb5bd73a56ae103206b759d9eb57be3fb408dc615da7df6b1bc786710853852cc72684d077c820933f8d859e09c035aa471d685d9d2615f9a1cf45a4ffd0677fda02a417818f751a80d9ed32874e37223ff4996fc72387b0438716eca90f7d08913ef2f2fec05bd31ca4e17ab667d33ee4c7699a6be8ae79878a3225194e1821116676c9b7677a7d49dd23f422f0e1ede6fda14f5dde22d0c6275d4b31ca73bd4ec3dad28a168451b243787facb7a6eb34dc76bc2f12ef0ffd2943126c874211f9e1e17b80a006e0d7dbfdd08fceac82c2c270b6040a9d32d56175fc984fcdf3750cdb7aaa63ce5b4f75ed1549766deb01e2d7e13d633e25bf0e352f6f4ff41a312d11db3a9882febe487f0f8d57cdeacd63ac49c75c46b7960ad6cd914ac5606b3c50c6ac9f7f78b6cfd36fd2e1b3f979cf46e2bc1dced8e1f6b408c563855a58fe1adbcc9b21fab59db84674de6c735cddba19cf9b3517a1e0d8f524630486710c4f2c5fe6582a4d1aaa45c6596336743a1d597a3a1dd59a552734345a3219b0b09dd5faaa2858f6ec3ddb6d512e0316258e2d4c9b981942860c19be7eec3a6884209fba48e24a144faca755cde9d6fe4ad0b148b7ce8544b8c1941c6e422f61aefb2209487299571baa5dee9e5a547a0c94783896df9a459f37c557a7b9e8d0239016ec3302d23fba1a9ad38dd7baab8f37d6396b626c08022927a8b951e2db08aa623be11a918bef4e158993f8432bf13136e6c403b1f33fad0765243df0c6479e4df40144b1535ad15ede0d69d437d487b82ce142096791650a22fc1d1fe13e0271da49aba2d76a6d971e4e965def6278e78277317cacf111e76302a6f8a85deb4646ecd788eb6285a33f8e11883e5dc0bc4d8c641e04f320287cb3ec0e7976acfaa07e5eac5a61606fa7877c797b8816c1b3893e274e012ccd47b7e1e4638e5682e4bb2cbb4214dff947205c61ca2a674a16c192bee93a09117d53b97cfce2bb2cf24e9dbf23be14c1bb31ffc80094b0fcb41d306681ddd0a303fc540fe8d429e7f0f39e8df5e2d6e510270f6c1af434d2ed073e9d597339fcbc3ab7947c9b54c1a9b90729ece853ca22f0630a30fed9b996b90d82ed5e91aa06d6068853d32ae815c29aa21ae883005aec8f6b4373d04d4358e87d83c16bba35776077ce1b9dad6da30f422b9e7cb9334ca619f674727b5f73333144a03cc665646464c89021c385de64f299ad8b3fe328940c136a8b11e3a84de86d8c189f89711d28b3c5e64c7edaec6b6e46fc8e864c4b1860af26c6c75df1317a8fa78a0edd06888301208ea870faee6db18e8187935d56c2aae8288d54a9a0d987858ff7b10a888f9f3961fdb508d1816f0392cf2b7838ab167c9c45eaa3e0b112c681793cc147e712bc1bd2a30fe3c02ebf1ad3651c009ee28d3b4459e9ab8f9bfe6a3f479102f66afcd17808a5b4621882ec7c6ade3a8c4b0f027164b8742110e7edc0780c970ed437302e3dc6b6b221c3b4cdb8c9636262502894ef788f72a18fb175fe31fcb475f54f3eb375fc336eb74e480cb76636197f9a157abb01c997b9f009ae61f2d3d6359637b90e8cd96273f6bee6ecd56919dbdbb15ef2d738a4cc3accad34dedee94cdab4ad43bd3f76d5534b20b05713a4566b51287fafe39e049a73769415de3b95005caac02008597ad004086014edb4e7401ca10e1c018a2caa18b184125eb0d3ee5c4d3341cac69ca9a0d8e75837cce08b3188216c62a5c84912488e1c65a1326509115cb6185979e22409922c8e88a83059d2858b156f4583bbeb1b5979e22422c9e288880a5cd2858b1546519ef4105ab2888268c84b978745f5c4f2553d813658c2082324ad9ecd738ce7834d250907d8f4e773e36f4c05c54ec7981bc298e2218336cce7567bc29f30e218c235e6543db130559c2089b75f7dda308471d4700d681fc7d6308e1ab84687aaff1836a9ebe1edf5296d3b3407bb06c6f15e8dcba1a5dd78bbdaf50760898dfe44f87d523dec53b77fa9c01ee3b01e4ef5e79771487fa8ad4215df788da7e2b877a39f0d7be737f0318ee6faa6e34fbf2ffd710dea5c4347cf6a88150d1a1cb75ac9a39a2c3b9d6868dc6b6a7080bd392dbe18e38c352671892be7782f8ad98d04f66aba6af4d1bd183d01fe5df152c4b7f6c3a3b90e7ed2d37e78aaebe0bf5ca7a193beb1cef5cd29c65f6518933fbf00c5f2ac3764f3706aa5c11ec08914ffea141f291688538fb42a7aad16552996228853ab51c5528fa2d728760a4704a3d76a2d0ae5ce71ab15e7c42410c706a88a5e95402dd1eb96e8b00846471d25c1f29c043a81388cea121d2681385c0455d1ab12bba46e19d2d19f6345ada56ffaa37751e358446dc4c5ca4730a210c330e2bb3e02c38aef2d1fbb4441f45d7b39f2d1ea97bea35f46242c8c631e9d37a2d89b9c424552692e66692c6d853dfeb415cfa68d78fbd9da4a7346b4ad741185b1dcaf8efa84263649c93065c2e466391129a5cb48192aed2c738bc0afaed35b173981384d459d420b14129c7cec217ca4599a8b1abc140b018840b17c74194c626e5b793671c84ad3963d9b1943567a578fc8279b4ca23929abac9249cca25531c6245a153d72918b9c951863f42755ca472a1f9d93409c88c409c48159c0285a159d098a888f71082f282e960b2756aa1545593e72d15bd9daa8ad889e6d9da58f9a8b1049ab3a8b5645a7322465c993249c098a080b87d0f2ed0505a3c31bbb28c608dbc9291f637c37ea7b471d2dcbf21dd2ad2bf4fc1d14e4b9b72af4f052806bd098f7c56ae21957d0a8e1381a3466f3518ea7313bd1d4d0b091936323478ed99da469688a48203967cc4e994663b5aaa139d9b0218566333c32990b58f9638cb05d73692e9ad55d9a6b7fffbcbd34d7f53617194c6c577ba64b49855f97ec2dcbe22e976318b317e612c5bef72e759f2c760eb05743dda6188079e611b85c738c31ecc23c73202ed75c28c58092678e038c6b9e6240c9330702e39abf177aa8ede02f37956200c9330762720d0892670e84a9244b37c538986e4a9248971b29992eace418c92f17da79da0f24a51b040548c949de8067c49226e9bea6c172cd332d03e2cd3be940b1dba1b9e740d1da7ab85573cf6b4b2add5c8402a47a57ac6e1d05aa6275d25c8c31d6682533338cd397b783891e63ecd8b18da090c39d9333856433179aa727a9038d0f8d90645662ce9a1a771d381f2e0ac9662bd89c6c5d580e49cbb0ab557d3beaf31699dff39c1d687ef7408564b710446e04f3624ece0981aa76e729cd71ed766327f6fd3fc83c44801c58a672594a732614d88ea57cc79864eef57945884d037c36cfe60d400a22fc3f300b475e7a10be4343f5f7b67ae9111dfca91edfc39107aa4220a92d07e87b457d0262ed2a454f5b8a5e8f71ea3137080a8de1311e3483c16c296a32b98c0331b98c5397b94150e80502e3a81b14c3613c6806e3cc870c4551193486d34b46a373f35183146bc3db92a22eb433b3a5e8250264c6631069c0dbf9297903de8e8cc7b841414f68670758a9bf1dd47d3b311ccedcd48f189e2add06bc1dde99f1140ebc33e3bc3373573b32423b257fcdfd8037d6d037959a766ae89bfad06d80ee0336b1b72f23cc245bc74af8518b52f7a9378bdb12eaab91313ad6ddb7ebad5b75abd748248be29e0455a4db699e79cc666acd310dbbbaafcbaa4daf0e94f2631bbdc70ed47a650ffe534b1abad8eef4d1461aba58769d3e62c1a3a149fdc035dae376718d769411023530300c352714f3ed1ef702db57078421861862e048ea843ed290a1656049ea8462e0349ec88cca2c43b8951e13db570601d0b0190053ce33199890a25101a00595ca0557a954db0c954a860a156346a56a620bc78f31ca88a37144c95b68a68a82854f37aec90b494c8e9571c87fde44ec4209fce7278bc92b440a734bec1efa1907f36b028e10b600e34c9f976fd8bbb7c5f7ed1a9ab08ce341a38b05d873ac998b8c119eb032587a4a73dcc34fa2ce57b4bbbb6f0f907cc83dcf6146fdcd1bdb653fa87adf545a8a14db7114b62b884ad2423c1c16e2a9d895a084273c610a5388b2e224cf86ad7d37780630cf07cffeee0e9ebddb9e71c0bc847d4c3484b5bf1a1fa727d8e7f4dde09ecdc361176678ceeffd8c12214c89e1d9b0c75461bb181e7c0d638c8e9e61dbc0ee83fd07109c3c07a9918175e13d08c47126aea0e2045700a1e58b1df6defa87281818bb8fe6deeba8b6b0a729a72eac9ba0609f5779cecfddebd2bd29d827b043e0e1d4a76a97374ee1be2276c263f9eec524c176f5ebbb5161647c63d1a1b8e8d98485c7b3692560f1dd41b0a10afbde632b3e30c45bfee1988ef08084955c098214a3243a030215df71122044f96628a46fbad2bb62a4e5db815c11c291ef9a85ef5e16a526d65710c7e67811a4c2446fcbe39824d81f46b0df6bce798becc24a51152060520508963c7b169f5f10ecd574f0e8290c2fb0a59b9a5ebad64b8e83f5d235624473eb38c090ae4395a6f90aaa34d7dc86bee9c9fc72cdeb90cf1edfe95bcff4cb2fc7665f28ede775350b92dce438941c5e23d04b6eba46a01889912102fb9abbdc74991c8776ef8b83c9dbfb1a816e4a5ddea61b04e5ea1b044d759a4ca67bc11be34048de315ef2989bba4cd331b8913c662bb9a92174230e7f3ca326ac1c5e1d931b3102af1093778f68cb0eef080a7d4df76d6914c790097402a560130e01e79cf3baafb946d29ce6d956da529897fced903648721cba9dd46e24c6a1bf9d9ea26d1da53929cdd1f7efed5492e36072375d12e93acf982d35a7974e6eba41253f79500ce6abe827d28db9316ee26ba4745333c681408fb9a9e9262f797b8cc94b0e24c6491bf498ad9db4ad4c393728084a03de0e12235080c47869c68dc45c3e0255d44b1ec34f97a34015f5287ef218ef384a13625c5672040a33b7747908aa2895b9ed04aaa81b31b991d26522ef78a80931978da08ad29c151bfd203592e6a893b6ae152a699c47c55164f2d45f07a3e0a32a4c6816850a2db40a2bdfd54c79fa1d249ad42b363b7894440b932d48ba4b9423433049dfa4f8a839ead4ab172c34162fdf3517617cd75cc0f8aee6aff01d44f2d46720c23a7538049d40257447fc0995b48a3aa5d49b7a3bc148dbdb814afac622a23ac704da1d45df644eab536f2ba48d77da8ae72d5045bd359e1f0f522dcd51bf91847d4ff252c75a9e7adfd404d25ebaa9497220252791bc7481984c770555acedc06ec773c34a5bea72d3752f2fdd2028d7055272d30d7a410faa48294b731845df748de5a953cb824ae01226d46112d049e34491421d4ee91bfad4211548d437458dc33bd42ded6a2c3289ebbaae1e9857cf1c7bd8cc9e765da9f1f464fe7e6e5de635cb5cf339273631ec769957efb2b75cdb7a7e82befafb8c479c3fd0aa1a76bb218fe2cf7c504ff3d3aaec50c5cdc4a95378441b004c8c705605783835580f4786caec69652327c6082da4d002091158384204494a5083226c9162092d17135e78ed92440a09305b0a83060d9d2123c18327654778045389a9e8fd587d365d359e212b0326b480354a1624bd02db92194d2937a081155d5890840a2e44c0326484225cb10112531031f18212133580410eb164890d86380211484084f7c587151461480840107951c21639aa1598c062664e481a0c2173828923488d09d70f55ae1d500182c833c8d981fd2113c177ce0eae900a42b085102c400108888ae88007bc6c39c1921bd8e0053440010f6860844d16ae585902f6ef8a9522501b6cf16d79fd89478e94e081a8f347ad478c6875fc28f8dd0f3bc24c8317a6c8b213bd1b30cabe797d43ca62239d3246a24ae50dd2899452ca558c11461821841042b9411f51588e34c618e323f2e1c307f4e1c3c70f207d6379ce3f95b455ead46083456dc49793a3b9b6913dd1d5e58f87f6c97823d12aca7bf739e74f080cba0bb0594a1125acdfdd92e4ef867cb1f931b324b57ca1c83c832c4868232787e9df952a5b261845931e31c2d24246ce0e888034cb12bcd00162bd1b2baa3cc740047b0d8ac651342e84022bd4e08a111578f0e50920bc280a628a2278c0050ae60c8a1040ad021111306707308011c4142054590108a26084072b28c2962eaa1802141ecc2089a44e74cde774dcaaca15f5df952a4258a2e31ee8e30518342abe17a2aca2b8bb0041800579373a08f420417c04f115c4d1fc91fc51b7a8755f9554def89a90fc052448db9056b56746b0d0b9873fbc5973a8cc36b1ab261c0a052dac2d395083a269ae0a2411e5a89f54a852f41007e54f78a0668a1b00c1355334111341d44c11af545182f4ef4a1526553ef0ddcaa84b74b7cfe6bd9b39638c312a018b2f2cf1c2121542086137e423d80ec489d05647a17ae7419c3725a9468d1adc8c45014e4c7064850455bc0021c4c4045592108526d0c005514ca008242680f283228880821d2d8ea67084267ae0c5162c9064e1094ce072041f5061e7496185284d0851c40a64f0c3ce5352050a9c34a7e52d298a9e7b4cf3fabcf9aff0adedb8527c79ac7d780cfef058ccdef6aef40088c76626b76ebef4018a2db2fcf328df0dccdf9d2f3df66445e2678e6d5bfc4fe933c7668685c71e3361df1529b0c08657bcae4b5ed7bcae8bafebbaae3a83d40925f198bfed5d91228cbf36a1ef1ec93bcb9b44ea213def2c2f691d75cd4924cd061dac94b1a6c372eb06ed76cf2db7341eec09610930b0afd88c175d7aec919de53d96438f9a0f211dfc7b343a6d019643f8fc6aef60065a3e8fefbd87f144028f0f5982b8c10da06072831d54a5c2151848e1c3151e28c150173bcf1f8fe028c2e8532808de20283870007a5012de81d7480fd07be02e6af083233bd73d025dbad00e756b7be189659415db59b97150c56e5385edbc8ba08ad9a592ceb1b19ac962bb9609c376abe7c6e2d9990a2644cfcf9e03c933511f75c327300c63be9d94c2dddd5b47f3b14a3927a5d5b22ede302ccb348dc45b29898c376b3798cc741125c1638a394da122e53433c333b29f6ff70019999999878a81c4cef75d1ec0b0ba7543ea86c5a7d55aaf85ce1bec79cfa68379e8437ea06cda74f6969a2d7b76774ba7321a61afa66218a682c2529fee987cb0d66ad9886158ac447ee837f7eddccae88d37ae621058a43506e13b9933ea5a7e51778dc70c3d561fa55b1a8fac959f7f66adf5587dd578668c31de0cd1b1a629a8d46df6843dcb189a1101000000f313002020100a07c4218150402899ac99ee0314000d8ca844805617c95110a41442c620620c008001000010082401434069a07181ddaa605845e6819cea16a03192feedd8da33a2f85ec096ff4eb857c6335b853511c8881d44a9f6851cd81795e48cb89f421c878c4cafe034aaeef8f7de8c04e14b8a67e566390bd17bbd82d1dbf2aa7c8593c280c3e9a25e7539973103fd8e73b4259d19ac375be65b643b624a4dcdf3958a3291a2890e98f3184e864c76aedc107d9498f117f87c694b97527417f443403909acafebb6bf9870f95641fba05fa0aade626eddb4121ad3052bde5b6987bc7338f5364bac6674c1c3ef0cc05fcbba71e391ed99ef642d013f486bb04b732b1e1524b76efdb57f6699f22499076a13117db52c0da8e996962ef3eedd1043220579ff3249926c05d602eb836a389f0c56ced3fdfa25860f1423d1399d8f2777551ebd5c741e975bf080335b7661d8d34dba54b38e1716afbac2043c5d204c350093a1e9a33ab1b508bc36398e6688329d1a2d0834625b6ba9022295a5751b4ca0533bcc82600ae73989cefeb9a9c0c1a2fdb840853a45d385bacf9b9b03d4b74caac1b4a24a5a3ce71d338a11824fd9718c0a947ad323f5c6aa468683a2cf561da32adda36ba77bfccf4a7b9e83e3759c95eff81c8a79f50afdca2e3ffa9d9593cae85b4b467b5bd3d9ab6ebb393eb515aeb62a9fb0c0a9e85f0c77e8aabe740db5eba83c6fb28119d7a2153870565baa88207a7c40d1879bae6115e73053b9da083ee9b9fbb64d63523c0f816858e9f0edc9fcd16c7983b79b7219495eedc709404c0bb935026254a8c97e87612eb3af8e8e38b0e28171c65aefcd02d609bad27c9ef07ceacb715d078d1f6a549cd34c8fb7cfe2c8f886effab97f3115a4efa7301775e80b4911b95092b065e06b4f83be008e85bd0c9ba0fa4203d8c8c4f658f54b4f9443f2ce731bb8ed98a1326366067d61330dfea54719617f59eccf17be275207e0d50bfeb8967cdb0113375b10a282bd48c65ee252e8cf9710ec64b4f37ed96191598d513b06bd67feb991d7526ac46bd27891344d78b6fa162466e2c2da7f607bf8aca9d27bc7e1f9b38b751858928e56f323f38cdc5cd64ac9838d6619606f03557e9e25e7818387e422188fdd427f1710cf0e4f481c6b6a65efc94045b43f97e4e06c90c3312fd3f81e1afc5db3c42c360f8ea029705482bd4c05358b8511dff7cbae267dfc02c35fdb2b2e00aaa711a6940e83bfdf4f014d8cb5f9d2b76eb2f87f23ed98726ac126976853135cfaa52a9fa67562c7acb61b08821c0ec668ed49002d7e1bd1d941ad07fcd0f32485647d15bfde6b8422d7880c562691123ed1a711ccc571b13e3837cfbd61ef4c17d68188a599e0c474faea0c8cff9c4440538a0653b36e4fc3905130303e0290342318f11e44d39112efad0d936dc29da78c305e16403cf11d34ab9e182f101737b2c336abe1a25214b25bbf886cb8813e1f96066f341dd59e58cf5b4359729d49ff18acaf32ef14b1ff5b3b45150c9532a2e82a61c0aedaacd78a4c3ba9c393658aea6043af0350f4db50f560acc0e37b7cee01ae7a556965b72ea4cab58f0b003ff8810acef7f8403a0e3d0ac46e6a2fc376e523b684e63cc9020f59654562dc46144498d1297d974e6ae1336bcbdf7f92a4b31ee76e3db836e9212ba531df1af2efbb441872e7a25e0c486ad7ff0ef5a06ea0c9e35c19c1a88016c15a0c4943ba0fa06a65eecc179de5418e90e49ad5d80ca0a04929e460eb7a4454b2b75cc1cc6a21f4ba59afe5fc862645e8708dcde1f663901f0239527775be0f995754234852caa94b4504329cf932c67ae1bba032e0973782bac183a0dea6524ce31b6ed4819c6854bcefdb691e0d585bef9da158abb568d0ef0773f9b63d1c8267636fa018105fe51927b2c0b9defe48b2c20e94486b61bce54606924c4a2ab50fbd4f24f4d4dbed9c89c0319f857fb360af91379962c3fdb9e480f499cf031a5ee73a367b0362249bfb9869c496f2ef7d1fd84186bcf385c9ee1bbef43cc6f53843cca0023488ad320725b6110f5f07ed4e373a2a67c34a6b464dd80d06ae6487e040a3ef1950b77926386c1438239aa2154d9206056fe19828f5d3d4ba6ec8e2a838cc172587282f86b1ea407e8392c8cf952087c4df00d3bba500837273b7947d5e5db1f5feb0a738378de4e02a85a1e929d9d17d8b9f24a90c6b90d378ce0a7b2ad5479d9725f2ad76f26d059486c7f6414e7647b2f9cf4ab36f532b6efd69975bf6a203ee0fa388c2ec5b817838b5fc87e5b17cbfb93f41cf338876a9d3e9b4d61ed736aa41a7d1752886b11efb4e816dce009dae67c89cca46127171d8890586b8092873f2a49a280ba480e429633bb68041f3d7ed105e05287df723b7d03e14682bde148273e15e920d71a4c36c37db19094eea3501e8c29dcca9b6c256b0578a9a40bd3a9522330d6e02dce6d68a4ca152281831b140c9a0b2902d80318a52933cf925402a1251e56cb27e00458190ed324d01ec1868f89f8cae4ba9c59ec1b550b45bdb84df031ee2e65d1048c498401bf35e2f32fd0ae489e145ae1d8259400bc293df405e30bcfd713e447f4057c31c95e03c267d1274fd158e19f36a6d08aeb4ed6256aaf08a62c447489b9f4430705f3fb042254b219333338ee540087fc67d463dd0c7428c1c49b66285c2e815746040dac727eb246d978a0382bc1f7595cb015cb889a4c72bd94694ba86d87707b22c63018040c6c6b9a2912a4407e410ac263d2559b3fb375cddff5aa5ff805096ee46af0da1f9332921468a78543935bb2d9272b7fe0afc345de616f6a889d2a34d1c212df0c83e38df4f545990add338f876d9f7138dcc5372d9b7d12d58de0fc83c204928f1d0fbfdce7a694a573a0b369dd474dd2c9575e449b0768fa116551139333bd4e70c5c5af481884d69942a0a7765786fb5b20f4ab67da89576c2a0dae6f15ec976661754f00c8f007b59b533b5393f83b6ed68119f73ef88a38ff955b8bec61b898da2bfff5785d3b22eae4bb9dd77694be9d5cd8dd822675ef0485d53e356874451bbc687cfb41a19727445bd6a34d79f3c62490b399aa942ee176d400969e006b5f40b043d35157dbd3f015c37878b51bc067a0b019642f5460d4137c180afd7f11520363cd8864a338456be197881fdc05fdb91e7bd10aa40bcbb940734f974a482030c33a27b614811a0b0ed99ec3e9305d834f2bf3fdf3308d0f435b4c958ab67cd144c6e63f7cfed7e5bdb531268376bd72f24f932f86df28aecb0e11bc49a84e17702ae65fe89964edc4f9ffca3f56680ddf07c7bee34b36198c75cc91ae0602b8bb3f66ae68d3a6e248f5eafaff4becd12dc26e683426fb52008df86bd395e89aa673b27d2e08c7df8dd068a9126051dffe19eef7c9f135329a012fc69d13cdf57b04b3c1b0b44173b01f78f80ca4b8b502401e3be6dca0eb19b1428b22204feaae01efd2326d6c66c1ff3ff1e2c550eb81a17cb9f57388a819912cc56f592dc12c16d493286fe48006e7085a58a0256a517a9456a7402dd5eac6ee88cf94bc352f5830ae7f9e2ec54ae76587a47aa0c4683f74d51dd2114c484ea3bc349e1cab3eb10f237208a527912e90fa46696d32b6f7c99ed8fe83a71ce2559bf7e497cd21c74bd0a69cad30a00c453e7da529857f734cbe95f8807247383d8f79de41ca22b90872a3a138a6cd8d5d9d5351e47b6ecf114553757e798e9caba95a676a1c3f0e17d63ebeddf0616bdaf8b59cff7be3d30fd6c5a69e4d296de302f6e320717168d49ce7c24d3e0517d62856f6be0c6f03d945685604d97c1efc24ced30188f9c1c6a1ff5cb5372804a9758681c248080107cf02850c1406baa10df50baa401fd4317c0ddc012fc6d407cc639e003e2c49bcc98a79cf21e8a16ac3ba75352c79e246a0f231991c7fce15d516b6f0190e1021a47be18b9597ec1240643a909191d35bc29251bcb3412004bdb48f64464a1edd90bda20d4f8e49d6ded39f1002ff7d19557b1a985c0b255c5409101ec06b5eb171ded7b7eb32c445fcd5033bf9cd671f062eb77634ff2f273f71e9dd1b0eaa00fb15ce0c4e1a50c9216d510acde21f998fc5320047195f973d3fefcbb938e37b4ec137b346b9a17262965b4357fba9796c1ae18941f04baf7309d22fa408f7eaec37c0de569c093ae120d0da707265dc318efb2a21e773e88c4a0640932ea12f1210182cc8e1f892a5800781af1ccc47d025d8fef0c79683dfc517a42bd4dc5158c017e696b41cfea6a8cfb22807f8402eb4d2746a26fad9bcab37c4d22bacb94a55eab4f73e9dfe3a3d714acbc633ff7deb794b8ab087cda76bcd1994e72370d28b47e6fab8b1c09298f2aece6320895c2be8df0846fd5869812ba80a1fb5fa57b218561ac2d99024e5001623a2197a9245bfe0ab1d9225cec7f5a3f3fd99dcc828feda8ccc7d4cfbddd328983e85aeb9e2bb50049fbedd6748776fef3f97afe4cf567db6f495b1c2af5f32b551148dc1b8375a09487e363e955666aee3a24ee7c6fa4a8e79744a5bf5270c1ffb93dd8321c5effc1b1dd42830932293df7a62b78dde1323e33c2005ba4317a745c46ec8ed2b16329fda6fad6a9282fd05762bfba899b4bdf20d9e7eefd52eccecf338b04d0105e70c817f2b0bc19780176507b380ad50c957e40144469a9c3c677eb3299a47b32c15a5a7505c2327dff359de8120ac8a839ef503a2fa8d3aa2376335e9c864446bb0206354866294d8648d262b65d1e2a0349f0c5dbb94827ae55c1e4170174a3d68300ad070d11bdd6b97b2d68bacc92ac3acd4bff68aa579b633202f535a40b3e47015fa9cdd89fb073daa558045d6c863140184992abd8ee0075b8bd59c256b4fe987a74e8566d4bbc287a5fade9f016ae8e749ecc52ce328a5209b3985a31bbe7a5ad90dee945890a19197928e73f22c661416d6d7504ee452d834efd58392566e49afc654a4c9d90d5864e8d6b3ccaea8316b92779a8d9b2dd0a490347914a695e1c2ae6bca1b3cc040f136ab88435b9eb5c655d49bf5aee5e522e8adb078b5b73611d0904d5318845d5e7ca68eb1d041faf5cf32995f85c34b7afec63cd0f6e9667ff57c266df458edb797a65925f39ba04c90399e3cd7882c258e02e6e3cefe26660df0e871d83809f58f31e7316846a6ea290a26729a359bbc8471b8a28eb618a5e78c23fd5343e6ccb12fb2ed9f12edd37f2b3a41f8942e68db6d266a2bc47be0972fdad3025d688c9503fd731c238c301a4d568ec3564504a08bf3eba6ba144ec1832c906f05f1ecf3c50e95676edf58292048ac6b999dab5f57ca9485203c099cb3e306cd76e6e36ee68f269a0679f069f6f2b11e324e95baa97fb27d4219876ce4f91e8c78349ff10347b4df906fc54e8915385a83b94266464a49d355f49359f4236fbb839d7733243816e0d520c3ce98f6f869e2c48a070df2a9fd0c2bc1ee9e55f714629f841b2a5bd8f9154f1d0edf37ca240e3206bfcf13bfb21b0bdf421709379424ce28248a99440ab5113d07bc5d68f130c0bae1c28702b6b8cfb8a1db1be63b5060c915a00415370100f27853fe3b40759a2e3815bb1555c4f16f797f601954cdc9b5a23a6249e09436b8015278ea18844b3180356e3965364ac78c02ff1aef5a934225549bf9e480336018c65d2ebf11eba1c272e44d6c292d293f54c21ac26f4ac0694445bcea8dc82b66971bbdfb876fd17818c16aeb9108900661d92db56b1261b714f4e87135052dbe634500a9b081dea546f4b87459ee3192aae9d883358732c7bd1d7dce6a30ff75760a032f1ce19381833321fabd03b790150af646a63b58998bc977382ee785fcc37f54724ef35464725686e28fd6292ae03c16878d6dbe59970709893a87037a629e8d48d87521d2cdd05427568668b47963d0c81b61b16134ca97cd33c1af3094289f27ca165328cc52bd1b62f51b79489321251b749c80ae25f9ef2a37122030e80e615c5be49aef16d634148c70cd21b0af801999b5f730adf45de4d99e74790f780d4d573547a341573e1ecdf5034fa1bf42433dc579a1a2f4f96f9f9f2bcc85dd0f9e2bf8928ea1fad4cb28c2548ba8d6bc933673c8760c671528a0b4fc8631e316226a35884f90981739c9c3ad155665975e60f5bce89ba7f99a925fe174175969ab9ab405787e7a8c1a3a3ae4f8138ded8b59733f5f24c5097d5f65a0c583655e0053835d74e3f6d11bc9f5b076a1c917c8932617a82975776b00f12653b266e09ea4e33d1c3bc8fca9d98197a39d8f76a539d1a6690ec2a96332648ccaa4e087e8f83d398516bf1632c4a95e9f88a883d26a0146e87dbdb73986cc270b7cc095ab6f3a5970c1b1c9a768425d256bd986fdace1d1468d04bfa1f76584e8add83aae5706419c8d972bea479b5c048defeedb8beef8c4c509d5dd19d69c58a7a4feaaa367d81213faf4c6dd51ab56e3defa2b8a7b8c6653a1758d2eb75855f9449677e2dbf792146e28529ce71d971f86f182dc55aa8f3f0be101fb096e395f131e8c3433e39fb2afa0dadb76ac00ab69b52ca8f48dbe266f42ab810f0c912522606e950dcce720bd4474fb4a86fc67a51718b71b8bd013a3de30fcab54343dcda2c3ff654ed91b1d71786cdd134ea462847d1973e38cf1011525615f0e1188f6a29787ec72e4c53aa2bd4525ba65157d5b7ce502f31506bf87eebd76d1e0daeb18601c6fdf07503a89429e20392421fbe41b5ff4d5c0219297f19efc02735db80a33bb40acc809fc5a7e2c111c5c4f6f87ba9c9acdb37e19e9aeb4774b10e2a868e42f698904820e04b3faadf60d50475afa953074ddac83158012cdbc32d619e43abbd65bdcdb855817e0f6666847850eff53c1cf3002a1888a47dedfec62ae8449fe427fb82cf71ecb4c253eb7efe640c6f550728fc08dfe43cdeea2822d5443818f8052a928f1e9b32c89416305d46c555fa0cf9314934810992d107b92a3e838323fba778cc35c258c8b725643ace13684fd600d97815ac0528dadc2227e028c5d3044ee21867963a01d54a2b0be3bb79588c47f73a02a3036f20490cf69ee0dc070c9e48739b6466a29c7912819a3d525845755d11f452239eb286ca2dbbe34a60941f612161b9f4c14d4b1b8e999bf3be8246dd67b63bbd8236e42444bd0a755fb534eafe3bf294334591ddbc05f2a30bca7f176ee28710b4b50161837d8fb8fef56fc98ce0f40b447e3abf6a412b7b06e19f518472ab680bac55235048150dbd5b9a1d2f4285670fafd4b1cb10358d8c2cf7543e47c824bc38bce8ecf75e3f34ee71a7e98611cd857afd84e1e5fd7d50ab93e58e845dd6952c45ec22f08a81b32d983b0f77810cc97508b0f3d71e8b6516dab849050561f8bb17f8b0b38754b87f88731f9ec6cc7571cf0a8a226da242112dd6ecc3b73f90417274d3bce7733ee5c75d14f417823860ba541b73a2c9312d77c6bb8fa9c62d9f95ceb632b80fae69554d013d92c87b77415ec017418f96be4ce2630316c98d785682f110189cd8043212ebccde76f8ae15f2ec4fe50010a122204bbe5592b0173ce33d148374f652ef1685cb9169e38a8428acf1bec29a413a022dcadd3143506482ec711596891c3e121c2189101725e24b678c7c5ef590639b9728cc842c3313ca2059b281025b91e35be373ba5671d756e41ab6c1097edefd1c74d114cd0219642618ebfecfacedec080f24ad006a252a22c7e874a714cbfec831486026654bc2d2a90576bfb892b445e591ec2e012d9d2e607a56728c70b0039521540d97495f78b43452cf9ebb5c56116490354f2ed4ca6ccb91b353d6c7001c728c6d3cce1ebfac2b9fad34f159422bbe61ac502c5cc35d17dea923be059f4154ade5f6d232651c0fcbb875a8145aa3c9e4c7b916e93b91c8b535ae22fbe338ff2e79691e497e00152c62ab018ab1193b257ba55a344d7526cdc7e6a1ad15ecd44f534f18bc6e0b404a5f573b78458b7a3ad5a3bb8c043c4a40d4eb16ccf0fe6838f4849eedff30d36c85d3c3813c0edd3cbe780483f53bdd8c18ddfc76729aeb95a5f803b670dfdb4590d2b448197c78ba484e0983791b622eb5b43d439c13d0f9ef19972c684240f08b78c8c4969ec0f2b79eed5912d3272051090e3801b68ad3598e185a9fa077dfcb5f26a17809ef31708c23d40bdf1f8ffd6f8bd24c8b2d2fd420678b53c82c91513df4bbfe241fdccafee49c18b2fc84fd0716c4fe63e54a12dee29fe063cf6303bc3be6f4e057f0b577c1ba1e547a32a39390a43d3e05c9c63d3b68c983f145a0974c41f6a0bffcbd7fb2e44863a152c77c780624042d3fc1d0a336bf764c203e841ff442e52de2b70b9b16fd77f73719c8fd5884ba46912eefbaa113edfe61c41ca63b47e9fbe2249c689dd10a9f62fedf7d92692dcd8f738e498e001aa96a953d5baf3e6d1a8a5ec097ec3b299a2b7be4d3f3d478751fc106ea7c8db9490b76bb41625204846d88fc3edafe10b1c00b356c81c206a91a7344bf917f0e782f233afa808a3d2eb87660321b663efe500ae365fa0623c793ea2a0ea458405ceb58eb30334fcab5dee4701373295e54335c3b5611e3598b6492d0af2f362c37ddca4214fee8c71f6081e5538b7cdaffd3131e30a69a1937491584c95924289af962128447f1c7cb4540ef4df062c2f145209f70e42eed257e79eb23d481629fc2c75d2440072628bcc471e3bbf2f4c3e26d2eec492db6000c26ffe29d22c60ef8022a4c97254047738e850780f7c2d2059fe61195f4bf64b4a8325d4f87a9e9ba1d5731a2ed2d7e5fa67e93fa30342f063685e582c6f3ca04b0679db90b392b5491a98483de1a303458ece0a99f437ecf9f8de3bb9b52599e41b77e7612814ad918031ec417fe79007f9fd0c3a9fb32bc1a9fc0de61d50f89eb84b8393ee0b5319713b4961238fdc771b197c0eb0ddf71420375451f1a33a3164a846c869d3a91ff5b3f35a44f2428b6306e430de39896193f1b5ed77cf3d35a7d7bafac435d91f4400c6b9e9dae36424cb31a987391da5bc032986f14b241145db44adfe12f23ad4ddd58b7a7e4f5ee6135b66eb87d15b584fe560b4cb3e14ba756cf3c7e8482bb95bb6a199905211f153f9ec4778030d1cb5d98443a84e32455a7e6a9ec8b96c5c41120ec85434ec43237bab5e396565659799ab9d2c9d75d2506c5c42264c244258f63e663cc51418d1decfe7673c51957aa4dcb5062f0bbc9785109bb6e9689d6f70f6efe43d22b5da8a552b000043d7be2266cfd7b9d87b4adaeae6e914ec24d72b8606e1c0da2093b8bc691d4a199a1655108a35c74107ba5ae8eb635da1bbac7c7fbc73ce1dfe6b4224327e6e9d1babcd5645f93eaebe2409bf1cc24c9d93142443a9238672c7fdd983e0b99478b8309b1486834400c627ac8ab1b9e798264bbab6d35908dbc94ce3e9050e54d1fd34be9df3b90af803b8b63fc8481df7e52ecae23e57ba99e15e16297a76a53d16db29c14c828be8efad653486576b25d03a225d51944689514eb89e08ce850d1247e2a6341095608818eb07c85e854d67df01f8a3abb85189ca1a6c03d631339dadc4e77cfa7fee3025c129bc177b86c62862a7ecb0061f2390fdf6decb12a0ef5c9f88f885bffc311ffcd8a2ce736d32b103670ebd4d9b2458fc93907443259ab56f1151ab1b3c4bb8fa08613c261787aa350f76f4212fc5aa62a70735258758fce7281d99cac02ba274f8854bf4ee3374c564a72cb76adfc604014047d72a431f2eb8eb0ceef180e6023f7035e22077ceb4f17ce90615c2fda6e0b97c583016aeb496aa1324e5c22ca8d4c4a5d7e898b9fec50945239dd06c4ffa49576d5aa0fc05bd389b9cb052e67178234e81bb6cdc1e24b7f5090b93f59927fb21c2af8d3ece9a2c24757d3152568f2480b330014f3d9db562dd0cd6776bb17c673732583f5a296db2a6b02f37a6b9815c56da514086f8fe07375e666469ce58d8daf3573c0492552dd12169b96d11c0a59f633356e410e32b58c8d468897075082f3e1fb0c38d5d164b0927682bc3ea58c627a4e739d2d1c34388913fa7948a371e7661b1d5e043e2c79a2bb3eec0bdc284fc0df1380b039f6c974d0ab6863a0abd5b7197fc4d63126f26fb12b30c81ade249cc639120e85b41e0f90dbf59d94d1b52019986d010dd0e17a1ec7ce2f1602201463838887d0b2792c33a42b073d158a23418b205becf6aeba74a39eb59a49ef0181ad2800af3890c5a37d9a196ccbc13544e8a6be0b71212a1208338879a440c967d0deab59b60ca65686847da49f1bfdba5fd26cb79d368517f80a86a130750f3718c2a5e89dc321e05ad551ca1aae983e7ab69890bc6ea53eeaf701065bd856079e69deedd565a70ca517e210edd06ca0fe3ef8089f728d849d81791e29c6d134534751a5dacf39b3059b56537426b841907c6d0f5cd9c6de66ead80b90d10107dd8ac92ee758e0cfb955b8906af89ce145e44f13382a63d24093cc55a28c9b5df16530df551e7be8b1503c3f57e9c9a9677c0be683ed6782b100e89907e27804adf6e1581ce4565a48d58acafe300390a4e962d296f67a3e48a750430fe99b11af3ab13dab5f493e087b25d63a9b9bd97cf813c50e4ca590ce1af616f0a8917edaa8565021b12a23763de3ef88e8e8ededdef64aa4cb261b255c8341bb302dfc6740ea301cd50988c456ac6c42741663ed99364579ff0712966c7ac76e3f4d360a2013c757423f8e5bae00ecf67f32d2fa2f8a0e8e9e0b08501c8021d22c66acf2f4e7358163e937dbbe482c1cfb8f0efa68f41445ceb436c54522025900f4ad8f8885eac18a6c104802de686731053676595b1d030f1a42b93d097b5e74b598069c25a55cb1db2c1cac8bb9574182bf85d8454402a14a79dba2e3b7202a654057de04b46b5de30247ff10ab9ba3eb7f7f29d0f8c5e4405a07285ff55d5a05429cb7e76e0ceae49a851b0b2741644f0623a04ec8fcaec192bd8d393c67ead04ef4882af26aca111275c6ed0ca68147431fb5733ec01d940c0e240b13503c15a98550e65417880e9f69531100f999dd852d3845a61672316ee7cef8e734835b75b2e7a4a59f3d9e7f333d85b730563a5f39a1182f6ffaee1f4f5c20d912528023d65a03ff2273ff8308ddfa2dae32b41311f7f3df9109dbdfa9886c67f177dc5caa40815aff77bbdeea6c62da66432bcce4405e862b7ed393502aaa1e956f33acd4a9c509c6886378a94e248f2bf6076b360a25f11037c8d3fc133e151f2c916c408bff552a82c1876f6472e7007398895043eaf6375ad3f9e54240a3006482868375b2d4e8ad8f4c43b8c25b484ae3cc2d859dd542c11ed136d6c3bc41c57a61ee2dd81733564f1147203e013763bdaa5c3606ce110a0a459013f5242ca49cf92199a863904cab66c459647b531211e3e7eee6ff6393ee3dcc9477274de0cf2e7e1e616cf8ebb0650556dc5f8afb5b117f2bee2fc5fdad88bf15f7b7e2fe56dc5f8af85b717f2be2fe1aea0862099977355c2481da55608958fe1270570dcf4c20c5c92dda22986a2622a2c85f3409cde49c4f23d6afc4fa957969e6ceed9422fe56cc5f8af85be405b96682d225044edcaf68e836a98ccb6676cd654440594546539aa3fa7b40ea633d58e3a7f4489ece0ce2836fa615fc1bcf8412166441359a18e09bd910a0a1be1a96b7504a8f2e6cc3ca2d65b381e79b53d5aedaac6e337191438eb9949af361a39cd1077fd41680d5a9c5e31eb9f6cbd4d481c7edcd77ec44fec13861c3acc4d1d411abf63fa99a1dd5aed4fc624f5c7c95c8e80dbb3ad6a19a8a3bec45c7284d0d1eb8db20fb60e1882660c3967f9ecc75d15be044e379fb70dcd9cac5323f6da112e8f3e95b72d1fe3cf709fb9b4cfecbfc4e9bb9f153b08988fe99f452d7bd797ac1ff43b5178550fa9468befce9edf156d6c8ad273db04afe272a441ecce10f639dfe2cebec8553849d821d745d91d416d057d1733483bea0ccd9299006b9afe1a99ef99abcbef94b911dd7b3292b6814ce70ecdd09df7d5d4481fe55c8a330970abaf29140822628819a84cd28ea32b1c3a6fd042ffbb6ce090575f78ee2069977fe2cd097164487eb904ad0da1ce603f1d0806d7e2e6f2f0fa82f5290b3a47c989f696672ef1ae2b06b4f0d70959680691497263ba81c5e5052305cc5d4951f24a69e029ef15de80ce17cb0c928ca9359a17b65de31bb6ac54ac46cb937454ba5c0ac11ac0499d3b5cda97637e28c342872ab0eb56802c40bec20629ef9515559964463615d2901ad9b51dfc65b6fb6f406039fb52025217031199b7113330facb5e9556c4f1c71413bf71033faa5553981a10f04541aa48e027e69d019aec3b889b94675fe8bd27585dfddad2fad3766ff936f7710b6adf60319321a0bb73d344c039549a175a97df554fd9a949eb4316e8b94b10eefa53dbdd3a5010f2d0f88ac0591799390e41a5fc303aaacc81dfcdb687fffacc6e7318449d5b21c9d5a9e2a2864eed1d7dfab1b6a4d8e753284025a4c4a7575db4d4bd9781d00dadb3c00956c76eaa9eea42051dbfbb22c5c30fd710118020854ec07b9e7cb0b1379209973d444371f9599c61789992e83aa71daf5b46e0a3cfeb32103d043c235786385adc23d46514eb8c871ca05a65c125d142c58037cf6dc3f49be7919393b2032bdc4f6835572932543895f6d6b650915d70cf564d8114626a09590c1529398af190170ecac465b5f64368ccc9a304b35ffe72579ebe339824675acd89e5948625429c98e322dd66f920312c7af25f92f3bb7af78aeee55814cbfd066d8187082bd3ff2751357a78959a8460f2e54ac5d7ffc16db23ca0c4e3509511191e5e38474b45885e882cbc4019324e7855db185cd920c6e34558f29fb54b0f80aa81499fadd0ce92c330b949d8cdd601c590131f30d731c18df8fb3a3a18f0162f360f4c7991fbc3e7bd08f228bb037354ded3e8fedd4ea07df07e07d1a2c5390e0746d089a016c0477c2f31679b656c5cc2e236b15dc94ee15b4e3afb15d93f7b5125eb0545afc985745556283ea0d375ddc0d544f49387851a2bf2785bdc207094452a511ac6d6275c7f5f178c122a282487296ef62b51dbaf5b549e4c70c778bbcfd4442f7e12e96a0076787360defcd2f9cd7df92fde035c1007b1b5e82832bd045a009f29bdbd3bb244d7aaa4dee06e95f607e3fd9294e01122f44c987efdc80ab93af42c97992ebf70727ef0944424292177df336e72501545d81122280fafa2c07361a823d6dd19f30767f2dbd7b29444af7449cbf0172850a3a435b701102b68ce360d00aa93aa322fcbd807672ce993c76c9cb7af6cb537c2cec5af0456ac5f3294d3d1b74aa4d37efd01a537ae4a2cc140c2437caf33efc55db29e2ec17da8e937e9540b30ca94f19efc571bcc16394118ff5eef1b699198f9551aef55d040a3982ff78cf66a2b2e83ec57b03a38b8bac9c7887104e1cfb6b671ab9adaed7eb18f5a2aa38acaa462cf740508371cc03cbd2666edff59ec87643948d98e1787a79a2714db1f0377ed690be8ad76c47b3b93030c1177046af53d5ca9b0b9e964f5424b7b6209cc2b9acb9b1bdea117abe50798dd564f2e4747849a1c8a22fc6e55386c92737dd4f5151d93222d0e72ce16743e486424e5eb002e17df25344ee5a55c8ad153cbd131f4341a6ecada8156a9f85d01d6956dbbba76c14560c994f000bfd61297827d93a07ada88c05c5093bc582ec894c2af52fb772463c8a13a1d1cb60abcd604bbe89e00a2b57c275448cdf0d754e532e95ca13032f2667cb2b8489e5ab994a71670b5de3e16cf85f8ee62221f648fbf74e637a320dca9c32eb3b2f738a09d49c0c80c1e76c8ee17844d00d953d3c8d32b5a8a2b5500c847db50468c2c666cdcffee8ac621d3c81d1a1cceda7d003ef5e97815c4475af988452084413afea70fa634fdead5500c2b77b160491d928d871fdb334f5e75f61983a6c71a6c4e16b56c06c9dbc00e22373d0441f3322b05c6853348d8234bfb73781b262959a16172dfdc3682b1d0867882aca92834d6d74bc81040469249aecb634cb941b639c2e7ef4c32d971b14936482a2f0e3070201ab8990207b2eba5b00574420e874f45ab01636188d219ec7467d7b137b3d2b77af386e28039de2dbe54a4f0b076329c23f28bf8d3a6eafa2c53650cd628fb3c710b725034c4537f8d3c7798b18cad633f8018f5dbd664e7539629ffcfa456791816b36a4a89ab471d3258e89f93e4a02fd8a8afc3631db5da18ad17ff945d03c35d80827cf887a29c34200399382acc08a4b223d824a20a2b668c3ea63e02ea526608d4462a4c9195bcbfc8ac21c46959f0d64a8327b4cc56fe15b15bc8202968f98a8c950f79b7e7af6ad6bb789721affcb9d44e29b0d76766b9d5c94452e411ce8c4e56a480d482b0451e096ec0fd28102da1913d9bb6fb4b6ea1e5318e761d25f6b51dac39db1e1500f413d5819bbbf7788a8e6ce4bc8788472b4cc83f6906f4f786e511a345e6231be4bbdb303f5a84a3b719cf81d500ae2065cce97198da734337132dbf128196c9e35e10537eab3592094446b234f5d628ab4bd2ad2d20b04e9c2b93221b8fa83ef363509912396d45d21881ce993458d1f505949919e19465d2720d1cc3887a55a2968a74391e778c27be1956b144633a9c95313accdd19b51247cd307b856ae402235881d67e9f2a7d1a0d358a31be18b83452f85efa00d227d4c9d9490d1c7f5e72bb42af6c4af31dda32fdab35fd81914973c44aef79be587a232d825e4ac84c7b1e7ccfd9a69ff1dc59542cb56d140522d23aec67ac0c1a8d331ecf83a4c11c76fe89df5b52001f0e119173fa8a48aa6ebea40f0ef10585fce1782b1ae4bafeff09075a3893d17a69417b4b7be8de7ffca0208200fe899493f7fa066a6c19d968eb292e56130779313e2903fddeeee6e50de6ddb44c4059f190a6f6ea637d84becae73d5b2d7b769a0151cf429c66ba7163823b3e342ba613e048fbb25d3d575e3c8cbc0d19d41e3e4f42e44cb5c35bd20fd612ce310ccf6c3981a33a75ad870d2aa62246535f03c3ce7c9579432e997e99c25cf62774e9e25ec6163d9251a52726f04d9a0d9f3e59acba6d1d32b53d197a0c681d73971965df83ddc047c94002f9d7b1cb60e095eaa2d2a35aebdced370d993bd616af2999f0c659a4ec524f1ac4319c2c122665ecceeb00802d7d90555ed94aa14b3fb31f73410675032cb84d5156cf7ca08464c8fa81c9b19075ca49681961e12f760fc37c1ae1237ae0da9473c2af43672ca640e47ea4675f726a72177d4eb387bcd478eb6a0b35c7bc39ac20a8da32c579c7b149ceaffd0dc1c99c24a4468a5fdebed76b48481d1da16571cd81935d63a967ff0f5df366e83f85580e6e3af8f6af2c5fa162b012753a07260e66edcc249ff037cca1a45e90e890cf3ba91e23e8db5361375961b136e0c15b2de41005772b62beee0728c8d76eed5fc986ded5fd1a6b0aabbd55674813acbc9740056e9a77302ae3857e7b013d026bedb9651401f685407ac44373e79f041e7959e8a051f50811b1c074765671bf76a5354a62f4cb04f92d3cac180ecf32b938fed08b838284c242d524e45c550ac8276b1c9926d383ee122ee426234c5cdd3d988a0d2e268c0ea04d44139d9b5dafc8dc5787e6d8d0be60e0f272d14c9f49b579acaa26c647114412d0137c5d76048e27cce00e94e9177f5e711253af4175e4bc9fcda2819e571af9dfba370b940c1b547791468053391f8ae48d11f6d8dd6c3fafa56a05c5a5ba07676035e3e8ce09134d38a234b35f2309fb8c72f3b5203f1bcc5653b93ebd1695df260fc50d0c708b56d957f14daab4b501abcf93226962da1c37f999e8f4246bbab50d430ceb7880973164905a34e5cfdf9b97cbc9e8800ee905319d4e6aa9be3bf95e99711a917874eaaf5b8141a54ddb5f2d54f1422303b29590b20b8f2bc679c1fcc13cfd71d447356dc21956ffa555d5b20bf2d66fa3285c48c521193d3d3e342c06569c2e30c2abd080291d603a4919b58512122144230a32d059750893464d46d5db913be9a39789184a3857d7b3577ba60bce2d396eb599ec6c6188ad1e230b733e6b364ccb874249c7ff28e38b5f2b9bf78d17c41f389395068b1970a4faa0e457e18bf204639455ef5b723c29584f3ce1404d0ae79cbac6294005a15e7799a337f56ec91ced62c5a7ca8233675691b24f2d25bbebbb5a09f3d4a7f3ad0084c7e7a063db46c378a08615ca5a6bcb752bf801f177f51dbac2a9a8bf92c79228933dfe600a04747cc7790ddeb76191f4a74494fa9f599d97d47f2c78d96bab8f8d91d4176cee70bb63c3733ee01be93d9b0ffb07e65c604b8c1ae06a659a83957b46c8324b640750ac07b2287ff476adb0407bec6fec116b341164d2c6b5dc3a2a4c3d68e2ed98bab648d407e7a57550b7a8c6f7ded1f91a47e239d2a0ed0609816272e9a7708599918828b001fb06ad873135c5de9b1dd749046323b8ac3cbb5c03968445a07972fdcacc603dd43a4da3608e211374b10615b30f0bf8b8df63118dc69318ef005a34573c18f0841dc26b7d6b3e916f6ead42c6ab2bbf472a652f9c553d6cf9f72ead892340d43a8fd162f01627ebe9947613a9836a9ee7e71b232916240ff0ea3ef049000d2581af708a0fe64cd783ab7a8279e76273c0819608102c2ba8f99e1a677aacc8a29cd01f6e0e7ec11c61a2a63f9de6f80549f8b31171e6d44958777579f6b47cce09344cd0d05926ff1fde4eae6f7c86e9d9562c59177e056c7641404c473feec2e73f6770b8a483e51deb703f06bb267825c0799e71c0cf464a0648f12db8810350ce27ff2b07ae829f9c227dab0d2a72592966a9274a37ec5f74cbdb88fb448bee7cf8ad2a2b83b46bcd96f54131e8fd626da3177b5a12d8f714e65cae5340cd66f9151c7b657c75d98267554111746009b5c6853c050003f69a6f83bba63f9a399eede38499348631c92a5482525c331cda39471f55f593d310e07876b0bd369d39c19481284d0c86f6776a5be5e4123a9c1da709f73070a0365f2bde2db4b63c2420eb565d903f7640a8923abd9107c520e82d2997ef4b20157fadfc9e80003add0913ad738c5d36a4dae1d3de822cc46af8da451f8e9277440dd116d2b695b0ab20f2811f17a2e5d971790836beb8795e24bdb484e4dbfb408c1b1e19b0c4c744e5b64e6acf531466f6a25659c5b19c753b197ba69eeea6392038e052a2aad2a69a44715b5732b43364e192779d172b5d2040184288dd1d0afd254f638a484be3ff022496f6bd6d5eecb1331c8c17d43cbce265956f8776da21726a42d1f210d5f077f5562d5be969783272d5323506f48172cfd4d2390f551c5b9cafb7d50a49aa6a1707f5433adbb8cce5a4be66a1724e8312038dc8c3d01119197581b3fb768814028e895d102ddb382fcef18a12fbcab34689a88bdffab67da449eb6839757906867d7b881fff1fb59f262d18f2db9993b2dac916984513450a5dff02e712f05a810521445ce7abd242c46f58f3c6b60d6aa40cb467fe4a0f72c43523f853c5e90ed6b80833d735a163697d5aa57b7b8e9086c69a1fb9e356d56aeaec9f5acd98fe9406a94a704509b7fbe92ccda2f1457cf5abe120204f74904446b5edc52d86e43d34bc48a00ef340ee9d6042e27be0e9fb5bea00ce180af7888c7477e01c281bb9a2df2f3f5141d740d754f191a351a5a714aec2dc8015a2b841181535ba69c681549a96517778a51085900785348231c655a86eac2f26445b12ac7e584c63345aaa445785c7c9dfc2c1582a109965abd38a8a7a76dad2015c5c1d6a7708f1df96af59dc0034a4a5801613b9b117946b15d87da38c75973e0f5995fc90c88983223f857d7e95554b66495d13ca66beb3a9a120cb5f729207384abda08c059fcf62b9e110b3f3067a23ac720ec1e25041d9362060c6f85bba2c2dba7ddc3ced398a9cea48ae46e9441b76c7cbd3f50da0b8f5e8ad47295de128c370530e9fa4716bdf02a6fba741f0465615ca3f612c81657b30f56ddcb9d232887b6552d63406ab8a24f830314188b2e1182802e34cf10302b56167252822327243573b36c1ff714c254476ae51709bd2124dde64a6a2dfde9836e89e89eca2e365f94c671afb783f888e27ca0370a403f0ee33a6a713909d72047a39134eb381059f0f522d55e07aaa77f40f95ee598981c63da9d1679f2ab717442e3318554f2ae463244ec98dbfd7639bb04f9d9ad9ff8d85e7ffa20b1739b3b1ee5b3d1babe67ec616eac20edba1721058cd7f7c6b5f818e105bc3ae8f67397a3765095850722fa5f299fe324041a4ae842a4c9c0cd9e36e72bd69894e4ebb3e9f0e97c1f3116e93e36d6412cc7fe98c3750a19ed1e8f68a921df628792be91eb866ea1744990f6c90a22987e3e7d25611916638875f06d6f8bf29e43b799c298a2bae19d79975c8440cae8d56ddd52ab9a882043eb18de30017d9902e30faabfb93cd7b3392f3952ae32cc713a00f6ae0e214151c15003f5ceb7e41c7216f9bf77d3f66f18cdb69603061c8aa707dd8018ae438d7589c0819c958ae29f0e159490ba77315a3dc8f7c23e5833a7dcf24a9d27a9f5db8dfadbca814a527fc3a706c97ce745a3f052550b57e29ab57e2cbc6e5b0d81cc7af2dc47492605c7abdd4093ca44f6e0c80d1f6a18312893c41f318626356856690fb4bea2409ea811f3f1d77af16211847219461334155442d55d2fe0ab55d0514803af265728f18e1a1a22e9a790116d4f65b0290a77da953f058beaacccabd232cab919383e3ad4d31392fa0048b96d7575a9adb9b597759fb2148483c2efcca137ac6e19c0a6d4621316c82db7417b9d194118e00b856a88d5685628baac24eeedbecb6cbcc7be33dc8296c34f7d1d52cdef645b8cb54b949c04adf130d34416c02a0171a07065eeeb100f8bb697f6d735b0db5646e738c927b9e531a36fea6366d00043489b64c1f766b69ff1106e21f6b4266aed356670052bb379552ac9df692675012ec8caa94eaa2351b7b787ea4b9ab0954ea38696f2c2c3d94881e13764522f54422dc69e07a50b5a50ba8ba215dfd3c86ba1328eb3066519f2b8e822b3b5e083efd1888ab1c7f81f6ad2bcb0478857aa1fac5717b27887cc4c60ea525e0561dbab2885b36f7e78fd5e41511c69be2984bf3e4eb9222660d61bbee913297a7f4161f5949b144045482d18dbcb29d042e347e5b148c7a2ef8501bffb3fd31f83a4aa70a44c5640c31a3e6e7098ceb1aa06c453252ef9e6b6f7ace636503c4707eef13d200c2f24faf6735d1cc4f9090acfe46770e64af5fc7a3c3b628a2afb7f58de178f766e73046347aa765537ad5d23328ce2ec69651a8a7688cf85c80f51f2f623677a760a69e7f51b3d22f1def11eb20e157a8e165844576db6386001c5e568049f3d8aff8895c872344b043d2f6bd4093913ca5839b96350eb4c759250e2d002a20aa5b69db0227c8080611ff936bd05335ee80a2397c6c580b6f4f7e8c3c1cb744c2e8e13ce9a767f28c88bd3d24c502268243b17c750d99b9e8b5b8c12265ed8446460bca794cb94243db9d9b071e8a40ca481426b2d73b2c2380ce1e38202eed1cfc94e1000bcbcf5b12629438cad40bd647988fb29c5188ec5a052683064a9f0c8baf0db93278b9622778a57b9095a96b8aaa5480a3fda01ab28997fa4bb96b1a839f70ddbc91ee8a5ee7fb927318339e9265703beb05a30c8d161806f6f1d7ae854fa3fea92bd508e784ac378742503668a8ba348ae8e4864784eba21872abd3479329962ac928451b37c876170bd1ba73104ab4799e0a0ae692bbd4f5cb793ee522c0b23b4f1c27bfa7ab5c04f2402ca53a3226d38e4e9139f2067b0b96576d443a6c5ab3ed6721893f53ca40b09a6f5313c7b86c3ad494994289d800836e4e4684d85189271a63395a7154a16ce3266983c29a7a6310e4a669de184939ace1e68544499d384c206634f3ae0418b26307c4380e30cb907c536862c4eb911c1d7560890f7216c7af62825aa41928af1dda9248eec93f147f71f5970a92e44a56d6610ad02407ee09d52f7c46b8680b8abcd31b7b14f30eb89940ff5df211ac8aca75319ff286366cdeab4707c43b3edab2df8d0015930b54739d43f762678f96f450a344e05765acba2d2f8fcfc7ebdc548e3d9cd234dccc3be3b2ec6eb8f9281d4886b21161a67afee9826144b2204914b67b99d66a24927a86815fac22c42ba966904718867730cdab0a8467d2eb773a073b1ea14f24e0e502ccfb91922cdd2d246a8224739d015552e0b674de8bc5925116723150a2c79904e5ccc242b4ccdea5a5f707f93b0cca59d650ec6ea847c872e6b86319281b1ff6790b15140d87825cfd5f05e7bece02c90a895130e9acd6a42f141d35173a8c1d083fd04cf4098a4dd5275a9b8965939ce201341ce40b4c92576bace0a794e9ba1a2f2ac727cb12c6139f53ab722fa54f8a978c655eaf05d2ba65ac9a3a07928311811d7e043a293252b75ca6ecfa7c3b40fb9158ebbe85d5d42213a90ac9a108d786e3e6ca4f1353744835c582317a692d4d488351a7dfeaf784459d6f1f1d8eadb7235db1ce0e26c31ab6c753f0ac1959de8b773e6ed5e92c8fe56fdbb974f9cb293d6b8f538314e11a22cb73f4e05637f1ef6bfb870fb1e718721cdaded75c0f60e3e879bce79ac02081299315c51563f3688813cff3fadaed753af7f5623f3c28691aa73035abed7ae5b65bd78dd91eb799495167e73b986e0e308d01d5a101ebb26f354f594e6ad5be5c5935a8697c82a10d9ec397610932df99f1c36707c2f0e720d07a1b0986c50e3f2eac5307da0b25e41301f57b77d87d38f9096a3f11a5e565ca5416cc8352d1665c1dbd60f602d8e7cdff2211c0867271433fd2d81385d4bd26a7c36770f7f21dd8d7740bdf0b1d8a66fe5ab462776a38aee1bce8143f1fd1b833599b68041421868ddee8a7eafa9dc9873466ebff2ff4ff86a695668e85d38813a1526c022e0e30558ee37d2782490677e1f809013a9f08270ee7a967cef0f40fc6df73116daa4cfd5d0f98e883ccce202dc030a22fa8b6ffe03708bf9c5d4f93221a21c58e5946000abd3fe19be044024037002187d03403a57a845df7b11f5a7c631eb2345d00035b10ab8ec5dc7a25e761da7c206cdad4eb0751a264efc595418a2f231cd05f66c28c1ff8eb13de2355ee73cf84a2c245589b67de53417bd97d02ec23efdd3f3d9dfbff79def4d59ba0c1be89eaa52b8573a5d2248b2ee48f96d941fcf1b69ba2c7c410f5879ad92f53ae8a4b4ac0e840c9d3d7b7fc2647350873c929bfde7d3e0d416652d0cd290ec051537a487e71ec5381b8cb0e71d9ebee5f24c91942603311f3b083e3f6ac9e599b08e7235b17f9b202ceae8fd1991981920aeb60170230d0c82542c7aa851bd6d5f6e4de0f0c00f8ecbfc9fc033fd016cbf873bc713dcd41e726be6d988732a520f6c7e87fb2620e8c1b979a4f6a0ff908e5ac3d7ac2467aeac5d291cba0080e20336b8b3d6040f350c8dc7a0c2ed975cd828eb5f8d70266bf55b0ba68cfd361a11548f40bcc23a076e45d55a4d8257c582c9d9e2e68d953d1209c3efd34a13c792d29b076b9e1bbc8c382658831c7106476fea6e4b47f5cfb8086475c000c99b0a24dd118632742da840c6f09a90281d095bbd4c11ad17d0fba02dd9a6063c9264d8104ab3415ce164f3d129b56d8e9151c4a16877f97a80c0e12c474451d49c94e2c0d25cf2a1427229409b62955d3c6c2cfc6161bccab71c4cb3b004eadfb270e232a89fc1bd50509f80cad6a864dd461cde7d87375c57f9020efdfbca65d597fe3010db5eded724d223d5ccdb09d5f319d7407c2f1ad601aa847fff5656cb651b9450c0990fa7520ac24f6b9d6ff3c70e49bf8ddf43043d1c4d0f4836ef7a457d5359d71c1b29f6e73ad1094c6e156a2bb2329ffa7fc621033fefe857ff5f3a6d07c5ed60ec9825a2a3bcb0f97fb0242a97b357394374685e848286d98983c51ab4e2387c06f101745d06edec828b93b293f91deccd76770a95bd6f796ac81473d4d201d90e2ef1805e3dec993fa3c8b5efabf3e583b26a16f4ad3d0e0599b052fe561fe44ac65d76315db9555581ede8d85d4e3625056da1a726e6d170d727800dd8741cb3c7e846a1285724d6106c27e5567e16ca50afb09024fcc60a06e1f032b2ff830926cc36a02e16bef1bab3c80e21fff01d62c7d44961073a1d9c5b3e7ba0bf2b8f87ec2385578662441177e26b23237b209330a91ee09d3e36f4fa3cd370e4d006235c67ee7a5a5847949d720b33057e6bfcaea86687702dfb837992d6decbfbcb85a18ff4a6d5eaa9000d497ec89a2901e1973761cedd1ed731a503132fc4df696b6cc8d967227cdbc957cc2a8ca6698473d6eb036ca7c1c44458590eafe3e6d8a9e1bb417a0422079d43185c7eeff34a4575ea8800aaed5ac341eda7360fabec8eea63ba02a17128f057ae638e2a232fd08bf0687ab3fc7c18f5ede8d353334dcff48e54b2847fa94e2e4fb0ea72c03b62da4ad2c36fadc38c9ee422c7a1ef2c3d1f8f7a410fa5973b4f53098416f7c827342a469c61a232900315632695c6236ab25690f7895fb010644d1de9853328bab20133aa7e3656b745951b0f27e8bbf0aceb2609fd259eae66a137f39e4ee13c200a03a18d8f309fab0c96a530b2640659c87b7c62eb7ed6544c8c8971b128609713cfbecf37439971b0f51529335791b4a74a6d8ba706550a6d1b83ed9d20c0456f3befc31041c0ac8bedcf043f639f20f1a2af9ed6ba79c5afcf2454e09d41aaf102225e62265be3335ce5e122521033d97caee8d9c9be02fb1ebac1e27490d1868914acbef607fb318e5dd61ab18e4d9588772dd2c875ffa5542a3b1655bf891e674382a53c5fa1b912974e2481f51609914046b518c847a4fbf3e07df4e9d7af09908ea0edd29486fa910c160e2dee194f4afecd5822cccb8ac33879876ca20bf6972d19d691191577efcc4e83e2230257eb890b2d88a378a05386342aa192210517f81aa6141b2516a2d9b2722277244b95c6a5fef0a5365a4c5e71a1165a29a676fc9ed6e9f590d48ca9e622772be0117bb87bc3a7c9b46d60edbcbdde242abd321caa78d622172be4612d90f90690c30e29513c9f5cd3b8b1662a1a62fb2b721868887ad1ad0b7672143bb97890ef6052a0283f1939ee56680c919505d54d64794ed7b6acdd239df17b1dbbf075e53656bdf4e71a8ed04cead879adb1b110388b149013becab5ac919e0cbf84809e327dcb46e5142fbad4181732939232c4fe2d0920ab23204e3450b34d4febe5739940f069446349fcf6605d1016d006e89d1eb63c4bc060b26a0dee18f6b0c8dc2017731fb5766bbf6a5525def300412d182a965f3f136112389781eef335cbbe6536bd0a3f8017a82d7b352f668e9e15fa9d08ad44854e4d5c658e3bffa56ed922fcce83512206846ffe2e81aba0f0dad5ea7302666b69c622d4c0f2298ac03cc171726b2129d4da8b08c9a00d9149e4c398386043301c4d9a1327d8f066dd059ab21cc6885de68ba7661474473051b70002c83cc820420662eaa667a422e08f070afae8eee8ef244eff26a9b582f8d60b952b5ab50e3ebff6988c17a2ded6a10492f6dc0c381061b139ab09884f338878a1007ed01a19925502a259270bc33ee389e568507dd29f06348d471002443c25ecbc38481a3f13b8fc87db468c3209fb4166e753e9259c62c86fd8f4821e0c3ef8c9fbda9590757a01a1208e736a6715789a96c77a4b8caaa3cb6c0274a756e6c9da47154dea06a4171df4effa9f7d7108427658e3f47e310a6051dc1301e2a3ddd99f209310e954185dafed7a86474cb86b42d95cb16123dbc4cc81d151c1cb576962d6b0ed5c0f51c84d256dc22dd4950dec3b4057312a4c12cba40893419e20642163fbe4fce7e81ccf2410185eb8645bbf60204e199e4db7e3d023514056362ed7a155007e9c6d36dd678d16d7b3f063a403538ac1e8e51377d45e2acb4280c6f60b957f234e03c9c76d9b77442fb05dd56ce785a6082c4a061823ccfd75cc4cb433fc8928b6f4bd125ae3673958eb24f72950227080669d4d9f7d9886e1a61360e9344e438f60c9a879977d000c59b625341b817335fbabaf5f086b173f53f7195fe8b00fc4d929ec6da16d5d36db3a05ff7061e38396d32147a7a30c729511780e6d969d1fcd100f7b76c25a82c14a8d0cbf2829c80142ca585d121aee8117c8570970a515dfe368d62630fcb1ba816050ba06e3c00a2adef949865da7d77239bd193f3f548609d6d6aaa31402a1a437a2cdf4cbefc79dec828c9110d17791130454f5108d6e24abae5360285066f3261cedb3eb42a3a82e10541e80950ab4143936a311519008ace6f998ed38a409b18643c8c26591a7068f4499d450653055084dcdaaa6fe7fa696ed76229f699eafcd679f313b44b925d2183d337554e847960e702d3b2c805f581851e4beddf805d911fbd7d000e9673e9f4d1b8f3205e5aefd965dd03185d9ed41dfd6f0589036cf86ea29fd74e81c1f93b82add3a382eb00e4c42c40861546ef42d1a2444d2d39e0dbab93775362d3d264834be72f8590597cc8f1e9d099edbe78c7ec7beac0be2f136ea56773a17668169f42304469a9142494f54d48f9757c532e156a0946063beef78c6a8bc63d748620b6571729729fbb7e977887bf699931b0bb969f8b8a68867d3113c76fddd399203f9282380bb8bbbc56b16e3744e06449aa8d85a936dbbdad1d5bc052bd7e26f99604937e8e14667c3054b96407373c34dd72f88e7a657356ed8960d1a9a2d99083883fe9828a5409ff31734f8967f87b44b43d09aadf09252718d254baba039010894d5b132005e75e71015e911fe9327d47bfabfe437fb456182d6c4738e03125b71352a4b4dec662e16d73e31fba812bb32874d3de46a4978d796534379c427842da77162c00d4144952c56a5bb055405896352d1b2adf58c03c90e933696253efeef0017eeda9a1ce8b0ff90c4b7d3fa0650ebbbe6adc2d2f5397ab0307409f5e4b362268d05d8ce064e2a992e65dab88fa2f6af3ac155ca767f540e5e1c8bc09cd4c2ba0ca0fef1c5fc850c5b7c433571417cd23442fefce8189eb2b6edd922fde5987ec8b2ab2ab353a05d7560d1eb70d5254279f20b01d35fe24eac42d7b3d0cd6564a049dcb5f41b6edfe176b0373919a839369dd784c0cb39c4330071a437edf84ad1ccb28e54a8aa1ea2e5067cefc8368ba475178e21d0799bc5da1634652013aeb597d0ec91bb5c11e2585dc8ec4bdd158a12b80b831c745e7c203b7ee6df24d438ea9472f53e90a6aa6e652439f163116f60515c7cb3df698d4f55d8da9a3b9b4965dd4d611f2d03ced09046f5090c09b5e6d91840722ca85e81c43a73f00aa69d2ced5e077d306255013564cbea0151fc2591546db68e43c62e83206b249a4fdf0e1c9165c62d5c0f8ddd0264208e0fed6f874ffe6af83c4a121ae5f8a61eff0f761101805b6ee27c4efa8b062635d5a654ca73b51bf7da782c2fd918f3a70ddc52002155928ddb525ff152aa61263422e9c8018d9c0673922edf037aed683d2f345f8810ba07254235e713dcf946806e7cecd4e9e905e9f0235aafcb829b849870b2d22a11b336322296af43d431c707bc199bb256961864dc71f2dd84e42684f114e7edfba5d949cd44d44b5a85a1434d69343bb78078e138f2fc7bf545568ab03224671365c7e2c912f062190c7d5fcd0d678e7354eadda1a8072544b114d0ec1f0d866fa0b77cad2e7d700d4dded135d82358933b78a30d6d26c93790fcd43220c13e24a2162210071975b1c6ff7b08e1e3657b2f9f3de4e98a0cea398bfcd5c95d3edf63e9227e55036335fc94f80c6427025b4817486ba98ec4e7ae223446442db2aa2d009a56af5082ee63e223bc2f80b8489c9e8231e113118a6ed51e83b8d8bd8dadddb0fd48bfa516985120fa82603402644aab0c861c317d7d66ae926d394126c2cb0623a2d78f5eac70d25eae9608625567999949533b91ceec59ec6de03531a0a039244b4b521d642792160dad23c8ab4b0c26a806b8b5d3e63d4bf84ea8c06db0033819aecad90088f408a44e10f107821de8ebc3a5591d8b8759792baeced1f2da4a4be3a76a839530533001e657dc0202c40815308f8959b734d15ef5bcfffb3b31277f43fda6304b8257f6ae05e56b0901114397e2c70e5164441475288529865e74cb622b117608f262ef40e89c88e7060a13c35fd0c4806a8b0e217bf6bd7c73925ba697787e2a258c16c9ed5c4d1c98ef3fc8bcb2eb1f908e57b223bc0d0b893a4997de3ea65fc5ddbfbeeea29a3a05ca6f9797ca45118e9b196f080a5cf2f4d6e34a70e53b5c5150f9e0a6d3588c3a8d20d4000adf65b6214e7fd7b8c45aaad26d4462390dbe57ff584516568129758003c7893074f02d3e860314a3ebef3fd48607f5442d42534cdd0d2976699463985349d15eee99a30cbaefa80a7b33bcc241f9d0afb717ce895c0c3d85a66518214c97bb60c8618f366dbdd1e87f91314390d96c3ed9f192e27e59cd5511c1712fc5011b170c1a7cbca4cf3c73de0f1048d535ecd0900d8da2b1b3162d28a8950a5d60144ccc41f9784a89f17615edeb15ee3e86b8bca3a34186d982fa93e6a1351e61668f64ebb4dd3fa03ef89bc5888272782a4a6eccd55c1f55a014664cd4dd6080b3ccbf8f408efc0d38d7e5a9bbb9ca80c91ffb4adde1990e46504237e5e2855f46ecca656b75b369f5331e4f696b5fc3c307040151ba1956068ecea8b48c1b1fcc310aa77f63176b894446a67a3024ac98f2ac136939196d465b064b854bd417cd62e6b64c870cbc72ace961deff82ae2a5f4a9c87de526c1be1b8540df3215d596d4c4a699019fa9e4e08115168cbcf60a78bc6b6d9535458cc6ce83a52e0c44d7e4bdb1c18654bf3977734d8f10a998122a748705029c3b1c04e51b162085b74ca99ed34c70a8ca09c8dbb38cb57e53b830d916c03c81a7100fcd72f1476e912ff9a297b8f1eb90aeff4956bc20e6cd69a49d084c126c10b53bc2bbd1d007caa94e54fae13c0bca1f539268a7101b0a62ea4aec3369dc0f5d2d884390daace39c6eb902dd63cf9d4af0453396d07c9745a2b56825e815543e0bdc16bd6ccb15e262c75bfd28132fc55db18aca7a213456037234a6c2fe0bab181f79f7dcc59edbbf9a046a0836f046174e81ebe370d43419c5f4e5b5a75dca10a313628d0c4cf1b652433151960ad261bdbaf6123af55994001047a6ad2c57ea692e3121a8f2fb4dc5a3800224be6911c3fa47515bdab7ac56d52624147daf230b5aae07b1ce36dab8c42b279f5ce83cebb45ad02b7e549324efe0a3856e31a3c50df6e52f1229f70fb8e76f72379d752228c04d6f2b4ea56f3e6a250acb829029b7055adaf8a321f61c99767771e4bd3e28249665d975d323e5171d7f1f0fe0e11874c4d6484112c21a5403299e61cd50f2524834af9cf1d97eb349d3865b648bb6d0b00bb370dd1e3d7993afe4dfdac6cb87af9bf484db333bf38f21a2b89addb251d21fa5108bde52eb2dd55e9c0878e088cbb07cb41840a0ec46447bb2c439ada44b923cc5390f240d41a9cc087c5cc2654e2280a58eec074c725fc78615dbac3b0cab585d6126132ac71d06ab48a15f88fcd3471c8a23b73ef807f588303011c35a5e3572bcee60a0f2b6d28cd6f99a2164fc57e4c6e488936593718ecfaae7d1ca323aa2aed62762026ef4e2345faab9dbb0cc21018ccfaa776dbfab8e2024b07da9363d4b4a6ae76f05a1ffa1eee839126054579e335c7938ad1a32459ac24c9c269980bace727c3480d583ef25b49b5796a74230ef98744297c6ca23c9a7b77956405b9ab10e77caf4e40ba634ddfca6375584b47b5a6f23be5be7a52234a0cca5b55c243936c4615b9b12db1447d5c93730d497fbc0b73005e9f439073932a47b9a2037a2de8ef0c5a58953274e9c4701a6cb6394d758b41713c2cfbf249dba39d94ed39787934b4442d70a0585f646c6fc294a10d16f31309cfcd9bf9a5e0d5664fb7f36ed61f50538700063fb1f129141cdbf1d77d250b99945935bfff34c41a8c7a6d3e2b3e699c635f0521873ea65a90e4b4fd932f4f37f6d7c60d131f9bafde8ae2dbdc1bb82457fb685fd1a1932328e7be02de5460e72bc6f51f8c2c0b440cafd76211329b8ff637f0e9791f680bc5996544e127b94f2be100143b2997bd1a54665c0916959b15269c6b199a2d70356bf338e50489a6d6a29f3093e69273febb56c1b475e853c906246718348ddd9bd7c200a1faeb546277ab6094e6da350b446581ebb840fbde4b06439f9110c4facf3cac35cf0915fa838f3f6744baaee1198767b2b791b1440d55b50ee21446541dc8d8dc7a979f5950949e65ed3553abad3c4227fcd54100d5d55e19acfbad05e373db54ccccd08ac34c7e50245613789d21a5b7ef0d61740016c701bd361f04769e444b4e76347201f0aa15d3580f4d3fbaa632c81e23b84049276b2e2b7e9d9640f599cfd2a508615349f2f9b3afde360b44094136eddc3b6b853604251de5b79bb4ca4862c21ec9e7ae701ca93208b091344a2946157ffd5bf279ea289c017d8ed7797e12871d793ecf11506346266e082817e52244734f12be0e10ad887efc68038598c6c3c8e72e9ccc70118460f5109857cfc354e7de7b4c06a1d8bfaf229a026cc035725d6345f20a0994f15040b0b9eee6295f247cf63cb4bd723349f01badd063870eec38da176be8bc5d634b5426550ecbd24802f640a22990c622b153fa91339b32d53323b41d83c4a138cb2015d1b2b89690051ee1b75d18794d5642c6e19db73d7cd9005b909af5851c1d3d386bd62da5664067f4bd3cdeea1d5a7d74bcdb7a7829647935066ea950d9d61f54baec474725a35863e62cf5fd28ded7284e2d2f13cf20e64024920837817fbf6f4c6c42d9b8ff6a38eed8ef8c6f0cbdfe0cb725cf65610985008756b51c4be24931033b3c72399f36880d7a180e71f863f5cb0b1f79a4ca1a1afb64bd82a06fab42e74279959c556615a397214ec9d8eac66640cc83ebc977d5bd4d5eec903cd832ec4e41159c313eaed9924f3194ab6be50bca36150cc6ace527f3fa1bfe4a71c1c15bd6f672adc1500885422678b6c0ad2ed3131c54c1a750fbf2a98315529d6e419c43e3f726ef25a0b1f7294f4ac68692240a194160ebfc4e30ebd8bd8475226f5312d36b6745076403718efb0e5acdac21ea5c56fb00d66e2db36ecb6a51d52ac1dd9ae0f8b9899211c30201c6e39ffcedce860699efac4b847603959d03b0cf00929d8038aeae90b60c0ddd096417edf4452da88734be0dc63207f88a6d3eaabfb17d6c074baa55bc601bf344c6399c35f8c3227eb11dbc1211f88e724caed10282d0593138d344c8be9dc34254175c162f4efd57a02c17d2029d1663d0d595e70071f1fd3f64cffac46477e085b7875ae3eecc11092df572735b41c1d58d00abd93222f46c906cae4690e095bd07590b39e9ef38facbc30ba698ebcb6c21718c5f4415dbf951ec04876dfee80624906976f580b1ff8b55b924ca9807e0126a7b3a0692cfa3c9f38dabb847028e1a1b00b9232090ace239f336f76ae06885102965afb3e05e12c3c73ecc47dbdf07cadc782a263c7d00daf4dfa1b8dc07aad9d7972143257354c0575e8394fa12f59d0161e7b5b616cd4e58a800561c040f77ef55824104cb66455727850e989e7209c796aa9b428425d1b8881c49edfc2a454e592e7166d391e618c9b034f0d1ba689b5128fe97ca064336d3fed300fa8085a38cb651d79031565e361c1bcd2c4db56c50eb7768e070978ea06db971888c3d9e2d379bc0ae7d212161d490d66bb6a5f813494bfcd8c3330ef187721a70651e4fba80e965310ffd16c30e7ea637f1e0a279fc64499ef324bcfb793ab02091091662844e3b347c87893d0d51ed1cb7256d0c2761f8ea8cd4dc04472f72d6633f5f466e84b473bcdd1c549b39825c65745a0027ba189746adb02b9eaae1a295963b2133ce02cfd6275d128d5f6d44179bc14d793c5ee13592cfd474f4b023db431189e9e1e104b5f2dd458a5668932f9641edb03967f5e5812d9fe38db315e10a463426a0f7af12432dc9151d3bfd0e8cd2916a3aa0587cb8b08c45ae3ea89f844372b9b2b83821ef59d4323a6004264549ae507271a975ff4de5a5fd38e09d7186e772ff02a77eefb78e5782f386467d726b4a79ca811636c1bf9b428827f3468a42fdd2e1be18e7054e913283937e5ee6969e962fb8eaf16ce6461acc0c2ba168ea03fabc523c7c74cd5be2dadb73833efe454f1da2788c7565f3d144b7fcdf2992f05660daf65a83c630235af927c694872d2af699dcd0a12eddadadbe56607d9c5f0d5a04e44a46fc62f16772ec63d6b042c3a29223ccfe6a6591271744f9ba66e6f576fa858d1d54168b068469bcbe0dc95d64a866c633ea6ee326dac00eefc13a21050575835e1c5d9a2964c96f700048c49e5766370f8b2e278d47045822689e9c28615d5194e45f51162e4ea9c00d278eac5ff0c152e121459e13e7983e257af138230058c846bb25bef4efb02924e923bb2a63d1e2545dc663c30f840450bf564887530c7fed372d63bd3d8be9c50cf23a3bcd28b6b53491573f65562d91007006a608644794f106fe2a2d54eb3ec1eba7ad5c7e9cbe486a3e03c529093bbe075121544424ae9e49268bd98fd0db63cc2126070e7465d7104da4c3320587b66d0d85fdcde8695443ac4edae06069e3b84f3d50d9dcdb7305e19cf6eb66efbeb53b34db7aae7fc913bafc702b86be443286a86251754cadffe666d63e60e44cd06a24a2e43ecb214e4f64aca87ef9a547c7ab2533a9db8261b44520e5d7ca50f3c780e60918ef16d34fd255acb90ffb0c4df3e9bc4613857ff99f80e3d4df534ace8ba985350e6790c8b910deb6865aea1fee37c2fad45836223e204abaafc49c1537ab184ad7966f356ec603f3a1c56e23acaf34361bbde8da688ade465ef436a2a263a3accf46b9f585f48a07761a9b34361b5dd193c6a61b0fe9905b9f89ca9f7d246736d777c54462f0607dbe1e65d00162c2fb01010e81661c5c9766ca0025e9a5601007e44a78e99924f0c4cd2cf6b1d8c162870d84c033cfc287adfdf422dc12c59aa702c1fc8c7229a8fd7040b143a19fd3f3489b0dd5ae37c150e1327dc69c71e15b090c6be5870fb3efdeb2e366aa8ed487aee386e22c22568f928617809ef6962e33178331d362c84d70127fa1a67dbc706af2e86a325c9c7993bb1bd4c8bb724e7b1812a4347ef03ca9fda55a1af37b25052a55ea909a06e65c793404ba7461e0694d70532ad6c0b34bd12e2b37dcfbeebb1808643437bf1f5cc5de779edc6f90c03a60a0abc449fa0ed57b01debaaec35f3d1fd9c5547a52c9a93756383db200b6720b6b584a7d9bc98572d07cc28ef0f134b247429dc37a08928c7a0cb7440c56bf7fc18e6955791bd06d63d10e32e4d3a927164f80d42e835bc025a69db13fd639a58893bf31f10ffa50de49539ce71279950e40d9f0240c65e70bf9e218bce3f928ab839a995b633174930bb2bfb2448692d2d154b43ad628681e9164c49d3363b7bdecd6cf2c40f288c443a9073b957de9323bc81a0ad74d8c6f91d341b3d1326a92b3f80c17de671426a323f36516f96b977e4ceb24fb959a0669309c3e48ce1c15f9c14be1b2641f38e01268a34bb3d02e3c9efb1af10afd5a040596c9901e78cf71b3df29a318cf79bf17a8ee5d6b20898bdfdedf04b6e46a0c321816e56c409ba6e95e1e1e98973558fd8dd0fda9a826181662903c8f62895c72de69545389a83c22f4af29a13d5ee5263c9e78ded08897f8c6667fbba87810c726b165f3015ea696979f915d2af3fc7316de3d063a547ac6de935a40245de1c74793ba55efd508c589282aa241f5285b0477ca420f00d13b4a23e2371c4c56bbfd9a86249cb041607551224d6a5cfd6002829c649ba431c063630ec76ecf3b754022bc4a6793f3b34b50aec39310b9cff2a73c92e3a6899dd07af72cbf8e5fd4c62a8334e9a0ceaca8e20c8cda0b0379b90b34735a71bd1a85cc6c177cbdb8a9dde59209d2753f34998672b7ad0a7d03e5cbaf6e9002ab81211bc0d1555d187c5dfa5ba532bbf44e7301d5219473fa698aaeaf4e62f8611e51d4574b30fa3cbc7e9babde67ffa7c9c5e3a3b2d1da3f6e513ecba795e3e845c5bed4f6928b7000ad82879e89e9386bb182d84475fff1ed65140a5bf6798bb19684167cd1d431a7233cff02092429e964f28b9cd3a552c88d822595208e066e4b19e28d31ec173976806e9ee00888626840383ba224b459386842a498c52768516da67f351584df0974804daa3dbf53493f6cb94abe05ba3fa8462c21ee74c73feec4fcc4e8848363b149485a52df8434829082efa1c2600bd5eaea58db02d5329931555a7d61cd3cbfd9176f523f6a4caa748e20813409f749a679f12bc4e8262f9cf25a0b697e16d5a652e39c44b66bc99905e12f2f5dfe2a1223db2bdb92929a28bca8f4ddfa8d6e0af6f7591f0f4417e95c6dbbad13305a9f3ac76648552db3ec22c65b8950e6ad9add4b152523f347b910fb06079c98eff457823b0273a9c7eb41dd42a446e138ceafefa49c6993a011afd14dc4d838de178d360db38775b995cbf6e0985d84801a61d4368b3f7ce54d938bf8f4a03d056f5fc159fec0be370ca3f91b58a08862f1b43e4756977629ec299bba6a6c424a315204751878200d40d59aaedd3675c2a5d563971112a10507d5055808f8217a519fa985b8a389e3a6eb504495649d47442203b4042dcc8b597a3cadcc5c38b633f811614cfaf36c00a5e3b50e716375d076d0a226016d9c7f4bf4012a878b51aa63fda7ca6eef3fa65de9d11b24a090709876893a11edca16e369630c5d31669aaac6a75e3b07a9aae7d1a4ebc6817cdddcbdd07232297ec412017d69772718ee3b5d48dc984c27b59c0b45aeb6853257a6701266ea7d1e0f36d1d071383250eac584b1b8900ce50ab547350153d46e46e16e6fe4bb8dbd9e28a50e816513d097ef926402e5f4ee5ec25b474ba3c3710cc3a2a0cb8aa14bdf3ab4b8e0f7542ebe96f02cb83acd1416de14563ce51e0c6ed28aa7d010d89aae2f38fbec26ec1911df0bcb831b3b348bcdb22799c0e433c10721455ce9adf971086418e7b8cf545da25bb42bd029068c8e18382f37f4e02c77d6911f3106c1d2f4d4e7c97869a73989da34c1a65aed18e3b2dd9a302073971bf1f4fb5c4b91f5d84bfdc0b3ca6971319f482a7c7c7814473a0097ee27325bbfc8e4faac60b6a69d603e5f91b7683b107e1be1e7c7196f3fac07236527415e3bfb680fdb54f8a5be7e881f52548f0add84a9069e75c2b6d1e42b8897d3ce162188ada17fa884bb849504e76904101fb434254c110293f29502798f19b45f5a4591ff3fdf66bf29817bf22691dc9c8c73cc697d007a143935d096a110170b3e1916b11fe31ab99021cd4df5cd88cafcb127621bb8cfc08127d37c2b2668e31e53637a6ec517068f58016ecdcaa4c909838f0e86362c97ddcc01553c4fa8bfa9a4a1239ded5e4d483eb7f8107570be9f74702543cd2b79ac888e991555688b0dd93f07af3e2559bc59c3913955cb4ff5172cbf93cfa7c442410aa3818f8ea6fc4d7a7978466c310155995a58290735e572db6475eed3c24ccd2e9ad1f432020ec90f36cc5c3a729fd8844b492a40a43e4ee3f3fa583dce56a5424bda587112dec749aa069bfffa6a077d62972a42446dc034e808dd6481cabfe210862b71fc5de39e2c3de21123b9ddbc6307b51cf681e6cc230b82527653ad68dc5a5d09d55f8a17720766085dad6dff830285161f71140e3abd433d98980a29aa7617ee057f539be4593059b29d770a19ab07ba375b35fd3bddbfe90272cc52a69ab1b22e80bb899b06b11eab5ee56a45ecb9236abf6a7b0afefdb06cb882b33222c61604ac702c1c0e64df040b23d13d3c8ff4227e9abdbe92a9b07171982162b64d8c3983dfbb5221dd4b5766e424ed0da96baf28e494dc09cc5624d5e8518d2c413a83e2fca64b1fddf00011c407cc1bc2b950aa2f2fbe72dbe17b6726f1ccd903f090d04e20baa978dff5821c7a561cc0badccf6da66bb2d6c8e0b161d2f93d61736e4849e1818e57be3b3de124a8216d103076e238e180195a626d27c41839c87da86adc84670e5d0c3321c42bdd258f8002aa0f8e4298f16d009677c3584f7971d4ae1f28f40eaa7576f31508aeafd2c5afd74e686c9c1d241c99ee6b5d2b79de978407b7306140fb4f44522c5c328bae271fc31519f2efa2f8052892fbc6854e3e40154c092cbc9ee5fb2812e08876c00533b1c7b0e46f6997336de4b499947fb34af16c0270fed447b9a24ed03d438160f3cd58769afdd353177fe723f093992ec514f5e3a4d8cd9647894aa126c8f083dce19ec1420caefbcbce14527a498958b1f68f19f4e6fdf9a9c632c55e64c26cb88328a73fb4338bda042a00520c6f7aec4ff39bd5491960463a3a885024216702fa46cc895c3300b8061cc307fc37d8ed60fa048d9b94610211d8badf380d4cb3dcc259fefd306532627a2a42a2c8cea3cf22a3b6b535ca07a0ce639af211e65fe75f028d3e8b642628d1c79797e9566741900d71676077cb373edf92f08f0c863f2cfc8a6a3edc60baa9588e0eee0d0731fc6d9bd8c198b397a776a85e4b91993cbddda15972d0ab8b0350f438079a4ccfa76a5cf493e116daa6a9cba013749d3db109a7b65a2ce18a90bf1818df25a869ef893f40bbf1c0cf2d18be156b3e69df276a4eb4ae73213a87d9baa20baf19dba9b958c15da84a83f827df2a8a59a1effb9cee57c0ef4a0e1d0c516b4c75105569905d663596313aed57f63cf3220fc3316c9acf13f38e049e1eea07ed2f606a029a7047f9cd640b0f646c58a8b4a3b38b513539c6c8f6a2dd318f3f1e3ea64f0ea8c5347f93bd73877a611025c8fe65939c0459d5168a732e7dca2824e18a54febc419ce4afa5f26ae793107a10e62c3a5ff3308113c9c16cc63b3e3ceb5b1756eaa1407d5d228e4d26e33690cd295974b2568bdfa65877f2787e82e05c633df129b9e9ff2fbd27e0b04efbb63337e8487d7638fff6477761b3206c298fd0ca9b667e32efd3e946e5354f989921fdf3ce8272135da42b3aaad197a8310e9c9c466ea559574131a52fda2bbaa2893862d3b85d6288a786f60f61411efdfec4f9ddf54a11d27319225d27c4d842f48646b164b7040afac3c95930585d493a61c140804d3138be1beb16e846ac54baf978fc0a516b808c69bda81d1c8b445c2e39d8ec44402ce401c23cf401e2a3b32cc296ce64ce89a3df6db8f39f13eeedd9eb3abf24b2a136d1eed608218d1042f6de72ef3e0c740cab0c388f2eee759d4ae549248ce657c518bb35b3c9ee7ee6ca4c49b9992b2333f3644ade342eeb78eebb8b2fcf56e2ba8b1f3baf48a7a3ab79a92b5ddc75ff5e53f2be5f99f7ea5d1ddfbdebf43dc6debc38eb72f4c829eecc4b311edf186fee0d5bb237bdb737f3eeb1d311dfc9609dee6e98f11803565decbf34176544945948f96828b3cefa11904fb67928b377b484a46c739bcbbc75988b09d5a1b80d5562c9605d66168bc5756b75eef1765dd4e97ee978e4ef9db9774693f16e32ef8e6793ddcccccc67666632950a635d0eeff8aa2b55bb1cde6dde5dd575a6eacec03c64b6b9b4e1d1ba0dd769991bdeab61717ec02cb38f39f3e7fbbad8e9c8790dd7e92680f2d051522e3d3611d4844f2e3d76394ac78e2ff66339a4080000b03500000000000c2982b5bfb83d3964ae710068bf347ccfc371adf3e2adc7031b238c7fd724bb17bfab1cde6feee231dfcbdc388eebf426795ae417b90d1bd8078e673ce486e3f8109ddf78919dad391c7765e33b8f3b37eeca065e0de0c6f37bc0f11d1cc40dc7f18c8338c2c70dc7f120747ee37127762d6870e0ae5375f7f1660dcacc3ce4b28cf7e2f6f0d43800708e1a8e3f73c396fcab6ed892b3d3dc1e9971f6090353fcd2f1e3ff63f318cf16b747661b7058e335dcc595195f6d75961456eb8a701c57648619669081c362c9a041838dcd8cc78ec7e63a5d53a554eaba9aadbb1ef95fa783329d92638eb9eb72943e73efce2c41c2241bc9a5c733e149de2a1731c6b85eddb5e9dc1bbfe1e2780dd77b8d2bf3afcc5368fec8dcfbfb1bd7b90f37f07dc081e364a97ec3b7d8753de2ddfe5d5517e3f1caf0798455d01916c92befa57b973eb73b1ea6901d0fa547bcda9173ef31cfe03813b3066bfe1bb3ce2db273c32db293c3842a15b0318a12aae4cd857be9becbb83468d0f84bf7d1380d7cbb4ea552e16fdfe77933f7aeee714ec365eeea9e86e3a03a1ecf9bc1abfb1997815757a787e4996f9391b98ce73d7632325ed6a0c4df1702918374eefedd30cbf8b1935cb7be47cf53a91e3bcf535da58a99ea111fff3a8defea621e36675dc667e0d50e9bb36e73d6b71357e381a120e418a509a22cbb1296569e58f1b079eb2dfca3749baf78b07e94ce7acc72c6675c863264dc9a0fc9aaee864372f7ad737cf7dbe44ad7fb6e8c3759b766fefd5e99ef614b8edfcc37f33893e3ebfeab8ebb986b6e2873cf64d9fc371c9267bcbb413adb5c758374661ddf704896c1d2d123a7f86678a441e3dd0cff6e4ba6f1b025cf40e358c7c31434667836c3639783069ee13368b0e13ec39d477752c1b9136956c962570f6757f3cd72abaffe7dabebf46af58efb66b9effb3edbf1445c246b90bb69f5d54b2f973ee96964d463ce78a9f5aafe3263380e77472bfe8719beab1b7128b3f7cdbb211d9a47556c388fb29d3f4239cb429b43efc7da7fddbbc76883eafb3e1bf9fb8c98a3f3ef53f11bae0a15bfa1e2aa1be3cd0c1200327ff97b773c5f50eeee9c54701aa9916ccc69a468bb67e479d4ad903e99544e979f55bae572f9696566c6f358b0f0a9b93273aabb5cd54f1cf7991b16c9338f1dcf4cc7e3dd90662f66e55dee2b8efb514c4c4cccb79a1bbd19a4baf7d50d8be4d5b7c9d5acce9380fc4940c66ec5f7c51bced0e96fa5558880fc3d765dd7c99b801cdfddefa96fcda9aecc635724c7fbc3cd32780619c3fb77431ad9bbcef42ef7d59dc1b4a841499f3428df23da20b35c711c667905c6a1cd2b1ea3e971c51b29cc601eda9c7a8c39a19753dbb6b56c87d96e7e1df51b54ea8632afb8a18c99472155c1e2862d39c665b83fd8e43eddb6c78e07b58a97592853d961c186d2a7918e8ab66ddb3a100c71c21a45b3284b9f98d3442fb11ae5588f6ee0b8e1a19777021080bb7de7c6c8ca374696ce8d9175c3c5716fdc2ca80809009909cd5ca71b694a5924a1748be632e621183eb43d72e6d1449a2c30738fc121c8ddc3e15598fb27b134d284a26c73174d68926bfe3dd33c9309b1f8cc55dcb04856f1ad85e33a1dbfcca71c6d1b77f9af5b31ab7026548a98f2cc25c41b798e3331b1e15c4296f2f449b7662e4f8bbaa5e2dee5671384908eba15a3342128cb4f2a55b23cd7e9888f7951b9a84e2a79d565c7b322f5e190e6ef31971d0ffd3df5b1b84eebf4bd134a8392c77743ba02e788f87b4ceacea2209d59e069f40206eb20f87d9dcee34e4cc4ab01dcf80def01c77570103ac7f11b701047f8d0398e0771c36f3ceeb49846d3c8c52c9a46b3684299460dca9ab3b8e137dec30db8450f3a18077e8f1cf6c83fe0e41a16352c58b8f8cd63b7838bdb3cfb77db0508de17bfb161bd78ec7860dc17b799b05a9c050e6966f12dded0a68b2bf0761c2fb2133fbc1ac08de3b88f1bc781871cf1ddf071e3388e030f69a4c992bf818bec7c1f0e7be44f763ca9c72faef8e5e2b1dbe17bcdfbf1669f4711af7674fe706c90c5556771c1bbb8ed73fba741f916177cec7822ebb611b7858aba2569ff889ff9fbbeef47bcd09090114321912cb33871f23171c2a4890464fede4343310f830835d8430f5b28472981993fdc23b3387112db4983f2cd446661e244a873282806db47ba153652962c9320e9a06e8511292be925b1adcc9c223b12dfc55bdcd7b0481d67deb88c49b1a871815b605cc302dfc7893b7c84f31b2b1eb19cb2e2dbec78e4950663bec52e85c31e5962e9560c7e68f3f7d0cb371e82f9fb670e8e7fcf374ed60d5fcc577c8bb972c595494c6ccc439994e59506e563aed3386edc2e5b118af9fe25756bc5e5e595cee99d159d8ec6924a83926501292fadfc40d12d7959a55b973885439bfc3de686357c64ecf1d6efdf538f37c4b951c6efc61c5b682e8bcb4ec537169fcc5fea31379439e6db7775c4fc7d9b1c8b1bf3d80920e60f7befbeef3a62feb087c3f89987f3287ec553d78bf16e91bce206b9320b9c152163cc5c75c31a9467ae33b306676664643e8f66cefc992c19432fa6c3d1fbc54253663138b4d6939f3fff7e1ef18f87432f5b99ab7098651f0e6d96b138f43c999b40100747c66629333b1ed5e9575ce6aa8889f1baa5c2a1ccaacb7810c49935e6d16405b9b2eaab6faaeb5d8b0305ab7a6855d7e979e45d76de67f09177ce7b0a875e779d197365fe5d15f72ecc63c703ea2bf08af01966f55dde53753cab2b7f1daf109923fe0175191c16c9a8af767446a9705824abfeddf0f97bbc317edf75e6e71de6d1e3515da73d1cd2ec3de6df278425284926b12281909088ac147df17b188f70f2f77d0f71722caa9165d686def7ddd4e385b9d73324a38eba4e7b3766d5ed991975d9f1c04454eac6065b1e51e741e1acc196eb7413b5fc058759cb5d5aecaf9fc27337b4399c471995b5cc47bef00f36f409942f0c36a48d336a64a3e51048db5952c41e4159ca1043590957f216699db3ce06a794739e25852d92512d5952d84e87b6d11b0ec9d2c69b39bfdd962c270fd81453605a4651f4f2c02a9632a8066526969138b071daec0a5b8c36cc8794524a67cdb09a654a334c02d1c8a0380a66c7b22ca3f49396609b31c618e99c9d83c5cad32cb322bbe9176477db491d1001a4ee146ffa396038d5c8a2144f535884d239a5300528421305a51ca340b940672b509064f9688324400443124880a2841328f18421ecc4c892a61088dcaf4179be3ab135499d81edd7201adbaa03218da6dadddddd33c6ee4635d8ddbd0292a9132fb25f66d8d55863e67491d54fc9e4eecbd9d194b917bacaad619a66b5aa5934f164e2b81507acfcac2f19c7451b229542128c8e04a00945024842519424283902087288832921091a9832450c4c98c205a02954d050606b8e51a6204d39ca6884c9310a109810658a1046f37336bd62e9159be122f9862658c9c92cdf2c573b62c4f48aa577f62401f5426d49bd509160e5279ddd00a09f2d634439cfcd5f456c1b8c2c58f9ee4c061772f743292428ca413af75f3071634abb76c0ca7cd50e58f9964957a44f74e5b04cbbae16d41668a52ab3715401f126e99a39f5331b40dda9580158a85cad62580127936657ab1856604a9aad21b145d993d60bcb32cd6432994ca5d20b28a050dd9cf3a217bde69cf3a217bde6c49d694e596bad4d3f71283829ce8ca6b181ac5372a793b52d2e2f2f28542a0503a3ba542a5555a95a5c381bfb52eb8b28a45aa6ba1713ea04d3303027944db5b878def4bcf6525e0c0c8c4ae5793131dfb75a4d61c50a95caf36262be6fb59291513133f3cffff73e998ea75dd0c0769531df4a4666252323a34266858a994e47e7ec05142ceabf7de5bdf19ab13dd3e598f95674c88b693a9e14d8c6b3a6a6a66b6a640d66c18286a6a6a6450b172e40904517720556e62825043957ac141064c92d93bbb5e2117f451c64660e2877dff3c9fd8cc60e03134c28caddcf7d908926a0648e663bc9471a204282ac763c638f19c33fb0902cd32c2fb1531c0e0112e30dc541b2897b66beae5b233715d283dde4b6c960d35c73352595979452ca1916c9530a114e72d32bcc78e7e5dd700f964be71ea30dabedf2ab1e3945eec13d14902792fb40280e22b1cc7dfbdca5a1c41e730b99b94762c9252da4f8eac1f036459e3e3e447cf2fc0b27b6e7450dec8b1a5820ed937bb0e99335398b364984a20b808008fc40ff0d2ac92de50347729feb8cd21df294f2205f83cc3cdf749e8796d3025bf69ec8d15c26cb1e3b6b356b356b6ffab437951e3b1e6da2e6a433d3ac04c928827226857296655926a7e4ec54cb613faf5da958f11c32affe72f0326f9466f24a1214244e243d913bd9259d4892b40be4ba4d9bd257bc7eae601c759752a9b4852edea2d6efca4cc395400d66420d14b58084254b1be99f46d2495a49502fc9de4292caee2cfc211a81383db033cb9e4925272c32bf1e825289cc0a15cf6ae4189c1c7363700c8b189a989a98ec31df302882c0b0246734c8ac5940eac8b040040494334c763bb06e071a2e03d42d9967078f955e94ceb3e2e6dbeb0caf97312e7f7373195ed4c002093233ce65bc9ee2cc8043191887de7c7b0f9663e050869bedcf1b163227bd2b5e6fe9f2ca34985d022b9ebdc706f370d7e9174958eef52b5efa84e1cd0b7318577599f402e3a62e935e5e5e5c892593490d66331b9246c4a04c0ac51b4aa3ec0029d3db1335999d5eb924de648f9d94d9b116fa791707bfda28285d9cde95a42e28485bb878965bb0f08e2cafb84ecfeba2046625b004d20b71817bb0bce22d5ae643a924675f49a3a43995744ebcc25076b9442863d239339ed59c5d1265ab9cc52858ace4ec724ae7f44e764967c6e5ec598b679757341f1d35174088a02e470b2c64e6159fcf321a1c5a1638f4e6310e0f1e87387166c5a52a642e77bb1937e686366bd75bb57c359f82b9ab89736429ee2b1e3f5a9ee5f996a3f0aae51505799543e697f91617bc6ac13d58e65e4f90ab923c3b1eedf6763f8133f33c6bb3bf18b2f3a18c0e0e53949745a326b269d612b6b984986f3177554add95e603e6283c4475986bd7077d0a0ff14eef42091905232632878ddeb8d3ddcb0514dbd7a147b7eaba52152005fcd02d9aaf2f1c71f9baba9216897e699a761d346b3a38e4b095baeda79b7e92394caf3dcc7bf80483573e52471dc5bd763c6c3f61accb61525defa90bf398abc2be4dae5e2c3361d6b6609f7dca81dde5da75b11153ee3aeda2b9e8ccabcb81a9ae77ed9a324dd3b41ee81130261b326bda36396dc7f62ca439b06b12f730efa94e7f51ddb8839dbe9dece92db72da757da727b3823c7d09cdaaed3ef1cba731dc4ae61d8638751c9d88b1958ec3ab33bcd9a764b3037a5699aa6ddd26d685a942b5672f6aec484128cc8ddb51d25989b3abda8fbf0711d4a170707b6d4e9e8d143cc5178e5831e75141e62a3695ca73030366c742bd2ac7d4bd13458c25d8a763c64ef5e38edead023670af64703b43fc7ac611f0d5ed7c1e5e2d0e0f58de6d0d2a2c35e7bcb29cc8d3bf606e19d7ede20549fdf5a6e77b5a7ee90223ba9c76eb9bcd4727b971bb6a078e8aebd0085891c618fb0f5a9200d28bd845f903aa27bec7674ee30d8e0d56049fb751f3ca50e07e9ac3d769a06ac0dcef52de3ae6b0d43f32f1fde559f07ab604354be7ee82b3943f9409fc22b1f1e2a763dccc7e0950fd590d4552fb27344f7d3e949b61a6e79f71e4c7bcb4bda5d5eba0b0e32730b1632b3761d74e6a6dd86ddb5d3dc59c3749e2e77d376ee5b77bbad89f276d525a2a5a0085b28da3962eb2b3e503a348debf484d5609e7a911d1dba057387702f20820896d82102f301265cd9894d23ec2a59bb4ec35cf9020bec400aa11d9d89ba71a7843d75e34edc416538036271831825edce5100452f14d5212f3c91c3787442ea8295285e30ca61ccd2a74e4ae97574a602b88225b2a24ff61359318302f0025064c5ac43bcd921b2fa54c87d27f47350609f63942b587218a10019d9220d48051bdab0a1c30136abd3ad28edb36c593c43de88432fecf21e5e8e605dfef2ed2691f345b2bde1b37d774ff67293a636cadb752687d360966919ce7ab80ca0e78f34d260287d6cd7286c59b762c419d6d69b74ce392f4a29ed6efc991027b7ea254f19a534d6cac4267b66184ecc8951bbcfee7fc5ee3ffe2ddbf43fd9b6d8ad963debec5a6be51a9c75ce06637d1673329b6bed2c5e57fd55af5ab10b67995e27d8e29c73ceee8e15cc3544703efe316762178d08d6a0239bc726e5917bd249eba4ddb30bdba4349ebc1a22486f04204f1a11ac4187766b228d4c79e47979c5b0c600589d3cc030ac2485bd728cd2852308d185201cc95eb813e5388bf2ba90031e2304715d1002010f94240e05d2a02cc7a164688ec030ecfa801248701c5042051e5002c97565dd22c7284af4809a80522e38214a1750b04929b96085460e178aa0d3085bf581d73234336cdce430429912a954b99293c398e5892cb94fbba1f8416e2c94203716a690851d3cc98215723f071fe47e8f273e68018adc5740920392e47e04a26c410bb9698e5dff091b7da4719162439c7c8536dd0a6942ce66385cbf6eb303bcaeeb3ad773b88e73bdc6d5446cf2f2c63cb7b9c38ebe7cf46c8312ff8897a778c5a37f48bce28121109570c227d7671ad878d07a3ad872d05eba2b8cbb76eeaeb07398e4aea4dbb31b77b80de7907fa891af4b79571277560f4e567de905d94b3df44e86b3171ad84f23f9c413199f18ca4e4ca13ec1822c1f9f40929ff0b9b890e5312792206ba57546cc1402c962e858b0821831aa597d54868a42769128b63a2fbbefaab3cc3d728ace4472bf6f678d02536b79a234d6dc197655ac361d03152fb7137d39415b657bc3b696255a94b05db13cb33773c0c96a19a25e8d491b6d883457772c60bfc7705864932d866b42a1f5c26ac8828d4430c2951c8b48502587efb0794d542cbd4cf3a52ec795279e5d0b0f4ab49401278a28112c0a872e1c59b1dd0eb41fcbe518c5092472c8fdc009a18c8dc1663946712228879c1349ae905497907959c659941486a85ab08265384bf00015baa27060e2a08524956888c6c211ad81105940ca8a10223bd2ac88a459191694342be6d07a9d59ef5c0b4a32ebb672051564f9900687880e146951aee04344c4383c8125661856ba7a956394216ce022428c33c6f9f8897fc4497b62d7e5c939e79c3473ce396966ad95ce39a120d54a75885ab1469d00e02ce3c9b825d82ab10bbb2a16b5d8d2f32647554dccc932abd2d191afc7389d206cdd4884d862b768a457ad2d7f409afb190a17d0810e4e40033198a0bfcdcf994323099ca143db291bf81058f0241645a328c3ccea9032e38010054cdea65b33e3ac70d4449e566890e7dbe6d4042151e4b3d33b7dd9f1b42d326527d93821e4171a897e38146751d3089366ce390395431b2ca8d082242451aa80852856781225e702a0cd8c32ab5c20cf39ab2491270ad560144452e0c1142958c107619821075f4022620a2433c8c0cec4f1f1f1c1c073c8a6d801123a95b073ce6850822db02198e5147e70a6e064c357bd628c317e668a29c690e723bd902b772b467942508e1d5d1cf9e48adb49fddc845c2041660f96eb55e9b34cb7cc0206b40a5ba49142b2bea19039af76f91e2c632f9cd81735b04066909935bcda01247baebf9c5bcff57a7136be5d61585fda34ad1eab3d43f2f5a8d3b567e6eb52883092c3f8841e49968d6e9cf62dbea8828d52446085661cba15a584004aa6f43a748bbe47677846831a96b91e4e83407aea7b62bcc16990be470245c2ac620f4335486d1aa4b51fda54acde15566bad33622dd8b53f4465fa0dcb4ad85d95340ccb304dd3e4f50cc3640f962560bb75619c25450c24489c371432739c7fd1010b24e21e2cc7639fc77090992fbcca72c542668ea72c471aae76643e3e3e3962dae0125b73f2c26a95b4db5157d05960e20828c8ccf1094039468e519cf0842c7f75b783a4b807882cf10b7e54ec64585e180f92caeb959a80e3240e71b2a474ca7bdb95d2d7d739e79cde7561f26a27c8a31ccf3a8a4759c6232ad84a71a4619c93c69b496ba49961b84299ebf55ae34dc5932a60524ae99c3348ad18889683d44c29131327c71969a491abb3ce7adf609c6731f479d5ab567ce1648aeb29a55efc8f967a61af5776ea056cce593feb7f4c2a29957d1643f2726213af76fce0655ae4a22d95567abbd6f82183d2e4d8f990f3e21cbb15c53d349ce1dffc9ac416a30dd8452f3a29a53407cb326cb2e88c94ceda190822e06383d02c29a5320a9bfc1785bdc1a1cc37dfb6d8dfd732ee30ad56ab9b388efb3e190130705824c3f87543991f306f1fc3e290ce3bfbc2a17d8c1b18f7013d5f91cd8df9013d5f51bcf99ec4c0306c0d0c1b03c65dc5b8604c18f6d78df1ebba7ef3633ecb3730e66d8c0b9939060e61fc060b99190656f20535485fb2ec7858edd08ebf250dd24cbd60bf250dd6fc5312146df89ec49b998733af98f98a8fe84b819581510dda15d85066d665e0b81733b0e147943fa2a417512c51ccd2e930e5893fa278438f73657c850d2c9781ec90e132eee23a8d7365c0b1c19b8b74731b1b9b18df62e0150f188f711d301e03c70663bc48bee67c8c1bfa902f19ac0c180132c6cdcd75e6cd5ddde67e8771873448dfe28632b7f88b9a215ba3414a8f1aac39fdd6b2db7457df9306e9817c4fe20d7d0f119fccbac581ad798bcb8725a299e3c30cbdd0e6290389c7097146504a29a5945ef72f4cb0f33ebad5e2f4b3e63e803535c7b1e6f771d6fcd7992eaecc2d369a1be2b0b82198c3ef86debda1fd9db9615d71c39ac34f49a657f10d657a991bf6931c7e5fcc0d239177c388a4baa1f481b9a10c4a851f51289172f87d44a76fd121871e323670e816fea18d328fa9812349723dcd269ab94bf366a373e80e3d0ea5e3cc9c1251b3e8299d354a44333cc13e6601052cd80007449065c90ae8b71f2ea841fa1135484b4499be64445f3aa22f11d1978a32ec82bdc206b69443bac385339c7d4499fe33fa8e3ea2afe8850f8dc6e10af23c6d7bf783037cdca27c68102b61258c45e1838f1e3a481c1a04830d2793c9a45bcd7dbbb68b9e103969c24467163d2172329b34d893c9f653ef9ecc279406fbda9c73762daf23d2dbcd1b2a00e3e6f6ee16c993db5eba59d52e0e741ae58e2787b64103eae0c819d485e0f7884eb6e51b0e69de7862eec9dca264300c2b69736e316655e3b46bc808244982d05b14920695fc1c69b0e72c619396eef5c3228bd57ee6946ecdbf747779ac5184451de6d74f3fb376fe20987a38bbd269c00671e6cf9d327722b933c99d4131777a771a31871a049a4a1aecbf44d19eb7bd4f87b99ee47e777f6a84cfe1240ab3bc1d9d2814a3069be88926e744711c2ae4b245991e4dd774aafd684b1aec87d757490db606d460bf7435245a124d8916d4606b471a4cc28693e8277347ddd28ce4fe247ad29f54a20d31f79c134ab768ccd9e9c11226387842054e60c1ceace20211444185221021053bd30a4d7c604082241ca052829d0268e1064da284a0094b886267ce1d4f46ba082151edd22f2e477d661d4f0aa561d74a2d9737f438abbd05eb91b9054b83d7ccf279c0c6cbd276cc6259ba457dba558d748bfbc98e5ce7384e6251d8982d58cb228b85c10ef7d3afcf6062b93be9561864e6d3bbae0a7578498397d00957234025d8f0072eb78475491f2db1a7f711908d79d523ac49f2f53e6ab012d5a23a549bd4245549b7ba5faf41dd32a152ad253607b1150a991975975faf3c8836f460198543d485ccfcf28229936eb9e0f83a24ade43ad4e0757d125d9f45d7e7d0f5d9e47acbcd4e17c7746d401a4fcb38d4d54443358ab0f2d85037c1809264f99fa20632ea241d64a585927a084b1d4a9a39b1e5cc892d9f64a522211d1dd5a25889f205745464254936c1e4afa12617d0ac4946498a8088e4cf1016a1a4202b40473f46a8a4131579f9646924cbc70b28cbeb08965b54967caf64f9ad4291236e1a797a095bab542a413327b6063473e64fb37ce4717040f0f73c6baf20a02c359f2c97e47036994838a02c8fcc1f23b2a3b021972514f92f60b0f29c1624844d66734e2a7b0a94ee29e96d2872ce196b956d9424528c095ba409abec492bcd686696690dc5680a2683759e77695a495e286b6bfdc64169a39ed247218d8cf4daf04c4cd339b11c0d8b204b1b8a1314b65bd4444343136d887508cb0116020b93a3940cf0a0f40323b4246c4b8e5232700227ec29472919383203cf6699b55936b38513c86436e32c50b36292a0151e4e66240a402b9c1a38336a4031020a1315d6485109be220cc918b18108628e60b4328202af89a1cfc80f11aaa3a1180c5809829912e461208a0952484052618007a8258c603080c4102f46495218502202972849280c7800042d472f194e184060339b7136095894e0e36271322a10713ad2ac98b3236956cc56091f301935b14040d2259d2e9004101785c874011588609b52d44d11543a0210f704128d094d362424c996482ae9a0045813479a0552a0e492629449b1c010403998e0230508721861c80a1139a2fc08a10539980892e2a38222722c618a2c2dc87240c162696eb92ccbac274395dfc400bbfabab0e650323254a11102511765072aa12986b8c9aa188cc106b9bb1b8a4d9679fa10f3751a5b2b1e357b7d5cf1a031b6e28d88acc8243a894f2201b040893699de1fea7ce2f3a0f5b2eb34ebbe94bfae1a4640c958ef73268532cb0980e548644524fda324b22201b02c89ac9824868d524a29a594d258b596b7e07002d995b9bb1dfa19cd4188d6f216bcc25eb36f8aed6ff5b2b3e55b4bcb75f45b5e246b59a665d90dd2f984679031ba6bd24783f240b86f3d1c0ed283e5ed326f38ec1dfa4266865718de517124aa3c8809c10ff70b884090b880066d481c4cc547b3644e0eed23dad02381b0864dce01680eb080032c600a413372321b4eb0612cf241be63951e94436115c3ae08052024b9a3151391143fc861bc2285929a069248721fbb2a074e6143cf53004fadb556f00936a4a1e91c54b3644fe7f99ece14bfd881959f3702f1462a01ac11822157c3c6f6516d738344f28c51de186fe47764652492eb55eb95dd1e0a10c9170e27407798bf502d50028b11b980cea93159f4a62db43103c72602d186fa781a4aa573e89cac59f4110b367b89d3bebd70a617d33993c9f462baab1793e9e5c505e3c1b0969b830eddea1e6e386c39dc1e90467adda25ecf1bec745aa6b39d7dc761b7d793e9ec662faa41ba9ddb4c9dc9dace5e20d6da6316ffe89e65ccdeee3874eb74fa1c74a0a7ed6432e1b08b9da7031ba250ddda4eefc99ca65b1ba5b7e95669466c1067f7c590c5ae173bb0567230d8e26317f16a473c761d11d3d8dd550e31c7eb8839e2fa2259763a7668728a2cbb495d322e3668d360c46162cecf1973ce3967cff5fe85641d6d106267b44188ce94b1af902cf72b15b2daf18a7f64b92fe583f46039622159ee39255024774f908ac106e7cce48a4a4a299d4479d2ccfa64b5a374ee4068967feadb816479c3ab1d250ca473e925cc436208ccbce241b5d8f5f0cc98182c06c3b81486a5b0542ab55da9d495baaeabb73fa0473e3ea01472376d2fddd9a621a5ad67e68d26730fe8919ee63d763d3c2e3037c53cf552eaa77ba5de73faf61e0a702792b70339e1201c7799b7d24bdf52a7eb8adbeaf4d55337e62d9e1ebb2d65c270e93962cefd3acc0db197beba3d5886f9f60dbb42a69099630e7353e76e0fd683e5d333d536b90b03491de33090f8186cc27a80c8272029dc83e513bebefd450d2c573a67c29ccb9c2edf68fde9a2bc7832954e26d4556f51a1502ad45f5e50cff28b0bea9c45c94ed5a95287c142664ee110857bb0ecf2172c6466175b2a6d0f4bb2547a8f0d088652a65b320dca1e9a06b9edf66c3f99bac71b79baa1cd59ee30b7bdf4ea65dc76575c69bbd5041748a9542a699acc3a62ce1a5c4919234da31fe2ac7c6459731b765dd875d18b5ef49a76551c66329b4788a60e7b97cd1c8a573eb8d3391744b021a5382b1fa6eef55af76c296ddfd834764c257c8f98df2e3cb5d2e77b30f9d25be220339770b8e5faad4e297163bfe44eecb0cf89619f189e7d65e5838b4da39eab2b1f9de9dd8becc46e451377e34e87f545832dd268f598b63ddb7049d3b29776681afe91ddc5e55b76439cacb95cc35b368fbaf4db8c6e81e06f6d96956e53ba38546ce9a18d0e1c3c238c545a5eebb9aef1d8f9a078e5033564b2265e4d3c64fee54576b2c9aa9969935b8d398f28fdd25e63e670cdd2e29434a59b5ddae07c0933ae46ae49426d46b7360dcbee75d48d3b98cb0d7fc0c1b9cd8c97b4af4aa52d4a0124839a1455b924d72a99e45a9fe4fad2d60abd05d42ba05b1503b9d66d5a79a459f51ea069d4bbe8c101ae2b52c97e806e69da6d5193a37669977669b4e3d1367c7d3b926e95300470f28febdbebb54bbba10d8ef6a8653768379c91717258242873dcc31e39c3a51be26499b59ef787914ace019a550f6073602395bc71af59e6d262e591d25d6e68432f67b7377c08e64c1e89d9248ffc8093b1efc82312a85bdd2b86facbcb2b96479a467dbd8b97bb427544b0a573dbebc6ca608e2d4a3539e668a83b44e30015110c6187088c0b4c30851dd4bbe3d97e63d328e130cbaed71b993ab5c4162f650824eea8a50c51246508a22c31308104e9c1725fe6186fb267558a086628a05b61b492e7fc0f0ee8960c0114791e87393190432ef3b021647a4d6c36b3cc5a6fc8264d245240004596c9510a088cf2768abf12885e899443da23b39049e32fa744c2caf5db49e66d93d995d755b1796c9b3ce8fb3ae87bc88be498c9ab336b8cf47587d9780a6d52892598308a81141218c921953282244e72394ac97a04537248a58ce04996a7b808182960620c475c72fc01125c809123136350a2e39079840e78a068c84c939dd3e910d390d35b7488d0f0012492b0636fba44a215b61085a01dd35b2e9117a21d8b8fe87eba445244ec98300e4da3bf6d4db4fc25b1b32f6c66d78165b2746de0c0712fc99bb26c52ca1f092c165d8c2e966593f9ecfe909f3ab4e3158fecd875641a0ee5851c7b91dc3dbbdd65c4a530880d1a52d8bbaaa7b9bebb2b1f3eccd885a31c330e0de2a0434a20a40f4d12368823e68368b9bd0947eca3c5e21729b0a1fc09bd9923270e2f71086614176c182f7d6a6489c322f353fe34f8ad84430b044e3dc166df6892b071b2ba1e40b4bc4e0381617740831d46287e40c286b1c88a2644d66101d18698b3ccf3e617c0d08126b2f8e00b4d50d991f7624e4d165c1085941d0ca1842576525058c288139e7c20044eecf0d0440e68b0a404265802113b5202c91f3903917d0e659398a026b965c87d49347ffc303104e429ee98c0b0c51ca911528810924244122944203131408a0786a40801254729423889528448225f394a11c288cc0528534a8dfc9860ee907922337660aeba2b1faab70a06cb2b4d836ef5c626628e248a8d94a9340203021bb6510e108da5ca8421c2c6bc4d1f8b448e51ac58c932171d4922f9c488a8d65a91aee04c37cacdaedea75b61fd3220b860ebb1631f72faa9e5662a683748f35091573bea312c7d1a945d766b14845a3946810296dc46ddea6efa9565195604a429946658d0697c249577adb50675eb6ac91736b978c2862d44b96d481fe6e22338eea58a8f4e31a785228bfe25d5d2423459f42d8fb1856ad49566d1a3b46c0893a6a49094e9a74fb7e6dca1d732a1a1505ee99f2c8b7624530f64724e30d3f7118dd734d2ade94323e9c8ca154a3f7f3aa777e833ec1afaa16f239a09bdaeebfae9568c22052699ce649a8485b9eaa12492c1ac6050742b6c28999e5e2dd442d18698691bbd14d9b07f905238cc70683b09730cab2e8c8962a5a36e3873d842dd44479129f7925462c3270a579a4acb55d7aaba2a60c003a19d4791c2921ca34421490e658e51a460244ba24d0841487d654e23f2488314b4911dc8a19c02d6eb9247ba555b6e3abd34d2ad96d3cb9f6ed9d3b56fa69bdd140ec9406858bbf46990b65cbb2d3fb5f4514b9006690b6e237b7b0a141b4aa04c2550f71f44329a4d78fb11a473f62a33767fd41cb575323d763c4ea65f1a100dd2eb576759bdb14120563cba05e4ee51fa642b9c190de278a18d3a27120dd1aed2499de508a55060928d523587d3a7ee84f327d3635745924fe8aa860dcd474ec954e3400e25954cb51f49645403c98ad151056288f4a934f7257204f7abe3293dee6c573e9145128a34da326ebbecb8cf8e87cd1c9645a52b89e493243ba55bd745afb0ab64ba812b0a2d9cc003576ee0e4270c3b7509222758200831084306bcb0531f637d164bb4c59055d7c5912320d170824f61c336eac1019345bfea41f5be0a0f491dd921a2a2073baa37cd103b44a40ca6b0d327326347f5d8f5a080c9a21fb2aa573deeac7a88f97c0c1e12b790022b0ced106924a61051c48eea130f2152820210a610851d153e02bb87874c131479a1c9ce10227d22b109507081949dc6475cd769f9446a57429139ac76e8d02095443290c4221a4620897af868d0060c5615a45b15af7c68903ee60334127d5ba1ef233a5f862094b4d3d76917979e410a5bac618da0143d2172228da0143de19ca066602f269896d4adce39710848da11957aad8a66a573625eaf5da92eb95ecbd2ad2885033fb9bee45332525ffa69eca253e46e1b9b06ab4ca61ccce90f34a04d0c2258fa9006db3458b92946a69b4cd75f2c614fdc9406c32b49339a399c9366d50b5f4d5a5e4f8fdd9392066be9dcd5a459f515875966ade71dbcaea45c9b3458eb53536c7831c9f59452ad4abca91a5283f5e53495a28749a94eb1c3a8522ff7013d1a957853b376146fb429301826f5eba1069352c1dc950a86c2dc6a02d5cb0b4c2aa43030982362d22dcce51b8e95503392a7d350ae34444e661326b90e2d6910ca131b0dd68ad360a562bdc78e076649b79afb3215ac6634851aac9f46f45c82e792066bc839c1d9b6ebc270fdf52f8824991ebb5710487252c670180450a6475d67c6a06ed18aaf250dd65ff80a6af04ad25db84683b573cc45dd900ae57aef8617e5b06042b9bee5869ce98632f974c33994ebe7922b89926e69afbf82ae25dd2a3d7b3d0df8e3fac464e7eb9a4c97c974994ce74e4de73800944b4ffd0a22610e834321de7bb00c73154e83301cbd30b4e3a1f4d4378ceb4e0777d3e9351d15041ba2509eccbb75c2ae140ccc5b85dd0bc334f51ca8bfdca26e68ff1262426676394eb7b80629b546f4267ae1ac3e877a9cfa1af5a5ab1db536e56a460dd6b35660431c27b91ea75b339c742b3c21c111714f8cb429da51b72e4c4af9d3508c14b61c5ca633b01de3157ce63ba849b79e583902254f2a450340c8612fc9b387343094c376926736caf395c63e328128e5b2c49dc436b1b1c119914662c992932449526ff692f950a321996e282966d4c0e260c34683335e7ce0053bafd3b373dbe09c86cb6a60c3d3d8e0681ac8f3366a6402074484408a1e1c710128458a78c2101640220461400210a5494c1c3ac10669124626ed393f73981184dea26a34382f4aeb2f2cf3ae13c954dad0c418b2b3da99813c2f536badd56405300c31032d0055c1c80e2d020e9c24d18223357882ca0ea5f471027548d824b745066c91267ce193e9af5c1ba55ce7d888a759a956ee3afd31c18614090464f28f79ee1b55d2ad9658c32e291575ab5b92bef4844a0132ca510a10510e4b394a013a924b4f3ac7c81131324e5f9a19f71a54cf21f32b3684198109614a821a64810d4b3f51d8f0236a9229d6a45946305043cce95504758be6f42a96a810ead6fd0aabf21d750b9f7a9e858939d893c8a287f9d5ed90af15af78c8908183cc1c53639ec30eef2f3e3b9e1738ec9171efb4eb91483e3e3e5906fe96c45cb00936fc8cc8b8f7fa987f9311f342c65dbdf064c8b8d504de9501c4f3bc4b4faaea63645cc8cc3270a8ba0abfa086977e660e256a167d9659eb792ffd645ac2aa64fad3176c48899e647a1659eca9490e4b44ac1dfaee48b73050b72e926ea992744a54aa7b5ef530456a909e1e3548dffd74abcef01a455818b7301e66d9c27868b385f1d0cbb6e63162c488f18f68d6a8818303827f871fd10adfdcdcfcc6c6c6c6e6f562491aa4ac16ac16ac875966bd45e865196478b90c29542a43a58e3ad62463493025ddfa4e8f05614bbac5e2f49810660436d4ad99531a704e4f8b649cae4e4fe9e951b7644e4fa974ebc55d4e4fab742be6f4d44ab7569cbe868bef455def769506b76f1ad772b78de399f9e6e2c5757a8b8991b192616f5155c6558f9d4e579587735df61e0ccf7a55e64aafe46dfe98fbfc7617b7911adc2eb76bb7a16870fbcceda406b7eda806b76fc7b9b4c1ed322ed7e0b65de67a0d6e7f71651adcee72dfe0f6984bd3e0f615176c70bb6e5863c695c9e147147e59323d0db73659f9d4a34c2fc30d5741999e75c38a25af88323d78c32b49a6b7b9e10a29d32699fee686323e99bee686d751a68f714399a04c0f43862883392c11adb0d7cfdb6d930675ab052f11a24674ab3b3d1da24ca893d93f844166b63fc5e86c0fe3d79d57f7794fb744b2e9b1d3e918b7479e82cc6cba89e6d2d5c1d4e11c388e520a234610434130c9d3de1e22154986711be3f6c86c0fe3da4d07196b73f0d9b26ce1416fc088ee96bfb88c8bf39afbe22e6ecc47827af468b05b540619677dfa348bcae4f91c7afcc0ead0e3c2c1e88736caf33670a862e7431b3a387c466464be615cdc899f114aba157e4d3e27dd5271faaf49b764ee0c5cc933394ac90012f269de36ee5322d3875d8e9f51a6df0f228bfa5414e42845035632cde14784a45b619cf215752ba44872928fa85b518a0684724b7e5032fd76cd3927eb2175c921cd252ec619e33168f88c83378c3fc860d6ed30efe21f936eb938fd37d42d23ba35bf23ad8737683ca491e74d9e3579aac833d5e5f91a73668dcfd36843ce270e8d348833c5ce879f914c7ff077a4c68d0dc6c0618ce7dc186fc0631d0fdf924f23f0e05b38ac019e060e71c09f7008822fe1f0e04d20485fea72cc70f0dbc671b2d361732b3b1d37bf3eeff51837a439c661dc506618353d58b63536c60dd219c675e60c183766179786196ef843fc418671f0373787cd2d789b4a833587716b3eafcdb5b8a168b0a66b5ef3979a979a979ac7ae795026841a42fd23aa39575373164737f28a2c50aa7f52ed936bde354f3d76cd91b29aae99d7c8ab6955cd55355e8d57e3d5dc036340107ccc3f23dfcf916ec55894e7d7f1302969b2853caf797d53e20dbdf06764f319a828a844cc36b54dcd32856844000100008314003028140c874462b158309e69d2543e14800d91a248704a1989a32488610819438c210018002300200003341306051442324d2529f5a03d4141d6bfd085c24feb17205815f2f86d88b218d8a7f87d6eeaa810bb0b1cf62256b06f8e7534a14f9651345c80221daba6628bae4d2f4c7e177d161227903856dc0a6e8fb6c724ea61f9e45ed960380ee090734fd2761ba4cb08049ac8167c2fa9e85eebc52e0b8fdc1f42d6e666a4d578f6b045c259292ba4afd95a860ba4962c49a9386a11ab059fe0e1a386d8441bb20995dbb219c4c58444998caea7bf8ff5f4f1d6266ee152e68280b42d10085483e70b99cefc4863ba1fa04bb67e6faff2e9542feb242b9031d8040a0a0cac5771d37fa44641db6e35791d8ea1b750da77ee5a1fdb6ffb1071d45b4dc5e0c0a5ae390aad21be9f82bcefd726b298ce9bcacbec478b4630f63312ea68d0eeea914e0ae743b571a788cc6c4d329a2fbd955ef7ce26a1098d0903a95bcf0b78ae82998d0aefaeece040cdc5eeb1d0979db9f831bfb47cb0b82bec77101c5c117d4e1818a8611d640f44b1db59b09522da5b61d128f15417ca33a7a622f0a58cfebf8688d202550eee0e7c05325b7395bf2bababa87a5a755ddf51e5f43904e738e12252ec9236980fd4131afe635e6e2f8b0cb07c3ea5b409bb3d4cccf3cb4b50c09e9e40db524da6018f0fe36bec5c2c6e96cc23ae3f06d661fa1b581716f14d7db95d40092f90bae277759789cad0b7c61b5c4effff3c5fe8e6190fc606cdf4821e727145c41c727201a872bada08e42ae7df22786d3ff0117bbe0197068f1ed71009d02d85eae0cb75ce53e50a3f02b29e6a176e54a7dc82d89c40fa1bb66a01f481ade033847e70b2c7d6ec18b14a1fcec61d062a9e81ab4e9afcc16b695dbd7518acc0ffedffccd77b5ab466592761b8984749299fd38e1c5d57ea7086d846765f2b8cf785fbce061b9f212b879874b66ff11ccec484f019362a0cf0eb21eb8488cdff5af8cc8a2cc3c0cf1f9e59bfc8cbf5ebfea59bb37cc22a10519e142b269fe917d1a3a302cdbb353568866a29d73dcc46e42059b2dc99ab4b54dfa5ad483d4df98472baa2dc094956605801701ebfa6a87e8cd0f75b298ce4b0a6823104ab27da3b866573f41759444a10d073db9e3492443245b9710f9986f63623f9e4a43b1b29966de2160f848448004ab95bf7abc6261215bb6f63b4fcaca52887132b09ab4d7161751b38425d54a044b8c6e484d527b6f1bc48807c0737740b981ae48c974e780214c267e6c301440a1d0a54dbdb839c28ffdfa7d6965060450c4bccd1e16ecd4396143c5ccc8981b2ed78b3b059b4de3bbf6151f608f3e072378604fcf137db8c92134c880a4af91d17afef3b46654d1c5deebbf7f79c8058743a29f112101c5fd756c55c1f1198a8d1483579c9c118b59310b16d387f0f2b8f2715b0b1ba99d1f0374d44f9331e52cdf155dcfa7ec08064eb544b4ef65d8b03037230c1f1184e3a56c0c1909983bbfbe24619afd8e0d796bb521d80ac70aab170de6dc245b95e8135e2aa2d0f5c83e08c2104413cc844a5ce2a1112c9883251c1b24b4f692bdd88809519f194d74a15b7a88146b02c83a63e38e78fad02e26779a1973da7a2925001c6026229db7f793d14b13039e49500d9b0f2681bc22951444be28520c93bfa668d9d39b081e8cb5e3edf7d7d488331953d40f059158095581542c3ebc940f4fbe56c5183016e1eaedc83fcf0aa752e44179e3051827de2c5268f8319f430b85a5f495a87c797e52c87ef8936d14cbd259e41575cff905b9f2b1d1c336382ff0c701bd06cd309de0edd243187ad0c12759e327f8c92b1d840b5726caf13e24e174dc15f140d8893cca7dc3dc5977154bd128d25066b2ad5d12993047e195bb6fc34ae6125d9b878529c7a49e137641745d4c34a66f11309d9bed703e348c777619cc2716ba73eb43152c24d82b8f613e6ea450e6fcbaedf27ba3e9d6ab05ad6772786e5620b981aae3c8f20a0a091a78892da34f5a2868bea3a4139a74dc17846c048ed067968c470641c482be8313eda016fbbd92f273c21ac3a1c8fdbc1e2db5fcb0403d6bfed45f57a561ac687eb92d4be748ce4745572b2b775257f49691d840e0378091118f60bfb8ac398902fcf6129ab453dd725655559d55cb7c426e4f76eb41f41e718bdebc89664ba2a68e778ae9d280c7f12f375e1bdbfee0f8cbe5b2573cf98f6d886bf3b823d5741e52800f495b86f16b021ababf39e58b245e1a71ecd937e9fd5cc7ec59f3f6b33b38c31636c15a7ddbd27f40cc960a7a0954441616f52e2449d3c663e64080e560d54b2d6cc76c7c081363977e84fb977059573d661f4c01a8168f73e2793728b63d81c637941bdde0603aa1d1083039223d71cf3820c49e294712463feecf5233dc3c8433cb0a5b7dfa4b5e58dc7b753c267256e6260660383bae545f5bf77a470fa8ed589be5c1fe4a7cfc0c3c962925be1ba79e46a59989f15978e4bb04604096081e51f3c4caacd98f368adbb7e02cccc736d65d5b08abca2288d8b0901b98cfd400056f193d28c35068ccbfd17644137727453e4842015914b4132f6812d21b25108168928fe0c4e9c830ded22db6bf43ff9758ede9fff3f28928d658256d9bd864eced434bbd77a35fe76e6562b67836f9f16df6bbb881dc55eeb9f06d1129c1d98ae1d5054e9e436e6e4566b51f12d5e86fa051a6db7bf98ce859d042d39083c31afe807b8ec4c429887541f5ad329a9c29dac059d06e3e673986c47001da3574da40cb6ae618994eedff8217cea5b7313778b709c54d4281daed036fa04ec48a7914b3cdee0658e5f3809b28bf433c0e1584003df4e46143e21c21f1352d0119976755a026ff4b7ba1c1be2c9693a14a13063cee3b3f30979fa05082d12de61424242e5c94ae3acabd67c1c6708e40ccc0604e1cbe372584d3d56e469c26d27945d05eb3ee617e88b31c05d1b47b7c84caa8a687de0a54f9a6e5dc3000358f506ea2e9571cf0141ace6d44c627b03245aa3d68445520b3b99ebbc7666bce7bd6b48d4f34c6bf3c5483dbe76d4d16b5b64500ff809355a5720d2b189378b21e32fe9fe511d7b6e29ce57882786956d4292e8cd79d54a54a3f78b6b291ff68b1c617d6040244626220b60a54df3e9b74c70a734ea7fe8c5917ef34afbd0687dbd3dcc5c514d798c4d2e5e9e611b0ffe6d2cc621bc244fe5d2c0f240a153cb1a5cd12940b6a5dd5ff91e4329b4a18552645ae83a9782a815c5ca69c9ac2868e74c6534386e916b3135aaf1dd453b25fa0cf7a9c4fb0d2f067fee8c24186b9e5e34b157a3fd4f64cbfc44fc5a305c9c120a14f189e46c7098b68c54ab08e9aef7f3ae39c689628a4c4217bca2b400914845c116e4107f9c6cd008903b695b62f8a5e2351eddf92c7718bd95481b40688cb8d20be12ee6ff008431d52ef3b3d4e627aa2b44296412be98889c3d6ceae9be866c54d500ce3be628977a88b1b0b553a56bc521cb0dbba8b866aff2a954224f4270222e631ebc3535f440b0f8d48b61ab3cad14fd5f2f745e3514d9b8212b9187bfd239a4986878af75d33e22a87a2e45944f7d08814da294eb74c9e940660564cd987c3678f20fc5260a8c0784720c91425364ca5f8978b9e59be3a7c3a2f6b319a778580c97a330e4c7eb92987e9ceedc92c892611bd0984fb8074a8ad32ab7b1781d2c50698c9eeefbd505274ab2fa98de0ab7c77c92e56ca84ded12f88770bc3b485603a76ddf11a5585e55f5f6bbf1bd4749165ca9af03a8de4413e6121827aa9c02e14cdb245b8bb2d2c1a6792fdd5a6bd1815635b3e7b8c11df46ab230814e98f4486895b192a4ac4c67ed31901a11e34a0f1acd88022e04274bcd8039f711265e469bdf6920abc8641a83504aff20124709b1a9b91b9a71edb10648c433181159c808ccc8e3db81311b69ad5bc3bbb9d5fb766f56b4a3de663536bd32dd05264cb84947ac017df3764bd942c9a5980e5eeb4c19601b98f1a19d4e200442c2c43e09912316a326e2985c956314660e925263a874057828532ffecae2399a06c328b02529a9e3cd86dc70755adc8e5c0c94ff385f3d62d7496f1d7f6ee19350082d88f4ae64f69e15d1572d5038276430e5531e4ca274fb8d64164fdf0638ac2e3b2228e70624f1474dd5b1ea046a5f604892744e5b5c81c222be5abee25d206487f4b5c86d26f2401bee494189e7ea5ca5c1a69cda0401606db481e62829e6d7ea6fcb1810391bb3b64564fbb6b47cfe36bbf327da2d78309fff4ecaec67abb99516142c825b9672d93229bf8a42660f6b029631fdb23aaf0e688d00145822074424adb40a5802e5fa95f3daebaf609a656838a56686c66d2df317331b4dd2c2496d75a5a79ed49c12ccff0e50b95b9382a89c9cd8d791c74cc115a967f4a252294daefdfd8fbf22deb57ab1fc609bbe307e9731a338bf595dbb9ce00420798f30fb277c463adb968b69941c07ddafa179edec3dc3740ebe9576a46a2b9c6262e5cd8548292dc66b9ea1f92f3d82195ccef3ca78002c3bc878fc6724cd0011724a1cb9035bee7c878badfdf235b7a6b68db832b201c36082c78457d2c3d7c4804ee5bc50d1029bc9313c0149d85cb685849ab3513fa2d98c861fe9c1fb290053add6e44efa002b31e2602faa5aec44b53f916fd9fb6aeb2fa9f199368b681ce3874666ad2bf1ee5007c1aef4a4d7af34c7d246d3555b9937cdf4207eff95ffa9a537e1b1daf557f2cf354a0e487cbee9c651ec5080459f2a2908496ac6b2779b83d65c9d49cd814c2df54040c72cdc9398d1e981dc2fc6a1de6956bf3353637befa80f5a56f48d7add5bb54ab6343a691c5e52f9490ad78a42b4330303ce6492848b42a4418c6e4ac4a10bad2d61c5af11369b482d6d305a541e6df8deb82ff2b6fc95fc7cf86b73c87103eca27df1b145db7aeef917b13a0c1e9b3bcf9be4577613fda3a96992e74de45a415bd5aecdfc38f836bbf975fa1bc49a01482bfa4b7bf78fdc056b094d6575d3f6d608fc51af88be5dc24a123377d5a6ad71fb71cc055819581db2ab37702b8008de6711a13e13a37a843ff5e14bbbb213deeeae090191c2e179198e65b03075041474f14f73ff3b939185019a28de657f40f2a2df9d5f1d918dd077ef865117513f07c37a220c5d9441ba008b51237b868ec0351b49078219b2222d452eeaf1697b6ef46232667592ed5255441e137e719dfcf32cd0d107cadf49948ebec58473290d163db267fa6d8ae19ba334751edcfdf62a96c9447bbd371edb15f7df5567b6eb0ad3e6093408d30b7a42293aa9a8588e3b7f6841be5603e324f298177cb1d9872d5b4dd9abf38d5004ffab4a45d0004ab11502125a97065f7aabec7ca8d2686197770370d459297bf28b53d4ecfe4a7d0b049f3ab5553b9c0798d7c4d21476b166aefb22337fc75393391f009b1078f415f0d7d85acd9c1ac8a0042f8a0b4b79cab3313d6f95babf684173c5314422b4adfb17607b044373d9397c0e4f178f0389578f3c3b1782a840ca5de7d2e5f05b6a245c4c80766cf4a9eecf332cc3adb8e3560a1d33cad477edc60ef27a58c1eb6d02bb0c43dce7b700c2af48be4915e481b3ad61b42add8af9cf1c46fa8325829d112050d6dbb61e0804688a9938072db33c15014edbb9f14788d1c9277cc0811c28c90d0687b77fe90c65044e823d0406d0e72bbb6a8fe04d5a1be4779d443c1e7cc6df0cbeaaae75162c12a2ea7a1c53a192c83f8c5217c631f51d5d25afe05f3206d36fb139eac943a29554468ac6dce920b03d27e69a3f0c07f7fd68faf669c5c1abc522421e29946511ac7763571666ef2305732045658ad4fcca0337b3745890a8c66a3feacb399414776883e48f7024f3f98b04055666df5e25ab68f8799603f2f9d8448b70073ee942b1901da82a1cca2f203461aa40fe6227b2ed4463f885009e4ef90758fa70e8a2a430078630039e6185553b8c509ea8c13150e9a08e586c4c30b24c60a43db32378dd9915eead39034100c0d1b15e7986110ce3d96aaf2f1761e257f490a9d65073be79ee72b5f678a40f980435d557a8614846c2924d47268084452eef28e76984fe72572f36f46f118fce5d5affba092952c563206f1b921c9f0b93ee68cdc73943914d6c408c3d01791c02e4137c1a00e586d63f28c434e526525c21a175c1bcd295301429d3e7ab7571f83c37a86c792010a1050f6084f00e07c1f31eaf3de435a47cad19bf8f89210949b3d01f57e3bdf9370f03d47bc1057574168ad043e727e9cc9c36bd7672a8d931d4ec2c06f84f7a5d90fce59f3c641a3d28e351534afefb74b2b24b31619534677784ee9bab47cf31e28cc538c6ec434ebabf3718f9776346ddf50dbbb31c1801adc872111f9ad1c58cb20f4a03b5066a95cd132487a132f49086f1a7f61e2ed9099809e30b77a1d84d6295a9b5ebef13a5b6f67e651e5f006b14612c3760d82af3e4903c821d42e340d9e8b751869885c598a82e03b1edc0bbfdf027e9ae074fb5b53e560747c3d6221bed4e07b4ace374bf2643cd0c15b50ec7a1785d22d6a442137b8be17e2ec5969c210bd6b76fb2ebb490f3c4ba21789cd2a58ef6ded3d808826806e05bf44ef7167093f07ca361bcd090184cf01ea964bac1222ff956d2a071544692259d2200ba8c37d74be9825c061c2f40c0f7016d85a3cdf41ecc46df249708921388aa76dc4ad673486aabb5f98a3fa94648902650cfa0805b3cb56eace43464adc299e49f311704b3842680885710244b39188a467480c69d2ec85075d449128ac7b2a8470dffe13580689be15a81be067aeb140d77765f506458ea23980d79c4e1263ba59954bb42735965f223944b8ddb0d01933bd97e41ab6336ba012d75cbbab16d07497d4aeb2c1924d42880c906e74a3540ee5f4df74acf60011a3160f74799064eac6ea7d9e6b086ef96f33a50975904d2824ec90bf7115d4fda1d7b2186ccbf35103ef4b5156f796712f0b1eea9197d1c23aea7477839b24b4df434e04462ecd4701faf2e1162ece7b4e096715543f27e66c2d09293e465d3062cb0d703696e55ef240e68c5165be38c874bbef8777d7c7080961d9ff6eef19d23d1399c58aeb412761aa72a6b357d8aa915e2b68dff9ffe5b0c9a6edffecd3097f15d35632f2881970116415debb464c6aa4663d5bff3fcc42d89e5feb8ce1268911b46322198e1a92e946141c646141d882d0e7d01fa48b07087fac86c9725c3f37cfd3cf93beba502c432d6d2a48b3070cc79bf5e3385bc0d5c49e9d96764990e112f256ebc4ec41f83ddd919bc1e494b164ee600e371971418c1791d81e071dd84d60bf80f2b0d52c990ddb4e52218f408a3a551257efa6c80632674612b643d2d2ec3215901c06e38bbb0092215aa1f02f84704900b5714cc54982f4a4a5c58016e2429a5cbc47727460e25434aeb24872f43fbcf1804181fe4616fd5ba8c7c6cf006d11ad28e2f4f0d43930cd8c95629933000386a64ba78baab6d5e37bbe79e1e872c414e0ae62327447430dc9c69a2505474a5c4105833ae35cddf3f48bc9e9598974f1ea2a4a7d79f2b0a344739dffafb3dd055cc929dad6f77ed567c0bfe629177519414df031935990f68d8c114202d6fc4ddc089cbc293ea2e77f13224a300adb6d1a6a719a0af81e192edac2b5a7ae0d49d0082cfc7db4daf688d35ec4cfe82bdc2065267ec46ee6aa554e3d9479aeee4d7e14ee837143835186adec45b21c1dc67313b69cb593ce101ef8f4ee5844fc180187dc6d6e3804348f46cc05bdc010e91dc3996ef62a96f5ab29d14ab1faf66f7478446bddccfb7f8314aca3498e3f42455cd2a2548011554895dcc67c585d33d7e6abf6a5958e94324a2f51762567c8174feec5f086534754b8c8e052f217f0eafb91354e62280e9c8ee68709cfd5b4eab54642e18ad4ef3214668df318a717aba74f79ca6c124dcda35d1902e52aa06f75aacf6544a4bb025d2768ee6f13f0423565383f480769da6da34dc6e0d49f85224e48fe44bbaf12d2693e86d3836676521ae98bb82e1a390a375f9a0b67765a120ec2fa5104675950aa516b86355bb60fc2e2ca7024f1f761462790d0426d391c3eb54263e4ba2abac71cf881a16414636ee4cf065c8db2b74e41a12faea783063d8a6315635be7bcaef91dcb8ffb9ba1066f30b4b99e38e25c1e93ef2f0a31a012d70d845c1c476fd9a8e2cb2c0155d2252c7e8317490719086997218c318f2cbc93144ca6fe562e0a80c60fcc9542433ca92d0490c300f0aca5ae0123c2c5e54c912d8065d7a29b0575be79a88db48661bc21559014f8d4fb7afe5c36bb700b7ffed900099c05ef433b1d2bc59520ac227feb31a5b1b94ac68abd59c8ee6b3c396a4ae4dbdd1a8d505b0d81216d90832b1c9f06d490e8931bbce4aeadb0ee3dc55f35ac3258bd4873b4db3185ce94b1e6be166373f9f9609c111f9282d7bc34f2118c67087fef11a4c057db783ad70d8071d8b6a1400bcf84d92f78ea3686ce9b89a47f84452e19a92d24be2efaf70fffcb7f3ff98c96276acc6738f5452e1b2572214be7366722338117d8c7e4ebda5660e68c94f25d751b893dc11c128570db2fb0c2538773e7328b23258bf1bbea35c48acb2aea1892fad2d7f965c08bbd1bf5403996bfc45cac5700b1514d2a07616753f80ac751b018462e77604d2fbede8cd692ada860ff8046ef4660255a5b0ddfccab48d6056110a264aef6afb1b20c66cd8492f5c64d9a414dcce7212a67ed3932a45b07b0c0428bd718e5b12bdbecc2c58f42d8b8e80fcfb02ebd8ef01e14bd0353d1c724c04d1de49eaed2c30cd466529b427ee0d60ab4b9e9bfa83ff4176c1ec8bee55390dd23e9991a8607b159cc4eb3909f2bb6bcd4811d1cfd6413f91e2a714416b4544ffa28f2984ceba456e51c188342421d9b2918bc3d9b8236141c70922f6c8fd93bb7befe3e68f70a2d2e6fdddabbefffd434c553941333b9078ec1a46f4c0aec2fea547ff2016d66483fbdf0f280cc92e20d2c58ee8861e3acb674193f98af162aab28d7d64c91aa57286e07bcab666c449378957aa4be7ab351cf3aedfa527d2ff3afff7831696ef46a158933ab6a31208717129c9b428a7a8b991586bb399cfbbbcd30146fe9102e09aeaa85afad8e719bb7836c970513854028377216ef8fd3da54114457842d779d7007eb60fe2389e87811bbdf3a459c2be52e922123adff4aad6f6c183da2bc280c2dc020ae186414600b9c1721861aae1abe2dae14cd8b662cc6e38345c3d08ae5d26e0e182a79b556c6446fb451fc2aa3d018390a79606651f05c88015c027631119da87d25cd8a7501964ee4d8f822535f4718f8ee5ba224ca74c5073dd796b970df9e7a6419a1cd0ac8a4d0e5ff9ead7064775e2611174cd792eac626bfac01d04c9bf09c3cf32cf6578a4980f50675c244840fa192183018732785df09e51d5027e77dae6c5b8ce1d87a19e05e400ecb537fd2d99f16b3d8209d29aacc85342c6b87b49bc78f059d23d7cea8df64869fd56ff94483ca0bcb3690ab9f03dfba151cdd931f4d025f4cb4c75b69e153bc4a04964da3244eae6b55d061e360bfd325330d428a7fb7d42f48830c59426a2ee701f272e372acc59b37f612bbdf0efc76d642d2b6d9c38a8f4ae13fed5f4169bfdae1313955ee3b9ec67e4c94ecd27d50b97331fcf0b5ea965154ca727c946682a211711f26939f4759800da59a5fac6e8c83f1c44d4d2688983f857a0b1f10512a60e3476ee2e81ab3f7d0c7d9638af79f077fc00aba966c074634ee0ae48e596c1293b1c12d8c9b95594672a553e44c1448e0c21bff1faa90f33fb6f951da96913a39c54d292129664f3dc8cfbaa36ab013fc534466c3ad2ec581b01f7f62581a991ed2bf198c0cdcc67190a1d4dc2446ee272901541d8712c23f760a102762b19d19847f79b9a49abd3a1068eb1171c132d6c3d30eecb83c1e99cb8cf989e576161bafae44f89ee4b61dc8a1456248dc29c395118a045d5239dbb0d1a885f1259154fdc20e96a016305f697cee40103854035179b1a14fdc7c28d55a5630bc7a636d6e8beb1e3eee001cbe020691b1b8ed99875d51a53c056634de439e4622d2027acb3ff60db00e2cbe286258c78853547be5063011df575bd62a8218cfab92848bbf83a52f619caa18c299f468c6c078b474ff02a435591bc54c26fe8e9d91151c304ec69d2c2c0af270edd533fe507ccfa52d7ab385f1731dcb5b42668b861ab3accafc7499c6266b5cbb7f88219d83de0681628e26ba2ca4b9a03ce28efadf7973e5ac8d0ad4e96e2d1a81700e0e46279eb730274986db55d3bc4a4e76a6cdbbc69b0405567270c80047326e1ffd3ffa9f59c3de7e7e5de0f0f79dfdaeb622b727d82baa3299bdd861233ea113977336363808ebda5e39cf475049f6177c0e08f1efccfab85951e4e9283acccf1f1940991cf7e39b885a3957480a9bd01ce33695ae5ae381a4a8661e754b8c8a3e84e465b16f3a007e966193eb8981128f4267554dc7bb8ed17bffd8cb745f115e623d002985c007568af4562bbb5f52e27f47e9ce990600e0ef8026995fc01c54f533d7e3db317d4f9dec83aa20da6d2700298bdc5c5bc4d34d0b44809d143df053496dafce0101b964ac99feed07600dcab099d49e4fe345e73cc1f293bc456cf69e80ac804f22b2e3fe428bc9cf48aa651569722a50a8ee5821dc51418661378a29dc8cab95cdf8c44cdb5a41e0bed9fd9a396b37e0f4d20ffa820d72a04e2401ff642369d6303a009c966a2f9348e0b1a5fbbe5369843af82282556183a96f07c9ecbb81a6cc42f5aa79742dac030b0004fc75f1fe1ac2c48b2f14d839d57e174fd5f892faffe90b8b4e3d3d192dc8d86a8e2ae29100f6e53466dbb971fb21e084b69dd28c7aa4c6d23c79278ca0df80958800094c534cccd45817b95012b81a5216ad821c825dfd0b89bf1ff090a01a8f9b5c09a1daae620bfa858f3ef441dbb9fad2ea8c381fa9f68552110f491833063f69db4d7e7f7f24bb69e407b21a354edbe4ce0dbba939570f380f8515852552c9ebe959511c98ec6d97a6c664cda46052f505deba4039a55f03b53d23d4ce81338024d2cca916164c39f3d9cc52288eb9bba4f8c931b9832e9d37a8f6875368679c6a62d2d713f44af0dc2294b17e5d1254ea99e0800ed6771007daaeef169015366ffabb9bfb3197d19e2e4b2cf561a471207e81d1264c1517325be5435f390fbd22d4e9ac9519868c2c9347534a3ec433118d704746866014cb09f3bbaaba976afb8f7174bed405f5734d81d773ef1baabc1e6267c2802d7e92e3b3c016d6ba4bbddd9c48a4a23c5f54e2640570dea6ef22752e59ae2b69389d5158d74d79d4f802e35a839d96902511f9b70d95016df4b2ec6ceb91b4c0a81175ff524bd4dd1654e8805fc940371ddeea7b94d2fdb718b37a23c7d1e7b4bb5814edd35f2ce3b3b615534ba5c767802a2ad9176bff38995358dc6612713a61b0dbd738727a28b1a9d9b9d2642f43518d73b4eb4ee35a6baedccc449030d6f2dbf8b1c896f6271af001098708394f71288800b3709382f81084cb871037d30096e78fec95dbb390004a2d12219790108fe2b7a521d19c491212a1c4226e6059463ad4b0d96c5d9114d408702a2a1f087db8b250477a77a8291f824a001af6cffd2fa5719984ae2c4e7617c8ef7c74d39f24369c2fcc10c7005c8ab92e7716d15bf5471eb38fc0ddfeef777c35f2e59f399377677c71247a87586e009a566ad1a530bea8d462aae20c474f89282e01f3e9a59023276484495f983cf8f487dbd26010245b6fad0832eb6c299a222ca8efdc4211dd913d5aebd1f2caa2254c0a0dbb6581c506895833269756ed542d9b105666f4ac77a243d26f90a5b28c993cb15b702f048f35db95112a41b057782ad53bcc77f25e8bc699a4ef17ee6ae39e81825f8f5374a017a737546954c93604ca6b9674865f2136379e4321c1ca09ec080623b67f7219b77b1bddd31490031acd0c93c07d4bde86d4a5af3fd299d84c49e34db09d0902b30575fabacfb20e8cd142c511104e7969cc2201ae4f3b6c9ebcc549e23f4b5d00801bfb4d2a22c74141c13219a3bdb5246663c331b268ab6109579124aeab7dbf7ab8dad204517778e9082cb29a6d246fe951a4fb2090d3d2656f01bb5a21c64b6e74b75397b39b6124ad1bb2e1fe60700990c20665eeadef11f9fe18a8680183c8a4e4cb621f808d7f7bda68e8ee52601bc4445b8897a22baab32eb6c0200004b43f361863139f3f5a2c0460085f8220899ef4c19d82aa85dedf27c5653b5ab394000e6142cc406b3f2793b803f9dbb5dde00260c247252a5e18b7ea6b33c1340d6a33cce748a98130c1e10cc15af1b9a16ce664b2ab46c3bd745560d91a9233378acbc2e82b548e5e2f11fe103d382d4c2b568fe1cd20b9c8fffa06a6abf85d6ad98053c66bf9c3c956311087a1336407de85bce77e9bbc26e8643a4c65b72f4327ae438fa483045b22bdebacf3780b2ccf2d40763808b883a5817c1d625d90effc0383cc206d5331d3684df8c67708cfad403ae6f170195bb86e4509c2e336595aefe713c0a9391bbdbf3c6ebd670c70e3dcc2fbdc1a9e507bc083873d584efecbdd91bb3ee6a603e572255d9d657eb78f10848c1b2ca39c923c7f179c309a92e3e1fc8c3bdcc1e1ccb6bd9614a2f4014b48270008719aeb754b8ba8c4fd50c77751ddc2a80d8b7a8852132cc71339e87544fe4605e86b8912c13f7cb772298fef9815bf38f1596a3c50c9bf4da0cc6e06efa1735d165a3a14d1f10588f717ce9230cfe1161bdcaad9fe7668251800b3dd575e9380ee1c2cb1212090ceeccb51fd5ea9af1218918705a92e09cca6a47a6d89454492067e411607f5463402a7856a3df6af0d34695d681b9ef3f6a16961f6453270273997221e98f8e97d1c8a44942800b7e4108f76c6834246d19b0f2af7d4c0e0c4bd85b148c3f9b21f51dc5a19842bc5c79e38cf9283937616063a0bc5d925c12846ac4b2740ff762619c5388ed8a4b69b20998fdd83449531c7d95b0e4df5f34240d178c258909cd23fb2895e9f3013705aacc8014fa441086e197860705ea90a8ef6a587cc8f5828107480f766be0eed0d40a600fbbd02b8e041cf6b5858a4ac00c1cdee971383921d01308c762431556deec2ab437bc8cb10b95ce0e7a76967004f213d79f6cfa186cd277eda1cc3b961022ec82c15454c1bcc5d0d56b545da8492dc045f4f38ac620fcf0f79671974f49c2c9717fe4cc11f736f6229641fa2d0536d3014f82747e10d227a1c07ebb56b87ea1638d35150243333263bc2f74f19e127926f2b149f1c73808cf6fb62ae82b1511cd6e35c4f144f98cbd777b14eace01368048d5b36e83d245ee44270c8218bb143cb004031d9aadf6a0fc060c63aca5ad3477a8cad9da3580488af1634deeb8b137bf11a4c351432a37327e08ebd1b5719bd19539fbed201ea029b304418f4b1b71f0b2f779ee8cf5663c16361f98e7e92941d2dfc3b185eb74f12427ee8229ff427b6288f6049f76962289237ec8fe00ac55dd214b5c0ab353b9a484f743a298008492da90b008bcd2fddffd90c7f320ee9ac531273b2ee76438ecf349061404f98c353f837995887e12706c42e11dcc4596dbdf997249038527a4038cd230693cc700c215d39e847fc13d0530d10dc6e56b4b21ca3e920229c651f2b30347fdf9733c948fddacdefb268dd262dae275204dce7bae537a097b6b97e86fceaa0349b577cb3013d27697c692051ae09d9056401f5651003a77f0ee6e55de4e67dd2dce33df4e7858ed27ec08fd9963e7a06bb59b30a31866738bd7380371a5ef966eebad42e118c5311b8469dd97a20ce31a62dcbc2f85dd0bb3c065e19ac6b0f08fa13df7a0c3aaac64eaa5e721cb2951b3e20233e33b92ed0b9edb90caaf0b3eab43093c9976cfd9f17bcd0e0625124eee0b1fea577a610e8a5455d41be91c4cd52a7d52fb8f08e4003611522bc9ffec50e9214eaaff8fb0cb7e79a8bf8ac1e79d9e3edc8f480d57105ada8e50071fdbefc2b137270d1ce0d17f33e09338db73dca8839215365eeb7103f0139c3ae6688043de478de22e468020f96921f376c66dcc0ff53c35a627072853758761d274418384b438d8fd9e544fa9935172b40e6b22c4b0f1be05eb269dea79ac488be65ed9547b21d97b55c9dddd26dbcce7dbe4aa08863b74e6974b1802a954fddbd1f1f31f595140d233e952a4ca4db22f2fa255d17f6c41bf3a2851857bb1e3c3beec798026a5e24bec1454ca538f7adfcc0855738edf3a03e579840d8419df83bc4aa53961c604e453289e309dbea0952073beb191638fcf7a73b16c0130b002933e77c20c4d77f8e02e6bc656a36128ffc79a774723701b00fb4ba211f8678bec8ee495cf3f01926606163de01a02342f98ebdf3bef0a2663d3df3ff41af7fbf6f0229f5feea40c8957f9b0033b0a849fc8658c99c9264a14d43b81191cff2f81f6d0b38780438a6e2e3fa048a1009659b619ba2ba04ea23a647bf8a68aeb9c868807e1c3b68be58828c74bfb76d65c4df94727e465dcb75d844781969d7d804edc8a26e3b94cd7ff507f52ba3b155caff81e8a57462d5a6b35e9b1927ba1fec716d6281168e055ea19631d9ddabbee4e7ec9b350e1860882b3b2c75ccb74aa34883c2a255330553e65c3135496e0f305649b3b3ccded8907f95734bd6d1d19a28a02b3cb9f6162f1147ba3802623a2fcdbef11020eb2b33bc0e2529a2178f9ad1852f9999b457b9864a11cd2040893337092647536b926032599aaad978c18b407a14f8af2b8a2bfa09796bf92bfc84bd6998e230130139da2ce27d248bd65dec2520d7987f68f9cf12bbcd6b178a36fd712cee178247b2271216faabc932283234bf22fe7714fa96e807140df5280c3d2422812b63ce758c2c57fe014beac059d9a69bc59ea3f79f101d44eee9f7200f870dc9575aeb1994367d3b1a9cfefa46318cfae897e5a7f681b370e0b2752c47d5ac62fea96d31e49ed371414e59249c86baef0f0ab2bb6bf78b7aece22d26a55c869e22cc88ef966b0bdca418bcd262d22af5ea19fdd81bda200f6005a3c2d6192c6e6ec4e2b51843639ff5fcc66e5726228caaa6662b0a00360b121b8f3f9f6131e8b350e879d1bd88efea14f78dcf9f94992f9b42b7200e20427128f3e2e4c313214c62250a4588877ae2dd8ecc1a9f3e7970d02807fae7b48cb7325cfe6ce15b8a13651ce9246d823893de86d9f6fe8f3d66dbba876090e61df35052bdcb8165e5e01a23921affdb95f833ef76e1593585ff14d30168fa0ec26be48b1b8169cf74be2d0e638435fb75ab2a8fb9a01429c252cd29edaa9eff01a7bf92a85ee3b35cc45d8200cdc895c1d67d51abf197f9b629820deda5e3d6a85436639ff7c69b9a83d0e37b455e8afe95486efb456a3162e076eb575732369667e293ab8db37a59abe186a1ac0899c8a61ff7093ecbe15503b0f359bf99f0f06598521fb808b14a277a1e418235744148c8919a6f49b5ea815582958080d3a8be58dc4d73718a380586dfbe52a01bec9e303094aa90b1f42e4363de5d3037bdc2e374db2e3ae6672bae7606ba420687556263937cc250bc9e2350cfdef426d022a3d9fb8bbe431370852dd2a05e3152c6b23825c2db10ca2aa3e17e7eeb1cc965607fdbce9c0d5047392bd8fc430ccea47ea422d3e1824ade0d4408487544513e4a64c16a30a7d22ddf7602d99e830bc9c1df223d28cfdc3fe11e43e9d4d5043db58693b447be4bcb2fa86fd081029e4ac03cf433d29994148a34dbbbe30f5a9836bd945907686e466f41f416a8d60ae7b9b2c5549ee147045a27f1743a1ca770900a8624fbacbf69b8217c01eac04cc8e2a7ee250d874be5bb34cb99aa80e84dae046ab5db8311332b87a64f3f49aeffcf1db53d007772b29fd251c45206b700138d0f8abf7c1e784887a09374ac80d821a829efe5e6198b78ea3df1aac62fbf7918cf597b99e97a3dfb0555376b76806ee2ee8e59dc295957c05b72de3abe036ede9d9799e4d47833c6b9daeeb5e09e867b4fe6c8d4144d228a2673ab317263a8292e0479f02179152cf31f58854ca0ee1c4a9dab4744f07079217d5486e5b108c5cf40d340de47754bc646dcd1c762bbd84425d171d58e92483134f7649dd749c202595e3efc6e8b2574b34ff12a6f2a9204f6e7f4dd0c2781d74051f7b3badab8526858e344ba074f970b3dc1474e3c82d7f4a7eecfce0935b459307b59ed4860a575dedfd8906e07845ce43e49ab454b2d9d2cf52cdc3189f1e301aec90a841322f7b671dcc7d52a55d138033a5bc06796940df12fd316a8700676906e27dd28ab9d558211e9448ffe4a099cd97c44fd49ab176a0d170077c4fdb0091b2f1e7c5491b48ef4a731c0808825edf1cd46c74a86f48d5c428e48a7c82adeb37143f431d8c6d335ee3d71c2c88b9c52dd240e96f94b700f302847b4d2728e209f2366a4afb494bac16d2a64a8fb64ad44d390cdb9e380d3366217852c8849c931ef4de8e581b0577ff2e2c9d651d37b242f0d65937f6c03317a56b356a75fc681c618b0007fc624176d61a3c5845c272399d76d6d6b82c11990e78f3cfe2a66906465601e67f32e177f542b85ca2c8f80562467eab17b43f90ee1b87c0b977b0695680272c487ed272c548bcaed58caa5c1589db6dc08fa5cc96694d541af6dd91cf6f0235bc79eb7eb0e9912e4e2acabba8a54b9f1792940af21dfb636dd8b107bfd441b4f9cd2e6b9b50bb1467b5edc565d4f0c1200a40bbf4765301693c4a5a3e2c23fde6984be1336e3c2ebf9f91adb38520deb89998a00c851e2e6f82a28c8bb30d0558b940dffbae29159cfb3503fae021af0ef6f3007dee02dabcc229b6e080d24572325850488bb2db15126cbe8cebdd1c64e78be3dcbb7896915da5a2ce9e622561d33c810a5da0df9c541be9b5fc180f07efd2be91f0cf1d7a0334eb658ba92ce85b9a9a78d9e179121019ed66aa43ad14d49da3fe8a27714a9a1d65c84245272d275dab5cf9e66cace5d9e1c3bf568d120e0d876caa813a9c1f86cefcf2ecb2d30d930435040e1dcb525dd2b3faee1a838a1770eb13103c4bea1685a926a21bbe9efc1be640c7f8c3537fd87d312a9663e8be4fca1535d6895e7ef857f5923b48e0c52680c932f033f7c77e2f418cd61dd535392c3ff236734ca26c6d957d9e8a5129a1424eed061bef446c0858635b26a06d862a821489d78a972b628fe348aa38548b00d2794ce7fe69f3900439e1f80bbd45342ed23769d77c7685b56408e37f46b739a8610d746df9f40e1d09eb3501efd4548dbbd7a22dbff38beaf0091394c3c3f5de4c30c3c1b1863d219b055d1aa6459d94a05dfdbecfd33952d2ae3e5b3b3f2feb22e1d9aacd626c10c0c1278acd8a1a7abe7903414b2ce648a251352322e29cbd9c185ccaa90e422b57c46455efd8964db7ca0be000cd7f703dd2de37c00cfac9db3e72c33227b6f628d2595ba56c71704f07d1e5e7b2281b0c76a072723c2c933ac27fc700478231ac3454f4d8ae0f580e01c72165a9284daf0c907e40170443c45b2c518921e3c736cdf4800ec390967553abf9f105bdaf5f6ab48c298f63e77d06edf26e6d768af04473cb37f8d28a1aa7a511683bdb059867280bac063f288f011efdec39e453246dcca27590043484f87d161566f43ce9c1ec12521d46b63b027c14c4ef6dde139130cd1c2c6d08d228319c40235569e7c53525b086982626ba8fb50ce30e9b022f3ea4a133c1207cb397f4dfe660dc53ef4658e6467938eb02a6fa7ba65331cbf7668f0177d62510027d668e25b4154c078b99b565d6f21d94248c1177216d6fff8833529fda106b0f275041164eefe1a7f9d88125ca6506908f4832adde7382561548118f8304d0f510ff2a9b676653f540f49587b8b5a0b641bebf876a36124d247d30253c2598440013844f2582aa12c871b595d8004300d5e5cb3d461bd9408b8910d5c22815f4f5a12593f2fa2179fee57ae43f616ccff3e619754dfa32d734fce9cc301a083f9c0a81edc050a9bb5fbc9b59399275603b2f2aabe114b2a76feba2bd6f7b8cc89554fac89fcaf88e85e96f618fdd9c138833cf908e57cf90964325c761fd3fef8fa131195a9e27895585ab1e13e6906b2af28dc4bffe5160f883d3091fd8b924119ee0708a5b852f8586b19377a3296853079e7f84754bf03552fb9549363bdd055533f0383e635b113cf95a238813d82c1ec886fc422c973b5666c2b950acb3381dafd8af4f6f62649035314149b01be5b3694bdb2439fbe6c0845ed4b61b47873c7133253d1f447a9ebf1a762c18b0c16f7c7b2f4ba1caf653a49e9c181dda0c2804496df2784bb39020b2372cf0445b60ab7488d6c62880f34121b5e682330d7cf50dbd78244f8f3837706911ee7291225b00f875908a1fa43478e943f198354da73c1f477f69c264ba2860026a980c693fc617e424481acd443d1f935d57b15b7b78f7f70262f450ea75febb85b1e0343cac564cebe3c8245998da5a1f4751f5600dbbaf438ae8ef44c3a62dc71255c2bff0a9206301f9524e4a9037ce3ff6e3e9acbf4fe248bef13ded14a57417ae857101bcb7ceda00301312ed2a1c40b25deb25adaf9c982c1ca043ce2e669beb3e2c40fe91e01d75c3ab6e2aacf782b1935d71e7b5c3d54e7b93b477c50d7eeee1f58f4c2338b24fb894ce4faa653b3bb0aa68d3b34e78844f85df13cef7238b9317eb97a61fa1f617306109450d834a974ec640222f923cb01f3fc2ad00da6e7575ca04677756d32e6f5fc2969dabce614c76b6c0c6657e0b4d3ae2ebcfa33c17a0a0bc7ed7dd865e8c1e53d787006559f1d5b6db263fd9454fe2f05c10e34ab8ae7ddc6fc5fb6b7c4c333c31be7a6da80bb8827d119854daadfd068f6b452963e487935e6ecd58d040286225e8b0be93a7cf386bef4f80a743957354be1e748829ed8d60a677e36ee5e87334dca6a11c3fc79e0139613d53a74f9307be1bfc911fe8637bec4ca70721258df23a9c7f9e0995336360ed46fa90809e5b3541d67c22759eb2f108c5cc96b934fb8fa9c62421c4a2068673a22bead43f1c3b8055547d220e2c113f8ae997417418773e9468ce33d93a0cf1e18273e9e12fa0fec57ad1018d9b20fa91cba29f050990dfc73e2637e4b0dd566af37356dbf37368d0fcbfe931e3de0046656e0de3a057da7d0d4789444a2844437269f299788abcd803a028a71caf3f37b9c7b90572fbf8664e9b5a5569eaf946ecf37995099ac63107303adebe88f99753c07444d748870b5d62bf0d5986b878634d73297aff9b3fc58f11623c3899cfaef155f8ac37efbbd9fecb95687bb9bd9cf5ec99498291d5444594782a59c88804d3f6171b3589f7b6aed6faa999b4cfef651a086016a7f13039306cf835b97515a878702fcd709c2521e10cb2683be57545e9e96338eefd50f5604466bde092d88a0a9c40d712c10d05b42b7803e1b940a4623b15531e10c3a89804ce62bb058a42a4f52fa146f7fba890fc770772dedb20123dd57c506b40c3da31314808d0eed7ab286fb8a794dfe8eb27237b0006c711dd28231b5b2dc3d3e2e37814ca176e1daad93bdba6b8f56b3ac9837a3b999f141568dbbb7284855ec5a0767ac37cbbd8009cac93167a82e11c560a5ebb8ea7000924dcd1a3c12c1c4cd6e4b257303030525db66918c34ec60603ca07ace2938ec5d21c66e19b91ff158271096fcaeeda426f055d8e4c47c5e3a0b7a69dd1c81b7fa1af2dda0ca444415d96163312cda1cb2d9e30c912852937bab603166a28f000beceac39a5ec3776166979fce19cc20a2c323ad038856ff5293bba9297486a4f8ef619f78626074068b0ae92d83f050c620d9f134619088278d0beab6652f94b674480c23327c77378409aa083086f246ac69e87e1b26e393a1a5cc2d0e50db2eb79a9955c653ddea8cc5791318f4f719f724053b9360c59359ac4809ad174a2385f56fd8979cb11c4d3f9222d09e7b62fb84cedfdcb10b640adff2584543cbd9186db9925f583a0e3e4156eb482563dd6274cea553f3162a6a107c4c5ba77b4e0f8574e997e051bbc9499882d01ffd191ac4e8e00fa5cdc66e9881ce45ae85706aba25cedfbbd467caec7f6cd445c5d0243473f61ba33a759a57a9f8d44fb28a5412046c8d663c89f6e57455b6d51bb1a32b49a469898a3b0f6a64b19b9373372eeb5b9ba31e03f6e6dd0ea7c1c74bb0572f003773799d7aad470180595d9352d468cd1bacb54d8eec094532a84d7abffc4844b40f95e01de65f20ad6cde53072419dfa403c16d8038c4bfc40c8deb74c2b8c23be9801e2f59d373b5ed0c12167c8168694e7d7c8471388ca746710e485e213e7200417b74d30656c9d4715b9745ed29b5816543f4a3847b735e4c2adc1a0560a695f2bac1d1a75f42064597949221aad09b516e10ed1326cefb9a33e591ab5f618926f91c3cf03014be5250b81bee3425d57409ceb6d3f8787471383c5bfa375b78f0a964eeb94c6e1c01cce5945f6699b5f7298f015abe516e83ff7dd3f5817d5124095938520f6f6790704090e038832e5e78307622d6317afe1a588604b6a6f14f00bf37ebbc2f562852239672b06754c988bed2fe5f4d38fd9ffd9154cd590e554c77756035d94b6828de6081096c06040b120187461b90b0bcc9084e331b088a939ac93b518f73537b033eb9a238a0c74c0c621d9ff0e427661861e664cb060208d81777e0643a53a2d4a23924698cd473c53fc1c8124a0c32f99e0e852f59f33a184732cf93fab0e1926dbbcf4688552c56c58372c3ce9e01d68f4c0734c05f862b5212147de08964f1c58733fde2e1af78e529c6ddb94e7459b7813d16f93ebb2c41baee86d9ffda597995822f5f1ac338b4e814e391138ef9c9361a6d93f70d2e78ce22234a49a20e60a149ffe86d8bf07111595f8b300036cc28ff782f88218e373773d5c0a73f3b626cd1ca6513fcdaba4d6cd71633ba318266a2004e4ce8e6fa2557fa6530b51b7cd4c5d569e63262b8a4c7697593179883f78ea3afaff98c42c7d0c52dbc7e4a9091e6cd74b893a56f13606caacd644b6b5796d2ef91a170fb283e656838f2d18ff8ad5aeeecba709d5b6e5fc19abc6e32ab3870fe0a85a8ce0445ac6b3aa76287790765665e1c2b2bc4d6da7c0f6c74464f12a82a8256f2cb3487c80c78e999d139b26630991821c7f518c66ba0200248a7c72dc86c0861540ffb4e31f4a31b800779ec2d7f7e1ef035f7e808ad4b9401ba6cd540025fb4f9fa50bd337364771b40ae883ed739285d9e0cba86685d9075d4dfbb4b1509d9853b76012c472192cb6e63fe702efa3a12aaa9c00adfc7c2c054eaad50c5262b6b96ac5a979a30d7f74be29430f755525dceb25a6cf47b345ed1b89c6a414675263a59bc8ebe0878674c5cf720d72f5663381c365649b8910724203986fc7ef7027d92bb923580583b3fb9294c8778fe3ea7b6dfc7da576c2ff6f9efaf476c6b7ff3bec27ae0b0d182f8f4f53b3b3a857da0f293772179f1415f1edb5e24ef126695380a9c91fb6cb0ca12c988411390e0777bb6bc8668a75635c435c83414413c886d549d6494f9e2782f89d1373ee3a87a8c44dbcdb8639f987e7080fe2660fe0b3a560b26e4d9e75bf1856361889142201b568bceb788df81dd8dac8608055a4e0336b89b77cf2778e9da6aea985ea99d8065a7904e889d50789f50e0097aba0bc6a33eed76773179b9fbdcb6e711ea48c906741d0cc2df2745b780b927a86319f2c9a7282d35c2d828b82e0e5030c5bff7f4a00a5c06fbda0c63019d0c87100b1eb8258eab93c5272de9e19efae0aba610dd6e6c22a59cbe3f96a4917a02ff9ed0f4cc3fc2c5d5a9b3040efc9b5fb0eb956cbb196cda53f3546276f2451f01650f6b979f1a966fbfed5937efd15c1d5ef103243eb2f4ed929c0f9216c334e73daef536e83f80a977f0368aed3e01a51a9ed0de8bff9aa3d211158cd93613fda59ac148f30ecbd65bd42a085ee4356688adf8889a4bfa0b8e30f31e0dd7ccc11336dabdf6ef4b0cc1f0b7d975f594655a282e3ca098ec8a82584a8a6046d2a0880c54a300ee8c900e18343e6e95e8877800c8373cf44daf9c979342f70026984521a405001d52f7de61461857240ebecb5cc6e47715d45df200638d520c4951e0b36c88c91de5a96253475ee45b099b4b4584a22450c6c7161630cbee6f19bd4cd9afc38d1c423fdd556eb5634a26899fd991140a2bc893a44350bfc7011965ab02e71511e3d2896d14a779e84dd5d6829b3eab9d6f1c900bc234a88bd3c4069a12ee72ec66e749c9e2e6a60df76d0001e107bbece2c63b13aa138ef0d2506ef2021f39a68cb1af35bf4279bd3c8a9ffcb629fe6921f77fd07e5eafb8f1ee6392bcdc64b957a5cb4d0ca04491dc1b63f4f14e0dd8d63b1f46afca0646d2b818411463f8be991c3574ac048d3aa363b07767bfb230a3b380ac91c0878da489cea6f3a73a5da57358d1f64c5acc47863d0201cedacaaa298e3221360b6f9191b6dde3888733a0b07b35c57be1053b16529eef755512c18ad30b16351fda17432ebee6536d8933b21e2003a1e74a9cf067208e4da6b15901fb9429f17016a13b9d4f638a76dc8cd6c7cd6ac676786f880c210e4b67d9a063c2ebb0e0efe6a3217d1f3eab6492cc798286ba0f6c761785edc45bc6862e0f912def1beb18a6e0cd539759e784e8be20fee2607990aed3f546624af0a29e12aa4befe6887f1c1db0455d36e140a141c91213d3865a302e0952b97ffe342043cf01d52cd1ea230d16c409cc2bbdf1a5758822b8ee9a5b4c3215517008989349889568b54bffb54a0ee929563ac6b35f30823c73ef77860039de054d1d20e40f72894590e04b6733848b82365044f91dd0d923131f3f2b447e2af58dc308312ddcebfa9ab03ad26826d810138726e064e428fd87503262116d5d49db3209e0243b721473f9756df94502c7ed9c6363d3000b3f209459f31901da7538b8bcc4431963c193b636689fd8e9f4186303affbad642a6d8c58f9c8f41f2b772fb312966713b335e9e12f042fc951c2d7ec8c3781876e781251472ddef134a41c0e260bbe827f2b4d54f968872ee60b6c7b2c2673603791bf95c155b007871a205b83cb33936fbe54a313fb6776863bb66f78ea4bb2a518ca3c1c88a1cf8b0860dfca14d939d1982bc954d7d8a7e82000099184ce5d48a56be36bc3abc1f28f2face1fadd364fcfeb378da49c034f58e838ebfe7229075303ef9fcdbef890dacb9f3ee7371003e0f5cdbc3822f2b1b6a23f225236cb392494805f67ba79006a3c3680bda2a4c1d74ff6cf159e06429438e0702fe98242f041ec2e9c79b02bb3b6930f04a4da525db860fa26feac44e4f9a488b8e306a8643b1bb45d0a6295b5aa6ab85a809bd9d2c1dddea990b377e2226ab45477e8af830f4b368a1df356ef5a50ba0fa79c99e48c46df343b4c89d0d36c347808f79f017e0e0f87201b00b39aa060e85d778d8671607ab9ded3d0fe2601a9bd3076fdee2882934570bf2725d90993f13a7b7a4ced83c5c8909f8d9c43e2cc7bb7111654b4fbd12ea5d4c1b2296344f5a82c0481095c7fc0c6d15070c8d11ce76540243acafd524f4d47c91d0d6b8e5406777a4cc844350e51f01aaf7bd5e144d2520951fc99c7c6a5f87bbc03a7dd6f088c8ab7d2d9ae2334a709eb86c49e3ac1b9401f6ca434e13a0dc036721bde22b13f09dd050d6f0b2d74c4d043811e6390182ca090b8037ec3b0cc0ea313af5956e405f109dbcee3fbbb717bbdb87a569e07dc7cc9b65fd5a2a9ed37c18e65af5f0bce7d704f797e823cf1056eee162aa0f1f09da08aa227c996103bbec61c9a4d2043410a6a1e350766d58b4ddc8f086a464e936cb92eb40677f5055e6dfd56233c18efd16be52d5c5e00ad56358e8c09fa7c4ec54fd6351236655cadce96b2880b9e613d6e7a8f6af15aaaa23fdacb30d2a59fbabb642d4f81154350f9cf202b249dfcdf7226f39df72922a70a91db2089b691f10be00377b1938fe69b2e5adba632e573dea8af0600caa6929bc519806bb9b084036ec1741de742f3e6b90416d90e09af23941eecd6bba66c30ca93674b1496cb60a6b4d69aa2b9ff878c2c924f36340a0c119bf75c775ce4c703a0708dc4ed75ab60d9cfb37e1abab89cac4e129df590889829fd2f79466cafb26dcb6875cb0815a6a5a0df625a6b08b6b5085eb891a77e9a93d6c9b116f891ea40b3ff1fbb8b94e0cf95ebe259967fb5ef3092b37b012589ece19cee303411bbf5eedd35b1f46d081a28be77b9a5e9a536f3161931c1fa7bce744cbff34764c296e828959c065c7616cfd1854d2e2fd2ecd98f9ee6b38a5f78605cc2ab94f754cd8f356b49a9a814782750c2c2f7e3657cbf49af5f9c68cf70378c916ddce3b38ecadf144c8bdc7855a75fee791601f770df157530cf1861bc7ef3f13c247a4c28063e48a859df10b2c00aa0e2234b4003a26a772f3dc9faa001eca026cdaf51f30a7ed392ffdd35d5237a1704844bf731c3a0f0ba44406fc6eeb792df4649ca01884610a91ce2d6ac09b7abd65a025e88924ccad86d3b9c26ff37dc14fb7c8d4ef3222dc582a84a50743d2b3a6a3cfb8a77b253d8492e64199b93f732599848a14d48d341bc66678d4307ebc68fade0438dde9344e259850db8cf65b6cf554efeb5108e87e0b4b910fe8822c47be4039573d2e60f5c4a1e691f08c0d9b2a2f59f3b007df12bf6386eed65bc5c1391b076c5856e5e04292cd3374e06320beb19cb6147405edebdbb129db08c4a41969f34c807c9c40ce5b39f446b842d015fd1307429e1c9ba3d3f829cf60a1160fed866560c09cf33eea83764111290299f0c7a2f3a71a79fc335f421ddb8e1f7b8efb7e45abb6aee533190c6a69c69e81395481ae43c3978c8a1f14c14c1e67c8fef7105f3d0c7e4568933a76613dfaf6dafe0c04f5f11c8a212174766e7888f86e22d8564a2850faf99b781f18fd4da409ed4a2b428e1f5024f59c969ccda821f7bb03922b6ee5cda87d6b8143bf438fcdbd73a1f784cac27f07cc695bfd4a4e495b247117ca6a7c5425664a09afe5aa6d77566df5d991f4b2536bbeae9635d8c154aca0f4fb6231831fc203ecb5c60c96185ae694bfd0db30f077c7b29888cfb3facd451985c813b6550380d800bdc568fd9f2e5b5c4bb7b4e4bee831008665a42fac5d009f6952a85892990c1699f45a53569937792faa3e175c45dfb42cfb89a9e166f43d0bf4dc9f95c6d430592b6611abe6ca1e5db6538cf659cea6d94d39fc131bfd2bdc3d8ea93f08f17a34e0391b73893df6d991e52eaa2ee738d5d94760720d81087534d4b4930f24457bde192dbf048cc7df4babceeb14e826d83daf117ffb06583eefa1e11c0b90eeb583d89502b66ea06e110ff10a15920820ff2b2feaafbbe8b2b757b732c8734c27368cee3135fb10690cba96d4ee15dc718c108b06051fb218f860e81dbd50e2f00b10ac7a37becbccab92d6b63e74d85bdfba8b93dc8f301c8777c9e7122fd77a1c940bf2fd9e69f079a68b4518dd9ec452240e032f4d8e5536b7bad8bd92e83e86db268a983a3e67ddc202b11513753fe5a6fe2ded651faa5a4d943eef99aba91a75c5d34911b592ba9a8ba6fd338455770dc8a431178c186615786e0e825815750dcfb9767a499f0fcb8ac3899f90b7114b7bfec8325e5a130beba009388108daad020a56851849f2811adb35c26811b92ca019228edda996748865fca1273880029d449c4d7695f9b5a979dd55a26e96f5d1e1b93638003ab86f066e2b1b9992e0f7d611fe66fb08a30f6e9fe43d6410ae730a08c4471e0b44a4788aa1f31f0cb2a7eddd3bf9764a16854683c0ee8192b8100ad18155268089dca576474f403d1462b7a14bf750794c84b507b76670cc7d890cfd98d61edc8671147fb1239a8880c2a49e42ed8f970965a17db8d0d3d4477fab538444820870817b7220493d1cad0595122c886b4bf604ac4834639e71d4d2af5fa35288010efd620ef0606ac5900525094ea157e2d4e0ac7511fe41febc50fe68dce738b8614333863a035c71152b06707b7dfaa8478f32d8013e24bb875ed32e7d306865da8fabe4bee9f6552ab65a5a2b032cee5c6eb1300961ab5424b4ce7dcddd7ea6962b813490a5c867c3d056f642d06c0682244ced72fb53a4593190e0da6e4a8872cade285da70a8dff0c85b9288246b9ef60e76a834fdd4db27979a941ce898aeb601b8e1bb635c81d6df9c6a2110c581a5ecc3d5da2aa7fde9dcc9dd49cd2cda52865904720830d05eaf9621abdd0c0a8cd03bb723188b17fb92bc7e71f1a9711ff91472307cf65480fbf176f00c5b8b09c914a1b207b452ad191a1c3fe964a6674119982b0984c316eec9a9390418523a084958790a001cd9f8fc23c67c5db780efd78f0956a6d0b9631325ff4e1f495745e8ccb33f896544664f4e18da0895d9cc677beb821bee697b222e06d18314e08199f17fcbac44ea387d8aa4e759d6e9be4184d2ff4ecc41350d4a8e6c681f4640c52fdeb77e797b6718f0ca96709808449488ce8c421cb8990b24a433c090577fa68faa4afbb01e612e84768bfbaac5a20949d70720c9bd6f218f74755cca480c06b43bcb3c00efc2c5041d6079753da747eb601c8f1cd5be210c089e1d07f36b07f886a01700905aee7f70cf6de5387ed8ec06f9ddcc89b37a7c2eb0e611bdf7575822aa31faaa45c63d210017377d24c657fd330d0a8e8a4a3f19396bcc85b1f4126c3b03b63995a35e5c7cfe0fc46de53b88319557e729ce4d85d328b830473930f1281daf336e129bf843dccc54b0a2e5818ab4f096ff95a3c496f90a600f168153e06da41664b46f781dd4f4af6255fa5f6eea3b7d27cf15e2e214edec1ee61e791d7f936e8031fa10cad257f6b2916af619d8f53ac731ea70072a32a36e459c8bbc5d90173369233b7e0a6ab70180f08350fc3c78b93f03351b1fd5eac254d819545e3418139ecc7da9bc02205d08ba83453e0b3a9be081ddbeb7917a554f3ec80ccf7430f4949b16065e094d8f7edb4ed70e9f3273ec9b9f7ed90cf30c92410924690da4f5e500ea35238a1ad6c2eb67716986285533269c3f0dacba6858b3952da70715fc16f1e606139db28e5ab4c2ce8fb0fbe6b72a25a7395da8a9cc71c8dbeace952ac7fe3dc944ba9329fedec0366d0e2a6217a0f9e553220d7b878c50245c9a49d27bd5c52634b51dcc8dd45b4808d09ba0066f58ec779390a51a0040a250e786f5594e0c4ed9b1b256bd481e984bef6d06c330d142050e17ddf578de318511a7d1425e098187a2ed621758b052e8e176cdc40c46254a640490b52085832ba20e93f94e8024d508476bddf21a520f17dc1b01b98f020806b66015864cd858fa9372c6e2eb168313aaa52549cdf75fc8c151d3e5b5fba9426069e25856b45422d6fadd2a47acce4cb54f1319060b434c866d3e156a3e745218dbdd506508e6dea225eda0921319760132946a66e134227a87af88832f496ae53e5d30bb29c49e6be1f90a61040ef96c4b5067f3ccc8700847361e033c46c27104ffa87a87178bb265f29258c8d4d0e33979b7d82d607adb1f8c074623b7a9102ecc2e1f9253c3edf4eb4f0fc26dd0de5c9e05c6ae7aae8e1d74cda8d98535080c03a8313ca2acac438509c48a491564c0e1fb1ed896dec85ef7a39b8dcb3c0ac717c5a574255c02aa630dbdb3823afedb5fba03c7bb2f1301e46735de3d6741ad505035c5bae209bcfc6323099d57324705d7a8c34ee489e534640c35bc6a74b879ee5b0bb8dd754f171a7d8a44b37cd90d68bc41e2daf15f55ddb64a17566fd00ce697b4db33d86208976829b3e1f5a7416fd601a290010d323d3434954d93240b28073ffedc7f2b5f476f167bb233632f46a1a6d57a1424afdb0523cad12ff1ed84dfcff152bb6779b30a87661af3e9ad7fb2eede7911eba42d8ae0b3a4922f2c72586453a0903650a8519166838207c7e29c3969ff13a7510dcaf6e7fb6c2b548b49460e18012baef2640890c7d765f653850a98345aef7961d74364543d8aa69700cba09c95034319a7808a8cfe089e9c956d47cac62002c9eb1512e0d74bc8fc74bac22381a98142a690601f86a1a9d0f5c0937dfd851ce08c88be6e43d8fdc8bae35e07fb117fee7dfdd7947e29a0b55342762cdf8159d319e769ead88f9382b463cabf363df0670d7a57271494d8d2cebf1c6283f27485c05151e4b122244ffafd02c638fbb649bf153a866be4239af62f0c8fc4e77693d955ca92fbbb10924a373c3a78ee4c661e1ef97ea11b0d4f51817344d67ff2ac42ee6461c003432af9855a5f76d4daf015727d5087255605939bd34b12451b36ff1db5ad38dc1035047c221be5706886cac3d501648a329b2411e37be97a9a476fc8dd11013ba9a1ae93c02dfccbde868009346905d6b6880432c563f99dd22dfb132e4233c69e39163f8032cf66bd6e465a89be80e4a133c65b39b75d509fb05287e27da7d7285863e3f718c08bfd0a9e5c06890c033c7108b553e436f836a7f5613aa3d7fbe2aaea5d6f5e59fc6962a87c43f734072accebc95013a31e81a50c8f6f2d39832030f25eb07a3b04b8e0304d272f2dc9b47310febd8ced9ab4a655ea31a7691b6023ff12861d76baf6e918c29aaffb05b465624a89ecf744707e6e220e0ae232a1e8c551096cc798985b3194d07333e6bff5dd4829489e49c1209f7b6d2cb30f978bce64ea9b3a514eb020fb3bc6dd5cb65e8d14e833bf021be4561c39df4e9cc1790befaeec343dab7a63b6d4dc8c0a8cc3772b6f938b25e2a47f45d3a063adec573e04fa2b41aacc76bcafee0f2ab456f388583681dd8160ed31f5979e7dbf2c37affe648f6305afea669af1717ea1a819048f26ce28ccd529d3dfab373faa04591b04d031120367913dca965a4a0ab5c6c0832efd89e764974764b168f6c16b3d9b124cb9843f906f4f1a973ae137756158fceeca78b5e2fb43520a6aa41a07f0509c3dc1057b6b05db2016dac4ddd3d44aae9e11580058c0c45252fdc62fc7eeaa412cf92a3610f6d8b9c098aab0c4da270e8eed78ec81342f0696ea18a56125e3fa58bb6bf2e05fda17b92d7ff84a61b069885e3e2c8a17f3d4c93fba969632035108e96daf19c79eb521d4119d63aa2b6d9785009d4fb529dd4eba3484b45f2aca575dc62ab44877c0392f2636d703bd28822f8a1b6d747492be6e5318f225e454ad4115bc930ca147e2aea02782bdeb052789cdf0e2cc670459724114910d8f83112db217258d4bfe7b469c2fa200c6eb4b5aa9628aceb95502881d0f3ac8c1636157bc9481f0bd47f55987d50099c93b0254738d76692e00bbc5bb9ec0d53583fab86c6b1e87cc69889ce2166a2b523d900d449a4c5b5588ab53faa3746101609a94d39a0265f01b9768456ab700084f0b2942ba9891513ef35f793398e607f17e3ea46f356e429a06a03f91c1870fec3d1bad8ee1804755273326342522939752583b2fb3e0656668142f1879610530c4d576c15ac2739bdc6c43b51d00c1199b58442cde7dd02c4bae538d89c3a6d312e4c34404a4672aad4dc04f7b56fdcb6aef4353d554360b3a7ac18a71c39396fa62b743e3d0b008ce25c278fe925e3380090bcf660b042491d72eaff0847d5bc944a4f686dc8f38dc3aacdecfc5693e59bd66155894849f0f8261ea0ddeebda1d747489f70d193bbe8427eeab35a9562d1e052c379614341f867e707f4ca2ea893bd053a69c3b9c97d147b2c5ee2b4b3bcd1fce779d9b2a3ac52000a65443737f616f9a9e32e71f763e03dbe80880e552eb9f5fb72b8e9b17333daafeb47cbb7410588373140b4e77d0f3f93e248d80271aba536271445c214394e60b7ee14d3ac9c69aa2d673c088f097790dcf61d186b066f01dfdc8b206e6f97e8785738db5c38518c98321d31e490f18f82564691de082b51ea9fe89525d4b5623d24e57458edd1a479d23f278a43ec5b12610f3bf1c8a6cd6ddc66461e0d458adcf37616b4b1571bb7ffcc4ed3cf7b75d31cf4d58f96e1e0b1821e6037026069f56fd183c655e90aa20d07f8beaa23ced84129c32028e2d71a54470a21608e30f65c4ab1dcfc3a48bd88efd30c1d3dd112033ef59bdfba60ccfa263e6acee3be5e2ec7bcc14b63b47c2b07154e9f2188b670684890647fa2bc9696c915be52674a70b2c7075a7153024c9a8fa7050a63e63c24c3ed8918241da5fadfa5a1113ea0ef39c81dec1f71cf39b873bf893f22c10b37301dcb9d47d037f3035b31d1233f595d26be61d8941561e897251804cb52358f05a5526a25c8f2b8ebc75175ef74f271f95642730801e9f7f60ab143fa5e67ab97f21fa19f7de4384791109d7dbc79021cacad82ecacae773a034832cde04ffbd3058c46f8700686a47d0b8601121d031cd0defd98fc98b3b3ea7aa53ee629e5d986e79c31de7dc073917a198bcfa4fd213aef21923ee9681667df752800d91749f5180e776fbfb67e569fa4f80577c17dafd108476e9da0ffb33179227f4d0982ea98987b47d0a57350740ed0c7977a1964943c0e09ed5426f34a9510d84bc5a0436431734c68c8e8dd91d883539dcfdca55ca86040d78d83457d8084b4f1e35d218002f8fe22a4737df71b4715c4353e9256a42ed49808561b0214b5e2470589154dd215554b1969d883a0eb348f87e143eafa40df5322ea3351092e85710d90b3ed5d2ef0d627303885c01913c3d594f0b9178d7e0e717a8964887bd2af44c048c77337db1f1f4ba9d2fa096a202a89bbfa8b8bf1bc760d3b84335dc62437777d378c9649326031c3d7dc9384fbe4208f9f51e8dda1a48adef0491c16c3e0171480c36be122641f880d3b058c86199334e45dd49bcd30c6cc731de352a32f227288ed0c4aaa7b409c1c519a062644e12cd11f0a8d38feab8244ad032dd907bed4ffb07d2e6dd68003f1eb739cc03bce18c31238a918f17c889f27047d603672c2f4edb2ea224216ace1bfc863ec1090fa9c47c2fec402a01de34edb21a1e652b6865774b4193b826ba8d82d4b57c80ad1c4e049a174deb209be1b19ef756c6ddf69e9466ac05f857aa9e85a7b16ae8f0e97c98c5134066b472a9f1ea7ba83e9f32b84a9cf806ee0db79c38c31ce611a8d129ac928999ddbbea18ee87b08d653fae943e1950a8ada04a6118e43f98f310c28e29862cedd1fcd1703543290f5a4193ee2de0a2803944d7a0eab7151f2ca61dd325236147f3d525b9f654f802d17141efe2dc3e8ed1f2cbe06d76cce8370f00e95f71105ff7e6da7445f70cb6af7b3ccba7017b86410941438a7e620fb1c5b94ee5dbd6b35b6ea9670aa15137d462baed576c9a65217044ef94112b2dda9cbcd100d8aa518b904f5b0e002569f0fa19f87f47b78cf0ef9210d1a891317d703443911892e23e9125ae2c4636a0c262ce4e2304156aaf89b1c1625644d865da1228bd8cd37f44e4d900264e5a28f11ec33b6b3191077f5376df0200ade31d9e8c751b52fef6a9caf91023eb19423038a5e07d16068952599e51616ba175c74eeea2c6efe68942747f10d7b9fe402580280a34703973600f46cfe728ac7ff38dd22da778266fa5b2345ad57befbdd5693237bf5ae1b5cacd6126ce5b24494c6d7241d53b7d655088a8ebd5dd8989708e83f6b5ae48b393704acf937977a7a1cb4de08fa07c49bcafb10b01d943512a012719ae2615f423edc2d1fe611386339660cd297c28904504d1ae002c07cda01f8ded57d3cbfb4778d07462697b1c8bf7c9efaca93b5d2391b3ee2c09206e5b7e223e5760e41a6e76daa5e59a74e6e7e191ecbd4e6fed8d14966654fce19f251ee4c1f2df62023da152163dee32c199cf14b2cf9d41e362a2b77600ad9562731e6b5732a59033e00c9fd62dc2b329c47d783459504979dfafad2b0314a2ef94f77ecb791274648443d4e3e3238b1d3331812497dd087b9ab8cbe727080d3a2f7746e9fc44471ae48a19ebb8ce60457e19bcbabb745ef84436c3bb4b38a6337dbd1ecec3db2a8869a29f1dd49ad8c48914b4f19743891632a196b78bdabd0387bc8aad04cd7a1ed3a4970ed7d9e20302885b58f54ed3331ca784182d4e13911481ff931558002e7acea8abfc2df92b62daa0f61ba9db684e65a9a577eb6697e570590e5df385906e3c9b6d6b464631cc46ed81e80b723393ebdbe9951cc88ac74ffece1c82ce8e8a1a2542412666ff4e1e6f6697fb461143d20792a7c78330811106e87b71a052640ed28e7896995877e3ca97d791d6ee9c5a9a34f81cdf4c81c03b64b477d5066267a1bc838dff90719b7df7382d875ead54d30e98e68414cda9fa14ab826f93b9feb5bb90f21ed369ce50b4450a1dcc0409863cbe73ed3acd02d1f62b71528e1480cf03750ff4f6791271054aa0969d1eb289b68edb225063f4a12920a2d21f13a732e157610450d82ce8883910c28a23087dc097ee0805345adbe92e23935751b3a4d35a4e052ec0323de5e29d06b492040b900998589d9f9fb75a2a74b287b4ded08c23b0f77f6ac85cd2fbccc087ff5cf59c31e84201f567c32561707e35336487aee85699b2860f977669a2c9b7576b212e14ceed4080f4e33e59ee068c14a19772ecf9d16ed358d57495691bd6ea843f2a381dd2ab53164cc8df05010917e8e24a0a27f1ec658b039ec3febf54d4ef5a38b596165cd0f6ec71baeb9c9ee4c889055324bbe1c0d433c85129f4522bd6ea7befdc0133bba7cc767e30519251aec80f03e5fc6b3681e3b1856226273e329341e60fd59e3ca42c11a55816e6ea0b56a8cca5215ad6b11df3fc86c94ae10aa87ec2cc5d610e722ec912df82ca0e332340fdd80eff795f7c9bae61c233fbe9c9c5b87ce2f91a0616f602f8af2b8203c03b46b083f11afc97cc725ed368a7605c862443a8fef4f88bb37cd1aac76af22910be5a08f4ac4aba389cbb78936c1cf7f3a3c85084301299c08413ef92f8a842ff174981224f1dafaed98a3b450db176b50cb941a0def3fb52d1f2bb88881ab00ad87a9e14a7b8562585f903df48151894aa98159bb9d77e2f85b884c02c6f23cbec79c7c13de70e337815de75a1b3f60e0d7fc07e513a75f45d93b9b4e90109642f32c18d137d84dbd401be6e55dfab30714a360e26384dcca5715c5d9dfd571efa6a82afb9208092f5107a5f6db601e0733369b745805ad42d487dc5fa0f976b878c669af7455f24c80962650689461f027ea483403ca45542edd7ba11afb30b1e9a65576b424febcc88fa06a921573e3c8a1e37d593e62fc22047e9c6b5e69002ca54ed97d567827426c4cfb261ba446dac913138fb4d0ae8347a671995e5996f70e5d9f71ce0d01e5dc6f372809c8831cd18c94b91e54250322c9500adfa24c28f24e2662dae451d9051e7b6dac755c33099b56f8e60329d63534a5d89c12653bd95159a76daefb9e98848aa5195e56e5689b8e7cb21424c6aeb9c30e33afb337d0e7728e949a3b5f3bcc422bca96387b4ec038178c2ec42d38c32680989c02ab8b2a6d49b5e955b8253cb7433342f21a2dd35f1594c118a329d3fc914bb49c2408fe5471163e42eda207e6560a9aa10029b34c3bfa3812ac87e5b120b073483d78d079a0f132470996d689717874420441254e21a49f9387f04e1f4be77d0884e8dee1997f913248d4cc48fe00c922de8d79b4f455c1ebc106659ea9d22129c25b5b5ee9217c0b754553cc371eb9aece1090412e3929cb2b862acec8397f45daf0aeb5485b6875be2c500faf6185827495e0ca620b3e47639cab7cb253c629e03d087907a421efde377e8b109d1281c8e9d8852d13bd7e8ba0344c75b61c2cb528cd5fb6f53a137264fb45e89c8c302028fa9a6177ff5f939e1fbbbeb0cb30df1de5d62330b1395196046a47fe328413870b3390006338c1bc1e8534cdbd29421de49d6afa2aefa193fbe8951b688334805b6dcd9d9e4447516d3cc808b99bd0a75a789f0c8d21b5c7ec1082160a04b63f3c233834f96c6aae9936cbb4a814899e3d05f0f4511d83d85cb3fdf53348dec87d00d0fa2ab4dd0d74a0ab12bfcdf0ecfde43f421731484e3d5ad050a7512d98f7915563c4f17a5d4761e57514d43d1f2daf4b7f462c72f5c543af7e272ce1fb997e2ee353be693d03b37dbd2c4e376e92727525b71d878375b4741d592ed83594ca58af86d206e335337d41a6a2e3badb150415a4e95680e252ade9f249ba3c7be3ea394ffbc6242632ac746f970a538ef787749ca8713b4e446585f7137e2e56ab06bc75992c5f17c82dace8fff4f5243421d6d4172059fa87f9f4c8b5716f10ab2ff6af843f45ac5534599ed880653e87d9b6add9a6d2ed9434608721e2e9013b9e837e5d58c0e62da4df8d2fb06839e8bb982e44fe47c22d5b4b587d85afbe8b01102210dc728f703e6577a96f4264f0adc1800d4706e5aa511de0bc7bc12e63a1097f24a90cc79488c20b26ee2b4968fbaa12221dd7a209431f2742a941f2e0f94884377665e8c5724913d828dbdd9a6d09c97451be6df7cb962c14ce945771af84c4ae2b3fb12b5d25e14dcc645728b8d94875501f6f0827a07722a9d55386c819c0164ec449ab126696cece6709ca4030d879818700bd24c37273cccf185dd36cb647593436505029c4c6aa36d16a73b87df397615ec91dce7da8e3a78e67e4209b6693c35b734b3aff1f65a02845cec47d297a39cab3ca96775e8ab874272880975f391c56dd524003d2567f07a5ca8736b341aaeb4cefec2f67f8cc207aaec8f1fc26a9549d6736479878e66f2233b80dd68c111d087dd1f51a874512b8de38aa3bb96331bbeaf605c3420817be8b90f8c42e5c2361d3f1f53cf93308dd670c3c6d2d40ca0c322ec0c3ccd491619845ba9d84f7a92fe6d7c08502343727949f63f12c82a48e6b52437fbe7d0641f1a61cdf234b5ff309c6904a157bc4a187876e9c4fd3a5e38c84423ca0af24465e6ed0ec6f815c0e120d3235cdf07f6798428cfb85653330481378ea3454e403890482b628ccabf1b4bc34503c693d067f8b20c25000322ba35c2a56620b632376c6350f12aa5b91c024c1b10a20de0d664dc35fa1801f3985701c0fd0c0a3648b8732970646a630579b419e7919e88e96781b6a5ac343bb720b2582410142ef9d5dc609e1bffff12ed527f7701baf0033d15006e7df70341138e501e6fedb04cde03890e24d40fc4d6b8b7300e60597cc340e6c56afcc552f6fd52fb74839705790e50905726e553d450bc83d078ecbc2ad7159a64d4cc8e9a95a76a2a09c36ba4e6d31850bf5652d0ef0efd8c07604083ce33df963051837f70bc6ef43e4990537cdb8e49ed4c9460e709c21aec37785039f5a15e19c51a8637750ff66a00f7601ff8fc20680719f62894803cd5918491950af73fb22904c5b92f4927d3390f30c6c492f01b7fb6b04499895df0cf50c944540c29aeb8c120c4c6ad4a1799de5d55a000d8cafd7768130f41ae454518c683f033f53b2343fd438181f227d5724b012bfc07736535d7bbc3ed25b7f729aa142be9d8119c734393a8ae1840db523212c5ea181843534990d5aa5ffb5cca568e01603f83bfa622e5ffc82c5cd44629a478a0612be855830f86ba9b387eb9dfeb9e37304fbac707e43235d37d7f7e452d43962249bffa3d13f98fec1f81fac7fa93b84b67ca60b61eda0feb325b5b1a388a2ba7948bce1f2d9974d7fea08c07f68914ddd7f4bf1150882b1657959a159f1e3bc73b93f142146eb0ca434b1cedc339f93ff8772dc011ccc4edbea5680dd636cbd0ac65b71bf4fba8cf621482f7880c6fd5a2bc90fa973a4c3f1194815f52cae441cfb020451909bf52d6dba04ad82e9a73b7819e0a03991edc20d2f38fe6f4e6d01d9df772ac7054cd8326c4cdc72a0e9eac003bbb4ad67ba8f25505c9c1a6d60202af1898061076e37cade617d8112e9cd0275f2ee7aedff7537fd77caef09eb3aae3a7c92969b468b77d8b0e18c9f5c22d9feefc6ff68f54fa16d87f53fc1281467dea1240104c6026a3c0e755b3092324e07c9094408564903e0632b121cf75845d3e438bf29391b75cd28cf4755343a4a003b8ac9becc3b00443a86c1eac3fb7f37b3abe402808c78ea30ad4fd4db1241dae85308ee251ef8073686faa51bd97b6fb9b79449ca14120736073d07749a20fdc61317e830459c1fff2007b1cbe1f5d72a88d28391383f862208b1d391c35a1d33a65189d4820b1547e2fc783811934c49c7e8bafee40e4c62622753a00691d8cd32904469c30e49a254410c49ecb41dbcf8a155701912bbad065c7401123beb831831b1dbbcfe640aa480891db7044cecb833e990c58f778a9111542af5f4e723e8852476d79b1f0d16627f1209316410248168e0237637bcf9d10489fdb1b0100249ec5e6ee0212676379af0113b1c5e7f1207a024714a51c64bec60bcfe642b0c22b18b79c1608390d8c930a1612243c3344c8868880190d8cd2851a3c44c0dd728010510af98d8d138b1a18162c3362d2b593871343f1a09b258c344ecb8bb39c1075db46a4a3d1978c337b202f577820fba68899d8d37bf1a25c4fea413b02e80c4aec6eb4fca200c23b1b3f1fa9337bce02576375e7f548c247ec48e3b709a60052e787908dc2507245c3b457c2178f3a36122f6576ac20621b1e38ec7093020a4104410418b71ba1e9e64a1e9fc685898486a473f1acd5170fd24894ac4fad1689adbd78cbce6354c442522973c20db784d89eba512917e4a44b1c72af4b4d493818cd32304f0ebd1a3478f1e59a53b4a66123a619c748cb359e99fad15a5431062c82fac48a1b57b60246435ad7a9ab79500430c2fd1824ac43ae552bbf564ae691cf8ccab3c12f3ed5bbb12b1b31f381e89d97ab49d8f86056bb72f86865d89a8444ca1edc7a2fc686f9aad536e8da1f6a59764d0d55a6badb5d65a11303da3318053f944567aa1be549fe0073ca07d976cc96ea5acb9cd6a9996717da19e396756360f3ae629e504a7fc40c72f058b2d5c4efccc3c459a68c22afe91ae8a34f1c3957651a71262ccb22cebeeac332deb6e26e109ae75f3ced2cc3c74fe40eee0ab779d3dcc1ebefaacdd5d73602267d6923a13b2e034e1a172897977be2b33333333336b5f83ddddddddb4bbbbe9910a048bca75d6b955e95ea094e085ce12b7b2516bad9a6b55f39a39f74634a763966559d69d65dc9e65d676a0b96fee79bcd69ad5aa84b42e418d0d4dd3b46dd336d7506f6463cab4a39db44468527c5883d963a37da4716da76414b02b9ea3805d79f62c3c261cd6984941c17d1d373bd08763ea751fc7b99dab0de4616d0d4dd358d36c359d91e5b42e1634ab9a4f97a71fba99182e7521ecf314579a50afb57e33743c6cf051c16923c85b6f1f645cf63cec94f50ec78f04f18ce85ea2b830e82cf102c5a15cc0a1c890202649660697faed66b61cc771eddc1be96e66e6beacdb3aad6efb03d483b2639b998ef42d731cc71cc731534b43f711f1687f65724e9eb27f5ce03b73179eb3eeacdb82a392259ebb7f4c961411f09c7577b792a13fc2af51d2f0197da6a2cb0e4fbda6a0b8da33155d6e78d9c3aacc997e3bf7c80387555965fbc558af0645fd699031c809fe63bc9f65c926253271d1b5772d6b77edd6ba767777d7ee9d233bcd3c5fa06468c869c16ee62db899ef62ec3af6ce39d0083bf7463a8ebbe71cbbe79765d3f9cb7c76cba9c96c826377c6bd9dabaebb3b88e7a51fde67dd07199773eb3173c565e1388e39aebb53200078825717724f78ba73b71a5852a4555071f2d4bdfbbaa8b73eee3ce58f67e881b60cebaa7438436c50ba06a59429659e2ee8545ca877f4a3e00b944b9d524a29adb5ce1bbaef8766e6cf05695df823df7f2f5170cba0e32d6ccd57ef0a76169f2506af934b5dfe903a4b5cead3b3505ab32c3a118266be8b4c8789cc0875d41b6190f26c1f29cfee91c131c9738351b476f969deccd56957aa3538326ba8cf28a595d2aeb373d0b16fc1b566599665dd19675996f9dca2997da471bd535396187c8172ab4f2f0b777737b3ad37bb6287bba8ce2a70ac8499c70a8e49be3a73917d0878f65ac7249fb99ca091233c05d014402392b7cf53003d3bf7bccab818228c1efcc8ce9f0e131a48a77777777f5c7f3a7ec6e92a7bc7956ba53eb8dc76d373d1500c3c9a655996655996d5aa79966959562b9d5d7400c0e1054a084397ba3da2a37981cdb395143079ea3f9382e27acf566e60e3a95346ea64c4609ccc27133dde48e5e700f3bcb0f35138dff991c17025499058b71cb8814b6450899bffe010ad8f7654f29aeffc887afaa11ec76b9b5b9e91561f3503705fbd561fa902988baf6014e635deebf7001d2c4eb4214a234778cbf83272d10960ff01f91ad801def21ee836daf80c8c3282243c0590c8a08fbf742e4980a700122588843da653a8f78113245c80842b66b78f45fbf95029353c21810f311097c8a012a5ffe01079890c53b4fe83c20f0aa24512040bd291b480240816b60d94167cbd380d13588942060e60b0832a4225395c89010f3c386144041a621016dcc74794564bc7ef838c6bbbbbdb6af2d5f128621e66aecc332928ee74a7cc336be65d05ed0c2b6515954274d2ced5163df287fcec78817f8172d99bb3bc0e13b6e574429932a59486b4bb69b33103d009889820b15c72a9b7fd5a9d716a00ba9a14193c670d4140183b2bdcc87a751dddb80d14d215887938d77c23621ee99a7336f08a6bcd108879368e051c6a3ed6251588cabf207fac407f02c78213ae70adb93ac10a879a6b1bebc57ab14a05c46b3e7241af8d33ae3089559a045542acd27cc816374c7acdb78fe7c52acd790347216abce6e3f69a058524b14af39c185ce923ebf51c850f0e2e95b28d11c20a71571b9d95660ef35ccab8c43ec100fa4c6a37edc9cff45de6555a7b565935d3e6f23bbdcd59e25ea0851906695653cf322f40085d2ee7acce333f09318fce6761f7edcc54e62dcc1590cffc021be0c091c98a99a99ad1fb3143d40c337729776423ef336f8102d6ed6d56bb75eb14c63c366fbd0acd55bffdf19648bbc00c33d7c0166698b1d1053242f68d155ce9fd2365a1639c7126c8884b643ea5dcd14fe78e38249921e6e9f1d361a85cc9c12ef7e260339cde71af667142957bbd8eb89a8fdccb0b6ad606de98d17e0c17f41dd2c6c199e12cf5fc98592633f6f90c8e10a0b4bbbb6bf50674d425056d3f8e276682341854404fbd9bd743cdccbb8c049f20ece3adb020cdb21d648a8b2aa2ee69200e2a6e8c776dcc539bd896a7d6765dd77536b119d2d1e6e8a98d161280309d9d8631871c5debe3c9274a093cf974be59ef34e4caf5b1364645ee33aba47d4df21c3d7b4754e7d6fa4f2b38b481cdd0f3ea419a75c1930fb58159c1ab8e43eab4f3d1e6e4d3f9c9e7a997c0d1bab6655ba6cd520e2191ee6ead3ffe0ec69a760a3a3da13743a727374c9c82e6ea26091b30341f6f8826911e493243da573344419b230d94199a2f56f504915895420aee887211b9f99818ab3a2804ca1ebe422bbc4209cdb05152386c1fc32bdf23897934ef1b22949493936f6f4709cdd569073659a13dd4707d8f3744dfde3d9258d55c08af6fa75fa9c5aad640d38b55eda7a0ef916b7d7b47254f53954fe557905985e38910a649d19d3a3ee5b8ae1c7a067a26f290e2d4ccb007678635b5ca5adbe7373842c06b8ad43c4f530c39ae11aa18a18a1cd70f1f218b4e72f76c8fbb995249794091ee4827cd91e25a3b8d50bab18a66d9fc4eb27400254fc1b1f39e4b610aaedb4e4b4442ef5fa07fa4babecbb2cce767e00881afddf7a54e3a5b33bbae595e4d4c87df7e5131233cbb279b3a47dbb4819ee74dd5b3874077f45efef07c3ca5596bdb578f54d757d7aadb47d9b94a7d959c55a22e46f062042f46f062042f46f00285d85be7aecb716d476f3d85b9d3e30122363946dcadeb5a4a29b98ed68c5a2bad3de514716fb34e6e5d87a859d5adebbc9a95b9751d989116e0c4993c5a2d424e954bfdf4d1c828d5afbf7817c2cdd17783d4291d9defadd7efe6689a60fd0529e9ed8e585de2ee88354b8aae07647ef22e3da0fa0575843a65fdf4e9b83a65bd4eb9a38c110c953b7d24f5f8486295f51c22eeb8c335de1d443b8698a7e4d67724c13c9bef70ed80ed307ae699bf922e451b437584746039985c98ce94c992319a29ebf68aff9431d2119a32463a4253c64846cb64e12475cabaf52e6ac4a9f99c213c87ca2de2a3e563075eed70cdd0eea8e2c3c998b2f2d6532fe6e19c47ab04a11d554a98b2c33557250071c324f6324693036f7e74843e00087120094239ae8b23090558b36e629db27e83821109473e92748602f0ea3e9befb4aa0312c020e188796c7894a1c2d21f75b1aadbbbac9443e5561f56754ffb8d16bcba89cdd0726e9d7975c30587d6c71b2d6fdd47d25b1f6f98bcf59b1fe6e99cfb6460acb27ec385cc156fddfa4d6cae64a8601918381f79b448d0e2ad8f3e92668782e98075a08c0f078e3b28d80d8dbd75afe423e7add7a190b31ef76da51e8b9a5d273b083c57828f262fd01f758474a6f068bde5d19aabd6119aa175f9e9b86668fd0693dbdfa1b4dc51474847480a9930fce9e57aeba7d75bef3a1e2510e550b9d27d5825fd268549c4e66f7e58e5a38cd1cd0ff398dcfa8d11f350b745a38cd15ba7200946acb23e648b3bea08958858659d4b456cde84c42a9ba2e0c8e908bd75012431cf8eb73a436f5d4768ae80bc751d57b3a65b0f7c216495f5223f9e03a39cdc82d6e278e2868f426c26d631cea81267d09052ce09d699346ab5d93257b582748659b53102f2d47f08314f78e505fafa9189aa51b33c05ead3c78ae4638dc100ddd1c6a859ce29ea5682e3bdd349f881d3f10e69dd913e0e77b4316af2d46d8ce66a6a896d399aab0916e11fc306c9868b4d924d171ba3253f4f7dbc69f237404f7dbcc1e1a6f574de3879fabd90812aa0ec8ace366b7698c4838f7462055492c4f9d11c2176538d197e4842c2810e40e2fc1849cc0f5f68212629c168074fe8d0426cb05223a02a5eb082a40c8624a264528e7cb02421ce8fd55081166267bdf9d1273988fd21a13da821c68398a467b0028bbbd1e00617574d80c31a2610938444b4cee83c242926446d8849180685d85f4e152818ca31cad23279fd856b9c1113e7c73968d922e97afd310d88a6387ac922c88a23717e3b476277a37da4e4e00731490723e30c1c56764003212434a6a50826c424a16b680b929d235186293618d5e7e9d58588cbd018aeaff524f4d5c7a9e52bc8b5ba2d0933a8fc6899c0ec0faba6679ff6e23224d4e036c4aae94090346af3a7a066695a666afa16a1315c5c867e6a5d4e44f5a74504e633503302e38755d5eb0864c66d1a95bc6455c7798e0a428961c21473ce392533334f1a60378c5bd5b0565009e34726daae5cedb9880a1744d4c64cafb9099837e6c67351ab07df3d1751b9c18f214c8a986baf6f540e41021869622a413fbd54ea99568719421c0579ea5e0c424ce9969032060e3070a5c04a1555134008030b58194b601125dda0c480047f25ce0ca553a142c4f0f3a7cdc1456a414d09428b20640882074f7d8b8999417a4f8ba44c79ea944eb9312510e329b56d14c180ca536a6915219e9a9e52ea51ebc9e718103f3f2f0f38bc45143fd63c7dcd3c757bb73c2d1272c275dc00a70a8cb525a8c284676d380d51c39d3e2369b80cc3d2e447effbb9c809a137400d0bc6bd671850db3253ecd124f5e078a65d7b5dea3979f3d186f452937ed658a726f5767cb8a3774fa6eb230dd267259f12d3c093252273be36c66469ad4ec59aa5bd9c10e130d4c4b5e4a726f4538bb5b8bca54162158e1b431789792ad1cbebe5ca5ce1f0e92f309a1fe60140112fd077e2850666fcf4ef8c3b7aad24785567e070081c2b0d4cbc0d60fcf47bc43cd5e7d0e6c40b9a2b944f4a3d1d319e140e3da119b6fdbbb9d76a560ca8c574685eeba77b4273e5795278e565319757c547ebe580e91b59a77da8ad435194066b160d9206e3707c5b972d29d6accda853d363f628b6c5b6d7b75dd960db15b22534c3d96a9686a4c53c6c85413f9d06a959da96999a4d83f416d4b22594724450b29fcc678633f319359feece1b9a2cb9844774c5339a2bca452fe0f2d3bd3164500f54fce879b0284b7ef4b4fc3cfa99d1d85c8d5aeb8fe66acc5ada96b9cac0f8b969311b4cf0a337f4d43b8ee8db4903b49e0c72a85c2eea21f6d2e6e757f3327354d19a68f9dac6b3c2244e693e724e7ce56093bbe2ab730dd74895c00c18a09fb565adb552afdfe93b0b43e566d508c85cd1d551a7f904f2d353754a11d528a84b25aa4150aa50bd52afc0687a644c12778cb1304058748c33ee082262d5742aa59412a5e58ef5555f52887caa9d62a72318a00983c364599f7ee3629e9d9fa7d829763a9aabea5c26ab4299525b4b7efa1caaadeac4a5dc53ecb4c56fb3581c6beba7d3ac60dd8248a4a851204d62cd9219c2073d7ca185891e48204e3f25354bc90f59603880cd3003365e202a890284276670050a5e33e020530333acc0c245121a6d88d3b974da428f4eb1194ebf81823bde1b94613183d104bd0601d1cf1f585c396757ca11fd9ccd45c738230c6c655a83c30a03af4c49d587a57311667145cfa8a29f3eea3ca35e210cd14f1298c54398f5821abaf102d384fc60dec53c36cf9276d36eda9436a528a15310ab4e41a522a8a01ae5c5a39c4e413de3a98759a4fb053cb5c02855ee786a31e11bfee2d3e910f3589f5e7f98a74ee7b136791598b5c118cb4f17c2439885c3a7176116caa7fb18b27efac6dd519bc02d8672cd9005bc4255e170facb04d61e607eba48219e4f3751c12c98960b460929c4038f7e76a0d419ef0e18a6a5c573a0eb278c123fbd43b9e68af34155e1155702ee0735c419c1fc34cb44c5cf4f931696a569073f615a39de943457b53543d31abcaa2ca83d6cb0a1666db18669420ad9ba489de93aeedd5043bf75e94caf8e35cb94d42f98b57734258d5beca7941958959c60609856b32e08d3c41d4f36fc8469c294f4d3616ec0424c5ba4cef469daf213a6899f5e2a72faa6284b0d60df3ed41494d00c834a8082e23357a81e389c3e7150f183a3633f9e38a39f6e1a6ad6e90b4e4d2fc33474d201a7a6e3f84e58f8640587d35fbed38def24d4a9e9fd9da0bc9a751a326d91424e3db0cef4792ad281c9f4fa797af2d3479317ad669d7cfa298879a84f14fcb8bd3cb55e3e2b368e3fdd0f4912f154c51378aa49b46a9552848195668e1944e1f39ad3c87035d6dd41f4f661daa391e16615ca0c35e6202e2734438df5d29c488b796c5ea3ef50eec9af9ffcfa3803c47a358b0bca69e2f20c25183403c482754af313cb6805d6cb7fb8231704459b697dad30405f8b582f4e695e9d650366cd2c9923cc92af303f5f9d239242a694af2fd599ad786d07111a7ce525d2c9ca9f602f4f574820bce6a3498dd194f4b2b362e5a5d7a14af4523a47c43ca54e3e8e97d5a51cd2ba9a8749619794cf5c7942fc0bf34b5fa806ab346f304cc2e18e303eaf79ac5933ae4e5de115f784adf08a0b9aa1c63ca6665d1f5947afb18c5e2bf9c8427acdef674f1ff793daac984e55d79c0b9a2b6d66e84f35fc0a8e47aa7b2821e6b1ae398c0ff3a05e73981fe699afb98ce61b10e329e9b5173c20dbf82827ff80fd28d76964b876be07fe58f1e4bad367d7ddb454c4e6ad775b0f65aeb5d6ba39539a7df2bbcca391e172cfde6525e99de69dbeb0cb4c6961d2f49266187699a1e61af205cb68aec61917eb8ab91a8fb4eba3fcb878727965a2707ab160332ee6e1d79c439a68f08a6301174d29579b7677333383b43e8343b25cfbf485fad28fd0d0ebfaea729ae94a7e0e817933b4331ce58f476878869cb99e237a094a507e12a9a4a7d79a4058b064e153ca5abb76eddab56bd39eb4d65a2bfd9105b7776bb6bb4cb3dbb51c5732993c206a5cc9dc7276adddddddadd91723ec3770a06038981c3a62626e8c66a90c9da13494524aa9a6699aa4b5d65aa936e5466b5ab321f080c951734371e837664fbd4b792a6fc7f348e0b90aaa409d9a5f8207e48c6982b7fa7e0609008f67cd001262863ca1d4f3817e06004820000f0032581c117af4e8d1a38708e09742edda33abb5a6727efcf8f1e3470ef8691a9033ee3852effed98903f05c1280cef06b63002522e11380da5022448a1421619ab05aad562b137a88c0eae6201c848370100ec22ce68113c24580a700052c8052ba8066ee05782a78af202a910aa515ea50a7cc18f2a2288ae2cf01780c20404f8fd70022458a7805288001d43880c7020212e0a5f8b6a4033c20670051e34aa9008faab0c20a2bacb0820a9afb484d9f10f0809cd18217815aab04989941afebfa74367d8047bfb185084420021188400b12f02a30010aa8809c01e48c1054336ab7052ce0820b2eb8e082054650510c60200319e83400c48c2b9d6a806a40670495bb8005cbd9776b5ab3cc6e9652a64c993265cacd53b2e98d506f396ed9c9d3368ee3386ed3b2eb7557a2266aa2266aa2265a2a11d1b26a5f4a2bc4740aa419ed2ca355dec0819a2b6aad73be8916fc0932773aa46e3feefb2746b4dee5f0b68db30e639dfe58d1fa662dc5c211494a5b94528d524abf0a663a6817826a469513497bd1ae792d734e161cd14c47d3dda51ef6cacc943fb0c5b8d241da0d96c1cec9d94dbb67d8dd1dd34dad6dcdab9f51205caa0fab2868e90bd2954edbdac9f285cb957e3d2b39efa58c2bdd32b775a651c997acd45a6badb5d65a6b7796bb3a6074d0d4780822f4a03bc227db139b9a191a1990524a694aab94db3aee9362f764a336630ead4c4c8e940feb837934ee9c1f947e93c39a7d0d41f643552bf51c480e53eac9ba36737377edda2370dc93fbc574ea094c49470db7db874ea370bcdcb82a4a29a53b955270460757faa9baf452a9a79abc1d2036dceaa59eaa03882bf5349054c775315026a5946627fba2bde4a0f1fae7ed77373b3ad93a9c2b40a752e814510b2b68198c4c0e8799f166719e143dc9c9d2ce0e8b72a333d4321c352889e3bbf1f272abfc4a1b8707ad5466ded5db478e35c8c3b3f90cac40b3d6be51eaa1b49b230a82f66d56e74c3fcbdc177345b8e106d8a32fce4b8fcba3863f841e9dabcea4a9d453c1192e6e0f4a5dfe74a129f44aa51e1d385cea92eaa0e1b677fd4180a55deaebb8ad33d5584d968e71c6eaf3cc221daa3f4c5d6348d107b65d31e4ea82302464cfb831cf4543405a0b6e0e20d8c08b8ec9353d172161a459416206760748c040878b7a2e4242051c106d807161c2d8620b258e80b98e4862872380c8c0384287ccc9c5f15c74c4924e8c7bb95432ae7d2e32628cce05b7f45c64840e342af7c673911137c8811156b0184164c4901136643db0f7de1c28239ac480030b239822237c9ac4d29801898b148838786169226ad1bac10c444e34c91273d93054840f3a9c004b4cc472748ba061862d0ba1ae081f1aac518c438306cdb555e9a2864c8c21d92ab118aa988323adcaab45c52cb22a47dcd0e2164755889f69aff5aea88356536b9f6819430b975ba575029798c55e15aa00e1f8f5acbd3145447cf1a3fb0b381ddcfb5c4404161e8820b269dc1dcf4544f4e099e0fa731111307044dc1b2eb836ae8c14414324b163c310446871753c170dc182ad074334e9ceb8f4b968881f1586f0b19495986c8b5c47fc18e38396dd5b4f197de6849e3d68862f69f02422050214000819e4e08b2cd080e1480b9e365cd0440d39b842863462d8a6a8a184ed872b5903907c389ab28216b011849c2eac9802450d28d600c2a77e91a381f044f6c4142fca6510a00009f05cad1b92882f72c1e0678cc7cc3c175109c206836e1cf2baa3fdf9cc76d2c8ef97208d01e4d84a5ec97743b2dc21b03bbd93cdd3346ae01b92e54a1f02bbd2896e76338700c495d3c648f6660bcf3f70103ebba4dded99a0c595ce3304b06720687877775b1eba2e478a2b5d0577f29c73fa4b1a5752da26dce04a6ffb7c93c69573ce59ade8184747c64c293fa6593b3b26fca01b9cad622f88be41d4a51ed74a6be83b9d9a1ed312fc827065f873e5e379c80e778c89a999ac12666abaf48aee0e2a9b2b9dac66b0271de38ca8a09fb5bd93ddcc154afd82b652cfe438c9314fdbc93ffce33f404ceb4fc900520c7a5de923d77232c3597fb85ca9488d2ca9405f72ad4ecd66b110d70adaf1dc0aaeb492a7694c32e7e6d51a264fad419e5a41567ebae9c53cd54f66ecf0d3bd3126eb25a84b2de669fac281a8c9506989abcbcf17218fcb0bac9bb361681f56bdc61812aa15a4aee999cdbf04356b5e3153d3b5086d718d31bdcb4b46c109ab5a8eebda52119b37bd58557d4a219bb353aec595c36655e65b8fe0a964959669e0c8b588ecf86d8855d54d68a27aad2733bed6f6fad2307cf579c5649d82ba7d98877a98e2a8e44cb7353d0c19aa190120002000a315002028181209c52281280ba34cd56a0f1400116d86487654341947a21c866114c4400c820c21c0180280310620a454d1d80093af87d57008e107d0f382eae4915aff97e6c010ff19c4bca31e926f67c14a71aa581f0fdec3c384c0a429db9435c7e0eea58c0612b544439cac7356348e7d685eeb58813a6dc52eab77e3168d28f46b2a33a886b6d8c369c6d8cd12a41f546baefea52768f8167673d449d7143c3c8dd076354a33ef0ccf465dd5ad3d965f9f214e97c9e9dada26562ed6b237a60a33853167900c8a94e3a141d803c2c08b9528c6dcf56cb870432db74c442cdb9652d13de599880b539508fef38f34ed9bfacf37f5d27d2fbc81d59bd89784a8eaef3706cc1fc63fe90719ff582931f9f663bf21873710bd3a855cfbb93ad0bcd0e1cb5f4bcaeaff1d52ead31cba5e41d6709eb0865c05a848147e96e962c5e89bd67c2d3c07e416c9d7907396ecc37fcf9230f82112393b9a53363e4b608113ef2ef61f0551a7e167d4505da9edf1e5a684989ec797b2725ea3b54454e64911996dd8fddb78edbb2941fd2b9740d5b3374dee34f1c53c55b7575621bd9d9bc44138a4d7f695e11ce30c3cb073a169b9a4aa2da0d0ae844c81d281ad5982aaa508f815424e91c55b217a4d4fa8dbe5004bed959a3752efe50a5f41b38fbba57491fc2af4701f3a05d08914f3a8da5ea9cae9111f353ab850b0530f2c2f0c1b0354bddcac308cfb7d38178c5bbdb3c4a54b7271091620719333a1241d33170adbc45eca1058b6d1b7e9e89df4eee2cab85d4653a9b052f82a3caa2afd3f283a30ad6f651bc87f75b0ad2025f4a252dde964573d08629ed56bd4ffce29a0c7eb2a0e8c798184daa538ac1e4a020a19e3905091a00870132078f4f78e8d1396984968950ae4349e2ec0cad9e2623f58de8e705a84a04ec11ed69181b30ca0dfda17211cdf0480b176423f38b9bc5b71589c3294a89ea21b157a27ce450c8fd78366d95f6cc83fcc975dca8a99012b70becc1119a3d7186b7ade561604251dadf57aae54e633109dec715da3fc89afb81b4db292851c403a85cc85e59e68d41d5f4c13e13e5fefbc9d1f9139262bff219cf5df41c134b0bb7f8a25989bea18420e19e801cbdd483a747f9d5de180459c8988248c69d1b86a37611376dd2fd5a82766a5f3a2a2496892b6412ce7c9e437843c132ef3e7ba8d827c03bc54fe366448d37f8a9a6a3c178e5fb41e8bfad9841d76ca5213e128150c9fe7829c3f5d018b22f4eda8f19dcde6ba443c878b739fb9c636330594e765658efa24974a0bd812842e8cc387a2b84f98d5eea8e80565e8a2a848088bddfbb9e1ba7e248fcdef89f1d8f43ff913cb258ac247087244065c053125a4acd62c0f66511fb38c48a348d16f6fac7a4425bb5f57e05c9f9dcdd4c19890e0e45f88e09bea42046b705e27b1d3ed108ab697d6824452385cac3164b121638ac187566dd6d963e5775bc022bec77f442b376d6ba0d7ce5d447e439853320957734dfcd3e3b617fa12d759eff61675c562014e48a3ae0584f5ffbfffffa3800f03683455428c27ce68f6f74cb2a26a1e78d021b9eddff676442ad1bf58573567ce920248a863a9fbac1decd72cd0e19f96ee91ff63ee3e9fbb6a31dcbea6582fda9b0e74d608577d28162998567733c1e8f05abf1f7b4397f7f0dd78d8de3e251bb38ffb45c041b35f1c17042714e3e58d3e3f5057e475679eb9db52d312bb8517c661c349fbdbf875bed931ac4f3e13d45f1861a7f51c82acb4d790fb8b086417c95f08724c26e1f9c8c0900505ac1d6053d9483ec5266a5d08bf5b5e31abe97473ed65dc7f5e544d64caecbf324b328e004022cfae956db54c9d4cc9c4bb88e508d9fc08798667c2cf81173582465b85c9eecd3dd78d88694dab70191c243c688955a14559cc0bc0a98980150496796e5034984b4dbf27d70da916810652d2b4d5773308f1ffafd12ba2f702f0c08579aab66ae5fb9bbe2411484f5c889f542205d7034a442d10a80bdc45cd9827ecc90d2666b645c5522f7a5e6ffb1185bffd98c26f4fa47254e5b3f6e73c8791828db59edbafe948b62d96e047365eff035c38aceb228c44c03f08c14b289d3c4bf0f3870d744f2e0fe5929c94119143b2f00d91d96f7024bebbc4706fa8f776f4b0e4e0a3439211bcc0bf0f5ee0dba3784a02ad56e9b63b234bc95ef293ad38f0b4be0d5557ab92bfcda7584424cdfb3fb744ab5a32a68c3c8123d903fbf5ff1ea750bd147043741d1fcd8a47c821c6707650392b0fcd35a84df178cc7b20bbe906ea65f076748afa2bf181f8cf82c06dc4fa1f49050cd715d25f1a4892a222609fa81a44237f8a5f2b4a25dc33325452e39766b82e3ae49a8eace19608e1bac4a3cf33e996a277d553e2f6136549182aeb566a4b74a4d2fe85b87b54bc1ab07e9515b437696c63f30f0ce82e198eb91655a3f7277ddcf04ae9ab07926dca85097e4a7aa0fe1756f55ad8985681080a05e79d887c4c5bb609e58367968037b0a8cd9abb4cf118785c35a2b6221749ab1e5e4db9c173fbf86d457f1ea0a93071fac4245603e6d247ee45efe738e8681718d05c409f774d73cf4cb3cecb94b4d45c0cbc0561a2b9c8cb07852e6c0ca97617539d3e6a022ef0b5f26b50d0f1b0e4b7a7a257f25e035e8161b555ec837e9614b37a90d6f917de20d336dbada1941d6cfc77963970395e7eb58397afc2b17dddc72f806d46ea3a63f853f441294c9f51a2bab0f0fddafd486b2a7efd50c729ca254b72b9287a7cbedda89461754223ab9483d44aed23a55402cbacc6aeb72e47008c2a4af8f2a89b9eb2ba38b32d90d32ef2950aba337a90d59ed995316b732c0152d80c2e62fdeffc84213115b157b3cd2e477fc1e6f1e4ed1ad8a78f9c50e50ad00d334beb77d3634df39fc58153ba26d106a972e60b4c99cdeaa75ff5c15f69db2e2c6c4c248bec2906d9110c914d61ca3db0003e66c47693ab7ce01a2cd304200038695ef495ca0316ea2f7c6916944d961c7863c5b7c342ad5c8089b5a6b472039b0298e3ca3e181820ff43885a31b5636a93fb35ab62b91efb4deb14aad3229750e1c4c4cb1a106056fdafaabb9624b707e596cf82f2e79f50972757258a3c6f6c18793ef332b2195cf4a3a394fec721dd709782516283a25c29a1001e36349d99593205e557589ea1fab0cd896c078e3a55e46aaca94f5e5accab943fe0faed6fd5e0d29aff3cc6a2dafb23dad48e724ccb4ca404436733d3fcb4d3c2c8dbea786615eaa6937ab03e31345ff4355cb46061415196eb1c0b93035632baf9e0bf49fae8547636f6b3e14d71ef55992819b03de9478d5f872a0c91e37b1931fc4fe756a0558394e8f2a5ba3167e6aa0ee872bd97c6a720db711a1e302b136577778c20bdfed633ca331a97360d7da986b3df3242d44e077e72608e55c6a5b251310f8e99d5bf667eb285f9c10c496db2bc1cb81e5a818f6b8b31feefe30ab7effb78443b6a5b5709fe4e940b8eb4e7b3466e9b42b7b207d17302fb42fc754ca3be3e709b5ef5945ca1b3c5c5e9f5ed8a30e567003dd518b5bf3ea8bee48fd9995956e6f500eddbe61ed0442442d3bc11e14d8c4bbd0ac071afd93d7267b9b41ed8fbc4cd3fcb5a9fb178e1548f03b2c221930fff2bb6503eb05a38446e6b3c968d49ac8f056da7624be82c8a013ba0bbe0eed0aef462e5080705637b51b8abe91a7691bd960d718622401948b9a300728ae56c4fbd92b36bf025725afc0be098b5c20ea89b1cd810fe5d8ab96df77723b4b26c533c65b0cb227068a01806e6fde1e3ca4f75d99a3341809ee3a956f219a1c07da907cbbfdcfb22d56e253acd1d79641e0bd642c1910feab51016da748f9df89f75ab1d6245db7b24271860015b3381a10c26c896e1c4a4ede7157de275194bab03785216f177b7c1ee651545358a4d8199025eae1a65a9c0d9b0f25cd5ad5c2ff5d1479c7008a901770e17833ed58a8d929d5372ca73aab2de538a5c0eab97e71f9ab3536ee35f4b440da85cd85f44bd5690a16d2b930a11d0888f8ce5344f51cbac912696bee2e563e3ca5d15f1f49ce45ffeaeaccf6d0360bcadc0b8e7f68e4d48105f6d9042f97c4cd9cd18db009557e80795ac18da3804a01331aa408f560113e38c0bc7da84ff7459e0fe50764b4a949c698c1b19bbc9d4e43887d367eeb51922345663abebcdfcc16a697c9e1498bbe1f6d6bce3bbe7b9f4354114f3bdcbab827f413078bfad1b9eec1ef26e64d170e7212cdb53e6b51fd47a52558ece7d785c1625e07bd5aa23865f86d793e1bb5ed69d51a770c560c5c03f6860b485b587d2c4b6def9275c9b03f8d3f99241a5bf5e947db8d10bf1a87229f2f60f5b2fec79709b433912b52d41df36667e75d0916261de4ce0cb7f1bad8fc793c8ed7829990e0bb0aa0bcf82e2c4c482355aea434c8e50b124981c595a2baa803a81041731b7ca92f423d45e7eee63c70adc163d0bda203e8e4aa0f2bc0e0abab805bb5a4eadf4fed43434cb7656aa6a2244cd671d25fc0b690947b64b51262d0318f48b0fd7157d5b05d0ea575fae153ef8fea5702cc65cccf5e5e603cbc443121ce795201693c5ab7ac2fa7af989469b30034888970a6ed36d250dc4e7c60d6bd8c23961c679c808bfb6a28a97d06919ddcae5f2e52c675baedcf2661996556d2e2e719c652c2d572c3927657507d7cb0f2bc84bcf254b9683e5f7d29f7764157251f9cf68856cf0e1e315af9e816b3cd9d1ec93a85dcb89ab031051ff211c74173f147750d9a93c42536a8ac35ed0cfac68fc6bc957d0b27ec8acf2591e7025fe23bdea21b964ede69fa67a75cf7bcf74acfce48fe1fd5c9ddaaaa31e2f9473eefe3451df6c4427b4c47c44ddb1974639ccad26c54b5e44fc119fae1f04dd3ebb018a67a13d99ad03466ab5af82100de747da4de1ca8ed86e92d656f01118bcb3b64eab3fa5882786985c5312052348b0719c29a908cf50cb6bc084359eda5246733dc7ff34bcb80ccaf2ede8a3a501423301f85253d96ed290b514c32da8e95e763f6f8f4596e26ba08e133da19f468b934cd38bba0ecd178f9d57328b75fe6899d7478f4a1b1ef12dd639ee8da5970cdd3d5b9a3db26fcd0a618f964baac90f876ad838915d21dc4a8b7e2187f93b6f7ee756cbbba6e65c0a773b17a5d05a1a0eb0627e32254d29f6bcc2137bc8171f9aba6bf0c14c252552bbf169d52aa29b1452d801c2fbc2737ef7a0c6eea75c73edbbc76025b7c2e5b173d55cf8a4417d3a9485adb282a77bf9c8657f7f42c8e9f73d3f1fe20da6816feb48feb290b9df8b728d4a10d454c8ebf50d647a640ba3d614d2bdfb4fec046f6ec623a93ed849e635362d23514d184a7042b5ae45e9de1c39c5f50f2b5f7e25e8743f1892b2126e28afaac9f6d265c4db114c9c8d6c04aed9ff2709034fd2815f0ecb1abb84a41d19bc93fdf1950379242a7cd6b32ab257e905210dad65fa89fb9508e3a51345856a794faad129447f9e738915f4b3508876e08957c7a0c56c2c92d22b45b928ff5f341fb353d967ae34bc010f8771f2e897ae13d447a82139b05e16049d1a50387e47204f40864c469f5033b1c9b8f4f81f2968830f58baa951c75570e430796d53713a8932b554291a3a9ad64425e25ca1f8a3d59298a840481533b4f46154812ec033082cd6b2b4bd2d05db61829d22ed983eb1ed18739b25929be7f820cccab4288f7ac046bc41dacd5944a03be4a60c08e2b500dab500ac085dd440e37d92c67044c715947ed2144ce6844358a4578732bcceb83a89b4581848b5e584c6a7de3c6946595e5835b310cbf2d1147d1d622e8e37a479297c6822702f8964949bf103d1abc2b347c78aba0616a0731fbbd44d6343766a8ba9bd20ee53e07c9987a9069e37367c45d68f726a3aae0ff94d13ad89154eb43c63137062249b74e98ddb1587b8021e5d8b18083845ac80eb6afa7d3419055caecfedfd4f96cc2b9ffc23330dab1270546a58090044f4e63a1450d82d81688965654d6c296f0db1f3272bfadc75b36a055efe0469fc99d852602df8042c0b1816e8afd64c2c09e82612075f0b8e9c2ac39d391e1a099c548696650ca3e465208e45b38ac3aa79d166193780ea3ea9a90c7b256996d81d827c400ebf05cb56bdb1f7b7ea5ad4a2a61979ca407c76eb012493bf104157f5e6ce125583c66e4cca58caa7a9bc084aeaaf417d8775c7110509bf469a4891cc7177a3669c692c90ae716c77e6473a5b16a7fe8485db3cffc4f45f2031a03b7a723330f7d56fdf760a75d8f8507dd954254ebf14aaab364ab5caa1ba4a300294a58cfb48b6e488dec4b295f10e622669be43cdd89bfaec4a30424262f5de21e40d5c73d5d3d3755335e26078612253bc59f7d5e9d8738bcb23c349aeaf52d1efc5602968c26e4b181c0e15fb66203d7b966496c182794e76d181169b0fb740621c2bcc7b34b32d9d38c642938420891de4fa02314bc9f50e68ed05fc51992d2598df12cc0326cffea6f054192d9b923c03812758f54a258fbfd913580442d51979ecca682ff66cde115f6af5cccaafaad16e60140e4a5aba538962064a0806d4be62a2efa6fb5e78815374bfe131a98d81c0376bc67a52f58f37274672d6f03e858ed766af871e6a5ce3d6991d036aca7e2edc38ea8b2d84d807c8bddc048c0ada0b20802ffb3bd3f7d9da93d736e879b8e9b1ee34a065987d6736c76c1c5e63a4351857c337edac5d9861cda44222be6a1ee827baaa102293cbc24ed65bab420101f144949671b9cbfabc79c9a732cdf9f7238a3b8c413e292b01996e802f86bcf2a2fe870b4f5d59ed865f9fde89549196ca71f7ad1101340e9db7e7bab16ee97916f49d68024eaa5e0f43af918d8a744c6aead0154704482b458f12f7374eef7a2e822f12992a55217455ec502b11fb67c8738fba50a5bc8590b1bd12aa0062edaf8ae823a56ab95345450528e2fe8dcb147669c98ca29b663bb857827737f000f7bf5b4e516644627fbfba5a13a2c30c3a509a005ce46de317c9c92027f7be5e05eaa3e3671c2d9f21183828492223fe0c08215f571c1af54d33d4f1a51b424a8c5a96ba0c384687605736b2dcca7e8bd6b79fd1761c1e6e42f9a0bee9370eb44304266ddad72412e86916cd08a2aca8ce49f00b6523acd653e36fe482dcd325ce1fd5f8ea916d8a5ee8de2fe7328599eeeffc443c8c83f653c81c59561779cca6403c03f092dedf6e6805a44a0eb1715fea52097ef096f00897447a1e68382c0208ba429691e252a87c99754c4879f15834fc614b23a3d12847102f3e6429fc3ef642c923962d3441eb08c9d770e5811fdb0705e2e409fbbca37ae35ace3efbda3bcaa8761b5d31c06c8c24fcd49e177797d2442f06efd8e77fc521d2356bd545f49b2bc8a561ec7d2ccb6a161c2c21b5a5409a647c23327fbbe7124a4278f316df0a5907cd350a3b91066f4b0d11bfa585f973c26b94fa36739c40033381161bb5f475ec0cd64c43a45f57cefd478a46d7e44b558f12228ebd6a0623a48bb8fc61a5dbd4610c9f816277f2110a1a7d8dd0456dee588680cb024595e9fd0fd7da1879f15bae4ec48fa0f32da853998e5a6c88a2e09077709a3e71c6539e804c57a69391ed2de97b480c86f6234039711b3dbb269191aa312be1370b148758cb52473c69e586ec27fb1aff74fb539fceaee9e18ccde909075b6429aab126bf9839a4acf7b143f58372e90e744f1bf8b313f87b9c4d4944ff07174a30afa84145a7b5cf50014fd1a982dda77c4227f0b788ade3f9ff955f1e92d98d2dac36941347b335fb711bdbcefbe22f91d7a499ae5a7502d533c3d3af0c25cd73ac21abd21bcf6d216ba630c5705432b70724cc43c588faadfe5dec5d8e35d035181cac395dd4d286f2c365f4270724ac63578ee8ed50c8d4ffa3c9ac993958d2d14e115bef45570cca231e4ed2c5c6c044b7b32181d18847dba60486f5bb5c8f6051cb4701c3d0b04c5238bbf2f065ede9612c60900af14c2c8d1058d0ba40cf92accf1271295f964a0c9a9b88be24ab25f42bcc72cbfc6191c25e0cfef73e544ea21efa5b3819c5456409ca6b911101b30f5246a87e3a1a02cd4d6f50b9276503e756b1330709828c635da8662b38e1fa3bbab7a2b220b7fd116b6d45700b0ed704cd61b455246d4b855bf43fe4782620bc85a4581bc6bb2ce8c54112adc067b04519e3b4d0940ea99c532b216f0f7e33ba95dd6806cc1a9160c951b8de42d064172cb8563be3bd4e815a5809c508e2c01f3440594f74dc6fb99f1143691365ffae2b4e22b641c1253064abcb7191fc65ace105699db7a616bd101a986fd71e5c345064dbb83e1213f95c01c21d48dd21f39ce70215e3cb02f1040f5d47d9354ad84dddf665394b9ea478e20ed9051e428fe0aac5ada34b27a5114266267dae7f8595e7b234690998317919050037a42540b52bc3e057b24dc9eac6b5531915d536c85bd478d61606c9119e660a6a01e982231d8e70e6997939d33ee33fb26e1db1688aa7f6399dda43d72064f0dc368e0b0069186ab479fbb1727b7109a355decfdbc5f34dea8fab9f8cfd79431b20f05fde0672fb1d1a1a55ad0d5fa991e3ac145afc5d7717668424713b577fbc288e97e382769ab6ea0aa738b5f3ce971023c005d96d988e869e8733b0ab6014b419aeec4ea40484e32e4d9f95c94bdc9a53d38ddc4acb8aaf4cd9f25efc4f66444fc296d82649df3967b21692ee2b3f4dcfba6ac864348d8068d65bb8a1656f96e065fae246de75c536e76fd25ffa80e794b15a94905a54d63efd71372d5fb554d5f75130025c169c2475f24909a37206bb72b6ee9809a3561020783c894749e4602bf163fd98c5a8e1599dc2fed9c27117cf0ce7d5ea7cafd3167e93d3b90f3b2ed6a875c9e6e0c6abe7d42f4398fea3e808c3b7174033a238c83965a581557319767eb5ff6898d3c6da8090192cbbcb2b13783ea16422d64db54c18d75610b65d3b62fa32d81277d4cdfffced6303224e50422cc0613c6ad73e39c1e13890278897a9fc662488a9962ffebba368b2f6c3d46958bcb63a6c2d89e5d8ddb85a6c98666f9a092396f1ad16543cce5e90d0c69a8bd517c95adebf7a7119a3c0d468ca28e254baa104634cf2f9ff63c64078a740ad38ccb0ddce88cd530faa262b7727499eb1fa00a2b2d54f1840c8d13b31a0efcb302c12c426a1d63d151fbdf32fc81f577ded8f534bf8af537ebc2bbdc824c3ad0b54bfca6ea53edc1a41b08ac8a7ab3417d5ae64757d3198f065d7236006caf6b477f48dc18455abcaaf39bcb2a217ec0c0b322a178e09741a07bdf5e94a3cb0fed4c557cc3ae4c8d457d258182371d0528558d42ecd45bce68aadaf8636e38db64b2d4262995e12c1f91189301f94d7c02c5da82d0e3aee2199916bac3cec3920524ded2eacaf045511c74034ba5724f93f57d00ef78d384fc08cf8e60c9cbc78b4d6a781f5dcb51620420cbe220991257664b029181c003eb9d89a88eb24c458b5d53542ab180176c69a2cec81fc0b1aa3577e9b67d461113d7190c6ea8ba6d44799cd741eb46b43a8a21b38d8395ec154e9277ed1fb49c36f5b61cefd8365840866a21f30bbe8cd703c41ffa31418981dd4a9aab220703d8b5de65290ce091b8a492c6c1d29c68552b58a15df58b37fe7a27648146c45d10e276c9cad63f5d22d98cb352c470e8efcb858db881be27154be0e4dd033c638d1cc49541deb6b90e5d878de62c58fada187452029f7bf314b3cc7aa8997aee0a326e60cf05c4489d40475d154c403c2f3924b2a85fb9306fe0917b0cfdc1aae13763671197dbdaae78bf335aea8643549df88114b2e2a9c64c2f0e58c92b77eb52d399562977615c4823fe17c33dbe9d09f62bd2f3faae9ddad315e104c5e6312d07bcffe792d866e2b5cc9bd7773b849776fb5e79df2f102a48c4579a0b64420f42aa61024782873cd1087b5f927c301fb06cd9d844b44dfde456667534d2e7a9b1893eb9d020ea34ec99d2ae9c4253e02ed221ccc084159635011ff1e9549ed5662163e43a9e15ebadb0b38fa2161a7ec29fb12568e763a0ad11abc0a8c6c3f41761bf2523513114b0390f8c17a4379c26bc66cf1afdfade28c5e47ae53e36871a57998278771fe257f86643107b93090834ff516af5ec7b49c2b2ef391e0906ff0c8567f4c8eb082d741a3e9f4dade60c97e25c14d17e24ab234d046217af976dd85ae0c801db0c79ae2bd879ea91ba10bce8b456a6c15f38dbe2b4bcb500bd0b5360a4cae179a71fe6aac4b67410dae6b2d65240f4fb5aafdb43888162d5e99ad03e84344b11c4e6b3e4cc20c12810128bbfa01b1304a67e8fd97937f4b6a246c190c9e2ddfc036756b91c91ddb02ce3f04b4045281dad8c70474a220d41a6b30dbc5628564e7497d6dd6b1eb67be7582a3c494a5a26369a6fd1ef05fa0b4b0208567e0eab5203551bf26b4da7daaf62e64f41bed47ead3f59441698f23d23cb67f0deb3c2ee0498fc242adb4dfd3509f0cc4a31484c239c724ff416194a5372a1b0014a96443476c623f0acf8cf7a1d5d7cb8f4e39433d85000a4ea46e9125bc8fd8b01ef1dec581680c36c0e3e867503847626372e8f465febb14b92357b4f8a0e2c71ec372305464dc80318c7e91422e95923182c9aaf70a85db149dfa605184de1d14a1cd5ae171eabd8f3204c5c29e5645701b5683e5615186aabcfa838894c4688898cd2207a88888349ba2e5315fb679ec933461c60fede983cc09a877ede71ad5f54353257b9a1bece7b568be2b2d9adddc2ab2bd1645912c7b6d15e7acaa3d0e762f21abb72ad02c2f02c9141ec32fde3f0ab813e68ebc1424254860c3226d0b88e8c959b8d73202da45f5903981fa758a6e51f70aee60314ec5453ffa682042ee229c88196a3bce40f90fa43ef301c3d9334b319e84a95122d109647b273c6bd3e235e305c400e497b8cc7635a779a2109300e478d3aeef1b45aac2e8901458494728276c1de93b440fe65bfa7cdb3a28a0e2a6b8d7481b5ab3a1745a8db60cdb224395be565738d500660e74a3872f7f0f9b1dd3092339d581cd92118dc0a55b9ac117cedc0d2006c0c44aaacb7e684587df5797192b3598a0b36cc0142469a4f0f70564e3c75155fb885fcddb09202283bca17e72a019f9f2b1b1ac4a2ceab20901b3764afeeef4f1ac6c8ce0af7c97c01548a64ccf3aa1bb0c903ce8ebb44d9a8dd30cef6c79782a82c98478c730828cdb3fe92ad701948899b925cf83b4c4cb381ca30e3819a93bb492241c1384915572fa07e24eef8d65d5a8d5314d415523d219c664c52cdc31f6720f1c48515916e0b2c9239ad3b3c27bec5a3b6fdbffe3c8dc0da90705860854a3e2b59dc5ad3621217054e5d236c726a785e73cd9179d63fd0c47327772164f0cf80f60363c816898f23f281b279059e663aa152a16ab51a5a429a621205b0a7f90aa3c4e2dff1b054fcd93af4b8e249a609de1c5176a785b12d101370615af57a58d742b1d49efc6b09e1ee535252db619cc049ed2adbd9211f379bb06d52cfdc40f4764d139f53c5b65d6436d13d73b481569838e3bd1b44bcb8002864fbe7e1c11db33347afc142d3373bb741d31b6be36e82767afe8585459e618f49a31be56d119939b349020f47c747fc23821e651dfce5e7c9d2b0fba382f9b273a6474249d316b835cea4bd8084f6c2890f2346693326cd5aeffb02485c964d561b07df870c731f18a7f8cc53de964f334b2ebf2d8558a0114d0932c1b06d02f216fd2998dd154c2ac4654e26c0ac7116906ce3b5c5e53aeb3a56a465e500fa852b5ad7065084903fefcff76dec3b670e6df6c8fd273f8c3b8b33606fe52ab7ce0928f7b4d20297d2cde01a6463baff446ec22899386293809d16423231a78ab20dc5c34fd39eacea7c80f3bd66fcfc4f951914966fe3e787fcb2470d05a9b0d50dff8bb98c238f48efb417c47fdd33694429a92b721d2f9466975d14927c1f57f74431dd6ecb2de10db5c2db6756d731ecb4d53a710e095ad630f1106dc2aa109f6aa146bb4286ff1dd3df10aaae9103191a8616f39fc25e8bca8dc3a6060eeef8775c86342fc496e18be385e93a0dbabd9d6eea04f8704c682f204629c8eaf84bba02c6f845bd789c2ceb307c4cef93f18b52c053ccfe0f91a580d1862a9fd07ff5691a63220e8da4d8606bc6717ca9e9db46ec3e067fa342f5d6bea8d1fa70ee09af5e344ae82e743af0feb55060fb58c14175c2fb92ac3e5672d354c270da1a1c179c816bd1b9f1369308f5550419e1086f8e85251081a530153117cf094364e74d26321a9a35505c060b7ccadef3be13a10680c78945b97db88626b5039df99aeea0b19e9e73fb8970e2cf7dbf3d6516f18fe2e783c20f5390b9ae00683926c639c41be4d3a0ae23cb2bf026433639a400413ffbd128c2d2ae4881bbb83679dd935f09f95d2ca387f8369812dd100c839ea189fa6b0acc711cf57029ad7914cba159fa8d426d646cd86d6aebd8f63a4f9fbffb1291f73b55c3dbfeddcde8e669349d9fa884cd11cea5ba24122ea0efebf119fcd8e60fa5104cc03ba2204a73e3dfa0cdc1e75ae158f5a1a1f1222ae3f8d753b3c82c8902d7a31eea7d665cd300582237895836231d39c50681366aed62e1bf656662d715cf5ede9a9912ac1c70d6e048dc41bbc647736028d784e303c62d008ec8870ac588b865843a2ec83b430a2e13e16bedad4c8d7cfeef7f6111366d6c3b086223b782c8347adc1f5851a24b2346ba1e6e98cf8918d437f196d780d02fa26b4b9ae7ccaae7d607cce4733427f89b7a0adc271957924690293090595b9c0011b8270bfa65e14f6c386cb58f04f35f81c2098151dac6c384c65dab68e4a444306559e99d72756b236d7903378c8bd92b7e24046186ec47a336dd5abfe99207daac89827782530be56522034405a06ae06234be6be05bb4ffa7cc921b916d39f06703579af9e78b0a07a5e112572e075694abeb3fd330fa810ded3514f6f1f9f0d59132a0bd03b3750d14172434b3905e67415eacd2ffa6cff6db74a381f737066738a3884c8aaf0100a6d38272e7367c8335723d23a61bd9414ab2699fdfd495b72d90bfdabe8661971f1b1c2bf1633f5170a195ed97a8066e2505405d50e2385245a1aa2cd34ebe9516da4bf134dcaaa41e17886584e8768fc7e3125ed62324602ef989eec3454811c886802d2eb1948d406c6fb47235b9bf03418a48ad073d368302b87a2bb6929a795d9aaf400751f9d190d86acc35ab72e68bed12087d4f1d472f995299139061400924bfdb21142c059f76070764a7fe312c13d98dda8a32e5bf4148bdd4d9d2bbcfd731a6764b17b881ee87be5b7f6275eeaa1cdef5d01557416f6585b87522958b5c1c063b009cba5f0608382d2276262d735785d0d1831dc6f290311e30a6ccd8b921fd8a7001f4606610077030dd8c5f6aa23f89aad5c055e47df0077edca3847fbf5c6e79fc48956431481098dea626348e703da8c4cbb45b9cc41b6057ad3522b1ea43f74a7bf3ff47b9fb0a752b4690b046b7889728487ca631c930c4296e90412163d8540d92e3078db65f59195045d36527a553f3d7aa7b3e70945c0e5bada8036f50eb490ff6782cb3df6ca0b3410443a50bcc3a4e733daab956102fa0d7fdd2053ed44c16f0fcfd84228ea6bd5bd6b5765e00659f5f75211582779ad3498649a7af18b0a49a83386af756a764948451c0ddaee01a3af87535985290d90540f35fd6a4c261b437c48588ce0a12691fef668b4cd186a61ad4310bec962542446647e622bce9895a98c93388e51514fbd8d77dce51892a181e08172507703c356f075c70fe8cef8e0cd768a53acef6c5ceb0d7700cedb52be9ede9e6407ee0484a2dddbb7ff7955c763363f0cb63682f68e039d926d93d61cc4c3a142bb032445e3bed8045846ac4313c476663c90a92d2d7304732b8054c9d74d93f9b4fd31ea18a5b0f3c7ede5f999fd41d863b3beded17ac151d28e9b42e48acbc3f7fc36e2e595bce762bc69481bfa3c63240fc1ac8ae2a79e2bc0e6c1a6a8efe9a97c3986aff71f91bdc824a8dfec9e4acbacb00cc40136bd7f88a484f845d2d0c8173636a697b1011a95827dd57a10b0d4cdef2b85cbe80a3540ebccaf2b133c2660fbab6256b4d5d936e84bbce24e9808246866ba906394eb84151a8a183257747a9cb084a36a557c4e88fb8c70adff7dd24190f50f1235625d8b456ba8bd131a561bca53f22d22b494816ad59a26db4b7cd1228b6381317b3c7c596766887eb1c3c2c6e5b943dd1d6251916275b3a935514de466a2bb65d33b8f9994e025b58aebba8984be1b00a0fa9e2974ab241edb3e935c35c3adda2094577248f2d77ae330c50dd58301a3008b0fee658e4583ab48320cfc70e0061476abd18c8540fb448bd3642165b8980c0308101c4cc642f6f5e5f946cf214c32bd421901a5bb8482a12588ccf1b6e3d58022b666b355fec1192d51943e6bd843431f3f491665e54fd72acafcfbcb21bc721eb15a0ecfc792e0016990b98ec4ea114390b6d656131f15face5c24490a60ba2bf8be2e3c8af07c0e36693cc2f97a6f3982d3a12206c00c717470189cc3e0a9e4a011e52361f0ce3f03aed4a3398163e706bd645963eea34b6c91987b58b1d6a06ace56657c4ee5787b69d1afdf7a7aad610fcfa20462f96e30756c86f76473d42b458853b35fc85e3d34962df299d6518fe7f5cea110bc97e5835794594904253f4eab1924699937c86a210d8b7f0746aa378bd1ef096af5c7061beada14da9b1ebc9df7f3a11dffbae9724db84276ae3c1d1e6db258bed793667573e653bebb56b8a1ddd696adf40dcbc410c9890da4768fee44b6f2e16745a3f5f5e538959c3825f948135c26f488d6b54fd57ba29610b6d7ab2f0297a8e5118da34037ab7e6fe8472e5568428a4d02dba5ad4ec467602e39bdd3dd30d693b51b0da02584db6023870ecb3cc185f6dfa83b59c0182681ea799b27819e042a02ce32ca7637b61819e6bf7413bdea73b00afab62d3c1a02805b5a30a203bdb982544ffc2268befd24b2b1b8f824d3d596c5089111f474975b92497df396feea8836c9a819aafd68a0ef43a12086fba3f7e868e54d8d5552f29111d716bb21c233cf2e1a484ac5213ed57b3000ff7ac5a69a0d4a8f99d46e7cf11ba345d08d89867595c0da29ebfb0118f6f019945d7ac9d8df165442878ef9de099f0dea52f4cfc0e46fdda88b51d643b529700b9fe9960e6244742e11fe8dc7b1f0fad97273efde342c4c370672070e5c945673985dc98d62215ed378c481c94753fa81f23390ed15bc2c3d573071884ea329a6d18f76596826344e8158adcb23e27c27294c8a44e945614721a554325ca4cdecf32e272b0e881daacd94617c696144bf959826bfd57ae432e07ff7f701b81815f165ebcfd624b824346e8c5110d8d3ba2d2bff44309ce6e4630dd0490aa8c40460a5d19b40a1189e0ac50518b330fb72f8eb9fddfe04278fb674f7e25c3a1f5053f8d810c3e2696378e69ac62a4e89ebf71bec9cd092d5cf9a549e78d99b4b9055d0375e4d648493ec7b851d4d2f9ecd5c9a5c56ea6f9db47af58921541f2f05eb6c9b6a881368aafc60b8153334329bf2cbb4ff4ef5e3dec2f7d7ed192ee740f65e2567b118fbf24b1cb49fa7c5d490fc8335e7124595cbbc43a15b49842de84151c8c802d62963021573b44c1671ee8691dc22acb7ced1ad7599aef55360623bfa23682fd75cfa69124fa8c37b832a8bbd8e8c69d64c0d89dca1371947d0b9d637043c4d2a6ad36181a13321447d995e6007a224228e6d7da6eb9e2070739df1b0180a8c3399415c8afa06ee0098db8fb0c51d6f119a666c6a608d7b951f7f345f7c5400f71013500a0d0f1f88e7768e120085a04749b52817666fc3108f3ca01f139dd60ccf00ebb6271d67e5de2c8c8f7cb0dc9e0ab6fb0be913984034df4948553543ee325d5d39ff1298131512c5331fbcc0f50bb8d608f7d37acf27da3ff7f9ead18bd0320a9958a4001903f1630bcb1b753f315a25c3bfb9c5e269557ab4b6be74fa4b8e3c825db0b8e5af71463ea35e97d911fce31b7b27251afe6c44cb7a07e25aab4eaa298c79a021b542fadcf96499f981c98a60e81a4668cdef4684a8021324c6968e4fbfc67b6e454e0ff92f2d661f3ae0468037139696d2c3260214094cc4790a6611b58e5cfdf8f4fbf487033e1cfedf760567fe32d9f2d3d00722fd17971428c86477b389b4f3b4cc0faabfee32600419d965462241fbd5b4ec8bfa87fe678db8a450c92a7492e3eac5a78d9d851dae3e7186ec310d9315c7816b76f0fa55237aa5f983891e2051dc4464324d0c4ffbb38f03aff92b4095027c5dd9c7213fc44295c4a5f2c7b88bfd93a052c51e0bfb9afd1109099af560c6465c1e1f97eb5ce7607d916851e68f5833645b42bdfdced0f8feaf8a600068db51360910804f09cf4b6dbdfe8d198a336b0684e3a3903d22bac6affc04f3c8ad44b724e4ce63436e06a74e3fbbb562be033d25945f4bdccc417fb8a370c73a607c57fa44b7be637bbc111c8686753deb43d09f132b1dbadc9e7fb994c089709422f5ec0967c9631fd7d1fb660a554662bf4f65b107e91b862284ca34d3524daa9a752f8a24f8c3bdfb07c9902053c417f61b40cff4569d3bebcdd6000cd9c2f257d89f5873afc4a62383431fa98e3932bd164fc8f09aeae1219a49a960f5e7e028e6c6333d58351f46a34d8569996501b42d2a09a4512defef8996abf5199b625fe43254353a09b4bd8df0e0477b1e64daf53849b807fc41ece5dffee6f521ed601db64f52c1d2ec28bc4c09965ee4a80bf03fd45c4c5dc82f7653e2bd78744b7b7804aff023704a7338a5ac58ceb7d63bcb10dd0f6b421cc195b0e09001537a4b8921b40ee84c931197c5ae11974431bf8917d02ba743822226ce49f216898819c7da86dfc722f6eb9c6b9cdc2ad78785a0a1e83deda7467aac284b0bd02e9d8b3cb4cdb81b0583ff383e40e1b341351b1b1372c973b7be49b2a754f867536e4421c23a574064a32730643201821848c642f1dd28b870dbec0e706df6e692fb52feb559376e777d301e3a90f0f690e17ba79866f8ec3cfab86112bf63cb12051ee5981a4f8489544be0e7d413b5d2d89e2f751d2d271f3d9cd9b3dd3cbb8accc3beb9633b6dd39348a47f893795b9b4a87d10ccdab75f527d7c5cf6f93828b4f58ccaea34dda1362d549abaa6125969de3e50002c887aa0aae129ee8161182802d560fd190bf121203e5526fa35e2b300d864303233588c3083a0967bbaa611427df830e2eb3644635ee11a37ed24f26e81a88e9a31f021b64d57fa9d32023af223cd130a61d4c7f4518426c826697b75deb911297c8cd17827d491d4e465800f094365726674f198c8310774d8cb31a8e5fcfc66955760059b994166212691688a5d9c563b71e278621ebc145f99dc8543f2e2de0d07f8914490e157b877e538911707feee0dae1ff91d310e1691a079a2f26299f2ab0cfdb9ce34b0013600f6870d4d1c9b23811001f0166a27cb1c5d1883aa314861a78045ae05c7780377c47b359801c176b357224ad9e8a69abd94a362746a59a1e03a8ebfeb09db0f70128a6cf3f7956435d37b6b70222b7103f3758c48f59d5deefbb85f3993d0505b60be22fa816f7f3ea8e08361b5b72f10e47c1d73b682b9990a183b02cb0544628dec51d7f6adec81f2f3c0f59fd770028cbfa699ad7cb6f05a2792f850553396a9562a87c035e3d447c728a29fff2f467d9fc2960e389270f15d08d334610015e67c4ecece854ddbb03323220530a0302abfec30ea7b20d23b11575ad7ead54df87799a83e7223173ab60c2bd017e48168e2c732d479a18bd7a41fab8930e54826321f78b33913ef3549b1ff22d4192307a1a0e88415d815d13b71ccc500d7cecc8b0149db39a2539b4fabd7178380e3471b830b9cbad3118d911ba03d540025c4443031404cb3339068a2e1603b930599dad1041fb24e5a8b6644bca39c92020fea715045ede099fc5ff34f1315cb54c730a54f9a3875afe469e4e46e07880b4e7e832041036e075656081d950d1ce4e6dd81d22e1b4a664fffe1625a7949b1d7f535331be51dce44c5e94cdb530bb189e51013e17caf5382dc4377254f69a94ea5f9a335e77255243096bd6519ace89263cd680f0d3f81fddf44b1f47782b94eba96ba335faef18134ce08d3056d453d1ea03f42a635d385258d225e4c3a0a78291130eddb0dc1bb8ae2c2d9bd50c47f5dd1b218a626651dae9eabe42658a061153d2b7fc3350b72bfa740b3a81faf6bf62b695d0a06862fa36853809d8090baa4a2832c7a6cbf569ac7bb63587cec07e1b6520a0305a7ae668dbe5565e786b1a1c33e3dd1a5624d798058d66b06ee8fd6db8a95d09d37895163b1623cde2b68d7236ea0bd24c65848e39df74b27c54cdbd90f372d26d79b7b31a969bc6661989c37f1236293a5e3c6728694217e20db1dbf1864827cb13fccd6a15a2cd48354fe8005be9cf97c3dd6b6290bfb2061a356758b806958511f74c58155eea3a4338104a1e5e685c6a2a88ce1e7398b6e8f1af80f32d18d1a09eee8d8f55424cb0b611926bf9e9b174a8ecbcc5c34370e52d11b0e89f3eb09b89aecc7a486f70340ce342db047bae151dd56fe111e15f95ad14251f97ce7d7e5e9ea433cc31e0a003aab19748b8549254ddbc10bb6dea49867ec706eaaf00fd577932fd5bae29ddafdd756d92f7a8d2858641f567bfeb374c86c114ea41eda0b9cc89ebd46053acf577ce912af981f121625f505652e2f2ef9959d1a81f59da7abc08a839bfb8fd959f3d1b48c792f167fe57b4f32e5703974d9860e6f058982fa7f43ffdf072354f433b3e5d7091ee56e9fbfa78fd68eb4faf8ca544dc5e007cb4c9220ba71db2b743b69fa75a067b2ba1e61a0a5a000ef699248e16d49412fc0a7c56236688cb07ab79465f2de3110e6b2cce8a617678d1b5fc65edb08eaba03478138fb006384e7a414bebf6f3541ca012da3c3cafc6841382cf3e24a5413cad21cc2262864f68924760bce6b0fdac55bec867d378620647bb1580264a3c9ac1fa43a73ce0c55268a3bc51749877234f0b8d1c84e16aa11f427cac321ab64da8be7a46924d8ab82f0815e73aa6080a981a3e307d2a42a99681b25e28376ef01ca109c27d76fa06a0aaa7abf7ca29e82da2f4631c164872b294bd7a5a1378df40e2038d6a59b5cfa4825659482959fd64a90507a9aca996f8ea2b1b3aecdfcc7c8cf34dfd2fbdb2f80b6925807aac6f19a61268f3f8f9866bfa17c13d1f6062e31627730c9a60be93498bc6dd897584142a47d601e2799f373cb5c99281b248525d41e0bca6bb2edd92c31a74cfd12a223d328a0b3c63677c8dcfec880fa6338ab3b629563acbe7b365ace71394f44f7e553749bcef8953a21ae74684e555a0e01a90e3049454f3956a0cfb3859faf0b2a088036f0edb4f4116aeea0d14279319ee429d62278608076d178717fd334468d0bb4304b4a2d58f1e29650146a0ac2135a7b403488bf606c783dc63ee184bb0c22a32594fe908d68bc36aa4a20a6740b6c8b3a1003a3cf70b5a2ceff603b1d50ed2567c47bbd51d7bf589746d52548ea8fcb0c4e7ce02925a0d90a72e23dc921fd8cf76fe797db519c841790ce6f5b250ed7a468e82491e1c7730596aa98db4fbce61e117387ba427494357d9bf6340b120deeda6fd1637aec046e96233d6384f6234c26ddcc5be6ad9acbd7e8530bbfd98a1fc209abac28556ab0066b8bdc144d96f63d562d94999a8c4db1dba442e117e3a8da4977c529d2b4e8ed1cf668d7d9841cdfd9e770102bd3fbfacd70aed70bcc5d66a2af97bf933aab4d5b25150a3cb23d9872bec84fa15f6927b327d8b99c5994329260f8be080d34f1c08a31b7f57c0212a348d5456e9379d0646ba9fddc40ed217be3ef95c1be8cb201602c501658757cd1ac3774b9ec83e9b2f53793952e67d88198696f2be13e0481447b0e549868aa9d626e79dbf10eb7bd588ca6d83b8c84a1c7a826524cf875f6361d69e2ffa284b4fe5a59f746e041bc2a507dd35d109dfea09284c998ec9b8db4798d3f67497eff6547683e77636506baa80a64c38a7dcd1e04c6c85a59fbf2eef8867b68d56a63b3b97a05513b7856b479f8f9cc19b9df82b450df9a7ead1120d0489b8c4efec776873df53cee14fd346211c7faba70b1d916753dd539a39f28564c0f81db3df005e7d7f7aa75bdde2c5ef950320821decb7e559af1f3d493d455427b7a2663ea231db8496d882e4514e834f147bd0abf90f88c455326546b63ae53f46a70528231762afe0982437a03d55cfa7d7942b92bb065ca9596786dad59667e41c648bd11845db607ed34446af52d5b904c7648e3651efa44632643bed3cdabac261751086441bc1056d9beb7049265142fa67f1bfcd7f53a9a96402261de918abff4ecab4e1f892aaca60abff64602b9a36a5c3db1bbd56f7d19dacf413b7ba6d3a34f14b8794a2000f076a9d14e76b07dc4e935cb476b39ab1971b9551708d6e105594975075622a7f9e8419cad9e949d198529733409554f9a417a57dbc997f687c02875812927a63ac7ba20cb01ab62d5ff7a07a63f1865f351b1a96c04b879fba0e0e5b8dd0eb416720e22522c87dc24c5a81acc0f049bef6fc9042fb0879cfb18990dce6021f5f0c388c9f47e9ca2bc620f8733d79d9f22e78b3e10d8999b7dea091271c2173ba4127ee2cfe8a3d822201cded60fe80348d1da39bc3ace6e7a06fe3f4d59bf74305680fcd2a7ac996d0ad8db0c9f80c7daba3a30fd23f365b89630cae3859f9ebf456c5e6eec80d8a15dfdfafc2397f845452458542b29fc398531596022131c453a1a9d01e3ae648137221bcd58827488cde7c2aac286b9a6da4e1a0b76875218fbb1cb0ab7dd1ca0a39eccee6482da315e09d9ef62ba06f8a7211600e08c1e8f2b5e58e5ae05497aa3f94ef1cf2aa04236e3da08387f87b392fad20ce264e849ca9131ec36bf1bbc267fe257e8d221f9e0abc3664a44302c1cc1e8aaedd3d944f3c4cf71475b0556b1e2e2db163f6775820e67bb2ddae8a5e022aebee51aa881864a2d7e79a0bd993e6c391f8e6cbacc3d7754422e30f9c794f96cb5fc738578f64d52f5e5cadc0ea82babca310ceb2650450b0ecfafd68f44624568d5a832ff0b20e09b267a40743647510713869119a569bf42f48aba5befe6e7fa5d1d8ee8ede73d767be88945c1cf3d96853c8eb63c4885df9fba83dc2e66301ff28a340d81ec72dde02974ff5b7d2ee8a7d581c44ea1c1ce3ed1bdfaa3ffc876341e03da44b67a5f30103ae21c8973935fc0aab331d93c4574915b608d76da0168727b24bfb5d039f16254fad44fe99cfc8bad2bfcaaa0d407fb9eb9a2a04203c121d5678dd8e266041818155cfd33d52efae1fd632fffa0a5ed6ba15fd04f4b4b9b4829a594014a077c07e10732bb83be64f45d23b7f66bbf8cfd8f9e7270c0f880f0c13fc1f8e2eff0c1df4f8ee0870f7e7862f1b4f706169129a810ae1dc778e0dfd37b0bb2a74d14dcfe35bf8e42969569a83f4dbd5d6559bdf9ce94d5d390d57178cfd4243eaba724a829095f8fb91da1e4de7ba4db27b8285df720fc1a08c7ec93238a3abe444627d8b0c62b8f4eb0b9d5d38d2290579509631ecface6168e80cd11d835c837c3dccab2f0471b3bf735d0de4058061394b34f66c0a3e35413e998a40e71839e6adc10403dd54eb4aa753dd553f0b5d65a7bc3d38e4c08d3bc768cf58f6abc52b9b51fabd9966fe9ed75fc62f821aee35cc7e3c9ad2bab59a683807429feaa46753b5e0f28b730005c98d9242bf061891326924882c80e7e6ddb359ededbf5c1a875bde0e2dc6cb4f07bd36bb7353c8b0f3a6b627fd65a6bad15f7cfc036cbbe9df146e2c70f204076b2be3b353e176b80b3c0730bff6d81b4acf4cb5a0be1b85bbcf3b995f100523330f0d4f6be1a8ea556ad9165f8f55bb586036cce7d8cc7d1aabdd4aa25b02e4d02ebd229abeda7669d0ce726f80d6dac5c1c029510dcd3cf248d9a05320aa6cd2d6d7bb75f5bb72efcf8af12291a5823fe4d2bbbb6755f144b258cb30d64be9dbcdfacdb47472c64c73e6a736e7ad3edb76cac65d1cc4753862ceb930214d0a2023601a3149001d7275000a3f9532e46f0578c9dfc35b2cce24eb06a955ccf2fe355828fda9cab439a75fbd8e68cf84d3b962090c38651bb79171f7f69635f6cbff8a18de917dfdad80c6eaf4e38eb56e7577d7ffb77da3e8294195906c306179ef011850a86f0ece42f21cb2c153da22696cc5a40450f3b12e80187157a047124070e36781c31050f37808245490d0eb04f73c6d397eb09aef1ac083205fb21ceb5fad32f621cfe0786df8ba999c726aba3d665b303f1e627747a0c19b83fac09d0ef0b1e3ce53c05e2183164903083a71e846e9f0c51c4c80f3d45552058bbd8113c4de527a1e38fa159b6b553ac9ea6b449ebf1c4a7b5fbb476ef1dd3cfeaf9593b8d03b45b1bb26e64c0f1a7ac7ed39bf0d49432859f5f5846986526dcca1f5a1c9ac29e9ace6c5712df7bef88c51c66fda1d5187fdf067598453c5e1df690a8d6a166cd6054e79cb32682b4ba6e538b1be1bebd1fde4fdd7fe5a2c87b7f5576466a466c34291fae4240eefb330bff4d89d15796d91082480c423920424baaec1440870f328841880a831876f27f7e34ff49099e7ecfff58768ba8a136b67bfe05f8f4fc40327a84d8dcb7ef06c2b174464866e587c183a38fd1fc2f2f7cdf39a8d9ac7fabf2dbe8f903af39a3076eff9ea96ec71dd477bf272fcb6b869d1c91ca6b9262bf27016cc06da469d61b63cc736befbdf7c390f65fb3ec64572120bd5ddc18b557773297d77e1e1900bd1fe99e58b4c14b79cdeff6ecf7fc6e61ca6bce18c2ed93d664d226fca58ec78e826b43e33205244ccacd7671ac1501bbaccdf9465b9b1dc297a5d602b3d4d030cb8b51d4720384115c7041b27a4d4d9019d0e620a7d6e1fbb64eb5d63a6f334683173f38ee311a94ecc394680193b28279a131c1cca8ac8da9d141a6a7d65a6b513a954259cb42e6a47aab32594bb385722b4b0803a3d76255fa1636fed7ba347739cd52e79cf3b6914e1a8cdea8a6fcbe128616d285b5e20b6badb53a07d9597f9a73fefbd9d810523ce79cb78db5d66aad61526c8cc89614c1857144b82f1cfbca594b5a783efdaec5649386d941b77ff95c6ca3ad97405ac8adb5d696a4081f88dfdfb7dcd27bdc34abf588cc2204a336a6f306c2684996b550ebf04cc31cb46da3118d4cda910493c26f1882b56e5f873cb460e90b5be86f98520cadcb7ea86d18829f5b5926d270eaf21b5e7bcf348753b4160ad2fbd6edfd187454a9e733c5807d1196c0a538ca5129509e6528ca512950d4ba6ed023d032bc85fa535cf38cfef0fb298a61f8af46ad0ba33728daafec062d423f128af1d7637571d6fb03437124cb11c985975e604c3127544a86856a8666d5e201b0a2f96f844dc3b28f4643639a270c9a9999f3ac79cda8543535231a9b25046714c3510c37a862c18265bfbf2c462199f0ba00c1954a8150da047110460778711396a27891b339d9e67c5956dae498c8ac1fed7f502874cf6821f47b7e348cea8f8642b5cad68806f821e4efef6e0901df86af9a647461eac9330dbfd0fc6ab01c7c347d636242b0413b79cbb26b522f4f8807754c0275ac9ad42cfc9a5499994935a9fae6fb5dd377beb871816063625c63cd8538d4ed8bb8551f85ac0b061463328980c3fa000a6b0948d0c379d55cc0023b0e6c80f78251a6b28cbf1db99439f9ecf6b999e2e8bf8c17106c3aa0863a8113608c508a9f79ed480abf78040094ff61c8535fcd6689d417a3dc349bf37d8b6e52b550697eb4d048c7ffa546a18f96226394314634c0ef83955ab539379b138463fbef8f4446a155bf67d701d7eabda1a1747b55939a6532aa49d56599ddc1e12933e5336576231afb94d121e1e987a3063976fdc38163e9b742ff56408d0c40d3ad58d19e90d19d6474323a9b6361341feda3d9f40fc26fac24e56c0e89227db48f465bed46c0810901b6eed2ed93211cba88b58e2433d62e39df28c1efa357f0fb1bcbc6a6f2e621373588228a284643bc4c9c87ef2dc3b4e29573ce5878f487c42946090e6a759cb25919f61172f3c13e9687e1a752362041032860288e245814a2607fe6dd2147512884167aa549118c1ff0f0f0f0f0e00c8a63f8edd147f4097dbea2bd41739f56098f0f1ed3e5c1390a1f1f9f549326fb037d3e1f7d6586297c7c7c709438f84d110404431004c10f0bcf14599a4c11a4087c1a53cce0e3e35314040f0f0f0f0fcffeca253c9fcff6c12fe8fd65bdc1265f91a813a3682c3c4c680de6ffbe6f6b2c3c7868c44b2ea492248bca717c10144752db28f9701f17d24d9491cfb63da9e2a6cb94f4dffcfa6cee0c8e70d2c4081c4030c9edbd7711fbfbf60782dfe62187bd73a6b277ce5496eced43849224488670430811c411208a6490338f11a1223ff8b077ce54f6ce994ace79ef9ca9c0d0e014c3e463d91cdb77437ae0e1034371fcd66b5d19efcfa4e9fb0ccdbba34d2deee41e4268a150ccb0423143aa64b2b2519d513bb642681853804579c44a18d52caba1aabd06139efe33c184bad53d43f16305d8588d45f15bf4d6c8566d759d4aa0e76bc5ae4720f6fca16de9afc935b28cdbc7af5f9b39e39c73ced78ea4cfe7b3fa03bf1d6a9d4d62288661a8b7fe6f84007dce9cbae7dbfbdbfb64f5f4a0ba85516b508fa4b833f963fc21fe10d7dc01fddf5e808d4d424f6602efefefe79d73d618875aebdf5ae33c4280ce796433be367fee99861f3f7ea49ef41c29a208bdbf9def7fd81d285420c58f1f3fae2871297c40f0e31186df073ee991e20a13297cc4ef9322abe0c78f1fab504f4f4f4f4fcf2e439b43cb81f7dd6779eacff99503bdf5c744d489519ef42ca1f5b75713653de93952ba70d2881cc51d298ae05f91a65f1b1cfce1f28334ca953ff68e1d647e8bab5b2b53badf5bd37672bf3e1b1d721082430c647e852040a80cc8027f4019191999b7b23004653a46c5100422f33100593b90b5830108fe00e2f3e3053d379e1b6cf021f33735c8fc7ae3829e9b1e37b69b16dcd070c30290b50359bb9799b1321064edf60c26a896f56f30049c9da622be0c51e9f80547aa916a349d5403ef7749b51d528d5483a9651684d04261d42cbee0e21a6a975bb86a9cc6699cb86a27b48a63d7f1cd5cb42d9cb3a6dcaee5d09677d098cb85e3143b05c7d2d10636b039dd2b21e7544ee5544ee5d4d84b1861c677fa0689f38886f8fb1c41f19a9ccb2021460aa3f8598f8bc81736f316b5cee6807648893e5ad1a22816dcadadb88ddbb88ddb4a766ee36e3270390789532653a865294ce39e267d75cfdd645d2693cdb1575259e71a20ef42ea14d34df9f139937a243c254147c7e6587b71e0425996752ecbf62ed2d396ddd9260fcdbfa3546a6777763b9b63f76ee7c48ee32ebe57ec5bce0b4fd57aba8382c621b266c7215267aba5c4b5cb17861ba6dbadb3735c1c5ce3b16d181d7d461f1cfb5eb679e0d6ae7dff9ddafa086d3c725c9dad63870c35175c78ad95b9008d41c01f7bdcc7c76dd350430fabb379b80065d9b6d95c803ade36972340b800213219836cdbd8137336bb7df66dfbd83caeceeeb16bd8346c9b0b4ef78099e9ab8bf4f492542de4a3dbdf3c6c42ece8f6b70eab231eb938b836c282533b1ead381c0e273a11ca29397275c4a124d6853f1585e8f8ad888311050e6676c5cdd94026399ba3419bca2dfe566f9c83f82568533796de6f65314647f6d5379f3162d81c8b592949bd593d84459da8e2167e511595a462929e847403bf25cd54d5e6d82e46119574fc4ac41c968951445554b525a9f9c97e5d6a9c8632d45f7debba36c7b2308a9af2b3bee86f58077cb7d65ff999fba55ff83502ca32326f215c968d6f7fdfb46a73c0a7d2f1a730aeb80bda4136c7ee20eba2e941a35b9a296eeea07d04a704a3f84773e74606c0e9d966097e5f0cda2ccc5e373bf8cd22cc40a3c1b022bfec7fead157c72f9b9c7bb302b0bcd1c1efdfd4f8fd9b19f8fd1b1948175254abc6f48d1b810516a98654dec450dee4e0ff82dfc050b225b1859581e0b971b985fffbb4454f531de745188620e727aed5770ea330232f30ab1968b415108c89c61473a30254c8730b48aabc7981df47ddd0f8fd1b17666e5ae0f76f58e0f76f70f0fb372bf0fb3729e0f76f6ef0fb3733eea2fcb9dd469acd152e5e20b830b6c0add605e309106c7e805a1b2bf87d9b2dfcbe4d15fcbe8d0f5ca50d155c041c8cf3ea2d52aa719765dfb971351bb7eb1807cb01bfff7abd48a9d44ce3172a5421a26e55a128ae6e55219fce4daa111f29d5088f8e5d6243ba0176063afa7d128fca11a4f0ef8fe2e7f8534fe8171cbf37e4a91b781a83e7d6bd5fc2fdd77d1959960029aab06108072d4dfcb07331c6a619980a328572d6f35b56ced97ebb7beffd18b5eff7badc6bf1bd17638cf75ffd771481cd2d16ea37b5bb7eb975d930e34c84d52967ddfe0bcbc89b8c02d4a08013b5e79952d7f3ee6a7c83638fcd7d4f6e5d65ca537946fe12f2bf6460dc6ca691206f11b914a849cc8620bb55ab10e956ade2d3ed7fddaa556ae8bc5bb50a0cb85bd6791b9a3d8ea52995ed1aa35bfcd9bf81fd354ef854df5703cb4cdc0919c031bbfb7e13dcfa4ee1e87b7f78c3404df14f59f56739e6cfcac491030abce28a2b7672484105dec9cfac12af74a5b4beec605bf7ef0bd08bd00b1016bd7f656eeac6dcd11defbd2fb87eef29cac5b97fc57bea5c98a428580461df243077c549e7e1188c894531acd62bad5906d3f1b2038cf6029465b01b2f406c7911c2b11854e0707a5a5a4b6b4c691d95d6d2daa3b4a65e705db7233a45b93a2f1d58e9f8c553948eff9a3e5d4f61d0741845e20565f6eaad45bcdd14fc8a8251d4f952096043089a3da0d549b5eb1835aab1c2ea51a303e8fe7d36477d347f584f9a3f2e5e74814f4417e7ce5cb052508177fd200c493d992555b5537b0aa3f6a26271f0d79830683066b9d5d382d1d57cf15e44af9d75bd74af28553afe13d1d5794141e244f49d2fd5069e92d4924db5abf5342c4bb05c6e615da48b827e6e3a5ee0a916a66972d27c6ec26c268c665d26ac87ad75d80b1676c3e2e8b99f21231df340fb9ebe54ddca7cb5e01559d7cb098bf382620998970a33a2f163b26031a2f16366739be69774d1d511a75c9c15c7c45d161b13ab5834e6532cf272ab88958d3f76bce5d61884d19dc4c6c62138e8cbebde2824eaae0ec9c9d575fc3434c873c5c328143c7ddd7065c250264c090c7732614253ae0e6cc8e2885560477638063362510c4bd2f1c7885362ac660c919765b01b3fbd8e3f0616db8ad18445f16358104e10b4a77f8f948e8edfe54c39ec858eff8557eb69d8d397da5f2a46a338b93aaf1abca49c4e3ae6276c665d78c53379d64532cd1569ba33a54d104fd17093a6e7d37ca9e66b8af97af3c5cb2dfca69101707a78be743ff095d962c66c7196ab4ef66c7e23f39a3cb72eab66049e2b9e0b5527416861ead96c347f564faef88b72359a3f2d5e6c71ae5634df6ea13ab95ad1d0d068bd5a318a57bc1974f6dd983ae912452857a0a971ca15d8c1f1748ad9df067fdfdfe01713631ad150ed543bbdf5a7dad91c4b237d1b06e6e5e5a5b4e261745534a2412280159ebe545ec7ffdae1981ae5a57b4dc1b1d403aa8681df7ed11985af9d21c5662a5c811e99f69ca7f779fe9bcf0edc33a56b82943a75730e311a05c77f9f8ce1c0f1eb57e5e0f853cca3dfc78901c77f7164acebb41d4ceb33705682bc6f4384cf7ad6856f0902396e9ce069981fe75a6ee1b7ad37dc03ca41b434f37a1ae65a96e15e38e3b454cef986f9dcc057cb5594a85270aa9420558a90dbc4498f1078dc3e294249ef451cf972aa1cdaf8e1082974bb2655849c000222c5500fa6a06d79819b306a87883c01a20b4243112a86ece0062ff841071eb0603b55298c5e1c235c9fb51e09884c606dcaed132644dd6ae9f6496eed79c40031a8b3304a66408505a8ef706c24e2e1d84d55f8732c2d4e860060dda62e30c69d7c6b8e9fc52cbe1ed1184f0fb0baa87df872e083319610d96ec4ad7fea9dc9de87cdc9fd7e0670cc3e3182d6ef7f4e368063a29028fd7e53fac5a4d4465f00466f0debba3f83847fb62f87b70fdce6dc7e3f4d8567f89d319ee476b4198ed19b403ad3d00419b319111c4bbf5cbf332cb347e0c83b21a0b061198ed1ad8620faddfd3ec9f9e8f72f108ef17eed9322b6f42b94b1b5442a8ea531744e9cdcffa2e0d806a2dfffa6e0988843bfff11e19818833ea35d6bea5f408cfbe53c60770bc0a80541124b84a82571838524ac134a8ed8b0a336450a6298b560831a6e5576b060633171c10f237c7801908e2148660054050eb0e06007315c71e586a11e52fc0879d9247ec8a1dea0c3f2821319a002a4a74991a22d30183de0054f6cd13193c10724d60a229d1245acdca0cb61019e65a4bfa3bf390032c4071d761002fa5962272489238c40421ae119f8d6b22c01525e9061880c497c9802045400192227831c9ae0653303d66583f0476f6decc10f0b84c0010c4cacd8a00187102baa0cdde003111b4108294143922d3bb4200614c0a8fd2ff7e55c39887c96c0b0c4c78e0bf0d4e08829a2d8e1086f079b256621e57b7d9e40ff3e817df4f1836f63e7fecd65997e13be3f4d90033e4dd8faf7a9c2fbbf9def6decf07cd7fb28dc27c10c1610d7ff00bba34f9b5b19851a61ca04b7dbfb5418f1f1c44f4f103d5877ca9ef17785bcdfce7bef9c73ce4b78ec0c74943b1af406f3cd39df7befd55be7d74e0000081878c839e7167aeef776e7bdf5a986d5dc1414a7e68af0932088608c2ffead738963a9a9ef3a4780f99d8f67761a6718744d4426a8ce61ac6c86bd314bf6947fe20cdc050a144bc025475cfb063c2452b2809341441b1ff95897c850c592158288f08116229c109b108103229aec60157153111dbcc461af37181091e39381881b4078198538c4491e84347091ca9315a8625032c4b7e3badb274a8028c2471e7e54800252e2630525319c4a663198461a2fb5f0f8c8cae7c3b91471058ec2559164c86622c94ddc8197dd3e49c2636fe164b74f92bc80c4969e5a1cc7fc09122c234fe114c14d34fec24438030ee324fce13243f60e90e030b680a4053db5b8100912157c40f8c88aef063f590179433400553eeaf6c910115afcb6ce1637a300252c6048063d45558e031e1e1e1e1e1efce9707c6e22432b9a3fe4d7dcbeef9cc1e8cff835b7940cdceaa1c36b5938765febbdb3288a6118eafddf08015b01afbec1effbb4fead8057d73b6a82b0ba0da2331e92a2e9e853f1d3f153b2bce51d91483f22dddb4bb12c5f2ccf7134f10786e183e13923a3ddeabc031b3f5964b821c9ae071625ec9614a440c8ae8917dcc0126489110467f03da7b0e24a0f3ad478286200961b20b10148a887243040711281b8ed291fc11f74008a180a33b08bad869e6eca619241c7cab6f2b1aad99cf2c791066773f6f76478c8d8646e594687d571e10182abdacab6f281d1bcb5de5affcaf6633cd3158f8e1faf7458143f3e539aa131080dceba7078a632403237195b96e1c1e3eac8e8b038672ab3c38506999acdc932b48e3f93cc7047a6461a8d4e199a0c6db422710c1124b72168f941922a2b604114183420050b152b3f331c78e0b26ee1321eff7e968e54967d8f651400cbb04e72b6d765c541a4d65f96398fa4fd11ebbff78eaf31fa367575f089c23d53b0aefd038081a716b7de1e36f6286459b8ffe2c031f2f75f5ab97f0336e7fefe19cf019b65a433f569f8e94dcf9c73977393cebb89e076bd3c2e6d64dedacd7171987796652888677ab37b5874ffdefb67e0d80ff8299b7d7863d6f593b70c43fe7addf58c59c1530c946a5b8a7620fddf1af21490cd21757d7bb9a59f877cbd6b6e696ddb423c05ad0a24be7e0b6419896619060aca2d9b133e8afea774ea754884a7d676712bd11141d8c3303c6dd6f0eae40f3f1dbbfd8bbb3af9d4b68b83c4e684a776811894652884a656734bff686699b6e5967efd658881469c97a914f98fa617279e3a975b5b787efcfab54d3f0a28fa9fc333fd7e6f2d8f331257d34f3ccd6ad482ab5c4c30b71ee9a5647b72fcf25bf81d16e28c4aa552a9742ad54a8b4abfa032b9d97898bd98ab75d1565a74ebba7e69fefc6f13d6b3ae588e182d36cbad2d18c545bcdd4a9a3f38542daaa082c5ff687e0baf1d16dfa209222a576ad6858dd8762c5aa8ced72e684513a42b49f3c76c61e268c1aaf9f3082e49996bb9d09ad57664ee92035b36f3a5030b002b1606150b6b71be76b523681214571e69b5722ee7924373209ad3b996cd9c71c9654daea6498dca9a814563d95835a450a7189164dd6a9ad4e46a54d60c2c1aab06962d55a3a26ad4538d1a53a38a352a59a3b26e63b9db99782e65399e7aa72a5033d4102821540ed50407fd1447a93ad074aae2d443cd5043a084504d503919d42c859aa150b3136a16839aa16628b5f34c269752b7d3f174b6955785a6569eafddcec49b11599839e827cd9f55e9f22111ef8a0e0ade9aa5cc23ce572bd10ec6cb2da29d75c1a89cae4c39f1700ca644958e7fbcd5483a151425499749ba918eeb483a92ae8a755121c2e86ee7627231f14af3c77cd2fc397f347f54268e1c4ce5e76761ae597a458270494e3122d97bc9ada7499ab27be9b24ce918c7604a5814c36e305a2fcb603d456c415906d3910496038763b0177a31a5de50a9d7e3a117a4c75f727de6e584d5743b1d4f67db55a8d468b3d7961e46f1ca894ce76bb7eece196fe59954a5f9738e2cce75e5b3d3bc4149c7d3dd562c16c706a306830603078c167cb5ae17ef459465bd3a2f2a55d69d6ec7e3e9ca53173d519a59a9564f326140d665b3ae55905b0f1d16e5d17550980c19e161c75399afdd4ce984d576ab1569feac7e74996141c4bb22ae3b00090141fe886361aeb4e0165ead375499604422514482a8cf4ae2388e23298e6216c5555c5d566debe96b8783d5d6ddaa5bb5acba5545d3f368a5315fbd51f52c6678aa9919b345cd3902552e6648f347f5a58a85c9734b2573d2acb4a878bb75e5ed8878453c9d8a8666665d753b225e916e464b0ebd95a47bb1aeba1d11af48a7ba2955e4e82a552ad00ccb199569774ad2fc99f971265dad445e3bebd265d9086aafa7afddef667dd7f18b3366985bab16de6e5d793b225e114fb76ae1edd695b723e215f174ab16dd6e5d753b225e916ed5a2dbadab6e47c42bd295568caeb49074bb75d5ed887845ba10fc368b5a0a9f50e4c666ba4867b17ac528ae79a12c33c3f3ed6f1f1c7bc1517a8b3abdfddd6375f4a7fbc7fee95161c36275133d2a330dc5ca746f17b12dfb7ac8ca7650127da4dbd7466c8cbfe9ed6ba19d1bc5b7ba17a40bab23ea2ece082cedbd186bad75df241a3b8c39ad8a70eb67f56116d88d2d54e08cd852b41ea9ae032ba66f258e780486bce4650d4c27cd9f9adf268c675db02db01e6c851561144fd1a9e60f8ed5b710ee9c573a7e58131607d7a458dfc26b87e64f25a240b141c72c9a5307eeac68e0a9eb968572ebfe0775d7ed060afef2229e268ef35f7c0baf1d10de052a040d428788a8103a05bab666ad15c89befcb2db5682e1f9af7525f98af1a5800e007c17c49b130f0bb305f502c0c7f68bed6dcc2e7f9522d0cfc2b1e0915820e41834454082a844e81ae5916034b6b85a2184da0421915ea7954a8840a81a8508be6f2a15d3e7806e2b945fa805e5e4a3d8b4fd6e06a92d4e4582eb066ac1a6b878a854c2a66c4b2a1402388aa495283abc9b15c60cdb20c7683b5630bab866331a8c0e1184179f820a91e3eaac9b16c28d08802c1984c5924330c0c39be785a4f594e3d541154100a874a62d1fb339fe2a09fe2a89c6acac882a85396d37aeaa18aa082504950b899534f75eab138f5644ebdd499f21ea71e2ad7f1b3545346aa29600c48ded1014691d437d388868e69b17fe4d269cc1cf48fe68f499a29ec5721ec29a8c0fbcb974ebad39413132349555951ed4e44272b3828e72bdea9288c825bf8a562b405fceaa2a8d675d25d1d18148bc3c4690a0c898e7fd4755c9b9154959593951391485249929a49aa0b4925a9241509eb826271f0eba2b0689f2fd5ba30017cf094f7ab634634f6c78c0ea03b0afcd2d59ad449f387f5a3f9e3e2c59dd8a8542c996c7a1422a20100124316000020100a064462b15818a49924980f14800d68885068523c1788435110a42088a128c618420031c0108490518688681c001ba6d72f52f88b090a94543125810405fb52094e054d4357382d0538373683e841c56a94d50560d69300a3a709262ff8372dd49e6594ca567882766aa6c7f468b830df84b9e9380e931653e5c7eeed71169d92159dc254112b408904af70bb82893e9d8495780f751fbe45fb462c664c2c8f8e2864c460fb2c79f129da7bbcd45ae2103ccb695acfe2e46d975fb7d80f0c6ee065428a0c7472935d78f529b5a70946de0a4b91124695440bbdcc9171cb7e38052af586156b88037597af0733909ecc23cfb64ffce5e3e98ad5fdeac2a781a8951694fb8429aae072e878ed66ce7f9e76db9914943d67cf10a18ccefabe86a884829671a3f210046e715f77a9d803972b36b8b8364e3e4f639b910b7f2e1e276449a7bafaf3ce5d57ed81c3efe3b31bbf567fda4d30c7fe6f558ba15d95a410a5c45028895cd4783d988b99483275015a3007f5056a6fc4b54996b25b09a32d809927a8005fd5b2c4edfb04dac4e5994e0d7018d739808069a10294153842b8854ed93d11a8d52a0d1d90673110e33f7707f1885278cc25213a47306ca4b92452d0432cffa868d9fa99c492bf197c642ae529fbeba5c7cba4ae582ae4b68f4e2342e44a902d8dfc3615c3a075f3aef16d01dd1138567d43c558d2d2c41bc80b9f9c0d376621b36574158d444ad25c4bc2d2a6585389eecdbfee9296d5aa7b85f07bb60c6f71b7091ce8097914eaf2f6163ad60f62cf3ae436567e62f26ed1b028cc459dae074448580498d1245335bd17913ee2386a340b118efba2e82c66281ac8cbc2fec3e2170ab03ff5820ca2c5c2f48feb47e6068ace0eeffeb2172f57f36cec4338840fb4c547d9f45ab0d74ea94b67e83436fe5feb1a6758882005179407a274e72822a43385bf50f42312189ff56ea16a16473733496c3ee8829a3852e4f2934acb608a5db2d1f9cd97e9a798c980dda537e791a9c1c88fc26221b239c070e9dbb0429613d15db973ddb9842252b5e26939dd772c642b8744456a7de20eb511a7ea395cb20f465bd343d8d7589355bb457898afebfbc82df47906bc5622b28f29ac1831cf36e8776eb37c6511552f11729ac68579396d30c39f9e4da50fe75feb5fa0d942565f720219ad2876c4b7dd5db42d50342d78dc37accc10362626c275c6d110e1622399bd7e5b64426ad34fa8e6cffef4314df8bc9bdd75b64fbcd75be28167a6ae7f158151342dca87c54ae18a6c93d3c6f1623d67cae73f3a5fb608c920b9bee3e43562f20b62ab3212ad75e3f4b6f977e10cd6942c9889c55a0c5f94330a423e815a13778e235afd5971c15d2b63757efa7764e25c01e0c0b8be40c60764dfd45b5308902212e604999cb845b7aca449ae1efcd92c0d5d5d02ffaf827581f0567e334884038c65f9ef77a062961f9d0250756bf213f024a4b42cd0a4a5cc2acd7cd87538c74851d707e6458195bba501b6d798c0b447096d34ee420859c1593ab56c4b7b4e828ddee1de4a5f4ba6b6bf76d5b426752bcd0e4120b5ed2b3824d46a891525847e4c259ff870e19bb0c84af5201ec01a28a46e5ec4c610011ec5dc28aa5832a0dbf03af5e9a7855eb5fb9a2c4f14c38500ccd66a49791278a495988c3f4b2bfd017e41a328dede253360c7c65970e4c400d4ed45c39dd1dcc554b635fe140f8cbf5bb19b1fa4b191d96c9b3f543fcf7403f413b4e6b4ac084476c5fac65b56ec6cb60deb1a73e6bd6f551d64a59d942fd82185a64652ec1fdd43da542f6e55e2ca8ff2656ae107f08da591878a2d7b3f838fd400d19db70474032aa492d9c9cedba3841367e8e65d091de59a6ee81111a011154e3978998dcedb24db7856e234f9b9091c6ed16993bf6f848071e3578bbfc3b3c6e61a12224ee092a815763b62a88e511229456e8f48b06d742781633e34bae34265cba9d654122d089c3d08046eb392c799c02546cc056520b59512cb099cbbd1fa446c3c550406e260814d2ef08ddbfc326c95ad4cd407d53af922fd78c61a04f5681302a4ed154f8566d49eac957fbd3561adb65bc5a5b7e1c626f24006d1e1e5a713c931692af91a6c307bbb230244b6c23f74551c048d21bacb49f6209f0ab2749683a067782aead546c562955c8a15d2b17d60766b9ea0f9a46e84ab50f3ddcbb75431b91a1466f7df5b3d638b736b6371344309a66dc12e8f54236801299c738ae733d716f6ae5b518285d76e20de3f1e5d1b5a15edb0db91c66b11aef931ecaf409712728e007f03b744c1e6e9976b6bfd9ea9a286f542f4b5ebf521cb4b143ebe8d0a4d7f8fe573412fd14953bc76635b9b815f97509f28653b26e82440db791bbddb06c09c47eaa51df4ae2aee508d2f750e43db15598f8b7a07230648f99853f4afbf2cf069dd54b0f43507041a2fd2bb4165e326bd4b0c505964061dfdf1b696cb7939ac32a8dfe81d83bf30669f6e2d20f105345a9f3b7983fefb47c018b29cb3b5646d26a1c22088ef862fc6c9c9fb5f381da2376600159f2bbf5997854e8d912fb25a6eba88daf5698d91556c6f20857cee155b19258ab2b21f52cab5c3b283d949f452dba29723c42fb3d4f3ac1f67f40b4df49ab6547b55c21986d3f12473eb8285ba7bcd60af277958dfe48fbb97ce86cda3745fe548554a8f2d8a19321126675326c0c71433a54cffee6d2f81d1d617f34f67ac1d9be6eed90fc4afc63c42449a0e11727e04fade7657a0be7e4757a0280529dc09e73b85aa16f5b1c1be774dfc949cd9fa792b9b339e082c5e37e4eb1a4b56cefbdf680ce8b7a5762a6a011fa12e80fa5ecdb7607c789dce050692342d916ac066d1a230b0e9475bd8498032a7415a2e484c24bcf830d48edc89ef670b56c4b7f8754c9381ef7bc5dfbf5fa5fb491421677e95ef80d19cdb55c32b0677e10ce48fdd576177737be3afe036f74268803f092a329e1e4afc31b9d583a645683bbc01b2c5ead3f69c6efc418b333e14e47fafe26548652cbe282edb494dd28d462a4c9ef2e3cb9c8b7f18ac0fc99add0b73eaba12ea5d6865089a395f165c73f90de6603f2b7e5dae8c788c0af63a2a6454e0c5f724248ccf1e6cfa14535df0667f76fa2ab686577741700bd0ab1f05b618c5dae97d1736128b7ac3d0562d937e8b77c146346b70986676ce9e29cd6bb94238e1e62fcec109b3de93551c0011a061d14847482a88a484da2885c9251bffd24611df2249a71c943f2698114e78903424569ecfa622a013ebed5cb498389d98410b38274c69bc6d2059bd3a4745303fa8d3790140833584499c3273c2a00a4a110e55094df1410906052242aee1a89a304db611ad674e17c237857e9c9af85f3c93ff81292b74e952f508c21c2df922fd931d5a8c698d056de271a926f80590283d5bbdcdaf3aaad5566d095d5afa4b9457e51bb25dc0e08857601675756c8efa1b0f0304e44c44d160005a3c07d07ca9c2236d9698d3b90684636e7495bb282406f8a1b33a37a79f884f1d1302bcdba4ed868419cffa980086ecb08962ac7d3731834ef4ac63974ff604015b768880b03779ef47a83e6b29fb6e8a6b703de19a5ed6d7e68b81e28aa1fe21f3ca7b0b04195a665103ac2be723beeb355b3c7954b4e03ae8261c578661a3107281c1941952c994ec6052216949ea9596d5c2be2942b2263dc4af4887a91248cf6b4ada2e2560388f456b0d58f70534de7cb75b45c18ed7cce3b434cdbf575e06920206e8e0899ccb0f937f3e4fd3288100e294baae00118b15eb2623547433cce47ef5c09c02c6e3fd8c78cfc642cafea800e00dc607edd9422886a726d78454c06cafa5959c1f048e0b989b5de7f66da2223da2d394df0c5eef25dfbb526cffee7db38def6139484b68eb32021179ebd848305e180d4786e66ffc636e3ecc73df113f9ba698ce4e399dee10345b862411aa5a791d126a8f23538a6748235d38b8ee4442dfc6bfd9600766156f567c48b6cb6f30aa52bc3fb4c64069abc01f1039a2d3f98ab198afdf45a45c610c4ef5743a424510dbbfad05cc1687d057932f4adf2cd50cade351367af07b5b25d3ecaae432a16b464f04c90a7dd1e8c00e4d3f43eef9bdda2845e3ce94db571dd83b79ba5e12a6d641b9e7f3a0e2fe6f55ec87a08489b1daae41865a4d1c93fb238792d0aa53111a233c5f9305dcc10f74ec7a33a375d9d0294ab9cc20e0127caa4b19e586d35061c724f55f18e932e5c6a1b4a6cdc7fea1e568e9db56dd4b2446f45a755df968303984cd5ee2b8455cb5b0219f9a8dbff585d879eeac32a869123eb10c8436fdaae130b1ea7f367376e54cc104365d5d8d27de9552ddbb55f5ae845b7b4915b2b1dda5f1e445dd08e83a64e73a7e90f10726bb22f109bca4d09e25a2df470cc1100f342758ea906220823c04844bf7aac834d24415f3d52e1c6177615e3241119065c25207160df525ce040f10ee445a4a6872b507e04a48c220ce2aa426e4aaec34ee30e405b35c3d829bab5f0c48efb55845db938e7c95804c6064858e8b864d4d6079e26727205759b20927722376cc0dc280561ea315fcc5919efb00b15a0c28277ba19b997385507b2efc07566edc3ac6e3892bdfb585f241f02e1ebfa039fe196ebf00f30c763ce42ecd588a3df50246ea7c9f92d3e874a72bb7a4ddf85ff1fa33e918039f5ea7b7a090051098c3c036088207016e0058037efce04f30c000e7d79ac9f12637aac5a82555fb148cc0a4dd8041b1c66a83c742df3d8bf21f39ee991102f00b5ab376c78c837c7c1e6af50afa2ed9ab372bbc4e216ef9f46864a8e2a9e8ae86479c3f3d939269b24175e4a0fdf4107d2e5b253c8de6822f4a0e07cad4133ffef5530633f96f2657fa7374240e75c1f1042c0418c86a91f0173decc4e88232bbb2eaa8946c9ec23bb229d273ba6849a28178f72b6d3bf7ef4e6366a5aaa245322b7ae4f89f6fc236b7e57153d0b07994388fc7811eed96965237cd852bec77d6f55f5dfee111041695a62cf66045557fd918e38761933a7ce61cc47f40802e3fd8fa6014e7ffd1d40604b9fd0576e0d1c01b82c03412f1339148fd978d1a05ba2960be466d861fd31acd2ca5fbcd49b24a56e64665a91131589dc345219ef546b69c2ed2bdc820e12fa8a9807a16881d1197588fdbb836946146bcb93ab87b13810bda31ccc4f533a599fd57bff035b55273caac2b3e32d92b2cebcad148364f64d60d7c2cfcdd2368750bbbeed63d7896fc5f16894658d0556899034cf54592a8dfec70b57ba878b7b75f285be1f9d21c1e32f4524c03e8a05646808a90429fe533e9fc9e2584f1bd9ca6ec1f6edf8452af7aa32c63f8959562487c0a8be654e048ef957b23738abb5145af52fc2622e46fb79fc281a4c113b20c91c87c03be49768cc8d510aff2723893530d7ae8ba5b37dd4540c2b517af017348b6b9a98ebc24e3580b751ef4b983ee574dba8da748be2144ba5f5878aa000ff8c0e09bbafca89e2561a2e84320a399a62ea474b482452286e6ff168154f6c4cc0f09c00a09a56b7b7aed7d804960cd3e7c3815f853074271ae8a2acb5ac016d36046db5afe04f698713caa93952e680465d45444f78cef22fdc858e2d9ccb03752a31d22266246a01012059ec37cc0570f0ff0e047655ec61cbf797899ef254648de1461821146ee6e897fbb42685a1a0723fc3210fc779cc8625ba88d86890f70bfe2119817ac0897a16b1cb647d4604316edab552f0c06661779f5c158e34041e061f1dbd09965c8b684d229321375f106bd0907fa9ef3aa7ff0decee6465fb3d5984f920903ed4b6fca65f71e0fc70ba454e1871709d59f3aa805cec1d4767aa06f19d41aa3615428d9d3e7205ae0e22b8791d6f7c18853ada0d4f72d8e2725c1d05cdc71eb53ff16d2ebfc7965129f18e81dd5f1cfe3137a0e78a7ae3fa2186d7dce4faa3a55b31199c65192ba63dde093816334df6ef3cefac687ea71093636935cd073aee68fe4a28dc635a32227ab2b5d01c655bc0df937322feafd5eb449fda506d626f529d164eb60bf11f171f444f8c6fa84de56d44526d1f8d08fcbe38a472f4e356833bc8dc11ca3e609f4ecc98cefccb344ea266993654960401b603c2754622075e69e944ecb7343d4bd161481da1a3a8c27e9f57f7810782e1b164ae46715bedf3987c987923e2abe7ef6d58357a7ee0366118b3d6ace45a7c2ed13664f5e385cdcc62e55b9f9bda29ecd3c607b4a0df92d065a202ae0e7c3936c16cfd0d3599d12b43fa81aee918d2e6f8d9ec8ba53663ce80b9806626f7d01934446097df1b410a624670737e79f2fa5076d5d2a183ba9f5aa45a4bc63d12200580b4ec50c0b63d34d0de9448d1c81f831956706d6d3242c612732756ad5ec60613d0b5597812cc5e2af9f049317c46d665850cfe0b39ca34ea4108a8d1a3b42cb8f1768f030aa2676759b4de3d3e869cd644888045d13c3c927252fa904f4dc94be05de02b2a373361c3568193bae3546d44f19eabdf5dad149535adc22a24d1a1feccb838dc73f57bc628182d42a2838477f862870f5ca05f5f99aa8aa813acd2d767eb2c860dc1821e20059728b204fe0897e0efb2074d9eea861da313c7a2fce3412d60248f1211cc12d275ca2aff33880ed144074fb55ec5dd4c5bb8e045c849d43e41f19040f902777b47cd5bd66e96ced565252035a3f864eafa761f6abf1c15805eaf258d679e48061a0b8bd91b22ea4d97ca0c6992fde352f4e860061ce649fdc1e9f8ef210fdda3cd0f893fd6e9b8a2ecee0384c4dea2cc7e3b4803902d90a07a697d6c537d8088dcf6d15e75a872403d3b2e85fc1be02e823cd6cbc09531b9fe967389ca99734d4de7a98a705e3063efe49cbb10eb561ebb14607b625bede0626e2de85930a1c4c4d1f33d60a835183bc4c06f38c1ec8452c284e9fad7972566b65fd2cc91c419c42a00b0cfb6aaf5b6b7881b7aec6894b58dee19b42fa164d90e0590e7d52492e04df7b0ab11649595b8e7824b0303cab159be89380c3aea99aa9b8a3191d26727654013e5ca83e54a012901f2f0b6090f0f375a81212fe22cb56113dd26fc96a24165ac9381a238e97295457f4d291a959037b222f2453763ddd6e9695b1909e4c2294a06336e0b7a047b8b74832ea327e2dabd122bd49f1543ed0313c600ece2c465cd58a7fedc4ca92c8c910743363fc694465cd806020c77ccf13bd211fea15d9dafe27e90414cef3b328109b65409e361635e98b2053a09030fbc0a6a07ef25c334ce8a962ed2ccaf51b52fec1e9838714f97649e687e019f7abd08a811a6971d5d7449b8000a40f34c975584e466ccdb79571bb898229102bdbeffd636bb7e5e839650238a3c9ce716e0ce47c8b0082dd1a9eae5b03cd921a91d3fe5c4de468c5325cbc2de9f0fb140ea143a246424f14de1e46dcf24b59150ee1514434454da9952f83a2de7c366680aaef8f202747614e835e7a635180dcf51622719e5d1ef803a6b3e531149f73f4b860d388a00f8d45b12c78924064dd03a13920962b172524f53f09bd916d4996c073724d1e80967e9b7e6b21141f61bf2d6583d577ac5510008e9ae1c1d5befd0168a198da8f1bc25602a57c3b3c0ca3a7fd5cc7fd9606440bab9423909dd97e0ace2303a6198ed044056340efa3396260d08f96b2180040d61f4c9b6b343068d76823b168d0bae21e7a19cd82d36528cc4f8773d04d0052d1aca134e857c2f0a54de577347dd332c69eef581b3a2199b42715b24657b7cd83baf9c4dc1e6324bb202c1677a9b949721dc63ff17b18c1e2d891401b2363d1c8a6597d85376f9fdc2a149feb937fc9c689f53d52d96b0471bb15caa8fb9c470a15b0126dd32a52570f7c27741fe4a1b5b1c1cfe24b5c967390a95c193a85eaaa97012e56413afbde3ce9775fcfed4030e69ff1c4d66ec301e096b074738e7708204a204d988798d60d8d9552071c6022042831ad15e9e5e568ebc778fe27e46c2cbae9e75b775bb074f94812307f1c4e362af797a85ee4362cfb84c0d160058dfbed6eca1b604ccfa04244583cc5d13ef49cbd4795da20deac657db4ba32945d3aad93e2a9b20b53dc92f4a4887bfdec75fd6bbf75d054eb4024e4a8162d01c061d03dd28181a21bf9abeb3dd8208f0243a314e4a7f13c4ab436d887924c782824b2376c297ad7a54bb15375c7209745b1835f369c73243f778155866390aab42bb8dded6196536d7ff388845a51b89e4277e98041c814a3dd7867e60b4abd14f8853df8f9b5d95b64c86d4c89b4ebddf39bf70bdeba1e85d8740d39c1f2013343d19523b8d97d2e2517dc4a7ec4446c3d4a2ee0cc3ed4c12daf7bb2b084cb3c5e031787b3918990b069451c0469e95413befebd3193cdef04453952f866e503855378ff6ec9a88e7a026f46ea4a8c7a37bc951b84d6be3e3eb539d2eaba148096a9b3aa2d244ea69317f4d9881090b5c764302461c11647abd3b6d711b35352961c4b7c9fe86fecec4d1c744bc61ba24f26b4f2766104489ef5aca9d22b2d2e965e740acaaae47fc7e61d5ce4d68c9ba296746cf2209504a19e801c3f9812d143367c56c67e6423085d3c9f019c6c04280be1c6935b79623faea0271c06b655f4fe48a28fd28262d0ea94349db52790ff2f2802215f18aca55a057a220c80cea40869a53aad95eebd2879132417086738baca77bc736064cdb5075782f8b19d1e9e8aedc1540f2aaab1ad89662e8413611b669499f43c9669d599630cb78119cd0e84e64d1035141372d0c1ce3fc71c5321638127a150ef23ff31e7047f061983e8bf3806d54f5e434f97ef02f25c7f9cb2c0ded4b693113c220cdf66403e55aa82f0cc032110f41a6cfdcaf31a73e6198f4a9465c8ee3f774cc60aa54d68f81df04234995b0928a9067145102d4fc3325164716a4cb130d270d135a4baa08d002b5fdb3b8a39ea7902dfeaf3a3c8f9d517cb56679cb391b752c6b9cb76a9258db2b047ce40892db394766d2a5703fca0e1bade5b3eda5551a0e8eb42e6ea31186575c1fc3150690bb217e3c325d8d10ac93a9530544dc874489f3d128b7a36270b9861e1bb25829c7da5678ef6c02090cba32c9fc40a5e66027476d3f8dd0aacb8803610bdc118c674056c7ae8f32b45d519a533e1a7c182a4473ddb3fd56940009979883d6384405cca36a930fa99916b63dbf4fb18531ff9985184c5efa67c1b2a82fe33216fea0b65ef8efadd078c3ce8fc3ba4f327324b0e1b79146ea3f3f654562d68e7e5cd8408a08af01928f7ab3a205101ea324fdcd843f18131b31fd1f56b9d4fdcaabfbf371d926e3c7760166b417d662d3b9fcde33c26596ad216fb7c86d8c459bae562e5506d4e17d023b164cf4d6021387d73e59b5a7325c65c652d9debfd309ec6c19100e31756229a2bd6844d245c2e775d6a13806c07c54b8f0a38f0cb7747bd3cf940a5138b52823bfdaf6fc89dc640814767b9b83a95117e0c7497153610a0bfca4fedb3614f2390a76c2dde410f4531f467f2792f06e8fd37f4b5d72da79a598f6f28a10e7a6f9ba17788b75f9c00bd774b02bf9140efef108514a545010ebc3089e03888361b32e493498beb07ecc62fec5b488a809c330870ef201c1d9a9162e3218c475104aeeb60031bf5d82c8d588a4d8ea314bde4f93f9fe2fbc351c583ab39d9586c8d32d29fda8009688aeff56bc0d8f87780e48af0ba3df200a7b1464a9089305f37d2b0081b07155f6e12589ad672c00f5d99727a824d2b76024d4ab677c684ca85100e9003ee0239300295ba71917dee7229f3bf61e33a19125bc8f227d746c54c96d92e4af5ab66a46429d0d1a57719adbfabd33eb97272888ad7d70a50e250e45fe2f5bc4c342132e9a21e527a881f07aa8ded011bdd1e28f1d33d2f20774553c511ead3131a126be8d0b92d0a0ef49704b99ed70a8fb0434e41184b4642013094308631968df20a390109174f27dab2e9a7b7c4ebbfe6e1f01cc9a926625916ebd020ac0a0a5c01c177261472b460f0bbda4ba89384b3693fd86a165d36238e9b25c8f05da49ff06cea8516a47bf4261721eb943b784a174a72d69188b09b13b05caa5600306524043b695bde271d02d9cafec9885591754d411e5c7839220b4453a396164cd89e36cfc1340d9cf0b1b945d6bfe60308087cf1adb57ff2511773233f3201fafeddc023f8f3d636b808b41e10c16a1bb447d87b1989460910ff6865f530535ecdf312c02a0f96e8daff5d3c0e2f69f785b2c417bb9ac1178a18ea58fca750d41e977bf2f6327cc113bca6a846fb7dd1719082e52a452ad7796cf613acb02e4f7fd9e437dc2c456368474b81a53d1aa7c9f70f5ef99c2ae707eccd73522e499b5e75c026fd716b353d844a4a205cffbc0b2cdc269878fdf3d6dbe7b1f09a561b2e5bbcf6ad4deada631ccc5f34cda80145f3907212bbd9946aab973ecd8efe053e817500374b7736a40f7b6d66c9ea87556f15e21e6bc8b13c161422db56dad915a4eda49cc484d19a8c6bf3a4d76cfc231a2a1e1a89f5486c3da1196f2f1314933d48f33e4a451de2a98cdc3aa097fa6082ee6f6ce170e66e0e26d3e7ade8c7e83221acffecf61c1c575107742b0c4635c2a6bc743dc64ef058a9f3fd132736c0bdfff847f624b6962824b81e88a202103c2b25cab3f654f7954bfae17b2d8e60e1cc42c31252e2f9b7e951c07ce30816365e81cc707f2c2ba16818db6098ee42ec4de8461ecff34c95d36f65e81a94f80af75ade8935ec11bd57ee297433a21550e957221e7872a8e8117566152378ad627cbae64b76397f34c6b776e2011302dcdefb7b343b51afd034e2b22f1623d9053dcb4aa78c80fbdb967fec5967e35c6f9f299c854c80aef7e91351e6837625b9db29357e8507d2d48f196bb9eef4c5389afb00890c8a3e1ab836961a82845eb44409edd5fccb3eb678a7d4ed9ab31bb5139922e5bdf691bad4698841ebdf560c7cbb727298e9b2778ca4e20a9f4313023be974f907f14e8f7f483b49573247b41a70ad35524deeac5a9551cfc3efb37598e4440854b3f69a195479ebfd8d5454ee86c26d46691665349296ae13c836d7ece8660d1a5c5929c7af63f269e8148fa8553c6b27fe38da500311d808f54a3d04c3dc83f4018b4f70cb8a94b50dc62c88229e844c784fb2ba3ffb6ac0f022caca988207b62e3803898552543e1a20bd01510e1fc82bb4fcf1b6794cad94bbe77eb2751d239ca1dcbd7f0528d2cdeead735451a4e9f10a1f61466021b5cddd87f885eae0ca1bd0e89be616128750cf44511900743f4bdf6fa33b41aad228c797cde430810f69bcfff4d40e5572dace36fbeb6ee9d3313f468c7a8f2273daa29ff2939e373978d41befc544e63755ead1e8cd9b5ea6723a99f6d4f0bf468afadf02771aa39e216cfcbe05ad7b9d763b7ce8f0b1ca74babdd7f115fddefe03d64d39282b4d98d294d0e67a37b058389b51351a91d4c090772e62bf0d2765357a7bd2f3dddacddc2c638a204f20cb9c9f811e0db1c2bb4160ed7958c983909dab21c011e896f250d682d18c462435fc5b9bf94b1cd44853f0ac34d8ab01f67850884d4a2173ea3bc4772a8fcfafaae6635eef0d43b79a8baa06e2641500398aab8949629310c9c4ed4faba16a88d6ca95a471dd4d47874df31d5cc146344d970fec86901e63f8e10bc38eb4b454a4fd50b687e486ad3f9cd26642af019f3db3dc118570df58d67f1196f7263fa4b73cfacf528876e325e72737ef4f57fe2bb5c8dc9f7943ab736ec68460ede1ba290a4ea4b309b600794c6263f970ab8d947ad49efe5b17e3747c72905a705f58980a743e00c85ee42166fa3a37fae38d4afa3c7c5c47f5809d9009a69962f1e2c9fa75b8b6037f791e080caeb4d2adf91c251fff561b9342c357b6a2f8fbeb32c11d697778f354fce7f5af9f1590af78eeea3310c9bb7cad8b9abb5f6cf1f5145654cbcbe0581c3e651bade0074d4191428dba1a2713dfe3426a8c426714ef6723609a59471e96a8ef0fb5ae8a4f948314da6168db88a800fb7f23201e7c7a0f3fe4185a03a2e11ea198479c32b4ffe841dbe51b110e49a852d879aaf49786cb984ee8bc7820e8a3ef269f3079bfd4030a75d0c3826a3d202d7e7d42fd10d3c2b45e8580038910cb71cd73a7cec5bf2ff6891865f13149a24520a905bb70def5586b9649ba090de5dc0a6f66b77bf5911ab8b80edb89f34dafc004d321a98631f1329d722c2255cfa533a6daf926510568200be69b6f51a2f12e3208d72b61e4991e51ed0e79d328e710e4dd029bc881f1055cd449994ef7e227335b0c4c268cabf9d17a824e9c78b5719a4c273e48e38be4b43426b67cd2d87c80a248afdda7a41fa80e68d825b817ace3c08126d5bbcad080355eadc7e419fd6b275903c0ab2e34339205264b196eee440621042f2eed99c95406894b68bd58e214f5de541acb023d20dadedd8a0e83250737a2159a0a23b5021a8fe23ba99d80222c1e689940c46050fbbed8f0ad69c0b5b0548824ab97d81b5daaac31cd22097188debd97c3dbfb91cf33ba0ec6aa0101238b462699f3725ee7ea46c0d8b09e8630ad5be55a4fb4e1061ac4610519f942f14e5fbee506165e0b58f8e26ce03394f3f3460b867457dc0c3d3d470c6269dd08aea301ec07866df174c75cf9f97f0c30b813c777f4e0960acf43eae22064246b6ad387308067b67afe0f669cba5c6689d8ebfb5129584b77ef889564773b13295cf781ca5dfa4c5f2d114db2d64d021a13d7d5125a3351a68090128f423323aa66175e2ff8be72e417e9c1cd0f3b5329b12c47df458d0e10b594b0b88e7e4dbcc6b3316a8b9d3f41a06c3338c6bb8d4592cd4d0fb9921273c64860039dc16d7f5b4a6a163223b99302f4f4ad16c5bed6662efa412462d291ca4a8fd3046a24416da9f49fd5172c9270b283d0f7802138087d999505153fba2cc42fda9bce1509cdf96b168d145a447b83e2bd13c97125451639ae580d8d4299708642fdfe6c11864f63daae9d0cab717e08468b6cb6012f72a251293775138a8c3e3bdc70a2445058a75cc801b81fb15319847d3fed917750c6e97de9f825838f7a704d4c487eb3fca6bc46f715d504696675d74d44c3b85404f0bbbfc07bcb7f02c2e07290e12e11ea4979cc874cb4c14f429cd1894d754e483f6afd40e2bc314bc77ddd81152f1de04a94ee4bcdccca2892849ad2674fc988cae657fe90764d632ef3c6b8ce1f6f795a920601e41501f97b4849fbd9bb00a9a296038583f145e60b4dcf3b659e37338e38c7df2701326e4c490ce02be0fa7bfa618cb80d04af40ebbc3f5a9746721308d42b10e8999820377aa50e7c962e0ca1c06f591ec44b30733a3816949d440d2e9d28f1fe14794f7558249420924ea08a0810f6cbd5a26452858d6fa80d4c97c29926e30257be9168860e5ba62a93215c0262674a070d54e296c7c7f05e22101460515e933c89c4d99caca7521cb07929341e2a4832e31a0122e9efe8a04cc038ce0dc9de0fb345ea7978b685ff21efa8c6f0ac18f5c67f20639864d405547197b046399b1166e2d8f7dc78335f28e58a4e045d2128b00bce9041001c95897eb1b4ce70dbae2dd74479e071979258a834d2176b3859f3a14b954841bccc1c016acdb1a2785253b777a938ca725218024eb428d2b7d4cf18299561ecada4fc4f3957d377b606914b95197102fa94ea9b53fd6eea90940a92f25bf5887a33378e5e935eafcada1ab832dc14b30e8da01592d68caf864cf06e3c13f26afad5e731f789a13c5e1b566df84c9d3eefd7ac67c4f17267e30054b4bca011c2da5ea95c8bab2749a561cf64b88eccd85d3f21f68cfa9945eaa7e6d649231a48593bb28cb5e4bcde79db1df4c246d9a72641034354e926a650ab9b353a9a3b58c89f0a398722250c8224e3fe865a2889fae2f2a8c9082611b44078e3366451176cc999a241e11d48631fa13d00c762e8a4b5a8b5d0e0d2c6808137ce109d3abdae87815c60d8cd04d414f177efbbf46bc7b1df02d7af8e1b5e4e084cffac6c17acdafef39a9284b147c02494c00870a2892c6b4bfcce02297732ec6a98bf3d36208a30adda3930f529a6c7ff2c50596ce7336747206ce57b826f254d77b3cb6e2ab57827a17082feba258ba306033e80b409530cef3eb0f5c68c9c959beafb7440a8516ecae0c1b16c0354dfc618454666b55611e1eb2d63e9b8a535a919ca23787d4a7335d91cace77b4a2f4b23f79e470c75e053c955f56dac5c1cf3d2565cc21d396346cc72f4beceb28d4f43e72ac9c651f9b83b308d025a2180f7acc0579592ebc1de853e9769d235a6d26fcfdf07ef366bcca2e8f6a6ddcbaeb47f7db2c521f0b0e318f0e5659dffb172dc2f0e2c0f13fbbc06b7cbb3ec625ec933ef9d54860b8839c92949cf26369238880b51a2fd11786f82075acc93de1842721a841129fde503432f0217f9c7005b53a5818077135679e80133f936d88742e1e16987063b631a44dbb13e1845d72222ca59193ac38a622b2a59ee8250ea2ce83a7f21cc7f979407d5072c61ca93499f2170decab63edb5e7eb387fab79790d648809db3bef891856adcf120e3e3836a2678ce940414cb942dec3bb43926e696aecef3d53ddbc1836b93f5414623728c50b8bfa7ac7dc9d6a21c1543afaeae95acf49be8540d42937983e579188e1025b87a40af4ef4227f1402fa7143f08e757ca6a4070f7bbb1bc3ded971d9589a2e6a7f7df5dfc10ec91efe77a6dfe898b87974dff839b348d3f34c3905c30c9f095f1179a0998e11871d3d224e65ebda3452217c9a849251dc864acc237794241d23f35d70d83a5acfa9f71781cda5d4f900e07c977acee4069d739e0348b9f5d69fd461f30855078f8e03adb575578e5bce8855f87fc650eb56b7d5abdbe1eb93eaaf573359b75cda0e94e53c6629c7eb018e6239fb94a6b9133eba1902f431e95e2f6dd76304f09c418560b68012492dbcce88c50ada4c5101f8ecb38d7d3f94590940999bb569adbbdfd9374abdd35194a57cc905d9d760886be933b4c69170096fd6ded354bcd7acc3abeb4aeb1fd3c241d62810f3b21c05645de08102363dc40619d5bd54c3c56d6e9f51aec37d0d16952fb107b99dde3a118f17d73f48798924b9b80c93081379ba20835ca75ba0347751a1fc9ce807850384bf72330e85e4ca49e17e78c20d3122d6bd8325003234c4f99c3636564db1954a63e7654c709700fe5b29a948678641e9264ac4288ca7c6d84c2ce43637c6302986d8d141c94eae01741be8f6ae95d328464a1a7b09e589bf8b6edd86965e971ed4fb6b5517613df1420fcf9a7824bf05785fb3598495601ebc4f38786f0b957bdfc2caa44acbe64d30a825da55ac9c5f4dda5837568d39ce4999a924e9a00a50e5759a46598e8c586024116d4dfcaddfa1481f26b7a7024be93f87506bd6ed61a2fc10c2260a3caab0a5601f4a10180ba70b1baf43a497b7af4984ee40f169fa306cd4da8674ec94fb7d25bb91700ce9f291cb66a56b0d481414bdc9804216615cb011877de231722df443de35b0ef89c65fe0c69df4c92676b709920825d10bf361f551a9a0853270e084358ce884c74b7eacde5d4269122487963669678648d1f51f19160f6e686572b5a4e036ddda22f55f6087c0a8745e1e7bdd4d9b5ab61f775170ca2084705e6e4bbba312814c84a5496c4a70db3432be323a8d58130b6b02a2a4cba601b2146c1528c5eff2bb8c8ae56c945827e2c4057453d4f57f27cfc6fb7492f8e98a8fe5b6da88480137dd423a28a924b52415d5da0de5149d4bfed665827c53287e3db9adc085565abb007853a879685d91af2635880c03a854dd706f471a09986f114eb99f73639692d0ef979adbb47883fb4edfc12a1eb92e3c887c3aca481c7a9c1bc17ec6364ccd6d86bc159dfad9b9380c6b753d454413e5fbeb5fe375119ae4980f725c79d184578076287027efa6a72a6839547a6fd1e5ca3f11413bf121a2e2832b7002cdc84d1bf584e1a7b4297c58494faa6bd64f305063ab7b87bacbb7e1a66f9f712f68994695df2611fdb662ed6f439f7ffb8c83e13e7928f726cabae74c03a2e781884a288f9bad844cd5451e022b59699d33e9844bfaac92723712b0d6a12b46964e451aabc127fb91b52e13a725e9d004955f890cd101d55a6013e6d63460b8184219a89202e57a2b103ff88202661122b4d6ff81a3ce78326069f800c1240373daa8572309a46d00fb0de1ba9f1541eb5caaf5d61d0abfd4b2bdf5feaef8dcdf53767f5f66fda7856797c25449f23f27668f958aa7e782d0d1186e67c7dfeddd67219ec29a574dff67b6a83955537fc8051fda24c5eaf615031e7e414c3c5bc6c15a5dce2179e7258c16d382f3e38b9714d01240a8ab23c549833034fedbae18b20f3de2c989cf8c43808acc8ddc52171ef6feb11ef1d9e3de8cdb48ac2715075f32b827fa7da09bb7efb2fe82ad98149ea821c71c16bf66bbb8a36762417f0371b0e47fc006465f4507a96ee81d6658a1a5b394a5f10a301711584b9ca671341808bb44e6579412bf89d3f4740a64b18e30873d0508efe8d249d8320f29e9bce0bc70b48df5ee2acd4eb1fda4671896c93655326c021e9c48f70d9848207e1a43c870aa0e5d8cca0a3222c3f8ce69d1fe3c448da2c044da311f1bd6ac0db6d857baaaca16922924c76760b61dc26ce97faad813945669f77e134b05db2c28385e5afd8a693f82e4dc16e8d251f9c64a39d57f8154cd10056d7f669d90fd33a44b5e23f948a4cd17a980a1f679158eb17d68be7123c6e707deae747fb7df585f6ec6aaca780cebc2d012fd2f8b64ebabd6ca50c2dbf53c26231c0b72a9bf674d589b7a4ce703b6cfb65c5c925faa4ddaf4e83cdd1a31399f5efdff287da35a3c6bf501b0074b06797e5a026119c0f8066cc26fc6e37d67447199923a3b4bf9e3b1d8803b9b3f7c7419dcd93b39593703c1948140a974625dd2d48b1e707277cd89e721a313f1bfe70ec607cbdd6fbee846fe996b1bcd899b4d0cc5a64612c05de8801ca6eba7567888787b982c45249660f425afa807477905f855cbf4ada20aabfe32e515f7d42753515a20993523006c2e4cfe07978497082b406133376ee3136f17d2c51df809237bab6dcda43bf298e9caa2213f57755889ff366498f8d001d869f5ea5fe9b785a0b98ef5d2b99bb39f3c009030f294e67e2650f60d80c8b0d5edebb410f81269d71c00808c0138897f1b47197b64eb80a3afae0153f5784c1eed78d15dcec1481265c97c15a0a9979408a0c11a017ce2886156b7c85fce4a6885e52517a7ddbaa00c157058cb65dc54cd82c16b037a433bd15b6b9db58644637ab2384cb6a0bd560cd13c83aa8d7a652ed7444a3fbcbc0e3f82e0ba567aecc5761eeb7e6c36c80ea36f9442526eb9bfe4fc2a070c44c379df3135233a7349e55eb4a6a315aa4eb9257972b2f3ce327536a0862ced5ad64c42b90dc2b883f4346555764020c3ed3a4d82fd886e0eb1b84374d913d70e48b11ac5e492b9f272b36451d6a439a5bdf95c3bc6c68998a3be6772b7fae3b2e03005127b1738ade6d40b8df4f48059904bba92a00ea38674a04cd0fd00e81d5b00fde124bee0f8d92ba555a55a2b873491287ad45eae51ab166244e3ea991b3989f98f475e5cbd22fc045de39b98f77bda523155ddbc80228eb18c6a7e8583e968fd9e98cd8131bf84ad3a33f523070da76cfa2eb244c229ef79f85fae68b080b485fa012d84deced39b55e8a0c62757abca4a10ab68fb99f8132fe19d5f8be3403b79d6d4619e3509e759839eda842479c3d8a38806f4a55f10a03a89372b9578c49d7aba5612ca6333d3ea1e0d2f59490248ce7c5dcc5473384b6d66b647518564fdd26e4b07e7d88d6d43a0c4348ff2128c267bef7aa728fe83138064a005edc85ef40208b66b0a1932f371086855b59cc0913944f2c1019beb6ded8be0bb29ef17dcec85fe26398569982a36fabfc9b29083ef85e95f8a8f1fc3aba42cd7e983d841ded7d00770af4c3ad29decca04b355ab15c456d785fc80b56b621ade44368a3cafc989578c0c672cf90577e4d8e953af40fa46abebf130f69b9c8eb811d407b5a37668b78c4f54d0f405a0d31b370187c32dc22723cbd663c7ed90c6cd2d365d35356b4dc5c7e79013c9483ba2730e79e77653b39dd7e5db8f4042a270daf7410a1a7f8e15d30e1c3baadecfd655fbbde20f5af90ee94346e4657e6157e1166740acc6da7eacdac1aacdf8cb78d3429469087cbd036f863aa156b5ce4feb7ef0d25dd7f8779633a7ff803ab2d0f375f1720746062bb72802c9aab8c3615779e06c4cade60231e0fafd92712ed027f7d9fc07abb24b8912f6e41fb99c354eb2eeba293f8d14768cd6e10e784abf9341ee6afa89990861df54264fbfcc4e8383187062e88d0ea30dfb1add0a8a8e95118a5a9cda1014e912498e017d4fb6e57abaa500fa75a610aa9bb3405477e81f866db6e3c04b7c2a97a13fcd95a21b111685557e70c2fdc095dd7ed540036b6b5ef40e4175a154e95cf2cc14876aa071a681e8319920a7a05107524f28d9c7f56e01329d270607cf4fe1487c32d86c9d2b531c285a9cc08fe94000b20f2a01ad535688d81b1234a1e79d925724a0b702b0a812f667d8c87e08003188361ead9c1895a140562d602d4a05848c60526cf88d5a6fe1081ab8b5a0132a496b45cfdfecdf44628b4584748465fd151e0a8b9599f935f729dea0b32fec20a4a1aa8e256ccac580520fe7579421ada85f6f32493299c80a453507839ee7ce6e14248ce12398af6081d57d1867ac3105c5d03f08757e8ecbf5acf3a5564baeeb9a4893a23d03207a559fb15ef4f7535d1072a6c64298c2e0a6cc07aba935c72a29bf8fb71cb7e7aa0199bb8408ca1569b08eab1f9ed85f1e616e36a4943286b636795ad720933a38dab3942c54813af707881c67d0e7859526d55857230ca708773298e5b63b04af93302630fc199c7294e7bc15736a08a8636b2da13990dc6e36657a0f1027ce3175aea4c7f9cb819ae8a596a8de03e3941707396bf53f6ded2245c2718ce684c874e026bc807975a4c359aebf1f8fba6fa7b64bd12c17976b6e3f25095a63a1d7b2ba8327ec94421622cefb7cf035e90290689ab628812cb7442c32773c57686156062db141a3f3b88b4094e72384faf327f60460edf6b1c6c272225b0e1537cb4023c092d19a729d7b60bc1cbd8634b49a66c8939714480b2bb9b2f5ede70c75959914d0742b8a7f15ce517df306026d0329099d46bddca172f5059fefd4f005e4f36640840e148415712cf29a58d93cb3ad727298199e29628d2579fa2e4576176aef7da05393a27808106af4bdc6f10ebb5c95b9b4c549523bd89a4f47c3ea9fbc0b5bcec2ca0b40f8a3eea20eeb3476fc3106ee4ae8924ef4fcc11a24ef92d57624d6a6d88e64b8fc7205c9a3459168c6f2a73c27a238455809c5704ee35330b67b08f5723fc778ae06ec5fc5e739f34b23f88f47784330de6f0489648337f002e7b206446e27853a3f29b96bf603db206ab49a32cfc863dfa277c27c7239efb7f055ea2460f3ada5a2287e0e05123906960477049526e3f53bfdb536cad0186acfa8465d74d4d31f81aaa984cec1f69942c594bfb2265721b5d0e79fa8bba97a54486b514cf65af8213d329a1d8c491935a7912a07fe82ef14e1946ac253a2e537cf19aa0754b70348c4179dcb216f27fe9a4b3397b81171202747e760d9b68bfcea7495731283b8fb0ed0c2324fba509ff70234dfc351ea95044c36be6f32021638eb3b871f20d29053fc93764b69480626eff29f133147ac6842c889aa1f49992db5524d06588eb400517a57cc11f110c515ab3b561345c2583b03f4250fa38e304981ead19a42c9a0f7b89e242dd15202aee55c7aa4684cd17216f98b1ba410475808d784e83eac52454b0f082155be2a88431181fe058ad9be4edddf014705b9e29ee63179ef54702bc7263d1c357b13066a686815f768a2942e5c765402dfa821f6c0c001a3ab32c327e1e3f9cc0f1c15529fbea1db314efdbec583a92ff924955b27e17c80a30f2c13c40051dc19d2c922a78867a44606433c623b1a2f120619bdb1752b8f2884a04752a04be3bab1f55d0d2f82434c98fd76fa7bf5304aa0ba1f29abb9722ea7fc843e26e76988851913194e1ba81970a74a4c88248a31b14dc0b6be71ab799a3a38e9e5426531dc77698a94b1fef82fd60607c234801387df0678201a3ada2437c9f24eb228334f465ef2e394e90af4723f7973d552680fb29f7d8f6bb7a3526e3a3ef1125e7c88146570d99aafef3235ba452a8849dfb03898fd976e7ae18d4a056b810ec2e9f8061f1250e673def1ea198019464259c88451d07ad3e0b05cf4e606bd6db3499a9b62543591e2414c74adef5ee79ff0bcfd144fdf26f83022591b4681c28561ec243888578d291adac2f3b87141547837fadfc3e98eb50e2aff306c982eb240ed18a64c95e3376e8b7807fb26e9388861a962d16a7b532a36e3136a147d1250497137187ea6da7c26d1cd620a02260003c3e91f37b6e990862f7155fe74b8e3d1a393a03cd625e98ea124761e56a32a926dafef13ff8c64790a7e731af4bde73c51270b1a427c5cfadedcf34b3c90a325aa4dc20e72542ae754be8d44dd3cace8bf71acbb79d4632de81e4f896019190839d14cdf5b2dc901d4fd7f5069160e3b5cebec88a6008de6e8c8fcd00338749bc7b23d4edd106e4228f609e544dd2e1c603f51a100d44502c3eab449c350ab87e3b1b2109f9d7863b33a4e0ae52fc3a28dafbc4214588d367124401e3df880b72b94da04b1e64bc9dc15efd3f295f841cc09e0402f432ebca9f96cc78563c7709cf392167c8a4756d7e5bfb7f2f4c110f6f45b55d6efc09703e868a2df39960391b868e23b440b897c1944c7d98e4fcd48ad6e04e515160d3d02489d2205dd7ed068ce367d1b5aa4b30660210e3ae299483048937c7141dce48557f9167cc61a51c3700dc529e4829547f3b61194860ef1802b2c1b577ecad9003ce93fa936b80db0eede296545dbc594441484da0afd3bb8c962fb8ee9d293e435acecf5e250af419254ef81b30b76ee40927c4802320091708d8fd21420dfafb6a76f913d81caa00e42ea18ab3c9354818260d30ded891bf02de8fdd63947158604297d559e0aacc9885bceff45db6c836e603ae2488032bb4e6ad8df112f9b95540d385bb81eb747480c757ab6b397da25c2e0db341126b9dcd5b21890d3c7c17c8bdc10735bb6214a123f92ab67c2475df7f68f9b447e3b0ccf8bc30b4388628c47bfe07073f2d77e39d1d86920174796074a03fa59a194ccbae1baa6929b337b1bca2bcfaaa813418999e4b2fb768655a8000e32a66b00af5a2ae41a403414c3145e31a6e9c736f265031398929f80d2b88f04e6324002fa1662e7ec6a1cb2e1389830febf5db6a2cf75d52349f5f4c3df54178f830e42baa6b08b0af0b92a067859d0b2b472d6e6aee12dffa09d57ed185be52970220e239bb0520848962aca0a1b606bb1bdcc19c102748207af694542baa5c2a73495287aba0a5486961fb6a973e76ea1ca9c8718e3864f1228057868b09993966bba466865f6bd136880374fd7f2a849b3ef983d1dd359986234731b76367ba476b3c50d149451edac9c6c2744d25fb04159f0051981c1ec0a0d5c5f6d1d642e8e2bb67dc1522e8fa4949d4ca3dced1311cffec000839bbff62194051f7871962b74d20ede2cce1cb058418f98d0d9b88716843f7a7e7436f5df943e63e0847f39644a60878dc7eb2b9c62656e3118374021f9f2e18499ca9919d20e2817e0e3c17578d1a099dd749aba3271810020606b4f535d4cab69b1e3d85e3a8adf29f485974d5a51deac0b4fc79cc4c65e2688e4eb275861561ce549dd75980486f8fe78d25c44139fe2e79853c7c0f7ce7ec2154f67a3030a00b54f1b79a4aca673cc585868b3c83f062363a9b55430b5f63c2b5d2a9e0ed7b7abc2a35642db7ec4780542b181df494ccef8fbd479506d7e62f4ecea78133012f969104975eab8b6551bf01189ed2e4a5974cade921c095391f5d85607ec8879bfae071783c897ca6952c778ccceb1b8cfeb36c760a3b1ef24533885e0218fdc3df64041379d8af6a74db7d83965a7f2ac8cac759ba23400027b0a31917ee6d555b4621b9ee5b979786f7932b4f967570988c9de2dca7678987fa2db28be205884f6db26a9d9c4cc96ef9d326404f0862900f4705f52362196ff6e7cdf5a8d9d3bc07f498640a6c523d7732713d1e07da59f4e4d71356318223dc1ff3d4e2fab0d8dc0e8b57cfef703ed5cbb2bfcfbc5d2a626be4c188ea248b5b89cee19cf3420c7afdc6f446fa8be78f5e9ab69ccc8593e73c072d5d8865df11b4633732e04b930ce966698901387450e2d03ae880fadf3a809d11df3bbead6a74ff475181914487bf3b07c14694bbb08100ee7a7c5fa5d0a7925e692ae16e9d2a5d971c2a212804fe05d4b6d4320ec4cd2a7366586809e3d252d80a701f294b02b5b5ccf0af58cbdd8ed20d5d43e12b658b090032dbf4ef48ef6932d382a1594edf2539985d1c59febbefebe06871468b807d66523674bb6c282b32bb1dd4397202834593b63e7d81c5edb46a1fa8520138dc93496a649fa251844ca1a96ca529de9a3927ce03eb9857becf42b4a6af6748ac7df9af261373a1b1e12ab0e9c1f0024de6348696279930cc2c9aa4d06c5c5620bc9e43ed099b0d2ee88c352c849a1d3cec46e71c791f251991b12346c1d38b39fc6c318c4392ca3ac2f6be1f284c0fb0d63c0ba5f836868897b1d8b6c361de789648500a5bcee6f0de32a80b9a6dc0945739b72ee8209bcfdf08f4c40fcbe2c645e25ccf9951ce0951cdad7fa4ce4e8e8ad71fa59c83c13551092086b9b43ed2d2a89714b6f4b03ae90556f35548b5b9a683302c5298bba874dca7e5b1678ee9817e4ac6b9298a09a2b6e1eebea1948c576a38973675497650a82304c3985597ed11692ce2711653e1219dec6804a34878bd09ca2d0109923e00154af9eae1364b0a394a38535d11562dcd81bfb8199097e2afafc958f1cb17bff8ef6b63822e77c65d5b63070e035cd49d40a965456b77759b50e6a7bf1c398d3088b68b9723e2c86d5ba667485fb3f6e15f5d49e1057dc8304f8b0b9b25ac291259f890dbf568544de159b9bdfd52e6790283679f49646bfe4b6d8c1d7e9fad4ba699e3e207394c039aaa54930c2793e814c5185308c6a0b1614d1ffd8769a996a23783961e5cdd9bfcb435b226b2c494dabedd1e138aa69df5c059596477c5e4b6a54849dae5e49a9e5719fb7959896947d38cf41a5e5c41ebd14842abb50b271114c15242f6dd1285b8b768a1a58854c8b7178df693956f23967a8c1b8ab04a5bccb436194c4e45f11e995fb63f54f74088d08bcf3feabeeb9e851fe35b22f1384bc2cf7d6421c56fdb0eb8adc78dabf088fccb403cd3764e10b6c049aa23b99888a7e0b4068b41f2f72e89cb496fc60f6f6150117c3960ef5920c680bc1ab05243e6bcc2d58125c62d712c4767823e189e930109700ca4ea9fd0e8877d2b2f4b544d443a1a249cd5c4e895761c056dc1ce53508366f646522b4d870cdd7d46ee4e5505dd1fdc040b9b6cc3ef4f5fd62fd19f22e43bffb4ef9c82b62421cdf9dc848047fd4093313078cf1a5098831aadade0f6e0c64d9edd32285c8d945125cc24eb44e8529c74053ae81ae887cc1e7291ee3efd7a0f9a4a2df0942348887088f56d2248e42dcdec2807215128df8aa9fb731cce2798a465d0ea432590d34f066c83336180fb9abcc2526a30f41cecc60509a3a0e2ffc7d31109d8975bc7c08259f9a585231def61305e4209dd868fd7d5d25fe906970f8e80de85e6f0855a218344457270bd5ce412e31e6267def85a42a41887ca1514e032e3f50d266bc50275357966295d5945b0d0d5f541a4f65fede598d8b18f465dee2dd592673937e6b9cd09976cc9621076438e9bcf7724773cd181c5a52b348a1b0fa209fa8d577a1e5afcb7d3d48d149f99daf53f040f91b42a2047bc3e69d8f1183e2495b4d91666bfc5cb7ff14e7c778033ba027d61e35042f942d982099796c8ba28116168107748f988f54843f91a91387260d9ed844d870bc52f15c434d16114a6b0cf0837f376c55127904abc47e50aa9dfb936a69a94e325cebb5337a89e2a57fea8ec431f0841279153f50664e2c781e30ce88e05cb735f39f1604d2b112c3f03387002b682c30a064dd27dd48bb572a3156b5d953972e2231edba5cb623249bbb4735a61811b825bc2d8462ae841006cff8b2299d36d16427c89f5afbe8e09ef04b82b4f313b14e2e9a8ec7cc31ba68890a94cef2aed005550f07a48075b1fbcb3ef67c9a67af0b1b88fe49ddcc480a04f31f62b30a4ecf41d5a520059f6b805396b74a4f31baa25cb2f72e95936e46013286f9637c4a2adda682954146e8c5f52ab9552d28bd8f3eeb6c45f274c5593f002d1efc8130b72d484a3dafe870866f476fe89a3178c88c7e2960c16083546b9c3bcb0073b02fdaa565378d1b21d65a76d837e6bdddeec6cf9c0b3296eae82f0a0b18b04edf4dacec1ac79b5ca432dfa05b7e27a1a26b6638f5119cb394c34268cd27db5a9e7747b462a5fc293789a178a08d8960a8927db5ab7394928dba9ec6f290269ad161615629840cbacf005bcb606a56c5a2f7945b2c72e1abe5eefc487732c91908ec67a2fb68fe6d6381dba5ebd03aea9f5f83b070439038047f041aa7a7bd5b2052b2da1c96cf20bade6378cfae106d42cb94593a15ddf45fd34cd09cf7789d02fd35ae933457d24cb0f1495dd5d2bb0a06e801502148211ea6942ad760e514f2a8a6f83d025ee8d1c9c9188d58d5566d32ddddddddbd654a5206880b610bf60b3ffcfa8a180890558c0c8e4a916ad0aa3c593132d7899ef7615830304131356855aaca93c5656b47fdeb0aa87fe9f8b2e586a1b8f270e451d5a097ead92575bdf592f21ac5e9e5e57aa5710e9884943011dfa75396866035c6fe92bad7a976b5b0a380e406096df7de8b225fbc866cf5a8f119aff11917c2afd6759fbf65caf9fef586cdf875935f2bbf8e835f2a87f1eb94f21752e40932b8a91f250c6cb28e17ff527e5dae4bfd14d9d281f2ebb73c5b3b0e70c619673c8cb7745c4f79aa3c4d1894fbfc756a56797ae579cbbb44de1a7995d8e4cb04c5e541db27c67a312e8db778d0d4d88cb7225063335e6333a5e93468bce5214c8d4d5662932b151a64add184837bde5a8dead41e443f653e14fdbc1f8635e83a05e59871aedd2269c8181a3653bef0796b90ec767ed620ce2786a23f9267756276d02387d41ad2a74b228af29d4ba0d680eaf4771d9581124fdf4d8ebe775808bf28107ed1d88c734e9bb438ae4543eef0507bce6fdb56b674b4f360b30605a58264b866a9b3dc936e5d2f5104d5b195c2505e82a1d75a8001dc541327f5f5fb5abf52ce65a0ecd5b93c0ff075b473cbdc7ebecc6c44f46623da88daf3ee25026b5c112dda3dcd5fe2b25736d97c364d17bd61666f4aab5ccbc985552084a82e8fc1b74731f45d9b7ca53a1ca8e48b95dbcead215c4ee8052a2f50c0fbce999e81deb4b7571abebd5939b40fdfdd3ea443c8220a48a89bd42f755607b88de300e0848516cf71ed86a3755536383b3729a0dbe6ecba11e2d2a77e9382cbae83fbd68eea9b6f5da95dc16e6500aab0afa753ae007afbc4adf12ace0e0b38391c94f650c5c43d1908a8614782902861f2ed3dc2d8e0b676549b90fb3c64d8d32956043d9338707ecab82a21dcae9dd6f4edb4db9fcc9b1baef91d96455d57dbf3eeadfc799669cf32a02796393d3539310dd188908e966aadd5f34a7ebef57c27437f43b6ef2a536daa57da5e55a5ae24f7ac4dd4ca9a84de5e816a7b6d6abbb1f885124942d7cd0eb73e3b61b3cd157e388207673839a3092dd617b062840a7e40c40e643011eb6e0f85869cda133d926b035193c964330c293939ab51d77e6423cd064bfeac4267655267b69afc6a76f2eddd4dcc1ad45e85aaac0285cc1e7374ab6cd6715c2811bf241076c1606463c93dab118abc2e9ed128363122d246f58836ab6f7bdea8232c37af230c6c6e0e24478e6ea10523aa65a35a8e644344fc6217baaccac4097fdbb6b515775cecda99f316f8e593835f3e39d8a43fa44948cdb0a4cc532b2a890b03901f3e727658e0ca93d66c36ce87639028dc3ca4483eec33860f32c43e3b75df461edeb6a6b6395286fa9c37b9c382f78538be3a772187f31cc7b1f7772b3499011c8fe339e7cab3d6fa793d7bbc101cef79fe3948da53088e1e9cb3c02fca029b1fb9e383f37ac673258f1a441fbd0c224375fa21f59b84407451149d236d797ae4e923fb6a9d8eb56d6d22b20debc8655522bbb61ed93cef471e67733beb91cdeb11d1057f2b96945d95acdcc873840b7ffc882186115270cfaa7456a0edac4075a932e12849fcfabc6387722bd26fb687c92aab53f4f0f39dc7c02f9f18d8dcb6f007bf7c7e738e52f9c1e65681f895636b72ab127ef19092dfbce70586d1981086d55847654b0d9afeac32988d6dce420bdbc604b383905ac00855833431426bb1a2b33ee85ef7d764578ee4f7f94ef7475a6b81bcc02658fe6093d25e72bb3c99099b9593965cdfe4a3fca6be1d45ba90230980da3dab937360e94284b058e5e7f5eceb52356c7eee954ca5642536dbcf9e356c27cb10bbe8ef642162933e0f36dba9123dfbca4f33e5c82e1167a9f0cbd2dea341ba99915d82ea845ec3d03bf214cbb0b4a00bd67a48d20fb2e148fe1475a844c990d216a3efbcbb989db6d605125ac301966aa97c15fa76af5685c80a59246c56df8282c0d0a35ed72e65dc5ab34aecaa0e8029b72672fd36c8f6119b55885f1fd5a902ba08ce9aa9419fe95c9b8cde4abdc42faf6163399bcd6666dc2096099b7588cd66fa28f7b44a94a46270698d8ba6b7355bb335281e15a5eb198d3a5cdf54d8aced61931bb0b5affcb0597368b8a725faea413e1f52bf63a5af41da3baf9ea54275b800491950efa07be4c995676995b8d0797b48ebd1a54a5b987ce74ddf5a256cd6263d40340b9ba9d2f7c8b64cec907f931be03f9ba94a5ba9305b6b57f5ea6787e183af4e6b0ba10abda935cc16415dd56b4f2cd3d7daf4d5c5d112d19bea0040baedf44fab447ca2d32a2dd9a7666a9d3d6b75b9c3fcf63e62627ff8057af51ac65e50577531bc316e19acae81e9abb751cf9aca69f367cf584937cad950be2af16ba9be8df2d59b885f2733792795c626947ac466ad3d5057f5cfebd415e14f4eaa4efcaaff535cfb953bccff9c69df9e2387e7791e4d81cd1c5c5ccfadf78352da44a953d32eda019074db3df74617baddf3960ecec12f5be0d70ed31e7c0adf40f0e8195feb08be6a80baaa77a50f36bb1437aedbf675be8d3c31b02906d19b0af3d515e079df6e6f97e790ce6cff4aea2db410a4a5e3f3ce3fa7df9567477e6402d8a4ce12e29e94f6955d990403bf8474ef81feb3bebff003c8f79bd7339e370f83d8ac5fca864dd143ef19bf5aa09f35c86887f9a0836545c2e613aa539fe82391ec41f2609332937a4275ce6b5057af50a80ee89e772b57af7a4eed79f732a92ad42091997cf5cfcfebe23c5c44fe2b7b7c62238f3cd6690da3f7f8c4c69352f19fd329ff3998f45f79facc3e8807fa9b846074facd632c47ffc8cf4520ebd8bd1a7c64b4a120a01f1a6690c56cf089754f7cddc8175ed86422e3b821a4b53287e06604d4e6ec8696983c7e72a279debd2c96bb4984c35fd75aab8f91b541ff6db67e6ec9cf435204f2ac2f42255f368e0a9b3c2a4025827e83c3e56afd6c18866158b7da9f3eb3efadcc4090cfbb262c6cde005dae894d2a9efecd086eadb5d62ecf1ecb35bb58e7b823aa63b7926be268fce2d8c64f960d18d24ffe95538689f1d59517dcb343d229e990f0ebec823e885f4c63936b7e2b4ffb9bad7fc32dc9ba515236dddddd92324ebdec80d8b457a88ef59243c226dbd4ae334e96277f4c9df118afe30af66dc91d29ba27bdc2b42b47b8267e91cece61e19793340634507a27e98b2479491245922e24395acb529ead25c994bbb50be0a6e8210ca6b725a566599eb4e645ed37df61d27fa76d13bf9c5f9b8fe0cc62dd4b53e3341eabe5274bb144f4868788f82582b3f31097e5e9d170b23caf2d4f9675cfbb97c572374d9c1a39357c2313c002f378b9230249bf0679d2a8544e1bf696259a21375059e4694f9b982be2afc80dd43fb923fb27777474dafcc91dd9119cad8396c2527a04fe274b01c953fc48ce1b06219c44af40e1d710aa539180087ab63126830e81daf05c7778763a1465c6e4cf7a34a5064922a50287d99facee6ec886656ca8b214fa87ce7e107fe6340a3a057c9acf38cf5e6ce183a7225690258929621e2002081b2425391923089f1da0347194056d09299e62375bd0e0450d7810c41065c44eea54031e9e9fd97dc704536a90826796fd654171cda7536a5fd494b828c23086426213a48128e070cf0dbcac076c31cf27c69134b6913e313a823410044110044154cd6e514385c4665d7a982c278cd3338ab625714f70081ca20184a2a15047edaab6568ba235cc6bd751c3b618db7a595e55360baa061e358c4675a85747a1923c1085e480aef4fb731bf24023366fed3112dbbcca79c7384a6e442438dbca6d48e82948fb0ad2c023f008a48147e01178041ea16a2fd83ade8456a84c29a51d94e487e64890c8015b6c136a57f52797fab9b14865a8673033d39bba79d003b6d836446faa6f496a0ca1c64039a99a6638176b42936b4293bb09b1c9358466827a26e88a3582c411e54dc699a03bd343aace04d5ae3340ed7299e9817a57c5724bdb9a50d7767a295aa3872641de933f678090109a0102955415667a386780c014a882d8645509923cfbe7cdfca09cf8b50df118f4b5216167aa0aa0125009e9bd59bb59fb801a73295541aa12a892a89a9e7de667e6069410ea04a8252827d5912b93c9680820974f5e24b02d8edbbabb9bdb6c77b7b5d65a6fdbdddd5b3a8917d0dd6c49636666666666de6c3333777777495ab9373f785ebf006156ddc6966b529dfbd55d54a772486faa73a55c0c359d920593af4e2bad51ae35b522213a4e8e9bdd4c5718e9544b2e9d4265cb532a589e4eb981122e9e4ed9e2e85dc62d889e4ed94228cad32937507aa631d320880ba6cd6e6c14c42434139b206125ef19b1ac0d9bed9b7b54383515a56ea646b5ccd99fe2c948deec1fcf5e6d949fcb484cfbe1569b02bd691c276ef54aba3893433615d355f9aaab418fe46b189e5c6be521f53350871ef44a1a61fa0cd0da83e5e93373d14f9fd98ba7e82bb2555564abfaca7d62436c36934ab61ca0f295f750f5c4b8cab7a31268b80c855f78b8ddce4330dece44ec845fd7db99dad5cefa1559b4c91e76c53d59c69da919be967589cdae9155a95261b37d169695c9534c3d562e5365c81e195f7909605c7e01e2d619e875d6e50dbb9976e694ddea04c9b32a7d3b8f3bbed9a398c651d86c7721b9a7580aa1b5ee236b5d4d71abafb2b8d5575ddceaab226ee5380c9730ad2ccf5bfeb0ec65881715dc23fef32bfe2b2b906ac93debcf77653247cda93f9b8ed60e9bedf55b3bea730276180524345bc2911a6f48e710eeadb38cc678b4abbd5b5cc9426c090526242689f488f0e43eedf866dfecaa92c64d546ec91e86a9bc9d888aa4ec0a372319cc9c58c63206fa0103ff7c2d601993519d757b6bc96a0b0d4663ed5c63166d6cb94ce397eadb1989ea80df1e32cd5a189d8113925263e1179d828359338d97f84af7d3b75b7e750b48b7738d9798c6482d6b589dc956a8f1b58c32e445666211d625f74aad9603a3a7e510fe0eb0fe242293c97e080b8590da9cedfae252af074a19c8a4ae2601a84968122ed5d99e47c824b5f1e1b6330bcd3d58af8b788a380f818018764316c4affa748a2d646f9d9e0ce52d3b79cb333ef2ba8d870f7e9dcd82f516b82e2ca5526b13d5d9dc6e3c9c371093b727bcf58d748571b9a0bea1b3f7349086b1f5d17bda413f7388346c2c7bd8a688eb2c0c519d25145691a8cb7a116f2b126f2912756d6c9f9afc51bb9888818090745018e3405dd66b358af47da914456a261c300ef4268a256f8348f9f0d6cfcf02d11beb30532e1814563f8ea4d46e5ce9e64202bdb1fec53d4978eb8c03a53ab42b4fefbba9ad9ce9d92825a43627fdfa072034d73909e8eeeeeee65ea70cb5dd325dfd25746b758971ab6d39b9a96fb721157338f498e7ecd511973d87a3bd5ae25667176ad86c56f5b07a51bc50957471509ddab09e76b1ecca1a36ab75d17b50dece436e9d8748221e3f5df614f568b7ceead26bd7d65e4474ebdd0e76d0d9c112eca16591d1dbbbd2d9acd75dfcf44c562a75bd08ca5329bf39f7deebb734e2a35d658e79737e0797c6dafae61cd430b18e3c3c7e9a7e730b5463d66d59848858026997e84040ed12a3d57504da6d59a4a8878b5b2f82f2b61e015bc4c5adb5a5cc96468a54a2766dde3eba5856a1d859817e1b4b9307505d74eb6715fa422ceb513d6ad7b6f98b71c4e3c706d1addb307a8b6e3d02a33707356c2c2b52bb841a26963cd43097b22eb56bf3a0df1ce68acbf9e6b569eb6ad36f5dd7f57ce81df97ddef93ce7213984ffeb389e8146782a2a2efbea887b7a9c9bfce2dcc5a35424771a245b3b3a48e89eb7d3a7a30b4140df9c2b5d2c83781e7ab78774b441a887e48ecec1d68ecebb7e47da901b39844ffb38e80df51a720711521b92aabeba539df02b0a5f5d5f5f3f5cfa02844b3de46a83c91340937a26042b876dae535009faeaa20f1dd56127bbb8d477f825745fb65cea48869e43f1b8a8be7e185a1cae8e9affdc8774ce2d137ed570ce2d5137b34642ed6a9809ce99ceb14af0d3fc9c3f9be9f39605b9962d57e0ffbc9918566733994c360316ce5b4b3f716e65f687bbcfb9bd62cb736e83f8b53de75688615b8c033f3ee217c79d15cb73fe3a1be991a07c2c4852622a9c27a280c4e33ef0f3d1c1f2fc56f8dc9bf1afdb7e66b433dd4c49d9e4dcbb34425a54cf7937519d7ecf1359f4d004929ddac57909a48bec29ea31829b658f0d1fa1e49e119c76c358ac1a6403b1c9b90db283dac5f908244d79f2781a2fdb9bd5350d03dd1b66e3a0109cef9c2cfb874d2eecc83ec226e73846b7e3808e903dd4ae7635d3c72acfebe5c902bd74cec3ae24dddd4ffbee241904f4b2ebc052756d988286be1ab3b0670d6b2476712e829f1e8dd9ac61f5a99b81b3cfebd391b2913eef1cf46e6a1bef69b953cea6ec6979d9c4e53466e336ea13cbd8ec5ca40ff207d902fd86d31809640b2c5b0eb071123c0236fc4659e486db7012ca22453d6eb80d2fd253d4830497dd288d987ec349287b8a7ad8b88db2a7e8465924a75d9cdf709b92d52ece632830dd6e7ad9e17e1ee367338dc032ddc66df8697e6153726ea364418c1be557c4f28f2c491a5208ce7f8e33c6fd9cfed93f23bc93f4c920211b248d31147e45e1d78c73ce48fcf2dc9d73aeb112d50199d63f0cf3629cf7117e513e7a3ea23a0aa00fd2074936a2379cefb00e3ae72109d6380de9347e5ab2860c621df490244b5bba0f613306e7fc26886bc36ff84cc94c98899d9ef3d113a1ac519eded328af052dc833266293731b654f510f1b96c26edcb8e124b80d079dd2d7e7a0d7910754bd259ba9996e92dc1825ee599fea13d551397723747b030aa0bf63c641d21ea1379cb793536371ce5b4b6b08bffd569019ff3cb446b73e8daf9a7cc6bf7287c11a1fcb8fb43c32c073fb05f9661c245b35344e4706783e5353b6538b6c1ab2b16ce1d7d9432fe3d7d9b319b2b5b0c979335920fb638f501dfaab95878dd4b0fac42ece3da486f111bb38ff1ce9395751719d39ca475f795e18a4cb79cf8e869a88ebb88355b6787437b1c93114366b97692f39dc7619b7b141471e3f3614295200e5dc862245607936b151da701b364e6395a85ddc0d526664042f5281dac5b90d27c16ff85989482869737ea3ac4847a6238d50167d7ec36dfca44f5fdc286dca2ad4aee69c9d9e989a9c95f873ce43fc62c22fafac4e6c12b1ca8ae5c5396723aab36d621d75a43ca4a3b564fb0f947f248cb796215c7da765848e984ed59fcdb402c39043b66fb9bc902914d972f1fa2e013072e2d7e79c57272f4f2244be72487feb73fa4c2b5b9fdbd657f2114361937301f01043030d091fe0e0890461d01b60f144182c38030752a8542a6c72ee21d9da71c2f05f59b1d0b12e7d7ed6a5e7be9291d8e49c3b6a17e73b1c002d7c5499ea15a6e7bc9d38ef27ce9b89f36e82f97c68b00933842d1eed2c7bcf7a8b964d36afb1160f6b6bacdb6bac4b56bbaa77ceb55b4a8b5293c85a63b3b6ab76248d714b94b64375ea0c9f84e543aa5217f5ef4ba5e80db5248ecc0c1292315b26c25613b03462976245ec3e5fcbd68e209e531f9fa71f843fffca20adaefced3fffca0054f1381ee9362c1e5ceae213b7d54e5597c91a36ab3b4ef59cea6ed2ba8acc5b21a5abe30eea8129f7481c6ca6b075dbe6512daf7ea6536e0045e8d937af5b7a7ea5c0a68f1888fc00d2755d1713e59e39393f1ad6436d504315403123621037688ac1f4b498881981598ac194459dff00427550cf2e4487e82ece9129f7c8b39ed585143a679df7b91fedc2c1660a526ee7278ece51a5cb4b99c2cb967be68c3a52de2d1d5d47b674b447cf38e33def0ef09eef70d7f97cce76cb46952ee5c9fa416f38357ae8dc5949914dd0457208c9aa11e2e2e097e7ec383cde904d84dad2e1f9e69e6f658b73af6c39fd189a9d48b3ff00e20d855b043d3b4ed1ed5e60170f865a0b2daf28cf6cf47c5469b6eb534ac6af93369d140b0c31f0eb2775c46b588db3dfa786d198cf09b24801c58a124c641102d582c5097a800311586e880286283df5072994a400c57a8cb8a424012236e34604e0c48a306234ce3d2d319062465a3c88f5d094407800ec33a5101e003bbbe7f1dc4beaf07cf4ce1b5dd81c0636f9522c41b59b3d77a764d7e9092df7895f748a164e9efd6e614f054f68b05d791283aefb38daf8825b1bd52e4eadb5d68ed613bbb71a726047d6cf63791fab03adb52ccb514a291547b15d588ca21d67adb5a5adb7e3ba6d7777776b8bcca6b6eb82fd5afaa0375c370e65b9ce65c987677e29910bef136dfb58f2c1e4c37ee197aa94c9090cc5facd78ae5f22c0532729cc870fda5bdbadad387aa34b67b7b65bbba038bbb5dd7a4ba57ca4522f3935364f5dac4b3e2ce50da77170967c6c4bbdb4f4928261cf4f93e23c5dba386eb78649a958a0b5f6937c3af3a9afa4b0eb951080a73a4faf8f259c5f1a57d85c36f0e15df796522bea3181a48f762df9b09732f960d3fae0175da55ce8920faa4365344358ff90551ba8f4863da7edb66d9b8dfd21fc944d4faca4cd875f1886a228565288cd8b95448d3aaa4c86baf7de94981a5bb4e4615f5a2bf4d7ca952bc96f3b847949c1801f0c8cd771301b8ced17ce8cb067eac6e25aabb76d9b4c5bd6c6a94e7801db1c36c72bcccd6e9bca83e9b6176f0bd2f47a9dba60b96d1bca5a4ae9b6f150a7edd23d8e620dbbc1223cd715b776ab174e30c2c66937a537368ab03686cab0575d57d898d128a2be58ce82638b07e8f443bfed9cb5561c2deab625c317d192e14adc624819d656555798081d79cb9539b21fc2dfce664943d334b7e6c565bc4143a41cf85fc7d510e1067519d60b2dab0dd146a4fce2d708247881e587f0d35ac20be1eadcb8df9a3c6b73a5bcb970a4109be73c2c61e4e1bce438ce398ebc7143424dcb14e94829256500801896d0b40cd22d9aeb71268874e438196ec21b19babf4fc7dab23866bbe809332c191a991d8c170cb9cefbac88724959dea80dcb4a6fac8365f53cbbb1c76d22786e548aacd4b5a53490faf6e1e158cc65b496bb04991b6205937369c3dce33ad2f3cd7696b3bed9b256254ecdcd63d1adb78eab3720420ad3b830c336f350baae5623276aedba4a44134f8ebaaed6256a2d2bbdd9bcd625b52eb1a2eb6a35aab58b5abbae12516bd755225c407f1359d0b0d045e63bf7bcedc7390d1b61a85107971f37b5edf295dfe7dfe802cdc17bdc959439925273dbb62d44d5b73db64b9263216a246b0ce5d296698fcd20189294ba2edf6f0699f3f1b863b282f117954a9c42e5516adad96577b6bcb1fff00fe2154b48d9c4699a36759c37af95c8e3a4a1ca342ecc34a5d65a6bc59b256ee5626e8c543c905840ba51e256f126895b9dde2071eb883a6214459d7a53610276287d0173e4bc502fbe31caa881ac809217ab98302a402d40619bf356d61fe6c1b3b36984477564a83829b87020432dfddade2e166b46a45487368cda20a2116f66b7d2b8d42151086137154f9678caa6581b7a9222ba42f7696d080805f7696d68863b069309ee49af3cf5a51cae1053d0d5d39a104cd09a104465b40f5338859c1c55cbe7f46323c57a3939f83544b7a5268410429ca08a2ab1c67b4f6b4294e04f1b32dc3d5b8b42ac826932990c491697235412125427494a33380b31c3d7ea7cc450ead0c9485fdd3b798889be8a3f8ea3cd8f3852f831c78fe3383a5df2a3dbd1bd1358f9d12f931f47f7247e745389d38f8e33fbd1735090e547df51e2c71468f9d1c59167f4173d1c79c450290cc3d06f171fd68250e2c35a92251f86b26f067faafeb3dfe77704ff09495103428ab7ba33ba9ae76ccd6f4eafe0547fd6c4c08437c053a58ed22a74fd79fd598fd0a09b044c7cb77b351268f11d5482efa02bbeddece1876fc7e92106df9ed383956f67c187137c3b0f1fb4f8761f3f72f8ae95a08aef762238c8905401e4c3b75713207dd77ed8812abdf5192b6a0ca47b59de124e15f2cbf28c5cd0c9ac3c716409932c3f48fd1ce9800332baa0a20b338a965ca800469eae2a251e7ee001cb0e3278f6008c3cccba3f580031c6134e3440611f22662e289a010b8030fb418c2dacf2a7c413339899198591872d68ade0c2e54f1a050712dc0007306a388c51cb818a226a3a94513bb254dbc1e8ade38c3cf64913ab13469e56e900293182203c3b00461e66c93c01c00d5ba68c608ab77e7365ae68f1d63a8e11a86e98c18491c77aac1b54353620b121076fbd84ebfd245105e81a79ac559d10c58f12cfcefac9410d613cbb39f27091aa56c313128eb08019e1aaf0a768060d4f9efdc67dd204a6be6c2c010cf0ec1e0d32193cbb0d960f0f5e4c01d262c6165c24f149e2075282aca0a1a665885863812204af96234f579ea188873d2154a2ec08156ab22fdeba1fa9ce7081096fdd3bc3ca5b17e176a14232430666f4e0add760cd00c65b771a6619752693c974c00226a50039a2d024aa24842d4628638632b2d8c2c3962bde3a4ece107c78eb3b2cf0a81979ecd296124e1c4f62d408020e41a822041ddee2c868b139feac01820e4940c8e2a9056f9dc63d6005c82888329ea494e153021d6a2801132c9e90328498adf44bc205b32f0522ee793956fd54d590a1f47a76ef07393c3beb074ccf3e03650990eab0aaaa4646cb1664186989f2ec323ee321668ca767580e3c93c9642588d59ab7366fa9fc9983662d156bb56c01005b916059c205163390bc75df8195b76e16bd751c1ed4e0ade7f4c088b7be73c3db294e55de3a0f1f5996bcf51f5982f0d68128bdf518a6f8a00753c690e2ad57a01a2454059617aad3558c1d88b1e419864318b51412360c200860593750e9fc59d3d4821a802103838bb74e6d30c5104f3650d1420556387172c5e8e27faabc294d24b8e2d947561247bc885174d0c3b3873d8017e98b289efdebc19329d78ad613bd8bf4c50ccfde39ddd3aa52c8c10eb41c50c16359d656b3b518118d66c3ae8d2272586b8353e5c5132cae90e0d9ef152bcf6e594c78b1ea1a18ecc40ba65891c133ffce95140d9d8a5c1fbdbd3a05755f1fbd48e8a21309392074d123707d246f2889bd903d1589110d50c48c30162362455c4515494faba062e9cf7ae5db29154faba02287af57f8057ede6ddd5627afc7c813b260a98ead3508dfe7f6f2e2a997b2889d56a7135cf6d31b15d0e2e1c293d330145005eaa3f61678784e9e93c762dd7b549d9c4717b81932c07a5b0601dd7a18d6f2c431436b6d8be36ec8bd743a58cf796841bffcb20e5eb2150b49514c9545421ffd863e7a91ebe28ecd6d792f098220ebb9f204f25d298407f8912db0d93dd875d4dd971c1d45e6380155a7fa3492a628c4759bb7107d0afda4594a2130beb95a9daa579de80d5215aab6d26a53b3a7368c783e1e5f2c2e4f6b56908efe146b569cb015253f3ead5939f2d5bd960efe13041f025a8384b6506b6d535a9424252a5e91524a696530865c468ad33017ef8b83f3629a2977d4bda10b49632d27b7728f912a0514264c1073f19e4e81163123345e1073298b3c3f592498e0a6fc76946f47fde9270f9ce756e72fee134b91a3773edeeb3eb18d895faa176f90e338ae565a5fc6171f9db6eb73191ffd85bda8f355d83519798ce5e6d4aefea1edd259c1757194bf788c17f580f1b1e580d15fbcc7e82f654f51e73d234e8fd163ca9edbaef67163baa39f4e632f7ee2bc8b8f650450eee228d1bd933b22c1e0721082230eb1c9e49b6e2deba1e68ebe7d0383cba1d22cdf3408dfdc0cdf5c9e97c36188930be2db69e57ce85437a5481abb51727b8a7a8cfee23d30cef21897298bc8f88b8f65cfe829b7b1e5b2c814b9d3ae76197263da9aa88ef8ed1b167eb16f47db518d298b4e80c17541951dd4aef695abfca4b42f56a5aafc416b458ac08c3e8e63291b4b2345aaecc553650ced6aa697b2d67800ed29ea940a0a6a971875e6291fcb3a6474abd75265113bca475aa5b5abbdd2682c64b209cae938818b2a6545d68d14b1f3cc9f2ee3249e4e7901ed9b49b6d44b50987cfb76a537a65e626696f16b631d7143a7e77d8f472e694913c53db7a37353f22d54048771694e96bd3071cfed684b10f6cf2ddd619be4835b9376501bfce7211d77701076eb21775cd9dac1f9e60ae03c509f73cf37f7f91dfe9c23bfba85cdfeca209c77de1e1af1bc3248b99141d8bbb3721fe7ecde67d93b67ee9cd9634e62b359263b9271953d6b416116892a60d02cf4a997962c1214669f1c2c7be92b7be97ae549c1f8b39768953f7b89b7a3ef8d69cbe27ba9c69aa9bd9bda5b4e2ebf7cd11b93e7ddcb1dd19bb64ff689ea6c55821004960f52619cf66963ea247db29696584bdfee42d2f336a94b3053dcb36ef96e1f19c0eee3e4ad0e765b562d6cd61f10d5f024d629d022d67272c53fdd89cdf68d6973da9e36a6ad8957430110d041c626fddb37d49af6a9ea22450e324a80f1d63d277200459578559d7515d158a5258b13903183135940e1a307258868ca811858c8a8aced8813326c14d7dab08a7bdab06036564443135d84a24abc2a7b733881e299e99ea2e9a4c95b2f892ba3a812afca758419154422a4364d5b7c7a19a8f554e6639eae9ea6609ceabc38f5737ceaa7cb53d4533fefc394ce238f3b5992366ce80dfb48de188104d3550269020ef28604c009d7bdc5b0d4f2fb2481c48f0bca70e28c2fb4c0000d89891cb494c08825aed71f94e726cf516cf11cf3ccccbcb1056d786b398c6f29be9ddcd37ead7123849ead78662f503c5cd824dd9cf20bbc9f589e6149d904cbae9e53aeacbed396745208cd895b53aae1a00b4316f7c6883726b4f7eacca81c81620c1baee8205605892d78f0c5145758c9410c756d16f65e1ab7f67aed92611515d0eda798be9d7a4865401034f22b99faabd263939d45f237a9e13b0c82200882e00ccc0813c157dfce476d74b244289928e6c6c494675d1111b11a9401794027a01d529f27c74787f1d1673c04c9d3c2385d952ceb8957c53a6b1e7410c657247dd638cad0fde83df2c080650c99c258b2667c875b98d949400d5208bbda6748206c1a1d39999595888d98c8c908765aa04daa90438719dd7e0f7eb5ab6456342bd68a895631de420cd923c6513c62ca1e4cd4b0bac5a3a1445b9868c6db790bbf447f892c96c7c4c8ac6456327eb2623c6685181f6378665e6688b6b093b312b111c3e8184970c14316355061c595582b61573b0f8c6ec003133a20f14513b194cbb45c86b55aadca5346094d19c36a577bcc503b2be1578ce7c4d0a00cf311e30de41211ad2a5183de60790a81f11e796462627c1543d25fb1e8cbb0566510180fbdc715603c743ac6c4f80ec3c4b88f186f071213e334966a4ada6a8a719ab229c667ca1867d1a61897a14d31258cafca2695e72f50beb1d02430244f215e796b00dd93f57dd914995acc02c2b34849968e2a6badb5d68ea0caf6c9b2b79e0f9583aef2d1da18079d635cb49e78552c18b71e43d217552b95c334a1015a558c0a54f90ed3a8298dd4788d873535a5acc8c2c09442fa552fa85a761cc7d668ad0eec4be7759ef779ca4150f45e543031302b18186bad6f3666a58a09436f57a954d64787294feb312e866e63c41b136ab18db2de8c8b8be55832312b154c790a49a9ac751807411004c1158c6a05530649f9e7765c2165cb9d94b5768663c9c4ac54b64c39cc4be737dc72562843b60f4bef234f219df53ace6edb5963759083c62d0dd9e24186554fa036a7ec52b3f56c427e8be137a577f1d5eab7ae3740dcfa3fd8e495bbd8189972f48d3cdd7ae255b1ce9a576d64e8323210d1e1fdca77384645b62240c39bd4f09127e45f39499f8a21696bd0288dd0701a1ed220c33af6a051ca8a3695ab4a21fd2b1abaa8c41a3207e73cf5a05470ab8c089bb5a9cd1dd8f856c278e881fe327a7df1884d282ddaf0eb29f56a5359c3a68d94bbb9dbb0d9d4b08a445dedde8d29cfbb2a4fd6ab8890f116fd257a6fe44a4537777155796e2ee3755c618b2145df4899d1c7948cf834be9441c2d03d6bd36f4e550bc3689624aa98f283122690c24aacc16842c809136568610519b14b637a3d2272596ee23c8976b323cf6adb5c455f15a3f2558caa0cf2e2a0db718597addc61733bcd8625805d9bb7e7d098db4ccb94a7c362cad35ce56ce58bab72beff85f43c458a7e49289ee7a0e8593673b0b0d9ed350cab311b22018872ab536d62b35f84ae144700e17372f04b14bfe5dbb60520c9653f6d6a88c5aa2a613dc3011c1b3db42618ddea4475da366cf45ad24bbb65546a1de3a9d72c54858aa4b563f3eab50cb2c35ca33a9df306aaa555cfbb9586a4aac04ace8a8474e121ae551538a99ea0e4995d9aa07c23e2a18631126b3b7a1ea2f2a7e51a928d62694955056bbba467c7c121465bf0f90eb07e08eb63f48cefd29633af869a164d352b3f4f6b55b4d4aaece0c7a7b52a4c5f1b30bb42bb11529b7386f6ede116a3ae9a314cdc84986c4448b6289b8cc8055b101351173522267f6e46dfdbd146b3955144fc3a3b941327eea99aa96665c855d514442bfd5c4e236fcf0ebc2d5547aca66f20d58cea54d54c3563d88c4c75a48aa2aaa9a84021535d51cd54482a25d5928a49d584220a4125334824f9f6139cf22111a96643ed5535db92706de272de9533337ad3a48a2355462c267ae3a2833b93c2e4a203171d501df60e0a32ba28a086a188dad5ce62dd8b02fa0fe99b55258aef19110b45d4309726ea6a77faeea7a36f94ecdb754002e1a2836fa724d8027ad3bea188b60d45c4b06d083543414121a194f8456b52fc7ca3a87c5b26285044df2e3528921a8aa03f5149dfa81a6a09652b38e3d7a99a1df1eb045b001af1eb73e2bb0970f65d49ae600b3aaa33437ba98173259a60d92a0da09872058b01d4568f1e14a200a3c6de4255a17beaaaee79f764251955f1da05848b0a6a9264fbc9933f737cb52d6b85b4c0b094acc70f222bd8f2d56c2268121130f8935e2182883fa9d3d7994ab7d8ae51dd865fa8af8ea3aee0e82b114cc4efe873c19f348a93db0a5c8daa02970158726b5087d4011a48ab81b40fd4b050aa6181f4b486c511162c78ee690d0b228f0161e7b4c2282d5126eac4b1d09b550165a355d103d4d094135441058609d18c7604c912f7e49a984b4e89cdae327d07c65b36619e07bda1955d4e9f2b36b515085da9352155076cb14e688bd960e29e5c1387c46607abb1ce392dfcaa9f147275ef2b735170384da9194541aa5da9512a52526de90ac73511f9d0366c134bcea95d1dd7d4aece89c0b8c039932748034370c4e47981eaa8a3f93917fab95ae6bad56870f4d55989ab759d10c33ca6aeeb3a2647baaeebbaaeabcc3df1ebe4ae7c57030aeab8a72348be73ee0a09811d866adde484c431e1d7598538227e79e75c10f6d951c342efbeb22209c90ad4aece2dc991447470c90d953d6c769d900d17dc931baa4243dff9c93d7de7dc13bf780bbf6af73384480f9b1c735c5dc96a3410e22a532d15c910223d5556812a123af298c0c46dade0bd3763b3fbbce923392c6cba66b522d83fb26ee416f31a56c4c54797b293955e8fd0c51ac93db50bf440f0db86a648f1047e1e37e39ab827aee6919c87e4e6dc8c6b7aea645cad878f177e0089a1f38d64b5abf32645d773e47333cfa59eabd4f38df41cc7537ae395a710d0678771b0d9792569d879e75c8be36a3aaf434eb6efbc46e117ad3149face69e7674dfa6e057f8add1432e8a610fab342f9aeeb2a0bf1eb1487f8755e227e75278e4e49f731d1092df167e7e43ba33f3ba3ef70b01a66bd736fd8e65dd7754c365a6a965adbd96062b61da5b44675680f9b9cec398e13e221aac3cfb94763a4eebcd57d4356398eebb8e69af3b6dd13bf9c38af5a38fe79aeebba6e46753aaf3527cf11c015c6c56959079dc646073d02a383a21709bd2b232016015d2c693be83beca3fbc4b66ef41ea28f622982e4b531823a574b6f5795bb397b751ca08a0385d5d913ce73b424cfd5dac373d4f57d2cc424780e87b213bde17c36a33a9c84de208104cb88d410cff9f971f486f35aa33a35f8be548a52ee86a66a96452994524a3d6badb5d65a6b6570f9d5a0e739dd51cf38c32bbbcda3e6e622f588547b7f7ce02d09a1436287ae073515aca0633dada96087079fd6545083d1c7cc520c51061884db7a5a1b82e98821a0c872534f6b432c61c510446014432ca90d71c40460eda9cd18e206ef89fb0da10302196096cb3dad2de901d79654e161c3c9c14921670a120f7169a48c71c726b61f28c13d71bda7b525478024b8ddd3da12262ccf528f06f77a1eab65c5053ab08668ac340992799af1707e88f1ae27de29b624fdb0ae151b7a5811cd642e1941aa284131587080a142b6c2010f2f34151640a9284d30b41f2eede9e50813a0a2704a5541010f2e50c86e151d4621145396204404d0825c70bc2e7c0871727052c8691a3d1b1c01a310a1d8e18b0151c8d484270512c8644450370325eca24cd8e5cdc009b39892f470c4a4030f485d9c7104a80b1fec80001accbac8c10e084002ea820b200448699ad2456d07042411b58b7a24ccc0f33ada9fc7ac05ca0e7fe268b93463744d9c686272e20a6f06276a00323921e506276290c40925827022054ee480e44261e23c15dcf1e9942686108326b0d026bad8614440134e5e1356ec2042016a9797a489273e1634b1821e9af0a1891f1ebc256abd8327653cf9810d1cf5ac87002768de0faec7838e76bd2fc27872c50c2ef774ca9329df1301a6c4a8246c56964dcd3a552310000000d314002028100a87c482b150240c14495b7b14800d87a44a6a5298caa32889510a196380318000000400cc008cccd0360097f32720e36e7a6172fdfd6f24e2fe10e76aa9f7c1b6a5611c7cded1797201744c2cd6bed49592bb54bbe5bf706fea3d1a41281260ce527ac0109b5ed61822337625082c462907eed847cb30f308b2e3df8b92a0d129b4fc7b8005052fa4226dce556375ae6516cccd400e6f94691131cebd80dbbe814d54b3de953644e61e7a9d80598c26b904ebffea588500478978cae7f177c59f5ecef27b5772750672045fb7dd3f47d52bbffd1aa57ea080a0f64fd6837f26b61c83209d54436e960048664b6128a6d53a4f9d3619b2e62e35b298c520d978335dce1710077b49680cd11e614517dfad336ffa4cebc73e5aa0f58d6ed39fb13e272dd2c7c102048410cab19495f4843a81ffe6871386c61d4891fb185c850d89c05ec0f60223e2b0007003ca7e49ab443207e016aec621c31818076e8088f54a93d29e082f34541b1d0bda2bffb4d000733ee353ead73a5c6abcd6101504ab31ec81096dba2686ab7dc24ce6f44d46fd1435fccc4e8d48226153a309c5866d856b205a90c873cd6e9f25d18660c7098d211dcd3e7cef9749d0272f5e609554cee8bb21a264f4489d995c8b91d5739deabbfe16319d6d804da3e40fdc031efc63ed0826db742e6698828c58eb681e2d878e820c9e917280cacbe340e490a38bbd7a61fe24466c93783e11dafbed0d91323911ed57a719c32ac674dcf3c3800da83a40ac56c4331f7ba944a92ce70c16372b20c72c69a09d26e64c98ac01f844ce6430ce09c98d84d0fd034bc8958a50e19d1d0a41afd76f6a2a50d07fb48092163af35ae74b6852045f145c892c43d4d4fa760367c311691415050c4fa0f010cab5bee15ea74a489209a1f4b58c67ee90d54d2947c9ee42ff4fb4fe428642a65ad53da591181485b7a38357e86d6e336b03fbc0b114f1b002d3ba82c961cd26624d32c281511c6863d797fabfcbaa4dfbed5cb908321f07c0ce4aa20250638ef199b23d7f1d2c3e487b3bbea0e978f09bfedc1ed4418c9bc34cbe1981becce2f2f6ddf88f76d94869d79f1fae808ae801aa8cf3a48839264e21ad283f822a5eb32a2d96c4af00746ef3f719340b7a7659340bccfa9e85ab2fb9439ac830ea59c0123befa35edfb50fa09503bd2fe8cd0ef04667963512d66fa9d6e3a7477501c48dd945532f84dd4414d70cfa3b29974c05cec37a15cbe08ab48cdee7e80bb896dcaaf1da44ec2cf60337ca6cd540f1ca8481ff63aaedbad5d45d4519ca409e775e609b7d3a022e14c5e88cca8719b8743b29d4babd3e62e47faae9b86c33b424cc47c126681d929e1afa7198143e32c8dabc9504c38a3e9da3c51184ec80211de7b27b122cc28bb29701f266e335756c02ac32043b541b73a005e01cb4978e14e7b919d4804213a156239aae558ef4f1480c2ed8bf2af8444812c369777f660239274ce5bc2904bae95bec6e3f79ff806f6e26defca84d6a563490e4d370082f14a7ef75daff388d6626aa12ca9e937d1567b8d2012386c330702b05adf051a02ca2655a25beeb9d02279cb136f7ebfd3ac7d26a36b147f6a367ca5814d02b59820a87be55aa91a0989b9f241eeb31881215d645898930c6ae8200a5b57de27a99e309561169ea7d72be4a5002d5a74360610cb38826b711cc8aaa0bb0eff10ee75871f5dfe0ca57c0e9aef0da74b1c3e63de12af7f25b5c14de136969167b1a56395cbd22bc703f7cae71034344d6b69f4e567e92bafa08a4c308c570df80af584201819ca652bc3c8fd813bf94d4d5545ddb854a5ff94fc4978916131ee9ff44061a04ca923750fe52d53f9409f1df7bf44154aecefc8937049e736d95826f4d21f7ce92b8280e46d9e2eb1c7b8e7e62da55cbc00da4ffc99b438fffd03b21575972e0637ef8b6814669a1768f00356c54ca794f35144f0d00945a75a9b5f990d0b4011d08c6129c2ccb8da5e5d6bcc87139db86c979f4989f3bdf1a88db028065287404995e86646a187d4840972044047c084466ea09dcdf0ff0ed021bfc559caa1aa9a742b788cab643925b9d84bc0a1815e40362216fa26f98b80b725b83de442f45f55de27ab67e51bfe51eea806a014454e092c0634d253b06b8b5a4b8eab82bcb366671e107af79517cb0599a9d22cb3c116260801a3f77ba182f1d52a038675807b1dacda1b93698f21673d8519daa0fac0d7a2ad220dc4709911cdd884129838e8a72605a19e2641141b4ee780dd5c6d41bb4526a359003bd6a328e402ec2ec7bebec1036afd8233571a29fb024a2aa06a41309d64e0468641acfc7cf4f26238923c5a3c5bccdd1bc942aef0d771ed89c360021dde9bf9646b0bbae635713a79ae6aa2d2dcf004628c71de9cd29317b42d2a7062f369f2f78a110476c28a792213b4f52344d30efb6b811272cf1045ffd954d353f801f18bc69d74a313ead3bb4164a0b026e5ac24b90dbdeeffa3efd9c713ed7619354c75a92544287f2f17ec3f742fd9d21adcde9b2958256feba321ef284a55a8670daf76bb5f0e428de5dd86454f95d7906128c605944dcfdec3bf7df2689e39c5eb527705cbbdca88aaaa0c38902244c3d0f279a1d617a4e46071bee1c2db46dd355a2815617bfaa249907d0938c883832797b2b166b127792ff8558785c5b5dc2e11b7e5ef096cf53ca332ff41285112bb5542c5110f6e9cfafd058f3768eb49cd2adaa48af00ce94a6e60e83a825610469e7d32c700020819273be9e4bb67c1ff6f10fe74df895c5cac317b633b1fa7db34c89ca20dfb94d896b4b67c8c8c50c1409b6de95d461632c017b0883b628c2bf7060f5fe1db9585332be19ddda8e6e2bd982a6d8d3805bdb588ab7a8579f8160dc97550237ab5e6290d2ba669a2c8533500beac93473fd69f014b07850db3ba28f60a60d633e836a980f1e3e4620ed0744217c45955877591d74c7d01774b463ebd376185f428db325c6ab98e068a02a588d6c9dcdabf825c111e6c4e74bef201fa945c4e6121320f06edb2f9b89eaee32e2a84cfdb1adb2ae31ed174670863541c9abb3769d647b150673194a318ef9a98e1fb5ff3b722bc600aa9b0af1c9cd3ba11acfbe877e0e319828cc57c4df0c5e7a1244e6cf2a8abdf1b7403e1708d653f15c05aeabfdbc0054b150a3d8592fd28a71fd747dd54801a99865203b37def102a066fa054e6dfd7f27573ca5c69471e4e38d328a462c04adf9bc05eed4af96ee62831efb6d151f3131e1467228127229e53126b868edcdc1ac57b49be96cc15b89e38b6578087d5c6c8c2c683a5903b73c24ece7f7ff3c9eeb1bb42839ff61fc8c507e061fcaaf5d3e6733bb6fe1ccf1c617749b2566bb707466c4a0f193a62401cba6c53b955a9609cf849488ed7cceb97401b00d65e87ab5862f5af32079f458b256db9ca24d574c813948d5ee48a73e0cea24f26b848020d4c947944223acf797cd1cc88e864bc45fbb7c265e0a0e11435ac887bf7d37d77aeeb84a6507562cd89f8d8632f16318a380c6da6902ab903c662bc57259aef10294caf707e9d568d029fdc4beca267324f4790ef95744e005fb6efd62ff145df34dc5e0a78cd01a797a36f6e80398dd5be66481a6e49f0681cd43f526d183aa30690740355bc9356d2a17f0b2de0175090d8800957058a13cf027b8ff016bdc3df76ba19a64619e9c0388504d578f370f10afd8e8a2689db29f6525608d475c79982dcaffd96349bac8183c4d3ecb169023876e928594db08995ca6b5853729e3cbf7e13393852085d4a8ccf4b33f64ab51569b3184451316339dfcf60b1953bdb4cfc12c9ed8163e0a9da3d40751c07cf4ace5f3a19f6e60afb3127daa5b0dbfe64d24d2668756121f8191eed60a8c1b136f7f52e63aaea5edbcfab394126fce530cd87b5fa56fa42d35bffa3556bf91eaf041bbf38d7c5ad31153ba6ec2d92aca8bb781e9c94ff6d5b3b234aea5210d4d8225f4211741a0824adf574857c620d9c28a949d5e94cd79f92d72ddf455b2ae0630cccdf7630f7e9f4f350954323c3d2722d27487b807c0abbfb8ab6baee129b1585f9de68e88b9b808968f92b871d1e9237e3a8701ac7d8d5cdc695cf7352236763df4449cb9a39aa467559ffe1070269dde01d7252e771e821f7d8283e7d1ad332aa2f9abc29ae813a313c3c804ecf9ec0014a557194632148f4de2644458c3abd0e37c97c3b11ab2a2a3257ee30a71d0c0e555477aa08e78157acb2e9ef2ca309351e543fe06807db71abdcff0329c2245f749dce29901b582c7df6438f1c24fa66f524182ae96b8de7ef128fba55f1a71f41f3772dff136857254d07d0aa52385a8f84c3bb5655c47f79da1a0a3e1db208bafc3b97ca16d0fbf54d17e3d3555f96a5208191d83584a09f37c7a4a56bc15d1d5fa9305a50989d5d901c3d721e7f3cfcf24cb64102d31a318b1aadcc0436ffc98da10da32eb46474d8a2bb941f0adce0d7abde2ac8d138d422385352163621a49c9047d2299b1c69b3faa0bf61450e199a0d670741704041c9e2e8942746e2396135d0c2013865ca60aac6006839a9561ec12cea979a5a307811a51cd217e1f95f93729e1cb32cf2eabf1639cde6f58f8fe76ce372fb49fe62eb322faf5cf9e3fc8c84bff502d1faef9e228b9799671721d05e71e54d4db659455d5d58f24675631caedf8597a15a2e45bb559df6ec7a2e28b6d13738f4249883adbff6fafdc1c0e82c474f2b2347eac8e5bc13d85b0a46f18350fcdef6e96f1a66e30215b16c1b706073da62d4bcf6066f7982e3573f04ca0d76827a3cab2a874fa77ba0da88465b55e4dd9ddbb0e2c521ec60a18c7dbf4d8bc8d58c36807098fcc058dcf56f6439ccb70c26a5e33f1d84608e03239459753d9a5fd980c8dc6f6b47c4887dc50520509dc0acbaa603a3195be497a79b43a5e2a549e6c59ad26c9010e0e69f0ba5d9e6b0328cdc9b392850c28569ad8746f067c6f757a1baa038b08e2cdc2fa8c5ca4402677fc5c4a5c10d4e85175951a9bf7e94b5cbe9c5f446c12b6fa4066dec3ad340dba5b73d5db2f04e6312dd379b99277066be7262bc8f4d5889a09374d4d3c775d843ea8b3ae4012e620e72751737d10d72d46126c9a90becff6146a447d2cd3b72e46a289aaa81e9ed61ac3d60f4988ea157f97c8535102359daad76507051514c72e989a023d12c4f746d2881cf18485d7ef26e4243fa8d095a887f8e8c18522fc48256b6c2e0856526c8a03a63ebc6fae8f2e638c93aeae786755976b1348566e9273a4bad672c5d8d6b3230a2c244e0cb6864440fed3ab89f66d37187141bf4d9916816511f867728532199eefeb090a7f56a0604979da9eb6eb11f5eda00fd76919370caee86655d8752b1ee96f654d9449eb86f66ac50fa6a4b86721f35c86228c3d90a77ab4c619efcf011f053cebf757f28ea5eae1b7414eb17592ec018890d85ee2da6fd133b1dc4aa095b023673cbaf1ddf940d2df100272209a32c33b1cc21949a316da9e63154db7174533fdce79cb7aa141bfcdf016134161af240930ee5c1d98ad16995d38fd04aec670528be3179dc72a770074d794a8669fcecccf232b95576f7b9374581f8730c29f90698947f28686cb24c15c3619a8a9c1b30e4e9e9b2d31548841e8e5964afec7bffe05366290b2cd94bf1386bc06d85327eecfbe70754bc97e061e070e49a960355047f340f1ed090a29c137e520ce1642a5f1b94eea082deef5b491c8cc86f4b205500fc33a912f1ce873f82354274d8e69f37c560403cf0dcbbb3232995362fd418eaa25b1bc5915fcffe4a924939e182901418f52b0cee40165a1e97d7e64fa51329699ea5f75aeefb766425829cbb6f386b0a5978d26f5177474a949fb4be41c5c4e5b2776e220f5cc4d8b0ce23967aaf95d74bbc3e74abcc0b40bda78e7cf59c590532a0a38cacab2836c9362b9791679fbbb666549fe2c156687516eeef3c6c465316ec2eb76e206deac2c3c299d1568943d6ee9973cf234d93f6b4b5dc1743c869ea0c45dcad6657fd295864a773a1a8a09b9db61d2d04f9e7a09c5d579f1d1789bea4620d844c77f66f49c2536b89f247c204ad4fe4c90d4e49f436612d1c455538577e86b2743ec032ba5898aecc70bd8461e34c8caa6b43f2831879ee70fec55d674b1a4f58180cd73dc82db0a0fc16cdd85405515c0a1c0bcfb0c44eebed38b3fc8f1c657a6de16aa7258e58b670841494ed47a3b9c55e37964a0a6e02b41fe26ea38ae3877989a50ad83c44631c50fd3934272630da357aafc3c0775fa55e62c4f5652320ee9adb435881ce52b09dd1b7efc2311f73c3812c575070c26a6cb0dc8c93d806e90fa58d53d4274a408b19f3db6038b05c82683410eb0e8bf06c02050131e226c86fe89f93def15ebb4a3a4d6b27b968517560ab22a1915798d482bd485bf8dd0016dfb2cc0db54e45396ef81e7cc5fea341a83a609ce9cc36642220765b6bb34c111e8a153ce70e89b67576e029b1d8a1c422ad24031210f432505588a117cca017ca8aedd7ec7e596e557203369e2001489256c0f23a5702909fa3c1f0242203ffa8df1710ba426c857babc9d0b44def7aa64aa2b3ae8c8192c22c2ec8860e2367d3092b1d573c35dc9eff49dcbf81ba28edfff8e5753c342e76f054290b1285add577b9c31d9d1bac32b5153d26b85245bcb0ce39b2df9ea931c25240d3c45a1f740033291119d9d743fef667d0e364829503dea2a20be61164e2b5dc13332c480642d3cfebf2c6d4576cdf102fad3d194659874c6ba652297d038e6b56528150eb868d44a981adfc3bcdfc402e13eb623e1a8aab5c0f1c4a222cc25fcfa5beb2432f5d170aa7283f89c2ec26ab678cbac5a19a3e635506cdb89c176c5e242739ffa3adc30b04f2466b15e45457f812d789ec214557dad9ecb4c784bb879264e8c983308a53425c63c84b20e8411779fd37a717e38c925aeebf9139980b8fb25e9b03900945b00eb9ce8c484c732fe3fa8ba45df6c0a1e585c6af643c4f5ed2eb7c8fa87d102e30486476fb729cf7669b0c4840b70de13a74ef7a96ec26accc22d71fc37b26a5f0a8b38a902cd133a1a7dd2922077bc695897c387fc39f72a7477a75464f15a0e6ea264b8fcc14adbdb45d1d55b05459c55ebef11ce2692faa1c6bea487b474509d69bc61192e5743945e10247c40f5411b3c436d341d5f4a0399c721a9cc48c4eac8cb6d4301a1e6f554986b7d34d94045bbd01b8ee63049ca2e3867e079530179b68605a069f5399530f13160513b549f938d47c970a258f82aa5ec73678dfacfc2ca0ff2651229e2d2c4ba7e861d36d8cd45ee1d268902bf08ccdc8260c6d58022112a37caa6e8c3961404a077266fd4a09871e81407a2304c144c0dfd7634d90eb24856b644aebf2f5e2800f17cebfe3a5fbf5f6f36972319b409f59766b1ff9fddc7deca32e4b58652cd410f859c415b8686ac0caecb4fa0a1eccdab11dc92a3cb74669decf2591077a11487448a5f4a69c138329a430b9d85c03406257b7338849fd5623e0caf7bc4f3870ac3f4a80a7b20219fcba3ac3cf5809841ea4a8a617336d0739b99ab3a0c57dd07d8f5971bd722c69080cb39c2ae43c8ea2e00031e74e1d6a20a85fe941f2250bb13ae4b63eabfa9e5e6879ff96e2f99b44209715fd6d1293e88c4ddf7117aae4a0448e341761d8b810aef722f9b490571bf15347699efe2da466f8bde82d6bd7c20ca5f871e439847642145d5c275b91909fdd94f554ccb5d47d7887613c42e14871b8511f8c726ea9c3ee6cc88b1552535ff7fc0b6c068f33bb86ca15a185350f4269d178ed6796f0a330fd52f5922a35189df15407f828a99c05a7b2e47fadbf690d31ce8a97277050620884a52c8030b5300d1f507174bad5eb038e225f779834096ed0174f4dfe90786a1d57990069c8af54f8f22c240cdc8f8d7f06c89effd09db78861a91b13f78494272bd30bed0a809bd8177032102d0d8df69054e26e8fddb6902990974e673ea815041e8f6edf481922034f3e11481d219f4d6cf69074247d0ae1fc2266eab0074fadfa9033992410beec2feeab208a93c54aa95fdd707e4685cc87a9067e01d81241ba6138aacc0d73134d6479c98c84037a6d72e1080e1abb12a450be9123b624a6e0363faa6649bf10ef4dfac99248a4684f46d96cca50a47a15c5e449a44bc581c5b54e9c80aeed1cb2339b845fde8948c9289948c668482c2fecf04a5cd75279a2ee5fd2b0eebdd0385e16d23ff1ffb0b7a06c4b6b22a3c93cdce7db044eae9f716c1632cb9a322104ce625a38033422e4c7418051eb75b4c5c48d0e30ca7489d9088a1220a088f30191a50a12870a704e0982b4e893d82474f506c215f355840e913b2fea74260ac22ba4282a0be159b99fc3a3946c0ab8b230aec5c7a1c425890b3597e48b3055960fc645b7b85cff875cc175f663945852265e008cac12a8185dc845924b37928f0a7bb281d008107fb705bff21e32430c1cca91380fd74f76f437892bf045e1707a13657de12879d708f5cd4a9163ffb23a0d1e796107cc180a0d9120ce99c8531d50c246c00e379a32d453c8d3bf7df833e4613204193abb602b64bfdbde935049702d541d3dfae5924777b9818d8ce55229212ef57903e7db33ecc3c32b9566abb86b6504149428936bc7464c9ea87a79300f48d1efd0f74483d0609e65183a3072539156ec8dc483f426fe426873213fa60a9901b1d4826347d4b81dfe8403cf1020f45e428f9ec991d872da231c3210ee120e417e9c0a422a78336a168a3804aa6887cef5fbce1f4a07c0db294c2561ff6e00a2875593299414a8bcfbc08808de01ad2eb25985dc5d438ad1834a81549546a994c6cae82f1dcc5146064c8987dbdf4b31cd3a0472ed82a1d0eaff8f66f6316a5490d82ef69e5f7a0d11d049044ca0ba5a61d38fe36382b7e7393abf9448e3ede1a0fb66f26aab2f8d2844f8eda63cee7c2f173c0d98603c168e4b9fbfdd905c5189c0b1478c9a0916d82b348f2d87111e4030a28547e1976c7c95a349272f53c061c968bc7d051a58dccdd0f958b747852888d758158aef88cabec45f1fa316d7b91adcd0e01b68f20c0a7ecca04e420f2c56a8044b225b3ba464df7467f4113d50118f6425aeb993e911be8fe0caac35a872907104c1ab9a05326f43842bbf4e5603c92b2a9118e19f01e85da549d7f08a742e1a3d6ab61b8fcde5592af3802561fb36dfc40d0c02a777392318422f804028d604b75649359a35bfb6702000e2ca82839db31dd1a0a9043b6e6b76d1c8403d0be39af5ce5fe3e735a14b036aae20f43d4d53e5cd592f243af0686bf139df098c1532250a7ad260cd20ed0c851357e0ab99361980f8648f1a3707eff8f5b3a30f81c103f9011224e438c3e1fce7603fcd31eeda568959db6937f2766f2366ed40b2e3efa2087f043341e20cba458c8fec0c8703c442314aa81c576717413337e4675ae70d7a97648b5ea60dce81cde2aac32e3ee85550dfc46c97c36e328779566ffd55fd49c0e97692ef33a559f1d47fac5baf193f37aa72b4b84ea74cdd59fddb062a070a8bea0d5770e8d67c8c4a8aa765155ed4bbe55a496bede2e1d572e693312b725aa7e4716c0db71fb048de676e4db1f2986d3f0229e26eb744aa1f80c93312e6243a1921b70815087545ecfdb551ae98ff45f266fd81e47b746c67bfbf05c94dc5d1e63090885d48e3d77e2850c35f79bf0947e56da0945ce6292ad97271ff537a74da630e8e507f76fe2d43bf2a1485482ba2769d27f9f802b9ec4d94fc98f795fc06655857475a36ada9861b876b7924c469f5760abb5f802ffec96455c86c67f642d7f09042f2ef869d4096e07ab81d8b3f1a0fb2c17596eee0c10411f9a2018c86e6cb60ba31f4c7256680c86db8ad85be2773444910879fcacb9c4deb4f5d6b90d5644663c5781f8b76b52a466f93dbfcb3d4ad5a99ceb109578240fda013a17ef4547f12e28a51af9e8f06423e96c1e5c542b0ac3b3aff4bdb65b0f9e36d3c0edb4e585cc3cce838bb46f3711ae3f669b9dd01e0d102b443219d2e4f805477bbd7c9d3c911abfb4eeee002a3526a6a6c2f3c8e1996c91858cc553f3783c1274ba9f5c6c0b1f7e6efa1816db278cedc981932b2cc34aedda18656a3699e0dd8f06901fae1d52aad8e84524e8db022ef03486c7de043f88bbcaeca541dff2b9bdb6a4f5061740a5a2004724618f723fe6b7656850debc01b6867654344730a907e3dd7379f71db34c788be54f72b66a003be127c39585ddce695fe07e2c9606df97e0eac37be11a9b417e2b58d38df3ff0c9b6e30d4f7329554a3cf3ffcd9eaa6fce8ab2088d12d7ac8ee4360801d04897166f91c18230e58f2b87005d27a97d0a16c27681cfb3546ac7f0baad39af0255cbee32ebd18af13a61ade223339639c5efbadc02729818eed49bc4c2405a53f119f45c9c4467dd09111e7338051c1ada00a901da7f367d3ffda227ea6f690fbd554cb818c337c15cc4c786af9c96392da1127d2f624002b560840b1f9a32b04fef6d3e5874a7659532116700faf867479a5e277027171d496e791043c7fb07752d9f29fbd65b5de4ae75bec535b6bdc78e6e0d097fcdad81d86b5867e8e9f24bf2aa228ded4c713358d4c1a96337dcb60ea6d32f48dffd08e782c43725c7772413d8dde737096cfa3c2865993ca6bb1bfc811154f46fcac932cbfb70725402023da363d1bb4b9aaf60157a8df6d32e88e2c0a8b46c3db8b3b918388d5f1e7155e317ece219d4f224510a3b548fead2a7990bf4150280bedf8496d652224234b953b3c460869d6212c24f50b33512ebb679934ed9e0492efdea5f62e63113d28a14f4973662af998eb833c59d678c2b6e1c965dba920ab19cfcbf2d893c388d531bfb0c5206027b3e8551c698e317c188d61b8c019c824bba3b969c91203e51d8c4a3d30d6ec5a4eb336cad003fabb555d5cfa4bbad85fcd6e35d30705768e69b775d1d5e75bb34add73167178bfaf0b01c050b2998036c3caad4f060992da2d624fc7e68fbf4aa3a3dcba15d4353228b5538425da164bfb8a2b0db4a741b9826bf8f8b3a08665b8b44c74bc9355244f3067258bb325b0c7104e172c610f53d11f577d20f31499adafe2c0e19c2e0a073a51910045bfd7296307d45975ef922db3ede32d169ea271da7a97dc4fc602a65d44759e6babff0c70164f722c916c56a560cdce0fc22c966df51c2b22810bf095ca6e8e20fcd043cfe4111c3123686dbaeb630a7306a32bb237975bc0bfc973d821fd191686a50c10f29e4bb02f6acc0d1b0361beac24724e3361f476139c05a8859d695ba242efb993ede216871679bd44cfd703f5b0fe1fe0e1da6bb159b107e68c36d257dc2f7e7fe6e5544e7364bd3298fb01cb016eb9dcb82e4e1749c0bce0203be7a4509996f51c137a301cc2890c689e52046483413366788585bd4e80fdc1e451d529cf6ffaf4b20e531feb894bc5153f13a0b909d95aa149d3e5b9726307abc631b2fd3c542e89760b09777c4304816fda9fcba501a99def94bbfcd2f17869f6735f2a188477d4543cde582f36832f6468277843f56ecb265ddfa9979e716dca1a4974292c8ed0acf71211027c34589875ac227979e76b80b7567c88c81b0538b246dfa2eb5cc7d780aa55634dfdb212c2870efec504199d46fd566c3881887ec01bfc180831918e8fbbd00f2c7695e810dc32f2b1db46f8a6d5117461ec2a1e9386e6046b2cc2d3a988279b3444316a0d561582309cb0b5596e69814b1c4ad5f1d7b2ae8f6c65bb092dff0a1f480c4ec266c87326e50567c116cab44a9e3f1c3fc934222df8e10cc3e52e19772d3d9ff18513086db3ee49bbba6bd5cc01164c2d07ee91101d8d611d7ffa8bb3fadf9675953143127bda477d2e4ac3fde92c8b232fc77d457ed0ddf4496acaca5ca6e825227c9e18714dde6d5de40da5ed8d16066fba17a522c3e4cddb25e5002bc37e91d7221811b727381180fdec061f67377cd785bf75a49700e62b6678f1557f92496f08aec1bd11730e08aad041cd757756f496381c0b4fceaecdf0b6fe63d8f8bb8935a8ac86e82f7feed88d71ebd6013ba34090c6148cecb193417003cd07de1b84dbabd33e5f95568f0394cb2623e74744b7ed63befb5fd7550bb09f49827119928117d1c877912ebc04f90c0fe48fe5e67568a96455d4b301a8b87023b14ab681150bb6d94415a5b58847f912a87a10d05dcf42ffb5a4612651b50dfa881ca3d583f8c7014fc4bb4e265c18f602e691d01a3d824a1d882995daa32b52bf288416199eb36e447ea8cf1a8a6ea47454bcf0e8ebb53c3952ebddf1d11af42aa8abb4e0de45ce52d7bd79f9a3490661289abb69943c3098478564bb25bd7bba459f0edc0f704cf980d0d67456c391ebc1f3db4da540cb8bd6abe48e3a8e7d66663ca525c33acad09b6125eb55e78db515fdd36397792fe8f1520472c80513656a276f5122f2468535a0c00d39527981643281e4ad9fc649a6183c0ab69a8e5e976f3354dfc390587c36502fd72386b48c79d02120de69df2d1de294d421c67bb500bd588fc82b23a0e8923bab5b7216974045a450675ce9ab029fd3ca93cae6e59257cfbb1408b5105ab43ca772b3fb715e9a0b3b6bd887e4df391e2161d2eca470fb89637d0446ddfa8e477839a9605ad8d3ab6500be81dfe491b720289688011dc9b047f54a01115433acaea18dc0e3165b4c9eaaeb485702d79817215a8fd3079527819e8f8f3101ea996409e26fba70d87304024d698a20c129920351160355fb244266da46bf8f32a3889d33ed8f8e88ba3467ba27ae7129edf6b659a2c7a8d7d191ae564cf0c4f1012215aa9bc06f1b7a498a999d5cd85ad0586a4de20214fa3517826ecef0e23810b6d4d93a887d30fbb9402f6d120112e89fcaf05a4a233171ae30b42086de134d38a5522f8265c883904bbe7a3c38cc67cbfed88e8c07b6ed4d714a28fcdf3ef5249a4b1ce40fc4d05e8f04ce18106ad4b3aebd255c9ba1918aa5a6471bfb3dbeaa12110d29472a3a9880c3f7a433692ad7d93babf67c604d5a073d4907c85140a7058399d2393553d389b478198a70771d6dd220b7ecfb6d0f7cfcc9cf8d2b3f3e4453d064634c38dd2bd04c2fccc998c378e0b6fc067463d03d1980bb50e3b0e91ee9f7f7d632c027d2bc9505a5e134f02c86a523e82cdead2de2f400e38eb27e0c4346bf6e61ac1b47277a7543302b6974a640edb7668e09335263b626eae3838e6b7cfcf93c0b1bb93934731826f591c9da3cd66f3e12107601e9f84e1421ca6bbf1789a6bc5126544ff5111a19f0b671795b83012550df7a6e81e8cf0211a51790f2cadc0af8f6e17030cc413a2dfc88f4115b01513cfea5890992605e0b559bbfa01d3a00d72ec07bb2b6d7cd13993187081c002891ef086307f102e8001e812d84381bf8483cfdc0c31c11ba2a7b80494deea08081e5c73962ba3e6d2552eddddc230b65fea57789252fb03c8ebc4ef4f554b0fb1371f835b36268c18aa5eaf6325f7cb995bc40db67dad16d9217e8665ec1b154494ea0cfe27486311b58514ad6987696ccd4add07490c1047bfaa824c32ccb8f92246783c1ef82db1955685b6b91b1f431b19d84343d3b3f04406eb7687c3b5237f0851ea73d5ae1b23a34998484cb90958be7758b8cf820e354b28b2fd31f580501a9e56b909371f902aa3ece5bab348dd4b8d5db7126b80478c33b6e357281530508128c42c737c1744ab7b565834c252aefd58a7021e1131710e609408fd68805335541b7e62970e2bcbc1366c3f7cc843ad6b911d3003e3bec9b59cd7256cad1e6d9c4f6cbb976dd5823eaf4761d3ab40c1611f732392a60618e8929f040b3cec13ad2ca5d1f7f49c164c8c182d25728ebcebbda42bf368c82a2b5677054b7fff7abca1d5f474364bf223d29b846eba729db18b211a5e9abe12be0edb35bfb4c50d9e1b0b41a0ba9b1304b661f98e21c02ca5f617ccccd4ff089aea70f80e5adfa9e4267d0f55129cbf98ec9a36ede54a6a7cfb02690e6e7721d6535e6438ad300a3453419f34ca11bab4330d2cb1b5523c109c2ac7fb4cd701321a972d6d16e15a377ef2de2fa3506bdad1aa4e788c41a370e2631df91349b56685b1c00fb43e2f77a66871fe1260785acd394d5523e2101163b49d95ad546a7fde5ecad364448d323995c6d2f8d50381638426587fb675e4a5034181b143f98ac4ce81be6880b60417085d90981f0d336f26aedf8df4c76297803dbfd605aa825fe0e193b3d208ac05e92b9ec890c45216531445579e07db2d5b085b71cdba1f8835eb8e31990c5c2759fb04583c736d1e8fdff28fa2ae43bb486f96cebe5266db8269e95b68ed4d35564fa4dfc29521b1cd1f4803a13550aaee7f36652eb5169d2400cd23bc1bc577c275065aa0e1492302c4d677707b50c6cf977a992eab4e7d190c1e9b087fcebbf87f7bc0b225e20c5b54fb41bb6971a4a21bd6b80f756a9ffe0404be35422a70659956b48d10c2ddd2c9148845af7f7488d03300aadc4e5841c06698c7e35469b4862bebde8b7c6bc71d7e8cdfa4d32635e88f1e799dc820a033941e2fd3fc6138dbb217f57a023bfe328ff3469b8ad648e832d59199d3120e1da4b23e36c2685e16cb073e6dcc77e5088f3173ff790471f7da000fd8659f57e8112664df5ad1df1ff1c0480647313b889cc08929f76043ef97831574f5c46aa98861fb6bc24918ae4bc341d74ca66b63858a383992a9434a4ad48e53c8b1f8d4a67f78c5989c23105cd2636538128086d5b00b7bd8675c99812f7f899ff9128e36f76d7f29fb85f52e0b9e407d1ced0421c3593b2400361e61ffb8a80a53e4fb85a293eb911612c8b9e44a356eee9910c915c716544f2d41d9e97980cb52eca94a9ff0068797889cc89bd4d5a91b03293789697a0a4667324ef4c081cafe1ea8557189c799d538e0c0a93fc69f117d76d5dfa18f9906a0cea0a9f1bd35a5ae95801dd95f8abdec913132156f4e842d315f45aa23d4b636f558ab594ff43a8d38c7594174ba74ca8e4a1644b5ea9e687f2ce78ffb85539216d53b36e788126cf4fc74af42fc5aef6a9a33e47ac12d5a494f8b1d0b92a11ada6bfe2ec5c9c0eacb09b517ca46533f7902bc139c8b843ca485429f084348885ca486cf0b9db968f223cad6cdd6b3698cf3ede3c72bec068d9990771a28c936e9365cf788e0d6e2d629d469f257895aa9f23576e58643ce6f97179084cf44205e916221489cf57944f99e63500ea72c8e53f03177ad775583e862803e0701b62a5c56acb2ae34d28e947166be7233f450b5bc555b5867f594c8052db6e94d8d46c2da3c1bf7da6c9080830fa5d2cc6bd652dad7881183db4a76922243f90c13f3beb28e10ea7e9d5806c937113fe5d18fa9258f45c1a12a1a7bfb1109a3b0938a7f38fdd91388295b71408229b4725e07dec481dfc2c7d9aafcb7efb98a353d0e5bdf2cd8a53256efbe682492cdf92721858ebf42adfcc17617241db700793a4c783b70655e68d33b9b7a89f17823cfa30f03b2c48baa93fee2994a3ee85d098b20a35319a5d215ea7ecdb7408fbbedf0c37a0ed227a9181bb8b3cf78db355e988831d084ef7eecd9d0e6afb2935b20e42d1f5218f0e9a7ef76ebcad48ec09ad30bc9cae7034a15f59e78d8ca5c88f211c77edb39c6e9d6deb66dd164317a7c39fa76eea44c333cc91455c8fae3ddf83a0c5dacf30b14ba5150213655347deb05c290681d7a18efc9399ea47ed7506e52e6bbce3bdbc94a110e40091c51aa641598eb2a4c6eaeae9597d08860ed754adca74077ba0fb80170e6e07068aee1607b294a86178faa91ad32e3e1d7c7f97f36c8f7ef7dc0c1a31935cbbf0f518f05b5a8070cea244c64ed71803b3af4e30842191d3d66c74be4cf6af66565cb2a6946b23f82b2ada7b0a46bbb75f9fb294ace030cdc80a1865eab26650b101fddaa944802c75560b40d7d06377205a45098f34098fd4cc177106c29fa68ccbb4d9c65b258d4b02d37a5161aaaf3fed3b02ec3fd34edf59df480c5ad54690d0b85c61add9734f57a5bc02ce2888d333cc7cfc1b3cb180d9f31d295af135f4a22dfa826b8c03c541c9a541da7a7272404a06ba257cb425161a9cf10ac7ab887d070cc8177ab796552a9cd115ae4dfad52491189f5cfad25afd02e9045e68924d0c6919c7298f02131d54e6a1e747f4c77d1904f72d27e1e4c217275aa3a210542c918cac7663cd33a971cadb0ce13a943f47b8019a4081a9f70e6599eb3942b6abdf57feab84bf75782c22de1581969c42329b476dbcbc05fe95ea44ea15a9adf15d9baa2d1a82f9845c26b58f6402d4041f3c90d39ee8a8d7cde1a3ea38eab5907ab1542e8c20fd55540c15e00546244f58b14afcd995a225716154709da95db5060e8f344c4dcd4ea9e78bd271490d917dbeee9d52cc7cd48bd74a68e6ab6b83547d9e898ea1c0ea61b5882b491ca60495ffc5765a0fe0c16d296b3949383637e020b43f881ddab980f5daf346f59cc88508ed4c4d22c9f6b8537d91641ddbe36dccd7843022fc37b4a234f8be5f7b2da84e21424d40b91a815a429a538442402dbeffa5964323b7bb4debb3fcb528136a0c27dfa039e0d020e079bad1184e53f8e9092897b302e19469f87431bf775f8b0470b9ef55deb81b764cbada25dc0c51b0c78366fad9e0b72fb3f0186bbf12771b755c24c06d914d3b51f63b10643dc7390ec88a157fae7c101e434a58e1c78dee454e59b49d6c85bd667adaaeaa9d9960567803ffc8af515c36995bdb6f4d9ef9404212df076d67f939d0e7045ecfdcf953e02aa82b909d1a3789145ab96a68e12194c651073a191d981b55b106bac3294076221b780c197d03c1c71ae1cb92f4aa4a27127d4a7332f76516c403069ed0a8e91c202cea7728b39c5d7918f9606fc401fb8be7c6bcb8977273ea288ffc8a560d874f4c782a199da01a8debba4fdd2b7638b7cd2ef0f0d8bcccfeeafb8f9d42abeac75557cf21c7ca8b9267b296a00615aefd87592ec465154c3ee04cf649bb33582f3484670daeb2282f1c5064fcdfa89a7641cfce127bfeca48211200fbea2ce05fb762da48efe24e48f89789f328cbef3765f0c2bb9c67d7a48785f1d98cdbdfa94ce8229f2c8ae7fa24fb8c508cdbc167df2df618cf279fa3e883a8684f2f404e16131909bf1bc831568c22a965a320d637640d24d98cecbb4ed9b1d0931e8260220ecaee98c82b9bfc0b9c2f1b28e1d9ef8959787b10dbf4dbd640888a0708d854544afd7dbdafe328bddde23878c64dffb1c876765b45919c204e19c8b5bec3d87aa40a43ff2c1928b183655e2ecb4877feba0252ac3ef2b68a4f20a159303e27baf291d6d78e8750c004ba6fb95bdcb9e416455ae07424a377995488a7ac4054ef007e5b8288e726ede4189c643c6e4a19696fe4210212d742106cca9c3387d312869c2bf3bb2671be4a7ece8a61e14cbdad0d271b86cda649025b143aecaa0a0d5720104b884cf6efe5fa988a783a8b4d17025ec124a2877ddc6dfcfe0c9831b396aa9e77c1623f9958c11ec6b33db46e8f8825a60d839bc27ded4afa114073fc62833cf6a00501785017315b7bfbf47202754150f1ab4275783ec129d9430d45e6882d1e1d5e10e49bc0248208ccef36a6de5ec201fba78f3704c990f378ca03ef9159d444c872bac51681f955c9a45471c70c48388d2f1e8e6f2125a8c21e91e6b4382fabadbfb7fac89d1a3cb15450d4708bcd3f55795d52243ea37c0df189c3e12ca371aa430e3ec865d3c3c0b810ff331aa1d2ae555bb57d462c4c55d6abd6e3021420919673d03150ebe7ece55b97cf8eea1364c7c7e10e2f5014bf5fddf420cdceb77c1acf843e11d275368ac9101efbb2ae1f4097186f5b433b0872d3b1441dc8e29b538c461f32df766f4052afa47efd22c846e99e12a6365bc9371832eb5962128de997e9b822fe89180ade23c7ffa5847fdcd2f7d4449dd7dce7a4d79f7f7e1099f274de86186c47d4219d5fb7ca3dbfc784b36830e805843f61035ca0f86d7cc6d8ab214f239469c75654f93a5f912417f9a770dfdc8943da33c86278b20e52a2072ec4e4fb2e568ce2d86bc4c095bfa7a974b85bd2288437bc05d6e20a430b57f55af644737d33669adf8b6c3b075feb412dd7a30074b6ff6e9485f833bdfa4de3b6137e9cea1dcc6d1b3e40b53fd399fd4848e0aab34f442f2a117dd391409aad8d89aae2e4f3abbaa7c003ea3d2a9347c38386d32402f08bf92518910d92c179f9f92376f3ae60eb54e3930c9cd423c2c510d0de1da187df2b29ec6b998185dcc9aa88c6e95ef35741020b505a616e5c166003cd7017c2c4921389530f2eced242f9cabc1efc2394292ddef93fe106dee087af538c779bc209722027adad0dc6f66a0239df26ec3fbd56101844333af6919fde9710e7f83d50291768ff0b9949744f49c54d5ca92c82128eea0a618986da47015b0cd5a425c23909863ec9829336ef44e0941d918d1319c48fe6ebb5ee8f1370337485a6e8a6e4ed499a263223686cc0d9406d99d0ac5e46490a8dd2da1799ad32774d1b1a6f5bedbf1210d424b260fe8215116e25e364ad8079be564d14638a512a586f5eb91b61225b791051993a30081a30d014ba9d024a7a0aecb7b6cca4c10b026539c8d0c7960515dec52fd5d3c3ba9a0f8184141bd51fce13de2c85e945ad0df71ad49079f6708fc13c9c4116f98846f9289d8707e227455c7084c502f834c5050c0ffd704b366d409468bf2ee9f4818a25ffb5a6400aad4e96da016cd199a2efb145e1878f9aed01e53f79131c912d3a1a9bd81270c6b70acca62007c822c2d93373fbcdf4cf92cd7fc08f1c317e1d3ecf811410a2223e731af1a173121f0296f810dfa63d367f885630dd61521ee7154a907903cb329899980e924ca1284b0cd5ec1148c9d82c097c0be6cb5a621b19a294b88bfebef424a5400599b05c498e11ec40ed20a66055bf08c223ac1287f5a15cca138a37f62451d1444c40708040097620335057f62414c5090205da0e9e070aefa9e78b1f302aaeca279b7fad49472a93af251990333d58a6c1f071310e61837f0b75d438d2a77c1ee5ab6c217e50ef2fb8846a148dda441e1cde3d54faefb436585d2eb4585804b83a42f5830d78236f35ad3b493565f203dd2f977b228c26f3f1302d8769346181b31fc8898961d481fee259cbdc4148315319d383329934a64e579f5e12b8e50e95da333fe89cb12f48d08d558c78068dbc2762379539131e03488e1c8926ca4e86ac9948847584de883f84b2226ed2722925e71ea39867d16fcc5c7e6fd0da34ae9e496d146d20cb8fbca2e4fa5d69649aec827931cb281678f132d338ac0e1cc400f1bfea636066551a6ba334c9205f8acfd10f60a0e90298197d9adc8c8ecfb0d9bb4357fe529dd7b70572bf2dcd35c9487c18e38f426765775c71b59b85737d04c5993dbc763955f27013154483a5128aceb882b749f9e58d5f35203607fdd19aa0f616c0a6fea88c2731881ccbacdf976d862d26c69b132f24ffb5a2817a946f6a319e4c4b5f21418e255b55a38c6263dbb33b14431532ef3542f028c52ce039cad31e6e7e3a8f02b0b6ac1e098cbb01ce5765d45ce7a3ad9a8bd68e50eb8e4aa3b2e0f6add65e0dbbb74f4d25605bc358f807a5bf3a16dbd69d2b770764a013c88141f088ae3be9fb6f542c078fca6d17e44d0f084241f0ba9315fce847fd313d3a9bb1b1ff00c31683866a17893b423af691f5d9c2d7b6894e33c3ca372d18cfbdbf66ae3f68fed900cc5115248c827fd5a4bcf16edb95236a9b66659f6b9f989d148d584a6a45c85d5cd4cafc55c69da9349d83ea6111a33b1f0017277c0a7fad79dd112ba065225b1d128e60fcf78588e604f072af1b046fa184dd994874d3ce96a00dc4d03ea95411d2b8a6d12ac60be2988527ac10351165678e0fd644c25014ef43a4d2ef5cb5813006e92081b85c7aef0a824cd652907ca6b6575c4380409bb61cd363e86523405c354e114313685897e38063ab30d0d0d1ede82af028b718adc5ac08b948c787308052a9b21a77ed6bbb8694dfe2c42208ecc285751bfa643870ba4dd5a6e1a58ad516848d685d841d892484826a5e54d4515f70b539fe00e63bf9ac05dac05d8e10b3dcb29244c1be4a88d526c3b50496fad3ae7c29f85e64c19bc4426b63dbe37445e33c3cd404290b3b449cd51ee2313479a5d5a17700f44084278a8324b8b08e96a3124a42a820fc8afc06a2fb08f9d6003cb8cbe709b0408c81dd3fdb502d3aeb8245d46ace98eefa89e784053a505edae3ccc7607947bbb43523ce0156d1e30ed4dec329e8d8fb9d66ed77d15e8ae3a0906b60894d9d8d6bd8051c7fe838cd81c286f614eb191d5bde825d8428a6a5d929d6083170a86e56cc9d52aec7ea3e85ee504b2cabaad56fbbb4d686810f210efb646c0ad35a535cd6843f3c53a9644d6c8a3c8fa19e1c25d9d805393a7c34d4ec5592918bffc4cec332735dff9e92c7b329e7a4148eaf0768b86fe8731b159e370787790c8b6820f906450459ae58413b7263c6824b9325ad7b29564ce72c2a034341cfde284c44c987ef680827f95c46a6f1e1e4a4a8fec02c40ae81a032986051a411c8331c44d29d8f20e77ab0de5d2f6f244ff5b624f2568f01455f0c9120a53a699335951892a9c7e4a578be54c2c109f3218dcee37250ab55bbaf9932e2a1fceca2dcb2e48142cf65fe01ce281e2ae43b72da33d46edee8d903a78049fbf21a4f20808986e2ed83684e2063cf0838fa18a446ce93e118e4d818662a2db4e14a8eb071567ae607d2e3106932a4e2de96fe5e6af6088cf9b575d881eaf4b8c420419aeccf2ce3da7b0851427ad58cee20d0c89c271c309b72609d0f348d87ed494541bfea3d5313548525f3e322c796bf5765edd0a24e0711f74fb4e17c7b3a56d63162d5f34889086ba8e4d906c7a2b7a9b0fee6fb8bc4ea1c0217e4ece5fa15edb7e2ef4cd21316ed38cf1eaf67d47577b6dccf9d07a9e6b89522704da0f46c335ac17fc0ed2db35b5aa2069449323b194888d9c3b76dbaadc7440db31a3a5ee1fa6f1e329d2b8dfa6788503d1cc6111a0b94e47dc2df48ecb69fea62f19880f79b8b720d7152ca329cbc420321076977dc9c6573c2b0f977c6fad268702075be1b81fce4dadf5d0c9144cb4211a5429c5b81ea9a676a6c84a7d80d4b07e501b93848d61f7b61a591a86ed71cb9690c9b8045485da2a45e8e009d43155257083237bc9153a390809664cb9a37d7f24b410528e0a4c942149323f621060cef00fa36ed9170191236400cc03d4c598e52e1b0dce250c63d28af8c948555b678aad551ea320ad938318825787feaa542022892da5f867b58d7c5107f2f8567c3441435dde57ea73b67345c06b68b57d1f8d18dbf66130961101ed85f64948d2dac3459ff92c8378136d4943400d7a933f6985065dc0165eb643bd8e94aee6d43c46a9cac8909709fad89887f68496742e1ec97d166102849d8a04d749722103ad1e831f09f4332ed04a01da6ee6703402c81890842c74a842abfff615d5bfce003cca0f6091c4cb27deb7347aceb6ba5f3ccffba680565b1623b1eddb72db2ff2ae0a2a29cd7cab4f5580374d0a8d6b39c12a4f1c61fdb48936a05422a8b65eb4f03cad8f4340d13c98a0d9e86234513b4352abf167e270214c127717753e6f073b9e69bf8b2fd4e05b83d4e1000b839282c9db91266f2fd5c9a314e7fd4346d70569600070732522c58ee074c3a46eb66e032b2482ceb8906c7d45fec95b7a29f7816897d13fdd21be52227df222db0824c5b242e0fb47925c4edf86f3b7ebbea21e948d7a3bab696f698c4b90ffb8bcaa5ca6acafe1799f1e86a5a3d584268db7cfdbc9692d8a8d512643fc24dea5e2ff77405c98b91c6f5543517c3f4de47632e7bcc6e2ae4e36e66939e67d08039f77ae68d1ba7c3620e3680e97421ec0f95524b3d2b2556b2ee966778bcd3a5421208343d97fe38f7c954832a298ab623af884e05960724d192a862ddf0f851b0975fe117111c77328bf93962c9d2af05929fb8950b28ed22679796940c9220125ede1d846563e28e4b7e01d960d10583dcbb4ae6c4dc5af1b5f5d45edbca2efe38aa96df4aa164c6c70434e9e33d0c4a0e64bb16cf2bd7ebd0dd73ed6289a420f9e46b5145a9f63e8dffb9af89f862fff25f0f327c531f3513d9ca424a8690c411cde461e78b164680691bbafc4151324571ec7cf0e659547674162ed44921a56891a4629539517010fe2f1decaea9474b2706f856899afec3736655d77086b47b021d14c1675e0f370d44e2e638271346ffe0f251953d16dd1cd3c92480c1f62574782bdf3b19a7c13de8b38a800f6df44388983be32d6655bd6f08ebbe670b69a77b329ec0a249160a49b65522692199f07b4a50deaf34b747bacfdc7f45b15723cb7389c09dc442389730ef3b242cc7c795196ff50862561be4a5e42f3911b793fa49297edd11cc668eaf5d7cd2e3d8794544c883ab04c116e824b4ebae6c8e1e07021b98590cd1437f8b52912cddfd60ad7192e5bfcf4593166e71b93b3fab53dfcf028b3f8cd42c9daaf8114eb3a8e582e6c8d57cbc7eab1fd553129d2311dc83cf247e44a3ca5df62db4f25c6c497fa193b7355a4caf53308115f6a7f686b980ef60f79368570ae577d7a017d8d15ed005d95d9821d4409e45956c933a32f0254ab18d192bdd45bb68afa239590e0804ea30b3298b89c4a7d7dbea11bb83aa827589d0ab1303f210ed2cf876995968500a45fb34d86c8bd4230cadd345b88e5a171a0637a9058530fbb69b8e55ecbdaa2c15cdd380444005e7e633582847f94faefa49647114c0972e17f5dd7de7c08f1764e5f75eac3c5a8619e8b5c7dd43b78efd8a087051d3b846e853b266a0ce9dd61467d0c5753d16006c13735f58c0a9878e1a3d60be0a8154db1610332eb684e4917a40340d35683d0a9cfd37c62bbb1973d11611f2ad304cd5c031503c9d9f5187c0e6a6f3189b3a4cf190a52935cff9aa469001528e2910c10c21feb833335ea61ab5c4b4b1e9d9edd80644662e5d8826ef173a1b17be10f77444e2961b5024f7e0fce9e73a0631578b3c3d0115089d8220c200b147f97b492b2650943037e87afc1fdb51b5d3dd75f9c90a5fc79e6e3099da25d621242ba8f3b73831e84f48d644255d82b7bc58b713aac7f5d44e011bc4b2106792ddee70958697737bf95524c0a0ff407c1e6b0be0e25ce8e67094585a2b08ed35f28cc2ccb80978c8de63e16c50f20d9de140e01f7a070c0de6dab07f00fda3b960c2810dd25117aea9b7cdc0e76f711febe7c2dc52a5c650860caf8d4c4e06c7e950d8af29a6005ddf501e7fc3fd2576f1e1843d31883b67a9e0337d5ed5119fa8ea88127416ecd50da32cdeb9e228cd64f784e5d6505f4fa255b05a65c69b59bf178983905444d2facf856bbfbf7d1f937dcf8fe8f060ad20e042e501f9390c05030d439aa9dae4ace874076f2e9f038c9757a3bea1782834dd6d6c1d3e4ea955867fe802b75b758f3a93f8dc675fd92a63a1cfbf573ed763f9c9eec2ea4a9a624821cf9c7945cf0e465148235709ba03b1b9384ac6b5f7b2084e289477d2b2f22108103b4002a62ae538d4dde78a6e58aad2f04d5aac7269d05f7515dd95c72ab56710839c72473a308ed1fcfb9dcd217e075eb8465649ef74be13dcbbb06be57b4f50f85f3dc8bff37ce9076eb9b53fb12a7d149ded86f5cda69d2de30f90321600626fdd3f248a05c4ac479325824b20309a39a7319a1a8ef6c0060cf3ebabc54a9c6f28d51a890acfb449c383b388c35daa1ba42e3ff9589abaca85d76d105585f4715b3a073b4405a5235103041d2588a4cbdece0f8c243a1f00acce22eaf9f2b22c89ca119f19c96664733510a35981a492f49951236e55f3851a82afe4f07a896a9826b505e0d55c81383e875b5eb2c9b1888a547c79449bc6869538051bb6af12679e3b2a86813f24fb7d15019254962d6556de4b431b064051b355bf7d0bf77e5c28b9ef188ef7fe729a5d86fd040caf43c7909a6bfd5e22231d0dcf78c2eb876fb076dcfd5cca83efccdbd58e46aa014098a5566d54a1948f37e79c4f58f2058a8eb07da2d0b93859a17f2200eb6c41eb0edeeffa14d53868a961678a301634a5691613104fa9644d5b49217ba7b67a0e21ccc37e7b52ff0c6a3300ac508502789793c8fc68d1994f3a738403589ada8f4c738fc1e83380f1ad53852a74c94060982075f4f53a1eed52286170c7a7a000c719456efbe02ab8f3ca3de73665d854298e3d67df5e461ff38c0fd64e016b7f95ce1a5a612ec2f038f9fef91ea3d39311b8a4252e9b1bbd570003d238ac6b5c30bf368234d88fbb415b28a15ad4a3a2a001799b9554988dd81f8557357538e03b5f1654acf5072a9e11cc67846466343e08c70699d5a48569b0097d54d385e96f08f40d10aef800a135c3fe869c20eaf2e26a191f30d4a93529b324358ae2f7bca1bfa3938453f9558228e3ed8404bd4e2840a76bd70252b78c4006057a8e803d1f36c6602964584fe12f0df32be838e2929653ebfe06771351716243d6c673e911205ec3963d3604aa9e470ff36e0022abb987c63daca10d74275382b177f5b37df847ec7ff00bd314ba045f271a0d66dd6109ace768cc82dc74e51ef7917529cebf283f4f2268c5e827eba2f2462e0915bd168ea2b83049ede1ec16a01d2455d35f3841c952146e93864fdac4e13bd59d1fcb0a89f2dce414ce5fcd51797f93f0c4ef377e4fbbf7026053244fe6a4166c811c39a1abf7e83ca528d82e7786ff00b06ce7307c342fbb07259edf39ce2ddee03259e8edae98b2b51e6dff1f5eb5c4a6b1d37b940d1b9342c2f8e7a426661ae82949055b90a417914eeb95d8a2161c1f9b672b7b2bba7a0e8c4b20f270eed8a1bb056311c541857b70d0dc1d0c9aaeff785e939ec306a95ffbca6a066d70ff888585d7ad1236fc3973909c286106938f3dce9aeadc8b13dcafbbe48685c09424ef352db483e233fc391ad00f5ec820e4d9e0d1674551aafd6bdee59d25f7b9d393863b0f612aafab979754d9aabb5d1b009cdbfa6f8e7fe984e8e1fc695800d1d105765b253035f93eba6bee8f4f9fcfc6786168e607d6425eb751cde3c635d8c52dbd3a4cd8b9d54328e0d0ec1b309fc5c2b9e05fa6904b4faf9bac72189a7bf3e17a9815d63ce8e1425d70d3ccbea47b7d7961325e536488985d297ae4adf84552468e812b866252d58f455bb2b142a048ae7962cfd8a464742b036bbd040bb9d8b3d6c653d3182cc268d07470989f6d5e36fbf06d13686b83accf3222761959c36b1461564c18ff7859322fec2faf69923feafe973ee3dcca8d797896d1f872e734e9133b003025ca09f77ab16225f7630af111a24af7e20c2862580982b4f2e37a4ce387d71abc3a488e02864b18f047c11a46d8e30ee983323585807cb79795c8c16e6ca7c580fe4eca1ea73b684e4c3e18991d91a59f41073eb2622064344082e102a6de49e1fcb71c7f52961c16ac2f57d02157bc1801bb859c038ab3561992e8936978747c77a8569b1a626fa55ac084db28864881ad4c67b8232285e2368357d055342158ff45840a1cb3705be06fc266652b974ed401237d34883f6aa1f6489f6eae917bf5e22693094b80770aa58a786b2243cfba3ca1cfe20de0d7762338c88d1f2201a9c21b7ef1dcff607292ac9d2702ace966ba9db05da2614531b33a1520e831f00afc957d36b9600b816acb57b73d5f27eaadef3a11f515d89ebc27d6e33a3d744d0b73ea0d21f006e0931df70fec35eb6fa2a95957e27f1faee1f6bb26019a89870da7b52c974b0838817049f77b47d2aa88fdafa65362f74c2ade4cf4f7ac7e85389cb9654810be3d7eeeea765c2fd95ec75d3f0d2c43c93b970225f0fc7dd6fff5976282ffaff7e598f540d3257fde4e1c77288061d3cff68cd86b097913960bbf19943ff77bfeb83f19d0d93cc286b1798bc2703bfad55dd1827f301c7c211d750368f710f326c11fdbd36c413be0247f21715eaf85f0ccd8ab68c85c701229cb02d776ac768f7371aad0b8049b42841d3822add91b98a46673f41f43146fe01f996309871c528da3b3e6fc21b52f7bcd10fca3a26c8ceb917e04a19fbc76431a93ef4f916995f0d70c13af35784078386848aba3dc338c5d8f5dffd66960184687b8d1f995b15c256c88f09c4392181f02e072a10be4f43151d75fcd3318d6dd060583a26a8b2fb50c76708184642add16695894b8d321646c36168ab4965402b73bd794853d6817c76f5a1491b609b8a4f5efb8f75bcb8ea540a4b92aef6061db23f818d1e24bf866eb49eadaaa6dc7b41ea0f6038ace19e6817024d093456dfbb9a4bdb06edf62ebd7ff955a58838e53b7acfa7ba82000f2b2166cea6721a3b3c3d6884de63788712b3b50658acfefca8ebf444557cc15552de8e174693c71828140500987009403165a1cf970e52f7c42b8888506a9d36afb4b815e4a2ef784ccb7553e801bd7fc184102bb7937138ccac9e56baf9200192f72c2cc80bd4da10422de51fd56d4489a1c80dcc2e39c9e3a0acca627064c1638afd6b730ea1020c17a3f3b55e6a48f2c021d59caeb4fddb02cffed3119c8336a409a631bf6531870428ad55f99d131e3b872138c32bf9283516a8e705551526154df6384dd0f18e105be7c379b8a58441e0061513fd794b9bc0304d03d5a923ff7337f716e8aadfdcd3977f44eeb366d49cadbdafa0bd09637290019e0e37d50a021c4075c83f69309f29a9cf579ac555a7ba8c5e99d46715e5f81f7db1ff783cb234b595c22a873c0bb79375f3c1393be090e0ef11ba14d8a09d7f29ff32254e1c15ec77515cd06184f7444c543bc6cdb5b883749bafa2c8ab96e53ad119d41a53238f2025c736029636051f80918dd753508c6a9b18562d1f05352f6252b09ae979b512fa5e7c7ff76f2d468a6d89b973cc192ef6e261ecee8da3423160a341d6ab450940732e51250fd8a86bdf58914a880a59d0b28e0f145b043bc62aa5ee5c05fe8db5af64488ce1b024e110cd88fe820e4b54f9e0490f4a8af7d44d5a763b0ed2bb2d77eff363f786aecf55747590a8e82f8794495503203fa7d68ca90012861677652cb358f4ff6e9eb82afefe598354c8765a9f6eabec6fa9d0cda42258981fb67f20bbf9de5c0c9c7666904d3934f88a5283f0aa8db2e5a9c6df55ff6bfad8ba8017e1c0f4bae59f20156eff9096e9385fcd11a18e5caa1564e0ca7be1e183651cb2ea63567e433f53f0d688d4fa1208a82c6d625ed651bdd39361537ef3fc170634b71cecb657b0193d09bab1370dd53d1a5b32d606e8102f7cfc7347a223040609571fcffcc28243c37aa46ddee11c95137fd21084bddc41077dea0a5d17440a4ffe55912ec57dbf92773d8bd407d903c64c7a263592b70d1e0b5337d304c75f1e3dc98533ef78ba9d18be2a6709df42f9c229d15b57a9d47055995bfd68f7163a4d4562256bdb9947f89623e5f8ab430a502a54b7b0180afde9f11a45c1b143fbef0b178336dd1f16fbc2d53a92a5c4385f39174e6ef021eb866a729f4086f07a4a118f0af584f05474b3c07e3af3c9f6293c4a37657e4785d36d30b2e414defefe6838306b96484998686cb206fc610d7022a90753738b741e58b4775ee5cb62d11d8fa37d0b313e7c3938d757191098d7ff5a914283fef2032f64ef7867a24dd340a4dc1504a59b91ed37a241ca788247c3abb50d082e25c0920d7742dac2ccd51ad59dc5b4006ada0fb1d8cf80b9f4d53884006f828dc413a9316a3f0c56b85e81bee2dcfc4795454cb027dc4f02e652b28332a82dbafcfe3dd06f6bd31fb5094b0eaac602232aa44acfe8f78c74c9a34f1f3bea058bd39424da1529afe48b8a406b9497ffef2352b55cb6fef1cac29abe5aa5d0c2a34424e56ac608cd3d64499021413ea7bead593f1ae6356071fb510a3f36e383018f7255041d8456f941ebab96e6ad8515b15fd31a8863fd066ebaf2deac7a62d404a790c1f3fa552af24884f75912ecf00b83922eef7e9d6bcf6d3640907e2a3f5be42e6885768200e745d484f6380a7eca8004f5f4e1ca5f21d959ad53b7479dcb8b30fe4dc544f2cf679372b6145aa43afc43f745fc1fb51f06f76b6cfe1f387de1dfdba9833fb2fedf615f3f1c81a841b7853cf7c1f4dd8fd76cfbb6db2ab9c98e2f488c775a2e9a2a1f71454ada626af50107a588f9631a0f4b0fb4905b98b311d3c6aa68c96229a1b7d2bf178eaec6747a6474b402c23c4fa1bf6f4369e1a0cb3ddc7bcd359dd8c97858192f0c232c5101e2402284d84c9fb43172c00160e45140a5914586112baffd00c6041a0d8c0d965f15e22c2af9288fd3604dd75b31691ecc89af2728ffa758d568b43a34abeeea661971586d58b800daeb64de45c01deca1ad9dccbd80ff5beaccf646b3b287660eca50199ab978447e070f45afe401c091068c0f48cd00372584576ad3c7ac8dca81f84af545ad0e43a3ed8ad8f3a265cdcad06d2a8b41e13bb81d5b97b209f844975933c35d17f28fe78f4f9a57a01697a314bf797f07232fa0a1dd39a93ea3f37e8980d5415785c41dfaf525f066f9547e22a2ef77d82145d1d753df0df8c96cc5be124d5a1ceac0b46ccebb96f4586833f6da56cae5b95429e60f58ffb99d807a99baf29f8930de59d8823b0becbd570023c070ca1b87721fd8f0dec9696c610ffc95dfa016bbc8636fb024df06469b1261d4b0d736d59b7fb0261551dd648ea84a83173e531c3c01ce5652cc3cd3a3b5f9359eb5f441ed038edb8cc5da1728db42242a37d9bb3703a472f42c0134d201115376fff801e9eea1f0851ddb8513c04454f781b1b5cb9751ce03c97a7c7ec698788d2d093ee1994763fe5b876ceab8533d71ccf77a5bf6f022803d4e54719555e19e1ac2cd3f074564df363b7a19b99296ad8d68a37ba8709ec59679e516e24361535eb304f42c065f1c684cb6e3d598687532a17f687a8356bc7a935d637a97299c7088e1492f526763a16be3b934648fcd83057263048d734f4e734f8d70d6218a8d17d9c9bfa423303f50db7377d5585b3e4b0c3dca8e289d11167ed15ea6cc5341f498d09e66fae4b5cb9f51fa1064042405ddcae9055dc85761798b1ebd55cfb61602bf5073a58159de59f4bcee5d2d180d5b7d710b52d88938d95bfdcb0ce33d30266e18fb282cadc3ed3806e8560b8cc660d882a52449ec4c1f922b401a02bd2faeda7e435a2cf97d403994acbc945d77789d0fe507d97f5279938112cfca242f371196696119a3efe05c9d1ec473980b931472fc60f440612e2c834130c0109317d995ac5d32426d2028967ed1620b4b5cf72cae86e27e1ccfea8b951ae37c591ec2710fbed68180ee19cb183b8ea2e089c0b641d6eda598431fdb24f34258a78d48075ca32c9d2cc19b5662d73647ca6e8ac4edb20bfb29e1652eb03ca207566d688c36cf608468477a70df1cbd7210eb245d2c9ff2e0b3ee269b7fd91e125bc94e816e7ade02e845987d4b655588d691574d111ccae888f8c173eed6a9fe1961ec7a9917dc9378f93be2f28f5567f023e4c92f23a09b6872a0162c2de579a6f37272b72fcc6104ea62aa3d3b303b9e0418e0330cd3131a6d5fe51d45bd8b68fc6f4f9ca2c878798fb8be51ecf19929bb88a3b53e41ce3d8736450f9e9fe33e7a00024fe489408547500d7eabb6111c4f25cd37392de8a7b28607ea8997bcb9088fce3b9274de2e24c558abad82ddaaad6d5168c9b568ef16cf3931a55f8e8c13f50dcc505d6257e89f980e3d12b2b3ddc765a284bc5ba4993eb247e18c43bc8e3c6bc9258302b701bbbde3c70eaa2298cc4d4909626b24f847d393c843fbd435e52b1bdfd3e2a1a8bcbb4c8e097803d06644e5841464a88116fda5a345450dd67b295714df5a4ae0b74fe81374008098a4b8da50cc0a55b4bb6101f91e50ef2877598de71d38888f03699db410d26de4ce8ad481dc480ca5e36c3175e89386e9818ab5299a7c93d7c91360b03e21af938b031de8243e74484ab108bbadb132cc0cd4800dc8b6b3a169c9d14166ea2a6ca512436f27a0f4f3893e9ec24819c2058e7a8651b98f6c0800a0942fa08d8748446b4cd6956cd25100c1bbf89d89bedc66ae24591c6eec784257a20a92d22ede8a4c0f0cba6dd160b7471a7982c9631a2c64aa30c4c0b0b31fdfb3005c490d2a58752ce41aa119d8e1dac2027470f484b1ad9ed4b1406fa8180840e394267f4aa14c5eec152666b621c47fa2ab6f45fb527f7a654fd97a005a5c2e49f4aa22737c659dd2cda5aed7232f5b95f376b9d43d4404d274d4dc3dc2c221bc95c63498057c21cb9d9bfcccb3868d2fdb4bbfc7f764a2a747c6f599deab90e53acd82cd9eb7b3939cad2fac87969c5169b6d5d28531a00e8ef1d490e14b1b30bd0578243068a6b8875cffaf209f4b5f8e1c0fe507c802b4a322e24d47af489995993a0a5177bf41b84cf1babd516b749dba3d71a08e8984b8c25e1d06aa000d3b045e918f90c232a2b7752ec9c4c6f1bd76ba55f2f8df3c46e7d4a87d3c6d5ecf4c1998cdf51a8860068a2076a689d2828aadb4fc896d38f235812a4374cb2b60ddd10a0e1d3fc597747349923c305d006da300f2ed1c8bb5d18d9382768ece3de1a26cf1f261b89f605d9e04e61bcf44dc7c43165497c866d2d19b9d00d1a44ebea7322aaae6959ca8921e767d3bfc1b692ca5dfdcedd6de2ae4eab1ed75918c08ef84d6c45d6f850b5f48c65f1486b0391874c220175311130e7a41824bc7880318957969554e3ce14a39b0d65564430ac12027c1ccb96f22e705c6a588e32a43115ed02af079514aad8342f77b600a0c5b5d3b98ece0e677046d02529078d9e37e51a291174a4e86d2fb8f8f6da6b820aeffe3ec6879652d5b955f54ee5cbe284df84ff534a4f2d5cc10e679915d15a7ed8431339e10bfdd38349e90b0182184f0c89053dd57bce63ede097c0525f15a53a11b5c63f00df1c7226553bfdbb5c36d7f68f7c41b623558aa9aa91f6930feda8a0005198cf888a2b31be77f52004800177e0a3c30dbe8d29282e3768b8908a52979d0bcf4c51ebfa4de342f0d8e678f1ab20f3df585b897a9dba7385207e01ad5c2423de4bbccc796a9db719e87092f2cb2c18d4de456a0fbc6c3fce32961a8e7f217bcd6e9887e876d80cba1dfba923984a615d38095238ce1f384bd2ca10c6f34ad5a9b69df25cb89a63193be925027dd2775e6403178f5f152dae8e8fcb587e800f1611d9d1fbef67ef7c8709e119c1fbe2517a5afd2bb2a836036f3d81ef5970f6df62436c1e2fd4157b56166f3a4d0acc4e738467ec56afaf9b5b29aa151e5b7021d7460e86c700d0d248e76d0ef69f35e12e6e6e55338a4bd6b0290bb211712a7b1c1e74f7962fbbeddec2d6cc92cfb1f7f04616543d8f527016cb073fa717e732c0710d4547959e091e8c658a9f2c8aa48ed9c89c986874bfa0fc3ef87a3deebf669bc2f644b341e925b4f72d8d83817584fc7c736de12a68dd25a2261f179b0039bebf3b5c061d973b327f72531fd6e005d88d6c1e78a3a949918702efdea8fe0d459c94f73e758dd333593454ceeb980e754c23389b5e4e60bece41713af37f7f4044e07c7903a248f8b1d8cfb7066a474ddc52e074b1be9d46e1f569e4bdf9296039343142bed2cf3f4fec7bd6f59d6526b16504fed65b30f6431ed16e624d880de8d951f904021ba4891514463fdc557369e3bd00c67e2fc0ab7ce0569dce84e5a41e148963b925541d6964ff8954497997d28701e6260bd4dd99e10cce432b31ea34db9420f0713ddd7babc91b3a2c5614a0519da2270739fbf955724633d038d0b9b452c9387feecd72c4323f2ce16394df91e0d466874e261b928b64e3cf22959cdef7ac6c67e3634cc8f2944fba34c47db84d7dc2bd7648e80fda5d2f9e7f18d9212f5a528c8654295b2ae74edbf457d6942beec5e2049c30b65be1c470da965f9b326d1c6facbe59dcba2012310be5ad562c56834882f3b20dff8fd730166ba462d1d38705659624408bf24948d8e5c565e0c1037a92ed672b49084f4ff26cc4c40d1ec67181aa2785a6005afb3e2802fbe27277117968529fe31650c4228de1b1cf361d5d5d19eaa1a9fd9c27e142153458a575388e2c5970c2435c7b39019c0cf2dabf91aca5eea146eb69fb99adc144240ad1f4c299a4979170ad9f399e1d814fcf27dd1ee23a9484834227419640ee438e4eff9fa74a5bc14180a9c3ff17ae43e5b54f922e96f29ed4683b5edd7918701c4753b1eb5d59ccaf6009546d131da84099d6b1a80ebfa0a213c1524d5cb2fc8f90c96fb6a03c7293d5cfb6fdadf60c819c379fc23de0b1e2c79ed40c916ff5e5a1418562da68bb839c9e28372bae4c1cdfc6d4d40025b5d94fabbf12936a31f584253c6f217252e709b18014cda517ed7f3a660895ba53ae4ac50df543122c4bb2bb183f11b9ecc5ff41dd3d92d9845c70cdb8e80704d72be2cd1eb8c940afa537bcaf323b6b5b226379a80bbc1066b9a1532f0b6be26335c203358061598fff38e1f649f4e77aeef87f4911c6d9818f420229da2b06a3fa08f9b95d18062e6faea3edf2641d8d35f473d2873911d030554484889eb81f7c7a20ef3931c5df86f321348ecf296b33ea11a0d9cb84614e340348d2c04d1b16f875c3893326548d37f0bceba34c73ca9c94882574f82ff807532b5fdfb2dd31c97a0f0c8fe314b4453e1e4e773cf4439735072e037082b4bba80f4b26d1b70f4b468556bc873087c0bc9fe87ccda14d5191a59e687f100268813c76649b6bb0ad48583d25a88fb539fd8b9bb7848206c7c1a160f388446345d9c32b083192f2efeb37cdbfd5815ae30fafdfc2f60b253422460a907da1d7715f48cbebf8be56b5539e8bf7c2733826f28d8ddaaa72ae30150be1a6debb3b5333d1c291ae6fe135ef674b410240bde6cf54f3075348622e0d4e8059b9ac58238329719ac154fc3b000ced433dc01edc52b60aa467d58bd9b16ece3663c837c2be63389ef02eafa17586a12c74e50f779c6118256b899d1e95e70bfa0798fb11412f5bef40d0ce042e7457545411e5c6826ecce962797cf644c0836cab223528a3505486b349a4bf4aa66af21eb81c1c76561490a99b05ee96112dccda8888e217caf5b715c3f5ecf0910630c49377e8f94e713820d085f283017dbfc981b90ca9d0938cb3afaf07a06824f400b423f4fe4f049d43c3441c8b26e5e233842716450714cb168d0009e5faf015c213cbc61a12a553f1826c107adb56ddc22265407446349e12d2b43cc99b2f06ccb20160bd6506bfb396397d394f4b3a5452e06f21860bae7a31a2e777339997e696e586f12526119a6c654fb59df07d145f5a55186b76473ae92abf178d03733b2d52e2457bb36a071dad4632f413e4b3b4f8293b701b83c198a981846566b2a95c04ad885c80a93dd61c0250c548c2d19fcb094140e9e53b5ff89270d10a7ec9523e9549953fe698040a8f2db0989c8050ef47b2ad4755805ef71ad42eddf40fab733e36c0b8418d69a954d325ba78c4c172d97002a06045a829f8dcb76fc01b8929cb1dedd51d577fa49dfaba1870e52d95ab0ee360d15be370571ddca3891b0c2f2f799a52b0e2a7b78efeb470b013a2bd63e8379d5f902a62b35c1fb526490a1291cecda570a8219fe2c714e7435957d7963e3214a9f36395cf87a5c5d0894237c7a893819318abb43e71f7b3a877f425086e3744f093c3cbfd1016d3d5a462f0f612c851e806781bee0ddeceadd34381be8e7fe950b27a8f4a4f691c466df170a72e2da5518814ad1a42b54960f12c32e4915575639d802efd4c3bbc44135d7f2491e4852cc9266caa4581c520a55ff197cea635a9201554ebaca6ed1689690cc60c869bbd2403985d3b1f95e51f4aa209f7f399d2c8dc32b708bd5f8abe2c460f7f5eea64851ed4da4ca826988c09644f3640d2663dc3aeafb24f35dfaff7f1a4e2a5da347cd50f6d526ff0d717a9974b4cbfbc27528f753e7951a70deccb4ca54d4241b0a0f112288b328fa2da6d14a8bce4b28658638e96febdfa0e1275a31633b3dde218ec0820dc641c30a0221fc362a1f96966eacd8ffbbccaa44e2fdffc568d3c11e4c832dbbdf9860eaa5e781e80898f2520dfe9f870d724d38370272b1f0bf5b82e01980f551d3757a90fcc07472a62c3d913913e468e255a6e0ad3f9ea09440eadbc7507383dfa98caf57892638f50b0086be2c2cce2a38fcdb190a71c300273068296f4dd112bcfe5c121d6ac597e23f765e59855306781d9bec5738883d502059dbc2640efcf53d129596120e084980017c0ce202889909104845ecd645d6022c746889d5da2ac4c615121495b7d226ebbd6681bf9a0849f67548627011a1021eeab423677f0ff43edefedcec75739bb77745019c55d97efbbb7a13687c6dadce037daec19fc309100b18c856d9ebf7dc2830fc5df202f38409c61b6d7c56d538ea8efbe5fa42fec3f96ecc5b43e869da65fe09c1328d045b1ecba5b1d93346190839fbeb81b414ce0227fbdab1710d02b647d5c1c052e4f44ef0d571050c968d30108af3ba8e50c678d3d48cf5c89bc6dfd3577d3bc56267cb811a52e8aac83d57b7e6741cb07a69c4f169c34f06df8724a03d9043ef85f0531879d3fa91fbfd6b6c1341ee1df38063fbac9a88990bda5dc01040ec70da60d34cdd2b24c9472695dc2ab95f6a0a2525abb190c19196658abb46a1b0cd538957c78d267d2ac2657b325902a32942bcb6447e9c864a1ce91eeb687573bf38fb406e61b349756714b42bd2ba3693131d951c84587bf845e50ac73fbf5994851a8306c1fb26ddb3693c9047e9e49eb93ddb66dcbb20c44927d03b76799c8b027404c1f9e00d1e4ec2ccbeabd937dd263ff78222cc7b159a753923b65472873e15033699aa66dda2626c93e395bb7539f98e8ded7b2db3dc99268622786656ce13a544dd3aee338ee1509b76974d26b62177547baaeebba4929ea66d929ac0f6d17725df78eb5f29ab689b5d69ad55a6bad477855c239e79c3da137bf9092279a1e4faf076d08c6ec7e61f6cc204584930d174f01c31d9a55dfd7818766f18f5010862a6176a9d801566224552fe5d6b9a39c64c8e2223c1b3dc8cd5ac167d993cb81cfbc135f9e27ae9c49e7a107c303daece0ec3abbceae53d548efbacf3375e74e3fd27ca46350288e6366247c0d447262f17bf965af128ab555f5a76b07adf68925e7896568124b542796efd1b866814a8c6c1d8869b0071e67a3034bf8bd1196dc0cf284328cf9b523c4d0933b672c89937aed34d8fa2e47465c56df38a6e64f97d24acdd3997cf3504effc4285798c83ce651660e7e8a4c4299c75c4aebb35168fefd64a35c6142f3ef5172fc741d148439c414a511c39fce04c7bfe3f877b233ffaccc71d82354d5c55e2384b375657e464cf5c17f9711532da67288f9e9313ffdf47d3fbd6c57d82e7e38e7e4a6455110499590aaf8324e08c1c7bc0c3ff124c65846a22a3e683b885148af9a3dac6e73cc28a4624ac904eefcbc25235d3ecf9605a2476e4a7e9fffec12aa126fe8711e79b61c6fc9af928bbe5976953dcca33b9f89506ad74ae711526d8388d24a1b88459e925ac24cc4784a121a1184e55c0ae3838e1a841da414c59706f3a4593797ef43b3741885fc1ea6196a64b90c0e607ebe451d9af4c84fe5d02d7e5115f35d00c303c9404a588ab874e9f2ead241445b8c6247af6695cda91d24f0f31a22eaa016e2c1eb1c67fc60465117622c1d21082e984b49b820092da86ce9819176b5d3eba020acd7be9d63310ccfd7f9558eaaf8955fad0e2e666b8248964ce15eb9f36968106adfdee7a57398ed5ccf625d717682304a7d6a09942b4c4cd72ea5a58950a204b125b5c453153f3553535cd2e4dd5b408af160718411366f49add9da44d796d4d2c414103dbaa88a9fd9d96ae1c70527c2ca4434fcf0abe45ba572c8cc41414a4b94952865258696f8cd049818330775cf18d151b34a66e212719798ab5facc44b4cb08264687b48dbb641f1e509364c696ce1b2e58b238660b4a50a9810926a9ed0b9c2999a78c1185014b1a5899a273c7ba7381e0d5d8e0876b919558db2a03b3f6de079dd59ed1d306156b3da4d87e04d9d92863b6bd44718ed69a3519808a34694a42d130c06ab2af078cadc29a66c98539cf6728fe135575ae9a454bcd9b3670c60b7bb6adbd711d18ea86e5c57ca514a2badb423ea0e964d71a29df5f481bbcfddf493041de5a408bd3b635a96b4b85102e6e999a1c8a867a0052923ba01125f0c6909a3886f862f621fcda843137edffd686ebea2a16ddb52b004161d335a40842a8d30c6cc5c2715caab1d9a2297e634df0f683eda535457ab8391c2d32697db03c38a6704729dac4e1cdc5ac56d708ef55d066e77e0bb5b3da0d5ee13d862ed31c8a36fe6cab5f64f385fef8c69a9526b15e39c96155c7ee5686e905bde1411010630a4b8f428308a70520a97052785a52f5e20a1075f2c21c588257290841438f0c10c8ad0c0e04c5b0f0c47d80b23286e87a8d0c78db9333686d28d654e30b7c32f8b2157b10c7b6c9a27d9a5dd2d721d46c81d45811a417f5f28a1488bdbaf218a88fe428adbaf7dda030d8828010fce1003c6829e00193f0002147200840417ad46157561a57e345f4813c40d9e811b3c5da411533b1a1d1af40add73cbecc28516ae0b226e3fec2205b7bb58e37616a1db599070bbbd00baed85106ecfc08adbdb178f9fd082859e5a1ae69dd1222c5bbb1a9d49229ccfc437b5f33728114bf85bfef2390c57c475b2e665aa6597052c214d9a41b41aa32a8d8f10d61825bb059e71cb99544e235cedde96dab6690652bb7e803a0a57d82e2eaeb8335f6c055deef7c945d005637ab6ea0310ae1e9ad555f968beb8e54d98bafc85372c61d2a459d9b57376071d485e6a1514a68f1096b88804788876ed0e9824cdb5b227462cc7d578cbef7ee217851c2f7b8836a291b8dacb5ee26a6f2870bcc5725523f2207e87880a73e010cb20b7e4221ee8d7809275e022fc8439248858b695318aab3d462c0f8a6533715173a90c456ffb364bef0ca2dd003fb03ab9f94d1a765fb759be9e56dfe0b51325c3f11225796895c65903fc0c4d56bd124eac73dce61c372897e3441f7ad478e8f187a8c759ce241327b6ab1379a9de549826e990cbe55aa2a55999aa8965aae65db24596a99a97b5648b30e6386fb9e3064142c8efcb35ab66ae9316da693e959d6fd6a50a286e972a56707b6a32f7bcd6344dd334bed65d05a5699aa669da4c0e5a4124da719c3f7329b57cc269b67ce5be900655dee078d5001077bba594ab81ede260ca41d8a12e5cad9a7b3535a2eb0aa75d137ba0b7e46f40cad5c001304a642a8d01d3e53ecea5cb438f7346641897d9e58e5dc43c50d53cc741e9713ee9713ef43eefab9b58c69c3f588f934a8f5042194e7bd2e36a8cb0d2008408a5c7d9415335cf8573d24c41619402c53a681e218427c8600744e82d6bfc08018b2c6082d03a693acefd661855cd4feee3aac66aed6b9aa6699acc35ad65440cb4e8647b29656887a8699f548788c221c246988c58aeb4932dbbcb9def18f012e871feb31e0f946498e671ac55f34f9ae4d60c1373614bd8466217f53803343fc9b0b2021853999aa644d8aa29a6fa6fd22c6e8a31498ea9c1674cb28b5a353fd7b8f3a3126139f608244cb865faf09df333421c373345383f6f0a756fc28bfad1252c79eefcb67dbe675eee0243b33631a59daf26726c0617b05821c2cc728c8f7a9ca796bbb8a006c7e6fb68be8be6dbe83ad635e342758d169f3fd2b3ca18a008a21d66f6d1843d521afb24fb687aa43deb10680d6284f048f61a687acc326d45ea80f5ccd0378b19b101c3cdb22dcbb8332dc0b819106e769dacbbfb668c8559b94a696f2bb76c2b7723fb7586121733c808a38856f61a28b9c30a159431c50d17175c5ad957d97bb26ff673057953a73cd52ab2185b9a41413488aa681025e98b55f41c17244455942953716982750961495f3410a2435c44837da714e6f2e207062d9a0213d590c0e2d26b302ec26929983e5c1166107afa351aa58684c98b51d26484c915c1644ae221f4b4f48ee00d813245e1d27b311c97a39cc7844b0f0661921e0c3cc2a520132e05a57069cc082e8d3922268932a6894befc12819e3c136b1447d65a28f11a2bf492c7bc07731429ad06968aae8cb18a14b27c81561fa247191d3d01c424f7f2a62fab078c5a5a755c484094b135215979e863a91a3a7a2247a32ba287a1c5b84f39627a48a6442aaf44a979e2231490e33552f2ec26ecc21464c7a82c9ca4e994eb9fc12c72de9ebd22514c10296903fb908dff9378d692a34b89a6530a7989f2f5a6071cb151142700acf8cb0bae083220cef8c699102930bc2993b635ab838248427379c10825e3c20841b0f3c2e687c4284592cfb819149085980616a41165b78485958f1042e3c719ec993c2bb020666a184a98aa12f0b1318d161f1f2a600e3a8789956dc128cd8563d2b9e1e2a8a3a6e35841f8d0bb92fbcc288c3810a3221ba713340a25a11d3569c900ae8aa67c5d333b46586212e59c8ad807a862a8e6a4c063f3f542c71589498004018222e5c8225e9e1c7ed38a209c315793c68e20dcd4af82d41c3126a47e84a1066494b3af098d0441926686206d90e9aa8a2a34108de6946132ed034ae797a60e08b71bb771c3de165d73b81979b3dbbc6725c165336748b4777b669c89e725cef44e47a2799eb75dcb6715a5629a5cd9393d2dc409e3741fa7537f52acf4a659ad01dee80e950e7362dabb4bbbb51b4bb3babddcc62d9e1a976777777777777770e2770d39a691bd781b533795f8cc77da08985a1100469c0b9a8a31924a6fb84389e3442b7ffc51899804cb0cb13068db909283c859ba9aba18c263393cde0a8210e5a2bad343942d47c9b864c40e15773e8084d413a7600551350b3e68e98534c8c09c8046402aa193a25c106e66e54284a697ba935b24628d6eea6b56bad599669611d79d334a4c951ca5b4f8d87086e68074cc8cf6a46bbc70bea1018d4ed06ded4e1a655ab3932ed9e4635dbd7dbbee9996c395feb14b9bfb89627763f42bbe6c01899191cdfb465e699be0a52ca4d540b4a9843394e3232dc56afe940a13a2ef5181e789c75266e337d4c88c4a01bc20e6095261d911ae554dae252f10621ec88c02438b78a26a11d257c6076430d604ceda9b25ac59c808c4f8ca79075fec4439925d70be6830f424a218a9ba2f35c48785367c22e7733ade3b8af366bea342ba3df6ea84106365e42fe669b2c89356bc70dcee465de57571b58651c3f90bef60d2ae6f46d5f8109d33f640ffd8290df554e5f67ea1a3654511c2daa228bce8b212a389230f4041cdd0c1ae672b9506005159e1552a89d17578cc16937e8181643e82eadd4603a4c495d976358b6b84c7f989b43e8019015344c10668b19b4cab9e42596440dc4d8a2854aab64170f31d18c7d5145052ea02fd850a35572121522c8000d33ae60011659a48ce00654a89146d0154b6db4501f3512855d0a84c512aecc651e8248646caa70ddf0271049783ae3f47a3a6141e59eae30e39e1e032239a1bcdc98832092980a7e5e210467c51665c06a67c5cfedce81483a2ec78fab0e5529bbaba140cb16410872b534991c54a185ab754ba5e79470e927154d04260cac6ec7996c776efa6c17b9198451afb14d7aac47bdb3e592cb620fab9e8bba87b24c7aacb1d929e889dc0c8242bdb3618f28d477a0e44dab50af7fc245ba3904f57a1d742e6a8221004a64d2638d6151871e4737423e27e484cf99381b364e85973dac6a142d54299fe36cb9e4762a30efc8614bf1e2388d2d51178788447343fb039f6c49531f63cbefa03dd263fd6761e8b1be866671aff54bb88e4de20c3dd6d79b80d047f78de338eec74b4e8597e1a832ada01a55e025d72496debb528d7aeeacb2bfb8f53f8a1096406e5d5d20f51be7c364eb5d5dd38f1f3f7efc38abf0430553c789a20f3ba94a2713bbc876cf0dbc27dbcc122201a2137b5d993b636680b91ea73ec398644aa45d6e68cc060008672c076c5c4e8895b09c31ee92c392e9c39d521c4c1515db8c4bdf9c9029c22333d4f064bbdd761d9a1eb7772fc32394bc3955599d566d73f6b81a0ae71ddf9dfb669d74e7442038f0ed3e6ff684dcb998efb8b76d2012f0f559b27022f77aeef356a221cea29e084b3a24522ccd0ac0f98df89c73eb48cf4b29d1bc5e152988842996223a63ec15d5da65c68a6a172ef2c42e97debbf1ecedbdd46f0e36b949a56ebc7e52aff7ade63737160a8fa74ca292ec1b3072b94391d2ca79941c317bb7b8c5e351bac5e313cc01e71cf71a911235cb139da46cd89e7d1329961e29518f599ac59408757a8aa5c6f432bc1c6751af34ac7a501fc332bc28eec63b6751a7f4721ed500bf81aa377bcdbd6ebb0d1200e773aa3c9cf3cd80741167e2a13a67116a8587d06f3adbf5380b84a34cadb049646ac5d22e2b4adeb48ae6220de57273fa1a7434c3a3231da7347351b2e364c2234a66465c98191d6546a9531e2f399c97e195295157e699924ca624f3393325191e2187234eaa1233ee37dc2bc7cd7033dccc0c8783c3c1e1e07070c7c1551a9b3e7de9372555ac12e5e6387513696c06e9d223bd10188438e75ed2d801700ee50a7773c3c3e58e73a6a70984b38c2fbedceca594cb65379d7b0dbd26d4b76fe20493d41cc5dd2cec91eb00bdec4d908692cb5e5f72f7668de54c36ecd10b972e5b27f5db0e4ebe84890e3678622965820ad88ef32d7b8cb24191b8ec66962b81b8559c3b6cc95d4edcd17d311a8b2333da6e99b96a1497fe547ee27ba437a826b95602429b97a86ddb72c8c452fb137ab9df0071b76f1bdf520adf8d0c42e8a402f5bfb313024c62e472dbcdcdcdcdcd39b14a08a2a46e4428dc4a69df9e5db3e5137aeb33ae5586774e556633678cd376f44867d64b4a95bff4489bbdecd084bd6419b779453810d2b25ab9ad074ab3ca7934825bce255a6bad272e212b39c1a29776a73d454a0d84a2aa940db54a8a49e724b5e47b951413eff35691f64ba9b3a72a5a35256d4729a447283d6b294dcb3a244a63b1309752971350a09f52500aa8135ea80e4a29a5d73256892aff843e13c1a534b8e547b7dcd3e5cb40564d72113dcf220370c2893964de0138f1c40c326f39c97eadf7c5ad8e5228bcd444e8bb2720ecc428a6770e267104465aa6734d84deb32155d1aeebbaee554c6208a2f483684d70492742e156ff277c8f2a357011a106425c1102c70b0f7edc5842690a305af404c6891d1491618323845a3476822658e186120990d268f55d6012ea57812a8c424163707b92a6ae22314993c83fdd12b74f69104d9f06d12aa608cbb97481a06485358cd60ac4402c0406e16cf54b7e6d5d2f51b213695285552a348992340a6a856910134218d0eba75995a9d0a057f78f8998cc4693bd4455cdb1faeac46d14dc060a435fe197a641b74f29a534a99b26354d6a9a44936895499a6ea255dca65adca65fd031a819b7a91ab7e907f360a6daf1170eb6c1345806ab3f754a18305dd78993aa626010b69e60ee9c5e42264d86506a58d22cae7b39b7c0c00344bb09fae8eb455faf1e4ad6255ed50633298c89d4c5b1b81d831e286e3fabaffa3a5522a6aa8f0221256e3f71bbbe66909ead9e91e121263923f2125346f4ba642e3a7d38064cdc66a0a96a206617bdb443f2845e5e624e86e20d0e422f8b4094214fd2871e81c812d22722103db6e9a556b5ac3ecb7ec2b2be5e1998a429cd4e5fd3e719974f361f7aec03f1d59a9932cafcbe3e9032d78228292332100dbafdeab17f188892f5a755fd2a8af52585b0cc82b034abac42e5137ab72c8a1eb99f8050e62ffa027a8d715f976f16446586fa1c1786a849cebc5f5f949c11b9ac8adb9916332fb32f6e67639831d5b89db54113722f4ec688fef4ac46aeafdb5694a24862e23695dbd4eb0175b959b363aac8c86cb01c5bd1a5f71a465d2f7c5e8bc2245f10299556d1fb88f4e536c4a5f73cfe5eb0455eed576972badb2e1a381725b59ccce5ba34c7cb4ac5a4e3ad2d652285b511a67c3c95a42f8f9714e6e3f44c5578ff4c9f9dd323e7396de2d2ad8939847efb3bc84555ab71fc51a8304cb5514a05b1e47808fd8e973e2c91b70d67107a1e96c6a5449f33fef427c8cb55399647f1785f8577a6c4fd1851aa15ae01d10711cbd5ea43c4721c7221627921072202f9788b9950ac85d51021216989885a98accc6e47afc5a8e791cfb4a5175e6a4ba4cfa78f98015118c785210cfc5a587d1ff249857c52209f2c04b9c7b244c4251311cb8a5132136a153d0b2f39202f43212f51434e4dda92b6a42dc5f002cf919d98989898181c1c70c42a517cfec2fb5993170ee54afbf8bcf0eeebc385e3b8f0024db3789c52574d0eff4c9fcb60af02fd397dce22f4670ea13fada014aa94c25129fca1142a65402d88e56ab512cb711c2296bf10b144a180886518b220a23e9bcc84503ec42f3c84de268858f2b03d8e636b8f1910253324aaa25a8caa78000179c9b1f01594542faf2d6d59cad58f97e37dbc44e564424259f6e55220628c85d80a624c252e515203ca9028d9415b162ea27119c57235fe10cbf12a88e58150404b261e62b665b9f45e0fab730d88926da40169402854a86399ca1ce9dbf2a549dcc8cc9ccacc340c8797d0e73dacd81c1786461a5010172ed2b0d56a1c7f144ae625a771b954b40c83f5e951329f0dbbb48d28a901756b4046ad0119b50664a401519f933e2267e432fc12358eab9591908b0115fa88d6ce1e65b0b7e0a4574225d1d074ce678f38e48855a2c4d04d7c0ee54a16430ce2a42a1e62c9c3edfbfc08ed0175fbf2b0e593edf671c42a5160b80f1318441f114a9193e08a068cdcfa208af47cbee78dda1276531825b90d18b9fd235dc442e1d60b2390d2f239b7a09020ca077c6ea425a5e553e5033e6fb14a08a2bcf028ad092ef111a174eb85176ccf6f6c99dd9458d2d8d81fb8c696343bec0f3a280ce8d2f01456d0c2cacfa42dd1dc522b19564e29dc27dbcdc42f4b386f8fa5ffb622221d8405ded409f2e235f869c42441b1a36855bfc53e2772258da2eb57b6ca1266e72f577b495fa6bbdd13cbd32dfb75bb83c29ff0357db2ec35abe7b2773133ba5c7a67cc8cd8f566104f2c9f6c37bb499c3f30c7af1ff8961d4423a56fad30536742fca9b3e2a112681d6035e4b6581941fc656a99d7b19d2d02cc16bffb9848d398a8c90f56c485b95c3af485bab65c0ac6b87cb95cbaa092b2a14e8c4bef99b22ccb4024a925f30498ad291e80450e0219c8c70561c94445cdcabc8ef28f0c42284d9e4aa06f60d1a9b489f76b19e6d440241910f3331049166611962b9f1684e58f6455ccc41401666b4a7f0a77d3bb67a16522366a1bbb746a69430759585902136ad09a52d8c28a1b5eb888b95cad49b42a57ff5a06195e6f75d8a4092599e8f43e4b84f5d2da5c9352aa5ce172b99220822360d1aa356422e3831e4c3185292e177ffea4850d966e9ffb1a97d7d5ce278fbfaaa44170b34beb0c52c59269f31b0527ed61b352366499184e6ee338e678dbb66dcb4cd9b671db9d6c5cb79d13e746b7d3eb64eb998925376fb2b355a20dd9b39492ea7239b9d90f328eef4db332ba514a29a594524a29dd324a699665599d95bb76aa0dc912f6b37e1982dadf349bdd5a6b92e7a19a95b2a1b3b798b281d2be94dbe29cc0e42dc219b341d2dd5e7fc3f0fbe6afa6a49580a0ccf8de4f70fb91d6b46c8add4cc86896d511d6454030328e2ab53640628fbf9b267b260c357cb12e6e82ccf0220d2dab311f1cddfebcae953268437509a1443b15e71cebb6d56b96ed149d707c83d2accc1b54adb5d6ea856b4b174454314480029006818c32ce826a03308c224e407908234a701d1161841011620c8da145511194ca902209a450c9765bb6044521d3d21d512ddd1a9996fefc5265054a323082073840020c3008b797e8028d9f2354f0c2a2d51195a1041a4cc14204430c2184328478a1e24a9614bc206603d711aacb8d1fd50740f5e6c8162ec8c8b6177858626a90184230515747713a33d470034786954ac6d06dd4513477c6c800baf5ce1819546e8942f2be78939182b830bfeb2d84b63b2908745f5a2c48888a0329036f52c8df2801a60fb64081953496a8410f84d0e20dbc49e1c6514ecbb89e1cc7715c4f31e5076edf05b5d63a4190832aa2104619563c610d16d010428d2b50c0a203257a441078de38e3892e6c60861b520ce00446444105558af0d2258c2d5e43f8010a9ea0c6115fbc8855a0d182130c210d27e8400b077919cd6acdde53ac9496a0b99ba39476b58da8502ceaabeff76bdbcf499f037284908fd0ee81be6e770dc3ca7df445b3a8a156b57a352265845fbd755e6d66cd9aa6ddda5d4696bd72999024c25abf6665f4bb1ca5dfbd34ade2673857758f34b5375464b3d24a51fc8c99451a8db2117e2814a529337186b5e7f6602aa22205aa3a7e90cdca4760a106b5395ab50a223162d455bb26969a66cbbe9e966959adb566307a844cd3c4fea493ce1b5416d2d05b7e618f773ee40eeff32851d201eff32c51b201ef1371519201ef1379515287f789c028b980f78900515201ef1309a26402de272244c926ef1319a22402de274244c903bc4fa4889206789f88112599bc4f2446c902bc4fe4889204789f08122573789f48122597bc4f44899203789fc8122505f03ecb45491cde67bd2879c3fb2c182595bccf02a264002869c3fb2c214ad6f03e6b889234bccf22a26492f759459444f23ecb889233bccf8a511200efb38e28d97a9f8544c9fb3e2b899247de672951d2c8fbac254acaf03ee9a2640cef932f4ac2f03e09a36491f749204afabc4f0651f285f74921728892e4fb24112559ef93459424f23e6944499ef7cefbe411255d78b7f03e9944c9d5fba4122587bc4f2e5152082573c42943f01bad2be049c0b574deef795132c8fb3d304a0279bf0788922cbcdf1344c915deef11a2a4eafd9e214a8eeff71051f2c7fb3d459454e1fd1e234afa78bf274649fbbe8d159b217ae9b91ea7e229a5b453e04fcfc2106899d8fc2294179e2083a396cda965927a8e086526f1a095bac71bb03bb19da31da49da41da59d251e17cf8b07c603c413c423c433c443c453c463c413e339e241e249e251e25922e222f222022302442488881091212244448a881811891139228244248988129125968bf562c15840ac2096106b8845c42a6219b162ac2316122b89a5c45a225de48b849140641029440e914464116944c6c82312894c2295c8a59e570fac07a827a847a867a887a8a7a8c7a8275625e73af6c5b572c41e1755f571aed7df06ac0dd10fd6a64803d6c6c8076b13cb80b539c280b541ba80b549eac1da2839b1364ba54db92c60532f1e6c0a56019b02a2804d054dc0a6842460534311b0292208d854d1036cca68079b8a39c0a68e1a6053480cb0a9241d6c4a690136b5a4007be34a80bd7935b1373004d81ba003d89b2003d81b2126f666a800f6868800f6a628077b63b4c4dec406606f8e04606f9070b0374937d81b2525f666290016c76583c579d560716034581ca02416270889c5119ac1e20c01c0e210b52c4ed1b53846472c4ecc88c53992c1e220c560719260b038452c8e8fe5f182e5d16379909607cbf2206279f0581e3b96071155f55db03c8aa8aadf82e5614455fd95e511a3aafe10cbe388aafa422c8f20960710cb83059be35ac1e6a86c0e8caafaa3cdf9617382a8aaaf82cdf1617386a6e47c88205c2d7b1d3be78e7712ac5a73b6f09d0711261150e491b4138bcd161a87159b3ee0fb3daee98373fb46b484a5ce0bb43f5e33488f3640d646b43630aab209cae17adde6918492c71176bc942f4cb97dce962fc06e6b79a25ca15ce1e7f66b8688c25295a3da7955435aea5ace735236c524f59ce7a472725236e7399f200d649091654f80c14ba88b30f5f2b4745a3229f51c51954949b44f99623ba6582a464638554394dc41a1b81d364ad5d00e1b335b42da1f8bf6fd03eb517cc9d194689fe21f578f3da5c7061580f39c77a00278dc464c31b19942139688b56c2ea59563534c72a04c34a268e55c4acb9be122a49447d20c4246486f398b887a8e7adc89d9f4b886581196395c3b2e4afe392fb9540e570ed7bdb813cb1167efc47a2726ee7c99310ae7a5cfe1615da616912497a935a9aa24a2747b27766f2caa552d863dce968d0b30d889ed205152650591185680b0842ab8b4fa3b4994f4c145050ca4d872c50e9cd0eaefc4768ec280c140ca8e6e82048f6b40460e28fd8b83497983838cf0eabd18cb48c0f0479aefe926b1e4aec643b4eb2354fbe7c5d591bee1a1a9aae7b855d29d465a862e27de988ef3238df315256b666870bc136b2c942b486ade36a9c76ad4e3bc5f7a1ce94bfacae8abc91d481446a59e32d1ac206aa5eab8d50c27b810157119556a56d947b7be6622c8b6dc4a297dd117bd95b6926d30bdb4e395fe181196ade4453b8bc27aa42fad959ae4567d2f75c85154ca768b660b7d5172b50ab7ced263159b88be72bc6c221bcbe313cc81c79b5bde677958ef293b5b5f9594cd3dfe78589b56ea3bac0e4d5bcd5c070f553bc3564c55fd1628306a0dead00c52c90b507185172c9cb8c1088a68d5d750bfeaa9c7b13796652c17f11623e6c231e097f4e5d6d7224228fd2bd9fb8f12829a93805b3562aa859f7a36aae7a1aabd76a9ae1b6af214e472b984d872eb998da25b3f2b1bc58c6add34fad3ac6e8cdb6d1bc78561bd768f873a6eeb590dddbadab8edd218caa57931ff4c26935239c66204986c1cdd324b7a985b9f19018cc988308bf4fd6c3847d363ec3747d341cbcdd174cfd6399ade4b26d3cb3635534f08a87e26cb5f0571e0fb8961b74d563659df64795cc83ebc2fdb8838d3d2f461139b1e36eb27539925cd19a413cb275b786a6a7f60ce474cad1e05ed753e11080ceccbabd6cec8185c96443ba56c89d6ba44c9e6b83044a1b2244c92664ec8deb8552b8176825bb515dcaa3971ebe7ac722ba723fa106fa4eb30b556fa732b9df289e557a3892e315d1a7bac1cb3a597cb7adccbac8ffbf8045751669186cd21f59d77ca74c6930a1e53c9a8649ee9cbac567b9a2e6549354bca924ca24e57247b123ba9eae4c19023cbb21c346f1f76fab0d961b03c6506e127b14ba88a5fc436e991bbd3c783f1929a642f41993e309c5fc324939cbf64b28a9c67510b975597bd2822eb1255a900c67c45ddd9f4f7b8ca129a5e5e67ecb15aef9d1744455c84a9f0905a04837de145accf935824ef9652b52eb51746c41d70bccca1a1a1c1798e1c38383aa724735cc83d3db716f1d26a1c8baa495c026bf62553cac0b46b823e5e46cee757b34e343e5ed2ab23e487ea0ca6eb29613adbaf76b5202c394cbbc47ec970232294189ee21b39b7685ed6a56cc966607aac176233251d9b7d01c3e395c77d8865739624d346d84658d2a525ba347d3ad00e798c5dfdb32d1c8935721fdbf3172cc943b4c4b52e7db9270af928c4c76b76afb37c3b4e26acf9a7e9b77d3d4b2f0591047905337dbad7a556d5735c18d6fa5a44c923afaf46cdf22839c36b4fcf6a7573c6f1e6fce6e4bc0cef4beee67c527206919b2ad3730010722d714ed315e73479a61f3185b92613ca8432994c47cd499a5e8677079b4024a667a69bc024f47a15cc815d542544c8c74389c1c8a31809f2236de4743262c48811235162789456b762c84186c77030d3877c3d2da2a491d753a366f5b05ef6adf9e121f535445e9ee7256ac7059837e4f5744ab356af2d4c1f9d8bdbeff6e3652bf1907a9b1bb1355015bfc79216ca0cc28fc19e2cbfde3f5c240a935631eb878808e311613b30362edf857a1ddb820d3fcbd529cd12227aefc4767962a5e9560a225eb440c4f22c88256a05b10c5b2536510f0cbb9dd8534691c3fc68a5ec1f88c4c792ab599d0f91ba7a9ca2524148976898aeec81f98b52b338ccd2ecc41e18764d3fd22b20a092cd044c105dd3bded53c1eadc87cdde43491d5ac5af610e06d583a2d1b1df0e5456e35140988a0c404c224f8ff50421bf04b2d4994ea74e86eedeabf7fa0c4cb6d475412c5d4f861e3d7e84f6b0e1455baeac2dc7fadb1f98e3617fe07b634b9a942d399b259afa1a5b5226dc7a545dfad54197eaa54962c2ad9f09652caac7eb8cdd263ed96eb89b80308697345dd79dd8721cbf2ef72f88a5fb8965f71ef8754d0f62696bd8ed4e56037c8bc2a466955a123cf09f8fe960966412b919640339068f5f468c183162c4880c4664e0570c4f364de98546024617ddda3d83c03e7f91dca4307bedb169f896a88c4483ba2a318b70161e52ab0e0d3755cc379c25b37d1946c906e29810fd185629a51d7df71eebd86335d9668261d513c771bc29439ac94a01c143ea7bac291cf540a0c21307a1bcf0882ccb32304910d7e32617039a9464cadd27156bc47f6c96f75ae6dcb28180b2a07058936d1a71bba67b1cb7713dd62ee3328ebd9e26d3ec91d2a09d5bd22c167f142ae41aa8559dd840d3875fcf794a749d8c4c4dcd988290a6c9ced64083ba69963dbd3bf87a9dd99a4fb0c966ea616711ce3287d467282e6532994c99dd8eb2dd5357c7ee3081f9cd393e495d9bed59c67d99d5ee35e9318ab0bbcd996b6ca99344c7a27a449d7b29e5b278be1ef88120921e0741ef4b9a559b984c5f73f1fc90671146e221f55c438f75498f751addb0a4c76a7a8ded711d6bbf59beddc424273055f57507242ef28487d4d72a7e133d0a22e9c419f0062957bce8ed404920a8aaf20f0fe11f99c3a8701c67534aba9a7703e85ec3a58e3a679d706716534a6a4427dcf9ddcbee9ce824256e9bc8404c056519d689369eedcbd6f36cf7b01d245adb429e8e8fc11ab1684b162f49cd48cc04133a352fbddb79a9e39c897848e53eaf492c4d672098c93213a820a622321338b6856c47d163f528c84db0890aff21fed86c0735132f99d733d10c4aac11cbae9f0d3483644192410a4b66246f96e18c99517459b833664612d7d3be1e96c7459b736b7f207e98d6f32559388e157c14d9ae8305166c3755a621a5ea9aeec39abe82355d654d6f919b414c62d9c38a819a653ab79541dc1a9b7b1c8e6caab2e3f8bcece50b676f1042d3391049f61bbecf64e9d5a6f76f822653786f6eb22925a8eca8cf9b030e00f58c99b974d2c3ea96ddbddf9cb39c98529289a897a8b3e8c413734024a8f36dd0245670ce20d96d2c0826d19edd64e9f5b61e56d749ca864f28e3537c28525a3f1ee5c7b9f5c376ef165b25dd3760e4f28f1f3f7e44191fa5d5adf1600e2a7c3c1b713d67993ede2bce4b2ef5b26f1844677df81c4bc3c386a39d1e50b336d14977ae7e7210256f9ab1f02baae2882cf28dc8b01eeb538c054c82ba771b5b83baf78a7aad793d03799e656f9a02f4d3963d77da506fe95d1e71824926067aae93ef31f76a287bee3c17f6b8dd747aed4ba66ae2c0b9f3333eeebccc7c789a67f17bdbef386cc95dcff31eda932d7f5c4ffc816f8c4863513df45c2abe860c881eb3d99fd39ac452e7ced93bdcb912224658b22b0b09dea2795632161a3b9b48c95d8ecb9e95402e77af5686d22c76b52a3bc7856179d3e73b65a22fd9c56239da1a747ce0ac78c0492ea1aaec939bf334ab2fc2f9920625def498f11429b3a5619ececa73be4757b3a6347883943be9d94bf5a7c9946a51c978fbadb384923bb26c87a883e372cc6cc2c0c343b973afd59661a53cb5d6c432884bebbfacd6ee8686e3388ee332283dcecf581b45f74b329a1ee7bfb059f445325556d9b337c9ae43ac075f786e76eff4f698ed6fdbb26769ba3c73d9e63255652f790669910a310ab303d159352bcb7e43b3fad997641955c22b7db84e7808ed5bb706454a4bbbe7696f9b89fd5a338daf6513e501b9d9119055102d256b6a0577b73855384138efd139e79c993735ee180a26a197e79c2514ba036f3217e1348305a81a0669f8a5f554670df3d21aced92c5adf9beb361012d09d5aee8cb5d1e57a415e2127f5c8a9b0023eba652d398945f6d223f984d0b58577ea9d7aa7db3d26847cba7d9e76de52600a14958cf7fd6fdfb679db46edd863edb1b357d3b75f67e34a150ef45e8a3b7fda40ef89294e54325eee9c38721cd771dd970c9d6de3ca026f52e00b1bf7eb32052e4c086b8fdc953277d6dc3b46985dc812c2f2574bc59cdf3d15e3fd94e334147bd77e9db1331007fe97f2de9f36f03f31e5894ac6ebdd1347af037c3d11488f2d9aec122bce4b46985d47ab5e7853a764d75774092567bd1622cd24f0aa2a42fa1525e79c7345275ddd1b84dee45457051496fcc3494c9fc97cab6d20d796b579d6ecf566975f94a49452dadc10eae332cee5154f9059a40938c91eaa629feeb9fcc9db575f84fc6dfb2d236c6275e8b19fcd5aafb16e9072797636555f72cc71b5be56e69eb0e4ae766eed0d228181e76aa7da3dea65b369c699c6af97ff6b1496f5cbd5bc5ab9ceae9ad8650a56aecf9d5da4a0743dfe78787aecff305fa6b89e5954325e3e8bab1ed9e3415872a9f9724ccd8f577b4d4d51c9783571d5637fbcf596dc7d527fa8f7729517b764087ea3656211488fdca455fd9edc3cfa69046199da3e3fde793eba3dda717e461e87b1a58c950bfa63172c45b3fcb815102e349ec068285d66c097183698cb19453db40951a033f8053950ca6239f872f9256043075174f1e6d308c3697cb97cee8934bc5ce697384f809fb0ef09d100070d446990a50209d1004b65a308ef05191b534026b4ec8d18136cda1338ce8dec8b1850e892c235d858a3cb11bc35b67c62d800e4b4b8fcd81a587c6b0871376b7409ca96e0876b007589e2562882c233be54993380c4106286c351049a9a63e6f2d71081eb8b1d5cbdd38c2d5decd0c284262b6a4c556c6a8a8d2df574a7195b8eb8d9e2bad9c1971d2011ed20c6e582c1f9b42de017dc1078846ae4107d07423b086226760014da8a86c8ede005d3d101e74307496018cf0d15be2e8daf8d99367e7c5d1afc8f8c2fa6032eb833867480850d2c3a68c175e9b833a6831777e47d612e062bb0010612158dd3ac80850fc823c388a32d574b1140be232c47568e9848c1ed1b11ce581a5d382842500a42740c61c8eacbc1d26521be31c313e245f84de13a7add194b83e896e19d47ae3b636a28dd12a54610d4e872f95f04626820c5d038ba338686d12db3d79dcf72670c0d2b77a211050bae388128c219fb8117208ce007602eff33e2cd2aa1d6a5080d5809030ce13f1d201f1aae5bfea68bd277c6d02d7b38073477c6c4309a398c1105255a00852b5b7869e96022ac8192a92550aed07afa1639aaa224b7b88aae2da945c514ea54c52dfc14f55015936e4191d21aa98abfa4c9911ab8590a9dc586d8c842c199410bfc67a1b011c048b145ebbbf7f197d2ea148d898981124365ec89eba049c69db11860b9554e628f17a38344386f5f24ee09624ca375fa67a1788f79eda1dbffa18290e638ce48f3fb448612fe93c249b683261761d94141321d14ead0220ced6cc91c0ca22478997714f0df1b1453f5dfc37f8f2223a6aa98ca01bccc997c0f0f9607e0a125a825020c4c2fb74a2846d981aa7a0955f56719b05678999733260419d107a418a614b540d1888da6d26c4d90db98412c94efe0bd1b6031420b14afe88805c15398b1822fad4fbca2c30aa3366ebfdb983e93db2ae529a6687b629b449137511333b16c2cb7a90f397e5c9f9d2d2f8825d444df633e732950aed00f4a8c14d78baa38458fe333457f80f038c428e0c3cf88e16c71100321e92c119ec4548d11537404a098aa220fb598484c5131f5fd00e063c42857be833fc0f798c77c9fad232dc508227620948497a1376ad06a1c63bc8009274cd1041743b47ce86005615021c410a020a2d552b05842164b683c81684b125afdcfcec4202c5989955a296b2b596e63992daad35deb98325b86a3e0ee20223128afca33397091dd5a75469729a59467a55d2a63e79db132a72012993748c316e408e1e9f331e7afb8d5aa3f066908dfdd649d50f1267152ee9106df163cf5819235473d8758723b4e232a1d87b8849235228ae36677844e3049f86ec63493dd0b3b4ed1cf6bfac9a61ea39dfc222cf98bcb0745203ed187272d63809fa9c464890b6acc585867a6846588ba41f1e7d156ead6ee43932c20a6644a318e42a35c25bb063822e8db70d0ee030f4b134111dc7a293e4c1903fc7480ef01745c8718848eeb780c538aae57ad9218a614dd18a61451b18a2b862945ad20748857fa572abd0e7ba55f7f19b4413b02c4617e2ab9f83ef081e0e3b022c21bb745263d2e4125219cef640cf0d3ac79ced1313fded4296718b03b3f73b872e478f51846f89ba39f634ab3aad4bc9fa33ff0d452af0bc2cd728080c419413958f8222c7762497a7adaf4fa89354336441687e808ad56d412044ab7ecde4306bb608e6da10644889137086bde7d27d6acf2b4746bac4d9656f5391ba22ec2df9aa11b4cc1851056b690f1002028788006195698800a4f8714a1ce4be74707a643a5599e9d399c03766d4e07da2a37a7b64a0e98a51e7b24f5d83dbe782d822a9a009ac2e9039fa3e3ad6931aa21158e7ba045fdb33baec3b290e3a590580e175581df61bf9f4ea7d3ccede9ce3cc7dae8b0aaebba650ed74948172147a290588f39b1a39da4f75543a14cc8331f28048b102c4288c09c83e2417b100441f0ab54248296222d94cc39907bfdd9d8f986124c589a685401ee74d93902c59d980ac682b0cce1da89d1406f95dfc615c61cfb25bd262145ad7acdd0f401bf82ebb33d42c298544851f7696c88b80b6950dc111263c56690064518254531270c29ac4752f748da12762f77625df6baa5cd0a412bfc582184e584c4aa15b7cce1ca84b8650ed78e979da5dbd73cdb5755a41aeab1b1f4d8f4deabc87d5684f352d516559639390c2592306ad95c4aeb48f708130e89a295ba94d64e6ce7a859f42052b37088ac85bf602fb80bde82b5601930166c0557c1573806fc02aec2523014fc043bc14df012ac04af8093602418057c023e828d6022b8043c021e8285901225041ff000077a3ce9001020801204bb58043c8549c02f2e827fd8040ce3143015560103310b98096e0107b10b380a9e828518066c85a9e021be82b170164cc45cbcdf734449cef27e0f12257906eff72451928bdeef51a22483f17ecfd20bae56d0f491790b89ddfef60ec60929a2aa267b24ddc371bac71f0ff07ad94763633e634fd4c65c6fa35bf336b72d263c0e4b73d0ce9cb5d81fce60587bd16ee05c647d9cbfb01a38cfc0aa70f6c2fa70ce627f9cbbb019387361c7f31616036722ab3a6b612f70cec2ae709681ede18cc5b270c6c23a395f61819cadb0e579c8063957612d70a6c2e69caf581ece56ac90730c6c05ce30b043ce2fb014380bd9d5b98a9dc0790adbc2590a2b817314d685331436026717d89df3131602e720cb7376c23ee0dc024be4dc84dde1cc84659d97b00e38b3c09267256c03ce40b6e7bc02cb80b30aec0be724ac0e672ad6e78c845dc03905b6c819055601679885e17c029b80b3096c0ce7236c93f38f95e16c8445c0b9086be44c843dc0f9658f9c4b600d702681bde7115826e729b6751ec216e02c020b80b310960067979de1526c0e0fc2227914bbe4506c9287c00ee020b034fc03560007c2d6700f581cde016bc339606ff8131b80f7b04a2e6359b8d49ee8476df85b7bd662377006c3fa38175915ce5fd81fce33b03fce5e580d9cb3d8f1dc85f5e1cc85559db7b0193813d915ce5a580c9cb3b02c9c65602f70c662819cb1b03d9cafb041ce565827e7219b73aec296672aac90f3156b81b3153be41c03cbc3190676757e81adc059c8b670ae6229709ec2ba7096c24ee01c85dd39436125707681e5393f6123700eb244ce4e58089c5b6059e726ec03ce4c58f2bc84dde1cc02db7356c23ae00c645f38afc036e0ac02eb734ec232e04cc5163923617538a7c0c27046815dc0196663389fc02ae06c022bc3f9089b80f38f357236c2363917618f9c89b00838bfec3d97c01ee04c02db3a8fc01ae03cc502e03c84657216819de12c842dc0d965915c8a25c083b0491ec5e67028968687c02e39086c0dff801dc081b036dc035600ef800dc0396071f813abe43dec0d97b1aaaba2d245a8021255650fa3db9f41222c7762a50a76755e2b00b5aa2fa428a987f87e0fa41e4794fc4b2145b747d2eda01e7b05d70a535678d95871dd0dfc876be0efef28513203efef2c511203eff3b8287981f7795e94ece17d1e18259dbccf0344c9f27d9e204a5ae07d1e214af2f03ecf10252bf03e0f112529f03e4f112527f03e8f112525f03e4f8c9211789fe7889210789f0789920f789f278906ab21a8a40cb586594c95a9111100000008008314002028140c0784a2b1502820a9b2643b14800d8ab250705499085a9263ca186208000200000000000404a34103ad9cab2ab24c6020ea6d7a2f35c769b9ec2bc8072869d2ce1431415c92a27a98ad2ec8c34a73988b66580cae8f803ce74ab577e5ae22b344b802a0759a07f4806106592a83a393ebb617650da8cfca3705aa6c3dba4d93333430d94697d6d9177c728e8e3200ae391d38323e2305396ca4e24250a6a1431b6c3cd93e800020694cbe2b7d995ce1283ef79e29aee52a7aa41f4b6d2ba7110f7d5713a741fabe6c0996340bcee56dd760d6806d7d50a1695ba39458b9eee50e04e5c0cdc10058237c51d7f4738721c650f65c202eb2a1ddaf79d3930f8e2df964d290867748664ba6e61aabe6c1f5bb5bfa14899283fc198ed29717d35c4707a27d861efdc4360c5f7599b1906254323d7892c3b3bed4a0f5a220d4ab571060d4e322c815688c1d712cfe416023d5ee8769ec0bc1393b1749b913ab1c38fd897bdd859cc167a4ae56ce703e04b660f0162d60b7d862ec72d52d0b44b348d5b7507ef9d3c5869cfc7b2d07cbf19e67dde622777a5888074a2eca9b8282209a47af7f8d892c7e2f727906c58a7d8e842662d3a310b9acc06289516759dc406692c7afbb4d29b9018f1c2624952b5fd7b13664a5f424d1e01eca98e5eb6ff4743bf3f5c1128f61a256645d9a563469207ca5566531bce65fee7ba3468f8f8bbfbb65dfbba47255cda462cb6222f731dc69f2ba430a240c9b12f0d4d6b68a2b95839da36de1940c9bef3c786e1712fedf7360f8eab243d80851cb60609d932a552815bc6763049dea0ac3997f243e006cea759075a053ced5df299e2383620b67e488dd154c35108dd95de2f81d7b738a9be72e3c667caa369c09506de88d4fdbc719bc0033c4e52058cbaee1acafd2b614236e3ebb141741c14d0152200ab0ef770e736518f4b09bc30f301d859b947fb04f028f54634c0c79541e28ded132b8c6f18ab0ea5649f26ca7f1c886e48b8a8a051f3fb22398ace18e989e26e8eda86013d8331640c8acbfb2804c9ea7a438b8b55a4fbbbffae24a6632f56072a8976b4b6302b69b69f101f1ca7dcb7fc0acb04647b5d50c648398fc14e1e1c2887de739ec33ebe3c6a269e143b3a689615d669e35916641f33fdc9680c0613bc6991eb80cf841aa141a437388b0d51c6689204667c20df7720cb0657e4ca9e65015b4af5bc1e0150d5df7a444cc7a2b55b9bb378d345609fdb8ed831ecd83b9031c1c53f7a65dfe6a50ef392eea0a955fe74d6bfa94ddbc49a191301b13c02c7d7360620210c4ab034ccc395d788cc60b35a150beb8511056c91d8bb31166c177d3feb926bef567ce114a61dcbb02e392bdf0020c8f0cf3523c768c6722d965aebb8a6a6efad42a9820c43e19608a97e46ff38aa4a4c64447c4ea3e668d5e7d84194277173ed386650e670d81a8ca3df352bc469414a4a919362bc37d602904ba1580e5618ca159fc7ae53e951588daa10a1473836136feeed46c67eb50a1e09a25a1a6e0fb3be4b876790b8a838e6bd5eb48b422149f4621d539f3cdb57019ff65c5ef50bf23d37e17ccf9347bdf4b826b7e0dbebe09c3505a3bdbde70dba9a588dc7089e556614d81a3021bf159527036f1395ddcc539641b4541183304d52ede412e29d3029b8f17365e9bd401fa03f4042f994eb11089ef1d1d6f25e92b0389ddc59c9f91f0c97ace373cf572f2bf2d62473c3955fc80cf27b8a2fc0b4d79904321f50a364e609b0d1e33dc2e4fb3fa1416fc4c66c3b262c3c0697c80c5ab66b45849276add0ac6b3d4242fe3437a014d3048c25ca8ad61f8c8ae7bb2369f9f0a22f988749b4deb688596532a489253e16be23d88d77b915c5bc31c1f490ee98897a4704abbb78905a2e83926bf9a2053eee97de9dc4897b5b8b6001e44262830d8c9838bb008d55db85d0e3e35ad163c16a7d9f67da5cc7e4fc8793a6de0a8b6e8cf6325090a64b09074eec143e9d58212747c21030234e963ae1a62081c8d7bb239ad32fde8fbd5536f94ba9ebe74fa1cc958de137701387ad2a423afa47be0d30f5e7d66a856cfe8daee3de11c4a132179b777a53b7634bc2061a0ba92fd3d352b52487aea663473a491527fb15af13b47dc936ad552119fff1e30b9dc158870d1651292ece9849f3579da6b89f8f3b86e4d5fa1c51056ab1314310ec47ce04978da46a2e2e55fa767b3fd499b19afad6ae74d8dd0c0161f7972e4379c13a0d715206f407e5f94d995df0999c564510bad4f228a7f62f2892636085e9b96c9d277839a2eafcd2b8edafd13de22bff2696b2b210c74b0c43f4ab42e4bf68ed51a99782b688f1e08f8d698c85f2a9abd2a6700cb956953ff2316708cd730a80b4372d213bdbb45456ec92d8cf3c1639bf64dcc49a76512b3089f10baa456b22039676383a91386bddea8221d12d90bb8c64a050dacf7e29bd18731b5b45ce4c2a2d876b2a9bc4c218617061e956cbda015e8acc4d7626d021af2f7c3110d5c43f9863f390821e7a5a068ea5a7a757ab7de0e8ab9f4378b2c095f1eda3c1bafd3a0f46fa4961401bd50bf891395801d6e43c310cde64183a2388db67beafcbfc00fc4279fb3af8db56c12a3443ceb393f65621dae00b41f32c87fcfbc7c725479a56d3b8b37d231a9bbe85590be12951c1aaf55a9a00e2b345f7f94292dba16ee547602aef63a0e1fe800b40912a45ddc8891b751f637a4d4bb57d0354677127e32e8825b271dde90083c98eaa435667218f003ba889dccb5485cf08d6a7390c9a5ef0af5d27e5e73a0771f55201611ee3132649d8aa081a4fc0cc9a2351d641001e779159d129495806b133beddeb75b9b72f44788191c743449c5b2ee98d6bad088427940409f1e04a5fcad8697272fcd5bf4c0f5e09e51de80e159a953905dae7d4966faabc1e85f043bd55029166c20de0497247105ceb9f70864a6f0a425a4bdd32494b2083450f7be969ea6007bd4bfe543d0b7d7a2b03ab7b1def861c6c6ce1bfffc51d13f2402b230233b5635897c6989d1af86e09461fe7189607da75904ed5657b71afaee777a7f516727a029ca4249239cea847c883ea0191b2ee69141036f8d60ea16a88b69825b7fe48b64e82f63c623bfa7c92146093050b4e3fcd0b0fc74f2d5ab17849de54717921435482b38e72f5deb07a9d8fb03e3ad312082a2946db08cea02ce2b587274e91874fc22b0274b3fc62c20949e4417ea0dfffb3f1189763f732b3a5ddce8bb043ee76437dd088c5b63e43b84907599b4d764ee7a66ad4b4681eddd62f370a7c8cf08d30b338331c70bc4452dba8849072345ce466f61fb751e5a17518fe8a5ac4152be18e8136542954e5f3517ebba8a106b38924270f07dca77d77ef344b47145a7363b2456cf14e0e88e4aca036005d0dbc9284fc3ffa2cd5605597950a2710a602dc57428fda53feeebdf0bf75742f7228fdb269efcf8ee666b7bea6561571a2461f46fdfe5b421008d52031c7f87e4ded41a067a7c79b4a1d1d11128097658b7dcbd6a7964d02d01e409c4ae43281aac09809a44b0228dcfa2309e843e8d46d554478e9d901ffd134cbe47023a1b186f47f886ff975c8cd32a60b4062c84466a3af89faff4dc1ad1d03a77a089c1a3fb49e767700d028c4af719651cd83e4376baf50c0301cecadbd5aea660bdad6cee8c417d75b9c9f20c0d73ab6b0b2d58ababa426539885c0752dc7b08a01c8582ad80652e29a65004e7cdeac2c0d7fb3a3bce93f8edf12662ddd031dcf68ad4127245675a73b61b3d23117f4f37e3aa1f853f6f29d1f5f897b3408fa0e8f4c2832e64b81b95e8086850d2b8b2feb37133c49afa9fc6ca2a25133505bc01401639e7dfb134975e59df1acadc6142233387a6c6db3f3728a001e878b37299f64f07a55455e86a3eb77b772353bbf3877fe5d5a86c373aa0a3ec432d40819e7f4a6edb973c40cd6cdf42981540dafdc70fe80c0f64af76d2207d08a7b544962996d77fa5b65a0d6746bd93acfd1c8395376a73ea94fa64beb377e32c8ea3a23668b304f6de2067680323c2a0400310f29015c3dbef93d7e41dba67c5ad67eb254bebbbdd426965d47cb521921d65f819d69e304c47e556363c3263a774007d8ef31c1e508c73d970221c7393047b2374e130fb8b59e148dd171eb07972cdf34c1eb8df548cce9a28c51003ebd265aa6e8bf72f601987b9bb9c5ba7121917a4f269310f4c4002c85025066c2ea1ba58e35d203b03493c88bf8234b591d50187e4db4524c314c33ab689ab4060cc169d8891bc419f75f00a8b319e9998a3b812d24f353570a8c52c6b39ce2654b8612884b34b6fb4c5318bba707e2dd7a1ecf60893ba3028cf70b78a4ae07c7847e6c25a72f1808418ee569b5727fc62b03f595529a592556153a33809e2ceb8872c145ab15ea1df1b05c0cf1fd2cf1d55670bae450d1e8576c89a93bcba238a598923f876ca1ff781199c9b1804b165a64bf2221e1085cdcc48282f1f48fb9a87f58cdd0b92c5b1465b8163df3f9aad8ac5945c037968653ed0667913c9bfada04b5946c75b4fb1e52a99a90c044781c0b6fe900e46657e4be16f3e8e315d5912f4d2785481e082ee6c68563e787218aa291358183aa4d372a63af7f2a99b3c4e2c0dd4ec35528b951968347a30c58b60168008cad523ea8ed2fd324df4f1b0a9d2eda0b43ea4f8f2aa89c6ca90236f5990240c0e0434fb61550a7e2ce4dfc9c41b631d1819511b9e9fa380b285c2919da9cc9d4f1beddecbe3ca30ebec672b367a1a68b1dfa75a67d2af3a96246ca794651003a104c392f0f34ee12d69ce54731bd8c446c030965d2cfa3baaee371e7d6250233023aeffa702aad704c02dc93a94addf52cc517e3048dbd0b4fd91186782726b1505ceb436a227b1abf062844f7908723cdbe38a340036c7014fe04f8551fd864f7dbc85f9d5057059d181ea4052d69008e2ed829bd9b4aacb1bd96fa8d5a5e6fff2bfd257016a4f5e00879c9e692f8353a3524e220550e31bee1326c6e0addb17525b527fef8915ae83a75dc70da00a09e1422e93367a325f509cd4d81d555f8cf402c7cb35f39a1e2f8ac2000389227fb676945e020acfa90e5ee6aefd6aaafde309f630ab925768f1280bae8d0fcc06eaa4e995c3871095d43ce321fc3be25c24408937a2a28741a275a41070a34e8f76fccb74fd5464dd473ea393d3f68540ddc095bf438e7bebb4a91cc6de086cbfb043a263f505040248c624cea1dcaba5e809868da138b57b8485a82a48b24aa09798b50448a4aa9adde069d0721148c01dd469aa318fa221c316fa898669a56e3543d482da607b7a1b16718e737a031b4688beb1a26bb7156593cdd5d271632031404b29b8c6a45ebc5b032aee22a1e95f21eaf380159b206b42b12084091f7660951fb201810e06cf2164d044f002c20fc9a8e75d72c47743de4681af52582c1830698d10af56e0118110a54b8cb535c0ed0b545e419b4d00568412020a1aa770c302b5bc0e514f1d2baa7f9b3656beac7b20b3dfdc1ff4fa18cd47616262e6f063151a157550c7aa4efd2b3c1c63ec7aaeaf2e2098db416f0393c9668872dc73500a992b91801467799ba95f2bff78e47c011d88659b17d61da611c7082a4d08378c08b1ededcfc870b540d32ae30e0bd9289dd65020000c4e82afb54b1b4707749d9856b4638e17bf04d6c7e00bac080ea9d27ed9a35d8cc50e4e8169420acff7ddab3b7303c67342c745f66a8eecf6873aa3efc6fe92079864dd5ade19750223414308db7736fac61b9d6f50e574a08309c450db436b22d9c00e2b61878f77f655cb219c2a7fa7995af41c4fe44d7f12a8f7637780dc5e66d50febbd218bc18082982667dae442910ad020934a3ecbd6c8a61ac8cf2be07f2e1ca3ae0617a4f4c980c9caa13084c87bc3fe8120ffe938a0b0eecb66b9f65ad2e4d5684bc8016ce7ec4609fb37410f014ffd50eb59752fc9d0e0585cff396437d9641833730bb57070a8cb9f13fd471fb327360acce5a580843915a5f401ca44dbb9e9a499dc29a9f45329ffaf391a82c9569c00311411e85e94bc9c9109b3890dd0e0a0d36111f640dd6dd5deefc77df184541aa60b3784551b3c03d0b8d7c42e9988186763c467b910198f7fdcfc64dd373557ebca2d3258bb44a0bb2082f16967dd9af5435c2b2715035cc0cae863d58318a45766c7f34fb9066e4a1d3d62872c9431b033dd6ed262b4111d9afac7dce646cb7c8fab48ec0e3bf8de01deb55d19e13234b2e9bac38de84de2ecb957e6be386440f27654cd8d433f263304088e4c0c6d50bb85b6903ec528064db8a3cb637d40404aba81e32916a83429ac0f39c376330f1e6a48fdb98ecc23e570aed64317cbdb6282dcf2588cee2ce1db1623af306201ee98dbb1fed2019f73797bedd550200f0a819986376ace3a71f1a197237f1a34baef1a99bd8f53122bf01e475d44e0b469d2b7504372aa357fd7ac3335508214cc2e49f7aa9da0c606e54f42b711fadcff7b981303f9620b1e040fdac1b891af09dbfa38138a1dd9336c322525b7aa7735a0b6212dc5a5e112447402c43989bdea3ddda0e56e6751974413d3293fe1353cc73adb87d19621ad237cdd0b32d4c127c7b7a0561587b078fd96201c0adde6b26d6c4bb1240de95e113f3aafc9f58a639d7b8321f977be2f64ba4ca6c0e501e831b75c28380275239e843d5668cb980d1fbf9223886f1ec6dc3d14e8cffcc1f57a9051e7c66e59b495efa4887bc82cf79e9120ee18ca9ea6a54451fef68fd79c682a0babf029ccb40860a601c62251062bfb2fbc9b7d971821a34f0b9a213d9ee50f151c11e5f9af6337f482a4067f85fbf15ece96ab200b8ae88d4a786f89b867ce4be1d86604bce29baebde31482ee51a322ca3604f847a70a5c89c0ade2f8a649ead34d751c278384ababeac1980acffa32d688c2f499d40ffd8c52c09d096a2835cb12d61274ff331ef7ec82959c82819beed01dfb8bbae539ffe19de38e32da8e181591d46c061abe902a2f16e047801a03f093abfe8140672b10e33ca3dde731bb17e6008bbdcf79543ac5c7c49acdd176713a70690b70b3fa5963c165979cb2350216b4b2a00b31741efe3cd1cfb85f7c9280ceeb0142ebb8cd03f76574b36b4d6f2c86029c8dd12789c1cf6d32d6427f6928f58cfee5aaf3af55116feac5e6385a53c465f9147187fb8cb8a9b7a2121ba6e3b720d4906583fc50c3e33045234041a1e7dd283e458453733435d8eadd6184d231ca9999e5864ea8485aa1c0a351058ec24472bf99abd597b8741bf01b2de72c74f10315a1cc76ad2ac343303779945f198ed0c66ae7819c2bb4c955a462b96ddc3caa2b8ca76963257a00ce14fa64a26a355c9ee8164517c643b13992b4286f02053a58fd1ca63f7d0b128ceb19d6dcc151a43f88ca912c66875b17bb05814afd8ce286685a9506ee4077554bb7d15d37462db4bcca1470ce920a6c5c3e8dd6157a86171c4b02d16e6d015867409d30261f47eb02b64b0382ad8160473e803433a816911307a07d81562581c2d6c0b8539f484211dc2b43818bd1bec0a152c8e08b605b7813958f8b13cfa272b4b48efa1bbcb1087197701b23a548a7bcc563c69eb0956dc05a53e5be68fd317b2b8155f1da334920b47d73a9b65fb257a17aef6f7b7447b36723af833ca10e2371ef4ae1345fa4d9121565a2526baefd101183b78a5d1ecc3870972b7c1eed4c5bfd63d9ede14b9c5132622aca740f8da8b60be58d70b6045b6184bf154dae6c4ca767f45d387f359c71f4ecc48c629d44840ae9bf110c33b0d0d9fd8fa25034530c784311f917d9207fa03833e7ea34bfd8d142e35e52fad4d97a9c1d068295b568c64f6201de63419e6c64f6f97c3d2da099a70907a15cd50590d7ab25308576f4d56ab16ca1f1294fe3bab44bb3d1d3e5d9c8f5f7387075053cb542519fa5d71b3ee9d42a103dc807f6f0ef79c39746bcc03dfe632ff6d534047a2fc51df0ce396227dda0ac51fe6e5befde2c847c4f06f53167a8b1ff5da1400de20e77e7df3d05764e1c1fa531d434e6fb1bf82fb9141754d671701882dc30f8baf2b5434a27ddd3e587ca980a211e1fbf661fd75051585085fdb03eb2f2aac28a27ddf5e587d51812210edcbf6c3fa75851589285fb6078baf2ba068449d7d3bf63af830c06f1f072d54195b37e28b844fc7cbe4ada92107b174a304ee3ba08bf4a8b0bcc78d3fa693ceac7ed2f179d4b669697cc33dfe4f97e6596f154c32e88bd2572a28beea0c3ae81952b1e8ba057f0cd9470dff19a24fcb21bb40d3b3f7fe35cdfe874944fc5758cdec57af0519e7249e258c0e9d96c872f2e2cf978ae275fd0b399778b4a1883907e8c7de9665cba5ce020f29ee1cc1ec4aa5d35b4c5c7bc4d2a117f925dc2cac5d9649f5aa94361e073e9d05520e3dd010f7af308964fc50c9013f6d00a798104a3d791187a929833d9d83cded6e33e73089ff7b3cf7e8acaed1c046ef786e1dd910c888d93b942ffdee307f68e380042bba79d5008078e22e3ff6c052d74bbc929f9e71fa5250f404fcbe726ad51fbdcc2ecbb197824c866a7da9a0656cdf75b6965642995d575eb76212ff4eff71fbd5390447ef541af50c15d28e69501a620f403c31adf3099ad6d790fdb9fd711793baf6c7e0ffac6ce3c6e8b52327f5e77667d993196c914df5eafae234bd1afab0c0ccbf46c6fab8e7a46b609c47d92af10eb04988de901734b186177f9c0b598288612625e0d740bba8c32f9b1271e56d3c00402cbfab368682e5ce33a23bb1b1223eb03a53e7f0f7b893848b877fc7de4f1c2b59a789e3e3e71d42825d1519dadc35846e62af310233546870a0c695963ae7c28312526dbb9994a51126ccf7d24f06689b39f540f24028f390102b8fae12470210f2d1b9659eb18043bd49ad8d9bdee05513a208c1066dd7cb2b53b3af515568025dc5537f3d470c2101c2a64e773fac3bc17ec11f3df2e649f078c4063480e5e223970aeccf231a923a40e692c90f778b52316643d8fda2b502f86a6b9408b526d6a6a1327434e80e016ba99fa4d94f0565b8650f9f9ac75ec0a30f1eedd2bfaac3188066e54384b88eb0675939bb9da31beb502f852017a2c8e111dad0429bb252aca025f91a943111be97a2d45b66c3a5c61e2840a48dcd0be04041fc7b0f2f8aae0f93af9c2d70867c660d03bfbd64b7a4db54de1b1a755acca6c7141f6f1a62cd2a5509b642c79f764c6c1e3e2a203ae042c1dc3dc1e2765d5dcbc82f318d57800e0aba9c3c1ba60814b7cdc5fb271ced25bd6f6a71a13cada7cf8fb60096399e9150d61acae5e27d46784066d802982dbe372190706693a4af01c15210f253ffbeccc2c1a8e8228863c599cc486dd30576f83780f1c5d346f48518e9f4f9dcf2268399c8febf9f993c810e15aa9bdf0974df6e3b8264d036a93ee1a0cd541d678e617bbb9f5a839a86f2bd2411b571346b8512187a388c8b69d2a1791d3224c5031a6da12cfec7e620348930b0193d5f1874616ab99583b43ed99b48aeeb61ff4ca48d7322d8d82a1f106186b7301073eeb15f58f9b58fd0fbea06c4fe9b8f08613c0c334e3e869ff9e14f08dacda82455232b11f8b6a876500fe4f7f4ee76cf4c99d5d52474e4957c0f2a267ead9fb4ad2667f1cc7533a8b9c53acc212b7ea6ccc1819c95b120f836d7ef92e19b3f2659157929d9ce399ca00139e42335f855724b38f4054d2e36ae9055e4084bb548c4e959cbc5901f7535546fea88c61863c688be424f5e9e307e243c3a62a42a4b215952419c83f09a26cdcf80a88af1a11c31a7ad1a9e00704b314d2379c0dffb630d0fc54eadbeeb2835910cc7e473d9a3e8e99ceb572f46e02719cc6b363c8c1a6dfad397b574e4f00beab831d706341fc6c68185a01812249139adf1aa9515eda5a49a143f928970b7d7264327b2e8b2d4332369248080b3f922c145bff03971afdab66c82ab807664e8e4aaab9c9df97a7d9b8661a9b26d27186179743d074cdaf69d76f422845a744e9d7b15fd945a20a1c2cd01e5d0e88542bcace9802473d0421517bc6633e9f9d30ee8b18fbb88eff878f7dd669cf8d6793088f8102a05407115f8fc8261d1b10bfc778206059f29b3fa2605c1924ca4e6022a882e48a8cfcb5c4223838a1315359c8324ce92865c1c14e1e22193d3879d82bc47e44a0ca4f7855f31d83965a2d716fd05484178f48114c36149d62eaf296193bf8ef05ac5608df560f2c5f4af31881311b380e1582435a6140b083fd4d030b0651c93fe7d8fc659f33a54e14b68ce8703700538bfff6347096aab9456f903964d020eeea1ec6f9690f3092e0a192367cc9be1806432eea7641f415d6dfafceaeb06d15033688e20baa30c93af04b5a4956d8dc163a788130d94415eae6db083e4b0af50f06f02402655340e3a000127654f5f6fc55e6123da137f8b203114e11ccc928cd42d6a5403a60f3b20e29f381f298bfacd01c00fe67922dc896776b82b8c676200558d37ade26c50bfcfee23a80b8625c311dc00b0465c9e5863effa4f601f81b65bc5f666647a27612fcdb5eb9de4a9d101bf9314485b2c6def34efb5c52c57572ae3b586ee694c5b0207444ca70274fccb2ead251b1712ce63c72b977889dc9be222b8f10041ad0302790f75cb24856bc7d6d158167db142f8577ddea3ce677d06d8d1d109927a51ce741176bf6d14dc4d7017a7a66e0a8e5e6e9c5316c5d710522a44395e489570545b2c2e1edc21aaa755944868ee15061e363e71837c72149af44e3691b66c83312a247d0ace90a1b53812887550e37930692725814b0acd6cd6b4c6088f1fe0f281b9c443bcd14c769b23a03295e24d1fb7944c29dbe866a4c512e475a01c862220a5647c5e82e0e3787258d8620d5f61f0f34c48ca854865aef7378accb5b43a516455f0d52fcae8e1aebe56130442072ce63a04800498b1e6aa747a60964f8c7a39216709b6d86bfc759d42eca469f67a081cd2b7562c2cd17d423d8e1c93188a30b659e556dabffb93748de98f70a2dbb98e8141fc0fa238147ef0346c7d605288e126b215dd6804465fe2034648a097e017da85aaf88238c419cc2339c091c0e44a84e66eb63eac9b41054b0124adcd00fe74dc22dbca2d1ab32fb0d8d561a10288b93e2a58e5e7ee34ef15a99b83975a109c99da6075aed66cb84bc013348aca7e3a20b9c93682cf7a11f0046166b04032437f9433376ef415e5be98dce2a4fd0429ee371f9d5cccea3a631d9ae48403bb025c1ac2c32c844b5487992f2a7dd39d770a55d2ad5ee33b487be36cd9e32e858298e64c9ae2ee2e66326ab06e1faa55997970a7c1a6e2060fd3a0522bcddfa1bc3298e49a679ee75fbd8a6f0d8da9719fac76328f7834238384e9ad7019091c99bf777107ab796c7229328d06795e90b9cd53a123b003b95d24929edd93515751cddd12fdc7c6a30389bb86c90ee66b49115f8a7ed2478f55a988df864f1d04e991e85350426224ed945213b561b47bfdbdf7997e5e08dc01148d9fda81883f6d9b96a32cd8df3c014c206267005dd4f889613239963db2124b8620c2e6297c8fc8e5e1fef2048da52c70a8ad4b27d959734d21a7f3efb831932868fc28093ed67fcc0ce1c9a9797303f596794e3988c2a37c8f5049960fdc5cd98733f1ccc81c0a4af6c0e5f228993ed2e035be382a8e7e8e5ebc3b53809dfb22d702a68dbe490ec407201be949839e85fa0043601d9cd5336e44fef241747eae2fae301aaed33c17bdd233a5d9ab665ec3cd8640193f68e185d3ae922d268079051914458bfe2fe86e59a5a08053bf9182101cd5a4de37065cbb9ae5e58cc7721ff3b74d25016ec711d676f04513d2022a09f8383d62b130baf91ee0f99145546e40e9cf3d86fdec2ef98d7c3b7e4f20785a40e5f3970b220dce08d13066ce0d380b84e4ca841cf01176d86a9cae8b9a5f2f0748953685eb9e297707c6882cc282dce3a6789a247700e24009c0e4351743dd2a9849780b834c00683dcbcfb2bedd5c087c1b869009341d78120f5633a2a2097c34041fb78102862a18e5cd6f9068cfd1507f4a8983401322f1436249ffea01a6ccd542ef2e0357c1d9a935282a0d980851b64aaa8f649609dc5f01d193e29c0b29924118cf07423a7a1bdc181f595fd0dd5a6310aaf7a1af4fb70c5057529408a5a6457259a60a09592aa959d731fc1ca9662afc975584e01bc2b3f3b829834d00811678ac2c4c0ef0eb4078a443c09fae4bb7044c5405de41ee1c062ec1271e26673f1c6458ebf714c187c08d43f543fcde3299be0401c500caa1c71415e2c936745816264cedbedafe5b0a32290af7ace5d8a2f8bcda6b40c13629900d183cf75231b5a9281f7de9ad3d607457b9f817cb9d4900a66ff105a8705eb56a44394b1d1f2fccc45aa1ea429e58bb5d5d588ab561a05c5430f721582ef98428509f7b542cfa3bba6a7386daa99fa5118d5331d69a44ab46910d18036bf7e46c8865059e44adddb53a5ebac2292585a448c508ab28c3ef710c0bff592306a9519457bac8395cbc4e283fb49f3bc203854eb70f430b513d4adcf328679444be0f052723eae4b21d62227ff2b2b70637c3a1631bb5efe225389450e83615e80b30768fb2f7af69c9df8e4ff82619df4e0551874f1d831fff75d65b34849a45a8066f2c70e65e5fd686d0d1e0fb24f7e1f46e52afd6cf4fe5388796916d8596908bff708eea8d5b5cc38ad7b8b938849fa8cdf80c399b4e2e8a92fb9d37127d7c894ba7c1b8acfadbd3eebb3359ee770cad81860f8c80fe12dce2ffdcf6a74e19fa8814f6445b7d484cbf9fd6c99206cd73ab7847b32bb445e868fce6690d82d6faa67bb4248096095c606be2e97834bf81dded680c679087a09f2440bdd1b6871038c5d11cb1f576c8cca4cd8f1056d2c6a75d53663e831ad3f0fd56e19785a02c4b6c9c5a2c7e47f63f5dd8b9e27a2efd1577911e1eb593be7cd00cdf6f66b86c62f3b0af73e1626873f7a196555f8ffe7b579e28e102ab7a2b7a01f4ccc8fa17c2ae2c2032e9977707a82c3fa770202fa51cbb1cdd6a61bb460234eccc6564c97f8b9c99a297a0cb11c2e0cf992581cbc3ca367de1d989bd9b0581c24dccd8273c4ab4d17b98279158315c5b98c4dc46505c1b7636272e5b511cec700804cab5856970dd082d88505a96040b3b9e2b5604af08a24f396b346a4373b79534386adb6849918c849c93759c2f0baedc536c424bbb73fb0213b7aabdf0ef5daee664fb128f464cb1a3070407529c9ada5db600602da1f3e4463024e5d9f4dd8b230d17836f396f9d284e7fd7b62d6c4f15d120d0c432136975bfbb3d725ff73332b6c025232f91138263128c449b80bb93688b03000adc4cb7c49ef9c83887f935e7aad69a865be661bc8014c677668de22ddc11e118ea208087288506ea4cdb79ac81adad0dc5e90a9712702ee21b644921b993482290a18394d4a68b121c80d67c8265aaa207c405a84321903ce04c0185a461818cdf0d545c342e262f000e310db372cefc91ca81c544a6dfe97e6e330115404cc15c8c5a79d20fcb92082f54b41248b03dace430adaa5db4a63afd137e96fa36a708d3a25c4278108feb12149aae4e1d6d3b83c9bc8520a674e28e9466245e96a8e978c20e6b70ea131a2d9bc72cd0624167f6e327c07088e6f970600353942d04e5e900e68188e22c87826ca90a004cdd11cfe77aaade78f0437a2581e5ce06ada8f1f856cc641260da932297a897d227a45e2df197cbf36736069a123daf0ada390147ec3e05d0450e18f60a25135ecc0e0762229ada44783011f631c70a314954d649dfb43078935990353f46a7c4b1a292ca66091e472559d40900b400fcbba936103d45ed127e5a4b0e4a86e439ce946a322fd60039f53f112a2aa237d0dbce6f520303cdc2deece9af680cef6ae833d51e746431d4112a5862c70d2ecc6538585b4fdd5710482cf064eba2d851fb33524799c630ad65bc2a58fe34501a1cc0b1f3ce4acc1d2350b83cdd37fed7388e9856bc51eff38b184a63a7a86912f03c1f469ca6b3686d7c859a4711b26c53732178d4bd33c1b0af00b6cae44c512a379de78f9bedf5ccdf6f7de13bd4cd410a223b17fc60c2b493584bb60dc5256ec0db29f35a67cedf7a8b5dbdbc20ea8e1feb00343445cceeff1e3de74511d297e254c721d6db15ea9b559f073703716bedfac4c0ff0bd4b489503ead95f5fcb38f32bf3123c2eb8c1ca66c3a1d0273fce540c5aa55ccd56d3924b7507b6272c53c738a7cb8d07b2e5b416f438cf33dc52d28a28b7f4b4491597ef08f0a6452f633562ac3f2566ce1b3cb30cc7c30b49b51cb311874e3ec4d014810900e59f2505adf1a74845b12448d55ce244ad90dde23af8010de4d380f631c5c0a12ee6bdc040e541ebd3a7302e328443206a68e8ff890e9748d765d918150dc9b80720a3d5d5181c6c9813a32d729a94fe23da705476721c82bf6137d411239a1e45bac56b2913729fd11d889425f0e8fc0349e316d9af8e27c8063e56bd9355cab1a967e7d35ed164d20815e160f4e06737a9426c9c65180036179cb3bbf9dcbc0a5bd1551bf0e70489c17f75b836a5ce8185810432fc3d20018588e9c4152fd92fb52badd36731dc5e4421409a868fd1ba78b4652fa698d0178eb9620d808a1166bd163861a7bc21b3518ced71090ac78a66fe83a3fb1ea028b8873c8ac88324b0c0e7d014bbf1ffa76a07973f2b436d32e5c02fa68ca41bc5737205039a08a9b82a185534db2a7e0713e0ac391bc60fccd8037b0455e42b09f1c0cc24b81cd2851ebe1ffa2e9585580018536973bd0904939b84d8be4633ec55ea91d6c300f8e88d5c43a9b3406616ee5142a7ad6eeb6327d0bd0e990924691154cf4f41115e2b290285d1c2c87ea03067bcf85da40c43b361614e0bf658a77a2d6d6f76b3c35ab403de32625f7158a56fd2bd999e5a6d348afe0e708c2dff4853160989cbc2e2e6e71a7146627489c0bbd8ba5a49a04714d475c57dab4b75639fef47d3fb3793b31731b556d55631825a9676354d7229bf8b0956d4302be892981a3c49ea9cd2358c336ec1914cebe9d8aaf7b0a313278a0c119af29fb8c6b1b13e48c9247cf9f8e33a72af8937e4002dc1e0fc8bda1686c9ef0df4c98d48561a16fc594c0fe96a1632a83e3990353565cb493fe244b97733383578ec29c6140a5a29d90ea298d76465a35d665a0edf86575e1d4fbc7cd81b3eb8a3276de2c74cab79e77caa2a67ac96a1c657299c0ad474ed8bd97e2166fabea63da8d7216e0418facedc31b00d4e1c12f03f19fbb64a5a47d68e7c9a36793033e2d5658567621923cdeda8e82a96d338d80df12a21c044037835df3e89829eaa62b1e299963b7a8b32d5756c0fe81822248a98ee2b6ff00ee37c2049182923bc11ee8099c2f4084c369944f02761276017c4c8bfcbdc00e41cf29bb2d4314701778f11dc501a4174849008642ec828021f21064e20a060201542aa4d199b018cffb1162d0fd9d7df57664ac4ce993dc4a5a632f2c382b54d742d551fc523bdc4942eac3ee11d5cbeec4e62bc9ea19fa8b3deaffc6f45a0524b5804c0cef3572e6cdb3b6b272876f908254a91d807dfd6de402fe3652bdf05f167a56d239eddec4103e96cdb3f0ff58f410d98bd54994761b00a65366027dcbfa82354ca68d7b3155d84f03850b518d228281d809b3d0fdc888a9e01e542351812c87a1ddb3d3c30ceb4aea3fc68f16ae177f96e2355dd6a90e63bbf3c7cc4c71f928e79cbaece482c7b1a3dba088c6447136e6cd0094a486d0c7995f97798713731ff8e533a95c59f8dbf30e9511143acc24c321f102db62972812ebd0e3d4e169803d58ec928356949371264ba5cf930a1c0654fd434cdc3b08ccd32401dad42e8be3f2d25e29afe6db0a7b4758d0f8db04cc2d9d2902b53493d3f4420a9968020799d9c4f365ce068674be976a40cb5495d3491bff6b5d63cae048612730b647b1cda157b5b918bb386f7eee8e0147c9212994d3ff5fe0bbb27fc47f60d2dfb1806c5f7d848dd2de04f3aa258dad904adf14e7c5243f95d99e0e71fec037d3c3ce93e42e019df0d11fec36099024bb5e6e99a58bba78a2cb3875e67f9dfd5a584642427fb7f8bad3c6e04c60812d3c33370cda202d1f8387492c0364d9711dd7f9b48e35c11cecd566ab075e16977c61a59932f5dde659f0e936174f8f168b11a4c49c05266db760077742c48d2090053e3f62f66dbde4f4630306e2f3f7aaf1ff80e488c0cd59f4b765618f6f716386befa2fed59e544b051ff41ad051ce735ddc388d976d63c75262857c309c1ae7de5b38990acbac671797f9acf9dc5c0402ed152d0868ce6258e47ecdcf48613201a43239dbd7577a5a1c922e70733f19a0774ed660c2f240b308d49d5bf3130224b045f0b9b15b76f50de02b7f293710149413ef06842cba063e11b819fd98b8a2633b68a98929bc4b14042bbd7297d5b5b4f0dd91599fb7191ae34368d48dcdee8c5a0fd070e5b2fe62e503d6af982fccab204dd55303399ba18279033dd3b42ae94da9c652eb1ea2c02a08f5795ecd664720863673b9b2d826b3999b1a62bfeb7fb8dd887fecb80947b81eaf3dee7cc8fae18e52e435e7a4414ab37ea6d2224dfebc9e021f3474c1260ab5e5684882fb4579702ec3b6c21722093fc9d5fd25d5ab9b19f3afdca76bff22bdc5e10dba1d5baf0f5ffb3e5f6f933b79e6d7247a48d424f475c4741cbb4a2ffe6dc63d2ff621c4745bd7bedf582916b1926c1ad718d7abddfa6f430745c2e14b30c84e544624639fd895c089357c1207259bb29216767fd1c8159ba800e7804271e7ddd73d1820f9d2006743cd5d7004d9e134f02dd795aaaba8c644652adf8034e992e2492f21674c0bcbf42808ec39316f15d8192c329009aa5cb0fa714d7facb269ba14b48d6097ac090ba5a42b4edc8e98a8946f52d3efc383ed6f3f1f99444e17f3f0e9fc14f10b7c3e159612eef4e26e1c1ae43f604a3d8a56db7ee6d825df827736234b8f58bc1efda0c223fad4f2f4b6e7e17454f5ec29ea5c2f82360ae9a90b8a84ca52d2784f901402e39efdb16592cc5d3bc1210a67a766b9e90a35dd9ce4fdd9672c37311cb11ad93720bee52f8ed2ee0e75a5a4cb79415949db800af8cf12eacd93745e488d97ab7e73632f4ac496b6333037f2af5dcf4230048e9335352b3899af4e043c3cf7a6ce6fd42487c4b28542e52e3745cd889b4ee469e8fff742e4a95d095d32e1a2c3dec0842a2170ebecd3ee1857e939dfbf060aee844996614bbbe797e69724380fef4a88d7db33bce6313687b0a4afebdd99632cb272fbb8fa2f7dc4789dddc931feec52d3905acc327ee1ebd923ec42c9b993570a296d745fc57a2847e798122bf7571fa8f93e55feaaa2c2feaa03e1c0eb0f4638346cc4ba6d54586bcc1507432b1ae5b6ef2af465ae67a818a579b0696bf5587b68425e3fe2e2aa79571e13230f7aae22e5f9788cdec566238b8a1d34bd0eb944d19a5c27798db4323a205b95f7c5d4b30a88a80dae9c41faa73dc8ed00cab213a19714b357e46a5e1a8a68212c571c1f06c7b67abb408b1a27a218b222fa0394aec1dfea9a46ac9c1da620d9279e987a8034f016597feb33a488ea3740bf742a360362cf48e3a4a7099abff2f823fd5f47ac2ffa2beb4652a74d4474765fd54c250687ad8af27fb25c5802aa1a4a476b5dec1672f1fec2e848ce6fa4168a8ad6c7eb5dda0c660fb89a2aea3fe4eb2f96ef733b4462a4702725bea99aead2c12b5506abd2087ada8b8011d95338ef70e442aa591a2df0cdd8c9791ed967d9e11ced114a09881015c296a3687f105158268a4efbece2606531d94a8dbb570c5916fb843bc900760b9ac89358a5f880719b6c9ca0e173848e0160b478b3416e32101861b496347db1a0a83efe4cb82b18d43de044a2b754e855c08aa32ad4172d4a2fbb61eaf1139ffcf22927375929ff872501c29fdeba94ab19df9f6c724152d9ad827d5c5b7c31bc8cc8ffb637a31829931870bccf96b693a4f77a782355429ed794553ab6593fe7c90d6c3d374ad9529796d90688391002fbc2ebd0e3c71ddd9b46aa60a41031e62a0e0b0472841e720f2470913dafb47b2d3ea801eb9ce37b424916e76b66d310b9e3ebed5b3cd6829a8d8f2ba6b01130bb9380b0ad6cc24c69764f7a0236a5a29061363f7a0f80f6e735ab6e2cb808554575ec75a399c5a5af304ac9dcbd766d102aec67c0c91aa71886a6fec28fea584a85eaccfa74c5163bae12317e5c3917dab300388d317a62f19344a68271cff1eb9dea473522b242f57ad9801dac894487130a4e42e8d7ac71daee543b32128c2a3ab15d8a910d2206f212d243e046087fdecf4fad8464241209ade57324da84cd4736b4404f5f633e6d6f64f17ff08d571c41fdd2c5d507af7d14b4cfce35671f06a946e79391c8c657c323a4ba87f3526d86045c9104973d1f68bdad04c55d72eb145b5d6a2ca6331776231730edf789aba01dce00e1c7d9a0efe8d70df73d3ed1722fa084167fec9f2519ed984f9824f218282f4ab8f3a56bc644b838c4f8daad5b1dc9e9bddd2df38f0cf9ae323128b37726c9d756ecac7fb2202a9fa005ed3585214ce1e0f81c34a3c5d798e128cdcf18b5a855890003983b1a28b202cf1ea6085ef644f32014763ba785504e3934b206d89874f0241d2c7816609733f6a7d1fa3a3e31e603efc0e0d4d6042015b5b9b187c9c4c9f0088145f44391b4ebfb8938069ef7a941888a0eca8b7e88384fcce02285034c60482f19f1cb83cb0329d0d7878f46fa4e2e503bb8c8a068e827c30eb075519bb351c7efd82aced6445b7c2721e10129f6c5c9cfd08b49b3c079c3b3850d4f857acec3b2a36529e290fa430f83a81b81faf8098c7ad1994d9ad4148684eaad2e7f4c5ba4a797161aa00d8c6ec636602a523d22575bd889e14bbaa7ee054c1d24e5d120fd74c654dca2af2f0a7a0b7cff930cbebedd7ce15b73b2b04fa22a0aca05f99939cd6ac2692988f1ee6cb55c57248f25863c03c91aafe9c901fde1ac77fa04037132f50a4e6b5576575b60c3d79c0b1525925139e10ad2e765fca00b86cf60d7d18dac9a32eee07c0120a18d7cc11fc4303a35619c445f3e071569aaf19abbe72efd06d62679d9662075100986421c400f5ab07ba19cb84d2c6fa8c4390d4eeae966f92301fdf4796f3b92a367ae4f552c39eb3253908109f1a719d521cd7d86a36d3a17bbca9783314b7e9153d17f56a963037e4bc4df8134a174ca23b656927ec35365732cd224bef20d6be81210b670f01d64e4f4be861586132ce318c827c36a8352fbc2557290269c9b59ba8c775d210517d2b01bf4e000d5e34522434359e70437b0f4cbbcf245d1fcf8cdfbc483766e2f628d36c3f1b7a4eb5f0a9cf56e819da11b6d078f5ada3e521caf4008cd2f57b3ee5ed2fc67ba0bd7f4a8367e63541ff47fb787c91b2b7c4d3a170fa5a3e06a2c09fa5f7a8afe40e0d6faaf1ddffbed5a01c8cfa7fca63e9c87fc9762d888aaf14119849f8b50a83bc4329251e0bcfae5513e959e331c7f0859f8db9d19ab77ab5876bdc3df415e0d0e8ced5662c0b934d561f0028b8171c354bf080028e1dbb520c59088f5ca6692d4a772e7b11f6f734a5dcae3b849b88c3faf14b45d4dfea00ec0076760a54f62e08cf4501f861e1aaa5a3f3f51cd1d26bc649fa367b110d962de054ad075efa4596a005c3c73c81c8600ac45e2b2db01e94eae0ae009e8d34f0492b6ef76e6c69ae4543a880896956e16f7f8486ddb0773ab9f76c4a23a23749987367373d2aad8736c8b7f16a5a987d0704fd042c4c363b2783e7294af5df9ca4de4a194538a4f8869bfad94d75ca9585364faf46a4c7d5c8d57b6d62df1bac60c68bac31dad82842475a3fda53b92394df24f320b7897575cc644cab8374150a41e33389be97eb63a8f9f068a04195e00cc0e3569e29c4cc300784456017154f0018b4708118c375119d569b97bed293941190e3a7779520791861c1e76354fe917ed3da0756701274dccca6084d7b1cb992fc3804afa691e9c7575af3989e9670221b102ee01428fb7c56c3db1e0c5789e05292a76fa31211517a7cae275391224a7c1407a16a6c3fb7dd7160145059e077172f647bf9d638af80b0105e6861b339b49d67b390bf02f62a8e227f8fc43a252cc30ac653b8f06c4c8c30f377a82624d40646a035d8e0762706a974b52502e2453348b9b1e9b14c47e806eefc92eb1f17a449ca26c47536852a0ffe7802e6f4260d448b19f2042875d7b740430c8d18e13102f5742c94af460fe3e569ebaf61a796128ad10dc8be6771413574144ff375e61e100268e5b56a0451b2c2d0c6d97567463fead046f8f33f73a7a5a6e5a6e7c417f3a95ba714bf107b44394f7f2286cf2fee2108d03569750e8908bc1c2463dc93041aff845dafa15c6704415a957c09f144f4a42b9a92132ec1bbb1bd56c9af2309ddb88392aaa58676f1e82d7b1c6edf76d34f9f3baa885212e64630e684866205c4742f32080d67404c21e8db212613d0e105958201d26eaa1f39a636406fa3d7d576e21af2d911a7eadd30782828c02f96582c17f7673d327e15540c2d12fd7f8a343d6270d69ebf6e725048f3b3922f70fe04fff7bb5fd30ee557dba173c294a8c6660846dec786d09083d43dff4b03988a90394482ec14da2d3d5fd4dcc4ca5ee5e97c079894f0794c5fb6e71d03109dddad7ea9d3b011e019aee97927bc4df490d096451423c3cf0968138946a9746eaab93fe36fc59c1d7445271c1af017ceed24b3c751cab88f0cee7d6423861a41b5f42313e10635648a05738022d34962cd094237c67da2033a33117cafa7136a7c992e897302db14acd4b40246f444e1b2605f091288581fda4ee85648c5959b59fffe4bbb4bff3862b376cafd2c2671ebd6ae607581ac800c12f5b6b19991dc8d00aee5f06fc141c37273d7cca7e0855b6086c435072b7f785bcdf20ee494e34df7a5c89e32e4fe930844cadad37c22726774ca3d12dc6afa70659425f4969ce95681c1bc633bb7136b4af7ea4702b7c80dd021b6d2450bff45c141064baabd4057464bb67004a65ff6927615eab43218b4acee8b5333a3c85c79e67a3c22c21a028ffae7a3e0e836e10425fb72aca4693dbe6e5d70e71d48a89e341a4748c64d81e3fb1d6d3c22ce1e5fec452806fa3876294d9011e2e4b3801375914e715b1015d0aed6094d6cb945a8bde1d71df0e9823ea1b78539da3f068a68044540c2168badd325cb21a7ffd67985054ed39b0f5b9ba418656dcb5123f9eff744947f274040e951838e2d0a147bb90fb7f07059949e6f1a5ad18b4fd98243ab07d3cfb3f0a4c08a43ebaf4be1b90abb464b530b1158c9884e9e1033977812fc3f0e39bd71644d1f8cf3fea1001f688f3e051dfe6988ddc8561fca07d09e84ca4b8cf863c9147041554d31682d13df034cf97246a10efbf13960cc7935a902e7c6ddb377b8ee7bd0ce74ee50f19c169facf28271c710374051d4b88d194b57280967a820c4ff651d00e775838a3020f9b45f3b54a14727eb0e74c590617665c9371a60ebcd5f3ce98f35a2c9632e2d0ea29a49f76795520f9cdf25d70764c69ac966d9c2abf85beffc6a8368069f0b10c2c8fa417eecfd06a1fd87d98f74952da8010efdc84f47dceb714410d420185903d71d4bbc8d361d540419e1968e091266b01aa104d842355068cbac81c30aced3d19b63f29367377c1d696ca8f7a41c30479f943a42a7e62284764991518ec7552c8271b3c3d042b4e7736337c864453f90e1170d29ef3e64203fa0448f68b991729d106ee50058730a32d4630a8a8798d74dc09a04275c84092de27bd1b2c64115771f198f159d4e41fdd9b9382804e5ca9b2878313325197be9cd8a84c41fc15b0e708378a2ce9081e3c0b9ce5619340c9e4051b23b862706ac845e82d9f3b3da4810a1b33288d56e2aa29cb3ce1a231240d33cd9e320e6ec04dc73d8d8f954caafd0a92b322ec212ce1b2b5fd9fb2e023f22b18375ed320ea93bacc624ea093970a15cca40e45a4b8bd35cf6abb0302fb882816f0d3ce550e52c75d4b197e6e17b47ec41a1b180d79d35dd2de02ed4a13d4cc69659adb45c4f208eb580cb00d5d85119779020700212ca921e9648ce8178e3a63eb2e678a34012358a994fc93aa2cb22de36552294ce89a88caac6215baec4fa059105c812800288f32d5441012ceda786560c3180cf32e65ec5ec2534b09b71991523670b14fb889ed489593f7bb52972a51b7fac39224011f03ee9436a944cf959c6c53b13dea8d1d1dcce834005f95bde898f5f22da7e11b0537214f4ed634f5bf31f1d3ed4164d277f8793a0e05b463edd63f582ee1f1436986719424ee35ffba6e30e161058765cc6d7fd442bc7ca6fa8a8b2fc008e473e8984c7bc2bb219aca23ced85710b038aa26f3922d7f8988b707b513d811976cc2bfa2f0ee4149f6a36a16385820b33cabb5c1133a6813f3eccd75b533c6060532cf5a09c27117107f5627e53ac55e2daad72945acd15be5804fcf24676844b08e690226eb8000ca226540c78a2c40169962d3417d81c98e0fbc8225abdf67b2ec2a255c37688fed611d7fcaae580ce0ea58c7cb228144ae510b6da068603162584edaee754f7de143f38fbe6c9ab759b320f1bb8c41a270cd0338e55fe8d0df327398004a363584206628d476d5b836a751a097120419649dffc4ab5cb506d35757d96835950ad74ce5201cfb1c6e9cf74c4a41e914d94db015394c9cb98e4dcae721a7ae8e6505612bab0317c2436315ab4bceede57d9042e8daffc82f7125660c461fb4241a36434da5de35618b0176ae0d6f8ac7ad3728157eac9eedb7128a95ca7a7652e5dfa1740c9ef180c82417db3b0f783d0996103327fd2b977318606aea870dc54695d0538e51a825a65c04b68f10ccd82356d48688053caa8e55a2c0593b650e07736e30ef8ca2e749380b22e5160d10b5abac45f99fdb30e74b0322bf63d4cc4ddcc37e2aee84dccb236a4176d4c6039dfd00c0c10b55d49d786e7eb617865d82d89e1c058f73fe488e77e633c2cdc2abd4e5e1e1e70e02cc2017883455ff999491b1abc6360aa51ff154a6b5a943294fa413da37401aa695077296115454f32b03360ee3f2ee80ee2f641e6771b748cec8b13c023597b2651f0782b6854f3cfd181167bdc34e111d1b099dc18ed8ccc2f2bccb75da9e781bc2b802f88175fe518233de0c938f126481dc33906724f7820e66bf87f1d4812cdae07ae41c7257211fe235b74c140d1813fff1121827e349e4fdaece5f5289cc80a8db2f3e49ddea4c2052f95c387737d598879219a6b85a1af17a66a8656db018c081c863cff50d996391746ee929ed5a72b145932f70b2a99fce1caa07afaf57d691fa0333da1c751dc74549613a1585981603d93658a82707667e5f0518210c89a95e47a9e9d272615f4412f7e3d9d4c68e005cfc6ff7c5ba3d51b0d5cc15e51db1bcbd3cad370690aab91deb3572554fea9e336e65a8112872babeb9a3de62df0a69287cf9ffbe063d339893cc584aa84b7c839b6ca17456e47d5538f4364f0a731f9a1efb3690699bb00a9adb25a3e5eac4de6505561c106158545608ebd88a9f9186eaa2380b2950d4dd8c03617098033ef6fc3c8410b7f64ada09cb59edb448a0930c690ac081c24fc057214834121a35b0722264f7a2a1c5f4453b46f4838a37f5442cd9876d8182d69c3db2842cb83911641539348f50d943086a1304eb4858316b67ab6310660d660f06acd071b1fd6ddde3ec8c9f1da29fd8c9107748d5c0eb2f7301b12ad70b68f452982db7112a069977942512b47400005703cb807c02921ada532bbaa254c82d5a755c89b0d50fea94428b1e751bf820640871213d8addd33428add0c08c254a33a60db57ea6113b2af936f5b881e0ef721f45528207df2e443e3638931c1939843917870bc3a786e514b571343fadfcc0686ed211a245db849c4758cbab2a11e3a060e0e6860f203ffef2836a35f897c50a13e4a074c64111810cd02e097d79ac33115a25ba63b9868434c421abeaee37da5e96feef23e9e1950f47c1a8c15e6c6417bc80651b6ea0272867817fa27434485c1c02c5b476abb61fbc5b834cfd61fe9c8c55a3f430174be51f26ce448fc5ac53e54cf919722c4b83efc07766e906a319e8b44eba5ceb4d2f451bfdd28b25076d271ce066576853c0a9c06138d1cbdf6487ad9852ecb6ef665be9684bed157c64e70233b11f8136c449faf419c2d01a4b22dd94463d7ff7f6909d7cbaffca5ef27809b2cfd1c12358c807b908387d0ab7743e5663aaa83295f34fa0bde3b114c1dbdcdce1acafd0a5afb01cb2706f0672b259ca2b5ce731e8483c13f9d511c587264ebbbe95e716b2cf570a1af43f8df86a8ee041a4c3a94074a13244ab028b414b87a8d7d682cbfedfb2b62de4f74f2b979dde5cea17724e1408dd770bbddf8ee637a0861ba280414b705d34387f81c80d347034b0263b568aea0f1fc072421c49ae2c76667daa7f6765a57ff4b8216f61fae5b30628715b75249df9384a11dfac34fafe88451192969030e22c839e27b103c96039ab371e4060f18e544969dea55c100604fbc57c7b56865e1f5c694b1579ea0709656740b66e142af80348c1a826839636509ce7acf97747e54343279a1395301be24bc98eaa01af4a5c76e03d1eb04b470b09b884405780010d5773982655732989a86f32ba130199c60038df1600544b21553d3359a1374f486a30698f7992bb459f70dca0d1052582907452ebccebc827b93f7fa6a9abed8338ab3da843bc2a4a0f5a1b906af6446f387b2d8f6b3572d3aa52ffded5a41530608a37b40a029d355ca58e727d3831e25eed86dbabf998b8088e2daee7c704d7f9241516f3c52ac0ac960cbc92b9537d9395757bb6520beb8a14b84615127bea95d1d846171c02b8537e86ac42df6eeb49d2ee56a6428f16f7435ea864d855ba9efb15f5119686222095e24928e048335da478206972e57e3cfc717bb0814a7a80211f01f830e5fae1dc40364e91c50ebc3df8eb1a0dd4bdd521986f753f7c71cc00e03cfb03a4c13a617fd2dd3e1f9ca85ca6aac844977af506aa49c5c86c13f47036b752f428f1aed0db0a175ec09acc90df7b57c974e79042f81aeb884a42554b6e205bf568319546c6241f1349adbd85172214a5a52b8ed5e4a8ec6cbaeb42f5950768809ed2070c526bd50b9cce91f524ca700c70a9893679711b55eba3f25504ae8e2df6d6102d8e8059a69dee8a50df408a958070d3c60115009576b07510cfe7eaa8c3f2db6a308301854de8753433a63c4b6804aedb119ebba9ad40017eb63c3545eaa045301b0d96bd29600024931d20ecde301265860c83bfaf6ebd8fc94f9cc6eaa9d30f8a2aa455121788e13408280d815a30721e2a941cf40fdaf68a81f3811e4afd22012307f180359f1abcd2a137f088c597d4c36458ae6d56340b6ff8f4f1ec6ccd55a64e1098284e5b3cf96e0a1a941764b44290d580dde8f46717a5e12d30408aae804d8a7dd3d21fb5d56c7d869b03a3c66a881fb5f94649415749dd2066164ddafefc0487c69041e9af42af8db0dd48aa488ed642a7d8a3a18efe9e40b6195f2625df4897016ddab8c7d1810d53ea19f3ebc3ebdd1683e40c647e2244a4bf6c754c190af5787b1bd8f10e209837d4bfa70fb493d73d50f976b6d4e994e6908303dd128f763d3cd6b2f978c4c7588369400394e62d086d506921c978d6070da0aeefab82adfc56cb42020444ef792570555800adedf8034629f6d1cc0b292bac4d395fdd86ac7d18d672def11e64f90c61414ba3ffa0dd85f0f682216f51826ccef1d7a23b33b90d70494ca9171f63a671f91d06b053847d313be3acee57256ac1989ca28a9c24876dfb5d03dd89d61f50d19e760906be138c0244404dd2d0c743943a892057da56480522626d536e8e747e17d74b74239bd2ef06d7ec9ed9cf453120cc856add7fddbf526ba5b92ebcbbb518e3810c440c3cb4808114b202e751ee69e4a9d36111c740600060e9dbbd4101730795359c06eaf4104a2f14dedc80dbbbefe5e8ffc55fb6aaa2a10905a1a4a47318230fccc5776c98dc678611a3febfa70dbfa97542c8853212248ff9cd226a8cdd2f566efc0987787ce4f6332ba3993bebc28502a1929fd63d8e3043e75ad78ed6f87a6115390b73507a3db74f6e12233f449db09d36275e9f94161bebb4714ae2326604f2d306a571eed2716596ccb3cbb22a6977583eb3f840934595ffc28b043ea617ad75e507b41d63b49dfc86c3aeafe746463bf3c9d8d0daca3e3361face57a610f8db0338c5618d6bb318c4921012090752e75eb778e78bf2978d49b23bb5c1f3acdf66d6d8f0452f9cbf3ab5db735a016a1112c7e24c08c261215dc8f982e636eeb907d87eafc02762a4375e824a1551cc6750077669a7594865e407be6532f5704dc44078b2e1166fa1d938a7ce671ac47d84d62c76b40e81f27e4098e5cdb757f6c40b88d63fab52815bc0c36dfed807ac516731df84287be6994be860fd5857340c61687b2cf699effbbc5390b549dc61b02f89d3a149abf6e41275f5446884057e42dc9906d2b720bb4e29e15616c6f96a1734650db832ba7d32e2442e31c227a2b44cbd3c5b4584ec905328ba8131b94d434bdbce317b519b40c2adf2adb8505e4ee184654988b04af4f9d1f5c497a648918d1b116415eba165e644ac32861e351f3f83cecbf11e2089602ea5081ae6d2f08c12e523752785107c86d9833cd9fb36d54eb1eac4ebbe7b168b8fce595bce67c0b5f2cc6917766bd0029e7f00c6a3c70db05c0091cc32bba1efcf3c62112905cf8aa16e5d42be08900f2b25bb436bc3e8b50173ab95d25fdfa0a5f71cd0fa8b3f1108b27114b2dd07d08a6ff871f71f2c17046323ba82a03e5fb17282c735924cc872d2fb0e601a164be3278b7afb262edff903a76018ae2845648016cafeb86db051cfa695ea5b5800dfaeb44081f38cff86a746a9b1aa80160a638e1dcedb9b2de9f226da8c24586b81a080ed9607a513b87ae79a9654aea54803058e72632180d54583a0e2aa1b0d89f9b042bf8e955d94307dad7582df39382f6842e29949085d9ddf6a4f24bffdbf9880d1635024f0d563647c20edfd58f82c92564723fbad8b4c1722598f677ce27a8b0633d1e176ca890d822574700b1797130cb0c42396f1641124d88d176c45f7f0d0aa1b0d116814fc9627aed5a9b35bb15575b10c3b3891f7d964060f8290f822b28ffb8c06bc5429e1bdb4a65be95fb12169709120049fcd533deebb12056dec2c65cfc2c80118440412cd19b34e6977401bebdfb3bc383ee68875a0125998153d903d4df5239a16a2b587bf75cf5dc6a35fd01cb804059f684290f752c2dcd23b8328098393223aa24e9b7380d24a9a3f0a879539e2b03dd3d843b5fb89b84ace681ed8232c96b116ddbbf10a212c55058fc535d95a71d9a6288cb1fa36eb08f82f2e67aecdcd43b84d2edf2b0c21cc347476c07585f54b355f0ccc369084f0a8cfe9f7c4d8132dd4f074150834cb5ac8e10d8cba4834eac89e59faf5150d41127f7f3da37dc4bb7500ab0fd38170e28eec8e04bd362e0872118571e25d15dc50fc819caae8c07d924e2d97697d31bd88d982e36405966b556f28afbf35a634e34746270b49f9b42e2e2bf0239d794da4e2acaa9b3f5b6df923588cc693ad176d697faab650df59814318c22ea355d085c7d80d2996d0c7ac8c697e6a8fc0e0a6115a58992180f92b294795ba9463e91bb8aec050f95649800290b6715f45ee7bdd5219093ef7c70d1c2d1f3172e54478d690aca5fbe38379235ee0422e2875dff6b3508ac1e2861227a6656d79377d0b2e04d78adfeacb6db92a5055de27975495ec76d18cdc74629c1eb68c0f7d73e1a9f1d65366c32323d1107a058ec54674ebac2208387d49284a8c28df0dce5d9d02a2e68bdb54beac72bbe7d734b38181af23d9baf923def6fd221ae8c7bd90cc023535fd2826281b83818ca820ed207f59efaac027f69b89a23fc9e59ed8bfbac35cce63366c627aacdcf1d585a651cbff32702a1d7baed804d469de068884071536b4c8a226a447552f90892b5f5c0b0d02bedaf6981508d10b863ed2671de523d0d43f626c5099f22f99488b243b17596306ec5e176a994dec97035550567bacec5cad2e476ceaf61c875632883f96e84d54c141f784d4ea3bd92648b8d872d8ff0df4f30642bb1263c5799b2aa2b94edb9161c22dcb23218a78d4b9403408c90e2f826344a0bf4119c035ffb9620e225ca096f4bbf69913f8a020ae9097463d3ee490197ac9235eb36b37062860f9f1c6696c4585475bafefd2a361ed608651f8cb1a518b80ddedfb9fcf38e80067077986bac05c65a22c0c91c27c6665bddf2626e0f2262e939797a6c5f0ce16b44b87c5381a29d4d8299bdfc53a80eb8899d7fe566a02e28bd04c326a058d50812dd9be4502b2c38705ac63d5186899a1aa4a7da75f59b5666e99b979cf05c393b3b34bb231b9316cc543351bb03d7ef8fa967be9bdf2ec72459a59ccaede60347def1f368649abf50e31cdec0e201e3f585783e4d92154a260506dbbd13655ba6efefb2b04388306ba2a83450cd54386f9a3ebad69e1998aef9e9288622d6bfe5359349c84b56293072cd82d0cf13349d4bd026bf7310b48dc4eace20dec3526d75929ef345d47b02d3c100e255a283fe99114ab7fd548ea5cf29944b5235b2db49e66165f7339daff8435001a37b3a74a5a32c75157b3941f422ebc7ad5571613388811cc2fb73b0c73fff362f7af6694b3c6ab493452f6a6fc41ca75403d1e9ad0c868f9ff5df4d336ad5c022e516532641349574a5d901d1c1c579209a730433e34c7f30c6b20b49430ad0576aa54dd3c8f6d2f19aebe7313ca1e2980df0400ddb036b0bf56b0929d116cb784fb1dff610363086f5b3dc93516013fc0e4fe3ee008e88e2806620045f97d635e8097c15f3dcddfb3fb7a4373380b3dd01d426cce51e97d0aee0481bea5d44a3957cd7a056004f2435ffe35477287ec72788d519087cca9b27ab7fc1b2a0a2f75ea56ee1c93ede0390a4a3d2250ce97856b71e4c636e21ab03784065fbc70d342ae25ae38676cda860acf5f6772e6900e88159f365c4c4eb9fd04820c1ebe2c40b7068b6c784b32026958b29f7717112f93be5fa7ed5791e53c1820bc4228110e8c72d4e102115c2460a993eab2eec994e0c6b986f858cef0399130a2d0c2e960d3dc855ebf4a57e4e673fc351a86e4f95e24a021a57b74e3d6836fb55dceaf40e8509a593fdf7e84e828d51769cb294ae7895e3a86e982a1a6ac5f46804a9290dffdcd9081f7c7e71e6b9a4580544e1d07964c0e29ba110c2748a0dbc861ec8531748ea0399ae9689d96bf57e853effc0d798c3e037e160ca816bfc251b2394da3300d54083ed58b57269ef6c7ae6224c26dc0bf0c5c56902d8ef8eb066ef2eb603bd219ee97f5586c872922595fe77d2dcb9510b84131a3400044057444e51898053a1bd84a854f09c42e7701174dfb5612ff1967385b55cf9e0682781d12452fe075b04cd1413dced7c52b60e597bb53c9071d149f7f198b3fac95970a106a5933f8cbd6416f6afde1aaf09fdf37d2e1de30d7332b3283d7e7d5ef2010c611c463e78738699355a98792f0a66fe3f3033aa73b9428fd4b9c9d2207acb8c4f4f5ae04bf768b00e7cf65b4f1b29b9cc53f8839747db9cfdb48fa9526d38d57f10f4589e05f832076ba5e941c03bafa431e94a33d05281cc9626444723a1933ec87a3582a984499e1c01a79745d7adcf61cea84a45eedee0cac958300f361cfc83ffb939b92e63b7020f1babacf2e1399c4436c46fd1059e59aad7b458ba4f89f6b9213fd38db6cb81ee9b2ce5bcca898ddb9a5e2f20027fcc3bdfc073af86223bf641c9afbb3f85cf9bc5d7416df2e92c9f39481b8a62b35e0253bda1186836ff162b58621d934836ad1ee9deba36857e1a83f41ef010a109ab5c9851fb316e8d15fb795600b946e9bb4fe5cb0446e9dbac277f2292e883a446fb4b393a11b019c1ae1ac9fb4789f61b18b15ed27d8873364c4ee8553286261344da980d2295b7a8bbf4db7b89238e2631c333324ac37d5b2f1d831a96a7f141ae3bbba84bb32d337b31a6f98566492cb12e84cac3810651e80725a7a5484b46fbc074255f6110ec6e349a0222556761f6291d1913a175e80b76c8be6c55918ba6ba9f67b466c6e0ce98644fc645f6da538a6230cdfc1975778c46a1488adc089821e5f9bac427225663e33fbde91032607355976876375ca4a98f56d1d9ef977619b18e45aba296b9ad9d431eea856071a3874933aabb39baa53ecb6507c4a6d87e5ae4b05ad33d983b15ad95a2d38db1f5036c2c0c1a786fe15ea6dd02bcf69caf65b9385355f72f73823e710334f47db116665fee051937ad19b836b36b843f5e44e4c4350c0eb6618627f20da3c1066be231c18618147e32ec139ed04765fe14efd99f9d519a11fb61c83a1a5d4a2a105176201eb10a1dea7826837c42df0df059a973778b694ecef96ff10e4918f0428ecd81e109f0099230ba0671b25d8caa1dffad38115790d167e64c1849bbb2c6c5556230af1acfcd5d3ede0ca90d3d0ccf33ac5d65b2d59f137962c189cc7ebe511f50c938f536273cd40b816ec22f639bf02ed9f1bf419b2250875966463998f86bf8546f2e096fe50b744da19bbcf1a5ae371c4ce889f2650a740e53bbaf1fa9296804927b93c70f1d182a8ecd4f9665287ae87b5945ffa5e62e52ad7812feaa9c29046a856203c429b1e4eb51ed53fb03d82e311209426d194593b68c3adf0bc535ad59ec3991fa33b00d6d4fd7c151e68ef40aeccb78fd9fd122c39124bde40e94b2028e16eb2ed3e44ab17670741bc5541316ed264f847cf221103607b2f1678d6d0227f747e4e8668f8ba34500cecc66337571cedb40c1324ab4951fe15b71ce7356bd3911022741e2446ec3037ab0630e97288e1561e2f71705c8fda167cccb044f4eab61afe1c6acf700d657bccc7017543837f4516343e9e71a5e862bebdadda9a2edb13ac572c3894bd3d75ee565829f9baa76aa7891aaf1a40b7163a97e07bd302209f98f95b5628a2f45113c1dfb781b4769be61dc0582c8d09e4e446dce2bfce992404923bcda111c42e64c21a20f856fe8200f93782f6aff18183dcc1a0dc1cf16b7180ce1504e8b72cb68d90f0d4ee3b6b9bb99f0cf92b7f9ecda7e0e94c6845ba7f08e5c328f91ae7614076b8bd6d9da48ef16f9a29d5c34a0b4f2a82d2d92e8907dcc0ffc97a19456e2e2413e794a53a0100bcd11cca2087c32236746fb3716f0a9c62b33796416720064833a0cb62fe92d62ca463fd5ec128234b37e9e518a6a3c9fa3b96d0d88fd3015be877ae4168871932f558c52c932a610cc03b6683c95d49605d2ebf2d75d4289d0e88955133c34b505ef7294bf293a0c171f8cd5f5930c0051bfb62284557d06f04e4364f368d189b1bf6aeb04f00ea599791389e3332daf6a701a358d2422f9ea68468068b0476085094f98464bc305f0ae6f44f3d2adf0f4b4a8912ed59932b10ccc8cff76c7d11049a6fd1ccc0e28f76f5b861fae068041dc0fc8f16a14e7f02e63b5cfe61c622ad2a7092de1fb57295056ddd9e5c0991d0629c9894bdd30c1ab1a0e12b2e661d25ed5d981498cb37eb2768394f39a492c4ba41434ae1f660e9e20005dab853310707622b0c019ffd0a4e28201b8769117f95cb0acb209514d7ff9bdc2477fcfd1b8ee140b908982c6936b0bc49835d177b24e6f80aa40946cc69b85cb61c1fab107776a2825b8d3a2b47a91ecf32d51e2f2c247cbc852b681af9cebe6e3ddbacf4ae40fd80794a810f8361399b81a1d8be9b5a615196930ebbfaf09d16b91dac2baa8ad96564fb305cc434d966545a4bc6e8782253cddccfde64bec9b503320539905d555b30e09bed0576dec47bd8a54e0a9d63acd2556adbe217eb1d7efd03a615decac709bbc4bd5e4bccb6b3ed5e8a42d9d08844c3c647f95bdd75dc7370e7c4806dc4864588a7b446b456dfac8d92511b1082553e8f2c3457030aea4424429e5686ad1606f6e119884ddd684ccd05fa913602224155d2bd2642e51caf24bfe2c2254bab7bf56c324f835adf74ba4c7715e1b3e88a949db7b28e335961a76402fcddad420538d538415f50eed8251ab0a7f0a884b535605452be2cca302c6042a24950f7433f69553d2a860757aae2eb178865dbde4ddb1dd11e757cb2c39c81ac1d76b2c94c7004768786a8c5c94ec273e4d51ffd226c659a967c2a05da5d01214079feb612673062507ee4ca0a6577ad24c98252850d9c024ec17264601305ceae759132f9c7eaca1c172806379adcee3e8a3e3313126eded019564711c9e7c84f27f853d506964992f96a3e5a817831a8dae5e15f6d52b7747ab574376f2bb2e0acd8fe01fe2e1c2ffe7c08c1d677552a1fd96b2cdb111f3d0dce3465938d25079de769c39c642c0ee805eaea7306fe96423d02fa9566e3fd4090a6e5a4a054a1bf400bf7543cc5c001f5a7e6017c64d90d112afe7b26e5ef7625cbbfa5b8269da9f6ab20044cf771709e11d5c2603329380de4d5b5009af874573cb3dec4d00bb34264881e1404240190b17c84ad5d67c6e4081426270beadfc6a80ac8e0e25d49c5c7b11c14d4f8d8aeb1c4e9ec29a1d8f68591c716af9cb803bb5bffed4615bb1b306ad3fa31db16f7da7da8444a70409203c92168270fd23c018f1a40877ac1b44744c8370a116406a02571919b8faed40100d628c19c55661d5f4869c7a24ca0d87e2a7ac55cc52c4fc7c40ec9b1ba40137b9d71589479dac73dbac12a04d29fb1e1960a37937c2871502491079ee4ee98a375b6ec9740ff6f3ee9257060ccaf5ede7bb1fbadc6a34634caf92331bc895ea24b069074aeb8b94642fb9979db6ada8f76198668d43ea5828008cc59fa8f30eb37bba08b922556ab9c2c024359c2dc6ec19678b643a5a8c4ff4700562a18b15a1553b63a40c7014ebf125341100a453ea14685cfd218df9d4791de3fb8ece79fd78a362c529104088e8a5951ae1fba028ef7295696f20aca994c5514b90f3f94c9414dc42a36d1bfd028394d2545d80fcb540d99a1fef7fa349eb516fcb2d96dc25f21e1c16bc424beb1245d33d0229db7ee814939a6a4065ded5fa483e913ecfec27c14474b88813d1cf5b06a486a49dff2f41052f1f5903b2eb406c6615985cd659d2b3b3abfbe0442f7dd3c33c0b903f3cfe6839d9a9076886ce568cf089696d301baf18c17a65509e72758047fc4eeb7cc1e4db1f10538e362b4f5a25ad9ee2e25780a438ffebcc33d54186190a0d039135013f30c9a8e6a943f4842d7f0fe101103a68fb8906f6f9ee26504849ef3a60ab7bdc7efd3f9dbf63fa0a8043dc03603165bbf3a227136a48c8f4f7a978a6c05b5e6a890ac0564d43055e22d5eb132a00986a76f83e9928578f072f6bb3aba3a7905f2eb9cd5bfc725ec114e69e475d5127d22f73b619a3880906de89cb87451dd7272025e4250582bc079b97ef02989e06d973b6ac7b8eff4f3d8f765ea5e317260e6d5b12946ee326e1dbf6b2a2d0de9a4dde0f390a35f198302d5d963a7127b83d532233ee021aded82ae303fefd871b146ad45eb63945a80805b555154e7c4088eb545ba5aca314514eb9f3cf384fa85acc8cf27dd7bf87f337e6ec2d70d3a5d976586828e40de7f614db195d4a29dbd536f38d548121715f4c1d6b75e49b45b912d96606240b0922ca63e80ddb1d599718c46fd7e6df5d9a3c7382e722bc3b046a316b6d14a314818eb2288f32dc50e1a1179791afb50f2437d6d9a4bf932e2911d6f3ddb0a7e024b000968c44c8738f8eaf37ad7f9bff93886ff317b6828e2c1c81288f8f4ec0b986c34c8b63071403c7f72a2f56aebfb27a0c4492d6107e91185c3037812e72fa776b2d296fe619b06488e3eb880d2f574a7799c1aa7186a1398ce4c518f0c2a000b37eb3122e4c6d220d61adf2badbee3669359daefc311313a9c8925339db6b62335b80fcc53c01871159099e11578562548b38e1e4cf75cbf874f64af01e9f5e60c0b4fe5602701b289a5ef8a518fb71167c28de281fce9ebe7d200b8bca7a0dbcea9138380e550a7fd40132c329351c733c3c6f21066ed43d19dc3fc2ab8ee6e986cfdc2d5c6bb234d81cde22f1ca6f674c32cab2b72a232aa05ece2419f4c6009f04c533b6d74f7a3bf60e2d4ae802b935edabeca00b5c453c0054815470ea1f69a5b7b224aa40d27ef88dc575856d175f96e5306e6fb5ccf3eb953ac1fbbe994ff4ecce3ce7448fc29980749691f8006eadbf80c115e4f3524011f3e88deb867d1b33381980f8af90f551e21b8758addd274dbb4ce4c0724dde52fbb86460f927501b3ab11db79f5e7362ebb0d896ff9a1ca423c6ede30a61408cf93021c289363220c090716780f704b03778443cb2f69d55acdf17ef998b6f849693713cd2d66f51592e230bf246d06565745c46cc58802dd3583d3128487c25b3fdbd221a25d01438fa89648955106366bec4c254e7402cd9ccb19a19b1a70a3b5813c795c1abfd5efab3f759af6d2ea2cdc3255b0019376f99c1903a0d6c94ce6f652a31c061cbe638fcca6b1aaba07d1ebef760970fbadfb6504a30b62689fc5802747e3b7c677b455eb50901599c5592d584268358cb31e019f8e28ff6f247b1fdb4a18d5112f76401b3158022cab1494cb79fc3bc89147191dec29955785a68ada6026821507328e4e38ae85a1355141cd79e118d1713fd9686ac1e67ba3173176b4c70878bdd4d62883f48e0d4c7442dca3a3f4c5f453b8f8615df3b99ebe285892a4909242f25da0b1a968ea134df08ce5255b70db6ea1aea001140ea6e28a59d53a5a6122f539744d361456417dbd74b6686dd93f1546bca8e16f691d34506b802115bc3b22c4d71b4bdaae629aad25561e7746c3cd11d8938d9ccc29accccda95120338026598919ec4487eb6d5ee3521fa419478dea4ff62025f2389faed52c0b7bb46cc09a4e6cf480b6ac1fa7a10c46b744aab6508ba7cc8c1a60701125060252e8b5ee602b6b8e156d506321442ec2ae029b57f881a6388561a9ebc064f1fcb6b0acabab4e6df5572c7243bed6727c093d36442fd69c07fb9fc8348975e8eed7a48c29e56333ec05a7f86e067df175922ec4bb365971ef362233f981721fdcb1880f3dad821671bd5aba306d8d33378a77eede2fbf6015a01172430e16e3633acc9cf0decde5e430454d6161a24235f1cf42f0857aba0aba4f363a9af85c3dcdeb067d88716562b03ec4d77bb16872307fbfa12f37585492262a0188751dc6b8930373184a03f6a5e39602f8538c7bc0464f6928a47bd69608475ed8a802c62edc70ea50f6bda90543903c5f5ca389a5fe91451a010dd45e7d11c873f86c4b94fbe5af2414c95eff960c09d1ba3ce4c1edf1ada8ccd8d500ad91c617758d3f85474b3bdeb9ac2a780d0ccacf7099e84b26618760a7f122ddf5883b0e106c9a05f136833d9fc12e6dc3201d206107b09c254fa7a4f7b8d55a48b288ff8150034a3f63e2095f9465b939d803ec66a44f938d4b56abda57f5bab7f07fd653f56c1bf0cda4cdc2cf6bdaf12e508fc33d920c317ea860857a3a08f364f94fce0e007bac44942383d97ef219c92596013e7ea857f35674db1e6b124f5f1d5cd2a399217a4b37d3e93d4e56b318e10bd14a0d9435797d25331b180be34e5003ca666d1c892d119dc8b00c2394b8470ff79b04f1c36ce2db3b975fdc880c7d9095d810e9880260e58225e443ecdef7e11d93ff1f265de55717c82920cca981ab0e55fa2434b46031d7df7f2b5db934a7ee3d847074bdd6f59b111ccb8970e0de8ddd82859a29df511d12107feee38763bcc25931f669d91e16d02eb4a7e61f4222a85a21b8cbf3764be7a55e6dff78da96fe692489a3180191c5f27f54ece1f5c3f998fef1c5ef9cdf499755ad7d972f11518b421498a892d3d0f02a4fd645764f32caa501898dd26f09c90dff2217cbca54572b41e9f422dde1ef6a2eccacdaefb7decc4e2bd3f4697de3ccde2488299b250be9662c6d7c0baf8eecdc01453ef1ce916f5218b7abbfa400ad1e38b1b34ba54d8659f100d62ea368fc5f92cf5b4128c432b50504d406d760105ff483d7e1f7a06d01430e5b552a98f464e60d4d133edfbf5a981c52bf565163ff81b10207c3ee85cc6d3afcfcfb71878cc1c4c203843744a146cd937f882ff79d6fd9ddc8464a5605b03590fa51deab21749d9decce17cc20600d85b9d02a0e5b0004389b96905b3f2597a1bba506a91936d57b474168a8080fccfd24f145fec3f1ff221ebcda7d5fe38eaea33794f95b265cf7d26d365dd95a7b2dd272c1ea7ab3149a6a0f068f771f5ad845339fdd78ace24f6da42a60afa12865883a7918f93b5b695beef9900b83d03f2a0460f50ef397b3294706190770f8cd840c61d8a89742d58d1cd1879c96821cadc6a065e7ee5cc45e32c9de62181e4737bc99dabceed8e052994c66d9b08f974e6193e9d08d8babcfa040c74a4d58a817f86ea11f3f9288fa91be3c8cfd847b42f74d2e5cb2908b072682404812cd622ec6dc8c1dc5befdd404ede25d1eff0df141870e471401b56f06964da8bcb5c25ff00a8290fd64c9f3aa4250d6dc430b47770c673f6ddfc1b4ec52847b088870222947568bbe9fdf49c99214c1847a0840897df9853593da95a6e859195e743c251b83873d5fb860a7c5a9830b54010513b8a47c83d18755fa02d13883ab14b60b5c5576c2d9dc751b3bd3f4670fd2123983c624e2b97cb850c4b56c85c68379edc2776efdb682a3e50574765b45d5165e8a7090289afb772d48771a1d35a60df739ed4e4871b99ffe95e22bc3fb271ef831a8d183fed3f9398d8ab926798c48876308d878ff704f4b2daf08392bfd99a3938723cfe78f05e8ee3ed694992c539bd24f826766eaf15ae1f72f3545e7eea45767a64a506bde436f536337754389336d91f8003fceec451870824211631577fdfab7239f5221f4f959e95ca8db3bea0031bcfb2b9b69bb0acf89adb5ae3e85efa84f5caa7e84a5af22f49850582b621e8954042524623f61af2c20662dadae729398fe710487fc586d2a2ca1e3151b1a233df3841a90f69b133f7c1529957774fdf505ca804f202582613b1cb3341dfda9c3ea3eec5b067cf1329f4834592a217a779eb28a4a9c773c71716ecd8917a76fa0d760bd4a838fa62dd0b2876a2757f447622848c18871bd94d6b0eb7d0c4fef3b7a452f8b1b46516248be8ed619e67c87f1166ffd8ca8f40c179808b2a86fd628877b4a8e4f41cd05d9e0b0d35c4659b21cc7560dc12511c507ab4589900b07d7b5e3f6e27d428773bd44a21d400b1170391b552900dc4ef76ca0b21a470eca1188438cffb6794b638675b3021099dda521538030a4a4647315f82c1c901ef6ea60a897d6ecdd144fefe0c959a8e41f578305eaf2aae00211dfc4ea1e8700484c71f6a25cce80ab3a841a9ff4c5dfc334e1cce5cf35709107252a4990c2367b654fb89612989684c5902066819f49585a9148b052116c43e9ad76e268a98c8de63ee9a714d8f3a256a4d426e620abc4e03f86f934f7d82e59a1947754685bf18be0d43ccdfc6a5f5d28d82c6f65be024a66107d6054ff1bde0246a1562ba3c94eb9987c86c894c0c02a45361216f810e1a3b7c98cb163ed352c44c439b7950f53759bd33e492e609895ae025d214d141b3a2230a78623ec1b023ad7b77bc62bb86fb9dbbe02448710dd0f746515cb6be570be8f2996f64db26d6992da5796fe8894ace0b3410b8bfe80479269f7240bb9b788d6441c08628b7c7887ba9def329eb24a090784b89cf4b0b706e126a699bbea6fca52d0522e0f7814c886882783636fc8085372407700e3658d64c0412b7697688c2a0e73c8991847d9aa08c8e68644e4880137e8027dd3b8a1e1eff41cc77c1f3a813aba7f0277b639c6f5fd278b1f58c1615792db173c17c1428e6f132d8c34c59efa520235ca3f9788254ba977a0d19582a9d6535a4a8356d711e1c3ea004f68ca72adfee186d70daa8e6ca144753b52acce2f1f270010e99539f1523fea8793c7e83c4aeb1c187ed5cacaa0ef3139d975fce5c94b85dcd16e5ac641ff0d8ff28475db2c3253b47053eaf0c1d4d03cd96ec4496301dccbf99ec338da2fc81b17f40571c304df64510ea8de0644f04291420acba3250ce93a35ffc2c21c519c3c0ee0d4b01ae80d2d5ad3e39e509710775b26c2b41e5c248381fbb05a1573a0b2be999a52a5d5ad2e6f33f0e387fdd894172ce846deec97bf6ba2ed6eb8244f6229f7b96004effdb412fad5b91d6fd87fda4cb82444fe260d58f98d3357495ed8cdd090c7ccaf04f63dc73d38e38323efc5474d2213b7a0a44497da5800946d58d6da3e2803ba048aa73e93760c262c33a8b23a4224a9ec11288efb1b01e07dc32d7a0d73365e90141b86eaeaecb9be083eb45e648e003026c5ad3d54bae96b01851aaf565a370b6a0b69e5aaf7424d7d6206d36abbb22ee40430ae08a1c9e33e0ca599709b6a3b7cc1aa4898c3bca704f012c01046a3dc3a7582018564d07f173b09be9d6c02f57728dc798bc69fb187b6732d3649d861e3542dfc7bb257b4f67d770ff80015c20969817efd16fe5a43159eb9bb12cf5126f7252b3c16bcf5ec447f58a4f1d4d76db7bef2de59632252903360a650ad909a76b326191cadceefefea04eba747447a61acb8ca1dfe1bc728677be8b9a37a190e95759339fcc183a9f4e9bfbbf9b79badf7f45995b0b95f829e5f264d68432863e9530f4c7ce557c1f61601f676aa67cd2d4a4dfb9673afdc53777378b0947d67ec41a4ba6ad7df77744c9b7a43d89ac1744793aad9abd1bd779df08a44199e68e54c34649e5060ed34a0e1d2c2d3b7874a14769a84f991e27af430de04d4d562dd368b3746f5559e34333a63a6cc6780b366bbc1fd89d1e2b47852361ea733a43c818efc75341aeeffd589885d9278dea0183f703083d1fafc74bf54b4de120d65d02a34020001e046178b083c16030d0e5c16e36035f78b06bb55a20283ed80d0d81e183dd0a0441f01fec8080401e0f72b3d96c06ee78b0dbd9015b1ee46030180c6479902b2a02753cc8b55aad1698e3416e08e486c0950739d920089a1ee48080401c0f6eb3d96c06de7890dbd901551edc6030180c2c3db8151581361edc5aad560bacf1e0363463ea10487a705b812b109c0f821b1078613018ac08bc45207ef079e899edc1df41d274ad560b7c245d87c02f226beed00a5c812f7b05de15f83de80f0281337006ce40f0b90b048276068277070461f8868000f0523018b0804117d80c0683bd3012bbd650d7ea5a5d6b28d7fff0fb6ed50175ab6ed501e5fa3c78783b66ddce6c36eb7672fd1d2d1d0bac08068315e5fa2d3ab81c5c6b886bb1ac6c266ec501712b6ec5ad38a05c5f078e7b639b713be036e3b6d98cdbc9f573a8d812ac6883711b0c5694ebafd8d06a6cadadb5b5b6d63694eb9b4858c0358fb6c9b6da80b6d5b6da561b50067f9a40101447192404560483c18a727d1c76bfe1e8ba4e1c7ffc680db55aada1cedf0dd35d5da0bbbaabbbba40b9beab509bbd656133a67e90c7f27c3c9587e30539cacbb1309e57de715927e4fa3eb4c0e39dddd9944609e0a94fa32c8c2ea14001f89132c9a3d38f9e2e216b6c91cbe8298fa479e1474f538db22c1655b1a80e8baea6f4cc9b216baccb75461e894f1a655550a214c17a26e442d6581f9f260c491a1ead4669b15850cc3562f9d17b14b2c6e2b80ff2e8fd47d2ecf8d1fb4ea33497cb795ceeb3248f5a7ef4ce0259a34181e22ec8a3f71c49a343d6288dc59ab13cc57255949e315941d668424261c4244d8e268dd254434f462b57c81acdc7070b21498383d5a81a8bfdc45aa36f9f9e29fde8bb0959a3e1cc983afa1e7de334aaba5c9de3ea9d910a1ab2a6428192c614496383a85195c58ab164acd9939ea9d185aca942424f80491a12934655954aa8c908fcd1cf1fc89aea3363aa4f10f2e82790a4c13f8ac5664f8c35e26090473f8f903515c787465197bfd4774d8122258f1e04b28642993a92a6fbd1f3d033f347bf83a4f118261a3d92465196bfd417d2228fbe88aca14233a6be14c24154a3efd128aa3ad233de8f9e88a4b93ffa53cfd81f8d01c8a3c7389e619035d4c745d2d01ffd6d94c7fca5fe68843363ea8f7ef438be21a3a06c61b62800a2850140b43018440b73118b72fd177c8881c1b72c9765bd6559962bd7b7218e42abb23e56f5566555d627d7afc1e36389599c184b2c6671727dd20eafc505c5c5e27241c9f5b18ecea4b1843496496369acfa600e6e4553693e9acaa4a93495e693eb8f706ca59886132bc5be58fdefc655714119b94aaecf0525d7f76cd81a95558546228bc512caf53b920656954f15ab8ac395a3b18a23d2188dd1188ee74e0c4cf3689b50171497cb0525d79f9b38fec8f5074b88c562d5f71bfa7bd7fda4f2a12a9f5cff86f46dca5696007801f88abc70a1961b07b13469e512e613b18f28d8f327a9542a05a44fa3b014545fc60b7231c89f389143b1b3bb63677666677767c54ea19e71354a00b864f2c249d4a7fa3dc209a55fea77eed9f798a3eecc29ceace9a6cc986ac238966b3725d7c7c9f56948df862c1ececc519eaa5fa6cc1a2f081953bff6e43abb33efce721542c2d41fbb2ee4fa9c978a82e97b41f74ae9fdfce49aaf6dd23323b643f6e5212e35eae56bfd77e9acc785357b6b68d678413366e5282fe52ff5316ef95076cf57eef96a95eb8f5ebe7379d2be432b4fda634775f245fbfa5ed0ac2db96ada8f9d472f28d7e73e1b3e772873bfe67938d7495f7e53a433e0fe996b0f20fcd1327dc2383f018f4ebcfcfdeef67479ebc89f9b437daa2f8070c2faa57e0f592934f5cbbbc8649ae73765b2977254c974fa9acad545fff6885cba87223ad9012c877e5a597b1d46b4af341cef6f0bd07e1b671af9a6f1ddd4bf2198ade860a6620f609e528c6459238013ecdf239d2eeaea93f6429a004bc0a37d656d356be66bbfcd60b4af790409e31ab720fba2740b72d4d6b305699f235301cf9ecfe5dd208f5d0a88f2e79a50c0e3e7cada6f3dbe6d3d77ebd97af24846451794a7dcdee427ffcd337500e8497b11c0f63da976addb2cbd1d5d89b9755549b86403c70d1cd6237aa5ea743baa8aa56978807f533d5bdc415bf39b8707d694a37acb3bbe1ab4bc8957c2c8882f48397b64f91d0cde9434036800541d7f99bf5ab1f26cc1f07279410022f7f77ffbfa0db9dbc6fdb6f1d0b6991d5f6fdba1bda6f5f09ce6b37c7a7a011e2f4c0b0fd1070b8f1762643c3c3f47570093180003fcb81183abcc94502dd6134b24677a6249eb67c913ad1f5f5259354212ee8090b403601af0e768e6a3f17e8b570d118405bd7a068c6d2167c03040582c8c9718effccd3c22a534efb351d2445ce3d146d55455e51eb15649f09c90c0234d8287d5c39304ab876715e41beb113b2b55e89db79d23f2ec59d111a7ed646e3ecd1d02bc3bbd4e066f06211eed93477b86f6a9b3f12e8bd4fe7e27f30db9281c5e4f8027254db55f32bde7fde8e58e0bca1a1794c79a7afb3e6278d49efbb1a6aebfcc37c45e2ec44028ede873a1d7791488e7d1d06179ef6f9ba6699ae6afd5ab699aa6bda689e3f696da986f48a5dd677b80aeeb86f82b571c28eee3973f15284b39d6a0dc35617effcb4688fdc5891a8f432178a8f15d8db0b2c2569ecf8560585355f5023cd6968f2c3f2d84d1d1c21ef9ceb7e194ed779aa78502c81ed67a92011e2b509e9676aee228811c4a1b2d7cc9a4f0d6d03536cc2044bc1fbd6dfbc9daa74835c030c01806b5f707618eaa214a9278fbc158cf804161c819f024c120d00a0cd297f986387d04500f6fee640c00607079c1074c8f0188e1f3d8d1c22280975300aa92af9168d136b8e8030c1f60f8002377a09412664e70488ee17e1be86ce9f3d5cdc9836d98b023271374f28cc0f6e33a79fe9cb36e2a7f991f8bc96479ce394516a5de5377eaaaead419758de53d55dc52fe02b3051e7d8795fd7da767da79b61f2f42275d464f969dd2299330b4f31f57c1dc8b207294bf9ac834894c8fc83496a92cd3173b716bbd1cb579ea67b2cd6379d4883422c7af1165ff6ea84fb03ef9bf248cb7b2df7caea236b469446ee3c16c81476d28fb8f5baca936a4f9f464750a52d3acd5ac464b5d4740b328c7a0b4565a297d2728a52f3cc162a294564a29a5b9d64a2ba54a9ede80a788973195e0b1a38545478e15138e1b160b1b3548181c65f99f279fdb68183a78a4d96add2ee8640f00a8bb33f0e875b36708e827bf93a10d326f01edb5cd5880ff57eb7711ff4fd4514523d56b098988af44b54cbed0efefcf91ad807598e3fc29b64f27477fe2531c266182c023f5d1a1df871d07aa333a4cbac3437b24cdf77404fe68f45e38822391aa66e6be9b6dfb29b3aa4f74be90ee90ead01cff01ea17d5cf193cf251f829cc9ff48bf4b0737f363855e5f4cc266eed9e69741869aeb6efe9047edff155cf542cb6ac653ab0e88e539f964df166ceb383af57f41579c9ced3273a9ff489cee953fa44611286eae0efc3ccfdb4c5c4872069bcf07bcffb1a8e9fe889d4a74f1457569fe8bb48978c814767f964faf4a9cf48bb88d53372d634d5338e6a1dc817fa3eb842c06d85a9b5c8f451b26778329d53bce6e9991e097e43a637c9b4e44be8744da11994847cf9b96275d6575de43b6f92346781477f98a4b94fdfbb9034db53fffed189e6fd6efa67ff6f46fa7dd4e1a291535ed1a653d2ea3c3dc3893dfae42887f50bfd7b3136997efcbb7d7fdd46875d879daa58ea13b5b84fd444f34cfd302da07f7efbd73f42439fe69b98a0a59ef1a7d4ebef4127a5cb2ccd2642fb0e002ec023ce8f2969be7d53901589224280ac693fbec82019cb1fd8a14f9afc1ad297a10df5299dd53fb003119309e3232f29d794524aa9e72a8e40d06f0827eb3784137fd0e99ad4b8a79913257df92262e551c6b2f6f635bc83c9519a7b51d65ee3b80164c9451044f9fefcb64df4b49f01d39f79bc59a35226044a29a594babb53a71b2501f1cf071698524a29a5148949a518feddd04a3dfaf252d95ffc30fcff6f697916965f597993e95554be547a12e9f1f7bde7fdb6fdbd4fe9d7b7e149e9e25ebadb15fcd50565df5a6eb159c3e9e86cb1d98136e4cbd49127c5f11db9d2f4022b7568c7b5389d562b04a50d79c2215fe8e872031ef43ba224e7e941a1a8a7675ad99f63e2dfadfc3b9e9e999d8f3743cff4a3519690a8f993e4477a834ca1a03f68c08f94496886444d18921f69109916418f5880e542a23a75e447f7223b155c8c223f7a514b1412d52c223fba14d9a9f02c86fce8af47f58b861f3d06d997f01be41f7dc98a1524aa67427eec31729be1412080e50a89f29e203f36127273d15e1ce0c786a2827217901ffb89dc51b4143198d0902897f510b959d03120c08fcd4342d1717e91a715e61819a624e7d044c2bc620e21f7cf1f48140d82e1c7f9339f984de4990490cb8f3347fc710ef1c28f120db985dc0f821bff456ed9058f1fa51354ddbcc78180dc31e486c94d02619097bb173be0a7013f4860370c58c0841d31925240aa488a45846503ab06d610d68b8657025e36af97906d350b52d343d373801e171017ca35e38ac1f5c300052080cb6462563e5630ab20568fa001040920e825e85e8c4dac988b8ef8028f1c3a6ed4168f1a443688461714c78bb1a6e291c76ed56ac2cb15e4b29287096bd4278761e7ae85d3e1018bebe1563495639c0ab8d44c1686e2e84f3eecdc1276ee5682a2007bb95a2cdb6a0bc2f6b3b1b69e961671f49ddc7925ecdca9c836176caa2d359399ae0b0c22d86b65451cbb499e9d55c2ce1de9f614a1f5c36295661789ab735537a5a2228e8d936767d24b4a8c0846842dcb6261836ccbfe9048e23899e4d9f9b329cb845d591dab9aab0c2b431623fac4511675dec2ce5dfd51822ba8b5bd7c85dd4ae5a82e89aee544143d4fac9ac8fea326c3fd63b7ea21619afaf8063490817eda2393438bdf4f5312356118f891aa2ef023d5b1c08f74ca0f1cfa894475aa023f3a140afce85126d02ddf406ee81d2d896a96047ef4a008fce82e08740749d2fdbe2351fd7ac08fcee3801fdda701bdf22d0449e7904954cf6e7eec19037ef4d402ba6938d24d24ca7b8cfcd8430af8b19f1469956f22447e6c2c8424cd0d9644b9cb861ffba7861fbb35a44bdf47686894cb12f063e7d8fcd83bb949df4884740d2289a2ab197e9c31197e9c3204fc389f2409d24c248a06d5fc3885687e9c4d0ed0dff70d33c681f44f204933fafeb992281a43f564c5f0a371f041a22a017ee26403c8fc0802599303f8fd3cec2069b8981f654c12c13c12d9a3bf88ace1c04b901fb9bf874471ad233d73bf9fc8e9c700bc7b86a1df45d2685db3c38cf97ed337a47f36a0819f0cc8cc9ab9240799cce96060c22e306116104793ff8f59335938885bac02290aa42620029935d3e70620128840b32020069935b32749906df50071bc0e1047ecdf0021b366f22011c7f62bbb11c7cb00710134cc9ab93a225e97911e05f4141147933f9159337788b85c8eba3d36b86a700d993553870671b4b304b8ccc665d965d91fc9ac993942c4b1edcb5f6658c9b04280e89f64fa0719ca6e5933e6289b4acd18ff9a209aa0030401815d9438de1971c431883fc4d13598bfcc1a20668cbff6336b4a3063fc0da053001d02e8c88863c7882d1fe288fda78738b6a6fac0acf1a1db61d6f03063fc5bfe2fe2a967882a91e8224659326b6acb5b4bc2300cc330ecf0e58d18862e2fbe8b18861f86e14b0c670e5f43b5858428509e28610a1797269c0e8bd3e174381dd60bffffff1f8661f839be9bf0ff850fff85501c67feff2533ff929f275c412daa8330a4ac17c2ce62cc27168bf9ec68696969696969f9ffff6f59f96ebea525fcfff0c571e616b1a5a565e616aaa2397408ea4355f04f71b6a09ea0a0a01e1e2c2c2c2c2c2c2c2d2d2ddfd2c2f2f2a68585e5bfe5bf451c676661616181c2239c99054aec8b3c3f35934da1a5858847d879c78a8727c7cacacacacaca0a0b0bcbb3b0ace0f86e5856565a9ee55b58c471e695959595a099573cc8857c084f869a781158589c896c2593c9563a4c2693c96432adacacfcca8ae9c677b36232b1fccab3ac8826d3cc26e7f11e4fc25bfee32c57626545ec9ce3ba76aeebbaae6be7868a8a8a8a8a8a8ac9647a9349e5e58d494565e54dbf6212c799555454546637c299556653b6e0398e5386c954747b746ecfedb93d3a384aa552a9542aa9a8a8bc8a4aa9f4dda8944aa65779934aa9f4a55269a8340473228b116da1a2f2c21176be31cb99cd663935482412894422954aa52f95482f6f4a2492ca975ea5248e3393441289f453239c9914365043d1a4859a49f3a054ea252fd5eb655f536503638c31c6241289846b7c37248c4b4ffa12491c67c618631badd345346bd546904862e71a2c1c168b357146dff77ddff7618c1fe3efe50dfe3ed2e327e1effbeffb62337f33caa442e3cc29b3688281f1846253336553363553a0e7799ee779dff7fdf779f8bbf93c0ffff7f8f3bcf73c4f080c67f6a6906b5241047b4d2bbe6f068161e7110c08180c3685dbb66ddbb6cdf3bcf7bc0dfc6ebc6dfbdefbcf13c76d9b3d7389c96402cd259309cf9b3cda4f09b41fed47fb9975f7de7befddb6edb7ed8ebe9bed5eefb7f7b67ba7dc2966ccd5d4519d213b732a1f8a28a594527aeffd7be9f7dd5c4a29a534e4a2280a94265c2961881cd5adfc65ba49da5a6badb5523ad22c6f68ad5494b5fea83ffcd5f5643780949130b33b1d9e6c54b7f26ec9859b4206c8bbbc866b354a4e2fa690c76ed5df7d37b369ae2649d42991fd7d48c1fdddca51b26b9eeff293bd63657f69a7a099088fa7cce299dc6bbe9ebd40705096ddca9faefac56be4697e0d6790a7f95ccb5109902ff5fd7545d622cfafcfc39b5d33111ea97ba92c5f50928139674085ebe5052ce3dcb84f7e2f969e27615c7642bc6cc8e8410b5c361eea80f22d440f9e35924750be9e77bfefde3902c10f7b974442c30731100af8054804ea00e527794e4e0875b9171d7d43660d1b9e8da694eb1139569fba37284a98d95cb12a691b2ab1f91b60ae87f301e5ce98e3883c670e9e3c3f874e9eaf42459e2b41798e2a3af6a7cda882a392e332d89ff355529286c4e3862f447cf1a3b25d0cde7bad05ef1ddd7052a10b4b10d9d8b0a5089b860115b270d9742bde0da712b3590eef863d8a78f2b2b1a1b4e9747836d491e49a6065d3b178d7bbb6b3716f8d16cf864a6cbaee7380b411c22ab1e9386e2561fa418e27f77349c82d8b49474e4619a3e2e8e5c54ac2b872dc95a4a9332561547986765e81ebe1baee381f0e8081c7cab1dc65b81cf090de7ea17535430c6bef7408c578c7b6a39b4484e184958d0d75706103f6b810c99736ba5692caf59514c1e98f4048aeaf44874a5f864c9ffa8edf91fb77cc4047b97f047894fb473cb2929946ee704441109dcadf907e19f630d3a03ae8302243ee1f810cca52d4514486dc2f834c2377d4a3d35ea1d3a175b4be7fa7ddf00a78fefd6e738e078f7cc51e78642969be1a70ee61caf2e71e26912767cdec203aef3ef7dda7d551a50b08b7e7421b661a99db3e9f21cbcf48b561867cc51e66c8f73bec4dae9d8e48d0f9072d5f2bded4d74423b88b39674b8d7adac4384818ed863e69efa30c3c7a79d37e94441367aa66ce0650da732003b226c98cd15ed39e084877434981382a898c497bcd469e3f4a2664ede9b649a2bb7db76db4feac2f69bc4aa1932e3d276d97f72e07e90b2c67cd9d31fea71b1c75c589f3dabaefeee530de4c233804ae3f4e1c2b8e27faf55e531e3b4f2a678f8474157fa814f7ceddddddddddddddddddddbf47d249dab9201c9851ecb3b2fd66d19163c5f438666ebcca97dec6d7203d067f740449cf548a12df9bfedd4c27b2e35b7e8748436e1147d0f2fe2fec4e7ff2782fdc9e863b34edbff0fe28fc1e0c478f43f04921fe1a35be54fa1ba1cae3c0f12ba1a925ec0105a97bb18925e4f13a4296cf11eaf89530c777e1cc628803c58e27e26dc4cf41fa02ff6c1f054379f23f364ff8632f916d947eb1efe1cd189b4c1d653ce54e1ce7d85156c4f1945b42993df1bbef8187fadd7846bcf7f75a5ab2378fb08b665376842ee4ea17fb9203f2e52569a86cfb6a095b6eeeb0652c61eb087b16f64ae8a93ed937851eba2a7495d075fa6477fab4ea93f3380eddc747a12ff11f206f05f5c9be18ba50bf34991d652e69a09ef11f7fd09b439ffabb092025cc8f3c29a5007041eda6eddd9fe11ca2de4dedaefdd3adeea0ee281d45d2d4b7dfb22873480c59339dc8182992666e2161e64bc2d8f711061e7fbcdc7fdcf4c3fdf6f345d4deab656d9fdba4e06ebee66b164d2752ce2eacb5f62baddff5bbae90e4869a2f7fb13fbf50655a5f44b36cbf21b65ff66f1545dbb6d4278ba44ff3652599fa34bb1bd645aef5bb76bfba8a5da5c9fda5a35bcee8a4cba8016994c95fec5b6b6d9074a1f90197ac3f376bbc97fd72f4dde8a354d3b41c498b7aa63fecfefe40f3f73d80f9eb80745df7b7237a98ebe27bef03b9aebafdc5ed2f6e7f71fb8bfb55a2fa0bf962ffdedb7d37a3ae7bf0470f8ec46e76b7a148943d798ee34cb9b6a364fbdb8fa3dfb0389ebedfc41eea7ee4df4d27368c7beb11e934adeb36d70bb6e47e357426c3759c8907791ea5b3fee4b323eb12caf6ddfee9ffda6bbbbbbbbbbbbbbb35d7e8133791133b6e1bea53f7dcdbaf48ffbd186bdefbdff74423a7a98594e77a91cbbca16cdfc70c8f9a4ad3d18ec8f6b59caaa95ad24823dcfbf541856649d92fa2581640962f2226b92391784a5e54e2e993f5fe7a7fbdbf61fd2fa4afd9bc692f77d1a9cba5114fbc2fbf1f66f63495cb5c2661ac96a3d33395fa46df39ae5ff3ee3b00652873dfdc77f7f7bbeffa937adf7ddb7fadecfd3d0348c6a321f833a4dfc911977335cd83f449d6b2464d59cbfce8fe2b6be4d839cb77d3621077b9819b7fdbb778573e230e8a23f8da9bbe1bffad338001be222f99fa7082bb49bfba5b4ec3d68184b1df613f2163ecd7b081fa641f0cfb27ec1dcc182824cc926649185b69ed1c9f112a4ed514674e9f386ea5a34ac95cc6b1701ce73297712bdce8b99c29eb17fb404064764cb25c05e6feb3e18aee3fd0ecdf0398fd47df7d9fbcfe8ee861a617764d1dd4d40973cffe5e7b1ddf4d8b9af6deecd68c90a819e42ff65d307829019b44a3d168341a8d46a3d168341a99be21a389e3e254713f7382a6cee9df64c29815742fc653a73b6de2dcf88cb4278ea0f87da7813e66dfa51ee60f37d3f7c21ff013bb0dddf86eb8ef963446b8ef1f7520bd0f33d7787b310647de9742d78284b16f23f431648cfd1ae124853327bc8ec5f15e50f4fab91fb7e7bc59e333d2bf893fccfc7dd7853ea880592e9b35327b91cf7aa6be7dfb74d55df568a39ae52ff67fbc56c9a26cbfe4672a9c364e0fd13892866b9cc6691cfbcd7577c4f1dd78a2278edce3af48f79c0ed876a20e9f3873260e4ecfe8e81f01a54d8ab27d97bcd8f427ea72b9ba0278d38be84e9fac94a2cb0ae0321fc3b3e0453ea33a7487aefa648938caa7748ec5c9f6afbbffe644311851b6f6ddb3ff953532fb7b7286cef4903272a676e0f4795f73d7bceedd73239d26de18686ce65e6a3ce8f130985ab0caa7a9e48b7df99a1152ae7cf03a30d9002b316a30a0b2a987656440a2a6cc41d2dc5f592191e40f34f7f700fadfefa6fb7e1d5f0d57c45e9fa85792e1e179a8693a39aa9d7eb10f0464c98927dba794524a27a595d25c05bedf52595ab65f97344a767df54c0f336fdfc42484995420fb238f95656b94aeacb14ef1ba4f1cb51fef3bf187993771bcdf7df71e176a4cb49606f4136a3a12c6fe166a474818fb5ea8bd60c6d8a7a1b6d3a7559fac8b41441ca5f1f48b7dd77d61189116cbf6351ffb3bbe1a3a93a1923436dba733da44d2787694a6a2ae1963bf5db28e1f68f6be07307b7f8304f9207d9a9b2cdb8fbd4c2e2c8364ec370d7231b56095dc236d22db1fbfdc5f258a36215fec739246e3be9bed1bfdf72399bf2373f4ed63852c6739fbd4f5efda3eb0599f91ed3ff187495dd6a452b5d50114fb67137b890b911da6ce04ea1ea18ee5fc0cf9acf3bdf79b75e3fd157f98b97bf1aba1fbed3bd1f350cb5d38a4ffe6f4c9fea7d32ff6ff4d18bf6b3fd936eb3352c55e325fcb9130b60cacfdbd7d721b74e87efbfbe3c3cc9ed84b6ec8e2584b284fb6ef84cadbef9f96e1c65b98fe4f3c752aab5e2ede0b5f0d2deae089fda44ff67d98b9131bd627db43433da3e3fe268e807a91cbfac4eaf76e09b398decaf44bbf7dd941d8657a3dcc7ef7c3c39ab9d0e4284dd52ff6edc5a6f13953b6f3fb39ed3362dfc51f66be22ee93fd7cfbfd6dd664a3260114bef7effdeb0010ed5e691f4d708af60baa04fd42bd59e4c5088f96343ea58f171e5bd6efaf7befcf70a869e76c657a3abf452fa77ef909b9364a1bc76d2c264a2a37be26ba1b1efe86e0c8c138b66d7b628a0904ddb6ca0b3a53ffe81ccbbdf5e6d09e7bfa429aeb6176751b524a6bbda1274ff56ffdeedab90380d58166221ae242ee1f6bb27c1aea6b2fff0040240d779d56eb28151bf9dde6a8928dfcca715c67a3fb86d0efa4a36ad858ad0433a6fd47909ddc3cb97b34e1aa4844a4cd3c92cd94af0b359beef3bab0da7423af0ba94d077a5de8361df63a92d785d3c6db487913418daf0829dbef6cd4b0232961b6b7f970542598352790314ea344c2f48f4d431cee7783a3409b8e4660a661d38952bef84dd2a79b5da4485ea0a34636f27bf886499fcce974a94dcd353a1bf9262fc4d2519c8dfcaee4a8cd46e2e07e2f0d4c6fc8ff701881fdbd7b6e78d2515d78c3c6da4c9932050820625878bea36ed8c8efc0919430bf750908638cb9e0444a3983e5a1e103522a954ae9744105a334706063c937f6c541a39c651eaf34a4c8dfd3ef2f0b4a4068f7170b5d8801e6a8156808ddfbf61b72bbb0b68b6ca7b020db2955c8f60ca06c5ffb865853183830182365a369d58bdc533c6106291bfa57e218b8c093dd51350b5c70c105ace49bdd1232b64571a20732067b6c52420a4288c213b12410296193a41b7773a9dc3f42c85dc30665cc6cb004278a286c64a64d3d7959d91ffb9bcc5842f6975c64ff29e46b62c1e25206918f590b72bfe9fb04e49101042b232777e329c8e4b1b40526ae97942764e06421ad5dc1851661698d01c5e54615f0f4bf22c6a08d09c253f3a1b6a0a3d74a7771a45f35777f17a9d36009da84b775010aabf244892df030818c317e803822ccb0a53182d9cf124be4e06431844f7a5d98b9a2c8a7093297145334142772a010c18503278abcb882e7a4e6076a9b01db6b7f0452328218697c22ee13be4e5243981b1a374b2738f8a1b176779f4dbff60e40b2bfe722357cb280c10e40bc271388a4165de45cf1f3844eac2705292d0544e0f02b62984256851674c0851498b0620b65b895d256ac90b0557421cad64f3827daec86c678faf122630a4b9012032d9c6183c2b1051ac8aa30a50b4300b219e54bc81172ff252aea21ba4ce83a29693429a5942de594d26a95d2a64d74f5ab13485c14f2429fe606f8ed43914403020a1d0d982f3fc97c39c524f3ad0884145f9c3f62fff911e89732e868e8a49ce9a7528a774e1b3ae9327ef69f5f0d2548a55241648f07782ce552cfc899f9fe038f4c0225b7451d46da87d93f5f8b4ee691c630c1af0375a7b3e9ec71cea6b4d6eac42766355ac5716699041dc9659f9ed3323d039a4c57fee8a7a16defbb43e74ea54832c6df0753f69fd6dbb7b6fe976eefc3cd52c2d8c612c6df8623291c79c85489a3a0db8fd06189523245162f226a4046124ee0828d3c82194ba230848429528081fc2be5cbaca5642b0a2b26f4a415d4e405238222fb4983b50488f523616acb7aab32a9ad566d492d75a7c018632c63c2fe0283bd6081312e618c710fa71272633c73e5c3cc41cd14f00084ce4ecf766d0e3ce000913e0589957a5cccf227991f40847c60870fc43e2063456853cf34c6ddb3bbbbbbbbbbbbe76c1c9c4f7d52b50abb2c81310d3d33b68ae50736b99c6480041142c4aa724a7d6a156e55ab4aa612c6fd82c2a5675abac81f9e8bbc25d39f7ac800b17e030e37f40d12462f95f709138b0bc5f4524a2fa5940e75336ff98e2f7195eb388ff738cb7f1cc8835c093deb298e33deec39ae7295abfca54595dd5b59f5498555a026f5a7679854577dd5a16b7b7a66ac5272d3eaa393694bc2dc1ba4d4e362963fc9fcb04e592c0f7bf75e25e8206182c891249ee779dee801f13ccfc39e07f33c1c72c0017603ac47e874bae1c791934c1021449024c9414a31b1b8f4bdf79e4e38f4cc68fa71e4241344081124496ec8c1c462e24c26530f991ea7d349ca2e152e1863fc18e39ed9e475f52003635cc218e32ae8c8489ace445cdb05b26d2548097101902034504a29a53f240c25e2a24976208204871c3ec0830f2548d17b8488a32875517a04c9111711974e0e3a7943a7b9ddaedd369b82d7762db5d6da27f9fedf1e82e4fa8ba94f5307fbf747fbde154bddedd30d7dea7f2dcc54c0aed9eb9e22b2eeaeb9e804f742dadee03dc49da35c88837b0e386c5274b2935eb55ab5b6fe542da1c324f74f1dab3191a467b6a2596bad633491de2e810071e9d3d4a1bea98ab74a4a828011aa26511d393d334a17e50010a8a9440e3bf07023cfc8d7183ab967464d9b7eadd22a7429a5f42461e6d5e993dc9e7e89b2c8e06c4fc4db6c2214f573d0effc1b42bb7e9f4c9246e6df421c6a0e375812048c58cd17df94502ad998eed3dbdddfa794d47d66774da7b44369d676afb46b155dae0b13b47a2ba439a76bd59b4a413acdb2fed44125bb3badfe92869a289f3af5222e7ada905b351ad6dc39ed69651d51517a969f8b94ee000717acbc158137262c908c278ff8162143620cdc59be64313049eccd1ee0dca38c2cb5f5135911b9ff62133665f99212cb1e0ec2f7b17fcf9442208380cc97970c2c1c0c30f27c79041b4481440e589046105cd0c2e5c42a0a2a308295453f992fe7dff9a62944ba9068f7852382b6f681c6b2894faca07a4f11d4bec92251848bc5e2b50516aca02d16e2f7e9095b20228f32a8280d15b84c2bc660419bc337b27c15415144461e6536247cc18331ba2005eb052d702df9c014ba88c24e4a070b424638bd9014ea419e2fe7dff92697cdd2094e1a535c8e58b2450f9808ad863001109e2042166958a1e3c415f278ca634cf1811358e0d3841ee098920417e4c0065534a9e28af9f2ce37cd287c68c2881f2734e1029c554f61bebc623bc3c70c962c410b515c2d10832eb181143f5809d10420aecba30cda19ba2eb3ee8aa63e5951c9cf176130d103a122a6b0620b2f0a75e38247548534583190c22c0a94920cee0502a85571c5a80a1fed5e22b095b26d5b1539f0aad8a2e5f75e1cf8008c1f8891451652acc819825a2184b799b185ab0b2229448002194b4c97a381c8112d8f2eaf222bac94820419b9ff9ade84234b2748300109314c44a093190d443022093e2990220768b816f21c23e552c118682c91624a010734b88288a808520c010b6ebb5b149f1537f09149b0bf8932d312218bdc0d85dc7f72998ea902755b3cb994b0274d43c8c0c91048e41e8a829422a1269491852a7825ef25e549c6593a198288bc65e96488557e5d612ba3002940c2136c908430a4a0c2868c3c97e00206668c5145103f688931d184217041074d563baca2684203293d4b1c6104ad0547c6c829821742403182ac896ca4c862064100010a5430f1910333b290f3041386f0ba02b50415568802c6853070b06de1068c2c70c044e6050c8ce8c069be69de2c8d603385b8d2031d1d22cb4772801fe0796713b866e92415cbf3e56896b0002359fa472c119746e1345110180b7e70be1e31b03033676ec89718aeb6696a65147277d1cc5307faf647fa1eb5a522641eeedaa7c93244eb93f83d7a79f60a5658e857416cc7d54c102a6ad9742885a26063849d27f408610526301b34b45002cca6ab5e873240361e02d1413016156c50609760233b86116bd28e2419674451d9a0a0e7bc4127dd096b967df0aca34d905d24cc945d64c1e6009d74195d2777cfc6ea5e79f7ddf4262069eabc17e371cab253279a369dd8711e21f7cbeedf3bef8f3b9cd4600519f66ad87ff2c23a9d489ad67e1e6109390b49a3bd13962005275c410ab9a79ddfee44b356fcae7342fa8bca18f8fbb157267f6927b0bf34c9fb09481a1fe52c8b09489ace6d051519ee7eec559ec0cce25e8ce78eec3feec89d7492bdf7c44ece565b1e5f2e218fbd925d6427b84ed75b0fa808849ce580090f6c50f07961535f898d873aa0d415e0b02ec153a45747120a451258e8d8a0e0c3810d7d25364000d1a2850d556243461201a572a8b4abd8ec7a1c2aa20100000000e315000028100e870362b17814a7a1a2db0314800d749c4c625e389509a318077290310829040c3200000004466464c6093a8da9f6ad05b91ccb04988a9131ab67c2e0b991b1977d0988a9d0e7f7d5bc433d8b339da42fc8d552e7d31281609cb0b24750079c8130ed05250b2058a388eb2cce857d4e709ace3cdca279f7eb810ee218d9a121ef0270b5d3e00f9e07a11e74a5b97e716845e431833eadd0da4a3818981611a375120ead845548cb9863d0e98e76cbd16537085a4243fa02a40c2a705469f0f92ae35c71219e0c89ca1db60c4a68f1df754be56a819d942143ac2b64709eff954c71acb142c9bab1401b31169e05914cb42b35142f8f889d6651ed7f6c47129c2363ddf9791877078c38f068f55704f8de769fa04762bc925224c6b97f93d6c30a6d9a473b31fa34b6f779aa1d1eba2939c8caa98becb88dc071db3622ed9285e8ea764e4a2aa9cb371d791be6c35d83035d14f56b1dadf2bea59906a70708074d837a8552da3490be379bb71d14b90cf9b224e4a9b45b5bacb908a811d8f869e9bd423ba33a08285d3dbf95ed2fcbd7f1d0d485b9f6eb68aa7e09f20070c3d7cfb9f16e1d98adfcafcaec0eaffc58f209d0a902df81cab0d03cc9b0fd5e9fa341fb7a3180dbc75debcc2a71c38489d25177ccd06acd7beb702099d2c863e62229ead4a964d01854c3fc73accbd1dcd23f7bc16f274be2b25ba95852e280e08a1a617100c026c6db2af3a7f674230f50b9c102a2b8464ffb7635ecd49d2c8fa315d4bed746898cec9354274555bdf35a5ffaa0be8b1c04d358c395f678c7c2bd60eb3742445d8e06c41774981f748e3fecc89d9a869dc75cf1aaeb68003fea8260b5a0a41327d9791229b831f99dbd4b5f90357cda0e36ff5126acc106b341c1d9c0cde103ff38f579121ac6dae904b73ba26c15a45e757699ed806a97226a822461fcb7f94b3c8774389d5e90120f83708c9b02cbf9d9d24d180c344f7db58cef61adae56d1a21b44d35c6f4a9e9e8983fc54027a912c17ebbec5758be0c946e6b3c7bf79331eaad4029d72d51bf04e4751af87a5b7168cecde1f78e52a0f08fc5d0ab192fcd2fc02ba182c7c8eb1156e05be1811e4fbe943fdaa1e023ff96c9fdb57633aff762a5649d9227a9471b3f1fd77972e801a0274e6963ca41ffd71958530a09ad1773587cc8b998a909c99166ab88f4ff83e9a808cd055ac0951da458bb43c71693b59548d4028d49f65f62deb0a130880377ed4afe80175e1a075a62cff804f8fe899dd758b6f3ae158fb8fc9b94be8856532477a6f453d5c8e844827d4377fd0e9a5b6d842fe33fa24a7f8e7a2e2a89f8c6f2a75c6b0de2af344d352b1bd3257434ff58bad95ff85b7b4e9c537831b3824c637993c0b0a700edf1e279c7ab0125d236bfbf79b1d2ab55e5d7d28535fc3a49eefbf63460b87aef458a6fe9d6d392ffdd2d68ee6b96013e2b047cba1c1a77f289745e926faec7cb14488b8bb90b1310ddf2c8653ffdfa055619b2701eae7c8c75edbe68863bb0d316f30c90940a5a2d910d66ae19ce3fdd8b0e633a0120b45f14dcf2f09f852d139c2de4f7c2d4d4c38c25d673474e3299b34be43dbda0b96b0203e3f89f32aeda4da858a5dd244cde9862adb59d3e3599e5320f918d0dec7e76df6d6cb055a84967f4079fcc0f3e1dc05d79247834147d254c72debe58f5f3500c83f6e10d391d79de47d158b295af0ba12b2051cf0dcb6e1c08dfa8c27ba9c1e1ab3f376f33ff60ab4a6686acc9f122f6e22a40ec7246d94a90c711d8355413ec31fec89aea07ba272c10586368ce030fe1fe79207d097b365d58de66a6801c1a5f0858e5a614256b6848cbc7356433e5566d29f73be01662b5f8dd4a47c89aa08f1a68170ce3e777588d31505bc6c11317309dac01ed41bc73a99deea7f1705ec704da387c375d72f6c39509dd1b369ab634a5009c9c3b04dbd048cc2bdc8b540d12e448d903e29ca1b42a7fba2aae46532f742f7b23271af66b961d82083fd584172d9415e002a09709b55b36e12e582776f76c3a4b05590c6e8db3af0689b20ae2b884fefe1a61b3973e27fc6490ec8d5c6fe0f8b023a726fc83cbc5bb16e03ca1ba49d71602e22a36fc4af9f5ce7cc1a5550d408e8509c20a19fc4b968e058cead90b0279d38dfc6425ea126263d3d34b61c2db0e0b0288f8a6ee038ad40b4fc8060139c6e1ae394afe794ce999b6616104650390e135df06c616a91885d57fe566c44051661e42cc2db9e1533e5b4d2a572aaa68d3849196311886852c21e212a7e65b6cfead987fe3a3e5580f048dd389f661a4dbae51274d8d70b0e433a0440ad97576d4379ea50eec0be184e9ba56fa7dd5e26f8105b52de06bd416f3d3f7c85c6bd57ece78b634538bde54969dc4ef3300ae2023a49ac8d4b79208db332d939239bcda7af783b760d86d08387551a8702bd515bf5f778c233f379a8f1a06fd15ea8b446c8b6ee74986d748da9d59252474824f5e528b2b17ba5879120d462e605294328de5c98534bebf3478194065c1973beea4b30058bcbb19a618ebf39d3309206fb59bf2784ec265d1448dbcba98a4c5865d720e7b240e836aa50c4f042f89dcdf8f1073d1341cf67fda842fdbd1fac4b83ee70843fb64bf6fef4a6678457d36eac6b96fff73ec57c1637ac76f0ec6bb2a888efb379f89c69f6849fb0c1a8725adb12dd8d3a6e7f5af6d990f78e535d9fa8b901cbfba336404d2997f457a1fcbfc1bba11221b0ba07fa23da392ebccf6e2f4b18f67d9ebbc0df42b9a387a61f256a77b881abdf7b087b388a1f426ca176019c3fc6e036c117626250c1dcaa95a2677578ffc263cf475c9271a279ae9de2eedf481a85f702d38f4faad37a4851a0064a9fde4c1a02b4086117cdf455af1099b0e4200b980e357e001cd6999a017a1234ca6aa3f4aea7741ddd144171178e6f3ae27372ecbbc8094255f23bd477965df76543a47a1bea8a4fa1f5a6c322ce017f2fb5d3b583bc37530606addb181f9517bb99951a19989a1ee4c63595a95a4431a62de1f470321f027baa07b929146d973ac1c5b63da001b20ade3b14d526d83dda276d72fb12238b79faf83ed531609a6f543f2f67d52af6a43c66873b51c419294d3be94a4843c745fb9f7d56bdf25066103762d3082aa350dcfef1a076d35b9486395d666f925b1acbfe82381d4504cd97a43304886c5b9e0dd58033481548815bafe8e98de9c9cac6ae9db311a9f1dbe53ea8a9e9eb749e7d0982b3838aa6fb74bd9a20a9c688aeeecb87898bd3557b188fe895e6f1885ee53ff8a29747ca2676ecdbfdeb26c71d55003cb7eec750c7843ce0590abf6b37bc8034e00d048b7c667954bd7ca4900d4b45282d419ca2bec8597ccd90fd268a70afae2d45cf4ee3d12f37d6a9016efbd656b6c34769cafddd668edf622580af0ced03d4637b54b76b3820742675af35961968e87e53d8be6a05111c831c1b040363fb8afe75b14f5806ac54d40759b8e62c65b8bc0ca5ba474cf350750c3641eb4d0d88c695a05a82b7897f4c0ace25e48a6082d9f15beeac220df4ca9babfbc4d35b0bb06947e03f1ef062d61c5df47a2ef67fb13b40b7da8931c6719a567f4f74a9761cbf16ee5427f911e60a8ba0b0e4feb899754bd400c68d3b31aeff1176ce34f0785274f74c4550d2914d7ce4d81c74f050e43d892f07b25713af8514ff31e5d8b2e6e7c3284470a6b1c77ae370c3c2411ee7931d7c5589018246c8566c460e1d2e59931027ddf0bcafddfe3df131bc34c095482c8b61df8a9ef03bca54499a3a4e6e12fae68373f70a6d1a1efc5956130e4cf9e0396953a74ff4f8f9b2dcb86cb4a011e329a1ce4f4da65b99386be3819d306f48889e08049dda80bee42eaae079fe523cebdf139fc95ebfb0285dfaab7e788509bdb1dea5648375b5f4be08fa8190c39fc7ada8236ae5067b36da2fa61a530f0aeed36fe159ffbdbfa62a480de32b27bfca31179be180738658eaac37351e432c8a420d85aa562c87f8e48eacc425dadf72a04de3ba538e214c5b7cb07256646b53eafebc42a1e20a76bec600bae05d19a9be31822421cfb21e9224f5f6e761e984b54768971263894f892c0d023c67c699e9fb7e39d67a98fa9ab054b743512120ac832b606df39099fe1f64450c36d96049eb118065377a5f37112fe2f02562bdb2450596c2af13886655a27892cff1b5501df2a97cbbc812a699751b9f1035701d0a688ca7d77fefad7b91cc746be61847295399d6fdce389b804e3c0b9f0670cd1062456a64cf7136cd1dc94cb71750a19b96ca5844b9bd48e0464333fb30b674efa2c07f7fef3d1b80373b93ab4f9c0539c5d98fc5662ae3bd2ac558073ccffbd744def436235ebb57ed2a502162e91eaeeda65daf419b5c04c0b8bca4ddc8e47310a74e6e665e50730c98f0c0a5ceb466e3154a847869052eb27c78c890e61f0877f9a8f8a064d0ad60de59e04c1f0d3f78cf64f0f2b1a2fe6488db1c6ced04e07f320a9356db841b582e2fe94f13df4e5e65d0a0eb281f18531ab0ed37cce97daabfcef3939c481fe088b60c7d9103e57df1b5c61bc132ca48d4457cda01920c9b496415efda67d47a90a92f847e176f087f93d2223a2b8f145eeb1866a6817ebc554f0f85cc7f5ef153f52c6a1bf58500d32b2e59de8c2c014f74b61f88cdedd352acf4421bb3a769e3ccfe75f2221349f618fea2dc0ed6ad1cfb5c17dc473ec473ba4c3ef43877f64375171881ac0b4063be27513a0d63163176a7bd9dbf487f34d159bc9bc5fb15952f17ab4f4755bfc2cc8db2dd1b2c9260bc500c87dc6fc067097badd6e8eef82628e56db0c1d31911779a93c603806ed6806687c87b4450804c2f467c92d6994f44fed965964f8c5476534e3ad29afd7b966b5f76ad0dc95b5de83461ee814183bafb4d26e55880cb90a1fa70a44a91077ffc385392e919707ea145bee886c273389da6c5d9a66ca5dad2d45be0a1a55bbce40656a43bca474050eae6b11a2e425717fd18c4419f6bc688d6d73855aef0768cb1b1c9dc5c9cfe2e96500a3d62ae032c9cd4dc23130373e30fc74c3ed87f320d6f009113843dfa36537f672cca95ee6c9a6795431884f897a488e0807f1808210444935e8094697984da22c68057b4e9c3a32755c2fee8acc18aae8c160b4b48553abe9ee0ef0fee8e4d65120aaee022a8bfe253ae12b343911a238d12dc2d85fb86654948c68d4df1186aba98dd48f2d78854afc5fd97c7040162a9d08008e60eaf453059a769cd915877d4fe923943bccf748a88f4103890d4b963402fac82e8e4114ec0147b90a47a5318627231d17948779b620bb1d84b96caa8e0e01a4db3e5748415c208134a574689985eff8daf0719b5ead8e0df3c37d91c261587d1c4568436add23aa5b438519530bf379e3f2411f2b38a099f0839243101bb6248bbbecad4c136b3e9df10a80bf243b3aaa686f2f9484ba71e4a7eb9d6589a67449249a0b279e5430186e94613737ebf282e411e828400c5b8ead904aa1e2947f989ac782c858a6c046fc613709904a35af3c4e07d7900d45b9536a16dead1a3c7853027cefc6c2c34aa70f9ccaa364121184dba9dd220a164005521b0cc02fb354ab65d1029ec903bf60e9b5842712c02e08a55708ae4efc18ef5b920811a18d207db42c87e7b8e1304ffff351a149e9bc24c1344a23cbcf55309397e410b5bde5723c081653f3e0825956caae259c8548720743f666d92d0884b39244446f4ff049882fa8112cc8f1e00bf35ac4ce229329057099eaf3571734bb8b6d25c8373bf7e855c3f09b06a7f7e4bcda395ed8a0b249b1dacac9b42819a3690c400b3ab76dbc9f3d433b95ca9f05aae8c4b83319a81bedca062676407150121fb77a8902fc66e52814136a53130793a4e91daeae458fc2a024b8ebddbba1ea7e051a6f08de2c75d2378fee3ba7550d37bc1db8112a21ab9839865ec7a9b665dc221c6bf1834c6b08c006f40e6b4689b0909a69d0f1b7981f1097efb9e6b15a11695f644cbdb69f3a75d4fc1efb19e40b8db83d178344cfbb58d63121d1cc981bb82a2da982487ad53a050d0df684d584aef3a3816938651ac2ffd4cfc2a7e747098ed32c0117c27015a2e7bdd5ace95b1e9371678a965e1f1aaf89d0713f88d6f393ff989945e63adef2679e7e7898272f02a7460b87c8b2477d419f3ea526d71473bada923bc83274c6e9c67488d83ce28f86756c1738b3346cbababf17c9b4cbe5c7e1894868c0f4ec9ba049868d2f8a4338c129564bf5dded27a182f7fd78c55de27dc586b90d159755657619e3553750590db45af0c7375b5d17fa8c4496b94248735f6ec08b729ff411fabc2b3fa328afc9866e35da067e41def2bcd53318e0de70e86642e2154c4d9aa77ce6c6cfa28bca8096f30d1b00512318e5d07a18f2b87f6bc385d9999593e440c1545c149832cc71bdf976110d324553c89577a995fc12e4d6d44e26e43f28c3ff3b9db0dd74ce079ff787028e4e2a95d1b121b77e492cda06a0c89d9165097a58e77c0815029aacaa0cb0149a8095f1d42b5db2c19f58502c5a70672cd986857d1f642f8a16f16b33a04a01f233635e8fb310449922117c38054ff501a87496c2a9a588db5884f04089ebc0d7408749f4395b34882acd09de0342aa963d8602bb1ba0190ac3cfd6e40543a603db0572a2094892b425844d1ec059f0d9d847c9264a35bbd6fa170707d7454dbe0b7023b16670548ec2ff3811e24d57b0c7f114b9f603a7d0186e6aa64862e639b6e1b132fab15bb3259ae2c4027e5d9c41356695a222e9c46476713965c03fd4ad403c3c2f8dfeec97971086569af872e6b3ac31ea230d2124bbfc8f9a0801fe68d7f552ce9c7d1049e5975b70015c308c99050e810deb70d101abdaa26d227a157b340634427506f77083e80efedf04cbb33d84b402deaf2db10a4b7178c5cd06a786659e25216accc5a4e5a7e53dd6301fec212bdb6b522fed489b26fe2a03737b892382040ecae225cc62bc4944824393c19968e3112e2e7345cdc391187bcb16acedc9432621239a2e7a753a8488a732d747232f658a0b206059bb18f32c5f9f279bd256ffe590b402c1ae2e6decb119031eadc77fd2d4d202c3650ec59e9e496c3f16c4744b93fb681c80f9181ce4bff606c203eec83c9df76402151256ff620d071f0671470b606674178b01b66be135d92efa2110c3706f02f0a931b27683888399fcb9c8bd29f5fd9ba9323636de34f3674cb44142931ba9571e11476dc21e06bd1e5b194ce5e3d504704cda92bacc0636dd403c95980686ec63a7da12687032ef48b12c4720e6abedb5924782465952ee9851549e031fc1ce08c3f787e4e0fdea749fd5326a7dbe0cc7bcfc9e024cac0f24ab802b4ad4ba80ab63472036bba04b982b117710e1066012597e914214db93b0fa67d730496e0be7be2abf8ac055bd4f90bcc0610067b2735526b01f8322ae2136f20b5b1c0549b5a7aac280bfd12e4c809b1ce15fe37a510347ad53543b54bcc5a5415e368e428b75f810c07ed5c13f4c220725325387b06eaa1b07332df569150c4a3ed22be6f952b612b1c36a571874b6b6078072c055bf4155ff7039e6892621274d6e8e904de7fa89bd5045a72b146e0e7d6d75116aaedc4d207e079d7d57a0c3a63194b4745c05c160396af62d226791fb9842f9ce90887507cc0ad15641532b6df78ee291f5be1ed911af9dd80f683fb1abcfda6a96d4aa6294bc539778ae5f63031e4008adb38caedb343e2aa799e05f0bef535de39a1b21362fd4b7e594e98ee6892b354813ad4df666a4789dbd294c626f67a3355b6cf7e55fa8e844c7b2dc18f3748e68547bcfa6c8dd4d5fc23316df916e3f91cf6175e024bd103ca4c70eb11a41c072e5da6104ba8c3c19aade8d8d65983be644805e140baa198cb6ab0ccad2c8c19cd1320e8cd08e728fd4cde46bd108be8d217d865f18a9fb5651547fd805340487f5a363c94b87a432e65471fe3b4b82c79312945ea4bc2b8c95f997990aa07653b991ad82b600469a3899dd3273bee028e0c8be326f695570d79d7a67d4d2ca3c7725155c7fad08ccc8ac90f22b06453126b16cbb0e171774521ddb2329e0beca9cfbe8e8100b370a90557d8f5c5518864813bbcc37b8166d029ab3ac6ca2a8d288724d7dbf1833be94a90f960f2256be370abc4562e6235088f5995a9ba62c84b33b988b43ba22da25c96b116a250d9c094a75d84c74a07e54a623eda2e2876d206cf754e96123ae7d448418933bfe40cf14e200aca329cb31977e6179e247c7a9afc038a4de00beafb59f1c60fd935050b5aab00379a46eb390c0004a2db0205f6bb2a2106b7f5ff045046f04ff117c98993b4d922a5f0f333cd31c3f3110c2c21f7012ceb471cd73192cc6905b97244cec9cbfe3b61832c1207cec436a072a76fe1fd2e546d09c46890c4d17b174f21484d00a3f725e4bccf9ac707219cf43f23c5c4c8137061d790517d51d73989c5c81711b6cacdbd28fe623d5abf9318c72d52875b864e076baf01e990816c4c4230820204a88455177f57641458ba9c4aa4f6cf182ffa8c53ee3d4d4a1c686a983d83dad02066222cb266ad6d68ecca93d80a1a3b58687e7a6818dccead0310c13e418a2cbecab0dd52d57c0897adcf10ab711a34795cb05add6f8d391c265126d2dbb90cf4bdc80ad019d8b5445e71b939bce0b335628414eee849ad10345d24dd59a3964526492f924c6f4f182d8e19b8aa686f53282a2a8f28b81c3da7220ab93bbd43a441c00f492f64d2d26f009877087bbb1b93cc3f485f9a505188a0af3d993e7ae1ff0e9546a694195e310384a9bfc2c1d9f5e724c0aa984d3ef55af96086194490d5b62f99a227b8777f85981414cea5b2680038442363e89be6c6b6e87b7f1994ca23cf8822ae7ab3efcfbd0458dcf4c28412b50733e2e585dd638c4aa6076c76e9722426198690f6f98982e5bd26708a96ae53b9d6c70a1d994b4f3f307afef40767e62b612670903e49162cbbafd944d19b84692c8e7beb0b5e491824ddd55ac6076a1f8568bee3b505a838381b6bc06461085226788ad48291d877c968ae0ef14cf192cc21f4c2492ff8b301346d1475ee907a0d6efe072bdc085ddf90337eeaff039fed1740a6451b4a3af409915d24e8b2d8e5ef1112217a676edc07ebb8e19017317a12bdfb86ff4033b7d5a4ea454c7c6483870ac52ef0889f5074c4796f63f7824b28f10680ac3f4c3a335eb6f2410c567afeb1193f0cb2feadf3fc5afaf9a107754bacf1f2abf001bd7079b179a98b4eea5f8643d3c0659da5b88eaa6266d1061cdafcb5ae90deb084ccc4d1beadbe8cd30bb35b90414d80119dbeb80bcefc7991cb15c8f13afcc07f024eb8e2aeac80b0f712d1a21181e88deefdb1aac00b96f1ff86a2f36b1a1cdd1a21bf87f5526f7280ceea63d1e3c7a72aafd17805aed7e87f8b457543ed30cc0d31defb848bc96d3ec2a18eba42451605a3cae5356453fd2f18ea5e1deae756942ce135592c764b9f9bbb56f6dea4158cd7b107b8b688882e464d409a5eba53ebb4d2abc6822f0f090b50f99120998f58088df305a1d74d09f79609d243de29245ede611190bc3c6347481b05e42c230090bf35bb06a6fb9e897f81f81c313f260ce68ce84a1fa3d5a5a48485e45fab2daff8e4d399b701594d1f6c715d544f03c40e9beb38f5bc0b193a86dc9512b3253b042b8dfb75e907b7ab7741725dec67e1c133ab2b5d1c91894909e4400020a878900b2884d23267779ee78f5362dcbcb4d32e8d3a3a7d374672197455fdd1eb70cae61a8525d73d6c5368054e7cdfb03718b3e1146a85117afe9a7dd9f98be5dccf3cdc75ab52792bddd9257c9ecfc93b2808dae7c8fc158fae7aab5a0b3b75eb56e01897a5edfee8ffc5c1aa68f9976ea86892fa5f3caaa3420978e524fd3131bbe38c69cbf0f267f4590ead3894ece3114899f99ed506b7e62d12004b4fe9a9e4d31e85b211f26a9d5c734224bde658470b4d1a4115fbe59a7aaa83c54cab5712e1030bba7d36d0275250d49f675b9c08ae7ac8f59586212eed4f46f59075b777912a5979ae32967d7f220091c7c60853c218bc45e7f942814cb9dae5008040a84098b2d08d82b39174f6d2a69da87d757aa9ce90e11aaca16b6db5f2ad9547bbfc224dfafbcfcaac20994730de58da8cc155b18fa226d6e9e40ad8758c959bda3e425955802d8107e189169e4ee8ea694312eec0f87e2d4f5a2a2f0d2cb97777515df8ecfb9121f843b648a10e3139ea1ef02423ed366764ef7ecc19c54ea7c76a5d10fa2dd33775cdb98ede619fb1262f4133eaa795fb395d64207b665db3e7499640ec397a428a5d42612893f69e527aeba301e6ea437453baf29b74e8a548017626930815031ee6372b93e9266c251630ba6e4ab8f8ecda9fa29934263fbd0d13834fe7c71527010f64d33a43791c2f9af940ece21e43c1480c614cf26c92b6d21090e9aab49de99c7f46f5be67d88908fd4268ef15839311bca140ec8d62d354a9df11a567d291d8abd3de7a537950a317b049f05dbf2ad7be8807cd8e7a3f76d061215e3a02a34d62796c0e7aed05c07d7da91d22c814e7f3b7ab5ae612cba1efe3290172a953d7a5cc2655d0f84eb58a12d90eb615d88e06aa158380f7374e2c30b97a8f7257daed87fabf072fdf10d873edc64d2952aaea1503efcac48c8d1e7c5cd546b42e3e6931307d3d3a818666f3618b0c2dfd74037bc809f7af80cc0a10def3224cbc10a78bca77315be4b1204841bd379a7ccb7d47b0c02f91dad3f8eb51127b7f2cabd66a7dee00662987de2185e1fb721065eade08a78e9c112113e302773ba976ef7f244c3dbef45f7ee1c5a42198d21dccb0e5cb72f30923a346b8652619508c5babf5c297588323650cad16f3789d91302d22cab54f1a03dc449e74190570043f6543ea4c5bb12f20535c549ecec81b02c094298ab1d69d4fe1b4b0b71c45cb5e6f84d155ccd058e825fc087f761ef0c95df11be05bf58af00105e94cf2e3ab4ccc0ff5f73b4c4122a2559c15391c680822253e43932711d98df6ff1940ae564e386ab9b43cab741195a9d63d3be8bd80737e108d3a44047f288ecc69906a36068e8f6f795ec23a483dee6de464f7fdd85fd64ce1667a0b0937f831359062e206e5ebb6913128ff28c6acb3f3f1ca4b8a1eebf81c518ff25681914a4f0e1db7d29549e8a18cbfd70abfe857facc36206d3442ab0fd34ca788c01a0fadff3d28343600a4235521c5d28c3296dacd1c630bd017ac936a40048be280f37af8dbcef34c046807933cc7bc146f9c892533228e3238d30d2e027f1a8fb51f1288ec45c09affcdc53ff61a1e0c815af26e1ef1ac440600aa924308cc663056cb8a04259e8c7605736108b40dc93915d8ac2af4590b68352cb28cde3a16bfcd06940faa70f0c1a2a33a75e191385a5dfc8e05bf8af0bff677aba120ea3c07131c602005771f3f8500cbea4d8a619b130cfcc5fc9de280fa178a6b639ee2888fed84047492c17c992d9deeda5661e27c85aa879b41d3c7a557fa6062e7abd9f2272809719c6ccb336b8abdadf9987c88738cdf31fa504bf1cfefa442faa08c17c123052fe3c9536ca4d762274fefa47026999526fac55698d522e8862ced8734b4ad8bb23896de8e1167d880abab1f84d4b15bfc30963496bb2cfa277957ce33a6df31849809a70ae12b30be5f8946913246fccb0b31c0e73f9a0941ccdad943354c549c8d297ad57b38ead07bea701d3445a6be21e8e5eea95c5ba4d511549126f81e0f565c55142420753c68a9b913280a2bd272eac1d110f9a4f3861db3ee5e259e8143c325cc3436ada11d623865b4521bada6323a7ba75e705caecc7c2c278233a23f89dead1c84e08364427c008577fced0f22ddb818768f1efbfa7d14ae67ae26414056657bc9e9400d7212b86a30f72f28672eeedb438cf99342a0637829bf500837765bf53bb2fd64c87c47518a9fa14f24c6f9c93685ffc5e845a729c8db101277366ec9ef42434d67ed99049a6ca1ee056940be8dd984552b194dfba524163285e69ec729a5d973d03817387c1f15083ad01e00d7a5b392c618a8540ec8820ae22492499150b549aaee81f29810752b40885c66827b7998a12fa0d5fbf243deec9575678917cf9f3733a881ada58758c4a7548390dce034b95362968ca8e34642ca8f15d04cdf093c34b98a58ab53ee33e3312e8c1765246b01ed9961f4f814ceb79631651b9a59d92c28fce92e5325e6bdeb3491b0f953fca84e94a69b92f55646eec768688915192b3be1d5931369c7b4e753969bfac1472669ce39cf332a93de0768ed324549da11762c9272b2499ae267e39f36a02919a3472b9ab951bd1ea964a2d49866cab85369b15bafa469a838b6d193729b9c797abaaf4b5617e1de70a3b8bf2516ae467a25d0fc94dba37fc51f4a032aa9b64b36c01a12584580426d532859aaf14ddc304ef10507c93a0089b9a2e2cee7e7e0885d0ce2c9034133caf73366b3440d3986bd119f90fdd403243dcb702c401ea165640751652fa4c5c6f105e5913b3de3b30d0311b49e6ce71282e8a5fdb567a100ff63238b4bd068bd9195eec69b6583612b91b3bc1729784a011f78336955f823be5560c6771eb1b0003982ac16b2736b68afb020afad084175f7cb2d2ec6d1eff79f5e2af9a4f9e995ce4a65acfca8d0947ca155ab236511bad1defa27081dca29420b6440f803ae5fcf405d65c9e9ac132353eb27f47fa9d82685c140d1f2d534751594dedbc26b53f13b8eae0d85fe3f9764ca85130639ca9925b5d6486e77242229b4df7b2e484465f3263a3d8e8a5d302c4153fcfb8d1f566f4a8d312c807d4ee0b683b328cc33dd3c939bc3101fde61c6519926ff848c84c6d0e18bae13b5750a68ec55e562860433354527cef4de9e389e91b6b634a0f7e6d0ab637427a77c87f63e31ffd1c281b1782f9f8f3c1592883145d2523bb3b929a73c53f4d64048f29149622d085007bbabc9c7a0f32f7842c786ae58248d15413f7a7c86aa1bb74cc767d495b0945ece260e6189054db7a46e93a96e9fb2f255a9e7fbedaa09433ddb0aec85883acf3a6a9580fbdbb4d8b42e4618c00060668f690bbda51112e08d074d858c8374c74ee80d664974f1ae0955e174f918a60e54eb22c8034eab1968d166e8edac0eeccd337387f5a0b61ae71d6428858cbccbf0ac0d137f78453da341944328db27249cf5e9e745da681af297f40317582cdc2ea3b7d71199930230e00bdee87fa43e95bd033147928e22077129f3c5a7e0f26815c6cea73a094e7458852455212ec8de562a976808ec0f3695dbd70e0329e7d44c832c64a5867c2b6299861e5794a823538cdef737dcff7f8484ff7a7d31e93be9dcaa480d39a843559d878638223b74948b6aea805232d79ecb48c4e62eee074328ed0e68f79429e0dc026ac6454cd77208d9ff3469542bf86102b1a0b6caa83a0c7c93310182858ec390d395db865d98ea5603be6be665e80a938ed64597afb15db10a92e354c3fd718b40a8d588aa42018a6eccfd35fabbbbed52c2301812dc722a913df0eae6f0708fb76fd8b5e837a2c0f56f00cc6de60fd5e914a1ed9e3f10dc8708b12cbbaf10c9b1c7a55934add6265256a5373e54aed42dc0d81eacaaeef96d78bccf157e7460d399a653b2bd6901cdda503e2200ca9abaa0684f9ea428f8082de67de51bc1e8c844be0fc818b2053357e745196e4f2c71d16da3b579dc39330902eb17b026fff073757286cc54c223075802a492b10f563ba64dc17827c148bc07c790b869d2ff4284c4c428779570fe35a69792050097a8fe6154fe37db4977272a7c986964bac982159b9a30dd322f529838485c654d9e8c6fa2fa050f122d908a2abd2cdc4b29a674ce27d429583a153168946b6d0fae7213590df70b1c498ef31bfa88b04a7a7229817e695b8a9540515843b62eedaa2907a005f39521a58334dfc2dfe7a3942ae0a37bdadd63a4291378c0d770fd82bdcae0d0d8f611db5783569b263d6c023b49dbca901b1fadc9cf65201d05287de5d5c7788cb24b00f3f889ff734619c27485f7620454158950eafd3c9825cb383cda6f425e79ad7b973eabaf24275b962749b1525a2cacc0021069682d70a4372e2b56503a52f99096681f5c2245699c92e0376986e02c388a89d37884239b01490972f1381e93be27c813b4100fff910219558d5d06761d9621fd75f48861963d8a67d4422caf30366aeb86ef7efffab8d50dd6b3ce92f194169d3197f68727d4b66b07906e9b8bd30266540a6caaebd896369ceeef263acd1c0fb370a27d5462597fb989d7ee97e7f310511cde2f7182085e214d81a3ed718b6d4f53839d76b6f68f57cc9ecd3f5a48b08d9bec21c6feccb8daaa9846b94d345230285df8efbac0d24f017242709106cfa8ce2a4d90f8303f129ee6cf591262c805c94ca94aec594ca103d8949f1e07a3e11b7d622fb939e723c7f2491307f47f14179a1908244fde9ea32a3e9b8c189dcce5e61ae22261d5acd04cc636f763dc0be1ba1aae230872862a807dc15c9961ef8e020045c1d99145012e62f3309c6152ff7d488cd853eaa61566d5c1a3c5f0b4a16798555434b13343eb4c53dc93cdc5715a40587237dfdac8a35b225286ce3953886e6c639773aebd66e60b16df2867c2d8a7829ccf2002de5f3484d031bd47ed048424e6d1289b17dc1754fd9b16e700fb386970a4ba52ab768fc90dfb6118811cfeef5f63da7ac9d17bd996a1fcf3480373ec5804fd93a0fa8fc555aa4764d39d5c317d293d36b0bf00ba2b4e1c748f3186835bc5e026305b9cd581bf743d0e115559c82c6699e5c801df3bd3b5ed8e5642197ae6a18211e169ede542c2c87cbb5d684de7776da49e04e1c95e4add8aa9131ed83ce51b0e5839ad413f3c9efe81c3ba474357604cf708620b8ab695693edb70747c34c311e9e3b4eaa080be5559f5967563c582204d6f7a535c91982019476e397a372ec4eab8e7b81ae21147153c77b41a36101bd33fba3b33bb189d124184953a548cf70c2a23e3986c4aec300540662534cc176e01a5802f4193b0680ab0085d7fb8593e583821c61b3ec8f08df9442b276269dfbadde2d2fa8a3c6f4c73263ac44d10c9840343ebe2f846685ed81b5ddf8b4bde61a2c7d32c8f8844d3fd775b30f40a2c96c55270895fa937c6c2ef968c6c6f82b036348873fa94ecee16673384a955aa0d0fb52819b0b670c15dc872753f1fbfd2a0ef7dbd9aa06e53cc42776dc0d54982b2aab81b9b9a8fc72935c2e644feb0de707de186c4010bbb51017559640d083cc181148f42a9a6cb6671e6e60f48257f4fbf93ad5bab95007e2a4c762f9cf6fe03e88217b01ab695916bce3d09804080910840a669f76d8272e15f9cdfe16e996e5bc618af225d1fef25c4e3737ab942a61cef08574e2488c773ccbe026489000f87d0a5e33544db847009740a4a98414bf5aa5321331756169a85ac66f604b0c621de48e296fbf0db441377af1401a1f3797e06550f180d09368b769c27c4b2ab287dec2aba5cce942b3d5448399903944db1bc34ad23aba570c2a2850351290ce8e6caa6dabf380dec59da12244e2f4b8da3c6785da877b8e86e4a5e630a661de67040088a58e1aadb2d9644ca3d59826f48117b39ac0f528a94dab06c786eb1202539379adc469ad6654cb385f2d7ec04d11fc57e4cabdd7619042dda31abf38917cad4f7d448349ffa9ec9112f12d39d73cdd1d00c5e6889337e057334701200437607e2ccdbf8a4b794afea80d5e3c8132e895de711963fc7972cd8ab79afb3108ef5eeeece52c49d4581e2d71ebd882748bd8c1b546b1560c9645a1c509761db733f32956bbbfe9c9689599a05b6f8fb453a3f5bbc7a02f8fae5571357d62d02a1d1db1a6c6564d36e8ab0122916606fbe511d5890700d53ba3d6df72778ec5d3d547e5a5fb1aae6ab778e8267d4475f6aa98b86c1f72a5161d0ab636bbd83210478915fd2fcfeea902f1b1af6d17ef35ce2c6aa547b02868d1aee5a860a13c254102a003009386f998ed1436d10347102885836117530739188979c81fd77ca3274201fb724e0cf7dee307a7a7295e251a507979336216c93a9a162f0c8e38a54b8dc0eb0b6fd6064581475a3bdff177b08e369368ab6364108466ee0780c44fa8d244857cf611af68482f0437f5b025e0104a9751ace979c653285039625f2f265d9f39fed662d92efc5361a87785b23f0b362744a8b6949eeeb8b495e197a5f95906fe57da6d7844de2e37328840271e9d4d10541227a36735e4bdfe42af6ad23b3c8143b82fb12f1208ec50ce2e30df351527d081fa47564fcd7e96db375f4af98cc6722556107d9832fe7495e1ec8294d611e51a740c302bac4cbc0ae80a0dc46315b6a0af42385b5dc2086825b06b4ef50bcbe9daadc12579282512dfd616f9f43f5f780256ae027ad7afebb6109139d287e10776d906fdf7bf3eafba204f89120c2943e9785b6b82f2c0c5082e58a9f12382840b9f652eedc8382c51942b1267d019b7245183b489214243e41ab5acf4e65b405393562cac63f265f615a9ef97158e0aff1bbb4722ee7b15345c669b3c6a7d60e5539bea0afea71ce20fcc2ecfd1128a33dbdda9b5a5ec866d22a0f64f35b94464088e0683bea137d5ec4442a1676638a3b4c7482d646b65db326a9024757504ac97a96e6c98d1fe54be95fb8cd422e8794ccad972ac61ae66e93a45e625af9466c6cb1132d91034ae00d24d5bd345d3e2cab6c75ab01c52085751bcb8117666a982ba0f2cf3f9867367d44357874988d4a72e7cc1252436167c3991f474b4547f42d8675659a21cc997afdb55032a683880c0408b8b66c5439c99f9d3d578a29b2b0659cc3e8bb90d5e8814984c60f180890cbd8bb6b0cc5d71281a87441c06705165dd6253160ba381044700f0a616cf311890941c9d082cd1c234f7c71a5f97362417e22a218803bddc51efd41091d6915387780a43d278dbb800bb724f1a6ae8882877c1e4ca11551e2bd687b937bd638e352a1e2074d27aa8b8669d66da9bc614481302e9b4e570684a680716cc288c2d7b9466e8a15109a1fe7b2b2e30b378b71a6544449c843e68a39a8955d7946e6424cbd413a7c44dae255cd57bc4dd26332dc791dc1642939ba4594464fd6272f86271873b78d52d6f9d6fd6338e6a2aa8e29ce7303dfdd3f1ebfaed3472e7569af82d552108d0660cc23cfa3857b7906f515a1769e2836c958b0a87e3ba6bf14d97dfc8491109bdcaf6ae775ac32ead0d0ecab1eb03161d33ce922ba70c3f6f65f33d5c8d373c1503f0c90bdb150104a424305da5ba55fccf256850871f64937f34a42cbd92a5924a7d1496d8c30967f1557e57f3c4219444c8e57dd17916a37144d7796619a0db7f51025366f8fd794e27ea36cb2eaca3fef607cf4466941f6b333f0a909277d28b60829ae8dd52b05fd77c06af38be8ee12b2cc5173e706275f2026f9828e2268585e21d538483918a645d817a0d77951e473f8cc4e8498e19412ac42ee4cb6b7fcc5c000482d2d512f60d58e7fd0de413400f195a0a6c5ca922d3a42b9cc290c8ccb0542c611d028bf477e0999264cfc25456ab4884592baeecc7fc9014c80a73ee630903d247bedf1ff77a39e0b042c9dab7dcaa4fde049dd6768d49e54b3c00d1ab8425090ee3e805c0e7fec6c173612f0ed3452ace1078f3bf89f817426c1a754ca14a17edc6e94643f3aac513e057e88b4082f164c43508ca04cd15996153f2a71bc9abf95f49e71342da557c7e4e8b85313a6c229ea874cf02c3947819813bb89321ae6330b141e8de3ff3062c9892a268a10c371cb2df13b4a0d88f043a0aa8145b87fdd64020f7af87005c043bf8c16c3694ab703b1789256ea1704dfffb432a940f52436bfafca62586975b23720c392d1d39a663f10e7880668a5767316d62717a58ee1817605ee5896dd61a24aede3e12bf6bc00c7ac4d7d5d9ea2c4d563ff0c10c12f2cd0936439f1f3440a05958e7f87cbfd28eef54b634c317a48221fa7ca51a529e95ff3e6403986097142fc6520f9e42ee29f1d41cca3ca171959afb87a8d32d72ed640fb1ed9e98eb34eacc6e2ac3fdc240d7245d4200e572a7317d5b356ef98fc95efc5a2dbe32c980d53430bc5f2181c63031e91897d44d77a8a791975b742ff0a77c204ce0b11912fe386c10fa0a02e91c14288718b552ea7586209c303d4b6be37650f7a2b0197ba66dcbdf20ff9e7170b1e647d39f765046f67aece8771789efaff1d87e5927fd98a6722573b2f69a28b6e1178d555c8e2691120ba976d0ee435799ab23d0e3227ca020132ccde585dc1dcad9b6f0442c8e29c4139278ed1b1ce22fc605848b7972f718b664e3902550e5cfef85d5c3669a26dc90b94e030cdce647f8db5b8db1b132bb5fb4cfd5f50279895e6de3f3b2a7bc3a7eb147885aa98c5e93b99c1d27cb0d4ff336bc6c48bb9b77d6d5c0f4b417fd1bdc88327d2010d76a9837ca3501e1627c46e307950aabf28053db1f4d685c5f23115c24248181d3f9d017895b1df8685d4b3879e992e10f34886a61819b7536bff3642e8178fca4d8e68130132c31151371c7f6e1a2e08deccf816130ee61a349bd5081b552ca26dcead9afa709425c9122e585ce1874c412a6ba9551fb2b7522d05a7dfa447a70d6be39cb485a26ecd61e0b38fe989580ab919fa3a7c5a05b54f12f1893cd09ec83ae9a25bdb1df0619ffe50f6249408d4a61cfcc498634fbc3a5333a054f4e37f4f1733d25c4da273963d604b79039c13a89393421295c6aa6777406c5e4cacab0421eca4902c69c4000e31387f918c2a65969325a01b052577e5546c01e915719615a62979751fd83bb6753765b22a9b8a69a562ff39b6dc77978214b14e07224454056cc4b4b5b10b71514b010c6b3b11e2a6a154cd471b3d6b8f1ae00009013edca416f8393d605e7dadb1c975fd5431783094861833cd35ede77b941272256e3338f8953a1a207ef085cf9754dd9b8978260dcab672949eea2468c5c711cf514d0858027fb012d0c25d75da6cb887f4d64cd6a4e3d90d8768aa2ef018cf12d312f878b02cd19e12499bd5c3f93072cb16f5bcf422918df17efac710e6e2fb6182227bd75502eaa81fbf17ecbbecade7192149a830213f6cd2b561f942f0f96347120716621d7a366ee1ed980c5a3503e0af5becf35b95048c4e08d4c3869971364672c50901c1b2d82172d2b61b6b1ba6412366bf44acec6c0721d94de55fe3a233166f746a8ef8680f76c46f76d202a5571fd9530b128cfd75027d99ac06d6bd2e58e428cd21b5f0e06561618c792af21ce8bc84d8a0c66662a9224e513b1e744fbeea11ca5fda748ae56b8952f2b14b8b971deb4ea510a50089b4e60dafc09118ccdf695888648d220e6b2bb5c3422e4465bcc57aa3839605eaf8cd054331e3261878ae160ae0efcd5f94b2e106dd2d2916531f4fdcfda9a9158536702e44b22f6d4715d37c4395ddc574a55d8be97c837c478eee04804a3a7fa67fb7fb4caa9747204dbb77f188203f9b6a6d4736a9a0e0ff69a4af7b599871122e567c83764e3f6cc46a4ae532a64487c5f0cb38bcb1886ec73f4fe4923bfddf56deed4e2acac59da657655d5a742b0688c6493ebdfabe7cb27f305649f39b9f1e41f9743741491f2ca4dd5f0425ea60f14d664b6b1e714df2a1e639567679a893767da8f31d4430391e142c6854b1a4c5e853510e15bacd1c4a0a000526cd56f67dda0e7922e9bcf1768d970e8c369e90ee957550e3b90a5f6c5fcb019958726bf16849b1aa41e4fc2b90995440b5d617526be5c24931ed9b281fab80e8ad1a23c57df4a9342755fbb14066349423d787e2ea51bb09797339bb2d4ee7bcc2dde06839aaaad1a9b6a79480a963503b019596645daefa74ab6b8f4f7934bb15c34ab3ac99ec05d0d8427d7cfd97c2aba8f80f39dd61c7dfae1a284dc261064c4001f0b33af4faa5fce083255b03ac34433e201493fb7769062aafea6b0c2615b658b8cf416ba1716198bdb79f0d7aa3bb0f5c064086cc07f8d6a0c83fdbef10d031fa8d5fba34f0b1a19878b3180d30a56fbd09ad36896cdb4bf9c5dd79ee16f80c030d091be0f30c26d825cbb2851f118231bcfd0a2037d8f540613214c8e4c0ff3124e12c487fa9741f7018f440ed477483dab9b00952dba10e8465000737c7a56115407c2588eaa47af8eb677a60c189f46fec511d39fc2091705ef8df0912ed1da1da038d73b239638bc4a78480a437d7ebbc15c5d1405fd7e0ef4b68cad09463463222ec901e8c9106bb5a0d1a8de073b558ec7fc2576bd22965d68828ff4aa33922e9150c085004271403c7e52fa81fc58bddf93380a758f1a65b4ae33781a610e928fe1698376835d1714ec401035d55bba86183cf0e4e2df2ce91ab68d90ef07fa21c05e782da074d1424f2fec1f0295e90f08985725a7569601700ee672f0d4ceca053184189881b0647f8fde7132057e09b4813ec9a8456131df7f242ccac8a1d1e142be1cd29ac03d16a4268881dac9cb01732fd4698e80000e1a170fac5ea23fa82ceac6029e4106b8be432c32ef377647719dea2d7dc7e717e10ae72ab8cee3a9540b98a932a0dc33f5808f1ccef5293d66dee7db2704884038ca4417b827b3d8e2d4a9c98373cbdc7324aa072c1a7c6c5e41cfc0513b55c52bdd027e3abb746e8398ecf8108df69b854dd012fa0b72c7a9ea312578abc15d0073e11e3608cb16011363920aa2a64b62d9da90ec5dc3b1939ce9d5964180dfbb8514e0c8b51e4e5a73e32588ca4b320f363763a60d36ffb392141394c728371c67be3036f40d07d159d5ce42466902c931d3170a29285517277483d10e1c178823630fbdaa445aadb569c283c532d06825e618e593ede3ec594350ddce4314382ed89448365a89329668a24b5792bff3795a8c4f2a6cb88f43ce6f13f803cecafc58e0788054d35d8dd365cbfc8755ff07724d0926d8666004737c6dc1182a2367413a395d6013f2ba5e5e4c96cb43815fa3f31041a5300ae6ad566a3574dd055e943d940130e1ba3e048850cc5517039acf31a5acfd43f232765ea7f4dedf26e196cf43bee984140f8308d2b1d33dbe551208cb2a96ddb85a0d61bf0d224c4ba0a48edf1e47ac05d2261e1336edac6455fa84dda915afb66d63b9b5dda0d001e2775478bd18cc61028a6f1c24637dc83565c65f4aa632d340ada64856f093a09ca3c60f9e3b4f25b71e0d43f40f00c61be945adb9a6b7ca86fca1764f8be843d74529b93290dbc6ee71ad4392a54f7be2649071f1da4ad0b439dad9ad52fdbbabfb5f67ded7bd0d0859f29a670749e97289f0cae51a3bd49bf1326679ad5a1a6742998e8e224243a7cb508c57f662bed3460bac7fb2a894fc814075e3a537f8ccf33acd84c018ea3c7f82b28bdd0508f7bc5ea48d301c20212d961c35602a6ef1438b2c3b22281014581aae3a7a98cc02b07849c0abcbb380ff67994b48ef3f4a16a080416204441469b7b21437aa0bdc08741b1d5bc01699968533d4c398bc5c9c0751e2db1c00c45f5a6694f8a187ffeece67791f60608518a09b0267386c8a3c2fd1e250e4fc2a174b1681d860dbcadbd1e3752401fdff1eb7802c79d3df0226657130aef6ac45de02252e41336f39adfde8687d010d3c334d8751e0e8d515bfb316cd8d59c3aeaf933d629fd41a472ccf81d0c4a36d2a5f78aab617008184933beadea99c7b7793950cd626c98815522caae3fb15b36006af3b7ee7378884349afcf944759d49e3f13219927849a4724eaee7c2390b93bd40912f1bbb98681e1c17af53e81a20e6455f5a90da6602e100ca86802beee0b736b70986802d8257773ae2350d54203fa1038c017e88f961f40af5f9d50b586a7f070afd5cc6cd22e43e0353851d7773d0d8546aca57d1936ee66a61cf5fe39eaf484d07c16d94e73844a5f0e582eee138c092fe33015b9d8096512c22a830864fd072ae7e78d04d810df5158d418b57d61b8e3718300ee4a2118a2ff070f72df7c88540f316ebd25feef94d6d02907fab3c5d3aef1f14309748aff49c2f718d51dc8c241f16addbd8781382d913fdd7ffe93681e11e166559b309f9585cec9fc79519932a6b9010df30e69bc8b74184a214bcdf130b09bf38f0fc16723410e2fe791641f4864a18d8f411a287c10c6eb348d4abbc413e30ce825bf3deba43ed1215ca3636acb196959efafc3005e6fc63e1b32a083edd87534534e49c3a8015132ea5ece8968e5403afdcc34af1a5e0ff8c5e188498369d79135db0ea96a8d312d7366cec0838182027a5068f86057219077946c35f7c3e10ecf3fbfa93ec101f23c999dd2f64e8e98d91fb60202ea1863bee271d80b7fc196485c0cc195c848000182b7ec3321386bc151b4779cc625fac0e30d04dc922ac79f775e930a0e080134d3c496ab8b8bb58c1b1a0b58278e765c10aa873c4ce32ea7a15098b7b46fc347ddcfa4cfde3f039d8607613dd0d8ae6d0892cf2e5817af3d7f13b22e6d773aa085af133004a85867867fcdd5be822251e2d5f789f18a440c08387792cfbe478e4d1204eb122bd070cdbdb5d867a76f0f316491a2f7b1fbee69b7c25331b19e876b8a3185afd225723bbf29f6ea5e54041d7f40a7816b9a20bb7d1dcbda12a11e96615630e895863b1a3508e4ae5cbff2fef957a9edd1df149a925a4c4ce9c7fcb466ca25fb17992b85f550c2c72f602065cc1b43a02254bd57904c14696f0d6226b713da394601304569e72dc9c3412e562f2c3a37a0e88e4ba23e95c66b30c14f83dfb7b8703044781d507c4d6fe63a1d6f57ef19dc81e806e07617393232930e399a0debd7a4670d88fe95745a24b627c847d2d4362ff5a606f357f2452514c1608304d60712ab9617ac2dd2d9af68e1840491480a81df64f25439e6dd2a32fd29688507143af75a45d371105ad8e8b515e78b5de7b22a7825eede83a7868b97bc2cbc294b606883e1a3170e549bc78a9b48703e0140100b250c6e7dea4aee917c7cd64af9b8a7710da522c2a190e483fcdd216695c778683508c18856a8f215f82062535fed0a2ad4eaed5769fbe50f05cda5320cdcf2032b3be3183c65074612c8c7c30cbe29ada03d3eb7a07b73d48df4f6be6fbec2f7d82c3438a678764eb209cca0a3108ea0602e8672e82c8cca1301775be296a757e8b217eebedbac44403e8d319767073df2a27543f56a49f62bc20ac4922fef850f3ef92f58a40ab5ba4532d57b0563b805c30281ed1ec241b950ce52372e675afe7eb3450795e00bffe901d84b7f14a3cd5309a985b98994441d481982746cf0c6cdb6d817aaab0c41bfff7262e71535d5f19aae32387212c67a90ab6b83f8b1dfa0dc0c86a5c425b59df1c5d9723e372b9dc7be9f6d0872bdbae24d51eef0dafffda71c0e9f52babaeb5882b895d2ddd38cfb033ebb3d248b94e6513caf915d200d3e657c476a3e21e9efeb6984d68ba7ae59ccea4656d6455ea2912903b0cf126a6535108d5a616b189a35d7b0bf474ae910a4f31a907bb3b66af22aec037610077aef6de38f51d85e55585cafd5e0d5c430d3b8941f0b07fe4bac02bfca1f44eefd42bbac60997d257fbb377b119d0ab617361a4ec2073e62ad8840f61e942452d0d31d44fba5b41fe509e7406febffdc760bd26f341ed63706038917e5ea1ccc0eff802cdea838f4921bc3b9701f4cf1c57cc72ff135cc96c729f81030483c4a6c41fdc9798697db41c176a17e22414c4ef6d1616e906868cdfb700038342c883c9c19279efedf764d9cf19d0def1474475b363596d02e3830ffd105e2dbba68d22b8b8a866acdc89c43d395f4206a1ce0e7b7bafab4d5419c5359dc491d621927a15a87a6ca826a8e9dbf07d6e7ccc3cc27cc90ef1143999c272c55b3761e9c8fddcdf3e8b46bcdb1b8335aeeef5ce1d78d64828039a2f0b3ab16864821d8dae73009630f901992034766b62dd15aca856c4e8c16de796c28fe0d0cab82c923effc8df439c492c7b33bf33b150683bf80bcc994465ae9d24b23fd34694e93e6b4693f2d35cee77f1d79ba74a5492b9db4d34b3f7d9a69583aebf403e9bc4a50501d6f412960d03da481caa38cb5044d81ed8461734ee9f741e5082d1cd8aa39661aff463ca9d193362999a49777309895efe6ba8c933c78001c7bee52aa57a4c9bd6227730463a93f245e39140d2a61417304fbaf993e34060d97f0f97cf40a5705e478a9d31e15e712def92221fd77946d1c2db7445de1e161a07f188da563d158e9e2fecde6353aa59031fbcf6235e0a5aec69be5e29afd5834353af6fcab94eaacda8ff19f51fd85e673ff383946cb52067c5f4fb6e71476c36093172dc6d54c0760ce45e0347a7083666c1f0dd5b50daa51b0f2d866f553e4dfcccb4fbe860496ad3c2a188679f1b6127ed92595f8ea3f68b624b32f052a9b8a306a139cd609b0bbb11e995a89f2e40a5620e915111a896c5f20957858b9943b430c4194b10292db3beca2c6c883a950b75442463b2c5545155bfdf594fbe5f9fdb1db2b16d5ecff53c26e45755ffe25c0fe49254cfcd9dbb645751fff4174701fee660567d57e02888beafed6d79793975c517d9cffd5266c51adc36f60d6ff37cbff0fdaaca8eede875a4fad1d601515a7f9d32ef797e8fbc7b4472c2aadffa30bb715d5bcffc24e296a02fd9f31fadfec5577c2c0ba68517141e39042a4b4e86c7318ff2a8800b0d3a0a862f06fff5c5554f3f03f8dd5ffcdf2ff433758547719a1628fa3c2b07f51c534bf3ce5bf38bf7e74fbdaa29afd7f82dd6151ddd7bf06587f043cff9c2fa845b524b3021f207a28bcc7b1a27290f60b09c8835cb213647dfb1b32fca97476c1788a38e2c5dd98ee8c986c507d4428872b2a8edeb2bed0f6c880ad4d45f5994abef42a40d92e2a5ea7de68ab6ce30751bf2d3c4535bf75c1d8ed960586fda009afa8568ddaa4a2a2f9c99bfffe8dbfc5d8fa6d64b5e36c9f5b992aaea5a82e35b32308a7d453b3e5363f384dd26e57057a50cd4320ac562aeab92653c987b43dba9b8cd9c24ff10d98848739aaf23d43c70df3f8df75f794bd0e626aa4e0ef35f137fddedbd4eb3d901803078247b9bba47723235627cd0ee19d97783d6989a272244bc4491afbb8a8dfa602d0936e10c73751539e31758858d0a859b027ca38a4fe7b83ffaa3d30cc8fa3fbe5edeff4614ff3aa85176dec8a19c217143aaae1eb6575c5e7ca9cacd7c3a3d04689d98d4fed36714b20996d67331f49110234ff75831a0fd3629b8c0869a223b1a0e187a45e110228ffba641a37217d6021bd69ac80aa8426f4da8e8d183d644a8912d66fa86e4dc4c8b54420c2433e172c81b08fa4224442260715956d294c537a67592a0351545d3458251eb1cb1ec440a1b0f075d54fd57a49672783721e055bdb543a24ac2768447f8d24cc7b7cee55eb42b1149af1ab9a4cc0ab422f9bd49367d0f1972999e785ac1557d1cce87c5bfd802f81e470ac61614b6b129d2f6166ff89e60e3934eebd554a70016f431153226c916805407d91f9662247071c219aa770a72462f9bfbd00a5a80e83fc2b04e47408cc8cf264053901607bb20c084058d229e472246c81529f8c90c4c2f844b1cf121b4184672168485403dc3729d5543fea32a8a91b43919ed35632f0cad877ce36dae87f7b1442e1276ab076ce8d0b21ad0bf0d551d702b0c0f018ab7d2458700d3add9015d0599250fee2cfbb225d51abbf5fc8c32b63c7edc5681d401985cc78f2b3f2839ef4a7889d075f9fd48c53895947d640f62a8c3e862d5527f05291a3e59046ae4112463394a8de6bf192c80b84d7708ecd5a9c844e05ba581a8993fbe018e4c8bd710ab6da81b84fec4b2ea97542c0b6713c0d0da9344c8996137434ea9d9af14b87655a9c3777c3a574348809b38d58ad1c303f0d73081817f9e9bba40548bab8d25bcd4436d6d6dc9a046a2bf631fa2a2a25e3297b3928bbcb555d01c60bfc332b621562e254961d93b72434f6471b1942722f0e2796375bf699f0239cb3675a52c66fef6caf6f844901ec491ab4dde11a988e24457c88335a3f110958c6f9f7cdb2e135a7eec44ef2b3c0985909b29d88e21efc9d690c84bf951c264b7ef7d6dc4ce75562506c683ff82c3b9806799a7336a9e1e354e24ef0c8f35bf57dd815a2454f8868d55e90b09fd5a2cc8011f3a0b92ce274207e1e936082f233961332eeecb64a6a6a19aab53d826466d4e873a0174ad6aa266d013fb32171e29bb8b26e54be894d15148b897e80ce744df7a0cd4a62ff75290d49c969b9a6215b8a1d1f1377b062fbfbd7bd0681227a0a291c404bbf246a921d6176fe29549434fc3a1f46e5e1f1132a231a902b3fb51de61213a88ec876e935703b2025297db184ed2b49bd2e075f3fb4b4315e13fed5a9121ed18fe84d9d4802f17d17e0098274295091ce52cb6d5d4f5f2787b2790b7680e40a22494bafcfe40ccacfccf595735d1f977112d70de8327e6de1eca5c2eddace3d15ce83706c04c834b6d9172c32964f8247d3052e38de2ab59f90143ac46620bd53e8098fc5d8724526c26d18eb75c4d0c82cd5f74d93d41f81de3a20d580310ef8c18b1ee1e84b0e427951a4dc01364bdc46d68dc701820e965899f3e7c029922b763e40f29d09a16fb028210393555dbdd5e5f7ed7b3d5f26946e37964c631a0c6a54fde72bb2e1c7f8da2a42a5b50e54df6e0b559dd3bddeb39105ce2783c127f3cc3542078e4367694aa7221ec703998870260d4788ca671aea15cc26f8983fa44dd5433beb9df66c29ae083b6834487e32cf1b3fc7b4ecc2540906419397e8c069f51842cc5111a6fcd7cebe65ea800b000a094b2522eee1fe50318d0fa760cdee11640e99b8c8e9875382d71f2803333ea50d48e848b3d16077ac5d04222f989bfa7f47ea54714bfc85ced1b5056cf3f62571e63e8774c0bdabb499ecfef652be7b8185f88dd0e66643149b002955c137bb0f22679e88206faf369e7fc546dfa34063e6b957c888b16e3d761d794c79c46441627c8c1d831f43dfc17fc337ce242294e7af979be42a89a2c184bd741125163f8300f95a5904453d82ff2c8cff32580f7db840a02b148d01f2d3a6ae525a34392d444fcf2b14f765f630af9767d393d8219784ad9700f2d481a991d5dfa893bb0b8483d91cedfb1f3697ef21dfd87cb758b7e9f0b910f210819043a6df48ead066510205312cf5a95664b4a08e163c4d705cca994b9abd86172093fa400aa217a1fa73fb5e34f9336cf6cfa09f224421f41949d5756815831f44d3ab1f09dfc36c3af2b6aa459b0790117cbbe6b8be147c546791b25ac2609a4726300472eb6901f8e0a98c60049cc8e64f3273c68c075a69d33f45e2cfe2574d477cd369e81bcaeefedb034421e71c702ff97825cca817a239ee6545360dfaee78f257a8ff460f3f4c953bc2848c4277ba99fb12079c1a5da4349934c784a2ccffa6a8656b8e76cb9d5422525df4857fa32b073209ac26d443fb5b351c9b84c0b44b9fdb53231f0abbddc0034d18edcde2cf513d0ff1df51c03212feebea1560f388db90f544c11eb4f071184146b5e59880598ab35dcb976dcb87b6fda2131befa0556efd886d05d2b105d47b45b128a5bb826169879f2f9bb01e7676c7984a0eab686e509c57e4cf99c785e18f3bbaf30f2e6741e831a84e1ab17664056b025e6a83de3c374cc51686efe8938b582b1be175281b3d8414e4698459209a2379cd3508c8ce2efe48442b2012a38328363a57be62bfde636d7b321c7036ea5554df60df8d677dedac2c3509041bc46b5ce7b41395eb4a71a946c9d5a4483abee42e8855cdef50229fe11219806f48a027f57b476ac533bc516cb054b812e795127f71a32923f916d483628e867308e5842257a998379d86e49bb8ef2cb49c851f678e91b0c4cf422edf616e539bb4c6e2262059a554b0756fe17a82148784e256091093d590cbce88fc80087a2339657cf768c215d448c785c866f682291215f9c1df95872b780ff4570f9f4be8dc32c2e4e744373b7907048fd7c627b37a6bd4c30e8727a3f0181695628a4fecafed3fe6e5409122be10dd8ef9e6136bec14afd60838e1ce0b07fffb7ee83d8af4e29553321d0127220fd91a14335f19fd4cd81b9f78e1ebb1a37a1a80b38abdae97d1cfcacae820675a3567bd3973352485787bee03f6707e5c40f14713785d83731097493576b1e7c3be8f362f71584a0503f4e6b1ce6b3d3f41acc29843ae10c297ace0fd6531ea573aedaf9feae83a9eb101b64ba2d7fa0ce7ff528b2d17211902dc215e5e4e5175d57d1423a38adc494508581389d4a46f2bf297279913b633f272d0c3eccd460f3171985ebad1ccddef8f69cd41e81b75383e58aa39834a4a29c5d45863cf8f454c430e20c3bd8846054f0f471a66e37cee1d402f8f0cbc6d1c421bc37b13e6a4b01eaffd4912b27e02afaf2b489ad3d1f79672a50b62b404ac3d6673495785e9407f04f46cca600f457de60cd0ebed5d12851b7f238ce9176154fc83b941ab19f60f913823fbdf2e72728af98a50da58e5e09fc911765bd8395221e56e6e78103a950372812242cb545e1c69b6c110f4c17598bc1984ea80a8f76ed63e580dcdd1027984b38602b8e00f9ab481e4bb60f1645f8c8c253ba2205b64001c034a0841a24e1900973da2817947c52a9320282283904e084d946f7f3e433e08c8b3c70be42de3ea148415039017cdcf15bc897ae08da84c1e999058ccc685ea80399ecb1b972c90822f20dd7704f7d5ddc90676607e37ab1fb8651c06e1691ab00b493593fb1535ab65e4cd514b03c0bd5195326abfab7a7fd706f49dd98672cac4edd7604a9f0e661d7b5879cde1a08780c3f9d3f2b44bf31b4ee2535be8822627f540dfd8f4cfe0f12d083fdf091a235a8cdce1cd591d83c660f7a8f2ecaa73e723947f734b3b305e8b28636cc7b234d51086b14626af4ba1a2798b73d147c6b1b9c00634e011055841ceb586542adb300732fd528073831c53a6e74cf4e0d472d2bbf60f3593f5f50860f994ce7a0e457c85127ec9344afeb0c29cbf9a981db518f11dcc547803ef7c11ab9c4de5dc6581abd565f56fb463dc845ee6df3f01e248e50c8df0fe7c7db5020e3ded1ca8a94fab77ad2f684ca382e01c42f3e10cc3f56d238c78774cecc2ddb5ff2299c5a227d9a1ab251f091c1c73db6e952405fea0a92770dfabb07109e5938bd6a6c17318a2b078e6dbab8dab137df88267f8d527d5cdf992ab3664ea538ac1d8b09f983f708cc6299c8cadf602b5fdcd5006255ad6e2178ef1e494020c37e87d28ac208c52050d71a868ae31f7a144936fb1b330b617a93f21463dd4d907e1a8ddeecf2266e6bc187e0b8ffa009fcbf76ce3f5f6329682d7a5f6390bac3a32f43f7cace8e0089f3442dca0880f02cfc61f82a957bd1fa4e4c8725f8d1ae1497d06150d02786a56942a3e7f3b7c55f14b1a068ec75fb8d5c4937805b201b57ac2d03911f76dd4c10c5951f6eb7117f5fe10132d9a5e2673af7e564861726f468ec93dea1e7f0b755e166653f9e0dc24a9ec3516a57eb58f6017bf3005f5c6930cd2c2181777b001b7e726176f8d01bb821dbbb91dc3242b3721904ea591003b95119463ba9200179f877801982e9ac1eb5b4ba9730d90f579402503ad36f9bf0d90818645c999eed0eb43e9efb4ef4800623a5fcc0e189f0f6f0dcfb700c300a85de99f9e270f8b8999c544017a0be97bf7ee12452e3c9b298a19e107d6e143bf90f94a3ee460042dc8a83ee9112905f0962a967bbab4dcb73a0e30e2627377dc1191c1085b2c748e91d0d57fdad9ba1d4b8bd0d6b66fa49257b61ddfdc7bfc0277658d19c801821cc89e6fb50d997639e38b4525406a23a468c4b6f8b10520196c2d5a3021223c3a1db9d3bfbf5e6d2baa861b763372da666c9c9a480da4b25cc26269452c51a8f4ef3b31633d8ba495f7b62e98a9cbef94d4e3cc903a14534ef147a0ec0a89641bb68ff94b8e22f3e201d14b6219c38b1b9b8aebfc0bf3938f2e8c20042cdbab89e0e939ad5cc45021976c18447e19f067b4312c55722338403756f8eb99da62e91988961d722f7400a5d1977329ebce1599427e6fd0c42fe028f8c111507ed746ba2176bcb05410ba8084fa2c39780e1fb6a2a984bef187d6e6e7f5ff05b1f9221556cbe87cdbb5423910e53a386129e566f9f9cb5677831905395f39881a0299551896f7066ef6f93fd27335d7eb46634edd9b003734b307047d36b205edfabd1408c10d546d30f994325f20083cfe6225225ef500ee2401306d6f127a0c4561d4babed6c8d921b8f15cb29b1d602d8971b6e20a7d35dea18c000d3229c3ecc09a90d54a41f25e9e42570438e02b06dbc5c9fda16e45a000b852df830e3f6288bb3f629f9657ed539f453988bc42a9eba316128521f7cd5053513117b09c23848e381a304b3a56d229ef24108ce714cef21662078d27fb305159d698d804d0a0c8745588f8620c5de5ac369aae5936d301d21c36a4c01fc494035dc1f9a72fe518eb17b78ce3f330ca66216c98dcceedb30fa35e5c9958e3f02309be5804c6fe6a958282c88345a83977aea0f2ce8d12504016001305c7a51e5178c0195b86dfc22d5bab7ac4f3739be1dc41a98ba1df9853eb7b3ef61498aff704dea7bd3d1018583c21b25171af7630b6a2eec061e63b7cde3f90f6995afbde0fdfc2a3ab517638162cd01a7433b8419b9ec2ee510404016b3010907c2f71a2521aa97f696898994d52b5c1cdae5f80f6b4e8a75b47afefffe8cfdc509fd8da7ad1095fdaedfbfaf0feddedacb7394a019d85a153e40ff275b6d557b0dc0a008cf5e992df994d0ff59b4576bdaeac0d4dbb88cf5fc21db8a2f7dca84caa9db32efaf306840c03da2396725820ce61950e03c936e082c9d319154add78949efa902ef5ac0d26c2a152d00c2d693aaab055a12ef9ef297a551270400170c2e5ed33b4a43f39426adcbab7f85d242f968a4e8bf7f2b343b463edc8277bef2db7943225290301070007f8065745b64b8ae3385a68224f1b103bc023b63b424cdd01424955679aa44dee89bdb0ccf0cd99c4e18b4bbf3dd2304fccdddb13868c1c5487ed0aa55bf661cfb87723fcfdff3fe9d7c07c25a5948274b657eb4dedb43fd3adbdf3f35a7dacb4c37c9f099fb37fce39c1e66827f17d2ba884dddddddddd2114812baedcb5532ae6ae9d32658a67cd1ac775d16cc139917db0652958b070e1a208734438034a3455f47bbd4444454444444444444445ee6ebb6ce55aa713dd9294f198967c7129e3d5c39e316148d105337bee0c39f3e308b0cc960172599482858becd30c9b387a321d93018de267dcb3c6d0ef4e76aa273bedc3d44fd9bf9b44c9de560e7ad696b7992058fc8092fdf66388ecff3964ffd9ad894ff61b1033d9ff0595ec1f4386d310d97f04128864ff11bcc9fe356e040182f64443530f2821b7282a215e55574290c06aa4791bb2430d8a169134940bca4af6a75d5e5058d99f7e3dd18a60354141193113758215aaa5aa233c5c6129d18292fd86844ff6a75b196626a45ab914cab495be732146ebda769c2646d48c10e112220d591e4d6fe94b1cec011d8acc20049c292643c8b6d6da2a61f94217647f1c4ec9ee032abb2ce9477be971e5c9a4b165ff0fcf169efd8a921ecae60068952771eff7718dfa4fa7579441696ee4ffa245ae16f6fd33a0019a44eb5023ff356bdebca953a7a45126501368b64ee998a051611d12822a5c5f2d3459e35485479563849590163cc1bad26788ae3b733bcc790f61acb0f818d1c5cc991b2c99ebedb8e0ca8e2a314a5c38c1696a015101c321a2797ce10174cc71b4db438960c00d54766a6576e0c164da9034e56125f7ad070b3ab0903192258922649ef28079de7aa0c0f57595e763e15aa895e79c73cef9e5512e95321d6bd6dabf9cbd77ec19753f829bd028f489c260d8598f7255bab396ef02f28cfb9c576e9cf356579a46f3ada51867d05f621d3607edaec8373d89a45a8ee0266194925ab919cc269c7164f34ed7d127ac84396badb5d6da5ba9157895c396c3cc776dbddf5d5bedb5d5cef21d2157cb5d5beb48491d5d8eeebb8452ab3c6914dae408d592a74de9e98832cdfabc1ed99d382fdc2849464515b692d751d78cebb764b6508bd6bc7240512b2a7a95c31652ab1c663eaa4e49e9e86836fbbfb3469f720e3d628c39b394cafb65a1d7b464bf4f6bb556c3ca7eed08a04831e5029ba6cf29ba4fa59ecd9761afd5aa8c754e0ace1d83e603b9f65c30ed49a153c1931f27543dfd1082862346744b1a641e59446ec883c4e685c7173d03c157e8642f23e2b82038cc711c47454b4a0e51aa04914201c9958a24cb098f538127599878c9c982e3c475574ae3ba9e1d4d1b539bef5fcc1b539ddc8f652f8be57963b23169795440bc90cb236f89294a5518e679633a7263f2c1b4630ed72414caf3b624c4750a83f2bc2d717530843f79de96ca74566e4b60bc2ce197e76d098b024b57b8ce89c3a520b9941d11eabc6e8824402cbcf1c95662cb4928042ac8d6140b5203bac1c74f90ae70cb1098d355ac4a117008d7cf13211f102d188f22423c2790478fa7cec9f60d01859f9abc3943b8aa6e8bc805d28575b05c5c96531552bb3238b9902fdb42530781aa549a280843a2fcb623ca8893577f8b3ba06cd79017feaaf7948e9ca61f0c82e152cd3d5ae8b101137a65b8841c0e9d5308e372b3844056ac11a107c50e8124c34067c88d13fee469a343c359215010476d44bfcbcd9023a523164a20f8c03184384f5b979a5ce2a510ccd3d69543eee684b03c6d5db59c44011ad7871b87b63b6872cdf3468b21979fbdc62c7c5fe732ac945dc6f5b5b862f76bafadb5d6d1dd6977777777779b50f2d1f66a3b7bb1ad7e394e4986655e937d7dd1fe1cbe2f6a234ddcd9ceabb6daea9e87ef46e28b9ed5cf03dbdd56b715f460f4939294c27fef9779cdd660de0b37d2b2793f2f6ab3c5e44261c2d6a6f6daa697bb4db9210a50b23ecd40798e4a1cb8373491c54c53f4acda6967e759adc74a1a332bec2613998e26d44c636a65a63c47b10c634dc39f9fa6f3c7da8a6df866df7bff855f117f27362991f73d91c90726ef372991dddbcb35ee3e10f613fb3ef004b556a8ba588e16c37e622150d0cfec6e53a0b28dced94729a55869ae4a1c98330c4d008941f54bafb596a042a289143f41611038832efe3bc71976e4b80f276c68e2f738ec46553c016ef1af3bc269b39a9e98334fc82e00cbfad32706e0d098bd8e77ac6d82cb0fac1bc47347d8ff79dc58ebf469c7fb2b94bac9260963cce18fe3525c0daeaac36aa1065342fa0d82ded8ddc1155442faeeee1ec3efe592662978c491829f28d88a75dc72393a6b955dae5e1077de27644be06b391d2cbe1c9e02c2f0b59c0e165f0e4f81fdf4e9c44b7e3f60275af28b819d5849273f20b0139bfc82c04ea4a4277e6258a3042c84300b95c03fc9fa3f30187872778aeda66261d7513c15024df1a680826047b3d90c840ee57d3c0a85f74bf07ae2cdfe60235d136ab62eb21d6dd89a0afd1e9eddff79ed469d57bb11acd53d094aebfb083ca96dd1083c09bce149dfd3266dcaf3cba9359647992b8afd50980660ff8d39863040c9ef29f98d4d2009fba64a327def03937472d03d2852b26122541236fa588a91df37792f0c19df382707ddf592bbffc2257321cc2fb46328291d1dcd669fbba9a5e525e32e0e0b617af1c65b54d435e7c3fcb66e7f9c515b880f37d205321427aa09a112414061ec07067e5e87b96bab379dd6dd73501ddeb0a8157942fa2bf2b8d79dae38f56778fdc0bf295d617f9445f9eb59cdfd29c016fc79f19296ace4e720283af955f0c244ef67fe623796e97ba1e5862050e754811fec465cff8e10a8993e5773d3aff7bd762ad55e7bcbfb9dfd7bbbb1fe8745ce8ea58e6c692e812641455badb57786b59eaf5880b9c1d460cefab127ad9844f4839f2bfa33e8cf449d2bf7994e3804810cb8ff0f0fe0a7049a44b67fdf67d08a6967e7c38d8401f8617041966514d7829c9d463013e416ca257250febcef0341d0c558fe7e404e9ce44f0c7411cc5f08baf8e50f0874d1cb5f0990c399cbd7e60f05e862cd9f0c74d1f377014874c110063f3ed615581cb99bba0f76c20bf2bc2da1bd094fe47993aa4325c5c3124e2a4cc52188e37449613902474a2aea872b292722706c51449c10070b873894618fca4b851be469b35324974742c20bf2b4d5f9ca13a2c8d356c74d0c7576002289064342fa5ae1556a1aca1ebbbb4b1912a1c9fe267bc4c1829b83f66d431b83fc433882cb6c8e7118ca64ffb31b1a080947e8ffba31bfe697adb6ba25c939e7cf4979a843505c6badf55ace626bf1c85d5937f50ee8021ce4b34e21fd2a809f1dc9e605303c4db7d79f2abcda5ecc610e0871ceaa00ca0db4b5d676e5c07a31b6360e14e85fb5757c3b39fbaf74c5d0621c42adb5d6103e37a6b5a12e0e358e28bb09354fdbd1d16cf62f9351a8282577a740931e5a17422b7129a46fa285b0eca626da04e47b269125e4fc79e29b9e444e4fc2f48d98196a705ec8c2a25ce0a0e1a25fb07ae8f2b696ce6a2de922bdbac18a560ea794c8e7e549145513440c5c648b96c812f26b1e526ade022e5768d5ab8621660bb4a8f075a1587969a251a2ee50611bc45461755a32b840f36e73a03ed0c5c9a7ce538d6c91003f901fd8e48b0d06ba38f140e1c345b6d8386c21bf9ff0e795b8a240912d8e58c81c4d9b4badb55619f5b798c31d5aef1e2f05bd56af3de38854191e649b8764bc70a3696d19c6c1508fb72b7b4332fc39c834d31101998e3af2d7f64e9ea58e6cb9a68af99ee9cfa942c98deacf3ae2c841fab8c3f7615bbd3d3033adad3586e24748e75b9bfd5a8d982ae6cb8860e5f91eac09e97c0fccf8f7d7318cddab3c9fe338cedadb94adadae076371da313d9bd8da115bad9ecd178784f403fbb8d6faf78baea8b556112cd93f7bc491c3e6e8fef800d1f66ab93157cffda21ff8cfbf46cc16e0cfbf5557b55c86e18cebb7f2f4b2796979d5b03c29f4e2f2eaeaa4900be33094c9aeae6454611414549e2194ec32e59897ed63f5e4190b87c0c9f3ad9bf941f864e3d8ae46e29a2deccff9d6d69c67edf53ed07e1fe87520ac7aded761d88f779d87b99fd88dc733e895a6965fdf7aae175b42fa1e972785e0582919240e601ad92f21da0f4ba407841916823855d87fd13018f5ed0a2e47cefa6198035a0b280e358066f03bd35c024d6262aff0cbcbcbcb2bb74c089727795c6dd4fd1e8009af3cc9eb72a3fe10cbc297795cff41e5feab12a3075b82c4a269f43d508afc7d08e5495e184285503fff4520e3307bef71810fc6c632fc193f0e64fc74f6793f6bfe7064fcf43b11ac73084a9717c7cb93bc3b1d3ed10f3c371f53531f5af6f4c0099f72bfc73555f48b4e1e577b5c1e579e2b2e47f53d5088014918255d6d6a681206890db344f47ca040d3a6c70a4880a1c10a12fc2507219562c9b261c458e7a1490ac90f4e8ae4599226eb059cc525005e8f16b2c028a1e1d683114976e63cd9d266abc987100c110dfc4b094ec00245c6cc52162d1ac832670839533600e921ab2b28cb8821365490609119e2081582e0833b1c6686eeead04d6982e1cd983234a8253534753514116aa3c30a0c6762c05244eb871f6cb09beb04c651c9a262b3b2ae781e0fcb5e1635c744ad69a18725b0bd93ab439c8724bc79dea2dcd85113e41665fb7e68dd89aae11a6e513184b869308e4aaeb99c3ee4727e51261a1585875c522c4a63b9a475f264c1092ff050e4842a208a90e5cc023cf0f045c64627cb0eb29c5dd38b36e5a65026b8ea618d5498206c90204b5aa504e64c0e61725092041eb2a457d496fb27f58a2ae279a2a2fa298d4a85dc4f6b5154723fa685b2306a299733a6a32f970bc25928b9e0fa0431e951075eb5d73fb8a08c8ee7254f892c2f71ec4f9e37255a50b24230cf9b922db93ce2b4429ce74d89162b205558f3bc290977aa68343286704e0afe583b5e114f15d45a285805461c39c81eaf4c24f6107943bac8020c4997947025a921ca0f1b7850dda082b8044b114aac1047182173c12a7a5043d611f2e3c02a22255952457e18aca2076dae92905fc7e60a49140face2c423c6c9870face2afa121c1058255c4f16ec28c4142e6e8400a9337647d1771d02a7bc81c424ec83a5671b699227303e9e23cc387ecbaca6d93c366863fd6d24f1ac20409d245a12f9ec2378b4c784ae9acc0378b64619d481356717c30bcf2bbbbbb5bfc7ec2400b83d5469af393cdffa2598afe81894f2416cd8e58b878e11ffb212c414aa97ff8b63db7d7b8bbf79af995958291dc5f6b38ccf596bb7b9f71776793e97b7f95c9929bcd9adb3668a6b59baa7177ef347da6c8ddddf61aec3277f7dabde6a8d5f4dd127277afb567b3aa2685bb7bafa9ad66acdd5beeeeed6a6ceee349aa6d50dc902631406d8d1d420088fcc81ad1502eca55c51851e14cd75592a5aead7b77d8b103891db433b5d1d446238a192c7975d9410f97958fd6e3577d45cb097ee52fc69b5a872b4bde44bd6a0a4580502fad9f2658424c2d281be630416d592e5eba64fa5bf78a52d9a6dc2b17404d595068b840536bb5f6d6f432bdc4b8baf038d328501a8d8287c9327306fb96579b6ec0fcf06a3ad8afd486f0341a6d87d90563e468997179936b0b3b1afb362bf603cc9bac2da2223146542012ea406acc1ca1da686ca09c2c4b6c5b4e69341acd86a7e1308d46b3c1a1a1c1a2c4960e7068b000cf503953054c4323058a14f45ca191024d37ad891ac9469db59a66ebbbc91095e9d6168d231354ce54399211e00c15343464366e48a3d16c5c4ae909b037c579c2e8f3f89ec26034edea3e615dc708e8f0517105c19e799d6e6bad3ee703aab3c59216518f6d8f326ec6e4fedaa006627996716366aa825f6e51b6b2509e37286432fe69e48da58d9b61de738f394f9c81df01337f9c58ce5aee0adf13cb17991361ef8936ee0cf0699e30ef71f93d6c2c218324924822cfe0667ca38d9bb9b77173799ffb8f76e20cefbd710637ce180ac1bee7bde84e4747fd062cd8a7a4678c952d3b33b0214296321ac2dc1a68c0e184d7e4c1973759a4aa7e90f3dda0e050b10679dea054650cf2bc411942e79b4562e8d8c8696248481f02971e2141043d739cab38690dd55126a842da54473412ed17ed6e6d7094f67ddc57d6b35a024a581211856135f2cdf76c82294c1aead74176ef7fc393867a94c134dda8c674a34efcbeeb1e7c11ba07471c56baeb5184eebfce1bbbef460ae74a9d15962cd5a0d1c82337f2cf72482b27f072fd164f40738b267684e5f4aae149267a84e5e4ba4302976588d033b7d1a61a3720c03d09e687341a2dcf11808e08cb39a96c9587e18863322824c9fdb5311e5a14801629b207b964f1c48c93dc2ff392fb7faa4dee9f49e5a672a3f446f6848a05c6a187f99c429ce7ed49d47d2ae2f9f0c449c8931e2c58272d38d2446a4eb6a46040d59c80410283c8573f97430d6278844130805161900a638240f243103f383378be38356198a70d4f1700f2b47989f1e19b5e6b7577ff5ac770d6fecf80ced93da1edf572cee1ee67f9fb92b6e28e72453ebbeacd5a6bbd6dedd0eeee76f739e79cb367cf9e4a476ee4ee2ef3ae2fab5cc7e3526b6badb55a7707359812d23ae79c47d36badb5d65a5ff86691f7bc6f6bad0e54e79cd77ed9596be79c9f091026fb89812168ad6da439a7b576cee9c5c039a7d2911bcd5a6badb53ad80e8bddaf97bb2f7323ea312853535353754a9d9a9a9a9a9aaab656d529766aca4ad514a787b6577bb98e3b0205d5242aaaf32e65a2d126cf121a43642605dd42b7d4f0c2f1f58155045c344680a90c1b074680f9d14cd6b0f901c502c16f059a456b3d6bad36c2a21f501a6855ee2e14cb663bd22d20a01081185a93fecca25bda684603dd92fbc10f73b07fee5aaeeb2e08ecd5824ca9158a38746add9c38652b00aa2b5aa10db72654f01686024391a64eb6b53c867e56b6d9bec5d6d645c98e14a6ccf0d5c47e8c8aedbffd91ad182bd9da0f2d8c277ddef440a74a9e1a485b6bad56c2f2bf47f6be3199cafdd5719422fb73866cbf36528a6c97ccc9f61b06c3566b2d9633d93e088d1466fb31ec47a0adb5d6eb2f6102666886b0735965a0a010fd233ace82ae42daa7962d6dcab628dba750f4482345090d11d6a71f444358e2fc9884b75fd6ce223bce0899640ad6304e58d64a4713b08d9bc12c3a9618a45f3872fdd4d7d41372c212cc7e1fcf24fc378c6151e456d442a4b296762884fbdc73633914255f2a3b9a209465cea6bb6bb750cf6c9d301b9ddba5b27e16cd2ea83c8dfcfdd53cecc554e1bf35a7077481205d3d9b59b93efdc4dc61176bd4652dd47d7d163349368b665299028b9c78c531ec9950cfe6d79a95ddfbe2a918dbda359deedeffa2a56cb5f6defbd55a6bab15e2388ebb1978f7782679df8d0151fe58ca7361c5097bd2e8c06449149b0e26a0101182c4ca8e94145b0bd9412273ea64b913654c9025283e6dea7c41e1863e3308b1e4137380012039c245cfad6a4a4b14e72427851a6a538228f3e4858f06515ae043844a1d3c559e95075c886386ce55d50d743c480a676a75c0703112857be8e084291f6c52b093664d5d81050b34ac19b21404535554b74586ec8fa36e0f069059a2a40f973c607c4c07040a47682c5c69e2c5737292fdb1147744922f4b8931437a2011030f5a5ab54d100e44a4e0d4c34a1e1fa2ee157f2c051a996988c07326c994141a6e3d47470a39ac81a384cf0a397459d259b5487244952c5053a2a4c123812878d23819b161091fcb030664981421a4c89a1b93630972d282aa3e5235da90280f4f0786d0010995a53a5288a8674020074d9f21564a86ac89fa9efcb1d40e2b40e552d641a63bac402bcab4d68e5c64eec7dc0d8a08713bb076e4f18fc84e0365b29e296d60242c65d45fc78f3368b0981903430d07b20c61e893fd6b11d98508224b192f6a92c8f142c240000ee1cd7b32b54bc6b80993a429062c575e90220fe8700493275b98a2be6aa62f3c79f8a55f50f3421f186cc8fdfe5a987e423138c50b564e1cf182927ca2ca903f2b33ecd39f2dacb8c154d14f6bb93f057d23b21630c3df4729f7ed58933ab0c51081c651b7db0d94584071df60b6987c961290fb8e4398e4e0a92663841731aae83246e87fd11f03ca53c1feec5a7bce19a5b368b6a0426349c3bebbbbfb84bd7d9818f6accabe3a5bfcdc0a838d313e3055d4e8a40350dd606a526bad55b9c2bacd084450b970fe2e581bc9849fb78133a780264c96f8125f9a28815d94b8458d04f4f36729c21731f61a35054c04df45a06f31f60e830164c3661028a6e40d83011b87204033ec1d4033ec03313c29451bf96c5609cbe955a391beeebb231573c5cfbd3f2309464e3868975cbdffbe7e0d124cb051c2fe036163d919f63fdf6219863d74902a087a16ac20e87d5072ba51f7f7b01272340056020cc6e77d6fc373f7d89358b08212ef839225be8e4332823e68c441c9a0d09330598f54cc15f5b915b9a6982a6af5b21df154b115de68a412d7b0d1c2cb3548bce146f54b982a6a4c151c2009c5a15a6b2dbcc1a757afee7d7d6aea3ebffa9c1f9b3972ec69ec5ff48c7d1563e3f7ac9d163ac9f3668455aeb99b684de91214d9cb542c813a80cb3317738e1ed5b3d88cc56ccc4e2b2d51575697524a4570f7d8777737adbbbb5b29971db394d6148bc5622258b5c9ad94e7f42a9ee44dfe3455b437b1109694468b817798d026f48ea9a28946699dd4016d6aaba658564d5aa2aeac6a6d6a8f6a03e47eaf3255b45b59b7eaa4035069a935d21cb3d51e95bb3d2bb79bc9ed6c727b9cdc6f27f5a8462abd4aee261dc57995d9a2c9932853f7534a9b2ada00533628222ca7191270f7fd1c10818dc671efd723a5167a6a1f167b2a964d9b352a558402d991296d168a33ec3215124b8873ceefa9088b4d3cc5ef673a97dd7249e010038ddf3f2367ee0913c1ca101e75e4f0276c041c3ac8f03978eafea6f57bfd340679402ab45a664a57a6fff589329e956999295a7289cb4c999281f22c33252a9799e264ffc6ed7b2b6dbab5bf40cfa9bbfb8650834b328a4ed11d5ad1b3dfe1dafda52f44d065738f24f4cc5170fbde7a6bdf68a4721291b9707840720966a763f7df776729eafcdbddb34512a60affd93467520736282d55d995b6341413c85544562e295511585758f42a7195f30beb81a2542b09371a69de5cc092fd715014cc16d666123c49461bf98b305578368095d0bfa44a409a660b8a8b50a94c5100913e5064c10abef741c9efbffb13fbb1ecbc5abbbb69d75a6b77d7172e76b436fe86756ddbf6da0db6c2068952d0282a896acfe8ec19ee1242542b0e4d30516fb0c849a6880c55e4478fc0d1a257ba507991a16c4f5886637c18a165412b521580b8b922eb05adb8002275b8c82a8e58c88f03ed0a22c2be61d1ca65512e5ddcaa3ce5fed95137bd9fa110702e73647f4a99e4c1d244d617947648f122ef5cc143233b8d9a2d4d138c0b2dd4f6f488dad3a60e549257932bf2e3c0168980902ee2a05d6a4f4ec81c778bbb787674d808b9e2f261e07befbfd1fbf9569aac44755df73a32c61dc6dc1791589ce4bdd77a4d04b54adba12b9720cccb4c532ea76d87ad30a9c96babdbc95e279760ad2416e73492c2f50c8f325a9c6f080338689d2bd2fbee6dd0ac8121fa28b0481c28b0c8efbba71c3c859f272067cb072f5547ba4ce9980109255439c06083172672b6c04e9218fa3051f2c38b040188ed0ad51e3a3fd821fbadb6f22ccf9b150bf966f595e7cdaaeb66b52387b305ed6cb952c77f781c8a31337e1d798a252ec16ccb1bb92bbc5529225ff7e7441d998a363cdf91bea12ba657b1ba93cfabedee765c9c22b06b43d51a273007219f97270f0b486725087602c555399d70ab684e564fed7a721bd410e9baaeeba4d832c7711c77b99b94accc3d911cc771dcb5a15e2b1e55d18b62c87e86803c6f527ae49be74d0a975c1ed9c21df3840f5896e8d01a0a539e1b6a53cb4d13216c34d2b1dcaef4089cb5a864edf814b564664c0400000208f3150000200c0a8703e2803016a792aaba0714800d6e883a72543298c8825190e2208a611808629021c000409031c010e5d4dc0d706260ff91457b5f01353193402f72bab5eb96235f5f397a294e112b7ac4b82985396245f84e0c24aa7e109a93b73c63d6b489fee112f7931643ce8c30a31377d1d37cda4748603df18c3b6247653ab958487a9173ecffd586fea4b6d412a877390f3a96d40f7a847cede324f69557ece127f5f96d9301d9fba4a83a3749dc7338c596ee5f2ce49e5262a6c093b33f7dc3ce808f4efb0889bda4c53f792f12f83143de4b10a4ed154e9c88fdd7cad33f4e42f691a3ffb800206326a15f9500b2080274cfeec312a9f7ebcca958bd8fe7695eddc725f44667b1f4e882207f3f707622f65f234ffb3889dcbf9c3811eb4f945fffa084fd49c7058dd28c276ed6025530e5e9fbf4a7f2096798ba161bddf88fc4557ab614f294b2f2b2f3ef4c3c15eaefde607116ea5501357f2f7aae2846669c96c345c185a29a5e3961214689ff5c35e13631ff2fbb8514458965bdf1d8b2f3b8308c1f38276f0d7b8b05cf9722c0ea8b5102681fe1169a704abb0104bbad057c6483658634b5b6be47b280f48685a2282ca179c57d2cb6d215b34469264b6ba87b0de6a7ba830e33ee2ca624ce9886e5d27d553df0c415eb92304d9b5bc62f4c444f07967e752a884ff55013221a454f4eff02da4aa9ba7c84370a4f996112868f3eda4671c004dd4fb7f69f272d25c214ce3d254001611877a5d9eeea29191994f42805f3c1eaca5d991e392105d2555e6479ecafaf302535071130ce619a59049bf1b6e4f6aef6f6da6a5942468acfa81e30b37052d5955966906e46504ecc2de1a0b1a0749db70ee129a645203ede094b64ef7e5a2321b3496cddc657b5221ebb1e49808a15c43c0312bc214799920bbb27aa906231adae80686041dd6e85cb8c0a04d39872fa33e6f8e8e9a691acfca024e1f9a78223e0eb119870a8ac3b5d7566e6e42bf7286871696b852a230b4d3b7b5663951de0a2283f79bb875139b8fce6919189c02523a9de9235dd02a39269afc5a58a1eb46f02dbd55ae30ebb3367bf5c78dcc217c98b8781963a8b59895fa556b79bbb8e734f48ab2bf5e12fb6ebf34d3de28d3fa53ffbd4089253ad94eb20d25e350887cb8e08c2c7785cd5fada830a2de069bdfde38cffbc7fff618bff057ffc5fa46afa3a9ae6bf198295d5cb0c63683410168ac14287d894195e8106468ddf256181092206e6e017e951178ff5691e9191633e31e6a18161172af2423cdf315a1d4b7c6922d331332079c2c04cd0154cb14943f3ee18988b50604869a570f987d469e92e8be3afe175d6f241df5d37694037a8b9ca764199567cf50ba0fcb55c2f7041586c1b41c0c218a4c2f0a7d276111a6070358eded57b22f90a43c5749ae44d6c508b9be3b011262207a5b039e1de50ada9b8ed35d8c39790db7206e4920fe9214c2c04603efe1ec5c6ba3b54dc7c3ca4d5d87d4d7053515a701d16dec6abcef9556812bc73de79c349883b04e66b01e7a16080b41ae985598c39e3f053fbd6dd30283d77f54ccf9910246215a3631ccb97199a1bdab1be00e8493ff491f6711c633acb037693873ab10708911fe71135dd1472542d2590eb7257bc5dfaa1d4c9a1cc447d525912a06c08f24392d90d648ea8b0dea3f424303278d842d5a8d2e734e1a4610f2c267a0a4257080d297db59f4b9f2cfc44f70138df5f3dd57010498f86cfc9b92eb4f398cb161e11333047502329648e4441636173301411498c9d31633d87fbef2e095e0ccde53b9b91641861502688d790116f5e656c483a859bbb6e8fe5c0099540b4bdd1499b71cc5a82147be4c9379300aec1b336a988800cae1da75f411c226cebebd9b5ab400be7ec19112e22fd4b47c7e91e4f932bacfedb775eeeaea29cf80a8e74a7567adfb2ee552165eda125b5058cb59091ad4c324f6035c6de88c1de8fa94d72080a41629319739e334e6d2d6ebbcfa8d5058bf727c0b9da34c24c30f0230c0b0d8eaab344b3892606778977e5feb0ffd6b4c500e8578c3ddbbb0eb1b6d3c881087b93103a7bf6772a5a66e96a920deddb0ab5a5fa0aa15184dd09dc4b7632ea029cb928a765c737a9b9d3d4b22151a896bd15283c28161039e3720aaeec1308f06b602b390f98532a3c18675545e0f7a95681bd0d2eb3088f8f4420730e5dbc0534b14dce2db93bc648f4dae2cc34ded484d230ab1666ec813264995cb802c24ddda0e081651158e5c6ee28492286508dbddc4e7dd9b7b0f5efefcf113995be1ab8ed9f89ed3ca03775a2211190624b15e3b08ec7d407a54b8695d6c9f8940d4a1c90c0aee91248aa53b14d6c8fe5d7bfc781ab359b29693a40689c71f565f602d5cc60a472bf099559c458bdfe4f7d223641471aae71030e2047c3d00ecb139162fdb66c9abfe19d4bf28f974e6cb841908abdfb42d4a1fd110ad2364411ce60529037fc6c18771b25d4d2e6e354b8561a25f55450964b587232b2128db198119ea2095159ac520a4c14f7212b14b3a1ea1c2262fb18fa5880d9f9971585543d9e1688dac03e4eb66687ce09f397a049426c7f844682ebb3096021e6542541a47ec3999473c463c5a6f2d92cdfcd04c87171e692808504fa1a5fc1b0f89674318a97e13e5bddae94ba3ed93db1651da17b7cecc691c6c1a9128411533e6aaecf69f93a820fa29a7270103145c128a114809765c8ffeda6b2bef4c1453d0ef9b7c0d4548a621013a87797c5676426a0f71c9f0db3e2540d4c730b8abbd97dc03dd2a02930a52a199f40ffff8470048013b64245e629b50b80018878e6effe673ea745c68336e7e202157c7826075b0080bd3874a24c61bec107f218e630743960773a53d676cae0dd7aad12d574c592883492618466180a6afd54045759f386bfb1ac802f8fd2d943478bee47568cace032656645299227b482d91561364095a124f4a83cc0bfae7bd60655768ca744d09fe8f9a9604ea9aa266757e3351c5ba1a1b655559ce7e34aadec251a4ba2c0476b9d4410c986a0f44100ff5b5eca05245afcc5f74cc3dfb28309fe2f164ce35c8d2fea4b497f098f83cc6bec0b459581be27db0a297516a498f6a82d3ce52633beaf8a5f739c9489fc8f733529a8c90fcc042d7bb2c38aff73f6439b5299d4ddc07d9ff94dea18b100095447ce46cbc1ba6c0084f2f09eac00fc807a81bc133ebbb96ab42f79107cc77fbff474d0104fd8564704cc6deb311d351bfb6232564028b8737997fbfb56449d0e984207b58d9347fab5daeac6dd87dc0e9d00057afe654990dcd482646609139915492230dbe39d6de53096f2a6118347633d85d3f26d79daeaa5d78ad596997d5bde0a25e918316799914ff6796ce01fe6f0a275f004edd4a241dc80af1ed34fc4c2561bfe867ac8ab8f4654ca9171c97dbaad7ea293ac4be6893b3ff25eab397956ec1627c07f0266051c74402b6b8e77977d680db5c6d371c9414d3ca47692f002ab27533fd4f210f601a38c0334bd1a803b615767bda68b36523fb2dd1d322285202360b99f6ffc2ffbaa79f403cc06c34a8a8fe22b5b03dbaaef150237026a1abb2aa6e12fd619d76636d5a5c982a5b0d4846059b8bde93c63a399d91eaac6b142f7de254233a886d46d1942bec80142b3a74851a366e40d0afd1524e4f8d2e8d8b7f247f22bb34d771b1f548be48e5baf06d8233895cd3757298a8c19d15fcdfe11cf996fd31eaf325c4c0c539c0a4a595bc941439923fca75991ccd77c0f7f012247d36962c55f5145a53fac608dd88397d51176d92ad534467f4285a13c0ef927eca7b2cd63c1e1f83eb2dabb2308efbd6fc2021b2c2a326fa4bbf7b5ec6d7f1db6430162d7cff8d5d076572f9d5a5d19e53e257540657d985efab09535477f9979870d2a4c6a3b2238c5fc3975bea87ec92808f02eac3e97f3965b3675c50a80684e9421377b1f13d20e555c403900d9d23fa9f980b4e80a96386d21b3c4c8761eaac75913acce754afa2036e9b309a1822ba3e814219229fada09d2cddca00f8116c2abd3a4eb71d60df75c16bbe2ad0ce24ca1420da8020b3ef8bdaca7a6208944c0de4878fea36375cc8b3b091775778f6bb9552e41bc2d33950059bf7a6d3955684262af3b59ca482bcc373718c0b0ff4794b67071f58ea784c207749aa69969a92dfe67061ae67e70d41f193ea35036c6a819e7bac0b1d497de70ec538b4b951be18c2097b169a46e2f68646bd55af3020445321ad404297115bdc8687cd1b48312234ddee4644c43ceb5676cf218b7775ce820042eb6738cdc0092127c9573d12021c5b239ebf423a4369cb37ce538a26d8e97e30a1d57136736a2c1ca3c988e90305ab881baa9fa11e1a3310e1ef92b8a81f3fb3b9023ceafdeefcaa6076e9b0019589638d0c00b9ccb6c6f037f0788ff3808044f1aedea9dd52e5d36c1eed304e59308d2c92c9c0e71a24081f23fd49e452afd583f73f4252447f4cd4d270b5983f5347c4113a35e8e25935031780a05a04bbc897b92f99047aeaf846565bce821137e6e9843267f189704a2ebe197f74c13856b80babe4456e3eb0bfe32b789b80eec042ee18ad9af05c10d0a51d31dc5a825812465952c457bf4bfea39972162261836c588f773815d8649cd1a4ee61b8011c5f2a258a997a1637b1ffff10c8f97c15645b8fa3383999edd4aaa9762afeac55e2d7aca666794deb1f96da447089d3a22069dcc4d286239755b2e97773400934f887c04c54e062c2c030b21045ddab9ab5a836272a6d032952865eeb07a4e61e84ad88f93213d7aacd2841e2c548aa0bd453b5018bff23caf2ba531505dbc4389de4dacc0a2a503fc152d4c5decf8d4a3294fb6b074dce12585d14b4b4474646c48db0e571e5600a233e7977765aa7adc8c9380d3b491911f1cd4d2b88c417d34f02cdb9d7c2b7eb1068f91c56dc51e56e0bf13c5dda27db00207903f9f4a7035bf6c08eb150a9c9c7e419678efbdeef0c79e1e0c536600c5f7fc1c426cd011cff77d199ce9aee8e0fcb8cf22393c98811ff284e07ddf41c36ef582f8303314bdd3c1ea91f08e06a005b48a23498a68b01537cf2771d51459d15cfccc7edf08e3a4e6a31957ea51ba1717fd3dffe3a28b2c11529cf386bed7aa2581ccbb5f155900f9fab6dd4c83b3bca7d0c30e21ed08c2ecd1309194ff02a0afb872371aed068a9178ac0633fa0bcb82145677b56203d425208f250776404a6f1c7b0b13ebd14c3ea5427e8bd3d9a6138c7152a19bc21fe6deee087c84fb7b9d962d8d3e467cd8897aeaa85380f4dc9a274efb50ef97f2f6a6be56a25b4cbfb17e61bcd7bd5ed8bce7e172b0cd0373881041a1119d5c9774ec4ceb4f2783e494ee2b4c89ee29794bca175dd603a1410d811b0cdad5715264c87a0fab6fd15c5a404deb9560c5bfc16eaf7ff0aedc2489d4ce11da09bd98e080517ed66b5d61a741b621e539a0977706fae7ca22f46b5782043eec65b9e05f01114111721865721e817e303a4bc7ac942ac72f2e384e582f8dfb3100630b35f435b06fdb1f4ae58491a4c8f99c58f3f4d5f6b93ee538d93671b3c1befc824f943fbdf056b13465b39fc1f032d2880bd6bc9dc708018b181211732a9a5c62ad70fe1628db9c9d7a7a3962f831605d2311ef627a801ba54cbfb288a396f30abd0dcdbe313ae52d45d8db49450c0cc0b9081ae93a11608962dfb1a0f05525e9628937eb0ddee1701cbb49ea6d0b1ab08fd9a9822e835b34af400d504c9e928c86c68da3066fe5584732f0412055d1cf256a63f14ea3be339c621876f7c80b10be7a078d26b2d6ebe5ad83f7df04e1cc8e2921b02583c2767620b55c66c98b7163ecde3a8adb874f77ef101341b4e3117623de8166aeeb81a2551988b5a20e206bbbb253dc55ddaa1349aeafe38e4e12d305d7aa8ac8102e621b2acf717669091d04d95e2e2687b6f1f6724b4b175460bf608bc5e18efe5e2c1a46eabaa5993d69444b42f11ae0702b0d0cfb5cca75cff19feafa13d426bcc614392d2244691af5526a0572b173911403937a15adc1e802aff7231859947050e48ab06bcd8dc88370ce78f43bb1cc1a8bfd8d66ac220544ea29f50d935d2e2f13a523130ddbdd20c9cd2457d50411a594333ab6f171b6fd1a6da081b1a1022ca590107d3d71f02ec1f128f7c6c80e6e4219363ef0340c1c01f1781138eb342899aa4a0a7bc79bc4179524a19b5910fdfc0e97f82340fc1449290664247a63a41b877fe80b9ad748d15d2ee0d68969b69ee7cbcfb989e96473c2b38f33b92a497f8373600c729e0f46f00945fd2e89ba1531a4963db7f3629dcc7f3abfef5fd9a6d4ffd4fd4e06f8ab1740f8cfab4d390e3fccf8efea50fea9d5095e8097e2f066beebf13d6fe2eef3521ead22fc487605109ad594956e4f7ac29ea8649644a24b56a4594bb8958bd68b19e320fc1f2332f33c544bf30b791998b412547500c1322062a5b7b85755ee23996b9d1cb64df4690e2b27fcda198758d64a9691c3d41d88f4c4b29412a2c79eaaea92dbbb19b88aab40670e176cf15f4430611286f66e00a399f694a965d43297121009e46b951bbb8884334af756771b775702b1c6db2567eaba538ad84decac4e4021953b3771eb32ed6e1fb888b492af55b8aac480f44f94028aa2246d09b77af9dd25f7ba58722d8b71a02c92b9fcc845d1fb5096edc932416d4ce73fe38e5ab1df440bd291e7f8e1da84b627922eabe4b4aa8540a995bf202fd2577764338abc89f522548b0b3d55b0bd8675c62194896225e3160504f1def1701954f67fb2dcd7ba4defb9b1e706b7cfa5267f546a62cb3c3c02216d1d3e7a63b4c604bd85c8b285698f643eb3f312f7f7796e6d0b185bc336ddae5aa45d0a3d66b2b9840b7d34c840f0a32c7bf733da87f0304adbf78445c61d476699f4a8f4165a0b0acbb6ad3970622528de8364a4e5b7c48c41eb452470bf72aba91de15ffad2b8e444dcc07594e94d90d55ba4c95a8c9db74eef8e8a5b764da7ebb8a910cc5955b93bb29a7ec2c7b34bc0d951b8f2475f8a33c6406b54db773e32774c1d2b7d2d4271c1581ba57c74f6d9f4d14899f1267884ada9c662e5195b8051c9a3a00505d09981d4947b892da7d42a9351c3de283e64d455956ed8fec1de09737293e790f9ac85846fd674be46d0560bf069359336283ab31494b922e58030ad4d2aa0fc751fde9c1c5afb91c2477145d44595ae1503cec8f6e2130816ee626ca53a5827fe4c49ce089e07f2c2d26d7d254ed6748c377c70169506ae8e6030bd04060f6201f307619290c67c71056d84a4ab7b07f80942c5ca85c43beb94a7f51dd03a4d13d24772c00868bb3b90c75b4daa61112a182aecc2ae4f63150074baf3b7c9aafc3507d845111644f0700718220a1028f708d4d947ffda1af51dc12a0b497359d95fc33d5b213fd623049973be0d3dc02256eaefe5fc4c946597417a0403e5017e54294342f0ad210c711c4097e15aa59a99fd56e26dd130945340ebe397ade5f1171ed7f10e86e734f2c60cf9fdf7de45e1b0c65b3ea8bb2e53ce8508546f2c32538065a7dc68851ae68e2ea2b20668adc945a403ad1d6a21ab2aba6ba8980e76a86b250b531db5fb4b6a40dae8cd585ca9eb2b88fdd95296e2b02ff5fee79f1f558aee4050aed2830e5588a1628e5fabae61e9097e6de01a211e911ee6f01d8acb6e1f9d30c65bab127cc3609c25d7ca25474de1ce796d9734e221a564aed581a8c5f37e9b3608afc6608053a077ba96a59bb5d0021aabac3a2457a741a88d9e0e5ac9af6b297c3e90ad1031a17bf44eea3a040548359b230c4067364969e88e0c284d60d470810a422290279008237a2d337ef74d99d098fce2ef3c04c2e589c056fd6abfbeda44242399835e8cbf0b4d3742337c542f289ddf4f93c4e6b6b9f25fc59be0f9d2c5ac6ed7aca79ffa9f5f04d3fde83b72807b63700fa7f17bbe835078edec3724df0e3c2998b6a3ee8c9323529b4cfabc9b47c288bc1585933152cc3196273747b9ce6408f43ce3e91352ddaca186e7955d2ed0afa0c443e15a888c3d032d627e6b8078aac7777ccdd55248452b9c9f50b5b03bbccc3cd02cc2deacf20929b235e11c27e6562d4b9d8393140e837a06916caf876c464a44c6a43f3a506b5e18ded26995dc95483d60ac94a87c1196d7644e3079dfe3d927a3512ca3fd70a5b2d292a70552cc5b8d4111dada812e9c205fc13467e0e9961084e10bbb16328113e2e519c68dc9c3e5bd3c45d5e4da7a80f6ad432be1486ca5af16522e4876483b65b57a4cf7a93320d9fcc512015c5d89386018a4f66e6328c17918e09ade1be41b10b47eef91759db823609a6e92ccd37e7b95591215b4b17101546cb63cabdbff11e7786d3210c763c2efb80145b0765463f46807bc1612d8a99a8755b4fb54b26bc70323631570cbfc9aec314fed8f55f4263db481f3ab79349b8a94068b821e27f2c762a8e61a693f1b101b417726ea68bb218e66eb6c2c106d382e58c7e78f30167e96e5029388232956815d44797f19eb690bb07932721751a41ea49e9391561f0f2368742964d7d0d5144b3a6b3a7efce558865ec294b57e1f8009c4b0c9e27847bce12f763300c60ee428ebba9727921edd9958c2edfcb54c51d010b25779ec3226c352267ea47c460636ffcd8d62ce21b08eca8603d179b50c6d3b021f28934497f8cdc6a9734a2bb1771e99ffa270d499738f4794ae1b301d680f669eb4dc7b18d9db3987e7b6b2d24838aa84db0b0ef488f724249d2c1f2087c1eff68b69349909ae74a1f0ac010b0b002dfcd5550dca050873620c2faf1193a8983d4151bc08886a1b776f3bd4d18e451b6e8863847d95cce003f3ba8df3d933fb9743fe02a69e0f2d171d530c0404f0c9ca3d44646708255cbcad64e0ab3c1d822121735b2a87ffa17e29d18b37cc3a226af691bee67235d981802e536077c87c573f1db45e0509140e9d1f62dcadc364f01798e484f555f86abda2c29704072943e9c212f7d0929462bacfbd4b2cc2ee37508c0615490ef8f408e705f3de00d2206c7b7aa815edd6c58ac5c2e564063049c1f82fd9a9553a07c7be444c030f445fc701c33e5b594408b7ee3e7da152baac3d04f13a3f9026dbaac3576541b185998c67a7e8f594f7d39ae0e94bcd6dd0f7721f88f3ccfc5083409b058c92c3984b5be2b408801574322666288a34ae269e104e3f8cf555ec08271b1bd5b35a27019b13c4cf8d4f361063989c1934c07e5d9a70de5393c6e408e62a9e0b0225eaba0ad49149b3e9a50668b408f7156568e4446994cac90fbdcce2b0c35759709644eec8526f3f0d2d0351f4c640b319379a5dbca78ecda153ad7f2047b3ac1f3cd9d8985fc71e1433839462fd7fee7ba34f04c3ad35ef71207bfe3396c67bf28a876980441a7b906980a6cf29eb0ed23041d0b64ff51dc543d44ba34c5ee73c858792315c542d8a55887234c594d35e341a21c85e5d34d6a629528852c3e2e50b05008dbb44f39394898b161dc72a6dd5ef020817cb9ecf811d1e743ee521f9cdaab7c8ac822eeff5df003e19e302744b79fa3d7d4f3fc11a186c2b6e79c1de282249b28f259e0f8481457836d8e3770625fabfcf4cf394f8ead59d01d7042faf3c80a840fbabf65f7dc81350fa9d8fa3ddc517c5bf8c0caf98054a54a7b85da70a14e4c10f7103834a19d9694963d9427e004788b1b344f0142dc54b95ffc7dbd304eb0184386cd80d5a468bf27c8b2d846ae5e7eb2d9f5802b94586cba55dc40e00266430c55435b8ad150464c5e0878f059b5d7919bc1e94354b62d4c5acaf5f36cbbf49064846e19c1161aa2b88d10374db65dde4e0da061f14eac6b1a6eeb3aaee45cdf9404f21e29d84bc55ac26d86115f37173ecf0534a26bcd89b5862f4882fcd12b4e2f21b0cf59b1b8237645ef8684163f8971d5ea20402629cd2b55488619ae541b9ef401106e1146d9076af9e00baf4a503319acb542d660a49d99631e58486845bc66fa585e5046f81713130b63dfadce514364abc255a71e9362402ff8b73ea0af2b2af4591d245fd77583939b2e094957108108a1e47c8d314043c0d68aff62e50d578141942d6a089b566eccbff7a36083651c792bf7d6b5e10533b9dd64e83aef1e24021944c2a4b4379dd6960695c3f2fa0025564d243b611024615a2069d68d3bb6239650debe0773597002508f7e3e69358832f4784b99ad67699768ff32c3461216f8c11e13c28104903791967cd7c41cd36a4b307388135f19ecd68630b7ae5fc1a048897ca885fe1a313fe4de14f3a67050a6b6c213dd236ea401b67279f2edbb509a106a018e4d610a0015c8ce9b10a7b87bd88fb0fd8c9ce1b6edcdbf7779c13b6332758f7f62c0e8b8645ca84e0e4779cf11b47c90ecd8c1864669e35a8b4951a87f8088c14d46d0a8a61a736b676bc7d9ff39691168fbf4bdb2d76ed900d66b6f085583a9db7eaffa83f9a858ef53897a4e98fb0274f107a1151a3c36910002dd324ea9c0929542f1af2f16779c9d1b957164db25e0163ce2c6008cd3ffb1c39a60eac7812caeccd2262f5a01af84674eb246c05356587c51e0c917b6fda2378c57a38366fe34acd711c9484090e3dc4e62b02d2c506a86c1ea371e5059431684849245a634663d7e2916d5cb18c196be35620fef886ce8aba3a8c5bc68136668216d4236dbe9d357cea77e1412e1bdc069003127afb2436908c96cad7f64b02a435b32b9c5092666942b3a190f4ed623599f30646169d219b1c0ba3303311a99ec740991b359c29bbe4ced9da9611d6be4335418e597c0f460d0ebb688e1cd80eaca8e19d05485308b5403b4f01f2e14894e444c558842deac5d014cf2f363e28d18fd82b1fd19081634e7ce84332ad0a650624812ab776968d3f2eafa0c74ba55a82cdc105294b994ea55029604f9d6a7c7835ecb650a9be61cd184bf97a051c894295aaf0e96074f7733ae4bca8b11b6a3f95beb5f8f4aa40a3c356acb66fe38f8f9d50e411656f1dd8ca9bd8da8043ef486cf31ae1ce6fd092c0f5161e2446b84773a07902575ddcb2f58b0e509cc7ecdef102d52bc3d1cf0035c626ec9bfd17d50f653e22509aa0edb5ccb7382140f624d0b98481cffab2bdd8b38c37bed88c54d91fcd63607944d9762e303df4ccab23765ade1930abbbdb911c1c6fed43cb22a541a7e2bb7c27f30ef96e440548880278398c9fd11c2a24ad2301309fc4d15e2c699b67f9ae75a834c371ad7abc88adea2e2b3929326e34f46a72f8bc34a72eef20db44b0a37ad8f4f41396be483cfb7c91d80a1feec66d11b878a4e98b90e8846f30d43f384e1df10190947d3cf57c66c00f613cd303f20c6968a4ce8ad4edd159b8b544477da2117ccc0ce2c16686404491a1c0ce065e00e27c0e43424b32c3e4c2e128ab69b53b309f4e72cc4616bbd76da5a3f78ea99e0811e0447b4b228dcbfbea3ee47e78be9fa2d958845c8da27cba46b67f94d6e2763759ea54ac94c06ba27b16ab6d24be11583a8a9efa0a4a0343a2d3b307a713460791db00827c6874107153271c42f5e05938636b4814ac0c7d008a304ca11a7fb6108f4f37e3863fb69b3a90e39e2679fe6f009a49ffe19617ec4457675b27d11a2f1bc071cb0ad81a14bd3130164a89a063fb818f2fcf218a66f2a1390f7ed5d05f275391213076274bf8b273ae67f1b47f72675c4fc57ac04cde9b6fe06ba5b5651bbccd5628eda10f262dac0e8345fe143bbfc557c4c7c03e6ef4a8875481bc6587b4d99943b0b65ebc9c222a18e809e17ca7785f67122b2b28774057308bd1eaa8052acdc4a954a9d389d488dec20f29fc5459901087a507b015d3ba534aa69551a96ca675cccfe2f95e4714dcdd864b676e41939beaa826c5338dfd55999184a52f7b3d48d10f546b72657c61b660448077e92ee72646f3a33f2aaa5b07ca8b80ef8ee6f6cc630f58cd420c38aa721f83973d19130a01d65d796ea8844ee45482e96804b10ab2049a83065fa8545e9f60a0a120c494b6d0d9829595ab1b0d5b6355c8a534f3333a40a81c48c33439279a830684dc2ccebdd80381d57d35907515735d13c4025b9d807eadec8170fdcc12407a58a14102e6babb6da44527a4f83d6a2c60a2dcced62254b80fec2200b48e6b136edca9102bcb75782b72f750d100179facc9d89ff869bb4616876c5d02c12c0798050c821665d23a6094266a1310411072b90ed2a9c74dfad18d44db88fec2b81859c2698e6d8ff0ae08a2703494ee48a672862b2af3e2c5a9a478c8978aa5746fffee24e3b495edd86f49fbee27e190e32eaebfb9fa20914d5963448dfb0ed75e5954039cdfda3f2d777f14face466d2a52bda32238862e830e00726e46f9a922e09c47ed18c9ac42db1ac1917ce5000886f53da6a09b9b49212f050543da6e73814213f53207b3a8a2f827e67b9d841fe64f7878f2d4b84cde1a7aae5b83612605bec0b9a9a5d7b4c258a560337a7e2b6c66b64b3b8fd997cff4b7c585c3dd114554479171838b87ebc2a0c2abdb5fb99b9ec720c27198a26dffcee1cb3212b63763332ed2d8bd485333138a36e27570c7a0d4c247e1ea8ffe0f72696d00bff2c9a9799781a9c060c22753c1ced45d4970bbfcf93fb36771e5f67bc557c0aed8151015b64904189d5132361f84387f6b9fe3f11b8758e4cd19f0182fe352f91af0ecc955cf727d71e3d5c1233c742634be5a756b0db1361735a815640a8d34872914511d28660514a19fd226aa727dae1ccc36a4e632a337d123455d2242ddfc9ce4272c9aa5b26a16652558855558685665912c8445586b5665d5ac9555b0082b3959c9f6f3a0e891083a50fd3058cf94756b55b9eeb858fd8088183b337a020620fc80b6bf1617fb59462bfcae40120d66f48ffbd7db68794af9005306874c041f556de61a31133cd4a2edd5a2e369f2e70b283d92780b523cbb476ac28301c31e4dad30a706452369c70ca455bcee55cd9cab3709d969c8e4d4947f2a7d4f9c37918afdd3ee9abd2dea98268ba0a2d164a1432a4f1b1523937cedbd6ca26a414db7e857da819cab69d849d349676227350b9730d51bce649e55add7e7531e08f087fa59a39415f32e8a680e7e05aea4bbf55969d0dfb5d80e2b95e28668cc84a522c523ac81632a1680898168ef664a1150c7e3e3a07a5d1310e0a62a4d95fd781a67079794facc8377fab8a1057f5ed7e8033255388a595df426ac8f0d20ec1960340b98a3fe1fe4e9bdf999194f0320d82a82f93e52a689cddceac55b0464526d47c199cf1290802177eeff399323fe3660a507b8c110818635a162115bdb3f0750f1b04b74877b57b25b76902f05d6b44b13790b718b3e02839709b014341b14faa859c1e2a68073cf0ac772e24c385c2c846468d4e9ea9e78cd74028f3c5470c415004d1614069d8546eb56db0c549b5d1b8cd8e2bd3137c6cc82c8e748b4e942aa5f4dea2d93fb507601e7ba29605040da08a4bd2c7f7f1d99d230d18e375aa1bc8dc014029826f01f11f8971eab3d2b43c468ee67fbbe4634601348e813357ded76c3edd87da05c8400d63424d83dd190e0a085300cb9fd856812d2e33ba30f9d8ad06c40115ab22259cec048904f0b125988e574a0c6de06cda6595e864bc0c68836a3aa81bc4220c3c9d2bce17b64a9da6e3231b81e9e069f4741e304e6010bf4210c00d74adffdb43dc0c5e3a04d49a8000dc8a1d12db83a25423c27cdaf74920b57946ba092e931d1683ca2609fb5ffb641ec17a6a353dceaa78549a1d8058fc56e383b8068dddd4d20a6a351b3fe072288bf12566bcc86976e1e3519a9496e29a526a3bfeecf3c84821244600ec8d76f04f06329d62489948f20722494dec29a1bd4aeeeb34550d91717fc2014fb1804222e95f7892d7e3b36c1da9c3c95841460d0e0319bf9f8d8dc737724e8e241d848dcca03fda06f84135539f33928490aa7efcd4ba2a3d456c314c039a759c38c019c739cfdf17b31f4f3f901712a871cda2229ef2406d7ee6569bdabc1a7edf4f80e88c138e6b9f34f08afda467bd780ab8f00a95cb42dcb54c6993b08cfdc956d0dcc0f46e426773042c45fbc0f222a89aaeb9f729f360b2d8f5a7f00a15b31d2ecc6167c3bf2710032e2c486bd516bd6fdf66d8e175f8255dc29ebceef1e2f0b4f6f5d63b3ebcda02596be5260e31ded6a6ec2c1d288a74250b12fb90fd3fb137c779484eb7268af1afe045bc6a7f0c529eb505182786a2e44a7c608099513b5418364e9418bc87ddd4d7cf4c225c119b14210d9baa5bae677848136941be63a9c7021478a0a0d7b427745717262a922c60124a6ae045262b0d9570c96e46c62a04b9736c865621a1773ed5b43101a3c1ff00974630268524d185116e52248702969dfe20579c4a5f6300c6e4f74e247b7cd9e241815585a05653c10fda5465ab362c59ab9e26fd5e2a00b3a20abce27f41b2994894e69cf0931bc8cf5cb35f55bd189b211d6d5bcd9c7c1e57c0ed6968e36ee1b36ca4179abeac3d2a30c2407302592e472bdda290bb6074b39ac6ec0253e460ce9e3e939041ba1572c71a7487b699720efb0bae8b945a86327dea1dc8ce912735b71ea6aed1f18d5c50711e464fd17ac92ec738c969d87ae6a8a2ec46ca7961e000c855b34584e81e5463af3f4ecb6328e9617b08502839d8b92c080d87b6ce602b0994aacb5f5b11691dfaab00226dcba927132ae824429fd95c34ed013da54f4c6b42642db3e446ec946f8d1b12d2e6c00ea460a650f8e5a124fddbe54a415af7b77d66b01720f15d332546cd58bca89999359e95f31b28e14633cdd4305f5a565dd513363695726aeb59fb6d8c1b65dd94958df032db9f52f1a93fdc0bb28dae400298d27b398885ad9a51b5d629b4344508e05ae24a0b84ceeef2c90ad5550e59b00d3ddb9372dd2b8bce06cb056f62d283b3f9867faa0ccd56b1dc93bfa13f68d630201b9e2f7c740a2985b8b4fbc85caf6f99b00cef2f51b43685c5b4f5f7981b809f627f84b2cd5292de93a40be40f077505e0036c13d353e1dbb42bd042bf9985db89552f6644e724c6ee692c37375f4a24168d46ae71432a9eacd5f09a2d3b873af465e316c2341adf5a862a5da4a31133010971ab1efd5520fa7e1a0017e7cbcbb41a206436fcd3f789e3628d96c72dcb0246fffb65e3d8c8817538d403f84fee7871a6bc2f9b0f0d164f60e97d3da993654e2882ed35b76d7b1da6384d36b1f0a685ca9e69bb7d32e287aa6df96a7058fa846a1ad293c8a5db204bd76566ea358260a9d9627203e0c625701b75ff4f15422e2254c7da2fc6e94247a3bc7b05660f41dfe23a39468cb513bd83d4b31ef9da9d6c51f4d25d9a67b5f4cdb82f7493feb6bd10c540df3eb119304bdc5b16ddf6fd49d165cd2f945557ee93f4bd4231407a71d7c94f41d1bcf02dc371478b5ffa0b878a43834cf1d7fe148b783b4b0b06baac24b873af98d9747921fe0e944900f3e5060cb8b1ffd0d126aad74bd19601995f73012b0a8fd6c095190d21eb99f22e05cf396a6169af5faf5f503613a1191a90cde5a1d5eb31d74938b3cadb2c598d9d62098d9037af00319f3aaa5d724c8494c980def30a1b03b34030f13a818b87c3080f9366e98eeae094c475fb58cfdc7b5b05d3998e69ad369f9a3be1f9948431299d590d9802e50e52ea3f39074da5cabf27c87a473e7fc41cfc0a0658c059dc033b4f7c5147518325b1160b6013b710cd0195c0cb7024e082b882d812d409f538d9a826d24c5123c36528afbe35b5a4b7291caaf97886d60d7309bab5060bce3b18211c1414a2fc5343f4b24024ba545b1c05b15b72df389d98fc6e3b311002546ca9ff49bd534dc74ba3b07dc73187beeb8f34a49ef0a86c984e67ad53a0805bb89f9355c6cf0633ac7e44e4504dbf2a2be1a715eadbbf5db2511a28cb34d347095e23f85302c36f1ffa3dfa17e428ff49f6c6b9a9d2fe5eef7ce23697930e21939f58613128efce3fff14775c78d14e599901365df12e866e580d5966933d9042d4023870c66aa6439a71364f870889d1cedfa0fb435787d40a0b42c59ce70dc487de167feda34ebf795d6e28099f1caa5a4d46ac735a46f2a40e720386cdc64dde45c508fb06075867f3f443cb0a34e05a97b92805bd5d216e4cfbe9f877437d6c3cc83fbaa0f39a4b42776da9f2c1197c323a30d56e9efb0f4a651a90dc773a6e0b68a87b31ad347ce64e1adda2d54564de07955b8dac56bdbec7d2c00e69e01808699eb37e20bdff9374a433f72c6310bc906628a7f55a15281c79e92858610547bae175b4edfa5bec9e0e9496fd639dfa55a8bcdd3b31edb734e17b46b2b1019308cf11f7210c0d6a057ad2502c4bbf84979ecc3676a8796006e5e2226792613ad16c4198f8e490e7db63cd715775f470f32f4c3fdcee4d7e1483916048a489af240802fca246197076069886c3007e86ea18a684d60078939631148a483b29ff60bee085cdf1f837dd7607f54b3a7b6bcfd945b27231831f078f55167b83c05dc50532a0518c598d8c074f5407086a7a5296f292291555eae7f944fe816d4180db56f3c640cf901890735e81be51f6af43e1ea725089b1953049fc4860d970197b4a5968120aa5ede49b432e9e782e9220972fb13caba22a0efa66e4e2fb92a537fe4c1d20b5067b868377cc4a3ffb1a739e67aa4c5c7e5846e4610f4de5cc703b425813cb706ca16789115473b2b3f418a116f5b3e089accd8ed7bb80609378dff2866983f887d9662c8aed5cc359b4d53d5e0cdbd475453d02a1430bc71dce10926368498b136b7d3eed49ff1a9307ba1b34a552c17faca45fd6ce3e8245e023cd4d9e44c789be7895ee88ac38a196c0deb35b24f16e75ea46785f4137d3a49a69f83ece72f0458b1a322e86342bd6ec13328ad9854ed11d1189c6d3537c638db48047bdc6b49e3915b41d9e4b0f417c35bd6061acb3191cb07b96d9a3a4175ac2d367463b755cb69588194a45f10110e8a28d1dc1acb4590daa651df53ee7fd94c5f744684800e29160c8a15c712897d473fdf3868aea719c4334387d60da3624cb2b0000be220cc9b921af1a398d8087fe89c500ea4310d94dab04132dd11044e91180042aa98c8ef666c58bb8e30612301ef14424b00d0243a4a1b3af5755eb51c77731f0e0eeea3a29962777f4e14535f7a1a7db917883773b769d12a67dc7f5a082968d6ec8c3ccabf3e1e5e6c72d6d6de95383c643f3b03fe3f3d1b3fdff1e507f24fc53928f73984d3c64176a6fed794534cda6a2477a4953daad7a03b0bd388fccedd554708716091e22b625cfd358511f79c734047ffb3c5d85409301536617427d2c9fe284de94525a8e214ff0e09c9c42853ff38eebce5ca6d660c7f59e4282cfe507084b7f165a8ee96937fe139c13896c1f207bdd8e981d6b10ac191ee37fe26bccf5b9601894a24f1fcfdf851ab670bbf690540c3c483710897bfa16f1974de8c624bb650dbc443164de8e333d62afd001550a2edca75dc50c1095f7109dfac5612618b06422d39b5b37f71e8bf67af784f6154221b4b389857292214ce13c68888c42427a06559328018d7ba726ccb6a1ea3e8692bf164559d77423e78e12a311e5f6c2e2542fa9e45bf04c9670125964681b741791e881aeb16c2d4644d2c65c105ed2e4c5128d455841de464fd072134c7bdcc91beb0a9c9f1e48133712117d6b3ab02a63340c01fb14a47401a8a15a8aa0a286527a34eb9d52880296385114da50c5116994021a80176b023686943fa827325d177ab001383fe8d99801f278acd5f022ca48157fb6e4c2376c0bf7a7c91282cbcf62247029dd9d742cf3937193ab474e65d13fac34bd6fee7dd5322840f00e6b0f18e7f889807668aa78e68bfc2e776cd2e6ded48510d88128a9502fe2020f677164058214d30908634db3b07adeed1b0004c3d9ddeea1e05c98dae9a272f8450960ac2cd6600cd226d63744d2032aee2c8fed717ba313be245405d5b1bffce4bfb8d2998a0c3529c368933f0af1bc9a8abf6a9e350c3994621591e34383ceae760502151e5c4a6eed8e04f5c3a67d7ac7d2c1d703db137867a7ce908f795ae810ae7e55b79f289db12cfe5119853a5427e2156a07163c582505cfa024879ea0866e388cda5a0b2ed22229dc419cf0675bd3c8716b761f57c45c90665d6e5163a3da771ea99a0464337e649caf0a89b060dd866033f0e84370ce1ce307b0ffe811a7263b0da653264a6d87a8de247a1782e8dad6eafe8261beb112257dac393970d0a2a97c5dfab939e2c43f0776bdf6e43bad90ff7cd188f42571ce4f54e04321def431c1631bd77ec3e31061083179d750321ef0221468a6df6ad20e2587bfdf8c7ea2f13e82065c30e2131cd32a1f98773f0cd06f6d28e1f27e3b37b924115e86696066425402d2383dfbdf110274360cebcd6bd804e107dd54ba9dbdfce209637eba6c0ff0b47f68c48906baaaf1cea9efa819b0a5f4caa1eb2e4ab3fdfb6a5e945fb9b5bd852de0d305495c8a2eacfee5981d1a589891cab2865a3961811ed9331165c579e26c1ac2edf1464b63ee34fca824fc44659423482f2eb454293bfeb270dd5bd0054eb27e8fb6257879421174947ebae70426d9d4d7f16906216bff4ed5d69045f40c0ac059d35714c57a6847c4505c020499d7e99b2af48b60b4bbbbb7f68518fa631b01632392e079964ff95c59f2b52eff8478c073e9fd8ff542344172fb9c4a7338b2c4bf0a4543f6c0683f6e71a3bd1751c51069eb301f8a7be5f8c4c498344b9683e3f04b9145f285a180287fd1e9a7717b671cebb2dcd547f3c4e5c47151a6b2f9c540cdbbba991c0890027aa96270c82fcf901a66a33b76e131fdd9c37cbe35d8cd8a97f16a059f8cffd68851edc82661673d951f26150970d71f6bafc6dbf5134bddc4974d5055432435d494ce93f9783be480e7fcef2ed455eb2daf491489a54da84ed55227cf43c512062fa6b8d94bd41557f053c6b5c2c2cbc77c8850ed691f103019793d97ae2374c4230af2d19b80412c3cdbc19f3c1de91f254cce6fd881580d715352824949a91cc6264410a5145da6b738e0863b6d04838668b425b72e11382a207281acc75d0130ca7c04158e5df41bd42cc42f318a87033a9ce491f40926fba1c98b3ffebb564a10acb14ac6cf8ed0502b627fd4e5f3204a0f1678543dad9d70378ef98591dccb0a420b6d798c99d1acca4d7f77101533c5052858aee07c77d33582cd193401b15cc8aead73f90cf9863b2715fc292a134372f38906deb69bea2d588af36c13e2bd5594d18ed78c87fbb4f94f1af3e832d5342bb4eb584308dbbe412eef14921deb821acda3d9d7a03324118583b0b0dab45a0b1d214473c1684a9e5fcb2ce57701f4af09cce560b6499c94af4c614f8541ff50309081f575c4404a2444bd4b1881ff46a09b805f2b145821a227c10fe75dbd9db94112d70cb3e14d6c854d261499e18908477d99b7af1a55da726ef8951f9090cc5947c989c80a31a231840226cc0827f2996ab29aa22f59fc73ceea11eed2cf1101f8782b56c4d013b408c41eebcdd7ec81601a8d951d63fe2bbf59cda994004144cc23a984d28b8cef7cfed3c7751ce32d6ca48b95ce9f1196feaeacc19b915ab5f8b960c45ecf6dd0e58837b80263d78a6ab2aa00bef5cbc809e1fb4278a13894764d4a2dc8ac8459d259baff7e8403d01355b9d4f616afc9ce3813fe3ea9391a288e9752b8dfe92215118cae223dbfa6e935cd4ca6e836628eecd5ea9c24706fb082399becb88409d7c172ede8e5074e5cfa78ab9fa7c6707f7db6c69d8e7815573805ac21bd0a8743dd0f007bde6e7fab7f8a4685a7caba5f603dab0db13b4035344aa340e914091c185f500779c22efed705cb93202fe5cca5605e68d16ee750bfe8777c7ff098f9b778270ce008467fb7058d520c7a433afac95f739d1e307c110a7fdf19d1a0ba8ac9420edbebc9fdf4060e5d18125f57158d912f9a0d6e914642f044bb8299868be9de3df04d14430416d307041bf24b5072252f08fc8d0f45dd7010a7ae09f8f23f3e2affe39f3c44332914dbf1e8bea7d4a4d6dbcc792e3b220a17fdf39aedd750b71383aae5856c52a9018432cd15559a880d93e12903436b69cd1af00a7ed57e0f3f19522cb6f5636775fee4a1680a32632e1a750bfe9543275dbbfdbbae0568e42f448e030375c740af046ea408f7bcb82852ee77c21ad914edd38e729bd013ce1c3a4773f4b8af016ec37753ec253f9936d59eb28a900739e9a639425c8b011bb0ce0c9a0199a6845e014ebfdef6dcac4852c920f3a7f3b6a20aea23fa1d29aa53bcf9a69d475f79f08a115898badd78a224efc19183f792f60e75ac0ff7961ea7f6aba874719b555c6054ec381279be809147cef8839da7684fbc065a9f61607b20cad8ce14587608fec75d5e0b82b6fa131f4c861bf896ba900dc55c8a137985cc229d8f199a9be3a725197de1bcd1158f8b0fc4ec03b551ac902cf8ae3e4e25063abedc2a9cf863922e45586d9c3d6658d1b296e186b74e76eaf3a85dab982e870f266c23f7a3f22c2aabc49e3f3bf1fd33c2bebf10db76f3ecca3552d4b3e77a9720bffdeeed4928fe3e7cf8f9f7f9f90a46f17c2b391ce3e34b11fa1ceec4e781a62f1c3b093bf96b18e911ae083c2715d915c16d329375ab44f4d3778e6c24d0edf87daa1f20ca1becd01fceb7ac91fc09af4cbfc076f8e0ce7b42898c515031716e8a5d35670408b740dc29654f3446ee0bf197dde4a9303d6a78ba3b783eb8a0e87d10487a8ac379baaeaeb194f26636c4ea70ea37686aa376c1b0918b581682382b39b26082a329020c0c6635e1d2c0d7c80c057b400fa9b6dc86ad127b5277f26da39651a25096427f572ffa5bb1ff3f52d3016378d916ef935ea52a98453b53d9972d2051d5c04988cb08b42c3e649c1cd7d1c10f7f5e79efcb4f6b69ec02cf8a21fc7f8bfdc3c9910f96ea41442091056f5c5ac1f4951bc0b2ad2fc80565f14d262916a1c58d79087d55abf61b9ac9b0435965695f20995efbf450317d042859bf21b840e9e522a20035dca400b5abbc90c59064a8e688b54469affa062899d7ab67c68154ff8f406b38622c33312a1ffe0d77d99009db6240469d5164b7e65956dc22564e89fb88cf4cb1cd282a05f13f3523fa35b06ee879b6b898c4284f9144e862ce238eb9162ac26124c133dbf1a8fb22b97566d758f3e214299c6e2d7dd4a38d3c311f06bf2333d31b61be386dbcb3c03f3e524ad76e7bfb22be1bf56f19d77cb0e5a0d79f37bb460329ad4e66fcaf8bec80b973eb28c3d569cc518594c6bf7c2d272801bc72bf1d1208b02145313c64970a019cd27d999fca967c7aa7711e1c71f6530642cacaa06085982e919a06fb1af2bbc335b25262db643c595384a87c4ee2cef5e5b8d04fde0dd3262b347f63eec0ba4c00ffe75558a01bd1eafb40eaa8fb5e76f1bbb682bdcde41f581df5079b073aed5be5cec3166503ca682c4b29174111aab6c0b7e4a7ade59315cbce7a83881466f7adb76a1b2e8dc3755442287b9082e555b2e267595e56830990e4bf41a657d074b5918faa805ddbdb7108424eda1631d2dddf337f041fd65261170c3aea291e72c0c9583f4775ac233e2342ba893f5ba4315e03876a0b360f35da77545ddfc0eaf5ba9ddfb08b2f71b16aa6dd8f4185b73e8bb82946ccb7512e0202d4fc8380c065fea9da78907ba4abf92beef83987735d3a6b9b4f38f19c831c1a134c054aa57d350ec2e6a799d8e82144e386c898db017cb2caf7bbdbdf6015ed00ad80b8e665180cd50efa5b1932c8334d76284c63079a4082179bb40053628ef211be8a28ba003bb5955a0942c9eaabe127b1bcdb2b014aa313cc4a8d11ccba1025157789af29f744bd96b209265ca034df9aa6e1abf7fba4024413a9d8c0b4ab2a4d2c8b820254dca1a19094ef0a4ae9921c1049dd4fa191688404813ed0c0589540b70fd5981649e54741910a44c49572723c19924757d06085210d2d788a0a31aa1ebcf0520f3a4a3c9d0094cca7e438a4c82806633a5f50de215029823d82f71576712901f16e0f46c662ce85fb06cbf3f50f45a7d6957c58af170410102746f9fcc0df0d981dca0bbd75ac8c5f15ccdd578408d248729dc8540a6da6aff5d7d069b41c6dad7749e0f4ee013f5357021985782bab1374b46c692643ea77516b4debe46a7b4261f66534e663800d4d07a1d8be001733b2c00d6d7e33d619a8814aafd26c7a8155e5b668dcc1b9abcda37fac0007e43be17a7798b28ffeecd78f81fd4574fa153e633a97b2be3384f8d44402f3cc8d4784ceef1eb7b8ff771dc6818a088444e10ca150a00d779101abec79602c4f378241f7c544c6549121975afa583140340b87e2b5dab2049b9caa8c5a6416e73bc4fe519ce4a9788b685a39fcb124745cfbdf74cabc41f776c63a4b7ca2fc81ab7a1adc6e6d199792b8413ca339f4043fc9f1accb597b90d485440472a3ce035af456f0dd8e25514e48fb78f738486aaca74251147d6193b834fa46fcc48da746e5fcb50ae9bebb848b71243547094d694ad94b6de293e37488ccb1647a899ce6eec15fda3ad152d38a3ac7e137b80d8ca748580addd78d7d17b0f9849103e3fda63192e7b3f8b2c07bcd34c4f860a0418993ba1af811940750a94554b9840937a39adbb742ebe036618cf873439eee490f383b838279a6a9c3be0ec6d853916e3141e0256f414c5984e844ea9ae23eb1f05bef84de1adde0a3c0aa4388c2c10a0837436afd56201b497c9661e344110d019e5fe96d19f4163d78e36b532335f82197b3b14df347e0427013223c8164205551d9696a2e6d105b372f250235285a4227d9cc0136b1b30801ed4e0a94b4166de14ff59c5df4f5d13544496705566105a48477ab1a931962ebbd69fd2c1fda14cb523a817ee8d9002b447158f834de0caa7218ca841ba1f0d27891d431964e090e96f7cd195577bc571f3ca4c3b2996ec30e33fa707a6768115f41af0cb8106c2d899d75db120be8579e514199a1b40e57d67f58093cdfe070cc14cb6cb28703fd2492918b454e308b1637980307175e527160cc9c92752e1e3d712ec7218df11723b2646931f7c313e13c305d1caeec7bb86172071bcb55f3e805bc5987a9fd0edeea1029ac4f40d851de0c80f1cd8191d141980110fa1aa130a14ceb8d9c0754190a1de6536c6968e4f7a32833af9342cd0ea99180ebeceb01505d8facf61d69b005518a1f2fe771aa72b8b747d0d80d0088119707d43bc0fa33b6263c83f636e46580ffd1be6627b00f7ebca80aa4652fd1f5409005c6e913a52d7647307378fd74a4cbd51ddf7fff6106dc743765d01788bec067da8169b1d3136c45212380f8e1136e30093266899631331aed50c05517fe7104d03302fb24ad272ff2c769cc13cf6e800be182787d446c7768341d3ce03a77665c6ce87552eb7ea581b2c638fc66b4a22091e4aa384dd690f0d074e0431cec99ef74ac531f6e4b0052ce6e0ce05c13fcd6a91c7c96e2e0d803455814bebf234945f0220587b1053a0017a9406cb593a81a886befce4a8b4d26c79120420a26744e98e0c9c8ef7d63d158488177cff5e43d30abe5d1bc95cf21e9f8a4cbc1d634e93c58584055e429d7104de26f5c4b55265dd0b1f12bcbf8423c343026135aabb78814a96b0e0a4950ddefc9119124b74e05a89e3505ab612b4b8c02f100be90b41139c38333c7b4b213ab7e2e65853069dd9c7009231be949db8b69a462123a76a21294a7936118f8d3a735769f39e3bb7b159f787806d65b528c433be3ceb31c9a275e97363e21b96d3ac0d9d4d9f6483850f6712c5b43e994b9ea4276e7b4dcee822047f910075dd950d64af902d4716b621cfe82b6dffdde22453f3d4c075016c2c5916d0c43aa5d18cdf04284a7e2aa75da4cfbdedc09f61ab9d1dfe62429c2fe74e950d0b9038a9f7c39226c2f612c88fcb753bf43d33ec64011553e634e4e37d8ae7fb81165b069a608ce01a8ed5bc68d0798d5a24c38190492bf12759983b617e7b011e69f0164f1b1882e24ff2a28bfe34cf638452d56acdd4cb9461c9ed11e0ea400963c8157ba608be653b52499067def0b3d5d305546767258497463d5386f2632ab6b343a36c5f982cf9a2f561a67b759ec4662a7079ff6968f8755cb1fb7bcb09c437bdaa17a33c516e686e8e637f7143684fc1763facb72007876365d1107063141558c918f5481283a747e5e734b1a6271c09a6a139a703a0a982f3854981750caf3b428d2d0c45b240d79cd44162bb3addcb97ecce1c7c6af2c3c3ac8dc1f020970c84e54bd19f86a4dc3a63fd742795c11b47d7c61758c2f79fbf3734b54f408e32692b563c1156a832b310ee40f965d81b262272f12ac9b97914b706905f448499c041fb5c00131915088475f00fa42f3c1694ab52b996d6273a0d7e19cd8d97219cc579f04a9e0a2a5ac7968256228b21b4385f9e628104bec6accf83bbc87fbf1b30ba970fb815fe1eef2e3ccb11af72d54799d26926310e7765bc39419d30a7042fe04731e26d4667d2b95571a5e212cf12833a71b6c813ddba707a334965c31677004edf5c9c75a7f41bfc8469a0f806b2b8c5f359352c16960663a080550633405f81849351a14948c86ed62032bc370189aa0db417282c9426fff71801bce088297e387b163f949095fa9f818d07d8b4659e215246070514ed023a26e2705a300e524e07d8ca3b0870767acff7f7a8833a2d0804ee9bfc33be7cebdd75bed5e8d21817223ce77a20fcec8ca2f3b206ba49000a40a463aa30ca2375e6c1d104b41ee13b0a6d5462a6bbb80166d788b884c8de7bcb2da54c49a6ae07b8069d06afcae28124ee93bee7d80f157d0c750ffa00c52232d6bdf746623eb8fffaa75b0280566b95b7be94b374ebf3165f5a7a7347f0562ba62a576b4bcad4afd1956efdca4e566ca1e250f8e0ef6857ea17974112e2d6772cfdda80be8c7132f0ad11f077fe53b164e173cf2a1fa1f8f383fbf039d18fb89731eec727d66e099e853e08be159d260119b32f63f6a951f8f912f8dfce4b207c503c01fcf077c413b2fc003fdcf913c2ff62df738c846ed5df6181e0b3012593323a9215d50759b27adfad5ee7fb7fa40ef8f253b1409654c95781e28ffcfe07f87daf128bb0d7ff2a08d629ee70d07c4f143999d76483507c436497be649960af106ece15b2dbfd6a71e98b000287794fbbb760c84383d2faad865930e4a171698b355a08c1573df7f6c7c51ff72ff2e3933207a2927ff8756e3ffc3afcfd0fefbfe7ffbed7118b7822fd7838107d3461087c87f870903f57d6cf0ff0bf0745162debe787154721ff08748c0b65f508f75fc75a666d18f6bb9e5fe8b3a10f0d2721df1f1f43fdf277aebcdd8b3ff4ff138bec7020eebb3712f358423f54fcf9e18945b2d04e2ce28946621e8b631d8b63ccc14013861c447f8783be3edb647bd45763fca18fb394ad2b155aeea76d73b57ef56aadf5b9fe8e6eb126eceafeae21f24bb0d73584bb2558ee7f9e9dbaa0b9eca403951bc24f7df9c3955f2e2756516c512564045800dc39c6b8f3c702dc397f14c09d1c34bfc59ac9412cae7cc305898b932e4eee18ca2e4aae94978b19015c76e28285c70c61bdde7fafe588312d501913c4143e2f84fdefdecb77bdbc4f841cfbf1e1893f9cbc15b06216f187137f20f0bdf712f8de134fc8f2a37bef4fb0ffbd04bceebde71855fd40c0fef72374effd54f918fa443186b0ad8b8e6110219761b7641870994241114dac1c2dc5e4941ee03c6d6993e4268598f4c0d052182590302344125e78403a82e80a146a90f836d9acfc795c08f976de277d6f4511e15ff9ac14c2d1872515c2be97efe33019c3d1405e594158b7c5ce8543a8460ac220acfb1a004202eb3a334f71f4e75e3a54d106c914619a6652aeb018292aa8991295c4890566620a2422396a6e28686244871886646083256a082a2f1d5c38e812daedc7e1ea96122870082b3636538694c44083234b9c6141d41a3929c4e4032141d6a8e080e6b2130e62ee68802bffc565271cb6fc57c9affa41157f7a9ca4a008293ea049fa01ce1b282b44ac59628632b19e2492b0a1055a134545b10a38cd20e6298a0a569089c967958d33e168af946ecaf0f054a687220ef2b9ed63b6f25eaa7af4b5bf26ec97de7defe309d4615c32bb8e7d17759c0839a8bbe5ec96eba0e9ff7efe94dc85ab3e7ccccfdd3240171607b0269c9f839d79329ff1979dcd03a9b0551f00f920e64a3001a8e2089353181796b439c18b0b46dca02043449698971a8800b9582fc6e532485baecf6527a62d476c70b94c92a4cbe2b213530b688caada943525c27136391172d3e5f9f4484ecda67136155d2ab3618cab262c9a4d2e2b721827e540133cf26e77ec9ac023079a522e76bbbb8b63c718652d8970943589261c5d56f3de9b82e293c1f98ae278b7cf48ca619fc80e54a9544b7152e1d835dd39bfb3798c13423ed51867a68126948c714730d06cfa7e7e27e5b099cf89158131efe7734d0efb44906bbaf31d49c835a23bce231bfafc046b176c026d777e5377b9cc14a4ebaa5a97c4edce6fba521ce9957c59fe9436240ee3588ba3756993e2285da8979d985470e7fb91f0ce77222625f28634c31ad04a1458a2406116450b51b000c5134456a61c6162894d0a285f1718dec44009273f70c1e1852b96056fb8289620c1643bc2a88d1b229a00a146cb5214238ef8e00414cb248513982a6aa0ac143104118c241bb47c992384910d28f0152b484991a60729da509141044aa0492a220a8b0a6dbc5b1419241b908ce9a2849c5944451a3303261a720843a5635ae17a0b5c549aa3ca449f711ab484798aea418632489870374c9eb4f8c0a6065b9222281f1304d4707822c5c311433039a20a143031050f508e9ca9e289b7c4df1e1dc172fd499c14702102881f9882986ae28b8c3669567881490533332e8913c0ac80051eb8244d716596860830444ca89052c3157505217890e18d1134bc898383db82e488812229ce104c8879e2e560850986208e70811447d31685654a92336590a8a9012492c0d40c3098c1172664cacc27cab429d384144c7a788ae2099804156506b22f71aec0a0246ff8ae60a1a6464a0b5156f0e42be2c611344069f2c30d0931334d08e44049c185284e71c01c713508c006333c48f14414342d734889cb0c51ca1c19211953a3a0708517255b91154ea6f0222aa0054c941a96f8e1caec0997c5a3748001ca0b4a4889f2022d4a2697d1cb13922676f072a4548f9620b3c495219c90419b2727c2480e2eb08149152d8012050468d4c4133640a94972e6065913c14f2a00620ed1152f284144e702232c6072244c1423a331637ace0252f0a202941992102df1c4891f61e0b8d1e28219393a28b11138a809330312253c9ce95af0b7506c1b3e02063bd480488192992b576480a28217185c9166081da0c400c4d410513944e126081b50e0d1e40564a82c99c2091b0fcc0e4f69e2a4204aaa369d607001d410493001020e1328f64c2b8d1b1848b5293ad364be80820c599c88c10ba6a8c0c421f12a08a066082c5566e0431c18aa97de94db1a5c7aa3b7799b81013ae5466f9db8a2cd229c5f3a3d38f476a3701ae6c1f16ede6d75f37208697416d124fc6200b7fa99c728b94e9226a74bd5072e57ada207424277470f1e1cd4cf4d2c0e5a2d8fabb833ef0742e40de71565a16c27cfe936eda369702bcd611fadfe47fb681f6de5449d6e7f342aae6c1cd4ef6304eb4559285b329d3a2e7e34a7fc24acb45aa5615f958f96837e1f8d161e7d37908cdddd8d84ab747aaf6e20911c17d93e997efd0de49c36e084f27dce392755bab3abe1bb712494fcfcfcfc378e84f2651743e77d9deae3aacabffa137765369bcd66b3d96c369bcd66b3d96c369bcd66b3d96c369bcd66b3d96c369bcdbc67889bd503c1f7b8073fd0fbc0eebba3fed22ba294baa594ce6b411004ad70a2ecc4b12fad17fcbc592bf55b6db7dd01414444444444444444444444444444444444444444444444444444444444444444444444d4f1bca1d3b9ae7b8e7e673bce764d3889dbd583f2a4bc270fbd2787716c5acfd6add9755d9744c57a3bcbc9e9c99f5078360eea6fcfc639d8b3d96c6197836c9fb472b6f33e50a5b30a7758b4e0e971f1c207468c1f191a40d1647349c64f0c183e2f5c006003196e44a33628173d3c2d58d00dfea76b3437da09573aaa67c530ea9a0afc3c9608c388abddbcaedf8a337ce48b46b7bf25cd1acd78712dd4ed966ef7732a107a6e77636889868b7bd5843c9738478fd7e9f424f18ece3397bd9ac7e43575abdf0bc3e4b095cd6bead70aca0bc3af559afebefb568550bf5fd91cb6925a41f56b35b54ac3af559c9648e44aca61aed554bfe42a0ebfe48c5b52d2895c41075e1332904da4ccb379365bcba49439ece3a695b27e59ce727482dff7b209c3beef9748beca799deb86cad2e04a994c265ba1e092bd62e3d96e3fe550e639cdc9f2220ee2ff269db18629fd7771fde9533ae7db6822943fe70ce1c575faa4bebbbbbbbbbbbbbbd7ea2e29cd42c56f6a0614ece23ac7b9fb0d52b88a8f698ce092cd8bda4ca38962d370a4f8d686a18fcfbf1447cae6a86da409473f728e63d3b04a5382b35499ea50ad5525b5a93aa9b68a74549f1cd62935507fa7a444f32125254b4e9890aa8058aaed9b62d32935077d9267eb480ea22eee6c5bbf5e54340d549fbad59f001ac2b15352ea179686395203b51f815e42d08f6cfdf2b94cc1255b44fddf8086e16abab59c83b65f925bfc94e59c732e31333315f99b734e6fad09e54fa5ebadcb9e8d85b5b685b5d55a3bdd2dd881737a9e4e052dc7feb6b26c7deb51afd6ae2f39ebe274cd78a267ca2ad1b8462bc735a8279e2692ca9a4d9e1ce64d53f604bfe6ace96922f186bc216f68c91be29c187507ec4d4de6dc262fbb5c5191c3ea140deb94ac5a59bfeaad5b93fbd984614818d6e25c9ff45572ac221baba24d0ae58fd6fda1b0486db975f1a92f3d77ca1c566fb729ab3755975087104da8498c1928a95b0767aa4e6f536ff5566f1ecd23ea6e73769ead916112d3794c62c830552aeaadbe6158350365a6c6319383198b8481fa398e6b128662062e7d59a7dc3d70696d0672132e6d6e3967adb556a628393959dcb55ed75bfc5661f62d6b7620c6acb5abe398f2458c1934516ce4d45b9d3527ea2d883695dcb4bb7d4ebe8f9fcca0798a82b2c9f6492b67a7b5ded256ce766c3beff33e50a5337574bca50e832a5eb94096cea783e5f2af942eb3c270cbe5df59623159b0f0962c9ad62dfe293872a6e0f450cb6e4d5fc4347d3163abc923e94422c923e9445691461dd56c380ace0d48e3b83a70f01757b7f865835652d9ee73525a27ad95e3acedbce979ded2e36cd779def781aaa952794b95fc4009aaa4ce2a9c61e82d43955cad4019eeec8092458bd9a285b76cc1d3e3e285cff4f1f1963e3b56de110c41b27a5421c8dbf2862fe68b17def285d5f9e9d16375c6105cf93d578a6deb167f01a47c4c63fc6ca40947a1eba2ed1fb1b14ec8fb559398975f154db7389653c13e876df4d726af35097eb953c12161a019c36a5403fdedd62814dc6e6589eae401c639747b9c476eff947507cdb520a576fb7d8e4fdd641efe957e93a1df1cd6592255d5c3de4456f598778a9dcf61a7a2e5d319992eba928679cd9938877f93131b92436171a92d7eebb93299949ac33a330dd48fa629cac6e676706ee7522327bb81d073a7d8d9bad53fa38950fec8c9e66cd5072eb975f88be10b39870942b83973a6aebcfc3dd8a4ae144bf0cbdd92391660bbae4397538605682e8ccb4e57d06eedd61f1f20cf6e95326ed5ff99af9a73fecc6f7d5f44f5dd4780635fc4c781eaabea0b4d714804381676e2e8a3f3a3108d716cf5a3fda13f8203552a0e8900c77c88457838507d23b107df48fdf9a1faef55e28f8ff07f7ed857bd0d2ec4e7c871809c7385784f90523a4a1c466ebff74b8a2d26711f7e684123147c4c63ec9e2c6191133cc5bc67d50fa9c40343e8fd58bea00d2736f4095b1ae816f57e2bda282c42ded85cfaac1442c9862515f24d626998f7453af63d7da9e4350940e8bb88211ca5924b9f5669a32b2a1842e15230f45f649c708ea3af7269b79452f657dbb5ea8320accbfdeca603ab38f08b340c24d22f96ecd2405432d12eb266e4a45f478dc443dcd12dfa543239cc138bc8d827fe74b3de8692873d11fe6d1afd56a2df46f4251309401ce6638439670737a9c9b611e6fff4a84b96d07638cce540f4297d188ea53eaa72293b81d9c2f4e5525903f3e58e20058d60c072c756ba74cbd5a15dbb947e95afd155eb17ad4b68d75372a964ba544a291d200ab5ca84ae86dac9f2310d66daab6100b8b5d2967e8981e32adcb1b1a8683e54b963337d9173c7fed24d6d1bdb4c3f5dffd9dddde57adfc02def692d8b2ad11cc652523162bae5b54aadd241c01675e110ce1fe997eb4d54cce8b3b2d52ad7bf69b7db8cabf5b7451a48a322034db13e65a235dae4d49dbe2cd9b991241ced6c2c4cb89ed3dd29f5c07252ba74e9d2a5db77ee5df248e9d25b4dc207f4fdbaf43d31a45f76e57fccb2324a2955526597af511157aebbbbdb4f70796ef5596d6658c4094709256bd078f40b94cffd9adfa0bfe431d33039d440f2c54816242c2681e47b1e0b16316288e2000670e38690dc210d20593584f2613ecdfc2307a0517f55f4df4812d2e4371696df6212362d46cbee481b278d527983079425299364125a7229b56854fea4cd2d1e78c0e4301f212197abf5df6a128e96766557da10dd6cb7d34abe35a884ddad4125b4b7069590bb35a884f5d6a012d25b834a386f0d2a2137f2d4a012f655f530ee742107f1db39997dce39a79439589579823c3c2d845cfa0c19be1b73ce39d9f62834a7651442764a67c0b07262006a421ef342d1e5315598ee687d643c8d2a2bc7c22b57b9dfe11cc7713ee9f428a5a0ffa49482205be66e9d7eebfd5a72bb0e3de15231e42022b12a4405ce5a2d5775782aebc7bfbe15418855b148a85dde9a5f59f672914facfeb702395b5fa7fe647da7b22a2107e2ff6ea46039889f5308e5f30e337b57889c33c55104aa291204c1972a9d5518ae7454e00d99dbcad1e9f3729256a1fc722c117834e958c00e5aadb270b8682ecb011244d974da4d425151425109e55fa92c22c2412d41950a4c5ae520c2419273708f8e108fd7d10976202bb4b2db81c122f2442c57e9bc21eb24139144bc769144b64fea6a013dcb0746b843848d30ccf34417a5942b5b904d24121d514ad1e713e515219d6eb94a9faf955248b02da5dbba141e529a740849119a2c226d027eb95842b7dcdd722285b1333968b6fe959ea5cfc91384a7b35ca57442f98496ab74fa9c73b6583076e6cb25a825a825a825a825a82587918081fa51b89da4b642d3139a11b7df2372c5d4d7e9f4ac5ccaaac7fb5e2091edb367ca7593925a5e2c22529504022a505050500390403310f54ce8b4c0761868a93320ce13cc9eca396c0f23a0ca2954ce9e429ba543887a0d07a51ccb8434fc72310809ddea6f6ed15a82ebf33fae25b7a7633916b6a7637e16e7a8cf9283c4ebdf795ff89e8f8ff7f1d7035a17100b46c713840704baaedb59cbd5e9aed26972b558977bc96152d6b55c922dd5b8a394d5b84a3050bf13456e8c1a852e4abafd9d0a04ef4e5142cd8162e9ddb63a20f7ac5cc4a07680dfbf27adb5d64aa7ca556e3bef932010ebe70c233333db1932d449e96466fedf209cd2ddddddddddddb99b33c255eb0bfe1fbefdbc5072ecc3309c2b701c154a29e5b88ea0bbce52789df52667794e96b5f29b0245c8f2c0cd9d1aa11a48ff252a1bf2ff3eafab3d7b5e4a91e334f07274d9a907241b979d7890bade13e7f8dee573cfbd0fced13d77e31cfddc77cd8d3847cf73ef509cc33ef743a45b568fd2f5a71f15d75f0582b9fe3a2ab8feaba8eb1feeb0f84fb2ecab7efc9464e8fcf851b1fa11041323fc51a502183b3faaa27c58fca8a3e5fabf68f1e32a85ebcf8192e5e2ae9cb84a27f8f682e07b5eb3ea4f567f0f6bfe0edfd13cac21f2b660c11ad9e972bfc31ae594cbb9b9dcaf5863f370b9d7618dbec2e594b81c287a451ce49f8021c2917a453748d23888fbca92b71a07713f596ec441dc5b9643711047c375ee8effd3a3031c274a2a4ed6530bf951f16eeed6cbdce038238a125037b45ffa0b3360f03927cf39e79cf3a34f29a54577cee95f02fa86ce7997f8b45c75771b526aa5f874f9734ac94d5fd1ea644adddddd0d7f5326e7753686062cbe4d0f434add6381768a9d53a67b9f540991736e77b7a4ff49eed6e9be53e67062d0ae49e99c734e6bc3b09563826063ce6983836cdc763d03c906c1ed962ecee1d7e8b9d55fe44a3b655696d861d25a29a594721c154b68ae47759f735a3b6b926db6ecd2b28b24736bb24b77f70814607f259470c209376e78aa452ee220a031e128b74c91861c8173b46daea9f96034531c47a4615e935591c232258d249254e2ea949a73ced97d458874cb7f64a859eb039973d6073239ae3e107f0dcc7620406658b1ada49f612504f243033b6ab6dfa1a386c4062d1cd574ce2938311c27c20f204188e890323151373872381d0be8d7d8daa163ce39715ca6ff57f4d112c1871007eb78ee3f2e00dc029ac00326c771e2102e006c0059e3ca6f8d2080b1027cbd399146002c70593c7c81db9381e45b56109e96509117b296b9314ce7a494520ac26021e4310209fd9abfe38ad02fbe95bed71715750871930e9808476efac14384269c8341ce8aa4c1f25bbb56596573d0eaee96dc9a2f550d30c11d4d2027bb8e149983e607d4ef1ceaa5466aa4ee6ea47047b702c082706c27eda49764ad95561a3208e11502822b439e3216e89c94524ae9534ae911aeb4d65927a59452d7fc5aaa74086903782efd8fb24ce81e26b8aa1e54d500bff404cee018e943a3d572e9e0f183d1b46a626c4f5045fa25a5e496b7ae8fad968b35610944ac8f9d456108001ea48474525a699d3a84e69c13d63d77f3c651f5bfcaea31653213ba5b5c9e20b2c70eb7fa5df27dce1d0eea77c977be7307c707ae7c6e105cf9de922b194a27f3e0204dc82868b55c3a78fc702434ad9a18a71369f4199ce648a10b5ad7a528e388f3252b6edf6f05d210ce9f2f61b586424d8645a6428c3e28615e2d859aac8b8c498c3e8f8485b521994c8e2c4a8cbe0c8900f1d267f9a200b893d239bb5d563632fad55dd7d9ce72d0b2b4724288dce9b18656dc81fc231febe10e3600e34a9e0eb4e020f95205020f082d6ebf0e07c951487722c8412118559727b74051489116933ce9c9e8575fa65073b4b7d2dace6d3427a573ce39ddef27851c2682991b318453643941a33694522ababa95c4e1a0605348e9b3ec76d0e84a9d754e3a69adb5d686d5afcf77d65a9f16b9b5db0457deaea2e456f7a075ec135cf9ae72809c33a47e09f6d6d1c895d6c74e99924f7e7777777777777737fff04b293d89fb1dede3d3f7656074dde5125a808f0bace4845ee95cc9e9d76887fa35864d42d94a0e96705cc1b9be82b39a32720e5a73ce3976dddc4c6076523ae79c3389fb16a1817c1e09a709b31f2036b76a09ea03e690d9fd3ea72843a74f4e093f03347fa13f948ed030af010942a45f43cc4ca71c9f9f5f045ec3524ad900d92c1ddde2177258ab81f8b9f2df111888dfda6e7ebafc92c50e48da992f64981114cc4881c5091d90d4bc4026898a1a1610918233320879043558a1018946850a1756b374749b01891daa40c2cf3bbe9061b01dde08714354151764d081244f92d2bcc18285a8670d192068b0c2484d10311642ce0bb7355164718ec4f83901dc041827b429bc202561c6c89417d85aa8a28508222e120a8824815f8a27882764f921ff04fe399f278d15427e1b0cd4ef813710532e161461ab8ab763013c5c2cbeebc2db755d278ef543960e8b9b415c77aa589e3c4167c4b607f17ddddddd3df52a22e46e6f2d5ff5a177360fbdb3e9fc6ffc38ced2670f80778a6309d78a41c0db0fa7df4c41857477974147712bbfb955bafd16e99ce3fcc9713f3971fadde1963596607facdf71b7766f59b3f3cb737cf4db3eabea03fa75a460658df576b3dae3966ee5ce124b667777972ea940c2dddda54b6677777777e9920a24a0b84fdaecee4c5ddaeab482a005634085d23bf2f95b015e762a23c51ded1dc00cc2cb4e65d67454b5160c798a70e247656a2b984959a523a980a15b19a3a34e54c0eca84c9167431f27a83b7eed09d7822b5dc884322e3b5da17160c216979dae2c717a621bcec0841393316b84c832e524040e45977b1f32662ef71fe572b6275c30a914ab4f551f543b668ada39c686be4ab72af1b1dd79adabc9651e4fa18627d0ddbd4a18c09cc42c8d51e1f6739819dc7e0af238dd51c6c8018e1e67313fc8b9fed39b6cd79bd600c18549104884c972fd77b053981ed85666c50302c2eb6ec37577d7e0872a468c7618723374c58997322e44cb0b76a801081a192262eeeeeeee31b96e039cebdf7577f757103f14c900793e309f9412f6e53251a44220af3492539c184967a37e8d2ee576bfbc25b7a795f9ed32556eb775fc6bbffc21f8e597460de53c9da300346ecbf01dedb4197c4c0347b78492b8e7587d1cd49faf8c59e5b774e0100abf15faa879f9d5261e3e2e4042094272b8098acd6d4a46ad6c429f5823028fa590aae67f93357f8a43e80f71f5bb28b9454d70fb039ba6a8f4ec98252d75866c00008080022316000020140a87830191509a848134ca0714000d7292466a4e3c154823398cc3200862180842880062002104408248a1013a036aa556f216c4c9e53075ba782eb0d1d5d130ebb8a96f9de584576a48171f5536d9d1137a0ea5c3bad00986dab1d100646bcd9d751f7275324b90c9712ec4404b833799f33342dd33bec056ebdeb9fb4f0a4ef4b5b4d2dd82c6942cf346c9df98f750fdcde0d78992cf65e40ddfad351ba7928e23eab141abd2aaf21874a421f6e6047167334a9d56cc544dcc23b2f8f154ae7ff9bab2563c1f532fad781ffa5d9286dd43cb248e05981c627f411034fb6d959edfc742c0c6dd7a33f630859bb746485049349f5530ef4f91fc3daaa4bde1f8307a872099541e2177bc70f25c40cbf75da827d905eadd5bd817bb389246a74ce8f63c8664b1afb32f12c547bac8eca8eff51e3dbcbfa394af3ee98b7d0d925d524191a83bb1afa32cb0b07538ab08f4fe7a042186019401b8d91d4fbcac1ef43eeadc19c0320b9f90fbd09656e684b3cb1226c5692b671839a38a982cd01a51c4cdd34d50d2516df2a6c8964d67f88fe3500c7c5420ba0cea263da8579f96e2206320d5983db0c76264827d552182bc4284b462ea63d7321df62ee9658d49040f37537d3ed9716c6fec42192634e0eed962204a6197c8ae3ff88ae6d6e22ce4133127f016eb8338ac734cdd07770bde600b9ddf6d88f6e23127e57e9d838e643a83e9044048d76a403c2b5c214afd44ab15018e708309696b9b01ea309424d6b1a68979311f9bc265589b2fd631d2e06c0287c9d2456cd684f986aa7db8a98065e56e56b8318f1a586f4c5afe156eef89a62d7e8ef55664805aff02396c45ac1a189f8373e685f8c11d8095b43a5e37fe296e43a31eb4606251bfc2f2c81b7f559684baac937c11289d9b7a197ba85ad27d3b3784e0ea7a4b14f6e7e4ae3323273a66e1716cd53a1b7c4f105642770102d206d6a156fcbcb42ca82a8bce4eef09e7d2f841f2a570bb52fb1489bc40907acd74ef019642567c413fee446da9ac25804b782d16171116b2c20d568460b69284e080c9d8407355b540ba36e26fd767ab7f22a51594f27cb9e3736a4342b54f86adf201b23f6e1b52d1facf95d025d8d99e3af4f4d1270862d65153766619377d4683a246b3f844a8da89cc41095a3f1aa82a7374e8c9c7ecef8ff16c30326fb118309ddf2be4aaf09d0aa8bc98709d8e0237a3fa5ec9da45aa706e8bbda9daaf75a9ca798322e9c2fee628247801df20078fad8dd7ff2cc8324ad1bc8cd80acefe78684649f6ae8ed3fd50ef51e36804e2e57fbe6e926596226b623360d99d2a70faf36af2ff2f790b4a8149d9df2702945049ba81ca1d6df6af2aefeacb0c541a3bc6e11c4dd9c2fda2ed258a4112d7587b0fd36df0e260bd196b28443359b1c3dc294d29dffb4042cdbc04203b3b09e3132603982ea146d04e9451ddba2dc9658d3aae3790dccdb7544e91aa881eb1b44652ac128efeb135fb4ba59504c5b9429e2590528af58e972f3ee276b1d7cfc0a3edf9d01af4e42b8049048149838544425c99b6b0a75bd675cd22e84d496999b30d40f707c97ada4ccd59b369762e40889e9c897df57bef717f0ce94cbf2676e3ae5b0208359cfc51634b5d5c2cc9e91cd91d1fa05f1ac1b5d5700236eefc9b90c2f585be632a519174528a35f0b0c21a82f9b34286a3adb842e51444188336798e1eb748be75033ea3f0d096c32813b39eb67930122e5648d2f637b59e868ddbf8f9975a2c05aeef3191b568b2018feef6880e80045b3c5cad4a249dfd3b3a0d98c6587835f060408ddac0cd75fc81b321939a13effda04813d894ad25b660e2dc2528fb8d16fb0264fe83f6e308293a254459be18a737efc015b7aa1689cf824f53cf32199f2d4f358e3980ea6021c22d446fcf5f1d7ed538ea3155069235e9c5d9ab2f716cdac44b0ec6522fc0641f444c0596a6219bc553db1993b142d9ec076beac72e9175e993f239e8d69387b07627df4d905d40169444bc749328153225391f11dceb5946542a4953b01f1854ba9fa384fa56f121f2eafe71715e8f536e405a3ebd6f0b9c4fcef8c7570025849a41b8c1f9ce6320ac57f740a68d6c381f9af595f40812f3d39fce70a4d369a0221d586de6a2cc058b06b28579bf30610704b06a978ddbb76d5dfe27f88712aef86d820e68feb7643be98f03cbda4903a3b8b03061e14ae72f870310b174107803dc4388650f574d8304f7e2726834fc48dae4bac9c5b95b51c2e9f16e26f2ae5318c33dc328ea0f1af2534cde4885f11fbec4c330f374eece28b77f4c4c0f048d672919258fd8065a00af53940104455fabff732673ec878d3b114503948c9666add5b01113594a8f463b8c2787e47410054e0972778058650eda2f2219c20ced9db6dd452a90775d3c1e7e1d3c18146bb0e42606f49900ec9091a6274e4ff7f30efe8aa3acf210f0d88237814cfd8732956c952d9880d0a3676c88b2151234811993a66db99279a42043c52ff3a71d8aa04369c8f6611066350274315d64d8a9a89da45f7de58381e432056830441e7963947b9b93e8b7d71cd29aef303bcbf4f07519844d57ac45b184152718cba676f898b69a258428a8e61181dce6eda9bf6094c93e503d0d8927eccd0f789bab435d96f4b121ae0d7a33df84460b064108eb891e1512e530bc06da251548e241173878fdf39668c0c5fe85f088073f5c14fd0a8b9de2065bd9f1f4ddb1fe589aa64fdd441870e665209ebc5248922bd2d1e2650ce2f31dbe1e2121c7c7c2fc3ac27b63c06592dfee9d986771148de38b77841db863d89a15ad1a149b17031f8268fc04ac68258ac67736712c8c5a05fff0aefd137f69b48b13c5c059321f3c3d9b221262c0c43e21f392d1ec657f6c4bad8341cec76e9cfd22a2dfca3064449900c9925dee022c604aa9aec9060c78eb802d56140c6be131960ed2c9813ac83df08cf8f34dfc867900e149e838abc80d983d96309e87d07988a4bfee88ef6300e65a91d299e1827b85ebb44d24f958b03b7d7e4816c389109122df113f7a5efd93c13b798e7e2cb08e1f46e929ff25d55d248796b0a0d88f50195f979a8be08f0b87aba7e1c1c93c207050fed61ead15480803686376cb69bd81bf2d50707feb628cc432772688f23941e062ff953d72d5e6249813c6b63b85b6da58bda26f04190c77f7f54c7083f87bebb902ff10ca71439837cb7346524b1639dd0823781c413908a0df79fe41c0786886a65674c827bb7a215a5a5a62cf06662ccde91747c626df98656c89cbb6b6a76fb568fb6617c1aacf1ee48eb4827ef0580e92124b63cf666c28936e94ef94da913b39eb8dc4d5475c9e1f449d352717652043b95bd99e64eef79c80a0d78365a94935f9e280929bb1784fe19dd2e7b51dc8f237ea539958c3722be3f2716c8e82c3ba417401dc8d01086b0100dba81356c272523447b520e06db0efbb9c06c4bd0d3ee0590e0dcdaf7b439a77519c42c3257e289eb93cf15b950ef0b687d7129e8316917b64a895d0fdf908e17db611f1a793f31dc9c284b56f96fe13641135c734c7999b3337f70044eef404ecb4da9b3db7c3187c9d0091aec382c33ce7d426cdf57f9a0ab67826d311186fb6a90e969a4da7bc7205c4e2ca91aeffbc12d749698a353ff3c8fc68a86e271263ccf66f35c39b18e9170225e3c6ec21806893704950096f5ef01468cc993f144d57c0527bbcd62900d996614dcdb75a93209bf5cd9156d874418305e30bd2572b087c927fc49cbb6128a3419b10083c88712519542ed31946d609de71fd04aeb0d8e5916f7a2f20898b708b8170544461d811a306c162205558a11b4cb92f10c4858b422b065821c0935f2bc1394e8195ae813d3dd600854481d6d90138d72f2f815887919698f99ada7e1a818531c904b188d8bf4889fc183900c9189b45f8632088b013fcbeed75988e9f079f451458e441301ea5b5ece99733917e46702ae5be5ccf24380f48b9bf89bb0e62123dec8bd04a418139aafc2dc705701981c055fab1870dacf4ba5d23dc1601d3ff168e950acb961a1558a927c2d22b82ff797cc8f8458f5c437d3e43b43eef344f9f611a1042332146260712dddd7ba56e27175851906fb734759778da3633f100770b413440b8bc4a7311b03ec77b48d64fa4bb16b65eb866b77c3b1c85b9e7e465e4e89dc185c4fab5af6eb96b79c21d7617c94d93e543c1ca69725b1bd1f915fb2a917bfd2c11e88532ae24f87685f17e741310638ef48999fff6ffe2d0dd021f9e3b8b287ca17ca22f610379c11da88a221128169761c10268497674e28ac5a2f631e5b9d67d2582b99544c2c9c2d48963e84edc318fbba3d682fca2a1e5319a495d3dd7cdd5dd24a5185f9012a26b1b284b8c60b63584db33b493a456a04418050f1019fde1332367ff508f483985cea2bea4b14143460d144186edaf667c1ac45f247a2e91bc14dca476fdcc6ade5d1354fccc95d6d5520ac3558c02f283a9e4793be280f03d12062119cbd0969aac77eb03e21ca9f100a18b2a2a309fae4c04a412c6e301f9e5d663a334e24eb448915920e4f300a2b22e5b06d543a6f139375597d8d84595dcc9fbda415db6bf028e69f89f437dc4c39a3be9a046e016485299bf6a2c57c8c9f54013f75135af124403643e844c28547873926b3b375918e10445dda37d2d286f2bcce3252df6bfc0430275fbad46754aef68791a0d3e7f2343faa23ee845f6b65d2ddd02f425e37470b2f678221e9d9799fcfafc3d321456c002b80eecf40d357067f8ee446a79b335f246a5f053843fecf3922d9ed18696ab45345ea1b089a30a8958d9efb315960a2f9a932c5e60fd3defd6caf578d116f874de0e433a0f7652c1203e29d7eb2eed60269247c864b2f2487b7fe51c463b1bac682822276d3ffd94084d036f8f33038f009b5f6b44a4dd7a74b1b71fe13a0795b777935c8123ad086232220b4bf3727628f3891a4b9c2f33dfd983cf7942bd08a25197e05a9e0bef01855a78ed49ceecf87110f59f0bb602104a4430690237edc0479e482f21ea2d2c85124a2c347c8db4587d19c63dc9d83a1d43025e6b5d45d9668cc9f43e17b0706c56563f367ad2af59d1f4a28c22b96a34765d7aa1ce5d97be0700dc84c62e16cdd8722fabf491aec4fe9c5529f051981756b756e2c08366bb00a59205fa7f28a483a304dac4aa582058224c06c7ca96dcbf898ce2cab643c83902bc127d22b76ade95cb4f425a371b7f051e0245656391acf873d08a471c2627dbf6e55e89f85cd663d4ac71f8ab693aa00825bc06ecaf9e3a9b107f909cc4fb258229a28862fddb556829005ea0df3cc6f95f2646abd960a9dcce0651bfcb5fe6d16393ceb6012c7142eb58a823f2dfcb06f5bc48074fb81f840847394fcfd6057122f0b61662e50b0303615b0f8c88a425f5027c8b62abbc90d7e833868f94cc1fefa5280849e3a648599546ba049c4a2d6656cea69c79d2ff91e29bc7901104e5c501dfce287097fdbc4908560262776261ba7f418b397c7009a37da578dac676d10114fd138ff6ed07b5820a1fdcc807d10da9595ef8e73500d165afa6a0d6cce335f6d40a22a964e5ad12508dd501fe78a76532eaf10e1fa4dd493b73fb0f29763b7adb2dccb74d5a7d4cd20daa62399b29063e59c7a0679ef2c454b21c40a00efb09076419fc6ec2d949b049c74d243c18a6f53479362472f47d19652dce2904fac146b81f7c53251797b6b20f616fb678e0a2fe2de25e059c7034f1be9d1239b678b2d4f827b828b319b549c37e467b33fb260ea7299d2f969bdd2137614297eb86126bb8f001f162ae4602c8046ed9b03e27a282a0b5bd2bf42093867d96c03c88902763ee2ff8903100c294d1043a983c3d308f27fc201c55b1d46a203cf8432c56894bda802b322eeb22ace54fbd72514295821d2eb8703d410488d6093ac0dfe64ad802bf391be33eeae26747dad35313c6e9616103ac00fc809f5085458f7c2c819719052c477418ac57d91cbe015cd24a4f97f2e001e61acefdcfe0910a8cc553c062cf77df057627554c87d683cdf949af06afc91a1cd93ff4ead84c37c04a70637facc0e080be22b4363799404305a9338b71f07f1f2ae55b9e1382db9d64871d8afd80798888edf3995778393642c51bf8816cc47ea4014da3623bbf32c8c2f9e2879580e79cbd8359d3736d0a93e57dfe2428646031f6dbc1739e713e828ed4a2582fa14b495f445ad0c31d78261d88f6a0cdfb82c2de0d94dcefd2af9579aa997bb18d5bf2eebe3adb373dca05c4f842b346d1e085400dd20d2ae1c4010085052109c1a75abb40befbe800ca8e2f05dcece4c41a5df386722154aed44e1c77a4df5b8b0e8ebfa7dad47c1b7316a08fcc9cb7421a59e7a960f708dc347c39990e77ef8a9296f6cf6469ec2f11852bbf1d28e11cc6f9b85dea18319e35c712a80dd2152307f79baf41e5dfd2934544a059880a228b00ac27a8c896249fd523ab7f056b20be270aa5935fa1c75e5cc6b68a741965607e631559573c056bde25e37f48b00e79d7691ab29a46f84d5873a7871a3fdebc2af4ec31fe7f72642591cf82330724f03875ffec741e39a8ca110d4adace4cfb929730cb4cd2bfc15d96b7f560af62dde0565175a7db7124ecfe39e3bf5cd39ee14ffe281f257f06afa1495c0be71e1a2a768fe2a6a4e08830ccadc965460b44e0f3487761072b71faed4266762bd9134211cb529810467995c3a8d7b38500d541b1a987a7730920f1920e2363abbc1a85c47035b5ce963dc379a5ef74c46d1b7bf259b673a46b876b90daff7b594eb80bc52848cf7c12fd3608b7427b7b7153898a48614475940944b900495837a3a6851a4c28209a8529a223410355bab766cb70249524ba88e5645ebbe070d8d55168bccb0cb29ba1ee89d15b8733549a455303d24224ba2c1c63d3d7c30231e57c7a16d386c1bd5e36f7b6e9f5ddc000bdaa962768ea5112264ea2331c2763dbb331fbc1f58d71910a5ed7e036e74ec0da2452846f370dea1f60323cb2b02cb3e00e205b0cea04d77fb8f2c0f7f4891e2f412820427257535386fa3b9bef4a8ae49aeceaaf69592447e8d4d9b13ddaa1205c32dda2ebed8c57c439e94e45c97bd0b0eaac37e25993584cba2f37804c3ea26cdff23b1fb27d7b80e13863a05a92edcfa4ad34957d6a35952e11c788bb7817c059ee526ce5dfc2877cbde26ad7f87a2b0c88c204698d52020e95fbac0ce5be65937c38f63f7aa57a889edb1b4f87aae5abf7beba73d7ef1b561abc0c7f398269ff0c5fc6877dd4d9d49419248e94913ede5d3ac2baed901263e9226c19128c395ce75c2323be581f5aa555fd8da4a143ce68c73489aa99d46a6426f212211fb3f7eebbe29d1500cd1e6fed370c79b6caf93efc7804410f3bc75ef3d9d908d756ed3a656784930e59ed7c1e033f48c8224917c2a0c12ef33eadac2027a73c2af78b211072aed4abf6bfaf194e7cfb0bebc2b9854d51f0f2c4e065ccf35619b6bb8b04088a5ab7a0f26a6c1e36c3bc9737d22209e5e17261727e7e738fd9366dc76084696a245464f63b9676f2342f42f067a7c1a39a8cb12ec16ec4018e5c36ff87b63510927d0a22ebf25b59e01c9afc4694fb47e712ee33d348cf9944329599ad985ca072b85db0ca1d4ec2ff582937b52f6e507faa79c640a5372fa035c455c5db18af4de3ac8f0bfdc89e0adf6673e1c0922b9e53be64ae61d6c86719c41ec156fa8da4483805a331a3cf1870adea90f44bf1dd90ed17a84be3284ca32fb3197d09c32d04cabb2f9db64fb404430efc5d39faf35b9ac975a22fb74f135efad9af6954ff2f83e85c32b9c2f6b29330976116c8876ca5cb306968d48c389a2e2224d985b450bfe3cb508640a1256215aad8e9962186b9160838c1706cf91143b5a6682ba595f133820501e19581886991b55936d06f0b4afe11072d03cd7127a1ab92a75d38ee607352b8d6e30d888d4cc94f79a355521f866f059f4ff51791b785a5b4b0e0742c808113213b79a8e4a2b560c36d35f28ef7f70bfed2a8b1463209ada2c36db004489e88214e685fd18edd3c58dda9db1a24887b8cd38409bfe73be89da7fc0cb7e5b87de1d95ac5f362bd644fb8101f46d2a6d05505d9f50caa3aeb58fba675ba167488a9b8d8ecafdd7819d62c0d34edef4c939c0b0328a1f2f2aa11222abf9f5f85b11cae4e64a557b98e1f252e9cfbd1b8dadf2ac4831aea87b8de707c08f69f4eca6c262ba2d45e05e1bfc1615391ad1b1d1f34d2c2398d0033b12124b39ba96a40b653d9c4c7774994af8cb46786b935122df494b75f4b194a45bb1bbcad6e1d8544016336e274abdbcc9c9b4926334fb1fd8ec9df13ca8a7fde3909197e5d21145ef504f5c9a29469604190206f00d77c539c2dbac6c26d0b429ab16b5ebe41bc3ea6a56c0d4a8ff9c1742c1f3b505be7b61a86b7ce4def2ac939e589a42d7de47f17f226a72249ba0998ef75eb64dd0cd74f19767e3305b5a7d5c3e1d353731a08e045c061a64014dd1b5b5fab414cd8c5906e978c8667af8ee2595b927abf7055f831c5008445122e3d56df6d1a1cf0a8ef8d35d7a7526f891f32aa5b4b9a620662634e76dab338b7cfd0b8ec72d179a2537df1b119357f21d6d2cb4b0748837c17cc6009d9d01cb11d50cfc5a60cc702f588ccf8d6df667f6fd979511c879993c4a75420b6840d628caf9ca372d563690a94646579e0c5b8e9118edc680666259f5eaa0a13f5d00255be324281faa76c54e73edfe17d1bfefb40e5e18784f1a9cafc758f004da379a0c3b1747ce2d3b0e90e33494612f30f6159be257b158f86c68391c01d27b12eb19402d3bbea839f089a4dc7baadc08073bba5a11fa77c7e4f428bcbdd410f9dd331e783c7ac21643f6def65cf289844423887b0378450fdd5dedfa793f8daa9239729520219fd545cc03eee18219813dacf7e6ac8c0e1b6db0ef4c3013169e789f6f81cdb463b26e266931e225811b2de1d8bc4dd5558a926b3c937528bcf60854191503768647dccdceb0fc108e09335ea7a2781f984153417052bfc8f1ebf1498f59a828b96b03602584886d17747b253392a179c40d5f9ebb94f0e307c3bf2ebcd555c8e687dbd16fd44e51ecfe518d299cc8752e39a7e35742071d84ca44ef3978da9987a58e54facfe12214db7d62ae7c8598df8da86dde2fc934b6df311b30b03f97dad3f796ec3e4411ec9f7878182463d2791cb8d11bb95e63a5f8961731b7bedb7c429f2ebbb2b9f130f0eea007dcc170011529cb23ef7666aaeb8d52cbd5f8d50233b9782b3d6e8f9ebe0d698ae4625336d2219d13b836570d8bdd9eb17dfeb2e6e04f59c063164b3cd08ffe449bd489162f0aedef4c32bd754a5e02c804719f503c517ac736e20d80d46973ae175c43bfa8be5d4273c3f220177ebc4c42d361d1ce14c03af8db99b04c82d2aaafc48939d2b4853abc9964b4e739122d7ae11f6524de0a5a1091edd71b9d0511b54efd84e810402aeee4507ba99d736a7526549bc4ce7bfcd18efea4ee2f0c0eae650070dada7ce2dcd0548433d0f8ddc409fca79d7046458504cc770261d1b5dc5ed31fa2002ac0a47a4f1d240a318649e310d1be2d85aa87d8a162b25ed8372c08a382c641d3d73ab65b055af578d1862a173af2f89fc72b35ed2de9500ff10f242e7c4869935582b1f28a3a1393d6c9542c44b66191e5691e668d050303b8ec1a6fb02eec751fac163ee8920873cf2a50239dbaab679345f98e1a57a7c4121d2858fa634a64b01b417d4db7bb2923dcc6fc04ad1a4a7c7394b844240daae6e99407ee2dccf72e47fcfe9b0b4376b9c1f2f32b7f928a34aebbdc2be197e24974146fc86f148a482487c7ce31d7e5cf1c6f38ebc6a6c849df9b7fb7306d82db680b79fdbfd82e352deac044175ee246724b85876a3d7c68fffb342b2e265a443d9f345edfd593d36508110303c0f4d15c352cc13e26f288233fb057d87aa837419cedcb5c2f17cab754acbeacc326587b1946d3c30fb1c39bce08177dbeb7b83e0e9eb8d85893f2a10d4501ece892ba34b96ca41bfc0635c7585cf28ee2d47a503eefbccc8354c1ef84c1d2a62d7ca79be7d8771590df686de7b485ae355d4f75144905a12be611567f56cd34bb34dc3b1d3a28ba6995804e1171acf83d494f9af3c15c73d20ba0ccdc4c6faad2ae1c0822605577c82c1de41384ac581fad3b828f5ac322785bd5f7959e199ec31f5a8b27a8c30de18eb006f77e361857f3d7b1afd16b263347a4c9f4bb6633c0a2dae831f638627dbb94ae76c9b7479ec6da3a4a9fe283f4a2a7876ce4b2a78913055260c67ccc8ceab15522b896b3a3ad0ce3690e678ab3ca995df37e67957defb4e6c5f5f40bd63e3bf330018a6ee6693aa0df099b238c6526729e3c70a0bddf299e80ed19ba733e730c23c771448e4fc1354ba1c223926df9d6a06bedc7368a5e6d3b6e593b634a8182b9470ef54e934b93149c4f85277ea56584d8be090a004baf0490271ee465f9266e5abae7d1c94694cd6da2ded1ae1b42ec569267d6017efef78917698d289b06d9bbf1a74952c517bcc680068e9637b4960b30207d38e987d1756bbb10ecee1aa8f02718217c7780b0c8dc9e1eb3d0f0035507dde1368efe356320e562bb2a1961c37fecab16dd53479d0e48d6bd5d569fde6c4386d45ef73918811817e228125b647a80928e9529702f536bcb2c8739a91c5bede15c8d62e8a5f4a9bcc201bb34409fbca09efc9a736b51add8ae8d19dc623c448734bec3ea5bca99192dfcda9569464004dae50f4fd7bb7ddca984645f7b64b3e6b3a5c6b8d27ccd994a350ea92bbced803dd9bc0043bd1d1d12abf3e256bcd27ef63060a268777fa9b3bca24087ea11f40a29e93f738124a44831f480081c21a2b53d0388a8d096548d8a198a9d5d95c62b964893087bb21c6cf3449572fd186ab2bc941dfb4b0092cf32a27f43babaf618712d78511b98618023f251aa604d0112c3dcc8a510a4e9340368742370823cd78213976a2ad4d8e1a9d84b3d0dd342c31cb28ce76ce7f5d33e1c38f8b2261bce6a74106d7483d63c3f88fc0d80624f8b3942ac5ec72ba9428950c7482744057446eb45f1e1cd1b3e7a436d6ab68a080e8096820d8fd9cfe0ae6c871cbd57c144893fe2e892013ad957884a454cf1d9655036f38a5bb512431e8ed7c34c61c784f86577450b557cff6691508cd9794558b898823fe3737d56e517154ef2fc5ed95be58d10a6e745faef16022436aee6233fb7d60b68239459baf748009ecaac530ad5410f85577bad3227dfd502bb1ce008e961c8060c3cbc518349e0bc50fbed814c8c5e4b0b1c68bed0c31ea5966b00c7c9f38b0de022afc01568eb612d6b6a6a51fa7fc6512d312c5ab968b6f66b9dc09ea9026221e3d8612405e8471eaf3bd033c457725f541b29870386860031077221cbf5c13b48f7374ff4ef83be322ea49841630ed1cb1b055d68c44536d46706ce570167d09725683e209304ff1efe09414a5a5f5260c3e8f2d7db009906e3e727a9306a8d7d7a7e5660c20ce2fcd01a39d3bc8b0925c2146ff35e1cc6c233f38a53270fa91ac6624065c343919e058f387adf81caccc9552d030b0396d650e193a1f6e803e917c171defd6984aa4a8094f14093729f697a6a793492b0ea485ec70acc570d94276f78a7b2903572d3e9178c7347da900934aaea4e41774f4eddf6a9acec799f923c1bf5bd9b3a57bc1d64b63b62af9524c7f37f224163a881119a0e908f414ee36f90425f22e2d0e78560763b5b822b2d47da38e2bc163fcb40274e833019ba4ba7c7305b2c085f4b7d5609e15d7fbdefc7aef9a8f0a02b7699d603c3414a8bc11f9e8a4b28dc0a14005f389294d003ed9c2a3180077c08a8e06d281322b162a5ec1d79bd3f957a9112d54c6117f849ac49be8ed55f6590160e7437417cc27d94e198eb9b7ba807106fb195618929a03a11c2dfbd9d6ce27e19bf363c885b0d4ad473e382145a7ba3159072c9703d6d5498ea34fa14eda0d50a79fed5062d5acdeac0a2420ac44464e0ed9410af515cf46b924fe2368fe1ac53883502376de37e1e8acd4947f1d18a15f9b83a726cdc58c2f5873480b384d14d3c84aaad74341babe1dace7c2662c60dbd6e4e27b3e41484a346750805dc564fa4bdc35d269e5e05103901887111ac6e122ead54721299ac23ab2ea3ef654510e8489fc1eeb5767375641c1914992d21a94176d60b732f31827356c832d403b29b9206920d78face0638e4c3fbea721d45a59e86332069d447d8f1489bc15f55918ee837d837c16c9e65ee1cd6b5d4d794dc0697bff94ea3dc2791b1647886c9030392297c498954865c6cefbdd0788ea7555730ae826ec52564981ff0222b04a6d5f91a32fa01462e80a1e37d1a1bc237b64db9c4bbdcd2264fc61d67475023731e2f4aecb4e4d31527070c83b12f1355a7ab60eb35bad37879982994e211406035eed7cddf7fb3fa18625a94e6d9f066141e7a7589920cee1a4ea96a4685d5fc05707d03b6d6e96d799742ee10c75fb97cd48e2bd14879406656ad5322dfd993ee154cc289a653ccd4b80c25eb66c3252257c80b15e20ab651ae4d55cedf41af565a07b402b6cd825ae065765c9344f5878055a22210fcbe548918fb3bf6c8b7d99f61db9d3219aa8fbc949fbbd0f6ad2d2566e2002a5977c04ba49a62eb9542d9c1e615418275bbffd856f37b549223b6016fd82edb86a0db4d69bd461d289f16237b11a3f2415c8b5a4a8555b4b01990b352b0205411b65ef2058bbd498e864a8cf03a57aa45c15323f301db16adcbf70498438d9e1dbfb31d26500656585f8246957b7e1f2707bec7b28994aa4393f81c4d10e412bd8b69efc7f1369a1cbadc6297437c2ce4d70ef25c4ef6da26b2d6eb55e9bb3dda11b7152a038c0b1b4e12579e9247f83c8a8528d20b4e5322ae1d99bd5ad847081089bf97bdf46fc4d41b7e7f20232f48272b3de5809809fdbe7eca7098675552c5eff02f4aba9acba941c2f0092cacedd2e6725ec4808222621a70d2d86eca0e3244e1532572464dc61f91856be389b124c3e3fdeb3c4f85d27bd143e56be51ba988b9b109f1d06f13fdd28260550009bb170487ab053fa31c8e61a3db54c015f6dddbb43f529106b4ffbd454ba69632c0e73c217650983b31e3cdb50ff1737ad192cf526c521505a331e91dc550a05a79edbe16cbe347455e7ebdda65a6f14a6f6f6eb905c7aa21688ff6fd47681b78aad246f12d2834867ebba6805d2ebcf5813d82e555a565a704962f226b5c866652708738ac267cbe10c8c4df881419c815b28630c0951528e29fe608615170f854a33d41567257b114f89522907f6329da7755897378f04faaca548296abe7c7d509d0bd7c14137e62155dbcf8f260459c02d74ba98b8c908907e920e5135caef74b1ee93ca54df87756a68be4c8a8725a769ff8126f44934b24b6ebf3062e7549021716893fe6e535d6b67eec3083cc142cceaf01bea4e09ad7fa0b0056b5475ac2d4e7fd3193b2ad55174a1c6cee18407572890f93429ba23936795c0883db8709be653d28f0da03ba2ac9d343a99e43227d245ea49ddaeed787c33b30b1973751862f7aeb44ac75b6404725f21a2ee8e9b13f5176cdf9494527347e18354a98c83f8271db1c83ab03eaed965e6770815a9912b59ba20b3e4ed1c64baa28205859602761a2ddfe53857c35bb46a881c6baa18936e2c31145c44281b7c705ff417ea94bfe8ca448627257fed3207429a54de9be0eae64e864ade2c28738d12dfb8ee8ee4091cc9abeb7088c409e5aa932c299a010c67cd61c521a607fb6dc170750ed0683567c51894d10157b5e17390a34de85ddb9464dc831c7c8bbefb07a49bf8e4d55442a3a9e135463f5a66e41d659442c2bd2d369c0adf14649d90d27ee504dda10fa404372c6a07158fc1e60c1b0eae4da4640fb1a515a3bc3b024bff4e0e0df4b604ef5fcfd7e3f33590c202f90df1bccb690dc4d00335e525ee901292f07cd99af027f09486bf1d508e560bc373212d816098a8b691dabaddb86ecb2d0f380f5520fcbf1d97b2331f83befbc19454581a84d898808be30bdc7f654084900d1f9adfccf28f97073ac641d70760d5d9dc9cbe8fcbfdbc091c30301b0a06edf42c80a82c202f1b3d3b59ea3d3d1c20af6d52caa66deb8e0a5700275787eac313e346cf63df4eb91156bcad3ec4ed048a9fb3665a5cbd8441cd8573ad114c1b9c2d72b23e5550f0e2afab6c5ed9e330dda498082a0baaf6cceec1bd75520863c64f5b0e50a4e04757450f09621c958aad3b75ae767a2007849f99483344dbb63f3231e1b93939f7dc0dda6612e824095c87e263512a7dd4f7a4229b3dd493f75a72170d7587afa257364c25e1c27f3029ee6929728baca368e16e581b6c0b320a9c2b2dcd660fc99c16f6bd9ebcbf243a58562864fa5d0c9211101256c7afc6c036da2b1f26b897f3d3a7d96e5dd440b07fefb483cceceee3a5762debcee8e95ecb7467631f689bd2f1a8e9ae33ba3752faab98cc394d777d5313b7f4af0bf8361de743752c44db761a94b83e133236cffb4aa594d85ff2d27299e831d446fcab59a313adf57d11d30caa7ca96926fa91653c2a334f40683df55681dc32a3bd5d65f577668fd9aab861373ce75aafefd5157fc65ea35d10afcff77306373ddad5d768fb82ac9f8ee741a3dd5d4dce3aea870bac68d99800fb28ba5cce1179d3a19756584b154fef5e086edac9a7a9493c275da0f60eac58e6f2f72c1cda9635917c0a6307efbf178fda23d793ab70dac3ca025f42db233db457f00c18b1e0d7d111e05a3fbdce3caebba17e8a862c611348fd6f757d547ad736ddb1b10cdaa6e93c6e7ad79b3f95a71924e6773ace80b6695d8d4f9bb17cdc74d79ad68d9556e48ba944dfcdb7f5799786bd38e90487d69043fb3e0168af4899af8839eec01d4a8bfec7c0b6951c1e1f683adb94631c8db9420ff8963d6a7637d7c90b71187d9107914a42dc55affb84e92e20c3fec67a459d6c276abdc3549325b985a0e7f747c34522e5cb5cc169575e8ab1d2f6aceb5efe2addc269a97dff02c102efdc057744e3ec89ff5638cd10a69ccdfa9b0ab19c0d0015b7b6ff36b22b1b30cf9e13923f63a86a72c6ea736a06267395f93781c1f7e66ebd3ef8ece3ead7a94dde93a7a9866413235c808f28ad1be6c18a461434c0fe7c5f8d54a4036fa7ab426b92a1d7d9572115a9c0f1d81f68a81ac9cedcb325cd06245223f6d7db385eaa2e93e5a05d9940364d671cc736edcc6348b6b77a13e85ccefff4785518452836eeea8f4e995ee564e2ce64b7250da878897f9e696ececb440ea6969ff664834c4d82e922c3c8b7f655cd25be29ffb92b3ddd6bf394f72c7805ed958520493411a51068efe29dc4bd323ed7e44a9b1bdc791bcd44376b3e400ab5affc235c3151f49f4e09e691e1a0a0c7975b750a3f41ce0e2370ae3686ab520fbf6a50a3655b58d2ed3e35b7aec02a02d841c90263e08d0036a5ac419d9325310a6b53cdc00de1da6ae52873e6db704033168e94b81631e41a50166c1ee95e71d925fb33d500237b1006e3d3685e18bbc6e6ec485812590b4eb9725c1c690f853e81c352a5505aeddbe3bcb41d67129be061cd9d9036839f8c1c111b3bb15693ba448af104d669031e61483d8b6bb1eaea46245bb11babb936dcd721d64f1cd0cca0562634cf7e4dccdda217ce4c95a2f915145bc29b1c83a0115428c945bd1d087f4e08a1081a39766a60a9f860b093117d2a654c2cc5182880931ad5f136423342bc69db47ec04a15c4102b76678aea5a8a889ac4775596e68f7b1e906147183f15db84e984d95ebba136ff45340a45ebc3118c80c5ddca396c91b0112a41c3dbcae110b52850e9ca603dac4ca981adf496d035ab2023826dc88d2ae2069261803ff34da3478d4439ad6fc53cef98c77718198b4ce237e68d14d6e18ac42a1416ecf9d40d9698a1cb48ddb57a0fca2cff475d3841ade192fb9f27a507da9d90988af1c1f32341e32c0e2c05e7da06519bc160fd0a20b94693d889b00b3040741010ad39d0f74e074c48e1cccc3664547e34ff39caabdf79bf3c5277216e3d4ef07a8313510df07661e72334165af5cc26956aea36a76b0b15d380ba68d0daa9b8aa95ea218a64f0dfadf9e62a3710c8f8cf520475644e868c5afc99d5f533e8a7162bdff50afa1f56c5a978ee9bf4a0da4369ffe737efb4037fcb53324002b9b7073468f9c9352a7364d168a5afd6bf0194d097b4561fd2ff81574cc8676643f6c7e91f702c85f4a029dc304afdc62a4ec68e3dc2a12bc2f0593fa5d7db44b216b45877a4a2d0d7b11c48c6235f363c2ce0f21a11886c4344dedb6561415ed08eb4395c24d56ea68534f59c018552c069c706a1203a647504815b3c0ee945729b78f3d678868eeb77c4490ead99a3722455b7576e65961dcd23043c252ceee5e0169625ac5808053b112e20b0e2d15cf6b55213d8ab903a0d504e722ee5d3a1a7bc4d491bf1499cd5f5eb171a8146462898432b63c17fa648c8bae26bd13e8481c01b84d3032ec567573da398dfd491420f8ad89c476ea0b0e04bbe050f32078d8c06cae99b0d65e9c93ec2b7ea1fb8b767f5d312de7dd3d6bf3a8458d4fb380e3d4558f8a2d5b9948d529632863ff3e7dcc8ea28c1939b9f4509e471ee1a0a85a07e496a9ad43e4ded6785dc43d36471eaa085dd9feb2ff5194176d502af96e054d46e564702731b2a82f387a1f51553b0a64492ad26aef1fd07b22252877740331f026cb67c503b7edc53cb5b319b160328394cb53217de0c9ec378b70b7392fa5f48084384fbe415911a49a463cd17d0bc9c7e3f0fcb832e7a65cca4f8cf2c1cbbba7d2eadf0deaa157518127c1957a97a3f54d7cba1439945b81a403da2232763a3e6f44a10311bb2afca59c3ba3c6f8145271da22a0d84025f8777eeafc5f98e36fd0c1a62f8fdbe2b1ec3839af7470be84ead429c1aad7be9b3aa40a454727e1d8f36d098409bd2212d9b7b70ae258edbc9da595bd91f57e4a4f73211c574a81a79980d68ab354b7506c37c70515ccc647d0275d917a2c99ad264273e780868605563ac2520de5bbb7e83f998bdc82642f0fd0c81e8f6f8354fc30a526c77c9bc033f648c9f51b4ee8572b4c2a6059d3bea96c6ec8fbbef943e33a8b8393596a48dc2f3574f2b84fbc735d51cee8c7380fe0235b2fd9bcf18225096e7f391b43a705a61f1cd23cf8dc30c08119b5102c14a525fe835539e4c91c1694fb13f85532fcc4c26ba70f3681f2b0047c378aa29906bea029e33700b4f75d0c2d57dd0308131aed3958b3f1b04566685822947e31a1c0c521f20ff473f6b4b41acd5ce3e2ced0e4388e7c3a3fca49b227d24315034f851a23b19c2702d95ba574b7bfa6b6f7e2a387e43ab4b4b735b03d7061a0083047c9ccb51d4974c37b17568123343e9cb3f78038476a32ff1d2929e8ca57bf0679d57e359cf43bd4ebf22541bf8474e904465204a4af6723ab53df393ff0626ee240dedead2fc64f2346b7cbc8511de14e2dc7e9339944b98f82b710b9585133688588e63e88921d6825f04a00e07e931c4c610de5dc42a68c87e15c46847ae4e832dd4f487fe3eb0bba9d203ec6d70ee8c09a49d15b5b09b74481d924a09c55552e605d591fd530afc70ad80098b1f73be4e2c1ec2ac84378e6ae29fb011c686fbb683e669bf3313b375d74f4d9c334b2931ea89b79e69c1bcb1e59a3243ac99b6ce0e9f3bc7f51574b0a2336c0e1bd5b7c38133b641b2faea0a17972c613e308f60c60f1ebf037db9a3f87ae0349b43f463312d59442bc5b15832f457292a72a0095cda79dd13590c60b9747fe400beb1cb1422c12d1bc2c1ec30e9388ad220948074708568b47996c4a3f6fe18c168f35e1877bda4caf9f9ebb1ad6f39a93e8af9cc652202d35cdcc7f4d738252901661639ec3cc07c31b1cd417c03c6a9f1df933dbb68cb34da6e10cdc68480b7a23ef02bf4d1c60dfe14a5ec9a18c124c07723b7ccf1aa698d52e4dfd625a29310156dc5cc2c76e55a9973e6c029f5963294c858aec6fb8f7c1249a9b5fdcf3ff2b68a8b008491b5e2baefaec2c048eb339f733aa4c9aa8b0e9a229ff163699d4f2a5315f2f04d9cfa090190f6088201927f4b3283899d40e02889e829f3e0c4c25bf27b8b985d59d333da67a7b710bcb92bcdc08c43e228943bfb54a5d04244e0aaeb98fa126fa1eb8db2356e5050d40166bf558fc5a5dd7bad7a757cd56f88b821a0b6f2878031c032182f2b9d558398fca602a41e200c626071d70bffc45b9e6cca51010004304a0aa504edee7b1ba2af055c38b0f0ddf12b0f99748267a9aea415d6296af4c16d61bbe9f881583dd328fe9a3253c67f65d084bc41738010c6df26815464722a9518084daad44115ead00c7c7090ea552248678e015a06a748e560a2e3fb2ab8814a15b3c1cb680f322bbca546382183bad519e46045ba41a9b2a510f0c4d0a8099fe3908565c80f4a4327841cb084b6fa2f3892282ee7b5ba44f2475f486215b4d9aaaa172ecb026b630978c13139e90649175cce4bd01798aa80d591e4e2e39150e52f4dff2daa941a78f075a0ce5623ed3f79605a6ce5454f0033b334b117dfabdf554871061f59514ebee049abad06ecfd4e08aa715f29a83b44062349c7048abe1bffedae15c974f408b94b6ba7879e4e713fdfa182f13d0237ee2465ea7077ed903002d38d0763a50b3bbe3e1738f2551e619675b59d9be2df2590a96f71e6e30ab547fbc496fb8d41b1bf7f82249d436431240d9ea48e76e24de09f804e35bf7bd1e5a94cc4ad35c5c2c6ca074552671e69c1cdedb278b770047b3959dc29ca091699ecfa61594340fdef3690588a2a5c1ea5b81d982ef24cd1ce317adccd859914f2f935002e82325721b223c4a60ee04680f45b9de2391930e24ecdc21054f7363fdf43e7cf5d3fce74be188b9b656238015755dc7f46a522659e2e4a385981fcdef9d971cf197399e8e4c89f26c8ac364478e5c606a4cee478d8e6097654986acd1dc8ccc50b43fa7c1855de47e6a1c697e4e8beb5d17cb4a066f3e116b489df8d7c442a0b2b818727121fa7517d1509567737f3e5a486b7210c8c239d30be00fe17a09efb66297b1dc6eb620f6965096794cf0854a14f5797a56c08c6130fddfba155ff0fdfbced8ea119d66b9a6acbd3ece6415334daf99280998af37e74e21d4f92e5d84b9f98d2903880055f5fea2b285a6e915ac8c5dc7e52f0b249e5d6195fa8d029382b3dfba3f81ca7ed08ea9a7cae3282abbbb30901bbe26de459d51146316f763290652a8a5681b4199ffc1de357caef374d535ca3d3c7fdaa4ff149afc4deabdebcab051cc9edd56eeedfe975e8cf28c397648fb4bd5f1d6142888764fee33693fb8061a5c26bac75d72d4ee1c0d700dba6d13c9946e2be873bc9ca0976edf8b3576a90eb43b1ccf6483aadcfe3f33aaf5abcfed50cbf62402bdae47ae2fb6e83f070c89d0117bc9964a53badf25ce9e531a53e03ba09062584c50f8e74f4b9f3afd26838a0bafcb13cfcccc8cc0b6bad8fd90a12d6194c94c49836ee13b0953d28c43d581b6e546de9760c02363a0f191e257fc106e934a937f57acb0c87e7a78f55efcde2263f9ff41f9a0aa871f2d781eb396924c4b2e2923c4a779382c9316eac7cca31817f1e801ff423e6ea97654289732447c52202f2a646129cf9c436d8da74cc3ba3ff4dadcc5a466fe71d36736091e943be5c025c8444ee496b9d015186184960b2da4529001b2290b86b3a039fb18dfbefff9e8472709aceeb1130c09baf48be881c984c1c1435f0ed9e63085804947fb07768b8ef55a66bac4df6d28940f037cf63f5248582268ed164c0976bfc12295cf13e2ad10f186279551308fea900c8760e7f90877a0a170fea09402e3f66aa37abe8522f54038da520499ad0f59128504bffe5030d4049973cdcd07a127ae5523d6ff0400a220a5f4712b75234c2f5ad40a7f3598e61f19453bbb8f795a2636869b2d7e4c03254b8260879e4431299970f73d9069fd0f86b541809c78382a9d462fd237e57d175631caed1b4b479b4409a74dc5148ad57efad8f052b867ffb347a96bd694bb8ebc03933a5aefa8f1758b65c24c4822de363776e268a6eb38bb2bf40a1edd459760669c26a231886b8df9dca3c11cc2f1c16830da04c16c00eaad2b24f33adda369fb911ad352d597285da1a5e5aa20695d9fdb6d3a2b72852e1e823210e28ad60d6aa313aeb9ed5531d20491868820b3395aba57ad3d676311a1787fa6f5c1681229bf4c881e85f213274bf8633146df8a734abbec719215f36f48a800f7776ba10577ddb0a8b7931d89124de071f6bb51e541a5ee8101bf2bcf8b3efac10ca2a18c5f2458dcf0bafd43d1406e488ccac7b3d44a0bc7c771b45892b408536b881c8e85db5ab2b1377dcbc9a1a87beb8ceee2df332c2f299c1cd15d84481cde222ed80ec0ac19e938cc178ed6e2b6a31b11e832900e7b378f6ae5308a92d9bd4e4ba44ff5759d3b66edf4af3836bacc4f7f40ed7a4a1c6eaa365e8c855af0b50112e7b84e22964f94bbe48955899ae2f076dde57ab5f24364fd44b003ea661909756d4e6e4f5bae9f4ff50e3e54f198a11e57b50039f9913b16e65132f69cd87731eb897a5df46d3c0e99ba431c7374f1888bbf723e4242471d9890cf7bf8b8af051ee9243949f9cdd70c07651513c4d5109c87019a226e3b71a5f039aeb27633195b3f7ceffbb6a0e9a08f9105d9ce32728fe9c3cb440b6e275bad11ef5e653eacf376774a576affeea98e7f320bdfb149d1b7c0d56f436f3c0ef280c53e1e9e803a1d9939956397d5cea3f73f716075bea52fe50780dfc237baba01d050b2e6eb0e9d896b4e90e06d2317bbe08a7cafc4a39daaaa421b1df71ed9a74db41aae9c6af0c6c1ee12ea63887aa60defa82c591e991c61cdc8753d47dd09287de0d1df24b9e3960bd70bc3c36155229c9494a2fa338d489d32a34e02a9a2d679b72097678f9d0c9c6ae53abf87657eedd0fe9a956d27594e0c8fec1fda4b77bd701db54bcce94db13b7b2bd77fbc516e06d305fc73c2bc5b691676bb64ee757043593d06e9ad8a907f88cc96bd858ec0a8d49faec91277afafbaca2e35e6067052e93dabc5bf2f36f74748970bba5cc63de808cf04d7360dc382f79742ae5ad81cab9970394f9ce7525dc3dbd54a603f47821459215b1331d4e7227d775287f9baeb6ee79d6b1da4663705fd0eb156ea6d9b15596899a8f19d5c8047d15368b7bc674de40a6193b3daeef44d0821c9e2330e961d046b9121a1b040de22d8aae2ffa247028858f9022dc9614e419845e961c880d632ff5a02cae336014503012da8bead62e574809cda7001c9cde1e69e31403f80b2d7be052a2983d87724dfcc3e477e83259e275c4ba1f07d498c6b0601bf36559df1bd7188543fd8c1917afad596c1f20c9a0c7bf4b5c64234d90cf223f9d08602012c3c1c64399a42498bd5c91c58e48fd760051ce14ee9f5fd2252600fbce4f3e0803c00303a0fca21ac74d1fd46de1ad442a3883cbffb2d272b5e5fb1e6073788f1f9b1bcb93655a2a05b1da50ab9a26f1904a0d0c84e85c5ae9dd66ad741ff4d183cdb5eb8fabd686f2db866c1b404a85ddd50444ac33dbb944418a29564da730558a1769be7b8d2f967b55c42b08ba02eed8249ee5743b7f41f49cead0d8c94ea15d8b2d7ec994933f602e254db65927ef6e8d63a3eaffcd603db8ad3c7b32a8d7128094f750a07a222ae1d3398b9f6021385dafeae8033af5dd20cb0ded8bc16d16068546291cc01dbec1a4125f2d9f0baf6b22341d039dc5d83455985f25489b2b4d7176e85a1bce6fd195e10981294b5066cb39c2944955e8fb49ca003b6cc47946e77e6f60e959f9dc34802313e5b6b0bbddc4158e43a81764300d30f047aa9d5dfeaf8111e6e30e896870f854a486be804e4b420807c44962ac480a7e83add53b1c2b940a47ab3c6fd88481fabc580d68d52c056bf1daf20419dc066b5a0706fafc0c99e0adede24ad0b9b587781428bd34b43b648e7a9bda3c7143af77103478e447004e139147d724b09e6316c3fed4e847a4e3b2ecd5d768f9aceeeb54708900fcbc9493dcc9936a5dc053fd044478376737a08acbacf141177320c10340f67b42eab2e6185b4bb04935c970be2d5a41d308e3fbb4028a78703327307447073be2d237e6c42e79dbd3611d00a288d23606034db9b76986459ca179f079d55b7467fd56e0896d6edeb6dfa4d49f13cc97cd34b63350b395e085b44e9f534f6d882695fbcdec75917c21dc5ee616255ca1b89d58954338c8de937781e0c7d5448e6f5a311b564f323825b3257f0567cfbb2acb98aa85812041aff47fe7bd4910e6f9b688ffc3676fe5614e1c1e08dbe091a4f83703706f14e8bf9786b71a521a16811b33aa78f20dbf8079ef71eae7b57396e25d80b0fd1ff09b6da83ed69dae704aa9855475497e2b40709452c50a2580ec27797f35f7d947812f551925418f6186812047bf0ef012dc505c4c56336c4e44db1c4a9a34e14eca06ecb131951fd700820f838e3adcb9456ec426f15c07a074f32ca56e39ee3d3591d76301fb6c6b29822fd6f3c01f60f55a5ec7c8becf66d2e7947d73cc167275f744ae055df1409aa33f79a3346c67559ad131dae6dcecff332f5fa1808682c22a4a635de0dc1516e256011e678f48f8fd460ef2713428f52a7fb145fd111eacb0ce0c0da3348df8f4f862e765e46d7702711ef4a4f7459c4612dccb9ae93e890330673a1e87ce789b8ba933d42b5577b90b9ef3cb32931c54aba3b4ae7aac45bfabcd4deea89e9c8bdb573b14881839e13643dfdfcd931a904647de520d2231b27dc54b6b341b2e1c79621094b4b964d44ad6993fdace4a7363eea1948a0f44a4f8166938d3db81bf4d1165900916e4ab7b8f918ba70f52d6c0c340890c194c870539e6f5a32b4872ac34ab354624cead4dda695f40fea2d931831ca4eee969d2e1b9e580379a6274fe517a3714da01ba642bf40d23563d0f4ccdfebcccb9a65c262bfe778d8fd88b5d3f221dd40a725feb36ec8b57f3ca92f4647d35ee74e22de8dc5d06a97a7c7c62228df1d1f41ea9e76e6b4d89a09226d261248fb9fae2cbaef719bc65509e7963a3b2ddd1b9893411aeb258c18e3f4d41d1e8270e23b243df059cc768f9c6ed3b82ae186d45219d013004610079ac99b6562acfad44d18b4f52a0b793f3d8bc505d736a418f1ec5e30b5d290f6044e62bd46c4497b0df7c4fbe354faad4d1b32f6980d45f12993246d7aa44b2632f1a4675e22bac209fd62814ea2345c27ccfd3eeb4e29fd30a7a701a98f64216343d369863212eb4363a98498d4c97d01c867c8fd4a2a1eae15a1054265216f9f89d3491b48b925140764e7028a18e26a5c4090b24a07adf8df33112e31a78274c0f56c902e491953524573f29b067e58011ae4a369d0a80f0497eb645fd80e747c0d73c5d6ff2c6a0ff8822920e6a8208599e02f666c9c3fa124ca2563e000d58edf24217befbda59452ca946495065c06e506f657b0d65a0c65c55030ec457360b5e25f9bba9ff29ee5b558ad489dd27e090d3179d20e6574773742838bfbb514a6891700044929ba2007e407028e280e2fe7e25c3e2fc3bb389729378cb89f6bd1c204c63674034829a53e5a524ab98d90da21c618638c9d9b368d4bd45a8d86780e6cd204071e9e34597aa5b0dcaf972c6132c4c885fbac0d7a36e5b54618e22e3fd0f21c5865adb34ee9a325a5942d1faea365f02ea53a1f2d10a057800354295f051dbd937d20c04180383d42b02d1044a81148f654ca763c8ca42e86b56c954d8726525dc81fa2703eb4773353a7b469bbbb3bf4a8378d9bc786535a9aa51494d2999259b97cddc049c13962db72514e38f17ed24f9aa8a5f45157c1d24f7a4a5369a44ea2d39d7421ea7ed274bf66125dcda4993449a2ae44a92bb94e3c5ae2d21495442157f22e3e467cc5a038e45370f0dc045e94210c727c9764c0223b6390418e41f9abc99f2bb912539463ec70bfd924c79f4d8c5c0a0eb087e7f9643219813dac9108c09ca6017af1b930e16602717498b05646600f7b2473a8b2565aa9bcf1b8a0935249e5f4d19a924a4a29b5967eb4cf8292e12e37cb7c1b62e2724ed9ad7ea1c0021326433d14d4d4f4b5a0ed970951a79f401b7f4c44d453fa9553f8917b29cba32c51c8ed55beaa9427b007a594ce18638c3176d090934fd97c1f641861077514006d22c526409cf83aaadc8ff553ba377d52055704abc85fe78fc5823893096bb509c17e397d49ae1ce2a57d07d4f3583e80f464c9e21d5549525acae2395f7b91636769283407cafd1a0b1625da5d5eb854524aa59452ba7764a2944e3a870089363923c896625625abe23958b2a4ac4a16024f0030b85f4625a39221c56c698b774b10059c52ce1b8fce3a67f5583b84ceb3569e39dd638c5718a55644600f974c521a49e213b404a909d34b6888099d9f3702d29c736a2c2225400bc5b502c2d752480c9153a90f2cb491f62190a863244626a4d4e70023dd7c4ba711262626a01764ffd96f8489493ec46907741f0a596744600f9746968c2860a0935249e59c73cecd5aec356cbe95944a39df4a2a27b5f2b169316abbafeb9cb56659b5c18d17db9b0b8249f9a273524a297dbd86b8e06a6031d56dc88bd9ddd3a77c49306e28a5934e29a5cc52199030ee855eb76f496eed6cf48fac2cdb865649397efdefc67b45d4be225a1979ceb792c14a871591bb3b248a2c182277652f4df98331ca3a18a2682302cc2b4bfcc1a3f61551b4f7a63618a21c5d58d7410f84ac88a2cef6764594631320d3d7226cb7dd07142b5e4d0ce566f7ef5d25d12c986ee69c74521f2de8d528e27eada3ae690775788eecab05e4c60df8ce015977b1d4a3d05568ab0fa137a59c73ce99794081e2ce778e84e830ba409bd0c6b12c2b741a7cc01e934a4a279dd247cb8701f207910c106d84104224165201e04ebf007548dc4a20ce8d231fb0c7dc86e60e4d16b6c750eb6b4e31438dc310582c88e359bee417f6a6de83fed0e6c777ab7c492d3548ada0e7b17c00e9c9e21d5549525ad2925590f9f3bc55119e33e146d0432ea76713bdce0ee0f6804464f801803a40667d2f5a1b530ec85d9448d45a0b7bf85075e2db565393815c715dba6043424a79838d8a76d8304c29e79c736e2d8872ced930787737a538d88a0670e3710f4d883a27b874539915b178ea86401b87ad2316f42c0b26653924b7c42924794db34e8190c10e4d4ae99c73ce2dab107a18b598c56d60cea969b469523ae79cd35f99ca6e9f4f70313ce1017bb8e7b17c00e911cae21d5549525a125ae26448484a29251625f2e72991a111466458008f00508701d026beb70088838beed74a3c25413c600fcff2c995a1591f565aabac92fa68514a69aa88522b21004770afd65abf521eeea574c0b00df6702eb474ad9556eab8b3581cdddcf0f83182093a2cdd5049c292458bd4c173a4bcc0480729a5bcc93728a5fbdd3411770316595049e9a453de78524a691fd6409bf9a99c020b3239059f2c25a494b6ffc43f33d0904a4a279d128b49b9155b2d5d76993d279db46fbcee6ed8ee274ce97f2d1f9e1367f794b3fb3c723cfd5a9431ce1ab496a528abc82a58a848aad2425905c9724f67e87e4da5a934522f49211243f849f9ea00a4944e3a7db466ad78042028f0b621a9c4ec39e594eddedddd5028a4325af1a0e7bf7d2be4f6b1f22555703b2c4bfcf292ddfbc21e313fa949b5065183a8543ce7ab32a8473508da44a4eae872bf5a6b559a73ea404a29a59419b2503a686702f6942fc039679db5e668bfc9879fdaba865ef6acccbe8621c4c99e35047b37555c96f360719ccf27bcbdf3ecdd1e51c71f8a70ca157b10c77f470ff7abf1b8aee65de76687d195b2bee72d17cb24561d63e9d0e1698e45a1d59861b4e91104dac81d3cdc772f2249f92b115cc823c229530c04e2c80f5293e58b18f7b33ba0cee60900ea8039dedee7792e63a0ce667ba75f8339f4e5a360ce7c9a944c4c4739dd8610976788920cc337aa86580c738d192e05bdc04ed9c04e8bf55bc8599611b1d85e6bf19115e6d72560dd11faf36bf77516b3986547ea63f85b2185ce47e86b7812793bf1fd1829177a51e7468e7f59b115dda2280d1a5c69338ab8322cb89f7c18c44676c9024b67f81267e25e7c9752caf92a49f3a92f414564f5335f047f0dfc53e3f1cfe0d44f0afb580c5d33762695e3f1cf55f7f37fe53931aff992232efdaec330da00893634af1a42438355b35d3333dfae99136a7c0aff14f5d4f8d4cf60d57cd5abf04f0d5c2483554264beaa84c0bc7c98979f9a799a2f92fa1a9ffa1a0f5d2bac9a5ff3402e8c555ff33daaafc13e45dafba8b257a1be468555f555f3551aeec9f1ab5f611f558655e8e91ec797005d3fa24dfcd5d77c91d5d7e0ffc1817d3aac54047ff71dfea9c126e01c5855b10a3d359fe34b80ffaa2ff2afc23f453daabff13f39b08f57e4c6d77c0dfe516123d0055d40ae0f22e5f8af55f3d0a5ea1eba70fce7e587ae0e17c1bc7ca8f916d3bdbc4c07f3393a1cdf75367ed5fde3eec637a71a32f3453cf8d44f3c84e64df00017c9af01800772cdcccc78f000c03e33ef012e9249a57e66e6f1ffc068b3fa9f19cc02fed47bf0190b0f308c36a91c5ff3abc7ff75d0ea73fc09f86bb06a488e1cdfaeaefb7675ffc36b74aaf91e3c908ba6534dac1a4243837d8a26eea9790fb00fcdd7e02298af21b51a1d0da6f91bfff3ff4383fbc6d7f89acf585c1caf226a2226385ef5ff37e23f8e3fe1c6abb06a080e1cdf2e1b36be5d36fe8777bb66d7414c712f7e4fc9711cb1a4a324a4a4a3d94b30f7520e9918dcd597ff1d8eee57eecdbfd1d9e82e122f4bc0cb47b0cf7e7bc79f07d4cde8805c34ba1e1a3ff3a89fc13e4528dc33e369b08f0af5340f5d33de4785c22a22a99ff922359e06ffd47c8d9fc13f453d355fe37f549f7ae8a2f1402e1b755259f62bcf397d96fd8d3a342a22aa4fbd0935b86b3ce454e8a97915f669a66813bf0697005d3d33f3d0a5faaf9b7214a2fdfd8b8fa05e9bf9caa1ba77cf3d98ea663a18b30e7b9f9dc452e541ee09b9171f7b1a1d74cda0ffc3dd688a3fb176d2496d482e087d0c0304e3335ad4d76a77d58610d74ff63110a04ddd2cc7a365d8a92720acbfdae1b672fd96e7dcc8f5fdedd265aa35beb7ea8b70ca16b7204efd1fbea387fbddb4807430dadcb05cc747cbe87e9feb7ffd540da58f61998d3663f67f78b56fed5bfc2171efba579f75c4b5ffd9ed85a8b27d1b755a6e53bfbaea5fcf69b957b5bad910e2ce0c7f56d9940c9ba9ec6b7ffaad5359ac22b27df63f3ec330397c9e0a7b0dc32a2259f6a7c7b0f7d94e9d0a7b14767a14fe41fde939fc53d483c227fc83fa0cc3a8420ff728ec634b80ae9b4157c6e242976a48967dbb4ea76fd709bab82295100a3374d91fd17aeef9bb37b988792071ad4b22a4b7dcfcab7d6a1fb318ee5bb3c9d0c75288ddbd79769d23ee67ad05cab6d6c6b0748fc752acb9d76c77a4fea7bd7dac5309a947b423da57ccf56f9df158cb53f187f15889615d2bfeb4e7f0c4a8049c84f8f575accc23dc671bfe80f26623d67d2bf886c45fb3f893d96258c6fedb62eabb9fcd54da6d762701ff0c1fb14fb12a48fda75825a47efc2a83d4b7f883eed9af365307ca5a6342d2feface257b37a7edcf3eec29a534fbc6aafdd9a500339d15dccf5a1f20d7a6f900b9b4ffac06b9211b90aac8fdfa147b6deb7eb4f7e17efbd845fcc33191e5877bed9bebe1b0fab33b01f5a7ce461bfb154b1354b8211bf601726d4334ecd32e1b6d2a093e647baaf906b98a3fa09cc4ffeb1eb7c2c418d99f3621250320432b4d08e5e64eb8af611fee2fb6d1666212fc29ea4f4f5fa813e26baf43e5fa5bd4d6fd6c7f7a8d4e99bb6f8598eb37d602eab9d7b48a3ff97d3e4ab560ac5f67f5c9fe01654f2166bb82ccfeb95f285ce47fc23f1c110eab7ab48fafbdbfcd569ad092e16b5ab77ded7c2cfd862ebf14a8bab674525d1ab8b3b58ef872eb1d0a401dd1c22a720141770866792991eddeb7c95c8957b84eee07b1503c21c7f26e9ea4406ad2a56cd97ee3b9bb639d7dfaf3a5acd6ce5f2195bb4e3b2db5f66b27a9c52a041d84d12615574617b7e0b78d8eaf1175898376ba11e54aa79f7d115a24bb7883146612c35675fd22d9d7fa3f12abf85db221ec1d0bd3e43e8b156fbc51de88726386b0b920ae0ae22fff4a114679be3f50fe60c97b37553b9f800830f334c4910e71e43b179d7260a61042e7293b08c6a01833b071c9f1e7c604714e33c0884f431027fe29e8b481de39bd4e429ef37136680713f73b0de5d350ef788e7f5ae239fd724f42ef386517f2e74357cbf9f57fe8630d1bfbfa45b0aff8a7e807eb223f1643f74884361fae6692e78470caf3e14f2c9ea3147bb89fb7943f882576305cd8e3e69863b7c53dd118ddf928c84e294b8673628133c93d38bbe04083ab6f860c96fb9dbed3508e5f63c795abda4e43a72727a2d3d08909a48d5544e6d3ef994fe94f9ff91503b938a41cdf421591faf67bea5b0ef7d4b76fb14fc5b0f1c731714a393eed5ef9bb75a88422d235b14f0baef93f7ce2cb748724907b748175228ba0d592fb82032517c5648bee098acc887baa92b900871eb6b85c8656b0c021072c3c808485126bc5961bcc22ece5b66811433606d3b685892518194dda962a560747d99617c450c52012c308bb5b52b001aa8325bb258ad02423a86ea9410649061165d92d1c188aac168b476b074fa20d2c43e800622c8131c69016278e628a50fa4106afbb1551c30aa0fc90c3e6e48711e47e8c8c1f62a03bf8b0032fba4c2e7cb0424b1333195a99328696412c5a58299cee32fa94b16543ed840aa33dca496b36abc52c662996d54ca3da363f2fe51877ba297b42394abbf745d3324c3b41c7be70ef6e778f52ca392795f15a6bdb6f6f6fa736d0628cb6abd318638c114208619c91ca18638c32768c115a13d02d468cd2182385106adb0cee4465507d638c14c29376b988594a658c11f5b2d19739310b632b9d18c7a5c8498c4e627412c5498c4e62744214c5498c4e8a88b02615b3488c30556b218082c51ad2252dd4422dd44242b12665da1c01089244c08f0dfb4dcb56aee524d1c6adf7df4b7ac83dff2451a799b88df74ec7d042b0a903b3856cab5157c813422863282c042979edcbc7a6a1d7eba50129c878f1620a2d292a42007325554510563879b1a28a0a60bc8853b4141193bf48450926e6bfc82576e929cdd45dfc8913b95264923b22e59894636472cc1548392626e6ef155be49887e1786252fd7a65987fe17860a4527e9942871344bc5cf75ab1c2c89ede428ee339dd2b997b588512dbb6bdc6f16c2f57b6c8bea14e0f11244174f472652f4b1c91318c0a2f32b62484152aa2fc0d229e64fb95e3b1aa5c1f4e318695410caf4c651353c85095bca428a229c7f465ea7ef9fd4724be329b4ebb68d7d8ba0dac9546fd035296524a29979052044d0b461246585ef061c9881a6c6ec8c19206a818820c205c122e21ab30620618236416a69fc24be24696ef3232b20524c8524a29a5dc64b62bc3ca22029bc32b4f4d05043de5c8b30a11d7d64692f9e2da4721057b402dbe656a229aa994e7a8b03e8238f3573fdc0cfb14f964f8ea7082083feaa4a803e4420e865042031a5e00e30ad73c72c592104c6440890e96b8e6f751d489465c5e10050c23ca28816b3ee00436bc80b46414c6906b7a18454491f472c5ffe12a20e837a702e2c60c391e17a05c4d7ce4e535a10c5df835432b5960c092b837432b51dc207fac24ee29432b5130b1a258a2d43ab4378a1408ddfa0404f2004b48d44a14414ce201a6409a6568c0ab602259168a2d40d0ac168b478b8a2e6e03b3a5a2c96d60feec856269035520118142e9680acfa96da9bb6b5784c884ee8c0cadec40b48d60071abab859865676e840fe5816efc00125f0005204415b6b46696468c5872a4730d06a0771e2928cf33d56eed4c73ba352d67ae5cec33df755eeee9693caaf052a342cf78ce6e14929e5b7fa683484f062a721e77f11c60c319d4adc3d4a1d28883937dc767747e940c185702a812d63b451a2c8d81f65ac324a1425a436310be4085f4a3a6192211b0a5107f54cf079b8ce471beca1a7b504e0352b1bb8d36a1dfef5219535a8ee421b4dcbb4cc6a5aa665d64eacd52eaba4b0062a59fcc1a49a5a3911dcbd66f840ec5bf97dbaeedc85566e1d84b5e123e0877b40760a00754437c0cc115b8c0aac02b164f1e1239b9eb97683ec02c592172fac40618225b8d4c81e4f4091e3ed9265471be08d6d42ce0d3722f1f256d33f33122f773b097a0a962a8302a51a86a6b862c50ad777b3c481162da83c610510485764432b60416f32db958955dc9f904129b54409a6e072650751b030c275e5962b7290821976b081861db8a494d246d98123a2c8f211e03975870a7862b6a2c4022634b8d2a00db4f1b721c46d1deeb9eec66dfcbbf3d760eb6294e3c93e809d1d043804f46f3ba7dce426b70dbeb5f7ceaf256098b5dbc3a8b369f5b1fa18911a23e5b67723fbb35adc9fbc1125e74dddb77fe2362d6611b3b15238531d68b9cb18a3bbadb6a672ecbc75b8bbbba34edc764fb075c0af71447b9493568b65dac69d50f705f5027be7346944c1c4703346669399a1cda091a168cc60a899944dd16cb0776aa6a9416bf4ce94aa4dc5f1cc57d548fa591ccb0f1f3f76b2943725c38fa823833944d26068cdb561e386dfc031b9edc8c6ebf6be7dc1f1de3bd25a88d371e0c56def407b61efdc93b5b6c6031acd1a6a660d15b386f2775510eff7efce531542679bbbac41c75058dddd64f85b8803f18c73763178f6a0bc823b8c36315641691e25f5186374e9dddb6873a48c75c7bd5b079d324287944aa751ca4e06967bb6b3e3de7cd0e0ea9b31cb5e90582c8c05809f78421cf934cb0b480cd4ccdaf8532396d14c9bda26372e4a8ee378b0e750d9cdcaafc56eb2b62df7dcc74def7cc0f2e80e8d153f9b7144a64bc32c0c051427191a5c754f99cd8c6234479e4add2b3b62191fcb62acb67a0bd52d46b16c669ad4b69849b9713cd96fac1b8b653babd62121ebc6665505b08a597642b20b6d28c334c0a5ee65c282df63b8bb3b0d9e64f72db0242e648761d425f6bf6ee25f80203be78dd4555ae90b285acb0ceeeeeebe832db6f020a509134f1021d1c516618c200cd7d75d746edcbeb8216b2f3da795b5d7381e6dd51cfe808232f75af7b160b8fdda731d12d8a47d37b9bf9bfb8ce3396115a4f6cf8d0094b51c355c27b2879f4ccebcf040ce322fb4c8d9df2e47397bcbf164298e079320e46fcb96896cbb40caf6210dc0c8f629c763ef06e5c55341c8d40a0d7ac8f425c743ed945c6690a58cd799e4536b2f4cf902d3a2372c6fb6301a628b2fb2fccb4511597eeab9d892e57b5c88c8f227cb06292dcaf820cb2a240e296bb26441964e64a9c550965af0f03ba4988470eee5410bca5ebbdd2a591cd94b91d0e0ea9b464ed3c395f15e661a4d4083ab8fd2f4703fd825ab584802818e17e27412d8e356f89fb5afa0fe24fd2cd05712462fd84385f9d963db6338eeb87231ac67922ac8cba3fe83f2822a9af62756cdc79e621df7b33e9d8f59cfa63c2d2274ae2ec01e73ba6687ca8e52489fe46198bb7342fab5d7660724134453d4e9246f8a34b9b3562d0bf5d53b355cc8f02b8d0ff7835d0c90bfa69265134d2929a9b16ce07e6dd4585c87c6f5d3be7da04c3b6ab7fcc3a7b80ecc810a9828d1440e4a6051854b7e6711822cbfa5780e96e5f751ed5a3edceb5e62eaa456722f56994bf1bfa62899b019a4a94cca94e964713b1f999f1965140d0f37665c72e4a14c73db3a2d675d670a515d74cdee9421fc319462f24f3c22230f5265f9feea1d2ccb779bba9ff2763c716953ebe82488236d937c9b6526d96deb66ce01c3b37892b7ad53f90be2c8afd9e6d9a9bac93df940b9773871e9b74c0ef7eb6c764079eb62ae31e3865bdf5f5147fa5331301ce3825ba708e99f581504fbf9534a10d803e56dd3c9e27e1300cad9678d23613ef69513321fc31a17c20c329ffbada3f9b1eceb37470277fac84d6b55445e1ef54560fe7e09d0a5e485178cfa176052b7e35e047ffb5ac661f83392b139bbfa590a58872495b9ce19875b29c93df9314bb7fed749744aa7a1b66ccb937b5590f9d99f18286b954b0045f950f6a06e8a79987f79992f2a42e11ed4cb601f144621dac8bf494d591ea1ee0f51128355f55f1ec805835515c7af18857de8946813eb4b1b6ef61c0d296e96d96fa128c32a217d8476712f4a39ca165e91f2a2536667e7788664540c88135febbe0dca2b639886e15e7ccae4de07affcb0942d46029b4840e5f942e691f9d86b939641332c42ebf8e0951f943212d8942bd099621d2adb2e85584619b9c6a71d2acf0ebe18698e61c08e80724fa03347b934855f0910e65ffe8302835f2d141d4152241f09862520312c9d5cec33d94927777b6d83f2f282fafb309f7af917ec53040383e19e974f611f8bbd546a02b92e56612f188665a70a121f024079e6def140efd825da6f49583ce7f413e6e73751d4b93f533fbf9590803bada475cc9fdf04e784210679bea6759e372dd8d738fdb6c5ce5ad7f9a475306f5a723fc6d46fa44b56f2cd2a723f7dcd79050c79ce258803637f4cd73027807b69c3e5a0c4c47450b499329ffa992feaa1f1311f13f3a9ef89f9d4fc180ef7c4fcccfc184c03b75e7e0656711ff3402e19ace230f73ea87f790ef7c07cccc7609ffb300fe4c27e83e9e894fe8b4493a40d57c32afa3067f87b1a525c8b6953ebe829b99f7628b82733a0cc371018a97a27e66e7550d4a9dfacdcdf2ffaab192ef6d99bd0ad29e9252db4059b4da8148db92439e910cd4800001000c315002020100a05c30171402ca0e8a1367714800e72923874543494889218c8611443310c04116000308020428841062a1a3a0324039395ae1164b40b9cdf92d84fd776aedef2cf8ac5364ffe8616c29a01ca4fd4d81fda65e852b6768406f6315546c0375096021121a6f18918b083d224b8a295fc3476b22700c84af806d66f573e0a1409e316a2f6eabc588ca254e6936cbca9d16df08e9bacdb48aacf175cda3d05a0293c26dcb4dfa84e526425f2178b07ca9e99f962ecf52b1d0e654a21216ca31a475de7c8194a1cdb5bfb96ca59b03491739d8754503ab60cb83ec6c1528cc4432747ca6e552d2f538d8bcd6f4c73902543877ee0927abbdb0e97093d82ad624ce32855a0be24c2b2e6c98e6e786e431e36593263fbb7f9a924846428faca268906b7891d4f8c732d1afed53646e2273d4f0296da96157466b34395b954d4d9bc97b087c2fcc73e73411c5043906a1dff2f872420d9c412485caca0c131d32c52a1198e23ccdf2c815078eaf508c570aa2f29230eaac0e02d7ff95611532732518ce49287084343731aa0779dbea5ca433705bdac2db4775c84f5f379c082a3d3911b02152f499549a07aaa9373f0f8dc80900cfad49fcfd26c780743ae37e75abea52b352c4c9e33236135d3635551cc63c8aaecf17c4cb7f206ffa257f482d1cf938f6e0ff8823eb72e4839c94f9ac26aa2cfbaaf9c4682b04f208e5ed387599e072d2f96b09fc5b08b907a62851f96ea5225ca92633f9e5980af0989fb6be3ae8758c71375442deb0739e3d8003692089bec00f5c7e0133ccd44bfa48a889334f6cca893c65871042d8e7e586a8bdeb94bbf9980daa80ab8b399e5948c453795b0c0f9e433c8712802f681fc2fd440f5cf32ef6dd73796bc0220702a7574a42d79bed87d42654541c87422146dd07292e864f9f0460c7cc6c3611f717af8645857423d6faba1b7c52fc15debc6528546b2ec868762cd94f6aaf91cf4ba54c6a21a0978ccb8648b348751a96c0ab483a268091c0beb3ba430d2ce83bf3e905c34869065fa6753e2d514a20919874ebad156c15927303aed5a59404217dc3e47d78fc4fc75357177c6e337751a7913b3637703371992ad3b6ec88083fecaaa2130bd2af795e1da2988336f2af1f3ad8130ddd1c5b4390361af02e59f1f5629c40f2adc742bbe38382bc728d50fd65970f00c0b9d697b13c97cfd74ec2276183042132ad2f323304af0154544ec4bd19a0754c1615d3bf9cc8ed2c4cf50f6a89aa4426a9e300f9a2209b9a276ac48900400db195fd286a5a11982e9cc1e56330897d5cde5b619f709b49833ff50d157854f06c1d96913d2a22617d029d578404bde1713c05149a8b742e9e18d83542a8cbea23a16a5d3101725769123931b5731be32f104a989d6ff64622f64e3a9346c7938f9ad5b0c7d0d9f9f7b948e2f7a1c3bc882c301650d0a4953902dbe4ce367328508ac7e9d457b17ac8a7a19a25547c48520a84795d7c82544a084fec6c397d7d33d09b958f4aa3ebaad335612f997ca526d3d1023f56056e11f10f208bc25c76b2dc79937b0f90de9a71684605d164472218ce6d208f821736e6307a097759b15513656c47d84cef3b540edb53ba61d95603a4f80d907f42e3c2c0df09a3a4371ddfcd5443cb4d1d9efae445eb2c31bf6b8ae10a65380ba5ccd1983f5e4f51fa09fb098ab88e704a3830911b9e8a5e35753c537295b37ecca9b7ed90b8db1a05d4d26cacb2cb87607c4a5d8c6424d1fc927646592e92fca2a8b30f504b25ac924c504bd51d13920fa8ad5908c9713222b66886131ae645c2720906f379d80ca521d3d44f68cbb6982d1a9542ae3cfd3cc743e763d6c85dbfc743362771ea4dbcec853235b6e4bfe9d032861b4f6fde5dbfb3a28d8bfb902915dfcfe3fba44dce473a55f7da2c359eb482c09a7a13484def53d524a241c5ce9a483369de0c05e279d83a62ab750c6061705f1b09e4fe78403b5e4380d43edb16969d0dd74c3352a62b4a462b268b14dd0d9dedee94a611e870bc268d7e5f28317a98b478bf8eb1f46bf024c8fdf66c620100979539cf3f746e32d4362128840fc429448eb14ed4a1cc6209c05ac60ada7076bb0a2a966ba0a660e519fc298d53275ac8472dc509f48fb1bf22505505e40cd956639ee12066518601ed6becbb3e9d022244138f45a310143cfb0b8abbd33c991d4b56ac19d974b878edd72cea908d13aed787789b362a799eaddf61029ce599d159ada719a7b3c6bb44cfac4221aa0d65d33538338cff546da4ef59a5c4b40e1c72832d069a45799043d9152af09bfe5d801956d07544a867bc0bb934f83c922560f9d6573d582ff7ac0203a82c789b1ce38080a8f79ece6c91fd13a6d6477f0312c8b30f28568ab29071d47ada3237ccf8c2403daa58ce953be71bad30c18e6e5f403cd2d8563a0460f00ca460945ab796e5ff267a0c12778648f7894228ec114ae149a1625bd94dda7521fdd5b9676fff7109f9698c240e5af5538d9ab342ecc03bf676287fe1ca0427f7d9f27f450bbe018a4d3fefeb9f32f7321371bdf082a92a8848f88c55851ab4d63061750547b5990c229f98d88c6225740b5863d72e4edd1c69be141a75b734039d2573ebc2b140410ccc3dd3b745c576adf3191d1a52afb86fe232b569838275a35aea2547ffd395eb71cb91c4b1802f91f8569204bb14a34515a2f89ee9a8da91a50ecaf0eca43207bac8b89e905fce9c8fdc1d0108d4255f41e33d90af6387dea087d070d824759bee695a7b2f79c9ea2d3c43f14b970bc9a9832f1d2aef8050949cbd05e4a39d455cb98a863d04e092ee5af66dec3c13cdf22d98792523b677abba7456d74837e3bb1290f183f1eefef8cdf11dd7b9346284669f85c3bb6a07dc6c59dc9457ba6840cd0ed355625fa58b26a143300550b569269763056d01b360a8507cec4be789ccbd70a0ba8446bd4e968b21e38611371476f28c40aa946f243cf9af053fba8493ce81511254f02e11373690b1372b382c7f021d00450f8cd0ec20be8b45a4d7ec73f65a1b0a0ac4aed028ef8525903a2230802574111180c095c0d19059f04442fb56ceb4b94481c29981e8ed66e950ddff73e3cc98cfcc9ea995489d818ccb1809c8889e2104d9a2caa274f786cbccc87a4f935090c0423bdc027ec101df4e65c0603365ef87131d21bac0555d08a5c4896b6a2f4146ef5f994e3555c3ae1a27772c18813a39a2ca317ad4607cdb0d13b39c1a043e0f59a5a019ff81f875da0c4ee2206b607f73af12598111fdb32c81f019ae1beb4ecb4cb9440acc4ebf83855919c0a6c273e5e152375d65d3f0b6eafafdd6c85c27f98b61675cab783c10d8e24b91b4dc4b995126d2b3ebd7dd7fddbc6c5669ddfe27c81cf84d374274c90626d2a44ed9a7c62863d38904913d562aaa8bddd1153a360253af6c479875580dc4319240d09795b0f57e48856f332981301d40f86db49602856543ced1044c209e5d0ae06f3675bb396682e58423b5e717a29255a20194a06118926401f23e85e880a5ce453fac4930db925e1afcb73b79f5f5f5d00483c60e22fc9f1593a0065920e70add1017cd71f1a84c83c7611617e4a5b7666bcda85b889ae18cc6270e1182053d0223bab18bac7a78abc9ffbca0b8382fb4f8bb13c09fddb4d485656bb3d6e678029912671f43f447cf9c2ebb5c14f876594b87698458c20566e9167546d646495466b3ae08d44387b99cba80aecb2350a831008591cd0410d0902dfaff8843fe0c8d9ac1f0650e4fcfcc827a0671c39e15e4e5f4eb399bd9f28f67513a95aeb5e7448667540703290bece59e9c6ac3346a4969769c5f6d2265a4692b76964d1faa6c162ae3df10ea13fcf5fbae7a0eb239327db1f2de357084afedf8f65fa8ce7eb80965afb4de533bc7b662c8f2df9b88d3d9d76c683716779c8443d74c61c534162a7c8d4ea8a90c35349b3bdd725255467f168c447525b6dca6ed99921238c8136f7aa8adcf4972c85389bfaf928a59a81f26f85cc8674080fe89e19a0faff35cceb78af9d265e978df4cc75ac06249f12a9838fe3f4b59427ffc7f87b790e0eec5e03ad41c009891c254afcd95e0cc727ee13189cc458a073f11f7dc51e4388ef4be00469b5b51feaed70becc70bb245df3e52943ae6279c967670e0568617e3f13000512f19de5b5f138b251c56af9483edd41f9538504de82f8937b1b44e4afcf2a77cf8cf66fff30cadd1ee862d89111fb69c5546116a9a16603ea57c2a40a72913bc1e51accba6c147160f256fef859bdb42f794f55e5529374ad2cb909e1df2410edd57b023786cd9a1c3e24719d9116bec17881de531845733a0ac779e8c1c66c6ffbbfc59b716c5ebd8ef7b537068f91f263a3ba9a7072c95e658d8442d0d304c2349094e45a823b4a82de61164814fd4d15dcc54c664673a7fe956be4167f82740b7a45dc46a0e76cb4bb091f56d748b14433e97256027c9dc205975e975cde78971b72821baea71d6ebde0e523a44c945e32be7a07ab764057bb13d1e77cc91555560027bd136ebc9cf0e0699ae74f19b2fc475ed9866ca758ac350f66b02764cb47e4b8118ac97ebce7e9cb774bb57b7ad6defec1f393e6f9ac5eb8725d6db82c133bf418a697aa95e8d5e910f9603ccb28491171a4c9223fa3d878c73850432a5dcf783e7e6ed9790c81ca9c8318b2a9e18acda2ef9f9755c0facc0741a1d4388dea422770886ed13d70f2845c58bc97672ef68e0be6a2a09e228e92ba157b4d7625356705c637b4b69d0e2f229268481bc8b5439003c05f7a85e129abf8ec524a75510278b9d2251012e6692845164f85b36bd0851bfad7f5c2f241e60d92c4ad11c857edd772dca8b5b637f5d2bb0e12a079cfd1a81c369a548450b60d0d44566cf9022101a35e9af9caa0183927b907d77daa631e4ff7ad08277bc4a2efee05c049ab6e64b2ee57ce82ae01ce71df8d303fdc7c6440398e2c7b5d11e026abcf645d04f6824349fd020dd80df1e256a92890a169cd56a5a85186b0b3bed2d0aa0211df01f44c401f0aa7cc54b06b5280259320bab0d7dd68e2871db7f290871539c0dd91ef1faf3b4d49857d3d7ab42e20a569ded80ccfea5d53ba8a3a0ad9e496894daebb4fdd6d14129bc644ef55b6444733df160d22acf63fd427cf73088396df6cbe01d16fc30051cf131d265fb6e7d9c108033a0ed2d2683b416ef671712460a5d4ce3898e00c58b962bfb74919d06f019b4f0867b442677c924afac4201dc10010a2285dc2462be84f7832ab31042233c0b90b1b2446d529516240b5fda677ef3a9bbed75d5a4d810b1c16cf0f1a1a87d900383840d587c0813bd1705e62c47f050e5d156536216f9df43c6b62044a0ee04f9e3e11c9c572f8aae358d06cfd638d9871d1bbf1c749cf05d6a64214af337a12caea3a8649070efe59501c29b0dda634278b6dcab3fe83186c5fca89138d54196aab2d36e2297ea8b47f67f53ce577873aa391585321e4769aef57276479f1404cec9d4e297486e7478744a9ab6489ac54d1ef23ca482ed45799098bd03684e6e39be035e9acd296a368d66908d6bb10e569e66bb620a1d414b3438212ab15c520d8d64511c2c801871142be625ef70c0638d2a10c9c5310887744d27b009d8e60ca6622053afc6cca07ca7825cc20587649e61cdc087f2fe4592c078507e4590d0685f84bdaa0f68e2cfbcffac4e9b19fcfb3c9bcf63a6e5f76518d7dd7ba1801899772ab900523b4869d07af5450310dea5525bcea76d0782a87245254e0b91030b9f08f531e8ac882fb1f4770ed4c027807a9f60667c0562878ce56aec85d1a03d45a2a16747cb49a6f7623aa139903b024f4305e6015a29008196844204148b8c1ea8fb7d56b79e5282bee986eeffb91c9f3250bbedb9d57be4e42bbb44359f4fde64939abfc16573223321f9ef6d9d5b7be3ce80c465c0cb842b5739ad8240dccf104ef8e7f6793f27d5d1921da879730c27d472237edd4497e74dfc39d171e34103957a6c8f5815108f9c2fbe64b28282b9843dcc794580d3206f60bd07c9a6df9d5db9e1082817ef29eb9df5aecf649c38986989fb3820c30648892e7f4543718bfc7cf939bcabb2965f9210734f14dc7b251d1c27095a9b806b460c6da44457d4d7783c4cf0065c4e8a2a5c03bbaef663b7c1918359ec7d1efc4234f764ac61f24031c012887f4318093725fc23e96d8aac44f80f4279e720c7ff3bfc1b92e127497f50fae6722eb0a9354e1d7486d81b0ac0fc3d018394627ac49eb9955ce6983153c00626668d5ec09b7d423f314d306eec73d054fa930aa4be78a9d31bd07bab0df6d351e37093a8fb41b01ca0abb4809e94bc42289d4457d7a983d902ca6340334d4074c58b1afd5fdfbf1c5f305a7c61ad5d491ed09b80269b26c625b8dccd9036872a24b93fe9be5dc8eaa171f4471e591eecf747d2f713abfdff3055015ab3cb3e2b9447cf498cad075c01607af482640b68e4258143712ef422d49eb04600c1b65633e7abbd2115df1c04cfade84b881f8099747b42a6f07873592fad8614298c1d6586c503472de19c08f12a51c4b0fbe08ef61c00c97350cdc7a5a62c84331ccf45e40f21790197d8f575582b40ed4a05da4b13939e2094624a61001b79fe7a810f37a0fb07924c2a4b207745e8acdd46c20bc8bb955dfcc2d0588995f2f9027ec38f16b4e8c8b2638ef94a6498d5cf9e9aee62eaf6c053e2c39258504c05dd4807cd07e0f155e3d7119114dba0b03175053e6f601ba08c5a0be42ec239647c88c95954237f630a841733c230d3f18395648a8fb399e828e400f9b4276ff076c726526fa85f40c746ce1b5f017011c9e562d826c07e0021a4e1db789af0896987c586cfc76b1bbd9eb8730d29cb6dcde2a6d23e0243cff3ebf19bb63b52762d171c5586eb698606862cfd22b9917cb44101e634a8e2ceb81bcdf08cf0dbab94a1eec9db843262c2c8ae200e68312c3a4214d623862af842675c1b2637a81a71563986fb8903c52e73abb71ac7b9a21cf7f8148006af02deacc82b591caf503342b882731fff7aae833b6b17aa0f81c98575a61937e91a56408540b2330da83e13c650c7a194d6020b452b9f094dfcf84a4c5a81decf9c4d5e0cc6419fc6901207d18aaf9860b04cbdba03838a159e6a03531633a2d40ac6296640a6b8f8efd94fd6596b91ddd7a08d63f4fc5f0eaf8066fcc31d7407247d27e2e814e0ce441e2c48a97b69c8955ccb86d1c6a6fb23c8cc4fe8dd56b005486750e4a187a443ddb21dd03fa7320f8c03f5da3c3f135768b2d55b66399eb49881fcf95b6928461c4a67f9ddba2652adfad4b47f6f64b8cf2ca4f82252974ba2ba88f977b6599da48fbe8a40fe92989e1500a43b75e46ac56637e24fc5349805e4b8cbcf3489f39d4de3a8784f5ac992627b9eb1e01561a2c543414c818ef396244ed38541144271780d2e4448d84410ff7baddbc100077033ce4562d6a6fddb15ea05f0852b3c0c398e6a0295bfa2d9c90c14ecdd29c937a21274c7daec6c84b96cf3140b3d673fa640766f079528cfe4002188b808d9113d49f124675dcdeb48b9b56b99f62c27753f2998762f8bbc3cfaab06265c2c9b0449418633456d761f4996230fd485db3ccfd3150915e68ca62e8f0340a025e549ce67b78f23caaf0cf6eb4d662e8966c96812d701ed394e5b3348bdd6e4a88b0fe1ad3e06591c6f547176388a764d30c16215310c3e86220787be2ea31a16b37a3e35b0bbd36c8eff5c88a7f64b1f9ec61df1c402e399915176306113c9f96bac1411d41c3c57492941628fcad6f163f0cefc4a02f75312d7cdf805f65107f5312f166c531988b69baa14d774aa5df42c6412c26196166c716d4378657d94152fa278b49029156d73673797fbc9a542c0487286310c99111ffbf5c6985de20975323815007410262b0e0d0e3bf32f6a265e5bc073ab9474921675eda294eb39caf4f94212b33fdd6b206117da192bd5ab999c20e7e18122ad551d0d48f1f7e160291da91440a473a3e79ee7bbb5ae65742a745843266d804199fa79f1d1927fbe277e598925f3326a8502aecaa92ea5d3215d2cb95898f3f13a85f793715a54f489e7e40c1693e85ec143c87a9caa041a135815d504651414691e87941c15ecad6c7f87adb76624c91ff9501f40f2a7aa59e2947a13b8f9110aa3c23d37b14b21a3a3e975097186e454522fbf407bbe02c91c1c9ece72dc141f1e99962926ac636ededff9db2187e208d9b04df44f9c34316d217d9e1bccce77f2ac23a139b5582f1c18fe2fae14fd92bbca23302a44406d8c6f5db67126f94c858c549a1bed0e30b61d2d1526fcde447db6bd03d1e45c5a7a5531ab6596ff15babc2e3bd5bbb18524d002daf030b5673630c149c60ce10b9674a0f3af231caa2dda0619121f5b5ba6e96648da212b4e5fade50d29428a4b7233279bc464e910118658ec606dd313f5cb0b5b640970734c767bb62ac5b50ab25bb21c5fe8814f2cc1ce403b1b4aca4677de904a473088a4ec1457a8a4428c45c3a22c046d64d38ad032d923047957c0a689079a5d645137e90b3263d5cc321d2f2af01e98c4b020b1f0f1ffc450bb6e31f650c9560c9cbafc5eb71f16ab4a2d0d23502781734a1450b39d4af4440ab2ea165797f1305a0f365930a685406187bff7ee6dc52b586d566ad416f3cc7a47f1e95d301c12092cd25b280a00dfa36c47d0f7e72fd1b41cbd2655fe6cade36d0723e7ac32f7dfad522b498fb94a5e026530c1e0a38521294df79735f4cc85b4111e9d0c8b8d4dbe16abd5458eeab230a628c16e7df65f0724d9b5d5afa565ff539bbd43358d88bf36a35c8eb8bc069d50e9ebf13bda73ddff91e961fce57d910544289f182b779e747dbf10565c4e778e7eb8028ea9a980433c4b4fbd694eed95f41f50c1fbd24a9d9da3c5d590eea74ed9eea3dd8899168a027f96008522f138310c6f3fee5e4136904336c90080a2e88fe2439744ea98b4965c19e44d6e64ea9583870da71953be00a118b7a2888cc4d192817d13708858fcbcde4a2f2aebacb4dca5009e99ba6c23a381d6a9ab4bf68509c9b3c6b050df92053142affb6d20d25a11555becfa24712ed947ce00071c7f7dc3f2ff0474353e92d515259ec8826833851d6475bc2cd9c2efee0a16a13674502268347dea2be41d3b11a64b0d0633c8b8de9489f7fbd99b380978dcf4248ae5520cf3f905e8e22348e6d79746fc196f3103f5f1c852e19225dbc77fe93172891f2aed11fefdbab2272eaff910a94fe082862faae5282d8383579b5d8f15399627b988e62994b257ec365f2512a0551cd1527c4b8e0e5003c493cf9ce38dc59b1213acb908b7d47a2dd2e72fce53b82eb6fa2e04218537086a8e1d54d99715f2616996f19d57a7688310fd0c5092a7ce1a5758cf788fb5d0971b662e7262edc0c81871ef5d0b65f0a8efab07c0dadbce309b162ed544377ed3f59108ff96f8971f88b444f09de7611c023b2f528c945d8f52e05b6b42a40d852b7119c44ce3f5c8cb624c8b8402a35602e60685b71001d20c8235bb5cae0d1b0ed596433ce91448d46e05f465204a3025ac365f5d8051753633db7704d82dc5ea852c722277e24740318e770fd95162df90e9ca9c81eb0390b00a3f37f51fa494e9ca6d7859d0676e4d9512d6e4f49e22bd3e061e8964f83888e88c99536ca31e2bc0d15979007a5eb4a6248b845a039ada456e9541066e9ac46fb817114227288e692670577ceefe54814f4c3aa7208ed60c14e71c1e331ad180e6a6dce1d523b5a70a2a7940aab8d5954f030ba7ccc7a82079920e593aa9d37b6fbac9b76ae17ba5f7243b763a796be087c43fba20aa8a7384034228e9156105fcea086e476f6a0f5a53f346cbdf49060bcc445dea28082660a14968d79417da7bdd819c79abe125db981624bc0558ea74f906081a85bc5a6a5e67526ab62a814c0819e64d7404d2e14de13d35ccaaa1b8251376b8781c643314a5cc0600f8edb5122fc77a0ccf8c1a81b1e7bb3d54945503aa2a0829770d88cee1a39a5f079886a747f176d0aca3c234af29d4559b3cc579ee94193dd6bb1c2025234d65a75615b802f1da32e31e8d5fb1b70952a921a2ac996637e473e7526aa048259ff0c20f7712ac99cc6d6f63a5077980797e232cd030c5d6ca9a82fc6090f7b13575e3686c760fc2bde582aa44d10bdd96160831df199cc1daea2d957ef97b5843f6d7782191380b6b362f0a939da3fc68f784f1b45f59d89661caac69342222b3056b3af21a630d4c6a6133301c4b3c5632abdb56f88458282f191d6125f2a24426678b7f963ad5a13ea184e903822eb0434d80bcbb61372846385677b33cf6b0116c2e04c4c2b178c8e8fa344fe0637f2e9c5c4cfb576b8eecc3648c5cc98404a868f82812356d4ac055e06a6f4f9a07238a251fb974911e9c33b8c8279f40d716cceaae330d608ba66a4fb89cc6a29a7b922a8853a68e32b3464e2b182e353995a1c7d6cb04c79db743767bcf659b052729baf783a45145855cf2860b063fba20f55a8e0120e0cff13b92ce4a27f4299222bb3268866a7bd513a0dbd7f9e97cdd13c414f223470bf0ebcf6085c201ac6ac2d03d31e584b9f27d5b72aeeae5e979d6ccb48cbaac101e7fe66d95d851b376a8030d47080d039876e7a51d47da79e8e0bb972e4bf1780163ff6a6f83935496e32fc8acb039124b5199e9175cd313300131f59c3797ad80ac58ba17579ad73efc98f31ec93810cbdf65de2a53002c0590db69edeaa170e69020cf4a20002b4bb7903928fcac1e549c2915eccf48f60aad08370aa9017f52558a298d6c099d0285ee71d29f19dd6c08452eb1ad8a0733385ee2ff33010fa2531389426b5b4e54ede7b747705a24a7bb2fb0955c68c4165ae45170bfcb7cef375772d72f0f6c3f0edf870737595c2e1a4eaac0335c5957db05b112a04ef236e0b5c07e03c7073c20e0e794e5482d3889ba0316cc108f82f0e5651a657e3e8f4c88e071bda860c2a441660a04d8abf9f4edb97e8b7333ad28cf8e3471d1b1672859ba313a785436f50fec4f6070b7564de8d4837549e757bc980b8370cd88341e33047cf7f7bfd91161b4c3e5819028119fc55cc6f63ff7a94498a4f2146da03786ab4990b8b56033e3634a7ad98671ba24d7676cf0064cc193c72fc4c967152666a860fc867bfd47cb60ef0b28ca29a22a1b6bb1cd86d40cd5786f797c8a2ab113a7abbde8fd08b80ee8ec78c5a69426d06c1c8a9a69b55a9d76d697ab6e780ea15aa29e6629a530379ce0d27f6b12252a1b3fc18bcbb88ebf3b55ceacbfaa0828ab185567d37777bd2d0e38806a0b395915d018b8e120cd9b82f3f95fc5b95c5d29ab041829209e0926a8f2306f4aff07b1250b5a935250afd33830ac6665f13b7692a6034529446bce7137a0aed25f4b3330b62fc75cf6482c0c59e96ca2aa847ad46392f79d96ab9250d13463ffa932f2eceb94f51bf76f9c19cb1d1a85fa72dd253c984b3e712ecec5d531ca03a2738f495d918bc55570c21035624358e40a68114ef338a403ba41618eabc1032f8805e1ec92354bf93ab7135f4a484f35b094929874d460099ab4da504bc22a2904a35cdceaa702bff7afc1a0fe52217c48a62cdfe6bca8ca16081086dd39288d616171acd4da2e24923a7c6332ace2e2d516a8d3f69f4521de6c177e56dab2ab195c1c3ed99d21ebbd3d0b32f84f060ec0ff7f223bace58770b8a0484648eca97604f6fab5e295644ee2f6de1d13e4e2c48e68f3f439a84666f4a83d74a151709983ff08586476f52837c17c79c77800c44a776d5dae895807266d6186713fb07320c9b894b040aea8cc16258555da897c19f8bb629381a3807dc0826112b21c232ff6f339619845c80a2682573441665cf211d059c435009aee5078b326b908407a472d3a4b575b64214a1aec036d6fb4b00ba91023ccc97f73910d3296645653007f8a0ae20dfb26c3102b53fc482472aea7de76137bdf1adf1ce0c03f832d37e1dd9123a9ece3daa140cde4b5ac97dca833f5711e3fb58c57dba799f3628f2ec756e2537b5116a956fa915d294e3daba8b1c7f6ef1d3982394cbc127775308ca32b4df9583d470f8e568d776b28ed7f45bd41436086801eb1f192ca6fd03452d1241e9494660b1d9b81128faa5a5c6498ceffefc83b92344464089b207b0363b4fb714b11530393b2e3f001fcc2c5eab7522bfd2cb9bfed5872c1d5c9c35cbe886eacb90f02e2fbcfb779784a94265f8ed526e495b3b6c128032e4fb7408a266fbe1e2ea65b1c12a113964b75ccfc64c02de1bbc86aa7c20e87467c9427b8c8a305c84fb398570b35027ee5e9d48fa40335e850c7fa244265d67f87cead8a02ace84e14b77db9d1bab7c4f504aac790ed7312b7534d352276737302c3e48ac9e11477683b993a27cc3eebe418ac0615edff517e338454b84a5f3e6342ee73af366c03bb40ea27b17afdb8ed4f71d00722cbb2f0097465831099518dde2c00b7b9409d805a4c625e7979ec8f39e8cc7d29e97f7b76450d0ee718333e2ebb86fef77eb587e5ed5e9583ef9f8856e5cb8fc3350961fe8fd32800555ef84fe7cfa355f7639152f669eefb79fd56c70da67a91592e89acf2dbc2eb868c0189a5de7abf16a8a474defd3bacbfa213c50b095210a6c07ba1a8df6b0c204bdfd39c666bd154d662a19601b653e17b371eedd01edab607ca808a40d9130dc07eeb095041ee232ec8af7fec875046a85239b71a50c4f482424f2665d62e27cd4e325d84bbc57265f86e7e81fe6f256c7fa7a92dc3edc34fa101994225ce50218e4e2ed741fde17f6ee99a21d8eefe22b86086428fc3dedd8167e14c92cc4f82b2544ed0583bd3169881ff6143b366a647af41de23d0f8a8526cea7301295b48fbf28fedd7690b23cf294731dea89086d7f035987f804d606ac69572486d1e2f56925103082c416165c1e557b029044b2504f3b0fca8ed1de85b0e7a0dd1ba08df520b69c0deb32f043c2a621c64b538f5ec98f9294b25c7c5b8febd4242f791b3d033439cd3e620efaba7a9989919e511b08472813094ac3b011e4cb13404c8367e2086ca1c217994dac6da74d0331ad72d2e7575c6c41c1a7683a6b8f38101e8270490c5c59cc2113a8b9821b8d33b1c9473831efff0f40af77b702edea010c2a4626e9df10b4effe873856db52455448d7d61a94fd20e4749b0959c7e63b8b4340d3801d6f91c149a6443cf89f0eedff5faff49e618910f1f887e4e8c77decc324bea02225ad41da9b42f1fc405762175974907c36ceb95746d2ea666790d3af3ea4f74e889880cc8fd3e60fdbe15028ef6847aa13eb32a4f15480a86118136c7160d571805bc248dc099e703f748e2eee883a442c043c3ad231d86a96addcbb8259995733b4f5907a1ca936d82b6433511944a07a87757256c46f0019184f0198867fc45623db219d5414d7978dbd088d5669039d43abacdaa0cc86671b46a5766cd88144d442517b57fd657102f4a2453d6c14e5c457ea214cc388c332329ea3b466ae318c9b1195ba812f3d1522e6db70423980f8f9d52c03b650759d8b25c596e87773237890a4cadae79c5dd6646dcf21c794d13ed8e9728d8f591bd68be01609d61228618a3e05049e454a38ad5c3310431856288557cad19df6c13ebc876eefe25330ea276d3a34f37d23def7ced8139d026ed98f65fde722034ffa0c05f1a5f26cc0d53eac8d31dc92c88672c5d8684556f9dd9093c51e3516fd47830c45c3f059f634b51f982c51bf2bae0c2eb892e518565a9519457cf97fe27afcba555b0491f1bac354de849baa349b0c10eeec72632472af614d449f524d22b1bb0236b521639fca5c0c19f0bac4d98e5b20c8019c1e58cf8b724fbd27da766364e4ae7a3731075e9614a518ff8528e31e442c98469159a34c322e1ad1aa59e5e3d3d7d2709f6cda1b4e4ccbde02cc350e64ef3bdf553fbc6db0f06a4dd5b733a4569bbb59d06d9f636c5751ebfdc329477d9d7c0a4e94e00bec1609fb8a821b552626eafab9efda71f94daa14542cbe00f5c727cfdd6bb1f3f453b9f899def1609b7264da844e47986dcb0ed47ad958fb3e4030766121d4054da643005e73497ffc36a4301799b51391bfee5191d89740d48adf3f7e0c2ab26d088a41453ee73d7c540a07727c5efb1687985c4f7acc28e0d90f9d9739d3517b3c983f49c2cded6d7f590e2d86c28a728960bee7faf701515bbc8ac572913ddae2283ba29679b9bbddbc02870e9c1d7ed2ee452ca33f3f19b5a92eeb2648bb5b102324cc0ae8df6dc76ef2f5320c544eb0a0aba4603ff40adefd1bf479bd7dcab8c1733bb082f233d4704ce532a3b07c8890a4b4fd1a574aacfd3b4a90eafe01c58601423a6309c8998de210695b14d40221b66a8b83163e820ba0aab59d5aa993188c08a857c5a60939ea83fda448065329c7418ef09a2022cd9c2e734d81dece84d7ab3da3f2b17e63d435c117efe54847363d624bcd2ce9ef5be39ab8511b68b555c1126697aa4816fdd2513e6226111304cd89849fa8c21cdeec1baa0e85bc5e0b91004c6e1974c9026da792db7f79d98c83dc53e7f2725961dac8aa243a6f854e68d95bfaac628a49889d9c521634ace21bef42a4f6ccc7c3bb76210ba047287760292ea5846bb657607afa94d2f9b40bf154a271d892664e9bb4fbec61dad1d11b351918ead6738fcf3cde70386d6abb527242a39174e29e73b881d4b36d27ec4c955fa4fcbc215030e67e033a68b6b5808e0992169ed1fbd4bd137f0257035e14a6d653e9a9fb925f6576a193dc6282f7c29a6f82e02dde9a1107875e38ec0b275f6239f4327ac841f09053fbd4b958c894cd6aeb15bc914ae631a220cccd3b0d35fba357ed034b00de1cb3560dc41da13f2e782672a169801bc46f49d86ee03dd7fe55dae79c775610f09660989575e853992693df3458d0f0a2c0f5b974e5c0ab7122e6c7e97188f44d2b80ebc2965caf5b11dda1bf705ffa4e8fc1200166a72f8ba6ba77b54601e8bf70a652fb335615e7ad60d6c0df411968aed0168e448eda5198f780886c0814323c616d42b42d84eed03fb7aa9ce1584437c7d10fd2ffabfbbc603c810e89bac01f29275feec499c643eb77c121912c354f8d1777a4cb1dccec39c2328ee2eecc8ba6ae8c725aae18f21d81585ad2890fbe5c8bcd1a6b9f6ea72566090f20baf3984178f41c9251a82222b1e70343b500c55c70098b9ab5d0dfe08d4b43cef23630261606a14662e304873ee9a8d5f8d9014b2dd8f7af83b8a8dfa57a64eaaa6b9b125817852ddb70c216548afe0dc7092b26d1cb2dca29326ff28e81162ae03bbf112bc0750f740c68d323352ca95f92d5cd2c7b872965b2b4c7fc295d62f11407b61ba03783f920e408d5fd0dadcbab286b55b061b855d12d841f5e8caa60ee03362db1b6d2c1ff1cfa02d6e82c35c57d5beb2b0866595d7440c72e058f98a9418f86abdde71b352d1531fba52035b42dbda41b5b2de98f3cb76346a35ab3f2006c2875c9f977d531ceabf5b28adde219f8908431717f33dcfea93b02526b0edbf7bb3b36f0218389a74e29e8bf5d783d3ab83065a38ef63ad4889832151b6bde9bab6e4b008d2ce03996d35795e99d0bf4a3f03484564fe26badcf091650def45e40ea75cc430e498c9c70ec1839274bc20417f90d776a1a52e370df9d17314b8e5b205b182503251f1c245f26175342169db628df3535cadfb11cfa9204063b44b853addba3add57c1552fe91cd7fdab98dd81faa1fed9b8e2a32d65fda3b0b6cd7890ddfe1e54f3b7a7ed3c48e2979113f2eca4e5b3075c7404f717212d1c4ffe1d8d0a442845bf355bbe7fe180ec8b33ace3f708a883f866c0c2373ba8ee8bfaf423a113b227e1f88045023515412652b318cbf0517cb6b3e4a588e5a73859d26c117c0ac3f77a59a4554955485821c01df0a078a8b6543231e4455ab9456244bc39192470420489e7982ffc90ff3e8a203b23e2862654a47af8bfd307e6368e3a9a69b27c84d134c1e0371b66c6078aa009d1e53d9773ade5d64b2534697f7946b2999f76862a5aff297845ba2c847652068e43830927ce58656f035dd13757a9bc55a92fad47e7dc5ca8bc42dfa60856cb82473d6dce270d0b65171449255c04d206465570f79780ebd2907a216f6112aa96856adb666e4afd02cd943a249c0ce948d2e91192fd18e298f18a7862c9472f290e9d9254210e823545f605310e19acbba0c9c235e6105c86ac70a0c204b945d33bf9cf45df376b02bebc790b18cb3d422d12a9918dc01c611edd7db0d5dcd9db8ddcf761e2f6aec5ca7151677b9ccfe9cd25c53e588e4e95de8389adf0f020cc5fdd08da836c33cc4503790105054517c2b61e290b1818c6be015bbbde6b6dc2d9273e54e1488ad659b220673f01489d8787264733a37a53295a8ed7e881a11259f976b0f79d51bb965e4e38c6ce0e729bad5dd9f898ae5ec812d2e8e5622aad87a1222afb9543d30da37628d099e0899c459f131e8112cc3287084e7cd2ec269db488d404a34440be0ef505a290d6e4c5941695148c3839b443f5d48a96c63eb01ed46bbd60e9b57e414c2860e05eb62041290f9e7e794f371faf842ad2c79d32789c70ebe1197851816cde405f772f117b3c0f9fc17930a3ce8c328c1d31b4e48cde913d6431d8a5b87b1e4e9fecfd1c4b3d4fc62191ad4c2e049331e5d75a652f2420cb53040acf70cbde66d51e719f7a3b809cdef7c9d7c8f3b10b48c9db2cde1d0827b5aee59415081fe44741be81c2421ab4c04d89f56f76de64a5ef0359421300ec013edd52db215cf5f0b1ccbbf0c4c47075f3916d47f90970d15cddb0fbb65e91167ab478effe40d20fa8cec587a77f588fbd8eb4c18bd13086172391927d0a06e9d36238e2003f92acfefd64f09d1c59b18b706be370455fe66d6f5ab9ddb85f48d64b4aa0f8ef478982dada015d086b7e6f5083c2df88fb53a64057dea6a9c570a5e42a707497653036756e95b5d84f8a8e0baba9ccca6e01f5976f7c5a7925bf06553a0262ac52c3b8b2031cda6e8464921f6603a30e454be13c47ac5b114332fc6fee7c7a98b33853eb03f288dad95996dfcaaee55a8d37190b470a24c9071640266b96e66561590692dbe9c2466fc72fad780a9eb816457b3eb03befc8e65fb083a595b5ed67f88047af5fc8d04f9091776a10b5e428b4e54a2e5ae27ee870bd5535eee39bc255c745e9c2cd3f9b850847d7e706dba8ac5a351b30c4b53e598e97e5c88620a6bae1ec3be9323c7ccca40ab85b37447d11beae646886d8fa2b46735a81eaa7b4df7ee08f02ecc35f9289b44dad66bc94c617a8f0c49ef31d0347ed706a006699f1ffe21c1523d7d4061d2955da07d58bf9936a73927bc249d5dfef46b43d037332aca67b4f4a1ad398c220f89e5d25749607dda57c108a7843c63eb46b48f60899b7930f6b0160ddd9b61c38f7ae412a0a050189ba3fe000fb479b2b34f6e15abf2f168dd589db7afb0ec51b1a745d85686c0946cf4242d3783e81d6366c35dbc0f6e12d06e09bc7003272bbec95dc6826c9d8636c94743ac98b47d4d7c432cf6a92cba316bba740799f1db652031ca4cb2b302e5ca0311c844c4cc76e0b6614e854641693b94bbd1962c1335eeab76dc5121fe7544ed875f4c1b6ae827e5f307d769be673d9b5e36d5c2c93d73a7a370b3c56d91c2bc7173360aaec79c5a46ca9b6e227909faf6cfc5632a58c7c3af4764e24172c22198a2aca608cf3e7d972ea8af9c18b8c149b9f3191bbe19a43b6edb472ed02dc1f3d0bc2287bdd0b9afd13a0d2e4d247dc6ddec8e53b6a768fc124a4437044a58ba986b47186939b09cc8e4bd09a62940c6c8df8de40470031594105670904a41977d9f20c532027809f10606a15e13ab03b2273a9888941e88f0dc15754e7cd05afccd49ce46c209598785d1659b46e111bb2c77d2af4a4353a7b45622d040b18e1cdc2a968a96754ef1d148775dd65d93922eb60336c59971ae4733db2c334814ac757594ac82993a48c49e1a5292c01bea3770ecdc55603312825a7284f0e63e49d253a253b567d148e2143a82023e1f079b3ff014e9ce60085a443cf7ba9ce723bb3fcbcb408747edd6b73f5cb87e706246bce7bf2761cdec151832b324afcab3fe8ff15504a23408f712ff54b0593ae70af2359b11f0216d2d20594b15eaf38f618ee813c6e9f09d3e33716f3e3e8e9564e510522097d81d567ca2516cdd206bc27e71237607c9de71f5f50228211a139240fe43b029d20f9c4ffa2e0ea803cb1bea7387c193d09918969f839465423250f31d148be02bdf3b87f935b934c653d3005afc167acc632587123c26611915213613ce4bf64a2460fb9d264356fb233cc76043bb4316e98eed8ffe0cd1daba0f7608097c6e5f0a88f4df216d4aa6c3c9ed6d3fb056ee6d885a07175cffe5fd8ec728552b2cc617451597aae0da2374cec5eb5978b8953993dfca38de2bfb439a218c846f00294f2aac1d7f7d4be860e1c53e952bb0b37b72a9f68ec7625ed21fa6838fd491d30e0efc82b60f31e52eb3140f888ba0d747f90dbc0caf7256f89a117f269a10c4f82a177af75e4bd57a81aaa8e75c630ad3f37946594e829ebe5d53621f9059258a898ee600180e8041167151d7ba65e95b629a0f0be2c094d7a752853f0b4d5394d920252b096e993c7390951ee49264049b4acf320574d402894fc86ea03a27ec2b337b938e7b2fd9af8abf04192d2e9549e084f5833b839960b57e0a28fe83ac6887f2165c4105cf59003e60fc74d4126cc62b184d67b1448bdab78fa6901efcca2a97b789a5a7986da95a68765bee96298122b9ca50d03e07e76faac3dc6488146520a175197511a2602c295034c60025990c80481dbbc757659e3f4473ee1aef59e9d14e20e3ce072cd5ed770ee673e3289ad49bd23cec1777c4af60978e6ab25d555ce5c2e3a70757e696a0a2c43fb1b3d6dc89162d83914918019c08cad0c93baa46b64dbdb81eda630bb0a1901a8d7dc158e53a02b1fcc0286cfbc4bb65daab1fe95b9f2ee029ef1f6ccc8505dc7265c1988816403dc33a5e8bb4305d2a6e7f792ebc55e14c44a45467c91c1bc379ee2dfa5373ba505384768c9237c5f5dc7f18148be09b6a02122a1743f2da301081adc1344b748157c36ef04bdfbc8d17670d410009a36f4e8712c8459755cf187b941608e51f892a758a51abba5689a669c80eb7caa9c7255839107aae2234be9cb6fa1924559d92822a959e0501e156b94c1bd3b2950cd3a461e4d29dbaed062808a85edcabd133560158a9ec0fdbfa36b50fbcdd95c2dc22ec92a486d05ff5a94a3731eb586dfb09ed1c1c384aa104444bbf551406f5f8bdc10a49c09611334b83440c56a20d9c6e0ea42c9b4485b08d2fb3d2489674d20ec0b6af0e50cffa548b0f892d535756824c7bba8160094d478bc5b6e10e152705a5a9d9d329c58be80a912670b7d4ff758a1967b6b480fb521bb18a48b2e802abfac95caee15b221d6b9dd72768595584c5d7b0e24a8d6d6dcf498a9f262b7934380ebde5907da4dcb280691f5fbb672651bf18c3b93690e5d188aa147fc92cef1abc3791bde43df2105904527f987f176559e295ff9850790dc71bdcc60a1d716843e8535f2dca2707041a9592b0c2d287d5824bf74fa68368dc07a2c6d541e0b4117c4186abd814aef8cf00467628bbe967273c36c5f126e905b3fa7b65575f6e636bafff7d7c9d0fe371fdfa942398e63c94404ecd2320e7f892bdec5c959c6720a64dd0090630865fd1541b3e063c6ff082ef50ba212aa5eb0628bd135a56da81c83544949df002a012394738cbd39dfba21aa7784ab98bcb8145ed5902e4218613ba62d0637073437236e3a02a7f0a563cca9b3a9fca031cb180551fbc06d8316a86f1284f3ffe84021317beed54cffe815526cea9b8a162b01bae96c114a5ce55147d500a20d5201611652b534c274e1d4a26220c08a146de942b1454b7cf377560b4dd24aa4c114b24850f40521b56d4d19e60a9fa634406fa0fe7a25d46e14d8eb0d30aa56997d3b1fa4eb55a740d9e107dd1ab9707ad4868e8b5a89d16605911846c8e74ed420ba5f86a6c545b0142ce366f877e939f336fce276e4313a02409f906bb024e0f8ac7d5a1737437b2473234ec151b6f412a89ad1533a569e94d2d44f84976a038479410ba8e61fa04d39c626d6a042059d2c6b917a375cf6c97db1a7fdc873a5204795ce9293986ffc2d4dbfa0e494daf1d63dafa2a26f0ee97cb1a961d78d49bc0d99e493b2e566d43b34531ae761d8b9a0df17b18d5da8e6a433aa5fb231a92c246671b1c5836063df4583882a64edc7202f6d3dbc96df487254770585871d0d3eaf47e08f431b44d27b73be881e480f62f1d469080b89ca4c2a5f1d4930a172ec3089792a570ad338456ad57a3e500f1fb924af9bdf2d89de4dc5015e8ee764caa34816fa3861b77b3cb050cf29058bf643944211592831d6ee9b7ade0289c058026ee947d2d4db1424c774bacf5426868fc94c6c9cd12f5bc9469e207a85df49172acc92e03118df9c8fc6e5fad69adc342bb4eadf143a387a6cab1d1da0a1400e4222d4c945ed5afbc2f3a342680e09908cbab2f674f79d9cf27c0ecd7d57bee0be9345223403e10533e3f60dc0e665e8dcdd03f6afae734beb77a56ba02e1e46ddf28dbbeaad342b7f1fa5cf582f3114712eb278231aa91913c6bd2706a0da6a18851bf1fcb1a1b3d89ee50f4ee650b2fab209730de2559875d97c61a0a4efeea0b6a86e9a72dab2d2df54d0bff2c584e7df9462a8864ac41704ffac85733e7f1f667c628a177224b6698dc94203a8db7faef7e7d7b05687b15831f4b14f30eaf737ade0ac8e310a39cf76e340dc65e036611029cc51e2971660dbbc98fbe1885a4587cb58e6d2aece7b8c76daf205ea0edf9821dd9f2de3b3b5b634bdd4f42134f2cdf9b9d8c52dcd911dbeb2cd82d6e2961a6d7620e87013a84c6a0f7d0a7118205e24da5a598a11d242ee2378c8bb0b81e69385283863037eed40550fab0305875f059c04245a42efeefd62a67709a6896a11d50d7da084d75ed6d0005a03568c3119d15d5264c9f98ee0b5f9accc813d8309c5c8bcc1c75d0ddd01a669061987042f057a8a0e0071a7833448e0a1940d437877232d001e2c9b5e8ad8321ee1dd02a67e4b3287b203707456c7366530d18991198c25ce8034e4b36df61cbd4a873c8f56bcdc1afbf3623c016765dac1116d58ea98c610498548c45280342486471aae59829761fbbb6a202358e200d3ff0d11dd196c51764a9e4efe12a967c4f07e04fd593b20e406c023303e2c6f4d94d9e014ac8b4aaa1f90d25788eb5d22d74cbc270564891909d2f635927644253aeb6fa2ee0a0a7f818bbaf40e00c8974c478ba45b9f1082aa24a14b0a95be5b858c2ead63ccd033ee3b1eae140ef4a55c3e69bf67b4771b57e4efe92454f7b1d9a2ffb18e0dd284226e79dab7896899ba1790c8e0da6320f6eec4740884076211dc035e1f25c5d667f772be8e37890a87e1c4cf70a00e660e33bc5b9203a08dd2a7cd8748192ef443644c71010812946106232ffe7b59fc70a5da065e46cbb922e25493b17858806e026e9003ded4621c6ea31d37d5cab5741311a936d740780d90f12787d885233396271db389d3f07d175193018e44aaed5b0cb31a8cef981a1bc5a159ef25321dce765f2811b7a1966768a504f2ccb20dc405d913fe11e4fb2c5f323656b8ae6956da2085860246b30e6e5e0c135ad40703afc2daaef0128221b8ec984d130ca0d7cac76a0e836f080a4a4da1e9c1c795848262ba92387cb4e0b8a1d4f29055d749fb6934346e61cf1c2b95f8b86b478bad7bfcae81dff6ff4c4e1fad98e33454babec921126dd17a8a72f887a32c21f5e73b84ac6379c706d6b78d2ad0cb4850638d5053103b0ff42762d3cc41f9721d9cc3cd73fe456e58c2ab9cce588af394a14bcf3683bf611c51ef2cd49ab8aaf4e67a5bd0c3de4059e891a643b68c74623c9168322f22d7818170add4cfd20ea94bf68f3a03f7cabc4e9a256d6f9d8c5c875384ef80e1ee588ea40f9635a94316d712d28a09c20bf3b6364fe01efddb04fbb372ab864b20068fc2fdca68fa8e66cb521216e8b4d0791ba23e63bb62b67376c84cd0c364f5e90aa8e472f02a5831c4c8f1edcc1a849a44529542f0b6de1f335a78e39c2a30ca2810aabe9271ac3d31ecb5fb470a693676a68a368219f61d4474bc2ece8f977caa040cf7a0e2f99e7116e13060763f1bb645de99779d4f275f1c50f60b13c677d41a3c86481226dd51600891388d8b158d191bcaa89c9a9a98738eba3986949508841166b2b4a60a36f2a5dc28e72e88dc320d2f8c97e3e7ed2d259e4c5a528974dda497948191bbec2e642dac4409ef4158a0eb409ceede90e318137bfa48768a2bff4acbea99f221d44bed931a6144b6f188085e4ec991e41537d588c51bd6d2c635442fc3c9e60195c4666af05724e3494cd5d0af26a61bf38ccc98d2ff80e22825ddde8d777f44e7ca78206c7747ea0e968282105488f64e2a168cea86ff523223622488819c5f0a9a6b9a7fd80759817f33ad9ea0ccac59d4b8646414e5bf84552f110bc8e83c4d8026ddc1b19bfc5002697f5bc03a9f54cbf21d9f4b40d65ed14e7753074ff50123e2d9e28092f0a6757aede6b3d73b8928cfc6b96b2934c2aa48eb88cc5336269ffe37cdd8440d9481576e0a8d634f34a2b0155f48a7e98665efb088d9957fb394b4d1512f371b2e7f0103105961e5d24a6478aaaf4cd4413de3336b08996db0526797fc153892bf53af6cc0d2dd7c5dac41a75d92d6c438b76eac325b2abc01f8194d0b916be682bce8658c6bf5243ab436e84eb5340e82ee206de118406fdbed6cd17cbaacc693572a83349a045d913ccb02e1a5db2510b9aa2696b1406140323f228e7bd8d971054cabde0db581f678ff14a07a58c12b0d44617118b1b468c2409ebc3f5c54affefca9f09135c042f11abe6b0a06c8a6697e0c46e37dfc7568c4c9319825f328c15e8934571b383a0de356e547085405120b8d31c6556ca66694dc78c9ae76fd4209b78e0ae96f229633724a0dcdc53499f1472a41282512e99256760d4c0b550cff7c41585e30c9ea4654d1a092d99e22a97c898a4af29de0d88e100361e11625877999c6b32860e3494c7513ae95545af5d6507faff50116e9bb46858c451739d4b1ec161bbd9b1fd0c4828949a80b5a4ae461a6be41462cd882a75357c4419a1efe763d6de05c64857c461a4e266f227c80d10b6798af4e077efa5c70c426355c28f5846cf193d4b0b87f7dab9b7a8713fc9a46864ac656e10724572c78613c159a31300f42ca50f9bc4cd7de006ef0c983f700f4aedd792b31472fd8f2c4df4b7692f9816d4353584ba81aeb00321c5b321a57512f669ea56951c6eb1a8274463bfde7e926775400727fc330e87fa45bec1cf7de337dceca0e0968ac43afb0ac59e9879db764c2fea3d1ccf1b03db3f241b80782a980820d8aba2657621952ca190888f10d99071c59454fe3265fff141a2d264d051190ba3af48ecdd2e76198a98dab86562a040af6f6345cd2d57f584dbb50e6b5962726a3b4f8e6442835f0180bd89eacc3c4e503b508d70ade50e1380f7221fbda018e2b452fc92fcbc68c2023a7ed80c7f5da7b7ed8fed0d8f0a7154ed79b13ada2d1473bd7454232fdd474bf2b367dcc2c80ce4035acdaa935920ce424e074d0b92bb3c0228dc10b203c6ef98e173df70d33396dc690fd53d2b55714ec47df9b43305af9d2f1386cb7950001ca172d26eaaec16f601985f92ba529b4fa61a21c1fb4eeab4b20679c14676b72df796322529032b09040907099cfb10c077b2761310d08114d7b66a8ddb3e89807eb20e8af2e4e049b49eb86a203d3ed8950076160a1405fb9edbf7c4164610bce7f23d9185826905ea2651e5892b76f5085d0844ee68074313388476aebd009247fbe81e1ea4a2dc0cb6b8f375a0b8384994c9275b1d4871a75010bbbe29ca0f7090e3cf771f5059827522abf31fd7cfcf20339de77563cc3cdb81c08761d54a9269adb5f36d0f61177b8e042225c764185a98887d1685e131475c2781b015699b7d7976131856ab48c909093204b4f2832fe407425ce99c0bb1f65efedcdc2964c519c4ae5494eb89e30f1004b00b08d85f5bcfe713863d01a2eae2b2907eb1dbd1d6646de5892310164ca215ad759722489865815d720c659f42cc429dc4154bc8945d1d282e5745908257ccc7fde439a544d383803743d2ccf71a6dfc089e6846a4d17d6d4a6e2b6d1c556966779630e9ccbd0cc15309d2a9004870fd47e7e9d88f0e686400428c284a5c61236bf7d1b19f2d47552c39a3022a88e822fbc992431ada1251dc944124eb31a22881860b2654ce3881ac7d6787cbbe33c3e5a4305e84915aa061f2ed9c11c3a4165e40f9766e0cc32667e6db3f9c1c9be3ec4340663f893e3e3f1b105224a9e7266b4370fc741dc7a938c467c755492c0a86286794c8a2ec4758f43a4fbf1a077572949ffc8a3ed755228ee8e33e12ec2b4389387e7222383baef223d7719c88ca4f7e128fecb8caa5ec0401949f421655853a8e13a6e61cc2315b893e33883614349bb41b3aa9a99a8d93862368e518f88fec029f43d32f8eab70fc86e8336f57dc117d66ad5d85a3738b6e6d67e24c1607862c4e64a5f0393b911cdb39ebd68516a5338252be65488e7ffe7d0efa90cf41f1f394e8c39ff8f9c8b38f1674c37b9693a3734bdd107d6e38088a3e3744ce99ddc41aa62cc549185cb00a71dcaec8e2fc47767de4a41d97b29d9c948f3d5b39fb8efb6c1982c33ff7013a80ec8683e24af459f996213b0e8a3e2b9177441f1e126b98b21b6291caa54ce5230fa9441687e3528623b23851481223ee88717cc7b70c516de1dc676808e83ba24fd3c41e92fd1a39a354c85d11f4b169a07864cb101c07838ee088ac21a813ca4f2c21a02f40ca40915beaa10c2080309acd645dd4af761f2096e1780c22cac71efaaed58a1acc0d489021a306473c120328ce4416154fe85bb358421c0b8e4867fd6a07fdf3b16b5476c9486326c836c4197552df5022eb7394c8a2de2c225306fa94814ea3b36f500867d4af76ae261b29eddb0760c3f51f3b5a7b07a59b754060378b8a94885d4d833ea85f4376f5e3ca9532938c06bdea87f2aa0acc4c68bdf060c3a38dec5700aa40c0cfb3fac76eca468d31bc1501b8e24e20709a7822bbf8ac5dad7c0396816ab9239dde430bab59d4e7872fb963ba953ba65200b03009fdf4cef9a61a7c8b9e51470103c33a61869f32bc4cf3dc6340eee81668f003ec8d7061d81867bb7e4d9ba558ee481f845d16521df55c0a7c63cdeae76c5577572a522bea9c73560084b91cd775950b5279be451596d621c5a5ea910473777b0737706f7a12b88b06535876493074f4e9a0ca2fbb54466af5d6a18a136a7d41f56ce59aa0799c7901888f2f33746b413b57d56df82a4a9bcd665464ecdddde1d7307cea72c77434f4022edd4d69534a45d60954649d30cecf792a763d4017b71ea056fb690afa59f4507ebab80236ddcdcecc4a6ce03b9819a15dee486bc5b91c275e9cd9fa1685b0c08c17e88f2cf0b0c035275e64585819b5117e4a294fbf40a02d2ad25741ee0042044838802a940ae5ca4fa6b3ce4ef4167bca40a9ed39a7af90a89547ee5968bd651728774ca1ad25cf76a3f723abfa7c1c2fc2fbe0e6a77761a882dc319d8ba4a41c64b95cd925f5fa34c815acd26264f960d714523df65d87b018a69b1d24b877e88c57d609236dd108bf65170ba08fdb457c10c4ea523a914ceee0061a64dc5ebf917c963616dd4309008aee485734b494a7484756fbfcfa02786fabb9565800bd380882f714c51dc136427fce203c034e94913eb8853f6042e98d1c1c213c86beaeb06d7a2395ef4c41f3ec6e6e6ee6c9719e42f2f37b588b1ba4923ba478b999628c74010df602a8ac36ce7f9327a3b0704e64ca2a99d516f567b78f1cf9aceafd9af3a924d919fa524a2d0e195d9bca35cffab1be114a9f05f02dbb7e827412ca5d74ad4150ba2395b5ceeadec3204f5156e978802e6efbec3072949a52565f9c8f86d6379873006e58f0a17a813e0b3e7ed2347625e58e743a084a2048a9486d334bb28b167d327653330e0ce24ecacd96343593354dcdd8085457faf35f6ee8a58e7a794aa1659ccf137c1304250982d27520a0ef9e1dc5642b2e056b2b1e80d25589b30a8e47e41179441e11f5e91e910968ce5991cc0cbed63ab65add2b6bedb9a33e6bd775d4274729ea8867c760861a32cd66507c3a454f87e40fe9ed75e6119980e40fea6d7af6b122f9a6b117458b19bc89d6b1d54a4ae9995832c7712936a8a25492f41155a453f4c54ae9ae9100c7563e2608518161ed5c3cfb20c0eb0c1ffd2a52b9cec8e4f1453a268d4c11549307fbd8271f1d0301bfd857ab7b977e640c04f9aaeee313adf8eae306afc333016c48216c8074558741aa60e5aafe00f9aa9d38d6af6354df2175c857f50eab02be6380eb4718bef3611703a9a608211061503d08345812d4a9f9a48fb155319ab62a44fcd256c54b063cc7144d84a85a78140bfb8ad198c2f0e60c56bc6298018611430d94c989649737d90d0fcf4ebf5879cecb326e922cb5b1ba756964b5e2785f76a29439c66a6b15c515eab58dd49ed86ab17141b620f060cc55dd295eecd1ed97658e386a391232f412ad95f669ca5eb05b4a902f4ff24465cd1f98b2cdff9c40d676e4c119497070c61934b4a0c1c6b7bb964ac08383c8f6e4346eef12688c971eb1049047416ac12d18d6025a0bc030c1b33348e9172b9a524aad52170a5627dc9252951f796c12f77b5946090a18f7823638282ee7c62be27a491e1287e5da1b38bbf6c81e71bd2c2c0e17150567f3025e6181153558d0c3186ddae8a10d196fdaa4e17eb016a70c0d0c421929f9c61c9da05062bae2067a61e28959fab22cb164924c42d8d0d5fa25db8ce086116a426d96e0300216416d664b8cd8bc4932021921364a405904b12163c90863a0b0b92d19218b24be5165872f6754375fbcf8927cb9e2e3e14b13dc08be28e1c39723a6b8385e96f9e2c3165f9270435ed858bd2cc384142a28042f7dce6fd93d7934ed168179f2e4d14cb9daed9a3f44a03e76c3b6506efcf1b270d57ad78980abb672421cd759963caad3c931d0ae95a395a34d2827542b07d3428563627253ceb9cea5e7f8e2d9c7ef7b2a2781c9839d4747bdca1f52ba354d11382e06eef758726d8f3906369d82706e7279a164e7d5ed9100b53127b74a008d953c289fc00faedcc5137b4225a5e010324441238a282ba05bae0d03e853a3e8d4c50da634c0313a786f88be3040f68d49091cba204b50bc21383568360a0ed5cd907543746d51809a045943c88d0e41d0406212e4cd1214364041d2305a12448d5b193057b494c0149d000c13d604d7f4b20c9821286084bc20c058712136ee2350f27342b9e5909148f54c1d4193afadaf7504487c859283ef50d49de3bbbb8724df3d9ce1c1c8a9989bc6bdb2eae27b0264822728e0c1895fad92803b247976ca3ba4b197bde0f03c8f6fef198107c67122abfb79da968ab5dd84f6040459b520ad2063f639d8b53af90080aef7b49bd0ced3ee2305df945e7422e1919ab6d0dcf5efda5ce56a3757575ce5aaeb9b273333e32031b96b8e72575d3c3e2fadb42bed8e725d3bce769de5f161f2dc6de8a2bbfb5db9bb7be7ce2eea0c935ee70ed6c6e9cc715c9d7704bbbbb590524aa69372949b2796acf5d65adbceaf5cc739915266e9eeaeb6bbbbd9084d993265ca9429455faf40ae564a8552319a5275bb9b40c2c90e5aeef7d2e60488499333ca68b2268c6b5fda9aa8f958704f2f6d4db8f8c2b8a897b626567ce12d419b6d395a6a526509174d9c34390a6a82a4091745b4a4265c00d14ed024c851cd2f68eda98932539420872d6a694ca1c59b6c98c2e8471054010155395e2fcb4ca1a655548da074de9000bb804ffc44cdc93d9162c5461b33b54ca339669af939e79c734e4b5bcf71b4aabe02f95afdae61d3218a155d01ed52743362ba524149344127929a9a2d892f4e0891e60c255c60b154460e63eee5c1092e64e098acf1ec9471d8e239072ccf5e576650904995a74e9998712d3319cf5cc23cfb08947b9631c38501966059b274c318256380a0134e509382d482b049395052452a48cb275b63acf6b69546be26506b0dc39861d4adb79418569da3b56e2b1599db1f13ea97f5945ba04bfb5107942e5747bcab7e592cb7863ba66e6f7566a95bea96baa56e3d6c778c8d79ebad961a86598f8d61588e5b8f09752c06d42febd60a0901752ce5d6a5c4f1934be9deb527715cc580bc18d05b77318cddf39cd0c52ecf3dcfd3416bdd18c6e3adb79018c63b6e5dc7ac632ab7507404bd75d93a84deae7ed401f4d6555d6eca553ec24a40bd496cdde40eeb2d2f57473cb225c78fe878ca77a6eb78ca87e888ac934b594acc1187ec88ac93e892a944964924d2a59cf3233a3dac737461b78e498fcdacc511c77b5122ecf6d653614fbfaceb841d0471a7332b85ce530e81ce53a26c08702e5b88ec97774acd5e3ecb52b77ed9d42c45c31d7ffee35390af75eb97a5e17e3eb63410ba9c0642b77ea7f1823ff93c29a07f84e1c71b259cfcebc05338a6fef4e3913f85e3e94f4e4f0ae07e8c013c8563f727af270574ff811a08ddee4fa1f89f05c193c94f21076f0a49e8fee49f374f8c32f9290cdf148e22f8937fa6293d8b5ac1e4d4bdd99fc2154c27989c7af5ee9480daa106ef85d2a644c9cb5307536e0d5b50bdd7a5e83d718506c514124bfe6c2f1cc22eeb35eba630a52648eac62e9bba394b057659972f017659efe1511ebdf556525b6f2db5f5d6adadb790acd0ed97d20c27bad0c11bf17cbef75eaa76c7d6ed5b3786b15b8fd5524d56604125b6a0fae95814fdec52f4535ca17d3a1d00d0f5677735fb6df6557341e32acdb935a9b78e9968d6d29a54ced25051e4d0e40d5544a39968261a8dc25a714d2f6d4064fcc853b3011d99d25cefa50d280bae897b5fda80a0c8315b799135017db9a113e2971c225a4981c259d08ab78635fc924afc9235bce197b421c92a083bd012275509ad034a52030de294681dc4865a2d430907a1e1885a306a98419220358f096ef81204080cbfe48ff6e264d1c4cb1a8bc6f55e96f192821c2fcb3031337dc0e3f2284fea3c2f4f0178791a325f2f4fd6f57d5a4003e061601380b6bbbb270fbbda031703913ba4f3f04bcc9d5e29ad3e68ad22b52b4a296d2a59435a665dc2706262cea494a64fde385953ea596baded3ea42baf8ba76340e48f59a45f7c3aba5c178035773ac7d9dbcd5a6b2de88361ed2b9e9e7e719d58a4bb5b917ebdac28c22e5a6416a9b4e9ed76b33239bf313e90032eb6d6d9dddd6375aed6ae768b5c0db5b3b68c76516f8efa844ce79c9373c9892086ca7155544356e6da3fe9aa382e849d7455efaf035cd873ced97d1da05d08be7d1e913baa53ce8bcbfa8a0abd5dc924334ba6db582ce4931f6705d8f8c18b353b28516289cc4b510d4a5280c6133cc8c639c3a0eb727ce7328def9c766ec57ce7b70635dfd950e53b578fd9e3a75b91032e77ecf1d36d904e1cad77ee516bea4c26ef3a21ab2ac43dc08faae75c023de794b32539c173347859d9af250843a90e3619c0b0cd00e669d153d7ecbb59a2c0d69200024ce3ba3cb0210942f452e59393c7cc8c67674f0634556431869929d4fcf870830d6850b1e40c275c6683b1831368801f34b9a3cbe5e3a76b821980fcf279496f3999f589349318c6abb627153af738e7e997f50986633efcb26ec1ab5ae5f096cb83373de617a5b728077d044d3ee6e07c6c7930f6f851be79eb3d1d439d563cdd7549eba0b59f68ad7c592ba5ac282ca073f0e64e24f0b344389915c0db2ab3d2ab5b6baf3d7a5b431eb9c33a0782a2ab5fd6d15c2bddfa24923f3e5368fb555b565ce12675417cb2f5fdc009328754a74e85f48b1b72afa8c278bd03292e5de38ef6392f6440c1cd19c642c173eb567476712ea568334309886435a43f3421e3380f0abb38294f66c778f8c5b9b5975b01b9d3ab78abcf8fac8ab65fdc0755aef59107749cb07ba628d609fd9ef77ba0d84389fb533379bb38ee8bc8b81ef2c787e35f487f9e70c417146002bb38b75e02bbe7f4ab27ae244802cee9049a405a827c4991f029c80ad371dc0b2deb84e99e7b3f7d3a618a52ba3cc739f907cee9394e38c230d6f7e4a348a03fbfbdb00b797ac81f464290b10ee4c8b1b373faf1f423cf733dcc4d5108bb38a7cf71415e11196c7179ce0cb608123623663f824b2f6d43bcb17161f3a797362e6ad8258998b171a9fdb47129b271217afa52ee90a264570b5ad0a046eaa51923ba4c2a6ab041fbe9524ae93279396b5d95e33ab7473ae73877715e27d74964dd73229c57f14875ce3df1c816161f6197853d3e2652ed68725e7d9691afe9f3cccf99e6e71ce3674dee98b3a6420ba9cef957f35a4dae75cf87e694768d1a66de0006b8862c76764ef4d9c2e290cf39f7f1becff3562cfb26f8797dc43ae7353cb265881559d43de79cf32326914545560ad6ab0f9941fd9aee4a23a94c0bd25429430a19e756b4ee3109b8a041072e4b824023ab528dcc137d6650f59a4cca38efb8b0565f49590d53b6454875e93934caa8253ed91a75043de308a5cca7e3083b2ad2e420f3f9baf8b046cb4d764302203c9145543efefaca594747474788dcc1def2723b08bad4db41ff26fdfceb36f9c7759676e8f967fac0130aecd0fa877373523a2ab0c31dff76ec7f37baff70ac2e003bacce02abe7f897137639604e0e9813f67f15ccc9116be874030d32e81c2c0c2ee0158e1b3baa294f1c742d548ef78b3d45ef2ac4d1fa1cb187dc31bd754b5171ba4e38caa4e77a271c47550b0dbbb8a50a5b0058c11d75cccc3cbb0e1ac3c6548d09c3c6e9ed73a60368e80bd3f8499252cdccd017da133ae71499885d3cc4899fff74bfd7a9df9b721ca12a54f9ce0eede80e5585f2144447f62be5a3fdeb392e39a6e37acebddec33a661d6bdd3825ea4876e978ebc62e769ea39bf2b1754b39bb8e787b306eca755ca54ad9942a25b28b95c205be72221788b2dd87080ed16725de7eb1e41046699bc2e83b70e3c71eea294f794a7472f4d2e6c4e85d2f6d4e825ec78c61ec3a9230cc7b76f149e838f8af2765d42882f03f0ad6d309fd384e43947f15e44e24d03f390d41ff38b03b9d50ff731a9afceb407b3a817bcf6968fdb33edebf38a870bce0393f852e746db4d1c69b1bcff9178e47c6540ccf75cfe1f071b59aa16f19e7e3f095cb538738c2c9f90b516103b4a1da4ca2f150c7a64ccae41214a2a3b904858956b55a905091d16d22cd808284d8e8d9d724b56e2d3542badc51c74c88907e69b963ebd66ad6b4925a4b0ce3d43c7beb8dfc31ad3d411750246df1e2044c58219bbe9231a9823266524c19634c2d09d97429a75b39a7a76a1dc3e1ec3265edbd3a66dea364c975cc5235f9626f71b436a563d6fd14c78b34a652475296b384439ccec19b3ba66a0ce3f1eca9238671cf9e42c330167599ba316c8a2da87e034f8c6698aab12b95149372c1973627483fa66a2d35ec62efd2427a6edd5ab750042d6c00c95454dc31e5291db59a8e19bb526eeea823d4a9422849a663c6b016ba40f1fd4df0863c0949d552b71452aa963ad211a4620e8cd0095d21c7a720b50329ae901309ed39cee5845db54ead1744ada54868d6a3415684da80a2a5034f56d67a78b9ed1b70310beeb160845d0c8104785e849374e5190d494768d42025292dbd61a04abb688629c3869a5a6516a90007e12418a855c400bbb8c6ae8f86df3f5f335367506dc68449c872a1e76c54edf6ea1f04ddea2a1cd982e32951051691d48f2c250a91b751de8fba620f25aeca77704494cf277ef20fa6dc1e157c40008414542192a54457d7efe95388000e9a0505cda03673346b3368ce39e90f4dc86ec89721d440c34ca623ba12e08945523a447af84424e57c1a72c375441f290605b21b224f0fd1c982c8089a4c4774f5abbbbd9d258cf670110c0851619c4a73cd0c120009ee0da976a4e33788dc707922e2e386e8c32a92a5449e7ea55c47f439c0ccc9d297f239b2e40b1e8a642957853e2260a38a4cc7d52ff63944a32d24e979a7bbfb44a4224123d3690115328a6429efe194b3bb64914a87a52c154a990cba7ca3049f6ccd196860d06431888045972299e7d22573dccad9854192144e22bb871b8875b3059124e8882ebea4235430276d21d43b4ba9d71aba1043d7c3d43b351269ded8d5222779218b88c93d37893098dcf36e6bef6da076d38d22ae1a210ccbe28eb3c631949f49f30dd43194386ba71a58bb35a05a5b3bce1ad798b08bd640ecc219baa33c02328526f4ab811aa8694c80fa99933ac637be8945dc5ac77c084941fea8ce2f94913bd86d903bd81ba881382680a02f0da6813aa8b5f4501355da363cfbc83756e224eeeeb6c14c0d69d63e10ba23cf6d312680a02335b39664d626d2549a4b33a6cd492a0c614ee2611763b9f28f78220c9ed730659eb3178a71bd89d4ecb3368f6a18a0a0c9b5012951c17d70bbce3edd26c58a4d8a14db0f6b0ef0d3ef4bdb0f5d3cfb27bb5b7a95f414a4abcf1e9e50d8a08d1e000dd35dd3eff455101e664e759e9e345ca6d460022219c6fc7841c20443b53358c83469b5789a7673332d2389524a3da0de39d8558b604048c74268d38228a6e4f0459720592d2243873545d4b420514356f955bd4a9672dea0f1cb9a119aaf124dcdc2892fb5cee4641318266d3ec8f0758caf3e42656656bd6cb8ec758ca2a76f9ed6aeab0c0ea18a5046a8211411bf79ea7c9a3d755e923b6803215fb4459494d40f7744ed3c31a2a43c75d410c3465511c3c69d27be306c3cd59e3a7514110accce135304146df2a04e5750e494dcfd5c4047bd53c1aac0aad687706e51449c0faa4844fdc83c944bf4f991b1aa73fe23ebc2aee3441feb9efb70def98f4cc53b45dc1a28da73dfcba03be2b812bbb8257625c91d9cd3b0039a3c389fa71478bcac2bee4c81089575a24f0cb2ce3bb1a3b5e3c81fd5696a34c872bb97de7a00b407fcd231011993b2001283ef1c88fc21572d50c1776050d1b9945bb8d8d5b55253eee8c34707eb1c480a9c571fc2791d521d04a938047413fad53928fae857e73fb254111a64b9200ad4d9bd7005fa7d9ec83ac1e49e976072cf08750fccf7dce2bc09e7e58cd5222441b32476c6ba2224b7d997191399f53b63384533dc6666664f64d657133693cc82deda2cd77bd95304f6ce716ec7aa3b4e524d01ed442939cb59ce7296939c5c413a95d65a2b3b713422dd2b95cd49137a8cb8ac19934a4a788145186ae0d02649c626d1eef0703d58f9e827aef4dac457ebace133f3ec259576a5ede580e0ee923695e1fbb89f73cefadd7fcc3a3fe7bc737461b2f931e78dd0e92d03774354b16847969d3ca4f3d3557f5c77cef7ea99e5e5b135f6b5f246b8d2963c299beeeeeeeee6c96334054720c35a58fd0ad3fb9a5111d19050d0a4f10401c336d0de320d2754ec2045098c131a3b0d5e9327581029f190c615322a16e9d71ce54dbe098a1f5d4ffc288b9cf8511e81f9512635f1e30462e2c719b4c413fd386b396c947441f3e2062a92908d8e011cc2d092054b126b9ec8461f29f420460d31679410a28bacc551d66688e28b9624cc7c098209198b3f382ca105094992a21e8e64e82288376668d105e9896c9c502cc0a508206e6803041915c8a498334038d952060e54cec894f82650a2a8628da3268c6413cb17639a5033059a36b259ab3549c117628e001384ac0a2db47c21852dcb1244c87e9828e3d686872baa1822e9740619b530698868b20217c638438ca51ebab091219bb53068501a6a728234a8904d9f421ddbc00a1a56aa78c1856d8c6cfe6061020d2882b6d860858d6c1e756db89d028ba12cb02862088b2a3f5e6ae7db48c004b3062f6d58d030268d1f5d3532348925444c812508871fda28fa198117b623bef8210d2c537ea418b16143942664b6582201597e3883450b9e902193841543b5c40a14ac4132060d3053a41926243e3457b471628c27a6a0954903690731ce10f14045042b905893c5cd1a2a4ec8c6d5144f8839b3c51a2c3c98be58a2da1493971fa11290208a19324e50c60e3f4d88ae28138615316a70d14a3e80f4f0b45d61c3b3dbbbb251b1f4fed226460c315e50367e463004501343dcd086062d64a3db0db268a3444909953072005b2af0ae622d098027770457ed9c87b7de6e53976f77758ccaa48fab5a5151c4826ffb236598b45141f476f699fcebdc32ac9b230f8fc5f1cf714294fcc08fc8490447fb56ec425557913d86fae3314dd343c5ae28775479d02b7709608a20bfc78790c66d676b5d67dc66661fbe30372a806cd7751ca594524a29a59452efb84addd66ab14c97d58c3ee9b215cb2068369b2199ded1662c6b82d8b84aa58a72471b5ba95454a6104b4c39c011776cb55c1ccbb1a23c33ca17de365784eb816904cfdee2f9c9c495b6a1db73ae7adbd053afa7205d279f4a505531878a5d54bceca2ddd57881cc903c7b4e0f17c84bdb9095e7f8670c4fa178961ecc9934f452f2f0805d2e39c6d483cd085a0841362d526c5ab4740f25d6855a4a9b98eff3fe933ca75ce1a5f7b0141985efcc77777bcfa215b7e79473167d50a4536b67a3f13177cb1d23bfac4c2965cacccca4e9a5b2bb8a10aea8ced5ea5ce717945b755f6634aaabd26903457ee0930ceb58921a5cc679174237d7ca3dd53c21a1308c7656ca7ea712cda4dc4884de042941594353f39381a6b3198ef1ac5fb3ea9387fe88679f46fc6891d85927b4060a5012974167865fec6880d4d0d6744a1cd4bd61a13ae3a1aec67da465a3c69fd760830d381bba7cb263b25aeb0b0405b83a16ca17e5ba679a1c4e87eafcf4aa527de7aaef9c272be4970ca320c843b048e0fe4f4a296773f37015c68939b88abd5a61b921d0d58a79bab185a9d997e2941e50ff703c29a5284d1c572b1a9f64d84a5631cd44f24986810cf34e1ca8b476d7398d843e8e5eb07a1cf606275f8d7ae17482fd1aaafee3c02ee73f0fa4e17d9cff40d49f1efc0f05d2f0fb0f07a4a1e9bf1c1a7affe580295005aac01df00688035c7d2c0c5054ac7247bb089e43c080e53cd4da6bd43e297ffcce0a3b407cb2633217c342aefaf4d50534a4c0579f2fce3be4380d7ccd794ef6d33134cf362d44bb4d55f249867195d4e7f649f98327ff0f9d738b0673d22324bba419f090fca1c1ac4246318513728a298514cf3d21a550e2abdeac736ef95e74cce10ad9b8d3c5af669eccf38acea5f47ee56a0e9e9b0007537c5a39ca5336e7957b0e690e2d295f72ec45e682a36a3e086c5b906c5ab47861b7f8e9431790555659abacb236edf64b16ed328b762794efa06ec9a17c4a250d57ec6a3377a4406f18467d4ea64dca946972473b05a2348671480ce3359d1935246ac58d46714497a8d1238c6896222a4714cd37bd11d12825b011d7fa68615cdcf17617f292dcd1ec46be7ac98c2c3c545c51be89ba492b4142c4aeb1938c929a67492d7619b5f7188eb919179a6feff1aeb196c6341ad39867340967874fba15335160b843a2ed16fa0951a3fcb442a3d656b9bd57058d0e56be01f7a54d88273f8550c26f7e523183ca8d4aed572f6d5494f8c95ca85cb13d3fa9b8eccc9629b311ee67cfdb273d842dee0c73b8533a187287f4108cc24c157cdfe753fb094218979be7dce19b5f72ac1893d7f8ea3d6cd1acc8e0aa48b971d2538b3946773aad274a29d87d953b5068ee489f762014773a25a1ab0fdfe4ab022f8692e40a3e06278e1ee626cfd46dce394720f3ce3979fa6466669ea9da9c734e19f3b3c83645cd2cb205cda66d8a9979e79c939b99bd847ee639e79c73823f39073377501a340337b77b4f5a666badcdc0cde5327073b90cdcdccabf838b3b3691f5b7d68a2f4c9e2e5772477b9fa81423f9c3321a7496e40689cd6d8ca334b5336528936f2b5c4880e79ccf130aa08a75c85c9f1f19083493f4142da1c126690ca4337cd456be8518d6795be79270cc72cf66bb64261a5cb944463d18e8d8495e71f455cb96ede10aeeb8fa9e4b3ceb382623cf33358571a5b3cf5e8652862c29e5bd52cacb3e7dd638ec993ce69c8543d7d5afa57e49778e59cb021ad488f193e7a7ebf2acee40658a0f44d89c28bd9cc224f5d21604193f994829a5742aa5149a5688b191c04886314553ca1d2da889c0074213f04b8a89999385af587969bbf2e447faf24a93b72f6d579458e95edaacac61b3b2f4d3b18471c0975984954e0a07f1a6879f0e22d98aa05559b2b5081b2ae5669f0bdf27dd02fd741364983174687635fcf41e1f2d0f7a0091616e5c2e9725c9abd857ceb01cad1e36a1354deb2d492f65e022aa25cb2ca916c10647842c238594976f7efaed84d6088df1d3afb50981f1464a1018e24a9297362e423fce97bcc4c5073ab9d07ebae532fb91dafad2b6458dee97b62d4b3ffd9394cd373f3153088a9fe1b4a2c41bd1592857a5765238eea54da8879f938a500e3fa7509297362c4a3fdab76109e3b997362cb79fe1ccc2c5339380c816268ccb8a0d8bd1c442f4e5a50d8b152c51b0341626dc4bdb10670cb166d221d090f9a95434b9a1d602beb40d11d40d41ab2f6d43008d16f5d276250d21befc083e4bdb15a42bb7ff5edaae6cf1d3b332b35d19f3b303f4cad7c3cda47259d2ed7fcf92a2943ba48d08a29736228a7ebae4e0328088a52a495c6fd9050121ca1021990c01228488b0f2d246c4932b4b6f7a692362898d08a4ff5eda8840e3e3ca9501a2d1a8c4cdb555392915a2190100000000f314002020100a86842281502898ca8a2e7d14000d7794407a52194c846910a3300a32c418628801c0006008218648114d1500999781fff6363125a6cf805e0e05eb46da04f7082f61ea02130906dd1f342e4d324f63692564c2a0f49824f08f1ce2f529e28d78cf2d677aa9cd473b50c2026c33facf9d626b830623a289ed9c275aa174112f9245af42e4766f6386da9c63507bd6935951f5e2765185431ce021eee31f777fbc9e675256325b2093d75ed5b497f55dff9c9e51909653cf96418989acffeb9ec73233f9b5959c2c6f120f65e247efbf9a4aff5631d19f9ad2e92bd861d2ed1443d0516918f43eafc9c06f0f66dd2cad77afd954992fa2eb1d6582a1997548f63b54c747077829246202fc94f22859faff35f3a30fa27cb94a83e4ec61c9d7c7443aa217c0069490cd9fed335128f6fdcc3fb4a2e7c893e22748531702a9dcd310fb6ae5e88d2a2bb4f495b13d44111bdbd1366c2c5b33d0185c5bbfbb2fbaecfaea6782130bc3835079ead2e4f1155f0d74cdb7669b7d75d4fa82195d7dc4c49e9fd58914fd7086feb8eb72e4a7dcfa5170d75d647b2ba9457ba35ff444a80c9c58ecf473f91e6e74ebfee7b814d4c240fe8663c3212e66b128d782bf925ae9c84c3d6fdabf5eb9809f5e45ad587848cfefa379c422d7fc68515e388c25971eb8329b2cca8db5dce286bdbbd4635daec806b84865c3a95083282bd59a02d13e11ed4b4a1a1f902de8214abbd70c8a1a03f1d0959c222259e3af76afb9d2d03b06980e66ecaf62d6cc19ac602399065fb2ef490808bb2b0133737b845d93210d7def844da1d066454c91f4d6031d5f53840b4339100dc7c3e5a012f98a56b0f097ee8350404b98d0537761b33a43b4f44c6b524fddc1a5e3e107abcd53041a9619933916012735360630cb8552a5251230b3ad8882246effc9d634c33242fdc529493289a9e82605a18831923559d766e9cbc481b08ee559ce1200a38aea62c9d95483c24d82422587804ab9e45669a1d89056f5efb18936731317e2df753aa6d486b92972abdc770f65d37906d3605b8e545fe61e2a02672823bd06d0192dad65e1bf2a4ca240bdaf86435490e020c720a3393600f16b92d97ee2180b945570dad2befd1a9c354a293fc412d057edd63d1da33d195aabba2ca253f36d05d6b802b203048b9129fd8a4a4fd2df4285cbcca087378533fd0e6aa1a4a5d9aad8b3b23f10d5e3c06cb98c13007abac2a73c8375ae5ba7135302ef6f7e223576af1b48ff6685f4279861f7e3a93c260b1e9213944024574359c104c5029690c7ef6a74bfd804eb7a33be11e86335390a7474db65ac72452d1b95ecf9c02fbe4c2bbf84c537e9fb1071f118b2560085de4a307075b8aca598b6ab057a8aa6e26aeaa1d969a304b0b056eea120384d0595b7844881520dc7332c49165c20d6609fd246b0c512f81361cf2d167a4c83b5d38db1f5164856e470fff35271e29d1fb7c5ab6fd56b7418d8bc9b80f27b7d37c3ff46b67bf56e87eb1755a2d0000aaebad269dd58cc4b9493b030e3266449a1bc7b533ebcba9626f44048379622ddc4a7bb58367ede7183d5d8cc281ec334c65a6529b5fd253f7f79a9d8575128ea232b8b93d6b0227f73474aa3d4f8732266bee7bf27e8722be90c19fcd40987d4d01feac7ae450889d6d45e0e38951e46a6100c4dc24ef18e1730a7e7966b9b1b69867b362aa21104fb005d94202219eba3ddf95a0c21b6393adafaa2d6e1a41f2299691a6cfc501f84eb20c45dbb3566dd89242538e5bbfbae044a879ac05057b236f263a94633cdf9508acd0417589d0c357139a67a9a51e51b1aae51dd223e86b9b3558796366ca7ba87df979e0dc9fa9aa7c1b112f888825e4659a814b6a1352c433fa8663729f2704bc3ec549c483ea079950f08669c5baddf35f6a06f2845140aea958c67eb3a8b1562f28cb7a64747a65777739f28c14a4f5685d6b1bfebfad69e78c3aa6b0ece8d7ae35dd6e9c4c92b16964b2ee36966d5d4e3bd7e88f88596dea313f7b9d2aaa3b538ed2f5aeef5ef9cf603c6dbe546c78f41a0bd7a68048cec6e579e9101e4bd37a8c7a5afb1028f130f1e2df0088a55290cf302c367771a2bb58fa9ab09740462438c524f187a5506ebfc55358d5789a0d3889aeda79bcbf959e9eb8fa10a6f30ce2721f0d2a941e55e5f336bba7821dc725983e2486ebbc4ce8d6caa2ec7d29261aa1ce6d5b43eac36251058229afe4aff14ccfc17545e6f6b49436daa1a5180a0abfcb321baea9eff2400b5847944b0f0592864218e512e8818370eecd4ee6d4124472397ef9fe9eee25634c2329d48921188e2aa8b43cf645f450638678d77954f48f479773bf0caa6840d86e180756c37f21d4a7a8b991de923b8a61580c255f145cdefef7548efd748b803eda5506d569ee80e0157f86c58532ca53f60423856509974270b45b04b31e8844cf8b63d54ddbc7628b6796bc97358886d44e572bae4398ce8d6ffd194c00fd2a2e5639d16847e51202ce6e99e1f2ada9967e6063face75b742cf5fd25698652db811a0ac661226722b48722f50c7612062894e632a22a50548e2a7c975b55f1ad723d24a1d64422798349175005495ce5aa9b921241f7edf287e8e23138cd8d828c03ef8323d4255dd55e022600de2962d8ef38017041818450d5cbd739bdd0c4563f4351ee7540a3e729ab0eb8387d0c9ce74e24fdf947519d23ac0e2c08b3ee1c6680dd5de930c4171dfcd23870ba0a4aca702ed4c5940230ae720f736530cf775195b81d36ed1f7e6021a9aaba772308b71c19a352e57f701ae31425eb7d76990df4482b3a445d76b93a4c143774b961a85b13c2019194a96ec9c8abe5a6756092faf14e9298c4449fb4201b8780f7e3af9128a87559a543f9a0f564998bd043a2dd746f1e564a6d86ef46405972f99f7c1d840172718b0ccd00a534c5cc1562d7bf03bf5b076d17ad9af8c5d2ea596f87f28febe059957fd02cbf677beb08006c35c27a18c7508d03bde4ff1dd70ec920bcb41eb58cfa6388ab184d24e0e9e679ced0bbb826c65af0b4594936fc9cc50f21c2aecf2ef3bac3d4941e73eac5fa724bfc5bc22607b57ccbf362a853320afc4c89b550cda5746192eadae91820b901402c4f680d594408dfe65d84eec9c095242748b1cee17bd07c1931d763e70106695bd9d13cd044d06ff051d52f7133eb5165771c588063c60fd041024f1add45693a23d915088bb69f01069deacfd8c20f05c3b4736f9af716040ad16ca39aacc1741847da22cfa3cc0de04b6e4490ff5c140f0141037678e8634feaee2945877e5263bf408003059672c87a151bf7e8cf81b38c5d28a84304dfccada89f38aa5ed9aeb4882f1a100711e1e22ec9c822474b962c4e834fa21ef2bd85b613b927ca15da266d29a84054729c3b43c58a984c43e6366a0e17aeec7af0d96e460ebd76a53175aa1812542f343183fc5812e701d9acf59f1dc44417cb9cdbe0d9e8dcae7032a52dcc549977b60ae082c30ba20cfeed6f7e020b360cc12748bbd1a2abf23d5c31be61acb142f33193bb93a0afcca25bf061f50037740a06e0d0504d6cc84aa78c8e89bac29f90628684ea51ef2ccd20026ffefea14a133e444c39b2a98761e8785b2e068483dfbd0a1e72e0d4abc010cdc85e29e94d404e437dc4cdd2e0702b0f6f8f0306897324c8d921d49e6eff040c1ed73ecc6b47260ac902681a18b2b6c338f951fb7599ba9d3ebeae9ba6414da5328a558fb3f67a883fe991f7a7b0cf7ccb8dac09b5d67ddf0d3755950efeb33d288f09b480ea90d0878cfdbd0c87ba7b848341b7cd658e244fc743440d13e6a8e06593e698e884b84a89e176f1f512fa82985260d9a26080ab0000c468b596c43a2f28a98ddc31b3fd4266f8dfda766988627ea80eaab925b3ecaba6d3525b88cf790278d570f4706de42bcb10ecfae944e0404795071e0b747cbffc13788df8746b23b2238ae5de88e5a5ce119ffdbd854c2a44f014435c2d42e8704103e140f67809edee09226a844aba11e5b22c94de778e4c85842e413c0d9d10848d1679e3f5504b60b87ba8bedbe832920b42e9250df83dcfc1e74dd4fa1950ffacf3f3621315cef02de0521e0ef77a188d6839f18304d680ab135d855ba3f13f3908033dc824d8a5368c37700868ba0e4a4dede7d43e1f7d980c2cef7e1f23a672b1628b51be83ea355adc8a29ae8ac39273dcd582c7121b4d2d48511cca7ad78237f1db7781f3b0097125e4d14d6020eb0cd1c7549292577cd2dc3e2140c453ea1399231d0cacccf6db1e849224d47becd5b4f7957068be40d8d4bb6436a43efc40a8b950b7c85c84d99cd271144816ce35e79c3397b60f08c3e45b3fca67900b15ca98616966b910a211f228812c4186d659803f97609dbb0177c40ef49f29cecd091e83aab9985513dbb2258670c6578a76b0993dfa6daaae3fbaee58e60ab1dac8d23ed12d327d27280b1c006772db9c4c5fb4b20567c2385546f07e28ffc31ec7b93385a958a101edfc4c6b8cda0841ea54191923924ece4819837d2ec2b81f6a3eedaed4ab6d4489b1891b7bd0a0e8a64d34db0cc555dcc703ba783421fcd78ea278963aabc176d1d13238e8a032362a7a305e190157a1eafd31ca078328cff87454f9244540a8d9864211271523fa351104defb4c253087df0c5f8a5f16e9213c67966f958657d9874ff50f91cc3770f2e16813d438bf19448076a1a7c996e89757b642f1fcbcf878023db2598518161e85569c3ee68c46a0e00173be66bce115a6aa2ec2c0c36379617f67a3b1958d214dd573058f9057760a60b34f6f9538c5229098da0374b8a22036d86b7bcb71ff014ec27801f16ce29dc43a110f6c00218f43068579b33509502d164bcac4d5d9547cae3b898b01bf4fbc0b4f24e10fe7990abbbd9d05203814d353796dc51301fd1b66b02fce6fc46b4305685b7ea91901e472fca76ad607d5cdb76a8d2287f2fd25e3d93e400a8f31dccbffc9be7d7294afe1c66e0669ff2933db99f40bd3499ed4d9752e8be57f893b9e353cb79abcd897066cb55c9470c88ea12b6746e762b316363f5f594c298d41d441dc3b98037dabf6932564dec306d9750d00c743758b7c85836b5f8b02a07b8fc8e5774327190bcbc23f4a6a070ac5b1c884382852c10d5f0b156d8be34c49def92da2600ee63d053f6842fb4470252e21f7b971342a6f7c25ad41dc1b521783143e63fdc872ed087c156b0d5a0a1cb46e8fdb056256f9f6c3a9a406b02fce18cbf572527875e57dda93c39efe6b490d74c6c2ab836b2d2bc41fc1e352c923fe091422793d784b19d27a5acc8f1d01c8dd549c2e1e44021dd2b32591b0d75e720a0ec9b7c8631a045fe65a33fbe2b2fd3846063554f47aab51d71aba5f350d96a1aaedaa7f9f0b16c47b26a41c22546283edd8700685250314044cf62e1174b30bc2b269ed0f1a64c7c931f1d61ab1fc1960520cdecd93ffad9323212c3811adac07646313afb2e6da3ef687c5fb919b7ec2dca190dda055e6ae1558190463bdb028ad98b250ac80f930475de29b8632da8e642b330c0c41bccd0d629f35686e7a333fc0e6b862936c964bf4e0db5918b06e9cea86d9b63b22fc26bf8e415088bdd57671b4c58b6c91ba71a9751c6bd1c16a01827319326e17f886c23b2fec70b650035c3a98af57f22c24ffd0125381fc46559248212bf6cbd2eecd21518950737ef46983ce248d58807bb8519a19d066b656e9fb3a9047f770c7207ce52c7dff33a96f0e6ce0c45698e71af11a5fa842a7f6b5be6ae5059697a15338c2d869f43c011543ace6042e5f295e79946946e62597991c5c4150d67b62ba4c792526330f7b32162129f3e34af06056c48081fcb92c437aa89dafd930887ef732dfa5fac344920ce0d13ece18fb04a2dfa1c61b9b48fc0399716808854196b6a4d14065d58cb670a51b4e3c323884339d47364b2f708b81dd640fc3d9245c5ba3528eb01f5e81f5803b7819bd05d0fd54b0af3fa1e1eb356905bed5427b85b524f235273714d540bc36f4fbaf264f8f2e8a664992c496a9e680a01c5c4e1401a4f72ad29c65932d148119fddd1550f9da517ce38c44ca8e186f9d7f2094c5c1abcf6fea7621680f01e730d481bcc1e97c8196ccee756233b7a99157292b4c361eea50c4855bc298734069d58da4f140b6cf885369c9c0779cc24725062ef4712b45381f933c2641669568351f298364883ba4dea871426359f5440b72802a3367b96347758ea7494d1f9db3741572c28090bc258994b4a0bf64f1f0edaa060bd1b5d6388713011b52085581e77e7dc4fae80686165a7b7e88bbcba284583e5d1f05718e4c0960104c1478fd1f4ccab0ce0bfc765b5c6631e2e95cded4d50f8f570e6911600e8f61976b4c9d3e877079c905a6a3d7870f74072ed2946a404ffaf2c86148590e9c00ad4c303c4232751c8da3acbdaf53449ac9308221d2108a4c3bf8433494f27dbdff5e048b3640f40fd6c78fbc8edb3d97086faa0ac13b7d08c6782ffcbbccb1f1ac93f13396cfb87ff79f9efaea2ffdc3f69bda8bc07c8f59e3f8c06cb764768f0e73f9e69bbaf545b0bf7805fc7f16a3db5d802dfeae443a256b1fb0aa50fa7a60a023a2170166f14a6d266f77b495076bd47c5efc73820e3cdf2033037b64f7ad382f7f3dc93b4d8dcda2e8ce0c2b37e3a684b0759cd5e55b15ce950c106dfc753e715cd8c6e6c27a28dac0ca99e8b0ab872326ac358f2b4bfe15e854afcc04239b50c84f0cc37d419ab7564328696733d49f7727eb5f2ce30c870c0db998f76e3c12835346e452596599afb527bb3de9e6c01a776cdab88230cb2eed0c02b66826b77f32c188e578059e852944f0b7b07c1233302985662d3c382906226d1036685ba361fee474054c9370090bc5cfd133112516727192704317978005e8eff7bd2945ef6c107d91804fea1bb94aabb6265b6f9b602b83834639fdba1f1a66ff00ab58e415de65a9b70971aa6da7811c1fdd60c8385da0703e800914b43902edd866af543fce1f71d02ddc36cec590c3fa30adc80837a670946b930654c6990776c230432f10fea54e314bfcac5782335fc326abcc4027dd528694a94c6fce75a22a1ed1c4cd43bfeb5b17f6bf0b66253b36b7a91415750c187eea6bc8449ec923788b5eb3ddbd1cecc8cad6050b9e4a76d894c009c9609256a29e49fa460a62b8127b6bab33b3008f12f66cf4c21446dbe427d75333c80778b8b9ce954da32b0333644a958350babafdbabf7a2200c22f530d3dc891795c523a9c95bd48cf934ebcee89508d2f9d0eb26ba2087847f1d9b220feef04d29a1bdfad65261dbdcc38cdef44d85390e5e1d7adf260e6f8c5c63b07cf0eb3b6532d18c2a608bbdf33173b114eb609e0e8502d464a29d8cc01098f19aaa33d43ce10fc53df8d0239d225d433703efc258007bbb9450bf49dfafe22edfc479d28993a1df6ed29a545ccde108a632da823e016133b557dcc84e6a726687514e9b017b58bb0f8490084b94f43995125dd21c45b54a6f4286b275ba41dfeaaac150a728108c5690aea622807a21ae7932268a71552b35b5b563d72b0248580afc823a3810bf8eb2d268ae1536085db0c409822c257092027f200a72f61cf655b89385da30f5c8cb109e68983e452a84db013a606f736584bae2322427cb9eb33fb3829396ac4cc6f6f31a204eb2c9b68f15a2a07f34a228c80332b0906d675e88354c2919aef8c5f107ef83c40b4bed843eeea9d4349f9a9cbf4b6b699633c046dc9c3183f4abc447add74c5922fd2f8354ff5385792c687ce366b1740b6536640d2b84c4176e72232658033b1638c0bfca1f3a67f6c0a393c44fd93ddd4ae80553f12b25f3fbb126994776243016da910b4bdbd6f5ce5197031e287324585599b642103af14cdb0c1d66ad2c14ad17b138a8afc9a8492743f6a49a611a7100079bc06cb7642cfe2c8e24f572c172ce410f1261ad151e9523ee367290d5714b5c6618a1cab6c09ced64a0a7981a26b0ea181f0d2703046031c4c4029524af659d462a7ae4dfc1388b0d8248a24c3532a8a1486d416cb9949ea6f5e043b7f66703f2aeb9d85dda03fdc48329232f05bdc710392de64e82e0370480004b89a07fe523756f5d1ea180773123c92250ea2548b1c9c8f3e9bc01aea7575bed02a8d1990630f0fd5688876f6fc4231120ab9064ad0c263a1b366238e9a27989389ed087a653ececdda4e70e4d0878f12e280c11e29a4acb691b82bffe14df19fef18bb702f7abdddb237bf42ab670071bbf39d313bdf39c101e955079ef603f6654fe2043de76fb4c5023cd4388c41c45ba41162ba9a45e23550d29a2ff8809d98fdbfcb6bc23b8b4bfe0d944c13c51735756ae3a933164709348be8714c712c6d807b028ed4b48312ae91b98e386a7fa0dd8b5795a216cdc6e98f95c8d113c8cfc71ad4d653ae278177c39910187eb8139d9153c1cd56c38dc913715caa21ecf6dffb26504df10745299b6a5ab46a55d8c0cd5554eb4ee3a0e4bb494a68b407dbb23ae7a23c681f2fa71b002cae0251eb7549f7f84dd7903507abe77cae8351dfffb5a7092db274ae573c8b8092fca9eebb48935ec0a1a152fcc716afb23483a7af1e4fec1131bf420ac693e341d236e001a4c19342b10e3a0a2812e75d575dd6d92f4163940c953ecd6b8b9a918e7485e17366ab015ca65eceb4bcb5612b7682be44c620801c894db5b333cb12658ca75c721919fded5b9c1de2fb758e901956cb29201c901f7241551d87d53a6a6004c94966899f3f028d170fda5b4c001990ba26c814207972481b50d9144612dfa4f2ddae8b1d4db950e80caecd06373ad75d9ce0b9733d7cf81e6f8f2c4dad2f5adea9b98d30c99ddb8977b5a05ba9c9a71c13a17c088189473edc9011e73c6f130b14267f617e458a71c7a02d214bee65a173e5dacf700bde0d7456ececc79c6be847114b076286243b37afb283dde53a6ce9897158229f8047f6627a2bec2d0a2277bdb87c7272e731e9ab12a9aaaf2219a7546d1ba9811b2aefed336dd34de274070f5951898a4f0dd769b96ef177848703a8695359da0830cd8fc19381a880fb1fdb135fd4101ea0e1296c38c52db427f96405c9b1818e4a59cb217b247bed9cc40578f281262238e40b37930d1663dd51c7ac86eefc9e12ad6277b8512d952fea7ee450d92ae339eec48081e743a184c638b6601878212a07942c0ce0895344af91f36b5dd4c8a8d36967d0a09df6ef3602014e7f301fbe84396243227bf7188aa2a9c26306d75d8b641ada1a39d070735f6c8732b53a6dced0a4794f1c808df1554b786196ce792bc60e8b6fc2544c5237551adc60e0056da5c356fac62684d8ea3158dcf78e26b82fb425498bfda6b509abea485994050664e7059dcd04ce5976d0db28839e82896d99419e60926ec730aebcd1222f27407ceb49bcf692be4ae25e711d5459bd22729440a301d70450d7d80b2aa92a2a922d50c2911532a8ad85167073bbf3ee7d887b0f809433e876483436972fc32e0c91ed5e775811a67c733c0d95e288f9d2fad0b4425961a642fd42354b5df11436182a4636a47fa52c42c838155b26bf78240f43c43e128682ecbd4dcb42259a5a2b0a322ee0666602d34c246d8f900dcd9cbe880fa7c2781f769b1ba76e8de16b3fd2a69cfa704582e03aca8f7104b918ef29bd5b0d52de34ca83d2b18c9cc95cbafedda48024c41e1c9c432b89d14bee451711d516a9892a7343478764ed64a281ad5718330b5f31bfdf015e11ce84fc70c04cca0611a078bc2aeae3e62455835735c886539ca1f51bde2bb1b0c0746be8b5b9beea72b57df228a2fa52b8a381936968c040e5f1370c9c712f52020525b49b3f0ff8b62e5f19a1dc1f11a32d3d2221ad5eb490387dae7825a3f90dbd701d6a347b34dc3d85eb02204b5bc27f88387dfd4f79e86e7d8208115dd3de9b94727be2a619b1cd248296561d82f8a5463bafc1c9a4a366004b985b2d1cac1ec09e7345d93b0808203c18948473e54065c6b56d2b41278f801c3f1e176e942654986be4d29c9502305e847a15c7218d1ea7416833088b5c5dcfb91ef237f610a254e3eb576809ec515cfd7cd40cbfe04b21e43e523e096d4daa4cac6673591c11188152ce82405184e0a4ab26d89cd88b1f9c16ef207fe2cb8037185b5747d1c61b2893bc9fd9af746247a8450e3c3e57e1977329f4c648d0c8dcc988d3e978424d804423d298f591e5e11cb3688c96edcf07f79700e3d4f2b9ba1f2a3e714a09eb38af5a69e18e31de20c5c8579b5c33d1d7207c2957e9cc0d9eac8028898a4c0a7cd5318a1687b6633751943f7be648b41b7e9755ff2adb4e1b06035c78128fba018d5ae94f1294f1f2ac364886b4aad77a7001153f68359953cf9b78d58220e20a76648f6da1455f71aa53178ab97aae4eb3e8df24180553dad93ccee3bc4a7541fb1dc57f23424f2e804d59ba6fd8c2724e85d21d9a87b0974115f5192b7ec0d905de6bd50c83e2476fc8cfebb43d0e5d4402b9070ff2237ffc3f86a038fbf9c242f46cb61fd8050d3fcaec622afeac2c38e66cdcb39f80563ab51f67c380b6e355c86aaebac0172160c4f00f31d1e0f01add7017477ac78d5eba9075cbe6a98b4a19f03aae0955be6f0aeb21339584346d17b4f98c04ce6003cce100bdd6eb1336c1aaba7ea25b9f048e4fe5ef0fe13ef0f4443143eb1c6f873cb32c5429572b4f5e5b4f24756a4eeae51f82a2b2c0195896ecee68d54d0005e62f0869c24b3751a2fac18e4eac5f7ae69eff207c04f30793012184536070c9acbf498bb4617035f68abb7153a99170af5aeab7184d14b461f807407d9d8d93e36c80d866437ff4ac723669c41cbff9c9f2ffd63c4ea036167509b79f50d316dd62f0c08920175e3df1c86009eae810156d4577f24475eb730cbf43e68282c856cf89000d084d9c14217a46f114e9e36f4ad4ee48e1bbdaa0c04343450a830083a636ddcffe30c91831f05a9198fa5d8582401ac1f46f8489ecd1c64ac06f54b5cf7ec19121f0682fd7f09380f071294fd12af06d8b187d864949332afbcec609f103498cf5c505de0fcd6342bc5121063359d1236b5f5a7857bb228e21131199f02a303453e7f438e0e7408168403c34340816077d713cc608b00ddc908707e2b0d74c2883dc694b8a8a3dc8739f5e532b211970b8f19b85e740f0034142b03a5a80652290362f6ee91719230e6f812847acd3291f03dfc309e609931df0baf754546ffc4826fced50f22ba8c49f6a2a411fb36f01e10d3d097627c12c4a355eaf598da6cdbcacc71442e111c8e91d07c64c506af11078a576ac808f2b28ef21db216fee52dbb0f75cffa3f08d53fb347cb809c37699813b6f395b555bc19c0f99ea0c50a653672c98e30a0f5f28b3ac27de04121b6b8ce2183d4454f4d0631a95f1f0484c1baeddc6320f400f95410aa12d36c302010b75129516b96b8473533e8d2b157e0d28d1c04a13e2e984d22be5406921dcbab782ed286f18f4118fe8ffb5d186b1c5afbf99f05ff75811ea7e6f2592e882dbab6024eb182e143fe406d7cc0c78818872806aeeb40ff6cd97636eb1d421f4785f5642b33c1e32c86024f556c3bbde9c8648a7fcc77a55c3b440c10db2f929bc1342c5457e0ab7408302292f0ef60e85d541ad3f9c18e4de440200df44069610e8fc04436deb94c8277d2164135721223020f278a3e383700053d8d1b788d917c2663fab57848370fd95460dbaa626bd393185dcc7fbbd84a2a239d8b90891d5977b825ba0c21ef9978219c6bf67a4c7279090262a27ec9f7338c66578369db009959947d69e6316c0fe2bfd107c79379762ba3bdfca653f64b52c4fc5c2fa3efdf9bce9c090cfd02f24af3f5641626adf6341f51678197d4afd578d339eb41f04dfb20915fd62258757ca367e957caeec23863b960609c0499a67fe76f651e8c990a8179c7b4ec30e86e6d7b5c40882c3fab28fc6a480518d17797de4bd1be050aa63e115fc404a9425960ffc74c82dcfb38de69271778d8463b471ea68d6551de791354d9c703014cc9eac0f7c84596ad856c380f4dc53ba58b6680c2d001fb2f6b7be2d9fd30edf8c1d1720b02b062de9896c3295e082d7348f050d51bedc14b96401c258ae235370efdd520a29c4dcb3a4ba4a408419e3d5d0239f6be64b0c2fbea09cec02af9b87665d3eb3e5a11b09b7e2b731608a88ba510eac3b4553ccc1eb85de6d2bbcfcc444f00428178d6ec8aecc39cbfa22caf43320d8d8a2864a13ada09c38c1fe627e00bd3a1e80b02b04691946cd05fdb4d07815f46e6008113c00383aeca5fe5358bd2b10b950b6f2c14e26b22c9d780f7c58a3b035651c23c10eae0849210ab72495910799d900d9e78e7efc31287ef04d3007a4bb53a0840bdde2279d4ca961a064086f251d3fefb747677db81343de0bef0e465899a22aa68d1a5e648a2d43d8a5bb95a38f0b6a5ae99c80bb91dacb96237955ca0255c8e075314af2c2eb38e9dba6fe644ec819c14c7a9d373942e3cd7234fef6eb62ac7110d22e1c2a57f14f5c377821e859d2a6c8323b38a87a8ba5dd166777ef9d192fbc950c749b1d1a5be263a05ee8fb0b0caecfd4a3856108dfdd0d788074006f244e8a2ea2e19c51405fca6b7b3daf00c6bcb904ba589e39d0d5ca2a7a40926f0d5eadad7c289b012ca0977ee07d6b51ae603dbb047b6534a193c349b3d2a497143a685e45affe201e16977f91a2fa62dce471653dc1894966cb6245ac32dd171217d9918f72a9282c097e0e545c452e387501c1ce77614c9f0f63855ba8d7206658d5a0968b6dd312e5d80ee09b4fd5f673e792b566e6b98da939a56244d76d4cf98b028f3db3ce1210e4af1f4688afab4407651e19ef75fdd4bd2e8eefc4d5635fa1dd3f8aee6d608502db1e63b7499d9dd14b9730fdea08b565f4d9781bc7ab8c1b50d08fd6088d705a5d8261d72eff540fe6a675751cc9272055171186003c629a9921ccaa7dd0de7e092a2da4bc741b84412833c90ff149bdd44338d9172e1a5d6e1853622bc6fc5072936d66140343dff850f54391885c98cfe464122d3b20dff3aa130ee12265f5360a1aaaa9704de1d276074153a643a9f03161c062d9af66c64f8d2696429e5e14fad23fdf8c116a7dc183cba400626c1b9e089b980fc02208351e60b95981b677bb203c9be0fa2128b5b260b5e7905bfba1221990904d7432d6913a22bfc861899a515dacb8b3e6327c9f89eea2ba2efff70aa47e9e62644b4247484955c05369b3ed395248bae8aca13555efa148b24e35af0058542386bb2d76eada065970e01c49f932f1ec4e2ac61459e8f2f8a4f715380dff02658e807a647ce1875b2b5e0b6d8453b3e7fc828b3d2f9cc9582e2ba288eb5f7e6a72d225c30a46bc72461cc440f33ba4afe69c130141087389a4d8c263461e4b2a5995f5b5993d6362e431f09d7e3b315ad6951098b0c8454f8aca82120497ad786605208a68c86fc1c40b89aea6b54d98168686ebbddae8ea27fc00c099f22b0c44748d6ac7ccb58f43811621e6a0a85b0aa2374226607961453687952c88d8b70a9163515a0bc2e213b72def7a94cd152b6170db16dc5b6b5948d151763af4ba4acb4dbe84da5cbe71b37cdf7bdcf371048e42ef4b07a72083e06e3924d0835c16cd717632f13f92db485b6443892fe598c9b8dbe1ddde4cd82364d9f35ed9dade2b99407677a42fd8231a6fa35e1e447a31c04aae501e3ca37415ba441541168859b9ace0c5811571eb439443186ab684341e0bcf8ad4333ab9900a43c972b20f4da6de1f3af86de17075f676e65ac0528ae9dfff4bbf8e10e50b2d6e1276508cdaad49cdb8d1281f0c0c1f4f396fb714d3f5f547649e516fe6ab86853781ce2e7ae05d2a4100f76054dc1c22f814063e786ccd7d910ce3bf203458ead67bb99e2c4ee7ae14c8ec2b9bc45865f8a08c3de253ebf02e709cf852be00c7a4074346de7063b7dc60ed09c0082fa7eb6c0e2884addaacde7b9582340f1cf815e2646f8f6745bfb4070a82973bedbc4834f37c51fa2b8381a3b401057433bdf4019840962a96a1d77b3721b02c900dbe572f0e83ef60ba5dd5ee461b3256ad719b0b9790ac8fdb64253d47c11bb893f7698386baf440674c060fc11f870c048c5c16c7c2f28624f6f27e2b3d4c00507d536f079c9d6572726f3064378fe89100d51fa779cc28db7b3ee8c6cfc0192fe0716c888b46637992920be8ba9ffa259866d27de3fb9f8f237866a6f03545474ace6fae82ce727ace2bbd219ffa5cbbdcd44d9380675a26e8a9ff1ef993dcc3bf5e19e0c5c53e64514caa7f396a2efa84b3710a9febf611b14cdd41bf63eb79ea3121b2bc6c3633a8eff82c4f7da1b4d6a020c5af387a9d2f00541afd11e652ac432b59409f45b8c2b38e466e0a33f644111b64235b661d109941d8fc9017d565c0f3bd80ba722969441b9bb218dbf6ba37364605ae5b8438f11e49de68a2cfae6c83c1364ce12b8ffe1e47f4453eb1d4533938ba72a9e8e0183bf0785efbf748eb2aaefb343119cbf6fb5c27f32fbf592a31ae67dd2205e6d926e30911bfa1bba6cb22c44aff642d9ed1d636959b87f8ab6bf10e12b2f6eb45b015775aba84eec7c56e3d7deb2eb689f51cfce2f6c8ee77c4a1298ef8eb653f4dfa778c6cf7f50d51fbc92aa84658b97e7218f4977508a100fcfaee4834d46bc03b61f1e08df544418df31ed10fd5cbd621af76fef119d7a8887a1640b0825de028c295c24ce57a890cfb1f233d0ff9afef1958bf7253c830e9378921d911b76ee0f34bc6b7eae6c437a228a4c95fc513d83fc8b343c607f79d75ec73fdf30fb091c2baee1bebce0a6efc6354d2f4436a7c7492fd5504350fba0e3a52a0ae529f0fde1710786ba5730b565f5fa302dc35c578add5291c3b9ac91789731f26b0525aa3a752b845babcbcafc98cb9da6139009e572aaa06720e0728530be8996fa1880eec58b3c405f3aa97e8d54640e37dd036c999d42d7d4d5e76888b195b431086379f9763138e02501557722edb0501327805ed71c2c4df2cf229ccc12d9aba860d79cbf14210c18063967443257d3badfcaae2ce5aaf2f944b822fb28e5a949d66e1cede5d99bb461875c847c928b8bb488f74b2d517f2283a595017b10eaf1272460c27af9e7f4d4d05ae057d84028a7f22115df635ed374fff6d56f5bd08ebb7df676fd920511721258e657dc366e76887141cd0c974674d97a85866de529c12dd7daf8a5b9773c4f7003f98ca88e8810cc2b55155062c0342b7e7afdeb3faa968df8b98a130e82b30b647251ce5af79a05acef2d46f807a2da070d06372e535c329172f1d4d90cee2f825e97bde04852247938488bfb3d6726b58072b76efea2ed8aac45bf617f520b7a3086f947a9771ea910fdecc92b8874a6539227e0a2a3df1317b919b02880815cf4663b47d5c5840a84ee92c7cfde56d3524529a8dbe392bbc5e855f31e107a117918f9412ab8de8d337af180bd6a4bfa82c38f58d8eb46553b202c035fa841dc94c4e7762f9bfb011f7fe2003cb2cc7bfbcce14182b1cfb3ac393f9fba5d5ac27e6d5f80e96f4bfd73899fe17045dfcba447c04de369969462bb4a56acaef3bfe3ff7d4e1f7feb223d6a940912b84f010c08000282dcf20b5f5a99c3c00e938d4146c1da8c35120488db8201ce5ab949437fb46e4049ec774f9a5c08b8b76bc87c087ee04374cb6ff76a1b00fb3e3468b41c4a3e3792a7e5d3133e0fc599fb6030e465f54e7098c371cef82b1a9529394412988b0fc96826f614a1e95e7967e26982c310523d4f2f122a027c24715db5423659d67f692710866f6a4953e2dd90a63925e075f79ef10c277961695b0db64c2098ac397d7c45f83840268e98d00af2c3971b5e98662ad3c525e5d784bfd9ddccfdbb3c2faae25e77a727089fe37f2d5380f3df0cdded4f8b6f182dc8855b39bd20da32737f0fd4085ca6d7c6ff8428eb9cba943cbe801b32953832993ea19ccd97b34a6da33181ca69b2edb606febd118dd914c6f858e69138a37781a17188aaf52631d6c567d77484a9aa8cc284006a7e32ad1694ba9d8902742682da80e97b78262b2a0940e77f7bdd2d5582c95c5b1a8b6d540b11029e071669319eb7e377a8badd8a93e29f032d4a1450a8f8331d97770975c589617141bb00b64ae36f50aed6574d7efcd9f6ea18c0eb22d4101510c962a7406f3a743cf9dc3b28a8a409b2394658a6a8ce087aaa6d2135a711f1f5f906f99f8a59b9491dd3ebf41ada652e9eda9dc8ae0b7a790f473cd92ccfa1bc0a2593bca6f5e9d82cb77aa026b8bd0e7fdecfe6e7a8362a9bcc6481e7c7c06dd2b1b979fb2e688edfa2d669adaf2694b345d1c0420f63efe39a14f760bad0835f7628c36677ba6973e4a3d8ec4b6d113995e9a51c62d1e80a15cb451cdcc39b19da32cd86090b45fda6164280d7d8fb2c0af89f21e654789c5e78e53fab7ae8c53b30f6a7dcd602b9161c1a12dd45b613978ed600b5dd792338962d8cd88e450c0e87c0330473da7cd227436fa3f9143a7f6d8dae3949daa004aa34ab6788ad11e05beb5566cf4167e4c094c380998861a7d664bc448022c6120e30d600950bf328e8d717ffe885410932d0c73b537baea0969699d27a88c412c7a0565fbc2dbe56b21d1e9988a044cb631375646bfeb1a29a60a6dd3f3c0d4a5970aed62bea6efc993e26ed854398e75d7e7e44d6518f556258fd1ac76a44481162245dbe53c759392edc86dccd4445e68b122aa487e316cec0ac23dcbb85fc12986d49368fe67385ab00958088ae122df96591d7ca6eeda8defb262bc446a08167d552c430b1a007c7cee3632dfe7e6c6d223379b03aca3a4eda4630635e13ebf85576200a6cc0778a6cbb4b17921ff8a88209d3ec4a106268715f463dedb313ee0c04d078a807a07478559b7778e35b57ad1af35db95f87b1f45b61eb5e0ef3d16b9b8a815ad42fc652fe0de463cb7a4a5cc43c6d2c0784550c138d5e3970fda12c966dff9c7f3bc9469d7b9e102ad52db75b2664f376ffe2e9da7127befc91ce78e31d0553e81fe5bc4aff6ea82d83e173b3c8c92e41b4ecf468098a50c8aac7bbef8a1f50c728e82d96a03edae0c1cfc77e9df7986a3494c7297b352d415955548c4f214afe114bdd931758318a3478291276102688c6582244d531cb06126239d20c137b2d90ab1a440241fab6a690400a8a6ea80113b2489e68dd0f547b324a05bdcbf8a192dcd57722b71da40867ce4f8834579f0ce8a870f6a6b4a74fe5c227e1ca42b3ae220577098344321a59ff0b1c6bb80f9992d6555c9480be681dd0bfee3e942932bc71f1de77ef65917de1da89b84299c53a2f07c40cb61527cbc1f42d34565d08dca3a75d50a9ee215e0502ed2dc20c7c54fac1821ae3a8d6f959cd74f260266d05f43b77da84d41b6ba5841810ea97829386e8011825130aa6075a5c97910ed9bc9c11cdc46d821a51ee0bfea86d8317d9df110553a0b822e2d78f056e293ee63ae779d9bd4b0d6c210073a473fb7d1800feeceb3553c8f24bfa9fd96562dfc34f7f9bb27644ffdb51cd2ae8d92a5408ecbf0eb6af4661b351d0a764bf11da75886e49c2f21958da5143b1df7fa13077434ae545a0fc8822fc07f75d403a21083b84bdf2817b5582f8f13cc7d14f853878cdada202487c6bc5869e722cb5e37591a3201e96fa4337d28e0cd0289c2409b387e1ed92347d09085cd9bbab97ab650cd9c0270a1b6b3efcf306d41089d853b8aea0003111cf72e9a7a7e9d95d7a8138517d6730e740d9644d5f7c7ec25488d71709f99d3305a316cfa69c831704af9e81fd1330588f53fff3dd32e566e47abab17b0a86bffaf6f4ce3a6e2a953efa89dc6c02d5850637aa9ae8225f3723b8bbdcec05b2966d4ff5c5162951b4da24454663489d253f9682254926581703139c84845225172672abe99f8e654f91118eea1065a5ebd86c1eeaa777948dfb387a99af16d789501d4c9f4f0b3857d4ef75f8e5b78c485500a01f73bc9e88f4b96bb25a108fb8424a49ad2e810f2eecef8683ab1f0a8873abdf2d242afac87598931daa75d3d7fe709ac056110a053d057af375714322c5dfd8099a0e9e79f20deb5c00a1fc22f7048089929563cb1d4ff555507249da7e9c303bd312d0e121cdab4db63a5359b2586649ff13196b3b23257b7a6411f58fcb562688c698391ed25649b43963d0863108a2cbab54f57a1f79b88616df9ea35aadf0bdaaad50dbe66383595e9999b20c898ea9aaab5127309bf1e7e96c7a97cd05d35285a49132ce66e8280407381b47141064c69c4fd1b083ae18381d361275533a103446dde681717b5ebbd5c150c833321ee8b2199a926cdc4209ab945ac0b922ffd8de3bfaddda5f2969af2d3f90354a5720664319d32e7b6a35ad6926bde4ae1528528e9f0f599160b0e4ca89f96e6a840beec7dcb11e57b3fd5d906659e7370ff860aad6ba1c4a6d690b6ba836cc744d0ade3bdd7059a12576f6b8ace74c0407104a353a9be98a8b8a48e9836b19de4a07c75758a0c73b03046921b55ad532a6df5b8f3041c16ed7f4a5f70fad5aab558d8f3f7af43617873703cf9d9854ff297259a9836a846be54b40d5f8c187d1074d0a7855c347d18b0655b27949330284c9c6ef984041b029cdd0eb91ed1855276272d953672f9cb8f17424c401377c622a4cace652ceba36d2ee81a6414e3927456fa84151ffd5f026f7137b92f886c458d79d4f3f72b7ccff155c15347e795859117c22cd44e705d20b128d85ce83648c38098433c45be2de2e4eaf644d4b5b067838fe57ff69dfce51dbf4360c19e90e5ceec6c044e38db0c0dc8e9b01ce4f0bfc5c9a3addf5f1047d2fd0b4495f1126c6990b865e759937643a35b5161216ef9d45f5533a4565c3212548948692fae0c827d175d7a488042a9921865f1f494224eaea5fa69e949a9ac23ddb743e230e93d61768d6ef062f5a6158ed9775336ac3ad2c6333aa21073f6446ed38b0599685200fb0db663666753402adbf057c570daad8c8550f9673eaae104b0306625d2782409cad601f7b74e0a8f9cb964829022c781a1bee49317483c8e2acb6fff67bf21d0b32612707c2cf4898035a94e8a14fba5c52fae18ea91386058ef7ad20513ec7061feebc49f9f2387cc45d9afbe320ab896fac66bf63b06d09e087ce6c59a2bb8bec9458f13405dd8c936d36bd7c774470e93441b1771e459c0d1a9eecfebe320f82c7c1bd65744ba9143c0c5a47c29e0cd9eca2ebe19372a323303a23c8b3b79305a34e4c1a0b5a40f3f8009eb16ba734a70131d1c5f6f4a06946d4a22c81b93799dea41a21afa47db29f30d7c430894b63cb3f8da20d2ad5f31287fdbc88cec245f7325796f520a09bd249277e5e276638c9eaaa1611876a7c30656618077a728a8b8a52c959bb5c363184078072bc1d17a8f592cc4046ea1a3fb2eba9564cd3928f76122d5b9534ef26e82f4e549f5560093daea4eb89b9d04f668f038563500ced419b3957d3ca5b24aacda8a0e7c57abbf11be2b22b5f39845824715b014e388ce9f6f2cd3eb75fa73fc5d4d3649f28122d6565ea21a1ccb272e1d72345c3a0f155697df4bc310e9c43c60d1742f13d6fbc1af0f0d6e438efd1b3b12a196068de9f27f849a395c75d838d75a26ff5eb4f1e09871da8164d3ec3dbe05f77843e8a1c03be4409e0e0b7af31b2a88576a3f16851c5ad18ffa381563249c18ee0a800a2d90ab15e1b9ba02d071f2cdeee6b4d67f3e877705f4057ac983dd3a40eb21040475e721295eb4021fe755617e1b2be9cd18898dc6f64cda94a0f75481e8d2792434a0fd10d1ea5c35341a4dd5d7a0dbb0a71bbbad7aceb2ff42778ca616f6c112f5ba83f4714e75393c2862233ee5a0ca4c2f8f06a5a429108db35a8230a952e451e358a238ce1aae9af258c4f50e2c1f1cf48a98472cd241d29ef248c16653372f1347104d7ea4c46ebc191a4e53606fbdce714275b76d890efd978b0b5ccc03de7fb7acd6fe1e11fa60a6060c936fa1ceb54ecfda0a975782807cc199c8a99b7985e5e50c165a61738cd7dcb8ccff3085ceff16a84ac4e41fd3c89fd1c58e65d078cb9b32f8aa8e48cda0d77068b9ebd150b7b657ff3297c06d8a7a2dddbd17e420cd82282da3386e9b6adc9018de5d7c68cb5696b1275d440986904a30a4928ccc0dfa11d88725cee739a127019e81f98cc81e76f602c551a0d6e8cf63918948a878659f8ede22ca38ce8c393011f558533df3412cf575cd7cf07bb8acc0d07160c21ed9df6926ced0ee0d334ce3dc29c130bf676f5205a08f970262d3804a8da5374301d53aa53b9a328208e5ddaf7e4c73a588a73e796783bb3ac618e4523d1821288ae2a28b4482d87dfeb1d7f0735424930763c3cf8f7276d80978209f39e9d6f3a649695ccad95a309d466ac5d13ed801e9ee12ff85ce570885928a29bfff2ea47633b933c16ed7aec3edcaae34af8916b18c2b38381647e06a74872d526bcc5bc85b5333beac7522c20de7dd8d666cdcb53bca2bde7d151a8a13dc2ea6cbf75b9ba7b1ae2235875a84717da79d90e35d485e3815762bfa93d1a996a10e4bead328551b41cf5daf7691a2fa6030e9beddff877d2613c09a095b003847555bd6b62bf7ddaea07b64444013e272befdd730ee9cf2183a9f99e060ee551cc71cb3b578b2f38e2d0169dd8ebacb3a4bbeb4ca40275bc23ae8e86423fae3999d37f08ad16581858e6c6e2ba6be850d7202cb25731cdb19fd370a5b087e5d800e7e43d07878ffc7fad8627ce3680bbdb49aca6b6974703d39cda41883fc5e2da08667563a9f1fbf3e9264257dbdfc80edab56037c1d0eab9b4b4955f3b8a53b4dce991e0ad6ed4e00e744b871aa25db60b6bb0a5079cb335a2ad810164996a9f94ea8728c1c01082d479dacf541a5f1af70672ddd157a6cb870ceb34b3e43748145bef3a48e4180c0659b3d73d81194ab751309dc3580e94027dd9e6a875632781d24a5e083c8335c0ec479e18401bf817caa9fbc22348aa4cbfa35fa3b03eebf23a5db02d4e2db1f9859c7e500a12f7d3eb0ec301577e52f03882ab153320610b3edd0bbf05908a10ca47d388aee06f4f3d0abaa723a13b989e3310ab12ec40710d2e80045412338665d881e055c66067a8b4cf4ae9ad0998a5e830b9e6cb212713fef5ffb340d3c39dce240f3c4c9bd33fa6b0e2d8e90ff3ed12db9d1c27143be8a9598b33f15426df27ec99f09a5bafdaac3c961aa16281e3571869e052e08d805b304f59aad9f07db75c93e6cbc6b697f332b604c22df4385267cfa49ba2a4c610e35a598e60c2dc9b905c89f528d0e83166d7cd03108c914232ab810a54d5adf2b39c41f922c7a2635baa613e424efd0bacd21227e0d47201d1b8b7a24c0a38d42f5f63be1ad9651674e6adb9d140932906e9667ada46b2931a6f3edafa7b92b25b598db046f131c3ada426bc474989d9eab98b9a00252add8aa8adbd841d27f1c716ccf71120bcc687b14b50f1b279517e31675d4648389ea1896775d870b62c10ef3a41bfd1176c2838d046fb82a72027cf59f1c364a043fa13a79a1256910052682828923cab1013a447363fd7a1a47e4540210f9712ed49b51057da3372aa12173648b23321b35e4ae8f06b1f0570dda9a1365407c46ca73e40cadd33dcc900d79ae3969a769c11f0abbd334a527833c02a29007bc92624ac2a6afa440d24cb22697273cf681915c5e1e1301e6654532ddc6ac00c8f8c5aae063388b07c78a4b2c8d7a386095066f361fa5a027bc10111cce752495c6076d7787987b2908d722e1c9f1ceb5c36eced18fc31e2ce65630acb8aca84d0aa759e79113431b850312a58f1cdf480aa75151381fddbf8c24d11accec1e06e1a7fd463b216d8d861146c658011f61018e06665a704a06529592742288e37b645a4266d50755359ab4ff9b9ee40675e9c7aaefc84d4454904d7462ca29889e685aeefcbd2d91b5927cc9811a8548f1c28eaa1fd52fec07028273540073a987a47b65e2342fd936bb7c012e26cbe49246e953c92fa91c2931895c5713b9e5a293ff93452c062e6960bf93319f49c71edfef334d115078e66b38b772d49f8b7338598c69db99fd7f620cf1057d2d2dbae8a92a167312d8f84f6353ff8629631d5b00ab98274342458bb3f06e3bbc52a76f59710e437f301868276c23136c1faf8d185a19368e22f084ebca23a40f3850165e8623724e2c7068522aae95fed3a8c4f652cb3c043d98e2aa8ea0d564d4457d4b532f9118a8c26fe02ec8316984955050332cfc7474df770671210e2b4a641efab66b5182142b49eeb594274139022537d0d093a24fcf5c550810daea6c78f3cea0d7c578f9f4f6753e4968325ddac3be3009a268605571153b727571d54303c9c1acb4d6a8b339d670ecd81b4961c7e10f05a207bf97f27a6a35e7179adc88ed40879bb4ab618fdab7b9d691313b81857438fb6dbe228aaca12e000f46ef0e3a9e909b347b1e51d4bf984620cec3fb425b2cce371651068bf59a2ee67075db271ba371dd374988e82ae8bac3b6c3ed5fb5f68e760d70442b6a2804fc7104953ae694a677ed580f8a2c81894b7c5a64def312bee92e6c20981401fdd6052dd487b70a3dab2186e576428d3de5396eecea1e95145e45ce6d2f9cd06e0000f6ef351383ffd480d3c73a38a9589ed7cf64b2f79c462f47f0cf88aacd877c5a91039e4ab0bd9ef335006a0a45f5c74ce3b8a370911baf5b2c5793e7cc9237ca4f4694da4c5715fa3e01ea7169fd69dec76e68b8e8c6e26eda2934d6bda30981bdaea30699d491a09454fffd5fdb366695846f350bc974300c5732fdd4170888b90bac847c5d581932935368964493a5e13f749a3566094d33ecc0e920cb730c0c0fcf3910e0c6bc84e9f28d712b2b586d4150795ebdceaecb17e435a87c3df2a98f93dcd56d351fcc1c18c19711d103f001e70c99ba81d2e82ab16b1dcbb3a76c02713b5cc52843c3d98d5e6a0939f5a414a7932caa97718db08285a9b0c449b2e7cacd77ac3163a6eecd9ecc8be1e9a6c2a8a6e8d6590ecd65d5723dd95b9292ed0b7e5da86d787a9a6f115cedb269f95c35abc2d9e3d3f5da209548cdd04ce4f5d4308ef1be33f78c7301793f88f45d250b188cd3ce1e06f607a6f4c728952db48b13e0c0dbd7962ab4c95d83ab0e99fd6aad327aeccaae2adf8928fbdaede78ac51230e1dbf8cd4dee8d72380cec273d36d0dd4b7cda225e72b6d9e098975afdf20c2eb7ce4077f55b8e4299af6f9112828f372d558674a60f3618926f09be24581081908bf8d7e02878922d4836bd2794148660d3428209522b86383bec4cae035c38f164ecbc83c0dd267c3341cc8966dca7301890f38158c92c197b6cab1096b745426e92e45dd7814b096c4743e794bff3b48acc912a568dc1efd6e6534e3ef76fc07625ddb6d623217b8a3bc29df8c968126164ba27fb9f89efed6b5932889b907ca5e003e8a612dc811fe2206803ed461c7fbb81b0dea4709f0f2963238a59052565e60dce8ca0c20e3f020b575476cd9cb033083e07239cf1276be988330ab9693cbb08b13545c6ea7bcd6cc31f3a18e71339a5ff266a4437fcab53a713e9e67b55a7dc06c59911f1d3a8f6559f8ed2e033fabaf4fca00c41464caa32aa7e8fc2ae347beb41d1f52b3e811e7787e7330766384d49755c8af9e3042a546dc8524776a5e67c82edd02ae5b0a00f97a089bf612df56b8ff5eb5c5d1ced596ce95100367e037b2c3c9a91220317f6f30a8d09e2dfb43ca7aabd2b1118d000afed11505968ada62bb895a350d14aff94b90f028e378c3b875c9d55b7e16643e7861b910c4dce27e1ea3836242f0609206791f6a61c40d719ef25c96988840c5afbef9c0f465ca4fb9bd98100f9204b08001e84dc0006051acf1620176748100596ee0601ef70420ef38fd032edb1d078e98a36d8becf0aaac4c56129296ded04f9ee5a362b2781fecdcac299912ba9fc310be03f51fcd4ca6c4417bbdf2e71efd56fa9303e559e7c59d5d1ee8604650dfaf0b944246141af9d673dec6a19ec4168638ab8fcf29396f12393a2a3ad1bc66dabc5bb927e98e7d8923e8eef128a0786b41acfadac4a0b829591dffa6e84d496f6ce71ee7d86b4f8608e5434f6f6cbe6e45916ac50b4346b912ffb8918a80c7a14965c3f580228004d75b3306ee2ff4af1821a835f06df922742af8219f2079703b48c871499182ca5789f3b1321c79f809b17db3c420ab46c260ce9df542a3e64348f84e0824e621e158489646c67d560035ed3f9ab8edf4fe0853f2064e4eefa0266e2575945db387783074c22a0d4bf6c2a537d8c3215ec23549937773b4cdfe784ff4f3250fa5cc81a6a9c725a8bbdabc253778e7149ce005975ba233315c5fa52001d10ab7bd3f08519d5b8a4091330615c96e285203c5104cb0494ddc96faf649217158e71c1f579ad1a2acd7ed3819bc7d6294b150f9fc0bab9ac653e8fd856e9749bc6e316c12d682a1ee73a7e16b2fb181b5108858b209b9e092cd3fc6d2edcec7ef0ca145f2239f882096aa7394d9435c05fb1df8f8f39ad4e45e7c15bd33b116d14bb29d652bf4f28ddf19cd8dac881d452ee16b225179591cad0a78c847d2a472c666cee1bec59509c5279b353c8e98968b8919af60d941a0c11c03d4d6b76fba1347c85cb4fbb90bc4f4497b7e2d494e2d30c05a8e5fd135b37556a3e372f1c41d9fbf055670747d13b0a592be968f0b492a287aece4c23da6e0ea6eb6aedfef4545017e3e46ee1c93b841edf9dc38088127941809a0484669a558d6310f529ea18023ccb4fe8f976c764b23ba50cba85b8781754ba52aad9a3844a2ab7895e258c776c97128ec5074c029f9ace1a820d6b0af5f2ea74cb06b8107c949e578ea9f07fea17d192e938d4a7a2f3adc56a5f5eb4030a8f444c5e76ca378a18fdf8d0befe35f65ca206d72c65c948a1a73f21867abe0f2df8bfdea4094b39bc61dc7571bea21031b88997b09a0c36cdc0214814ce17ce5be8e8112136c74e1c15bfdc85ab2df94bd4c214b07538cf21791e1a00b7b57be9f41a118c4aa348b86cc8be9b793b8103aa30e46e4c7ad533339b761b80df657e51d0fbe54c379a3acb973af1a2ed47bf71c63be6cc12db6200bff75ab440a2c6f7c1915777f937d3104f2e5beda8d37baac62b96b84fcca6906cde63b42bd71c8d2c3e8bda925bc8553d878362ddb1298f1348f86eaff21bc98f744685b548718b150703207112559c60618cd9d6270b692926e90a207310447a35fa828572de92a88f14ffce723aef9e7efee03332a52a2419581d5d42b15a3f41b548020b2296ec9687b7e19117ad9f835c8d111a495de68888945fa2a77a6ff7d4e47256ee3448c1e335879253efb7a62eb167d913b95dbf3480753df5173003ab6b2c7f51644945d0cbc6eb2a023617f36b57d00bcfc607c1f6fc7cd29b8644d12053f80b48bd427411248812314b9b2c8b18004d4cd2f719d61440604441707840fbe97f4aa4ba4a61d06c1c88a6c5fdd808c3e22f62fef30b5870b5eb9bf781525de773dbbde60ed24f1195a6e92b5e7a5dcf4f73964ebf034624e5199e8012867b675243a3779ea041eb9a9c0fcaf265f71d003c80ff782f058c8f77df5ba05dd30b0affee295930ffa6059bd3d72751e068927457f43e5f1a6b08b296950dc8088c370dae3f31aa48b91f906097ce3b01c2f14a164102fa6483c5130b8c04d60a4fccfcf73a798e6205dbdde4f8ba89e054167f5903525195063ff64e6f351e5a020f038bb856031226150331fddf1f9cc9a6cd862077244bf38a01f343d0022ba7fbd94920486303c91ae2a51de3788201b9111a3723ab77e17f3f9cdc18b28ad7ba1629ede814efe0a8121fce02c1c0485c3c3f1db5d0533515427c87ac023a6e526b564800f01026d986e7ba3a3e2a29d55580be2ef86fe79d7cdf09a6699423d4366333c407e623a45dc70ca9271683788909248f2c1494518da0a74dacb98d93b65551396facdc6b16be2c07dace04d014934f1018243dbf68ce830a0c0b42b3f5442654312bd462c2206aae97a989ac74d7d12dc86ce6760c352bbc43edbb63b66007dcd7a89e3f7090fe6ddb011b0bb748f070bf544567d4fa138a9bdf7a731892c251170497763c1c00b4721d093d3914ca4f25a53d7238b5a103e747903eda6a7b7d00979259dc28fa5188aee7749c79c220cf7c360fbb1d3902e36db40c33efdb39b067c9093862f3644d7d7f1a5d4ff55c3aeff4c132e0a921d9464c205a799f04785581afb6c51f016b7d557e2b00f83f98efebe56ba61b201e409175922fd430bb475d65ff8a800a597909194d1bf94b89254f9da9572b294fcb65ed527e390d86e105200317b5a38fc78fbe09503d1655c8d9d39c95cceaa3718fb2931508e9d41a52e4b1a42f13adafee5da3eb5c373dc290398f823e1826bb0ab6c3443f42411ffbd2a29cf4587e005a49422914ab57f8ba92d2a4f0ffca5ae1ba131c888fe0671abe03944a672cff7d70f76d409c9dc4bb67873d93a5e4c25c75d0a27f12689141a28c4589d015340c540a7934bf243e91048a0f19df95819485b838a9f3ce11cc7926c98ae6c131362cf26440b8f3572a138e5eab45884334e9ab4074d24d1f545f8ec05a620152f5abaa9dc7bf71ca3da2d074ccc78b43df0a75a4c15a9d80f066ac055b26d4d8ea430560ac402c15c9f745e62a8ee9bb862f564099fa0eeaf9e9eeb14a533a60312960e117ea5386578005e48a002c56496500b4c2bb36f36a667b84a3b191603442893d3a9983e01b41bde60897cdc6ff73e844a6f18af02fbeb398bf9426f765803bc053702793840d00b9bf1003cf24659383f9c3d6e1deac23a1a958442af39438606589139bd926b653e17d736a6496bebce95ac8bfbaaa9c7d26efb091e102dbdd7f78e97d2111af0eb9a4a6e4e8194498129034e8b526e49c4c3c8465255616757621b47ed4c98948633a9d5324c9f6ff3a0b9cf1ad28d42b460ab63c00624bec26987da2012f6dd2e1b16805cf45f6ed4e13e309c0ad44e88947acc3541df1205757501507f11f66a0d732ed0366f192fd5542996dee2bc95079db3a035252672e686cccb7b28c64afacab0d458bc3246c9fde8cf48ad491f08411ba408b6add5ab4b2f80f3969898064d8c37b460c694a2b727881fe5ac515a06c54c682fd9d18ab16384c77ebd61c68311c9a50413d6b5051d54e159a61d3a60a5036c535b9fa6b4429b73900ec084fdaba8b468c316e005aa5f29a059d0372e059288f9ca17f38c250123b56a3c91032bdfb481e64cfb639ff7fb8fd345435572e2add48ce2e180bddc4b8dcf430b0ee85f74f5d8cb991eb88bba12ea6d79c8ee4ffc501816ebd96c86e659aea483cea45be6edd0210d790e24f8650b965e1e39a1136138fb0ca045370d67326ab1d7be65f0f2b6fe7814807ea17fe0198f1127c1a0a9ff8cfab3c35815624fecc63938feda3254d318bd0a2cc277466974d6d3748560b994eab18de90618e453b35507c6343e1f378109f0e26edfa1337b2caa38727feea2cb014084187668d0c44256c0b67579d17be37c2d0053f5ccbfa6c1efc6af8d985680dc636e0b4d5dc524a473d6a5a499e5687ff91866382a9c04aaa524bb0fb48ed21c83575efc0f8a8a80b953cf4c2dc49ec3581e18e55a6f8024b88bd5426905eab6ef96d940d0fd2618af49c00095a57a7007a7900ad2ddf87118716bd2f6e0242d7cc4e08383a5554cb5adf52269713dc91cc44078e7d82daed1a09fd644800a5720467cec40ba99d7a0c7a479b528b440d64ba0357934d12e55d14c67003a2a5af585f5769552023920b06f345541a8df92f295a37e61b92574f6e36ec21d411f4dc98021df950e09735f420cbd5472a9e88183b3bb353b2d79df1a2b402fae67457e404ca2af61b3e00a3647d4f42e1acdf2d6da3f94e657075cec4d8d9055894bf321073f8296ae89eb5c782881d69e44c670f027ea1964679d0f0b8099dbc176a86f663fdd51e7579444b4d498355560b23b2c9aafd6615f852c78ab64ad4c810312c691cc631c4d3bad1c4e02576cb03c862c14b3e8f3d5b445f88af4a1fd2fe97443853e1f904c0d3747b058168e80f12edc383cdba76330fcf3e8f5c05a8acd11ceb24fcf804e86dfdb80f03fcaa7ef8ffec20f0411fd7da2b38eae7cc2bcf91612ec11f8c65bafbfcfba142bad03e45ef96aba001618eb0a426343ff8bb4c290f71d43da02ca28dbdf4a28a65196f0c5eb54301f409dcf58d770c4ec1ee2d6997c5b5a66a53e32a68dffc4fb89721568d70bed68416e29c92732ffd5da4c8541b27a0c51d4e373ca90fc726db4daa099b53ae5e618c99a16362ea98cc600977c78a9787402eb05b97b9196f0aa9da5aaa3bc91841b42e1ea8cfe8c4e283260cb6afc283bce209d6c81dde8d9cab05615cd7acea9a7ec880bcb0d0e7b74b97dd94b0c91007da703b07c38caa63adc7f9d57e67ff20a6904e08e9c119d9683387fe4015c0242aba057a911e9e70c6e5ed9afe73dd2b3dfb5ae29d4b06976ba005064fa379ca8a1a11eb3de1342bbd7d5aa32419e885b4d244748117b42bce39f83092dfecdbe2b755df8c09976ec5d25b98c2ac053682d7e41f0b85981eda679699e1fb588b4e49107132aeaf538fe9e7e5231d12471107e8839d7d8f170c67ee63c69e8d33d46edefdaa93b1f8f1b4c4a6463c0bc428a235e7a822ecf471e2172c2c04e570801e38a5152a1839c8e50f2201302b01527a64f523feb1ef901243765fea6a5ad639bf8d27738956e8480e61e0c607abddc01ef320bc0148e053c405535f38b9619b9a2ff05e5e061308cb1da54d585bd244c9c95af894b714a14e7c58ce9d5340df0108e4d888f6df3fb1b58fc0fd67e734b40e1dcb770521b5103a96a23108c8cbbdcf308730e7044ffa3efa2010f5010205870a5f9b4ca3655aeb2dce46bd4b922f352b6c934489a40ad9567a022fea884c963a7716e660eda171ba5d6c8bed49aa37ac353a26da0d48b385f1b71c68b1b5d84b1f93fd22941f8c1b6be92a30017a286d4f0e5c566959de19b8c37883822db147d7a881efca2c596b6315a2407eb938d82d2c4558e93156dbfc8bd432b8703f37a47b6036151627a42d5d75b072551696aa85a1d202c245da9640f9a19616c429e338177b23a4e00868db1ba8627aab4d52b80ff37f4c6fbe0593bf66f4e2d8af4fa1bcbd87365a546e6cd7cd3b44cd61b173f09eb419eccbea79fa5914caad46288325085b267597374be920af940dcd06105f2681ee5f90b53e6416e3551cf39d803a8fe4eded6a325941bd1db425b114386aab4ef782a491b94735e15302ffc5f98e148b9e6e3583828ccbafa0b4ffc380852fc879554674e6caf8c75f79e260a41961408e1951ee083cbc1487ec298f69db8a15bbaddee517ebccfc42fe8375d4af9ee07e3a1e8639113d20dd2de8e8fecedee5a5dcb54e345c797b5f86d1aff1875cd076b1e8f0e45f19581aa86d9a40e4180fa97e2ace6eac9a0449949b54fd198e1411b62487210cb80c58ac50852fac410a53f61103206559b968c9afaf60350d55add5e3f61aa5ed2b048eb1bca44eb2ed44b8bed1e8d5c8ae6b67f52505261ccc1ffc2c68dc06397fb15670eda9556095f4d5e2dad7e93be3f4c6cabd75856cdc7b45ed5eea832dbe47bed9e384a5a94bfaf14ddd834fdd8018f872005a7f2e20c2d64b747bd7d8d5be6b891d0ccb30ed73d867929447a3e3f81c727eb5098a38c081e8cb6dc36864e7af47a762615ab8428195d348ca7dfb505be0c402e0e1300bdf41d48e78c6e12f096e794915fe5dc0109a27dcafd29b11a46b42fac0b02de72675d2783f535cd16d28d8027ba9bc85b6f6ac2152e13545ef1d03210204601ca70596139c35fd2c80f7709f48d85ac42e4c70da65ed030d3012d3089db2a9a6b407b3b4c58a45db66c0c50f4a5b4e1cde16abe0b8e0858109513d54edbee7b9d9c30d27021bd7361099909e66a5ee21732f4d61d7ab4dead5353453ac3f0db10f9d0d4007c14ef31bb042361a8f05ccf3836aff34d00ac532b95981a6ffc88109fabe19664511dce40237e475a0f9bc41f59e7e227c17fc1321af1c1c361531160142527f22ac4005862820d3da037ddd8cc5506b1b0d8f3752ea5c700432407b01aad334a9dab534048136b0af16304d0b2613042fed603c42c9c1a6d03cda570135905932fb6eaf334bb66c0b7d22a260f1471c763ce718bb25a212fa6f19822dd6419fe09bb2bfd12538531bd2d5f9e3100784496b37675c750ed9ec4a7d671f978b624859b97706cbf90ecedae6334c08742eb8471c03478d2151394cad0e1e4e28e18622f5e17b3cb01cad31a42ca5cc09a1dc2dd4d519b0a924db51a06605c9c5165d8bcf1baad636198cf629d757add24caa53c897a70bb3ced23a19926ca4df8addc1bc983f319b56971714cf5555b4a93a32cc8c72df886d14f2286663594f5fac8831081612176e56237f1fe7aa41ee7f9dc25104ae9059caafdc625c7f96b332b2265c0535b538525fada061816349c0fbcd2d47db1fe6b6679235f7dd948ca3a4be46da24fd27f6d3e8e741aa791068d19de9e6468d44701dd8ce91dc25da7520ca655c4300599abe96c52e7c08eeeb7e215fcecdf405637f93258a74c2c221d29d1ebed13a493924967c64723f88272b7c844d37a59af6b3cf7e1d729a51a640a9fc3a61308e51ffcbaa59f153daf2a598afcd8f67ae37a3c6999ebeab230fe99a2a0e5edb183230f6015c1c344b72e295539e5e6392d1a28aabb684ce5efc6b29b47fbb4b54c09619e5cf3c248c7ea6da52bc357e30785445f8c840bfc529cddf9ac8ceb5c1519aab5bff40bded48c8d6ec61ae42e4ebcd85cb863f3a14f838cf815c4d02324a726693512cb8ad68697a7f0d08d6134d3525882290003442fbf17e2d2b1d83f7803fac7aa6af35002ba3cc524d23ceda762f4401591184dd30f1865fcc4607fa0d555ed03c6a1e8a7c5c75af28315b2810d7e55dc8812b5df9e0bc7572d4fed371631ede503fd44a50b06ff655095bdefa96eb0d455761039d8d789bb38e46db7e26720b7d61bf64a1d164847781ce3501ca5ceff69489f11492e68407eb0d2ce333bc074e64e235983119e32037ecd9f1b59b6b67556822b98358d39ec724db1c3eab9226ea38a8357b70e3ba2d5b3cae4d42d1422c299989b66369644e346adf6d510af172fea164444e34ac8c57ca47ffe7212ca98562f6b84cec1bbb8e61825a8975ca2a15e93576f2924e151160786954acb27d1168924a7eec93c7f2c2fbc3f96392087444603e6c8aec9f78281e3338058d9d04db2cf26b7ef6d54b8af0ebac77adca7e02bea1b179020060894c218927704724437f1145f800d80e149a03cae94e975930ce3a6ac68acf33641a797a4bd2307c8325f089262e0604aef1090e60e713dbb06140c791e2bf78e4f629d733367c52c72a0882c86e4cc501a2ee8b76ab5f6b8e2edd178b5c2ed4a3fdd6f65beb46424b5676776f29a594329e08280a740973ae91c7ae9b698cc8f4b35629d6bffe559f596e54356b98a147e0949a4c5fab94df1acc5bffaacff52c5451a5d2748032c62c91031b574441638f41634c1c4fbc8c21060e1dd6a801e5431729c08cf1050a1120192e763822a9082a5ac6ac818394524a39ed992cdf43a7a4a17f9571c30ad9c51026e4c0040834d878e114061a65c091a608316d9cd6a4c132679436640d5cf27357b9c197266b6cc1e24b0d485cf0c413356820997104860f35830c9211409ce1e20a377c040085923069aef090c51aa824f96b6099731fe0f26012ed79b9ada40752e95f99d6aa0ecd2814544aa1cce9f2992f52795cb29eea12d057faaa5db2de6ae923b26e593b3f3b40b4ac3a4c28c073cbca7325c63651dbe8f576ec1a762a6a5507c3bc4d8825e79e1e776bb5f10379ed526ff75ebeaf9af7fbee754f2ff5c8e230fa2a76c7c4f1c81eed85587bdbd8b953d17b27d66fe258021750ae7a146281730bb1b64c888577d0e4b9b34b997d7a22781b5051569d6ddbb677a25675b64cda2f76f61eea81fc02c3300e1339aede3b11faaede5342df7d84b9b5dbec5ad62529c398bbb6baea86d5fa49fb772dbc27829af616f85dd3ee799e87d20e2002afdd7b4a1cf3e56d8ed244cde63d54fbeebd86a391ad8159cb5ad6723e883af80f95c18f46f6f7efda987f359b7fe2f83dd49b4cfeb4cd351d6473940e6a5d1bba9f1ebadb467badcb9f585aeb66757b4d8f98c502c1d56a05ae6ea77d57fb5657fbb2c7711ce7799ae7d97bdf344fdbae2581ba3bd5ae7910ccb2cf6759e665d9b950a3c4f11bf52c8e4676f63c3deed89e0e1d3972e0e0b85c3737ad168bb55ad9d8a854a9140a753a8561ce20f87d9ed7751873dcb6d95cca20a954b6bddf5cca20a98f7783377ac4b677d65ba2943e582a70a5479bf22ee58fd43d3d9e447cd4b3787f12c7a11b8a23ccfddd6699f6bcfc0a3eebf11ba41b14477cecddc76f0eeba1bb399d5d3ecb1b69cd1413d386ec567a827c9f516aa9a516d3466b456aa9a5464c4c484d496694e86bc7524ac5ec1803ee15a1eeeb0109d6ac59a3b4ade8819d6da5521753206d026cb93485119612c3e43fbfaf951a77f5a871f5627a34b287eed8b347f9a14bff9168d3571d68530d29260ac6cc40ee268b7f14650f26dede55d7eade5b374771cf98134f07c5596fa61e45f81ee1669f86e473dc4171fc0641104c690710ed13f7097257896378fbd5539cc8adde433307fe9e9ecf899827040cc38f7973a176398068879fa9cf671010ed940ec18e1dead1c8cecfe7de5339710c9fad9e4f7ae8ded5391db47a4a07dd84e2d0dddce7ddae8337b747b5ea8d8b75cc6bb5e6b1c962b1260bcbc06c3e1f6461cf66a8476c825d778c76e7c46e7618c3303ef71f45d9e5c1ce9f3aa8fbf6efd303eabe696e77415d9e9e90dae12c562cf1eda477d223d13e3d258edfa987e268648720a8c71d1bfcbc6aea71870e1d3972e0e0b85c3737ad168bb55ad9d8a854a9140a753a8561ce20f87d9ed7751873dcb6ad567ad43678d56d44cde663b6c1bb2e6510d5c7bb5767b9f4886df0addf8852fa68d9882c6d63a355e0a5fca13a08ea11a5d2a3f7947d28664789e3d03d8923cc9d6f3d20baf3a7e741fdf64d8fddf3b3084ecf01443987afde8fdca11ebf27dd531cbd6ba7f947eedd94bf3f500775a3a787eeeef4769bf7f8d1c8b697690fd95da3b899362da8b5d65a9f437f60afaf4aa948353a767bdbb88f76d31a868d4037f580eaa079faaa54edddb6e3d5b951dbadb7bab38ebac9e7701655ff4490e39eaab5d65a6bad5575303cc83de77f5fa881f0f79e9a457c95387a97ef1e661173e2988ff3bf5bd5b967712461e763e1393dba8678c7dc413dba420d84c17bc7b8abf42693390d0ee98e7550f75007a5ce81e298f510dd9dfe5297bf4171a71e504a5bfa6ae95f140afc054fb739dde66403da70a24dfe876bddf9dfc9e6d7e61cf88cf5786db883dcca46af7e577a9c9b03410e3cc8fd1ebcc6811c075e779fdfe73f3d721b07e16fe036e283def7fc79efc06d3b4efdfb9eb3ea3636dfc3ab424fd21fe1f34351d257eeb238624f9d4ea81308be0337f09b1ef14150f47a28087affc4f0591cedceaf1ed0f750cb9ac5eca077f0eb3c1d843f3f6e9772e79d61d7d6267064fa1f30d040839cccc2b9061800d1acd5ba29b2983025f02891e79e42e69e4b6a30ed1e5b2e8599b2c39809f302b69df43c9873df6c32f250dd230888466db3cefaeaa7b782c06f07a9eced28284b4b4cf6a8654993c5cca6298c75d2034afdd3df316fc876103cf74e4bfa02bf7bdc53e2d85dde01f8b90345eed283c0dcf8e039bdc964f0de2be609497d3b28629e10efae3ca43bb7fdd3a32b6ba0ee3ba73709fb7bf7cbfd7a3f736f4fe94d266ffac3e774107ed641a86f9f38827a886eac3dd4e55be268f7e9d5f36002a1b4a52f961e57dad2d7e913f269d5a52724bceaa1389a60ab8ea7873d5175ac759ba8faf4848ce03d239bab754f4fc8f81dbca7eb0ef55882adbabde609a15bf54dc87750ebd17ea86ed568e96bfb67a347a2add236d503a2dbe69b68f3efdff67d93c943f57b260e7d43766fe75122bb3c98fbfbdcdf3d1dc45d03e2ae6917d0bcf7794f8fdcd6b8fd5d7a43e6350e7f6207beeb88bc83a2a4d4db4004babf63c9012c6712592e2d2dd9dab90e3a3dd2dd1de51d1447241b4c5da5d2a3dddef35323086af8d33df059f4448c1245c8c2538f83b9c377414374877a84b93f20babf7fd7f4c8fdfbc46e7a43e8a7c7b9bf77f746bbc1570fc87bd63d153c463f91d217bea72d7d61ba3b1dc47d725abb7c4fcd1b13e5d00452edc99a9e964cabb55604b891b3d7e39b4d46c6ec087407d56fbfb11b0b0dd6667dd346a072a7f680a5e71ddb69e9d741a6a5b701a7594ae4abe5a6475b6fc59168639f19772c3d0ee6e6b87770cf9d6893b06ba611ed6a9f59961259729366d1640a2b69957bee794b37a05572fdd5f51edca06b96d5476be4953824c9d662f77e16156d2a7448a10a29ac58010a57a290a10a16695c71e20a208c50e10c4d4a06802c61aeb860cb252d362c65b13203344029f2a2054d18294924e0c61193161c5d81858b294e6abcf14213439c51c10f5a4833a024b16245881cdeb0e268a806278430b302124e18016685344360d182136414855123c316484b51c0a8d20519444ea83069a2a10d2b340cd1a47ba30d292d1081c310653610d325852c94e0724398a532638cca90e28215701cd57064420f48308c11c31665ae203501854a0f428c6142146c0cdbc29a37ce6839010c5d6a98400f5f9069e184259e50816512c3d146260916294e00c517250748a38d24379c24c9a10429704812430949525881441247a3174a8aa080f2c2165a94b42a69c008428c2064c8820525ac6086268688b2c6cc1133c4e0c40c4fa0c1841b47f01005104dcaf810c61b5a8e66a0c20b15518c9244a942c31218279a50e00823cadc00e585294451a22851810a343a4c41e10b1638e43086cc9a1b56f0054a0e4c1ba881c4850b4634090207ce8bcd12295eb62053c60e2ad0c410ad208935c2a4a0c21938be5c51834c0e493b1c6186970cf410470a3f146146891928507801072c5da4004c9625341f8e06a0051a2a6b804063698b11f440460d4e8e5288e28486b9410254c2e8c1092f98d820730128253405f1031531dee832e50608a459c3c60a297841628168052f6a683912430b242d1c97189c3061060b66e080438d962635062c472dc052c60f59a08172a6cc067c48420412461c39414492c605102645668280630b993272b40851c507348868e249064a589e2c41e2a805516c112283265820c4971478d06187151955349949028949135ab66842e945a0c7d72ab5554a29e54c62ebbaee1dd1e6c40d2a007cec89803da702bc9c6ed4c6177d4ded45297d278e09107b6cdd83bee65fde953ce6f0e821ffe4bc7a50aa5d401fb05b0fd9ad7943b4739c1e4fb138e68d3fbdddb4f12d7d51dd7d7a1dc87901be9c1774d9b1889dd334aca8eac85f9dda4d59dc56d76da6a35b09723299452f6c2bbb7e22eda03a26606b5afec56aadb5ca7b57f2c472a002d340cc1a475268e9a1c915306596784183154e967cee113a0bfdc40088065daaeb6244a7642593b5ce7be909f90eba348926b4d8c46861e3ae502b3d940885163051210a9931c244a15b5888038837aed0c082182c7872e2b0d06965e3aeec518a195f9b6e7126862a927ed042298c0e9ca09482162fbe6c11c267944a5d9e6060baf8d0250a539719ca9875043c3b07c8a0637539b58301102fc2a03b40763028da32c41055a2e092041192cb19388861060635c0d0d0c406274692fc44f7ca49e54e764d588c51030b4f98f142195d56985636ed521d17355cccec249a9cc84d517cdd18442dacd0041352709022862a3470822a698290e28928599ab4c8b0347d917156b87cd181619dc5450b172698b6b855bbdf31f79c41aacdf6976a5ab661d8bdf7de8b8942e24c7519bba3b8ab66e570ef9d94d232a6bdb5a6ecb679dad75b5f5b05565a6b338c8809f004955e6bafad934ec1929e52ede3f6f17ec4ae69af6ddb5e75eec5302c579db96fad785a6cb196568a7bce39e714122dbdd65eeb85a495ce5a29b5d2c7a4e38d0a75dab505acd11f52ea11c31e839dd36a6d36597befbd76d27b6dad5a504a2bbd92a7b5bfb752ec5e5b27a5c1ccea0423a3246baf9df75e2d63429ee0a6b690c4b2add6a814365f2b25cb886b8572b616cf6e76313d626063f729714b2b6da6c3c8e2961fbb2029337985c46db54d81dd007d19a12f5b29a554fe524a8bd017b556530a84526dad0b853c6fed116be9776857eeb5768ad226eda4e8bdb3d65a3b0c7b7dc6302cab7383b79a56cc8af96e18ff00225f6c6343d8aebf40e88f6cdb8cddab5d1c64dbea23d2c7bc04637f20017b08db551b15f991c3eb55add50103905aeb2ce35a3b0226e39dc1d65a6fd3e71979a5fc78efbd265c8f8bb4f75a6badb537b379639732556b927b654a4a25f2c87a8ed51dc8dd630703fae3de256bd5c06217bb17bbd584df31db6b7ac4aad4a94dbb7a2c02a22063538f294ba98058cb3c82c8db47ee23f631fb78b76d7b711cf7aa23e7de304ccb32ccdadbddeeaef161d8077eb8f3363336e6c278cec70440d16ac786b6fdc4be8b61187631ecbbda7e3a34e92886e5cacf39e79c76d62be5e67836edb5a37d04623f26c08ad5b4ad592d39f15a6d3b56ef66a5e6c9a0e14073464a8fb64799d890f1baed7273da7be87d507dde72cbbcb5e7ade9d1ead0e7a55cb51ca4d02d184bc9a36519942f6b595547526a2fa59a35a5add65a4b3f3094ed0ee49ed287b451b0ce4e018688746b8918d05a2206ac269fd96a2ba5e0b696ca11b22d83b880b25d9fed7a45906b36466b25bad4f2c0430aab870f0cd9cd4391ab02d3e77efa5cbda4f3b9cf55471e08dcf5e0e6610457d75a6bcd6a9a50f2552ec02a66fe040b8725e6064fcc0f1d982a6d58c1609282d89b0e9b127cefbdf7526b2bd19d94068cb30ca395565a6fcd320ccb30ec5a5befbdf65ead5dcb627d47add44e7aefad9c4ce86da6738911bd9452249352acdebb894728a6bf036781b51f415279ba8f49e5c9973f924753ca62a4c6445f3bacd36cc6a61febab52a126f275fffac9304c072c669331bb7e26b9923776fdb47403f275446866408b98eabda73bc9be6b76ad15fb346d44fab8c7618b1f489d7b90e9e8137ba4cebd275e299db8832552cfa5cefdf602ba41d28c4694d10d0dd30f7d112df1e48c166390b16445cb91325d80484118356851c50decca1a45391c52cdc23281d919353b6388382e9a33b42d076f3d4cacb370e8c66c19d694e4c21e25521743520a7bcc181b198e8c0d1368666dc9a97cc69299b32587b1448f42393bdbdce3c54ae5cccae0964b5bc46cf1b2c797521b67b2cac9b893e2911349d5993dd2e49d790d3e1b724f037e1ef0810c8284844929053267117d4d17fddc54232181bee60d30e583223d3f395316fd2021a167be0193524ae9ce3c06f407067b1e15461e73d63a4d278916452bc812050c46704d24c103162fcab8d0e433df53798896285591823248a88082227ce67f8ca6b0cee4f13ae4548fdd1191d0173d5275d4e891268f3b94e708d5a13d6cc8638f4d5f65107a4488cafa8b10027d5197fc7449a1293df43ff43bf4405845995eee89c6964b43a4d97387209b8e08edd0262aa59460aa6c0c363d2a8c4c2f17cd56393509e64a7fb3bd5424b226a094a260c3a28a0f7fb1e52b5828e16c8b15d659385b2e6db961cb0a3693a6039e52da2ba594f2269846db520a3a91e7a97ee95791472ba9dcac8efea0daa553069892bf056065861eb8dcf046124bea94344a9c1146d31266f8cc7ffe352fab0b584a09d65a99a4d0b9c4cc0e02a4c8f392fe0c2c93dfa94eb4d7abce779cecfcf0d053758a7ca034e94443a99541ea07f405db9bfa021944de0ba40fea7301939cdfb177a6585d6a0b0b299ae1b0e5842d4ae8921635b44b75db964b5ad2d863ce455366db02e72769604fc430809643295d6db9a4258b9db75cd2e2c50a3943e9c3daac1de1c59c2737d47421c5b081850b54a280728518128a8c60d2a2e98c14ac10871b5be69c73fe354f65d468991395a4cc1c93a6ca5ce3461573ce34d29431e70c430d5691913bfa9a735279a202bc306754c7d025cbaf2f59b01151907630064034e852dd1726c8c81eec02cab29d01aeb5d65a6bad1c0897dfc00bbc265fd909ac9924b7b1e5992daf75431d3822836856beb20c09bee601d9bd9180f1ac90678ed4c99e7bec2cc32e5fd9af0794fd136dcd2ad68935ef2c849daa693bb8d65af17fa50a8f698b48314f34b1314d8b1731603f8b38ca355de1be6c60cce03155745d60304e644813851118428c592d91060c4ec2e8410dd2166a844a72705a94512b065305ab544761a50c154b5841c5081756aa20b38310268cc941cb32c607945dc166bf48d364c6889733bc84714202e369ed15ebd57246597117cbec8629e1858b3d666c94b72d97bc88d9bc8451a271196756d65b2e7919c24b933dbe9c6c444ed68c81610a1156d678c228090d432cd9f0461651b0133a2e8b0c862c8b951ab29f0720655e58902981c43aebb5e5121468405146ca1071e4608112518e825023b5040faa3042bc81ea1284092726464451f510c40fad26d05a4b05866d55db5a2b6fadb5d65a4ba594326751fa41cc910b2fece043c4fe070b2d2d6c5aa060210b52d11b453ed65a0c8cf298e9b5495292d9f20da03fc02dfff300c993a5bc804b96b7526b76005038b122a2931ae1574a299da7cfb5869c3db7ddd76863c795898aa15724c975c9cc606a8b342f50810c42b57d42fac02cd3c6fe4516f4854d61c55825fac2b4ac72217d60cfc4dac5bc003bb65dd1c66e4b50435f98556363f64efb996663338321ed760b40218fd6881ebb35b2495031d6c81a59236b44c5689666d1a34ac9de1d7bb542feb062c81776acd3f62cacc71e3df658a56c4cfb32e661afda36491fd80b30060a15b3b15328540aa542916852e5913eb30334d93e13b13dbdca247d601f801af9dea649b384fed85230a22f5026153b3ddab65ffe188936f636c872386f834dfb764b792c525151d1131fee973fb4675996651b70dda66f26d67dafd592a6529218a626339d48c2f7129ca0fba75d15903e2474ffb4f741a7b5aa03844b562633354d65aa4d4c26132229549064d3911090541e2b8100e9f9f9a0889105a080b4b16b99f517962ada48499587c8077b2712f958a5ca637db05b3195472231d92619645e231b14e4b66ddbb66d18639cc3898a86a5a03285954476045602cb61b8252611f417898f096b035765d3ef68f4af3d7c4d505c45b16af9b5a50915e877e8bf0105a25f3863dd697b26cf2db7a64756766dd5e3cb8aedf0b4b1465b69db4fe185beec311629f5288451795fb1a46d8f445f560a912ecd0b98986a533553d3142d9141662daa45754935aa4cea5185428fe8118522850a52920c32003499be8ad8961e55aa3763260d2da24ba81165a28494a42486a9691a4d2326f36842914cdbc8911090541e8954349750a51d203d3f1f1459000ad97eac52acb5d65a1f4be4635f912a8ff5b1af4995472255a52a460699d608097f4084b966db63216448b673af80f64c9720bbe69225d0be6997943e52d472d5b90560dab90772fffbd77d26caaa4def83ecb3005b7c5079a8cfc5303d8033f9526a51c08ee7d4d3685e801dfb4906a17aba30050d53d08034461e659a0f365abb02609143a8489066120f774c4f23d6983f4df372ee582cfc4d4fa4aa83bd005a6499c1089aa6076026df3fc94a7b16d11fe3c4553bd6b4d35df7f438c8aecd14e80bfb5c72fa21d34b1fadeacc6934a14c238c0ba9643a2bc59cc897963fb4db2d87beea35ed47fac8aca669ade6caaab2566ab5add7a67d827f6410fa9c1f1964cbdd77b6c4a23639d86acd913e00804949a5adf5950c6cefcd979c894c76764a3dcff348d8f81ea65d873b916863b1ba4094cdb966c889a22ed4ac91a1053b5825512c01070d60b098e20a0c0bd110362831650d18274a459061faac9002052bc400260a1042a081c10517d860610d2c658cf8382b34e8619a62a0a832a16822b37200b65c82420628967c415fdaddc192ef954ab0567950c7581bdbc180fef08edde6d85f79402cc79f9de5cc62617c4ceca99708782957a5b25172d26e733f3d6a4a4e5a12196dede189f6cfd6f498891b6c7ac71331a02ffab2f7db6ed946945507e3ab442192be26c6c7383f7525e04ff9a913c94f6922e04f5a7af8f4d489d85c755262a3d2b9ea58ac5d444e0f531aa565d5d9b0877f6d2cbfea583d0a0901318146d4d1ac851f68e6aeb7377b565bd7543fa57e739bd55dff8e3d31fc27caba9a73ce39e79c33bcd4c7bc21ddbd0e3cedd33eedd33eedfbb42b83dabba6ede81dfa924472681cfdaae35d13e71a162b6bd74a721cc713b587e2089e7aa9672f75cffb77dbfd7c979a36e6ad799ae7791f775ce03b3dba3ae82ef5e802350773cdf6f4fed99e775707a0bca7bbcb4df45f498ee37c7ae09f4f248706e79a2bc95164cbe3e822bbf3721c47490efdb325a8c79fdd81c752efc4d1f374ea9a0e4a3deba0d53521209e1602b253dfeaf42e1b6da5fabda6c71b2de9cbe696be6cf43854b71422f538b7eaa74b4f88eaa78f26d827f993269ebc7fdde99abcf74f75fa3d5d93f73a3dded377f9b54ebaf5dbba26b6beeffbbeef071aef737b97557a97b5ab2390fd5d8ae3cf9697abdba42e2bcfe9b2f264d7b5caf3dfb06c522e3dee6c79a35b7aa5c76ca3557a6469941eafc7d7fe1eeaf195f5b833ee7cbf28abce872fc5510848e779d57ba647ce133b21dff1a779e05c9f488ef3d8218afa57a26387d681c343cc712de254cfd3e3c411f573883c7e51bc0e7187f53cd8401fe74a783cc7ade78a803ece89f0788eebf84f0400cfd1a1af65d55192a38bb6f769972b02bf78223abee3bfa8659557a2e33b340f2d7a407577f73c0f76e80b1f73408473f14a727c07cec513c1b9a8f189e4f80efdaa83bfe3e289f0b8dea1651535be121e3a571d7cadb1f89fc88eeb10b5acc757b243ebd040aa0ece818f23ca8a5f8580d0f7d49f4d5f8580ec11a6962eda728265e501c78cf5387778aff388f614b153713b7d28565dbbaeebf0b3e3530f886ece041fe063c713eb6eb3acdd43f1d5753afc15f36936697d28da67b1041b6862b7181fe35f5113626d74344138b13989b24fd4aa4ea6b3797aec19360ab1d0e4b931cc520c338125d2688603be3e920d79069ec7f71ecb9d251827eca53b6de4196ec986ccc2822ac6e862830b4aaed8c0135e7421238c2154908598093c39b3022e96929c11e589329ae802081ad4d0018ca32359460f4d25a40003952c4848e00d16604041195eb8a0b156bee0e0040b4b907200838a214a88418625a614f1644a0bb01c0961a50c1b5f8c943843456ec1a2868c384ec0658d9a2aec1629b46861c5145058b1660a294db08023891933a02843c51425a8028412264a0882cb1701a823c2305ce212656389b730bcea74f2c2a39ef2bc5085ba867a28ca9d42e10c1b92611587e26877f8ce03cafff4e9f7f60454c1673d412dbd21197d7d5a236135330bd822d919ea18f7542a8ed9e9e73c0888363da63614a39ec963f1c39835be36c677db36ef5c786939ee2008de8ddb384e3b287affc431d4423db6b7c18deb193e2a75ca2d3d6a298dd236aa6dfbf52ce0a238dbb12beb50ddb30c9e0efefb5c5f2aa55d3f72a7de81dca913ed9398654fa1ce9d32f027916867e033783023b2b773e2d8ed4d8f423da4dd55deae68a7644ac6c9f1d4ff1dd771497f881fedd6813128d2af4455d71d14555fbd87a2502814ca6501fc951e5d546e227b75941e896cd4b1065715fc3ed0c8c63fb3a3f4221426b5d6ba1255c7787a40a8af5a5f8116e8a12a71eca152a954dad5d244785cab8ef546bd0df2c32ddc36cc23fbc2f09ec7c3ebc22edcee8979753c3b1e1b15a54f4fcdbc07b87e7350a4cfbc1f7ad56df70c8b63eb9dde64724bafa80e72fd460789287114eab112c79616eab15d5ad2d7afd2a3508f2d5e0289dad2d7f577e8d041698e1c4f3d47ebb895e3e62d16fdcd5b396e58add3160e0e0e0e7dabd56a712d6e4aceeef26087a794869803eb11a95d6aae567a05825d0a5c9202ca6e618e258e3d36eb37e24864dfb45aa73f513dbe72725a3838bb8542e9d34fabd6e94aab8e52b57e6a5d521e7dd525e569e931ffe6a76bb1a7b244f91b117b16bbdb84dfc25feb0185dfc3e959409fc7310f8c87ebdeb1beab955e81e06a14eab1c37b77f5d4f07b0f0dbbccf380883e8ff750cc83f2f8491cbbed1d6bf155677a435a5aa32fd4a94a7c61ab1e8ab8763abc39d16e89e377eb3654bc69fd445554a5ba4acc0fc594468940b6773c3bfa3dcc5ad257d683488f1d549ff02cc5619c737610f0cd345607c2be39206c39112d8ff59b77a9efc79fa83a2886299b87aa87df10d44fff0e822008822a0d84d227f03df51bbfcbb37efac42d6f600ebfeffb50cf27105c280df481b0f3e5066187dfb18da5627dd341ac9f7450ea5b98b359ae2ee5e19bae5be1aff00aaf56ab70f52dc4abd5b75578306cad74abd5021f8661188644a0f448b451a77fe20842a8411004433004c383c701c130c409f598fa77d571403d763fbda79e44f94fc49e1247a19c9ddf1d750ac3d34371ccd9e1290c73e84b26b5e817c7abd65a8becfbaab5c84bca4b8acd53aa7b5fb1c0d33b16ea955f5d98f39637d5435557646f5fce397fe12bcc458a64d54ba57aa8835859147abdb6eab559ab8d65736fb5ea3a1b1b9bce267707ffd9e40e638c3b295df7f9ae03354dd3b2fec4f15564775deb2c1bd6eeba9f342d6716eb147e77791904c1fcda75af5791d71e61ba5171a687dcfaccd6aa734488754488e52488cd736d2dad4b81a88379c8e9e173d7a134d029c4db7644d3f276646f478e1c4109b13621d6de8458db25c4da36cff33ccff33ccfebba94a753a95410ac231bbcac3c398e3ae931e7c8bbd3423d6a422c168b455fac9d23ac3dc2bc6744cedb6a96e26cdbee901076f66f3a847d3f644318b299f6b01305f52de5faea36adeef9db7116f13711ecbab76aadb582b8b39b7872610db4792ed77b68b7e177216c073fed3abdeb4208c175dce921eb7275767776bb6cd7a552a9542a95fa964a7d4b811b2aa5512854144dd3344dd3342d049e1c3c38a75027d4a0a43a9aa6816298c18799beecc65acbf22198d943b5453b366a09da4db88f45b2eda80da9c7a8b608b0cf4420a4f4614318aa657cd852e7b0f7d56d5a1dea5d0b757048f8eff9d3dd779438869ff7d3e77d1d0a4977d075da484e1a2894d20792f0f350de3f1de4fda4835ab56bad3056e1eeb853617c7c3b4ec4ddf78b3b15c61fe65258a7525dd7751d8f0fa0778af1fcf6897116bf4f8f44fb7bd79d8e42853f89767720f86ea87e394f6fc8f7bd13470d28ec1e8a22cc351becb2f401eaa1bab1de644e21b936cd1ea2b523b393b3eda8610d847d2f76b18b3d47e3badb69cad2d9274a0a82500e1115a19c9d9a46b5170ac6d8fb865abd75dc850771289e9ebb6f841dfb043eccd979cb39e72dfcf7afa786e2261f8adb087e039f6f314f48fea7693987e197ba500e08fbfb08c2060f7e7b4fddb00d3c69a11cbb09e508e5ec55d6a350ceeef0d6a1ee373db630cebf395f9b5f1bd6ddf2c1f0f3bc5fcffbb68ddbbe6d83927510a65afe7c0ec2d7404dd3349c03c20e553a5f9571706cbecaf4f58da99d59396795f85d521ed7a7ba4b945427ebb1930f45ec287114ca398956d3beef7bce393bbfa78222dd591cbb679ff731677b5fa7857236d6da2527e63de680b0e56dce1ea1b2e8a7064b8a6dadb5ca3a270aa8941f299364924cd292b4242d494b82425f55288421fa4ad292b4244dd358fb47a23c497a3179b22469c98bd2177dbda418e19e9e06fc3ce008d6a494af63edc5e51dcdfa8015670ad368be405f1aab6a1bc8922a797a9958e8abfe24431e279609a5ead41e69f24fa7a5723d552a2391c8a0c00ad98a148a54c872690b35f33956ec58a1d4a9d41aa17a070806776a0c300052e915e5ae4f80156f670a26112c39e20c105bc07186924fcdd28592121c70bcd084059f7a23475a70bd88186ed0018b3698b0410c9f8f853558dae0a14c1c4f7cea334b534af57b2a4f284a9fa42c7dd4ba268a302d80c20b2f6a7c3868e28912121a323b3ce153df5379aec516483bb001868c1ad694004493262ab40087167cea2f60227f53db050ba60017144a3043852c767803c9d1529927258c4901cd1a50dc283c09c515139ec0ce300090bd030609d4964b609ef0c02491724055c9d618a135a0e7e701acb3c0306131798166531ada6052d3821b4e468072040f3b58f9c18738b2c49126cb1a2539382e4436365746113b4764100db39f395207ab59b6e5e50b3b6284fec0ee7b3ed8a202b282b12d0bb2e4c912902f2160153ef8481d7b2c76b14bdb06b1ab01b620db5aecea02481fd600db4260d78c0dd9f5d69a1d57cf033007846db3d4c1ce894634ed3e6755cdae3c9a587b69f6c49176b1cc666832e746cea2c8f7087f916696d064a68aa3ccca5fc2d8e34b498a00bac0c2461059a42891c17921862e3a1c51a1430f2fdc197838a62dcdcbca972abe8cc9b65cfa12c509195851caa2091ac29cf0041c417811461138a4f1c28c2af7891ddc981e59ae28ca218a174a3e4835ac58a30217b2483ae3040d2e70163452dc1699a68694316648434b5218274dbcf0418829493829218d222e4b1a2ae02a1c29808105a0e3a8840c596873d22106491000002316002020100c87c3e1a0501245c222e70e140010759c44624e980904c22847411cc420639041c618430000919119a2a103d53cd2f32a64f9ddcd9eb4e7ac9e6430a891382849f415451df91b8fe4cf8538c3bd2bdfb4b6778df5ba72fcce6f119e5f16e1899001c9c598f3330fecf7adf39e9632896afc12c6ae5ba8888fe40aa9a7deaa7b64cec9fdf4906cb419365543d84c44b12e35f27b4b4eaf44dca39037071bd9f6d4bf60f8b7c92c0a749fcbc28bf8f6c03e154b1278ab3ac05ba1037aeca2e67bc8894a8e913c1ec93a2e89ed97f4652b61150cd48235ad01424f866932b947fa7ff42e994a5781a96103337d338766f5d8ad85f4742989570086a426b0091b8be5652acb88ee4b38f70dfa080c22bda06e446e3816a7d216f199837b2f504f4f3c883338bcd0eac0512389d3a745befe564c845e2153eed5b4cceee00e0fdae29a5dc89c5bf342bb5b5c6d20ce2bdfc961e44685afb5236588fd6c75b9cdfbf9470cb00f07c3cb031c7c415de8e2751589266a4736b61c12dc47006ce9b06e8a1044fcf5e0f0cc4044231df29081890ce20f7fb83f350b4a1ac4fb8f07b78ebb47414fa34af5a7cc622046901dd3edb1736ea24baca6a43a4d11916b7788e9e3dd8e8ffc6ae91207f6892e8b858693f8123b6f197a9452ede015db810a69c6f5ddb588c3011d3a378b38dc45274afdc7d37ce6d7dc4691f04abc657031fe1ad95b226c98b4facb36995c96493f67549b1d51fa8188d1ab584dc453647e313c6ca93ee4a55bf657acc40acff8f08d8f94529f31ae88bca547a4b7897082d542e83cec4878122aab06b92fcc44e22ab4aee62eaec7ccd2c2515a2d24dd620b8c4fd533ff91c33f2f9997fd9a85591861005fed15e18c089a51cae810ae19d4de54319def3c6fefc6bcf321a04a17197fcbca8480980991d150816d05143a210a392508e39616068a6ef2c55c29bfaf50c880183ccb23813b8b37471511dc4eeb731c4fad0822768cab50131d5930e90587ec8b5d10d11e7e4ab853851063a418564f6eb031994deb900bcc5541b4e03fef6c8c9585abe3213c5a970fdd12b313dbef2ed98462ff39aad3de099318f3c1977eebceb93e49c7e967d358c84fb649e38addba7948e4557cb3321678f9a5a3f1faa2ee557f5e5589100982fd4c400990628852ab9940192b0e23196edc12a0805a5dfd6edb03cf32066619a43710199f56e52114b7e17c4008df5a6caf13d8b74264e414f825c64e056cd0d04e44a3125eee9cccc7c04e8c187190922dfb7f4aa20aa2b0d3f8de069d0dff78b429d879ab648b68438c6292674ab43de38046ac916ef1105742bec5961597a7a31d04f8e77da303dba9a3caf272bed54e094becaf1021957b52d7368f2ea066cfae6a7846dd83d009e5f94473d47296e8d31f54e152fc42d60d9817959f75a7ba71ea1cc0d2d730aa2c034745a3a512eefc31255a9bd7928e45ff99a3131c182df8ceb2cb061398ed3d6be1338ec28d23ec504de8432453f9b8e4201302ed4fbacece54017c5675ea6d01feb4ac457ed31cac39e997a74078ad3d2988c3d105434e3f3f3ffbf29dfdbfc45f73a63eaa122ffc50858addc59964c564776144773308fe740721bd9ff2e8279cd7fc5d887853d78644d7bac8fcde2a0b5e30d69ad7d20af6d18629dbc0dbb3fe474496217c234edeba3a02e84f5bae7510ac1b6ff26c958dc3629dec2697d5ed85a041573aa31a68ea2d2cb4c7f143bb69a0acfbc3841e50a1e46b0131d47799ec71ba999f26bd21620472db62e8ec1530f9b9a9e44a055717eb412288beef5f50613613edb38392615d2e2821b88d1b8aacac5a176e8b43b70acbcccf4e6df6d9e3d703979b29422153a1059a14355055ac0d26ac652e84015e01c65c4834e3bcc790b438882484ea82aa55678fee87ba388c9caed566a2c296f5fbe692cc4df103d8269c09acda9c82926a253d72931fdbfb0b42f416a39eba5a1a83a8c851c8dda4959cd64d8a19b554b4148e1143ee1188274b2dfc5143390aa2088505382df54743c7c305c9c7f5c4fdf12cee2b834f6f45b1b07904d4593f9c86206427702a56f7deee69ef0d5f3f3cd6c0a64b8e80f618a2928234a3169ddc5f4c891d1f8142f942fcf608481dc0e46ac43e42f81128037baf5476f1f456ac2545e57f040a447c611c9a927da1c36323bc62b328b053e9e40810417c0621e56faed65bd7c9de42b825e151cb30b243414740f259dc6038d3ad1fb4d95c9302c4b7935edcbe2370d8e27dae84a54079f2b37a6b98281aeebebef5ce5a5c04c237d9a07a0cabd5578aa7205b415a01d6c3e90a40d2447358a16fffc14a4156aea8dabf7295305095ab025a1329ff43eecc0c7641df5957b5c05f318db0a545e6474d024ea0c058665e706603299a140aa6220ea52410010f10e7dd913ee81a78d915bfcf07d3278122f5e0c9ae3659f41f7df3967e005279c3bc8b06f2dc73458ed045dfb57e0a7c295a013df4bfa782a0d1f40fa3461d91643070ef7f6f06e584dffc5cf58b15f8441dc54ce7e7b7b8844a6465c51ffd37460a2e8a578c952ee4163484e3d060d3167ac657e98117d3132268aaddc0c8982b3f214d265e1870fcaa11b0af0113903bedd7f8848171275c7d32aeef5cfe631b3f0ceeeca8f19e83e1839109a96a5fedb307d5be1497d7a62b92e14b1ffbd8875015b3102fb83abbae86de9f647b08812e8a1e2b1e2cebc91b1318d574a39b101ea17d3deac48dd5fd0b5c022b9f13ece802795d74769a6da88fe7f174473f99e8bb0ec269470a88a69007559f529994cade9505c2631e351a99341dd9f1d1575871e43da545ecc767da0f272f359ca59222c5ba4945ce2bf1c57897cf67d649c14df0181feba6ed45cee117811812ffcac37231723abe6fc4d71e082886afdee3f06bad35efe73fb5cbf6be631f210416b45ae7163a03e4574c1dc368035c1380cb84f3a0adec401c6b5411e73af4c5465f05464fae05bf3ddf4fb1cdfe1d918ca053788648d30628dd071a6996080fce364c1fc53074c7d77b15ee0aaf50340a85c048a3b57c5ba07471c389db58ddde4858baa69ce229f31de121608e5e2b19af9f0059001c4b290d6c0be9cde7966882598cc5615d4b1974ca9d77f3dba3ccec9481d962c9522678a527e430ba7b850f6a399d3711a561e16f756e24f502af47d537a7aab56b2929e2588fcdc68cff9e740400593c9cabbbcee707ccd5b673821d410758e24b2c8fead9f213f3f66647547d230d4b0d46b00f1826b57c14dae220a0b0383cb09702e6f0421b44b800ce4cb99d52bf08abaf1d2b90feea8be01cb8d57d6143627b0122db4e4453810dfb0768605a35927d01cbd269cec09450cd54382374519f60131862aae38161b480afa4098941fe06352059eb2fad7d7f92472f5209407f29967762f8a7398b662f2a07308362448ac6ecccf7fed231670038ec9e1caa29f78fa60a37fda56d05fca97b02c782572b651b9d945cb9fed2bbcdbd6a6b27db5f8a0e4e5e246d10d405d04e76c28af32ba53beea7307e9d799fb35ffaea224b11c9bacec44f6cd676a62ca96e5b62aa947f4f84bcfbd7e29d35821da6e92aab73d4dbff8591c9d5987ec7906dc0be0ee7984a56f9b1cea86a3561ea307d49700bc76bb9feea0cf0ed24d54e2dbed5994ebed0aacbd43573c674bea0654ebbf4ec4cbcd8811620d6cc23025be89f965c48fa794cea5d6b4017ac718c821b5f77ef88c623bc90cd788115529a2aea3915257ad6e9f61bb69a1e272460aab6ba432664889e06a079c69df0fb7682082c329405534e088bd9003a4325d41df2f469dadddf54236ecf2446697901394823861322ae3c22fa838957a468d150303510a0d920fb5a756b904de073992942a6169a787a71d6079e761ed1c0207d42e8af2291ed38192159faab763662337225eff40bead88629f25de7f122917b660562776ab8188235446d40ede6c2591c55fa62cdd9bc5a5f8c42e501388948ef342e999a948824f7eca96c9bfa62761a4844be8f44c21de0676dd451f16c4e1d167926b6212a0d23685d6509442ebb1d45dcf177074ad32010293c91670ac894247da7af957c432072b4eb4db1995627b068d299e974dce8ce2f57100291dd39d4726202915a55c199e80ca443205221d79b4a3887049995a151e9f9dab3a98535e9ac9f602038bcb93d6fba2e433d51fbf8132cf8b158acc91619142f92ce33b3df431486a45359d7592e09198b6060294a5474a6b8e3f428b024887c1205ecbc60a9f0cc0a17aa7cb96bcaeb04d85c23b7e03c19b3b870c83ae7a2f1c15c0033f8346531423ba378592785bd5940ec93d75d4e712b0950e7fcfe7ece14efb90781e07c9244b2269188c527691de70452731204786ece486f4edc5b0346185914f8d1229cb31615a0233ed940c9191ed61052f7e29cb4aa54facf1b5ee264524d612925cde0cdf41bbb4fac69cad4424f100baf5127178c2dee431d01d1417602cf28804e7ad30edb3ba6046a18cf60058d12f2bda9a3dc1dee61734d7528669506f9cc68527652c75425ad17c7824e9ad6d39949e9de2590bd5fac725f42dda7888ad81fa81b5b554ba807b773f6f5a2b46cb311b01797b742d39942dfabdfad5d0540a1d31cc032e768b46276d27e955621704ba87c2a63660c9c6a566a1696fb7cd5cd00b3b3450f038bd45832981001013c2de49309ed6902346d7638f6881f5cdea954a092210ef5e519839b0b52dbc3b019d4dcb8ba08afa65b909dff738c991170544eff093a51a3c7c165207a1c5ba0f22ad922082857d54c282eab8b2240a4d982de1705d7e21d983ea8932021ce540f3bb84392dfd83180f60a9fce347f8380c27c501b64552a42ec8364dc85259954a048d02da6ef7a830cc2d76d870282e5bee2d09754732e0daa1ab44230bb390f68a486a0e079f72c13c099a8614602a04ae8d022d4d9a252fc732767cacf42bd835f73305e74c6e52e4171775c03d83dc37cde9ed537c331d816f81f4bba25dbe44c102640d6db1c554787187c76e55efb98ef3f75525955eba8eae2e1fcb456133e0be5b9cdce0e9721d6052f2c9bc715b7b216501708f3d9359ff2892bdf5b90a2b827363d19808c8a162b0509c0c860e5e37b739ddf2c8483bc1d3b057071bfe7f083db4595d8ef0175727e236173a21af9629874e020122b4a50ea3c656eeba9c7925e04c295decc43f2e1dec46933df1e33d2a71345906f8874c35aefbc58ef2b1c511598b9fcaede30f43284ec5f3a9749dee5ff483ade21b0d28ad91f20a6ed543b2cf394978a4206f48a7413438a16333fbc55d3287831c14e1091bd5558529c093eb49f2cce1c18e273d412095e8f3684bcef29ed8a3c6153c7ce0c2c8eab5708caa4dfed30b7fe0d323d0d8203f38753af28f8672972ac1b3038f7402a46af22c038aa0f9887d10ee60cb33b8bd445c442f1c52a50672a6d1d6737747962881fe3296684744ff1790143ea4452e54514c231194222a476741018342d603d4b6a9f72370e984d951c7e98d53ff515f633402da4fbb41b084241840657775a650154b5a11c0c08cfad58d2c690770402c9f3d90fe1a30c80d48658017def77c43d27a2961313e9a6447402ff8bace77af2ca43596f1218b75a5b86c63bee1b1f29fe4936097dc5a4de16e29253c612858a3e8a7eee2ceb9f5ae0013ba9988f14e5cac068950c6a22bae9963687b707ad0d4e6776acd7c67a9be9c9994e85ccfdb4460f7866b0663919125ce2e59c5da57555b4bff04374f4ca0c2b30f4b08a89ce8ba88b8ba63e85eb113746e2ca46fe0747208dd20a74a07831a1ad94924c13f3d070929beb2b41f3991cb19fd2a728855010055399322b5a403aa3b0c0ac1174a96ae89aed96cb41ffc31b9ef5c8a0915bb17e2dad03951155ec9e557935c8ea043db8c5c9931ab7eb656c9583041994d071025efc9db9cf327b3219ac07f51b4098a13c8dfae340fc52c6a0a7d02adcf848b46004df48b3566c99ca8637f01d9dea726d1d1440e73adf38890ac62e71984e4559ce4b475b0eb509cfc172059ed5d41e0466e3946b0d61d38a582ca36fa150192ba27ebf014cdd2eac6005ab0f294a683206080104a90938b3e427da6d6b4c5dd83248e1289734631e3d2606393c1a450957175b86c4186eee4a2e74bebb4f4d4d8124eb18e8b3bfd8d288ca34239fdcfcde1a45daf8054db866c8546a0ebeb598c076d881dcff194559a8485eed59946046765b8ca2374fa69acf6143e3746544627c4fa9ca60b6a9e1e03428bd1892c4e156df3e2de64031be57926e890147412978550ab54216b12aed0fce3f8284978ee0da8295cfefb133accf91e1061d9887775da6c0e2fc9770a418a93ad2bcb92b19787b76d9bce806c61bb3364087e3c493fae3647ba74e9c29c163ab7a41f4a6f0e69d6e84feeb60c577b01fd462252860fad9855131b6566baac3ce118bbb98add7f7840bb3094187cdb15170187b47ae5f1e2bf6f533923dde62bd852f707b513c60452bcb060c854a0fe7877e7a583a875521a1282e4df448b241a5c511cb6a4cc5137e1789f95a88d4fd46151fa8d0c6a35d29cad1721019e5d490f7389891722de6c4c725e0935f2b007048da88a5778caf0a60f393b77db243af30a53a0409dff9213489b7d340b8daef868d8c7b6540ca3674abdfa706cd82a0c55547280be6de0ba21fd5eea1510e054fec626e2097e4f08e00891d4d1b69c57f5d47c8adbdc97ef24712a2e5c38e958f6453006f3967e724e307062107f6b96ad0766e9d4e2d9c626d0a4138ca26e9b05902b5f66aad737d96e1178763b4c149d29c28e91d43801244f1ea6de48d764c4644ca8ad80ff0ad5a36f5bf3cbd04e3df981a43953bac60fb7302c8754acb34c4d24d24a39718c8835a0b92d23f4eb207eff06f4457c9005d1f6985c1bc4b23f1ad43af0b0921d9a2996770da3e966fe65d8815521e27a70b7b38acdc58676e23f220cb538ff2cd04e8412931609d7bb085a2a08f9dbdaefa87c1e314dc220a8e3affc9e3892384882a0c5b77439f87496b4ef222015f905bd8077612a7d8c83bec933801cbbd35a9816bceaaa522d5fb553735255b3a2f5faf542aeb8a184c38a143bc5de9957de4f92a5ab9c097061bd3ae3cada2692915478866e90831597821fdafca7e314a162abab7db911cc8c659afc547f2813ecf448880b91dc1f56ebc5b2a26a46c5e15037df484118582f9d0df163857e26d30417e6f67eb965eba5528d6154eafe3f355a2a849f89c3d70cefd3140573cc686a65f6a79576642b10b21746f929a60ab6062ca15818f5248557b91d3b24e6c7ad97890c7f031b19307e4ef64135e85b19c308e1566e01d098831f222401590ce088bedb83ad2a72eaa7d463451f616c08a5a45265984c8f44e84bcc330b71bf0b66e7dad0d7c1e6807056bd0d555ff8b148535ed0549dcac0b413c13738a6eaefa3610cd4b7c6f788395a4e079badbf2dd24444c06336927da4218c3cdde85bf51628f12de1e6f3ef8296562521d33e2061c59e187a31fdb450114b9c0f80e420e060c4dbf20601f0cd8a2b34f41c6831dfce5aa690f0eb068554ae4b4408f4d851b1b9213fdf026bd9002da984b9d8753d911e41b7819c0dd1ece2730d7565333c8a4dbce18ab77e590f101e8d3aee9cb871d1c54f8e810b8d947d02dabc59c5eb0616d7163f711047ee5f9f8db53865ad96e82cf5dc4b4fd4a3e2c6ca42393c1feca0c7869aa6a19f1a195fb6247a17829dd70a03f066c869582c0015cc53622e3ed53ef104516ec6b8bbe2c63afdb19fab149a7c5beadd8601adc865b38f96143771ef56d385ee1f062ecdb9cf8d7756c126ec491ee38d33024a80473c439e1bca9be47ad5cdc7294568f77071ac7686129724de9e847024bcce9edda35baec8eb97b97ea3935091f036944fe8988d6979f5eefd849d646572df8139b1bc71c8ddc748201b9fe403c4899ce3f95df8aee872e6e219cd62bb096183fce4abd3aa4292c70c371a3b2f44431a16cbc29940dc7b31660aff478e27d79d43b75b0bca74bddddb87a6b4f87e07ab22a27716bc40172f1d1041bb5474bcdbf7f985c6c7ee93413cae1d52fc893f4263cb93dd1757bf083307d3960202e74e604553aebe3887ab2abeda776537b18e6cf9e1da0ee90c9c119b08ad888571dd0518cc04a5fdbe3f13070013f09949b9cd8b503b3e9d4425465a1c0394bf5014abea625e80d8e7ff51c284f6e91d8a09191eaf8afe265ee3cd26ca4001b749902f882873ebe726c973d8691fe43cd52560ecf1381b62e1f946d689dac2f7d55a5273a4e168da8f107163ab5b49e1eeeccec46ed812acb70d1c37ce224896078a7a1fb3f7a831ea503dcd6915462c11588241bc62047441a0234200b0a5f8a87c1e09c2f21829f13ee6c8183cf164418cecbc2e7aee6715b6995645bf9bf920ebd567ec1f0b57eefb4d0ef95d0a1a2211a5484ed278ebc19b6f511e1859b645e0cf1b3fd0810f6fb8f3ebdcb925ea3fbf7eebdb02ce48f2cb80a8659f550f0cb7b5ce422ae650e274dba1dac3fced9854a957cc51f8cfe152da58048b99091d9f5539bd81b68e82de29aad8bd85260ce7b76586c573adedc77c4dc9c639f9a6a81e520f8c33772857d13cd1fbb0f782708a76b5ae7ea3a02d1c607836640cb8457545ceb4a9fac745057a4ee12556329816b3fc97c9c8176caedfb01be52eebcff14b4ea6aeb36a5c665b064d1c5302e2b76657f32ae0f31008e45ccbc09c4931e060de24c6ce30651e45598660e405dd9760fd9b5c9d1cd8f2b09e8f4f26bc2078ce27a46a4f278ad9a94c5e76290369f07f843130b19ec2b32011d8302b90c6a6588b3b60cf8ff694381a0b472d19e57130641191f0047d3dfd0d00c9a4dddcb9532d76d22d59a18d74d65fd21820f1c883c06d6654f3dac198a9875a5d42fddc2a4072bfc98181a00bba5d9574fa6a37618191d5884c14d5ff1e999e54f6759b8d1b01c0fb23239da356fb587448449fc90ed0284220f4b58900b6ee2a7c1b4caeaff980ccb334871ad0e9110b4de23233aa24a0f071215985105af4a431563fbce53817fa6a4dd39b1749a97de50550529e30cc713a52e84834604c217f00f23b4973ab9206deb16469974435183c3026b8ec9861bb5d0c9ac304a97f4f4d96e84192d30d4c01409d1f81e6013134fc45f077348e32e5fa792e64123b63b4f4932408f415d743b12c4bfd1b1ef61f97fa10c310a7595c9f30afaf1aae2480b4e83cfd57762c0222ec878f935490d6d797d1e3549068f5f78abce74fcab81b8f6378976e2815adebed20a07c4e6e97551f81f891dc8f4a3681beea06d3807ae92677370547314bdf9b1a27960ef07063ed101f5e6ec8b6e1edf49bf79f57860ed1fd1244a097158c9f735fe33511c3708479f89246f7307023a8f221fca5d70ce41fdb934e5ac6240e82940a63429d6c674b4ba48ac57449f9391f80ea6a1e646bb86526dcdf007c7c739e9a9641b610b3d8077e124112ec2abbd76b2df4e4af820bfa70899ce1cd62331afc629727eb4457826173982a2666cb756600265034140fa3240ccbc6b90fe6e92db9f8c3e26644d0269fab16507521a3e9e5491319cbe7df68c1c1c1f65585c4181306a3cbdceb582f7ae6c9643124bff93e225187386a33081456994197358093bf4725d68e8657b4c64d3d1f42b4aaf4dc02ab19a8b79506ba96094ec4e5edf03324f1c43d9a6a69f32c9e94074afcec8964c2c8c3dd89184d15d627075bc29c703f68967536267bb9285275b9d5906798545091b5a1946363685c3e5470fb788ba1c1afc852d1080ed3d0dff93aeb38b4da4e40c990b10643d921fda60e40173a631388c591e9e3eaf7e11d109278b1da36496609c44c75d1fe5b51073b984e17c252cb6aef322a2500e0c588110827772baf26d2a42b0e6ff6a477d3bcbee330ef0e0fe16f8fdaeaf35ec81a8072eb3e12cac3c9805bd651fabed757c74c5feb0bb894998fa00b1562555c957ecbee4dac4bfd8d044f4ac9071c51f8befae34d1ef66eb8e268c206a406e3e73416d98c6df4d885f3b96ec827b96a3198608647f6dac0bc4a50654375b5d9033920109587a565024174110c63dfd70e6b5323ab8560e38cc1d34d588dd74868101067e578cbb61c09687172d314cebb8b8646dedf2c94fcfb51e7cec72cc08f9b98c5cbefdcb2719b27f8a2bf088e0c787f685a418fd7e9c8bd180458be39ee23af45f93e18aa65f674af0ab8509f18aba9a8737df32595501bff3534c3215ded5980347ea005d9970a9bd3f74025fdcd59692ec92a9b722e5bd920bb24eae813cc29ec73d0a85757a35a143b2625163a5321b6772f985e590cc0dfe14d5e779b80f0021497cc0e5e3603487f488b9bc82bca719aba94763b51933ec9a63803b9d78d1f48b43bee1572e0119de927056cf61a9dc4b79569d356152839ccd70b6a07d347dc856820a4f3ac13a16401ca1005b3c10b860e73ee15efdafd062f2bca07286e33ee26d04ba7594b55316d78bbb21dfbfdf2b5ab630c96040fbdfc337a41c94d7e63e7cd23b68bc536abf38cdc404908f58a14197083352160943ccd9dd92e79c0df9ec909fc83fb2e410f61fdfcd5663807328f19680c600a559a9484be8a43f8cfeee5c00cc045d38615c0d33ffdd52c862fa517ad8527af79bc99b64e8e27a9c0b87facf608537ee683286f10ba21a7d3c95762ca0203ef50b0bac7408f15d4988787ed498afef79f8d9231700922c1d541ec4e908b32bddc65a13cb8d9c6871a5a7e601a2037330814bf83bddfb2b02b0433596cb1888307d479ffd3999dba558ecb400acecc4ccd169715b984701811ba53a5ce6b4f102db471ff0633df561f3b2072ca028c2ad0e19d6e35dc25b54b433aad418909a8d3c2e166830454105e50097dadb75735d36228b32aba7ba2b1026cbcf074c5d2d993a533f4a3a6e15704e6cd7cec5c5403e88a64ed0d5a828aa61abca2cc4b1d81ad6613fb199f1ba22c8de744244383865a429ad418701b976646c527b6e17b539765608382597f003abcaca35c00b646220314c48ec6d6e4afa5f9a1e295eb456eba3a6d42483d5528b3df802eb07d540a8a2c085d85e74c61eaecec3831a5d2cbe84800713d8107141bf49548e82ca99683f10ea77889e1dd34eff027097ac7469d825c8e773e0025897ab49c6eba8cb1e3b82c8c2d48e70bc45a91b89eece59289692511fb39af80c4207caa64d39b5cb78b700e0026d79a0ee295123e76b42c15d2009f7d9cf7297caa557bf4cd36d3479ae64cbce879e97d8159ecb5fb3d954e4654595f0a5b889c035a8ec7ec514cdc91121b7322e9776bb6e522a40ae74e8acaa85d36a48363c77bb66360808559a226fb103553b44cc8a188aa45ec51d3e8ea3ca9808f9ded722f336826db0c5eaca9275f73787daac109dcbd80238f19000d26d0fd617381d5f5815af2877fcbdfd3212bb33a08be94f4ac59911143ca621454fbc98da9189caf506971c86fb5c9defc5e1c1f1297a08a85d14526685c19bf879e320a874f36f8430bac7cea69b777a08f97b19ba33697d9583b7900a35f5a9a5a2edc678bc2802d24591383531de2395e73d8e2771a17892f2be908467a171be2905d96e21a0963a53c34f02449b19d6a8957f2b7d842327c0b1700b6c81acee7cd3b8c297904f9913a2f5b3b77fcace3508101dabfccaebef5bd5616b1fbbb84180bd97a3fba3a867921cf67e3dcc3a05ffe1fe244159c0ae43d02478d905389c7f580a1e434ae7bb8bc69997b107bd9ca51a7f6931d25c5ba4eef84563ef3e0a1cdd9b2b3893a69fb31bab83df498fab119db758e77945d40dc9e48c187b994f222aeeafcbd4fde7c2738eebcb0bbe4e24bbe2f18decc53f773d0f0cba015175e5773270e2cf1ec6f001199168fab0224dc9e1d9cdda67ff9828e1ff0be21d7820bf01c4df023709fafb06849d32b1382eac47c6a4f64bcdda56c07ac257d2066d535489a4c7fc2f38c7fb2216b672472474b7ab63b2c16eb58623ebf44e03edf105fdd877a09df7ff0b329521903807fee5bf300d2c09e8b39b3c42104ca5ead0b752cd3c5573871a9abf844f4d704441fe1d9147bf3a29d3e9f4260e3bc43c9e0d48122ca80d13c6c5eec40e4a4b56b11bd8fe1f1ac717911f1941496fe8a631a45a39dab2b83451967a96e59ada704835dd91091a51a446ac6aaaf6c7d2cdac2fa8254f7d1aba331fe5b40f2cd948bc1f0f1bb2345e9f13ec80187bef04b01ce6db68b0fd06f2f9259645d40686fc98237b1f8ead2c0dc2f38a9d22424eb61c5fe43d6790f96b0bc3ecd07f93e11a203d90b3c81e0eba7fc90e2792740cf750402d16a3a2b5c098184113efd0a870653d461e993060181f88f8ef60d93c04f01f66150b90d5df368db187a2c8182cc63d1fda6744e30ae6011a6b569969262367d43d4b8f19ecfabfceba0d93ddce0924f978f8fd45abe26d0b64e1d5af97527ae7f13e30c81eee8e868f134cd76f1f66806cd67cea61bc30cac2d3ba1bc33ba224f5f1a82df1460cf92877795015503c7f9a5f313404cc7e8912b3bfd9b98307eb14566eed05a3a38b9cf4853f8177a736ff72cfd22ece5e54b9174dec4a0b056c6e56213d5ce8f1e7eb8b44228eb1a8626458140711b0f5f9575dae22b21968b4e27693855818735cbe91cc9a4c215f98d22dbc6b0986eab9d61a4569a1df5d1ee8bd303e9df43d297b3937dfd6a55f3f7a545c111f209c1e06db2efab9b9ceb7b764a845bf72ef31e06d5a4a774362bc43eee6071ec9c879483ee867b996943203f555eb284052ba94d979d2d01ca7821ea6f29b6187db752ad66b19815c380dceab1827b74e3bed401384fe6799129537fc5193dfcee405b6453ed64c4b21a84864e8ec1a95596ef21ad25f772c4b5a9efcb9fd64a91f924737e2203e721e966933968b73337a99c91ef43908a123ba2964abffb66b18d9dd489010faac0251abbb5477c3862b07f87c8b9b792dede837388bd20e11cfdf1c9ea74e2c5016411f9e5721a0fa6cb11e208a79500d40b2dd269fa45264671d4030e0c0ff536cdcc7ac7db60145213538ec10aa3740f17deb392acae8e37030add0150c5a08464e69c244144561cf9811996e8cde52c4f38de6432f7a2641996998b8627487065d80d286e8c072808bd7dbbc6eeaee6b64ff3235fa7c2056e0df1fa11f797fff3c66b40c49f7c14d104572731f4c7046840f8a6237cf62af6c2f1b72a27639e0cc24c749c85035876e7db01e6f3dd1b1ba341a77e531ffb75c37c6ad51a71da626704869d5a51da6e5ac24ba3baef4eb0ba7e34ce95b350fd38e76880b37b3e396111d2d5d2f1b97ea91dab01cb4f0a7501b7a9134632ede9ea664e34e9d86352c175066fac335671627cd2b4b9572a6575ea96f501e5c3bb5b4e6a6965e937aa5ecdaab47c7034ab74a6b5e4a5daf9b8da3f45a5748be1483ae8b68dc8a6a168a9beff7ad66dce922ed1a1cc73a8a9e3ebb0e0f85bf4377f9b56bbd9d69f4cd8c23e57a5007268e94d2529fc7e03e7a989372bd2c1501169c7af2a7970d7ea0a4061f6c306417baa25be74c8d30168ed1b19961b9214bc75174e1c52cf428188eecd370eae5c4865f0e5c535a4562c3b439b8cae98d722e7dda741c297d49fcc25e4277d4a518fcc25a2e58dde648bd752e360dce94be8098302d1407d261c2ecbb50763bffe9b5c8f24fe74ae6bab8f477651f37913dd7b2a089e1468fe9d1bf52233873e2e92d9708968f99a9b4e68fa85272daeb95df8d5c3fe72e18bee02a1973fa5df7cd38db15a260b4d7066b1b4577e4e02c175dcc4f471b05e167e348b9da1d2bdc29704a69758d15a6edacf8b95f917b6b8c33e5c29728852806ec9684d93b52e63ebfeb7d046602fa905c092ce635e1a0ef161600bba63db52fdfc415ded605e5845e54fdae635971a3b476458375022014fc3812c595919a5752b2745c29f75e74c2da03ca94860b9d30d87f8168550a201eee03040d03ac7ca2bdadb32efb1df74dd5c1360d8eb99b60f04b7229a52df50806ef058794862e7941415e2eee969a02c310ede0f7b98301934928b832674d490ee5d52a2eb1734cc2a9f8e5a81685e19e2a442f58066699eac3dda7f3938b4035ab2e38d3ae67fa6d3cda4dc767029970867dc6276865c8149947da1369a1fdce17497a951269dccb53ce501c67c765deb67830f06a249235c6dd1f73c612fba7eb35d02c8d9f90ac655e86eac26ca48df56243a53fb580526e273de4892ec431f298413af3f64a8405c0c357842f10bcae621472a932602b2f83941e27683d53eefc1492d98136b11ec16cd5ee46a96bc83bee5128da27744ad3c5c87d78a21150ec48074be1b1fe45c9435405058f1212344a9ce257a3cefab7c10a5a95b35e0ecb13cdc2dabeba7ccef4e57b4a28e35b9b1c59fb884fd4b7344b8c207553d2c823c8b8581212ff239c274dc82cbd5342009ac7729e1411df8ea7381f3d9b56c6d137c94fd229b2b89904ad37dd70d6a2cb4f61476c1e1f20663bf946ddd870e74c6c7185222d9a8878f06ff5ac824f8df1920b86bf1acd1ca1645dabaf1ca564e4ac382bd01ce59a97b376c1ab32ab6005a0b53dfbff26850e1d356065ec0d25e1b9ed39206edd76e06f6f0ef24b3a0271ae478a323573416a08a9ba9786417b182afd5fd32eacc5e5e5f55656814166fab1eb5ea9776bc446aa4c5ad950f78d59f9e72fbc961e8cf9e833c0c1e946712943fb8d6332d4bba9f08ce60ad8674ea3e2f7a8c5b232d4a3f0da5746a93cf82ba5c1867a5ca4f30599adc02c4b0e75c0602aed6cb5963cc57e794eb57d3b7c02afcba56190854eea8912c1ea55f14f70d8f6d956593634c6bc77978183252e4c8995e5bb36f0c37102db6455cd5801c79fee8fe02c0d427bcb42977dfd05727e19f480c30f27fc338c0efa07c7b4687229ed14b5dfe192e3b127bfadf3a7e6b31fcde2e606cc4437b6be1ff9a7491e6121c91f6079d2e5a276e13f507e8db0d292bc16d84758527ea81eec8016f8da288aa2e9d7b81af03a7401195c9d4a84288e23342e468ae27e00f1f233e83c17f94aa3b50ab0b82110742ecb3f94f7d1a6a89dd6aac217ae584831e373ff9b97cf010a4a1c48cdf41c2b2c389b8260c73d3a7635561b0767b1e31f5f0846b463c57a494aee9573816af2de6b00990d10625d5387e3f11a3a064e7e68b871c17871d57a5d037d4b6d18afd1209afd426c83cac9367383d6b149eebed5ac474ba079670ffa8a4e55cad8d4ed1823d0cc4cc6d99cddf5a7659a17fdb2505dc6096fa8c9e2d9fd910e705e2c06bf73e21cc9ff658ed6b00ffdf32b8bf25d7098761017aa8ba828434ca9c60e375bc7526744d84b8f014d1b9cd0de762527828106d9a343d2bafd38724da34421e3e197a9a079375eef1b175be45c7cda14b7cff6fe81a72eb603e3735681cacd76f16ac457e42db550617b6213a5a3494573f850dacf02581f847dbc6a719e8bbfba18716b1b1d772d645c68afd88974a25422277a897b143e420ca6c80b051ab2adc5d47bba5047d56b9942bc050952239a18151f874a024143ad536dd108f350225f6406376e61bfd465c50f0ac2c8d78e8afca6f480993e38521b5cdb7875c0eb72ffaf1dd9028d8382722a9cd1b2689891af624681ab76d66e754334c60971b948af008af7c08f1bd948264cfc2fd9677c444e37e18938bdf0e4a64be92c17a5ee8d4811bfc25d58af867388670d9d6b9e029c0a7a84d0efc7843e4fbf212906477bfecf2338d359cc307bdb87ae0908414b345b8ca543a66f2bc4acad3f93d92728b05d0a04f9da48f231c82d23297fe6b14c1f80e36f8c0bbd224192f9e3e0d1708c6008599c17427219a7a79f3ffe14ab5c008cd60ffa390313e0c8a3bdf5beb32ae8116076dd4f5821b3484010394eb9840438d0e0f43be9d54d6250f234beb94def3c40570ad28f321e0c3d661e0bef41f1fd072a09ddd4e9240e3bb4cc4ef64f32cc291800b849ff47c7e014aaa74a964ed1576045aa6efea77087c1a6556ef1cfd5e209e44878864926a727a9357b564cf263ec8679a9dc9364450d6c975b314474095e320cb65cc6e50b0618086d3c21b670f3747ab72b03c721806ab0058fe4e1c17a1f6da57ef3c9a4736a016e814f70c1a24b9dde97a342b4d11d7b25e238ccff7bed65cc6bab42f575364463e776c6cdf87538818ae9d1868849dbb1d603072e435233ba66bb8b434a92e3f8e1150cdfa3ae7f0bc29e36d15ada20eec357c32c5cd048e25055d748d6fd10157c3658f41e23d4d771a66cc50313eb1ff82abcdc1282c645a7eb2894f4c9797f9868395fe56e485f85fe4d228cf82114677252701f398a720070c48b9edc37ff8fbda1c178bd67f5464bcf9801dc40cc305ad1b6b37d747b2c5c18d1c87ded2f9750043e3e1bfba796595c1e9bd4e342bb3b0a79794d8c07820b629d68c58bba85a7c98f4e3ab08d52ae016f8703fe924a8e668404f0007ed8996bcd601f27380b7a3d4d4988dadaebdc136eee3bc68dc6db5c39f950456fc6f508b62e9a36197447ecfd707a97bed86a4efcacfcbe54c4cba09ed9157c77fbb2e6993c6533f83f3d2104e85c786b6f75b63404625c84996ee301c1194d5145c1a0f1ca8e00a17582c315d89ff6b4b227005f441360059cd8bb62517e7a2851e7c15131448d808e0867ec60613ea738e5927e51e4901edb05f7d57acbe1a2c44bac297b1cee91077ae1db5b84cf1e125392d6ede32ebbf6fb6fd7aca761ee79d97e65762d5a224901b3441759004b873d9547270efff35e218318e7426b4f7802941365e43d5ca68d0b053aab3c2450b96a86cb3cacae0baf9de2dd7b97324e69848cf648b772c2e772be6359816ae55058b5f1818d48967f704505928c1c58c2949b9a3ab020a84b78dcfe05432e1b75ef5fa93242047ddd376fcd8d6247d5845e66a72a3fa284e6d972efa573123263ea70c091c8541603d11e22bb46f6596f898ee3e4fa94e135e3ae226e0324861ede129e6f40e047c852b1ec609021ee6bbfcb9a843c772b6894d24613d550907fb36f93dceec5a58444e49024c428cae37494774cfbec49b937191d025c16e7d1d85c2f88677e6a64c993522b1591df46631eac8278d9aa31ef170db4ef970883eed55f0ae50bea40362e6dfb8179eebbbe2fcc2ca2443e33f32038fde735454defb168342029f03e6d0c285f799a7dc5c610c471e784ed40763858dd6922a879bfdc48761aa7562e5ff07449435e4d9b234cf20bbd57c4742a96cd44de29b124ed1d4ee1f4c38d94177bd95476ea7286057b7fbde36958c0c3f89a3d6cf46202acd21a6bad1c9f123674bbf3ab8e857dc692461f4e5532691244f4dc1d2fe7a3f1b184d634c5bc409377413ed4397d27dd73efb6a42e9a821ab802900d1e7988d3533b2ba563ad3e4a5f9cecb5d8f8f8f273cbc9bc122a8036b3a61f2daf6ff48a8ff3d9cc59ec6ff171c34e81d4cc3c0ae3d4f137c1df007a79f32baa2322857d682d67134e0897fcb5b6dd98076c285c1be5c069ad831a994b9803c614e42ebe06cdbdc0fd55fd47f668e5eea90007b08721af47f9a5099cc261534e0fb9736879c027b96c7f04caf720fb603e6a043cd5270d5cce123fc419db24242545c5c1be416a5c304767405fe36df84440a3a4bfb28548a6b60fd6a46740ed5e497939b421e67fd0c63e204dace01a74368c55cb370d2d426b129b60ff134b77257104acdceb7edf8376d753b9c1b0964f0cd41a7cf28bd297e9d386f779d9548d81856c2201fbd07d1a45c5e2be42c9a640c046c765f754fc31bb2a38ddc9a590105f754dfd98ca1ee76fbc64c7a32398930b54fa5f7dca1a0944366a81932972b2f7fee7b7cba6759a9ba7ea050d32c8102fe83909ae496aa38dd54002b743981c3eabd05261c6673c80e1fe53c14b8cb448f3d8eabc789f2adbc869ed5b84ae870bf16b0ba491b145b5c391a6c98d2463d7278b3d12f93fb9422fd185006e66b213f535083f79c4fe187af011a20b0dbf7cc1be94a0213ab71be70c15e9e86343928002ca332aef4ee6974ccbb8092d75f770f4796d7f5b712c24a6292a24635e6530c2d35e764f0370b2c23d1b88763d9f2a3584cd869240be08999b02cf4f039a34148961e37c1f56e853964fc3cbcd34d94fec6c8d094e15444ef524c45eb449a3ae20c7fc6f71b0192b9f50bce122df6fd03d2a764903a93f203c7a94389829cf09e1d842cdd49f4fd44003e841375dbdd4d9b74f69bfc85207fbbe29a8d1457ae34ab75b33e786b381d9f80c482de0a4bc642dad4a6709f67ac99245d5fc1759d787491d9bcee2c0558e5c7666266764565492e165f07cfd6a80b829ba381ae4263e101ddf798433510123951ed27df3f6581a61303f3d9eaf13c15def610d73408e36d0666d6aee9500dc2d88a949c82ae5874b76d03e923c6263ea8e4773cc62d0299f81e429f04ddbc179f4f6d575ace2bc5d3bc3d99b0cc8e58691dc5af3e0cab0525a4bd420fef85d73387be448ee3fbb8739ba98517fe8caa84a84116744c0987b4ef9c972440f8cb4f05cba995b38402d9afb93325e0ef7f235918be618418daebbfe6372bfddde723440b84b4508e9802636e62d3172076b6b5deab5419ea6b38c0958879ed3f39774f31cd5c92e47b1f8c6dcb93e8ae66a8b40bad12a3a2d5638f99d3b5d18ed240a284d19d020d0950e33795263d43ebaa93d8dc33a1f6acfc9fd2ef6b306a8699f55c1155493eaa17c06d7bfd272f4966eea01b2f2b60efd8780129a40453395ecc8d92eef2d82a96d77b96bcb524f87c888c75b11f319073ded2637dd6581a6e7bc81f441872085ab29f96d61390eb789c00c948f70c97285f615e2ccdb481ba39a13ea74d1bd6bd336bf1aab18557f77209dde1303cb023f128a648259e59d39cc5e897734b8f4571844cd72507b4e3b269a14d122464677bbed591443800b7460ffc9ae9bedc9153fa596f73398bd6178b3529b658b942d3f5c780b115a502fdd330f2c16fa83b74a87f214fb1e1fe13a8cadbd592af88cae66f303a732366945cdceac29698481250be7dec1f8c4dd94cd9e6703f2a04fca6a5c891a6e2329b8eb870d5d52b982db191556921341fd304313816343fe194b38360d7a53d5670a7701fd9d52c54292f2b2361cab5eaa36ebe824aa488550522f1890b01367c4ad00d8cbea49e0a29362ebb030f5569fd1437c263a4d89feadc6323fcd452c298b14cf74fcc681e1e0ee852c63e286805ce27803d30629143dcc5c572101f7417a7f4a4e23dc0804230bce293fe01f1a4af65611f468c1206432196382e4cb65df6c14f6c7e9ccec81a8138ae52f7103e77fff7844c84cf7fce6947effd913e06ac89defe00cb08e2b015cfe0a9b9594dd9e15afce6aa27e370099a26f8421979df63c64cc2c07dcfd41a3554a66d8be7a909767403d4abe3f35a164d3b1770c80139653c16859bd38f673c5a66a97590c6e1ed83625eca66d46f16d10eb2521b9e8cfa138043237d632b32f13f93d2258da4cd928bb8b495d84097e646948ea95086659f4547273ac6276e5ee3760f53ff09a2903618de900aafd6138e4d12d2a09a72856e145459314a7bdcf9ff1217dc2c1d31f7b4cbf5d3e5253b9fbab9c791c9235567ac58255556fe10a95959ffa6c8b80c1d1b70c7040c5d00471fd1a002a50849b2864d8b2442dc75a899054ba28aeb3fec0d95f6be6292add779c422407d660b67bbf2d55b9c3524e1d63e53df41d03efb12507d0846ab99598e52fdc7697dd435bc3049bb2b91665749358ea1ec1a8ab6e69259cde24ef0e52f27e312b245a528edd8085366ce6a5cf9d7012c1a996b42e35f7701048354da10d194533cbd4e897234041aedf6865583aa7bac5eac4c687cc3c223528a942a40d78a93f98747fd784036b86c8a28e4a3f6e866201d8ca5e2cd59fd2e943527d8557f33ec1c201d3582a2cd51135ee0bb3e6819364942ccaa4e2403950d990382eb46d43003ed524a6881e2939e703a810021fc32631de6fd21ea0025514b1a8a25f30ba0684290104c0c881a28a193de873cb7a3a416d03de14ea9dcf951040fb5f8cd55ca18bb197a70996236cc2fe2700193e24ad0a232c700dfcc46fa4498263d023a6b45c1c10bba1d0b0cb54b82a53a14c98d79c9f8a4ab7e738e9908208e1c6b130bed6044631fa508f31d6f74d2d42b21183b568a91464511942531d200459323074b200e327f1a5b0e61fbebf35dff8ece0a88fb5d1d299b49f30ad8755fee9834999d92dbc36fbe62b9529460f440a4fab4364d77992e8b4e97fb0c486e78c53e59aa3d226aa53d1263e33e0918e3cc3ff730292740a6c7078ac81bd8a8574d4c169d029b16a418d6ca8a3bb04d6d8e27beb4d3aef092a53541511e74e30f9ff37208f982dd1026849095afb6ff09680768750e8357bc5dfd7b237c5328ceb6b10ccd3371751bab30ffbf1d33893f992e138fc5c0986e29001a4ffe0dfb1f2c7d784b37a6a081ec03a9b26eb7f6bb131d90b3ab65b82d913fe1c3fa34a3d99cd5a59320d922ab8fe32e41893d2896feac8114076b83384cb83c90a2e5fe67ccfd80177a0b6e8befc1026e90c028813e8378f863b29953a3f9c88d11611d2b93d350b029180127673136c89c17a1c5d0606d43309d46d4f0107a247346bd90d20fa8431ea8935309d0f63f5be4a4ec50534468575474acbc79cb4c80e6211fbbd3587f5ac6e66b402012432bc7c7cff7cd18b7c7678cafdf64fd36a9fc0735e4c599f9cd49e18a05432c5c9c4e302465f11db7946d259d9d4015f7b675bb566ff37e2c916e9d35f50a12c90d88cd3e9596c235653ff509e53dffe2936a30b3a15c53901ad4d18d8c607a2792c54c19ed3439aa44f3292e5ffa4473061d3d578e6079ab4b08f1ea82ec5ff17f378325b01839cfd644611afe8fb7eecc3e78edf985101a17317a198b45d21481ee029365c1daf416f776b71630207053d582abab22a154b83454beb1ed8219598364c787db6923ab99af0637b8d60b7501b67eedc16c0301392980e67711e6df3c160ebdffcb69e53753ae12bc97f74451b5836a1ee12b5a326b9bd3ffcbc22025988769510bd26355c3266eb8e57a3aeb7de252427679031f26416432006b249a96940fa2380cc598321dd32da9cae6dff543d6ce41f96ced671c68dfb3e2101631c9825857687b1e5a71c8c6fccd3b6852ad3023be705049085366d002fc1d8b0cf379dd27486e36f88b42d19d4f6029e4c9294885a04fe9b7106853504999c85444be18f6b2eaf03fd06166f9feb67a1db8c8fc594bd822fff579871f58af5cc0c168d48ac51ee6fa9ad7f44081d7638642ed1d2ce6cfe8dbecc3c739ba001d0d2bf6d330ce6a6938e14a7b644e8335a3cbdf80240026465754aa30c2d3bc63c9a85a8dfe6a0848542412c1ef2193e3baf1ec925d1855cc63e11a4a8606e184f70a4021cf01ba920be54df98652e9c15a7b40816d37f98739e91b4021f8a64ce8ff72d319764a04bf2814466a9644f563fac00942caadf46e251e6352c7bf2dfb09bac59306d0409f52428555b203d5361b9891130095c02c0ec527ea2330f8b0f51524843c463a0277b80ba882611d03500f4d485c3b482d04b06ddb0c878ebc39777e39eb9309f5fe666058d5143c554e58af5ec717e96cea4752f33055bbd981afecf09757903aff86b60e777ebcb473e3ef404452dab8e4778569df1f988f7e6fe9fd554d27a0b146cc0aead03f8461a38ffc634542ba2e7815f1a377f88b836682090a8aeb60d4acf2211bfc3e74ad67aa8ccdbe2b7a7c28f8513ac263d53b9b231385392040f257884135d61361d9d8bd6b6c19a5208c7b234d031565019178c268db3c02a27f1b14d660049d21a2418f4cd3715b014564ae63da4ccc96a5561ba35b217068c1ca03641d555640fb339f2ddb39a2b711a1130b4a87eb19bd3638a10b7edb9c8a0d76bc822a63bb086ee98df7de442b283cecde175801479dcff714689932b9bf2f553e664476a406c020eff85f72c6675f2931748a56a8634babd1778c8039f290ebdaa735bc340dcd22590787926d96f8a9df3d0ce7dd03b8833deb85ba13f52ca0d6cdc806b881de51207fb82ff5200df20c1219d02b89f22ec76bdf6594a2221f7118a464ccbf8971bceb739e54accb31bd0f73b529fbbee248eab0788eaa60af5c3b31f40ff42a16e275a44280bcbc605c279fb122236d6f6e8e94e6d2918f22c7b898d6f609a5f4ff3f9131b7273ab5fa8e1032836fadb61c325f36d7b1ead5088bc398d6ac4cde1eff0fffb49b85f8a13830489c7781ed4790741f7fef6c8264f2172161b456a9657c5a732a0a34bf2e8669b34286db6d8f042ae7086dada33e467badc8dd45d009784f888f1fe2d7b8b3839909d4e1921617bd72b74d22a52d00fd21ebcf1ca25c59f13edb2dcbd4ba90d8f9b5c203172167e0b3f94c4cc7c132c3080d2ec4909219e3711d97988d531f1007b73cd92eb8f1f7d1648417624404a88f4fe1564daebac7f1eac852ef89dd2f6456ab1cc81e2f0fee7015b3081df09a9de2432cb18280ead7f1e460b13fcbd92209407b69183f7fe41ead005e4c371db84bfcb0fb276248e7f3eb6df90ad32c536ddd0ab25e3516f153c882a405fab79f8e0b5576a96cc910f7c619654f249f60d44f97e52b2ddb1874c1d6a02916303c4e9aff8a14cfb62a71ce6f4a56ce18a127241c8eb377133b2b35a6e459a0ebbdc2e5f177fde76b586c3624cff57b54eb4625f686cce16249d58133d5b55743ce63b4c775975eaeef95c635124141b64255ff8c60fe23245a51364d918239438cbd7dc346b9dcb0bfc51388c221430a42dbe4c84f3d277f7b2bf83f0a20634bad0c1b8f5a45eb1db4009a5ee4c1f712cb84e39c052d5bd4541a412edb1816d11b314dcf4e332f7c72ac0c4d007b5cd243f06ab66c677098d0c2af87267e372718b8b3e1775a54e53d6fe626eecd6cf0fb77282096090cfac5e77df6f4b885c7d99ad5b81f838f116e0bde05c18b1a9d6933f74402e4cbcff9125630dafc958af3c9133ddb4524cac935fd3a42cd2574a37226d917cbdd7e079ffb43f08935bb869b4a180fe30587d1cc395fc1d56006ec454b3d27990ec28812a2da5236fe9c142ddbba7fa9c7c48bb468dd9b36a6610bb5c9133f90dc46cc40915678f12915b93fed8dcaedcd4dc9a916fd3982c569a4db08d433c32739ee5e58612d828c51de3bf83c995a3a3b3dca4eeed18937b17d01cec5e08aa45134cad1bc545f7ec0edef70d862041e8fbdfdd4f93e7961851a7302257b2000a55204d7c8a936d5d2fdc4c85eb2cd8146fe7d95d304e2db41cf6e96e6a6aded7a174c00ea5cc1f9466392745d13cc36104bcc042752c2f958df8073849ff16eb1315716288f99fd375c8dc6d8b82b56c1a5980a7fb54e99f24ad19e569714c0d89b9f994d2adbe0ef8fdf5acd1130e606f8bb618b9cce12fdc86cadc1d1aab4479278e5f07d8592ab8054e37329c3623516d228492ba9f914cdef6e484792ef31a2b7747c883329086a4bb36bf522d2d9346caffd6bf9919cc91e89564654f0da7846c57337a258c7479efe4894765ca8f1480a29586dc5c95b18688a9ce38fb9be0cca2d714f27255710fa184e6c28cda21b1b4a98354d8dc42404b6dcf50248cca03994cf0451ec4f2aec82c68193b971826805f4521e1481d84b0b90ae0619bf2258102b7888c9a32e4981ddc9e712457db9d942895c7d2f296f0ab602be9edf8f2e8abda2275e6f0d750f923981cee8a6a4fccc3f03fcc3d5e10c5e431f0f7ffb9208610a639a98f47ff3feab3c90d1e65c425f5898ca6d0bdf7c322f33610724ac803f9f85c372e4479e2302e0baf75739e295e02cdcd5ce905d08f69f0ebd10ad609bd2d182b98c6e0eb6f2ac7ce03a1584ebbc43578fc83c08a889f5355ce730d0e2e41aa65412050ac2b4ca450d3a979afb2705faf90971e3d0c7e577f41974c0baacf635ef5fee5606083827bf0ef7539bfd5b883f7def07c645728fdeabd9498c5c41c4563ab839d21e3afee2ec388a7c45177e40225c8c24e8e7605c5d34d8e59da157aa72bc597ecc98158057dbb52aae38dcdf04899d72393e4e4938edd8f8d134687a36565005d5993229b90078f2ca6f6ff74c5fda0f0e2fc4059d12fcfa2624914de0beefe320d895ecf8fb8f439cabbd73b6dbb9250aa0d55411336eb09a46d50179a60bb9640d22655816936eb04a46da9149a62b34a50d2867a81291beb9486f252ff6d78a2c01d49dd9d24599ede74f9b3a4912ed52324dddd0f29fc0302ec18461ec373445c390b7f282b9404c5cde320e6eeef3b6632daef2a4106064e62c926ac0f2596169ecd132d6ca0027f34a684bb1604670357b56e4fed21ce6a20e8a75a7fccf4ab1035abed887269a6e4ffe0fda6279440643cb9663eac53fe032d19fdfd2f8e4495597e09512e0172a7a53ae537bf5be4f8bd4720231d366ef2561879f61e4a57944550efa25b50fa8bd0cfa857e77ca134f5959b16100ef5d8472cef2f3229422a89bcc483d2108fa028f569f52256c026e7e9f002d64095022b19cd5c957175c9fca41b36b44b050c8a3904b1c912afb74f102923de654f14c314486c78126d23f6ea140ec1532397e0a192814cb7992e53f47155fb409d24aab50d6fe5a48c7d768a1b539801c75fb18f305399eed6e1bb816afb55ef23dce16ab1dbd30e0cbdff95737042ffdf04ee33c32d262600a9b57070207d5bad2f7d3fe96b313e4077f17bfc2053336945d5e43f796d7e51fd1bfad0c8cfe41711318ce01a49824d62517e64a24dd9d1c8b2e7587463430b4e6785ea7c2464883de7063fb571b584a20fc47e234bcf2bda07f9d84d28af1dab43ad37585ec08b9ea87229d7ef6de3ac7efb18c74405a1b8615214fb6860c4c1662b6f440a2a52644386e8a6ed167bd71d5de3fab3bdba8d3744a871901294da7a7e6deec1273e715f4e1fbf06ac1725233943d83783aa62f2e9107bdde40eab60dc35ea57ecaeeb3b8b5c6278e7635969190f8f22aa4940b6643290b7c8603ac1e801ba1369c3a4abe14b7468769d242db21effc2b2147828a612bd1552e71b1cff82745ec5794ff1aab721ab28b4577c6faf1379259b9a9af5f6e785e71530291cee01d7ca2db743dddd8bdfb6f8b8b02570fba2ab707515499665d9b45eea137a45c5d204155fb09036588b54185784d1f2224e28b5b4e5fbe3a2583ead82d16fc79dc5136e517bcc22f8e28c203145b47c9349653c70469c981f9f5e7674c22d3f6dd3e5dffb15d0b168346d20fdcc9f50617f3b204170ee8dabb13ebe795390646590a15813cf12fb1d7480285cccf1e44cb992b6d40b4db1592520694badc094ad7502c936d40b4dd95a25946a435dc894cd6a02e9b6d4854cd8ae25909656912e13a4107b201677b91bfbe6d29369ad3f875ba077bfdffddc5b465f26a61979277c01139eeecae103a79dbaf8f3b61afef4946cfa03962e344114d6cb8529a6fe22a4a1f80f58e9ff8a2ab299cce714c8f7e49fd552db664f891372d0170ae19368480c923b874c85ea40b6709bc3650726d19b275dad1f279f9a45591bad46c0c515b43c4fb35eb53a291dcf1bae51d3b6a1f4fc61dda4a457e425199392b0ff839a1e9518b6a1c1b329e888aa9027992ba203346b4d8adc1e93ab181d8fcaca24441c965d4da6129c3e096034bb0b45c6652df72ca391fd8bcc37d20e049e74d91e271865e71bf48a52365b7ee21f07f5e016829b0cb9897e8b04b398231441d5a8b2741db0c86a2c1061b1e6603d2cd26eb2bd6b7295c26858ae0ffdfd02ed2a59cbdea490aa2847022534f9e8d361dd4d898734b55f1a6ebe366531964e5dd0856ebd03be0bec65d279715577d8baa694dd35a75ed7781d911432d5ac22249375e9541a553610b4fbec72306cfa6b8cf8aedd463eac513abb7546f6900ef918a9bc57986882849c208d4d00237d4776fc2fe71d7506ac3eb43d8f5beccd01349f076da25ed2b1e10c67503a81afd1416cd19b57ac4215150f4348a71ad40e63c34f9a1787744a388a9eca6dde327bd38d400d8169aa2a0ce97807f818b65048b2051db2421ba41d9221150871edb49adcd1340990a44b3a4117cbcc66793a08c44a87a4f763f6dda4235d17578a087d13996871ec80d1dbb2432d297152908ea8f046366cedc9d329239693068e839c0eb670e96c1f3e198aa83a24b456919ddd87844e0d992578cd433af2342cdba8a462a1026c94a8c648c3758494d279f83e7024a6b6ad81eb4e0f1971d7444098806ae93c3d233d5b3698e26b3cc8dd7f9b36ccffb240afc03ea5b34b79001dc26e52991c2817d57e9b44f34d9cd366c3bd582c984b5720ff488b5de0daa4152e4ae316cd54903168aa44e750b7271f35ae80f87e96468ceea93f4d43943e523f23c49b9176c9d4e819d7ef5a13eaaebc42e363f6fadeb93ae030fe77e1d6f4358d04905ae293cd57d6df7c0a9da0d08bf634cabeff0979b0252ef532a7ab3d3886efc312f0d0a90cd2be06cd083aed5dc46508811885d9fbd98e00cdd800c4aec7c4db8a226e4c81cc70dbff8db9fa7fc8c61fe3d2d298fd6a00deb0774d21f21077f862f65da8b574faa835a8140f1515dab481647ae09ee1b204cc14e896e3f4ad1970f4458baad4dc8b200b74ddbb9a88130678f0c9d7b9242eed0fc1116a234b9281c3934846855b6d80001851f9ffcb1e3ef663aa77aa09751350cf3a0c4589fb455779d726fd40fad630ef143e742dcbf3fb39503d94a2212039334ea8968a409b4c6981926dcad33505ed4bb85b2cfb31de8f31df7e18efa6c084c2a0d56577be420d17f984bbf3ed3e1786def8fbad20b1cc840b401b0aedabe8590965dec3da307a3011ecf52218707f1b073035d4f2a191db63ae31bf8f691214e047d414410b41210d39489023e6a6169b402bd197b6d8eb2451badfcb0da9126b1bc46bd9ed792925564928b289c4432b5baad8e7ab88cbaf356e205476f45365a4edfe4a7b9e1e77d129e9d9eb7e8dc55d7d0fd3bcc850b1b2cfa82a666091f0b9111077efdb46323009018aad4f8afe9e086133321b5646d4e93a4dd04258491f584570a133f6c9e29b6f622bed41819c04b5e889ff0e26a19f067720500541e5f743d0b2a0f9b0d603912cc8fa54eb0e7967e08071de92b11bc3a7c400722c48ddeaf6c81b6202d33d87904fbad6878e888bfcf3a3a2bacc61f558d09f048e29e700ccba1641ade38fe78ca4359aa7bfa3c1d266b965440859883880660ffad0243cdb6545d344526fa6097a3ad20ed7fc1775e6698af76fd1453738c8596a7657938c65a6cb74192c248e0aa2d3b1009dae2dca5aa8b4216156b53591769c2c22691f52f624950377ef96c6df43fcf6c90450c03b6aad7a52887ce87fba5db75f35056ec0fc24c05dc30fe90ca1b6bcf5b6e77db27f12a06c8e4e0ff52ba0dc6dcfdd0cb801abf8ed99be7fcbc3623a21629fa9b9aee28b30ea8275456cbec2318938f9a6d4ad1bff03b06504ca78bb3999401121120423b0d501dee16f3a13d52d804280ed966e9c37e738c290913d1d1f9dc41dab882505c065bbe57c858ec337121889ae559f5beba40847b8e6bd9be7d0175cdcb3022a01921294be079e8964f968fbed0a1c422b68992eec3dd9e6c885e0962c5dcef2e26117e4f87a4039c93dd88ada817adabd373b2e12b12c81046f95ace565ec680787d12ac94ca2c40abfe5103f078fd4cc159518a3f21bc90b6c88033abf768c592012b3491b5eb22dbd7135b7399dc8c4a54485ece46d86a00021e6fd7ee399dff7238727d9f7ce7823fc383b44bc00a89000001057e41f377500ce2a005aa39a52a905c30c9644c36c37eb6f1b694d2421929288d0caeeee1d6c0820080a09369e43357b402e4454aaad07aeb22ccb5a225fad2fe546dcf23e95e57c5a2c7bf55a37e65cbb116eeb6dc4553f50542f6910579c504e83f575419a47ae6d286e733799b4be77b4511c05766c1dfb72d268d39a482ae56e326d1487dadc888de770233b5c87760db5ed08d8780ea7804d0e0aecd8475e731d4788bcc6699549a55261d4e9743a5da122f239a34ca7195337d38d329c3d7854d188111bdf91c3d3e136de0e152a02395c87532087eba0808de78c8a800ecfe114d0916367363b021151d548cd85247a7a554b7221e54d766b3bc6d2b157f28861250fd2b49207b1635cc81e98532f8fb995659c469aa4699a0bd95cf39f1f91489af719f951c9616691bc9fb74aa3ccb7cdf12491366a4876920bc94efaf915dec86bf9dcbe8008bf39cec4d8beaa1cc55b4315fabab01cdf0eb771947ff4519a74cc33995c733c6136049f503a24971f7c143879ccf3fe50e0e433a6b5a63d930e2072b0186325c75c6f1d924bfc5fb40cf325a7a1a1e93add759dc94483d5cc013bbce4da935eb314a45b597b26af1904e2ef70cdfb486edaff459336b6c3e5ded9e1a5bda3c3a5cb8fb4796498dfb1a14ce570bc75e8c871b241a1a43c9d4e24c7a453c949dba9b4915c926a6a6a6a4824128944aa425b8e1af29dcb2c3bdc7919cd68e433331ee6e5feb27b6993dc3d287b9036e9334ef2cd933e729c39f2f20c4dd7759ec54ca7f36ed2d0d0984c341a789307711ccdc837d3ee3ccb971d8ecca1f3be9fefe468b45143667ce442667cb47fbee46ddbc8fb8c7c8966a3d917883e38e7b8192f0f6509fa99874353a4f1238f0bc7718ee78ce3998d1ab2f98c0bd97ce6e749de47a5f7adf01979525792dfed0b441f2327799f083fd29ccb19054e64981c12358355ad156218439929e3305d61857b87343d4275b3bff511797cafd62693bb75650df89159b6513999772e24dbf4846d6642b29ccc473eb3cd6156b2bc8fc85f994f92c3b9edef6788bfdcf2cc017fed5207857048fbbbd4479e0933d906a7dedfddb6b63f6d1ddbd6efb63dacfd11791e55f5a8c7a322499b45961a1d9ee7709b1dee9d96935de3743ad73d5175afd626d3e75f4a736ee7704ed3a5005f49c94d2eb7518c1fb3cd31e566dce47df9cbaf3f5de2469e0832a57dc633d17836a60c7b689ce69b0832a539a73dc7da731ca933bfbc4d6bdfe13c4448390f117e0ed9eabd5a9b4cee5f8a73ac336d47db3df193fcecf4c4d73b477b76f89aa779e769c7334b7d42c931cdd3b5d725f979ed9d6f7a8f60c78c93848c1cfbcc7246258799c9e1c867f6a499196dfb23f29a9bbc3bda81264d3db34578bd3f22df39cee4acf5bcab998ee77aef788ef7ce0e1ed56bd754efe950bd8d7699e5ecd89ec3c6e601283fa14ea8d3e974429d4ea79ad3aea9a9c9a222228208a9140f9a92cf94f6de5b25649baad79a0047e8cc3f954a454425b44396d208aa4ee48de575cf4ce7ab4faefd9980e86b75225335a8baad23e0f21f749efa04872930df360dc4f40b69d6d8f5b655bd711bdeb66d43610c6b1310bde6b453a6b9c67bc784b9ae4f78ea13adf596f568a4b5d67a8aebbaaeebbaae6bcbd9677da2d1089f58397c7db2016102a2faa43e198a72dd3abe2e6b09c15ef7111c695df86ecbabcfc461d28ac5864b1ad5609d65d6e1ee635e762e07ca94d69cc669ae3d6ee330a7dbe6262072c03c63e7bc6deff8cc4f121feff4e464474173ceb38eb6b96ce793737bc794b16dcb7934721cd98d72371a8db0ad1be9d146229148144baeb9663938e79c7d7354e69983726299e940a9478e67960333219b73dfcdd93c472d44fb96a3371af00050e08c54431a719605051551aa37f120169509583297cc2c4d904e9929e3b0874fce9d320ee35376726def9c4e2513cd4ca9442275a48e4422913a1289446a62435dd7bdf7661d5c54853b1d8558a10af4d20c50324c74344e33e3a51ace2f2f9b462a5cdccdd7c8a1733ad3dc91acb56b9ae7fde5253fd2f4b567bd77b291e7435ff34cff3239f49a124d37532a651289446222e713e727cdb57bf52995bd70975ca76e7974c95c3223174b8c48333ef3d578c9bb0dc3e69c73ce39e7dcf6d7735f89cd636d37e0e7f1e61ad73857c335e0e7352cc9cfe33d821dafed6dc9638ee11aaea6c6b9bd43836bf2fedcd4d1cc904a5d47229148a4d16834b2ac254e270fca1ed775afbe326579fa69640e02b6ae58ad5f7eadaa020b62befac58298180414df5082cb4a9d935c739c3decda4ccebbc8696be8387bda945d67d7b09c3d945601e52787bf15419d5810c38298dffcabd126ac7dd37bc7e478efccd4789bb6671c3acd4ca9239146a3d148d39836c234cd711cb76ddbb66d4a5cd7755dd7755d396b41afc5a0bfae4b859387f2ec7d31a8c8c9511bce1e396fa718249fb0202606bd92189f0cf90d50be7cf3ebd227adafcb354dd3b4cbb56bbfae8b46d3d775e98efb32c0d1f8d4bfaeebd2a0936a4ea85c536332994c264dc318634dd35c6bad694d6b5ad39ad6b4a635ad694d6b5ad39ad6b4a635ad694d6b5ad39ad6b4a635ad69ad354dd3b4ebcca7da4aa75f2d79bedeabf5edeebd5ac3af6ec48990b832cefca4e1cd1bf9e5694df34c6f1bc76dae392f795fc78d38bc39b7f1fca675e7ddc7f3da3bb71c1e69a7dcdec13eda3b996b8e233b8fa7fb369c39f41349cbb4fd9948a49c73ced7454343438384ee9ce3f4fe74c9d3af75b7bbddedba8ea7cb7ea0f1bd2ecdc3c3d3f1f0744fb895ab739ca1aecbdb38ce4f5bc937aed397369af1be517612c7f1709c6f9b6b3ccf397c9e91c6791fc76d9eee356def6427ed9d93733cdd73be759fbb3f655c756e7fa62cebbaaec3dd755d34343434563a9ed74afbd325aeebba4ea63a9eee95c46c094a9744612b9df8de2347aa8c444ee5e68e8a473af345ddce6bea587e2df4912b48d94311a492e66d8e8d304ef38b47dec7611986650f18611997ed1c8e738c2dce5ed728e348a512c9671c660f20f98c930240d7177baf0af6987eaf8c3b526e94bf955e556ff78a04d59d3e5d84f95957ad646a5aeb24ace48dddf3b3fcaa5424a85696a7923f62102837bdb3d680218f1f30c31be994fa74826774a2fd1467d059047d743dc5fc0785c27c741c08a4c7fab9a91767d070688b977f38b4a58b4f41de548f3488fea5620f3a5ed52a05c5577780bc217df5610b105feb1627be561f6af5e13f13bee6e751c9c0b1072940201711f9435341ad8a3f6827685135dda4f3fef4364dcc2df58bed14201079edbcb9080064a0231014ed729172c75709618c32ba8c50a6c9346574195dc6785f002499c81f4c346fe241b41d25064527f1090c7342b4d06210c33019cb98fec1305874ecd9b37c2d8bda6b518a61f1f46368afd909d9013f39ee1db9c8d49cdfbc22b7f8ddaeeaf44a29a594515e6bd3b83f7ae50a1592a9e99a47a5cc1e5664ea2607fa8b5cb8442f514a6e0186de83feaefe542b5510e92938000289580c51c6101653e4b5c9e1f2e6f27bd9a9d90a1f3b741282e01cf3f5e2579faf594ebdec3357e99a471d664394d0b7f6bd7f616e3d73cb4756f791da86d90999e3ea61bcc2ce8e71adfe935dcb1501d187e596952fb73c1264caf2ea7d33bbe5e11eeb73c61b6ef09a73851de7e59d60fd7a28bb11107d58b7d6bb3f24c8d44f0fcdf152b1b2fc8d41329592365ee8cf86e888dcdf7da29f9e5ba239452cc1097903ad2c0f5d36f1dff55fbc3e07ee18544a43df09bb2c5306d18b53998219181dfd337da954943fb434c91e533c4a8960c412e2432f2f7f988e235dfe8041e6dc500a492987d2801642cb72086b85a65b6bad96ad134238e70a20adb0c231b56a3a06da0a1dd25aab8f84f3068c558710fae538c24dcb6ee7b5be6bbbbce87dd3a35fd7370d470f6762d2332f7b77ef40873c1e781ed3cb4bce2c52ca29a594d567ce225dbc28798779a9e4dde61973e959fff105c3304fc9acd999717b1d6f9bc95a3779181631e831c6c8420ee69a29678f39b3f098dd9b9bb08d691ac963e6344dd360842360cdc3de671dcb91d43e73b43fd73cfa87e408d06396c6eb8916839e790647d0dc5ac7ecded13c2fd93230af2cb261f65a6b478e799f9ba696980a359e731c719c674fdbd42da7711ab795d0b78e7123c7dc3a67b19192f976e7e8a087339d47e734e80dc1bce4321b52f2ce94f767f9e733b387cac14cdb292b52e33bcf9cf32d6282d9837f4d6ee1ecd1d54c851a87b387bdde79f06b3ccc5361ce1e5d60a39a9cf591c7b46dfb92c4a2a2a2386abcc683b347867a3435cdb33967d9b669286d17a9e9dc7ad671e791fce499308fe49d87918a9c6adca43dd4e61a3bc91bf9c933913c3c2a7272937fdb2e5273f24c359ec9adb7b9f6ac9fbc1a8759919acde433b9088376b2262862c881275f9d027df559abdd3e1e9d96dd994e753aaddd9f8c143a8d39d43a9c5f0e94294aa5c3b97de24b2536ce2f3075fce30b48e3252ba47c761aa1b7a80e8d97bc7a3ad9b563cc7f74d1f35effd125522513956377a25b1eef577225f2774c8eb9751de30ba146370d6628ec6c0e1f633943c7300f6edfcd2ce4688f58f62d3bc45878bd64273bfc243f1ff10afff3d9617698f5e488617642e7307b74884261dbb91cfe8c7f3e12471c231ca106931ce4f6873976ede68baff787215902f43e12eb899f25f979bd35cf7c0695b37776a2e715b66d85ccf1e64d2ab79cedd22ecd370f5fbeed2f023d759c516c7ff4b1ece5792592088160d4b19e159e44829ebdb8a9631efccceb994fca9b3acc48d931d7a8cc511cc92f0f95f90fd06b24395b4ef6a844763be732796cef40d7dcb4a193bc08947f8b40afd138741a97d9101a2fe958d7188db739cc7268f647e359fef9c8cd43e5642f79f6921550de8a54341caa82cb47b78eb19563a653fab8772cfee2ebccc39b5b4fc3b46318e6d6fb68cee63e50a67e3e6a1dc22c1f3d734c73c9cb25aa631dca1456f2e067effbc1ac37331dcb33bf1e0675e20937fbc14547eb9777824df2f3996b87f286c32c8c7a7ff2f55df2d846b73cca1eceb4f0310fe2486d23e6360763282e3b1e79d6356fcb3ceb232f734dfba77976cc43e99d33e328cdb5738ed2768e8698671e4af30c45f2915bc7345ec967bcce73c6309fd9dfcf43cfdea7ed9c92a3f2975df3cc43e59da367509b8f3c3be63cec33dd6bdef98c87bdb4bf9fce91c4c73b8773d4e6dbced19ee5919739e76dae79f137b75ee623cf3ae7e96dc3cfd990037c749fc8137f7efa8f2d7474587f78d1d1a175b7bce8383302cdc49a26f4e1bd3959a622d5991b6eda04a5d7ab9c965a4b2d4a3f6ae54c30bed0d4faa4544a14a8c7a716d5b1fed19c9973c98031a45e75e8d1ad639c2eb74948741955985bc6276cadf387a582b56db5f69228c5ac02e8a3eb6cd69fd21873b6282d9f994ef4cc424b4e896ba65bd2aa63bd9ce8b26628c8fbf337be10b474e83fbcd0d3a5943a3ad1a7941185e9d57f7efaa10a2844effb41217a74ead7bb7c7ad42b72fddad0cb50989f2e72f7953a08b8668070ceeb734a33a8161ff006a3d3482392f8724eb7ee93459fbd83ca895ebdc7da4a3af0f37627a9ee53bfee24d595705f7792e83ed947ba7b2c49862ac5c3a67bebe66c5996913cb19b1949a5a61a2a2df089e49b97af6bce39e79c73ce4cf29c4afdc6eddccd38374332a28d7cd98891cf33a49919e7f64e4dea2fcfa99fa9c134259a52a9944b99a6542ae59c9576966539e79cb316f7de7befbd77db369b6ddb463425d2e449a5b89c53329582598ca4c8a85297fd5256a7dca4f565d54d4544259f6cb9481ccd88dbb43699dc5329aee3eed5da3d95da54c8e1364572d810195d9abb5cbbf64e37ea4ca8191a53e93433532a954aa4524d4d4dcd161b1b958de7b0f172a80218cc978b1581c981094c1324ac0c3682c4454aa9e3c0cac0339890428403185c6e28e38449171714717145882e5b4c2b3a0e035280433d8082840c9c10e205276fecd004881fc63c6186126082c0c8bc94524ba188848a888a13551122c2c1961cf42582077d1f0e11d980de1668d19de9870730425cd83083184dae884b6881c50c845cc0c486214c0c2e4a18a34d5674a7a3f0f2465e59d1354c04610855b080091dca58454429a3063c54710319a02f30685f5a90cd2752d0262702d26a04a11e0ea1f1050d2b9eccbd92a91b747e3884c613bfc2010d237efec868101154f370088d175420eaa5c9a6ac3bdd99542b12da8821aa562a125469c0602b9d52eb42cb60685534d994756759161731641e9dce265fe5cee60c28fee32134e1c05970e4ad17004c3c6c2c1ed636b90502136972cbb24804f138c27487ce2822c874994c9e3a03ca7faa38ea25e594d55eeba5a0458a2955a200820cdac08204414d86c2047104110e5670db186170e0a460fdd09665390c7acb0a23cc5b965d59b9b6d229b3165481c9703d1c3a03888b981590418417559a0019a9b2c30d40b812041161c2b06207f6c6a7bb3266e03dbe46dae33f2a29cd0180379ee369e9bdc21f97d3bdb15d73ed08bd071014944f8da872c30f9ef6781c8923f524a3d22d2a998ab5d69a85fef2ca88af6e61fe59966555ea5654ab56b776cd4ff7dc57ac585c4e25ae3fe74faf2fbdd63cedb5f3cd55864bd249aba59fa67e23d4a69482716c149665ad6280460d2b1dd05001bd6794f92f95c5e72f578f89792983276880410a315e0044100f00f5a0458c2e5a48828820d24d2a29630bf06782fe68a33dbaa94b156070f91516fd412107e030c0b22ccbb22c4b5f6c05853603086650f91d6444424b87d2af7493ec1231371e3a9115d4c10c2b550445e9a2052782a06045105a507141961b74594111c3181f3420c443c6c789225e1c6be3e7101c40fc845eee8dd0fbae7b3738c2f42b7a487c668ff5d6a79164e734c723bfde03e10897922b2110257a42204a4c7ff905ff6e8ef97529b97fe3b6619812548e7fdcb9aece03d6f3f196c8d4edb99b078e30dd676fd6a3e61ff4826473ecd9f3999f1d5b6c643dd4c85e16cbde4ef6ad73bb772ebf18265dbbc71a793b56c73f057923e52712253dd6633d970f2ac79fe4f0497ba747c9fd6b1ff9cb731dc7fdadf083c4e7fe759c89238e2439d6b3c447498ff520e0f100b635205313f3e8f7835e50d6fd472452c42ea6468eff682b991e9218f3f5fbf913029fd3fbbb7973ff6d2b997fb3e821b18e1df75c6e824cf1902938bff8c59bb37bb1df8d33ef44e55c8f7eb7089d1950fe835e86ccc881e8f21e12eeb56dae49a6b0e399a3f74c57c111a6f724f9f9b84dbbb3b8cbaf5b8f8eb1f1589887197679286cdf3530a2879955e36116adeb77ef58bf8f8a8ea9f12814ee63693c46f4d5e1c7bdd9dd63fdd3ad647ef40d02813f575668392116204d431c7d91d662c00b1988d4b8428b1d6810824b0e788822054b932862e05083a171839f1d8010e20561644902076c5cc08b1b63e06042081aac882105859d317f88641451c1c40fde00a383a124b4208206656ce1820e785069908174c0172c80610639d0c00b193f33c8e2c50d4353f0408b1e80c161f4254a2f570011751737b4fc415b6badb6b1d65a7ba9b5366b09848da3852b3de80086052ec0f123a5063f209185162a9c6871c50c20e07863276d78ac8ed837d75abde4e06bf52b53da8a71850c443b80011a446704f94c8f8215384059011c64b67811a43a1cf242c4d75ac6d7ea2abb5756340c423b2656c063d92aa5e3482caefdf1ac542b12a853aaa7432a7e4ec9856e4b8271c50525de5a99041460f8601404183108c1eae11756b83c01860d164646dd3cab7ff20596eff170e80b32fe3e1cfaa24b14580141e86b1583944db084d60dc2e5891074f8212e4cbcb5eef2467af1d653d62d4fdbfdf1acbeee6e15d4c3f470884b94cf1e0e718192554ea8628c51084e1e000514757aad95ee54a792ce4969e751d9bd431e74c6d10412d4a5748c8bf7b75ef787391c42f795a92128c0910792eb13dfb27c4ebb3349f80f96f1d5ab8ef7d671e6bd5ac36f07cdcfcdbfeda74f78637d6aedd3ad0d7a62d4cba7ce5098d50de004095fbd66afee0108247ef50f4020d4eba88ef690d48f7cb44590a9cc39af6e82bca9ce7999fd76bcdd78e6792714ca396f2a5358522977249594521f5634dd57a66af50f0ad54aa5bc91d2536dd198576c5f99aa96656508643eacd7b2e0fc81937a424737c0189d6309f1eb55af65d94d944981e106ae4f2c5344b1f2a787534481622d0482fdca21d7a7c7e96139e398fbe381a4fac497ee40be1d1fb78ff02633c12df8c3347bd87bafbf7513dc6a3b5b45bbbff9d363f4eba7ff72e9f5a28123f3c7e87278dd8458c20afab06ead9be68fd1c6993dac733b3369d81ed1b2bd61de1ad0f18f9b47a6ac1fb1961540133dad47ea5adedc7bafcecef57cfa2fb57a3eac68e9b56e2d53f6be3d226f6ee48e1e9d114eed4a7923f7a7daa2b1c55bcb94f54b712090f9b0ca16e211d9c37a0a0a1ddd0063344e2c21be7506c81be9d68ff8c89bebf6baf495c4979a105e58a194d22ec8fc473f9b0ff350fa10b18b20c905981985a84cd1ec96132e6c9091ca2db6bc94130a9e8ee97f165a7afc71f97424d531e6d353f226fbccbc1f36bf367f5aad0bf1cfbcfa4765b6e9b40295b83685fea710962d5e26d1241364039421a85cc9c285bc91ff73f39844c9ea06a467ee850e9f397e80f5babffdd8a9cdae4ccd3b915c2e24caafd0c787613604058f339f9eed4f0eb1407f2bce3cec391b32a9c8542753d3b33dad681ea61579837dbacc86d43da9c89492f85fa45efc2122f4c2c94bbf598e8e2efd3ab67be2bcbca9041c613a9e114638ab56ef878279650ac111a61b000efdcd29532615f840b706f14d339552a956abcbafe3eb5e97d3a98273b552b99b4c73ca6bc7ea5dcbda57a662ddd029ce8cf507f29aa0033002e451422afa90fe790400804aa656b38704e613893ea41b51027a160f739029558402bf08657b0920f1d2a595e82345005da74b8f4234ff45a1b8041c61c61ce44ddc02a6a4cb784528fa9051083a68c9c1cb88e5077004e95f44e28574f49ee82fa451f0f8710b1d85a2df1b97cc1f4edc994557ff68bc054011aa4f0f0350840ab9fc40a915caee10484c0115cb45883983945a6badb5ce90af961884be56d7b5d65add30c909a440ccec01ffbaacd51224c55bcb456ea1801d14a0030f3f2ec0e28b1e9068a207576af8e9610a358aa8c24416451405d1a0e9a005530b563bada773a7819e52153ca5b40d6b7ba8a5890a2415364e2aeb74e329a59452a7944eaa0506a2a79452ea06b52ff8f03b1e6a81818acf1e6a81e1ca7f3c66955a73b0af8e44f575f76cbfa7b52b36b445e57c108ba78e44f5742ba133479f28a97843cc5442046178dc79c52a0c192d2d1069012253c6b2ac1591960fb5bc30037ac9e878a8e585175c28e3081ca74422a61b419429025383a11ab058008b98184c79020a1b64c041111a3b69a33a7cf2558b0b39ccc42a6d6ca1174d55196084570b59f46f8a2053d133ad93526ad93a551044a662f637c27b6badd6bad4b275472804e1cd1b4b8c6c70ad11c5c233d0489941bd82c043145b94f9810e52e87c2173441718080141086130a161040500a740ebc10a013cd402248516a026ea65467e034724b6f0a18b21aa2ce1831a43245001032fb230c38d2aa87ca942bf1c41c2327060c8072b5f2c61460c6e30821139885963882d6d30f105caf525088d83f2432d40375c286fe44aa7d40fb50035c1a2080e27454429a874ca55ee6cac1405e1490f878aac0ce0e150510d454ea2148ca54b9fb00d1b967cac8ee14f8f45298c3ab188e8037a9c22a5c8548c9e742a32f5d363410f3af52035638341b2e7bdaaa2bffba6ec356f7993737623f307cdb57a900d66f90f474cc62ccb5c08fc6ca334dfc97c7ab6a76bd9fbee7dac79d9bdace39fbf6c154343e6d1656de20179e4ac3b13166d0209ab6bfd0031861551ae58411b29a0f2b3831a889e18834a1138c08063b022e79c73cea214fc9cb368869f452e14b930c6972c7c3066074474d1c4ca082c9a5083075a407181172d46b8c9c552d0268f238c50b6d65a1604b156eebefcba6b81d6e2a8a10c910d1a067a07bdad5ca0b55799f22a773663a69471a28c0f9ce0c764b8d8f8ccab2e1a351d0e9501fae93892cc1314181b4aada539e79cb3db7cce64b8cc596baed633efe7b1e9e14c4a664ba482318d2a9091f2d971a496d06fad28d4574791794226c8c6e6abdb809164828a34b182cc1ea8ec70680c97cf18e6d8c3b02b4b965d598673e699e30c3b8ed77565d975b18b79e659c79eb597c8941c1ae3c4679f3241988e99b23dae37744f2db71bafc0d03108f75cb03242702fb3d0e899dbeee150991b5414c0292a2a8a23c80a3f491415151505d9b09b5760e8cdb5ff6098ead1cfbce9dd8f9ef6d8f61f0cb3248638fe234151d1df15183aca75ede1509920f9df098a8afebaa671dc57e784c8b22ca3de860c95874364b83ca6f2d871ce39e78dc27c277b742c7bf49cf9cf4fef5ba239cceafcf9aa61c79937bacda33ef3507147388275383406ccc321324f1ee3aefbea5d991bb03b7b6058962b01d7b56d5f7d1b33e55e1e9429ccbb373b01d78d4a017e752199ef54d73edb0f46a372b4afae650e87ca04fdcfc7e97d4b7e7a963d7c79f67e1e5f8e33311f8f423882f5cf8746384466cbfb64d2e60621289272861b53ccb8e2839429b240624a0f72d8011b4b8c6c70c5e1658791171ab64aa7d4f170e80d1e6881a3935dbc9066a5538a69e34757586cd269ef755d1cdc48a2862db2604283252f0083862741b8618a1a8258561853dedade8a3578cbb22e26c6cb1b59bca18507537653dc614201c044dd5751ac5e302446085bcc392d6b255324c894c9c67988d1a2d2f0d3af982a6c151f8fb0d838a1052e9a54a9a2840e55827c291d60086f289db2040991c48f3ef2463a8d3ee1fe60065dee19c3556badd7c216b6b085e78578ef78979aae6eca4bdeeb4e39a5636a37f5697918f66f7e955f1fef8ffae53893524ff2f3138b96869fffa2cbcba43a9328d19ba482bc108b7c0751162310f85ed8437b77a653192b80af0e4ce50f18048a71f2d0f5096bf98349944f7a74264d54d49b78901762519028944a00c3287504321dba06815c9f1eeba727f9799f1ef83f316e6055855ec99bec32bab4309f38af92d0d7e15fffbadfc93c3b99ec77e6bbbf8cb397f9f572b267fbcb3b9663d9837f2d87d9f572f676e2b53cf32c8f274ccfbc09339a4db6ba21db106a834a3dc156cbebb5baeeaf3ab6722cb7fbdbb15e77ac67cbdba95eadc3ace69de939da35562ba17b576ff70e0d010f1e1e2b24280d010f25f5727cbd7c7974a5047d2af38d15ce20240413a12b5b34c9a18b3156b061051358bcf0430c300c3f4e8ac0ecb0450c9330c8c0ca782022c1819804b7c41258c6a082c5081e803e2844001eb6bcb065891db06012e4d30f31131f60885e70c118685cd1220874c8019fba8a62e5031e3ee0e183f959af5e3d5eea365ea7318ec1e4fde1901a4eac11e6550f87d658e2d5a09286105c7cfe925b60feb2e1c327e0e15098327e288c9530367c182c8f3f7aa442ad37729cb1e7ef8b54682cb7f6e783f717b54c277a9609d1dc8af0b1859dca14ae518a9c734a6f2783dc9cd8a5c43df3776e11b184e938723a9973fb938f638cfb9b59c9bfe8252caf67fecded33bf98e18dcaacfdc57f80e5717f399647b73c4ef9f1f3d17226a4e4115bd3ade5df8c97fc835bac6f46ceb9bf394bfb835b8458be2375f25bbebf24174cfdcc836f3f2b4194f18b5bffcf0a16de5fbcf23b9ab3f0d1fbe65b2f31fd38259660f9dcf1f3d93df3bfa865b7a48f741f392595b718bbc49a7ff2c373eb681e3d468f994efde8993625fab0dcca8468d13b2f3bf5689c6479167e9432425d878f39ffa293fccb9c34e2a28ffcbb2e1f6dd475ceadc7226209965bcdb34fdbd6a332a5f7b7b9751ab84548f41d4d277f8cfb4bf2f396679e3d4af158442c017ea672d5fb95e02fc733c72262095f7ccbad7f7067ffb05fffa2dffdc12d65e89dcb2dfff0f6995fdc3e33ee3ba5f69de0f299e5d4bff6f5e85ffcd68e45441f9693a31ba4d143501a3188210d19888888c004115df125cbf645081a5dc34b1959268307326a30925dc8b0c19201031a75c03101033298b8910d418c209878701a020e66111b51a460862ed628e385034ca1c50c8088630b2c57aca187f042015eb03588e942c61562bca0050d64418318c634594306431843cb0606e78213555401c2105f4451458d21d8a0650b2cb6cc80658c318618c3881adc821817ca983266075288a10524830c942d5f829822ca0ac08cc1c680610018c8823143cb60b408a0c7a894ec58697b54a22992008000b315000028100c0704e2a048345104618d0f14000d86ac465c4496c8434992a3280e8220838c318610000030c68011a29aaa00039f1823b94d2ac8e3268fb87b5704f3a4a81cbe53726bf858d72aea26473eb1ac9cc035a4a344a3fcaddcce27437683475e62053f2c189b16336d4f9e4c8a7e447a15aa3e5f8c3905fb8d1a45fbc2a12e3e1a5c03f4861b5928650aa20d2ea9d1dc7d4646ce8f1931fe1cd2be5387d46e3be50f33ccc229fa8d33d5710f3850110e5e9130d003a55185ca9ab1395564a381110c0d934808078c409ac9a509de6940ac06ff877bd58966e2f602187c15774ec2234ac9da36fd9a53ce34b481352bfdcab857770de765402b2d1d2346da004edf7138dea768d9da0dbb2da005a1b2d1a74e87f83c64dba90e819e9094f5313d90443818ed25a4cfe492fd72ed02f7fc263bfa71e07157e53cefe0ced3afc2e82ddb3bd7529be7be3e7f7336d37b9d8a70c06ce5b1c4cd2e569945407473e7d1fb37f09625b94c085856478f9626929da91383b912483cdb85b46862977a987422d9947cf46f7d670e033479b6b6a1d2472a61842c052ace20246338a47ada4cae22b804fe95aa89876f93ca6d29d546377b4fb72fad513738f95c92de277ab5afbb453e923c73e8ed287592e3cd046b18d9ab950d7dec7ed8b31f8789d0e60d09dd6b1167b734c9d938dcf66664b189c82f06c0b726a5e79e6168d9a4a15cca1449ceaf98694dbd97895d1bb2b82896b674a3c0ff23ff94e7b800f7b0f586f545f83f53c002941133b604a104fd82804e7a31ffe9721fc7647fa38912aae06ad6df3cee9dce004469918c70d2c5c6548afffdbc755def2d11d07d0e9c3dab29536b13e70785c8df501b56c3fc4ebd193ed9733d9cf5c63a7407f1b0c04b193ff9417817b4f5b0e2071b8a99ae7e1ae244b9dedecad8bdd6465064399b70320190f26c3024b4333e539b1be799c68b285b97394ef6bcce8a62c8bf08e3e40443f174448d44aca8e1c209d4509f5736f043385689fbb11a5dec624e1856f113d4f5a435e54438eb6d0884e4c84c341a18cc6cb0db72a1da719dcb9a187a4024a841aeab3153d1b449197c0cbcbcb7694ea62eaadb2be94cb43692b4989f5e3020ae7200ce451124fd4877877155c5447aad2bbb229224728c184e6515e846a1b7ad33657ce549a50efdd0f8d237f5dbf3818d055c8c51f9f66f7e2585a9206cc71145f662c9c998fae43ac8471b901518b31fdade91da2e45c7117c67d525ea4320bfbdf830a2dda29f18331364c782b216fba7f1400ed49d77ba9151aa23429f4a863c02b174dcb380a1740be81c8e2ae4b98cfb7dcd48dc8513203a19e416a887185e89b60cdc2b9c748bc1fe719e195bf9236d04dc83b6fb5da12b709d3a505e45f8acc43561e83a9e764b6ef44216eb5d8edfc479f6adbce59015b7588cba5a5fc18545385ecdb33375a56c921a56084e06fa147ab255c4e5f0d13adb54f02dcdc3336c356f6e976f11ad87ed693cbc405437b718137394332778ac56447d5aa6fc70de531b5d6813a8720b69e68f9636518bdc5a08b40fd52abd8ba3ca6409a94b477f83f750cf4f2ac519eaffb84146c07ab812728352ec4acc34d58c7436e73c787a70c7a5467bbec17067bf9d0ef9db0fe33e146e6870145b2451fa820a0cb5467fe5fb3e337093856f82965792a4f5396b9b437e3801780a665826717f1a11d3ffe7b03f3cf107efe1011c4177e3bf3eeec122d9fba653e2679307fbbc4e7e86385c0a2a65c5534ea0fefd010c9f6a89346509bceb365e7aa0fe79191c61bc3246c6fdc2bf7ee247fcb0bba5c9f0a3c2db71485e6cad63c7ac97ae7f839002b11979bc99e0348d1c27e10ce499e76b709a478d2e0e31f9ba91954eae28946c67b9b4d255f818d0690119c54c01031ebd003b722a5e1e693c058bf0dfe7850c532d929de91bae65c27a265eea9eb39e9de98075f740e73017444794beeca0fcdb485bd25f6c2661265907d1b4a9727932ef457232cba6ce00d8a5fb17bf28ae4dc143959d2a8a1f8261ff40f3c044e490e33fd0c4410863ee52039900f99a14da88e49bbebb57ad6006bcbf59c5403f3eed29c0bf28c12bdeb00a401c7e96d630c952abf2873892bed1f6160b818c47f6952b2c5351a118ec10ea45f6de4b9ebe787449c238d86418fe86a123a3166c9e93331d56a4347602280866dcfae88eda446cd41f880b3ef525e9c2046c681d4d0eae7685efd808ef29553b4dc2c06077827b5f9f8e2727d178bf77e05aa71d663241db0017ac03357ac52f8ad9e0a2bc53d28f9638a5bc2dc031c0b4acee8e20e6d13e06363931d9e4c034b44522d90f59042e126161f306bf3063fb3bdffba539c78bad5f3e6fa53c44a86e88e1cf00386b3342b6204fadcb0103271e61bcc32ee3c38314830afe5e9b40d521afd279e8aa4f45624282be107fb515526898e06d38f78a6e2174dec5d8bde1375b0aa9e93473de9e0d922fe10c2a610167e94c3491642718575a54a3f93a8b1296cbfcd0e87db0fbabf47073e1f2b3055bc514c1546305c04077e13ee421ab01b8ac005ac8b2b7d3d8ba5c3979490f9cc91b73933f27403a7857d4ec315caeaf418e9d22db18f9b4016099a9555c56839bdcebd0210ad45988c2717db3541cde2751697840ae7e0006492cf11c85cc3a4551aaff5d2974c503ca7636f21cb18853f1bef98a4bfec681136eb82273cb902a7ec7b923beb96b9ea03afa1fc1351347e89d3b7dd58d635e50202b7e07ebea7494ab2b8e4d89d893311b079d856e694cb8ec0203ca7214ad44e4aa7453653ced2314f611ba930825f973b147f2310675270f7018eaa2c0a2e0289c88efb305defcfd9a544219858f17897e68528d516f21c623e36ffbc6dbc228c99d51ea0ae4b55726a792f60a85a0348f51cf438d861c98338bc11c28ec8166f1f7a0661b54166ebc45eff49ccbe98994ec50b2806dd119eda149490456eb4224f20c18b3ebad9d9ce7ba0df72b2e060e66b9e9ec699792ef190d79d9e0f96c1456bc5255bf9c9ec81eec4bc950c156f19bbe3d4fd446a1e2cadad6e972e9ac7ca005e762ecd673f15e89cb376ba09a5f6a7f501cfb31d8ccdb8789a97bd674e7063c0a1b72baac6ad5f1e0bd54afa2e6f304b63295e1252f0008a61a804471eaeeb928b72fde07a1ae7c2983085de0946cd5c21d2f45b7868a6bb9baa4f0c53ab68dfb65ab807d37dc9b1cba02564677c5db85ceab9e8c1d88c83ee417079918b624b91f8462a90b78b4c56e1344fa7e67ec4cedc72497988d071ab572187bcbdbd0fa021f7874ac1d145d9aec3be5696c3c393e56859d4987c22028f88822996dcba3db134586fd6e5223b5fe697944ca6d88f99f2f788076aa4b4da52f622ea0ff83cb5293239ed283996b04efb73026d7843f245a7ba5f3b627987cb16b446ce6855712b7a42e631268a31e68f526e2872ad274469cf99a749dc0e7cf165e0941b8eba1151e7f37979621999cbda0e0b2a742809bf0d725528e2d14c82a3931ac2f2b2c2223ad53f33e83b65d16319d2636357b3310f2429c84654967aa70ff8e4a5ed200840af76b3bf2915ee11fe3c97d1083d529dc10792bf9c5a97e2887a99bd1e1c40af9515cf7abc2e0d915155a87a2bd99366216c1066191d86c809160a3facbc4f7822a98bc7d58b918c2b80308e13592fe825121cc641b44884c18963e905d63b2d730a81ce1afa93dde99bb35e6d30c93ffb1b910569e0bd7f0661602232491836202130a909142265b534b967d68514d8a37a95606f82a89acd01d416aaeca47cd62f5a6ac1ffb9d615b950b36823a6d1138d837dcf21414fd2f1e3410a8d848a0748f9b1de5f5203b11b47c4a1049bbed1ba7a6c11db24da4fdc0a7b0f758f71da20cd82da50ca01ab8d27dac46a937dba07b00f1f42a2c8c4acba53f82f6e94b0220ef780131f0c1451627037a0783171cadb8b213f2ff31a2572c75324504df087237aab7938c87a39d94b2c86d482474c0d3f19ea6ddfbd15cead65d4a048ca69b2f63518a04398a8426825edb61211fed8ae39b6f18bf0c59370211e4f61fde23401b2fbf47b69ee94e8b871c6b3b3af4db3a91fb37ce23b1848292c8dd7000cca8ca00c994957ed230e52fbce54d1ff64545105824354e5b6681765fd11dc5ec23c1fc85f29bb85a722a05b0a6e2fe7a561f7196ed10a5e1847572f41450fa6a514dfb129f4ea036d3208e3bf9f40fa484b4c195de4795979a82a9b4c67a8b2c7ac82061ee2fbe68ffcf76f4211cfc579c7b7dda817384094b52186ce5ca42285d9f3647e51be712ea36b5b110fa11adddfaa43b4782d61818212c3e41c27e006128f80cf563bcea0d6b854035890d223746086434211ca147b03ca7fc09625cbd675fc63b5721bcc084fd703d1282df77408e1b65755957c7f9b83c2565615ab89ec422211e90b315ee468dc2aa176cb60e9603a7e805f6048c83f2c4a667c114307350bdc35da112f3eef64d6e0c9b574688a0e431c17c872a453d798ef3ccf34103ebb8894d8cd80bf84ddaf9d906ba85cad68edd501f894c41f3c075738db4936df7f692a71b2fe6b960dba4437f2ac1b3835fb96fdee833b882379cdc3f9f2cc119d052129771feb57a3699ed97e9069e06187206c39825fa7ca874d582523d0e382bd59f842736840e53936de1e9a3ad7543d0b7e540695834faba561319a9895d5f1c7c15aef1777c945132d0c2a7a58f06d75892f4a2a9f4801459367559b8b1ea99c2b174968f897c63a9f2ddf6af978894ceee69105b43d04628ff2764c1e68e7a08082b5fcde876acd93ed90113bdfb7f5a566012de31d56036d438f6ea49778ae8a41fa48d913c3ff3fa0006c5a93eabac45c9473c7bb9be5a3853ed69330e5444ebc2e1a4d1ad2aac5d9cc9aa58513e84f6512fbb2a1fb718a559b9ce7637714d550855a13b03277d279395d1fb080ee6eead4158ec8a8d92ae07aa944d043d4f8d5c1333c877dd4a8435e6700319fbda60489b87ae7f2c2cd033325c90e52109313553e0618ceab8201e000ea25a3f98294fd73a48790337ab1dfa05544da19781eb9cca02734e5ba693a5b39a26e6f2ff2dac1e6ea710ab659793c134f0acfc814becdd13297a9bc22476cb6ff839838e32d72907b0ea7ab0b1d6f5a6d9c3398916e8b4b2083e6ca60a3fb83b0f95c96da977c723ee6d7b4281952bcd0a0e6826bea356c055af4b2ebd10354142a33021a566ba6aa746a3fa628b798287cc21879179e362e0b2680d2fc36cf901c1756c2565277891d548ec358e6c53631b9cb4f182dd7f41e3d14c42299c50b8895414c7642a05c0bef0e381cc7794246023ccd833447fb1fd53207f806ea244e19e244918c8a459635b0a83f4621996e47c4249f1ccd1a62f0126d0dcb82597f5fd4a5632391d8a4a911af5243fa78e3f579bb608553466b353837a25ecfd88fc00f4ae6a167c1f41362f86a6a70f39ce55f656fd8bcd017f3024e2ffd9ed5d729684bbdf99e8027a9a8bb92931d6118a8d1556ca44a7a0605d8fe22925741e225916f338861e3afe718d334a7a45541c0537768f284672c4359cd7846d166fb1c7315e1b73c6223c90689bedb1896c0f974b5f05a5b40209bfef47630454d670b6691c666b623ae22079fc6a4ecf5cac71e7806c83d4211ea373b0ecab653bdfb5bdb80c6b7bec12d4481dd40b006a908e766c4310dc6edbc2d01a8370af3c354e16a8efb44d710937fbd17e7ab96818340cd9e7d9664382bca187a864b7c74b7744e0d4c5422d26278c86ca893bdca530292b758207ccd688b839a0d1d54754acfa498a93e541fae72220640beba3a8db0b4cc12721164477b644c86aa925bd5c79a0eb329bcd981f49e9ee692b499ff19cd7e541de2b34934f0c358260a9b178adec37566c85164c57d91b3af6c00f60f7e060420448338d38c61e4b58aef30224f930391fecb7d01393418217eff003e66c3bb5ced0ede21f42201f7f49adaced743adf156abc5cb7c465adceb10c2e87d50c644860e5cdf8c9e67a2b330e32ef0e41f047928ebc76acbeef17f7800651fc22a49c22b72885b105951b7e3d7cd79e375c01890817c30450ee5ea420fde9e5d7d14152c423fa63e3d9bdfecef3f02015a06a1f0f5edb978bdf72b365222fadbc4c4681c66d2230f910ccc370965543a75e51448eb7955372bba3d8c94e1f176efa7597db98f4122bff76fcb13c2e7f6eefcb1a8611074ad15da4599ebaf496e226b58a9be7f688312bba5045c30411ed3918b6bf064df64ed379b753f0b3f4900c189e9cb2101a0478eaa0605d84cd75c61754a9c9868923e5884c3611437b605c0d01d04bc4ae18c4005d97b0ea5cce17cc7048ee22aeea0f8ea3f69229caa84930fc0d36aa3d9d172f6df2818a68032b1632a31bfdf3c5f3c0a157dc7f23eaac98ff36ae340960b79bc65509fc6396421b8e0be0e67c057c2b5f76642260b5958b3736866f6fdee9baa1957b088a74545be7c35122131aaf9c474c380758a176592198424c17a2c0b7d7b14d77132eb10104da8e876cfe646ca195d4a406a9d89659f345733c4ed215c4f5e493f2ae99e119e96b0f78831669fe98111f26fcd25cb48b4e4d2420162db1c963bf62a6a27c6cf469f39fdc596cfa8a78287efc14533bd03c5d3ee246773f44053867f4540b9fee347c2272ce8df9b89571c2af07c7e11363f80c03bd4eaf96398cf3659df65b12532b4b2c0ee30c56da1c807bf85290eabb7a2879de636deee178c9b402640d1eae576f2b2f5dbe68a7783050e4880d6572c0a755d55fb75aa1ff9a35a23f2c007d9df33e3752f196c4d4fb6f37a7b1e05b2408d5fce6abd37affa99f23ec0bd8f80a129f5a21acd23bda9c025352441eef41dee22464765bb23e9fec3c7b1fed0a9cb29ee8414e69f51bfdf09f4283d8e84b8020c0ffcae4549319a6609d0e2aa8fd14004c74ac2d304bcd131cf7accbd8310213292041106a26bcc17cc2c8040127e07cd01f73da0441cb4449184c2fc166b027db817d9d685c34326da02cd96725b3c84bc7088c475f4c3920729cf04d4f52b2ff8d176ae262e5fcf761c30f8a534ab1fbcbb35ee86f59d47e03a9e31e8a2c0cdc42283c89d20494e6debd65f0f27ba8edf30b974fea8e3824113491c02dacd467592aeab635e2d8ef468c9489221b0f2071d6aa72abb8bd7ae30cb26075d696ddd90b6b6613151221da8ea4e743dc19c3022b3999a016a1d2bc2b272756e50dc5bd2404f6644eeb9b2acfc12acb76090ba18e51d4f609878261e0539eb4f83b71f03f07ac6e3c5ac0234c5fdede76c757e24f8f9b83918416bcef3a34485c869036290d1e4fb9361dac39bf2ecc2d62549cfff66ab974183b7437a6001a181dc6abbf85000d4d5d3050fb645b6c3028f4969664b060d88649eada547d47af2b4aa9cf108b672bece53a0b3916e9db10b464f815c16af87aebf10614868855b02de5ceaa972a6827c92ae8d24346ac02bb60716eef7b9cbfad0a14d44f659b1cde26592c61244109361a9087a8e56d8d235b59e0a6fa2215e3cc31434223f545706aa4d33e5715b089bfec261a74c174c6126acd404eb0f120ad440f19801a244620de22b9157de6770799e2d14d7d6689b350cda2d2e68dc18abd55cda50ac1083032f63d4c6bde2a739d78b76f154b77b408ca11438bf530768e8634800da7c1cf4af1092315c830d9b927aaff7e8af2909a9f3c878a4feb301af84a7b3636e1d66b1cee486af54167e4e28fd4232d40367e5b5dec1deb6875c3b8c4036fb30389a550522d19ad1f7f39f2ab9323a3c5a9014e4946d000e30c001a88d51804dfc0ea1080fca7a294cf1b211ce5580b03ed6dcb495d13ace3762aaa624e4562ee9870a0cae20fea4eff320fe4a1ec31a10f1e1fd1e5efa767bf04f09edbf8876a819a5bd959021c7bcb32cb50951175107585e3aa8da01f4f5a1f13d4c1bb001789dd0904ed8db84e342fc96e928a6f7b68d2eb8698bed248183c4b7343f4e75c62161478ce76d00ed448fc2173480e9868234e25ee0f550ff56eef54b9b88723e096b540b140deee623f7478468ccbbb6e2d6708256c2e86b87537728ebfea361dec0fae36785e1985aec39aa15ea606e8b529200bd11a3ff82b45d27bdcab7e8681d128c31393160bcb6e05ef29886313d8bb4cec42598c61ac94e7772c9cfef41952ace35db1b595f8ac97cead2f35f55046bec90714284de484a7d61e6bf2d219556f0d6f4a9c9baf76ac535333c9945415ae2b99cd62d54d8367d5541ddb8e19b8dc988a18d4fbd08b71048333bbf05e3837b89ffd788afe89d5b56e9aa3902bce89daa8b52ab9692e47d51c3e6aa328c2b6ca110e5d6905f01d8cdb8685c30677a33502a3863ecefaa028f9b5926529bd77c75463598023b404ae79f0db08f53a7552d1227f2611653cf7b8c1dc0a9414aedd100b9b52b7a709b00e6f9b3230ce399c1b7128e15de49aceaa16aa1b11ee5fe11116418c91a786993b05e1de9ace5177cb029dba0a51014e045cf98ceebe242b57d116cb28d9bba35e541f8429c15975b317ab6a2be68e4a53dbf86cdd369862fdc73de35f5bfb1b82c4f41f5f3196ef1024c41acd27fc111866cf2fd0876ea3ce9f6e7c8e7cf05b9acbf6133bb9c3f11ecaec6e0181b22e634177cb0b9db9c049fd4f98fe0ed52ee4356e1659cf54daf5d9424cd7590b153f073436104932cd44c35fc2f8a35343e7441e6f7427a2273dd0c174493c22540f60414d730403c242b00c7b22f7d951a7faf161d8ce8cc7de9ba529b30233ab94c83e94d7c3cd207051fc40d815be964b42447d15614e9b9cb1a6939e7640de8589c543c2a341075ab170baf7ec84f0703e85248649c10d9a3412f26119b67eaa750d4af7bf0ab59808ec6e5a814d6dfdbe84d621993d81838231ed53998ac150c3deee04e25bbba7560c570013bc73742869b8ca9b3c6cda654f1aa415ba3fd95dfa98bb88a4bae07d27312a44874835d4861f0c7c8cd94df4af0c30037fc8215dde890a4480ec5153b7278b5a33efef47690e3c0d6c1417a0b96e4a22bea87f86be2860c8f8fe60d0b19f31fa2b88ed8909b81879f75ba7953e11d4c740d7199ae2f5bf9321b858a1a412fbf35bdca0d061b92b91eaf7f87442b2bfb89f49746f373d239d1407a3cfd2efc730be6efde274ec6c1a56f04666a196496393e1c45fc8e4d0101aa1d3944b55630e5a06cf1c0d87e41ad9a654af63aeac63b24e514ad6071e4ae70150ff82ad96fb9d94172736a84c1c9652501e789a16546439dc8daa8b6bb328f63318523ed4ef0cc9e9d22f1d809321c92eef9b1768c894e7a2ac47336b3c7b5e91755cf149ad095f888998de30b089f94e23e8057036ede34a5826a22d631458bbfed52da1211876850c9bdcc15a9fcb31c4f54a8e3624861708c4c2654495af97c8ed6cd42e2bb4d8b8eca261bfc8e3ed9373bf24507b54d37b9cc2c50e697d6e96434d5f998375a577038a52f6e65cdf1da17c057918190ec38530bd320c0cf24b52608ad6ba6ded30adec8a7f29fe73e5fb3be9460b6158b119c3af2cc8e4b8a77b1749f715ea7b9752f57bf8c768d96239283e7ecfb232c6b65a8502ba5687e581fb2079a25b812c197667e5f5dfe55a1d93645ae978f7a3543cee8a1b49723827115692d46e6c326a482bf436f13dd362a19824dc02a5c3edd58d42ce09a25638cb3cc82c0b52c02a3e9915f0f6f93138d6826ce6e82fc33ef5d774b5de121eb40b0c9c8b50def79bc9aa22571eecb1c3c9b7f17e8de82817929acc48cdeb1594f463068018e6271f6fdf29da154b7b06e6f32790dc26e9bf956567d1085fab6cb94b04fe29479ab8706fba8cc3526a64214bbf6a45049d7e4f14734709ee4f646606abcf264799c51a18f9606371228692bd96e775c1d75a044006b1002a82f996a0d59d9e124c838f3178e5d64247056736b685ef655c6d05a9a490e596a8a2f07c31d1ff7bfe42acc004bdb838ebbe80e782f2b814932d3dc55370a2a7754b50f45455a261b4e27236d27971347a395a1eb73c568e240964085704ece9fa0817763860df65903144b098220d9673b09677589cc5d9040b6d0d61e23d89b046a10e4905858713a34ff5c38802ba2de40593f56fa7c94c94b061eb84261aa67b2b5e1120e78d2046edef9575d32c520556f66f5e63f7a27b722ac384d77055e302e472804f03deb4b2f523d4c7ef352cdb3a0322c11fa2b1a1ef2819753f69aca06ecc3d3d3b4fb47a50fa8cff79fa194107ff1a5dcd15d15b6d41eef5748892a6d7393428bb3a0b1f9df8d06e096eb93adf14bdd64c44cb09236aae021ce6ab97014d16f80d5b1038f56cc30dfea65cdcb622ec9996dbd00aa994b7f0f66dccc41bf920769860a0fb9676e9de9c1ad0d77ea86ff7fb20ea03850f79cf61a7f1d9fb8da4bdaf2089026ba8c1a86c628a3afed53a224f8e6631016a2511d6e69f03bfd6ae2a6881bb8c4f8b0dc47edd464bdf3316990b809d875172bdab65f1e5047131709299d0c20c7fb1ebdc310c7006af14ec07f1e3147eebfb01c6618945bb4d89896b4d01ec1e6599b83f49fc6da1e2b64bdd1c0cd8cb3fc50280f1c91c7e22fddaa01f709aa36c809e993399063396b8a7de4a179bd847154bcedfeab1443a3eb0302622a7ff334170dd917e45c8c17063962909efce3342083aad680436a602d678128724f5b3902eca383843ff15b7bd270a1c97d7639f50ade783fdfa40ffddc2ff759e29c38c214cfdc7cab8147ea132355ef9547c816d33e3c6df4c4edb871b0a42cbed5f1ea911e3663cd150698fae3feca591d5e04e69dd62ba1393b47a622721b2ad61f6d86031d5d2c90782f4b75fc1517d2e0469368fd480b0e49499b83f4d5ba6d4c8bd2c65ebabfd8ea4c6356fccee4bb45fc9769fd3b4383382e00c82842e273f01f38a199d715922d4ef2c463228450b09a713380ad469fcb51817f4c217143ff348e687d4a4ef7e5cc25e20dd20fac68bccfb21af5151edd72fc4a5e78a11090e67cd72428740d2dd94749e18a5041dfa3db8a14ccf3971082826b2998c1ed19320cfbea8e6ad29ed830d1885ed51eca376e37e47dec735439430f879e107bae814f5547bfaf38ea58bba57bb5c96e027adc0e5dde5167858f0a9759431783f80668f38f42126ee580fa4b197746e93dee3b64e22c4a025b5fcf07507ef25c53b68da96207b543d9ad93c7041ebc5f3e71f3394c2172eba6d9e481ed3a07e4cdc65a3c6a804174e7cb1d309f7b7125707ed83048aa49670a396ae3d16c346a20d534f8e5d573f48b67b957c8aa101fe26d3ad70ce17c71d6d4bc44c9bfecff88000db5bb3cc71798965dfd899dd3974ceb469b894c9667b2b16eec7bce93282bdb5f3fde85a55f14164fdd7f57e1cf265b10481c10cbe7c6058fe42a754a3b024f7be58a41c39a25e54b6ade466e6724c7f50309518cbb14477d79d6a34dc6bc655af6565acf296aa4f52b02dc792c81d537f6ca056ed77d7134b1c57688e9f0c42e1e56f286b40c1728f1995fb1f7601d90e8af785c4ffb389d118c5e34e7b66882782d7557cbb53a01eea8b73e62f33bbd7009f8d7203ef964de3186130d0b78158e6e284a8e074fd4f9748c4c689406e7416f8f5a9107552ee1c2321aae286e7dcd26562bb5357cf2432501075af989dead5a520a10e4a12d19eb6ae84b02076eec3bbf14a67e494e88bd1970e8bfa64486c61a4c7ac3330b0321a2948bd088850cb0a74963060f048119f171efc0e5aa5dd4cce94e651702de9e82b49da578cfc3c0339f31840dc538d7c7d6ce254cceda2f07e71cba71debe72dea0c412cabc7fb2e748e0113ca52b4bceddee84cabc021d789961deb9b292ce53b178fcecebf0bb960f2e423ee3d9c4375cc955bf3d6290a0b9d1b8359c2e5e807e6a894e090ba8a4aad017e5a0a67926e39b41ccb246ee1d59dd25645ec4c1b12318c00a4b5dbee30b76b7f54fc80fce5c3c88599096fe2ef6a50fa49fd96dda76bc068f119dcee54987e75002a21e987ae2ea8b4eb06e213d237537ea429a87b4a2c58f92c9038dc5f65da661d0cc0ca5555a784c8aad7e365f9f97e79563434843a6543444840e31fb3cd34e7017c910440661bc81ad0ef10b9d8c1e1701f891dc11d3146c188525680e990f7c902e36508d3c7491bf476bdc1480fb0fa984e0b5a31c6c861c82e01feb40c8ddc1cb54a0d2c6b35241b5410dbdea79b2b9cb103ebd9135dc9cd93619291bae9350038f2deba387c42995fad10bcd1510b3c0544187635e95a10bd75caab5c3e351ecb31a51a69a1afeba62ea5abd5575f6a05f9490e53f2db65e53108771ff5d9accba1634d84dd9ff34821c11b7d8d93a4fc744e854043280a9223b6dae6088ae33b5dde70373d8010653e71962a70ddee07c74bf948c3d33a5a17061869a6c77dbcd698a7a842dab3149c477f409da42bab03aa9897b0f4f0624c9419d506f7dd0e7ced0426c92e97b3e0b02d032a39d5a870f2ed7ad735979b7108578d262462fb0911cbc8854c26296ee524d6f85e00da929541e782f947dc4131994ac306cd0911cddedcdcdedb117e0bcaa06cbaa4a736ae0555bbbb3e28df8f60f7be47775eb14e994be878a441ff892a3bcbb01dc258f6b6e7b86b153a12e4ba616f3ec16353597277c04a40db87e87e4330a975cbf932b97639e4d51b7da1bb5c50d45f9f0f0aa701258598af19a07287faaa7c7989382c6f6726cd67c526e74a0c72558e82af227634e103718d7a42cb17b38595301fdd967eb9429968f98bdad12760e66304cc2858562f32d56e587bcf88d26bd591c742d6a56a313816e90b42f1dc5747f58cd54912004f6ac59741af86a959532698e812112c49024e9fe6434a0455306352a3b5b8d81262e5fb869e0caa08d63061100fb1318921c6a56c4ff61281d86565cc5ac63edecd11803aad4abbd72cf2839938315ea38bd8ad52066880a8a5a08717162a260ba7596ffad46d82839a24c802e21b19e54bc745410963ef69bb2bcdf4a0003ae3c4094de23027da195efe49295430551e41d5688657e00c0a8bb9c18d86e04c675729a208ece20e2a5b87a189b0d5b5a19e93cb3d62de6dc6ba5b1246fd01bb4353a629759439d54ce1b2342049526f144dbfdbbc36bd00078335cd760c94546845485eb26e22fb100b7980b5813d505813d5128cc9ba18609db23dd639680447e98d773e5be0e0c13e9a589319702886bb2a50751cd0daf5028dd76dd14d02975c53b002f4c636187b0d470df5b23d1d5c057cd189b076842fd2c1a564effc64a964ae575f39a4a609e210c8be4e92f8ae2348810fd1a04dabc0236e3543501a83afff2d6919b5ce4067b330142294e329ca41236212dd2ff32e3808a998c057ef4210ce5114606b6cae62b9ceaeb2e00cd144ad62a46698e9352af64c0d4b83412bd49124928fb4b10bdb6e47852eab0cb23874bd12b75bf249a3f4e56605d1ef864cde00d30cac4e77c181e774ff252055d093bfe9ba713b13a26a201bdc4301de32a7a6436f77e577c22f51d28aff816f55e01f9de51421e79a19dd4c720e20d0ace259df63a4d96334c44522648f6e2b849f779bae0a7d320583a0935d498e68c249d589538d10915522a18e34550f77b6c3d65735a8b5ae86417d244e8193ae674562f6e0553278a0d0f472da5967b5ba50fbfae0ae8cda87c985b6667b5f2e77816996120975752dfbc6c2e24cc19f6f42dc6ad0551fe1c8d08068349c9d2af3931312baadcfaaa3c1d6c9e47201579654f62534e89b3f180d1f220a5ae2a16fa652359b71bc7831e4397506c37605c4426ebe5174992129080225468d863937912146808b613865702027697ad00bb0ba3519a3812790412bc8e36a0386f060dc4d76838015dc25c5fe0c080bed2ac646cddf0e952e261c4ddc269153b72b1728b52d82a75e81882e0545e2a52110d7b729595a888d9454569a4b5998b4b90f4b943d583ce73d6372c1bc109943c4fe05b7e3851acea9873f66d523e64365685cebdece42b39241ff0209e87121342282f300d4b6cdc8e8c3792642ca5e7bdd2616d8ffd4849eee9942bf916dd1d2fbabf3a8882443d7e87b2ac9d1f339daeb22831381d7ed942ea4b96e154ebeb1e2dfbe6d19b0d409196d13d7b894202cc539de8fc04835e946be4c4ddb9151e6bc295d4a10ac31afb4b9b2d1568821d79ad67383447b748b22840f5a9b2e111ff3d0ace8c9c374df49597a91966eecc5277caf3e0bb6774cd9f8da94951e871658d005316f22267c2481a2f343bd9209643c9688358bf749bdd3bffd6a3278a6469b28123568819d7c532852aa9e56bae2e7e32e1c5342561b1ccfaf6db1c797c346ba4e1cd53d29257e607f7400654d7f6e3c3358c05e0d6883f8f8d00b17cf120c36cd04cc27a1962c40485e365051b1d01cf21a5d46754888c57a52227547b1f326a2df4652712af31945c55473b5f19187a70ce2b6adc1be7cd2c0d0f5fa4c140aa505703f953c627b48ccde9840a46b2e8745646d426a7dfa20224e20068390b3abe4ee39acb6a6ab3886f86a6a064fdbe099dc7d0fd8c4de747617e480bad5865d720c81a3c9f31927bf8d1903c0c0c8cfb7f18db19b255ce4a5a328e1cf9a480d8255e42931d6c7da4825c8852750851493ce541d8cf518bea08a679d2b0a6edb38c51500c880b4118744983e3d96b02b8bb3012d372d557d43b7f7f3a135c0171c750f1116c0f62d988d79ace63b489b654eafa2b459b2898d89b4a535723182265ea2f23cedc1de0ab6bd3b5abca379a1e48da48cf232a50b4e16cdfaacee9fd8d47a5cac0e043f5c8738f0b4d9c10bd556222be15b9a8707ebd1c0fe5806015c9e2d103532fb71cfb8038b3a1aef3304d297ce36aa6c9d46525da6a37e95b64cbaceb57b95cfdceefe4a8877fc761d907152b68cd2c916510040d5cea0278642355a00bd0f27da4fe105610ddb72a408565db5261d2e50e76aad6d95fa7baae2038a43305a2bb54250144678a34a38aed40a2663c17e0d9ddab0f50487e51ace7d9a1fc215daf67a52c5554dedbda7c6fc4318e79b163fc3d1e409206115f67d69dd0251980ef373512621077ee73a3850a5ef58c828e249fdd93ff043c0424c0bf7e898a46382b9856aa89c8e44b10542d659ad030b0021087a5afeeba5e1de85ed536f2b54ba8ece3da03c0b2c655c9e65821aae91b58f0351ca9b0655d623714e692f5f745d6394cd460f6d0a1e0046d60c1b5a8fee02df72c2454327ea0e0b2084e0c17ed6db9642868735739dbc928d0768f9b14af09712b191dea92190ff61fe3c07129ffb175207b758c6b91178b1ac35bd41ac1dd585d2c6a9d2e202ceb2275e40edb6c553a1f68d7b645d8393e3ab347c786a084dd22f78871130d7f33b9fda671b79de6bf51fcf22fcdf6d7971e6da1e00bce1c821246fb92b930ebe7a6e849bda0768f06d8a0a882097f2f6348fe82e2b9ad27a0ca0090a2e51021ee4027b0c5e2928a379d8a36cd714f7290021b2fcd61cc54f1c926c609419a9d204cb66dc88e30653a207ca8b74595cc82f2f7d8eb68d74c6c158702ed1a6c24624cb3f897da21bb0fd482940c6bc560829282ff6977a891b62d346e6400a8b543b282ff6925534456f4850016199247914de8d54ca1ce890fa76232d96ce25d1f4b197a2f4c5e3ea56a3e153090906bb14df533165fffcedd97e5bb7939a59676cc4cce831e90b0c7bbb55f928f85da162e67bb587de32f0d6a429acb5a3fdd9cacacc9f7171399c10b321e8f8a60927f23e67608ada6cf725ff674c710e44e709fc1bc530ef7d0569fb12cfdd87d7f1334cfacf83497635ae0dd3781d92a51a849af6b47d85666c0072d9241d0c24833e3ad18806f0c6e2712e0cb06c00dca151ce9792493ed453760629790066245f17df01203158a60dda52ab8da1e21bce43263d7b9d25ce2c288b3a8224d93396e6aa77a9b4ca2d9aab28d838b45a63cb74ef7e0e8e9e4a0e645ec30998091c06183f24d132262f03a4aba7092669816089a5796368153748264b4374db1b410381bebde8376c723b39abd0a14779082f9ec5df5466aec92a14a61a9928487959399cb2409d6027425fa6fedc10898ae935794ec4d44681f1c730e4077f2afe59232cb0b28eefb4d9c861a105c9560b8b7182ac417acff345fcc76c3d50e5e5ebb25dd2c2ca625ba03fc33ee6790ee9bebe35f7306d23abe12439e24a6795104530db7ea958b389c1928be48f4b03d4c8532f604929f188dbe22afe853e75a7903b426346682b068946fda9a58d4adb2d1cd0909ba234bdc15d9020cb9f88102debfbb2596e2773e797d55404f00ac75d9ede4ef675a375cc8bc33a9702d65871417fd43dcfd561ab01d693579b6f3f208a549d19c49e44d5dab2df0fc45931e77ce8dc6e126636cc232c1ccaddf7a845545bf8ed59ace5f3089a942a9e89a9dd030c65243307552869e1a48ba76ca839beab4c22d93bb6c05f86e924678080e12619244e0ed92ae67fb14ace537a3165911655d5424279e241567da10bb6ca592a6c0a69fdf526672db1f2c5c282f070c88e756a52fec1919d870e9c815c8ef408f53f32bf7aa57510f10e6726bb3caa3afaa182456b27bf8de5180819f1b85e78a779e0ab21e5f5f71a01ed4a4f06e26d3f34c8506087b3d440bbec263bb4f53838b3c248c4eacc8a580c13aafae462372c3803cc876411c36f0a7c5d3f267ae0d40ea9730a5b229d7f19338360a860bf2aa0a10d1dc339b7926ad0ebd417ed18778f86a4b87b5c508a965e27031c34bf1308ce8c5da7ec95c1271a04671e614804b98c06a894e6276a2104c7b2bb9284c9e1fceac0f46f87ae3e8119d5aec66c488538875ad46174ce321feb30b535b784fb56eb544ac0b98687dcd2e2bf6ea176ea739ace974b33e094df00c3d3e1cc3ff362126587372e465c84b306035438cbe4477ca1a3f64c136771582b0f9cf1036a8d74ec05d13c0116ac6ac812ce62d1000566c29b5cc27604c06beb627b5b3863907fb3837a05d369015270c6d77f267703908031c381f3488fd5c1536b9700f12b5b38337615a14ecf12062f7b3db6cef65d7c3843baafd34843b33c88a81d911bf3ce5af0703602c2e3e81c0e7992938b0bf32292e05c375e9a94b27cf911f1c3c2f609e02a825cd90ecee3072960236e725b8c578d18f4187d3823c2f20b52b706a002012a3ffa659c7016dc7d3722239c5fd42f68bcdb6e76882a03ce723e51b9e6f9a20b8d80b23e81c4fb3bb414443240df343f810a926587f30bfc339e6c4162cdc0d18556090a980109ce2c161bb6a1ccf100ad2b7cc80c863398f29bf35ec6a076d2566f7db5b5220c12488cbae92c1a111d5a827064946c9802cee4b5dadd52b22330381bbeecd1bf1e7b9d9607ea6097b0e2186b3f31f002e77a4be87b4b106c39a3f5f5b5d409a743fcb31d49c1d7b2006708da91f7ae2cc5b540850297292fe9384e02e7d78633284c01ce7e1ea1856d2da70e86dbc7a8b594c179a4934600e04209ceac2b2841b812d579de4b7d94be42c955952ec775383f9c6b8a00c7a647eabd706736c20a1acea96f3819d2dc17819d0d6781ee392db817d170757c918171c164c0f9813fa22d04e709d5984d6362052238fb3d6938773964da66109317d88aa6380a2b7fd63d321213e16c1d3fb611c22454429a758075aed1bd0062712ec6b36c0313ba1b360fbd4708441e94347b0ee01c611b9cd7847270677e6320bbe08801b098724ec267119403abf579bc05cf19e99f6ac737354fe7eef3883c9b5cae130eff0a351ec5f85190f2d6f5dd079eeb411539ff22e7cb1092c63d4b4844076273a1921464d8c66084a62a3d7a60d8b76e2593bc485196b8e0c7507d0a3449b9ca92b8dc321110294ddc82a47e296e2c432c4cade6192affcd41219dd6af25d33c9f400e25cd8da7da941b23e4484dc02fa07aa9c642c139f81dec81b72a346b5d6e594805426adb5f54d77d2ed7bf7806240ca92b6fc0f7db05ec22cec12fc107be7aa00b0b72a202d772b49e6d8682ea5827189476e37de8e050ba9a8215f53fb0fe9d4b51c024738606d1c6c196be9a8ddfa2cfd8ba6b1a199515ec0321e24859830faadbae219376d4bc5ffa26f2e1abb01a31fc20a2d56a14e4849aa5b5087639a6f2c99894b0ead992750f0f0818ff5443ffe864fd53cac4c99cc6697283e6ba4d6dd005954c60973f218c8a0b9bc5f6e8d24b29d8c39491884c61815416cade9076cf74b43918e46bb5aab5780280feb1c0efb2dfdc636421324b5ca841464eaf0061fb17908a70e0adda28e76ab4b7000202a49bb55ae335161e8359797204c7a7e2967413bd2fe017ec01bc4670df1de238678a7fde2b67018102962a7c0e8cf3fb0e924b3ded000537e7ff56f7e4502025703603752301381e3ccf9e7b5cf66eb8d71c9956f5df0292a2a689527ff51d67ebacb54d00540d35d56e3e5ebfc73cd6daf8a55b79a771bbbdf9037b4c3dfc16bc5c8c33ff548b3d019c0bb7e9a31d07160453d2fd5dfcde47072eb4be0cebd0036c14439f28547aee38c61cadec777499eebeeb481e0596a0fc54d39b7b069f7dc132002b458d3ccdac05243590a90b94fadee65580ea3ce900239d1e7ca3b316734d395017225542998f783449b9eba167a60044588e8ffff7eb7048d7c97ac701917f7ea156356d1e8a62172b40e9d23af9cbc14e4d066701bd8d166f3f3090a4fdd568c5941097ffdda1a7346000498d85447c5914578d6a35d8c1cf0b4414907a798d608db14c5c9790b23c7de588472990de1504972b2e7504352aaa9cc95809519a3274947f9250d5f483d9fbe4270998949d70845822bff187da1c2ef06bf58ed8cd464d1b61a4d2c6d2a21dad53b8299d22456db46301a0f31d3a6d25c815e76ae708f50edc615f1a8cdf7cabb65bdd11d4ffb035afbaeab5e846c9b29903bec53cc491d3c34c20bca34f02910df894180b1fe88b2829b6fc77b842b5e18a521834858b36917e892c80ea622078e71cbc88fd2f4a9f3e2a9c616b1da6791cea20a119785c79c24519af6d349966426c493f0535538689fd4c96008006fe581007fd04063ad3209410e538bc4afd804a6a322cd6217fb1876ecb37e28964f01f15bbe300cc25b085130a3c14da6c8778d07ab8fe0673d0d934d82316dc492b50a21a28600e490e4951e8352ad795e5a115e5e50a0cd0757e69796707558226971101bdb6d1fac961fabe8dbe68d77d1127017a9a6c31b61c2e2ca165087d65882ed3c851186841c012c69bfea93f2006cd82d4e77246224ddf2828fa496284d2bae5b844bd6f517220668bf5219102d32c7b7912ec7d41c4fadf1280219122ac7210a4b44d89f2605463554242f18265599adeb2665c14792c43fed804dbdd34caaa1214752ce8acd0e96aa53ad523151a76d07036aa61a0e86b7c7546067c6e3cf565ee7332acb1c7b0cf677133ad795008fea3d8ad0151cc782140d1cf43614d7e09ab287271f31f13267dd65f38543475e5b20b467463068ca2eb0e7073d8d7da450e2bc401f7e376743f23e2bfdb089415e111457738bf0c06c5deea9a26ad6f53ccf3acbb208a715fb76a0df68467248ee2856d90f846bad3dda49fe0a7ea05359a4b025e6f825f1ec1e4ef18a626cb299c28cf3e0a6e3a907752d3c29a1b1fe1ccc6206292b13699d56d14a0063715e86cd4de5560fe03d9cec888e3f281c3556e8bcff5bdaa4d1d0fd7dca742c5e0f00017a45cd6cd8d6c3ac337372a6841215639a791d5003945aebe9d42d0ad8a96f934097dfd0bf1c7ffe2894a4ab81c4b3c963273c67f3dfab76ad437f483f333b04f28c99b2f3f2766e11bcd3a63f4e64091f16672a0a9c0b0035a50f578640753e4455ec323a19b6790c7a4556fe3db29f45e53ffb6d017216a28f79d2f94a03616038b53a875605a15298016a2e403103eaace529108d2bdf392c3a9858dca6b93cdc62b13e5d2f3c3620ed530963a9d80caeb12a99ac2ca0c97100aa2376d16434412064d32217e409a58e52b2dc0dd8c25a993f4056bfefb3f1dc6be520f0d1bd70330d0a58cbbe38b51e80849c01b90c0008c1dda0cee27c5ae1f83d39af9e1275048032cf30c946164c4993f2453ba09c35f3fa5d8b35501b9968732d80d71edb0e18b2eddfae4544cd27c583868ac1fae11f7e9b9281b402e556f379f2868ca731d461113a23f44b00f82d5e16f192775c5aab0ba43056e1c7bbf0abd588435b3465429d627b11be2551f38aeacf3e7ef9b847b524356e27f26d72c44c54832e6c9dc606892e19f1e72a2b7c7f3c3ceff691fccda7b643d7fc5bc9b5c99aa094eb3ad5f310db88c17ce6db2d9e997b4dccea1d77cb8d04121da4b3ac551d5309608fc4cf0f8f08f6578031f02e3af1d4c7610d6bf455ae274c4c390872625c80737bbd088da042c5597fb7b607ba69eaf95f69861451e266bf50ae1b01f104f10746e41de989b848e3c4c7b57f33547c81f959f9110bd220fadeeccd81fe3086399a29c7975999f8e7cf8cc8391731f6bac0019f23026e7fc6883753d8fcd8c89a4e9b5997845201e82e359220779b8e3d9852663812ccc74aff5c951a9351c8e10faddc4b0a8724aeedfafe1a26383c35808c169d408d59a4de4a1f77bfed094c288c00d0a9698fce3d71882188c558d83198023c013622f90a0873a4d7b58f6f7ecac156f75bc691c9dd813e792da9cc0d8aec7fefaf7ab0a6f4db8dc5003c828aa5638ed2ca274d79715853b7eca4311fd8a7c0b208d7721d5969d7cb86029ced34a42664bc8f602934a93faa19fa51f4eae180fcb0899bf558c867150472d474f56bb777b294eedfc0e0b4a65967961c142630d3ea6c534f78ca6f5f01467af8b50166f48d29c485ce83e98114ad67fa6aa96d06472418e09ddd69c26b42c7bce7d600cab8eb299eda2343e66ac5ee73ce337c778a2cd178d062e60aa739ea87fa3c362fe468dbcedbfb6650923e4b6a24d49e9ef9706b3be8df2683409a5af2181b2db0683e690ce46c6ee8887878ed778ed56e16a4e71bbaeddf42dd2839f37702020412982030340f363083844442a01bd21059e872071938e78f5d522ddd96e73ecc68ea6c1238aed0809aa7daa19021966c44568a14f326a12b4f7df1ed33285b6160aa1fe9f8b093e169622a3ab8fad0bcba02cb31f8dfcc53b1cd168d5d480a6c22a8f52b61843390860d7ddb36f25aa8e89618f5e19ac7cac8d637c9168543e2b7378d0e2b141cec8b5e5c90b575c5c82abdc4420dd5996809f30ef87bb4c5498fa9fb5a8ce1db703a67d8196a6ba9ae9bc78d3761ff0913241d2037ab38f3efb482da658ac3ec26b6604091ddf8e160859a0cbe805ea34079b56203977d5a967c9b9b60eeac148a8617c05f69c5bac12d182e51b85a589c128afcb13f4cdb46b07b4240c129fc7bccd898c820a0aa75a5957aa2d5ca910621f8a902fefeb80783d923e7c9f4662eb3a995be13023ea696343cf5ff8e7d300c15b6cd3f499d1b5f77377c1b1c0ed4c3fc0b43c3127732712158792696b650927b8385f90cd1bb4f2dc78c0bf3932969921a544cdc4ca551e19f22b94ac8872ca9101833c9b94a8899d7221191dbb566d1871d24d5e976cc0cc93287ac98081a95702263bbc3cbd7298cc4007dd95c664b53c327aa14a361881c5f9a0e484ccbd53be965c87b1e25491479f5cfd9be177fbb93956aed825c5ce19ec12ca115513f82a57679f71701c3e4db4a283ab73dc5e7cd9e8375f46bf874fa2ff512cd198047ac7b4158805d71ca8219e71f5e5c7361178075457775296134489fadfcd9163166a772a44f21cc2679d0dfc2156897199fc42a18363588f3d62c1560747cc49b7c854d73f68c1c0d43669d447fc714aa9d470a0cbc8d1d6e58e37004a84a7f442b51f85345ff04c76ba007988d2e92c00e97695a7b46c7ea15a6422654c76048169a8263587a8e72d356c3290247383c343e1217687d054273d4492d687488cfb10112044c4304f31dbbf33d2a27ee0ef2710694b67d57b5d006b176ead0719301e3584e648220b9e432406cfc02323adc71d70d321b712b500be0c4ddf535e94f4bac8f83c990b25d2fa1a487a138ec75915e2f4c81f1976aec5e1160e6847caaa66d8af7657214fe1b006b01b2a35351c51c9bb23babd4edb5ad32b53f480144d003025d5445daea67300e277f90e7808cb23b2c31c7e7eb419f8db18a5150d21001172a8c9010e2b427d54afc25600a0f6d45c9fa338c95c82244a294d0bf06964cf24d4003b92047a1abc5b121254584695ddc77c9ce4328c2664aefa30e8fab3da99582791dcab10d89cc5a5548a769d4410f900f19e3e3e0cd5659d04ebf36bac490f224ca87caaf460627512611aa9e64b08f15247050d70fb232c760ab158f11f30759db2d6e4b759d552031850379c910c887c84ddf87c0f398ccf4ac976fb3672fbd164d08339680cc25886a4f33d7e3ad914749a7f5caf1d68fdcbfc781836ad026aca9a685428cc0dccca4ac8adfd2360514922df078021601758f768bf43ba112abc9b92abe7151262762bba94375593d49e0430fc9a375fe1463601e92b71557f8b4aaa6d5afd0f2d6ef33bce09d024f102132516da8a24b1e55d807c0d7851acfa3e86e1592965ff008ead66e9abc4daf2d8bf716eead26cd9c702ddef9f029fea69050927c2f8bd1c858c129d55a3445d3211f5ea109b471701eca9eed414ccc24646093ed4c79c14eeaf92d379580792f8bec10cfd6cb7399af3c8c1b70547b2d8f683ce22dbd12ee7b341f6617f57b5a27137636c5ddf87b2cdaef8def6c5e5a43f1c1800640092dcb7f596c38ad0cfe6e8b05b2de85fbd44b78194918f02a8948d4157e3f1ee2db2fb16758ede76ca21b389b52827e083566338a044a482396af9fb246b5cec366ef1a7ab79418ea5003b4b29ac855035dc62827238a93e6b7088bf164f340673e2e58580123821c03e222c07bd48698994b6f1a9fd895b002848824100c96378d38d2f2bfcd12dde0eeac52b92594e7448f1652ef060a98e38222aaf8c8fa3d9f642b5afea67eb909a5399d8596bb20cd6f90662ba1b4a45e851503e5029d34945355b64448835818b70927b0016265c98699a13fdcc37c896ad1b480b8c9d3b3014d55c71d24b4669eb1a5c94736e6c25df42963641c86e0c0a93bacf2aaede10beb878025773512e83c46a12eceb5c6f223b32cf258af6006d427b8ddf94670f4d63ecb472912fcc138db5bc09449fb63b17f8c1a31bdb5a61f5dfcade59b6640b98b795b267c1a8caa5cf2259ae2d5cd315adf1062f62afc82d00f02868527409aa6379b42bc5f0065e13946481e9a4584b7fb66a48e8fdc94f27de0db7440229300ae09498c042082ef00e18bb76fc231f0c222e42d48c651b5d3ff1885812a2ad91bfbd5529cbd142d3b88299d9cd0ffff937345fa09ae72aa05bf2fb886c222cc208d8cc40577ea0e2c0bab1a2a61a95320207409fbb861ab6b496272b215f91f37fdda6fefd239e832eaabb62cb159435f8d6a828cb897798a4daa83aa6671ca829435ea44fd97183121e4d320895c915dfb0a7522ca9e51bfd33b7da46b38265d4cada0ac099256ed274683bfc77e8b7dddb6a3623a5520c48722f428c25b280f2bf95e751788cc543400c23ffb57b9c8427cfde2a6fd74f103f85632ec423784900a98071e8058f352bae0bdd1303aa10fd2ae380a2525c45d630cb3ed0cd8bbf5effdc15ce82c9c41154483a272b4f92af26c50831717b0918eafb780a6bee1018d265e71b6f7f54f537db82af09c411d4ba81208a314718a80ad6bbe317fb0c137d3984075250076245449275cca1cc85aa5452668194ce6ed7476951d7e44bfc85c34d4e3ee621320b1a3262cf6d538f3b960722186b08f5c863aaa5f1735a2900a0cdfd4afb63c89a8784cb0313e1e450eafe46c4b15ae41af28ca3ecf31edf5cea9912bf58caac2f75a6358cc78ea3849cf2a645e8c2e4a138c5ebf7cb7aa3bbb345b0adbc9542da440f7d1b8a8b73d22976b52266526ddd4d88d05bdb2b1d96d4f27ad073b83d34e022fd6f432ffef38fc2f4bf87b7cb44557c28ac6a215c8933116fce96b74c16621d6c32cd3028adce70ae3d65448f4a9d76273630be06b77fe17f2be84794a3ae239d51636124b47c01d2004a06ac1cb4bf9b43a2be93bafaddbe6803ae577f84685f5f72b0f7cb26ecb8f92bb1f00986fffc379dbee5445bca05428209449f42a8ee963f07e5181da1de67de91ccc054ab19c1fc19841598f8e717000209e22ad61971ff4638f143097072f7a613cadf014f48a69364dd157f8af52be745443daa6464b26740a7cd06bb0935249ec2e56d2458f685bc4d57e78e9d0b5860889e139256b8de77d9e5052a42c495dd2d6699839bfed9904b15b2679cbcadf52563d8bdb3c8dd861905b996e01f05d03f871468fdb8a821e6f33060e1068e42cbff00e954f7f4e5dce616859a0ac42847a0813c077036f33f68978b3333d9c4372109e541bf35b2234c13666868d4dee38d9c38cd1879ff0b4721aa0c6a532e3889a4424666f0b21d0d904d3043e00be6a9f47318969c685fb018ed650c131a1a02d52cacba130e11dd44ca14ba74502e35d57b0a3cf536058be82c0c5aa33217041c51ffd0da0c112278418da1542b4405d7c203add0f38af48f2001abda7edcf9d69da6b1c00f97c511027695f9715d8777a0595ee03dd1f51291125712998730bc70c79826ece3c6292a0853506a014a8a479cc6edf94fd8ca177dc2e72e81eabd3fa98dc6a979842d829e66fe2483e6ff83ccefec70809b5ef6fa65b4ee1fca10d0a2564a34ee13ac7bf0c6e806a2def00f8141351d4d16d0d20b617608bdf482eb03e311de80d7daa5641eac5734eb4d380410d4df118d723c2f1709b3fb40029897c01b9aa84bc2f1dc624658dfee2b943f3fd11985ada6e0c928ab133f96370d93fbe32422ef7a9833b2d7679bb77a3c1939c618050f42efae4469b84b2b640282b7e6102668ea8f45962e838eca65bae2d1424beaa1a3f7d25504e44d26a8eeb2727a8a3f2446eba5e959a6fe239e247c2fc1a483cf887b10e8f4111914e9ffa870aeaec6b365bda9ec1a940172597e06d76fe90d569598fa91a62f838c655d2b127df93ae5f608927e40ea2ba27b811c12793f913ff1d4e3e6315d89929e422471b85cb8104fa1ffd841a05fda8c22f5a3d939ba38ceaaaf8f928891c656872a9c368af98e54078a98a566afeb6797846094175aba4e94d4d25c125e170947b6a00e6a7cd3b19befb5b37f44c24ce1eba1a752d081cb7a075c1c209f67b0bd128b2acd01eab3405d9a4f521ef73054c223e78434a983b15667826072d8b5066e100ff97e3b3049d4200f7d441f5f46d7163b265d12b07454a6e0d355a56a2e1d0d955fe836b8880412faf0c67c8466149a6a96379063391d3bca243bba20e454edae457c4765fd48b8a69f4beab27775ce7d20ee41952ae30e5b50a298d9ee97008c29b4cd05ce8c80b612b308fcb61a906d9770c79c4d872bafbc232eb80768797a0ecb030640423335f9053280f80b28009aca90468bc9a8b307b094abff2a7af19afe78335088e4520a034a9a0e889ba977ba66b0ce19a3104df54e5b6fc450e8a15f3360006fac25dcdb355255e6b71c2a0b91bed1757827f2d590997a6d38a4e0fd87468fe0e3d6c4e063014f72585918f5a5db9a3c6869b3485d13da4067a1713b40d4786d109b112886ba469c2fe8685a660b52229ec38128b4e65ec273fc8bc2ea16d494753d82a3bebb75401dbd0e5e5ddc2ab342e791708e8fd1360bfe3bd395423db6f66dbc1850ea372a30e2662a2831b30b92cfc600023aa337e605318ad40da3d47b887ed00afeeae0782d8e7b07fbadeab6d4af43a57e59cf91bd4140ed01391b17e43caca98438028c7a64e0ac48fda0651322921a5d4c9269041743421e1414a1ae50b6d384e3f1fea7ae4f6d8ed0f353342b5217f31735f7b65567750ff481fa69fe1133ac284ff886ac6c2eceaab3c869ca31c79ce9835e035f863fd10ed0797b9a68546a563d113b8df3d4b6340fc0f395529c1b37a5c197796d8b2271e3bbf416206d775491d815eb136048c059871664961ce6a06a8f1ec35e59772eb29b793728cd89cfaa80c1261de61e8187a1fe1c6de0eb4a770f1cbcb47f04110d8b3247fbd9d12cf35629c3e2e83213503dca790e208df97bc4493c9a53430420c1f98193323462a254f1d9e88fbb27fb01174a852abe2e01076d0184ef39b622a9fbb91a65383b98f3ab87c24529cad098ad2d7e639112d0276244d6ed53059e8ee7145006381f6c6a8e268ae6476dad419944954f066a0e6c8aabca916f23e763f3f44dec4e865b215535d0282af4845ec6d60a46cd020b1d8d43dab4f22df5a672a960dae07041b3b9f032b3dffc82429041b02af5667275b1692d149e148308a5734e953663a538063f727b3626e1c8d9f4729a136398b0c5466e5e45cde21ba4797646fe21c9a193fd0a6aa99be6dbd70c4db72a87e221f2e39a371c6ba2867d49a4ecc378ecb5d0f97786aaccf7bc19005d4d2dac005af4b8a4efcdc082a13a1a3c304e6ea037033a1480d5c5b084c6c16ab027e69b0102a07b881cd59d581d0bfdd5747cf0f0f7cd80a3727b914aef76c5a295371660a9364075cc9b81a8c9612eef9b8134eb43135cddf49f64300785455f09b84bbdead443fb36031407995c7a63b3e5c8c1d9a4452a15ac0b2aa8601865430b8934582ea9518769cc360d5252605da2460db3315bda48a48171490d354ce36c69919602cb81af1c4c13b03c13d324a09b27ce804dd64c94942f6162680c33493384485a9229c565c741f2979f3f5bf6e8bfdb4bfeeae780658d9bf44fe1358f00648d710cbe57e90a797bbef8e54f20ea129732bf56fa6a70ddd2675a61ad7c0366030ca0b6cac8c5294db440a7889b0460e2926f767420928d66ab91c79e1180961a0200d054ebcf7a0db149a24b5e02553cebcb9e981f3ac36a8c27e42144227d5aff51732bacbffee934d4e7e6147d7981a7265bbd0afeccbff55f09ecef54e9441a42cc71ccaf75bccc603e4ba4933789944a0c0b6881a8402d9b4dc09a7845725050e4948275d44b4e0db11bc1d32d801467b2950d245cbf205b6705eab896bf46f73088239daacf1af522545a8ee8c74c9465eb40cbf911f7552dd5fe9c8c02024e7c19a6f2d43fdd2d80f10046e1048f44cf8489d35ea43da39ee14159b9f2299c646a71fb1b74647a12f70a70315879773ea862129cfff0e1ce8dc3be5940600aa8c002f615a428a9014bd78ff80f887f39feebe0ea3b26feed69867f772efe396f1321774f1ccedd4c3ac5c0f6cd9a5acdf71922574ae3fd9fba59934d8581f705ea8fe25c34c0c0220a929f66f9d4b526cc4a827b5385cfca23f088b88c230519de11656fdc63b22c391034a296c6c06c2e9391d12114cb0528de0c6df8e2a0044ff035c24ae27cea02fb2f0904713bdcefc0998c069919f3ac1869661e54b3b35b418d91a4db21ce31d2e6e8cab63b642b2252464f4ba9a3979ed651833e8c052e25efcb0d722e3bf8c30268d21ff604f440672136a8214fb7d5c9db4ca2f69b6dd8e3e79e700517d56bac75cea716f08742b180865364a5f953d8b10d86e865f545a200fa2c42e143b2a6bf4eaef1314bb373130a5284f8dd6119570299bd035f92ece5e097041d9701065e995fde364e1c134c212553d795853bfeeeaa5c9ee0b9eca1a4ca7469dc497e39ba3a41c1650b93cba04842ff95041aad826db330387bce64691b0807ed0ebaf1367004986ded71d0fd4193725142b2a9806363713f6b5e52a04f55e3dc4676b83f08fedaeecb32d3a8c214b549ed2c03c36c0b81f7c8183f7f9bdbd768841b7efe02e929f71c7f94e8d47abe6f37800cc36cb3fb6acf8d5bc37b9ee579ed18e3c041f647a77b370e994909a40d046a361fa65920923a4a8b01a9f14edf7f4ee0356cbc57aef3163142b01a7ec74563d1785d2c9ddd6905be5ffedc1f52f5ea7d43b550850250042082a87c98010e72501f4fc185ef7e6fb0fddf3e7451fde8bfe8db6e84882422894476f70e450ad909cd09a7fb79bfb1b06927c2760bdb89b0222b6cfb1f79ed37ad87d60159fa06fcd063538bd04128c2e7edf81d113aaa83c80d4334aa91ddcb6607734fbf1c678a6072e8f8f6059fd2ed0bddb68c7f6fa6f1366ac110b353a22f92d91f91846167f99b7bf336baeda3970864bb9d198a7a7ac8b3d17bf7ccd2e84f6eef11cc8e47e9539a3d8b5946f590f7eed9b32e7ed3aaeef4d8e966adcd317abc596ce9e397cf0645334b6944e92f56b1f40bd5f1cb17cff3e8b6452f1b99216cb7cd0b0db365f498f76dc3ce6d56cb9dc558053f520febf8c50b8eafc99ccc393eb30e9ce186fbb475f11463a74f5fe84724b76f745b3df44844fb49ab6cfcd2fd8b5536d69b0cfc11511d3947a6a61cab6cec19f6e5cb970a66a3dcb67d760f3811c5b42c7ec1b2460830fb1bbe8298f2a4cbded9f0f504ca0ec209104b9436b7e39f6cda02a45dc2862f21b66c219e3c29b385a0b2eff6be546bb2fb0cfbe8e973ce392709544cec3a21a84f0cce25ae03c23aa0a8e94d3e1dcbde6f46f1cc1ff026a5c201e110fae071d905b9fa4b45fd7dea6fb531fd8da0dd7bef90843beed5feb8430f69622290fba85dfec342f88e10e8120ffd8de00504fdadb6c0d1dfb3c078300cd3181631ed2919ff5d6bd58e6767c11e773c6e3a9c367f8e0f99c78e61d9c5309c7bd951f1d87cccaebf1142d0df8a87fe0e825655a9b17b515ef5e168a2a93fba497dba16670e1b538755da46ec272fcbea13ad627b47865bc3300cd31f356a618f337e451b7bd4d4ccfebc13c921d461d858a6747bcf4ec34420f31925b33f2f7e72a33e3fbab43f2fbbf77bfdd1a5ed5dfb8e4ebe39c5dfc7693591dc570f614769c8835d638d354ad1b363fd76b07bf1d8519f39e64fd3976e2d63d877a0bc87e984a07eefe5f99f79934f4f659aebc8d95123ec2f4659ed2f46e97294093f9be2f97876c5ff46d81f0fb7d53c7642eca9be6684d5ea4f79fa4b613cf56777e576c6a8899e1eda3eba63d488648d56d96731cad4a9238cb05afda954947aed981112b6f7cf0809dfcece3ea2477dca108a105f3b21de87b0ee4ebb22dcf61ea3ccbaa3c5ae316a1815138178faeb34151347c04ec5d025b8356ddba8181eac949a7246fd1921c10809247c4648d0befbb83722896d9b46c5449cf8352ef401c2f503977d632724eb410267af1fb2740e308a6243d8e3db6eb767871d91edd97f24cc302c9bdf32067d5a20a25b3b1c72efe550d027ee785786cd7967add9b51d90ed88c84ab1990df98c8cd8f6f266595c31e0985dcc4ed811c12284f671ffc86df537826d37fd056dfb19c4c6f69178667f46516cab2114613e434111a4dde2475e582a654b2756b68cd4b5a78635b8901e814b2ed726a2d9d82725e236f6bab4690b474ed8128a204f846dd90206c6a60fe1c8093b42111c0085500d7570a30c40d0f3829dcc87303d94f1c18cbd4c7aa6ac7258b0a4872636ddf0d503191cdcf9103e1e3b0c072de6e0ac477cd34a040ba6919191110b17d50bb15a18a65b55cb2e745fb1d30be163df94b6773a2e6dba456d76a1eef4b57ebb10cdeb2f159bdf6b3a7a993a530875ec583bfe09eb1666752bd3add6764a7f2f949dbe7b727a774fc72dde69740b3bcd6d74a4b2535fa35b34bae5e956b7a5fb76ab57682509d9df67ba95ddfb49c7272d7a936e799b6eb5b6a05692903da75b57b77e34d62c7c4697a6e39225a525a91d2f54a20bdb2d597c52abb6d8ea94974ce32d872c4c5ba5aa5994c6284a2b83d1b6b849ca7a811f8ff4327566cc474988a61749646eba6fb20c27b06007745fe66609ccfc818414c2552a1d97e2d28d5eeae8ee4eb946db5d4b86c84a92a7b932a3a46e41e8c7b9d0007e7388731e03d06f511db71c833b7ab7b987f29ee3de7348d510efa87b47fd9356a04e1d76403abe9a7f310fd5e70fdfe424cae342ff4d520b42aadffc9a87a6bae846b76eaec2a9591e3a72c299333fd8aa2136df6ef3edfb4648dc717b8e6fcfa1bfd3f16df29158b3da3f5276993fbc6c59410b0b53670add1ce75269fec0d1adb8242e993af3d04bce3fb8f445174b00ffe2923de36f32ce6316ba398e6ee5df7c476e19b1765c76aa14707e731570f42d109fa8f4cf54e5a5a24865eacce32829452af937c7d9517f3074a06ea31dbb21d502996647366241fd79d7749cdd4f58bf30f7b7da437208b6bb0b20c72d53673e0039e66400e47c9d3f2c7f43514b4d34979a34692297787ce27ceef8bc44924be68f9bcf7b1742564bf524211c4e9d88935b384f12c2f377e4d68e2709e1bfc94837d7dfdc15e9664746bab92a23dde824aa8f9cb0e9af3f49f5d03d54daf3d662dce5217bf92bc3092c9cf338fc8e674838ba088443d6cd55dfb09b0d5f3db8f68d9cdc327f2409e1389fbf93838710f6a0652b4dd9f3128bccc27dfe2882383c0e79363cc4d178eacc7feacc0ff3d03b3f38ff76ca80f346074d9d1d2f8261c7af5d3b7ef39bf35065f8d9a500593bba21341f3961df879065388105c2a56e41eefa24207c87def4c73d0908bfd190d32f60fb6a2820e812dc5c5ab153d3df0bd8de52a1a89476ec824029019c3a124a0976bc46259ce3e8d4d471296d552e812a9760c76fec827668db4100b276683c759436ec80826e9e6f744abaf63419e590374274f8aedbb9e557b2cb8efbeef00977b6842f162cd9f2d583971db702b6a41b67cef06281ebd564cb183d43707935a1f26a72f46aa2f45a0199d70aa2bc56d06405482f159469f252c1929e215e2a0083553a3187a2f4f0862d9b9e526a002c66d005958207276ac073c3170f5578b8814919fa23c5809e1830ddf0c5648d1d0f9988d9b5d65a691a2f263c802f263cd8338e1c9e9e1ea44bda2c6253c21e248cb55082310d68c0262b47989b8204731bbe983c9101a3367c3151d233830f768f0d3b80c9d9c1cb9c29026cf8da81c9ae1bbe76c0617fa98984933ad2984e894b03a348af0de90b7c7558f160dbe0a026212971b2c2e322536348a909d214314082019627e060c29584431134280184452a82bb392031d9906cd0c2c053e615717877c3970e34b86430e0a70171783c4e660fb829f38a30f094c9e3845ae171b1298558363da574062466b0b229cd1bbe742862e7d8f0a5c3922d9a938c041e05f424c1da86af2558f4581560c3570e5f72f0627f2b1fe4c0450c396821c3b6e12b871b5058719e84f684bd4b789c3031b9c09381c789d403080209183134f9628b0a525862cc0f57c470041b41b0e8a16b531a94d01a789cd81ca2ec2df5882dd83e85930313ec0c0f150d26b4cb0ef3a701130b1a64ea5f32831a7e1a40975ca921954a91b063f586af252c58a2647f3b5b6c9425486658e2eac6cce02489141cd248820318243774d901d8f085830c70a8527b98c0c0ad33f284c13a48f1448a5d8f8a51723c50f0b713d441abe1d3cebc66f1ce4401099b470cfe764a38057a2002c9b52bbcc1aeb87e0bd875cbc636266365034208eb0f862f1c86d8f119a6b55be90382d9da3f23104cec1e9061bf9f5193fd6dda0804b3636b6b1aa6c9ad05c93418b63d1277a68bf4b8007fa63d29bd01968230292003692803030f47e4d0431563ba2803bb403a628d28beb8614c1032d82e0e2fa84a969494c1b5d65aeb0d4a52fe88c00d5aa40edc9fc52970d18841936001fbeaac662677cef9a855438c6c9448591cedf97ff5726655ddf1fb304d07d9545607d9b62ad341b6adc274906dcfbd7f663d32a324323535b251ead0d3464f1bb8470c9697b587663b0bd08a46711a610173c58b0d4f44381ebeae64b9b09e38b942ddd5a50f58a1bc9e707d5c98797c83808117a80da90daa2cc98ed1731ace0eb7a528d590b8e5e9c572dc477bde66886d23abec9aebf8bcb4b2b3d3289b3b86b4b9e3259aecec2a22fa33bd3e7b82ccaee25ae2061b7585c99cb9de8a3b22f319eadf69dbc75f8e3bc52e48087484606fef88d45cc74d5d8c02d37fddbbc8799d90ae8b5d903984eb88d8bcbb4962d9d0e9f3f1c342f06b0d50cddceee5a17ab851a710eca1fc9d2070277c384207624041c513d6ed86d89ddd6bea82cc9bf24fda26dfa86152db9ff6f9d90919c1906d047ba3c79dfeb45d4fe750fd08f6cd5fbda4dbbb5f9b9c3acd39dee5a11cdae958c6ba20f4f8b50b426fab8a88e93a6c478152a743d8874cef6ef3477f6f57243bbdfcea103d3c0da65529ad1a6273d36d6ee2bafc61e73c791dd986fee635637a887b7dcd4df5524e470a90b5c348869b2781f0005ffd7d64fdcc9b1c36b9260f71bf9a46e3ac22c2dd74ee26ad7111060718196daf43c1280a585bbb6843ed34c3b0b3d1deb67b228c3b11b68f64dbdec4156d7b2484ad1d5e18b6ddb408529b28b5b57aafc36285cb9edaea943cd9009f7bd2c09b0c3c25100ce14b092b5bd21d281165c3571256ec1f1bbe9260b2af097ef58281932d81f8913af23d66e00f5ab182f421f42d6f04fa4c2a66f607c7d8f1890be5ef0ffb65054caac796ef3183b3820567c39795275652e0c4999c0d5f4e74d163c397134890b0e1ab09389ae081091bbe9a30a2091c6acc88f1bc705ca8f0ac1051a30313496ed2d8f1526df8aa62e555e5c98e1e3238fea330a523870daa86e6c69b4e5cc8a136ddb083281f17ee6d21b765191c3f87a6965b69bf80753e6e2ced23d97e81a633ddd9bd806de8d342f4b25fe03ce8d34274ed2327ec78972bc62f6e5402c7dbd7125aea8f404a72b2afe434952d3fee3ad994257f40d6115e7c1645af0f4734a147d1ee882d3b27cee94dbd4375b851087cdab13189893433c7a056542bd894ec899db2442bb38d71392953b670b7072db1ab52a8782c7801931e3b0b60ba4d708d81ccc93af192d205d268483756c91104e77b98c0df8e14242398e4f45081bb0d5f529c4869b2bf1c586bd502633aa34b1886d51a065231b5d2a59a651c605a50060c982f5ebe8001732557370b35d4f0fbad95d4cbaa8bc4be836171d39c4d51d45622f2dc85c873da68dbdffbaafd66a38d11c9adb576c5ea95bbea61b167d9b45693b64a39b3634455e93910e7b01edda8c4916f79046fa971209028648c388272c6bea64af7b7b33f23246cfa09b32cdbb6d6ccce7b739838829c9a8a8923dc9a21092a5d922b496b95dc670487521eb7590c4906a074a9c78e006db7473470249e39fc8276fdcc99fe22a5ff901d3be66d1008860b469b522dbb5e4564d6287bfbb4c943db6d4e03c5caaeb71957736ab46fa0081c97bff9d122759e1a4d94d1b4d9afcdd9613724a397c676413852fe489c2c83ea49224beb84d8947dea36dfd0ed37c37d9f09e98ad0edf636fb7df633e18eabb48e3bc4ae12624f5379c8e67073b985d473dce4cf3b7d2a17a9b7fac3eff4b715c1a7bafbcf1cb2bde639b210b8b7abb24d1eea5ea33b9efc190d79b2d3926655bc9452ce5ecafdd2ffc86b2fcd2d5c8ebbb6877521daab711b1421bba68f120a981daf33b9fa995f2b08fcfe91b53b4282a31850e0da10ae20acf99ba7a7540fc14f7da48585764af74682f481998e3baf5e6b338ed3e4b79fb63c5fe79472a3fb9457f79a7286edae6e9c2314616eefae7540dd33dd9b26924462fddea637e5ee32952b538e562c67f22c0cf026334d769a6ca58ed6719799fcd6b8d38ec809797bec80b48d6eba51bab10c313486c0f055849657114a452051c4930b5cf8e39a20953e22bd7c5cade68fa7567bd61d2d1721bdf66a24d8447367df3290a66d9e9b4a13b8c343bb2da79f9259f03f408115b2dd3d4de4643d4ee00d506085254ccc96d4ce523859965dc15f2a85b342b6810f44207167678188045974255d1891307c11a1b4e16b082b3602367c0dd1c3ae96daaea70a8c7d6251733d587090f42144810824eefa1536f001e943be3e6219a2c9a69f7772a1bcf630876ec9adb05d0b23bc29c37de4cedb016d50aeea36bd9333cf394ddd3dd39198a5cb0a902b4aa35010bba7e6e9823ffaa57e44a4253d5a30fcc7f36fb54d9de99aa2c9f4abf564c15fd42e71b65267a6e4ead69b32f72d5722bae9f5916be39cb05ced9e18e07938b5d01298a749942d1f9b48a8a589953eece7d4b21f0634008520e9c303e3c90e68bb5aa54a01bfe62a9c4ef31a8de4741a6db4af67e2de19751a95ad699ae6e40ac2a93fabd42d7161ce15f2e5ec6b71a40fcfd6d7bcc709fcf5d8f5da7b481f34a7d3bc1ae1a957004d8622d46428754c5ee66cfeeee72da723dc35d35cf5a45403031a23d3e6128f02e23de4d99fd1923daf41c0b3bf06eca987b80f65b7f4e3f4c763f7e9f8ff50a7dc651eb9f20e734f167cbf7d47fae8608f0daf694f7f764f08a1fe38ce6af9eb11c4ea0c66da491a060f955bf440d1030511854a9462557a40fdcd8865945c7d3bd80b85152756d90207a70ab6d7926a1c25ac8aae782457979288ae7a7056833962c96799e460dd6030fdfcacc76615fcd9207272a44ee4d9f43d628c31c62a050e9aff9993677719255790cbb7b3b3b3b3b3336f2dc69afe5229ab75ddd914903a3576f4105efea0b6c70618e7cbe992eae19202836118771a77ad899ab24729e65029b992af5b46292f4d71ea60a9e974d33dede5f0e35338873ea947fd19c9c1357f39315bceda63961e3b14a1d66f4c6d8dcd0dd5df337dd601a52cd12402ed4d863b95e9d69173649b9cca359926c79bbc63a0ce74d34d9aa86eef98f71fa965fb9f698de44c3a33ddb4238263a507626c69948a558d6aea99a2878c153b73e68c965d4fb74e0601cfae7a886a2b5d20c8d943f4d8e1edb52db5fd47ae76d45c771fb3b8efb96ce56adbf4672407ee0c043990cb9c9501e6e46abaa0278a2cfbfc4f967fe839e8e3c28e212bec39753687e8650e92ab287d649ccc43f341a6fe61805cd51fb9aa158a5087401f0ffac45d663f433dfbd5b89c2e88d136511c303bfb7db9a0cbd64ebd7bab695e6d0764bd6ff17613614365eff6de965107f28a04c910599693ba08cd5e900c91b50dd14ebd6b47e59afc799fd103bc6bbf262eeb808ec43334fb7ccee937cefc759ff698ed8a64b7fa9b45b47745e8aff72be4a3dfce7545b2a36e334aab88dc7b50fb90ecdfd43471bee636595724fbc7fdd33e77848204e1013e7bec36379b5e933f1afd196da238e43d6e9c87ba6b8f365ede38ad71dc10487b9e72d0c7857871e700a3283a2173c36e08766dfb2ccb20f601268d8d367722792484edfde6a1ee70a78070e48afe87cde15119db7c31b3e186fb6ebaa37cec509a16df497c7b934d0774baebe83fd2c9136abd0f779f49bbf01b6da42694a76445aee86384cfa13e4ef0179d58d9f49ba67544628ce264d3c728914a9c12ab401fb829cc72a0d85cbb943972456b5724bed35f77d3bf4ebb60746317ff12c3c9fe12e58bd28edd6d277d74efba22f8567ff2f85c57c4f4abbf1c79930b465b62db154169dd909a1c95d0d3e4c8e407fc45177d0d67d95c1eb359a48f4e4bb4a2eb7e63361deb803a9389c644137197e9f66182e96d58f8a85c5122e943ea9cb7a04ff733757876f8088151a01f4f8ada15e88f2218725cc76d4e7568d75192b36c9ee3f4ab1c19ca126c88e43649bd92b23375fa3b3d6a2a7d9c7476ca61fc4efae84e8ff38bd3e54d0636fd6e1d1036619309c7cef4aeeb5272457f3b7fa020579c90f4f1753b64366514e48ade0707dc59b1298e198520d3efed804c8f510f759758aee817956c72496472b90ec8747d80c01fb4028520ae03925d9646e44dbfb0c3eff20b717797d98824327777533662baea48dcdda7c9f3b407a05c6171dfeb7540dce5ee95d2d4016d546af6715b3d542f619437754072cb49ee4063be625f2e82c15e9ab06997bda68fa02c413ec959dab3af56964c52111922927b62b5aa88442b89b816a33f61b31ef3bc8c712753907a6e484584dec33f5de621ac6b1ef20e379134416902cd3f2249bf797cec3419e92c1ad9328146b7a02ca1be457318a02ce174284bf05ea529cfd364c8bab003b2e7301ca43bd6dcabf79f69ca435eeeb28a083d777aee3f13ca95dc32cd6635abf5a3265977b81af6cce61a2569b7b9cdefe4501ba5e1136475993b96f4deae7b87fd4eac0886716b6b45b0b83b7cc21a56843a649d4e5966833d43e5c8ba9065938b50d771d809a1ae4317e568e1a21c6fd9bc26474ebab7c949daefbd272d6eed9e32779cb76730cbb20cc3eab525617676cc64b398b558d8dd5b45f6b75efdb900c396cfbad3d3696edbe974aa9a76a2dccddc49522835fa8b5b229d5563b46f77284da8d1ad24fc56d2e935efb05f4cf34b93e3c62649c3bd8bfbca6fdc6fde5e93214b9e48b6bed6feec89a4cc708316a3188cbb62698f5e622831d159f3472425848f463bca0eca15755d08a90415c1308fcdcf2e6563d8589876cdd7cb18843616fdccae8da58b603885b183227e70c41303d4ae79250abd972c5b9e040584d164cb1e32029f71f0d7833b0bdbc63408e06b1cb28160db33f26c193232391e30b258fa25c9b5a1865376388c9a4186c393bb658a3068e080d8a224611630b27859dad9862f2f66705fbcd8411730aa7c51e68b25139731fdb9a03f236be1b3ae48bca6bf4ddbffcc2cbb60f4000c8503d60ef7c76d99eda965b303c224d0503ddd34cb126b5fa83e37f8a4a076915bf0f8d490c3e353434e86e50b2edc95deefe37d0be9041677a95b4942f29e6e799742f152b73c8d75a7934416a7e5e335624597cab230756866fa0a5387feada4eedc3d6df2ae694fb782a60eed38dddad9e092b6a31db2b643566441d60bd827646d39cb5f1cf2c0fc9fd03576a60e2ec5d1e9a3c38ed538b93aa2892562d8d0e5072a8ec82d00030e36962811062b7b950103237696653e4a50ab1c14e652e73814cecb0b257bc786af2fa26cbbe1eb8b271cfd0f7f5937e6a22e059961744102909569cf640701c84232c309ac0cb2b42331ca461230627541479a6e250565d79ee9566465bfb10b3a8adf5441f12aa852481212c2744b86c8c27e35526461dfa8a45efdd4a1f45ac690851dc2ecf4b58b0064d95700b2e8ad0064d95f3a25964558a9f52a9258941d49a667388155841d09a6673881251f244fa5a42a7891a1e435060b7c7288e30636c2d0e06383cf0e5d80d1c5161e9c6d3270f6786b2db4b2a5ccdc2f0b3865b3ac1d835e76baf0c095e936bbc7a096ed311f991b04a96df5f7816d24b56536a74f0cf71e619c8b92824ec726134d515290e934ba65c4f2345481de5365d79eddfe9e72d144bdc8f45692d0e928ddaaf9e92d9ae3ebc8aa781d872c2faba256a560ba7715e675680d5951b67c565453a4e3de63a74a81e6a60bd1dca42327452d54f3a96d2ea2b9496bc7b204ca76ea6cdfe4932e966c49bba023ac8b92ec299b74cb8875bacd4127cf3379a6a0234fb792824c67c5a023fcd36f96599029d09b6e011d9fa679abb9d0b2e5b32e5c5c74d9b10352a5e07934f7302d64fad4ad9a9bb435229fa9826c0eb7508ea3ae23d3bc371af41348752f446fbad0bc771f17fe78b613762d3a1d759c8b741cff52fd6d3a7212779c8bf06db42c8bd9b3bc619ad0e9a82dfb96ed29a7a64ecdb491d426400ea4e4604b1abdd190b7d1454942f8285d847f0a3a4252a3559646ab322458abac56dd0b099db42ad3aaab53309d5e056fbe0b2a1baab46fb737e12d0b997eba965330fda45b49560b79c7bae5bd959d9541169689e8964ad748931807326099e223c36b8b2aaf2d8eaeddac766f013875b22d9571bfb700a7371d6424358d3229b934f14101521732db7689f2d2c20b8d8bd7acd8da6fb06831450756bc749085a339a73a69d8c31ed68478683841d05cf753f7014ea5c2b7008f83603a87750aaae35c4885a38578700741b3b04d1cd6346c24b5bbd48d8e7befbdf7de7b511a854271f73ccff33c1f14586bedabcb18af2e56acb5f1f6a585936d394ec5fd74958793b200ce41b080ea3c5499474a08e72008a9ce03e74220681c954ef17c20e575e1b227a5b1d639eb9c531e995bcecb493919f7e46c1c211ec639e5d428945055a9a4945209b1b8e53c47cfd139299c94424a2985b0d67c64ee2a2b9119446f79e9436aa9b53cd545e20522c618634764ce30d0460921841042082184328b0b254723a591c623ad39e5189b5e4620f08b27a2fbc3fec1cb38b5df89d529b726ede186bd5afdc98cd95b3db461adb3d29d1d5369f52a5bafc22a9db25eca4d215ca8c8674db260b2b70dc3b20ccbb22cc33221f5f4928b5896654374845ec811a6a55cddb0eedb3e4435cd0dac5d7ee8da2a3f14a5946e944df6791d594e79d764da448cb0e070667f46585caeedc2a4e2da5b0b5a5c9b9e68dbe2c2a83dcbb83ea8e4da54e788234c541c611eb2b1331b28c23cec503d3f9828e8b37d1ed3a068074464eb89037fa88d4128024ab341e5d8b2dc281becdadb5114cbaab861d9a75d7575904da56d57d50dc322c568b63d7bc6e5c98bcc8e5d11232c4b5cdb05a328a8b8824c2bae4da9b836d5476619d7deb4174798efb838c23483e310341ccd704f94064f9c56657318cbb0c5186b78c3185fdc610e7b42de9781fd597963a2946e1ba5df367ab7ac03425dc1dba15ccd0dd3300cc3aad60161da6691258551bae5b8eb770f6fb665f0f67b39746976b8b367c7bedde62faab0f833b37c6462fb46d55569aa6aaf8a966e475a9b7247e6a69cded78b7dbf9de66c3b7c654126f1b0039a5613001f2549084f25c698d2c128dc150481524a29a594529ce7ac7a481f33c6380029c30d12373c96058061cfb24502cf7f340537005848dc39186637cb6af780f9ec586623942bb85029db908bebc98e1bc813985e315c5c4da20bf131ce09af09088e875c5c4d763492315e0180cec74749548780546badb5d65a719eb3ea51b12979e01da40b02a5f413d64b2d177200fb3cfd2811ecf3b51b426b0794d10c03a1018e73e34f6ac6851cc83850e53122f304bb3ecb5f1daa9f32d64f2146588c5c9ce3383ca58f29511cae34e2a8727618e0c65a9812b252eb30c0cd8121bd36f82849cea72e9426c847a95138bee7d660482f86514eaeb063b9c24e33102af8e3388c6194520d25fb8f9c74669a06d73f86fb7118e772052409fce1ec89f39c558fd38ffcc1055203c63848dc267c94043d0c695639144e65205850291c2c43a51990a04c4cea0e1f25d96fd816e883dee2a95513ab675c0e7bf82829ca12e48f92a08fadd65aeb85e4aa1e881218852021e96352995b8891463ab5e845a20048126cf1c77103c8acc5dff7b7edb9419d1e5b0fb99adf01b203fe7a6c7bbec70e093c0ac09494f0b2e777e785224c14e46a1e880ef8bb7b1e85a05a730b71cbcb98a1d20c4c62ee28a6ab97346e90b8299e36a989e5d05a28f15112274b989f874090c0f29f154432a0f30d739e527aa3cdd373009dd386317eeea82b912046320895228b932d3f891845b1e96796dd10a8542fb114371ee69c1962c3d70f86d89f69c393b0e12b8e34368c3a62f87321a63f4a8af233e2e2d201e620b0dc908b6b0917976bc3d799a5fd9d7046695f138e5c499ae186af3355b69d3f762435037fa91e15ab874a33206da834031355d52dc43dafa1c4cb571c60e48539df8f92e6939c95140f29c4590887cd03a9418c7174d9f065c68bfd85b0e50db0e1cbcc946dad0c78fe43e517a89c2f425d2ed4bc9cd8d42d4428c227531388ce8a923ea0c4cb0805e9acf81f3969007254eb67e58020c1d93f6af14c7d574ab10c8bb2ea17eaa67ace2980a0604bc46695b6be0738903061e58921b810038c124a948c81a30833708c81c17186d4628b4bb3c8018d4958334db20a47131f0ca1848b1254d040c5982d57e4a8e249920d57c278c30c8bc211655338a604a006282e732931e3f2c2ae7a6014ce8f7aaa13c33ce1620b24315ea0b8010b882a4e4891411667b8ae964d290512c30e1c3f98ff7cc1d18685a38d1d93a001151328a3c9105f24f172030b48460c6ab0821a7041030d64c08a4fb1608c9923c26461a64c18770659b4a08d2d4be4f00414707ca00d9e367cdaf0010f6f94f101928d09816d6fe890450bf3c442e1460e0a73a98fe1301b1beb224436260419bc1126880c2461c10c6810d3a40a1a5078a2054080a1a10c1348bc3e45971dbcd185a34193e695d4996fe0607f3956dee82193c28d3259dea8e20d28a814cf4a724a323b5f1655f46006597050061915307385103850e2e5022ea85426ec557283936f08f106142d0aabb921c50d2038322de8a10b1a50b992258d1ffc7003209cd0011957980c6145160337786801b6ed7063ca5471230a3265b25828dc1843c68d246dc0c129e130c6c61a775c2e974b89151fb7cc1ff4098ffe56557fc734d526ed69b8eab07f9f5ee60fc9c3b3b3239750993a4f616cc492d30c3c0463973d5b49516f8993bab674c55674b12651b631ea22ca36a68780a43e02cf6cf917b22df56734c36600862cc8aaf34774b1e61b3b7ed996f08d06481f1168830c5c411f1168c30db882fb8355ecf9452ddb0c0cdfd8707f108b3dcf387ac38a333cb8a18316d6bcb2041a5bba1421e58a2bace90416314890792dbd806544049438a01051864c1a3d60653103132c7ca0460f48b2604d1f62e0228729b678a34b10acf99df9230429da60220a2e92f8000dd6ec62690917e4e0439929de60cdffd42736894f1e529f31e69c5e5caa34ab6c430b1b5c5e6d88a95c1738eab4e1451b5df64777940b73a0e422c6281fe39ca20b1b646e906121a382ade30c0ea017587040230757e07086873194e8c10f505c3a10c28c2b3457c6b4c18613325274d428238e1d70c1e40a33a00d96680192325c3c89620936a6989ed802b5ca19a365cc1763b458838dcc099a0d5f63981803c4162936036616b7601c4a35ea0352a4f172b951a586309edca0032d908eca04c1450fccf0b830a822d56335468635cc44913c3c5658cb634319505001041a4dc29061e50a296090d4304612343ee0c4fe56fbf136b113a0032741f8b0461664d260ed60f224cb146492084385159fa2c2063c3620c0185f584982092faec0810c7c9930411623a494e104184d8658c30b1bbc7a10e6b5e4030d4a113bb821840f3f2cf15a038bee5631aad2450639240d71c6120f3e55cc1e98590389358cf08162a90cb5a8319492f0c1b2d4657fd827064b36d83e51e06cc3d7920ca85d7ae20c9f2b5f9688c0c6d82cdd80598b8dc0648c154489620824de48415218417481e2d2e14b1a56ba3466c0dd25d2a042d35062f2c166c7862f35c8a831461bf2908c684403174cccc0060c76d8c207020053c5152b5a4011c6952cb012320440c88084cb11165850813531e60a34c4785283307424116badb5d65a6badf5938bf9f3822c6304f102e3c889510e5364d1024b1431989941199b4bc5470a16ebc46a8cb1d2491f6bac31d6a901d8a3ea13608ffa08b5d02106941ebe78598249131da6208388306630230a247648a20615981a56e4c06a30458d18d8334a90c4c00a2ea650c1c115451736f84026ca15336a54d9d2a842e70d6a1871eb86af303198d1820c09bba18106c6387534ac2481860d3ebce00c313fbce075c617253e2fe0367c9da183aac9299588c2891a6c4083154060d1c403dab8020e2096b828c344938e08ee884c8d1b36359a2479717930803be50c0e7c6882c9173d80e1a58b1a40e921075b6c60034b0ae20ddb7dc1164e8a5277839d65383338a30a06f30a63e61566061f255e6292c8321f29a91eab140ae3e42c8171ea3c307306106734c178fa2cf1adb68c58b64c03892352c0440e515ce08505c5f070851466dcd0e20665244d39e24ac1801426b0a821494c191e8c30c2881c23a0f0d08c075e9461c68b076136a53e51541bbecab862631bbecad092d1df38ef968b725192d076ef4532b79284ee762abf5dd342dda76e45a9319e3ad93d99e33a8edf4a12b2798c512895d241ba952494e351b776a64ef61cd7a173e8d68fce8e752bcb6ea3e1d4d93e73772e5ffaed42f49b6e25696fddd36b5a68becba2bebac5c2d4c936a95bd1b52446dd5a61ea64bfe7244d763a64c58c46663559cd212b6614b24c99de6b2505d5e85664e5a2fbeda75c942474757cf2a25d06a64265ea64d9371a182b6a254100b2eab143d6a68bea21eb8b5476f62d435697218bcb9075cb5052c6937da184d283a20ac2ae4264d5ff4896d294d912d71ede28752b2948b7228b625a85ae1e29b26afda68f929cc0c28e1459f5da678eac2b23ac927a2c9a83f20af631dbfff810b14dfa79facd7eead8473d75ab65ff4125294fed216bb2b057ab87e0529413cc9d87396130c6ddef9178e75e3b550addef853aad853cad27c60161b9923c7225646a68b40f4feb10f66fc810bd861deb86c463df7eb71ccfececdbd4b402648c18165175b5ba5d770f4f632a7a1c373d4efa0081bfd56ac5791e778853f3070952479efaf8803f12a036c16482c904a4b37036e533fb5ce769249cc61a4f1d78a9492d8b3b7f6c77cbb07504e366b6560c33bbc2b02709702b49fba63f75e45bdb5bf8aed8b7185cf5113af3914dfbb0dbc3eec8a49bfd892a2592f617b3af74283bddb31b929d66b5d3e80eb0ec6ac5865eec0b4b80e14b8c29fb9a606bfbdcb0ae08942bac65c4da1ea56e418523284b983a73bb0aa64d5b093f2857a88a2b942ba9a518a6cf68c7f86bba9ac6d5173ccbe9a1225da7b1cc2d10d9bf80dda4ed6d574416311d07a2fba864edb495450d32c666240000006314002028140a888442a150309c6a9b281f14000b9ab24464481408a32086511064103104194308010000630c88d0d4900375cca1d5a4d723ce37062ed9346c430fdaa20302e9c162470da16d8d4df4049342b18300ee09a0694e91046d6c61790453b8e0d7c5ecf0aaf9a74af07cc8a3684dc86052d0dca3d2572421fa9b826feefbf1a6c5cec608898130d811f8e7d9452d7351c83fceda5653ddbfc07476a6bf62e95fa82bf19321990a78af02f7e7cb5a320cfd459d22ebac62ab5ce8768f79c71864a10548404b77bb6f0527e5573d0dd40f2335db85011e851eab4f493631016d5d41149817d69dc1b6069b57f359a719608154b751badd8d2d86d0191324e2a053ade5b3b7eb85a05eefcc5aee10c6b0c2e51a2d5f0fc3317756e0858d8cb28e72c2321cab02636cdcecb946e4d5e046d74053ef53efbb979e20cbfda4d23b2ab782f7112a4e285097ddd8c0d7dcf28cd9f916c7c2e2c5568329ed7a1209eda95d1f6f4180ccf5fc270fadbaa11ad4600e7be6f3973f1991c41a18ffc525a91f86f9c508ed7d007a425db014063ccaad2699455cfe3d698dbb4976f82ad92fbac844a027f44092903d6ad03f4ee382a79071730171d6940392aa4d684dbb999247f10f7bc874d64b883b37ec6a9c06abc364b4c2370a6e9a49353fc50371954adba91b1aef2031e14b77d1053e9d2003750f9a4c697af3d830e342d74a1c784d7359481e3788445dc5ac73e5a15cce14ac5b49f44de4838159fd87fcb5254f0720a26dce18351cc9739fea569490f379e2cf108493a87c34911d36ec1cc0026c1fed950ed963870ad3c241632d36f2f400ea34dc0389fb6f425a45bcdfe9d350aaba40d7f5ad6b6ec1ff52a9a73f9feae33017da9d03898a0d90dbdd038501f4c072cfe9985ff38e4822f696e85c24a69d986956da0d78c59eb83693148f571581f8763498503b0325027439d1254b96c6a099cb200c6b927d80359cb036ee47692d2a18b51e22478dd3b30c825b7e5e97e01c3b34458ae1e4828807af34d7e46c32fa8eefaf74082910845d557fff5c0a5f2b8328ff031326f1c1019f65acce05428e67ddaf484bf853e32fc61e509c74329b20cd65ded6ca0dd02ff154e8566411e6d2affe00216bede025ff8379190e0c75616725e6ea48a0b28157ea97716fa471425de1ac1694c106bc0798073078ce01c607fabfc7438e94735cc07610e831d15b6d902520b6180a982b7187ead6351210a7b84cf9be18dea677020cb0df4338d642d7a3178c347a67ef83f69d2a4ccc89b1db9712a3f25d004def3ab4b73a38ded25008e5870613a223204e2a8fa9a7a968ba81f1af8420de6920b8152d9402ae1a325ddea1e987b841e8fa0a2d3e742d5040601c18eeb9c954aab181d56a1420a134593b6f0f0f3700a970a7c0900b97486fd012c7f312ec4ee589a2f104c84f3fcb3f1ad5c55441cae65d24460a102afe71a102e783b74080c20c1a649cb04e2814cf463357328b07b97b7278d556e240620f7e8f5f14199124485192cdc693fd839e9982e7cec52fb7a96f564b05cc858c4cb4f3d8c6451c016c829b5d508f22f57c6b27020e17b43cb2a39d9f59b7b44aac601ff970c9735a541da42fa5f492282a197fc19b677b990186e7d99d0075724f3d177ef2fc5886a0c0292b6ba29a55b62b63efba2f8b37964e8d059db649a4a017bd995a1b7ff8e8b2cd9948bca23a1ac53d449f350533cf4528b1c22f44e78488f4ad77f9e41c82cee21234ef3913c1962a0c5184f1b918b18295f5703890774ccfae07603a5cdd647538810be93f6a938c6b7307c54a138be373d86c6c87257e82862132f7d33ad69bb600738aaf74954a384432239b0c1bcceb68d3307915cdce8b7bd2330ed59b49312baaf85897d20022284157cfd16605d03572d2f085711248464a965f01038a5148769b22f1434c18a9daa6f21d646b35d833804547acaac9ae0b3c8d9d782cc092e5af51f836aaab8686de4e793b671bfecd3447a20730f3da0ecadd60729ebd0f90cddb5c683bc877afe8875b4bf9c1cd2026f2292639fce437264842489c388db189f7149bf2f3430409fea07e4fd6d2e750aeebf5c0dc9d25e0c0ae70fcd52a070ad3509b0e9a320253f0a82ea2f40454e52ec05e85e8b5c4b05031dd6576b24b290fbfe1ba443b3af4c469eae307b13730366359226454465f4fc30e6c95da383b4d2c6858d36f9a1ded6b28f3257be1ed3d297d6f50e3c4d4b1ba8981a05778552261b547628bd7c05191a7d6a1277a00288faf7ceb106a97fe6ebaf2c24aaeb6549dd823b8379bf2110da970f4ecbb72463106e358617f2c892064d711efd333871081e7828a6299bedb4c72c4b2377365af4fc971b9f25aa5874ea4a6934ad1f76d6eca5f3d586d23f9ea506a04ddc13fb216479f5d30737227132693896daea0a42d00aab4932f06610af722180686492481047001f1b5b91481e84a02c19fdcb853fc4bfff0d60c2747686797340fb31157d2e3d757c0f3295ecc416ae54a8d9c11188f366f0d3cea941a66e87b868448ed6f382f444a0bda0da5647129e3f7bb938c31cbcb832c31eb28e958f4afc95e8957cd04dd24669151e25749840882ec18d220b75285132e6ee8804cea6203fb7b322aa122ece02a278ff7022f09e7d6acbead7ce1e2b8262e08a7a4638c361951b370e10a3feba1c9ffa3ff4fcd744e3e74631b8cfffa33701f635be1317469395c265013ac76219fc797b7d626d395a0ec2484444d78eaaaf92bc82c29478ea4e9f13316aebb3a4bed6a5a542b3841862e09abdc4b71d82b632e9a9f171945ccd2b27850ea290ee4778c2e5bd4d2738e8f6893c92e2b255a6f328baa8ed9b639d09d953613cd078744f755081f568eccc26e795fec6f2f18a87405312b6cd64a866dccc0959c2d4e7d0ab13668706df6b095971ca0fc83729b863d701c5c3ef575c2482f4f0debee90b3cfa62e309724d13fcebab7d9aff519d9eec474c156058a23d675de58c1d5b0b72b238e5c464c08a229c85626d09fcb4ec466db18310536be245a13be0c7c5728158e7bb57c0d511132f879187f56fc3208165193f2c85ed5abc06f105ec8e780f4110a6d997c0d3e15079fd4a3c6988718002cf3d8a3268dd61333c9cb33b898a693e22f90341682f127820b0891d9c9b8e60c154f43035d502f29eba1dda473c64d2165571774f3c681d24a9faa498df999af5ca31d806678b0a4f8d63898530e54bb8feebbb8a3a9b6c4649a71bce208cef368798f3d9e29a9696401a5e5ed8e322af089a5e115087a58eee94a06bbe10e45bff371f7f66391a3069ef4cfbf6a627596621691c97230e2426ccc3ebf393391295046668a343ae56abd17507643d11b10fbb35e3b0c040d9bc5f6a5d53e0c93a3c642914677c3f4229a3037880724a07408eaa1c8cfa4642828ac084268063d48cea700955be4bcb5a15426307a1e4898c92206ff9462f2b6aca1f61cfd67951575dd088bbcfac1b4e0fb37a75092d821339b5f0ca3dfddd06649d9f8f5dbc283227699cd253a65510c84046b5c71e8824d2448eaea6642ada3846ac6374449e57de714675ba50277fe50928725fd963739a2e63585682742ac2366cc4fa0ec6cc1ada4c9f9fccd6bd828276284b74ad4fc54f7fb8ba4ca6033028493062da2ff825b35925c67cb75f3718dff2265c43a7b2b45fd1633135ce61dc994c58d7a6595c930d542d3bb1ff73d62f70fb88e43d9a2e47d888daa3b5fa6c3f6a9f1ad31b13f40c67bf52e5807b2652758896a69619b5759de0c099da76909c5e9bc0319cb6fc0465402d44054c3f3032d8bf517cec179a1bdb4627e621804b6a444d7d050cbf9e8ccda074dec88fd87c57f38256340c00b1a5f1e01c19ab76d3109e53af0cf272f766235c37e01bdf3487f53316f01a9736c6b9e4a5e5991f4e22bee6d6b24e72184911d4e9c7955e9ee17c0cde353ef226e6cb589570efb3e01c40db2ca5998c1e247d5e2b8c0a90ef80274ccc0f28c129bc2f7f54ae0d37a02966c3a84fe56358c4a232c981639961bd92400a9a8cd6c879c2531c4476dcd7ae8cfa67a1cd5d5e640248715f894e4059113831d21026058d92027f452863997071c54d99df8d26a0d260c0db532d87281858d2fc317245528085604b246a885f64e466ca69fcce9bb158446b954e681c493b4b2b8873539894eb70786487f375dd5f5dd96fdf9e443b8796a92a28a819caba11f6b75eb6b862b7fcfe3c1e6c473a488eb5fd3c9d5a6d6e0034744608866d8add11d0675c665b6ac20ea55fb661816c006500c48bff14b6bd4e050b0015b1724616030d4624599ae6326e6fd90022021e166d4a84e685194c9d52c4137485c47eb5724bc7072b1e90efaae45d05866caea9537fccde205eaa69f3e88e1900ad3430e156ff8ff30e717222a56baddeceb188135790734b99a181cf2d369e2617098797d424e7522dd0cb96ef3d6278f9f189182f8294b3158cf587f032d5122779a0904ce024e5a1f8a6d6e06e7162dcab3c5f55f01028f0a7e13812857dc87141b2ead0a66ea829f9839248640a273daf00dcf807e711682d90981a8511df71502906c33fbe04f2498735b6cad9b04bac891f3b1324f5e9bcd0731fc78481bbe86839bdf7c5c5dd7ce2b5301101aea334105c4180648b74b454571daed62a93c2f0caeec1531012d9fdc2e20c94540d654f278fb59c1b8bd125a815cec5e5ae85f2e27b9f7f2df15727b37ee4d381ac3ea886b60496300b65c30bc5c5dd0851342d43a85b50802ffbeea7f74f04bfa6f66becb9099769d15f35de04563ef841efc4a2a2815d246dffd377a5c9e1a5466d5c271567eebd2f305a2b5322e78acffae9410411988bdb8a4b040779005be80fc4d9d785853c4a6fd71536d3849936caf90f7ee90494029be1a4c258eddcd2ba8bdab5d46f0be9273055c1325bd47c446c0054a1873798cece702767d625b81afb48cfbd07f40e07cc96796e46b956a2850bdfb8a0f58f0dc82afb1db289a8d094d88e0f79eb899ee8a440703b04c449e604294e5c6688f1ea5384a604aadbd9f6406f537307eb4fb82f48530fac954ee217939bd675b749e6a1d1aaa16d2a1e3170a7400d141473d2de62496941f0777bea68f3b1b1ffb293d224a26f6b924a856677713046299ecaa2f41e93a5002214bc8dcec7175176b6cb6362850e403766101f0dd15bdf573d688610c162e60aa0e79438ea58616524cc5aaa4d060ab21f40b4d2a0837183e4a212bab5fb3120d37d58bdcfc113ff0d3c24d98eecaafa8a7bfbc8b821dc33f79ca6cf063e6e1ae8d27833e0c6d5184ceae55e6938d9a7ddbf7d81abbece6f1b62a5045b44e2d73f4add0ee7de36bfb9405f669c4c1bc1b2c6a0cb83f9f85079484033a5d61934a5cd8aaca2571a386a2270683cf5240682a4df7a7b172691e1c3a00dc0426cfb5399921e2f5ee9c0814ed6bdfb58f6100c9ddecce8770f0bb2eeec4801f66e179d11960e884b981b1854e8c05ebf5eb85930cac10b50222c2e1d4c783aad6ac904948f832ff3ff13dd26ddfb73601643319c995630c05effa8b561d847259099c88a7000bb9c8c8fd18a8a306f49062b93cc5454037e013d6a5b82b2ffa12325b0287d33f6614def781d56887007a04f4e4f7a09bb9c831cbc1558a0ca56487f12669871da0bac13be4fa25e25024a7adba77be103900e5e6161c0acdb62171b20a695967e2d0d0e3d2cab135e83481bb3e1741773dad9345e7e5643468ad3bc6e222ac7ad32f4027f58e462d308fd283c71db63a54c84adcf87471020ff5a1000bcd17c6db68256ab24f2a2b6e81a6e50bc9b2e051b76df4b38a4b2c65661b9f83b0adb1e1a2c85b2a50b1af683bd57f36146eb0b22d49db107a40219950ac06d935143e7b1baf31a229cc7cff218557e6e18d73005e0d1100c7f323a5d78939bc35dc5680b4cf41a596e7c04705e10b03c1613a31ee107371a81661af5e454118726259e928475b357b3dc9b8fdff6e3255f44109496d940942869069766a1de5d21bb89f96b529702f473ae830ec74fd01fa52d2bd7cfa5411957f199e7f2ca702efa6ca53ae25bb661cbdfb8d92715869378b2fc6a5bdf1085a701720b2a52055da3c509a3105bbfcd165aa44a638b6cc51ff0525cb1cc13a7a13d3649e677a126cb41055c6442b1cec2100db75706ffb75228f67f8d5fa09841f79cd5ecea8229d0cf8787ae6898f2ce08662c35cfb732950f6b2c0d95c9459122dd6e8d6d9d5a3da598ec47e3fbab14b8f988a3a55eae6e09fd6d87764e1861e31f166ac09ea49387ade84f0c33008371ed7ad3c6191a30269c66c751d99e2920374d50c5b5ee44cec0a9d9169f90433136859e69e09e18d524a5f4ce6d58025b8154398948c1be4783db935f2ac5a248ce29f7bdc425102f4308f19746e550e910cd8cba6aa11785f93e8fda6cba32268dcc6e68aff85850481c6bf11d2afc0d8b812b2c1380c42a8b01a03ce8806b66491eb159a64a2b01d5712c909a6230743e00f86bb380dc7b332b06bf410b434aa111096f749c6195659ad1c1e738d5fac658dd05094af228deaefa87f03e623e3e88d593cf9cfa8c04383d472a61797c4718a524662c4934daf37072663a1c17fa040353830fdacb1dae4974326e20893cf6468dc1fc0d977daab0c318917b221d35d0c01bbd4228483efc804c82c020c2ae54aab227e6d882a91b420783ccb1954a0dce21f2b00e947414ac2eba79fda86aa939e58780c8253cd8168760b224663c07a90dcd67177223ee8dd6f30609115e8f164591b314178729747e56340328b50a00bc900980c7bba9439811889a86a953e48473c9c47e3bebe9e9372f251d9bbbaecc8d80c0169f8c392e6e91b429186b2d6eae30b9985abc97e093d4b11f322f548927de6a32f1c03ad1dfe273c4e56042cc96c395041110046bacc813f195ad87a9cd90ae11206f56271c93c97fafbd001642d1b18f516ccb916b2ab601f46f12702dcac13d817efd79f3cebf5d2c7ce4a67bf7966ed6c3b7c4bb6d5795254099a230c926bde7803c506837526822debfb541422025d5c1c02a5810a3bd23495752897383b92c02e24549d7b2210b0c0ef5fb4f4b7009afaaa82def092675fc0f6332eb41e77f410a4e5be715b3d823b8f55b29aefbedef43152bbb185b024886029f9861b900b9b9083cdd364241c4c1151c2a99205182b095518356fbc64f4bef8872ebb9e7d0c00ce476cb3570f0ea0342035dada8af2024aa96564260b7762f293d28b16e186750b009d3a4cb1004ad45b8d9fe697a05ae8a24452a1260c2024ad23d31d48af58bb65f172861604e5bd24232cf74cf3a8ec4e17b6c0f59f791ddd62120d94a70dccc6314138a4fede758b1a622c785ffe61f1995fc0ff348b6f4cc2011f29980d6dfd6c9511b84c960271d80a754993e9b0739535300e0f3d995cf1aed410105a294d48dd54db35fbc6c87768134f5890addd6f7abd01dbc476432bd023d7220614f277fd0654335d9fcc376240d690bd18a754c20e598fe99a41b5fa628aab025edc7095e3ae41c622abbd09e61f56e04f6f441e62af6b81f6aff82c4756b4587191006665a3d83c103a67e8a2c28d253ed59602770a6908fe96d0d9ab50e43bb0ac32039de831515f097f5e4b9a717bb40ccde2dfe702abe46f97ba333c1887436157ddbd3120377599afd200b749d60d82028b38fb121fa53c2cd122412a5075fe3503817e2969f2576721c8932970b41b6762d000f647d142a9fb508d2ceb213cc98634b5e987d114b2cbc306f153c735f35f121e64f3d9a513576651971329ad5a8107ca5daed6f5cef0777c656ce5e76efcaf03d3eb8a07da2079ea798678fa19c284c2df23c759dbd3416e336bdafe4d31c22010ca41345705fc5120b5d5783e543577cf91eeea98b6fdca501c3b3811f582974db336558fc0c8d0b30d83cabf22bf45f55daddfebfbc421bb429f8986db1ecbc20130ba27e801d1f1003f8d2324ffac2d70ce19952b4a22bc9c5b23cdb0231b959ade517f8e16598a63416b620857bc9fd1190116c529c0e16bf63fb0890c562995e4753652ebd926073df1003d39081562aa19e41a7e02f1a4e78fb0747c8eac26a64288ff32e03a8aa5338b02cfa945a6b3bff7cd886323daeb47616542ef850729548d8270fa1b25740405b0d46c2003f87c04990f66c382c4ff6dfe77d07116aa9332720e3456270acc3450c29e1f4b2f80ff9b70552919321d45e890fa1d06a2d5ce105d85095c7e67c789a1e3047d10a6ddcd33c716c078414fc444b1e8891434f5f9096d0ce7c6efc63e1bbfcc2ae1c4750ad5ac217c3904af7c55d8747de1d70be7aa1e7291311feef4db04fdce0d40c43d7a1cd7927e11ba6bae1ed8f1b86726d06c84cc4ae77ece3325898a78780020c8806bbd8ec690d0ff4db84497a24416a8b619d62e53c7d26d6d31b4e0a485159869126bde4adefd4bf836ff553e411bac580fa246e342531fee8b57260c6cfb50d2b0049cf0227b25fcae7915df6d9626c86c370a533e5335f08ca17eae088e5a3c1c9512f72772329a8897e1815b303581e3a5d6bc10d3e34a240c606f5a20533e47d9853db244a0c641d810b9d346db675537c7f5b4c812d8f890fc0ed15431d80bf23909f29025578c0c97790c849a668a2a2c81192cfabcb7259514175d3b43f2fcaa04fa1c3d00ba57543823604d4b22a68116aca40fd7f2f59ed2772e224a311061810150aa7af9b89e50fe3d49d40cfa87577c09712c670cfee67bf0c5508f4b589b90c7087c1cf8cbab99259f5d5ebe4a25fe2e0431c4b6b99cca78f1a432061f5e10ce8a58094fc442af5e91b69a473ed69b9c6ffacb092e8cbae453ebc53630d40d57509b5171af2e593e367da0f2f02c521fcfcdc0d088511a9ccca8ff46fc3e7f6e2ea4ce021e63133d2ec45f1b9d708d198f65b2d24c5646c649ee5a2e2719dd029a8848c003f7d6e11bc6720946a29f584fdf75fe62d60eae5942d4008e0fb8523a8131b14ec9955e7485ad9df0b354db3c1749980f3974c4784a0eeba8eb9701717f89c872a645c4b1f6e2a8c752617aa4d220306174724bb3786de6872b75d782d5dac18bddc184adef52e4d3937102fc55d970821e6744f7f1eb6e4a0953b07f7102f8fb9ad35c9259b5efc7fcfb9235870c6a631479278aaa788cc75198e14fb02caae2c3029cc451bd15bd6d9794d8d79e323be17b0da039dae9d00ce462e0b71653254b006a2a416e95cebdfa45958cf3f36ba300b8235de6dcdebb768223ad39f7921420c87cdaa99779e10d25fbe58f99f018a7385ed724f889fdc852acf6c3fd2b5339a094965adbc4bb619cb5684a2b81728f41452e8e85a9a32c533f0cd1094a791af6e91c584b71beeed55099066592cbade189b72ba7fb68e662d7d9b8da7a927b1c2bbd3d8090f6d7de7308eeefdb92f649bc4cf6ea96b839b30506cb7105183b2c3a0f5183a71efe89772b58a6f37280853fc9d5a847ef73ad6c04f79ac46eefa4e1ded511da3c68e84b13954d8b2061ed1d70b156de7bd6b5616de911e689cc276cb05cc34887daad156b2bbfbd6bd689325180fddb99cab17e29589da0fdf3ba587d5cf4ed201f8711107e39accc80db9e8d0c0c2d1cfdd362070182c778316229f0b8b39092ec4ebc2c64afa58bab0d367e364f9966adc4fd9a0b7b00d0d9bde643b717213c8b055f4690ad7c2bed69377052bd223c157042604ac51a1e4c70ba4ff2d33aec089d498f112b4b41ba04511628016ff342b7ea4d8b9bd0243e546f026740d8f895cf39f618ee5e6c7007c15dc4db073f7b56f79bd31b39deea881f5264a36458266dc201c1c56bccf5b72d26d769d75dc62131e68e6cc9d6196e9f2e314e32cc22aeab1fcb62ded1e819dd1e9cbc5ec1376137484b83a552f01faec0e07d7b84cd79a0c7d27dfd6560b3126bc626266d3dde686510410696875a193e7f5833f8fe6774f604edaef39ce9c8e2fee29dc868828ae6f344d45c805b7bc3017cb11d9a3a7398b97ffe94ea1eed630502bc24470fdd02186e847dcfb946d0969484c1cf77213cdaaa8ecfdfa98b1195f5ee0870b3e164991436c1c4f05f89f6584721107863791bd6b918c799f3ad8225413db5b909798cc56d21b9285a66693318ed3861071ee7710403ec0ff7efee9a144049ba7d14a230c14102fa1de8d56240a08bd549b301f532ec24d48fcc10807635106a17e53a918011eb695bd848fda0ff490c804da7db58fff19e51e39dfdf47214625d64fea1c973ddb3007d5c33fd01664d9bc9b04123e826671a2a7e25e83e28055b61ad73794a85de04356e60cfe307e14086755bc84ce6ac73384ef0d9bf7d1ecaa66deadd57d36c10d1f74538d1af710c084557948c187ee883f6329c99b40292b866bf79155f598064f89e61d2ccac48ac613827c97e128ce18766e7114a6570e7d3db8799227549ba5b34078d74efe910cd394924f27755d2713a07b1c19349e336151291372df3f6fe56a1d57218102f822e9cd7a3387d82c8188bb931774636da73bdfd4a8582e5143a65c1e9f7becc5ef619dcd5556b4995a09000b8844c1e221c3d8f64c2f6ae34c20733c975fb00db5cd3d3563ccbcf191da754621d100c7a915b7d3b1e078ef2d7cecc07bb536b28c9c865eea8a552b96217caf5a92e7288acb180451e67ef1059465ef67b7622dd2ebd3daeb89d4062399b02183b8e2116d005b6e866563e1b1de58139381cac69fa574b3ca12839f1eb46891110c649323592e231f155d900548b658ee51a9af10b6f2d7860108740823eba52783c551b6e06947df791261d372e799ce4eebcac667f38572e61a42070d5421645202ffb9348d59fe2999333b3fac6e8f2700502581fd31f46477e45840dba4bb46e2395f95b7790ba8e69831cd9756d15b4e36cefa507f08464cb0ccf5bbfc9ac7aabf7e284610b164bb8d5b92b11d9743908825c53b3fe178002f0d68079c4f88f4c35cbbb90db1e26a7fabcb458952b8b4f9523d16d00fc37796472dba68fa007fb9918c67f8a98ba815f86daada277eff315a139930ead8bdc16042c913f7d905454398384c4a5da115fb0217ac67fb3c6c0392b52261899e8ac5e373f235af9454e0741137f300b6209cf3f54c60aedb94842f7065caa919cb1a7d19f7492d3c1118968678f39a130679426a8a2935b5e5be30a7e2a6a88fa6c4aec976c0e0df82b54de8fe4a7a2e5ea39c7eec1a69c6985c95aafa2f25ba8bb310d1926551bc582875d9b5d8dcc2508c00f71e0130f896de1c49857c948d7483a92b4f1012254e47083be50832812aaadb9fe2c2a47f1f856d5f44882999a97ddba037dc40a88b6a434d50dbb4b9c139aa7d07a1ed013aff079467d9e7384b910f25528266cd8c2afddce7fe4cb3ddfbbfc816d5e6296cc424c6c3b07317b1aea13bf9d00729377a749070fa8995e08e8b9b3a12a1db6913e5449fe8c8dc5aeca277443357075e0f590821207c780369446ea701ede0efa2b769918e5e66514ae6ac1fb4ae7c69ed0ad7053703bab8b863e3a936a14cdca2ca2169b50d05f7cbdef977853731df999b4442f83f3a8661c948296cc3f5014b5d1e1a973a920ed3aeffd5ab702ed519ef20002a398e72788ad2a0567fbf80aac395f28a8f3b993123310cf897e5476ce92a7a17504cec30fc21ecdd677ad287319a21df3e5b804fce3527262978974214f530d1d4dd240a678ffe3f94277573d4ab6df4a25db68271cae801a0d220799f7d64aae020930ef51e2c75a8b92552aba3ade5fb73e72408ea87284576e9b44c6c4ed4ee19fcade7987b39fbd5b9e9cb0f575084176068246901660587b611ec9b5c6db454a9f89628a35ae8041fa6ab5a4f4356b2c7b98ec5fcdce43dc61127859537dc88a50b3b3a17ababe213cea8230855a924485d933b1bae292b835ea7aa96951a32dbe4a6168ae38886c5bd199ce85a37030c90aa44e2272e24fc70351eda802c2c0c79439a45c15a31b3b351459f0342e562d9611d3ae9ecb34bf9ae0c5d0f81e067e4a972abf1aa2f822058eab122bc687f29343a74c32d5c96c590da92987d1ecd5882df743cbff9fe9a515a1f3efd595880b50102d6ce1555747bb196b9be029e4ad788a22d8ef74367af2aa3076cbc2bacf46676bc5f76dc6c25d035ee6d121ecd2c320dfaca27d28befaf1c35e05b14f64e4ebec53bcbacfcc5251da32553ca5cca3d9360f62a7108fec90e80642d261853262cb6aba91feef50dc3e920e169cbdb7ff773f8e8de046ca755c2af1dd6c14006ed84088c01f15c1ebadbb5906bec9e4559196af6ebfc4c12c4a7ce76b2171588c00f53eb4283e717db5f5675d108ac56e6915f1834ad390b3b03dd351717ea6b17b5024bcd03af387690ed57f575017efb129992144f1772d1311d8f087433b1f3bfef8fb26d93f97fad8d0dcdc45fa67aab64504a1814fbc09353ac456cbebda00b5698b8ea13dc15b039867bac64469a5dad31b3254a3b20442e0413481ddabdff3b47e8b65a342297d68b46ed65e3f4008b5553a3a22d2ba247f9571842d65f64cb1e5cd1378b656dc391cd96ac65e901e2c0bbff37347af4998f519667df1ec5b41c77c3590d977b8c4594f43713b3687cc93cfc4767a2cb65417fca2aee4dbb88d2475df71f7f920e267765e5f225ddc74fc1109dd63e2c27d0694cc5c53d2a04f74ed324817b19ff38b5144cc77531df0cbb745aee55808aeccd9de9e8ca2d89d271d1bc61b5433e02625debe08acc917fb7ca1383ada5eb967458e016799ae4018fc813206091e11c32ad2789e9b60f53d9452e26f1b1f7a81b1a989b1556439f613bdae70f94c884746f0d11c39bcbe1eb17c6656a861a2b7afb6cc1af563e7e1688848ab30ef00046665aeb2d61506f1c738c086304f54e5f3013ce3185f7cd8cc298e213500279653ff118ae7573e9153729a6e714e7ea8a853604afb34bc3eb07d2a63643566bf10762619b4d2f514026388d23d8b534b1ab94948f15bfe0ae1e5e83decd52e23a18422fa2576ce84c7b987f15c8fde0e1aa14fbfd3a2e5a983d448f658a58cd065f04c11fccc0960e4b646de68c10952b09df051a730aae420e792acf8e8bef3a979cf5fac658644281d45bc9a51ec3ed58fbdc056e96c0642173133078bd1c49a4ab97da68f7ec06bf601504cae8c7701df7ff7c47ac7c1788218311010e9ab4436c4b531bd7b9629c4f401e8a685b292e1af6fafc954892930cc4e3daa0c968012eeff5b4a1986202d5d78585265e363a8bff5aea69be86778237afdb6240c0be82ecc6326ca2d5502005f42a0ed67b4957699fd1b84292ae33e78e109c20d3de9b219b9c4a23eeee1fdbefb801ff21f0eae0be8499cb0ff2af3805f1e6649db684ff13eb4cc626558c8af52fc8f99564448571cf04b9377694e81950d6f9989a5756d014798f3d0fbb1bba786a011525bc6fba7e2c52a4c17363628a4c3e1848b980db121ed94e580ce0c939956c12157bb6f5b8523f0654939c0232e0450a7516824c4c978852834b43e32a8d25306bf8c20f5a0024b2fc617ac1554faefd02dd4b6334f4fe41c70263775a68f59e354ee52f4d931d6b00c2f4a7afdf3ecc864fa41a98821126f54c0b820e73e6756e115f7623ff380380477a82ea69b489674d213c1535009176532e496fd83a192d93c33b7937bb4fdcebca835f0d138128f0cf2f94493209eb7b5f76034a30f8f97b9a3b13cb6ad9b2e6b734b53019042600848c46fc9f4636d256cf72ac74493d1aa722a61b0d6769cc1b4bc50f8000755fb4f119986af3f7f9153ee67da77a0cb0fc5215dc81b1e74d75ea9e73bc1a053c225ac96f612d1610e7959109931b6372b37cd6b932337810141a37672e6020a0f3f0a69fddddf9c0e042b2af207c93f7e5524b384ba23c714d42148775b7ce23a227f43ff0730dff821ee140a0b5cff6981ed33711d2e0a8616c831f98cc8b6ca804d7f5e07eba49d38e22cea98d299b9e88087ff08691861a951e79457db24054e483b2eadb9d3f746ebd5efd2531586ecb0bcc8e2847fc6e0c9535471b3b5eaaa0a3d9b1a1d925a405c76acd5216ebf9e6766f32aecd060280d846f182a8195a904fef37a0605b1e86ce83e9e6da11ec25f13e389571759166d09059c7c95c505d2e9ba676ec2203cc2277204019d518a4c08757c4b0bbf8000e3be1e971500e1bd32511d8bac287b5104d192fcc76a21dce528cd8370dd012c13e32902435431750dc9f5ffdb9bb0618e4f5346821353321c65833b0ba695017997852db47c718480c30e97007b98d518fb3d4d27be1efc14979affed6f8098224ae84c9d6b481f945852827442aeefee7c8dfd0ccdc1b005cb835d064c58d335ad8e474bc8a9ac656e59c5af7184ba514347ba143dec8df241b9aa7bbc0b9839ecdcb16c0a52203c372d9ce80ed47147bd47ddf4ad69e6d6d72536fa63da27bcff39c50fec180dfc612370dfafba3be709a008ae4346003e28f992cfbfe936b3f79a394e14c1d09beb3c32e0a0cdbd67ac85b6863cfdcc9f13a062977fa768c3bb905467f4b8b5d15a888316cdc9702268282ea2671333d7c8693ed41bf080fed4c4db39606493e16de827b6d94ff6db6756aba5a9e19d1b3929945fc131efb31b21a20ee5b84f0feabd4f14ec03e26e9b075b2c8977e37404c15d66c93a08bf217da316b3c0548bfdf884794f334f330020d5fc3545f62eba20e95c4c761401ac87f0824326a4d413931ec664eca3199befd3a6f7dda6f866537cdf34bee726e7491e894a87b8758e749365cb0ebaa30c9293385bb414acd212dcd2e57a0a8a5ad3095881f65ffd13b7880182cf16ab085c4ff8bf8bf0ec4bb12545dd97449da01cd2e1737bdc7fdcc4004972ecb55494aae2f0d608943cc327a25559f653e77327a94f3fdb8c2afdaa6e36e252e1f05cbcf6ca9608e6e249a41c429593c5acba6df2be2f8c6891d594fea051a9506bffb913ee0e0b89a517a5a09024a70a78df66becbeb2ac8695a2b4580162360c11e9ab986110b528e3cf7d56338c70ba7427a25db33518b08121daf1a8d9ef4fc9e4e0ce9dd5d6498b0d38ac458c9df96c1a42ffa44ddae1a5f3cf0dc2d06eeb941f23b826af7f4b237fa2411ddbd61c5296930abcfe6ffd91101eeae075859e94d16d7748aa1595b471c08bbba3b0278b66f6e5e9ae248f6e61e16273f5bc0c01e4bb5637029a20902c90b68e46eb7add754f6f90f751f473c0decb9589778a85e60d2b303999c3a2f03bc0ed72d31567045622be0fa391f989b1e82677b750a085f8304c2aecbc73e14832541e669eab294a828ad6b911f6f05d9ad48111fafc228988282e7097940204458d9ad624528ddeb42fa793385eeb5c90417c067fe3d408db38fac67a9610c4b07a38cb6ff294b2944178ee026c1d806dab3cdce6b4dd40fe52e355c4e50f8d77215bb54ddabc9c7cc20f09bc253fde1bcccdbf03511cf7d4092f3822338e45b2a78602db0e8d7151f3a4db14dac4e042d4b72613af4911baef8e4632a509dc3bf4223416d76fa6d54faf9ad9150da7d2d7679ec093cc02ab0772ddc8bcc4632203a3f9e7d098a7010ebb494c2dc1ee2c13c3b46e8262d27b4c28a25dd9270b1bd6dd7b449bd61c2d28f38f8acbf878be81af420f83124a0d4447ac1befa127bbf112f6d8b7e5dcb86e51d8c82b7c959921371835184aa26d535626332557291d377279c8193d0e06c2255371f6b028acddffcb5ed6a39b7c3756aec449d91ff560124c78c657c6cac26238cc8c27143d8be3f6bfad0cb16373bb653c56e27128478a8fa171cac4d9c347560b98c133a97272d282c5fdd37a3098d2bf2c6333b96809f46089265b95b96b0a05cd3ffaace3ae0fd59eccb2843c5d6868be717797864b352dca0381a66e0a364f6754bef6f4bc6a9358c8c14db743e37a8540e90993ad590ee447dee0af45d51208b70a52799bad355e92d4e6c7ca8d9cf2fd65d5158839228a165c963a4574bd6afddf10de527cb170965d122813980fe7717d5275d2caa7ea137ba008c5578bc84fd6fd30849df64fbda79704dacbeb610a55a9d0140ac9b24f49e15328e51dc27641edbd2a87c167b667071c5d3750a62042d0a50af263a8cf6f3c19894b040d22219b6c74c654d0145239c174cf0983decef273884adfd1f50b4b4d23e2e99ee534399af07e825e6636df8274bb43b6748cc4215045a20d9d29f91496aba3321ed9cd6abb2997c455a6a32b90622afd5d42ec2b55e174fd37540cd15d19c881ccae574ea1c6326ffd5adbd46d8e228541fdde8c6f8e131428f0c785d6e05e5b494d61077c1e37ceb2a1f629325360624486b71e162cc125c2cc09d98797706046ba921a553d7e700029cdfc39e5bf3c2bb3cd308e36e059a928e7043a3e4102214e03534e59044712b2ff40c2d9e3317f5ccfcd85fdc3302fa87017d8378eb58a7b7f01516cbc007fcb0ceb698170817bc1c71bdd79e463063bf09914e4a6015b5f1d3794659e0db611694bebd405a7c37114687e97ffcf12a31c28ea60078552504051052a3aebd6815edbc52a4c2752332bc6eced9a9c602598b33f00a1c089dddb14f593911d4811485fe90e50b03d304be82bb063ef9f0b1caaef472120440948a0b0e5e17780fe829bee4612fb6ba1fa874e45661e285f11f2f95e00ba9e074fe897b24ffa56fae96a761d009cdcdaa95f4c01acf50b8eb4570e3fbeeba20f24ee103aabb3a4099bc9fe348840c91c322510c11323d2e988525b0c7223bd3144d873960cf6300f25738faa8ad27e663cd6cb776cfbf764a591846693e80db0044bb4f17e299a1843f2ca242d7cf76a200cf38270d4604522da029fba014d3a277361803167203bfb3e4d44c207e611222181e1efe1a4224060e4962d30ff986a72e02c8342d839c0b6717fa8585a34868639c333a0c711d51c7e86553156af978dad204979772ac01b4d7a3e7c05d1ee5f8dcc89bb54eb0cac272dee0a765787400360a8c39e5d2df0366c35108291064b5444a3c74717c650ecbb5d7f729c3811d79027fae00e24b560f9392c473d639c48ee0fde68b4c2a3904989d512299f21564ac1e4b4a929bc4ba47f646412a2cb1adeebe19e91175da4e7bb1108d0e8406d266a050a739cf5d9f09f3504309aba699f721033f986ab49e9cec7b843f73acdb4d36995889eabb565e86c651a3500aad5bcf9113f45710cb5600d5c69952de46c1f7d42c114d128a033395ab6aeea3d834473dc5f5e6ba19bf322544e9f71b7c63b82e6e87db764cefb916385480c200dffac7bbd27c4d4301f0c1c2ec5a450361ce580d9cf19e8b2f3487b857ea13e78adbbff87eebcc48953d8e89e61fa60976e0b1c3f3ee87966c1ffb9d7cd80b1e292411967375a2055c4ec6d29e4c450c3240f4baa209bb3b1f0fc663306e6115ad3d6b2afdce796f9e9dc53827836fb19f35ef8ee04c4fe4cd8eb9d00a7249ce1a03b39ae7ac22085990d9c36f7e1ba3c72eff776315c556eef67f297da44f94176d65340a7711e2dcdf411db34846670109d9a65e185fcc4433dca42658e1d852308b4a867e2a5e00bed36feaab7fa4ca8356b343f034cf8dc4f03193a47e61740b477d893cc4f5162433f7008a7bbb6c3b06b3190dfac3117ba3d471a8a5b91d7d36f9880a2570acbcfe3b047316749cdcd26185e77aa9f85ca70f7ab1b29016ef4c85155a5f14508827ed15c6f6da4579a26abaa72c087f3cb49d14b83f1649cf5a45d81d89833321e95239b5ea5438d708b529d4136226f25e2a1cb3ed8386a86328a0f3bff19e6dc52d472bad98f632bd2b982d56a8dcf4e6cdcba2f5778ab5e3054a94ea1310406d811cf8bff765e67801ff105bdc2cae7d2fe74d14ecf0f4d2d92abd996ea316a315e316a98094d0379a16baa25be64d3d9da804f9219037c6454627d3c5c14ec4862c9b99e326c9305f433e56aa316b5109fb30eb9daad680516242a0a5311fa5059f49031fa785cfa71d9fa4051f63a24049339ff3b45ee72f7d49b774af4e3e12883ea7c8660c4e8cc22eb8dddb2d2bcd585e27698a2def63bf06cfd45ed84e5b3fcc1b9ad75d8e5bab1893121c1e1fe4eb524d3b7c5e0e3cd982b7bd83adc705ba996dac54a74b8fac2682cf3d31e71a7b096b4a614e47e71defbc243c94e4ad856a1d5ddc058e80628de75fa5bb026d36f2b0d1a81424ef94357c02c3335232954149809a346c7ce9b3f65a076c52880256d9ba2ba54d7ff1ce867d1bf9375bd7225ba61ec260181408d8f06c9d2af17b1031a3df020b5cdffeb5fc55a5aa70c4a1668c4240d4d8e80328904f265d1556b0d666a27d3098b5f6a6a445eaa0ba3e5d0859eb22f6aa3584f9c989a4464c2635f70d144f3684aa241873b4afec239f7d57639592de37ffe00386959f764029e6e871bfb77274d7688d18ec993dda6de7a49ee3f999287a218c78d5ddb4af6af45383b3744623f7cefbcc25ebe3de1d5c0db6eae20906ee812330fed9f673e99f0bcf79145eb8ad15173acfd715335dd63bc95ade462f8c399bf3666ec594a2d712f6794d4ffdbd8d5ad1185a6ee26064a2243f428862879b5a5def6e1a3b52963d91670da864b4f4d8ab2b402c3ce2d4979ef371fbc9ddafa3655eb55e0c44cfb38ff00e57e474f8887dc2cd0e523adefa35d1f671392781d54f4416cca02c8a2fcea9f74b5d412c8ab205b871a9ad8209403ce07e017cd0ddcf1bb2b39415f1504161d351f981fafbef8dc9943f584625da43923a05b0d5f9cf5988b59a883134770f71e9fa33aa2af07241740c7a65c163cb0e8039df50a8faa2eaba8fae018334b94ead87a294a2c9b216616ce2aae249f5d3cd38430b2d901025b20e8512efb9c6844a02c21ca76263c3500751cb8181b97e260c59670c9b0fc874485d8e0538ad0f802986662cf25d1e980675c366bb601e8c72d5a6b5814cbce4300d44624b539eb87169686032b59fe8c95acbcc26d93ff0257ff8c4c06a598dc47daa6a3201044a9eb1446e96cb9f27c9548bb5ae9150eb4db8f436e316ee5ab206879216099992940cb2a442414d57e2a95ef1f4e3a0f9075f52e138cce977752e4b5f3b71d471d66a896060c77a29fe792c95c243b8821b2c82c1286abee51052cf019f15c9e6149b3bb73d1728a4cbf3bcfa2f07c37dba23fe9cc8e5418fe88d459455c29806ed4c2996c2543a349d54d84f7fa414c913aaec4b6060f3a1bdce3e585d5b2d9652f6526ba9db9506b10bbd698e546e1a69f209412c84c6ea76f2cda2439bd5c69b25a336515b2bba2c0c54e5467ad2aa51d223ea91b5652d0c4002fb7169d5571e77faba43672ba0c7cd112b4754707f16628dac3fd20eb019c58e99d0238ce5fd155a3c853fca50dbec164fdbda9c29f73a63f3ff75169769bb0d8f519ab28e86b65d0d49335aacf50625af2df198512961969b6347a5c6d677e7f57dcc374c08329508ad8b664988e76b9e515a39cc4a10e98dba3f21ddc2ee494b077818704dbd1dbcd7bb06d1d1daf2d27f7b124afc74d6147d74864d6115c453c693bd1d3760a922306e37391777ee80335335f0d18d74dfb6d727267c02067194ab3372d2eab3c89cc45377ca6357d5ede6775e7285de0340c5272abe7e413b4c4a1074f1a6e086eb2eaa94d4b293a8886197105d8b7893b27ef33922a8f229503a9c5bf0c62147756e194ca5395db271cd0453ee59088d3b1faf822cb49d9b8e7f42c2776b7b1517d348336c6e17d6e87f21ee98a676935b684963a2a93f590dc0a93db97e0f175464040e04ca9c3533beb26a5389577419c7a74b8408ede494cedff0d38ddce98ecc9cda070b9e3ce14a1c40ff8d659a8081f87404cd0362673add444f949cddae44f2f5b784ee746a8b75b9b1c290c6dde1f7604c7cbe7a6a5cfb963eb32d34bab6b10a74249c0955ba120498271f2d5099ba6074bb5dfd90f8a8ff07cd5c679f9ddf928932d8bc532217bae830c575b1959b75c652e3802e4695022be5fa02541f9a58ebeb61598d1fbe068b4731f44a6d74e552eb7d84e3e37b6870cf7dbcb848feed28cc4411f9a4ecd75fdcaa6cf30540c7c0c8da6e403b342b06f157c762c1755e2f580db540b2932a9430601da490f79cd42c00f4780cbc69c7600a1462011a6782843a03925cd33ca9c72672318ea9bc791742befa29e458a90ccb6cd36031b35a2302090ab735cccb9591f5573c420961f70c38dd4d000064800fd60a1eecd40529ecb9dfb6b7d12d16f53d7dca858642c679d4513c5054afe0675cc45046623e02e999be6b84a28a82682af957c2e412be575e8df8a7020c92e10e62010c4f8c398b7694f3e9b725d8d8780a5883b3f3ca700aee1ea544b04e79be44b51f6b3c4e758245864c624e073fd1d3577e2eee1941aafc01f199e3d3cf3e1125155616d915afe497465e2c652cf4554024e9a0346823a2500670a8f4d4dc911a4391655fffb0d17928e99c15a69ae4837dd19f7b2be03157770c0f74627cccfcd296f08ce0bc77351abe5b9e21760a69b2433e59d992fce56a49b19a99a75039b078388f6d5d909468496b09bce286817dfaeb6c2c421778bb8bce7c22f526727ccaaa753c71f16038c3f1d8fd32bc7f375730ac5f17ef7887984cfe2d320ccc197f8e52565e291ad789e6c38321f8246671c66c2989988c77567da27dd85e911eb322f6e5ff8bcc328cb0ed80c1c866a7be31a43c7c64739e0606ec9cb3809d12f245b3aa52b8c2d9bdc7449983120e8af7f38d3e891e030b499d37adcc08f5f05a6cd6157dd41d95e5bad95e116ab448b2e2a37ac835ef5903152393ed4ae96b02c3e3f4f56defc775a38bc57679421e90b9f2b4a31e2ec9ecd0152c1f0a0713422c4e7aa276b59cc92900ae3b5602dc853d384b6667a45a92b083351506b95b483a7416a30f503b7cd11d704c00c91f74b822680fed52814e65ece3806ef3141328115f6f2aab0ee96ce12c566f11377e4281d0a33272cf9fcf9cb7f6b242c1210624cdd7e4552a2954bad03d8069e820c4df0499bdc07d5d08fb4a4e098404dc414b602b098d01e3c09dae967875d13314dbbd885d993ce8b8e043d315e943df62b1710ea80cfdc04b74b1eaff80bc8ebd2f93c2adeb734fe873b52861d7e9361686ea30aa7ac4618000feb3623e1b000662239739589fe65b8970a14a862bf12b9bd4aa7aa168aad02c48746507537070aa5d70490c02280589fa6943c14990de0725661488f640846ead27bd09b18138210276dfd985a6c84db69e28ecdf362ab8603df3ab452db4bdfa07d423adda16273fbc7019d45d26e76c1c0cea6992d826cdadb59d1162d361bd5f9f6b30c825b38364bcf8fe3aaeb6a0239753b2556f121d98f562f6cbd42380c8db7b947d545e2aaf43e1e0164dd8ff7a7996a8aa468f42598e70d5872bf533e747af5b8f27c89ea8550eeb16d95ae20928f902c5c7b1ca59b8ca20caf562de0fb5302a7c62e8dc446e9482ac100d40b74ccc94e7746f27f2cd8f3bf26376e68c12a6d7a634b6f42c2d5fd6ae51d9f71b228a490f1062fd49a54d048b408c2b111db1ba01f3900e82950c862ca8c009d846fccd99dc36aca2e5a8c596d6feb1ad3927baace933373dd6dfec8fd67d38ea921bcb4bf3adf97131c339498bdac87f33a1820868fd262cd25511008517650fef9a4ccae9adcd7e9aad44bc98c27b596f6154a0d8cbf1f98095dffee337c4847dd3718d4209d91295c7174e86b5a0027c19742bdc556e681f0313034b36e9cea6606dce0ea3c47fdc5b86f2663e9f6176ea1988f064afa6c064811c569aed4ab988fd6decf104f8b07a564bb88f56559bbd05e5e8860c2c502e769a3b9b70b1d6864a79b3ae47e05d3c18acc16153862352b4cd7180aae51b98318c6de8a22957005603305de95e439759b2a4fb493f008d22b0b5ef8298a15f5bd3fb5d81b94f79628c3e6e963d9abdd41c71f01ba51bb5200f548d5dab8ae15520fc3018bc026a8258d766c4db456be73faa1e487a6c4754fb20ba13aaf74befd8791690180a032081f8ab91075b8e1569ce84906161e0262a2b12e82bfc92a500b7b46d4661a94698dd4b66895f90aa165fced05ca1759825166b7ecf05e7b6320a4325149df1e1519f480773f46f3d66cd54c73a46e797ae608e684a2fa94f5df47a6fe0cd99b2a528d7f8b261abeb96e0e251b9706b24f4aa9f20eeacef240a88e95ef7b543b89e19a999a8ded281dcaa7e38ec540b523dabd869c576a1fd0e1cbaa326734662fcdedecc855fd6e08fd14bbca2760e540d0f8353a721599d88b5c965d375202f5cf49a309039b976e5ee37961134587102d7a47ae3ce3eb4e3ef684c1a1a659f083b6319f29489ea9ca087674ed23aa7e7677b08657c48bc44f4a40f63ff42d476733a8a060e905936be916c679cd5206a9982d7814b8b80a7af8b7f2a4f0b334e2e347c04dd22b928771973f1173f5592cb05e1f322f1a152c7cb07af8640da0fe0be43b39398b6e0d13052520cab054930841b08eb600d401d623074f0af4d6718ba3848a7f8df3ee6a3611e7c8a0497f7de07462f0615ccdec66fbde29e3b5fa96ba31f077165adf3a97ce979e912838f5191f979d6a5526c01445e22601a26b30c4e16b5e3283374c292856d27f46454e2b80a924b12252c699e2f70a216fb9f1650481dd2c7b1b04ff3e9f05ad02ec7c46025794502210c730c3129425dc646a221353de04bc4ee28901f5e60ab7151ed30797e59696412486cd6fe6637277176ea65c47f16c46db7fe6283683811a34e3a0b1dcafa91e99286aa0a1ebc2c423cbbc8108e62e03c28ec95e442de0275de932ddee8134ddc6bca195544d2ece401737c6e357e677f2c6daa82267a13c90d29fd43338e4c5481d0a9153aa6064e99976392131e6a2bbd186d15da1b935897e3118a2a139fa660fe1ed7b42716d4f6c3aec2e49a5ea9fe1d13a42a9cfa9afa24cc2dbb9907dace8914280f501d7819044d6085e8823042943ac97519dd1ceb7637828daaaee34309520f5922c72d2e822d01c199be9699cf70365e9aeb556f8dc9c7544e957d7a6866e6cf497b9e64b2bf0d5a77885b5a1c6eb24d8ea0cfc94f8cc12254d82645bd44fe095071ef83976c7035f4496c06c463141afaec39df1cc848495b0c18b75471a072a46b375a49bf9251cd6bc3c3843943f68427bdd33057f794a7b835d7971db5b1499d2a51a577b08b6704223fda4b82752ad7f4fedc4d81921ef17ac64b50ea1078a42ebe24427a911376815b84bd0e1fcd960f3f98a0e64e5e597b005b1bd6bcc92b46e52e1f55940f12bcba317d2fbeb2109e10e85a539c71109c5fa4d75aeb469c909a209bd1362fb5ce8c38eb9c854afc2791ac6e35466044b1241cdab8b7567bd1bc962a9c055aff33828f4f7484e109132d41cd49a59ccc1108871a2db6855714094e679cb73c56aff6f709110e0e98f7f2731ab8b8a8b6104c4efe1481d926bbd59c39b2579e20a0e9b6cd4d26af93393ccc97060a236d8cd3474de061aefaf8791755cda8046de5a79487a08e308b553ed26718dbf3a87aed1920e7ef8a24b017223a69935ddb783c62e6c9a0b5f95c5a87e88615694589518da2833f18ccfb2ac8e333c7deee42e1c27601579bb91a2c0f5794635b375432cddc3c830b1293a46797f0844a970b4db9cacef04f2d3027acecfc0cf62d18dade32c903f6570e4aeb0b8d858f036b32525fd6b3370dde336559684f3b93e0962113472946e041694fcca04d5275c4abb6c1931b23e705417f839a9c0d3a6db8b7715ff73446ea23daaed913d11886fd74133e6fa88a56753410ef3f0f780aa1d8863a3bcde15935b82df4a90f5bd1cfd2ffaa7bee84732c7137d1ec168b55a8bb00a1522eeab70d7f6c0a2d6c345097d53a26e2093d8da31de1c8e8c68269a93d646db6d6b536c05aeb276fb9bbbfc56243edb3ed3d853593b8d8d423008ee306d637dd55f829b3567c6c36ca3e6dabe2c56876639163ea03d9494002d3870ac8530999703a7a4a09400de5343eb3da240a90f4f532a1cfd2158d4d92033e284ce33387272c3dc9cc0b431f83a44dbc00897555cf31a329ec022ae649d2a4ad79e47b5ac65ea4fe58867359ac00d63707de44e35bc4f8e7c33481ab64047a3e3c694bc8ce97aff20cf101c6bfa2c6809ec3d33dce29788ece5a68e1564dbc109039cbab296581a57944d055a5956d512fc8d60fb536745c55391ff8dce3860b6f0b0f58d3b16ce6d53a8cbfa1e3e53327abe355d4a602bc3929f18ae1503106e0937e0fbdaeeeae1d65c023e552953bf46088c54b6690cc9ee7d12eb22f2540ffdb018d7b47776aefe9fdcdcdfd55b1c4dfae7762999784b69d75585b8cac2468e9341e9b1d7b0883b95de483d2af4898676adadd788a6cfe7b8268cf0316db551b28d7174fbeb2df8de4d91cdb4a0948b9554b1e92f225b7a06cb899fbc30f92d66b44b7ec8bd7c3b31bf37ad096c7aa726e1f598a04cc13db04adc153caca042591eecd067454ff7cc3c74092d83450be09a3de07913602815977d46e0553591d3cd9092999d7118114da2f4882656613c99b048525929580b08795990d3d01061590f8dc29c2fdc48a96757a61dd3b793e276bf524161363b6b717a58e9e4c1904107ca73d31051bbe28e4fbcf89663a7b63db638d5e8b945956d46816ccc9679b2cbd228ae5948d40856a0685b3aa7430b04d33131eea6336cd0f092e39b6457fdbe76fcdd0e0feb50cad5ea8d41e5aaea4f72df87f1c92410d9fbc13ddff8e71eecc756c9248bcccdfc1c3e6971ab7eab31a782f3bf17db4a9650865de61dcd74e85611ca6d7fcc2c1c23d6fb6ee7fa04f800f6e48d15070b1567d3404df10c2040996489055cd1a5cc0df517458ae71b6cfeef8fabbae6f44f1c2ba48b796d31ae2eaf15cb2edf34691887062864786db213bc110da5f82b2f2a9a2bb31320461ac21525aeada9b6337a8a8a3911155373df94cb8f942857eb471d358b8dff34d9c188a0744245a2d275118102c7c6e4dad370c0b0b83f167de09c0d1e38ccee5acb367f52646459d85718a2c80ec36583290cc7a9799b27f90c0d634ab84422b61e725227d70f64ed01334ceea9e8ff2d49a50190f77e47df84a645db80575bdb5243393178ff28e824dc1e3feabd7a2e384104d62bf832855cca4476a151905584d0326887b48ea403f07c40cc44079b3c994954c3b152287653634605e03ea791aa7e818f1eeec49827abefaa9fad025767404fb26227bba4b19f69c95c311fea170d2b4ba3bbafa65f98f5d1f23d6221aff3b406da2e55031a3c59fa75aa2daf73b005a2e5357151aac1f95412406cbe90bf8e2f88f64d7054139f65eb76ec1974556d127c9d9ec1758bd9c5e13dcb7bd44ce564c5431b2cc894524184f860f257d69f1e93ddc0c40698ff385240c973dcf15ae3b27a2fd876b54a4789690b633a87fad9539682f696a3f75c9d3ce3e99efdbd8f879302a13acc6816cddbc6a9665973b38b52bddc9ff0d15c605be245b07925ac499275106d46c38598a85d122ccd8365572f6682efda1872ee6b1231bdb2fcd5474c3508d6d158cc733cae1c4ce9f3de4d9e0775ad742de2ebb8cd12cc74cab976326a1f62b237af621bcfc04d638967fb63c189a63a6432fb2a86155d49d3a5ac479498adee1913711eec8b1814b985efe17dd7f0d146c2fb233bd4ed724bc55f5efd4bf4b23248ff9027e2d3f4c33aa11aeab8835a3813eaf3711491f9ce4411c33caf3699f85212559c1aac469206440eb3b3d0562c311cd6f018abb2f0edc03050cc3e8628c1e161abb22f2bcf10757d001dd03279411af44a3ebea96fcad71319758166458af597a224c1a3e2350b63bb570dd2bec8c413885d8e3dc95775f9e66142f7442ca7a4dc95c217325cad61faecb37098c9b89640bd3c9d13e81d0e4a684e2abb0120d930c9a673491a097e34481745dc1561b203b1c1162e93a1bd372c2ee2786e42e83f50149cd4eec12c605f772c9b2c7735fac722287dc0b71f948bb655db28b1cf4f6b58e5536b8b5c1f0d8e0e266cd21111f8a0c0d9f334b6914c13b27e065de19b88d7c592c766b6d21871a4cbf2e262be9c2944bef24407b6624e1112bce3e1f96e46a5dd2cf11d48575f942c6d7fe1b9fbd02125e21c407cf6b1b695ee50ddde20dd99227aaf51d37b8e56906b56f1656b3de60c8b1a0edd57a94a51f90df58391cb46d45f86378056dfd954df73eb798f5f6a4ef11c37787c726da9a49daa6dec933aa75a0179de0bab5f259d3e54a2ca4ffbcb95e3bb50387168457de4f236b97fa93539f465b56cba9238e53648cc51fc2361c2e8577200fd53f68ec9850e00c5122e26714ff43e3c564cad9e2abb389721a9522a2443e4bc59900915910a9c6179acef2c229abf69d7adb6daeaafbd0b7c299e4a8c3c124530feda8cb78762bb4e216ef815906ad7a364215395b78ca8392cb059586ef191c29dfe1ae8a01e0946a49dfac8d6317e6b47a2c16f0c9a25bf3cf4f4704a47e9d0e4f694f229439027897f5f2e0e43fe1654ad44f0c462a539ac627e42008a9425a26899fc982258a91b2da13b64240a922a58ad820a4498554ec3da20261196c38612fe4d4bc6a518aea5fb6fd3d3534878a94b1919636f51a8ca903aa7e8681354d2d7d5841664f14935e5849859212bbad9d883b50d6734ed3f004e480bcca5ab7c4959e6562b7d340188f6c7ceb8b3bad596d8667f86c5868a0bc8a88f58f2f990b6266ab555d0860a8b73caedef9cc71bbcd53c99e677cdaeebb1e2634b73e07fb43fe1265b1739dc6e1b36f341e5df2bf03eb4e9b75932a558bdbe35f4c0a8b9ef989cb697c0e88c6d66a1402210a3cd63a1802a08fd007fc1e4f16f73d2f4fe8b4ace7ebf6402d9a24f50b5443238c2360cd59baf9abb2d046a859deb54bd883c9c8db9680dd7524e79b0bad1ade5001e1cc9435a14285108199c05047935b3582973333e98d5ef71982ec4819a0981b24359d82048a593cce761ad64869ff420b4fd4c658cce944c4776f8eb96be5e973d4a00455fb0de93a10bfca339b982356fa415ab9f17cbfb58aa866359ff763e6e9f7bcea6d99ecfa3ccf81aa0c766d75569fde1c4a6fdd16c43c026cf543dc31ae19850e4013e86c22a445026ec14c50d41d0d7d67f94b3f67d4abfbddecc019f6ee97e7d018bfb4a0a8def6f980b16e711261bc8a4392cbbec30e7f47e8f5a27dfa0c1177c33caedc9b953b7b040f9704817b49b2c24077e759cb73ab9aa7f88ea7302d3a40d8b7e55ea55a4d46c6d152291446289f866eeb6669bf8c13a8cf91f9c03d4fbc1b9dc8407876d940209b860c809bb1128a4dc6033aa8ce3f30c7d9d43a18961e24291d098aa3ca5b85ea594dc885bf915f5bb212fdd650300ce038766347947f1cc69d44caa12962bb28b3f95b30f21c99fd64cf9064e0497752915a84b481a8a089cd47ecc312183e4869c1a441c6c21675ad66c21eefc0d8890456f6b3a6e6299ae792b56f034100cd532822a4ea9a92c263af5260f94b63394663d92b7a7472cdc80a7056b2ed27e173b10eaa9fb8a302278773800a549485b5c6da6394275db5b984fc475b3f0594f8edd1c71341820837493c51c231a9a1b7b39718ae6196ee79e3ca55bcdaf59c837d3e420b0032407035484046dfbc251e1711410627060e8c16b25ca529240fbe2dc8a9fca2654ec9b012faf315d98a876780f9300694bef6cfe484aa626e117abfebdb59f9fe3befc0b3175e1116cd4a73402f11314045af5ed61f102e681204c5372d47295f4c4841725a090593bb27990032b1744d4db0306b777b51ba30a2f811042b815ffc35497f601ad2c3b5b8753b805eb4d47c8430d56b9436f348aa61fa10fa934c99e6af083357012d6636d858bcb1d0676ac1e7b8e89a085a88d521640b8150350f34f1bc53388bb4256beda77f718b8432f0044ca8b0420d2f47b8f32d94ff0c2019ba96015f97f30764fcd3f0ef04154365d1e6dbb21261cc71ff78c347c62f13b92b5d46a14c8df63bf8adfe93516e3274d73887a0befda964e4225f9dbd1a927c3f7ae22a882a4c0a60ca25e2842edd528ef4a1c3a25f43ad0faeb11c9e30470c23f030746cb4bce175defcb8f0e480c96f475e02af8aeffa6ac2df9548a30e55f8b488fb586dddb7040a63149b6f6dcc51a8da83338ca191856e707cdc810127a67a2c0127510509c2ba4b0759738bb224223c54ebc04db9372126155303f2fad620d2d7a0f3af9492ab58c393c028a757150089183c5c9cb8068dab86b700bd8faf01192f281cf3ddcbcc7f0bcc8a8709dbe538f9f15c9b7683d262e8987573aec0b33e26b4b5ce7d10ebb0f65a1b21af805508d018c875be4b2dfe97619743920b2f27256c180bc2d848d1fbf0ce434e5dfd38e56de281e56111e74b8b863daf7c4ba44e5ce3c0051d34cc61cb00722e89c472e9aa2710c1606e6dd34a23667fc2e20f2a026c367e329d4fdf0f3b53bd9941eeb0f04d9fdc7b2ae1e37a161c0eb07d1081ce4a6e9c8e12a2395a14176fd62d37aa671e05e74abf86d339d59fde4a1ed3e38ebb1a471d6142962f2351d771e85dc8438af1072382ec06ae39313d356446f2a91f2f82c52df4aab805c1ece0520724c9a08d8d4d31863d98aa233a6abc53c863110fc967f233daa8d793828422aebc2318dfb623db287a7aac05a5adc21f934077ef69bc58f64e2ad8190522b282220c8e23cbe8e32bacb268b12bcafb2dce4d6e945a400867046c9c3c5ad29395288bbfa7beafbfdb3785877ba056113727806c8c41b54adced024ccc45a5fc535d39deac049ea332866d0f22e9ca011bf454f5405db78682d09145bf2db15fe473494a451dfd06b7a2e07e21d5159442a7e300631c8051a731a373ca984c1ea7680463ea18487d68f8dc2b81659eddf9362ac3203d0852d31c45459abb88584a279c6728b842e7fc4dfa6bcee4c6861a92759b6f869f092ea4e2b1042302a509b0d48820ffef1c8e068379e3d8184b1b04ee407bc10fe2af4b5a21706174d80f9ab6d2512cf836c50689fb1037badb4966f62be8cd05046e1e6ed8e39e3704ad39ac1afaf52a37888c4256725dffd31c99d035adfed75ac0ffd2638be471c8ac91a884b64d00cad35f595669f8b757049ef80c7f1719c512cc940922aa10804eac33023a781bbc6c4d7b44fde4ff05dfabc0e5dbdd8f41414ddd0c1645bd36497beb7d6a9328be2d7cc4ae2a527c2fa43cd6b5b687ffe9c1ba46816c2dbb6c7d8553ea086d97803dd5d63cdee4bc706e699b8b7a30b1718bed7e1b1c27469f996058c7a45f6e1575e9a9773b81ba0192e4a2fb3d96b992f7796856679a4e58bc85e371862abed4045894aac869b8abdcd731518af0342757f8d9b19c09b3e5d7262d2a1a25affdac99540771c3681aee7b7b5875b5d426ada3857293a07eba429d68886b1cf0a35b748b44f9e931742d4a855907b1c20f4758e014e6e4e5da391b78955c1c0935b3db41f45ab0a586fabceeb0bce9bbda725909dbf96a27410d93fa9147b682589f24258597dead650599a2ac2145d7e18dea5d6d46d944692fc2e9a148074d3efb3553a02240ae0b09a34b13e26b1d92a6f0e17431d60266f3f626741c80deca0076bf14909d0b63e4ad025ba18c987ccde493efd24b09e1860b5ace34e16a2583a710e1ffe4803b138c5a649d988c4f52895a28750f3e099119c674053a648940974a3fd615ced2ab27f35795e584deda150f642053b86157d436ab3b8376b45baceaee94706c0f04bc1cc7399e6ee7531cc864224375878dc86b25a1f2d996b533b6fedc703b867ea3f1180e53ffa5f301ebbd84631c4badbbcf240aa53f22210509e60bbdf5bf85d0b5d87d8f8fa65233cdae68ff93b1966814143478f384fd5f7f78c092b1ebde8e0b58431be67a5d43a0e82fa22c116f485b3584b12a02437c2d5d6cb4d5125e492665a944e9b64d00984aadf292d566a700c9c0cbf19754b1344d89386964b344a994d81feda592e3ad4c574b0daf9c906d287ac015996d523f3ccfa053edf3361822b5321794a89353ae98215733158460d77a982904680f4e577167461ca1d0ceac90a9f2643ff9d748645da43f035d5b267901a49d79d81e1beb9ec0fcc05913f846417a618ed7cdd227951653246f6619b4022880ead95c7ed32f1078963a6d930d3b43278988b61fa78f396d67ced519769945f6f5c42793db6bdeb68de0eb36e9430d98a0e53ac7e284d1a6298768a676b18d7d8fa42937cf674259f0a9f6888ebd95f5dfc32ffb22e491098b994ab511e75817ec348f64d1c5cd163a4a9e7b96da4dcb54f67ae3bfd090a234529eeeb0739d7ae200bea2040a554c4fec3838d4931e29eaa36529a377d724eba325e0e2987923845c9b57442f4083997036ad4f099dd9a30417e671904b8b155204794030447e325776f5d5af9d21c2f6a0f0f1857da2382581a05ce217d26abc505829c311416c46e46ac6b7a66b0bfbe8a8e99f8dbc9a442e51fb796ab1efc3913c280e8f8a5481decd3c117a2debb84c10265088214aaa87d48238380f03ee8799e8d5ddeb23aa5ead64806541ba31aecd3075a4ce75a11a615069612dca921cfa2885ef372d8428914833f6aac51f115da95199086f50e3922acc601720e38f5cddfdc60d9447a1c135811d280accfcb8de9dd1aa6cf5e6c05d0613664d9ce238e6b0d0840ba1678b9d7216fb613dc49810f8ac9c647a42a43bebe46c56a6c2ba439532d459417e7b04eb7fc2493a24f13103afe39927c553c8e37117e0ad9abda0f216ed9d5649516ec002bf2d6565eb8f9a0aa9ffd6d161cb7b10b0591552050ca7321d95e0b00cab4da702044ee9cdb3d083d60eda1cd21edc568bc65145c89e71ed6722394140760286c639f1a3f2a573e32c429042b7c47523930b3237f3b9975f0b1a43da94b723c782cdcb7702722ee03cca58551f0543adb28e3755563639c3c43cd0cf83a39e45b5469bef0a13bd39051e3681feff09fabf9f55f986685e83e2b0ff9c8a9d47fb13170da29fcaaa420abf94bd21c2de6d191654236f172953bdcf4253dee3e46c0494b06072829cf7c29ea0df881857a9846ef3ac42a551870e0650131a45f9be959304160a2c0e313c036fa41e8871558865b29ebab6029c153aa6682712cf9f02b6d21e825d1b5a53630d889f906422cde9875336bca4fc6f0e10f0713c97b178dc03ed50fefb2555a4060e94deda8ff262252b0b138d7b9ca46b7d2c91ebf86d50ad8a2143464a7a9c608c3d7d43c0aa65a472d114ccd02655e1e2347e783b8adb8bdde862c6b5460666ed168316f70c22cc18c8a18b156dfd7463410c4e773162191b76b573dcb6fc307d023cf7b82143af76b8455257889e326e4fed50f6f524c81229a02474bfa83f786fc3a74b5b04f5b965c06fa016b8661a394d4f4052e2aa9ad80fa69273a653d27513f5e395ac36a1a90a06aaa00f680ef40b47747a277254e06bfef07914497e07cf3ead005a52d107aad592b2a30beb14c457412ca03076bdbe332024b9f02123b2324ba030c47af19528d6a9b17035a1cf586157889ddfa27bc6eae194cfd84a188208036ac13d02f8e3f36daa2f0b6e0075a1d5e1cd694a7db37bf2e285283b9569a164d94b1b513a442eb5ba530a7fa11f9eb3553c99981b75f1018465010a09d13b5a400a21d60654698c0e02254511095bb742ce4a46881e453687d225ef6503a24698402928dd97807b073afa09f4ccc23b867acf01b525dd05ee951be539424b36d4565476647e7e0d4c98fa294497c95771242511c9953ba594026403a703bd0303f0aec6d25e436d0df9e74f21c502cffd967389aeff2deb0c95e9e77dbe131f67116ea4bca182e75e63711615cfbd26e32c44cf31b8a047cc5aee1ef2def52deeaee91fb4a03dfd3242ff1eba082058cfd49aad6102cf3d3a81f0e59fded45acdd45263699199eb73fd2233c1d0358722f47f0e7b1ab420e46001107a40e107fd5221020a427d427f6da2f613847acd77f2531112852b5c457b0c84170833308014a105423dd45e0001a80085e96baccf4f3ef77b686b306fca6410f9bc6badb5263709b5e729f028dedd5a2cfe85ad21f5dcefb6bcc1d7fdf61b6d6be89eef1c9ffb0ebb7b2d74cfdefd4a4375f5105084feb59c76fb09359c7e0181fa41cbe40cdaf784fa47d7e92415085184ba4697de347bdfbbefbdf7debbf761ded73aef6b0db792a95b87f037574158d81350b4b57dc81be02eb055b4ef800df4e42c3226bae973e4f83953a00367e9c055b4ff4d285b3864e044ff54480a55ae829e08895c45fb2e34d396a5136f0a87bf9243067206edb7f621e020d0bdcfd0b5af2f1f0879c3879cc125b65c207bcf592ef8ecd19ff0f45d353d7437a341a07bb7c33f39b1e0f30efa934205093c0082c1a18bf24f0b4337e59f01105620cc5c458208f226a6e4c9304d871e6ce205a10f5220cc5c257394adb257b1be89db77ed4ded3b60619b37509ed73259ce39bb2bdf834d24c932e79c73ce390fc92cf749be7989731fbbb9de50d1722d535d7dd4c7ada197f75d52ff1e508640fab6f0839c240220e02ac1f3f2cbf36bdf087d1f779907922449923c4f21f7686fc1b059287832e85388a6b9554e0cfff43f2119dcc4d3a3c2944d3c4f8f92284afa3cea899b78fa867e13cf9ecf61d987a7900f53be6384d2e7eba1272a745b3eea3fa028ea37b1d71bbabe114a19ff5195ab6c5fefad63aacfaf9cf8bd89a83f87e78930dd44d4ff50d4a33e3d3d079ef2d36417ea63b4b22c490f64b7efe1cc6e42b72c7d4eb2d6507dfe6cfb2ef951dff37ae896fef4e63e87e91ae72949b21b40ddfe02393c8741be1a7ba0baa8a613b827f5af839fbd4a41f9eba083ed3d94431504d77b84e94d10fb347d2f4bd397a6ef807c7959bf54f2bbe99640aa0fb04ba1feeb97babf9ba67acd3f6fc81b4eeff64e3283e939bf42336050b3cf265a0035939a83fc4b9f537e10d8bf2c85fb9bead6e049e066c91a941fd04dbed63e48fa10864b6739761ffd39ce81fb2e3104dad3db73903f1165b3640af4fce94f101a649f92d25152525050be5683a6ff20fde92fbd1a4ca2ee106c10e5e63b68e639f20c61fd1d1fdbb6d71e84d621a079a33925850211d4b8c64dfb7db3b6b7cf295b5ba1fa6712cd5b1bc916afbd6b95a43459895c4dd508351eabac340406726f594d5d763e582e2272a4b4751fa4c094b68e0027efef0583ab281481b7b26000bc719de9c28b8492d3925668c0da18053720e369124b39e06186b7468e75b40e1d22bfc8734b7834ad80957410397815beaf268148d6012b8193089961d254e56b9aa67992a6699ae6533613c08b02d66836c660682648716242b474d4cd48b5e8b12256b3e185a522b569f2af9757e6d102c6a06dca3238016f06ef0bbfc1c1972c06fc06df20be1948db7b059fc1c17aa788ce7b595e5d938d3009ca6bd94dc32b046b11697001de24305a0a78b30dfdd5d32f7217acd9de9e991a181a132fbab49868004789d0510c369545b394d63c693cad020ece38f2101fb0161cd7f29e80654cc014bc46f4500e9b82b58c0ab9ee8257b3106206f9a6f924c17b046e5f1a40ba4d2cabc53130d90dd844f24d9389460d6e92997485b9b1c1ec0b84c74c0fd1527946005ebdb503fe01eb1c9717073c8020f084177db3dd0c38059cf37a9853d4161cd5dd99d4d70c90a21391a7301a9d6fa6c626f53dc2e66b04a5ed32dd0f3403bcda45e6c25ac399d33f62194ccea4faa60955c1db84ec01e71ca68e9ed294652946219df13cc69d8f23f0beb17453ac834b58c1c00830205f181a892ec107ce3d90c0333003b860df04af05ef0254887a208e665541648ee28c762e7829faf1d62404c3586395caa4af699ab1b1eb9b5a8969c41258c7789201cfe47d936943caabe4cc6455765f3248a01be104028c1f1c466e633e479a9f6fa6314cdac9c2ab8ff21d91175df455b60301674c0778730d4d97c760de22c1000b3b1e24657734d63ec8600a418303049515d3c4a0294c7bc49b9d973b2686f1714541059ae59047f5f8ba2623e293b10c4c92eb1a50a6f87f3fc73175df55bd5c4c1b8f9652931d369831a2d7e27842f1f4229ca09c1c234d0cf3624ccb9349833bae692b67f9735ca4faee0a8a1417b1d2b83814bf2cc545a89e1657b51e17e3a2daaff0735cfc6a59719c69adb5d65a77adb5d65a6badfbf04c790c1445c9b22cb52e75699a5a9bda2c4b7284fe3d6cbf85a730dd423790334972ce39e79c73d2d47524d4bc893ebf498ffaddeb0df50bd71f6484d91794fbda73bf8764164f5310368eea6aa8cf7d053e6cd5d2cd8ab70453773726b7ba0551db2166a365136b816cad732b581253ac15d35a046e8b245a26a51c164649862d82d7eaccb52284acadb14c37d89cb11c5d2b8b2e2a264e6d8e113be387bd4ada698392685a1b4bb8ea58a73716c887190e1364ed08af76ad841b5621a0d8b923b5a0d60689e707a9668d6bc2964012135997b4b12bd45a1d356080ad46b4da17572da26e92848658213d2c8aa3106547451292c888130284880eaeb8150a3b82c1265171e2b8a4f5168de8c2814bc490e1b176742cce5bcbc376422d8659bb15c6c25b3ab2da362af6ee893d7154426815d2436374d39e19c5b459782b10ba15eead4d626b7ba8ad6d666061ecd216912c2554acd2d34ae4684aa845ea8129ba614d14c5c0e159d1d5786b6bd8da1d6a5b66ac8f3096c6560b96b526a1626d9ed8baa39684d04e0f2b03df34c131ad11cf896ec85beb836d0da2c64a99a185456db537597454314fadd1910821d6ade7c57bb3dabd31ec0c1e0ebaafb7968aad5da1c67e99b14761ed8fad3648162b47c5d23c291dad7442ed909e36a21b128862d821783d746d9137168b8d75a1d6ce99b546c25eb6d812d4338b35aa27552b03d5c648629bbc297c5a1c599e211b9f2198ef66b217efb75e42755b45fb5308ee734f72ceb95fcb10856a6d32656d096ea25ed93c88ea6f200df6de7befbd77cb422da35a2895fc390e72fa466aefe738c8e8b36f90cf4f2135002ffc1c03e501cd7d37c8e9d03393e72e39a9b5d64057035d3ddc2c5a830ef566ecedc839c78e7debc66c4153024de1904049381c08080728e767c93118f444baefae90a5453874d8c40d36f187ce8f4387ded36e52b21068d0cba6f7ded9a2fafb39fe59b11e517d3fc73f27be1b6455fc3c9d424733e84ff3e778d37befbd37f9bdf7de7befbdaf6c3e77a78fdcef6d383c663a043d9104dc77577e5e2f3e68c6d8470ca72505a2f8ac605223e2770b7eef765267ad0b16ed870f1211b3f7ce06f9c06b931f1629f6e171818979b4beefe7d8c7f84f7e8e49dc91310f930b53cebff464c24ff386adf59317070764960cc28abc54925281aad1a6671401e4c6a21a0452a4428a73442569c24e1ab34f922d474ef5e7f898f44fae2351cdf167e6c8633cbe7c7745860c08b49059363879c92500cea2780e2d6dd5dd6797a8fde77867ee0351309cc19fe39db4ef06bf0bf4912f90e47ac7c14bddc9c2513110f34ed3778951db7479213949f2221bdf4e4e4f6fa78873fad64d357f8e75f0be9bb5823a43787470f0e894d5e888cde8c4a0d17161d4c992f13fc73a423a36df5db9f9e2e40c8b2f97a21a2485188811fc1c077a89482f71008f874d13ba9d266e45c0c094f47821b232922d3c399602484f959a748a9e334d62324f7285d592699ae6499a2609df348bd44dc54d92e4fe34eea1921795584065e9b95ad672519471c2520b2222a2c91312115d1a99119822356d175255563c463c9c4ee850d99da1d1c518218365044c8f9a544cddc854f590bac9f17089972e256f0da92b3294cfe047bf4ca174a625e49a84de56dc186303f2a064044a46d09b8e9606658ae22fb1941871346d44c58b381b5c36e6def062e24a94f5a8c0da29c9a1b2c4b23113e0f9165392ae33b01c533e8e60726cc3c248b5a4882cee2ae6c7c7a0b669c5a4a8a99b26d6dc37cd1445df4ce12934a7f4de7bef0d90537b07aa4192244d4faa64b6cb215602450c1edd8fb21b24688c4c436024c558c5f4fdbdf706cca95925cb5c52689d39831561cb266aaa384ed442929ca72b44929a97da90b589095dd51109230baa364e6456157d097e8eab767c134dcb88ba5aeb93ab70eeb7560c9abd90a855c27cc02c37558c620da8e45ead1af1b927a9e03ee79c7397ab949892a9f2aa68522d262699c9a74ea028fba1d8b1b9ca0d86f9ab840a3ebc21722f3e323b710b24437c2cd911f9805191573d1d5a4a85523ec65514460a287ef81813922ca7dc7e3965e497cfce3eb5638a2c889650067f2a040cba4421c9605d8981295969e0aa53348458e2194642b4c8845cf09fe329311e4f897117132d1ec86369d0928b1a417668b852a09bb4bcb999a9253596b82c45319948a1648294cd49549b2faa489afeb8244595f528b474cc2529caeb4ff8398ec22ae282e4e3529c11d6c346c887169c873bb6172432e2aa9d36d26d424ae2f4993fc7264ea84b28706b20d3a0d65a6bad49cf94872e44aaabaa1b78ba28fc03b7061e2cf3e624d9f7f9e3a0e4c2fee38093bd729ba8eff780efa6727f6ee226f6dca350819b13393611f4f90f023a13b5d79998bdefc73d8a729fa5d6c83c984066d980f3a18be16735320f2cc07e3d6cc9643c68810ba0003308fe1c9b80f9fce718aac97783df0612600f9196acadfd51cbabb1220123d26a435c5145ed24b16c433e3deb0fa8104d50c5b8246c521c7b04480ba463958b9584b54b30c254b0404e942db561efd80876ea0987c7534cfba264c8085be4c63ef1a071b6becd6863aeb4ac3314384d308ab07c581c4e3aed90d34c7b95c7e6a063c586b4377ab44f686c1a8d1e31da142d5854ed78626b9460df80e49a8eed4c93b145c164cd3b620657c3c67aa51dcbda982f242ed8a8143a26a490d82042ed9b887606930d8bc7f40265d7121561b37eb02372c499b525c86855bc80c362e9a46428b53c88582324048dbda8144bdbd34986666c0080022318000018088301499223318ee492ec0e1400074fd46080603c483c1444e26030100883612806a01880011000a118868118042321b2e801f0fa88d9c4266ef25b3125ceb6f377b9624ae864b5607252a5fba5bac39c02852af3722b8b2ae1aa1209d184514d6f540391c6a953e4cca42f79ef94cba5aa34f97d827eba08e1019936051d5809416dfe80b90099a29ae5ff55772bc1632108f6043fa6da858003c0d1c9e84ed90f2f3c7d9ce1b4772bea188f4556742a1e122c8932f8ba25502497de4beaecc1e190d2de1c10fc715f08f76623052e0331a17611df5c69d7f2a8bc12f843144ca773017c472710ae1fab222dfa47b1a6e58775ecb7a27f6778d4158ef78231820058d5af95acd97c6492ded38b2e7bdc8d3906c9f4ea16fa1cc25bb6473756fe8f40a90dcc11e7a4b6d0dcefaddb02c70c1889083408aca6bb366de698709e82f4374ba21996db058f39a7a74faa4e60b88d6ec8e9d3c683f47afc777ef8a31691ccf5219242b4c08f0c31b8e204f489253d203eda0aba4147912fbae21e83868022e7d244e37d5d5f22606bdafe154750591aeb8fe90dc6e9f5f8712155e822887061163093a42ed359452d3a2cb14f21607b6c64e7b85c5b082bccdc10357c68678999f201b880f4c2219b16b0332de8885905c458f726529155fb06bc1e13b4172d3b2e79b3ea6f8bd2e12e7029ebc154efa1a7e3474abdbd7afd59481b854b0b873c18a47fb39a24dceca73a05f8cd34abea649f1cd167825503e935bf13cceab597d1124f1c020415c4a50b4c1282b03a698280cd866ff1ee6cf782cdb8dc434c1d606d2e53c5b7c0d6e1b4cc11a1a5c4ae3c91ace35009a57b9f3514a87fcf95eff129dd55d1eeaf5820c9d936714cca80e35c3ef868be166be6f4c3927d975bee1259787a7c39fb450e55b75fcb0676377d3450e901eef571de19e2467376227a9208788231b7d4c8a2581a453ee48aa56d5c2f577569e0ac2057a57db3c214791cfb687fce4dabde9008db3dc55ac73a86115a04d56cdcf684517112395e315fa2a1278606fd710904c11b8e53154895eea440bc3c3c579c7ac0a921e191a9e520cb31ebc4c2a39be88b3b7078d165f70dc7ef4bef11133723882e53380fafdcb8bd4b34b1503cf72d560a14c022b56c7290d470eac17b1034b65816a571d43eaf77f59404d4a9bce7b1f03f000caed32988fa97b35ccc1505cd90a5c242471b825e79dea381066259e004fc996a6a6e3e2e2d5e985699a6a9ccae457cc41cd3f7089528fed33dacbe5829f6623e1e1ffd2041d3c6691107f119e9231f8bec9eda74d0de4d6d0b4c2e39530b1d72340f2cd6b642960ece433be3c53cf129ed450fabe4d245869c6839a7b71273a425b83cad0e9be2461b280eba84e2541bd0d1fab702e96497394b4496228db914d11ce792c51d4e8fa1642fe0bf392ad4b3e6bbd50fc907690462fe3661f95a6803c90a74926534ce7afe661612485435918ec4763e367247f23188f0e3a6b3da7a4fb6e4f90e8397fecad14bd124d49f91d0a41946dbed32d9665dbe8afaf3b354b1df41c59027a8fa08a9930256c0db0e29a28fc3b438e625e002c748482f7f19d4350b8d653cf8e6db3e184465cec367f325461917d01253556a802739c7502ffc52a7c8c756c114d57542cc5f91fe4709cc5e365d0b80c1debb4709ae3e5e21366143ee0cc7130a02a0b42cc4947cd86afe59ac96d3e48b07518cd1aa21262636d41703399c906a0d3179418340e676e25724aa92b0f1095105d80221663ee77a2cb41404c98251b987e76fb2888442a804ae05df0d46ca3e997af14869fc1ccab1cceed6d9b45835ee4f84d1732e8e704320023e4871e19af3f6385dbc787b2b755d79b78a285bc24e3edbf4bfd0c14b41bdd677447bdef9b4bcf04e60ff808b13de5e509965450e83c91f8cbe636a0ea5a32e4b7597d480ac627bba3b1dc0e4895c52aa3c124564568ac7f8c7838cdb9ad823f7fff6e5a2124613a3b1e42a21c8387528a1a33566e97456f59f49c925fc683b5bf74d1afc7c1f49765b64ee2a91975ae7a8218ca81d1ca1e31a5795b4320c8c014dcfdfb6fb62101553bd9c50fd4dc696e4e494cc00d07404dd474b1d72d15131cd04ba29480a8db3e17e77da1aec072e12ab63c515e18b2030e9828d397a35854fcc592c4a80dcf98375fa548a0c83c295d5da1b5239ac60b5731be5e17de846b8f04736c25c47399b0f9b74aa46184da7de35eab7d966544bcacb6ea78fe2ba191531c13690e4b8a1062b12531d470d1bb83ba7092a05dcb591cf01858d3f6e11bbd5e02b95531311a8ce06c685cd651bdafc0726689813206bf112ae379c815d0a82a624177411d706916e98acaf7c71cd4d26c8cc06da488a751055b4608f541d39b66044cb22977a4c53640843d03c445d1d5dd740718329d3c63060b64b9c230ad0f378c3867788197734aa4ca072e6d24936c7fa5c2924a91179b7caf5d1a6446946e572088ae6155589e67b698f39514be85844e1d914e9540c518e175c9b076678430fc828ff0c19e212b8609f11b10ea35100f7b98603d0b5f6e957f8a784b78a5c501a861ddbf72d4d1ced170338da5c8c9d942ab4d05d0e07447fd533d2d5b599fbd4071f2d98e1182d4ed72b4a4de642e6d253d61145dcc3b7b0c1aca01fc97ae4032d6913d40afd5db9e69aed66e4039e1ea6a14d08c226a62fe41a989e0d58d7b4ac76b284abfed231b287bdae97d690ddc3ef4b64ca75a543a7dad8063e4d1ac3c62581f7815ae3115341ad533a7cb4f26835681cda84302a05f84935e28c50d9d231d686f574eb79b6b46021b1c151eed1d860e6d01703c6d3c3ac3ed6ee14f434eb13e71f6d9cc7b214a004785823cf501e0761abe3861049907205cc39ec00ddfd2a2590f83e3d6963e3146d045c833314d1ec56bc94562b55dc3d8fc1227f152cc12ade6380f8cbeb5ca069f02ae2cc179bba82ecfadb598c9b1f5a089e0ee2b3229f6cafc35d89a2a184d796ed1d41a8232a957574e5eeb588d7cc62ed2aa360ad8680460d3949daf09f5fc1a3e18ec3bd57f02a34ce9d50693ede928c3d4b53b94d95ced1650158489605e162d792daa9642af2b997168c534a413d4d94274694ef2545d1ab995b9364f438686e4f8dc5dc28af82565ffeca8c522b1b03c81f58636083e23921f6c0718fc058bea333fc7e933e422662e989c3dcb4d12b07c135329c1b548ca85dfec146359b503b6cebb9b1a5eee7c4cdf0cd3fb65b04522454fdc6298b1f8e4f43a2eec1ff283abd454e5f4e184f5f180b23107f784c530629f1b229cc08cb2b00efdcc8c372f0614fcf6c1e287ab915e37f836ea23ce0170736f94bc8a2d6ea3e134289901b4dcc0afeace20a512c23d675a3a408e116f665aef220ceee4f950fa2ff9938c10ac390a09a0f18556033c0582704ae35ebf306c712cf6b69ad7c80c202acb889aa9816326e272104f9b0ba4744c230a4ec2ee8d05dfc317b057bff65b8d3e1c8ad1ae3cd4b49a56de3478a9f3e1cf61921228fd28c6eafb46d5e6935fea1f61ec16f32f8e442ead2ce70749baff2fe056c4d33a2b9d7042b34949dd5bc3b274c30c1148e0cfaea5f8e81c02e6e829e8138b3e6022d06bc96a320fea810bc866471597657c3b35da96984ed7a7f18c38c71f20dd8916e6568b7a2de3d63dc899e77191d142466a61d1186cc03cac48f94e9883e768253e303948ed639e23ba1376002609956fed56c1c18d8ff4667d36d406946fc0574b3c181030f37e369ad9e7405dfae499227083cf76e60d40d02d9ea9d7854e3c5e4d4b88f057f285519cedff96cf58c150eaa1ddb6a3d15d447713da77b66ef839ed936ee57db1298935b5df4df6b18f890402e66466bd25dccd64a63e77a994924a9aa3d5d7a1cc88de48dc34c17cbc848af60c6bf49d55bda413a064459548ccc140c141b58c98c29eafa6d7bbf8b9df28aced0e870e2c241c78c5e6410e3299eded3a84e92ae4c76f0a8d1a8feeef24acb1e56be7365f223712bd95dd9a6eca3e99a7a1715a53a8fd9bc22c2a600122643f46a278b02e497a868e283355af3a8a07bf893ebd5265d2e51c9a0a25f954a54bf0ff38962095642b372c4e6994443ae163722566ead12f08ccdc7e4f65244b8c236e3770322f5436dbf2fda073cd2b81d7af6430fcce4d54e2d268de57eac5565624729b256831176cef09ac3b80cde1ad6ab45f3b6c09b69004ae5aca169cc9efd40f744fdb34046a36f5370db0b73c804dfe094a27918cda7b877762317b532a6ce8660b2333800fbdaf61b3bba73d9e1e2bddfadf5033fb56137f81f98fde42e87c965fd5f694d6f15e5da33cea95f9c0436d860bafd5f4495d3fe52b268bcfe455d31cb8b69874b920d2b1fe6aa094d104263915737924a0dd4b00fd659070bd4cf54a8521769d22ece09bea62d9c5fd8075bd7d64b6baf2064ef6ba22079b918399136c537ad7f2b541ae36e88042aeb63eda74b22bc53ecc55dfc424fa23d02c371936f11ec4f1ecf99d6f89d82f36dff29e5e8bcaf7dfca65cf737d99d1c3ffd7f79534868cbae0fb6c024ca4eea87032e422b3e90bdbd899add83f28322902171447b2a75563979de5ba2a3805c0b17dabb5f54de48f14642201e445ba16605b7a73def458561b0b5545f6dddd33d7afdfa0a6d81de10fbe3bcf86fcce92d706dbfe9d07086f80c4e88e2fb137441c51ce2cd6027b343e48261539e397e466ad9708b8ee0250dcf590817dc766d8f006b5980e3602d261be5935bc7cbd97e62376e29b4da3b7c79d0313894cb39034fe518c05b09916e732675d1e987ea7616aa83abfd6cb7aacbab57655b6589a5355d2813b27a681804a59b4d8b2ae1f81bc84a72d25a127cf52f997d4f223acea6b0400d5539ce223e5bece1a591d96346b6eb5e4fe6272af5aee777a243206bd7e463579264f1256ebd276b0fb406935df592b15bca41de8009bea53b88b33122950a980478f1f5461cb27432c675a5b1594f24fb6d8a31551c21dc3808a1c13447086010a091ab425845c7065f45536270ffdf0f013b1e6e5ab9948153097bd59ae8bc0e7468d3542e901e93c5bc71eb62570e742c3281c8bcce54ab3b35d15d6dc93baf1fd499023a79c43f0c8b1c07a2848c9911c88f912fa0ed61bb0b14db601149a04421a12290df3a1fb912c7489cb64042244f1ba59c16481b9795a3ae0e1945d13c855f1d73acd34c8a8c60695b1972ec870c10a4eb231969d3bccbcd51af4923988e8b23221d86286978043d1d65db691b19c0f1e140769ca8e3580e4d2508cc31e2a635a59623d4a1c75180838f038923dab176083bb8d951e44cab97158e453bcc17d10008ce01948e21afb46e4a8dbb423b21fc8e36c714b959c39cb78aff731a79d13b3ae62160e0c280b64b95e3324af4b2b1ae6227d37539683204481c7161b40d2ae803a979cd777d1fe3a500bd3dab325188eb1c6573b4b80a899f0680e03baa1d4e47ca01d0e45a2e1aba60a1c081fcebbb98515d32924f5b0ad8e1c49174a46837f8dd0c49bc73301c6fde15db01b7903dd3064746be348d90b248daae852498a6e3a2b4250d68646480562ea17790e0687d29657fb440c98c834895369a2c3bd6eea8b34468e751ccde6969c95007fa7c1a33a176c03966d721cc24d2604aca62d0b44428c7b70359bbca4f0e1e8ebd7018f2a721bf909c68b964bf1de8b769a89391415aa96c6b8d42770c88e3d82d0d9180e7e8ab31a486032c87de5194a3fa8e8e07453b14ea858cecc688785cb8c63b5933939c59879878e478b6e39013ad3659e178b46369621a014b593cda522ec841c44ddb462942a51de5fa1d6535689b9291304d5ab239ae3810d241b2a0e1900f4733079a721071d2fac8d951f310bc84053643937c7d6be4cc27e91fba0991192dca8b211a9a3464844a33175ec70607a1a38303e9d068471151bad1ff1c4e71bce36d252d8a41e6a5a806ede4629d330fa4fae62e32dfd1463f8d2f861cb28ea6c3b4e3dc8ef4f534c6c888172d52928eab1ab96c72e072c0734497e3b40bad1c89ad8324475bab98e64b032488e12884426351315641d312147690fdd1862323c1e0b2b3f33487488b43531104ec2071d18629905469e7a4c7511bc3fa3832e9af919ce5f638a74d8ac8f5f49f1051d0402f860869989c8c6c696d511d203936388a6a928277cccd513692f645ee396a1ddc8ea423d2a1ca31ec60e280d31a09bda0bab665b8691110380b529eb622f023cacff2a20d9a562223765a5a421cd1eb6a8092b22d16ed1bb1aba5045c93253cbb7a2ffd9c682dd159701933830f388bf4cd31fd7133980f4e73a12758051f982f9a6da2e904bd967e07ec1df650489310ccb0066cb62fa16fa23cdbf985be4542b315b328960ea67714e9d1dad27447b1e034373139081cc0e11841d3ccc29b638783d8d17c67b6602292a675703f4733bb10297f875878631199e978918fc61330390699a145c925c7ce263d42d45624ec1c6ac7908355ccbdf54e5bddb100af9a3469dd94b7452d2addd45636730e64db3abcbac3e114c03a3c5b4d13258a0eab43a31173f49eed4b46129045e36bfa528ee42729a337234e728c409ce32bfcb90bcf399ca00f3b13960e961ed9709c9347d750e6995e3f02a4db1c6597b44cf285a3e93077bc716c1df2b568413a2c38be0eb443c71c6539682b1294a35e384802dd11b698f5655e41a86f96474918846fc062149350cf301a593d1dc5f24ae56b03d31989fdcc0742df68b1d8b5f98e9e426c462962625a1fcfe8932da2f7f144de8357ca65d2c8a30c306069917525325e202362337b159e42cc5d838141323b1a53521b44843582a660a747865a5243251dffb1c67e36b07b549a30b9c1e8a8eaba6afb0683c063b8b7ec4a479a4776c0ad401fb33b5490d702d89c6b8381c3f8422518f0da00a191a15620cc9f6545133b80e48588b3111760587259dcc1f4dd691b3914b3e4f21e49bbb5f94802c789a97e286e2a226bff3d884ef4023639d13e5a0bcda23e98162f11af665cdc0f1f282614a79991ae925d8b7579a4da2de9ca2d8a2b64c34b65ed02333ec1cdc43a4c821e80858c8419940aedc46ee8488b0a4570fd7e987c70e96b0453baba909907e31da86ce6f03829b20ccf1f07e96157c7daa25ed4f82dc00f9c18584c99bad6585a6d37c2565a1ea4f2c0d0820ae41f537dec3547d04d3bee90ac6d1d9d6df03610a044ca4a0fc4981169bd44cd1e72ea576c9ef0c72ae5b2a27a50f37b9468dbf3aba5e08991f59dcf907f86b46930f9e7a904ffe60c15801f3ca77574ba740b7a99834f73bd8c671b7231d7db35fd2d6e09f2b35fd7559ee3c05a593691b4a5d0d4138e03e3874cad46da2b26cce149d5d70ea3f522f6bdf686f70ae0715290bf16872850f6448d12778d8ea21957a8fedff0fecb96df21c771a6f86d6358d4a89236ca83ed368cada272d0d66d94bee420516ccd6327173b65e5de00b1e4f926a0a8854f7b47cb08859662333fa9b51257c4a4a5ddec6bb4c763760c46943f8d9eb6037ad39ff0b933101f90a926a0a6f871fff3f62ef35e62b31f290f9589caa36e9a7ffe2df8f6ccb334cde89a3517fc160942e65668ce57b5e14c744fc699b6878d25c24d69ad0297a6cdce8419162d2c7b90822bacd2b78f6a2a610445ec0f183b7ff054ee3429d43916091a6645529cfad4531810ea9e48eaae559b2de832eeec2520caf276cbcc6c07d9a359112f79c574929d5872928d9db298bbaec8c8a6c017c6ef9409d7ea94a73902e1e56ff167eed2a38fe32aca9c31ea4676d39b44220e59d62a589d3230a2931c37e4ce23c125bb72422f28a2602804755bedede7519aef4c222ccd255c7765a5b5fe8e599d70a565ac55000d5e6eaff9b05dc8b53adf9580291b04a27bb81cce7658148bda2cc7fb33bc194e043157fe07308a5b7ea413d5c3622620c7994e5464357a98db8a1a1a2838858a198c33af95026e1bdbdb3dcc6c9daa24f7ac629b568347956dc3962d40581bcdab175930078ce8242b8f52a6de942cc7fd093728d65c117728dc18e031b979dcde7718367c34107880132b6f350b4f01c247a63a2fd68f64c73959f3ecd65416a1a58e2058ff6ac5e174b5e5046b6171dc41cf0577d4072c5ae0376d99cf99ae8826f271cfb1d8c4c12242090311a0848472756dcd09ba16ed45953726059c2c4ea1325823911f68f9294f9f0b36b16f422ef1be8ea62280bef6cdd2ec8812a3eeb3c04773c56902e253b07e011a308c87cc42a49e4cd6c011d4f95bbeac1e80c282eae4380f08a552525958958d655c5512694b4a596907dd159fb26809809b5e1f1e2a0489abf84203f0981e1a1ea7a6021fae92096914dc487d9c42555c0d4eb180dac842258586bee2251dbf4fdede971e444f581781b10b3585a9e2445f1c16e6cffcdcbf4226db6f50a6ec9c96c1eda2ab5674887336b4e881b7fe249f65c43895e1fe4e2ff823e8091b405db30bc958c0b3aa0e7c561a2c975daa660672294e96b9120470eb85afd288897af039444cd38177c807422868de667ce602fce60374f412d9c8b0ef2f3ab341a96d8c7175c128918185c785b0b70fb51ea462ca3126fa1d1de0c169abad7814d1ea41d0de1a2534e9d0180540215fb1fc3227caebffc977732aefc7654725422d1548ea10e8b7efa09973ffd3fe75494e791441f3648b6a3ae093dcb9a282bb1f7a35dbdccb321c3700f41c500a406814e6f6ecf806d6eac948a85e4b0c33435c279f5731a8d148c168cd482fbfbd16df1b89a899646121b61312843c08dadd0aff701c4c23edf367c9d70352041abc23c00e449910df1cb903381c8342a4c4ed21d60ce1466ecafe686ca2c1f0cfbcf89e7871e1954fbf67e6baaab3826afe835f19ce03546ed4e32be4ab7e819823deb3f3910332057d5963d8e8ff768dc03969cf036ba1801b5dcc017bfb9aa9de70d5fa490ced695e29900ec339673488917ae9223d6617fa48bd92d2f6955f14aae00029311a628cddfda993676735ee22f8ec430d5f2cf39b3596b984fc5c399388dae81fed3d7c384214baf8e6e53178d2c8c86e2060bbc23372cc0033900a446150ef2bab12b606c6ca281393d3312436aeb26189a171a8c0997161b3d57786899d16b9141cbd140218c152e0099faec92fa7eebe9073a8c0df8c18d240ce3375472190f9379800faef5e0224b6fa41c0dd126f8c46639cedaa94903ea03af43a15b31ddc090f221293bea3593abd58d4662ad339a9b3b783bebc4eef3edf0863f541d41b6fe47b5e5a354a86a61773c2d091905dd84397a91e2fd11c9a91045ed31a3ae98bd8eb0639e59974f7fde0b169fc17da925fdd0507eda23ae56ce20a8dc7169387a13c3de87bd13b96ca6f37f7d3ba36efd8e9bdee06532943f7f17f3359b4b539046231b2a492fc6a2b66423b55792b986400e5ab4b83496da4eacd7c8bfff2ec2c164f8df5b871c035273ab61a3617a4a8cee46661c1b339387f1f0a7436b23bf14f00f273bcbe0f81dac72507e90fe94ffb0f66e75bf37f304182b63ebfac405686a0983abb03fd431db371ffbad540d293550202dd0fc4254aa2aaa023f9b708fcae47cc470d9a9b0ebe2b82c9a75050d7513a5b3ec2498f6f25b6e412dba596a369d87a302de615692d34f104d36efc075b8a15ac7f771a39307843a4b1426a1e5b2f45b6d0a00a5014eaa1df925df2382dd839762c6e2c19453f99be3f00621296f2095a1a0445d2402d01be483049ef0d48cc7b2b8d5265830381b7efb8f83a7cd432332b290e77a8011f8428d50c42090531334043de05380282639ce9f41228f8f1106de23be5e0424dda708add13229cfeaac24badc282593114b61f8614e5c73672c9a43bef94694b82770c9393ea09fb41691aca079a9377dff2422a063fad508fe8b1fc1db164fea72cc1d9d4c716e4949b169af68608999494b2851796aa73cc665a21a394516a957548204c7905c507467c9cab076a3aa4e2cca65e2c2bba6647fd859479e7687199815a0bdeb90337cedbeed15b13f76be5cb63eb6625e70674058c29c91e321107b1c0a12ff76ac71fe542d3a30e0a9e36de4e833a5f74f7d287a0e225d9edca2ba4824594575f543cc1260a1ed440af351b19799183db8de351cc1675b49c855ef5abe4ae8b6a76f1d83d231ebcd576e97fce39b04f67ccc3b9a435b336b458dcbe7d88a0b2a211082de9abfc903e63f129a201a89cf9de123356ce1a9bd8b078d61d0ab4f908880672862c854916916d64bbaf48172d28d8cbe272d7706477f569447058c81580e20a8d2ef693ee6704402cb7523965c44690ca9959bd33d9cbfaf1780a26a754c2905b8fd94fbe3d5e21e4756dcbbe3e893d47c3e757df270cb41f9d720789ce9b345c88b1431c25e7389249e7b49fe4361e1f7145ee33f620c63673f065b049886e9006df39f4ae374846e31b52e1425f594145c9f83abd2823576c9b277ce6ab5a9a0f51041f083177992d4ae45622e57a5a76ea55943af2cd936f742caaf6955a6fabe2b7a761da890be11cbd77d94f66a8c0ff894c46385cf0e52338b3d33969c2435a771c123d6ff51545b85687ffc6c8f450bac9a4415ccc827e4d55dd3420742dbbe4e6b2379498a43510d484028aefd9655f40503a4e0755203e33911545b74d2323f8a564ced74e659d4d3cf31537309cc312a730786e85e75c15045f91c44db1651ca8b8e2585ccc07dc93114bfd38c10aa05823c815c8e806d0b886d88bbd9827242222b4a4edbdf7965b4a99929401a406fe0522063ecbf62b0e6dd243b632199662a51f259d124fb7ba8b2146ec5a9834fda51fd3a65b61967862e860e85ee878743bba15742e743a5d0b251def58e874743926ce0a9d0a5d0a130736716c49c707d9cd90fbbb58d7587dbf17c67c29e64da79857dd4f89289104ac7cc72231a3c532693c4f62b61acb6cf5ca72c96da3c8fd96a841e8b7b05125daa159d39f12ad12b3a61f25da25664dff49b44c88368b6da2245a2748a2d552add0275a1988f6caace9bfa2c5326b2c6dd6f477a23dc22221da24eedd4831a2c53269fa57a2d532697a1ba7d532c3214bf31b3a2d8c56c518d9d2fca6eb6c673bbbfd7db2dbb6af395b9e62dec6168c34a34fbf244bb5f7c42bd9a8b33ab34129a510d872c9899ca86d34f8da3c16b351abb95f5babd56a79fea5322ab3b66e979c349a0dec92711d8923f7fbabc79785cd1afa76825e673931728f757697d459160186f015c35f8417ec3b5991b8eb703fb3a6be4b28b43ab976311fafdf2b4dff66b11a6fcd71fe8d67cdac99ef955c388464cdded4469b727c0c67cdac015fa8eeafef0ddea8a32836f832e1df5e47f71cfeed4bc05b37626ec40ebec217bd41473a762995c9105e24127009780ca149fc02b7afc51778838e1bf8f266dec09c54eea64183035d3184b4452efb4871b75d5b7d7647aa20a0616e8c760c93555071d8dea0f0eabf6cf69f33cc24a5af9afde7c47356af60055fd4bdf43a480f3e05c75208be08fd7addec3937fb4feabd66be77cc455d6f6fbfbbbbbb5519bfe755a7eae4f9eeeeee157c6dd57ffc27cfafb5d6fabab628536bad7dd94be7df7b5f75a341f3b7ede5d97bd74e48cea32310d030b98eae9d107c75d7624c22efc5ef8d3338df9bf3bd77e3ebc9b372a25742212746c69f1323d75184be31b63a94e77b604eaba0e2f0fa5b0106ab4fc72ac6c813f01b0b9b735a18cdff459e223cc1ff336d02a6ca4deb16fdee22cfcc563f5955ac6eadc49b49d3af125d93a61f378d99698380d9f2f7ea8336bc8a37dfb8d9df5563e290be9f0113a7f4fd0b9838e1f72b60e298be1f67e29cbe3f011307f5fd214c9cd4f7dfd880f0c1c4f9be1f01079838f7fb0d3071b6ef7f1a1307ff7cca009d075a800e8d11544f4e21b2ea73492ca2436384d593c4223a218cb00a4dab4f718f124f220958991b8bac46ec34a609027d8fdaac225599c680409a1a675497e99fbcb02492c0d0b3ade9389ca948670dfd4db4f5da8de4bf1255e2749a0dd5980aafbe574512eedb9f5b1852908412ee8847ec346132055f349748da60635269a2f0eab2ffabcb5da261f2045f5deeb203b9f75e5c6f1023456c5f2f1b11ef4e077a8022d65afbe12fb31b686103173e3f302180142d44a9291105134c96a84ee026385ce0a30658ac0852e54a14363b4cf1f282225e869eb4d0fd98502862300401d921080b42b628aad2450b9638a10312a46f89113a82265d62455820841519904a2d36042111cb410913a49fb089fcb032c7c124a4de1ef04890878122528468a155d1b2138609213c3c1105480f318c604b4ab880e1a103b642173c545041c4972840b32b868a18c15abb05b104f6ef7698551f17f8b66ddbb6f5b06ddbb66d61ade2de7b71bdb7c80b3f4636285122872f2d58c10f3bb11e2f465d980021555875b2c327cb0d52aa748165470f1d6278c2880c31406284bb448b000061a4c2e8e10a0e5c6e60c2420e270893a48995245b5828024c72b7e766a03f45dd4f96cf86778b98db4304b7e026f99e9ecdb91bb87b97f4d8d161c98e1b040fb40898ed873a9d0042872d46e030c40b1419190fa513584c5982431046d8871e97f9e4ecb0010b1c8274f019428a142b80445136914393262e94827af0067270820635f0a146a5070986604228880a5b808a2c519d40820a33459229acd012248be944902542558e9882851e3d3a08a13bbb3b321092a4052f4796b811c2c4cfcf112c5c808192214aa494be1e5ac90d384890d4f5c729d01e216018a26746c591142d1a7882fcd082213c7238950414a1658523454811051648d08c0021030f4a867ef878f0cb640a135d62adb5b64a0a66a0820e46b4cc404393273e3b4d68c1c38e244962e0b7438fded1c124e45d090f064c864cf60631ab9f4f91273c6badb5d67eb847ef601d86fa8795390e24d8212684a4882341c050c03264040b57f00064b405a1c31d79c7e2566c2ee80e8c14b1ac2a397069b2d3c54a0f076a447686e8896283229624d1c167a48847200b248ed0a2944aae98618608b9520ac1e30a254cac7cae448f0da4f0d1430d4396b8228a00cc00564397253160f992e47b8020dd7bab77689b60d245a907ace2c9151668d8f28317205ee082082aa4d430250993f2f3a30e3a2e6e3726f3ee7b25171021592f8e4ceff5f0f5cdb83797ed7badb366fec5d93ea5a909fadf0658ebd5ab65b1eebdd45e4ba9b781beb9df97fd7b4b12b0ce518e54bf46e08e3334f7905767ea9f30e6a2f073da5ead47af8e1248e0e76ddbb66ddbdb39e79c33e319fb27e0bf6fc75c14cedc68756b7650077577bb8fbb7b2da245b556fb437facbd5487eadc8d9c433e61fdfb5e876fbd173f8742bedf3dd7a932fe1c55beaaacba621f6ddbe4facbc1d65679feecd9f35ba86fa63b6ce2d03cc8aa7c7f3cc1ff7d246dd4afb4bddabb61aef33e90540a4d27544ab58a61c9bc206dd87166d6d07f1767ec0863d6d0181ccc1a1916a869faad60a1300b97ee92fbc916503fe941d7ba6524f6518e2ad3d1964684f46d6dbb327f866ddb5c3a9ee8e04ae1c90d4f5ec0188309bf3c859ea4c024dc020a275e9c60b182932732d9baf2c1ed9cc0e0e3871552c0818b1d9eec54b1c3151d5694f8f0045f095d5c54f01243163428b1640a2c02e0a506a12a5b5850e3a188f739b95ef0e56cf5766205cbcc10217ee2520188ad8a93d80e273a3a217c29184e886cdbe64418b381131d2f4f21273faed019208a92d0c035038c710da125999c658d299af870c527d7086a422493618d2a9a08e170139e8c31c6b8736d0943d6d33c859ad0f24c9e424dac684294c9965dc115c415c415a4fe9c14e32f35c6ddaf1bb5ce1e326790ab4b375ab58e2b17fe552ec0a01b2363d10406f98de9045653adfe67d254e36add32ea56a5771b72a14c1f57a2ae769d37ed68b7bbe3cad9ee7ab6bbdef66170fb30c891ba1247ea4a5ef899bcf0338127122a5553296f9afac4d3109f4c1fd5f34dfaa9f09bf455b5d23f32027364d4391a560b02b2120424442b298f0f2099bef3501f74088dd149e9a4745213269dd43fc8b44ea04cf3ac230dda5e6db5d69bdaf66aafbdd79bdeafdabb7d77c31ce6386fca7d1be6b8cefbbceff3a69ff775def781a412a954f2a625d2078239a452f895c09cd074329d4edef41403be502c19f0a57a31b39a99f1a6339f09cc711105be689ea90f05e6d06c55e08be670a55aadbce90a93666e70769c329844a290eb93f55eea24f2845cc7a6750bb40206752ba85ba09520137832d58c4ca61ae4f6b35ece76c30545e8f37d82af188e33ba21e63a7247abcf0406996a4eb38d2b1957ab7db559d3f5cb0fa86f5aa869e8e7f01c60c0181975e9c2854b67c99249ae46abf5583db6aa81100354cdd69f89737f4e4b1be2b8e8826c8cdc05e94c5b5142b8e8c924e98854739afe8a92cd9a7e52cd5d67d6d055eeac344d7f17d42d5305567014d4916a41b9bf046b1bd2d272d78c4847243016d7dac51392358b198ad07fe6b34c7a3337e6db7fcd1bfef65f4e69b77f9fdba60ee6d4e94d6bb5cf72e738fb9e6d6badb5746252637ce365492023dbf797875ec1577d5bed28ce9a69c1d79da1c0f6f7757023bee0cbe2c81bf8aa7362aeeb3a8fe3ba12b6bf4fc236861082d3709df5582caf84edda8fe3ac7ddb8137faad676badb6473c6be89c5e07f6bbe86df40bc30f2461fbfb81256c23769a06c106cc6cdf6bad954e4caa2f42bf4040c3f80dfb15cce9723a14ba5cbb6cc7fa9d8b3337e8cf7f65effb3098c3657062d08e23c8b5c7dae10ecf2b7977035f348c8b05e1369276e6356066fcdc774fd6a1231a3431f75329a5947a91ff147557cc53e4ee750baab5daa3dc6fed256fcf88c1576fa2cb86103f47bf0d7cc096bff75edf7beffd6eb7ef74723f37947b24af9d43b98e9334012d77c0ce408f720088e5de70f6fcfba83d42a9eda1945e7b848eaa1db3d52a9d95c8fa1851e64b62b6689545ab2b8bb0be6aa9a6d3365d50ab76bc4741d6af5e87ccc77c09fcbe0492204389494303be6428315bfd2f8ccc1689239f4e3fef8c7d968d79d68802998f7914b07ef5384678c1c91076af7a7a7aef650cbd0c22bf91393de9f9fbf9bde89938f63be61be799d3f4933c977e96c8173da86e28f7cb8878d2ccec5d12a791acb96d9a945194fb6b9849552c04947cd1d3cae48b9e2c4389dcef89a48c5a6e5807ec2c8ba49de5fbce934956eeef5e4067eb7e7f8c8827cdfd9578afab4b48022086dc8f29b6b307502852a00020966aef67d67649114d739ad8f77ddff74d1293616651af33cf149648a07b9caa042acbb24cc57cc462b118ca894edd6c369bc160391ce6308739ec7af0891c9850c6beeffbbe8f068d54a6418386e7445c89047a8a730f5502955e7a65798ab5cd7dd03d0e9bbed9cc93cc66b3d9ac2600334454a6b1582c162b3dcff33ccf0412939e0c892611e7315c22819f9b30179640655972a517f3118bc5623127722e4ee4444ee444041800cd29d3b22ccb92e3388ee362b1fe582c86bbdcc0cf4b5bad61ae042acbb22c633e62b1582c56801a53a6b516c618635c6badb5d2d2bf2743f7ca72abdd0747f2fb52291830668ca407997471ed4aa0b22ccb92c65780cf158350867118f6586badb5d25a986b462425e9a5b27e3bc4caaccccaaccc82b5568dbc5ae36a0dd7da566bb7d6ac01541f150f30e4003eb91f013d1f7c08f03ef8a848da24b91f84d9b401c1c6c69bdad04ab969adff6e1919fecb72c0dc8d9616822a0210df974ac180316386071ecc26e5a6f98dcd325403739403663b5a1a10b48d238179cee8905ea0e6b54f9aa24d290e52c0408a0d6d436fee17ce1a6765774ae32f4295f06bdc6ed539bfbbdbdab66d45f016eb9c4da34a21626295a790941ca9396d3c9bc2b4b9a6ec9348a777cc96bfa7306dbc27bb2c7bcc69bc761923db1f96c716d9225b648b6c918d75cb6dec0e0f39774c9b6d67b6bc6db658b77ce3711a7f8cc390c57a72e3c9fe4162c9ee94626d53221101ca409eaf88277b4f264f3db6e824134db56de73424c7dae62464b678b6d2c7f6b3cd7af22643d1668dbfab896b47907e453f4020d91fac617e5d7cc4401e608e0fcc6754e43726a3a6f13781a9e5b0473c60d94f5727fb0948690bcafe3d9a6addf2771911925d4996fdab58e29935def1b8a084f42df8f294ec03aa8144d845ac0c954f4c2129b32c82b67956926611662189b3c3702a86c056eab356d2cc8dec23a981dc31d41042284a91283f518c4409a2e2aad2eeb59bd66ab5da6e6befad52a50ad6010404d45eddd65a96d65a7befbdb70cc9eeb2562bcb320421b061d2cb26f168b454cb64a85369a2b11c4e22a2922b4ad8b4b6019b0a49a1157f79d2bad5a6e977551192a97bc7b05b5e67297dfb369cd2896f525d71882bf96556ad5caab2fe5b21b5deb5e1dddf1caf1573241c84852839d48812e547941d61a2b0f0419415a07cf181d204ca0f50a2c0a1c4c99427a4dc40861d7c3049b2440d5480c187280a1426840881628a215c7c6ca161e39144132d38590114503628472cb10594263f4011820a28436a348102048a0fc6b88616473c29227c42e5c993274a9ef8f0c4c8132e5052786244c3a43940483056cea13371aefde0a88f8ec8a6e11f1cf90d2804cba2c325d68527834632104c4f6e2f470706b95c40da5aee1a9337b103735425246dad036373d43674acddaa24989037d3007ffb2f774fa57a7a771d433a437ffa9d359bfb66c310638ec5721a7cedd7efc01bd662f730b46fc5d7ccfef6fdab7df5d7f7c01bfd39d4ff357d037330686b77c49b33eedd36cfdbbc6d768b6cbdcf3c076d78ae1dc2553e127a23e9b3bcfd06ce70de73dee391286fef6d9ef75ef7df515051d1cf51deb6a794524a3b286fdb7777b75b9ebcbdbb7b2daad5fee46d7b6befe68d2e1f5c3e9070064712850c921e67d248a2f02a3de91dbc511a87f2f6a471f3c091eca3bc7d4fde7ce8a280963be0335a45c741a25eec6f30ad129261aea3076ef9d31f0ccee13cdc077620d37d68ad7be4f2dc1ec7c1699834fdf7c8b4f19dd9ea9eb6f158b770f0207ec3c421f90fb7c16b701ea761e2f0f8cd9df90c2e83fbf01d6781f7f0d8c4397d5f1e1fe24472bfcbbac6ca149654a8cbe1adf348e0b7bab33bcb6d0a4b5995425d0e6f9d4702bf93292ca952a87b3275e7b0443309ec38bcad2ea9fe9663aae5d234fd5d8c2c98cf7179b46e081ecbabeca32572b920245b7dcb4e0aafdfcb21c3d0fbfbbc440116ab7e9fa7523865fb555fb59672ea0472e8f04a36c6afe44ac281b928ac5f5f93f6c64d8eb6577b378e64391474ab3ab946427a42ae3cbae5321292ae93ab1dead67db269354a2985c01664a356547677374f1795eeeea08d5a2b8d594b7588f2bde41c72175d3c84f8e97b98cb9941216fcf8d240ad9e29fe08b8e38c727e8b88f7254d9bece2adbb169ddaa638622f4ae2f3366b8b4a875868b0656091645508666f8520be23048a2a33385063d9c7c6006430061d245861eb4a82a38608a18aca0072e41642cb860c5ac7683293208c1a2bf52005c78a122054c901f2332b4dc1ff56adddeadac137ca9f2cf7a37ccd93be9db0d739d573dcf9b7a1715db6a459513e47ee33aef9b614ae9a434d35929bd97e3603ab9dfcbc123f77f3a301fb99f14eb56d76ef693c4c9cf0ca89cbd54d96e5bd1894b9753113d11cd93d1a97622a2311e1f407862436431ee6d7065109095a0b2a28450b46e35aa441da18c50605047a85a0e18aa0656daed5eabc7d5906e9c17f381b9fdfd893cbd9f4f8ff4c8b3fbf9b40b2979724d441679621e21793e9549318189737f06c14212b325666705a4faa22292c2f22498fb37af4fcac0e8c84292fb6fcc96dc6fbb9ac7ecd08c579dea8bab88e4fec6292c34538cc390c5aab4d96c369bcd6030180c060b4da7130a95dade4ba936185f9ddd8fa3194646923bdc12ee9480485f4844faadd7321392704bb893fb6f09a8495f48445ad633fb2983cab22ccb3236fb39cd4eb3d3ec343bcd4e33d43755ab1903be62bec992a93232de54e67ae2cc190ba8f32df1a8f07e7435104bee775027f7f7b78466eb51e1fda81d35ac75623ce5ece74474223a119d884e44b9df5b792f381b703c602db48bdccfd1b2b392fb43ce06b9bfc4f190fb29d65206d186888a663fb1582c168be5fe18df8d6d52ae972602d318699392fb65b6eb25d318e5a1b29ed94fad2ccbb22cf30c8c183138e040868c17ab287a5391956f0eb985e836896e0ed70a99e034f48b6a47b0948ceaa06a7e430393a81aaa46a26aa8181e073db95fc6109fdcffa99eff684af6a25424534972ff989a75503be8c09b7630c7544cd6e1525c92461ead8e94cc6f68b8ac9c05fd94b98372bf27e35b85806652065683b0a30c6cd6c8c072abb20ccd02445c2e5091e10b959d1950e9e1e241258618507981082a3bb45071a18611545aa0b202959efc224f212a52a8fcd419256a8f7997b566a9ecfa84e4a4f9f86cb1c4124b648fe220f25897352a2b793166793e0cf001a918332f9a4496808317322c27912690c18a59a92a893cc15b128902d1149648e07749640ac68d44aa207b1d8c9844bf3ef1e60cb2ce72bf07a3cee84cbf7099cab231798e198ab0aef21ce7d7d9cd02cbfede7d96a8ca30643a66a54aa19e5ef15b64a932e63aef033d18ef5df1c55b51e6618833a5272d4db4df228b48768a0abfc0c8a40928fb77ca0434e33d79dac9feaeda79f17d5d9db6c8806f7f46245148585986374c8af138c7b00f4324ed2acf88a4278bc9b04c7f861d6dd6983ad8ac716109494f56a24d9ced5fb06256aa9413911589bf2914c9ee88ec5f22819fe73df0fd1102b7a66033943b52e5e91e510dc9c499595845424454ab599b020963ceb4f8a245192abb5f8bac49f38ff95a5ce58aa4496a619d911a6ce23cc6789c4f25501f04340c9eb9f5b72269366b9c5682b964109229982a45cb4e9b38a7ec2a992b89903ea992654fc168d9555b89d6c1545675a9b3c09b33c2a7a5a7a4a74f6b13077cfa5d4e9cefa9f7f49d68e2744f4d469c7e4e2cb9df89e4fe4abfe47edb7f77f04944bd4984d1bd499cc1de9bc417f87b9328834f22f82691854f22e94d624cc627b1f4267195b19094887d927eb94f36d08e6fc9ddf824865cea714ea14651954da22a8762499cc0aca14f12a96cd6d007455a9b35f43fb14b8fcd1a279a4790544816994ac9b447f6272c0c0b8131bec194a32bb4a06244032f4ad47eaee0d2c505c3142aa6449183cb53684a17502c3743c2151f8ec851db82ca8f1bccaae841e28a10cf941a3ee2aa10255334d0949fcc419e425382a6002169b46b5e561ab39368e6068eecdd4f0425218e2c829270d2b18b07a35dbdda6a6db7d76a6dbd16d72323b282a94758246d0e0babd5d6bbd98a2bc789640d02b212c4896415a26d1bae5c67abe779ef79225979aa0f2095c713c93aa4ca3cefab20c9d65211972e4546b55859cb61759ddc6fcac1e34551e08b92ee23f7a73ca6aa2a953755799f98c449eeef9f6e750ecd5d2dbbd5dd3b51d7cb7960e9945ac9cc8829536d75162e5d86f40d0d1aed93243ba10144c34a9edf326ad43726108121ea1ccda37d34905adb70407d4363312b31a1589618972e793e2da98fc640c2212c9f3c9de4f919e81b8abb84462c3039328d99d036f7b3bc10cb8a073f8305e3e683be6999771f9907a884cdd6f6b074a84e000028282317000028140e0a44a224caf128c6357714000c687e48625a341249c3b12c4a911c83310c23040063080004006080614ea14101bfe371b10e8dd0ffa59458055686ed94acc295e451385fefefea8058a5be4e56e0f31ff98eb44e957310b845e5fc57c1a40e4f6b069322dcc4e8027b2f1c88815a765d509458c94d9d07e8d452888f601620a56ce63f9beae0a640453de94ae0516eb369fbfd9b71bd54fe85b2324227af68fcab1e004fd117fcfcca84b46ce8e7aa1d02de9393d1565648e45613605f011686f02f4379838b1f5b474ec926e628a4f89da8ae633ab9e87c96ca7a753855a0a0c8490e54dbb5c3c32dd8ce447784676a512f67c48032a09b474ac9a6e69841a40b88b59544823d6929fe9c00e95e8b6343809b3b141479c882b4f93506df623bf7a8adb448dd93b47f2af5a3c2321faa1a116d6bbab13e30750f51ea84d350fc574b1c7ee377a8051aa5f3799b6fde56437a71a19e7ae296420ed05f3c286089a3b4924a30e2962e1a12fc43fda2b6220a5ece7057040f13d018a3d33f76e98737d816b29932b83432a330abf5f84003395e3703d835d0a3bd1f8bb34a645d46e37a8db3c18fc8ae71e4b433ae306b03d45dd4844e7d742e87aa9b73ee2315194094191cc4174a1437429cd3ecb590b3ce8fbd5909be2e713ec748344659a8ea3211a3fe41e8f4cf0031d3dd50ff8c55c422ff1f4abfbdf4c01dfff934f50aa8e9cf04a71a0a7e629cc85dfa1de1a3019024f4b26986d3564a831c92209a66b3a9f2caf4434c5481d6f6b5d28eee68df1258de5100bdb25c451f3e2d0f303d4f6cf63d26048a659a5a2a74c803824a862c39cbd0cb678e60fb3408f6caa8afcbc10f5ad921bfe8d6902794bc06b3cd4daaa6c4b506787fa979553a9fcb50ad9f5bd519687a2a52de51c16788895bb086acbfb6a73334466bc0a52a54a9848368c368d028c9e12ddfaaf44a06f11014e97ab330450ef845687752a9f2f62dde0f9c29b21135cc63099c7652e20b8fd2670c4390f8eb15c5b9c86349c096ba6fc8c2589bbe65df869f53df51faed4a01d7dbe346d18e6266cf2324048ad99186bd2e3876906bea73f216b6d28e53de462c6cc628da49c26b57dc402106aede0849e7a6c4ca4ec2b7d02883090a6d0a26a828d9c05b6000da0a27c90732f6416a496423f3eb5ac997b6c5822f9dbded3bb26dace7fdf2e22a342ae60c87203f0f2113e926571f2035a6d2dc4b9eafd49e3bf9270c13a469a2bf6f6a22a78e9301d54121590976fc0bf9dc0814d90f3f5e4b43c4051c50a45121cd28d389365f0dcf8dc37c5c69c6131c93329a210d834eb8de6c592c734d54c2a336fda0031ec27eb994bad3bc030c7728338cc2189debec1131ed898d72b20e1f4593892c8af19fc316362765b56dc3bece02530da724f8fce030f4689f2606ba22629f8bd0c5db3243ad9f3427353dfec5968d4f110e048493950be3f9f874cd8dd322dcbc06d1a7ed6f7be56944dc6dada76870f5d3369fc142ee37033eed6fa6e34a0aba1ff40a72351d6076b4855a6e1b53b585b4a3a3b4e873b86770e69a896b952439bd703d3b41071e86fd72d3dd736ee335aaf5ea85e996e9d71cc81976bb142da43f56cd9a8d26b1a74310a5f5bef3a88735c64646910e48f1684efc27ee5f3b9e6eb2846d554b32eecc39e774c332839c471f0cd39cb3f05694707a89097fb9801e0b25aeb4522efae9ff149c32a869a018865671b803227864993b2cbc097726dc8e2487f931fadd4aef54c679f81e19177d0a26a8548082f7e2007fe1fd5977ef69a23d4c8cafe7f1b698e8345ef43abd67af9df8836102aca0645289fa35e43546a4513fe04f7e25ff61172e112ade72cba20d7543201ce60cbb8a52cfeec318c2a6403b705b661f18da9cc26aa252a09945057fe14071df0d7e64a961dff908293667c880e70088f937d4cc168f29c720b6dabf5a54f79272f5ed10b7de00f797977bf4f80195195f8525a27595819f9cc7dd04feb72a608b723185ea9b22e19593529d72d7d035dd991efa61cf6f272039bcc3b962be736e56b88bf78dc51e9a311b58e066a673941468a1262ecf24fe4659a8837a8b18ef4f448345ea45b6c384007722d56d801ddc27af1cf0deb74c6b910940ad419fab64e5a43984aedb945e8ff5386840972b365da0fa3a1c6c1609ae3e46373abce969c8465bfa064544e6543bd5f83ad1d1cf4aa446875ec15bc3ee6ba5cf862e3329d7e1448bbcd93ccbe43771d065c42abfbf529433f41b604f7d8a0dc1bfca40b1b81022f7a197ea2d66da5064e28f8ee2670cfb9b3709b42e0656b855a705ebbd515b3f57189f792a47009e388316fa10072b117f5f1105182183b59358c69d9f1fe13ff0f5bc6e0ef266c416ebf9dc5dc153efb3a800603957da5600a9aa64306e27a580fe02e33d31ea0309c00664d3984ae4d3b9f5a6bf99213a0d77e7b4118d4eab0cc37a1edb721123baae0920402a4479303e85334b1dd066e4627bc3e95ebf2a10133f9fb74120602281b6b3303355a5bda3cd6555bd35cb6b799d8c367a00cdfbc1c4a48a9a299d93a4b38ceddf3481bfe7a2717451fe6aeebba930f4a99493a9cb3aa69771f268bc55f8ce150e283125950e50555babba2c5599a9a3bb0c62b15547b0bfa4b545ea4acaea1f249b499a1fe5377a121bac9fed9a1b5e76b94e5c91ce718cf359550cfca3272fa11b835a26be4512cbc74569088ba978584c426b098a284ea23de9c6f35ad865b86b49a3a7c5b8e40cfcbcf17e34f4d38f0785ab5712839491cb620c767b1e5e52830c96b3876fefd90a8b7c6f773d5ca6ff84b1a0dc11aab4630f352d23ce00aa6513528fc31fa5e63e6d84bdddb56543b798f6ec46cd51e1d48b695fd1fce5721239f1c4be3192b65e9b5f2df18017050e37d8af54169d4279d83b188811ba060318f5d025ac99ef525f7abfc038bd60f19212d8c46c4b51ad006d88d68a74b8b09d8f4b3e1f85581d4a2e3105b66c628c91e4a820f0cf4da10f92046b8934d15f34d7e96c72983599451106c616b4ea6fab9533418383ad9ab7b9109068f180f7b0d8ae280f80fdf50d0b7717ec8d0858f430f6061eb183226900a58a4ec36c2283094911aa055383914ca3fc960378916086616265cfde7d4b3209c73d6228c243cfbf0a4becbf74ec0a99350c2f3ff40cfee9ad1c74a394142c1cea99de19fa9d28fa3eaa65d9a19ea617a603561c16abd1551dd872076c5e0f77a344b5ad8b0a970202725609462104a5d9c817d1714af2954457eb4226f3d6223d0ee26ab6f2e3394b3b2a9f89cb9fdabe7458c78685dbe06b2ded27d71ef5b549a85308d5eab30addecfdd96123013b66a6439f45f459063b60b897b58e792b40808e836d3db03e22af4c099a50119b4d931071e12c334b03f8895f1eecbcc9e54d2821027eb951f3c68a74180562879620a9ac27beb5fb80024bec066c886392f19a766ec88fbf106bc80f03e3090a8b76803a0e38dd4d26f98f403b1ffebd4360c5774f81077217879e128dc6f4a06db1bdee6c102058ac32675e3428fc10bca2485b4143e79fd7783fbda1299a8c598233d8f03107c5592936c09a8a6f8d2d41f2524fb41c0b2aa2706cec2c5e14ff01197068b763bb53f32314c3671f6023f376943ac3cc73ede0d9980d699efa91a3063ac061601eb2f160d83ee43e2c0777abe855324934cec3954f17d1e52bc01290f27ee7aaa231ea053e9cf00da6147dec57fd2d0e2892d68f25bc20c2913b26d0acd132bc130ab586dfe217112a0b29bed2361a9a57e01fefbf3f045ace954769a4b80d5f72bd48c1e584fd4ba2debdc44f7b2442a182afe675c3229bf00713d5262480d6a0a124094212bfb3e2eec98bf2213a2a44cf9af761688daae04b19c43d9fc56c2956a582392cfb280b0ad62d28adf7beeac7b5ce5415909044ff480cdbb96fc5dfc3090fbfd91f8839a7c7d767507ae41373fdc98318aea746b389131b598f2a44c6d439356dcb6596a3272343dd93b6d238d6d20241e91b49609b6964a98463afb1dff51c04a9d100aff0de507d29b3d9d19b0ab9d0017d869b7867b9852607358c9217cd69c0d13d52f4ee5f537b423112e93eb97e0ff9f9f0c4bc72af2eafc44585f8531505af2ccaad910c3e997c42a0b8c880b4d66c9a51ec26d0a20ea3a5102ad5d4ce08e031cd55d800291b48e0b7a5d30d12b79802c3eba42296c610f80fa7f69d48c53b8edecaae8a89d9229d81c03e933a01f0655688edea465e41d997930ed53728bf323f317a979c0506aacb557103585720afe8483103328b18a19827475b4295cdb331748f1331db8046e2fa251bcb5767dd6b4206032ee63454bdcdf5ed2734a9c024fda3fce8a118a1755defad0a40e37bc7e259e821439518d6a0bad751cd48e8a6376210c6fad5e1d2e5dbbfe1589176670f34ad113ba77b791f280e4580ad121f1e3dda37501863df06c6f5e836f3a3432aabc7faaf012a2301d879895b3dc5b19cf4f212f3d7784c7a98b43ed610dab852d1249eadb9fb822b322de24f1e0925c2d9c7dc84142e6f431d3613e8c6337e9bd70dc750cd1b1cad136e5b1d49fee2a50be9eaa979518ff38d1f110197c9c9548a213e14a3bd7eb1349f479062b5bc8358eb7c837f448fa7122d54cb3cc75aad0203e0a4e88359681d76bf121113a17345debc3de68505741cf0378ce4a642576aa3a460d1cdd5769991c4cfd8d1d2c5dc8e88040c76b3f172d5a76be7b2be026825f606f3117ad814099b130a0e38dfc6e219069cbfc3f426fa25bfa0dd10896ca833c7374861031b1c4d070f75355827696517cb87062126ac91be562403ed5934a8255ed34943d980b17c1f53c16a03c9b4e8013cba0c5232d2d1a0a5b3cfe53300b84f2769c5e55f90c69514f3eb66fe7c1467cce06586584953fccd4972c3453f839018e5e8752c22bfe4aeee9d051ee359303e8f838f4346d1852f425e7dd1f951b6e3af02f07cf5fec6be94800922cf26a73e4bdf57871cc5136391af4169ba5983c07f7f0d7086a221fc0c61074b1e1be678841edbcac9d8982c9499bd68b49ccdc91c169e763faa82a4e7ac12a815ca61fab12327a440ca60e369617e13a2233a17b994f30acf02514d6bce9294388dda850600202003d860293a6a78909468f3ad6a205467ec1ce53f8dc81e8cc31cc60124c6b07c8625d8b0f765618c03b32eff85871db6df5c98a607bac9c9916f04cead6855087a500a65adf740137f12637b2b352ce34fe6df043f778db99eef74d3556ff8a3737c06ebd4d4733d2417f69bcab2d784d44ee5ef76a1449a782f9bd38adff597407cbf8afe5411f748271a0b5a5bf795873749bfd54a131eaed25c2ea0acad5bff556bdaea3960ca9da3ac8c084dc39fab7e9013aa50f233b8c67065a04ca2f155c3c2f767418a6b14f261bfb41d6ba88c315223613612479262779b584fca74f925ab3b85dc2935ab57aa9b0d3f41f2ec94c32ffc4a918fbaf982b366766721c91e7c051b097ee359bbb2eb84b40f49f6a1fb406a8e50ad5bd7d548acae52390701550ced231f6518450e5cf2bcadcd770ca8c66860283e6175bfaef80132b13996ecc1311ef61c7de706f100f845618335fb05c8b12f281e5d7e0ac0ebbfe2878d2cb961ed1b16cb8315dd499319d23453e1631309259bee30bd12ba23c169c8ab57d4c46d4c4c84abd712196dddcaca9d20f9277b598d7f443103f49f644dd589e8f9653ac733703ddd1392949c41226171ce058d71c9ca470455f95755e68269de6eff433c30879575e0d5cf6fb5a62f9bf2945b2170779da5012b094a6c29ddc47259b9831e44c75f05e2fb5fd8d6c47899faeb8ee5787aa702a131a2c152c23ac92107b0fd34b66aba71e4b5ecdd40f362b8c70d2000800752d6cf01d0e16f343400143a173b91f50a7dcb9f7dc64ac1699d9b8e9d2f03417510d44f3b68bd840c527ed2178bf86c94f7b89dee9c4ce991afb171faab155c3d765b54d14ad7f7f339807f947ddc16e52176aac9a2d65a4cd506c1d241fb8cb598e6f1519790110a5cdaa732555f15aa13ef15aa4b9a77f5d85004a20c10040349e999653f9e7e038a007c7fb4d0de784e0b0f68459e070439e29ad791d672a2b9e2d324b4a07bd9fb9e24c535569749b2b8deff80850efc730ac614268880dbe82d9bab433821b85e211ce978dd209cdb792c10ce4251cf2803506babe20a8401a143454752d414c280514c234ca2f1f3512626dfac322add205cbc1cd38c0d5c2cac384f7a073da3c1969a076143d22807bb8e5e5118219996dfb958af87d5b9136121fb8d36cc85dc0f3837dd96bf5978f2014b1ed79c9b1a5db41b9d294a6f04a98dd82d7165472dec968a13f0066faacd5940d6eff531a9371f3bb01fa6acdab8dca698f740e5410cec7e2a57940d73e27730ff9f4b05d9a66908176e56bc92bf1b7174580d9baf1b9f6e53c59d83fc096b2593dd1c83f097885d6cbfcb5cb89c77c1a4c8d96d4ea0e2ba80a6d2a666227798b26f2bb344d79441f6215cca51126447dc2c60da4cdcd238178b65af6abf7bdb25b4f5c5c0bd826c8fd9ff555b97c8cf7589162ffd4f2968d7a8d44088dff55536c0f73e52e07d0535af6dd3b2605edddfca469e7b5f06637ceb40567cd58341c0a2074cc369e54d048f40464bf29c9b924658217837cfad2eeb46a8d35ebac8dbd0c7383afccddf4cde78273f59d161a19481c9a6f12685c4136e575b0ebdc13d7875d3003320c9dbc9f3fdb912d5788fe194b5cc68129472e7c9f7c4881cbe7f3f273f93f02685b407d75dfc4aee8296cf02af5256689f4b4a122d7632f883b2acd328823a7e94321a72461955183d0430233a592acccee52522813d8b76f54b49d146d4b4537e5259f8ea19d83c3738af2b9d2a0a2418768d9e0ee774148e9f4c70e23de57275e1462a8d60368db4952590b81552ea9ace36687ede6deb1ea42755b464b699b2d172ae8505dc11a68be34790f5e4d4fc50c5e05ae0dd7760bd98a585e1ec5c995f4601058ae328506768bd0a89add253d621a42c5646ef8bea8a445ee3e355f69d6a5e572bdc27c2f733dcbf9bfc537e663e4019cf559e36c2df432a9b2e0aa1175a4e21611ad16fb9693226b27ca5fe25cf41db8be1a131dfb45b5bf7e3116b1b82ac952aa543efb1a42fc79fbdb091919fb1b45d38518e5d970a8c9bd1d889be668755c2ad83bd87c295cdce6e43d55f193826e72c116503516094192bacf7494d85df8673daf14c073f261449404ee652dee2a08100ba443b694dacfa02b2bfc4a97da90e3286e4e80134761531b5ecf665570760719fef6e84c179069282693f57c3ea6b1328d45b0c703c1867a21551ef355fccaf190fd97148bfbb49855f7fa08460ccaa44c94e7b1b0b0e0a92c7a105c772dd4d758e94aa2f073c6a83b73c9fdf85ce258e4d0f33e007e0545b2fd9ec789280d0ab412af6200b665f43d4672b2df296040393a8bc55069c61e95499df1efa45f1cd94d273f97ef8c48c664e0df88cc495ae059b4a0ad2b3e7858dd136877735fe09d705d133322c83d6727a6eaa95d209cbdded01765757cffb9555d69c6cac9aa8a3e005b17f9c338a80287a7808c034c5545d63dd0520404159220200387f514f14d065dc153417dbf220853ef2354aa989d395001a11cff242746d66f00ae96e9dd174b2e5438676236ef488fb8ca22e914c5fb22a9f97684265f9841793590dcfa21ecadab7b4bb7528d02435a14d8efff8fb2a722981b64341a3f5acfb579670b65644976dbf74b02917f422d4855437ea225f4814f3c6200587821303621d6db41f7e196606c822c68568aa068dc93b01018e115b90259693eccf357eb560dc0523c9c9950ceb95489eec5a1b85582f6bea8e6947a094a0799931a1eec734e0935e306549305837c6dcb4eac72b87f519cc2ffb33ba65bc328e7d5339c22e78bb67f86b49928fa925f2efc6504ccddeecc7dcef46de233f6d9081057f10c97f1c4e5534e35b58454f4b324f253e30abbfeed55a0409cf791299acadc112e90d02d1b8c3ccdefc05e2cf4ce1fe982d621993e141a9e1864ec417196135ffd4f76167cde7f81149a947da4bf6bc0497e46bb95365d073c8fc4a99401bbf52920163d7536140ceb6e4b1d18e0392b2f0fc2a744e0449b50fb9c555535f1606221ec980c7ef6feee0d8f2931ca9251b29678c4900068d8d7d0d80061964c35fe424c7f3bd2c59b5414002a223b49332696447d54a987fb3b793308d7ad3e495d2a615aa7d4f77c21cc214b39a9efcc2b2ee615065f6c4556dbf8f1f39a958be6e7a86802b9140be296e453e4b2ed7e1b8bd877a13ac5893b3397cbca4a70b2ade4bbe541dfe1bbf9bf1c6477c5a49e72cdb707a50fd12daeb0d3e67659a0e88c137f99e46dced418b86189371437ad9b12acc41cb7b3d080d3b322f7abe2f9416e9d2e913bc192886072d98cb451f3f47dadef34c792e3c68fb5c7dfafc25de99e03432a863a9fb5eda5ddbd443ee3e0703d7211a9b93a40b3c8080827da66fadbdc725ad6e12210b1f2acd511cb8be50f8742918769b06c9176994c705ee2f95a0bd5aabd6d37dc56463fd3ff24e848b670a138bd236c31b345b00a288cc293b8ff6efb9e03989b1ed1b1d82f6f095c1fc0f2679dd64b5fa7809193ea0601362696c3e247ba97810a1021805882e681c43ddf526621a6f3c99319d8f5e3e5bbe68cd1d4828abb97b7db15e668117e3fb7022a70d18f1ccda008380918c6fdab687abdb85c8db810d8407d85df2a92499a8b4147c483a4d996f2e46f119c0aa0e877ea73593aa468f50d60c4fa64767aa60689bc1e6bad80820d8ca1f4a09fb3d38de040d37aaafa5077b7830d9cf42f90b30c5ba9fd407c5f4d106d5233a95ba0d6703176f90d76ac27be38c28b86048b6b2918e087d749c973806ade8800f9b6180bec44302138a5eba1edc8f007ae1bb84e890d7530dd0de9c8232003e46eca18f97bd451f986b30f562c75cc87e559e3e1e58e057ec8cbd85d44632eb80a0a0f7d43362272ba4a0ca821acc2a3f6c75a45b6f1910d374aaeea7d7458c0cd90da7e2712882d24e4af4d79c46688d2523157edc97c9c4f861086bd7b03ccaa1411ba159ac9f6f88bd9f69895a4fc95615944b23e3dc80d61b0a3482037de49466ccea17f429a6954180fdd5bc50e50eb6215e44d5b94103975ac5164ba685fdde00c2acc8559f3af840aa8908e7e1bd0fb4bca0434b88db4979d7ce70d66ee04eb0d64d21131a035497268cc54b28b203bf6e4e78cf6f792e456cba5079feec008c04e650a7bde060034acc0c1c553b529efed106e6285f4c68654ef08e668fc215c15fe09aff5433350302fcdcd630489aaad0d520715150cd0a6d4da47ad5e67742fa7275e49d1554f33296235fd7dad2bd9161771c4a63a59a2950c492d581e44665f0c423d58c8ef904d57b2325129e760baa79176413e7b110b0e5cb8f554d7384d18864aab9d7bfa545048247fc0a8d359be8ff9ff37a1a0f0848cdfae97aea466c251152f919cceb83da88a3597361ecfb798e333aad37f1d2664f9d10e749dba9d90c442e0ec11cc6ca7ecde322fc63834bfc211f7bfe6dda1379f11f95c29a830e6672ee4152b35f0cc38a71c8cbd46be2ee3788b5a5be2cdc63d37272546adcb765441b157105b665e0bf9c3a79c109c53b7efdaacd87390ec2e463f54a211361a199da804ba36235dafe0ab08f48397e07adc87de8d38e4d0d8411781c615ee2e1abbac2bf767cbd7f760590941bb21b8eef5fa9679b92eb40c851835d8ec1c64ac907291b677cc1262657b704e3b377bf48220e70895b49c90a4c88edb8e109a692505eb11500587f223592dc087019c7b3104247edef0e3a4e14d2392aa06de0b142a4a5545c09b22b0fdb2169d11abaafeed5f1f196e8d1557c0166d0318e54a4c372ffb0817738f91df3e536a24486c8045ab6244572dbb6e5312c0103fb163608cd87fc375a812c4ce430a87e80f286ef793cc2515c97e72df9d3cb80a89230c19f8294ed5f048dcf4f80c2188d5349c0ffe4e0407bf195e52a8ac46b5e49e818559c362fc4ecb0d30396d3fc52a834c93bfd117348a2255c3f9342f92b2ba31ecb18e9aae85d5c6fa04479a3fec5504e27d42e66638cbd8338c3cbdfd77be5c3fe7b80d1a654c194c4c58ad547779370c48a85078ce7d20c60dbd16f6042d4a3be8b8cdc2eae5b21d0d0a7200561f467b3bad6b06abbe6c60ea451b8aa18dd1446bc54a7e72e7a1b2cbdb9995b58cebca9bc72232773e97734ea385b85f62948ed5f45562348c5a3d637bd75e8ab4ff3316da2956134da5c4c69476372e1eefa45f073b56f847ac8993416453bdfbaae9ae173d7d834a9d57b14e156254377166c31449b0200df523cd5486e72cfde7870a9893de1670b81c8829413b329b0fdd28c27906fb31c59b70c2a30b297a1cf2d4c875e08a27950655744905e68b6330ef8042b6ba77559e61e61e6004fa4efdf124e95f85c5a039de3154539aa62156e7c716f98cfc4e31186ec3716a9939e28c05de0b19167ec7fa6ce79307a8d9d22ab4e5faa56da0941c0d87662354781216deab3879b608deb1504f3254070c26addda39d29501e14c1be92bba7346133ec6fbf4599f6aab0641362dd2790a57b41777db1581454805e476172c26502361b8102b08edf1541d5deb29987e295ff6535f7e0cf03ffc8cd2b4018599eb3f61cbcf4d03f2c5c2d17947bd6f6f7137ba0da2a1d8994262a60e69cadad117bf224e10b13ef171599b0e223b64db469bb15e08dd81e25d149d04fb6593c2f491bcb308b33b2c4e6ade2379c5013dce8c36ca07a0598d24354d9b89ef694c9f63ba69279be304cd7c804865856d78d49b93178dfddc523ad1a4fb1719ba86f5893bf22b561bd13c3a2749c07917696c776dfc07fc6b7c7289f5b89b6f0f6f9edd0208023e14b2c3f467e32416e9749ea8b04a6c8ed68326a729f2ee8019808e2401ac669f37b3287641f7d9512c0aed799d0f4f1a16676cb0c9dab4e0fd5aa15a78c3cab1edecc03d6d4eac719d780bd45dd1da401ded6a2554b62d5015af959b8303af2d64846d75f56046a5a59d64d3694978d874fd027dd0a60f15be84e5902efd179c2dec2ef15409a4e801c165eb6b69c98c5c2568334f00b42316daa0153a2fc17a0e9be00f76a86e4d9e12d05e31f177ec6bc74e8486eae2441a04d9794792ed739c2893f31ad9ef7e10b02b75a1211b1ad415380cddea1c07f40d5ca27ec9087e81d5030e38e60985ed6ebc76cd4e84e45e8419b9fe088c5f4f09967c0f01d41af42c6cb73b86809a4e750d8ddddfaa7d3565e9db185aca2eac7bdac0d9f879b27702bb1b8c0e6e14fd3c8791d63fd06496d0663e00c8bc8bdbc92e5cf6a66f7f7facf4906831dafcb4edf20cd466f367de756a034db15a86430629a68bf2f98c47cab3e954d5ced0c81f3f6cadf2f4753444f26e714587b837c3e91e7f66c7997739019f1519c1cba83c7322dc2c59d2091b6fdd2c71a6f40ef3127aa18b499cee749084edb0f8e032c50ac345ceedcbc4185b5213232f3b8b3ad8ba604813a9bbd60e2458d85faa9337698c797639fe69f09e0a361f970c9bf7141b5f8125d85ea56ff8072e63fb966ae333800cab7e554a6f78f90cf8e91d5c52d513bd25a6a19ab91d1a0bb147f642cc79a10b034aa5ec1bd6cb969d164fa3e31ec0121f37128a1b19e4960fc494f12b1541d860702e4b612fb6d564ac69a9209151f40d0b22fc79310fec909d6e9b37f2d286c19f38f6357e233bf5b6e2de4cb8c17d7e77e486148b3a07a9b7ad662524a9cbaad877ea0304dc940744645ba6dac6349f107dead02df37b143bf3817c5f32023e779f1a895c48c7b7d7e8b4ad9fd04f1170ea4b911106abbf8ae44866f21ecaa4eaae0794d0144930a1f709ed152a7e764f93dd0ba227c6d9bcfaac35fd27787830483d1c8273d45fe3c744bb39aa63e6b1d0e98f25161d566aeaafbfc618d1abad01df1e61c77708b4a11b525d9157ec5c20a3961bf661f8fd3dc25a9703230a95af40cc5ab8908ec1db334a02b0986ece14dd16c2c41ab666455ae0c2c29529b99f412dc21ba4964c1255a840249098fada8e6d8f1d1bb25d8428e45993b028f31b9bb5c2b9eda174dbcbbd28a31a5380a6499bd580be90dfb1404da0916dd47bba9b682c351104c48ca85681488f45228849134c0b812beb0e912d222aa9c35ef557f0e01cf5ea3d1858a3dac58c0858d334840cc8057e692004669a3eeb8530b2472e29eaaedb683feba82775e951c8df505452a6e4c43d2a4341cf4c246d2c18a148c0fa161aaaa54772b4eb4c4aafc114abc2436f5002be7f5d6993afe117651c31034824743e8a3b9516e52956876044860d52a4ff297771596017255bba30d5310db65e61d0eed375d805018592d6b6a57d3cbb44e617c89398767a0c1a8c8671cc90619c0bb45583180b98f44bab102d51d107f04e42b03331263cf8c1bbf5c4ab99a5fb0a7c8e7b47c6212530d8742bd47c2552960408de6e0574392c0ce3eb8c700ca782729c82098915d72a691850ead19d92daf5c273ff87d76c740746236faf9cb01d2b166d6a26fe45e4805216617b7460300a7471fb360c48fa3b68c2b51f34babb1203f7f6fe98027ee407c82b5bba54f501f64e26fe3927c1e736fcf9527b54ff809ae172d13f31cf61ee39b52328e49d9249dbe932fddd7d0d0b9f004af22100180efd40b8f2a30bfaf804a3a5253e3809045ad4d6ca1eb641d300698c283e98105e3b3c35d7bac3c5c16bb707e19387804d73f59280eee3005b95971cf8531da0ede34a00a07c2166ae2871e14c050dec297f7dd7017dabbb042b8aac878c9c36c1c962bca5caeac5daf5c215100813b62cdd689829f975ccd2b70903259d31ec35de076cac66644ed8e2cdba42e24a297bb34cf853455684522f8a1684bee856f112f678284a19a98c72844dd70bab43f54d1148bd2330053be603c394b497e4d75baab7b6c0299cdfa2d5052a1d2c28fa2e87697978b0d0621364b4b2a13919c7f9007d8578c66e7a281b24f9e127de5528e0685bdedf5faf1bf12d22dabb7bf46ec60e619496dfe6bc1540048d3ef67bb3386ccca5be622d53ab9dcfeac68abd7fc459871b426c799945839eb1ce85ffd9d7ccf6d3b7a515072d94c2091671b996175e2278921f62c036e2c8eaf8590830bf6b022a92c4bb20690b94dc7e4e52b0906a778e2942c06c1175d4050ae6c93fd288e93c8c1d397c463b6fa048cb30058660112cad015102f140d32d005056442e1b6ea797e05d56666e053e1a713771654197ea402c459a8a4f2ec5863b1fd66b72d310a2e29abe1e7d0f65bcddf62a165db1a28e74035aa9b733e0a4e8949e8973ca80e426435909a57d738e44b926525ea60697900138f62934f9b4731c5eed49e2853609f01f6ac1e9c81af875588132db215ff8289a690c5400fa3d442f27eda1fe452d971b711fa3adb2525e86f90f95e835c6b80ab23351a21ff3be96d8840fca942ddd48eeb322a99ddbb26a7f276f6947824a24c05b479b68c2a6ee091a5c239be1fb59986195522e574fe205deb12bd6b668edcd546ae368ecc9fab7d532569917d45a0f369a8a10000aceecb6749d4d00e899ba9e97450f9994b2005163fa2e60d980798a8da54716e406bd8d1c4e7a3666a368884193b14938dcc067fa04c420bf954d58a1dbc155b599c916d37474854bf9b2bc333d14aa276d6a107145815676552440cae7899cd3b863a9c49f676c0f34027d4f703e1c2b60e4beab5b800087819ccc62385afa10c7c55a6d656df4ae78014383299fce61c681949c313a3b5e902a15a0d48f2c2534cd2573108e75dff36a98ac267d65d0e9d22ae1c3eb9e823231ae34c03fea6ff5e56e6d163937bec1dd06a6e260d515e2734f68d172f874cdfe2090515c4767e1f9fa734e594a2ae7291398e8cedca35411fcd6a6b1e8adcb0ab59d1eadb6913b73c7b596330bf6845b4bb1b0921da549ec9b79e3cb63d9977ca033e4892ff3bec020547874f71a1d1c53a20962d303251b7bee6ab9deb86719b1aa0b86864b6bb98e71eb39f9b257594d5b1361375adce55d6c36454eb1d13c5b1f64a6a8e1decff0596b178a18d8c849de31acf680646a0adf1b796f6774d850793c5f6dd03f597861efda0c0d4ede9822d232d13671c6399c70dc93c502be57ac63d79920755770692d8b3478e7ffcabb00934e9781c132a1446ac9f605a2bc9425f1d139d5868f2d572e51cab7e349c3a0b0db45fd630351d8116ff84a9a68410486063c43ee029619a38d141bfbf3b94990439109eb6a47021c7946c374c58282847ae326c534d6fda1360e419fe0930100ff0ab95909f9c4a69b41752eee525a96c4dff1740497a7e3d865fba2fd69e807b2493d286934c23c935f5c59b768a0941d372d5c88ef8cf5f20a2bfd67ce937e679f57d58bc8930c4cc5d712065e79e9f3234609fcb27866a6ed8021deab42d7b41027e4aea6462058e729c5f02a44149443daf27eb1ac4dc36529851141da9df05b0b64d6c39345eab9770c2d52fb8e1666342260b76759c66472f86fb3207b7ebcc0cad99adf5178ca08a7e7e8a0bee970b88b08aabf4c1d496f184c98819fcb56ae4127904fd93dd5a5eca23a070be4120d85b18640fc8465778570d04bf19bbd9d438ebcfd002752e7bc23998645b74c1191b702e040b410bacb0340f40824b1d6f81fd68ef6559b79f0efe6691363d6b19c6563f231597902730c08c7fa2b1ce61df402d3d7e8ac08c1e97535fc47f521abf0f531f722f95496f6dcba877b6307d81ac27a4488fdad563cedc2dd30628f674d2c8e482f20fc6396554d723334cb012b380884f58c9378f5bbf1eb2a116905f1424e168f5eb9a12f330578a154329b5549f9c83d698ce3ba0d6860fc0a169e3b701972d144b483277eae00aacdcf47691b8b405217a5aef7b31da52a0b877c383144004242720112c26025dd49cc0b0935de9ca1ced952d682a91bae8f1174a6608c41cbe2e69cde4cfebc01b6652d57d918e610e854cb7555b000b94acdf59d587cd46fbb9aaa508fde2757548b7ce681945c72d2df2a1d4d9323b74ca638145bf5bd1968733fb189eff0b8f6175b59127eb5b6327d123c1376faeae62bc83d2c5a400d2cdcad06c2657ded64d2be8051c526c0d84d219bfb74ec7c2708d4dbde40a8c91e11fc5ddbe6d24fb39de9ab6136c5a0100168082ee581bdf95700b34d7dc4bfd28888ea874019b8703a5a10e2e92942d1a2c1b4d1a9801d8accfbcb16508e0497cc72e7314d358989bfb81bc78b7b32aed9bf4d071b0dd516c958d2256437dfc650b142bee2eb397a755c4e788b73e3362836e5fadf03d2cc036b0906531532ad04b17277a8ca8f70a03c8160f183638b180af1f53eb47a31d4b05c46df4d1dc02b0e60526a727baa34d13d029fb836f7ba406644c296a7fcdde1dbed8c1605d9647f2fa4b2162cf75bc79a43f4365200b02100897b87a0a4a154b9c216b555922946f3fb97a3be95cdd0cb4e7f45646b15c58208025f2a3c7e2780085cbe3b89ce3031446c2c50c3d8e994f37a06c2c98b4bb7aeeb138736cfcbe3c909fa97e308fa0ef03f6b6cbbef5e7deef8409cabefc29df23c8ef7112651cc6606e523d1a3dba1e9bccf041df907990d9bfc594ef2cbe8ae130434c2d4e3da265005efa7d4e1531bd853ade429efed141c3a85f7747f83ba54850a99bb7872a5a04aa5b0cc321537501d26fd04355fe7a50b4a91f978948612a1b074520d9682cae70933e92c52f98464a93641a35c13785655bbb9330123a63928a469689dc7ee9a8b1c78a6594879bb0d69450a0876b037285727586442a6a512a746a76269141b0477113fc4353592bec6afc464656857966604c8908349ee1f7d08db14f37c673e3bded0489900ad62263ee46c56f4c2c028a8b493157e596c02cb1e36bd96501c150f6eae08e4cf6cfe81274c23f7e04c7c560083635df0c6c4c4081802f2b24fa9732531c4db6a48c633c141e487644e55044723a45aef4ecf74018d04adeb5f58f33b720460421bd362b81d142e51b63faf70ca339a6e2be0711b2e5d2dae1d78c8d61cc4ff8358b995f86d7b181cd7813d01e0bce2a3a86c6c52973ac5bc31513e7bdae622c890bc78e24a1ab11b3a3c94d946795c223d7116cdd795a4ef38ec8b8b70e218f45df337168531f49a29fee83e474a52e7dd0ffb704d5c314402116191a5e32f6a0128fcfc15b384676bbadb7fcf1ad7ebfe7323e1d1eff0c88a1364b483755b26db8683f0fcf782de4e88752436c240431c6fd3f5cb93864f224e80da3203a56829c9dfbafe83243e501040b91ea321ec5ad1fc7288d3e5b1e97a7ba21f12b87018635f1e8d7ffd49ee7557a08f5c8068cc201b5f0fa65b285fb08a1b202af5c2941abbfa60039d0738fbfa6476a21649547551e6e50d2be0a0cb8b16b0963e0280f4af12c1954db2b6f536cb762cf4f559df4feb89508c648bb42efd0ed11e041e684ea407e876e6cb15615592589d739dfad5cdc79585611180ff71972d3db723c05c69180353bc6b4ffb5218f803717ece0ce67437e1b2783965072d3872e92fd001c36ba739c0cd3a05911eda30422424b7485956a396a0a2182f608583fea91c63da3f74c60c6931a62e4b670718172f990bcc7c1729e355be8420e86b80f9fe1dfc0f44a56ce079837047a3f57ba6139c8ac44b6dfeeac81481c8a5e0478c619cf948394c9712c3f0d5ec3de17cb6e6449aa2dbf491a920289a21e43c3901f9372cf89cceb9e871525fff02e643ca55873eaa7a8463b0e7d5b6c90839b9c9f4db9385ce3bb9474d85e72e591d527ec5220ad8dbd1212a33a8f3f533c29104a13a180dbdda185ea29fd46f4130832354798956123ffa816ee74d5cc10d3240e0e0fe68366c0b99bd0cde17d7d40d55b80b855d63e5f50b085cd7f5f7f5f79ebe1e6b2e73c04a9f24c058328df4588103d9d931ae287aa8a024b46a39fa838e4a208827222b73d58316d7acbe0061d7ad318a9d215fc3dc082f5547dedb90543f215729dc75ab2228496049780d45f5a40d020c4c82e7c85321aa96500e0d65f25f5e608a96745ffeb8ec54006d4aecc6ed2d2a88a1398b975c70b6d17e51ed8eb5a6b2df10342bdd033208431bda8a60e100e39aeff2f7bfd0bbb6a537474dd27805455c89666afb345cdd49790a2481ceab38f1d2d175c208d6393b64b850868701516ddf7a9382908c120f4e2c6794a7d4e67df699be8629002f28cd53fe632625e5427538bbacf02010bef2d30f8d0cabcdc5af54aca4a2e35689b39d71fb48251d161764281461c8ae018e3c2dd577788b0f2577fde3358c723c94ba1656232492cf3953bc6fbb178e5ab991027b5ad5ecb104640dd9d5967e5c851b54a33a6fe1fc3c7f22ee9ae5aed9b08706f84a8b0423ff3fdaf4356c605b1728fd2bf5fe6686c1b4a48adf5a8808244fe3714ac0d59c002047b24533f124c6becc0175da9ea40660562a428147db840e3d962bc10a980d4e9fc99731c9d9280743225c271cb7df5af167bb78a762ba53eaf1eb3579f0d0a26dfbc97f304a1dd7b18046a2331f52a5d83dd8ed87c5d209fac31d77b547326a9c45085d605823f4d11ecc2f987783431b3d874decf705cad333f85f38172d8fec90b7e05d6125b45c22bbf0284aa5baa91fa1522d901db46287561d55c42659b9df28ff538f9fa4ba45495869a987b771b9441c95b5cdb8cd94ec7200f71393b78a120f039737e1c09fc65fb1b4aebf9b9e5ee7fdd4f7a8c498949cf485e657de75bcd4f1dbbdadc31989d63af007f05aba858f2fcd2dea0f1aad903a9cdfc1e5bda1c2a9a0bcdf33f347c0684ecf2234f65a0ee8997bc07801a66fecd2d43fcea17ea39b3aca48db3ba6465840102d54423c927d640377a34a6cd2b596360f6aa20b71c6e6b5d664cd1178d904898a29a402d2f6154266021a005b4028d24d07494a3ef36a232fcab801802d4805c90116c863b3767b2c9865a819a111a42bf3384e7a450f243418b1526962d514550832b18d0a6fe472e75e4017a39b816e98f465fb62a4227cc1c2350a9a0061c24ba0af1d857b109373c54fd24f2b3670f731fc809f585784c9adaddf459cd6d4a1845b9dc09a1a60292b89e8532efb86f8937327c3112a263e20845898ce10e2b80a8b60a6aa1fe9e658d6441ebeab1a8246197138cb39e33da7fd7f8d7afb982ab186829aaca63b01f719aa595d3dbe4e12d54c1a1c89e48675a3f6c58aade858419d018390fc554ac021bb0a9c660f52cdfc4ab39834d194e8aff1416ea1349a6303af58b683e4d9a682283a341f65a4a1eda4b7a83e102ffb514690bc3f4562d8c004e3f3a1a5c74eecaff2132330b9cfd7b215d0a08cf771e18665a10fd0f52b9e4d90959c804d7a8793628fc434bf6934568e22cfbd057663e2c9f70f9611c88c3b20293fbc567e5644acc0bc876cfc90705444955fe8a6b6dd712ece12288599526a11dc64ca861d44e257e887a615e1614f464d142ffd5afc231692b9b8556327e0b307e2f373e2ffe58de9f5f1528b9d5408f69d04893b798686cd768d431678f4d4ea48169931b51d869252fc503e2375df3dd4ddf4d01c1f99f8452e1b09e03ee55c79d16386f6ebd32f3aa70721f195e50c29f71d69d09da6de316e9be08015a063a0842b94b10704bab99d8e55b1937d374c6ca01a85205d559d9d0e882b31f56b952632b6b7daaefa4ebb498ec1a33ba60741bcb8548dfbcb7341337ad124fe16e128d6034ac2d0df1a32ed43f823ed0fe992d9b26ecc844ee23bb07b505f084f55f968a4ca718b5f5e1922eb71508963a5366fcac67296f421c9fd7ea0e85fe490be48331a4871fb2ae558ff44d485e1b49549ae847759fa8c1162c5d47008f926d06b2b83b80fbdf56902e115e4129c12cd52a41b56a5248655eac1c63b3869862a4676b2792febd25fc31ac4f5582f87cc8d278088cf154f2e2388dde9ec0a920b4c326b7749c63c9c5a12122b40ccdb1334a79dde61fc901000c33dded256a8605ac5c00e6241628ee60c99b04cc2a199e0c65cda87995f8406452cf47e3481d98055ad9b77fb996ed1de1458110ee7601e261216222724d8fdddac7cf1ecded3d1adfb7ece4048fc9393bf814c8c7f38910cbf0386e51b0f0904f8dfa44e39b5e7f48fcbfb181e62c08a801ffa2ca1a5af7bac5e87f3da06ef521630cb0cfdf7334b91e76c113eb95c400d66de5bc49fa842468212b051417a4d1f42d35c8d5228a3e683bed30614f1e1596f34b6c10a02ced489de54fe5032d1db18a32e3e19eb2267479dc7192aeb58b86cfa77cb6987db879f843013037ff0a656ba3f6f083ccf3b12bb509cee18a625e022ff7558ce8b7a3d024c46fd7e7ac095a17da2027e40920bc27fe301816aa7eb519026f83fe6377a3fabf6527e56bf4c17c5e32dcef7fd0dbf4c2b7e3b8ccd0afaee953da32077b4a16ef9a7c9dcac5a2d696e3d041756fa1f0dc84ff726021bb39df0fa1d1b0248a6ada6ed4e0e5dc487c945beb80283e4865799737ceca4d0e181b536579086ac38ef9e2390e02f3c1fdc662d8236183a2eab97d12095cb628bbaf1578e509b4a73495de6ee8d7811edfc7e88439c2096b634808950a101e4bd510818b425994c0c50201a1d5e400e0bf110fcdd7897f654b21ee72de8b5dcd11519820cc76aeeafa0b34948c007d39ff7ad4f338f8964364dc7cec63143b4a671f06e037c90031aa9ce885d40d4554d1b9dfd3270dfa5fc0e217b0171daddc2f3ef0d7d37045beaeced93832f4e0cd7d82686ab8f6be6c1df2249e8de237c7b763e603b06f3014d841cb0521f557efa2ee9f85bf735a84714c565ebefebdfd6ec924d24b2bbbb7b07ec0869082f08b5c66ac413bcd65a6bb5422f800add5b6eb47c4a6684bbf0279331910df1ae4210feae67dc155aa4f6f971f0d77069707a78e1851d7a470b97ffc28ecbb5e7f08634776bdbeef862d0979c461ab9df8bc16d9c1a9e66e519609bb8ddbf5f0af1eb3ee1a5e2e70de3cdc4e752e031fe7dfafdef5db9f3c580786b3497c6d2e0cbe15d69b0c6e14d69f0c6e13d6930e6f0963498b3dc467a35efbb35c7f7e62d69f0c6e51d6930862fe2499a24953813b38c2f4f52de1b0d877326e112d6f0453df186792d6d5643e1375e170441a408208048203b4206b22378901db1c39fec089c234680e48a8be485c40a19922964488a6e2093f5c864b012c86436c8642358821156144166c413322386f89319614466c40f6446f8c88ce89119b1020e7fda17812062448f031891030f23486083206d8d70801f5d221ad27509247094a0e4defba4889f21dac49fac881afca061308422788a50010d973f591145cc29e07b0fa59412764ff62862079756040d3af748136cb04790e0920207dabad1048fd9f24a78b46ebc9f06dce081ec4810ce8d964f1d21c2bb0a2dd08ef4a0067980233770454e85d32a478ed0807747663083b602a7f2722408bcbff8b9e148cf0cf2080b781c29c1eb088f1a82665c094147f6464e1cb9496da69c928b292dad7df15e782989b6225743d7e02a47730d176013969005df311ff2bb1db0c267ae61ffe61a1462344d6a93445fcb3528702b2b0cb72db8cc36b8bb6f9c892a977613f530888171f1826ae1d2c2725ab140a4a09874899439bc69b6d229c512f9b709290421349c5840115990104148295b6813300848fe9505fd200bfa81d71eb88810ce1ba8442d61062f57901f34a1c374028a263e84600426e0304133e79c530ee173ce39e79c72ce39e79c73de54d08f2014e8a02159908b882756f02723828877cd9f1219114132228cf0272342888c881cc88800e24346c44b46c4cd11ac43cc64121c11b648104aa45fd91042644300910dd1c39f6c08986c081dd9103328a10a9910444ac8844022138248106442f8f4c884e09109f19209e1920981f3a2a36ef8fcb76d48f3685a3a3a3e4cf9c941f74b5d6f86f653db33a675aa038f9b0e293f2fc69c2aaf1763ba7497199f2eb3d922f6624cf9bd458ccfd7c1e5f566d49ff3bbca8caf5c95199f6f4b2f3e2b45dd0405f1482389267d7e51ce59ba93d6a46e846fce523763cac67b29d34bbd7f9583b9e6c554ea7de94bfac598cfe51afbc598bf5f8c99238043030db9065faee61a73c358d3368db359022bc899f978cbf3b77fb9f41873304ba0f498e3f204b852c9f4a5df72cdc64d1d3695ee8b71f3bfac25a01f672ee6cf790257ceccbf8f257cf19274e9f5e35cb3f152b7a1e8d772cd76ed46323d4af7bad2435eea7a07b8ee5ee92f2f913a1a423a478ebda56bbbafe002cca2db4c70c381cc8815fcc98a3ce15dc7644586701d5bb212b3b1c2e7ef1212ddb7574c65f666cc97f1a98ef1aedfebc590dfe9ebc5e56b21ba00b388b3bbcd1ecf8277ea7a31e4e7a03dc7ece8cde3b179030d213dff29d1f5697d4f370d212d1fda78b00759911f3c1c3e0765457c70f82f0a61c81043860002880430082245b4602d14c8d80296403f59921fde391ebf06da05181631c20300f893010184084736aed9101a6e980cd1841b05f8a08aa3285c468c80c80fad06dc78000d221c3cb9018f31deadd5801b0f0042063300e206206e6ef09cd467038635102162079717472d4036b454a151721089bc6087d30284e8c99f8c080b88ec90a34284869423bc50a0d0312591a38fdc5002e241b2418f1cc40a4ec005818309301625d8a0388106840450911200fdc003a827054028d0018826f000c413302094e47004c411179123cec29fac080d456e7857a185116834c10581650a1f84702428073a43f1df8d4d8e7083273841a630a28426aaa002919432222184048d221c11638442348a4084191f007f3222c4b06d41bf2569ac761d86204e3fc64363570c29d19822888c083cb221c8644370b594e06f4ff8f62c459c6c8810977f9f086172dc93bac62e6fc22ed80443104adb8059705cd36108e2a5ef3004c110a4b18b097fc9e57197c3456f1d34c6b72fb99c682c25a7e49c493893527226e19c4ba552a944630a4dd33419115eb22110699a065f930d01e21a6973269af4a6cd9968a9691acc36b8d735f93b8dc5682c28c61d01a50b34e6caa417509e8dc3f4457b7a5ed487bee0a9680fb8dd437d680f9eeabdba75efc5d05e3e9d97fe6871ced0555a5e34ab75b5bb9c13fdb8eca8b5f787951ac4a34ad76db84accf45d02d91103d48bdc81f92e7362be4b1cc8d2e2bb0038ec18d03aed5741ca38a1933e72a6f3018a0c782a59e4c674fdc2745dbbe87a0b7fe9faa3ba9eda5bfe964cf8c4a89241459e4a4a9f5db934e2a94e1f5f2679aa24dee9f42814b41075a2fcc9d39e5c0649284f5b721974da91cba078da90cb248f899780f708d0f52c2e20e5df4b00cae34a42fdb67c3f0ab7d82befb25756dee559583e3fc086afb0ac74187237eed52d0f480bda52b6a590cbae3c51e8d36fafc2694481df65a74498cb462972d92697ad398d2874e95d7689d38842eb77d9244e238a2096bf9ca5eb1ce02c9f79cb3e753d3ee12bbb4b959db2bb24924ff0f8a6dd5f1282666cee4e5ff48727e8870e19cb352697d901b106414c706b104c2c1961a5c5ec452987680dc818cf61bfbed51efb88291e08bb0df662dc5dffdea7db46fdfb24d2735145bb0da721e8e1340430e0b4c39b151af2522bd21f79afd6b2a5c57e8fa126ae0686ebcef4e4c5889ff5c7870fe0f7610c41fc7edf603527ae6f94361e3c6f9b8128147596776aeaa36c3f85de0cf8dbbf2878fc37e3d6d8567e7812dee9cf8b6245c92906859491837833f18ffc28e1312fe1f18b98e0f17619e8a5fb06335da184c77c8af1083bd3131d7447094af1bec1f22baaee472ce20c7d9c9ba3775a7c40f98353209c7edea1dfb7dbc527312563f45fb6d162867bc04f86ce3ffcf25210ca96b26ddbb66d5b1234e43a775d735d6fc15dff1414f903b96eebf4861c4208650e2962116568199f74ef47ca90377772939dfc180bd75efec81ff9237fe48ffce9f2e709ef1c8f7dad2bc162aa06bad7231e1ebf1ebd195a0d7887f0c9bb5f80bcd7a352edb8a0ed2806924a6edf5eb956393bb37341e69af3bfdcc29be87af3f6b5e7b01d35cd296594aca9eb96d4e58ec3d6767deb764cae75dd66a5a3c25d12c4b97a4108e193f049f8247c123e3e770efe765ff98077f5da56af7beffddbdd375d94fdb28b974a3d77efea9dbbba717d6d93f2573a2b9d95ce4ae7458ad5f5c40f2658c4f71e7e9b49130e833f1993214c827003f0276372c35f67dfd3f7543e7dd6ce7bcaedcee1420cdcfee3d4761d72da77c4d7278f9d05e3f26bae616bd87ff9d99734c6ebd67126da763a6cd82e87d649296f7dcbfd949d4a6c3aa99505949f05c3f5b186eb531f089fba288a52fa2cfa38d7a0d53ecc2e6d1bf52e767c1a9332debbb0aca448d35621ed7a4c2a6fdbb6e5e05eccb6e5bcc57439f2733195c23c8561c152bed31e4e690b5828a574cbcf7d870ee06a878af9f8366f33d2eb47f9171afbc699e8ceea2c188f8fda39dba84f6b6cd1727a7915fab6ebb038dba89f83dbeaebd70b8a2645ab01511e5379cc7e3c539a37a5d42606d68bb543bfb27ef06e512f03a71b64b176583e78b775eb72d047e587df77c47e7be4a8afbbb360dc12d103d4025ee90f0fb1fa94c793412bccd70e451f45dfb680a2947e0cca3e6b07a64051bfbd85d9a577b1f3a3f6e32f5b6fd68bc6a48c6dc6d2d1d8a95be9684ca54ba131fab7bee4ccfcde12835d7cbe49db28fb8f6f34c6513a93a943d9cfff9232a8909c997f35157a09f518def5ab6357e54cb40e1ae3f9bb0e4a5df97390ba9e9f0a491994c79b813d4968c1110f1c7ea7457c521d38fcaeeba05dfbf099b9c7cf7ab17a401666c1f8b596d503b222d641ebd5eeedeee4b676ac1e3005baf2d3a20543664f9a08c255e04fd6040e9f1531a144cf0fbf471c01fcc9887cb88cc8257362262382ad5efc721e5e1fe7fc99e5f4902ee1317e8baeeba05d8799cb364a7f1fbfff56ae95ceea155537ee996b5ca85f659bde6efd7897229428b074f484eec5bfcad911b5fb6fa5ddd76c4a0b2a2b9d94ab3de9aea8743d72d2afac5edcce0ee3be634208490f21046e87224100beed3a0bf0eddb87d15aabe39772b6b1f2965b89f6f547bd1223be5b2ff1706fb7a2a35efd9048d63e7e58729adbc42003bc5d042b1fbcebdf117394225cb9563990053fae7678d7b7851e7969f5e27d477c8dbbbe7a71fd1743dce5b05ffa8bf555f9db5dfbfddac7fa71e4acb54f2ae9550e4cc17ed51b9a5eee935eb9361d78f05a2dcac36c03869778d87440e1368a84527a1448825f22a1fcf624940ea5bd7edb4b3cf0dab7225e77ee3af2b3ecd37e52937eeafa26adbbfba5fa2b9dfba4cfbf72ad7420ebf1fc32d7c8ab17ad5c5be94056875cca90126bdf77ccbe63eaa02eae69570775d93bb976bb950e4cc1762a3c3ab6fc906f42195b44d0315e1863d4e08d56563aab6c1141c78f7dc629e18daa3e5f76bdbe8d72cac97b4b069a76574aca29c532dc02d27d76cd4d253ca6c09b1703de4008e19c70c299922a4ff880a30c42b80c3f73faf0770383e0401f2ce08fb5d6eeb0d45a6b6d9cb4da99c3cd6aaf5685ccab6df86e98cb1b97e7e4707824e19064d06584cfd7f3c9a26cbe148a3e22103e9fbed90b7a71f462be4cc126f3e10f9f1f77c80f4021d0c8061ac0636cc00d984323d0823b3cbe84f138f49ad8f0749b178f0fa394735218a59c93d23a69add6deabd9ab69db8631b77135575229d75289ab5a73d564e22aca9cbbab3057e6ee02387193859ab8babb0c44bcee14a203f0f92a45757701f0f92b2b5cdd3d017cfe4986231ead8d32cc5ed7618cc757e187f95a45e7d27031116302064cf828c25aeb2384eb53c4b2c0f2400619ee80091c82a850c211ae58c268092782a065bceb1b5d872082c3c40cbca76a9053d67b2f124d03239688c1122eb0610921f36708c9b342153a08c9d3528556d13b182279768075cb9382091f3da8a2a7871e57001142921b244a9a5042637770026e77c0c3c760852a745c628725784c815f8caf25ca486bad4f2801042572e04409204af028618223256a584092a1274243530c112921a4c49112454a502cc815400927849d7e534ab9d275172e3b095f42d882aa416d8e62a153d97500706b6f0c130628f0f85535359c19e863bb67d800aedc8daa14321480b5d64a4a274591e4dffd68e04e71fb2202e0cfcdc91909858ecfa9600c70d95d15e40f3ca3ea85969732b0b43c3faeb507f918728f06cf2d65e0b57e7daac2fb999be3dcc6d930c4e9a1e6dd43edc16affc28ecbdf4b61470b0b8793430ef394f04949b2df8ab35e6eee8d73fbd164ce444b140b3fe18b2dfbc5985be3735f2ef186350d76737b43ae66ab46ea32aca0b9b9a78caa6c512ed420b75def00af1de66f7368d52be594d55abb04ad7d3084040d1c868ab85ab7fc5011234d2e2088ee578bff2d7246caf9f244b1202940a4372ab54704bf88638c24cd668ee18b29d28d292ac4d00c3ac048e268079924a2b0c15a6badb5347248220997325a43763821073a1d901b364fcea380474c1239dc0093840d35b8b842e7a50838a090d86901c40e2e12891ee4b420d1830e0b122b7821c103123928c9428913254b9420515244c90f4a80284181121a849020b44448263404212142303881900a72844890c428891249900cfd180a92242845a4a77874a2456d9491d65aa748d26343121624e9c16badb5d62649729048723343153f38e2091a3847082971841045470c9936890e9cc08d43ca218c33f7c59081866fc3319450ca4e6f3a1f04f44d7cce7f3cf29951af8b00ed38e4400caf2d786de195e5b4008e356d53717af74a871a7f91bf15e40ce6b07238399428702c63844f6ea4f85d843000fccaf0fb82df8ce3fdd0cc6e9fd03d221c6329238410c2873752fcf703b7b966bbd70598059721dac86867405274841024482031826408487c80c4064862808407090fde5b6ed02490350149132d2fffa275a3013125bb010e9aac0787bb032d1b410d7509d40a5e6badb5d65a6badb5d6bf3d0eed371cda6fbf7531689d0d0dad42cf97ff125391df687ea37baa023aa26a7e9c1f810b3c9e8aaa490f300510558fd77fff96bc787c491f05e571a7674168ee63febf9b5c2b3e269729c7f432ed6c3d52c6c35bcfc73c6c5179f8304854ad3c647908218750cfa28a28aa5c7493a882f9e88376bd192d5f5d3c3ee9b1101e8aaa958f8f6711134515cbc7ad87fa6072b93ee66d68523a9404fe631ec77f4c17430f291f43cc7f97d2e1d8ffff5d0cffbbb3a1815ddf3171ca3ebdcb5679d8826f7a78c7422e2ca4676f469194f1df2f2f95dec577c9b58bae438ef21a0b995c760a961ccc4ef9975b3ccc82bb78eca21bd21dc6b88b37c1ed6277f82ea87f7968c35fb60eeae228976fc9167bc6948bfd8e6f78fc963d8578f8fd8e850e1053f14f5b0501c4547c95aeb77094ff7ddf0ccac76c14f9a616bd443fd1592812f1d84d2e938bc7a884bbf7e4226e308cb2115fc67f8f826fc35fc781d8d5b8e86a5c442a4ab319a5e2e8a852717464a9a0828a4b85d5a8d8a8d0f05f8c102aa1e5a4e5a4e5a4e5a4e5a475d43a6a1da9fc70d882dba0fbe69a97bea48cd70b06e3e1910f4b2945251f0e493e2f067c1a322dbff7cdc5217571951f290577e9528fbcf5238d3a70e32105bd19b3d4d3c3a54c119269f89df2947a26d08b3163ea51bab98cc5214451545454a3b5448a181428386fdb3671bf710072fddb93bad612bd3dc9c46ddceb6ddbfad6b596c010c4b97ffa2bf7a66eeb72e48c31c6186b8cb1c6188a1aad25b1d692d6120e06531899c2070fccda22d87c5b9f16c182607104464646464646464646464646464646464646464646464646464646464646464646464646319e16139e29729afc48618509a5047f23e2dbb3c864520c3122e2f2afd11097cfa964182ce75c042bea30141515655886c16028282693c9d462d2048b26415204211549ee493018ac450483c18a603c4b5888afe7951e88e130bec7f1e4cccf5c432b7d9fc5b4115fbebce122c6186394524a29e79c734e4a29a5b5d66aadbdb789561351ca5c53b3d9d062a2b504fc526b7674045b5899cd62942f29a5ac734e7a7444e9acb2bfa0a0d6ac35d3f09fc642944fbb4859a83246d9cd58b44978511549dccef12594dac69cb7b46d3c5e7a9a6f3c5ea23c78b6114bfb4d4f43caa37ccd2809a8bce971a874f94d8f23a5b3b986ad5fd22e9e4b5d6b48e7ae730fb77ff9730dad919cbedd3510e5c583cb9761dae42895009b716adfe9cbb57aad5ef7eea07395b3d2f1d94268cc0524b4d211825b1013f07bd1318d45159c7176ef032c584c59166cd639699ddf62f68f4ff764f58074c3af13c216685047655c7e2b898edf5564c4b0811a9e86d5031a00be7c958ec29f73569a44ef8b7b82609dfaa02e2983f4b0e50a01f18e562942771ad346748efb145bcd47c8cf10a0558eb672fda03d407ef444d506e44d2ac4a4ab9da0d80f2051758dc462417c84fc6c2b9d988f915810212b9d55ceb6726d2b1ded4979dabfb7ebd0d5b2d2a1415bd47ec0ef058d05e1d087c38e33d1587bdcbd298780d8c2eeb68ee84e835eab88cea13dc576e330855cd76d5ec61d6b07a60037d6cb01936b5d4bd28e0ea1401bd3214051458d44557c930ef1f8a4d40787df2242d787748891a892df2aa2217cfb7428aab419258aaaa2a8ba2f7987bcb37ac014ba6ee3840f4e85a2aad326322776b87c2aa3435c3eccac1e30858eb56323a7b073a0059df4c88a5a394a394efeca9573a692d25a29ac1052aab37a51c94108394829a590e3385af29133f649f93b8d01b7f65566dcd2a7dcd26ea51355af1255b0b3d5662e44d3ef5bac0686cf9f374342c17b2988ed31144170fb925248df722f370c7fd906f774f66654de443f28b8fc1bdb6235302fb7b6cd98fd4b611c3ef731fccd88e176c27db998b2a51f6e7f9b41e0d6f6a8cc8200e743d8d3d2026beb8d9ca16ff1db0e42f8479c9e7c44d5d33fc1a2ea4f3f20fd134f54f544d56987b27a0c71fa3c07dd29c6315ba1c442f546cad03339439f96ea0da7a6dac3e9ebee81f4ec96f48ca46759cf669c76938bd3c71b057b31e8e3d8f634668b71dab110a7cf79d0f4513c70fa5a3fbdf807c169bdf92ca494524e1289d4829ef5eb4a67e55ae5c82757392bd74a67f55ae948b972c9954e4c8c43232b3951b5e28aaa5fd9892adbddacbca20a1655bf8203573a93eb68ae03ffe58d0a0c94b7bd220aaeeb4f0c0f77050c50500b979c8178fbbe51e1127b31e00a06e2f0390a6e38ec313d2d5e2e3eb480c104c161d1eab5d289897111fb70c4e5e356119da33ee5f27da2f0c171e4606681724bbbb4012184b385c9d1396b58db8305cb3568ad33aae09c733ecc7ae59aca3720ee032dbfd31f2ebb1f3c77c7ea0153986f6be782dc8e86f22a2753fab9723967ee92eedd9ee372cedc73f439ee7b87dc46ff5e99f175ad74563a2b1d9ea35d01b7454aa9fc9da3db9f96d2483fdaaa6dbfe518b7c8fa9103ff23ddfbac9dcd0549c2f86fcc376f5572f13e77b78f9b76bb0e9f571f26a731c66fc398dafb18ae5eab57b6a5c7586bac35d61a6b89ed638c4bf84b566bacfb8ec97794fe4a19295feafa0e8d65c915e35a7d4c75f5e1b8eb3a6ee6f04a67a5b3d2a12f52b44ea2c8e128f0272b9a150571a8c39f0c8a9f927c54fc3773ce99f6edebcbb0e54ce17d58f3ed936badc8eaf1f931d673e699f57ba639f3eb67ede45634ed2e03cf015b20bdfd567cdbe9ac95dea6d352777fdaa74fca9cd6a948560f98824aedb86967d062b42c58fcf7aa7c55be2a593bd6b27e441ba3b5d1da686db4ac1f31c6c87a45960ffba2b5b6e2afdf75c4ae43dc6996d54385ab4650c4ac7d29abb48fa58482e789274f14f102f0277b228894f2b3fc2c3fcb5c7f6616a40b92e7aec31a1b7ee77cfb3ecb1c1a106412aad829c1cab572ad5eac979cf265395f525abfd62925ab47544939a59c3b5a0e1f15e221fd4a87447afdb4a298b45c353bb30dfbf8b1dd603b7bf321297595e093f6cdf0396da523ff692b9ca3b7d56ba563ada6759d56fa28dbb45bc0f6e14fb8d2e1a9525801b92556701d7f9ea48f1bab07e438db60bd583d6adc8a36a29892bf35f9b71171d9698c838f7767f960e51a51c57a450d077dbb1755b405cc63dc70ba20b3c882c7a72d3939131d29fda31c1b95bbc082bd17f36244daa344f79859cc9bf1a40c1d23ed62e544b887ed31c6db9e3ea54d49184688379a2d4a578cd37f90db6e628a7e2b08ddb79e970f4ee96f2f49b7ae6f389cbe387d1a08efb641be6ddbcd86b3b966cf9bb13d9d4f38fd497f62416f284e54697bdb3e6f758bbf09f17971de353c4d0fb8d6522c07f7df8bae372122ba1759b115c96d2be2f1c1ddc37ab17a6c3ebc4d681bda66f083d041d8810ab63e9ddfd53c75bddd1827a62276e11c7c13534a68f812de0883c7273c72b1caf342a2e73f1f213f43808c04c984866644454d8eac788205abc70bd692e9d90324aa62373e3a04f5f1a991a8d282843a1b8fcf8a6893379fa669f0d6f91e765b776fa40a9c08e29b3f991340b66ef58aa909730dfb62489b1612badb20b6da37e3711cf771dbdede7f5cdb3aa86bd29fc8e4bea8c4544beb08dd5f74ccde8c18f8e29cd09212c1e3c7cbc94ec7143f81eeffffff4f83a409708cd583b5c37ab15e2cd80830754529a59434cba3a21e995998724e2925a471d35fb92895f265c7c5f86a8f91cf911010ba0e4ae5cbcd7abd94314ad96d248cff5305474fa870ed98ab9c950be3d5cb891027334080131f2f2eb43051309aadcf5d5a08c67e2818cd76d15aa86933d780792c730d6b6d6b48ef7b511c6a1ff7dc7d035c9b35b40c6b15384e8c5c3b2fcf6107d13b82455105e3e330c2d8c987a61997cf71d05c9461129226219ea35d52abad2c74af375a0b8ff163bd89aa8ae3ca79ed4415acfaa83c5185821da7bdfcf82f1ad0c2b96720a6e4ef8829f9dca5df13f91253b2a5097a6846d4c47464b2c2f424aa50b57bf60508dcef51c5021d8c97f95e6fb6d89b11f3f5a6e244d5092fbfba6a0ebc312c7f827cf13286e54fe05ca69b7ac30261c078199997e96290897bffdd1ff33acd624a96585c2a8ff26171b1e4b0bc5876744fd73d16b88084d005dc30e6e13fec1ec27b9a45557fb3135154dd5393a802c04b1f4eae37c3c59bde241455312fdf341455fff24db3a8da2fdf441455dd4bdd837d6071b9e2cbc41863ccc7bd5ddcf47029c4e2b200b01206e6022db80d9afe69762a923260b49c5c585c9ec5247461601e5beec58eff32ccad355617f35bd1864f17f70231256f6701998d829ffa9987b15130054309d73e465b816bbf5331a5fd095bfbbdb5efb6f633fbca19ed531bc696d9f77616882969bae1f25dec2df662c8dcc9dfbbfeae3831253f66d79b98920f3b0c636399ad65935012bad79b16afe51a2d505d73140a651292324c320a3d0cccbbd8dd86bb789c6bb89873da5a63fe6568c3610ccc4798bfbb6f80c3a4bc8b8df2766fb9468af62fbb5398ab85cbee94470bcbc924a4555850b49010974fdafd44c4e5e7dd35b7d56edadbc9b74006e4cbb43921bec8e2e177b92f3d0df9492f821ee28b80fbd2dbfc241cf9495de41c803cfe8c9bdfa0391adb2fa6e8d77aeffd6ddbe2b6d2a134462438c9e14f56841737007fb229867849453f7921e10cf8bde8bb7337e28ce9b90e07e051f87e9aad3cea75fad3ec44742a3a3581280420be00709a4118320fe371c83c8c00bc8c0c0a2f5377f7767fe400204d3198b23253310931f99882986211c009c0a3f098f3a84f01999f790ac0f894087ac081c2a75e0401e850f2675ee6673ea2d0a16487aa9d04665ee671ccc83c8ecf4f8ab906a9eebeedd690ae7677189ee8b7e151e7afdbce988add8605a15b5ee6617c37c556662a6f8a998274fa86e527cbdfdc78c094f9a8bbef3006839cf031c60ddb3ea2caee1f51f5c2e5ffe7cdd03fffe7efef4ef879c383e31997791b9a08e3651e078c979179181d8ed4c378185d0c303ed5d9d0c4ffba3bad85f40dcfe641bdfc8b8cb52fb294f52d29461bbeb564b6b6bb115373e5bb1642bd5e8c793a3539ed7d228aa9f9bf4f331e3b54d18b311fc6461dc999f9321be61afc068df2a8a23723fe7cd491940143e663bec54d69092f351fe6df7cfcefa9e893989aef82c7e7e6c390d94f42ba84220ebe14f793fb92f631fd34eb92bbe83ae5c1fb6936795e76a73c50bb531ede5f5e5dbbec3e7d6861d97dfbe0f34f27959d12e3ba0eca73882f1588a9f9e223aa62ec248e987a79bda2aaf2c4a24afecb0eccc7cb8f979e17205155bb07dc889433c5f20b76fb93cf8bd1398ee354b60a3538fa051b5b9421f330beeb0b6373714666bf38c373d01dcf287c796dd89b51b74cfaf764e87f4f8629668ac5d75da9eb5777cd39536cebac29c6039f8f6bb76124d01dcff87c4b54d4041f4595ed6c3c6e057e125558703751858aff54a029c65d7ac3e40c8a05f9bd02a7199f9b87cfffe123d0ddf4f28a4555fd098aaa6d7353101f21a621516502321989aadacdfa0204e4f7d8c17ee90bacb13c762faf24e83efb8bbc11461927a93eb6f33d0827a9cef83768e6d0fea9365d7c11c566515e85fb9eda17cbffb9403ae86d425c7e4dc6db8c789bb1ce6d7a3c390de6a727bd5ccc36f25f9bf23854baed71a0fc93331bc65ddc9dba5a433a3eb775189e70f8a67f1942536c035c9736e9391a7b136f3342bccd08237ed8722fc7486349680825677913daf27ce69acae3cc1ab7b759297243780e3d74d73cc67f9be328d7d1cf67d05d739596dad9789c3eaec2013a673bb9b94aa774e167c4729d07544007053210011c16b800af41db8ed3a0e17dba1a41cf97f5b7b7a1b9b54349400ba1d9a8c42d75a639ea14910c000014a315000030140c89c322a1501405829aeb1d14800b839a4a6450988a034a90842888318c184214020000400c109999a9a1420008040026604c40cc00cc81980098033001300163026206600ec404c01c800900d39ad962ddcf6fa366e7cb9f4600de1cd0148c29802980790073105330e600a6604c014c01cc03985f103023f54977fbde90d80cb223a95a02654065804a804a80940195002f012a012a0754065c02bc0ca8047809502281c00c3c6128526296ef8925346130334013e026802680e614003447c7072ff1a53b4f0270a3890011961fb0e845485018f031abfad970e13309a609304d904f5829e059e8540efda3351ddd04dfb5efa40dc5252e2b60dede6f502acfa2a2b36da04494c87d6e7cfa9bc37ff32d1f63c4d10d9f167bd8d9ed59944a53fa58eefcf7c1d72bf9000ecd48e6ef3969a7ccfdcb89537d79f21a937fbbd66738dfaa07bf0a90d5a35e5b6f991268b56b5273e5937f43eb6d4025755674a066d11503bec58c1396c9f793fe73de6d107e047fb3769be0ecfb6149411304d602ab1ff36ee968cbd37cee25046b5562dc3482c025c4329abe901d211f03afa0a41aa796245a32a991aa269ac1d3c6d58c0361fa6602df8d6281ab6b863992e05e840ae5497996ea6e698c1b145c9d21a87171adcfffcfc9272dc537168a770303d7f1086d86a7a4719718db0caefc97a9f7244a632d575c07f94d1db9b415d9a6a9e2ac4ff472519ca9f4ea63eb157e20c6082e42d1354c5d4075cda21f246aa92204506568332de3ee640a0122aaeb690c52d97ba6cc5fe5e67be1df59b21e56018c03394022f3eb9ecd82280a40fcbcf456a615cef2c026f59038283348df8b70b47ad3a403bf85aedfa13a6b6f6ab9a08e59f7a9d1f100ce269e14db53dcf82cbe1ede51b0ea4da78616cae098c1f827a6e09d583c6454806f427c670ae8c0240b463cacf20bd4d059b78e10df3b6160676ef873e967ff0f57208778628e760cad931c5b6d45ba83129a9061137e8500c730a8b1dd51e1ccd8daf1e0a0cd2239e4ccd8b9512f0db63d96c6a93c5d257b52a075e85df3b56a734abdc0e43b29a367d1e29eb6819df8f3d48795031a0befe460afe8be1d05a089f4f6920931e41e3b9e75eaabb555badb85e1858387cf97f99c1bc2e48fad76b3f42674557980a738028ed571dcbb0d4b9df8975ea0eeb3410953027b940e391131fcf4b209c7813ac248aa628d6f6d9bac2c26881056e7a119ae7defee9a59976e78974d654c5424ba2889660abd289b24362feaa99f407da23711820e0514360877a28df52fd337d6707580d6196ffdf02273bd034bc369a2774bcb2b3b9c5f0187a525ba121b71bf4eaf2992e2ecda86a12eb33079837354a5eb56b6ad7432d8bdd83ced3756d301c5f59b052bd7b3afd23e35ef9266a2c380ac560cf20971638692379c19a4765e50fb570545a47594d9ff2919eaa7d4cf1d13a8ec1be05fe254a3fff9529f563d16e10f20a9f674f876563d732d47aba7f5a9313f1d690352552b8ed7d1f3b47be7c23c51abf3f2edc0e2f4c0a1ecbb8080276bc5f10523da4864c2f1867f80d88acfc63969f3f83caf8048864953dc1061206fc0e3419ed67914de79c6decd98719e2518c0eb5dc55c4957b975a39ed8d035137e965c2e856c1c0e03678a9ec7c95b898e33ba6365dc2379f76c98a9038af09d74cf82ad548f677e8d98946afb6a6b2e451c5a3ddb187ea5dfc9c21ee1c5d4313e135253f58a309eb08d9c71cd9ddb358d3f21180ef0f1001e1424576c7fb4e780c5b35740d7d143078ab79a143574a022de93b6cd9c56b0e3407621061df2a05fa1696cd91bf72849b4911cb982218cba0acb2d8db512daf567329f4b747395303a4de209dea14170214f9613c7c9942d23a4963d358c9b0f99ba347602a1d061d22773516f73e45a79cfb4455552240727422b8e9e19dc99e16d634b9157c85ce9e3c581cc72765671586c6cce0fee7f0eee7601a5dad43f12831b8dadc4ce301bbc540b5e67450850d9d749ef34e7a8c22fced215c41b38668156f16ccabfcf6a386a1d8c606fb458581775a1b1627d5a7c8912cef368b1c21acde68cac0a159ddd9076f12c2ff95155e7e4861e370521e984b7f90d0c0c48ae27129d8ebbb5acf315eb18cb2a63f56bddd2edfbe3f68a27afb53c57b04ead9806949f0403ad5266eccfc401ae95a8adc8839f8eccdfe54b58a5376e8d3457cdc4005e1d0fdca48d3a57eb719c90aab4e6397044309137299d4423649058484796ab0e3248eca1b8a61a06196e2d45dbf9760224e2a9fa7817342f9bf813a8585d78247a532eb237da8d0ab3e850373207069f409431ec3c64ec23b072d369e1c36728208e43e9ce9ecc43a212a49b1a6aa8a8e3684267b8ba0a8cc0af48c88f80a609121fc3fca8bcf84c81099ede1d563bd21feeaabda70f0347aacab59df5c9b9b93c7d4558d641d8d1c885c9331683327191f5160b0f3330889082d73927e4ee8b0b3feb04cc4b09f43cc51b6e1106eebfc16affe0d7936d1dad8b34883816eb49fea43e88f36aae6b11a9b4f5578c8f05b0b5b59334ecdd25fdf4cac2c09d52fb114b2440459a42f552498729a02007cfe48419f125102ea50eaa4d21833b39b1532f334dc7d635bf4d0b9323bd500b0a382de9702f911d3b6c16e7486a94be4097d2e6293f194fc442e68748f931137d7ecc39f5e5325e14b0d3cb023638a9e54d40a27cce419b82e9b7fd927630c0de85a4c600e853df12c53ad273911ee56526608557ca05e396a8d81dc8f2071ad71a47b4d48194667acf361e5c72bd3dcc97c98dbf95225f86e178ebfc6c6e4514cbd110bd95a9a7262fe256c625bef211b0f744ec6f7fe03192091cae7c386bc846b40512383d94790d3be59de0acd070d69b57b8e5d1676544878a5d390d93c4699fc1a47c94cecad56a4b3b7d9252ecd2497eaaa7696cf0bbd3bc39fe1f3a1460b01faf6922a18cb54951122495d75fc2e701c88d56dd4607bd5ebd79b66c382feaf990994898fdcaab91621062189dc7f84179abb33d7f7683886215bb3b68fb9460d4c2495345f7249189a3fee0386051111431d33a88647a3241b388a16dc35cc5733f3c4199cb6e490fe9c9119680e332400cfab9b733e8566d63622182deb3d8c4d0a0c58f188aaa843ae2012a9e2811a468169c4d2fe734baa4f90ce33489078a6269cb12ee4ccbaf9a32f0a8ac0899bc2383e70c0b1493b1d37f9a22cb5518ada9daf799dba0906b053cfe8925050e1fd9ac5a0140cc4cbfa2eb8ceb6cbf40001a603f8da0b172eb24aa5d7c6486134982350d1fd9f07949908c8807b01b60b4011a570d9bf09181daa5e279b717f021c8fba206ba3c361500eeb1ded9f57b3ea11169f76458f92f486613880f5a26fe84c04ba54841d02aca921408640ff000fc2548492a66ea6579ab06f91387aac7f2aebb135a4859477ac7fa30df5435de3a7dac71da5f5c2c443f1d682b8670ee0ea70b80f2c7663b3e5b748bbcc898e7715a9b1e3eb734da4d8500a35e0d2152dc6a7eaaa9d69742fae122dd4b7f9688d4a990dc2bc14827431a6b1856c876380a39a7d1c61f95fd1b61b75b86aa64db9cb058eb50ed1185e62265b414816043e17226721164510b4dbb30cbec7f9e2f625ee0e108f94a60c7de881caa2e508617918f1841e09adf7e452cd89406921c09f10e5861a2d3c1a9118f695276e370d1f6508e88bab5633266b5bab85215fb6a352f2702e0b1869bc732e05ec706cc702383a8e0501d58626bea93eb9e66486f66dce60c06bdaff2718e427f27aa1ce10c066a0fb5e30eeb24c51ee4f687fdf9264b77a211f3834d7facbeed0f238211ef8ad5ca68da6636e811f105d2df1a423d06256a99f3845d760ff4a6d326b79c6baeba489615039e1e42f0bcf18fd09e379e8f6d78b3880888a9377559b5b3e5d06c102dd1a72359b20927be899376e8330aefd93485ec0025384566744106ca088186b398c8e086cfecff9fb43e54e52b1423cdd9d434dd73b31523bb123c17780373d48ab2333697944a06de6cb3141927ba3c42feeb72ff1de2be7954f6504c9b67adb9ce773d7e6baad0be14ba6c6c9954660bc3bd16feca9d734c765ab2023ddb67fc6648f495116353ce0bfa5663ae708d831518a7ccfddf67549a1314bc0d39412b89226ae7fd632778b249d293d89c42dc61d0995db5e64af701a9f88854b4c7ff7d20e82c6988efc595d8dbe368bb510d34e00f62edd724a66572941486985edc010d6cfe9fa845c5de2372bac9b1520260b2b02059f4df5bde705b99a83fedef25b73935e9b3fc8f6fe55f6fad5a304b16717088c5c751e1c9ac801d21ef5fa5484423e1bf424e44945ee82bca24a22543e13e6a137b80fbea8cc187b9b78f8af305e6612682a8ca5add0290a786e0abc33881acec66435f3a5eb50c118f61da96ea3e40fef88ad6f3af7be8a491b228458c69850011f322ea1d4c21e2a71c1781f93369c645de493d97f933371f38886736af5b830ed8077447c3b471148bb241c1e689fa6bad3497475bc7764ab2848c73d9310084e3788d5ef37c565052550c7b3c87c73938b1600c1cefb84c6e46ad50cea6fe0cad6b6ccd0c2ab53e848c21ee311bb45e320ec5c6246332d54de9f6b6540c3bbeba894bab1ad1f7da68da3ab3c8c421fff8e1801e066c0333586aa07597c9549f98d1316e89d99e6b711da51c096912d86466982c5ffcf192d855638e7de790b346bbd1766eab3ee9bcef0b27bab4fc00bf358b048387d161c4065cd1d11777a582ce6414dc5de5feb1c758a0b4743df69a51f28924385c64047bffcedf9b063ee423d9e8a8fb389937400a97a54eb708b956d6e0bd33e283fd15c2d46c008f7c3fdb1e2f2e130389d47a7d3780460fccf2d30e0dafec74401cf0a9d192b812fade4ab4eb31e6b2c9b86f64c131b02a3c8006624baf7b34204e71295227acdb12a6ee876a3812de6ad6b1d5a4d10e40f4c71c71e6d8482f49d7e1b084e405c612fa1459bbc30f9ea1e406d6d0fdced59103b63b3f5f216d81a5d8932a4809afaf380236a599caeacc01b8eaf9e913db3709b67513795df0963672ac65cbdd9be18b9c92afc913ebdff58372f4f5d41418f731496cfdb0720756a811ac81eacfd38406afa0df633bfc58033092d0c8001578b798093bad91c9022c29698fc17a9c2a47d78d03260e2592b0026b418ca0e8ddee57b93ee55319b8447446b3c5413d16a89d80637e83d651af25df5c7287dd50dd45c05b088b59c929664dd40a11964cd3c511b9a851addc97463328cca31464124108c5988f9b70044a215e6462d8192da84f9d9d298a63a5c21b7313a8feea100c438afaea79e3f7e955c97f99877e44581dd5c73f38d6b58008f8b99eebf75e72e3d6ffab3373cf10a60a1fa01bfb95398a876b33cf3ca264f3e85b6ef4d2ea562f2e0028ffade636dc50b13953f54fb7a7349735fd987464d187d8803f1dd973ea8455c96dd629daccba5c7dc204069cbe227ed7834808b45de3075e7ca1d50840a23df32551a0ba1250455b7af6e90281748e9d21747606110e71a121a235c359d7270834aad631698202c797115b3adc61b126bf835a6292674069ab12a19d1eab01ef2603895bd302d6aab60767439a298e9bc61f32b1289d89a943e793beb47c4a25fc6889eca9526ca125668170269336817c4489c0d57f484c92a879d8e495b9aa99c290c3b6e5f51d79f251ade66a34e73911763e5a1b09aeaddae99f626fd802ae8f4bf280216a67fe8ae68e28d016121b61182396145a23b44ba0406357c68480660a4307f7a417bf4bbfcba025de863731a7ec01979dc5de4e22c012c3c15e58e8e060316d5db194bcc4f9c50dd254af1dd4e7a796da319725067b8f5c07305e3c468295f4476e9f4d9ca2db4d6c2611ae4b5da1391d6a4ed2dad96eb368d95d3246ffdf4fc82edcdca576fb6b461a7975fcf1983a5e7d1b642dfb4dc6ed6750e2a50f3d2295b6d3a80e9fc7617c2e5117d522b1dc2864485564588124653188909458b5efa884e877c28e6956a20efb773097383e74fa17cbfa09ffa46afc94f93fd224b393a7fa7da98a653c4f00dec7b7ad2f62376e6b1153d7beacaa25ee20eff3979555a33a337e20e2a0bdeed0508744fea85d52644a0caa104a90a1cb9c64b477abf7a495de037c78340105571f42cf420a06dcfd520abd7d3c4d66313805fb3542b7cbe5e635c43cccb47cc2c66a6f6bd92a45c2cf3ae03ef79b0c5472ae6e2ee62caec759de577a6d5b8234c3af46ffb93d433dbeefc413587cd09ac5bc810d29efdde83c030949ecaf4fd17f5a3c7899937734e1003255f6f56eea1f1ab8d645f868170fe05dd29f67e7e9f6795b3cfb1a678e95c1c12d92e74788454645a55714a7fe235c1c1d43e3014eff563a4560d14aef19a433f96a9bfb9c04e5135c0a4fb8611b1db98f47d263aedc3682cc34e9121170450b04ab755813303f7d1bb9d819f0306de80a6e40556f2e1f647ac39b58c0240ab11f470817b057cb55a544df396e6e1da39503f025ca043016b96063ba12379c1898a0fc4dd7648357b6577f592a594adf4658d6cd363199d2ba160ff456c75d12721905b98a504f2839721c5388b5245accfe534cf1f66b4a8295ae2fcf434ec79e013460a86cdfa7c68933c85cac36bdbf2f7fd9a81a39943034892b0098d603250961b21e294a4dbab0cc94314250765a6856fdb070ca28e938316b67e7cce63f4e1f24df2ae18f990eb534fcb1ca9d807eb061dac62a276389dad87b1116b1959adb00b8297b25b22b9268a0d534e2667bf9bffd1e861d4f46b68efbc325a3e3e3bad4ad713d86bf570c4e42fcd1aaa0c85e012150485150b4bd627c5b8ca746122f7413b779dc2d62cd73dadd6d7e28132f91fb9a4db2c93a53b06f18657f7fb921995badf567e147c9a73099c5373249252ef4277e66edf43ffeb5a0d58fd7543d84eff636e5c829ef423c2b3527a35230a286812a92124567e7c2a9df870e0fbae11e7ef2fdc174eb9db8963131aceaa7dae357e4d68c4171a307f185faed9bb02f6ee8fdfca5c7d87726428e89c9473e32f301d7f2c9ef39bfcac7c7d227069c1bd063e9fec6c26ede5ae56917e7626cb39d5210c5ea719510df3cb4b576dca3e4595bf19f25de889dd400a42d9592d16ee6a521c21b7f8bca5a5cf71de6eab7ae4d635254f22961c3ad99cdeec956a2af1a305e8883f2ff63ced7b9fb43088f859e17f83129269575a4c41a2e21168233f0b5501c23c4b0384c1c5e472f5cb77ce62bf7f9cac6fda53c390be5825c82647e496c341b0c06a020495c0c5cad61563fa699c761362e7e4e131c8a5e49f9f76128f342f6076f73a5ebeb5cf4a3b5c198ad4dc21ee764d282c3491c4fdc60c5664a8810b85ff79ac8c2350ffc9a17d59369a3875664386ff38c27f98cc11fa28e16cc75c71b23fac0f8b4040b229e16672926d04f8fae079c8b0280110ac1f1b7cd6f8184741b1927a93438c4586515abbfa1dcea14757ff2b7b61115f62a2502ceef8331fb8e91d6f207c5633bf83c9a74d0b2711293f2bc8dbc72a6fa547a29ef69e4a62053219192528ce2607828f38270b2648ec1cbac345aad48cf1ba576b6d72f5cd955fbd3c19c218f6ff987c12d99753d97b31104ad4e1758ecf4ce6467b770e8f1e5183e3b0aefc77e35f08e0f14cbfb58453b3d94ba1bdb3b0213fec5222b3f08cfa662a1f5b987c75005d2d05866d3bef1407a880a004a8bba13e698366f32811aa8f2ef696fd4f28dbe06053fc42d446a9cf3c8bb3b5883e742f419e8f6b30760cc98a7e1841f1221a17d7d4dacf560760f6cc8b993ff611b4ee9586b46464af04fd17781688a57502f964e222e3529a637e1226c264f943e1cc699f0efdaaee8e4b16bfb39847fe242b464a40d1d65756cf8b9058b0fa1fc1a1f6f53339f1122e8fe3ecb384350732351a3a1a14d56b0ad2959cd7674c8358e60a75b51d520899a6da412a24cfb5c4a56921708485facae9231f0a5d8614252886d80982a926bf32238f3d51d4b9f003d623dd605ddf08f3f883526d7768e6597a5fceb14bf28c4831b1cb1d2d8c82c327fed9d0b6514e4227cf95b2bf31a3c69c7af7208a522ed16b343bf1767482c52b57b84d96583d5816d69f7ad63932880561df413f357b37f687a32278362b38ff9d4b9d676c873404ad7a967c98805495b7809a73f177fa585c968b4344b6992ea8f8439e7cd3e226bf78a59ba179bae58c952584a674838cab3544efa6cd52a102e68f41e66b6a7f965c5912e546488888a0767220b114993401db38878f3944ba4b8275696f5e10377c54931601b21016bf5cf8b07321dea3c97d78636a7bfc6f378122fa015849092b68bcb655940dfe87a508fb65216210849181911ceb28c6824ebf70c1e0131a2fb85a4bfcff2d7e77bf95ec441922814874de36e717980c3a6047e382e174450a4327878a934a4bd7974bd1128dcb71aa7ec11e0986495c660b535b877e3125612191c0ac1629fbfc79d033197bd40e136764b792b1b02fd871a13f561b40455236e65c8184a46fb44486df70dd1bdf91ec2f39f5c29baf000bc49fdb51a53f0d39f915ff25d4aa953782ff129bbe081020c5e612e5264206ab2044e23fbf6df546318da6d7f3e010a5e814a4c74bdbec8ec6b2a70aa68dad5cbd205aff91c7cabf43536305a1bd68491ebfba7564cbba07582fb5b0976779a244cb38747f56f482a982c8589306554e69222e862d084ad62d3ac1252bb9b893a48d87965044735f2397fdcfa3d655c6889abcb65a8b5ab18c4895b6da5e9b7bee8aec36c606a6641621bf3ae91063296ff4e6dc2b1dddeafcb84c7f913ba1aa15e30120c8f5e0ad83e7bff98975e4f08f0942902f41de5e10040d5a3bef8e9c5c0cf7f7f62522e2a537829471698417519d6829e8908b2cab837c982677adc9248ae5c9833f0dd6d6f6664888b3f6777a379f9c15ce964acc0c05bb7f331c18477991a5303c9ce0ed6b006a1d185df1fefa78075713ac7bd6b2c60cc613cb789f612f206a684c7365b5cacc7d3b16a775a53fc7098e6cd8a889f66e89e1112fbebcabfd4b8e0e66f4786be126f41aa5d978f03a7706306819682408c90dfc421d6f55ea7fb7554d81ec3882fa8a0a0660f51ec391f47247dd3b84cce819ba27833fbc637c93bd4cd3e567e8cac0d22c10f4ff1151b173460c61bbad0bb9f5ae3d847302200c047b6eb4d39bf3629a0f4aecb2d173fe3a6f11d2b3dd45a715bc84a435d92d5cc0b34df9699274dda1f0f50469247595b3ab069d0be3245d64bb22faa30c90a50081565aed5f32867534b456c758269114d39528bbbf6a31ca9d5e1fc79f913ff081d2a2bcdbc55b1ac573f6216ae8359f9f2a625ed35d1af24fe8536346190153b4671025a4595629b2060b77714df023a43fd28db88f4727356baa0b4ca301ad1cb1166a509628dd4b01182b3223d059e15abd1836810a8c079f0822932a234b1e40947cbe0bce8520d91a7445b64a57e4a635e7682b5818a786728c88be3cb1f5c368d3ba8f131aa400c28ddf1f4fe2f2d1766484be953c0258aff46e0320ae351f417c19729f8035a84085c42e11fe82320f0128ae352fc03c12e08b8e4fe45742fe6fc08cf121406542fa3437818319e5eb51f529225acdcb5a7071c37377378689bcd01f938a1192bb8c6d9dbbeceb1c752f7a5ba7ae9a0ecaa0a912185ce4130a90ecbe26e660ba7b0b67c8227ce5c886b76fc862172c691384a085728a225dbd107b7f80fc5af913afce3b1f41634b90729ee7c946d7101df3dc26ad987b1b574429b91f0028e94e4eb41d294a9d241216ffe806e5c604ac95832862f00fed8fc1d232cb382f44228b1e2a8a265095c223d628d8914d5b4a71b6564036bc71bff852686c61a995f28922502fae7a93466358f3bdbb9f54b37971a804c43840b12bef1304bbf9c853d4bb99503b4db5a4db8d4adde56858ba545c4930549d07ef296a47213378d01f4822cb1e18a20cb2efce544903f77ea6aa71613b4062f1b15cb8bf85552e33f109e840fa82454962af42add5fcfb7bc76e98b6b41ece4f8931fbd859e6f11b7685a3f684e82b4896e42517e0d0f340947d7f7553740378e79f6f5942364135f2c40f0d0a8cc0e160593130092bd16e30111ba418d00f31668855b0d9f7f4be84f20c61f4edb0d8c35255c5a0010b30400ba27e96bd0eb4848109eff46a6b89cbf3e7ed21b602711fbd936407f037617f0997426b94648ee684369257f10a2469990804cab66934ae28903900bdea986a34a92e3acf1ec08b4482f0ca51549fa8d19f7bfd0b870947a692fe6488f2001fb3be37f27efbb2bacb8397b0110954b1665b57f7dc4444895bd008baa0536ee5f4ac00e72b56eefa90188be86fea7294a4ba6b09769faff69e00188ffbd6c8d4d5c5d716422fbb7114fffc865426ee49522252f00931afcf1be8ffcfe8f65a864b34b5b07ed51545a26aa8693fc88a9c6aa368230e23f159a85df6332274b88ee07ef76e5481a8586597ec1d1d97f2ba9aecefb119dd0a6eae87e579d5c3426159757e753889eb2d17ea334e8742da8cbd9548b7d0b12829bd1292c25f022de31f5f5cb9c2dec96897ddd6bc4b90e39d33b43aac5b8e366553548e1b4ef1fb020970a6840771530f3a6ca5ce304ad2c272fa86cc3d8f5df2ad70c8fecd6c7e4c2199010f1f70ec204f889cafda721f05a17196c7135a2479002759bb841d62a9e77ad390825dadf97b204ae725bb556334942629279f9fbb4afd170208754bc5babc1096716c95aba3429f6a2364357066b95d58a9311eed15bfff5ad77f60d39a821c2a85ff1932a1428edef0117bfd3aa824a8ba697da58cd35ee6884818b661ea91819118c7f77dc84da57540c1fdb5857ac3a34a2f42c8e5a5e72a76939854e90c18655f170a705681bf46d9e423f1b4032676838f5a1a141059253235983b4a779dff2522e787b4c86ee9f131f09de0a48d13af15364f7bb36ba3b4204fab080a038a8249d928c50c20221a4a59e03b5e9187e141111740c29d6981c06bd07020d0c779eaad808c6807bccf2d69049a056b723124cc624e9ad95ebc1a8510d36faedcb0c591bb50a4ddd407a4bd92dabc10124437cc7453b5fe2e4f4b4658c71c122b3c4242d9044b25488a77a711b6922b533e05e3814a76d7322bbe39e909e82a0060627880ee97fcc2001460bd82a905bfed606086c2068f1da79126e5079d0979f256c8e371192cbaa89618b85a1dbb264cda258e2daf2607c0a1675397585b9c04134b0eb1b5b2ec325332a112863e904a8db6080c13755624984885392fc9485b081d5b110607351d43be063175ec05818028c18fa32a788beba3dcbcfa765375952e85f7d03a77c127a7189f7fcba66302591cc09e2615ada7904bccc74838427f0452bc11b1319fe5418885c6a9ecb3efc9db4acb2479a680d77bf53ab6be6d4ad48aa916e7b8e47ddd0d21e552c375697a17199638e6842146532d4a561352b4d239380fc5ba8dc86ae603ae4085520ab461d7a14b5b941b1c568b80036a9d7548a824d0f3ca40f81a28c8a3f87e927202485b047c1e2c65a76a53fdd0cf7155e08d5c07cba4f7b18c1924ce1903b4e80ffd4b75f30ec2bb16099bdd095cd0084dec6a918120e4dea26e45348061ef76b2def870e710f35ac3610abd73ddfc5a6b288f95c62e8c1be6d0ac1a90a6731a77c221f675d381bd1265c3856a6637a45b1052f89e350f0f4a57188b94aca4c2a39b40e2bd8014ac338cc1e00ebdab05e7b968db62f85ed2fbc33b7543b92cf944e7acac6781bae49fd19e7ac0315770715481735c7b0ab2a8cfa2d5a7c110988ee3a68e4b0019fda316462b367e315008a9a6592b883dfd0d1910ba64e610b44ff27c80e390466a07d2de6abbc18771b5a7cc7840183368eea050f819c661c46358f151914e8843549f7cbcb32b61970b509868ca9b69c9126313b52603edfc66d28537a02d3949a544ba63636be49563eb55d059c9de0a88a45aece58c7b5eabd77db2a353f12ee615c4901c6a2bef0ab51bc70b6b35e8053bfead2024a0c7749a8163c89dcc3a538ade2371d674dda4469ce205d875f3d132923f253d02620915413b0320043e8680823c723ac89bd5c51f952697d1fa4592343450070de10685f1227a9482b649a1f4c5973112c19eda3cbb104422f78c9d902314fc7e43218f86f8f4cc594ce888e806f43e3416a676390aecdc801944b43fac853c00dc5f363fc03ae0c3f16a40bb8f249e9958732236b94eebbafc0171216799a7db432611fc1b988a2f63fbcdf6f16ea480a28624f47d1143428d8d9500403fe50025330b10271c619b6cc365d47ccdab97e051efac3c5a7d8962fd62c575240b477b49afe575b2b1f49654340fa442f5bcfac0b94aadd9915cc4d9a485795661707fe2a9287754ba59ef328363b84403e8e08d58bdf24551972a45fb774db83213563ff4990245d125bb62cf6ae42e78b6fcf2e92120ec4b7a7154e633e74758dae37020da7375949615c6bc15184f26aa3cfc4206a5940136421b23df386833c8fe2ed8108e304ab7bf4c91c69b88c9aff341f2dd16949b149c77f71e68290ee90849f4a6808c14eb9aefeea8582c942cef3b5cc7f450e5e03d3db01c5c6fe7a0a9d95a4cd4cda26b0c542f904b5c025aa210c5e14f3c05c3f49344b6168e774a768dcfbdf14865380ef6e00422cd48bc9eff701a2a4f32b8ab671492491924b30b9266abb15d2e5138194f8e8773d1229973467a6d1a3c44bf3ab3b3e72917b3b29cee93f0645f811e4a038040ae5322cad15061bb979d70d95ac69a1e2c3eb6671670dac875f1bc5e490980b44e40052d6358839e08a229efcf0a15d3ee36c0eb51469a3488e90f47c9d1b8c257082b9bde7df37af533e371f89b43a4a5034a16e64149af8ebd52682c54078648a5f2878fdce3310e18d3e205e893ab0e78a5409bd1d619e9bdb550a84075722613954ad4d0cc7eae4d4ea8042ea76edd0d8aa7a3ad1bee8f390c292a9b470c2372c827c08942160314fb18f2abfcfc931de14c9431de1ced81f8a9c15ae1c08520a381ec34a966bd0ce68ba273d130992725486b1ba64c109b70235de50af0e75ba1154d0b916b5c9dbdd5dae19cd56966b4d6aa0c2b24930619742c7a5d3d81b9606157df5968ae8ba2594619270317347764b87924955da98411346674726a8bbfd93deb65994343e260b8b50cbb062a4714422da50a34dd2da2106b8d059853fba26cba7c2a6ee23985cd14ec6683e16b7f37324e5f290c80564ea7d117db318f3551c90ae14e13412e6e3db02f82a5b8aded061bc1a93e7a2e6258b911852f35f69e9c7bee8de409946a11976b7b972a4c08d425c48fa522e1582113130600ab03b9d0039e4aeac71283b9145502ad59c06d6fe00c197fe6dcdd50e4fc803752cd12351a4bc6005adcf8db3d8b38e910c6dfc9eae24138331ceda2d44bfa81e53f905bed90b10fc37a72c097085686af13d146118991408d8d4735aead758340e97542c8183e39b7fb9f7d8def70f98622b61b28b0edc0a00c758d625c97ef3fb8bb6ad471d8b8ed6af045d00d5d6c4a891888412e984b47fbc35c4f95b05f8bd20d57257ebe0c2c81b15d0d81074116181eeb1e4b0297fb3df07978f2cfe77bac02fcad002d470725e4148ce3d99c71ae29e2c6b9c4df99510022142a275bec4451c3c701d9a77ef9dea4fc9fe80b084442279cee246b320aef439bad59fb0c1a56a1925059a9613dead9cebb079182328c687477e4fff81d31f395f67ac2d908cbee0c8865957d92b6fb99d6535ee8a08e62d870921cafe304f3397dd2e57afe19a9f66d1b63bf35845299bc12364e3a7cdf8345bc259a4f669b9b7e8034f3f5a6e70bc899ad803d35731c7f369cb8a1c2dd0680e510b3264b6c2d3d766b9ea2f2f6a3964b0dd1a60411f7f6812e735444eaea8d1c5abd46aa4fe52e339796c4020e85f91657ec5563c98b8315340242986e7748ca4f966409fde6dc4a01f2b2c74c95abc0f16e5796bb80e126162107e147c92c0058a886055b58f916ae90fa1a058944d5f4ec3c4f8baf0efa3bf5f1c093eb828368215918ad83a911222257f1bd5ee935bf643273d2d43272db2e3bf8c7e939a7603a67cee368f5f6e975b5ca71a40a4188daf2a9ca4dc203040b3d435245fe53159954e3723c519014ef15cd0bace0804c8c9c910faed3bc58b059a270e6f52873ebd3b6fbd4b791e28e13eaa19c4b46bbced34d56dc759834c54d647fac526c48b798a7c1e2003cd2480fdd2919caa62e852032c2baa6ef1e2c68c1b10365f37c41f500d3621af8ff61b1975c18ffe647b9d2e30247de90e285efc8331e73ae519de25b63fd40fb062dd7886ca5bbc47ffc6e4fbe5bc24ad04cee9e72fb8a0d5112e261b94cf3aee98f0ad9f0451d53b0b107367ab4b8068137a7958b30a6f8391f25e32edc8440ba6788e7206c623e4796fe04b64bd5dbbd2a59f3412517592b433034a8509e3c42248208fc63a75fddc3c3b3d58f1732d3732d790355889601501a069193f68c25e1c610a843e2116125a5f129178a89df4564dc7adc81c627ea290d5e6bf294058036123733db35d308fa16f7916e2f3d170a6c71377e49313dcc4813c9de988731be92f649f5bb35dd11e8f2e477525c4dbfb5c20d907c3b50cc790addbeb2f0948f9f60a356a22f7fe384045b869fc918cef88a8d57b8a97bb25122112809453265dac8c853f1f901dc98342c20246d4a576d95504c1f81da525cf25c5c6ef670390168579360cc75f92eb17028ab5374abcb65c3f96686f0649f5c0ef1c5d75ee01bdc8568cffdc77d77049ca85ec52cc1ad8c1ccb5aeeb12a7c2ec8a4d078cc6cc9ae1b395691b832bdcfb9f95d42d325de0873319412ae426deb8116013ce42919d95d4482b43489ec69f571a1c756c293c501b15057da69abebc42832b0b18ffd88956c83cb65bf8f60c630d789ff761312877ae9a1555c7f05741cef580fa1a17c24b73d702740b9230227d156cd813815c73a777cf790f5381054d45d58e68ecdeb3d9a12c74299602ac8e58c25c764c6989f74a838a84243d4da9a719977079bbb10d5c5b93b6448c1fe0b85f5e36476a060142c340f6b15115b469189e0084ac075436ca663b35b419723f63719cd4a87a119e0725faf78e61c1c518170a82d6ec4ec72db2aea146116a183fde20eab21f200f6188997e77e5c24b221fe0000be70f44790f70e94030268fcec5d91ecef4d1aa98914f7394df33d5336fa1f4ee7f68b2038e1a0b21980bd52a24f99a379ccc7ee8e42f2245b98789444405f0e8b9f1086966ce0e69b1565ff8a0ec990ad71e6417b02e8dc2f71eca999dfd830d9488dc08d8a39906337442e3ad01b6ff27f005c268d1b99e129420158ef27d6039e9897ca65cc9095e019f45e244e0ee3ce6e3b5a872be8be0a8c8599b5505486be967280acdaa66a85a904a06d71eab8dc5db9ef22f589004f871278b48bc6ca869e170d3c64c9c9246645c150dd2a2ee582a4b68b4c6f58c5cb0a13fedb49dcc7ea98bcda6fc993ad0f68458a561caa4f3e28b504123bf79d491c8ee240ee3707e4407d5403169a89419a8ac213848efba02b97be6ad501c73e2e1f505802935265bb5fec0511aaa4d0a09b5dc39ecf4ea3dcd5b452403771f66497bc6ebe41b42c2302e8b92a5fc14aa202f663f81b0ccd15493ca45877816d40f6bb709a988df0a1a1ef02b868920908946d1466aaa2454c4dbd064be9ca5a0da9a685232b5e67c7495c0316f696280609a3f0ef85ca1be3cef4bc837e7b0cb99376798f275eb2788f9f0378d5bf878c089400de60aba9b91801ff842ece22d2d5f02cecd883b68a08543aec4e7be1747817488a3d54b5842f9839239abc6593914f80f8a345be66acc65f34a01d40ad20148396eeea4fa1080745db7c52c43f4d2447cdaf8ad87849953de7f8e0b39d3cb7529ae22d81b0cb54254358a01d30f402d8b81e90bdfa27d1dfecfd475145c6071d13fa6110e47d5e0311e8a7a58cc228c01a2c6f47099e56b609bcc6eac542d95dd66d95fddf24c75e24a053b92ee4df897e1e528cabf10f3a273327b12eeb6d5d223430765f842861d4fc28839075961c632a913a27586cc1be7e36cc64677138caf9fcf185b43c600ca180633584e1c86a3e4d0b9873e2c672c098d4be68f5360271980956d334a4eb295a41ce3b94cef07ce9da4209e2caddc6270bdfcdd78018ab692be5d3d017415e66fc3e5ae0c046c25f1b3346052a484aae89f4e5b2be934f64061dea3364ae806840934cc342cf51da854d9c627c363b5b97be018c887cbe194a6a5236952a79c56e74feec6ccea157acae694cd3fcf288696a0b19e6867c07e61bf06dedba39bc867dacc15dd04ecb404548ed166aa347be6d0252cf2dbfb66ee0241f37fb5287e7f366b380d1c28b89c09755b682a89d80a5264d7878e7686febf3accfda31c75e05c97ef46b4317aee4e57181e77b799c966072091fdf5d476aeb1f2cf02a013a50a6eed347396843bb53fa27e06b418a9e3771e827679edb12026d6506793cbf5df5d80ff2bd9e7ce5ec0d3de1e0a7c8be1ccf9bf98f50a91b93ca32c99fa8b847893e48b04417d0d647b03077b06e93764fdedc397f1d021df4f9e8ac93f63075c1d388a5958798627034e025b441e35443903d133f2a8b28c6ebaf14454a6157d2caad4b9bda874326a6e74e8990f7a1c72ba937c812f40ce51b0bd45dd7050fc3fff5e4b91783c7f9c0a7bef7e397b644b00aca9145b6468e4051ec9c3c547dfa1bcb4422f0a5d4c465de61504e8f616b04742052cf2f56d7b01e9917ad3e34c32d80ebe7f1e50e7b13d7d2ce98edcf24f9a7be1cf083238fb00f4a4c37b3e5f17ad18464b7e6a843044f3ffb6128e7c0752c08204c51c1ef8f9d5d2ee10b33b0703f25656fbafd1b5200f14a51bb68003028e4961ec2a8ec336baf68f5eceae67aaeaa2348aab71002700394fb851348ea1bfe91b6dfa2131f28fae5e9705ef72fcba37773f21811e6ccd8be4f9f8e270dd21f7bb2bdda55bceae2bdd9a43c8e71afc17ddc93757ba35208941c941822eee179609e8756f8623e572cfe85eff33ccde329748e9923220b5ecb788ded083911666d2e98b1f388cbbf3923ea97a5c024a7114896cfe5566897aff674e8468871e2e2afd08befc7b4a35b3e2b6c9a76068219aa99fad9107cee479aaec76414b3f913d3abeaaed70822e3adb65a8ab989bd0223c99126ab62e0f3ed79d79424fe94adfefce35996123547648860a89382d197b5e71518703aa4054d47612d5b29a26fc4348c37cc46d692015d223749c77e8214d7feb2225924ee9ecd08dfb6f6958d22b7b0978190ad10db05a5729e40fcce2db750b8d9e1ee7e4e8087b4be4bd9f3bb27ff86fdc3b761e330cfff8f294a871c37cd12d54414cefe5064066a0763e1550a482abdb38555b37ffba85d27f0040da4271631523e739adbc5be88c571e5f612d030ccde4fcdace948d3cb5a8e64876e0fd0b459eb3f982c1277dc1fc3d0d4d959675bd8be0516b9fa10f7c803d527bb1843086001d8827f81970230c907ef756dbd5c399241560bbd9b4b3e03673eb5fa4d961b4f2447c8b02e9a433ef7c825b5df3b25b66185b2bc77e6301fefc541fd74d05585deecf9fdc8315a2a544827ccf4b33a5adae099d44a8f41f86b42c766a88e157ca6d98c6c06971d359e654ea3052673bc60c8a2eddd7c2ca3822494a83347a0a2134fc31515551d74cea3e9d119d5a8244f44062e8a0ebd84841ad356374c60ea8953364776f27b2056d6ff1c18fd183f4fde04f713d48235e82c317e12320b654ca8c475fc2866f6800ee30fa657bfbf63092d689ffcdf3572316fd306a086e21814b48b879c0b9f8cbbf74ce0a705a07d62ddbb5da87c50495141de87bdb739a5f5db341ed026bb9a81c4cff2638224aa9d48b462c4cdb5798fef00c8f235a618ad4a36c665daca437f67ab5be47460824fcd0e23528ddb77f74df099691a1cb5d3e2e090efa4675c07543bf1c421ff063334308812d041d545e83b1f88a93a0163382f1aa27760bf0f06ac277d44b37b624e95717cb3e4074b477ea037cb853b6ec960dfb355bd449a05665c5724429795d70bed49e64cbd75a357d51da67e10ece86118a3ecb670fd4e646e6098da99e4a7847f246b1540c48379ac25b448737b986fc2b180f2e133d3be8c790263b84886875b00fa0492c711573750a3e67398537ab7dba9b770df07652f7cbaf3f56308cfa6b0317bc7551d85ff286fd2b7096dcdc0e03e10de17f5d1d85216c568b1710e34a29db4109b7210482ddec0b760960c467715d171e0fa9791e4ab8756885e2c309d967540d47807e089404df7402dd23afc1b4e6733bed9c7a73dc68f6bd9e9d13a589466d968a8af7d4a33c992486ff11d87c347e0346678a7f1a567d85e928d29a292068ce253e374802759c86546629ac55947b4f1e992c9afcaa551ca39d21284286de63b67ad8d7c5413fe1d226afa20a84126b7165a30f8fe88ba02842986fd0f2cca11d1453e0991e10323a0341b5caba6d958543dce09b91d3c1622b7940be90ad2e6e910ebe57ac7515f47ed5ad3539e3b5c580a9e66c538a7e81dc90d71a3c8ab3fe8f9b4d7ca038237b99522b03d12a6221b43537d38858b28ee14378cb7ae767dc97eaae1c32d4f9ee5fb811704a60e2e78a53e2761bb4910d1807d812463da90a87a273c2f27f70131648c605dd1c029d045cd3d061972d1a8060c389402c511bee1617a89941552b12693c8205bd0a0d3bc0fb3d650fc15730bcc25f563d162fb729483dee5198030ad1f5f66015c96b381414944ee0e678304840d36e75c89efdd9c09c4431011f640cc02cac61c457810312c3275891c88366259b0f9e63d2cca2314f30600d8d676f01a311a9070cfe334099e6ab4b11654931652e79c759d5eb5e0d97a26724884e591f74f865dc0f4984bac4190636144391ab161b283a7e05c6d1b7d37354b17d2b58112c978d416172c00286536602c8e021d4fb2eaf0156f0b489532d0456fa2a60d9ef0c27463733fbb612add0b3f1c7028d4666e26485b32b968534bc4f75513b1082cbcb53c38de5cbf0ed2d677d4d27d3628e5a9155261463a34cc96c26020548c3d1c8f1689a09704e56a93b90c33d2ff5c23076f455c12b0600cebdb3782c4ebd188cc6c25208307a60f9a5f066b402c4cd478590be85fec0c65d4beccff8bfb589bd447c8a01831ebbf3e0fed6c977b5c031edfa17c72512c6f319c0a2314b51c00588617ae043269198bf440b21b687558329eb4b27589b5d93f887aa0cc14d0251fac40ae8e55a68c0c0a61cc7232b0d46a47cf19a4764508f21306946241c5b15fa516140246840e5c6732144c28e59c7288560be925ea0e70e5488630006ed4738571b3104ea6005678dffdfeff1638eaedb0293e578c111e9d6cb07daa61047e2757351e12e83cc8744f697b2cb1bc3180c8d8cf40c7b30720f4e700b3ed404251d26cc43d18ef8eefeca22649dd01b60ae1d5ee2147568ba1a75594d0c00a42e729f0c9a3956c7d9c4541d91eba5e53c7c8e1413f59f350c4511c18321b1235f57f7ccced036f2cb8d8ffecb3688add92348c4492a1e71f8b0734457dc09e016fafc74310038079ad9edda607f0a3b7271e069633ee99960c310b4c855b23baa8ca204b5b27ff626586aa5a5404886407d31dfb3ea33a2f6ac3a36680f7a356b606b38fd01e0990c1b083abc65004bfc74718e86af92ee8a7a7a3711885d4094072e3526c352a32c14d4197f385e4e5f10e3f0d59ec6d176dc548d1b100e92f852c461fe529d4f73426c1f6bec768f3e68a64beb99412daf207df3e8b01c5bfe911b3af07079da5ca82b0298a27b9b28b07940b5e3dcbc25039d86428ac0c0f03987bc497ee5927793007de0b470ac0a37aa315f346d4dd1cfc4933804bd84d14df20f5cc71cda368a3847a151306b6917a81ac4e3f805e1d8e6c2d4406944e3e1cb40ca60bdb6792269db556821ce868ea99225b47ea8dc31ca3a561deecddf847ab52dce2cdc443e954b462ed7c653f13dc7802d9a54934570bf0aa3e2cb3f1e5c217b5a6c4a5c12d426150e62869e3664c4e4a0c443d86f5576bf61ce3a4b54fa3b48d51a6481214284a22b8485a7f14a9a195471061d446685991771af2a7fc250641ffb649cf056c0c2f6bec2f88847ad7a5db01264f7f5a54542fcaff9f4af66e6af9098754185baadf59dca0e892296c4a321246a94c70a4f3b029350a027dc44530ccbe7d043f8401a2f3f28fe0297a097db53ee8906a76c569113f81d151dac61fb678d2779592b8ea5aa04c85a9a40b747ca104d2220c185290a245efb1fd31eb9e3730896233434d4e6b1e82702086bc27ba764060c7d33c55060e6b666c722ad71bcd31de49d6836cf8bbca348b37cd2e10d226c79d5b46b3ab7fab3b7a4555efc1a1384aa099eda5d2e18ad7b33d9dd0d953ee8aa066f6f89e5df337e5ce8a21fb2aa67e5dbcc6e01c28b6f901ebadbc55583b34e9742ea1d0cb7c87510f210e1bd3825a24ca22b47fbf7dc706388df5b7868fcc942ec48f8cf55ecd6893422924c1903df21811bdaaebb77728d59aea9d7aaa48c89734c3dc3e31aa4315672c65a4b34c0f50c8d5f96420731b445479736992162a6f062bfceb9db6ab758062423c6f260c066dfd626cb111f0c968a2cfb0a90958dd0010ad13a5dcc8b02144bd18897ff794dc735601ddb11a2372c5ce1b5ac7f67353e0f9fd90ff7c2dfe539a68b9fa6dd6dcfd18a76ed5783996cf27686a9d43f61282b21ee0a1ede9cd85f00ae2e62bebeb4387ad0874caada7b99c2b823863499e16e920b05ea9c439b46933a551ba82252a6aec184162dc69a08ddc9d52d8d5eca0025bab8dd8975fa4a9c9d4a14df7419347c5bc6fdc470a055c618a344f6f2e8dbbc7283ff6a89915b5033992d95aea92c64881a30a5649567abeb6d4b13452d2b2d99f3ec768c4d713e8f072ee4d256cc335f5aba781f3209c400e86a0aa991c71e6c4c834989f302259ec93425022d5333db48752b7f645ad83d82d1206c69294d199ffbed406b695fd09534e03f4ae332db21ec4c32917affbb992af1a726a2254ada9b0b28d3668f77213d4c5f94860948dd61c37929f6948fd8c50e1e03445015198d85947b422a6cd18ec5d28aa2776c1997f09263321550c1247955314e2aa2c2f4c8539df1a302aa4c259f6ac64f052a994ebe6a8c4b25543129b9fd7d828049876c1ca02083b790599c2ac984fcabb98eaafe3a1b24429741dbcbbd805b5eab0ba0f3154b809ebddc0ab8e5b5aa00fa5eb104e8d1cbbd805b5e0b18d7620c3c727bc08daf1506e8462d19853af153259b1fdccea4831026e4bc7b492d2ee276492e6c4bd6285108ecd1dc248009c6a536c4e666c6ef9f1bc1c1b96105736cd348d252b759d77165437c617f83731a8b91d93c8d11d2e972b75ca78cbb8e0f5ae38ab8f00bede927dc9d9dd5ec41cf365d46f19039ed82772c306ebf0b13286d94ffd1741c76c8fffa25d6a9b13ef3007a63b88ffe6db33ea41f11747290b06ef1f26c0ca6e671f4eb13d0b6069a80da6a20f81ce55c29dd5748df388a109d7123c8405cd83a32088f8a03a7466a85c23eb8a02aeb00aaaf0028d424aa95134ee6dbb88ccb41280b94244d01bad1534a0c155a3eb5d5387d40c4d1884ab7058a88703314233c8636f905530bc512c205293fe10ac229c974654b37e5f737a972c0e1669993792e98c21771ca68c10f15f6f5a907216c42a1d1c3e0065719ba1cb777761c4496c8078853835e4006663d9e9f3a41675e918a7d300af214040913785ffdf63826eda62fc5c34f54ee2dd49295b35f30c55c32ef2378a63b839524bcf1197ddbc3129f9d5baf9505d0f78a2540ef5e75e34ea953b80d2513a07d8d934cc41c5545c21c94fa1d7ef1048fdbc5ce67cc3316894a4c30a2132a0913af25aa930986b41b174f868496fde3ad6c053a411fb0dfbe3a37b7efe0da41a8d8c223edce1496e7466a82af120baf4d533e30f2f52dce2d405c01ecc3250b1fb5a62d2a77c92713bbbc86043baab4e5b7d96c231f4e80284b83d9623778df946e3618cee7576f6b556e641d66e385eaae70a5b19277ec845226db0dadb560bafae16505c95ba93771642740553c0d0dd4bb3fbfad73f1b7bab74534ff86e5d0e05ea18945a58b3f5bf6d44f69f4db7c8889ada95e66e2c56ff51e03eca0dd793738bc89198eb5f9354eab190b53f489700e65e6b045a70d72249207fc92b1324db1797a6b242dffcd30f4df7b2ddb14b810a42c1875655d6625cce97d54b17ce43ebe825e3a92e43c6939418b01ddc5172c39ac0a02a69d3d72b643d141d566b95c470693780be0230d2dde8f8c1cfd4a28b739f2e88f032f719b178c80765ee23bd73a011ab0559e17397388b7213a9335e9f667a671297ff19a86b636035df7e022faf934d5b55a96e98a5b0337f1212a692472cde1ce1f8a444a0652e43c1d1f6795889c7058f6bad0719365cba847b9c0eee1679c930643f44603ab179966d22b7d71ee38d4f31df642e2904d0484339ddd704bf363d08d39f0f2ab5086a232986d8e0acec8fe2a58eafcee861c6a3f1d8f033979a75d3be3f93657a3caee627718c80050109e3430aeb6aece869b78418241ea42dc7d979c9d29505ed2c0b8484f630327b9fbb27dfb0560ba2456745f30668fc5df90018020ac523528f67e9cb0936673e54b50bbb5232909024c71d687253296e5d9ccbb20b7548a4b08a8041ed1e8b1ed15c1402960215eb062b2bdbce0dbc780be85c7340560adbde448d14859983dccdc4a3fa57400550d917ce26f3273a1983d05e972be7385514193fd7d681aea39bd9fcfd97f13762fe847c41e2f1b0a458545981812fd1a08a8471bc2076325ab15adc5607151a10a49a79dfbc589aead50ab5c8b36bb1004a8f35a72d343c1675a036ddff8cf37b34f51d800bb38ff55dcd8e2fc4533d85b05a0a51f25aa3572bd84da2a4f075eda043a2761d96485101577470129d66e4e3c1df916daa81a6d82ff9502445da7ef39a5c9f0ad61bd13a914855b913a6352cb8ae21f405e98857f207518d7a6c2bd4953f1908a9f47ba96102dc7996c3445753dd1ae90a4218ec36755632949771534bf3b5ca14ae64b30d5ae6f0a257f0bd595e734b8cfcbe8965e3d06c46f809472d14aa38ac2a79a2d75f30df1e6e808986f1b8df7834df969631e8e5925a363bb6f8fb61d19a7878748b4c724a018a73747b7cd09d3600d9551c1ec4e3b2602bf6932394114cd5cdaf7034fe5473c017e7603d5ff443968a00e001a4dfb706cf24093e299030eb4621a164946074ebaea15995da9d4336e92b42a2db1d82d12224a027eaa0a8c53efd753e2c78aea5bdad3bef03d555f1bd62fa25f4104510c94cf4ea5e197c6f2ba92846e0b8948df35f61ae86562c282bb76d195438e721fd44dc3f36ad7fa45089c23a71215b46b5f78019cfd3412b53546585abcd027e859365811979fc4be7bd911e321cc3d13ee4244f91bc154b05395d0caf2b41813fb5eacde9ff53bb2f84e96df3956982bff4b389f0f2b70162f7ef7eeeb63fd1eacdf87e577b0fe0e96c97b775a02738c8d6bb3a2f7959a7996af19260ed1ca3916e0338cfc8a393f4a9a251fd6cf5f2fc1f2a1bf8c0fa9d3daf9d1604edfa6c3d7527bb07fe2308e817103fa7ff2b439e2299d54fbf497b74565add06c6d7d0216b9c403257497b6820f7b317f2893c726521281309c151ff3b0645e36aa42091462212c18961280f59e58ab7749652dabd773e44b24dd6a6055c55714d8af53078e859c94ad6778f5aae222d8d01b97a2b777a9ff8ae165aac8066fb25f971a7029d6b276d6f6e8b1446559b7eed82da1ffc448a8bdf19281d6d63de2a7f888839402baa7961ebaa64953ab283dea5f6dd3b0f89029ec5a77e6ea9f55b1937075d0045b1729d5460606cd709a683e1fc1b80a64ecb07920202e8dee9370d1140e55cc1530d4392f0b2bb180e43a9d34b0e69c3aa08f1ccf05c7f192d849b84631ab1597bcee8120f8eaea248513d333023771096f2749e99d7f5ed1dbf7bc45a89a85c422b029578cc5e2e029c246aa2cb00fc3a7910f067c4b2168aad6be95fb725a0db2dd47127cef30e1e1c52bdd922078f516cfc24b12bc14bc062316717285588047d382f04479c5e23452aaa119240928b49bac19e202907170ee9c7cb1905e33a84cc27945dfb8090fda8b3876d52127ec396f783ec6f1472f7bf82efb7e5467b30ecb516d7ce1946eda4559888572cf2fcc4b6f229f8c61076ac60a455d13023b834b34935d56e38350ca9850c57fd578b5a4ced6e229a72a705dbb4cce5a650dcdb207a5bd18a0e6624e0b20de6f7a597d49dd40c7a421a9f151bd52b0f5fd6b52057f60df4c9ca6962a0a1b227b58909cc61083dd4d955778d1a7586a8192d3f192446789b820d2843cad5ba1c959e54a57fd58728c4fc0cc208c9a4dc8fca2f196bacf5eac0ddc1a273eead25b4716f351790dca9f837705ce57ead0c3a0920c31c8bbcf9592fd79d390ccfb166b6b10a3d6672b01fbcdf23189fa52e8a0c3275196c03e8d3e63eac28eb116824add7af3add894ca209c2245352a6ccfc4deb12fe398e95f88d17d7045689a4051cd131c8cc89df1e4081a08eec72f4879ad87c14fe55b546e992de2ff19b1183e14da5381304c5b0987aba0ddd605179dd2a607cae25bd90ab6120db43fb4e8d8e46162156d7bc6969ca4c90d85e09fd27baafd9554c46c421f1ae920f9cfc9f2a641487df717c219091f5ed1184a313ca461ca72c8794b8e83b1269b8488e7ce8ca28629fa95f03ed29ddfa6ddcf35f42a9035cca1ab676cf5f7720e41dda1101d58c3292a8f7cb33cf8a08b530d4d03ef14b2888654f48b9f4c3b272a152364077670f77078b89959d5abbfead3504be9bc9c54be28148105f834de6a9f69187862a4f2554d63543e44d3e7a723917790ea7e55b1ae8fc98b0acd272166a626f4fcad751742050029b3c4040c896a99c686e981b3be97f9faf08423ad1ebc74cc914d54d96551ff0dd35979825c4271a5f04919ab9bc7a448ace189d2db3f6ec6f70bb3bb1e8f97b4688d262daa2a21e6e8177cc1208716390c35ea28aba7427062ddc11899e92d62912c25ac43d89b3acedfe15742df27f6008d05cf26913a0e79fad755568171397c03059ce32cdcc8e7f98d5922e356132865b8cc55d686cd65631f62515bc277e224c3d2cfa392db83b498c1fa7b5ccce0af499db649f81f0ed34cd40c63e82d7155c3fee5c3756e9337e2a504c9bc730b6d04ad67e3a3a275209c241212b311475a832387143f370a64742e14156ee27c28ffcd322bd46c0d54c329badbce586109c2e827340dd9761a953aab5b40afdadf1577b0e1b2b50cc722df367ee08fc0f7696f8b34eb6c925b38e3d9d6bee52d1a14307d6761c0790c5ab4b8e0b67e9c920bbd157f358518bf386b4dfcf812aefc6c5085d43526d33b221c28a2eff85b1cf72d8843ffc3b2c460dcaafefb54f2bcd95206d9982ce99c4d4011b66c894cdeeeed591f10db689288093e51fae675e69e7873ada5e5396d1bd7e156fbaa622a4c604ff5c65745aa98609f6a8d57e55499c01e558d7b2a53cde4eb51d578aa4c05d3d853adb1c5b16cb52fcaecae07d6512c702549ab284c118c77451d043d795f144f0d3679df176d20f8fc9aee51f447cf25a36698158eefaa483ecbb8625cc9b4cc164f3d9a1eae6e41ec41c08585378cd364e64c1f419cb215714a8f464d64744d2a34e7fde0ea98dfe06e9f87effd5cdd3a9ec9f0e7c6fc774194e897b04b3f72d4a32c79a9db0580183c62add58f7d9f896edceeee2e3f5cb7d6affaecdb4ef0e3b502f59302180b71a35bfcdc682b7e1469addd5faaf12d7d7a1fe81a80206513fc3dad45f5b106bad4a7d8bd37c41b0b50a90c2ae8fc04b32990a4c5d32b1444a5256ac4590ad27c060b3789f14d0fd0963e05c302620d555c40514e9584cebb3f78b63c9e814dcae858fe1ac18f88a2d45168cf97b565e62794da6328e1efde6c89ed4bfb08ef39b40d03d8d4f371413542ecdd1f6f3c9ac8f988cf1bff8cf5135d2ebf89124beae5c691ec426bbd9edf9f0798df7d9359a02d068f90a1bd14ca16fc4346f51e2ca88b127e915f77f2dd5f2e5bcd4b70ae2db583ef7e2dd72261a86dd88ebdfb7864bb3582bf9bf6427dcfe158f6f3b561b69e9896a4549a353dff6c2b06c0df6a445d8ae7d8faf4af653c2df7f65c5f9a17d5181ed0b6d55b6a85b98cba18dd7a8464df4909c65cd2b1128c99855d1e10674d4709134fc521e08f2ea0c8c9073eeb9e6f1f54fbae948075fa4d6405082ea16d2ec103560bae773f640b53160218e2cbfebf02dc5b045fc4d24c291a5aa9c39b63ad86e0d4854108419f15cfc8aa00aa03e5a30915c205a21d182f0152b95670b5e00a5c049fd6b9eca769b0acdc4b7045583b72be3f8c25d60cf89e39f98777ef9ef9c6d802ca0498b96160460866140603653f17bff7e3ff2123704904ea0602d549137126be59bf6b608198ecbc493f1f31f32b13c4eb7ea5328e0c9019a01c6931ed99a3f0e8cf948885ff1c14d8bc0269ce74e8f13ac9a1dec06f0ce3a8d92f4b451c6ecc8e8987280f234418af63e657e1a9a52f6d39f1836e31739682579483285775ecbc0626ac3e49cd6cbede756ec920e0a9386fafceb5744d781dfbdaccae9cb87ef3bf8db00fab9dee72b2c8409ee91142d9465fb33e78d3cd857be7522941d7def8d1cf198edfa5b11620a01011615380454d99004031973054cf62741e26a3bf4d57227b35d6ed64f178118f0cc9707aa432b9d0375a5383b94627cc6b07effd227a9fe25ad97bd5dacf61c08ec0247c2007b237c472a2046016454b670b72fbd8eb0cd9e98c4b34c47987637386b706e86b57ce14b59d83885deca5c385517ed7572f216359633b8b63e595d9b7182efb8981ef10b092986c8e1da7cf9cfee7f154321b2e49501d2521e50ffce2eb211a62615a28e45101e5200542c8229de7c58b48564f512eb4151e97e986a29cf02a45dd65ea879ca9f19e3ca341321842db39c26cf0f570d42c060298070715e7a38aecfcf0cc9cafd4a1fa44ff3472230c24a6137a5ebe0ab63dc1ea2043604a3dd870d47b52c5891020091938257bc823ae25e9981d1e87e94081eae4e8478ef126f60500bab49738bd845ff315f39b5aa7f78f64882f2686838556a3ac7572d3fde760cf8c63cce725693f4c3144ee6028639b00e29c1e5710c5017f208628b536e07b22e3e185f6386eb2c38dee6b155dbd6327f1274a4f5100ac448f5fa1969255b40270ae546c92ce2e7070c6b7f76d804f4b9fed61b4b15416641694b4ec714d300914a65280c94e7c1454db072de5cf7ab534b0447e3c35d1368005ca1574a499ff4c6f2a339fb8cba645ef66f71cff89534aea3f5f9516974618f74bba81f79469571bc00924f3140f1e49d1286ec6745c330d8d5ec0411a5f896ce41941d37939a81a720c58b6b5b856474cc5e896d573b90c98e53b471b46b17dc8ceded1616738cc886b721a21b3e97baedb9a01de5bbfb65903675c93221ab0ddb27ba2ed6847738c549976f69274b37bfed4f53d8df921b72b0015a5e2d3e2401cbcb0257e87715c26def70e3dfc8f482d115d074384651dc50d8f5c344e1c83e6c901f7118a4276e829e2e9b25d9855527bd117192616318d55afc0c3fb25a628ad0150c96d99a383045c999cc9827623f1c674abd0f806b0c7979c53a4df2c93b5e4137380999ca8098d354abf9c11f456d782de4f138a193fe274234b5291e5600434813de91b143d5af1050ece1650c3dd924847a2f281b49772a1ffecc4a348089c1d66b47653fb08534d7c0aa01a9a8b922c69194a2a72ef0492cac0ffcc8aca9c4e1b428f85cc315a27ef99b39aa0ae92185ea898c319d748e462ac71cd9132d47bb0e7e7271b0949a6b731cc5834228ec0e6d77c00c2741e0aa2958e096a732fcb6075a5c4d6724a77cff5bb1a95ea887ff4ddd050041d56ea418969038edc8e924a93b12a9f685cef66057fa88fd68d98b543bbbbe218b36d794e3f035131891df0501bb641fd59dc757fd5b6e225b692937e90a28a2699420e7db7268e075b744c7f65fe636dbf00dc173d448bda8d2f70f007329141615c094ac3dfb2e0b6fb9c82563627644bc667bdf3e5ff707afba5bc2c984a9c123e28a8308b39cbbbd31a0189d2fa5afb1ebcc4cd8de8f1270c03909db2f8eb004009c7e219fbbf6173584c175d48f49e47aabde34c764b99aea7191023c3dda97f219488ea8c634b47c85d0a799b7609275ffa3bb860f683579319e9cd9e40aad03a84ce125c385858ee86acd413eca3b0bc466ce3c81afd2e0d2c423d4a7e25984a3e285ceef8a9c3f374ba51f5b16a18d86c0627cd449993c07b5c4271e8f8629077485dfc0b9b29476ad3020daf621d2e58e99ff321bf3160dce1141be326f090e38fe377c0456166677ad58a63f276ea1ae2f61c51c41031b06cfb4f941616a1aee9c8622cf8b2d5507619a5e297411d1435069e4e468815561038ec6a3a3f9f2ee772a735f9240351126683f9dc21a227293e5a3b5c1c07a0f3693c2abaf81348dc52726c915d7ce946d2ee96c6072f178e6f0af70d473f285bdedd40d47e4b012d36fcb440847bdfbe9b8890bd5355177515c614af2aa488c2892d491c918022b418a0894e1021600108201575668d326a2c88110615229e01e183b515995003dbf20316233422d842892d43478276e4b0a989c138f811010848799289530a4c4a4943447e763298ddc0691da0071c6ec8604c110a3cb180256478e2c448108f1cad0e8021c349d1094134b017036c88a201460c20081d5c40c0010ee00313a7221382dc786ab062f0996995a1617c645a2bf84ce01ae371f185e003018d989b305f073e2d3e293e06b09ef8a85a535e08de07b10e5c1ce0f4f8767c3abc1c330d5c197c334fd6baf1d9b86a3e9a58ec83c15c5fcb6379decb6bdc87cc4713ee65adee6bb329e4493cda7b7a343eae7c3c694b653e80c87cf490f52043d6838cd3a80dd31daa43e993565f4bb5a5db521376b9e68a1b69b574ef6a3dace81101590f07c87a288046a3b76b1fa7a33bf40422aa7302d1141004a3e06eaf233aee5292f5f0719dc19b7fef6a0ac95b7b8bf5b927dbf1821d5b5cbbf593946e7ca97e4cd21d9d1ff389f58e28761ce1e4fd5da9de6185bc2fdb01b503092da90dd31f6da969c6b65cb7a67fbb35d3803445feccfb75596dee0e24086c8cbb7fe0ee1a23039a4f0b8efcd0229af3399270e488d0112347828e143942e4c8902340477e8ef81c3922242464442848a8881011a1214240423f423e42478c0819316224c8481123448c0c310264e4c7888f9123414241468282828a0411091a120414f413e41374a48850112345828a142942a4c8902240457e8af8143942448888112241448a10214264081120223f447c881c192234c4c890a02145861019326408d0909f213e438e00090119010a022a02440468081010d00f900fd0911fa11f233f413f457e88fc0cf901faf9f9f1f939e223e463c427c8a7880f119f213e403e3f3e3e3e351febee3f5ca62306cf9dd7ca270c1d44dccb6a2bc56dabc3697b6d961c60b8ef9e8aea6de9676cfb1aad94b52487143a833a3f59dab32664e76c4a2ecb51baffc5549fd8567d36e9e3be347378a4fbc4b86d757497f77d6ad61cd5fda5955e7bfb1ac59b923fc5851a9e1a1d1d18280c353c352e50ca435da09452ea5e82bb931024870e1d5a030c773a24d3e00a0d1c20d320014e876ae8d0b67d49690d6de36e3653ba6d5fd21e37ee9a3b01c80927b8fb8e4e100da4641a1071a7dad27dd628d5f6719b0e69f29eb8466d98ee1353ab274710c1bd6688ee4ac9a71aedada69928431960e165adee339701039c0e915fa33bb27e2e6b53c63927e970ced8c8f6e458ab47848c0415213204e8c74796810bee0e823b67cb20892c0324afa59d4f06bf5f5ad59c8fed5aa7ea54420fe8034ee144f4ced5a440109f20355a44a7f844b19d3529dc1d0497cd48d71924710e8b14dc3f313e147ce517f40d31810057b8cb0c13b86719c095e33042e29e0d5adc83c8dc5964dc9df44a4002af8bbfd889462fb6db64b2a3b3db66ee456d41db5903d28413483c1c9cbf0addd5e893b6ca92146fbacddcef5dbd9a27767e82281111fdd1a1449496b0002696500206190ed9a96dbe2d69e170c100a8b85178a1130112cb8c03f418011050a0e08712442c2ec20cd961002276e812126179e9e14684901690cef8c0c352001540be40c26a82043d21b074b84252d2429524b4a8810396d9840e1541cd84327672b09aac405600358a20e2c600372c130a203b22052cf8e167c76bb128980fc49021f1c40acf1aac970e4cf42006049010e1a38ccf0513a85ab22489239064607c60d428c00b2238220924a22f3e086c114107a2a4a0c00103e8e22bc009b43ca00b213ef0190af3cd90650316c87001489417587c362c681605f880142b0554f12db9b206193bc6c8094f20c5f713812ea8889262c1145940f16d704606089013900501529af0d65040012c406404477610e108cf04255042000586d022a28008cf0a01900085941808a1c50101f09af852240a035f0630e5841d3c206c88620310510a80010b58f17450487d51c48e043c742f7852c6a0b172010a18a86ad89e9111b9040c4100317429945e102ebc30481f260f2d203d1c209a2c0f123f5600458a8f51c5940ed230a2d20101a47c0b005811ebc107133f02770a7029c10bedf0c5892d486ec40b46237ec254a14610f72b08601264841d04c84922e239311e103a8209165ce1783cca871880b270a105524c77212f4264e18206603a1ce0eec10c281cb13213001a2bee2c27ac5c8081266a3767c89009a300d9992c8840b2c619077420023ba09ca0c7f3947166881da4c082063f5dc1028c33314891821809c4cc870bbe3833b271c303c600805f71a38b334c4b8410c2105603f1813067c02fa4c8aa20a104135e589cc931040a27c80018176468a28a36d2e00017119afccf0f04a468c38b1c6265cc5081430715146d5421012433081fb614408b26da50c28c12a21657360c0138a20d1f90f0820208e892822e3e10d1c6f6220d5d08e64e0c1408401b2c0cc0a9861d7e886284263bb4818206a438432352019f282b6d8870434d74952fa4a0c30b6dd43ce0014e6c59e2cc5597cd8618649cc04c1025b8000c4628d9109300266c5070442ece20d98862044d9421c050538015296c6809820a01594c40040d0c408a8d1a304002a4203e3ec0812896b04165e54b182f3c9001144c4062e3a9014237354828d2801e88d8282206919a2c3b4868220544d8f8a1c5062d382004154294c1c3868760d7b001116818b2228435548065002dc0424b599870b0c6062c200b4050931a4e8ce4588301341065b09b02812c9edcac31800560c1f40312aba8dc99d61a2eb480881c1d0861e8b08135d6a806a0d2840f4e20a1810794b186d2075490a2f3d384000000630d1e1ec07ce0041619d620fa628dd9144e7e1023a402c14d176a9c7146c78035a690a20b2661d4e88209b38d1d5610200357b8bbb781851a1550810f2d5827f848f202c7bb91e3ee29f11e004fdcbdaa10dc3d2a37365e8d950e49d6dd8ecee7b016b50577746aa716c9a71a1f3782fbd62077cf8b4105aa444931256142129330458950c2267a4211ddd1b95f82b6b3a62bcd2ad7e7b57eca605bdc8716d17d6b0e2475062fbed54c0ad9dd7ed7bcb590f149a05dda5c5168885d88914519f7055d5c7561051a4da4d019e3d3106307164db497f18cd40d22a30fb0d0818ea0109cc8808dcb080da072c508600b1c5aa4704daa123c6520031d426ed8420408c8537ce0862859c0173cff9c58f0c1082c2486c8d0430a0e70e1a28a5617b10f6861061820ec2f84e0d021c406cb8b216840011479ce83098b0528a45106174908f1822bf402928aa90f3c6f85d1930ba3d4d08418338060c318b802eeba2201701b1758c0bd9f1e770fac5c390b0789bb1375878171f72f9fd3127707e2b2d7ef8a4b9bb8b3a490dc793fe3d1879e5044eb2e9f7c3aa4ab6f8c74bbb6b4354be93187b8db896fd2c64eb87dbbbf64b7cd5c92bbfb28ebb9c74afe1edfb44adaf6669184807e5e57a39b35c2586acca1bbf7688db992b6ac559769cc6115ee0eca5a562e255c59dc7774f25b9bddf749a63dfe548dc916779fe232978ebbe778c4dcc9cf656c2b6b8e223131217221ee2db8ac6535e61a041e017d7a488b7bb6be7874edee2bb8ac8553b3e5ceb856dd75b833b9b7662d16eb0377d720037799bbe370f71b7ee335ee4ef3d3a37fef3cd3ddc63d8acbbe2cae33f8241e9ff4018b803e3d4245744d88edc7c7a7c84fadd5808048233fb6a01e6c41fdbbe611dce5adededb3107ccb75048564bcc7c709d1f97513211fceb72d4d4d69bbd23270d947e45ed61d2efb6edc3d87cb3c337e427e7dadbb7b2ef3bac880bb6fe0328f8bbbdf2f2911fd1a25cb13e334dda1daea50ab27afa55f85739f45b3eab4bb03b97bd8dd7bb8ccb3e2ee3a83e3dde9d89f65ada2b49c9368f4567a31a5ede89835ebee3934b4cb533f148d925f96757477eafe91eecec3651ed519dc391bccfde519e7fcf4564afecde7febcefe7be3473966e5bf3a6b76bf7aeb98c6db46a71cf0877f7e13237dd1dc7658e0077d7e132cf81fcd2561bd5bf77354a6d985e6c77a5bb8c739fd319fc80b83b072e731d779fb9cc91dc5d874b5bfe2a4c77db8ed5aca3cee0f855a2ae662163d642465c9655c82ed75cb3a5bbbb58eede72f71b77fff689777549c63927e9c0c18b8d7bb9ba0a9da583072f9e0d9e0d2d2b573c6a432b87872c3c41d802994764137337b2b901f2dddc7c379fdfbc727e28c1e88b0a9693c4eea3af9c24762c8a42d8a2ad9a16adf9be1b2034f4c379a2a12d205660b0a11ecd8d1b7d406c80d88082118bd600b172c53362511b50306a51cf33fa3e572ce78a45bd1b2b38f40a35aaa13120566ca80dd4a8867a36395756608881456b72ae58566ca04637f4c361e106080c31b0284ece158b7e2ab0e8475938522c7ac533aaa13440ae784634d40688151b5030aaa1573c231bdabab9c981c1c64a2cca8d6e72607042ca867a14861afa513772bda867148621a34a62f7d124762dd9d3473d9c1f2ab4e847a59e58348b4d8882f08b18cbc8f75df9ae00b172a595e30415146c70820a0a1f0e15f7f2e485183ecaa23178b4455f70420a466be80b56ae502397d48bba680c2fd8408d5c392fc4409373851a7931bc682ce70a356251584e0c2f8fba7258d4690c2fefda8426a072d11675e5b8f7b06460794a6cfc034285e52a63566898c1bf96fb90f7001b970108954761395458214dabd56ad10f46d382516fb1682c463dd614cb6bb158ad298fbe98bcaa6fb3688cc658b11760b19ccd5af2609445f5a2c9a17ac55a39acd847a95e3954582e20545e083fea9f8b8b8d7b1eb5b159f2c298d7aafae8ab05840a8f90ea453dacc9f98050e111be72366ba945bd1c2a2f8436fea2b49543c565e1472d60f3f2c2168fab35d50a3f1a1a63f1b43c9d100ad34e080b127a3953bb15b6bcec85ad1faf0ff6234659ad50e7d3f13ceadac1c6c5dca045cc0d59c258e8626ec022e686ab156cfc1383c395bbf77d1fadbac9107e4a3c02e85cc12274313774114ec56ee012c670e012d2d0c5e08025b461dd509d2fe845c314c85e2c1bd6abf55118fd5ad45d406230186dd11b9793879fd24761d405c4719876629ea713b276f06ebc1cd88bd250d7eb870bc80f176db95c9ed2473d203098f7c15a3f5a2c17cb45dd45ab6e328431263f5ed4457542578e4e063eeff5c211b26809a18b99614ce872d947bd250f3f0f091b0f612a168bb1aaf88260316a138bc5621487c973c56e5c39add78b7a30188d81f1c2781e8e126f8c8bc9abf13caf2627067bbdbc7079168595096134067b167589b1014ce8a2af5906b3190d81030d70943c2f212c67eac6867ace940d102b4e4cb9e8476da0464e50c97094782f1c384c2efaca41933305fb4224ac1b1e21f8102d49d14a2b2b5888d8e2416193e346c78773c3e58626b6c18d8b662a46bf187dd18f06478927c686319ec714a330ea38321a202e1c252ceaca69c5be16cbf3cf0b4e1a357cb1e20b0d3e13534317313570095d4c0d5ac2d0c5d44080f015ba981a02400418a177117a13a1531716214b0c00a40859744a86d087aa5a3f58493f583940dc71dc8128f1426fb764089d3a2b86d3d4f4ca71ea1e2bc75fd4f34212c8762b7ce134b9a8e7fc50a2c3d3daad90f582e134794d5332fc78b5743ceaa23fbc97c7137af4a32e04d888a1a10930369e4d4eeb53924149cc0c5d4231575f844e39f8826ecc842e66060fc173a8a8938d7f343a1f4d924dce0f2fe7bbb1a11eb5a10102b3f9be1f361ecdf7ed5648437f50f1c2170d4d8c26a7ca0b5b542f23ce12c11a5084308fb63cd60bf6e3f57d30fa03465f300a63bda86034d4806caad5f2a1186d51970fd1d0168d51bd680da5014205070df5804cd5e4d0e478f8c1e82bf6a2b0166d8991227c515713a187ae18a42185982b65c259e862ae74117a218bd2b8e8d4eb454303a32f58eb86ee160d8501a179b96e62af168db16c5855ad10a7c9455f3f94e878ac1775fd70fd70d1dcbcc22e642fea1427e9c5f4852f5a75932164518ffe88519d1dcb51a213bee82b4787e70b7ad1cfcb71b97ebca8ff7851efe57af1788fe38829c0c686e70b9afa280f1161ceecb04648435b3ec572d5d05016cd6ee1d01bcac249b2c954708455ad1046772b6cb1583f582c5ac362b1680b674a8632de7393f34389ce548bfe50a213c6a63ecaa2353494a6a99553e5fd88e5e8c810d2d8140df5bc900432a71e75fac3a32ffac3a33a1eebc5fac162f1b83ad08614a1dbf0fc68d1a956e83f5a394a74429db0153a8bfef0688bb280fcf0280f0c4605a31e8de5b0a8a63c8f7a0e152f74e55079947e393cac1c6870b0945e34bcc0c6c1518ab9dfd01f3834b406070815af898685c3a4c5ca51f2a29e84e7eb800d8b8d31a10d8db5a82b8517885118fd581fbdd1f1947ed0d45098bbd31b2a4db19c2aea3955ac1c25cf7fd0d018a5c951a213c672743e1d8fbe603954ae9cd68781d6174475e3439f8bbaeb9533e539931665d123dc5b32b83caf015642166d0520fca84d19218bb6c2a8f145f8511bb7c95ccc95172a18659285fa9361ca45b717e6fc60e550e550d9d00fc8940d7db570986ce8476d5c5470849aba987cd4c60504489557e5c568121b1aa755add0a35470849e476b5839555e489343d5a2db0b5f392daa8f6e2f74e550f1c2580b896f515818ff168da9514518a32f8a83e52c6739cb75dc73a67e28d10979c258c8ea808c8a177e94c5a236ad1665b5e8cb6bbd7098e030bd28ac458575c362e97c39555e52cb63da093dfa01997ab5688cbe70583854aabc10e6a254aeed9109a306143ead8f8310c2cf693802d994cbe3093fea29a9f22a6083c37ba8a723a422a422a4c2c6c35172d7d1b9a12ab891951a6a7069c1c2da8925b16e5c382ab870f09d9b16cb75e306c5c9a1e29d09a590e1a0373e9c22f9582c168bde8001c17173837303c70d1c36de0d20afd07192bc288c5ef12117bdf9207613bbc9b9a12e2eac1a16a5b981b97080511b188cd6c0288debe626278b0fc1428f4ec5804cf108a73e88c9a65c43842f336cb4178653248553789e37c5f77db02f9ca24c19162bc98b95144ed172b55a38495a2ed62b9c42e6d1245f3805ec4b8a019105030d20234b2801d767c38d03b008a762b15bac05de8d2e3e9818568c032d1b0bb824107ad4e645068c8cabd0a3319a3542cf8731b68c71c4171a2e504516686841430068f080460d679c39238d33c638038c33be38838bd0c38cd1c519599cf1e50c2aba8431d344183347781bc062083301308325f43066aec2291d34ca80b2097fd0c0151e188383107888940981870851181c84c0b3451834aa00a3d584b7a08c8b09329e96d712686c117a9830685411060d2ac2a03101cf8a2f3484584220ca8040190a28434be861cac052860e6500808c36c840838c31c668e20c2e6768398388d0c39cb1c319339861c68c32c298510233c29801810098b1c58c2c0230030718186658998a9571461965841ea68c2fcae8a28c0e90a1a58c2fa111634891c615cf4c99cfcc9810b0c29071258c990e782d33aa20234be8d11b335f72fc2a4c1a4d84492301a18731e38b30691011260d1f2e504516a10f610142027cf4bbf2837b9e47433deac2e2c3e8d5fa6eb0a8d7927dae580b16a3af98eb86d660436b28ec864ae1e4b8b848d9e4d0c4983ca3308bccc5a5a68bf7b8ae70e9c2a58bd0a35d6868c68c202422242224824be85d3c16b571cfe805248bc7fac22cb2cf03570ecd17ef69b162748618e572856b0c920fc8a672782dcff321980b890a64532e2fc28f8641f0e0c183078f315f19366e4496634c180bb9b84c00a32d586b02322f6cade06573e541e8e5e4f852b346161797355c61b870e1c2850b17562bc798a91ee19725ec4186838b07612b27c71717c8a66caebe6409736820fc707099c1e6ea8b0e2e1cf0127e948cb05566ca861e6db572a6cc295ccbfb72a6a47c3e9d9007590df51f521f4e92242c1c2cae63433fea22e3867e30dfe2aba14464df940c07c8944c0b2bb4c999920de1fa12d6009922e232c3e5cbebe6a5c1cbf3a0178d852ef73c845768469645cb27d302644bf851282c23322eac9d8fca86700d88083ffac9ba841fc5d2ca91656185217c3a5ed883ccc3e165069947a76cb078a159c106210f396c6ee8946b8b67c6f36c68c228645e6823739961c560af1b33496c9a88c95a2ed7179b26bea09a9cef8beb8beb4bf8d11b59cb55c4102d1eb495a3c30b8f180f322fa441e651306453365cb4841f957589c55a74ea83d035868b0d17598e0e32def3d1503646861b2fbb8e178f5014a409d9f649a3957e8dfcbfeea07ebb6d596ffe6df5d55651f23536ad9e7ec67b6b90fcd7bbb2ac58ef9eca862bfd4dc97f0dc3f8243ef29c905528c84f84ba547faaccdde90944940ed16874eb6ad21f6fad226f1d97d85d9e4d45454227d1f84e886833e4d0824cbc72f7135c269aa1424dd0387f157abb76575e4cc9fa25c59bea6d6bd4da6ca7cde2f478040c0287f4f4ecb6cdfa62533f546e845232216fb8d3d8e9a33e375addea8ebad92627eede25021070f71f273e4e6e552df438ab15637d2cd8f782d9e890fcdc6fa6dc6f26bded9323f27f5f262962ec33e7242a264952590a165d75b42ceb88e43229486451ca545ceeb7a55fdeaed53474f71e9745e9e2eea03e6bb22855dc1d5f1268c819e504776fe23216c8385896afd395f2dcaedd3a5b1bb5614ac15d599e364a5a92eaa7364c71e3ae462c540139d9f7ed78c31f27fb7e6e574df175fdf2a156c840d04fcfb5f5f45c9b98c5155a4ed221f712e31af9393c1611093a898a88c67792b1cda688f357b9f8eeac6b594d5d735235a3a0e8c86f6d74df6a73add2bbaa2bc3bf58f74e3f66ac74bb76cc5849db3e3f65bc9d60db65aa7b0cf5ad6654d4ed5aaabab5f824e6240a07b7fedbedd474e36e3647dfdced4a2f7ddce679dcce9db75c719b3ed5bd5394931b9a98712feb88b369c78722a36ed7eafa797ca45cffda2595bc9fdff6b92a9f47ee3bd18a481013f9565629e33d561b896d7ed3fcadc9fba5fd31635cdacad2d6f23fa9c09ffe5673f6b349967849ca848dcba8934a359990d72a21afa58a1ae3ee4d2e8b0a421685828353a46c5c6a1ef25aaa285240fd385d4b4d49f29fdcf7ab9e6a8b93a2e0c6a5a69fb39bee8cd666c737750f792d950e792ba589af696f9a154769e4b554347abfcadee893bf33363f537a2bd5967e7e9c141359147d73b7a97e9b0d4305b12b739f9fc82f4bab04a7eb8e229fbcd84897183fd5ce283257dd4361fc445e5cbb4d2ed38fd58caab2fabeed91ae6d2a317efa2aff59490527b76b77386ffd48f74d26bfeb2ecb50573389dbf689d65f9a397ca4f597e4eb126353cce19bff29676b79f494005bd519ccb91c91a1a19ccbe5724fee4e87444d55df74772598ac706f364a34cd3a3474e4a74811a0ac8786fedaf262315777450a2a02f49f71524a828a00555c54501120ac937aaa5a1a010dd155a89f21ba0ae5334457a18e00e92a941090ae421901d255a820205d852a02a4ab50448074156a0890ae420101e92a940f90ae421df9d15528a11f5d8532f2a3ab50413fba0a55e44757a188fce82ad4901f5d8502fad155a89f1f5d853aa2ab5042ba0a654457a1827415aa88ae4211d155a821ba0a05a4ab503fba0ae5a3ab507fb153d39726284d459e7f6fab93fa5bcd31e5bf5dab64de9e4a5b73491b5ba8da3f29ebed97ec6a696a8ba4878676db8a64f95669b7976c877ad26f75efb4e487db30cd9df7298d461f273534544df2d67cdbf7ab92644ac038487eeed49f95180192afcf6aeefb399f475bdb25e17e2d2a8102926f4bd3acf4fed7a8ae38ba5fd3ddb619e3f659a9ee9d524801d3062e63a271d9521a2e5b0ac3654b645cb6d485cb96c0b86ca90a972d7571d9d2167787c95e371b68c8997f57976027f271637da86d737609f93a5c96e1c64e1b63a88b6dc55925b9bb0c52ee1ec368f7e770dbc2504585a5b4c64e50f973a7f617aebdd9cc84ac46e64985f11277cff9719b89bbbbe0ee555abbf2247113f95fd62a79b11359e2a5fb557056daaf7578b4f1bdf52877e6ecb54d3a5cbed1d3aebc4c34794f2577d7552d89e0eeb2a4292e4b6ae2b2a4251ebbf8887cf29ed848efbfe52a457eb6fa9176b736612ca5c34b3096faadcfbc6f13f29e182ae331ea3776526f937d4f7c94ff5efbe476717ef2556c5466b21befdff2e792a8c65a2bcbaad484fc7bb351d756dcd165228af9495b85b3299e660e1fb9e7af2a7194ce19376127a9b2ac476789a3c8cf78476127aa112f3977db96b666757da5edaea9c6c77dbeb8764695183f7d59aba5ad55e16db2314e9bf546b9bb4ed2d8741a1aca7f6dd3f7dcb3e775c5993d7697674ec86edb5c4d9c9f859dd1c556db2a8bd4c4dd3315a40b580515213204c8ea877caa112f3972ff8dab86866ed76e5c65ab2e1ec5dfd8c95fec8484e65caea727e772e2cef6bfb3fdd7644752ee0e44ebcf2459e9925412c59bee5ec968cbdaf94457504a4a32a23b7f95bb0b01fd9cfa564ba59ab755525986a3b64dff4afacddd1e1ad2fa625d1fca8809f29e586963a727b1d3ad1a7dae465da68d9df2dbaafa4b1b3b695b0e0d6d6d4b51df6a4d34b55d1276e1e6eb9e1c26af843c84db29de54937fbb15379a98fe79edbe78b479d313aff0832cecc0835cfd98d416b7296eb4381de5b9d5d246a5c8d7273df10afe024e6c0149e940a00ff8539564c4044a2a8ae6b9b7c5d319fc1ace5bff803e2050cfb565fedccdcd506081eb0c5ab38abf6b95cda62802dd7099cf5ddf4669fa9e6215154d9f94fcb256efd3afd1adcf1c256fa5a5cd3dbba772772a779f72778b734111180722e5d484c99188e4d4840994a8242a098f8e9294d05b719be617c97be24c4322e00fe8d34355c7f1a9ae62ded5d50c573557ee5757fe5d39ebca71b8721d7470af711a77bfe29ec395d35c5dcd7075a5c395fbd5550e573478b7b7fde770d4934f46af3da934f1490b4fa63c91f224ca13169eacf004ca13d91014bb9a73a51953bdb3f1a51953f27bac7c286ee39a8ed7201bf261c88aee4a79e850fe3d56abc70d49b95dabb5cd59db67935af91c11f222223f3cdc5dc8ce1127ee0e4449a025d01f5af5f93511d0a7e7c9fcbaa73473d6ca8705991018772070c80fe8d3737538d770bae2849aa014a7eb924c08018e6d97e9c99a6f6693adeb12bbed65aa62cb7aad52d2ae34cd5057dc139468eacfd5bbc76ae6f0d1d0d0f8241eab80869c45627ed3aae6a8465cd6725937dea255cd59d5dc68f5b5795bbdf8bad68a80869c44563587af542ea805f99ff4d010d5884b230f0a591129f6f839e3916e7c35a5364ba9b6f47152d4049a98b14823df4867506f9bb365eeb7de494579fe279b2859111e6e02912dbef55f11679b38bea9858c5f45a407b27cbb42fe2a26e4df263af7b7aaf53769fd23ce4f4a643522bf2abf7ea8ffac346a9b1b1ad2f7a9f01e1ad2e7ae3beac75bcb6ab4357ec2b6cbb4cb7857f2d6a6b2e63799943597b113a977f5a9887cd3b479eba19cae3a22eca47f050f0040de8f77c373b97b76199097fcdb8ab9fa79ebf2353d818892365756d9cf01dc41100cb2bfe4d9f5f38d6eec44414dcb5acb732ceb78bb96bc27fd5ce93f192abfea4bb1ea5bf31ec2e98afb49e2ee3b639ca6186f9cae383af43a7fd567aa3388d315c7e4ee4b2dbc45f314856cbbc9c556e77772bb96c4e34ddad7e227bccd5d3e72f724493f5787ee2e020b2e130286bb2bb97bcb3dc9dd6f7553ab33b8afc5e610d008e8d3f333be769d41216011a09e1e9caeb87b0e0dfdad66bcf5d0d0e7ecbe6716e2230414e2c3dd6974884677a5bfebd694fc6d9e39e32392697f59d6a79db1699e5afc5ccd367727ee8e44c8b69bdcaebdb6e63e9375d7dfbb1a0aeeee15b9df26b72a95bf963b9d6e55ea49dc74ab52f9c9fa50f9ab9830b95d9b9fcc4cf647fdaea32dcd13697f94bb9fd0b2f8eaf0a5ba4d48cba489b44cca3ada8b6f1d2f767277a25bddbfedb53613dc7de84bf1ff32297dce4afdae48ee7ec4dd5de862bbadc6a6bb1be17127afa5ca38e724770f2ae29fc3517fb1935408c49b22444d103aa31411897a579ffe6da2de5553eb5a1ee1c65d4d6d91b4aee5f864e36ef675ee0d70f7eab212d8204b7bfafc80403dd8766dcf9775d4e4df9bd51ab7eb5301461881fad01380d0fdda66c3ae2257cf0823d0138a2879df897bcb022d2890b8b77a68a5d0817b8bc95b4bde324146c2ce580b919100c599be1d5684c0c7fd5bc1dd4597ed98b0ebcd56d5775db1ef89477a4211bd5f8adbf6a5489618c6c1d6243de184316b2d3a2ff72be43fef9a107db1dde397251e8500fdfc0c39528bd4b715111a420ef923458a000d013a1254a448cde783aa8d14f209fa79202121e3d66716b28214d351f8141e51226a455a907cf27fb47a9d7fe32afaf9d43729081241b4d0212b1f9d5b957ac1dda3d024a9d00913d4539027f728f4884989e928e929aa470a4a92941393a3204582f090bfc7337f95dd3667b33982902cc88d209ebbebd02951a8131326a9f08869c9d353f8d46464b575f2392b457e155bd6fcf7937cce4a1d4935291232e127ad13abdf5fbed4d368f3e74e27a9a4a8a423a7a4262a2445ddaecd3b4a4849aa095292540895d4d4c429694998040595c4a4c424e59484c444a58e92523062b2644913a724a92326499c98a0a4a2a814931154529224292726a73069091326463b23f838ab2a881f637421e22d27b003c44066715808929c314595907b00c035423ce101879da185c905f0c719879d3973e6cc1930dc35001d8c3c61b3807b14896b8550c2bf9c094fa4b0d371d70058171832421177b1b004d20b9aa8fb0e8c041d4a2872a7c2e28a266178e1de0564c0d280971587f560220345acc1c45b3415088058812a87d9f0058b94189cf1970a36f5842f67dc61f5db5240f1cf054be0930f1c71676389ab29485ae0a241599c0002671c762403a316a209b86b0546d03c2f3bee6dd13141c7a580b39aaed06005ab04f8872467000ce4cef84bef6005929dce595a2079615d4139ebe9a98a041254f157010230420360b0827f5d80965a6b74e0b01a0480c4d59203384c8c1688a0c00dcd5d8c02d6f0818701fcf523480a37b470712f734573580ee62d6f9de0394c8b47ba661ecc7178ae0dbc1b5e0ca865c45901687900fb6231578be579bee303fd734f85160a9ec34c70398e97e79ee7b95c443c8ff52d791eccfb3c8ff5aaf2799f07fb3680f2bc9707f3cfc30159dfeba55343bdd6f7b5b0782dcffb6a3c333e8fc65d5eeb63bde74d7d9ef7c59a7c3f3eef7bb53ecf059fe7bd3e4f056f87e7b1bed8055c2cd80d6f03cfd311637906f03eeff579dec712bdaf554343e4bbf18a629e2b04d6091eecfb5a3fac9aeff3767004792eb47e6c94584f9fb7fc5380d762e9b45c9fc7729700bc1378feb94c2673cfbd96f7796178b18f04cffb5cdfc7f2bc219e102fe6dd7cdff7bd8ebc20dfd7fa3c1f1668d32336828793818f4f08cff5f5f05a1ecbf3efe9a3355ecb3ffb724af3786039900b788e24031fcb7b792d9887e3b1b27c5f6c88e509b1bcef6bd1ef8646c773791ecca7f5f3818ff7d5bc621fccf386bcef1b01ebe5d17c2d569597f39d9ec7eaf1686c3e2f06f33e249f079f075f072c67b987c37b7d9f87d392b15a5f8feffbbc97d7b27934217836aecf7379378cfcf8986036349f578bddc03e4f052fe679accf6b794b5e07df918f83cfe6837d2e8fe57dde67f3c15a1ecbc5f23c231ecbd3f168bc1bcff34cf03cf86a58302fd6f23ecf1bf2bcd7065f0eaff579ae9677e4b3f1589f071e8bf57dadafe51df93ecfc757e3d178b1d6e779de90d7c157036379ad58cbf33c23d4e341428c885582cb6379345e8b874743336413e587071e082deffb5e1fec3d990e1f9b25cffbbccff3bc1e87b9e92cc8e09559210ca72b144106cc0a40be00e3493dc1029a98608c4b01e1c2a38ae8c047552d1caa08290c0005043351a188a9324f95089225457840c652e5c0e748113c841ca937983062029c108c00a9f1824ce0b111443b738020da868334353ce8a16df978c6208179a80f092568e111e3031abdf980eec8c0b56830c569ae1f9cb600e0ceca8fdb980825a27adb9b25f175af0977f7c06594cccdd684e4ceeb5ea35ddcdd85538acee09b75d42fc5fd49464d9dc1ba2b29e2e060fd604d71d5e2e1aab5e44502f56066cc2043e2cae5ba818dc0c50cad227e5a3b6e8e60e295c3556b09cd06351cf000c015cd0a2d16581ed8ecd74d4c2926f4aa6199c0a3c6b581ab5897ab1c5266a031c232c018375e5cb9ce5cb96e7c80e0ea66e74c7145c3e3c60733c125c415802b3a6c7a0841436b872b1c40700061f5cc84c478ccced0e02a2126042362e16011c58eb86235fd0879d5bc9ab862d9bc7cb4786c7e585eeba6c553a3e42a01b6c2cbc7abe6357593e326070d0f9a0d602bb0d8a0e1e583c58506d7972b11a65a392a8ad0416be806c76bd6f2583daca3d6d3cd8ed7077b02fb017372e9b8e1bd6c58aed60d8bc5fa5830568c4553c3418b056b02cb00c753cd0cf682792c588b484b48cb8bf560fd9881e603171357379a9861f66afd8821d1d0f282861c91fa99365620822d3a0046035fce5bd40f58928c5038c108be62842124880c470c168505264e67b208e3810f7cf0c9220412027811022daca022024f2421041c6100e7f64167336050a60b316130f000196268410a0b5098382551fac0831d1b483101199e58400c30881d7080ef0737bc280195dcd59936d038434a941d1bcc426045062a40450420c0001f7ac0416c6185274c9c98b4c822031ca04096a51170a1851518a0620a248ed0a10600c0a04c08c4503185140db072f52453d20ca74c0abef04203189840145028f1030f4f8a2d4889f28429c984a19d198e165968c00005f8c1ca932da4c0a4946482a7e00b2db2b822031388020a062801440f56a6a4c0748209434688fcec64306bf999147c51822b3490010c4c200a062801c40f3df060e504e21429280801d7506389121c3748c001961d7480f2c4c7081e74d85939417386d5c6c7864b8d2f0631265a4b7c4a7c497840df0fcbc7036d7a5825b0e8061f7c1c783f603e583d3c1ead1dde06341a6490014bd6c271734386e3e3a6870d0735331a58ec05fb5e2f978be5f9cb4a8d081bb882d1c0685a376241301a560737523338e5c4745e3531a1d60d0eaf75f3125b3a160e6bd6da020004b87addf860342d1e9c0e84167055e3e4866cf1dc98e123f2c3d5a4e5bd882c7075c212a41900be564d6bc90e1a572aa08104303378aea1d9074866f85a3e583da607a4c8558298abd7eb83272b3a7018d5c04a32c30d573d689edce4b8c95145498719d335675c116d9a24342064301a168e8baa85c30e33c45a375e1d783886ccb0022368480081959819216e7c362e2433d89196928fc285060d5c3a354a3523bca4b448801da141024524a161091f3690f958c11997e450c595cd692b0000708070784e38609900eb1134430decc8ab26768365842909ab831aa533ae6a604c3851b1a51f494a35344b3751249104ae76b478826a5e431ae0bc6a6c92725a40e2aa26b6e4414d872b174be6f25e2abc6a5c26bc482832b2396982c4965e35b01e38483421b49c6876e4e060041f1b90102b4109d40833d4c440d8109c2146989e60372d980fd7102b88e6a615842281d1c06a5a425c4a5a42483cd70f1610d7063e34b1917524c9041eb19a0d688ccc70e4644324a6d30aa115c26b892b126eb4905c25b83ca009a1c5018e1f5607345c81423c968dd5d362b95cc869218829f07d620160bc7079628923729001062b4d65fb91d6821416a0386912f5b42485a521a1213a238800026d65000367c400630528148990e3a3074c0b07b048020915925018ea40c78d4d78f3d4100c141de4cb9add607c36be144cac865a8cd959e14c1e6981c56f5fda2a9bcddfb5aca3fe232d90807a88cbb4a0f9afae9a1aa7eb5259d623ab2f0afa39b3b8ca028a67e193858c0364c02934d20b072c074c92ac1c409213f7f8539f39e0239fe6ef7afbf2c9b27ec615f114f1149966a86b0d110fc9b4b3fd1b0d0d49511e6d452c7e747fc5fd1aa7ebd2d09014b65d2630eeb427f13844dbc0167a996ce08a5975e10668baeac20d2071df4028bbe28b839fc3a3aeb827ed68cfa82b76ae5efa38a92b9eaef07fddfe1a7d5d3f6b60cb2d9f660e679cbf4acfd54009927fdfc8651a90c9be8871079d644c69651d9340dd6fabdfbd12bd7baadaa98b764f55b47b25b9dff6493c7e31fd0b922f32700a4def13efd764dc0a2fbe5f5b91c5c12934fdb76a8a667d9cb85f77e0322b4cb12c2d95154aa872cd7d2e9232f14eaabb22d55d496d7b285d73d2d09054d10ee5011af2243eaaed6a13c9e494426e84a2ab59dc768abc96ea56ddcef85af1da5c59339eaa3911db2ed3e7ead53827ee2aeaafb237f25a256feeb6f854a3dd5fc56ad1aae6c8ffb27662a4dc68a5ad6a4e29634b24e8bcd832118def644815516e843234045455c5ce1dccaf4fb2e676796a59152394baea6c962c8b8686a430796a912cf105c660f2d434bc40974a9a27262f60e554f89ca23b3a53748d720125e4195523ef47e9fe5a61a3b2ac639114918d89795261bc84c4381d19700a4d57d1025dee2962f2d416c8024ea1ed9e4adcaf2d6085c9535b80861528632bf95b56012dee0e9eb50a24f11c66bc4d9b47fd48dbea9df25f1d93dd2b191a922a2a2a9222ca58892889c80a1bb97b082ef3b2c5bd98322f480e4ea1fdedd6d224f39345f9a132d2d67fb3e43e4d9cae4b4544e33bd1f9c9fa4bd87699b6c6e6141fa0294043ac9ebc53a461f52493a1a1ad7fd752ffdb84cedbb5bb6a6e8dc7229289b4626e849271ce8fd375293742216d5011a0259cae380a3899f15da5f0f252d820850fa92b8e4e408d092431812777f062f3a4e4efb152f2d61ade3c3cf9772de904645e3f4345d16587961ba190f7a368bf6d5827bf8eea7fa5285a8822b6b5cdd910dc96929ff1c5b81327812fdcefeb50025048000012e0c197263e55dd344ad62e6174c9e260d311947c628ab7cde14d29597134ece2a44bcc1dcc915211c0c2ac79d3fdb208ec22e0e3eee0cedf8c6b3a745b0ade100263408008082c3948dba13c24138f0e8d5655dc499a00011d5e1cc46dabab9f1fa0c30382a018e3e0e7ecce98f2d4fc557f6fd7d65dcd41f1e4ee4c5ce680329cbcef00313207ece0a0d6a736f1d6f4a4f2f99fc81c20d4801334004b79eafd37f2b4aada5a5aa5edad2a34008a7bd311147a2bb5e1a406f09031c0020cc00cf880011fc8b860c1c5caefd728c6b71ace26d5f67ed58d96f5bcb58982e49b26cee44e9f38ffed567287d6cfb74bab0ea8afad393bd6d224bf8a0b757730d7727c1237dedaf3f9e80932e48ff471524f68b927b6d1afd55d37ce7da6e113a683f977696d4f2c81f4b35e4019f0628a498a7574b7539655875e1d5e40976b73f9f7933a88d4025e7077506a01424e9071076db6b33656936aac25ad549b1597ff09bc96ee60f2d4da525d754e78019d4842e6c493a578dfaedd27ced486e9aeea28be25e5f9b2567163fd7c4faaabae093337fbf9abb0be55d68416f7fd9fcb7893b69aff38a92670e0eed61cc578e7bf3add041277908932fac46d4bdab23e4e8a892f3226acc09da62328d48649ad3fd7b6d5d9f88e54c6848fbba55fa3d1a4644b8c01c9df9fcd2f6b9526b5c40c5b677dd6f16b947c7a4ffa3829f2c9a2a2b2ac474554572a4544941ba1d89c5d221615ede810e54628a255cded72b5a3b5fdfd5a91d64043cedc6f2bfedbacb0d1d64fe64628454456d848a6840e0f97291103a7d0645bc06cd9b20577cf2d3e0e4ea17dcde651d7b6c8c8fb7a4c7e5b125c3c375ac992b802a7d074f95b243f09289f42bbd8eafba63eb5f863c6b6a1215a14fa1f959f6ac4a510d0cfb9ef8973b5485bd526cab32304f473521e1da2f19d8c45f96dfe938a58b42374521ea15387e88a5fdbd51cf9fa4b8c6ba2b6fbc49fb39b7c2754232e8d7665c162309a22e16c0642083a20384d11978baa34a95c22009901f971ff51c1dd7fdc4510c1e5342e1a9c1916387777970f2aa044e9254439d0dc63b0978b86f579beef5791163bc95f96f5a82ceb91161504b183115218d1c50807dc8cc88c38c200089841004600c0852096ec9c116f440b412c1901c5ddadcc5cc6591b7ec88216c1c5292de39c5fdca749837259114dfc2fded49e9447a9080d645a5ae0645977b5d18b2f0ffd1c8ec2e4a96ba6c5e91cdefad4e56c2d472b9ccd9bd535912c2d4ea4dabadab0cea499cb386c13f5eb2cea3a8a358bfbb5aee419f5b56a64e6ead69fb3524c3ad44b4c724cbb7ceafa59ca0994deda96bf2dee8976d2e466b57ebbef898dc8d2e28ea8ead6b7c9d655e988fc5c71514c660ec9cce5256cabb93e69245d737d0a6bae4fb942e98dcb287d2b2e491dce47b911caef0ab55feb30e79a6cf59760f28c7ae209776f015e134cb87b4b784a6c71f79240c2dd538077c45058fe78ebd18d3c53b85d4b75f357e124f96d173bed6ef8e64e6a6785f3d3107e5d9fa49820d15d7d3a732605698066146007e75908e1c5871388b1854b600020f0f2c3147524ba04d1850803332e000c9015041bbab80d3a4431f2624217b722c101ba486203342f83f802041398808f571cd4b03a6ba83f41807863012ca0b81304b8e080002620c2952020c4160207c0380a356011440e2746f023322b57f850012d3ee4080aaa87cc8a83381ed4a005b5f94e0b3ed00083fab9083b5c94a10282e4406a06a0112922c73b60e3011d48010957ee030621b4400d99e73c86886145491649b88e295a45bcb8c1876b7005842096c830c5673a5ce181209c94c0715c801e8000b52e57377450d0c50688b4f84d17294334f002832b9bdc120a4526c16b8ebeb822c304059c464802500738411157b1a5081c416409dc158c0a0735d8e064057f3d51a60009297af0977791982ac0e4aea740a2788103496b0b08eca042f383b75800c28726640802098b05e1991b7ab0171600aa8c305778e28aa5d33282012098f1f289290112471be470f5ed90c1034c2a332f1f9315b9032531d0f2dd3822840d4b977a5b4860021b8461858fb765892412c8321be3c10083130b50a38b27cf09141518401121a83784044922d0008a325e0e2c04e8a1e5c0e266320f4ad6e0c0957be1d3346e0294f12f32ec114050228b43d141090ac01ee878111cb0bb870ce0fc07164ed0e2a668c96908824814379a00e3e7122b96c86081256ec511ec94e080166f4189a72f9880e2ca9bd00c61ad9800852f21a5904086e98ea4254783528a1dfc04246a3eb013c47523158718722f04f98f171d170d57ca380f039ec2e4548185eb8cd0811910b270e021cc7a50b8a2e28a539b1516352419c13bf8318409333488c27d88b0446b054398c077c0108215041c6980ebe891450384e410c4332803012588aa40037c0653a2b2a10726c7b144c78fd404ca380e05c6a88247931bbf819202ee220ad06d3668238a1e1890c069ce987294030531f018191a986007213e8fd58c30822953ece03021323fb02c6186bf5e10a329881dc07057980c30104601d65d4435e70520d4e02d287e0460881c2e78eb0897081411840a676d200268fce0a53a0bf702dc112cb0c259321007890ea8e09f971d03177af4cf4a0c19cf04a27f4232482de0e7c6bd361c6064822e0770ef0a2b7609a404b947448e1a0ea80206f732d1fe028318f796643985e8c4c03d12be78f0c10674dcbbb981c05665873b0c3c10c1f5c200dcb72080124b5c4000ee16108090323b27ee0bc0828b27988c7137008c2cd3c1903b0fb2aa145a1eb8c7208198030e00833b151094c06b2dc0dd86c4aaea82e31ea504b50f062b7087ba6185303e9eb8a700022e84045871371a02044042bce06e42187393f0722f424512100ab870f759b2586820c8bd04110361e436dc4738e30b129460b983e0568c22c8c2fd032a55e0d0460eee1ca040231a0a807b0f9a10326a74e0bec106a6982141e39ea30a15da081fb867f0554865b47097d9b0c4088440c3fdc6163b70e1840bdc719cecac6085e96ea3c68d13c08ce05e73811368051ee04ec3c4073d94b0847bec8917a8a48001ee300edc2136700177d82705e4a105ee2f2562d49c38dc5d5b7042b0c3e7eeca2166cc0a8cdc5b580460458c16f7560f2b8c18000b77d61338b10d90706731e1c9a28222dcbf346c68e8a1c7fd63a2090d040085fb6723e19b3670ff8248400a006471f7c4300294e173f728500480d001ee9e0f3170fa02e6eedd9e886e43b87b465facacd1c5dd0382860f458edcbdd60b0dd04101776f81c743dce1ee1e08f272c50fee2e4508b22849b9bb124730d143cbddb37c8e0a15dcfdca0a665f6aee5e458d323060e5eed7851d02a071f7110524369872f7157472784289bb3ff1b8d9c207774f42c62e08ebee488c0853c50bdc7d480604169cbb13d97932868abb8323a8c04801772781874f130db8bb08608878e1cadd819899fa401477f7c0cad25490bbff98a2a999c1dd7968c101490feebec10741981370770dbcb042092e6a209385bbcb68b828c00adcfd062e972374f71b18600d68e1ee365a80282273f71a2a65f4e0e2ee34351f3fc8b87b2c878218da70771810576140c0dd5f1c28857070f71707b42e94dcdd0543931684dcbd15c699e487bbb7ee0f2f4631c8428a20868808e2eeac20902900eefe9d4008066c71f74f88ab0390e1ee9f94cd171ef4b3c78a4d27f16bb5d603081e1c4a24b8bb03e181bb3b103d40204692104840870135dc9db58209c584981c67c870f7d616239478d260025f8cb8bb870210519860c1c10052b8bba7830b3ed8c92e2226dcddb3004b860fa410a60aceddbf1b40c88100148870c506dc9d65c60b5a6840131818e205eeeed10e70a48912102d90e0ee1f142d3cc0858717627e707716979b1ca47e3cd1022677779d902b3242888fe70977ff9624a190021d82e88086bbb374f800260c21b248e10177f7cc245c804002a088c1c3dd3d072ca0e6385220b1c3dd5f041080192fcc501b48dcfdfbc28c1f5e584308141871f7560168b021701b98f2c2f7dfad7ff7884284e0d7d514d2d404d268bb9253687a68c8567e142d0a7ddd84823ce45b4aa3d5fd39fab89df111583ba39eee8aa37dc647d63e0593c0b2ac47e03ecd6be9e730ed5f094bd1fe6d655947905696f588f6361eaa8235c3a77f9b88b728fedbb0ed5af17eb9ad4e6b864ea0ae22dea24dd4fd15f11669d486cb5a654f2aa4154b8c4d11ccd8f6398cd35933fcf16227106f11a4914c21ede23b566b8651229871a51b9f54a8b66688b40b33ad4708cd9a7597bf0a8fda926fad76556f73127057da6c98bc15772d99311e4b3ce28db3b9e9aeac39bccf4a2f8fa61aa90dd721bd5fd39b0dd3f2499cd327f8ba676737befdb5b9e66c36a9b6a4d5b5bf91f54677fbf7b54c4f2125ed27d9813f3dda525bf97a5b6a048220e5012ac188f2fc9460a4b36f25ef8ffa494af1b6795bca63741ff78482e46b8d234ff271a336adce864f484e215412d0967fdbfefc5305f26fb72a45133f3f9931d5d8a4bbafe92f4d5a626cd6e8aee69c74d556d3685affdd23def4a96a4e97b6ee27e9cdbbda5bedadf1d213a877f94f2a4c4f61c6a02ecb0aeefbb5fc4cf5892fceb8f1ee74d541c09aab69c3a22802d12789b34931120572bbf656b7a6956a6bc3398cd381bba72aa9f2e76825ada8ff9e6091dadfadb7c6651533d6e35bfdc5b42ceb675314b5adca04f7eb8c773525274fd486a97e51b4559925c626a5f7766dcf67932a3979a27ae7b6c636204ab7c6385ab3d554936fb39407db44f16250935f5562fdbf71d5586b94e7f7f966cd63d4ae26ea6d453397712288755973f81e5150977f6fc58d36acf715a9e44890e6aabb3a4cd26bb735edf8598b23d6f9f5b6e12a8ae06baba3d13e87a3686fd2df95b4e4ad23ada6fdf1b378b1a5859ff111131ad5aeb65f49ccd82682b4a3dbb5f766a368b4527ceb58da2a569b7fdb3cea6aea7d62b0ac27950fb27bdcdefdc5b7f2d45c4d5cab36cc444551a491ff598946b5adb9da6ca5bae64abe3ee9adb8ac944632d55c9f68175bf2b7b63a7feed4ba9256acb99a2298d33557f3d6f13f2b51907c6b9ee3883fdbecd3cf47f4d6aa2f3f535d478ac5c7ed8cb5fe713c69d87699a0cc13e724349a0e5f1add950a57d1df1ae374d48629254b8b1bf7e336367738fae4eb5aa3e457b1d8762dcee689f38dd2c76d50ef4f0292aff1a53c9a2cdf56baf599bbf489825aff487efe7dcfc7e5fd5c0e8f9f9928a82da596664cc9276d15d33e4d4ade5a96a7ed49bdbb955eaca744f141fdd9fc4ca3d1ba99f0be7a8f67dedaee5b6bb8ac5127265129d04a75a5db1e25a1d15d9ed5f624b566485aba5fefd7a415f7ebfd5aacd256fffd1bf942ae3ef57d7df1a8a3e01e6bfe7d2dc55beb2f45f22dd5b6877ed59428f42f1e455b15a5d16b29fd5cd5f42b8eea1f2d792db5d52f2979ebc5a6aea7d6f46b3cbfb1137d7d6a5bdbfada7aab3b9bcdef84eaafaa5fbe2e932848bb34a8a6261edaced5f91c8ea227d0a88d89829ada72c636a8a62651dcfa6b5ab4d52fc59ccb691b16732e07e230ce14aaa9897ead1ae1b6d589a2086eabdf178fd75e2614dcb9f9dc64ae38aaad8ea5b76b6d968237f0298f2e6db5edcfa3a6ca58b7ffd2c76d5d47b2e25ca35fc357a7ac232ecd1fc74abf46defab51d1aeddaba6b5887569af1a69b8abba7cab84dfeeb537f3ef7a944c18be957d9926afbbb52babb95820f5acab371377bbbf66b94c4b8fd394cf5dbf23325eb6f5d6dc6f766a9fe5ccdd5a4ba52dac6a5a651d54d999ec2db89719b0e25493171a2a0aeb22795b7b9daa969c65afff8977eaeda86717ea2603e494a37d596ee9eaae25dd6d166bcb5c595e68947aa2dcdfdadea937e69e6aad5d31b52d3e274feabc3364c2bd576e352ef903fde13df5be9aea4baea74a8d55f32d7db677ab1bd56047123369fee5a824946a1d179b3b68bc74a6fd7eeb62debcdf6a4f2995ab3529aa841bc29cde16ca3bb5cab68595a1dadbb92fa71d7be0d54a2bbd2342b782d259f3ccbd152fd9fc3e33ef5598ed7d25ba935c39c6bdad9fe8d40bdefdb722ccbd3f6faa44c4fa1b8adfe927ffe4945c8b6fa2beed72268c3389b95eecad19ae11326a0352bcd4f95b14eb4d93048a974ddf4da8a1b7b6c364c1fb7a3687eb23e4eef5e0968cd1a45c1dd53d112a8ae666d4bbd7baa27f1f8487af754e2ef1b6852f269d292f0288a92bfebfd3477e66cc50580065106671dd536882e0e0681450741037da8b641d03a03e2cbe3b6898118c23de7ce9b3b2fc964f50f66c029b4fb26fee1cbad5f8e3f64a1c2e60fb81f7cccb83b2eb5fe11cb17700a0d8b88d3f6b1d0ecb55874dc872ddc072dae6d3ed4e0830fb86b0f65f29bb4872f610f3bd45d91740f4b7ebf8798ee2f0f5e78b8e23c40e181c70e6476d8e2be83b97f07243bc45c07303a5cd1018a0e348732e0145a0e39e0dc73f0c1c18ce3d0059c42c3e10a8725700a0d07d9953157b8b85f311d9c42bb2274dfc457620e4ea181b921cb0db41b7c6e701bbeecc6fb5b5badabb9abd990c5069adb5083b85fcf6af0b25fd780c57def1a68af6bd0995929034ea159e962e5cacc8a0a3a87452c5ad5dcd561b2c478b4aa39ab8ac57d925627e236ce5f456b118bb65c25ee6af9f9331e45ab9ad3bfb17edcf8b9dc5bb455995a87715ac4b7dc5b6bb23eae52615c8ab76b75aee6fa6434de9d0ec59a78f1950de72b2019bac0381d8dee6a3cff364a33eda6d930e5a1fddb68a1d6b57c9bf86f13ff6d62d12bbd4d34ed46bae9dcaee2beaf8b848686c8ad4553c760c6a748e1c1385d142914cc36062eee0e5e1c430c48dc63e0010319aa9afb8b290c5ff0130c59dc4fad6b09c3938364c6365bad5230f02837ae7ac1cbaeb4babe70be401d3c699487d48fdb7b575d712e94016fd7851e74f89ee4dd6311365d90552173cf2a5faa6871f72aa67b95255ca577f5eadfd5b26e6bd6b188f2d4a322fd1b3bf98d9df094f849a708495f5c4435e225bfabd7d6ad6b7557efc655562eb0d2f2396c45734b7ec5e5688544c98a475935ad3a32475deaadb8a46519eaae3898b1ee7550f0d66d5c46d95a1518b8aaeaaaee4afc4441b256d1bc4ac7dda9129413a7d38cbb9f5c78ce2b77da6b5ba174ef44a3d7da66a78ed7a80e72ee2fe0eb9d65d3665b666fd96eabb5d5e690dc4cd7253ae60ee62ffae62bb32c74d2e8102a63dc3d5f9efdbb90cad5df9bad66ae8e54a03888739fa3325484739fa3b285c9e5cd2b8e7b2a6c9a38f739913429f9580db38ea712f9dad65c94df161d6d5d97d42cf67107cb32a4b3cbc5bde220f9a57966b29e54e8e34d3569abc24bc49d36250a8de6bf5d5c5292b4353abb1ee4bee4684f68e66b8c1b733bb8833ad2e66cb91cee2005495ba33aa5524c79e5e0b5942c1f47b5a556b7672514f75247db32e6545fdcc119d516772a2c0ed24b65c3a59e32e3eebabf535bd4a6b8383885264e594931418a9afa291e6ecb580fd82bf7d2ccd9247457cd209f67f629b43edc2f125354d5e498247ed1ce6793bc5649ee4cc23db9e37c70b12ade4e706d4e146f55371166b62ddcc1283048cdd534f1a617d39a6f5502353dafadbad0b6e54e11a3d0a8eeafcdeada943cbfaebfe4df8bbb8b6559c5cf024ea191b9e2dac562fedbcde66dc53741fa4bee5e1ff73aee471f73f0ab584d7271275f20f1a666d5e95c356e63d0ac3a4dbf1c77e3db6c4985d08d4b5d473223168af7eb3ae266e3e3a4467777128fb406c6419269d7b238b893d3c1ed9aeb13ad363eabc1502b01dcd5529fe569da5b73b87c22f1a8fb5bbfb85975ba6631dd9d246b45e25e7938ad8ce3527c1a185a02f2dfeaadb9a212e3da5f8ba7689ff884c88208a40518b4a0a585215a409a4d39630a18076bd8ccfda999c07bbbb6fea96b0fb843a3e950f27b6653b04cc94de1e10e96f8946246ca172958aa265f0a1477293aee1ec54c388b428128b7281fb060c6c11f8bedaef975adf234a1d5d2e66c940d536d495ab62c6871a7d5fcb4190b341a0b321ac59b66c32b2025d1d13c57d8b2c295575c955a21079430c01dba53965587ee72ddf72c7155594328d7e2291343c1e2b55343a139883194988354a3a5daa94fb6202dddd17952cb7c6aa727b4273ab4fb4bac6ad3d0102d0ad54f5c9ff45a275c1c0c5262ece4e95eece424468d9a80d1440ba8b3adb90914776fc2c149e5c92aa586d496bf18975fdbd51c296593c211154594095e8b53d0e15237d1db1dc98b6b184fe1fdb92824da294a06e28d2fd41710ca0a541215cc501ebc77b75615b858555baa70e53e53c107b4375cea3a32d127330e92afa34f4f11983ded4aadbfccd84633c69b4ea10d0dd1a2d06be993cc73b6cca78d3219e3a710d2d212e3272658c012639b2913288e315252ce52ecc444875ad51cd596eafe6e8cf3a8fb4b5e6c54f3b6fa22dddf6bf194786daec4d814cb5ac3e5adc98bfbace90a94261dab9a139b968071f7d9122e164f2db9222e59a2335362c6ddc59912304ab628b9721795a8a04592a9c4f8a928ffd09094b82bd4d1ae59b4aab92ff7c619b78b76748a8aa4889a509e9abf488a48bc36572bc238eb2f315489f193fe12e72229a2ac97c6804b5bdc974cf7a52577f770c97b747f937cf16b294da2b3aa4d344d5a91b462121d2533ee2459bf2809f11b5715d5f03c511e92897c7d8a4bee0eda241dbf5513e9cbae397dea505ac634a42c7eed0c0969b455f9f5c6778644c2ec882c31a5bae2cc7ab4038dcf8e68b3a39a31ee9fcfaf2a5fe71eb7f1ef5b733d6f74e38b1bcfa89bb199fb4db535dae246a6b6746684c4dd6ff5291c330b15e0e0eef94c7735ba2bb82d79ab8d1a1a92fa5b35ff56cd10099e851e805368b9a88848e713d77037fb5724efdfea93ae6511e5f92a36caacbf440434a409de9789f2089d667d9c51936d6b4550484b444644e33ba11a6b0d0a29e3a38c6dbb8a78dc186771a9acfbe22a36635c91eeaf1645ddc43cc9fab8a29a9da21dcab33f2a8ab4f9d4353fd35885cd8c772d4b7cb41baf4dc4bb8afbc4e2e7ec364f9c937c59b3e689f34d143fe3a3f262d13c8b9688b649fe2ef2a9e92543434343e3576d5ba33c42a735d27fb1dd3bdc6d4b34be93ddb64b44196b8dd3754953e5aa138b9c28cf1251f8744434be932227a223bdafad79eb8bc7a21dcae3a4b3b34f26948764d2a9c2e6f84ec82228d1cc9d5fc53a112d3173798909a7ebd293f8e8622b8ae715cddc295ad55cdd1589acbf248ad7e674cd7f44872f25e911211e5df3ffae1422e30eead2e274b467eb6aa3b76b85beb883a45029b4c34819bfd83c29881b7725efe79aa33c9a164523695a87cb12dba8de555d5943235ab4b53323381abe467cdc7d1634a6fe12bdf69e4147f82c284a508f83f573357f9083536845c01461e2c92a366a671f59d526f28b9c501e251b97511b97e2d0d047511e9289f2602745444745524f64c5e5ae9a24d3fe28d21625e1aa225bfd2544e33b79123b118def842cf110b3e7331def90a45308e8a7c9ef9a87f000f28063db65da1a3fe1b67d026452dccde280908026931eec444d9801555cfe6c81efec8709a75627de2fc59fa71f9d990f191f289cfca121291dbe3e393c95ae5254ba6e1f21f7a39990310e92f76fbabf9fe94c88172156b78e33215048211aa72b0ef4a2ebc63d17eb13cce220696d20cddd4c320379e4ec7ea8cf55272a5da57ab0f4d07a847a64ee3c2af85cb5bb6d8b8a9e8686663c347710c72304ce786218a72b810cb8672560d9d9d54a803234245502757712cc5430e08c842b900412623b60e88e961d7347a8ee50e98099e96471f075c59934d4a1e9f83818c40cc6370818f78b836cd141ac9e6a949a05f101edcf46d8427fbee16cd26b69b5e13ac216f029761a81e656b311e84c04323488085bdcc99a13e14a8424be4f1b4e575c4e2ccb1ac215a79a850025041d31bfee6de25f0c42997bda3e83b00504118425f16fe4794110c1fd73566a969345eeb4614aa576655977d14e2ed7b2eab2ac4745455463cd5bbcb68827ace1d9956595a23c479487f2508d354be5ceade96877dd3ac808fb7e6e8ff5be786deedadce76a7e36493b3e793f879bc4f1c9a2dbb5b95c542445f4a5794a9133fa644b9b0de38ba92c876f38fb600b904632d13ee8025eecf48100284949a6a50f3470af5fdbb93eee7e296adc3e4351f777e64116c739dcc483eab75aa37f719307b48ed5166a4be2f27740e6566b9f3bf0024ea1cd3ae0c186c57d71b689d78afb34ab3e9b9ff1a8b7d5dfcf788c1a1a92ca6f9aa778abb5d2d64dd6c7ed44511e273a5b676b1349317f152e4b9c49a6a1a1a25d7da2bad2fc5bd7dc8eb422f9bb7e9e7160e6cdc1925b5c157220fbd1a5b4fb9e347f15a6ba2c713641575cd4ecc795fb8f27077ff8fc70cf67cd86b7f08145876fa53e9e707ce663e643e6e0e7700f14cc7a607130e3cd44c11e4f396d6fc58d9f9bf5e031e3b1c58e927fe9e5c165c6430aac178f968ace78cc768c0177ed715b874b3cdbd105bc12b263c933e6d9212b6bf666cba7fb77748312b83b58c4447988acb05159492b5a3d7999c8fb66d40642b30d78cc749439673abee8c8e23a4cd2e2aa998e2707a7d074e8805368628e3576153f5b534911c94434cb719503cacde1e30e6a30e6739d6990c5c16d671ad0dcdd7bf0c5cd34e0e1387f15a959065dc68be9ae94a664491323310929844af2d4445c8a0a97442861138dde8a9b32b072cf656ccb6f56f90c96c05bae33319ceabaf53e31c5b708a7eb126ec6e59eb32be2cf6650dc67331dbfa7ac8d8d6fd18ed4538d4043ee97b76b6fd7ca74ce9bee2f0e330ee2f882e32ffe1cd6210e1f4ab5bd31a64677904b6f6c719fddc039589b66377860a719ce98190e1707e9ce679cd3a1bb5b8f663850dc431c1f0733a64052331c0767375daa4edb9bd5f8d2fd3bca43c31babaa939add20f152f7b699cd18b59d7e9bf116f7cce6c946675663e6479cd568c05d57a2cf59a9fb385dc645a1556ddad8e64d79eaae484536d1bc99b5d79165bd7d59da9afb6b6b6e46d3c57de7198de995e62987331aea1e2bb367b105cc62385b7336ef6a7e9ec574c8cff5cb7106dba2a776ea196c8b83ba8633186e06a3eebb5ba96e82cd5ebb6de65e5fdc1d3bcd5e5c1c24ff9566af2ce0ec05c5b7cd9274f692cd5c65be685716f7abc3b533ca6535734171b047d74e3d7309f9cc256b9599f9ac0586eea846bb5b4e80b468a7ee8a4479489ddaa96ba72ee2a92962a2ba52225d74fb5c7745fab70d0d49cd585b5cb3ae5850583eb97ec992815368649d7d6448b27e5eeee70f0bce8afbf5ec43e2e0149a38fba84ddcaf675e19f18bbbd7ce99a7c57ddb93cacc83019c42ab9d5ad4459447670adbae2d22998894b6987917dd3bcdfc8afbae46b59d396de642ee33e7519e29e3e0192ef975264c9db97277906a7b66c91dccd5f16be4191dd7f68c836d70a1641b58a0da30dddb40e20e92656d8387bb0ef2c406995a568d4d2736beb8bf8dcad8c0d1abc3e4be2716f2568a0da19badd18b755d83056b64e160c6bb9e7847792896b2bb1d1631511e29221b136c49d28a6b58adf15485b369d63568b6a6d58bf7b7d5ab51e68b7b396a712773d559393885266ef3c7b1aaf1a44608bba2ddbe2736fab7e5d7d8c4d9144f52cc78d77c8ebb8a39ac4fbcffb32d0634f718c8a80e4d030cb893c6965d8deed76958ed6b7369e8287199193096fc3c9a69c2cc684686371a5ea08145e392ee13f32025511d2ebf46f75943c304c9d755dc4643c71d6f1d2a3b630cb893b1adaab8af699b3b834bed8c2b7e06eecf5802cd28e3b527290f8d56d68da5cc0003565d0e9b9165ebcf3233a0b8833b66504a7eaede32ccb80e97466570b95fc655595a2a1d15520692b08cb2529db7fe4c77db92f6a4624b32c03878b3388af126430b59e225b2c43832cc9ecfa61119443425a7ff2c35869931beb8975534ffa9c6c8e2e239064e8f21e4beeb93a238460dc94435e225a4d5f93fdbf4ad96361848c1c0c9d7b9e77e9c94a565c03838454a1429f496d12255e6292ce35527c610623cb93b782db5569f3f478f28f81793364cd356b5894675c58921a3551762db65fa010a03cbd65f1586a9bf2a0c24ee61f0a87ac10b6ed7922f58c2bd6868488ac80a1bd5b2ace30b90b8e3b6d5bd80475956b14c05e38bbb8b6068a9b24f8aba823183835368e4ef138ba4ada6986db76b499cb37af2ab585df3d7fca2bb1fb9cc055d5c5bdc1577509ba10ba0b88337fab906d12e005bb085d36814b733d6d11650b5e0c9cb1d1d9a5be0a036ed68b76641095890c541f2b725731d6bfeca02d359d043660b77077327a92d252f1e5ff75813f66b5a33193257f9ab584d66c9ada5f9d889d2c749911961056068cdcff3f64d9e8cc3156871d7f9aec08ac4b915e05081142ab8e2e0e34d773cbbb2563776a2d556fd14293c51a45050053e0e565da8821b590a309002d33d054fee2099abaee64f41c639fa8519f04f2af69e94bc35f79be90b2fb86d3e49775f94a5fd020948bbb6e94bba6b130575b8a4181f7d21cb282803a2000c4e6fec84822e200a5c40810e68ab1ab7a9f94f45560a4aa120963b41175bf3536da14e8025db7a7402f3043cdc411dc67d0eebaf95f59a000a9ddfa4f7477dd2d726686282d7182eeea0105da90ef217d36876c736d12e36bab68946ffb5ceae667b927e8933cd78cc15a8a9ee891be9ad47b2314b94690c0fea45184eb4edb359b4ef8ff99f4a8cd39f715bb4aa39247daba9c5dc79c98b6ba2786daea8ac24598b8086e0742d4d262510aa620964eebeab64dcf38b98045f3e93600b09acdc5d24c1d38bbabf24d8afbb30239af5731760bad0d28555fe2e96bae0e1fe65ade6bfe55975cb8c008cfb08b4e4fcb627c57104563e02280e4ea19d23a05c98a917d7b8d862b4545c70294b9cf7e5e24a73b1742d171db88b65697163d1bed6ac4dff59cac8d6fc385db72ec26df39176e417e92656b58988ea9eb8a326b76bcd5317e97dada88b767488c6775234be13b3a888f2107d3e3536ad92ca7a5e261dde028a83fb9e1889893a6d2104d22d5c5bd229045b3c155408acf8ef6a47ac75a578e72cd541b6a558539eafb2e52bd121780a818e0641190777eea9431f045fdc1d04c11512d357c1d9168260090431777721e47fb6edfbb7e6f29b545b315b4889e1e2ee2ee674b0aca3bed5eac92b46480c8f30661c9c42b38501e3e0145a182e9fc36c5dcb8bb1a658873922fb8019777087fc2a5bca3e00c507761f28f2b953bf4e481615511e0f78d95afc8defae2259e4443a15116d6d97904f4a95f5af2d2fd3d2fd72684849fc7c9a9f71074220eb801607ad9e3c6fb696abda92dbeafee6d3a46107ae48b27680d6010ada2ade370443c6419e5d597521982de5be38ac76a834d0c936ba20059942cc8c80000000000063110030382c188e884452c96ce53c2a0f14800378b8648a5a1d4aa3284721841c22600c00000000000000300400a242a4947caf40a86d2d8a2043f4b6a65378d87ae6a6ab230be45da167914bc20d90f0fec128a4574c60adf3063630b74488254ef812e75ecd5d5912a184e0648dbd6c3a38acf26b630308eb6bd7a1b8759bb6511b2594fd8a19c0b0000519e059de9ac31adf358cecc69c2ca94390fedc361ae99846f4121ce68c205e49502cc3391f58f1866b308eb459f613e311ddc805947da5aba496b6ebf0a33843510343f446049aa4326a37e516b78a1e10e1b8d56f126b02e0f6f4502bde60d6db12fac33a28bb704ee5c358c1c79eb3122a76b7c3ac0a80f35006247bbf75d9d4d9ae60cf90a1b4e92da41532db3e92ec2e17e59c8793fd12b814dc5f8a4feb9cc241d3138a2d6b1d98a6751c58e8d83b211683f54b50a83abdd03487dab59ca6832611fe9253075d680fc6e530f061ae390ee16ed95e5c56b71c6679a68199ef410a3c22eff800bd26f830494dd13e1fb318e84a597c1b6294b06dedb353990559984e9193d908970d06274a08dff4b3464ff42814dd06f2e95a850daa3b049bb9f7cab7ed688643db4b160c5fb7c2aa475804f0dceebf899b725ca23c97c835c4ec81fc80a617131e0359ff1ec43518e74e4abfa25a798d169c63b71bea6a0876f326f9594ff3460bf10deb64836bb63b129802c076e7ba8e20dc3ec319378ef2e82fab4ab6a65f629b495bf8f5b25e37cfa1b639076c8f09dff532b8e291b1e173eca8fb1e39dab46ccd9c321f1a5771164460179178c07e4cfc10e26c471bab3b007186501b202e8305fcccc20c68da954a976833cd217396075c089c848db8ccd07f53bc1e67e884cdf247d3d8376877c427e14baaecd9b47b570099bef7a97a8b71f345d6ff6dedfd69608bac7a8e2e39a75c728ec1ac7a7b5efc062acc8db73a68901674e3b1c2303144902400b5ddae592808188c4b9385dc0e9797ed9e89cc7337c8e7149b71fd5caf1a93b1deace9cbebd8df990ec661348e112ce0dbfa729e605060520b4cfe2ac85043b846e8bf5f689bb61bcba1a6138773228c4269ad81d8021dd7e0c2a08b4cd02ec0e2616ccc1b135ccdd3e57f53455a5baa2de4132e39380223eb18fdb65e909703dfc183a6a49e9d9d17d0c8a3f7924b6d09db6e7630e4103bc24585a948edac13c5b658aefe7def5b4b30cacceee55be5d96d763a4f2ca8fc11c7b2fa04b0d8036d77af9742c5271643eaed4ba91c03b3f0ff203956c2c0465a52da89445dc7c5cf39524b200768bbade85da51570a4da5e690d1156f16eff5323b2821b40489d8796938ad50dd605b1b1c581101e228b80bf78aa31fb0903e1960bbd57fd23ae16558def81a29dd2a3f97988823fd9d93d8e05c0ea3c3766f895c62c05784c91dc311fd4c53d5887e521502c6a5257c3793f0aa6a0d0771afeb24396cc5976f2b0099b52dc96ea8fcb818efea56f1c79d3cae5460ba2ef5085613c2116857d801d376db11764f84c98af92aa703011998ef3e7d0e009d5c0a348a2cbba4c89f4d1fad04f9a916045dae11a1fd29dd72094e0134e4a8be219c8bb6fde59f12758f78cb5e5692595101858adf0b29f5b7206778829db3257231a5d5e6cc4becb375c5cd6fee1cb40d98f205830aeb4c90208cf9cd3d41296dfe3269a7ed43d9b47782c2d031e92e5711d4cd5fc05e1ad14bd89bd43c0540555f855e0ed25e486a8a13893485030163ca7033f2578413b7f4194dca3173e90073acb74d78c47a50a60bcb16a02c4820a57ee3455b62a77378bf4df520be0468ced6d5b26be746edbb78918095016c046dc3f54e77fd82da3269abee40bb2a9afce3831b2ba014604c479f35cc441aaff21a35f3a7a2150c2b2c2007cc1a69910bef48be35cc274f3a59168280125d3437ac4ec80d185d8629d809d330c900a9c0f6e4596ac0d679a9adeb286623429188955f92033952c5df7746cee6d628bc82a612f27937147092c34bd1c0d48aa52758e8eeebd70e4bab2964cf61dd364ad4c38b38817ad349b64bc2af5279c71dd3d1b8e8ffbe65eb6ca39c993c7ba4ae14d8a4dcb1126b26859ec199d9119bf2112890f40d19ec71aaa58251a71b934d590ed45259536a8ceaaf8b4bf1a4fedaa785bd60c635a6b1a6c2c3cb8db5c10eb98e5d8785ca2e84455b7b7e9eea30a9f7296be652b83a765f95b390d86124a8c9142fcdb0c3c12f07fcc2043bab2101317b31fe0e91348d0b770b41cd71cb5c5d9188fa588e9a58f38d1ddfa851a9077756ab35253721e84df476e823d661c2132f25ebafd9629be55ddfdb1e7f8be611865660fe2e7df10d065dd7618c1c5c930a783cee06adf3fa7d7f1baf84146f08548906291fb79e4266d61c78811dc5ade2fa391ce8699d45021ae73718489538dac4004aa9fec4dd61a323fdb1fd206539adeac18d501629c7e892bd82575f2a3c11f8703f0f08e63fa4c6c2e116b11e7dd3c56741022753ada8a238e3c54ac8cf1cf522107fc17c1b51fcddf69f0836fb89fdc09b948c152ffc88dabf6e876e2497655e9c4ebbcaba3d50a49cba5039dbb113eca4c5569501fd4f68b77157c65cef1949e3b9d6e1fb3c359024819fdf5975525d37963bff51d4e410386ec092f129a71c65929372d94f1a6ec5c61eff688db14718766861564693771c893cc7806c963914652c75265bb90cc146b0b63a37fa91b627a17bf5b14f93459ee97ff4f7bab8826ff5d3edc58ece21718bb3be5f5f608a60abd0b8e2019731c17422e6e0022f052c9487d9540e3ca6c37d560bee41a03887a871e40dad42a752b4eaebbb91367be22c87380f22b28f32a229d7e103d39c97a811d144ba498074752e13688fd97b1ca330f1e5d7b06f84362c1fc061a306b711008a1d081c5b786ff24192c106b857ab43c529df37559f7955acd45cf2fb50f54bdf6ebdfa4dac735e98957a5ada8b2bdbce8fd8a43595068f393a1f30486bf9156deb148575bcf944788b9aaaef8ae3a2cab9efba10e6c7d0ef63e15c0ec7d0cf72a7c91dc38bdee0b4f08641aed518815c0485f27fd12b920b7e8ac7658c52c84e32bcc9e6e6669458b63dd922588c0c0429805348d512a87112433df46891ffeef80cd400752384490554874fb10204f9e9b4c7d81b6ee5b1c3837047a3010da714faf243f281d1af4f3cd0a3f8ee0eca5842b4e7a2be32329b77a2db0e5db2da37e0fa71ca73f95987f3318ac78dd945b1e6a605ef2a71fb72bad2ea8491a4c0030b0342209cb98a6b1d32987752785fdaf9160d10eaf620f97cae3a7473f813cdf03255a9fae097840f7681973540fd70f951540b073d055282b06d4acf880c9106af8aec4b237ad23da49b8571ce976ad74f22303576cebbea854c77967f862cffc6a9e425b9d246652b0211d61c00ad1e7ee04a2656291f7f66669d1b66575703153459574cbbaff7393d7039e0f0f93d40234dfc850a84d597c1852271fb56a3e185dabd41971ebdab0d1a5d3006faa02545a3fc37ba23b5359cc672103a05bfe4adb3127747d2ba6dbb33269086b4a5e050024aa7b5bdfbc904eb13019e5ce306a8428701846e95ebe7dc17628953881340b5568b1cb43b6f89a6ad15c5afed95104643d886147181fed4dabcd61e1c7740c1ba0df2b435c78133a0c80f3ca024864cc57e03ec7404da9b63242eab11998c4aed9e061e48668539ad4d3dee42fc8e7444df14cc0365ae61983d48369e078a9cec5f8f7943959e37233584eacee5cb0612f41a7b36ab6dff11a5c061532a51c9dffd358addab4b8e482b19df67eae8f6c6c8d2b0dbf0330966a124fa037b000dcf857c0b169c9a6184be227ab0bc75601f66e6908ea428f4d6c30047074a031b7775eca8a30bf4bb8b33211ae16ed10afa6602435f94bc10105711f455d1e9c39ed9abd7ab2ff86d629566f38c1a9c4cae5ab1ddd6b041b7bee8dc75c53ac0e3bdd6cd5d68ac00f6ec0a561ba8888eedb9104f4bb7cd74e4293d9c2ecc8b9315f683e7bc1a26b8bcccd0d03554317677d41fe03ca55fe46006773f83f9aca88586beaa61197767873dbd7177f53b99fdfb957961bf7fa5da0aa61d18082791bf8e3d275b8e91f8d713bf7377d0905605cfecdffd9de5298f0e9fdf63af6c11a8430345f983e41df7ef66c22fdd39f7928ad88a1dc4f3d9390889835457781ccca3e0ca4790fa88cdc06b981686831e0b11d3f2ed1f6b1496be4de62b0398ae49c4944ef23072933b600461acaaabfa661a2638cb0692687a3ed1929758fc5e194c46224d742788c53d3025c8c1c987132e4614e8e841abad5cae229bcc6e83c0c3011d5d617ac89d63387b1ee49ff10853f1861389c51d8267d7b7835fe182a8697b2ba3203dd8daae61def1ab272dd3e5e083eb80c4c948132c03c87981af1cd2bb333fdc7c7e3eeb8758cc377458d2bafee040e6e9f72243571e4df6ae67ac3808bb458826bab29a030f9c08db6b220c5334729b7d3fa19595077af673fbf22da884789db79912f9be1771aed99666e34b0bb7203973093ba55ff2a76109cc623041f32b8bce392ebeec21f78231d93a6e8ececa2beb88c37fc33b9326559da768108b3c7d4463d404458cb8b179c1f1cd6cad1269bf6b1b78302a0035c2746ec9c2b84f1c0bcdda1b7a90f33c957db52d18a8881947e810f7733c16ea5dfa666ecf35f514eb71655a53561da5535dbcd786f13d81129ee297e7e13f9b57d818ccc2609b706f300efbd65e7b8d7cbdfaacb5f4ff0e25e64962ffc12e8ad326bbbabd8ad2440de7bc007b9d6846731ce81c74576f093ad6757b98b7fbcd0928270b6b46c9f06b073f8102c52853f4b665536e789bafe9f0b254e0cdc4b431eec6fe74e8f8766c635a775b0e55eeeccff9b77274e1c29070b43a2d1bf5cb1ca596b77772d0aa432bcbc6388e1bf43bbca732cd87b9d9d552e1a63c1f744b5da9a8002a705dec7b70e33d4dcdd8f45bbda411cc5dac33cb47d351f99830b3fbe39c01237652f69e9d0fb08f51a8a01128a0f4a0e4198d644147f4a409e0abb3a0db11550503d6a1a5ce7d034e89bcbbe8139f5ba4f32a7562bcfb4f3e7c9905c91f20fcf09bad8e7e0818e220c03ea3bc7d42b3ddec5caa3c8195aa034e466f2bd6b21e89c37949ad37e4c53f5c8e8060839dbb832a15ad2451bd88c9e3d5d669f0c9db6af0c5d27c002cba277174f82c914f9cadc28c33b03d47b04992f64c8a10b0e5c60c124eb171b00d2c4732c7519fdd920fac3e8d8c2b6f4000a9aed34add05a177be3f8c3e6944187178f29544741693a8ce49f3521e41b21d8e983d89046f60e0824651f4748e2649d701c1d7e736aa3b1a758bf6dd52e39c736c568895c92b18a602b2bd16c595de76a732372757d1be5904b8bf0b076067f30b3c1b7ce7d5dbaf272bde986229f34f57be5e1b441cf445b629adf841150e3c76418e2119321c0467506763dbe65d4f4f769f47593552050e74541aff423c1186959532ed21684eab88b69ba02a4bcc0e8f71df1dd1220675dfcb1758953b576e0deef09448359776d1a438745480f541290a86cc6456648ef86def693ae25c5ef9f28fcd1585b4d15530d86ba46b21f6e2db6f1f9241bad1ca091776364b80cd3c3d136e53c3d125112b7d0a227819ec31771f2f46ff874703d48329fbcbbf59142846ca62a808df258f56f08f3d449d4d4aedb12519f13ecf86ed2a6b2c3b8b9eb2223e0922d0d9933b53c2c4966eec2a3f3d3ce556fb95adcadb8b6d4e6e625bc33ffc195fb3f6be70bb3f7987cf2cea58d388ae4bc86eac3ce6321f06b47589364a996e240379e5e39481ff65aae11af122f17e7ac0dbe92c3156d1d52161ae418e7f2a64acf04a36449bb7b7003b3bd9ffbec2274cc14f5b466cf4833e4b19f43710601a118ce014c69edcad134a065077ae871340c61d6a7d47cd2f6f5aefc9a2c0d0b98a1bb5b257b11915fb0fdd9396279269c11867a848e97a6e9de433ed42110bd2974fbce69d7a55581109f2a1f9f4abcd300a53d59a726c8c7bab233ca6cae15bd4e268745437dd7cc8f1c2d1c868c50f20da96f1c5e47aa5991093fc29e409b57944f9fd391905f156e708a754305bc733ab84c6dcdd1e66d602b3107c07a40e4959ccf0407fc8cb919a63d3084f4c1e2a1e5cb733635f665ce434f20da115039d6c300add5cca807edb4b41dba7b877badde1c9b9c32d571e8dd8f875e7a14cfdf59a6d6ac3868d78cb63a9ffec218b23f3a87afec8d2821dedef07c93b0338a8c8d474741b7785baf0b496419b71e012f78fd822de46bbaa05d8efed91fc8fed3f90195413ec38f5121657486f57a86d636152d4720ba5a73f01adeea57f121c30d408529982182daa57b3a514c027c17f25af6dcd3cd6f0185370d72526f689b6f80f809d5da38a0de6471f6136753db13d63a4f9c7d1cb4aa9c99b3862c5c025cd12f3b409c60978f9f48d4c3079bdcfca93dd2568c3c381f8bf0c19d7aeb4dd943cc1c636ff0afbd3e6476c3f8ef026ef2f8a13f7a7fa54892bcfba608702c13a1bf4a0d9013f7a27e86d9adac116b4a59961d9935d9ebbad15d548e18f453dff263e4e27e3669d8d27e6fa980f5852161874f74d9ba83959a56112fc5f3df51cce1a90c0b211e10b5d65c860e130959c066089eccef095cf6167d39b4dfbf90b7bdc5bbfec34c0ada482cfdde98cd8d885114cdfdf1fac9488c781beaf892bbc8b1f50c9e66fb6c85b78c17a9aad0948d4ec112e1e72d920db1cc08640e10c9c9d7c8e1a276906a511cae32395f938fdc37038a2b9ba94e883f2f65a561fc24e080aacfb93594334cabcb3c5b2701ff148dcc017807f5822a5902eb68a53e19fe7095f5c79146e2d2d59d416a0e69a6e29c329e3da3e893b8c851352206d2c97c92388b93cd76e761ae9af4f83628544221c439e386baa3d4636c73064f501bf7733ab507265dc3038f40c2585c1e7de58d865bc35ce3c2ca7d79bcc3b7ed21a4204fef324bdd53061c47f908c527db3281ccefb06f1aaca3d0e0680096e05ae573d98cb0677e0bfb5ddb97fd09c66bd4a27b3cc2acd51f070480f228b79e8b9bb33fa55d0103f7543301dee3f0e9da248a7c544bdaebc253f435d7db3a2a468724e063714f7094cf9395d0bbb38163e7449b6f4110f2447f4f3650bb652327150a2f744c4a26cc48fb3f5512045bdc93d47482dd0a8bd0dce7a1a6d301ddbc98165881e068e059bb0402e80dc8ffbb264f36d700018011602214ef9099ee221c5cb15614a23904e33e58c2e71af7e7d8ba5589de18b8dd3318e244ed3e5c3ddf9384c341fbb0494f0b6f1dc91d39928ca0188bf8f570d4f3302bfa3c12d0e0738717689505cb4f116630be4f3df61b0fbfdd0ffb23f3b089a246c5c54a5317fea31e76edcc1ad7d4acc6046f2577b37d8ca36c78057d5ae76005f85317d41810d2fc2472ed8b0be076a17b2c8bbbb85e840cb108407fe464cf376d3a6ff154f6d09bb487026f4c64e896fa80a33685caae3c173b8acc32df56ac0dde4a92828fb2a297e1aad6d060e89f7a919b0e6e35843f6b334f760b0547649e06a1e7d66ea0cc25b429cd74d7789aa1f7dabdd2fe73c76e5883af0a43ce030d35711d89501a67f330c547fac623cbdf874df7396aa2832595ccb0e828639cbf006b8cedbe6d72dea9a83ee7499b41b73936b03040e117e601daadcb23909c0f9c594d8ad848ee7e9e12e0d6a0472584f645207ac025778e212d31e7ea41ef20e53526de45cdffe5344f494272811dea996e1fa15d711587a95d4c01f268527d51565b62985526682188db3064aac5fb520001ffbfcaf43123bdd1eb3fa1877ea3a4b57e0015e61d940dbc14427ad6947d331e2cc84cccd839b272eba7c8f2e5849afd1395190c634fd5ce501e52af7d2762f8eda94841ec9e644de3c17245438f212f46de4878d6a47c4b1707a140253a99de3ae24e7142fa825b4542ee9bbe07944055cd39800fbd73f98c39611fccc2c89a9975ca328858d57ea4da7dfac70f90bbe85852927ea01c991696012854d5817db5949a721e40603bfa642089c3a27ac885edb592b29d04cce8d4531bc108ed86036f166005896be32bf30721d1708010d637e86c6e18401d4515bf3d72009118fbd3a8d6f1b34875f87d39885b43317b46906ecdc5d82cd376ff18e79d23bf8c0480528d559b1ff825acad3fa56338be42ea7ef957ef5d50979aa42180976c018a85ebd14cb98c25f129a147518580ab1f67ce95edbd3a487933a539024526d54b35080dc851b0ec2da21110bbb66db5b9695b48baad9225f0c6fb40623cd8a4fc8bb2fe0d4ae854ebda765c1009bb0ced6ad4a4af517467144081a18cb01c1b24dda0c95be9e074182ff10517732e2bdc9be1552e2a509f02644d1e7033047aabb27fe79711c4ed05c01809cd931bf223c0d5e75c32e31464cdb312d00a40777f1ce170302e507b278eceb9f710f45b450a450dbcc6e283d552fea1c771aff5e06c532600a56e5c033990e752e48e4baf863b796591116bbed0def1e681c4e922bf3890fbce60df408df46626415d5bb3df03019c52b434726e31ade970cad7df969b360c21a987575a15b5e651ad366072a81b8be6b308c086a8d3c6d9e9bb707c8b201fa1bc5f117c2c0f8f82bb872d93c6d30eb7c1d6bcc209a5dda1de6f25323aac4baa2dbe13162319811d1705e3d7729f3e2f3e50ac6e1e44ef00ebdc9c953afc331a51ceb62027e89f82bc31c3fab9a0d6e9606463181e741844a940ddd0eeff499c43b83a5554b978349f790780c1651b33894ac840b96109afb7448a9612e6a16d6e5d521c8df41a063621ccedf6ca4a64485f858db658f074bee25a4d6f3e29a8434e5d8382da74427b05307b4ed882090466bb06cd5c2ff92167159b21beb201bea790465a267eec2c9cfa426629c7997ae8c0aff2b80064a519c7afa7d92c43ecf5197ee145a887571600db7691c5f56189232bc2269480802a6b3b1a48ed9aa17a3b8a9457738639e5c9e8dc34f4380f253803b9beb9a121a00c7dcaede2e876b22bca907107bc36ee30b867cf2517ab9e109bffaac8bee2bb2843032b01a0a6d3b5123f7c19cdf742fb7d3136a7e975771b522bd8a2ebf8b11a68eb023530b6fd5873e3a348be2b2f896ad0e370539579cf1578bac83ce79c50b59fa56364b3c7eaccbfd3010467254f526d8155a86057d6a13f0400f7b8ce5428b0affccd01107c514f9d0588423cc6c8d22aa64f04cf27a27bdcfa3ed2fe1eace28ce3216df3f4e650434553db643170df77e5392cd48ce4fdc94a21eb3b321358bf685bed0cd7b81d74a8da70ff699617767d7979ec5e36865682c73a5b683b7d0e827898033ef077df037a8bf4e4e824bfe90e4a147bd7ec4bc6926dd63e498fa46745a90e769b25dd7f66a466055046d127c08ec1566fcea300cff48e704ee09a466303ae4f2af9047b51cbda7516f6c0ac23bc5e289caaa3d649e8a4670632bcff035603b8ae04fc8741b62ee8361fec684e19c2fa8a240b283fe197358432648da5d3373ccc55f8c6e73b9177ac1c04470c65aad5ff96f2dc8335f1f8f9aeb9299b4e4a4ce64f276625947f3d18c24159b35b9955a5ed7e1ec62472bf1cb6854a46ab03cd57399162c5ec92c6da4bcd7e695432a7134f9b682dd8c78988a7019506121333fa12b6609100f476cd58d30a9c5f4f0eff726d2338c30aa08cfd3554deff7d3ecef41f470629101fa0ae97f54ecd8790cb9a1c125ab877da0c89c7b6082f1066ab46c464b1de83da9bd1c8a29fd582119d7b7d400a67165a607ac985b96471816518c44df2467f7961614316c38a54ea8e170f88d1ee2714ff3bf0247d6a03668e5669358f0f337edbfdabf52c06c624df51be78aff0dc46c06fe90bff90f32c1d7a569835c2ac33ed9ed3d7f382fe9087589f270f575c3ff0a2ee527dad7c21e08274d40ed3b77bba23909abf131929669321984cf33702e76b8375f68ad92314508aa7a595aed7dba1eb8a24fc8363ecd8b1286d422d19f7cd38c7938e5a693e421667163847cd32700c8f041c7997b247d45b35548791484a6bd7086ce7b6eeeb7a2e868a0700afefbd2f03fe2688f77505190ebf17a71f12a0969a82f3050ecfb6c9b20e116cdb65d199953d3d597aa66e76cab7ad4cb2873f5754d71bdb02ebbc44e97d2cc41829c5ad3d66dcc992671122fff43c905152448a7434b68e3e8d0c2a32a3f0e1a25dae6cbebf4f17e2318f788ddcc901be8c6cc31dc2c61ae7f1c22b79b2eb5fd7a191b7a63e5ae42fc328dac11e065ac87424ab73e0ae6cde0436bb82e8f6428ae809c2f97411f2595e3ee8dfe6605383c354c6d2e790f97701eab8cfd45faa4136a7ae37abdb04e4ac467fce8dad7284458de002e4fb324fabb8b114d9e6eb01b9b0a2dd07c622bd4035a8cce0ffec55a2a581d2917faacd81b15de5fb0e023738c26e539bfcc648884543fbf12bc81690c45cb0ca6255493297a1d922952ee5bbdd5b5087771e2bd87a13bbb8588efe1f586d97a10e1ac48ef5b4fe451a34c937e70b516dc4ddc43d537c4a653f8747eacc75f64f84dc7f9a64e6875234643119e182dbbf30468d9a24e37324084af9f5763b95039649e4081d3d43c90c95a2c36a0eb9669ca8b06c4720a7345be1140fb03ac95cea190ac984975dec607138d091c1f92bbce8b2d226c69e61b043c5a0a17eec7615922bef7dc068abf9dba04067dd9ad839d9505694adceceae320ef3cc92f6726cca5d250502f1c0ffd901adddb4eab0a965a253d4c99c695a0a5def568d49cfd1a3685bb80bb835577530a56894d0f30db48bc4beca12657833435783c6b4d0484f2b26f8c69bc9955830b8facfde87ca3771a03652500227f57d9333bf4fece04a1659c3e832c35e24b07059f20d7928e5e95013b67870c8f7ea94671c69e3c0cdda93c6fd28fa964890d130113c4f771e115ae0263d8a7dd3cd59ab82f9965a36c7480d74312d7fbcdc3a1772a8a72f0c1254cc9ba00d7bd0ded67e2e2e3c41fe5b9248992ce3f52d69a86f05218182d3f90184cab7f313ba984114db776136cf369e090501044c9daf8c131a9f79413e41c0b4a32e1251d94638ba54389035cc4ac2c4ea4363fc212bd797038139576c395525f7c1a9b878680eed45c687c8aaaea3b5c89f94e972f79198c4eca065c00aa2e6e51f5639317853d5d67fffce91edb6265a1efd9649c3e11ca76ecfc37f117cc43922d129a29d10e988eea9de6e40fc5c922d6524170ac23c5ccb687b5f0c0f9012028bc6dc0d6585c73d0be3906fd2eca7797b60c3ad3f96b2a2affe680e4a9ac8c25457062c11f3fa9e448fc1e69bea68c62951b922296f238077165aa99f50f424292069356eba6aa2b5f725c6130e8d3d040a4e9d51f7f535441cdbd195c8e8379c602291c50c86d4bc4c1f6b6b88696c534f9e9005da6da789c7528f5dd0f2984aa05d8a0d73bd6abe224d080c41e8d6fa150c2eb3322fad9a60fc38a928dd2d91c2fd7d38232628acae57ef00af9644a3e5f2ad37ecd5d0e8227f9afde36da36dcff574d3a662d464c76e4ce08d6f149fa21c4ce38463ed6f5d2510cada4f13bb847e0ece7de41c46a0e419c01275fa6c3bffa4559a3f8ae5a9a51a1d929c467c2c2f98bd1accbcce4899f3cb893471c299c95ef35b4d84b7b9c4d995880824df49977c711ec01fe7eec9cce08987ab829b428779bc54939ab9cfc931218dc8d8479cba05e4aae9feb0a2d43be5979a45f2dd46c0b5a841be90c74c7108802294f1d104489cfbe06856d4af3488eb80e33b48a6c096189abb6328fd0de0933bc3bc0a1c627fc15113081382790b2f1c59db9169195b4e184907b08016390c011bc4be5f45ae496dab5210e30a5b53667f496d9b9f595f803cd37bab23cb20a9c76c8173f67a1ef12fbe7b479959eeece5c7378dc4d5eaf3db731bb135e9783b1982f5a7c676a71f23064805eb09ed1ab79ad9e8fafa9ba5fc2e8b4ac1c25044b4f5b639ebb54a2152237c0cb5b156748f6d358869214ef9da89d2980776018c318527fd0566c1f205712fd0bbe1d75214bf867528079c5b603dac8f6aa00d2b4ed5bd9194b9d213cd4141c8427b7cb4fa55a48dacba6d580cd6622a5d0af88a1837efbfcdbc62e4d0385b6576dac1b6a0566262d0691dd2af6c71cf91cc60057a27fd2b9d420495dd55180b45c6d837aac4a4b4a33e230dbeac78e746795e187ba3384772bb979e63bd98ba0b9e854446ff6b8a60cf78a2650af325dfc19aac5d96a6f8df0fc475027c5baab491cbc6952172c4ac426e3bd4a46e7055d7c6d08ec22ea7a008ee2ebb05178188100d9f7754990745bb40a1deadd69595f6eb210087e423fdf104b2e486df6737d805fbf08a2b9862ef8753de4cdcf71b14e37464edf88e61f25d911d69d3c2c92065f9a3f641904ceb6ee2821484cbad6178f3a8678271fe6cad4afc18106c4cf1c609d116091131a2fd83076511e91faab225cae47e35af0f62b4c9f5a42e09da06cbe7daecff10da2d01e812ea8cdee8726213b3d2b67e2d956d7b37cc8a027047a2f18849379777987e02b18964b85565896c8c30da08d366feaadd48ffef809e492f090c5c3a0e44c030b91736ec19c4b5a217eab6854e709c84589dd995d770a359897ae1c47fe8f96df739cf7c275f16c9d643d7b0e1a5983f034fe1c550680b3a8598610cd89584b6882e21d28a389c7741741d66792d34d4b3b5bc7ec50b1bb762784b28f94ee7341cecf42c9d6f33e9813038598088a956f14d5ed10e43ef7e327a2968a9b629103952a45300117a261e1cffc2734382a0bcceef5092e767b13a1c935ddb236f191fe52547fc867d04b258f87a27a8eb2bfe3cfa91d19b208bcc5300364472f95b9c835b21ed891f3aeb827c55dd7829e64e0bee43ac06106a824e861e64943ba7b3c3c4636921811e5ce6ff44f74a8ed4844bb48a882e7abe0dc3ab7efd833c0496cd17178a91031030d778766df72af88ca75ab851d099c8deac514d87c3bbf2329a8bfb8e70e9b3be7eeedcc3b9c99737f344243beddad2ea823f69c577db5e7c74bfe922ed431870ad63a5b7739096d1b89d3c6e8e7f8c14cac4221f785162992e74ffead22b75498c2e406a2bf5b94461cd252f0285034622fbe7b80c44fe51e66015ebb263eb5e854990315095f9f6ccb2a980e43bf8a63b6e33a3c3c6654bf7abb9113bfb7f684c3e0f9066bd87c936c22d64e45e88e3f93d955d0193af801e7a5d156e3cf61e8ecfffd1a004553267e96d0cda0d4369a0e886f335979a755db742cb7dc01c0cee55adc85b9a773a915364889adf5ca82ba23984b34ddcb278218b90b1ceeae397c1297305ce932ad9ceaba2ad0401ed72958b64eb1053dd6eb04d836e10b82487940fd75194b491b6f16c74a570966cda157354347a39ee92d5b9a79995276389674903fc709c8f865115e5fe9516978d53eff389632e4bf49aaec5097423db3882381543da126a35acaed80f2d9dd51f36d5974e29734f29b34181c0166bd0e43c95d45cbebb743ddacf9d28be38e9a7ec2830bb613cd9e34d56569293aa183972a6bcd3f021261df9151103c869f90ca875caba1336783901cb2560159b0016c6552b934da25897afe619efd2656982933808106b07018174e3f3c1ef361db773e4c6694679831e29ca3dbb301834ce6d4d1f42a4af463ce245a0af0227d7c1c95ac60611ae0894963484e7b4b57c9d5680ff30d1424904922b6ddfd0fd4ea8fd9abba60b208ba44a3b1288be51600162f66396dc8938fe58053dfd130972d174d0eae726d252cb38a41b9424f99547363d00d548f1cc8a60033384ccdcdf74baddac3bef59f188c7b3a29a296319692d16d62a7f873faf974a903886505154c41e1bf8a2d0b9f21efab68ead8c1af60e8a3fa642cf25757cf1cf2ee1a32db8071788ee97714dc55b42adcd0f301fb3303e7dd8a2c99ecb480d004fe006cbd91059c124d55865760d0aa7226b1dfaf37f1b275b6455a17adb433ae2b22aecc9d6b403816dc58e1fb0563616b8f5acab03c3202c93ad2c20ffec73ee24cdd802ff3921ca8ebf47e457ac471576416e3b6791a11c62f659f61711bce0941502d32ff0d741211fd1ca45e472417a30b848f341332fba21cc02edbe467ce92ebb142c0182290fe5aebb030eee4ac3cf1c759148df6afa8a147bd79be701ca45c9339b7460c06cd3ea136f97403c12e2801512e90a020252e1518aa73b708c9190294a181d40d805854e1e9eb83735daf62cf915788c5313fd849094a02d4532d3a36c800a9ee504bd1ba4c36bc651386ac3109e3eb85e7cf4ce58c2951ade425647db4115c88cceab18b2dfff6e4a11c3cc358fbca4db9624fb3855e0037e736764da3cc183b1092f880d22030300b6d35afb6619393df9f8be098e1adbdb5480963234771918ac70ee52925570404e5306324044b28a713560a37ec7c0ecb32628ecdc809b3c2cf279e63aee920c8b73a60ed72161239d8dc6526bd9aeb4e1b0342e9d9df84d4bfbba94f68d4a326147c926005522cb1b34c2210730d58490de128d9b6057d27309a58ff01f308f47b927e81f10564d2d41b2cb02a8105f0d59dbae86e33811aa3dc5994ed06d838e9d94ad86224b7e810be2948c4f75eda32ca72d319217135d0f965aa8cca688a48c28ff5cd83c2a93507be2b7cf9f49f8940fba268e6b102a6050ec1e40e923c7e07a8e86d0ca54864af59af82e41d0469b84412517ef30f865f82cede49b95c2556dbf10f707e80cc42946aefe1a1826bc0fea3803e80ea318eb9d4ba567812963a11c3acf437b6aa4402e339136503059f9da027e26dd3268c8a941e130b7a009f36274a0747089cc7b3837748346a563c49e88ae4b0b363916d2b457e8f66e9e201b27cf8f2614c2ee88989a9c5c0cf264f7a6f663ee23d10af694ef40688b4526ddeb01674569a6830c60574a826e18b318accf052226b55bccaaf97f4713454efe5cf335e96e348cf05016c1cdf151f2ede23a2b9373c252ea1d94dad157f27e3a960a95144f11ee985bdc38e81e863ef15655b462d79c41e8d6406e4c31ced791e225c2f6b828bd61cfb4108e7a2c3838846284ed6aec879221c8c1de2f01c7334e229321c9119c54f90f0eaedcc6aabcaacb71d99e42f583b325f214f4f335a56150528a4cdb63e3f86494ae8c0ecbe3823ab4ea6e61a849e2fc22ce7abdc727d7423e56ea37982e82d03fa482993afd7d4e84fea21572654f4a04bdf44b83685486fe4438192527c49575243c8e4a271724868fc6e78a907be3ced294299323a8e85b00e5d9b3cc34fb60131cde12913b76814d278bc790cfd2d7af9d129ce9c71d285556781b01dc869afc7662fece00fd1aaf6887e5401546acc6c2e7cdd1eeca5543187c80475b950541f4566b9203d3e70e8f65cebc6de05b9fad8c679e355e65b24c978b1e415aaa50e74017056bde602ae463405ef017c98927bc0ea9963926bec0ebeb5740056275f820e9f039ea3e0ab8d93c510f20c919d5795ee7e040a3da355f179e277f01d8206f78f0ba2b01ff61114b6a8eaa4bfb78288479de3d60ce1acfaf06d9ca30ff99a02da5919175d42c4b00e1277a7da043aafdf231076bf88f56e0f8523c61370fc752848c514822dbe46397847e3bc889d5ca0725ec6336070bd396d2558ee88c48fb85deab6c31767ef76b5b2b96c6dc17bc7f7e87fd2916144957da36e1c7b79c142af2bd07b53ebb3931e66ed4372911c6dd10e87b8a3514bcb04920df5d69db9a262f4f3be6ef06c010902ddc24e922e6f16e3175fe7c2c11bb32b38fe8f8e2a66e6a311e593b1a1013a6af94757fc2daf6e2534c3eb4114685107e11f7510f5986a5095a605e908cb319733f2323585ae3743fda7583b692379a275b9223ad0b8a2246d72e31c337d621256761ea68283a198d2fde9d58746bda697b3d7ce8c09dbf11ca83f77f2ba66f7a3eb1740d28777dad1330a279c805b4df5187b953e1180856930a760e5b026731272950c1f3628250f459fc295a69a664dfdbb699865218c0fc817dd2373debe6730f539d4e3b045ea907774b71e15d062129aca8d6011b12ffbf4ca3ecfed836037cf7bd0b55a9cb1bea5421d497be5a7222d992cbc4372b0b701b9c9750ac4f2ca4d5517722340a74337117afda1241ba760ea0c97f547fc07a29b235fc62d11e2727aede2fdd7b5121c4a2d43f13bfcae8ad2e3ca718e6c89c9807eba3013d1f94444eed820a52f530b75a71871dea862413a874e153c48fc1e99c0ff2aa1d463acfc9c2f19d70fd60d0f964f732cdf16a2917bec27d67a195bff9039f825834f4663f87427059bba2a81f656cfa692549e30330af31896b31d752e387958dc5f0c6befc665c94f69211eb33e5e878de96d5950f30981212e84cccf0df376bb9e5959ab332ecd8a549f019b51dc946a6c692db92c1ed4f6f59dfa0a95a1c3eee808258c9a370b940d1509b8fb490c8717f3abf3e2327c10bec8b33da0bed31458c8a8919db0be2b7628380272388a3e4961d52dd6daeeceb50e5ab49f79d401129fcd51735ace8ef3712a30f3a19a602ee00c53bf558488e0dfc84ca3d67437c516ca60dd5f64fc957cf4120efa6320c09e669cdcde41ada747e33e5cb00eb3bb602cdee9cdd735d64b61f1a16ffd49533e80093aa169e64b9733213906d70dc97cb0f435fc78cf5dd71413125e9f05c85312ac2ff33361b65675e3c5f5da1112dccbdc682880a43b2eb1ea5d8730ac208dc74f1745b1fe72944a88554617c123ddd8e25aa123f8e65e0bc16f53fc330edc1dd5a01f7793fc5601873bcb6a92b7e01c832ac4fafc3255b36a02a664679b90eddcddb9918586fb70b17314324dbe23ad371e754d8d935c3bbad892da3101e5a62c51ca5bd493861ad6da8f13956f4bbf424cc0ed0b1b3e7581d58a358e8281c4f1e28502fe5c1af35ce6525fbed66002e77dd342f30ea7b2343b75b117f9d6d4c0cbc110b7cceafa3cb90edc12105b8e023605938feb2813bdcb7c736c8bc3127ebc0de5ebe2bdf30f779736a5a4742bf411c9a1db1e0941969b86ee9b7d2491ab3692721052cfb16644bd81214e6b465d60253867594717509a5eb4a5bbcb8a2898ee3258dd7ba33d52121bf43e59a0d35d22936196cc87b80d1377e8c4d02b2e25b008b75a16ad1cc1bdd24d06cdeae2b3efc76b99e521bbf35398b2e21293ced4e8e969246fd20eaf330b0a8ce2988ef38ef80ef4bb6b7e6adc66754e1b285500999db0b0b64d1897ab707c9fb89900204e8c7e226059cd4b99cbbbc020770c658a2aeb3a44d22bc8b9ca37fe146602969c920f0b78e868b2c94dda81a1cf51c2dfae09cb67f4f59aceeaaa0959ac4be298a1c30453414effdf7c4895fab5caa1fc3b50481bba2156e3c4642dcc3a1056f778a20c998cd591ab57122b479ae389be45773e751278921b0c7a03847c0caedb9cba9a9b6297b45d510a3eec3699c6408e01bc262b26064006117e49c0f58def19f1e188c7873c53794e8d7cba6777961623dcab408f867913a8922cb26eaf57164a331146c3ce0bac416147a7513eed2eae34a4b1b89cace63d80fda90d5b3f284bd815f413cd25e28dee664af2d4a5cac71b7a7da49bfb04c253e8513faab650a1a58b1da293a9e897fd17a47bcbeb27db8c47ea902a183aae8369b54f03e9fdf256beccc0b6cba865ee98a0492254372aea82ab2221eea99315126cf4a7ccde232f082138acd0904eede0da47744098aef5087f58a5425d282da84aa3d90ed42545d11e04deb04418e1d4ceb933a34391fd670ef0c4ac8e192474b8a1874065f2b69ac49e8a4e51bbee100a3de1042dc68e1d6f7acffab1f6230c00ae7b255aab618880d1723361dd06598192d3dcfc46159b534847bc26a24688d30be649f786194a4bc8e425645a391ed6ea89d6e30469d984d62d85e29d2e8d5a4e3ef868f19db23eeb1c678dc1d7899d5d3669c7654c773348629d3817c3dade0e83b45aad581b092bbd62d1af6823738671a88446fec433fd51cf27c5dc89d2b063a4d399675e44856d76ee420c449b8587eb36364c02883a41176805bbc39c4e519e001f59a03f922df212a7550e2dd89a3b6d726679230f47d71b14f5b8b381d8cd36eddf3cda3418bf63985de4bbd896a6cfe27865a2002961353c74884d9c4be605e615759252879e3ba4583dbc00f643314fd3c07263373aa5c5429a1da3d3c5e0e779bd53dae9fa0de2002b1665a45d025035858ff6ea8218db969b6f560a833b42c36ec262397da4874919b4f4e395430aa28eedadf89659ed3e9761d0ee88010d7f626755a9d4e20cda396c6e1561663866b149415466514dd2a745824f6d8cab0b93869becc77cdeeb4ed8e51cf9d381edd83ac9ec7799f97f795acd7fc22a75ea6cc05ee46bc1cc6a39107be14725f65d172ebd6ab6963322117014e1edd882f5dce6f712c1e19dad33d791301148b90b91eaa0974c2a33ebe81ea38edbb259cefc228e8984fbfaadaef2368e7de99e35203fd36bf0ad0f75459d36cfe567b689d445bf4f152c75f1cf05b08b1c366b5b6e4e2297d88fd0f733dd030e2e0e31a30e821ca757d931528ffea8b389bff0f4a2f08d895422432099b71a61c42da13b5fcfb4fbceb3f940d907c835118b098ec265650db5f72965172672572da07254ed35983b01406deb4eb085231dcdfc90532b337e27f8ad4533e897177163fa341754b14925fd85370e10f009109eea04c1be8a4b23dda5f3e04121eb01dfd084285a569f8ea1222adee759bb0b02b09bffd8cec14436ea6400651d268f3ddc0ae7a8da36812900d8c9a16cc38c74faecc00ea4d04bcca9585099cbd663aee4f43bf37bdee31be7425517142b55a02b6fdca888e8b744d2c986bbdb426df3e33a42bcb3d73a056ed6e22cae8beb1b44153c0d4024038a57f97fbcd30c97ac01460f1e62f06e0803ad2a9e2ddd5646846697f252dc3ea73443b7a29ad0fd9c5814d30d9093827e8d9cc77563501f92631860157a197dc10d1e882067480a2eabd7c0eb79d5dad9cd8b2e281e2d55b929c8bcecbd16a78bcaacb0c2427de57469dbafea49ee20d4b529bc233ece2212efb76e5fc8b390cb487c46ef0204becc0bfd137b921a8619e9e2708dbd1b639f25b3da5b459356e8163ef550185d04c85f56a484977e39ed6ebd5de52a1dd2568acdbf2f9622915bb58cfe554c8500cc899b67dc916145acddebbf0dbb0b28d2eed199b9dea1ae89a7f2d1ec2a22b5f3facc8fb5eb81b6edfcb4c56e006ac743a31aacdfa9226005486188f45cffc5f9ba0d8fcb2716f51d130bc7d58109b7532d1f29afa0eb121d3f66fb713b901a59bcbc9ce7d0ccc520757613afa0ad043fdab712d09de8890edc0b43ca877b74400f08f0bdbf46521b84cfa52c644540a8a456484551e57422eda13c20e8847ab16da37bf52d49a71dcbe98c9bf6de9c085ac9b0e757a7c0510c4a956a6857b27237fdb7b68b96a26ca7ba9f8ae4197f0dabf41b6d4a3bcbd2178fd375ba250e216d703bef9b2225a7de448a87d6733bb2544c2b13ac4f64b0657ac69877c1e99ae01506aabfb90e830a02856e0145d94e55942110507e66faec8b8e77d5d7fcef048c87170f1d0267b889c7e085069214cffbf162c368c3651160b7e2298ace8cd6125f863a1bd28483136916e7cd36df4f22b1c952fef94317d6203acb6b055921b4cad80a04b4b39aab73de349f2e343ff0fe3ce6ea7d5d34bd5f87abcb45f15788cfbf5f957c38fd5e9d53d07cc48d0050f68c87c7ad62be9dccc4a7217370e32f1cb011d8dc7e7e0708fa1d80bc1b8bed3c4258e6d7629f1f707c16602ebf490da0bafd276b4d4d293fe3da73a247da58eb765c06bea946c7f3062835af06fab6e3cb853a1a724862bbc1b3e3e8385c413a71ea79d565e57cf85c43960fd7b5e80ab787fcf90b87372e5d62b44289b16e9ddc3981ead2b504b0eede61d888ad63b474273ae84b435557ffb7bd8e8291ef8b5674e719795c2c165f7d5e0c8e0f448a3eec77d2b4e1af0d281477fb4b7ea40faa1abda0fc9d4ff2033956ace05ff23dbfdcbd2839459fdabfa65b813ccadf80d04cd41f02fdec3ad058d2e0b3a303edcdf09c06f5510d4fe4ab615768ce84593fe0c9bb50efd45079bd9f0f148eb407ed208fdb96c5d7efa83928200cc8d0186515475af7cac5f2432dc9e42586eb34c29a61f8be6f4e957247e7d5d066f7c9019df3fd1386b300f54684f04f398431dbf532cb2cf7572c46161af3ff749880c047b207dc637ad2f8ecfdde8655adb922d0ff6362ad9598885d6bf9383a146b7b0659a12e1fc2789077015bd9e6b06dee2b64d4e3de5241ef990d23d45113602cdee3dcd247aa12e707c3ccf2377618317e54793546dac4938d56d40d57040b6e9b97d033860d010a1e6e26888fc6ddde77ab90ea14592b5fe7bce8bc00333a2427416d1981294b448185b19fd6c25355b5da16ebb4d02c3137b642c06f4ac2cbf473f2e0cc01448ab54477378e8955097f922ad30e019ac68dce94b292653ed98c78d9b4f1cf4b8431807c383f618555ca30e6782c84792354b584d188a269f0f993072b3e28a85e99a94335cc3a22540c85737be5a64e4e37f6ea09512027026a6a0aecb7b7c8a8a60df33ccc8dedec59e37d0b0beda473399431ce44179f1f2c1a3a04c4b7647f319499997b7bd3ffe3dd7dc7d9aa8241fc0a5b9dc48aa17ad7636e3647e2cb1b0e88831af7628b8f801bc8542bb4f1d7d55bd2efc6311ba22f2d4ed698272f6e480d510de988af7d41cc9cc2638926c4493eb97ad00909f68019b4ca84accfbfe3da88e6e497752ca73f884e788929d2aa8eeb84f564e14b82840ae9aa31634426fbe0272993523d87def0e84ce78bfddb93c10b0fa3c711999c7e4554489081840a2c62d9ac6303a7042d19c789de08ecc177d3e7cfcb72383a6dde326f3ea0c0c630689ee92ae330290d804497476f247a1d814958189e0e64be4a24d39731edd5526f4152bf824645b346193d13b93326096031a1d4b017b748a84c4fd9a69e1a112e2bfc0fb8096e95b4683b4ab170aeae100da16c1771685cef83aab16e146314d0336789a4360a5b48caafa334c03d7d8f7aa87c2997f05bbc89fdecc15ddc72a234cceef4907afa47d8778e7eceea02f5391b0406d0da1e1e01c4f3734e7e2fc9460aca5d74f80231d085617c5532da837739edc466179e83e5d0c002809de60445b0baee519f5c24a9b432fc2cc3e0b973937cdd212201d7a183bfc18f1bc67d6d5d17df556cbb0fb6861aeca3aee47008787690b49ea0dbe8002794f3b1094bb3ef49770ed30bccff559b203f8004d6c0c17b0463e6cec3993308dbba86b3a0d3f372f9d64a82ec43d80a64c9d4ca62cd45cfa993078a8ce4377045b230efe08dc56e4d0cbb368d1cc949830ea4588cc70a515177f971e0651e3c9122721c8b45c3523689cefd596ede9ef96a9fa2c2587eef3f5736183dd54c9af715ed9670a5ae52648d9ff6fe3f967048deaf9ae753cf833505bf75a801b1295196497af7f0fb8279bf24bf2c7dd7384ec07c046e92cfc36ea977fab76e0e31af4e94fd0857539119d803c972539a9ff31f50d612ab05f53ee3f906a11acb6e60d317deae612c093dcf25a3f02a422e2c290d19151a23cfde1e4b81f641e862c6ed4b15f3e43311d5cfe06f602938e2f46ad6b777bba3c779faea3d3e6e848775447f705776505459caa375ce1bfaa8cb18bc3fbde60ed201ef1a3bcfd5f3a43389f6dbe4d21201cd36565687b58fc34b32dae63937a74eecdd992280e64121740fff2af329c0c2e1f3b6fe0e1ca57f702693cd648a97156de10cada7503f357b61c968885901bd28eb86b081b77fa06db3a4889f60cc5a70c999fbf65b8b83b6601c0bbe3396d066f64486a73940a80c6866b18fee7f1df150404e844feb81d97e049232a5924fda17dddc80bfc8419e013709d000d6d7e883d274e183b5bb387ad8d3c35b95f1c92ab88981721b293c1378cecdb66b9d48748a406536f3079d5cb18e8f235cfac76a24e343f887dbe86c822807ace21248a18249b3fef24f18f512e8305f0c1a3bbc99fa8fc700b3b8fe9506ffc297c5ac1895bc16f223792a65ac2f967c33442043be3e45b90d3554c9d1c869ad9b1803999cb4c5e8909e2c95bd470bf44386e30563b3a717d8479da5d58978ca69ab6b2e1a3b571cbc742e56a7537a362903f0c84084cccf21520c3ec2c0d9c0753cfea016949590c1b9d5905636bb8de491165a4a6513a9a8d46901e8891ab0cb4768112ff3924533ad668da529db82c6e8b9b9edc9680ea0a0a4e0aaacb061f6032a65271ec0c8809c2a3f079cf28591676b7fc0cd356d288506694e4bf23af36b3f7af56235760aa0c472cf29c7fcee13d8625f863abbcc19f5d62a380bb1ca5c1e4bb60cff0851ec70ae7489fd2aba2a7bf35e75a51e22431506b1435935d9d2ec66a501905a55fed91f565a57ea493a67248a18a42a82a863c13c073be2648021cf6320ba5372acd7a2b1ad3c50c066071771f567b4941b2c5a083b898d16cf14a30cab65c44cfed3109c39fd631645c12c7b0b910e429ca208c6d0ad62db2f154fe5c305dca40ed10b86fa4a027f79260836d5ff40865ece59a47a1b271b3d31653a507f994c22b98776923c7f7b3cfcfd0c1bce62a8426c5a5947e7045e03377882b46fa1900003ea83623a1977e967a620cde641a44d8599946b9b7295684f2eaeb999dd86f768b197e7259e5fec96b0537c33f76918afee021f745c7e40fdf8c00bbf327c818aec16635e7bdc74c940a18ddf5eba21e2432f1b2053aca67f7270d3253dbd3154d36a695acf01cfcc4ccbf8e20e4480656fad058d3acef84893da18304a06843d0cf67407fa26e3e7b0497ea9d13dad8c39e00e97f2a6b08830309645b2e1514a37e3cb1456219b92283731d90cafcc76f38d0dc0bb8a20285a36634a398bee59f7ee0f24d0b7bb59d7e45c501d5d8d087ce062c9d53415023230141d2e50fbe5b15429bb671028dc5e44b04110e32b513bf6d21fe709e156861644d6b690b50cb3b9cc0c9cea2d952ae83bb8bfa5e25a564a925cd9370f982b81a95ea1faa664724ddf5b2a10b12baae6a9e607db94ef14d8dabf09bd25dda02d8f70f9695d5a9d425ba86e0c07302ac1a898a33482720f469a361d0d53f94b38126046de1ffa0468c5f75785fd5d2205fbe44fd03d676269bf45c60950466008b7b5509d2128b6326ab59822c6fcb14dc0eeed561fbd874105e3a15d99c19c60b6483f3e17bfc5f49c76df76f44312a6667f97336a274b94ba5413439641ad4a51d03ffff8b9d2e6e5f6a87eab334ac39ff2f93d5aec0438d738fd2494910dea42ac86d8108a1d9a4c17c09cb38e9a43b7f2d81a5550d6497d98f30085c34d6da797a27715e2bf1376ec88b75d77d4505cdf63bdc778769c3cabb1241f0d14e1d2ad03e47c9ac58a29680d5cf18bb1cb39e6e84f54d53c534a91e6710104e83c8e32aec7a36e1dc315fc1d6a211ec7bc05b102f00f1e09093e0f867279ac681d942a7328c8777f78da8087ff8c554ee7ab2cad3a9e4723c2a7980393c56763654e6cc2f16f3a4ee9316da8f89a3d3be684d5932bd2aca276c1e75bbcbf45495e0b2b804e2f401ce208e04ffb9e8c02977ea7c8891d39328a911fe7fe275488583409f3cf3dc7d61f3ce71c27ecb0c2391a6eada10b586ef62fdc2904a3104ca31c44e001242986753270bc272998a8b202240ba66d6191cf1f6728100e69f614e2368fff58a77d1a809814b7bb395d929b0c0e79d699c84d050c9d64645d4d17f8aba0ecc14b70e4f5138fa90a5c886ba6a480a09e27d1d4e5bf5a7017dabb55d3c866b1241ebb140acc2fa34bad6741e5f2d56547b50652f82a00353133ca212a226646bb101e19fe13034c8c9c49ea8e6f69382d1b189b2e4f44573101775c87d8162a83f469e2f89c775c9d453ecee8462d217340e52b8d91eb26506be5c4cc33427e9a171c1fce97a81a05354b624eba5ddf1dd82e63df02a47113a95406f255058648796bcf8545852ba3bd2b8c2223c14ab5577f3db246df63520c9c7a5965db840bac925f4a1cc0c4e26b36691c1151c23cc336bf6ef6befe89b6cc4588e3615016070ba1eb623ec36d86186c15bbab76745933d5fa518309273aa6f91ea085ccca37b30e3540d4a8d59551cb4994d168ab4b4ff39f45cf6f186c8f0037961629039ba116e4a0a670f116f63d935d9892e62024ca8c176d5516b19840a6f1427aa2199ed02ce5514a50546caf52c3a17e0815d733aa865ca639d504160151e2319b0c089fd90225256e9896db769a38fda1e70e5d03518515a0ea62d2e3dab44990326e97c932308b558cb346bfaf11a1fa4fbd1427e2a0b80c1bb55df25a64dfa14fb35f8bc619c05bc8d4bc26ae001d2c7a979d29a22cab54b4fa45601e0dffb2abd33db10e11b0563e45c1738cc476cf919b0e71237b208a4f5fbb470d2c4efc46e8d6d835c825f98f9fb8b4a52979be2e6d4a8222a63191ec2fdaf2bc82e1c40a7a2ed45409710fb1cff0e105369cc45ec8da3cc560a43929817d2318677601c1df1f357996d84cb2bf86e1e2aafffd8af0f6d6782004df50ac7816b622eba8aabeb4fe84c5c20ed224e714ccf16a3eb66a4751c86b0a47afb1d21a8da7b2ee99c9c164844f864615f544473ef6e447e00dc02074cae6f1fb85e917bc1550b1d6923a863159c4481b11dcde8b7e8b46049f8ba06585d2f1d3e359e23e423628d436b724a219ac6b7740cf68c8bcc68486bb6600a17ada64b40b77400747c72731b21b507e541d4a5ba1f3b568ccb83bf22c08b574f44e3c5c8b5511747484c6e9c78ac8333f40bc8b8d9cc5e6e6f7b6d321ff6dd8df1fe260512d2317f4c60f7e53dda03ea34e853d35d11fa790685c43579e5cfcf3d5fffec32944528304a57a7fbb5cb41f4acb45008c820e4810f8e42c8cde08546864ff70dc28525c0132bf0e5e90802d52d1c6f3650970a2dc8ab215d9b21b4dfcf365eefef1860d49311ab79a32c594523da38bc4bcf74ec3dc84c2b0ec64b99c844a8bf3e74905058fe3bce47662324f6554beb7fd972339579e9e486d41bda46e9f8795dde061c33f27629cedf19453e93c3f0d47103159ee3265c97009c2d352774b7d64b08b4222c75cd98c23c1f0375dbc8abadb85db45e90b44170d9b9013788e24da7f5679781dff25580dcc270f3f626396f4a9189ac0c44228518bf7ea5163ee94d64f19fd3c0079dcf1b4a9cf8937bf9bfa045ec58bb19e797223b2b0ebcd0de8a13db8baf85c7ac381a3f4601788091cc02d3efbdc368703bd4699e8321d9afc856cb726cfb0eb772bdce207c670ee33e042a47495e0ac5d50a756a4c4f08a129d3b5c8a3436434282f56cd709d538f5476400fbfaff7aa3dafb88a701adbb8035a1ea708a20fb91ce50bcd3eec491f525a208fc3ae228bea8101d6692acc59fae5a5b8107b280f5e478d9b3513a20917fa55cf98eded6f87ba318f9bf85a1c79b876e4853f137d558df1cd1c22b49d74c1b2f2f914ebee663b6fd81b99cff5f75fb1edfb3e4d13f22ed908eb05a452ef843d4ed1e3d5a21fdb03834180a7012d5562675d0969f6443c89a82fdb0a3f04790590a64f80e2f1d3346c0e61a2c2e5ed18405ca9b47fe97873a3b711a7f3df9f353200c360473efc44f0cedbc39e33e355c17f0a251db80f1d2b1c8e33bb6c82bf77fe08cdcb1319c61613d6207cad9ef33c5a86d1c49bc457b23a7cb99504de500aafc96c5ec763975cbbf71f22d70aa91ad9a380a7adb09af91c130431caca822e61b378327127ae608342aebf332ddf46dd7924e8120de5549302a88b28ba5c7018435ae2301fa26a337c2be264bcb4c8e1b52a13f6781d1af4a1a7479f72735051a9f4ef6bf4dcc15eef415f54ae51c7b90ac407e41246c2f397f2bbe145a5bbcc583ea7ede083133c58bb3aff714f9bf87f61a8e12cdda3fc332842152bb27989a861d2cf2521b4fde1cd99ab8ccad8d174d820af65d891ed20d7be929426954b34822375bd3fba301df18c20de448b941c905ce3f82455912aa9e1bf22d312c8042ef4b70a6e838a39563c7be9100a9f0d4e2d1b36743fe095958a8797a8fd7cc16c3c70e495cdbdf7148855606a6093f4cc2ff9eb01d794a4fa18be3b2e89c8abbc03b6155240df7da90e1c07241677b93cf99fd6555158d0a141e55eeb069f10e5d59df958e068c900b578b7c1548d006dfd7fd41338d552953fef4251d16315dbb263d94543238866a7d40914f4c3f1f6042ca873a12311bf085af687f3aed3e7d424dfc326c7de03eb4c0a1d6b940af7b6d16f98ff20c519f153566fd6c861bddc2e6f1623c4388a8a44540e5c8a1d967ebddc48b2043b05bd0e36febb3d11d5888788c309e0342a0819074f5334a173900643d981f88f94e398aba5baed4a04f40aad0f9868586101f029f877c0579dee1ae3144736adc8a6f234367927a0d204bebe635d6a1f9e9d52fe22186ad3b76e630bc25c20f3b77c9751c15f0c3814d89ab4bccf251aacb9139f593012adc33051001627850343cd59faf8f1fbf9e85493819ab00cac570ad0c2f96ebbc2c2f4425f8cfe557e5b79ff7d009e3f1ab33c85ff339df81000a069a6d8577400cff24e9a9e1bb5b16f766c35dd29b696170e6275009c5b5aa909854eb0b4710b6143a042e97739489e85a8b12e095099f8de4b8d4d313bd9446c9de7395c061667ee38db84893c42bd069ff0daf9fa60d0a3354470f134690de3c4ed6716560ccb1a54bfc5dbc22704382a71cc780931f003b3ff0f831ab90cae3df53aab74bcdc34a81e096cc77b999f26a89c9bcfae34bec3bcf82f106b3800816d71a505dddf4fcd292ce1f1930cc4628782126d1d978f021e8938c272eac58bc14bec433599b08f31b822c1e861c9164f55a542eb3f72dec663804d8b72d319d996d1dbc60d5adf1fa17c3b94d66e5c7e785d333dc50b67f140d80b03f09e3b2ae5510d886d921095d452303c10dde3ced1acf1caf4ffd1abdbf73988c9ef02f763668be456bf264c4baa31f71b3e90af68ef48f011d0c837b8a76a8d530b7fe7e8d976bd0e792c0f4c8aa4ddb9416f784ebbcdac29032d7abe53f518dc3d91ee5f7902b34279e024ba217d2bc50a221b80d688e9ba46f687baa3af81014982febf10c8d74125c1fe9f08e69ba092c0ffba7ff15b8632747b2be242adb5564922241399773c582e4d0a4b6b6e45ac9e1a6eef35ec242e6eeb61c21cdb5afd57db25b4fedc284cc4b7cbdba672edaec3385233c5562531f1d0603b9ee6f3cc41c63258cf82b66530852b091d7c0db9a87cc9aba6566216a25d86cffda409959403c3847a46d8a362edd027791e638dcb029cd7a8c215fe37947096aef7c4ce2027d6b38c18a46d1d35bb6ba7bc5e44139ea3ebacf8fe165751acd56a2e9eefa6cf91801175009326a425ef5f1926a74f5f21d0aec18da731af88468688b44c53940ef4002489942b3f749188202aa001134d29d036c12a73c4b55f1e510a11338231006af54c30e7e8b25bc6a79a10f440fd33653bbc088731341793cbf5e37613898ebef9954720a64bffaf80d4345459973fa17465ffdac8242735076e4d32f54df4bd8ff5a5185b2bfe816005d0128e7d56df331472a28b57b7d7a4ea34e8c7bcd1f8c6c0bc10e8cf55daf18f6057bf72a526f8b0b7ea44a379ab1f73d84c0d77c89f1f204bc522bc8d270e33564989d10b328548ac300134417592b43f7316dabf67095dc58cd04ee0b130c5a77fc883e9e61f589607041dba73b95f12258aaef57f2214f4f24b10cbc7b4014685039fdf0e9981f0c55a9be17fe0f38600b6dc10c43f1aabbcef496371d26c4cfee742f691c64f623d52b6ccff4c1624269ce90217ced070910fd622b99f6dc10c8f3a97bf48f7ba644fb75fd776fe35a6b443b92f38c54092333e97024574d2117b328db0081ea86edf7728665e7a99eafb8ac3b9207e6a5f3eeffbc0324e11e7dabec72c562f5591063759933adf605ec38e0423a29a0ecb3385fd16254784698c592f97dbb8c4149204a7ac2fe01cb2dcd4a9861ce26e08abc687b3198131340a5e5ced197b3fdf00435be8340761348755d163e3681ef677ce3a9294079a5741243b97d36589fc68ab0f8aa9d003d48f5f2004c3978bac354d0cd0d54128c9d5c058f27bc42b061f5f524876bce06560b1278b2637ec19074f7862fbcb7d1e36ba69a64c72468581a25828d147e1d3b462181a8e4f1bbed503a25776f75ffe3be1956d71d33e8fb6c4f35874fbf1fca64217e291b175feade3d73c7bd514b07ca01d7d6142247ac50e0ac2a5967eae5106fc41bd928b5ea5ce204cdf35048966796229aaa27c14f24ce734c240ebb57fb52abb78d7ab41a22078c00004ca3f08b780cce231cf247edd0d5697e4146207d435c618531c709f507558370e1601c551fec6db80babfecf4c05c4e2c80cf69dab7b2fbc74a3f6ae0eb04eaff9f1f91de33e597c0be454b3684b3ef7dbdac4d2eda8b27f024fc768bbf398f7093a39ff2db919ef43bff0bf53f8d8e4c421e702f3a00a37869b3fb3f4dff397c7900a47edcafad53432f3415176eb7a0befc1cec5bea220ad87ee866e0390a1b64cb6cdd63829c88bf5eed58ff130332b37aadc9158ebf166e5cd80c2c3e2ab79060a7fa2db7eb10b3defafafaab70047014952a48ef508fd47ef779ee0a5f915644bc8ac667f640cd276e5e7a6598b662c86d2d620b78f0d5e28b0992c930a443121c7a2ce086308d2c2191a0cafd2148b11e47bfac034bc0551e1c5bff1611cb7e2b8fd6d91f8c17012e3af4065a5f99b7411ef10557cbfb0a2d1878820ed1c41b1f15498f760444ca51fb07477033e543f33893501f50c2c7ed36cd0f510b9732fa40748a9cef09671db96ee70f7af720db35501581518d98e967aed2e03c3b207928d1e78f09e794f45b3ce62dcc8a1386226f39d7da845f4cfc9114825c5f8d84c056f55d21a1db5f13fe1395dac2c3e85bc9e2f1e3c284a2ac61879705d8d65b5cddf712bff13f4720bc02c08539571ae3872615c2f5915fe241238e1022a3f8ee03c9b120f11649915edc36a371fe872e01e89c31ec3bd8325527153ddf5352a9a774dc22dfb5591fbcb83aa4386e1eff844e915c5d7419aec98575142ebc280fe3d1526a1a7cd25d8571727d17872e888e823d79c21504ad0ee41da990d50a49f1d46df83e8af07d064b6a133242d0f77e02b849a60f437accea3667c6d85d53cf402779045487ae2ba585d11be5bf77cab34dd42294af6f2eb15a459601e650bbb6e830fde95d6b322c53c0c6d56062b34454ff93bca5a8998696d94a85cd6c779eb9d16d028f59c29fcd5d643afbd5698a0c671f658386e50005fc93acd44febc1baac481e5b0082da64d3aa933ca4612acce1be89fe5df192be1f67a85fa31b0275c6ea945c51e82105ff1f1c0c4317d53b9f659dd8435f3b7de677fdebcb044e19fcb058872761026428cac7f94139e8e373e881a3ced8290d7afd023398e77ffdc3232c6c56ded4b29108be2a0b90c3372ae3e39d7826daab3fb4e71bdb732d2e8cb62f927d440a8a229c84f7941f1d67f75d693cdf167d1a2df402cd0c940667d024d297c5e69118d037a1aeb17a5cbe138bbaa48f61f49fda55cf4d2052bc22cfce7e50b03a61d1bd57e30abce3ff70f609cbe5c43226fe9f4afdeb9833e95eedc18e9e7c421a30fa7ce6d8a8e8069da343fa03b6b1ac3f1eb852b2c3e9689e9154d3b2195ea0d3f83b8ffb17e212e367b599471ed79258c70b0f5ac3cd3ffb29f78fbe8fbec7b297e34dc6e583a8b098427f88c255d6d6eb015250ef37cd313bb95fc7cad3f8f36b551b26ff5c7ba49295e3c1e8691e714270a47d6cd1f17b547a1296ef490026be36f42be766ec7393bb8732f0bbd53a36b2d0d085718fa0698c2b1e114872dea3aedffdd61bbf8a7a2149ee7263a6b8bdb5d2bb73fdb450f284c030ff8d47ca862343027d4205af147070d41d8fae4b535c5b056f75750d342f50125ce05b12fcebf0fdfef56b68901cf107f6f9eb33ec4df5b10afb3e532ba1cb5f2baf9f50f9bf41e4afeb02d487c1807e87b0bfa4a2f64b9bbd34b288664ab76a29fd1ff40e53068d5265e6838925dcecda1466eb33bef3b5cdcb30b31c84137d044877669be7fe092aff7111f4efca7befd4f4e3ca85d4e876a185f09b826fc8965bdfcabe486e4f8d9a1aaf4231600a8c8e1720286ad5368d41dda4eee00b7939bf1456e3f4c40261e01d2318ef7a3802da9644fec7368d5b274f60f59218e3024c6446d103c2f173b23a70cec4406d957b6778c451cbfe98d43d395fd391bd7dd56651d075d687ab65be50ddf1733ed1c771b25e870dd84b23d29e0fc7839791daf0d3d300598e630ef03b8ec2aec6e320587193dc634dfcdc1e42caa5b7ccffa0371e9e7b6a5f4af500f2de8324b2f60cb6a28c2351bf7cd7bcf4f842561da72f385e2db85f097d6c4996908d0b5c9b133940ed41941f60f06af4f54ee44585b17cce9bbf78878e9f47e43e7161bed0246f593053f2597bef71c271dfe365c839df95d855d067085e289bc864eb2cbde759654d68ce3ae98b7757246b0aae623cdc6aa2f227a4919e8d2fee9517aaf33f2b4c5f8428d9f4e351b9834c9d484a2a993bec6fff3d1ebaeff03fe4530adb891f1f191352eb59af1b079a563321a5cf7508ea6692b62ccc8d60a640e8b9ccd07b45375ef221b8392ad6ee8237b6b3de1bcc2bd8d08c55809d27bdcc0bb6c030312453dfb17f2ee4dd391d0093095f8b2b654f1ad554a39f654a4cfd7387b8419bb68f43c409e35d1d6d023875420ae5eb9613e769b30cc6bcbbd0e1b581db153cc62be18f11a712f901b154f23e48c4f858589125fc4962af043f5e9c4bc40f8a8592fb0131578a1f214625e9f3c4b0c4e863a25b9fe0c6a96efdfb0dccc7787748569cc4a18c4f912c2e1833b3f0bfac0f129325f4c962af043f5e9c4ae487c542c9f940315b0a1f290625e973c5a0c47d494c95e027127b25fc71e25c22f403bb32da598125f60b6227b5090099e954ec4ec05d7c1ed3df0aa3e8ee34bac119057bbb1c44990cbd0e71e1c9d4de5756124b5a7fbe993d53b8a9b183ff891a46227f673912df0892cdac36a6aad1f8c1d45c1ee3b8f802bd4a5ed0c8387e5974d1d8bfdff303c83effcadbb3418fb0e378a5132330aa6a7100b97dad054353f804ffaf304448db127a4ed06f71bc9cecaa1ffecd0a11379266521cecf039d73c3bb96df21fc4a1205f7edcaf2612fac906173fdf5bedcd3c37c4a5b4c111ae6b4d891fd372edb9faba2d9563a88fb78ed741014e362b66416342a1bac44a3e0fe5d98a7ce1fe7b42776ff806d1856f33d76776cad7b2e6255cc8141f773c86527cb7c99c3acda39b89dc04e9d9ce1f3438e1d4f6ee6b47827db47f4a592a8e3406712f1495e63e3196aaedf79d5e56d326d89042b803fb1e86d88341c58392f75deb04f09fc0b14067361591e881ace8298242132c4215bcbd9d5dd0e5c473ecea456b77b63ca07b3afa019469a5ecd2f21f78a95f20572e1f96c6de9ded86b30ce6d0034494903c6be81089e1f4bf6d7e0956af442dba5ea6e785f92752e51ed19232691484b809e1af88a9e84cc5ca7c0d7eb52bc273c8acb3b4a10601982cf75a7206f317cd6f8e85b9a0de3957d80041fec4ce573259e3c64793e4e72ec04a843b074604a4d31963911517ecc8d775e12c43f1e53330393a2e6e49846f4ccff3bc01c446ef6c5732edf0e5f2ffefe5a5c1371092c3e82b3449ec383ac6f33204bdb50e65d1b6bfa51551a0796fe8f47685ca22d7a9b00eac0e720e9ae9c12632a2a03a31dc571419b433f1dbb8ed1001ebc73debfcb3d256747a259ae4aefd3b886e85efef4f453be964a45afb75463155541fea1930e90c2c3c9b9501b4692c11946cfec6fedb753556d8653d82aea955bfb9d6108000211e059e99c6f55923ca4a8cc29c27bf4ce55ec386fc8aa32e9410340be858cb36aad530e424531932561db70ad6d0b87183b08e6f0fdac4eec2f3000eed756e945970ce45ccd10214058301668670211c70085bda0f1ca8e595d73e185a189cdb0e768a0f642c33c7c44e8613519323bb7777948600b207258d0bd5f01a346f24990634b720525048f3892e653e6dedf9256a653f0bec3a01d68c561517e368fa4b14542be20c0fb2e34f5e20ed5b9aeb776a4834c6e8b21935812863ec4ebf429661d38a49595d0aa06a030def16444cb9dbc4ba5cb7954dd8b0a3ebdfaa258397264f64c285a589f9270e54973fb079d558b004f337c6a5e8da05f620559ecc4db2ff28a88a29a3554b90a8da88e5275eedd2f849a824d64717bff8662f0b875f002d3acd0a35d655649d06806f5ca7a38ec32f6e54c04eb12144e4a8bb55dfd9125601e8da151ef89bb16204aef4f906c4ca3017ef0759b8fabe81fa0730d8a5eb764c2d4dbb252ecef9832c353225fc361f640f8d83d4c7c0916f5423d29e754dde63e81b17dc176a2a4843a375fdc2490b207fbcb82b3cc4b8e9ec54ed38d5760c0db8ea8a8692f63b6a24286ef45c30fcb287c2fed4942da80a7a8c95db0a0b3cdc5b937cd6d8f23426d2712c2d3d67bce591735e2e47980634872844a1cd594c62e13641dd17cf529ffb854e8dc6ccbaa7f955e4d8e4ea21bd990018209e8168b4552d5357bb06fc6a5fe5186a6823bccc5c4b34fba9301a6c64425886441247e0daa9f04d73c3e477a24529e6faa6f23206d89064e55793c650ad14ee3a101dd04ffc9f69743ca80430acf66c1b2dac996bad6b4b88b0441ec9202e758aec263a6c1265d4dc45eb28123859f1ed103ec880d971cb1561eeb8cbe5f48e2e00921d4f9e9bd5cce91c5e66b970b034404f36ff0529ead63301274388791b9c866e663991f8550c0d43120a2b62e5b343fd8c0df24bc6acaada66cb4b541cc0d92f7f31d120c8a00522f3e657f5e598338a4c5857055a18ec366a3ecdc658d4939c113e8c51725a035342dbb67e32635b015bc99de47f944f7ff2c2aef9423a2fcfd81cfd7aac7feaa7814df402f127f84931073593297d247fe20340e701337b8050f66fd24aacb62977b5cca415e8cd17c74dd46965a535e532d06e4829d9d6469e783aa1fc6789ee4052848927ed2270a0e8045cbd214972a2a5936744e1db9538a1fe189141bf4815b12170ff11a8af103b81fa94e92634074bae14b7087012839f16cfe41b6584ee19343aaa84a38484d2b7304b0f94e46b2a5f4445d8b3a2a6ed128ca1938e5cba1e58a5b71ca6d019bcdef760776f183662ae4923c418c476146faddc46c1436219987a79c9f02ea72d3cd49e86e1c9ab6a49a79944c867e4d5bf67eebfca2f33a10e9e080572312f7948f615bdb49ac58ea534c1951f9b7217cbd06bdd2a14e57bab8a26739869318f25720d78c4e31fd94e26813e4e4f4021271ceb8e76d5c59aa9a6af909c6342dc19a58348c917b9e6d71452e983925683408310738044f2433f2651e613d5cac7955c579da2dba92ca37880c8a9af709c057fa6fe387341eb96a1d19764d0e6d5b4dacb5edac17dac2ff750403da464b288e148e81983474452e9ebe0588d4322f7119600e4fc868820ca7be9451869c54d0c20fe8bd7b842ba150e7d799a40057064e460023d794738598eb3003399e79f91f600ba8d502fddf306ad2c74b7a8e6ce995cf9d96fd0f927b29f6981b6410fb8fe112ec7b1037aea67aea09a9f068bf163c3165bbfde371203c9a064da24752231365ce951cf2cd364931a0445190afa111cfad8a7e07fb0c1d432e4266c0f48cd0ad003a51461d86f764cb3b0864ee98ce1776a6388da639e5d19067cb453f2eeb2985a6f3a5e2890a0ce7d019f50f6021b0f069da97e618b478476201c3b272da360fd527e1a8d9ee96094fa9241f7592f8d389bf5a89aaf132709ff394a938c562f915877dffc21ce04eb9cb908f173baabff5eb57ad2dc9ec017f77012af4d411da88c2d813988fc565c6a40def27897753504800ba658f632b3f9f95573350495838816b4b5f4a6a2b3a51b427b5975462c32cb0700f3bf160509082fa178dcac57101773933b34576b0fe44a7afd85095e7d9b5c438febd081c302ce1bb12b130d4cf792d35c4c090ed7f590168de284abfc0ed9fd5dbbeac14e3e803c9e58163207478fc330e796c7f0cfebfe75e96c3c0782390cff0efdeb77e5bbde1ec5e16d46726061db102e57bd321134648a48b79befc7b0e0e4db9458ba76c93a17c37ce7d1e3bf5f9215bf687f43722a1870a521d1db8c55ba09186560487670d0269efa2d19239439f7056cc2c0011f2bf36480a41060bd0f2a8493b45fb72561d36dcec836b31ad8dd8117e9987662c7d38a0e58f94d5d59effd74beb3292d27608d39a457b44260d2a01c9e0b472421736e9d2de4cb786bd392741f43eed1926ac3a6d3d715f4ac4485046d67a015d131b5123d231f196849876669b0b9547cf0d3cc9d24a31f4d6b8093831ac9532c4f2e540e2de5863f76f2f6e27b0ad7d955fe87b02a87bd673196a34563d7ba44fd9a1a45463728177b357eddea5131aaf841e71c0d4badf439a014912e3dbb597c464aaa8100d20140bfa3e940c9edd9f41f726fc1393fb0d5d505f0995676eeed106b51c9acc30e0bda048531549590eadbd810cdc7116c6cca672b82f42dce9f78e1abe7dffc7eac15ac68db20ef9716cf9caf082a427115271db2afb7bfaa8b82d89035a7830843cad883d0628ad3981a1e60d200c27de3a081cf7d9f29ce9596058bf096ff33896a9cc71bc6cc6719c81a6f7a18a198960697ad4309eef93ef2c6f0db9bbd4bf6445f4c428fe1cf695834860d3712425c508a171379fbca2a0029aa9bb90e639efae7cf13f02caf9f0f81274a7082ba0613d57dd6ed80a728fe601f1a7bd16df138807356090e2f5a38cfc13391f21a7bc071c99216f861d6a06a4c9d4f333bc907df5b9da2466e8ee83a5c89134a60558e66cef6c28d08d8784d03439a498d5bda832d4c11628f8fc12e52ca304c3e7c5b045b1fa9d050bcfadadb096a2e6e56e3579d855b20c67c95be7826f9bbf45bf11a34add265d4091d9c77e43069e9aaa802f9851f693b62cd689197e6f8a495fcdd8dbe782576f08df47a661242ba341176db9eca8479f0ff6f55e865d90520e1a51413e868c8d05847c84e2b2488bd0819b7d3d915442d2d0025f58be7bbbe41ecf533e801c061fe4398272a9850e26c1facff99bbe7ad4c1dc740287434ab2c04f7db7cee5f8453ba33ee2921b4a32226502270718475dda922a26a22b666627c22905a61a29bbbedf3d6ae29f6bd8307a9c4c631378b56aa8b185f659dc9aeb2ace038618af4428cd9586e9f4fb8b3f414c31841e4d223c924291b0c65605cd63477b4f1a96eadeb7f41ab9ae96d4db9b9d014ed0a9715c533c02743730c25e4ae4eb9f5b290d10a1ed5c921f2654dcf3d44b03bbf9db16d97413033459e5305c284b416c51482ce5f604c18ecc886e8549b81d86dbfe8ef8ee0b270a8aceb08e5ad8b8ccbbc522469b5f37d6542d898d69b91c81e42f835524f3c3332ac28d9d5aef981a9517490cbe1dbc650c91c32785b4efeebd25cf6cefc640355af00dac234a01553e7f0f2e70746683800e300d9d174d84e3b5ca3f765c99fd24970bbfb357614e2b9d60b0c0f29dd83933912c2717622e592d1b9f040c5ef35b54eec7707baa56023141b462726554bdb3d2a664445eb9d8a00402097005a8acbaef5dd85400bef8e2e95ce5c8d4fea0118235adb54550ccb9b810bdcea37c1144225c04f7c5918a1478aa00dac572e629a38a82f25f55a9bf3bc63723031c80ea9adb41c582928750b7ae45cecc61d90299c99fa39ffe2db4b770b84f5d9312a00b8247eeb8de444713c5a4c00b4ff889de03dc0c3c1b4005a9b51c4de14abcce7eb8e5a3dd451c78c8802a03d71dcc0cf8b8a8ed63520bdbad4821a083256f5379e9901e2476caf1da23ee37a1689e075424fbed874cd57e03a308ab130b2f0e8e6b3cbb9cd230e4229dc76fd02d7ebb34262bf26bba44498a3ff47e6a8316f6a14e38f3c9a02036d6e96b90b816eee3924769508524c5e9262e635221c9a9c8b43c597c78502f9933379bfc9f8bef3370ada0e0a829a8975a5c9c0c1b48adcc5fe38fedac1c95c84425d5ecc9ffbb7e8fb4cf35673f0e20877aa43d65217b5fbe7a4ab7b112e3acf456e94b65c8128cabd2eb85568f29815400e461e0bdb3c70c14ba72cf2011b62b21aea36c39ae05550954162a390b91642c4400b9c4726a3be8083871baddb6441097979340c4c429e14054f6118720d94143b4ca2c3ecac0f4390802ee3e66d440a19c8d601f39d6b39c4e68fea6a8da56292da20a398891a15193b8e30c07d9c0d1286fc836203886fa383dc50ee96f145bbb53cb467f3c628de97d10f230629ae34005aa386ff8762c0267439135d12f7f95903f1e5c06b718cf0dbc5ab6158dfb97012f9c6ad49f6d685b5a8debfcd47dac7a544b250690dc8aabc17ba6080900c3b59acd2e5e8e6a9ce3b460401ec46f43fdd2f5df0d00dd568cb42bd4427eccfdab58db4229cada8e6ce12e6a86d7305eec5b72b5781010beace34a5a64a2f9a0180cd5ec9ee1d777613802185f872013890c6bd898d369b70f371cf96ea7304346b2f2e0e23786ee1815699f7a32e3cffc7b1c0ae5bd69ddd937a99aabda3a89874598fdc3045519717793748b1871273e204f8cd6dad674b16d90f2e928b0d7a275d5fc4cfdd74668634934ef3e0764281b6b624bfabad181bffdadff29a492e36d079e7d78185bc33b69ad164ef8225cf1c03d8439767d93940fe021554a0b2c66a6ca919dc51b0ebefcc6e767d0d4aa355c260c1c53cd522d0b5827bdf2da543bd9848058669a6d8d711bfa8e7334352d5f65b179a22baeb1f2af9168c14a506e6a1cb51dd5146e4b2d46fa1a2bafd9f163f40f44ce68560f0d42d3693eb0a7e28902753a236e0b59f45c1596c34ceb3e78f180b1aa5ccb93091ef436bb174a6963de10389e74fedb3a1c538b3d0b19922dbbea786ab2b3cc70b469d48628cc3d6e30e5ac49df462d4efecdb7a6856bbe11f35f37177f855ee97e760e5803b19b22bd455b7bbea7559c22c034a5e9d25dccb32e4b87a1a3388ffba37f25c16f43cbd4c6fa763088b5a67b2e24787aed83c9902907bcfd3c2a00812bdbd57ec110b8a416b71ba7e52b262c4982b0cca8375f62934c2a1f4161d5fc1383384a1837e0d3cc3bf164f0b0b7924db7b9d186975c2ed6a105c21e929fd8473ca45cee439d10ee44c564398301b7b8a1e97d5d93a1d10883385aa4424ddccb926d81419e6c5721d68893bb22e9f2cafa10154a71346176e3373f9e7a76664523ad252c301f67779262ee04c2e094f9d7557080ebc5ce7289e471bb9d3f899ac17038548c26fdd83ac374996c0fe560504c094170780e83e7db321cadf19220bec88e99dd92cb602afb5c745d9c3d16ea3e6e881e25273f320a148118183c61361b7ae807079ee1cc2b27176720846c2bd1992e5092d040c1a968ab568d4b13249c97803c0c9c64ec075a8d8634baeb6c47ae245599553b5b468bd568dee97c1af0a1af4d8c4a1fbc7965a8f4367759a02305837a983079a11885766c82d20d74417d7112a0e32881f0a09721a9dc0000b75c2989c18986a758e2083b56c79166f4041861da0cac783006c434e52174bed038783911501c0208021663d4889291cc700b5bc85d3286f4c010b81435e082d830fdcc72490b504306f7be0c21561aff2a23176531e564a12af868639106a791456118496b2e7c86302c0b1ff95dff89e9e046aae8a26b9af52cfddd33d8207615e1fc5074d49e500190d53cadb1d4833b2ffd0fd9efe2bb1b05749156c10833fe32f3b323d16d1fc2218ee0792b19530b1970a8460b263ab52e4340dc38fb10629a6c65ea5ca167360d709beedbb6093708883e06d3446133692806aa4e6a231248c98da65968489adf15080afbb9147f9ab315d50221855ea010193d72f438b09a98c5646717eb0c6b8e134728241cc74ba787c91e04340a85f1ecf580020a49404b0dced415b764853e9104060d87f8190b9fae5d9fec03e312ba653265b6e32d1396cd12348e9880055e64c2dca2815fb484101e5d6159ba79206412cbf84cbd66c3ee6c8f5d0516b2ff88d91660e239b30c1b95f2a6386aac4ca6b7300164bd39c758548cbec31da22ead9fa43e03300803d76609bf41a4ee48f32fdb79576c64aa2807e0b7654f190209def41620d889f1532f8cf677df21e841ca856d68e903038cc8d14c7b0d55724ecdc51429608c8e23164a7f5f18c3657b05db79ec8edcb1676ae0f88075ec542487408081fb4fa4490e42104ca3ee06cf9703104541afd5d3d61aec83d52d7c1110b911a925ec53e3dc1da3562cda552cc269284c4ef7061519926f258794d1067cc2202f77f967c89b478ebf3736bb243578834ed65c0e042be3989e1cb55df2293734ed7d1dc10a9cefa1c1b291cc1bb16b9da908e914a386e83ebaad470d461712942d47eb739f0b32f42aa5ae87c1b32e0047edb12009d116a5a796e4633319b0260397883c02b91bcd385593527911ee1b12945446c091de3581b6ef99412c91d2ea64c482292e706fac5c148f54d9a08581238c2318d6d91290d49cc5d609e0901d857d7c2604bf8562b3dff06313127c88c119441983d96c07db8e6fa19fdaed09d9444a2a7248b6f686b8ebed0516725dd5dde2c62fa8a898b27a6c014ee9386c5f92908e98f7b6783418af5f4ac1ca47755a03d33a275491570f06e25c0afe8b701d765564270580870de08b3455c225273498cc29e2d43fa71a24a98a7f62c7651afd00983f8843a3822afaeaaa690d857bec819ec15a1323892ca00d3de06c3d521cdebef95ef0aa4b08fd74e3ae0c8181d12aa09d5f03424a4e7c11dda0f818aefbe02f319fc162dacbd0796f9ba7727928955f142ce981e2eb6d815d2a992eb773cb4729bf90ca62e21097ba518ba5fe9d898a9e18172800f59b43b8c8b403a4f9380953772fa240e203dc7dce136969db04858676bab10450047cc3c545d8145a1eb4ac1414c34324567115d0a1d1e559e4a862f3430141f8a564fb31a721dd7de22faaf51d9d08d5a43073dce5a024d666d878a7d70eb674d697903c6269fe2051f2fb634244868eb1d7a022ea3ad197be98b5c1b3c5a312bcd5b2e5d0c619d2b570272acfc853634029183d0184ed16550b86bbe431d937ac2777998a126536e09bf8cce20ed105018e9e1c99c200f49356fad5970e16e93eb9279dfdc6279826a4dc9c771625159eca1fe28bda940b04f809d7905072fff1705d0d1d193adfdbfbd501abb060f2e742562057d4bf0c7a3d479c703b83b84840820b6fc19f7905c4c342efa433107844a0c7496487cef297d2cb9ae62140d30af385aa5442a1d0be13e40a95ccd58eedbe7d4c4bc99e0a0687c6dd617422043bcc2c2fd9c4f228f8c77bb91eb43c9690827db99bd58389eaf2130f870e3cdf50c53d4f8c99bea67e90f2fef841cd0f657194d69d7c128e0c5e49c2acd06599e813815af88f8bae00b56b6a53e9125ebfe2c3a0c1f90b7f0e7fbd18de959aaabf98a1216588acc49409456f5f93978d8161db52b507e76106efc3810911832aa07d83ae438880bb3eda62111ae517cf0f6a40676f97373e08080f10e3cf6022c3c0c1ef87da25675377190f653ed79b8bab0ab9b55dfd0e1dbbdd237be593c2d81edda209002b0e28e2e9d10bdacf5130bc9ab34cae5f6892e23b34497ecc1ed13e7df8588638e79069d1c75a05188108a771f7c554c54f989bbcdcc213f3caf249a0006f0d56000db92e0bf380048e90f890638a8fac81db68be6ed20eb078ded4a967becbbe5d2d600192b6a37fc6794cd2aa2317d9722ba581c342ae4baaf01038ba97365d2b79cff51506d50a088875e1887990a2b77b009e38b30ac098159feb1bb07e351037a0c693eae06ae932c83764b3ef16569ccd52303595c91870373cababae122afc25727c5005e6609205e662fc30b826c62efdc1e62ef4081ce7ddb8ad9109d2326642754370cb8397167be10c1e7f7b3f4af5c35f39a53c1b07b69ab542958e394a3c6e8b945d13bd34c87c54d7ae8597510c9e328d5d1bc738b8e09097620057e240fdec7f14553ba3c745149977280502016ffad4be4304b0fdef9aa644a49e1054d974405ab70f330160b05cd6dca41d2ca4566473331b45c30ecdbe628200080fc23bf2509ba58ffd6a10d3be808974274624782090a16b27d8d85ae24f087eef01d90388b0efad4126cb9043a315fa95510382b391da0006b82d39ca834e3e741522f4cce7284671af491ac3f5ea87f4adfc37f92275559fbb7549a2de58e56a891b4bbc98acb1ed69e1b5c171f489a5445acdba3bfb604169e9155d235076f657612443605990af209180b756bb266d93d22c76ca461a25889c2c778488396c4327dcba28dc75f2a8149cd2efd56ccd5a5dfea9a5d1b8b4b9830fdae48e137811829ffae0955239dfb29babe516bdf12eba35a4d29e9282916dad683d7c6c2dfb87f3d9206adbe76283cdaae2a4443f7492572cc4649b99f82c5d8c6fd4be77e4a186e5d91b445d244afb1f8845ff7b5e05c141eed8f1de977aa8f5453bae96a54abfa32e9dc4f19ca1f0beb1b7d2c3682569a402cea9a5d5b5ba49a13ec9bea8e11e9dc4f0943fd16f7affc5624ffffb31e314832c56cd7de32c3ee8fb68f696d9192c652278918c336ee5fa16ee95c157f09d7621917e5574137c544d1de88f2c3b04cd7ec7a91b45986652193d67f471cdeba54cb546eba6edcbfb4a67509ad615a45a5a5f0995e2447abad98415a53c8f4dc379175f43ccf9bcd206fdcd69a98f1ae3b62662a0bd6886336dbc2678ac2cf4d972bcc94ac7e980ae2ce9ab38abb9761493d242654965019412b73f64c22ee23881b41dc8c5669acfda248abb409048709e44e20573aea721f456ecce05e26090d69d23469851972850dccdd1d001bd03961258214c761a9e70f13fc09d0d32a6dfa9873024f1720e0628b2e3ee0810e80c1810e70d1812fb6f0a20b0e70800b2eb6a8b3012d3490812cb0b8820e062e60812aaca8a28a2aaab041260a25eb05847c67c9ddb338102fc270e7a9c08e0cf8d3dfb9230af730bfa6e1b5536aae30df59b9961ceec9a9dc3abb40e23b36b5606fb6da8720ad5e61c14a152a4cb2d8920060af24a4292b18a950e46a110d0929e958ab354848e2a3ea19410424211c31b2062d024200887ce04107433800c01a6bfc58638769ea90b9ce1dde642e832c527b1672668e36ae84473673b4dc9d8aacb1c61a33c70f676d4be3810254dc76858da5e69940911313742cac434e4c785d87c23ae4ce338598b30bc4a22844e4ce23011e29469c8b7822c003019e07f0cc19e2f3c609ba70773d6fbc71f71b3ff8bcb1e59b37622d77d7f8aee60d2637907c1fb5dd7923c7ccc0052bea8d318c6543af994117175e9bd039e97e58e1ad598e03a288c3038709283c50ec40a0013b56ec5ce13b74a68d273a7738bf16eb64439ea389eae1b66dae4a34895d0713779fe213e5c475ee781a90135bb4baf3bc71e761803bcf133c4e60e1ee3038100fb460f2e4e061fddbe481b943b92fd2954d8fd476b1d0dca1a395682537f0f788c18e56deb6b5ed4a5214c2cf6548ab175bdc3de7736784e94a7327c874164c07c17434fecd664b3bbfd32f25e5a4df6568632fdaae8dd59476a9a4f7c7ba1c8d8ae0b5ab55ed6c4986bfa2ddc03a443b2dd6fc4eafb5280a7d1fd595d63fa2ddb53991ee7ce00214b0581b5351aafb933ec4445bc35c8044bddf35245bda054bd2506345bdad312c0d2a3c8d329e0698c60a481a3f80a4d1038d2e9c46a1d4a3140d22fc335da1d1058dcfdda9f75aac4623887a5b33a141dda987ab4963b8ec8c29ce5073c60feed423816ad1d6b4d8d819e219023843e5ee947a59eaaee10c8b1966b0cc30803bf57e6e56ba4c7adf1f95881ed6515d296829ed9ee8aaea2398508f2b4968a988d630d57adb6d2bcd895fab7d141f5590be55a146e0e35c65d87019f91956738279de8b64b95940c74bc046e2deafc56afd19833a3c1a7e07ee3edd795070f7eb403cb0e3ce534310771e26de09d32a5d69fc0a1f0536dcdd456563d868ab48845fba1ac5c818ddbd23c30377ef74bd51bb2fad44a2588970b6f619d6e1bd627d86d12e77ab7dc237da655ca3f749fc994480bbdf702060bcc077897342e113851f86422678c18bb35cde33139cf126b89a24620ccb0fc3d51157c7f0e2a16bc7d104495c038db83a8ea3ceb0a29a5d404a0073d74cb42d0bcdc2fa37b1fe92e72db58ceaaead5d2a853f5a59f89f8b3226aabbb6603a346ae2e4797a8949e7bee9430cca907cdfb7f7916040c458220609eeb96f1a411aeeae97bc7e1b1ee5719c917a7f6c044bee0ef4b5aadd79dcb871e3a6091e2644e000d7e2d325371093aea7d5210a2ea08d93457ab9bb8ed28184e0c749f16fb3fc3c6c7896f02e7c1728de6164c0a97771ed5b391cc6ed51a63d2f779ee779b3990780700394f980ce1debe271c4208bb56b556b690259782da9d002beb520b471e553f92b279c608ba85cb1569a5a586222d3025bc1e856bbd5a42697151f71dcb72e57b1b47d56d26d1cd62611939d12259e26f7be510f69894945bbdcab498d094d286ce26add642e1548185315a61b68af64a625fb4c4bc85795274c624d642eb06005081c0540b56d62c2129690516ccc6fab3447fbfc377a74d3d5c8f3409bffbe6d679c849335817f039f8cf1ace151c3a384dbc8c16d90f9c2eadc7de8e407a8fbe9805817eb16661fe60702ea8058e03b89621d750f102fb6e8dc95230681b4e49e808074a1c6ebe96f064170d1b15a41890285fae042abdab547f296b2d2ae3d12a594ea7881e2423b7b5bf8b3f1c6931c377078066950004a1009b350c4282f6c74e136cad0866c5183bb7f88af173ef5882803445950a0d0ee6de1e700a48e1524903a413a774ac83aba0640b8fb1507b2010c907504f77d271c965a9363be013d784457faa9d22a2d871653f13c1d517058c688b291cd6a5d6975284a2c28e32251ac446225f23c1d9ef7e1fd30b4b79925eb8cd4daf39a000101010101fd003d71724213134a60b2042828a80605053dad0e053dadd2b00c09d59506fdd7a2cc9c3e939ef744cbdd3beb84099ca8e3dd0db4b7a7d056bdf1eb0a395143e70492133c6ed8b8a9b901d244144d84e9fee211e3fc7d99f727624cfb3ecf937d4af9af1d7ff5f97c5f1352dc3b204dfc70af42a4c40418ae9998c34498fb3a7f0ddb2ece5598b8e5fa4c38717767ad9aea3f3191abe402ea5459005d00e9de2d0006a44d0a2eceddbaf7d344b1acb579e30e9623c56349dbe46ea55f9428513c4f1654530a7aaa4b41383c347baa398a9ee1d810c1e636fbd97ecde6c76fc9c64697e5abcdeaaead281a5793744cfbdc21ba1231a6a9a2bc8272795f97aeb96a716fd91a347ccd9c3538f76e8d14ffb2d0d547bb35384a206ac0e8b49a376a6e6556e3e45a25c4704aff6221259450024767c3fba0ae4fd44559b9daa380281480f33e6390820a80919448014988e1ded124d2c8928021095812aa8a5795ea3475701f5e5095e607f734a025d3a0a9e3ee1db89fae5695a64283735ac6399a7e914463e4c3baf8aae83d42f3c3e8cc1b9ccf7471a76782dc3badcf6c60e68d7b670647cd587137b3840a86d16bb3fa330675d6d7ee3a0382c41b249030727724e81174fc8830eef4080260bcc323702019c1c6882d5f9601ac428b65005fcd080f8ae0a288314558a925ad8552d32270f8006e580640bbf08998e33522ba942411469789081c9dc6af21c0f0ee623a449b2148f78be9104e5a43e0f02ebf05ad58475a85f0c02d7d6eba1ad1d54d572355d0972e7c0b7c2a429078a45f44052684945a0d0b1126808a0474716ab475c6b504fca874eb5b193ab54c1877ef5c0ea48c941c8de65de673198415e51eb70e0287fb7d1f8f41cc7e0731048c591856202ace5d8a2e6f0904192da2e8b212d59c60336dab7668d75958ff268455d81f9b615b9ded3adb751625ca2b48fff84b41e05309ff963947fb214dae648e06fe50c30fdf0f2a8c9768b54e409e541a43a7674c18fc2434e6e69db663707897a311f940850fd407293e0c11238677a118fcb4e96b311fde558cbbfbddb68734b0a425237a2bedc18a77342c527f616dfcd247a25845b15ea6cfb03008372b0842bc9856061065ec0984103a4ad012322470c7afcb845fb88565afb00e896551a8ab91d2c6af1c60e0423fdc5c5b2420634eb0b51559dae664f53ddaf805cb89b9ba42d7c6afdcad493b63be707f6dfccac1871e678dd6c3763f61248cab49f8758f624f5f84b1ec855fe147d103113b4aa06070f71d1417a795da794ad0cab88856c6367eedb7e557f8b62f22c78d5fb432b6c50e67e86ab44b9cfba22fc58afb50bb0b74086309ab7ecb76ad4640180bf81346da42b66bf16ba747181b5e26071abcd3e56dd3d5db9c4113b50e318559d794b0ace622fc22fa8c93f02bbc7808b6f16be317155fa6b8bf74eea7e057eea784a1107ed530ce3c46bc8cd9f8b5f12bfc8d5f6ec60bdcf5e318c632004c1cb29ce0e47937c070c3df103aad618a4445a6690e6f502003990f7ce9f2811b72182205340b16215918864261f89f4b58f83648c0dd6d10e336103969f27d1f5dd5cea70910cde5b68a8695163eeb47bb7135a9867d541d25812e61f235d5fdad58dfb7355dc224cc4fbeae435dee9b3e550dbf16abbf9a036b58d7dc37a9680e87f3ea73256b12ee9635fc0a2f137ebd48ab9769e3170f922d753c77d4961766b3d94c498e14433cfa0366a0e264fd9b278a15e7bf72f18ba875f1cb85657f84653afc7ffd585fe093311e2a836de7a704eebe440cb4768f34d33d6a0231d2fea48d5ffabf28b6f1eb0923d162f815d6a13af44badcb14fee7f27e8cc99d470a9416d762f54e98023419411c0b86317cc2d0020c4a1306239d3b50db5109a82d172a261737938b1bfd560bce8708de63f37c008b212568711f2a2a23e820410f527074900407002840a87077146e412c7991254de4085864516788170bf89962e82b72c743900972c0800b0869bcf083113b61bc90c347d535655cebc2d76283bbd3d913be340b16fd52f2b93c8209d96c37d5f869258a57146b7993d1ce6783f56d756baa0a6fdd5ff725a1947a1ab3ea670cf63c8de6eaa2dd0dacdff4034477a5d4a3fbd66b471cfefcfc00b17e7e80288ed463a93dda599d318c453ffd19837f9568a7a9b6e24ebd9a13a983b891ad2d1278737ae63afea2bd3d9125cd3db83b4d887663cda2ebdae7998b9c665c9bb987d3e9c2197aabadaefd10971b5311eb6e11e5b665ea3e2c593e2c7495e5bbe96ab4bb2cb9fa54e9912d57aa35ed76a5d956d2453b5ddafa54a97ea23eaafb4ff49f7405c52a44bb6debd3cd63b64e54bb644aaf72657b2ec69a6a21daddc06d9f34bd15d421d53bac2c6ca395de72dc75f65128515a4735573257da51274b69f8f99decbe4ff1ce8995aec2271b66d2e6b7d93e4d6b18ed76895742b4cbf27d589c886e3e2a5658ffd63a12c5dad9aecdd56c88475ac334cbf737b012dd36bd4a6156a29dfebe5cad6871a550ed445188a2ca08df85b7f46fbbe75610c582496be33e69640fe9534889493361d254eee4986fb38ee13d9ed7a35be4988d94c2d7825f17db5c7dba4c44fbeac72dfd5a6c0ce7bfb254133f86654af749dcd15cd536ff2ef1171efd58bb28e111f8543e9affde5cab50adeb4d2759caba1eedba6b6db7864f73d115ccd57d3e30ba3a527d945e4b8f3e3afeb61f8c453d4d7d682adae96ba94f55d1eebb23323f61f195dc8ec254da7ade4773356d77d5f5837d942582f673155a7d9937c5fbfb3e1f2b7435537d9f95eff399d19515d5a7bf26b06692aca0757a8d2f6551ef1ed16d6f25474ddfe65ab4fba074dd47df666f7dc2e1b54f3877f6bfd5a69538a4d7eab7b9d29ebf9895a3b16a35dc737126edae4ef60826444ba57b54b444e5697568c7ce25152c75d1695a85fd17751a6f4d5a2b9263fda78f1c4b1ab5ad708c76fbbed6fff47d1f45c187048a8258935012e87f6da6a2502869f76cbf88820f69b70a142b38834245254ae86aeb327fdf473bd26e1fd26e15d5ac9c787116eb98f5c5b68aa5c5a4dd34eb4abfefd3181f21eda6622d77b64e473eb17edb8ae52844b12cc4e327b996423bf46278ab51288a424bb0f0f10b768f7255fc562d53b947426fcb150963191e3fa98565b9b0fed2c62f8d5fe187d7551665a5d00e6dfc7252729195e8e8627b5dd735748f722dc258a6733f65e9c9eefb6cddf941ba351ec5ea7324bc650d5492238fd092a84092765f7844bb5c6b146b9aed3b595ac661bde1da3da2077077d1e70a5b7eba254b585ac49864b15059dc1d076a00abfd9a565a4ad631039f2b1071775d73cae7510cdc7d1e9d39b2818bbb172d51b9b68ab058788572b09c08036d78e441f8637de1d7d615768fb00c57933ad647f7c768579b721d6fe07d1aedd1fb7e8b92d0e97aeb4a70a27f5b423f97e044a3b02813a7265d57744ed510a1235dde2793d8e0e131c67421e1ee94ee84e122adebc75b2eb4caa0e1d9728333adee1efa6c4971622df1d9b2e1de85a8a2b91a3289e0b85b9dbbdab59e973d8f1cf32dac7ffb1083a258674d98dc36fc0f3d4f8a14294072dff417b7b4100ecb5898fb29a10dcbd84c810e0ecb58073e53f8c1759de1b0c461a93b135248a244da9b9e51cecc6694944c146b7729ae26753e34fd819445813e15fdc04f57eb64f306edd656b4fa69ae21a1a177aaadae09b4998635c5a190255ad570c5db86377dbbeb13ad347c96fef901da42b4f3795dc1efa3789738a75ad162b4fbd0ea5d628b29595f04ed1336a29db6a25e69daf9e84cc314676b3912e77d9fd636beb7caf7fa3e20d6ebfb5bcbd537bbf8f3a9bbe7e23014499acb1593f469e2675c63e52769cd529f9a8ae664b4cbd5266cfbfd7d2c2b4a5564b9fcf351bc69958dd30f5e25da7d4632155e2ea499ece54a52c1159bbd948e64444c4bb2d84b8968b6e46abd98be92f5b51a667d58f3a6957e15da5d6ce98bd24ed7b02d7cf109df26d6b5186455fd1a93b92473b9eafc4e610dbf88763ee27f9315559f75cdeff44ff846571ab437b266dbb52c08258df9372dc5dab57465bb56a48dd54633aec9945e5416634a2ac18fd11068972449fea1da62b17bc1fcc119719e18a0a860791a8f01ec2d6fbb96d084004b2868a7122f1d88afede801cec385a5ff4451a0d7521e2a50c8edaf559dc1129a94b466290a7f31786d094d4aaa6da7cb16c22a443bead52a08e8f1c9c2c1fdfb74ee3c6fae12c0ba56895841ccda11c05449c05fbec44cf261cf6b3d48650a0e4bcda24d15175fc2629989c1dd734c404edc879471e7f172bfd1e38e4a75f11d1be69c002585470dcf1a540a11e8d9f1206abf74e1c319f84edd5ffca2d752d75ffca2b8860bed6c36c28f3b8bd5ca29e99a5df7e87111958b8944229dbfe96d15a675ed97741572cc46757f524da9eedacab848df4ac6322eaa29695db3cb458ed948c33452cd1596df163e52eea784f58df47fd1fdac8bfe8b72f99dacf82dfd36e734599f62b6fac2b2df7589487f885fe02f6d8d9334ee6b4a9a56c66e25637a5fab6b768935bc6fd3fb9635a5fc6419d3e17d3237f42126facf55185993b4de37e3225cbb4763f94c5817e9261023e9b79aac4962624a0719fd5629950306a91c6b7035a9c3f9b56ceaa3daf5f3472fc5d524da89386f5d86e2e77fd2db2649d23a12a29da6354c8fecd7477cf45bab2f06ed882f065fcc1f629a2ad7baa7ce67b5ab8a7ab918e5f1810222291b488472974211b15d2bd26c2c77291e139c7ab8768f7297da2193dac1b92ba1bbd2b7795f9bda2172a75e0eacb64732d2df5a2a12aae56e16c5c912a03268e33c6f0d32d6b0c28d587a9f300a020f3012826aae81c475ee72df34132b88cf2801668718c4e00ec4122bced6e9be1a6dd440a3060e6a3c51cf47ac1babe87b1f11599f74084b6a51fc0227dcdd459bb840042e88e3023819d75a2e6abb76a671c6933852687f2cffc7742992b98ce5ca21239cab95eb8b44b66b3516899efe458ed9e8c59785ff5a2f71f2bc11b482461134823c71c61037333430230377dfafbfa41cedb513054a0707683106d00e06525006116ee407bb6aff341b96f5da74adb99217df9a6d3b1f94e163b60210062ab0310725c7dd797080ffb56258bf7585fe736d9261858fbf8f46bc6fbdc16633323c328a9031e4043f9c60cb09b6cc2964f03945e9738af739c5159f53c87c4e61e4738a209f53fcf89c0289cf2982f098737ee61c99c3c3a79c16f89423029f72b2f029478e4f3949f89403844f3931f89453f32907a907073e3e88b3c5671cd1679c98cf38527cc651f98c93f20987053ee16ce1130e153ee140e1130e1a9f707cf009c7003ee1903ee1549f7092e0783ee178e013ce0d9f50900105163ea180804f2816e0138a323ea1c8f98422e6138a9f1f423c00e2e307ed20040f21d580303e1b80f3d900d06703947c3620e88df6f9e6f3f946003edfa4e0f30deb4d109f0c80814f0680e1e307074f58c0e7130cf0f984199f4f7cf1f984e8f309269f4fa4e0334d9127807c3e8104c83402800ddc883edd7c3edd08f974d3e3d3cd0d9f4d8cc0671356f86ca28dcf2676f0d9840b3e9b60f2d9c4139f4d78e0938918f864a28e4f26a0f0c9c4189f4c6cf1c944169f4c143142a4c8082114f1d9460d9f6d36e0b38d047cb651e3b30d199f6dbaf86403e493cd083ed970e0938d0f9f6c787c2ea1029f4b84e173892c7c2e21c512717c92d93e36c0b1c4129f4b509f4bf8f0b904cae71a16f85ce3019f6bb0f0b9660a9f6b9ef0b946099f68cc5823c6e79a1b7caee1e2738df5b9a6fa5c03f3b946c8e71a1f9f6b7af854d3029f6ac2983c7cecd88163887730d5bc7caa19f2a9c6894f353d3ed500c0a79a0c7c2a51c68f1f4964c0671252f84ce28dcf24d2f84ce2079f4974f19986059f69603ed3b87ca641c1679ace679a223ed3f8f09986c7271a337ca211814f345ca0a1804f347172f0008286fa44b3814f34eef34c0b7c9ee980cf3356f83cb384cf33627c9e79f27966e6f38c91cf33467c9e19e2f30ccaa719327c9af1c2a7190cf83433019f66e6f834a3844f3343f834b3834f3307f069a6f46926f46926e6d38ccba799954f33447c9ad1e11309347c2231c68e0e86f408e1d1c1e4d10112577c2221e41389950bd1d1840bd151c685e8a08103213a70b8901c5eb8901c685c488e2e2e2447cd85e428722139582e0487192e0487065c088e39ee6ea48907de81911d3f8a90c167112df82cc28acf22967c1631e4b388273e8b60e2b308558f39c4103e87e8c1e71038f81c828bcf21489f5fa8e0d909e2a38c169f656a3ecbbc7c9649c16799d5c40104199f4020c0271024109f4f325bf82443c72799099089c22799277c9251c22719217c92e9c12799303ec9d4e0930c0c3ec9ec1c3b74cc311ef03946033ec754c0e718287c8e61e373cc113ec77cf139468bcf31a1cf31b2d40f0d70f85067fa60854f1f22e0d307383e7d58c2a70f46f8f4a18c4f3115f029068e4f31697c8a01c2a7981c7c7a7941cc169f626c3ec530f914d3f22986894f31487c8a09b263fae8a1c7670f3a7cf6c0e39307357830814f1ebef0c9c3153c3cc0270f4df8e401099f3c00e19387303e7938804f1e60e001478f0d7ce8d8a1043e77d0c2e70e16f0b9c31c9f3b3ce1730705f8dca18ccf1dbcf8dca18bcf1db6cf1dac04d9e0870e5af8d4a1023e7580e35387363e7520e353072f3e75d0e253079b4f1d967cead072f71e3b7c83d4102161def80c4384cf30637c8691c167189ccf1c94f8cca188cf1c7af80403039f604ee0134c183ec168e113cc057c8279e313cc113ec188f10966069f60ac4f30557c8299e2134c149f6096f80473c42718203ec1a07c7e39c3e79712f8fce285cf2f1af0f9858a1f00981bf0c07183832f433ebf04f9fca2c4e797213ebf6430bd80f1e965062f2ff8f4420ed160e250864f1c46e013070ef8c4818ea792a8f05412cc5348753c85f4796a8a1853484fad80c60a5d3cb5020e4f1d85f1d4d1104f1911e129239593940a6d3ca582131e3b6858c1270d29f8a481894f1a92f8a4a1884f1a38f049830f9f34e070000c09e3ce23e51ecc19a4f89c01c8e70c20f89c61c7a70c23f029431d9f3168e13386393e6348e33386303ebb94e1b38b183ebb7ce1b34b153ebbc8f1d9c5099f5d92f0d9e5079f5d6ef0d9a5003ebb943ebbdc7c76c1e2b34b92cf2e463ebbfcf8ec0282cf2e00f0d96587cf2e3adc79f0e8b181f718e2387674204c07e8176138f5be68433d1cf5be9042bd2f70b8536f7a51c7a9e70512eed4f342a49e173fb96fea828a2e3e7747830335b8738072e1c6b968f91674b6f8b640e2d4ab93823a719c7a7560ee1b18630369e60664eed41b430b1ab46861510b1ed4d300111a08720db8bbd30c84c900cca9974518ee59a4a15e16a1532f8b1f2ccaa0dec4624e0d0b19163f9c7ab32bbaa0deec8adbbc4235e98c413d3a6adca94727c87d86013a597c62e0e6ee1828817ab30ba031c79d7a35b853ef023077ea5d8008f5b418d4d31668433d6d8196bb5be007f5ac40425b2152cf0a1c55d0f159451977ea69d0a30a24f70a88e1be4b12df921c9a14b0625220cea400035cbba36afe8d9d848adc516156e00ec5dd59400512274bba1f162d64bdcd3b4ef8b9962ee8d9586a77d4ed87fb4caca81c5060505c505f505c505e503848600aea49e0059dbb8b7d54530a3a6005a570e3d4cb34f01449412445cf942200ee4e6dd7e20dde326fbad2a2584125112040047ee60386e8dc4120055a0c77dfe21302a1cedd0dee8ec3513694b7ce0710e128226a40d180520285001e3e878b3975dce96d5bdac498215240b38480250d1a4721e15db699fcb06697ede2fc042addc03209635985896259d454dfc60e0e88008bc58af144e1074019004543ada67487a290e21e278b3855cc38108833c647b5f251e1de47b55aaa6f547385ddb44dbae96a54b56d3dfdeb7351cd1576992e5356d2a2d06bb131fda0dd613500cd0ddc75d436293cda69c2ddb9f87cc3466725a128da1a4a800103d0b97be20b77e7d1e2441927c2ae13ed2e592cbb4b3735f86bb1fa7513c6b29d131640858e02f85c800e3267a47377829312911cedcc9255067787c1271b14b83ffd4bc764f3c45de73aa47fe3d77d16f26f4c85cd5c220596076a08502a852efc4a801239ce4cb386bbdbae7d551cdcdd059f6940b23ec53051eb434c24c444a3a46c2114c22ffc92857f1f095793f43b5523dcdaf8752bd17d52292be56f02ed948d5f196ffc6ad276697fd2ce5d21dbb522c6302cd3431a202171ddbe720ec4116ddc8ff0e2eef388a623c0235a78d315f556d43b8288bb1f61c3881438f5f0ed89ae8cb880fe90ee128f20ce880318e1823bf556d4fb0162914580e14e875e46224db4f8f5b60ac3af251e938835ee64098b05f49bac619d79de1cc28a8c6dded5863f8ef69bdd0ad637daf8258a65d1c6af35dcfde6530834667047c9e08e8ac11dd5c5dd6d14c08f88218c3b143e013f3385f8e13a77f7475bcd37f2869d2f3b3284471a937746f200394f13e7019a091081c91296d698bc01ee46dc3dc8533c98e14ebdcc0318b75d1bfe8338c36827e2fb4d38d3a8b64fff3fe6c09cfec2cfd34bb0168568b792227545880e36e8f0aec3b3d58874500f1b75fa6b95525d622c7ee053f9c6df568876b68bc58c65b4d3a5d6175b5dd66e78ebb8dff685f5c5cf47f5f9bc166b4db55f7ffacb7f2d76b49bcc45366f7debf831daa5be84c0f5a8f58338574bc438296cdd5d2a85b6c26c687277c9f4be56849f27d8e67a1fd4b4d21b58c66807e4d530adae663f40fb078876b68e56c3b4aebe4fe777c29f7112edf2ebba332647fbb1f06675a1a53da3ad22896d68a9de560be577728df5465735f753a8588e2508562a62dcb98a8462dac9ee11afbe8f46b1651a2862acadae4fb44abb77aa2f524d8ffc586dd736e923d9d25d921bd32ac549b4d33d9f8831ec637ddf97e5d31f162a8af5cbffa47106eb96327ee4a92d46eeeea3dae2f44551acf485389e033d4f967a61e76eea05cfc3f9afa86619cfba98e7c9baf841e62e624d535a7eb8ff502850a8cf082acf8b220bf2bc1c069cbe131e498c5fa4d2bd479f8b70653859f797a2a764407052a460651ce765bfc519e1a2e05838117043701bb8d1cbf39a38799eec2da87fe96829cce550d21253a831d2d6652bfc271c5e971398f20a77f7a3528e7735a9b35b3fcd89d4c85f6c4bec546b14b7281df1de788876374b73b9df96aba32e712e865b34e316c8d26bd236d3fb84692e718eee5ae29c11ed7e76ed47e90ae7d79224278af57312234a4bae2bf4256424a34b2e99906b4905ea1aeaee93b856c008ddb285864fa144a15bb6501f95b6dd7fae751ad317edeae755cd5d21dad59c78f1f7e9efd32b5dabe10f6bfe719743f4fb58e042295d8574150b1aed2d46d624289452fa0211a52f5a72c420bedff7b9680835dce9f105ee3ec553634f0ff5423b5bb93bf6d4f8a4fb5ad5252de707cb10e77dadf8464837811889d2d96c564b23fca5a77f95b154cd0677ef526f029a71ceae0fbf042726c4621d6eaae313be4db4824f6a9a3b52e4c404ad8f38312116a336daf55c5b6fb456f74dd809bce96a14fe2d3f14b1aaebf4b6a3a747a0ddedd397d62cf55151da7d4b9894df577edfd658bcf4fb7262f9f9aca2c882322efab67e5ac335aadf6696c6a02585827c5494d624da6d6d45fa4591058d7fdbf9da1a66ed12536cc3e121caba9652c1b0dab547b4d4146bb1d215edbaefa3399a4f4f1d55146fb226ad7649fa5c4bbbd651066fdcbd7a4a005ab8db306283de74bd953f6091a1d4583e2c312c485888b07458565848702731f511414595501f11285d89403d12d395085445a977db369a054b0a8b06574ee04e3d1f559ded6b3d17aedddcb1583c37522cc0dcbdbb75074909808521eeee368aec239cff0aae268de51dcb57f8b89aa48fdc6deccc2ad2c5d6095793dc515e6c8090ab51a83716634ff816c32f9cff8a10ce7fa508e7bff221063d5c1d67a2686fe0be16b7c005f7e36ec6dd8334794ac645e72eff0ddc75bc21003688a494caa496a4a404e0c5dd53302229180ed88e1f71234ebd8883e0423c88f3701fdec337f01daea3470ef70be0a822c49c3048806bc3e587194222dcdd35f012a3c2532e264fb9923ce57279ca9582a75c4edc3d478a88059e221a81a788bcf0145106dc9d071a25784aca124f4939e229294472dc40e140915d50472cf52045851162f057b85025642977da04091db9228915a8ab3024c918baa3802be470a002f93163078b112234c7e7ee4b5c8c0c98f9a1c20eca63c5776c98c381919318aec2ce034a0801171f4c4841c916d9b1610e15452d18010b4d4049498640918690231d8e40b8d1e353c85902a578511842766c988312a3884e9008f87802062b34751934f91cc15386112cf4283ab34151103c720c7965227278aa68871d1ae0d0c1cad500857a91016cb879f1137462e070161e243f4414b8d1e35758f0438b142fd239da932222d082672a7932c4415095177e8830668c1d7722c56ff4b8bb8d36eebe83fa0203125374f122ec01b0c03b0a405440e6ee9efa826883281b08e36eb3b4b1b4e18ff96d96969f24ed9ee53c1b4b91b4b7afe5bf760ceb2cbf286e8cb33b6a0c0c15668c5a4de9bfe86db9de88dc51267047952063eb8e22014a0c8d1ac12d6bee281184164485608342bf3f831713a18218321b411c2a8c0380c0016ce47c8893f47f511358778c1cdd511f083ffccb24d66fe117ce75f4637d69b116bd13ce85b14cff17d9ae7d7d88c16fe17c9976c6642862a317695514cba2f02f933bca033377549ada677714181db00e407d015a126f7794175db88776c60177c78192e3236825bf2edd515cb8a3b6b8362b5677d4123c51781dd40678e2a0bcb88f2a8aacb36314da5d6b9fa08401c5003e1654515a4853415d7439a80141628260accf64102b08472d854246a1a57397f2caa8294f4dcabbd194f7937a52c6fe9c7ad2060aed42b0d227b8d7c2fa4c3e09d24f504e54907252270aa59e130638619372f2038d3971c1492b8555ea8414ac4e68536b2246aac91b2ffc307c5951cc841ff4dafcb0dbb6759f8fcaf3649ff77d54db9d63e58751fd355a7ade87855e1fbdabc6d524da65bceb6ceb729cd112e74a9cfba2c882569f4b1d5aec54b5a63859fe6b939674cfdfb6ae6415df849509b43e997fef1f8a1d3942751d2dad61da7db4eafa351a3e6def9eb2672c6f75834fea6bf3eb9285f7e327592ee3f1c78bcbfa9f8c769a8e611dbfe79f7edbd2854f5ffb7d9f3f9f996a2544bbcf7f7b226b92a69fcb5d35cd6d5dc94a75cfaeab9f9512ed40bb51a8d4bae8b5b42cdf8725cbf76111af12de9476391aed2e26cb55c6abad9ff651b2ac9f7f04edd6f8daaa0dc35bc91aeb436a860f23f0300326421defbaba302542162baec2cfb409c422923290bcb94f62243720d1924212ae52218ce120a659b080a910429fcd5247e87c1fcd189632b285c54a1939725a0b9f24eb532cfcdfb9a1fcb06ee76aaeb0c76048f1f6e9b05ea968177ecfad59da69b23ee914083505420922c6e42c00b701ac34112b0020048047009c7a17eb3acef47fcdab7d9e51efbf468980e1d45b525a5a725123468c0041a48bfb2cff4a496a080c435a48113172d7e3ec56900812771fe229223cdc8ef6c5d9ec7505675b67fcf48118140a14281fd0f9c0531fa8f1502c719512fc00e883221ffcd0b3940775dc3de5c111290f6070a71ef5b26cf65fd3ffb554076b3ad852d2e82afc8cbfee568a43fcfa3a40a25e0746521da43ac0911a2202779ffc24cea48a76d433f236e73ab4c4863f1b41dc909e21448604a1de6c45531cd4a1f888140739a438b839f55a1c3ce14088536f45e9aaa4799e66724769a1810c6481c515743070010b585105aa02ee280ab8a3a870474de0c7faeabed9278ab56bd1206a94910af20137a25fd3fd217e1dd9ea502a480d30a482e454905b2ac8476d9546c3cf828596d10135853b4a02ee2829dc51114039209552c3dd6d7588a260abb40ff16b878c542a4967ab347adf058a02de21be5a4c4d3a2edaba6f977a44b95b93f0be96123dfd8b6e7bcb254c7c54aa1a26819660771533d6f7495c69a54ef540e33af74da91e425dee9b48a05f78f4644e96fb29dfece2ef06e6fa9ae672bd9676edaee437bd530df7e86b6d4fa3556e4fbfccb24fedf0e2eea91d5adcfdbe16fcb928b50328a8dba804f447d5510a15a2110000000000b31000203824180d06c3e190583ea4d7011480015fa05ea85c48168949948314528618430002000006000000060c05f108e2a2c0fa27e23275c813160f8790eaae5683035ac3f1ed0a5520b38cd1166dd7a4b61edd93012995edb2959fed232dc876b7e49c82be6346161d5018ed6f17dd281dd657835718650693cba7b933284500ab1539dfb965a99e23433dc0970e292bb4b9483a6ceddcc954c0fae876e61e5118334f80083f464fec9364bf3a59ca49a8ccbd231822e84012690a361712798c1a5dce3a0265932a2ee0f608b22e390e99a18288baae0bcd826a09dd5d734bfad65acc3d07bf9862eb968410dbbff638f6dec3397dbd0b39a6845be2a1ab67fb26fdc4a89c6a26736d86a9bf95cbb420abce292799a34e214c5b74e40b2439e2e891a1be9da53523d321eabefbd1806c97aee584cb3ae84a273da6869447fffce0f06a0cf383b01a767d78a7b09f9729f85f904ccd4e4e6d1fdc62fce6b6c50fc2683a4e9d24f94136995347b7cb2e8a6c0a4dbb80cc8cd33444bc6f0eca02a1589ecd23a9b2662643f8ff66cd645d65fdb36eb58179ea71e3b3c2e874673c7850099223811c2d064ce5b1f7936470ade688481cba513e7ad2589b6753a585260c72237d019ae0d9e985575d2690098914311d4bd726c322560410ec4435cf26929536652669707f76322d892972fb32419f44823a641a34e21491cd3a2c81d4cb9955d4beea47fdf8294e34a51afb1aad50030f011a211c4d82b02d209b85a5398993fd0b74151a21ddd2284dfdb657a8372a5fa9d314aca439502e5973388d03c21286db1bce8e78137961471cdb80885842eb3129ae018801de6bda021d41dec2a05074a6057d403ffb27031c7c47c1933dc20180d158157c9ec605c176ef4bfe6df1d93a91d325cafc1d8a6431ae6a3f88dceb70a092d58b59000c437e6af8ff5775b18332b38b262e80619881783948263c234f6b1052d09d7032dbee6d482119135b6559c770be6182a52414f541b8350b331246f61ab4a752562b1579a8afb8c4788f0ce69f1c60a5c14658286e89142b64fe7a97a09602a175ea3a296d1277cfd23c1cdb698879be58ee263d704f0624a37e2f80d5237f42606ad4af1e747b53a99ee2978e14d04773d342b050f7229e22cdd40fee8e219cc9c143ea77fd4eaf26fffaaa5650f28ccf7fa3b53668c31345e9dcba9ce140c96187398c9c8c9ea61f3fad8e85d0214bd09590e57e20611bfdc0fdb09aa974c8c2c39839d7c9fb19a033a6bab3fab5087241c2725ce3ff3709f2746954a71b6a58fa3d78e12d354cc520f0a75740095861af0e1f167573365efdcf3577376e2273508035a4c11d162bc265131c89e23b13ec4a3bdccf99c2b43f5b560fe34840bb1b70d2e21e134a98f3440a72c7a6e0cc9e25f98992454364397f420c1783e19382eb24496328aadc98cf437d5e678a2f28ebd1ca5296ceee181d6e191ecb3c34b54259cd2576b62b04ba031f7ab277b572f2daf5c89e4e3932003777d227748c1abb43edda9bd7367fa4c885a210db124138552e000b8d8e748ced43eede885849c7de21e23ff0d65856ada89f3ec1407ed72c5107331b8a505c8e4694b302dbff7ed0e5870354033159264866fee9c4f0eb75a2d6e96736f88c4d6e2a925b67f70495a02e9c0f8dea12d6860d9fefd203f6e12825a0ba8bbfabd5569e7bb71ba6e627d8e3eabd041dd733da2014b68fc9f09dc7c0ca1ad366db80e0c42c60d56135659f3b175784c6c8b6ec711d013747030c548fd0dc6489aa9059fd065853352d69a101c11de88527b469b7b4a9b7c2b5517f3432da0051ca5e1f2cf59703833c651624d6cd888b8b4b953427292b0bfda063a13c6f9db9df596b7ec440bc640b5b1f4d1aae20ac7dc7625264ee433410d3bc24200b277263f0fd94a9d9e1c51c7c0eafb2ca2eb6b73c6d053a1710856230089656cb10b6033760c2acf7feeed160c6ac0ad2dcf01b00e757e751b972a814da1ca3d42c5d2a0e5f0ff8be16e92cc79315615f28e5e864a53ae87099f18f9b6732a42a50b35ecb270d18fffceeed261c34648c45eb7734cc0e82589a3861f8403ad251527ce89cb00558f8b9a9ba39f94ae2e9e711491f51d1abd404a7468ead47a8f47985b51fe5cc44355ac9ef74e1126b6aae28f4d5e421af62dbb8a093e37e37ce1e2858d35809490c4e09c257ccd51ebd56f8a6bdcb116c7cc7c1e4b037a74ceb2a64244674c0fb74b9f794dffdd0da42f2713e01678e78a0056088d25247bcd4e7fe4f0ca95f3b0c84546f1031072cdd354a6947103e04460dd78d371e2bd355f0eaf1d86199520fe98dd97fa4eec0aa40a739407fef4a0b4dd46a4f64b44f004cdb4e98984c907c1c344a0e039f0bc2fa07a90d93e87381cf2e8f77bd70fdcb9838a5d72843fc49ed5b5cc640f380088c796bf3e876cb434902e21d31fb5fef6dc5e6865af4430df0f16ec043424817510d258b44b0b33e57a9fb4f69155d8a8734002e53516a24f0654f94391f6702dac5d5a4e3d8e7fd0d70d06a717200982d37266d555fbf68e6fca3306d61e975ad7b6c55a8c6c3e69f56b2e3f5974c55dbeb6ac9d9a1c0037daaae69f6bbdecc1b3b894c9657528f9b04972822d0401473cdd07290f0bf4054653481f19f4a159c8c7fe463ff88f8c3821860d5c0ec440a2542d160e903089e176399f58a5d724d6c0ee8affedf4446578868a90b57b40d4e330444f3e9a4246ac208e5fc1b81a03e0929030701d9bc7b66e020711d67a4345fc427613ed676c87ec6208723f525ad30aee001844b29643f4c210b4d401a8d08655adb1439b4e0713a2414228b936d000ab14290041bfcf44d80a427442e86299533039bc85463dd7284e07936dad702959a1ef8f947d0e130e9f1edf98863c9ff92717f2ec3673255ac224062d8dab88350fcef16f6ceba41b755d2940a8a142950ee48c46482094600730cb5fe6dc8875de64a3c5b71dab8056c05cf849475c54783b0e85e72917a8e6900f3f8d0a8143de95cba56d347541714799fc87f8b72fcbe3eb78119337fb10a4455f21d8a799e984bfd2f14f755c6ad73e4438e2ef12d0ddda699d72586af11bd9618fef575edc24f31dfeb8ac6659e30900fb209330b38ce1df81936c59d4dd911c3a025d1af3b1ba827ce1104b0e42563652ba0eba2a0ef8546029b00ec1dc9a99b687ff034e858dacccb484eb59fd23780fe35830e8112596b53ff4a648cbaaef992c08a2f3efd4f063745f80c163ab5af697dc54fe37d440d6a85a6c0643ab2352cad8067ce0eb59bd315ce151a66a29438202deb6bc954637c104f51ac074cea2e54005773be881329ee89f7e89761ebedafcc2ec990fc1a4b6cc418640fa4fc8668f7a50962b77dd35bdb62977048baef33a460eec8f595485e0f0d00582d1791a04950e807d1b30a85f67e3eaf2513f8a2ecd47dbaf97e67b885265756108f60dbac7f4e884589a5acf61bec81a564d70814a588bb2eccf4dfed4d7fd864754e79edf85695f24615a0cee3d173fe88f106a79b0102c61f64f12235af9208f28d70c33164c125b06da0dcc518b321158baa54248e7145545ea242e3a91428bc1b986eca7be150cc5aaaaccdad116d8478190d60078807b12ddcdeddc3eab1db015fb92039cf98e97d0acf3c30aaeb7834f66ebe946749bc0708900245fd7e9d942beeefddcb0747b4abab0b4a0ce2eabeaac9bb8ac74bab2391c8a68777d9b03a445fc5c5c53f0a8fc2973f36da5989991ab77b00021cfd1388cfdfd6cddf7ee9381e0671c0dca0c589676033210bbd8b226ef87ecba77ced76fec30829251f1219dd48033ffd24723cf8008dbf55defcc40110da51b49f268af47fceb74aa710b72684605b345ec419d67d170a1d4138e0b774fdb433364b0f73be8611ab24d043e01b6fbdfc53ec748939b009e4fd55e8af645b16006e6027d17a7ec32ff278279be74c9c47e0c27a3bee42f5c810e6db9fede02f0677e6fa9f69221d6246d25171c1557740bdce34f82663d472d405382078faa5536ad1eaf45b42f509b407e639ad7c103a57c39c17c06cfea7e423c44270fab6cc40052fb94b1dbcd82826b96e97840f9c7f6409006bfa61051a1f9c877f1490a17bdf2832a418253189bf8e6b84447141079b6254c272bbc6ddc7371a134099654676de08627bcd9dea5aa6773c02cfbca8940ea8ac86506ba2d51b884dcb7f846633058870f0bfdfe855d60ceba0bd79f92e7722ba377a05029e37cb551e3b8c1fba4b677802f882511bf13d1d05dba732f55e9bef53781e564b3714cded0dcf821ead4578d66ebc8dadf74d195fc84eb0b10fdea6be4057b0cd5e2aa7573190b417f74b354d116690c5fb68c732c6a6a8dec755bcee6f36674a619660aba1d4505f5229711dd20ed12041a7373b035bdcb4d2c5cf68fd4f341bc2757d33822ae73a0418c1d6a1285fc45570e83fd7bcfcc0c320fde5c83507074e31fdf2e5e638b54163f1067024910530466b87edd33fcf7042bc7b8a941a09b641891f042844a2ae526d04f85f3edfd1df48563b093a9c62b561a7af2e8c7144b540cd86717d363909d4e1562fcfd0cdbc97f9d34c84bf9e34f32afd9c1a89d789e0bb45114aebf2f3c30d79a472e930a26b183e295b1fffeb6a770e72f1cbe324e385603a0b378b0dc929375bde0a182675b1e94edffb4dc996d9e474283cbeb7a6d306e47723b990f002ae4d2e18b82018bfdc2ae841538c7e80d3a3459da2f824aa7b4506c4bd0f7d4c4ce1198297ec722e9fc9714463c0036a3801961a29e2614145bd010b60a8e2cae395161430872a7f552f7e2e931f4ce11ae6ee7de44f746c2e0ec5c2c49456cf1899c7decd7fe76635188d902209bc294924b1d62601095b46bb91a12cdaa1a9f927ea35994ba956e266caba92988c7c3e909a05e5d0cafe295782f96394ce4cfee5270e0887ec6e8987856228cbd1bedec55ea4131e021aaa5ecfd2958e99dad067335b40b47159607aba2f4fe8f75426fc1ea0b953cbf44b707e96c72f88b6c945fa34afcc66d4a6dc695b985eec0dd083bfd13b224baf1a11478c25d5e805001662ffb7c0fba330fec56e5a3fb88e2e2bba51353ab215367160c0ec6c76bb9c4eabe1e1566d5791de6f526bd7c69abdbc3646bf169c38e1e9e175d81196cda8bfbf195d46c20c3e756043b9d5dfbf5548c03aa494a102c3ba50e4105147b86c100573846248fe81b09ea7c23fa4aafe6a6f684a807a9c3c9f9089d2bc97069929868354834f2c06e9983ec01d0bd763b3ad084e6bb496229bf15efa85ba33eeb8f74835c9b5bb993c4e08ffca2219e82492aa400d0c7c7d2f707e4df9b78d348c5034c1d1ad7729dbf6d8af854f6fb823f19ae563e4a4f5fb496ad02e01a41192bfc1e918c0835b3a93f0b8112e266bb25a732a11ec1119cb2be38f20f06e16064226cbad63527387d140c210fc5d4f7a84d4c5b8cce4c8f0309f6d2fc31b0672864ddad848c9831183252013720289aefb5080528d0d81fdc52bd24956164d980992d7e6b75018ca17098ab12758ec61b386b68764e5304fa7b0259046a8c820dc1f59f6699ea0a2d5ab5a9aa04f6c1d108d62f6e787f48363672e96fd6618e2f5a51231d47f0970b180d7a6b9c5a4243f89ca3877ec40d118e6f6f8ae294caa33f0e099506c3138c1945bf0248e5abbc28403c79fa82d1460f48b2603a55befff5d867d1dbb24af65833123f734bf614d5b0a372df72182fff2cd2acbb77d5e40b62f8fb5b21c833f7d2525d516f23abec2f98067fbab67d3eb954986411c2d69f6da3843aa6ea2eb8627b9505746bfe8cc800712bd9677caf1c87d5f014b25292fe1cc29ef4fdf89b6dfa36bf044ed3743eaea6024fb3ccbf1ed188a6668c2d0b19bddeb0199d9502abb7a250ee42f9a6d5a246cfe3a88d42ec80ee176b5822a5b22a8aeb1e8fe6087c32926b4d59bd7c77034cc0f1dd9af431e6698ee06d8793a96be0771b96e745418a191813f34340c2881f62bcb20047b0fd1d17d04e3ff34aa0c0799a54ca71dc5ac4cf0bf809c5ff51fda1fe3703eff909043bc0e035d839affb59833258ddc7d84e3d7666e938edc3909c7af4d67ef95795cca6968d78430df1b7b74cc8f36bcd2f9e4d49be72029469ade82d9638c5beffadcb0b7e3cf0eb6ac05f76fca29ba39a174793acfa68a97f8bc359dec3812caf6432087501d1a3876978707280dc2bff96090972b0501676b97fc5b3f1f7a98a794a9242cfe3c439e82fdd74178b1c2561ed5a0dea3d134bc19f2380a1bc84575a7bb12dcce17907108490e52d06bd97bea11965adb6bedc03a88f2c41e78aa788ce77a992f7ef2f3e998eb0367f88896bfa5c51f1d4f573683d7e4531ecd7d8ec395c31fbfdef6916206921fa8b892b45a35e9c4be5db2b72c7c7a5940c318c91586179f0df70c43197c0efbc86483e73f71358b3f1d42fc84152f86147c606f1b2aaeb581eae1446be3df8b115975d442303038d7c710ba4d21b480cabf5f102027b6fca72958587bc3e0933b2d35971a5ef33168e36ec887a43e23d941be69768eb2f14abfd2bef11b135baa5bad7c64e81668bd44f6e43a2d7600250f5b161675f0e2539684ea994bdc84d924c3829c8c0ff90d7c613abb7756e8f91644bd25784c91d6747cd9cd06ef5d2c9181ca07d188e4cb4c8dbcb473bee5f1052a0d6a3788fd72b56167cd0cb9ce8310803434b281050ef6570f80d0afafe5979804392ff7da79307f7c20b25855a064fd5bc84a097e872283542eee33242da0eb9f3f83d049d6b188e5eba810f3629a611c03afdba705777d756d36f3aa6ba8dfbc801d1f8071f8432fa0b6a07ebb923d64b68cb5f3b04ed3c3459edfcc3e7eb0eabbe8b0109ff2e46606e621b531fd781de588436f6fcabb81fd56bdc8bf887d7e1b7dbfb1643f481a683070b611e38558d6577ed38c25719d3c077c24ae7cd93e680c08cd947455cdd763d34706f7383209c884e2bde6103d6f76e0df72e8913bf88f34caaaa1c470d88be6e7119fd8c44889e19f70bfc943be8f7868bebf63fe3ef9b62f1d5e0c1d468a4a75a7df57cede7ad85d1afaf44f49284846d50709f6615e504460b48d720c419709a7a3951b422a2a20072d6459eceb07b489c3b8a5c8a414a87d6bce0e5db95d0f0db7c945db5f94305cdb7e7ac22044718daaf8a1cfada48ccdadd6746061cd9e4892d3e3a43544911f0addafbb0f0d904338bcc2f34236d8d27ab32bea5fda8b84522c502bb4d89b1e59f8563bada56ff3ee6b17ebf3fffdb1779e90767b408d20a9fca41e1c9dedb0b9c569f67b66159df538a7dc5245dd00bddf78cd7bf83e1d1d524a6fe95b14c947e1ffc2d64fafc1cad76f3a23cafe0c763ae8c4bdbe2b0ee694e7e85027d187477f8edf0ba68544cd65c303077dc1e23d64d0385060b08443dd1fd0e2303ee6fe9a0f0e2599cedb750592923419809c41149168599365fe164fbe1e8fea7c746a5636d7234def88f710afa4b9122d22b677ce590836f67ed7f399810ebf794c0ff7a40636ffc3807f0bf2296cfa1506f65a989d2e6827d1b7bfeacacd3bb2d4f67190171518e8065e6811de2c990d9c20440060b945bb1404c3d1e7606c4b26a77dd0222be965352d1c84bcb0078bd78a5e5b454178da413f7e7079d3d9da25b8e7348f5dd286c9bd5051b04c95633e2bfc7e7a61292854d7d17031377821ee2b501a6afd35b299232484d9e2b45028ebc314612fc60d40385fb8020f2c11f1e64d3e430c300537954a4d52f7e072633b5dbe0436aadc6f074013f0969a96834b54c3e65647694d433051bc1cc3d3c5f1570a21e180c1ebbe5ab926cdfb68cde6720cb6e6fa59746b4739570021e7e8b513ba3289599da75bffd44654ab87ece2315fce28a5482460a3ee7e2039d0a82f622e669adfd2599300a7938036e129c94be08d6670e6c619e820d646fec001956b39301edb85f286484c92e2b8c3d30260a873ae0b6bf266976c3db25d010050f40563a305fe3396c19e9364a9d890f4d3b0f2c88482be8a405b5b95519fc76976c45be1d945bd821f9b8e1121b71d68f8f7a6e338934e69296d2d82a086e7032f59ecafe67774e91810f65d073f021ac240d36272812bdcc0438384a6c7e7d304b0b8f6b1e8a0f4a39385564edd7055d4704c6e64d26d9d6b6057c59d4195452f9badad82654ed49718eef8de4be81e54865ed62e6e61464f0acf8d6f3f6533c9bf03543ef072434b847bf97a529565eb290815273b6f86fa0cdb30cd10821601ff3987840bbe3ee7c0fc21ef78fbfb1d2ad2b97707018e637cccf1050e33641fc78ebbf90d7945c36ff5864f8f2b82df28673c76e8a49fcd4fee4f85eb1064dcca7e0f26f4d9d91af1fad3cbf37132b5c549ba1510178e1c059efb6619cb45598847b77278c0bbfba45f5ad9d71c9ec3f06007ef279d5eb7bb832fc174a97aa14cccb89b0f0b512459ac82b761c57f2586d1f8198b19c5f518e40bdb9c9244d4881bde83cc26041c138d11992b3e3b275fb14fc767d6860093c37d8a9d6597d9dbe9d019622f52ac08e99390414a4098c26c5fbcceca250799e14ea0e4be621d2ec828f5b54ba54058a1ef1b7f44af3e955a1397d061eccb53348e9ebcb167cc2e06a6c115a2da0b0f55f14e8bca5a1656a34d8c452c15515caece90bd8c4d764bab380aa535ae93c3304f0e2f13d7302022650bae99a23199081a828deb5955738667c3bbdae78606dbf9d96dc2752589112dbe8c594665b900969fd08c158b70a83a08d0dc9f490d62bc0e5b5101e2f32bbd23313556e0e5d7f9fbbc275d043b9a837d3fdb7215a2793aaf465cd57aecdda38c3154e30ce6ec10d700e8dcbe815574f08a79d85ec78bb5e8a0269b12c2a4055c09dfeb1ebc1172d320141021cd8b14d5aee843169d43834c823be65e8d74b98a2feaaebfb0f55b5b35e284f4a93a6e1900f3d234ce1c71f66a38e0bd22d0d35fcacdc61171d714c72d91b44cae9030001c6b06beb0192aa22a44c58bd4b2c9fb308bf934ec8b84221ea075965c05cda31d151aa2e209106bde6eca4ab4cf6c787532500fcfce9ae6be96f59732a591cd4c8ac06c40b996633a68ef3da75e65bb36a93cee1e4a782c5cd06d7fa9c5cfe0516773dbbd3dac82f992e1c86ef0fe93883ca29c7c19e1c0f754859e388019acde6b3d722a9103714d16dc62a61d76bb583c44e88f57e762c9bc7537dacb0a6ee92bfc1a41952d839b0f45ce8ed0575bcaaffadbc17fa8ba6aeb35c5c8b8dc8c21d00464bffdfafc6952e64f4322fb26a860dab46838be5086b5776c55190affe7569f0f6c0513ffce22fc465c5b1ef854c729af3d73ebab37fd8afcee052e23a3c392b5e5c86c58398e6cd22673bd998fb7808613c15c76e474cb305dfbc10bd37e8314e9bf5fbcab1e589e7cb2aa58a978eff824ebdfacaaf05cc7ae5b663d6fdd89d465509b57f6147b9349fa78ab19dd0f89d8e185c39163e6146c1f3a3306dfbe80a7cc397a46ca9824748e00211de1883a691dd73cb106001b543ae4cc5125b9e2e0e538c728dd8443fab97d2bfa8f0ea938186f3c1510a7c36b252efb185cddd7aa4f726a7cc32eb439f22a0ab5adb910e385f5663447f3d7df06a6ab5222072c69adb29068ebad421b77ca5deb907fba9dfc6295c29880675e1d822da0446d36f1c1cb8edc7dba7f0b4e7bedc9869f70ff8f8ce05455d9393e4a2420dfa805ef799b40f69d752afa17df2204b418a09796ccf8805926acdf182765291b99d58f762e8b67aa04d84760cb3f9bee751047ab497161dc3dea34fc8cf134874095d742b5bbc5234bc58a55d239c33cf3c71d1c13b2fd2c08cd52ace8ddb94cc076b46a76afcae7582228383dcfb49ef8133bbe010d528149346ab7aed2894f74bf06cd6f63b173d055c6651086b33a67163c675f44fd0839fc7cd6a12cb835d3a7706cc7c3cdb6c7c44e394cdaade6b84d17ed918deb4dd5fcc374126dcfb2b03795bdf6508264d56ff454ae42dbe79147b5726a6e7d61555741dc29f6b32dad814bffd01c5ab6c4e1ece03c8b9c6d28c3503db3e1ba4c521c5e87c7469911682530e2b7db0b39bfd82bb71a667aa4ce31b1e3abcd7fff1c72b37b9e47b45d11beb8bc4303887f06fcc1a76c98910e34787b5bd21720bedc44f76bad2de2b17b73456e108cee146e1fa9edb777c6527bb0c0ebb91ea94e6e386fd1240338fb2eb734e78122bae58e1ced1bfe9438c71dfe635c4b48e69d04584e70b0f921b392e7166d1408cb4a556c6a7588bec890ad5eb3b88e4f5e87f6015b717ec6dd815a369ce863e0b3ab65f4861f5206f75ddfc8fe48382d1abed6e8831d919227372c8c3788998b44da61b66cbeb6b568070c6aa09b34b1a2582898be304869431982fd42b1caf60fdae4e6c12e1ff2031499d076f5fc4ad9df48c9293ccec5356dd92ccc03cbf9794c6cc7239b810a46082477bee5a83a962c0301ae7061512f73d52d77f2c238763ab4698752a51e179a9648e038aaae70562098d31df9cc868ba6aa11bbdb9e9984a571666002691433214053fec7bcb755a214d5f4b696a5fb7adfa47778c01aebdedf252197af2d5da38fd09f27b6861a3620951d7601a24a11081284dd9aad9caa85c5b971bf62dd100556a3e932473d3cf059fcefdd34d437a3b5aa194d5f18b40855b83a25a35473b38c24b1eb6acf897eef5872bad2f0f5bd8bb58f0d500c6f8ef76f11f17b93254144fb269fd43e772834bb8c6ccf019b08ed47f43b9427e1ca0fb19d27bb61b84203ba5326dd260f5864864fa9e4ca4800ce2c054e0404f6865eda585161a61e613e9531c740fb0351a21c6b5208c7db2f4bdbbf9622e394bf9e13384f318dfa8a9a9f8975d52d58f89a72020fa17d7d8fa4f85ec2c3d4c8fd207986c93ecdd3ac8b388d729d30babccde8dd02d5860e3af18a134edee12f100d4709d51b6a1ec9b4cfa324f849fc3e526c74452bf0ebd4a7efe91e3221ec0127d22302ca9d37f18df55fe928686b2918fc43c9d6a4d452e93d3dca588cf68a45a398b3b2e31c05de3cc55018d32822112822c195e63acb99f956f86ab00db82d149e119b836243080cdc7e40817cc9f3df4a5a0d540a7d8e2796075dff1a820a13f05b41c1fb8b7705bbbdee6be35720b276b65e53a51497272f1e9cd5b98339704ea0544819f8ca558b121bc16b42e2b8864d25a7013767f6b5d9ebfc609d33628290202240e982768cdc9f734ec702b90a5b5187bccbb1de0d1905ef282806205e90a67a01f5eacf3ef302b285773cdaa0d08f5dd7873d85666562e99128f294d9cf159bc55c9c8a28ed57e2261ab13a5023234b411babc1ae500820f1084cd12317b7df80101b547873caaf06cbee836d10ed8e44aec3598fe126d1b7e65c70c121741ec35075d48f2d80ff84ea1753725385864af4ba969fad521ebf30335a3e38cb82710e42655470ad2710ad1ad280cddf5b40f26f01c4c7f49d1b64a5933e8fe880dc3710fd613035a3290196cbe3b8bf8ea5add0b42b10c13ba45a5fcb2f700ac6ecb2c50d97e6af9f4d76f16eb1e50fc6511dd700d1c972c35b8e62904a0d0d8f64d31ea2b91e4bac29c7c6735069aaa58a388062748f016a79a8de0fbb035d75cb9de73a6b6ed58c5c947df8836d05e5c0d511a82872c046fd4761d1d1e83bc0381be0e18d00936d29369f9b5938a92201604a92be1079f8e91e7fcf7cc0b4565222e161fd3c93defc85fa7816d5851258dda5592da5283eccfe96fce10d318f520cf7731f43930531437d3719424a96c95a620f994280896b61106cfc3e7e3baab02df2c7cfc483a84da47e73e15c39d0e004d755ecc4c71cd50b169ae37f3bdf0a6982498260983f5a301136bfe63dc4874acac3cb626cb3a83abfd07897e5062b1b1828d00377d086185eec624f3cf2819079a31186062b125274ed89a9ba6be6e8537cfb51cad84c3161a08b38a5f5d7e700c1a103ea2f4f46f2e1958bf554a9ddfd811bf375ba1da29350184d433776c12ed2fe43ca160f46b87aa02f4978d89fb58342d0eaf82b5c452baad8de6a2f70e84daee54b27e1ab6aa19144c4079c5c2f971221bc087ddd8fdd2f7abc589fec97c63916a1b7ec6ce359bd10b7ddda10d52e1941a2d314f3fc21fbb6cb358bd6b527a23a10349b697e7ea5840e4ad22e75249d0829ee8249e375b53f611320cee8ab3be62723f6f666462405f61635fa088bc299fbbfdb67af0a941a1ba0879ddd5f24e0832dd27f4d37a2f3565b0f744ab9ec6923f0a35783636a43bc0a7a5b3aceb60b279982e67b2b43fce5c3794a88749fcb8001c0d9c068f683355569aad090b477bb08d242bd219b07b8f301f7f328d3dafd750a9ec178a10ed50a234f203551934f96d9d82203b887a1a531dfd5021ed8aa264696683c2442dc06e640f411e99aeb25dfce6883e4b20e66a12848533f9e4c179e6c667b1be8cb7a68ea137e9622c56c666f08a0e78f32045c7d239feb2ae61858333402d2600b2846e4ab26b42940cf9a3b815c12f56cca8b41f172db2c0128ff80d9d5772315768bcff19af2c3ada97776a68d70b21c6b972006f8ded1e71b6dc17c2598a786b53dabc99ed86f271dfb80ef630d8697c0c37179145f2dd851a398cefea9703e68146662d8844cd9d1540a4fb9acd052cf16c56994ac9e9c3cb4097759579fd3e056a9f03c8d7655363896aa38bfe72598aee468bfd1c9f5b4c10ea189f2dbc33f7c80fd45e545e1b9736c8a047f2700552e0eff2314c766cb61972041178643f4e23d5c96fd9231205d38e3480f56d13c19c1e2f743e0cbac20d3f2576f8d3793040aeb255de3662047805975363c6918ba5f8e3c80757bb282b123dfa51efd8d7b43c5e5dc7258c9bba0f7749b2ad5af67448a23615b0dcd43c559ea7e74b367f23dd719f7bbe3fa9ec5b2a4a82af9b36608f8e9122e362b612abfc6a5793652aebf021c118145c12a7029649743ba3f2a21a80df5a52a9215f584d194fc777bf9d389f579bb0e06a3ee8b99a78b36a5f15c385ceaa92189261e177c8eca89489edffac2281bca61bb285fb7c867c75a7458a331c9af4465541be1873ebaac4197b89655e0f669f6018c421dd2e5c6cadc2b0a7d6e657b3c5e65a95ffc87d330cafc42f01ef82663b234e08e5c541ce1cca0e17b861bd7a743f4e68330b88444512744385d6870e6d2c0311dc257dee346ff47e7560ce98643ca316f5deb3af37d85f930bbb0ac671cfdafa36ed79da4edaf522e0464e7fc9b5547ab22b1423453a55406c02326c3ae636db885b40ecf4ca736d4b09984d75077e1f1345c48dc710eb40f842c8c260f318ead01c588e62cc310acd1088aa687716fc163773cb298f124133aaa4023463f0cd52d2eb7f323541877ce48cc03f075fa2591790da009d9975f94af8a3ae6f123fe09acf17892fea827c4bf06eee9cfcd1a76c446bad204bd3a66f8f26f9430ffbea5bfdfe0bbadcd676e98dd58b65576fbd57b4efe91efc20fbf773197bcd6a68f2f9edc33001ee6bacbe7ea6fecbbd36f3faffe35607d212a5fa8d6903962b5c3456c1f95f4bb285affc71a3739acfdf56293349b782752e69b2a6f0914c8835ef6bf7da85b4467e2e712ae674d5b021e0d2157bf7c6f2f29ebe957994f41ea2f12d3eafad46e31f72fa7f0a53994e96b2da8f49bc144e1e602cf07defbdef28211aeb6a16bc2bdcec07c5a3c06ee39a07dcac45d231e0c7406e1c3d5c94f55fe2947ffe0ff80049d03b24f147df9db9f6e871b027e139339efbfec12e960af07e90f257e142a33dd419776835c79a3f6bf188f20c79e303bf6074ffc1b5721d8814fd35d291e103b4bd2d1274e9a5fb8e34afc837a889985b76c1db0f63a3cf30eaad9df2f0fee218ab28175e53df0edf16b4310749dec874e288f5dcd8c47d81b2b7c7f7dd3b236deee72dbe50ff6ce4d6f7e05ae3eb9fcb4f0bbfa74fd8187385fee7cb829f883badfafdf0a27fb2af89afd045efa6eb072c4f8a8fc90560176a934dfe989b520b37f8fd5eb05e386da7f31a8ad256cfb0bef06f9fcc31943fff7b6418936c4301ab38a3f3df88e3febe3985659fa7793e992c1ba53dc53c7764c98a97fedb6b2c7bc8e4c28b679544f455bd99aa6d8867a1cf3baf876ec20eedf4b51bd848d9fdce0228fa3eec80d3ec7b8b20745c408ddefafec8f60d59eb0e8c6db91e75b80502714c93d5da526ea22c010339e3f9f75e7830e3f99d775b08c79da87fdbc3ccc9a72d7c13cbff011a8c942f504671f85ca5631ef43879af78afe1f48235db9ad71e3c6c343f07c3bfbca35f452a904b8516d344c433b9854e6de32fc2161cdee6fc3611e07e5462b14b6a1d75c9907c53ac2b7d8ff42299377f5dca0500c345d7a65fe41c90e9f4dfef90fb3a09832bd2099558e52ba3cb67077e741a0ffb8f96f3706a191e4ee0ed93afab2eb85f407682d0324fba4998baa08a3c30db9adf96d5366fac439dafac65488a173bda2396e0899eb46ccb9a8689f19dcefbe48e50544f3927366dc2dc327fe471ebb031ede7cc1788ae5a8b394cef2cbfbdd3ac608f1741895c6cccd2bfb64f6c94153ea45881a4ec60ec70234bc7be0032f783bb3e05e88977d4371bb8d8f9b1a5a01c8ed7d20357663f2a2fc3f8b05755fb3fc7f28dd840154385883cc606a8cc6c4321ec8bff5643be57d4c24309d55bbb7e3f36d943194dd430874266be3b33bd2f463fac2ca496aac392ab011fe6371ebc37c46a8d072ba49e6a6489e05813f5c90703a2a6bb7867feef1668dbddaeac7582ab7ff09bcf1382e2c4ec5fec1a89dc99156fcaa7258e8866958450bcfb3e95e7db658450c3aacb1c3cc30e68c7f1bc1abdc8e5f10ce50d8ed7ec1a8d6e734c9dee3b1950d74c832191d3dd1dc3a0cc01e006616d6741405b0aa9f6243af1a99c2980fd7ed6e64b7c582d338118115cb9523d0b6bc4b6ddce86a262bfce063ef9ba418e6ac387130cacd1e17a298948699c05e675a783c62dba8b321880bd34f80baf5787956f95d1578d100cddfc0ae14fcdff406e4de216bfaef55e72a21b7bb42408e44b06277493843fc4c9403c476c90717c41cb6b8ef53791f19e4e664d750bfb84c4a229bdfd60c227a8ab2c147c26e600222885df06ac46cb27b039dd5ed162e727e65f785be873cb35aaf867ff6eda1a8fd5c01bcdc8d100b174ae08ed6e21c7cf8a8549a64ead3a0195bc0fbda4547da2c6fe66af80bf113aad814b1cf6dfae1e8c7ab59cd2b3047cf7a9ced69d061dd56f34affbb39207e5ccd53d62da621ad723f4e2f528059111d40dac226b10c9a78818501c2e6d11b069fd01b54d95d1fd5c617e366e4ef5a9e5a446888f454b6b39ee005f27a25ef61cc2f333c47ac5b2c27be4e766390518f4aec1f1e267e3c913c341cd6d1c92b70d3b6f3d9cfa9f056c484f74cbfe109d2f0cb7411e85a52fbdebc10550ebdb6faa05ce227179e87d4c6e4e37594233836bd39f6bbfdc96cb955bb66ecc03500f1e1ad8f857fcecc2ebf23a2dbaa06341176e014937d11523793d038349301c173f4c93d01a03880a0bbc5762b9572fffb0c38414d85879d7f8d3f7089e5c3f03899deead317c57464ef35ccc2c2830ac2156623cc79a7ba348c8b4cf67b78db3ea1f353302f50c40f3263c3d7a6f786787d4132fc5d73f94864f463e0dfa4f817fe0126ac4f47d0136f38b1c34ffc57813f37c8e1a5f4090bde285af4f2ab1bc2c0380525bfdd0839547b92be07905b267d1b142fbbd64b02dd636b725c1798bf96da30dccabbe69bede0788232bf537411496a8df78e21e17be7be3f04642932296fe5bd4dbef218c6f548e624ee603e8a5f2bd586f851b522e426726efc0be1f709eb15b684a5a1f7c106cd078681c98332f3836f742b7dafb2ce01cf2be4de60e2b2a5dc05bf01d8b80cbfb9702478236c44eb81a92d0f8f0f61e100d2a9b75e7ef3564159e30b3ff15eaca17af5f208f403e57a641b73be1c40e5cf0d4e176e7c56d720cf41e7298eb9256911e1db860dd74657cd0c3c8e757bf4a9bb7a7832e52946e03eb29292852cfd9a11e1808770cdf84845835947b42a4fa8d10fee113c98acc01dd4832a99ae76dd492bcccadcf15664ec233cf400b3c6d4f1d5860f9dc137ee68993167efac27f18e5ed44b3b5e019f763aa8adfd8bfd408d33f244f734eaf127b73867ca5c4f94cb5f56069a78b05196f17903f69e5addfc27710edd439a3f79bee5799bd8e25ac17001e4b0f836d108d74d5810ffee07264924e3ae98277e672242108235c902651ea5c08c25ccaea9befab934a1951081b1f7699dc70c6d278dc775c614bfd880d337f4404f44f1ee825c8eb4fc3411011d109edfda2578422a478de3967d010ea2c9d405608da6525bd2171423fa7d7d6f1ce8a4767866184947c06582d7846e93e46d2321bc73acb9354ae3a9d14cf7249b36d4c349690a2863da1f3ae3a41c7ba87655bc299f047edf7313cdfefa7b509c2c4c32cda273e4a1cc793479cdb4cff2016ea9044dbe4fe1a0f25ec2cfdcad8db31a970bd0f99041cee8bd4c0042764a1eae5ee51881b42189b8c5dd70d87c27f3cddc3029fa07871b6386d9e1e9953f420fffcc27781efa4145533cc18b623bc5702d0c0e133bb92af4f0aba1b09d16089be399159efb0980f7adfc2fd71cf2adcdb01a3c83bbe12c885662d0d27ea299973bfc0c0b85014cd1219a540173e02b8d88c0ad8b96a96e9aa8f072bbd20d026f4524c1fd746d6cc1e503e397a37b4b5ad57d3fba4ac2236b46645847519deb301edd0080d4096c60117cef6cd8b9145226a7865fea8a4d52286886383783742fdb15a2f57b7899667421f5612b8db7a91e0d68c4e8b7cb00c227a0f700e35e32948be40f62f6bbcfb9ac244635b3526e272614616f95f03cc7bd4e4a459b0317fdca0d2d3715ecc47944b0ae874c90cf0d03df27c8f60d9c5ce52768eb3bf820518ca32959f248761bbf21d3e6b4e9996f9f605247ed0822381c04a0c05d93b2f5343775eba913cd523e39a4e279043812f11fa0f71076a8d7474f99f79b4db62ad675495f3902cce7f802908f101f7edbcfdca38110033fc97709d7b2edca2aeec54d599cc2a5db86f8e58bd04bec040b8470daf854eeba2fb930571409c9dd7b9fce829f926ebbd7547620819a0f617e3bf3d34aeac88b13fcd4be8182b61e772edec7fd9549aa58bcfe23221cb1428b749f3e05a3edc7807f2493e47bc34d011e2a5f2c37ae624b182db9d67eef0b26cc87d55d926a17fba17b0f9dd14f77caea0ab82af84286a352c324a20b49779aceeb45ed24d8c2e380fc894235b16bf39f6fa321005f37d01f95a4dae8e7ce2132aa1ed7bdd45177c3b412fca272a867793a51f2b736bc6c6927c103727e3eb2081254083d74539d0cb4792e16e16a0f5a7b0533964a31e851c5dd6762f6649419e6fb958d920515c0ea395cf538ec04d42d7e4801f3ebcd3084cf6c89aaa3dbc696cad2561f5647c3ffbfe610d6e0fbce6ddfe6ff99078fb9c77f15afbdb10a6d4f1123b5904151b3e6819364c360555c38442aa7c1c8bc3cc5b8d4853b964dff0e61aac91c20750d557b812b72e6effe347f0c3df8fb4946b53453ddd83b351422d15a938aa6f186b4e0dd3d72deda3254fd3702fa9e68eae4d8db5b460882d45afd5c6fbc74ae44f2dfa05bafa07c35018dd4677593c3c63874e97ddcc716a1bb7c6b0a8d15214ca9ebac63335c97618e398e43f4bf6ce7c1233a550d4d0749eb7a2c7a105eaed15f852317924f147fd41972fee698207bf0383bc322a589ac1313b9a78b4a6193076f7290ea3e36c7132e41597bb555006ce90804e47d264601c8a4014e24e72dd6ae353a51a97d8e19382cf58f42b15ffa637f0e07880fe914027acc4d01ce5b8f24ddf3746ee7d3c4cb07bbcb2f29da8da1f31dfa4f5493604a07557d8bb997ab63e86d51724f72db36df521329d5ae169e36deed193fc0f46d32f535ec57ce0430e8e0742db6c52452cefb3ebc2233001d49d66cb9865b116df77d7c463dc6b094ab979eecbd796adae9c49fd887b8c30d0b4fba428f22a68dcf3ebebce88e08bae18bfd8b6fdf180a10295d590f145c9270e4809ca85dd7f5f089251ec57544cae907765827f904737a92664a285fdfdcfd32dacf0604def890a1bd7ce521ad91453b6b3e8c8658a3618d95503e1846ea38c1fe98a484e26d28716cfd0368af2c9efafb060e44c01a474a7fb969215bdc6ec1cb46f730e21d6c1c5043e51242b439bb89e2398ca2e3acc677c2fd0c04ccec57baefeaa99baed66a78515ade04ebe16865cd89b3b2d21866e3dc2f5f1519f9921914b565021caa1de8a2badf45198b8052b6e99124dd65af8b447dc6c60f29b514244ef69d8af6a3a388e2fa74eb4b789fc178d3057059638217acbed94639b6e20cb68d158b90712a02a2fd1431b13aa2e91bd91811539e636aa9a30b6bc91b60fd472ae6a6480fbeb37bcc6bca1c7c0339b2301f7542f58c7eb1a018f600fc6b4a8c1d9b5de11fb0aa54ec02ed91e1ae055050b5bd0db673255d0df283b4f9a9fce270f4e156de1f8ac78a30c6c8443f67508efff4f3b725e423dfece93d4486d19f9733c2f267e5dae814370bc0cbd0f15fc369c5c8aeb85d7797cd781736d47701ab5399e5308646fc2a0b2a345634ca6b4794fb496e1b9423fab684fd4d49ae41d655a067482f262d81d877b650a9e837a3fdbe3f2ed6479d258a940584ce6ad687a6c258e2c2c0ed8700a67a395600674b469d5b379211e7a8fee7897226ddeb0cb8b0a46ea59534a9a6a8e1756b1be48d81376009d26082c6d884a4d50b8ea8522b1a8ff70691ac704436e53c2114b12e48d51badb0a6cec07a8fb0b79aff247fb450646b08741382fdabe7f9f501d995f0d653a59cd9036bee1816d9d97e8f502d92216ca4a8ee6122422fb841c2b36dd57ee4d7ad40b0828771f0ba00e4780c3a0a05be8b34af7c98d214bdbddd903204773883ab8ad50e3755a68ce4a1ec480e22c4bb24981e2a0a492202f822a70fc7035f1ab51867a40547081a8e0c8a5ccd6e75c32be2b43ff354ff41b222d7a602538374c80dda7add9e8cbf29bdab4d642b9432d1d8213e086c67dabc40b3f5bfdb6c48b16a9478cbaa32cb5c057fa82e5b694eabf140c75a6d22d51aeba918535e5decb7b4d7ee190cf005376f0647ecc41b00c5a30cb20801aeaf2cb06e0249fed8125157c8cb94acf7c9a60c5ac8e475d76b79a7457671631c79c1875622f35c2f2984d583655b90ca8debd2c7359aecd26577598a7727d67e1cbebe3b9f0a5b12d297832d430e58797072f3307f85f564a3e8a621ff03b9d12d3a5752d27dbcd222c09dafc86997677e07d915e8ca6677b73b1fdd318907e780e5fa8ee0363bd8bb28d0a30b4c85693fc905f8c93fe61518495e69d7466e664145c1a5483fa689b0e27ca524a66e96ff8f72007d0b92f4cd7f5cd1a0af56a980a92d93020713323d4e92aa1b32844a5fd7a4515b7f438ace888f24a5528f05cc5cb41a2879e46c5bc05452f43161387dbdd74fdf58c7374475d39b63b6431744099d8969912416cf6fd1530ec76ace5236d28037976f63d49f041eb196673ac2347f31c5528082db84854d4512d94a27788e55522122f1d69bb4bf0252d9a6d5f83ea441b651559419256aad7d21968f39e4c57e9bc609c5a2d34e77724323f46acb0e8cfd67b1656c550c9da21d41b8cacc9ec74023e078b49bcf9440a45a09eb0a46d56cc84306ade04b38909ab3cf6f25cd2da57f14661867a95483ed22021293162d3e4c28696d7b91f2406aa7fe3d07aa64b5095407a1468c3347852d4cbe680370c25583fc7e328a662855cb397c63cb7cb67bc12da0ba97097bc94ab55952244424a665126ecfbdcd85408ab69fdd4191190ab5145f51e550fce49b4c634ad654185030c2845aa4be74700295a5524a02ce356ff169567f3872247c90df47a88be531b98d4ca97006b7e6241a90c3ce15e0a99150349bbff626bc823dea6d2d51bb7457c2ed3b7c00e8fa14acce5c9e7cb41623ff9a8ff96101bb2f31ec9da9237789cedef431d4f9dae4af76c8a98ab5f06b09884d2c60df6fa70f91bc763170c6a6b4ca4443f7148a3278dd43d0f2b123c96ebdafdb494ae2c4807a11bdd614abac40a3ec5a8fe51d8ecf64bc3dc623a29c01c654950efbfd61dbc8bab131cc1a75cc84f0466fa6fbc3d337a536e582e4488f85db87e9d9914dbb60f485c523f2c0278f0bccb6d7fa1fc4d4069825a5fd4698d85061ce223e398b73a71ee858a8c2942109e0ea0b292a6c20548e1328a1ca2cc5fab9ddc5d6fdfdb3ea82f698862fecabde45b030c0994d094d1bb8ce84be6e9007d676df8df455187e8542118a900ad17dc97546d734801c3de11b10a36fae0baa36bfd676e6084a683380eb0ff02540ae0014b347a18116bf982176dc65cc7bcf221d5f806b0ea85b53cc2b79c23caa2ba7e82d4d0af9a844d732240b1d73c29928b555886ab0ee6e06c3bb1968de056a62995c1bac9493d00a877b1c4c21d9f9213e95cb59e50885e3a973520d71e66c543e3cc1af4eacf5d25a2dafd9d1e3b4e389404651abe3d7b01bc1e35f02a069c5f7f9fd907438ef1fd0542bd3be89d16a40765b9a0da9aa4b1d966b2661d69cceb160cc86e9a26398ef270308306d10b58367d0c596b4ff8d4e1c644a6dd133a7034877545f4b4276c392b1a7d1044ddb4f6cfcfe948fa1ffea588647d2ac8163706e47f7593f37711b549c7c0aa118dd563d4d42fa7f7f249b6118b08d0c2d5c6bbf71a4e9f99240d6057a160b27dacb0c445f05f84401c37003c47b3c9a58411b2624372b4a830ff527ba24d7736379a594536d5a888257ea8daabddbe32c337e5bd7182408635715002fdc5a5deb05c39038fde72c03701c387209228841dd3d3e8e89ff09284f65a45d45a83d7b331f38f87990c9933bd8834d27d35e45125ec6aa076a01101e7f7f1c8920d80138984e3f3a2b264e9edee2d554e64d4d2c3e127d084976d8e88e81c93a2171301fdeeee3ca405f94d88958b941655cccc9bc8d559405a0750e658a8adbfc0747f5794884f18a29deb1460efb050878fd4af2b022b76cdcb7ad2a8136f1eae8bdd0f34da2dbdb723c2ca824b8bd29b13612b4e08d158bd4933be323a8ea5fea33f8e4a92012d76916613081697b63d02b1d1c0810d66aa6304197da6e3abdb24212c7f46cc67af481ac07472f8f1b0078c2b260384ab711c1f95dd634d02922301afc77e96ec73d639d675ae8b03f813a3c23501f606d91d0ae30f024cd94b9897087916662b7c45fc02c34d2080172709f33ce1f4f6fd53a03e24a7c8837f58a16f72de100e21fe6466dcda8dbb2d9b5237e20dd630abafbafa4b0ad8bfb5a146f35a10cfce9f02593557d4876b9c64fc91e1e5a4c904489aefd1f5a1e49681c96be6c2997abc0f935e25619f2448e172e73c145d88c8d3f8f79ab46e5c23053a954dccad83544a8d025cebec8467f296d061424ecb64424eddcb15e82e3bbaff240f835a6a699ef35e56d6f3665ba300b68b6e1940631cd44e7f21d433e6436e3cfe0dba5017f1a9b68573f40faa704b37c22987ddf8764f11f01bc4e624d3268aef1f98045e00213e70e4b629b97bb3c20cd1c27526da21a277c1a68d2022444eb3ef3fecbe89cded59c746cb80cc1ccee08f59d8700a96f7fe467076957f0b00dbdbc8cb5653ce8e8da705639280e969a58d67429c873d369f5991f44838e64bd66607e96e7964788377b8c2b16e85de5d5a23edc84ec1a6d3af8ed985c659bd9b63ade5646ade730d56fc0ee72be25697d7f89e5bfe776c585c598f8b66dc2cf3bb55b5e7c5ad290c87a17fb8f5ea924788cb17e29e0079c3da55272dcc3567d6188fd53c3774a2d5e4d34a7cbdc5add21c64e36801903581596845badc59b44c1b2e090aaf86cf81a1d13dc6701b76763104d575f1fe146277c107a7c403921e25c342bee76a7b3a4b1e0c8dc7beb18a9ab8b8b34c2332976646cc1daef04760ab015725380c235df5609eee5f7f16aba1cb3cd6e02ffec70f3d59a0fe502f3c46048685fda042c79fc952241ba4d37faab97a4771bc4ace8ce4dd230093f62753734583b4cd3e702f08268d048e6a164880d7b1ad2b614bd4fba6205fca499e711052ddf8d4ee111b4afcdfe631ea332b07b36196c4dcac1f8638a0e62869185905212c933b2543cebd8c177f0bc1d6f12ff170799b9e8341043bd5ef14aa3b662b98a3f6c3635c241dfbc983c9f1201af203b46a82878303e1a2523b2d510733a400b577b7a13e84afd19893a06e63a57a38141414f510bc2d4d7ef4a36cb4f9d9b4a1cf97e680b082b4df67bdeda8106493a56efa0b79fe50266cf6c3d4a2748a8aa8d3a0fb3728164c23dd4aade807b29dbc3ddc07e14f4579b3183a3fbb719a09ded581aa15bd2cb105a6f1e6a1c8ae2be6808c36d46307be0804048be9ccefe6fa78fbae3e474055f166566e3c9f5e9a629e9205b5bba8befbf278a06dcc9fc573c61875f5bdea043e61cbdd27720a7fb89ec3b9988e64d37d9bf2f24d330835b1991698b229accb38983ddbf9de938a7535358c66bba0cd01ad35c42f052b2c0a963a5a1e0b8ff47cbf0b39c1b4de63877437a8f7ff12760d1b0461c5f9474e1a13a9d355009a4b42279389afbe80f9ecdc199bdf0c63693dec9ff283e3530d46d5de0b83b45f1b007438baec00249327504b398df7aa1f3c8d9388ba32d0f6b3bab00ebd1a44bbd2f45591f1aa2d5ad6971ea307f3a5b3f3c7cfea527318f56b48e0c281076ad2b85e8b1b4adb9febc842ae9963219c7db99bd3f004c7acb2eb154f18358e8f3dbc88b916df16f5300a8f6410a5a7fa134bded2a63b0145a9b20aec17676eac969ede3a95ab82376b4f804736119c5dd03e9cba718bd20bf40a9f4218301ad4458803f09d2bbf88bda875bdeacccb180997fd98558efa51e3d9c652b9ca7da9df4fa79327b1ff4dc41ada4b224983805211334ce906af613348512cc193a853d8fe5cfaba251833e4210afe5a830702fd0f01b4a23ce6db39738d545ffd19df74d1d5d21f678d43f9b979b5e20faafc735ea27e494e0916256cad15939066cbd484b729242596ef4ff526e1411e0067f774542d4a22242d29f10f8b6a5d03498085448fb01a056c80b9bf16b3705a020793046206dba9e0aca456a22a72dba9721181c76ab9b8cc1664def5b3979f0c059a2c3a693ea33f244971e209bd0f1475c61994a536b05d65c5213a70f04bbc9fc7ebef36017466f5c985e3bf06e2d32dcf69335b5903ba1858423bc5bb78c6c8491b4a423acc2dff5969347849b6cee0e4da1526f3be4dd951482a455814dcf18b6b1d2108f51f016241c9071fda6ec6961cbdb6276e372591bc022574cadf9d3d0b9a783dec0903acf275da463dea626f1ce9870396a8b90883e10773e79a3f4d5eaf24c488f7250ef7a5faa6b130cbfe5b6ad2b25c00ffe61a4280eba5903e93b27b12aabf010cd57091fe86b9ecdad6b7032942d5c8d1131b97db2f0b1c1a1258a902fef20611cc753f0a12452661ab014441f5b3420db3f51d6d9286d1dafe100490ec1e977817cf8df45ffe8a53bd35fd844d1f7a98fb3c873c387a4fbcbb964292fe425e211c9b15baf6bc4891f6cf60a64fcdbbe0d5a483fa8c0507e442777a0f974e14cf2fe3d78965d335dcaa0b079662737d36ea510cfc2bceb092185199ec5e6deecb1c0d57e2ca6e959580192ff45b3c222a0119b6d4003e3a0ae8707f2936cf3672bebabd09f204d99c6c4d3bfc22d0df4dfebc496de0f5575af7662b8c041652c14589ce4a4ab15ec096e4098735fe06fa9bbbd1768ce64b2975d72d3680a8662efa5d3daf8f630610bd4c045adfe0f14c2f91d38c855c5b31d37ae8e60b05a24defac39a2e22c084cfafd82a197c289d4dd74b4aa119c4358ecaa0a5943d60892459e94bd1cd653849fc03648e77128e6e94b0bc2f929f764520dcf78428cabb65beafb31225437025d0d96bdd9766d221189760daa87ceaeaa5165a9e4ace484667f79c9639dd22b9bc6798940c7b3b88707d3156606b04a8b104a650a9b55fd42e37980ac3694e5c63736b0354c1af1c2cc76fee2b502d06a45ce0f311c248f821ab209fafbb8e5f2efe58b64203084dfd848aad7c65f8edd2bced25de939082a4345f95c82f3f24ac30794daf1a1b732b9d3332efe69f64a0eaae947a8e460c3f9ad8a49e7b595a2a23bb7ae97f53fc7408a2fa4db5962fafc0913b9aca2f9a7b77223131f9ed2c6718603bec29427a6c975d9e8895f23e80e495fd8d4bcf030427af4b4338ac66204e3ad875adc11114d76d47f258c09a49df9a1b0c537ffd8e80c822faddb111cddca3a0ba210c02b49f5616ba0922837208bcfe23aedeba813e36b32ffb62538ffa7bb6cc7845d10b87aa935b611f71d775512969b348d1768e79c6b127c02200e63b4aeceb7150ac25cda9eb0e9e0619516b79753ee48a71cfe8b1008909e43d1940bd1e38665f4bd9938de9778e97c63fa256670c993d61f95b0916c674e830bce781487f009133aa977fcd3c2a68410c04f2ae948e977e9acf74867b888c93a31290acdfd13b1f70915cd68f0d1cbad18227e1917c7c8411d76885c2e4777cb5cf59cf73402f0951662daa6129191aad5836e1877d4366b07dfc24a225d6e053d7bc4dc1e26413b7773f02f544ead1298ca88bc167ed385bbecc21ff3793f5ee23074353949a4beb95e8ccb803ca62f9414c326df41e2eb2cdd8f0cd7975385df4878b7075562c6aef31a3bca0d050affdc889c14a618be76699302dfdff940fb58d810b80af013e84ddd9892c45a393d6b8eeddee1ae442a5e3a4c9e3ae4d4bae24d3a30ae1837e525bf09ddf612ca692904ca1e35c044f5fa02c52a28b4c8e74d24383527c396b5cedec50b60098c4fc2f0774d5606e83ffc55631f81a949567db3e14f646b6de95db67c1f61fb372e40e641b14d35672274267139bfbd2cf54ec15b8c03381cd091c5ed5140623154c08b6882ec6c4a4f599f538984ff18e6714bd459e75b52f5dacdff5b374b0baa627de0735c18d2a5be8892e2e8b7380fcd8e81a84d18dfab081fdc56d4a778ccae60e076f2234645ec930f5de341e515d419b22755fc62dee142b77306ff984c655010646d2725ae96676ff003860553421de567315458034e3ebef00722d4a66b4b8409081be245b102ee0fefab34ae436dd35ccda34f03678a27d7d70f012ed7fd467cdc7988d80f2bcf95677d748cd234f11b69ac01b8a9bf372191f76226ba74e23bb0f0a0eca3a4951a8806439eca11a6913ccf6a5d537325522b468c720260873127069e61e2e9fb16955b4045525698706f0ab73742493aa4e838e4edbc0f9dcb98a4fc9ec26e81ed7b7e948aab348654430daf3b664e98b1f3c7caba90a0142fc8fcba278ea89eb278502c2b29f85771c34a371cca63ece5c2ac193502bb8b183fb4f1776031bf66787adbd99049ad39f987f96ea0fb4ff8df9a5c628240f393729b5e62fffca4ad94375056d6204665590a9c4b9d275cafcc2509d26cbcf0df20f81e019103b3e89cc47330d3199be8d5c6d3dcc7495f0aa1ff29e57e33b3a0fbd9807bd2edb7e49ce00fcd37b0f7cea2b5973f057f38fa6bc7a1fc5c8f8afbf9f7eed8fc1b0db9b54a52a5f95ebf447aaea9346d98bb280b77768bec716ccf500d708602a040b4203e300e8ff834748be2d862124fae459fa9e69474a1ae38a1920797ac2885d1deb004ee1a9bd4375d08c255db11314a3dff62e6e75de855fed3932c1585fd3ec091850196b77a4ca6415710c3ee2f04d5acb42dc8201fff44c880117c78fb59f7869b84adb37a758939b9a90628a3d32313468e52c698a32e526862c3201655f5c49e945cefb0c418fdee39b8a64ee588694919c795339ed004ebd9e3ab0f1350fc3a6c5a60167aa31dea2fddad06ac3bcc5c933e4f133419df5e6f7253e5518332f7d738516242bcb37ecd91ba17ba5bf027c681dcfdd176da574152788e01f6f9b351bee74cef4997b8fbc3ecb4e1d8e0ba657acb81d0874e181b207f2ab6f3caa750bb4b5efb6fbcdcd2cfccfb8b72f43e89230a101d9512a42bd81881543bbbbb63802f110abc7f97aa787cd2d2359023acaf74970787ed751ae2c320f0ac96c6e688d5171552315af8aaad3b828678b2d4fbea5469efe0b68b4cefb7af29e12d99a26440d1008d63920ab089eca8dd2c1d3d467f46f947747aefd859057bddfb16cf1c0fef1dc971567ca6db258badee44ae4b2851661a5842a9d0508869cb6a114dfb3ac68fc42167b4c097e6e27129a12e48c7a7c8dd303c98739f59f007ba661a764e797ff5f4d6ee06dcbb005ca757f2aa8e6c136e245d8e9c28ddde2d70f1884255e0ca0d664eb22ad454956094911a1242b2b78c8617683b992878c0bf1146e6cd412fa2d1a33dedfef5a4356ffdfce6b4962072b84b7067a676f68e6d3a07acb57b7399908b573da68d19820333b6d216290b36c5d5f88680107cc48b97d7171b2f762ef73c8cc4f40106220f42d8e161ccb1eb842826adb91456bf02bf164f7df3e58671b3320540f6aec011f80c03d63ad02c295cf3d60be00079075e8481f7d512ce5019895d4e0ad00887da68e1cf9ee18f5d09ccc11b68172b84e79246c3b24c444cde58ef39bb61418a3bdd00da4d6449ab3e77a33fe94f287adf6d4625ad33848c77c11393e6275d9d6089ac1ae30663a7bc247886945c7b0a422e310bb3eb86996a2255d2a0f09e30d0b92ab4b15fac9de31a8d27b095e5e70a6c33cc9390a00773d7a983b01b771db1000e1725def7628690a30db19a1db2f97b2b449b0958d13c127d32b87c3dc155d971689e831fd861273fd8b7c882c968199e3297df81f7dad292c57b1a8921c76601ea77d791326688e03e01855daaa108b10571763030cc1cca946c4edb826fbdead307b005fa149dbb78908803137825e09fd3a116702c4b7ae229405aecedf04813ab33c47ef196a0cd8b8237931d7ce1a5e4aa35779b5aebf5db0dc9b6d7bc76965b4d90c5c750be7e1bafd0e5df07102103f06aff148019f48db411e0e17338b0f80c1a0c29a52810cc07b68911e29f69910befb82dd138611485e580c4f03a735aee5d207d0610df3a04bf98a89e4b033eefb3354d3de1fbac64e893e460a73fd5099635ac32a226268a5a672f10723f42d2b9817056eec4840659c97800642492e9283f7507c565c018cb3dd2403790f69989434c1f27428bb3df1e653e8bf58cc59e85ec40e754f1f6799301f15fd96076ec0fabdb3e0a11dbf8b0cc7318513e9fa621488c5f06ccd530693f9d565945ac74d00556c3bb36d59d407a9e278f98811800be7ce2666f947ceb13f7177a042145b180db75bfd1186f5dfee54409a337ffde42212d5f08e8151d1f5e4d1e34a730136bc63f6f27fe231c60d52316c6936d5b9e1f8e12f5d30b060953686c1048b6aac961a605fdbaa78de5e1ffece43cf8fd60105793064a909e47668fe133579abdf3248b8eade57861acd1efac032420225f6b5b0a3f372c173c39f79db7b060122f755a67e3fe6d715a12d9404f5cbf82ee0899b4941eb62c4e3248b266539bb5547d3d5847783086ff837356e6605c857a668afdb442c3d7746510ad0543e7d35b7c8b26e159f4066f889fe3a0521172c4caaf9038e585b252502a54eff79f047ed2d044b0121a31ef87c8e6c8424c826ddc98e99b5459047dac23c8cf59fa4016586cbed3734f1e4b83c3c16fc14ec5c4f019e0f0b6463b2eafd6cc0182f7346e0814d6c1b00136432d295336d871f0d1b4724dfd6363df5cd1305ced1e6108daaa401c060a4b37240ce316804cbde0398cd4abdc4c39ad8968bfd06a65e166a3781f7c8cbbf9db1b354e1ee7a3b17e1acc4816690465daaffe9d6f37a0f37bfa77542711bd4590b6aaf24247c2c1c0e824e3d285ca52dc5657867506d34ce1a6b524ac94255aee8d388a12483ce4c736c562df1b9b9674277257061915a31016c1be32b2700fee36ae388e3cb0e3f8780407b6ece46b0b30a657e73fe054266d953d539cf70c43f98a1fde972ad1903716e807f73231f969d2bbfd5fc99b139c05cdfde7bbd0e8666ab9d7cbcd7e9f3e68692193f091250ff13c7b94cb046760de3ddd6517bbe307de4896c1a60185a901d402e797c760a37f601364b9cb2708c06f73c762021d4bf8b0936144dbbdf0930d859fa2806862279b615db82c2b7a6035a0f7ea76078343dd26290bc2e4ea1b80af691512799f07d563d546b806c7924d00b2fb848c2f4e021c88faf95060a1f9535f51de841dabc667942a5667809e5add0d9e0bb739b3802a6c1ec0ae8d75de76ab1a2aa2e7e1845f2f95fd7ccde9cc5a10defaec486b5f802a6bd0b110f63d74ddd33dcd25da4d6a734e143f21aaca60208e6971502a0951721aa11ea4f03dcff520a5d458650db682bf83b4508fd5f92a151378d69d6725ff308962a4d98dba523c3165a8b6237f6d6e2f08ca4429536309836ce946aaab2bf3b7667ceef45347fceea65fdba03403935c7d0da05c4d4c37239e3a58ee8942af27c466a48f36cdf4a70815ff6b67b6ed33a522b62855a4f62fa1d7618004eafa4b71852b2dd50e730bfed254de97cee2d8fdcffe21e691d18381bf9c58951c2f469b3744292c66be1127cedaa0c4baf971c30d3b5e8806d8385b0be0837d7b69d37b3a559b95c26ff7c05d746953a9fce696368e37dba1aa10cb5ce357c7b1a7ee64b4b1e139516ed3a014290cec1c50bdf02280788e132b9fe45f0a5fefb50859653239649b94b05e7e2db4135bd417d9ecdf397bf5259fb8b65243d36ebaaf08403a56a6b7ab0a443ab079c0fb73feed0ae1f12ce9dd76973304bc8d63f2e83a37b15456d9bc40001c9d092c8836f1e69fb9140b4b55271624d4cdf0af66f8e9dc1e9bbc9874dcb6100cc30b7ac078c47f7599e82fbc19f9443ade2451dc8fc8d44e8747e7b7f5beb48ac5fd8b688e02d381b2b84a6477ab53c94d055866a25fd74b0a5a5f63c296d02611cd39fc291bc7d6c1413a20c902cf3865ab0c19476c67f7580ea8764961f9dbd2002f1001834c0ebb151fb410b3a1350429a6b57ec0e2cf0950d9b581c670f3b8fc1e34d4a03f58a7aa404605c45b334998caa472d2804f5ed846edf37cd35b375b794dd3b8b113bdc3444159835e449c70a009712b6639b113df69a61cb431b6a9039fb7b3f6198242ad0226f295f5c6a289f06087efec390fc817a41ac9733ccc568b1d9764b11c6a510d8f78aceaf20347cb2b47f126dbf87d314759e1afc9a1c6a6bec1647b74ec05fea7717f80d624bc1473b913a645ab140de9ef9b0692701bb1c7ccae5d4a24fe673b91717e3b93d85ed98a4c70766536afb5e802f38f450362ca1ba6ab53effe0adba03575f0b262e992b7032a35c4c0e9dc291b4c97c2f5537619c83f32ce32d2830675b3474c89f4c54c4760b309c5e14c675e3c1d99803b14be4e49257c06516811582dda7991b1178addfe1ab76aaad447bfa62d1fae21257aea3498611d52aa3595f4be2e82757099495cfee802c33db5bf1c9c1b371c6fc1dbd57f4e3db9babc19d60b60d9d8349a583b60f5c13b2de1788868ca5fe42c4301b9cbf0084ccea1436402b542a1a720f63c1aaa5c8740878505629da46835de3306adfd7696e321c2d05df7ce657fb15dde4ec891393410057684a28387bced7e61f5ebf8cad630b7502f9b3c65b186cc252aa0dd986c389dd27cd8d02c9eef56e000860d10e95ea6519235717a472b4108cef31a7d84b2fde8da16f721f8b45fdbfda6e934b410defd5a7676702b95400a230e665611aa9694ad4aad2da42ea8901f3e00bbb50718b8e48a511d3e58805a764cb1c11251aa304f265bc9fe35c9b90e63855fc349ff7e359cbf30bf05bd665e6474a2d9f491475faefe97efb358b37bf4df600d28d97f28b82dcf9436349ce52d5a31b31cb5cbcd90834883b0f92dda6829a9192856fc57d5209465e4423c9e69ff1a820907b677b91b6dc58031303d5fd9bb857a11400577a02e2af12e2952587b3fe9a0c86e66160d0f7ec60232915f418fd9c388e94c3f01c6b2697cf020f9c3eda8df3e7e8f92ddc63730732026313d5b946fd448eb99ee03af4d8f39e38e3bd2dbae64756713e9c306f89c3e54137f0895afeeb9f54bef4bb87be4b6963313d8b614b90b847cbc3f488282ec26e6db5dcc4edb3b77147c3f61ad3363ab801804160a8de649966829bf4df3fc553c0fdff614270b30d6811e23201de657e2938068ec06643da9ff2814ec2d022fd4efbefa65cc4fcb0efd7ec2864f8a8391993029bfbe4640bd6bd086fab349b80dc6834de05fb061ca30a3619644c137818708c7ad832c89b66f030601b15b0799037ade079c0376a619339e4932d7e3950791526aadd6d7f2588b1677f1c7ece7e918267b2a7f86d88e22d5cd4507c38359d54cb0b289ac3fbd8615ad827b27e45401cadbeb43a60052ec33b7dab978ac117eedc40f213171688d4c953c52075070a8b3fbd5f08fceec6f8d7a420f0d9d394995ce46efcea696972b61a8a9042f7125630984071091c76b57f59f70478bfc2b9c5abbe71f220bc9445b653e06a77d176e1a99afc5b5bbde9cc337638347d01474fd0b19bfd76f0b4efeb98473fdca5c678430fe666d2f79850f0615f06a4b5ba4559e9362635efb889fb283604a4418034a9bfb67b7679983db114f42df6c2765641d77e45e8baef1e43f1764df8b65ade4b3fedb5d4682d4e7bf37d5a7fda9befd891eeb437890b7a41edad8ba54a1355e990f2bf440e329d7073fc67e373ffd3cbbb541815bc84b5486048ece65ffe1fe926dbc54a00f6b72829ac5bb90774e5099c20633e47a55b008e77baf4389af7ea6f2b0561043379c4628af3e8d8bc52eacb549c29076520bea8c431c9670ae4fa3487917fada78b13604e9fc93cb1af7fcb3f0718869a9f0792969ec3019c42b93f49386d04e03ec4b924b6bdad5fc0d42f69807c1a60911dd08ca6120f88f762f705fa57d29e46e8b7defde3c5be0e713e9c1f7f12eb279c7edef7c7b5908a4c47e35f19aa13669c40a0fe3e6bf3a4286cbd5be134be859705e010335d91db15f71ba99fe5542b5a1277c1b4304192adda772f5e77959513020938c754c8a6587a39c885618eee822639ea200794700bf15346837974f13b297e2a574a1c5256832369e95ffc7ad8799d6221e2ee526ee6f0bb21100ed925527e8c8e7b7ba6ec67b1d62f7d0ba75296ad374c4952804ab7c9849243da86b1f50ad483170e135d8c9d820f5559fffb682e514096aa6c23a8958801a930772d7f976aeb0e508fd1f4f7ba8fc6dd7081fb7da1ad5d2a5ac26243199b0518841d72a248c0c11cdc50883dcf3c621f32931f570c499dfc42ca1f6939b2043e3018187ed370cee8d4242b1b6651d70ab662799514b1dea98cfe412d8dc18ce5127187a55834d7a71422a22a037a6d936275096650680d6eb1436f9685ae2925ca91bd8ba66838bd23f8fc9133ca5df315f284d3ac5a1bea85f5914d1927e42505c64ce068f7067514494a97bdd5a2e206b27a81378293f636c0e0cb875d41200675ee2d0a827f2d808543a2c8c1a3cac1bf4fc4e60754abdccec2a4bc40bf248258a97b139b953639fa0ff8bf9010d52b287a8bab22fda5eaf4dc4b7013f02478a28c9d1af5438937e8154c3cadf8eeb0a3a9280ab9b52f91513d07ea414336d8f717c30ee98ad38d72537eced2f81a1e17fdf78225830b2d7f07ee561888a23b4894fff2f1d2dd20f1c76a121b27d9a401c630239075a20af2cb1fc5d8208299862a7660d27ee1bf85a647a0ec47658cd0bae52c10aec2a4c5b1cfc2815701389c8d72098493c027e7c2f0f08903ce9c0a93ff9d9a084e1d70f8af189e6a0342e8034ae9c8e391294f7de4b62f40d5e19673e4dfa48dc07d85e489b695f69d09abd52dd36e8389687f19b2ced7938d0373ebe1362ab069a3a6efa4a6686a1c2d083407267d98babd9b02a5e78a690434bd598760b0f93a9517db9f36ddaf849102d73c13b2fed034583ed3c1b6bc23dc286ace28b35e362f3d1f6c7fe110b520324c44649a17589f9d1811cd412e670e76dd73653178fabf81d0cf38446e3e2b3b43f243da53e2fe4d1ba1147f7344f25afb2e4887f72ff196e551de0feb6edcaef1206dbd1b25c381a3b1204c08f2d920945bfdb8b38cf6813291e8301fdbdf16f9e2eed4cfb388a7b7d6d280789fa4e9fad83102dca538b92dca21d540625d614121987cad8dc15c41d08ad83b9bc7ea9812181dd6cac55400d939770a781c999823859ca54f9909ab6177d5bf514d8de8dc2d331d80ec8dac8ffaac8a451648a4fefca73afca857af9a0a1cb2f97dbc2999565531e343cc564c160ce023e8096477456cbc9560f16d6a9213f3de507843833c1f161d2b7e1460d37c5039040021e9e1a3edcf38ef91a61a9da403b55c5dd34b964f681f43717fe0b0f016412a1e3809d7a662cae02a03bd0a6fbf2b86c985e8a77039ba8a70f266a257d34b9d02233bc26504662226a6132ccf5372335d0451db3f0b4bfe3cdedd4af0d25064bbadba4f5b6993b36b4e70e478f98dd5352e5f567b85af5492b887310a49690cba13f982ccaaca47acdd12018192b572d67261eed6ed1eced4ebe182c04be813fe12667decdece75161f9042d0f83a9ce7d38ee91982ad4d8fd7b68b48b36c95d6fb359c69ebf13eb6f1353955af7f2d32f4f2b14ecf5b84b85e8449dcf9c9655cee104462c29a8c134728695d57cf260dd7fe600db3f0fc2cc26017ec96ec56fb0f003615b7092aac234db925047ed6d52cac57f92ae434c0f3580fbd426bd30c9b3da6e7e961bdf780c1381f561ec700c4d4d80a7109393b0e21e0253e32ed2d48968aa911471b18fe88fa7d4c61c733545ac16aac7e795f258ab5ba5ff3a8b9c28925c5fbc3ddcb6f3824173b130fe7d1edb07114b65ac5eea1d15b800d0a45b8af9af0305291f1d00fb503c64c94720b1dfed29d3b7d373a75aac48ed5c4c6d9e63ec8de93a2395867c66a91f52d271772a988e3e593d7d64f53ddad795bd8571ccf37014c9a3ba2ec81e75cc1775fff39366338f6069347c18f3fc0a234e09c364ef92a4a333828f055028506ba79811fc44e9f6d0a5e8a0d239a1e29b8840048ae5f9c34c5938b1eeb6672fdcb964039055338887be1ab3922fb7ac0fe0cffff9198e395c7f81552c135971ed0db30099c0b46b78070243b0a77429026f088a33ca22406df9166f28484b0376147c7b0923b82fec804433fe003caf41ea99a0721e002929841efee3f17210039270515c9dda3cd89bc42061a155471134e5cb8c578f35dc2fe12cd516c826d995bfbcd3a7bc99c11cdea54c6b5182e4468f1df462a02ff8d4421bb7d1c63fb341f0dbb56298e6a15c91dc2abae98ec89acde881c92c6de254210bd23aba9885916209608c7e14d296d1aa81a541a2ceb04d9c328a75f92e1619f06f027d1baf077d77fc1a78804e0b0e7e27659e056c522b4602342e3dd8ac9ccae9b85cef9365c170e9154fb8602fbcd97db075003ab8e80521aaa5bae9e6fe6234f2863b1bb95f21e258bb20bc3ca780798bab9d5c1cacb31f5e6c16b4d78983b481f2f0d31a1643b46be90de1ce54d675f2132698d5a79d8c30db07de3f4748c9d31bcb2f2bca8f44315ae99c8c53a6088660a9ca24a4a1453956755b534b8a8ec6d9cf2534449fa04dd232eddb09385840f88e0c04c30549ab56ffcf2b45e78a8d402026a6f5d014579730ffa06bc5f9724ffc67c6253cdcd8db9d2506ebfc2ef6c057374038953acf06e17316dd12cab6e76e21310abe0b0411dd8a007319181b107bfa28e03bfd04d34203826f20421f695c11b7126da3bc80a0062a283aa63914c204adf5b26aa234a4d094898b96798bc3b24ee2791853b515d87efc0c60cd62b6206ca33c5b134ad3e56f035f20f514dbe9e72fd6bf9cf610eeed1c71d6fa821f3c1f69bbad43a6c52b198838e2299c54825faa794fbf532a8f5feae05bf67e920932a6e02226bfdf7351e013e3bf9679bfc2c254b71ad82b9071c9619f94bad22016d5d9c92481ed459e1219deff276e773ba705df14a1547ee8fe3e223d30751c85682ed519409a4e17c051f0233056420bc9b29e28f849e0216a50805abd1a163dcf32d0a2762e6da38d1b936c4b14b614e66c90e060fcf56279e4539310c8e8aeffd3eab1224fbf3547bce3fbffbc6e77c74e8b6ab5740176759e95986ff00acfe7b21c3807ef10bd25dcde3d104757057086673f775b8cadd1a934dd94ccbfe7ace6ce5b6b4af46b10806eed9d5efdb3ec9eab586f64276d67112b9ecabadf5c7204b5fc3d7203a3a6a89ccf3ecc842cb4dc93ca29aa759f57dcd909be071bb3c4663d347be359777100b92d3ec1bd7f0efc2431bcdb8b193cd2f35ed0831feff86c55ed15216feb390b5a34c8c1ab4cbffb88493bc3198e08e61579f773a7f9261414fdfcfcb3ae26cd38198d91c5874f193d109e4d513b4101e58ef7eebbc3906fd101989426c85ef4764c6a28e3ade3884516e5c638ce10115854ecea91859c6c85c7ed0712f2896069b3ea2e664907033bdd570ccd10e719467f02f6205e891a4198ea6408790648c7cf098b8a5c2ba8a16008f19e01684758c3264c88c06f243aab15ba58e061f8c913746a5d65e547eae5c724023be228719b3007a38b3024272b31a8d2147cc8c52a9d826ac8cb582549e6c5264dd9da3a455f35f25c18787a23f5668d84d0a9f1a5ce25406067dff3bcf0dd848dbcfdaaf5b9bdd774933ebf1d1a3990f6179de1924b9f56df49ac872f21a9f10d621266252ae80174b78dbc9e487366ee52876289d2e74efc6c64e5d1350f37664ae63a8216fe9b0036daab4111cae5fe872281a1cffc26be237893d2f554a223f5644002737441b4971fafd3ec92f5cfb6d573cd08d1f3bdb2997400413ca5f9aa4ec054c683494eb14b7c3bc33b2240bdb54911856996da2b4b0e05841b0c90156290e211b1aee77539ba067db7d16e1205e69b142c81779cbea478940fc48a1ca2341042f761b321eff8c7161891a57e7628d521d775f66e3fbf885b80ce689e7570b149d96c07740f782e38f18e3ce86a4687bdfa9fe22b6bf617054d0696530e55590d65f0654c4dcb192cd1230e8efb2c3a2f51f25e417717aad98d142426c992aa7be4b68f9b28922a3be9881dabe508d01fcd6d0fe6f3b00549b5abb6a67e6aea102a076302eeaddce94042466298814ac127786abcb5dadfd26e2f6080a440b4175f3242d96cc71f39e525329eed653909526335c02a6c1b5f98b36f18d4b4bc02e82d22aa24526695df15a6533493ac2d576e2f90bf7dbc84425624bf2d254047ecd89dcc68a13287afb90ce0ad870a33724c64f7a0e31cee8c8eff1ee1831c941c092de071e8ab733f8280e2206457a2cc8066b6e049c4b39242b62d35cc60c69ba0c1518e12e22525a7fae0c86d010cd3879b2cfa51bd1958337c746a0138480ea59d8356a24505c584432d4e933e6544c41dc3d8c2edc3518b9166c10d32119dcd810c66d24e22346ac3d1d4a7f3de7366ae555d17745716272a99aa40439c6e09a230d490e0c9f418f4c3e57c311288c84482b0051ae31602181272cc2e49d7a23e9a67e45760c2411402666b1f9e12f9f51c654acf0034a55bdf5217570223244f9aee80b2523d37a0e6ce655bdb9c9171f982962c38db229a29d0a3a4f6154cea5dfaafe22df48d36342d6c3d70e93ab25532d27a652325c73a8b908e9726c2ebf9fd5d5822ad66879c414cda578d8c619a3394fda1d6fe21f7569c437b6b4927e5a5d1a66d8ad1e0906f8cec17cabc646f3f281b71c42fa9f4c277fc76f8e48a1e131e6d513892666e14000b6418005e1548e1896ec3cfd672e2c9d47ea04a5a3b09457f1ac4b730389a6c6e459dfa0c7a110f5e7c2062f082e4a013fa687cf189f8d45030033fcf0d0ffbcc23755d5762cfaae5be5e79fedd6aea0b9bc01b8649bfd501fd610858e603eee2e7b4d28ae7adf0583c06c3c087389273a60ba671d33fcaf178f6aa0f83cd80a4bb08bc20b94fc55814c85b29f4195f0c979b8fa41edd934d34feef7dde76fb3a93848341c8cbebe6b62edb88761bee006b8e77ccd76be0ad7e41feca4362d5553b1d5bd63d97d9b0831a5c873f1892e873deb03b3379fbe19d99782771b1c99e0fc32ad797aae17e1828002cec6f87b6d1bde7e24389d8fd6bc5ef254eb19dc759c7dce2089f46d170c11b2132836fa657e004ba9ebcba86cccdc8cf9fae696777fec357f078a7e64fef36497609d08cae124496910d9612f64d08bae9050fe98381952b54cc3e2744b10f52fbad469456afda654568dafacacde8a8601b9c4d9945727b5f49d6624bc6a4493937074705e35c3347264c64f54c07aa1db272b6b7d37478b06a1c9d3a72854857c0f72862ec2b81a5afe76a745f633114c269aff290da56acb84edf5aa1347fbbc288a7706104b43f5f4c9f3b5fe53477962d02a291103f64ccc8227420a99807c0caccbfc8cfc14be88dc24fb3db69f17ed472a45e7daff71091f7696a3999811e263f13960ca0f346edbec7c6a672f99bb361aeb26efb5d8dcbe88b498020c39e740c3441a61b14e6893fcdb8c4b1c2991ad4e01560cdabf94eb47185d9966262e4525d36dc17265fd77130f4045bef1a781339a65242c189796f06d08fe46de9e55d2438bfef6d808f962f6fbfe108e7b559c6945915b3986a993475e9c18d7973077bd6cd90a03e5c95ccd78b3a91e29fed207cc6c4b732a371227847750c4ffdcefa114f9e4a3283c31697827a5bf224e1c2e42fa9bb120fc87cf956800116dd31a70bd975a336b18693a527e9c73de4fbf37e57ff72a791df703b4e1ab30d0e461b4ee5b38103400a5e72c593d23c7688bbcc9b3af64227ffa5509b4f0de0ba6d522f3863ad4e04a359b477c5e237bb15fe20dbcf52bd4ed6dc38a528bc67afebc2a2606d1413ca1144312fce4de17799baf882fe8e28d3ed2000609900cf6e8958cefc1a40b9007811141ce122b4d88f4d15484ec0028f3e65f1a56257f686adb7d54e32791d9a767be74e5a8882d70ed4212575d6a3f70842c2e40b68d791e7146a6444347314570498fda9cb68558a069e9b82df13b42619889cfbb7237be59138a11bbea94a6182019f52ad28c496f6800740f32f8ed209136086406802d2a4778eb302082bd69b0ff3af68ea87c2538408e7d97eb393a1ef053e0e52b9692d778ba1ad2b5b960f40d1605fc9ae179418fb88997d506b9b322242e616c18d14420b4b8344b52a0b7abb3dda42aedb87b3fe45e93f3e1523ca82be6f184361e19d49024db371b117f85fdc123cf6b383b4a55cd10182078cdbb16fde54e4748d7df468c66fc2d3d5c93b470a4cff1bda2dcb96b3ec7739e46dbdd30b70c742d51a89359043d8760babd76381a0092c71f05fa3cea4c64cfd37106c2cbff0dadc39e1536924aa394cb97148933794684fb1bffbfae2833e2c333545d02eb6cbdbcf65b8bd4d6161c12dee5cc13023c6bd886cd413417cb46edf1cb4ffa611c50e0ef9bb53a0b5201044f1f1d7a84d83a86e515dbcbc0aae328c4b894b0f7384f0d40ced95d7359dcdfb90502f2674a229c3ea219312c333313371ff1cbc33c4273cd4f3c416454415204c72fd9c6dc81319adab931c11374da0284259a8a19cf9752bc1bd2c17030c9899d4f87beb3c7ed17cb8ccf247a8f7b5d49c79cf91caf83069ed849f026c78ef0819b90f24c066025679e24c4b467dcd19c2b5ac219806e20c35b3302d4c96f1a879f8960d5dc859575058d5652278ef341ac20568358b52e5b1a65b0994064e7b0576e184cb2e82722cbf8297e0de639b0949de196651c64dbfcd891a194eb2d3e323c1a124d580353f407f018e4821d612154514b06e972a3d53748c096ecd4f38a02aae4966cce190a7d704141119265c368503c0fb7c538527ec06d3fed47aad30ea6920ee45eda35d799b8af8a867a8a94c0edb44079f27fa7d0f7e2ce56cd7d2ecc5a3b998d3a6538b4d508cf3002dc366d6d4be070d91cfe36b246d01a0fa9ae2b1c2b10a14f521cea1d7ae9e0e2c064f4024676f849d36d2fa57e44ef416b12883c505fa9b1cada820d2c91a5e63821d0e11cec138f5680da63d700bbdd7b8c1e6091a07ff37fefb4887021d9251f792482b97d2748e5f4e211880ff809488763731968eb1e66a824003b2ad46797ec36cafb2b238e4a8b2dc0b66e6a8a32b767136e28380752f4c46655a17cdf13ea1ac8720399f18df2314db099d67e3f5b2a2fccfb3882b65baa8cdba2afc50deadc4e6e5dbbf8847de74098c33acff98d805c7fddabe6bfb6c1a3b53491135873768072c0a053dd3a4fb4ee4fe0028612d52b4519ce1f2d84ab7fe5c858ef643184b26e5f0461fdfd8d1e4a676ae05e0a5b47827800c39a818365c7ca74fcbab407b1855e9a5a3aa774df8f6d152b0ae30173c251836af4e4db0b64fac467f8a0f02975b8e99ebe67b59c45fecd5e9d389fd974c373a898d6f0de73304c0159e38938de38f4c0d0afe4c94cebcf538c05203df2995b1bc8f2f9ea1e1e4b231ee547c232dafa369ee678a1d0c1b807291a0f9a12a643910b6ef63298ee70ebe5b0560d1b4fe6034fdf7028863ec182c62cf74b633ba88484f5a69a13e5c1d70619bfbed270aebc9ae3780f3cf685677da2ea0d2bdbd3e9e78b3a7270445605b83544a8228af89ea36e51718a531dc25396ea4e1bb02c34e691a6252408ff325ecf33d0bd593e48631db727ea43a657f5913484ffc0033befc8a086c1006484160b0727ca3699c56454ed04d9c21d6534c8dc37852f88b294304c2eb36c78aad72e18149a7460f598cec914c28bb6af64de100d2a0dd8a730864dd29ce92da12cb0b329648241e6f83a7a77b867566809a48f6899965b6d5e64861c98bc6548e012ef1c335712448f31a8e5392c246b005b7602df7888dc76135f3eafff4b61666afcf9961c7c2c3d562d330e88fee497bd2ccc13b3fcb4045e18c4260e511020ee4a7549b768e229019a1c4e1e66094542309c8c3014346292e7a35aa0a0d87fb0f41b6960844e3d0d112992880cea0f9cd5e3f90e2a1c58eab92dd9ee2de28a7cf2883fa17ad0769894fd7c7c9b02200e980f400e4a3f3e3df63a292971aeacbf69cb6e3ab6712994aaa6543597941de5887ff3757b5590968f0e05ffcf12c2fa714181a19be9d795a52f94279c9703147982829aa99448a97d9a4a89a0dad6086a4d65bce5dc3725fa0afedb777d90c6ff0705f1deea18c704635354a5a15b57699c5d5376ad9d5bef68aa76fe6efda3e47304db8236575b11c1b6a08deb6bfb82c1b6a01f259fa30d886803e2bac77c60db4b46b5a66ad1074adbbb719a0b92d58a36eedcbcabaa2e424257a42e63955874453abbd3eba649ae27b0ff47e260dd4d9360dbaba36c1cef2a3b63f7a6b46db071fbed1b10ce401dde5a76ebb6745ba5bc0d286f40b80a6c73c72f7358965e755dcebd8a3d37d8176e53faa4cd54754a13056d6e8ac485b57da6c2a860b01fbc0de04acbb81ff3c826e5b32951b249e16d001b551518d04edbb7cbd83eb5e9a26d838daba9acd50be4d6562d6548e9f5ea2dbbf9fab2ed4cf7d9f6d27a9b6e2f33289575d7dc80789fb946f8eb4ef1745b87783ba5571a477237b7aba97edd297d4ee9736bd3be6aaa3555b7ed294aa93b713e54f4f6a7a1165c4b64ae2542ff0f84b25bed4daf64b5f7ededec654282b4b46ab4a76d9f71fd6482b49d34979bedd4d5443a85c1ce7765d397956d6aba571abbd37e4ea527fb6e6e0ae4a643ab6be4d540ee9b6e444e9a4b44d5dbdaf6192d062f686c4f986a6f8d5d913697c6f6956ddbb2f6a6aaa67d60c526f5573341995e1a1367d9269d45572427579aab3d35e2482dc7b9049fc366a4e1ff7f806a9dca6744affa9a76397b56da89235d75beea5acba2ae308e708aff17f2aeb088edb5bdbad6a9a6f4e90a89986ecb9dee49737955fc07b93c21ffdf9243fc961c46be25c704df9243e75b6fecf8d69b36df7a53c6b7dea0f9d69b27bef566886fbdb9e15b6f50f8d61b2cdf7a637eebcdd3b7de187debcdeb5b6f8e7ceb0d05df7ac3c0b7dc54e05b6ee6f8961b36df7243c6b7dc70a10688771d09f2ae2338effaa1000bedfd54f57fce12ff9f43078e13ff3f5a7073e6c851e3766370561c1de4470639750cc991e33fe70d900740136773dcfce7c491039211fa9aaa514cb8902cf9777178709fe49fd5c510cb8a8b8392018e1f6c7ebcf19fd3e63fe78dff1c37aeb8bda32cbaa6e6ff8f3054fdaedaaa57a553ff396db0f1c38d967ddb9eb386aaeafd9fa346ce0effba9dbbff396c7abae63f870cba228511464e1a3968f00ef59ff3ffe38c29ca4083f7154a8e9a1c3372ca78165d9172c8c8f981fc901ce939b2fdbfcebb8e58f02fd36b4e9aff1c09b0e88af423859c0838e58c91e3aa2a6d09c8ccf513814f192e1f33dbabb704c0f040403eac0ff781faed8abfb6b74ff98cbfbd5c59577b0e2c1c1e8ccd8d4d4de9f3ff7cfd3376c63afa7fd9bb8cf8b432590e5a531d1474526d170763fcbf5b04a328abaa1a455d1c08f9ffedf5b2b03c71159152048a5fd9f49dd166bac7b657cf923e35b97ad4e834eac96d3932c8d573e4eae971d9ed6e6bfab47b9549a5bbd5eb65f24ea57b140ddeb50114a68b489a7787b277059b288868e92fed4da3c07eb6234a36d8c64d71e5c6ad28cad465ec1367d926aa3ac4871879b7d6a9f8faba431be7c284a0927024180c6567bd03e9add35c377d61477bebf3855df52518bb699653394f3755d5a8d510ebba408f0bdc5cb0c50554fce6b36d2fa74d6a7b55094202c605efff0fe13d4bfa044deb0a30fe73c4f8ffa6948d42e26b9f39bd6b4b23721a725560f48fc46936e5389a6e6e4f59174a5b3141725fa09646c4cddc26cee55569934cf39525e2a8b63e8d3cbdbdb6b1ef06357359b4abaf913588aae6729df977572b767de2722de06ac5a1e36a9971b580d8d877735b0e00ae205fb88274e10a32852b0813bfbdba03a1a06ddb6aa8218737bff3f3ae20eaffbfe94ed5d955e90a0284e40e197997046c9ad45ed593662cd4aa674f516f7f7ad232e12a13ef3cd54dba2d4957043e425c11007145c0a2c305811a170462b820b8c205c1025c1000f16faee9d976aa52c3603d6d473b136ea5b140ddc6be40b573e35a16a575dd966d6f7275cb59bd335a7b6ad3ec7a6bfbec4cf7d49ac26030180b0bda843618cce53620d80b26a5dbbe056d5560efacb6a6dbac77aa1fd8912bad04f3d960475ad608e6b32179d70edbd07463d7d6477335769382bd5eb02a1bfbaea9abcf97c6ae7ae66adeb2fb897367b31526b575604ead6937abc0b6976e7bd0f6e3ca68bb4df7566b750b73dd94a3a8528754dbb6d7c8daabca2716c90f5f69b0d58a5df2994acf0dd6f6a69685826d1a9782c1aab8dbdb5d1d4342dabadaf946a5d2ce8d7d37bd6d1c4c4ab725d016b4e9b67cabc0b635fde9b023a8a6928939c58909ea09e90826057bbd90aae8f64d37a0963dd3a718906ebb9bd6aa6c3aadaab93a69e3dad70bb6f5d9dad25e1feec7a7ed6ffa7ac1b6d7aaaf402fbbb6e9cfebd63a9509abea69dba66e7775cba560fa65691fc0aa6cae9175a6651d28e5eceaceac7efaa9d7555bf9b47c8555d96ae7c6c6de2edbdad811a827284a47b63ea5d957bf3a91edc7479602c13a18ab5f2244dcb7afafdb5f74ddac7c3655a73157f7dda390366eaba967ba5dde5dbeb2fb5d3b4fdda8e0c6cb9a7624df72b3c44d5d3740c6bc108719715811879938bcfc6c6e0ae4b3f5878a238c83678cabddce3b90db6d68438730665ad6ade000facf4173a60d1b6dbe680381364ab8402e3b5bb78db739fab762d7cddde2c12b84ed05839551484f4ba551c9a4f5461b8eeb363735d2f697add27d36d36f8419817bfb1b4f7dcc0b9b1b75b8a1861b62b8e100f6dd7eb635dd7c8a6c28abdb971bfcd59b1b49dc70e0a7d674cc0bee4c96b601c2b68de182b61c30fe73bef8ff1c2fbae869fb72f19fb3c57f8e16ff3959fce760f19f73c57f8e15ff9f9353c50fbd5e3be57d85c206cff63272dd964362ae71c1ff6b735dad461d1ce77a53d5c0e2d500a383daaec6153536359ea8c1b5dc39c5660a1b2436ddff6f40459d4a4359695953c7f6b24d36eec7f4a1622ae1f512eaae26da5cbdbd5e5049b66ddb02a024c9e6ae017a8eafec99c61d699c49038cff4d48c9b6bdc6ac90851369a0ff1c10e7a99ead5074aa0eed74c6f6a7fed4d553f7b765550da5d55d2deaaadad288bc961a04b4d498a0467d33c83083016600f18fc40c155a65a0699541a6558612657c6568f0c59a9a4ab553aad66dcd4ea55fb365f9ca9e54bbc78ab6a4819ae956a751f2bca7bac9eddde883541b75b75369a8ee3af19ed6b8ee4fbcb72220c3186acd74f9dadd96181db43de562efb671afee561ba7df8d635f2b261b87b29bac5b6d6e4b63dd24176537ee4755356edf94f60373790742d96dcb9d4aabe713d9be32f9dadd2fd02f60ff4fe3a2d6da428aff77e05b5b30608b30ffbfc55cbd6d2e3bdb4edeca647ced33b5bbb1a9161665b82df7d2645890100cf10f25fc2f218229743033b4000f343495396207206ee7a9fbd298fe719c9045800d2b20c035abfee784f9910615534d846f5581c73fcb7b556c56c389dac1ff6fe55b5568715bae0a2a55405541c1bfebaa6ed09b9e3376e778d93daa650666068e14b0161560a828a14545fa0fe5aafccfd1e189fceb40d09a028daaf69d032627871c1cba8c7dfac769e2c71938647242c071c00d3624a0869c2f577ea440c30c32c49003c30f28390878e1711c6895c1e33d70bb0c68af35778100bcdc32669451a255c64bab0c51ab4c5726e7b7a8a6c791a387204f403b4d81de967300ec99982d2770d0af979bab5eaf74a6835a4d88d13601812680f84722a355b1e7501357efbee9696e4a8698fcd5040a916e2269883e9bd8feb757130c9051f39b12a16d7b9169e29f0c1832379089fdffcf9664f319b2bd5e57ab6498fcf672c91c2133011334fcffbbfb9593e606b941bc773708278a06b021a4b5c3019e5bf5a5eea22853eddcdeee72eeeb6a75eb556aaa5bada6af06aaa9412bbb35baf5ce5b761674aee991b7d78e6cbcb71add5cbdfdf0eefebc6eaaaedac75d3b0d8b668d366e43551debe7c66e346ee3fda7e6e32e7144181896f0d22eb19780f2ff542a8de8bd2a65ae8ed2afb492aa773ac5d65a5666a4841dffff3b0000882356dab6f6f64d81d0ed0856450ac6fbeb05abb24dad299014acab3c3557f6e59c14ec4a2bf553055ada60eeacf727ae967529985ed38d48a77522486c249e5e401ba7b1e63862ccbb697ad537293b10f9cf71e1755a7544929223b8cefb4aeb20f64eaddd75bbca8511556c2faadd8da019416544132344a04d0990db81288b78ffff559524a16dae36dff4c4e0a7881083b5f39f07072d22deffe77e76cbfa6ced79b21c00052b0a5614507053b47363a754bdc160db9a96494443474543a5d312143e581520718e5400d60447c31e87ea0847c5a11a6284f7a24e992d21d208a1c3ffbf3655559b4248f0ff6f9a9cabaa4198c00691f4ff5b42d836b7e55eaf1610b31fdefc9026cc92ffedf5c3093f6cf981f683fa83953078fc6f4ab617906efb98177278b349b1ecf0818d9c16587877f72af75d53dd96503e60e083cb87067cc04182d257fe7a99e6193c6830c4ad75aa0d6f41565a2bab15d4ca69c58a152256aa3c902140b81d065a6162eeb774f8e25b3af49012b01cb020fd1698ab1f6a8169e075e000c26ae5d042100e6970c802072cb6dab96d40bc20a5854353eb0635ad1ba4f856979c6f7191e35b5cd67c8bcb18dfe252e65b5c8ef8169717bec5a5f62d2e55bec5a5e85b5c80bec545e75b5b28f0ad2d6b7c6b8b17dfda02c5b7b624f1ad2d437c6b0b0fdfdac2c2b7b614e05b5baabeb5e5cab7b64cf9d696a36f6d11bfb5e5e75b5b22f8d696ff969638bea525cdb7b4703164674747021c1cce7d529a9cb091938710342cc01de008091c4f00e1206401242da4d6977ff53cd315870b1a9af82ff3ad19de7c6dd59a7d5756e5f47f4e91ff9c1e578dd3785fad983a8ff29fb3c17f0e919c0c8c6448f36ecb95b0d49a32e67f4d5b31f09c055a308cf0ffba7aa6ce663024f941220f40ae7461b31d4dd971af208d40c11759a858b8e24a8b203213d540aa060a8518182668522136331cc8e22547faae21248c304e2ae992316ac4885932220d0014535988708244eccc14097b3871864a4c070d7038fb607214a3ea56887cbc1c88816f0001b2028630622c13be8802c4aa3585c50319c8f143cf1b53326051009536189c30a5eb58c1880d9c803105c4c416363a4c0c80deb1c70c6e5cb96144a338cd8883cc1179a02a5ca9c01a93002ca0514cc062010ad0a20194c81768f0608101253d0e0d1c4085cb95ee6328e83c380f367a019a8c10411d54b4e94b627cb104e5baba1022686214b150c4d37062026ac206426e840c53d026d444f15ae972ea92b8e24cc4a2978e28a6e011008113f889e5b0c75013258568491f9b8724ae8c123095f78c05045019410214fbd5c5a96413668bad938110dd60a387930b3b9e4c37db08670288645001360fc6d99560f365840fe2c4522364e1e24bd07b98f96202497c0de8295e45402c5841a35d30033ae1c1962b6dc53d81bb628f3a340751805184a54019d81c60d5085366c081394124cacb478e1b60252c89e14a308204cca98728147270aa0386c19928e5150c80c35c830c33a81630e5309310001b37af248c985c52d84188d41bad793413a1b6a6892a664b05906b92c10810cc388232c11a51ba8010c48e10570d08820508af0e94209804d080b02487498f9296214058008c6c070d1d440a0c2f51c6252aa0498141c50449152185d415256a8e62582393fafa50da29a3298ad45f31f3e2895bb362851915b811c4a98a9518ba1c91199280162b3a8389410ba4ceca0046f888a4018452953b7e586163019b922a50d8e0e4490a3566a892425051033a08400a55a20e60030c483ad8a10a11205b8aa45040042a6d2270ea5409c2810a03782c10b5f470a12282d5511e1d06998a120a3fd8418119262a0208d3460a17180fa6a0c18613a910146031a58821241054b140c494abaf480f78b4724c29b2e2c61b413e504c79600f09ae8e864029629889c01460be235276f8028dd1cb0f19296c03d23a9e080252483da48507a9a4e42829e17a526ea27021f463471448a410e50b1f10b8b9810d3551b8152e070280c34b944e073bc6b47ad0283d6c6862ca989792280838e99a4c01431f512e00e120072f22b822aaca1225581460294854112cfa50028af10014396657f001b43c8042668d21beb8cac00a28067072930626240c940f2440c7044918b101e5020464708031585c2835d20859f3a8c30a94029088280243992d505b888a0853420e1c5493180a4b904945a08230b1801415b30c9ec8b883768a91c47efa010f293688b0c2f4e40609008e285b1a78122a228522e6d0443c0141618707f82cf5387d11a68dde00313070ca810a82057ea650e1941269654c14413a7d16ace0004e0e2a9c7e0206ae900285fa41154d9831041460960f60988182a8ef88990f6057674850068aec832355580bd0811242931d3c35e091c3e46c7aa20c1e04843758d074000ab8f9e0cd1e661394198a48c008922e4d434a06a041c203be30bd11e6015c9ca94015a6055880c50f127c9980890046a069f3804b02a6a424145a480d588269821dc2d0c080c18525342e20c004c828fa61498c1e690a31900d2c59714ca021830a254b44289819624d0e7cc90131afd18b861c94c270e2a70b335928500ac3079907c83d9a28ada71469b08047ab3432fd68c3833cec50fad1a625a0da85a42d30a0f530b3c182241ad68080011d47f024ed36d6ac89820e264948d2e8b0e68c913dc9638b921c37c0a23c91820b5159a3d47ad2421346a34949104fa850d0c6150a2830f4a4e78c124c7055a18593374aa82a19ab9013269868e28a614be78404ed4515197c3ce1e4030b1e8000175e83130b40e002c48a170b486cd860303a9871919018c148124a80b182a465a7873650de144846540c78536405072409dc4c31658b2d4947691480e60e21666a473ed87125851a30faa895d243ac8082358e94ec1f39ca58e9e10800229450870d4e3068e285165f1c994007249ae02080314551520b9ac482e4b1456d4ba38947a45b2a944430ea838b04b82186961f46667c488388511536182160cc124be8ac0230325570630290237a8c7e84a690605270a3ac03abd1438d3086944f18590389064108509e300696357d8c80534211510703f20fb0dc503802e483e3021337ae8a6a63dca00493258270a838c3c91d4cbcbcd96247e9cc0b4c9e54b0060d1a6e9a98f01881c1d512292c293a43ca1a980b4abe68082864534b66bea8ea8b42821860be68a84c4d54e3e58b1aa0b28383ef9f084d135264d0c23f5198ce06364bfe896415c010463caa62e3ff8970c0985b1659f419c2186107e162881bc10b1e57ca98c0c29229bfa4e7df042923c76d393605e25fe7071fee98a30d161aac32c888e0d9b6ed69e648b3264d13ffafaab4757bf559ed4d43439a150c90c6cb0bc8278d549a6d95d154766fdbab37daeeadabd729b66d696e5f59f5075dd3202403d85a765bd24bdbcb4ef96c9bdbd754d73ad58f11ee3a9a95a0aeeb3a9a159fadcff4763b8cc8162920d8f682b1dbaa5b3d33622a5978ff7f561fb3d5b16dba29cece03638c2e31d2e8f4a0c383ce0eff3a61fe7574006385d6a2b4f53d695f48cb1e2d0c29ff1b501847ef0ac307081b3442744e62aee3701fe1d1a8ffef42038566099a4f465b3b1a9f9f69191a2168feff4c1b31fecf0c9d79e2b7333c3ceccc08b0ed5d5336f6ffb03350679efc3f0cb64dad7ad55d65d973d36fda9d6e12183d80c1b341fb85149d196278b7052fd47821e45b2a2e2face81992da2b430cae4b738abd7ab6a9ead0ebd5c110437418f0ff4cefeac2842e846c81c5161dbc077dfcbfd4bbb4e08fb91c74d563415a1c3df02e2d8c68e1fa7f2346b62c4ef80fc17c9445ec7df08246161f162d7080450bff6f5e7559509031d705055d21c40a3e56b61d9ac9a0b4535343ffb6fc6597b8ee47567d89eb7ee4aac2016dcf92aa33591bfb7f76c9ed53f4669374144085140ab8a64033c50bdb1450fe1fcabba680c55c1d836d1c9b6a1704c6bc0b025e5e76e52e082c1982c0ffbba488e2ff613c6dda7c4da9b610779190663228bac7cc8d4536e55e75dea7b4a9b2ecb9b3472bd3810b8a312e287880e2bd28cdbedbe6486f77dd219e9aaf9757250586525d7e4285ff9fcd74d493cd95b97d4a736a00c0850e97256ebc5e11fcbf13474e5ce004044e3ce004007e36d366d19b2f210dcc1a0a10e60105181a84a1d744e9420f0414017a60e68aa033009b345bfce8b2d9e12273848bcc12323d2e269470352036e6ccffb72c1af54486f4f6a7feaeddedbd35e261d5ebb504035c0b68bddb722acb9eab90d055e72b47328538ef52d9e3bdbba690d08f4f92dda3d6f4094f85381292104fe2d63a15475ad3277daf29d5cbaaee164ab27bd49a3ee16bfae40b696b57cdecd190c0f21c297b34ced9a2d7eb082c8ea0721473f591cb08220e8023c5957f9d542796c3c0991b3e0b96344448f97f25ef2a4289ffe7f6c62e15d14211b3ff229a8ae08ae8d988d0c345849a7f2e0a11649edb9c5d8366380f8869e3b69c1828c428918418312b9b4e9d419bdefe75a680e8a0ee9b9eff3a9d73dd63ff3afbfcff96733dd23810d3e312b38198ed8536a0246f4ae41a624c183cb26b0897105c3c0e08385138610f0b02d6f603841f54d6c0e9c205c4983c80f0097a29c0f543091f54eb542b8d5d5d2a165d91bad1cb46e9a2a13755674fbcd57cd5ef537fd92a165d91f84a33ea6d53dbabfa9269b2e83ad3b2a827332d337b6fdf138923d5a25e2f105c3c08fda36bcab24edc4a3bb97b65d73064b81beaed4f36084048861934004194122247936c8c174e48283ae2ff03f00387f5ef72a18777b970c3bb5c8081a5f32f4196ff8ffa508ed90a62fecffc3f95ee009c273698231673c04a29c6ff5bcd61011c357c931a1a28c0961e130c20e4ffbf02221ebc444d10c4ff0761800e0ef8e0ffffeb59c2042a5c5f1a20c6f5258ceb8b0cae2f24b8be60e1515c5f9ab8be24717df15c5f38707d71b9be4440c30a34b878a82a0d851f23579d91fc6d1bca6e9a4804d70c3ccc40c3ff55f7c30dccd534ca7fce18dd3fefbcab485026551d52d521570c643e7bff3a5c88c7afa6db7688af5074825676490748c782a9b62badbd49e75d6700bd65dfa795e96559a7b73719a588524229a0944f8a27254bf9cf6983a5f4b61ff5962d5a5376bf29114fcd28ec6637ebc4d7feba3d8a966997f624e6ead8bfce11204fd5b24635a22635229756f4aff3f3eaf80069696a93ba32e957f37f1d233a426afdc93f4e133a1cd43a55976bfdc98f33be30fdd729f2ff40742cc8deaa6350bd65958664ecdaf9bf4e8f8c5dddbe5336ea0527aec6a6a9aad39d729a13379dea49b1dda17ad58f14ae7436e854e9ca2abd29119d214fc5a4b3e5dcf023d5d100c70936ff3fdea09a05c9d620b4ad72b5a0febb5810f3ffff3a19e860e0fef878318077b1d0f32e161a88b934d70a6d9c9494fedfc83f0e1b2bc854a080ea82d5a07026519c9aea77ed9bebae48dcf65ad974aa756beaaa7b958e751c3774ab673823fcffec5de61aff383be860c03b16bc0d20dd926c57605b07b0a7a6a6a42dc996c2784ae416a94f6d6f72fb948bb2db064a3618920d06db38cdb66f6f37bc056db0cd4d3be836377d7adafa19d46d3df6ba4666ab4cbb1d4ecff627e8a4b93e9ca744f8da3722ec4e5d1a4b9b4adf9575b93e4778dd5aa772ea53ba89af25575361eeebe5d2d8da9b4e759577daa6ea97f75ed537a094f683b22e27054399d69e04abb2d5ce9aaaeacd4d5d969dda86fa949eb1b31f577b0152d4454dba5239b9ba80f97f98ab8b5ae3bad37a4d8db9bd35ea42fe4fed978bcb13ff1cebe2b2a48a162e147009f2ff2faa9f9cb85626eb2e2d52681941cb989fc9645a6ad0f245aa4accd547ad4cc6b92b4b1b52cfd4a56a59abada6aa6a4b63a76c9c4b7bf576e4889b76a21915cbc66a27fbbae9db9f38efec39246b9b983cb99cabea2a59abd5218ef795b6a6acdbf6ad6551242ed7bd1ddab8b6772a6df5ae9af6c1eaba7a563bd3297ea595b81f9f0d4683c96828bbf5297db67a6ad36a8a3e1935216d2dbbcd6434de044b6b2aecf582c13634e57dab9d1b106dd5547a0392d17458394a508890ba9aa29b7b6e4044b3f45dd32bcdc1d6542b1559b93ad6d1d7dd9a38fdf6da4edf73ddf97f1913b211b601b59b555fdab8960b0a7abd605030348f3bda709be54d6db02c78c075c5eaff7350d0cc75a50f489d70a541bc4c738909e9c9a98c32cb26434e4c504fa6f94a69e995ff77c5d8b8622ffc3fd75ba01fd88f0ff7a9116d1c517779fa76f75935ec26eeda1aec077aeab69cebccc0e4e9b9ba3490db725e95ce05af63c1d3121427a694212576dd4caacdaa2badbf6c551c526bb891375dd33c383ba2807049a9ffaeac091794987f1d077ef72a738acb4a9395a47f7565537728086dabd634086dab8c9ca262ae3e32728ae288986cea0f95ee4e4a01674cc47daf2cd9f7cab41a85a33b639f74893f4fe4dcdb1bfd4634879ce3a6c0ca4fe7ad459cf7ce1de73cc644dcbea3bbdba1cfddadfec8252ae66796bd9fe0d98d604635399e6137d27a8c9c7ac4ac04841287bc935dccf904d18f14398ea7acf9ba6b684a9161e78da3d88da4f87560f6bc6f24fbb83b4ef6513cd1738bdfb65276cfc367eef4d78161d7275aa5c419dcbdfbd02f9f5de6e308d563e4d493bf252a66132a65389ea0d8690f0ccf9888cdb74f91a1699a27d506f31215b368ca2766d0f3b03782a1d87578f4bcfc8d27d9c93d8af9d4224aa2524a0dee1115c7cd35d98ddb8b52ea4c7a1ffa658f87e3e99d2d7bea0da2f4dea4a8cf3083baf7ec612750b817821ccd3b9f18f5b487c644ece124a8fe6911ef9173504451f1ec193f792a4fbe35f8693e92df89710e493c3a95e8078a79e3dca1b9e38f3c6322e6eceb835244c1b1f3c01ce67ca2641f39679b4a4de6bd47ef3c43347b1aa35d26994a11c5e2de39ef4e76ba9f39266275264bcd515c2a4794ec7aeca2388e9844d19e73074a65d761117f18f4d08e876788ba6298548a23dee197bd7d765dec4e4fc6b6339c5f4fce908bddc3796fad77cf5d4cc433b6e5d889931287b87314ebec75e1879e614cc4bb5799eceb65241c7a62279223e879e1e7815d18667067be39b871c7990c3136330697a8984f8ece2665474150871c8764c7a7e87d1e18c5a8fc3aefe4fbeb279ac5f1dc684cc4ecbba626c6e108bae7b744c5ecca12f34ff4ba4776e7d99dd92363221e7bcb16b53aea24fa70b844c5149994dd1bc7b1ebd0f3f4b0776e1465cd3755672e9954548a9a3cbf7c82e389fbd9654e547af814c12ea320d7ddeec42f441a2abf50cc1fe965cf1337d93b1d13b1e9618c43bc7b15d392523cf70631efa1d65fcf9c8c89d8dcadcede5e6beec7c4832d8a9dc8b93ebb107b61171371ab63bbc33521ed81e1477e9ff6b60776241a1371fbba23b844c5b452529eb9e7139f18fd72c875df3111833d504d7afacaaa451cd75756dd5db844c5ac92a41c4f94f34febfc9ddd163d1c13b19971f8ca502fec40c6b2a6ca5bd35ce05592609847929f60b775ff481c1371cca5cdcc9645439c44963b8f19ec1fd98d2238628ec6446c8ae35866ceb1479268d86db177988c8978c4a25872107330e439835b7778d431115bb1ed94897358929aa3986fb1eb780441ac632236f9aa598eb3d803d5a467a8a7a807aa072aa967f728115ca2624e01bbb087231e7588f7a94790e438325ca2626af9f077628dd1be3b527ffa3bbd29dad999b8baa7cb34d30397a898aab7fb377ebd4343ef1bfb378e4f1cc771f94333397e1925413e76a7a7370f6322ee816ad2c3bd3294eb814aea31d7d49cb12d17bdf69d693c6611f4c40c8a22ce3814f19731e66455aaca95a3d7755afcc88eecdd177a3b26e257869afd4d5b2bb2bf691b057c65a8d75b767f4b544c279de9d25ad3ac0009ef6608e6239c2c08f716355bf6d517006d03307f8e10f9717d7c7c8cf0559b1f07478ab81bf460221ba02f8d08367bcc34b79bca2e18626403d2c048063f185cf085185870c55abd1954404108e64d081e3336cdd826002313b814f064966d2b70b1ed9196ee6d05413290e0ed53144480dd0b20c0a94cc6fa3c908938d0eaae6e0b1ac01730903708c03a95ba4316c03e40da2200e05dc66e7127f7165385609eedee02e96c9053e487696e8073a5651ab0b0c9aa26ab9aef55a7e087dc780085185697e935c70328d06880813fa3020d436f25a5027df041813df4c8038f09dc61471d74cc21c71b3770b479c38d36d858430d366bd240e30c35669441461a0944600c31c24073068c2fbce8c2032d1f81073014fd1083813f73c21343cf53d4e65f042f04d8f112071cac0838c16a82e88b9d2e5cb6fcf72ca92b8668dcd1120293129a70f9ef62c29008001076b2ecd40240c692a69d233c4b549e254dbb1de2f120cde780830d251c3d09476f4bd441de8a6c6b57bb4dc9906ded2ac823f42ab9a30e228cc05f5a6021aac9032547bf13074f9208fc4e55f66821de79dd9d7607cbffceac294bf9df61572999944a75258d9d53a85497dae1fbfcdfd1b0ff1d730704299e519cc0ff8e952affdf028fb851f97f203b537e6a4d559a0b72f088e733c383a1783a1a783a2035ce1275b9d69f40b56cdb7a2cfa8519264e03ced5b23b4a517e27ea08d21121d9be2a77a0ec40fdef3c79fa4f5728b5752857bd5e7c4d9ff858f1f9e065fbca69e7839da29da61da6a51da59da49d273cfddf71d2ed20ed1cf1700064a7c98ed1ff4ef9bfc364a7a888acc829db5733dd42a92acde8096af7aa7f9e2178f00c91c05f0933c3bb43be213f3810b80df06c38ff394a03253408c28b7273066a3238f3b27d75b22a1157d32846321e0caee0c1e089ecb9d9ab7abd7295108b0aad3d4968ed495da6afb45297e955bf9a0b71242419bbba2e57d3284249768fa2a17c28c4e3dbeaa61a6789de1a67898484b297247b505e77658bc68c6923add6a9be30a5094125d93daa82113e57993c1578c05301e6a960fbd95e3efd4d5b2bae4f77e6fe17d228c0f2b4dda3dc7436e4a6333db5ce64a90b65c5160999f2df44884700523c93d9d3f67d3267ee0454e8b6ebb60441100441f0fbbeeffbbeeffb3ccff33ccff33c2fe79c73ce39678c31c618638cbbdce52e77b9cb5dee7297bbdc65922449922449921cc7711cc7711c47511445511445510cc3300cc3300c4310044110044110fcbeeffbbeeffb3ecff33ccff33ccfcb39e79c73ce19638c31c6b8ebbaaeebbaaeeb30499224499224498ee3388ee3388ea3288aa2288aa2288661188661188621088220088220087edff77ddff77d9fe7799ee7799ee7e59c73ce39e78c31c618638c3b4c8e62087e5ec64a32a4293c0e24fdbf6e3b1255f7a7b649d54eed53d95fde572b3d73db5ed3eaa66a26432d6d6fd68a55d175684913a96c6c5bd96ded59da941bf10cf1ec64f13c3b293ccfce93ff1740077f44039267e77b1e9d389e472789e7d181e17974ae3c8f0e93e7d129f23c3a0f3c4fce1acf9353c4f3e4acf0ff25d213bbd4764dc4355191935bc6de3625d2445da5bd3455d545e68c46c5b2aacbf10eb8556f9babfba9d5cdd53df6b6e9a9b735fdb1ea684dcf90544dc3b2e3fadf69fdef04d991802707f6bf13c1ff0e04ff3b0fec38f0aa66c254b4549a4e4c4e4ea559264161c2a4644a195252d9293d63db595295d094866aea542cd4481392f517698a5585461a525fd3a9b5c499f2cf72add8f5c9eb7654f7a4984b6b9a31edb4ed329aee496bf93c3f0af91f1fd6eb7081c5bfce163a5a005181efffcc028b5ff59acad276bb29ff2dfa501fe7a0f40a2bfe65aeb6dad82377e6463d61e29a54ac5012fd6ace07d85b9eb2514a681bc584b6515f583a41811a5a6a82f45452417a32999454909286909cca27734af9c42c424a2282d2f4edc1c5a36dd5ebd5dbec954e4d23f8f4f4ff5f4863f3cfbb1e1dbc9e7d67b5769bdae5bb0bfd088d348e84070a38cac829ca7dbdfea752a19f0d88fba4e617d25e5675dd9755dd9f2fa46d405f48f3d9464e51afdba7d0360a6dabee10f2bfd959c97b3f3591c9a2d5e163959299eb4aa221a2a723cb4ccfdcecd1424c1b6963c6b42f4c99e6b0e1d373ccd89ce3c89831ed4dd137f2cf2a23655d69dd107ef852c257fd93374ffcd3a6d2b389123762fcab6a88a1b4bdc9f566e8bf88db72aed9f699cb0d162e3752b889c581471c640001134703ffaf571c55ff1f7b532bb7e54c73e6b691e28da437baafc0023f7c10c2e1e0ccb3b6605df1ac29583ab0b1bdee6d9733b0a0838437cc80e92226040d928879bd2e5566d858b1410b3f5d885e1fac228cc14417078e58b026878516b8840195c6055cb411e012460826274baaa0c14546c613211e013fb8886b9298f0341bb8fcb8800ff2cb048ed8a2050c66acfca490b48506ab9d23862809c096fd02d51315ccd0c116244d62d016e4c0434b1e0e448d71eba0428b140118628a3247462d2d0039816a0b283db44cf981c84848097768e921410b1cb2ec9821bca16200893dc6a410986062460106a082510824fc5003e704255e84d0b4c51be06b06098450811ae590094c01210b1b12722c006ad2250b1262a86503b56709018503c04622d82c460b74e025284a0a5924004301f4006266b5341f1501b0caa254f3a1851c3a78c18c925aeb40121220c0e05a12345a5d5e4f841a002c20c2c2ca1dac2b2fb4803327204c5ddd8000139210a2ebe16a2a88d70f141d63ae321c66864410451e567d202df9d6c0c18a9599d797326db81c618580d365831399032bf30754d01e059859f96c518502121ba854d131c600c2a4b085a7ea01509871258b265375c2149b38cc2c21a9827aca400a18a114aa36222e4424f58186e6c60f3ed0705921074d892dfa58b202f204cd8b0f9d8117645334273b80614693110cd07898c8e8e23e20c97b460348e4282ab0df219a10c08d2e68c0e1a579a10594378b90778886858c3bccb85e06dc5c2043141f0ce0a29192c61035a71c5707350b2042c5cb85abd6e0444e0b45003744a3e3a24a55162ece920aae169381360b2721bca1071ea29d61ade20418ea38a13d1f00001d8aee00a30deaa34d400e723c6199401f514c40810a69b094c95f1959c24803cb0a0b60820f17a6506191f202123ce48ac2b2011045a078322498b971d9047c30b4316bc00f073c6584809a8db0bdc1c406138a664d1540e1620bb9c58c82324d783163a50bbbc60619b2904d80057bc496124b4f10256c9613c8123b0580812d2d781da1b2a18a8d000d18e268620bd02a819c215bf4d066ac3dd8b0c60c7b10a0cb8ac58993191498fab2762044065e50cbc2ba330489280e104503b22e945801ec408b99cc06a809c8bc90861a32348821aa20627a43968744bd12e06ea0f281b3410b788c11552abe36964c91c714ea0b2d3051c3484517aa9412526556684004d548192e21034a402a3a70ae0081e547a81c70a50c3ebaec08416502942e385391a17ab2a2a10e9fa88e4a83225018c087374957d878833592a04200ae24e1e60b6e18064784b2dbde387a6127338879fec4590d8ae36a2fc799b8f6665602700850ee1e76f9433fafeb74e61cedaaf9a269cc35df96754d30e37829fb4986a0179e631eb5d875dde1b765ddaf0265c737173b11cc7ad46407e63eca1014d131672ee6b1839a63f65dd3918f120ccfbebb477ebd13d13cced89609c7cdd8969324054aed79681776bd4331fcc48e7b9a9c9a927a7aa092f620412c7e2299711762307bf8fb46d1ebc00d72af8f3914bda935adf10eb3ef8a04e69996792f4b8f121d45bdb9debbf79888cd99968978acb56387f328398945d0033f32c424b83bb2e4388e834aea115960e1519227f98d7b730fed3abac73e8192875af7af7732443bf1f3ce3b4a8fd4df78ea0d861df86dd28e52e41e7aa23d8f2117fb178a7594ddb7c58dc98ee68f1c3b95453f1689e38c7a8a7a907aa0927a665a89e3665ac6716eee301d251a7ea3d7852307f7c745f2a4526927d932a1ba2715f544f514f53ce929eae17db562e2b8b653b55a8676a7ced9258ee3384ec42188f11dac39ca8ef7ae8b24b83f54f753d43111cbd816fd7aa09af4f0ce713d50493df8c341b0e42875f6f6e981212649deb94792c07a53eadd9de3b8bff33b439204b99b12243fac71487678f44074ec719462f74e14dd1e1f73e76171c3519218f4d00d863c771d18ea31266212a9a7a86d8d769f3d711cb77bd5d8619618569bb2effdf52d669044f5b7bf5a13c775f524c1f69d49b1de28c751445151fcf4f99d61ef27cb0d8cc191fcc20f04c390ecb2378a188f5def20984f4d7e797bac364a8f243daeb1ce1b6f10f5381ba597f3296ef11bf7a94f71edaac9ae268977e7ec06b739e2354a1d9263f7a1d80bbd0ed52057a3ec783f79c7b7c8c3512449b063b129f5e7ed7c92a038628cb3f869a8252ae607ac3525e8811a3dc34e83a03ec7b0a75176d01b39d7dde39dec21ee388ee3a6f4cb716de72c344aefe479cc1d1543b07727076322c6d2cd174ba939aeabef4973396e5ca262d25867781deebe0ff4c64f0c470f779ee879a09741fd7531a31d7be08e89b865abb48a9a53a9aaf630d7586a4a3d8264377a1deeb8478a21ff92586694e7d8f1d0eb5b9fe00876e8d879e7544462f67d7bfbba694b42b1ca28c58df9de79ef8c398a6a50ede952af62db268e0b45ecaa19f3c122a30c39dee7263bfe32b9f7e69af3a1946d2a398e771f5869ca73047777ea737f60c7f947d2786fc350882581926f4fece0f6c4afe3243fc30e8f1128fbd8791fe98560eec8bc4f322662aaad671fd86a55ef278e13db9000ac314a7d7e5ed6e8d99d24de5ca5c93ca8262a4d89e3bad10b961865878e5ec7fa13f3f9799d1c6322a6ca56ec0c0ca30449b0771bdc9d16f73ec33126e2d46cb1b899e338ee0b691cc7711c27b25660a129c73d8aa8b84f511cd12fc45d4cc4ec3b62f0fb429a17f255a4eaaae6bdaaa5ed102f5131abb0ce94b9f378973729629c35064130cabe47516b10e4e8ee1d14bd2f4af21cc1ee13bbecf5eeec204af3a2e4a2d7b527927d6f8e7a1eeea2f4b2f7e15387b86f10f43ccc4529762fe3108bbcd35c77e3b845796ef00c49116bdcbfece50eb3b4d821ea7524cf5f0e3316774cc45f28ce64a987c4caa2243b71937cefcf133badbb138b72d4e2e789bcc327fa718fecdf1565d7fceb229af9a9498f0c452b4a313cf3e771b493e0d745de55517ae0cee4d889dd798e9e287e66cafc7de4f7657c76b88738f4a828519004bf3d8ee787c52f87798af21cb7263bef9c731da2980c31044a3d9260d779077a2709e22cce6650a4283bdccf6ff74f8bded981dd78d58fda6ec52681c02a53724c76b1f34e7d821d6b0f4d89acb0a22849fea17d771d04516fdce0f7852814e5d6e4994774873bc431d61365f8a1baf7bd75d619ec5b8f4f32b635e2388e6b5f3794d1d607949decc89cb528e291f4f0d7410794a3b7f589c7b0eb1e8a4734344996132507b91e75973f0e6af244794cc4567df5dafed4be4f188bedeb36517ea4ce19a359e7500cc51ec6442c635b9474dfb17d5d326538826197353972b0eb3239caccb5ab22aecdd80df67090d603d57382b41e3277161325b8b9ce9dc77b3e3f8e379997b01a507adfd975d6a3c6d8fbd0bd4326ac31251fb9d6a326c7af0bbbee9daf0c35db2e628fc580f2cca3f8f54e04c9affbf2282ea0dca7de9d878e9df7e1fe75a78e2d518ae83e3149ee8ec50e7b60672951f253e37014478f93e3497a6288dbd7f59228470fec3e94c45ed78562ffc4d75540b9f9798e9d1647d4eba838862acb9e489459ecc08e3c3f1493bc8b1e1813f14ccb8e28c92e0c419044bd3d92e8c7c554edb011e519e6eefb3ebc41ee851924dd224a340c45b1db249a43318fe40812516ebd37888258dcbc1343cd3f3165ee488ea262b879c747ef0bbd214a3077dc134332d4591cc98f67214a510445be31f7cedc47b1eb6010e53982e7873f11dcbb13492cc6448cb1c802a20c7b3f73c71dee611fd18e747f283dafef50c42229660f1c41d4f3a1e4dcc3b98362e8e9b07b7ae71e4a54e47a04750ff90e31ba41d30c330f65e765141c31b8499d418cee9888772879b77b276a1005370fcf110c538e21e89160377ae0486a0ff53e960e25ef401ea260c7bbc6798805a61cc5b07b7b2433d6f91bb39e791c2b87f21473b749fee9dcc36ff72f26e28c43497621eea8b7bd917ba7f658fe61b07ddd1bcace4345d41bb1d7a123e6dec9b2a1ccdf899e1e397661174fd03b6322567302bace64eec48c86dd23511d13f19831cd7c65e8c8aaa1dc601fc78eb9de5e48a2181c3336595f4614837cfcce133cc11e7e5f4833bbdbead98765b4d55362d1508adaebdf476a527b5b1c3b99bd23d60ca5f7e5ef233d3c7aa70ef53e632236797f4dae67246efb6b447ac092a1d4a74633b8f5877a9fce6168aa5a9692192c59319421f98da3179e1dd8f12e92e84c2b8d2c184a91f4c8feeddd33f748908f31118333ad8480d2d37c7f5fb841b08fa2e7893111d73a9517b25e28d1cd33099ef90337297a9ccfb4920ba53e33e879e0a9f7e891587faf9b26912d94e2798e27f98d67df593c45302662f0ede3c862a1d4df38a224e9817a6fefecce6e8592dc587f7b7bdb03c3efec5ea742397e282a927b24c70eeb1db2522877c67c0c43efd32288d14f8c89187cc2787c65a8c742a114f9398e20d9bd4f8fa8ee3a651da0d4dfd99d19a322a877de7c88eb266e8a7542f975540cc7b18bb8eb9993a087c3cc32a10cfb17eacc3bece19dbbe8b9efda65b4a976880497a8985258256c3ce60fe3f0cc689775076319c0db63d785587f64e76d708c89d85b62915092a1d879a4d79de0f971afeb48cc1aa124bb8fa33df78e35086e0ef235b55a69ecca2a40297e3b77dcf376163bb8c1992cf564b4d513a1cc7ad49bf432efda3bf388b2e88ab4d35537711c8baea9292e513151160150fda19db83bdabbc7bbf164792943f0fc506ff4c86f7394f7cec361ee526a706f8e921a3dc5be37de31d174d38c672497d2cbe7d835cf1a25c3f1eb674cc42137bbacc766ba9d0271c6e29632e467cede26c1ac41de7557dd9ca29d9d9b61ce62ab63fb7bd252763b8b5a3c3b0f87e73e35564ffdd2649d371442396e1e765c24b3c6f82345de6529fbfebe8e76233f5134877b8c899877d3cc5955fbfe6aa5386611eca1b849117723dee11215d3ca552962bd4f94dc9ddede279e23c771bdb52a49ee65143cf7898e6088512f26629e9a7d567bc57588e36aabf696a89865558976e226fb187e19e53a83bd07aa49cf15479a5ab513c7719c3b63b1b844c5e4b47263ec7de09747f0eb449dbf9888fb9bb656e02b433978514f871d1ecf10edbcdec99e2575a1701cc7c9686b08ae18ee1115c3ceebe4276611cd1e8d457bba4c5367b21494d156ef95a1b4b60c51dd8dba87e749e6bcc9218ee3da7736864b544c8da504c57de6f3eb34b8f9d69fde9d9bec6b8ab88359b949dcc3f343cffe8124e63b2662f39bc296dec73dd2434ff123d1aeeb5fb896e887e630c41be459cc200e4159a977fe50d4eb421e9e3d0c794cc4ef8c35490c26a965d831de58ec67f7895aefadafba1155398e9b04f348ea8e8f5cf4784cc420d09552dc9cdc5e973fb477e19747322d4154f4341739d891f93cc72e26e2d7053152ac24456f04b9ee78888e1d45bb98884d9526eb70f75d656f2a251a43196df5924c95bcf3ae7f58f76edc1e39ee9888dd114fad2915f942cb9014bbb01bcf8ec7eedc201a13f1da5573ede69741b0971dc724d88558dca8063949c644dc612b7666aa3419b9b253bae5e128ca682b112f33f75010a3a117a23c83986cb2f5c93dde773f73efbaf3d43130b7ef0cea0cc571cc62388a1d1992b813bd90ec7ae49ec8bfad4f8ff3a380a8d47209c645e91432460000c468020424c31100304024188a8562e17050301cd90f148002548c5ebe5440178ad32846619031c818630c3000000000220333b80aa92aacca547144c509b08644b2ba816a2a29136f4bee651fbde01ce9f36bc3f346d25a1805597becc63af2b65259667229655124b5fa84e0895df5c73c00a7e547841ef5a4b5425fd7d4d43f69da8bb9cdb0e4d71a35bec0d1b892f8f40b23ca473804a02cb4851433904b9e622650194f0277f1d0ffb2ac078aa9fb24c6027877484e116cb16533e8cb558843e04bc2caf509f9d77ac89e787b204d8939d823707fc3d8b39475ce4386e4c8f9f1bd1919647522cb8061de5f98daea6aa6507d2049a55a0e9c236484ea6f17b51e7d5a3d5755fa0f2803c563166680495439919a04cd13b966edc09d4f9ca7579ecf4ec297234c3efd2833e6b2834bc3f759f35a3ac457484901eeab1cfcb83b50d27cbad55c0feb0f14771039050bef3894c30224bd033f1ee39b3e9d267cfc0ece65e3bbaacc86555252765d90792ef3006e15772dd032bf0503a710f26033fcd33eaf506d09d969a29eb214343514b3915e2b1be955ba99dd4ea4ac5014e25abe507419c0a0a6d0290310f3323dff539576cabd81f7da014f270f721d226996d18eaa8a7c079068d675f58bca5594501980fd270c4f6d81a0591b1ac0d4a51b13be5b3758d65e8c5b27c1417b8bcdf0fd804cc7e510c8a331460c435cf38396f95997df690f008569b69fd7b5512784c95f9a77c6649bd12d75870a5494b218f2cfeb4651f455d11c712030293789bbedeb6c2eb4eaf6db4a3d4d7446ad859ab532aeaf58e05281ce5af1d41e0873953515b5def75237bdebd45207ee8af041fa8bf625ebaf047df8abb4e15ef6d607f537a9bb4bf91bd88ba0bac37a33e59d21ec241c3105064132c8cef5e0695c28b6ac365e1e4695410c11d9e013e6af73a54962e19cf04ca384cf905b48e3c2ab40da0011980b7d40c08f2d22c1bb80e576dea2b5723c2b53936d4b864d480d4150e0dc975e03a807bc87ddf9fd1c8564c3422f20e3ba086907a04d23daa46ade08c9e3bca38de0f4d4224eb3822f7bcf82175eccefbc1a60a0096f665af42019ed390040a0a2898453402049fbc979b2930644da4372b493bd4ae7f6110138f5fb072b546891c340566e59e4b8d7864a7b208fc4642a7a084204fd625484881994ecc1805e08aab2667d8f19418366e1f9ff84879dbabce9bb22b9fa5cd812dbbb2450bbc10b94a041a0a9e4a36bf3e328a7a5f1347dce250701383a9143116e1494484a685ec071d19bf8e58f8c5a78c299352e2594a5bd9fecf3225d8f146289a1ed9f08c4e864661db27ef3cf1e63df66d67f9af0aa59532e80f1b7a313f65993184eed2d80c2ac245867bb005792842e5b89162e92489d617a60650340fe03ff63dbc05d353320630c79dc3f0c6e5c1c65926d5d423be33e2c4af5245add0fa041bde670a59fff53315d37559b45ea97da0a7b355e46719905809d00513a8dc379647a6270394323775f446741bc049b92a13259852fe754a866546b39325bb84b5b50fa31be9767a72a061f92399fc06b9c02d1e2e38c0987af8512cfab742100249f615293ba9203cb62e1ae1419aef5e4de38620a12203071cf0345f590a7ae906a2aa05aeef50a4be17d41084ad2b6e08758aa1dce0f3d21638ddfce08a137cda001f76584b0d843b04de9983a31a4fea7b8e2cc3f709118913196447df72f9f5cc65a0c7f15c42224a7e2b1d6a85a87208f34ac6c2b5927327d45e74b6f8fc820bf8cb7fcd50ae28ad45fb27d92b88b282ab6a90c4f4f1e0252c1a1a2e9aff35aeb712ed643c5abd6c865d18578734bef679ffae60e5ce4fc3163178d44495893fdd2a0ef674b55f0d8087380d6672e523930c53e5e9aa802abe931feade71f3f8710e04262751a44be16bfb7342b5a911eb56a3e10db1c6a04094d3f205fc3866111f4f648229849eef6f3bebb08c92e761930c014e9dd7d232a9b2c7227b1ec2af301eea8ab7ffe795b7e885f8c6fdb017402b687b702ac19b82e8784720805d79fd236328cb3084859158e39ea6e50e5ce65ea94da27e6db68dc681fdc16b27f07ad25745196357a2a88f9984b41a63a3d25a8189ef355cfe01b7beceb105a03c3b1e45370878207a6cdcf5b9867171f3951a9f3e1267cea86049ac0caaf8a0636e7e037db334be795644e70602f9e4c1de1c3d2f41b910cc9172c9088271a9ea392644148520dd1b4989da2a84572fb979f253f73aa5a72cca79ba94397406d79d0021d4367ded3e1813f755bdf069ed373ae16b9a41dea5047e223c34473727305a90c0860747181ce0db078cbd24b2af1e1fcc2cddd95f56f89ba313d44c3e359f64228e57d8dfc01619cf902c25684b977a06ad56b91e203c9b83b87dad02ec0b9bbfed486669b5c92895c9a3df42e6286aa9373bb617aaa36803d60bd6c28d185826cf4d2c800f74b400810f1bcf5cdf950c6e8103a94537c58c401ef01c969466009a49e298f9962debf44bf01061f4bb6c29aa49d6db54d1b4c5434c2d46bb2e47251c304526a9c13b18253fd16874d6e80dc88c2c5671c1310b15c8390fdb456f5711bc7c8cefaa337f8298acab2d08a7feb439b8973d3c9450f098c355049d40bf8e29e23d511a3b6629c9c489a8eed845a05789c0a94dce8e3a91bffca53f7da4f34db2b1439c09798986343e0ee80de22099482fc8620df3f79d9f7a469f910624e0d37450f5e440f267543f6bfc16ce2d8e31376f20d25f68df5e45c6fa6cf3807d42bdbd3326813d3ac56218be02959f017bf50e9b9f1584485ffceaade51640d1e0cd568f3c56c887abc3053d50b9797da6ecaf7b85ce1d5edb1f5ef928c466694aefad46a5481c6cca943693200ff45a8998b29352285cc80fd293b5aaca1432994bcc4c287bc81e10a2b6f971c0e8c3c288d67e7a4e723ae5b07f862101c1321acf840e1e1cc98b62a4c37a033aa73df986ae14c71b29b2a1e2fa1829e7f6cfb311d2fa01c8190412700d8fd6dd8b6c4e1e52d8c4cade52f176e675110b2a1ff4c78a358dda0d3c12ab6e607611b13205ecccf629be7b139fcefcea0db1040c928c8df9f34b19472f160bd6ea72f4e28625d50fb2892c4be176da8a03126a872959b887cacefb396c5681594dd3be86c6a6415054a55528acf4436430e45a5c3db24794ad255291e973c55eff6ac0d4af0e5a413cda1b0a6cfbf13ff44f2064d406484012f7c40df76673939d0ba571a8b04e154b5098529548dab13f0913ce26d8cc67090d42f6105a658d287bf4c43d496b1c7f843c2fa41dac44485f13d05d0aedb154f7585155b64ed74322f451ccb09481ff09ea2cd6a82b1f2ea1028472061e94627294999e37ff6014a9e10df05aba80fa23aac5c1c949ab56ab0417ba2609ea998b6f7719b8b664bd7fec1c430132ce7007d8f7fe761833e8c3ab5648f803e42eb41745d8dfeba4ac13464dad10749d476b0a8cb59e3d50ee51299232577f28e2780224f59d409c43401210c83c7365af00d5dd8806d28cae8c206c472b125badd1758b089ff6435164326a6f00685df7ae1ebc530bf989fbc11e4c5a5266120f711b0dbd056b0b37289933f65aa4b5c4b3e26aa63483f6619aede09f321ef10dd1e42844a3071dda33545c525e7abe4adb4f6842c9a86fb282d62e333bc2d02dbb3d07b9c6e7d05ccdd50e9360ebb900d0535410cc6ddbc5ae82443a4bddd7ad0ce0d26e956ac2220f77f3c75d6c7e50d011265c41b03f84b2e7a1f50e506349f3ba6b560cec2e742aa98f94170809376d6493b8c894312d0020730903b592c0d3b183f85059a0424a3264ae9bfc4b68e3d291e1f4ae0e49d96f1dbb34928409fbb9f9f1f22842b090b5423d2dd1b41d1828e7fe585e1d35b869496c823e1aa88bae5f78cdc66bc6c0fd9374fc007abeb575d45e988278a79a15a10f8eb6cafaaf07ce9bb9c5e98fd36dd405b405f77aca741f84fec54a73616b796d5d439c039fe3ad603e433378b6b81e4e82d61e822364a83089d49ee46554e30bcb9c61e0d647c0c0d98c2e9f7554c6fd133e57f7f85bbd32eeb7c786d7768278eed6907e4e69cddd826ee5148d69feb49a5a58e8c01f4028fdb4f80bffc8b099f4c5fc0b78024acc07d1f3d5ba3cde2de67e618a0f0c18b71cd1ec47bbb824628f7dd7a30319b1653187c417550ad526324bb1b3e75f23aef3cb01a5fff775a5ce470d6da758d23b994893575dac18d9f08cacf80e62708085c73699c167bbe4d879e38e4a59748f3769fd2a50bbaecee23d1226c8f6d4abb3582a1112e257a85ae3c68d5599f93dbd3d9cf7a1a4849bb16c43ef1f20c3e6c2cea60c33e3a67a0e3876b90ff4e10f78bf99a8f083e5a4decfa0089ddfd64db7976055e65f08d3341e22757a82e1ffe14d0a494ca93799128cda3b1fc3c5e113b7ab0fd1d64fade81de10637ed844d39dcb7bf95ed78c8c12f94044bdb6617f7f95d8f246c016e8c81ef9ddabdbe15fd3eb3e97406c0af80c326f911f5eaaecc0f8841dded30b857793a925cdc69ea64fa91e17fd096460e8ce3aa52cadc4aaf73b4c46abd250b6187f6f4f8623d9cf95b9e4689ae6a66bcef5423b13c8a216f64c8257b5f7f1d3a85193d0ced745e5e1fa9c355bc3fbafcc53ee57dc887db11cf32f3ef94515244673ab830b07616f41838f64086111e9f7402f1e836c360c872359e5a391ccffa21af1ff061f278dc17967b74e1982947c5c42605d242898f6884f45244e01f91b6144b7a146a033b0b3d6725796fa5f46a20e6fba196229f0acc4011d3a35ebf7af16b91a49677ff85aced510d50f93a55974f336dc0ddca42803bda6288a1e0b10e71f6e4e47adab7232d8c0f6b3823b122b3b68d0fbad58fa1f1d2b380b3474263f4d9ab5ff77f26ec54ab6e5b6db028ef23e987c4913d3f0fef92a8586fd066e10f682bebd83668e4534ca4064b0c3d5eb0e20b0cf412b61691a93e2a3b520de32dff3230225601ac1a4634336b6cd9be60e9956b845d262a229d2fa989bbb2f48258ce4a18f18b08070d2f9dcc802b4f433c6b8a36f7701e453b2ed01ad2ea7a4f8fbc97075d0abb77f7a53ab97b5147b770e606541c3bd7f3b02aac1e832133084231835cd9fbf00576a80ce0fd694264aed8df8e7302dbcf99fc36081c6b561e2677dcbd6bd7ab0edafb053244b2d3ce1184fde137ebc24f60a1d48c02cc56b53ca22b62b86681631b9922f50ff25a3b9a41627a65da80061f489ffcbba6f48906871865a8c4d2d52e849901565455e5b0d5151544a0982dbcd9070e84e2f56df050e9bb67984211abdbbf6b7eb74944154b0c8df3e90c8f882da014ce91cfb21ca8c29f8f5972714765c84688682f6ab970ca57b1145d61f9497f6c38db2916c0c25c5e2f2e3eaf567ac52ac5dccae5278f8ae59a51000fb7141f749906f22536a8e6a1fca8f2d9d3f101c37185db429d11e5d2969aabc889f1502241efc92e3e24bc4a847ac369adae2dedc6488c6540cb4f8b9eefda596670be6ecfb6e17b832bca750a399fb031c3d18898a8eeafcd3325325d668873fcb3355a09fc57ca19253f26ad1adabd5d529affba8ad04184c6056abdd9504e9000ff93233cfe01134545160d74a8e23a6dcb2f0c12674e3ce86d7cbfdfbd5e382513dceb56e9dd3d00c620ad676efc5bf43dcf104e7b65e779fed8b25a50081d2a3e1cbdb80a15a7f458c8001269e745154436f567a8ef10d17e64f5dfd23859d7651bf5c17a09022463ba4e007a0a5d6bbdaa1a17790834464d20870aed02c1a68eb2d1ae72cd04d235e64840119f9ec009c9b060cf814df9f7a767af0d7a99fb23e9181781639a640e42c8330760d24e5cb4f9cc9fb7001e2d3e43ea8ba7fa38b1477d5c9ac284ccd370c251127ea4a1355be6844f71c22a6fc1f0b6e96ec71f7e7260ea7ec4913f6c6edb30f62e319026c1ee25013dcab07973382bfa08d7616003c5415c4ee25664c5246c7372db0902a5615aaf7083f74d37b497496db0824f8eb2ec3459fa7fb33c36948a5105cca89328df572774cf024a0767c82feadfb46fd84023eba1b3945d338c1a1c59aeab3a8a8304910bbe00bf6a56861a9bfe0529edbeecea6d0dc0e67e6131738658335d348316ce06eaaacbafba05cce09eb425f14b2b98cec1edd06bb16950e0b88826556fe30a7c97b3aea58a83e84d3df19e31a44cb5d3f87b1e0b40adc6ab4e199c9bc991ce84608971bf25596e2db2c479eb324916b05e7bea98a337b92ef4138171039b6a367edd9e112b8ace31fbb07f4ae0d45d10a93e42b51ee6e77825b802d7dd198e0b895b00d7d094bcd370ad18ba3f360b4506c704299abd12040626050c9cbca3b74ee1145eedb875330c5fb061fe1945f58edc994ff31f1265ac0d59fa5e48a1f6fc67228ef19fa0b5179d79ae5c5d4fc2073fc92916ea7dd0ca596fe31332c5ceac7d4bbb8b05bbf5689543e3d9be452bb6df6104af5bdd59e4cf91f136fa2055cfd594aaef8f1662c87f29ea1bf109577d63664e57d9a7b881176edc32a99e2bf87897cca378c7e42aabfd8d8932de36be651ba53e8d28796107253e03642b5599ded16b6c0aecdd55ab36a0ea0064aa60366f5d531ce690edb5688ca33db8dab43e6aef5f5ba837ba96d478a80f9db532fa5217e6fa0254de13fb4d7a4fa50ee78575b05b09f192c5f0f26ff4c6ea02db0179dd76804ded336aaaa87e57d0b757406f80cdfcef404fdc19d62aa3c8940221be51844e693f30e99266b18f2963c0f04bf59f62054dca571471035097df1535a7e129c1bdd04e26047553431732b8720c74b35eb71db704eb25b3534e739d884328dae90b28d2510f9e5494305ce2419c4033641f0956c4696a285144f8e20222620b91119e4248cb2ecc4cf5ad95d9d924111f35f1061588d8923fb15e1b0d965a89c0d911e698f213a487d23ffd919e5ec96888ce64e7363cc154711e140f1ad1c0bcb68e75626b7a1eee33cd19aa8ac3439bf88a6b5c3c858dceac3e5dbab819c94aa767616ab926dbc5cfc2a95ebf92bf21fb7c9ac63d7737ed3b5a61f1967aad9944f224a66f8efa179571e8764ee59b402b30258159b2a3f6d716d348a170c812ec4c2dc26bac46e1dfb92ffd88964404fda6264cb0c4031c26a6d2eda5613a1fa5e1571a19253070fac1b8d58d1b436ea03098cec05c59519d6b49fb9405404a8178a33aa1fb00e0105d7a6c4b75eae2f8270b3d17c578f9c76200c4164d5bf3f1443acf6385bfd549f70059ba573675c1a375dc6416cb9fa16ec4fc3c31f9d98403a0334ce75291a8d3991e24b9c5dffd5cfeade9bb65260b5e6436f643de28b613db13f23d0981438db69f4f2c8b199d256bc979d8e5bf94195632b3070b963a99c6ba66be5a2fcc9ff60065e41e846a1f4e8000b2e74c35365970fd20e21dee61df0ec4a9879268794f2171027457220f4863fbf1140b5e7a7eba760195c4089cc918fe04a04d5f536f0e5cc5dc2ff7aa78228278d6005a6ceae75fbb0d98633c261390ed4affcbc3e79d5508d488cf4638229d74b216e29d546fdabc0d22e9dc88bb029b4d77bc3512ddbbe85c8acae4270cd986b05349efc559c8f30b1902560c8ef66b8c44e600e61277ee7af4a06aec250d08450fe92404574f6b1fe80cd9aa3a9a624595f2ff39d53634c024ff22dd627990c137daaf8e8e4c9cf956cb2b82db4f4a2a54e1a97cba5021ad93e10dbcbe8bd07ba09fc4b65df52247351990830c8a944c630cb621e65da8bc40f49e9596f84b15446bca6946a7a2e5aeca82e2d6d8a27fdf849139aa81c45c07bdf5aa3ec9716e7e8c809696174d8e03c11b443333d3a4a18448684d377175f30e9cefe7e3eb5ae2cb03c2d8bd048cd13d5bf9080d203f755711ff0bc60484ec110c6c644d7896347e6b15fb8b6a7418b207001f5f827c467da1aa98cb948130a728d91b5419a8a58f95b0a6efd90f48fce27cd25ce9535b4530979a8af2736e9250340ee8bf7b60cd4b934a9049c382b21563c98bdd10000d17d4448fa33a9e745a39a29164b1269290d5ccb40389123d18a859e2c78f02fb50cca80a03a2f0817f2eb0d69ea0af544c11960d0c7201e6e70e14f636966c4827d6013d62f176f69444677e131f0022d4e2e485b3cae76c644209ad1410de5b56bee1b31eef47c858a9c26cf0fff4702ff72fa17ac867a97073594f7fe3ef6a3f01a52f470db25c46623c786558c052fb91dfabea812dd510b71ed84c7cd1b5dbb302581b3f15415c02831815935957ce588171d6cada2df4a959eb15f128dac373b08c710249931cc370b3288876248af7a75dba47e360dcd49727c4e70663eb7f28a4b8ec38819ede943231a630aa4f0808472fac3d5bbc3fabde58ff9b6cf51537b76c81ba5b9a1ab69c2e725bbe29b839b18cc3effac0c2b8b786751a5bdf0d3a00ff969a7f8857c72cd81e311647c9e699f0b2d05a9e92ee54ea403cd52b35d4ba6dd07528f03dd4b657a7891aa0b4a8f2e21853d19075fd56454abc25ef060a9150f37e755f2369e1b06873c97a876aecbb21dd6efa0804fdbd7a837670c2e36b66f95c6c4c3e1b2778814ae322d88be4a749f5c7e5719dbc53f458980a2b01400a6fc7983b6ded3f02f583fed730d785f4c95850b805f48c6eaa3077d4175b2eb2cd98b1127d2146d6addfe780111f599ae79b4edff72e1adc2fe850e4d0b1d3f78f5701750c0a6eae963682cbf91bde4938760ee82f194704ac23e2dbd5ff3e7c7cacae737ba1a25f79510b147e1a5fe212012a7a78a5ae2bcfc38cc007f5a869218ff7194487788b2cffa1cc7dcd7a7e877ebcfddedbfcb98aaeff37d350e8c0e936bedf6b74f4d9b107c2881e446954fbaeb0ee2f07b1958f68a32340cdabd13b9e63b211944583ec33e482ea873e02d9a33b78dddb9c7bd51cad4e66e21f6d6b1dfca0a4a62cba4edc8e4e04e2e44146a6b322f101c9066d6884b36caec46ac2deefaa10ca05d81e7c6dc222928de4fca603f4af2caeb89f693805f4109740fe321e1ba33dde0bf96b99a45d307f85b9e8ba9e830460b4f14e606d0dd06140bf2bede83f1033a966976fbc6d267af516fad7cada39f758206f3e1d937de7d1bed0352cab5ea164373f60fee0d862f409fabe5f36cb07533e6b948b5d0631399411fdfd49bf5feca38b176928b0299442ad9b7e18b23c9efd8a625f905e06579003e52487cfbf29ce191508e9410f2fc37d5eafa62653eed56b8965afc58cb66e28c2a97e5d80e1a712c46dbdfde3a23fb5488c6b6ab3add999d4059cc8bdab3bf6b4b269a142595356322395ded8c6f51f0ede52cf13ec8a77a8205c365e2da65a22d636f4cdfa88c35dfe214b7ae7d395a5a41968d26bfe480c78f98f3b2d7cca2cb32f439e2babbc81a0536504251ff9f31cf5801bc07bd22d1c428372e7e7e0c14878d99e42da84cfe0eed1d7e9fdbee6be9660cbcad22edb930f00c504fe0c082429395c9d20c638ff28ad4e52e599754d60896aa402f24d0340824f89a1d2301e23208650af1a6c278616908a7df954139a5a8f5ed97fe4817194b3a663b46f78c2e4b510b3456070b905a85ff25cdf35627d52f776efb2f04cf32c3011bed2812c400003876dfb230b738fb23d3099b1d6074b805777b91f75e7e5a0dd40612c22bb9c1e807e4b84e9cbb11e3c67f3869b9d2afe56f8b4dfb47d1cdc6eaf8894b9f527434c7366d6f6d157476dc08b129174b75722c48c2154f0a25c743f0212ef9f8e78ad1d4adc9251c0d2a53f02eeea6815e3bf706c79bc390f022f6ec4e746f7a2faaf65f9445be726fa701e2d2efe95d9518596cfdc91394a36805b17e787d469a168ff5d98c351c349bb8139ea181f8c712226c26c16ed33912835a334daae18e8ffdba3313a11a214172891f331367f78fc5c3b1bc4296cda06ecabf02498964144c1d5ba955386bff137e1a6b7ecd5dd8bcae0abe408639f05c26f89d8bf583e45732b2ab71cd8d74577a3f177587869d63da9cc28d5f39770d77269e173385966926ae888324901627df087cd7f38261aed3d2778bb00e9cd74f82f089327b11977b738a31853205335de44b007401bd9b98fdbe8ca49bc57bd77b3bb3ebb500519f9a108d3f1f7f15d36278cacf731aab6b8bb4a8dd345c7bfdc1ef188b43177fe70e5afb5a5a683d440f89206f4e723826325661efd2c24a3513a69d12fbe617a52874142a8e6076383eaf89dbc818a95193ef2d7cbd995e68fae7e89ff106b07701c90f82ec6c2e18e69d40c06d1a66b0f143e2fa3dd4a981c6bfc39912c93a1fcd1a3a1bdce83bd8404ecb97305b74d163a28eeb70d55ba511840a88915f86b68844764c4fbe939b291372fdeca1529870ecf86a61a920a43ee747411388daed031aec217af5e46ea00f4639d7c1882ed04ebf2c2df157166bd0f7cc94f46512885c9815dd9b7d5ce581d866b14a0e9893520cd0d21d4439875a118366acd863a16006f8b42264f6727b6ade8042e5cd34440489a13eaf248c685278c15dc1def7c107b161ad215ab67d74604a02ee52b60919a3a83f60db0e14ee6b18b2c167ddeb75541254e37666ebf97999647353ad4ef704090e6df0d5ba535d48309498a9d3da15f87159fce7cf6cf80b169482e0bb82e13ee37b5ef6967d32a65d007f0599bc41a5dc6bc5a05fbfe75e902f30caeab8447920f7dc39ef56aa6cc1ff2bad077a6f00b78d3e93e63ad2e42e5c7021a07eebc412f3526a7c90a21797f22c9ce31bf78ac58ed5f4c156b663c95a2ddd7bcb2c220b8d89e166b8723c5d2b6d3a3ca90a0c3521e8431e16b9673e56c87ee1c91cf4d20a422aac232dfacb547e1db904594225ec9bf8e52c3deb9cb9d2162e0551796e4b58a3c3d430be15414cec044835ad296fc19257dceeb3409fa06585b6f94b74f19b10234740e5f2c791d9d00d2d6c4ee208991a83cc2d87107db14e4d687531b7216f9558e55b0d2742c855324655ace039528137b6c3bdd787e365bf61caedf1e6001625fa4988032fdf96c27ba60f31464939beb0281e0d1a8254cb72cb19693bd00ba3a721148b26799208f218dc5a30fcee78a37912b3e054fc783dbccded56a3f7ad4f2990e20b36f80ea080969ebc20736c1e582de7749e1e58bb93cb1629589a5ca0c8b7d5198397f53ef671a19a903075e6ef58e6a5699964b30201d392c3f3f9c72ef2fbdba85a7ef9da61a7a43adc8ff02323e19d77a80009c17ce622aa2558f4c48ea20d8f928990a687cc7435b86b55f78ac7e4b93f84105c19668572340d43004914c5a742509641c17f65a5d0be40dbf082641a8e5eb36806a69a99bae544f9f9a432c701c048526837d244d7f86cd5a80c5accc2c0c215fc3e04c2b89897d1ce46c2b5a3b93326b9b16988f6ff8782e34c801baf2ab517c90bce5790d27c8873d917caef67154f1768efcf00b8a2a4acc223b11ec155abbe8594d63788607ba803f804b74d3fcb0a3767e30646c4c71cb4792f921f8e79ccaa62d707346e7e62f29520c0e8c409e4724a37f34e316fe119fa310ea2da8cf2bb9487e659e0e7db90f8fde7ede96bcd02b2f0b8b6f5edffd9556d498ab54f2bc99686ccd2800f041fcdefbb591d99ff568aa61d9447ccc3655755f32f71baab84d8a74bcb1fa90cae45ae7cef3ec1813a98df9e4ee1832de2ad1cc7a07be379b0939b2e364745b5ed7006b8ff481810fb98f1204bcb74239330892633bde21ad3c7db838936fd1411a09ada95a3cbcf3a50582897631c5ed206ec8229e54b1b4043063d9dee944001fb808a4ff3c3ba3d08c6f9282e228c884e20c344753c36207837cdeebb6a943364e1dab4d7f8fcbd5becdeaf72b284a03b0f7eb25edd403ebcd00b5abdb67ab08c8fd501578c7f36273f7ca2a56dddfa8e28527bafe6d370250bdba540d69bfbb53168c8354667391875f3e531e912fd826c44a2dc710897809307e532de26326e99b519fb9018492f6430d5c81753b73b4bbbdca2718b2aa943ed63c969cbbae5085ea84bf91713cab7ae40c39fa4cddd19ec87c66be47c20686c2ba773f9de185fa8514d48e8a68347230af7fcbe7702b7fb0b6eaab0264b261c932b7ca476741f47f0072bda370ebef67046fab697cb763070e993109903c68766305fb69963eebc5bf87c0f057a24534c174c099f2c09e8012cdd0ab001528f5bc64780d4c91884b431e669065aeb504044e01be46e7e64cb7aee5ab8fdb3309b6303488b850cb68065a57b37f0e9614516208d848443c575ccceecf6fdfe8a9450b4919591506e9558bb2529d4c4126c00793f0ae89c210cb8c800dfecd85ebb21304863a0af570b9fd2566c219d428655f839ecee9e2d071f5a08d78d1ec971821b709f4334cf71ce17baffea460a7fd9508c0391fb6097f97d598f8d19bcb02b4d1501e8730ae959df6e7e40f8a4261f506239f13099f30405434f2027ac9dce736a730b3c9c33ce1d986672fa8233e2215f04fe4a0fbde95f4e95e26960ea80e94035da399c5f739b5343af84a15233f3fc5430e963397969724c0377f3cc8ff3fba07c274eab6a33beff72942b3f0e64854991bf3fb806e0d5778c47e9339e40a7b553992de495233f6e96ef6979d8fcbafa5f71d4aae993ea6218529b005619dbe0b5945369654d8f6987468e4d73bd47dbb723da768dd05bbc2e679d0f98be4e7fad692643d988001aa3e1df5622ec4b0867ca432a47a5cdc6fcd04453286c333236b86c6acc18c7749195049351c85a314dcb81903474bf57ef6b495bd83221fc200be0c49e6696fb2802ce5528b65f9ea4983fad05989f36230e35acfbd39075aadac19775cc5de59bbaeb6a07d5746e1085f687c8316a56a79bd497da4fbeb7a27916b84d6c01f74fb1bbb2a04f93a18b26b2b37ebd5533b8fe5320566ebdfe42f2c1b54147995b0c2e5919d0e107a6e5bc179d5312fc34bb61f5e26d079da4f8bf21175970e05e1541271e06c584bbd70aab1a6a7787247f1d1a9f51cb280bebc8d218fc7532b9dc591611c3c1ec8bff378f731482ccbb8fbabb2522bb0c4c1cdb5a777415186c0a45ae413e6bc73057fa057693083886b29a43c9f593ce707bf238124c6b47d5c08cf981f20ec655301ed39def9770911631fef18f01940388e10513f8b17ccd58c12fd5339116883f5ad0f9f827451ca8b8b7e8dfa32922aab129e9e98b02cef37437cbb8f4bff7207fec50aa1fae1e854ca50763ae9cda32dcafb9302d406894cc3b6923b2d18ef85b4f636ab489c41b32b0998e743708e9b38822c9e8d993b65c4cf2372b7d63e9db48b99758197beeb53f98f1dd592ee6a4c6482226f231948e39d9d851a97339eacd4ba79fcebf492af5c20b78cd9aadeeb696769d684005885904cf50a985c85e8fb4b647423791054a8bc0163460537a9bf609adf7537752a8ee0defa00b79fbc224b073c9d78ddb63998f276fb4430fcdf01634d070000c4456a571e775d1fbeb816d4b2db857edc34cfd787c198f9f2d12c62d00ea555bc4ec8f3e1ee6802737a6afbac9b7e12cdb110d83c0780d2c4309bc71974c90eee5dc86dbc029540d4e525a7ba033d4d8f17aec80e4e88412ce6d3c0ec07c934d9861957f49514b5e8a78016555fdb98f07affa497f3f31b609d455d35de08e2915892194d4e25e21a20708eb13b63fe9c1dfaaa41152ba941761f2adabf0def7bd3ddfb19d62d1ab3ce690b179efce710f97d96dc750698ff2324efb1792f7e92ceac16266c9e93ef9fd73753c898301e49914a080fb63e0a16c626ba713de0e890a9e1aef1b7c22262676eca573db5bff217c6c11749f64a1e35211dce70514204deaf85901189e881ba2d71841c6ff8ba848b270f197155719bcf60536e77ce488d7bc45945b62a2bb5b485c68cdbff81807e48b8b1adea3bdc2f96188f76173d2bc08539585bff0c5486927524add28bb2a1bdaab2aef3b5982ee2bd5840ec9fda6d376598e169c0d4f32da38591b263997c078b369ec9eed3cbe26710f1e261fd3f8fc7865c4d1dadb9c7f2c12e675753658a944aeec2477e3c5334619b6f53077ea19d7010189d29aa3e28175151248abda09b8d204fdc677b52ec6ccda15bb8e404a8c426cb5988e7ffee424f06ccad2df9d4004e492ad4b147743d96dfeeb1ad2b8ddff66b1427db6d1ff69089f65f5ac09c701cddfa1cbdf3497202b62e14b440575a402587e4c4bad247b2eb249e9e82dc95410f207cf566d212b4c0b7a70cffdb48971653e64b42ec70b0eeab84f797115ed60196a55e8a5baa663853cb0827594b0a86b9500d5b25370e861511adf694de1000911aac3af253bb95fc89a31f0b66be2c68e1a3da1a551cf93d3390d36312a0d316e2ef9ac37a750cd510b55faf3c679f1478047623c1506507c4b20dbc1dea1d0c67179858acbf89df1d101257f763c0640b1b4fb5c62e81d6b322f9deedc14ae328518ed89cf9c11d69d909a701550d242af51119cfe2ba0bcc2123a7974cb06eebcbf67835e3689418abd67f28f1a02feeac2bada8ca6d7d741a2e20e0c169129e3f55b2ad68d5bbe33af9ba32d9f70afced44ff4f179a3bb6833244a0074d130e64a7a729dc246269bff6d4ae5a980de8efed3c24ed84a47bf6f604016ebea9e6133943c4741d50068b2e4e41f9293e94ba223c9e7b4bd76980d122600b5c469ee5771a6bc699449829f4a3cf0f12b6a35d7238190a85da603eeee0575d7e568410a8119292009e0e7620cd5fee8eb4f8c15d499817f646cc4a38f2870b2d97c004b0961a9408363303289e160eb155263a2e20aa6b757a29d6a341465b878d0df9b2d0f3d92a6de3a19aa2622a9a458b0201b2e1a8383aa02fe609bbd94f871f470cedbfb52aa6ffa7ba9ea6826498f9c1fab174c4b3d579c8f5ffd4bb0e5ead72b70e05d8babbfda3cb8928ec6825631f575da20013963a1089cbf535e73e7672157fd61a9ba26fa18330f7b1b4dd6d78a63d302e5caca40d5f260cafce16125c21c7a006fa991a9d694559450ff14c05f6386fb374a3c5008aeb7be585d54e6387cb8b42fc59b5dfc94e30f163f6aa630c5cf5a0eb90fc8655ac1d93f4336e7189288fde928433cf972dc2059ffcaf0658efdcc4495fe9240a691f85d61c564ac509638429a6cdcfe8930b1d30932bb84457391c7e0c5c076d5a725274295d0694c7bd35c43b400694e296950a9e38262e7f8dbc163c52c19a1be4d303454a59f2499c4e9528abf3922d1894bf0bd5c6278aae15c20a63927290539ac1385dc22283be4b636bfc199abf25707009a8e5838438dbdf59ec2a088700c07f1c242d9e51cc4c0a84944dc9814e2de885ef6144581599d557f4de9831338d74cc387bacf28365d1b0bd9728e407523664535deb70d0d2e43a71d948d10f0c79f55d9687bef5be387751de2536c4e44202000caeb9bf7aab2eca6d14a9fc4c2133ab6300166cce8dac5ab493fc1faedca99bcc74a4c5285add0455d41b31f49007ff102df50d12c8119faab49252052cf1c9f25e221ac008c6b4496e6a772a3d4cec9d09aaeab9035cc914bbc4c01c7011b9e80315a58146d391b44ff28e1d8f606b43be41a430d1d8e3df5ee05d6e24b9f44d461b4a4b9e8bd181541be8f73ed4c1255d688f835f230d6933efbdded80cee0e86855f47bbec173eb0118e2c86d122685b862ff7e5b228fd7e0f9072635cca88d4b891cde29b7f5b4e8512765c0cd0520e80dfe8ee402e2a92f0d8b3def34819af74cbfdd6e06d660fbae4a96486743206005af60888e2aeac5fcab5765ee7b24c388fb9aa0761f8ad88f64f860213be2283ea54365382888e452f01ef5de8aeb83ac7245b49639fccab1133b133f6221dfb1ae4ed680f1fac930c8cfab4f396dc54eb5b439e35cfb04be015032c510abe37bc4f60226723b02dd8afe7bab56ead5331259227c6656f5cd5ccc502c266986bd1c8cca1dc345dce4b8f478c14121565375417d170dc9b6cd764f39af0d51bf006441f340b480e4dbd1184be574aa187cc4d8470893da74906a1531c988f6bea9d1d93480f2f66de4fdc6f286034e46ff136c7523b1f1d2547a8f6f4b16825941ccc4727fe614bf6c9f99adeacbd403b5b8ff7693ebe823c1c108b887a18609a8c53384186580b20858d5c18048d8d9a93ccfcff160e544be67129d3881c120cdb23b4be922e84e21017a66831096d54fd1f6859f40c5acfe0a4643aebfe4a0f839457c0c17125a04a55e604140a991974bf0c8c795250e3d6cd8f292fbdc43dd2256c50e64a9e22e7f39959b0e579e9d0cfefe7713857df4bac0b9fd1274fa2d85d2fe5ed41ce5288d1da9881535b1ab3a640cce9fb91b2aebaa96026e5cda951d8846660645e01cc909710c27271700617c58599a43da6d1f4e3c5aa9a53c138fee66a3e4333a0b6ac193ca91b2cbb3037f367d23882a39f6eea1dffe7965e23daf02234c65fbbcc0b832b877c0569eca487eb49371683e528a9520c582f73bc86aca57ef56d9e041a079eaf68670a16dd931f91d00be81cbfdd5853ca9b8df9a1d195848bd909e32ff515bb63447151d1e40eb85626ec496b3a797fd8e66a353515e30b3fa6a3e0c953a6349b425c1a513b93178dbd62419a983544f2821edc6396c69a238e43772fcad253f59227b6f781053c8721047482735fd7a43b266c0bb8a4d8c009c2fcbca4aa202e0a847fdb294ec15be4ef301be9037483c82563b883a5c59cf21abf1025281f7b35f20094af6dd10114ac141efc164b4e36ffa0dda1dc6b14e51c0e483ec75ee74c2cdea64b7ce672956a214aaa7cb4f4f5107579a43f7a9826b902af3f78c442ab7a4cd085b1b1202cb5766b1ec0ef7e816d45f430a60c4e068caf4d8cf44ec181714701e6d808680674c23d698038d8be88d29337ad2c3d797a01e4720ebac2ac7e2962dcf59c0368cc4ef83000c100e842a550d0f89885738caa5121523d1d86317c015e4bb2bf16960dcc14c51f7d2eb8d499dba80769c6cd0e55c4c7d74f4e90b034c1e75cbfdc8d7a95eda4276202e3dbbf9d14f7fdd7d0a30a8f09b91f209b22b1db6b64f1307e07bba701a5eea0a8166d11823b2de41a71986f67c585a98f1659d1b97c79025bd145adf542f398b94db3ecb7eb8f8593840a434ec627c765958b64e278a7922e4679ea4948e303dd7ebc4c3f5dab1b6ffc573ff6db662639e10f6a1766bec2e4444bed8dbd0b6b536953e6b22eae7efdbcb038c57e4b05f3b8f5c0fc2cf0118156153ce7df394166892af6c570d4de800297cdf1b1bb94f02ec59ed7721dff40f65121b6b4ded6f36b4db3dd307b95b7ca39e5a7847343ec67c1cf3fd1406b1b9176a7a0d5917dec567860099dcf45187d2fbcfa63ece59a71dc466a6291a92d44196c334689e0702bebff99421046a60a82b3db25280c5dc007b69421fc82a4e72dd6b078e8eee75ed1e513d9dc1fa0d36302b723260fc882b1a4cf5c8a457b1691cbe1362c14dc96143b34daa2b81d0b220e678e19548e129fd195ea53f479e807873f05a158c07ee1478ddc6a13510075ee457ff8988029e55529388703a81e78c72fee269c5ac3af3a4b7badbc26151387cfa81010d62fe6fd0ff43ee17e7a36c89f92316f560f152b03b66c6f81a953a19feb0696fe1eeb92d0e9ede899deab7dd6fa76be0ab5cbd7ba0931d7c7905c21a2e8dfab91fddeb77870c882fc5b634a577251cfc4269adc21a3835c5f6d2b52767f038ccd0aee015dd612f64228303bade510d9ad95fa9b86c7f6adbcc5a2038bd2ce275a51d2a5cbdb4bf4d99276f049ddad5b32d560eba0c48908a5ba042166eb172225c8e8f47bb76e871f5b37d1cf7a051d365a7f331e681ec7d65a58916943283f51066529586975d309ee4963cbc80e7c6e553c1faefadd873e755df422851327bd78b63d2edc8d20efa06babc87557bb6b6f5e51e74e15a4d54f5b07798c7878964745abfef50a806ae5c6fbe39c151321a75228c7ad13b30a03ea45dd7161af317d89878d4b5e5f23e2e8e50d01308fdc51d56f262e5222db53ffd5b120b07aeeaeb347ec6c489f8d289ce0e0a2924306540105680f422ab9e9bfa7d580690e075a62d2926f6953dac66dc3866c325367bff7bfd50f8243a834e95a969af568ba4f7b7306e392f0c2be162cbe4d051d2142244a1319730ae9697465712b96cd25ac44473ebe96cc6e9eb76805eb05af66a7302b515b3d9fdef4304c3267319dd660e6dc998db9aeb0ab409290eb78662dc082accba18174ada35087c57f811bd3a03f04a2b4350d17e28f663425eada2726d6e0f0f6be392f107124b03b4083c58a4cbd8de72e57c0c86018cadb5b68c4d734f8f9538d42d4c43c9878b5d7482ab3e8b904c86e58b0c85a2bb2609cab63b49549436c7612f27e21419ed60d3a105d753639fde3f91ac2361f67f980d81df794417ed3e2344d0caaf7513101165669a61379d7e50d708e1958d4d1b537751eb7cb2fde91951566d233c05480c1d59c658da027e65e39b15fd2e992ceb933b320bff6f4b8f966ae018f658030be8e0d9657e6381309c06d0eff6394d94f1601a92779cf0278f8aa673bc60d3f96c4646d31c9af7f4f093b1a8b3baf2d9347816d4b043206f24e5985c439e99f61ad0f68ee7a32b3d3ab1a8b314308e04e2fba109603187fb036d6dc74dc61ab9419221bda146cd628aa79a00aa015fd5ca24bb75c590bc050b83b696c3dbcc20211d8aef61c2af93b24eb95568c4b079580a98cd154132edaab95e238d0e66c61b5d3d34dc9c88f211bb644d57c6aa49d6bcafe40f3dae34272b2ce417752b4d3d940a285110d7b3459909ac20c436b30857f4e5839bbde29cc2ada0c3106d6b9791041a99a721e275253b7463184e415e37aaeda6229fca6f10d19272419e3bf46e4fa199725092faf198c829e53aea04cf70b97e0f8577313cc642723705b9fa8a956cf883f0190be4b6264151fee80910cfbba667f4442aee653b07e5d96e884bfc629ee5e904a73555c7fdd94d06c31d3ba9d201e577ebc474d9a22fd506df340d06eee39c0987d8372522539997b580750ae08e8d68685354b08da7de4097cbe78ef7be390d34630d8dc403cd103d6656b735b6cebc9be46b5648ff8e389580e07d200baed0bc853d01b198e05a50e097a9a82097b4194e967da15989d101c2ceaf67d440738295931c5c4c2a7d2615a57a28c6d2d1e119889e36442c96c56c20cbc626bc3381779ad214a25e9d4b36a74c566628d4128e6c4e631fe327f06b5fc34e7782f729d5b4c687da8ac7fe7a274c0a5403f2b56881bd85edfdedcdbb68711709f4707e307da4119602af6edf30308e9ed63491a7446d5d0037b58fb1d16d9ca62fe93c69a38549a7b33704e54d420d811b2f0b4e870d9c98e235ba836c3cd1f7b4a335dc4f96eb86139a70c942b683f4b41a2ed5325d4b2772fb545dfbb9d139201d9b1fe27a13a026f22d5f4b2b15135b760ff86e9e37536c34854f246d2539143d753e1e9603964d20e84a035d1bb5e0dd171102f0a33cf5c021dd12bccdcf73f6915e8d30ef1f2c373e5c8d3033b558ca2eab3266a1672a4cebcd0b148942ef49b310818ea418f66a72ba3c9b0223625103b6d59047669b007a83688615417f23c62d7d2c12f52c9739b7c349378626e13be731f2b1b7bbc9b463b8e991ec74b9b4b9218c2e8a55dbdf2ac5fddd1ccd3c74d2499c97654ba0025a9a3ba0be0291cb2debf23b48536e787ac5b7265f9120c1f56c51607b5a1568d0676f7071af28193b4b20aa0d017a19c97a38bbb7c7b3416691b1ded56c74ced11b094b0ece7de3def490d3011f488c61623d40064b5461475585338508095bc3bc5f39ce4948827bec6bdde570203e68c8237a86fe101cea12e3a314c4ba19ca434968a75144155d38ae833cc185007ef4f3bc7898117867c8a8435f211b9ec614e51c92de7a39ba93a0c0ceb45089502ca88d59411af04b6c954de0d1263c207c196568fd3df64c0a04fcfa573e7e55ebc23cbfa7996c1754c67c00e3f42f1a504f43ff84c9ee58d1fb10d0006b15babfc84b5fe11a6f27c2c14124dcf78f3e1ddf789626929b8122c2f578f899cc162e5f055b3d87dc4d094c610270e8d819f926c01fc63a6f3e5703ecf282501f239942563d8e93da687285419fbaf3844fc434f8b6caf7814cae8c86d0d75da03a7e1cb4e8b5e46ccefc38191c2535e8f03928039d9b220c3a9d0dc3d910992aaa6dab188d248c26eab21c84e279f3abfbe81120125544d2de39bc6c5a9ae56576db867c2d3931459c71a84cdfb7e47413e6facde27354ab20aab2883ad4ca6c60d64eefa695fbc97daf779db55c8911094e2a39bb9e43883471b7ff9cb377dd8a015aba7371c227f2b6e70a198dd16cbab039e2e0dc208d86d19fd37afba327bd1d4e450e822584c2450cb8e64be5869765439f9e56afc0899e0bbf47a556e992ce289ec5aacc98a5a5f22c9b1befcccda501411c35c4d498fe16f22448d00c5cd42df6f737d820e7539c1ec46c7a26143e528dde70c361b89214194794cbaac76d94ac88119dee248905c33e119c3a7a06d1ebfd7e082d165f44de70f66bbbbabd10908517b96b7bb7c88307ad135958597cef6933fe7a4c489ae3f81f03319363e480ebedd8de89102c014cd46797d36a4dbc4c0e46e69b1e94a41da73f0e84fa2e2723d5c58658b6458f827d3355d6fbda28e1acaefd030222a600ecf58acefeeb638fbe932a7b1ac9188ca6891d73e20e20a4bf08aa98403db3cce837d36a067a9735d4e6c779344cde2c38b009ab4575296ce879b445ce101859060dd090d74edc8ad05ef93287cb8ef6dec6d39bf4ae97a80f9b914a24370ab584ad5170bd778b79d143447c86ce12413d1272b55f7671fb43f2646ed9d3412a5748cbb92e28bc4a4b0c163a5871f76815ba3d0312236e190ab8ac8d175fb4e75b4ca1f0cea0cc05c573cd079fafdcd11bd524c0e91e09afb73d53ebd6a9097ef877a7fe886c1c64f0ca77edfe5142b67be8b5d680c21aa5de06dc9df97d4e3d1e88a8f65564d3de2fc4cb52e22ad038f7097ebf6c288c537ca49415558d04a2953408a4a446aea458447a0c943b2a16a38794b36e4f9fe1520a9f1bd9b362ff15e5b8a4aeab998f1c5e6707e2f10e9cf26654dcf965a6c38d124ad96840cbe03dd50a03aabd8d58ff2e82a65ccb0e3541ce7b3ac37ded10d9381e2b273a1b501ec204d312977ba8e02114c77b8af113c2399082e8bd6c3d953e7b7a4a17241bff35f37b128cb27916f1468d28d2dc8b204a70f25a8c7f54a23a0e019a4371ecccf450cda43f9089838d79e29998bcc18133748b41cbe11811999631994cd5c8c44caa7cb6081da549cc762ae68126cce94d3111eedf9f9bedfdf9e19f5705529e5ba58cd2a7fda91e5cb39de4881b490e752119d98e03fd02d5eefa28b43f3a36c66645c2bc5779fe6206f7fb7826c7fcee9c9fdfb182e576ea4e2f69be6f668e359aa3f959ee724fed8ee2f9afeca0154ca9fc73f70ceeef9503757ebb76d89a032da22f6c5e7e51e47042aefd5acc5c07a6279c934d21f2d3483d471585c68c3642bd2612dd67cbe16acc3c03f69213610c205cd6304c0a3961f4cfcba17277a899f1add9354e3aa7bb8739ec34301c33704cc2ea7837f669c8e11ae260dea386d7a1e88ffda72976df3ff0109e52de0697fe4bce9be7443f55b956b3f8a592e14b0c33b83042b804f883503d6f4f032b38162e918a73249f84ebc5f0f510beaaa05c5e081e33d5d34bfe307e40c5057c2a66bafef9aa71a0e7ff31f385c8eae987bb5ad70d556d13d5be37bece02087c672dfc03b444b415f13e4b8687880dc8dca4452e5b8c30420c9422a7436e1031adf0b7c4f41a94c783b2ce1c8682c123599b6a6d2cc239bd50ccf172d7ed6bd6a77ffe25445b148a44c387ae2b4fa38d0e76fee6e7fd77cfb657c11a772270dbe91142148a6902be217807ca65239c6806cc1bf142c12ca5b34fd6f85c89f8bd05b16ac5fc91ac6860dd38a8c6e88387133cfd4756330966b461a8cb744c0d991453336f4a60cefaba873b04c02269537db6f3fe08dcd1fed27a2c862dc86b788d6d3c9331643ccd77e389c5d16a2753fe0e2ef53bcf5df2ed827b86fca49ed059879e093be9d91f1c5922d7c1c4d2bdd6076c8f785de6aed30797943cf38c985796177186caf6f672921f51bcf4cbbb7fc29fdf25c6659945d4ff583b4c137db78bdc3f87df86686318d04389fbc4b518d30bf18b717cb1f776915897c56cbdbc2f725003bb9ec5d79939770926636e7bc3097edbe9c93f91c6fa9134d50934cae224573e523045e60ab65df0825f613c77b7622e9f3d3629cfae530211fd4f9aa33a73c8433a4ddbbeeda59529681f19e67c869d81935d92d1abeb7a3e3b967fa98e1ae393e7f62b93f73c15a983c294696fcb46cb5d583c555742c8aafc07defeb4c811c41dc7446400cb5572279c7b9c75956818177480cae5c8ad083cfe015786e0b0d8bdab5ef3ce5a3e85688b0bfa861150b43fe56754b508f540df5647bd8be4f0c7fc3fec0df4b43aefc6fc308c810fd066a6e4b862cb27c26f811ba407d60c9576d6ccf0665cc9112ac10b79cbf5ca978bb7e5dd6addde66ab9db6d71288c24fd877f6aaadde4f097c7da2ba7db43d1e5a13d2c21f973219abe2040e066262621ae67685997d59c10c95c2e357d20bd23d55e2132e3594f7712a799dcc56008dd6fc518bf2306486aee8d2b987eb7f340008d33565953ec4d53c46294aead303c4c3c04053d1495a622bdea1de7148c1f93bcb957ade422fefbab23fd529481c69913f51bf24807c57e1199f83f625cfaf09bb4cda90c0bc5beab4c62ec19d16775d2bcaf3022165ebebe7f35ac9cf79861bca2136125d2943ddede538cc076ec30e00f2027821b786927cb61541bce803ac61a80fb32f6a8b0a658b0b77f643c8c83be7a6932c7af29764d085327548711a983744310030b7be2421c69536e41e1a38439e3904114da32e0281ce7ee8b443ac41a22c5449de9c4f9b8052e6e5a1bb8a54c8a7b2884ae56fa2ccb780026d690fd336fda4156f528bcf75b8579e7c50d31565938335d0d6794a313920805fba890bcf3e633c1c3b708688507c77e9234c107de03e1e55be280cad7e71f265a6c93bb649273e0b75447801a74bf66e248a91920c2a11d4294bb5557d31671b8390daba19566535bb30d99e195e996643dd1a75883c8cfe2ae8ab2ac5c2d59d69b5581c4279d73d109af34196dd6424ce81dd3e68d98a4ab07a706c5d0d08d8507dc1a9181e7e9f867bfc56ee6d1cb7e32e4b9a74de40ceb675e98876596747cb25402ee1d7b957130428bf70e02fa4adbc25e455c9b7cb0c0a4ac4cb751018408025f61ab87828ef100104c9d4d523e2d6c369e3d0bd25d2f1f3c18cba35b482f9e32f6c5f5b8d11fe5b59bb40263a1aac6c45c9a0f07dbfe221409a386b03711fb317edfc3a6702c307ff035eb485c7ad29a2e7df0f0e129fb3d1a59154c164896eb741c627daa4c958897ab860b969456796e9c3185e5d1d55019bcce21f609b58e4950635837bacf76c02e7a427ef2eb3952ca563978001258e420ab603601d3f4bdcde27454325d9de1602fad21c4df95b30ec827f9f15c461251f82362d7231a4c0903937e1efb8063680a2de64b77b6e4dc0be880b091eb437b962078f144e2f2e84efb602fbfa8146cb819c5c34c1cc35584992c56586b3c146d27de89a1cecf66082b8b1a9e52738b3042915144e614832faa69b5a549749f2a60dcde95ab851019f504037a9362e6bc522c7ae72d7808723f8d5fa7d453d4930d38fd5c42a0f63d17ab908b3115a617cb057fed69af6edc9dbabe12da98c379fe75b8bb12e1d292ed22708f10110b8583f53759014c8468681dee8882ba8355fc8d2519b61defaa065a031bba01f695c72588467f3ccb32a089f1b9e2ef50ef92a9aea27ba028058c7e389b4b6dd3d109c827d7771e64000267304d9075fb552c61a527d4608fc91ec87602caa7731f2ca8036b6e8c27504270ecd309b639fec63860fd4a913461eed05c700cbacf648b7bde403f6611ca3adcceae53ed055b434ab7af83f22fe625ff6fd5bb56be0188ea97bce96a82e379bc646946349a92c2f42e9084d465a887f4b216fb576509d133844cb9a929c8e972c3dd0fcf0c0d7eceb762bd9e8c7174cfc05a7d83f5c311c6fae3c3cc54edf5084cc8fe12b34b196bed581179d8ddf6e24753b1de6137592e9b4aa34f4d19e104523f88b66a6f67375bc3c9d25fba5f7c2cb03c17c29f98e043dbb4794dc5d4352d9bc12ac1baf90ae4f3dc2f2503182200e68a5c5f6593898cae49aa80ef35b87150d922e665583869562dd61aec16d579c689cc02f1b0b511bd507e869b2902f5c8260bd783aad5bf659907992b9b3d4b1c9a79027969112b35bb30583a539942ae70ea1cbfc6a1ddbc1042c888634277fe2d260019b7b2d2303c55569e6310b3547b98a6e535fce26c344767b53c1e12dc022023fd5a5236d30ebefe8c7b25760fad60c325384010c8a188a7fe48d3af43ad9737df237e3e970e0982c391f458058f354ea9dad4e089f83ad1722b28f0cb1a465a443ca2a9350172d38c919a975c3b174cae8c5f2f43852a9589892578f122eeb02acf112ceb5aa63e058e1cf6b9ba9840a9bd9118bd04178ca06e688b4307da14d76d1a67679365beb35d800fd02f73ead9357c2446bafec606d4e7b57f334e2f12ddf6af322fa1676d25dc6a04aa0da50d1de12def527fe73fbd42bdd17a12c850003f236c4ae3a1e5a4efeaa384b142d8d06e7085483af9343b256754b4b5d442c6dde70c74c606e772b6f25aff7fdaf155256f34be054deb4a48740af710000bbc6b79c628443cbbcf2035f6ad1e9db946011b0b9f8752b0d2ad1e5cab288ed79827ec3193e8847a17686460a0dfbad5cbb868f586b0b2a3b25453677766d32dcfe886a1a64908ebaea4bda1832f01aad657349f59a66cd23c9c8315f4ef008eef9f81c658dfc7e416fd2af0e5583684367c5c08e194f1b87b3a66a9a30af84453bf64f2ee5d9acb596f7f956dd44fd2bd9c93bb28d5a1a4baf42ad59ac473172aa83b0a0d881d12a029f5dc1389ddf50126ec0d6e7a29e71a497660e889ac8c0a193678d1b5b41d973c75ef6014652ec481ba50e0997055f9db557ff5d48b74fc62e10b1269b221fa21174e617c6f317e044c8c7c8fd115504831e579d348174aaed6730ec38024e753a4c8ced2aa222bac40886fc7c30818d3b92b56c5055805ab79c05be53fa4ee116a4059bacab0af8ac8de5c30ea0b519e7a0c732966ec0a7859f49e6986ca35f82555b057e77aac3bfa9d8be60fc59409b642fbc6fedb94a9ab2945fd4c87b12503c6b396d65074e34c29903d7905ad472199109a3a0d148e3ce2889f1dc5e40cad0aebfa1d56470a403ad1af23bb471fbcb3c2d208cc21bd6130260c38a4870ae1114bfa4b89e8ca79160da31824e1f2b603d248b26ba74135c07daa40c1826a87a3f462f845d70cfd406e2e7ceee0d4a5a7c7942ae6d4ca997b2a8bc91c00ea5e56c5d46b8ab06f44cb2c9088221c5dc3e2447ba55cb824387121c2f013f756ff08e8a4d6ee785cc5e8d902355adc26eab1b3573bf3ffbe4aebb7e4960f48b6019b0808b6224ae70ae2b843fc787ac2bd8dd297b35c4ab055f8399fb1f1dca36d6e23e4e622e8e558fc2e4ab23c8e5ff06867ac72bc6a9944866c9f934d277d3e3746c1b28ae49649ecb9e80ae7f32b399658ceb3179f25154fb8e413e1354aafa43d83ac3221317e1e05e5a4ba3c3ff8a2f06183e2da45a2fcfb668d2624c63ab15166deee1fcf052cfabead1a059937ac665871aaa65a28f07d91c0ae4c032c803e563eae9436a3bedfbc9fccc13a491c2e5629b1cab195a7062103220dad0fd45a33269842d65e4d68a8e04186a58eab3e19721e4349dd74e1a5bc264bce2adffdbbaef135214e9815117014889dfda36750cdcdeb295e31a53a4d0af83b9d8c45e718859e4333eb63326a2de15fb38317638e18731859e04b4410585dbc9edcf22e685c76e96bb522fabc87537b8c3a0e1b14e3b682e2d40c681ae22c84606a929e7cbd015e8ca74fd66b93186dff915adef2e774bd99f6266532d7596c944d5b78347151802006b049afc698ea7394b04b79bc61fc5b31917d8f8542157274ac69556fd24d7fa940787e41140408e50e1a26df4b9d2290fe9f7d8d2c69488ba50b788e2026381523417e41f316e15291b62110627029b1d588911b9f32d7360fa32e1fe0ae0354898b20250d185ac42cf7749e924ddc70c230b8a949e0f6efe2c0fa2208dd25c9f29d57d111b623121aeac48b38344be5121ba97c7ecaa29483615151a6693a102845e0b9e55b11ae3587c8b15a3bacceac7fd910cc5949c55b3bed876fc50a9ad4fa45d114cb730b012ca490b9cb62e640394a3f925279d759b2b81315dd7847e3c1b09a54af8c189308e6e2d2c00a3261641300c648ab033579dafdf9b66fc7f5e34b6011524c0fbd040275932b3f067ce322f1d285bb8fe26ea0515f94d11c73dd94036567a7afd0f5b47391c53a1ef47f21920ce6d680e0935f37080412f425a370a9c71c631e5ee0a98af6fbf519a00977ff2211d77db1e04fcbbdc5af721bcb435817dfecbd861ef7c50158d82acb7a42853940d8115aa234c041e4785596247b27b549b2e4c79d17da87d3182d16d428f17806d63a5f4a87534e02ad3a4d8d7c15ba9425880a37ec987513b2c216eece8febacf554c972b66bdff1880bc3ae3262e4530dc9cb2df4690a9280c9454900900feee4ea19612f52d3f66781f72a3534aefc1bbad320e2054b10c03aecae7d68cc767a032f1acfdf76320a796b2842db7675bdecbf7b37e4eb8bb3778b29a2a0f0238437bd6c0b82875c3261dbdd45114ff9bd01562503bd9832ca38e0f3fdc53c8f629071d21941d921250cb2d2388109aabaeac04ae0a893fcb2b840b5a3e55460e08b40200cafe2d00cd3892025a15d7914fb243de80e44acb8c1c4dd1c7a7de825381ff3b2393c44f03ba96168e1f061c72e404e463f7db98c085ddf347a9ca9831b3082e06ed9ef5aba4e62fe6d9900b290836acae265b5945b7084240e5e4dfbdfab7828794fb53a3ae1eae7b4c383d6d465ccf50fb8405e2cafa1ee1ee5572ed83ad77e8c32fb81f083e459454b3e6afc9acf75d35983fba17e5a3893e037fc3bb93a8020a240412794862ead78462142650a2899121aaa343037708381d685c5da6eed9681027bbec56cbb9b75defee364d4f4f9c889569e601d634c1b2befe62b10531b5b7ec6956044ddd69d7ce7c2b8019b4e0adf5db36e05b7a9920fc00c3470d6c4ad6947f52662d1488df3e404563cc054d85f76d9a65c8f259d4c73576c150d38ecc85c70a0e252b595843bc5663bc241fe504fc8cb4e078a5337071f3df1b6070a3f012c8ccb52375c96760124aac0900ae7aaf3254de8412da8461c838838b91397c814dd0281e4a6f1f1dd4de3d707a39edb5f297f69d0bd1646d7b078df5ec9ebcecb178daf0a862b78a1ace6b11555f7bed6321b19ce58a4667aae4be894e5eba30d469db7f64e162f814d7d80ed00d73fdb3949fe42a6d0d69e70c18f7db67c097a23c735821d4c9b0e9ca0520678b47282a70d548888906b8f01f3cb8069f07fdff8cf21b24e5e42df82ef9cfef3f9c69832c786c87f52a36954a8533f41b3a7c62fafa661f8360c8aa7d07fa3c43383c30a20bb1b366c978afec8d6e791b34c568b37e4e0c566ff9390952e281b23f2063689f8ff06195bc3c3d3aa7f57023aebc47e621230e0003e7dcac69e261271550261eb07f7d756c47b79a5da7d703e85c630280b71e733bc8bedf8127cedcc5bd7c31d358fdb860fa3870df8c31e2e0df5d2511356029f792fb065b48bf7ee7828cae1234ebac626887fb6f82bdc02aac226f25b88a3616fd22683b0d5ffa1cb95d6085faff98716147f35786c952db88efdaff0bf1015595ababd050a5342ce400b03fb9c12c7bb23d1ad1fb6cd74360216c6d15375dbd3a3351007ab2400db25f834ba6752ce1479e212443f3d9ba989d15e489960f83b987fd80d3cc89750fd90ca7b3cfc27471f7e38734fb82d1638a8415716c6987ed6941494939cb3e2ec0e88617c26fb1e21d7c87bee813751ae6ef765a7fcc301f23cd3f3ad8a87e736ea47db70a1f631438c8fab066768cfee2b69ba3c5c477eca90ca55ff8f5a21a36c3c6813d284811ec0f082806147e5ef62414491848c25fe43fe9fb771fa42396bf624a85f7a4bc9de2320adaa6a41cede35f36d399f950687fda0ef80624d7a915ca3aa4f9b07c31efc0c1a2cf9f4aabb375a890b858c5fea67e7e01e9cbc3bcca0af0ae42f9137ecc010d49a2b0a0c014afb76e8b78edbc650e04e50ee78beefd9934e0733abd9c2df7d8ee43130b45ad4385a3def1a84fe04ee125c264f11cf421ff7b0e34309623e46bdd8e6708e10791791ff3d870799e3231c22d1044f6acd57a82e8b157c4d141ff1045fa8ed4a4ab0b3d2c7989ed0e6e2fa16778efd5653d8bcc409d674c9539d082d68ec3b2468310d66653df64e9999bda139d9385211bdbd0267d8e6545850d2df607f47a8726aa2f9491b12684ec24aebec843e49d2f7edc1adabad99c0aa1f6af141c3836b1eec524f08f30d1bcf5f8f75e225371e7153f8e3a4bbbbe9dbc6b5571f4759e24bd4084c41b987a177a1b756457065b8c38c0e48606e8ca9b91051e28b7541a788f1820a3437d888b2250b2bf773ea0789d21fe7175ff603c29604e04007dfffad7549200b98bde0809a34ebadd5b61a85df34d12b80eee0f1c3aa0de0e3feb8631001e9e6673461b0e0e8484f90ef50d0bf3f97d42da04d58edf88ad918fdd6bbe4b94fcf7d95f34dfe4a76fe073af76d2f1f3c358a7e7c2b70571094d4a56a352a3a53829ba5dcb4401f0489c4be5104c2f94ef686e857cd84afc1f8defd79672f8df4434f55af9d1813b6e9e510a8a0d46665794a6dff67e8aade3880cfe36e99a3387428e4dc5c8037cf483dc6bf9a56e298a104a51ba0cb0827f9116f868dfccc262d9ad10ce8e26aeeccdc1cf8560814630491caf460c0edc6c36961d6381ac906a5cea972fdd9eb9ac7144b38af39455131864e208f9309b89e7f69d84e2c3a47340ccdc56ef9e9f5c156919b6f56429c41d652e2f17f039a12d11ebfb5e0719bc906a1f4530e99250e8c2d9f490df4f91ccdb2ca1ed0f2a0ee547deebecb2bc5031dc8d78f315f5f579870fc44b9e4ccb3b8055468009434d700d952138f01320205f8c370757bcb338b27e6a6b4d07dbf459fa29013f67ecd0e75450cd52493d5799691c6503d2046a2ea24ec061eea37d54bcb82245c881f96d527c9a64fd7cac0ef6e87d10f34f1c39bbceb7c9be3c8a5d862c6a548012fc4ced81ee0b17651fd29d25d4f0491cc4e1649ea5f63089703cd86602a4b75894fe5285cc59e54edfd6403d0fa10ec727fb38fc57a28104c6365b05a5beae220b47e3a1c6518812bac76488786b2d2af641c5fc5297a5963daadb628f46e4982de2b5a769ad28cccb3df845ea573622ffd8cdbb656fbe439e6c94ad60bfd2c472b20e91b133e8a26c222e65de226556932c195fb61926add60ed33cc9a5336970d506960cbec88893b624bf20204d3bdf224cf6e1327a98155245dfd6d405336a01c17d654733d5ab3f1bb7e4342e8923cb909d5df21ce630e1603aadebb2082d9afdd70795d9301dc07f0f991455e36752657f25302fca4ff547257092f109b4a207ad32653d5c273f3b740b347b1cbf2c302e30612ecef8b8f2a94f1188379a5f514e921804f6d2378a7a5bbad8b3e12263f030961ce6a9785db1fe2ff960fef796bad70101416cb3d9202eb57365ee3a1bfa3f5024bf3d62b7feff5e82cbe0e0bfd0808f4d4dcfbab8237e541f8da59cf99e324bc3eaebf236132830c80324f64fbc655f0dbff86cad40323cd1c3439b1df014baef56807e0e24b242112715b2e27ff5a54ef79fe169f7e2f2e616ad138b2e06e4681080697f76668d3b71639d4bf11b21ffcecc509f8a6a195dc3cbe5b0a5e6ceb4580f4a4259c47b5f13da7239250edd68c35f982f5b5af2c463b8892f0c8d499896e7f8307b75b27b7d87a7875d16640ffde727d34e580815f351ebf16e99568729878e74ae83de92ea50b5fc31a18440b3be822b7bfeff0310fec5cb570f8875313c4604eb28d7026a0e97459aaef060086d98a6ee2fdf34ae8f533f0e98e950284cbd7d9b1604c7a6f2d5ff44bf46f41d6d3c6f71ba2220830abd642e9a74d2d831c1775e881cde01d62a96c06e9fddf14a3fd749a0dc9801365acb02f0a799aec61428225ec20a9e73997c839d8cdc363a69bf25bbf14fa68f3ade945a48375348315484797b1275ce3bcf1cf92ad993361234c45dbd2260f4fde12db4b33db7de8595d6285d87189eefcd08de10dd5bc850fa6f7b88cc85cd386e1c4d9e562ab5c630c6d86f01a1e2f2d091a0a7e07f8970f24abdbb8acb0fa71512901ceeb1ecde83b6ce527baa24388e1dc380b02cc0c93dc22fa03d655c262a4b09bd402f46399171fc2558a3aefef3792e9076c1b0342c0801616b1f641f9fd9ce9d56264027f2301438639b0e74313357be2739560f048e2ac5d4888976e9b7edf9c07e167ab4e7957c3b39492b9ee10653db38409987ae120c29e3e2ce52c3d2c7ea58fa68d11a03db298e46c353489b0ceb9fc5074046690cc7f34b553a42060fa12e19960aa09b8ce3da030b652b136930d0c0e93c26521643ce93e4c3af878c7c40cdfec6d309acdf49ffe196be469731ab8dcd702e62ed6fed29eab8f66130d5bf630b80b7249dec690dbb0c51f7434bd75c11aa903c58b09d11c44467753302709af0dceecc8c701aebb653fc327f66eb564888f81fd139320a27523420beb1c60cc541d995fe052ffdf14f11667027ffb5fe0c46ad4f30f8893e8a32636b6313ec98fd2f19f262f13ad839647e3f49ecaf65ce10c69e80752d18a7fdc751d4d3eacc56c73eb078b80e98c1f3c215db8c10ef0e2b81db7b6326a2b7fd356a9e0eb0a6b5fd868648e08976de8c43f37f614043f64d81acf907c19f6035964d8a1f77c337c3723d88d0c631853d3a86f05df7f55665c3330d84dd0828d88129e17d8aa40bb494b8d5a0f3c17c4d19c11c6566cb5d0a87337a657662796526661da396bbef7abb225f11eca6236cc3f18c47162ba5005d8451367372567a4c16df34613d03b891fae62d64021bdc6b15bab309c6c984b8be4e83e49a07439b2cfbc1108c63653b8578e986cd9108d26d845619993e0e2c24dc292ac20e53a9123b0d1bd180559300c8cc0d2355a3d17545cf5fe1e56c15c01d1fc44d067a89b6a59a1cfcf0ef2567241bd2d00c71bcb38138a4b45545bd36f0c997609fc85877c5d84d65dc3d4bac24e581ca9f613f56255f7b0639085308a5695b88e144886bc7e7c503c69d1f977863ce2557097d28be36650d25af4c4005d1bd3365f3ba9cf8103e65be4e86a624aca68624b4dce5b312f291de5df77511f6babc36631c76f19bd09faa179ca9e7da2f2f68d981792150f027bbe01733ae05a61597bc570db52bcd149966d690428517c6add8fa8e68841bce3945f2c07f3503d083723ee36ecd73a1c729e7cba84290701352147ebbe1b82bf5f34c4d6057615d73547890e7cf51f96dae7a9ac8bf0a40f8480488a2e946d9f2130d8f805b4b29299020029f79d9ac324275709f4046526be8fb379fbe9e948106eedba19a86d692f9b46ab10c8b90b6dcd3563d132a10c8c1912a26b402f374d3e35cb12d0a0dbd2f7fe2e08edcf0237ac530806b4399a50200c5f0706e09a1ea7b0885acf54caeeae3ca5cc23ded78a8316910add2401f24e4b3be625bad3cbd145214b1399678b8ea3117028023e0a53c6cdaca72b2a22ea4ead5a87b7fa8e1c6b7bec0d2bb1544df143172925768a806c56778fbdf4e93b833cf3307332cdc9eb2e194c91d93d9f9c97f5488d160e4edfb36fc6dca2be6e799553045f28cccdc139a8a11a995fff7715310c70d5b7e58bb46829838ddf7ac1b6bccfd392f220c4cfd0d90237fd68da4c36561cae2d0dde1e0618225dc7ccb2833eae7b937857277d11f2cf05d78bc29ee2c8e314cf313718b4eea092b437f0568d6180e7169e11cfad5217131c1c7cbc37da447c8dcf08a06082aca5251ab9f33a0ff62d28337bef4fc3c012690f0d6b05db065892fb24c224393673af83a30ac630bce4aef3df4546548aef67d09d2ff4d4f839b111e6c1184fa587d6411dda9ac3d731405f0acdaf6fa0e9f74f381e2b81e8527600fbe783cafaf9c79a4cfa647c3f7c983e2e06f155bd78819ddbfb30c4b5a194d655e8d4a41cf426a7aea59f8e3487cde2eebb2965ef8439199bcad3a681497c75769cfea464b19bb4c3b182e6721e5d375ce4165fda92fac5615bf610bd8870eb3002f7a356f28ff361d6fc4dbb7d2f430b195e0960d93eeafdc1e74a9f4cfea3748e07d70c90cffe5d6df5da9e5827bc7477ecfdb1a91b20d9bf187907646bdaab59e442bd7455cf2ca4cb79722a5abe344a2740612c2b285b74325b6a1ad8593ad19d266c8a36a236e04813c6cea3a135bf8fd3399c66b82530e149b470d91f0a93bbf8bf815e86c3950aed0c2bef52aff9ac16fc4174be595c767489c2dba7400ee1e81875aec76e94ab0c2221d4528824219ebac7c4ce15fe3a09d8f7ba8cf55edeb8b08bc99a9497b4f38797edc5a397cea3ba19e3baaf317e61d80ee3ce2e53bca09253ff6a3ad2d60e4c312d4cb1a5483664033b376c8b7f1f7f83bef921687f92e969126e1755444ed37e359be5ac79ea0d88b8f7ebc384490c9e47a06e3c83b68c5d00a17bf4894fca0edbcc177a818386e357e6de8748ed30755d83f789edf7155a0df5646d44ab3324009c2fe8284fcc24e32a4411c720294fe7cf872c598dc7b0bfb5e0fb0d8438bc6c5ba097b218ed1ab6b611d9b971e8b99b3eef3d9924e89e1878ca97d40caf4617569e08a230357ffa68c67154c62c201ba42e33b896884e88636c11d3851d93bcf280c90ab52b8cf4b3674fdadbf6bff0d49b331587ad43efe13d59f0ab20f101ffc36676c3fdefcb500b1ed02464be3303a6a8bd88ab588bb139469e53d0298bdc436c82cc86cfdee884c8686ab2d01283d8f7f529136ba145a61f78eaeea67ae1e419696f52682c04c385f6bd9015eea6447c59deea94d86ef8f60e20a3ce7e811f357ab6a6885ce565ef8cfbdb1a1cc5f2c9f0175f568e8c2b09c14a4c411002245860036df25e0e2fadd8576a2143b694fef465e0501c033adfb62cdad5b343fe36d1811675a969de9d3782436581d6cd8a89da2e9a59efd53ee8df57a62d581ce403e5a63f7e36806e1f2f0506675737653b6d4e96795811cc51c0778a277193dc4f67a06486ba6f8336ae0f7eff51cb6bc78a84ee440ce8e9ce04f6c7b72f8643296bfa408e753f96a64042889d78ebffbce226f31fdda9890a0cfdc0daf67b7e57df05876db1071c8fadd115078d1a1066451067f36033236142b292ea068c9d4d1842905e597f37c17b33fd9c4fa29b8214fdc243aad59dd210fbc22346c83124546088b3ca08d7b574f4cb0e608a272043bc54172e8e4c5d1f9d77d29f705159c74f0037b7ca6588431e9ac856eee8dd7f3a4171e8811127365d61eefa970d7b8de8945df83d496b81afaefa4ef18817cde13749357ebf4dce359c7a75382cd1a103e6ee189eaa17da8fe07e9c07505e4da023e4c46b40f3360b0a4900330333333333333333333332bf59ff17bdab9911e0f43a4289092e4ae8864253e9d77daf01769c35f44e2f9b663094b103110010ff7c49471373f051a68e073fcf62905e94852a8740834cec048dee49ea0de9185a41938ed499ddd83cedc792b03933f46dd959964a946063e88f038eb476bd2cec6c049fe3842b98e4585101a62e0739caa31440f3d1791461838cda1759483b5456e0b1850f5d6d2b4f412add71c4a73e687b92fb016247fe5ff69eaa0452f70561531f4a45a2649c5c82a0aa0d105269ebd07153f7a73c88891b5870663cc2002a51d40830bfc4bdd4fe69c24c6fa6c81f36842ba14dff7526a686881cf156b42e3e5786d521a59e072bc8ee9513f648e2d88055ea472a2d6875d81df9e8eea2e243d5acb0a5c4edbe558df6bb5bd2a30923a3f3c4d21d7688a061538a9287def1ee84bf0694c81cb1f670e2f76f78a78a534a4c0efb746c7962fc7e83e8d28309592e4871cd875c78e0614f8207914415b72482a590d98a0860c683c81f58cbe501ec51c529a6819683881cbe951a40effce6c730c349ac045def2fea4717214e21a051a4c60731839f658a5de6fb6b151e3055ba3ce682c81cb1b19b572a43a91221a4a302d259b98856cb15424557ad6a8ebb757132149602553b465e59fac7a0c1894f182198c11831a3028a306b1315ce0821bc30516a08104b6cd55e3e4282639f328a071043e878c1eb48557be6a0da06104cebdb6e26793ae102f348ac0af07b59f5a21b1f2f5061a446053be56c63b4b9f39dad8d8d8d81a55956ba03104a62be710d1ad3253ec6908e16c91ac60a2ae5621555489663174e091afe5894610d894b13377b6edc7f588410308dc88c77a6fc9b2a5af88918512500d98a0c618347e50847229cb90d4ea2a1629426dcc9c9cc643d9051a3e60dcd423875a485fe4f8a217ec58da58b4714b1fffbc604353aeeb980355b5f18b5df0d144ff3bb9ab0bf62ecd7ab7f7d3889a0bba4bb3526464b308352fc9711c6e1b792d7a830b7e343f4d5c229855cac6c6d9d080096a8cf1c52df8683fc69ecaf669390e5bf095d382eb47deb298530bae72c8a1c4e491379f87165ce53789c894d9fd9d59b0298ee669cde9515e47165c4eb00fa9fbc43ef463c17405f5bd9ea899290f0bd63ff0eb2868ea8dd0bf8231df90577a7557f0696f297d103947bde956b0adfdb1b33efcf778b3822b4f5fef9efc432b7b159c788c11f2751c424c695530622b5175e94d05973448a5f638e6c86317156cc87d6b2175e468b73d05579971d3a2e6a0ef5153706b97ff7a43b4146c85944315cd1852ea4852f09e96b4033d7d8f2b390aa6c646ea2d3ff61c92a26023eadd6b8530147c9d76eea79cf7af5340c1597adae7bc1ba2c47c8253f11062a19248dc3dc1b7f54de95a8eb3aaa413dca9d55aafe7cd390727d8f4b431fd73de867f9b602aaf2559ce619ae037858869eff64c309ad9525cf16b350f26d8609adff7c9e3f0f512fc24dff030dbfd678878f08525b80ef3eb55dae4b1924725b8906ce5221e9460b2c4d72fc91e4bb56312fc07e192344eec9cae43125c8a39e50ec93c3cc74f24f8dcf8db1943a68df7810417c733a6ae18c5ce721ec187df3984e0631d72ee3882d5581f7d7ca37e39f61bc1a57c413cc42469a9c3308215ab8f8ab71ec729c72c82f7e8ca6ab921e3e68d22f80badf2c92caa1f6b12c147e8d3cc49b2fa8d0611fc678994b223837b901f8297eec951f63849481f6d08d6cc2b5855fa8ddf5d083eee47fb1d76d01cec26049b3c9d5574e4f697d283607264dd518be6403ad782e0f26e45c7a6413dc63a10dcefab448e1dbe6bba8060ccde839c39f6f8d2dc3fb06a5131ba59e55171fdc0bd25f31c6e78a0fe917de063fb97ad84d0f6b8e403a39176bc562c761c967b6077facef323e299877a605b733f47217daee82979606b4259580c1eb8f3fb8e0c0fe93a2f776052e7287e93d71d8e67073e69f66a7548759f3af0e1be8d644e3cf30f1d780f41f26f799787ff1c58ed8e3f453c7b743539b066eabb77da41928ee2c0558e4777520e3c7a0f6d6c6c6c10257c010726871eb6c4cad14296fec51b981c497bc85cba1ddd74c325592d22859248123dcd3adfbba7048b4955a236f081f9e60fdea6a9548740181108e3016170000361109cc1176ce036ffe247d59df4c1176be0a28b75ac106953cafc0b35f01b993c27f3abcc184f03eb1634b4647af471284143165582e50ef5aa2439dc57527f48d0aac8589fc10a1d8487d6b3187321f8c20c6ceecc163785bef04ad91865c460bf2803bf1aa34a47d559c3eb2564e0a31cdf3c5987db7b8e311c69923c92ab467473c95faf7eae6f8d2fc4c08654b01c79148f4cc1303099abff6139ca786601031f4142a7f2dcacaf912ff093af11275ada8d5a79813f3bcb9abaad8207d9d8a8aa5179f8a20b7c34e5d145a77b4c2117811a25872fb8c08717bdff22855437211b1b1b1b0a003b7cb105d63ae8d882848888a7f1063dc6185dce1830302ef8420b5b7fbed46521659031010f846177822fb2c0679d349bf4aea8f46381dffd0fb615b76d42ca15ece989d7a1af4545c50a9646a860d96d6d59252942ccba57297ffad0ba2faac087ff194adac6c5dc2fa8c0460fd39a283921e6fcc6c6d6282a626cf8620a6c47d2ca5ba1e3e9582a030622d8d83865c080061b1b991a30418d187c210536492ecffef690982f5f4481ebaecd1a2939884aa12fa040ee88edaa16c2d272a490a22a9447cf1eed27f58b27f01d44cd31068d14fd2131b2363636366000820d417ce1042e74921c6b1adb4f8f37810fbdbbd7ef30455099c0a48f1e3df958ae067b09ec8418bab692a33ce10b25b05e92111e068d3412b3b1b1b1a135aa905198f04512b80ef2e5f29c9af73f1b1b6590a182166c6c10277c81047e37e9c5686522f5d21747e023b4494f8a8e9e59fac2084c8ad1736feee8ad939c14bce0b4a0052d86295504d66264cf1a2af765778891456a025f10818fbdcf93c49c254e4e20a0a24ac01743e02f273acc93b89573b286aad50716510326a8a15f0881cf1c6686b82eae173431b2ee8b20f0e9ecaac377e96c33e00b20b0af152d2787a718effbe2078c4721d6e4b969bc102246aa20065de33460821a1b5ff860fdd82a8d485eaa600b8ed28b3df0d0551d913d2980410bae67f082dc662975c65fafc5c84a010c307066ec226d8d4ce9b2a826261d2229de84aeff1c7ae5a4200530c0400c60a0818d8d14c0a00537461931d04591c4924a881e11521a1eaa3efe48437d18528e185931a8a1980b2e846f1e4bb1ef2d3b189481300041162e18e9c9517f21ee792131b2de05301863026398710b763db859a4750d315a1f90c0c6c6c6466d61862df8d3103b267f5dfd6bb4a0b55ae0fd811bb4e0011b1be7052a388eded8d8d8c0622c00001166d482cb3fffca9039dde45206649009d80366d06216aa4529e948a219d1cc4d8386897e9cb7c39c912cd88cb593fa1e7d5aed58d486c2a2365ec185108ff24b7ecdf974056f154dca3ff77fd8be1859686394118319ada80d63051732b2271bc9275a1eabe045dbea7e4248e11d5570c1e38bb935f4c4cf9e54709f22e7c61c58486b2d2ad8287ebd1fe4088d6d9e82c9714abe26921baa29f8db4ebbf992eb81574ac107d963db8d1f5eeeed48c1b54b784ddd48b858a360db2dbe75e7c0fd4f2246168a825db5c9eb67b707668482c931dbcfce2e55f68818593028a306195a3e03146cc7dcc13394e4a91c072a78c17e823dfd8e08f78e2f45e6093e4c29e728d13b0fab61596836a0aa514585c558403ac1f8af5db579791ce4d0143083134ccc71b4971b296aa7498cac1af418302883eaecf9310e193b63135cbd6d7e092ac9a6dcd41a8584199ae0ddf2760a39b674dce021a3c5e040d6a81bccc804132dfc3fa4d7a36307134c0aabb42d8f3f52a497e0f3dda8d98666cafc2dc15da8764a0f3bc4c9b195d0245959081524755594bca0251a223b4b09b6f3c64aa1991afbc3a24d983109b6a5c30a0b69121e93046f3a1d7858da7134df921a30410d31664482ade415630831a3a4cca1356640826949e61ed53c9a452e0604f611dc5ad6a5b3cdb16a536264a999230a5142a5a45995452ccab3527c3ad4b427da8a9135060cc618831bc1844694bc5d9617b2b1b1b1810685198c60b27696de98bff2c576117c904c577dcaa397788661862238bb9c91952d76e07de32682af948e65f9b7624e16447059296e04edf0bf626ac62158ed48a3354ec68a9c1982d7f3a4df1e92445bab105cda49e4bf0e9eb12642f0914493488effd7e1c70e82f7a8738a741f955488a82038f11191cecfc8c1b31b1b1b5435ca90a1021710c435cc0804e3ea5adf195f2c26dbf60a3300c14e477feb633164774da730e30f6c7a4909bb96a8f739c8e8164460a930c30f7c85d08eb6eeb0a47f326ed01cd8d8a851da0726d685b00c397b602af1814b1f9e859ff9e4a883670c12060828607b503524b5235aa40896b2527f69e407a9735aba8891950215f855193388c10b2c605535c60c3db05db9b3b5b667b3dcf3c0e64afa38c61e4ddd0a1ed8de9cb19255456fed0e5c87377aa1d6beae2163f40c28b0b1e183197668daa3901193e7ce61d180096abc60461d6ee94a2982848a65470cabf4398e7c9122e6a6ccb931ca8881994107562a8b755d6574cee40c0c0533e6c07b9c99ded2e1468f837260829667b4751c7ed05171603d8f4551bf1c3d7e6bc02fe1c0079a6298d6e68d493b31b26a20061e00810d608002883581196f60526aaaca29ea07f1324e0a482919e9067268a56c1e39a272a66468c80e3df66e9790ee196d603fd6b69c3da70faa270bd4a82b0d98a0060f66b0818fb443c44b8f611ee74030630d9c8f7e94e25658cc08ff052ab8c00866a8818d132a1e985d85caeec606160d98a0460866a4818ffe77c94ae37176518c2c1ca38c18cc40839aed65dd16b9324a5d4cebd26688186ac522821967e0a3a8d38de699627e6e065e4b353ffaffd0a153065662c893236e774a122103d7b1461f0f2db6448fcd18031b623186da5821adba6264c1e078c18601020a6819c20c31701fb4456e8d5e795aca1c324a04c2000106c2d0a2aa615450460c54d082161c12cc0803eb714e93bc4c3ac5f6c1c09b468aa0659a391cf70b7c14ead1670eea83c89d17f8dccfa97218daed535582195de02a8739e344b888c63c17f8bd1c55713a78a764cdd8825129457496584694abb855875977ddadc5bcc00c2df061a6d89a2c48fe60e92c3029cd4d2dfee57c1e2946820003619091f52d50c10cbc48600616f8da2bcf49b24f060f22e40afcc6945692bdd42e3d428815b88e1e3978102a495448aac05b8bde8bb7f65469845081891551528eb3650f3b3305f652b2b19f3839f7076da8064c50830633a4c0e4c815d348ecdd8fdc0dc628e305fc01a2861951e06e7dcf3f65debff60956d528c2861950e0e32cf5ee89faef172df08118cce08f04fec460067f3ecf0c339ec0874193e594f2e592546e6c94613a062e2025cc7002f7a9d32177497bab765f98d104b6554b72f7e487955902c20c26f04144cb93464eef77395ac28c25f0f1c75b675f71f34e574a041a81194a6033c7b0bc8cef69838f1a30418d9f91045662aaaaeef6ff52f3612086ba610612382ff50d953cb9a36a2a88c103acd030e308bce5b768e9ddd7e9716c94a2418d2a4583330213d1af32ae75aeed78810ac4a87170a00232b6861466148109fdddf9517e9024a23a600611b8e013f6817dea9d6ec8036144200cea40181cc0401808002ecc18021f87a429c71edc4ed316831b80606ba81666088171d50f5a72e4d861f245b0b151a86a54926146109894304b1e6b3bf3ba3002fa67d1ce66d28291c8398c413b67abe42c780bf95672fe4e264959b0395e9ae01de6a0ae8c059b3983e86553dd2861c156c695e88e57b01e265d0fb4cef67705fb1962be0e66e3716c05db793e69db753b4456b0659a27e5f4c934c72ad8b2d897b552f37b54c1a79872d8e41cf3f754f096f1bcd2acd5f3820a3ea6ff0871cbb17ee5148c44fbab9ca9d5a34dc1856e0d0f5c2c7a9a94828f396306d58eba13420a3e6ae52e0fdd519951f081075ec1c4bf3e79a26027dbe3b7a8a93779a16042fee9db8a288b83828f1ed9233c573bff0413db42dc0bbad3ae2718939083c5d4b459ed0497d5f1c7891a27b84d11730e2c99eb669b6033fe76e05d6982df0f235ba8786c51592638cffb74d921c3047739561717f5c83eb24bb829a2f54ece5196c8bd2d4dccc1a312fc75f8ab390e456c725082cfaabf6ef963cbce99041f7d54fb71e6448a47127c5c51a67bdf61073991e07ca543f238079bea4082c9dde1d15d8e1fe4ff083e2587e9c47adca277049772ec318847b1b3c41bc17ebcb9e3f7daf49d3382d5f620215be838ec7b11ac5d4adf574821a4ad08d673cc514ce9463aa513c19bf8fae41cf273d588603d33f405b1548fef2118cb2bb34c2166f51a820d9596bca31ce9782178ffb4395fe767af84e03c6d4eb0ef8b3675107ca499299d831ca4101504a7b9b93b4787664a03c1c6cc51ac4754f75240b07e973e5f8ade1bca3f702b15733be8c8f0f003ffa179e820c4e8eef481cd711c22636e47c9463ef019ebe30a379536710fdc6a250f82e4c03d827ae02bb6a48f37329787796082e730d886984334050f5c0879f247cdf13a57eec0471ef4a4096e953f881d984e39b4cb0a9efc2775e0ba6248883cb394217460537b253a732a343207fe7db36bda49fa614e0efc655734ffac51ba8b03a7ed1a69e3b9e4e9e0c075ee86b0cd923eff062eee74103c8867c13537b0131d62a6715292581b180f63cacd2ce6a93336b0e5318e7ea09a83cad6c0c791c31c761d21f96ae0ff5f7298d2b98374a5818fc8cb9e3352a52c347057111deb66e59fd419989ca392aabd374eca0c6ccca9cccd99e3dc2903bf1e3d3f0711457232b0a9bf6bc74fbd5aaa31f01f327fd746ca714a2506ee723fe4204b523aa9c2c0588eeba23fd97ba402031b1eaf7e7cfa29aec717b8b4f9b3e97845881c5e607376ad69741c963abac047be7992f56bea3b5ce0c3d51072c8514ffabf057e7208d21f99bd685e0b6c4bfcd30e6274cc7e16d8c80d313bf6f813792c701e07aa1e7594e2a15760472c04ab94d1dbb40217b2a53275e6d02fa60a6ca69ceb4d3db6dd0c15782f1391909f6e333305f6fe6e42b97ff0ca4881bffed6cc21b3f2e351e0a4e3fb8fd284fe280e05f6edb35f738cd2883f814f3974c494f726759cc0871635739a5f7ddd0476d36be6a61859b34ce0e368e355c8f1275397c098ef8d9f8ffb445a09eca51043475a96c3af93c0c4ade49ad34907b9460297355bca51d588497d04b623afedf8bbe35cae11583d0dd7eb8d1253b6087cbcd9e3eda7e5ad96084c7f925aab0d79a21d02ffbfaf371a3fec0f21389691e32006818fe3c5b79437baf740e0248877ec16ba9ff2033e48770a661a526b01f0019bfdeff2b669fe487bc1e7e8e3ee0da2d9392fb890a04957fac31cbd0bfeb38434d6139ad705d77194d9cac3ea2b73c168bee051e575e052e282f7f20fc54ab3aae316fc8450399d75a81fb6e035a6348f9b6c42bc167ca7b09ea8d5d96d5ab039d0cd792224573b0b36996b78c594faa92cb89a1ceb85a44697c482edd0dfec3205891ac282cbb29d6c9a3e1ee7157cf8e87598fc73e4bb828bfbb924674ecf602b38db28d50cd92e66ace02bcd744b4724466515ec5e66eeade8e86354c1c7e579a2a2c95234157cdfe65023dc7c4a820ad6edbe3f48f7959f537053494b4f638672cf145cae1ce4c9bc68ed948289b512b572f4e96f52f0b1a34d9e92e3d8e62838ff2c9d7da73aa488828b109d39a46fe464a160c4c3df1ce9e7180705ebfa57a59f1db5f30926d56dcc75ad5d1a4f30b62b91bd11a9f14eb09139cc19b3c7ab2327d809669e39799c63496d82afc98d209afd7f4d705a9a3f77d4cd6c2698cae5edf12be5fa98e04c53a460d771b24d04c625d8e9f68e23f2e62d89c0b004db22f97fb5a963864e09605482c931d3525c2fcd0d3e25d89ad4f0d4f5d21ac749f039f98ae7b0e320d54b24c145951e0d51ed2711a92680110976f2b647e93fa7b6ac4382ef38478f4de6ab05f7118cae85966075fb1eef8ee003c9528f3f1c1bc1be6bbfe5cbd48bfe61041fc71d27f148937b85e82218eb8e24f7520875ff15c1751e3dabcc7b89d871063012c1a57a0f327aea44b38e47808108563b4aa9af94e491791c82cf9fb3c6defc8b18f1620876237e592c2bd3ff142d041bfef1e8b9476f4ad706d228000621d8d7982475a7778daf11232b07c1796976a474a5cf981623eb8c1103ab304040813068008620d8bee9cf1af1f6ef6831b26a9c61d98037369e004620d8d8716a58fb9547538701020a6c6c90c10218c0400c238001083e6bb6fa4a5a39544cf9031f7654c91fefa6f08ff981f117eb683d58c88debf581efe852c71da5d3a43b1f580d4d1afa515bd490438cac1a662f08c1c6c6ef81bb9cce2baf8f6eb01c62a4046400861ed86dbde41ed47ab8394e4300230fdc27bb1ca694cdbcdc27238d0b60e081f7bff48f5b2468f9bbb141d400c61df8a8397d0cdee6f799aa25c0b003962f5bcc1db68798f43d805107c663b26c298344741c4260d0819bac48fa795f3921a400630edc759c43bfc9b1e418626264e10ec090031f07df0bb61e73960806301883e4008c38f0ad922669598d5fe96264dd608c32e0c0795beab8c35be37e6c2902186f683f8a943753d607ba81d18997a3dd88a74162dac047e9618c9c94839c29c806c6eddac389115352770d4c921062ad44ea1d330559651c0aa8064c5003004100430ddcbfdd65bd1ccc93bf06e0021869e053dc8e2d55c7b1c76d6c78fbf1f602f0020c34f0b69a6ea93fc791f32d46d6d612c038036fb1c7b377d8d1dea78891655700c30c7c941b3ad0d4ba1b2515060828108130b0580536364c042a88c103c6704106c670810b2e0b609481b3f678ea1abd22a7bc1859859c08541083071045804106d6f244d3cd1cc7ed612e469616119441060c2a40060cc4a8a1821834195100630c8cf6df67f28888361531b24a6d6c6c6c1cf3820cdca00c1594b1b1b1b1414604c20883037f64e00121d8d88840187633f83e15d8d8d8d8d8d84011b4c09cdfd8880119698023802186bb3eb69caafa3e2646d6182aa851952000230cacc761da28f952948ea5e8000c30f0492c567d9ef43dcfbec0f5fd4f88214acee4e311c0f002ef7194e24787b1a30b561820a04018e6011108e305c7055e667083314040c30d60748149f6d1c42c1d87fc8e22461619c40a6070818d59967a1f8ea4d83b185be062908af46c5ba2b9d40217aa5ab7f34cb78320185960bd63a7c6aefd07606081abfaf032658977e039c0b8021b72e284e6bffd5002c30a7cbef6d190a35899994255e0274b5b65a8800c15d060c3000105ca5001192a10418d1a1b1bbfb121811a680830a8c05bbce8d1f143faa04b31920c2080310526ab47fccc5b51a23962649151a3063d069905c09002b76e9a3cf5a2e6b4d602c08802fb1e7a44eefe5072889f0bb4e0a0c06ed408bd29cfed2e0bd4a0c0c6c66ac004356e00c613f88f52113b5e11fffba4e09cc0c51c66bc5af1e8e3d81423abc7383380c10d6a004613f84866b9a36e95cca589915523062e3057317041043870690083097ca7c9c9aef7d437826264556df4008c25f0ef29645a757674a1a2023094c05477f4ede7a2dd625a0b5a05658cd11cd8d888810b108c24b07add3e1ede3eea123090c0862c390aabffe83498476063fa38b0607e9f2949140c23b0395393957694058c2270199631db9587c5046010819fa4a5ad95437e4ab1010c20b0b1f1c7063070cb2134414d3b553c9d9ec4c8222b004308f994d7f6c7ba5152bfb1519d002308e777ef74e754b66830f88d8d8d8d0d5a9bc1093080607938a6f14b4cf28d8d8d30404081304a8d51460c008009307ef026af5cfa8167768c82e103f2e6e497b336fc72f4c2ca69592f3d2ccff0c2cbedd67ed9533be22e7a89b993597a6841cc1a6a478dffa652418f0182bb030d5d94c673564f4d8cac303e6710860b542006191b3408c373066110c9c5da99112b248d16d1f5380795a1aa3266e0821a2d68411b2d63061978c1044a0768e082c98efce259166babc92dd8d2bfed905aa2d95d1b1be7373668d8820992f15bf76ed32e550ba652c4547d919f26850c18c440035635ea3460821a1fa0410b3662dba50e633d0bdee3681e27fb8b1272109205677b77b59552a8e82a16bcdad7848cd7f73978e080062cf8702473b68b9d5473381956afe02e9877b42a5a1fe7942bd8360b5eb1323a4be62d6841531268b4828f10a3e5e620da81c524c03458c1b4b5dbbb6dc7973f5e8c0c03041408e348e056c1df6f4e264143e5b07f1aaae03afcd0f16fa2471d98a9e0a463f33bcbbb13df50c1c64bfbe97f221ef277be461a1963cc2002649c326e00011aa760428e1bd9b73f95cb9fc10b6898c29c831c5688ceb1792019344a514c492925cb22493417eb4aafe016f3c71f88a4301aa3609365670cebbc71cb210aeeb39b2791989a13fc50f0ee4188216eb953da028a2c6874ba254929da91cd3352c75e71fdd255f4092ee4284f7f2f7298e3d83b4fb07f315b4c965a2547e95d186874828bae1ed629794e1e62c609a6fa473fe58d128bfe26b814f69eb1c32b73746a82ff6cda9b163fbacd5f2678dfca488fcaf2826698e024e62093e55beaf04e59028d4b709df343f3e7cf4a316b092e57881ff65fc84a41a75109265d82e4f59e976b9894e034279564eaca5339dc88c624f8203564f1979ced3a87185948c629a33150041a9260728584b859736e841d09c6b3a654e7597a27b83420c1e4203784c5d81f4fca79049bed530e53688cd09c3b824b4bef9b358f9a77aa115cfa8f6db7f3438c2c31c898410cb68c19c4a08c196c0019c1e4b8c314db55b3aae33416c1e6e0512be6fe8598dbc6c651d5a8ab83030d4570a9421cc91e77f6d0311b1bfa051a896043c71f871e63270fd2bfb16134d8d8301a5835810622b84dfaff61742c8bec21b8e0717c52f76511238721b89059f3935804fb3c6b542158d1d89fe38cfd71a987105c7dd25cbb79663f9a41f09ba7d3c7f96204c1796666091ec4dc5af336107cd0fcd0426693c388800736368e4003106f8b6b7e6021fd47e61ff83f8967b13a7b5caafb813da96421577efad8dd075ed532ef5d508fc3900f7c5c4f1e7b4988529dee018d98a2d1124285b985d4e8bcbe6eaf29c40e0d3d70db1dcc42aefc1b6de781891c7fd3144d2b22e18153931ca61b8dbe94531b1b687760328a44ced8a1fd68c60e9ce5889891a3cae469ac039ff4562abb6efa1a37f01a3450c19782000d3a30d19fbeeac792c75605631c326a8c018316dca0cba8516c0eac460aa5f6d9eb71d434e4c0e616adb857371e7b4e1cf8c852fd8667ae9bd4c2a12049ca5342a8ac6cc92fc78ed2b6d4f6063e62bfbfe6d1cb36961bf8c914d5c8d4c80f510f68b4815151d5fa502b8638f909d06003ef6e9aa3f44d1f3f47171168ac81af9c52745e8ddd715f1b6ae0e39c31887b9985f2fcc6c6c6c6d628b5028d34f01373ca09d805f001bfc1726465273b4d6902f482fbf83e97e5304d31a509c00b6eb37969a965176ceee4e6894aeb82eb209da40c1e7dd090ce056b952c76da74146bd2b8e0a3e5b2983937ae47fa167ca07f1bad5e532fd2b6e0c3bc8865d782959026679b2ca9c5a3053b594ffc22d47467164c88145137595eff65c17fa59e889f9ee31b0bbec3d871d66aab060b4ecfcf363d144f9157b09d238fd4a1246f64ae6042b6a05174b388df0a362cf3473bd13e0a59c1c77b6b9deed73454abe0bc2ba262a889f4a10abe3f96587e143c2e53c1ebe438674963661a352ab88b79792af24698a7e0c65282757c5193789882f598f2c77a31d9454bc1e94964fde0e178c821051bd29b4a62f2e9f85170bf2956caf2ec18140593a4dc52acce1f5342c1e4e48e24e441c174d29822f9092ec472b3541a4ff02791398c9c77828b397e20f903ab09694eb01b82bd9a787d8eeb4db019b277a45c6b82899b3d07ed172c7b6c2698a831063b91641fbb98e0b5ef5cf237f2be7b09b63ec5b57a8b7bc9b5049fa129f32a8be76c2bc14ebcce5a1ad3071aa5041b9da33fe9daa65627c1f4e6641524ac36a49260fccdadd7ede3d06624783dcbd9a2c6943a4a428237ddcef125f908eed4b4b2794e993fd0115c0ee191a257aaa3b111ec86a5c90ef7a8153282cb13a1bfa7963e5216c1affd76ac6aa1bd238a60b753aa84c825820db7cba903adf8924304ab318594af7607217708d673760f358b4ececd104c852cdd1a53e48a6c0bc1e8787c298db584606a2ac6d6edfc51a676107c0eb2554eb163c765ad2078ffe8c3cfd91ec5606d20d81077c5a3d41575aa0504f7d99356488e249bb47f60a344bb2c2ad9bf39fcc0844bb6e4fdd10736c7b9b9fe41a7f5e0032bbe7f2e493a1ecd1ed897d8e351f3efaf0736fda34fac8914953c706beb572d794f277860a37be8316367c8b17307be2fa7c81d1df5453b70b12623db7398b97d1d989c77b2a392fa1c74602db3a6667747fa9803231124e56b530d8d910353371d954f8f03a7395868640e07fe3c3d4f7589a61cfd06be423d768896fcbe7603d7ba5629f9dd0646625b45b3698d58b381cf96a333e9eb1ca25e03635652be297ee40f3530f5a59fb9f91d7aa4810fdd359dc31c3a7a2c1ab89f98d4c3de3330de29c903a96d0f5d33f0713fa7ecae1a1da70c9cef7b8829ad64605aaa62c7f531b4a963e0d53cc689292a06a6a7e207cded774fc3c079da983754bc354d3070a779a1839c32e62dbfc0a59c52b17b244f2abdc04dd65011a2e5741f5de02a56dea40fe4027b9aed6fb7f7e31cdc02ffa15cb3e6905a7cd402bb1dc1420ec42cb0e9437d07be5d35412cf09ab9a6a390b3bf04afc0f874bc3b92f51b422bb09e3cf78fa73469c22ab0a71d332c6aa6140b153897c8cf981a517d3205364296c6ddf58e1a22053e7a3bda787fd371a25160a2e3e8dbefdbc142140a9c6d4aa932e4a8ca73fa04364dee0be239818ff224ebbce671bc6b021b424d2c84799433c604b63d881fa7dd2c8fb525b031a5d879b22ec7a02981c995a6e395e86ef1d224f06799f36712adea4a91c0f4c608a9b3c3b718d22330b9827b548d314735a911180fb2c7a123d6b79216810f3af2b1ee682a7d1c44e063f0ed389fe4fcfa310426c779edfb2c781c3a0410023bb126f6afc4e8ce1320086c8c79d99176a0a53d0180c06ee826d188f8d96108f0037eed3a5e079ef17243001fb0b12ae80729a7d534bde07e3d2fbba6aaeb79c15ec550e3b93f7aeebb606def4a7c4c3cb7ae0bb6222ff4b54d75a0e782ab4f9d199d263de8b860533a4e3152505fcf6fc184985cca73181562db82d5541fa46bfed03eb6165cbd8b5eec585a706513aabaf7d33f66c16565c9e551aee49c2c58ffd0927b1cf5b162c1e43cd1bcf23d8d14165c9e1423a494e5005ec1591c89953aef6e923900577057d767619ab2a33207d08af5bf831c578eace034a57acbbe1e438babe0a2550c12cfa20aa6726dea64d7d24b4905db164357bc90b95e4105a3e68188d96775ac9c82b5cbcda6f98147513105175a123274ac1f764829b89e4c898ca9271d210597af3f34d7894e1319059317f3d652fe30f31305d367d9a1e69cacc60b053be167f9e378e3a1060abe3ff26825477610b24ff0618eb586ee38b4a73cc15404b518ecea04d391786d97eaad599c603a5f688ee38b1423b509f67b24660e5de25aa509b6a3145531fa48852a33c1eb56fce8703b9b871213bc7ff2903da939e39497e06212df0b9aa3b821a525f0d01e6525d8c9499be92379f6a00437eddefe9e8358fb24b83b6bad9ffa8d5a125c7f1027ea7dd7a891e0a398dd49d30312fcd69e87ba8aec96e3116c4e5759fffda2b4c311bc87312bcae33482899d63bdbc0b12721c46b0923d8ea3c7e11afa5904db71f4122cf557ba1c45f0217960412b4f72ea2482a9b89ba3c9ebb4d520824ffd91a6f41de44bcc21f86c89636d9f9b1a37045755d69e72fce06b1782ab142923354a9c5c1382c98bd6f1b4467ad683603b2a6257748af96a41b09a9f8334963de8d581602c25ff0ca176f6b180e063f7a41473f01c7ef60f4c8867292b7358e4ac1f98dcee761d0d66d2f681a9ff14152a7a455a3eb01eda58aae57045d53db0651eb4d4a317ed540f4c2aade974691e789b0e2c639ee01e291ef8949bcec53fee5af20e4cd48769f735b7426907d634fad57992b41c75e0fef533073979b63c1d98fc9b24738e93973e072ee8e5fdcd98f71eca818ff78278c5300e7c3c9efefe7110fb2e70e03bcee0f1063648f4286367c8b30aba817789296df288314305dbc0c796d399655709f5900d9c66ebf03c4ce33979b806563b27dd8e31598ec3500dac96986a9ebc9453c334b06569a7171a1a986ce6414f861c796667e037640fa22ba1679919f8307718ecdf635ec9cac0c71d897ee5b2d77c9181b74a9fd9e3f4e66e8d81cf712421ba5ea5db120393b394fd7594ca422a0cac68e61ed11c7fcc0a0cbc47eb61499876e87f81fb8fb207e1f9f2e65ee03b2b3bb4cc3a7c09bbc0a5b869474dc2f225e40217d3c4eed8c3ec4a116e818f3f1933b776bc8a500b7cc5da1e0fa121548459e0c3ceae8cebd729736081091551752b163aca7105de538e43c892de9d0e2b30f1e3eeb856f2eb4f15388f3fca11f69226e65081cd996f1f9b87f6963305466b4ab3fe635ded4881ddb65825a2c1eff351e03fbb876ce392cbf250e0234279278f9eb28779021f6f244dba9e9caf7102d35752ede17efe8e3781898ca93c0e19253b9a099c56cef7d5facba897c0a4c80ec1fecc3247096cab871c43ed56ba37097cab851c6e1a9aea45023f6eeea1835412913d02176a9d1e7d397bb746e043d7182d879a3c445b042e69c8714647bd6a2a11f89c6ff71739d4e773088c448999d43e4889c9010881fd50543b7b76c9901c4010d8535ffd9083b6c5710040e02db679a448d8a471003fe063520ba976d3ecc301f8800bba1751246ffa0fd20bde32779c58d1b253c20b463a0593a0162a7976c1a758519355d0ea485df05194a6cddf5e1abc5cb09e273d4c19d563f170c18e073ad691b9b7bb5bb051d5a11172f453670b36b7c53fbcaed482cb2a92b3786aca88155af0bf933992977ec75165168ce79e74f8595be25464c15ac8cbdf51b68c199558b0ad12257c73c082330f11c53d737d1ce7157cbc7ecdd08fcbf2e30aee436e0fc2727aa54f2b988e1fe75c751b2d1e56f0e1640dc9ccc3298f5f051f7adbab0797a839af0aee73dc9cfe0911fb4f051f56fe74d495266b1e156ca49945eab632d79c820f75696d732c62a531057f5695620c1afd717829d874f5d8a34d09a9765290e3382afd888e824b55b7ccd6fc3814059bf45527424c964342c1f4a40fa286dcdbcf41c1f49a7f8f8fb54efe092ef9da567bf9a66c7b824f3ee11ef27eb4b53bc1e6e8f414dbc562bf9c603f47cc5a8b314e7037c1e55ee6a6a996bcd1046f5122e7ee9a185fcd049fed5f2f4467ca9a6282aface8dcda91871d790976377a3db28f3b86a425b8fd8b39db637bff6025d88ef6bfae2edb5d9012dcbdd9c6ecaddc3993606232f7cfd197d25f24c1b4e4c8d771bc1aa712093e886892e3feef5012487092efc3d7be28e13f82f3bebc932bf22fe30846f3dee338aecdee36824b3988d0bb1e23f8dfe875d16a2d67b708367b495e799822380ff9ddee1e65ce27824d93fa5c6a29e61044b09bbbd351ea1869d52158fb8f4edb10314469d571488a112904e369952a85383d2e21d89c961e4224a64e8e41b0a213e3994df7871d82e0e3fb9d07d1a1c38e409c9b22f226092098f0f833f55d72f3ce1fd81c5d8650cdfb816fcda1a78e7e1f98ca1b62eeb154937c3e30f6b716b273fca063f6c0a798b22dc7589fc38d1ef88d57d277413b6b260f6ceee6b8e3b8e381bf8d123dc73be948bf033f29c48b139253a7dc0e9cc490561e86ed7e741dd889f71fe57a50f6371df8ca6114d31ca4adda73603aa5f68ea8d7115f39f025992e6667a470370e5cd254d135ffa411170ebcc6742f313c0cb1ec1bb8ba5c29fd2ea163d50d4cc6f81ee465de10a26d6092076952a6c829c6940d9cde7a983fa3a3cd916be023cf92a37d875a39a906de52ec28b26b9a1c9e69e026e448fb4e851ccf43032b95b2c3a0d217a37967e02c539aae081d87963c33b066e39aa31873442caf0c9cea86564fba6f493c32f041e652c9b159c814bc31701712cf73ae5fcd514e0cdc89ff75eed66b47b930f0e9cc227c3af2fc210706466dd383bc8a9232e4bec04fc8aef7a4917248ce0b9cc7a1e29f92cd62eebac04af6fdf724294a7dc70576f57f72aceafd21775b60f2762c71a4ee226ba70526daf7fbac2cf09a53a63a893f6e1916384dadb7e5315dc8b9029f3bfcefb45de68156e0730c16b67665495205bef63bae602975ea8a0aacfdbd789047fbf25360624ae530859ce3b65260cb73f8b97ac5758c02eb6d9583ce99a98602b71ddd458f26216b744fe0efbcd2836887d63881d7889903dbe9c9e5d1047e537d7eec543ded6102179d82a498c5c35f025fee23163757fa56094cceb288a8f66c258149561b224dd48e0a12d8b28fbe081d68747f04b622e78776d69b3946e0d3ae8715fdb3c37c11b8749f97d69b3dd6108189f02c518267ff7608dc5ddcc8a21d744e11027b97671337a79a9009027b6df635395baed081c0e7c9fe30e6b4007ec0a520f5d99b2e8ad502f0019762151aad9aafdf5e7095d69f5256c8109717bc47ff4842eeb415dc5d30519d921e52f08eb2ba60aa6f24be89d77e682e788d8eaab2a62c652b2e98ecc98385d4b9e3aab7e037c33cdbf22cc4d4167c4fa7ecd1e6b87fcf5a30f1241e4670dc2a5d043e8cead291460fa96a22301131b5a5eb4a1dd443603daa4ae3515d21f09319e1398c7d9eea06811df5fadd6ec953e72200084cce9d126e9336b48f801f30d137f6adf868ca1b04f880af919c2cbb4deeacf782c9619e14a21fa9a69a178c6edeebb24a962ddd057fa97bff76515db0f9a3c9949a2b574534175c7bfb478d22ea394c71c1bb985aa69ce92dd8094f9ebf25bfa7a4b660247b3dc70e7d4c23ad059fa6cf7f7214a37b50d382bf8e4ad344c71e5aa4b3e0a38d2a9ea1729cc34fca82f58ea9adc3201a3a3a63c15de6ef92aed8a776c28277bf493994e9ab27f3155c8e728839767748f939ae60520e77f42ac7a92399ad60cbde237de4ee7a29c90a56ba3f8448a1377d2a57c1e71ca5be28a15405e3b61e576d08d216ca54b01e6da8a9ce1f74e4810abe3dd3d9e6cf29ae7f0aceb743349d5e8a9237057f3bfa671d259ab4a5e052d358ce2a3df15652b0ba397b1835e646a8a3606b42d04c57e2c12b280a56cb93aedb9945b230145c8e43caea6b498358080af66ee2c7940e2125859f603bfccedde15f3cc16bf7f476868af1624a27984852f69633e4a465e10457d92ee6f4eef0b42c9be0837d9c1beb5234c1ebb8fec4f4507db592092e87e379c13bc8d03930c164b878548ff5277e5c8233c9f1bb4951ff7a4bf09b3b3dbba5b95d5f09b662a688799e59fc3e94e02da4d552329360e3448447c99a2ff996049b3f394cc12e877e6d24d89174e51d5f2a4b5148b02b5dbf63b7e9b3f908b62e8d7f18c2f2c5cf116cb4f13c4f398ec262a411dcdda40823f8380e3234a68cc871e616c1a4a66d268d2b82558d2942befb6c5513c1e62ccd71f4feb1e4484470f939a5504dab54f3109c68883192e7ab8f4443b096f386e4fc923ad51582ef38cc1c67cbd72ad511820b7edd295dc714e90c82c994cd3cde780ae91604e797432c104cda2d5d891ed584c400c1e71427348de70ffc258bec28720eab347ee02368e6cf24edeef13eb0995572c71f2f5fd4381fb88e19f524343f28b7f6c0fb5488a19f436f5a4b0f9ca5ed4de60b261d5979e0f623c79f2a2a7a280b0f5c284bea133bc68a48dd81711b8f728c943ddcadecc0a6aca11f67fb1ebbaa0e7cc8d16f90a89034e7890e5c4e4d48d7f47587cf81a9503166eabb87db7260624eaf9e249a4c3571e05a5244f030d65b04e1c04a886611a3a50f397c039b7c444b2d85dcc0b6f485fa2eb3ec618e36701a39886ac4f44a123670e117d1327a8e11ae81b5907218199375484e0d4cce71b67fa591300d7ceaca71e534b942060dec6768fe8590b3ba2231b25e705a600e0d6a6c4de000676034a5bd4d8d9272c70c6cb8f7beb82431bf0c7c4fec8a9f34d5c69081e91cd67e14d1a9fb31063ea8d3cad7996a7b31b01972583ac9b9969f3070d2f9732cd1fe7b30307133a4569407e1f9021f6ffa76b2ac20792fb031ef685e7e0edaee02fb51865f9e4829840bfcc698f951f55b602b748c581d460b7c849c59f2ddf2654c16b8d718638e8e3a46d660818bc8f4133a6adedeafc06ed65881a96d09a94752c56815f8a834c9b4b5ba3ba702e376f7ff365e914e81d7dc21e7a60f8f925260df739caed2e51c865160ef3edb448d7ab1d250e0e376cd10838b9afe04cea35b0e742db88b4ee0f58386f9c6da94b6098c644aaf9f72bff34ce0bf2a2d7fce1d25cd12d83ca9f28f5dfaa054029b36a5afbd47d524815bdf7fff9cde425091c0479bf1dd23f1e8398ec069b0f68c19ebed4c23f041d00bc9be99e216816f0bc9722574e51422b09f3f4c672d9d2e84436053d61c722015fb7245084cce98723ca9e3d0db20b0975ae2af871c00085c882e751e77982f2507f801d39b3c5afb2b4f8f3b800fb8d1faefa0bfc300bd602fb6c7cc29378f78870178c1d5e4c8318e5b8cb13b0cb00b765483a6bc1e4287ee30802eb8d469297858396f8e1d06c80563f1e350dd443a3ced30002ef810faebbf62b7e0534aab495bdf2962b6d03b78c56099d5828d1a9239e5a022e5450b26556d0cf57f1db6350bce63caa371333b4aea90059b3a4c317fb1e0e3e8f3ff26cff5a982052baeffe9e9e398fd0a36a528cdb917db5c57f0b5ad9d9347ab35690597d643f4841c73d258c1741053b6acaec92d3a56c1dda64ee7d4dfee51051f3c680e42fe380648052ff15b43ff570edfe3180015fcee27df00a760e27d10766191b939c700a6e026e97aaa14995b738e014ac1ad276bd3d2645d9f6300521c075e4933e547c1759c1e3d33e958fe45c144f5bcfdfc97a27e28b8bb4e912e3df5a60f0afec3570b0f43d48bfe13dce4150be6613cc1e41ca3e4f477183ca6136c77bcd19037e7dc184ef0a19a92eee468426e36c18490f21dcb35c1ef87bfdbe7af8e3299606d2f730571959c6382a90c397718c9efd37e0936b32e7a1ce3f66f6e09b6edffe3984c62f65482f73c2904cbebcf9e12dc0756512c87b4cd4c82c90f59cf9206cfae24b8601fef7ded48301ebe69fcd37f4f1b129cc5348f03ad1fc165288f3d8839d4aada11dc847d7bd8a1deed6d04979b9e37a464294d96115c87b5be1d4af5fab908ee2279d8a12615c1e6907247b929a55cc944f0615fbdd122a584242218bf8bb6313dfc737908eebd634ba6e0f71134046357ef393dff03b314828f3786342d413d300921f820b47322998468de20b8feda24a9a2a9bb1304d717dc7ba2831c5a7702c1e6bb4f1fc95977ba03086e62e5d97ff4af713b7fe072d884e72babd0d9f103dfff92c9d53efeb74e1f588f63a84f661d3eb01fdde5fefdb749a9b3077ea4a205c98cce161d3df0bb1539f0d4bf0ea29307d6a26d472d2dbdcd8107fef2e31c9ec7f7921c77e0cffe24e4f250cb1c3bf0122dc48e1a2b52fa75e0c53b735a2f3fb09e0eec997aca10fd1cd8cfb1e74a1de75897031fe66b85e5c83d67e2c0779cca18ec6b7c87036fb5c9c30c212dbb6fe053c769912ae63832ddc05e8a9b6ab503bdcab48149e9cf23d3fe96071bf88e58766639887e0daca61d4b5f69bd4a570313e377ce61ae5dd6d2c04928b7b10df553a1818992aa0e519f818db4ed388eae19d83eabf50e51fd915b06bec34c69e7692c5d4b063e637be69493db73e8189830abad14ea9a3b540cdcc5f18cefd69e1f0d037fb7e2818aa98ea46060d376983aae0e83f9f90526f74308f5d0728ad20bbcc40eaa92b506efc02ef095af3507aeb997825ce032ef682a8fca97c32db03951312d654a15422df0d1b575cc8d9d31c22cf081d487973d050b8c558847a9995a39e50a4c7a64d6fd673f59b1023be5665d113587a85481fb1cc4bc3197881c4205be7c920651cd2529640a4c9d485859c60f39f752e0a335c7a4d645813b3ff5f0b4cd4e1b14d8cc9bd25f70f18d790267e7df717565ed502770dad97c2fd66ea709bca5767e7654f7554ce0e3f175e9389964ca1298ac9c31fb790e3b47af042ebd6df6c7e8817524812b1bf10e32340012784921751c6b25edcb618023f0d641df69af664d87018cc09947b9639fd6f1388e018ac0755e8e834899b7c7630022f039d2f45b0fa777720c30043e7d7772c8193fbd630021f07937dd15e59edd314010d8ca314eb7b887371d0300810d9e15e2719ce378f306f8017f912362ce903107be017cc0c50f4b1ebb6596f7bde0e35451d772fc2149cf0b2e337b1ce7afde90c3ec8237cf81e4f851e8a835bae053464a69a53daed3e482abdd888ec31bdf89c10517377ac8903a78cc995bf07e399c8e93755fcad882cb93b45f531d5bf45af09ff3c73c7a9d52745af01edf390b5eba3e4821a72c915c16acd9f969eaf85173742cf84d3147d1c3538ea761c1649eb28bce3cdaf72bd8be7cd19cdeb19876059f4933630eb6d16ab782bfcca16e7994759666051733bd6d3f65588e5d051b394a8ec8618ef9b3aae02d456b0c412a527c53c1a4368dfc6c79425251c148e86cdf93f8514e4fc1a754464f71d74c4953709a6f92c7b79a3a92a560a5f2e69cf18394bf24051b4a57af1f051faa876ff9e314630c8a82cdddadfb31ec3f130ac6b737f5470e6697020a567d53d77ef6e708f9041b9ea5729424d9fd9e60f34e0e15aff246ad13fc7ee5ac3d2e1da538c1f4b7db4b5ee84db709b6637bad8bdb93a309d6b44f4255e4dc31135ce520badb44458a0c134c8cd93e7dcae8f1b8049fd5e2b58a947558823193bcfabab1e3bc128cc49883c4afe0775382ff3cc12b7ff2b88293e0e390c395ecb8352b25093e6affcd0c21b5f948b0af493c5d4b2546c84082dbff78c17df4023ce2fcebb18e60c4367fbb63f30f3c8d60625acacc99e2153c8c60dd37dff7c713c5f38be062ca5e1dead64ff38a603d8a12a37b9477433e116cd4b20f434cd929f78860334eb4b5b2cf349a43f09fe3fe2cba7e51620cc16765cd0fbba394670a81c71b3cda0c213815b3cde952ca96cc20383597ee28eff50f417039bbee6b8d772a03c1eae6e82f67b4e42120f88e5243ac6cdf61e57fe0b7326fdb93f76bda0f6cadc7491f84c50b6e1ff8089f1811b4736cf9c07a500db103750f7cf8a61b52a67ae06debe3bbd70ccdc93c70399a8d4749f2839778e06f235d9be6d8299677e0e394dbf6d2e2d79476e04edbe35c1da7690ed681afc8c156fb52472948072664ea541bf5724a700efc74ccdb39aba6ac500ebc7fbc29e520a5958471e044c33258a4c081e9b70b153943f45879037bf1ac2268d68d49e20646aa62baf4e4071e6903eb9ebf2c04b18e52c4d9c04d74f3489b4dda73be06be345e67667b089a733570bf1e47938715193f4f037b41da83998d77f01c0d5c5f660f3a4abd1acfcfc0667fd7b5ca4a229e9b818949dd2346284d1de665603353b060394aaf3727031fe4b28adf71f2d8e563e0dc524e96a3493e75b91898b4f6ac9bd2d45e7918f86c1d7710b9962f073918b81cda3cc614e2e59ffc0bfca5b81df787ad1758572ba9102abf4ac8bbc0db646d568664fb0f2eb01279d39991c5ca630b7c6848ef4a1139ba1c2df0398819d2d55b0c969305a6a37a85f86e97f4c7021f3bf4f412e268b57f054e74453bb22599f756603a7d14ddd2a3c5ecabc05f86cc1f8fbc2d7a2af0a17d9ca38d8e4a35660a9c764485862cbd9791023f2ea69744b26adea3c0e771ed10620e728c7128f0b9a37ceb90374a8c3fa169b70ee1b61398387137b847d28e6c02ff96b3a5dbe4182f6702db917ba61b8d36f95e02173ff2d89d13f2344ae0f3b7a6ee6fbc4d93c0f8a47493d7a663b848e0d6fec32af856ec8fc08e65fdb823fd286d23705adf922b7dfc6c11b875fd97901c54599408acc6d49a1c43ba8c0f81b50d59ad69760184c0c4fefc90e3df90c7ec0204810f3cc7faeb95bfe2d805000293d42a7ff7d7378d5d801f303177282126bb10a2018bd8a8e46ae42242e1e0c05030180a0381c06037be3593160000000c180d85d2340d34c176071400033b322c3e2420121c120c1810160e0c0c0c0c0608068482402018000604c240301818c493d1ba06de9514db58cd16dcfabd95d3eaddd28c5d84376ef3d1e3b9bcb6ac5e0f606e1fd8a2c511771fc97706f0c30c1d4a7cd1468d0b6a28d1c484c9b7712ddd33b6e90bebaf5ab25d45a468636ae64976f9c918e45043a3a2007a92372148d92eaeda4ce51305f8d8ae815e59ca75ebb6525958c1ef3d03b17ffc0cf14752b2d48e9078cdfa85dbe8c42065cddf8a2bbfd283a97105b1bb939b186c0f779bd66a81088618b1898a2a6ef49216dbb4b435a202bae2ee765c89d435591fc7ca987177cd038e50269cf55a4d3c0c2816fc1c0d9294b5ca28a8091379954c1eaf1cd07d64297ebceebb705facc3e881a20743fd8738538dc3c79dc13cb45ce6d0a05da635f6c96c224a70df5421956b07e60cf1847d456fe6eb9133ba61a38d1b7b638efb1a5f49f7b1a689fdd4a3870c87d28e0935b59e746b9011c280982aa54275246a4e532ace09d86ddf387874d2d98703eb2eeadc935737befbc08a435040372e1f6e3a41bef989d04913694e2c87840d719911ba192af553bd994d007abdf6f4f1c34350573e6c5092b7970f8fbabe72e5dc31bbe4214016a533090a441d499328134c5ed7d9530797b6bb1a2a208270d954440e1fb64c46026dc774845d2a7d5426bdba2b1fe5258a78edccd18147174edf3d7770e7cc0127a3e7a401215e7779e0d17d860b099ae2e038ed8e6dccc4b7c778647a7e5289e6834549244a34c184d023484f92c4299f7878eefae99bf36e1d1237c74a428502688abbf0e88443e76e4edd3d7b76fddcd36397cc3d5610bc217ecb62ce6326b042cb13467aa49bbb3c35c8d1b2358a358a1472cba756c41174152db13bbf7c7cf3c6a36737a71e3813d4e725fea23dac51d1e7387fca5e122a817e0930be64843670834f1d7077efe0bed393f78416903fee0d777cef712b09d2919c6cfa642745069504e924a7a17dcdc1324899122b3afceed9b3dba7cf9cbbece8dac98dbdabe0aef5b8c09972c708b67cd69025f14653422ab727126a4d9ce6f8c8938fbfa9aa1d94c1cf6cda5002192ad4d0491023eb324d8f633bcdf0e0ad540af9cda14cb3063a56b2798d255b4081f0844a5f182eeee529d920460339959c4d43339ec3ba305d7affc831d720064cf6ac72f7c491b7f7ae9f3eb877eab0d6578942b0be38be79e7f0facc8c09b9949d3b758e810ed1af77949969d1442ba10495c4ed6a68219498c53cae555165319b6da6f5274e9ce2559d24330c1b08218ff4fc12bfb5be35b5cbdd93c6f013b90c4bab836879a6051b23784e718107946bc5ff83c3dd7efff29a0d94582d2ecd6d37177d0751e71e47f1f1eb8b07dcbdbdaa4932e971f2ac5cfaacd1dd75c7ce5b4b341d0268153dbc940c92085049c63acd9dd387ee9c3e906366cc125dea3662a14e8c7f8a9e464774ce84829bfdb571b86c9ecd523d596f3bbc7becf6f535e78e5d9d7620673b7a059c81dfbd75de3cfa08c9dc329be859582584ac930066b488e5c4a2018b84f4f8fdd91e0bc2778b3a77e8e0f447876e4e9d3dbdecf8c5c3fbce4fdf9c7add8ee39bf7cdc51b4f5a61419a7fb008f0b56783d70a8c7ed249907f017e14d2489a32f9347e45ad0e4f1ef7d095a383f74e38be350f217ad491a44a76ad534777ce9d3cbbc6f9e5b93b470e2ca774e6fcca933b0737234c843632c91c5b8392fdd40d87ae9999016ed7410a59a448d4c933fc1957f3f7ce6f1cb9efeeaaa3937b270fee9199a359f73812b45437ce3abc76c264faf5a76e9cdf6b9274ef8cf14898681811adf62d7ea6b68f25ceeb9f01f4cc9b53141e36d721b351e369362223fd7943851141c889e369a6a7686d1a37ce6d66f35d48f2dcb55307b97102dc838594c7270edc7675d9d9c9b5b3e70e5c7f7a8d499a09134f9d442448a490247dc2f4274f964639470843f0898c60c34c680b7d54e5a08e5cb28b6ca02929f5a633860f1d12b40c4f48a7b8995da43f15fac74edd3b7ff3d0c1c519e7675d38f91a52fb67e20e419877c50006ec6c9d98ce3dc720c16546b8d070cc61449db3d3eab5b44516b350eb8d77615d1526ab9874b1315dd4617a3ab60895965b5ddcbebde7e8d4cdf9cfce2e39bb7b681ffaa4b7271d1fb78058dea95b27e72ecf3b71fae2b98b1336d29fba71de6cca8533f78ce1829028dde44a9dbbeee8c2d1cd9366f8a73c7b76f9f98563b62121c249ebf0ec1ac777cfee30c4fcb037497b9f067acc865ae1dc6c6ad26d5d3a35e898d0e225611b21129e3426d0b36590d910070a94fc6a522d1ae6d032cdf07755245480a199edb52a15c7582e4475e6396541fc6ad691165d377f13db231f847e3c0207ee8926e27d24b684f4315f3a5d40d3ac37d2312b0104e32d3048d731b75c9ed484da8179234c3a61901e616072f36f530b1a09fa97dc50940928afe39f14c728cd943eb19c77e70866e198c6a6e8f8e7048eddcbc22d038fc433a00e004c87884488627d3dc98f195e28bc96819c850a5560e5f605b53feb0f0e91ff9a1ac354e1f0453899253e1d9c085bf8e4aa8588c7bc0b98880d46d5d062097ff8d2e35e9dfdb53108545281bfac16e14ff86a1992ff4e17b5c574a798bd1ebce18611c7b452ed0c9a4a711026fcd1205e94067b1510907d0b7ee7a845fae81fcb7110b948db36c94c638205de06625225f4a8033b048aff6ec689590168f522513b8a4aa05984e91cf209013270abb2357ee3b79acb49304a6236acaff154e7cb8e39d9ccd6baa8f4b41744550373c14e8e932cc63cc42885f2398c12c0d870be215debd4a9ca16e6d74cb101360551ec482dee3481d412f033fc17ec8515e59117b4aac04bf8d33a7c4d6f007839def0d289145742f128013566654cdede54a23389289aa58667515da82854e195facda491db4fda1dbea95bc4113c15ae4c5136f86343dc1d7df81cba9c6d61e0a34ab68c0a376f485e988bc521b442cf4cfdba458a6cceba78abcccdccde708785375a6db61dc2e48773f08a1fe315ce6744a2ee1400b793b122e474970eb11d7e0098a37218a4f4312a6c12339f07891e10872e1779d0de3fd7fbcfe4145bcac9620c04bcf3295ceed13fa42de23231a18e732450148903a5ac0ebff0c08053fbea353893946e6b3cc4b8c33475120afa14b6f64241b8c90b65c84b44fe90e916204e2d979b3bafaa59a7c5df5d08309a7eaf86b02a2cfbf41f588d65139f8be5dbc3230d50831837d65b1dd49c91798eb2353c80aeb8e71087113589db0714215f1d1e67ee54c4dc8f6447a4d1f0d9ee8185e6a99e30b5e49397e7337c708a4d2c50945da25593ca99ab4758385608b67bddc087b47fa4c421a83606779ce39ed0e94ae91ccaca959063300f1fa4a7cba8a224803d915cdecbcc00b84515147029bfe6b7f5b023d8c20db56aa90678662cebed044083e9ba5f16d50c09e12ba91aac8d68b157a98a292e99d77432ed2302fa138e03dabdf5d00d4d465db9bfdc424b27cdffa014b80999137ee4770d4900ee4fdd0673b57f147f6f552ad4b87730780714812a0a1648edde55d2c1b7cfb9a29c7a70c66a141ea681eeaaedc7292d00a7f67137bf3e3d87ed06300ffc770652c9435eb72cb00b4380bd5c0eaec62da08df1f303278bb9a66c5cdc6476229f135f3cf337cb08041a6f3a8da2690603cfb49bfda52a4c4a60479ad9e258b81d034a5ee177c1983c819e78cc5e345749de13d79243ebe271c14a01be909d7d5bf75784c31205ece6c966a4dc0076a44070b31bcc72f1816e4857150615d7de68a3f420cb3e58a29840102e1671937e11da73885b89f6c5192f0473f75641da416d3e1b1a289c028a1b550d18cb391f30685c0622dc1671f6995205a861cec29afd6d49f02ec8c00688f4a178dbeb9b9568e4beeca50a946ead82dc59c3c52f8f6b59c9fd08ec991d6ab500bc2382aaa47272267fcd55266cd5a77accf28f220d9ef287003df79bd3cc32f0aae9d9f31bc35e69350a83ece6941669ea4346b07006ad90111d371ae9d2fa3fd204019987181c4bb89b020006668033f0b7777b58d01007c05f0420a48c2141c5183ab142b5f51c47a7873617c9df14901052872e5b19b6775b2b06f05fa7100e3e3c31e9f4a48be41acae6a451984f8c2c5100d0c1c372da0b4021007d923833585e6a8c1e9be263de024aa478320b002e978283d073dc58253602bf1252517b813e4da907e59e549dad232f3a1a4d395ef6bf975a0e83672c01f9b4615bb610b4752a9c441136a2f7d642140e69314ff6498e3a6bc77688e3f30e0d4ee5710fa61f61f6cf19388040ff91bda50666800c578f785fe4fd69087dfb1d50c44a8303529dee83a144cc668aa0ae5ab401407d94cafae342c013d32216c6b48882f70c5aa9a3713d132da8881ad539d5ff66d079d58c3d6381c1b0695aed9ee22b42350eb7f8e47ec501deff1cc0eda83b0c1e20291367e2a54effbbdb69df585a37d1df8590e32c3a6ce7e42286a940385c0ff0faf6d1e940eae5e53912eb9ee7c3584b44cc60f1930c9da0ee94e8333df7c7d105fa2b14a1f13d4822d69e9fc2b1440a1d2f21a3c01ee476a407de062e35ac139fdc76f682d9b7c265f7d4ea3785cf46d32e7aa3c5f0e20577ca0968a59914dbdbaa90ef29dcf6a82100abe8e7d17cc8799a0d6535a6d38844be2abb852900817bd451d0c2530a11de0e87d07b0ea35546aae4d269484f0d2bbbdbe73876c070a8a6cf7f89817b38876c9a95e054f5b0f4376e9611b7cc3d289ccd4660016c3b1466b567d1ca3393507b1deb075cba4588445942d676d283aefbe3c26bae958c08450f2496160f97b01fddfb8630fb333bc2fdba2e89d9d0c1e2d3f52f51c5f1f07ec550703d696594c6ef8065d8a516a645ea42da8e9d26b18efc41be48e19664cfac553b35ac1d22e8af9c0b37209ce73587b8f430da485c7a00d1a8e83a8a98189c342372cf6ed8c2cd542171e8aca047c606e4a63c4edefdc31105a50b52ce2d696007be80b60d0b87c39fcd57c0db799b52e536ddaeab45e20c7bd8c9c525bff5cb4b2d6699af31e538eac01adbc88420f892e7d24cb25cfbe65512331ec2ebd02f925981ba25a54ef72638c132425fa2aef98568de8c34ce362323b6b7dadbd123a26328f42a67ff3b34005962038c44a11602be0947cf0481c4d0f862a564fcd41fc6786a1c2f46aecd135a034c11539e5d8b5494c166ed4924bae9f025c3776a3709c55f094a2b753d01663dca1fd54384f02dcd2a687de216c828b4240a671e5ad2d154abfead23bd211cdb160d7c5b959b2e5bc549f355a96cc5b01b45c4ca204d0eeccb1b8fd95201b8bc4e0f10bada9e0ac25d6a2331fb31c7dbfd2d391ece50a05e397285d5b2b0d12646bee054c5d7b592181afd64cd5317987dcc110a0bca066f8b689c7b72e8ed9ecdbb56cb208dae4c4d43fe6c50045f13360f41f042de0cab7bc64df9158b8152b11560e2608ac216d9da582a30a31d48ec61e65be169053c8fb72a2f92a4cce0e2cbedae73ef35a9cf732893abbe5dddc6341b09a794e7660a2199a5ad5649e8c80d072972614865fde8c02eba4c2377b21e68161806c17333d41aec9ba4606fc2e2f4932d9a60e58c5265b674f12c1ddee63d3402e313215b370e58cc0044e4be9a1feb805e6f72742642803905accc01b8766116668073263cb82a21355e8908c06a798711d9ffc961b2d08f18c77699ed3363c474fecd9a81999af865745f896bddd8d1b0a2e9404113a84d04759739616118b420e841450496485907ebc9552896fb3a2ae1c9fa1b52b66813f39a37bf82d22e0bdd1561b2502238c7e69a6bb4fc482d021197fbf5a259a0d41b29c1c82b0b4e9e9185b84f65a50081bf436b541454b9de23e5736d6961d1ea008b6e71fd7ad4ed8476a481f038b275a3288eac375cde5026dd9309725a6f342bfc2fba982038a4ff8139ee0580f9ed0c3448a1ebde4b0f0fc2ea94ecd758faa4cef4e25468f1f9560181be89bc79fffb4bdca91242362eeb229e64d806da634909ca842bba29fe2b60e7318c97dcd058c36734dce8687094e060a5cdedb667b38d505521f45498eb7393055901276169b0382dd7e5a2c32a64e9bb6354c96c651466d8d714c22477b8ae057b1eb02f73ecf343acef7668e79638cdbe9afda34820116378c0842a6d378bf8c60c33fa5e13536abc895684ce9ebc1e775d8d41b8157c6261acab0725846d2e6d6c71b301f2a3bf213bf885b358074633a442b51516436a5ed64e4957437548e8f29f7e2e185395b84ab67ed1d93b99e38e6d10a11b99e752b7eb9c76ff799e6cffc121785e7271704b3006a112c15067694c193520295b7e926dd738ad353bc5f3396620b3b868e3024152114ec19d2a6bd99f2f620fb3fb91676ba448a0a48c7d4f45b9967a425e6d54fd571de3e71ac6581cf30e3e01c82c3c769fdaa122aa82477b6bf55ae10187504ebd262124152f1bedf84c4a8de2c9fe3c7c0a25c13bd1707a664f53b1ef8119199d275e8e132a06adb928119960150a245567a69ef11891400fd001a396296ce8c8bcf00ba09e7874dd4337904a99cb74ef2429ecce7120777584c36caf020b594929906f6615189b9b0ea7f1bc1d102870566049faeade8d901a27c1e81309809499b336c9cb91ada67bf9649117db321683af1608fced281c4ac0a39a887d4a426b82a008a374f7cd92a8f8fc9040ccda4eec63cd080f0e0c0f675c741ac8f29deec08fc9a7068296e5683cbad9c8cd48ae62fa0f88806d2a497871bf2d304aa3e8d586bb99cb468b37219868f4cdab06e40669930dfda328c5ba93e652a292be7043746772501d8011c7178a5f91005c57cdd71a20d7163162f768b13ce18a0ca97b5fc8edb7f4d48c9bf8492c3fa9d691b3e9edd24187491ad00b898857927b75f417489523997e3758dd3e329fdd581c851ef7dd4119af25126347184d704f31322d103e5f8c6ad316ff07e10639912417b365110f7d6b0ce6d8c136bc6700adda71893566c4a0c2ca84118b598bc581298f5517ce10f5d5b5cec7980f4c2c0c11d85b991d682e27154960b860ca61cc65d981bbb8a87e8ef98389815931c814cf868e480c239ab566c3a9299de5a6c92f3302862d34451cc20c3fe4748e65e36c26ae116ea582f7e40508d093838e2788486e499028d504d3428f9a2449a4273779e2d4224125411a12934d9feca4c8a09040aa18d13338c281ccd34b9ef7848d4e0a741a46877566ec49858597e9fccb0925afe82778940ef93cbb0304460ffa605fe7289512f5d509c0b6c291407c22689817b27e1bc2d4c61b427e0acd70e4a974445d9d4aad06dd05c414692fc8fad1ca1533e76cea8ff8fa4b84a669377d9db321fee05d310647e484cd4bd754098ff55ed8fcd8215c6ccd0fdcf94bf628a154da105ea710ea9ee2a3f34842df2d236a9ae0ee7eb7ab62382f852a2b765f34e33cb94e7ad00b5ca312abd7e0dedf35ed497f32469949167f22bb5aa1dd1e8ccb3660cb2b48d0d667d49bf309cf66d026b71c1ce1c635c840959a6a682338ba5b230db024637d7b5f74dee6d3f5101fd98caf0c256d5c5623804a0835c149624b5b589600cff67e4d561167ba5e3afb06ed46066501096e63e8d7b16e940f00618c51b2bfe61b566550ece5dd330ea8ee529ab85aa8a69f27cfbf31013c586e0b6dbea680a90003b7939b47f4761d36f67cbe922be9ba5481727ce0d5807b2776972ec71fd123f26db02a29aec1a15ddde7b4db0abb125d5eb8705e91cab02a6312a2c4806802a2324ac5bb693275a015d1862db9b7b623173c6760b34c38f8c5ca725532820710576525ff11a73b71008556082cb7bdccb59844155bb980a821c1e511bd3277de14108780eed5695861352dbd5deb0d45e4c40b445adff00120705d801d901301d88a28697bbb4f82bf158a02de10f0e8e3e9735c6c94df592f4613785eac5becd98b05fa0cf5e5b515b592949db22d7fa5014cf65a7fddc37f910672fe694efe4f5f6f341f9e3c0fa1fa793645ade3cf6c5deb5cedcbcae11470adc4c2363d2302c2eebfa5f7d343056b5a45f26547b93dd9e23682b575b55453f86c957f8efbdb0a187c50c26a4e62516557099805249c2609b662fb68512b3cf831dc212573904a14e238daa06c02a0a43a30136f6a6dcad205b8d40305b0b683127fa23f41aacf30643a763f9cba541990b6661bde4903870260ad6816f3f6211fdc761f26205a7045ce02ee9ef93a2ac0b56f4523fe15f9a41111b86fb0e9156cba4cd33005dea7f379bab0ef2083cdbda90925db4d43dd86db1fc5b4682405762066291a061948b36c2e7b806d8c6024058770999ad0379f2dec52a143b5ff144f1b37fb287943c48f4e8c5a94625ae48355649a803e7cb49536ebe8af5fc3f7725127dd25d5db38ec80d3b3712105d6a926337cd3c625dfdd706d7304f9946a6d815540671e55230a01c39d7ca853f4caa8825393a89876cdbfbccfe63a93f3ecce4a4bec1515b765b7aee8988e8774785cc18df362d9aab9ec596e825e9d269efa8389858f142ed4b01f862422b316f385e5205c47a2a19d77a569fc63d95e40dd870c8fd87758c03f2156776bb0bd7c076080e2ca187375da4f1c5d7986f231b1723d07f8c31561e76495d2d7e0d3276ed0ecaf5f1038e6b4ac4d05031e1ac05b1a0c2889dba70b07b499d1366d5696eb084115d17002839631235ad5536365666dc76061b49462e6724411513da426d706ac2d94c925c7390026f0aa52bbab023d3f854f923754343c44b102fd230847c6c7e33c1cafcb80b61b5303060df49096dd224ec0917c821c8218f3c9689d2dce4d359338e4061c9ad05f09487e145fee02e372d1c8d6441484a8466cba454c60b45693eb36493e14882f0075ec392b40f8fcd2ef7eacb7208d1543dff8c61e806ee04208f596d647df1c92f0d91151eacc2c3c63834934d09b73ea6d2ec9e97a8d696105c71031a4c8e934d399ebebb2576240e673d6c9ed36fbc604bcd2c123162096051a1345b992535d9bf015af4f6085aa662854dd28efcba599ba94459303c2e421de6b93edae2a2ff5bc5bf66b03c4719b3df82d4f6f3ec16a9df894e836953882c8ca2e8949e31ad17584255a1145d4f6f7d68bee4e3c2588022bc070618474128b7e29c6047610b1994d7dabeb713a07d868d047f471862c2c46e4ea7aee32bb41ca8ee72501f42a1ff82862237511671fb2a006deabda92925fba09e25829883a1ba19f2e7a38acbaaac4886da548ccac63f57a15323a454b0d6c15d1a42bc7975033b87236d53e7f404a869a78eb89a4443e176bdaf7c7ce501953043603d8ad17892d609636f889515d5465372041c9977634cdc3d3fde6e013163c05f5401f096a2a80403fa55b6427800329f1d72896445d80b218c191079a76859d2245ac4d4a1e8dfce89162c1590aab01e84ba3ecc961902d7f69e7c68e881958df474a410fc00b86f95b4ef4367ca50d018e9a6740ff19ec09929624c2b0ae195ef94f9fcb258143ca1c533c502d33693a3505e2e84d3369df647e1a871ecf7d61bdbd646e570b03710421a43a1b727bd47da66476b208fc5d494a9f569319f5a56b8817e7d53e16a2635e48c9edcf8dc65f828c2d92bbcc87fc5a2384874e5e12b69c5389b7d503abbbed981321c8b7328593a9cc1f20bc5fb5a2b92f4e365c73f57921a3263a0109851944ef996fc2e2f79e57a3a786f35a7cec2583be413b8931da98970703b2f539597940f0ca016a74c48753d53bae942f37cbf614bb8834eb09ad37c7311f449f3ef331ee6e9eff931a1db26ef98aed026ff4c8011e25a5960f8ebae9b45202ae2c0241222aff11fc04518563943edfa68d76171c648450c313d0542daec89daaad0ba62d3615dec018259d46bc5aca668288577ae4aa0ef9944f962fd04bb1d7624e0a85434937fa16526d2b8ccf4bac20425a33cec72dcc6278c99adab1682af7cb0e41a24d905dbff7eb01b32b986f932aee7c323da02115893fc758bdca7fa5203f7a376c4840b8369bdd2df9c220cc541f146629ad23025cfa26b984e330cd798295fe90744c06710498a3ef2ef3265fed393cce2b7615d050309feda65ec3a35a1250dcc7c4ad210695b2d4360047abd7140a5a0a7dd812b196a1bd6775152c45029e2ec4a60a3960b46439330f0f0f0f0f0f0f0fafa18d90da483b8424c8946412af76dceaa5197557a694a44c2909ce4c7cd91dbc8377206b6467c4a7934509620a2f0bae0a5d7e5612c6274e5153dbf75f7c99ac270eba2246549377299b979d38485121457b98fa87cc685891030c4e9c949c58150de7a6e3927480b189e395a9a559887532e66634ec03c806189a38ca8a8d980d977d3fb3a0616ba5071899385f040d3959ae4745048f031347ff0f95d4f9d550f382b9a0e15dbc1e1897388ce44a2d6ab63203862556ef5049c9468c8d2d6c201a364200a31296685132cf48b26994408b74564a066050e2145537cba5b1c352bc5cdb9916729cbe861a0d05018c491cf3d594f0eb1c592ff130004312a7494253df09bf60012312c7ebb3935a71439e3941e224d17dd734a8304a591fe8c2c6164b01188f38977ab9141bcd1a6a8e38570c32cfebaebb0bc068c4294951c24ca420b62dd6502bc133e29c737bc9da33b9db4c329108c058c4b1532e62aebad450db82b9d002bde315301471ba8d1199c9235c84bf869a3d0046224ee611d6efb4ad2815d650a311827f2faa0276efe7001888389d8eab4d51b5a4ff431ce732e5b4a410ca5490214e3232d585388dc65512d9bc2caef850020c429cc7fbd5a25ff6a6880ce26c4a95ce74997f477e8238e91eb30c9d6c6a9436e363c69a0046208e7bb2499a0a237e210910a7f0962b7cbdf504187f386a285331c1477e38e6899d2482b4eab7511f7a4d21649c58623e9c7e938ca92184d290e73d1c946ab694b35b627bd6c371d56f73fb8dd5ee9c8753ae1e4bf99f9d96331e4e4a4c7adde8fb1d0e26cf23e6fbbd9453b5c321e5dfdf87cc3721cf3a9c3425c85a1e8d913b4287b3e4891584a65c26229cc3514d5facd80be570c863b2f15a412be671389d929b3c83d01be4342c3e667c34e0238b2b262043468e40868c1cc1192dc080c329cfc45506cdb5f90d0799eb340b6de3a2bae1d89a215ab8943c93eada705229236224c9d870ca9d3196898fb469b6351cc534c5966c25415fa98653e65049684a0d49229386a34fbe0849de050dc78d9727d4522b5406912f609ce1a4a2654d5a3c821e13491c30cc70cc62faf462927b3ac31a38b8011f33ca68d88d77fe1aa9850518653858fe51f54ada94a9b5e0d8c20b2eb4e00206198ee329a72a5c87f69071f00df602c6180e7f62aaa1f67f23070db32386030081802186939688997b5bf14f4f6138650491a476392f520e86f39799a5ca5c3891375fc0f7626cbc709c9c6717f53798b0b50b8768f147438dc98593e8bbee8bb316df2d5b387ce5da57bf65fc9668e1e027f24bdbc6d6f62c9cf5ecc664ee35d98e20049b87808185638989b9d12ec913697485c386b9d18d642148535be16426c2a2ebec894bb80a07512526869b9d974d8563c917b1ab396137de291ccc23a920f39f94e0a714ceb3a243f66d46cd3289c2a9ed2bf67b8974aa7450387f5cf68d24d913ce9a4e5c879297c1f3aaa1368210d048fcc43000817201c8030c279c456ebab05d89fa736ac2416c92a0fde2c484a3c8b352a64e5d25f92fe1d4f9a54509afe81764251caa5dea92fa2609c749238259cea96d6f9170d098c9a13d312feae50887b8d6657e6aee7b538c70b62cdd8a672292e94a114ed935a5b89908a7fc9f5fd2f327e84a86703689e633daae57260ae17c29e5bf8a77eea7bd201cf2cf7dcfc87658de8070da5cb67719edc7de82f18363a5d04ce7235f77be0fce1b438ae297ed1e9cb252388d5ff72563cc8363b01a11379ba129da1d9c33e84a9baf411d1c57a4e60aab961c1c44be942ca892903d3d1c9ccdae94e685b234767900c60dce93fbf6349e12fb7fb2c1393628bb58a6279b08d5e02c26262692086d23453438e8502327cd058b1e9b191c4c48bc50fbb1517d95c12957b8f8ab92a6e1a23138a4175d1e322c3038e9c875994bd246d2ef05e753718236cffc1d4a5643ed3fe04fa39c0d182e384c90fdbba067bd645a708a184a4bac0a0c169c5636baa9b1f82acedb13fdadc4d37e47aa38056da6749b48d779e1541c2fcaa5f83b5fbb29898a7305f5216da2ef87aa9ce2a0fd4385983dc37655a6385b88ef97e2945c5e677c7d529c3e6f444831eae58d3e8a4310daa4968590b07d8ae2d473a272855852362ea138697c6658d0cf9431041407d9c917e26ec9698a9f38b6ada776c5ca1307d917f355c62a624c278e1e692b65ca262c9d8913e79131987c7b869f7e13c7b653ed12322f4df29a3828dbcc99bffefcf24c9c228e06adb334264e42b7a4a8fbf3258eeaa384c7697c4d3f5be218a2a9c6fa7d2b71d211bc4fc64a54b19712c7cc3e4bd72c67e9ce491c36485b0b0f91b4dc298953f76cdbeae4d2783312c7fe7feb519599549b90386493d72c299adc51e6238c71bdd61435c4116799a8a6f9da24a450234e715b6335dc6710f731e2acf5f2932af6a6642ee27c2a6b9226466b508b220e96367c75c66dec0f7441e33fe0e7b7f02eb80165481040224e6ad3b5e948a2174f0120e278eded1fe726b346c386af0704708883be3bb56fe32e7bb12df873e0a011822dbee862e6de6d744104608893c9092e12d444c9badae01268910c737c1181126891300034104021ce3722a620be4d1c1000218ea3b2355f3e6d947635d4f60b0d086010071d93d8a32c28791909e26476596fd35f6b6b62122080401cde4f6b4e9a98dd1702c431bd6bda7f478c1163fe70086ae36662b44831b37ec04d8f188d23210610401fcedfba26735c491dcbf3e1581d2ac96fd3b29efd1ecebea1a331d4480f47f58cab3659ed5d64f270d09c20ee93eb4d36888773ea46481627b488ebee703e4bc9648a9031400076386cd6e01f62d6e170fe9237f8a620b582e8702aad48e21374d94b7a0ea73c3a8345d68c31822c87d30615ae614a5ad4d7c4e17c21bd7e88d312f15b381cc4e4db7d6e1a794af28653b6a0f2a6fef90b3a74c329fba91877662405ef04d08663521f191776574c576c38dfa92ced21396428ade1985a1a5f456d2bef6a38c89455d1083a4cc8d370f22a7161d2e44d66a3e1b8c9f54cdbae2ed26738498e244c5614bda349663845331d7df9082aa4a90c272547f95f881e190ee2e96e1674dfe998c67032b913af6c92761b93188e3fc2e7c26e27ac98c270dc9798134524cded12180ec93c46fe6a9aec2b7de190cc36c52a8b1bcb7be198f6ce72a6b01db1efc2e9f287d6ddce85635a7ebfdcb61223dfc231f4e289bdaf2469d7c2b1769209d32ec15ccfc2512f95509bf6f6478485f388307243d63d5bbec2210565ca54257527e3b7c251ec5764d4f4ab704a3e9752cc57316b792a9c54843b9942c5464a7e0ac77fd1155dfd99d92485631212b4a4a047e1745b32560aebb17443e16c65bf296d2bcbc44f380611997d6eeabb66271c62ca96922aa937e128baefdfe3cf2d93ce84f3a5acaec154be84a36625b9a9527a4d952be1dc16a92d6782c8dc51128e495d1e19564aff8810120e4a49772bd1267e54d0114ef14f9b983416b48dc808e717597f76a992e91015e1a0f233fc6c564f9321221cc44faeaed62071ff1ec2b1d449185b11429fbc8570cc1511bd2d97874a76100e49e48c280d2daa5a03e198fe62ca67f95664fe07a7b2115142aeb5b4b00f0e31f65ac85992ced41e9c3de304ff92a4e62ccc83d35eccaf31e8f65215dec12924aa5a74938d90631de0e69dd9926c9c8353fede4ad413cfbc180767d3d02e226688088b6f701e716a84d8c7feff3638c98914fb746d4a3daac1416bfe081a432fa30805ceee88ace15c69a7bb2aab6380871a4e32c8903645a9f8999d86b356ecfd17ab4965ab071a0e9752241567458ee6ca190edf9b3526192fd89c40e161867368d5dc9b6cec3bcec16e6e20161ca011804c7894e170192e24b75a501f298107190e2a628839c278394af039bab031a390041e6338693c33a12ecc89597e080f319c427875c9f50ecd75ea834718cefbe11b638f96a825bb8307188e32774248485a499cec0ba7d899921eed227c4798070f2f9c7c6edf4f6daa281a77e12442bebd72176ddbe171e1a816a772b8445d93bb1b3cb6709e64316752764cc8a40f786881517726e45610ad520db5c32ff6230b067ca08b0ac890f1376c54a08e6bcce01a3364c8e01a886b201ade05dff0c8c2f1c2dba46c3fd6d02e6cd0489d8207168ebb9da9e773a4068f2b1ccfa2d987fd4912daf9dfe01a38f23dac70de517a825b280b7de11a6a9fc3c60868e0e01a6bc3a30a278b166a55256d64996aa871f1c50d1b5f88208f70e1410563c50d172cc409d6dfd0c20b4614784ce194f13766c8d3dbb2be865a073ca470f6f6fc92383ab9281c53c85d5b4f99fc1a34080f281c74ab558af9b58c372b203c9e70d26ba27d4a69dfd5fcece0e184b4a67cd59a1b6ec2a9feb4474e5ac634ca82060f261c7deb92cde45259c2d1e6eeeee2a8f48dbf124e69f9336ed0162fc4cb47c0cae0918473d8eba83799e812c25cf04042d9165696d99210c2820334bef038c2d1a22865ea2f55fcd53eb2608006687818e1e4ae775a64299965b72458708046043c8a70cca6e9de5e7d4484b986da0d1b39b4e872430239b448800c1939b4682c3840030b0f229ccc4559fb87b2865a0e2d1a6d011e43386484ab79d6c7f6a4861a8eefc2068d3209202db6b0400e2d1260c71e42d0fc4a7a88dd90e5e0f7e26fa404cc8f2087161af008c2c9455c0669ba94ae940081cdb8a523c2e307e7b858a6444c90114d7d70ea4865631543479d55a885f0e8c1317885cdb4298dd6bfca070f1e1c458548298968e789a03d78ece05c297aef621a5563af76e1a18363ca095d1792da13a99483535808b69947c490f7ff076e7ce0c647a040c00307a7f417b19bedf2d285183078dce058215cf4124b93c93362f0b0c121977a1ba5e25a265fbce05183939d67d22ef1afb839390f1a9cf2e7f4569c7c661bafa1863ef098c149b2564ada6acad662060e1e323824b1303b3289a7ab9a85b13678c4e0b8a3a44aaafc1be242dee00183f3da48ab7bff8ce0fe0b8ec9c243b3286d5d705cd3792d21befb7e6cf068c149988aa8070b8e96dfa352f3cc551ce75b540a4267658c93183a5471d8152192253fa93a261c07828e549c92baaca3dd465c4eab861a1769853b5071da3b15b4ac925788f31447dd202208ad2979a638681df9fa23161bfe183a4a71b64a67d71aee7e7559411b1da438785aadb9a9fa31e3c3d9c61626e0097c6471c5c7651c3a46714ac234e809a5f7249a5c8310d44087284edf554aa43d150ffb1ad0118a93d01052eb689712b382e220428a9133053159177fe298a4d68e4c2f71df27c6130793d1441aa5d23b434727cea3eba5cc57333e6d4e1c52457bbfd3e9173a36715c9fa0a26eae53e7996a02e1ae72298292944c9ce2c98adea544fec919828973f986f09a2e9e5c142f71ccb420b6b4feac65d01227a9418624966e256b0e2b71f6b1db1853282971f0bc987bcc3456d224d4b07c15492411644c1267d90d32450a264afcde489c246f87b975cdc8e822244eb1542825d72765b25f858e471c27c860fb95c29a94dc5b204717cfc55aa1c31127f5932d6b9730a9d0d18843981817b12fe95ff97114469c4b9518755731bf4dbd88f38a30314d3572225f6ca42e1c708a3889d1df52e9eddfb031a32311e7f7b1a0273376f13d441c421e6fcbcc7e9f3b15163a0e71feaa9535b9ab4a491be2984d988ab11e5a5a4b4ee828c4d144cce8a34f2f745236d2123a0871fe92c9f466bcc811d3a60b1d8338ee05d9aa624a759cd008e2fc69bad56f696b260ec47944ddb2bc895ee800c47936c5e7c858b5ec2b0a1d7f38cee54cea299b846e976fe428c1f998f191c3868d0afc1621b8f11148fc57dce022024af4d0e18793bb6f0a61a1324a56169021e306175ca009d27f77f4e1a077c44aca52a3454c7c38e5eaaa3c2aaadb947c0fe73c151725a63e514d8ee074e8e1a454acda18d5b4e593c9c3c957349366381b35193c9c2cc55b49bee81d0ea35637779ad468c60e47135a2d454cc973dfacc3b1728890820a173a1cacd298ba1435ef2599c371f625eba6b92829dadfb06159e890c349347acfeda91a11b538681b4995b5e90a0ee7bef7caa332416732bde11813c3669dd8a6abbc1b4e9b2f840e9544ca8a95c5151f34acb4e1a0445c1c13ba345a92b3e1bca7e74d677e0da7645a1b624a133fb71a8ea3446398c592b0164ac341c6c9a4d46caafc7ba3e1a8b5f9efdc64af8658061a0db3eb38c3215fa5d6241ab5ebc21d66385fcbc4149694f41172194e69c25ebf566234cc28a2830c47d98ed39ab7ddba3763386e88314ad26ec4702cefed48aa52674a360c873d8f6093cf7f33ad6038a972bf0caad42f1c278bcc90cf37355ad40be750936d215e94a851bbf0c5bbe9cdff92960d7470e1683ba6f59362082d972d9c3e4bac8a522a36c7440ba7140b136df375cf255938a94c1b84668d60e1209216e1e67e622c835738d68f0ccf542366295ae1ac312bdbac99f8e6b00aadf59ba4af8bab630dfdc8e20a2f70987650e1a041c6c6929762a59ec24934259ac8d923437b5238bfb589c94ba579f451385e6fcf5a5c9c95170a07bfb093dd5f31a0e30995bc0ca7a76571e38f191f3264e0c861630b1c5b870e279cb4c94b9bb4f5f2437c3a9a70b4131b359923d4cd4c388750692bae4974886509073fa54dac970a426e5009a7f0aa15dde49ea64ec2a926799bb0b5cc52de133a9070b40a2a4919113ec2d144662f17e1d6b1970930a1c308c730951d1a4246091d4538bfc66d536d9d6ff2255ce82082a2eff296502a47a476e818c241d89f9a51cb5359f7113a84702a51d33241565d7077c6474de063c64749e063c64761f131e3a322f031e3a3aef898f15110f898f1510ff898c0151f6ee808c2f154239dc58d191d403897a891652b412925b316f8985103073760cf0be6020d161ca0e1808e1f9c2fea294d2762941dbf865ae6a1c307e70849a208a01102c4bdc5169c6430eae8c151c279af5c467bdf041f021a38de6d74a1f7850464c8a881831b500307d7b8e28ad7e2461657c89071e365c868d74774f0007926b3e7b58c080e3a7670de903535368514db3f2db8d0e28a8f191f58d498f1376ce4b040123a74700c37a633ae26639e59430d87163264e0c0f137f2068d2d3870a4a02307075da5a9777295265836860e1c1c766c7d53c9480d35bb0b74dce0f81b36c38990a2e9d372a0c30687d45f15825c10bae1770570f1b1800a7cd8a0a306a7ab79b11629136dff1a6a67775774d0e014e76cd2bac6cd7eda7761c3ee011d33386b0cf18da7b5c64cc6043772acda62c1011a05e890c1e15bde42bc2077ee26171f5930e00301bec516cc850564c8409342470c4e4ac577f3957c04db0fa1d00183a35c9ee02ad9572ea88968e878c12158058d5177c1d0e18293340b218feecab030de163a5a707a11f194fe45cb2aedc70c1ad6c182a39c1c25f267f22f1f59306089e961c1011a00f8028c551c54e90d1af77fa523a98002ae00431567977c714b49f8df2ca9a15664c830978af3bb66d9d3a8da692d0dd6e3dfc507b4b0c01460a0e2706f2959b890358ba41463028c539c4ae8d3b9fc9772c85843ad468ed7c483618a8358962057a11cc113d6820b1b5d98600b1b13f85fc01e0e122c004629ce6f695a16b63552fc3880418a83dee58929a55c21867514a7b0cc25e36ce4964b860c18a238869cd877abc965e32b0618a1f0b7bb5e94bd4d8cd601800f304071f64ce51ae96e6d9ee826fc34e58815ceada5ee728cc7d90a062baa7098a0823e21226aa34e54384c904164a63f8563502337559221242197c2b966df4f5585f44a3272c18a289c548c94444b432a7d3e140eff2f1b54fa3671a57cc259c447c8b1d558fba1134efa679b2e29d56dc18a261c2f4553d2164bc4fa13138e998297ccb6ef124ed6ebebd737a3c4460907514b5d8ba6e2f7c30482154938f9a83497dda02a79e31c36b2f898f1b1c5169c45de07bad022878d11d0e080154838e64852d226c65757c88d1c6507818f191f96052b8e80bc4d61923c5beb3e19a19558df6649ab4a3615218db027aac1b4f29a88f0a9c81cfffb10b014639824b5617121741669e28f8290c30a20a0b343c6483d7957463f682c93d0923399423e20f9c93c57cb92e11e5821744e489c7097632b7890c64ca916e31d98214ce5e7629f90191d9865f36a5836d3a4cdc197ebfd4bce5f650907e88a2e9b221e129237289245d1fcddf669411b64ca6a2c5b9cdca15403448a4c7154478364d613aace5f53b5e70547206d8bfec28697e9c08a191c83e6bf785142a77721e01ce4bff898f1f131c30437fe0b0a7cccf8f898f1618287c0c78c8f1b6feb0573813cb04206479f24ab59b1ac54750678c15ca0e981153138e5dba6a99353e9fa0483b3241133e69674d22afc8253d4d37b199171c129939a4ada33a4056795e09af6da324c6756b0e05c95dafa2fb6600c5c0362ace2e0162b857c21aa388fe6f0dd48c137bc948a83e5d0dd8b7f1911a2a8387758f6b828d974c4f114e7bcdc90bf2bdece2586298eb6224348a737fe09efbd6c01314a71144d1935645d4c95f518a438583c4d5f27770d352f6cdc701a26b891634d70230b1932100e2db84029c418c529c689ea1bdf92ee21238a9354c97fdba74ef67f1fc408c5f96408bde312725c3441714a273625c8abb00a8b7ee2f026aec637a98c295c3c71d4786eebea75e2a445488b91edf5ca7e4e1cb45a8590f5bc4b6acc12626ce2f8397ace267c5cb818690009313471baff1131057595a26a35d4d6beb92d1347cd9c9adae12237885ae0b031014c9ca4a518df228d984a290e70c0071e0b193270c890610224e307312e71941417c9eab45eb610201b5b74d1420c4b9c5e53f6896c4159e8bc1287a4f26bf4ff579a184484189438bc858a2761ec7655d7102fcdee122f44964dd9db5da4b983189238ea8c0ec96f298798192312c749729bda967d279864c880c4c125e88a215974495a7cc429dcf574369bda6ff46f10bb2286238efa36226ca765dc383f2046234efb12b4bad268488d33e29054d7cf4e6e10255e193264c8b8e26306161ca0b182188b38c574ded9e75a3971451c459a49bf6497428e2811c92c1b53d64dea45c459f7729b88f425b2ca87385784bbb4d61ae2907db646e8370b71cc663f4ae556aab610421ca36b8fcefdcd6ca70de220ff82b03d75d9622909e26892d62456967511fa409c47ad2ccbdaa9f4a705c449ac2c25e50cdbadf20f0719b7fb46e8ceac4cf1c361a4e9510fb16261efc34154a40b3973c1e7267c3879a89d5851db12c37b38c4f63719412ef86ff470aa2c2a365c7526c42c0f07192c5f52722f3c1c4ec8d55032bc7e43bec3f9fd5cacc3e254cc163b9ca49d963e13ab21ed8828885187f3c92442a4905b0e2dbaf8020327884187a35a4811ba4a755fc498c3295b9814ad2968d3a395833331e28fc9ac89c36135f4c550a752de6882c3f9d2649c1426415ca76f38e8dc2842e978982c951b8e6159e5f52ae7662578ef420b19327060c1011a3662b481547fb59f25dbb3e13a39d714ee23e2a8d780ce1b512fd5809b927759624b8ca14b037ba2aebb64558c1442c339e389d8956d1a12c2831867386fd2faf6b33166388d58b2b44c7941db329cbd7a4ef7b48b418693c509b3fb4ceb91ff319c326ccae7edc9d3530c07292a3a9bc454743731c270c91d19fffd82c0f0755fd0a2440e7de1705daa4e466d6d1979e12483c964526643f75d3858760996b6612e9c4b56d0a095925851c9b185c36fbc9c1d3967656d2d1c34c657659066e1243be4868493c1c2219b4c7ff15ada4368ae701c931445bb4a2b9c53c2240daf334d2756e1e09e9b23a60952e11ceadb8450425febbd291c2d531022c97092c2612e5bcc33be21fdf63868c890f1ae5138255169a6bde1567d2c3840438b1850e075279ec60c91715f10f013987fddd029e9420b2e9cb06ea4788e269872ebad64aebc5b0d35e7af71966230a136537ea991d2ae1a6aec058e8db10445b25cd84dfab4a86aa8992087175c7c89c04716577c28002f957012b5385ddb2a42732909c790c91d235fada1a697430b2eb4d882468d1c5ebc27128e1ae6e4040bd1f6bb9d11e3088cca1075ad952086114e49aaa51da1496613a5229c4bfbb2e6d4d0203a12e194f46fec68fd8fb55c16c5630ce15426832ef5674ae64912c2796c4536cea659ca3d46104e624c9dde70eb225312100eb925a56d4a963295fe07071513e23f4146cb57f9e0f8223792a94bdb0aeac129a80b353b99761f2f0f4e4205953dc1de812a2ac4a09405d9a0cc1ec4d0c121aa08a11b536e9dd4e7e0a0369a5f62353838c88f535142ba32d10d4e13641257f56dbfabcb0c62d8e098c2ed051339474fd663d4e03896d2abef5757d2eaff16b0183438869aa03317f2dd583e83f37f7a8599d930aa443238f7c4519df2a3189c6265b598a59c21d5078363bafd8c4187fc82b3a49c7f12f33c56171c7305bd0dca92dbbf18a305879467d258b0a83b293158704cd617f4428fab385f5a50a32396103231aa38994bb4794915e2f24ec549e84e102b7751711425ba6d3dd7531c92eabdad8b144648d21407152f987b04ddfa3296e2d421329c503d8d8da22f48710ed3e2f59142f56946719e1421a5944b76a31d8ae2d8be3e7b21188a83525aedcba4a4a83683e22cf2a33a8229adf43e7152a546a45bb798ac7bc0c313c7922b32da27892d912443864727ce73c9de4e2d7325536ec1818386a1771b33b6e0b080c9bfa1587080c6013c38711217597d3345ddb0f526ce21642a1322ef85cc4e13e70c97a99d1f7ea5f732038f4c9c73b643fb2893e4b261e274327d9a9a578b9fb14b1c8498d3741e9aa747b3c4c1629e8d10a3335656e2e027bfb3976a76bb428943ae8ae152cda5332771debcbc41a9fcd520a287240eeb23aaffe2898a9d08de02eb118993122aab48d09b279ebc0c078e4708015e70040c24ce27216e3293652535a8863ee22442a83d11edb327a478510f479c32c4525518690d35921e8d382459618410f71edee6178c38c637136abccee543a7c1c5223a194a735393dfa988c365f4892198897b7ef87ec523111e88f03844d225ba991296459521630b8e36c4c9beb54d89101f29a385385e85cc5952b110e24888639824bcfc358338243913122fe404e111886390674282d99aec9e64f131e3e3021f13b8e2c3031007a1920c1593429031d713b8e2c3e30f7bdd5c4d1c597aaf871f0c42344e6ee632a5217d386528b770fa848548c0830f8d5051cde343c5bcd2630fb5c5a66fd7b518f5f0f7c99341847b9ba0ba3ca86615453777c6743df0708773a6747131da7ec898d750b304dc35c0c30e87eb133da24397a60d9a79d4e1945962da925bdf6d7e036c6421434609be068d0f2f5f7cec171f5dbe3014f0a0c37934a9d89325c489f8e7707851a144c4fcad92457238ce56f28b5113a75e138783ba4ade251a389c9418cb15f632c92df30d6713f23fd7117465d60d4791a15e6445ecbfd886f3a548bb0c3961ae2b6c388f684cba1d0a402040160e415e99a639b99a82b0700cd771d715bac2b9f572c83c42d2c58d158e26729e17db646ab50aa7b0ed12a236d829930a27911dba3189f3b6e44de1a0c4f7ede6eea4706acfb01941478418bb289c35b3e35fddf3f20405c3bd65fab553aa80004f38069df6db97bb36424e385d50beaaf15fc1454d385f703f3713a6d2cc4c3858252fbfd494216596706e3b0b2a5b259c82da7e8a3cbbcc3409a7eaac4d966e4b7d24a82641e9d095239cf2f547a6a0b32d4233c231ae9588cc6317f4b2221834668f20e26ac95c0d9df171e80e4873040188702e65f2bc4f96943d0de1341733a6a4bd422a5f08af768c5b8a93fa17c681800facddc8e105003e4180201c5c82d0d29c03e1242385c6ae491235f483936aff9514969b2eea8383a59862a788580f0e26d42f2d24a931e5a9061008c083d3e40b937d839b66f67770d24ca52bf2d4c129fae4d199effcd4f939385e586568e91399e3e3e05c314c6676c4a99e6e7032e996c93d34e9736d708829a5d998b306c7e0ef63c2d2ca29d16970de90296d082f99c171aef24de58564700ce2cc542add8ce4770c4e33c15e4d3dd4a86cc3e014847cdea697186212bfe019cb681155171cd3c9184959d80a13710b4e21a99ee50b255ae44b00169c3cf4bfa664372f395dc551eb6c738b4aad13a48af328a5952b4890396fa6e26076797276acc7c9a0e2ac3549659fe40b1a2da738f8a9d5202aa864fa35c531e4b90ddfaf77df95e2f4e223c9b25f525e8414c714b3289594b8b875ba519c2f8e4db83ca7c25213c531838f8c1cdf97b22514279710e3a8b2d92fab7c3000501c53fcb9ddbad9a429f989c3cc89c8eabfe0f0c4412911da3aecc47964636269881387499b33ab6bd2268e3116dd6c8297c865d2c43944367d260ed252c8a1b4d4d3d7c7c4295bf5fe7a84a462f99738467ad5baf491f42d6f89e397cbfad76f48d2f295388574ddf4912a74da4e89d36a6668ff2ac99bf4499c75476e5b3049e29c67f2b52f7d479e237112ffaebefc69c15b481ca45e67987871b2d4479c524cbe7f964bb78638e268da726ea5a1469cece47a8c568811e74b2e2792d266a46911871141fc3745844c157152639ba75e464f851271b4145126376bfbdf883804a16d95bece62ca218e1e4a29b56d9762c418e264329e5ac9de18922bc4795344e267d68468b3f2b7e48df020ce2229bb4bd68d200e26834fdeefd21c6913889334bbdcca7db27b630071526a7f6232b4655ecd1f4e2b1629ac23dccec4f8e19c973ee22d8dcadf993e1caf47c9598d193e1c920a773a520ced73dac3e9e2cba58c889239e9e17c152cee324c65caf370d26ed75a4153cc20e3e13c399455d2a941c8f70e87fc954296e9d72ceedae1a4a96eb4869716ab6c1d0e5f363f2b527fe2b77438c87c5149c8a614e4b673384d5ab5bc5e4185d5e57092225267d8e3704a09a32496b0701b048783c5b49c60296648e1371ce4a89ecaa152248dbae17cb3d1e2ccd4361c368892bdc8291b4eb729fca436f96791359c4289ac985d8494b654c3419205e16e266641290dc7389564aa90454fdad170d0204744b6cb1bfe198e1a93069933c80ca748226f440d97321ced5bd5c42493a021850ca79b5197936d545aaa8ce12443aa09975511c3a96e75b229f195d387e1b0de953ed297901243c07010137db38e26d538c9170e9b4d9fca9ab4a0712f1c564f34a4959c97f22e9cb27c5e5e621c59e2c2a944e5d37095a2e9164e5669639f58c654222d1c4cb575690b65e120367be44dcd9a62838573678998d0e9150e7bfa2c8ce8c90ac7b4aba65c92a5881856e16476a5e57ba7c2b94e538a20eb6ac6bc291c2f69dfa0662eea962785d38b56ac13b9454cc845e11893aae8fed17faf43e1d4611631abeb89193de1f01abc9234d79c70526f1617f97337566bc221c811f55a1582e88931e1781a6b6aa4664b38dacde8987c9b21f94a3879cac9b4add134879270d2376d5947e9503946c2a9ae45ee7fe9bbdaea08a74c9b67dd2229a9a76484d3a9dd0ab2952fc2513769d8b86fb1c974221cc2c60c2afbe843388f7b5e9cc916a42809e19482124994d21873ce0ec22989346a379899be080807eb114189b7fc83c3a5a0525710611f9cd4de98fbc6104facdb8343da1d4d69920c994cc283e3fe8b1255896695d31d9c2fbb05e556afdd1ad1c149b3e9db789a8c859883735eec1273a15e41e97070109ff9332a96f7896f70b25ac91b577923656483836a3999746e08ea25050803a8c131ca84582ddaf49f667a30001a9caa2da56ce608a536333805e9116287a4cddc1a13062083535a4b2204a59268cd1f8393081f95545c8d1b71048383c85b6d4abd864818c00b0e2944e508a7368d3ea501b8e018d297efc5ac2e3ffa01b4e0245a46680b25739ff807c08283accad817b2056deeafe260dd9f5695aee5d657c5612d8638499e9e8a734bf6cd27c442ec1242c5d994882849524abc1d9de2a472e694cda4442e1999e2a02fc6596f9858dda0521c75efce4b868b902722c5694c3cc382d6a3389ff6bfa64ebafb0d8be258bb69577ef396f04c284e722932ed7f5d88a605c5c17bd29a94249276de4f9c3647ac58c5522966eb89a35766171311edc4a94aebee5bb48e9c1327ad4a9be426b334a74d9c6293aa8ca01ac5d4c4f9ea4e85b03a13e79ea44a88de0d268eb1c9b37fc3bcc4c9747556e957ca362a9638843121d66a1b73a4a512a7d8582584aef85fb050e2742a448c91567754582671fe535632c8587e32552471d80c32a61c3e89c471efcae2ce4e927b219038a890252fb2f65b04e1234e99f735ea255a36253ae274f325e35509f11bb11107f5d297cf0e19719898912ac435d7b42ee2b4692e481d2b8dd9a288c3e6492a89dd505edd25e26c1da9cbc3bd235881885312baed7f54e910c7cc193f21a5185eb5210ea3db5204b529c4b9f2f859725115527b429c5236df19d56c7ab23d8884faae6c29fe268873462da5ad0cc449fa5fec05b990646e0171ba517f3f937e3df2fdc3796382fc16137b2ac90fa72e8b5f2797a52a53fa708c90d344d67d496b1a1f4e31294c8934f98bfd1e4e32da9908229e157a30f8846427538a4fbaf3d05c690916c6c594783095bcd1bd133695ee70d438579bbcb42aea6f07d484cc2eab212eaac3e14fd296ccc576a90c1dcc942b2e748e733849ebbb9231c44e14570e9ed8eb3d91b1445ec88a381c937785d0a52386a42afb2d9a6f7c0e071831580187c377b756924fd3ccf00d27b1759af46a379cdde6a46ff08c3b596bc3f9f26a99904165c34149ee95604ab3dd660da7245d8266d1b170991a4ea1213c84b62babd2a4e19032882bddb04f8d2d1a8e7ea78450e7259489cf705095d23fb2ddd8298f0a5698e1147a2d7268e6489d4ac18a321c279fde88c41039494c8683256951824b8a79cf8ce1dcdf33326917b14c59311c47f9a8287b1b5632250ce7de8f1d93ba11f3236038c88b3b721e4ad5462e0a567ce1142cb8c698345e38a6ccb10c415e10aa7117ce7726df72da890bc70b15dfcf50a3216fe1a441997a8bae9c31532d1c25baa81865c45cc4250b674b9aea279c25cbea62e1b47d4246d35a5de1048a7da8c4ed0503c248241487030251201406a071a600631408001828248d0663f1681c46c21f1400035532263a322c161a1c12121410108a03c14010100c8bc26040281408050220a158708c23d1f007847dba4834dd96206082be846a04161d2c8fef3dbd4d033507082790a38c201019fef948e867f8499c3f26e558eea95539d24fc7d646c27e09d412983661790432923c2dc12a024e850d2673165f2884998441ca06190047fd3e798a239f72f9f7e44734056563b43db2cd2ca1d65799e832ee56eefb4901ece6af072484753162ea4e3147c2ef08c246980ff51b5d6d9d6c4590822ce9d9192dfd596f70c2c4b8de089751e7d76d1725858f9e53bd4a87e8e83c74d7b637f35fdc01368c6eca77aa4907de187491437042e909ff36c2e6c98d989d7ed5506ff6dddbefb6ab3902f11a283cea273011187940a3e012085e70f6910592088817810c4a5ded280e6c817959e158a0594045c08081e2d5fbf683dd2027201d9060004a90c5c03e41e4018405e009e002670164030725c84c4980ebe1caf780c0d73f9d0eaa78506320764f6b1217609220379f890db420d715a61ea08c011640b93d0d29854d2f80820016007a80770013007d1ec00e3b39b9611bf8310061a06080e005305221f98228035619ccc5686cc0d202bc0a2a0d1c0b102af867203903984e208ddd2100e6539e178b4080c0b0df682e178017400168073801c8af006a8e1d7676e200eb03b6075a0d9034c027400370012005f82920290357b6bc3794e1027a03ec0720cf0086dbfa08c7151018b08379770e40168012107fe0b940aa0b3005b2cb573503c2081fd88f011400f6660050adc690843920bf401d00da00b203a008ac1240293809032d9153420536000a0318e39cac6f36065a3c826ada004d1b10188052407501e000f9007003d00d204c40d8dd59ea15809f00af47c015d5fd2f8b06681db032908a00a69c00a4af118f25373790a37818cdc7a4db03f320f97107c2e22349434eb044873acc1fef47da7dddcb83e041711e84920360e1ecb1ec81301fa7aa41d83069b01181deead7cc0fef3cd6e7d0092f6090d3f27e375b01cb2c4ce6c5486bdb8d91757d1f98253014b6360135714da0521cc08adec6a3b6d9a0c0a480a758a310a4687314bd918ebfac90a24f214d814c318cc2cc2bfe94be27535a14fa32ae59583686081e60a56ef64284fe4b3e7114bd6124f36623052385491180628722bb293c4ed94c9d9bc241814e114241ab28fe24190b9dc28ae40b458b83a6108dd7ccdfd428fac206bcf81b714f9f7c013914316d133d243feb214d4249089089081c060c4b09904f68e5d0089ab9fab945254087809862ad68e06f84ea8b5e75db2aed8310609b36c965b5a3b8beaeafa9e46024863d7bd88517329ff0534a80ae81a8616900e3fcc10990ac16e42003167837d3b2b21f2c4f42d9b5510477682942e3d5b0e5068d0973d70b38bb82c0924408fffae4c0c5b064ef78174bf2013a9528783fed9b110033d7193e6d1b6584eb72f7892b7111f551c1155aebd8c478c0b7d3bfbca8bb6e7e05f38a2f8cb1178ead0878891d7911f212a11db3d2c433270e6a976b2f5e615e30818ff4acc2646a3f0d7f9b16e75078502a2857140a5058e2f5e306e162ceb5d3d9a491e58c10fc8b2196b607601d8fe4a5d1eeaa113a1bce2501a49fc43ab0900a02405c708c76dc9e5e0a01aff92e56f46224899fb5408942609a9fae403708428311b6efe48b31c573c6e3e41e1b1c474f19774b18bfe2d4a462106a0e0d7c20c4d9cfa1fd5327d52bf1a52459253c71ec75db710cd31103884cb7080b13bbe5a5914d73a3d3768b7b489607bc47008b377c918c2496b778e9357516d720ada64e11f3f15b1c9ce923cbca1a0c4a83a60111113f72a55c9ae98aaec73137a5975c15c6fec86b0354371f3074a5e73b8c5968b8304bb14d841abd6b933b5c545d5e9b4d67083836d94cf932f8acdd72b9ee77dce37c27d980eb040c3bb3c3565ad2a20e207e49fccc9fb862b26385750d82e857461f06e4043f039cd1424c8fcba17408132a369ced90c25eae8b1c95730b7e6348b2b100da71dfaca0d19593cca72380eadf381bfce80e76eba1378c8594cb0a4714de6d5a5e6cc464e3c4fe0375844508a5b2e1cc91d395b4c2ed2c9a911f939fe5498827932983fd9c3ed86a90805def7426caa232b4b4a5d1f7e9ccc63b33bbe15377cb047a3b74fde2a7df74e6b36f9a069803ae439cb65b5af50b3c62d8a557e33a9c0772fbccd4b2f80135e4ddca2cba8c256c431451e6ccb1f8bcc56deb6fab1bdcd6dfed006907bad0d26cd0f799bc0b27b6746d31d7b422accd7f288ca13897f15aa628e9e430832d16b4c4472d9101b6975de840b35cc7ad8c22ec43862b061bbbccc4c34de4062b431e9f223d9de6f80c7a244a5d0a1a9a58197c1bb401302417bb46a30b267c71e76388ec274be8d5a316a420384c34eb5a881197e004d44704b27af5f6d2700da618a4701b63eac61594ce4a4ff3020771cacf0602522e5a5cd5bf7b18efc4e4fd42135d8383b62835aef13320d121c82f1630f0da01c84588caf3090e1171a70e02637324be16e1457bb8c88a81f7825c71fec462c0f1b900385a3219c4af3722c9f8efa2b55edab2b29688ccc0ebcda887229a3a7ce0592e760c4f0c9360621a0a8b6f7131835db947f4004095f86b87c326d054e10a54f608ed3993eef43e169baf188b2fe4f3ac02cb10ce350ae06e8ea2e4169ae5b506ab3a21a298f2058467a9601c206951fc9b035513cb51d33e96e24f2af51e8e250e4061ad00f2dcc858f7a3b838e6d01cc16c21b80ba6f3db58c1baf9967796d0582bf83b3d930b70286c9e063aeb8362ca57c01c196dcdc2cda5f347f83c8cb8e527c81196c95cc69d8dcc9a6675635b6e21b8d1b64bbeddb84c8e75388e24a801b20eccd97c3b4bb7042c14a43a7e6200606c73dc2809571c0021ab0a14a8b9817a9dea734ea58bda00939224537589acccd48630f73c7cfc28ed1ad8b82aeebe01c76c7269907f22173bcb3af6a4fae7c46ac5049ad8a7fd2a5659443b9a6bcf6fc2cd202c28cefa0cb615e15720e36bd7068f31d95b5251dde77cd29ec5626e9e68332d9b087c2e2d19aeccd6a2a2590cef301802e2361b6392f8304400614da68014ec4de0f4050e7d93c630bf4803e3a10dc6743d83e539b92c32f3c2a2b078a37afbae9568b0f4ce6380a8e732b822b98ea928778ecfe1d57a69dd985e69f508c67bca385f979a1ac215f2ffa2f437a04a7f74180de147b3f0dc82316091e7c40e967b241f8c0c28a857b9d7b118c99742802a3d497b3f342e4b3f6df239509e454b20efc898a4a614b54b085d2ad23518a203495a03c32092973ea1a037c2917400cd783c8ef879bb6c9d8577d2035002ce311039c6639e4e511387ec51470327021d0e4f772299b1da8383e7f6f2cf5f7b8459311449b210a311f0dc261c1c895b86c45bec40dd3bacb812537d4b31dfda5bef7fd427e760fcc86c5a3bc8c65f43d885b733cabc220f25e754e3977201858ee70caf024d4145b320fa82d6bfd8193f64aa0d112de4883e13c247fd7171f1046a37ef28d23d699511b636dc624e6e65730025598ea825bf3afae4bc0f8ac502da330ba139abbf1349dbb1b42a49eb590ebc07906401af02cbc8cca9f7ec2a24fce99880549003480a060a1098d04e2cc9a5e423428fe4abab24d319115ec3ffdf5b75e35455865655ed6ec4b734f463f3360d36bfff312715e8926bfc05d89099103bfc2c838ce483a1f179a95671106bf4c0e53331c5d0683ecb7e04879399c0ecedae27636a9130817f930f12dff03256cc3e750cc4e519143fd7e5050d611756e74dd0a4a7754ee03100abe2f71b5a9c7bd697609eba2362ca194cae3fa9781ca1254bfcd0897bca290045fe77e0d359d6289f61fc7d9d020e0065697c86701e6eab925d9c5821e3bb8d98e90ac9217df0f155aa3069cb91b17264d481b55e2f774330716bdc3f9b0c4497e7a5b3640667dc80cb349dac06636116ec1945d09a2bcb83fea8ad042a168ca7432fa6d0ec72299e382d0911113d9e3956046e7f79f232929e8a7393da1d5de568e845893cf51b3a3813eccd2276d491fb57b8aa909bd5e60f2dcdf34582331c43080b6affabe0beb78466d199e64159524a54448ef5d966c67cff52b47d0508d1c6e15f18b21da0ad1a505197ebd119e255ae9795b8e535156ef8670d1b177f9145dd3d457a0f833ae130f1c8fab9d3962b463d2fcecf29d8a390caeb6883b995275215dda32e7b748600b997aee62c8000bad3267ee0084f16b4e11278f447d6def22098153df517143d192d12cab0697e72a0f5b6f5a4a46db399c6424681fb080a92c27e2c870eb2f00d5b605e125aa3d41da28940042d6c783742f04a80ef7dd2eaeefa88422f6ff968a757d28480805ed0f6ca7a0a8f4cf12c4b083dfda03e46b96a5fa1b511ff5fe6a00265a6306f762a66490f38f5bc819977b8e387bd33dffe48aec2fdbb869275e9ce25f32965e6d07a68bb654d088e60de38e1f4f760c45524adf2eb2ffe279b1be2c0ab614fce0995ddb4f1e66f4be2127778df03640332d92fb2599712bd960ec04eb1014264e10f1a3b4d6611a2a3a6b238848f872491e40533d8a5c01b5bb8b99580fab7c6aaccf989f43356ee4bb82ad5cb4454dd466a74adae9010ad994f187cee4ab15660e027cfedfef1dfe7fdf034d4953c61aee9ff7c5a36739034fd7f6991864aef9c2d2ca16074b7e989c29e7046c04757444d3f86f4ea42954814d690f45b06deb962b6e1f8b5b26ba819350e3a4b36588910ca01541061295303769a195d7a0d4ba4379ccc61f31199b82909cf516a62e2f0f6ed7b48f9d232b1fd70bddc36520eaed8116b509920666a0d72b917c74b5fece793c949f3a8628e117bfc40fee3ce4114259870cd6436f049cc8e44c2963897f92f01839c98f7029d0ae5b9a908f00de3ebe885f23bb341cd1e118a0881d664a67439a8be538a269cd0e9ee0db247db7a330107a58cf2bacac673a0c1923cdb4e9efc06d5e216d7e8bc95a29414155ee49ff1b8b33f4b4bfca16cc3d4914082c9506af6a28bc373ccb2b37bc4cd0d231a7453288556a8aff5efcfa173b289c2d6b48a7e7b879430147401704491126222029f938e30b142b249eb40588ef4b8c2e558869b2b96d7f3d103b4bd547d6f151ffd37cd47a7d945c8484bf150ccb32d300f69d9c8105e362e0125bf1267a00adcf5fcf954c6e106e5c8125f63a7f6170f812b4c8de7e3fd9135ab6aa2703eae49e00c28471f0c54212ad72ca98a71f16ec4e03e269049021a07b202faaa7f78776407e0c13db436266c3591787329c01cd8fe59b3f319021e28be96e5db126e1127c7407dc47250b2f4661fd723d46d6b0b7864d889c3965f6bc8b3b0ed65a59515c6b7e0364c4e117bbfde2c7ca977dc9163643c9d66cc836d1ffbacc5eb398b1df47223b1164e89c9e33ab33a14d58becdd4d7bd6252190b8bfbd6ab7b66322028b2cc56c18f7646bb77266edfeb2d3629842cde9dc980ddc0fd55512dc5acaea0e9b4be0e8610f3f1d789f0b770872e7f2e0b12d1817aebc7fe3bba51dbd7c7cb489e598aabb13716e36fceb055796a42c88d9e00809861b6540dfd236f20a98d89c46a46abe711efb11177e7b75eb5cd24647ef85799b8b4814e583b85436f2e037f4b565054e2b6cb5b29b1ba8627e8ee5963b02a4b9425b0d94be6c15548125aabb8613ffe533f12ceca01301bf89bb1adec531bc610bad9a8e9c8b546a1949faaf29926302b59804343c4bde249aecdbb029f09ac7167c7472c02116d33f43036aab075937bb742412192b8fde2200920f8e91a859c6cffd4a510b2c4b4971e59d049ed492496bcc0b72dec80593c7a2d40cd4644a04c54f77cc484a32a864e436262cc189ac4466f77252016332af23cc2bf3fc32623612cc52e1502ee3f96f28b77be49ec0cda786874503d87f0911c478d33cb67c02a3841b1fe0bce80cde7454a4b5d0e1126060079f27a2fb05d55ef5b183d45bb2ed015f4083dc4457cb4c698fc2625aadf46db28c21cc6261b33182ba99ceea5189c6c576855bc7ae015164b50c1b1da74e15d05bb2c32248202bc1290b79cf033d713110f46ca252818cc91e09295cffc5251bb94659143e981b0677761e64d25463189249b9c150397412832de2d70a5cb9b294681c54a1380395fcc9be04790a741ea01a12f87a3b5a1afa9f307a94a08fa04a2563bce9dc540a406ab760e0029138659c76278248408ea6f656260e09639e103895ebb2152b1cf929b67addc50fc22b56002a65ec74eb9c4e5578ed1444570f4e0826473683380cb80258edd9cccc07cbe9e3693003f308bdce46a1da3cef4239d068bc26eeb3cd5d1a6107cb30e10ecca731116e0918d8b6aac15c25c2b96fc394d98ec16ca3cf48a15d5a88a437ec14b5aa76d57b0ef02a47ac8ec40d1d0be1d5d130510122257e4cec22119f009348ac679e3943034902b7965cf70d56d9ee7080aeab50d03fc04156d248b548daaa26049b94ede1f53c06bd4a235071eebc4751ef46e757b424d3732cfb087322936bc1fd5db9fc13769e8d2baece84cbae55505db0f410bcf8fea91b4ce0e094060280ad7abae2746330850d544c2f46f4c9a045bdc444103aa41102ba31acc6704fd6546ac0b707c5abdb82155f8cbc479b59aeb53b47a92a6a518399be85f8eb518c94b76ebf4756ca342a03ed9502e60227c02720ddf715d3f27d849c8fa510740cb32ec2a767d57cc7b21bd7f9e9ca78212acf2eaa9e31b3b808f043f6f42b47309fb21dbd87955122ed90b310e62c946a9632a53fb1f9bc2f7e4c10bac40e31f87f1ee1d1ccb39555092e1ff82ae164c60baf30533f77d13066f0ad4439ec5ade2d5e990109add165a455d365251be84b72a9c214a2aa90f7eb09883988c5143decd144498089abfba8d9a15c2fb0d6c1693294d902b99d08b3529fb0723c727fd89e36c47705514b486ee7ab68c4d0945951d2e10b198ccde3f6a276ed8f1dad814f1b1d6a8e3c0f7a0b19bb744de09eb9406d48d319a1c6e70fe6e0df1e041834617dcd49f80fc2ce23835b4f06956e25ea99ae2518c6fbaa80514451968447ec4a6a1e9cc93ea9c22391aa5ea3a2d16537313303adee96fa0f573851ebde45c1aea8bb285e4657e8e1297afd80912feac10eabac22a3c3291c80f6478a08a1a2892258af75ea3ba8c50b70a98f3d9c64adf6a2632471176e99e7e68e5a6aafb7bd354097b7e942a86df34a3ac4fbd28d1625b1844991a6dd3ccda080ce04090ebea9911851987cc5bef050bbace747ec36c661cd29e1a11df12aadeaf8a397b1baaa480122cd202c6252713345996e646ec354837a98d462b53076433aca6c3fe5a6753b365e8cc85de0f22d0459271ea7734a6fea0af6b898e39587c6a2acacecc0c8231e978407a728f95bfe6c3c29e7049570d05d6cba1aa295b471b59361233ce86ed08fbc9bebcc852173931cce92c81cab80a1c0fbb67c654d39be57f2eef1d6f6fd2eba2f7f5cdc72800db38451d02c835675cb2ae7440518d28b8a32594822945c66a21afc47a1443299b7500c9ecea5bf4b971ea7ef17c000cda4bb316e6697e11ac58c69b032c673cbc7044111769a04db4dbad48e2cd145de2bd3a8dd0ce316c3b8d4554586f7210557862acfb745aa2e8c1029b28973d19742e40cc66293430f44d8cb026c4b0b8192af1eb08d256365922320521296b82239e8966969921e1b1268dcb8726d0d4b92ddd3ec79fa97081b705ca6b7117d533a2c87955f43df43551854cd8b7b69b40506070758d5a06471d1f2291c8af9f36de2580c5e7bee539130cd586b36c8338e85c44057e5607a9dc1f906188002124c0a19fbd4c98ab47b8d88efe4814dbae56812352fe145d3e2811c0c3aad7014309eb8cde3bb1ef7267f65152ae1903ba7d1a5144b550437692ed2232dd48dde0964d8d452fdc6f8e34889b7738712f094d8d1dc00180524ed83c1d7c10a8451e24863fba259a16b1c0b3db04992053df73f2a9a97eeadb0d076f7dd6d9da08367420de842d0b48691a0640799898ff42ad53aa187f974468e73513c33e7a34e267bbcfebe7fbd2fe632eee660b1f716724a792b1b0416ae17f3ff7ed3bd6f5d19b280a646ddcf313ade2732ed59a1e4ab8b059cd955da2331ca8d57802c973761b1c79f9bceec5fc67750a9c93025f4a0906a534c09a3bd9154f2855cf677d2601bf82ec9c8a16340bcd8f7b9419daec67a58a9a04957283d62ed69a686e13ad78b1b032484e19251d53473178ed42bb8a88af1677efaef4416da218070af16d9e56cb7e2dd282c15593d813808bb39e42aa96ccc482f7a27b6fab1553c861bbdb12bd47aec90e0ae70c511e642dc48952c568603f9aae414f95d3f2d9fdfedd7ce651a38b45baf5e880d8db75867f6da2f3185d7ce39af99e2fbac6470ff1227f3720042f116f6733dc87a6f0a6e5b65703d72e997f87dd8126d1469f6eb344de11edfb7c25f35645c0acf0c1bf52fd4e09a3b1725cf44a79a9092031357983e514649e22e092aa252dc52be91098e4fc5742310be83650a4a81f108d9c2b2853a4f6787019ae68c47f9f046c453034efb04d2e527c41febe11c3fc16113d4a7ee87a6ded5c850e3e2154c6e528a3684c6a7c067fb6e237a53901a51c1dc89c4ecabe61279acc4bdf803a6206c3995710787c72462520e092312ca11978e213441b0b63e4e085631102cddfe368a85073e702181f4185df956db3dd8cbf1ed165ea727b48af87b017d12a2d35c8a73909a85f0ef89bbf56300b4bab2c43915fe38c1be2f476da46ee2b3e5e38ca76fdacc452d73e6bbafa9acd2fc3fc582c602356309ed6e2cff8f5547d83585cb352c751320959ad30c9e68a5c136a14ca79d59203480a93d6d0fd3ac9ef08cfad2eb6a9fbea599f33e1cec7494630ecc65094a96e46c69912f82d3f5db53c593a307f9ef2fc3c54ae2c7e344b86d2e6774d1fe974f97b6953a0da23c0c5adafcae24ba5b464711d88b8045d1af283c6c24aea6480bb0801e354d6b726d86a1588f48c7f1d6bdf08a5d489dd7b3a219b4978cd3bc654a0effaf58093438e1941965d30a6058268e414754df51ec90600c7313dae79f71627f4c44e10a6e69a053c27635258e72a93785b1a2a7a082b0a0d430e81f878081c1403e90b12035d53feb7c1a7f5f2a4e4f28a5508932d3ab5ca9659c0e8bdb7f0f511a4ba8ac40aafbd01f955e6b7e157e10eb643ccd9f1adda37232f10d2183d8f985e8a0326f034e4bdbe9443c0279670772a6d0ae4afa75ee0a852def06a68ceb40c42896749d813a7fe85334321f1c866b7bd8af0fcdea68401de51efdc67c4e24449733285b6b3e15ceffd40d2adacd187e3731966f6c412985d2408cd506de469a41933fb6a42bb7bb0ded8c6763a0e17e8c39c8cb711cf8d87aa4831cf15f796105ef37252957fccc44294d51b9c55ff2ac418707b7007bb75b64e91879ac8ffda2c75409ce485b65e02720d511c7342eb8820a71660b14c176850ef1e7495b52847814a8c3d1ce08e2d371553c739bd9cdf37d8f5b9b90c64215aade6ae35bc356b1e90a88af86224cfa911d01021915bde3b32209a31be6c19267287265a99202307331f32bda84cd934dc0ac0e0e607dc601ce31fecba873f2d66ee0fcc266f64b6982da82d35b466ec1231cba558e0525ee530a774ac15e3272a5515d0bd4a4e4f449e9af09c5b8a39292eb29a97f258bb925b1713cc179681e1f7df34db90d4e609fb39843c73282a0f0ec0a4fbde6818e1ed6f1a01fcf98f0d03be5a142693f62a52d9d87aa5e179aa36ccfccfc1e09e88b0bcd12e682713a12478d59185a8e779f86491f6574e58c2b9733638a3bd1942f94ad945dca9d65b99cdf3d47458179451988f24a9988725f4172b51184d37624d5f1afab60d16ccd05bfa32f3df26fbd433ffe5bfe64f7283b12602f189f8e448f5f8b4b8ba7c3ab85637d8650300911e92433a96b65f5c96605e81ad7c83b5aec227ab118b4b8eb889dd8d384e26e644d442d5a03d13a88dd7a23a6857251f11e3b4393e233474f8d5ccb8c660d264c730693e698ceace447cd8b571e6a341d86e9b8c04a0ce97121621e86113340be8627168660f092af8a05bb7e0be3afc49f91d02d4cdf82eb2da8cf42315a706ba1bab8305a546f638ec185dc60b09f0bd292a1d7c030e202a87af485d2c425cc32703a5a422044544b832fac7b452333e4a10790501a622997b71d7ffa929a987e403e034c1ab57b6a247d5dd27b129553b80a8ae433f0dc5777043b9712290367690e953914b35b4cd54f33878a24bf34bff0a3b39bbe463fcfa0412e025d4f295bbfb40fc0af7d284ddd81e94a2585426e1f8618018530a036e40190a25e1cbd57a1017dfa938c2ee2b2462c865217092ef761408a4d27f88ad8e55aaf295b565105b2e4ddb224706f7e56f35557a2a641b19436a9243df26b43fe2b9623c2b2275b7e0f89d9cd0bd49cadd7b3f882b4f03d2c45ce083bc8dcbc27ae3be8f7655ce5b6b3d5b6edea19cc9373c9f4b2c268fc87b351258ac77c13bfad6254407e41a0235780dd6027bfe4f6b39ea6781263f278002803aa9186774f8699b30f683fd93496046845e08faf69dc4459d23d49808328109b08012ec16e488f6c22797c439af8f62c65395d5a651b67905e988bddf3b9c7210f8c49a2b8e02d1e66214043e4db017a784f8c3b80b0a4900330f0fcc0f303cf0f3c3ff0fc009d37f1db165bdf851b8a48410aded15eab1172b9bb52ee8a283fa1d4f9398a2bb6d90128d57f72220852087b08e308e42e057a7d0ce1b323f7b0b228d047b626ce62a4d6ca4ef07c6f55c592a7308112a4be2a7fe07f3945042885be97538c17429614bab9e7cb614cf2c3a021c028d4930d923ea51c4cc649124014ca6cea9bd9345be953040284e2d85257b6c5982a03c531b9519773dafbfd4431ebcc278f8dcfb33df1860e374dd071dff23b81642cbf9917bb0927fced0f1e778ee3678537f19588888795262c8fd385943ac4904c2469abf294c7937248004ce8527a63d9a74be881997c8e9a8e2e87b825b47f9992d71829c7bc7640804a28d962e374982f22e54f09dd64c6a3d8cce9fbfa49e8e7c169ac205f1e462f09ad37cf6fe48fc3d0af4742bdbf701792e698bfe290d06388581a3b64479df923744b132c3cc8f0b03eda118a784964eca5f0f1e64668761e6c4472e8119b19a175249ac34c591ef2e54568ad215e3a8fc2a6d4b122d4ec91ed04cba61df92311fa7bdc48928cee583f10a1f9e5cf5b7b1c42abc94147cafd61b777184289de101f67f140234721749f6dcb3928cd732521948f1d4a6be642d8e00e428bec16ee71201f245710ea874f6d1ee94b749440e841238dcfe6c97ce400428f73fcf114cbc2c7fd1ff438bcc8f172dcf2713fa8615b2ede2b8773721fd4088f4ddcfb7fefe583d661436ee2e498fd1e1493b0cbd159f0fc307a503f24c9610e32824d300f6a5cc7d8f77eefcee141b7fc2083db77c79a3207cf299d54e6b083962b928cb975d03e74c2cdf774d0dae34d737acf41e9986b67c2b3859095833aed63c6416bedeaceca120e9ace5575dc298dc5fc1b947c8931793c8faf73833a9721e11f498e63db062549de10a32a987e1836681d75ac7bb1f6624e59831e2b7418a77a54c37eff6ddf9d2d69d0357e1883062597777c36e21625953368bb1d427df0e82888c40c6af230d5c6f86b4e1d298362c1e68265cc296b44c8a0febd650c5512fee36f0cca475797993e62502ae2858860f93cae5c1814b3ce8a7ba12fde3a30283985ca94dfb9dde15f5037c5d4445586e4c70b4a58e41897e93a73982e28939f3e4e7e883b122ea8b5614ae38e580e21b605a52fcc37a7c8fbf8332d68d1f144d69cc4e3b46741b7b05da31327e9c5b1a0c7978376ebafa067fe584c3ffb16b35650f3648f92eea70a6ad7e5eeac1c77bcc9a282b27d16dd79642a2635053de838ffa39c4b41f9d75021ef32de76444193caf83c613c2ccf88005050dc3cc7c977a32657f40435a6f841db84f9a033ef042d6ff4c7933c9c14c16f82126ef29f7bfdc6993c13b48b1d570a1b2c654ff712f4b0638e6cb7c30ef7d14ad03c27f7437c303a6f2741cb293f44fc2b56e73412f48ccffe1ef51114bbf459825988d79a8da048867b7c6998751c5c0425878eef74af34c23f4450339c0711e6cb27da33043507312c9e5484a04eeab03cff658e1cc60441ebd1fc8d1cf9332706088a58107f8f1ce5f82ef303cd2a7d0a1fcf91fb9f3ed0e3ff7d5897c3cb3fd9035d2f3cba147310eec7e481e29e65b2e538c16ecb1da85bef9283bf0fa77bd481321f6eb80fd976e30673a066674d9f3598c61c421c6816938755f92c3750a643ae904b426f8cc4069abf8b97c649b2572135503cacb98fc1937e3cd3408be0b9e307ede0367c33d0ae63bbb3fc09d5efc940e9d82749e5cac540dd9171cb419b7e9c33186833b95bcaecc267cc5ea066ca614498cb5ca0e7c79c3ecf9b660a590b348d94b5dcc345c84fb1408fd35d7fb1422f44b5025df204b7f01c22cc47055a443ad77133057a143ffc9c72d8b1d204054a3a4b9df45b3a817259fe121f97560a014ca048f628f7cc7c29f4f84dcbf3760a9dcc9342ed10c353c814f3a4f247a164cc0be1adf3c409be28f4f81cf5e638ea9c3bca87427bcb21119252dcf31e149aec5f5ca838313dfb27143f0f5305f9db938f7ba2eb4fe69e49f34e28fd22525693a33fc939a1a5907b6c2648c56b37a1586ffeb8ab3c8ea7d39a507298b97fcc3246329d09dd62a6ea38c95bcab331a1d969fd5c4a22b9cbbe841e79dae3e794b6845a93ea23b2b7c448e94a68231fb85f7f74e8784ae85af216bd3908fdf324d46a19f31453ed1d47126acef371a7cbf0b09b4828319e5e7fac2c966218128a47475dfe0829d5c88f50538a1191e3287684fe1d74e6bc9177b23149184023d4f0f142e48eb3e7790e46e89fa3bdaaf94cd59b6311daa40f5184ee1e3e88f25c35251d89d0a3c3cb7e9d909b7b44687a11d2b9450e1dee875053feac2ecd8fdc36841ea3e3380cbbecac6c2174ff8be92a570841b20e4673c2759cda18792418c020b44811a4e6b3c35cdf0a420f1ae275fe1c3bc7b10d84ee17234b5e0c104acc2392baec7b63b67f502fc78cf191586f0aad1fb4dc61868b74b9d2fb7dd07fd3659bdfecd29b0f6af21399349aeed379f6a0e58c1c1159f72fcba307fdbf52ef1de02b28608515be81f5c0154e634615069007fd33eb6c0e6e63681f0f6a8a3539538c5d13fa1dd4f938ee92143b14f72aa2bccc3aa89fc6c30f31c8e74e07c5a54d3e86938e08e7a05874eaf6dcafe315392871c9827e6e09edc5412f8dbf4f2962e0a094eed9fd7fe60d8a9d7d1c72241d9d9d71839e637c701ed4ef843cdba08c7ece90ddd9a0b5f9051d0d1a2376ac41c9091e63e5ec24dfa8410bb7cbf350962387641ab4ca7e1d9b64b8ec52a2418f29db30d9986c8f33a8adb9643cbda6e90e33287555d333f162a6b70c7a902badd89a227c2c9241d3f1b91c48fa3898188e418d937ea272da641f2e06657a6e436bacec110f831a27a9a39bafdeb2c1a006ad5012f9a37c418f19f5e1aaa47275142fe8619274937260e9822e35e3dd953243f0e082221de4ef460726716e419b0f9aef03330f9942b4a04b78c8e778b9247b240b9a7f78bbc8cedb88112ce839d6c7d56196f0b85f41afb7915cee3ebf492ba8d51dfede834408c9ab8276afe17118a7a3821e79ec335365b1b27400087b46cc09396cf1a0d885bbef587b26d6e70ecae40a9fb9976387b3071e772c733975d0c390c47d934c740a1b3aa8992f49bbf226546ce6a0799033eb5f7f96ec18396832a3993f0eaf7ca6898336edf91d7f7edc183470d0f287b1fb2ce68d7ee60d7ac7f156dca499b3c68c1bb41c3aff7ce4b78b946983e6b14ee7dcd6cdc7271b34fd491b9f63cbb9f15c83f22192b9af063d68aeef509ae3fd9306ad76fee2e38986cda041cfc86163ce4e4ee133a83bbbf17ae6c13d2ccda04739baca9037587c1c65d022777e73f0931d4b06f53555e49f8e9b9033062d430c1a530ede6f226250b672de3096f62a2c0c831ee587ab583d18f4ce49a2c6e52fe8712c2307752ef93cbca0cb57aa1f778f62ee827e96ce7d3254ee18c385ff23475d0e62d98292cd4ab77b2d282397453e9a2a692d0b6a7e961cf78c7f5863418de41a591f84e80c952ba81d467d7b9a98a9e3b0821e7df67bedbfcddd902a28769eb3dbce5450d368866ecf1474114fa571a6f1d12805fdafb296a410bc668b82e27af399a3da628482fe13442ba6cd1e5f754fd0f29df869db4ed0aaa733d7b84dd03f967ed68d35594163821a2f45e87db6042526cd61a86fd9d25f097ac60d19ebb257ef4950b365a48fa3d1a63112f4b090e9720c8bce1d47d03aca77c182e6b0dc184193cbe14bc2c383c78aa05458d2b81f39bb554504dd629bd4e8875d1f3c04cdb7267bd8a937bf87109438d97218723899f31b04ad3f48c71c83f4a40c10348fde2d798a0beeff404d97826fb28d3925892841850fd49c7c92c751ca17808a1e281d3b2b62c6bcf1639a0a1ee8a29de7c2766ec95d1440c50ef428428958786db18feb40c99e420a299c470ed4daecb15308c173ac1f1c68f29303cf4c1b4a77bc811e6cb2f2890add71b2d840dd0e4278f990b3327f35d0e3f7ce7e921f0f3ba381a9b28be494f29a815e1582e5780e19e839471b43ce21933d4954c4404979c282edf9a4ae910a18e891d959788ff30bb4fd0f3b22696bcafd7081ae2f9d36d85dc70c1a11a86881eed661aa8ee1ae997311c82050c10225c33d5bfee920d2843860c67a208b4650d18647be0a94fe1c69f8e7891cc44f813a9be793d2e9285077729c21538ae092f509b48f392e33420e2a4ca065ac1c9232c5afcd4f29b49ebc7176b72e63e89042c9f9c07c735f8c51e328f4f9ce8b99781185dae1c297ff68eef886428f37a67693289f9825a0d042f674cf7f4e5d26f9849a7a7f5b37e27e4bcc135a4a7b497eda3afcb813cad855c4e4164ee8711ce8e77d894b4cd526f4dc9d3d85ceb429e4506371c51607a92a28a080edc3149ad025dcc7fac14765e3716442b164d79b6e66628612134af828ecd684e023235e42fd8d78d55fb7655ab184b9e3cbf0521d570925d38664f9ef93b92c4ae88197d7e7e578337610bb05126b8a49689a64420ac9c364610a4930415c643a0abe158cb2c21491d023cfee91cc166cb22d85292081b8040fdbb1e765adb0c20c533c62b3ce20e952e8949918a6708412fca2f2495c74e4762394b0f96827dd5f8c876c610a46287de12c76841db91cc1c2148bd042f2fd481e7936870b3a610a45a81d836b6c37c9369292401917a64884362923270d9b909803a74084ee5315f6a310de634e1f421dd9ae8d55f13184b0017a01a784290ca1d7ff867e9b6fce4c075846030aa1bf95dddc79ae08da22610a42e8398e1bd3eeb139c5384696d79061812a4c310825f48465bbed18d2dc832904a1be077117e73ab2d4db1481d026e43013ba3baad23c20f43059ac0fb276d8b1fc3f68f31b92e4dde72095f7c36e9bdfe3f6141f5d1fb44bf793df47bc3decf9a0a58be05a7aa797ec3de8f1c6f2384b7319173da8e3b12f71ef764bf33c28d9a763918f82db68f0a0f9ffe56c9a0facbc8362e1357764231321d57650a68375e8ce1336e75c073dcc93b556ba4df2d3410fcaf773d0cf41b7105a23ce7dc841c9914c3a6cf2888356dd91e48d9b462b0f073de43cb6b88f52d6b66fd0e38c8777a4d210b11b14a9daca410c164bbad306edc7afe330da7eee830d7ad2d97c1539e472cb1ab4cbe9e3348ce791941ad42099dce3b839fc964c1af43890589315ae49643468164268b967495ce70c8a77746962647eb74c9a4193b19cff3963192a97fc3c53fa162964d06adc237b596f759a8c412b998ecf83fcb0ab11cc90c130662c8d1018a08a03949d0a4c2106dd4367491894c8a9dc3f8610c3851030a87716326ce43c61f25fd0ee52ee93ae8fc5c3bda09d4ff0ba710f66c3d70535acc6c3e01fef7e94e382ba31684587d53ef1b2052d82c69c1fa674511ed1829e5376bec9b0ed1a5916342d97ec8ee72d751616b41293b3f073791ed515f4d85a327496ca57af15b498105f3ec6ba90db29aaa06674c4f0b2d0de310515d4dbadb3943ba4f898827e169f24871c2928152e678ec542ae1c4741bdcaf2e17cc2ddc51c0a8458d5fd6f162e6a2bac3810101a3566dc144fd0724cd98255ecb9c9ec144e50ece378078d0a911f374513d4dc51ce81f7cd0435e7af3012638cd4f64bd0fe3d4c915c32e69f5e097aacc12c2ceb7d601d4f829234beb3b674cc573990a09d8699f3943c47d0c3e90afdd7d5b12766043dea482ec7129a27f8550435ee8ee59cd3a789e927829e66376d0e9a0f410fb635cbc22746c7b910d48a3936351b2cfcde20286133ef548ae7d39203042dc2277898c1723cd6fc40b9fc1c3fbee303c52be7f37d799c5d323dd043f8be0a9515c22bc803e5a7fb2342f877a0c64d6119924407fac576201f41fb6ab61ca8c1d2c454a96338d062a8b3cd331fdf4175033f4d7bf06c711b28b962c347fd576796b6985103fdc3a0394ee7c647e9a781e29174e6388e5f8578cc4071db8e4b7af771ca1d32507c3c8e426bfa0c6b37068abc747fb88a57995b18a85d239d7f52e7cafbbc4029bbc93cf99126d2c7055ad89cc3d0ff713375d8022d6c9e34b1310bf4cff3d69014243b5b56a0dc87fcdc1f6e0e3e8ea840bd9842c81f6c8c4b2437bb107a1ddb3cce02c6d2d819a70b1b3750ec2cb8e48e5c9f1dd2840d1b28356137c791bb5b75aa140b6cd440778bf4e1443bc5e44e03a52dcf42f3ec32934502aa38c02fa0062f8d1a22d019281f7d0af3f02ff9cfde81ad616586810d19a893d2e68a97f925586b8515a49eb011032df7bb555b0c1ac7ba23840d18682e1fc7bdd7adcd92737eb0f1023da549c9d3c6da05ba2673cbd14b4f32dd375aa0e64f8a7b5a17e3741c1b2c506fb2bc34f4327ba7ac203754a05ba6d84bdf6da440f138d8503937967c4ef1c1060ab4cfda4147d6b2192727503cf0e8f4bc4c6257b861023ddc194b3796a23f8ec9e82db42885963284f70d5691d15b68410a3d7de6a0c62b88a6df46a1cc548cd80d1dc58c31a250a77c82c57b9020b8088592f4da43dad8cbea4181071e4c3393a4cc27d48ae329e6d6d1ce1b3e3e70e109a5cf22e73b784e1d84b1135a7930a39d6386062e38a14476cd619fe12246fa022e36a19827e9d017733f638e035c6842f9388248e5109d6de12213ea848a7d396797e61c1723eb7cc005263489393ac9e1227f9c182c63865f075c5c420ff2d2d127860b4be81d749862547490e0f118593268cc380198c0452594eae02b5cbe860c1a309ccef502300a179428748c9f2117236b125a248fdfe5f48d91d559982cb4b1d842468c09586185b100e4c18524d418bec285093da92c1e60851559c8b8020406132e22c15b852c1e3234064f8cac04800b5c404209d963ccd1c590496d3d429dca57926d1adc4e7384966e3e2cb9251ba1bee44f931d6c8ee3f124b86084f2a195e3ebc9c7615e333c402306125c2c423d9dd38f7b2f7edb5302178ad03b48ea8a103fce92424770910825e730eafdc3903ad68f0825a74a23547bb974fc105a6faad2fa1cc4c896c3105a78c7e1e5e52869cb5b085d3cec28aaa2bfa3ec1042cbf795c1e384e7704206a1e6c8987638d1b12f8250e46aea7c2c24f4e402a15bc5bdfb6dbd1cdd00a1c7113a4fc749fd41f338e4d6b80ab9f0835d3105495261c44d18745550400165072efaa0e60df5b193874e9cebc71e562ef8a08b7b9cf0399cd2398d175cec41ffd8f5f5ebf42db8d083b2f9e38f2276737ea49a868c196e85155658e19c85ffcbc80d64714507b6861651709107c5b3b844108de11f3bf0604edd21894564b250562176bcf9ac24597234292ab8b883b527c17393e65d02a54c035cd841fff0f41d74ec75d03efac81e72f0f427d3418f390779b3a6944f2e3c07bdbfa2e3a426e496e5a064cf77992a5778a71c71d092b4c7317dacf7f072e0a05d9ab3cf0c1d6ef56fd02b4d8e21dfe4b0501b3728c9a3a8cb97d1147a6c83121d59b8e810a17bb341bdbefff899943568952e4dbaf14f0d7a5c0eda2eb44b839e9bf947633a4cc70b0d7af8f68fa53d2e668f50e0e20cba4488c57790262ff366d0638f935f6ef22883661dba9134c7fce4c9a0644b92fd2d26899ccb31a8614288c60d1f42ca88082ec4a0496859e630464dcf260c7ae530a7f2b94da58f8041bd90354d848a1ff4f3052df64be5728db0a84a8b113803bca07f2c4152ce7b0e229e5d503a44d01cfe8470414d193331f967cfde395bd0f368c7cf39885a507232a6fabe8f83f0962ca81fe52876b618c3829ac962eadb6c93e962727105357c1cf34fcbaa810b2be829795021c6182a5ea6aaa0b5a68d8f7278d91d3315d49aeec8cfa3dfb0f04e41b1898eb7a17db6f1430aca07a691837cc9814b15054dab4a4fdfd307e51514b409314c9d841ca783a08b27a493ecac3747942403174ed0ba43e463ee8e4c327603174dd02e86089b1d739894364c5073ca9d5899f662db25860146408302c5c512d4d78e72f85fa139060426a346160b38800b25e8e16f3c0ff2459090641749d03afc6053a810211d752e9040e8e0976fa7c443fc1ce133cf0d29e2fbc731c21f59daa0b5313b2f528443eae039e9d8748c032e88a0079176f38554c12a3443d0fba522b27558c747c1800b21a8399e88201fdf88e5254626400255181a3566b80882f72974180be54132461604ac68d498010617405073270d97d8ec29f527015658f102173f50477345b02b8b79fefb40c9c164ee68b64567d23dd023a78bfdd32e3b8fc203bd2c5bf83889f8e796ec408be1eff52f64e37cd381fe7d1def6ce898a34be5408f314f0e1347ccd24f2e70a0042b999ccca1227b72710335dd67c95196dfeb8c5cd840cbf92e480e399fb9af33b8a8819a2ed7475772d1b4330d74f933af7029730c7321838b19e895a93a43f853066ad544e87c799c65bf1659c8701103f52d69c6904f18e851ce7d7b6eb9edb17f81d6e935a7f6c6bb7217e89793c7e1e3c06252b805ca853fabefd11cffe72cd083dd98d7ce1f36db5e81dab1e57479d2c879b40af4dc91cc1f6264b8f9488196339783cde1a4ebb845817616e2f79d6e04c9cd0994f3fdb83c0c29e40e441726d0c4837ce8b842e4799452e8521d3df1f3c5ae9f9042afc9b755216ce89473a3d033e5ac113ff09034178526396da4fbb18aae2b14ca84c971d68b07963b99d508dcd0800a50a87bd65982666eb27e679c28a8f88416d95298799a98379823d819ef129041812a0e50451507a8a2c61632dc035750e00a095471802a1640c341f080112c04acb062043bc31c800118016801159e505c333c3a0eff9ae33ba1a6c957625ba125cb09f53c8ca49de3f9307d13ca96c741900ae7671d9ad0c3d0b124cde513f44c28269a3b8e733c64b498d0e3c955a5b97284652ea1b46b87a12ff7c5182da147b289fd1072a62a95d0db4c4224e4889794d0fd5af42f773f092de56d8753d54b4273d1918deb10337724d478f183f05a43420f3a104b12e3accde3115a6e9bffb0dfbce774843a379ae2e328c4d9c41ba1c6da4f211273c8719c33420de221c7981c8bd0c4c33ac73d92cdb28aa87d62878f4ad389d073945354d2d051efd988d034d24d7786fa10da74b09cdbde3463ce86d0e32cd6d53dd956321742ed1c861cc7ca39303b99106a46fb5732b7f214f220348f214d77acada12a2c08b53da7f871be7ddf8e03a1fec7f1f886e994cb3f00a1841852b887f9077dc7836c19394b58c8e10725242387dc2e1f65bf0fda957bbcf8b75da1f34191e938a40e0939c7f21ed40d99c1620a8f6ad6833ab6399b3fcce641036c50e3ad620e36749063cdb106edf23fd984c8a841cb6539436a2999918e3468b1a3bcd339b7d170d1a04e8e983777d835b13e67d02e879f634bffb1a61ecda0c7311d379285cba3974133c9b127276bc954173228fb2d27192cb70721640cda9ffe944b8e03eb1431683f9511cc3e8e15338b91056304346a54991761d03cc7abe2e4b8a2068d9d718ca1e135ae20087801062b4cdd95a40f5bbbe383175f28b74d55a418fdbc50bc840f162bac3010240b5e74e114d2c179ac1bd5f78c175c282bb078b105a5cb728e3672723fb6a802020da8e2dc025e684149b3b1b4efb3a394c22fb2a0c5c47def4cd2f81e3105bcc08296ba224c7e4c9e67f315f4f87dc2e51c5faca00751fd7576e122a7e94515348dd7f039de4d9e568efcf0820a6abc6d499983e5cf106721e316c0861753d052c87a793c5674b5468e03300083042fa4a0f48ddb565b7647efc7c8926180f0220a5afb07215b75a59c81a18507bcc615300829c30b28e83732da71e016d993f2044d3c38bd8f5ce9bb6a2728369dee3ace79d104adc39cf5cb42c4ed6d63a4d39041b00d2f98a0c8dcb487dd162ba5548c2c2cb05882de39112c66b6a4c7e32bda69cc805103c6d25de1851234bf54b9cf423cba0a99c28b24e861ee91b2af7c5f3928bc4082ae1542b22fb3d2cf5d8c2c193560b4db11d48f7119d9b7f3df3e62649911f4f8dbe96cbd90972ea7085a078b0ff1df8c2d64d0d80012418f25527820bd4172e55c1f5e0c41ff8c1f6e2ec4974b9b1c5e08418fe925c2479e7214a382c38b20687921058d0f7285d8738c1740d06296ce1c22ccb3a79418590e83ee092f7ea09f7847b3236217b28a91d530cc0b1f68915fef2534cd876c01a3d769c44826bce8412985d2defc93a9f2173c50629945a488ff61b9037dfbb72793574eefbe84173ad0d398472958fa0f3b87bcc881f2e12e4688a1d5190c1a768417385037898cc88f17236bc61637d03d9c5c235fadc92a33c20b1b1c62f6d81a72f72f034607f88a0e70e1450dd4d87f159ffff4d3c531b268a05e6859301e043360d4e0cdc2cd8b192831bbfbf9c52aed281223eb9d060cf7ce1732d0637f4fc5c83a1fbc88811a3c937ef8b72aef28465a0f5ec0406bcf54312b77746fef0bf4e8a2426cd37c9573bce1850bb4cec13e7cd83acb1cde02753c9e8e1f2652b858b240cfbe5149c772c386172bd07398cdd1a754ee529f33bc50819a2b6d8a2186e41e39f6450afaf0308c664a39670c2f50a0f6792b861727503b4c6e2529598e37e8a55f9840ab8e3f5bba484123e6520afd3a9acf31f8f869b731b2e83648a1849d4fe8927c597251d818853a3dc17e24dda5f05144a167cafc7a971de55c8d2d64c0a0e1357e8b8542eb90aeb0677559221bc20628f4703264d987e162cffd84123464e4c0224dfc6b6c21c3135ada4996a1cc62703ba14ce54ee7e870e2f8727798d984feb675d765d18626f48edfdb49026123137a1cc7b1d961e75964b13118866b21030b3e1e6c604297e0fe1acbcc363ec303346250e560e3127a69e7984ddb13f3c672c386253469110b7692fd49ef5ac3462574fba06c424c4a681ddbb90726993dcd3f093d54082316cb2209ad83058d182d9272a64442cf71546f5775920a1324b4309da31cf9f8f38a31f908edb7f6f2d3dc44a4080c1b8e50ec7d7259cacef0008d1884371aa1c7c82c69262b7b87b0163618a14bfb4ffa30f79c6256586c2c8214a126d9130f53b66264553dc06400c6b091083da2e2e4f9d05107bf09c30622b4f20fbbcc3fd08e99372f6c1c420f2c67df449e0dfa1a2a6c1842a973bb89fc7bfa11f21b85502ccd8657bd46ccb86b6083109a04bbf0be5caef72931b288051b83383afe8f9a3146560896060cf72f26083dc78efb7378399e63baaf0884f651dd9e47c390d1570908ed8330c94fcaa3bbf730386cfc41cb1d75ee2197b561c30f9a664b71f2644bbb6f7d503bcba760c1272bae830fda68c7cfb817db534ddeb0b1072564cc6f3162c7b11f3de8b9bbef83858dc7b66cd8c8836ee1c30e997f3baac278d03c850e6c63f06a8ff433868d3be851d8db87d09a1836ecb047a1b3e9818d3a289eb43a864e1132a4f7f4061db4cc31ee76d25ba6dde7a089471d5eb622a4d851725047b4d35d661b9790e2a0a58fb3a2e3f71c744a9d0d3868697298b27de7be3cff0d4a0739a44e31173243bbe1063d4899f37e94cafe2a67a30dea46de68ab8fad4def0d3668fb12f244922a461e1b6bd0624a1d527e25fbce220236d4a0e7c8c6364f9ee9cbca0e36d2a085a4f92ebbfe25458e18595589063dbe8ee3871839ecdde60e1b6750225c08e7518fa40ac90ccb88fd070c2c83962c927cd899d35c4d06359cf9758e236f099f31a821c227a49c52440c9aa7fa8a9c8441bfb7147396fc82414d9ac29ca6ccad243261e30b5a4dceb8193ce668aff782dee6162c7fa0e9829a722c1562cac8b39d33b0c105e57348c983fe84d4db5b50729c23fe5b2eefc77616be818531638b2cd6b16002820d2d282e2e9badee80165b0386f3623183686c6441eb38700f724bbebfc6039b058c2c2ca8d1a1a9efc7e7ab3431b2647495161b5750672b87b85397e1fd8221a3cf8c0d2b681d77211f87b3c9623e461616ce592c63160638820258c44615b4b3cf8cb6cc410e9702b1410543978792381e75141bc3116c4c410f8348a7ae1ce4cd392f3f6c48410b1f272abe6be2525f636bd860230a7a59a52ca29993bf075571002b4ac1283a6c4041cbded4e52e2968a7b49031630434b6d0629d460d226c3c41cd1da57517233c923846169913144979af3a0af31c6f3246160def000d192180d104bdf3ce6d82ec7c842ca9246c30414f9bf3847b98e9ceaa185923582c1a0b19bc812caee8800c19078c1835ae08010c2df022b1b184ef2288c771fa38691d23ab03326460d15798a96143098a7b124dd133731d45091b49d0c3858fe27ef889910563091b48d0376648861c58caf9b278c00162d4b8e2025a60818501aa38401516a8e200551ca00a25545e368ea005e9f062e3ec56e6da086a876579938bcf39b54550642e7af272bc134e4304ddff3ed9c67948f00c417dbf37ef16afd8b208418fde0edf8e47bfab725ec0043682a07b5c221d62aa81a06f7c4dffe1f74f628e1f28c972360d7ee75f2dfa408f3c11b3737f3479c41ee84166bc8e15471ee895bde7395968db1c3bd02572969c3e88e840cfb5115e95ae45e38d1c289bfdfab4039b1c73e4093670108886a874ae6402d2581c0e8783e170180c0629b32e00e31408104080b0341409c5b2280ce4ed0314000447281e382422161c22160e18101218080804c260604014088502815028180a8445e1714024287e2e4410114be70b347121a8d17b55692ca54a395206effcd8a78f56bf4da49d383846a0abc2c2da1662054a2cf91ec8df5bd4ff716d4663b2093c52680fc080dd621f5814c117a61c2c5edcaf263bfd844be25fbc988009570d0c36dcddb95a0c99375ed6262c153edd349c045ef7c1d692108d73bd7bb4cc5980a4d22131e704bc77e60701280ade49750c0f94017de7afe251012196e83d42ab2fc9ce18888db86e57c53040739e3a02c6cc590488c9a8a3ee86c02193dd87b5b2ec7f1191ca702089a79d2acb09b8551095ffb70439823a05f30e64cf08be9b384766eceb2173252013c3283112e2aaf8fd014b7ce29d77067e419304885a0a15bfad18a6b55a1d02ad0becb05592f62ef15a20c2a721841dd905d2bae195ab6e6116960e84c0df3e68e484ef7100bd117cafecb368e8ffa64c742a197d217150821457419352f49132eb5d80e1be28942b010af719419820ed841b958538bdea243f6484631b3e6ecf9562a9283fd22b2dc9fe7eaab4e90294019027ac577edaa1f8484ad9d1ac08b4d7c4fb5d630e8dea580ef3f5a56307b5516513ff5e58d717972063ee348a7440f2595c68aba30164e9380d7929e48a3ae0ab4aee0332f2185d20609c35dcd9340693ed5e3153866303e0b0f4f2c0f5770ed2892ab6b6c6f5b77fc7cd47a46a4a45d56b5197c906089ca8d58e959d017b1a95caa69fd3279dc1bf89752deeb0e1beba3950a63622b0971237c917ec4dd439c78db414cece333a1ce1424eed2f7b79320ce3a71da30b295c20e623b11d109c45e0086aaa4fb0b62fb648b4cc4c801085378406c96f8a067d9e3397210ada4ba6e8389785188440581a4f5506d37a8d18782f86db1f542f98bbcfbf1ecc48f4404f7ed469030848c7290fb10b704af54e42fd640f3a20962386fcf359f6bb3698941ed6923853cd8da29b21d269fb4a4a777875be02a4a723d9ac08b5e76d7d0ca85cfc8bcce8b9e19953daef3c1ac9cb8defcfb2647a6a22e34121c799231fdc37ba1c3b34db9ecf0858f3451f18d1301ebd0f33df5e6e02959938e2a0a9b98c671bd3a4b8c834b5261d5c0ee7e1747c64b6f30324f2acb8fc8266bfc0a481e118f3e421e51f3c5a24b53a721451222650d3963c3f38579162ff9e86830005870191e492626078f455f3119d4e9beece502824cb4b0c40c55b35fc89d1b69888096ba695f7ffdecec363ebb3a8c5a6ae9a02c44830d695dc191181c19ae384d4710c90f7e2f40a68aaadeb6a97350388251dbb04250276f9104b757f59ad58511c91aafeff4fb014008a6f07e0f6a6aa6596e449a793efd8c7a5ea7e20aa5794156afae5b808692dc42d704b56fb384137c64977379a76e269431089307cbb437d7675f4b66c076ab371129a2e7b8ec28e36386c4d58cf831c8475b4e0c4751551d166691806d277dea189d21921a110ce8e901167bf747762ad79d3324acd1889c0a19b3d73da1ddacc917a6ec082c9c730a34c370ad5a29ea431acf08c9fe531c47cb284df29118878a8172703d270921dc4095e6196784296638dc8f6c5a5e7a08d9ce38625320204fa23e0b50e801ec0132006033318e602c94a5dbe271a17522c6b8d16851edebef086a813f3100909fe479441ea8f84ba9125bd565367cb449b5499d347c01d5e6583061013d04b83182caa49feeb1390c2d29d23db8ac746df45636003c56f295e107338308080217438621092c375b0e0662a7dad3c1c19acb42ba8d886b8a39a224f51ad020d7179e9982d6187a4daa0628b9f67cd1973bd5b513bbf18401abf7abf1c9a16615676178ef515f77bb01c5635409ac02915e492e397b039778caf3f9464d45de5e2a0954dbff1c75b0eab86be97bedb5a3f44a0cbce8a04b0ef736af092c1bfef425a55f0f68e05d87fc084bc813c3b988c38993627d7ef0a31e585ff6cf4af8547622ed87f2b27e0cfd81bbd33a640514c65f73f6cb5be8b00f9b7dd286ff10486d541e26891acf2f165197d569d3bb41e561e9b86453ce5d5cccb5859c2088c3e9991856c3cc33469777e95dd57bf18b4e1693a5a824049149a6488bf867624f7d351d4b159270eb2e4d835c8e1071f4ad237b627a5c15c0f045d9e06fb776eb3cece63174b06a3298cf4f1deffc7d4ca4929fdc791376f036cc23e8a251e0e7ab9c39cc4673eb9be09c1d6ccec7a3e322993926cce72985df8ea3e00ef67449e1831ca41dc6068607294db503c578ff3ab369d884f7b667b3cc0d38f213608d7f2ac2be73cfaf6680f4a4ea881152523eb9def5fb66034b505b892d2d0dfa7e18dbc60c1f1aab420154d60011021ff7fc0cd30e36d48ba9be0448e98dbc47a837fcbf7d94cde68c987f07fabb5480afd23c9ad1a15ee8e0d2d68d358eeb4ccdfc2f5cac8963c15e76e77190988484991339d221c978d587c856136d1260e9a26829d9473056b7e6bdf8d52e391202f495d7dcbffaa495ad0898ed23155a1e21309c4bbf46e0658f840e0ab898336be263a92ec82d681931598f4850130305b84f5d7023994cf6d8004be35194a817e69e62b80ff9a51b2b61ab79ffa5ca092cc14c88ff401fd228179cb5fa1e1c218d5c09af1953b16bc17a14a7eb84d55ed59bdb680b847422111aa21859db7fff960e9539a3a6d48a3568ad313ee3726d10af65680e1575a1fca2efb9c26e58b000122512572cbfc211efb65a4bd35d9526866d74a9131bab92ef6b2c50d39f7219999dfb72f6dbc8bafb51d28d65f7129990d4f00777e405658e1d7685709bfad5b07edb3e5b68aad89d4ae370ca0a3a9dab8c7fcd86d39cf907f076b56fd9886a37039265e2da0d71895a9f17e43cd1dc017b32a56078d98d6640d7487a5c19800b812300959861fed99e858e531c23e229115d1d3a99e0803399026872ad5d28a3b1eed4b8613bd17b40b6d412a8e3889359e60a9acdb396252a7a2a7959170a31c5cb44be179de9b9deab9de64e3034a3f06fd178364060ec66c125b4ebcddeb630bdeb5e8bba4c4510809ea07b461aedf5ab5971fda46a0ba8b2099aef401e8fff0b9df91b9c15b4d983b5cc7ca61e45698c4b64f5c391a55ae4586d49ad579314a622c46d09022c29661d9fc37e592f242f2d69764e1040e22c9340af1c5897a0ad053c22d127bfed7aecbfcaf518d4bac4e4d66991523b5f0bd1ad7ea581ef02c6ca327c9b288bc04cd55a7a0711b060b35cbc21af5552caa3b1c5b3cc8d0daf02cb082e2156eb296b40b4ac1994f619205031914e96bab41005279a6d0190e56b800b5d75d8422f878d63ad98a321b9eba8d1ccfb410d06281b0edf42f5d35903304ed1a4d2014116516433c5891c3a5c8a0baf803319089e63742698865f997e49cfb548cc0701cfc908ecfb48ddd466473dedc8c85cbf4c76ff4c89999accc70376e66df37e296611e664287f9b55656a5194377874219dee61cbf757476716737239a99a1a79d7b9121a2cabe72636ca558cde1101af4c6b629d54110a1b0294714e12b1681975ed96e401fa8d25e7a311e00971d3eebb20e5c27debbec469a6b7cd53ba110c3be0a744e5d7bfc1c6624fb871cd3c7cf49aca0cfd84bdb58c466a6dd6f241dc766308fb41d96b289aab689fd2be3b8188717acfbfb511bf4a7be53eff9e3e9c230c38d27d22c4a52e8ecc483823e897ac1e33dbec016a136152aca44a15c8a9aebb233fd81e137fc5dcf8374124177646b5b325feb0f91f8fe881e23c08f6ea543762e7eeb7e6155a589eeed3771d0969769078025cca6e4594705e11ce0b24fb4821fac5257204dfe297e1b84fd82eb910f9ec5152253d266af110b4ec44924547a6181f8a8e3af8be3b61eda8b8ebd5a4dbc344f3e3eab283eac3faa349ff925a61479dcfa9b8aca2dfa4059ddc2a05529a503a7ca47240981bc784697e9380ce317890d2afc771f54bd4119c8495c5e0bc4eb8d03403f5a9e50a5b2225aa579fcde9c75c5dcde1b824d042d7d703078eb6638195abe801a2c765b099eea38a3fe636e018d28052cb75b314ee2a0a7cf584040c3dff72f17dd0e09dd59185342fe86f0fcfd60f50f0781b9f522c1b37bd52dd968e809e6e6a9103ef7ff140df37666d450d5ad5adc0e297756042c0144a4c890af52fd81e2737083f33430c99adb5e500abe9e671812c4c7e393eba9ba21e5c7c82a39b3350482fd9ca646d285750305a8cbffbc1310059e8d628f50f3874ae2aa4ed286218cf7242ce18d3b0736d485d895ba257537571de20e6780fb41f081f10132f5b4c7fedca37e561c1f5309df9753ef90869ff3f23edcaad7d6fd11bae6a94aba051b39a6dbf8c9b74b6830aa89d441fc629257aa84ca78be4c941e52715bcd20398d0219468cf724bcc0bc1b4ca85ac7cf8266a85152bb433f046a415076637fe57838d05da5691ac8d53b80b831382d4af6ce3d320be65eaf38095882930084c04200161c0d4804f01668e40ad6720f11687206dd5fe4f6cd929ff0dbb5b180eb87ede37fb4057c46ab5b566280027dc954d5e846b7eefc8e409ef4c4cbfa58d4691c0ff933c2dd2b5c87dacdde2acbd6341946bb50d509dbea442b3598dec0814098ded493bec25f0ddfe155fb9a72a2652e4d2cfe8ee012d2f7dff6dc83d7017071d83d1858a6ca2af5f2dbc480534a2ca7e379982ce3b68646acc0a1c4e3258bea243f02f3204b1e1114aff857281effeec2610da2f47d8200b10c4df68ec81e18f1726587f003912f354ae05af870b1c9261d9b4d71ebdb02b362cc98047744472611f7328a236bc4c98ee9639978f0053d06464c5c66801266223ea4b3f4751a45018a09a66ceb0a5c4df0600646610a8f13fbf5e3c8a63b86a02e2dea4023ddad1e8e34dde07368344aa6f66e5bdbd55ea7205a12da921a900c282df81ab50d49e10cdf545a822f6b18653cda1b4ae05398a11be479f9bf9cb738fedff9a0f812319c11d514943106774415f415b852011486d474687531961ab76d574c24e001989b2041aab8054fed36d78d312b4af8c33606d29e8d917b5ff75519a40a010eef5e276e0dcaedfeab9c07521cc895c19b03971f0d24fe5e800bedb0ed9d299e0c9c9a18e01ce8084366ffb6800e2ff2b500c958b7a2d426ff2bd45771d4ac357f7560cefac6c385e4700050a08759d511b4f97992de2519a545aedc938e96e97a20c73b27f37077fa4bfcf2bfa0ec93539532b259a65d506f4872ebde5d798835d88e6f1b2042c9b0f2718f631f2f926106ea3e82a0b26eb97197142765a836f3dae5c05bed1b68ea0f9e4011a6b026f60776492f18bafb6acb52f0d50dff6e771a0148f02aa1214744bf2e267cec8e107c81e1caf5d49a72419ca69905897c6108fcf09291912aedcd5ef436cca2e788610ebb36fa2322f0417a39a1eff21a6386c315277ac34d711aa4110f00199cafcac3e800a79c5409472d1fe681bfdbf7a055746bd9ed4be42608983f39f793b41bca0fd8c528d465125bba24a500bb1d91b72d338077ce98b229628f6a5c8a65217752998b8701756866b72d938c0fc3c23b7e22f151f26bf77dfaeffca2fe6cffca9fa36ff417faa07c587fac3fb7efe1dfd0aff00997256b4000a1fae43ce56ae7febc9273999b6df4dce67eb124839db21d4107893d24f3b874e6e80e7407c8a2cc02f03a5853061a9e0b8d5f6a52f0c48c77c9ef40c5af24104d5a5134562a7319c901283f163103e5f87f15a13c5e159029d46b2c1054f22737d89cbc8bc59b06029680b170aff01d86152022cdfb39e1c5e619febca85f875e1a2ff56fb177ab57ab37c03ba86fbd8ab79b83b4bbe7e86cfc4075375befed25f8eb0c0cf4f2f75abcb5ee0cd53d4f8fb24e1dbd73f49e73070b329d6e36eb4e4e62bf163a75715d8f2e882ea11be89e747db3fb9a3451d5e97891773dbdcabd01de59fdd60bd2a30404d63d070cdad54dddd7bebbb596b3b7e3b60b05ac8ba6abd785e83edd715d9b6ed2bdeb567439ba6fdebdcb3d0d90600c66eb35f046bef7771378b9dfe95e062f3276eb126e7f1afcbccbe941546279ef37efddef95b71ee14ece56e1ddd7e62033c06f09efce97b83be0f59d6e1d21451a9a19de5e929b875e43ef5caf8a37e92ba4ddbaee7611190befb997d019a2ae97ef3631a818c816d9d5f0f2fea2f50a7a21bd6b5eacbbbcde76ef63af8a77af6f9dbd71fc4b7f9c2bedbb91fc6e5cc34be62ace0e0365a0d74820c25bc6b573aa2c85241bf3d70ad666219b3a527d3b857165cc06857d0db70cb11e168cdc6fe1efe37bdde3b2e772a4d1ca8974c5ec6eb1b81a371aa5e18f99524a429a318fa8ac19f0cc6e85cf70e5d334aace1eeade860bae60bbbcd014f7b4427a65cefcbd104ff0898cde623bb0f7988a7dc8d118f81e8b4256ce248989497ef88c6d853117ba0bf6908ccec1e80d8dfb01bc3818f78cd9106349a9e78af2a871393618198c641a8b3de6defe96025fc72fa37702758e7e0ccec669af705169331b6bdd85f50eee6713ea499f6b167f8e3aeb119273de9eb05ff70368cf4109ec12a36344d359d0b1e8b0d185364d440298ae4d2755b1f1a82ed725e05968a39b90ee9f5802adaa9703f586be82f714a87f74094e6e29bd99aad083063d739ace72d668294fe8160f5f0a2b6ce9db3be76495744e6c7245f906e624fc78529cb0783310f02d94d196204d5d2efe4636a7e22eea2e6839c0c7b1cf3127aaa183c13ad4512b878915cd6c5dc001c586c6a2c08e46c060359ecb4410c7d895251391b887129455212fbc4ef2af8652c128120fd7ba145b71834b0a00e4965516bcc8c50f2245dff2a651bc656b88f1ca7823dd550e8f85d1b37fc98596468c26be69a07f37e2d95b2872e7c08997d8be28c09fe411221c1222b758331844082b1adc781a453a2178a9434259d609d11a28e5f4dc5c6a96ea7632931c5746f8e2a0cc50204e73f8d4079fd29f82be9a9462af4e8de2c512e8c4a4c6f0651bba286902c157a04e33849976f4e27c284d0287e272c3747c295d09510133566e0e7637f066651f83aece5ba06fad102dfe8d2f30399cdb268faa9f0f4e6bb8f25bcfacc309d3c034d818c8825e198675db81fe040c217e3086a028340d5e0e528cb0f9adfd7e140a9b79ca5169d80d46ee0b7ba4db831d02c78301017c609d204cd822f01f202444840331d8201fcf949c0e10c21574825d007dcc8c6ac7b989b93f2143ae89f8a2350806c76002823a64867414db238178d936dd87fcb127388fe4e7dd40f1e021e14410186c0e2e840c03c36067003e804e18e857b2c396f913678357ac20d033d4ef8fcbc8396396d62e1136de0c105a9a8997b1246a8c1f843a288cab1e9dd4e8985e2b40f95ede8c734a5b471f115bb3abffe63354d73b59000ea0005801a076408b020eb018c04b1857a45b9ad484ed468b29805d7dbfdae70045001b000d70080284b37bea0913a001e6ac004cfb20d7cf01b48844968d7a80510068b99ed3574b80379831acabf314a78acc60aaa757e0349a02a0067800360029c003700990250081257b1a800ad0000200a600a0407b00863ca8a9ef94628e5932624b4fc4dcdccfb279e228437815403cd93279fd367850b566476cb31688146af05551e8f775edc2e5e0136a0b7f6dd979342cb421a1249c3d030363bc9e47e411647073542e726aa003fb5f6daab89910fc0016db731a12c3df4adc0d7bf34446450c735c850e783b487e23b6257652bfd3e1a5d94c692c0452a03ef0c55de2d20a20089c470f5585185a83772f061903da806970198c19d806b9c1c9a036601bfc0da0c36043e2a10eac0880070e0931c2c541408244383cc08fc0596825cc234816a612e6133a0419bcf09961f32b6c3612d369ed0a1b1f0259d3df12665439e5cf264437c226f0bb2e41b6d9bdb60793f596eb89f2012504e10227612a613e840d2b33c66a36d8980f9f2060184ca6ebe4cb9104b918f40d7e06a7816070d40d167dbeb4d119026da07c204938271c4808110c839b034a02ba22ccb41d80c6258141252c838ced100682c080a283990bb25f4a3a6184b0b129885e6315852e19dc0cde068cc164e035d8a6c13e7215bb08b8c1d56065103290548345274017011a98061f83b00169f019e00df80c9ec1dec0131a4cd6eded37be816330e5a043600c1ecb60196ea0b7f80c3e83c671b0cfed666e0883968130c83af03cc20c6b2d76664ea0778338d433eeeefe6a650ad06d7442081b0a2bf7b26b6019cc0d60069f81de203198c76005c3762806d400763042d01b9c068b413e7c305947b975cec077409c504fb8247887304332b0d403399a7903a035b81bf6f65ebd26300e17a67b38b8e5057ea133209083c95abeb4a80543c882b03bb04ee84380165e3a61e3a2b2307e25c4ea819612cb6a50b5de278a114aa791ed99d066f8ba1324834e30d807e574fd35c2c1603dd849701f61063530ec81f9304802fdbd78cc28d839507b0a64d7b76dead53e7c93d33402660e591c6697dd3073be96c0c4840dc710dd6b21ec7bf42218c5081816b8846b04182b6cfe7c6abfbe1e2c93dfc28fd3a01a486307bbfb05f672128013ec08c560fea07b029370432019700f7e12a6125c803043cb430e6e066d72b01524dabd403de89cd040380656038a034c420fe1881a2c079e44c268100c9848c6206ccc029e7744b70b3440b0a6d0013c0c3c0c3c0c3c0cac4dfcd6d7adcdbc05996492d3d03e5508ebba24d39629a5e44de39f441a5167ca13b7ef90a20b3e0b620b2d0c962cc168ea5042e36e890eaa04a7aaa593888ac95644096e93a47b1da249b02f1e9398b3c916fd4882b11cf53befe2dec9468293cecdb593e5a43406128c9d6758fe08de84ac50e23133491a4730b2bff67b4735c66823b80e96a4549f3ce89d11ac2621fa26f97d3c4916c1c85c79d36715a1639228020b3412c146d58c2d523bb9668b091a88e0845276a3a5520aba840cc149328fdafc4107d3642138f194e89e5249085ef7db2a4cea5c264c06c1c7cdd7355a4170a952bcb4e992283a0b041fcbd3880e566db295008293398b49ca740cbaf407be45d3c9d3d9a4e1072e7484be6a2bd349a8d0e80327cdf3aa72cbbf4585061f52a204d11e78b5936212da04b7def5c027bd5e591ae3eb79f2c0b9c93a2a25cb0a428b073ec73f93df62eec099a4dc846c91164bb4d881ad9ce4bf53293b9aa5d481b394cf045d5da1035b72eeec41e5e53db1320736793e5125b33edf2a7260d53f74964a2194928f03634ac558caec24994170602beb85d226e80d6cd612af5cc93d9bee06fea2978d09253a9da70d6c55fa3ff71cd52d1bb8ceb1e289a9e1ed1a788bf9645633f92566d4c09b9d0c5aba53a8a434703aa58c5ebac43249140d7c2e1399b1fc5a058d33f0d71fb35745cd5065d028039bd45c4d59493fbaa14106ce4f4c82b6335db1928c8193dd524ebef99a938a18189d529434794278520903376e826ec8a47bb1020646e8bff760514db3f20576a345cf5fb526c5bdb0c924664cd7a982a834bac05aa7ed9d9bc905b6c3ec735f474f4a32b790b058d94665ec58f3911c1468688135e982c864f23f7efcb97103ef7bec7014a0e9096864416960814d2d9a84436d40e30a5cae2a254cb6b05c41293b41c30adc8a0ca1429355e0a44aeeae1e4fb60c15f82c393b2679e9e49429b06351439a1254e511a5c0a718e29615ba89058d28f06149f449b1a4072507853328f58ba6d913381f25a7fd3cb3d22b9dc07e284f269324a4d104ce6de4c8ac1233a98f3498c0bb5a8aa9a950ea8290c612f8a0354b0c1f1d6928812d31689de4f9bfe41ca4910446b4944a761eb3de83349060e58b9a96fe92a0a1048d23f041a8eeeb99badf46e0d4e5527277c84b825b04766b3449276e6810816b93b32839b35892541a436033a8b74e2767be6c823484c0092583ca6af6b1dec460b0e9979359bb8a27210283ed2b1364c98ef71de22fd890222bcc8367141dfa8237df2bf590a5733fec052b723385282595480d79c189799fb4c9c25d70d993a4b7478b09c2a40beeb7d35b29cbae752ef87cb257caec6d0f175c6a2db16bafa4995b7082494d495473ebcadb82dd944f5fcde3a6a45af027c9f1f2d4346dd382cdc92e09fab45970a2c49cb26d9e8d5e65b260544c4c9a4c932679c782cd5ea2b299c792731616fc5f9f3ceaaaa49cde5770f2c7f3fcd3189e5d57f0efb629c6dc69dd6d2bb83ca61f73b97e3e1956704295d0a7eff45b8959057b3ac850f7f14d8919557019a47890f977e6692a18e5317a55aecaa74c50c1e9283165916ad9c4cb29385139dfed56fcd836de1c6698a21ab74c25774ac1bfc53a3d3284126c52f0194b4dcc1b26ad2aa3e04ecce4891fa46d2e0a2e7fcc5a3b43c1fe77b2cda3f2c70f0f14f96776cd7fd61f1a9654ccf804d73b4a3f5b48b3b3be5829667882cf3e667292c245e5ad139c6993947c0f4baa63c7093ee978176c2c5797ea36c1c74b2568935212baadd3045f2908cda27e1ed7ba4cf0de991f4dffa44b4a9860f427a1bbd16d34275d82cf24c99f6926b304f71a969dec64afafd13c07d231a3128ceaf50d4a4c929c5344093e8eba8c26e7754a8226c1c88f67490a133eb64b82af24c9a2936e8bbdf148303a9b78565996d9198343518e1c7cc283478b51823052d08112842146182708438c32cc8004dfc9e47437717b04a32f0893692b5f996e8ee0e4f26c92bdbaa735c146307aca2e7b5da8ce1d46b09e97359d9caabed1457092e82cf182cecda32a821375e4c9b2745bea2411fc65f1a444ab99a42622f8cf49b6fcfb9d9f3e04e7c12f588ee3bf1a34041b324ff4e5fdcf275808c6dc3b644992a426a58c109c868ad18427a9412b1b049bfc4af7e5310982df18e36ba9a4626e522038f133e3552725dff980e0a2668ff1cdff037bc2734776cc6d52ee074e8a29da6ba6a566b0933e70c2a2c6d1d896da1932767f98c1073eeba25a4ab2cbafde031fc5b48a77a7b09cd1036f9ed5a3e612b4df9a074666502553795a0dfab9c30c3c70d9fc45c9655228612e72ac4cecc0757ebf3f9d2ae536333131a30e9c92aa7ed3473d4154e8c07930f76d171b799739f09ae42e214d6a911bad1972e04b9d2a617789c30c38f09ea4b8c94f75d09f7c03a374c926ed348de8b86e0262861bf84b7dd59777a23ad886196cb8e42b49ce11266a41d4812366ac81f3f04cfbd22625d1a9810f4a4a6e31b865ed581ab8f4974a4bbbc69224e9f230030d7c75fcb55862859faa70a8253646e3193831b59ff44ae357e29a81f3244f4f652769fbb932709973a38ac6d3a5a52123470af430830ced57dc8b5b23f21f65f0d091e387ff188fa76387f6983106c67ce3da07999a536862e0eaf429c1537ac3c06bcc7623c5dc5b93e817668081d39a3fafc392dceecd17784baaf3dbcbe2c20c2f70726bf00a42755abdde05764cf60e3a5656a730830bfc7ff6944e10da63f23e29ccd8026b9a4dd2dadc5962120bc30c2d70e6257e3491ba176664811f73f75329699bb51d988105f6d4e5d49583c7d28db760c61558cb65a95c533251db92608615d8927d2a788cfbd6f72883c78d31a30a7c3c73511ffda702bbbb194cfe98e050433a72a462831953e0dfe4f65c2e2e0fd2bf1418b96aa2544d5dcad1db30230a7cb25fdd4cf96453a33dda3052d0013d28f8c172aa3cb1242d42cc78022727e9d3a2b6a6248e57c68f6ec20c2770620cba9bcda44a98d104d6729a96d82787093398c098ccff1f732651d641e6862561c61238997276cb234d9e28cb8e8485194ae0ea358a097e3fba1a9b9104de2435a26bb44bc30c242c5adf5e6742bea80c338e60caa51d2645cd124c439b602769ed1c05c30c23b0d7f76be1fe6e9efc22b0b6299e2df849dfbc89c088f0fce9639b9ad664087ce7934491d79f59af324308dc99da92fc244f30182f292993c9eac4cb3b301851974ef4a5a73cb9f30bde7352ba93abc6177c99e4375ec9e2e68fe905278752925c25575ef0f93944e9135a6de4ba0b4e68d2a3b3094a74c1f787e79283fe93e44bc905772f6a479f2c5d192db8e03caf5349eae52dd89393d063c24b7d8ecc169c9824359922a3e8cdc95ab0dba5b6b172df9b9a169c261551aa2bc876cd2c58f724f707e15ff275ad031f3774ece0d13a40810e12981861d48fc1a38c06c882fbbe8d232d9b30d9772c181f8bb9531a008bc4b29b2497a42727a5bfc224be6582d0ef49da159e7c63622a59cd5664f2077da2e9ac398eac3899b6246d7ad5ad0c1f377057c197144b52b92296f4d3d28406a882931a524f0ce9c9a42fa582cb5e1dcb6ce38dd98f0a763d4591ba1e2abaf753f09baec24c16edb6256e0ad6838b3c3998f5e7f69482f3bb54cb4a4d273587149c88558799e0a32cec51b015f54b4ebb39dda64614ec987496a56a28b8d4494e6232f9ddc80b28d8ecd027b54575f03c7890821ecf8347f76081111af009fe4dcbd5629027384b4227758237b54a5983e70de0047f9725a65841b34f256d8291163a86e8ce35c1297dd5e0f17fc73fcb046b4a450fa5d2f6631e138c108f79b3aae8e827e9126cee7fca0aaffbca794bf0ea174a8a3b9e4af0a572ca11327593983594e0f2c63b39eae67fea49706eea452d8a9262ad24d811919e7fcd62f84623c178d4d7101b51728a20c1979249ffc494fa43e71ec17eeea44decb48e60df4451a2fe08a14a5d0d6804632926ef8b41c4083628d9c4cf6ab2b4a22868c02218abbc92f4d7679e8e14c1a994c44d72ca5c17539408be74c92ee527c898b70a235d34a54c8d2cc1ef6530b9cb729a68f24a704266beba730f253811619622664af5497160129ce5fda714111e4f46129c0a9e8470b1ce1db144821725df4dec5d4ba80f0412fcb76ec7f44b52df57208f60bd3ee92ddde9691c3e72e828838741418f1d1c30012c02c4115c2e49cea74193ea74231df80e6d04a374ca70bf7ce8c841869e0f1046f09d37476f074f693d090eb51e3dfe068f26431764115c86a693d5493f8a8970a8dd50d3914304990344115ced7dc98ca22f076d72e373d03ed08c0a4012c1a6bbff52d21be87ffcd091a37b203b1d8020824b4a988ab13f49728f6a0b9043304aff88b76e6188c10a1043b09a54a576665b082e49c1e4ec133355b5150a1042704198f6961c3a259db1417059bbbe7b4a86132082603ff9a7206c3b9d091a1d65eca0044820184fcd59baa485fab050122080e0a4f509ffb63e53a74104c81f7ad74d27e3c80fac8e2e557b29ee49361904481f78535a2a5ebfa160f700c20776773c59fa0a9e53529903c81e58cbcd3926a9a0ed4a5a87067c348e12d801440fc9936b437cd5b28203903c249a1853df01081ed85319ab36454bb2575f40eec0e51cb373ccc14daded4c4f80d881edd0496436258543edc7fb3865f8b8d18663e4f85146d681379196a34a929553376e58b209103ab07963462bd14aa7b18e473990397016d59224b8c83751397840e4c0ba65101384bc6c2708e5b8c1831f3a3a073fc6f7b86b9038f023c4c45249ee9cba9101081cf89cfa4c49afa6e29edc486000f206b6a44e49d0315da154d60d6cca6f5fa34ef24d17d31c5cf2029036b0f99e1d4ad7ea081036b09a9d73a865d1c9b2ee9808903570298666932bc858524c1b4b80a8813b75725f729335d9ba8b0b9034b019c2d35452b2a6e97d472f40d0708eb77b42c9ac39433a733a77fd1e6f8098810fd966a34b2c65606ff3e6b6b1cb3565ca01840cece65cb7eec1635079f3fd02c818b87c6fa59fe4741db59476ece851823a31f029a54a297ff02eeda91cf9c3478e10a0ffd163070a7cbc0f159402240cbca8d378a743fbb49f80815182d6f50e356a4afd021b6410bfcc9233880e03205ee0a49427a8cb495da9a959f009902e70c9c642e8d22ed964c805decbafcf3573d01f3b1ab061432d12205be05492ea4efad169729203d102bb514d56ced6affc570740b2c09ed4de963ea655651c040b8caadfb14cb9de9f2f03c81538a11b6ef2999845e8e6060ede879ae1008815b864b1aeb5d54d5a1dfd8e1f8a3eb40aec49ee6ed2bef8bba6763b5670e702102ab09f94bcf1f7205fede4861640a6c0a6ac7f92dce51eccb3366cec0d2c804881b5169344cb6c13f2b1e387824481ed1e252f6c93fc2a323700814295a5f299ec9b82fe06fd030548049027b0eb49ca166ee238d46ef0a0c78f1218fa30ab018813d8bb0c1d409ac0868abb214ddcaf8a291b35d091a3063a729838803081f3edd594246142f529c11e75005902a35a53a614b7246d9267c7184902c3118028c14c777629345bdef4469a6d8f5f9024f0a13b9f8ed1fa242979923b8020813ddbffb3cb5162ced311d87442ababe60f16cc64044e446f2c8effef054dfa02a408eca7b374c2a398203a2270655f7552546915eb4186c05a2a131332e6da8f8d437b7c42cb0211026762c94b9deb1f7b8482c18b522738d4d006fa30c408438c303c033c701b366e945d2f1c000cfe43a5b5b20e8ff9f52f38ad4abad2fee45391f1059bf62453f064740f0ed8b031465b2fb854523cd1d6964fb88517ecc7f64c2926bb0bf6dc6e2d944c7173864c060ed005af795a83cc7bd1b1c3e80a76a42059c16b0e6cd8b0e1805c7059f5fa3b9f20754db8602bb38bf230dd820bfd61bfa93cbb09d982bf6ca13ef7e824ca530bceb6e4e86e9baa849a167c10999efcb684f27716c9cb1a73a69895059b4952e529e717f54c2c1821577bc36df75f58b05a6a2f6e4c32a78cbe82d5fda4444b962bf80fa9d94c4ad20a3e68eaae7553e399c20a4ed05df29992bf56e52ab83777cffbb9af27a80a36a47fec6892782ec1940ab6abb582da7472474ca8480755b2bf662c9d824f6da3593d499b4fa66094e8fa29b4e49125540aee4e29318b8814fc2795a4e07ea26d39a3e0a48da7366a2d0a4ee8ca98a575d99336147ccc9d4bb54cfa681a5070a9c4e49b2c66c7019f60e4d726d5ee95ad4a3cc1a567da942d669a7782fb6c6665ab27d4979ce0f47b12d362aa4e1137c19db463194c50326df69a6034a85025cdfa4c702698eb47ab8e31acc704bfb142d5a5d8da31e7b41c7009c6456505fbcfd9b46f09ee6e74fab4a24af0490a2a968eb9a2a6204a7055e9217cd44cd43e09764c7e4cd1e48a345949f031ad5a6e93a4dc7223c17b5a6edfca7184d04082f10cfbccb83e824d5a9e49c8b89a36ea082e9a581e75268de0f37e0e0d39a6e1298ce03efdc99654052d82ef20ae1df2838f522245f0a54c728da574899e4489605bf55d3c88e074693593e1a5748d87e0ce3a8f0629d252c5107c8a9e6f264d3a31af106c8dfeeaa90c328b0a1182b7782abdc8fabd3e0d82937c7412efdefadf17041fa47a285dd1d43b0f04172bac83ad05217340b027f8757709fa1f3e3e070ef80327e35bd0a692e4dfb61f18dfd357bf0f9ca035babef8dd5ecb07c67e3fb58ecc1ef84ed32c71a407ceae629dd0ea6cca03976a694ce82579658207c63ce8933a560775953bf079326f4e1e3bf075415bc537ebc07ace13c264d01d4007ee4c85bc24733e3bd11d30074edcbcfb99ba7389cc1d2007c6a44d933deaa978ee71401c3821f367d3397338f031d47b8d5062fc36bd81516b4a7e4ca36d16e406fe46e9d63c1363babd0dfc655139aa7336b09b5f25ba41b532be064e4cd00c9d6412847dd4c0ed9858b0368d3189a6e1aad1a059538a0646f7abe468a69d7d39031b2d55faf599c59262063ee53be9a9c93270f92e5959289341956460ff524e791dafe278670c6c6ebd492645ed3cd9110327e231492663270cdc49a75ffd4785d6ea8081ff4d26655a12ca46a9bfc0c82064073511769fd45e60a38ec8a0493a59b9d45de047e5d51a9961b1ffe6029bf44c4de50fa14e8b0cfa4824e1802d701b7a416e4a62d4d16b810dd7d2d5a0d4a3fa59e0b74ec68cd56381cd329d43e465f6a02bf07f23d4da655341075981b70df66e59af02eff6c1e44beaa602e7398f9fcaa5baa1ed2970252fc91774ce13f2d252e0939befae49d923941d057ed3a7784aa91a0a7cd01b16ade468e6543f81f798a4a5e80a9affe40436a81cc3ed04396a4f4d604b9026fd5dc610556202970411d56beda1dd5f426f4992570257aa437ece124fba93c07fa7263b4b6fd24448e07cdf9457d6cafc089c89d9635f68bfef8dc099f4e3ada66392c4bd085cd44b9d729299543880085c7eb38cb17a3d95d60143e024991ac3dcf5da5c070881af13f116d9ddb1da0d069b3b4d544b122a99bac0e0f3424793d3aac83ed95f301a4b6dd46865298aeb0bf662daecabdff682cfe725779b92b2c46d79c198dc21ffaae42427fd2eb8de7a8d9bc41cf27e5d70dfa5b3b67663879f0bb6fb52286d4d2b13c2452687ab7774d12d385da73df34b83d0215b704135a8e059ad5f3ab56094fe7862c7cad5e1a105d79b3a4c8c496eb1ec2cb812ad19c392dc599705279a297b7d54f3a089059ba4c9a99d4c56bb0c2cf8249a9c83da5c7d5dbe820b558d1b9a5f455f9596a0e10a2e26e9275aeb3a5334ad602d6e0e4246f51cb36658c1fa08e55b23c355b07eb209161aac4c7d55b055e9154d253996284a05179a4acc24392ab853def5224597fc4fc10795d37743c70f8d29f8349eb3ae5b9e474bc19a9a955a97b2dc0e29f84e3ab37f7f346f47c1f8a6fcb24b2b0d51709ed18312d326213a46698482eb9875d35510e129a33440c19ada91e6714cb8892a8d4fb0a3f5e45dbcdf3551a5e1094e0a326e7a8edea9c4687482d1267f4c69514e706757efa219f3ada99be0d38269ee9910fd996a82bfa42ab782da9333a599e0cead7cb74d7b4a29c5047765194ad0a64b7051f4653c93c6dc9b50e0b256a950593aed3ce70791277015d3b9dfaec8098cba922989e64c2b95d38492de4b6207b36b0f224c6084454b973ea618367c882cc104224ae0d3c6dd98bf61f1b22e1e2249e0eaa2e7e69c2ac68f3b0eb52282044675d4742a3c3d3b96e050d381c8111825563439784e278949fe79249a8f05818811f84fd5226d4c501b998243edc60e64c5072245e03ce46797e41b3ce989c09d7b2c57f5bb8e3169088c3c1d3ba407e19559171182296d4a6a9d3cc160e36bcea31f3bd5540d0c3e878efae9f81a1adb5f30a226e6d2a3e4e5a04f7cc1e86df224e66f1d2593bd388e07a1f3551c515083178ca66e496971dd00076cd8f8319281448d5df0a2af64f44cd205174f7ab2a4e4ea859f0bd64fa93031b93532967091d037e9d641ff5b30322695c1cd04d9824d266d072bd3649de46bc18d59884a3a87097942b460e408af4bd5b13f799f05f72596a81d43e347d165c19e8e49a93758e8744f2cb8ca360dd629ad85be61c1c594ebd2e9e78f19ed577063fa22538caf2bf8b498eefa62eefa7a5bc15bdf8ea796969cc76505379e4992641b2585f29855309692ac96bf39aae02e3da3e6b849f48752c1f9080f6e7ad544e6a082d3b4dbfd62d253f89d69632c7526a6c0d2d65d36192aa5e0533ecbfa18e3a9b714527099df2ca50b4d8d3ad61805234fbbfef92745c1e8a7fcdca2cf24992443c1554cbe95735efd354950f09f5344736c0d329bf0135ce8d0fcce1ff4045b395e657fb5d4de6227d80dad5c163da6cf0d72822f49e53c2698123d4f7013fc055552faa43de87e4e137c0c91ee55e3f7a5bd4cf02725298e994962af394cf06939fa62ce5c823539abfb9bc9a6df9d2538592a3aaffb54da5d094e4caf59cc4e98a42625383b319e2c3de1968493e0c41c2fea7626094e50b2c935421409fed2e73249294bcb3524f8283672a389d193245a38d47494d123ed118c56b98d1a9daf7f47477027982a193c8b8dce4f2318dd62aa26985785a83082b70e6a774dbbff7f76118cd071d426bdba22584d927439f2ff922ed144705fd97b92fabb458b228213e36f7bccde92772687e0ce544a1ea326a5f74f43702d7e621453df154db04621b8acf427878810bcc953f953532a932c85438d070f8231da7784c0778cb163f4e320f8f85dd194ea917ea31a82e0b2c432319b7725133502c18919eb3ed7aeaf0b084eeaecb294e63a3a6abc448d3ff0a1b2494ac7ca1d744cfdc0558956dad4ea21abb5448d3e5cab9693505e92207a53830f9c784149f28999e3503339ba043e74e4e81f3ec8b81a7be0a44b7d2757ec14256ae881f34ba2bd72f5c9f410d70c35f2c0a8379deef17227f9cdbd49d4c0438d3b70ae3178fa9e6aaf5cfb7bfc40418fff31dac550c30e9c98b7e4a649413de524c90a76a4e04560c346f2861a756037b9e5f1d0bc46a2061df892731aed3625a6fa926ba831074e2ed1823e935392a7a46bc8814fd57a1135e2c05ad26954104f99be92706063ae58d2985935dec05ec778994bdff8c9478f1ce9c68f1c63f0f061e6637dac076ab881d50e4b3d4b511c6a64f80e6e201defc3688d367069576dda6e5f49df5ea8c1062e28f10cb6fb5595693276f88f3248906ca1c61a38d10c99741cff98afe7420d35f0e6f153e70f7da6c54b83963f98c95da28487434dc9f016dca2061ad8f5f73c4998c8933052d0010d88408c305810460a421046d638039fa6c1f394ae92623a1c6a7664780bbed00435ccc09b9cfbff464b12735296815152965de5b714d2c431d420032b4aa7249a244d63e0469352a293a8ba77480c6c98862c952b7b1a1907438d3024e75b8c0103174268cafcbf5143a9260b35bec056efa930b5bc17d81a9326ef49522955638d2e703e5e82974cf209fa9a26d4e0022f9a4c4cb27aca16d8b09444587b92dbf6d402dfbad72b4293184d7a5960c4b3a69493e5cf582650a881853fc9622532c7ce50e30a9ca4a4646e52f95ea69215d850a3eb4e92b26609aa029796c2bc4653f4efa4022f2a8959f9bffd4e48a7c0e54bb9fcbbcf043d1929f0ffdafbbde246811152fcf6ce63ab09322870224b92afe2fb2731b927b021849f20476f4e6053ead89525d9bd046113b8ffbe24a50da1b3dac604b6bd2441c7a44674ca9425307a349bec2564a7125325f019b5945827a6f6932a097c901e363af675d62e41025fd5a92a566a643699237096513fc95fea1a46e0a493a4969c775af5536a1481cd59deeff7a62da72422f07e26ad49efe3501b03d5180297af4daa53a9a9210456efcbc4de4c06834d5236d1434781c19a549bfab972cc5bf3177c3e256faa989e84f2135f70d2552519d3bc54e8d60b4da7355d7a53c40bf69385d0e6a1fe2af8bbe09424692551ab4ed4ed75c1c7743a7ea8a04c565273c1c5ecf2ee8a49d76b0c178ca57d92d49a8eba93bd05f77973326171640bde3cf52993c4249b68ca5af0dd5782b4e0f4b9491bb36ed221fc5930a25373559294820891056f365631061df3794eb91c1c194262c157d0ea776a3308f9292cf8b4a5c96292db4484bc82919f469924ba497a3b5dc1c5de6cababa3712f492b6c0621ac60945e658ec9f362d2dc87ac82ed91565243e7c6dd2144158c5a4b6551ad82d636157cf64e7143a80dab78082a582d2956e7924b424ec17af274310926640a4e9f24b8b929a1b42c1d21a52843e7a0b3b796d2e1c1df20ad64134248c15892547d7da7d44b49aa10320a5eb54f673cb929448828d8dc55cf49304197322d0b21a1e0b37e92d726090f214fa0606c44b76bd569bf2df904fb9de40bbae2f59e4ef1045f923ee9446fd9092e9d8e1e64658db17ce404b7aaf74147fb0c316d82abeece599b2d0e144d70419499942c893542da99e0e434951a2aa568ca144c30e241c52f593de5f3521222e4126ca518633e559324a5d496e0a4a0f23796076d3a2d95e0648fa37247b1e4d53525d8f11c93db93d0bf10854c827d4fa5f6829b982c953052d0011d8f822f03073974a800c78f1c2cf851c68e1e366c502144125c67adfa553c1d8f9748683a752621541248707a8209b5a44f89a15b0b44c82338f983f2ffa09395961447304258671e21930011d2084669e7dd710de2504b3b14878ff6406a0823b8e829ed7470cf95565a04ab5e67d79b92f59bab08468e59a76029329b894904d723a679744f29b95410c1c5ace9c430a143f0258690259fdca2653104277e3206bb52eb5116828b31a6ca9c2284d22924049764514147d7b1d3a80d82efb02b99daad5652b28c10417092ec6f4ac9b182456f4302c1dd88bb496dffd974c90d238400823795597143de7f60cb634a924aaae2871f217de0febfa397e42e21840fbc058fa12c8910ded00d7821640fc9a949348d5e22aac135e89b5c319909bd64f941881ed8f4efe1d726a5acebe40742f2c06d2a7157ed452fbd28040f3342ee1046881d2aa40e638cd162d0610e140891830442e27023078f0c94a046081cde75ecd07123070f0784bc2124c40d3e78f037100969838fcf91019110369490358411a2860384a4010d3342ce7023012166904048194c08196efc6040c8187c7c0e901031841112869010303820e40b0808f142dab1a3078f2edc48fd632420840b3f76ece85180902d4020440b4948167ebc8f1b58b8918347067890fe35a080902b58e1c60d1efc0d4442aa702324840a0a0899020e1f8d6324440a0f0889c20442a04023e4093c38379cd00426f82063093b52034294e0e3878ecfc18724c10221487040c8118c1081902240208408120819428810404082e1c3c70e0f2c0004183772f0c8000b44407e5101105fe4e0910114d000e9052fc200d9850fd4a375f03d72f0c8808f3176ec28c108882e725103041733406e718306882d7c3400a41634406821020380cc220120b23800482c0800020b4e6c8f3926138458f7e504905730766f7fe9772daf63aee0635aea4b0fb6c11f5f0313460a3aa0810d9001d20a1056b01e4dc93ebda3ac360ab20a3e7f7b499fd52dde5e094210c6085e70030520aae0cee2580eb7926f64387ce418e39401920a2e7a3653f6b7b5261f03082ada37c9ec9498478d0e6401c8294cd67f95f2e7c6bb8ece01ea3253585ae117ad2b746671688fff91c3478f1d1ce8c00d1b3678201e2ae8f13f7494b1438c313a073bc8f813e820810d1bef237d8f1224037003482940487120a3380665824cd79b4445c1aa26bbd126fc6e8416871a48281895fa2da3c92c0eb5ebf183070828180bed1a2fed67413ec1f899244553997b8233d56da3e2c8403a6136403801b20946ef07fd298f65f5276982d75ca272840611baa64c60825192cedc3ccabf046ba937ac0f4842f1c5e44e23203c00096ce698efa6b4c97c27fb8023b0177a23babebb2a77d0038cc0793ca12698d81781cb799d7da287d0a099071081134c12efac62daf85732044e599da0194b891da4e50142e03726e9977694c611058393cc73e88d6f25e705189c585265d73dd35fe52fd8cc9dc4bdcbf94fee0bb6b5c4a04cc772a4176cc9cf959bf25c64a54678c1e811992663a72e533138b414c7c82e70441766c3e0482e8a315ea97fd5ef366cf878ef51c60e1f62e8c8d138c4b06143478ec6e185115c3496c7df4cc6334138f43dc7183ec4b061037d0e1e3b3c077f021b3672f03dd07afce07188915b7095da841079d68ecd00099a30620b6e2fb7ea6ee894ced75af0dbf6a3d6c71ca1c58dcc829317541e19843e220bae4dec526e7f2cf8f32c6a3f29999643040bbeb45992e935a764f20a469989b1e3e55dc145d5dffc24de0ab63d2f95b9e6ac60ab63dae09736756567156ab032bb8ad75105db15cd2dfb6a77de9d0a46b42f2d73f46c26d7a8e0dd3a0537559258987b0ac6db43bf6b8c9a8233eb9cb5a4bf905ad152b049e52ae52226a4e072d2294a6a32abab925170f23ac949b997a4352aa2602d357a079129a1e0458a3ca1a3df54731214ac0769829b4c59f519fc043726556cb711ad4ef1045b310942889dd6d4dc7582ddd54e27c59337fe6e9c607b4dd268d2a64636c126b73729b3da3ef465441366a307239960834a21325e05a1a007096cd808c20826d831594a0c59a5e492e518462e6136d08825d88e2769e8efb859c34825d851e739896f3aed37995182d3ac7925b3ec488c4c823d19e36df6b7fe92948e1891041c4622c15b5fb2ff8c6ee29f8104e3754973534992ee7c3e82d349594ccd973989274d8811477022636feb07bd65291b6984d918638411ace6e67c72060f32e53db208c6da2f5989162a824b926c9db693fd5dc96a3092084ec9244f2cc97bea4a58b4308208364cf8e709f3ec594587e0f6c646f52539e639c5105cb0249b56108e14829374759027b5f5c352cfe1a3cf11824d3244533e9994fd9f1a3132082e6a27d5f9d48a5fa97168598f1f3c94302208fe649f6072103d1b4602c1c91b25f2bee41c94d094e41323806075af62c8d4232cc95a1846fec065cd5ce5553298162d31318cf881f352f6a64f12d33878dc50378cf481eb8ba724d9f4bb499beb60840f8cc5d4ac39553eb207764337de8526154e8ce881933f53d2697742438ce481d329bbf6b54226008218c1032773e852da8234d9bb0388913b302a4a87c9ce26aaa2e70e2376e0f54cf6f426f489a1e78ed4818b57c16d57e4a792d27448924acf2bf46f1a8a9139b031bce412d3f9ed43732372e0f2aea7fdcee88d4b8cc4813d3d99d13f9a3c46e0c0a52c8b7d9a72cecee1c81b58f72a5994acbea0c42438f4863137f09e34c4f265cb1a5a0e32c8d8e1628441c68fc161a4200461e0f01fad8113884004e67a9041c6f6481bd8a4ac7793d2cbcb8af7f81c683dd8c09e5af656763d29e7a00e1decb8d163c78deed13ccacd61640d7eaea4d735c9a91c3776a03c398ca88151f904f318ba5dd3db869134b02b1afd4673b0f8a68443edc60e8423686084e8571f19639a888c9561e40cece79433c97eb9c55246861133f02955cc4ba93db5b3c96462a40c9c3e0f66da04fd217b632c31420646271996838e08256b3406364b4ea73b0932e3e51313236260446a4c8fb1b763f51f063ebae8c7beb4f9aec42b3102062ee564594afa2425dffa0b6ca6cf98ace437594c4e61c48817d853722cadc9566a84cc2246bac0e9ab1c5ef229a995c47f8c7081b18ca9d225a5c42475e806235be02e692da166315ae06a64ca12f2a4c8bd71240b7fe5ab984feecf47ff0946b0c0be595576693e93638843ad879660e40a66c3062356e0cb3cf877501a138c5481d131e4c94fe9781f2982112aa08d1b9982d9b01129b06d4a9fe55c524d5c53321205cece4eb2304b82022b7a4274099eed76474f40b3ce82562eb91338a5b1832e61f126707ab98385aea669d23281cf1342f4799a27f9a34b6037a5eb5ea69ce378ca8812d8b437395d5d5012d84a72527a2cfac9ed20815dcfa76485ee9c61ffc811f83856b91aaa937812f120a3078e1c310227b6ea58ce5f5257770d8c1481cb95849e67af1b0bba1122b09e25e546bdae52e522244686c0e7cbb6186d93a8b27ef0e0ec8f3278e8f840c9c08810d8bf1293499e1aa3ff2d120cceab52d0627db9a47c038337693c6db64ae4178c98baadd5b7df03115fb0b9b62fab92072df19422bd60c7b209e141692d10e105a319fab4374d9f527fe92e38a153922767934ea828a92eb813659a4a503a9ede5acbe582d3b16a3c9518c581a6c70f1e22b8e084c6abb2284ae78b9d5bf0d91b3bf589c616dcfde8e793ff594cda5289e09f03366cfca71e9f031f9f831ccd8230c420c35b10460a4210460a7cfc73800c6f818d058029446ac1263bff134f7a12e43efed38daf418fc6e166092d78170f6d2d55a9b46997831b22b3e0c3c53cd5653d52a043053a48803ef0cf811d291091051b33d6a7f292b72a44291089056799b1c4b22406d34188432de19103870f85059b24dd92824eb2939c0c249c107905a332e7d239c554e5903e42c415ecc95499620a9a27a36dd82884482bb8cb4963d6132a4a3f8a39b8b1e3c70dbb80082b38ed5f39e992b4b2499655a4b1df62860653db2e5105b7b9f12495c4ce4a376dea0f412ad8245ee98fc61e2544a6051154f0afdb5563c12bccaae41466830622a6e074ee1af55972be49726220520ab67ad376d29a6ce3f7a4d8b5b67cdb5a1f397c07ff68c70846c10932f79baeec25b41e3bd28d5d8188283831d5ba9f4a9a074442c1a5ea2a1db5e3aa49b11c21d004147cfbe572d1d723221d37ec3e5083d640623f7ce418235920f2092e08abf6bc29fe6ea38591820ef810230c31c220c35b4086ef2011f1045b1e1a636bba5c915d27f8ac19efb7e49276f2c509ae4dfeba8d16dd045b7b62e22951d404a76308abf1f466821f35d3da27bd98e0934cf9c4ac3697e0d4e5f8769f5aa3a8de129cfa6675b76c578231c9fbede46d77cb9d13885082172d5a2dc898d7a0753419377aecb83109ee725413753f25cd8ced4044129c0e2d966e9477d6ca8904dbeb6a996a72b39896051148f056e2bee79c7e049fd3576f64107a53437806114770b1d4bf27cf26d7db46914670779fbfb5a40b8db184117c8e126a648e3a4158bb0846c3432715a2135104a34a2f5b35a713c157b4cff869d9a4fab38c4104117c66a5248f6852c14f120c440ec19a8dd9096dc183bf3a440cc1c54da904a5aa1b3ce8d13a729c52083e899a73d27d6e8fe7b143c710210423ac62129ef1ce20880c82378f7ea5f7714130a641c9ef55d287854920d87c26973a6f9346ed06109c8992617ea1fcd7b23f301ebb43059d52ce10323fb0c952a536d1174cda7de03254962cdd181fcc2798d22066b27be0b4b947139a6338d46eec408803113df0572663925a59eb047507b23cf0a5a4cbd16972c614223cb031d96591d5eb1dd81883129e6b64ecc05645abda1c54dab4291c6a85162275603d5e123359b68e4a111d92faf72c5a96340740108618617880073d761c7483073d7690f1642439109903ef1e83f664d993ce6c0361881186b1b25d88c8814b22b46b0c75e3c09f778a41ba499941fe70e07f3cd3b7c43aff45dfc09d5ece5f274d67f1de0dbc8a302ded9ed5e4752ecb20d206de54da9aa4fcfda2989c1844d89076fa25bfa0ed35f0a27674b224a90646879a6cee22afb3e7d3c0a6df93745d96a081f54c2986d4763fe93e060c2267e0b6c562e9fc61fa352562062e43ee9b92c2c7824819f83826f735f858fcbf5c41840c9c3a416bb6103ad8a78ab182c81838eb0b192afdc6ce211503974e2d57d212cc5385641009039f5f74a9e5f926d31e0c8cde161594ee85a554e2500b83c817b830a947875bf01df705225ea853675e78d0b92e70d2affd45875a04112e304a0ef6bfa9194aede6cf9f1b25b1cc2844b660366e20a20546a3e964927de87d93e3504b4260d2042192054e92d5839a7492e94b6ae22258484a2072056e94b4959f17c44f883844acc049b771ac76fb245549912ab0654263d0ecb5cae6d0011ee20e112af027678cf741bf28b52422536045ddb54eea9bfadbca0644a4c09a9292d427a8a0848969c42312055effad3f69de1c5e8ecea8d430455269281008c3e17018043170305f007313000018141892c642a158389e6b8af403140004502e2456302e1a201a181c1c8a04c37030180a0582a1402810000502a14028280c4bcb15e5012b410b5ceb89042187f93993d85d140fdc05ab49609df91f12296db48bd59eda01b1e28d204fee5335cf61a073de20c10c282e25ccfb262a5bcb656404a527db7e23519dee78ee6b0d65ab3e55e79e4afecc0fcfef5569c172e7af9f338937b00740f9090e959b616007e45a8838a00d700320341a08fabafc451e0a1cfff95108c11dd45e57cef35f12f99236c4e07e23aae7c50fea5e6946110c8f94123bc17b04407bf50d7868c33274b0e57f200ac0ad56f94d9889a6e94049e269cd9e101fb313405600072c9b282ec13365663ab9e517a2860b3d3be7b7159f623d7bed65e04bce1ee79901838ffd334767d19bb4608f6facead0eb0d2cd94fed4adac97caa15c9460c39792636d4fb3e6ea3470fb872c9839ddaa204d0a2ef98c9fdd429d61bee9b5f56b0decd4daa4f3020d44b357bec191a3fba42aab23e575281eac4aa45ede540eb19a35cea860b63ebcb04b4227dd4fbdb03bf1a35a3a7d42daf37bc9ee2ceb731e84d1d26364feb2e7d04f742a8aaa8a07107e12c3e28cb8af61d6a42a10aada10ac12e9b7197946e5f68c201e8408e351d5e9041f909494f6ed7f78fcc71b18083172986c60490da6335046e199dde4ee047a666c95e6b04b2dc9079219213c94e7afbf6481209c4e0efad215414a49461f34d5843afbdcf94e3eb8830f93f7d2846af9f6c2a0088a40ba7534140f909203749ce89b1b450911759d347be57032614630d893be67e42689acf2f8dc6319d170011b7f5e643d0a7a67c7dc9659c48817270ec425e2dfdad8b310ee32bdc40ce7d1b023ea24f93efcf30b41004ebf0fb06bb30cba3ad0e3bf90de6e61e3f522f42deae4edb2f504475d72c1f580fe2ad1910fa2be8c7aef9ec130f7b2fb0df73d58fe31679d0dad2dfed116fe5a0861cbb4bcf30447427a712239cd726147f36211e0c2c98dc1d9ed433d8ea88296d9e36d7147060ada48d28401bf4d94c983eb665637de103b1d41024a7190aebf7bd8c40093aa7d1cd6e86cfc92646973fbe3ead7267412c8f59ba9533963f2c33c77d4843f177ebaa14da3645b5f8de6de6299ee285e3f9bd8a3759e27b40c3e32afad090a97809f2c9a822b8fcb345c13988392b04fd333592c5cefa3853e5a5535e33918ffe8d1cdf398a8534a37b662c4deb3de811f988e9742cb8457fbd0586e46defe885f7f2e06aba6e0a6a0397b92e3563d5664e4358fb6cfb531ddbc12e3e6679bd6029bb781bd0db0ac450e23cda64fd40863a5927dc292c1cadfe0bcd2e6d479b8a6729dfd522124137903d4795317896a9766d5d8d5bdd19e80a090c4f121903b96bacf6ab4966490c7aaca4d37cce3d97ebc330f819ee1037c587b6a4aa37b0ae494e9c5e1ac9c76e212b78c07d3d39151b916e6491d3cc155dfb5f0a85ad8d66982eae830306cb2a1a1cdb9dd16e0cc45fbf2c66b3bb49b06bcd18c660474a2440a30072fb5735ef6a9dd75c705405c6e34495c4db0dcdd95e8b9098012527f60bd0c6fc462d8472a7d127f06b8d8d2c83e41eee2243c47f788dbbbaf24e8954ebe161920b840b21624e94591cb9ad145799c510778b90bb8ea88ad31661e76a1540869149760b53c5cb8d0194aa5fb961586fca6ec8dcfa506bd0785482e50cc7aeef91355e9b655de81c7737a9f9566b18aca1b8e2fc3f0b810558fe8e5bad26ecb2edcfed1af70d20e177fbaa3ce2efc98a1f31bb93538c6c293bcae311df40c56efd4a7bcc31bf36771f880a84dab7edf7c8cf334490fd52f759d6da6825f5d1e8bc1819f36313c58d1306e55c5f41fba318ebdd6185904b99348beb82db2276c88c4b11014631fda20e3d8ef4197c54fb4c621dadc1863e502f45e126bf840230ef22d5e230ddc8d834e733a6996312cf85f6b6225262218ff138e12a4328921e2aee5eecb41175a7c8dae8b5e884bddcea219e67cbb1a6d2a943408d509d6a67a7d233614f576a84d6684207c6c10be23335e553682ae60bdf6af9ce1586947a7f67e55122d97cc167538b84a08be56e3de910a947a191edb50e6668b6f314ba04770551a4e6f79e9834735680fdc0a7b6e79774bc413e1d5cb7ad05938ac9fb28e87f5f94fe54de9345e8718338b938a53fe98b43b8841d2960911ab25938d0cd3687111dbf4fc86cff245b65199f71faaf6b5d1559015e38b42d5f8d53744311308ec26eee79f86a10623d8409417dd4024169ff0fe2582323bddcf441217a57a108f936e168eec2c1383d558e16cc8941b73c113910816788ba3fbb8ef98c56d9afad909232064b8ba20d3339d2389ca05fe0da9f8c4583934c301bc6eca2b50e3c3c960fe941deac60f0bb6a2931322f205934b12b11eedce7103615bd628e8351c38fc03d7ca3575d58e1fff1665a452eda103053653cbf35f501cbb51d3edbbb4748f36a57314c44876a6fc31882aa27cc2be47006918a01c3af95a790a5f33b306cb51007f1a86d07a8b4148c071b6bc640fabedc8f470be4a6cb0064023c38f5c60908eb0808c48169f4b853577a7e6b91727d477dd7deb8fa5d8878f0511762ae3c8bd0634b8e8a5a91c3f4a07416b67c07165085b2078c28d00502a99646dc78918ef9757e45135d46839f481ae61fc188fd77a5e503bca7fd8e86badfd245872dd0aefe4a1112e5198bc016bb7e0752fefa4e65d858a40e352239cca58925b16f28dd5a8aa1e109aabf40787ed27db30ef0afdb5eec62a1f89427cb0d2d95190f9d1be9e913632467918328cf1a9c952b7ca256fcc79687bf49c97e05e18d2e1c93cde32fa57ea0c73306ed22a6b651c44f18221ee87cd8f737dc1709c79441e64306f03869d6d0d13ce03c976dc9a889052ebd94293cd86e3018c99c0796c85700565917165b557d61f0397b9df336f6564e40e0eb8d6892cccce3771d2dc5b0ddf8010f0b26ea59d00f5f88953eab86cb77f67abcfc365485884e1d3f2a0de4769ec6168ceaed12027636cd6b349c16f325be3fb195a0cb8466dd0f7895ac27b47851ac7693a52fbc3a61b890788fec113fa99485240ce5824f78d08a9b411546b072628f74ad1d860c0d9dc12c6957c939fdc1e022698b4a580e037a54913f9a008228c21d609207eb49764af300f20cdf3bb3a4d2205e615dbc4a3ccfad3a4e423c86ce891b1b9df6b51c2a06f74b00070ae45a29ebbae188b1744b5e7a9b79eb868e4725dcb5761998735b77e122aa6c2d114f3f7f711877c3a229a630ff2f8fe61dcefd3efdf44a77b203549772e66db295ba709b862774312807a22cffc8c9c49a576de7202332d78a5e69c352a6e6d8295e6ae5192d5d896fd8da7bd1a7a3a41a0473e017461a4eb8f528d7c3c9ca6ab419547e86adfa3a5f6958080582f2b155d914aa4170845d6302b16067a7998fef993a10c08200d3763077940cf2d40dc283071132359d6b183dca58073748dd0218334536b1fd2d1029fe6fd2cac30407f6f2c988401eb5a791951776d247ffa333def6b19d8616dc1802667398725197a548f97f1285d6d4070ac533c9f37ad8dac47418de44b559d124afa67d38a4fdb8d9bab86cde6e7770919bac6acad02edc3bb522a1db29949a5aed1409e99d03d1610301829a687342073d4263125c8317fb335f11dfc8db34a0d1b29d9288a6745f9ac5d1dcd9c4691a0d845ec6461af88fd90297acb0ee334cec4ebf900807848d7b59128be4d28cb1f26b0de77cc88e358f7050d39c9798347b69d07b4066c04932f0d9a825ec1dc382c205eacc4438b489a840ae5a30b05140f161aaf815950e23e18d54a7b1099fd852a450857e1cdee158564d114ea66265fc756dc48d5aaa75013ed5dceeb3c80be74ae7a7870964dd8b139860381913a50e1b792e8dfd1a60f8e33d47e627ae3c2b52e2f43559d7466e0dae13dc1e0e76e0879706cb46c77ca85be1fc9af4091987f3137e34b17c1ece9f7af60f370d2b80bda2f31423c526c739de0f409ace1b227add63311bacfb91cdab7f1c6dd32013900d0641069b3cea81c1958bcc3c62ca078db3d6a69bff3084cd11e2f6a6d60ccd33447a57a804b45f628ef62de9dc84120cb590b28e24937c7864e38ce1fce84e38442313e92b1904186170deb7d96ead9c4c1b9396e707f687e334a606f74c4236d566be88143d881151adbd3eeaaa4aefee53418c48cd2b983897e80616ab0b4739680fcf4aa5046d678efd9154791a282869c5208e0bf82c9f242787e97f60c258bcfa6ed790fd6680ee067e24e3dc8dff11b637785432e8994a545beb5290ac159be4a34b69dbc1b54d8d48140210070c8765c4d90f53d5df14afae41fa8539316265e7ff97da65aa37a6e7030b45b194b916dc41f0243bc6d2fcf5dc1a5f24253e9f18ab3d9e52a799d6779872151a24259026b700240369d54ccee63eae3dc21df4196291a6720dc5d7b373032156475f510ce53941fc14ed197f19dec70a70299764f4d267bb8040882e9c61026d64adb487168a18f083066c96a6b898a55436a4be71f6ef2c771930a0d6c8888f10005a8b50d162fc7d2a901b0d45c726b65d61db0d60e82ccceb09e9762ae8d325d440b56d7b4760f2ca1452051a3c39776872ddeb30a7152e586b35a4d754e29d368846c3f7201483d09eade2b00e96f59f291f63e7040a614bde8ca343eb1a248f6c455aff6bce4b0bff9806b2b07740d739a3c517846547596dfc6170fb63cb4c55c0f9ef8783d8f483000b495d1e04751fca0568a4120cfe3f9ece905aa2210237427b2876f2ed078b3b1776144ac9ee30240bce096dd432f1a16b1b9b02c02e2372b4990469d26ab805fab27b4ca597dec5efd3423bded6815a5614305577b7511076367d085764c8d599c6f99e3106d96c8a4875334e85226082c94a8b9a651f84398838c54493fd30c56830784da99f86a72bb28234245c5a1e151a415f12ee5563ca96cd3b73d3813d0a34fc8d824bc33a97e89161710e3abd4228b7cb85794e30b426f18ea3414c90a448c2957756f50ba7dbe898675db31f7d3d14099a1ea5a25fffae36f00b7f5e17c3fc21c4cb45b9c3c89c09a21332a9a765dac9489ae25f04a5820f898cd0ecdf08ced45a393b01ee0b3f4ce351b512158fa6c9a96d161ffa01e78e6f06ff02d2d323b7dcb12bda98ccba0e3ac26ac5c84926103d1f89096e18aa8fef93a5390830f9e03915b5c3a5fc9313f37acb8e3fd393f844de1e77c96bf29d0c0aa6d3fa0546fd58fb9ddfe75db22a90c9ef3a9c46fa321f257847a137b231ce8eabed7e119633fd12904ee673243304b6291222906c75647745efb5cd4f634bbf22a521ca5135dcbc34c3c714e086608913065a9d03c8cb98024c546e92dfd1d6eb1c45a421fd777bb22f973f80de3959cd76994b3853a9bb7744faf3e81d104dc6de3b6577060b5fbacf0d6b31511abcc8cb30006b36af1d5bce6e6c909d1ce302736db03cd92c465999f24e98fe5049a21b83087505620b5cd1e36cbd5fab6dc8304905c329eb4cbc164403038a0dfcb591e3b7a351dfee759ebfbdecf4c5502bf101594740817adf5f3974dfa9f03ad4066efdb6d664704557972e8276e953abe026d749930edde307c22c536ce537d31648694fddd81648a118b77cc65a807e4c9fcf2ba7560524dc308b64cd1ca531ca4b4ad9e909feb6e9a26e62b99aa81ad28babf4b7daf439ede0cdacf178c713615965e5b9b9cb9b3fa2a1d4a3194aa15753c997372619614b3b25a9897eee74ffab9df7cf5fa8a4c2c977a1efdd98ca489c08b9a5ba74183b0546319a016bb82c53c8a73daae72ef42b531f5fa1bd9d20c62aa144c6ae2883797aa4011fee2ff788c6fd977fa4d14f996f3c93ab36c1696f02cb569ce9f637d9c13a132ec8c8e7815286f592dcbec23a5c337281a4245c45e903855c983b36080aa94b25c0b47d4eb8a6d240b5f15fb897a680314b30a3526693ef0b5daa931dfc1631bc550385ad7bec4dcfa392a8b98f456cc6917fd4c92caea2eee253047f13285bf23129c702fbca032dc3c2ab9fde364ad0c9d200bb9bf446ba4ce6dd36866fc0cff9c04d319415319000becdbb5a180109261289823da53671b50510af7c9cdfd7d78ff6dfa8879621a00a32892e0a64ce8af9e010080a6d891cd8200adc4fba1faf607df584a0bc4ec3ef4efacd5f96a7f7624505584b8e78702f2797ce13b447e34c02bb8973867d517245766a0d9a14b86ed395936e8c61a180fdbdff8a150294d6e9a29363c1ee0cc9068f37630ee8813bb182fd8b5d17550c3a0df415ba9608fbecbf49d8088e7512b5c57e01077ae1822a45ff416c07a71cc9543315aed39702f42c6f0e486d12e702e298fae6aa55a80095ed3426340041c19beea0db49b59b0bee2830a2331cb2c6f76a94aa994b8bce3934a7c1d664d4f9b7328d085bb666173d6d6e7470febf8bf347068fd331c61d09b704246969ce2e1631bb4973febc65952c65ac5afe376a617649bc59b5775e3b06589a51edcbd0e20269ab985530692c950e651c51586f11c5c7ae4a43ceacc4c455a1bc7d88542dd09eb114d58bd308820b722382f863bf9e2b92746ee7d5052ff0ddeb09a0b75c875b2fd17a69cfbd469c46ef3003bd46f33abed79a5e2cf022b5173dbda055afe3853e244877a5d85d3eab9e1108ac13ead1d11ed5433a0a3a812ce763567bd4c3a6bb4523929e39ef930f92ce161d52274daf898e1925b49c57edbd76f4c2f65e9be472e472abbc16eac5b2d7545eeaeda56df65ab4d4c48b34af88edb5687537dca4ad5c158d975dfe75ac3d759c65f37fe3ee94eea4dfb748613db41888bee0c34f74529ae80f884a0a970689a96921858ee58c84df2d729ec4761b389cf817b96e18fc63c726211fe6917500d7f0cc741e5bb1c6bbde9be9fdf146127b111ffdc48e841984a9fb1fef368e61f16c9038a352056af21fdf4107dda6c132f4fb0fa3a3ab671446408836bd3432652136de6ecf0fabdc1990e828ede313dd225bb47c3cb102ea1842df1fb81c70c33cce090ecfe837e7c942189994c4a212ad49366b5f8aa8fdc713d865152417f089a68b865a5cb174099a8e4de0ecf88e10232e8ca10ec5202968b2ba300f302113e2280796bf4cb9aecd66c5d4220db784878c962fb6fc6ddc802e0fc1ef84bb21913c9dd6502c318af1d4a3ecf2aa3b36895512dfe30d919a4884522b9545d8a48088201609630b8c2c0166d3f6bc5f712517589900357ba0d8c51c39941038eec0ea4390995dd11ef0aab39f23888de7c000260328d38207e7108ae0d8a4ff8a15255e6c0896bf022065bd47b24a910c772bb1b6c634af203dbfaddcc414c956bbe9d4f414878025034f48f1a0d2721370a1017370691e23284d40f94a4c55e7e80ea4d8ee5d94a141a3c59e4897595791b037626ed701855f744e8b69ce40150a328edf77733cf58c837f2e63452c6841f4eaac652831b296408c567304623d3616b98be5d3255cace5f58314c166ee2b96d4908971079e1f9cb530d89cd2efcfc13791350bd49e3f0576275c1d303f2dbe7181d49660355fcbbc83b206852197f97a86f35efa3339d4b00307b23ed6e6491145393012e5c25aad3869724932519e583bc363e7ba20a9973bd601dc2563ff72d4ee482e67b10e5644b1cbc2369e368d2ad98092bbad33573d1789fa46524319e954dee88b88212e0e9baa27f840fb4fc1dc8d718738b4f91c58e18d40843e12b98e8c16027fc14f72b89c915b43b6c0794647bb2ac0554026e5d4dc6d25bb36e3dabc4520e2789f26c67c3a97c0e879768ccfd48a465d1e25176bd9e7dca8ffc8569489ef345acd7e853028fdf40163320b17b3b631bfa4c2a7b1ee3920fd4043b418ab78b8d08023bee8f62ef6222d439b3dc22a07fde2d09e80cb040f85e304d463b421f6dc6c740133f848a5c7b85df8a0e8cc9ba9d7703d05f026ce4f4c2da88c08a98b6776dcf4a5a78281af14a5f9757f74af544821ef13be73209b46f60225ede10b9eddc2088b5a8eabcbde7bd8165e19b733d39f389c598c2deeebfc3a255be17b1548f57c2ec2e13629c445e8c67364c5b29bc5db054223a59788d0e25e4cdbe00a64ac37c29d11c7afb6a1f72c8b93699b4bcab6c8a4dfbbb592826eeb97b4055001be6eac48f0de06698d370f44db0d2bfbe272615901b1505ea591cce256ff0b1732ce79ac0ef1f6cf765de34a0c6a6d3322ea000b9a86a37ea36536356d693d2be6a67be402c0d5c47b85884ff6dc2c9a2d34aa80199c00bdb9b5b356e4826a9662d18d078da4a83ab956636e1657f9a64f335db474dee55ccf5bdd78f47721c933f09d2acc7ff661335ba1963d0421bba8ee311a9c9a70ef00394f16626ca5461d6df59951467434403aa9f223723893edf8a0bed0e4a2455557b0ef7b07e05baa2b0a075db59629824d07adb468208e99c70474441c6fbcb03270f62f30dbbeefdf8dbe5e859e8a6f93370bb54708605871a31de84842a53a1f79c29858f22b8bcc1ae712824fd65635300267586459498721ef2c17ad952dd054d91b1d854f39ee846ca2883fc593ac5afb26fb2e8a07cf0a124821d328f0de02dbbcd1ad200feb480e495e6e20fe5d3e609de552748666e1dc8546b5dd7b096471856591044e39df0a9d6068753c7e9a49fd125890ea45cb422ff864d945dd272fd04d5ce50f848986a6d5dbed8bb38e2ccf2f8d9e2ab1d24f57b3eca4e8643ef751e55b7f785c10bdb9db7fa12b7d5e2c87f79e3c37fc60ace07b5b3b74ec8c4665d31f9c32efb80a6f9dac05ff166c1ce475bae1ab01d8b3c9d81045e18b1931739fbee4f1a930ca477a2177949383944a82462a2265fb15fdf4bd6c802d25525dda27cfa34a2f0945d18dfc8a3460b8647f0080020d36cbb5e04940db199f3bdc3afb2b69bf916b14b4ae4abe29b6d4c96ab35c346dbc01d85333d0493e7543cf9d8f8379116728807b8473bf4bd85281595bddffde3328cdf2e58cdf7b6b5930d9d84a73ea7e639f38bb5bc0a7e8b4d02ac3412d12bd6825441f937397a6d0da4df366c80ba629c570438c4f17f9096decfc1d6d1c3b71f5568f27355f5143ab3992121bfce92f867cfd03d4a8f63dd3ac4334547edeb97dcfa5122f79c0338f2450b7f54b00b6757af6c7c8e5558060458f92ddefa38f9eaa7ba56de8c009ba7da844793f3acdf909000b8dcefcfb461996c95a48ebe7c18ec5a53688a698607f9a7e0ec9b1c4ded553d34452d7da1f9b529c7518ba849ec9a63ab8f08bdfdd629f5a133dc37fcfe938f694fed28271a7953a92dd677d4d4d5e21de4747923d01673f36bb1f057eab26644d132081e04ec3ba1e3a5b233c7336a75e40903b079b5c256625d1799cf247b2e428e7320c4c8d43802ffbf11a5e8a701a86b3e009e0ab3708529cf052447021d5b011b1170ba2c660a05360a7c410f4f749fedee45484441929119728fc010bc4bfdc14d7fb7ded793f8943e151c8e64e3422f11728f149374b09075a631356cea10b09d4e5e586c0a85b6fd51a1be5f693f335c119ddcd72499f53019c667b39215431bd067947c5337eaf88cd1732eb11bf085383069f0499714bdb127f95d5793dbdcd86e100a6d33c680c590eb9b0545deb62411378042ab16244bdc43bf805f27ab910578ecd5225a9d749fd4e31f56b0cd90d874bd99ed4d0569462d6f2492a80e9470b0791354d0b08648569d4687c8dbe0bd4718c59cec479256b796eb5c86d11ec0dbd2abc758d01513b3cb7875efbe617202e868672bf5150b618de59c57e8d1b1c7adfa66f380d8984446c244932fd8c346ed5615e3fa460d2dc3348300f945e3f7622dfede037e2d8f61121622e12776f4f4a81b0b9f248879875097261c08c3fcad13ec4dbb06bb6eb08dbdacd032c7f6c24cbaefdf78eeca6900b31241594147513ea5290ab607412298393fad525c88bfd0dd4c9b50dad13ea50facdba9d7a36850bc4b26eb557f81be003d573b11c3db6fb5fb2aebea2b608f6c86d080cf748db66e39387633656683b0cea33bb23c3176eee48870742b97b1726d565a9a8a6876ef300c2786a4e8c51f6989ad9a7be3026114ad8ad7bcd65ec19fa7fac566b8fc93bd91d43f04d822fa288c681aeff8bcc2d7575dd933b9f9bf744315abed0cb08bf94d9d410641c3e85fd3f1f4abede34877c51901322e5324039694472ce5b48fb080aa6224bea56f1cf5c312358a5394da3d2f3c4682d7982b4c461556cdbeca09418c95a42ed6939643119b0233acb72540fabfbfae748257d814b0568b2e4fb8808c4ad9b3e50dd0c514a6c4a0c6bc1ac22f06dc8aa3d4bec16cca4dd297d66ca6eed2d4107fc9f97500dc9f86ca7b1cfedb3b896d4b1d0ca803e8f036b234892083b52208d94642ab06c97133bd3cfa0049c93285c1b1572d0022ca2fe0ca4a10db8b4f10a8358b954e28a8a491c0d2849d70e260c723201494ab4730b62036f5274801351e1581c501487c075eff27c9ca86b1524284d88b76793168521022b0408f13b81634c0d331c5ae66a46d1e8aaac04bd716888195fe9246993145d701010bce7a8c2ed670dc21214c490559f8fb28cefb3b5621a641f0d11758ce592b89dc7ee71af0f1652ca16048deae07aff30e0174cfd6ba48f1fe496c4d2973af939b152f8895d15da431482637419e3757df5fb4d059224f718d3a83c5b206aeffe9a9727ce3747c147beb129850cbad377b128dec1777d590a8f13c4c309e052062780aa72190ee4b78e052e4a64af465d69d29c56efa191698f7638689de9e7ecdc556d7db1cd186413f06145b3acc085b2f7771851b342149af737a9a334c680ec8d45ac2d476062a234e073992dadf7a8be86869b1f25d680d1e2b18618f20a6713e92162704b36fa066e3ae5292aadc21f28783863057c07d0b4ddba29926e8929304acd0fd976536733741d3c0c87a235eeb2f6c6b1cb0b69c175be3a6b1f70448860a53f5a24bc0629f4554cc2faa459a19cc18e3bceb0f3e08e379609d973d2c73d3a3ed6b692dd911d400b9998cdc5abcf50e25bd6ea8d3674fab28128ca6caded58f1506df62abebe037e0426d36dc02a9467f715890797224514215d368009ea04f1c660aaa150fd1428b05edbe0d9b4f432188156c28362ca1cb9b55038033a61c5c0f285ec18eb03f7b2ffc92a404c1c0a5e6a276e4f2aaa4b0e4e086a6a6a85d07538d01cc14523ef79d6a0c82afb0a03476ff3c17caff8d864af4e1d5a643e8f5e3cda8fe2d8240d0658e42b851795b614df42cb3c4995fd969e8412904495c255425a9f3817d8f94747a896c17a394b7641231dfc77617af56310a8f565f8f8ce50fae038f12f9710afbbe237a13b3edc42e98bc578eda9826f81951bf0182378e89fbbedf155bbc64f6b62df85ac9b0b32c9944d22cec2e6948603317121878925bf96c7f6c8e7d340188fb466c8933ca257953442787baa6a42099ed3ccafdbff5da7f8e65efc76f81ef6af11e31e4bd07d08e0b873eace86049f62fa4ed77b6934cd3dbc94e119952fe8e119d61f37baa2ad39429adf9109b08d3ffb93dea239675405cfe63b1c5482242ae403914fbb8377c52ce93cd9f9cb8b3ea3b60fd393c4b000d9803fe53af806708c1c2f7f6142cf47e1f99b1d97cb07fdb84d1aae946f71037b3828fa1543e5fb82e06a8de643a406648d638f1dcdb3e5ed817e57103d881ed1f7f432ba5e9fa59f934fce77248eb116ff7c8ad4dc5326da0f84f3e630d444d625f54b9db449401bd68b1f851ffe5ecc6679d8c837387105623d02e0cf246a58f7c0ad6b25d6bbea8a9f14de3e2da9e715ea9f4557f4b40793a4f79275a50e06bffd0961635a495c09cc61c7e8e5abf6ea2c8b8c7025d4a99666a4849c35ddf754f03ad28435761cbdf353e3cbf2c2cda07dd7b7d14b6bd899b3aa5fe912fb59ce3b39bf4366f63ebd11f824b07c528d3a697cd2516561cff241721770ada7e314be12a90df4f9727c39e9ead61257bb333f70ffa59718f8afd650615bd9ce1332f3101c788b5f3aba9a5e1198608d97f6b8daae4095e89a1a29e8bb17d49d74d4b73b876eaebfe997ba735ca16a9b5fcabe708ee12b3fdf7780cb5f19c806f2829f5f85baa0bd34d7d69f4f3688a81f252d6c2cc6d56e582bdf50db6d093aab672a1cdd771c4d2ce95cefb74b6e2a4d4603ba832002127199bd4f1fd1f31a2d4cce13a24fd93542f19f2102ac114cbef03021e26df2dd697497207db69d1525d6430d306efe7f62059375d3d881df4387f033577c567fe3bf3e43a6eebfe2d5cb8228e401b936c3cc491cc3d083a4a118ef66b497ac904db606c343759302aec0dd257ad99844ee2d5da3d39c0a2f2540bcfb3f7aa366dba3332fa5b6347db2f04e43e5a1f815d17983a0dd5d7b12eac6f41e3c3ae00831ac28de5464359544f41b8399a8f2f500cc9651fb4fc5276197fdbf4712e13efc8df3290f157e3067e8d725870c3b9882d7233bd7f3f5abdb4a0e57f2c05c0b03aef6e6eadf7aa81eaeb7d284c9f9c45ff6378d97d6efdccea6451a69a866d4274bdbe6e20ef29a34dc0c4337ecdff323383e04da30057da5bb1a10c2123ccabd334c6d37860c13df3290bf84af2e902656fc00317380530aef8f15c517f97b38d4c4553a4d901dfe2f90ebe14e3c2b789abcf58818686b769df325b8f3793681bd58bbb774b8d42b9467a55df806ae7625ba01f63a1ea623faac65c60413973835feec995b468c2eecae957fa128a2f022fa4f6e5d82f3d287a46577a1f2490e3a78856163fc185fdccd86c25fdb4ccb98fef61de0ebc5c26975021ae3104d1fc74b7dffd3341119bddbaa294847c845464200fc73d02602685bef279d0c7d8bbf03c198cb83d80bd22e5014ae8ab77aadaed46fe230f442adf635b8aac9b0a11574372063278e2dbeb2f41bc9a54099bd8dcf2c2419e7ec66c53c4d59052d712f5bf5ab9b68293cb32e6b4b193dd032f1c9cdcd70dc388db61a2b1d46509d97b914a0f4fe4f70c93d867fbecd46929e0edde64c0b6fd11b7cdf8dfcebc97334fae24f44b91a05a572583ddde7fca4a8953e2550e11428ec24a4208839ef95cb98e8b901a0e61931b03e987dc5934d453932b343802a46275f8a8148d519bc9a0190c1eaefb25ad765f05ddb989eda2b36f44da0a66d2f09d9f07bc79a3606c00e3b88a08682d88b48cca9f27acd0a7e592cc809dff3a76772f64a01783b8861b86319adb44565aad94a07b3d5520869cabf792bace920f5ae572f8235b00519fdd49f75f90fec1f5c73b398c3c4b0c815752275098286be4d9a3bca50be701029428d38f80283f47800d289cbeb4a07ed1bdf628d32933e5a8fdba1827b65eefad5b87fdcd16fbe732227559a8bdd14618a42383151522ca1fb1903c87336ae0dc8bfc9d50c4ec9e02d7857a2c122ff5ffd7ee5b81a1cfa69e59483469f1fcb59988c71f0bcd23e3aa8a73fc3e808651f992b655037b13051b469c96c15af80dd488c9fb75c5139d4c9cac1493070b54c919f23026ee11496cbb6af7e90eeb0f9da6c1a577ef83adf8abc4b317e3d11bdb25dccf7f0bba2ab3d47f6f6d6937413635e9a7328b8bee0d245cc9717e5f5003227e0a65335be2e39ae2712b84e108cec709771bf5b368c6ec7c049f61cb8e8c12bc8ab6b6cfcbb59debcf593a77f8186bdf6808d0306551dacac1bf89a1b50fb8d505ba5a2e5bc801864ed80da3c703ad2345273f6567cf5b77993709c765a27849b8a2e0a14e31cb1599a6f132213e0db39dc7c13955332373cdfd42eba37e2bfac33be68c09d31e65759e78b5e2178b9e576a62e170f19c5ced8f489a1b6a407e073957a42598319c98a268632fa3d1cd140be9d2240eff48ec3c99d922f86e3ae1483212233a1c0dcc07b50acb50c91a3c08228358f45d782d744a810f7c92433280059afd778129a13d4e2f7bc54d67124b98e538a2539b2477ac17c64afc71b29cb173f3c5f281d748a5fe1f3d1f8b71ddd7a9eb9808104bf321fda754b4c2c34c605436ea01f3f76119c917712cd34e951e6f74efca8880363f1e93865c7f57bf9024052e2af95d9190cd2599e41b7519f7b6d0ac5442894a88ed740819e3ac7c7b77602e62d6edcf4f108ac61d0f40bcc058c1c238f6e145dfa0f2ce45eb85ea8e054c0e2f74ad9c55bb39c7912e462ab90bce8a4930a3d0d2b96256964286f4d3634b45548e6a3165f61ebb896d3e3da091ce4c1706b383dc6ad3e3957e1c9d376990e9b8a9f75f77c41f05a596f789746ec2f20a08bc38ff3f63d110ba1208126c6c73c39fdf0a6cf0c338b67cc16add107599c6849dd1433908c6cf7e913216666bbcc9bb46473bd32b51ead62555ad87e2ab16490dfb4dad823d6b89c63309d8dbd46e99f33f15e82f71dca6e5663877cb986ecb932d1de56f18a687add963561c17c40871bf274e40396cae2b42f863453cb901dfaaf01a489a1fc15841e494df904c81f494defaf090af7139ba1a30f318a24467b1fde36350656daaae3c835386c9e9b04a2b3bd646420c8dc00b7834d0e96d5613cc41bba09205585e669b94b70c6e17a10d1f3ad0f3fdb121f198276a5753369856f790042ee2a336ac846f4910074640f4b2693f402305b498cf144a4d2f8b4fda9b54b9e355e744116111b1ac79e544e86d6544d1dc702c801787f7e1513c3c058642cc3c814a84456e0206a10e205950738fd2ee2225055bb532f260dc78e278927ca4382ef05af1184530fb109a9580c7c24838cebcf05fe42f10c6c702a61a3539f905b8c189ab0c18600f00da32b9f3c1776915212fc28266e04dd0384f548a290b2c108208a5b3502df4eb3850236fc4c5b4054eed48c888cc7c838a923f19d27a961beb115d4f735a62dcf5a6d13e14b4ead17024f837162a600cc428fa252bbb6022a0049fb800953598f9aeb1f488c20a413b036683db29ef29c61d02e9dbae454d8fbbd76d4275e02e8ee2a8e6d24841b925743b95e6c40fb526a3b6f47a9d5b424cff569758e0ae1b1d216b8219e5bfc0b4cdb78b93e2e2cf0c0c48158ba293e73d94c8899acd1eccc3c00f3e56e4e0cf910c589dafcc03b17a6a86fcc7ae17af6e0052daf8af4a2ea2fdbdd7c53dd292796eab60184f9a48f548eba4641843d963e749b5abf3996ea49b452a18bce8634fa7e204390bd9d6a5e868ec46024078e61e7b009d5ae213b50144e43729871eb88189174131a167f57154e8f500f3a88fbd2882d6d1037051b1f5857271852998d4cc6ad25f480e48b39225f00e588e2d35814543602dacbc3993760b46439330f0f0f0f0f0f0f8f4408b7b60642da169220934c12709a62d0c82499924c2945c2153b10b2371bfe226df88bb4e111120004a809b60954097e2e9b9894d64bef6622f8f89fbeaab288e0440973919512748ee42118d5f14b9e56baa934046bf23fd7c8bcf57d29046bead3065d1a4270a7df6b3a7e6510dc9f79ced17eaf3c5604c168ebe451f5c440b0651a4229394aec27080826e6f4a11bddf794d21fb8dc7e79645091b39ffcc0c7cd6ff99fd2072eabc4f28b1bbe993b3e304a7ed2ce31b53d702332e99832c60d3aa62e20850e3d247a54b209b1abdf151d79e033e76e9f3ceaa74c78e0aedd76c42c7d07eedd44478a7442a1c30e6cd24df71eb3eef6c460243aeac0e8a41954d2f8aa2f163ab09ea4e7a76c6ab2480e9bd03107f66f6352bb79b6194f28fd24bd35f552ba858e3830c24b5ada0b716bf5140b1d70e0920c6d2a395edec0a605e9a96336154bc4ddc076e477bdaea30dfc2699d484984636b05a952309a1295407915c031fa228b3ac4d5ea1430d7ce99590db22d8479a7c816698a046165c183b1d69e04430fda2a5732b59850636e5ff52dabe22784ee940c7194c2e4aa3fec7e0191a5a093bccc0da298fae9f2287ae0040091d65e0b74e86ac7531ad628d2f96091d64e0be7af3f84d9041ccb278858e31705ee14993ae6006500a1d62602c69d276a546c7af182ffe863942471838538d1194de2030b8eaa9f53b47911e1a5a37b4701b5b58c7173839b636f13a99a660d3d09a800c19bfc5692ddcc6164be8f002973528cb9afa2ee652e90213cd544a5a636d71a3c8a0830b8c656df98ffc696899a0461643e8d802db9637a6e99cbb337566bc16cd0531217468818b9a1f723c8e97c814d40e80207464c17c72434f475f2c7039263da6d2ba4c075d175760f285b28e49d345c9f52302001c74588157dbd1765481bf9464b092639b35561d54e07263aa51b24fd7990a3ba6c09f893c955939c6a44926e8420134bcc8c2031b820e2930ee934392e6fcca5eb14581dd7ef10832a93a6d1d2830a92de99fd09427b0e19931b6a6886de23981976016df57c5c494d6d1044e9eaf7972c99fe960022bfabc3372d6184b550a828e2530c9447c517a216372130dad2e14031d4ae0540af2d276356cccb8b1680b1b3448123a92c08dda16791683b64b161a5aef45165dace064c8906146e8400213dc72c62da12a5fad34b4bc682fbea040a22d6cd0c00a741c81cf3e52b724a6061d46e064a89f529db3f4655b78e1c5df480a741481bd8c599e73482764bda8ae00e0830e22b031588cd99284d0d09af12ad8c2c68def22cbdc1018b3344aa387ddf6c408810f539a829f655fd0c8133a82c08646fd18fb7389681010981c299808d2528a12b1fd017b155f744e61f132d34ce8f0011729a5587e0e7949653de0456e322969723a840e1eb0a1156ab3b492ea2b848e1df061229795ef46fb5f75c05e30fd26297516858e1cf8d515aa112d2774e020539f3721ad4517cdc577910de8b8017f693fec53d561035e82e7c7b46fd6a6fe0f74d4800b2a82d27749fd43582cd041032e4347d698d3fac68d093a66c00575b2e27a0e49716441870c8c2316ac656526653978e70d16e42c7642e634b40c72bc424d93f2e8d15cc1e5c632215483686879f137be8b56307a938eeb26522c8bc9b72d3858c1c78e393d2b54e98edc2ad82d993d49f34bbeea34b44ec0a10a26694fcb885e961d8023155c081aad5f4354b0f9ec533ad1d77b0d1ba760dc74e759164bbae427430613384cc168ae9462f48a3a5182560a6e73f05c1da93c7fd0719082d1fb0fa1b59641e48a718c82dfb4d737ba765ad20019324c148cde34939b1afb6a2ba16043cede97d4a6855c1714bc59d250e215a2c8f13ec1295753ca47ab7e7ac98681c3136c109d22c9f3b213dc858a81818313bca87893d488663391db049bf37ed03b99e1d0045b1b62e792a124f5c7ac58173832c1f5f9bfe8eb16536d16810313dcc49c543debc8d71cc271092ea5499b3cf9580a32ad21705882f5bf0a4ae4986efad29560824e253285f429247d29e1b7490b765a5426c1a694f5ce257ed0693949b0f6e6a696af4d4d7d91e04f2f62ddc71224b849f69533a8b3cd177f04232c4fe868428e602c9d6fb808e9ddbe3682731119733368d74d9f116c10aa699b7f4cc58e2f824bd52127ab5ad4c92b8249e94ca51ca39b49cc268271cba147969d56d6112238214db38a568b55e21f82cb1075ba25568f25b9214c6a3aa29e489242b041e4942da7ac9f7b6942706a915375064b27c71d049343c65c2f2243da4a05c1997c8b582a8d49896a2050ad512540a44a9b4889932b7fe0c4ef42cab9347ee0b73af77bf2f1f217fbc08b88192c99ce072666f55411fed903a7f28ba68bef114b89f4c06627f5131e6279607325b36e0dbaabedc6037f7e514b345ed2d3d51db808fa6ba37bb56b291a030e3bf0e719218dca98775bc251074e4d889de9ccf72c533ab041582953ca53e988983930d13ebf861c52c9905e0e3930724b8b03a3e2c99437a44cf79b84031f548a6363da1bd83c39998eaa615bad1f81c30d6c88419a92a939bb841c6de0bfdf36dcf7eb2d651c6c60f37f47b13bf5f821e158039b1b5457a8cc0d42ed345439d4c0a4fcd3bd74a3c433a3ec091c69e07254b7b3131f0d7ccc794b6e48798d2c4ac990c1451238cec0e6123a57764b31d794190adb284a4791e00d82a30cab57a6242dab68b9d4aaaafd74be105bb33cb5eac041064ec7dc91904e9f255d4901fc81630c5cf27ecf331d5137e60f38c4c088aeb3d2133f258ddb488888887877777777676666666656555555556545006fe00803e3b944d58bbdae05170c5d08d3aa9efdfa02dbbbe982889f953624993c707881f174d61137a56069121a5a356c6829a594520a22222222e2dddddddd9d999999995955555555add14401a881a30b6cdd0779a6313749be891138b8c07765a6535f2d217c1f706c81b1cd924763ad05fe5cd355a64f22b59959e0e4a65aa78d6982d48a030bfc87121ecf2f7f053edf3ca70e9ef386885b814b2a49f64e2a3a9234abc00913b92742ca39e6272a30f6395a293ff7586e4f819f904452217b8a14b894354fba489e1dd216054ea59560498550275f82030e28702b22afeb3f664ea9d1d07a021b27f9b928ad132c6d018713d85431e435ed3a2d93c990718109740040101c4d60a4c52c1d64bee49a837b430b6f02071378dfd3b9743c75043b97c0a69ca89d54489284bb1b040e25b0153c527b97ea2f9d01024712caa732f7c5a1c081844448b09c271aec25701c21edfc31159612388c80c43c6f091262b4a5c05104469767c564621281cda6d3e5f9ae8f128b0c193b04f6fe6bdcd3edc520d70d7c063884c0e9bcbb9d20e4416052d84737b9ed92b473010710d2a684ce1cf53e3f607564af859aab6451ab0f18bf7819f288509e37ca028e1eb07b29ee4955c9c103ce5bb495e6f0b20817af2be0d801632266c5f7fc0af97b0e1df0612542c5bef08a046dce3719f85c1d3d35da6360d472f88f8e5e29d26260dd2bbabe47bd4b6d187851b7ca165330f055e1498ae7d98847bec05fe7a4fa2364558f395ee0df32d32dcbd3e82975810b4a25e752d7d10f6a2ef0fa41946be64aa9edde0293b3d6326676b5c0f7af258d3ecacfdb9205d65fd26be54abab4e5b0c0a691253188bc6d27b52bb07e7afba332c4ff245a811fb9b1720ce9825105ced4d3754fd2c2a0029f53cc4bebae5919c09802a33153c90a5d39c5523252609295e5a4de4a2ec802461438bb48e7e11ec3430c80010556a2df88a463a5274a0c17309ec0097fd79228292b8d4a0b184e60bc728fd0f53cf931a86d6c914501184d602b55e97c91241a5a3366dc680301cb000c26b015f92b628abf04ce5208517b2d4909ec767d4a16e92544d1a1a1578f6c54000d8c243066a39be19693d226b2e14529a2001848307810a9f65e4d787d04d6f6339bce4976e93a69689d2f6e1881cb9cfc2ea938ea193766a0065a00a3082f80410416c01802d7aaad41e6a4934aaf3084c0e77417a9a73345c8de1637b60b0564210046105200030805e307250361f88051a62b278da634b4740b183de03d33dd8dd066d5588105c81560f080fb20ec63ec182f6c6476c08f2ce5412711354795349486a3e08b195ad8b0b1851a063a1830812d147ca1850d1b5ba40a60e8808d9aaf52bf763072c05f1e1115dbf2c97c32f5c8460d3ca8022198d1001838e0c254eef5a42b86b859ace1002b1837e0d534a713f97f3b378a11806103465878fc1c64e4d03bd680939c96694c253bbdd38089a73178a949d2533d03d6239bf6d12682fa88c190019b6cd3d64242cc2926c5827fb50c225d32c182db5499e259753cf3ff0aeeb5d54a8b974c3d7a57f0bf35316d79752ef9b782cb194a5ec6e897d53e2b38574fd2625756d2e0af8213c9fc821411a982d1591777630eff18940ab693259d3b28dda5324705ff964327a5b68a9df25370133f461dbded0832a660646534b10a31a4a839a5e0fd3e76efd8c689e721051fb2489e147293e84c8f22213778b6585e8b828bdc665f1b27c511da50f0fffaa79d5b50b0254f86529a317f5b3ec148bdced1354dac24349e603d2429493188f4e9339d60256a36b7d6d02f9b139cc4e45d9eecb4c78b6e827f4f8f9643ed5f5faa093e799bf9a810f3f529137c7e1759ea841213ec69f0589f31e4cfd9bc049f431ed312dca5ab67aea045675e2ac1a7b4fb0b1a546ee99460920afe66428293e0a4e86d176591045f4a4dc34b55f64f4682895e6a2dc71c735011129c7a9498cbbc47b0216b5efd98352b5be7086e6d35c7e0a335829d203763041793dc98f72eaa3a69114c3a6b11e999f32247119c4c9fd46a6e2a118c755232d52521829469fdd9ff121a5a66e6106ceb8dd2af219488ed1a82b710a38d67d03c22a41482ebfa98a161840721f8d488aa5d29c91c7a1d04d799e9544e5af4a5ac20b84b4252b02fb1cab23d02c179f00c49b8fb0a080f40b06982169d5e3f7ff0f8031f648b85d09af5f0036f1f82bab01f11e1d107ae4a9ac4c949def59beac1077e4d35489aecf5ffa94278ec81d159d1844e2562c7cfedc1430fdce90941956bd6ce4d0b8f3cf0a6d354edea453c190088c1030fbce853b56926f284ac310078c1e30e859c44f2b012ca62460d1bfa5ba008d4b0809a871d784fb94453ec242dbd08004df0a80363f9b4d74fa2e8790c1d584d52624a692f6e993c0b1e73e0f3dd542e1d245534150b1e7260a4a5182fe7d69c8304eb0c1e716063ad774a23e4dea60e1cd8eebbd4316d87f6856f603fa4c57c1dde99dd74039fee25d5695687142766f068037b1db442bc14237b3ab181dd7a49793ce9785bd6c0eec91fa52d281d4d683cd4c08ae5082ac64bbf1b5d1af84b7252b21c3c6faa4e083cd0c0669151d4bb257b699186560c3ccec07feeae534aef28d10c1bc8cc071e6660b3738f6f68e5609d7f1918f33442d9253931dd6460e47bc6133153caf19486d68c31703a8baebff1fba082e4c5c05ef5491e112d7afccc230c5c14cd9b3a0d067663f68a21f6d60e3cbec0e53a952b871ad38d280dad193650b981871718e9f993d05a39a7a0f91728e8021f936648aa793c85e75117bd822c1c787081dbff117af12628eb81c716b8effc119da2b9fddd85172c781b5a60334a905bc2dd327555038f459f9f58468ed98c1a36fc5170a346046a580003f0070f2cf0a9496eda30d331d5bc02173bc99327575249d25b81ad5cd3759319fe7e55810fea924e6f2d15d88f94f29ee8af51ba330546fb538e933f2749504a813777c9b611c745732cd0048f28309652a55777a690c1030afcdf7da7f1d45b4a795ff078427a4ddfdfbea75df07002bbe9a7c73e53d362cc3c9ac086ae12ebff8b9be2e8091e4c606367d055e3a639c7f412f89cfd638ac493a42eeaa104c6ebec3655a3789da6021e4960cbeed5ff5c73acdc17376e645124e08184548ca22cc918b38805051e476043791042f5e7a02e6cf877910123b03184d43b19a44b8aaa166e630b2d0227515378c698f5a6073c88c0a54db0d4956a77534a430b031e4360ccd45bfb7a8ea75a4a010f21304ad4724b6d0c083c82c0e7be9afc9c6ed2c882e602089cb27611caaff2c63d7ec0e5bcb6b93374bdbd4a436b468dc0c3076c7fb9c5696222f0e8819264e9e4dd21a9e8d3d0eac28307dcc94c4ddabbe59a275fe8073c76c06871315192b4e96c86d7c842075c0a3ae8ce41c31a5fa419a8868d33a3055d78811cf0c8011b414b24cb7fd7a44728b031e3cf0c1b5eccd0c2c6ed063c70c0a994520c11b2666a33feb4a0b9d0d20e78dc80d7a4929a982c6afcb752e161033dde05ff06e1510346a9edcaca1854e9ba2b30070f1a30a24288bbda66b7d9cb83c70c3895948974a363d28f6079c8804b4a899f759069f3361932ae23169c6b90db171673042d2c38db944596499658d17e05f7ed923b66eca4db4d577029c8b210bd26debdde0aee52a7bca7eebe6296ace0d294508b1a828bea7115bce61cba4b989e7a509121860e5570ffb515ccd6e48a1da9e047c57deb2c3a968674a0824b1e4f26353298acdd3a4ec1b6c71862dc3599824bb6fbfef929057756aa74756c3dd59e14fcde77a62b9decf1f551f0e3a9a47a1c656a37a2e045976e5ebd5c3aad1d0af684461129da939e3428d8eead78a557d1d7329f607bf46e79283dc1987d129a41e73ac197d0d1fa39ca09bed282d2954dc69221b609ee3f59f5e4d5ff136982d3a4428a91bfca049762343921e9a99027d28109465f758c6595bf0493521219d46b869c5b82532aa8eb521332ab852aa108d366d52ea2043f394f8ee9333e09c6cbb2cffc96049ff1f2730a514f39ec48f0aef96a4dc8b3d424487029c55394468822fd47706d99ad4143a4577a1dc1a476ff2e13318bd8db08ae63de74a5258611bcc8183989b06c8bac2e82730f42597d5415c1018a8e1d2ad735ae54602375554e499a53e0ab72a37ff5c4189502a74ab495be90fc92a94481bf9c257ac3ea74560f0a6cc68f9ac652824ecf13d8a044830c2ae60446df7890c164d2009ac0299d24ab44697c8f1d26309a83ab08e5fd123825e2a5654a21746b45099ca79a70cdcae125c424f0a34442fc4e4202abfea23e0217f285e688904c757d4628c1008ac008899fbabdcedf4c44e02b7ddbe91821768e0f81bd6ca1b93327a54647088cce29920e4241e0a27f48429dcabc881510b8ea9427c5cf2126d34407f0035633d48e8ac498e3ee007cc087143b6e797c8b105403e801a76bd7f7537678c056b42a91f7be72657b077c28b3ecf36c75c0c9f3dc544d9e84e99a0336e9cdd18409d3219289032e7f8af9dd4e4fa4eb6ec02821a4dd8e0e3169ab6cc0ad6f083a4ba7067c0679cad2521a30a662ab6d6be5d42419c00cf87051dfdb5b2123650032e0ecca3f47a62f59568a0537aa52bd75768f758105ebe9d9e26ff0155cba27e54127ef0a7e257fc7cb296a052341cf445df55552102b387dfad974e2ab607356c931955537c88f2af8a4632ea9559d543021879224d77c458f50c1e9d4162aa5a4bb4b7b0a4ed37dd2f92e798fc614ec050f962d5f5d0aced36ffeab9c149cea38da64fda80d77149c92af17224657146ce7abecb9a550b096c33ca84eb9bf42a0603f5e86c631cd272c8627b8d14968b59c329d6054aa5215d45789a40c27f8dba0d2c5eff46a2837c1784eea473497bc10494d70932ce608fdff2892cc0413b3872426784b95f7b5339fc89272094692ebc4e0fa31ffc9127ca43f759b7494ee7c2518912628d1d0d6d2714ab0b146855a10d1b36a3809c64f4f7f85a4e9238292608398e428d1bd48f093ba762d7dd0966220c1063fa9b9d4698fe0729b7c5d4bcb619f39822dab5a4d31e41bc19ab24e99397777598c60df749c9094b69876528b6045b5781c91bb3c8ae0f53c78acde3a8d27824dfd889fa1fafc438860eb9495109e94a5c70fc188984829a51412c3105c490cda25a9f6b491c428049b43c7f6901074ff2284e0a3e68f5ebb97e207558d2fbaf0c21c20c62058bfa0829ac8ac20f8b254b735519b636620187d5b41a45229e54e16200620b8129664befbd15769d25007c4f8036fea296d858897ce263fb025b3064dd155927a4e1f386d799193a95b92a1e5039fd59227d12951b72b7be024855e6b4ffa828b1935b2682fbe0b527ae0f3aab2b4e5185492280f5c2e2de9447d48d6b7e38133c99f4a53fef22bfd0e6ce4bff4bb14836ba8edc05f0ed282e748cd7b771db8f1a819bf364307765584c6cbf5217e660e4c4e95216489dad44be5c0e58df5397554a8d2548c38f097b4f2440a318d52a9187060734a9e9c4e4571f53d10e30d6ca6d320593d7eb4deb8814b1a4bbdd66b7c4515a30d2523530c3660f1255fceba3eb135a881b5bcf471c921758e791a5aab31d2c0c61853c8d7579df5a91a349c3b6ee9b6a6b36bd5821867e072debd29eda14ef54968c430830b62940165580c32a81631c65019882106ce44e7b8ada12cc73ad120168a1861e0ec64b9da69cb231e43436380210831bec0a735ef4ad125777304c5f002d71e512fffa95cf8070af1418c2e580c2e9c0c12c4d80293b5749241db739c2cd2025bc182cc74ae6781bfbfdc5d971b2cb0212125bb9390185780410c2bb06361c95f2c53aebb1610a30a8c8410ef4d086dd39753017d35b6fd273931a6c0785ccbc14c3d2930e95d82487f7282ea244614184b4a9b8aa6eadfa650606375c5cad6ae76227b029b72c88b219bc71d9140218613584feb12dcae734cbb3781118f92f527a7d17a394c60f344eecd1de51258ad111ad3378ba1044e5d9749bb6a93617954a3679c756ce0011d352cc0010b7430a043868c1849e047051594a9f691c0e50f31f9962788946268a8d517336ad8b8da13c438026bae913b7278a4d0bd11cc97c12d827b2996eee019c620023b2955ca3ca232c44c8c21f039a76adb1ea1591154d5b181076c208610f62cf3149558b142f08e202726cf62b142c960f1428c2070d72552c8feaf2afa03815313a3c994b2c5f823af007a2f6e7c8d195584183f60d52c8936ed4cff4af201371a5f2b5a05d1b6a51ef09eb74c5707dd41e879c08d92d93772324f39da019b469f103a754e698374c05a1a95354d3352c673c0f95d4ab79b83037e5c42fa902235a4f40df87859a322a3478ea10d18b5db2c9df4bb4e35e0def327915e826c9506fcded5578a60dbe6fd0c384929c94ef1c49001ff29461112d36616752c3817cf946458ac4f5258b0218890cc35e43091be02156a94aee0c7423c959d72a790d20ac6e37e32b993f4eface0d2ffaac79369f256c178a8e9a82f524486aae0cdd5f53b2f89578752c18fda547e13775470b9ef2fff6f3f055f6eca7f73ade9bcdd149c9bcc67275d948ea59782edac7f1d8fbd26472705a7f39de698b25bcaa28f82b32472907b49720c2a17051b2d681ef17861e93fa160bc333743a96592fb01055fa3834e29e83df5cdf90463daee25db554ce58e2718b5a126dbd4e93ed5e9049f3c9ea568e526f19b13ac88c8961c73125542bd092ea4515242cce37fa3d604a754f094ee2fb5e3d9996092b0a0a654bed1383626f82454333b477555ec4bf0d95a841ee55982fb12a9468de5d4a6aa041b53b473d5cf6d0f694ab0a11ada6fa1448ea64930d937795e1a15a9aa24d8504148f3eb4d7e478289eff5ed99bfd2860b095ee308113ac4903e8fe0276beab2acc935083982aff5a4d147dd083ec6f5ec511546b0169eabcd33b30836985f66fd15c1e90bd713e9a389e0f2ce72cc1b447bd02822d8b72bcd9292758c513d0497d36795f0f4a64c450dc124ad94e3ba8eeeacb4106c86a8bf951f42b0af7d25c23e575acd20f82064a84fb79e269a20b88935d9e464ffab54068275cf7ba7418858b980e0369bd24a124f7abcfc81b7bb98aa5979d476c50fa94b97739023c53eb01f42bf7f05f9c0b675f4b168a99df43db039e752263fc9167deb81d5f5b496b3bde5f3c049959cad43e814c4c4035f4af443f6afb6e8dd1d18a17e9544e5d221c70e7c7f59e6f3182b5b07d692bda6de5856f6d381ffaacea739c6649a9e031fd7b6d6d52f932b077ef33c66e64c11931a07c63462f5a7dfb0bd0c0ebc4d504f4ff91e43fa0d5ca8ed7463fa7e2feb064e83c4a452ffe93adbc0a5082a779299620377d23fbfb95a6be0532b9426dd15e9cf52037fd2aa3b9de97419ab34703f7e49a96822d328a18153319666b98954317f06467a8ca1cad754dc1c33b0d716b4ffe7acf69d32b061417b254b0a88878a515cf75c271020077ca911ca2ad89e0002e080117aa571e448f2f49e1bf0a324aafe062bb19cb10113d577573c526ac0893e0db943bde6f4200168b097b60aa926be240d0808300336d3e5a5af0e5252b75c74177d812e6c143c1040068c5c4d79bcfffa88055713ff2659b0a4f98085114b06cd75a65fa2a1f50cf8d4376a7040868c2db678cfaa57f0aa9daab7f482e7ccc12b067cb882fdf7907c726fce9f4c1bc3472b1897a0353187fe64e729317cb082d3244564bf9fe86d57c198ec241e33d737a6d40dadc2872ad8111627a5ca4a295847860c3c7ca482b39cbbf72c2da76a0b0d2d1aee45a3a0630313b0000d2fb2f0801d3e50c15db68ba46c7f62221fa7e0533419849efe4e62fa3085b93da852faddff28052fb94e6fd494113e48c1a878ae273add5ace75146c4eb591275db43f49110517d2f8c91cf742b2988582d37f5aeb49d64e0a2550948c4fb0ab2de2af92b286e47e788297981e41da4eba738b2cb4e804177a623ab4f9c1095ebd46cf44e807b9f8d8049772ff8d0e9db2c58726ce1f5c4d69f55589660b3e32c17906ef3121646a8b7cc10726eee312f8610947941ecbe23d41e9faa3125cb2cf561262f283126cb4bb6f4b9646a5fdcdf86312eca4ef0b2982e71d49d7c8a2bbe00f49f02942564be5a548f0a5dfa72cc95189ba4382c91752eed5f54d1a9ef45d5c601fc1dfe6da0b31d446929f1a5fd060000796081f8ee0d24deed01d3b430e79207c3482cb4a9b84d29cd3c5d41a1f7c3082cdf628f6ebd913a2c6061f8be0f26bb46dea4deaf50fc387221871afb869fbccae2b89e062fa66ab389e9a7db3850f44f0695de36f96a02989aa858f43705a72e84abbba11f23704a7a9fca3bf67de695a08bede5cf5edf253690daff04108de64dcacfc397a2e8f61e16310eced4f1a95b46f6d4c3254f810041bed47c93da14ae836104c8c21a95c9353e7f693133e00c1483f31b517d157436b02f413b08f3ff09d822c992688a949af014df8f00323f34995b4d90d267cf481edfcf96e4ca2c7e8f61a3ef8c05f8e79ed9eaafbc8e6c71e18f563d933069d0f3d703a676e917a31755ea81f7960f3e432a1feb992aae4071ed888ee9382fc1c3d0ada6f98eae26f9c013eeec0ff9ea6d0497bc81c94c65f0533bcc8e208e1c30e9ce95112f2250f091f75b07459ac2dede8c0a435ff5093318a90d6b0310305378c9c1b5b20d6c71cc87fd13565882439f01352564e4af47130b72a56e776d11a97f0010723a95fbfb20bbfca0b1f6fe05ac53c567255ed72ddc0d8969e9223d936709e5e3b87fedd47d1b08133af095e3bd235b0de56bdd5a174688aaa81d39fae2b588d6895681af8d3123a2ce7a9117941039bcd5574b09442436bc68c1b4da3d8c719d8d321b5952c8bf91e3370278445da6429c224a50cfce9b411af4939e51dc9c0954c5abba23f06ee2245b09a64b2d23c31309efa1b270911db932a59a05c054230230035f80803a79571530c9e22e6a081a16af0f1051c7c7881ff209397d2f9f9a1aa2eb01722a4cdf38a633ab2830f2e309e2ba4cf132ca4557f0bac9b0c22a59e5d588db4c0859883ecece4675a9e2c905de4b548d0fdb1b447f8c0029baad74166c8a7a5dc2b7042a83b9dcd532726d70a5c1c2fd939a90a8c4842e4bcf52483245181116da15d123724efcd1458df49e9358ee8558991025f955ff2c41c8f9d8f0227725869fa1dfbb82a14188b20b6e933e9ce127d02979744ead121e904be4695e851dffaaf96263022a28bef7585097cd6ea6584ac96a7bd25b0e9e6d99a9a5242d1c255d484dc5e8d38c21bdfc51733b4509005e9f09104c6d2ebf5865216621324b0f143d27ca6348ee7e908fc7fa594da825241dec9088c6de5b23b8bc058d29a2bd9ae5d2c44e03f664e761f9596636908ac8905659d759b3e2d04b6cd22c44add36d90d029bf774d09b2110b888653ae9f67ec07e9c9883854c318690f7019f5b3aa98ca61e70a5b42c6948e201bba2cdc72495ef05ed8049ff593b5bad034ee84f1b95de31883607ec95eb284d3138e0e45fc6f536b967e60df80f1db5a516b701b7a195da832e99a404d58017af3d3bed0e0d18fb700d6d25a3a567065c275d912382103ad21f3260ff4352f34ca1f4b8b160e2a6f1dc51f4b26560c144bbeb88b7196d92af60824cd9c47a62489e3aae60f36204d99f9364b15bc148bc1d333d2bd8ff49124cb555b05a26244fbc5a15ec9ee9b67f5d2f39e95470b232248e0c6954307133894a4c9237fd5370a63f597fbc3791846b0a4e62e7ce3ababc57dc52303a6de6d58c99e93d29d88ca294474b2a6a8a8f82097aaad54b6944c1a7592edd0f6da231130a6e3492341533030ace94b595ed464fd2ff041b3c8665aebdb75c7b82d169b2c25fef4dd34e3096673aafc909c64e33c4fa897983a99b58c58457525f13bcae4ac821266526b8ca08c192da60821fb51cb4c8d8a7ca7209ce3d8b6d289dd2774c4b70a142c3fa476290a04af05ef2cac5dfd3590e25f84df5936369ca24d81077fdd7b22a77a4488209417e16d5b613dc8391603d68eca83a2224d80dc1fff3d4d73ffe083e3b27d1d9a3c7fbac23f8e029e3244da3926d04a3f26a9a2795392dca083ea6bcfc91acff335d04e79f940c6ea722b8ce2942ee9a07d12997085e3d6a3479d623825393bed7299e10c1ba437032f95db06c396bc50dc1a86c21c44ae942b02958e5bd20b4b62404e39af5a2d89a67b88360e3a6d4cd0fb611a282e047086531ad66816054e598124f0d08364af2abd320f289fb07f6b2c7107488d85dfc801239ef4f62a5cc0d06d007f66aa4e5cb27731049cb072687faccb9ae928301ec818b5bf9b6b2e5f5c0beee5966a5868dfa5ca00232645cc08b01e481bd743aad650fc2039fcb34e987caefc0e8584ef2ad62c4341a3bf0aaa72425653a9487681df8243a56c918547460b209a92a7952b41cc98c1a690617377a0533de8beec20b1b5edc7d170b18c01cd8d611f23abf993c213930d2f4327e7be7912971e0d2c8c8232c75cceac1812b4b679a5755f3c4d21b38d55f5f4963c80d8c0cedbfb20db5812f53e29dbb3f6ce035be558a8dce1af81aaf68f92d65b5243570a2a3a564224a0317735e771e65a38137394affa7bdcfc0e468da1df33503a3fe22a83432277a956560e3e42b8b9184add964e02b9ad25da32963e0329dd6524fa318f87113e1d90c035fe9473db86b08fa2118d8f6d1252b646e8ba32fb0a292bd2b2466858c17387d8b6a75f9ceedb32ef09d51b36554d3f2b0b8c0b778a8e49fc452e6b6c0efe918ea26335ae0bc73a49379d22facc600b2c04a0c3a74e678a1af3b16780bd15a3af54516a573052e746ad3bb7ca19e3c56e0242799942c3d19afdf2ab0950a8b11a8d4eea6026924160804e270381403b1e9ed010314000000001413c742a14820908455f40114800452281c3828241a1e1e1818361807c6816030100a86028150200c0a8402615030201a4403aaf905cdc8200a1182db1ce778c61a327abe50ceb843e2acb7b0b269b45ae9c6b711fc689a11af0dbfc9393a5cbb8360edea843fc6be24a486b549cde159628eed8992fc07fcba280c4308828853c9f222e958fd16698d5b7692d44e3deffdeced41112a38f470d64fcaf6116f16d197283e98de2921d840f61fd0ddd59b462cffc96d7997500f40d2031cfc5c7c594dd57ce904df27c1477ac67a7aaa61b7df6f927cad393bd824f39b938cc3d9bf0583bdc9a85cd532eed4e2cf4b73e15aabb7aea75ac32b488c0eb8267ce32cd698f425318372b2f78ab72a47ad9504911f7fc21cfa404369497844e4913bfb2ff05eb812d722c7c0e351ed6e52a8f1a73ed228b3964f52f8998ebe06550384046311721dd29c30a46a6795d409198f7fca1235601a123bdf58f83aefe14b70f21476740c4156ed53830415a7e31591b395b3763fb1ee065b33d42830eaf5c53b5a6598988673c2eaf54543a5e503a2c652050988a494446df3856fbf01f67cc600cb50bd1cfc908b459fb8df33497229945cc586333a9f15ddb218348993f4b26d96462a8f2824ddeca0ae903b77bf031964ff28bc90ede3f1b7fa7211771a72632a3fd16eb6fe1c851f23c1022ca9a4dfd77858ddb9beadf1136082cbc7421a8e2c16ee067f865f145555be73a52838146eaef16b1ea7c657bc032dcae8c9f8854a8300d0b07c0ea3e5875e4cb97382fbe4b27ff72241256e1eccc63b7f55e58055b0e90dc748d3a459710be42bab91496d4fe4b2d9e79c427e0ffe450842420a87a0bfe9d37c677bf7cee0f7c4a7cf4d6687f28c978abcacdb1ab7820f54e82d038fae65a237e5e88101924e3d335ac257b5a17034d674a621b30da68fb0858054bd0794633b633a3b684203c505ae0d4513e2f37c004b1d33b2c7c65ecf8eb4e44f845eb7768af33fcf43a4ea1e86409178fc943af49af5aab08d55dcf3404a93af36628eb4a7fd304adf5058fc4c97d973df0183f989c91a0cd6b26f634f0b26f1a5007f4bbc3f758422c698bfa1f794a3aeddff6a82835ae7d8e2846c8f91ac5c465f07b95b46caea83a356e8a69a40b5036f711467e0c868f6690792512840e6b9e558de401c9a5f042981b7789308e48315a3aece28e90c94fb7a08a18671078ce4fdc0d485c4d3ac701fb40d7229fc817b9de8cec93e846254b33687f617102c6b455aa08a592f3f0b31af5d0f4fcb7c9e30066c079265c78366838dd58c56d4dd876998b4f4315cd3045bd3f45b6bdc6e781daa8d51a699107e010dc2a9c468b3eb13031a3a13de3de43b8a47d8c355032b9a7141a53e92a1359cb0bc3059e6c45067bc157e80871c920308e4ba025823a4b966b8b508760b01c594f7c1d2a8a053e5cba73a81eda523d08391e89d1be3515ec6ef27a91aae98a215c00e0e7eb797ac463d5920c79453d08d194f2f1c58558eb565bc8c7c3307b6e6ea0bdb28780a17b006754a771b53f6648ef5c9548803819ad8c23b56a09f6b125613886a5bc173d8d298f52eab85b90d46557626edf6df67392b3c7c131a1f5514d522b56b73e6302c275ac1aa180e480206105b66d0ca0c1a9b07ee78b0ffc95570e7c51051aa094700abaac002e04a042e7000450b271b08f0615c4158fbf33a69750764177863c1906d0678cf5b869c0fbe50279fc91ced55f0b4d4e290e642a75fc4cd07140982294c39b3d83d350740a01ce75d7a154df546a886077dc566234f0a3568f10e3ec988af19883a4eb9d33ee5c093bfe8535db65879c69d9b27ce80e071e80b814f190759399be01b40bc01847aa019a1ccace809280661481159d3099a81289e9a47595160148e40271a10f887df4e59ecf32332fb025200c5ac5478a6cb69d0ddfaae0242234ce3d440b456472b801b03e1a28385566422f5de2ee8aea60c8e959beca450290256c788dece5acd1534325af841a5609f7bad35135cac6627d7cbd9909027677bc58d1d3a74960fa51a789a8df7738c40289500157218ac756027002226b328d74a610168bf154c5d39a971d3086bc35706efcee869ba568c65dbac59aa9d9132fafb467ba8ae15dff5c472de8a246ac51309e65cb4d68e5ae1e8989b37b7a290b5e2dd0ae6355affa59eded24ecf4de3ae326898b5f26b9c9a28cda7ca906a5e6a67906534b44af3b6542b6c6e9ee540a1af34679dd5d0723a755757d0cfa573d767aa158c10ca5a2ba847414fc83f1469f852eed756d6ae512b125a981882d83fa38cc31766ecba9631ae694fd3bc282cd9c2c07ebcf652efa607d67bbf325ab981e3275a0795593467c56edb279f9e5bf1aac66d63ae8157ade8465e19432dfb514f8d38ab823e4b8b623d01b0de18215ce57c1b776dca95c1f9908d576aea6971fb93022b09b5dc96a1987bb1e6b62a274b582e06d1a4f1a7c2445f9d12a2e103ebf05392a69733732934e31786b3b4e4326473f116eb8b39399a9272c2e778a5601808bd14cdb6b6ae3c8232f6af6907b4163aeceb08c96ad4c873e76699856646d3ac85cf20f53abc6a780a48407d692032bde7a0fd00e94d5df2635b555f2d98931809f0c07b466d3beea8ea388c4c5ba05d0da185e91ce3e8db67a6bb1bfb6ee8af5cee056d9d44c833214d0b0a86c902d44d3763946adb0aa6c57994d9375b05057cfcd0a3719d4b8f4d0fad1b180a3d4c9b8b9b56744fb04601410ac39626fd1ca6dd93ce085733076b360d2b5cbef0fad7b7f69b8528171c784cc3a4534fa45f46b45e3042479fbdc405516d591bad77634074e614d0ca23c03221698c24454a20817162a09e5bf1299a088e7e211b574edda336d3a6bd402f45d46ac027ebff80c874ed20632668582f6060001f03d4deac9cff9ba259a08b5fc26da10090235009641871b030894ad91646dd41cd8c018e7d4e349765936ef84c201640fd2a02e8a41ea66b517b6d991725539259503eaef2908d2feb8c4ef63f2812b02d31aa38245cf9cca488757f262aa8c9da6da3811535a9f0cb9ed9c12fd1436c6e547773bc39b32e890d9204c199f1174a6907959b312284bb1d6ea3279b318de908ac409b35e96698d8556dc5ea862b39c5e4b4449c19279b8ccc693336acf76a55cea993335be65ebf0d683366db2d03b6960363e6cc90310da8b08d75fa506308837637acb736e56d54d8c46d136536d3b0f02d481dc42779d94cffe6a69c4d72367046d95cc29b3192e85083d7cdf7c51933f9ced22ada404536d32c6d7eb2f81b7e1c2f6a53244f823b51c9498f9c19e4f644845443bea6280975b3f8de88909b6a4f5387da73f8f76c844af760303700fc3109bb6025739ca9d27dc74bff7a579732af8bbbc29d10bd55b41c08b7d0fd98d5f8a1d282500c9ac6099f6fa84dc822040e62215043955e8f57153111e9fe20c8ac9719eea700db98f838e1641ee952e68763da9387752dd475b2b22883802ca7847ac5404dbf309829a107179251b4e6be74ea3f856b0caa8647a407ac8b253f996456fa690b19f7686a2a1af76f57c14776c5611970bc3ffbaa6dd1e87c43f10809d5a3adf8977e836cb8d739d6d6d486be8f54618d6184f7c227c13aa919fca89e158487a9926fc84b6ee15efbc94a1cf71383841fbe1bf9695462b1f8cc8e0d28ae5d9ad848146a32b1977aab44a90c55a1399b8800fab5261061af0687bb9a346849cbedbb880acf0a67f31722d0da7efb23f4a90224808c7bf6f2cdd8a1d3cf87c54e94077a2d9f467cd6a5ba2c13c6c004af8251bafc8de92d6a5bdc7a05106fb73bcfe840d68258d803e32516e48241704cd0b2efe9c391f3ec8b36328bd4d11af88f08931f26e14d7b2c2d9f2cbe5c6f854dad67b8366e4df66408579b61bf76b6b9781bb31280fce5e018b6c4461b3d32c34f7c7d122909080ce4cf2f585182cb98845c62a234c699c64a696dca733695143508d428c16072ab40e9fd361621490a39528860a296b6374321aa5d1a2b924df82cb66d1f884aa20d20f1671ba4cea6c25a542e22ce4782f2e2a09194c9a8550be9fe41ebad3baa60228487a07f6e240474b27af9c2344c55c5730661c90bb85a3290408504728053ff53c129b91bdb55b74e0eede061b26f14fbc72c39b4d6c3e79d1b1b1417dc8f10bb8fc129c1d5c66083ec8c9480c1030a0a801857a7005789db26fde1396c7944827d900d67ac5841716cafb1b06254eb235b35850dde3787576fe2078b6f041a9e367404b9f6c9abe87a2387149e1f9599d4d6a25036758d20bd8f91dc3fbce98235525adef5be39e18af0bf70b5861b5df6a2b961e1342158b01231420cc97740279a13a607e0506e980cdcd8f8228159cf7b14994346601131c33116cc8c77803ca82480b8ef1887ab0a97df1bf32879315e82d7c3abed257b01bd582fce2bf37a79355eb9d7c38b2ebf5376e6d6647af80292fd321746029bc442f4322f7b3b3c30dc099353c283957df31c0b0f571081f21adfa1a4f0d8a62782974851d217d953f3be7953de61e27d160266538443b0612630cad73e0c086cf61d98f3b1d525ef0d61630a3c22ed5b1802853066190116f17af658b32c18f605cc33b68061bfcc8591c09a1c0f8a1fb2a59de38d2030f88ec43c2fde04dfa4f048f863784bb832e0e3af09d709147a355cdce1c2f9bfa8e4a0eede61a5bd39980d490fd78d3bca6fc93f3714e6dd69cad88531fe25518c4779bdef17a20722628c016ee063fc526ee20308c600b2f3d7b1e421d504433d6383b0172447617855f9787095ef200f76f8dd6b10f4854b050d481e598b594c179845e9e371d0faeb82000ca6c28e551e160921c6974e1d84168afad061e31180b7c9883f62d958f10e53472fc5165986aa3cea706ed3f64f30609c94fafe237baaf4d45f21a2c923c259cc17e6bcd8ed9d23cf4251f804d1fa7c8457ba091f76413cafcc4a1b7601c10eb56c189b16580e77b30700376bd54e11e34353b22609fd4a8c0101352edc67a223a219b00ebf2604cb43e53ee571674746ce43c2fee137d86f289a837e5292ee7eb2fa234346065e4f576852fa1f1bfed9d6bb93335e25b105524292a98375f4729edc9a13cb1220d3eca399b2fbef2da0e478504f1f7f39545dc90a00b29d7d00dd365b2bb5c2fda9fa13f2fb4fd05a487e48f17de2c0e905424610eabd0fb2e3a4cc9414a527bce9eea29f19f68084fff7ff61bdc6fa333661a9b0fad149f98e55bbffe5c1640ef53166292ac6a57dcd1a828f30b5714caeaa3808c8f2e53a9f75e05dd8773b673232608dc12c85ec5b64eae067e00a3430602ef25870002efa5cbba7e8c594e88065fe028aa90953a4cfe7f667a7f02639dd06342410c2717d97b597a2cf85640aee211ab116b33e74144f0b32d487d0244002deea0af34176e12893d52e2921a52c74c41e0995d642cc84e4095512ca23940742b3cd9c0534141b82465453a8aaa11c445d4205844a62e82d5a05950421c45d0acdf64f16ef17174921ba2774e9d05ea26f42870d5d46a23752d1cdc1167ae7a112641864a87ef16a9a17c26828064539408d0c87fb0a951005d0448422be45fda4e82d991306be11555f43b91670f121930d9540368c08331a5420191a4bd1e728ca5db88464704d28a7c169ed65a29caab4d2e40d7a3c3504734abbf27c694e606e802afb33d28006d9aef3247283daa311aea72e9261dfaa1c1b7c7380625c5b05d084385d46afb2f4f58f2bd355631fef9583c2d1ad6f90b7919628a23a65fdde0384eb59babcd03ab987ba9c25cf436b83b51d0021d42265d5cbd56f8d6bcf1c07a690819bf1362fddf9a6032a30ec259b2f5dc8c3d75adc754ae565999ed26dfecabccd0fca755fc50c74a11ce04df0c3174eb4404813025e278996649206a99a49e10d73b82b17b7274009f549744b79390bd225d5502d6eb167a1d81601d689b670242e3c2457b25749d9479dde3d4147e87163a499ba121b4441a1a622749b9b9d890ff1640e2af72bbec3ae62c153a191f83853e03cc0c7cc0db0499d701ea837064f441d744a77096058f6ab00088e2ce5d83f1591a3e2eadc91f6e0075a30ef7ca0aba9a71780c2087010fe28b2178628c1ace8e234dcdd81726295b5c6d930eedb0062c270e42017349ae9b19478a82fc8cfab5368b952f29dec97f12cc7b228d865175e6da0cc869230d7553f2140b987f80e2239b0f1c28c61f87e255034306080108adb7c4e0d0907839cb4228565158594d2716542948b0e2ac19b94401ee15646b8b865b45bb4a2b0c6f5487cc40d4f4d104e5e1d7908666db687550c1203ad97f0e2dee18a29774805c710a8a211e72df61703d01613d5f5da3b73174d4db4bb1f52ddf9d8e42b81d2b540ea204e7231c7cbf54a59507731209e90c7aecd650e0e5af24f7f0f8a82dabf78992f76ae87d91754b808c95a8bab247a25a341f161aa85610e24108346922226455585c93f6ee28a831427526976ce871fbd33acec1174f89fcc72501711b5b89c5989b821a49b466edfc8b06408881d4da7f13b1b470438ae3bd03722a5d7ed0becfe087a8be060e2e3a780ebb36fc82f97e4504f6ebd651ae12edbff1f2ac61d5bce1590743d7ae1b0913786c256d5523e3b2af8b09984306c60029b4c04315207a220b39faf69320530c9ca230e01f8ae59637f89b9a926dbc683c1dc43b58856da4a10f42432d7f5ea2c0a88d13176f9bfcdb7a9a64ab48c8abb6e55ae88271adbd71be52eccd483f22b105d1d908bb9fe97054b4dae73cdf837b7532cf227a2a121d2b06c32895b909f06603964880981c7a1a5dfd82c605094830ad1be712512053c278eea78df25e86b63e173a4c027dbb98ad81a30b6c55eddde559bb902d79a6a9a79a3910b4302964cc5938c47f0608afd2803a68b0bae471430ec84cf0505a81352c14da711b20048a20a405606c8291c32b898e5431164f938fb8f318462224e1fdaff6293621b9fb6044d352d76cfcaf5545606d3fd93717ab4005b3b6eb662604486c7301c4bf0d1e093e80dffe6e4c1f4984d12f4ef3d743f1668c32d44209becc59b0166d764d2b4e076b7107b556e2d244150f3334df42a90db4e2a40504353d9b5035f79f28253efae57b43dad552c31da0c0cfc0a064b3c02c5269b7a7ea0c02a01d72cb6bfa423ad33e22d19c104528ec2875611ba56f9a83f0523700632fda6ad994347e501529a262e66cce08aff5a68073e20f01b7308010d6e78a00693d3dd93d9f3cf28dfb8f2b878a13406d6d96de798d1d8de3ae07d99ac3d171097ee0b51a3b9345ee2e5d5973209329e67c82e4b5870bb24255b27ae5ddc668dc7897a656defb5eb5c2cc349381fe35da8833dfb608bacda8ac0ebafd6b9e68c7fe3db532422a137ed34f364b6b000b717c3b0daee7d7d5629952de86073d23947b5291ed2f69a1b2b8b967598749585bd9e9cc4e931dc5b2bac20a3769413d185afd4e915ddc1c2f5285790b2c4a150a427abae82e10a16bbc173e1b21a2e273bb01a00f043b81df8db6d6004cb6aacf1c276acf782682f7142740227613e115a2a637eaebda0bde85536b9b3202d3d15a597f619227419d0a66569c03f84b56bafc09d1cf24ab0192a721e9b71373b9b06ddac8595e4f5b85ec580d116c6602daa5cf2dfac335d17655c0925927eb7e8cb643f09074afa4c0a2a296152aa4954cacde496768044f50d627aeb5e821f5b45de9433d9ac841c27aa855a5d6e5b4854672e026deda2e968c27b701149ec71129d031b984c20a7d6f8641b621fdb3bd9f62de3319f0f7c43ba80f47944681e4b1d619cb3cdc34a7c2c912049eb858716f23129f4897eb320bb7d80125219404eaac14559bf204b1c12b890ccc32bfc98a489025422f5c0f623bb908e04b294b8ac6ff300e1da8f13ab3e875e158fd30382639f6c299140fc6eb63fbf787ca54fff1effa9bf634530a3692d74cca210323a4a954e7e36216e94a21897704c132b6ffc657a7fc9df58238359839c806a7aac2434abf1e5ba16fe0cc0304a166a88081114d4af11b1aca7541012967edb09e922cafad3a56f258367dc2c61b3fa523f110a82bde03e59cdb7b54bc54a1c4f0aa9496b737011d69924394020645d6de5dcf9d5a38790020b45f4f26a66be5fb302d28d7c4589eee5ad824c8690b398a91371d7ddd963ec28acb6e8b9105f3fe934b3382c5a0699cff9396312b27011800b6a0215a03b6a359a3135033f5b1b7343659c39ad54786febb404c50fb75cd143eb49b57f3e1c4aa21d98cc22a060adafc9f2174d2bb1bf471263491b1f5bd5839851e66aadba49ae528f34f19731e33116e67525edb84b8b42feb056257adeb11f0ac592923c31cced48e7e5e97dc5929ee7ffd9a67342178f871008c461b120c7165e9c9bb0e0bc020ec9cfcef7c97107156a5a2e652c2f440e6a6f0791379d91d253ae1371f3fa47b67ee5c7c224afc28f121941e9d7994bc36c2a719556b824ada85383fa5012f56854138fab55eab15161ec81cc017066f5fde63cdccdf7a5899e8ca1b5e2e890fcb61ef4917186a1c9cee50bdfe8535f3d746ca33e8fb447b6207ee6541af91c71c9f34612e81be8b992a51b5a732aa08e84af5d5c30d78c02c4af90a7bef8a8da822f915d6033816ee8b4dbc960604b2d40c1622c7bc63b90eba3d6ae783d668fdac4f22d592f90bdaf79d4840907ec12f1a5dcc0aa8dcb9555e1a8641741959713888e6fb341e0ffb89991631567cfb7bac6146147f1257fe4c74aab616ffd60278b5763c508734e209ac89edfc0313c05af26439df61ac9ef05f879ba4f8b50a6cf82ce2c2c2deded88e32d205a210df32e010d2dbeae771d12fc02e3707e7afda2b4f5db4a19bdff161898720d0ede78a1dfd376637548032877318fac9310129cd262d995401252b0686dae6297fb0d6c2df8d833c82d27abbfd330b8a2efb580966e8d63d18198afd4a1481efb72260a8a18bbe53de1e35cbc8229d63529ba14a629823e617eb42aa96c160820cc5053da0fff77f56b04798b1b1b60424521da0464cb36da313d6470f53b57372cdcd2d7e08a5a98d50199919ed36f3b5d3b7c2008e3f409619042f18d175808384031f29108d9ae46ac1f9b5f6b2209cf363e4fce67a15d68a98c21ae315e9fcac42059d0421df9269bfcb2856a02b3f4a989de4a5b34a75234dd19178b2ef0e2b371f4f3a5d43de8f6997440b4a923855bdad261aae37fca4704a6b2449ca9e8e25ee03dce4d268d0272881153951e4536f2af1d4d61df23179bd0393bd4bfc7c336841acd7cb3d10b94e749e918776721fa06382e29d534d01a14db7de5dea5f19176c45c1101767f5f42e767e57ec9d1e135b44eb920bfb7b07be5778bc654e23b857fc76450967eab65ca5a0430489ece93cd4afa1a62ae58207965ad791d70f405f1707cd1286e29ae0a6b68d6c1aab5a7c03eb92407b57c1697e876263c9326d130136bbc1b02bc6854d6386ee51446c9490034595a58a8e38bacf3e2e3588be55d827a56c49347a82747071212667b09d4cb110fc259af9f2dbe80495a1f5b80bdcce7428e2b50ec2e113683f4b2f1361721b8aeeed659c17fbef995aa0c5781d0aa29255d5813548a5544b904aae0ad008a07b2e31dc4dcd7772d9188ea3d5432c52741e35977d4daafdb55dfea430dca168ce95c3cc431ebc771e48a267486a85a91e5880e1ced0ce48962df5c3e2e52fe45ee386c8e748de232954cbd75acec94d34e00d76ec2da181b639c1044ad6930614d5b97b0ca944437855053c6eb78b9ef97e75b1cd715293f09b40d9e295a85bc05cf15a4ef71bdfe209e19f0d890b33a6addc8e076880470631dab86b1832a32ecd43818cc30f90e37de84f38148b94fd44d0597e57d9a0700b9dae6370c631b6941bd5b594453daf44eff87cd9f026e128874521634367ff71d98f1ba9f17ca03a80c2e60a61bd07654f41545db55e6270f3767099f510af7b8847575ec69a4e8bfa393d2b2de42acd4ce0a06c305e1c2089c0e1f8dac0181634b08ee1e27188049715099132532b5114e7d45dd100856c189294b837a62b54e1a16b003d0c0b4e0bcc2ccecf0313a84d8db0e40f0686bac9a7d90f5df7b122f16c203f03f8a7f9ed8043ffaae6e060a35ba019821dc9ee3c00dacbf07638b98e05862273a0004ae35487130ff89edc5a28535b6bf4c934aa1a4211874daa0528bb0038e8cb846b7482cdf46d9ab0d6be8393812af7cd6c8a81f20533fecabb326468a8693c8d96375fa92e21763f6b46141fcccd2549d53aab1d85f9fdbbd7baf1708b302476b2002fd95d346fdc9d553e340fef37550e88eb5825e06e1c16d933b00dd87b9013849bd616d83736c7f68073da0f3a255290d9ed15656d872f7c523fd52a61747851eac1420f8aae7441aa727239a5ebdea84b6af6391809f670142214adffcb7be057fdae8af08fe39551b7634fcbc2354bc48a5c100f16fbf11482f1c4757889d603b8898bcda65f77c9b77b59293b963edb2b5d841fd3ed8110b13e7aa0acafe0e6fcb012d8d003efbf94f94f569bf859479e2011f0f81eacce56a8c528fd2e4f1303ade1619fc5af08aa050d5e83eacaee645e7d7ae48e7a216eb247a611d4529d0f188c53a88aa6067118aee2c5a91ce452dd649f4c23a8ad20340ee1910400904c4d0801daade368ec33dd9c18ba92d514735821f970d540175b3e106a81fec0f4c1aa6c35b232fab386c45897f78e1e351e07ead474f36467316a978a7a315eb24baa29d4529deb148453a88bc6067118aea305a814e472bd64974453b8b52bc63912ad2d203d692af3aa8f2590a086e168d3acda1a968e7a522382f3a0032a73a12a30cae9b5cd1d704696c5ada53c4cdcc836580c11f6ca9801264b225525fe9f034aab0021a2629a7d7c6e47dedb8db8c2c04ac037fc31f3bec88ae688a52c7c0a67fe870bdb4038a5105811b1c635bb8a9d9e08ac730d5c3d78be8936282a74a4eb5b173b781d1ebbb5bec9e1f234e81354d63f2a17d7e3980370afc7acfc71a67514a32ff3b36ae28055879510df6d88255dcbe77f3c335740a956604519cc1b411d69df65297b8e319514e69cba294aa3a2f657dd859229090d9606d0d907490ecce627d308a162ec17efd0f1af683db08f54c925b89c1b92f9925f2400614143d01ccb6a33dfe52bdab814e3e1aaf1822b3736ecccd87d682305140292297d8562dfebf3ae5dbaab348c786e86eb7b058b855079bd03dce5110bd2feecf04a6793f5ba8ead8ac52e16de01b291450d0d6129acdfe72ad299f197d2f7a37f6a2025bbc401ea503be9c8a0bb7483a0562a8b20f71fdca74ef38f69965552b9a12faa4737a766fa091af9bd5f2c98e35b828704ac721202cda0451d87d1169760c230b61793a35a8dcefa63f8fbde6dab0fc98cbfd8a076342a0c0ed86096fb3673100ecf7a9ac3ebf9fef5f9cca287def788e217cfe137d1daa260444d2978184c485cd5ae143d11e001f9207d2c314e94a43e3733084751a96857aee32c58e629af77fad13cd02f5ed05ed3c8763b76a028c9902ae0b04660a3860b46439330f0f0f0f0f0f0f0fafa18d90da083904429a4c494ac0c9624aa14549a694a44c2991bd1ba30de8e9ccc4a733139f2e12872e019d0a420a700a33d470d8f08234014628d2bd2ffa3666fc4bdd0b608082db0c56212f4ace3ec188fc174253b6ede51024c0f004773a82c8d8592d72df09ae525faa0cca93caa9e404bf7e9b54d29a7387082e8e22c0d80477bea13bd1460555060e1a9a60254bf2889f5d77234f1899e092d2a5933215d1bae2828b2fd2596a010313a7fc98ffbbf42d5e022f502738c0b8045ba3548c37e9c534441c396858829d54425d27eb743a56da03605482ddcef531525f1f1fd706189460b307df94ab3e46dad22418ddac5f32b3335b64788d3e4b00b911c09004a373f41c56ea9e1c604482d33d39e9fd6d3e3e549083868c06801a604082b78b9eae34d2569f07c623d84c151d9e725ef40d0e3882d3b9ce7f2d898d602fa8204cdfe3a94b32827d4ba6a29b5f4a80b1087e54aae410f447f6978ae02e68932d6efae39d7e13c16437d19b848710ba11443049736288f40fc1e79862a5194fc61a0d39c19921b8d6c956f991b5ecdb42f0314f2e2531efc9285a1260108249429efaabca20a6f241702745fb266afe885aae11600882b11ce39aea53b764d2fd018c4030f246a753690704bf13b4ee759e52d16bec018c3f70d1732447ac0c0f60f881bf8d172ffadb26130d1030fac076be37a5848aed972729680974f1058e1a36b4f0cf61a38bbf40cd01061f5853e9a172081ab564bb07c654a8e94b7f7e49281102430f7c5f9034396b88ca70b700230f9ce4984468cc931dc0c003e3b9f9f427a1c7028c3b3051925750b9d33930200194020c3b30228745f2d8554173ee041875e02ad47910c9934e214774602f8ae48e1b74c7882e8c39b0a69bb72ac7f7582109c19003933d5b08de2263daf1c8c813c08803a334671271f7941c30e0c068f091a0d29768e4b051e3ee068c37302945e6cdddaa1b92d164b261b4814f8f6a715d73a8cb1f2e3e870c1b6eb0060c36702ac9287aa39deec9da1a5813a2e4c9ee0cd5c08aa71cf2664b73e0285d809106d67c445b84887901061a78558dd8af124b4eb0cc50eb824673818e0b30cec0a5ec5dfeba4174bc6e8b1a3472a0f722056fc200c30c044619c84003c61878f5db6dcff4618881afce97b23d8f64c008835e1252ca9023677b87a909030c380809607c819f9093d69b269d9f5466a8c9a861c30bdc758ed9c73f731025047861e386023e3e70e4781c385a0b30bac05b57d42d29eaa1c423c0e0022fca226598d71cc8f10cb81cc0d8029f3108979cb154a87881a105fe368755ed0429cad61a3464e4b8f13870744a004616d8681db2bafa0717bdcc50b39183c691e1050e848105764f698b97edb1eded0b7c7ca01b07c615b8f6a4619d83367bdf0a9ca90d2674f348cf7c15b8dfac4928b71315583bd56313a3fda8264d81bb1425c8db520a9cb29c47275fb390cf1405f62d63984437156497a0c0e9fe0c16c283656b9fc0e6da24d3c2ee3448df096c6551a3f2e3041db46f0267e9cdf4c499c0c4cb66715744b6f64be094cc78a5e95402a71a25a76bc693c0978b6fd22283a7dc50f0356e612081edb7d6fc5395637d8ec0a63ad5cb15947d903102278448a37e841c11691118897925eb42f46e0822029733bd333ce6929e33043678304df9ed4f83f40881f588363176d6a4cfef20b01547f7e90d25b30f0436570ad192ccd348fe0f18b51b636a467dc0e9341e96cfdc1e70da9982cccb2d0fb8b8bfa224fa7da5b4d901b7222ac742905a2dd201173f6f25d6aa39602fa20413c94d1cf06b5a22e85a35e963de8073bb354fbe693c4ed2068cbb24539633852044b2066c523a89068ca5947db462deacd20c3895f2b8c91c52be2492017b398455fd27ada5833062c04fca1ba345d5899d441830e046fbc2d5ed3a48ce2b982472a81c695f3b645dc18559f6fa4f9656b09db3e8d2dc113c968515c5ed3bad82f7cb7a1a6bf446f255c165d2129d605d7a44a9e02249d14f3f2a1825f1dd93f47efb9ce25531ddf0099e24c5048f01aff1850d2f6e3c8e0e5370dad43393d4482918b55b299e2e85146cd227a405d96b9f9246c18510a9eb540e16c316057b5b21e951d3bbb509051f4b294d6992fe3fef40c1e690ff7a7ad927d8de6457edb7e149c9135b47eb13dd8bf419006ad0d109fe8450416ba87082f16c9f6f9fa67ead9281e6454be00ed0b109fec374caeca5df4e760303a509ae83d2496aaa6c8d39efc8049b3908cd99378e09fe829a8a31e279094e08eff40d41e5e89158820d1d293ff42feca844991a3167867650023b26c1ded968c58ea3aae3da2109fb00434724344d5b9b33436d0117c0e220f1082e930e964b24b5232694830e47d84747233869af9add5e31dbc969540723d8d0ef6b49c4e86239ea58041fb7468e9ea0a4084e4694ac26af4bf4d789e0b564c98d9a2b2238537dbe1abda35885741c827f6f3dd567aa4f6594101d86201d8560544d8b9fa4bbce2a7510c23e72108ce610d931d36ce81004afa1bb621afcb57fe3397e0b2d1d81e04ba61d8ff8254ce56b861a0d2fbaca1a3a00c1d89dae0f1d9d9feafee16a2f37f5f90c352c32c0803474f88151a5a3e4105bd3d1074e744addd724562af9196a9e1d7c60d367ce135352ce50432974eca173738be87a42a866a861871ed8ecbe5321c4a0aef1321eddb091cce4814bfa2777b0d0fb91d32a880e3c70166e2a9dfc5c1bcafb43c71db8e4eb2932a6d869bfb40323377acc1d3526d55a12ad43471d18797b1ef4f6eba62e3be8c076bae7a78d6d08ba9ad1310756dd64fe72ad90bd3e5bc8a86123fdbff82f2c5083021f1fdb21073e67b333edd2229468c481cf298a062d31c6f453e98003b72731df8fc6dfd486d7f8a274bc81c9312c9bc7535929bf2e1cf0393a070614b084041d6ee023476a2fc9d6c9daa2060d2fc7818e36707f91acafd1c1064e86e957478fb8759f321c5b34170b500b41c71a98a4be27bae49b24c9c3d105121374a881114129b5f7f165e8e1504d037b564a6bccd8d2e88206177a1d68488396ee0b96de82fab7a8d1373acec0e6d08b22fadaa2a49c083accc08d489efe66517bd7520626e4d86ae55a0719b8cd2445a89cd3757e50171d63e052545efe9e2a2195e1353a078d43cc8c02586881c5d540000e2f6c1031948e3074808133d91525c690cd50fb15d0c841a346e3f8428717f832916376b7bc943a9ca166aca30b6cb4521a33a7d48d1c355e031d5ce0237ed0186b2538b8682542c716d8dab390a259cec8a1430b8c1e8da4de3b687578cc1b3ab2c078ea04757e771742270e1d5860cfc623e47c5d9a257b05de9492546b95b4022735f9560832749808abc005dd922d5e2519b386b0830aec6545d19c9a24a3630aacc9b413ef75a5d1210526c98f496f43d2083aa2c004d7b088d9de0094a2030a4c12fd1b37f88aa85e56d1f1045693c6ec563a66bef99f7138fa238001484587139898f7fc3de71b061d4d6084122b9db6d184959409eca5bca62229751a417574e858021f49e9d225af8466dd4a60ef6d47ae7ec7ca61cda123096c72ddd51c27ae8767ddd0810446e692d9229be408bca8a89164cc27aedfe93002a7ab94ceca54f1be4a277414a12444777e9269d42e741081cd3599b54bcc835e5cb5d031046e945a55ca8fe91002ff2926d51bb314042ea987f6783a760081cf1bcb7692c6cc50cbc145cf280ee8f841bd315fca98ef93d1e1033ec40bf6b9ccb30719dd8e1e706d61fbb1d2c94a1fcd5015dcc800fa13986d1f3a78c0c40f9a3a4e48aa92a677c0e6fee6fddbbaab8f1b0a74e8809da4facc47689fd0910356cb4b2da7ef38e07a271d248d1b55b5c504276bff4ca4dfcd30cf25f8e89f7f82ca31f1532ac1c312ec86a462d6e89f2dadaf04a7bd322d683135d1130f4ab01fa369ec4e3998e6dc63129cdab9c5acae784a0425c1e80f5983f25f772d4f24b824d2a89c2369cc4d8b0724d84aa2d33a7ad48e27f3083e5975bb4b30ed1ee3e108c6b63a6f49c849768b1e8de0bd640771031e8c6064d2cc25d46f8e581b2ec16311bc054f7af2ae76e8c420c143115cce90ac3377da23118c8da87927514ded8d0c1c34520d1e88e02d674c2ffa53624afa21503184257da9744330c27267f4109ac733a8106c4c7522a6e5eb1fbaa2051687030d1e84e08249887b0cc23e4e109ce6681bb5bbfa41571f1fe71108de32247954bb50008b0c4480143a780082111234bfe5d0586aa63f309eead249bea8fbd94cfbc2c30fdc590e513ba8cbba5ef2e803abc1f3757eff502572b0d0020b2db4c04206161988001638f00e1e7c60548850497bb567919ac71ece430f9c648b9d37640b722b96818f3878e48149afd97edb924b2aa50d37eb8107d6555b83bcff7a0d252b78dc814ded17ef3426ffce423cecc0c9905822e69ae9118b471dfc14f3281db8d1c14c254b316b935ba8e031073e479f0a296e96db4353f09003a336b1934ae9b794ecc4e0110746961a9136c848d9173ce0c085b67526cfa49fd5be81511ada5b540af934c7ddc0e5607e96368fc2e0d10636bfc71c53c22ef3ea6c6027bb564c96e51af8ec2649c83c42ef22ab0626c41c3da5a73b0daca84b228be8100d8c1c95beea274c35299d81df58d2c4e4bf66a86b0656849e18428d5d064637a554efd720522764e08375a8d1513e39235990e6497a7e8888811b2d328994933ce35a6160b2be85203f4efc48193e7880812b3795f46d66bfc0296d37bfda4d7a810b42a9348d6dd993a7bbc07bb2dc9f3a5525752617d88fa0df444ac12d709123071121e6a1053e24bf28b1d4b64716d85342928ecc7c9bedd2010f2c705a62c81a32dc73ceeb7ae07105f4b0827de0f0a8029b3d317267cf1732a95081519274fcbceb4353e052e56814930d571d7848811dbda72bf306652a6467a84581cb25fbf4998ece50bb61c333071e50e02b8886ac09b94bba44468ec7416ce0f1043e6528f57d9541c1d790a1821b39d6c3098c7e37ffb24a1fed5a2fbcf0680297a2448d22d4c804937550714c434e09ca6309dc68ff98fc3cb8d808b51738f6ca29811b8f26bdbfd45b8f2470a762be7162a8a890c089b45f2945d00cad00175c7cb100228035781c81b15c1325d4c8e47fb211030f237011cdf27e2559394278148114f6294fec7bed8307118ac710180b39449f1ad51fa2cf50b33d7808815151a33e9e2c48cdd7305af0080297822ee91f96f2aea76620bc820710d8dcd1e2eaaf9a213278fc809f5c6bada2d4ff69e5cdbce0e1032e05393aa8bdd2dba9341a78f4a0a4a9f26eaa10d7b2e1c51c60c3c6051af0396c4cc0480b3c78c06d7e289ded3ee8910a6efc1726d8019ffde44b010f1db0975c336bdacf0cad0de4f84202095040113c7270fe2416bfa7712303a50c1e38f0b8019fd75c2505fdd9d3b891812d6ad471c0c3068c4e9a949f858a6b5a8ec1a3065c3e15738d2ed18013f2d57c5329d3b14e3360c42c89e9c9b80cf8ae5c71ef1403b64388dcef9fe301032ee8dfbb778d1944f30a3ec8d115cdcdaabeb42bf833a52b77d09be8752b588f413368cc2a757559c1454cda4f97a7362dcd2a18a5c1ae7b4d8614fb54c1df687c370b9223a4cca4824b3923e635a147056b6aa2272ba5d036f2533039fba78b505a75948829784dd394e954599482499bcd82fafb574a5716a4e04c88322f1962598c82edbfbebaad4cdf13e94216a2e03ba48c5a9597d2a7e80c352c32c0001570e1851708d0228b503031e26687f2b614d40b8acbe213ece97351697592852758911cfbe39b8d597482d3dabfd2a1ab196ac6b86864230239687471bec08021260b4ed8c767b189928526d83c3542e5f38b1799e0ccd56285a0732b6414095960821325a3249d648914c4bf047f29a6e9fd384154095982abb49d56b364703d5125b853df7ae7d143092e255ad2ce6954ad69127c923812a40789f99346126c342552ec6c151e3a18096e94ea2b214ba8df0a063e3e929005241879d5766d133596527a041f3c66fadfa83b82adbecf9b2b6ab4ba682378addfecd943c8083678bae6c94155f7733dc862119ce95e488c557aeda3b640c842119caba6b8659aa9de671689e062059142c8374204173a2d8efc2041da0907591c828f31a81f2d0b9e39655918828f2cee63a22b276451083ea6fb3db5b6e2f59d1d6441084ec791a3be17f4887e06c17f783ead1dec2ae7b420f8133d4ae40e03c1b665d71cf504083eb2a4ef8d21e40f7c6a8d9bfdaa2961fb814f214acebf51d3074ea8da3619eae403bb39418268d1d018d53db0ebd135699e187244d50337da35a87fa7f2c0afc59c92744d15fc4a3c70223953e6ccea1d38bf8979b1d52d8687d8818b68e98214617a745f7560d2989b0e62fa54ec181dd8cd911cd3dee84a159f03a345258b869047e41191039f4b97d60f9df62e46e3c0b9bd4409b936660e221c3877b1db31fb94f4856fe0ab25a9f2ce24a309ddc09b12952b63b6b4814d5dd3da3c11797db2817fdf0ccfa742966c296b606cfcefccfd44ed666ae0336bfc3b66acd377a5810b1a7c4f660591fa296860b255a764253c67e0c2d28d0e4a86181e333398bdb2e5cd29a7cac0fb95069535e7d5acc9c048fab4b2da8f2948d1185851a5aa52db79d4498981edbc6e4ac4f5a85e7e1818a1d2ed8e5e1218184f995975b6b1e2565f604349caf8d79d17388b5ba1abaca26675bbc05fa4a8212f8438d9e6029b64cea4a386bc31f9640bece954972c3b2bfdc5b4c0a989ed172f8ab2c08feeb4d5633258b0d47b97e81ccb2b7069ffd4760ca65d5964053e8559f43b0fdd16275560526e2c11a26a52c1332a70d1d4c812cd77156e4d81cbeffda63ec4e4214129f09e7724e5540ffa641b054ec490175963060536756bb0f4a03d42dc9ec07f9b16f3981944ee8a1318112c757d1affbc2b9bc027a5b5a73675d097264c6054b4b8c1829744c862098c4e5d77427dc5981f2a810b3277f8951615721293c0295379436789042e636a9290829649de8ed0a7797fd0258446e0fedc6f7784570476f2a7f1dfce664104f6644d0c212236044eeb2ee94eeb29c8241502df7fa24f9d8b41e076b46809aa9a3f4a08087c081e44e9b5bc9f46e5079c5dd66c1174c5075c6eff88d1ce2b68ee7ac0499d74def6271e146da49d8a1be90d42163be0a38b2ce1adf5415da403d6dcd442a4bbeca0cf01a72b688da1732931ff70c0a451a5c24567734bea1b7031ac2a36604765e7d1a4a5db12520336a827979c93d6a0ae440326e8fcbcbad90cacf3d55306ecb678e494b26a8a746370a65789640183f228695a43902e1160bc82491bcf6ddb5a57302adb77d09474becd7a2bf8b81b22478998b29789155c085e5ac9eaf6620757c1962a399a46e3b6f64515ac27cdb8b529950618e7da9862781aab2c01062a3e8d96a6e4baade70b0dc629182d9e419d902963020c53a067659372670318a5783dbe4ed28d1b19c020c5173046615e1de9363a248ba3230a466fe658ede7059ad20fbced26bd2562f46cb5f68171dbcb9236c94a793a3762f081f1e0d13cfd5731f6c0c874b959fd6b23683b861e1871ff3f1b751e182dd5982aa21d030fbc5866ed33cb1d55217760fd3f7b4a263ae5cdc9f2871876e0c736c5544f32778851075eb35dd20ff51322871874e023a848132165cc1b392ac811831873e0cf437d881e2647f215430e6c89c6f51c82c76c17ba03b0d0020b57438c38741e295792fa396f04074e47daa41dd29dbe5bd4a031230337be02e60131dec085d0e013d43e62f0387203a736dfe9aabc19a6325288d106f6fb32d4bbf28927bd9d0762b08115a529f77eaecbf7118df3f15146d660d6939836e60dcf7c0c35b0213737b64b34461af814747ad99d090d4711a17d6f153a03d776aa7b9a3603af92a2ea5fb0711176195853923e5eb995b6cc92818f6ea5796d9245cd8e814939c493d54bb25219313051339d0433d3ac4cc3c069d0fc135576ba2624a99a4e5d582e7d818f565aa76df5b4c70b7ccc1caae4bad705fe826fe594abd4940a165a181738cf987b6409a5a7712303ce058d195a6c81cff590a46ece1484ccec10430beceb552c2dd1f2a6aa64814df36cfb1d3f5cab9a430c2c30713f77d29439076dcf6b5c1a625c81533d55b20223b2ac4cc67c568111398d1252e3d9ed5ea8c08925532e2276aacf488c2970498988a6b4ab75fe1e430a6c3ecdf9a3dc14053ea6cffe74490f054e0409a92d64718feb13d84cadfa1da926a60a72029f2505734fb5d9c2bf78c013623481ffdfaadc986f26f029632affac7a09dcc8b3ca66572e9a2b814f9b3269245d31d9a649e072d9668f562281ddadbfce51c34dad6ee304318ec09b16a129f6a7dee6d1089ccaa0eba77c2c021b4964a5f04ea9ed2644603fc5d1cb36c9cbed2130d23d7d345a88221702af315ae7a867a33925088c1ead6934440e086cf88d98bc4f776143025868515b88f1033e48127a82d0cc07bc58dedb8f145b375226f0372af0f1914288d183f4c9b397b895e2011f2c95aa60254a5de5ec80357713f6f11443074cce98f7925fe65ab95fc4c801a772a8b8a758282b79e2888103b6eadad66bec1bb0752a447d1c49f921b2019f9ff2667f91196356ba8851831834e04314d7d851bc553cad8287c0f220c60c3891556e9e27e5516d8921037e448a98378ba608316250aa684c99346968ac982d9ed29d36f1ce093160c0af78b068f133ef525005e1e315dc886c42f44d743f5cc188106a74793a55de7b01400c3e5ac17d86b0e89e342f7f7c86da711938ba0c070226f001192df860059342d6dffdbeb3d575869a8d1c3256051fabe0f2b388ccb1b7ae4a7ea882cfc9b2e4cad2c9083c8d1b19c8f1910a6e2348ec3fbddfe7251736643c6a2ebcf81b6a15f840c5974325d50b2529d53b828f5370a74fbcd63d86469a22993ff65fc8d87e2958cd8841097d13ef5472c607290e4a464cc26a1b05935d2d28efcc19354351f02af1cfc52a49edef43c18e4e51d368f1d44de003149ce8788c5aad2239e5355060033fc157e63feb20b38968d4134cc89e92d648bf152deb1f9d60ddedd63f7ec78d14bb61434669c00727d894b41bc32c4436c1a6cf2239ed4fdedb574003c78df7fe19664fe3468efdd004a7a96fda3666b7f493b274e304047d6482531f8f24427275a6bec60726eee312f76109ceb6836eaa78df47ca161f95e0425d54e710733e28611f1f9360f25dbe25c18564d92da4b07c44821141c40eb5f0aa9c7c483039a8cc7831a6caef9a47b0ffa1f4a53121e4e8c88723f8acedef4e4b295e9f1f8d6094dea64b5ea54262ce08aed453d729a14570294212fd1666213fad085e3b75b609a272326d268291f984fada8eaea7ae2e3e10f1e8e834eddf4f2d67a8f1e0e310f96108fbf828c47d90027c1082138b987473ed6efc67e0e80668a1a9878f41dc8720d8c993c36d93e746f70b4302c1754c79dc3a4bc5dcfd0cd4a800c108ed587944e211287f607d54ca19eb5e645ecc0de1c30f7cde8c61dfdb9a472db0305f08e1a30f7c78b4f51cdcde02c2071fb84a1b2db25799f6f7b1072eb7a5113bbbae4cd203232fd9e42d553ff2d0a94d6b9d94c3942cf8c043e6a2635ab5ec5d39173466201939ce8cad0c3eeec05f7aac8bdea66bb7f9b003174a7fd00fcfeca8918f3a900f3ab0e96d358b6db238e0630efc451c6d1692c849ab490e4cccd44b5df9f2e4fb7160f7357f509e32ae780e072e079dd7827abb12b1f3063e44b44aa3ce76036341432346104a3f881f6dd8eb47d297c89a0dfc5a59ecbdcdda4fd7c06e0e59e21d94ce2162d4c09889ca7d9d21c6a453d2c0e5d3d3c152eaed6c221f68e04d44a7f1d59062eeefe30cac9578c531e96ba9ee871998643157b2f4dfbf95b278f8280377fe7ecaba554306cefd5b44a8d14abb6e1e3ec6c04634d116bf2409c9ee8718ee230c9caaa77b9f76570faf0c1f60e0d6db2db544f32b8b99a196650c1f5fe0bf82482269fa68eddf0b8cca953a889919281cf8e8021f5488a6db3ca4b1b5b9c0ebb59dcec9cd45a7b7c66fb15be0728896a8d7e4d458da628b1a346e74d1c50c1cdd801b14e81cad800b4840021f1f0ed042cdf0a105de4663fa8de469649eb2c0c9107a4aa9a46a9b7d0d7c60814b96c4b643c4ab0cf12fbc2816f8b802e7191683596e52e275bf173270ccb821638b3e12b88004245077a38b2e08083eacc05a8d47f6097a0d6c4123011f1f55e0b26d5d6b0ae9196a6a0af8a0021745e737492928b724f442468e96e17ffd3105266596887834f5e11f117c48810f9d981fea2f2283771df8880297b6c62707f32084d75ed028010e2870bfa68305311de266446f031f4fe083d094924ba8baf0e104fe449d44b7dffd949c42858f26b03d2684d2547577daf2f1714ce07d84f707e176697661a1c5165d01287c2c814d49aa7b1c9dfd42dbba527c28816b3b377d37ad9cd9fbc34712181952ec2c4b3b12788f394809c9424d33e508aca6bc6d97fdb72ee83e8cc0e4e039849cd3fef111868f223036e963e5242302a3fef69b23cfea2a3504fe62e6e44983f6a67a84c06877644ff9930892a206f808026fd61793709328d16a20b0192b4a767111fe1efe80bbecbc69cf7248ce8b0ff858f957e97475f61cf9e801579f5310bb3f3f78c0ebc66c1dafedd2d466076cccf422bb47e53acdb9f184001f3ae0f2b42625f3f76be8d4ecff460ef391033e5b9ab2945b775bf2880f1cf0218e4e232c88d0bad7f88f8f198df8b801632a12a396cab944e86cc067eb7ad296314bf8a801977489dc2193a7840f1a70d2b2b7a46cc1779238034647f18b1d2b5f2c35a166e14306fce7cd412dbd660bdaa3153e62c05eed450a514d9486e403067c502551e3e71399eaea2bd85abdd25dd7d178a62bf8edbb9c837a116999d40a3679901f42ff4859c18a5fa54dae238f557011ebf3c673f31b1df75005a33ce845fe2474b3728f54f03925499d924490a9f44005a7e377ea177d4966ed789ce2d7ca2b1d3c75537095e22f724f8594829b542234837f1ea4e064a888d51b9a3478e9310afef2557d8e4a4a2404a51c3c44c1f649dc102704dd9da4013c42c1da59a6b4918182af6cd9bf43dacf7ea62e920f3c3ec1ada6ca1c4fe566280e1aebe10956c3555376cbcf5093f15c6c5183060e3bcc4e7012927a50abfd195addb091fe5c7a7082979083d98f593c36c188d64692d9a3f79a796882ad4d42eb6fab1e99e00a6de02fb54549b24dd944367067d965c13a9b8ea4d7c0eb28937ffd5103274544919d73d2c0fbe67e4caf9793caa281bb929bd28472cf6077eaaf8f9c3403e725b25e4cedd9524a193893125448882275bd25031b4c9baf08d5a4447e0c9c26bdca1e1e42c42031f01e3dbdbe25ab6e320c5c5a25a12c9d704d2a6060b3e5cb4df22c5e90982fb066a1a26ffe158fbc17b8ffdc39b4e25de093d2b14b3aa95ce0458f12692dbb057675bcd592d4f6204b2df07d622aa4ff0e4296b2c0b64889a13f72988f05ce7545055b8b7832bf029ff22819bca268057e4d6d5805ce3b5fcc937f24d353810b5a4aa34af44e1e4e81cfc9432d058d4881cfba5b25c213056e437de648f1640a6928b05622a9cfd39757629ec0d77fac1c437950a17402a3dca2c8bf8871f3ba26b04169eeca9373ad746302a3925049f28dc5d2a725b0c134c98aa5be415b94c06b95cc244a4f50515249606da3664f1d75bd26a98c21814d5164c86a4ae3023b02a3929297458fe837a1590b981118dd164466341d56b932432d052fc3460e19e450604560eb6a42bcacbad1412442e54127f14cf22b36047e52fcec907933c8b00b13025ba222e513a1d74b75160456f376d09245e6d8498de34fd0cf858cb51b5d74610c087cb2cc5cc1feb27e8af6032e454a2993e9c8ff79643ee04a64fda63508d6032e4a52117c7d7d720cf29f81a367d4f8c214c078c0c5bcc1eb548d4db2640008b6034e8d7ee7cbead94c9e706819311d70f147a4ff5ea82fe97f8cc172c0fad5464f614a7ba3f803c30177e2aa1641d6a6c9abb9011bc9effb3a8ece1738f4b46881d980cbe8ee41890e762542ac066c90f194a854a63289241a703a5a864ea33a88f47d067cb95a8da58f4c06aca6ed1cbff3551411b2187023eab3ede73da56390c1800f9542aee01d744b087a059f26c5bb64ea96a26d57b0c9dbd279a78f92476d05a72668d34a23f1344559c1c59446927e4d57c1a98c4984eb6bf01b53156c27992cab68c4ea3015fc660ab2b4e7f0182da8e0d4e82f997b84679a9453305e793c4fe68a2918ad2a167f83f5c57829d80c8b77c2d3a4e03bed22d9c4dc28f8507293df474e147cfacc9ec15348b9da8582db546ec17dffd4f8060a76c783daa02b745f8e7d82d1acea929444a7f2cc136cceb95b3db34eb0d193166159276dba8c138cd98498c1838e96a34d70ea7ad36f0c1d71d4046b72344347ff18b393092e33b7f6065dff2a263851da36b3b897e06292273ce369094efc82f03eb9ef5aa9aa04577eeadae289128c3c59d9828f3f09c6d46531732b61597949b09ed5f6f4867c2458ad9c2f49cc6022760e2478b55117a2d4a3a8d123d84bbd6572e3b66ded08fe728510240769ab6937829568a2e27e2a89d0352378d19c2396c8f5223849ebd529563a21f38ae02ee42444ce8e3f4a2611bc557a45d66f11c167c88b549d630ec1aff7a8e58d3104ff41734a4246bcb68829049362acd6542683d94e08d64b071f112f340836a75349c84a9973982a087e2cf9291f990c0427d3d4ba9bce2f6e4940b06b1e4dc9ed9cb327e11ff8502273a618f5031febfb5db47d6512f6814b13da84ecf841c60bf2814bd5392cde7d6889ee81b51ffd99fbdbd7cda20746d276ca499ace08ca0393728e133da64aaa170f6c32fde423c5e44dcc1db8ab8dd8a1985925a97fac0e9c103a84eea9081df89c2832ccfc9c0317e615122d24f7b44f0eec47db8b5945895d7d71e06405215553e45788393870fff9ce552bac3b726f6044d2881cd1cb972073039f2d2f2ce96056d5b136f09594f24af3d0a65e63031f34677f901735736a6be0cc3ee7de6cff2f2aa6064ee5cffb66973430669dfb476a16919da181bb78a29a4967dd339d81dbf5bcb142277a7ecdc0a78da64c79f805a12c039b9288a7f32559ca181918ada13dc772cda41e039f4b83d010ac8a408981f53aefad98dd61411206564ffb586d9a860c333060d93ab7721057eb0b7ce7bf983faa7deeec9417ec6a5329e9bb3429e6868d2f70fc16349c7c810516e7bea8a102cfd15c2ce0e3a3c6e7c8d15ca401e4a0bac085e705cd2d3e17d88f549774c9d316b8e4a93e9a52500b9cbc4c72372fe8aaf72a0bec66cd20c5f2080becc79049e97a6ea6b194e1b8ba0213ff449bd4dd98f309dda0f18509509f1dbea0acc0aee6a49fc1b7d2e972068e96615505de46aadb57b0edc8a6196a26e8c2f7074505467b94fc18ea428d8360a1a6c06ac618836a8d90c43bfff8f0a20b274d2829307a54123a2789b95f1927a7a2c0a7a89e2334ae95861414b8689ec9830c494ad07c3e8153a133a994d652ae4ed190423981bbb16e3725721b866a02df1faae9a344103dea7aa198c00815217bddb2876fba0436e77b87f0ec2b81f75c9d3b8a3651229b60a824b09a4ee7e0393a3fdb47978aa64c17ea08fcc8ef4ffdd1ebfaff4e52bda8af3b5045e0345ea7564b9f82a520192ac851e30b1ba7ce0645042e2b4c2deccca4b95b831a02a3259a11026b6b7a83901e83d4cf82c0de08edfd10433d5d12088cec3b6da2bb82a89ffc802dc97fa1cddbf201e7f613c392b69c2ee6aa07fc5b9a3461728347ce140f58d39f2d28cd5bed80b153a52383e6be789d29940ed824d4d59526297ea3ad00142a077ccaf72041cf53881ee1808961d6e92e4fccbb3937e0929ea6c7a4531bf076a153b4e4f89fdc523560cf2e6d70f7fca1538606bc6b55e9b7cc50392c35034673947eb588556b6c092503d68277b57e4c79e15dc580bf78ff1153a9c70f220503467b90173f7743428c57b0a7c722f5f9565cc1c6896fc5680577625ba742ba6c5e3b2b182dee41e69034b9dac40a3156c1d7298d41afa555c1061db93b87e8c64805eb5669bcac8448f1c2196a35fab940c656100315aca49d5c417cbb0dc4380523f5bcd5b34677b77e3310c314ac04f9c1b4887c3632a5314ac1ab558f4a4d69f37db6f02f6ac8c004109b816af48d931588418a749a9b3ca19121c628781d212c5bcf62c8498982db58e9f2f8fdae6f2a003488110ab63e930e39e4d441e731063140c15b4b88fbd7b7a622c62738b14e9b513f674dd28385165a6091a788e10936875876907fa226d73968e0b0e14572214627385552f407b527d535b2450d1a4e03bd0238c1e6d851b209567363ed6bf4383aed4d88a109f6849cf4e5ed255aa24c88910936e61092334f98e78b09b64bcf2269042fc155d0df14b4ff6f75c812fca7894907954da413a54a7021735ab41083127c5516bbf1ec0ea6e49360ebc2124312acad5884b41ab4238811892bf4bd7bd0ff6240826f11b55a3313a9427dfe860c1b19e3116c7bb074227e899c42770427d3eb24e5a153428c46f0954c475e8e1416623082fbda24bfc23f8bb84c6fd26b31b50145f07fed9233de5a52a5c1438c44b0318629d1bf3b1a2597818f0f44f069325488db9ffbba5e438c437035f135a57acfd93215c3108cd0bb71f5b62aefe8310ac19e86887e3a4d57be530c42f09e29d967fb28d1ec1883609279444d22699c148f21082e558a559eb6744a9581606fb42555ab2240b0e9d4574712a910e30fbcedae5a0a295d2a8e02a82411a52269281609045220083108cebc07e312000000081a140663a16830220ef54d0f140003582a22523a341a20261a108dc681913010088481e14018140885028150208e84711ce9440f0fa10a8ea20c32aec88a0b5d2ba0a6bff5d4f98a86ab8caa9e0fee014a4d2a8afbd1cb5951a85a684a41eb4ab956e6aa12d5e2a65eb8cad082940eb4d9cae8f4806f163f0a0b75cf6cafba74a5a6a932e596e9ab0c101c9d6122534f85bf6e9bfc683e74366dc11556b33268fbe9abe24fa92189403415b122ca3531d789a80947257aaac8abc5ab208a324c78d6f6b63b18b1cbf571a932357ff991cbe2ea19f8de99ac95f068d7870ff96ec2687d75c15558bcc2df274eaefadf9f99a46046638ce89c13294cf618c94de26a0cc78cc19c1d627216c69a27b1b3cd8069f9f81df640ec70f3d353cf74630bbab474ce5dc965522dc2883a6bea8cdd6bf0146e6f76b00f0ff5ab02980bdc33af510919f809e221f8d6ad32158169a98bf94a43a7b9c5fbb5c7042830abda4478dd076243cfa908de9f6e5bdc41af203c346f6fa5c18c2080b01de1a58042c9b7d63a78dc890bec16729404f9e6b41ac4d97d3ca4080bff2027e52211d4590f542eec0728170dfc4cffed1e28085f60dc6c5904230dc642c25bb8d891b396d66c33114ffefe925c3dd6cfa672c533bda43734b46f8ef37033fb90501a802eb4a47d83d1eb2b060ef753f91d7b67bd2186245956c7a4806bb9d979058cb26e6984f50319cee2277c2b2b42e5dd99268974d7ecdaf0877703ad28f0f87b328a23384ed34052a0ed8f64e309adeb6bd88f05fa4156075bbd6fdf8e876f6e3c35b0b785ba5238293b93db3da70ea16030e9f2fce9c0e86be878bd9d067093e1c5874c841fe217a2bf18fc869a09fd3bf69e8f1e094baf38e070863ad2dc52e0adb0dc249846c0bb7e9806eeccd9cb50e22fbf098e5ecc0bfc06ecfd5855187e0288055e0a6cc4c8db6d8538e58c38a89482aa7befc630151b1d6bd1522745a330f1db8283c75b11bb2edc7c927e93c61bb4be0a1f49b2d1f8c6b05ff0667b085e5e20f2bbb4080b614c930d30940208de0b82b93a662292a495688f437ad1f7dfbd8435ed22cf766f8a5ba9c5cfa29a847ec0d19db7eb392127a15127fe6797494b468a8a3b8b32ae458c203bea0bc18db6464591ac26e9c82289af5438138bdb4132c1b99de295e0c7a76e1c5dab341927a571cdc34585a016688540b6d6863ea4a44325e0bf19c11308b807df059a4b31d266ab314aec2ec0d7c471bf1c3b533278c0442bfe1eb3706f7a498d5e830655c115bb34f2bfb2636c4f7ab6cd793c5ac391d03082f4d282d03c6af13640045afbee18aaa3a54153df4e821aa093a1e9a5ad21260024a29e202436819d2179a25abdaf0d324e161ddaae1c794d0ce615f87c155b0732e01577f04cf1dc227776609399d3355db75a4fb1f4827b3f405380b7f108a4697dd290c406f8860f54b66c9ee74ef878ae283ab65b5649aec84129ffb7015016122a7702be0f222e30f70ddb900b31564bf4cf459bb563c1804b1b39a42a92ac3683134eed5cd208e33418d2e4e72d78f09122e7845378dbe663b82aca645b21733f60ac1b3a5c579b66da55e81234992f3805ae7db88dc141c3767544342cc96c21a032cca4a1dc4ba5a3088c685e023ca0d679041292c63e3b56b9eec183bcb7dd5ff6b2588e81367db76597e1f843c54f245ad5499fc0f148250835cc71c2aef3ba33d499b200a45b28d17dc2c7f889aa236b33ad65b3147aa24cdf691d592351e9491e2da32a1a7df0251eff862de354a5f6229590206eda64006a576dc09a49e73c48ae8e46bcc81b813462d45e81cb8e4c2b0c456194f189dcf92e3e1055e915cbc82a856b72b3324e54f9f8dc1e3d61e5b0b31f513f4ddb754ff7cca18da762263862e2491a6393ba7b0969e0c5d2f63d514ce470f96ad9669a0c0945830b66d5427b3aad663efee4b4f6b7182b397f71080db6d22c5d19bef9dcf33e52410c51aaad0b330fe5a0a42049c15b9e3de8580d663087455a6b6f3037c7a88a82a728961560ecc335c094999f294c221b1a86372d69aafb9b1a06067f5d8c8bce0d6370f676584ed388810f21abd67cd22c3153039669940cc0a48b201a25a932cccb747414176ff587089c296c910d035753e62a5b762689a7cf23dd7c5946eb69cba7a091f7722a853c5bfd58a51a1229174f0ff5f6f064ec446f53fe631ce9323b1f038003d0f52aaefdff4725294d6ba870c4f1b827edc8dc8e1c3604aa45dc78d10d545a664346866b004f6644d56c6a7e381391a8aa95a2a519960d01ef110a6401b6df484d62843c4a7f7a29e3a07a37befa16a529b3b059f7569d71b134f01b135f18ebe220b65f2bd964e42af70f56de0dd792b43fd79b03b3a6dbd863503ad392e3e5deea6e8e820ee4a3cdb4842140c8b54cc0927073aa513614d83d95d759f3739c176e4a9a015896994078bcee486388d3f051fab043803d8cc3b54f689f37c1f714b95fe81e4ee4410e59a22480ef5f68f148012ef979c92b171ef8db54768bc11e82325673cd14c4933681f44dd29a8ca0e89f398599acc8306fa6bee5b461933293332a5883d3a3b417b263107b98b7f28f8e2d8bf85338eb53e8b1a588063be447ad2da264506b30337ec6ab123446ae0f87ba9ed40c7e70e33a59180d7558815a424af1557401c022899fbe46993c18587526feba74e6fee652b157cc968e9290b460424dd6e0c3b5026a2cb6848f2a84e0c742e81ae167e8282a44a3049289d523cb03ef0b60d08ee8b8640feec235c8e25237c2ea6cde6e46eae1508bb622532a1fa0d9be91b6f20ed4254af002d3663dc597b23e6f8c3c14afc78e51335edc62daf7ba6ab129996e5ea6447e43ade9849118644eb0419a3d4ad824f9193a05eba2b9485bca778bb2e92c4868460fa359daa3b327420d95a00a633a14220d570a53db2b025014527125d6c3a08b6873048b607866ac3c85c56bb2fb3f5e7901f9e3ad2490b78c272d63943793384d57f5fb3be41ea6260ba57e9722296972ae36ae620186ea4bfd93ce4382531e42aab3b67f56fc54412cdfc270812487ccaf6c4fc3c9914866abe65e110d6e0b33c3597e6d3879024685a5acca745edb9486571acf07f230a8bda9d2e9f2923060bd9672ef6c4dcce0f26e255853cfa681e3dd9237262c970689576367cd6ff7956b9df1f2b0521c6e563affc96aa4ee44c706432bead59332c0591da0114807d7e32f5633fbb12b54943c782c603f43a24b3bd1aa538644745d98ad4e2c467dfbcf57093791dba9f75047a353c26bdecc429ee568e720d66d61e874c3eb569b2c10ce2526dd9ed89f1a63344edd259f602855d79e2721436021653111dbde067e8c39dfaa37f3a2b4e71e547de5cc4b81fa105ba79a7cc97cf8d230f753799762df14f65b34de75b2d56addfec6a2eaebbb7960a478fc619417e2f2dea3fccada923b74b06dfdbc4b4465b60800af43dded429244e26d4a4f50aefd34681b5603d8eaefd02a339326c2215eec8091366be77583de18f9875afb68481cd82f74ff674939095b344ca2d4084fa91bd82ca5e0b2142f4a9bb62694753c3adef93ff27b2389b79bcd9ddc36264466f6bfa636c76dfb6a3864ea103d6094377dc08224d6081ae609a9875890cd5c9de45d6684f30b39d9dd2fefdc2d4f7ee29a8adae69a658a6884314a1881d38f2d49d76461f359506f43e068483c358433820c7993b8e6bb148c45e8a904cb14b8440007a1435829ac8724190a68c2c0293ab2e0abfe04ceb9043b10f2561bd6831c074f16c90684c96a0e92ed7f68a0cd3245150921a632eb4b8bdb06842d0ca0d62ede1d0293053b94462353c66cbf26b17b016d9c0fc8e2fba5d22b3cf0c258e4f9fb14b0f355168b4604fc68035f3cd1fe4e875ef48ebd5f712a9baa179908e440c7a77f80b604775670e85947d8b0fe8e11047a81c56c109a500383331cf99bc7dce9c7a389fc875e4476f19de171e4936df0e54c8eeaec26ff38b2c72ebdba214875b9efb95cb0800ab702fa072bb4186be9aa88199ce1480f91621ffb88fb3aa9c68c8775c159b1a27b883c6c7410c2733b98a3c7166b17cefb3506651c1484ac944b9649766c350a5fee61a85cf4901ff160c367989363405388da425cf7996f6f8182204ca89fa34b119aff20427e525c33511911c72e4e4d162b03d6f8e7653426855dc06c1870c94823d80d2278c62e4b1f715a5e4a3f60089409a47c78883af64218056f6539a12c7bd615e8ab19b4a4564c25b459e5c3ce920f49d4d368ce7573e48aeb44087ae690db4420a12976802859eba813b88ad0234759b8e3c8564bb2036f21b5cc120ece61ecdb80589b8da150df63d23aaaa90e25d9df002e61dd87cf13b004dc3fbf740978eb6efb349037d4ecdb2694c410da386cc7bad5937a067232da02230a9a885824e4109405e92ff51e81a055b56b90e9083d11f97f6dda63013f90a664f2b3ab0e47c480e388c0e925d8ff92cc378ed08bc208bd800dd05dbc30bf7304db282c8cf3e6d5c610766693af0ad2471d20dc31457bcdeb23507c9b6d1d9d86f902d7101768a913db9d07cdbf9e44ea9ff00e5b771a9d78b469eb5d165c76e60fbe4649831529f4b82b8e95aa92522d00cf740405eec623a244ca2d5bb82af2dd5f515f349eaa4a58cd21484643869f86515052936b4bb9665b731205766427b137031bce3cdf32ac9a78b7d87981143fe01a1870f3fd1da6b2056877763e5bae6609fb1dc4282bc0478f2244b5ade95bbc0cdde018cf25df80725155358bc5d0488bd5c1066cf2c0589b3242556bddde9dd091ea44405f55c7e1722a42ba669e4aa740c49fceb6a67560a28ed2d71f7f147144bc41da845d1aa2f35f97215980175502ced6f760059a8c00cac02e8a877f72524629b8a3548338eab82a806e0d688da288faa3200c10ccb06f91b2ea53c5a14555abb8e882b33586420ece9152952ab8c8f50081a01b18ff41ff6f041e2f93d465d5b3a5cb1d9fb32f6230012547253bc51ccf7f6bc3b568d95c3b175cdc37eccd929b77f7b68624dd567e9ec8d5c7ef5ba30ca88c01bce8f8a46341e9381636091e51eeb64e86d6e38d98b9a47630c5bac748a4abff61297970e9eda38b0f9f9926bf9c0e8780e7efd6eb0b4449fa05a6dd689ce662a9f0182239a66b04ef146fb1eefeae080348f6fdf82069596688642e3787af907f544749cd22f09806d13df7ada56129668512921de147b053f731d1f7125afd0d6032a4562dd06bc98fb3971127693167936533082ffa3478c85fd8182dc23a8270ec18bbaa336ae500d5477ad23efb0a204dd3e96f3ad6351d91f79d8a23d4fed33113d1354dd0c466d84de9549bb8cea9f622c25281a77910b9414cbb34d6d600590235779e6d675fa2c3e8bf1516fa95dfdc99cc44a778f5cb0de8abc8d38310d8baea7489094b7f9151694c93d305b536da6f1432edae98f0eb55b9743a5c3a60606fb12e07aca1310db5c86803b4ec66b7dcf052353f37426b36c65bb31ebf191ec67938931a23c854228d882025dc4289f8606553d14e5b141f1ad9a903a42b183e3d2f3218ca0ca81d2fded7dac0692fa937a306ed4222afa4f31b5e85f5b5baf11e3c0516b7218e77e17eb9e3ee2479deec2980aa88c90ee2ec57319db4bd05657f876b7060f9ee6875ab854ef95d630021a1c575b51374404f0a0d505637c9863ce1d44944edb9872a03c197cb9583bf2c0e916fc047a04bbcb6dafc35c692781fc500507a7bb5dffd04265c732b60c3f45ed3745cb1238a976995fa9e2814bb7800d17f182bdddf70c440cc735ddcbdc467874fa89e1566c9fd2d70d93362c27eb65d78e68c95d9806e94df87a42679f461edaf65cd8aa1c929f01b668332964f87428ce07a216a29595353c359fa19bbe9163828a2274a9d7cbb646e5d160af0613c6253e34bf67c5baea255a1b1d7823acf730c95692bd280a50c2747394460546e75422ca961a01b270a73445855e43d7bc9c824ccf7b5fb82f698e1cdaa8771ea3013918563aca63b279a32ff82102e088abdc63967728e946f27d0b1748011976c4298012acfeb63a5a152d8a0f8f471520122b6bc853928d7be748b90b86cbe741a7a023e5968b403bf2e268c260eb1bf129aafafac0693e942e799baed33e184acd9339b44caa0662de0bccc90962ce6d2e22402f22cc2180926856d83ade7bd4fe615c93746bb36db5dfb8f52f054934e0cdfc4926d39ec70c0ae30faa84b1c07536c41f6ab338a406b9a6d72fef2c021988c0acfd9340d84ee83e5fa3d4d912500b7658057d103f490b73af20d82283c6a63ad99823c6d2cacb940d3a8ec0add23378a5619ecd1732adaf9b0d892a427377f8e344bdb94a04f3d63f3fcb2c79b175fc9153e333be81f4dab8d7ca6a4d31acc844d8f71b7c190c7f63457a7bedafeed917f146b7fdb922141423d50d5bb83a452aa217d2886d4859bde54df7e1e9b4aed8ae6c144e6263b923bc11b79bb2bad2514175cd854e2c44384fc5af72f8836eafa93dc5f38e7f0172c079a030356cec0d0b5562a49ae405b7a04d6e903199a5efcac17c061fc63f42ccc5551ee557401c6d3e2365bb536b579587e326a595a8bbc752bbab9ea5cd9a4da6d41684c0a2b17a6b32f113ec2c09ce0f471e07890dc3a13b0f982308cdc412808db829ef1d7846161d6bf2bc74803d8bb2acd9cad890d7aaf6599c604936c80bcdd2498cb9bbf81e6a53cae73de2d408382e07e25aa059811eb1ff999ed42276d0d080720053022156af525122fa65f422c589ed53dfb792c510a703c77ce2b84d54e5782ab5869c70d7598da6434aeae21e8560ecc2301d7424129360883193ace0dbf18e353d8424ce5b80d8ca4fc3ff16ef75256d7a0570d93b9ef396e72ffa5cf541b722935b5abaeb7357d60068013245cc2cc81a7571fab7f9155291f2aa00befda8b8981a544079ca0c9e9ba6c98645071884936b9c7ba6dbd22f55090657be6124b761ec12920283e053b99aa2a3cab3d3294c16ec956d421ce3afb8f1225397b8db4488586ee2e97229e32648aeabbb62545100c4c75eda431e89be1074218df67cb2d863437143c342f41b782a68b70e49eb32e48c94381b80a139ba93a9005ab004fedf653c7bd640ef70c0dc66c7b003e0c58a0c6d4a03026cb868399aa21e785b023bf3da9fea9678185dfbbbcb8e4a5ad3d6c0a1f1c94745c52585e3201be8843cdc4c0943e87d690d610f8d32cf3849482190d724c269d12e06b6f678f7c70e9f7499287a4143154ecc0a002390e261feb5e714786711fd73a26c9ce0b51cf972274236bc9aa9494f9ad2650acac3b144ea33c0abed8c5b5a9d0a5481b543d59f350011eb34de0ff7cb2074f11aae5767082ffa3939ffb7a4d20f82aa0d35c532b90c625daf5f3e9f06f70b78dcc6f5353836acd98e49d86a0a796b87019832e313428a139f5cfad74f8f19606590b5189eb2890b025e63230f66c0a4af94bc7e679ec54a71bb09fb0658eb00c0c2c076c251b857005ea36aa5fc3a5d12b621be8df4e279b286c7b4d8bedd940aa2fcd9866af709fe5d744a1ba7672ed6a731f277f5e166468801324d942d3dd9472dd4b8b62160adbfbea45d8a2ff858295766f61a7f6a2014224639b64093b64811ba1fc06bd99699f001ae3c5b6f7dfee929a3168d62ad55acf6fff1373b2ae6dee4adc74e30c8919c045075e0045297dbbd9d48b82058e3908efd20bfad8c482097d361a4b5ee2c90650ae35815f3510956cc13bf07506099036fbcc765e8e58d90b1b2d2bdcb4aab5a7f044731444a67c5892a00fa0c3b11f2655ae799441ec4a60b484d6b7992d73e09d526cb94f2c5e02ccea6df03201b4efc73ad09451e2d3539e56790b3000b870f190666aa9dd786d445f340dabaeac4440411e98435815b82b8c2d0400dcc30089c7a86980a694879032f3e8951fdf680d77bb60800dfcdb40f807883a910289f461d41f2355c05baedc114914f60108a7ae4d68228400831f03e302acfdd86e1406ce50ff677770db4d4b74397db5bb2b86084f97f16387a09dbcd8a9ccad68e390b0e3c14e7567d4f6e78c629706bb29ca90cde81a98da74825d87338aeadd87690a3282d07ce29ef011c1106b41367a6dd32df31b9921af3b4fedd248549c4715d2e3830613b89c2a7139afcbab491ab441e8e5256adae8933928684c1251fe731935b8ce4851283e931f1ca2369d1d2e809aacbd891a6eeb9240ad278c104356622a60d491abe47640e006321e7ab23774f2b8e10ee4924fef83b3abd3ba637ff4bc09c4db3b7bf6b1d12e4067b64721de97623aaef17b486d1293764d46e661fabc2a20a5fce8a14306e93d7db5a541ec2593873001a2d150e656e380cd08c73a962f25607465f27da3992b2f34a63be435bc71eedbde1d4d006a2cbee9cca2430d1bed4e9d6724d19418a6b023cbe57fc21fec9237bbb3ad8b4731f0a13e6232a10556588711a6272cf87088093b670a39e3b00677f0cfb0083912a16ed8cc34eefd4035903225a932a14b8f3299e890adeb4b0a4494eefec562217b4a991a2a6d60633067ea87c925966b2cf2a631a4bef3eb25ed63c128cdd8a22b8fa326adcec00ab91b06c4d55f7671685254a186542338207c980f17d2621035bfc3d5c6bb0b81a5f9364d965349286c3670d252c9041bdea76432a4cda5fe2d5ca6e2db6f899d6e90069368719ec62df63890a233bd6df53a0087fc16ff88b5d7a1ed1a4fed88ef5549a23e66e26f02535a649e8661da032fd59835a67f511a87f64b38560dc47deda9a2a0d5fe3c5baec4b1bda9c053a21d5c29ce1c1fb4ead03fe1cd580ee1d67a2eb4451bc4836ae35b1660a52aa2f217e9febce24041834c0ebf004a01af5b6c9deb4fa2207029409e365d57bf6e593b380fc92ca562e1f6be2b5dfa4c133f66ffa0a4283baa2a3e979585adbe1f80c5199b4b98301affd00605e856bba6bd13e065880489e6838404a0c658e11b3f005f13c8c5caf06e6f12fd492bacbaaacc05678b29185882a1677519ddd088a91980fcc389097e9a753c5d23c92398dc7e51561d81516b18c06e2c02ab32e9d10248739ee4ad6ea66b97e13780e72ce268090e94fc29aacc6bb780591dd0e985c715f2b2c2d166013b561d43aecfc8da7b392de1cc91b136776d4c8f645603c048b4032512ea36d8228d141b143924321c44bca156388bcc54e0416d9886101d286cb4c8303ab28fed0ae20dfaada1d2ae3313196de5a7e7aa68bb78ef9bce8e1857cf7389756e68b25554abb302e774fb072b0aa50652bbd0a4fee015a801636e4320ab733af2aab96271771fc576d4be73e96b3875b5ac581d282b7f2bc1be8528f0fa72f513b9153976bc94a31f37c5b006ee43edabddc04848741c7ed39742f0551af58aa690f180a790f14d2f53b37c0bf7bb2848c52d5fdc71928c57f5615092f53de736cc26c415ab9c785e41752797218bf88f4b794956cc13d9fda10ac8297c2f11b18695445ebe17154c0b04f45e6d33729629f540780ec7ed4930c09ef1a562460ac14d24be450052f0a4d94a1b2e1c74bc9880a00ab1488db863f9b8e87f25a2f312c442d4ad081029d5817dc7e5614d3b3b9059230b40a952316328e7da98e9e2e67b62e32b45b52543e5c3bf442285b6dd6e4b54480dfd9b43e1921c21dfa5a65b9534ae38a5a8ed84638053fcd731c46c3e21e6c0f912d3867481d0c8129a966a1912fcad0c3ec7ece6d7f8f405f704a969d8fbf0b1b2f3364dd2ec09d15f57c195dce08d9f83ff79b404cbaf8906276b0de004a31762e32f542a4501b1188fd7641b140793347d6be05d10d106c7399a9428349802163d985ed008a58344d2bd2d0d951f541688ea0b5d60220343fdf2461994b361919301681c2850a8418106351354d4505207a5439450b31a6548493111793f8a5d0f2527541135d0388f50768022f6517dac500c4ffb4011112a5ba7ab96f052149fb3c87634949da080a410a8af4fc2f44c190a2202c450b4a1f5fd5a3a50f08a9280946750ee031450d9d9135a1b056cb3a126871bcaa05ed796aa1d0022320294cf50d4a05a841a26545e42e9d03c5ffe4102a50514a342f5ad836a0844550087d628685e448434883714280dd57773abc12c93424214b0b4fa295b3551c0236bb268531407d7000d9fcb0922ea2b25bca00f95f18ed2a197866af00a2524147389ea7b2dc5ef9043a15d286059aa7a026d146375bc4b29d25bdc2cb22e0ab32e20d1a485259ae265e18b5116a5bc84021ca1746ca6ce4adefa0602052314880205e400e5c4bba4fa60f0637378dc8e3c0628f145015df74748c2e14f109a13d6e8b46043fec756601ce22a16e148034f153610ed38e30cae056a44289a40498562652820e18064fadfe4aebc46b41bdc0808273f97af182eedb95f5bec2bd444a0c9edb2c11bcdc33cd89511e726871b73c6cb2195b19516d3cfc81ee5cf89dd4b9e31edb98e1032f1cecd225b27b8f88bb66203040e8919ab40cf374fe12486a217f515044019ceda9b04d96a705c049a8fb9836882ee598b5c7d57dcc6466bc2d6d1016560dc65c40c2dbcaff6fe154868c814008c17c0dca226e68d08b1425966d301a3b4e8f9bd780948852f9e4b8d716b7a49208452662816ea935028662e67b94617d696fb62d010d5dd97fb61bab6d0ad22c9b6f1a9bb17dec7acf85e4a29b96bea7bc3c35ab2cd3b5eddf83d8f8106ac952fb9d186d3fd37595380120287683092a5e1df946b0a95d39925e3370fa53be1130089405100849b619f9a3a55bc2c800dfcff04bd4d88a2678c290c0b9a5b610e0363aa28a2ac27bda18978217e280f89f4357afb98d2635ba135f71d863b01b0ff814e0e288528fa9f91a6b1753a6878ddb724883cf521f3061845d32820ef66bd1bb55c0de30ce8e48b0a7862d133a5653a8d2eeb59a57872e4d605ddeca4534f1c7beb93d00381d7c3cfaa635f2a031e403275e307a54d2be02e53bdc13e0ccf2304563e37077534af28e917a9f8b68b2c955cdb217171b82c8a923297f0152da3edbac650c5d1b908414ff6130a2760004815ba97009354f33942d99fa1ef81071caef31dcac440fd7f93fdd26077ad414621acf4bf52f6ccb4ee1bb0b0a4f55114bbbe8636476ef158f24327fda0fdd2a56bb27009bf0f592b0e85c3635485d249e07933201e9d162107f196669a1649fae0a31cdc6eb98680e715a3a065a0a7e3e42c6fbe06abe02871c1760ebeee958634fa8e18bc712c8ba1a9a720b21662a91e02149a7a3d4a504f10b3d8884207af36fd5205dc2d81ca6371aeb825992717c50f523d327afa6d44f8ae328b4549e16901456f0e7a66069c126641b43c40a19354048959d703ab5a729fad650584498b73122998815001612557a1ae444ed7f06c6a9c64e0b7722cb272c8a9881fcff093bd1db8aca722bae375076d934cb8ad5c61f16aa002ce12bd9b76607e2f80e8a58ccd4124bdc3b9ad94a723bbb1d36a1410796f567cf2158570bd1266856b88e215d3799585739928207604e7b6a8527cd24c45b006035052080b2f699152eb2935908d305a68327f26bbb56dd17b4ad649ee88435f252f0fcb4a8c95898652fee24bf371859b1ede0e5f3e304ebf203c45cdc3d42123fb2e277ab3ff122a68652ca91083e19c6e78a1b1c9c483ab4ce318c9fa922e57b199f8e8390c51aec391f0f2c8a6d18c2841811ff614f6070e246860284cc4cf220a5729c61720b61c942dc042f2ce2d7c1a7e7eaee634e47683ab069cdf5b22fc761e902fe59597d87614c1178f5d16351c01da0b72b3c29cae8c6981616de4f3cabc817e320702f5aa69b95072adecde27c487a47961d5406b933692837aa7e356e26f0b2e6231e7c99f79e9a5223408f2e8599ea5dbc2fe4e9c8e60074ee7d2696c1f01baff768dd1aab19adf881dfc7909843388e58ef3a7a34d7b81c0c58dd417c23790e4d9a9add26848faac8f3614e360d4230afa9124bfd69ebce2cb04728838e5fab1644b03f588d1242dfa2409b8507240be1b9f2b7cac26360459e725c1f593111c2f0ad8d526bc81433511032af84ce47818f21a9b25a76c372aef5865c38058c38b5bfa3d5ada2f2844e8a206d5fd794ebdbc5cace469a326113a7a958af43672e560ccf3fba4d23afd530da9ec2904e1f54758ec10bc6749457eca59467cd7fa1dfe3d7c61f5180384295afed6b342ac28cbf608409b5aab1dcc48045867e30151462b339d1fb84a9fdcc5418d21c7870ddba6bffdd5864324e7a7b2605b6abf762f203fe1272359f4c55fac95023e86aea8bdc20ea35e33c7c8eb3201eb5bc08a9820f66c6c33bb337a6d373ef67132ada9f5209d149a589a24b7424be61106d98f8a45c03cd4a70069944f430cca07a12bb4f66788739d374cbb648da417a58708088e0d186f5a47f6c30d1e7358b19f65d27eca04f927165e01391bbba01a47fb3f1f60719c34ff7c8d0491ba481f2652098aaaa844ee631cf7a219dcae50a35d2ef144ecbd2b3279e64899f2e7170c1c92329ef8f43c38d98609abb98bbd8251428c81026f440c5dc699f46869a60db1bbd7cc368a14b7817aaa29a9381897c3998d8972905e4a3f5a4388c353ca931dcef75bbb9a0bce7bc5003a0d989cac46f66f0daefe89602406f46de47ad5a2689c1f413ad0d038dbe63f2dc39a6892f54375c8de8c6403c6ef64caac8752b43e81e06b499d8c2c499b25ebcfb3cf9fc7f4e4e68a2144a9e65633167860ce477e66e1e686c72b9224b9cf2f88068a502840105089429939cd16abf23ee5131cbc731417d4daec546445a9aebc7e9920242dde50ec8f9fccd165db97b3bbc2758ac1d3a5be2a0c99afe1c801c4eabe0e5a64dbe1e08a02008ab4e0c44fc9bb06a4fd0615fd079052f0479502acceb7f5ee7ff5feba06d19993e4151599a1065acf01e0019d67467f55b8a5e333158b6c5ad61da265856eba6470d201950f6f42f8cc58b3c9e72a3b70ec9c0cc7d9c8de55914915379be3ef181e9ab3dded33dcf191765883b4078566309edca81723baed52b4131caff1ce28ae7530eec4535efb719b27acc3c7333644e19d237dd8aaa841c6a9c1e0838ea28c44c2620c323c10673f65e3708018af78342c7d5a7199d6d88838dbdc9dfe42abaad9b65525dfa0659f34895b1aed3168331db369a650b402b88b41c6d299a0c98c1e71ee1786e735c4dc60981c95b8cd7960084b50fa6417f8c38cd005d3a1930d651c9602fb126c7a50e8afaba2597264234a57d038a4d268d3ac554736a295a68d0e6495294c4f3ae7f03278d958b3373b1bd1e298187e987d4b6d7d22525c2f8759e1b9df5922463b94ae671dd24c34acb02ce7ecfbe68c6ba85df4f5ba91353f43ac6986e6b014f0486158f2a7f2d9e05613730186d3d19194dec98d524ac54c922ec7ba59982ef36e98897776a92dead567b11eaba10d48348fbd6acf71740544ef088d1242ff2d54df03591b37846dbc21773b71aa93332456a74ecb6fe791e6a252b60a2ae3aebd05a99f3a0108fa5886c6c9c2bdae2738a6015d6a8185b3c11a752c9313f9626599fb84f4484d454166b64099e4e8383bc5f027e724340c09589a92b2d6660af422aaa1a7ddd2f1abb5bcf51f922e63320a11485053e921a161cd9b822c7c54e960fcf895a3b8ab7dcf555a1917cf8e8c34d64e1e7647b34364bad78debc216df8d694952bca2e43a5d1dc4d36e58e96bf30b61adf2adc5cd115edd8478e56856acfe64c1ea14ace8142e3351b313b0562596f9540866307387962a4424d1a808d406e0ee80da312a1dffedfb487c1872fa102f9acaa3d9405ee73fe4b19e478ab69ffecb4b1006319eb42aa0d0ba49837b5a18df19ac635ea03b308e010084a2fb59fb020d44d483599bcbe1fa25072e6863cd144d0ecc864f34958f05bcf38034fc6837325cb83c53664e8622af5e862f23037d42c67e1597017b0e86a6b91be51639948160e34ecd33276e3b189683367e65a751d68c7235bab777001735b9d7c44cf41c711b1490b810d8b79ef2657fc27b4f966a41949e3a701b207a1f6ab4b563c7d53cf620903f1e03f0a50095162db8394e54721de4a484271fc74bd61650cbf6b29464e7e13fb791acf2d8c926722756a97a309ade68028b2c23c360909a602553e41aa8291361c68486b0b76eaf1d9f45d5fc56b134097cb5d271d35e8729a11e3a21271f22404518314dabe25831f092981f3e0b69da8163e3fcee32410ad644e1b8e04ef80c22229b36c5e7c1d4a092b8470e6641f9998301f98e6b8276b4ce6611f96dfa6e72907ac131e6fb5657f56bed1d21e07a31db74d24d796a6e9c7fff57e791218cf3ae845a139200bc5901da4f6be04ed458a85a37eebd9ab1c0e678e6d8f5da008cfd6fa7c24d1a41d6219772a8f2a0e608464cff4886c45f1fcace89be33654b88370059c05291ac08f815f44378d888fd78d26c49cddfe04884f09e9d5c4b172753d62c41aa7bf988e9cfaa9c651f6b88896a43783d91677765a0b17f84ea48941432f7665d4895693882a6a5a417ca035043a8c2338a145af4050668f47c529fcc6312065e11e3e8c696363aaa6f613133fd4c8c37b1446ea625cc8fd1967d08edf87c0b6ec0dc8c0bf63d21c09c539beac70c1a92505723c4dd3417e756441e18d8896dba019a0fa3d82d64545b389f59a365b6830c516c8285e7a472342e5277243d51597664aca5be1374b08b4b271c305e565f50098e1b6984c630f6e43c8840ee0248c3d545c0e8d094d7b55587d76d3d4f3964e5ec18ec67997b96220b4ef2e8320aa09f95bf6dd2df9a55c46eda7c3f194ceae7c0d7843ee452a207919f3e894c8b73e4dab887788e7ecdf66d24fb0d8fa3d2325679e55e8c0e483e0b6cad020e96c45e0b2b70b61a0730c30c33cc30c30c33ac9ca72df7fe8317a9bb39252525259709cd80c6c584c6c584c6b50de701140b4c0b780b7f08894421a5d118628686055f8c158ccac141c249314f86f697257f0c5df002128c2a13b400052b58810b2e50b6b847b849b35d7b4639473871269639549c856b849362cac631c13e5ebbc4c231c20793b43192b8fb9c369b67b8457852e1248ab7df9d38960ca708ef463b468c6c541ee544f8281d653a8ced21c2d7e8e181ffc55ec9dd1dc20b398b74467510b21d6708cf82a7574c8fb9cfa11cc315c28bce91ad345bcbb54c121c215c6b982ae5b289e1b335084f3cb45d5a88df26ef04e1bd4b466a3454cf8ed5e002e137f60c2dfb66b439860f10aec7742a8e442e69eafcc1ff2c764ee1fce025bf747119d41bc52c85eb839b1c887dca281aa53c0cc3707c70aad33d0e29ec4a1a695eb83db89212425378e6be4d0fde27edcf24a6e6c1b1e4153d3c78e1d343738bccddc1496f0c3d835ce9824ace0efea4838ab3be94e1375707a7a663e5fc6943c0d1c1e91862c858a293c34cde1cdc105ff3e910ed31454fb0b5293839f852628f2f35ef02c334b838b8f9f1b656ce920b56400707274778adbe7ce271db09f6dee05ba88fa88621df021794b7c1970bce0d3e8e17cd2a733131fa27d832255c1b7c341aaf31323ac192206b001a708001a008c706a7e423e69ad11851fa35b8e92d99b466e9e86be9d4e04bf2c9a0a18617f94a1a7ce9194d6bdb7a106b3478fd37a1a99534567268803b83bf3d6a6972f6fa89314371d2b5f69252067ffa2385da0ce9d84106ff2c83a694db31f857d1434369c5e0d46ae69864a799ba307853123acea70306371e6d7ef1ff0b4ec6a833c8c675bf7ac1df4c0db545424e16e982977a4c72ca33170867fe783c83b7e0fa4a55ae4fbf9d472d785d114ae6c52c38975298e8c8191e7b58f0e5d782a4d0fd151c77891a7923c60a9e5b8c18c6ec1b6ace54c193a894dd96192af8a04185c9488ae77f0abe64c73f39266965560a5ec66ad964b9fe2d1a05e7c16a68913fb9dfa0e0464a6b6af6ca139ccdb9fbe62a27789e2743cb1eb6dba5d2043f23244465ea14fb99e08620da5ab295736996e0dafcfc796b72a9b412dcf28e998f71127c0dbb8b41fc4282d7491ad544c8c33ec9113ccd3086c81a2ee273c408aae3b8641bb122b89a1ac5cdd69a544588e084e81411d619e6e80cc10d19927b0c1db1715e089e4d68d4a12b9dc64c105cbb680dcec2cb630b10dcd09da2edc2f7036f62229a64399fbc9e0fdce0d8d16904cf20a3bd7063844ca7868e330379e1add86be58a51b3c5c62efca011da3795535a6ae8c2cffa71cd9a6f947372e184479325f8cb3d88c1851fcdcdb3b745d3d8dcc20b595679aef1cad5b6702e74546e4d311ee15a781aa4a5cf238fac490b3759ab584a74bc7fb3f02346ed6e8bb52cbcd8e629e653040bad63e1a458fda64c0d0b1f86895219ab83bc9d5738ebbeedb9c2c7ec1857b83d3973fa36cfc12aadf0b6bf6385354e9f6256781e659a233e3f8e7715ce47c9d02f4759157e8a315da3a0e9392439154ef89cab26c6149d4546852f9172881839a7707a563bf27b7cf68e29fcf4205386d408277f297c183fb3f19f21f785144e4d57869e1a937965147e88f0e917da4b43220a4fe3c4da3233078b84c24f6b29b9a77641e1a6c494831871b2d1fd84db187834ffcbc0b1ba9e3036e830e339dc4e389f53aa36364d336f39e1e694193eb7dbca49bb09274b689cec31ca16bf26dc8a6c953617e53f9970a3d1c9bd8497ff07269c568dcc612e657b8c4b781a12a9659b39a786251c3b1bfb7ce3db5a57c2197f492b352b25bcec1e7e3cd45a63ac93702d6da7e39390b2b14ac2edb9476a3d6a24fcb4cfd2c03778b507125e9691c79f24cea3f3081f2493f6982b5afa7784936b2ac7f0b071b7a5119ec7b56493b3b45061847fe10d728cd822bc741c177f961ade5084efe9572d54f892b413e1bbbdcd6c4ea92dbd8908c773b0cbf8ce43785dbe59b423a3cba521dc587db1159eac3b5708bf26446545760c1e47087f22499294f1d5566c108e7f7d8b85f9e7d552105ebb59105971d43895817063e5f9d031d4937d00416cece338ae817ff0672b5dda98cbad1ae8072f747aec935cec839b791a4ab4c62934453e386162d228971d4f8cb8072f39ead5cc9dcb7f433db85916eeb637433be4f2e0635c15171ec9c3320e0f3e18ab9cc9caeac7be3b78a2619363b4f49cd4b3838fef616450da8da37475f073a7caa58ba152dad0c1b594c3c4acc91baa3207efa39fa5904198f5b41c1c798b5932223d0e721cbca4fe8eed633838dd20e4303926e951dfe06afab746fa49fad20d9e4f454d9ad2b3fd6d701e238fc7ff0dc63d36b811c3b5e47bbf34da1a3cef3af7cf91a9c1fb709724a7096360692053abe70a231afc9445a6c2b64f3257677036b4dd77c619c48a31839f9281e498256570c2245169ac92c10deb763ea11a83371563450adba4492231382d2985a83f94e48f738085c1c0e09d4accf88d19581c01fb82772b593d4776378f792ff8e3682b97e4cd979ee9823f97d263bc25d3d043b870ceea924f258e2df81f23527a48bfbc59d682935db3b95b3a2d0bae770eae9952c7b0e08b78cc4982dd69069f0c76052f1a4b7b78b558c195fb9ca2c2af4dafb805ab829b630cc96e1efa55ea50c187e21731bbc3b9953d057fee91879e7415b21c26051f66cc1a6ed36951f0fe46a32bdf7b8c313228b8961e5cf60d19f3803dc169f1088df9cb72e6a605cc09d604dfec35a68b19461d454990674cf02cb7f4dff5c4e64d1e0b6c09684c5d49e471b800a6041fd9ab7806153c1c35b8646149f0d342f75c6b7ee0957382dd1e181268c9d6f431fa7bca0b5e900017c8e00537f8e20531b8c1f957806d05404002015cc18ee0855f36b7d4a1720d62850333829f26a23374c629826f8dba3de4f4b03685be6044f0e7eaaa44f267508919825f8e734ee5317fb69a85e0e54721fafb3c25cb2d172c084e65d1c86a11dc345380e04ce714a984c17ee05d0c7d65256216b2623ef034b37bc6b081bdf06c935fa5188d7b45f342f1c26d94c5719a7d76e1d8a72c928dc2baf0b2ee62b498954f9277b970fb7eb23f0c142e7c104b452323af4f0dbe851773b9cb75b06ce15df86e1826c5ac4d9b5a787df162e1b91a4a86d1c2dbce94ed1dab789669164eb8b2e8161dc4571465e1a399f1541b7362e1440d6f3f36fe9b53a460e1847093debdc2b36d9825e3f0b8c2ab102bfb36b6cd658f563849335f869c452ce4c20a37fa1a6f86d95c851f414c72f0987ff74e156e085e1b35354dad5f77a970ad5274d89d354b95d8864285a3311323f6a468b319a7f0e2336504fb0ef628dc6a2853b815b6c19878570a7f1dd54f239b3cded3198a149e24af98e327ec233a0ad7bc2a948cac872c8f287c47ad6a86a042c1a5a4d690621e544603234381c24bad1e132cc2833d100cf50927a5f5c8b28b217779c2eb8c71d924a323c76485ea8493613566a3c5486dbc5c284eb891af4f4afa1f746cbb09afa3f85f5abb54a134e1f5984684d8f249c36b5aa84c385ac126483bb630c155acaaad746476b98c6b5feacd32394d41a84bf87241a53346a7b4ba2ce14fe71c5e24c83f885855c2793b4742a128e18ce3adac068eb1e40baa49789673c87b8ad992843f61b64172aa5958ae22e1038d512c87cd552cb50c19c8606c3500031c680614249c6cf95d35493ef737f97c41835bc1abe08b2f5cd0821318a01ee177474b86dd7184336b292bc2d62c661ae1864621f7639c6151c2087fee521d83e0297a7411fe854916edca83a7d82bc2314dc9dba56312e18770cbb1213588f04396b58791d2a5670ee185d8953cdf764ad910ce46f6ca30b914c207f7eadb195a08e1b45768ce78c728fc41380f366535e4b79042045187e7941eeb4078d5d3a629db3df41910deb9a4a3f0ffc11579e49d34763416fde0e377c9f361227da0b5b3850f4ed6d4108928116a9fa070420eb73927f7137e0aaaa1ee3594679fce138e45c9923cd147fb613ae1e7b79432aa59adcba040062b9801058c07c90947bad287cfb4f8c739f583dc84b3317d847acd96b4660f5213dea749b98245544edb5ec039c84c78a921d3c77e7439c61c4c38e9dd2e224b94b6c6b98497a24743ce915237f058c249513208e9eca1ace52be1ac4dc84836172e434f0983f57dcc24dc4839ed720852ea939184f3af9251393b049f48249c87a11e47d7dfe6fc8084d3d330bd671456a5ef4778e7a85d2bd886b18c7584976ded337c8594b7b6119eb7f86aa6f48e31aa8cf02d5bdea41a53f85575117eda1812625295d9a02ac2f193e449846fa1a18d86a4d8701311ae54e8c70d2cc798633b84ef5b9652eee428e4184378793c48c85e2144c4aa105ed6601969a699985a2284dfa9bcac2fed527906e1869a761845b22c4f47109e667ca934dba6acd0098497ae3bb4add778d03c20fc6c90d6213d5ffae30ffe9cc55423269ebbe1077f1d8614e233fae8b7e983134436dfe4ccd158357cf056257bf0e3fd3a62db3d5259f4e0a7f990a96d953c7837edd5ea51ab2d4af0e0dcc685c9dec1f3958e311ca590413bece026cd65e94ddc4a93a30e3eb6185ab1432d3d0c1ddccab098ea33f73b90e7e065c90c42f9c772f0c3cf7d288decaf4f1cbcbeba2812c270f0ffc61cf5e65791e4bec1cf20a7b6e67937381fd3e5d77eb6c1c7290387522525f94d36b8ad751943953a8a5eaec1f5a97fac1ae61a22a7067f5b528a4aacacda5d1a7c0c22f6c59482063f878c635a4ab660d933382239dd64f8a5d8c8cce0e4afe83845668b7d193cb796e065f926635c91c1779873acc5305fed18830f3ae4d47ea15296550c7eb8a3ab737c235e5286c14dffae1583e147a9d9a2437b6be082051080003570c1175fb880c020bfa09cdb44cff66833fa03e98522c009b20baeb6c64551cfd9336480905c70326477c687ea06c6050ac82db8591362c335faac2ab55083cc820fe5aeee4382a7c7512c389931ccf08c357905374f466f9d41b2e90aa5150a292d3c5345cae717590537f6353e87e66eb6122ab816a91e597414d3249d82ffd60d5622c6de5811520a5ed79c550e498d822729cd69b88f515c24149c08bffd2627a39d2ad7802df20927891d1b3f5a904ef052f97cc7a434c10d1315aae5e9aea94a269c72ccf24972c89c608b309730ca9b1ab4b483dfe681548265125cff6831844ae4ef9e344d05a39497807d218317c822917047c83402a208b2086ef00d55f564a5d21922b89a6d1e877a087ecd5f886f97d8a91621b81639cf658e36bf4910fc8c8c5cad16b53b0d042765c931760859e15ff2032f8618c1fa72237de0d8e7ef740f8f21c4bd7042a61c19bab8c30c2f7c9c3dc4827f6417bedc54c819a5b02ebc97f31bfb60fea1712e3c2db5b81cfe6287ece2c2cb9a7144c914e32d7cb4d2a0e61bc4b411b585b3665177eed7c943ad859b8287ec20e5248defa485e358b4424ed779a39bb3f0a1afb8cd947b467cb270455d621a839b6d8fc5c29f0c9a16fd86855392c394a389471bb357789d2368d6f099dd29e50a27ad23d2d9a4d70ab7c291ee984556f82054bc556e7f153e0cee39ac8fc64c8d51857fd1eb2462264c456629ccb26fc30168c001182000010840000cfc37e0043240410756309e010420c0a1c24b1e352ea8877495c053382ab22659b1d7ae61884053789f2c6323d6841cc2054be1631cee28bbc32829bccd97367cfd5d388eea285ccf1453822787c13534120c1485f313eb43667708a99141c05038161d24e78cb5fe490282c2491355d9c1f959840437f842066604fc841f9fa167e968933ee509ff51e798314507f128a89d702cb64cfebbd0d9eb523b20277c98398688d91d8bc7cc26bccbe141869d3d9af0522d79b0fe960b3196093f35b5e39b5c95278309a7cb3ea30e7809ffff3465b9a83d29394bf835e1151f29e7aab10f2be136aa160fe14addc3352025fecbe0ba52b28e9d0027e15caeb8e0a0a65b638c0428092fa26543cb23dfe1fa136c550123e1d4b54c24c9f5f2af2d0021e145cd5d0f3d4965087c84174e42fabd32de2eab41a023fc961cd4da1b5f4e0f35c233c97f8d728530c2b506a32eefb9638cba10b808373aa6c5f556dda744115e700f71ac61c942469b2030117e6cc72c296ef6512d44f8695d52f02c39c45417ce031ec20b61c356fa9a9475493ca0219ccd9d95633cd67cea0ab010bee5486ddbe1d305b52021fc697c6134d4c62ced4fb0655040a28083f0bfacad2ae547df890109f01350178021a020fc9ebe09cfc6e82be7dc0103e1a35895dad01c867c0808c72452ff96879b7535bf807ff0a3c6f4307b5e0fde0e2fa01fdc148f32c68f4286d9f83ef8e9fa2a58d44e1b900f4eaa71a41a630cab01f7e05b4ef3615d3ca6871036a01e7c3019784c99a13ee79c3c38a92754ecb29a4879d38078f06347787a88d8bccb25c03b381d3663340dd301b48323514ed2c29727d832c3052bb8c1784111b00e8e276fb9b7ea0eb68d136c0d01e9e0c318be619f7dc3dce609b6be20810b8ce900e7e0860c22d954b67f327a82ad18bcfe0c7e063068811b00328172c0fd552c3240410b54d0821990e00666fc178b058c83b32621d584ec0840000210c0030358c00028908104fc37c03cbd02e1e0a5f412793ca43fa56f70b3fde5ec93aebdbce306b7330709414ae6be6f83d3696e272b0d7c629e0d3e0c591d530eb5d99135dcb1311b934ad4e0a42b7b98d271c65c9a34389d2334389d83bce46ef994927206a7353c9a4fb9ddce2b66f0fd71248ff29e327856b361254506672b877c912b4608d918fcec2987e059c63ba4c4e067ca90e5f1b73d530983631943c91ec3669062c0e09987ead09b6a21ea2f789abdaa1e62e20527f4a650ab1cd205b71f4dc8f0e83ba490c1053fed318c1ccdde8227f218ac05278966181997b3e08d3490b568f93f628b05e7563de36493225da257f0254334b064a25511b582db2863ce1ed266e3a155f0f38fcd6453a9e05b5f5606c9814a6d3a05c73ffd1e5ac55ca15229f82af5c8c5420c13ea8c82172bc7181236a3a830a1e0a96a9b76c48414b67c82a35e39df5fcce2afa513fcfc7d6aeb40a39b954df035e4c71a4cfaf2fac804ef2393a954e85e79e0127c1c53688b1e1bc28751093e944849f2e528934a4c82db3977cede2cb92d8848f0debbaae453ad63acf1086e56ec0659f1753d3182e3ef3397ca52b8f7ae08ae6df94b248d61293b2238679929da9a4858c6109c0c2b66b056d127b82604ef6263b4216b8ab0c982e0a75411b2efc32bd5050457e44b4e73593ff024564697962603cba00f7cfce999963da6a7a517bec563748f3e656f8c175edfe5eccbee2952a25df86942e53bbf2465e1a30b273cb6708fe6910b2735c6e1c33bd86f4ee3c275e423e9417eb0daf3ddc2cb199944fb6a5b78f6c953d2a429fe63b616be7b5c588b9d917c98b4f033dfc74ef779ed2a9b85f749352daac34c479e9385efa1b5717bfeca2e3ae062e1ba45690ce9374f46be57f00216a0e00e070b7f3367488eabb25535ee156e8cecb852944d15dd7e802bf84e2d9b22caace35ae1a67b14339217b92063138e157edae80d1a568787d0afc2af699c71ce95d2cc7a2c9c2a7c891a22678ad54c9d63854b851b437e1c9e197bad8f8a325c4adf29fc1cf3e518292a6d4ff64ce1788e9650edcf95c2cf932e774fca48e1448ded9a31dd1b85237e9171a6b16ae144e183d8d45d123d62b844d370a170d4b7f3844ac58c9466058597353ae6f2e47dc299dce87358c9776c7f9ef07fc2c6980d1155aab94e78f9277c67d022393b4ef8995190702dc14336f336e17466b2cad1efd384f711d66fc173e332e1484b7bceaf7d3156d032384c7851be194f26e9b5754fb0751684bb849b59b9ee1a86344bda09b6583003e6c159c28f91fc40f3ab9f6ace09b60c095a8002133c411c5c259cf37614a7a511a9bbc151c24d29f44a4717ed26e1894beed0b5fea56a3949b829cc939896dc01abf073a39b3c394223738f2a7c9b7099518af4f8ec543857e944925ccca6c8a0c2cf9ed72323d23d85f3bfda8d362ac3fcdf9ac2372b6d60dfb3b19e3ec192e00b19bc805cf085e696c29f9461370e6fe12a34a440be2b2ce4cc5ff951f8a61552a489398fd52e88c10bc69f806945d1842029f7a61e0b7e3183f25fec0336146e9094b4ed06a7aa0d50782173cc0e11320ec9d34f386bc95187b4293478d2137e58ca8d3ca22283838213c480046adb09365d739d64989cf0cfbdccbe3504ec26bc13c930f3bd59c6999a70727cc68c19e3c32f2df8e2652083f10212a860fc1704371394aca7918a86c18417c2afe6bc39cdc9e65cc28b359137c50ca5fe2a96f0cd3c5786c9a06e9253093f4ccc23ff9ea4845f3ebf769161842927e148a7142cd362347f2509c73324874fc9f3197d24fcf7536bbb7021e18a7a5b45fa9f53cf23bc1497c9f2478e702d63b6b0d5d40d1c8df07270f70d973384a8c9081fcd5a4a90d011a12d8bf05ac66f8364aa08ef32e3d0a9368970423cb628218dca7f10e14f4d5bf21865c241c6211c4bb2197a46de105ea9b66cda14b5885d21bcf5a03d298609e1784a475af39d41f833d15182552d08ff62a3adbb6903e1f8386cd1d4f4b9220684232ac9b1fcd857cafa0f894cf77ef03f4850b954f954b1f6c151c9971635271f1cf5cf1c43d4e41ebc14c3c9a4eec96c51d383133dd59a65b5960cc53c78796a835b8ec143882a1ebcf990c5b2b2e243bb8367dde173e7901d5a991d7cbce2338dfcf346eaeae05874091d3cff9442ee7e6dc7aecdc1bb68b3a5f931e4e0a564a22173acff60571c7c1492a61c63f8f4535938786ac143a6b52af99c37f833133ecadb9fa9e7b8c18d5cd7e0dc34ac41dae0ada5aaca6a9b3684880d5e54b3fca1ae6294acc1ff5c6e7196b305b94c0d4ed218b59861747f3b0d6e87b98cac298306bfa6c33a7b4db0349ec14b91be1e4ce8d60cde68fa24ee3065f545b765582b8a7bbabace6c60206083372d40c117a3052850800c58d0001cdca006485832b8112606f90ec11bc38a418b61cc643c6c50c906360c4eeecfea073369ee6f30f81e7286eb589b5d1e7684fd82d560bde08c7a8890be55179c34762a5e165a2ef80d335a4677bf2a55f218760b4edc6b5c5a4b71b9cc09b674001a70800b4c9080131417bcc0bf051660810bbe680006084000bd0a8080040158c26ac16fd0b0b562f26818fc012ce0109b05cf5289d6f5e7349db662c18b78943699bb2b40c190c133e0bf0175d82b78da1923ad183953ac15bccd696203c970010738b155f0b32fd671e7cc171a0358c00230124b0527db81a5162d4dd08244ec141cbf071163225a54b14c0f2b05377b7a370d2af3198ac5878d821b551ac5a19a464b2928f81bb4e543e76c186388ea0efb043f95b8c5c49ea855e129d609cea79a982979ca4e6c137cd190da63aae076d72d6299e0ab660bdb61dde53b2583188c09ec127c9f98b29da69a11ab042f53e5b81abb069e7192e03dcaca525b23c19918a2d895a763709923b88dab6108991ddbc3085ebeb4ac718ea6d22745704e32df24073311ba8ce21d43f02ea5e020ec2a32305108dec420275f194b2c4f101c7f640d33c3dc294db58b05828fc424a4cf6e318728d81f78934cfefed53bc1d6fac0490f36a5139595caf109d615da0b672dd465e4b06942fcb8505e78af912a6ac63c2d7417cba41821d9cf545df819c4321ec61c124ea583e662bfe4e939a3ce98fd93c10c5869608ad025e5b8cc241359bb6581dec2394b375e3321a38b0e5b38a19549a543f95d4e65e005830524d85af819030723a6854069e155aa10f375eb889967e1bf9ba64669c89cdd809040065fb820060b0295859f4c267c86f138c17e418217fcab8004672ad058781b192e2236eeb631b0f07b32c5e3e0d8afe37136027d855be929858ccde30ab71e3bcc41bc6f85afc9cb65c426871433ac70430ccdf090bb188f55f8ffa9227f259b51165578f7ee8e31ccf8c427a9f042e8cfb0b0b8e96aa0c2ada90c52a2a54fe145d330c92a368593432b58ec724be168d87649e17f4c7f9c1a4ae6ec76149e8d65cf4bb7d8ca2a0a673397b84c87cbf26a289cb3dc39c25bf8dfa8a0f0453355061fea279c3495535bb265cb1c4f78511baae7106dcfd0ec84f325fe9e1b573fba70c2cb6ef5affede26dcd290982743a70927f643c7573949c660cb849341aa08963ce63ce1c2841b9742394e9d4b38b32e651316a925dc0619a718bf8bd93868ae95f0d2264bc5462bd6b6f24129e1265b9fa4152265ec9d9e842fda49ccdca1c30ce29284675d26a59e34d2a7250d1a093fbd1f07f3903b66ef760c0a097f2aa5479651ec118ec34a4bbfabe09223161c39c279edfb724b13b43ea7116e6d6bb4c79f3b37d630c2edd77490126691d3b208675385484fe9bcd22c8a70a52cdd573a23115e56a7d50e0f5545634438d519458aeeec219c07e19a7932caf86c13420de177c80c07392675f557082f2afc6ab86984f051862e1e3e3a0c91d520bcefcde358a4fa1e8304e16948139e2a1b26bf27105e568f901d6600e1468cb24f7e3985dbfe0f5e8887bee94d23bbec071f5408b908e9434cb60f5e4773f9103eb87953c5ce5fb3073f3a4c0e600104204091a054a17a70365b47f3280b31843b0fcee4889dc3a39bddc3281e5c9bf5e86f5adfc1ebbeb56df49ae1e5b583efa81e848fc3749d5307bfebd743c80c33a52a1d7cf039f8c534ff0956cec1b11799b28a3969cecbc1f9346d52b1222233c6c17f18993394b47c9e378583e7d1f7d2198c58cc287d0331b2bcb793eb06229644f6cedbb6911b9c7f6684ae92433aab6c70c372e6f033a90fba06d7c4b378f0183da81abcf1142a40681abc9c1bfd68feb19c26a26870fbfc62dd7d0420809ec1094f5a0dcdb1755033f87d113c5ca7e5a065f06366c76555f1e29d4c342819bcb7f03bb7b7f590ea0632d031f8314fcda518919184eb102a06277bb32d9c879cdef209b6d006a001070ce002e30bff62d440062d40810bb2340cae865023d7c842442818bc4dd529432aafafef82d3021458ed41bfe06568e1410c96b11dac136cb940062490c1c7400631e833ea052f3bb55f1dc378f5f50dda05473e63a4d277da91473728171c5f73104524c7863eae41b7e0a72c4d23924a6e6519c4c00517482df8969d1ef9852899396d2706cd82eff197a3db5c757834161cf1cc9b53e3c9f678c361d02b78252215eb1a5c84c85bc1690c2af5e4be54c1cd20d66d2c9f938c6a2af8e0256d632f0963f99d825f6229b52e7aab67530a5e650eef2ff1176f6314fca025f9257d4bb3040a4e46121da6b43ec10d16a646fb5cb227cd097edd5df40ca4ce2ae434c15f8d4c66d7284c701caf668859962578762984f86910330e132578ee9ab339fe8e922c2309cea76b2437418267aa591e47cab619ea113cad49a6dd993282271b2be4f88c2278216d1ba6168bd020028312c1bff8d0672953c21c6698abd20b3a04cf325eb5c6216c8105fe051618c0021470061582eaeb579331ca4eb075835701096e40484026832f3e062d40356810ec8ff93f3de42cf95620f8a142453568f0d92e2de80f1ccf31fb038796c35414a03e704de32ee3cd91e9d3ee857f8ecbeed185178eb5a4986cb298bbe0532cc58c65ac0b2f324619639c71850e3717c6bbbd4c99bba9a68fe20412178eb94fcc75a9691b856ee17f08590ec237e8f4c4e08b97410b2090b6f06175e4a496f3b5f0caa38f048d6971dad2c2ef8ec8da369741276f169ead4cd67e90a13cb232e0849485dbf3a0a1240f21bc5b4ae12163e1e491096911aa324a242cfc939c4348d50e041630000730e009f90ae79138cea6b2211cd2153ed47e14958346a4cab4c24b935103edad1c7119ac705423434dd963e11965158e54d8ccf113ae35e755e178f615759ce554783979a669fb07010820874485ff21a2f78791d0f2344fe145ba4ae7471f61214de1cb25cb17fccbffd5a42c858f6a82ca787bf99a0119fc173220a6852485f3e062509354113173cc841c8523fd1f52e70be92a4414cea34b31b45456cfd1134286c2c9ba881ad382da8be5020d0a2f39cc7479c462ada52df02db08006fa13ae6b9a3419315b45115d069ef07ec2c3fb854ab3aa7c0b36d0093f2d4ab6c98d32456539e1a645aeac49bd4295d49b30f23d8cf4d8644d388f67da53249f98ff41240613200001be78f3850b6883d099f0c543457a2715135e54659cf517ed66cabe849325cab33f2b7537b42db15597aadb6747c9e5c7b12476587827d8fac2050df8159021832f5c7001021080055fb8e020a18b90233b65f69c94f0cd66d4c17a27c711ea49781763b42c6722ff634ac2752cde3836763a127e0acf517c520e0a209169469d4736e347381fd2c7fba9e454ae3ac2edfae8fe7259231cadf9d35c1a41153423bc9cc1f6e5708dd232caa5a017e1a750bbec8fa13347ef02179015b422dc8c3ea58c695ba3e43ac1d6178f821383197c418218a0802b062b40810c669008ff529a8d1029c58e616b44902a2551d1bcd130dc8770da1ed87d76076d393ecf807fc10d3440833684ffa55922a667f43ee209b648700219a0a00624a8c1b740ab10aee5f2c813a983977f02198c0be00964305e803790816113a2cbeaa8bb2d4bb1ad748db64f294ca6d3bce50964302e4000029c400632200001ec053d08e743a61bf96594db6341389a610629889d47e840b8256f139534a4bf4903c2f791d4ff301e7f70ec32ae0931ca7cfadb0f4eae94d0ca4e761f9c343d9beb525d57a5f98099b9ca4446d6da7564c43e770f7ecd868d1939cc92ebe8c1b1efe9cb15ca26a48c3c789b793248455d0eb1361e7cd478a2590e973b38153edaa64eddb6832f31112634964a1b235d07279f65cf1945d6ba8daaa1e9e0457bf5cf5b1936fbdd73602dbb4cbe4cad356fcf35b69031c81c185a0e6e9e1a5bf5749f2778e2e0cc688e29a7e31b0e7e0a198f7bda8a6b34cb00022ee83778e71ee2603e6f837f000b5cf04503dce0953bca46e7bd520d7382adac18547d2183185cb7c17928a1c73a54fb952502cd06643e44a342a64d53eb35bc2d558c555446abd06b702b470669538ad4e08c55f8cba9b34e8357eabe9a62b34b82e241a3c1778952d79872d8469f3e835b0fb2c845c6b211d38136839f516a30f1df29e542ac037419fcf38c2a47830fd3b9800524a0010acc6ada06309b0c9c9659499686b8de1493064a8fc197cd413e494619645c693178951e65328bc6647776183c3b0f4d69424c8e301380005ffca1c1e0c3e86f194af7e66c321cfa0bfe798c31a5360c8fd1e4437bc1c9719b4522860c1da62174175ce9bf509b341d45c39a0b8e89c474aa6be8141a5bf02fc6d460a1b3ad053f2e6dc80dfa6e6db29d85bebd55d32d4ea4bea6c63e9ac490ebca63754d96ed7cd1ae265fc1f70696c27430dfd41b40b415bc34f2117f1e7615bc4992afeb6f3c2e639b0aae46ffd60cab26dd834cebd053f092250bd7a8f23a9a54069f8196821f7129fc2201d6868e821b4635460ab9464553d6d05070bbc26cb56b347325af9fe074189fedb4102d5ab973682778ee32f1133329a21fe38b71011b7413fc937e4992b5dc6682f7e26213dfd9226a3bc1165906b87a09be858f6a1a294709cedb0633cb7726219d2478921661a2ac6d6da691e06c1af11c36ac32b8fa084ec8ded3387ad808aef57fd61c35b37d0617c1d50e5759a29444f0bca53f926d0815f586e0a5477f3c12c25afa08c1ef764dbbac06a9371604cfc51b5d14bf09f75503c1cb5c1353bbd867ca1497a17fe04f0cf996f694551ba4cdd03ef0ce1a9ba4e49414824d06ee856f315bb29ddc5a280b0a5050cc99176e374ec9e3d15845f6ecc20729b4523ea5c8e0a2ba70f2c530da49836d8f24173e74b18c5170e0c295d3b2983ac99d6ff016ae7796cf6a058d5d9b2d7c0d9edf431eb9bcffb530653e4768e1e75eb74d99c2b36025e262cbb2a6332aba676d2da6f3ef64e1672c1e15dd92fc232f16ce65e03866e49ad3be8585971936b2d33ce56e617e859fb9619ba50769ec1e5738d7c025bf46a4ef07722b9cd83ffe1ad9d0ff1cacf0cdb4d32449b95578a1baab518c1c33fca60aaf53b2b5481f5306c77903a762f0c9b2e7caa89603a3c2bbabfc613c03e9143e96986206cd0e627fea052f18a6f05a2e3d3c94b7a8309a814be1bf439b4a313d76259f49e1468e97b0942454a3703525896e93c72a840fb2289c8c1af972d68c4371ca64cf79ae9f41e198d979494fda49dffc09cf3d976d7c8791b8c09e7022d6658fc8491a4a783be16cb97cc6b8c29cf067b68204eb18336c2b068537e185499a1caaa6dc51df6c604d3879a2564bbcd2c764a1800528980067c2cb281623524a5ee9a7c30363c2b5b210ef9a315508365fc28922d96eed1a51ceb534b025bcebad0a7d16c28aaf5c09b727c60e19d6730253c207b3295ddd864a9a734ae04978c122a4343331bad88325f1662cf9824d58e84747428d1e1ba5b5e4136b010a580089c4b7c363f173f0234aa952be317804ec88e733fc7f2c8f071ee64654de5d22ebb2eda91eee7da5629a433a66849faa1a23b9fcf92b3343e045b8b6e23835657a9cedb3225c999467aa7beb61aa7022fce49acbd187f81c838311e15a6730a129e30fe1c9c7dba784c5107e68bc25294838ac3c29841f3b330c0d3badcbdb84f01cc8794d37f84e9f0771c7a5f6b02cae201cf5de8acec1a7ac0f849f1a35aa464ba4081120dc4c2aff1fefa919cf7f70264da6a670cd311beb073f64ee18b16dec839b2b030dd3e893e6431f603e38528ec3cd843c6529630f4e477bb3930be92193b3f0f0ea9a4fbbd0fa8676d5ed99474209701efc8c3437bead1bc078f022675f74712800b4c07770ad4190feaf9eec1bb4839773f2f8872a19a48cd5c1f10793db436620293b58603a78a7397b76ba0c29f01cf8f1b0de2986871c3c15910acbd12045c6380ede5f7c6a7bf965108397810c120007cf3dc48450a932acaa33a0057e837fb153696e98a5410b2070636037f8d91da4680fdb16a0400261e036f81b3365309f53e34f90001738800d6e54a6be89f2c802afc14b179e634ad9b8330c13d0055683b76296f2a44bcafcc02f5cb000d354e034786915226362ff8219b8e00b077014180d4e63ecd9e4f30a053e83eb399c6c6b49f9d5ba053683ab1633ca5eb53952ccb5c004288841961606b80cdee5b48ece6bdee49118038b0093c1514bbf6116c2928683c7e0dca6863d59421383e313b3256365340fbd0187c1cb171b4832879a39a32f5ca034a80283c19190f933ec1ce92b2d7fc14bd9f92643c6602ff8f7f93eaa1f4489dd110377c12f4bf5217d50c911395cf09283cd309a5ccb5d7e0b4ee4f46bc1abd4e96a22a6742137b2e04486b9a35f9694ee0616dcec17c26914b9496b5cc1ffb0a5a5d9b7822b5f2187b10f31d17115dc185cbcd3d74a048da9e065d4e51aec29f816f15f41a37c8ca14ac1aff586a1ea68834fc951704336481952c38cb68fa1e0af87104b1ff0131c8979e31ed4c4e430eb04533a44546e5455accb3c84e99e076982e778726c5af850a6a11e9809fe49ba60556ae2a71a37f012fc96a9b4feb51a2bc1bb3f9ba8871191e5e73d7012bc4bffab7922cd362a7560247832339dda2d1fc17bc7b1b161d509b011fc1422a548991ce322b8594a265a0ae1d6dfbc021381aa6b9558d3c610dcf458f216c472566859085e649cc7189f0e82972ea949b444033bf18c5f41ef8081e0dd652e15cd97ea1de4074eb4981e457606fbc08deb8fef160d72312468236c2fdc14e4c43afac67cd6bcf01d54980cd1617d4f8541d85df819d604bb8fb9612c892e5409e70e26a63bc1d6e6c2c931fb52c8e359edc92f3c1717bec7949375564e154e2e6f5cb080372ea8405319606fe1a714826b7d6768616de166b11cb4b26abe183c0420c0f98206e70b1adc5e616be175c567f9f05241738716be75ae8918f3eb48e99d85ffd192f6a58478982f74bc200332408102d05a305e1003fc42062f900555570f3e3748afbae002b1703e539e28517360e1f57f78b97fbf4fceec2b5a9f3009796ab386d615fe78f0902c8302ab32197c0cb6157eca69a6474b1945cb7fe10224cb0a27d286501a528a5913a9cc6ef0850c5af039820d8dc4a884b084025924140804e280388a61b0e8f800a31308001038280d4542a168341145550f148003522020422c2a1c262618101a18128d44a17030180a85c1e04018140a8702a1a089b0c431570725dfd8a894a05b8acd0826b4f06fefb46bf4071403f0bbcb34e8309ba499b5787c0ceeb8086e43b1c12a4848be5fcd8011ca94345e40e68f1be4f5c8a7b71b7c572d262daf3b536139d27fd6edd19ac45b5bb00c8870f163671b76cb6b8c41fca09b49be1dc9d6a6bc0bedc1e0ef38b4819c0b507a7f9523936b3bf164b536f62105dcdc9dc438b5c9fae2c4e40a7053c4de4b5b3e197fb05389446aed2ad1c52923085a26c7372e053fa25c79b7bc6f28536c9b0acce84686099290bfb740a252448e34d3122bb778f40758b4ba9d490b52c462dd8167438c858074aff6e0a27cab773c1ecdfad3c057d999ec65e247893254d14b9ca48bcbb036373fb1f183d4f8e103fb9f09cde0a75235430df23ae3f757353bd38e7c2072466e39fa9b6fcfea9b4c9dbdf4b9258e786ff770b2c6f32edaed785fb4f46a9f93a919d3fbf05cf899fd87a3893dc9cbd343bb51c2da64829d379d6082d5ce31dc83c709fd545d80d9f08da41289652ff07b91924e440366d2795927a4800b2260c20080aaab2a7f2f4f93d844e180d54333911c4be3bec10c5b33329b7d8058a1f9dc97ba30a189a5d9ad80039b77c00ef50bcaa881cdf4ea1681a5103f1d50f31c0b91dc3126209b20f7296e846edc3e4dfad56491a096049d595ae41e9a6313524d385867f64f87a42f2e6cb6bcf0b511c31746faeca26d39b90a201afe48bd1294a123ad46e0271f34c37e82ed9ff2a2a9b1692473ba5d16772319ec102d6385583cbca578d62dc6a5ce7a65be29be8161eddcde56468ccae2cf82da33712cb09973a2c234f15392d408fe383e7eb0e09ae48c9c5a043134f9e54353e534721766734767d796037cb5dee1cface38d8fd7cdb891c0f955ccc625b75f6e49230a7358fab3f744bf7db0f464e8a1dddf1876de0aacff5447ea373b6f0d32321f6c6f4d4160bc7ff30ef39494fd498922cf358cb413aa35f995c3463bbd500e39c4fdb2a41eada8076eff05590da7bd0f42d1dfc2dce68eade6cb14bb26feb7f8fb92ef22f9b7d0ea8b427960e2860b628ac9f3ec30053d968901b9bf9edc80a8ce5df9fa27a98b1113e630f73ef5443476f2324f851aa75b0e9f856ae2cdc93e013439c4b7d32a5a1c9b94047170c7557e83311dfe39465708c586a8345e428171c125beac92d55475e15c1125ed3ae0b4218630427e560f114dd387980424f29371fbd9cb609456f002348e3c58f3a010f80b7a6cf0275d785b5609ae8a5746b9ffab41205cb607c8cf0c92591ea66d484c068dd1cbf31329dfd4bb254d2bc827685dc97b8833eda34de0686ded6adea96ff821df2a9125a44bb9e65786d1e609beec8563deb97fe2f3e5100a02ef38d6491078ff743b31519f0c312ba5f5d23a0d9b308186d38b517d098a0786bf38066e6241cda78d2a977f61b3fbffe2e5f0ae9afa4799497c8cc143c4a75c41aac7636da418f9f14e027f8b704a0272de9680f02b4c7ad257f022662e71ac75693519adb424a689c7945d1559dcd9778ed3bb8a3eb257436014298d959fc58c94783435b4b759359cc0d4ae6f39675d14ab6d9e076ea5493c76efda5a811696b0c70812e5dc1136d156f12716e41e630025ab64d9b96bf98ee3fd5dc6e332dc1e5417e2d0420b4e0fa23d8cd04973d18c6682256e46b7d85c2fd72a2411aa1e45f6d91dba5fb2246f3b94892cea2320d9bc5281086b0a120e82c8a091cb348e8e2ea4277f7abdbc693272f65c139c197c960e56683979158596584074b821e44d45fed8588db855dc17859dfdc22e2b74ec211cb36f7061bb6b09f5a359901ed52ff623451f709c6cad3cce12951f20e2e4e9053e54232858bceada6b782bd05315714f558c3d2f542d33df80b9db30d0b5f34fcfee7914946eb6a6a1cac56931de682be808d2dd9a127324f7af4568027fa9c97004d133c72ebf6923a364018d75320b48cc3f2dd84b8ef7e8f9ae5efcd746583abd2e5a93d2b31a79308b0a1405735eae4529ffc9af8eba1e91b1f8a7bf6bd1fc2e1aaf956c7867fe9fd6c529867ee4e6ebc5701a3e3fa221b10735a406e4cd07160d431d874b4d0cb0a91d2f9f1c3f0f1add6a45d4f26839c050994f0a2f85efe6412318fd26bed8e7040aadbf0d7308ad96b634c4922b39f6370b6fe013183e6a0d8b622c58efd6297482accbc6c0e6975d3228b6db3cfc38729cd1598e36e8744fd3a40b286ef566bedddc2875212bb97c3018bfdb79d58a66e66d149c4e681220d77366e9c5e7d91e579944b43f26d6bc2b09bb687e663295115438602eb73c8044e5b283e4ac2ff9a91ad640ac0d1401cf9057dc9623bf5e3c4d0b9339e953307db2f5b7246dc2194cb88bc4eac9b8917ec5f63b56df0095e458b9481ad300068dc7960e1ba05a0e2297d594679f7ad9876993fe3f849e32e07e86fb4e99fda6be9bb86c238f47ad1b46f97d7e13aea9b05c443d963d6ede1ef216e0b6cb71ff7cf081072ce7991a5ece4fed3e6392c41d20759fb192644804134748a25709999da173ca4467cd19f44f739ebdd643094fe117b16f8d900275c73000dfbe3967eb819d66b9a8a8209bef9821459422a1318c124dcd844c1c46e8b97496fc9a3a0a1d7803d1b05aae07d1b401216f1126769c028f2d3fcb8ea7122918e509ca8c1b9e813c4ef687a4c40edbb8ec23a59c71ee8cfcb8441f9a5ba6bb91e29484073a0640c5d119e1568306e840e7695356375ae6a478469a589d7791310577e32fd5a193aaa282529de025135140aab93e674fe1da7442bbf3244a7718e587451598c74567e14700e65bb4682ff314f9c8f8e3882342e1b7d0e9469abe006791ee3684666bdb281cddc52303c1d85beacdde13af5a926d2657275e92bb47e05d05ad53736fe9fb03333bc791b559d071e932e0082fd7fc4bda2b936712042efc3b255cc3402ba656c2058401a20f462f009fbd5b8495986d436da541638f38f367e11a38dfc34a0103fcfc3e79eb0e1d01873f2ec13e7f2e35813c92154b6918cb253334e9394531742aaf9ca304213e0513a66c3dcdfed80b4f4b1ad0a3acf8b7030839003818ba9f9f1e582d503ac72dac4a7c07db3dfe4ce4190922a7bd1f0937b387b6d712bc8b1fc7644b55e822bb84a1190cc4cff1e8dbad8fd1f3d32d7504ad298d05014fcba5b0952783e9847d44b99a2205f7a3bcdeda6f48117e885bfeb164ccdbe25292f700dbd4c1ae89121495ba21931bc16b9293712999be8c279ed24eefc24da38fe43ce79204e6dec823b6c234fd1ae96648890778cb0a9f4e503abf09bc0535d9b06be490bbe5327f5fcbf85f9a18cb2c7bc38b535f136bca3fb675d1046c972a6c01ed9b67f8b8167c1341ce8b97bd27e075bc9107e6b02fdebd390d8c9d25a58a548bb552a0d004026892f061135b7058078290f29761e27697cba9d74259c86f5749d5026d22f70b2aca8d5788c698d8d8411de55e68d7f8d0ed545afd6511629c5a740f7ee568f0457a218539c5426039a7702dee9002ca64a7f6c70d7ad43b3104338322201274828391375a6b20187355570b6ba4fc7d44048d824444fba87b51478a1c3bfe5c9a816479e7918ae91cd27a6db11673f2df01c3961d6cd7c7a1c9c15d166409e7ecb671d8961a0c83cb595b82fd57b84ba1d6d4d260e4848ca413ac67af54cf01ab5bb75f5972019d4723b743397da61950ec447736a59569b41a14652a0ff5b87c35a98f18b49ee911f21cc24e6d346fca2fe4a13832400e8769eb961d18561c7a825e33b9dd1a8873c5af6a92dd13f31252739802e6e4667edb4cd8b81597255704a6d2dddccc64d0d737e718907cf3c5d60e8219df6b94dd547ac8d14be7228ef2f4c4caa66cd6bfa319f378c8ec245817a6caa4ed350293fc0386f0098cb1a09e3128b53de0d95d5028d023b33d38a9ceecb8ae0526e4cdd49a847ee9d1fc37eda02a60144e1ca0b79b7886d6a5d860241b6946fb648e5d1ba9ffbb06f35039a197376d15cb0032b3ff3d5f05b2dac6001051ff120e563b0f184a0e10aa19f41153df418536eb8e4cf0c5bf0f2aae8b46e832d31e6cf110133730ad5707d9ba855b979a6223cf5cdc9748afac3305928870159e3d7698a608144f1460c47b9eb74f32a47450160a020789be4b4dd0fd882704f21561d63c5df34e940312a37d8bc2710efc04794290ada8dacb9747780f0fcbcc00cb2a400084e1177164706c673ed1fc4b2dd8e08f370ae6c24ce6517da9fa5ee043986506ad8a4a36a66d61bd8d93bc99e53b5bb032451582a907b0a99818d20270713ba17240043478fa434844bcc99502824b87d5c093c9195685213698e868e22fdc01f2c371a95f419685cf3238a3d81dc7d9f91204b137e97fa97e27b336858f861a16c010bc867bc2f50dae7a157043a2b5f501904470261d28024e4e40d1f434fd624cceabc457b3aefac45d85cfabc57aecd5f5e3941c5503a742abb19fccc6e4f74b6cb6c4abfa41751bcca3c6281c371086dc8180a0264befebc25d8d000d104bad14bc36d784750fd03eafcd0279f56514b14dbe6d3bf573f6acd866553f4643520e249e0feea3c47ef088f230dee7403a596fd32b2135601a4995f268df40ae6d51442b62cd794da251a15ca8efcb9f35a096dd438756fe6fe845aaace485d2d8e009a28ef023e14ace7e09bdd3881074125289832f63a7a4407da4c2c6aa53a207037fa5148571a07c7f21689d21a38f508d919c9acba9b2300c51db8c0285432d77d155bbb2afebb7b2ee7263b381d9b67173720ecfa5a808d5623a6d5ecfc766c11865f1547acfc85e87e56059d65a4857a8f9c269de37ad06204a9b507550562581bc2ddf3e9ccbb3674303b92c4bc15cc5e601c1fe83624045fc9bc066752e2bdc6b175509e2cd8567dc419284f62f03f46ae1b0c2d02276fe28a37f4f6b116b5a7c64997063df52d3dc46d2081f09f74b1d5d40ad014e30b3d22590bb47488cca815377f5edfa296b5e3c3c92f6293e206bfaf5ad7c56488a04c1b057662c98186f631e289567d904bb2d508bac0d7a1e9aed43beee201a43dec9130d9c6aa2f4807c1ba7f1e68d85c82d6fc096402b7432e4e47ce7e5927abcce79be0d6a527b5944c568adcba0cde32c2db225a91d58c49f3b803f6b92a4078cc0821040a8c7d17957ef026398d97ce71688f168f601aaedb79fbc36306227c69d73651370c158e1d13cb64104ff7c9dcec9ea73ecdcca26346d82d70fcc44cd4e20c0da68a9b0931782be29ea391f4ceb19e29ba065b1dda8f00b78baf1e071d18941ec3b54c777229732c0a3e4a062cc9cde6d713c46d8a487383460074a2f95d43e9b3181b8e756645393ef464b12274e20718a14ecc47d6b5d785d1cdfee90ca9d44711ab06850244683ba8034a8ad1c5111f437541882ea2313646614687c9460aede690614b96c748da692bd21660f0b63691bb7b65eb8f355b2d92f4cc739e536744cae28e3d3146c5639fb242afe28af70ef664c22c472d7af7d1cc241330470aeba8214e7326e8a6c9df3832a10fed90d9567b364a4f744408542f431db45782155ae2b5ba897aac94a0e22940b72107ccb26b826b57f59d5f04319b9cf8f3d42a99bb565af8f49c532e8a16c58c388bb0f0d44b1725c12f3f6ac3a9a42157db72dc308d847892335dd913d48ecc2d1ce3603e7fade8c7632298c6a71c3d1aee483c82bb91c6da6a3fd1b0b0f07a218e16ec495d188464a0fa37134bc1efbf18e3e421aeaa3e82369b74b9b225ff4462bf0ce709bbb8c986694dd1ced204d1084ee483b56e3a8fba5e83fbb4fa8e23454c4450538a4948870e8f95391da679cd649c93076da9325b69a0eb3b13e952991f2c5dc68d5900b655b4e22cf402d5b6f220a1eebdb4e37632c2b3ef77b95aaf4ef660ba236d1431fe597aa7b00dafc4edfac76bb3c95fe80ce8ed707fad5927d42a25c2998d0804969487c90234b0184b96889c332740279c5eeb467e568624b99be4c2d2d3b56fa5ec6a633450127a2b82c5516de01ed37ea9a53053a553082678753f400864777efdd3c1233cc7c2c129faed1684802b91ab9d96c5c398e94e0245929f3d0fb7d1d0e045eb6084a5a2aa8960aaba65df98bf5b572632cd836b4fce506b6fc7a5d2cffe640404c1312b4077c81c4885da955dc2fcc0ed0af655613e2d9bf6af1b721c44e9a7a753634d988847a8f2dd53bf6ae35e15380155d22db8e57068f6770f750ef6cd01cbf166923b3e46b436172109695d23492e43907004955c2ddb91c1143f82f80a7bb91fe13c4df44f06199e01876a8b01fd564b9eb0722bd4cc1eb65802627241d03079bb1b281a5db81dca780993d0bc9e256743fbc830fb34191717e2b3edd2ec61ff1e8eed902261262d4db67c5d04461873288d1121897546cc2ae2c3bdbe8feadb3f2287480e08911f8b86dcc7bf28bc0387148f94436a47a173b1b410b6e6616a083b061d42c7eaf3e12ca4bb464cceed2528a17d433646c89e158933ad01dadbc2321a471e316e34e671e183e48368e6f894e2a62ec8ba5084f0bd9baeda5c05cc9a9ff9a9e37a8b6ce3a68ff7a74027d344036e9e350b4398b72232de379c33b459784d19e762cce7c89ddacffda67a508fcf71e599e2905e528becd86e17a9b0b122ca4b650656644a98c53b4688258cb27ced9fd133f6eabea54ec96c6d01867984e54b02fcaaad62a3f1e44538ad5e5e7c768c0cc8f93071b2f5198d730a60053d17438b26e6113f2c2d31e8be54e494426cc2775b0d9ad728877533a1dc25e86c55419a3623a64c08ba5deb8cb5cc668beafc5cde5704dfe9b648a39e8560fbf1b2966e1d7c6f535a92a7035d1088a0318b5d8cdc058f653c3f3163a5dcf43939651fbdb333fc8090d3e51bffd15b7567c274d31a777cfe67628fb5504d0262a092074e2181511846d6b55d8741c1188a2240f661155fffa99f28bfd1da14e457adba8de37a2baffcf0a3b157ff234c0072b72de09aa12912fc247841891d58988d608cb2b49ad6d6e4baaa59c0fe2c97ad28bbe415c844752501ab253f45ea4febccf8370bb084a2249c7c81397ae182a8b7c3b4552660cb9ac26222911902b993e24a9b53eb610aa1344305b0c8783631df7883fd1f76942b844a2cb25de4beb6e2e23b84f657d998b59acbe488ee998e27ce1cc9334716f1c90331cead8a0fdc729734353ad7fe7e824f0a92f7f853b774fefe1657b31a855aa22ac07706a797229e250203df4b12415fabb250b6246db6c3bd54bc3933bd166a1b77a6b9e29edcf54507cd326d8fd503e2e8461dc62946b139bf62c23bb53af7fb1d1e9506df64519aa6431b2e30bf9512be8b4a58823e9e41af13eeccb51edd0501e06fe9f5817a0732ea9b7dece49c388ededaaeef6fbe5db716c6a86ba60021a8f4c6655ae35866ffaf820f849ee5f10679ebdbfd5561498fbcc585f3212f309cbbad063c2f48573b9cc83032832402e5e1475695ae60a060b9e8d74dd9c5b0807804492799efdf8bd662f2f0826c51134c942988892764c3e5c241126a4180078b5d844da995b7a6b3cbcee505a2fde17e007c76e8f25107265c4de665c1da7b9d9e04a058afc78ca9ff14952eed2d2d6f375487d4ceb8227814ff234d05df9fdca4bea62b0d190112563de7434732dc0cd94178f197fc4215061e6384f104d7170c599a337f772d5a0bd88b44cd071a3e5ddf8af7c4c60bad44a10475a2aad1552539f96b079e2cbbb94bbf6417a3eb222f196f420d47588684a93d913034200468b4c853d8366a83288906b17b52163874069747c84b31c4170c4012f50f73c8156bf3c278a8c272c0489d42b17d1f2f76335eb43bdc19d4e4c0074bd8f1b49e3000354826f0d65511f395ce8027d93fe64f0f3f2fdf3afb16b1e125c8ed221b62c9308c8a50c5fe9444746182c0a8bc4bd19c1de2532531afa34760395788f65a827eefb2e67ba088f0e494e11375b79ccad06f97658e6f91641d91a8c2eb8be5b0df4ca22647f470dd76fddf8982871fd636c5c7daa838294ca2b198908e9843880306fd28bed6f1690a8e91b732153103010b9102e91c9105d104610fd90388a8091909feb5e55540b808001812bd9bd42c4109e9d27f9f638b15f6894a0d3c070c52e4263021d0def1d8d7ef26185c72f61880cef22684d945e78230b51e4eca0562410c409b51e4a24b298f0066ee01bc4fd9073e2bd4b586f18437c1c84dc65b9f20d42149196e9dc5a6043c85b6854484e859e994b32d6380ae2885a851219550fa2533089c81d2fe03514b45d1efe4e6a3153510ba0db55f5d8a7615662cf3f0b33a4b57fa3d490c3d0be2dd6bbe0a5462cfdb4d51e6573961c0000849cf4a63a03eb184430d8794305b14bd64be2e2a3c4cdb7546aaaa16b6a22cc6a6e1b70b1091d6bd6b1006c6980d9ade93d65b4105ae44c95bd17cff87a9696693c3b141eb27d0c828ec86183fe41054520e3151bd8eadba11f40e005e5862f64199610d7264b5be29c6d12c736aa9e85c4ace3e5f082881c9794b1264634f525e5602ab5e7a492671e6d9b8ed9143c9ecac72b2a892b81c46f27788a8f50caef547ddea6fc712fb25003291ea31a4d39e948b1503ba82262100528e51704e7996b6054de0666d264698d4195d1687032ff4a83d08c1603b205cde63ddfc9dc947f20173c2abd5200fe79a8e57f73d6284fc8e1e331a699e3d37f7dd8f1d231c09d075d497f0ce70021667d87487d30d51460b64455e6a34894d4c9a92d8272fd423d9d9aef5037cf7edffbbe9d42bfda77afc3f83e1558ce50e699b4a3ff69a855ce1700c05c47c188067bbe24c898a1375ec320f39cc0d1a720c1becb9b25186bc97b7458f1abcd52fa8e0b8f01568df7a0c14239c20bd58d7111e060054c6c9df25722c9c1605be8f4524c6569c321604c028a40ccc9f2379260d6324fc33e7c9a062e2a3ba5cd7a62df0523242871c6b0fe0708d085e5738d3206a0acd2b0026097f9474423575cab5acd5373d4aef08b57f24fbc357d6dd53f6ef864f26bf127b0f2be1410a8e60678fb22d04006d27d904638cd72d07a92f8eb15cbd9dc445ac0a726a1e6670b30314339b6d0733247d807d1920c0449e78e4788a22e1d0f89a0a3c563e8e35cdf64407b2a9d86fc2f292423e5bb09898ba0bb46df4f8cced86f5b24ae58fbf875121ece5219d85c0d5ee65714e2bcb5602458d0d84631fb97502dc5ff709d38b5aa2f79af7475e097208b455cb4e8e073be1cbbd8601a2f926cc2ec72e0ea2f33e7ef75d19a3bc52452985db4454ea603aa0d54d192175f20645d93e78032dd87b0ec83d648ca560f1d42586489e83b02dd2057638a8c018b558b937d4c4d0b0a3e28120f58e1daba65673d6480c25f373f774e4bbf4e6a56ca087b5326ef2af02d14b5f8a073105b058c781cec450614cf071d6586297736f4815b0e8a03f7cad9397049ec3b68c110ef47f0825ddfc9fede954ff8d5bdceba33b569135e0ebe8d81211537102daaf1b9485d08297927a8b4e62c30a9606ef5a39e400154dde9f5fe5c83275fe4bbafb5209e7184a6acae12073ed621abe8025a824a1c29e4b66bae2d69554ee0bdd1aa97c15d2ce46614b32f923b44330c69b1beb5687031253d2abc90fb417163669c4bdc71998e205ee23bb1e21f85f520d443d1b44d7777414639241b871498b39463f46b40ff8c62ba2416735fd712a39316b3591f379eba7655ec210f45a72acad05bf355cee0abc55604b339eb6bd7446c3f5cfc22ac40b3e5eaf86b28130f311e250b7d306b4a1796e2fb7b0c61fdb82e939c97829e49a0b794c54d8669a682c7f115002256c74196a0e3a3ecb392a3662a8dba6b09ffff68d23165f8a3cb43d21ef8d5b95d6632be8c5df0e5c8b3c0c5c3cfe9991071442dc8ab34eb2a39183c571e732d49c41dd5475ddebdc62ebfd9dfbee38746cea27b9342080877ed1e0f3823925462dc2b87e26c8b73663cf523ae50cabc7aa89b44fdd5f7021ff1284075e92759452058dfe0519387bf04063553a6c68ac4f6074a276c661e5a64592ecab3f00a29e61e9debc1498c1e715c5cc84c1a41498c527b05c361c4a69121158df6dd911a3cf4d9ea889ee84e5ea481705bbe339b717500080d3db17344d0b144d4637ae60c0de36fbebf509ea4881e67fd93c9b0cfc7b5a727549dba72149026fe397b5d1d2d3afcff6eac4918d32489f07e309f2954fe8eda8032a9c1da5685c9aa576746f6552c03ca03d5a107e52b1db517793bc44562e195e25c63776eceb7d2f2bce912b4c63ce2084342c2e35148ebcb1c14f556f0f0388fc47ae1f9b41175b880cc72e9e694a2e53473601d128816ede60c9d4d9a8b8a8bb5a96dcd9bb3ddbcccf0d3eb8be3a7b953dd04a0946d35bc864ab42943760e99262d19b36e5affb766f0901dd865c06143160008aa85ce447685a0d4d7d8e6a3d97385b0255ab21ebce9bce4cb6ec35394290f8164a77c3c6d4decb7bd0e6b0277a42f329c544b4e531e16e3723bee82b80330aa0866a7d45d15bcd52c5f89b88274cded89a828ee5a454df0f4b325a385a492911262b2dc63645c474b6d11a9a2548c8a268956b4e264948a52112ab68c158b94921332e4188775d38aad72565c952a4b7740effa503b32d015b20d141611456c9f08f7f22efeb3801725a26a7d1ec6b31f7b23b186750abd06a43691a70d193f1f08a2f1de4f14ae902ab4a5d5a1532644446025035908b29e4d1d83d22198286146b3cbdf670e2b90132fee30fb0a5f299bf0d57af9f1c34833cea641b89b4a4925098b4cd3b6940b7445ec5fae42988f9a58cad6f84095f50a5191c2f01191852e6f37459a04c18ec349ec4497cb4043f720fcb6a3637e2343b249f9a626cba9429598afe5ca5040ce085a4fb469495bb228f0874d5436400d9e4222b116ceb7b180e06a849654758b7ad1c6c4285f3fe22a0be4d5cd6e0572f34391fb996fa1fcd91e986e27690b7bbc8a44839c72461c8cd5e6676baa9b6b995de66e7ca09f224b96b013e80f4ca35de71a97cc5b1b47faf607e1dff51b9884492f23575adc5b8783cb315975aa5c839d41b9311eb2570d8570dd9926cf387e7fd36055b39d63b7d5a690b564ef91d57e9b2feb647d5b307bd864580f6b0a99b0e3a696b43e272f30c87c23cfa08ce35a07996090930b2991ddb36e8c8ba2207351ce619035f37dc7580b88ee0e6a790a9f84fd0d65fb23a800ad6abf9be81111396a54862562238f9700ccf55b6d4f04fd10b05c566d2e070ee659ec914682d2dc3a0000b79ed1b37c58e7ac0b6ab658eb488417e35c250f5a3e98763285a7ad9284789026879fb38fec8739b38079aaf74ada2e602bcbb9efdcc4a8f676c26048b70b293ca34a63a9d15e07ba60c82e499f2282900dfe2a9aef5154d299e45a1fa818cf21529f82d559d3fcbd6716a2938e50958ce053fb87523f178667ea891b84f7d1f7b1584c827828883f245299bcdf2e3e81a6ba96dcf1850e1d0a819cefb68d65e2e624758c012aa1641f44e1a2fca3aab05a28647c93b8f756344b2d0aa0b11a4492751b51320871a07c1aa28588ce98eef944e210e3bf78c550a10d868e6946ac16dba580366bc2585b75a97cd85e53b0deea2f93695fcd9c5ebe28d694b41c71270d73f6344d6b43af2243b544f71cbfdd0b3dc29b61ffd45b509ac96ab9e29268f9a0821f0b73284183bc79173f2ded6cecc0ca79edeaa283bdade49895912bee329cc94bfa73bd65a84424e760cb9bd2f5b1f570abaf110a197c520146a66c18822324e4fe04b445131d4f473c089f49ea8dcd65192e9db97584556302f0805b360f86d1750c85541a83cc74bd8da45a215cc2f316ebcdd9207a3fd531d50356c251a86a2e2e7c53fb36b97f7d4254ec42076a1557991b95d638d01c078ba60c654458f6e6d96c20bf0cc91178c018e7e1de5bb1cb0ffc624056bc855d26538216daedc5582b328e0c485ff04cc97228b8bd6fb351a030b947bd0600cca5364386cb984abf197845ee8c14659ad5b870e79b6fa8914aec68ae4b205b15de4ac26544c46b41811dda3b6261b6a975e4bf6c95d5175ecc8cf6cc7f53440b3af2151b3863b523cb3561b74a7edf311b80a05da52576a981115f9f829d3ac6691dd8f2d5ec3ef1316c11e375c923863c0580547157b18ea2bfb3b1690d4b1af01a7039ef1382d47fca7a422c52a36906e025a5e0e457cfb2665d353792f5f981814cc348dfa77f2e2fab1da47688ec6f805cf99054f978835210f6f8c17ed32cc2295469c3e5787561722c32405aaf55421916032784962c3b5b0ef8f665f6237cadd8e6b7a277030069e81bb96faf7800b5f3054cd9a13b5690c20aa65ccdf4a09169711a2e1b847a91c91c2a8180db59a894f838b7b4accd862a5be076b655e9fce90918c00099e7ee58a4f8831e3d0417988e9d96d27ccd1e2eb641f4a5a7694151adb7571b1c68af54f4d6df425c0fa97ab537c28ecbc88192884116e3184ab5bf932655d1c33dd771012b1d5799061cf6ce6d7a5497424e14b5bbb72cb9178c6d6f932de03a936ad6dccff70c0d7c735374b841350f1d940b21d052a329ab8f0b198f49ae479afecc25ee1d7204619652657eb90c54aa554af552242a4cba859e063d752a722b6c8339ded156a920c72541fd61fbdc94b2ad19b8a06e34d9d4664017748cc6580e65b2864884b726d8a3e855a2ab8e57448c29f133a2030353b48102b36450d6b319c9a70151ff0cecf2190c908015bd8113ba5a3b6dbe1d6e83b835be598cad6e3b7d2a5205c6968a7628d95b22ef0513c6cbb289755e1931728e8ce1a157307370ae33e09d1f340acf9b4d0a125121fe56686c1825fd87964faf16e39641c9251ef5cf568d4112b59184a2cee08d579808795cf134b876d816464bb16264a5d0ded24a8ef960bc91a059575f94b8588960182f454dc1fa619474fccd0348ce659d748bebb9454bf57167fc2b48b908344d38f06fc72aaec8df82b205fc9d24eb5816a4b9990263367afb528e158a155dd7c18083e843555bb393722c642ac420e233f5f2a3ac5795a6dd9c7d74accb69e5dc26200c076d877eb9dd43cfa0664a1a8e15e22e14a544ba7ee16b062de90c0e485f1baa77e4803422ab3312b516f2af1c1438b516e006b1a76040c9258e24a45d3bca809eb0fb8fdaff0df156293f7662a1f5d13e3de8388825c290e0fea6101d025116e1a2464e52e94e57d05e26958520573c2d5ba4dd7b66aef1c3578c6de1795dd64bfae0d0a0b246f290ff6edaa2aa5e283007213ae08c03a31f18c72d080aad9a53326f73c13ad53552a851c2ae5fa11bd2be28e3193593c564b2a14854986b289fe16fe34a0c064e08e0c8cfb144858457a381c709f3065bce039db8ca6fd22409f445eb237484338c62c3a0b4a223d0630b21b7a0ac3e8f4dc106a10cc890a7e89c8350885ad4160b16359ad7e2ef099ef4aeb3e64e5582a78b2ddd1defe72e48bec7661a6cf0856b65dd0b69606271c5c6cb6d66ba6d14461b060b0240e150b29450625f44384c16784945e473a382b2ed47e19cb9710214556d280891d1723792229eb55b05bfcf2ab230953dcdc8146a345b724e65caa16d0bf536cb25da840ef3c12190456b261386701ce3fb49cc45d1e097c3905e78af94da0960333b1ef5db5b0d225d807e6208b6b967d86a9ba6f77e30b02f2c3b33c6a306567d6d1a4b0b9da92cfc464ac3fa4eaa036a3b46ff1404fdab21f679fc0eefd22e7114826a7753385b05bb6c88d8065ec6fbc75ec681bde38acf274d1491edef0d2e3f415bffe7e0456ffdc13693a7719fb42588db2327f280f8c55a3a3d0412784e5648e3120c3630cbc6821f208552be7267cad74c45663c90bc5a72bb24404791278247971b9c731d8642a2486f4e38932c4f72618c02755dca5748f6d44a3f85f60a939ee8412eefb632efaa92886e53ee900ca3a56beb6c1be4ed4415811e6fefdee423005f14e28cbc42208be8a56cb6148a4602827118628b479a9a8ea3b9860674c30d60268bb2051ffb0db0c1a8dcad2054c300d2ef1034b6b3a73e3da0ef127f15b7219950adc3c5acf7a346d9447d9d454248fe51e9e621b9e7c0c44cb246275347d46d9504c31409bc228cdce17fe29aba8e9e4b92cad612089b06a91b7f6ad3d9b261c3ef60cd94a7e5247e4dc077edf18e9b793b68ee9c2a31c24e4f82e3f5674128dfa567370f3a34f8960e1852345d31b04e4f8d2dca5859d1888d18f54ce0a96e77a947d519a065909d5af39f53cf73aa0edaaba690ac89ab5630431a7367ca15ddac15b105cfb3b0b618c7ca20a11f941be889e0cff2185fdc11745aeb5d6b5006cc5573022e4b04040b3340b2a4d001ffffffffffffffffff51dbdab7cdda07edcb94361913500c45c8fc84a494524a3225f3f43338ed03ff151cc287100f0b6c0acc0a9c0a4a3c39e520913005b1975fb3cc322c830308244c313eba69a8dccfcbbd8d1c3bf011e6d2be8138421fcd0a48234cfab48d560a35dd184118614a2d25afcf9a4a005984f13e95685ac642375411c62f335ddacabb94249f236127c26cfae652e724bd5423c2a04fe816f93d0f953c8449af6b9d7e3fbb3de11a6b6608534a2bb18e4218644f4a2928112a4ad6354298c5d664cb31ffaf837c076410863325433b5dc97111b7204ca7443b09baa31aa2a1c3c659208c1672f1b1b4691d95c510c306093c3c4000e163d8e0c118653000e40f56ba1b1bcb15d6b3933c32727455633900e207731284aefaa42ad907a37512bd7637ef1b678d354e3bca28e38339bb47dffe391b6d273a6cdcc03d184b963072edf43af4600ea192126d9ec44ea29e07a3794e425a78ec4dabf1600a131fe127b37b01c81dcc694cc3afa46d0763c979616445f4b8b97530cea6ea8de97e3c9581d0e1f5d0cf5eff49903998c457ebf23149fea58126079356a8fe53e154630d75e36054cf16173d0c07a35ace11933ebad2e31c9c24f91cbcc1a4ed4e9afcecd458d33c37984a94877e0eaa4c94688d353ea381ca6a9800a40da6dd33b59f4ef8874e52636dad05206c30de2533ff931a77f7ea5883a9d3785e4b52b2c6da0e1c38d46012f48b891e9583b6d4c100240d465136221696e754856a2c1a4c65626f27a14c0cb5748d353e83e12bb89aec5945c5e866387f6e85c9aabf0ca6f4222b2749b2a5bd548d35268341c7c9e1533e99a177a200640c46f99c1dcba348eb0a0840c46092aec3e4ae5ec6581b02903098ccf2e3cf9a60305a0e5afaa41925b8c67702902f986543081d4a3679269ada05205e30e55c363d25eee79dba60d2398710d54949275a88061607e142524992249f166da9b1564e06205b3028f5a1c4ae534dd18c86164ca2a75392f44ea22b00c98239f5ef4df2144ae49bd052008205f39f1484ec7ce92b1884c8b7bd93a3493a9605b142aa24bd566b6b8db5260148158c164fcf7df0b7a01d1c62141a89c60e1d386ad0d0c3c118367080031c622c0e1b34c83020549802881444001205d5dc2c2d2e68c650007982c9d69289fda4ecc491937143043ee0800e1d27051e1e1e06e2049026f0f5b2d9ea59ad7de5a9a49caca28e594098605e4b39f1e2b64936421c3bc610c1128c7a7225ed4949b224a5b59192083ef0811b3a0e0f3c3c9293d000a204c37aac279debc2824a27c1fc72929e58236d4f1222c1ec49b40e173a7d5ecf811cc160726996525610239837fdaddf336f56669022185bd3737dae83502d99004204833efd241ff43f0c934a5236b13bf51fc230c91384ba1065929069f90886797432cb59a205184693da2fe845f74e3afa8b362e59b8d3b2e02ea79569a1ba7b94245f18f76227e9e7a504f929bd30858a551a2127d5a8145e1867c3cf73ca92f373ca2e38ab28e375156bcb2aecc7dae5445329f87e125d18ce5cbbac44b53993fbc8854994d8a13d8f1017e6ee720f3a9c9494d0f716a69157d1644b96dd45b585d94abab575d0b072b7166619359324954db4307812d54faed678162635a22bc927e34b4dede1f139fc6561ca3ff34ea243dcfad5217cc4c268728553dfeb32081fb0309b55884a2594685d6b03c70bf4c6c72bccda26c68937d1043cf870c516541cd3a7726cbb15f9874e95e7da5167561c941c9ecda28af26e15cea5301d46ffe9b54d15a588dc76aa6859d20f13aa4a3015c60c5d7a266eaabfde072acc56264d54b8925318ae4aac1353a2867dca16e1c314c6396984ae13b73f4b45c34a61bc3b553a4d1e5142ac1c7c90c25c794fb783fc5f1ea9181fa3302555fb1dad2b4de5134e1d3a5833f0210a639e94662c66e95c521fa130e5258d9354feb9fd948707280c9773dcda3dd9270c4a56ca75675b269afe3e3c61129f8451fa5acadf549dc8be4beba2ddd55b7795c897ca27459c308cf5e7ec9b245ff8d884b9d242e627cdb64e0b1f9a3025b9b1193732f7b3c52b7c64c26079593d688a8962745cec122653b75dc1e4e5e1b13e48ff6c0983d8b8d87ae2bb9f302b615eb5bbd1159b1226a9aa537849529e24a727616e75b5539df4ee644f12a6941dff4818bb2fa5e52d25244cd9c3d37e28a5728aa347943b2b68597585d3d2b4a81764e57fc711e611f6e5a3a146cee4f8d10853126bf4e8f4764985cdc3e3ccf0c108d309b5fe12be63624517619e37bd22da411f8a30795a2a31cf4e5c35b59de1231126b95f9232199d0face00569f8408429e5131d174eb6868f43184fb549b765db5542e4831ce7868d317c18c27057b9c2082587fd8b3e0a618aa154ceadebc53f930f4258f284910fc2706f82295d268e891a0bc22073bad74559febf1a0853fa649ae35ea1acad0f4098dbca53e737753ae8fce30fa6bc999db42c49a2d33dc2871f8cefb97fa4c5ef9c242d7d30c99e7225a66fdf7eb4f9601c5da16e4d5dec942e34ecd159277cecc15ce174f578aa1ea99687c7871ecc63d9737e0927472ba93d3a280a1f7930bf86be7dfe3ff06034419b7caa2374b4943b9852ee6b2b436c4c6eed601c8d3dcf595475307c7bff9c7b9f5813a5834149275cb4b13ee6604e4f3988bfbfaa37793918de7c4e5bd5cda76012076399d63ad3351ccc2147bdf6760755a27c834996f586851edd5070b93677f98a9975bf261fbf3698f2c8508230b1e4935a7eb0c132abe8eded16cbd2ac429d7acfae269558ca640d66ab8fa5fd4ff3f02864e8b8fb50834938e94cc67deb81e6b317039581c3fb041f693098b55df4de133dd2f001a281056d061f6830e5ac8b122fa91a6b64dc484a0e14887156e0e1710693eecf9f36fdf81c33182c087595a44863f0510693e8e059e7549758aec8507e96d8db95c43268ecc08673c8c7184c4abac505955de2592f06f3996e379d4c4949e7160693872c97bf1c7dabf5533e3ec0603cf95b2c4be835d6c4d0dd31868d32706003ed063ebe600a71c13e65eedde7bb630c1b65e8206b7c78c1249a49f6c954384bd6415d3077a55ba7f315b3fcfd830b861be1a19b969ddffb8d2d9866ee533afd785549d00588850f2d983e3cfa96e0414f9827b3f09105549714dfee52fec082f92e5dcaa93ae90aa69c277d8e118b3df15bc1687eb7bed716c382f75105a3dce778b1fc2413d753c17c296a28e9659f82f9632de7b8ac5526280553278f6619da55b9e947148cefe597b2e9030a0661a27bf9b59609daf3f184d2725c4eb9d0b69469e1a255e4fa047d38c16cc92f9b0c11237ab90bb80b1f4d3089273549bf2583058d840f2698e4c7cae6e9120f0f2e7c2cc1a442c7b10fa13ca77760c369948123070d7fb6157c28c11c7663a276ba54eacf111a49f84882e1a4efcab5d55c3b291f48308befb6c83e29438bd0118cf717475edcc3dc9818c1685f274bdd4b95a0f647118cf932a69e2d2dc7b67c10c1a4e2e7fe938354bf5c0e1c63e0c046d9304c1fa2efe4b1b41b69aab196703c8d1c38cc84a1fd67939229cf493f9f033d3a18e612a57c7be354cef7e06bd0d81c0d0ce3c8a9dbbff53442b5af23c721a36df42f0c6a9d6566df22d4ff3472f04f46b131da1746d74f3749dcf54c9e400b40707e059fd81083051e1e7e3e878747752f4c42ab879ea8d331fbe585f9249d72a5b45cef42b78e51f1144b2e72e326cc83c996433c6c565d98459c4a5258c9615684395e478e9382b3f7cb052a68a9d3233e19376c7878e0b0d1b8308f5b98c7695b98472dcc9f44fdbe0c352d8c95837bbcb4df2c0cea54efe7bcb485919e79cbc21c6d6d776ca45d4e158dcfc1b951168b45c3e26653d52b5997c78c68dd176161d2aa9676667b8449a219f42b4c622669d3f8b25d61f636b9a52ae9db50e20e742bcc2ea2935f92ff4e6c6d5c192b6ad0aba0d1aa30aa9859ec5a4ad2ec9b8a15342a160f258ffa14868fab6c262f8ebc726f0409294cc193789cfb2496671426ffa815df3c278d4561d6be14cd721d0ab3fb86b79d30280cbb1a3aff423dff9f308927ce76cd5d67513d81d85a2a497ed90993de3925ca09396138a14a97286a3d266ec230b2dde52a78eda768c2a039dea25dc98451ad24b14d0e13d673983049aa593ada9524e95dc25426b9698dbf7852f7963025937b74c931ea93ec2b615c913fe9b2f69430c8adae97312df2a7491864c8d36162f9e82849c2a0f30925679c226178bd14aa5ae4ece99030d7fa96fe3919df9247184f4ac1d2091fd32bc81106f9a943fefd4698729fffa829ffa03a8c305f8559524927b5672fc22c5ba37a4de94f232bc27049c79d1225ca25d1449892ae1acf96378b1311668b25c5e7d31a26070f617c1344e81acd10c6f730f9de2ff7655808638ebbc54e3a69890a214c3bd77d927b83309b6da5c91ffaa73741983e97ba19f19e82c80261fc5075f29a00619273e4b4ced208d11fcceef5726fa28b6ecbfd60d4b1f39b37257d30eba9922f5be283d1a37a6a7153a1b1efc1e8b167f23d1f264df4601a157c5fc74fb414e5c1d8b19398167db9d2c18369b7cdfe04f16addb983492a41a9962d413ede7630c53425c6bfc9aeb7eb60f4360b1b3a9cc7ce743049522dd9e87251da9d83c9c7cb6d3cc8d0a59483f9a48f8d6725a54f308983f9acf42529e7ba9d96c0c11c274c586deb08cf923798e2a7b648ebd0ab2b7183c1deebb2b5dee4d1b7c178727f121edbe48fcf0663aa7e1215a4589a246b3087aed3ad38174bfca8c15cad5a925ca72e79380d2679276b0861a73b321a4c6a26c896f4d4ebd933189424992cefd3bbf79ac124fbe74a124fea11b70cc6b558a3d39d49926cc9605069733be874694c3a06f3c5d0255552c560d0be6a33b94bfea40c8329c931a98399b42523180c172ac7afcae215c62f184dd6091aeae20573a938f92e899f59972e18c74ddb9392e682b16333b7b65f2dbc2d98639bce754a8fc99e212d28aac4ea9c9414ca82e984f5dbdbf8981f1618f149ddae770593b0ed93b5d5f52b59c17ca32bada25f0593202ea782c173c4a86c9772673405a3b7578d2993b39f470ae6159513a7e72898edb2ea6e7b0eea562898a414ebe27a3b74e709463349f8befc49ca5e3ac1a0224dc44ce8dd49698269be644fcceb30c1d8fee59e4d6e0906b7b5dc2657824105f350b9a3fac95fd2a5c4f0d5d691601a1343958ff224fa2318d7a49ed27be249b311cc225a642d664eaf49110cdbf1b2441b2082a965946c987ccd7d8661521fd9fb310bc314ba9f82d06e300c4ae73be70e36304ceae941ed75fa17065d5ec29bec51eaaaf685f9353dbc4f3e31e1d40b83d09eef463d47fd122f4c6ede229f4abb30e7281152dfe35bea7561148f2de2d299bc26b9309c38a3623eef58d2716190bd94740e2a26e7b73089271f27f76c9e1c5b984289deab9494a0e3a4168538215a74f9af21dc74666152fad1439778eaffc3b2309d5c4a4f28d14ac99a6361924fede734f13dc4ccb0306988e89244db3d09f91506997982a50e3acc8bec0af32979abeea378740bb7c27432161bdbf1e23f668559949da07e4fedc98d5761f0d85f61b6b12a8c66b7fd9ed4793a8b5361124df94a173ac44ea830e9bc2174cebda6bf3f85b1f5d2b6ab73fce2a63049e17379bcfc452d2985c1d3925612457b3e8714c6fb24a2a662e8d8e951984afba6e9a896e26151984dcc6c8f8796953714e6fe93163f545098e38890a74ac5954c3f61bed15352b985d2997ac2e815a6541ae9a1f7ec8441ccd3d8e7ef2539e484313fa86b988af893b209b37934b972ce7dad451326fffc1e2dc9b75b2513c693544cea6e3161101df76e2cc66f6b7b09c307a157d55ae6165b4b18c5342b6e575b09f3c9f5cf494277f4244a1854d33c45578df2934998c4dd083f3d494c9648c224e79294147ff6a1a248986f54ba7612a9322248984d959a7ffce8234c79fdac93fd59298f3ac214462bed98db089387fe8ef4bf7bbd19614e79cab29f1026e9781126196276e76e4395561146cfe19d93a096a6dc44983b8efef4d34b49a528224c79566d4fdeae123d3d84c9a47029a7673a7f4a0d616c352fb162e1494f8530ec499f922949cc8612214cf395aa4e272955f34198444f5352b092bcca4410a65c975573e440989429d1d9c4c6e70a02c2e0167aa673f433cffdc1743aa7e7b8f7fbc1e871c2a81cfc3e984a9fbb5ea9124b9ff0c1a442cdf8c79cc9c1640fa624ede8fde59c28213d18b5f5b7848abfadf3609252bc8b9573923d45f1600c0b9e3394242a32bd83393fad4b8ea71d0cf65fbad4899bce631d4cdbf61566844807a3c9cba2ba2784bc0bcec16039d485aee594e5827230452d3d1197611c8c21d74a8558c93cc1c1fc995de1498963e26f30a7d2bcb653b7322637982fdc961c3daa93ba0da693a4a062e3b3c1e46aa944bdbe06838ea272c84f651f4ad4603a9d4a5a5c57bf1aa5c1d8b75e42754b3446683086297964bceae84f9fc178b37fb72787934cd80ce658419f779bf8f56d19ea959155eb26190c27ad6c2521945b07c760ce26492943e59294876230898bb65ddab5245bc260f0942264e32b603099fc9e27a712d47a2b5f306d8a92b564cd0be631938b5de2739a5d30accd78a5e8f9e552850ba6a463bb5ce5c773d2164cd17faf6543e54ebe161c13e24a84e85930b52561b904132c1855f57412f4be82f136f4dd7bb682c994fa24792cabdcb80aa6a444cdd968a960922cbdc8bdab1cf64ec1f8497cd3a14499c9492998e5ccd24f0a2f0ae69274d0974d2c39e8efa0600e2ab3e4ffbd53b47b8229ddcfe70473fa0d93562f4e1c53134c722fcd4305dd9d9298603ae531d7b4f6472d2dc164312a5f36c92cde578239098b9d3be59360d05195db4912fb794782b9e436314d253549cc8f60ae921e23984dbc8e2d2d39e92298e7bc926ebb35400493ea9c9b25499ea4131e865176fc5a6f45f8bec23096f814de540ed7ef06c3a4c4f8e5b91418e68ad721f6dae92afec21c4c5011ea74e60bf3dcecf75e28e969b35e982c9892e4cf1a2f0c9e6f2f469e1445671746713361d2e4b9a095e9c29c73f4b4123b77dc5c98c4f6cf5450aa9368c285c94ddd5daeb5e0b3dfc278325f9432496c618c193f497ea716a62bd9430b9394e409aa634791a69e85792d534f5c0c6d6acbc2246527e59eafc4da3a16c53d112ccc39bd63970ad1d22b4ce1db04ff5322d6e20a83da5daa133ae9cfb81526b5f5f46ce9c4cf9215e63013e7250517f9acc2242f594a19f27bb4aa30857f7193b62a76f052613aabbcaff7b658428579c37e4e2e3bf1ec2a9053985408a56a7e4a7c535ac282278098c218a3439b259d7545dfa530aa9d2a2528499614e6718bf96dc2c74f9c466198b9d8271e2d0771368828b074234ede791e2414a6a4e4aded3e0f3dcaf262a05305105018a4880ea7af832a9df11326292991dbc9e48bda314fac16aeabc28a5c0e75cbbdefa93eb21a6261274ccd6a4b163ddde66e2e5677e91fed9d6eba7b018413261f6d1eea79e46aa53b4036619204511993921c73d0a0b1e371900347ba62d79a306ca5f9e9106a8d35342e904c18363b64286d2befc191209830850f99eaa626d6a7cdbc8441c5533c71d23f081d8258c230d7da6d9bba086ee0c8f101b41d941c366890a103f700520953ce9ea07277892cb15f4a98c24dda9a947f12a6ca503a4b5e93244c579b8a7d2514020b93204eca5df112e49fd22b0c63bdd5bfa9224dc97185791cb6420db1b895bd9d0d6185495c45286d411cb20a83ab473b191796d524435491b9c6cba57bad6617920a539d94546fec8bece4a3c21cb236db834af191f914c62c8f7721a30b318529cb7df5ef8d4a61eee429a824550e290cdac43e6182ca25e5da46618ea5325ff254c4bc22428828cc55fa63ce4913cd2c2914a66a8fd62aaaed3bda164240616c0bf2629faaa421e413e9894e1846899e3dfe623d25c91a6b3bcecd08e1040ad98439e3c404e110030734c6b05163870d1e68e2ae59757b7b17adca2c8d4dcd3ecb67e7f3185f43471964ac65c2ec597bf7d9b36775b0c69a8d622308c184f9043361dab9e48841e3737076749b904b184c7f955c63828a250c9f3c334d3e75250caed9b762b3274b398450c224acba4af01c9a8439fdd7c97353265d724324611cf92d8f26a5b9c51123615ecf5d9ec4cab549d2658440c2145465bf99ca0e7bf2904798938e63331b2a58678707218e308ff2ba8f2587ce277a84904618bbfb3d09b28475fe890a218c305ac5dbef5e894b3a5b44882230118888cbd5f2e9d2f9935cc8215071abfaf7002c21c410e67183904298c711c2e899df265c86ec8ccc46c820aa3399f54a91ef0ba7b684755c0f4204611893ec6dd3f37277bd0b84f1c45fcbebda3b407c616408ad5fe5dd1f4ca14b647e30fea95c7292cdbceb83b1d594f49177f2f192dcf1c1e41eb5776486eef660caa7fb52bca44bed8e777a30a7b314f772d0eb336e481ecca34caca4c604dde9a329383c989358752525712785ddcaddc1d42b4a50972127cb566707f3497d174e9c0815c5bc3a18f64b5e5a9354e5e860eed49bf326c7b424e9949b83c1aa837c52bab46bfc0b918326a3dc455a546bace9b09197829038186fc4a934daa40f0ea6b5be509efd69f7a37b83f14db678d95343bc99e5dc602cedbc921e4625b3dc43da604ccfa962b28d3ced710d6183419bd986daf4c610b206531cbb52a1822a253ba506838c35e9fb96f71742d26092be737e34157fe6e25c08418349d05b4a49d79d2443c8194c395f3459ee67fd2d66216630552541ea7d09eb2db98494a18490c1383a429497df55563a86e291831031982b7b8a5715461d48418484c124c949faa0157f08184c29d5be6708f982a92cc712c43ada56aa663a42bc60fa5252647de56bacf9fb0d1c39129f0eb3414817ccf104ef4bd29987102e98e2bb987cb1be6209a58e2d98b6d479e92c3f440b9b453bef2c4bb26b921ea1521b92059314b6b3a9d8cae6af3970d448c6389fa3ac48108205932c1f53bdd2bbf5c3902b983dd977ccd236ee7d9f60063470106205b3575fba684a123f992e86902a9844b930f5df2a71fb0fa1823955adc55a25099982393c55fabe90140ce3614c1a59898241d9f5afe9a1600ebe97af214b4f3005515e416ee4844a8ad539bc859b6092e307f9a5cd6782410795a12d993c640926419a509517528239b5dcecbead6e7892604e56f66bf27ef04a22c1149bdbd6c14e5cb31cc1701d64a629214a2ee64630cd251f934a8a7a9914c1d4f76ef183988d168510c1a04bc71813ef30cc713e8b3a1d4a5f528561befc2154d007c398e9f183881026426018ac840a7a964b7e619091a7d7215f187f2cc583b43659fd5e98e24a45d73bcd9bbc30eb5c72cb1eda8529943835ad756130c1939b9a3ab991736190a332adfa45b830e8b6869b9436445de816a6f5e829af6f0b939c9fd5222aba797b6a61d836b32a25589acb0e2d0c7b22e45b4811aed6998549864e37499f8a3d4ab24850614b8832752c8c6582ee9e64e3a24b5818bcf4d77f986c4b955720c7f2ae3096d80bd159eb56187e7f2f457e49b2b266854949e1e492bb64152653d124514dae33c9c3aa306865c96151bc63979c0ac3fee5a8a44654984e5c59322ddf2d1e9fc224f3d624497df707159bc22426e6ceaf782c41a9140659a3044be984c95393c26022cfe4d3df8ec230dab45b25917752b6a23009f774b1846f43613215cff944bdf594406112f9bb2b96ca5452fa84294486bb8ceca8be3d61101a5b2e6a3d4929d44e98d4a69da493977668ca0973105fa2c88d36612c179d673e7874cfd184513b5a6fe83b13e6b294a4fc7e1384943161fab951979dbd84399dcbe82d614ccdd2f1f2323fa795308f9fdc62a29430cc9d5a2d53cb8c4998c43c31badf4a499835eef3c793c748983e898eab13724d9b20248c72f721c4b5f8088386baf1354177db828e30a79b8b8c88558ba146984ccb96502578da5133c21c2bdcff9cf692e35c84e9c33ac9498a75e75714610a17b467d3ae53e74a22cce1aa3f095171f4fb8830de5a4ab1f52af3f24398e4770ef5a09d4f7c0c61d8b8102a7bbb42187d6eb67366593cb1238431d4865a5907616c134f96a70a55724910e69254092ae951ffe1b540982ffff565bf29ed016112c5940eea2e5495e80fe63422eb722d9f20fbc1e84912bc64cf2528d1d307737ad5a91c2c0fcce083e14fb6ca28298d050befc1e0213d4b96d856ea473d983db9c88e973d992721cfc883594f868e1fc69e810773fca53d593ce7ccb883a9543f2849d81f4d0bd261872a4ebeba92b99cdaa68852b9c429b994c74b52077350c24ae45a34bcb374309e52e331a48866ccc1ac9d9f6e974a3960e9d5dd9629a62629eb51b1b784b766c4c19c34c7a41aff0a1c3e1346a94fcfd68c37983c774e759e4afde79de10673ccf582196d4087e5ca6f67e849b2a1b46dbb4ab92c5aacf911f24eb86b307a3a0b9de42ce2abb621cc5043eea74fd08c34984bd9675b366d21c734030d067dd2884add396730a93df30f9f6798c194b6f2db3e7974b530a30cc6f8e0157af1f3ee8ccad0c19f3274608a0c0611fa835059392787f1f038397ec6188c7de69b9fe25fce1dd631430c5c975e8d4fc15f4187c13c66d9463e3d34bc2f3f980106d3693f4b1327fbb8858530e30be6b42d9a5e9d448c6384195e3065d3ada44ae77b13951865388e2e98f472c71093a48f4098c1057392fae40fe7962d98f2cb7e50923a9562e533b4601e39230be6dd10359f727606164c52e59e585ef5a83cba195730a55fb999170b0a33ac60ce13e4d689d413473e560583f0131595928965273f39cca082f1b4f4db799831852a091df35cab9682397fd2740e33a260f6ce2baa849e9815ed0c2898f2c784c6b0815406339ed088d1a7da3c5f0788194ef0f3093aee826e0f8b91b209a62046e8c9d9c4bbcf3899c1044b4aa26928396ec9e58c256c767529432c76a7cac9faef9736b916c3c3e36628c1a07b37f34f94fc1f4c7c0677a7c4d0bfffd30c249853d49b7cf7e28c23983bfcd34c76898bee8d60925d9492ea6415790f17c1b0a26428499ec9a33e398308a6afdfddcb7a320ca397b6b82e370bc324b645b9786f6d20182693a794163db54ae2b20160184df6d241b9a95cbeff0b835afef872c28c9e92fbc218ae3a424d1e373928d9402fcc6f4975d0a2d793cebb015e984dad09d749691726dfae941ff94ef2d2ba30c8d930418d3a37900bc452b9b9bc5cd8ce388d39b962947cf9bd47be015c182ccc4f52bd57d2be85417db4d88bf15372b6308599137a746fdf956a61169d334e289f16a6d0ab5b15f92ccc26c5678d08fb349285b9b742b34b74ff8d62611ecf7913afe4b39561918e9e8258a96c7a85c13a8c56b2d615c6f5dc5fa2bc28d9d35618dcfafaec6207999315062545d997e5925236d32a0c335796f2cdf28530a9c27025051d37f9bec49652616a0d21c46b899656255498c2e5d4a293f0a2e2e91446f75831d174e52749a630959e5bd0132f85e9a493f36fe9b229053b7af018180307367420c0023a30f062a0b3a38c1b0bb08000747c8e32769c4f341670010054c00e03671828572781f4c714904079e47a58040a10001f200c2800003b7494b1020204e07170cac0c118470c040840478e4fca701c39c848800974d820e3282000b5000000000000004060c78fb143c7efc000e2781d870c072c4001a04307f2208000ce8ee31e0508c0d9711c470e8f030060000f48408ecf417276e8a0416301000840030e506cec10a3868e438346024664516cec701c376271801158141b3b7660c3cba041230123af308997b19cac4d6a2c9f957176e373d0d8810da7e1dfb6630c1b2a1871c58ed7d10a326eb0a2d8d891a3860e3168d048c0c82a0a0d1a0818518501465261aafe9404a5525b5041541874cb47ee53d029a7ce298c5552d0b14387d27fddf81bab23a630f6579a18e6a6e4c6dfd01b7fa3e818c3c68e1c2f860d326ee04876a414267b2b4168e95c6107525082097c600513c0b4c408297630328a2a9e347d9b593a29f588280c3f6ba3bba17bf2ec91501465eb33ed6eab4366fe53b6ae31afcb279f6006345a30020aa3c89d3422de914f98f4a7142766661f58c10476f88003628c78c27855662a9ecb9cca6a8d318e182928239d08c20827ca9da61ef216c6debd3e2ba983914d983d9aba7f474734a1239930d7fc968c60c2542deaec44852e610eb1a1e26437fdded812865fb3244fc85c1939691d64e0a051239518a144625d9d7ecff12f274732868dcdc17918ec24cca7935c9a312289a4383a8850da628f045aa62d972aca24198184e1fe4cec77ff8e65a547184b0e2b1fc654ff898f71c438578830e208c3dced6768132d97be6bac8d31d208539cd359eebf540e96c30893a4f38fd2d14a4b32f911c392df412f22f38f1db34eec5f30a20893785151ef36cbb2ce35d692df818e44987279282588f498f2f91a6b85630411c6d17b625c304f62091934c6c071e3068ea4588e914318bbd4c9e16ada8e114318f459fb9f160f395b71ec388187879916c2ca1baba0741ed558eb010e442307c91103f58bb10395a1434f30031a141821c48e0c42470461b4b025a5b5cb072293adce0a6336daa22a1e3f48d33c51d515afb1f6635c937123f9c008208c59f2e82f5349237f3066872c31cf84f2b8c960c40fbba789659ac96aaa452dd1e4bd52d92526df69a40f0613e27ced83b769ab4046f8703546f6701e7a30a9d52a29d4739aca96913c24ea34de6db4c83f713c98abba54f4bc0e1bafe3c7c81dcc49e486507a4eacb4fb881db20e5b3618a1838eccc1a42b3684475f0ec93df567ca3f290e066182121c8c2596e91c6e724a42fd6f3069ef50f217773798d4e8b96c32649d9ce36d309a945298ac39618349ca8b9ae07943c92d598329b88f7f882f2b4174d46078cb1e2b6bab73c99d34984cd8ebffebfbf0d14683714c54536577e964eb33dc88190cc273cae9fc16af4cb60c261f75299fcce40735194c51d394d8b6854a151c4331677767df2e73312c05252ad7411e11835145f4a44ec235128632028632f2851bf18249f79654763add85d26da5e4e908174c693f4dfc3211e4f81d22781ce4781394cbf13b6cd060640b7b6ab3b4fe338261440b86134d0e954ebe9dea932c98e72ca8dabf207ebd62c1ec95842c31d146aed0a75d34111d762b182ffb7eff08bb0ae63dd3714a4b72840a26f910eddcf1bfa1323205d3c9572e77eebbd6272998d473e62d892fd9aaed228c44c10c25ea7b12e4fa0a05bbba4ad6aaac5db347fbc8e9850d234f308c52a53f2b7a18f39213cc9fdd3fcd8d29b74ed204f3284950399e526aee3d4c3076a7f512712657b67009461f135521ef5182491097d386de175d79adf182912498a229a9ba62877eed7d368204f37deac81565795e7381c3c8114c49e5af133dc95b67a211cc1d33faf31e4fc7915d61a408e6fab7f4f5e291c208110cbe774ad67f7d18c64eb1a4e90abae6a426228cf455126b44f6a41c54826190bf664a78b8458061b292b3437f1b37ca2f4c254fb624c99a2c0422be3095d67653ffa79467d78be4a4f465956c114a8a8618e74478614cbb4cd379ca1288ecc2141f43eae97e35afb8c61a7b40a4fe8f53be7aa1a992402417c6b470c19274299cfc15eb20820b93c679f796f8262fc9ed10b9850d115b5c2d54841629320b7369e734694f1caba0d31c3bc810914535f3157761c1da2de6a28d4ee93d9938a2f1d658cbc1694189a4acbc46c49f4a81857135dd6396506a59ba2688bce25c711ead300f11569854ec1c4d4b2ce5e5db2a4c823c9d2cd5afaa30eca99deca1543fd625920a115498c44d999c6a07955b899cc23c4c6192e2f8a8f47ff2521c8994c23c48611ea330fbe7f73529b497a093444461927949edddeacc2733147a885730eb9275f9ed70b97f4d6c2e020ad35ab61c1d4a1d804c887cc2647625d77a520a15f4229e305dea4ee25d4ff68abd7e42a413e62d69237f945b9c688b70c2d8bb96a4db988aeae8092012229b305908176f3975f259521326159e92fc1d9bcfa7cb84c9e434492c347e5c344c986c7b74ccce2988e5942e442e6150a29efe2816114b183f653dc4dea6758e8954c224077d524a822539c93a11a184f1a472511f4a65adf6e01099843975bc74aea39684794ecf426aeaa9309526914898ef76f32c5c229030cfc935a52f3f970c51e41126252bdfa2c77684c136d64f9576451a612c2947fd421461449d24a1affd6974c6b07123c7b7c0078e83038f6ce44874bc07506411c60f192589bc8c4f4f22a20863a9fbad0fb58b24224dcb32266e15ddc275980a2ac69569ed8b082288306cbec941a8cf97bd43987349d966534f9785dc10fe8cf8f826dfa4102649a7f49f7c564218e7efcd4ef6141984495b69358b1f15dfff2208e385f8cb4edf25e56ce204914098e412c24bfcc9950208736fde88a648cb1244fe60ce275a52bc5c4925bbc50fe60d2d5a3dd5a95ed12929d207d3b765653d93b39ea8dcf1c19cc39a18dbca692e28ddedc11cd277cbf4cbffe975450f267525c449f7db4bfa532e0f86710f537a3a3a05113c184e569ab7f8bac81d4c5a224aca88a99ad444ec70b625ab5597f30a9be5c240a40ec65ecf397a10659e318b41840ee63a759dc49372ba5451292273308d1057a664b7e79b89881c4cf1f2838e38917b4b6986834988dc1033a954d02929f206837f86fa6c4a4ec40da6ef58b9cbe28a5610698359cb94a84e556ddbd12c88b0c1e826c8d2313efbe7cc4e640d06a584d89a245d4cbd2435984bcd08e939e55fd489481a50040d2a72066377ca61ba4e8e19cc29084f7a52d2595cb63298e49c4ad27fd16c248890c168a32f885d16392a976330579f99b47f520a27e445101183a94337f45f2f27059130984cea6cf392b3db9e1087200206d3953c7aa753f8af245f912f18aeaeafeadcbc238878c154aa4fde5b5c184b97638248174c7de26ef7f58b70c1b49dedcce494cfe1df10d98229a83939a6c7490ba6cf355917a79205639a6b28cf9a08160cb3a3b488e65a0221720563b9b5574a234f9424a714112b98070e44aa601e2f420593b65827c5cb39e9ac1415884cc1203f7f1ae59504e56a12838c1b3674f00944a470ae7a66a9d27f0e328e05225130d55f5813c363c4ab480c326a243bce8d7c8108140c3662257aa7d26953167982418ef00d5bd1151127985b44259593242729497d600513d80d8834c16097a4648b30216b20b2047352d663a37b6139f94a30c992c2a9c8e734de27c1384a1056b284aa8d3a418239b5727dce614b1e751fc1245faba5ab24664d6e0463072b115d725b04a3e8cb9eaa388a10c198e1e9baa4d9cec15b43840cc3a85b2a3caef6981027c2b0c45c95784247c34348304c9653a82badbdd793041886d55c933be83a3565fec2606ff36549bf5d5a2e0b21be308593c3782715bb905e987b9497ece085f0c2b0a27582d0bf3c3da65d18bb042bc982858dd35d1706a1f565ba9e5c984f3095e41bdd679260e3c254b363929a249d720f86dcc2244449c1afcf6d3d46b630b6e596a07feae1e3b53029213f5d57a74a10420b93508b25f9e9ab9e3c08426651d97bcba5fabd9a6c9fad9e105998bcc6f4622407426261028bbca8844d86c202712c14094522812814c549de02a31308001040288bc562c1589c4792a80714800261301c30301e22261a1810161c140844a27018100a05c36030200c0a868361704038d72bce01d27eef3b00b85f514892e958453c11e6f509852fd6ada4feb37c69993829a97f39fff8442ca5d66769eedf13552078fa948f347755964205c2adeec70de4a7bd56f01fedc60a52b8fe4e865a2707a21a7b1b39cdd7739a0f21b1d04218dfcbe703be4b8fbbe8cdd5a0edba8dfe5c5052de871837ac68b65c1f84516301e64f33055d564e4841430c57abbf30a7111465d1855cf229ae23dab1f9d98093a221048ed6d73c2b5e2ebb173b4225444b156c07728f5cd09f9795bd4d32b89a3f3b4ab83a1eb80ba8c5b2a2e6cf5c80a53a9caf80c1c9c0420f93547c67c43496e2e0b159cf66549cbc5d49d67983af744d3a9cdffda91a3839816ad87a60072c2690b22688df258f08ae08801288d08dca75a5112e5967a1d9c9d6ecaf2ee9163245504f4ae297d8d0c3b23ab354be07a25a1b7dab9f1546ea510b691178ff3ee3dc69a6feca02bbb77ebe8922a89001681f48392cca6e919a45ac28f4064c9315efe2e506ed11eacf4fd913d21176239fd38b5c454f1c2feadcc24b5c09a1fca23267941e115c686c366b51438ee787ec7c218f2f3334549a06a5b3d5297ab3cc66069ae4fc3b9c2856904361e69f3f9192269c106284cbfac206694dd6cc7582c8902e8b7b4587b6dea3fdc8690b623476e0d197611ed745fb30fa1a02b2d5557aad99f7e96790b8a43b1d4de056bb4cd140064e4576c393363480a54b0a490963eacc1e86f0beeca0866a9a3f9e9092ae474381d56ba45a8b5b470585820a3175b3866719e4585255411d33da9d9320e083f3a2fc01d9d0fd3058b1216ca0f5c15466994ee37c9de8827f6684b292d5f2eed7a2f479eefb96df17177a269cbb261c6b1d99ccad084f715837f8503afb878097b7499e7bdefd6b8730ed378efc1d2046144a94077ca6b359a33a9a269fd18f1deae2513462894373c94810ad9c2c4ef39126295a5b3bb99471c106a55a96a996a420d9485ec6a3f893bc554d13c3b31a8a2e74f3b374a7edf7dcbd92f2c571414c91b724edb8b56d7cccc9dfab9da7175e40b5c3a22b8e584c64625297cc92a5d12f59d91c426cdfca70cea6106b4bfc77a09ac31750d0a815ec275b6e42ee997396bd68c608608629f38e7acebdd0ee29da536d6a57acf58626520db54e03d74b36154003c85072a6dcdf2ab8e9bdc2728a4c21e7ff35af8f56384f969192ff6501702c45b38542f1dc6c0882c04bfd34c300a1a7282cda3c5084a84adb665eafe29b4619c726062681da7b04edde8599eb04c913b24181b00c63eb24d0d89a321270d0576a699e82f91eff82abca9d752db3659ee7772e58cc5cffd2e7db2df8ec1f44bc5420613316f34758110ef78e11f4870587f55768330f4157bf239b242cb36a33b0d8ff0d6046df21626fb402afc73812cce104abf16a4b6530f639884be0132a5b791cd423262a94c4e1c47ec56cd416eee1fe8087f1310d3bafe70d5db643291c875994f17631c1c2c6635a0e35c5f31a513bb19d26a29c40f3ae5ee0c28d5d63df7e932d3cd0642b3e863e90fff9f3369930dfce206f6079e51b8ab8a787d7238cd77ba757050cbf2053b644689cefdce821a4096d58734c50789273b0b5ca466a83a411d353d9ec2a4209b743371ab4491abfe2e64ba060f0b9710b929dbf00f28736fd5ae23514ac11b73e0c94f863477ed0ba0a83f37827b51359469559e8841f6f32d1398fd897358baa67f858de7f406eecf2deff960266edaf14a828cb3d3cc829b26b45e008ded1282fd53bfb94810de98cdd7578add51b674a7580df293d368841e71d9603f06c9b58ebf861829e73949ae2f1cd63050defd4589cf707aff9dddb41796b22ffe0a82f5445cd59e5c1c637364790f863c091483c61de7dbc347e1995182c7d27826b54ad434161a85876c558422a8721f6f16c2b916f941c337c725554cd5d298a28d5ea7eea5398c6af90ce2edd9a3df4fe778163699c87c2037cd9c4445b6d2d37dfeff0ddafba6d7eaa8d91f17c6b2751c761dbc7774f54f32bede8981420d69dcf716543192848fe20e80508512d052599e96bf00680aee4bd3805a81159eb5c92643480e6eaaabab34b43885cd099e6a5449984c1a6364fbf728478630dc8f177a6f382f7587166162f829b2601c9939b37049dc47f10a79fe074ec8e70c877f68f0c7cd07ee37a01bfc0e6f36807b9da112ae79e72f453ee9f9680ca7aac9caadac15c2b80a7ef8711ff954d289462c4544ec4a4252c594faffa49d4346404e2bee859b065bd82d1064d107bf863ff7ae119bd765a901542e702974869d4611580e09f6c61649eb00e1e54a9c267989f713aa6511c27c40aef6beca967cc3bdaaf4a54a327cee306b7697400b62d2cc25172da176b3281740c0531022a6236ba6860d074a4207132659dd70f97588c7c142585268b6611c86d5e74ed83538a11e5faa0ffc71d444630bf645dea15234430844d183182ef69b5d5222f15448dbf63174b00001d38167758450611487cf9ef9e8378d0af1c7d52ed9a8a40d6de75022cbb1c9e90fb72072e490f18050753655e36073f7e8c80452d2e87110da03808800f4ea369a594a0c08b90435dcb4f97136d7f2defa2ab168103a33f723e3b762d77396b3ebe92e88faa2491a3c222819b1f41143f3f9083b353e991e563952a3bfbea4f33ccef436edc917ea9d26ec2f4615c64cb43a3c089f013e0e52b727f6d4c3109eca2a26c4e5a40242aa93f1345bf8d4d0a483b3b2158f91a110abd60d1c705d21c7b98dcbc55a326330a2605aa31995295aaf9781797b22b15ba412dcfe5c22722f732032b8a5daa5e7a4e5c8cdbe046e3e43a6580fcc8a6900726b7f609474efc7d0eae89e0c768dd28920ec504fe5ee0055b0bccb2ef17ae5cfd1c0de09be413aebbd6f7a5f122702d359b85dcdf84a70e5eb3ea5df2a9f9733d73bad765dc202ebef2c7433562166b1d42bc4c20ace8bd951990ca5f450f1106fc28891f9bf3491284dfc54afddd2bbf0ca04071f5293cc6a2c57bbda040442ca19497fc5e35a6b057cc1af3eec5c5623c008ca1c5407505c0927087987b5669c6bf50b66ab40809d0ab4b7abe1a0ab7d1f5f524cb52cd8826a68f23f5e221f65894c00782f598327ca4efefdb49192bd5874c3e3f6aea8499b475b85ae3ef7ab44edb7962b8dce476d86895b2f77f37e46e5f2b422698f93d131e1ad861462ebee61e34b5a1db93ad762c1143325b79a8af4e1152a4c522711f5c1852dd34b23b650d1eca3a66b99e84600ea141634eea15004d982935a73693493fad6543ac344a38007884e204353070f84a4addb531c8933f8b5d7623c08b993c18fb4be5a24d5510d5cac3d2a654f44288ee7c9217ccd7fee0a1a9a0568f8174d9aa901b3bc69270a4363c822c778532d025d3caeb03ee49f03cda6dce01029bbd5a89bf6e6b4ecdd6e122ec0d089c71e78aeec49defbd8542c953663be180f13176e54e2df4f56b621b499d9c8374895ab2dd66a892eddca1bcd823b8ccbd06b7f3dc4f382be151ba4f063635f411ab1637a9dcc8343d7581224794963cad6d7bea7ca9459dc185943364048bb12638d642a78e22049456c84ad5f819aa74fa8b8a26e2cc2b7ee68c08e0b03d8b9011a084d3603d5c66051e56440f95f377a101a5e9f956184c3266bcdf81e11dfe30a4454ddc8b8692271e8f7f6b1ee9a9642d79f5e29ab2cc77e2a06e1c9a1318d1e4e0dc26aab378590d9ae82dcc131ab7aabd14cf3bcc01b7f0991b0db060b4d4daa0118df6212d8a029c91b79cdd130f99dd87a845c220e5402fda990c3915080cd15e62ad9c971b4b1f85f24eb5d18b7f03a129db6d890af048c062db80cf8aaaa3e3569d1295a5cac7b48c0140453ee7a0883a3ee1e559377c97f4be200a569f6535bab0765180877c6870480a2b27574916919c0f42579d9d87be55b2c69941902f75bb0522c68c244ccb7fa469520ecc49dbf2c5f21e57572c8d53953f3a4dd77ba40f20caf009820c831ef7240055d8e23f6df7b1d217bfcbffcc781d09af4d8a3042b2b2d4495dd4f663a839944471a5cb6e22168651bc0bc57da031ccd2624af209394358fae0258712066c4d417503a1c7d467eb4a55706a3628bbc9c199c8fe8454d11bb9300b585d23ea02ed701a820d0f72c3a5c0e984ee9e5e86318cf6bcf1180170a484a576750a36d3a3ec24b81b16a0fc75adb90990c77ae8ce6a239533a0732b45b3341343364c1b0a0bf8e5fc342c8892270c932971ff7cf19dd4b73844185915a6e5b22a0b779ed805194c9593ed456419dcd1b67447dfcb09b342ced21449b9e1542a95d8fd7998e00077edf8ae3eec342bc72b7787e5929b4652d0fa462f211aaf31b584e85cb604be2ab6f9f0d4b663b8e3671b3602d18c231fb1419fbb0d5c448a25fce60e5252e5a5dc790e000c5048b76988f32475faa4815598a8672a39cec134be4283533d93c86a86917e56567512464d55509d387b2a229ca90159a5c7fc0999bd1fc01db1081d66c95472674f41c6d6ac45ada8fa14112c3fd03d96fcb43657e87648cf92cb467c4bc626e2f33a02597c39aaea18882b6911a87de7e4f75c71acda31fdd3894122c87490bdc7c955a9dba4e670d257e91c40608992c17ae3e5ef8a78b1b71c6d2964ded9e81d82ecf8cfe3979fd550803ac33665b7b7c0421482905c2a640914f81defa09b2fd1c8dbfc538e9ec473685462968ee2a76733a4650450806b943690dc056a3e928102e62a95194cbec13c1c0817050c40518e12b9939f2012c43c43ce8242808934c4be4e050366ac0f97f630c2f977762f439e3c8c2658e5093748c4d9d041a637a0a85708a5f69b53c6a96e69f55d6c7d17cfa951147077527eeceda06695c58b21b82b67c8ed511ccd040c9a6177aa912ae7f752a64548e822818aa540d1f82062a970e4b3ab557420ec31f9382bb4d8895e4aa08d747ac8da75dcb6e4755984c4255ef08568816f774b0258b3f79bc738a0caa082609a398a139f2673abefca59ccd5ac600a0428baed34bd84d9b784c4bcb803d96a86337f9ecb3de64e0d5a6f9d5b2e2379f2a3ea82bcc1cc9a4b37cf97ffe25db81efccac93dd706317d245ceb77aaf433b2404d8eb51bf09e09c78adc2248695d1a461d40eefa4878a03300b5e5a683e11f50d6d15e9717cd34d8770089e9b5a3eaecf56de5e8f164291eb3fac13e26cf130c0c62082b3ee1455af50ad212737974435e78972f11cd587c07cc7ea24a6f3aa382375152a83191fb40780a56d43fed559e88fd9e15eb781db1a2b85e748d6659bf0971b2745e531e53d9a34c82d5ad9261f04e00292a2c15dd0423454624d34f427dc7480f5814e86ac82f7c101e014238ca1cdd84d918c6a1d9deaabfe5b2881f8e39536aeff8af171a06da130b8807f69ae243cb0ad29429f98c8fe6cfa9c076f72af35a8a18c8d7c953f20dc83c7f98029e8dd83473a4c8f77e9af0cc02ed643a173776d9acb7025f72a40c51ec25301d122c021b9428d4a8be54cc7081fb932c6cc9ffd69e69a105924ab708e1f32254a658b9280f918b80a439257449726566064630389b456aa4be15d0b0ef86aee0f72579e4a6748f78c5b72e14a61969d5ee344b098c0bfb674ae4170b8008adcc08ac8197af012570cd7679b6c872cca65ad24f40ad8fde0036d6d2953e405b4b81aec8fe5f26baef852f521d94ddded9d1291fab3e2f1f2fd275ef4bf21ace4e61cd8cbacc392a6c06e29d28e3bc5d6d65458e247420242ba964be407f16926cd51daf5b67aac4a5bc2ef1a5c722305bc744422a41f4fddcbc8a4c7ee3a5e5a980c1a6964c21d4400a70650a3a6c576a5c924bb300fe47b282d584e452c07339e073ffcf6811f8ceb7b7c1441f50e2e6336b9d9a4b1a478113db3e21b588b8f13580d91cee9f6d2585ae1e86d8c8e59edfd2983cae5f97ca80c3faaad7091a6b9c8814ed9e5ae34331b9f0d47ae6f6e0ccf74325d3226ba3d68c4e5739043d15c410148897e03a4c8d47cc070120a58c963de934184fd4f9bd503d579916ac173dde7d18476bb4bd07d4ac8e96dfc7437fb1e3dc1e4533f0b6692eff866b685f1852f7ffbf2ae2019ee923d797a32669682031ab53e3c57110acbdb088aef9f82d8a3b908c25a9bda7da060cd0be8569b442bef9f02cf1a41c97d100fd088c87660d3a0de2f840b795aed760c83ebce161606f1a2091982ae49940a36e4884f0dd990e0324b5cd204332b846e2dea877074f7b4b4a6c4a6098219c467baa7778876fcd52ab1ca743183c52609cca21fc8b55bbe1dd9565c69a3f576459c14d3015f39788f4ea8a1d0612275b366467fdefd608e6ba0748e3a4313f12782f695fd09f3bd3f2e1b1faef10a82d064730e429da5a24ff5c37b6b6e0986f01fc10e85340f6b04947f60ae6ecc6fa1d79bb361e05723854bb0d01ac26534739c06fea3848628c351881688fd82a8fd009ca37ffc5cdefc6707c3e10dcc25276a50f8ce16e6277d5943d506cb689675e7aeb0e9775428f60e417d1c4542e9829beb29b22dbe240ec5cb015c412ae3c74e3a7dfec142e2c0c7b4473f0bee1b1dc1e9565c3800c71857c2b1cd6ebc41e33a976e85d9057681ad4c5e50add5d6cbdf0435fbe593ae660c2427b9ee6b909daeba520a2b8e1cc6ebf4fa4ee83e746670efbb76e745522fc4014331064e28f717bd1ce930e72031a927089a8ebf8dbd6627b835ef7774d13d58fdd3fd4494a6e46cffbc193c679a2b527b9b00c3ceb16aba988fe067c0242467cd93df9fb862262181a223b7f2c73b48693995e6f532cbb42545a68eeab263b7050674958684ba326700a63c51ac307846b79536ce33d7229a4bd02180eae702c98a5b3a7959f6acbe716220f5a86b8c46297343fa183d0cb3a1a3e3e24e66de6b3d68da27b78576b85159c09fce7289bfbce34cfd6404081a67e5c6f28fa4420b2b33328ba39372ab5a8aa5fb27606bc758384ed701ff83c0fb2e4879be8d015206e3a7189a9841dbde58abe96762e39cc0a713c9638b4bacd66a4235620229e43efe040890febaf7790f19f179af80ee24e8d023fdedf3148f7e1b069a7ede31ec29560becdf24a2abab0cc5368582493b23f1587c372c8538e92e535ebbe8fa73ac20a6a0c93e5969b827f6737564682bcd4abb84d0efe2c8c032d9252e22e6f17caf6a15e520c9a2f9a51a1fea042731830b9c3ca53bb129d1b53f27b0a12f8b130de612bbd514bcce13f1279660f440aca7f28aecc44c47d856dd80b0deae205c47da81fc983964bf0989cba8c9edba8a363073adab7e325b9dac56bc37e5317c63bbe8b98c3fe668773e5a1baf818f66373068b901da3a414f653ecbb24cab9a85fd770f1a11cdd0d75e84ee3f22edba93f96bb337984829cd4b6829cd931bbcd5375804fdd655cdee93aa6631f9ff2b1f4eb1e5dff05c545ee705983abfec33242a10cdebf6d5c911a894a579f5063c43be06bbb2b67624ae902973fe6b07b2edaf5b7a2daf4a378c462666fefd3b1b9ffb649c62e6da6d0c3a35aef4a09632b7dc316e929129a4c265baee137b66163c42a295e53a27ecb33e21f4cd1235f18b8cb29655b246dfe143ba26ab59ff5d1ac9f227b114cd93d0632fa5bbd8caeebd6ac54c2d90d1496b49ad248b84441e21d828b0992d7c57930a68dc0932935a134d91100da224a76c2cf687b69b5ae4fffeb72699776394feb98d8edc02d2d848e7b757d07e3fe4eb3833f590e9b0f1ec8240c5d93cc52ab25e524eda99fb774922fdfc56191549a12061c1af075f53c613adb111deb9b785516805229a3b41cde2d3b3d1b767ac9909a3bc4238ba69c55228aa0457fe7b38208bbdf753b947694828f3d16598c3a9706f745872d9ce7b4c8898b440c99e185ac8db6680dbbb29d25022a93fd5d8bb98d7efcb81ebc7c70c7edb63f90d3bbb8ed4319787b5738c20b7501bec8d97964d5e82fcb2c6ca61f904c165296a00bfd14767a4f779cf29622d8d1bf29a91544f8d3ca8b286b4a9ffc786bd85cce2a0ade7d3f491896af57c1b22144623f32bb59eca872a960336bf0d25fe2a5e7b070bfd893fc715efc5be49eefb98e539aaab059aed227db8f719a72434fc01761e6ad067e0f202c72d0921385929aabb5070f75146d4c88411753d891ca9456eee3203ea69090f76887fb403bb8cfa202fe9267bbbd8e7e13d42e2d3f3b7825644232539e39ec4a591ff6c83493182a41c7ddb89d844abcdd8468010fbbccbede504e31942fe2511ae804d7b8fdf0b85ff4ed07de98fad90b94c2e37944737d1dbc41e3990bb3bb8b537be79b51a06ef3ceb7bb59480ea51912a8dac763d0e24fa6a4ce70d4e24733242f476842225711736f564913a9691960d5f0ad512b80adeb44681b503461f0139f369489da0427132ccb947afc99a2a5b006be98bf1bf9ee1aef88e3fe06e4b9e18e35d283df391ef98ee88ab84457fa74f06d442f146fdd5a4403fac43be0e4550b5b43c84efbf7a2748584af707351f1ef51222c5d09523ce2ccf2fee4db20e5fec98167eba2b80855717965c76dc19cb33edec85fa39951d2a7146ca8c7cdab9abe74acb20c1b13334337a90699ae8646283c9e96fa59859a55228bf9a8870c36a0910722ce1dee6616772d991bd8decc6c415dcd4d37e75a519def85b94682ddeef8539f910b919ce4c16d46bb60659fdb4f0e11f53de68a76b009d2ed7d8538cdf07231896e622e1a8b00f54904cc6f20c1ec4839866b88dc28c7388c755b0a58e23651b3d1ce085d88646b0710fbaffdb5959a8e5388ca360fb0fdda5e0238d756f5f5cb91af69e5e9afa899404de547a9b7c2590bcb3c05018c4c80499126916e2d0f6d1c4f207276337e32f5362f0ef99eebcf740544d9c00ee80ea99dd9aae37e40975010854c829cc979f2cfc9d5a253a5674a56690e3066c9fa6fbf9416c29c28b8052fddc84d9d69bc72aa258edf0505a99e93fcd55069bbaabdb8e120c1d34b0ca7218e73a022a9c26f687122739036048384de7fd89733c6f1415ccf7009498b5a4de553b483d3436dcfcd250968e3c80bc5a11506f7d03782afe0e48661c84357d8c2dd1fc759525f7a1a80dd346b93ee33b526567c41da09f94f02ccce18451d5426944c88eaccd8474a4b11bbf21b526dc8ecb30903323316a07631128b680afec1a9f2400671ff745a903fcb8c7407c1894894fc0cae758abf57a5cb89872186e42845b5f69b4f573019054746080d12938d399a64c7cc16e1bf7adaa72d646a1d4f785228161462a08e71fab62c84dd9c99e5fc45d18567647a9c89b5fd9a0929945bf5d49d50a63f61971263a45255ca99ab447f5e348b515a25289a953ec813e89c1b69d1329d78b6f6e702c45221e3713066ad22ba70fde00cbc46521106baee69258f3df20d8936e3b4de2cb7e70c3c824c8119ed0b63fac29774b24a9e319cbe1ec922c7e18a0a3cc58b8b2b223a9e3f20a6b577826940abce6dad8f467fc9187b300823b57a9234b968d804dcea80d26391720fd45582dc1be011b390a757a8c8a4c83696fc41859a46efbbf8a30adee59481d3c31782a6888fc13a0476010604cec3c70f20d955b0e8cae6f8d0b678181447d11798e9b5dabc1c7ab88545d345e6f1f182c8308532a333933a8d21f4e640628ff32195aeaf8adff31560fc7e68cb6b183627311cbedd03258aef3a30c712b92f0266b233de40a517f2b13fc5a0e6aea12bc435eede24c8caaf7e4ec971cd951181f36857e1c4c78ed8d43e5380ce88dcf5eb9221eef013dd0d3e2af7b66aa650d1b0e2746ce96e04ae6b3186c51b22c240b3be458ca4538bb1cc890fb6cbf02ce20b9a0f478072db03a079026a467478b1125c7169c97eee394a2688719ad9e293dfbd1bd7a0e96a5d18bc554ef602b483310408c764367ccf323f48cd7f9ab6e8f725333b19a66a1431a9881f36c359059cc1125cd31d1953bbc64572177a725b07c78a89c67f11d019fdd387cf4ec30ee8318dcd76a99cade0d0c45a9cbd10fd93688f34a17f5b8999a2a6c5e6198f74e0b4d0013ecf84c8e28b3eb7775058eeaab7c32160aa0f18b8c33eaeef60f3697dc62434e60d99faa3628b3a94d0f0d85715c383fef38216bb06ef34300408bd73279aa27a0c9aa1549a63388e32d89d61afaa0901c126bc8ef786bdf082c238ab1fd84d0cc9b485b0b796cdc17e1b7d16300060a481f6c5b99551092fda0786eaa9702f1e7bcffe03a5a36422341535f148ac007a3ab8c891eb363d54cd9dd39178da932f25816a0a474e96b7c77ef18b88604c55992a2c99c2f5f09004fa9fbf53bd45085c45be40c8872cf3399df238e21bb8b304c03208409eea94bbdde75f4b969af38d7216532a7035b1b47800b732e9fb40b4fcae45101f9432e965414e9f74ec1e122f2b0616d69383831420a0239d2acc4efb4e07f387a257d21118d9e52131f46fc4a9dcb965e46d112772dd5418be938aaf6c0ec67c9ac27137af60a38177c42a85a4a6135e4534647aa28fd55bc3bba0a613d88a72455ce08dff531b031f0d5c9ff8e069d19217678e817edca92e9b726047665b40cc021801c4eb719d1f51659b3292d2f724e4d1fa99bb481295472c2057f3cc1b2ecfedf59338a2f7fede8128f53d5f87953090b2c7823b47c9f53e93ce0a0eca7c4d0227cba983f5a20ae210321b20c2f4b9a97dda5238268322c5d18ad608c088e51a6cb14fc3be9dab5d80a55af0181b4e95c9394acdac928cbe79f304ca0037ce4b8c0a1e43ff8e54ad8b4e6b97c13accd31640e5d44b8d3302f364bb14d7637986c56a7893d67a3f96f8ae3d2d05b6c5b965a04661c5119080c4c507f0b07d9de283bebc378650c367c24d2658652012515eb75038740ba97954f29cde1978d30297aafa06f2d20ab72d485b96ef2b135b324a64e28f147c9866e6153e84529c4a220d4c90e2fccef893e39b12788625eb01dbacec409bcc038b320c0e80053489ac76a04ec39191500607c1b01049a3561c1f9652906bb28b6bd0ab6cb10436e21dfe546388e6c79c89b2587696736b4a4c591bb6b5567a916cc297fce14235c27ba0d4b9fb7168e6fea995fc71ced97a7a07be3109d429745d3b2167ef7bdf98e50dcc0e70d8eb5449fa1bf4fc4da340abcb189732127b4dcc2a73290a7656eb91cb0893cef64eec483e6639e0e416b3f5fd0708404353698e4531e4746a9726cfed18ac1bc7819bb16d6308dba9eb7716d0661172eea4f44942b266c0c50de7ba1df2d3757685d82b3fe605a27bda547b187f5af0ae0d678fb27089748c7b2d4646c8b1a629fee0c9df95e212c3b053b2383cbd6c85d4b065b6995735566420a8ee17db532a60c34c072d14c111a8e36c741081e2ccd3b2ad18faac5400e9d5c3411740e3268b4449c0a84a0b24310da871dd315ad3beac036e0b6e74c51361131f58ba7cd186d5b437d0c55a07abe61b01553a92c2d3eb01d5587f61d3f2ef9482f61e4d1efede76d4340d87b0fcc9d7421267f14a22cca6ff5bbb889c99df49f24dcc0a8d4c1f72607337949f75a74e81b35b38b4e5da4de598cebf9dab3c7129bdef825fd1c4b4f8468b8ac0810f14d4c07e9e965c0c6317000b1f5f1bbf5ca3c9771b33278dae93483ce9243794e62036dd1f5bd3102a889afc922e6e512bd235a70eb2809ded3005a07478aaecc17002dba479371de6bdd8332c2ccc073aab89e83af8b8c8e0c0b6cab14e1a33b9f69c85e3e9c22b1ac0de924570309273fa30e242f35d131d8e1f8c51d11d7b5e6b0baefffaaff96020620556faf460954223720d04fea71bd015cfb8bd144970791c9b82fdab2263513f03d4c26ad3e5dbb004bf5b63163e3204a9d0dd0a5d0284e4566be9258b96a5a0164e39bfdcc2b58f76d4112dc52d7812c58c9a47e73fef65a45bb898fba8d7fcb8ac1d266593e9b0c2052f46d2d3e2dfd6dc2fe1d656d28a3f04c01d003ad9656c5100b603f819f9ba32eda9dc1643c6cd983283534208d3a4447850abe58d22f971298dc0a5f8fcaf71e534ff4c7d70a783ee30c57032b86a4b9205f3000c61ffebe0c2cdcedd5b02ca80c3b1f5d301c482fce2f83a5cbe317b9ae0466105aa993188faaea171db0c5410e0b468d82b6d4d183b860f1787ab6cca3f567f2f29c179c1e538c4757f825369b411196ce827a6c0b094a29243ae57017ad2db6204609d5f2b4092296f55e27d55801d2c965003a50af84619f93e957365c3fb6518c9b18e070f8186316404", "0x3a65787472696e7369635f696e646578": "0x00000000", - "0x3a6772616e6470615f617574686f726974696573": "0x0110c8caee6f6eddc41c6cc55e554343392cbc13d2a8a57b97f6f85fc965bdd20ce801000000000000008270a62b61639ee56113834aecec01de6cda91413a5111b89f74d6585da34f5001000000000000004c669b04865e9acaf7b72bdfcb0099d70d9ec63c8c2d6b8cb0552815d7b50a0a0100000000000000c9a68a26e9aa37ba6334f1a20275e3be7d3a9d4aa988627eadac8ea0d0a2dfbf0100000000000000", + "0x3a6772616e6470615f617574686f726974696573": "0x0138c8caee6f6eddc41c6cc55e554343392cbc13d2a8a57b97f6f85fc965bdd20ce8010000000000000083f43ee3e4521b55de0fe830847fda88a6b017b87979af1a41b180c39da1e4b001000000000000005fafb6219eb8d463bec0370b2aab69f45fc780959fc2eddbc7703760aa34202201000000000000008270a62b61639ee56113834aecec01de6cda91413a5111b89f74d6585da34f500100000000000000622c382187c0b2c61ecfb17443294d11a9d2ab770ae6f1fb49184a43906d59fe01000000000000006e309dfa4c8de814cad140b8612a9e41bfba244f9ab1468e1b5d9b3cc1f5e56501000000000000000509f9caf32fda5584343c473b386c433acb99fd9400724b8cf3c618d840133f01000000000000004c669b04865e9acaf7b72bdfcb0099d70d9ec63c8c2d6b8cb0552815d7b50a0a0100000000000000e41426f7465c13c48335771c5450bf61c50a9cf28b9274f170c7421eea7974f10100000000000000ace46e899b90e75199549d8fa2ae7097e896ab3c845217e3155f99b6ffb888030100000000000000c9a68a26e9aa37ba6334f1a20275e3be7d3a9d4aa988627eadac8ea0d0a2dfbf01000000000000006e60f1e253735fb113c183fa603f591e4456435171f387c0849001b428b5ccb10100000000000000c8de3a01502422b59dfa601c9c3a04a98d2bfbd79dd0810d1d1250feab4241ee010000000000000064adb43a7628139f6c02100f6a5465dbd33422418426c572b12547c5a665008c0100000000000000", "0x3d9cad2baf702e20b136f4c8900cd8024e7b9012096b41c4eb3aaf947f6ea429": "0x0200", "0x3db7a24cfdc9de785974746c14a99df94e7b9012096b41c4eb3aaf947f6ea429": "0x0400", "0x3f1467a096bcd71a5b6a0c8155e208104e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x3fba98689ebed1138735e0e7a5a790ab4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", "0x42b50b77ef717947e7043bb52127d6654e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x47c9410b11325752265d54845357656f4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x4da2c41eaffa8e1a791c5d65beeefd1f028685274e698e781f7f2766cba0cc8300000000": "0x1003000000010000000000000002000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a0600000010ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826ad90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451c161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c682253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124b000000000000000000000000000000000000000100000000000000", + "0x4da2c41eaffa8e1a791c5d65beeefd1f028685274e698e781f7f2766cba0cc8300000000": "0x380a000000030000000400000002000000070000000b000000050000000c0000000000000009000000060000000d0000000100000008000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a0600000038ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826ad90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451c303094c583e253794c9db14803585baaa74472f4ecba846defefc8aecfb6214ac45a6d0878f808b1baaa85dcfb4e930ae06e3205bb38855527aee6f259e3327b2253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124b02683131f96baec9121383995904c49a02ce2c2451f8038291e5db2dce66663e0a988fb965b156a07debf072fd9d34a9c7c0fc0e0ff5bd63ef766afb76e2b32890032c39c968f486f77f8764301a8479206f063d49eeb9f6d499333e2a1be045161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c680ce84accce1ced0de223aa72f760f1b3d13ddfd267938cd63e25308378d320084e1a59090261a7e6bd82544df1eebd96dc87b4eb1211346645fa44d6b932960b441629077e228528f91ca7dc17051bb437408a5ae272d0950e58961846a8fc2ed0d052eca7d732d9f560ba970ca48f67387b899e76958ea6ed342a3a553ef0229e065eea4143325fbbd26967c26a228d51a3a8384062f7434973f15d1da2c010000000000000000000000000000000000000000100000000000000", "0x4da2c41eaffa8e1a791c5d65beeefd1f4e5747352ae927817a9171156fb3da7f00000000": "0x00", "0x4da2c41eaffa8e1a791c5d65beeefd1f4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", "0x4da2c41eaffa8e1a791c5d65beeefd1f5762b52ec4f696c1235b20491a567f8500000000": "0x00", @@ -92,43 +109,113 @@ "0x5f27b51b5ec208ee9cb25b55d8728243308ce9615de0775a82f8a94dc3d285a1": "0x01", "0x5f27b51b5ec208ee9cb25b55d87282434e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca0b6a45321efae92aea15e0740ec7afe7": "0x00000000", - "0x5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1": "0x04000000", + "0x5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1": "0x0e000000", "0x5f3e4907f716ac89b6347d15ececedca28dccb559b95c40168a1b2696581b5a7": "0x00000000000000000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe700afd9ad680e7563894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10", "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe700e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe701887a9d70c3dff6e6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70198703ff0791c2de1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70260868bcb77241070efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108", "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe7065903e26e594bcd6d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70a8a26ecf38bdcfc668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70ab8d3e1fa99ea7e2d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c", "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70d30ebbc69dfd05038eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964", "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70e7e316712ac574569037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc402d496d20c019d22397accfc42b7635d94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b100f0080c6a47e8d030f0080c6a47e8d030000", "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc40ffdb9747f7a8bfa200ea2291eea6bdf9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f0f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc411fcf3e922de10898cb04273301735e65270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c0f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc415fbc5d9b44885a2dce0fbaa3834ba211e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c4130f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc4279effc2672354478fb5e3f7e65726b668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c690f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc42ffe7c0dd7d3d8d8485c403a33fb7adb6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a22596270f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc4350ea875b4c0459b3527d475e9825c99d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d0f0080c6a47e8d030f0080c6a47e8d030000", "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc44d176c4abc6d2410c43423c2714b909c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e11520f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc4585bd5ccc1af6cf60c19d791bb091b750efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f761080f0080c6a47e8d030f0080c6a47e8d030000", "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc465bb58c29c9825c1f6727fe8c41650ac82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c0f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc46deaa967a94fa09152be01a253511479d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c0f0080c6a47e8d030f0080c6a47e8d030000", "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc4829f3f4d6d7c991993e0c044ae97410b043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d0f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc4ba2db252d1b8c64ec51b04d0f50d7d2b9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af740f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc4dfc40f350cc4563ad9ddff5ad92944278eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b8689640f0080c6a47e8d030f0080c6a47e8d030000", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a000000000afd9ad680e7563894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a000000000e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a000000001887a9d70c3dff6e6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000198703ff0791c2de1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000260868bcb77241070efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a0000000065903e26e594bcd6d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000a8a26ecf38bdcfc668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000ab8d3e1fa99ea7e2d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000d30ebbc69dfd05038eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000e7e316712ac574569037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca42982b9d6c7acc99faa9094c912372c2b4def25cfda6ef3a00000000eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca487df464e44a534ba6b0cbb32407b587": "0x0000000000", "0x5f3e4907f716ac89b6347d15ececedca4e7b9012096b41c4eb3aaf947f6ea429": "0x0d00", - "0x5f3e4907f716ac89b6347d15ececedca5579297f4dfb9609e7e4c2ebab9ce40a": "0x10043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e11529492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0x5f3e4907f716ac89b6347d15ececedca5579297f4dfb9609e7e4c2ebab9ce40a": "0x3894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b1082c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a22596271e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c4130efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170dd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e11528eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b8689649492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af745270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", "0x5f3e4907f716ac89b6347d15ececedca666fdcbb473985b3ac933d13f4acff8d": "0x0080c6a47e8d03000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a000000000afd9ad680e7563894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a000000000e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a000000001887a9d70c3dff6e6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000198703ff0791c2de1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000260868bcb77241070efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a0000000065903e26e594bcd6d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000a8a26ecf38bdcfc668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000ab8d3e1fa99ea7e2d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000d30ebbc69dfd05038eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x0000", - "0x5f3e4907f716ac89b6347d15ececedca6ddc7809c6da9bb6093ee22e0fda4ba8": "0x04000000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000e7e316712ac574569037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca682db92dde20a10d96d00ff0e9e221c0b4def25cfda6ef3a00000000eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca6ddc7809c6da9bb6093ee22e0fda4ba8": "0x0e000000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e169030afd9ad680e7563894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e169030e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e169031887a9d70c3dff6e6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903198703ff0791c2de1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903260868bcb77241070efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e1690365903e26e594bcd6d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903a8a26ecf38bdcfc668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903ab8d3e1fa99ea7e2d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903d30ebbc69dfd05038eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x0000", "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903e7e316712ac574569037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x0000", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a000000000afd9ad680e7563894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a000000000e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a000000001887a9d70c3dff6e6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000198703ff0791c2de1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000260868bcb77241070efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a0000000065903e26e594bcd6d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000a8a26ecf38bdcfc668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000ab8d3e1fa99ea7e2d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000d30ebbc69dfd05038eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x0f0080c6a47e8d030f0080c6a47e8d0300", "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000e7e316712ac574569037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01bb4def25cfda6ef3a00000000eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x0f0080c6a47e8d030f0080c6a47e8d0300", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade980afd9ad680e7563894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x00", "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade980e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade981887a9d70c3dff6e6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98198703ff0791c2de1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98260868bcb77241070efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x00", "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade9865903e26e594bcd6d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98a8a26ecf38bdcfc668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98ab8d3e1fa99ea7e2d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0x00", "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98d30ebbc69dfd05038eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x00", "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98e7e316712ac574569037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x00", "0x5f3e4907f716ac89b6347d15ececedca98c2640cda6c0d801194a8a61c699224": "0xc8000000", - "0x5f3e4907f716ac89b6347d15ececedcaa141c4fe67c2d11f4a10c6aca7a79a04b4def25cfda6ef3a00000000": "0x00001a93fa350e000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedcaa141c4fe67c2d11f4a10c6aca7a79a04b4def25cfda6ef3a00000000": "0x0000db02edbc31000000000000000000", "0x5f3e4907f716ac89b6347d15ececedcaad811cd65a470ddc5f1d628ff0550982b4def25cfda6ef3a00000000": "0x00000000", "0x5f3e4907f716ac89b6347d15ececedcab49a2738eeb30896aacb8b3fb46471bd": "0x02000000", "0x5f3e4907f716ac89b6347d15ececedcac0d39ff577af2cc6b67ac3641fa9c4e7": "0x01000000", @@ -147,18 +234,29 @@ "0x6ac983d82528bf1595ab26438ae5b2cf4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x7474449cca95dc5d0c00e71735a6d17d4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", "0x74dd702da46f77d7acf77f5a48d4af7d4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b150e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c01043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d0132eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e115261c091f7b7cb03000080c6a47e8d0300", - "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d000182c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c61c091f7b7cb03000080c6a47e8d0300", - "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e11520182c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c019492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f61c091f7b7cb03000080c6a47e8d0300", - "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f0132eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e11520061c091f7b7cb03000080c6a47e8d0300", - "0x74dd702da46f77d7acf77f5a48d4af7d7a6dc62e324093ba1331bf49fdb2f24a": "0x04000000", - "0x74dd702da46f77d7acf77f5a48d4af7de5c03730c8f59f00941607850b6633d80863c87cd8a129fa61c091f7b7cb0300": "0x01043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d019492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b150afd9ad680e7563894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10000182c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c61c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b150e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c0194c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10016ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a225962761c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b151887a9d70c3dff6e6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a22596270182c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c011e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c41361c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15198703ff0791c2de1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413016ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627010efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f7610861c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15260868bcb77241070efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108011e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c41301043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d61c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d010efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f7610801d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d61c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b1565903e26e594bcd6d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d01043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d0168728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c6961c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15a8a26ecf38bdcfc668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c6901d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d01d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c61c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15ab8d3e1fa99ea7e2d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c0168728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c690132eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e115261c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e115201d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c018eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b86896461c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15d30ebbc69dfd05038eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b8689640132eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152019492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f61c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f018eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964019037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af7461c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15e7e316712ac574569037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74019492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f015270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c61c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d62556a85fcb7c61b2c6c750924846b15eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c019037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af740061c091f7b7cb03000080c6a47e8d0300", + "0x74dd702da46f77d7acf77f5a48d4af7d7a6dc62e324093ba1331bf49fdb2f24a": "0x0e000000", + "0x74dd702da46f77d7acf77f5a48d4af7de5c03730c8f59f00941607850b6633d80863c87cd8a129fa61c091f7b7cb0300": "0x0194c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10015270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", "0x7a6d38deaa01cb6e76ee69889f1696272be9a4e88368a2188d2b9100a9f3cd43": "0x00000000000000000000000000000000", "0x7a6d38deaa01cb6e76ee69889f16962730256ea2c545a3e5e3744665ffb2ed28": "0x00020000", "0x7a6d38deaa01cb6e76ee69889f1696273f0d64e1907361c689834a9c1cb0fbe0": "0x20000000", "0x7a6d38deaa01cb6e76ee69889f16962749d67997de33812a1cc37310f765b82e": "0x00000000000000000000000000000000", - "0x7a6d38deaa01cb6e76ee69889f1696274e7b9012096b41c4eb3aaf947f6ea429": "0x0500", + "0x7a6d38deaa01cb6e76ee69889f1696274e7b9012096b41c4eb3aaf947f6ea429": "0x0700", "0x7a6d38deaa01cb6e76ee69889f169627ba93302f3b868c50785e6ade45c6a1d8": "0x10000000", + "0x8671567f6bbc0021f6f23105f33002a84e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x89d139e01a5eb2256f222e5fc5dbe6b34e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0x94eadf0156a8ad5156507773d0471e4a16973e1142f5bd30d9464076794007db": "0x00", "0x94eadf0156a8ad5156507773d0471e4a4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", @@ -168,52 +266,147 @@ "0x9c5d795d0297be56027a4b2464e33397f43d6436dec51f09c3b71287a8fc9d48": "0x00000000000000000000000000000000", "0xa0eb495036d368196a2b6c51d9d788814e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0xa37f719efab16103103a0c8c2c784ce14e7b9012096b41c4eb3aaf947f6ea429": "0x0400", - "0xb341e3a63e58a188839b242d17f8c9f82586833f834350b4d435d5fd269ecc8b": "0x1003000000010000000000000002000000", + "0xa8c65209d47ee80f56b0011e8fd91f504e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xb341e3a63e58a188839b242d17f8c9f82586833f834350b4d435d5fd269ecc8b": "0x380a000000030000000400000002000000070000000b000000050000000c0000000000000009000000060000000d0000000100000008000000", "0xb341e3a63e58a188839b242d17f8c9f84e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e": "0x10ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826ad90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451c161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c682253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124b", + "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e": "0x38ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826ad90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451c303094c583e253794c9db14803585baaa74472f4ecba846defefc8aecfb6214ac45a6d0878f808b1baaa85dcfb4e930ae06e3205bb38855527aee6f259e3327b2253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124b02683131f96baec9121383995904c49a02ce2c2451f8038291e5db2dce66663e0a988fb965b156a07debf072fd9d34a9c7c0fc0e0ff5bd63ef766afb76e2b32890032c39c968f486f77f8764301a8479206f063d49eeb9f6d499333e2a1be045161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c680ce84accce1ced0de223aa72f760f1b3d13ddfd267938cd63e25308378d320084e1a59090261a7e6bd82544df1eebd96dc87b4eb1211346645fa44d6b932960b441629077e228528f91ca7dc17051bb437408a5ae272d0950e58961846a8fc2ed0d052eca7d732d9f560ba970ca48f67387b899e76958ea6ed342a3a553ef0229e065eea4143325fbbd26967c26a228d51a3a8384062f7434973f15d1da2c010", "0xb341e3a63e58a188839b242d17f8c9f89d1fb17def62216d598940d64654f69e": "0x0000000000", "0xb341e3a63e58a188839b242d17f8c9f8b5cab3380174032968897a4c3ce57c0a": "0x00000000", "0xb8753e9383841da95f7b8871e5de32694e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc602d496d20c019d22397accfc42b7635d94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x047374616b696e67200080c6a47e8d0300000000000000000002", "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc60ffdb9747f7a8bfa200ea2291eea6bdf9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc611fcf3e922de10898cb04273301735e65270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc615fbc5d9b44885a2dce0fbaa3834ba211e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6279effc2672354478fb5e3f7e65726b668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc62ffe7c0dd7d3d8d8485c403a33fb7adb6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6350ea875b4c0459b3527d475e9825c99d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0x047374616b696e67200080c6a47e8d0300000000000000000002", "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc64d176c4abc6d2410c43423c2714b909c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6585bd5ccc1af6cf60c19d791bb091b750efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x047374616b696e67200080c6a47e8d0300000000000000000002", "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc665bb58c29c9825c1f6727fe8c41650ac82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc66deaa967a94fa09152be01a253511479d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0x047374616b696e67200080c6a47e8d0300000000000000000002", "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6829f3f4d6d7c991993e0c044ae97410b043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6ba2db252d1b8c64ec51b04d0f50d7d2b9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0x047374616b696e67200080c6a47e8d0300000000000000000002", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6dfc40f350cc4563ad9ddff5ad92944278eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0x047374616b696e67200080c6a47e8d0300000000000000000002", "0xc2261276cc9d1f8598ea4b6a74b15c2f4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", - "0xc2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80": "0x00e473ba7fd26e0e0000000000000000", + "0xc2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80": "0x00e4be87ea9ef50f0000000000000000", "0xca32a41f4b3ed515863dc0a38697f84e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0xcd710b30bd2eab0352ddcc26417aa1944e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0xcd710b30bd2eab0352ddcc26417aa1949f4993f016e2d2f8e5f43be7bb259486": "0x00", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb30e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x4c669b04865e9acaf7b72bdfcb0099d70d9ec63c8c2d6b8cb0552815d7b50a0afacb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe444000ca3c2703db1633a27eff681d979967988c3a6752c669fd41f1abde10f3b054462253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124bf0e6c42698fffc28f9fc769fddcdf165af54c171cde43690cc8f73c853de1f0426e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0xc8caee6f6eddc41c6cc55e554343392cbc13d2a8a57b97f6f85fc965bdd20ce8b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a650edf2a41cb81178704560b02c35f5e01a5a97a568ebc10c025ade18b6ab2fa1d161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c68def964eed9a73f8a6610f1a0373378dca6f277eb7787869ed5841893105ad930f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e8768", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x8270a62b61639ee56113834aecec01de6cda91413a5111b89f74d6585da34f5058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe32330274bd654c470ed9b94972c1f997593fab7bdd4d6b85e3cf49401265668142584ead90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451cc083b0d0bd7d6ffd14562b4c9e28738b087ccc32262170c633c18359ff84877992cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a543", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0xc9a68a26e9aa37ba6334f1a20275e3be7d3a9d4aa988627eadac8ea0d0a2dfbfae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e24553306bd8fd81e50cda2bd67bf6893d921d1aae5cb08409ae43e0bff4d54e1830e58ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826bed3b452f869d187be58a4ba98588611084283810728fa75981e792beaec4151763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb30afd9ad680e7563894c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10": "0x6e60f1e253735fb113c183fa603f591e4456435171f387c0849001b428b5ccb118bd0f67d77f04f1a92400421813d8927fad109b40a8689254a5f0c8b346857cd28145a7cde195a4c834276730d30f074b212a150e770931ee9470e853e7d22402683131f96baec9121383995904c49a02ce2c2451f8038291e5db2dce66663e92ac14f8ad1811cc83861afadf12f3191cca1391f1f3af705977faa2fa2bf46a629f9fd0dd7279c7af7470472d1208a13e33239b484974d47cffce4ad47856440333022898140662dfea847e3cbfe5e989845ac6766e83472f8b0c650d85e77bae", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb30e8cb253c2fa33f382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c": "0x4c669b04865e9acaf7b72bdfcb0099d70d9ec63c8c2d6b8cb0552815d7b50a0afacb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe444000ca3c2703db1633a27eff681d979967988c3a6752c669fd41f1abde10f3b054462253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124bf0e6c42698fffc28f9fc769fddcdf165af54c171cde43690cc8f73c853de1f0426e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e02182879ec92e811e2a8cc117f3cde1f61d3cba0093134cfb1ed17a4ef74915d4a", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb31887a9d70c3dff6e6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627": "0x0509f9caf32fda5584343c473b386c433acb99fd9400724b8cf3c618d840133fb2efe7e70daf44b3466c63ccbf4487f42c6a9f6fbb7050b849691e36ce92e347bef47a9e4b47ed57461e1d28cac7da327a52ebcd64d74080d31deb3ac7a7645e4e1a59090261a7e6bd82544df1eebd96dc87b4eb1211346645fa44d6b932960be4ca45c68b0248885d190d22068c6628ee2f00d9fa0706d5a5c1c8456369f03eaa3955187f755708cd6a8104314b962ff5043e36efa3ec5d84df40c58b44222102f4f4d0eccb899bf2d611b56e0afec7c740efba404f8d0e82a545f988c45316c4", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3198703ff0791c2de1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413": "0x5fafb6219eb8d463bec0370b2aab69f45fc780959fc2eddbc7703760aa34202274dacbca0cdb5099afef67e622c147614198e669931cebc605629da332632473b414aa148096a92a1831309f758f944725653363ccbaeb21817b7df5784b8d46c45a6d0878f808b1baaa85dcfb4e930ae06e3205bb38855527aee6f259e3327b2e2f75472708a497d1743f52b04edf26c250d9e6d220f3bae3d176f02f8e586c2ada042fb4bbfd9b6d8c48293ffc4a7722632c843a67e608554c41d06aabc41303a0af06322d100056125fac1df39d161089b07ae279505aae8731c4d110a54ad7", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3260868bcb77241070efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108": "0x83f43ee3e4521b55de0fe830847fda88a6b017b87979af1a41b180c39da1e4b05440add43e5388a81aef665c9086d386c0be0ce75e4f8a4a3d8168e976ea821f98aab6f52520022d011a6eba2dca1c6327edbbcd753c170dcf0e9118b5f0f25bd0d052eca7d732d9f560ba970ca48f67387b899e76958ea6ed342a3a553ef0223e547f5cc3455a61d0404d7296ceec7375cbe20322109d118c5e725b1a5cbf04cce3ec06252cf7cdad47fe1265047a9bbddb9059ee4bdc6dec83b67249b4a93403f045328f504c13dac9ddd9b1186098aee7c46cb8d55289dbbf2433bab7a26239", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3572aae990801cce1043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d": "0xc8caee6f6eddc41c6cc55e554343392cbc13d2a8a57b97f6f85fc965bdd20ce8b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a650edf2a41cb81178704560b02c35f5e01a5a97a568ebc10c025ade18b6ab2fa1d161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c68def964eed9a73f8a6610f1a0373378dca6f277eb7787869ed5841893105ad930f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e87680325fc2095902f5fe394f244bce38b0dc3d631cbc05f0b64d5620a71bbf2514f0f", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb365903e26e594bcd6d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d": "0x64adb43a7628139f6c02100f6a5465dbd33422418426c572b12547c5a665008c1ab03b1b3277edfedd24ef3d3359b449b64bd95ed82a04e7f9fbaab7b71dc0152cd12c731d91441f0114b08d314cd3f9a9f7fd0240d467fe54adefbee4d90762441629077e228528f91ca7dc17051bb437408a5ae272d0950e58961846a8fc2ec22ce14ba0e59aa974d4a05c9208ba5ae18674c6a23c9998d91e7d1ebea7e06b9a86227e204a2d003399c2a3b50c2c869c4380c195a014a02f6d2e7048941237029a1eb2e31dcaf468dbb516f9b620fdd7c3f090d58a88e02b51b25255b2182dd1", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3a8a26ecf38bdcfc668728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69": "0x6e309dfa4c8de814cad140b8612a9e41bfba244f9ab1468e1b5d9b3cc1f5e565c44b3e8efe854419ccd5801a82ada22d39cfccdbcece382304cdfeac81ebe402a8a03d86e6c0dbe180cadfc7994121f462b28f7a8cb1be7e0e354147624be7340a988fb965b156a07debf072fd9d34a9c7c0fc0e0ff5bd63ef766afb76e2b3289ef622d2467ed115fa0c6c86303e1ef6a08a0609c97e616aa69b026a6d3f2663729053f28155071474b4686323db5f7a318cb3f088b76660cc8ff5e3e11ec32e030e901c390fa37d101ff25d70594acd2df67b4493ee77a73684f25d39313536d7", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3ab8d3e1fa99ea7e2d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c": "0xc8de3a01502422b59dfa601c9c3a04a98d2bfbd79dd0810d1d1250feab4241ee6248d87bd2a640ffe26d6b831735887c24e2076a3a0f3a74f7ae7568c27604087c03ca47a3201455f8f89defda4aa909cb1d25dd9ddb7fd62a940606f79b566390032c39c968f486f77f8764301a8479206f063d49eeb9f6d499333e2a1be045165f3b255dc17054e6d4447c4005f689eb5ed2f99fe201f4ff799bf088495850047277f22b9ef92a8b99618f4c86c2412f0e3b08a4f965f842775672043d1e2503586dafcdab3d4647d4dc68732a9cab8aa34c00c5edd04e65d9dd44c2a1fd21e2", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3d12736684524574c32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152": "0x8270a62b61639ee56113834aecec01de6cda91413a5111b89f74d6585da34f5058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe32330274bd654c470ed9b94972c1f997593fab7bdd4d6b85e3cf49401265668142584ead90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451cc083b0d0bd7d6ffd14562b4c9e28738b087ccc32262170c633c18359ff84877992cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a54303aec8e80ea0375f8669d6e55d7abb6a3117678d7bb851a1bd100a01e52a4fed90", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3d30ebbc69dfd05038eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964": "0xe41426f7465c13c48335771c5450bf61c50a9cf28b9274f170c7421eea7974f168a9ec74fa35b3425eaf503dd36294ba8e758e7b8084c4d6bfd547f8c6b5827460fcc9d094d21fe17cfb7426501f50cb3d75c4c9395a3140e0f255443f660d3b9e065eea4143325fbbd26967c26a228d51a3a8384062f7434973f15d1da2c01068f7a83678a377701b46a5e6a4637e99868186ff4835fc0e3914cc56a76a360164ffc83f4f86cc595e607a00b977eeb6641e02a4e6e556c24ab163aecd7d146c03e843f200e30bc5b951c73a96d968db1c0cd05e357d910fce159fc59c40e9d6e2", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3deca1f47c95ad9e99492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f": "0xc9a68a26e9aa37ba6334f1a20275e3be7d3a9d4aa988627eadac8ea0d0a2dfbfae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e24553306bd8fd81e50cda2bd67bf6893d921d1aae5cb08409ae43e0bff4d54e1830e58ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826bed3b452f869d187be58a4ba98588611084283810728fa75981e792beaec4151763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e029338ece1c6bc6439dc4d16bfe33f28c9f0af31626bb8142849742b7a624f6807", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3e7e316712ac574569037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74": "0xace46e899b90e75199549d8fa2ae7097e896ab3c845217e3155f99b6ffb888037c8348ec95a0faad6a638ef74864761028c53221bde07e9ff7c81a3f427abf3f30c40adee5476157ef3c2a26e10cab95ec7d54b62dd220738f5a474d5f86874e0ce84accce1ced0de223aa72f760f1b3d13ddfd267938cd63e25308378d32008eed33645cda7812cd343bbaef9131b2794812f2fd37701ccb6cddf9c1e293d387aeb767131602e6612e607a9eb8e26b4ce4fa4765593d032bc923ce8acadda420203d51bba2124f480e3507eb1764fc3019ac7abae8ee215683a285078bda7f51d", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3eec11b5fca7cddef5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c": "0x622c382187c0b2c61ecfb17443294d11a9d2ab770ae6f1fb49184a43906d59fe50412bd7d3f1075e8f8e3b682d05ea20b391c287d8c849a0e49a78f568553e6994848b8cf2cbc9e6fd72db8d80676591b5be4d1ec68972ada48cf6fd01228712303094c583e253794c9db14803585baaa74472f4ecba846defefc8aecfb6214ab400c4164d016282b202c1d42d9dc8ede28cbe4b751d463bab5f23fef42b295a8c15606f4c121376097ff0e96c2a33ea7b024d812b42fe2c741c8b8cee17e63d03d46c454f9b620603feef8c3a2a5d7098205b8566500fda0fa0b456d6ded54538", "0xcec5070d609dd3497f72bde07fc96ba04e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19500ad445de53dc0cfe6175646980729053f28155071474b4686323db5f7a318cb3f088b76660cc8ff5e3e11ec32e": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19501153f927dde4f0796173676e80f0e6c42698fffc28f9fc769fddcdf165af54c171cde43690cc8f73c853de1f04": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195012ba4e8c9e90550f6173676e80b400c4164d016282b202c1d42d9dc8ede28cbe4b751d463bab5f23fef42b295a": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195016108068be661c046772616e806e309dfa4c8de814cad140b8612a9e41bfba244f9ab1468e1b5d9b3cc1f5e565": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195016d5d491326e20327061726180ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950172bf7b1d4fd362d62616265806248d87bd2a640ffe26d6b831735887c24e2076a3a0f3a74f7ae7568c2760408": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19501aeb8a0909a0259a696d6f6e8098aab6f52520022d011a6eba2dca1c6327edbbcd753c170dcf0e9118b5f0f25b": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950206946fcbcbb55c06772616e800509f9caf32fda5584343c473b386c433acb99fd9400724b8cf3c618d840133f": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195022df7698c94798dc6261626580facb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe444000": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19502bf84b6fe354ffa4696d6f6e80bef47a9e4b47ed57461e1d28cac7da327a52ebcd64d74080d31deb3ac7a7645e": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19502d8e55cbf27bd5fa6175646980763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195033918a92ec5a0337626162658068a9ec74fa35b3425eaf503dd36294ba8e758e7b8084c4d6bfd547f8c6b58274": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950365a4d707a6ade5270617261800a988fb965b156a07debf072fd9d34a9c7c0fc0e0ff5bd63ef766afb76e2b328": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195036942a186c91d1fb6772616e80e41426f7465c13c48335771c5450bf61c50a9cf28b9274f170c7421eea7974f1": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950377ac9e1db771a9a696d6f6e8060fcc9d094d21fe17cfb7426501f50cb3d75c4c9395a3140e0f255443f660d3b": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19503a73714b16fa1b3b62616265805440add43e5388a81aef665c9086d386c0be0ce75e4f8a4a3d8168e976ea821f": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195042faced8513a5a6162656566840325fc2095902f5fe394f244bce38b0dc3d631cbc05f0b64d5620a71bbf2514f0f": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195047d6f38d0fa588e4617564698026e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950486e2fc6fe1baf7d62656566840333022898140662dfea847e3cbfe5e989845ac6766e83472f8b0c650d85e77bae": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195048ac54571b914843626565668403e843f200e30bc5b951c73a96d968db1c0cd05e357d910fce159fc59c40e9d6e2": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19504d5070934a9a468e6261626580b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a65": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19504f6e7e79cc9e4f1c6772616e8064adb43a7628139f6c02100f6a5465dbd33422418426c572b12547c5a665008c": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19504fbe8be23f344f7a6173676e809ef622d2467ed115fa0c6c86303e1ef6a08a0609c97e616aa69b026a6d3f2663": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19505214a412d15781646173676e8068f7a83678a377701b46a5e6a4637e99868186ff4835fc0e3914cc56a76a3601": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950523f922d3cd709c261756469809a86227e204a2d003399c2a3b50c2c869c4380c195a014a02f6d2e7048941237": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195053557db7980560f461756469802ada042fb4bbfd9b6d8c48293ffc4a7722632c843a67e608554c41d06aabc413": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19505bb3161fb65601ff626162658058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe323302": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19505d3dc734864e36256265656684029338ece1c6bc6439dc4d16bfe33f28c9f0af31626bb8142849742b7a624f6807": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19505d9ac86ecdf920c170617261804e1a59090261a7e6bd82544df1eebd96dc87b4eb1211346645fa44d6b932960b": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195062a6c483038fd12d6265656684030e901c390fa37d101ff25d70594acd2df67b4493ee77a73684f25d39313536d7": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195064cc468ab603f8926772616e80c9a68a26e9aa37ba6334f1a20275e3be7d3a9d4aa988627eadac8ea0d0a2dfbf": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195065ccc9ce9f581b2c61756469807aeb767131602e6612e607a9eb8e26b4ce4fa4765593d032bc923ce8acadda42": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950678c21325827e7c66173676e802e2f75472708a497d1743f52b04edf26c250d9e6d220f3bae3d176f02f8e586c": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19506792a176f707220962616265801ab03b1b3277edfedd24ef3d3359b449b64bd95ed82a04e7f9fbaab7b71dc015": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195067f9bb125e8b25cf696d6f6e802cd12c731d91441f0114b08d314cd3f9a9f7fd0240d467fe54adefbee4d90762": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195068d2c0f060d8e93b6772616e806e60f1e253735fb113c183fa603f591e4456435171f387c0849001b428b5ccb1": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195069561cd534084d42696d6f6e80b414aa148096a92a1831309f758f944725653363ccbaeb21817b7df5784b8d46": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950717bb541f3dc932d6772616e80c8de3a01502422b59dfa601c9c3a04a98d2bfbd79dd0810d1d1250feab4241ee": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19507180ab4d5ffe8c79706172618090032c39c968f486f77f8764301a8479206f063d49eeb9f6d499333e2a1be045": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195073b0d3d9242f219d70617261800ce84accce1ced0de223aa72f760f1b3d13ddfd267938cd63e25308378d32008": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19507466b8cede2256a27061726180ad90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451c": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950749c8bce91e643ae6772616e808270a62b61639ee56113834aecec01de6cda91413a5111b89f74d6585da34f50": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950795802224826305461756469808c15606f4c121376097ff0e96c2a33ea7b024d812b42fe2c741c8b8cee17e63d": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19507e5838eaecbd9fe66175646980629f9fd0dd7279c7af7470472d1208a13e33239b484974d47cffce4ad4785644": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195085436b71cc38efc86173676e80e4ca45c68b0248885d190d22068c6628ee2f00d9fa0706d5a5c1c8456369f03e": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195087f680d5c3a7dcbf617564698064ffc83f4f86cc595e607a00b977eeb6641e02a4e6e556c24ab163aecd7d146c": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950892d429df08b8e486772616e805fafb6219eb8d463bec0370b2aab69f45fc780959fc2eddbc7703760aa342022": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19508cec3cc48ae13ec86173676e80def964eed9a73f8a6610f1a0373378dca6f277eb7787869ed5841893105ad930": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195090ddc04de598f6716772616e8083f43ee3e4521b55de0fe830847fda88a6b017b87979af1a41b180c39da1e4b0": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950961fc927b0be61a66175646980f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e8768": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195097b423b109a1a3e7626565668403a0af06322d100056125fac1df39d161089b07ae279505aae8731c4d110a54ad7": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509990e89dc7508f8f626565668403d46c454f9b620603feef8c3a2a5d7098205b8566500fda0fa0b456d6ded54538": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509c34aadd3112cff46772616e80c8caee6f6eddc41c6cc55e554343392cbc13d2a8a57b97f6f85fc965bdd20ce8": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509cc6d5a70d4342de706172618002683131f96baec9121383995904c49a02ce2c2451f8038291e5db2dce66663e": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509d726f19fb7e918f6173676e80c083b0d0bd7d6ffd14562b4c9e28738b087ccc32262170c633c18359ff848779": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509f08b41b3412bdf7696d6f6e8074bd654c470ed9b94972c1f997593fab7bdd4d6b85e3cf49401265668142584e": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509f796bfaa6092095696d6f6e800edf2a41cb81178704560b02c35f5e01a5a97a568ebc10c025ade18b6ab2fa1d": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a0aff76314285afe6173676e803e547f5cc3455a61d0404d7296ceec7375cbe20322109d118c5e725b1a5cbf04": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a39a50629306361270617261809e065eea4143325fbbd26967c26a228d51a3a8384062f7434973f15d1da2c010": "0x8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a69397f216a7497a6261626580ae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e245533": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a8670a2360fb4f7d626565668402f4f4d0eccb899bf2d611b56e0afec7c740efba404f8d0e82a545f988c45316c4": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ab8402a39318e10f70617261802253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124b": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950aba2e02edcf42d916175646980cce3ec06252cf7cdad47fe1265047a9bbddb9059ee4bdc6dec83b67249b4a934": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ac3745478a256f54696d6f6e8094848b8cf2cbc9e6fd72db8d80676591b5be4d1ec68972ada48cf6fd01228712": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ae71ab667a6367956173676e80bed3b452f869d187be58a4ba98588611084283810728fa75981e792beaec4151": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950aee25d4290ea4d846772616e804c669b04865e9acaf7b72bdfcb0099d70d9ec63c8c2d6b8cb0552815d7b50a0a": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950b090c0a6a6d34dc97061726180441629077e228528f91ca7dc17051bb437408a5ae272d0950e58961846a8fc2e": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950b40a2e291d3757e66265656684029a1eb2e31dcaf468dbb516f9b620fdd7c3f090d58a88e02b51b25255b2182dd1": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950b469b5316f2df49e626162658018bd0f67d77f04f1a92400421813d8927fad109b40a8689254a5f0c8b346857c": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950b6da07aad040c4596772616e80ace46e899b90e75199549d8fa2ae7097e896ab3c845217e3155f99b6ffb88803": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950b9847e90f2a93d58626565668403aec8e80ea0375f8669d6e55d7abb6a3117678d7bb851a1bd100a01e52a4fed90": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950bad6b6ae80666780696d6f6e8006bd8fd81e50cda2bd67bf6893d921d1aae5cb08409ae43e0bff4d54e1830e58": "0x9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950bd1ab2cd6f1dc5a6696d6f6e80d28145a7cde195a4c834276730d30f074b212a150e770931ee9470e853e7d224": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950bdd996f23001764e62656566840203d51bba2124f480e3507eb1764fc3019ac7abae8ee215683a285078bda7f51d": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950be81b84f18801f516173676e80165f3b255dc17054e6d4447c4005f689eb5ed2f99fe201f4ff799bf088495850": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950bef85ee78e59fe8a6173676e80eed33645cda7812cd343bbaef9131b2794812f2fd37701ccb6cddf9c1e293d38": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950bfb5b848b461277c7061726180c45a6d0878f808b1baaa85dcfb4e930ae06e3205bb38855527aee6f259e3327b": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950c1cabf91e699980a6261626580b2efe7e70daf44b3466c63ccbf4487f42c6a9f6fbb7050b849691e36ce92e347": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950c2bef1fa94927270626565668403f045328f504c13dac9ddd9b1186098aee7c46cb8d55289dbbf2433bab7a26239": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950c3b366be127c04d76772616e80622c382187c0b2c61ecfb17443294d11a9d2ab770ae6f1fb49184a43906d59fe": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950c61ff1db24ad5e86626565668402182879ec92e811e2a8cc117f3cde1f61d3cba0093134cfb1ed17a4ef74915d4a": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950cb18236e84f2bcc8626565668403586dafcdab3d4647d4dc68732a9cab8aa34c00c5edd04e65d9dd44c2a1fd21e2": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d1c1264edac2bfeb7061726180303094c583e253794c9db14803585baaa74472f4ecba846defefc8aecfb6214a": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d4b8d8139a9d2a3862616265807c8348ec95a0faad6a638ef74864761028c53221bde07e9ff7c81a3f427abf3f": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d5b902094e722e906261626580c44b3e8efe854419ccd5801a82ada22d39cfccdbcece382304cdfeac81ebe402": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d74338095b2b3a5f7061726180161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c68": "0x043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d84b213ff11dcdc96175646980047277f22b9ef92a8b99618f4c86c2412f0e3b08a4f965f842775672043d1e25": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d912f1fd94200c50696d6f6e8030c40adee5476157ef3c2a26e10cab95ec7d54b62dd220738f5a474d5f86874e": "0x9037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950db189b9054ee003e6175646980aa3955187f755708cd6a8104314b962ff5043e36efa3ec5d84df40c58b442221": "0x6ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a2259627", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950dd45ac2fed4ab0db6173676e8092ac14f8ad1811cc83861afadf12f3191cca1391f1f3af705977faa2fa2bf46a": "0x94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950dfe86daa30500684696d6f6e80ca3c2703db1633a27eff681d979967988c3a6752c669fd41f1abde10f3b05446": "0x82c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c", "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950e326352daf693946617564698092cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a543": "0x32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e1152", - "0xcec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903": "0x10043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d32eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e115282c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f", - "0xcec5070d609dd3497f72bde07fc96ba0e0cdd062e6eaf24295ad4ccfc41d4609": "0x10043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170dc8caee6f6eddc41c6cc55e554343392cbc13d2a8a57b97f6f85fc965bdd20ce8b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a650edf2a41cb81178704560b02c35f5e01a5a97a568ebc10c025ade18b6ab2fa1d161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c68def964eed9a73f8a6610f1a0373378dca6f277eb7787869ed5841893105ad930f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e876832eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e11528270a62b61639ee56113834aecec01de6cda91413a5111b89f74d6585da34f5058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe32330274bd654c470ed9b94972c1f997593fab7bdd4d6b85e3cf49401265668142584ead90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451cc083b0d0bd7d6ffd14562b4c9e28738b087ccc32262170c633c18359ff84877992cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a54382c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c4c669b04865e9acaf7b72bdfcb0099d70d9ec63c8c2d6b8cb0552815d7b50a0afacb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe444000ca3c2703db1633a27eff681d979967988c3a6752c669fd41f1abde10f3b054462253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124bf0e6c42698fffc28f9fc769fddcdf165af54c171cde43690cc8f73c853de1f0426e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20fc9a68a26e9aa37ba6334f1a20275e3be7d3a9d4aa988627eadac8ea0d0a2dfbfae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e24553306bd8fd81e50cda2bd67bf6893d921d1aae5cb08409ae43e0bff4d54e1830e58ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826bed3b452f869d187be58a4ba98588611084283810728fa75981e792beaec4151763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ec74f4b6dbe6f07e626162658074dacbca0cdb5099afef67e622c147614198e669931cebc605629da332632473": "0x1e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c413", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f10dac37e2a0f812696d6f6e80a8a03d86e6c0dbe180cadfc7994121f462b28f7a8cb1be7e0e354147624be734": "0x68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c69", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f39a56e067ee2ba9696d6f6e807c03ca47a3201455f8f89defda4aa909cb1d25dd9ddb7fd62a940606f79b5663": "0xd0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f87aebc04f6a52ae6173676e80c22ce14ba0e59aa974d4a05c9208ba5ae18674c6a23c9998d91e7d1ebea7e06b": "0xd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950fc36b10abae8cf4f626162658050412bd7d3f1075e8f8e3b682d05ea20b391c287d8c849a0e49a78f568553e69": "0x5270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950fcf43201be771ed27061726180d0d052eca7d732d9f560ba970ca48f67387b899e76958ea6ed342a3a553ef022": "0x0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f76108", + "0xcec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903": "0x38043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170d0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f761081e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c41332eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e11525270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c68728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c696ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a225962782c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b8689649037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af749492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20f94c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b10d0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327cd41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d", + "0xcec5070d609dd3497f72bde07fc96ba0e0cdd062e6eaf24295ad4ccfc41d4609": "0x38043393e76c137dfdc403a6fd9a2d6129d470d51c5a67bd40517378030c87170dc8caee6f6eddc41c6cc55e554343392cbc13d2a8a57b97f6f85fc965bdd20ce8b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a650edf2a41cb81178704560b02c35f5e01a5a97a568ebc10c025ade18b6ab2fa1d161d0af40e6efc165c17d0189bd2d770bdfa0a9b8393cb89113f473a2e948c68def964eed9a73f8a6610f1a0373378dca6f277eb7787869ed5841893105ad930f89c97bf5b2c07c05c84eebce4ffc7b28766946c03741fd1a71fdae0942e87680325fc2095902f5fe394f244bce38b0dc3d631cbc05f0b64d5620a71bbf2514f0f0efe248e3ddcfcb4f29675b70fc0a8e2db66b65381c45d299427b60d05f7610883f43ee3e4521b55de0fe830847fda88a6b017b87979af1a41b180c39da1e4b05440add43e5388a81aef665c9086d386c0be0ce75e4f8a4a3d8168e976ea821f98aab6f52520022d011a6eba2dca1c6327edbbcd753c170dcf0e9118b5f0f25bd0d052eca7d732d9f560ba970ca48f67387b899e76958ea6ed342a3a553ef0223e547f5cc3455a61d0404d7296ceec7375cbe20322109d118c5e725b1a5cbf04cce3ec06252cf7cdad47fe1265047a9bbddb9059ee4bdc6dec83b67249b4a93403f045328f504c13dac9ddd9b1186098aee7c46cb8d55289dbbf2433bab7a262391e30aa51ad68b8918d2c46e914986818c111bee03582610cbc9fb73fe0e4c4135fafb6219eb8d463bec0370b2aab69f45fc780959fc2eddbc7703760aa34202274dacbca0cdb5099afef67e622c147614198e669931cebc605629da332632473b414aa148096a92a1831309f758f944725653363ccbaeb21817b7df5784b8d46c45a6d0878f808b1baaa85dcfb4e930ae06e3205bb38855527aee6f259e3327b2e2f75472708a497d1743f52b04edf26c250d9e6d220f3bae3d176f02f8e586c2ada042fb4bbfd9b6d8c48293ffc4a7722632c843a67e608554c41d06aabc41303a0af06322d100056125fac1df39d161089b07ae279505aae8731c4d110a54ad732eebacd223f4aef33d98a667a68f9e371f40384257c6d31030952b9d94e11528270a62b61639ee56113834aecec01de6cda91413a5111b89f74d6585da34f5058108e1651614afc6a535c426fc013945e93533faa33819fe4e69423fe32330274bd654c470ed9b94972c1f997593fab7bdd4d6b85e3cf49401265668142584ead90a2c3fa2c756f974628dd279adb87935f7ea509856276e3b86f759b22451cc083b0d0bd7d6ffd14562b4c9e28738b087ccc32262170c633c18359ff84877992cb05c48fc643f057626c669604675c5ad5a836266f260ae7030c6fdc17a54303aec8e80ea0375f8669d6e55d7abb6a3117678d7bb851a1bd100a01e52a4fed905270ec35ba01254d8bff046a1a58f16d3ae615c235efd6e99a35f233b2d9df2c622c382187c0b2c61ecfb17443294d11a9d2ab770ae6f1fb49184a43906d59fe50412bd7d3f1075e8f8e3b682d05ea20b391c287d8c849a0e49a78f568553e6994848b8cf2cbc9e6fd72db8d80676591b5be4d1ec68972ada48cf6fd01228712303094c583e253794c9db14803585baaa74472f4ecba846defefc8aecfb6214ab400c4164d016282b202c1d42d9dc8ede28cbe4b751d463bab5f23fef42b295a8c15606f4c121376097ff0e96c2a33ea7b024d812b42fe2c741c8b8cee17e63d03d46c454f9b620603feef8c3a2a5d7098205b8566500fda0fa0b456d6ded5453868728d12a90fb1a9f5b0f0b2814d730401d314964113554e66ff19e7067d7c696e309dfa4c8de814cad140b8612a9e41bfba244f9ab1468e1b5d9b3cc1f5e565c44b3e8efe854419ccd5801a82ada22d39cfccdbcece382304cdfeac81ebe402a8a03d86e6c0dbe180cadfc7994121f462b28f7a8cb1be7e0e354147624be7340a988fb965b156a07debf072fd9d34a9c7c0fc0e0ff5bd63ef766afb76e2b3289ef622d2467ed115fa0c6c86303e1ef6a08a0609c97e616aa69b026a6d3f2663729053f28155071474b4686323db5f7a318cb3f088b76660cc8ff5e3e11ec32e030e901c390fa37d101ff25d70594acd2df67b4493ee77a73684f25d39313536d76ed774481ff68097867271bc8ecaeee3500817ccefdfda74ceeafd32a22596270509f9caf32fda5584343c473b386c433acb99fd9400724b8cf3c618d840133fb2efe7e70daf44b3466c63ccbf4487f42c6a9f6fbb7050b849691e36ce92e347bef47a9e4b47ed57461e1d28cac7da327a52ebcd64d74080d31deb3ac7a7645e4e1a59090261a7e6bd82544df1eebd96dc87b4eb1211346645fa44d6b932960be4ca45c68b0248885d190d22068c6628ee2f00d9fa0706d5a5c1c8456369f03eaa3955187f755708cd6a8104314b962ff5043e36efa3ec5d84df40c58b44222102f4f4d0eccb899bf2d611b56e0afec7c740efba404f8d0e82a545f988c45316c482c3105dbd4bb206428d8a8b7ea1f19965a0668dd583b06c3b75daa181fe654c4c669b04865e9acaf7b72bdfcb0099d70d9ec63c8c2d6b8cb0552815d7b50a0afacb2f987caac6c1290a9784b1efdba78343d39aed805addb12945efbe444000ca3c2703db1633a27eff681d979967988c3a6752c669fd41f1abde10f3b054462253ee3c02d89582602ca5b0570cfc01dc82cc8d1b9d2071eb5db6318749124bf0e6c42698fffc28f9fc769fddcdf165af54c171cde43690cc8f73c853de1f0426e2fc857945d01520797a75388c58e710c9fefedd28387af70880f1682be41e02182879ec92e811e2a8cc117f3cde1f61d3cba0093134cfb1ed17a4ef74915d4a8eef6710734f5d1e7d2eb303fa8f04e9bef65fb680647b24624723f95b868964e41426f7465c13c48335771c5450bf61c50a9cf28b9274f170c7421eea7974f168a9ec74fa35b3425eaf503dd36294ba8e758e7b8084c4d6bfd547f8c6b5827460fcc9d094d21fe17cfb7426501f50cb3d75c4c9395a3140e0f255443f660d3b9e065eea4143325fbbd26967c26a228d51a3a8384062f7434973f15d1da2c01068f7a83678a377701b46a5e6a4637e99868186ff4835fc0e3914cc56a76a360164ffc83f4f86cc595e607a00b977eeb6641e02a4e6e556c24ab163aecd7d146c03e843f200e30bc5b951c73a96d968db1c0cd05e357d910fce159fc59c40e9d6e29037d1020ed699c2f538d3ffcf0eb98087ee11ca4bd07bfddb0d68633806af74ace46e899b90e75199549d8fa2ae7097e896ab3c845217e3155f99b6ffb888037c8348ec95a0faad6a638ef74864761028c53221bde07e9ff7c81a3f427abf3f30c40adee5476157ef3c2a26e10cab95ec7d54b62dd220738f5a474d5f86874e0ce84accce1ced0de223aa72f760f1b3d13ddfd267938cd63e25308378d32008eed33645cda7812cd343bbaef9131b2794812f2fd37701ccb6cddf9c1e293d387aeb767131602e6612e607a9eb8e26b4ce4fa4765593d032bc923ce8acadda420203d51bba2124f480e3507eb1764fc3019ac7abae8ee215683a285078bda7f51d9492b8c38442c79061bdbb8d38dcd28138938a7fd476edf89ecdec06a5a9d20fc9a68a26e9aa37ba6334f1a20275e3be7d3a9d4aa988627eadac8ea0d0a2dfbfae240842b74e5dd778972e451558134f434c7a1d8a52bc70519f38054e24553306bd8fd81e50cda2bd67bf6893d921d1aae5cb08409ae43e0bff4d54e1830e58ea9400f05e7fb75a3f7a92febbf58e5a3060dd06132ed6d5d68a3d75ec452826bed3b452f869d187be58a4ba98588611084283810728fa75981e792beaec4151763d070989ead31f265b40cc7a0cd29d47799b766d6a7f084e44c82baedfc01e029338ece1c6bc6439dc4d16bfe33f28c9f0af31626bb8142849742b7a624f680794c4156ed6a101ae478a3de3ba70a05fce8a3d67be6fb85f33bfcf2777ab6b106e60f1e253735fb113c183fa603f591e4456435171f387c0849001b428b5ccb118bd0f67d77f04f1a92400421813d8927fad109b40a8689254a5f0c8b346857cd28145a7cde195a4c834276730d30f074b212a150e770931ee9470e853e7d22402683131f96baec9121383995904c49a02ce2c2451f8038291e5db2dce66663e92ac14f8ad1811cc83861afadf12f3191cca1391f1f3af705977faa2fa2bf46a629f9fd0dd7279c7af7470472d1208a13e33239b484974d47cffce4ad47856440333022898140662dfea847e3cbfe5e989845ac6766e83472f8b0c650d85e77baed0b4896a63b672a7a74f5234bf9ec8567ff3c5bb8f93795e15e2c498b48d327cc8de3a01502422b59dfa601c9c3a04a98d2bfbd79dd0810d1d1250feab4241ee6248d87bd2a640ffe26d6b831735887c24e2076a3a0f3a74f7ae7568c27604087c03ca47a3201455f8f89defda4aa909cb1d25dd9ddb7fd62a940606f79b566390032c39c968f486f77f8764301a8479206f063d49eeb9f6d499333e2a1be045165f3b255dc17054e6d4447c4005f689eb5ed2f99fe201f4ff799bf088495850047277f22b9ef92a8b99618f4c86c2412f0e3b08a4f965f842775672043d1e2503586dafcdab3d4647d4dc68732a9cab8aa34c00c5edd04e65d9dd44c2a1fd21e2d41a8a9678862ebe9d1a1d59cac1c8430ef31e282f9cb391cf6f2b4d9ce2fd3d64adb43a7628139f6c02100f6a5465dbd33422418426c572b12547c5a665008c1ab03b1b3277edfedd24ef3d3359b449b64bd95ed82a04e7f9fbaab7b71dc0152cd12c731d91441f0114b08d314cd3f9a9f7fd0240d467fe54adefbee4d90762441629077e228528f91ca7dc17051bb437408a5ae272d0950e58961846a8fc2ec22ce14ba0e59aa974d4a05c9208ba5ae18674c6a23c9998d91e7d1ebea7e06b9a86227e204a2d003399c2a3b50c2c869c4380c195a014a02f6d2e7048941237029a1eb2e31dcaf468dbb516f9b620fdd7c3f090d58a88e02b51b25255b2182dd1", "0xd57bce545fb382c34570e5dfbf338f5e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", "0xd5c41b52a371aa36c9254ce34324f2a54e7b9012096b41c4eb3aaf947f6ea429": "0x0100", "0xd5e1a2fa16732ce6906189438c0a82c64e7b9012096b41c4eb3aaf947f6ea429": "0x0000", @@ -226,4 +419,4 @@ "childrenDefault": {} } } -} +} \ No newline at end of file -- GitLab From 7099f6e1b1fa3c8cd894693902263d9ed0e38978 Mon Sep 17 00:00:00 2001 From: gupnik Date: Fri, 15 Mar 2024 13:16:09 +0530 Subject: [PATCH 123/188] Removes `as [disambiguation_path]` from `derive_impl` usage (#3652) Step in https://github.com/paritytech/polkadot-sdk/issues/171 This PR removes `as [disambiguation_path]` syntax from `derive_impl` usage across the polkadot-sdk as introduced in https://github.com/paritytech/polkadot-sdk/pull/3505 --- bridges/bin/runtime-common/src/mock.rs | 5 +++-- bridges/modules/grandpa/src/mock.rs | 2 +- bridges/modules/messages/src/mock.rs | 4 ++-- bridges/modules/parachains/src/mock.rs | 2 +- bridges/modules/relayers/src/mock.rs | 4 ++-- bridges/modules/xcm-bridge-hub-router/src/mock.rs | 2 +- bridges/modules/xcm-bridge-hub/src/mock.rs | 4 ++-- bridges/snowbridge/pallets/ethereum-client/src/mock.rs | 2 +- bridges/snowbridge/pallets/inbound-queue/src/mock.rs | 2 +- bridges/snowbridge/pallets/outbound-queue/src/mock.rs | 2 +- bridges/snowbridge/pallets/system/src/mock.rs | 2 +- .../pallets/ethereum-beacon-client/src/mock.rs | 4 ++-- cumulus/pallets/collator-selection/src/mock.rs | 2 +- cumulus/pallets/dmp-queue/src/mock.rs | 2 +- cumulus/pallets/parachain-system/src/mock.rs | 2 +- cumulus/pallets/xcmp-queue/src/mock.rs | 2 +- cumulus/parachains/common/src/impls.rs | 2 +- .../parachains/pallets/collective-content/src/mock.rs | 2 +- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 2 +- .../runtimes/assets/asset-hub-westend/src/lib.rs | 2 +- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 2 +- .../runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs | 2 +- .../collectives/collectives-westend/src/lib.rs | 2 +- .../runtimes/contracts/contracts-rococo/src/lib.rs | 2 +- .../runtimes/coretime/coretime-rococo/src/lib.rs | 2 +- .../runtimes/coretime/coretime-westend/src/lib.rs | 2 +- .../runtimes/glutton/glutton-westend/src/lib.rs | 2 +- .../runtimes/people/people-rococo/src/lib.rs | 2 +- .../runtimes/people/people-westend/src/lib.rs | 2 +- .../parachains/runtimes/starters/seedling/src/lib.rs | 2 +- cumulus/parachains/runtimes/starters/shell/src/lib.rs | 2 +- cumulus/parachains/runtimes/testing/penpal/src/lib.rs | 2 +- .../runtimes/testing/rococo-parachain/src/lib.rs | 2 +- cumulus/test/runtime/src/lib.rs | 2 +- docs/sdk/src/guides/your_first_pallet/mod.rs | 4 ++-- docs/sdk/src/polkadot_sdk/cumulus.rs | 4 ++-- docs/sdk/src/polkadot_sdk/frame_runtime.rs | 2 +- docs/sdk/src/reference_docs/frame_origin.rs | 4 ++-- docs/sdk/src/reference_docs/frame_pallet_coupling.rs | 2 +- docs/sdk/src/reference_docs/frame_runtime_types.rs | 4 ++-- polkadot/runtime/common/src/assigned_slots/mod.rs | 2 +- polkadot/runtime/common/src/auctions.rs | 2 +- polkadot/runtime/common/src/claims.rs | 2 +- polkadot/runtime/common/src/crowdloan/mod.rs | 2 +- polkadot/runtime/common/src/impls.rs | 2 +- polkadot/runtime/common/src/integration_tests.rs | 2 +- polkadot/runtime/common/src/paras_registrar/mod.rs | 2 +- polkadot/runtime/common/src/purchase.rs | 2 +- polkadot/runtime/common/src/slots/mod.rs | 2 +- polkadot/runtime/parachains/src/mock.rs | 2 +- polkadot/runtime/rococo/src/lib.rs | 2 +- polkadot/runtime/test-runtime/src/lib.rs | 2 +- polkadot/runtime/westend/src/lib.rs | 2 +- .../xcm/pallet-xcm-benchmarks/src/fungible/mock.rs | 4 ++-- polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs | 4 ++-- polkadot/xcm/pallet-xcm/src/mock.rs | 2 +- polkadot/xcm/xcm-builder/src/tests/pay/mock.rs | 2 +- polkadot/xcm/xcm-builder/tests/mock/mod.rs | 2 +- polkadot/xcm/xcm-simulator/example/src/parachain.rs | 2 +- polkadot/xcm/xcm-simulator/example/src/relay_chain.rs | 2 +- polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs | 2 +- polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs | 2 +- prdoc/pr_3505.prdoc | 2 +- substrate/bin/node/runtime/src/lib.rs | 2 +- substrate/frame/alliance/src/mock.rs | 2 +- substrate/frame/asset-conversion/src/mock.rs | 2 +- substrate/frame/asset-rate/src/mock.rs | 2 +- substrate/frame/assets/src/lib.rs | 2 +- substrate/frame/assets/src/mock.rs | 2 +- substrate/frame/atomic-swap/src/tests.rs | 2 +- substrate/frame/aura/src/mock.rs | 2 +- substrate/frame/authority-discovery/src/lib.rs | 2 +- substrate/frame/authorship/src/lib.rs | 2 +- substrate/frame/babe/src/mock.rs | 2 +- substrate/frame/bags-list/src/mock.rs | 2 +- substrate/frame/balances/src/lib.rs | 2 +- substrate/frame/balances/src/tests/mod.rs | 3 ++- substrate/frame/beefy-mmr/src/mock.rs | 2 +- substrate/frame/beefy/src/mock.rs | 2 +- substrate/frame/benchmarking/pov/src/benchmarking.rs | 2 +- substrate/frame/benchmarking/pov/src/tests.rs | 2 +- substrate/frame/benchmarking/src/baseline.rs | 2 +- substrate/frame/benchmarking/src/tests.rs | 2 +- substrate/frame/benchmarking/src/tests_instance.rs | 2 +- substrate/frame/bounties/src/tests.rs | 2 +- substrate/frame/broker/src/mock.rs | 2 +- substrate/frame/child-bounties/src/tests.rs | 2 +- substrate/frame/collective/src/tests.rs | 2 +- .../frame/contracts/mock-network/src/parachain.rs | 2 +- .../frame/contracts/mock-network/src/relay_chain.rs | 2 +- substrate/frame/contracts/src/tests.rs | 2 +- substrate/frame/conviction-voting/src/tests.rs | 2 +- .../frame/core-fellowship/src/tests/integration.rs | 2 +- substrate/frame/core-fellowship/src/tests/unit.rs | 2 +- substrate/frame/democracy/src/tests.rs | 2 +- .../frame/election-provider-multi-phase/src/mock.rs | 2 +- .../test-staking-e2e/src/mock.rs | 2 +- .../frame/election-provider-support/src/onchain.rs | 2 +- substrate/frame/elections-phragmen/src/lib.rs | 2 +- substrate/frame/examples/basic/src/tests.rs | 2 +- substrate/frame/examples/default-config/src/lib.rs | 5 ++--- substrate/frame/examples/dev-mode/src/tests.rs | 2 +- substrate/frame/examples/frame-crate/src/lib.rs | 2 +- substrate/frame/examples/kitchensink/src/tests.rs | 2 +- substrate/frame/examples/offchain-worker/src/tests.rs | 2 +- .../frame/examples/single-block-migrations/src/mock.rs | 2 +- substrate/frame/examples/split/src/mock.rs | 2 +- substrate/frame/examples/tasks/src/mock.rs | 2 +- substrate/frame/executive/src/tests.rs | 4 ++-- substrate/frame/fast-unstake/src/mock.rs | 2 +- substrate/frame/glutton/src/mock.rs | 2 +- substrate/frame/grandpa/src/mock.rs | 2 +- substrate/frame/identity/src/tests.rs | 2 +- substrate/frame/im-online/src/mock.rs | 2 +- substrate/frame/indices/src/mock.rs | 2 +- .../insecure-randomness-collective-flip/src/lib.rs | 2 +- substrate/frame/lottery/src/mock.rs | 2 +- substrate/frame/membership/src/lib.rs | 2 +- substrate/frame/merkle-mountain-range/src/mock.rs | 2 +- substrate/frame/message-queue/src/integration_test.rs | 2 +- substrate/frame/message-queue/src/mock.rs | 2 +- substrate/frame/migrations/src/mock.rs | 2 +- substrate/frame/multisig/src/tests.rs | 4 ++-- substrate/frame/nft-fractionalization/src/mock.rs | 2 +- substrate/frame/nfts/src/mock.rs | 2 +- substrate/frame/nis/src/mock.rs | 2 +- substrate/frame/node-authorization/src/mock.rs | 2 +- .../frame/nomination-pools/benchmarking/src/mock.rs | 2 +- substrate/frame/nomination-pools/src/mock.rs | 2 +- .../frame/nomination-pools/test-staking/src/mock.rs | 2 +- substrate/frame/offences/benchmarking/src/mock.rs | 2 +- substrate/frame/offences/src/mock.rs | 2 +- substrate/frame/paged-list/src/mock.rs | 2 +- substrate/frame/parameters/src/lib.rs | 2 +- substrate/frame/parameters/src/tests/mock.rs | 6 +++--- substrate/frame/parameters/src/tests/test_renamed.rs | 6 +++--- substrate/frame/preimage/src/mock.rs | 2 +- substrate/frame/proxy/src/tests.rs | 4 ++-- substrate/frame/ranked-collective/src/tests.rs | 2 +- substrate/frame/recovery/src/mock.rs | 2 +- substrate/frame/referenda/src/mock.rs | 2 +- substrate/frame/remark/src/mock.rs | 2 +- substrate/frame/root-offences/src/mock.rs | 2 +- substrate/frame/safe-mode/src/mock.rs | 2 +- substrate/frame/salary/src/tests/integration.rs | 2 +- substrate/frame/salary/src/tests/unit.rs | 2 +- substrate/frame/sassafras/src/mock.rs | 2 +- substrate/frame/scheduler/src/mock.rs | 2 +- substrate/frame/scored-pool/src/mock.rs | 2 +- substrate/frame/session/benchmarking/src/mock.rs | 2 +- substrate/frame/session/src/mock.rs | 2 +- substrate/frame/society/src/mock.rs | 4 ++-- substrate/frame/staking/src/mock.rs | 2 +- substrate/frame/state-trie-migration/src/lib.rs | 8 ++++---- substrate/frame/statement/src/mock.rs | 2 +- substrate/frame/sudo/src/lib.rs | 2 +- substrate/frame/sudo/src/mock.rs | 2 +- substrate/frame/support/src/lib.rs | 2 +- substrate/frame/support/src/tests/mod.rs | 2 +- substrate/frame/support/test/compile_pass/src/lib.rs | 2 +- .../frame/support/test/stg_frame_crate/src/lib.rs | 2 +- substrate/frame/support/test/tests/composite_enum.rs | 2 +- .../number_of_pallets_exceeds_tuple_size.rs | 2 +- .../construct_runtime_ui/pallet_error_too_large.rs | 2 +- .../pass/composite_enum_instance.rs | 2 +- .../tests/construct_runtime_ui/undefined_call_part.rs | 2 +- .../tests/construct_runtime_ui/undefined_event_part.rs | 2 +- .../undefined_genesis_config_part.rs | 2 +- .../construct_runtime_ui/undefined_inherent_part.rs | 2 +- .../construct_runtime_ui/undefined_origin_part.rs | 2 +- .../undefined_validate_unsigned_part.rs | 2 +- substrate/frame/support/test/tests/final_keys.rs | 2 +- substrate/frame/support/test/tests/genesisconfig.rs | 2 +- substrate/frame/support/test/tests/instance.rs | 2 +- substrate/frame/support/test/tests/issue2219.rs | 2 +- substrate/frame/support/test/tests/origin.rs | 2 +- substrate/frame/support/test/tests/pallet.rs | 2 +- substrate/frame/support/test/tests/pallet_instance.rs | 2 +- .../support/test/tests/pallet_outer_enums_explicit.rs | 2 +- .../support/test/tests/pallet_outer_enums_implicit.rs | 2 +- .../test/tests/pallet_ui/pass/dev_mode_valid.rs | 2 +- .../test/tests/pallet_ui/pass/no_std_genesis_config.rs | 2 +- substrate/frame/support/test/tests/runtime.rs | 2 +- substrate/frame/support/test/tests/runtime_metadata.rs | 2 +- substrate/frame/support/test/tests/storage_layers.rs | 2 +- .../frame/support/test/tests/storage_transaction.rs | 2 +- .../frame/support/test/tests/versioned_migration.rs | 2 +- substrate/frame/system/benches/bench.rs | 2 +- substrate/frame/system/benchmarking/src/mock.rs | 2 +- substrate/frame/system/src/mock.rs | 2 +- substrate/frame/timestamp/src/lib.rs | 2 +- substrate/frame/timestamp/src/mock.rs | 2 +- substrate/frame/tips/src/tests.rs | 2 +- .../asset-conversion-tx-payment/src/mock.rs | 3 ++- .../transaction-payment/asset-tx-payment/src/mock.rs | 3 ++- .../skip-feeless-payment/src/mock.rs | 2 +- substrate/frame/transaction-payment/src/lib.rs | 2 +- substrate/frame/transaction-payment/src/mock.rs | 2 +- substrate/frame/transaction-storage/src/mock.rs | 4 ++-- substrate/frame/treasury/src/tests.rs | 2 +- substrate/frame/tx-pause/src/mock.rs | 2 +- substrate/frame/uniques/src/mock.rs | 2 +- substrate/frame/utility/src/tests.rs | 2 +- substrate/frame/vesting/src/mock.rs | 2 +- substrate/frame/whitelist/src/mock.rs | 2 +- substrate/test-utils/runtime/src/lib.rs | 2 +- substrate/utils/frame/rpc/support/src/lib.rs | 2 +- templates/minimal/runtime/src/lib.rs | 10 +++++----- templates/parachain/pallets/template/src/mock.rs | 2 +- templates/parachain/runtime/src/lib.rs | 2 +- templates/solochain/pallets/template/src/mock.rs | 2 +- templates/solochain/runtime/src/lib.rs | 2 +- 212 files changed, 244 insertions(+), 241 deletions(-) diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs index 8877a4fd95c..deee4524e85 100644 --- a/bridges/bin/runtime-common/src/mock.rs +++ b/bridges/bin/runtime-common/src/mock.rs @@ -141,7 +141,7 @@ parameter_types! { pub const ReserveId: [u8; 8] = *b"brdgrlrs"; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Hash = ThisChainHash; type Hashing = ThisChainHasher; @@ -158,12 +158,13 @@ impl pallet_utility::Config for TestRuntime { type WeightInfo = (); } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for TestRuntime { type ReserveIdentifier = [u8; 8]; type AccountStore = System; } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)] impl pallet_transaction_payment::Config for TestRuntime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; diff --git a/bridges/modules/grandpa/src/mock.rs b/bridges/modules/grandpa/src/mock.rs index e41e89341b3..4318d663a2e 100644 --- a/bridges/modules/grandpa/src/mock.rs +++ b/bridges/modules/grandpa/src/mock.rs @@ -42,7 +42,7 @@ construct_runtime! { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; } diff --git a/bridges/modules/messages/src/mock.rs b/bridges/modules/messages/src/mock.rs index af921205398..ec63f15b94b 100644 --- a/bridges/modules/messages/src/mock.rs +++ b/bridges/modules/messages/src/mock.rs @@ -77,14 +77,14 @@ frame_support::construct_runtime! { pub type DbWeight = RocksDbWeight; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; type AccountData = pallet_balances::AccountData; type DbWeight = DbWeight; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for TestRuntime { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/bridges/modules/parachains/src/mock.rs b/bridges/modules/parachains/src/mock.rs index 143f11d9863..3af3fd3e763 100644 --- a/bridges/modules/parachains/src/mock.rs +++ b/bridges/modules/parachains/src/mock.rs @@ -161,7 +161,7 @@ construct_runtime! { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; } diff --git a/bridges/modules/relayers/src/mock.rs b/bridges/modules/relayers/src/mock.rs index 667b10e5c12..3124787896c 100644 --- a/bridges/modules/relayers/src/mock.rs +++ b/bridges/modules/relayers/src/mock.rs @@ -59,14 +59,14 @@ parameter_types! { pub const Lease: BlockNumber = 8; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; type AccountData = pallet_balances::AccountData; type DbWeight = DbWeight; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for TestRuntime { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/bridges/modules/xcm-bridge-hub-router/src/mock.rs b/bridges/modules/xcm-bridge-hub-router/src/mock.rs index 6dbfba5f6fd..54e10966d51 100644 --- a/bridges/modules/xcm-bridge-hub-router/src/mock.rs +++ b/bridges/modules/xcm-bridge-hub-router/src/mock.rs @@ -64,7 +64,7 @@ parameter_types! { pub UnknownXcmVersionLocation: Location = Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Parachain(9999)]); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; } diff --git a/bridges/modules/xcm-bridge-hub/src/mock.rs b/bridges/modules/xcm-bridge-hub/src/mock.rs index e40e1f9fb65..4c09bce56d7 100644 --- a/bridges/modules/xcm-bridge-hub/src/mock.rs +++ b/bridges/modules/xcm-bridge-hub/src/mock.rs @@ -64,7 +64,7 @@ parameter_types! { pub const ExistentialDeposit: Balance = 1; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type AccountId = AccountId; type AccountData = pallet_balances::AccountData; @@ -72,7 +72,7 @@ impl frame_system::Config for TestRuntime { type Lookup = IdentityLookup; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for TestRuntime { type AccountStore = System; } diff --git a/bridges/snowbridge/pallets/ethereum-client/src/mock.rs b/bridges/snowbridge/pallets/ethereum-client/src/mock.rs index 3ce34eee191..799b14f4773 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/mock.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/mock.rs @@ -95,7 +95,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/bridges/snowbridge/pallets/inbound-queue/src/mock.rs b/bridges/snowbridge/pallets/inbound-queue/src/mock.rs index 749fb0367f3..086b27cb828 100644 --- a/bridges/snowbridge/pallets/inbound-queue/src/mock.rs +++ b/bridges/snowbridge/pallets/inbound-queue/src/mock.rs @@ -47,7 +47,7 @@ parameter_types! { type Balance = u128; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/bridges/snowbridge/pallets/outbound-queue/src/mock.rs b/bridges/snowbridge/pallets/outbound-queue/src/mock.rs index 6e78fb44672..850b13dcf31 100644 --- a/bridges/snowbridge/pallets/outbound-queue/src/mock.rs +++ b/bridges/snowbridge/pallets/outbound-queue/src/mock.rs @@ -37,7 +37,7 @@ parameter_types! { pub const BlockHashCount: u64 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/bridges/snowbridge/pallets/system/src/mock.rs b/bridges/snowbridge/pallets/system/src/mock.rs index de2970dd550..a711eab5d3d 100644 --- a/bridges/snowbridge/pallets/system/src/mock.rs +++ b/bridges/snowbridge/pallets/system/src/mock.rs @@ -95,7 +95,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs b/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs index 77b5c1aa631..d2cca373e92 100644 --- a/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs +++ b/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs @@ -34,7 +34,7 @@ pub mod minimal { pub const SS58Prefix: u8 = 42; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; @@ -195,7 +195,7 @@ pub mod mainnet { pub const SS58Prefix: u8 = 42; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/cumulus/pallets/collator-selection/src/mock.rs b/cumulus/pallets/collator-selection/src/mock.rs index fe41e7318bc..061d8b1cb31 100644 --- a/cumulus/pallets/collator-selection/src/mock.rs +++ b/cumulus/pallets/collator-selection/src/mock.rs @@ -50,7 +50,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/cumulus/pallets/dmp-queue/src/mock.rs b/cumulus/pallets/dmp-queue/src/mock.rs index 6bd74a047eb..ed72ce678e3 100644 --- a/cumulus/pallets/dmp-queue/src/mock.rs +++ b/cumulus/pallets/dmp-queue/src/mock.rs @@ -35,7 +35,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; type RuntimeOrigin = RuntimeOrigin; diff --git a/cumulus/pallets/parachain-system/src/mock.rs b/cumulus/pallets/parachain-system/src/mock.rs index b76553a5384..0b1d536ba7c 100644 --- a/cumulus/pallets/parachain-system/src/mock.rs +++ b/cumulus/pallets/parachain-system/src/mock.rs @@ -71,7 +71,7 @@ parameter_types! { pub const ReservedDmpWeight: Weight = Weight::zero(); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type BlockHashCount = BlockHashCount; diff --git a/cumulus/pallets/xcmp-queue/src/mock.rs b/cumulus/pallets/xcmp-queue/src/mock.rs index 1fb88cafd93..294f978f6ad 100644 --- a/cumulus/pallets/xcmp-queue/src/mock.rs +++ b/cumulus/pallets/xcmp-queue/src/mock.rs @@ -58,7 +58,7 @@ parameter_types! { type AccountId = u64; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = Everything; type BlockWeights = (); diff --git a/cumulus/parachains/common/src/impls.rs b/cumulus/parachains/common/src/impls.rs index 957538b7cda..6a990740f0f 100644 --- a/cumulus/parachains/common/src/impls.rs +++ b/cumulus/parachains/common/src/impls.rs @@ -217,7 +217,7 @@ mod tests { pub const MaxReserves: u32 = 50; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/cumulus/parachains/pallets/collective-content/src/mock.rs b/cumulus/parachains/pallets/collective-content/src/mock.rs index 7a752da71fc..5cb0126425e 100644 --- a/cumulus/parachains/pallets/collective-content/src/mock.rs +++ b/cumulus/parachains/pallets/collective-content/src/mock.rs @@ -55,7 +55,7 @@ impl pallet_collective_content::Config for Test { type WeightInfo = CCWeightInfo; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = (); type BlockWeights = (); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 17a12dd2f6f..7da9869dd2c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -165,7 +165,7 @@ parameter_types! { } // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 1ead2897855..3d69e104bd5 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -149,7 +149,7 @@ parameter_types! { } // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 0b48d1717fa..843acffe03e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -242,7 +242,7 @@ parameter_types! { // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index e1344fce63d..d70d880c50c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -216,7 +216,7 @@ parameter_types! { // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 6bcf98c428f..15a2391fa5b 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -161,7 +161,7 @@ parameter_types! { } // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 0668b9a4c7d..928c3ecc532 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -171,7 +171,7 @@ parameter_types! { } // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index cdff371c505..41b9ffa0af8 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -172,7 +172,7 @@ parameter_types! { } // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 7fa70647992..d93c2a61ff4 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -172,7 +172,7 @@ parameter_types! { } // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index 232a82115a8..6967ac58e3b 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -146,7 +146,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { type AccountId = AccountId; type Nonce = Nonce; diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 2b8cc32f67c..05da00ac555 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -164,7 +164,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = Everything; type BlockWeights = RuntimeBlockWeights; diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 2dc2d06a66b..e921df1e5da 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -164,7 +164,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = Everything; type BlockWeights = RuntimeBlockWeights; diff --git a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs index 4cc0a81ef49..179bda356ae 100644 --- a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs @@ -135,7 +135,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/cumulus/parachains/runtimes/starters/shell/src/lib.rs b/cumulus/parachains/runtimes/starters/shell/src/lib.rs index 829754731a4..c0904f0faef 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/lib.rs @@ -143,7 +143,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index bea78e14520..24a325c6f5b 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -326,7 +326,7 @@ parameter_types! { // Configure FRAME pallets to include in runtime. -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 2b21a12c3ca..aea139fb66e 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -185,7 +185,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index 5ccec8983e9..8e3569b02a1 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -177,7 +177,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/docs/sdk/src/guides/your_first_pallet/mod.rs b/docs/sdk/src/guides/your_first_pallet/mod.rs index 6a262924824..c633c0a69ed 100644 --- a/docs/sdk/src/guides/your_first_pallet/mod.rs +++ b/docs/sdk/src/guides/your_first_pallet/mod.rs @@ -438,7 +438,7 @@ pub mod pallet { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; // within pallet we just said `::AccountId`, now we @@ -717,7 +717,7 @@ pub mod pallet_v2 { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; type AccountId = u64; diff --git a/docs/sdk/src/polkadot_sdk/cumulus.rs b/docs/sdk/src/polkadot_sdk/cumulus.rs index 60c4839f9e2..7d9daf9067c 100644 --- a/docs/sdk/src/polkadot_sdk/cumulus.rs +++ b/docs/sdk/src/polkadot_sdk/cumulus.rs @@ -72,7 +72,7 @@ mod tests { mod system_pallets { use super::*; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; @@ -115,7 +115,7 @@ mod tests { } #[docify::export(timestamp)] - #[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig as pallet_timestamp::DefaultConfig)] + #[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig)] impl pallet_timestamp::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} diff --git a/docs/sdk/src/polkadot_sdk/frame_runtime.rs b/docs/sdk/src/polkadot_sdk/frame_runtime.rs index f178fc82bf4..f9b8a381365 100644 --- a/docs/sdk/src/polkadot_sdk/frame_runtime.rs +++ b/docs/sdk/src/polkadot_sdk/frame_runtime.rs @@ -162,7 +162,7 @@ pub mod runtime { ); // These `impl` blocks specify the parameters of each pallet's `trait Config`. - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; } diff --git a/docs/sdk/src/reference_docs/frame_origin.rs b/docs/sdk/src/reference_docs/frame_origin.rs index 49533157b01..a2aac7dd355 100644 --- a/docs/sdk/src/reference_docs/frame_origin.rs +++ b/docs/sdk/src/reference_docs/frame_origin.rs @@ -205,7 +205,7 @@ pub mod runtime_for_origin { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; } @@ -248,7 +248,7 @@ pub mod runtime_for_external_origin { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; } diff --git a/docs/sdk/src/reference_docs/frame_pallet_coupling.rs b/docs/sdk/src/reference_docs/frame_pallet_coupling.rs index 942717ecfb2..cca7f9feb3f 100644 --- a/docs/sdk/src/reference_docs/frame_pallet_coupling.rs +++ b/docs/sdk/src/reference_docs/frame_pallet_coupling.rs @@ -280,7 +280,7 @@ pub mod runtime { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; } diff --git a/docs/sdk/src/reference_docs/frame_runtime_types.rs b/docs/sdk/src/reference_docs/frame_runtime_types.rs index b5838b79e51..32cda5bc534 100644 --- a/docs/sdk/src/reference_docs/frame_runtime_types.rs +++ b/docs/sdk/src/reference_docs/frame_runtime_types.rs @@ -228,7 +228,7 @@ pub mod runtime { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; } @@ -293,7 +293,7 @@ pub mod runtime_with_specific_runtime_call { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; } diff --git a/polkadot/runtime/common/src/assigned_slots/mod.rs b/polkadot/runtime/common/src/assigned_slots/mod.rs index 4f032f4dfa3..5f1bc73db96 100644 --- a/polkadot/runtime/common/src/assigned_slots/mod.rs +++ b/polkadot/runtime/common/src/assigned_slots/mod.rs @@ -680,7 +680,7 @@ mod tests { pub const BlockHashCount: u32 = 250; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/polkadot/runtime/common/src/auctions.rs b/polkadot/runtime/common/src/auctions.rs index 46ab673a7a0..6914fef99d5 100644 --- a/polkadot/runtime/common/src/auctions.rs +++ b/polkadot/runtime/common/src/auctions.rs @@ -707,7 +707,7 @@ mod tests { pub const BlockHashCount: u32 = 250; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/polkadot/runtime/common/src/claims.rs b/polkadot/runtime/common/src/claims.rs index 68f42914e44..49ac4eb8941 100644 --- a/polkadot/runtime/common/src/claims.rs +++ b/polkadot/runtime/common/src/claims.rs @@ -730,7 +730,7 @@ mod tests { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; diff --git a/polkadot/runtime/common/src/crowdloan/mod.rs b/polkadot/runtime/common/src/crowdloan/mod.rs index 35d075f2ff6..6543bf305c4 100644 --- a/polkadot/runtime/common/src/crowdloan/mod.rs +++ b/polkadot/runtime/common/src/crowdloan/mod.rs @@ -900,7 +900,7 @@ mod tests { type BlockNumber = u64; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/polkadot/runtime/common/src/impls.rs b/polkadot/runtime/common/src/impls.rs index 4ba85a3c835..acf5a701a62 100644 --- a/polkadot/runtime/common/src/impls.rs +++ b/polkadot/runtime/common/src/impls.rs @@ -264,7 +264,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/polkadot/runtime/common/src/integration_tests.rs b/polkadot/runtime/common/src/integration_tests.rs index 3aa291f0f1f..dfd0d356638 100644 --- a/polkadot/runtime/common/src/integration_tests.rs +++ b/polkadot/runtime/common/src/integration_tests.rs @@ -115,7 +115,7 @@ parameter_types! { ); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = BlockWeights; diff --git a/polkadot/runtime/common/src/paras_registrar/mod.rs b/polkadot/runtime/common/src/paras_registrar/mod.rs index 4541b88ec6f..5b2098388d8 100644 --- a/polkadot/runtime/common/src/paras_registrar/mod.rs +++ b/polkadot/runtime/common/src/paras_registrar/mod.rs @@ -757,7 +757,7 @@ mod tests { limits::BlockLength::max_with_normal_ratio(4 * 1024 * 1024, NORMAL_RATIO); } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/polkadot/runtime/common/src/purchase.rs b/polkadot/runtime/common/src/purchase.rs index 301f1f21fbc..8de93bd68b0 100644 --- a/polkadot/runtime/common/src/purchase.rs +++ b/polkadot/runtime/common/src/purchase.rs @@ -512,7 +512,7 @@ mod tests { pub const BlockHashCount: u32 = 250; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/polkadot/runtime/common/src/slots/mod.rs b/polkadot/runtime/common/src/slots/mod.rs index 51bd0ba4deb..a54aaa53f8c 100644 --- a/polkadot/runtime/common/src/slots/mod.rs +++ b/polkadot/runtime/common/src/slots/mod.rs @@ -530,7 +530,7 @@ mod tests { pub const BlockHashCount: u32 = 250; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/polkadot/runtime/parachains/src/mock.rs b/polkadot/runtime/parachains/src/mock.rs index e18be03bdeb..7ed62a392e4 100644 --- a/polkadot/runtime/parachains/src/mock.rs +++ b/polkadot/runtime/parachains/src/mock.rs @@ -103,7 +103,7 @@ parameter_types! { pub type AccountId = u64; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = BlockWeights; diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 96e8c4e0979..1f51258df08 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -185,7 +185,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::RelayChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::RelayChainDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = EverythingBut; type BlockWeights = BlockWeights; diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index 6c899c52701..8a3cd9309db 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -139,7 +139,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::RelayChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::RelayChainDefaultConfig)] impl frame_system::Config for Runtime { type BlockWeights = BlockWeights; type BlockLength = BlockLength; diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index b55d68ee0f6..15d78706d3a 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -186,7 +186,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::RelayChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::RelayChainDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = EverythingBut; type BlockWeights = BlockWeights; diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs index 637446832fd..c75ecbceb08 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs @@ -46,7 +46,7 @@ parameter_types! { frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1024, u64::MAX)); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = Everything; type BlockWeights = (); @@ -77,7 +77,7 @@ parameter_types! { pub const ExistentialDeposit: u64 = 7; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs index c84f062a8d1..b037d3dd8b2 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs @@ -51,7 +51,7 @@ parameter_types! { frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1024, u64::MAX)); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = Everything; type BlockWeights = (); @@ -141,7 +141,7 @@ parameter_types! { pub const ExistentialDeposit: u64 = 7; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index d5ba7312a3a..77b30b1eaa1 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -241,7 +241,7 @@ parameter_types! { pub const BlockHashCount: u64 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 9892c500f2e..9feda8fb90b 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -49,7 +49,7 @@ construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/polkadot/xcm/xcm-builder/tests/mock/mod.rs b/polkadot/xcm/xcm-builder/tests/mock/mod.rs index 06cedb9c357..536f8851bb4 100644 --- a/polkadot/xcm/xcm-builder/tests/mock/mod.rs +++ b/polkadot/xcm/xcm-builder/tests/mock/mod.rs @@ -76,7 +76,7 @@ parameter_types! { pub const BlockHashCount: u64 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain.rs b/polkadot/xcm/xcm-simulator/example/src/parachain.rs index 64333b4d581..50a12a3a698 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain.rs @@ -63,7 +63,7 @@ parameter_types! { pub const BlockHashCount: u64 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; diff --git a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs index 54c5657c00d..f41e273839b 100644 --- a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs @@ -49,7 +49,7 @@ parameter_types! { pub const BlockHashCount: u64 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index a20390b64f9..1130701a344 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -63,7 +63,7 @@ parameter_types! { pub const BlockHashCount: u32 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type AccountId = AccountId; type Lookup = AccountIdLookup; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index 5bf65fa9f9a..42dd8237cbf 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -62,7 +62,7 @@ parameter_types! { pub const BlockHashCount: u32 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type AccountId = AccountId; type Lookup = sp_runtime::traits::AccountIdLookup; diff --git a/prdoc/pr_3505.prdoc b/prdoc/pr_3505.prdoc index 08ad909739c..b55972927c3 100644 --- a/prdoc/pr_3505.prdoc +++ b/prdoc/pr_3505.prdoc @@ -11,7 +11,7 @@ doc: For example, in the following macro invocation ```rust - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { ... } diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 437f76c9d5f..0852264ef68 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -293,7 +293,7 @@ impl pallet_safe_mode::Config for Runtime { type WeightInfo = pallet_safe_mode::weights::SubstrateWeight; } -#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = InsideBoth; type BlockWeights = RuntimeBlockWeights; diff --git a/substrate/frame/alliance/src/mock.rs b/substrate/frame/alliance/src/mock.rs index fd44d33ef93..b183e412bed 100644 --- a/substrate/frame/alliance/src/mock.rs +++ b/substrate/frame/alliance/src/mock.rs @@ -48,7 +48,7 @@ parameter_types! { frame_system::limits::BlockWeights::simple_max(Weight::MAX); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/asset-conversion/src/mock.rs b/substrate/frame/asset-conversion/src/mock.rs index 870538a68cc..4591b87c186 100644 --- a/substrate/frame/asset-conversion/src/mock.rs +++ b/substrate/frame/asset-conversion/src/mock.rs @@ -53,7 +53,7 @@ construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = u128; type Lookup = IdentityLookup; diff --git a/substrate/frame/asset-rate/src/mock.rs b/substrate/frame/asset-rate/src/mock.rs index 5981b056764..d01996dab19 100644 --- a/substrate/frame/asset-rate/src/mock.rs +++ b/substrate/frame/asset-rate/src/mock.rs @@ -32,7 +32,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs index 09d59ae1b8b..583c75b3827 100644 --- a/substrate/frame/assets/src/lib.rs +++ b/substrate/frame/assets/src/lib.rs @@ -232,7 +232,7 @@ pub mod pallet { use frame_support::{derive_impl, traits::ConstU64}; pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] diff --git a/substrate/frame/assets/src/mock.rs b/substrate/frame/assets/src/mock.rs index 906febb0214..f6173a451ff 100644 --- a/substrate/frame/assets/src/mock.rs +++ b/substrate/frame/assets/src/mock.rs @@ -42,7 +42,7 @@ construct_runtime!( type AccountId = u64; type AssetId = u32; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/atomic-swap/src/tests.rs b/substrate/frame/atomic-swap/src/tests.rs index 4b444d888ed..9f51f04208a 100644 --- a/substrate/frame/atomic-swap/src/tests.rs +++ b/substrate/frame/atomic-swap/src/tests.rs @@ -37,7 +37,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/aura/src/mock.rs b/substrate/frame/aura/src/mock.rs index 8bc3e407158..535e27fa35e 100644 --- a/substrate/frame/aura/src/mock.rs +++ b/substrate/frame/aura/src/mock.rs @@ -40,7 +40,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/authority-discovery/src/lib.rs b/substrate/frame/authority-discovery/src/lib.rs index 2b4dfaf1aea..aa57378934a 100644 --- a/substrate/frame/authority-discovery/src/lib.rs +++ b/substrate/frame/authority-discovery/src/lib.rs @@ -222,7 +222,7 @@ mod tests { pub const Offset: BlockNumber = 0; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = AuthorityId; type Lookup = IdentityLookup; diff --git a/substrate/frame/authorship/src/lib.rs b/substrate/frame/authorship/src/lib.rs index 8b38a58d8e7..d8f1baab23c 100644 --- a/substrate/frame/authorship/src/lib.rs +++ b/substrate/frame/authorship/src/lib.rs @@ -113,7 +113,7 @@ mod tests { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/babe/src/mock.rs b/substrate/frame/babe/src/mock.rs index b693f4fce9b..ec54275278e 100644 --- a/substrate/frame/babe/src/mock.rs +++ b/substrate/frame/babe/src/mock.rs @@ -63,7 +63,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/bags-list/src/mock.rs b/substrate/frame/bags-list/src/mock.rs index 4282120983b..ea677cb9e73 100644 --- a/substrate/frame/bags-list/src/mock.rs +++ b/substrate/frame/bags-list/src/mock.rs @@ -48,7 +48,7 @@ impl frame_election_provider_support::ScoreProvider for StakingMock { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/balances/src/lib.rs b/substrate/frame/balances/src/lib.rs index e87aa6f9311..3fd3102cd35 100644 --- a/substrate/frame/balances/src/lib.rs +++ b/substrate/frame/balances/src/lib.rs @@ -219,7 +219,7 @@ pub mod pallet { pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] diff --git a/substrate/frame/balances/src/tests/mod.rs b/substrate/frame/balances/src/tests/mod.rs index 599909fa943..f2f107d8bd6 100644 --- a/substrate/frame/balances/src/tests/mod.rs +++ b/substrate/frame/balances/src/tests/mod.rs @@ -90,12 +90,13 @@ parameter_types! { pub static ExistentialDeposit: u64 = 1; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = super::AccountData; } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)] impl pallet_transaction_payment::Config for Test { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter, ()>; diff --git a/substrate/frame/beefy-mmr/src/mock.rs b/substrate/frame/beefy-mmr/src/mock.rs index 94149ac6776..9d1ece7a1d8 100644 --- a/substrate/frame/beefy-mmr/src/mock.rs +++ b/substrate/frame/beefy-mmr/src/mock.rs @@ -57,7 +57,7 @@ construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/beefy/src/mock.rs b/substrate/frame/beefy/src/mock.rs index 9cce479890a..fccc63bd1b4 100644 --- a/substrate/frame/beefy/src/mock.rs +++ b/substrate/frame/beefy/src/mock.rs @@ -62,7 +62,7 @@ construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/benchmarking/pov/src/benchmarking.rs b/substrate/frame/benchmarking/pov/src/benchmarking.rs index 84d81890b17..d78cb553318 100644 --- a/substrate/frame/benchmarking/pov/src/benchmarking.rs +++ b/substrate/frame/benchmarking/pov/src/benchmarking.rs @@ -355,7 +355,7 @@ mod mock { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/benchmarking/pov/src/tests.rs b/substrate/frame/benchmarking/pov/src/tests.rs index 7fa2fb97dea..cec42057454 100644 --- a/substrate/frame/benchmarking/pov/src/tests.rs +++ b/substrate/frame/benchmarking/pov/src/tests.rs @@ -175,7 +175,7 @@ mod mock { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/benchmarking/src/baseline.rs b/substrate/frame/benchmarking/src/baseline.rs index 2fd3b634ae7..e76d5aed7b8 100644 --- a/substrate/frame/benchmarking/src/baseline.rs +++ b/substrate/frame/benchmarking/src/baseline.rs @@ -125,7 +125,7 @@ pub mod mock { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/benchmarking/src/tests.rs b/substrate/frame/benchmarking/src/tests.rs index f47a3d9f96a..206ae515aac 100644 --- a/substrate/frame/benchmarking/src/tests.rs +++ b/substrate/frame/benchmarking/src/tests.rs @@ -75,7 +75,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/benchmarking/src/tests_instance.rs b/substrate/frame/benchmarking/src/tests_instance.rs index c28aa694a13..d6e1cf99ef7 100644 --- a/substrate/frame/benchmarking/src/tests_instance.rs +++ b/substrate/frame/benchmarking/src/tests_instance.rs @@ -85,7 +85,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/bounties/src/tests.rs b/substrate/frame/bounties/src/tests.rs index da6596617da..de747db5374 100644 --- a/substrate/frame/bounties/src/tests.rs +++ b/substrate/frame/bounties/src/tests.rs @@ -58,7 +58,7 @@ parameter_types! { type Balance = u64; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = u128; // u64 is not enough to hold bytes used to generate bounty account type Lookup = IdentityLookup; diff --git a/substrate/frame/broker/src/mock.rs b/substrate/frame/broker/src/mock.rs index ac327c4143e..c7205058c97 100644 --- a/substrate/frame/broker/src/mock.rs +++ b/substrate/frame/broker/src/mock.rs @@ -47,7 +47,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/child-bounties/src/tests.rs b/substrate/frame/child-bounties/src/tests.rs index 276a90a3e29..30601f821e4 100644 --- a/substrate/frame/child-bounties/src/tests.rs +++ b/substrate/frame/child-bounties/src/tests.rs @@ -61,7 +61,7 @@ parameter_types! { type Balance = u64; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = u128; type Lookup = IdentityLookup; diff --git a/substrate/frame/collective/src/tests.rs b/substrate/frame/collective/src/tests.rs index 02c3377515c..8a80dd167e3 100644 --- a/substrate/frame/collective/src/tests.rs +++ b/substrate/frame/collective/src/tests.rs @@ -87,7 +87,7 @@ parameter_types! { pub static MaxProposalWeight: Weight = default_max_proposal_weight(); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/contracts/mock-network/src/parachain.rs b/substrate/frame/contracts/mock-network/src/parachain.rs index 7a60a66b314..0848f97b09c 100644 --- a/substrate/frame/contracts/mock-network/src/parachain.rs +++ b/substrate/frame/contracts/mock-network/src/parachain.rs @@ -53,7 +53,7 @@ parameter_types! { pub const BlockHashCount: u64 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; diff --git a/substrate/frame/contracts/mock-network/src/relay_chain.rs b/substrate/frame/contracts/mock-network/src/relay_chain.rs index 6eb9b4e5385..8c79255728e 100644 --- a/substrate/frame/contracts/mock-network/src/relay_chain.rs +++ b/substrate/frame/contracts/mock-network/src/relay_chain.rs @@ -47,7 +47,7 @@ parameter_types! { pub const BlockHashCount: u64 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index 4c1f65e28d5..db6b2e80d07 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -331,7 +331,7 @@ parameter_types! { pub static ExistentialDeposit: u64 = 1; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = AccountId32; type Lookup = IdentityLookup; diff --git a/substrate/frame/conviction-voting/src/tests.rs b/substrate/frame/conviction-voting/src/tests.rs index dbcd643b60f..5c582a35362 100644 --- a/substrate/frame/conviction-voting/src/tests.rs +++ b/substrate/frame/conviction-voting/src/tests.rs @@ -47,7 +47,7 @@ impl Contains for BaseFilter { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/core-fellowship/src/tests/integration.rs b/substrate/frame/core-fellowship/src/tests/integration.rs index 6f177ba66db..3c2dc1de595 100644 --- a/substrate/frame/core-fellowship/src/tests/integration.rs +++ b/substrate/frame/core-fellowship/src/tests/integration.rs @@ -51,7 +51,7 @@ parameter_types! { frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1_000_000, u64::max_value())); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/core-fellowship/src/tests/unit.rs b/substrate/frame/core-fellowship/src/tests/unit.rs index de8cd858bdf..669517d61a4 100644 --- a/substrate/frame/core-fellowship/src/tests/unit.rs +++ b/substrate/frame/core-fellowship/src/tests/unit.rs @@ -47,7 +47,7 @@ parameter_types! { frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1_000_000, u64::max_value())); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/democracy/src/tests.rs b/substrate/frame/democracy/src/tests.rs index 973e0c28eb2..dd69f48dbc1 100644 --- a/substrate/frame/democracy/src/tests.rs +++ b/substrate/frame/democracy/src/tests.rs @@ -77,7 +77,7 @@ parameter_types! { ); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = BaseFilter; type Block = Block; diff --git a/substrate/frame/election-provider-multi-phase/src/mock.rs b/substrate/frame/election-provider-multi-phase/src/mock.rs index 18dcd7061c1..92b87d92e99 100644 --- a/substrate/frame/election-provider-multi-phase/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/src/mock.rs @@ -208,7 +208,7 @@ pub fn witness() -> SolutionOrSnapshotSize { .unwrap_or_default() } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type SS58Prefix = (); type BaseCallFilter = frame_support::traits::Everything; diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs index 882b894bb22..d7d2006d219 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs @@ -86,7 +86,7 @@ pub(crate) type VoterIndex = u16; pub(crate) type TargetIndex = u16; pub(crate) type Moment = u32; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/election-provider-support/src/onchain.rs b/substrate/frame/election-provider-support/src/onchain.rs index d937f42cb40..ee4f6992a08 100644 --- a/substrate/frame/election-provider-support/src/onchain.rs +++ b/substrate/frame/election-provider-support/src/onchain.rs @@ -199,7 +199,7 @@ mod tests { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type SS58Prefix = (); type BaseCallFilter = frame_support::traits::Everything; diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs index 308f2cdc1aa..b4be07030ef 100644 --- a/substrate/frame/elections-phragmen/src/lib.rs +++ b/substrate/frame/elections-phragmen/src/lib.rs @@ -1316,7 +1316,7 @@ mod tests { use sp_runtime::{testing::Header, BuildStorage}; use substrate_test_utils::assert_eq_uvec; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/examples/basic/src/tests.rs b/substrate/frame/examples/basic/src/tests.rs index 207e46e428d..de37bcf7556 100644 --- a/substrate/frame/examples/basic/src/tests.rs +++ b/substrate/frame/examples/basic/src/tests.rs @@ -45,7 +45,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/examples/default-config/src/lib.rs b/substrate/frame/examples/default-config/src/lib.rs index 224faf9dfd4..5b66c78e062 100644 --- a/substrate/frame/examples/default-config/src/lib.rs +++ b/substrate/frame/examples/default-config/src/lib.rs @@ -87,12 +87,11 @@ pub mod pallet { // This will help use not need to disambiguate anything when using `derive_impl`. use super::*; use frame_support::derive_impl; - use frame_system::config_preludes::TestDefaultConfig as SystemTestDefaultConfig; /// A type providing default configurations for this pallet in testing environment. pub struct TestDefaultConfig; - #[derive_impl(SystemTestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] @@ -114,7 +113,7 @@ pub mod pallet { /// example, we simple derive `frame_system::config_preludes::TestDefaultConfig` again. pub struct OtherDefaultConfig; - #[derive_impl(SystemTestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for OtherDefaultConfig {} #[frame_support::register_default_impl(OtherDefaultConfig)] diff --git a/substrate/frame/examples/dev-mode/src/tests.rs b/substrate/frame/examples/dev-mode/src/tests.rs index c13152533fd..1c79b5f5fa6 100644 --- a/substrate/frame/examples/dev-mode/src/tests.rs +++ b/substrate/frame/examples/dev-mode/src/tests.rs @@ -39,7 +39,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/examples/frame-crate/src/lib.rs b/substrate/frame/examples/frame-crate/src/lib.rs index 7e286df1e32..781cba5658d 100644 --- a/substrate/frame/examples/frame-crate/src/lib.rs +++ b/substrate/frame/examples/frame-crate/src/lib.rs @@ -55,7 +55,7 @@ mod tests { } ); - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = MockBlock; } diff --git a/substrate/frame/examples/kitchensink/src/tests.rs b/substrate/frame/examples/kitchensink/src/tests.rs index 7f626718930..1205fefc422 100644 --- a/substrate/frame/examples/kitchensink/src/tests.rs +++ b/substrate/frame/examples/kitchensink/src/tests.rs @@ -37,7 +37,7 @@ frame_support::construct_runtime!( /// Using a default config for [`frame_system`] in tests. See `default-config` example for more /// details. -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/examples/offchain-worker/src/tests.rs b/substrate/frame/examples/offchain-worker/src/tests.rs index ea37a2da493..3525b3b67ed 100644 --- a/substrate/frame/examples/offchain-worker/src/tests.rs +++ b/substrate/frame/examples/offchain-worker/src/tests.rs @@ -46,7 +46,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/examples/single-block-migrations/src/mock.rs b/substrate/frame/examples/single-block-migrations/src/mock.rs index 02f72e01836..68594cc4ad7 100644 --- a/substrate/frame/examples/single-block-migrations/src/mock.rs +++ b/substrate/frame/examples/single-block-migrations/src/mock.rs @@ -34,7 +34,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for MockRuntime { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/examples/split/src/mock.rs b/substrate/frame/examples/split/src/mock.rs index caab4f1ae90..5bf414ee241 100644 --- a/substrate/frame/examples/split/src/mock.rs +++ b/substrate/frame/examples/split/src/mock.rs @@ -31,7 +31,7 @@ frame_support::construct_runtime!( /// Using a default config for [`frame_system`] in tests. See `default-config` example for more /// details. -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/examples/tasks/src/mock.rs b/substrate/frame/examples/tasks/src/mock.rs index 5ad104b0dfa..76ac9e76bff 100644 --- a/substrate/frame/examples/tasks/src/mock.rs +++ b/substrate/frame/examples/tasks/src/mock.rs @@ -32,7 +32,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; } diff --git a/substrate/frame/executive/src/tests.rs b/substrate/frame/executive/src/tests.rs index 70b55f6e855..204889a292f 100644 --- a/substrate/frame/executive/src/tests.rs +++ b/substrate/frame/executive/src/tests.rs @@ -309,7 +309,7 @@ parameter_types! { }; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BlockWeights = BlockWeights; type RuntimeOrigin = RuntimeOrigin; @@ -327,7 +327,7 @@ impl frame_system::Config for Runtime { type Balance = u64; -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Runtime { type Balance = Balance; type AccountStore = System; diff --git a/substrate/frame/fast-unstake/src/mock.rs b/substrate/frame/fast-unstake/src/mock.rs index 78d881965a5..b731cb822f3 100644 --- a/substrate/frame/fast-unstake/src/mock.rs +++ b/substrate/frame/fast-unstake/src/mock.rs @@ -43,7 +43,7 @@ parameter_types! { ); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/glutton/src/mock.rs b/substrate/frame/glutton/src/mock.rs index 0049800d952..132ef5cfbcb 100644 --- a/substrate/frame/glutton/src/mock.rs +++ b/substrate/frame/glutton/src/mock.rs @@ -31,7 +31,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/grandpa/src/mock.rs b/substrate/frame/grandpa/src/mock.rs index 5d48f974c31..4a21da655e5 100644 --- a/substrate/frame/grandpa/src/mock.rs +++ b/substrate/frame/grandpa/src/mock.rs @@ -66,7 +66,7 @@ impl_opaque_keys! { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/identity/src/tests.rs b/substrate/frame/identity/src/tests.rs index 60866f12baa..0a9464256ce 100644 --- a/substrate/frame/identity/src/tests.rs +++ b/substrate/frame/identity/src/tests.rs @@ -53,7 +53,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = AccountId; type Lookup = IdentityLookup; diff --git a/substrate/frame/im-online/src/mock.rs b/substrate/frame/im-online/src/mock.rs index 9dad148b10f..cc448dc1ae1 100644 --- a/substrate/frame/im-online/src/mock.rs +++ b/substrate/frame/im-online/src/mock.rs @@ -112,7 +112,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { result } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/indices/src/mock.rs b/substrate/frame/indices/src/mock.rs index 5cf82305178..9f8bf8c3758 100644 --- a/substrate/frame/indices/src/mock.rs +++ b/substrate/frame/indices/src/mock.rs @@ -38,7 +38,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/insecure-randomness-collective-flip/src/lib.rs b/substrate/frame/insecure-randomness-collective-flip/src/lib.rs index 04f8cda6541..bdb089a1420 100644 --- a/substrate/frame/insecure-randomness-collective-flip/src/lib.rs +++ b/substrate/frame/insecure-randomness-collective-flip/src/lib.rs @@ -186,7 +186,7 @@ mod tests { ::max(2 * 1024); } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/lottery/src/mock.rs b/substrate/frame/lottery/src/mock.rs index 563ce7202ec..596e1a9d837 100644 --- a/substrate/frame/lottery/src/mock.rs +++ b/substrate/frame/lottery/src/mock.rs @@ -43,7 +43,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/membership/src/lib.rs b/substrate/frame/membership/src/lib.rs index f4ac697130d..426fc985a52 100644 --- a/substrate/frame/membership/src/lib.rs +++ b/substrate/frame/membership/src/lib.rs @@ -564,7 +564,7 @@ mod tests { pub static Prime: Option = None; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/merkle-mountain-range/src/mock.rs b/substrate/frame/merkle-mountain-range/src/mock.rs index b3b5127db02..212012a052a 100644 --- a/substrate/frame/merkle-mountain-range/src/mock.rs +++ b/substrate/frame/merkle-mountain-range/src/mock.rs @@ -33,7 +33,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/message-queue/src/integration_test.rs b/substrate/frame/message-queue/src/integration_test.rs index ce8eb80805a..26a330cc88e 100644 --- a/substrate/frame/message-queue/src/integration_test.rs +++ b/substrate/frame/message-queue/src/integration_test.rs @@ -52,7 +52,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/message-queue/src/mock.rs b/substrate/frame/message-queue/src/mock.rs index d176a981ca8..f22f318b8ef 100644 --- a/substrate/frame/message-queue/src/mock.rs +++ b/substrate/frame/message-queue/src/mock.rs @@ -37,7 +37,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/migrations/src/mock.rs b/substrate/frame/migrations/src/mock.rs index 37292647554..bcd6a189c5b 100644 --- a/substrate/frame/migrations/src/mock.rs +++ b/substrate/frame/migrations/src/mock.rs @@ -40,7 +40,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type PalletInfo = PalletInfo; diff --git a/substrate/frame/multisig/src/tests.rs b/substrate/frame/multisig/src/tests.rs index 887c7f8bebc..0d73e3db661 100644 --- a/substrate/frame/multisig/src/tests.rs +++ b/substrate/frame/multisig/src/tests.rs @@ -38,7 +38,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type BlockHashCount = ConstU32<250>; @@ -47,7 +47,7 @@ impl frame_system::Config for Test { type BaseCallFilter = TestBaseCallFilter; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/substrate/frame/nft-fractionalization/src/mock.rs b/substrate/frame/nft-fractionalization/src/mock.rs index a4138615009..82a60881626 100644 --- a/substrate/frame/nft-fractionalization/src/mock.rs +++ b/substrate/frame/nft-fractionalization/src/mock.rs @@ -49,7 +49,7 @@ construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = AccountId; type Lookup = IdentityLookup; diff --git a/substrate/frame/nfts/src/mock.rs b/substrate/frame/nfts/src/mock.rs index e86fafd07e9..51cfd5f244b 100644 --- a/substrate/frame/nfts/src/mock.rs +++ b/substrate/frame/nfts/src/mock.rs @@ -45,7 +45,7 @@ pub type Signature = MultiSignature; pub type AccountPublic = ::Signer; pub type AccountId = ::AccountId; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = AccountId; type Lookup = IdentityLookup; diff --git a/substrate/frame/nis/src/mock.rs b/substrate/frame/nis/src/mock.rs index 03976bc66c4..33464db34c3 100644 --- a/substrate/frame/nis/src/mock.rs +++ b/substrate/frame/nis/src/mock.rs @@ -44,7 +44,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/node-authorization/src/mock.rs b/substrate/frame/node-authorization/src/mock.rs index 84ca4d7eff7..656d2bfa39a 100644 --- a/substrate/frame/node-authorization/src/mock.rs +++ b/substrate/frame/node-authorization/src/mock.rs @@ -34,7 +34,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/nomination-pools/benchmarking/src/mock.rs b/substrate/frame/nomination-pools/benchmarking/src/mock.rs index 4e57c00849f..1c513a1007c 100644 --- a/substrate/frame/nomination-pools/benchmarking/src/mock.rs +++ b/substrate/frame/nomination-pools/benchmarking/src/mock.rs @@ -28,7 +28,7 @@ type Nonce = u32; type BlockNumber = u64; type Balance = u128; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index f982b72c635..686759604c2 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -222,7 +222,7 @@ impl sp_staking::StakingInterface for StakingMock { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type SS58Prefix = (); type BaseCallFilter = frame_support::traits::Everything; diff --git a/substrate/frame/nomination-pools/test-staking/src/mock.rs b/substrate/frame/nomination-pools/test-staking/src/mock.rs index ce97e13d640..22939ff5e23 100644 --- a/substrate/frame/nomination-pools/test-staking/src/mock.rs +++ b/substrate/frame/nomination-pools/test-staking/src/mock.rs @@ -38,7 +38,7 @@ pub(crate) type T = Runtime; pub(crate) const POOL1_BONDED: AccountId = 20318131474730217858575332831085u128; pub(crate) const POOL1_REWARD: AccountId = 20397359637244482196168876781421u128; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/offences/benchmarking/src/mock.rs b/substrate/frame/offences/benchmarking/src/mock.rs index 01ad8d64f10..ea2e9e93ed6 100644 --- a/substrate/frame/offences/benchmarking/src/mock.rs +++ b/substrate/frame/offences/benchmarking/src/mock.rs @@ -40,7 +40,7 @@ type AccountId = u64; type Nonce = u32; type Balance = u64; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/offences/src/mock.rs b/substrate/frame/offences/src/mock.rs index d97be99def1..31d5f805f3e 100644 --- a/substrate/frame/offences/src/mock.rs +++ b/substrate/frame/offences/src/mock.rs @@ -74,7 +74,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/paged-list/src/mock.rs b/substrate/frame/paged-list/src/mock.rs index 37bdc4f157c..5d06170aae7 100644 --- a/substrate/frame/paged-list/src/mock.rs +++ b/substrate/frame/paged-list/src/mock.rs @@ -41,7 +41,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/parameters/src/lib.rs b/substrate/frame/parameters/src/lib.rs index 91cf10ba93f..3e54eb6d67f 100644 --- a/substrate/frame/parameters/src/lib.rs +++ b/substrate/frame/parameters/src/lib.rs @@ -225,7 +225,7 @@ pub mod pallet { /// A configuration for testing. pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] diff --git a/substrate/frame/parameters/src/tests/mock.rs b/substrate/frame/parameters/src/tests/mock.rs index 98612dc6a6d..4c7dda639a9 100644 --- a/substrate/frame/parameters/src/tests/mock.rs +++ b/substrate/frame/parameters/src/tests/mock.rs @@ -28,13 +28,13 @@ use frame_support::{ use crate as pallet_parameters; use crate::*; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = frame_system::mocking::MockBlock; type AccountData = pallet_balances::AccountData<::Balance>; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type AccountStore = System; @@ -112,7 +112,7 @@ mod custom_origin { } #[docify::export(impl_config)] -#[derive_impl(pallet_parameters::config_preludes::TestDefaultConfig as pallet_parameters::DefaultConfig)] +#[derive_impl(pallet_parameters::config_preludes::TestDefaultConfig)] impl Config for Runtime { type AdminOrigin = custom_origin::ParamsManager; // RuntimeParameters is injected by the `derive_impl` macro. diff --git a/substrate/frame/parameters/src/tests/test_renamed.rs b/substrate/frame/parameters/src/tests/test_renamed.rs index b2e0c1fd966..cfc870fbe10 100644 --- a/substrate/frame/parameters/src/tests/test_renamed.rs +++ b/substrate/frame/parameters/src/tests/test_renamed.rs @@ -31,13 +31,13 @@ use crate::*; use dynamic_params::*; use RuntimeParametersRenamed::*; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = frame_system::mocking::MockBlock; type AccountData = pallet_balances::AccountData<::Balance>; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type AccountStore = System; @@ -80,7 +80,7 @@ impl Default for RuntimeParametersRenamed { } } -#[derive_impl(pallet_parameters::config_preludes::TestDefaultConfig as pallet_parameters::DefaultConfig)] +#[derive_impl(pallet_parameters::config_preludes::TestDefaultConfig)] impl Config for Runtime { type AdminOrigin = AsEnsureOriginWithArg>; type RuntimeParameters = RuntimeParametersRenamed; diff --git a/substrate/frame/preimage/src/mock.rs b/substrate/frame/preimage/src/mock.rs index a43e8347d76..903c34596ae 100644 --- a/substrate/frame/preimage/src/mock.rs +++ b/substrate/frame/preimage/src/mock.rs @@ -42,7 +42,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/proxy/src/tests.rs b/substrate/frame/proxy/src/tests.rs index 67a662e01b2..3ed61fbedaa 100644 --- a/substrate/frame/proxy/src/tests.rs +++ b/substrate/frame/proxy/src/tests.rs @@ -42,14 +42,14 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type BaseCallFilter = BaseFilter; type AccountData = pallet_balances::AccountData; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/substrate/frame/ranked-collective/src/tests.rs b/substrate/frame/ranked-collective/src/tests.rs index 31add52d90a..ad8b7d2a801 100644 --- a/substrate/frame/ranked-collective/src/tests.rs +++ b/substrate/frame/ranked-collective/src/tests.rs @@ -45,7 +45,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/recovery/src/mock.rs b/substrate/frame/recovery/src/mock.rs index 89374527e06..bec7e02c128 100644 --- a/substrate/frame/recovery/src/mock.rs +++ b/substrate/frame/recovery/src/mock.rs @@ -37,7 +37,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/referenda/src/mock.rs b/substrate/frame/referenda/src/mock.rs index bfafc107c28..135476d7cb1 100644 --- a/substrate/frame/referenda/src/mock.rs +++ b/substrate/frame/referenda/src/mock.rs @@ -58,7 +58,7 @@ impl Contains for BaseFilter { parameter_types! { pub MaxWeight: Weight = Weight::from_parts(2_000_000_000_000, u64::MAX); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = BaseFilter; type Block = Block; diff --git a/substrate/frame/remark/src/mock.rs b/substrate/frame/remark/src/mock.rs index d89583513b6..3eaac4ab439 100644 --- a/substrate/frame/remark/src/mock.rs +++ b/substrate/frame/remark/src/mock.rs @@ -32,7 +32,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/root-offences/src/mock.rs b/substrate/frame/root-offences/src/mock.rs index 1f7cce27769..626db138c2b 100644 --- a/substrate/frame/root-offences/src/mock.rs +++ b/substrate/frame/root-offences/src/mock.rs @@ -78,7 +78,7 @@ impl sp_runtime::BoundToRuntimeAppPublic for OtherSessionHandler { type Public = UintAuthorityId; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/safe-mode/src/mock.rs b/substrate/frame/safe-mode/src/mock.rs index b4d7a624ea2..fbfc16f4aa2 100644 --- a/substrate/frame/safe-mode/src/mock.rs +++ b/substrate/frame/safe-mode/src/mock.rs @@ -33,7 +33,7 @@ use sp_runtime::{ BuildStorage, }; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = InsideBoth; type BlockWeights = (); diff --git a/substrate/frame/salary/src/tests/integration.rs b/substrate/frame/salary/src/tests/integration.rs index a49b5637b8a..26afb2d8aba 100644 --- a/substrate/frame/salary/src/tests/integration.rs +++ b/substrate/frame/salary/src/tests/integration.rs @@ -50,7 +50,7 @@ parameter_types! { frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1_000_000, 0)); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/salary/src/tests/unit.rs b/substrate/frame/salary/src/tests/unit.rs index b3fd00ec76b..5e308354116 100644 --- a/substrate/frame/salary/src/tests/unit.rs +++ b/substrate/frame/salary/src/tests/unit.rs @@ -46,7 +46,7 @@ parameter_types! { frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1_000_000, 0)); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/sassafras/src/mock.rs b/substrate/frame/sassafras/src/mock.rs index 5e5909fcb0d..f145bffa3a0 100644 --- a/substrate/frame/sassafras/src/mock.rs +++ b/substrate/frame/sassafras/src/mock.rs @@ -43,7 +43,7 @@ const LOG_TARGET: &str = "sassafras::tests"; const EPOCH_LENGTH: u32 = 10; const MAX_AUTHORITIES: u32 = 100; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = frame_system::mocking::MockBlock; } diff --git a/substrate/frame/scheduler/src/mock.rs b/substrate/frame/scheduler/src/mock.rs index bf7dac0d53a..8d36ca1c42e 100644 --- a/substrate/frame/scheduler/src/mock.rs +++ b/substrate/frame/scheduler/src/mock.rs @@ -137,7 +137,7 @@ parameter_types! { ); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl system::Config for Test { type BaseCallFilter = BaseFilter; type Block = Block; diff --git a/substrate/frame/scored-pool/src/mock.rs b/substrate/frame/scored-pool/src/mock.rs index 6fba1bb3d53..9d2f5eb1099 100644 --- a/substrate/frame/scored-pool/src/mock.rs +++ b/substrate/frame/scored-pool/src/mock.rs @@ -46,7 +46,7 @@ ord_parameter_types! { pub const ScoreOrigin: u64 = 3; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/session/benchmarking/src/mock.rs b/substrate/frame/session/benchmarking/src/mock.rs index 2ef8989f4b0..81052141fd8 100644 --- a/substrate/frame/session/benchmarking/src/mock.rs +++ b/substrate/frame/session/benchmarking/src/mock.rs @@ -45,7 +45,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/session/src/mock.rs b/substrate/frame/session/src/mock.rs index 89804f72cd6..25b81668cc0 100644 --- a/substrate/frame/session/src/mock.rs +++ b/substrate/frame/session/src/mock.rs @@ -224,7 +224,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new(t) } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/society/src/mock.rs b/substrate/frame/society/src/mock.rs index 04f3e85f539..3c27c08a106 100644 --- a/substrate/frame/society/src/mock.rs +++ b/substrate/frame/society/src/mock.rs @@ -54,7 +54,7 @@ ord_parameter_types! { pub const MaxBids: u32 = 10; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = u128; type Block = Block; @@ -62,7 +62,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/substrate/frame/staking/src/mock.rs b/substrate/frame/staking/src/mock.rs index 65e660f248d..6c2ea225ff1 100644 --- a/substrate/frame/staking/src/mock.rs +++ b/substrate/frame/staking/src/mock.rs @@ -118,7 +118,7 @@ parameter_types! { pub static MaxControllersInDeprecationBatch: u32 = 5900; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type DbWeight = RocksDbWeight; type Block = Block; diff --git a/substrate/frame/state-trie-migration/src/lib.rs b/substrate/frame/state-trie-migration/src/lib.rs index 6b3aa9934e0..6e1de865ab4 100644 --- a/substrate/frame/state-trie-migration/src/lib.rs +++ b/substrate/frame/state-trie-migration/src/lib.rs @@ -452,7 +452,7 @@ pub mod pallet { pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] @@ -1131,7 +1131,7 @@ mod mock { pub const SS58Prefix: u8 = 42; } - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type BlockHashCount = ConstU32<250>; @@ -1144,7 +1144,7 @@ mod mock { pub const MigrationMaxKeyLen: u32 = 512; } - #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] + #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type AccountStore = System; @@ -1177,7 +1177,7 @@ mod mock { } } - #[derive_impl(super::config_preludes::TestDefaultConfig as pallet_state_trie_migration::DefaultConfig)] + #[derive_impl(super::config_preludes::TestDefaultConfig)] impl pallet_state_trie_migration::Config for Test { type ControlOrigin = EnsureRoot; type Currency = Balances; diff --git a/substrate/frame/statement/src/mock.rs b/substrate/frame/statement/src/mock.rs index 4ab9cf9e0f9..35d51e7a27b 100644 --- a/substrate/frame/statement/src/mock.rs +++ b/substrate/frame/statement/src/mock.rs @@ -43,7 +43,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = AccountId32; type Lookup = IdentityLookup; diff --git a/substrate/frame/sudo/src/lib.rs b/substrate/frame/sudo/src/lib.rs index 2ebe4cb0157..d8b734e6bbe 100644 --- a/substrate/frame/sudo/src/lib.rs +++ b/substrate/frame/sudo/src/lib.rs @@ -156,7 +156,7 @@ pub mod pallet { /// Default prelude sensible to be used in a testing environment. pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] diff --git a/substrate/frame/sudo/src/mock.rs b/substrate/frame/sudo/src/mock.rs index 3b907a27168..a3a786c4af3 100644 --- a/substrate/frame/sudo/src/mock.rs +++ b/substrate/frame/sudo/src/mock.rs @@ -104,7 +104,7 @@ impl Contains for BlockEverything { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 4eadd85a9e0..c524f8953a4 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -1933,7 +1933,7 @@ pub mod pallet_macros { /// # use frame_support::__private::TestExternalities; /// # use frame_support::traits::UnfilteredDispatchable; /// # impl custom_pallet::Config for Runtime {} - /// # #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + /// # #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] /// # impl frame_system::Config for Runtime { /// # type Block = frame_system::mocking::MockBlock; /// # } diff --git a/substrate/frame/support/src/tests/mod.rs b/substrate/frame/support/src/tests/mod.rs index c63bfb181c3..88afa243f09 100644 --- a/substrate/frame/support/src/tests/mod.rs +++ b/substrate/frame/support/src/tests/mod.rs @@ -227,7 +227,7 @@ crate::construct_runtime!( } ); -#[crate::derive_impl(self::frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[crate::derive_impl(self::frame_system::config_preludes::TestDefaultConfig as self::frame_system::DefaultConfig)] impl Config for Runtime { type Block = Block; type AccountId = AccountId; diff --git a/substrate/frame/support/test/compile_pass/src/lib.rs b/substrate/frame/support/test/compile_pass/src/lib.rs index 575322df760..07d2f7d9ecd 100644 --- a/substrate/frame/support/test/compile_pass/src/lib.rs +++ b/substrate/frame/support/test/compile_pass/src/lib.rs @@ -51,7 +51,7 @@ parameter_types! { pub const Version: RuntimeVersion = VERSION; } -#[derive_impl(renamed_frame_system::config_preludes::TestDefaultConfig as renamed_frame_system::DefaultConfig)] +#[derive_impl(renamed_frame_system::config_preludes::TestDefaultConfig)] impl renamed_frame_system::Config for Runtime { type BaseCallFilter = Everything; type BlockWeights = (); diff --git a/substrate/frame/support/test/stg_frame_crate/src/lib.rs b/substrate/frame/support/test/stg_frame_crate/src/lib.rs index 59a66851f23..dc5fff65510 100644 --- a/substrate/frame/support/test/stg_frame_crate/src/lib.rs +++ b/substrate/frame/support/test/stg_frame_crate/src/lib.rs @@ -60,7 +60,7 @@ mod tests { impl crate::pallet::Config for Runtime {} - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; } diff --git a/substrate/frame/support/test/tests/composite_enum.rs b/substrate/frame/support/test/tests/composite_enum.rs index b9e9c23c4bc..1f937705823 100644 --- a/substrate/frame/support/test/tests/composite_enum.rs +++ b/substrate/frame/support/test/tests/composite_enum.rs @@ -114,7 +114,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; } diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs b/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs index 78ae6f57f08..26110810250 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs +++ b/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs @@ -36,7 +36,7 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; pub type Block = generic::Block; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; diff --git a/substrate/frame/support/test/tests/origin.rs b/substrate/frame/support/test/tests/origin.rs index 5682bb500c7..a25c575cc51 100644 --- a/substrate/frame/support/test/tests/origin.rs +++ b/substrate/frame/support/test/tests/origin.rs @@ -170,7 +170,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for RuntimeOriginTest { type BaseCallFilter = BaseCallFilter; type Block = Block; diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 607f54ccc13..f41e606ad7c 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -693,7 +693,7 @@ frame_support::parameter_types!( pub const MyGetParam3: u32 = 12; ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/substrate/frame/support/test/tests/pallet_instance.rs b/substrate/frame/support/test/tests/pallet_instance.rs index f8cc97623b8..c79cdf93e97 100644 --- a/substrate/frame/support/test/tests/pallet_instance.rs +++ b/substrate/frame/support/test/tests/pallet_instance.rs @@ -296,7 +296,7 @@ pub mod pallet2 { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs index 33b96dea948..8e8079b183c 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs @@ -25,7 +25,7 @@ pub type Header = sp_runtime::generic::Header; pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs index db006fe7935..08b0b919e21 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs @@ -25,7 +25,7 @@ pub type Header = sp_runtime::generic::Header; pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/dev_mode_valid.rs b/substrate/frame/support/test/tests/pallet_ui/pass/dev_mode_valid.rs index 4dc33991b12..e4ea094d069 100644 --- a/substrate/frame/support/test/tests/pallet_ui/pass/dev_mode_valid.rs +++ b/substrate/frame/support/test/tests/pallet_ui/pass/dev_mode_valid.rs @@ -70,7 +70,7 @@ pub mod pallet { impl Pallet {} } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/no_std_genesis_config.rs b/substrate/frame/support/test/tests/pallet_ui/pass/no_std_genesis_config.rs index 7e67193cc76..23e411e1a09 100644 --- a/substrate/frame/support/test/tests/pallet_ui/pass/no_std_genesis_config.rs +++ b/substrate/frame/support/test/tests/pallet_ui/pass/no_std_genesis_config.rs @@ -27,7 +27,7 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type AccountId = AccountId; type Lookup = sp_runtime::traits::IdentityLookup; diff --git a/substrate/frame/support/test/tests/runtime_metadata.rs b/substrate/frame/support/test/tests/runtime_metadata.rs index 40e70b219ba..819ec176d2b 100644 --- a/substrate/frame/support/test/tests/runtime_metadata.rs +++ b/substrate/frame/support/test/tests/runtime_metadata.rs @@ -27,7 +27,7 @@ pub type Header = sp_runtime::generic::Header; pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BlockWeights = (); type BlockLength = (); diff --git a/substrate/frame/support/test/tests/storage_layers.rs b/substrate/frame/support/test/tests/storage_layers.rs index 88edd7de6ca..caa125153e9 100644 --- a/substrate/frame/support/test/tests/storage_layers.rs +++ b/substrate/frame/support/test/tests/storage_layers.rs @@ -64,7 +64,7 @@ pub type Header = sp_runtime::generic::Header; pub type Block = sp_runtime::generic::Block; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/support/test/tests/storage_transaction.rs b/substrate/frame/support/test/tests/storage_transaction.rs index f1489a8b0a6..a5bbfd24ab0 100644 --- a/substrate/frame/support/test/tests/storage_transaction.rs +++ b/substrate/frame/support/test/tests/storage_transaction.rs @@ -87,7 +87,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; diff --git a/substrate/frame/support/test/tests/versioned_migration.rs b/substrate/frame/support/test/tests/versioned_migration.rs index dab5e06dc85..3fdfb902129 100644 --- a/substrate/frame/support/test/tests/versioned_migration.rs +++ b/substrate/frame/support/test/tests/versioned_migration.rs @@ -71,7 +71,7 @@ construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type Block = Block; diff --git a/substrate/frame/system/benches/bench.rs b/substrate/frame/system/benches/bench.rs index a0c567bf852..87c5581b2a3 100644 --- a/substrate/frame/system/benches/bench.rs +++ b/substrate/frame/system/benches/bench.rs @@ -60,7 +60,7 @@ frame_support::parameter_types! { ); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/system/benchmarking/src/mock.rs b/substrate/frame/system/benchmarking/src/mock.rs index edbf74a9a51..39a64ff6177 100644 --- a/substrate/frame/system/benchmarking/src/mock.rs +++ b/substrate/frame/system/benchmarking/src/mock.rs @@ -35,7 +35,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/substrate/frame/system/src/mock.rs b/substrate/frame/system/src/mock.rs index 7059845a7df..e1959e572e9 100644 --- a/substrate/frame/system/src/mock.rs +++ b/substrate/frame/system/src/mock.rs @@ -78,7 +78,7 @@ impl OnKilledAccount for RecordKilled { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl Config for Test { type BlockWeights = RuntimeBlockWeights; type BlockLength = RuntimeBlockLength; diff --git a/substrate/frame/timestamp/src/lib.rs b/substrate/frame/timestamp/src/lib.rs index a62ac6d633d..5269f17eca6 100644 --- a/substrate/frame/timestamp/src/lib.rs +++ b/substrate/frame/timestamp/src/lib.rs @@ -154,7 +154,7 @@ pub mod pallet { /// Default prelude sensible to be used in a testing environment. pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] diff --git a/substrate/frame/timestamp/src/mock.rs b/substrate/frame/timestamp/src/mock.rs index 244b66a4bb2..eb4fdbe71fa 100644 --- a/substrate/frame/timestamp/src/mock.rs +++ b/substrate/frame/timestamp/src/mock.rs @@ -35,7 +35,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; } diff --git a/substrate/frame/tips/src/tests.rs b/substrate/frame/tips/src/tests.rs index 0e7ea1f4781..78df3736815 100644 --- a/substrate/frame/tips/src/tests.rs +++ b/substrate/frame/tips/src/tests.rs @@ -57,7 +57,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = u128; // u64 is not enough to hold bytes used to generate bounty account type Lookup = IdentityLookup; diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs index c8bf2eb8f44..bd9565fe188 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs @@ -84,7 +84,7 @@ parameter_types! { pub static TransactionByteFee: u64 = 1; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = BlockWeights; @@ -168,6 +168,7 @@ impl OnUnbalanced> for DealWithFees } } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)] impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter; diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs index 1f335b4f6c4..4387f319c3b 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs @@ -71,7 +71,7 @@ parameter_types! { pub static TransactionByteFee: u64 = 1; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = BlockWeights; @@ -136,6 +136,7 @@ impl WeightToFeeT for TransactionByteFee { } } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)] impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter; diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs index 17c4c773997..5f26680af37 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs @@ -22,7 +22,7 @@ use frame_system as system; type Block = frame_system::mocking::MockBlock; type AccountId = u64; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; } diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs index efadfd60bdd..0e440ee4e9f 100644 --- a/substrate/frame/transaction-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/src/lib.rs @@ -326,7 +326,7 @@ pub mod pallet { /// Default prelude sensible to be used in a testing environment. pub struct TestDefaultConfig; - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] impl frame_system::DefaultConfig for TestDefaultConfig {} #[frame_support::register_default_impl(TestDefaultConfig)] diff --git a/substrate/frame/transaction-payment/src/mock.rs b/substrate/frame/transaction-payment/src/mock.rs index 1ca2e3d7347..67ad1caa02f 100644 --- a/substrate/frame/transaction-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/src/mock.rs @@ -70,7 +70,7 @@ parameter_types! { pub static OperationalFeeMultiplier: u8 = 5; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = BlockWeights; diff --git a/substrate/frame/transaction-storage/src/mock.rs b/substrate/frame/transaction-storage/src/mock.rs index 31f539327cd..f1e9e0591f6 100644 --- a/substrate/frame/transaction-storage/src/mock.rs +++ b/substrate/frame/transaction-storage/src/mock.rs @@ -39,7 +39,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; @@ -48,7 +48,7 @@ impl frame_system::Config for Test { type Lookup = IdentityLookup; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Test { type AccountStore = System; } diff --git a/substrate/frame/treasury/src/tests.rs b/substrate/frame/treasury/src/tests.rs index b488300de99..67d81cb5c30 100644 --- a/substrate/frame/treasury/src/tests.rs +++ b/substrate/frame/treasury/src/tests.rs @@ -53,7 +53,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountId = u128; // u64 is not enough to hold bytes used to generate bounty account type Lookup = IdentityLookup; diff --git a/substrate/frame/tx-pause/src/mock.rs b/substrate/frame/tx-pause/src/mock.rs index 8ccdc43a46c..5206023838b 100644 --- a/substrate/frame/tx-pause/src/mock.rs +++ b/substrate/frame/tx-pause/src/mock.rs @@ -36,7 +36,7 @@ use sp_runtime::{ parameter_types! { pub const BlockHashCount: u64 = 250; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = InsideBoth; type BlockWeights = (); diff --git a/substrate/frame/uniques/src/mock.rs b/substrate/frame/uniques/src/mock.rs index eae12597163..9fd7f87e159 100644 --- a/substrate/frame/uniques/src/mock.rs +++ b/substrate/frame/uniques/src/mock.rs @@ -37,7 +37,7 @@ construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/frame/utility/src/tests.rs b/substrate/frame/utility/src/tests.rs index 8742513be95..9bcbec99f3b 100644 --- a/substrate/frame/utility/src/tests.rs +++ b/substrate/frame/utility/src/tests.rs @@ -143,7 +143,7 @@ parameter_types! { pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(Weight::MAX); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = TestBaseCallFilter; type BlockWeights = BlockWeights; diff --git a/substrate/frame/vesting/src/mock.rs b/substrate/frame/vesting/src/mock.rs index 8a0cd135125..674a6f6e2a8 100644 --- a/substrate/frame/vesting/src/mock.rs +++ b/substrate/frame/vesting/src/mock.rs @@ -35,7 +35,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type AccountData = pallet_balances::AccountData; type Block = Block; diff --git a/substrate/frame/whitelist/src/mock.rs b/substrate/frame/whitelist/src/mock.rs index e323e806b81..6fb8711057e 100644 --- a/substrate/frame/whitelist/src/mock.rs +++ b/substrate/frame/whitelist/src/mock.rs @@ -37,7 +37,7 @@ construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type Block = Block; type AccountData = pallet_balances::AccountData; diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index 63e0aa6e137..9270978cd12 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -342,7 +342,7 @@ parameter_types! { .build_or_panic(); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::pallet::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = RuntimeBlockWeights; diff --git a/substrate/utils/frame/rpc/support/src/lib.rs b/substrate/utils/frame/rpc/support/src/lib.rs index 8280c46aadf..a839bbc3402 100644 --- a/substrate/utils/frame/rpc/support/src/lib.rs +++ b/substrate/utils/frame/rpc/support/src/lib.rs @@ -49,7 +49,7 @@ use sp_storage::{StorageData, StorageKey}; /// # /// # type Hash = sp_core::H256; /// # -/// # #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +/// # #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] /// # impl frame_system::Config for TestRuntime { /// # type BaseCallFilter = (); /// # type BlockWeights = (); diff --git a/templates/minimal/runtime/src/lib.rs b/templates/minimal/runtime/src/lib.rs index 91859cf4a2f..00fcaf1cec7 100644 --- a/templates/minimal/runtime/src/lib.rs +++ b/templates/minimal/runtime/src/lib.rs @@ -83,7 +83,7 @@ parameter_types! { pub const Version: RuntimeVersion = VERSION; } -#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; type Version = Version; @@ -91,18 +91,18 @@ impl frame_system::Config for Runtime { type AccountData = pallet_balances::AccountData<::Balance>; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for Runtime { type AccountStore = System; } -#[derive_impl(pallet_sudo::config_preludes::TestDefaultConfig as pallet_sudo::DefaultConfig)] +#[derive_impl(pallet_sudo::config_preludes::TestDefaultConfig)] impl pallet_sudo::Config for Runtime {} -#[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig as pallet_timestamp::DefaultConfig)] +#[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig)] impl pallet_timestamp::Config for Runtime {} -#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)] impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type WeightToFee = NoFee<::Balance>; diff --git a/templates/parachain/pallets/template/src/mock.rs b/templates/parachain/pallets/template/src/mock.rs index f510a8b773a..8a88be3e3e9 100644 --- a/templates/parachain/pallets/template/src/mock.rs +++ b/templates/parachain/pallets/template/src/mock.rs @@ -22,7 +22,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl system::Config for Test { type BaseCallFilter = Everything; type BlockWeights = (); diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs index 89899d286bb..dcfab59eb81 100644 --- a/templates/parachain/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -277,7 +277,7 @@ parameter_types! { /// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from /// [`ParaChainDefaultConfig`](`struct@frame_system::config_preludes::ParaChainDefaultConfig`), /// but overridden as needed. -#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; diff --git a/templates/solochain/pallets/template/src/mock.rs b/templates/solochain/pallets/template/src/mock.rs index 8346461e6ed..3f1fd2dd6d4 100644 --- a/templates/solochain/pallets/template/src/mock.rs +++ b/templates/solochain/pallets/template/src/mock.rs @@ -20,7 +20,7 @@ frame_support::construct_runtime!( } ); -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs index a8a5b7857e1..358db0849a0 100644 --- a/templates/solochain/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -148,7 +148,7 @@ parameter_types! { /// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from /// [`SoloChainDefaultConfig`](`struct@frame_system::config_preludes::SolochainDefaultConfig`), /// but overridden as needed. -#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)] impl frame_system::Config for Runtime { /// The block type for the runtime. type Block = Block; -- GitLab From 4987d7982461e2e5ffe219cdf71ec697284cea7c Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Fri, 15 Mar 2024 13:42:58 +0200 Subject: [PATCH 124/188] Add elastic scaling support in ParaInherent BenchBuilder (#3690) Extracted Benchbuilder enhancements used in https://github.com/paritytech/polkadot-sdk/pull/3644 . Might still require some work to fully support all scenarios when disputing elastic scaling parachains, but it should be useful in writing elastic scaling runtime tests. --------- Signed-off-by: Andrei Sandu --- polkadot/runtime/parachains/src/builder.rs | 448 +++++++++++------- .../src/paras_inherent/benchmarking.rs | 6 +- .../parachains/src/paras_inherent/tests.rs | 2 +- 3 files changed, 280 insertions(+), 176 deletions(-) diff --git a/polkadot/runtime/parachains/src/builder.rs b/polkadot/runtime/parachains/src/builder.rs index 5b218addb1a..23ec80e66fc 100644 --- a/polkadot/runtime/parachains/src/builder.rs +++ b/polkadot/runtime/parachains/src/builder.rs @@ -39,7 +39,11 @@ use sp_runtime::{ traits::{Header as HeaderT, One, TrailingZeroInput, Zero}, RuntimeAppPublic, }; -use sp_std::{collections::btree_map::BTreeMap, prelude::Vec, vec}; +use sp_std::{ + collections::{btree_map::BTreeMap, vec_deque::VecDeque}, + prelude::Vec, + vec, +}; fn mock_validation_code() -> ValidationCode { ValidationCode(vec![1, 2, 3]) @@ -83,13 +87,18 @@ pub(crate) struct BenchBuilder { /// Optionally set the number of dispute statements for each candidate. dispute_statements: BTreeMap, /// Session index of for each dispute. Index of slice corresponds to a core, - /// which is offset by the number of entries for `backed_and_concluding_cores`. I.E. if - /// `backed_and_concluding_cores` has 3 entries, the first index of `dispute_sessions` + /// which is offset by the number of entries for `backed_and_concluding_paras`. I.E. if + /// `backed_and_concluding_paras` has 3 entries, the first index of `dispute_sessions` /// will correspond to core index 3. There must be one entry for each core with a dispute /// statement set. dispute_sessions: Vec, - /// Map from core seed to number of validity votes. - backed_and_concluding_cores: BTreeMap, + /// Map from para id to number of validity votes. Core indices are generated based on + /// `elastic_paras` configuration. Each para id in `elastic_paras` gets the + /// specified amount of consecutive cores assigned to it. If a para id is not present + /// in `elastic_paras` it get assigned to a single core. + backed_and_concluding_paras: BTreeMap, + /// Map from para id (seed) to number of chained candidates. + elastic_paras: BTreeMap, /// Make every candidate include a code upgrade by setting this to `Some` where the interior /// value is the byte length of the new code. code_upgrade: Option, @@ -106,6 +115,7 @@ pub(crate) struct Bench { pub(crate) _block_number: BlockNumberFor, } +#[allow(dead_code)] impl BenchBuilder { /// Create a new `BenchBuilder` with some opinionated values that should work with the rest /// of the functions in this implementation. @@ -119,7 +129,8 @@ impl BenchBuilder { max_validators: None, dispute_statements: BTreeMap::new(), dispute_sessions: Default::default(), - backed_and_concluding_cores: Default::default(), + backed_and_concluding_paras: Default::default(), + elastic_paras: Default::default(), code_upgrade: None, fill_claimqueue: true, _phantom: sp_std::marker::PhantomData::, @@ -129,7 +140,7 @@ impl BenchBuilder { /// Set the session index for each dispute statement set (in other words, set the session the /// the dispute statement set's relay chain block is from). Indexes of `dispute_sessions` /// correspond to a core, which is offset by the number of entries for - /// `backed_and_concluding_cores`. I.E. if `backed_and_concluding_cores` cores has 3 entries, + /// `backed_and_concluding_paras`. I.E. if `backed_and_concluding_paras` cores has 3 entries, /// the first index of `dispute_sessions` will correspond to core index 3. /// /// Note that there must be an entry for each core with a dispute statement set. @@ -138,12 +149,19 @@ impl BenchBuilder { self } - /// Set a map from core/para id seed to number of validity votes. - pub(crate) fn set_backed_and_concluding_cores( + /// Set a map from para id seed to number of validity votes. + pub(crate) fn set_backed_and_concluding_paras( mut self, - backed_and_concluding_cores: BTreeMap, + backed_and_concluding_paras: BTreeMap, ) -> Self { - self.backed_and_concluding_cores = backed_and_concluding_cores; + self.backed_and_concluding_paras = backed_and_concluding_paras; + self + } + + /// Set a map from para id seed to number of cores assigned to it. + #[cfg(feature = "runtime-benchmarks")] + pub(crate) fn set_elastic_paras(mut self, elastic_paras: BTreeMap) -> Self { + self.elastic_paras = elastic_paras; self } @@ -241,16 +259,6 @@ impl BenchBuilder { (Self::fallback_max_validators() / 2) + 1 } - /// Create para id, core index, and grab the associated group index from the scheduler pallet. - fn create_indexes(&self, seed: u32) -> (ParaId, CoreIndex, GroupIndex) { - let para_id = ParaId::from(seed); - let core_idx = CoreIndex(seed); - let group_idx = - scheduler::Pallet::::group_assigned_to_core(core_idx, self.block_number).unwrap(); - - (para_id, core_idx, group_idx) - } - fn mock_head_data() -> HeadData { let max_head_size = configuration::Pallet::::config().max_head_data_size; HeadData(vec![0xFF; max_head_size as usize]) @@ -321,7 +329,7 @@ impl BenchBuilder { /// Create an `AvailabilityBitfield` where `concluding` is a map where each key is a core index /// that is concluding and `cores` is the total number of cores in the system. - fn availability_bitvec(concluding: &BTreeMap, cores: u32) -> AvailabilityBitfield { + fn availability_bitvec(concluding: &BTreeMap, cores: usize) -> AvailabilityBitfield { let mut bitfields = bitvec::bitvec![u8, bitvec::order::Lsb0; 0; 0]; for i in 0..cores { if concluding.get(&(i as u32)).is_some() { @@ -352,7 +360,7 @@ impl BenchBuilder { /// /// Note that this must be called at least 2 sessions before the target session as there is a /// n+2 session delay for the scheduled actions to take effect. - fn setup_para_ids(cores: u32) { + fn setup_para_ids(cores: usize) { // make sure parachains exist prior to session change. for i in 0..cores { let para_id = ParaId::from(i as u32); @@ -407,7 +415,10 @@ impl BenchBuilder { mut self, target_session: SessionIndex, validators: Vec<(T::AccountId, ValidatorId)>, - total_cores: u32, + // Total cores used in the scenario + total_cores: usize, + // Additional cores for elastic parachains + extra_cores: usize, ) -> Self { let mut block = 1; for session in 0..=target_session { @@ -442,7 +453,8 @@ impl BenchBuilder { self.validators = Some(validators_shuffled); self.block_number = block_number; self.session = target_session; - assert_eq!(paras::Pallet::::parachains().len(), total_cores as usize); + + assert_eq!(paras::Pallet::::parachains().len(), total_cores - extra_cores); self } @@ -453,13 +465,14 @@ impl BenchBuilder { /// to the cores successfully being freed from the candidates being marked as available. fn create_availability_bitfields( &self, - concluding_cores: &BTreeMap, - total_cores: u32, + concluding_paras: &BTreeMap, + elastic_paras: &BTreeMap, + total_cores: usize, ) -> Vec> { let validators = self.validators.as_ref().expect("must have some validators prior to calling"); - let availability_bitvec = Self::availability_bitvec(concluding_cores, total_cores); + let availability_bitvec = Self::availability_bitvec(concluding_paras, total_cores); let bitfields: Vec> = validators .iter() @@ -476,16 +489,27 @@ impl BenchBuilder { }) .collect(); - for (seed, _) in concluding_cores.iter() { + let mut current_core_idx = 0u32; + + for (seed, _) in concluding_paras.iter() { // make sure the candidates that will be concluding are marked as pending availability. - let (para_id, core_idx, group_idx) = self.create_indexes(*seed); - Self::add_availability( - para_id, - core_idx, - group_idx, - Self::validator_availability_votes_yes(validators.len()), - CandidateHash(H256::from(byte32_slice_from(*seed))), - ); + let para_id = ParaId::from(*seed); + + for _chain_idx in 0..elastic_paras.get(&seed).cloned().unwrap_or(1) { + let core_idx = CoreIndex::from(current_core_idx); + let group_idx = + scheduler::Pallet::::group_assigned_to_core(core_idx, self.block_number) + .unwrap(); + + Self::add_availability( + para_id, + core_idx, + group_idx, + Self::validator_availability_votes_yes(validators.len()), + CandidateHash(H256::from(byte32_slice_from(current_core_idx))), + ); + current_core_idx += 1; + } } bitfields @@ -494,112 +518,143 @@ impl BenchBuilder { /// Create backed candidates for `cores_with_backed_candidates`. You need these cores to be /// scheduled _within_ paras inherent, which requires marking the available bitfields as fully /// available. - /// - `cores_with_backed_candidates` Mapping of `para_id`/`core_idx`/`group_idx` seed to number - /// of + /// - `cores_with_backed_candidates` Mapping of `para_id` seed to number of /// validity votes. fn create_backed_candidates( &self, cores_with_backed_candidates: &BTreeMap, + elastic_paras: &BTreeMap, includes_code_upgrade: Option, ) -> Vec> { let validators = self.validators.as_ref().expect("must have some validators prior to calling"); let config = configuration::Pallet::::config(); + let mut current_core_idx = 0u32; cores_with_backed_candidates .iter() - .map(|(seed, num_votes)| { + .flat_map(|(seed, num_votes)| { assert!(*num_votes <= validators.len() as u32); - let (para_id, core_idx, group_idx) = self.create_indexes(*seed); - - // This generates a pair and adds it to the keystore, returning just the public. - let collator_public = CollatorId::generate_pair(None); - let header = Self::header(self.block_number); - let relay_parent = header.hash(); - let head_data = Self::mock_head_data(); - let persisted_validation_data_hash = PersistedValidationData:: { - parent_head: head_data.clone(), - relay_parent_number: self.relay_parent_number(), - relay_parent_storage_root: Default::default(), - max_pov_size: config.max_pov_size, - } - .hash(); - - let pov_hash = Default::default(); - let validation_code_hash = mock_validation_code().hash(); - let payload = collator_signature_payload( - &relay_parent, - ¶_id, - &persisted_validation_data_hash, - &pov_hash, - &validation_code_hash, - ); - let signature = collator_public.sign(&payload).unwrap(); - - // Set the head data so it can be used while validating the signatures on the - // candidate receipt. - paras::Pallet::::heads_insert(¶_id, head_data.clone()); - - let mut past_code_meta = paras::ParaPastCodeMeta::>::default(); - past_code_meta.note_replacement(0u32.into(), 0u32.into()); - - let group_validators = scheduler::Pallet::::group_validators(group_idx).unwrap(); - - let candidate = CommittedCandidateReceipt:: { - descriptor: CandidateDescriptor:: { - para_id, - relay_parent, - collator: collator_public, - persisted_validation_data_hash, - pov_hash, - erasure_root: Default::default(), - signature, - para_head: head_data.hash(), - validation_code_hash, - }, - commitments: CandidateCommitments:: { - upward_messages: Default::default(), - horizontal_messages: Default::default(), - new_validation_code: includes_code_upgrade - .map(|v| ValidationCode(vec![42u8; v as usize])), - head_data, - processed_downward_messages: 0, - hrmp_watermark: self.relay_parent_number(), - }, - }; - - let candidate_hash = candidate.hash(); - - let validity_votes: Vec<_> = group_validators - .iter() - .take(*num_votes as usize) - .map(|val_idx| { - let public = validators.get(*val_idx).unwrap(); - let sig = UncheckedSigned::::benchmark_sign( - public, - CompactStatement::Valid(candidate_hash), - &self.signing_context(), - *val_idx, + + let para_id = ParaId::from(*seed); + let mut prev_head = None; + // How many chained candidates we want to build ? + (0..elastic_paras.get(&seed).cloned().unwrap_or(1)) + .map(|chain_idx| { + let core_idx = CoreIndex::from(current_core_idx); + // Advance core index. + current_core_idx += 1; + let group_idx = scheduler::Pallet::::group_assigned_to_core( + core_idx, + self.block_number, ) - .benchmark_signature(); + .unwrap(); - ValidityAttestation::Explicit(sig.clone()) - }) - .collect(); + // This generates a pair and adds it to the keystore, returning just the + // public. + let collator_public = CollatorId::generate_pair(None); + let header = Self::header(self.block_number); + let relay_parent = header.hash(); - // Check if the elastic scaling bit is set, if so we need to supply the core index - // in the generated candidate. - let core_idx = configuration::Pallet::::config() - .node_features - .get(FeatureIndex::ElasticScalingMVP as usize) - .map(|_the_bit| core_idx); - - BackedCandidate::::new( - candidate, - validity_votes, - bitvec::bitvec![u8, bitvec::order::Lsb0; 1; group_validators.len()], - core_idx, - ) + // Set the head data so it can be used while validating the signatures on + // the candidate receipt. + let mut head_data = Self::mock_head_data(); + + if chain_idx == 0 { + // Only first parahead of the chain needs to be set in storage. + paras::Pallet::::heads_insert(¶_id, head_data.clone()); + } else { + // Make each candidate head data unique to avoid cycles. + head_data.0[0] = chain_idx; + } + + let persisted_validation_data_hash = PersistedValidationData:: { + // To form a chain we set parent head to previous block if any, or + // default to what is in storage already setup. + parent_head: prev_head.take().unwrap_or(head_data.clone()), + relay_parent_number: self.relay_parent_number(), + relay_parent_storage_root: Default::default(), + max_pov_size: config.max_pov_size, + } + .hash(); + + prev_head = Some(head_data.clone()); + + let pov_hash = Default::default(); + let validation_code_hash = mock_validation_code().hash(); + let payload = collator_signature_payload( + &relay_parent, + ¶_id, + &persisted_validation_data_hash, + &pov_hash, + &validation_code_hash, + ); + let signature = collator_public.sign(&payload).unwrap(); + + let mut past_code_meta = + paras::ParaPastCodeMeta::>::default(); + past_code_meta.note_replacement(0u32.into(), 0u32.into()); + + let group_validators = + scheduler::Pallet::::group_validators(group_idx).unwrap(); + + let candidate = CommittedCandidateReceipt:: { + descriptor: CandidateDescriptor:: { + para_id, + relay_parent, + collator: collator_public, + persisted_validation_data_hash, + pov_hash, + erasure_root: Default::default(), + signature, + para_head: head_data.hash(), + validation_code_hash, + }, + commitments: CandidateCommitments:: { + upward_messages: Default::default(), + horizontal_messages: Default::default(), + new_validation_code: includes_code_upgrade + .map(|v| ValidationCode(vec![42u8; v as usize])), + head_data, + processed_downward_messages: 0, + hrmp_watermark: self.relay_parent_number(), + }, + }; + + let candidate_hash = candidate.hash(); + + let validity_votes: Vec<_> = group_validators + .iter() + .take(*num_votes as usize) + .map(|val_idx| { + let public = validators.get(*val_idx).unwrap(); + let sig = UncheckedSigned::::benchmark_sign( + public, + CompactStatement::Valid(candidate_hash), + &self.signing_context(), + *val_idx, + ) + .benchmark_signature(); + + ValidityAttestation::Explicit(sig.clone()) + }) + .collect(); + + // Check if the elastic scaling bit is set, if so we need to supply the core + // index in the generated candidate. + let core_idx = configuration::Pallet::::config() + .node_features + .get(FeatureIndex::ElasticScalingMVP as usize) + .map(|_the_bit| core_idx); + + BackedCandidate::::new( + candidate, + validity_votes, + bitvec::bitvec![u8, bitvec::order::Lsb0; 1; group_validators.len()], + core_idx, + ) + }) + .collect::>() }) .collect() } @@ -616,6 +671,8 @@ impl BenchBuilder { self.validators.as_ref().expect("must have some validators prior to calling"); let dispute_sessions = dispute_sessions.as_ref(); + let mut current_core_idx = start; + (start..last) .map(|seed| { let dispute_session_idx = (seed - start) as usize; @@ -624,7 +681,14 @@ impl BenchBuilder { .cloned() .unwrap_or(self.target_session); - let (para_id, core_idx, group_idx) = self.create_indexes(seed); + let para_id = ParaId::from(seed); + let core_idx = CoreIndex::from(current_core_idx); + current_core_idx +=1; + + let group_idx = + scheduler::Pallet::::group_assigned_to_core(core_idx, self.block_number) + .unwrap(); + let candidate_hash = CandidateHash(H256::from(byte32_slice_from(seed))); let relay_parent = H256::from(byte32_slice_from(seed)); @@ -668,22 +732,29 @@ impl BenchBuilder { /// Build a scenario for testing or benchmarks. /// - /// Note that this API only allows building scenarios where the `backed_and_concluding_cores` + /// Note that this API only allows building scenarios where the `backed_and_concluding_paras` /// are mutually exclusive with the cores for disputes. So - /// `backed_and_concluding_cores.len() + dispute_sessions.len()` must be less than the max + /// `backed_and_concluding_paras.len() + dispute_sessions.len()` must be less than the max /// number of cores. pub(crate) fn build(self) -> Bench { // Make sure relevant storage is cleared. This is just to get the asserts to work when // running tests because it seems the storage is not cleared in between. #[allow(deprecated)] - inclusion::PendingAvailabilityCommitments::::remove_all(None); - #[allow(deprecated)] inclusion::PendingAvailability::::remove_all(None); // We don't allow a core to have both disputes and be marked fully available at this block. - let max_cores = self.max_cores(); + let max_cores = self.max_cores() as usize; + + let extra_cores = self + .elastic_paras + .values() + .map(|count| *count as usize) + .sum::() + .saturating_sub(self.elastic_paras.len() as usize); + let used_cores = - (self.dispute_sessions.len() + self.backed_and_concluding_cores.len()) as u32; + self.dispute_sessions.len() + self.backed_and_concluding_paras.len() + extra_cores; + assert!(used_cores <= max_cores); let fill_claimqueue = self.fill_claimqueue; @@ -691,62 +762,95 @@ impl BenchBuilder { // We are currently in Session 0, so these changes will take effect in Session 2. Self::setup_para_ids(used_cores); configuration::ActiveConfig::::mutate(|c| { - c.scheduler_params.num_cores = used_cores; + c.scheduler_params.num_cores = used_cores as u32; }); let validator_ids = Self::generate_validator_pairs(self.max_validators()); let target_session = SessionIndex::from(self.target_session); - let builder = self.setup_session(target_session, validator_ids, used_cores); + let builder = self.setup_session(target_session, validator_ids, used_cores, extra_cores); - let bitfields = - builder.create_availability_bitfields(&builder.backed_and_concluding_cores, used_cores); - let backed_candidates = builder - .create_backed_candidates(&builder.backed_and_concluding_cores, builder.code_upgrade); + let bitfields = builder.create_availability_bitfields( + &builder.backed_and_concluding_paras, + &builder.elastic_paras, + used_cores, + ); + let backed_candidates = builder.create_backed_candidates( + &builder.backed_and_concluding_paras, + &builder.elastic_paras, + builder.code_upgrade, + ); let disputes = builder.create_disputes( - builder.backed_and_concluding_cores.len() as u32, - used_cores, + builder.backed_and_concluding_paras.len() as u32, + used_cores as u32, builder.dispute_sessions.as_slice(), ); + let mut disputed_cores = (builder.backed_and_concluding_paras.len() as u32.. + used_cores as u32) + .into_iter() + .map(|idx| (idx, 0)) + .collect::>(); + + let mut all_cores = builder.backed_and_concluding_paras.clone(); + all_cores.append(&mut disputed_cores); - assert_eq!( - inclusion::PendingAvailabilityCommitments::::iter().count(), - used_cores as usize, - ); assert_eq!(inclusion::PendingAvailability::::iter().count(), used_cores as usize,); // Mark all the used cores as occupied. We expect that there are - // `backed_and_concluding_cores` that are pending availability and that there are - // `used_cores - backed_and_concluding_cores ` which are about to be disputed. + // `backed_and_concluding_paras` that are pending availability and that there are + // `used_cores - backed_and_concluding_paras ` which are about to be disputed. let now = >::block_number() + One::one(); - let cores = (0..used_cores) - .into_iter() - .map(|i| { - let ttl = configuration::Pallet::::config().scheduler_params.ttl; - // Load an assignment into provider so that one is present to pop - let assignment = ::AssignmentProvider::get_mock_assignment( - CoreIndex(i), - ParaId::from(i), - ); - CoreOccupied::Paras(ParasEntry::new(assignment, now + ttl)) + + let mut core_idx = 0u32; + let elastic_paras = &builder.elastic_paras; + // Assign potentially multiple cores to same parachains, + let cores = all_cores + .iter() + .flat_map(|(para_id, _)| { + (0..elastic_paras.get(¶_id).cloned().unwrap_or(1)) + .map(|_para_local_core_idx| { + let ttl = configuration::Pallet::::config().scheduler_params.ttl; + // Load an assignment into provider so that one is present to pop + let assignment = + ::AssignmentProvider::get_mock_assignment( + CoreIndex(core_idx), + ParaId::from(*para_id), + ); + core_idx += 1; + CoreOccupied::Paras(ParasEntry::new(assignment, now + ttl)) + }) + .collect::>>() }) - .collect(); + .collect::>>(); + scheduler::AvailabilityCores::::set(cores); + + core_idx = 0u32; if fill_claimqueue { - // Add items to claim queue as well: - let cores = (0..used_cores) - .into_iter() - .map(|i| { - let ttl = configuration::Pallet::::config().scheduler_params.ttl; - // Load an assignment into provider so that one is present to pop - let assignment = - ::AssignmentProvider::get_mock_assignment( - CoreIndex(i), - ParaId::from(i), - ); - (CoreIndex(i), [ParasEntry::new(assignment, now + ttl)].into()) + let cores = all_cores + .keys() + .flat_map(|para_id| { + (0..elastic_paras.get(¶_id).cloned().unwrap_or(1)) + .map(|_para_local_core_idx| { + let ttl = configuration::Pallet::::config().scheduler_params.ttl; + // Load an assignment into provider so that one is present to pop + let assignment = + ::AssignmentProvider::get_mock_assignment( + CoreIndex(core_idx), + ParaId::from(*para_id), + ); + + let entry = ( + CoreIndex(core_idx), + [ParasEntry::new(assignment, now + ttl)].into(), + ); + core_idx += 1; + entry + }) + .collect::>)>>() }) - .collect(); + .collect::>>>(); + scheduler::ClaimQueue::::set(cores); } diff --git a/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs b/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs index ad3fa8e0dc7..f3365945758 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs @@ -65,7 +65,7 @@ benchmarks! { .collect(); let scenario = BenchBuilder::::new() - .set_backed_and_concluding_cores(cores_with_backed) + .set_backed_and_concluding_paras(cores_with_backed) .build(); let mut benchmark = scenario.data.clone(); @@ -110,7 +110,7 @@ benchmarks! { .collect(); let scenario = BenchBuilder::::new() - .set_backed_and_concluding_cores(cores_with_backed.clone()) + .set_backed_and_concluding_paras(cores_with_backed.clone()) .build(); let mut benchmark = scenario.data.clone(); @@ -165,7 +165,7 @@ benchmarks! { .collect(); let scenario = BenchBuilder::::new() - .set_backed_and_concluding_cores(cores_with_backed.clone()) + .set_backed_and_concluding_paras(cores_with_backed.clone()) .set_code_upgrade(v) .build(); diff --git a/polkadot/runtime/parachains/src/paras_inherent/tests.rs b/polkadot/runtime/parachains/src/paras_inherent/tests.rs index fb4d1bd2226..41a84175e9a 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/tests.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/tests.rs @@ -64,7 +64,7 @@ mod enter { ) .set_max_validators_per_core(num_validators_per_core) .set_dispute_statements(dispute_statements) - .set_backed_and_concluding_cores(backed_and_concluding) + .set_backed_and_concluding_paras(backed_and_concluding) .set_dispute_sessions(&dispute_sessions[..]) .set_fill_claimqueue(fill_claimqueue); -- GitLab From e8b51f60cce43277301a68d2a69c1bb914853290 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Fri, 15 Mar 2024 18:24:38 +0100 Subject: [PATCH 125/188] Contracts use polkavm workspace deps (#3715) --- Cargo.lock | 61 +++---------------- substrate/frame/contracts/fixtures/Cargo.toml | 2 +- substrate/frame/contracts/fixtures/build.rs | 7 ++- .../frame/contracts/fixtures/build/Cargo.toml | 4 +- substrate/frame/contracts/uapi/Cargo.toml | 2 +- 5 files changed, 19 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1bd596a7a9..699fd35a824 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9573,7 +9573,7 @@ dependencies = [ "anyhow", "frame-system", "parity-wasm", - "polkavm-linker 0.5.0", + "polkavm-linker", "sp-runtime", "tempfile", "toml 0.8.8", @@ -9634,7 +9634,7 @@ dependencies = [ "bitflags 1.3.2", "parity-scale-codec", "paste", - "polkavm-derive 0.5.0", + "polkavm-derive", "scale-info", ] @@ -13845,7 +13845,7 @@ dependencies = [ "libc", "log", "polkavm-assembler", - "polkavm-common 0.9.0", + "polkavm-common", "polkavm-linux-raw", ] @@ -13858,12 +13858,6 @@ dependencies = [ "log", ] -[[package]] -name = "polkavm-common" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b4e215c80fe876147f3d58158d5dfeae7dabdd6047e175af77095b78d0035c" - [[package]] name = "polkavm-common" version = "0.9.0" @@ -13873,16 +13867,6 @@ dependencies = [ "log", ] -[[package]] -name = "polkavm-derive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6380dbe1fb03ecc74ad55d841cfc75480222d153ba69ddcb00977866cbdabdb8" -dependencies = [ - "polkavm-derive-impl 0.5.0", - "syn 2.0.50", -] - [[package]] name = "polkavm-derive" version = "0.9.1" @@ -13892,25 +13876,13 @@ dependencies = [ "polkavm-derive-impl-macro", ] -[[package]] -name = "polkavm-derive-impl" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc8211b3365bbafb2fb32057d68b0e1ca55d079f5cf6f9da9b98079b94b3987d" -dependencies = [ - "polkavm-common 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.50", -] - [[package]] name = "polkavm-derive-impl" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" dependencies = [ - "polkavm-common 0.9.0", + "polkavm-common", "proc-macro2", "quote", "syn 2.0.50", @@ -13922,25 +13894,10 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" dependencies = [ - "polkavm-derive-impl 0.9.0", + "polkavm-derive-impl", "syn 2.0.50", ] -[[package]] -name = "polkavm-linker" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5a668bb33c7f0b5f4ca91adb1e1e71cf4930fef5e6909f46c2180d65cce37d0" -dependencies = [ - "gimli 0.28.0", - "hashbrown 0.14.3", - "log", - "object 0.32.2", - "polkavm-common 0.5.0", - "regalloc2 0.9.3", - "rustc-demangle", -] - [[package]] name = "polkavm-linker" version = "0.9.2" @@ -13951,7 +13908,7 @@ dependencies = [ "hashbrown 0.14.3", "log", "object 0.32.2", - "polkavm-common 0.9.0", + "polkavm-common", "regalloc2 0.9.3", "rustc-demangle", ] @@ -18855,7 +18812,7 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", - "polkavm-derive 0.9.1", + "polkavm-derive", "rustversion", "secp256k1", "sp-core", @@ -19047,7 +19004,7 @@ dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive 0.9.1", + "polkavm-derive", "primitive-types", "rustversion", "sp-core", @@ -20069,7 +20026,7 @@ dependencies = [ "console", "filetime", "parity-wasm", - "polkavm-linker 0.9.2", + "polkavm-linker", "sp-maybe-compressed-blob", "strum 0.24.1", "tempfile", diff --git a/substrate/frame/contracts/fixtures/Cargo.toml b/substrate/frame/contracts/fixtures/Cargo.toml index 9ca9e404c31..5ac140cd91b 100644 --- a/substrate/frame/contracts/fixtures/Cargo.toml +++ b/substrate/frame/contracts/fixtures/Cargo.toml @@ -20,7 +20,7 @@ parity-wasm = "0.45.0" tempfile = "3.8.1" toml = "0.8.2" twox-hash = "1.6.3" -polkavm-linker = { version = "0.5.0", optional = true } +polkavm-linker = { workspace = true, optional = true } anyhow = "1.0.0" [features] diff --git a/substrate/frame/contracts/fixtures/build.rs b/substrate/frame/contracts/fixtures/build.rs index 12a7805294b..19aff37c160 100644 --- a/substrate/frame/contracts/fixtures/build.rs +++ b/substrate/frame/contracts/fixtures/build.rs @@ -121,9 +121,11 @@ fn collect_entries(contracts_dir: &Path, out_dir: &Path) -> Vec { /// Create a `Cargo.toml` to compile the given contract entries. fn create_cargo_toml<'a>( fixtures_dir: &Path, + root_cargo_toml: &Path, entries: impl Iterator, output_dir: &Path, ) -> Result<()> { + let root_toml: toml::Value = toml::from_str(&fs::read_to_string(root_cargo_toml)?)?; let mut cargo_toml: toml::Value = toml::from_str(include_str!("./build/Cargo.toml"))?; let mut set_dep = |name, path| -> Result<()> { cargo_toml["dependencies"][name]["path"] = toml::Value::String( @@ -133,6 +135,8 @@ fn create_cargo_toml<'a>( }; set_dep("uapi", "../uapi")?; set_dep("common", "./contracts/common")?; + cargo_toml["dependencies"]["polkavm-derive"]["version"] = + root_toml["workspace"]["dependencies"]["polkavm-derive"].clone(); cargo_toml["bin"] = toml::Value::Array( entries @@ -324,6 +328,7 @@ fn main() -> Result<()> { let contracts_dir = fixtures_dir.join("contracts"); let out_dir: PathBuf = env::var("OUT_DIR")?.into(); let workspace_root = find_workspace_root(&fixtures_dir).expect("workspace root exists; qed"); + let root_cargo_toml = workspace_root.join("Cargo.toml"); let entries = collect_entries(&contracts_dir, &out_dir); if entries.is_empty() { @@ -333,7 +338,7 @@ fn main() -> Result<()> { let tmp_dir = tempfile::tempdir()?; let tmp_dir_path = tmp_dir.path(); - create_cargo_toml(&fixtures_dir, entries.iter(), tmp_dir.path())?; + create_cargo_toml(&fixtures_dir, &root_cargo_toml, entries.iter(), tmp_dir.path())?; invoke_cargo_fmt( &workspace_root.join(".rustfmt.toml"), entries.iter().map(|entry| &entry.path as _), diff --git a/substrate/frame/contracts/fixtures/build/Cargo.toml b/substrate/frame/contracts/fixtures/build/Cargo.toml index d524dbff1ce..ba487a2bb5c 100644 --- a/substrate/frame/contracts/fixtures/build/Cargo.toml +++ b/substrate/frame/contracts/fixtures/build/Cargo.toml @@ -6,11 +6,11 @@ edition = "2021" # Binary targets are injected dynamically by the build script. [[bin]] -# local path are injected dynamically by the build script. +# All paths or versions are injected dynamically by the build script. [dependencies] uapi = { package = 'pallet-contracts-uapi', path = "", default-features = false } common = { package = 'pallet-contracts-fixtures-common', path = "" } -polkavm-derive = '0.5.0' +polkavm-derive = { version = "" } [profile.release] opt-level = 3 diff --git a/substrate/frame/contracts/uapi/Cargo.toml b/substrate/frame/contracts/uapi/Cargo.toml index a5081af2a2d..12bb6b8fc2c 100644 --- a/substrate/frame/contracts/uapi/Cargo.toml +++ b/substrate/frame/contracts/uapi/Cargo.toml @@ -21,7 +21,7 @@ scale = { package = "parity-scale-codec", version = "3.6.1", default-features = ], optional = true } [target.'cfg(target_arch = "riscv32")'.dependencies] -polkavm-derive = '0.5.0' +polkavm-derive = { workspace = true } [package.metadata.docs.rs] default-target = ["wasm32-unknown-unknown"] -- GitLab From 02e1a7f476d7d7c67153e975ab9a1bdc02ffea12 Mon Sep 17 00:00:00 2001 From: ordian Date: Fri, 15 Mar 2024 20:43:28 +0100 Subject: [PATCH 126/188] collator protocol changes for elastic scaling (validator side) (#3302) Fixes #3128. This introduces a new variant for the collation response from the collator that includes the parent head data. For now, collators won't send this new variant. We'll need to change the collator side of the collator protocol to detect all the cores assigned to a para and send the parent head data in the case when it's more than 1 core. - [x] validate approach - [x] check head data hash --- polkadot/node/collation-generation/src/lib.rs | 8 +- .../node/collation-generation/src/tests.rs | 33 ++--- .../core/prospective-parachains/src/lib.rs | 17 ++- .../core/prospective-parachains/src/tests.rs | 4 +- .../src/collator_side/collation.rs | 4 +- .../src/collator_side/mod.rs | 65 +++++++--- .../src/collator_side/tests/mod.rs | 62 +++++---- .../tests/prospective_parachains.rs | 32 ++--- .../network/collator-protocol/src/error.rs | 10 +- .../src/validator_side/collation.rs | 13 +- .../src/validator_side/mod.rs | 86 ++++++++++--- .../tests/prospective_parachains.rs | 120 ++++++++++++++++++ .../protocol/src/request_response/mod.rs | 2 +- .../protocol/src/request_response/v1.rs | 15 ++- polkadot/node/subsystem-types/src/messages.rs | 53 +++++--- prdoc/pr_3302.prdoc | 15 +++ 16 files changed, 406 insertions(+), 133 deletions(-) create mode 100644 prdoc/pr_3302.prdoc diff --git a/polkadot/node/collation-generation/src/lib.rs b/polkadot/node/collation-generation/src/lib.rs index cfa75d7b441..a89351628a0 100644 --- a/polkadot/node/collation-generation/src/lib.rs +++ b/polkadot/node/collation-generation/src/lib.rs @@ -466,6 +466,7 @@ async fn construct_and_distribute_receipt( } = collation; let persisted_validation_data_hash = validation_data.hash(); + let parent_head_data = validation_data.parent_head.clone(); let parent_head_data_hash = validation_data.parent_head.hash(); // Apply compression to the block data. @@ -551,12 +552,13 @@ async fn construct_and_distribute_receipt( metrics.on_collation_generated(); sender - .send_message(CollatorProtocolMessage::DistributeCollation( - ccr, + .send_message(CollatorProtocolMessage::DistributeCollation { + candidate_receipt: ccr, parent_head_data_hash, pov, + parent_head_data, result_sender, - )) + }) .await; } diff --git a/polkadot/node/collation-generation/src/tests.rs b/polkadot/node/collation-generation/src/tests.rs index 9094f40cca8..eb0ede6ef6b 100644 --- a/polkadot/node/collation-generation/src/tests.rs +++ b/polkadot/node/collation-generation/src/tests.rs @@ -390,11 +390,11 @@ fn sends_distribute_collation_message() { assert_eq!(to_collator_protocol.len(), 1); match AllMessages::from(to_collator_protocol.pop().unwrap()) { - AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation( - CandidateReceipt { descriptor, .. }, - _pov, - .., - )) => { + AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation { + candidate_receipt, + .. + }) => { + let CandidateReceipt { descriptor, .. } = candidate_receipt; // signature generation is non-deterministic, so we can't just assert that the // expected descriptor is correct. What we can do is validate that the produced // descriptor has a valid signature, then just copy in the generated signature @@ -529,11 +529,11 @@ fn fallback_when_no_validation_code_hash_api() { assert_eq!(to_collator_protocol.len(), 1); match &to_collator_protocol[0] { - AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation( - CandidateReceipt { descriptor, .. }, - _pov, - .., - )) => { + AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation { + candidate_receipt, + .. + }) => { + let CandidateReceipt { descriptor, .. } = candidate_receipt; assert_eq!(expect_validation_code_hash, descriptor.validation_code_hash); }, _ => panic!("received wrong message type"), @@ -619,15 +619,16 @@ fn submit_collation_leads_to_distribution() { assert_matches!( overseer_recv(&mut virtual_overseer).await, - AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation( - ccr, + AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation { + candidate_receipt, parent_head_data_hash, .. - )) => { + }) => { + let CandidateReceipt { descriptor, .. } = candidate_receipt; assert_eq!(parent_head_data_hash, parent_head.hash()); - assert_eq!(ccr.descriptor().persisted_validation_data_hash, expected_pvd.hash()); - assert_eq!(ccr.descriptor().para_head, dummy_head_data().hash()); - assert_eq!(ccr.descriptor().validation_code_hash, validation_code_hash); + assert_eq!(descriptor.persisted_validation_data_hash, expected_pvd.hash()); + assert_eq!(descriptor.para_head, dummy_head_data().hash()); + assert_eq!(descriptor.validation_code_hash, validation_code_hash); } ); diff --git a/polkadot/node/core/prospective-parachains/src/lib.rs b/polkadot/node/core/prospective-parachains/src/lib.rs index 2b14e09b4fb..f5d50fb74fa 100644 --- a/polkadot/node/core/prospective-parachains/src/lib.rs +++ b/polkadot/node/core/prospective-parachains/src/lib.rs @@ -36,8 +36,9 @@ use futures::{channel::oneshot, prelude::*}; use polkadot_node_subsystem::{ messages::{ Ancestors, ChainApiMessage, FragmentTreeMembership, HypotheticalCandidate, - HypotheticalFrontierRequest, IntroduceCandidateRequest, ProspectiveParachainsMessage, - ProspectiveValidationDataRequest, RuntimeApiMessage, RuntimeApiRequest, + HypotheticalFrontierRequest, IntroduceCandidateRequest, ParentHeadData, + ProspectiveParachainsMessage, ProspectiveValidationDataRequest, RuntimeApiMessage, + RuntimeApiRequest, }, overseer, ActiveLeavesUpdate, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, }; @@ -764,8 +765,14 @@ fn answer_prospective_validation_data_request( Some(s) => s, }; - let mut head_data = - storage.head_data_by_hash(&request.parent_head_data_hash).map(|x| x.clone()); + let (mut head_data, parent_head_data_hash) = match request.parent_head_data { + ParentHeadData::OnlyHash(parent_head_data_hash) => ( + storage.head_data_by_hash(&parent_head_data_hash).map(|x| x.clone()), + parent_head_data_hash, + ), + ParentHeadData::WithData { head_data, hash } => (Some(head_data), hash), + }; + let mut relay_parent_info = None; let mut max_pov_size = None; @@ -783,7 +790,7 @@ fn answer_prospective_validation_data_request( } if head_data.is_none() { let required_parent = &fragment_tree.scope().base_constraints().required_parent; - if required_parent.hash() == request.parent_head_data_hash { + if required_parent.hash() == parent_head_data_hash { head_data = Some(required_parent.clone()); } } diff --git a/polkadot/node/core/prospective-parachains/src/tests.rs b/polkadot/node/core/prospective-parachains/src/tests.rs index 0beddbf1416..0e0079c02bb 100644 --- a/polkadot/node/core/prospective-parachains/src/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/tests.rs @@ -19,7 +19,7 @@ use assert_matches::assert_matches; use polkadot_node_subsystem::{ errors::RuntimeApiError, messages::{ - AllMessages, HypotheticalFrontierRequest, ProspectiveParachainsMessage, + AllMessages, HypotheticalFrontierRequest, ParentHeadData, ProspectiveParachainsMessage, ProspectiveValidationDataRequest, }, }; @@ -468,7 +468,7 @@ async fn get_pvd( let request = ProspectiveValidationDataRequest { para_id, candidate_relay_parent, - parent_head_data_hash: parent_head_data.hash(), + parent_head_data: ParentHeadData::OnlyHash(parent_head_data.hash()), }; let (tx, rx) = oneshot::channel(); virtual_overseer diff --git a/polkadot/node/network/collator-protocol/src/collator_side/collation.rs b/polkadot/node/network/collator-protocol/src/collator_side/collation.rs index 53f947142d1..dc1ee725462 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/collation.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/collation.rs @@ -27,7 +27,7 @@ use polkadot_node_network_protocol::{ PeerId, }; use polkadot_node_primitives::PoV; -use polkadot_primitives::{CandidateHash, CandidateReceipt, Hash, Id as ParaId}; +use polkadot_primitives::{CandidateHash, CandidateReceipt, Hash, HeadData, Id as ParaId}; /// The status of a collation as seen from the collator. pub enum CollationStatus { @@ -63,6 +63,8 @@ pub struct Collation { pub parent_head_data_hash: Hash, /// Proof to verify the state transition of the parachain. pub pov: PoV, + /// Parent head-data needed for elastic scaling. + pub parent_head_data: HeadData, /// Collation status. pub status: CollationStatus, } diff --git a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs index 8fb0bb21544..19cc1eb1a57 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs @@ -55,7 +55,7 @@ use polkadot_node_subsystem_util::{ }; use polkadot_primitives::{ AuthorityDiscoveryId, CandidateHash, CandidateReceipt, CollatorPair, CoreIndex, CoreState, - GroupIndex, Hash, Id as ParaId, SessionIndex, + GroupIndex, Hash, HeadData, Id as ParaId, SessionIndex, }; use super::LOG_TARGET; @@ -347,6 +347,7 @@ async fn distribute_collation( receipt: CandidateReceipt, parent_head_data_hash: Hash, pov: PoV, + parent_head_data: HeadData, result_sender: Option>, ) -> Result<()> { let candidate_relay_parent = receipt.descriptor.relay_parent; @@ -465,7 +466,13 @@ async fn distribute_collation( per_relay_parent.collations.insert( candidate_hash, - Collation { receipt, parent_head_data_hash, pov, status: CollationStatus::Created }, + Collation { + receipt, + parent_head_data_hash, + pov, + parent_head_data, + status: CollationStatus::Created, + }, ); // If prospective parachains are disabled, a leaf should be known to peer. @@ -763,20 +770,26 @@ async fn process_msg( CollateOn(id) => { state.collating_on = Some(id); }, - DistributeCollation(receipt, parent_head_data_hash, pov, result_sender) => { + DistributeCollation { + candidate_receipt, + parent_head_data_hash, + pov, + parent_head_data, + result_sender, + } => { let _span1 = state .span_per_relay_parent - .get(&receipt.descriptor.relay_parent) + .get(&candidate_receipt.descriptor.relay_parent) .map(|s| s.child("distributing-collation")); let _span2 = jaeger::Span::new(&pov, "distributing-collation"); match state.collating_on { - Some(id) if receipt.descriptor.para_id != id => { + Some(id) if candidate_receipt.descriptor.para_id != id => { // If the ParaId of a collation requested to be distributed does not match // the one we expect, we ignore the message. gum::warn!( target: LOG_TARGET, - para_id = %receipt.descriptor.para_id, + para_id = %candidate_receipt.descriptor.para_id, collating_on = %id, "DistributeCollation for unexpected para_id", ); @@ -788,9 +801,10 @@ async fn process_msg( runtime, state, id, - receipt, + candidate_receipt, parent_head_data_hash, pov, + parent_head_data, result_sender, ) .await?; @@ -798,7 +812,7 @@ async fn process_msg( None => { gum::warn!( target: LOG_TARGET, - para_id = %receipt.descriptor.para_id, + para_id = %candidate_receipt.descriptor.para_id, "DistributeCollation message while not collating on any", ); }, @@ -835,6 +849,7 @@ async fn send_collation( request: VersionedCollationRequest, receipt: CandidateReceipt, pov: PoV, + _parent_head_data: HeadData, ) { let (tx, rx) = oneshot::channel(); @@ -842,13 +857,22 @@ async fn send_collation( let peer_id = request.peer_id(); let candidate_hash = receipt.hash(); - // The response payload is the same for both versions of protocol + // The response payload is the same for v1 and v2 versions of protocol // and doesn't have v2 alias for simplicity. - let response = OutgoingResponse { - result: Ok(request_v1::CollationFetchingResponse::Collation(receipt, pov)), - reputation_changes: Vec::new(), - sent_feedback: Some(tx), - }; + // For now, we don't send parent head data to the collation requester. + let result = + // if assigned_multiple_cores { + // Ok(request_v1::CollationFetchingResponse::CollationWithParentHeadData { + // receipt, + // pov, + // parent_head_data, + // }) + // } else { + Ok(request_v1::CollationFetchingResponse::Collation(receipt, pov)) + // } + ; + let response = + OutgoingResponse { result, reputation_changes: Vec::new(), sent_feedback: Some(tx) }; if let Err(_) = request.send_outgoing_response(response) { gum::warn!(target: LOG_TARGET, "Sending collation response failed"); @@ -1027,9 +1051,13 @@ async fn handle_incoming_request( return Ok(()) }, }; - let (receipt, pov) = if let Some(collation) = collation { + let (receipt, pov, parent_head_data) = if let Some(collation) = collation { collation.status.advance_to_requested(); - (collation.receipt.clone(), collation.pov.clone()) + ( + collation.receipt.clone(), + collation.pov.clone(), + collation.parent_head_data.clone(), + ) } else { gum::warn!( target: LOG_TARGET, @@ -1068,7 +1096,7 @@ async fn handle_incoming_request( waiting.collation_fetch_active = true; // Obtain a timer for sending collation let _ = state.metrics.time_collation_distribution("send"); - send_collation(state, req, receipt, pov).await; + send_collation(state, req, receipt, pov, parent_head_data).await; } }, Some(our_para_id) => { @@ -1453,8 +1481,9 @@ async fn run_inner( if let Some(collation) = next_collation { let receipt = collation.receipt.clone(); let pov = collation.pov.clone(); + let parent_head_data = collation.parent_head_data.clone(); - send_collation(&mut state, next, receipt, pov).await; + send_collation(&mut state, next, receipt, pov, parent_head_data).await; } }, (candidate_hash, peer_id) = state.advertisement_timeouts.select_next_some() => { diff --git a/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs index 1b1194c7270..beda941d37a 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs @@ -356,12 +356,13 @@ async fn distribute_collation_with_receipt( ) -> DistributeCollation { overseer_send( virtual_overseer, - CollatorProtocolMessage::DistributeCollation( - candidate.clone(), + CollatorProtocolMessage::DistributeCollation { + candidate_receipt: candidate.clone(), parent_head_data_hash, - pov.clone(), - None, - ), + pov: pov.clone(), + parent_head_data: HeadData(vec![1, 2, 3]), + result_sender: None, + }, ) .await; @@ -627,6 +628,18 @@ async fn send_peer_view_change( .await; } +fn decode_collation_response(bytes: &[u8]) -> (CandidateReceipt, PoV) { + let response: request_v1::CollationFetchingResponse = + request_v1::CollationFetchingResponse::decode(&mut &bytes[..]) + .expect("Decoding should work"); + match response { + request_v1::CollationFetchingResponse::Collation(receipt, pov) => (receipt, pov), + request_v1::CollationFetchingResponse::CollationWithParentHeadData { + receipt, pov, .. + } => (receipt, pov), + } +} + #[test] fn advertise_and_send_collation() { let mut test_state = TestState::default(); @@ -736,12 +749,10 @@ fn advertise_and_send_collation() { assert_matches!( rx.await, Ok(full_response) => { - let request_v1::CollationFetchingResponse::Collation(receipt, pov): request_v1::CollationFetchingResponse - = request_v1::CollationFetchingResponse::decode( - &mut full_response.result - .expect("We should have a proper answer").as_ref() - ) - .expect("Decoding should work"); + let (receipt, pov) = decode_collation_response( + full_response.result + .expect("We should have a proper answer").as_ref() + ); assert_eq!(receipt, candidate); assert_eq!(pov, pov_block); } @@ -1338,12 +1349,10 @@ where let feedback_tx = assert_matches!( rx.await, Ok(full_response) => { - let request_v1::CollationFetchingResponse::Collation(receipt, pov): request_v1::CollationFetchingResponse - = request_v1::CollationFetchingResponse::decode( - &mut full_response.result - .expect("We should have a proper answer").as_ref() - ) - .expect("Decoding should work"); + let (receipt, pov) = decode_collation_response( + full_response.result + .expect("We should have a proper answer").as_ref() + ); assert_eq!(receipt, candidate); assert_eq!(pov, pov_block); @@ -1375,12 +1384,10 @@ where assert_matches!( rx.await, Ok(full_response) => { - let request_v1::CollationFetchingResponse::Collation(receipt, pov): request_v1::CollationFetchingResponse - = request_v1::CollationFetchingResponse::decode( - &mut full_response.result - .expect("We should have a proper answer").as_ref() - ) - .expect("Decoding should work"); + let (receipt, pov) = decode_collation_response( + full_response.result + .expect("We should have a proper answer").as_ref() + ); assert_eq!(receipt, candidate); assert_eq!(pov, pov_block); @@ -1469,11 +1476,10 @@ fn connect_to_buffered_groups() { assert_matches!( rx.await, Ok(full_response) => { - let request_v1::CollationFetchingResponse::Collation(..) = - request_v1::CollationFetchingResponse::decode( - &mut full_response.result.expect("We should have a proper answer").as_ref(), - ) - .expect("Decoding should work"); + let _ = decode_collation_response( + full_response.result + .expect("We should have a proper answer").as_ref() + ); } ); diff --git a/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs b/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs index fd9d7a746eb..2bb7002a4f4 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs @@ -271,12 +271,13 @@ fn distribute_collation_from_implicit_view() { .build(); overseer_send( virtual_overseer, - CollatorProtocolMessage::DistributeCollation( - candidate.clone(), + CollatorProtocolMessage::DistributeCollation { + candidate_receipt: candidate.clone(), parent_head_data_hash, - pov.clone(), - None, - ), + pov: pov.clone(), + parent_head_data: HeadData(vec![1, 2, 3]), + result_sender: None, + }, ) .await; @@ -351,12 +352,13 @@ fn distribute_collation_up_to_limit() { .build(); overseer_send( virtual_overseer, - CollatorProtocolMessage::DistributeCollation( - candidate.clone(), + CollatorProtocolMessage::DistributeCollation { + candidate_receipt: candidate.clone(), parent_head_data_hash, - pov.clone(), - None, - ), + pov: pov.clone(), + parent_head_data: HeadData(vec![1, 2, 3]), + result_sender: None, + }, ) .await; @@ -469,12 +471,10 @@ fn advertise_and_send_collation_by_hash() { rx.await, Ok(full_response) => { // Response is the same for v2. - let request_v1::CollationFetchingResponse::Collation(receipt, pov): request_v1::CollationFetchingResponse - = request_v1::CollationFetchingResponse::decode( - &mut full_response.result - .expect("We should have a proper answer").as_ref() - ) - .expect("Decoding should work"); + let (receipt, pov) = decode_collation_response( + full_response.result + .expect("We should have a proper answer").as_ref() + ); assert_eq!(receipt, candidate); assert_eq!(pov, pov_block); } diff --git a/polkadot/node/network/collator-protocol/src/error.rs b/polkadot/node/network/collator-protocol/src/error.rs index 9348198e708..0f5e0699d85 100644 --- a/polkadot/node/network/collator-protocol/src/error.rs +++ b/polkadot/node/network/collator-protocol/src/error.rs @@ -89,13 +89,21 @@ pub enum SecondingError { #[error("Received duplicate collation from the peer")] Duplicate, + + #[error("The provided parent head data does not match the hash")] + ParentHeadDataMismatch, } impl SecondingError { /// Returns true if an error indicates that a peer is malicious. pub fn is_malicious(&self) -> bool { use SecondingError::*; - matches!(self, PersistedValidationDataMismatch | CandidateHashMismatch | Duplicate) + matches!( + self, + PersistedValidationDataMismatch | + CandidateHashMismatch | + Duplicate | ParentHeadDataMismatch + ) } } diff --git a/polkadot/node/network/collator-protocol/src/validator_side/collation.rs b/polkadot/node/network/collator-protocol/src/validator_side/collation.rs index d6f34fc81b8..8c3889a3554 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/collation.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/collation.rs @@ -41,7 +41,8 @@ use polkadot_node_subsystem_util::{ metrics::prometheus::prometheus::HistogramTimer, runtime::ProspectiveParachainsMode, }; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, CollatorId, Hash, Id as ParaId, PersistedValidationData, + CandidateHash, CandidateReceipt, CollatorId, Hash, HeadData, Id as ParaId, + PersistedValidationData, }; use tokio_util::sync::CancellationToken; @@ -120,7 +121,7 @@ impl PendingCollation { } } -/// v2 advertisement that was rejected by the backing +/// v2 or v3 advertisement that was rejected by the backing /// subsystem. Validator may fetch it later if its fragment /// membership gets recognized before relay parent goes out of view. #[derive(Debug, Clone)] @@ -143,6 +144,7 @@ pub fn fetched_collation_sanity_check( advertised: &PendingCollation, fetched: &CandidateReceipt, persisted_validation_data: &PersistedValidationData, + maybe_parent_head_and_hash: Option<(HeadData, Hash)>, ) -> Result<(), SecondingError> { if persisted_validation_data.hash() != fetched.descriptor().persisted_validation_data_hash { Err(SecondingError::PersistedValidationDataMismatch) @@ -151,6 +153,8 @@ pub fn fetched_collation_sanity_check( .map_or(false, |pc| pc.candidate_hash() != fetched.hash()) { Err(SecondingError::CandidateHashMismatch) + } else if maybe_parent_head_and_hash.map_or(false, |(head, hash)| head.hash() != hash) { + Err(SecondingError::ParentHeadDataMismatch) } else { Ok(()) } @@ -176,6 +180,9 @@ pub struct PendingCollationFetch { pub candidate_receipt: CandidateReceipt, /// Proof of validity. pub pov: PoV, + /// Optional parachain parent head data. + /// Only needed for elastic scaling. + pub maybe_parent_head_data: Option, } /// The status of the collations in [`CollationsPerRelayParent`]. @@ -359,7 +366,7 @@ impl Future for CollationFetchRequest { }); match &res { - Poll::Ready((_, Ok(request_v1::CollationFetchingResponse::Collation(..)))) => { + Poll::Ready((_, Ok(_))) => { self.span.as_mut().map(|s| s.add_string_tag("success", "true")); }, Poll::Ready((_, Err(_))) => { diff --git a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs index a1b93fff348..d23279e8754 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs @@ -44,7 +44,7 @@ use polkadot_node_subsystem::{ jaeger, messages::{ CanSecondRequest, CandidateBackingMessage, CollatorProtocolMessage, IfDisconnected, - NetworkBridgeEvent, NetworkBridgeTxMessage, ProspectiveParachainsMessage, + NetworkBridgeEvent, NetworkBridgeTxMessage, ParentHeadData, ProspectiveParachainsMessage, ProspectiveValidationDataRequest, }, overseer, CollatorProtocolSenderTrait, FromOrchestra, OverseerSignal, PerLeafSpan, @@ -55,7 +55,7 @@ use polkadot_node_subsystem_util::{ runtime::{prospective_parachains_mode, ProspectiveParachainsMode}, }; use polkadot_primitives::{ - CandidateHash, CollatorId, CoreState, Hash, Id as ParaId, OccupiedCoreAssumption, + CandidateHash, CollatorId, CoreState, Hash, HeadData, Id as ParaId, OccupiedCoreAssumption, PersistedValidationData, }; @@ -723,7 +723,7 @@ async fn request_collation( pending_collation, collator_id: collator_id.clone(), collator_protocol_version: peer_protocol_version, - from_collator: response_recv.boxed(), + from_collator: response_recv, cancellation_token: cancellation_token.clone(), span: state .span_per_relay_parent @@ -889,16 +889,16 @@ async fn process_incoming_peer_message( modify_reputation(&mut state.reputation, ctx.sender(), origin, rep).await; } }, - Versioned::V2(V2::AdvertiseCollation { + Versioned::V3(V2::AdvertiseCollation { relay_parent, candidate_hash, parent_head_data_hash, }) | - Versioned::V3(V2::AdvertiseCollation { + Versioned::V2(V2::AdvertiseCollation { relay_parent, candidate_hash, parent_head_data_hash, - }) => + }) => { if let Err(err) = handle_advertisement( ctx.sender(), state, @@ -920,7 +920,8 @@ async fn process_incoming_peer_message( if let Some(rep) = err.reputation_changes() { modify_reputation(&mut state.reputation, ctx.sender(), origin, rep).await; } - }, + } + }, Versioned::V1(V1::CollationSeconded(..)) | Versioned::V2(V2::CollationSeconded(..)) | Versioned::V3(V2::CollationSeconded(..)) => { @@ -1477,7 +1478,7 @@ async fn process_msg( "CollateOn message is not expected on the validator side of the protocol", ); }, - DistributeCollation(..) => { + DistributeCollation { .. } => { gum::warn!( target: LOG_TARGET, "DistributeCollation message is not expected on the validator side of the protocol", @@ -1776,14 +1777,21 @@ async fn request_prospective_validation_data( candidate_relay_parent: Hash, parent_head_data_hash: Hash, para_id: ParaId, + maybe_parent_head_data: Option, ) -> std::result::Result, SecondingError> where Sender: CollatorProtocolSenderTrait, { let (tx, rx) = oneshot::channel(); + let parent_head_data = if let Some(head_data) = maybe_parent_head_data { + ParentHeadData::WithData { head_data, hash: parent_head_data_hash } + } else { + ParentHeadData::OnlyHash(parent_head_data_hash) + }; + let request = - ProspectiveValidationDataRequest { para_id, candidate_relay_parent, parent_head_data_hash }; + ProspectiveValidationDataRequest { para_id, candidate_relay_parent, parent_head_data }; sender .send_message(ProspectiveParachainsMessage::GetProspectiveValidationData(request, tx)) @@ -1797,7 +1805,7 @@ where async fn kick_off_seconding( ctx: &mut Context, state: &mut State, - PendingCollationFetch { mut collation_event, candidate_receipt, pov }: PendingCollationFetch, + PendingCollationFetch { mut collation_event, candidate_receipt, pov, maybe_parent_head_data }: PendingCollationFetch, ) -> std::result::Result<(), SecondingError> { let pending_collation = collation_event.pending_collation; let relay_parent = pending_collation.relay_parent; @@ -1821,38 +1829,46 @@ async fn kick_off_seconding( collation_event.pending_collation.commitments_hash = Some(candidate_receipt.commitments_hash); - let pvd = match ( + let (maybe_pvd, maybe_parent_head_and_hash) = match ( collation_event.collator_protocol_version, collation_event.pending_collation.prospective_candidate, ) { (CollationVersion::V2, Some(ProspectiveCandidate { parent_head_data_hash, .. })) if per_relay_parent.prospective_parachains_mode.is_enabled() => - request_prospective_validation_data( + { + let pvd = request_prospective_validation_data( ctx.sender(), relay_parent, parent_head_data_hash, pending_collation.para_id, + maybe_parent_head_data.clone(), ) - .await?, + .await?; + + (pvd, maybe_parent_head_data.map(|head_data| (head_data, parent_head_data_hash))) + }, // Support V2 collators without async backing enabled. - (CollationVersion::V2, Some(_)) | (CollationVersion::V1, _) => - request_persisted_validation_data( + (CollationVersion::V2, Some(_)) | (CollationVersion::V1, _) => { + let pvd = request_persisted_validation_data( ctx.sender(), candidate_receipt.descriptor().relay_parent, candidate_receipt.descriptor().para_id, ) - .await?, + .await?; + (pvd, None) + }, _ => { // `handle_advertisement` checks for protocol mismatch. return Ok(()) }, - } - .ok_or(SecondingError::PersistedValidationDataNotFound)?; + }; + let pvd = maybe_pvd.ok_or(SecondingError::PersistedValidationDataNotFound)?; fetched_collation_sanity_check( &collation_event.pending_collation, &candidate_receipt, &pvd, + maybe_parent_head_and_hash, )?; ctx.send_message(CandidateBackingMessage::Second( @@ -1978,9 +1994,10 @@ async fn handle_collation_fetch_response( ); Err(None) }, - Ok(request_v1::CollationFetchingResponse::Collation(receipt, _)) - if receipt.descriptor().para_id != pending_collation.para_id => - { + Ok( + request_v1::CollationFetchingResponse::Collation(receipt, _) | + request_v1::CollationFetchingResponse::CollationWithParentHeadData { receipt, .. }, + ) if receipt.descriptor().para_id != pending_collation.para_id => { gum::debug!( target: LOG_TARGET, expected_para_id = ?pending_collation.para_id, @@ -2010,6 +2027,33 @@ async fn handle_collation_fetch_response( }, candidate_receipt, pov, + maybe_parent_head_data: None, + }) + }, + Ok(request_v2::CollationFetchingResponse::CollationWithParentHeadData { + receipt, + pov, + parent_head_data, + }) => { + gum::debug!( + target: LOG_TARGET, + para_id = %pending_collation.para_id, + hash = ?pending_collation.relay_parent, + candidate_hash = ?receipt.hash(), + "Received collation (v3)", + ); + let _span = jaeger::Span::new(&pov, "received-collation"); + + metrics_result = Ok(()); + Ok(PendingCollationFetch { + collation_event: CollationEvent { + collator_id, + pending_collation, + collator_protocol_version, + }, + candidate_receipt: receipt, + pov, + maybe_parent_head_data: Some(parent_head_data), }) }, }; diff --git a/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs b/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs index 23963e65554..eaa725f2642 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs @@ -754,6 +754,126 @@ fn fetched_collation_sanity_check() { }); } +#[test] +fn sanity_check_invalid_parent_head_data() { + let test_state = TestState::default(); + + test_harness(ReputationAggregator::new(|_| true), |test_harness| async move { + let TestHarness { mut virtual_overseer, .. } = test_harness; + + let pair = CollatorPair::generate().0; + + let head_c = Hash::from_low_u64_be(130); + let head_c_num = 3; + + update_view(&mut virtual_overseer, &test_state, vec![(head_c, head_c_num)], 1).await; + + let peer_a = PeerId::random(); + + connect_and_declare_collator( + &mut virtual_overseer, + peer_a, + pair.clone(), + test_state.chain_ids[0], + CollationVersion::V2, + ) + .await; + + let mut candidate = dummy_candidate_receipt_bad_sig(head_c, Some(Default::default())); + candidate.descriptor.para_id = test_state.chain_ids[0]; + + let commitments = CandidateCommitments { + head_data: HeadData(vec![1, 2, 3]), + horizontal_messages: Default::default(), + upward_messages: Default::default(), + new_validation_code: None, + processed_downward_messages: 0, + hrmp_watermark: 0, + }; + candidate.commitments_hash = commitments.hash(); + + let parent_head_data = HeadData(vec![4, 2, 0]); + let parent_head_data_hash = parent_head_data.hash(); + let wrong_parent_head_data = HeadData(vec![4, 2]); + + let mut pvd = dummy_pvd(); + pvd.parent_head = parent_head_data; + + candidate.descriptor.persisted_validation_data_hash = pvd.hash(); + + let candidate_hash = candidate.hash(); + + advertise_collation( + &mut virtual_overseer, + peer_a, + head_c, + Some((candidate_hash, parent_head_data_hash)), + ) + .await; + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::CandidateBacking( + CandidateBackingMessage::CanSecond(request, tx), + ) => { + assert_eq!(request.candidate_hash, candidate_hash); + assert_eq!(request.candidate_para_id, test_state.chain_ids[0]); + assert_eq!(request.parent_head_data_hash, parent_head_data_hash); + tx.send(true).expect("receiving side should be alive"); + } + ); + + let response_channel = assert_fetch_collation_request( + &mut virtual_overseer, + head_c, + test_state.chain_ids[0], + Some(candidate_hash), + ) + .await; + + let pov = PoV { block_data: BlockData(vec![1]) }; + + response_channel + .send(Ok(( + request_v2::CollationFetchingResponse::CollationWithParentHeadData { + receipt: candidate.clone(), + pov: pov.clone(), + parent_head_data: wrong_parent_head_data, + } + .encode(), + ProtocolName::from(""), + ))) + .expect("Sending response should succeed"); + + // PVD request. + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ProspectiveParachains( + ProspectiveParachainsMessage::GetProspectiveValidationData(request, tx), + ) => { + assert_eq!(head_c, request.candidate_relay_parent); + assert_eq!(test_state.chain_ids[0], request.para_id); + tx.send(Some(pvd)).unwrap(); + } + ); + + // Reported malicious. + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::NetworkBridgeTx( + NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(peer_id, rep)), + ) => { + assert_eq!(peer_a, peer_id); + assert_eq!(rep.value, COST_REPORT_BAD.cost_or_benefit()); + } + ); + + test_helpers::Yield::new().await; + assert_matches!(virtual_overseer.recv().now_or_never(), None); + + virtual_overseer + }); +} + #[test] fn advertisement_spam_protection() { let test_state = TestState::default(); diff --git a/polkadot/node/network/protocol/src/request_response/mod.rs b/polkadot/node/network/protocol/src/request_response/mod.rs index a67d83aff0c..2fb62f56d10 100644 --- a/polkadot/node/network/protocol/src/request_response/mod.rs +++ b/polkadot/node/network/protocol/src/request_response/mod.rs @@ -31,7 +31,7 @@ //! data, like what is the corresponding response type. //! //! ## Versioning -//! +//! //! Versioning for request-response protocols can be done in multiple ways. //! //! If you're just changing the protocol name but the binary payloads are the same, just add a new diff --git a/polkadot/node/network/protocol/src/request_response/v1.rs b/polkadot/node/network/protocol/src/request_response/v1.rs index 0832593a6a3..ba29b32c4ce 100644 --- a/polkadot/node/network/protocol/src/request_response/v1.rs +++ b/polkadot/node/network/protocol/src/request_response/v1.rs @@ -22,7 +22,8 @@ use polkadot_node_primitives::{ AvailableData, DisputeMessage, ErasureChunk, PoV, Proof, UncheckedDisputeMessage, }; use polkadot_primitives::{ - CandidateHash, CandidateReceipt, CommittedCandidateReceipt, Hash, Id as ParaId, ValidatorIndex, + CandidateHash, CandidateReceipt, CommittedCandidateReceipt, Hash, HeadData, Id as ParaId, + ValidatorIndex, }; use super::{IsRequest, Protocol}; @@ -103,6 +104,18 @@ pub enum CollationFetchingResponse { /// Deliver requested collation. #[codec(index = 0)] Collation(CandidateReceipt, PoV), + + /// Deliver requested collation along with parent head data. + #[codec(index = 1)] + CollationWithParentHeadData { + /// The receipt of the candidate. + receipt: CandidateReceipt, + /// Candidate's proof of validity. + pov: PoV, + /// The head data of the candidate's parent. + /// This is needed for elastic scaling to work. + parent_head_data: HeadData, + }, } impl IsRequest for CollationFetchingRequest { diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index f11291fd0ea..eeb684149c8 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -46,11 +46,12 @@ use polkadot_primitives::{ vstaging::{ApprovalVotingParams, NodeFeatures}, AuthorityDiscoveryId, BackedCandidate, BlockNumber, CandidateEvent, CandidateHash, CandidateIndex, CandidateReceipt, CollatorId, CommittedCandidateReceipt, CoreState, - DisputeState, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, Header as BlockHeader, - Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, MultiDisputeStatementSet, - OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, PvfExecKind, SessionIndex, - SessionInfo, SignedAvailabilityBitfield, SignedAvailabilityBitfields, ValidationCode, - ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, + DisputeState, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, HeadData, + Header as BlockHeader, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, + MultiDisputeStatementSet, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, + PvfExecKind, SessionIndex, SessionInfo, SignedAvailabilityBitfield, + SignedAvailabilityBitfields, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + ValidatorSignature, }; use polkadot_statement_table::v2::Misbehavior; use std::{ @@ -207,16 +208,20 @@ pub enum CollatorProtocolMessage { /// This should be sent before any `DistributeCollation` message. CollateOn(ParaId), /// Provide a collation to distribute to validators with an optional result sender. - /// The second argument is the parent head-data hash. - /// - /// The result sender should be informed when at least one parachain validator seconded the - /// collation. It is also completely okay to just drop the sender. - DistributeCollation( - CandidateReceipt, - Hash, - PoV, - Option>, - ), + DistributeCollation { + /// The receipt of the candidate. + candidate_receipt: CandidateReceipt, + /// The hash of the parent head-data. + /// Here to avoid computing the hash of the parent head data twice. + parent_head_data_hash: Hash, + /// Proof of validity. + pov: PoV, + /// This parent head-data is needed for elastic scaling. + parent_head_data: HeadData, + /// The result sender should be informed when at least one parachain validator seconded the + /// collation. It is also completely okay to just drop the sender. + result_sender: Option>, + }, /// Report a collator as having provided an invalid collation. This should lead to disconnect /// and blacklist of the collator. ReportCollator(CollatorId), @@ -1104,8 +1109,22 @@ pub struct ProspectiveValidationDataRequest { pub para_id: ParaId, /// The relay-parent of the candidate. pub candidate_relay_parent: Hash, - /// The parent head-data hash. - pub parent_head_data_hash: Hash, + /// The parent head-data. + pub parent_head_data: ParentHeadData, +} + +/// The parent head-data hash with optional data itself. +#[derive(Debug)] +pub enum ParentHeadData { + /// Parent head-data hash. + OnlyHash(Hash), + /// Parent head-data along with its hash. + WithData { + /// This will be provided for collations with elastic scaling enabled. + head_data: HeadData, + /// Parent head-data hash. + hash: Hash, + }, } /// Indicates the relay-parents whose fragment tree a candidate diff --git a/prdoc/pr_3302.prdoc b/prdoc/pr_3302.prdoc new file mode 100644 index 00000000000..a2d93fc6073 --- /dev/null +++ b/prdoc/pr_3302.prdoc @@ -0,0 +1,15 @@ +title: Collator protocol changes for elastic scaling + +doc: + - audience: Node Dev + description: | + This PR introduces changes to the collator protocol to support elastic scaling. + Namely, a new variant added to the collation response to include parent head-data + along with the collation. Currently, the new variant is not being used. + - audience: Node Operator + description: | + Validators are required to upgrade to this version before collators in order to + support the elastic scaling of parachains. + +crates: + - name: polkadot-collator-protocol -- GitLab From d2a7100e3b9832e5288d6d035be6d32bf8961f84 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Sun, 17 Mar 2024 15:21:29 +0200 Subject: [PATCH 127/188] Crowdload burn remaining funds (#3707) Crowdloan account should burn all funds after a crowd loan got dissolved to ensure that the account is reaped correctly. --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Francisco Aguirre --- polkadot/runtime/common/src/crowdloan/mod.rs | 49 ++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/polkadot/runtime/common/src/crowdloan/mod.rs b/polkadot/runtime/common/src/crowdloan/mod.rs index 6543bf305c4..d405278411b 100644 --- a/polkadot/runtime/common/src/crowdloan/mod.rs +++ b/polkadot/runtime/common/src/crowdloan/mod.rs @@ -60,7 +60,7 @@ use frame_support::{ pallet_prelude::{DispatchResult, Weight}, storage::{child, ChildTriePrefixIterator}, traits::{ - Currency, + Currency, Defensive, ExistenceRequirement::{self, AllowDeath, KeepAlive}, Get, ReservableCurrency, }, @@ -563,6 +563,7 @@ pub mod pallet { let who = ensure_signed(origin)?; let fund = Self::funds(index).ok_or(Error::::InvalidParaId)?; + let pot = Self::fund_account_id(fund.fund_index); let now = frame_system::Pallet::::block_number(); // Only allow dissolution when the raised funds goes to zero, @@ -576,7 +577,10 @@ pub mod pallet { // can take care of that. debug_assert!(Self::contribution_iterator(fund.fund_index).count().is_zero()); - frame_system::Pallet::::dec_providers(&Self::fund_account_id(fund.fund_index))?; + // Crowdloan over, burn all funds. + let _imba = CurrencyOf::::make_free_balance_be(&pot, Zero::zero()); + let _ = frame_system::Pallet::::dec_providers(&pot).defensive(); + CurrencyOf::::unreserve(&fund.depositor, fund.deposit); Funds::::remove(index); Self::deposit_event(Event::::Dissolved { para_id: index }); @@ -1609,6 +1613,7 @@ mod tests { new_test_ext().execute_with(|| { let para = new_para(); let index = NextFundIndex::::get(); + let issuance = Balances::total_issuance(); // Set up a crowdloan assert_ok!(Crowdloan::create(RuntimeOrigin::signed(1), para, 1000, 1, 1, 9, None)); @@ -1629,9 +1634,10 @@ mod tests { // Some funds are left over assert_eq!(Balances::free_balance(&account_id), 10); - // They wil be left in the account at the end + // Remaining funds will be burned assert_ok!(Crowdloan::dissolve(RuntimeOrigin::signed(1), para)); - assert_eq!(Balances::free_balance(&account_id), 10); + assert_eq!(Balances::free_balance(&account_id), 0); + assert_eq!(Balances::total_issuance(), issuance - 10); }); } @@ -1740,6 +1746,41 @@ mod tests { }); } + // Regression test to check that a pot account with just one provider can be dissolved. + #[test] + fn dissolve_provider_refs_total_issuance_works() { + new_test_ext().execute_with(|| { + let para = new_para(); + let issuance = Balances::total_issuance(); + + // Set up a crowdloan + assert_ok!(Crowdloan::create(RuntimeOrigin::signed(1), para, 1000, 1, 1, 9, None)); + assert_ok!(Crowdloan::contribute(RuntimeOrigin::signed(2), para, 100, None)); + assert_ok!(Crowdloan::contribute(RuntimeOrigin::signed(3), para, 50, None)); + + run_to_block(10); + + // We test the historic case where crowdloan accounts only have one provider: + { + let fund = Crowdloan::funds(para).unwrap(); + let pot = Crowdloan::fund_account_id(fund.fund_index); + System::dec_providers(&pot).unwrap(); + assert_eq!(System::providers(&pot), 1); + } + + // All funds are refunded + assert_ok!(Crowdloan::refund(RuntimeOrigin::signed(2), para)); + + // Now that `fund.raised` is zero, it can be dissolved. + assert_ok!(Crowdloan::dissolve(RuntimeOrigin::signed(1), para)); + + assert_eq!(Balances::free_balance(1), 1000); + assert_eq!(Balances::free_balance(2), 2000); + assert_eq!(Balances::free_balance(3), 3000); + assert_eq!(Balances::total_issuance(), issuance); + }); + } + #[test] fn dissolve_works() { new_test_ext().execute_with(|| { -- GitLab From 1f9505c0d358c20a7f95839ff1f8aa65ad843a0a Mon Sep 17 00:00:00 2001 From: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:02:11 +0100 Subject: [PATCH 128/188] Eliminate `experimental` feature (#3654) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Totally removes the `experimental` feature. Closes #3648. --------- Co-authored-by: Bastian Köcher --- cumulus/pallets/collator-selection/Cargo.toml | 2 -- .../pallets/collator-selection/src/mock.rs | 1 - .../assets/asset-hub-rococo/Cargo.toml | 2 -- .../assets/asset-hub-rococo/src/lib.rs | 4 ---- .../assets/asset-hub-westend/Cargo.toml | 2 -- .../assets/asset-hub-westend/src/lib.rs | 4 ---- .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 1 - .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 4 ---- .../bridge-hubs/bridge-hub-westend/Cargo.toml | 2 -- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 4 ---- .../collectives-westend/Cargo.toml | 2 -- .../collectives-westend/src/lib.rs | 4 ---- .../contracts/contracts-rococo/Cargo.toml | 2 -- .../contracts/contracts-rococo/src/lib.rs | 4 ---- .../coretime/coretime-rococo/Cargo.toml | 2 -- .../coretime/coretime-rococo/src/lib.rs | 4 ---- .../coretime/coretime-westend/Cargo.toml | 2 -- .../coretime/coretime-westend/src/lib.rs | 4 ---- .../glutton/glutton-westend/Cargo.toml | 2 -- .../glutton/glutton-westend/src/lib.rs | 4 ---- .../runtimes/people/people-rococo/Cargo.toml | 2 -- .../runtimes/people/people-rococo/src/lib.rs | 4 ---- .../runtimes/people/people-westend/Cargo.toml | 2 -- .../runtimes/people/people-westend/src/lib.rs | 4 ---- .../runtimes/starters/seedling/Cargo.toml | 2 -- .../runtimes/starters/seedling/src/lib.rs | 4 ---- .../runtimes/starters/shell/Cargo.toml | 2 -- .../runtimes/starters/shell/src/lib.rs | 4 ---- .../runtimes/testing/penpal/Cargo.toml | 2 -- .../runtimes/testing/penpal/src/lib.rs | 1 - .../testing/rococo-parachain/Cargo.toml | 2 -- .../testing/rococo-parachain/src/lib.rs | 4 ---- docs/sdk/Cargo.toml | 3 --- docs/sdk/src/polkadot_sdk/cumulus.rs | 1 - prdoc/pr_3654.prdoc | 14 ++++++++++++++ substrate/frame/aura/src/lib.rs | 19 +------------------ substrate/frame/aura/src/mock.rs | 2 -- templates/parachain/runtime/Cargo.toml | 2 -- templates/parachain/runtime/src/lib.rs | 1 - templates/solochain/runtime/Cargo.toml | 2 -- templates/solochain/runtime/src/lib.rs | 2 -- 41 files changed, 15 insertions(+), 120 deletions(-) create mode 100644 prdoc/pr_3654.prdoc diff --git a/cumulus/pallets/collator-selection/Cargo.toml b/cumulus/pallets/collator-selection/Cargo.toml index 20f048b97d5..241a78466d6 100644 --- a/cumulus/pallets/collator-selection/Cargo.toml +++ b/cumulus/pallets/collator-selection/Cargo.toml @@ -77,5 +77,3 @@ try-runtime = [ "pallet-timestamp/try-runtime", "sp-runtime/try-runtime", ] - -experimental = ["pallet-aura/experimental"] diff --git a/cumulus/pallets/collator-selection/src/mock.rs b/cumulus/pallets/collator-selection/src/mock.rs index 061d8b1cb31..4a440dfe1e9 100644 --- a/cumulus/pallets/collator-selection/src/mock.rs +++ b/cumulus/pallets/collator-selection/src/mock.rs @@ -125,7 +125,6 @@ impl pallet_aura::Config for Test { type MaxAuthorities = ConstU32<100_000>; type DisabledValidators = (); type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index 05936e93993..95691a045b7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -251,8 +251,6 @@ std = [ "xcm/std", ] -experimental = ["pallet-aura/experimental"] - # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 7da9869dd2c..e6b5e55bcd3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -187,10 +187,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -723,7 +720,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index 78c48507a7a..950c6e62d72 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -236,8 +236,6 @@ std = [ "xcm/std", ] -experimental = ["pallet-aura/experimental"] - # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 3d69e104bd5..1ba108234c8 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -171,10 +171,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -703,7 +700,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 7a1951fd24b..8a6823ea3ee 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -296,7 +296,6 @@ try-runtime = [ "sp-runtime/try-runtime", ] -experimental = ["pallet-aura/experimental"] fast-runtime = [] # A feature that should be enabled when the runtime should be built for on-chain diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 843acffe03e..31069778e38 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -277,10 +277,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -445,7 +442,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml index 8623f7cb366..4eb201eedc1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml @@ -246,8 +246,6 @@ try-runtime = [ "sp-runtime/try-runtime", ] -experimental = ["pallet-aura/experimental"] - # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index d70d880c50c..d96c762fe19 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -251,10 +251,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -407,7 +404,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml index ed264f28c26..4224b397139 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml @@ -232,8 +232,6 @@ std = [ "xcm/std", ] -experimental = ["pallet-aura/experimental"] - # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 15a2391fa5b..5bf3519ac3d 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -184,10 +184,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -483,7 +480,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml index dcc6c4e853a..e4ac2016a72 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/Cargo.toml @@ -196,8 +196,6 @@ try-runtime = [ "sp-runtime/try-runtime", ] -experimental = ["pallet-aura/experimental"] - # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 928c3ecc532..f148ceadccb 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -193,10 +193,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = pallet_timestamp::weights::SubstrateWeight; } @@ -349,7 +346,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml index 0bc3b510ed5..eb92afc4311 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/Cargo.toml @@ -194,6 +194,4 @@ try-runtime = [ "sp-runtime/try-runtime", ] -experimental = ["pallet-aura/experimental"] - fast-runtime = [] diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 41b9ffa0af8..6efbdde5899 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -206,10 +206,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -369,7 +366,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml index a7d52dfd784..b8efecffc50 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/Cargo.toml @@ -190,6 +190,4 @@ try-runtime = [ "sp-runtime/try-runtime", ] -experimental = ["pallet-aura/experimental"] - fast-runtime = [] diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index d93c2a61ff4..2bb179b5b05 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -206,10 +206,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -369,7 +366,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml b/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml index 23c5ce1c7f8..a357bf519e4 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/Cargo.toml @@ -135,8 +135,6 @@ try-runtime = [ "sp-runtime/try-runtime", ] -experimental = ["pallet-aura/experimental"] - # A feature that should be enabled when the runtime should be built for on-chain # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index 6967ac58e3b..e7fdb53b253 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -221,10 +221,7 @@ impl cumulus_pallet_aura_ext::Config for Runtime {} impl pallet_timestamp::Config for Runtime { type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -233,7 +230,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml index c0b8fb7636b..eebd662c3fd 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/people/people-rococo/Cargo.toml @@ -188,5 +188,3 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] - -experimental = ["pallet-aura/experimental"] diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 05da00ac555..98f76984dd4 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -187,10 +187,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -337,7 +334,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml index e87e825a34e..39cb69e679c 100644 --- a/cumulus/parachains/runtimes/people/people-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/people/people-westend/Cargo.toml @@ -188,5 +188,3 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] - -experimental = ["pallet-aura/experimental"] diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index e921df1e5da..5adbdc1f38c 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -187,10 +187,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = weights::pallet_timestamp::WeightInfo; } @@ -337,7 +334,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/cumulus/parachains/runtimes/starters/seedling/Cargo.toml b/cumulus/parachains/runtimes/starters/seedling/Cargo.toml index 1f5bee7784e..9f08fdf5943 100644 --- a/cumulus/parachains/runtimes/starters/seedling/Cargo.toml +++ b/cumulus/parachains/runtimes/starters/seedling/Cargo.toml @@ -79,5 +79,3 @@ std = [ "sp-version/std", "substrate-wasm-builder", ] - -experimental = ["pallet-aura/experimental"] diff --git a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs index 179bda356ae..bf4768d8457 100644 --- a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs @@ -213,17 +213,13 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } impl pallet_timestamp::Config for Runtime { type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ parachains_common::SLOT_DURATION / 2 }>; type WeightInfo = (); } diff --git a/cumulus/parachains/runtimes/starters/shell/Cargo.toml b/cumulus/parachains/runtimes/starters/shell/Cargo.toml index 5a8f2a9d125..2f82547afe9 100644 --- a/cumulus/parachains/runtimes/starters/shell/Cargo.toml +++ b/cumulus/parachains/runtimes/starters/shell/Cargo.toml @@ -99,5 +99,3 @@ try-runtime = [ "parachain-info/try-runtime", "sp-runtime/try-runtime", ] - -experimental = ["pallet-aura/experimental"] diff --git a/cumulus/parachains/runtimes/starters/shell/src/lib.rs b/cumulus/parachains/runtimes/starters/shell/src/lib.rs index c0904f0faef..51fdfac5b1c 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/lib.rs @@ -241,17 +241,13 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } impl pallet_timestamp::Config for Runtime { type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ parachains_common::SLOT_DURATION / 2 }>; type WeightInfo = (); } diff --git a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml index 7f3e898d923..c18f6571f41 100644 --- a/cumulus/parachains/runtimes/testing/penpal/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/penpal/Cargo.toml @@ -191,5 +191,3 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] - -experimental = ["pallet-aura/experimental"] diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 24a325c6f5b..3063601e030 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -582,7 +582,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml index 42169e8949f..577ed749167 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml @@ -134,5 +134,3 @@ runtime-benchmarks = [ "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", ] - -experimental = ["pallet-aura/experimental"] diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index aea139fb66e..753d2d12065 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -228,10 +228,7 @@ impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - #[cfg(feature = "experimental")] type MinimumPeriod = ConstU64<0>; - #[cfg(not(feature = "experimental"))] - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = (); } @@ -594,7 +591,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index 8b498d407c0..3f40a950c28 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -86,6 +86,3 @@ sp-version = { path = "../../substrate/primitives/version" } # XCM xcm = { package = "staging-xcm", path = "../../polkadot/xcm" } - -[features] -experimental = ["pallet-aura/experimental"] diff --git a/docs/sdk/src/polkadot_sdk/cumulus.rs b/docs/sdk/src/polkadot_sdk/cumulus.rs index 7d9daf9067c..9bd957c7c1c 100644 --- a/docs/sdk/src/polkadot_sdk/cumulus.rs +++ b/docs/sdk/src/polkadot_sdk/cumulus.rs @@ -110,7 +110,6 @@ mod tests { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } diff --git a/prdoc/pr_3654.prdoc b/prdoc/pr_3654.prdoc new file mode 100644 index 00000000000..de4a68d2356 --- /dev/null +++ b/prdoc/pr_3654.prdoc @@ -0,0 +1,14 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Remove `experimental` feature from `pallet-aura` + +doc: + - audience: Runtime Dev + description: | + The `experimental` feature in `pallet-aura`, previously used to gate different experimental + changes, became redundant with the introduction of the async backing which relies on the + mentioned changes, therefore, it is removed. + +crates: + - name: pallet-aura diff --git a/substrate/frame/aura/src/lib.rs b/substrate/frame/aura/src/lib.rs index f7506db05d1..55653de97a8 100644 --- a/substrate/frame/aura/src/lib.rs +++ b/substrate/frame/aura/src/lib.rs @@ -66,9 +66,6 @@ const LOG_TARGET: &str = "runtime::aura"; /// /// This was the default behavior of the Aura pallet and may be used for /// backwards compatibility. -/// -/// Note that this type is likely not useful without the `experimental` -/// feature. pub struct MinimumPeriodTimesTwo(sp_std::marker::PhantomData); impl Get for MinimumPeriodTimesTwo { @@ -117,10 +114,6 @@ pub mod pallet { /// The effective value of this type should not change while the chain is running. /// /// For backwards compatibility either use [`MinimumPeriodTimesTwo`] or a const. - /// - /// This associated type is only present when compiled with the `experimental` - /// feature. - #[cfg(feature = "experimental")] type SlotDuration: Get<::Moment>; } @@ -250,17 +243,7 @@ impl Pallet { /// Determine the Aura slot-duration based on the Timestamp module configuration. pub fn slot_duration() -> T::Moment { - #[cfg(feature = "experimental")] - { - T::SlotDuration::get() - } - - #[cfg(not(feature = "experimental"))] - { - // we double the minimum block-period so each author can always propose within - // the majority of its slot. - ::MinimumPeriod::get().saturating_mul(2u32.into()) - } + T::SlotDuration::get() } /// Ensure the correctness of the state of this pallet. diff --git a/substrate/frame/aura/src/mock.rs b/substrate/frame/aura/src/mock.rs index 535e27fa35e..786e6e2efaf 100644 --- a/substrate/frame/aura/src/mock.rs +++ b/substrate/frame/aura/src/mock.rs @@ -84,8 +84,6 @@ impl pallet_aura::Config for Test { type DisabledValidators = MockDisabledValidators; type MaxAuthorities = ConstU32<10>; type AllowMultipleBlocksPerSlot = AllowMultipleBlocksPerSlot; - - #[cfg(feature = "experimental")] type SlotDuration = ConstU64; } diff --git a/templates/parachain/runtime/Cargo.toml b/templates/parachain/runtime/Cargo.toml index 9d9da2b4b97..41a510c5ed3 100644 --- a/templates/parachain/runtime/Cargo.toml +++ b/templates/parachain/runtime/Cargo.toml @@ -194,5 +194,3 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] - -experimental = ["pallet-aura/experimental"] diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs index dcfab59eb81..acaabc0dbc3 100644 --- a/templates/parachain/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -453,7 +453,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<100_000>; type AllowMultipleBlocksPerSlot = ConstBool; - #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } diff --git a/templates/solochain/runtime/Cargo.toml b/templates/solochain/runtime/Cargo.toml index a7fc0519ba2..33da035878a 100644 --- a/templates/solochain/runtime/Cargo.toml +++ b/templates/solochain/runtime/Cargo.toml @@ -147,5 +147,3 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "sp-runtime/try-runtime", ] - -experimental = ["pallet-aura/experimental"] diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs index 358db0849a0..9b52ee60a63 100644 --- a/templates/solochain/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -180,8 +180,6 @@ impl pallet_aura::Config for Runtime { type DisabledValidators = (); type MaxAuthorities = ConstU32<32>; type AllowMultipleBlocksPerSlot = ConstBool; - - #[cfg(feature = "experimental")] type SlotDuration = pallet_aura::MinimumPeriodTimesTwo; } -- GitLab From fe343cc71cbe85264a1df4ecf4d6848a707f0982 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:19:21 +0100 Subject: [PATCH 129/188] Bump the known_good_semver group with 3 updates (#3717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the known_good_semver group with 3 updates: [log](https://github.com/rust-lang/log), [syn](https://github.com/dtolnay/syn) and [clap](https://github.com/clap-rs/clap). Updates `log` from 0.4.20 to 0.4.21
Changelog

Sourced from log's changelog.

[0.4.21] - 2024-02-27

What's Changed

New Contributors

Commits
  • 3ccdc28 Merge pull request #617 from rust-lang/cargo/0.4.21
  • 6153cb2 prepare for 0.4.21 release
  • f0f7494 Merge pull request #613 from rust-lang/feat/kv-cleanup
  • 2b220bf clean up structured logging example
  • 646e9ab use original Visitor name for VisitValue
  • cf85c38 add needed subfeatures to kv_unstable
  • 73e9539 fix up capturing of :err
  • 31bb4b0 move error macros together
  • ad91711 support field shorthand in macros
  • 90a347b restore removed APIs as deprecated
  • Additional commits viewable in compare view

Updates `syn` from 2.0.50 to 2.0.52
Release notes

Sourced from syn's releases.

2.0.52

  • Add an expression parser that uses match-arm's boundary rules (#1593)

2.0.51

  • Resolve non_local_definitions warnings in generated code under rustc 1.78-nightly
Commits
  • 07ede6a Release 2.0.52
  • acbcfbc Merge pull request #1593 from dtolnay/boundary
  • 4924a99 Add an expression parser that uses match-arm's boundary rules
  • e06122b Resolve unnecessary_get_then_check clippy lint
  • 018fc5a Update test suite to nightly-2024-02-27
  • 5e15a9b Release 2.0.51
  • 7e0d4e1 Resolve non_local_definitions warning in debug impls
  • 8667ad9 Ignore module_name_repetitions pedantic clippy lint in codegen
  • 1fc3200 Update test suite to nightly-2024-02-26
  • 07a2065 Update test suite to nightly-2024-02-23
  • See full diff in compare view

Updates `clap` from 4.5.1 to 4.5.3
Release notes

Sourced from clap's releases.

v4.5.3

[4.5.3] - 2024-03-15

Internal

  • (derive) Update heck

v4.5.2

[4.5.2] - 2024-03-06

Fixes

  • (macros) Silence a warning
Changelog

Sourced from clap's changelog.

[4.5.3] - 2024-03-15

Internal

  • (derive) Update heck

[4.5.2] - 2024-03-06

Fixes

  • (macros) Silence a warning
Commits
  • 4e07b43 chore: Release
  • 8247c7d docs: Update changelog
  • 677c52c chore: Update heck requirement (#5396)
  • f65d421 chore: Release
  • 886b272 docs: Update changelog
  • 3ba4297 Merge pull request #5386 from amaanq/static-var-name
  • 2aea950 fix: Use SCREAMING_SNAKE_CASE for static variable authors
  • 690f555 Merge pull request #5382 from clap-rs/renovate/pre-commit-action-3.x
  • a2aa644 chore(deps): update compatible (dev) (#5381)
  • c233de5 chore(deps): update pre-commit/action action to v3.0.1
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 240 +++++++++--------- Cargo.toml | 4 +- cumulus/client/cli/Cargo.toml | 2 +- cumulus/polkadot-parachain/Cargo.toml | 2 +- cumulus/test/service/Cargo.toml | 2 +- polkadot/cli/Cargo.toml | 2 +- polkadot/node/malus/Cargo.toml | 2 +- polkadot/node/subsystem-bench/Cargo.toml | 2 +- .../test-parachains/adder/collator/Cargo.toml | 2 +- .../undying/collator/Cargo.toml | 2 +- polkadot/utils/generate-bags/Cargo.toml | 2 +- .../remote-ext-tests/bags-list/Cargo.toml | 2 +- substrate/bin/node/bench/Cargo.toml | 2 +- substrate/bin/node/cli/Cargo.toml | 4 +- substrate/bin/node/inspect/Cargo.toml | 2 +- .../bin/utils/chain-spec-builder/Cargo.toml | 2 +- substrate/bin/utils/subkey/Cargo.toml | 2 +- substrate/client/cli/Cargo.toml | 2 +- substrate/client/storage-monitor/Cargo.toml | 2 +- .../solution-type/fuzzer/Cargo.toml | 2 +- .../single-block-migrations/Cargo.toml | 2 +- substrate/frame/migrations/Cargo.toml | 2 +- .../npos-elections/fuzzer/Cargo.toml | 2 +- .../ci/node-template-release/Cargo.toml | 2 +- .../utils/frame/benchmarking-cli/Cargo.toml | 2 +- .../frame/frame-utilities-cli/Cargo.toml | 2 +- .../generate-bags/node-runtime/Cargo.toml | 2 +- .../utils/frame/try-runtime/cli/Cargo.toml | 2 +- templates/minimal/node/Cargo.toml | 2 +- templates/parachain/node/Cargo.toml | 2 +- templates/solochain/node/Cargo.toml | 2 +- 31 files changed, 155 insertions(+), 149 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 699fd35a824..f3535d509ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,7 +191,7 @@ checksum = "c0391754c09fab4eae3404d19d0d297aa1c670c1775ab51d8a5312afeca23157" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -202,11 +202,11 @@ checksum = "8a98ad1696a2e17f010ae8e43e9f2a1e930ed176a8e3ff77acfeff6dfb07b42c" dependencies = [ "const-hex", "dunce", - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", "syn-solidity", "tiny-keccak", ] @@ -347,7 +347,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -1228,7 +1228,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -1245,7 +1245,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -1427,7 +1427,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -2613,12 +2613,12 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.1" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" dependencies = [ "clap_builder", - "clap_derive 4.5.0", + "clap_derive 4.5.3", ] [[package]] @@ -2632,9 +2632,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -2649,7 +2649,7 @@ version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "586a385f7ef2f8b4d86bddaa0c094794e7ccbfe5ffef1f434fe928143fc783a5" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", ] [[package]] @@ -2658,7 +2658,7 @@ version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", @@ -2667,14 +2667,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -3383,7 +3383,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.1", + "clap 4.5.3", "criterion-plot", "futures", "is-terminal", @@ -3536,7 +3536,7 @@ dependencies = [ name = "cumulus-client-cli" version = "0.7.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "parity-scale-codec", "sc-chain-spec", "sc-cli", @@ -3895,7 +3895,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -4299,7 +4299,7 @@ name = "cumulus-test-service" version = "0.1.0" dependencies = [ "async-trait", - "clap 4.5.1", + "clap 4.5.3", "criterion 0.5.1", "cumulus-client-cli", "cumulus-client-consensus-common", @@ -4410,7 +4410,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -4450,7 +4450,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -4467,7 +4467,7 @@ checksum = "50c49547d73ba8dcfd4ad7325d64c6d5391ff4224d498fc39a6f3f49825a530d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -4675,7 +4675,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -4745,7 +4745,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.50", + "syn 2.0.52", "termcolor", "walkdir", ] @@ -4762,7 +4762,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.50", + "syn 2.0.52", "termcolor", "toml 0.8.8", "walkdir", @@ -4967,7 +4967,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 1.0.109", @@ -4990,7 +4990,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -5001,7 +5001,7 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -5054,9 +5054,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.3.30" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "837c0466252947ada828b975e12daf82e18bb5444e4df87be6038d4469e2a3d2" +checksum = "2b73807008a3c7f171cc40312f37d95ef0396e048b5848d775f54b1a4dd4a0d3" dependencies = [ "serde", ] @@ -5191,7 +5191,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -5512,7 +5512,7 @@ dependencies = [ "Inflector", "array-bytes 6.1.0", "chrono", - "clap 4.5.1", + "clap 4.5.3", "comfy-table", "frame-benchmarking", "frame-support", @@ -5578,7 +5578,7 @@ dependencies = [ "quote", "scale-info", "sp-arithmetic", - "syn 2.0.50", + "syn 2.0.52", "trybuild", ] @@ -5604,7 +5604,7 @@ dependencies = [ name = "frame-election-solution-type-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-support", @@ -5735,7 +5735,7 @@ dependencies = [ "quote", "regex", "sp-crypto-hashing", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -5746,7 +5746,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -5755,7 +5755,7 @@ version = "11.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -5988,7 +5988,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -6342,6 +6342,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -6935,7 +6941,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69fc56131589f82e57805f7338b87023db4aafef813555708b159787e34ad6bc" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-crate 3.0.0", "proc-macro2", "quote", @@ -7586,7 +7592,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fba456131824ab6acd4c7bf61e9c0f0a3014b5fc9868ccb8e10d344594cdc4f" dependencies = [ - "heck", + "heck 0.4.1", "quote", "syn 1.0.109", ] @@ -7839,9 +7845,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ "serde", "value-bag", @@ -7927,7 +7933,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -7941,7 +7947,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -7952,7 +7958,7 @@ checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -7963,7 +7969,7 @@ checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -8120,7 +8126,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" name = "minimal-template-node" version = "0.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "frame", "futures", "futures-timer", @@ -8589,7 +8595,7 @@ name = "node-bench" version = "0.9.0-dev" dependencies = [ "array-bytes 6.1.0", - "clap 4.5.1", + "clap 4.5.3", "derive_more", "fs_extra", "futures", @@ -8666,7 +8672,7 @@ dependencies = [ name = "node-runtime-generate-bags" version = "3.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "generate-bags", "kitchensink-runtime", ] @@ -8675,7 +8681,7 @@ dependencies = [ name = "node-template-release" version = "3.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "flate2", "fs_extra", "glob", @@ -9624,7 +9630,7 @@ version = "18.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -10852,7 +10858,7 @@ dependencies = [ "proc-macro2", "quote", "sp-runtime", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -11257,7 +11263,7 @@ dependencies = [ name = "parachain-template-node" version = "0.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "color-print", "cumulus-client-cli", "cumulus-client-collator", @@ -11947,7 +11953,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -11988,7 +11994,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -12203,7 +12209,7 @@ name = "polkadot-cli" version = "7.0.0" dependencies = [ "cfg-if", - "clap 4.5.1", + "clap 4.5.3", "frame-benchmarking-cli", "futures", "log", @@ -13053,7 +13059,7 @@ dependencies = [ "async-trait", "bridge-hub-rococo-runtime", "bridge-hub-westend-runtime", - "clap 4.5.1", + "clap 4.5.3", "collectives-westend-runtime", "color-print", "contracts-rococo-runtime", @@ -13589,7 +13595,7 @@ dependencies = [ "async-trait", "bincode", "bitvec", - "clap 4.5.1", + "clap 4.5.3", "clap-num", "color-eyre", "colored", @@ -13683,7 +13689,7 @@ version = "1.0.0" dependencies = [ "assert_matches", "async-trait", - "clap 4.5.1", + "clap 4.5.3", "color-eyre", "futures", "futures-timer", @@ -13830,7 +13836,7 @@ dependencies = [ name = "polkadot-voter-bags" version = "7.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "generate-bags", "sp-io", "westend-runtime", @@ -13885,7 +13891,7 @@ dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -13895,7 +13901,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" dependencies = [ "polkavm-derive-impl", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -14091,7 +14097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" dependencies = [ "proc-macro2", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -14182,7 +14188,7 @@ checksum = "9b698b0b09d40e9b7c1a47b132d66a8b54bcd20583d9b6d06e4535e383b4405c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -14254,7 +14260,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -14316,7 +14322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ "bytes", - "heck", + "heck 0.4.1", "itertools 0.10.5", "lazy_static", "log", @@ -14354,7 +14360,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -14697,7 +14703,7 @@ checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -14785,7 +14791,7 @@ checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" name = "remote-ext-tests-bags-list" version = "1.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "frame-system", "log", "pallet-bags-list-remote-tests", @@ -15188,7 +15194,7 @@ dependencies = [ "regex", "relative-path", "rustc_version 0.4.0", - "syn 2.0.50", + "syn 2.0.52", "unicode-ident", ] @@ -15642,7 +15648,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -15651,7 +15657,7 @@ version = "0.36.0" dependencies = [ "array-bytes 6.1.0", "chrono", - "clap 4.5.1", + "clap 4.5.3", "fdlimit", "futures", "futures-timer", @@ -16822,7 +16828,7 @@ dependencies = [ name = "sc-storage-monitor" version = "0.16.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "fs4", "log", "sp-core", @@ -16924,7 +16930,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -17326,7 +17332,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -17426,7 +17432,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -18224,7 +18230,7 @@ dependencies = [ name = "solochain-template-node" version = "0.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "frame-benchmarking-cli", "frame-system", "futures", @@ -18334,7 +18340,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -18728,7 +18734,7 @@ version = "0.0.0" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -18746,7 +18752,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf5 dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -18755,7 +18761,7 @@ version = "14.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -18915,7 +18921,7 @@ dependencies = [ name = "sp-npos-elections-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "honggfuzz", "rand", "sp-npos-elections", @@ -19030,7 +19036,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -19042,7 +19048,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -19314,7 +19320,7 @@ dependencies = [ "proc-macro2", "quote", "sp-version", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -19438,7 +19444,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "staging-chain-spec-builder" version = "2.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "log", "sc-chain-spec", "serde_json", @@ -19451,7 +19457,7 @@ version = "3.0.0-dev" dependencies = [ "array-bytes 6.1.0", "assert_cmd", - "clap 4.5.1", + "clap 4.5.3", "clap_complete", "criterion 0.4.0", "frame-benchmarking", @@ -19561,7 +19567,7 @@ dependencies = [ name = "staging-node-inspect" version = "0.12.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "parity-scale-codec", "sc-cli", "sc-client-api", @@ -19742,7 +19748,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -19755,18 +19761,18 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] name = "subkey" version = "9.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "sc-cli", ] @@ -19808,7 +19814,7 @@ dependencies = [ name = "substrate-frame-cli" version = "32.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "frame-support", "frame-system", "sc-cli", @@ -20157,9 +20163,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.50" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -20175,7 +20181,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -20289,7 +20295,7 @@ dependencies = [ name = "test-parachain-adder-collator" version = "1.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "futures", "futures-timer", "log", @@ -20337,7 +20343,7 @@ dependencies = [ name = "test-parachain-undying-collator" version = "1.0.0" dependencies = [ - "clap 4.5.1", + "clap 4.5.3", "futures", "futures-timer", "log", @@ -20440,7 +20446,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -20601,7 +20607,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -20808,7 +20814,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -20850,7 +20856,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -21032,7 +21038,7 @@ version = "0.38.0" dependencies = [ "assert_cmd", "async-trait", - "clap 4.5.1", + "clap 4.5.3", "frame-remote-externalities", "frame-try-runtime", "hex", @@ -21270,9 +21276,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" +checksum = "8fec26a25bd6fca441cdd0f769fd7f891bae119f996de31f86a5eddccef54c1d" dependencies = [ "value-bag-serde1", "value-bag-sval2", @@ -21280,9 +21286,9 @@ dependencies = [ [[package]] name = "value-bag-serde1" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b9f3feef403a50d4d67e9741a6d8fc688bcbb4e4f31bd4aab72cc690284394" +checksum = "ead5b693d906686203f19a49e88c477fb8c15798b68cf72f60b4b5521b4ad891" dependencies = [ "erased-serde", "serde", @@ -21291,9 +21297,9 @@ dependencies = [ [[package]] name = "value-bag-sval2" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b24f4146b6f3361e91cbf527d1fb35e9376c3c0cef72ca5ec5af6d640fad7d" +checksum = "3b9d0f4a816370c3a0d7d82d603b62198af17675b12fe5e91de6b47ceb505882" dependencies = [ "sval", "sval_buffer", @@ -21415,7 +21421,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", "wasm-bindgen-shared", ] @@ -21449,7 +21455,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -22466,7 +22472,7 @@ dependencies = [ "proc-macro2", "quote", "staging-xcm", - "syn 2.0.50", + "syn 2.0.52", "trybuild", ] @@ -22588,7 +22594,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] @@ -22608,7 +22614,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.52", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f256d02808a..3acb6c1d055 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -547,14 +547,14 @@ default_constructed_unit_structs = { level = "allow", priority = 2 } # stylistic polkavm = "0.9.3" polkavm-linker = "0.9.2" polkavm-derive = "0.9.1" -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } quote = { version = "1.0.33" } serde = { version = "1.0.197", default-features = false } serde-big-array = { version = "0.3.2" } serde_derive = { version = "1.0.117" } serde_json = { version = "1.0.114", default-features = false } serde_yaml = { version = "0.9" } -syn = { version = "2.0.50" } +syn = { version = "2.0.52" } thiserror = { version = "1.0.48" } [profile.release] diff --git a/cumulus/client/cli/Cargo.toml b/cumulus/client/cli/Cargo.toml index eaf0d5d5d7f..0b2edb593c4 100644 --- a/cumulus/client/cli/Cargo.toml +++ b/cumulus/client/cli/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" workspace = true [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0" } url = "2.4.0" diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index 84a232e954f..70423856d34 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -16,7 +16,7 @@ path = "src/main.rs" [dependencies] async-trait = "0.1.74" -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.28" hex-literal = "0.4.1" diff --git a/cumulus/test/service/Cargo.toml b/cumulus/test/service/Cargo.toml index 27273f4e0a8..45e21432f5b 100644 --- a/cumulus/test/service/Cargo.toml +++ b/cumulus/test/service/Cargo.toml @@ -14,7 +14,7 @@ path = "src/main.rs" [dependencies] async-trait = "0.1.74" -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0" } criterion = { version = "0.5.1", features = ["async_tokio"] } jsonrpsee = { version = "0.22", features = ["server"] } diff --git a/polkadot/cli/Cargo.toml b/polkadot/cli/Cargo.toml index b9232f95981..f57efa7ba43 100644 --- a/polkadot/cli/Cargo.toml +++ b/polkadot/cli/Cargo.toml @@ -19,7 +19,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] cfg-if = "1.0" -clap = { version = "4.5.1", features = ["derive"], optional = true } +clap = { version = "4.5.3", features = ["derive"], optional = true } log = { workspace = true, default-features = true } thiserror = { workspace = true } futures = "0.3.21" diff --git a/polkadot/node/malus/Cargo.toml b/polkadot/node/malus/Cargo.toml index ea25b9077f3..b3eb856f08e 100644 --- a/polkadot/node/malus/Cargo.toml +++ b/polkadot/node/malus/Cargo.toml @@ -43,7 +43,7 @@ assert_matches = "1.5" async-trait = "0.1.74" sp-keystore = { path = "../../../substrate/primitives/keystore" } sp-core = { path = "../../../substrate/primitives/core" } -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } futures = "0.3.21" futures-timer = "3.0.2" gum = { package = "tracing-gum", path = "../gum" } diff --git a/polkadot/node/subsystem-bench/Cargo.toml b/polkadot/node/subsystem-bench/Cargo.toml index 7c60ff48269..71711ad0fbd 100644 --- a/polkadot/node/subsystem-bench/Cargo.toml +++ b/polkadot/node/subsystem-bench/Cargo.toml @@ -39,7 +39,7 @@ async-trait = "0.1.57" sp-keystore = { path = "../../../substrate/primitives/keystore" } sc-keystore = { path = "../../../substrate/client/keystore" } sp-core = { path = "../../../substrate/primitives/core" } -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } futures = "0.3.21" futures-timer = "3.0.2" bincode = "1.3.3" diff --git a/polkadot/parachain/test-parachains/adder/collator/Cargo.toml b/polkadot/parachain/test-parachains/adder/collator/Cargo.toml index 8ce4ceb47c2..cb283c27119 100644 --- a/polkadot/parachain/test-parachains/adder/collator/Cargo.toml +++ b/polkadot/parachain/test-parachains/adder/collator/Cargo.toml @@ -16,7 +16,7 @@ path = "src/main.rs" [dependencies] parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } futures = "0.3.21" futures-timer = "3.0.2" log = { workspace = true, default-features = true } diff --git a/polkadot/parachain/test-parachains/undying/collator/Cargo.toml b/polkadot/parachain/test-parachains/undying/collator/Cargo.toml index 25fdbfa74ea..238b98a6680 100644 --- a/polkadot/parachain/test-parachains/undying/collator/Cargo.toml +++ b/polkadot/parachain/test-parachains/undying/collator/Cargo.toml @@ -16,7 +16,7 @@ path = "src/main.rs" [dependencies] parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } futures = "0.3.21" futures-timer = "3.0.2" log = { workspace = true, default-features = true } diff --git a/polkadot/utils/generate-bags/Cargo.toml b/polkadot/utils/generate-bags/Cargo.toml index c0e9bd332df..ad6d7259d24 100644 --- a/polkadot/utils/generate-bags/Cargo.toml +++ b/polkadot/utils/generate-bags/Cargo.toml @@ -10,7 +10,7 @@ description = "CLI to generate voter bags for Polkadot runtimes" workspace = true [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } generate-bags = { path = "../../../substrate/utils/frame/generate-bags" } sp-io = { path = "../../../substrate/primitives/io" } diff --git a/polkadot/utils/remote-ext-tests/bags-list/Cargo.toml b/polkadot/utils/remote-ext-tests/bags-list/Cargo.toml index ddc5af97a16..20e4130f888 100644 --- a/polkadot/utils/remote-ext-tests/bags-list/Cargo.toml +++ b/polkadot/utils/remote-ext-tests/bags-list/Cargo.toml @@ -18,6 +18,6 @@ sp-tracing = { path = "../../../../substrate/primitives/tracing" } frame-system = { path = "../../../../substrate/frame/system" } sp-core = { path = "../../../../substrate/primitives/core" } -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } log = { workspace = true, default-features = true } tokio = { version = "1.24.2", features = ["macros"] } diff --git a/substrate/bin/node/bench/Cargo.toml b/substrate/bin/node/bench/Cargo.toml index 8e0f7fb93b3..d5de1dbe6c4 100644 --- a/substrate/bin/node/bench/Cargo.toml +++ b/substrate/bin/node/bench/Cargo.toml @@ -16,7 +16,7 @@ workspace = true [dependencies] array-bytes = "6.1" -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } log = { workspace = true, default-features = true } node-primitives = { path = "../primitives" } node-testing = { path = "../testing" } diff --git a/substrate/bin/node/cli/Cargo.toml b/substrate/bin/node/cli/Cargo.toml index abe284c41da..8bddbbe0482 100644 --- a/substrate/bin/node/cli/Cargo.toml +++ b/substrate/bin/node/cli/Cargo.toml @@ -41,7 +41,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] # third-party dependencies array-bytes = "6.1" -clap = { version = "4.5.1", features = ["derive"], optional = true } +clap = { version = "4.5.3", features = ["derive"], optional = true } codec = { package = "parity-scale-codec", version = "3.6.1" } serde = { features = ["derive"], workspace = true, default-features = true } jsonrpsee = { version = "0.22", features = ["server"] } @@ -165,7 +165,7 @@ sp-trie = { path = "../../../primitives/trie" } sp-state-machine = { path = "../../../primitives/state-machine" } [build-dependencies] -clap = { version = "4.5.1", optional = true } +clap = { version = "4.5.3", optional = true } clap_complete = { version = "4.0.2", optional = true } node-inspect = { package = "staging-node-inspect", path = "../inspect", optional = true } frame-benchmarking-cli = { path = "../../../utils/frame/benchmarking-cli", optional = true } diff --git a/substrate/bin/node/inspect/Cargo.toml b/substrate/bin/node/inspect/Cargo.toml index 7db6e3efd3a..8453aa3cdeb 100644 --- a/substrate/bin/node/inspect/Cargo.toml +++ b/substrate/bin/node/inspect/Cargo.toml @@ -15,7 +15,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.6.1" } thiserror = { workspace = true } sc-cli = { path = "../../../client/cli" } diff --git a/substrate/bin/utils/chain-spec-builder/Cargo.toml b/substrate/bin/utils/chain-spec-builder/Cargo.toml index 996372c8a0f..c126a76b763 100644 --- a/substrate/bin/utils/chain-spec-builder/Cargo.toml +++ b/substrate/bin/utils/chain-spec-builder/Cargo.toml @@ -23,7 +23,7 @@ name = "chain-spec-builder" crate-type = ["rlib"] [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } log = { workspace = true, default-features = true } sc-chain-spec = { path = "../../../client/chain-spec" } serde_json = { workspace = true, default-features = true } diff --git a/substrate/bin/utils/subkey/Cargo.toml b/substrate/bin/utils/subkey/Cargo.toml index 93b1368ca75..8dc4bf254b2 100644 --- a/substrate/bin/utils/subkey/Cargo.toml +++ b/substrate/bin/utils/subkey/Cargo.toml @@ -20,5 +20,5 @@ path = "src/main.rs" name = "subkey" [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } sc-cli = { path = "../../../client/cli" } diff --git a/substrate/client/cli/Cargo.toml b/substrate/client/cli/Cargo.toml index c70a0893c72..47b29555e66 100644 --- a/substrate/client/cli/Cargo.toml +++ b/substrate/client/cli/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] array-bytes = "6.1" chrono = "0.4.31" -clap = { version = "4.5.1", features = ["derive", "string", "wrap_help"] } +clap = { version = "4.5.3", features = ["derive", "string", "wrap_help"] } fdlimit = "0.3.0" futures = "0.3.21" itertools = "0.10.3" diff --git a/substrate/client/storage-monitor/Cargo.toml b/substrate/client/storage-monitor/Cargo.toml index b2120b3efc4..5248ebdf9a6 100644 --- a/substrate/client/storage-monitor/Cargo.toml +++ b/substrate/client/storage-monitor/Cargo.toml @@ -12,7 +12,7 @@ homepage = "https://substrate.io" workspace = true [dependencies] -clap = { version = "4.5.1", features = ["derive", "string"] } +clap = { version = "4.5.3", features = ["derive", "string"] } log = { workspace = true, default-features = true } fs4 = "0.7.0" sp-core = { path = "../../primitives/core" } diff --git a/substrate/frame/election-provider-support/solution-type/fuzzer/Cargo.toml b/substrate/frame/election-provider-support/solution-type/fuzzer/Cargo.toml index 8a73dd38fa2..a27f0f7d4dd 100644 --- a/substrate/frame/election-provider-support/solution-type/fuzzer/Cargo.toml +++ b/substrate/frame/election-provider-support/solution-type/fuzzer/Cargo.toml @@ -16,7 +16,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } honggfuzz = "0.5" rand = { version = "0.8", features = ["small_rng", "std"] } diff --git a/substrate/frame/examples/single-block-migrations/Cargo.toml b/substrate/frame/examples/single-block-migrations/Cargo.toml index 5059b2433c7..613742a6787 100644 --- a/substrate/frame/examples/single-block-migrations/Cargo.toml +++ b/substrate/frame/examples/single-block-migrations/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] docify = { version = "0.2.3", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } frame-support = { path = "../../support", default-features = false } diff --git a/substrate/frame/migrations/Cargo.toml b/substrate/frame/migrations/Cargo.toml index 2914aa9ea97..40059fb9ec4 100644 --- a/substrate/frame/migrations/Cargo.toml +++ b/substrate/frame/migrations/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } docify = "0.1.14" impl-trait-for-tuples = "0.2.2" -log = "0.4.18" +log = "0.4.21" scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } frame-benchmarking = { default-features = false, optional = true, path = "../benchmarking" } diff --git a/substrate/primitives/npos-elections/fuzzer/Cargo.toml b/substrate/primitives/npos-elections/fuzzer/Cargo.toml index bcd908b9705..8e1dbaf2377 100644 --- a/substrate/primitives/npos-elections/fuzzer/Cargo.toml +++ b/substrate/primitives/npos-elections/fuzzer/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } honggfuzz = "0.5" rand = { version = "0.8", features = ["small_rng", "std"] } sp-npos-elections = { path = ".." } diff --git a/substrate/scripts/ci/node-template-release/Cargo.toml b/substrate/scripts/ci/node-template-release/Cargo.toml index cc60d0a4510..4327b685743 100644 --- a/substrate/scripts/ci/node-template-release/Cargo.toml +++ b/substrate/scripts/ci/node-template-release/Cargo.toml @@ -14,7 +14,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } flate2 = "1.0" fs_extra = "1.3" glob = "0.3" diff --git a/substrate/utils/frame/benchmarking-cli/Cargo.toml b/substrate/utils/frame/benchmarking-cli/Cargo.toml index a25ab3a8f5b..b7fbb24b1a0 100644 --- a/substrate/utils/frame/benchmarking-cli/Cargo.toml +++ b/substrate/utils/frame/benchmarking-cli/Cargo.toml @@ -18,7 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] array-bytes = "6.1" chrono = "0.4" -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.6.1" } comfy-table = { version = "7.1.0", default-features = false } handlebars = "5.1.0" diff --git a/substrate/utils/frame/frame-utilities-cli/Cargo.toml b/substrate/utils/frame/frame-utilities-cli/Cargo.toml index 919016b2d8f..3952c9fd219 100644 --- a/substrate/utils/frame/frame-utilities-cli/Cargo.toml +++ b/substrate/utils/frame/frame-utilities-cli/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" workspace = true [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } frame-support = { path = "../../../frame/support" } frame-system = { path = "../../../frame/system" } sc-cli = { path = "../../../client/cli" } diff --git a/substrate/utils/frame/generate-bags/node-runtime/Cargo.toml b/substrate/utils/frame/generate-bags/node-runtime/Cargo.toml index 68d4733614c..37d96d7e12b 100644 --- a/substrate/utils/frame/generate-bags/node-runtime/Cargo.toml +++ b/substrate/utils/frame/generate-bags/node-runtime/Cargo.toml @@ -17,4 +17,4 @@ kitchensink-runtime = { path = "../../../../bin/node/runtime" } generate-bags = { path = ".." } # third-party -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } diff --git a/substrate/utils/frame/try-runtime/cli/Cargo.toml b/substrate/utils/frame/try-runtime/cli/Cargo.toml index d123fc5f62d..3ff57745a2d 100644 --- a/substrate/utils/frame/try-runtime/cli/Cargo.toml +++ b/substrate/utils/frame/try-runtime/cli/Cargo.toml @@ -38,7 +38,7 @@ frame-try-runtime = { path = "../../../../frame/try-runtime", optional = true } substrate-rpc-client = { path = "../../rpc/client" } async-trait = "0.1.74" -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } hex = { version = "0.4.3", default-features = false } log = { workspace = true, default-features = true } parity-scale-codec = "3.6.1" diff --git a/templates/minimal/node/Cargo.toml b/templates/minimal/node/Cargo.toml index 410cfc9f6c3..65aa1e20752 100644 --- a/templates/minimal/node/Cargo.toml +++ b/templates/minimal/node/Cargo.toml @@ -17,7 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } futures = { version = "0.3.21", features = ["thread-pool"] } futures-timer = "3.0.1" jsonrpsee = { version = "0.22", features = ["server"] } diff --git a/templates/parachain/node/Cargo.toml b/templates/parachain/node/Cargo.toml index b4f3a504a4d..63267acdbca 100644 --- a/templates/parachain/node/Cargo.toml +++ b/templates/parachain/node/Cargo.toml @@ -17,7 +17,7 @@ workspace = true # name = "parachain-template-node" [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } log = { workspace = true, default-features = true } codec = { package = "parity-scale-codec", version = "3.0.0" } serde = { features = ["derive"], workspace = true, default-features = true } diff --git a/templates/solochain/node/Cargo.toml b/templates/solochain/node/Cargo.toml index 48bb511bfd1..a0bb5c27ed3 100644 --- a/templates/solochain/node/Cargo.toml +++ b/templates/solochain/node/Cargo.toml @@ -18,7 +18,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.3", features = ["derive"] } futures = { version = "0.3.21", features = ["thread-pool"] } serde_json = { workspace = true, default-features = true } jsonrpsee = { version = "0.22", features = ["server"] } -- GitLab From 6b1179f13b4815685769c9f523720ec9ed0e2ff4 Mon Sep 17 00:00:00 2001 From: jokess123 <163112061+jokess123@users.noreply.github.com> Date: Mon, 18 Mar 2024 06:50:54 +0800 Subject: [PATCH 130/188] Fix typo (#3691) --- bridges/modules/grandpa/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridges/modules/grandpa/README.md b/bridges/modules/grandpa/README.md index 43ee5c316d1..992bd2cc472 100644 --- a/bridges/modules/grandpa/README.md +++ b/bridges/modules/grandpa/README.md @@ -27,7 +27,7 @@ for provided header. There are two main things in GRANDPA that help building light clients: - there's no need to import all headers of the bridged chain. Light client may import finalized headers or just - some of finalized headders that it consider useful. While the validators set stays the same, the client may + some of finalized headers that it consider useful. While the validators set stays the same, the client may import any header that is finalized by this set; - when validators set changes, the GRANDPA gadget adds next set to the header. So light client doesn't need to -- GitLab From 1b5f4243d159fbb7cf7067241aca8a37f3dbf7ed Mon Sep 17 00:00:00 2001 From: Squirrel Date: Mon, 18 Mar 2024 05:29:35 +0000 Subject: [PATCH 131/188] sp-std removal from substrate/primitives (#3274) This PR removes sp-std crate from substrate/primitives sub-directories. For now crates that have `pub use` of sp-std or export macros that would necessitate users of the macros to `extern crate alloc` have been excluded from this PR. There should be no breaking changes in this PR. --------- Co-authored-by: Koute --- Cargo.lock | 31 ------------------- substrate/primitives/arithmetic/Cargo.toml | 2 -- .../primitives/arithmetic/src/biguint.rs | 11 ++++--- .../primitives/arithmetic/src/fixed_point.rs | 19 ++++++------ substrate/primitives/arithmetic/src/lib.rs | 7 +++-- .../primitives/arithmetic/src/per_things.rs | 17 +++++----- .../primitives/arithmetic/src/rational.rs | 10 +++--- .../primitives/authority-discovery/Cargo.toml | 2 -- .../primitives/authority-discovery/src/lib.rs | 4 ++- substrate/primitives/block-builder/Cargo.toml | 3 +- substrate/primitives/block-builder/src/lib.rs | 4 ++- .../primitives/consensus/aura/Cargo.toml | 2 -- .../primitives/consensus/aura/src/lib.rs | 4 ++- .../primitives/consensus/babe/Cargo.toml | 2 -- .../primitives/consensus/babe/src/digests.rs | 3 +- .../primitives/consensus/babe/src/lib.rs | 5 ++- .../primitives/consensus/beefy/Cargo.toml | 2 -- .../consensus/beefy/src/commitment.rs | 11 ++++--- .../primitives/consensus/beefy/src/lib.rs | 4 ++- .../primitives/consensus/beefy/src/mmr.rs | 6 ++-- .../primitives/consensus/beefy/src/payload.rs | 2 +- .../primitives/consensus/beefy/src/witness.rs | 3 +- .../primitives/consensus/grandpa/Cargo.toml | 2 -- .../primitives/consensus/grandpa/src/lib.rs | 4 ++- substrate/primitives/consensus/pow/Cargo.toml | 2 -- substrate/primitives/consensus/pow/src/lib.rs | 5 ++- .../primitives/consensus/sassafras/Cargo.toml | 2 -- .../consensus/sassafras/src/digests.rs | 3 +- .../primitives/consensus/sassafras/src/lib.rs | 4 ++- .../primitives/consensus/sassafras/src/vrf.rs | 3 +- .../primitives/consensus/slots/Cargo.toml | 2 -- .../primitives/crypto/ec-utils/Cargo.toml | 4 +-- .../crypto/ec-utils/src/bls12_377.rs | 2 +- .../crypto/ec-utils/src/bls12_381.rs | 2 +- .../primitives/crypto/ec-utils/src/bw6_761.rs | 2 +- .../crypto/ec-utils/src/ed_on_bls12_377.rs | 2 +- .../src/ed_on_bls12_381_bandersnatch.rs | 2 +- .../primitives/crypto/ec-utils/src/lib.rs | 2 ++ .../primitives/crypto/ec-utils/src/utils.rs | 2 +- substrate/primitives/externalities/Cargo.toml | 3 +- .../externalities/src/extensions.rs | 6 ++-- substrate/primitives/externalities/src/lib.rs | 9 +++--- .../primitives/genesis-builder/Cargo.toml | 3 +- .../primitives/genesis-builder/src/lib.rs | 6 ++-- substrate/primitives/inherents/Cargo.toml | 2 -- substrate/primitives/inherents/src/lib.rs | 4 ++- .../merkle-mountain-range/Cargo.toml | 2 -- .../merkle-mountain-range/src/lib.rs | 12 ++++--- .../merkle-mountain-range/src/utils.rs | 6 ++-- substrate/primitives/metadata-ir/Cargo.toml | 3 +- substrate/primitives/metadata-ir/src/lib.rs | 6 ++-- substrate/primitives/mixnet/Cargo.toml | 2 -- substrate/primitives/mixnet/src/lib.rs | 2 ++ .../primitives/mixnet/src/runtime_api.rs | 2 +- substrate/primitives/mixnet/src/types.rs | 6 ++-- .../primitives/npos-elections/Cargo.toml | 2 -- .../npos-elections/src/assignments.rs | 2 +- .../npos-elections/src/balancing.rs | 2 +- .../primitives/npos-elections/src/helpers.rs | 2 +- .../primitives/npos-elections/src/lib.rs | 17 +++++----- .../primitives/npos-elections/src/mock.rs | 10 +++--- .../primitives/npos-elections/src/node.rs | 7 +++-- .../primitives/npos-elections/src/phragmen.rs | 2 +- .../primitives/npos-elections/src/phragmms.rs | 4 +-- .../primitives/npos-elections/src/pjr.rs | 2 +- .../primitives/npos-elections/src/reduce.rs | 7 +++-- .../primitives/npos-elections/src/traits.rs | 2 +- substrate/primitives/session/Cargo.toml | 2 -- substrate/primitives/session/src/lib.rs | 4 ++- .../primitives/session/src/runtime_api.rs | 2 +- substrate/primitives/staking/Cargo.toml | 2 -- substrate/primitives/staking/src/lib.rs | 7 +++-- substrate/primitives/staking/src/offence.rs | 2 +- substrate/primitives/state-machine/Cargo.toml | 2 -- .../primitives/state-machine/src/backend.rs | 4 +-- substrate/primitives/state-machine/src/ext.rs | 8 ++--- substrate/primitives/state-machine/src/lib.rs | 6 ++-- .../src/overlayed_changes/changeset.rs | 14 ++++----- .../src/overlayed_changes/mod.rs | 16 +++++----- .../src/overlayed_changes/offchain.rs | 4 +-- .../state-machine/src/trie_backend.rs | 6 ++-- .../state-machine/src/trie_backend_essence.rs | 9 +++--- .../primitives/statement-store/Cargo.toml | 2 -- .../primitives/statement-store/src/lib.rs | 4 ++- .../statement-store/src/runtime_api.rs | 2 +- substrate/primitives/storage/Cargo.toml | 2 -- substrate/primitives/storage/src/lib.rs | 15 +++++---- .../primitives/test-primitives/Cargo.toml | 2 -- .../primitives/test-primitives/src/lib.rs | 4 ++- substrate/primitives/timestamp/Cargo.toml | 2 -- substrate/primitives/tracing/Cargo.toml | 2 -- substrate/primitives/tracing/src/lib.rs | 2 ++ substrate/primitives/tracing/src/types.rs | 6 ++-- .../primitives/transaction-pool/src/lib.rs | 2 ++ .../transaction-storage-proof/Cargo.toml | 2 -- .../transaction-storage-proof/src/lib.rs | 5 ++- substrate/primitives/trie/Cargo.toml | 2 -- substrate/primitives/trie/src/error.rs | 2 +- substrate/primitives/trie/src/lib.rs | 7 +++-- substrate/primitives/trie/src/node_codec.rs | 5 +-- .../primitives/trie/src/storage_proof.rs | 8 ++--- substrate/primitives/trie/src/trie_codec.rs | 2 +- substrate/primitives/trie/src/trie_stream.rs | 2 +- .../primitives/wasm-interface/Cargo.toml | 3 +- .../primitives/wasm-interface/src/lib.rs | 7 +++-- substrate/primitives/weights/Cargo.toml | 2 -- substrate/test-utils/runtime/Cargo.toml | 2 -- substrate/test-utils/runtime/src/extrinsic.rs | 1 - substrate/test-utils/runtime/src/lib.rs | 13 +++++--- .../runtime/src/substrate_test_pallet.rs | 4 +-- 110 files changed, 254 insertions(+), 278 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3535d509ff..d641f554431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18402,7 +18402,6 @@ dependencies = [ "scale-info", "serde", "sp-crypto-hashing", - "sp-std 14.0.0", "static_assertions", ] @@ -18444,7 +18443,6 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -18454,7 +18452,6 @@ dependencies = [ "sp-api", "sp-inherents", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -18501,7 +18498,6 @@ dependencies = [ "sp-consensus-slots", "sp-inherents", "sp-runtime", - "sp-std 14.0.0", "sp-timestamp", ] @@ -18519,7 +18515,6 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", - "sp-std 14.0.0", "sp-timestamp", ] @@ -18540,7 +18535,6 @@ dependencies = [ "sp-keystore", "sp-mmr-primitives", "sp-runtime", - "sp-std 14.0.0", "strum 0.24.1", "w3f-bls", ] @@ -18559,7 +18553,6 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -18570,7 +18563,6 @@ dependencies = [ "sp-api", "sp-core", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -18585,7 +18577,6 @@ dependencies = [ "sp-consensus-slots", "sp-core", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -18595,7 +18586,6 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std 14.0.0", "sp-timestamp", ] @@ -18711,7 +18701,6 @@ dependencies = [ "ark-ed-on-bls12-381-bandersnatch-ext", "ark-scale 0.0.12", "sp-runtime-interface 24.0.0", - "sp-std 14.0.0", ] [[package]] @@ -18781,7 +18770,6 @@ version = "0.25.0" dependencies = [ "environmental", "parity-scale-codec", - "sp-std 14.0.0", "sp-storage 19.0.0", ] @@ -18792,7 +18780,6 @@ dependencies = [ "serde_json", "sp-api", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -18805,7 +18792,6 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std 14.0.0", "thiserror", ] @@ -18870,7 +18856,6 @@ dependencies = [ "frame-metadata", "parity-scale-codec", "scale-info", - "sp-std 14.0.0", ] [[package]] @@ -18881,7 +18866,6 @@ dependencies = [ "scale-info", "sp-api", "sp-application-crypto", - "sp-std 14.0.0", ] [[package]] @@ -18898,7 +18882,6 @@ dependencies = [ "sp-core", "sp-debug-derive 14.0.0", "sp-runtime", - "sp-std 14.0.0", "thiserror", ] @@ -18913,7 +18896,6 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-runtime", - "sp-std 14.0.0", "substrate-test-utils", ] @@ -19100,7 +19082,6 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-staking", - "sp-std 14.0.0", ] [[package]] @@ -19113,7 +19094,6 @@ dependencies = [ "serde", "sp-core", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -19133,7 +19113,6 @@ dependencies = [ "sp-externalities 0.25.0", "sp-panic-handler", "sp-runtime", - "sp-std 14.0.0", "sp-trie", "thiserror", "tracing", @@ -19159,7 +19138,6 @@ dependencies = [ "sp-externalities 0.25.0", "sp-runtime", "sp-runtime-interface 24.0.0", - "sp-std 14.0.0", "thiserror", "x25519-dalek 2.0.0", ] @@ -19195,7 +19173,6 @@ dependencies = [ "ref-cast", "serde", "sp-debug-derive 14.0.0", - "sp-std 14.0.0", ] [[package]] @@ -19208,7 +19185,6 @@ dependencies = [ "sp-application-crypto", "sp-core", "sp-runtime", - "sp-std 14.0.0", ] [[package]] @@ -19219,7 +19195,6 @@ dependencies = [ "parity-scale-codec", "sp-inherents", "sp-runtime", - "sp-std 14.0.0", "thiserror", ] @@ -19240,7 +19215,6 @@ name = "sp-tracing" version = "16.0.0" dependencies = [ "parity-scale-codec", - "sp-std 14.0.0", "tracing", "tracing-core", "tracing-subscriber 0.2.25", @@ -19264,7 +19238,6 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", - "sp-std 14.0.0", "sp-trie", ] @@ -19287,7 +19260,6 @@ dependencies = [ "sp-core", "sp-externalities 0.25.0", "sp-runtime", - "sp-std 14.0.0", "thiserror", "tracing", "trie-bench", @@ -19344,7 +19316,6 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", - "sp-std 14.0.0", "wasmtime", ] @@ -19360,7 +19331,6 @@ dependencies = [ "smallvec", "sp-arithmetic", "sp-debug-derive 14.0.0", - "sp-std 14.0.0", ] [[package]] @@ -19971,7 +19941,6 @@ dependencies = [ "sp-runtime", "sp-session", "sp-state-machine", - "sp-std 14.0.0", "sp-tracing 16.0.0", "sp-transaction-pool", "sp-trie", diff --git a/substrate/primitives/arithmetic/Cargo.toml b/substrate/primitives/arithmetic/Cargo.toml index 301821ad689..29c406b10b7 100644 --- a/substrate/primitives/arithmetic/Cargo.toml +++ b/substrate/primitives/arithmetic/Cargo.toml @@ -26,7 +26,6 @@ num-traits = { version = "0.2.17", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], optional = true, workspace = true } static_assertions = "1.1.0" -sp-std = { path = "../std", default-features = false } [dev-dependencies] criterion = "0.4.0" @@ -42,7 +41,6 @@ std = [ "scale-info/std", "serde/std", "sp-crypto-hashing/std", - "sp-std/std", ] # Serde support without relying on std features. serde = ["dep:serde", "scale-info/serde"] diff --git a/substrate/primitives/arithmetic/src/biguint.rs b/substrate/primitives/arithmetic/src/biguint.rs index d92b08c8eca..164ec67a603 100644 --- a/substrate/primitives/arithmetic/src/biguint.rs +++ b/substrate/primitives/arithmetic/src/biguint.rs @@ -17,9 +17,10 @@ //! Infinite precision unsigned integer for substrate runtime. +use alloc::{vec, vec::Vec}; use codec::{Decode, Encode}; +use core::{cell::RefCell, cmp::Ordering, ops}; use num_traits::{One, Zero}; -use sp_std::{cell::RefCell, cmp::Ordering, ops, prelude::*, vec}; // A sensible value for this would be half of the dword size of the host machine. Since the // runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively @@ -35,7 +36,7 @@ const SHIFT: usize = 32; const B: Double = Single::max_value() as Double + 1; static_assertions::const_assert!( - sp_std::mem::size_of::() - sp_std::mem::size_of::() == SHIFT / 8 + core::mem::size_of::() - core::mem::size_of::() == SHIFT / 8 ); /// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers. @@ -438,9 +439,9 @@ impl BigUint { } } -impl sp_std::fmt::Debug for BigUint { +impl core::fmt::Debug for BigUint { #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "BigUint {{ {:?} ({:?})}}", @@ -450,7 +451,7 @@ impl sp_std::fmt::Debug for BigUint { } #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { Ok(()) } } diff --git a/substrate/primitives/arithmetic/src/fixed_point.rs b/substrate/primitives/arithmetic/src/fixed_point.rs index ce14d2957b5..46c09df2186 100644 --- a/substrate/primitives/arithmetic/src/fixed_point.rs +++ b/substrate/primitives/arithmetic/src/fixed_point.rs @@ -26,17 +26,16 @@ use crate::{ PerThing, Perbill, Rounding, SignedRounding, }; use codec::{CompactAs, Decode, Encode}; -use sp_std::{ +use core::{ fmt::Debug, ops::{self, Add, Div, Mul, Sub}, - prelude::*, }; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(all(not(feature = "std"), feature = "serde"))] -use sp_std::alloc::string::{String, ToString}; +use alloc::string::{String, ToString}; /// Integer types that can be used to interact with `FixedPointNumber` implementations. pub trait FixedPointOperand: @@ -899,9 +898,9 @@ macro_rules! implement_fixed { } } - impl sp_std::fmt::Debug for $name { + impl ::core::fmt::Debug for $name { #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let integral = { let int = self.0 / Self::accuracy(); let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" }; @@ -917,7 +916,7 @@ macro_rules! implement_fixed { } #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + fn fmt(&self, _: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { Ok(()) } } @@ -933,13 +932,13 @@ macro_rules! implement_fixed { } } - impl sp_std::fmt::Display for $name { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + impl ::core::fmt::Display for $name { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}", self.0) } } - impl sp_std::str::FromStr for $name { + impl ::core::str::FromStr for $name { type Err = &'static str; fn from_str(s: &str) -> Result { @@ -969,7 +968,7 @@ macro_rules! implement_fixed { where D: Deserializer<'de>, { - use sp_std::str::FromStr; + use ::core::str::FromStr; let s = String::deserialize(deserializer)?; $name::from_str(&s).map_err(de::Error::custom) } diff --git a/substrate/primitives/arithmetic/src/lib.rs b/substrate/primitives/arithmetic/src/lib.rs index 900f0b75c3b..33992e15423 100644 --- a/substrate/primitives/arithmetic/src/lib.rs +++ b/substrate/primitives/arithmetic/src/lib.rs @@ -19,6 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + /// Copied from `sp-runtime` and documented there. #[macro_export] macro_rules! assert_eq_error_rate { @@ -49,7 +51,8 @@ pub use per_things::{ }; pub use rational::{MultiplyRational, Rational128, RationalInfinite}; -use sp_std::{cmp::Ordering, fmt::Debug, prelude::*}; +use alloc::vec::Vec; +use core::{cmp::Ordering, fmt::Debug}; use traits::{BaseArithmetic, One, SaturatedConversion, Unsigned, Zero}; use codec::{Decode, Encode, MaxEncodedLen}; @@ -429,7 +432,7 @@ mod normalize_tests { mod threshold_compare_tests { use super::*; use crate::traits::Saturating; - use sp_std::cmp::Ordering; + use core::cmp::Ordering; #[test] fn epsilon_ord_works() { diff --git a/substrate/primitives/arithmetic/src/per_things.rs b/substrate/primitives/arithmetic/src/per_things.rs index fe88b72e24c..057bfd7bf88 100644 --- a/substrate/primitives/arithmetic/src/per_things.rs +++ b/substrate/primitives/arithmetic/src/per_things.rs @@ -23,12 +23,11 @@ use crate::traits::{ Saturating, UniqueSaturatedInto, Unsigned, Zero, }; use codec::{CompactAs, Encode}; -use num_traits::{Pow, SaturatingAdd, SaturatingSub}; -use sp_std::{ +use core::{ fmt, ops, ops::{Add, Sub}, - prelude::*, }; +use num_traits::{Pow, SaturatingAdd, SaturatingSub}; /// Get the inner type of a `PerThing`. pub type InnerOf

=

::Inner; @@ -414,7 +413,7 @@ pub trait PerThing: } /// The rounding method to use for unsigned quantities. -#[derive(Copy, Clone, sp_std::fmt::Debug)] +#[derive(Copy, Clone, core::fmt::Debug)] pub enum Rounding { // Towards infinity. Up, @@ -427,7 +426,7 @@ pub enum Rounding { } /// The rounding method to use. -#[derive(Copy, Clone, sp_std::fmt::Debug)] +#[derive(Copy, Clone, core::fmt::Debug)] pub enum SignedRounding { // Towards positive infinity. High, @@ -580,8 +579,8 @@ macro_rules! implement_per_thing { } #[cfg(feature = "std")] - impl sp_std::fmt::Debug for $name { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + impl core::fmt::Debug for $name { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { if $max == <$type>::max_value() { // Not a power of ten: show as N/D and approx % let pc = (self.0 as f64) / (self.0 as f64) * 100f64; @@ -606,8 +605,8 @@ macro_rules! implement_per_thing { } #[cfg(not(feature = "std"))] - impl sp_std::fmt::Debug for $name { - fn fmt(&self, fmt: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + impl core::fmt::Debug for $name { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { if $max == <$type>::max_value() { // Not a power of ten: show as N/D and approx % write!(fmt, "{}/{}", self.0, $max) diff --git a/substrate/primitives/arithmetic/src/rational.rs b/substrate/primitives/arithmetic/src/rational.rs index ebd89c615a3..2ec83e6fd86 100644 --- a/substrate/primitives/arithmetic/src/rational.rs +++ b/substrate/primitives/arithmetic/src/rational.rs @@ -16,8 +16,8 @@ // limitations under the License. use crate::{biguint::BigUint, helpers_128bit, Rounding}; +use core::cmp::Ordering; use num_traits::{Bounded, One, Zero}; -use sp_std::{cmp::Ordering, prelude::*}; /// A wrapper for any rational number with infinitely large numerator and denominator. /// @@ -92,15 +92,15 @@ impl From for RationalInfinite { pub struct Rational128(u128, u128); #[cfg(feature = "std")] -impl sp_std::fmt::Debug for Rational128 { - fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { +impl core::fmt::Debug for Rational128 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Rational128({} / {} ≈ {:.8})", self.0, self.1, self.0 as f64 / self.1 as f64) } } #[cfg(not(feature = "std"))] -impl sp_std::fmt::Debug for Rational128 { - fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { +impl core::fmt::Debug for Rational128 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Rational128({} / {})", self.0, self.1) } } diff --git a/substrate/primitives/authority-discovery/Cargo.toml b/substrate/primitives/authority-discovery/Cargo.toml index 70f00897cdd..8ee8bb94ed9 100644 --- a/substrate/primitives/authority-discovery/Cargo.toml +++ b/substrate/primitives/authority-discovery/Cargo.toml @@ -21,7 +21,6 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive sp-api = { path = "../api", default-features = false } sp-application-crypto = { path = "../application-crypto", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } [features] default = ["std"] @@ -31,7 +30,6 @@ std = [ "sp-api/std", "sp-application-crypto/std", "sp-runtime/std", - "sp-std/std", ] serde = [ "scale-info/serde", diff --git a/substrate/primitives/authority-discovery/src/lib.rs b/substrate/primitives/authority-discovery/src/lib.rs index 3b25e39d404..5aba76a3abb 100644 --- a/substrate/primitives/authority-discovery/src/lib.rs +++ b/substrate/primitives/authority-discovery/src/lib.rs @@ -19,7 +19,9 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::vec::Vec; +extern crate alloc; + +use alloc::vec::Vec; mod app { use sp_application_crypto::{app_crypto, key_types::AUTHORITY_DISCOVERY, sr25519}; diff --git a/substrate/primitives/block-builder/Cargo.toml b/substrate/primitives/block-builder/Cargo.toml index c1317facd7f..cc4b1085154 100644 --- a/substrate/primitives/block-builder/Cargo.toml +++ b/substrate/primitives/block-builder/Cargo.toml @@ -19,8 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] sp-api = { path = "../api", default-features = false } sp-inherents = { path = "../inherents", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } [features] default = ["std"] -std = ["sp-api/std", "sp-inherents/std", "sp-runtime/std", "sp-std/std"] +std = ["sp-api/std", "sp-inherents/std", "sp-runtime/std"] diff --git a/substrate/primitives/block-builder/src/lib.rs b/substrate/primitives/block-builder/src/lib.rs index 29e04857f46..9d03aa4d7a0 100644 --- a/substrate/primitives/block-builder/src/lib.rs +++ b/substrate/primitives/block-builder/src/lib.rs @@ -19,6 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + use sp_inherents::{CheckInherentsResult, InherentData}; use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; @@ -44,7 +46,7 @@ sp_api::decl_runtime_apis! { /// Generate inherent extrinsics. The inherent data will vary from chain to chain. fn inherent_extrinsics( inherent: InherentData, - ) -> sp_std::vec::Vec<::Extrinsic>; + ) -> alloc::vec::Vec<::Extrinsic>; /// Check that the inherents are valid. The inherent data will vary from chain to chain. fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; diff --git a/substrate/primitives/consensus/aura/Cargo.toml b/substrate/primitives/consensus/aura/Cargo.toml index 52f6bc22ba4..0cedc59ea8f 100644 --- a/substrate/primitives/consensus/aura/Cargo.toml +++ b/substrate/primitives/consensus/aura/Cargo.toml @@ -24,7 +24,6 @@ sp-application-crypto = { path = "../../application-crypto", default-features = sp-consensus-slots = { path = "../slots", default-features = false } sp-inherents = { path = "../../inherents", default-features = false } sp-runtime = { path = "../../runtime", default-features = false } -sp-std = { path = "../../std", default-features = false } sp-timestamp = { path = "../../timestamp", default-features = false } [features] @@ -38,7 +37,6 @@ std = [ "sp-consensus-slots/std", "sp-inherents/std", "sp-runtime/std", - "sp-std/std", "sp-timestamp/std", ] diff --git a/substrate/primitives/consensus/aura/src/lib.rs b/substrate/primitives/consensus/aura/src/lib.rs index 78409e84e93..5173d5516cf 100644 --- a/substrate/primitives/consensus/aura/src/lib.rs +++ b/substrate/primitives/consensus/aura/src/lib.rs @@ -19,9 +19,11 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + +use alloc::vec::Vec; use codec::{Codec, Decode, Encode}; use sp_runtime::ConsensusEngineId; -use sp_std::vec::Vec; pub mod digests; pub mod inherents; diff --git a/substrate/primitives/consensus/babe/Cargo.toml b/substrate/primitives/consensus/babe/Cargo.toml index 8b3006f79a7..724b9fd3e28 100644 --- a/substrate/primitives/consensus/babe/Cargo.toml +++ b/substrate/primitives/consensus/babe/Cargo.toml @@ -26,7 +26,6 @@ sp-consensus-slots = { path = "../slots", default-features = false } sp-core = { path = "../../core", default-features = false } sp-inherents = { path = "../../inherents", default-features = false } sp-runtime = { path = "../../runtime", default-features = false } -sp-std = { path = "../../std", default-features = false } sp-timestamp = { path = "../../timestamp", optional = true } [features] @@ -42,7 +41,6 @@ std = [ "sp-core/std", "sp-inherents/std", "sp-runtime/std", - "sp-std/std", "sp-timestamp/std", ] diff --git a/substrate/primitives/consensus/babe/src/digests.rs b/substrate/primitives/consensus/babe/src/digests.rs index afc967e3af3..e7af8c5763a 100644 --- a/substrate/primitives/consensus/babe/src/digests.rs +++ b/substrate/primitives/consensus/babe/src/digests.rs @@ -22,9 +22,10 @@ use super::{ BabeEpochConfiguration, Randomness, Slot, BABE_ENGINE_ID, }; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; use sp_core::sr25519::vrf::VrfSignature; use sp_runtime::{DigestItem, RuntimeDebug}; -use sp_std::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; diff --git a/substrate/primitives/consensus/babe/src/lib.rs b/substrate/primitives/consensus/babe/src/lib.rs index ff0b4568226..6eb75b270a0 100644 --- a/substrate/primitives/consensus/babe/src/lib.rs +++ b/substrate/primitives/consensus/babe/src/lib.rs @@ -20,15 +20,18 @@ #![forbid(unsafe_code, missing_docs, unused_variables, unused_imports)] #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + pub mod digests; pub mod inherents; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use sp_runtime::{traits::Header, ConsensusEngineId, RuntimeDebug}; -use sp_std::vec::Vec; use crate::digests::{NextConfigDescriptor, NextEpochDescriptor}; diff --git a/substrate/primitives/consensus/beefy/Cargo.toml b/substrate/primitives/consensus/beefy/Cargo.toml index 8ab817d52ef..fbcc6e0c104 100644 --- a/substrate/primitives/consensus/beefy/Cargo.toml +++ b/substrate/primitives/consensus/beefy/Cargo.toml @@ -26,7 +26,6 @@ sp-io = { path = "../../io", default-features = false } sp-mmr-primitives = { path = "../../merkle-mountain-range", default-features = false } sp-runtime = { path = "../../runtime", default-features = false } sp-keystore = { path = "../../keystore", default-features = false } -sp-std = { path = "../../std", default-features = false } strum = { version = "0.24.1", features = ["derive"], default-features = false } lazy_static = { version = "1.4.0", optional = true } @@ -49,7 +48,6 @@ std = [ "sp-keystore/std", "sp-mmr-primitives/std", "sp-runtime/std", - "sp-std/std", "strum/std", ] diff --git a/substrate/primitives/consensus/beefy/src/commitment.rs b/substrate/primitives/consensus/beefy/src/commitment.rs index 335c6b604f0..4fd9e1b0a6e 100644 --- a/substrate/primitives/consensus/beefy/src/commitment.rs +++ b/substrate/primitives/consensus/beefy/src/commitment.rs @@ -15,9 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use alloc::{vec, vec::Vec}; use codec::{Decode, Encode, Error, Input}; +use core::cmp; use scale_info::TypeInfo; -use sp_std::{cmp, prelude::*}; use crate::{Payload, ValidatorSetId}; @@ -97,10 +98,10 @@ pub struct SignedCommitment { pub signatures: Vec>, } -impl sp_std::fmt::Display +impl core::fmt::Display for SignedCommitment { - fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let signatures_count = self.signatures.iter().filter(|s| s.is_some()).count(); write!( f, @@ -254,8 +255,8 @@ pub enum VersionedFinalityProof { V1(SignedCommitment), } -impl sp_std::fmt::Display for VersionedFinalityProof { - fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { +impl core::fmt::Display for VersionedFinalityProof { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { VersionedFinalityProof::V1(sc) => write!(f, "VersionedFinalityProof::V1({})", sc), } diff --git a/substrate/primitives/consensus/beefy/src/lib.rs b/substrate/primitives/consensus/beefy/src/lib.rs index 1c3801e3a50..b3f62ead736 100644 --- a/substrate/primitives/consensus/beefy/src/lib.rs +++ b/substrate/primitives/consensus/beefy/src/lib.rs @@ -31,6 +31,8 @@ //! it will use a different set of keys. For Polkadot use case we plan to use `secp256k1` for BEEFY, //! while GRANDPA uses `ed25519`. +extern crate alloc; + mod commitment; mod payload; @@ -44,13 +46,13 @@ pub mod test_utils; pub use commitment::{Commitment, SignedCommitment, VersionedFinalityProof}; pub use payload::{known_payloads, BeefyPayloadId, Payload, PayloadProvider}; +use alloc::vec::Vec; use codec::{Codec, Decode, Encode}; use core::fmt::{Debug, Display}; use scale_info::TypeInfo; use sp_application_crypto::{AppCrypto, AppPublic, ByteArray, RuntimeAppPublic}; use sp_core::H256; use sp_runtime::traits::{Hash, Keccak256, NumberFor}; -use sp_std::prelude::*; /// Key type for BEEFY module. pub const KEY_TYPE: sp_core::crypto::KeyTypeId = sp_application_crypto::key_types::BEEFY; diff --git a/substrate/primitives/consensus/beefy/src/mmr.rs b/substrate/primitives/consensus/beefy/src/mmr.rs index 1b9a45f8687..74851ece7ac 100644 --- a/substrate/primitives/consensus/beefy/src/mmr.rs +++ b/substrate/primitives/consensus/beefy/src/mmr.rs @@ -26,7 +26,8 @@ //! but we imagine they will be useful for other chains that either want to bridge with Polkadot //! or are completely standalone, but heavily inspired by Polkadot. -use crate::{ecdsa_crypto::AuthorityId, ConsensusLog, MmrRootHash, Vec, BEEFY_ENGINE_ID}; +use crate::{ecdsa_crypto::AuthorityId, ConsensusLog, MmrRootHash, BEEFY_ENGINE_ID}; +use alloc::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime::{ @@ -150,10 +151,11 @@ pub use mmr_root_provider::MmrRootProvider; mod mmr_root_provider { use super::*; use crate::{known_payloads, payload::PayloadProvider, Payload}; + use alloc::sync::Arc; + use core::marker::PhantomData; use sp_api::ProvideRuntimeApi; use sp_mmr_primitives::MmrApi; use sp_runtime::traits::NumberFor; - use sp_std::{marker::PhantomData, sync::Arc}; /// A [`crate::Payload`] provider where payload is Merkle Mountain Range root hash. /// diff --git a/substrate/primitives/consensus/beefy/src/payload.rs b/substrate/primitives/consensus/beefy/src/payload.rs index d520de445c9..dff017b49e0 100644 --- a/substrate/primitives/consensus/beefy/src/payload.rs +++ b/substrate/primitives/consensus/beefy/src/payload.rs @@ -15,10 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use alloc::{vec, vec::Vec}; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::traits::Block; -use sp_std::prelude::*; /// Id of different payloads in the [`crate::Commitment`] data. pub type BeefyPayloadId = [u8; 2]; diff --git a/substrate/primitives/consensus/beefy/src/witness.rs b/substrate/primitives/consensus/beefy/src/witness.rs index b633453340b..cfffc94254a 100644 --- a/substrate/primitives/consensus/beefy/src/witness.rs +++ b/substrate/primitives/consensus/beefy/src/witness.rs @@ -23,9 +23,8 @@ //! verification. This allows lowering the data and computation cost of verifying the //! signed commitment. -use sp_std::prelude::*; - use crate::commitment::{Commitment, SignedCommitment}; +use alloc::vec::Vec; /// A light form of [SignedCommitment]. /// diff --git a/substrate/primitives/consensus/grandpa/Cargo.toml b/substrate/primitives/consensus/grandpa/Cargo.toml index b06208a4308..1f2da55c5a1 100644 --- a/substrate/primitives/consensus/grandpa/Cargo.toml +++ b/substrate/primitives/consensus/grandpa/Cargo.toml @@ -27,7 +27,6 @@ sp-application-crypto = { path = "../../application-crypto", default-features = sp-core = { path = "../../core", default-features = false } sp-keystore = { path = "../../keystore", default-features = false, optional = true } sp-runtime = { path = "../../runtime", default-features = false } -sp-std = { path = "../../std", default-features = false } [features] default = ["std"] @@ -42,7 +41,6 @@ std = [ "sp-core/std", "sp-keystore/std", "sp-runtime/std", - "sp-std/std", ] # Serde support without relying on std features. diff --git a/substrate/primitives/consensus/grandpa/src/lib.rs b/substrate/primitives/consensus/grandpa/src/lib.rs index 1cf5504c5e7..75ed81894c2 100644 --- a/substrate/primitives/consensus/grandpa/src/lib.rs +++ b/substrate/primitives/consensus/grandpa/src/lib.rs @@ -19,9 +19,12 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + #[cfg(feature = "serde")] use serde::Serialize; +use alloc::vec::Vec; use codec::{Codec, Decode, Encode}; use scale_info::TypeInfo; #[cfg(feature = "std")] @@ -30,7 +33,6 @@ use sp_runtime::{ traits::{Header as HeaderT, NumberFor}, ConsensusEngineId, RuntimeDebug, }; -use sp_std::vec::Vec; /// The log target to be used by client code. pub const CLIENT_LOG_TARGET: &str = "grandpa"; diff --git a/substrate/primitives/consensus/pow/Cargo.toml b/substrate/primitives/consensus/pow/Cargo.toml index 8147b063f6d..7a884f865fb 100644 --- a/substrate/primitives/consensus/pow/Cargo.toml +++ b/substrate/primitives/consensus/pow/Cargo.toml @@ -20,7 +20,6 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features = sp-api = { path = "../../api", default-features = false } sp-core = { path = "../../core", default-features = false } sp-runtime = { path = "../../runtime", default-features = false } -sp-std = { path = "../../std", default-features = false } [features] default = ["std"] @@ -29,5 +28,4 @@ std = [ "sp-api/std", "sp-core/std", "sp-runtime/std", - "sp-std/std", ] diff --git a/substrate/primitives/consensus/pow/src/lib.rs b/substrate/primitives/consensus/pow/src/lib.rs index f37aae1c5c0..c14d23cf068 100644 --- a/substrate/primitives/consensus/pow/src/lib.rs +++ b/substrate/primitives/consensus/pow/src/lib.rs @@ -19,9 +19,12 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; use codec::Decode; use sp_runtime::ConsensusEngineId; -use sp_std::vec::Vec; /// The `ConsensusEngineId` of PoW. pub const POW_ENGINE_ID: ConsensusEngineId = [b'p', b'o', b'w', b'_']; diff --git a/substrate/primitives/consensus/sassafras/Cargo.toml b/substrate/primitives/consensus/sassafras/Cargo.toml index b707ad18b5b..085709d4c8b 100644 --- a/substrate/primitives/consensus/sassafras/Cargo.toml +++ b/substrate/primitives/consensus/sassafras/Cargo.toml @@ -26,7 +26,6 @@ sp-application-crypto = { path = "../../application-crypto", default-features = sp-consensus-slots = { path = "../slots", default-features = false } sp-core = { path = "../../core", default-features = false, features = ["bandersnatch-experimental"] } sp-runtime = { path = "../../runtime", default-features = false } -sp-std = { path = "../../std", default-features = false } [features] default = ["std"] @@ -39,7 +38,6 @@ std = [ "sp-consensus-slots/std", "sp-core/std", "sp-runtime/std", - "sp-std/std", ] # Serde support without relying on std features. diff --git a/substrate/primitives/consensus/sassafras/src/digests.rs b/substrate/primitives/consensus/sassafras/src/digests.rs index 5274f1309d8..64190a41ce1 100644 --- a/substrate/primitives/consensus/sassafras/src/digests.rs +++ b/substrate/primitives/consensus/sassafras/src/digests.rs @@ -25,8 +25,9 @@ use crate::{ use scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; use sp_runtime::{DigestItem, RuntimeDebug}; -use sp_std::vec::Vec; /// Epoch slot claim digest entry. /// diff --git a/substrate/primitives/consensus/sassafras/src/lib.rs b/substrate/primitives/consensus/sassafras/src/lib.rs index 1752f765886..c1fea74d045 100644 --- a/substrate/primitives/consensus/sassafras/src/lib.rs +++ b/substrate/primitives/consensus/sassafras/src/lib.rs @@ -21,11 +21,13 @@ #![forbid(unsafe_code, missing_docs, unused_variables, unused_imports)] #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + +use alloc::vec::Vec; use scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_core::crypto::KeyTypeId; use sp_runtime::{ConsensusEngineId, RuntimeDebug}; -use sp_std::vec::Vec; pub use sp_consensus_slots::{Slot, SlotDuration}; diff --git a/substrate/primitives/consensus/sassafras/src/vrf.rs b/substrate/primitives/consensus/sassafras/src/vrf.rs index 5deacd8e994..815edb5eb66 100644 --- a/substrate/primitives/consensus/sassafras/src/vrf.rs +++ b/substrate/primitives/consensus/sassafras/src/vrf.rs @@ -18,9 +18,10 @@ //! Utilities related to VRF input, pre-output and signatures. use crate::{Randomness, TicketBody, TicketId}; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; use scale_codec::Encode; use sp_consensus_slots::Slot; -use sp_std::vec::Vec; pub use sp_core::bandersnatch::{ ring_vrf::{RingProver, RingVerifier, RingVerifierData, RingVrfSignature}, diff --git a/substrate/primitives/consensus/slots/Cargo.toml b/substrate/primitives/consensus/slots/Cargo.toml index 8372b2b04a6..94c02dba203 100644 --- a/substrate/primitives/consensus/slots/Cargo.toml +++ b/substrate/primitives/consensus/slots/Cargo.toml @@ -19,7 +19,6 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], optional = true, workspace = true } -sp-std = { path = "../../std", default-features = false } sp-timestamp = { path = "../../timestamp", default-features = false } [features] @@ -28,7 +27,6 @@ std = [ "codec/std", "scale-info/std", "serde/std", - "sp-std/std", "sp-timestamp/std", ] diff --git a/substrate/primitives/crypto/ec-utils/Cargo.toml b/substrate/primitives/crypto/ec-utils/Cargo.toml index 43daad08921..142a5abf9b3 100644 --- a/substrate/primitives/crypto/ec-utils/Cargo.toml +++ b/substrate/primitives/crypto/ec-utils/Cargo.toml @@ -28,7 +28,6 @@ ark-ed-on-bls12-377-ext = { version = "0.4.1", default-features = false, optiona ark-ed-on-bls12-377 = { version = "0.4.0", default-features = false, optional = true } ark-scale = { version = "0.0.12", default-features = false, features = ["hazmat"], optional = true } sp-runtime-interface = { path = "../../runtime-interface", default-features = false, optional = true } -sp-std = { path = "../../std", default-features = false, optional = true } [features] default = ["std"] @@ -47,9 +46,8 @@ std = [ "ark-ed-on-bls12-381-bandersnatch?/std", "ark-scale?/std", "sp-runtime-interface?/std", - "sp-std?/std", ] -common = ["ark-ec", "ark-scale", "sp-runtime-interface", "sp-std"] +common = ["ark-ec", "ark-scale", "sp-runtime-interface"] bls12-377 = ["ark-bls12-377", "ark-bls12-377-ext", "common"] bls12-381 = ["ark-bls12-381", "ark-bls12-381-ext", "common"] bw6-761 = ["ark-bw6-761", "ark-bw6-761-ext", "common"] diff --git a/substrate/primitives/crypto/ec-utils/src/bls12_377.rs b/substrate/primitives/crypto/ec-utils/src/bls12_377.rs index 8f19a2c4a19..a1ea5dbbf93 100644 --- a/substrate/primitives/crypto/ec-utils/src/bls12_377.rs +++ b/substrate/primitives/crypto/ec-utils/src/bls12_377.rs @@ -18,10 +18,10 @@ //! *BLS12-377* types and host functions. use crate::utils; +use alloc::vec::Vec; use ark_bls12_377_ext::CurveHooks; use ark_ec::{pairing::Pairing, CurveConfig}; use sp_runtime_interface::runtime_interface; -use sp_std::vec::Vec; /// First pairing group definitions. pub mod g1 { diff --git a/substrate/primitives/crypto/ec-utils/src/bls12_381.rs b/substrate/primitives/crypto/ec-utils/src/bls12_381.rs index 99a0289b7ad..5e02862ed7b 100644 --- a/substrate/primitives/crypto/ec-utils/src/bls12_381.rs +++ b/substrate/primitives/crypto/ec-utils/src/bls12_381.rs @@ -18,10 +18,10 @@ //! *BLS12-381* types and host functions. use crate::utils; +use alloc::vec::Vec; use ark_bls12_381_ext::CurveHooks; use ark_ec::{pairing::Pairing, CurveConfig}; use sp_runtime_interface::runtime_interface; -use sp_std::vec::Vec; /// First pairing group definitions. pub mod g1 { diff --git a/substrate/primitives/crypto/ec-utils/src/bw6_761.rs b/substrate/primitives/crypto/ec-utils/src/bw6_761.rs index a68abf6e43e..4ee1035f670 100644 --- a/substrate/primitives/crypto/ec-utils/src/bw6_761.rs +++ b/substrate/primitives/crypto/ec-utils/src/bw6_761.rs @@ -18,10 +18,10 @@ //! *BW6-761* types and host functions. use crate::utils; +use alloc::vec::Vec; use ark_bw6_761_ext::CurveHooks; use ark_ec::{pairing::Pairing, CurveConfig}; use sp_runtime_interface::runtime_interface; -use sp_std::vec::Vec; /// First pairing group definitions. pub mod g1 { diff --git a/substrate/primitives/crypto/ec-utils/src/ed_on_bls12_377.rs b/substrate/primitives/crypto/ec-utils/src/ed_on_bls12_377.rs index a03be41b854..e068507b347 100644 --- a/substrate/primitives/crypto/ec-utils/src/ed_on_bls12_377.rs +++ b/substrate/primitives/crypto/ec-utils/src/ed_on_bls12_377.rs @@ -18,10 +18,10 @@ //! *Ed-on-BLS12-377* types and host functions. use crate::utils; +use alloc::vec::Vec; use ark_ec::CurveConfig; use ark_ed_on_bls12_377_ext::CurveHooks; use sp_runtime_interface::runtime_interface; -use sp_std::vec::Vec; /// Curve hooks jumping into [`host_calls`] host functions. #[derive(Copy, Clone)] diff --git a/substrate/primitives/crypto/ec-utils/src/ed_on_bls12_381_bandersnatch.rs b/substrate/primitives/crypto/ec-utils/src/ed_on_bls12_381_bandersnatch.rs index 9d63f358765..487ad98dac6 100644 --- a/substrate/primitives/crypto/ec-utils/src/ed_on_bls12_381_bandersnatch.rs +++ b/substrate/primitives/crypto/ec-utils/src/ed_on_bls12_381_bandersnatch.rs @@ -19,10 +19,10 @@ //! computationally expensive operations. use crate::utils; +use alloc::vec::Vec; use ark_ec::CurveConfig; use ark_ed_on_bls12_381_bandersnatch_ext::CurveHooks; use sp_runtime_interface::runtime_interface; -use sp_std::vec::Vec; /// Curve hooks jumping into [`host_calls`] host functions. #[derive(Copy, Clone)] diff --git a/substrate/primitives/crypto/ec-utils/src/lib.rs b/substrate/primitives/crypto/ec-utils/src/lib.rs index 970ad71765a..3254bbe648f 100644 --- a/substrate/primitives/crypto/ec-utils/src/lib.rs +++ b/substrate/primitives/crypto/ec-utils/src/lib.rs @@ -32,6 +32,8 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + #[cfg(feature = "bls12-377")] pub mod bls12_377; #[cfg(feature = "bls12-381")] diff --git a/substrate/primitives/crypto/ec-utils/src/utils.rs b/substrate/primitives/crypto/ec-utils/src/utils.rs index d0dd8ed8131..47a49fe16cc 100644 --- a/substrate/primitives/crypto/ec-utils/src/utils.rs +++ b/substrate/primitives/crypto/ec-utils/src/utils.rs @@ -21,6 +21,7 @@ // curve may be excluded by the build we resort to `#[allow(unused)]` to // suppress the expected warning. +use alloc::vec::Vec; use ark_ec::{ pairing::{MillerLoopOutput, Pairing}, short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig}, @@ -31,7 +32,6 @@ use ark_scale::{ ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate}, scale::{Decode, Encode}, }; -use sp_std::vec::Vec; // SCALE encoding parameters shared by all the enabled modules const SCALE_USAGE: u8 = ark_scale::make_usage(Compress::No, Validate::No); diff --git a/substrate/primitives/externalities/Cargo.toml b/substrate/primitives/externalities/Cargo.toml index 6dc4f0a0dad..20fa3e3e397 100644 --- a/substrate/primitives/externalities/Cargo.toml +++ b/substrate/primitives/externalities/Cargo.toml @@ -19,9 +19,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } environmental = { version = "1.1.3", default-features = false } -sp-std = { path = "../std", default-features = false } sp-storage = { path = "../storage", default-features = false } [features] default = ["std"] -std = ["codec/std", "environmental/std", "sp-std/std", "sp-storage/std"] +std = ["codec/std", "environmental/std", "sp-storage/std"] diff --git a/substrate/primitives/externalities/src/extensions.rs b/substrate/primitives/externalities/src/extensions.rs index d99dfe6cf53..a4aa847a1aa 100644 --- a/substrate/primitives/externalities/src/extensions.rs +++ b/substrate/primitives/externalities/src/extensions.rs @@ -23,10 +23,12 @@ //! It is required that each extension implements the [`Extension`] trait. use crate::Error; -use sp_std::{ - any::{Any, TypeId}, +use alloc::{ boxed::Box, collections::btree_map::{BTreeMap, Entry}, +}; +use core::{ + any::{Any, TypeId}, ops::DerefMut, }; diff --git a/substrate/primitives/externalities/src/lib.rs b/substrate/primitives/externalities/src/lib.rs index 411ec97a6b8..142200f614a 100644 --- a/substrate/primitives/externalities/src/lib.rs +++ b/substrate/primitives/externalities/src/lib.rs @@ -25,11 +25,10 @@ //! //! This crate exposes the main [`Externalities`] trait. -use sp_std::{ - any::{Any, TypeId}, - boxed::Box, - vec::Vec, -}; +extern crate alloc; + +use alloc::{boxed::Box, vec::Vec}; +use core::any::{Any, TypeId}; use sp_storage::{ChildInfo, StateVersion, TrackedStorageKey}; diff --git a/substrate/primitives/genesis-builder/Cargo.toml b/substrate/primitives/genesis-builder/Cargo.toml index 15440b4811e..5a8f1c2962c 100644 --- a/substrate/primitives/genesis-builder/Cargo.toml +++ b/substrate/primitives/genesis-builder/Cargo.toml @@ -18,9 +18,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] sp-api = { path = "../api", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } serde_json = { features = ["alloc", "arbitrary_precision"], workspace = true } [features] default = ["std"] -std = ["serde_json/std", "sp-api/std", "sp-runtime/std", "sp-std/std"] +std = ["serde_json/std", "sp-api/std", "sp-runtime/std"] diff --git a/substrate/primitives/genesis-builder/src/lib.rs b/substrate/primitives/genesis-builder/src/lib.rs index bb1a2a35248..4970042187c 100644 --- a/substrate/primitives/genesis-builder/src/lib.rs +++ b/substrate/primitives/genesis-builder/src/lib.rs @@ -31,6 +31,8 @@ //! allows to catch and build the raw storage of `RuntimeGenesisConfig` which is the foundation for //! genesis block. +extern crate alloc; + /// The result type alias, used in build methods. `Err` contains formatted error message. pub type Result = core::result::Result<(), sp_runtime::RuntimeString>; @@ -41,7 +43,7 @@ sp_api::decl_runtime_apis! { /// /// This function instantiates the default `RuntimeGenesisConfig` struct for the runtime and serializes it into a JSON /// blob. It returns a `Vec` containing the JSON representation of the default `RuntimeGenesisConfig`. - fn create_default_config() -> sp_std::vec::Vec; + fn create_default_config() -> alloc::vec::Vec; /// Build `RuntimeGenesisConfig` from a JSON blob not using any defaults and store it in the storage. /// @@ -50,6 +52,6 @@ sp_api::decl_runtime_apis! { /// It is recommended to log any errors encountered during the process. /// /// Please note that provided json blob must contain all `RuntimeGenesisConfig` fields, no defaults will be used. - fn build_config(json: sp_std::vec::Vec) -> Result; + fn build_config(json: alloc::vec::Vec) -> Result; } } diff --git a/substrate/primitives/inherents/Cargo.toml b/substrate/primitives/inherents/Cargo.toml index bfb1d773347..6463c423fe7 100644 --- a/substrate/primitives/inherents/Cargo.toml +++ b/substrate/primitives/inherents/Cargo.toml @@ -23,7 +23,6 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive impl-trait-for-tuples = "0.2.2" thiserror = { optional = true, workspace = true } sp-runtime = { path = "../runtime", default-features = false, optional = true } -sp-std = { path = "../std", default-features = false } [dev-dependencies] futures = "0.3.21" @@ -35,6 +34,5 @@ std = [ "codec/std", "scale-info/std", "sp-runtime/std", - "sp-std/std", "thiserror", ] diff --git a/substrate/primitives/inherents/src/lib.rs b/substrate/primitives/inherents/src/lib.rs index dd7c294f1e2..80787669856 100644 --- a/substrate/primitives/inherents/src/lib.rs +++ b/substrate/primitives/inherents/src/lib.rs @@ -162,9 +162,11 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] +extern crate alloc; + use codec::{Decode, Encode}; -use sp_std::{ +use alloc::{ collections::btree_map::{BTreeMap, Entry, IntoIter}, vec::Vec, }; diff --git a/substrate/primitives/merkle-mountain-range/Cargo.toml b/substrate/primitives/merkle-mountain-range/Cargo.toml index 50d84778239..9c07f699b37 100644 --- a/substrate/primitives/merkle-mountain-range/Cargo.toml +++ b/substrate/primitives/merkle-mountain-range/Cargo.toml @@ -24,7 +24,6 @@ sp-api = { path = "../api", default-features = false } sp-core = { path = "../core", default-features = false } sp-debug-derive = { path = "../debug-derive", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } thiserror = { optional = true, workspace = true } [dev-dependencies] @@ -43,7 +42,6 @@ std = [ "sp-core/std", "sp-debug-derive/std", "sp-runtime/std", - "sp-std/std", ] # Serde support without relying on std features. diff --git a/substrate/primitives/merkle-mountain-range/src/lib.rs b/substrate/primitives/merkle-mountain-range/src/lib.rs index 6c0e75005ea..c76d66bb08e 100644 --- a/substrate/primitives/merkle-mountain-range/src/lib.rs +++ b/substrate/primitives/merkle-mountain-range/src/lib.rs @@ -20,14 +20,16 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] +extern crate alloc; + pub use mmr_lib; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; +use core::fmt; use scale_info::TypeInfo; use sp_debug_derive::RuntimeDebug; use sp_runtime::traits; -use sp_std::fmt; -#[cfg(not(feature = "std"))] -use sp_std::prelude::Vec; pub mod utils; @@ -248,10 +250,10 @@ impl DataOrHash { pub struct Compact { /// Internal tuple representation. pub tuple: T, - _hash: sp_std::marker::PhantomData, + _hash: core::marker::PhantomData, } -impl sp_std::ops::Deref for Compact { +impl core::ops::Deref for Compact { type Target = T; fn deref(&self) -> &Self::Target { diff --git a/substrate/primitives/merkle-mountain-range/src/utils.rs b/substrate/primitives/merkle-mountain-range/src/utils.rs index b9171c96a62..72674e24a27 100644 --- a/substrate/primitives/merkle-mountain-range/src/utils.rs +++ b/substrate/primitives/merkle-mountain-range/src/utils.rs @@ -20,9 +20,9 @@ use codec::Encode; use mmr_lib::helper; -use sp_runtime::traits::{CheckedAdd, CheckedSub, Header, One}; #[cfg(not(feature = "std"))] -use sp_std::prelude::Vec; +use alloc::vec::Vec; +use sp_runtime::traits::{CheckedAdd, CheckedSub, Header, One}; use crate::{Error, LeafIndex, NodeIndex}; @@ -131,7 +131,7 @@ impl NodesUtils { /// Used for nodes added by now finalized blocks. /// Never read keys using `node_canon_offchain_key` unless you sure that /// there's no `node_offchain_key` key in the storage. - pub fn node_canon_offchain_key(prefix: &[u8], pos: NodeIndex) -> sp_std::prelude::Vec { + pub fn node_canon_offchain_key(prefix: &[u8], pos: NodeIndex) -> alloc::vec::Vec { (prefix, pos).encode() } } diff --git a/substrate/primitives/metadata-ir/Cargo.toml b/substrate/primitives/metadata-ir/Cargo.toml index e4203d0e378..31c839b5c48 100644 --- a/substrate/primitives/metadata-ir/Cargo.toml +++ b/substrate/primitives/metadata-ir/Cargo.toml @@ -19,8 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } frame-metadata = { version = "16.0.0", default-features = false, features = ["current"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -sp-std = { path = "../std", default-features = false } [features] default = ["std"] -std = ["codec/std", "frame-metadata/std", "scale-info/std", "sp-std/std"] +std = ["codec/std", "frame-metadata/std", "scale-info/std"] diff --git a/substrate/primitives/metadata-ir/src/lib.rs b/substrate/primitives/metadata-ir/src/lib.rs index edfa58f8618..18b20f2ccaa 100644 --- a/substrate/primitives/metadata-ir/src/lib.rs +++ b/substrate/primitives/metadata-ir/src/lib.rs @@ -20,6 +20,8 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] +extern crate alloc; + // Re-export. #[doc(hidden)] pub use frame_metadata; @@ -52,8 +54,8 @@ pub fn into_version(metadata: MetadataIR, version: u32) -> Option sp_std::vec::Vec { - sp_std::vec![V14, V15] +pub fn supported_versions() -> alloc::vec::Vec { + alloc::vec![V14, V15] } /// Transform the IR to the latest stable metadata version. diff --git a/substrate/primitives/mixnet/Cargo.toml b/substrate/primitives/mixnet/Cargo.toml index 39cf684b977..8ba7f36da43 100644 --- a/substrate/primitives/mixnet/Cargo.toml +++ b/substrate/primitives/mixnet/Cargo.toml @@ -20,7 +20,6 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features = scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } sp-api = { default-features = false, path = "../api" } sp-application-crypto = { default-features = false, path = "../application-crypto" } -sp-std = { default-features = false, path = "../std" } [features] default = ["std"] @@ -29,5 +28,4 @@ std = [ "scale-info/std", "sp-api/std", "sp-application-crypto/std", - "sp-std/std", ] diff --git a/substrate/primitives/mixnet/src/lib.rs b/substrate/primitives/mixnet/src/lib.rs index 58b8a10f0cd..462d7fc61f2 100644 --- a/substrate/primitives/mixnet/src/lib.rs +++ b/substrate/primitives/mixnet/src/lib.rs @@ -20,5 +20,7 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + pub mod runtime_api; pub mod types; diff --git a/substrate/primitives/mixnet/src/runtime_api.rs b/substrate/primitives/mixnet/src/runtime_api.rs index 28ab40e6337..f3260782b0b 100644 --- a/substrate/primitives/mixnet/src/runtime_api.rs +++ b/substrate/primitives/mixnet/src/runtime_api.rs @@ -18,7 +18,7 @@ //! Runtime API for querying mixnet configuration and registering mixnodes. use super::types::{Mixnode, MixnodesErr, SessionIndex, SessionStatus}; -use sp_std::vec::Vec; +use alloc::vec::Vec; sp_api::decl_runtime_apis! { /// API to query the mixnet session status and mixnode sets, and to register mixnodes. diff --git a/substrate/primitives/mixnet/src/types.rs b/substrate/primitives/mixnet/src/types.rs index fc214f94d1c..3b069e1fb3a 100644 --- a/substrate/primitives/mixnet/src/types.rs +++ b/substrate/primitives/mixnet/src/types.rs @@ -17,9 +17,9 @@ //! Mixnet types used by both host and runtime. +use alloc::vec::Vec; use codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_std::vec::Vec; mod app { use sp_application_crypto::{app_crypto, key_types::MIXNET, sr25519}; @@ -90,8 +90,8 @@ pub enum MixnodesErr { }, } -impl sp_std::fmt::Display for MixnodesErr { - fn fmt(&self, fmt: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { +impl core::fmt::Display for MixnodesErr { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { match self { MixnodesErr::InsufficientRegistrations { num, min } => write!(fmt, "{num} mixnode(s) registered; {min} is the minimum"), diff --git a/substrate/primitives/npos-elections/Cargo.toml b/substrate/primitives/npos-elections/Cargo.toml index 7373aa849cb..b0b9890c061 100644 --- a/substrate/primitives/npos-elections/Cargo.toml +++ b/substrate/primitives/npos-elections/Cargo.toml @@ -22,7 +22,6 @@ serde = { features = ["alloc", "derive"], optional = true, workspace = true } sp-arithmetic = { path = "../arithmetic", default-features = false } sp-core = { path = "../core", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } [dev-dependencies] rand = "0.8.5" @@ -38,7 +37,6 @@ std = [ "sp-arithmetic/std", "sp-core/std", "sp-runtime/std", - "sp-std/std", ] # Serde support without relying on std features. diff --git a/substrate/primitives/npos-elections/src/assignments.rs b/substrate/primitives/npos-elections/src/assignments.rs index 2ac2b9bebd7..0686fdda643 100644 --- a/substrate/primitives/npos-elections/src/assignments.rs +++ b/substrate/primitives/npos-elections/src/assignments.rs @@ -18,6 +18,7 @@ //! Structs and helpers for distributing a voter's stake among various winners. use crate::{ExtendedBalance, IdentifierT, PerThing128}; +use alloc::vec::Vec; #[cfg(feature = "serde")] use codec::{Decode, Encode}; use sp_arithmetic::{ @@ -25,7 +26,6 @@ use sp_arithmetic::{ Normalizable, PerThing, }; use sp_core::RuntimeDebug; -use sp_std::vec::Vec; /// A voter's stake assignment among a set of targets, represented as ratios. #[derive(RuntimeDebug, Clone, Default)] diff --git a/substrate/primitives/npos-elections/src/balancing.rs b/substrate/primitives/npos-elections/src/balancing.rs index 90dbe7eb714..fb14c868658 100644 --- a/substrate/primitives/npos-elections/src/balancing.rs +++ b/substrate/primitives/npos-elections/src/balancing.rs @@ -27,8 +27,8 @@ //! See [`balance`] for more information. use crate::{BalancingConfig, Edge, ExtendedBalance, IdentifierT, Voter}; +use alloc::vec::Vec; use sp_arithmetic::traits::Zero; -use sp_std::prelude::*; /// Balance the weight distribution of a given `voters` at most `iterations` times, or up until the /// point where the biggest difference created per iteration of all stakes is `tolerance`. If this diff --git a/substrate/primitives/npos-elections/src/helpers.rs b/substrate/primitives/npos-elections/src/helpers.rs index 082491ea042..7df6ec9d9db 100644 --- a/substrate/primitives/npos-elections/src/helpers.rs +++ b/substrate/primitives/npos-elections/src/helpers.rs @@ -18,8 +18,8 @@ //! Helper methods for npos-elections. use crate::{Assignment, Error, IdentifierT, PerThing128, StakedAssignment, VoteWeight}; +use alloc::vec::Vec; use sp_arithmetic::PerThing; -use sp_std::prelude::*; /// Converts a vector of ratio assignments into ones with absolute budget value. /// diff --git a/substrate/primitives/npos-elections/src/lib.rs b/substrate/primitives/npos-elections/src/lib.rs index 8d741f4130d..82ac40fe273 100644 --- a/substrate/primitives/npos-elections/src/lib.rs +++ b/substrate/primitives/npos-elections/src/lib.rs @@ -74,15 +74,16 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + +use alloc::{collections::btree_map::BTreeMap, rc::Rc, vec, vec::Vec}; use codec::{Decode, Encode, MaxEncodedLen}; +use core::{cell::RefCell, cmp::Ordering}; use scale_info::TypeInfo; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use sp_arithmetic::{traits::Zero, Normalizable, PerThing, Rational128, ThresholdOrd}; use sp_core::{bounded::BoundedVec, RuntimeDebug}; -use sp_std::{ - cell::RefCell, cmp::Ordering, collections::btree_map::BTreeMap, prelude::*, rc::Rc, vec, -}; #[cfg(test)] mod mock; @@ -198,7 +199,7 @@ impl ElectionScore { } } -impl sp_std::cmp::Ord for ElectionScore { +impl core::cmp::Ord for ElectionScore { fn cmp(&self, other: &Self) -> Ordering { // we delegate this to the lexicographic cmp of slices`, and to incorporate that we want the // third element to be minimized, we swap them. @@ -210,7 +211,7 @@ impl sp_std::cmp::Ord for ElectionScore { } } -impl sp_std::cmp::PartialOrd for ElectionScore { +impl core::cmp::PartialOrd for ElectionScore { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } @@ -278,8 +279,8 @@ impl Edge { } #[cfg(feature = "std")] -impl sp_std::fmt::Debug for Edge { - fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { +impl core::fmt::Debug for Edge { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Edge({:?}, weight = {:?})", self.who, self.weight) } } @@ -299,7 +300,7 @@ pub struct Voter { #[cfg(feature = "std")] impl std::fmt::Debug for Voter { - fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Voter({:?}, budget = {}, edges = {:?})", self.who, self.budget, self.edges) } } diff --git a/substrate/primitives/npos-elections/src/mock.rs b/substrate/primitives/npos-elections/src/mock.rs index 2fc49fd72cd..91757404145 100644 --- a/substrate/primitives/npos-elections/src/mock.rs +++ b/substrate/primitives/npos-elections/src/mock.rs @@ -19,12 +19,12 @@ #![cfg(test)] +use alloc::collections::btree_map::BTreeMap; use sp_arithmetic::{ traits::{One, SaturatedConversion, Zero}, PerThing, }; use sp_runtime::assert_eq_error_rate; -use sp_std::collections::btree_map::BTreeMap; use crate::{seq_phragmen, Assignment, ElectionResult, ExtendedBalance, PerThing128, VoteWeight}; @@ -131,7 +131,7 @@ where if let Some(winner) = candidates .iter_mut() .filter(|c| !c.elected) - .min_by(|x, y| x.score.partial_cmp(&y.score).unwrap_or(sp_std::cmp::Ordering::Equal)) + .min_by(|x, y| x.score.partial_cmp(&y.score).unwrap_or(core::cmp::Ordering::Equal)) { winner.elected = true; for n in &mut voters { @@ -226,10 +226,10 @@ where if backing_backed_stake.len() > 0 { let max_stake = backing_backed_stake .iter() - .max_by(|x, y| x.partial_cmp(&y).unwrap_or(sp_std::cmp::Ordering::Equal)) + .max_by(|x, y| x.partial_cmp(&y).unwrap_or(core::cmp::Ordering::Equal)) .expect("vector with positive length will have a max; qed"); let min_stake = backed_stakes_iter - .min_by(|x, y| x.partial_cmp(&y).unwrap_or(sp_std::cmp::Ordering::Equal)) + .min_by(|x, y| x.partial_cmp(&y).unwrap_or(core::cmp::Ordering::Equal)) .expect("iterator with positive length will have a min; qed"); difference = max_stake - min_stake; @@ -254,7 +254,7 @@ where support_map .get(&x.0) .and_then(|x| support_map.get(&y.0).and_then(|y| x.total.partial_cmp(&y.total))) - .unwrap_or(sp_std::cmp::Ordering::Equal) + .unwrap_or(core::cmp::Ordering::Equal) }); let mut cumulative_stake = 0.0; diff --git a/substrate/primitives/npos-elections/src/node.rs b/substrate/primitives/npos-elections/src/node.rs index caca9561d83..6fe50ad1d0a 100644 --- a/substrate/primitives/npos-elections/src/node.rs +++ b/substrate/primitives/npos-elections/src/node.rs @@ -17,7 +17,8 @@ //! (very) Basic implementation of a graph node used in the reduce algorithm. -use sp_std::{cell::RefCell, fmt, prelude::*, rc::Rc}; +use alloc::{rc::Rc, vec::Vec}; +use core::{cell::RefCell, fmt}; /// The role that a node can accept. #[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Debug)] @@ -49,8 +50,8 @@ impl NodeId { } #[cfg(feature = "std")] -impl sp_std::fmt::Debug for NodeId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> sp_std::fmt::Result { +impl fmt::Debug for NodeId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "Node({:?}, {:?})", diff --git a/substrate/primitives/npos-elections/src/phragmen.rs b/substrate/primitives/npos-elections/src/phragmen.rs index c3578065f36..f331152e722 100644 --- a/substrate/primitives/npos-elections/src/phragmen.rs +++ b/substrate/primitives/npos-elections/src/phragmen.rs @@ -24,12 +24,12 @@ use crate::{ balancing, setup_inputs, BalancingConfig, CandidatePtr, ElectionResult, ExtendedBalance, IdentifierT, PerThing128, VoteWeight, Voter, }; +use alloc::vec::Vec; use sp_arithmetic::{ helpers_128bit::multiply_by_rational_with_rounding, traits::{Bounded, Zero}, Rational128, Rounding, }; -use sp_std::prelude::*; /// The denominator used for loads. Since votes are collected as u64, the smallest ratio that we /// might collect is `1/approval_stake` where approval stake is the sum of votes. Hence, some number diff --git a/substrate/primitives/npos-elections/src/phragmms.rs b/substrate/primitives/npos-elections/src/phragmms.rs index df6becf4747..9a17f0dfa7c 100644 --- a/substrate/primitives/npos-elections/src/phragmms.rs +++ b/substrate/primitives/npos-elections/src/phragmms.rs @@ -25,8 +25,8 @@ use crate::{ balance, setup_inputs, BalancingConfig, CandidatePtr, ElectionResult, ExtendedBalance, IdentifierT, PerThing128, VoteWeight, Voter, }; +use alloc::{rc::Rc, vec, vec::Vec}; use sp_arithmetic::{traits::Bounded, PerThing, Rational128}; -use sp_std::{prelude::*, rc::Rc}; /// Execute the phragmms method. /// @@ -232,8 +232,8 @@ pub(crate) fn apply_elected( mod tests { use super::*; use crate::{Assignment, ElectionResult}; + use alloc::rc::Rc; use sp_runtime::{Perbill, Percent}; - use sp_std::rc::Rc; #[test] fn basic_election_manual_works() { diff --git a/substrate/primitives/npos-elections/src/pjr.rs b/substrate/primitives/npos-elections/src/pjr.rs index f0e59a25d44..08e40a014ea 100644 --- a/substrate/primitives/npos-elections/src/pjr.rs +++ b/substrate/primitives/npos-elections/src/pjr.rs @@ -26,8 +26,8 @@ use crate::{ Candidate, CandidatePtr, Edge, ExtendedBalance, IdentifierT, Support, SupportMap, Supports, VoteWeight, Voter, }; +use alloc::{collections::btree_map::BTreeMap, rc::Rc, vec::Vec}; use sp_arithmetic::{traits::Zero, Perbill}; -use sp_std::{collections::btree_map::BTreeMap, rc::Rc, vec::Vec}; /// The type used as the threshold. /// /// Just some reading sugar; Must always be same as [`ExtendedBalance`]; diff --git a/substrate/primitives/npos-elections/src/reduce.rs b/substrate/primitives/npos-elections/src/reduce.rs index 6a5a0159e4e..c9ed493daf3 100644 --- a/substrate/primitives/npos-elections/src/reduce.rs +++ b/substrate/primitives/npos-elections/src/reduce.rs @@ -51,11 +51,12 @@ use crate::{ node::{Node, NodeId, NodeRef, NodeRole}, ExtendedBalance, IdentifierT, StakedAssignment, }; -use sp_arithmetic::traits::{Bounded, Zero}; -use sp_std::{ +use alloc::{ collections::btree_map::{BTreeMap, Entry::*}, - prelude::*, + vec, + vec::Vec, }; +use sp_arithmetic::traits::{Bounded, Zero}; /// Map type used for reduce_4. Can be easily swapped with HashMap. type Map = BTreeMap<(A, A), A>; diff --git a/substrate/primitives/npos-elections/src/traits.rs b/substrate/primitives/npos-elections/src/traits.rs index d49970873b7..afa6ac70880 100644 --- a/substrate/primitives/npos-elections/src/traits.rs +++ b/substrate/primitives/npos-elections/src/traits.rs @@ -18,8 +18,8 @@ //! Traits for the npos-election operations. use crate::ExtendedBalance; +use core::{fmt::Debug, ops::Mul}; use sp_arithmetic::PerThing; -use sp_std::{fmt::Debug, ops::Mul, prelude::*}; /// an aggregator trait for a generic type of a voter/target identifier. This usually maps to /// substrate's account id. diff --git a/substrate/primitives/session/Cargo.toml b/substrate/primitives/session/Cargo.toml index 99764c0a17f..784228c42e9 100644 --- a/substrate/primitives/session/Cargo.toml +++ b/substrate/primitives/session/Cargo.toml @@ -22,7 +22,6 @@ sp-api = { path = "../api", default-features = false } sp-core = { path = "../core", default-features = false } sp-runtime = { path = "../runtime", optional = true } sp-staking = { path = "../staking", default-features = false } -sp-std = { path = "../std", default-features = false } sp-keystore = { path = "../keystore", optional = true } [features] @@ -35,5 +34,4 @@ std = [ "sp-keystore/std", "sp-runtime/std", "sp-staking/std", - "sp-std/std", ] diff --git a/substrate/primitives/session/src/lib.rs b/substrate/primitives/session/src/lib.rs index 9933495fd60..fe7a3804733 100644 --- a/substrate/primitives/session/src/lib.rs +++ b/substrate/primitives/session/src/lib.rs @@ -19,6 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + use codec::{Decode, Encode}; #[cfg(feature = "std")] @@ -26,9 +28,9 @@ use sp_api::ProvideRuntimeApi; #[cfg(feature = "std")] use sp_runtime::traits::Block as BlockT; +use alloc::vec::Vec; use sp_core::RuntimeDebug; use sp_staking::SessionIndex; -use sp_std::vec::Vec; pub mod runtime_api; pub use runtime_api::*; diff --git a/substrate/primitives/session/src/runtime_api.rs b/substrate/primitives/session/src/runtime_api.rs index 5e508cd3dbd..3acc882aabc 100644 --- a/substrate/primitives/session/src/runtime_api.rs +++ b/substrate/primitives/session/src/runtime_api.rs @@ -15,8 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use alloc::vec::Vec; pub use sp_core::crypto::KeyTypeId; -use sp_std::prelude::*; sp_api::decl_runtime_apis! { /// Session keys runtime api. diff --git a/substrate/primitives/staking/Cargo.toml b/substrate/primitives/staking/Cargo.toml index 21346fbaca5..6304551b8e6 100644 --- a/substrate/primitives/staking/Cargo.toml +++ b/substrate/primitives/staking/Cargo.toml @@ -23,7 +23,6 @@ impl-trait-for-tuples = "0.2.2" sp-core = { path = "../core", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } [features] default = ["std"] @@ -33,6 +32,5 @@ std = [ "serde/std", "sp-core/std", "sp-runtime/std", - "sp-std/std", ] runtime-benchmarks = ["sp-runtime/runtime-benchmarks"] diff --git a/substrate/primitives/staking/src/lib.rs b/substrate/primitives/staking/src/lib.rs index f5b4a1ed63f..11b7ef41b9a 100644 --- a/substrate/primitives/staking/src/lib.rs +++ b/substrate/primitives/staking/src/lib.rs @@ -20,14 +20,17 @@ //! A crate which contains primitives that are useful for implementation that uses staking //! approaches in general. Definitions related to sessions, slashing, etc go here. +extern crate alloc; + use crate::currency_to_vote::CurrencyToVote; +use alloc::{collections::btree_map::BTreeMap, vec, vec::Vec}; use codec::{Decode, Encode, FullCodec, HasCompact, MaxEncodedLen}; +use core::ops::Sub; use scale_info::TypeInfo; use sp_runtime::{ traits::{AtLeast32BitUnsigned, Zero}, DispatchError, DispatchResult, RuntimeDebug, Saturating, }; -use sp_std::{collections::btree_map::BTreeMap, ops::Sub, vec, vec::Vec}; pub mod offence; @@ -172,7 +175,7 @@ pub trait StakingInterface { + Saturating; /// AccountId type used by the staking system. - type AccountId: Clone + sp_std::fmt::Debug; + type AccountId: Clone + core::fmt::Debug; /// Means of converting Currency to VoteWeight. type CurrencyToVote: CurrencyToVote; diff --git a/substrate/primitives/staking/src/offence.rs b/substrate/primitives/staking/src/offence.rs index 8013166374e..64aa4692eb5 100644 --- a/substrate/primitives/staking/src/offence.rs +++ b/substrate/primitives/staking/src/offence.rs @@ -18,10 +18,10 @@ //! Common traits and types that are useful for describing offences for usage in environments //! that use staking. +use alloc::vec::Vec; use codec::{Decode, Encode}; use sp_core::Get; use sp_runtime::{transaction_validity::TransactionValidityError, DispatchError, Perbill}; -use sp_std::vec::Vec; use crate::SessionIndex; diff --git a/substrate/primitives/state-machine/Cargo.toml b/substrate/primitives/state-machine/Cargo.toml index 09994f1ae91..aaedb500b59 100644 --- a/substrate/primitives/state-machine/Cargo.toml +++ b/substrate/primitives/state-machine/Cargo.toml @@ -28,7 +28,6 @@ tracing = { version = "0.1.29", optional = true } sp-core = { path = "../core", default-features = false } sp-externalities = { path = "../externalities", default-features = false } sp-panic-handler = { path = "../panic-handler", optional = true } -sp-std = { path = "../std", default-features = false } sp-trie = { path = "../trie", default-features = false } trie-db = { version = "0.28.0", default-features = false } @@ -51,7 +50,6 @@ std = [ "sp-externalities/std", "sp-panic-handler", "sp-runtime/std", - "sp-std/std", "sp-trie/std", "thiserror", "tracing", diff --git a/substrate/primitives/state-machine/src/backend.rs b/substrate/primitives/state-machine/src/backend.rs index ea9cd442d70..90be55d58a4 100644 --- a/substrate/primitives/state-machine/src/backend.rs +++ b/substrate/primitives/state-machine/src/backend.rs @@ -23,13 +23,13 @@ use crate::{ trie_backend_essence::TrieBackendStorage, ChildStorageCollection, StorageCollection, StorageKey, StorageValue, UsageInfo, }; +use alloc::vec::Vec; use codec::Encode; use core::marker::PhantomData; use hash_db::Hasher; use sp_core::storage::{ChildInfo, StateVersion, TrackedStorageKey}; #[cfg(feature = "std")] use sp_core::traits::RuntimeCode; -use sp_std::vec::Vec; use sp_trie::{MerkleValue, PrefixedMemoryDB}; /// A struct containing arguments for iterating over the storage. @@ -179,7 +179,7 @@ pub type BackendTransaction = PrefixedMemoryDB; /// to it. /// /// The clone operation (if implemented) should be cheap. -pub trait Backend: sp_std::fmt::Debug { +pub trait Backend: core::fmt::Debug { /// An error type when fetching data is not possible. type Error: super::Error; diff --git a/substrate/primitives/state-machine/src/ext.rs b/substrate/primitives/state-machine/src/ext.rs index 11df46f2a4a..73110f55cba 100644 --- a/substrate/primitives/state-machine/src/ext.rs +++ b/substrate/primitives/state-machine/src/ext.rs @@ -32,12 +32,10 @@ use sp_core::storage::{ use sp_externalities::{Extension, ExtensionStore, Externalities, MultiRemovalResults}; use crate::{log_error, trace, warn}; -use sp_std::{ +use alloc::{boxed::Box, vec, vec::Vec}; +use core::{ any::{Any, TypeId}, - boxed::Box, cmp::Ordering, - vec, - vec::Vec, }; #[cfg(feature = "std")] use std::error; @@ -739,7 +737,7 @@ impl<'a> StorageAppend<'a> { pub fn append(&mut self, value: Vec) { let value = vec![EncodeOpaqueValue(value)]; - let item = sp_std::mem::take(self.0); + let item = core::mem::take(self.0); *self.0 = match Vec::::append_or_new(item, &value) { Ok(item) => item, diff --git a/substrate/primitives/state-machine/src/lib.rs b/substrate/primitives/state-machine/src/lib.rs index 5909a30a814..200cebe68de 100644 --- a/substrate/primitives/state-machine/src/lib.rs +++ b/substrate/primitives/state-machine/src/lib.rs @@ -20,6 +20,8 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + pub mod backend; #[cfg(feature = "std")] mod basic; @@ -118,8 +120,8 @@ pub type DefaultError = String; pub struct DefaultError; #[cfg(not(feature = "std"))] -impl sp_std::fmt::Display for DefaultError { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { +impl core::fmt::Display for DefaultError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "DefaultError") } } diff --git a/substrate/primitives/state-machine/src/overlayed_changes/changeset.rs b/substrate/primitives/state-machine/src/overlayed_changes/changeset.rs index 59589dbbb37..a25a5b81052 100644 --- a/substrate/primitives/state-machine/src/overlayed_changes/changeset.rs +++ b/substrate/primitives/state-machine/src/overlayed_changes/changeset.rs @@ -20,16 +20,14 @@ use super::{Extrinsics, StorageKey, StorageValue}; #[cfg(not(feature = "std"))] -use sp_std::collections::btree_set::BTreeSet as Set; +use alloc::collections::btree_set::BTreeSet as Set; #[cfg(feature = "std")] use std::collections::HashSet as Set; use crate::warn; +use alloc::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; +use core::hash::Hash; use smallvec::SmallVec; -use sp_std::{ - collections::{btree_map::BTreeMap, btree_set::BTreeSet}, - hash::Hash, -}; const PROOF_OVERLAY_NON_EMPTY: &str = "\ An OverlayValue is always created with at least one transaction and dropped as soon @@ -225,7 +223,7 @@ impl OverlayedMap { /// This changeset might be created when there are already open transactions. /// We need to catch up here so that the child is at the same transaction depth. pub fn spawn_child(&self) -> Self { - use sp_std::iter::repeat; + use core::iter::repeat; Self { changes: Default::default(), dirty_keys: repeat(Set::new()).take(self.transaction_depth()).collect(), @@ -242,7 +240,7 @@ impl OverlayedMap { /// Get an optional reference to the value stored for the specified key. pub fn get(&self, key: &Q) -> Option<&OverlayedEntry> where - K: sp_std::borrow::Borrow, + K: core::borrow::Borrow, Q: Ord + ?Sized, { self.changes.get(key) @@ -448,7 +446,7 @@ impl OverlayedChangeSet { /// Get the iterator over all changes that follow the supplied `key`. pub fn changes_after(&self, key: &[u8]) -> impl Iterator { - use sp_std::ops::Bound; + use core::ops::Bound; let range = (Bound::Excluded(key), Bound::Unbounded); self.changes.range::<[u8], _>(range).map(|(k, v)| (k.as_slice(), v)) } diff --git a/substrate/primitives/state-machine/src/overlayed_changes/mod.rs b/substrate/primitives/state-machine/src/overlayed_changes/mod.rs index 626cf6c3caf..039631e4a63 100644 --- a/substrate/primitives/state-machine/src/overlayed_changes/mod.rs +++ b/substrate/primitives/state-machine/src/overlayed_changes/mod.rs @@ -22,6 +22,7 @@ mod offchain; use self::changeset::OverlayedChangeSet; use crate::{backend::Backend, stats::StateMachineStats, BackendTransaction, DefaultError}; +use alloc::{collections::btree_set::BTreeSet, vec::Vec}; use codec::{Decode, Encode}; use hash_db::Hasher; pub use offchain::OffchainOverlayedChanges; @@ -31,12 +32,13 @@ use sp_core::{ }; #[cfg(feature = "std")] use sp_externalities::{Extension, Extensions}; -#[cfg(not(feature = "std"))] -use sp_std::collections::btree_map::BTreeMap as Map; -use sp_std::{collections::btree_set::BTreeSet, vec::Vec}; use sp_trie::{empty_child_trie_root, LayoutV1}; + +#[cfg(not(feature = "std"))] +use alloc::collections::btree_map::BTreeMap as Map; #[cfg(feature = "std")] use std::collections::{hash_map::Entry as MapEntry, HashMap as Map}; + #[cfg(feature = "std")] use std::{ any::{Any, TypeId}, @@ -136,7 +138,7 @@ impl Clone for OverlayedChanges { } } -impl sp_std::fmt::Debug for OverlayedChanges { +impl core::fmt::Debug for OverlayedChanges { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("OverlayedChanges") .field("top", &self.top) @@ -259,7 +261,7 @@ impl Clone for StorageTransactionCache { } } -impl sp_std::fmt::Debug for StorageTransactionCache { +impl core::fmt::Debug for StorageTransactionCache { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut debug = f.debug_struct("StorageTransactionCache"); @@ -572,7 +574,7 @@ impl OverlayedChanges { }, }; - use sp_std::mem::take; + use core::mem::take; let main_storage_changes = take(&mut self.top).drain_commited(); let child_storage_changes = take(&mut self.children) .into_iter() @@ -777,7 +779,7 @@ where K: Ord, F: FnMut(&K, &mut V) -> bool, { - let old = sp_std::mem::replace(map, Map::default()); + let old = core::mem::replace(map, Map::default()); for (k, mut v) in old.into_iter() { if f(&k, &mut v) { map.insert(k, v); diff --git a/substrate/primitives/state-machine/src/overlayed_changes/offchain.rs b/substrate/primitives/state-machine/src/overlayed_changes/offchain.rs index 66e7ab5864c..1e6965e8747 100644 --- a/substrate/primitives/state-machine/src/overlayed_changes/offchain.rs +++ b/substrate/primitives/state-machine/src/overlayed_changes/offchain.rs @@ -18,8 +18,8 @@ //! Overlayed changes for offchain indexing. use super::changeset::OverlayedMap; +use alloc::vec::Vec; use sp_core::offchain::OffchainOverlayedChange; -use sp_std::prelude::Vec; /// In-memory storage for offchain workers recoding changes for the actual offchain storage /// implementation. @@ -48,7 +48,7 @@ impl OffchainOverlayedChanges { /// Drain all elements of changeset. pub fn drain(&mut self) -> impl Iterator { - sp_std::mem::take(self).into_iter() + core::mem::take(self).into_iter() } /// Remove a key and its associated value from the offchain database. diff --git a/substrate/primitives/state-machine/src/trie_backend.rs b/substrate/primitives/state-machine/src/trie_backend.rs index 7496463e642..f91ce5d2e52 100644 --- a/substrate/primitives/state-machine/src/trie_backend.rs +++ b/substrate/primitives/state-machine/src/trie_backend.rs @@ -297,7 +297,7 @@ struct CachedIter where H: Hasher, { - last_key: sp_std::vec::Vec, + last_key: alloc::vec::Vec, iter: RawIter, } @@ -390,9 +390,9 @@ where } impl, H: Hasher, C: TrieCacheProvider, R: TrieRecorderProvider> - sp_std::fmt::Debug for TrieBackend + core::fmt::Debug for TrieBackend { - fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "TrieBackend") } } diff --git a/substrate/primitives/state-machine/src/trie_backend_essence.rs b/substrate/primitives/state-machine/src/trie_backend_essence.rs index 3f789111dee..1824a77c370 100644 --- a/substrate/primitives/state-machine/src/trie_backend_essence.rs +++ b/substrate/primitives/state-machine/src/trie_backend_essence.rs @@ -23,14 +23,15 @@ use crate::{ trie_backend::TrieCacheProvider, warn, StorageKey, StorageValue, }; +#[cfg(feature = "std")] +use alloc::sync::Arc; +use alloc::{boxed::Box, vec::Vec}; use codec::Codec; +use core::marker::PhantomData; use hash_db::{self, AsHashDB, HashDB, HashDBRef, Hasher, Prefix}; #[cfg(feature = "std")] use parking_lot::RwLock; use sp_core::storage::{ChildInfo, ChildType, StateVersion}; -#[cfg(feature = "std")] -use sp_std::sync::Arc; -use sp_std::{boxed::Box, marker::PhantomData, vec::Vec}; use sp_trie::{ child_delta_trie_root, delta_trie_root, empty_child_trie_root, read_child_trie_first_descedant_value, read_child_trie_hash, read_child_trie_value, @@ -55,7 +56,7 @@ macro_rules! format { }; } -type Result = sp_std::result::Result; +type Result = core::result::Result; /// Patricia trie-based storage trait. pub trait Storage: Send + Sync { diff --git a/substrate/primitives/statement-store/Cargo.toml b/substrate/primitives/statement-store/Cargo.toml index 652ab3ef13a..000fcd98704 100644 --- a/substrate/primitives/statement-store/Cargo.toml +++ b/substrate/primitives/statement-store/Cargo.toml @@ -21,7 +21,6 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive sp-core = { path = "../core", default-features = false } sp-crypto-hashing = { path = "../crypto/hashing", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } sp-api = { path = "../api", default-features = false } sp-application-crypto = { path = "../application-crypto", default-features = false } sp-runtime-interface = { path = "../runtime-interface", default-features = false } @@ -57,7 +56,6 @@ std = [ "sp-externalities/std", "sp-runtime-interface/std", "sp-runtime/std", - "sp-std/std", "thiserror", "x25519-dalek", ] diff --git a/substrate/primitives/statement-store/src/lib.rs b/substrate/primitives/statement-store/src/lib.rs index 04175f6d616..bfcd0d1a52a 100644 --- a/substrate/primitives/statement-store/src/lib.rs +++ b/substrate/primitives/statement-store/src/lib.rs @@ -20,13 +20,15 @@ //! A crate which contains statement-store primitives. +extern crate alloc; + +use alloc::vec::Vec; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_application_crypto::RuntimeAppPublic; #[cfg(feature = "std")] use sp_core::Pair; use sp_runtime_interface::pass_by::PassByCodec; -use sp_std::vec::Vec; /// Statement topic. pub type Topic = [u8; 32]; diff --git a/substrate/primitives/statement-store/src/runtime_api.rs b/substrate/primitives/statement-store/src/runtime_api.rs index 13f88bc977e..4d25576c801 100644 --- a/substrate/primitives/statement-store/src/runtime_api.rs +++ b/substrate/primitives/statement-store/src/runtime_api.rs @@ -18,11 +18,11 @@ //! Runtime support for the statement store. use crate::{Hash, Statement, Topic}; +use alloc::vec::Vec; use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_runtime::RuntimeDebug; use sp_runtime_interface::{pass_by::PassByEnum, runtime_interface}; -use sp_std::vec::Vec; #[cfg(feature = "std")] use sp_externalities::ExternalitiesExt; diff --git a/substrate/primitives/storage/Cargo.toml b/substrate/primitives/storage/Cargo.toml index d3ade87ea47..acedc8d0004 100644 --- a/substrate/primitives/storage/Cargo.toml +++ b/substrate/primitives/storage/Cargo.toml @@ -22,7 +22,6 @@ impl-serde = { version = "0.4.0", optional = true, default-features = false } ref-cast = "1.0.0" serde = { features = ["alloc", "derive"], optional = true, workspace = true } sp-debug-derive = { path = "../debug-derive", default-features = false } -sp-std = { path = "../std", default-features = false } [features] default = ["std"] @@ -31,7 +30,6 @@ std = [ "impl-serde/std", "serde/std", "sp-debug-derive/std", - "sp-std/std", ] # Serde support without relying on std features. diff --git a/substrate/primitives/storage/src/lib.rs b/substrate/primitives/storage/src/lib.rs index 79c090cabf8..b55cc8f2174 100644 --- a/substrate/primitives/storage/src/lib.rs +++ b/substrate/primitives/storage/src/lib.rs @@ -19,18 +19,19 @@ #![cfg_attr(not(feature = "std"), no_std)] -use core::fmt::Display; +extern crate alloc; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use sp_debug_derive::RuntimeDebug; +use alloc::vec::Vec; use codec::{Decode, Encode}; -use ref_cast::RefCast; -use sp_std::{ +use core::{ + fmt::Display, ops::{Deref, DerefMut}, - vec::Vec, }; +use ref_cast::RefCast; /// Storage key. #[derive(PartialEq, Eq, RuntimeDebug)] @@ -49,9 +50,7 @@ impl AsRef<[u8]> for StorageKey { } /// Storage key with read/write tracking information. -#[derive( - PartialEq, Eq, Ord, PartialOrd, sp_std::hash::Hash, RuntimeDebug, Clone, Encode, Decode, -)] +#[derive(PartialEq, Eq, Ord, PartialOrd, core::hash::Hash, RuntimeDebug, Clone, Encode, Decode)] pub struct TrackedStorageKey { pub key: Vec, pub reads: u32, @@ -441,7 +440,7 @@ impl From for u8 { impl TryFrom for StateVersion { type Error = (); - fn try_from(val: u8) -> sp_std::result::Result { + fn try_from(val: u8) -> core::result::Result { match val { 0 => Ok(StateVersion::V0), 1 => Ok(StateVersion::V1), diff --git a/substrate/primitives/test-primitives/Cargo.toml b/substrate/primitives/test-primitives/Cargo.toml index f310216dd58..1b51c5f5919 100644 --- a/substrate/primitives/test-primitives/Cargo.toml +++ b/substrate/primitives/test-primitives/Cargo.toml @@ -21,7 +21,6 @@ serde = { features = ["derive"], optional = true, workspace = true } sp-application-crypto = { path = "../application-crypto", default-features = false } sp-core = { path = "../core", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } [features] default = ["std"] @@ -32,7 +31,6 @@ std = [ "sp-application-crypto/std", "sp-core/std", "sp-runtime/std", - "sp-std/std", ] # Serde support without relying on std features. diff --git a/substrate/primitives/test-primitives/src/lib.rs b/substrate/primitives/test-primitives/src/lib.rs index 82bdb6967b8..1e3b912eaf4 100644 --- a/substrate/primitives/test-primitives/src/lib.rs +++ b/substrate/primitives/test-primitives/src/lib.rs @@ -19,14 +19,16 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + use codec::{Decode, Encode}; pub use sp_application_crypto; use sp_application_crypto::sr25519; +use alloc::vec::Vec; pub use sp_core::{hash::H256, RuntimeDebug}; use sp_runtime::traits::{BlakeTwo256, Extrinsic as ExtrinsicT, Verify}; -use sp_std::vec::Vec; /// Extrinsic for test-runtime. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)] diff --git a/substrate/primitives/timestamp/Cargo.toml b/substrate/primitives/timestamp/Cargo.toml index 9e2b802bfb1..11afb175590 100644 --- a/substrate/primitives/timestamp/Cargo.toml +++ b/substrate/primitives/timestamp/Cargo.toml @@ -21,7 +21,6 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features = thiserror = { optional = true, workspace = true } sp-inherents = { path = "../inherents", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } [features] default = ["std"] @@ -30,6 +29,5 @@ std = [ "codec/std", "sp-inherents/std", "sp-runtime/std", - "sp-std/std", "thiserror", ] diff --git a/substrate/primitives/tracing/Cargo.toml b/substrate/primitives/tracing/Cargo.toml index 58b1e48c462..368f8c096dd 100644 --- a/substrate/primitives/tracing/Cargo.toml +++ b/substrate/primitives/tracing/Cargo.toml @@ -21,7 +21,6 @@ features = ["with-tracing"] targets = ["wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { path = "../std", default-features = false } codec = { version = "3.6.1", package = "parity-scale-codec", default-features = false, features = [ "derive", ] } @@ -36,7 +35,6 @@ default = ["std"] with-tracing = ["codec/derive", "codec/full"] std = [ "codec/std", - "sp-std/std", "tracing-core/std", "tracing-subscriber", "tracing/std", diff --git a/substrate/primitives/tracing/src/lib.rs b/substrate/primitives/tracing/src/lib.rs index cc651836846..b8b99230db5 100644 --- a/substrate/primitives/tracing/src/lib.rs +++ b/substrate/primitives/tracing/src/lib.rs @@ -37,6 +37,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + #[cfg(feature = "std")] use tracing; pub use tracing::{ diff --git a/substrate/primitives/tracing/src/types.rs b/substrate/primitives/tracing/src/types.rs index 003787f310d..3692a81e03c 100644 --- a/substrate/primitives/tracing/src/types.rs +++ b/substrate/primitives/tracing/src/types.rs @@ -15,11 +15,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +use alloc::{vec, vec::Vec}; use codec::{Decode, Encode}; /// Types for wasm based tracing. Loosly inspired by `tracing-core` but /// optimised for the specific use case. use core::{fmt::Debug, format_args}; -use sp_std::{vec, vec::Vec, Writer}; /// The Tracing Level – the user can filter by this #[derive(Clone, Encode, Decode, Debug)] @@ -132,9 +132,9 @@ impl From for WasmValue { impl From> for WasmValue { fn from(inp: core::fmt::Arguments<'_>) -> WasmValue { - let mut buf = Writer::default(); + let mut buf = alloc::string::String::default(); core::fmt::write(&mut buf, inp).expect("Writing of arguments doesn't fail"); - WasmValue::Formatted(buf.into_inner()) + WasmValue::Formatted(buf.into_bytes()) } } diff --git a/substrate/primitives/transaction-pool/src/lib.rs b/substrate/primitives/transaction-pool/src/lib.rs index 431f429e29f..2ce735491b2 100644 --- a/substrate/primitives/transaction-pool/src/lib.rs +++ b/substrate/primitives/transaction-pool/src/lib.rs @@ -20,4 +20,6 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + pub mod runtime_api; diff --git a/substrate/primitives/transaction-storage-proof/Cargo.toml b/substrate/primitives/transaction-storage-proof/Cargo.toml index e2fb54dafdf..fbd0a4752fc 100644 --- a/substrate/primitives/transaction-storage-proof/Cargo.toml +++ b/substrate/primitives/transaction-storage-proof/Cargo.toml @@ -22,7 +22,6 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive sp-core = { path = "../core", optional = true } sp-inherents = { path = "../inherents", default-features = false } sp-runtime = { path = "../runtime", default-features = false } -sp-std = { path = "../std", default-features = false } sp-trie = { path = "../trie", optional = true } [features] @@ -34,6 +33,5 @@ std = [ "sp-core/std", "sp-inherents/std", "sp-runtime/std", - "sp-std/std", "sp-trie/std", ] diff --git a/substrate/primitives/transaction-storage-proof/src/lib.rs b/substrate/primitives/transaction-storage-proof/src/lib.rs index 9d540ae68d1..352f2aec26e 100644 --- a/substrate/primitives/transaction-storage-proof/src/lib.rs +++ b/substrate/primitives/transaction-storage-proof/src/lib.rs @@ -20,8 +20,11 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::{prelude::*, result::Result}; +extern crate alloc; +use core::result::Result; + +use alloc::vec::Vec; use codec::{Decode, Encode}; use sp_inherents::{InherentData, InherentIdentifier, IsFatalError}; use sp_runtime::traits::{Block as BlockT, NumberFor}; diff --git a/substrate/primitives/trie/Cargo.toml b/substrate/primitives/trie/Cargo.toml index 16d3ca19a17..dd7ab080e5f 100644 --- a/substrate/primitives/trie/Cargo.toml +++ b/substrate/primitives/trie/Cargo.toml @@ -35,7 +35,6 @@ tracing = { version = "0.1.29", optional = true } trie-db = { version = "0.28.0", default-features = false } trie-root = { version = "0.18.0", default-features = false } sp-core = { path = "../core", default-features = false } -sp-std = { path = "../std", default-features = false } sp-externalities = { path = "../externalities", default-features = false } schnellru = { version = "0.2.1", optional = true } @@ -62,7 +61,6 @@ std = [ "sp-core/std", "sp-externalities/std", "sp-runtime/std", - "sp-std/std", "thiserror", "tracing", "trie-db/std", diff --git a/substrate/primitives/trie/src/error.rs b/substrate/primitives/trie/src/error.rs index 17be556d348..e3986e50b08 100644 --- a/substrate/primitives/trie/src/error.rs +++ b/substrate/primitives/trie/src/error.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use sp_std::{boxed::Box, vec::Vec}; +use alloc::{boxed::Box, vec::Vec}; /// Error type used for trie related errors. #[derive(Debug, PartialEq, Eq, Clone)] diff --git a/substrate/primitives/trie/src/lib.rs b/substrate/primitives/trie/src/lib.rs index fd1320b3fbc..81b37a0c9a6 100644 --- a/substrate/primitives/trie/src/lib.rs +++ b/substrate/primitives/trie/src/lib.rs @@ -19,6 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + #[cfg(feature = "std")] pub mod cache; mod error; @@ -33,6 +35,8 @@ mod trie_stream; #[cfg(feature = "std")] pub mod proof_size_extension; +use alloc::{borrow::Borrow, boxed::Box, vec, vec::Vec}; +use core::marker::PhantomData; /// Our `NodeCodec`-specific error. pub use error::Error; /// Various re-exports from the `hash-db` crate. @@ -42,7 +46,6 @@ use hash_db::{Hasher, Prefix}; pub use memory_db::{prefixed_key, HashKey, KeyFunction, PrefixedKey}; /// The Substrate format implementation of `NodeCodec`. pub use node_codec::NodeCodec; -use sp_std::{borrow::Borrow, boxed::Box, marker::PhantomData, vec::Vec}; pub use storage_proof::{CompactProof, StorageProof}; /// Trie codec reexport, mainly child trie support /// for trie compact proof. @@ -500,7 +503,7 @@ pub struct KeySpacedDBMut<'a, DB: ?Sized, H>(&'a mut DB, &'a [u8], PhantomData (Vec, Option) { - let mut result = sp_std::vec![0; ks.len() + prefix.0.len()]; + let mut result = vec![0; ks.len() + prefix.0.len()]; result[..ks.len()].copy_from_slice(ks); result[ks.len()..].copy_from_slice(prefix.0); (result, prefix.1) diff --git a/substrate/primitives/trie/src/node_codec.rs b/substrate/primitives/trie/src/node_codec.rs index 46acde77c05..78896988ec4 100644 --- a/substrate/primitives/trie/src/node_codec.rs +++ b/substrate/primitives/trie/src/node_codec.rs @@ -19,9 +19,10 @@ use super::node_header::{NodeHeader, NodeKind}; use crate::{error::Error, trie_constants}; +use alloc::{borrow::Borrow, vec::Vec}; use codec::{Compact, Decode, Encode, Input}; +use core::{marker::PhantomData, ops::Range}; use hash_db::Hasher; -use sp_std::{borrow::Borrow, marker::PhantomData, ops::Range, vec::Vec}; use trie_db::{ nibble_ops, node::{NibbleSlicePlan, NodeHandlePlan, NodePlan, Value, ValuePlan}, @@ -30,7 +31,7 @@ use trie_db::{ /// Helper struct for trie node decoder. This implements `codec::Input` on a byte slice, while /// tracking the absolute position. This is similar to `std::io::Cursor` but does not implement -/// `Read` and `io` is not in `sp-std`. +/// `Read` and `io` are not in `core` or `alloc`. struct ByteSliceInput<'a> { data: &'a [u8], offset: usize, diff --git a/substrate/primitives/trie/src/storage_proof.rs b/substrate/primitives/trie/src/storage_proof.rs index 6c871d73b04..e46c49be19c 100644 --- a/substrate/primitives/trie/src/storage_proof.rs +++ b/substrate/primitives/trie/src/storage_proof.rs @@ -15,14 +15,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +use alloc::{collections::btree_set::BTreeSet, vec::Vec}; use codec::{Decode, Encode}; +use core::iter::{DoubleEndedIterator, IntoIterator}; use hash_db::{HashDB, Hasher}; use scale_info::TypeInfo; -use sp_std::{ - collections::btree_set::BTreeSet, - iter::{DoubleEndedIterator, IntoIterator}, - vec::Vec, -}; + // Note that `LayoutV1` usage here (proof compaction) is compatible // with `LayoutV0`. use crate::LayoutV1 as Layout; diff --git a/substrate/primitives/trie/src/trie_codec.rs b/substrate/primitives/trie/src/trie_codec.rs index f29e009c476..65b4f505359 100644 --- a/substrate/primitives/trie/src/trie_codec.rs +++ b/substrate/primitives/trie/src/trie_codec.rs @@ -21,7 +21,7 @@ //! it to substrate specific layout and child trie system. use crate::{CompactProof, HashDBT, TrieConfiguration, TrieHash, EMPTY_PREFIX}; -use sp_std::{boxed::Box, vec::Vec}; +use alloc::{boxed::Box, vec::Vec}; use trie_db::{CError, Trie}; /// Error for trie node decoding. diff --git a/substrate/primitives/trie/src/trie_stream.rs b/substrate/primitives/trie/src/trie_stream.rs index f57b80f978f..459b5895f20 100644 --- a/substrate/primitives/trie/src/trie_stream.rs +++ b/substrate/primitives/trie/src/trie_stream.rs @@ -21,9 +21,9 @@ use crate::{ node_header::{size_and_prefix_iterator, NodeKind}, trie_constants, }; +use alloc::vec::Vec; use codec::{Compact, Encode}; use hash_db::Hasher; -use sp_std::vec::Vec; use trie_root; /// Codec-flavored TrieStream. diff --git a/substrate/primitives/wasm-interface/Cargo.toml b/substrate/primitives/wasm-interface/Cargo.toml index f7d1038903e..6c051b71c8e 100644 --- a/substrate/primitives/wasm-interface/Cargo.toml +++ b/substrate/primitives/wasm-interface/Cargo.toml @@ -22,9 +22,8 @@ impl-trait-for-tuples = "0.2.2" log = { optional = true, workspace = true, default-features = true } wasmtime = { version = "8.0.1", default-features = false, optional = true } anyhow = { version = "1.0.68", optional = true } -sp-std = { path = "../std", default-features = false } [features] default = ["std"] -std = ["codec/std", "log/std", "sp-std/std", "wasmtime"] +std = ["codec/std", "log/std", "wasmtime"] wasmtime = ["anyhow", "dep:wasmtime"] diff --git a/substrate/primitives/wasm-interface/src/lib.rs b/substrate/primitives/wasm-interface/src/lib.rs index 9d5d2bb358d..4fc78ca1553 100644 --- a/substrate/primitives/wasm-interface/src/lib.rs +++ b/substrate/primitives/wasm-interface/src/lib.rs @@ -19,7 +19,10 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::{borrow::Cow, iter::Iterator, marker::PhantomData, mem, result, vec, vec::Vec}; +extern crate alloc; + +use alloc::{borrow::Cow, vec, vec::Vec}; +use core::{iter::Iterator, marker::PhantomData, mem, result}; #[cfg(not(all(feature = "std", feature = "wasmtime")))] #[macro_export] @@ -76,7 +79,7 @@ impl From for u8 { impl TryFrom for ValueType { type Error = (); - fn try_from(val: u8) -> sp_std::result::Result { + fn try_from(val: u8) -> core::result::Result { match val { 0 => Ok(Self::I32), 1 => Ok(Self::I64), diff --git a/substrate/primitives/weights/Cargo.toml b/substrate/primitives/weights/Cargo.toml index a7d61de001b..d3118defb58 100644 --- a/substrate/primitives/weights/Cargo.toml +++ b/substrate/primitives/weights/Cargo.toml @@ -23,7 +23,6 @@ serde = { optional = true, features = ["alloc", "derive"], workspace = true } smallvec = "1.11.0" sp-arithmetic = { path = "../arithmetic", default-features = false } sp-debug-derive = { path = "../debug-derive", default-features = false } -sp-std = { path = "../std", default-features = false } schemars = { version = "0.8.3", default-features = false, optional = true } [features] @@ -35,7 +34,6 @@ std = [ "serde/std", "sp-arithmetic/std", "sp-debug-derive/std", - "sp-std/std", ] # By default some types have documentation, `full-metadata-docs` allows to add documentation to # more types in the metadata. diff --git a/substrate/test-utils/runtime/Cargo.toml b/substrate/test-utils/runtime/Cargo.toml index b6e6346e801..f49503da8ca 100644 --- a/substrate/test-utils/runtime/Cargo.toml +++ b/substrate/test-utils/runtime/Cargo.toml @@ -28,7 +28,6 @@ sp-keyring = { path = "../../primitives/keyring", default-features = false } sp-offchain = { path = "../../primitives/offchain", default-features = false } sp-core = { path = "../../primitives/core", default-features = false, features = ["serde"] } sp-crypto-hashing = { path = "../../primitives/crypto/hashing", default-features = false } -sp-std = { path = "../../primitives/std", default-features = false } sp-io = { path = "../../primitives/io", default-features = false } frame-support = { path = "../../frame/support", default-features = false } sp-version = { path = "../../primitives/version", default-features = false } @@ -104,7 +103,6 @@ std = [ "sp-runtime/std", "sp-session/std", "sp-state-machine/std", - "sp-std/std", "sp-tracing/std", "sp-transaction-pool/std", "sp-trie/std", diff --git a/substrate/test-utils/runtime/src/extrinsic.rs b/substrate/test-utils/runtime/src/extrinsic.rs index 05ffb7db5d5..e355e5d099a 100644 --- a/substrate/test-utils/runtime/src/extrinsic.rs +++ b/substrate/test-utils/runtime/src/extrinsic.rs @@ -26,7 +26,6 @@ use frame_system::{CheckNonce, CheckWeight}; use sp_core::crypto::Pair as TraitPair; use sp_keyring::AccountKeyring; use sp_runtime::{transaction_validity::TransactionPriority, Perbill}; -use sp_std::prelude::*; /// Transfer used in test substrate pallet. Extrinsic is created and signed using this data. #[derive(Clone)] diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index 9270978cd12..7148d2b2fc0 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -19,6 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + #[cfg(feature = "std")] pub mod extrinsic; #[cfg(feature = "std")] @@ -42,9 +44,10 @@ use frame_system::{ CheckNonce, CheckWeight, }; use scale_info::TypeInfo; -use sp_std::prelude::*; + +use alloc::boxed::Box; #[cfg(not(feature = "std"))] -use sp_std::vec; +use alloc::{vec, vec::Vec}; use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic}; use sp_core::{OpaqueMetadata, RuntimeDebug}; @@ -265,7 +268,7 @@ impl sp_runtime::traits::SignedExtension for CheckSubstrateCall { fn additional_signed( &self, - ) -> sp_std::result::Result { + ) -> core::result::Result { Ok(()) } @@ -440,7 +443,7 @@ fn code_using_trie() -> u64 { .to_vec(); let mut mdb = PrefixedMemoryDB::default(); - let mut root = sp_std::default::Default::default(); + let mut root = core::default::Default::default(); { let mut t = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); for (key, value) in &pairs { @@ -494,7 +497,7 @@ impl_runtime_apis! { fn metadata_at_version(_version: u32) -> Option { unimplemented!() } - fn metadata_versions() -> sp_std::vec::Vec { + fn metadata_versions() -> alloc::vec::Vec { unimplemented!() } } diff --git a/substrate/test-utils/runtime/src/substrate_test_pallet.rs b/substrate/test-utils/runtime/src/substrate_test_pallet.rs index ed1ad990472..8375a68c8ff 100644 --- a/substrate/test-utils/runtime/src/substrate_test_pallet.rs +++ b/substrate/test-utils/runtime/src/substrate_test_pallet.rs @@ -21,6 +21,7 @@ //! functioning runtime. Some calls are allowed to be submitted as unsigned extrinsics, however most //! of them requires signing. Refer to `pallet::Call` for further details. +use alloc::{vec, vec::Vec}; use frame_support::{pallet_prelude::*, storage}; use sp_core::sr25519::Public; use sp_runtime::{ @@ -29,7 +30,6 @@ use sp_runtime::{ InvalidTransaction, TransactionSource, TransactionValidity, ValidTransaction, }, }; -use sp_std::prelude::*; pub use self::pallet::*; @@ -59,7 +59,7 @@ pub mod pallet { pub struct GenesisConfig { pub authorities: Vec, #[serde(skip)] - pub _config: sp_std::marker::PhantomData, + pub _config: core::marker::PhantomData, } #[pallet::genesis_build] -- GitLab From 816c072abd99947e466e611cd96fa0db918f1854 Mon Sep 17 00:00:00 2001 From: K Gunjan Date: Mon, 18 Mar 2024 15:57:48 +0530 Subject: [PATCH 132/188] Pallet AURA: remove pallet::getter macro and write the corresponding code (#3350) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed the `pallet::getter` macro call from storage type definitions and added the corresponding implementations directly. fixes #3330 polkadot address: 14JzTPPUd8x8phKi8qLxHgNTnTMg6DUukCLXoWprejkaHXPz --------- Co-authored-by: Bastian Köcher --- cumulus/pallets/aura-ext/src/lib.rs | 6 ++-- .../assets/asset-hub-rococo/src/lib.rs | 2 +- .../assets/asset-hub-westend/src/lib.rs | 2 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 2 +- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 2 +- .../collectives-westend/src/lib.rs | 2 +- .../contracts/contracts-rococo/src/lib.rs | 2 +- .../coretime/coretime-rococo/src/lib.rs | 2 +- .../coretime/coretime-westend/src/lib.rs | 2 +- .../glutton/glutton-westend/src/lib.rs | 2 +- .../runtimes/people/people-rococo/src/lib.rs | 2 +- .../runtimes/people/people-westend/src/lib.rs | 2 +- .../runtimes/starters/seedling/src/lib.rs | 2 +- .../runtimes/starters/shell/src/lib.rs | 2 +- .../runtimes/testing/penpal/src/lib.rs | 2 +- .../testing/rococo-parachain/src/lib.rs | 2 +- prdoc/pr_3350.prdoc | 31 +++++++++++++++++++ substrate/frame/aura/src/lib.rs | 12 +++---- substrate/frame/aura/src/tests.rs | 7 +++-- templates/parachain/runtime/src/lib.rs | 4 ++- templates/solochain/runtime/src/lib.rs | 2 +- 21 files changed, 62 insertions(+), 30 deletions(-) create mode 100644 prdoc/pr_3350.prdoc diff --git a/cumulus/pallets/aura-ext/src/lib.rs b/cumulus/pallets/aura-ext/src/lib.rs index 31b571816a0..b71ae628954 100644 --- a/cumulus/pallets/aura-ext/src/lib.rs +++ b/cumulus/pallets/aura-ext/src/lib.rs @@ -63,14 +63,14 @@ pub mod pallet { impl Hooks> for Pallet { fn on_finalize(_: BlockNumberFor) { // Update to the latest AuRa authorities. - Authorities::::put(Aura::::authorities()); + Authorities::::put(pallet_aura::Authorities::::get()); } fn on_initialize(_: BlockNumberFor) -> Weight { // Fetch the authorities once to get them into the storage proof of the PoV. Authorities::::get(); - let new_slot = Aura::::current_slot(); + let new_slot = pallet_aura::CurrentSlot::::get(); let (new_slot, authored) = match SlotInfo::::get() { Some((slot, authored)) if slot == new_slot => (slot, authored + 1), @@ -116,7 +116,7 @@ pub mod pallet { #[pallet::genesis_build] impl BuildGenesisConfig for GenesisConfig { fn build(&self) { - let authorities = Aura::::authorities(); + let authorities = pallet_aura::Authorities::::get(); Authorities::::put(authorities); } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index e6b5e55bcd3..d3d8a495ea3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1067,7 +1067,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 1ba108234c8..711fadff92a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1098,7 +1098,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 31069778e38..bbafcd3c7dd 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -790,7 +790,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index d96c762fe19..11ab9aecc61 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -540,7 +540,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 5bf3519ac3d..55269283e08 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -777,7 +777,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index f148ceadccb..17bb45f6b1b 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -440,7 +440,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 6efbdde5899..26add2ee942 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -495,7 +495,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 2bb179b5b05..76732c3fccc 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -486,7 +486,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index e7fdb53b253..fe18f48fbb3 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -353,7 +353,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 98f76984dd4..2bb5641b4af 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -469,7 +469,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 5adbdc1f38c..b81f7a9c969 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -469,7 +469,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs index bf4768d8457..2f4f762408f 100644 --- a/cumulus/parachains/runtimes/starters/seedling/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/seedling/src/lib.rs @@ -283,7 +283,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/starters/shell/src/lib.rs b/cumulus/parachains/runtimes/starters/shell/src/lib.rs index 51fdfac5b1c..0f4957fd802 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/lib.rs @@ -340,7 +340,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 3063601e030..1e6d485d148 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -688,7 +688,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 753d2d12065..a066cab1b6d 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -758,7 +758,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } diff --git a/prdoc/pr_3350.prdoc b/prdoc/pr_3350.prdoc new file mode 100644 index 00000000000..1171614d67f --- /dev/null +++ b/prdoc/pr_3350.prdoc @@ -0,0 +1,31 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: removed `pallet::getter` from Pallet AURA + +doc: + - audience: Runtime Dev + description: | + This PR removes all the declarations of macro `pallet::getter` in the Pallet AURA and replaces the use of storage getter functions authorities() & current_slot() with `StorageItem::get()` API across the crates as listed bellow. + The purpose is to discourage developers to use this macro, that is currently being removed and soon will be deprecated. + +crates: + - name: pallet-aura + - name: solochain-template-runtime + - name: cumulus-pallet-aura-ext + - name: parachain-template-runtime + - name: people-westend-runtime + - name: people-rococo-runtime + - name: bridge-hub-rococo-runtime + - name: bridge-hub-westend-runtime + - name: rococo-parachain-runtime + - name: penpal-runtime + - name: glutton-westend-runtime + - name: shell-runtime + - name: seedling-runtime + - name: collectives-westend-runtime + - name: asset-hub-rococo-runtime + - name: asset-hub-westend-runtime + - name: contracts-rococo-runtime + - name: coretime-westend-runtime + - name: coretime-rococo-runtime diff --git a/substrate/frame/aura/src/lib.rs b/substrate/frame/aura/src/lib.rs index 55653de97a8..997f51ba428 100644 --- a/substrate/frame/aura/src/lib.rs +++ b/substrate/frame/aura/src/lib.rs @@ -161,16 +161,14 @@ pub mod pallet { /// The current authority set. #[pallet::storage] - #[pallet::getter(fn authorities)] - pub(super) type Authorities = + pub type Authorities = StorageValue<_, BoundedVec, ValueQuery>; /// The current slot of this block. /// /// This will be set in `on_initialize`. #[pallet::storage] - #[pallet::getter(fn current_slot)] - pub(super) type CurrentSlot = StorageValue<_, Slot, ValueQuery>; + pub type CurrentSlot = StorageValue<_, Slot, ValueQuery>; #[pallet::genesis_config] #[derive(frame_support::DefaultNoBound)] @@ -318,7 +316,7 @@ impl OneSessionHandler for Pallet { // instant changes if changed { let next_authorities = validators.map(|(_, k)| k).collect::>(); - let last_authorities = Self::authorities(); + let last_authorities = Authorities::::get(); if last_authorities != next_authorities { if next_authorities.len() as u32 > T::MaxAuthorities::get() { log::warn!( @@ -374,7 +372,7 @@ impl> FindAuthor { let i = Inner::find_author(digests)?; - let validators = >::authorities(); + let validators = Authorities::::get(); validators.get(i as usize).cloned() } } @@ -384,7 +382,7 @@ pub type AuraAuthorId = FindAccountFromAuthorIndex>; impl IsMember for Pallet { fn is_member(authority_id: &T::AuthorityId) -> bool { - Self::authorities().iter().any(|id| id == authority_id) + Authorities::::get().iter().any(|id| id == authority_id) } } diff --git a/substrate/frame/aura/src/tests.rs b/substrate/frame/aura/src/tests.rs index b3a5e144fad..5374105a2f3 100644 --- a/substrate/frame/aura/src/tests.rs +++ b/substrate/frame/aura/src/tests.rs @@ -19,7 +19,8 @@ #![cfg(test)] -use crate::mock::{build_ext_and_execute_test, Aura, MockDisabledValidators, System}; +use super::pallet; +use crate::mock::{build_ext_and_execute_test, Aura, MockDisabledValidators, System, Test}; use codec::Encode; use frame_support::traits::OnInitialize; use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; @@ -28,8 +29,8 @@ use sp_runtime::{Digest, DigestItem}; #[test] fn initial_values() { build_ext_and_execute_test(vec![0, 1, 2, 3], || { - assert_eq!(Aura::current_slot(), 0u64); - assert_eq!(Aura::authorities().len(), Aura::authorities_len()); + assert_eq!(pallet::CurrentSlot::::get(), 0u64); + assert_eq!(pallet::Authorities::::get().len(), Aura::authorities_len()); assert_eq!(Aura::authorities_len(), 4); }); } diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs index acaabc0dbc3..ad21b79a5b1 100644 --- a/templates/parachain/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -57,6 +57,8 @@ use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +use pallet_aura::Authorities; + // XCM Imports use xcm::latest::prelude::BodyId; @@ -547,7 +549,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + Authorities::::get().into_inner() } } diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs index 9b52ee60a63..5a97bd2f391 100644 --- a/templates/solochain/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -415,7 +415,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities().into_inner() + pallet_aura::Authorities::::get().into_inner() } } -- GitLab From 8d0cd4ffc875726f868b122c8b4b9bee4920c71d Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:45:39 +0200 Subject: [PATCH 133/188] Fix kusama validators getting 0 backing rewards the first session they enter the active set (#3722) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a problem in the way we update `authorithy-discovery` next keys and because of that nodes that enter the active set would be noticed at the start of the session they become active, instead of the start of the previous session as it was intended. This is problematic because: 1. The node itself advertises its addresses on the DHT only when it notices it should become active on around ~10m loop, so in this case it would notice after it becomes active. 2. The other nodes won't be able to detect the new nodes addresses at the beginning of the session, so it won't added them to the reserved set. With 1 + 2, we end-up in a situation where the the new node won't be able to properly connect to its peers because it won't be in its peers reserved set. Now, the nodes accept by default`MIN_GOSSIP_PEERS: usize = 25` connections to nodes that are not in the reserved set, but given Kusama size(> 1000 nodes) you could easily have more than`25` new nodes entering the active set or simply the nodes don't have slots anymore because, they already have connections to peers not in the active set. In the end what the node would notice is 0 backing rewards because it wasn't directly connected to the peers in its backing group. ## Root-cause The flow is like this: 1. At BAD_SESSION - 1, in `rotate_session` new nodes are added to QueuedKeys https://github.com/paritytech/polkadot-sdk/blob/02e1a7f476d7d7c67153e975ab9a1bdc02ffea12/substrate/frame/session/src/lib.rs#L609 ``` >::put(queued_amalgamated.clone()); >::put(next_changed); ``` 2. AuthorityDiscovery::on_new_session is called with `changed` being the value of `>:` at BAD_SESSION - **2** because it was saved before being updated https://github.com/paritytech/polkadot-sdk/blob/02e1a7f476d7d7c67153e975ab9a1bdc02ffea12/substrate/frame/session/src/lib.rs#L613 3. At BAD_SESSION - 1, `AuthorityDiscovery::on_new_session` doesn't updated its next_keys because `changed` was false. 4. For the entire durations of `BAD_SESSION - 1` everyone calling runtime api `authorities`(should return past, present and future authorities) won't discover the nodes that should become active . 5. At the beginning of BAD_SESSION, all nodes discover the new nodes are authorities, but it is already too late because reserved_nodes are updated only at the beginning of the session by the `gossip-support`. See above why this bad. ## Fix Update next keys with the queued_validators at every session, not matter the value of `changed` this is the same way babe pallet correctly does it. https://github.com/paritytech/polkadot-sdk/blob/02e1a7f476d7d7c67153e975ab9a1bdc02ffea12/substrate/frame/babe/src/lib.rs#L655 ## Notes - The issue doesn't reproduce with proof-authorities changes like `versi` because `changed` would always be true and `AuthorityDiscovery` correctly updates its next_keys every time. - Confirmed at session `37651` on kusama that this is exactly what it happens by looking at blocks with polkadot.js. ## TODO - [ ] Move versi on proof of stake and properly test before and after fix to confirm there is no other issue. --------- Signed-off-by: Alexandru Gheorghe Co-authored-by: Bastian Köcher --- prdoc/pr_3722.prdoc | 13 ++++ .../frame/authority-discovery/src/lib.rs | 66 ++++++++++++------- substrate/frame/session/src/lib.rs | 6 +- 3 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 prdoc/pr_3722.prdoc diff --git a/prdoc/pr_3722.prdoc b/prdoc/pr_3722.prdoc new file mode 100644 index 00000000000..7e2d7d38795 --- /dev/null +++ b/prdoc/pr_3722.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Fix kusama 0 backing rewards when entering active set + +doc: + - audience: Runtime Dev + description: | + This PR fixes getting 0 backing rewards the first session when + a node enters the active set. + +crates: + - name: pallet-authority-discovery diff --git a/substrate/frame/authority-discovery/src/lib.rs b/substrate/frame/authority-discovery/src/lib.rs index aa57378934a..ed9240d99e8 100644 --- a/substrate/frame/authority-discovery/src/lib.rs +++ b/substrate/frame/authority-discovery/src/lib.rs @@ -144,19 +144,21 @@ impl OneSessionHandler for Pallet { ); Keys::::put(bounded_keys); + } - let next_keys = queued_validators.map(|x| x.1).collect::>(); + // `changed` represents if queued_validators changed in the previous session not in the + // current one. + let next_keys = queued_validators.map(|x| x.1).collect::>(); - let next_bounded_keys = WeakBoundedVec::<_, T::MaxAuthorities>::force_from( - next_keys, - Some( - "Warning: The session has more queued validators than expected. \ - A runtime configuration adjustment may be needed.", - ), - ); + let next_bounded_keys = WeakBoundedVec::<_, T::MaxAuthorities>::force_from( + next_keys, + Some( + "Warning: The session has more queued validators than expected. \ + A runtime configuration adjustment may be needed.", + ), + ); - NextKeys::::put(next_bounded_keys); - } + NextKeys::::put(next_bounded_keys); } fn on_disabled(_i: u32) { @@ -270,7 +272,7 @@ mod tests { .map(|id| (&account_id, id)) .collect::>(); - let mut third_authorities: Vec = vec![4, 5] + let third_authorities: Vec = vec![4, 5] .into_iter() .map(|i| AuthorityPair::from_seed_slice(vec![i; 32].as_ref()).unwrap().public()) .map(AuthorityId::from) @@ -282,6 +284,18 @@ mod tests { .map(|id| (&account_id, id)) .collect::>(); + let mut fourth_authorities: Vec = vec![6, 7] + .into_iter() + .map(|i| AuthorityPair::from_seed_slice(vec![i; 32].as_ref()).unwrap().public()) + .map(AuthorityId::from) + .collect(); + // Needed for `pallet_session::OneSessionHandler::on_new_session`. + let fourth_authorities_and_account_ids = fourth_authorities + .clone() + .into_iter() + .map(|id| (&account_id, id)) + .collect::>(); + // Build genesis. let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); @@ -310,25 +324,33 @@ mod tests { third_authorities_and_account_ids.clone().into_iter(), ); let authorities_returned = AuthorityDiscovery::authorities(); + let mut first_and_third_authorities = first_authorities + .iter() + .chain(third_authorities.iter()) + .cloned() + .collect::>(); + first_and_third_authorities.sort(); + assert_eq!( - first_authorities, authorities_returned, + first_and_third_authorities, authorities_returned, "Expected authority set not to change as `changed` was set to false.", ); // When `changed` set to true, the authority set should be updated. AuthorityDiscovery::on_new_session( true, - second_authorities_and_account_ids.into_iter(), - third_authorities_and_account_ids.clone().into_iter(), + third_authorities_and_account_ids.into_iter(), + fourth_authorities_and_account_ids.clone().into_iter(), ); - let mut second_and_third_authorities = second_authorities + + let mut third_and_fourth_authorities = third_authorities .iter() - .chain(third_authorities.iter()) + .chain(fourth_authorities.iter()) .cloned() .collect::>(); - second_and_third_authorities.sort(); + third_and_fourth_authorities.sort(); assert_eq!( - second_and_third_authorities, + third_and_fourth_authorities, AuthorityDiscovery::authorities(), "Expected authority set to contain both the authorities of the new as well as the \ next session." @@ -337,12 +359,12 @@ mod tests { // With overlapping authority sets, `authorities()` should return a deduplicated set. AuthorityDiscovery::on_new_session( true, - third_authorities_and_account_ids.clone().into_iter(), - third_authorities_and_account_ids.clone().into_iter(), + fourth_authorities_and_account_ids.clone().into_iter(), + fourth_authorities_and_account_ids.clone().into_iter(), ); - third_authorities.sort(); + fourth_authorities.sort(); assert_eq!( - third_authorities, + fourth_authorities, AuthorityDiscovery::authorities(), "Expected authority set to be deduplicated." ); diff --git a/substrate/frame/session/src/lib.rs b/substrate/frame/session/src/lib.rs index 7d8128dbc1f..17b6aa7a464 100644 --- a/substrate/frame/session/src/lib.rs +++ b/substrate/frame/session/src/lib.rs @@ -285,7 +285,11 @@ pub trait SessionHandler { /// before initialization of your pallet. /// /// `changed` is true whenever any of the session keys or underlying economic - /// identities or weightings behind those keys has changed. + /// identities or weightings behind `validators` keys has changed. `queued_validators` + /// could change without `validators` changing. Example of possible sequent calls: + /// Session N: on_new_session(false, unchanged_validators, unchanged_queued_validators) + /// Session N + 1: on_new_session(false, unchanged_validators, new_queued_validators) + /// Session N + 2: on_new_session(true, new_queued_validators, new_queued_validators) fn on_new_session( changed: bool, validators: &[(ValidatorId, Ks)], -- GitLab From 1d60f9ca9ae82621380530a19162652c13106a4f Mon Sep 17 00:00:00 2001 From: jokess123 <163112061+jokess123@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:18:40 +0800 Subject: [PATCH 134/188] Fix typos (#3725) --- polkadot/node/subsystem-bench/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/polkadot/node/subsystem-bench/README.md b/polkadot/node/subsystem-bench/README.md index 94a449ed0bb..228fba41c46 100644 --- a/polkadot/node/subsystem-bench/README.md +++ b/polkadot/node/subsystem-bench/README.md @@ -27,7 +27,7 @@ The output binary will be placed in `target/testnet/subsystem-bench`. ### Test metrics Subsystem, CPU usage and network metrics are exposed via a prometheus endpoint during the test execution. -A small subset of these collected metrics are displayed in the CLI, but for an in depth analysys of the test results, +A small subset of these collected metrics are displayed in the CLI, but for an in depth analysis of the test results, a local Grafana/Prometheus stack is needed. ### Run Prometheus, Pyroscope and Graphana in Docker @@ -122,7 +122,7 @@ target/testnet/subsystem-bench polkadot/node/subsystem-bench/examples/availabili ``` Note: test objectives may be wrapped up into a test sequence. -It is tipically used to run a suite of tests like in this [example](examples/availability_read.yaml). +It is typically used to run a suite of tests like in this [example](examples/availability_read.yaml). ### Understanding the test configuration @@ -137,13 +137,13 @@ usage: From the perspective of the subsystem under test, this means that it will receive an `ActiveLeavesUpdate` signal followed by an arbitrary amount of messages. This process repeats itself for `num_blocks`. The messages are generally -test payloads pre-generated before the test run, or constructed on pre-genereated payloads. For example the +test payloads pre-generated before the test run, or constructed on pre-generated payloads. For example the `AvailabilityRecoveryMessage::RecoverAvailableData` message includes a `CandidateReceipt` which is generated before the test is started. ### Example run -Let's run an availabilty read test which will recover availability for 200 cores with max PoV size on a 1000 +Let's run an availability read test which will recover availability for 200 cores with max PoV size on a 1000 node validator network. -- GitLab From 0c6c837f689a287583508506e342ba07687e8d26 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 18 Mar 2024 13:37:24 +0100 Subject: [PATCH 135/188] Bridge zombienet tests: remove unneeded accounts (#3700) Bridge zombienet tests: remove unneeded accounts --- .../rococo-westend/bridges_rococo_westend.sh | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh index 479ab833abf..66c9ddc037b 100755 --- a/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh +++ b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh @@ -24,12 +24,6 @@ source "$FRAMEWORK_PATH/utils/bridges.sh" # &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Rococo)) }).unwrap() # ).to_ss58check_with_version(42_u16.into()) # ); -# println!("GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT=\"{}\"", -# frame_support::sp_runtime::AccountId32::new( -# GlobalConsensusParachainConvertsFor::::convert_location( -# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Rococo), Parachain(1000)) }).unwrap() -# ).to_ss58check_with_version(42_u16.into()) -# ); # println!("ASSET_HUB_WESTEND_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WESTEND=\"{}\"", # frame_support::sp_runtime::AccountId32::new( # SiblingParachainConvertsVia::::convert_location( @@ -44,12 +38,6 @@ source "$FRAMEWORK_PATH/utils/bridges.sh" # &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Westend)) }).unwrap() # ).to_ss58check_with_version(42_u16.into()) # ); -# println!("GLOBAL_CONSENSUS_WESTEND_ASSET_HUB_WESTEND_1000_SOVEREIGN_ACCOUNT=\"{}\"", -# frame_support::sp_runtime::AccountId32::new( -# GlobalConsensusParachainConvertsFor::::convert_location( -# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Westend), Parachain(1000)) }).unwrap() -# ).to_ss58check_with_version(42_u16.into()) -# ); # println!("ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO=\"{}\"", # frame_support::sp_runtime::AccountId32::new( # SiblingParachainConvertsVia::::convert_location( @@ -58,10 +46,8 @@ source "$FRAMEWORK_PATH/utils/bridges.sh" # ); # } GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT="5GxRGwT8bU1JeBPTUXc7LEjZMxNrK8MyL2NJnkWFQJTQ4sii" -GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT="5CfNu7eH3SJvqqPt3aJh38T8dcFvhGzEohp9tsd41ANhXDnQ" ASSET_HUB_WESTEND_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WESTEND="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV" GLOBAL_CONSENSUS_WESTEND_SOVEREIGN_ACCOUNT="5He2Qdztyxxa4GoagY6q1jaiLMmKy1gXS7PdZkhfj8ZG9hk5" -GLOBAL_CONSENSUS_WESTEND_ASSET_HUB_WESTEND_1000_SOVEREIGN_ACCOUNT="5GUD9X494SnhfBTNReHwhV1599McpyVrAqFY6WnTfVQVYNUM" ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV" # Expected sovereign accounts for rewards on BridgeHubs. @@ -201,12 +187,6 @@ case "$1" in "$GLOBAL_CONSENSUS_WESTEND_SOVEREIGN_ACCOUNT" \ 10000000000 \ true - # drip SA which holds reserves - transfer_balance \ - "ws://127.0.0.1:9910" \ - "//Alice" \ - "$GLOBAL_CONSENSUS_WESTEND_ASSET_HUB_WESTEND_1000_SOVEREIGN_ACCOUNT" \ - $((1000000000000 + 50000000000 * 20)) # HRMP open_hrmp_channels \ "ws://127.0.0.1:9942" \ @@ -266,12 +246,6 @@ case "$1" in "$GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT" \ 10000000000 \ true - # drip SA which holds reserves - transfer_balance \ - "ws://127.0.0.1:9010" \ - "//Alice" \ - "$GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ - $((1000000000000000 + 50000000000 * 20)) # HRMP open_hrmp_channels \ "ws://127.0.0.1:9945" \ -- GitLab From 610987a19da816a76c296c99f311ce8f6e9ab3d8 Mon Sep 17 00:00:00 2001 From: Matteo Muraca <56828990+muraca@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:19:20 +0100 Subject: [PATCH 136/188] removed `pallet::getter` usage from cumulus pallets (#3471) Part of #3326 @ggwpez @kianenigma @shawntabrizi polkadot address: 12poSUQPtcF1HUPQGY3zZu2P8emuW9YnsPduA4XG3oCEfJVp --------- Signed-off-by: Matteo Muraca --- .../pallets/aura-ext/src/consensus_hook.rs | 6 +- cumulus/pallets/aura-ext/src/lib.rs | 1 - .../collator-selection/src/benchmarking.rs | 76 ++--- cumulus/pallets/collator-selection/src/lib.rs | 83 +++-- .../collator-selection/src/migration.rs | 2 +- .../pallets/collator-selection/src/tests.rs | 316 +++++++++--------- cumulus/pallets/parachain-system/src/lib.rs | 30 +- .../pallets/parachain-info/src/lib.rs | 11 +- prdoc/pr_3471.prdoc | 33 ++ 9 files changed, 292 insertions(+), 266 deletions(-) create mode 100644 prdoc/pr_3471.prdoc diff --git a/cumulus/pallets/aura-ext/src/consensus_hook.rs b/cumulus/pallets/aura-ext/src/consensus_hook.rs index 089ab5c3198..59202980339 100644 --- a/cumulus/pallets/aura-ext/src/consensus_hook.rs +++ b/cumulus/pallets/aura-ext/src/consensus_hook.rs @@ -54,8 +54,8 @@ where let velocity = V.max(1); let relay_chain_slot = state_proof.read_slot().expect("failed to read relay chain slot"); - let (slot, authored) = pallet::Pallet::::slot_info() - .expect("slot info is inserted on block initialization"); + let (slot, authored) = + pallet::SlotInfo::::get().expect("slot info is inserted on block initialization"); // Convert relay chain timestamp. let relay_chain_timestamp = @@ -100,7 +100,7 @@ impl< /// is more recent than the included block itself. pub fn can_build_upon(included_hash: T::Hash, new_slot: Slot) -> bool { let velocity = V.max(1); - let (last_slot, authored_so_far) = match pallet::Pallet::::slot_info() { + let (last_slot, authored_so_far) = match pallet::SlotInfo::::get() { None => return true, Some(x) => x, }; diff --git a/cumulus/pallets/aura-ext/src/lib.rs b/cumulus/pallets/aura-ext/src/lib.rs index b71ae628954..7ca84dff7c5 100644 --- a/cumulus/pallets/aura-ext/src/lib.rs +++ b/cumulus/pallets/aura-ext/src/lib.rs @@ -103,7 +103,6 @@ pub mod pallet { /// /// Updated on each block initialization. #[pallet::storage] - #[pallet::getter(fn slot_info)] pub(crate) type SlotInfo = StorageValue<_, (Slot, u32), OptionQuery>; #[pallet::genesis_config] diff --git a/cumulus/pallets/collator-selection/src/benchmarking.rs b/cumulus/pallets/collator-selection/src/benchmarking.rs index e2af74a6e60..c6b60044528 100644 --- a/cumulus/pallets/collator-selection/src/benchmarking.rs +++ b/cumulus/pallets/collator-selection/src/benchmarking.rs @@ -86,23 +86,23 @@ fn register_validators(count: u32) -> Vec(count: u32) { let candidates = (0..count).map(|c| account("candidate", c, SEED)).collect::>(); - assert!(>::get() > 0u32.into(), "Bond cannot be zero!"); + assert!(CandidacyBond::::get() > 0u32.into(), "Bond cannot be zero!"); for who in candidates { - T::Currency::make_free_balance_be(&who, >::get() * 3u32.into()); + T::Currency::make_free_balance_be(&who, CandidacyBond::::get() * 3u32.into()); >::register_as_candidate(RawOrigin::Signed(who).into()).unwrap(); } } fn min_candidates() -> u32 { let min_collators = T::MinEligibleCollators::get(); - let invulnerable_length = >::get().len(); + let invulnerable_length = Invulnerables::::get().len(); min_collators.saturating_sub(invulnerable_length.try_into().unwrap()) } fn min_invulnerables() -> u32 { let min_collators = T::MinEligibleCollators::get(); - let candidates_length = >::decode_len() + let candidates_length = CandidateList::::decode_len() .unwrap_or_default() .try_into() .unwrap_or_default(); @@ -143,8 +143,8 @@ mod benchmarks { T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; // need to fill up candidates - >::put(T::Currency::minimum_balance()); - >::put(c); + CandidacyBond::::put(T::Currency::minimum_balance()); + DesiredCandidates::::put(c); // get accounts and keys for the `c` candidates let mut candidates = (0..c).map(|cc| validator::(cc)).collect::>(); // add one more to the list. should not be in `b` (invulnerables) because it's the account @@ -159,15 +159,15 @@ mod benchmarks { } // ... and register them. for (who, _) in candidates.iter() { - let deposit = >::get(); + let deposit = CandidacyBond::::get(); T::Currency::make_free_balance_be(who, deposit * 1000_u32.into()); - >::try_mutate(|list| { + CandidateList::::try_mutate(|list| { list.try_push(CandidateInfo { who: who.clone(), deposit }).unwrap(); Ok::<(), BenchmarkError>(()) }) .unwrap(); T::Currency::reserve(who, deposit)?; - >::insert( + LastAuthoredBlock::::insert( who.clone(), frame_system::Pallet::::block_number() + T::KickThreshold::get(), ); @@ -178,7 +178,7 @@ mod benchmarks { invulnerables.sort(); let invulnerables: frame_support::BoundedVec<_, T::MaxInvulnerables> = frame_support::BoundedVec::try_from(invulnerables).unwrap(); - >::put(invulnerables); + Invulnerables::::put(invulnerables); #[extrinsic_call] _(origin as T::RuntimeOrigin, new_invulnerable.clone()); @@ -197,8 +197,8 @@ mod benchmarks { invulnerables.sort(); let invulnerables: frame_support::BoundedVec<_, T::MaxInvulnerables> = frame_support::BoundedVec::try_from(invulnerables).unwrap(); - >::put(invulnerables); - let to_remove = >::get().first().unwrap().clone(); + Invulnerables::::put(invulnerables); + let to_remove = Invulnerables::::get().first().unwrap().clone(); #[extrinsic_call] _(origin as T::RuntimeOrigin, to_remove.clone()); @@ -226,14 +226,14 @@ mod benchmarks { k: Linear<0, { T::MaxCandidates::get() }>, ) -> Result<(), BenchmarkError> { let initial_bond_amount: BalanceOf = T::Currency::minimum_balance() * 2u32.into(); - >::put(initial_bond_amount); + CandidacyBond::::put(initial_bond_amount); register_validators::(c); register_candidates::(c); let kicked = cmp::min(k, c); let origin = T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let bond_amount = if k > 0 { - >::mutate(|candidates| { + CandidateList::::mutate(|candidates| { for info in candidates.iter_mut().skip(kicked as usize) { info.deposit = T::Currency::minimum_balance() * 3u32.into(); } @@ -254,13 +254,13 @@ mod benchmarks { fn update_bond( c: Linear<{ min_candidates::() + 1 }, { T::MaxCandidates::get() }>, ) -> Result<(), BenchmarkError> { - >::put(T::Currency::minimum_balance()); - >::put(c); + CandidacyBond::::put(T::Currency::minimum_balance()); + DesiredCandidates::::put(c); register_validators::(c); register_candidates::(c); - let caller = >::get()[0].who.clone(); + let caller = CandidateList::::get()[0].who.clone(); v2::whitelist!(caller); let bond_amount: BalanceOf = @@ -273,7 +273,7 @@ mod benchmarks { Event::CandidateBondUpdated { account_id: caller, deposit: bond_amount }.into(), ); assert!( - >::get().iter().last().unwrap().deposit == + CandidateList::::get().iter().last().unwrap().deposit == T::Currency::minimum_balance() * 2u32.into() ); Ok(()) @@ -283,8 +283,8 @@ mod benchmarks { // one. #[benchmark] fn register_as_candidate(c: Linear<1, { T::MaxCandidates::get() - 1 }>) { - >::put(T::Currency::minimum_balance()); - >::put(c + 1); + CandidacyBond::::put(T::Currency::minimum_balance()); + DesiredCandidates::::put(c + 1); register_validators::(c); register_candidates::(c); @@ -310,8 +310,8 @@ mod benchmarks { #[benchmark] fn take_candidate_slot(c: Linear<{ min_candidates::() + 1 }, { T::MaxCandidates::get() }>) { - >::put(T::Currency::minimum_balance()); - >::put(1); + CandidacyBond::::put(T::Currency::minimum_balance()); + DesiredCandidates::::put(1); register_validators::(c); register_candidates::(c); @@ -327,7 +327,7 @@ mod benchmarks { ) .unwrap(); - let target = >::get().iter().last().unwrap().who.clone(); + let target = CandidateList::::get().iter().last().unwrap().who.clone(); #[extrinsic_call] _(RawOrigin::Signed(caller.clone()), bond / 2u32.into(), target.clone()); @@ -341,13 +341,13 @@ mod benchmarks { // worse case is the last candidate leaving. #[benchmark] fn leave_intent(c: Linear<{ min_candidates::() + 1 }, { T::MaxCandidates::get() }>) { - >::put(T::Currency::minimum_balance()); - >::put(c); + CandidacyBond::::put(T::Currency::minimum_balance()); + DesiredCandidates::::put(c); register_validators::(c); register_candidates::(c); - let leaving = >::get().iter().last().unwrap().who.clone(); + let leaving = CandidateList::::get().iter().last().unwrap().who.clone(); v2::whitelist!(leaving); #[extrinsic_call] @@ -359,7 +359,7 @@ mod benchmarks { // worse case is paying a non-existing candidate account. #[benchmark] fn note_author() { - >::put(T::Currency::minimum_balance()); + CandidacyBond::::put(T::Currency::minimum_balance()); T::Currency::make_free_balance_be( &>::account_id(), T::Currency::minimum_balance() * 4u32.into(), @@ -385,8 +385,8 @@ mod benchmarks { r: Linear<1, { T::MaxCandidates::get() }>, c: Linear<1, { T::MaxCandidates::get() }>, ) { - >::put(T::Currency::minimum_balance()); - >::put(c); + CandidacyBond::::put(T::Currency::minimum_balance()); + DesiredCandidates::::put(c); frame_system::Pallet::::set_block_number(0u32.into()); register_validators::(c); @@ -394,7 +394,7 @@ mod benchmarks { let new_block: BlockNumberFor = T::KickThreshold::get(); let zero_block: BlockNumberFor = 0u32.into(); - let candidates: Vec = >::get() + let candidates: Vec = CandidateList::::get() .iter() .map(|candidate_info| candidate_info.who.clone()) .collect(); @@ -402,25 +402,25 @@ mod benchmarks { let non_removals = c.saturating_sub(r); for i in 0..c { - >::insert(candidates[i as usize].clone(), zero_block); + LastAuthoredBlock::::insert(candidates[i as usize].clone(), zero_block); } if non_removals > 0 { for i in 0..non_removals { - >::insert(candidates[i as usize].clone(), new_block); + LastAuthoredBlock::::insert(candidates[i as usize].clone(), new_block); } } else { for i in 0..c { - >::insert(candidates[i as usize].clone(), new_block); + LastAuthoredBlock::::insert(candidates[i as usize].clone(), new_block); } } let min_candidates = min_candidates::(); - let pre_length = >::decode_len().unwrap_or_default(); + let pre_length = CandidateList::::decode_len().unwrap_or_default(); frame_system::Pallet::::set_block_number(new_block); - let current_length: u32 = >::decode_len() + let current_length: u32 = CandidateList::::decode_len() .unwrap_or_default() .try_into() .unwrap_or_default(); @@ -434,12 +434,12 @@ mod benchmarks { // candidates > removals and remaining candidates > min candidates // => remaining candidates should be shorter than before removal, i.e. some were // actually removed. - assert!(>::decode_len().unwrap_or_default() < pre_length); + assert!(CandidateList::::decode_len().unwrap_or_default() < pre_length); } else if c > r && non_removals < min_candidates { // candidates > removals and remaining candidates would be less than min candidates // => remaining candidates should equal min candidates, i.e. some were removed up to // the minimum, but then any more were "forced" to stay in candidates. - let current_length: u32 = >::decode_len() + let current_length: u32 = CandidateList::::decode_len() .unwrap_or_default() .try_into() .unwrap_or_default(); @@ -447,7 +447,7 @@ mod benchmarks { } else { // removals >= candidates, non removals must == 0 // can't remove more than exist - assert!(>::decode_len().unwrap_or_default() == pre_length); + assert!(CandidateList::::decode_len().unwrap_or_default() == pre_length); } } diff --git a/cumulus/pallets/collator-selection/src/lib.rs b/cumulus/pallets/collator-selection/src/lib.rs index 62c00737f91..84bde5c9fac 100644 --- a/cumulus/pallets/collator-selection/src/lib.rs +++ b/cumulus/pallets/collator-selection/src/lib.rs @@ -196,7 +196,6 @@ pub mod pallet { /// The invulnerable, permissioned collators. This list must be sorted. #[pallet::storage] - #[pallet::getter(fn invulnerables)] pub type Invulnerables = StorageValue<_, BoundedVec, ValueQuery>; @@ -206,7 +205,6 @@ pub mod pallet { /// This list is sorted in ascending order by deposit and when the deposits are equal, the least /// recently updated is considered greater. #[pallet::storage] - #[pallet::getter(fn candidate_list)] pub type CandidateList = StorageValue< _, BoundedVec>, T::MaxCandidates>, @@ -215,7 +213,6 @@ pub mod pallet { /// Last block authored by collator. #[pallet::storage] - #[pallet::getter(fn last_authored_block)] pub type LastAuthoredBlock = StorageMap<_, Twox64Concat, T::AccountId, BlockNumberFor, ValueQuery>; @@ -223,14 +220,12 @@ pub mod pallet { /// /// This should ideally always be less than [`Config::MaxCandidates`] for weights to be correct. #[pallet::storage] - #[pallet::getter(fn desired_candidates)] pub type DesiredCandidates = StorageValue<_, u32, ValueQuery>; /// Fixed amount to deposit to become a collator. /// /// When a collator calls `leave_intent` they immediately receive the deposit back. #[pallet::storage] - #[pallet::getter(fn candidacy_bond)] pub type CandidacyBond = StorageValue<_, BalanceOf, ValueQuery>; #[pallet::genesis_config] @@ -263,9 +258,9 @@ pub mod pallet { bounded_invulnerables.sort(); - >::put(self.desired_candidates); - >::put(self.candidacy_bond); - >::put(bounded_invulnerables); + DesiredCandidates::::put(self.desired_candidates); + CandidacyBond::::put(self.candidacy_bond); + Invulnerables::::put(bounded_invulnerables); } } @@ -424,7 +419,7 @@ pub mod pallet { // Invulnerables must be sorted for removal. bounded_invulnerables.sort(); - >::put(&bounded_invulnerables); + Invulnerables::::put(&bounded_invulnerables); Self::deposit_event(Event::NewInvulnerables { invulnerables: bounded_invulnerables.to_vec(), }); @@ -448,7 +443,7 @@ pub mod pallet { if max > T::MaxCandidates::get() { log::warn!("max > T::MaxCandidates; you might need to run benchmarks again"); } - >::put(max); + DesiredCandidates::::put(max); Self::deposit_event(Event::NewDesiredCandidates { desired_candidates: max }); Ok(().into()) } @@ -470,17 +465,17 @@ pub mod pallet { bond: BalanceOf, ) -> DispatchResultWithPostInfo { T::UpdateOrigin::ensure_origin(origin)?; - let bond_increased = >::mutate(|old_bond| -> bool { + let bond_increased = CandidacyBond::::mutate(|old_bond| -> bool { let bond_increased = *old_bond < bond; *old_bond = bond; bond_increased }); - let initial_len = >::decode_len().unwrap_or_default(); + let initial_len = CandidateList::::decode_len().unwrap_or_default(); let kicked = (bond_increased && initial_len > 0) .then(|| { // Closure below returns the number of candidates which were kicked because // their deposits were lower than the new candidacy bond. - >::mutate(|candidates| -> usize { + CandidateList::::mutate(|candidates| -> usize { let first_safe_candidate = candidates .iter() .position(|candidate| candidate.deposit >= bond) @@ -488,7 +483,7 @@ pub mod pallet { let kicked_candidates = candidates.drain(..first_safe_candidate); for candidate in kicked_candidates { T::Currency::unreserve(&candidate.who, candidate.deposit); - >::remove(candidate.who); + LastAuthoredBlock::::remove(candidate.who); } first_safe_candidate }) @@ -512,12 +507,12 @@ pub mod pallet { let who = ensure_signed(origin)?; // ensure we are below limit. - let length: u32 = >::decode_len() + let length: u32 = CandidateList::::decode_len() .unwrap_or_default() .try_into() .unwrap_or_default(); ensure!(length < T::MaxCandidates::get(), Error::::TooManyCandidates); - ensure!(!Self::invulnerables().contains(&who), Error::::AlreadyInvulnerable); + ensure!(!Invulnerables::::get().contains(&who), Error::::AlreadyInvulnerable); let validator_key = T::ValidatorIdOf::convert(who.clone()) .ok_or(Error::::NoAssociatedValidatorId)?; @@ -526,15 +521,15 @@ pub mod pallet { Error::::ValidatorNotRegistered ); - let deposit = Self::candidacy_bond(); + let deposit = CandidacyBond::::get(); // First authored block is current block plus kick threshold to handle session delay - >::try_mutate(|candidates| -> Result<(), DispatchError> { + CandidateList::::try_mutate(|candidates| -> Result<(), DispatchError> { ensure!( !candidates.iter().any(|candidate_info| candidate_info.who == who), Error::::AlreadyCandidate ); T::Currency::reserve(&who, deposit)?; - >::insert( + LastAuthoredBlock::::insert( who.clone(), frame_system::Pallet::::block_number() + T::KickThreshold::get(), ); @@ -564,7 +559,7 @@ pub mod pallet { Self::eligible_collators() > T::MinEligibleCollators::get(), Error::::TooFewEligibleCollators ); - let length = >::decode_len().unwrap_or_default(); + let length = CandidateList::::decode_len().unwrap_or_default(); // Do remove their last authored block. Self::try_remove_candidate(&who, true)?; @@ -594,7 +589,7 @@ pub mod pallet { Error::::ValidatorNotRegistered ); - >::try_mutate(|invulnerables| -> DispatchResult { + Invulnerables::::try_mutate(|invulnerables| -> DispatchResult { match invulnerables.binary_search(&who) { Ok(_) => return Err(Error::::AlreadyInvulnerable)?, Err(pos) => invulnerables @@ -615,7 +610,7 @@ pub mod pallet { .unwrap_or_default() .try_into() .unwrap_or(T::MaxInvulnerables::get().saturating_sub(1)), - >::decode_len() + CandidateList::::decode_len() .unwrap_or_default() .try_into() .unwrap_or(T::MaxCandidates::get()), @@ -638,7 +633,7 @@ pub mod pallet { Error::::TooFewEligibleCollators ); - >::try_mutate(|invulnerables| -> DispatchResult { + Invulnerables::::try_mutate(|invulnerables| -> DispatchResult { let pos = invulnerables.binary_search(&who).map_err(|_| Error::::NotInvulnerable)?; invulnerables.remove(pos); @@ -663,12 +658,12 @@ pub mod pallet { new_deposit: BalanceOf, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(new_deposit >= >::get(), Error::::DepositTooLow); + ensure!(new_deposit >= CandidacyBond::::get(), Error::::DepositTooLow); // The function below will try to mutate the `CandidateList` entry for the caller to // update their deposit to the new value of `new_deposit`. The return value is the // position of the entry in the list, used for weight calculation. let length = - >::try_mutate(|candidates| -> Result { + CandidateList::::try_mutate(|candidates| -> Result { let idx = candidates .iter() .position(|candidate_info| candidate_info.who == who) @@ -682,7 +677,7 @@ pub mod pallet { } else if new_deposit < old_deposit { // Casting `u32` to `usize` should be safe on all machines running this. ensure!( - idx.saturating_add(>::get() as usize) < + idx.saturating_add(DesiredCandidates::::get() as usize) < candidate_count, Error::::InvalidUnreserve ); @@ -727,8 +722,8 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(!Self::invulnerables().contains(&who), Error::::AlreadyInvulnerable); - ensure!(deposit >= Self::candidacy_bond(), Error::::InsufficientBond); + ensure!(!Invulnerables::::get().contains(&who), Error::::AlreadyInvulnerable); + ensure!(deposit >= CandidacyBond::::get(), Error::::InsufficientBond); let validator_key = T::ValidatorIdOf::convert(who.clone()) .ok_or(Error::::NoAssociatedValidatorId)?; @@ -737,12 +732,12 @@ pub mod pallet { Error::::ValidatorNotRegistered ); - let length = >::decode_len().unwrap_or_default(); + let length = CandidateList::::decode_len().unwrap_or_default(); // The closure below iterates through all elements of the candidate list to ensure that // the caller isn't already a candidate and to find the target it's trying to replace in // the list. The return value is a tuple of the position of the candidate to be replaced // in the list along with its candidate information. - let target_info = >::try_mutate( + let target_info = CandidateList::::try_mutate( |candidates| -> Result>, DispatchError> { // Find the position in the list of the candidate that is being replaced. let mut target_info_idx = None; @@ -787,8 +782,8 @@ pub mod pallet { )?; T::Currency::reserve(&who, deposit)?; T::Currency::unreserve(&target_info.who, target_info.deposit); - >::remove(target_info.who.clone()); - >::insert( + LastAuthoredBlock::::remove(target_info.who.clone()); + LastAuthoredBlock::::insert( who.clone(), frame_system::Pallet::::block_number() + T::KickThreshold::get(), ); @@ -807,7 +802,7 @@ pub mod pallet { /// Return the total number of accounts that are eligible collators (candidates and /// invulnerables). fn eligible_collators() -> u32 { - >::decode_len() + CandidateList::::decode_len() .unwrap_or_default() .saturating_add(Invulnerables::::decode_len().unwrap_or_default()) .try_into() @@ -819,7 +814,7 @@ pub mod pallet { who: &T::AccountId, remove_last_authored: bool, ) -> Result<(), DispatchError> { - >::try_mutate(|candidates| -> Result<(), DispatchError> { + CandidateList::::try_mutate(|candidates| -> Result<(), DispatchError> { let idx = candidates .iter() .position(|candidate_info| candidate_info.who == *who) @@ -828,7 +823,7 @@ pub mod pallet { T::Currency::unreserve(who, deposit); candidates.remove(idx); if remove_last_authored { - >::remove(who.clone()) + LastAuthoredBlock::::remove(who.clone()) }; Ok(()) })?; @@ -841,10 +836,10 @@ pub mod pallet { /// This is done on the fly, as frequent as we are told to do so, as the session manager. pub fn assemble_collators() -> Vec { // Casting `u32` to `usize` should be safe on all machines running this. - let desired_candidates = >::get() as usize; - let mut collators = Self::invulnerables().to_vec(); + let desired_candidates = DesiredCandidates::::get() as usize; + let mut collators = Invulnerables::::get().to_vec(); collators.extend( - >::get() + CandidateList::::get() .iter() .rev() .cloned() @@ -865,10 +860,10 @@ pub mod pallet { candidates .into_iter() .filter_map(|c| { - let last_block = >::get(c.clone()); + let last_block = LastAuthoredBlock::::get(c.clone()); let since_last = now.saturating_sub(last_block); - let is_invulnerable = Self::invulnerables().contains(&c); + let is_invulnerable = Invulnerables::::get().contains(&c); let is_lazy = since_last >= kick_threshold; if is_invulnerable { @@ -907,7 +902,7 @@ pub mod pallet { /// or equal to the minimum number of eligible collators. #[cfg(any(test, feature = "try-runtime"))] pub fn do_try_state() -> Result<(), sp_runtime::TryRuntimeError> { - let desired_candidates = >::get(); + let desired_candidates = DesiredCandidates::::get(); frame_support::ensure!( desired_candidates <= T::MaxCandidates::get(), @@ -939,7 +934,7 @@ pub mod pallet { // `reward` is half of pot account minus ED, this should never fail. let _success = T::Currency::transfer(&pot, &author, reward, KeepAlive); debug_assert!(_success.is_ok()); - >::insert(author, frame_system::Pallet::::block_number()); + LastAuthoredBlock::::insert(author, frame_system::Pallet::::block_number()); frame_system::Pallet::::register_extra_weight_unchecked( T::WeightInfo::note_author(), @@ -960,12 +955,12 @@ pub mod pallet { // The `expect` below is safe because the list is a `BoundedVec` with a max size of // `T::MaxCandidates`, which is a `u32`. When `decode_len` returns `Some(len)`, `len` // must be valid and at most `u32::MAX`, which must always be able to convert to `u32`. - let candidates_len_before: u32 = >::decode_len() + let candidates_len_before: u32 = CandidateList::::decode_len() .unwrap_or_default() .try_into() .expect("length is at most `T::MaxCandidates`, so it must fit in `u32`; qed"); let active_candidates_count = Self::kick_stale_candidates( - >::get() + CandidateList::::get() .iter() .map(|candidate_info| candidate_info.who.clone()), ); diff --git a/cumulus/pallets/collator-selection/src/migration.rs b/cumulus/pallets/collator-selection/src/migration.rs index f384981dbae..5dc2fba4279 100644 --- a/cumulus/pallets/collator-selection/src/migration.rs +++ b/cumulus/pallets/collator-selection/src/migration.rs @@ -34,7 +34,7 @@ pub mod v1 { let on_chain_version = Pallet::::on_chain_storage_version(); if on_chain_version == 0 { let invulnerables_len = Invulnerables::::get().to_vec().len(); - >::mutate(|invulnerables| { + Invulnerables::::mutate(|invulnerables| { invulnerables.sort(); }); diff --git a/cumulus/pallets/collator-selection/src/tests.rs b/cumulus/pallets/collator-selection/src/tests.rs index ed2044ccdfa..e8b2a4e146a 100644 --- a/cumulus/pallets/collator-selection/src/tests.rs +++ b/cumulus/pallets/collator-selection/src/tests.rs @@ -14,7 +14,10 @@ // limitations under the License. use crate as collator_selection; -use crate::{mock::*, CandidateInfo, Error}; +use crate::{ + mock::*, CandidacyBond, CandidateInfo, CandidateList, DesiredCandidates, Error, Invulnerables, + LastAuthoredBlock, +}; use frame_support::{ assert_noop, assert_ok, traits::{Currency, OnInitialize}, @@ -25,12 +28,12 @@ use sp_runtime::{testing::UintAuthorityId, traits::BadOrigin, BuildStorage}; #[test] fn basic_setup_works() { new_test_ext().execute_with(|| { - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); + assert_eq!(CandidateList::::get().iter().count(), 0); // genesis should sort input - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(Invulnerables::::get(), vec![1, 2]); }); } @@ -43,7 +46,7 @@ fn it_should_set_invulnerables() { new_set.clone() )); new_set.sort(); - assert_eq!(CollatorSelection::invulnerables(), new_set); + assert_eq!(Invulnerables::::get(), new_set); // cannot set with non-root. assert_noop!( @@ -56,7 +59,7 @@ fn it_should_set_invulnerables() { #[test] fn it_should_set_invulnerables_even_with_some_invalid() { new_test_ext().execute_with(|| { - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(Invulnerables::::get(), vec![1, 2]); let new_with_invalid = vec![1, 4, 3, 42, 2]; assert_ok!(CollatorSelection::set_invulnerables( @@ -65,7 +68,7 @@ fn it_should_set_invulnerables_even_with_some_invalid() { )); // should succeed and order them, but not include 42 - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2, 3, 4]); + assert_eq!(Invulnerables::::get(), vec![1, 2, 3, 4]); }); } @@ -73,7 +76,7 @@ fn it_should_set_invulnerables_even_with_some_invalid() { fn add_invulnerable_works() { new_test_ext().execute_with(|| { initialize_to_block(1); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(Invulnerables::::get(), vec![1, 2]); let new = 3; // function runs @@ -93,7 +96,7 @@ fn add_invulnerable_works() { ); // new element is now part of the invulnerables list - assert!(CollatorSelection::invulnerables().to_vec().contains(&new)); + assert!(Invulnerables::::get().to_vec().contains(&new)); // cannot add with non-root assert_noop!(CollatorSelection::add_invulnerable(RuntimeOrigin::signed(1), new), BadOrigin); @@ -113,7 +116,7 @@ fn add_invulnerable_works() { #[test] fn invulnerable_limit_works() { new_test_ext().execute_with(|| { - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // MaxInvulnerables: u32 = 20 for ii in 3..=21 { @@ -140,7 +143,7 @@ fn invulnerable_limit_works() { } } let expected: Vec = (1..=20).collect(); - assert_eq!(CollatorSelection::invulnerables(), expected); + assert_eq!(Invulnerables::::get(), expected); // Cannot set too many Invulnerables let too_many_invulnerables: Vec = (1..=21).collect(); @@ -151,7 +154,7 @@ fn invulnerable_limit_works() { ), Error::::TooManyInvulnerables ); - assert_eq!(CollatorSelection::invulnerables(), expected); + assert_eq!(Invulnerables::::get(), expected); }); } @@ -159,7 +162,7 @@ fn invulnerable_limit_works() { fn remove_invulnerable_works() { new_test_ext().execute_with(|| { initialize_to_block(1); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(Invulnerables::::get(), vec![1, 2]); assert_ok!(CollatorSelection::add_invulnerable( RuntimeOrigin::signed(RootAccount::get()), @@ -170,7 +173,7 @@ fn remove_invulnerable_works() { 3 )); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2, 3, 4]); + assert_eq!(Invulnerables::::get(), vec![1, 2, 3, 4]); assert_ok!(CollatorSelection::remove_invulnerable( RuntimeOrigin::signed(RootAccount::get()), @@ -180,7 +183,7 @@ fn remove_invulnerable_works() { System::assert_last_event(RuntimeEvent::CollatorSelection( crate::Event::InvulnerableRemoved { account_id: 2 }, )); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 3, 4]); + assert_eq!(Invulnerables::::get(), vec![1, 3, 4]); // cannot remove invulnerable not in the list assert_noop!( @@ -200,11 +203,11 @@ fn remove_invulnerable_works() { fn candidate_to_invulnerable_works() { new_test_ext().execute_with(|| { initialize_to_block(1); - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); assert_eq!(Balances::free_balance(3), 100); assert_eq!(Balances::free_balance(4), 100); @@ -225,9 +228,9 @@ fn candidate_to_invulnerable_works() { System::assert_has_event(RuntimeEvent::CollatorSelection( crate::Event::InvulnerableAdded { account_id: 3 }, )); - assert!(CollatorSelection::invulnerables().to_vec().contains(&3)); + assert!(Invulnerables::::get().to_vec().contains(&3)); assert_eq!(Balances::free_balance(3), 100); - assert_eq!(>::get().iter().count(), 1); + assert_eq!(CandidateList::::get().iter().count(), 1); assert_ok!(CollatorSelection::add_invulnerable( RuntimeOrigin::signed(RootAccount::get()), @@ -239,10 +242,10 @@ fn candidate_to_invulnerable_works() { System::assert_has_event(RuntimeEvent::CollatorSelection( crate::Event::InvulnerableAdded { account_id: 4 }, )); - assert!(CollatorSelection::invulnerables().to_vec().contains(&4)); + assert!(Invulnerables::::get().to_vec().contains(&4)); assert_eq!(Balances::free_balance(4), 100); - assert_eq!(>::get().iter().count(), 0); + assert_eq!(CandidateList::::get().iter().count(), 0); }); } @@ -250,14 +253,14 @@ fn candidate_to_invulnerable_works() { fn set_desired_candidates_works() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); + assert_eq!(DesiredCandidates::::get(), 2); // can set assert_ok!(CollatorSelection::set_desired_candidates( RuntimeOrigin::signed(RootAccount::get()), 7 )); - assert_eq!(CollatorSelection::desired_candidates(), 7); + assert_eq!(DesiredCandidates::::get(), 7); // rejects bad origin assert_noop!( @@ -271,16 +274,16 @@ fn set_desired_candidates_works() { fn set_candidacy_bond_empty_candidate_list() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::candidacy_bond(), 10); - assert!(>::get().is_empty()); + assert_eq!(CandidacyBond::::get(), 10); + assert!(CandidateList::::get().is_empty()); // can decrease without candidates assert_ok!(CollatorSelection::set_candidacy_bond( RuntimeOrigin::signed(RootAccount::get()), 7 )); - assert_eq!(CollatorSelection::candidacy_bond(), 7); - assert!(>::get().is_empty()); + assert_eq!(CandidacyBond::::get(), 7); + assert!(CandidateList::::get().is_empty()); // rejects bad origin. assert_noop!(CollatorSelection::set_candidacy_bond(RuntimeOrigin::signed(1), 8), BadOrigin); @@ -290,8 +293,8 @@ fn set_candidacy_bond_empty_candidate_list() { RuntimeOrigin::signed(RootAccount::get()), 20 )); - assert!(>::get().is_empty()); - assert_eq!(CollatorSelection::candidacy_bond(), 20); + assert!(CandidateList::::get().is_empty()); + assert_eq!(CandidacyBond::::get(), 20); }); } @@ -299,36 +302,36 @@ fn set_candidacy_bond_empty_candidate_list() { fn set_candidacy_bond_with_one_candidate() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::candidacy_bond(), 10); - assert!(>::get().is_empty()); + assert_eq!(CandidacyBond::::get(), 10); + assert!(CandidateList::::get().is_empty()); let candidate_3 = CandidateInfo { who: 3, deposit: 10 }; assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3))); - assert_eq!(>::get(), vec![candidate_3.clone()]); + assert_eq!(CandidateList::::get(), vec![candidate_3.clone()]); // can decrease with one candidate assert_ok!(CollatorSelection::set_candidacy_bond( RuntimeOrigin::signed(RootAccount::get()), 7 )); - assert_eq!(CollatorSelection::candidacy_bond(), 7); - assert_eq!(>::get(), vec![candidate_3.clone()]); + assert_eq!(CandidacyBond::::get(), 7); + assert_eq!(CandidateList::::get(), vec![candidate_3.clone()]); // can increase up to initial deposit assert_ok!(CollatorSelection::set_candidacy_bond( RuntimeOrigin::signed(RootAccount::get()), 10 )); - assert_eq!(CollatorSelection::candidacy_bond(), 10); - assert_eq!(>::get(), vec![candidate_3.clone()]); + assert_eq!(CandidacyBond::::get(), 10); + assert_eq!(CandidateList::::get(), vec![candidate_3.clone()]); // can increase past initial deposit, should kick existing candidate assert_ok!(CollatorSelection::set_candidacy_bond( RuntimeOrigin::signed(RootAccount::get()), 20 )); - assert!(>::get().is_empty()); + assert!(CandidateList::::get().is_empty()); }); } @@ -336,8 +339,8 @@ fn set_candidacy_bond_with_one_candidate() { fn set_candidacy_bond_with_many_candidates_same_deposit() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::candidacy_bond(), 10); - assert!(>::get().is_empty()); + assert_eq!(CandidacyBond::::get(), 10); + assert!(CandidateList::::get().is_empty()); let candidate_3 = CandidateInfo { who: 3, deposit: 10 }; let candidate_4 = CandidateInfo { who: 4, deposit: 10 }; @@ -347,7 +350,7 @@ fn set_candidacy_bond_with_many_candidates_same_deposit() { assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4))); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(5))); assert_eq!( - >::get(), + CandidateList::::get(), vec![candidate_5.clone(), candidate_4.clone(), candidate_3.clone()] ); @@ -356,9 +359,9 @@ fn set_candidacy_bond_with_many_candidates_same_deposit() { RuntimeOrigin::signed(RootAccount::get()), 7 )); - assert_eq!(CollatorSelection::candidacy_bond(), 7); + assert_eq!(CandidacyBond::::get(), 7); assert_eq!( - >::get(), + CandidateList::::get(), vec![candidate_5.clone(), candidate_4.clone(), candidate_3.clone()] ); @@ -367,9 +370,9 @@ fn set_candidacy_bond_with_many_candidates_same_deposit() { RuntimeOrigin::signed(RootAccount::get()), 10 )); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(CandidacyBond::::get(), 10); assert_eq!( - >::get(), + CandidateList::::get(), vec![candidate_5.clone(), candidate_4.clone(), candidate_3.clone()] ); @@ -378,7 +381,7 @@ fn set_candidacy_bond_with_many_candidates_same_deposit() { RuntimeOrigin::signed(RootAccount::get()), 20 )); - assert!(>::get().is_empty()); + assert!(CandidateList::::get().is_empty()); }); } @@ -386,8 +389,8 @@ fn set_candidacy_bond_with_many_candidates_same_deposit() { fn set_candidacy_bond_with_many_candidates_different_deposits() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::candidacy_bond(), 10); - assert!(>::get().is_empty()); + assert_eq!(CandidacyBond::::get(), 10); + assert!(CandidateList::::get().is_empty()); let candidate_3 = CandidateInfo { who: 3, deposit: 10 }; let candidate_4 = CandidateInfo { who: 4, deposit: 20 }; @@ -399,7 +402,7 @@ fn set_candidacy_bond_with_many_candidates_different_deposits() { assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(5), 30)); assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(4), 20)); assert_eq!( - >::get(), + CandidateList::::get(), vec![candidate_3.clone(), candidate_4.clone(), candidate_5.clone()] ); @@ -408,9 +411,9 @@ fn set_candidacy_bond_with_many_candidates_different_deposits() { RuntimeOrigin::signed(RootAccount::get()), 7 )); - assert_eq!(CollatorSelection::candidacy_bond(), 7); + assert_eq!(CandidacyBond::::get(), 7); assert_eq!( - >::get(), + CandidateList::::get(), vec![candidate_3.clone(), candidate_4.clone(), candidate_5.clone()] ); // can increase up to initial deposit @@ -418,9 +421,9 @@ fn set_candidacy_bond_with_many_candidates_different_deposits() { RuntimeOrigin::signed(RootAccount::get()), 10 )); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(CandidacyBond::::get(), 10); assert_eq!( - >::get(), + CandidateList::::get(), vec![candidate_3.clone(), candidate_4.clone(), candidate_5.clone()] ); @@ -429,27 +432,24 @@ fn set_candidacy_bond_with_many_candidates_different_deposits() { RuntimeOrigin::signed(RootAccount::get()), 20 )); - assert_eq!(CollatorSelection::candidacy_bond(), 20); - assert_eq!( - >::get(), - vec![candidate_4.clone(), candidate_5.clone()] - ); + assert_eq!(CandidacyBond::::get(), 20); + assert_eq!(CandidateList::::get(), vec![candidate_4.clone(), candidate_5.clone()]); // can increase past 4's deposit, should kick 4 assert_ok!(CollatorSelection::set_candidacy_bond( RuntimeOrigin::signed(RootAccount::get()), 25 )); - assert_eq!(CollatorSelection::candidacy_bond(), 25); - assert_eq!(>::get(), vec![candidate_5.clone()]); + assert_eq!(CandidacyBond::::get(), 25); + assert_eq!(CandidateList::::get(), vec![candidate_5.clone()]); // lowering the minimum deposit should have no effect assert_ok!(CollatorSelection::set_candidacy_bond( RuntimeOrigin::signed(RootAccount::get()), 5 )); - assert_eq!(CollatorSelection::candidacy_bond(), 5); - assert_eq!(>::get(), vec![candidate_5.clone()]); + assert_eq!(CandidacyBond::::get(), 5); + assert_eq!(CandidateList::::get(), vec![candidate_5.clone()]); // add 3 and 4 back but with higher deposits than minimum assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3))); @@ -457,7 +457,7 @@ fn set_candidacy_bond_with_many_candidates_different_deposits() { assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(3), 10)); assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(4), 20)); assert_eq!( - >::get(), + CandidateList::::get(), vec![candidate_3.clone(), candidate_4.clone(), candidate_5.clone()] ); @@ -467,8 +467,8 @@ fn set_candidacy_bond_with_many_candidates_different_deposits() { RuntimeOrigin::signed(RootAccount::get()), 40 )); - assert_eq!(CollatorSelection::candidacy_bond(), 40); - assert!(>::get().is_empty()); + assert_eq!(CandidacyBond::::get(), 40); + assert!(CandidateList::::get().is_empty()); }); } @@ -500,8 +500,8 @@ fn cannot_register_candidate_if_too_many() { #[test] fn cannot_unregister_candidate_if_too_few() { new_test_ext().execute_with(|| { - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); assert_ok!(CollatorSelection::remove_invulnerable( RuntimeOrigin::signed(RootAccount::get()), 1 @@ -532,7 +532,7 @@ fn cannot_unregister_candidate_if_too_few() { #[test] fn cannot_register_as_candidate_if_invulnerable() { new_test_ext().execute_with(|| { - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // can't 1 because it is invulnerable. assert_noop!( @@ -561,10 +561,10 @@ fn cannot_register_dupe_candidate() { // tuple of (id, deposit). let addition = CandidateInfo { who: 3, deposit: 10 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![addition] ); - assert_eq!(CollatorSelection::last_authored_block(3), 10); + assert_eq!(LastAuthoredBlock::::get(3), 10); assert_eq!(Balances::free_balance(3), 90); // but no more @@ -596,11 +596,11 @@ fn cannot_register_as_candidate_if_poor() { fn register_as_candidate_works() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // take two endowed, non-invulnerables accounts. assert_eq!(Balances::free_balance(3), 100); @@ -612,14 +612,14 @@ fn register_as_candidate_works() { assert_eq!(Balances::free_balance(3), 90); assert_eq!(Balances::free_balance(4), 90); - assert_eq!(>::get().iter().count(), 2); + assert_eq!(CandidateList::::get().iter().count(), 2); }); } #[test] fn cannot_take_candidate_slot_if_invulnerable() { new_test_ext().execute_with(|| { - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // can't 1 because it is invulnerable. assert_noop!( @@ -649,11 +649,10 @@ fn cannot_take_candidate_slot_if_duplicate() { // tuple of (id, deposit). let candidate_3 = CandidateInfo { who: 3, deposit: 10 }; let candidate_4 = CandidateInfo { who: 4, deposit: 10 }; - let actual_candidates = - >::get().iter().cloned().collect::>(); + let actual_candidates = CandidateList::::get().iter().cloned().collect::>(); assert_eq!(actual_candidates, vec![candidate_4, candidate_3]); - assert_eq!(CollatorSelection::last_authored_block(3), 10); - assert_eq!(CollatorSelection::last_authored_block(4), 10); + assert_eq!(LastAuthoredBlock::::get(3), 10); + assert_eq!(LastAuthoredBlock::::get(4), 10); assert_eq!(Balances::free_balance(3), 90); // but no more @@ -672,10 +671,10 @@ fn cannot_take_candidate_slot_if_target_invalid() { // tuple of (id, deposit). let candidate_3 = CandidateInfo { who: 3, deposit: 10 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![candidate_3] ); - assert_eq!(CollatorSelection::last_authored_block(3), 10); + assert_eq!(LastAuthoredBlock::::get(3), 10); assert_eq!(Balances::free_balance(3), 90); assert_eq!(Balances::free_balance(4), 100); @@ -744,11 +743,11 @@ fn cannot_take_candidate_slot_if_deposit_less_than_target() { fn take_candidate_slot_works() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // take two endowed, non-invulnerables accounts. assert_eq!(Balances::free_balance(3), 100); @@ -763,7 +762,7 @@ fn take_candidate_slot_works() { assert_eq!(Balances::free_balance(4), 90); assert_eq!(Balances::free_balance(5), 90); - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); Balances::make_free_balance_be(&6, 100); let key = MockSessionKeys { aura: UintAuthorityId(6) }; @@ -785,10 +784,10 @@ fn take_candidate_slot_works() { let candidate_6 = CandidateInfo { who: 6, deposit: 50 }; let candidate_5 = CandidateInfo { who: 5, deposit: 10 }; let mut actual_candidates = - >::get().iter().cloned().collect::>(); + CandidateList::::get().iter().cloned().collect::>(); actual_candidates.sort_by(|info_1, info_2| info_1.deposit.cmp(&info_2.deposit)); assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![candidate_5, candidate_3, candidate_6] ); }); @@ -798,11 +797,11 @@ fn take_candidate_slot_works() { fn increase_candidacy_bond_non_candidate_account() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3))); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4))); @@ -818,11 +817,11 @@ fn increase_candidacy_bond_non_candidate_account() { fn increase_candidacy_bond_insufficient_balance() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // take two endowed, non-invulnerables accounts. assert_eq!(Balances::free_balance(3), 100); @@ -850,11 +849,11 @@ fn increase_candidacy_bond_insufficient_balance() { fn increase_candidacy_bond_works() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // take three endowed, non-invulnerables accounts. assert_eq!(Balances::free_balance(3), 100); @@ -873,7 +872,7 @@ fn increase_candidacy_bond_works() { assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(4), 30)); assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(5), 40)); - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); assert_eq!(Balances::free_balance(3), 80); assert_eq!(Balances::free_balance(4), 70); assert_eq!(Balances::free_balance(5), 60); @@ -881,7 +880,7 @@ fn increase_candidacy_bond_works() { assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(3), 40)); assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(4), 60)); - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); assert_eq!(Balances::free_balance(3), 60); assert_eq!(Balances::free_balance(4), 40); assert_eq!(Balances::free_balance(5), 60); @@ -892,11 +891,11 @@ fn increase_candidacy_bond_works() { fn decrease_candidacy_bond_non_candidate_account() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3))); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4))); @@ -914,11 +913,11 @@ fn decrease_candidacy_bond_non_candidate_account() { fn decrease_candidacy_bond_insufficient_funds() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // take two endowed, non-invulnerables accounts. assert_eq!(Balances::free_balance(3), 100); @@ -961,7 +960,7 @@ fn decrease_candidacy_bond_insufficient_funds() { #[test] fn decrease_candidacy_bond_occupying_top_slot() { new_test_ext().execute_with(|| { - assert_eq!(CollatorSelection::desired_candidates(), 2); + assert_eq!(DesiredCandidates::::get(), 2); // Register 3 candidates. assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3))); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4))); @@ -976,7 +975,7 @@ fn decrease_candidacy_bond_occupying_top_slot() { let candidate_4 = CandidateInfo { who: 4, deposit: 30 }; let candidate_5 = CandidateInfo { who: 5, deposit: 60 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![candidate_4, candidate_3, candidate_5] ); @@ -1000,7 +999,7 @@ fn decrease_candidacy_bond_occupying_top_slot() { let candidate_4 = CandidateInfo { who: 4, deposit: 35 }; let candidate_5 = CandidateInfo { who: 5, deposit: 60 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![candidate_3, candidate_4, candidate_5] ); @@ -1023,11 +1022,11 @@ fn decrease_candidacy_bond_occupying_top_slot() { fn decrease_candidacy_bond_works() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // take three endowed, non-invulnerables accounts. assert_eq!(Balances::free_balance(3), 100); @@ -1046,14 +1045,14 @@ fn decrease_candidacy_bond_works() { assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(4), 30)); assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(5), 40)); - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); assert_eq!(Balances::free_balance(3), 80); assert_eq!(Balances::free_balance(4), 70); assert_eq!(Balances::free_balance(5), 60); assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(3), 10)); - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); assert_eq!(Balances::free_balance(3), 90); assert_eq!(Balances::free_balance(4), 70); assert_eq!(Balances::free_balance(5), 60); @@ -1064,11 +1063,11 @@ fn decrease_candidacy_bond_works() { fn update_candidacy_bond_with_identical_amount() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // take three endowed, non-invulnerables accounts. assert_eq!(Balances::free_balance(3), 100); @@ -1087,7 +1086,7 @@ fn update_candidacy_bond_with_identical_amount() { assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(4), 30)); assert_ok!(CollatorSelection::update_bond(RuntimeOrigin::signed(5), 40)); - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); assert_eq!(Balances::free_balance(3), 80); assert_eq!(Balances::free_balance(4), 70); assert_eq!(Balances::free_balance(5), 60); @@ -1104,11 +1103,11 @@ fn update_candidacy_bond_with_identical_amount() { fn candidate_list_works() { new_test_ext().execute_with(|| { // given - assert_eq!(CollatorSelection::desired_candidates(), 2); - assert_eq!(CollatorSelection::candidacy_bond(), 10); + assert_eq!(DesiredCandidates::::get(), 2); + assert_eq!(CandidacyBond::::get(), 10); - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); // take three endowed, non-invulnerables accounts. assert_eq!(Balances::free_balance(3), 100); @@ -1131,7 +1130,7 @@ fn candidate_list_works() { let candidate_4 = CandidateInfo { who: 4, deposit: 25 }; let candidate_5 = CandidateInfo { who: 5, deposit: 10 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![candidate_5, candidate_4, candidate_3] ); }); @@ -1157,7 +1156,7 @@ fn leave_intent() { // bond is returned assert_ok!(CollatorSelection::leave_intent(RuntimeOrigin::signed(3))); assert_eq!(Balances::free_balance(3), 100); - assert_eq!(CollatorSelection::last_authored_block(3), 0); + assert_eq!(LastAuthoredBlock::::get(3), 0); }); } @@ -1177,10 +1176,10 @@ fn authorship_event_handler() { let collator = CandidateInfo { who: 4, deposit: 10 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![collator] ); - assert_eq!(CollatorSelection::last_authored_block(4), 0); + assert_eq!(LastAuthoredBlock::::get(4), 0); // half of the pot goes to the collator who's the author (4 in tests). assert_eq!(Balances::free_balance(4), 140); @@ -1206,10 +1205,10 @@ fn fees_edgecases() { let collator = CandidateInfo { who: 4, deposit: 10 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![collator] ); - assert_eq!(CollatorSelection::last_authored_block(4), 0); + assert_eq!(LastAuthoredBlock::::get(4), 0); // Nothing received assert_eq!(Balances::free_balance(4), 90); // all fee stays @@ -1236,7 +1235,7 @@ fn session_management_single_candidate() { // session won't see this. assert_eq!(SessionHandlerCollators::get(), vec![1, 2]); // but we have a new candidate. - assert_eq!(>::get().iter().count(), 1); + assert_eq!(CandidateList::::get().iter().count(), 1); initialize_to_block(10); assert_eq!(SessionChangeBlock::get(), 10); @@ -1274,7 +1273,7 @@ fn session_management_max_candidates() { // session won't see this. assert_eq!(SessionHandlerCollators::get(), vec![1, 2]); // but we have a new candidate. - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); initialize_to_block(10); assert_eq!(SessionChangeBlock::get(), 10); @@ -1313,7 +1312,7 @@ fn session_management_increase_bid_with_list_update() { // session won't see this. assert_eq!(SessionHandlerCollators::get(), vec![1, 2]); // but we have a new candidate. - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); initialize_to_block(10); assert_eq!(SessionChangeBlock::get(), 10); @@ -1352,7 +1351,7 @@ fn session_management_candidate_list_eager_sort() { // session won't see this. assert_eq!(SessionHandlerCollators::get(), vec![1, 2]); // but we have a new candidate. - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); initialize_to_block(10); assert_eq!(SessionChangeBlock::get(), 10); @@ -1399,7 +1398,7 @@ fn session_management_reciprocal_outbidding() { // session won't see this. assert_eq!(SessionHandlerCollators::get(), vec![1, 2]); // but we have a new candidate. - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); initialize_to_block(10); assert_eq!(SessionChangeBlock::get(), 10); @@ -1451,7 +1450,7 @@ fn session_management_decrease_bid_after_auction() { // session won't see this. assert_eq!(SessionHandlerCollators::get(), vec![1, 2]); // but we have a new candidate. - assert_eq!(>::get().iter().count(), 3); + assert_eq!(CandidateList::::get().iter().count(), 3); initialize_to_block(10); assert_eq!(SessionChangeBlock::get(), 10); @@ -1476,20 +1475,20 @@ fn kick_mechanism() { assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3))); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4))); initialize_to_block(10); - assert_eq!(>::get().iter().count(), 2); + assert_eq!(CandidateList::::get().iter().count(), 2); initialize_to_block(20); assert_eq!(SessionChangeBlock::get(), 20); // 4 authored this block, gets to stay 3 was kicked - assert_eq!(>::get().iter().count(), 1); + assert_eq!(CandidateList::::get().iter().count(), 1); // 3 will be kicked after 1 session delay assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]); // tuple of (id, deposit). let collator = CandidateInfo { who: 4, deposit: 10 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![collator] ); - assert_eq!(CollatorSelection::last_authored_block(4), 20); + assert_eq!(LastAuthoredBlock::::get(4), 20); initialize_to_block(30); // 3 gets kicked after 1 session delay assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]); @@ -1503,8 +1502,8 @@ fn should_not_kick_mechanism_too_few() { new_test_ext().execute_with(|| { // remove the invulnerables and add new collators 3 and 5 - assert_eq!(>::get().iter().count(), 0); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]); + assert_eq!(CandidateList::::get().iter().count(), 0); + assert_eq!(Invulnerables::::get(), vec![1, 2]); assert_ok!(CollatorSelection::remove_invulnerable( RuntimeOrigin::signed(RootAccount::get()), 1 @@ -1517,21 +1516,21 @@ fn should_not_kick_mechanism_too_few() { )); initialize_to_block(10); - assert_eq!(>::get().iter().count(), 2); + assert_eq!(CandidateList::::get().iter().count(), 2); initialize_to_block(20); assert_eq!(SessionChangeBlock::get(), 20); // 4 authored this block, 3 is kicked, 5 stays because of too few collators - assert_eq!(>::get().iter().count(), 1); + assert_eq!(CandidateList::::get().iter().count(), 1); // 3 will be kicked after 1 session delay assert_eq!(SessionHandlerCollators::get(), vec![3, 5]); // tuple of (id, deposit). let collator = CandidateInfo { who: 3, deposit: 10 }; assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![collator] ); - assert_eq!(CollatorSelection::last_authored_block(4), 20); + assert_eq!(LastAuthoredBlock::::get(4), 20); initialize_to_block(30); // 3 gets kicked after 1 session delay @@ -1544,7 +1543,7 @@ fn should_not_kick_mechanism_too_few() { #[test] fn should_kick_invulnerables_from_candidates_on_session_change() { new_test_ext().execute_with(|| { - assert_eq!(>::get().iter().count(), 0); + assert_eq!(CandidateList::::get().iter().count(), 0); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3))); assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4))); assert_eq!(Balances::free_balance(3), 90); @@ -1558,20 +1557,19 @@ fn should_kick_invulnerables_from_candidates_on_session_change() { let collator_3 = CandidateInfo { who: 3, deposit: 10 }; let collator_4 = CandidateInfo { who: 4, deposit: 10 }; - let actual_candidates = - >::get().iter().cloned().collect::>(); + let actual_candidates = CandidateList::::get().iter().cloned().collect::>(); assert_eq!(actual_candidates, vec![collator_4.clone(), collator_3]); - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2, 3]); + assert_eq!(Invulnerables::::get(), vec![1, 2, 3]); // session change initialize_to_block(10); // 3 is removed from candidates assert_eq!( - >::get().iter().cloned().collect::>(), + CandidateList::::get().iter().cloned().collect::>(), vec![collator_4] ); // but not from invulnerables - assert_eq!(CollatorSelection::invulnerables(), vec![1, 2, 3]); + assert_eq!(Invulnerables::::get(), vec![1, 2, 3]); // and it got its deposit back assert_eq!(Balances::free_balance(3), 100); }); diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index 81965a2a313..1c01ef33c7e 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -267,7 +267,7 @@ pub mod pallet { LastRelayChainBlockNumber::::put(vfp.relay_parent_number); - let host_config = match Self::host_configuration() { + let host_config = match HostConfiguration::::get() { Some(ok) => ok, None => { debug_assert!( @@ -281,7 +281,7 @@ pub mod pallet { // Before updating the relevant messaging state, we need to extract // the total bandwidth limits for the purpose of updating the unincluded // segment. - let total_bandwidth_out = match Self::relevant_messaging_state() { + let total_bandwidth_out = match RelevantMessagingState::::get() { Some(s) => OutboundBandwidthLimits::from_relay_chain_state(&s), None => { debug_assert!( @@ -298,7 +298,8 @@ pub mod pallet { Self::adjust_egress_bandwidth_limits(); let (ump_msg_count, ump_total_bytes) = >::mutate(|up| { - let (available_capacity, available_size) = match Self::relevant_messaging_state() { + let (available_capacity, available_size) = match RelevantMessagingState::::get() + { Some(limits) => ( limits.relay_dispatch_queue_remaining_capacity.remaining_count, limits.relay_dispatch_queue_remaining_capacity.remaining_size, @@ -476,7 +477,7 @@ pub mod pallet { // than the announced, we would waste some of weight. In the case the actual value is // greater than the announced, we will miss opportunity to send a couple of messages. weight += T::DbWeight::get().reads_writes(1, 1); - let hrmp_max_message_num_per_candidate = Self::host_configuration() + let hrmp_max_message_num_per_candidate = HostConfiguration::::get() .map(|cfg| cfg.hrmp_max_message_num_per_candidate) .unwrap_or(0); >::put(hrmp_max_message_num_per_candidate); @@ -764,7 +765,6 @@ pub mod pallet { /// [`:code`][sp_core::storage::well_known_keys::CODE] which will result the next block process /// with the new validation code. This concludes the upgrade process. #[pallet::storage] - #[pallet::getter(fn new_validation_function)] pub(super) type PendingValidationCode = StorageValue<_, Vec, ValueQuery>; /// Validation code that is set by the parachain and is to be communicated to collator and @@ -779,7 +779,6 @@ pub mod pallet { /// This value is expected to be set only once per block and it's never stored /// in the trie. #[pallet::storage] - #[pallet::getter(fn validation_data)] pub(super) type ValidationData = StorageValue<_, PersistedValidationData>; /// Were the validation data set to notify the relay chain? @@ -820,7 +819,6 @@ pub mod pallet { /// /// This data is also absent from the genesis. #[pallet::storage] - #[pallet::getter(fn relay_state_proof)] pub(super) type RelayStateProof = StorageValue<_, sp_trie::StorageProof>; /// The snapshot of some state related to messaging relevant to the current parachain as per @@ -831,7 +829,6 @@ pub mod pallet { /// /// This data is also absent from the genesis. #[pallet::storage] - #[pallet::getter(fn relevant_messaging_state)] pub(super) type RelevantMessagingState = StorageValue<_, MessagingStateSnapshot>; /// The parachain host configuration that was obtained from the relay parent. @@ -842,7 +839,6 @@ pub mod pallet { /// This data is also absent from the genesis. #[pallet::storage] #[pallet::disable_try_decode_storage] - #[pallet::getter(fn host_configuration)] pub(super) type HostConfiguration = StorageValue<_, AbridgedHostConfiguration>; /// The last downward message queue chain head we have observed. @@ -1041,7 +1037,7 @@ impl GetChannelInfo for Pallet { // // Here it a similar case, with the difference that the realization that the channel is // closed came the same block. - let channels = match Self::relevant_messaging_state() { + let channels = match RelevantMessagingState::::get() { None => { log::warn!("calling `get_channel_status` with no RelevantMessagingState?!"); return ChannelStatus::Closed @@ -1069,7 +1065,7 @@ impl GetChannelInfo for Pallet { } fn get_channel_info(id: ParaId) -> Option { - let channels = Self::relevant_messaging_state()?.egress_channels; + let channels = RelevantMessagingState::::get()?.egress_channels; let index = channels.binary_search_by_key(&id, |item| item.0).ok()?; let info = ChannelInfo { max_capacity: channels[index].1.max_capacity, @@ -1406,7 +1402,7 @@ impl Pallet { ensure!(>::get().is_none(), Error::::ProhibitedByPolkadot); ensure!(!>::exists(), Error::::OverlappingUpgrades); - let cfg = Self::host_configuration().ok_or(Error::::HostConfigurationNotAvailable)?; + let cfg = HostConfiguration::::get().ok_or(Error::::HostConfigurationNotAvailable)?; ensure!(validation_function.len() <= cfg.max_code_size as usize, Error::::TooBig); // When a code upgrade is scheduled, it has to be applied in two @@ -1562,7 +1558,7 @@ impl Pallet { // may change so that the message is no longer valid. // // However, changing this setting is expected to be rare. - if let Some(cfg) = Self::host_configuration() { + if let Some(cfg) = HostConfiguration::::get() { if message_len > cfg.max_upward_message_size as usize { return Err(MessageSendError::TooBig) } @@ -1718,14 +1714,14 @@ impl BlockNumberProvider for RelaychainDataProvider { type BlockNumber = relay_chain::BlockNumber; fn current_block_number() -> relay_chain::BlockNumber { - Pallet::::validation_data() + ValidationData::::get() .map(|d| d.relay_parent_number) .unwrap_or_else(|| Pallet::::last_relay_block_number()) } #[cfg(feature = "runtime-benchmarks")] fn set_block_number(block: Self::BlockNumber) { - let mut validation_data = Pallet::::validation_data().unwrap_or_else(|| + let mut validation_data = ValidationData::::get().unwrap_or_else(|| // PersistedValidationData does not impl default in non-std PersistedValidationData { parent_head: vec![].into(), @@ -1740,7 +1736,7 @@ impl BlockNumberProvider for RelaychainDataProvider { impl RelaychainStateProvider for RelaychainDataProvider { fn current_relay_chain_state() -> RelayChainState { - Pallet::::validation_data() + ValidationData::::get() .map(|d| RelayChainState { number: d.relay_parent_number, state_root: d.relay_parent_storage_root, @@ -1750,7 +1746,7 @@ impl RelaychainStateProvider for RelaychainDataProvider { #[cfg(feature = "runtime-benchmarks")] fn set_current_relay_chain_state(state: RelayChainState) { - let mut validation_data = Pallet::::validation_data().unwrap_or_else(|| + let mut validation_data = ValidationData::::get().unwrap_or_else(|| // PersistedValidationData does not impl default in non-std PersistedValidationData { parent_head: vec![].into(), diff --git a/cumulus/parachains/pallets/parachain-info/src/lib.rs b/cumulus/parachains/pallets/parachain-info/src/lib.rs index c17a6d5e146..a4ef448a6b6 100644 --- a/cumulus/parachains/pallets/parachain-info/src/lib.rs +++ b/cumulus/parachains/pallets/parachain-info/src/lib.rs @@ -54,7 +54,7 @@ pub mod pallet { #[pallet::genesis_build] impl BuildGenesisConfig for GenesisConfig { fn build(&self) { - >::put(self.parachain_id); + ParachainId::::put(self.parachain_id); } } @@ -64,13 +64,18 @@ pub mod pallet { } #[pallet::storage] - #[pallet::getter(fn parachain_id)] pub(super) type ParachainId = StorageValue<_, ParaId, ValueQuery, DefaultForParachainId>; impl Get for Pallet { fn get() -> ParaId { - Self::parachain_id() + ParachainId::::get() + } + } + + impl Pallet { + pub fn parachain_id() -> ParaId { + ParachainId::::get() } } } diff --git a/prdoc/pr_3471.prdoc b/prdoc/pr_3471.prdoc new file mode 100644 index 00000000000..0c16587fc90 --- /dev/null +++ b/prdoc/pr_3471.prdoc @@ -0,0 +1,33 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: removed `pallet::getter` from cumulus pallets + +doc: + - audience: Runtime Dev + description: | + This PR removes all the `pallet::getter` usages from cumulus pallets, and updates depdendant runtimes accordingly. + The ParaId can be retrieved using `>::get()`. + For other storage items, the syntax `StorageItem::::get()` should be used instead. + +crates: + - name: cumulus-pallet-aura-ext + - name: pallet-collator-selection + - name: cumulus-pallet-parachain-system + - name: staging-parachain-info + - name: parachain-template-runtime + - name: asset-hub-rococo-runtime + - name: asset-hub-westend-runtime + - name: bridge-hub-rococo-runtime + - name: bridge-hub-westend-runtime + - name: collectives-westend-runtime + - name: contracts-rococo-runtime + - name: coretime-rococo-runtime + - name: coretime-westend-runtime + - name: glutton-westend-runtime + - name: people-rococo-runtime + - name: people-westend-runtime + - name: shell-runtime + - name: penpal-runtime + - name: rococo-parachain-runtime + -- GitLab From e2ead8887681d2236cae4a0f05b05e4cb5bf63a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 04:34:17 +0100 Subject: [PATCH 137/188] Bump the known_good_semver group with 2 updates (#3726) Bumps the known_good_semver group with 2 updates: [serde_yaml](https://github.com/dtolnay/serde-yaml) and [syn](https://github.com/dtolnay/syn). Updates `serde_yaml` from 0.9.32 to 0.9.33

Release notes

Sourced from serde_yaml's releases.

0.9.33

Commits
  • f4c9ed9 Release 0.9.33
  • b4edaee Pull in yaml_parser_fetch_more_tokens fix from libyaml
  • 8a5542c Resolve non_local_definitions warning in test
  • See full diff in compare view

Updates `syn` from 2.0.52 to 2.0.53
Release notes

Sourced from syn's releases.

2.0.53

  • Implement Copy, Clone, and ToTokens for syn::parse::Nothing (#1597)
Commits
  • 32dcf8d Release 2.0.53
  • fd1f2aa Merge pull request #1597 from dtolnay/copyprintnothing
  • 4f6c052 Implement ToTokens for syn::parse::Nothing
  • 3f37543 Implement Copy for syn::parse::Nothing
  • 36a4122 Update test suite to nightly-2024-03-16
  • bd93106 Revert "Temporarily disable nightly testing due to libLLVM link issue"
  • 06166a7 Update test suite to nightly-2024-03-09
  • ed545e7 Work around doc_markdown lint in test_precedence
  • 7aef1ed Temporarily disable nightly testing due to libLLVM link issue
  • 556b10b Update test suite to nightly-2024-03-06
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 132 ++++++++++++++++++++++++++--------------------------- Cargo.toml | 2 +- 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d641f554431..5c0066e9728 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,7 +191,7 @@ checksum = "c0391754c09fab4eae3404d19d0d297aa1c670c1775ab51d8a5312afeca23157" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -206,7 +206,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "syn-solidity", "tiny-keccak", ] @@ -347,7 +347,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1228,7 +1228,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1245,7 +1245,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -1427,7 +1427,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -2674,7 +2674,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -3895,7 +3895,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4410,7 +4410,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4450,7 +4450,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4467,7 +4467,7 @@ checksum = "50c49547d73ba8dcfd4ad7325d64c6d5391ff4224d498fc39a6f3f49825a530d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4675,7 +4675,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -4745,7 +4745,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.52", + "syn 2.0.53", "termcolor", "walkdir", ] @@ -4762,7 +4762,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.52", + "syn 2.0.53", "termcolor", "toml 0.8.8", "walkdir", @@ -4990,7 +4990,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5001,7 +5001,7 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5191,7 +5191,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5578,7 +5578,7 @@ dependencies = [ "quote", "scale-info", "sp-arithmetic", - "syn 2.0.52", + "syn 2.0.53", "trybuild", ] @@ -5735,7 +5735,7 @@ dependencies = [ "quote", "regex", "sp-crypto-hashing", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5746,7 +5746,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5755,7 +5755,7 @@ version = "11.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -5988,7 +5988,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7933,7 +7933,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7947,7 +7947,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7958,7 +7958,7 @@ checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -7969,7 +7969,7 @@ checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -9630,7 +9630,7 @@ version = "18.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -10858,7 +10858,7 @@ dependencies = [ "proc-macro2", "quote", "sp-runtime", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -11953,7 +11953,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -11994,7 +11994,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -13891,7 +13891,7 @@ dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -13901,7 +13901,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" dependencies = [ "polkavm-derive-impl", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -14097,7 +14097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" dependencies = [ "proc-macro2", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -14188,7 +14188,7 @@ checksum = "9b698b0b09d40e9b7c1a47b132d66a8b54bcd20583d9b6d06e4535e383b4405c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -14260,7 +14260,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -14360,7 +14360,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -14703,7 +14703,7 @@ checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -15194,7 +15194,7 @@ dependencies = [ "regex", "relative-path", "rustc_version 0.4.0", - "syn 2.0.52", + "syn 2.0.53", "unicode-ident", ] @@ -15648,7 +15648,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -16930,7 +16930,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -17332,7 +17332,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -17389,9 +17389,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.32" +version = "0.9.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" dependencies = [ "indexmap 2.2.3", "itoa", @@ -17432,7 +17432,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -18340,7 +18340,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -18723,7 +18723,7 @@ version = "0.0.0" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -18741,7 +18741,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk#82912acb33a9030c0ef3bf5 dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -18750,7 +18750,7 @@ version = "14.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -19018,7 +19018,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -19030,7 +19030,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -19292,7 +19292,7 @@ dependencies = [ "proc-macro2", "quote", "sp-version", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -19735,7 +19735,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -20132,9 +20132,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -20150,7 +20150,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -20415,7 +20415,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -20576,7 +20576,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -20783,7 +20783,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -20825,7 +20825,7 @@ dependencies = [ "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -21180,9 +21180,9 @@ dependencies = [ [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "unsigned-varint" @@ -21390,7 +21390,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "wasm-bindgen-shared", ] @@ -21424,7 +21424,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -22441,7 +22441,7 @@ dependencies = [ "proc-macro2", "quote", "staging-xcm", - "syn 2.0.52", + "syn 2.0.53", "trybuild", ] @@ -22563,7 +22563,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] @@ -22583,7 +22583,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.53", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3acb6c1d055..01d6ef8e87b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -554,7 +554,7 @@ serde-big-array = { version = "0.3.2" } serde_derive = { version = "1.0.117" } serde_json = { version = "1.0.114", default-features = false } serde_yaml = { version = "0.9" } -syn = { version = "2.0.52" } +syn = { version = "2.0.53" } thiserror = { version = "1.0.48" } [profile.release] -- GitLab From 8b3bf39ab85ff7146e06e7c8236475bfa4e3bf39 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Rios <54085674+JuaniRios@users.noreply.github.com> Date: Tue, 19 Mar 2024 09:12:39 +0100 Subject: [PATCH 138/188] Add HRMP notification handlers to the xcm-executor (#3696) Currently the xcm-executor returns an `Unimplemented` error if it receives any HRMP-related instruction. What I propose here, which is what we are currently doing in our forked executor at polimec, is to introduce a trait implemented by the executor which will handle those instructions. This way, if parachains want to keep the default behavior, they just use `()` and it will return unimplemented, but they can also implement their own logic to establish HRMP channels with other chains in an automated fashion, without requiring to go through governance. Our implementation is mentioned in the [polkadot HRMP docs](https://arc.net/l/quote/hduiivbu), and it was suggested to us to submit a PR to add these changes to polkadot-sdk. --------- Co-authored-by: Branislav Kontur Co-authored-by: command-bot <> --- cumulus/pallets/xcmp-queue/src/mock.rs | 3 + .../assets/asset-hub-rococo/src/xcm_config.rs | 3 + .../asset-hub-westend/src/xcm_config.rs | 3 + .../bridge-hub-rococo/src/xcm_config.rs | 3 + .../bridge-hub-westend/src/xcm_config.rs | 3 + .../collectives-westend/src/xcm_config.rs | 3 + .../contracts-rococo/src/xcm_config.rs | 3 + .../coretime-rococo/src/xcm_config.rs | 3 + .../coretime-westend/src/xcm_config.rs | 3 + .../glutton/glutton-westend/src/xcm_config.rs | 3 + .../people/people-rococo/src/xcm_config.rs | 3 + .../people/people-westend/src/xcm_config.rs | 3 + .../runtimes/starters/shell/src/xcm_config.rs | 3 + .../runtimes/testing/penpal/src/xcm_config.rs | 3 + .../testing/rococo-parachain/src/lib.rs | 3 + polkadot/runtime/rococo/src/xcm_config.rs | 3 + .../runtime/test-runtime/src/xcm_config.rs | 3 + polkadot/runtime/westend/src/xcm_config.rs | 3 + .../src/fungible/mock.rs | 3 + .../pallet-xcm-benchmarks/src/generic/mock.rs | 3 + polkadot/xcm/pallet-xcm/src/mock.rs | 3 + polkadot/xcm/xcm-builder/src/tests/mock.rs | 3 + .../xcm/xcm-builder/src/tests/pay/mock.rs | 3 + polkadot/xcm/xcm-builder/tests/mock/mod.rs | 3 + polkadot/xcm/xcm-executor/src/config.rs | 10 +++- polkadot/xcm/xcm-executor/src/lib.rs | 21 +++++-- polkadot/xcm/xcm-executor/src/traits/hrmp.rs | 56 +++++++++++++++++++ polkadot/xcm/xcm-executor/src/traits/mod.rs | 4 ++ .../xcm-simulator/example/src/parachain.rs | 3 + .../xcm-simulator/example/src/relay_chain.rs | 3 + .../xcm/xcm-simulator/fuzzer/src/parachain.rs | 3 + .../xcm-simulator/fuzzer/src/relay_chain.rs | 3 + prdoc/pr_3696.prdoc | 17 ++++++ .../contracts/mock-network/src/parachain.rs | 3 + .../contracts/mock-network/src/relay_chain.rs | 3 + templates/parachain/runtime/src/xcm_config.rs | 3 + 36 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 polkadot/xcm/xcm-executor/src/traits/hrmp.rs create mode 100644 prdoc/pr_3696.prdoc diff --git a/cumulus/pallets/xcmp-queue/src/mock.rs b/cumulus/pallets/xcmp-queue/src/mock.rs index 294f978f6ad..9d9a723cf8b 100644 --- a/cumulus/pallets/xcmp-queue/src/mock.rs +++ b/cumulus/pallets/xcmp-queue/src/mock.rs @@ -175,6 +175,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub type XcmRouter = ( diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 2584dbdf310..c438361cc17 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -628,6 +628,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Converts a local signed origin into an XCM location. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 50865c00061..c993d61545a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -649,6 +649,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 55c78477b56..8934ff9b227 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -336,6 +336,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub type PriceForParentDelivery = diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs index e18df6feda8..840d0c9af0e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs @@ -264,6 +264,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub type PriceForParentDelivery = diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs index 87f637d5b59..b83106a5828 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs @@ -288,6 +288,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Converts a local signed origin into an XCM location. diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs index e8f3209eb67..ac6fe634662 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs @@ -197,6 +197,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Converts a local signed origin into an XCM location. diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs index 1722e1fcb31..955f2eeba33 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs @@ -257,6 +257,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs index b03c7748fe0..fc7d36a8ba1 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs @@ -269,6 +269,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs index ad61987c0e7..15bb519e115 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs @@ -88,6 +88,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs index 534d6519086..a10333fdb62 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs @@ -269,6 +269,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs index 6353a581352..fee2f5684ac 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs @@ -277,6 +277,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs b/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs index f6af50f76d8..df89158729c 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs @@ -88,6 +88,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = (); + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index bc1aa05a617..d83a877c2f8 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -338,6 +338,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index a066cab1b6d..1b7efa6f400 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -484,6 +484,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// Local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index 67f34916fe7..328879715de 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -221,6 +221,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } parameter_types! { diff --git a/polkadot/runtime/test-runtime/src/xcm_config.rs b/polkadot/runtime/test-runtime/src/xcm_config.rs index a48bca17e9f..8411b79f252 100644 --- a/polkadot/runtime/test-runtime/src/xcm_config.rs +++ b/polkadot/runtime/test-runtime/src/xcm_config.rs @@ -153,6 +153,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } impl pallet_xcm::Config for crate::Runtime { diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 7281007f006..73127cb1efd 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -219,6 +219,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } parameter_types! { diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs index c75ecbceb08..c831cd02465 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs @@ -145,6 +145,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } impl crate::Config for Test { diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs index b037d3dd8b2..534f7d85ea2 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs @@ -135,6 +135,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Aliasers; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } parameter_types! { diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 77b30b1eaa1..b29562fc833 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -513,6 +513,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/xcm-builder/src/tests/mock.rs b/polkadot/xcm/xcm-builder/src/tests/mock.rs index 4521d5e92a4..4bf347ea771 100644 --- a/polkadot/xcm/xcm-builder/src/tests/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/mock.rs @@ -743,6 +743,9 @@ impl Config for TestConfig { type SafeCallFilter = Everything; type Aliasers = AliasForeignAccountId32; type TransactionalProcessor = (); + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub fn fungible_multi_asset(location: Location, amount: u128) -> Asset { diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 9feda8fb90b..019113a12b2 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -218,6 +218,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = (); + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } parameter_types! { diff --git a/polkadot/xcm/xcm-builder/tests/mock/mod.rs b/polkadot/xcm/xcm-builder/tests/mock/mod.rs index 536f8851bb4..f3cf5ab2649 100644 --- a/polkadot/xcm/xcm-builder/tests/mock/mod.rs +++ b/polkadot/xcm/xcm-builder/tests/mock/mod.rs @@ -204,6 +204,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = (); + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/xcm-executor/src/config.rs b/polkadot/xcm/xcm-executor/src/config.rs index ebe532a42fd..b296d32ca2a 100644 --- a/polkadot/xcm/xcm-executor/src/config.rs +++ b/polkadot/xcm/xcm-executor/src/config.rs @@ -16,7 +16,8 @@ use crate::traits::{ AssetExchange, AssetLock, CallDispatcher, ClaimAssets, ConvertOrigin, DropAssets, ExportXcm, - FeeManager, OnResponse, ProcessTransaction, ShouldExecute, TransactAsset, + FeeManager, HandleHrmpChannelAccepted, HandleHrmpChannelClosing, + HandleHrmpNewChannelOpenRequest, OnResponse, ProcessTransaction, ShouldExecute, TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, }; use frame_support::{ @@ -114,4 +115,11 @@ pub trait Config { /// Transactional processor for XCM instructions. type TransactionalProcessor: ProcessTransaction; + + /// Allows optional logic execution for the `HrmpNewChannelOpenRequest` XCM notification. + type HrmpNewChannelOpenRequestHandler: HandleHrmpNewChannelOpenRequest; + /// Allows optional logic execution for the `HrmpChannelAccepted` XCM notification. + type HrmpChannelAcceptedHandler: HandleHrmpChannelAccepted; + /// Allows optional logic execution for the `HrmpChannelClosing` XCM notification. + type HrmpChannelClosingHandler: HandleHrmpChannelClosing; } diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index c61e1e1d15b..81b81fe6a17 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -31,7 +31,8 @@ use xcm::latest::prelude::*; pub mod traits; use traits::{ validate_export, AssetExchange, AssetLock, CallDispatcher, ClaimAssets, ConvertOrigin, - DropAssets, Enact, ExportXcm, FeeManager, FeeReason, OnResponse, ProcessTransaction, + DropAssets, Enact, ExportXcm, FeeManager, FeeReason, HandleHrmpChannelAccepted, + HandleHrmpChannelClosing, HandleHrmpNewChannelOpenRequest, OnResponse, ProcessTransaction, Properties, ShouldExecute, TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, XcmAssetTransfers, }; @@ -1212,9 +1213,21 @@ impl XcmExecutor { ); Ok(()) }, - HrmpNewChannelOpenRequest { .. } => Err(XcmError::Unimplemented), - HrmpChannelAccepted { .. } => Err(XcmError::Unimplemented), - HrmpChannelClosing { .. } => Err(XcmError::Unimplemented), + HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => + Config::TransactionalProcessor::process(|| { + Config::HrmpNewChannelOpenRequestHandler::handle( + sender, + max_message_size, + max_capacity, + ) + }), + HrmpChannelAccepted { recipient } => Config::TransactionalProcessor::process(|| { + Config::HrmpChannelAcceptedHandler::handle(recipient) + }), + HrmpChannelClosing { initiator, sender, recipient } => + Config::TransactionalProcessor::process(|| { + Config::HrmpChannelClosingHandler::handle(initiator, sender, recipient) + }), } } } diff --git a/polkadot/xcm/xcm-executor/src/traits/hrmp.rs b/polkadot/xcm/xcm-executor/src/traits/hrmp.rs new file mode 100644 index 00000000000..b6bbb9316d7 --- /dev/null +++ b/polkadot/xcm/xcm-executor/src/traits/hrmp.rs @@ -0,0 +1,56 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use xcm::latest::Result as XcmResult; + +/// Executes logic when a `HrmpNewChannelOpenRequest` XCM notification is received. +pub trait HandleHrmpNewChannelOpenRequest { + fn handle(sender: u32, max_message_size: u32, max_capacity: u32) -> XcmResult; +} + +/// Executes optional logic when a `HrmpChannelAccepted` XCM notification is received. +pub trait HandleHrmpChannelAccepted { + fn handle(recipient: u32) -> XcmResult; +} + +/// Executes optional logic when a `HrmpChannelClosing` XCM notification is received. +pub trait HandleHrmpChannelClosing { + fn handle(initiator: u32, sender: u32, recipient: u32) -> XcmResult; +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl HandleHrmpNewChannelOpenRequest for Tuple { + fn handle(sender: u32, max_message_size: u32, max_capacity: u32) -> XcmResult { + for_tuples!( #( Tuple::handle(sender, max_message_size, max_capacity)?; )* ); + Ok(()) + } +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl HandleHrmpChannelAccepted for Tuple { + fn handle(recipient: u32) -> XcmResult { + for_tuples!( #( Tuple::handle(recipient)?; )* ); + Ok(()) + } +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl HandleHrmpChannelClosing for Tuple { + fn handle(initiator: u32, sender: u32, recipient: u32) -> XcmResult { + for_tuples!( #( Tuple::handle(initiator, sender, recipient)?; )* ); + Ok(()) + } +} diff --git a/polkadot/xcm/xcm-executor/src/traits/mod.rs b/polkadot/xcm/xcm-executor/src/traits/mod.rs index b445e84d391..aa3f0d26e30 100644 --- a/polkadot/xcm/xcm-executor/src/traits/mod.rs +++ b/polkadot/xcm/xcm-executor/src/traits/mod.rs @@ -45,6 +45,10 @@ mod should_execute; pub use should_execute::{CheckSuspension, Properties, ShouldExecute}; mod transact_asset; pub use transact_asset::TransactAsset; +mod hrmp; +pub use hrmp::{ + HandleHrmpChannelAccepted, HandleHrmpChannelClosing, HandleHrmpNewChannelOpenRequest, +}; mod weight; #[deprecated = "Use `sp_runtime::traits::` instead"] pub use sp_runtime::traits::{Identity, TryConvertInto as JustTry}; diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain.rs b/polkadot/xcm/xcm-simulator/example/src/parachain.rs index 50a12a3a698..86401d756af 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain.rs @@ -251,6 +251,9 @@ impl Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } #[frame_support::pallet] diff --git a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs index f41e273839b..377c77f30a4 100644 --- a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs @@ -198,6 +198,9 @@ impl Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index 1130701a344..cadfc1e7200 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -156,6 +156,9 @@ impl Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } #[frame_support::pallet] diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index 42dd8237cbf..3224df66cbe 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -157,6 +157,9 @@ impl Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/prdoc/pr_3696.prdoc b/prdoc/pr_3696.prdoc new file mode 100644 index 00000000000..f3371d1734a --- /dev/null +++ b/prdoc/pr_3696.prdoc @@ -0,0 +1,17 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Add HRMP notification handlers to the xcm-executor + +doc: + - audience: Runtime Dev + description: | + Adds optional HRMP notification handlers to the xcm-executor. These handlers are 3 new config types on the xcm-executor `Config` trait: + - `HrmpNewChannelOpenRequestHandler` + - `HrmpChannelAcceptedHandler` + - `HrmpChannelClosingHandler` + + The traits of these config types are implemented on tuples, and on `()` for the default case. + +crates: + - name: staging-xcm-executor diff --git a/substrate/frame/contracts/mock-network/src/parachain.rs b/substrate/frame/contracts/mock-network/src/parachain.rs index 0848f97b09c..d4ad47581d1 100644 --- a/substrate/frame/contracts/mock-network/src/parachain.rs +++ b/substrate/frame/contracts/mock-network/src/parachain.rs @@ -282,6 +282,9 @@ impl Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } impl mock_msg_queue::Config for Runtime { diff --git a/substrate/frame/contracts/mock-network/src/relay_chain.rs b/substrate/frame/contracts/mock-network/src/relay_chain.rs index 8c79255728e..e2a8d3d1337 100644 --- a/substrate/frame/contracts/mock-network/src/relay_chain.rs +++ b/substrate/frame/contracts/mock-network/src/relay_chain.rs @@ -182,6 +182,9 @@ impl Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/templates/parachain/runtime/src/xcm_config.rs b/templates/parachain/runtime/src/xcm_config.rs index b1230ba1e5d..7dce7164888 100644 --- a/templates/parachain/runtime/src/xcm_config.rs +++ b/templates/parachain/runtime/src/xcm_config.rs @@ -137,6 +137,9 @@ impl xcm_executor::Config for XcmConfig { type SafeCallFilter = Everything; type Aliasers = Nothing; type TransactionalProcessor = FrameTransactionalProcessor; + type HrmpNewChannelOpenRequestHandler = (); + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); } /// No local origins on this chain are allowed to dispatch XCM sends/executions. -- GitLab From 430ad2f5610dc3d53b4708c651617e34affa97f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 19 Mar 2024 09:27:51 +0100 Subject: [PATCH 139/188] Make `availability-recovery-regression-bench` a benchmark (#3741) Closes: https://github.com/paritytech/polkadot-sdk/issues/3704 --- .gitlab/pipeline/test.yml | 2 +- polkadot/node/network/availability-recovery/Cargo.toml | 4 ++-- .../availability-recovery-regression-bench.rs | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename polkadot/node/network/availability-recovery/{tests => benches}/availability-recovery-regression-bench.rs (100%) diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index 26e55e9385f..d244316000a 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -502,7 +502,7 @@ subsystem-regression-tests: - .common-refs - .run-immediately script: - - cargo test --profile=testnet -p polkadot-availability-recovery --test availability-recovery-regression-bench --features subsystem-benchmarks + - cargo bench --profile=testnet -p polkadot-availability-recovery --bench availability-recovery-regression-bench --features subsystem-benchmarks tags: - benchmark allow_failure: true diff --git a/polkadot/node/network/availability-recovery/Cargo.toml b/polkadot/node/network/availability-recovery/Cargo.toml index 12b6ce7a057..23c4148fa85 100644 --- a/polkadot/node/network/availability-recovery/Cargo.toml +++ b/polkadot/node/network/availability-recovery/Cargo.toml @@ -43,9 +43,9 @@ polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } polkadot-subsystem-bench = { path = "../../subsystem-bench" } -[[test]] +[[bench]] name = "availability-recovery-regression-bench" -path = "tests/availability-recovery-regression-bench.rs" +path = "benches/availability-recovery-regression-bench.rs" harness = false required-features = ["subsystem-benchmarks"] diff --git a/polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs b/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs similarity index 100% rename from polkadot/node/network/availability-recovery/tests/availability-recovery-regression-bench.rs rename to polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs -- GitLab From abd3f0c49a472fc4e4b52a814493224222921ffb Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 19 Mar 2024 13:35:22 +0200 Subject: [PATCH 140/188] Benchmarking: Add pov_mode to V2 syntax (#3616) Changes: - Port the `pov_mode` attribute from the V1 syntax to V2 - Update `pallet-whitelist` and `frame-benchmarking-pallet-pov` Follow up: also allow this attribute on top-level benchmark modules. --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: command-bot <> --- prdoc/pr_3616.prdoc | 28 + .../benchmarking/pov/src/benchmarking.rs | 412 +++++----- .../frame/benchmarking/pov/src/weights.rs | 710 +++++++++--------- .../frame/support/procedural/src/benchmark.rs | 167 +++- .../tests/benchmark_ui/bad_attr_pov_mode_1.rs | 31 + .../benchmark_ui/bad_attr_pov_mode_1.stderr | 5 + .../tests/benchmark_ui/bad_attr_pov_mode_2.rs | 33 + .../benchmark_ui/bad_attr_pov_mode_2.stderr | 5 + .../tests/benchmark_ui/bad_attr_pov_mode_3.rs | 31 + .../benchmark_ui/bad_attr_pov_mode_3.stderr | 5 + .../tests/benchmark_ui/bad_attr_pov_mode_4.rs | 31 + .../benchmark_ui/bad_attr_pov_mode_4.stderr | 5 + .../tests/benchmark_ui/dup_attr_pov_mode.rs | 32 + .../benchmark_ui/dup_attr_pov_mode.stderr | 14 + .../benchmark_ui/pass/valid_attr_pov_mode.rs | 74 ++ .../tests/benchmark_ui/pass/valid_basic.rs | 2 +- .../benchmark_ui/unrecognized_option.stderr | 2 +- substrate/frame/whitelist/src/benchmarking.rs | 99 ++- 18 files changed, 1085 insertions(+), 601 deletions(-) create mode 100644 prdoc/pr_3616.prdoc create mode 100644 substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_1.rs create mode 100644 substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_1.stderr create mode 100644 substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_2.rs create mode 100644 substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_2.stderr create mode 100644 substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_3.rs create mode 100644 substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_3.stderr create mode 100644 substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_4.rs create mode 100644 substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_4.stderr create mode 100644 substrate/frame/support/test/tests/benchmark_ui/dup_attr_pov_mode.rs create mode 100644 substrate/frame/support/test/tests/benchmark_ui/dup_attr_pov_mode.stderr create mode 100644 substrate/frame/support/test/tests/benchmark_ui/pass/valid_attr_pov_mode.rs diff --git a/prdoc/pr_3616.prdoc b/prdoc/pr_3616.prdoc new file mode 100644 index 00000000000..fcf068dcd17 --- /dev/null +++ b/prdoc/pr_3616.prdoc @@ -0,0 +1,28 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Benchmarking pallet V2 syntax extension: pov_mode attribute" + +doc: + - audience: Runtime Dev + description: | + Adds the `pov_mode` attribute from the V1 benchmarking syntax to the V2 syntax. This allows to + override the default PoV mode (`MaxEncodedLen`) to either `Measured` or `Ignored`. It can be + overridden for a whole benchmark, a key prefix of a specific key itself. + + Example syntax looks like this: + ```rust + #[benchmark(pov_mode = Measured { + Pallet: Measured, + Pallet::Storage: MaxEncodedLen, + })] + fn do_some() { + .. + } + ``` + +crates: + - name: frame-support-procedural + bump: minor + - name: frame-support + bump: minor diff --git a/substrate/frame/benchmarking/pov/src/benchmarking.rs b/substrate/frame/benchmarking/pov/src/benchmarking.rs index d78cb553318..7e6aa8e6bf6 100644 --- a/substrate/frame/benchmarking/pov/src/benchmarking.rs +++ b/substrate/frame/benchmarking/pov/src/benchmarking.rs @@ -21,54 +21,78 @@ use super::*; +use frame_benchmarking::v2::*; use frame_support::traits::UnfilteredDispatchable; use frame_system::{Pallet as System, RawOrigin}; use sp_runtime::traits::Hash; -frame_benchmarking::benchmarks! { - storage_single_value_read { +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn storage_single_value_read() { Value::::put(123); - }: { - assert_eq!(Value::::get(), Some(123)); + + #[block] + { + assert_eq!(Value::::get(), Some(123)); + } } - #[pov_mode = Ignored] - storage_single_value_ignored_read { + #[benchmark(pov_mode = Ignored)] + fn storage_single_value_ignored_read() { Value::::put(123); - }: { - assert_eq!(Value::::get(), Some(123)); + #[block] + { + assert_eq!(Value::::get(), Some(123)); + } } - #[pov_mode = MaxEncodedLen { + #[benchmark(pov_mode = MaxEncodedLen { Pov::Value2: Ignored - }] - storage_single_value_ignored_some_read { + })] + fn storage_single_value_ignored_some_read() { Value::::put(123); Value2::::put(123); - }: { - assert_eq!(Value::::get(), Some(123)); - assert_eq!(Value2::::get(), Some(123)); + + #[block] + { + assert_eq!(Value::::get(), Some(123)); + assert_eq!(Value2::::get(), Some(123)); + } } - storage_single_value_read_twice { + #[benchmark] + fn storage_single_value_read_twice() { Value::::put(123); - }: { - assert_eq!(Value::::get(), Some(123)); - assert_eq!(Value::::get(), Some(123)); + + #[block] + { + assert_eq!(Value::::get(), Some(123)); + assert_eq!(Value::::get(), Some(123)); + } } - storage_single_value_write { - }: { - Value::::put(123); - } verify { + #[benchmark] + fn storage_single_value_write() { + #[block] + { + Value::::put(123); + } + assert_eq!(Value::::get(), Some(123)); } - storage_single_value_kill { + #[benchmark] + fn storage_single_value_kill() { Value::::put(123); - }: { - Value::::kill(); - } verify { + + #[block] + { + Value::::kill(); + } + assert!(!Value::::exists()); } @@ -78,263 +102,297 @@ frame_benchmarking::benchmarks! { // created. Then the one value is read from the map. This demonstrates that the number of other // nodes in the Trie influences the proof size. The number of inserted nodes can be interpreted // as the number of `StorageMap`/`StorageValue` in the whole runtime. - #[pov_mode = Measured] - storage_1m_map_read_one_value_two_additional_layers { - (0..(1<<10)).for_each(|i| Map1M::::insert(i, i)); + #[benchmark(pov_mode = Measured)] + fn storage_1m_map_read_one_value_two_additional_layers() { + (0..(1 << 10)).for_each(|i| Map1M::::insert(i, i)); // Assume there are 16-256 other storage items. - (0..(1u32<<4)).for_each(|i| { + (0..(1u32 << 4)).for_each(|i| { let k = T::Hashing::hash(&i.to_be_bytes()); frame_support::storage::unhashed::put(k.as_ref(), &i); }); - }: { - assert_eq!(Map1M::::get(1<<9), Some(1<<9)); + + #[block] + { + assert_eq!(Map1M::::get(1 << 9), Some(1 << 9)); + } } - #[pov_mode = Measured] - storage_1m_map_read_one_value_three_additional_layers { - (0..(1<<10)).for_each(|i| Map1M::::insert(i, i)); + #[benchmark(pov_mode = Measured)] + fn storage_1m_map_read_one_value_three_additional_layers() { + (0..(1 << 10)).for_each(|i| Map1M::::insert(i, i)); // Assume there are 256-4096 other storage items. - (0..(1u32<<8)).for_each(|i| { + (0..(1u32 << 8)).for_each(|i| { let k = T::Hashing::hash(&i.to_be_bytes()); frame_support::storage::unhashed::put(k.as_ref(), &i); }); - }: { - assert_eq!(Map1M::::get(1<<9), Some(1<<9)); + + #[block] + { + assert_eq!(Map1M::::get(1 << 9), Some(1 << 9)); + } } - #[pov_mode = Measured] - storage_1m_map_read_one_value_four_additional_layers { - (0..(1<<10)).for_each(|i| Map1M::::insert(i, i)); + #[benchmark(pov_mode = Measured)] + fn storage_1m_map_read_one_value_four_additional_layers() { + (0..(1 << 10)).for_each(|i| Map1M::::insert(i, i)); // Assume there are 4096-65536 other storage items. - (0..(1u32<<12)).for_each(|i| { + (0..(1u32 << 12)).for_each(|i| { let k = T::Hashing::hash(&i.to_be_bytes()); frame_support::storage::unhashed::put(k.as_ref(), &i); }); - }: { - assert_eq!(Map1M::::get(1<<9), Some(1<<9)); + + #[block] + { + assert_eq!(Map1M::::get(1 << 9), Some(1 << 9)); + } } // Reads from both storage maps each `n` and `m` times. Should result in two linear components. - storage_map_read_per_component { - let n in 0 .. 100; - let m in 0 .. 100; + #[benchmark] + fn storage_map_read_per_component(n: Linear<0, 100>, m: Linear<0, 100>) { + (0..m * 10).for_each(|i| Map1M::::insert(i, i)); + (0..n * 10).for_each(|i| Map16M::::insert(i, i)); - (0..m*10).for_each(|i| Map1M::::insert(i, i)); - (0..n*10).for_each(|i| Map16M::::insert(i, i)); - }: { - (0..m).for_each(|i| - assert_eq!(Map1M::::get(i*10), Some(i*10))); - (0..n).for_each(|i| - assert_eq!(Map16M::::get(i*10), Some(i*10))); + #[block] + { + (0..m).for_each(|i| assert_eq!(Map1M::::get(i * 10), Some(i * 10))); + (0..n).for_each(|i| assert_eq!(Map16M::::get(i * 10), Some(i * 10))); + } } - #[pov_mode = MaxEncodedLen { + #[benchmark(pov_mode = MaxEncodedLen { Pov::Map1M: Ignored - }] - storage_map_read_per_component_one_ignored { - let n in 0 .. 100; - let m in 0 .. 100; + })] + fn storage_map_read_per_component_one_ignored(n: Linear<0, 100>, m: Linear<0, 100>) { + (0..m * 10).for_each(|i| Map1M::::insert(i, i)); + (0..n * 10).for_each(|i| Map16M::::insert(i, i)); - (0..m*10).for_each(|i| Map1M::::insert(i, i)); - (0..n*10).for_each(|i| Map16M::::insert(i, i)); - }: { - (0..m).for_each(|i| - assert_eq!(Map1M::::get(i*10), Some(i*10))); - (0..n).for_each(|i| - assert_eq!(Map16M::::get(i*10), Some(i*10))); + #[block] + { + (0..m).for_each(|i| assert_eq!(Map1M::::get(i * 10), Some(i * 10))); + (0..n).for_each(|i| assert_eq!(Map16M::::get(i * 10), Some(i * 10))); + } } // Reads the same value from a storage map. Should not result in a component. - storage_1m_map_one_entry_repeated_read { - let n in 0 .. 100; + #[benchmark] + fn storage_1m_map_one_entry_repeated_read(n: Linear<0, 100>) { Map1M::::insert(0, 0); - }: { - (0..n).for_each(|i| - assert_eq!(Map1M::::get(0), Some(0))); + + #[block] + { + (0..n).for_each(|_| assert_eq!(Map1M::::get(0), Some(0))); + } } // Reads the same values from a storage map. Should result in a `1x` linear component. - storage_1m_map_multiple_entry_repeated_read { - let n in 0 .. 100; + #[benchmark] + fn storage_1m_map_multiple_entry_repeated_read(n: Linear<0, 100>) { (0..n).for_each(|i| Map1M::::insert(i, i)); - }: { - (0..n).for_each(|i| { - // Reading the same value 10 times does nothing. - (0..10).for_each(|j| - assert_eq!(Map1M::::get(i), Some(i))); - }); + + #[block] + { + (0..n).for_each(|i| { + // Reading the same value 10 times does nothing. + (0..10).for_each(|_| assert_eq!(Map1M::::get(i), Some(i))); + }); + } } - storage_1m_double_map_read_per_component { - let n in 0 .. 1024; - (0..(1<<10)).for_each(|i| DoubleMap1M::::insert(i, i, i)); - }: { - (0..n).for_each(|i| - assert_eq!(DoubleMap1M::::get(i, i), Some(i))); + #[benchmark] + fn storage_1m_double_map_read_per_component(n: Linear<0, 1024>) { + (0..(1 << 10)).for_each(|i| DoubleMap1M::::insert(i, i, i)); + + #[block] + { + (0..n).for_each(|i| assert_eq!(DoubleMap1M::::get(i, i), Some(i))); + } } - storage_value_bounded_read { - }: { - assert!(BoundedValue::::get().is_none()); + #[benchmark] + fn storage_value_bounded_read() { + #[block] + { + assert!(BoundedValue::::get().is_none()); + } } // Reading unbounded values will produce no mathematical worst case PoV size for this component. - storage_value_unbounded_read { - }: { - assert!(UnboundedValue::::get().is_none()); + #[benchmark] + fn storage_value_unbounded_read() { + #[block] + { + assert!(UnboundedValue::::get().is_none()); + } } - #[pov_mode = Ignored] - storage_value_unbounded_ignored_read { - }: { - assert!(UnboundedValue::::get().is_none()); + #[benchmark(pov_mode = Ignored)] + fn storage_value_unbounded_ignored_read() { + #[block] + { + assert!(UnboundedValue::::get().is_none()); + } } // Same as above, but we still expect a mathematical worst case PoV size for the bounded one. - storage_value_bounded_and_unbounded_read { + #[benchmark] + fn storage_value_bounded_and_unbounded_read() { (0..1024).for_each(|i| Map1M::::insert(i, i)); - }: { - assert!(UnboundedValue::::get().is_none()); - assert!(BoundedValue::::get().is_none()); + #[block] + { + assert!(UnboundedValue::::get().is_none()); + assert!(BoundedValue::::get().is_none()); + } } - #[pov_mode = Measured] - measured_storage_value_read_linear_size { - let l in 0 .. 1<<22; + #[benchmark(pov_mode = Measured)] + fn measured_storage_value_read_linear_size(l: Linear<0, { 1 << 22 }>) { let v: sp_runtime::BoundedVec = sp_std::vec![0u8; l as usize].try_into().unwrap(); LargeValue::::put(&v); - }: { - assert!(LargeValue::::get().is_some()); + #[block] + { + assert!(LargeValue::::get().is_some()); + } } - #[pov_mode = MaxEncodedLen] - mel_storage_value_read_linear_size { - let l in 0 .. 1<<22; + #[benchmark(pov_mode = MaxEncodedLen)] + fn mel_storage_value_read_linear_size(l: Linear<0, { 1 << 22 }>) { let v: sp_runtime::BoundedVec = sp_std::vec![0u8; l as usize].try_into().unwrap(); LargeValue::::put(&v); - }: { - assert!(LargeValue::::get().is_some()); + #[block] + { + assert!(LargeValue::::get().is_some()); + } } - #[pov_mode = Measured] - measured_storage_double_value_read_linear_size { - let l in 0 .. 1<<22; + #[benchmark(pov_mode = Measured)] + fn measured_storage_double_value_read_linear_size(l: Linear<0, { 1 << 22 }>) { let v: sp_runtime::BoundedVec = sp_std::vec![0u8; l as usize].try_into().unwrap(); LargeValue::::put(&v); LargeValue2::::put(&v); - }: { - assert!(LargeValue::::get().is_some()); - assert!(LargeValue2::::get().is_some()); + #[block] + { + assert!(LargeValue::::get().is_some()); + assert!(LargeValue2::::get().is_some()); + } } - #[pov_mode = MaxEncodedLen] - mel_storage_double_value_read_linear_size { - let l in 0 .. 1<<22; + #[benchmark(pov_mode = MaxEncodedLen)] + fn mel_storage_double_value_read_linear_size(l: Linear<0, { 1 << 22 }>) { let v: sp_runtime::BoundedVec = sp_std::vec![0u8; l as usize].try_into().unwrap(); LargeValue::::put(&v); LargeValue2::::put(&v); - }: { - assert!(LargeValue::::get().is_some()); - assert!(LargeValue2::::get().is_some()); + #[block] + { + assert!(LargeValue::::get().is_some()); + assert!(LargeValue2::::get().is_some()); + } } - #[pov_mode = MaxEncodedLen { + #[benchmark(pov_mode = MaxEncodedLen { Pov::LargeValue2: Measured - }] - mel_mixed_storage_double_value_read_linear_size { - let l in 0 .. 1<<22; + })] + fn mel_mixed_storage_double_value_read_linear_size(l: Linear<0, { 1 << 22 }>) { let v: sp_runtime::BoundedVec = sp_std::vec![0u8; l as usize].try_into().unwrap(); LargeValue::::put(&v); LargeValue2::::put(&v); - }: { - assert!(LargeValue::::get().is_some()); - assert!(LargeValue2::::get().is_some()); + #[block] + { + assert!(LargeValue::::get().is_some()); + assert!(LargeValue2::::get().is_some()); + } } - #[pov_mode = Measured { + #[benchmark(pov_mode = Measured { Pov::LargeValue2: MaxEncodedLen - }] - measured_mixed_storage_double_value_read_linear_size { - let l in 0 .. 1<<22; + })] + fn measured_mixed_storage_double_value_read_linear_size(l: Linear<0, { 1 << 22 }>) { let v: sp_runtime::BoundedVec = sp_std::vec![0u8; l as usize].try_into().unwrap(); LargeValue::::put(&v); LargeValue2::::put(&v); - }: { - assert!(LargeValue::::get().is_some()); - assert!(LargeValue2::::get().is_some()); + #[block] + { + assert!(LargeValue::::get().is_some()); + assert!(LargeValue2::::get().is_some()); + } } - #[pov_mode = Measured] - storage_map_unbounded_both_measured_read { - let i in 0 .. 1000; - + #[benchmark(pov_mode = Measured)] + fn storage_map_unbounded_both_measured_read(i: Linear<0, 1000>) { UnboundedMap::::insert(i, sp_std::vec![0; i as usize]); UnboundedMap2::::insert(i, sp_std::vec![0; i as usize]); - }: { - assert!(UnboundedMap::::get(i).is_some()); - assert!(UnboundedMap2::::get(i).is_some()); + #[block] + { + assert!(UnboundedMap::::get(i).is_some()); + assert!(UnboundedMap2::::get(i).is_some()); + } } - #[pov_mode = MaxEncodedLen { + #[benchmark(pov_mode = MaxEncodedLen { Pov::UnboundedMap: Measured - }] - storage_map_partial_unbounded_read { - let i in 0 .. 1000; - + })] + fn storage_map_partial_unbounded_read(i: Linear<0, 1000>) { Map1M::::insert(i, 0); UnboundedMap::::insert(i, sp_std::vec![0; i as usize]); - }: { - assert!(Map1M::::get(i).is_some()); - assert!(UnboundedMap::::get(i).is_some()); + #[block] + { + assert!(Map1M::::get(i).is_some()); + assert!(UnboundedMap::::get(i).is_some()); + } } - #[pov_mode = MaxEncodedLen { + #[benchmark(pov_mode = MaxEncodedLen { Pov::UnboundedMap: Ignored - }] - storage_map_partial_unbounded_ignored_read { - let i in 0 .. 1000; - + })] + fn storage_map_partial_unbounded_ignored_read(i: Linear<0, 1000>) { Map1M::::insert(i, 0); UnboundedMap::::insert(i, sp_std::vec![0; i as usize]); - }: { - assert!(Map1M::::get(i).is_some()); - assert!(UnboundedMap::::get(i).is_some()); + #[block] + { + assert!(Map1M::::get(i).is_some()); + assert!(UnboundedMap::::get(i).is_some()); + } } // Emitting an event will not incur any PoV. - emit_event { + #[benchmark] + fn emit_event() { // Emit a single event. - let call = Call::::emit_event { }; - }: { call.dispatch_bypass_filter(RawOrigin::Root.into()).unwrap(); } - verify { + let call = Call::::emit_event {}; + #[block] + { + call.dispatch_bypass_filter(RawOrigin::Root.into()).unwrap(); + } assert_eq!(System::::events().len(), 1); } // A No-OP will not incur any PoV. - noop { - let call = Call::::noop { }; - }: { - call.dispatch_bypass_filter(RawOrigin::Root.into()).unwrap(); + #[benchmark] + fn noop() { + let call = Call::::noop {}; + #[block] + { + call.dispatch_bypass_filter(RawOrigin::Root.into()).unwrap(); + } } - storage_iteration { + #[benchmark] + fn storage_iteration() { for i in 0..65000 { UnboundedMapTwox::::insert(i, sp_std::vec![0; 64]); } - }: { - for (key, value) in UnboundedMapTwox::::iter() { - unsafe { - core::ptr::read_volatile(&key); - core::ptr::read_volatile(value.as_ptr()); + #[block] + { + for (key, value) in UnboundedMapTwox::::iter() { + unsafe { + core::ptr::read_volatile(&key); + core::ptr::read_volatile(value.as_ptr()); + } } } } - impl_benchmark_test_suite!( - Pallet, - mock::new_test_ext(), - mock::Test, - ); + impl_benchmark_test_suite!(Pallet, super::mock::new_test_ext(), super::mock::Test,); } #[cfg(test)] diff --git a/substrate/frame/benchmarking/pov/src/weights.rs b/substrate/frame/benchmarking/pov/src/weights.rs index d84ac88c98f..c4fc03d1dd9 100644 --- a/substrate/frame/benchmarking/pov/src/weights.rs +++ b/substrate/frame/benchmarking/pov/src/weights.rs @@ -15,38 +15,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for frame_benchmarking_pallet_pov +//! Autogenerated weights for `frame_benchmarking_pallet_pov` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-04-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `i9`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 +//! HOSTNAME: `Olivers-MBP`, CPU: `` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` // Executed Command: -// ./target/release/substrate +// target/release/substrate-node // benchmark // pallet -// --dev // --pallet // frame-benchmarking-pallet-pov // --extrinsic // -// --steps -// 50 -// --repeat -// 20 -// --template=.maintain/frame-weight-template.hbs -// --output=frame/benchmarking/pov/src/weights.rs +// --output +// substrate/frame/benchmarking/pov/src/weights.rs +// --template +// substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for frame_benchmarking_pallet_pov. +/// Weight functions needed for `frame_benchmarking_pallet_pov`. pub trait WeightInfo { fn storage_single_value_read() -> Weight; fn storage_single_value_ignored_read() -> Weight; @@ -80,361 +78,361 @@ pub trait WeightInfo { fn storage_iteration() -> Weight; } -/// Weights for frame_benchmarking_pallet_pov using the Substrate node and recommended hardware. +/// Weights for `frame_benchmarking_pallet_pov` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: Pov Value (r:1 w:0) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Pov::Value` (r:1 w:0) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn storage_single_value_read() -> Weight { // Proof Size summary in bytes: // Measured: `136` // Estimated: `1489` - // Minimum execution time: 1_706_000 picoseconds. - Weight::from_parts(1_788_000, 1489) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(3_000_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov Value (r:1 w:0) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: Ignored) + /// Storage: `Pov::Value` (r:1 w:0) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Ignored`) fn storage_single_value_ignored_read() -> Weight { // Proof Size summary in bytes: // Measured: `136` // Estimated: `0` - // Minimum execution time: 1_661_000 picoseconds. - Weight::from_parts(1_718_000, 0) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(3_000_000, 0) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov Value (r:1 w:0) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Pov Value2 (r:1 w:0) - /// Proof: Pov Value2 (max_values: Some(1), max_size: Some(4), added: 499, mode: Ignored) + /// Storage: `Pov::Value` (r:1 w:0) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Pov::Value2` (r:1 w:0) + /// Proof: `Pov::Value2` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Ignored`) fn storage_single_value_ignored_some_read() -> Weight { // Proof Size summary in bytes: // Measured: `160` // Estimated: `1489` - // Minimum execution time: 2_226_000 picoseconds. - Weight::from_parts(2_365_000, 1489) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 1489) .saturating_add(T::DbWeight::get().reads(2_u64)) } - /// Storage: Pov Value (r:1 w:0) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Pov::Value` (r:1 w:0) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn storage_single_value_read_twice() -> Weight { // Proof Size summary in bytes: // Measured: `136` // Estimated: `1489` - // Minimum execution time: 1_785_000 picoseconds. - Weight::from_parts(1_980_000, 1489) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(4_000_000, 1489) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov Value (r:0 w:1) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Pov::Value` (r:0 w:1) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn storage_single_value_write() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 254_000 picoseconds. - Weight::from_parts(326_000, 0) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(1_000_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Pov Value (r:0 w:1) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Pov::Value` (r:0 w:1) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn storage_single_value_kill() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 239_000 picoseconds. - Weight::from_parts(277_000, 0) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(1_000_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: Measured) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `Measured`) fn storage_1m_map_read_one_value_two_additional_layers() -> Weight { // Proof Size summary in bytes: // Measured: `1275` // Estimated: `4740` - // Minimum execution time: 4_760_000 picoseconds. - Weight::from_parts(5_051_000, 4740) + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4740) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: Measured) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `Measured`) fn storage_1m_map_read_one_value_three_additional_layers() -> Weight { // Proof Size summary in bytes: // Measured: `1544` // Estimated: `5009` - // Minimum execution time: 5_490_000 picoseconds. - Weight::from_parts(5_703_000, 5009) + // Minimum execution time: 8_000_000 picoseconds. + Weight::from_parts(8_000_000, 5009) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: Measured) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `Measured`) fn storage_1m_map_read_one_value_four_additional_layers() -> Weight { // Proof Size summary in bytes: // Measured: `2044` // Estimated: `5509` - // Minimum execution time: 6_397_000 picoseconds. - Weight::from_parts(7_084_000, 5509) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 5509) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov Map1M (r:100 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) - /// Storage: Pov Map16M (r:100 w:0) - /// Proof: Pov Map16M (max_values: Some(16000000), max_size: Some(36), added: 3006, mode: MaxEncodedLen) + /// Storage: `Pov::Map1M` (r:100 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Pov::Map16M` (r:100 w:0) + /// Proof: `Pov::Map16M` (`max_values`: Some(16000000), `max_size`: Some(36), added: 3006, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. /// The range of component `m` is `[0, 100]`. fn storage_map_read_per_component(n: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `515 + m * (188 ±0) + n * (188 ±0)` // Estimated: `990 + m * (2511 ±0) + n * (3006 ±0)` - // Minimum execution time: 181_481_000 picoseconds. - Weight::from_parts(129_275_141, 990) - // Standard Error: 13_049 - .saturating_add(Weight::from_parts(787_667, 0).saturating_mul(n.into())) - // Standard Error: 13_049 - .saturating_add(Weight::from_parts(830_378, 0).saturating_mul(m.into())) + // Minimum execution time: 342_000_000 picoseconds. + Weight::from_parts(179_688_624, 990) + // Standard Error: 26_526 + .saturating_add(Weight::from_parts(2_061_828, 0).saturating_mul(n.into())) + // Standard Error: 26_526 + .saturating_add(Weight::from_parts(1_825_923, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(Weight::from_parts(0, 2511).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 3006).saturating_mul(n.into())) } - /// Storage: Pov Map1M (r:100 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: Ignored) - /// Storage: Pov Map16M (r:100 w:0) - /// Proof: Pov Map16M (max_values: Some(16000000), max_size: Some(36), added: 3006, mode: MaxEncodedLen) + /// Storage: `Pov::Map1M` (r:100 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `Ignored`) + /// Storage: `Pov::Map16M` (r:100 w:0) + /// Proof: `Pov::Map16M` (`max_values`: Some(16000000), `max_size`: Some(36), added: 3006, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. /// The range of component `m` is `[0, 100]`. fn storage_map_read_per_component_one_ignored(n: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `515 + m * (188 ±0) + n * (188 ±0)` // Estimated: `1685 + m * (189 ±0) + n * (3006 ±0)` - // Minimum execution time: 181_925_000 picoseconds. - Weight::from_parts(134_416_814, 1685) - // Standard Error: 15_678 - .saturating_add(Weight::from_parts(827_168, 0).saturating_mul(n.into())) - // Standard Error: 15_678 - .saturating_add(Weight::from_parts(813_655, 0).saturating_mul(m.into())) + // Minimum execution time: 342_000_000 picoseconds. + Weight::from_parts(204_945_396, 1685) + // Standard Error: 25_217 + .saturating_add(Weight::from_parts(1_827_513, 0).saturating_mul(n.into())) + // Standard Error: 25_217 + .saturating_add(Weight::from_parts(1_661_271, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(Weight::from_parts(0, 189).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 3006).saturating_mul(n.into())) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. fn storage_1m_map_one_entry_repeated_read(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `170` // Estimated: `3501` - // Minimum execution time: 20_000 picoseconds. - Weight::from_parts(2_006_399, 3501) - // Standard Error: 808 - .saturating_add(Weight::from_parts(263_609, 0).saturating_mul(n.into())) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(3_387_064, 3501) + // Standard Error: 1_445 + .saturating_add(Weight::from_parts(1_143_678, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov Map1M (r:100 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `Pov::Map1M` (r:100 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. fn storage_1m_map_multiple_entry_repeated_read(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `147 + n * (40 ±0)` // Estimated: `990 + n * (2511 ±0)` - // Minimum execution time: 21_000 picoseconds. - Weight::from_parts(3_940_044, 990) - // Standard Error: 4_906 - .saturating_add(Weight::from_parts(3_454_882, 0).saturating_mul(n.into())) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(1_323_684, 990) + // Standard Error: 10_546 + .saturating_add(Weight::from_parts(13_101_864, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2511).saturating_mul(n.into())) } - /// Storage: Pov DoubleMap1M (r:1024 w:0) - /// Proof: Pov DoubleMap1M (max_values: Some(1000000), max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Pov::DoubleMap1M` (r:1024 w:0) + /// Proof: `Pov::DoubleMap1M` (`max_values`: Some(1000000), `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1024]`. fn storage_1m_double_map_read_per_component(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `21938 + n * (57 ±0)` // Estimated: `990 + n * (2543 ±0)` - // Minimum execution time: 28_000 picoseconds. - Weight::from_parts(20_674_869, 990) - // Standard Error: 3_035 - .saturating_add(Weight::from_parts(1_995_730, 0).saturating_mul(n.into())) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(39_703_963, 990) + // Standard Error: 10_589 + .saturating_add(Weight::from_parts(3_718_040, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2543).saturating_mul(n.into())) } - /// Storage: Pov BoundedValue (r:1 w:0) - /// Proof: Pov BoundedValue (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen) + /// Storage: `Pov::BoundedValue` (r:1 w:0) + /// Proof: `Pov::BoundedValue` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) fn storage_value_bounded_read() -> Weight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1518` - // Minimum execution time: 1_091_000 picoseconds. - Weight::from_parts(1_181_000, 1518) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 1518) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov UnboundedValue (r:1 w:0) - /// Proof Skipped: Pov UnboundedValue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Pov::UnboundedValue` (r:1 w:0) + /// Proof: `Pov::UnboundedValue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn storage_value_unbounded_read() -> Weight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1594` - // Minimum execution time: 1_079_000 picoseconds. - Weight::from_parts(1_176_000, 1594) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 1594) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov UnboundedValue (r:1 w:0) - /// Proof Skipped: Pov UnboundedValue (max_values: Some(1), max_size: None, mode: Ignored) + /// Storage: `Pov::UnboundedValue` (r:1 w:0) + /// Proof: `Pov::UnboundedValue` (`max_values`: Some(1), `max_size`: None, mode: `Ignored`) fn storage_value_unbounded_ignored_read() -> Weight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `0` - // Minimum execution time: 1_101_000 picoseconds. - Weight::from_parts(1_160_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov UnboundedValue (r:1 w:0) - /// Proof Skipped: Pov UnboundedValue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Pov BoundedValue (r:1 w:0) - /// Proof: Pov BoundedValue (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen) + /// Storage: `Pov::UnboundedValue` (r:1 w:0) + /// Proof: `Pov::UnboundedValue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Pov::BoundedValue` (r:1 w:0) + /// Proof: `Pov::BoundedValue` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) fn storage_value_bounded_and_unbounded_read() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `1632` - // Minimum execution time: 2_143_000 picoseconds. - Weight::from_parts(2_280_000, 1632) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(5_000_000, 1632) .saturating_add(T::DbWeight::get().reads(2_u64)) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) /// The range of component `l` is `[0, 4194304]`. fn measured_storage_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `142 + l * (1 ±0)` // Estimated: `1626 + l * (1 ±0)` - // Minimum execution time: 1_665_000 picoseconds. - Weight::from_parts(1_725_000, 1626) - // Standard Error: 3 - .saturating_add(Weight::from_parts(376, 0).saturating_mul(l.into())) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(3_000_000, 1626) + // Standard Error: 1 + .saturating_add(Weight::from_parts(393, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(l.into())) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 4194304]`. fn mel_storage_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `142 + l * (1 ±0)` // Estimated: `4195793` - // Minimum execution time: 1_640_000 picoseconds. - Weight::from_parts(1_724_000, 4195793) - // Standard Error: 4 - .saturating_add(Weight::from_parts(395, 0).saturating_mul(l.into())) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(3_000_000, 4195793) + // Standard Error: 1 + .saturating_add(Weight::from_parts(394, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) - /// Storage: Pov LargeValue2 (r:1 w:0) - /// Proof: Pov LargeValue2 (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) + /// Storage: `Pov::LargeValue2` (r:1 w:0) + /// Proof: `Pov::LargeValue2` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) /// The range of component `l` is `[0, 4194304]`. fn measured_storage_double_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `171 + l * (2 ±0)` // Estimated: `1655 + l * (2 ±0)` - // Minimum execution time: 2_263_000 picoseconds. - Weight::from_parts(2_358_000, 1655) - // Standard Error: 8 - .saturating_add(Weight::from_parts(737, 0).saturating_mul(l.into())) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 1655) + // Standard Error: 2 + .saturating_add(Weight::from_parts(655, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 2).saturating_mul(l.into())) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) - /// Storage: Pov LargeValue2 (r:1 w:0) - /// Proof: Pov LargeValue2 (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) + /// Storage: `Pov::LargeValue2` (r:1 w:0) + /// Proof: `Pov::LargeValue2` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 4194304]`. fn mel_storage_double_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `171 + l * (2 ±0)` // Estimated: `4195793` - // Minimum execution time: 2_161_000 picoseconds. - Weight::from_parts(2_233_000, 4195793) - // Standard Error: 5 - .saturating_add(Weight::from_parts(639, 0).saturating_mul(l.into())) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 4195793) + // Standard Error: 2 + .saturating_add(Weight::from_parts(660, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) - /// Storage: Pov LargeValue2 (r:1 w:0) - /// Proof: Pov LargeValue2 (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) + /// Storage: `Pov::LargeValue2` (r:1 w:0) + /// Proof: `Pov::LargeValue2` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) /// The range of component `l` is `[0, 4194304]`. fn mel_mixed_storage_double_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `171 + l * (2 ±0)` // Estimated: `4195793 + l * (2 ±0)` - // Minimum execution time: 2_149_000 picoseconds. - Weight::from_parts(2_256_000, 4195793) - // Standard Error: 6 - .saturating_add(Weight::from_parts(677, 0).saturating_mul(l.into())) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 4195793) + // Standard Error: 4 + .saturating_add(Weight::from_parts(691, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 2).saturating_mul(l.into())) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) - /// Storage: Pov LargeValue2 (r:1 w:0) - /// Proof: Pov LargeValue2 (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) + /// Storage: `Pov::LargeValue2` (r:1 w:0) + /// Proof: `Pov::LargeValue2` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 4194304]`. fn measured_mixed_storage_double_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `171 + l * (2 ±0)` // Estimated: `4195793 + l * (2 ±0)` - // Minimum execution time: 2_254_000 picoseconds. - Weight::from_parts(2_319_000, 4195793) - // Standard Error: 5 - .saturating_add(Weight::from_parts(664, 0).saturating_mul(l.into())) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 4195793) + // Standard Error: 4 + .saturating_add(Weight::from_parts(691, 0).saturating_mul(l.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 2).saturating_mul(l.into())) } - /// Storage: Pov UnboundedMap (r:1 w:0) - /// Proof Skipped: Pov UnboundedMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Pov UnboundedMap2 (r:1 w:0) - /// Proof Skipped: Pov UnboundedMap2 (max_values: None, max_size: None, mode: Measured) + /// Storage: `Pov::UnboundedMap` (r:1 w:0) + /// Proof: `Pov::UnboundedMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Pov::UnboundedMap2` (r:1 w:0) + /// Proof: `Pov::UnboundedMap2` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn storage_map_unbounded_both_measured_read(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `229 + i * (8 ±0)` // Estimated: `3693 + i * (8 ±0)` - // Minimum execution time: 3_071_000 picoseconds. - Weight::from_parts(3_487_712, 3693) - // Standard Error: 26 - .saturating_add(Weight::from_parts(748, 0).saturating_mul(i.into())) + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(7_274_226, 3693) + // Standard Error: 280 + .saturating_add(Weight::from_parts(3_282, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(i.into())) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) - /// Storage: Pov UnboundedMap (r:1 w:0) - /// Proof Skipped: Pov UnboundedMap (max_values: None, max_size: None, mode: Measured) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Pov::UnboundedMap` (r:1 w:0) + /// Proof: `Pov::UnboundedMap` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn storage_map_partial_unbounded_read(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `228 + i * (4 ±0)` // Estimated: `3692 + i * (4 ±0)` - // Minimum execution time: 3_150_000 picoseconds. - Weight::from_parts(3_582_963, 3692) - // Standard Error: 18 - .saturating_add(Weight::from_parts(380, 0).saturating_mul(i.into())) + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_507_333, 3692) + // Standard Error: 64 + .saturating_add(Weight::from_parts(982, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 4).saturating_mul(i.into())) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) - /// Storage: Pov UnboundedMap (r:1 w:0) - /// Proof Skipped: Pov UnboundedMap (max_values: None, max_size: None, mode: Ignored) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Pov::UnboundedMap` (r:1 w:0) + /// Proof: `Pov::UnboundedMap` (`max_values`: None, `max_size`: None, mode: `Ignored`) /// The range of component `i` is `[0, 1000]`. fn storage_map_partial_unbounded_ignored_read(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `228 + i * (4 ±0)` // Estimated: `3501 + i * (4 ±0)` - // Minimum execution time: 3_092_000 picoseconds. - Weight::from_parts(3_595_328, 3501) - // Standard Error: 20 - .saturating_add(Weight::from_parts(243, 0).saturating_mul(i.into())) + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(7_285_011, 3501) + // Standard Error: 80 + .saturating_add(Weight::from_parts(1_395, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 4).saturating_mul(i.into())) } @@ -442,382 +440,382 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_705_000 picoseconds. - Weight::from_parts(1_818_000, 0) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(5_000_000, 0) } fn noop() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 533_000 picoseconds. - Weight::from_parts(587_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) } - /// Storage: Pov UnboundedMapTwox (r:65001 w:0) - /// Proof Skipped: Pov UnboundedMapTwox (max_values: None, max_size: None, mode: Measured) + /// Storage: `Pov::UnboundedMapTwox` (r:65001 w:0) + /// Proof: `Pov::UnboundedMapTwox` (`max_values`: None, `max_size`: None, mode: `Measured`) fn storage_iteration() -> Weight { // Proof Size summary in bytes: // Measured: `17985289` // Estimated: `178863754` - // Minimum execution time: 118_753_057_000 picoseconds. - Weight::from_parts(121_396_503_000, 178863754) + // Minimum execution time: 218_275_000_000 picoseconds. + Weight::from_parts(222_603_000_000, 178863754) .saturating_add(T::DbWeight::get().reads(65001_u64)) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: Pov Value (r:1 w:0) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Pov::Value` (r:1 w:0) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn storage_single_value_read() -> Weight { // Proof Size summary in bytes: // Measured: `136` // Estimated: `1489` - // Minimum execution time: 1_706_000 picoseconds. - Weight::from_parts(1_788_000, 1489) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(3_000_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov Value (r:1 w:0) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: Ignored) + /// Storage: `Pov::Value` (r:1 w:0) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Ignored`) fn storage_single_value_ignored_read() -> Weight { // Proof Size summary in bytes: // Measured: `136` // Estimated: `0` - // Minimum execution time: 1_661_000 picoseconds. - Weight::from_parts(1_718_000, 0) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(3_000_000, 0) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov Value (r:1 w:0) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: Pov Value2 (r:1 w:0) - /// Proof: Pov Value2 (max_values: Some(1), max_size: Some(4), added: 499, mode: Ignored) + /// Storage: `Pov::Value` (r:1 w:0) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Pov::Value2` (r:1 w:0) + /// Proof: `Pov::Value2` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `Ignored`) fn storage_single_value_ignored_some_read() -> Weight { // Proof Size summary in bytes: // Measured: `160` // Estimated: `1489` - // Minimum execution time: 2_226_000 picoseconds. - Weight::from_parts(2_365_000, 1489) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 1489) .saturating_add(RocksDbWeight::get().reads(2_u64)) } - /// Storage: Pov Value (r:1 w:0) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Pov::Value` (r:1 w:0) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn storage_single_value_read_twice() -> Weight { // Proof Size summary in bytes: // Measured: `136` // Estimated: `1489` - // Minimum execution time: 1_785_000 picoseconds. - Weight::from_parts(1_980_000, 1489) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(4_000_000, 1489) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov Value (r:0 w:1) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Pov::Value` (r:0 w:1) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn storage_single_value_write() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 254_000 picoseconds. - Weight::from_parts(326_000, 0) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(1_000_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Pov Value (r:0 w:1) - /// Proof: Pov Value (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: `Pov::Value` (r:0 w:1) + /// Proof: `Pov::Value` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn storage_single_value_kill() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 239_000 picoseconds. - Weight::from_parts(277_000, 0) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(1_000_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: Measured) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `Measured`) fn storage_1m_map_read_one_value_two_additional_layers() -> Weight { // Proof Size summary in bytes: // Measured: `1275` // Estimated: `4740` - // Minimum execution time: 4_760_000 picoseconds. - Weight::from_parts(5_051_000, 4740) + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4740) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: Measured) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `Measured`) fn storage_1m_map_read_one_value_three_additional_layers() -> Weight { // Proof Size summary in bytes: // Measured: `1544` // Estimated: `5009` - // Minimum execution time: 5_490_000 picoseconds. - Weight::from_parts(5_703_000, 5009) + // Minimum execution time: 8_000_000 picoseconds. + Weight::from_parts(8_000_000, 5009) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: Measured) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `Measured`) fn storage_1m_map_read_one_value_four_additional_layers() -> Weight { // Proof Size summary in bytes: // Measured: `2044` // Estimated: `5509` - // Minimum execution time: 6_397_000 picoseconds. - Weight::from_parts(7_084_000, 5509) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 5509) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov Map1M (r:100 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) - /// Storage: Pov Map16M (r:100 w:0) - /// Proof: Pov Map16M (max_values: Some(16000000), max_size: Some(36), added: 3006, mode: MaxEncodedLen) + /// Storage: `Pov::Map1M` (r:100 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Pov::Map16M` (r:100 w:0) + /// Proof: `Pov::Map16M` (`max_values`: Some(16000000), `max_size`: Some(36), added: 3006, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. /// The range of component `m` is `[0, 100]`. fn storage_map_read_per_component(n: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `515 + m * (188 ±0) + n * (188 ±0)` // Estimated: `990 + m * (2511 ±0) + n * (3006 ±0)` - // Minimum execution time: 181_481_000 picoseconds. - Weight::from_parts(129_275_141, 990) - // Standard Error: 13_049 - .saturating_add(Weight::from_parts(787_667, 0).saturating_mul(n.into())) - // Standard Error: 13_049 - .saturating_add(Weight::from_parts(830_378, 0).saturating_mul(m.into())) + // Minimum execution time: 342_000_000 picoseconds. + Weight::from_parts(179_688_624, 990) + // Standard Error: 26_526 + .saturating_add(Weight::from_parts(2_061_828, 0).saturating_mul(n.into())) + // Standard Error: 26_526 + .saturating_add(Weight::from_parts(1_825_923, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(Weight::from_parts(0, 2511).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 3006).saturating_mul(n.into())) } - /// Storage: Pov Map1M (r:100 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: Ignored) - /// Storage: Pov Map16M (r:100 w:0) - /// Proof: Pov Map16M (max_values: Some(16000000), max_size: Some(36), added: 3006, mode: MaxEncodedLen) + /// Storage: `Pov::Map1M` (r:100 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `Ignored`) + /// Storage: `Pov::Map16M` (r:100 w:0) + /// Proof: `Pov::Map16M` (`max_values`: Some(16000000), `max_size`: Some(36), added: 3006, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. /// The range of component `m` is `[0, 100]`. fn storage_map_read_per_component_one_ignored(n: u32, m: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `515 + m * (188 ±0) + n * (188 ±0)` // Estimated: `1685 + m * (189 ±0) + n * (3006 ±0)` - // Minimum execution time: 181_925_000 picoseconds. - Weight::from_parts(134_416_814, 1685) - // Standard Error: 15_678 - .saturating_add(Weight::from_parts(827_168, 0).saturating_mul(n.into())) - // Standard Error: 15_678 - .saturating_add(Weight::from_parts(813_655, 0).saturating_mul(m.into())) + // Minimum execution time: 342_000_000 picoseconds. + Weight::from_parts(204_945_396, 1685) + // Standard Error: 25_217 + .saturating_add(Weight::from_parts(1_827_513, 0).saturating_mul(n.into())) + // Standard Error: 25_217 + .saturating_add(Weight::from_parts(1_661_271, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(Weight::from_parts(0, 189).saturating_mul(m.into())) .saturating_add(Weight::from_parts(0, 3006).saturating_mul(n.into())) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. fn storage_1m_map_one_entry_repeated_read(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `170` // Estimated: `3501` - // Minimum execution time: 20_000 picoseconds. - Weight::from_parts(2_006_399, 3501) - // Standard Error: 808 - .saturating_add(Weight::from_parts(263_609, 0).saturating_mul(n.into())) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(3_387_064, 3501) + // Standard Error: 1_445 + .saturating_add(Weight::from_parts(1_143_678, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov Map1M (r:100 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: `Pov::Map1M` (r:100 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 100]`. fn storage_1m_map_multiple_entry_repeated_read(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `147 + n * (40 ±0)` // Estimated: `990 + n * (2511 ±0)` - // Minimum execution time: 21_000 picoseconds. - Weight::from_parts(3_940_044, 990) - // Standard Error: 4_906 - .saturating_add(Weight::from_parts(3_454_882, 0).saturating_mul(n.into())) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(1_323_684, 990) + // Standard Error: 10_546 + .saturating_add(Weight::from_parts(13_101_864, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2511).saturating_mul(n.into())) } - /// Storage: Pov DoubleMap1M (r:1024 w:0) - /// Proof: Pov DoubleMap1M (max_values: Some(1000000), max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: `Pov::DoubleMap1M` (r:1024 w:0) + /// Proof: `Pov::DoubleMap1M` (`max_values`: Some(1000000), `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1024]`. fn storage_1m_double_map_read_per_component(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `21938 + n * (57 ±0)` // Estimated: `990 + n * (2543 ±0)` - // Minimum execution time: 28_000 picoseconds. - Weight::from_parts(20_674_869, 990) - // Standard Error: 3_035 - .saturating_add(Weight::from_parts(1_995_730, 0).saturating_mul(n.into())) + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(39_703_963, 990) + // Standard Error: 10_589 + .saturating_add(Weight::from_parts(3_718_040, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2543).saturating_mul(n.into())) } - /// Storage: Pov BoundedValue (r:1 w:0) - /// Proof: Pov BoundedValue (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen) + /// Storage: `Pov::BoundedValue` (r:1 w:0) + /// Proof: `Pov::BoundedValue` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) fn storage_value_bounded_read() -> Weight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1518` - // Minimum execution time: 1_091_000 picoseconds. - Weight::from_parts(1_181_000, 1518) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 1518) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov UnboundedValue (r:1 w:0) - /// Proof Skipped: Pov UnboundedValue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: `Pov::UnboundedValue` (r:1 w:0) + /// Proof: `Pov::UnboundedValue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn storage_value_unbounded_read() -> Weight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1594` - // Minimum execution time: 1_079_000 picoseconds. - Weight::from_parts(1_176_000, 1594) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 1594) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov UnboundedValue (r:1 w:0) - /// Proof Skipped: Pov UnboundedValue (max_values: Some(1), max_size: None, mode: Ignored) + /// Storage: `Pov::UnboundedValue` (r:1 w:0) + /// Proof: `Pov::UnboundedValue` (`max_values`: Some(1), `max_size`: None, mode: `Ignored`) fn storage_value_unbounded_ignored_read() -> Weight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `0` - // Minimum execution time: 1_101_000 picoseconds. - Weight::from_parts(1_160_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov UnboundedValue (r:1 w:0) - /// Proof Skipped: Pov UnboundedValue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Pov BoundedValue (r:1 w:0) - /// Proof: Pov BoundedValue (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen) + /// Storage: `Pov::UnboundedValue` (r:1 w:0) + /// Proof: `Pov::UnboundedValue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Pov::BoundedValue` (r:1 w:0) + /// Proof: `Pov::BoundedValue` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) fn storage_value_bounded_and_unbounded_read() -> Weight { // Proof Size summary in bytes: // Measured: `147` // Estimated: `1632` - // Minimum execution time: 2_143_000 picoseconds. - Weight::from_parts(2_280_000, 1632) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(5_000_000, 1632) .saturating_add(RocksDbWeight::get().reads(2_u64)) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) /// The range of component `l` is `[0, 4194304]`. fn measured_storage_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `142 + l * (1 ±0)` // Estimated: `1626 + l * (1 ±0)` - // Minimum execution time: 1_665_000 picoseconds. - Weight::from_parts(1_725_000, 1626) - // Standard Error: 3 - .saturating_add(Weight::from_parts(376, 0).saturating_mul(l.into())) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(3_000_000, 1626) + // Standard Error: 1 + .saturating_add(Weight::from_parts(393, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(l.into())) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 4194304]`. fn mel_storage_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `142 + l * (1 ±0)` // Estimated: `4195793` - // Minimum execution time: 1_640_000 picoseconds. - Weight::from_parts(1_724_000, 4195793) - // Standard Error: 4 - .saturating_add(Weight::from_parts(395, 0).saturating_mul(l.into())) + // Minimum execution time: 3_000_000 picoseconds. + Weight::from_parts(3_000_000, 4195793) + // Standard Error: 1 + .saturating_add(Weight::from_parts(394, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) - /// Storage: Pov LargeValue2 (r:1 w:0) - /// Proof: Pov LargeValue2 (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) + /// Storage: `Pov::LargeValue2` (r:1 w:0) + /// Proof: `Pov::LargeValue2` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) /// The range of component `l` is `[0, 4194304]`. fn measured_storage_double_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `171 + l * (2 ±0)` // Estimated: `1655 + l * (2 ±0)` - // Minimum execution time: 2_263_000 picoseconds. - Weight::from_parts(2_358_000, 1655) - // Standard Error: 8 - .saturating_add(Weight::from_parts(737, 0).saturating_mul(l.into())) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 1655) + // Standard Error: 2 + .saturating_add(Weight::from_parts(655, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 2).saturating_mul(l.into())) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) - /// Storage: Pov LargeValue2 (r:1 w:0) - /// Proof: Pov LargeValue2 (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) + /// Storage: `Pov::LargeValue2` (r:1 w:0) + /// Proof: `Pov::LargeValue2` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 4194304]`. fn mel_storage_double_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `171 + l * (2 ±0)` // Estimated: `4195793` - // Minimum execution time: 2_161_000 picoseconds. - Weight::from_parts(2_233_000, 4195793) - // Standard Error: 5 - .saturating_add(Weight::from_parts(639, 0).saturating_mul(l.into())) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 4195793) + // Standard Error: 2 + .saturating_add(Weight::from_parts(660, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) - /// Storage: Pov LargeValue2 (r:1 w:0) - /// Proof: Pov LargeValue2 (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) + /// Storage: `Pov::LargeValue2` (r:1 w:0) + /// Proof: `Pov::LargeValue2` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) /// The range of component `l` is `[0, 4194304]`. fn mel_mixed_storage_double_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `171 + l * (2 ±0)` // Estimated: `4195793 + l * (2 ±0)` - // Minimum execution time: 2_149_000 picoseconds. - Weight::from_parts(2_256_000, 4195793) - // Standard Error: 6 - .saturating_add(Weight::from_parts(677, 0).saturating_mul(l.into())) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 4195793) + // Standard Error: 4 + .saturating_add(Weight::from_parts(691, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 2).saturating_mul(l.into())) } - /// Storage: Pov LargeValue (r:1 w:0) - /// Proof: Pov LargeValue (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: Measured) - /// Storage: Pov LargeValue2 (r:1 w:0) - /// Proof: Pov LargeValue2 (max_values: Some(1), max_size: Some(4194308), added: 4194803, mode: MaxEncodedLen) + /// Storage: `Pov::LargeValue` (r:1 w:0) + /// Proof: `Pov::LargeValue` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `Measured`) + /// Storage: `Pov::LargeValue2` (r:1 w:0) + /// Proof: `Pov::LargeValue2` (`max_values`: Some(1), `max_size`: Some(4194308), added: 4194803, mode: `MaxEncodedLen`) /// The range of component `l` is `[0, 4194304]`. fn measured_mixed_storage_double_value_read_linear_size(l: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `171 + l * (2 ±0)` // Estimated: `4195793 + l * (2 ±0)` - // Minimum execution time: 2_254_000 picoseconds. - Weight::from_parts(2_319_000, 4195793) - // Standard Error: 5 - .saturating_add(Weight::from_parts(664, 0).saturating_mul(l.into())) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(4_000_000, 4195793) + // Standard Error: 4 + .saturating_add(Weight::from_parts(691, 0).saturating_mul(l.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 2).saturating_mul(l.into())) } - /// Storage: Pov UnboundedMap (r:1 w:0) - /// Proof Skipped: Pov UnboundedMap (max_values: None, max_size: None, mode: Measured) - /// Storage: Pov UnboundedMap2 (r:1 w:0) - /// Proof Skipped: Pov UnboundedMap2 (max_values: None, max_size: None, mode: Measured) + /// Storage: `Pov::UnboundedMap` (r:1 w:0) + /// Proof: `Pov::UnboundedMap` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Pov::UnboundedMap2` (r:1 w:0) + /// Proof: `Pov::UnboundedMap2` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn storage_map_unbounded_both_measured_read(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `229 + i * (8 ±0)` // Estimated: `3693 + i * (8 ±0)` - // Minimum execution time: 3_071_000 picoseconds. - Weight::from_parts(3_487_712, 3693) - // Standard Error: 26 - .saturating_add(Weight::from_parts(748, 0).saturating_mul(i.into())) + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(7_274_226, 3693) + // Standard Error: 280 + .saturating_add(Weight::from_parts(3_282, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(i.into())) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) - /// Storage: Pov UnboundedMap (r:1 w:0) - /// Proof Skipped: Pov UnboundedMap (max_values: None, max_size: None, mode: Measured) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Pov::UnboundedMap` (r:1 w:0) + /// Proof: `Pov::UnboundedMap` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `i` is `[0, 1000]`. fn storage_map_partial_unbounded_read(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `228 + i * (4 ±0)` // Estimated: `3692 + i * (4 ±0)` - // Minimum execution time: 3_150_000 picoseconds. - Weight::from_parts(3_582_963, 3692) - // Standard Error: 18 - .saturating_add(Weight::from_parts(380, 0).saturating_mul(i.into())) + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_507_333, 3692) + // Standard Error: 64 + .saturating_add(Weight::from_parts(982, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 4).saturating_mul(i.into())) } - /// Storage: Pov Map1M (r:1 w:0) - /// Proof: Pov Map1M (max_values: Some(1000000), max_size: Some(36), added: 2511, mode: MaxEncodedLen) - /// Storage: Pov UnboundedMap (r:1 w:0) - /// Proof Skipped: Pov UnboundedMap (max_values: None, max_size: None, mode: Ignored) + /// Storage: `Pov::Map1M` (r:1 w:0) + /// Proof: `Pov::Map1M` (`max_values`: Some(1000000), `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `Pov::UnboundedMap` (r:1 w:0) + /// Proof: `Pov::UnboundedMap` (`max_values`: None, `max_size`: None, mode: `Ignored`) /// The range of component `i` is `[0, 1000]`. fn storage_map_partial_unbounded_ignored_read(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `228 + i * (4 ±0)` // Estimated: `3501 + i * (4 ±0)` - // Minimum execution time: 3_092_000 picoseconds. - Weight::from_parts(3_595_328, 3501) - // Standard Error: 20 - .saturating_add(Weight::from_parts(243, 0).saturating_mul(i.into())) + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(7_285_011, 3501) + // Standard Error: 80 + .saturating_add(Weight::from_parts(1_395, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(Weight::from_parts(0, 4).saturating_mul(i.into())) } @@ -825,24 +823,24 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_705_000 picoseconds. - Weight::from_parts(1_818_000, 0) + // Minimum execution time: 4_000_000 picoseconds. + Weight::from_parts(5_000_000, 0) } fn noop() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 533_000 picoseconds. - Weight::from_parts(587_000, 0) + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 0) } - /// Storage: Pov UnboundedMapTwox (r:65001 w:0) - /// Proof Skipped: Pov UnboundedMapTwox (max_values: None, max_size: None, mode: Measured) + /// Storage: `Pov::UnboundedMapTwox` (r:65001 w:0) + /// Proof: `Pov::UnboundedMapTwox` (`max_values`: None, `max_size`: None, mode: `Measured`) fn storage_iteration() -> Weight { // Proof Size summary in bytes: // Measured: `17985289` // Estimated: `178863754` - // Minimum execution time: 118_753_057_000 picoseconds. - Weight::from_parts(121_396_503_000, 178863754) + // Minimum execution time: 218_275_000_000 picoseconds. + Weight::from_parts(222_603_000_000, 178863754) .saturating_add(RocksDbWeight::get().reads(65001_u64)) } } diff --git a/substrate/frame/support/procedural/src/benchmark.rs b/substrate/frame/support/procedural/src/benchmark.rs index 27c75a7f054..ea53ad263a1 100644 --- a/substrate/frame/support/procedural/src/benchmark.rs +++ b/substrate/frame/support/procedural/src/benchmark.rs @@ -40,10 +40,14 @@ mod keywords { custom_keyword!(benchmarks); custom_keyword!(block); custom_keyword!(extra); + custom_keyword!(pov_mode); custom_keyword!(extrinsic_call); custom_keyword!(skip_meta); custom_keyword!(BenchmarkError); custom_keyword!(Result); + custom_keyword!(MaxEncodedLen); + custom_keyword!(Measured); + custom_keyword!(Ignored); pub const BENCHMARK_TOKEN: &str = stringify!(benchmark); pub const BENCHMARKS_TOKEN: &str = stringify!(benchmarks); @@ -73,51 +77,158 @@ struct RangeArgs { struct BenchmarkAttrs { skip_meta: bool, extra: bool, + pov_mode: Option, } /// Represents a single benchmark option -enum BenchmarkAttrKeyword { +enum BenchmarkAttr { Extra, SkipMeta, + /// How the PoV should be measured. + PoV(PovModeAttr), } -impl syn::parse::Parse for BenchmarkAttrKeyword { +impl syn::parse::Parse for PovModeAttr { + fn parse(input: ParseStream) -> Result { + let _pov: keywords::pov_mode = input.parse()?; + let _eq: Token![=] = input.parse()?; + let root = PovEstimationMode::parse(input)?; + + let mut maybe_content = None; + let _ = || -> Result<()> { + let content; + syn::braced!(content in input); + maybe_content = Some(content); + Ok(()) + }(); + + let per_key = match maybe_content { + Some(content) => { + let per_key = Punctuated::::parse_terminated(&content)?; + per_key.into_iter().collect() + }, + None => Vec::new(), + }; + + Ok(Self { root, per_key }) + } +} + +impl syn::parse::Parse for BenchmarkAttr { fn parse(input: ParseStream) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(keywords::extra) { let _extra: keywords::extra = input.parse()?; - return Ok(BenchmarkAttrKeyword::Extra) + Ok(BenchmarkAttr::Extra) } else if lookahead.peek(keywords::skip_meta) { let _skip_meta: keywords::skip_meta = input.parse()?; - return Ok(BenchmarkAttrKeyword::SkipMeta) + Ok(BenchmarkAttr::SkipMeta) + } else if lookahead.peek(keywords::pov_mode) { + PovModeAttr::parse(input).map(BenchmarkAttr::PoV) + } else { + Err(lookahead.error()) + } + } +} + +/// A `#[pov_mode = .. { .. }]` attribute. +#[derive(Debug, Clone)] +struct PovModeAttr { + /// The root mode for this benchmarks. + root: PovEstimationMode, + /// The pov-mode for a specific key. This overwrites `root` for this key. + per_key: Vec, +} + +/// A single key-value pair inside the `{}` of a `#[pov_mode = .. { .. }]` attribute. +#[derive(Debug, Clone, derive_syn_parse::Parse)] +struct PovModeKeyAttr { + /// A specific storage key for which to set the PoV mode. + key: Path, + _underscore: Token![:], + /// The PoV mode for this key. + mode: PovEstimationMode, +} + +/// How the PoV should be estimated. +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum PovEstimationMode { + /// Use the maximal encoded length as provided by [`codec::MaxEncodedLen`]. + MaxEncodedLen, + /// Measure the accessed value size in the pallet benchmarking and add some trie overhead. + Measured, + /// Do not estimate the PoV size for this storage item or benchmark. + Ignored, +} + +impl syn::parse::Parse for PovEstimationMode { + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + if lookahead.peek(keywords::MaxEncodedLen) { + let _max_encoded_len: keywords::MaxEncodedLen = input.parse()?; + return Ok(PovEstimationMode::MaxEncodedLen) + } else if lookahead.peek(keywords::Measured) { + let _measured: keywords::Measured = input.parse()?; + return Ok(PovEstimationMode::Measured) + } else if lookahead.peek(keywords::Ignored) { + let _ignored: keywords::Ignored = input.parse()?; + return Ok(PovEstimationMode::Ignored) } else { return Err(lookahead.error()) } } } +impl ToString for PovEstimationMode { + fn to_string(&self) -> String { + match self { + PovEstimationMode::MaxEncodedLen => "MaxEncodedLen".into(), + PovEstimationMode::Measured => "Measured".into(), + PovEstimationMode::Ignored => "Ignored".into(), + } + } +} + +impl quote::ToTokens for PovEstimationMode { + fn to_tokens(&self, tokens: &mut TokenStream2) { + match self { + PovEstimationMode::MaxEncodedLen => tokens.extend(quote!(MaxEncodedLen)), + PovEstimationMode::Measured => tokens.extend(quote!(Measured)), + PovEstimationMode::Ignored => tokens.extend(quote!(Ignored)), + } + } +} + impl syn::parse::Parse for BenchmarkAttrs { fn parse(input: ParseStream) -> syn::Result { let mut extra = false; let mut skip_meta = false; - let args = Punctuated::::parse_terminated(&input)?; + let mut pov_mode = None; + let args = Punctuated::::parse_terminated(&input)?; + for arg in args.into_iter() { match arg { - BenchmarkAttrKeyword::Extra => { + BenchmarkAttr::Extra => { if extra { return Err(input.error("`extra` can only be specified once")) } extra = true; }, - BenchmarkAttrKeyword::SkipMeta => { + BenchmarkAttr::SkipMeta => { if skip_meta { return Err(input.error("`skip_meta` can only be specified once")) } skip_meta = true; }, + BenchmarkAttr::PoV(mode) => { + if pov_mode.is_some() { + return Err(input.error("`pov_mode` can only be specified once")) + } + pov_mode = Some(mode); + }, } } - Ok(BenchmarkAttrs { extra, skip_meta }) + Ok(BenchmarkAttrs { extra, skip_meta, pov_mode }) } } @@ -344,6 +455,7 @@ pub fn benchmarks( tokens: TokenStream, instance: bool, ) -> syn::Result { + let krate = generate_access_from_frame_or_crate("frame-benchmarking")?; // gather module info let module: ItemMod = syn::parse(tokens)?; let mod_span = module.span(); @@ -364,6 +476,8 @@ pub fn benchmarks( let mut benchmark_names: Vec = Vec::new(); let mut extra_benchmark_names: Vec = Vec::new(); let mut skip_meta_benchmark_names: Vec = Vec::new(); + // Map benchmarks to PoV modes. + let mut pov_modes = Vec::new(); let (_brace, mut content) = module.content.ok_or(syn::Error::new(mod_span, "Module cannot be empty!"))?; @@ -400,6 +514,25 @@ pub fn benchmarks( } else if benchmark_attrs.skip_meta { skip_meta_benchmark_names.push(name.clone()); } + + if let Some(mode) = benchmark_attrs.pov_mode { + let mut modes = Vec::new(); + // We cannot expand strings here since it is no-std, but syn does not expand bytes. + let name = name.to_string(); + let m = mode.root.to_string(); + modes.push(quote!(("ALL".as_bytes().to_vec(), #m.as_bytes().to_vec()))); + + for attr in mode.per_key.iter() { + // syn always puts spaces in quoted paths: + let key = attr.key.clone().into_token_stream().to_string().replace(" ", ""); + let mode = attr.mode.to_string(); + modes.push(quote!((#key.as_bytes().to_vec(), #mode.as_bytes().to_vec()))); + } + + pov_modes.push( + quote!((#name.as_bytes().to_vec(), #krate::__private::vec![#(#modes),*])), + ); + } } // expand benchmark @@ -419,7 +552,6 @@ pub fn benchmarks( true => quote!(T: Config, I: 'static), }; - let krate = generate_access_from_frame_or_crate("frame-benchmarking")?; let frame_system = generate_access_from_frame_or_crate("frame-system")?; // benchmark name variables @@ -537,6 +669,16 @@ pub fn benchmarks( ]; all_names.retain(|x| !extra.contains(x)); } + let pov_modes: + #krate::__private::Vec<( + #krate::__private::Vec, + #krate::__private::Vec<( + #krate::__private::Vec, + #krate::__private::Vec + )>, + )> = #krate::__private::vec![ + #( #pov_modes ),* + ]; all_names.into_iter().map(|benchmark| { let selected_benchmark = match benchmark { #(#selected_benchmark_mappings), @@ -544,12 +686,13 @@ pub fn benchmarks( _ => panic!("all benchmarks should be selectable") }; let components = >::components(&selected_benchmark); + let name = benchmark.as_bytes().to_vec(); + let modes = pov_modes.iter().find(|p| p.0 == name).map(|p| p.1.clone()); + #krate::BenchmarkMetadata { name: benchmark.as_bytes().to_vec(), components, - // TODO: Not supported by V2 syntax as of yet. - // https://github.com/paritytech/substrate/issues/13132 - pov_modes: #krate::__private::vec![], + pov_modes: modes.unwrap_or_default(), } }).collect::<#krate::__private::Vec<_>>() } diff --git a/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_1.rs b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_1.rs new file mode 100644 index 00000000000..40ef884bf85 --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_1.rs @@ -0,0 +1,31 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use frame_benchmarking::v2::*; + +#[benchmarks] +mod benches { + use super::*; + + #[benchmark(pov_mode = Wrong)] + fn bench() { + #[block] + {} + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_1.stderr b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_1.stderr new file mode 100644 index 00000000000..add80da6307 --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_1.stderr @@ -0,0 +1,5 @@ +error: expected one of: `MaxEncodedLen`, `Measured`, `Ignored` + --> tests/benchmark_ui/bad_attr_pov_mode_1.rs:24:25 + | +24 | #[benchmark(pov_mode = Wrong)] + | ^^^^^ diff --git a/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_2.rs b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_2.rs new file mode 100644 index 00000000000..151bb931e92 --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_2.rs @@ -0,0 +1,33 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use frame_benchmarking::v2::*; + +#[benchmarks] +mod benches { + use super::*; + + #[benchmark(pov_mode = Measured { + Key: Wrong + })] + fn bench() { + #[block] + {} + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_2.stderr b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_2.stderr new file mode 100644 index 00000000000..0f9961afd89 --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_2.stderr @@ -0,0 +1,5 @@ +error: expected one of: `MaxEncodedLen`, `Measured`, `Ignored` + --> tests/benchmark_ui/bad_attr_pov_mode_2.rs:25:8 + | +25 | Key: Wrong + | ^^^^^ diff --git a/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_3.rs b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_3.rs new file mode 100644 index 00000000000..9c5e3801b1a --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_3.rs @@ -0,0 +1,31 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use frame_benchmarking::v2::*; + +#[benchmarks] +mod benches { + use super::*; + + #[benchmark(pov_mode)] + fn bench() { + #[block] + {} + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_3.stderr b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_3.stderr new file mode 100644 index 00000000000..f28a993989a --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_3.stderr @@ -0,0 +1,5 @@ +error: expected `=` + --> tests/benchmark_ui/bad_attr_pov_mode_3.rs:24:22 + | +24 | #[benchmark(pov_mode)] + | ^ diff --git a/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_4.rs b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_4.rs new file mode 100644 index 00000000000..11ec5124d28 --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_4.rs @@ -0,0 +1,31 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use frame_benchmarking::v2::*; + +#[benchmarks] +mod benches { + use super::*; + + #[benchmark(pov_mode =)] + fn bench() { + #[block] + {} + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_4.stderr b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_4.stderr new file mode 100644 index 00000000000..572b6b0815d --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/bad_attr_pov_mode_4.stderr @@ -0,0 +1,5 @@ +error: unexpected end of input, expected one of: `MaxEncodedLen`, `Measured`, `Ignored` + --> tests/benchmark_ui/bad_attr_pov_mode_4.rs:24:24 + | +24 | #[benchmark(pov_mode =)] + | ^ diff --git a/substrate/frame/support/test/tests/benchmark_ui/dup_attr_pov_mode.rs b/substrate/frame/support/test/tests/benchmark_ui/dup_attr_pov_mode.rs new file mode 100644 index 00000000000..f49636d181a --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/dup_attr_pov_mode.rs @@ -0,0 +1,32 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use frame_benchmarking::v2::*; +use frame_support_test::Config; + +#[benchmarks] +mod benches { + use super::*; + + #[benchmark(pov_mode = Measured, pov_mode = MaxEncodedLen)] + fn bench() { + #[block] + {} + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/benchmark_ui/dup_attr_pov_mode.stderr b/substrate/frame/support/test/tests/benchmark_ui/dup_attr_pov_mode.stderr new file mode 100644 index 00000000000..aab91d271a6 --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/dup_attr_pov_mode.stderr @@ -0,0 +1,14 @@ +error: unexpected end of input, `pov_mode` can only be specified once + --> tests/benchmark_ui/dup_attr_pov_mode.rs:25:59 + | +25 | #[benchmark(pov_mode = Measured, pov_mode = MaxEncodedLen)] + | ^ + +error: unused import: `frame_support_test::Config` + --> tests/benchmark_ui/dup_attr_pov_mode.rs:19:5 + | +19 | use frame_support_test::Config; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D unused-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(unused_imports)]` diff --git a/substrate/frame/support/test/tests/benchmark_ui/pass/valid_attr_pov_mode.rs b/substrate/frame/support/test/tests/benchmark_ui/pass/valid_attr_pov_mode.rs new file mode 100644 index 00000000000..35fa1e76ae5 --- /dev/null +++ b/substrate/frame/support/test/tests/benchmark_ui/pass/valid_attr_pov_mode.rs @@ -0,0 +1,74 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +use frame_benchmarking::v2::*; +use frame_support_test::Config; + +#[benchmarks] +mod benches { + use super::*; + + #[benchmark(skip_meta, extra, pov_mode = Measured)] + fn bench1() { + #[block] + {} + } + + #[benchmark(pov_mode = Measured, extra, skip_meta)] + fn bench2() { + #[block] + {} + } + + #[benchmark(extra, pov_mode = Measured { + Pallet: Measured, + Pallet::Storage: MaxEncodedLen, + }, skip_meta)] + fn bench3() { + #[block] + {} + } + + #[benchmark(skip_meta, extra, pov_mode = Measured { + Pallet::Storage: MaxEncodedLen, + Pallet::StorageSubKey: Measured, + })] + fn bench4() { + #[block] + {} + } + + #[benchmark(pov_mode = MaxEncodedLen { + Pallet::Storage: Measured, + Pallet::StorageSubKey: Measured + }, extra, skip_meta)] + fn bench5() { + #[block] + {} + } + + #[benchmark(pov_mode = MaxEncodedLen { + Pallet::Storage: Measured, + Pallet::Storage::Nested: Ignored + }, extra, skip_meta)] + fn bench6() { + #[block] + {} + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/benchmark_ui/pass/valid_basic.rs b/substrate/frame/support/test/tests/benchmark_ui/pass/valid_basic.rs index 126cee8fa6c..5899eb3562a 100644 --- a/substrate/frame/support/test/tests/benchmark_ui/pass/valid_basic.rs +++ b/substrate/frame/support/test/tests/benchmark_ui/pass/valid_basic.rs @@ -22,7 +22,7 @@ use frame_support_test::Config; mod benches { use super::*; - #[benchmark(skip_meta, extra)] + #[benchmark(skip_meta, pov_mode = Measured, extra)] fn bench() { let a = 2 + 2; #[block] diff --git a/substrate/frame/support/test/tests/benchmark_ui/unrecognized_option.stderr b/substrate/frame/support/test/tests/benchmark_ui/unrecognized_option.stderr index bea770b634e..2eb06e396a8 100644 --- a/substrate/frame/support/test/tests/benchmark_ui/unrecognized_option.stderr +++ b/substrate/frame/support/test/tests/benchmark_ui/unrecognized_option.stderr @@ -1,4 +1,4 @@ -error: expected `extra` or `skip_meta` +error: expected one of: `extra`, `skip_meta`, `pov_mode` --> tests/benchmark_ui/unrecognized_option.rs:26:32 | 26 | #[benchmark(skip_meta, extra, bad)] diff --git a/substrate/frame/whitelist/src/benchmarking.rs b/substrate/frame/whitelist/src/benchmarking.rs index 9d356f09a9d..7fb5632fc00 100644 --- a/substrate/frame/whitelist/src/benchmarking.rs +++ b/substrate/frame/whitelist/src/benchmarking.rs @@ -20,58 +20,57 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use frame_benchmarking::v1::{benchmarks, BenchmarkError}; -use frame_support::{ensure, traits::EnsureOrigin}; +use frame_benchmarking::v2::*; +use frame_support::traits::EnsureOrigin; #[cfg(test)] use crate::Pallet as Whitelist; -benchmarks! { - whitelist_call { +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn whitelist_call() -> Result<(), BenchmarkError> { let origin = T::WhitelistOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let call_hash = Default::default(); - }: _(origin, call_hash) - verify { - ensure!( - WhitelistedCall::::contains_key(call_hash), - "call not whitelisted" - ); - ensure!( - T::Preimages::is_requested(&call_hash), - "preimage not requested" - ); + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, call_hash); + + ensure!(WhitelistedCall::::contains_key(call_hash), "call not whitelisted"); + ensure!(T::Preimages::is_requested(&call_hash), "preimage not requested"); + Ok(()) } - remove_whitelisted_call { + #[benchmark] + fn remove_whitelisted_call() -> Result<(), BenchmarkError> { let origin = T::WhitelistOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let call_hash = Default::default(); Pallet::::whitelist_call(origin.clone(), call_hash) .expect("whitelisting call must be successful"); - }: _(origin, call_hash) - verify { - ensure!( - !WhitelistedCall::::contains_key(call_hash), - "whitelist not removed" - ); - ensure!( - !T::Preimages::is_requested(&call_hash), - "preimage still requested" - ); + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, call_hash); + + ensure!(!WhitelistedCall::::contains_key(call_hash), "whitelist not removed"); + ensure!(!T::Preimages::is_requested(&call_hash), "preimage still requested"); + Ok(()) } // We benchmark with the maximum possible size for a call. // If the resulting weight is too big, maybe it worth having a weight which depends // on the size of the call, with a new witness in parameter. - #[pov_mode = MaxEncodedLen { + #[benchmark(pov_mode = MaxEncodedLen { // Use measured PoV size for the Preimages since we pass in a length witness. Preimage::PreimageFor: Measured - }] - dispatch_whitelisted_call { - // NOTE: we remove `10` because we need some bytes to encode the variants and vec length - let n in 1 .. T::Preimages::MAX_LENGTH as u32 - 10; - + })] + // NOTE: we remove `10` because we need some bytes to encode the variants and vec length + fn dispatch_whitelisted_call( + n: Linear<1, { T::Preimages::MAX_LENGTH as u32 - 10 }>, + ) -> Result<(), BenchmarkError> { let origin = T::DispatchWhitelistedOrigin::try_successful_origin() .map_err(|_| BenchmarkError::Weightless)?; let remark = sp_std::vec![1u8; n as usize]; @@ -86,21 +85,16 @@ benchmarks! { T::Preimages::note(encoded_call.into()).unwrap(); - }: _(origin, call_hash, call_encoded_len, call_weight) - verify { - ensure!( - !WhitelistedCall::::contains_key(call_hash), - "whitelist not removed" - ); - ensure!( - !T::Preimages::is_requested(&call_hash), - "preimage still requested" - ); - } + #[extrinsic_call] + _(origin as T::RuntimeOrigin, call_hash, call_encoded_len, call_weight); - dispatch_whitelisted_call_with_preimage { - let n in 1 .. 10_000; + ensure!(!WhitelistedCall::::contains_key(call_hash), "whitelist not removed"); + ensure!(!T::Preimages::is_requested(&call_hash), "preimage still requested"); + Ok(()) + } + #[benchmark] + fn dispatch_whitelisted_call_with_preimage(n: Linear<1, 10_000>) -> Result<(), BenchmarkError> { let origin = T::DispatchWhitelistedOrigin::try_successful_origin() .map_err(|_| BenchmarkError::Weightless)?; let remark = sp_std::vec![1u8; n as usize]; @@ -110,16 +104,13 @@ benchmarks! { Pallet::::whitelist_call(origin.clone(), call_hash) .expect("whitelisting call must be successful"); - }: _(origin, Box::new(call)) - verify { - ensure!( - !WhitelistedCall::::contains_key(call_hash), - "whitelist not removed" - ); - ensure!( - !T::Preimages::is_requested(&call_hash), - "preimage still requested" - ); + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, Box::new(call)); + + ensure!(!WhitelistedCall::::contains_key(call_hash), "whitelist not removed"); + ensure!(!T::Preimages::is_requested(&call_hash), "preimage still requested"); + Ok(()) } impl_benchmark_test_suite!(Whitelist, crate::mock::new_test_ext(), crate::mock::Test); -- GitLab From 817870e3b25cebb3dd9c0934bcafcafb2532d96a Mon Sep 17 00:00:00 2001 From: Matteo Muraca <56828990+muraca@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:55:23 +0100 Subject: [PATCH 141/188] Removed `pallet::getter` usage from Beefy and MMR pallets (#3740) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of #3326 cc @kianenigma @ggwpez @liamaharon polkadot address: 12poSUQPtcF1HUPQGY3zZu2P8emuW9YnsPduA4XG3oCEfJVp --------- Signed-off-by: Matteo Muraca --- polkadot/runtime/rococo/src/lib.rs | 6 +-- polkadot/runtime/westend/src/lib.rs | 6 +-- prdoc/pr_3740.prdoc | 18 +++++++ substrate/bin/node/runtime/src/lib.rs | 6 +-- substrate/frame/beefy-mmr/src/lib.rs | 10 ++-- substrate/frame/beefy-mmr/src/tests.rs | 4 +- substrate/frame/beefy/src/equivocation.rs | 2 +- substrate/frame/beefy/src/lib.rs | 48 ++++++++----------- substrate/frame/beefy/src/tests.rs | 26 +++++----- .../frame/merkle-mountain-range/src/lib.rs | 13 +++-- .../merkle-mountain-range/src/mmr/storage.rs | 6 +-- .../frame/merkle-mountain-range/src/tests.rs | 8 ++-- 12 files changed, 81 insertions(+), 72 deletions(-) create mode 100644 prdoc/pr_3740.prdoc diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 1f51258df08..f68870c98ea 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -1991,7 +1991,7 @@ sp_api::impl_runtime_apis! { #[api_version(3)] impl beefy_primitives::BeefyApi for Runtime { fn beefy_genesis() -> Option { - Beefy::genesis_block() + pallet_beefy::GenesisBlock::::get() } fn validator_set() -> Option> { @@ -2029,11 +2029,11 @@ sp_api::impl_runtime_apis! { #[api_version(2)] impl mmr::MmrApi for Runtime { fn mmr_root() -> Result { - Ok(Mmr::mmr_root()) + Ok(pallet_mmr::RootHash::::get()) } fn mmr_leaf_count() -> Result { - Ok(Mmr::mmr_leaves()) + Ok(pallet_mmr::NumberOfLeaves::::get()) } fn generate_proof( diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 15d78706d3a..f1d8841989c 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -2015,7 +2015,7 @@ sp_api::impl_runtime_apis! { impl beefy_primitives::BeefyApi for Runtime { fn beefy_genesis() -> Option { - Beefy::genesis_block() + pallet_beefy::GenesisBlock::::get() } fn validator_set() -> Option> { @@ -2052,11 +2052,11 @@ sp_api::impl_runtime_apis! { impl mmr::MmrApi for Runtime { fn mmr_root() -> Result { - Ok(Mmr::mmr_root()) + Ok(pallet_mmr::RootHash::::get()) } fn mmr_leaf_count() -> Result { - Ok(Mmr::mmr_leaves()) + Ok(pallet_mmr::NumberOfLeaves::::get()) } fn generate_proof( diff --git a/prdoc/pr_3740.prdoc b/prdoc/pr_3740.prdoc new file mode 100644 index 00000000000..03df8ec5fea --- /dev/null +++ b/prdoc/pr_3740.prdoc @@ -0,0 +1,18 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Removed `pallet::getter` usage from Beefy and MMR pallets + +doc: + - audience: Runtime Dev + description: | + This PR removes `pallet::getter` usage from `pallet-beefy`, `pallet-beefy-mmr` and `pallet-mmr`, and updates dependant code and runtimes accordingly. + The syntax `StorageItem::::get()` should be used instead. + +crates: + - name: pallet-beefy + - name: pallet-beefy-mmr + - name: pallet-mmr + - name: kitchensink-runtime + - name: rococo-runtime + - name: westend-runtime diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 0852264ef68..ca7e14f6eb1 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -2979,7 +2979,7 @@ impl_runtime_apis! { #[api_version(3)] impl sp_consensus_beefy::BeefyApi for Runtime { fn beefy_genesis() -> Option { - Beefy::genesis_block() + pallet_beefy::GenesisBlock::::get() } fn validator_set() -> Option> { @@ -3018,11 +3018,11 @@ impl_runtime_apis! { BlockNumber, > for Runtime { fn mmr_root() -> Result { - Ok(Mmr::mmr_root()) + Ok(pallet_mmr::RootHash::::get()) } fn mmr_leaf_count() -> Result { - Ok(Mmr::mmr_leaves()) + Ok(pallet_mmr::NumberOfLeaves::::get()) } fn generate_proof( diff --git a/substrate/frame/beefy-mmr/src/lib.rs b/substrate/frame/beefy-mmr/src/lib.rs index fa3caba7977..e423f1b342f 100644 --- a/substrate/frame/beefy-mmr/src/lib.rs +++ b/substrate/frame/beefy-mmr/src/lib.rs @@ -68,7 +68,7 @@ where ::BeefyId, >::MmrRoot(*root)), ); - >::deposit_log(digest); + frame_system::Pallet::::deposit_log(digest); } } @@ -126,7 +126,6 @@ pub mod pallet { /// Details of current BEEFY authority set. #[pallet::storage] - #[pallet::getter(fn beefy_authorities)] pub type BeefyAuthorities = StorageValue<_, BeefyAuthoritySet>, ValueQuery>; @@ -134,7 +133,6 @@ pub mod pallet { /// /// This storage entry is used as cache for calls to `update_beefy_next_authority_set`. #[pallet::storage] - #[pallet::getter(fn beefy_next_authorities)] pub type BeefyNextAuthorities = StorageValue<_, BeefyNextAuthoritySet>, ValueQuery>; } @@ -152,7 +150,7 @@ impl LeafDataProvider for Pallet { version: T::LeafVersion::get(), parent_number_and_hash: ParentNumberAndHash::::leaf_data(), leaf_extra: T::BeefyDataProvider::extra_data(), - beefy_next_authority_set: Pallet::::beefy_next_authorities(), + beefy_next_authority_set: BeefyNextAuthorities::::get(), } } } @@ -177,12 +175,12 @@ where impl Pallet { /// Return the currently active BEEFY authority set proof. pub fn authority_set_proof() -> BeefyAuthoritySet> { - Pallet::::beefy_authorities() + BeefyAuthorities::::get() } /// Return the next/queued BEEFY authority set proof. pub fn next_authority_set_proof() -> BeefyNextAuthoritySet> { - Pallet::::beefy_next_authorities() + BeefyNextAuthorities::::get() } /// Returns details of a BEEFY authority set. diff --git a/substrate/frame/beefy-mmr/src/tests.rs b/substrate/frame/beefy-mmr/src/tests.rs index ec756f83dff..fac799bf64e 100644 --- a/substrate/frame/beefy-mmr/src/tests.rs +++ b/substrate/frame/beefy-mmr/src/tests.rs @@ -107,7 +107,7 @@ fn should_contain_valid_leaf_data() { let mut ext = new_test_ext(vec![1, 2, 3, 4]); let parent_hash = ext.execute_with(|| { init_block(1); - >::parent_hash() + frame_system::Pallet::::parent_hash() }); let mmr_leaf = read_mmr_leaf(&mut ext, node_offchain_key(0, parent_hash)); @@ -132,7 +132,7 @@ fn should_contain_valid_leaf_data() { // build second block on top let parent_hash = ext.execute_with(|| { init_block(2); - >::parent_hash() + frame_system::Pallet::::parent_hash() }); let mmr_leaf = read_mmr_leaf(&mut ext, node_offchain_key(1, parent_hash)); diff --git a/substrate/frame/beefy/src/equivocation.rs b/substrate/frame/beefy/src/equivocation.rs index 0a7ede327c9..bbc6eae6af2 100644 --- a/substrate/frame/beefy/src/equivocation.rs +++ b/substrate/frame/beefy/src/equivocation.rs @@ -190,7 +190,7 @@ where evidence: EquivocationEvidenceFor, ) -> Result<(), DispatchError> { let (equivocation_proof, key_owner_proof) = evidence; - let reporter = reporter.or_else(|| >::author()); + let reporter = reporter.or_else(|| pallet_authorship::Pallet::::author()); let offender = equivocation_proof.offender_id().clone(); // We check the equivocation within the context of its set id (and diff --git a/substrate/frame/beefy/src/lib.rs b/substrate/frame/beefy/src/lib.rs index 0760446753a..87304eba8ba 100644 --- a/substrate/frame/beefy/src/lib.rs +++ b/substrate/frame/beefy/src/lib.rs @@ -120,20 +120,17 @@ pub mod pallet { /// The current authorities set #[pallet::storage] - #[pallet::getter(fn authorities)] - pub(super) type Authorities = + pub type Authorities = StorageValue<_, BoundedVec, ValueQuery>; /// The current validator set id #[pallet::storage] - #[pallet::getter(fn validator_set_id)] - pub(super) type ValidatorSetId = + pub type ValidatorSetId = StorageValue<_, sp_consensus_beefy::ValidatorSetId, ValueQuery>; /// Authorities set scheduled to be used with the next session #[pallet::storage] - #[pallet::getter(fn next_authorities)] - pub(super) type NextAuthorities = + pub type NextAuthorities = StorageValue<_, BoundedVec, ValueQuery>; /// A mapping from BEEFY set ID to the index of the *most recent* session for which its @@ -147,17 +144,14 @@ pub mod pallet { /// /// TWOX-NOTE: `ValidatorSetId` is not under user control. #[pallet::storage] - #[pallet::getter(fn session_for_set)] - pub(super) type SetIdSession = + pub type SetIdSession = StorageMap<_, Twox64Concat, sp_consensus_beefy::ValidatorSetId, SessionIndex>; /// Block number where BEEFY consensus is enabled/started. /// By changing this (through privileged `set_new_genesis()`), BEEFY consensus is effectively /// restarted from the newly set block number. #[pallet::storage] - #[pallet::getter(fn genesis_block)] - pub(super) type GenesisBlock = - StorageValue<_, Option>, ValueQuery>; + pub type GenesisBlock = StorageValue<_, Option>, ValueQuery>; #[pallet::genesis_config] pub struct GenesisConfig { @@ -186,7 +180,7 @@ pub mod pallet { // we panic here as runtime maintainers can simply reconfigure genesis and restart // the chain easily .expect("Authorities vec too big"); - >::put(&self.genesis_block); + GenesisBlock::::put(&self.genesis_block); } } @@ -303,8 +297,8 @@ pub mod pallet { impl Pallet { /// Return the current active BEEFY validator set. pub fn validator_set() -> Option> { - let validators: BoundedVec = Self::authorities(); - let id: sp_consensus_beefy::ValidatorSetId = Self::validator_set_id(); + let validators: BoundedVec = Authorities::::get(); + let id: sp_consensus_beefy::ValidatorSetId = ValidatorSetId::::get(); ValidatorSet::::new(validators, id) } @@ -326,19 +320,19 @@ impl Pallet { new: BoundedVec, queued: BoundedVec, ) { - >::put(&new); + Authorities::::put(&new); - let new_id = Self::validator_set_id() + 1u64; - >::put(new_id); + let new_id = ValidatorSetId::::get() + 1u64; + ValidatorSetId::::put(new_id); - >::put(&queued); + NextAuthorities::::put(&queued); if let Some(validator_set) = ValidatorSet::::new(new, new_id) { let log = DigestItem::Consensus( BEEFY_ENGINE_ID, ConsensusLog::AuthoritiesChange(validator_set.clone()).encode(), ); - >::deposit_log(log); + frame_system::Pallet::::deposit_log(log); let next_id = new_id + 1; if let Some(next_validator_set) = ValidatorSet::::new(queued, next_id) { @@ -355,7 +349,7 @@ impl Pallet { return Ok(()) } - if !>::get().is_empty() { + if !Authorities::::get().is_empty() { return Err(()) } @@ -364,10 +358,10 @@ impl Pallet { .map_err(|_| ())?; let id = GENESIS_AUTHORITY_SET_ID; - >::put(bounded_authorities); - >::put(id); + Authorities::::put(bounded_authorities); + ValidatorSetId::::put(id); // Like `pallet_session`, initialize the next validator set as well. - >::put(bounded_authorities); + NextAuthorities::::put(bounded_authorities); if let Some(validator_set) = ValidatorSet::::new(authorities.clone(), id) { let next_id = id + 1; @@ -442,9 +436,9 @@ where // We want to have at least one BEEFY mandatory block per session. Self::change_authorities(bounded_next_authorities, bounded_next_queued_authorities); - let validator_set_id = Self::validator_set_id(); + let validator_set_id = ValidatorSetId::::get(); // Update the mapping for the new set id that corresponds to the latest session (i.e. now). - let session_index = >::current_index(); + let session_index = pallet_session::Pallet::::current_index(); SetIdSession::::insert(validator_set_id, &session_index); // Prune old entry if limit reached. let max_set_id_session_entries = T::MaxSetIdSessionEntries::get().max(1); @@ -459,13 +453,13 @@ where ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), ); - >::deposit_log(log); + frame_system::Pallet::::deposit_log(log); } } impl IsMember for Pallet { fn is_member(authority_id: &T::BeefyId) -> bool { - Self::authorities().iter().any(|id| id == authority_id) + Authorities::::get().iter().any(|id| id == authority_id) } } diff --git a/substrate/frame/beefy/src/tests.rs b/substrate/frame/beefy/src/tests.rs index 453cf19a4fe..2950264e0c3 100644 --- a/substrate/frame/beefy/src/tests.rs +++ b/substrate/frame/beefy/src/tests.rs @@ -31,7 +31,7 @@ use sp_consensus_beefy::{ }; use sp_runtime::DigestItem; -use crate::{mock::*, Call, Config, Error, Weight, WeightInfo}; +use crate::{self as beefy, mock::*, Call, Config, Error, Weight, WeightInfo}; fn init_block(block: u64) { System::set_block_number(block); @@ -48,15 +48,15 @@ fn genesis_session_initializes_authorities() { let want = authorities.clone(); new_test_ext_raw_authorities(authorities).execute_with(|| { - let authorities = Beefy::authorities(); + let authorities = beefy::Authorities::::get(); assert_eq!(authorities.len(), 4); assert_eq!(want[0], authorities[0]); assert_eq!(want[1], authorities[1]); - assert!(Beefy::validator_set_id() == 0); + assert!(beefy::ValidatorSetId::::get() == 0); - let next_authorities = Beefy::next_authorities(); + let next_authorities = beefy::NextAuthorities::::get(); assert_eq!(next_authorities.len(), 4); assert_eq!(want[0], next_authorities[0]); @@ -70,11 +70,11 @@ fn session_change_updates_authorities() { let want_validators = authorities.clone(); new_test_ext(vec![1, 2, 3, 4]).execute_with(|| { - assert!(0 == Beefy::validator_set_id()); + assert!(0 == beefy::ValidatorSetId::::get()); init_block(1); - assert!(1 == Beefy::validator_set_id()); + assert!(1 == beefy::ValidatorSetId::::get()); let want = beefy_log(ConsensusLog::AuthoritiesChange( ValidatorSet::new(want_validators, 1).unwrap(), @@ -85,7 +85,7 @@ fn session_change_updates_authorities() { init_block(2); - assert!(2 == Beefy::validator_set_id()); + assert!(2 == beefy::ValidatorSetId::::get()); let want = beefy_log(ConsensusLog::AuthoritiesChange( ValidatorSet::new(vec![mock_beefy_id(2), mock_beefy_id(4)], 2).unwrap(), @@ -101,7 +101,7 @@ fn session_change_updates_next_authorities() { let want = vec![mock_beefy_id(1), mock_beefy_id(2), mock_beefy_id(3), mock_beefy_id(4)]; new_test_ext(vec![1, 2, 3, 4]).execute_with(|| { - let next_authorities = Beefy::next_authorities(); + let next_authorities = beefy::NextAuthorities::::get(); assert_eq!(next_authorities.len(), 4); assert_eq!(want[0], next_authorities[0]); @@ -111,7 +111,7 @@ fn session_change_updates_next_authorities() { init_block(1); - let next_authorities = Beefy::next_authorities(); + let next_authorities = beefy::NextAuthorities::::get(); assert_eq!(next_authorities.len(), 2); assert_eq!(want[1], next_authorities[0]); @@ -177,7 +177,7 @@ fn cleans_up_old_set_id_session_mappings() { // we should have a session id mapping for all the set ids from // `max_set_id_session_entries` eras we have observed for i in 1..=max_set_id_session_entries { - assert!(Beefy::session_for_set(i as u64).is_some()); + assert!(beefy::SetIdSession::::get(i as u64).is_some()); } // go through another `max_set_id_session_entries` sessions @@ -185,12 +185,12 @@ fn cleans_up_old_set_id_session_mappings() { // we should keep tracking the new mappings for new sessions for i in max_set_id_session_entries + 1..=max_set_id_session_entries * 2 { - assert!(Beefy::session_for_set(i as u64).is_some()); + assert!(beefy::SetIdSession::::get(i as u64).is_some()); } // but the old ones should have been pruned by now for i in 1..=max_set_id_session_entries { - assert!(Beefy::session_for_set(i as u64).is_none()); + assert!(beefy::SetIdSession::::get(i as u64).is_none()); } }); } @@ -804,7 +804,7 @@ fn set_new_genesis_works() { assert_ok!(Beefy::set_new_genesis(RuntimeOrigin::root(), new_genesis_delay,)); let expected = System::block_number() + new_genesis_delay; // verify new genesis was set - assert_eq!(Beefy::genesis_block(), Some(expected)); + assert_eq!(beefy::GenesisBlock::::get(), Some(expected)); // setting delay < 1 should fail assert_err!( diff --git a/substrate/frame/merkle-mountain-range/src/lib.rs b/substrate/frame/merkle-mountain-range/src/lib.rs index 664f4bc7390..e3eb0dc8cf5 100644 --- a/substrate/frame/merkle-mountain-range/src/lib.rs +++ b/substrate/frame/merkle-mountain-range/src/lib.rs @@ -183,7 +183,6 @@ pub mod pallet { /// Latest MMR Root hash. #[pallet::storage] - #[pallet::getter(fn mmr_root_hash)] pub type RootHash, I: 'static = ()> = StorageValue<_, HashOf, ValueQuery>; /// Current size of the MMR (number of leaves). @@ -204,7 +203,7 @@ pub mod pallet { impl, I: 'static> Hooks> for Pallet { fn on_initialize(_n: BlockNumberFor) -> Weight { use primitives::LeafDataProvider; - let leaves = Self::mmr_leaves(); + let leaves = NumberOfLeaves::::get(); let peaks_before = sp_mmr_primitives::utils::NodesUtils::new(leaves).number_of_peaks(); let data = T::LeafData::leaf_data(); @@ -225,8 +224,8 @@ pub mod pallet { }; >::on_new_root(&root); - >::put(leaves); - >::put(root); + NumberOfLeaves::::put(leaves); + RootHash::::put(root); let peaks_after = sp_mmr_primitives::utils::NodesUtils::new(leaves).number_of_peaks(); @@ -301,7 +300,7 @@ impl, I: 'static> Pallet { { let first_mmr_block = utils::first_mmr_block_num::>( >::block_number(), - Self::mmr_leaves(), + NumberOfLeaves::::get(), )?; utils::block_num_to_leaf_index::>(block_num, first_mmr_block) @@ -341,7 +340,7 @@ impl, I: 'static> Pallet { /// Return the on-chain MMR root hash. pub fn mmr_root() -> HashOf { - Self::mmr_root_hash() + RootHash::::get() } /// Verify MMR proof for given `leaves`. @@ -354,7 +353,7 @@ impl, I: 'static> Pallet { leaves: Vec>, proof: primitives::Proof>, ) -> Result<(), primitives::Error> { - if proof.leaf_count > Self::mmr_leaves() || + if proof.leaf_count > NumberOfLeaves::::get() || proof.leaf_count == 0 || (proof.items.len().saturating_add(leaves.len())) as u64 > proof.leaf_count { diff --git a/substrate/frame/merkle-mountain-range/src/mmr/storage.rs b/substrate/frame/merkle-mountain-range/src/mmr/storage.rs index 03039be83ac..96a20c3445e 100644 --- a/substrate/frame/merkle-mountain-range/src/mmr/storage.rs +++ b/substrate/frame/merkle-mountain-range/src/mmr/storage.rs @@ -111,7 +111,7 @@ where L: primitives::FullLeaf, { fn get_elem(&self, pos: NodeIndex) -> mmr_lib::Result>> { - Ok(>::get(pos).map(Node::Hash)) + Ok(Nodes::::get(pos).map(Node::Hash)) } fn append(&mut self, pos: NodeIndex, elems: Vec>) -> mmr_lib::Result<()> { @@ -147,7 +147,7 @@ where for elem in elems { // On-chain we are going to only store new peaks. if peaks_to_store.next_if_eq(&node_index).is_some() { - >::insert(node_index, elem.hash()); + Nodes::::insert(node_index, elem.hash()); } // We are storing full node off-chain (using indexing API). Self::store_to_offchain(node_index, parent_hash, &elem); @@ -164,7 +164,7 @@ where // And remove all remaining items from `peaks_before` collection. for pos in peaks_to_prune { - >::remove(pos); + Nodes::::remove(pos); } Ok(()) diff --git a/substrate/frame/merkle-mountain-range/src/tests.rs b/substrate/frame/merkle-mountain-range/src/tests.rs index 429df75182e..88de7511c9f 100644 --- a/substrate/frame/merkle-mountain-range/src/tests.rs +++ b/substrate/frame/merkle-mountain-range/src/tests.rs @@ -608,9 +608,9 @@ fn verification_should_be_stateless() { let mut ext = new_test_ext(); let (root_6, root_7) = ext.execute_with(|| { add_blocks(6); - let root_6 = crate::Pallet::::mmr_root_hash(); + let root_6 = crate::Pallet::::mmr_root(); add_blocks(1); - let root_7 = crate::Pallet::::mmr_root_hash(); + let root_7 = crate::Pallet::::mmr_root(); (root_6, root_7) }); ext.persist_offchain_overlay(); @@ -656,9 +656,9 @@ fn should_verify_batch_proof_statelessly() { let mut ext = new_test_ext(); let (root_6, root_7) = ext.execute_with(|| { add_blocks(6); - let root_6 = crate::Pallet::::mmr_root_hash(); + let root_6 = crate::Pallet::::mmr_root(); add_blocks(1); - let root_7 = crate::Pallet::::mmr_root_hash(); + let root_7 = crate::Pallet::::mmr_root(); (root_6, root_7) }); ext.persist_offchain_overlay(); -- GitLab From 923f27ccabe802cf1e7a4f31fa94ba8039b6be2c Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Tue, 19 Mar 2024 16:01:22 +0200 Subject: [PATCH 142/188] rpc: Enable `transaction_unstable_broadcast` RPC V2 API (#3713) This PR enables the `transaction_unstable_broadcast ` and `transaction_unstable_stop` RPC API. Since the API is unstable, we don't need to expose this in the release notes. After merging this, we could validate the API in subxt and stabilize it. Spec PR that stabilizes the API: https://github.com/paritytech/json-rpc-interface-spec/pull/139 cc @paritytech/subxt-team Signed-off-by: Alexandru Vasile --- substrate/client/service/src/builder.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs index 31d63c6a81d..e71313428da 100644 --- a/substrate/client/service/src/builder.rs +++ b/substrate/client/service/src/builder.rs @@ -64,7 +64,9 @@ use sc_rpc::{ DenyUnsafe, SubscriptionTaskExecutor, }; use sc_rpc_spec_v2::{ - archive::ArchiveApiServer, chain_head::ChainHeadApiServer, transaction::TransactionApiServer, + archive::ArchiveApiServer, + chain_head::ChainHeadApiServer, + transaction::{TransactionApiServer, TransactionBroadcastApiServer}, }; use sc_telemetry::{telemetry, ConnectionMessage, Telemetry, TelemetryHandle, SUBSTRATE_INFO}; use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool}; @@ -653,6 +655,13 @@ where (chain, state, child_state) }; + let transaction_broadcast_rpc_v2 = sc_rpc_spec_v2::transaction::TransactionBroadcast::new( + client.clone(), + transaction_pool.clone(), + task_executor.clone(), + ) + .into_rpc(); + let transaction_v2 = sc_rpc_spec_v2::transaction::Transaction::new( client.clone(), transaction_pool.clone(), @@ -708,6 +717,9 @@ where // Part of the RPC v2 spec. rpc_api.merge(transaction_v2).map_err(|e| Error::Application(e.into()))?; + rpc_api + .merge(transaction_broadcast_rpc_v2) + .map_err(|e| Error::Application(e.into()))?; rpc_api.merge(chain_head_v2).map_err(|e| Error::Application(e.into()))?; // Part of the old RPC spec. -- GitLab From 5fd72a1f5e7f4db02b4962fb146e4b8d154a485c Mon Sep 17 00:00:00 2001 From: ordian Date: Tue, 19 Mar 2024 16:01:26 +0100 Subject: [PATCH 143/188] collator-side: send parent head data (#3521) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On top of #3302. We want the validators to upgrade first before we add changes to the collation side to send the new variants, which is why this part is extracted into a separate PR. The detection of when to send the parent head is based on the core assignments at the relay parent of the candidate. We probably want to make it more flexible in the future, but for now, it will work for a simple use case when a para always has multiple cores assigned to it. --------- Signed-off-by: Matteo Muraca Signed-off-by: dependabot[bot] Co-authored-by: Matteo Muraca <56828990+muraca@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Juan Ignacio Rios <54085674+JuaniRios@users.noreply.github.com> Co-authored-by: Branislav Kontur Co-authored-by: Bastian Köcher --- cumulus/polkadot-parachain/Cargo.toml | 10 +- .../node/network/collator-protocol/Cargo.toml | 4 + .../src/collator_side/collation.rs | 9 +- .../src/collator_side/mod.rs | 85 ++++++++----- .../src/collator_side/tests/mod.rs | 15 +++ .../tests/prospective_parachains.rs | 113 ++++++++++++++++++ polkadot/node/service/Cargo.toml | 9 +- polkadot/node/subsystem-types/src/messages.rs | 12 +- prdoc/pr_3521.prdoc | 12 ++ 9 files changed, 222 insertions(+), 47 deletions(-) create mode 100644 prdoc/pr_3521.prdoc diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index 70423856d34..37b7be75ef9 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -42,7 +42,10 @@ jsonrpsee = { version = "0.22", features = ["server"] } people-rococo-runtime = { path = "../parachains/runtimes/people/people-rococo" } people-westend-runtime = { path = "../parachains/runtimes/people/people-westend" } parachains-common = { path = "../parachains/common" } -testnet-parachains-constants = { path = "../parachains/runtimes/constants", default-features = false, features = ["rococo", "westend"] } +testnet-parachains-constants = { path = "../parachains/runtimes/constants", default-features = false, features = [ + "rococo", + "westend", +] } # Substrate frame-benchmarking = { path = "../../substrate/frame/benchmarking" } @@ -168,6 +171,5 @@ try-runtime = [ "shell-runtime/try-runtime", "sp-runtime/try-runtime", ] -fast-runtime = [ - "bridge-hub-rococo-runtime/fast-runtime", -] +fast-runtime = ["bridge-hub-rococo-runtime/fast-runtime"] +elastic-scaling-experimental = ["polkadot-service/elastic-scaling-experimental"] diff --git a/polkadot/node/network/collator-protocol/Cargo.toml b/polkadot/node/network/collator-protocol/Cargo.toml index f0f8be0f7ba..cfd88df958c 100644 --- a/polkadot/node/network/collator-protocol/Cargo.toml +++ b/polkadot/node/network/collator-protocol/Cargo.toml @@ -41,3 +41,7 @@ parity-scale-codec = { version = "3.6.1", features = ["std"] } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } + +[features] +default = [] +elastic-scaling-experimental = [] diff --git a/polkadot/node/network/collator-protocol/src/collator_side/collation.rs b/polkadot/node/network/collator-protocol/src/collator_side/collation.rs index dc1ee725462..57e1479a449 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/collation.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/collation.rs @@ -27,7 +27,8 @@ use polkadot_node_network_protocol::{ PeerId, }; use polkadot_node_primitives::PoV; -use polkadot_primitives::{CandidateHash, CandidateReceipt, Hash, HeadData, Id as ParaId}; +use polkadot_node_subsystem::messages::ParentHeadData; +use polkadot_primitives::{CandidateHash, CandidateReceipt, Hash, Id as ParaId}; /// The status of a collation as seen from the collator. pub enum CollationStatus { @@ -59,12 +60,10 @@ impl CollationStatus { pub struct Collation { /// Candidate receipt. pub receipt: CandidateReceipt, - /// Parent head-data hash. - pub parent_head_data_hash: Hash, /// Proof to verify the state transition of the parachain. pub pov: PoV, - /// Parent head-data needed for elastic scaling. - pub parent_head_data: HeadData, + /// Parent head-data (or just hash). + pub parent_head_data: ParentHeadData, /// Collation status. pub status: CollationStatus, } diff --git a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs index 19cc1eb1a57..9f306f288a1 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs @@ -40,7 +40,8 @@ use polkadot_node_primitives::{CollationSecondedSignal, PoV, Statement}; use polkadot_node_subsystem::{ jaeger, messages::{ - CollatorProtocolMessage, NetworkBridgeEvent, NetworkBridgeTxMessage, RuntimeApiMessage, + CollatorProtocolMessage, NetworkBridgeEvent, NetworkBridgeTxMessage, ParentHeadData, + RuntimeApiMessage, }, overseer, CollatorProtocolSenderTrait, FromOrchestra, OverseerSignal, PerLeafSpan, }; @@ -395,12 +396,11 @@ async fn distribute_collation( return Ok(()) } - // Determine which core the para collated-on is assigned to. + // Determine which core(s) the para collated-on is assigned to. // If it is not scheduled then ignore the message. - let (our_core, num_cores) = - match determine_core(ctx.sender(), id, candidate_relay_parent, relay_parent_mode).await? { - Some(core) => core, - None => { + let (our_cores, num_cores) = + match determine_cores(ctx.sender(), id, candidate_relay_parent, relay_parent_mode).await? { + (cores, _num_cores) if cores.is_empty() => { gum::warn!( target: LOG_TARGET, para_id = %id, @@ -409,8 +409,20 @@ async fn distribute_collation( return Ok(()) }, + (cores, num_cores) => (cores, num_cores), }; + let elastic_scaling = our_cores.len() > 1; + if elastic_scaling { + gum::debug!( + target: LOG_TARGET, + para_id = %id, + cores = ?our_cores, + "{} is assigned to {} cores at {}", id, our_cores.len(), candidate_relay_parent, + ); + } + + let our_core = our_cores[0]; // Determine the group on that core. // // When prospective parachains are disabled, candidate relay parent here is @@ -464,15 +476,15 @@ async fn distribute_collation( state.collation_result_senders.insert(candidate_hash, result_sender); } + let parent_head_data = if elastic_scaling { + ParentHeadData::WithData { hash: parent_head_data_hash, head_data: parent_head_data } + } else { + ParentHeadData::OnlyHash(parent_head_data_hash) + }; + per_relay_parent.collations.insert( candidate_hash, - Collation { - receipt, - parent_head_data_hash, - pov, - parent_head_data, - status: CollationStatus::Created, - }, + Collation { receipt, pov, parent_head_data, status: CollationStatus::Created }, ); // If prospective parachains are disabled, a leaf should be known to peer. @@ -513,15 +525,17 @@ async fn distribute_collation( Ok(()) } -/// Get the Id of the Core that is assigned to the para being collated on if any +/// Get the core indices that are assigned to the para being collated on if any /// and the total number of cores. -async fn determine_core( +async fn determine_cores( sender: &mut impl overseer::SubsystemSender, para_id: ParaId, relay_parent: Hash, relay_parent_mode: ProspectiveParachainsMode, -) -> Result> { +) -> Result<(Vec, usize)> { let cores = get_availability_cores(sender, relay_parent).await?; + let n_cores = cores.len(); + let mut assigned_cores = Vec::new(); for (idx, core) in cores.iter().enumerate() { let core_para_id = match core { @@ -538,11 +552,11 @@ async fn determine_core( }; if core_para_id == Some(para_id) { - return Ok(Some(((idx as u32).into(), cores.len()))) + assigned_cores.push(CoreIndex::from(idx as u32)); } } - Ok(None) + Ok((assigned_cores, n_cores)) } /// Validators of a particular group index. @@ -725,7 +739,7 @@ async fn advertise_collation( let wire_message = protocol_v2::CollatorProtocolMessage::AdvertiseCollation { relay_parent, candidate_hash: *candidate_hash, - parent_head_data_hash: collation.parent_head_data_hash, + parent_head_data_hash: collation.parent_head_data.hash(), }; Versioned::V2(protocol_v2::CollationProtocol::CollatorProtocol(wire_message)) }, @@ -849,7 +863,7 @@ async fn send_collation( request: VersionedCollationRequest, receipt: CandidateReceipt, pov: PoV, - _parent_head_data: HeadData, + parent_head_data: ParentHeadData, ) { let (tx, rx) = oneshot::channel(); @@ -857,20 +871,25 @@ async fn send_collation( let peer_id = request.peer_id(); let candidate_hash = receipt.hash(); - // The response payload is the same for v1 and v2 versions of protocol - // and doesn't have v2 alias for simplicity. - // For now, we don't send parent head data to the collation requester. - let result = - // if assigned_multiple_cores { - // Ok(request_v1::CollationFetchingResponse::CollationWithParentHeadData { - // receipt, - // pov, - // parent_head_data, - // }) - // } else { + #[cfg(feature = "elastic-scaling-experimental")] + let result = match parent_head_data { + ParentHeadData::WithData { head_data, .. } => + Ok(request_v2::CollationFetchingResponse::CollationWithParentHeadData { + receipt, + pov, + parent_head_data: head_data, + }), + ParentHeadData::OnlyHash(_) => + Ok(request_v1::CollationFetchingResponse::Collation(receipt, pov)), + }; + #[cfg(not(feature = "elastic-scaling-experimental"))] + let result = { + // suppress unused warning + let _parent_head_data = parent_head_data; + Ok(request_v1::CollationFetchingResponse::Collation(receipt, pov)) - // } - ; + }; + let response = OutgoingResponse { result, reputation_changes: Vec::new(), sent_feedback: Some(tx) }; diff --git a/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs index beda941d37a..38e6780eb7d 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs @@ -142,6 +142,21 @@ impl Default for TestState { } impl TestState { + /// Adds a few more scheduled cores to the state for the same para id + /// compared to the default. + #[cfg(feature = "elastic-scaling-experimental")] + pub fn with_elastic_scaling() -> Self { + let mut state = Self::default(); + let para_id = state.para_id; + state + .availability_cores + .push(CoreState::Scheduled(ScheduledCore { para_id, collator: None })); + state + .availability_cores + .push(CoreState::Scheduled(ScheduledCore { para_id, collator: None })); + state + } + fn current_group_validator_indices(&self) -> &[ValidatorIndex] { let core_num = self.availability_cores.len(); let GroupIndex(group_idx) = self.group_rotation_info.group_for_core(CoreIndex(0), core_num); diff --git a/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs b/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs index 2bb7002a4f4..e419cd5444f 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs @@ -372,6 +372,119 @@ fn distribute_collation_up_to_limit() { ) } +/// Tests that collator send the parent head data in +/// case the para is assigned to multiple cores (elastic scaling). +#[test] +#[cfg(feature = "elastic-scaling-experimental")] +fn send_parent_head_data_for_elastic_scaling() { + let test_state = TestState::with_elastic_scaling(); + + let local_peer_id = test_state.local_peer_id; + let collator_pair = test_state.collator_pair.clone(); + + test_harness( + local_peer_id, + collator_pair, + ReputationAggregator::new(|_| true), + |test_harness| async move { + let mut virtual_overseer = test_harness.virtual_overseer; + let req_v1_cfg = test_harness.req_v1_cfg; + let mut req_v2_cfg = test_harness.req_v2_cfg; + + let head_b = Hash::from_low_u64_be(129); + let head_b_num: u32 = 63; + + // Set collating para id. + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::CollateOn(test_state.para_id), + ) + .await; + update_view(&mut virtual_overseer, &test_state, vec![(head_b, head_b_num)], 1).await; + + let pov_data = PoV { block_data: BlockData(vec![1 as u8]) }; + let candidate = TestCandidateBuilder { + para_id: test_state.para_id, + relay_parent: head_b, + pov_hash: pov_data.hash(), + ..Default::default() + } + .build(); + + let phd = HeadData(vec![1, 2, 3]); + let phdh = phd.hash(); + + distribute_collation_with_receipt( + &mut virtual_overseer, + &test_state, + head_b, + true, + candidate.clone(), + pov_data.clone(), + phdh, + ) + .await; + + let peer = test_state.validator_peer_id[0]; + let validator_id = test_state.current_group_validator_authority_ids()[0].clone(); + connect_peer( + &mut virtual_overseer, + peer, + CollationVersion::V2, + Some(validator_id.clone()), + ) + .await; + expect_declare_msg_v2(&mut virtual_overseer, &test_state, &peer).await; + + send_peer_view_change(&mut virtual_overseer, &peer, vec![head_b]).await; + let hashes: Vec<_> = vec![candidate.hash()]; + expect_advertise_collation_msg(&mut virtual_overseer, &peer, head_b, Some(hashes)) + .await; + + let (pending_response, rx) = oneshot::channel(); + req_v2_cfg + .inbound_queue + .as_mut() + .unwrap() + .send(RawIncomingRequest { + peer, + payload: request_v2::CollationFetchingRequest { + relay_parent: head_b, + para_id: test_state.para_id, + candidate_hash: candidate.hash(), + } + .encode(), + pending_response, + }) + .await + .unwrap(); + + assert_matches!( + rx.await, + Ok(full_response) => { + let response: request_v2::CollationFetchingResponse = + request_v2::CollationFetchingResponse::decode(&mut + full_response.result + .expect("We should have a proper answer").as_ref() + ).expect("Decoding should work"); + assert_matches!( + response, + request_v1::CollationFetchingResponse::CollationWithParentHeadData { + receipt, pov, parent_head_data + } => { + assert_eq!(receipt, candidate); + assert_eq!(pov, pov_data); + assert_eq!(parent_head_data, phd); + } + ); + } + ); + + TestHarness { virtual_overseer, req_v1_cfg, req_v2_cfg } + }, + ) +} + /// Tests that collator correctly handles peer V2 requests. #[test] fn advertise_and_send_collation_by_hash() { diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml index 734dcbdeb44..e2bccfa5510 100644 --- a/polkadot/node/service/Cargo.toml +++ b/polkadot/node/service/Cargo.toml @@ -218,10 +218,7 @@ try-runtime = [ "sp-runtime/try-runtime", "westend-runtime?/try-runtime", ] -fast-runtime = [ - "rococo-runtime?/fast-runtime", - "westend-runtime?/fast-runtime", -] +fast-runtime = ["rococo-runtime?/fast-runtime", "westend-runtime?/fast-runtime"] malus = ["full-node"] runtime-metrics = [ @@ -229,3 +226,7 @@ runtime-metrics = [ "rococo-runtime?/runtime-metrics", "westend-runtime?/runtime-metrics", ] + +elastic-scaling-experimental = [ + "polkadot-collator-protocol?/elastic-scaling-experimental", +] diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index eeb684149c8..23773f7e325 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -1114,7 +1114,7 @@ pub struct ProspectiveValidationDataRequest { } /// The parent head-data hash with optional data itself. -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ParentHeadData { /// Parent head-data hash. OnlyHash(Hash), @@ -1127,6 +1127,16 @@ pub enum ParentHeadData { }, } +impl ParentHeadData { + /// Return the hash of the parent head-data. + pub fn hash(&self) -> Hash { + match self { + ParentHeadData::OnlyHash(hash) => *hash, + ParentHeadData::WithData { hash, .. } => *hash, + } + } +} + /// Indicates the relay-parents whose fragment tree a candidate /// is present in and the depths of that tree the candidate is present in. pub type FragmentTreeMembership = Vec<(Hash, Vec)>; diff --git a/prdoc/pr_3521.prdoc b/prdoc/pr_3521.prdoc new file mode 100644 index 00000000000..4ad3f03bf0c --- /dev/null +++ b/prdoc/pr_3521.prdoc @@ -0,0 +1,12 @@ +title: Collator side changes for elastic scaling + +doc: + - audience: Node Dev + description: | + Parachain teams wishing to utilize the benefits of + elastic scaling will need to upgrade their collator + code to include these changes. + +crates: +- name: polkadot-collator-protocol + bump: minor -- GitLab From 1e9fd237768a404e40f1332b217f638dd7e3d917 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Tue, 19 Mar 2024 16:47:42 +0100 Subject: [PATCH 144/188] Implement crypto byte array newtypes in term of a shared type (#3684) Introduces `CryptoBytes` type defined as: ```rust pub struct CryptoBytes(pub [u8; N], PhantomData Tag>); ``` The type implements a bunch of methods and traits which are typically expected from a byte array newtype (NOTE: some of the methods and trait implementations IMO are a bit redundant, but I decided to maintain them all to not change too much stuff in this PR) It also introduces two (generic) typical consumers of `CryptoBytes`: `PublicBytes` and `SignatureBytes`. ```rust pub struct PublicTag; pub PublicBytes = CryptoBytes; pub struct SignatureTag; pub SignatureBytes = CryptoBytes; ``` Both of them use a tag to differentiate the two types at a higher level. Downstream specializations will further specialize using a dedicated crypto tag. For example in ECDSA: ```rust pub struct EcdsaTag; pub type Public = PublicBytes; pub type Signature = PublicBytes; ``` Overall we have a cleaner and most importantly **consistent** code for all the types involved All these details are opaque to the end user which can use `Public` and `Signature` for the cryptos as before --- cumulus/client/network/src/tests.rs | 6 +- .../bridge-hub-rococo/tests/snowbridge.rs | 7 +- .../bridge-hub-rococo/tests/tests.rs | 7 +- .../bridge-hub-westend/tests/tests.rs | 7 +- polkadot/node/service/src/benchmarking.rs | 4 +- polkadot/node/test/service/src/lib.rs | 2 +- polkadot/primitives/src/v6/mod.rs | 4 +- polkadot/primitives/test-helpers/src/lib.rs | 6 +- polkadot/runtime/common/src/purchase.rs | 4 +- polkadot/runtime/parachains/src/builder.rs | 2 +- .../client/authority-discovery/src/tests.rs | 2 +- .../client/executor/runtime-test/src/lib.rs | 4 +- .../client/service/test/src/client/mod.rs | 4 +- substrate/frame/contracts/src/exec.rs | 6 +- substrate/frame/sassafras/src/benchmarking.rs | 8 +- ...age_ensure_span_are_ok_on_wrong_gen.stderr | 12 +- ...re_span_are_ok_on_wrong_gen_unnamed.stderr | 12 +- substrate/primitives/core/src/bandersnatch.rs | 119 ++------ substrate/primitives/core/src/bls.rs | 214 +------------- substrate/primitives/core/src/crypto.rs | 5 +- substrate/primitives/core/src/crypto_bytes.rs | 244 ++++++++++++++++ substrate/primitives/core/src/ecdsa.rs | 184 ++---------- substrate/primitives/core/src/ed25519.rs | 255 ++--------------- substrate/primitives/core/src/lib.rs | 1 + .../primitives/core/src/paired_crypto.rs | 267 ++++++------------ substrate/primitives/core/src/sr25519.rs | 249 ++-------------- substrate/primitives/keystore/src/testing.rs | 2 +- substrate/primitives/runtime/src/traits.rs | 2 +- .../primitives/statement-store/src/lib.rs | 12 +- 29 files changed, 490 insertions(+), 1161 deletions(-) create mode 100644 substrate/primitives/core/src/crypto_bytes.rs diff --git a/cumulus/client/network/src/tests.rs b/cumulus/client/network/src/tests.rs index d986635f961..3f5757d5eac 100644 --- a/cumulus/client/network/src/tests.rs +++ b/cumulus/client/network/src/tests.rs @@ -144,7 +144,7 @@ impl RelayChainInterface for DummyRelayChainInterface { persisted_validation_data_hash: PHash::random(), pov_hash: PHash::random(), erasure_root: PHash::random(), - signature: sp_core::sr25519::Signature([0u8; 64]).into(), + signature: sp_core::sr25519::Signature::default().into(), validation_code_hash: ValidationCodeHash::from(PHash::random()), }, commitments: CandidateCommitments { @@ -325,7 +325,7 @@ async fn make_gossip_message_and_header( persisted_validation_data_hash: PHash::random(), pov_hash: PHash::random(), erasure_root: PHash::random(), - signature: sp_core::sr25519::Signature([0u8; 64]).into(), + signature: sp_core::sr25519::Signature::default().into(), para_head: polkadot_parachain_primitives::primitives::HeadData(header.encode()).hash(), validation_code_hash: ValidationCodeHash::from(PHash::random()), }, @@ -516,7 +516,7 @@ async fn check_statement_seconded() { persisted_validation_data_hash: PHash::random(), pov_hash: PHash::random(), erasure_root: PHash::random(), - signature: sp_core::sr25519::Signature([0u8; 64]).into(), + signature: sp_core::sr25519::Signature::default().into(), validation_code_hash: ValidationCodeHash::from(PHash::random()), }, }, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs index 239bd946e75..101b8d86d55 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs @@ -190,12 +190,7 @@ fn construct_extrinsic( ); 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, - ) + UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), extra) } fn construct_and_apply_extrinsic( diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index f11954cf165..fad357b0951 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -67,12 +67,7 @@ fn construct_extrinsic( ); 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, - ) + UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), extra) } fn construct_and_apply_extrinsic( diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs index 149a3bbeb75..235b7f146c8 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs @@ -81,12 +81,7 @@ fn construct_extrinsic( ); 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, - ) + UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), extra) } fn construct_and_apply_extrinsic( diff --git a/polkadot/node/service/src/benchmarking.rs b/polkadot/node/service/src/benchmarking.rs index 400daf1aee3..a0c4d3b0446 100644 --- a/polkadot/node/service/src/benchmarking.rs +++ b/polkadot/node/service/src/benchmarking.rs @@ -222,7 +222,7 @@ fn westend_sign_call( runtime::UncheckedExtrinsic::new_signed( call, sp_runtime::AccountId32::from(acc.public()).into(), - polkadot_core_primitives::Signature::Sr25519(signature.clone()), + polkadot_core_primitives::Signature::Sr25519(signature), extra, ) .into() @@ -274,7 +274,7 @@ fn rococo_sign_call( runtime::UncheckedExtrinsic::new_signed( call, sp_runtime::AccountId32::from(acc.public()).into(), - polkadot_core_primitives::Signature::Sr25519(signature.clone()), + polkadot_core_primitives::Signature::Sr25519(signature), extra, ) .into() diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs index ca904bae28d..eed11e62c21 100644 --- a/polkadot/node/test/service/src/lib.rs +++ b/polkadot/node/test/service/src/lib.rs @@ -410,7 +410,7 @@ pub fn construct_extrinsic( UncheckedExtrinsic::new_signed( function.clone(), polkadot_test_runtime::Address::Id(caller.public().into()), - polkadot_primitives::Signature::Sr25519(signature.clone()), + polkadot_primitives::Signature::Sr25519(signature), extra.clone(), ) } diff --git a/polkadot/primitives/src/v6/mod.rs b/polkadot/primitives/src/v6/mod.rs index cab34deeb50..742dbed1cd8 100644 --- a/polkadot/primitives/src/v6/mod.rs +++ b/polkadot/primitives/src/v6/mod.rs @@ -1953,11 +1953,11 @@ mod tests { descriptor: CandidateDescriptor { para_id: 0.into(), relay_parent: zeros, - collator: CollatorId::from(sr25519::Public::from_raw([0; 32])), + collator: CollatorId::from(sr25519::Public::default()), persisted_validation_data_hash: zeros, pov_hash: zeros, erasure_root: zeros, - signature: CollatorSignature::from(sr25519::Signature([0u8; 64])), + signature: CollatorSignature::from(sr25519::Signature::default()), para_head: zeros, validation_code_hash: ValidationCode(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).hash(), }, diff --git a/polkadot/primitives/test-helpers/src/lib.rs b/polkadot/primitives/test-helpers/src/lib.rs index c0118f5960a..b7c5d82341a 100644 --- a/polkadot/primitives/test-helpers/src/lib.rs +++ b/polkadot/primitives/test-helpers/src/lib.rs @@ -136,17 +136,17 @@ pub fn dummy_head_data() -> HeadData { /// Create a meaningless collator id. pub fn dummy_collator() -> CollatorId { - CollatorId::from(sr25519::Public::from_raw([0; 32])) + CollatorId::from(sr25519::Public::default()) } /// Create a meaningless validator id. pub fn dummy_validator() -> ValidatorId { - ValidatorId::from(sr25519::Public::from_raw([0; 32])) + ValidatorId::from(sr25519::Public::default()) } /// Create a meaningless collator signature. pub fn dummy_collator_signature() -> CollatorSignature { - CollatorSignature::from(sr25519::Signature([0u8; 64])) + CollatorSignature::from(sr25519::Signature::default()) } /// Create a meaningless persisted validation data. diff --git a/polkadot/runtime/common/src/purchase.rs b/polkadot/runtime/common/src/purchase.rs index 8de93bd68b0..b90bbb3a7cf 100644 --- a/polkadot/runtime/common/src/purchase.rs +++ b/polkadot/runtime/common/src/purchase.rs @@ -425,8 +425,8 @@ pub mod pallet { impl Pallet { fn verify_signature(who: &T::AccountId, signature: &[u8]) -> Result<(), DispatchError> { // sr25519 always expects a 64 byte signature. - let signature: AnySignature = sr25519::Signature::from_slice(signature) - .ok_or(Error::::InvalidSignature)? + let signature: AnySignature = sr25519::Signature::try_from(signature) + .map_err(|_| Error::::InvalidSignature)? .into(); // In Polkadot, the AccountId is always the same as the 32 byte public key. diff --git a/polkadot/runtime/parachains/src/builder.rs b/polkadot/runtime/parachains/src/builder.rs index 23ec80e66fc..05f6845f3b7 100644 --- a/polkadot/runtime/parachains/src/builder.rs +++ b/polkadot/runtime/parachains/src/builder.rs @@ -272,7 +272,7 @@ impl BenchBuilder { persisted_validation_data_hash: Default::default(), pov_hash: Default::default(), erasure_root: Default::default(), - signature: CollatorSignature::from(sr25519::Signature([42u8; 64])), + signature: CollatorSignature::from(sr25519::Signature::from_raw([42u8; 64])), para_head: Default::default(), validation_code_hash: mock_validation_code().hash(), } diff --git a/substrate/client/authority-discovery/src/tests.rs b/substrate/client/authority-discovery/src/tests.rs index 4fbc196c5ec..edd50d073c8 100644 --- a/substrate/client/authority-discovery/src/tests.rs +++ b/substrate/client/authority-discovery/src/tests.rs @@ -100,7 +100,7 @@ fn cryptos_are_compatible() { let sp_core_signature = sp_core_secret.sign(message); // no error expected... assert!(sp_core::ed25519::Pair::verify( - &sp_core::ed25519::Signature::from_slice(&libp2p_signature).unwrap(), + &sp_core::ed25519::Signature::try_from(libp2p_signature.as_slice()).unwrap(), message, &sp_core_public )); diff --git a/substrate/client/executor/runtime-test/src/lib.rs b/substrate/client/executor/runtime-test/src/lib.rs index ec9b2378d4d..40683fbb664 100644 --- a/substrate/client/executor/runtime-test/src/lib.rs +++ b/substrate/client/executor/runtime-test/src/lib.rs @@ -181,7 +181,7 @@ sp_core::wasm_export_functions! { sig.copy_from_slice(&input[32..96]); let msg = b"all ok!"; - ed25519_verify(&ed25519::Signature(sig), &msg[..], &ed25519::Public(pubkey)) + ed25519_verify(&ed25519::Signature::from(sig), &msg[..], &ed25519::Public::from(pubkey)) } fn test_sr25519_verify(input: Vec) -> bool { @@ -192,7 +192,7 @@ sp_core::wasm_export_functions! { sig.copy_from_slice(&input[32..96]); let msg = b"all ok!"; - sr25519_verify(&sr25519::Signature(sig), &msg[..], &sr25519::Public(pubkey)) + sr25519_verify(&sr25519::Signature::from(sig), &msg[..], &sr25519::Public::from(pubkey)) } fn test_ordered_trie_root() -> Vec { diff --git a/substrate/client/service/test/src/client/mod.rs b/substrate/client/service/test/src/client/mod.rs index ba83bec8276..51dcc4966e5 100644 --- a/substrate/client/service/test/src/client/mod.rs +++ b/substrate/client/service/test/src/client/mod.rs @@ -2226,11 +2226,11 @@ fn reorg_triggers_a_notification_even_for_sources_that_should_not_trigger_notifi #[test] fn use_dalek_ext_works() { fn zero_ed_pub() -> sp_core::ed25519::Public { - sp_core::ed25519::Public([0u8; 32]) + sp_core::ed25519::Public::default() } fn zero_ed_sig() -> sp_core::ed25519::Signature { - sp_core::ed25519::Signature::from_raw([0u8; 64]) + sp_core::ed25519::Signature::default() } let mut client = TestClientBuilder::new().build(); diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs index 7da321af547..d24657b65b2 100644 --- a/substrate/frame/contracts/src/exec.rs +++ b/substrate/frame/contracts/src/exec.rs @@ -1466,14 +1466,14 @@ where fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool { sp_io::crypto::sr25519_verify( - &SR25519Signature(*signature), + &SR25519Signature::from(*signature), message, - &SR25519Public(*pub_key), + &SR25519Public::from(*pub_key), ) } fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()> { - ECDSAPublic(*pk).to_eth_address() + ECDSAPublic::from(*pk).to_eth_address() } #[cfg(test)] diff --git a/substrate/frame/sassafras/src/benchmarking.rs b/substrate/frame/sassafras/src/benchmarking.rs index 921f2f0793d..1c9626ad260 100644 --- a/substrate/frame/sassafras/src/benchmarking.rs +++ b/substrate/frame/sassafras/src/benchmarking.rs @@ -139,8 +139,8 @@ mod benchmarks { TicketsIds::::insert((epoch_tag as u8, i), id); let body = TicketBody { attempt_idx: i, - erased_public: EphemeralPublic([i as u8; 32]), - revealed_public: EphemeralPublic([i as u8; 32]), + erased_public: EphemeralPublic::from([i as u8; 32]), + revealed_public: EphemeralPublic::from([i as u8; 32]), }; TicketsData::::set(id, Some(body)); }); @@ -236,8 +236,8 @@ mod benchmarks { .map(|i| { let body = TicketBody { attempt_idx: i, - erased_public: EphemeralPublic([i as u8; 32]), - revealed_public: EphemeralPublic([i as u8; 32]), + erased_public: EphemeralPublic::from([i as u8; 32]), + revealed_public: EphemeralPublic::from([i as u8; 32]), }; let id_bytes = crate::hashing::blake2_128(&i.to_le_bytes()); let id = TicketId::from_le_bytes(id_bytes); diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr index 4229d1e8a54..d269e6d2726 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr @@ -13,8 +13,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -65,8 +65,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others @@ -106,8 +106,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -148,8 +148,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others @@ -168,8 +168,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -210,8 +210,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr index 855d289d0a1..13d761d65d2 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr @@ -13,8 +13,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -65,8 +65,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others @@ -106,8 +106,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -148,8 +148,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others @@ -168,8 +168,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -210,8 +210,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others diff --git a/substrate/primitives/core/src/bandersnatch.rs b/substrate/primitives/core/src/bandersnatch.rs index 5cae6047f16..c9d5f27b47b 100644 --- a/substrate/primitives/core/src/bandersnatch.rs +++ b/substrate/primitives/core/src/bandersnatch.rs @@ -26,7 +26,8 @@ use crate::crypto::Ss58Codec; use crate::crypto::VrfSecret; use crate::crypto::{ ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, SecretStringError, UncheckedFrom, VrfPublic, + Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, + VrfPublic, }; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -37,7 +38,6 @@ use bandersnatch_vrfs::{CanonicalSerialize, SecretKey}; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_runtime_interface::pass_by::PassByInner; use sp_std::{vec, vec::Vec}; /// Identifier used to match public keys against bandersnatch-vrf keys. @@ -46,69 +46,23 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"band"); /// Context used to produce a plain signature without any VRF input/output. pub const SIGNING_CTX: &[u8] = b"BandersnatchSigningContext"; -const SEED_SERIALIZED_SIZE: usize = 32; +/// The byte length of secret key seed. +pub const SEED_SERIALIZED_SIZE: usize = 32; -const PUBLIC_SERIALIZED_SIZE: usize = 33; -const SIGNATURE_SERIALIZED_SIZE: usize = 65; -const PREOUT_SERIALIZED_SIZE: usize = 33; +/// The byte length of serialized public key. +pub const PUBLIC_SERIALIZED_SIZE: usize = 33; -/// Bandersnatch public key. -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Encode, - Decode, - PassByInner, - MaxEncodedLen, - TypeInfo, - Hash, -)] -pub struct Public(pub [u8; PUBLIC_SERIALIZED_SIZE]); - -impl UncheckedFrom<[u8; PUBLIC_SERIALIZED_SIZE]> for Public { - fn unchecked_from(raw: [u8; PUBLIC_SERIALIZED_SIZE]) -> Self { - Public(raw) - } -} +/// The byte length of serialized signature. +pub const SIGNATURE_SERIALIZED_SIZE: usize = 65; -impl AsRef<[u8; PUBLIC_SERIALIZED_SIZE]> for Public { - fn as_ref(&self) -> &[u8; PUBLIC_SERIALIZED_SIZE] { - &self.0 - } -} +/// The byte length of serialized pre-output. +pub const PREOUT_SERIALIZED_SIZE: usize = 33; -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} +#[doc(hidden)] +pub struct BandersnatchTag; -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != PUBLIC_SERIALIZED_SIZE { - return Err(()) - } - let mut r = [0u8; PUBLIC_SERIALIZED_SIZE]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl ByteArray for Public { - const LEN: usize = PUBLIC_SERIALIZED_SIZE; -} +/// Bandersnatch public key. +pub type Public = PublicBytes; impl TraitPublic for Public {} @@ -150,45 +104,7 @@ impl<'de> Deserialize<'de> for Public { /// /// The signature is created via the [`VrfSecret::vrf_sign`] using [`SIGNING_CTX`] as transcript /// `label`. -#[derive( - Clone, Copy, PartialEq, Eq, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo, Hash, -)] -pub struct Signature([u8; SIGNATURE_SERIALIZED_SIZE]); - -impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn unchecked_from(raw: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Self { - Signature(raw) - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != SIGNATURE_SERIALIZED_SIZE { - return Err(()) - } - let mut r = [0u8; SIGNATURE_SERIALIZED_SIZE]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl ByteArray for Signature { - const LEN: usize = SIGNATURE_SERIALIZED_SIZE; -} +pub type Signature = SignatureBytes; impl CryptoType for Signature { type Pair = Pair; @@ -542,8 +458,7 @@ pub mod vrf { thin_signature.preouts.into_iter().map(VrfPreOutput).collect(); let pre_outputs = VrfIosVec::truncate_from(pre_outputs); - let mut signature = - VrfSignature { signature: Signature([0; SIGNATURE_SERIALIZED_SIZE]), pre_outputs }; + let mut signature = VrfSignature { signature: Signature::default(), pre_outputs }; thin_signature .proof @@ -582,7 +497,7 @@ pub mod vrf { // This is another hack used because backend signature type is generic over // the number of ios. let Ok(proof) = ThinVrfSignature::<0>::deserialize_compressed_unchecked( - signature.signature.as_ref(), + signature.signature.as_slice(), ) .map(|s| s.proof) else { return false diff --git a/substrate/primitives/core/src/bls.rs b/substrate/primitives/core/src/bls.rs index 2256e4cd823..9492a14ff0d 100644 --- a/substrate/primitives/core/src/bls.rs +++ b/substrate/primitives/core/src/bls.rs @@ -26,28 +26,21 @@ #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ - ByteArray, CryptoType, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, SecretStringError, UncheckedFrom, + CryptoType, Derive, DeriveError, DeriveJunction, Pair as TraitPair, Public as TraitPublic, + PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, }; -use sp_std::vec::Vec; - -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; - #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; +use sp_std::vec::Vec; use w3f_bls::{ DoublePublicKey, DoublePublicKeyScheme, DoubleSignature, EngineBLS, Keypair, Message, SecretKey, SerializableToBytes, TinyBLS381, }; -use sp_runtime_interface::pass_by::{self, PassBy, PassByInner}; -use sp_std::{convert::TryFrom, marker::PhantomData, ops::Deref}; - /// BLS-377 specialized types pub mod bls377 { pub use super::{PUBLIC_KEY_SERIALIZED_SIZE, SIGNATURE_SERIALIZED_SIZE}; @@ -57,6 +50,9 @@ pub mod bls377 { /// An identifier used to match public keys against BLS12-377 keys pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"bls7"); + #[doc(hidden)] + pub type Bls377Tag = TinyBLS377; + /// BLS12-377 key pair. pub type Pair = super::Pair; /// BLS12-377 public key. @@ -113,114 +109,11 @@ pub const SIGNATURE_SERIALIZED_SIZE: usize = /// will need it later (such as for HDKD). type Seed = [u8; SECRET_KEY_SERIALIZED_SIZE]; -/// A public key. -#[derive(Copy, Encode, Decode, MaxEncodedLen, TypeInfo)] -#[scale_info(skip_type_params(T))] -pub struct Public { - inner: [u8; PUBLIC_KEY_SERIALIZED_SIZE], - _phantom: PhantomData T>, -} - -impl Clone for Public { - fn clone(&self) -> Self { - Self { inner: self.inner, _phantom: PhantomData } - } -} - -impl PartialEq for Public { - fn eq(&self, other: &Self) -> bool { - self.inner == other.inner - } -} - -impl Eq for Public {} - -impl PartialOrd for Public { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Public { - fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { - self.inner.cmp(&other.inner) - } -} - -impl sp_std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.inner.hash(state) - } -} - -impl ByteArray for Public { - const LEN: usize = PUBLIC_KEY_SERIALIZED_SIZE; -} - -impl PassByInner for Public { - type Inner = [u8; PUBLIC_KEY_SERIALIZED_SIZE]; - - fn into_inner(self) -> Self::Inner { - self.inner - } - - fn inner(&self) -> &Self::Inner { - &self.inner - } - - fn from_inner(inner: Self::Inner) -> Self { - Self { inner, _phantom: PhantomData } - } -} - -impl PassBy for Public { - type PassBy = pass_by::Inner; -} - -impl AsRef<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public { - fn as_ref(&self) -> &[u8; PUBLIC_KEY_SERIALIZED_SIZE] { - &self.inner - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.inner[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.inner[..] - } -} - -impl Deref for Public { - type Target = [u8]; +#[doc(hidden)] +pub struct BlsTag; - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != PUBLIC_KEY_SERIALIZED_SIZE { - return Err(()) - } - let mut r = [0u8; PUBLIC_KEY_SERIALIZED_SIZE]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl From> for [u8; PUBLIC_KEY_SERIALIZED_SIZE] { - fn from(x: Public) -> Self { - x.inner - } -} +/// A public key. +pub type Public = PublicBytes; impl From> for Public { fn from(x: Pair) -> Self { @@ -228,12 +121,6 @@ impl From> for Public { } } -impl UncheckedFrom<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public { - fn unchecked_from(data: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self { - Public { inner: data, _phantom: PhantomData } - } -} - #[cfg(feature = "std")] impl std::str::FromStr for Public { type Err = crate::crypto::PublicError; @@ -254,7 +141,7 @@ impl std::fmt::Display for Public { impl sp_std::fmt::Debug for Public { fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.inner), &s[0..8]) + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) } } @@ -295,49 +182,7 @@ impl CryptoType for Public { } /// A generic BLS signature. -#[derive(Copy, Encode, Decode, MaxEncodedLen, TypeInfo)] -#[scale_info(skip_type_params(T))] -pub struct Signature { - inner: [u8; SIGNATURE_SERIALIZED_SIZE], - _phantom: PhantomData T>, -} - -impl Clone for Signature { - fn clone(&self) -> Self { - Self { inner: self.inner, _phantom: PhantomData } - } -} - -impl PartialEq for Signature { - fn eq(&self, other: &Self) -> bool { - self.inner == other.inner - } -} - -impl Eq for Signature {} - -impl sp_std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - self.inner.hash(state) - } -} - -impl ByteArray for Signature { - const LEN: usize = SIGNATURE_SERIALIZED_SIZE; -} - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != SIGNATURE_SERIALIZED_SIZE { - return Err(()) - } - let mut inner = [0u8; SIGNATURE_SERIALIZED_SIZE]; - inner.copy_from_slice(data); - Ok(Signature::unchecked_from(inner)) - } -} +pub type Signature = SignatureBytes; #[cfg(feature = "serde")] impl Serialize for Signature { @@ -362,34 +207,10 @@ impl<'de, T> Deserialize<'de> for Signature { } } -impl From> for [u8; SIGNATURE_SERIALIZED_SIZE] { - fn from(signature: Signature) -> [u8; SIGNATURE_SERIALIZED_SIZE] { - signature.inner - } -} - -impl AsRef<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn as_ref(&self) -> &[u8; SIGNATURE_SERIALIZED_SIZE] { - &self.inner - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.inner[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.inner[..] - } -} - impl sp_std::fmt::Debug for Signature { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.inner)) + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) } #[cfg(not(feature = "std"))] @@ -398,12 +219,6 @@ impl sp_std::fmt::Debug for Signature { } } -impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn unchecked_from(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Self { - Signature { inner: data, _phantom: PhantomData } - } -} - impl CryptoType for Signature { type Pair = Pair; } @@ -423,6 +238,7 @@ trait HardJunctionId { /// Derive a single hard junction. fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + use codec::Encode; (T::ID, secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } @@ -489,7 +305,7 @@ impl TraitPair for Pair { Err(_) => return false, }; - let sig_array = match sig.inner[..].try_into() { + let sig_array = match sig.0[..].try_into() { Ok(s) => s, Err(_) => return false, }; diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs index fab865d8c1f..a2bdc6ed58e 100644 --- a/substrate/primitives/core/src/crypto.rs +++ b/substrate/primitives/core/src/crypto.rs @@ -39,7 +39,10 @@ pub use ss58_registry::{from_known_address_format, Ss58AddressFormat, Ss58Addres /// Trait to zeroize a memory buffer. pub use zeroize::Zeroize; -pub use crate::address_uri::{AddressUri, Error as AddressUriError}; +pub use crate::{ + address_uri::{AddressUri, Error as AddressUriError}, + crypto_bytes::{CryptoBytes, PublicBytes, SignatureBytes}, +}; /// The root phrase for our publicly known keys. pub const DEV_PHRASE: &str = diff --git a/substrate/primitives/core/src/crypto_bytes.rs b/substrate/primitives/core/src/crypto_bytes.rs new file mode 100644 index 00000000000..069878e1654 --- /dev/null +++ b/substrate/primitives/core/src/crypto_bytes.rs @@ -0,0 +1,244 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! Generic byte array which can be specialized with a marker type. + +use crate::{ + crypto::{FromEntropy, UncheckedFrom}, + hash::{H256, H512}, +}; + +use codec::{Decode, Encode, MaxEncodedLen}; +use core::marker::PhantomData; +use scale_info::TypeInfo; +use sp_runtime_interface::pass_by::{self, PassBy, PassByInner}; + +/// Generic byte array holding some crypto-related raw data. +/// +/// The type is generic over a constant length `N` and a "tag" `T` which +/// can be used to specialize the byte array without requiring newtypes. +/// +/// The tag `T` is held in a `PhantomDataT>`, a trick allowing +/// `CryptoBytes` to be `Send` and `Sync` regardless of `T` properties +/// ([ref](https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns)). +#[derive(Encode, Decode, MaxEncodedLen)] +#[repr(transparent)] +pub struct CryptoBytes(pub [u8; N], PhantomData T>); + +impl Copy for CryptoBytes {} + +impl Clone for CryptoBytes { + fn clone(&self) -> Self { + Self(self.0, PhantomData) + } +} + +impl TypeInfo for CryptoBytes { + type Identity = [u8; N]; + + fn type_info() -> scale_info::Type { + Self::Identity::type_info() + } +} + +impl PartialOrd for CryptoBytes { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl Ord for CryptoBytes { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.0.cmp(&other.0) + } +} + +impl PartialEq for CryptoBytes { + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } +} + +impl core::hash::Hash for CryptoBytes { + fn hash(&self, state: &mut H) { + self.0.hash(state) + } +} + +impl Eq for CryptoBytes {} + +impl Default for CryptoBytes { + fn default() -> Self { + Self([0_u8; N], PhantomData) + } +} + +impl PassByInner for CryptoBytes { + type Inner = [u8; N]; + + fn into_inner(self) -> Self::Inner { + self.0 + } + + fn inner(&self) -> &Self::Inner { + &self.0 + } + + fn from_inner(inner: Self::Inner) -> Self { + Self(inner, PhantomData) + } +} + +impl PassBy for CryptoBytes { + type PassBy = pass_by::Inner; +} + +impl AsRef<[u8]> for CryptoBytes { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for CryptoBytes { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +impl From> for [u8; N] { + fn from(v: CryptoBytes) -> [u8; N] { + v.0 + } +} + +impl AsRef<[u8; N]> for CryptoBytes { + fn as_ref(&self) -> &[u8; N] { + &self.0 + } +} + +impl AsMut<[u8; N]> for CryptoBytes { + fn as_mut(&mut self) -> &mut [u8; N] { + &mut self.0 + } +} + +impl From<[u8; N]> for CryptoBytes { + fn from(value: [u8; N]) -> Self { + Self::from_raw(value) + } +} + +impl TryFrom<&[u8]> for CryptoBytes { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() != N { + return Err(()) + } + let mut r = [0u8; N]; + r.copy_from_slice(data); + Ok(Self::from_raw(r)) + } +} + +impl UncheckedFrom<[u8; N]> for CryptoBytes { + fn unchecked_from(data: [u8; N]) -> Self { + Self::from_raw(data) + } +} + +impl core::ops::Deref for CryptoBytes { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl CryptoBytes { + /// Construct from raw array. + pub fn from_raw(inner: [u8; N]) -> Self { + Self(inner, PhantomData) + } + + /// Construct from raw array. + pub fn to_raw(self) -> [u8; N] { + self.0 + } + + /// Return a slice filled with raw data. + pub fn as_array_ref(&self) -> &[u8; N] { + &self.0 + } +} + +impl crate::ByteArray for CryptoBytes { + const LEN: usize = N; +} + +impl FromEntropy for CryptoBytes { + fn from_entropy(input: &mut impl codec::Input) -> Result { + let mut result = Self::default(); + input.read(result.as_mut())?; + Ok(result) + } +} + +impl From> for H256 { + fn from(x: CryptoBytes<32, T>) -> H256 { + H256::from(x.0) + } +} + +impl From> for H512 { + fn from(x: CryptoBytes<64, T>) -> H512 { + H512::from(x.0) + } +} + +impl UncheckedFrom for CryptoBytes<32, T> { + fn unchecked_from(x: H256) -> Self { + Self::from_h256(x) + } +} + +impl CryptoBytes<32, T> { + /// A new instance from an H256. + pub fn from_h256(x: H256) -> Self { + Self::from_raw(x.into()) + } +} + +impl CryptoBytes<64, T> { + /// A new instance from an H512. + pub fn from_h512(x: H512) -> Self { + Self::from_raw(x.into()) + } +} + +/// Tag used for generic public key bytes. +pub struct PublicTag; + +/// Generic encoded public key. +pub type PublicBytes = CryptoBytes; + +/// Tag used for generic signature bytes. +pub struct SignatureTag; + +/// Generic encoded signature. +pub type SignatureBytes = CryptoBytes; diff --git a/substrate/primitives/core/src/ecdsa.rs b/substrate/primitives/core/src/ecdsa.rs index fa071e1b03f..0e6b06a34dc 100644 --- a/substrate/primitives/core/src/ecdsa.rs +++ b/substrate/primitives/core/src/ecdsa.rs @@ -17,15 +17,11 @@ //! Simple ECDSA secp256k1 API. -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_runtime_interface::pass_by::PassByInner; - #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ - ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, SecretStringError, UncheckedFrom, + CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, + Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, }; #[cfg(not(feature = "std"))] @@ -51,45 +47,18 @@ pub const PUBLIC_KEY_SERIALIZED_SIZE: usize = 33; /// The byte length of signature pub const SIGNATURE_SERIALIZED_SIZE: usize = 65; +#[doc(hidden)] +pub struct EcdsaTag; + /// The secret seed. /// /// The raw secret seed, which can be used to create the `Pair`. type Seed = [u8; 32]; /// The ECDSA compressed public key. -#[derive( - Clone, - Copy, - Encode, - Decode, - PassByInner, - MaxEncodedLen, - TypeInfo, - Eq, - PartialEq, - PartialOrd, - Ord, - Hash, -)] -pub struct Public(pub [u8; PUBLIC_KEY_SERIALIZED_SIZE]); - -impl crate::crypto::FromEntropy for Public { - fn from_entropy(input: &mut impl codec::Input) -> Result { - let mut result = Self([0u8; PUBLIC_KEY_SERIALIZED_SIZE]); - input.read(&mut result.0[..])?; - Ok(result) - } -} +pub type Public = PublicBytes; impl Public { - /// A new instance from the given 33-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_raw(data: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self { - Self(data) - } - /// Create a new instance from the given full public key. /// /// This will convert the full public key into the compressed format. @@ -111,54 +80,22 @@ impl Public { } } -impl ByteArray for Public { - const LEN: usize = PUBLIC_KEY_SERIALIZED_SIZE; -} - impl TraitPublic for Public {} impl Derive for Public {} -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - #[cfg(feature = "std")] impl From for Public { fn from(pubkey: PublicKey) -> Self { - Self(pubkey.serialize()) + Self::from(pubkey.serialize()) } } #[cfg(not(feature = "std"))] impl From for Public { fn from(pubkey: VerifyingKey) -> Self { - Self::unchecked_from( - pubkey.to_sec1_bytes()[..] - .try_into() - .expect("valid key is serializable to [u8,33]. qed."), - ) - } -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != Self::LEN { - return Err(()) - } - let mut r = [0u8; Self::LEN]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) + Self::try_from(&pubkey.to_sec1_bytes()[..]) + .expect("Valid key is serializable to [u8; 33]. qed.") } } @@ -169,12 +106,6 @@ impl From for Public { } } -impl UncheckedFrom<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public { - fn unchecked_from(x: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self { - Public(x) - } -} - #[cfg(feature = "std")] impl std::fmt::Display for Public { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -217,26 +148,7 @@ impl<'de> Deserialize<'de> for Public { } /// A signature (a 512-bit value, plus 8 bits for recovery ID). -#[derive(Hash, Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] -pub struct Signature(pub [u8; SIGNATURE_SERIALIZED_SIZE]); - -impl ByteArray for Signature { - const LEN: usize = SIGNATURE_SERIALIZED_SIZE; -} - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == SIGNATURE_SERIALIZED_SIZE { - let mut inner = [0u8; SIGNATURE_SERIALIZED_SIZE]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} +pub type Signature = SignatureBytes; #[cfg(feature = "serde")] impl Serialize for Signature { @@ -261,44 +173,6 @@ impl<'de> Deserialize<'de> for Signature { } } -impl Clone for Signature { - fn clone(&self) -> Self { - let mut r = [0u8; SIGNATURE_SERIALIZED_SIZE]; - r.copy_from_slice(&self.0[..]); - Signature(r) - } -} - -impl Default for Signature { - fn default() -> Self { - Signature([0u8; SIGNATURE_SERIALIZED_SIZE]) - } -} - -impl From for [u8; SIGNATURE_SERIALIZED_SIZE] { - fn from(v: Signature) -> [u8; SIGNATURE_SERIALIZED_SIZE] { - v.0 - } -} - -impl AsRef<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn as_ref(&self) -> &[u8; SIGNATURE_SERIALIZED_SIZE] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - impl sp_std::fmt::Debug for Signature { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { @@ -311,34 +185,7 @@ impl sp_std::fmt::Debug for Signature { } } -impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn unchecked_from(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Signature { - Signature(data) - } -} - impl Signature { - /// A new instance from the given 65-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_raw(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Signature { - Signature(data) - } - - /// A new instance from the given slice that should be 65 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Option { - if data.len() != SIGNATURE_SERIALIZED_SIZE { - return None - } - let mut r = [0u8; SIGNATURE_SERIALIZED_SIZE]; - r.copy_from_slice(data); - Some(Signature(r)) - } - /// Recover the public key from this signature and a message. pub fn recover>(&self, message: M) -> Option { self.recover_prehashed(&sp_crypto_hashing::blake2_256(message.as_ref())) @@ -350,7 +197,8 @@ impl Signature { { let rid = RecoveryId::from_i32(self.0[64] as i32).ok()?; let sig = RecoverableSignature::from_compact(&self.0[..64], rid).ok()?; - let message = Message::from_digest_slice(message).expect("Message is 32 bytes; qed"); + let message = + Message::from_digest_slice(message).expect("Message is a 32 bytes hash; qed"); SECP256K1.recover_ecdsa(&message, &sig).ok().map(Public::from) } @@ -387,6 +235,7 @@ impl From for Signature { /// Derive a single hard junction. fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + use codec::Encode; ("Secp256k1HDKD", secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } @@ -490,15 +339,18 @@ impl Pair { pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature { #[cfg(feature = "std")] { - let message = Message::from_digest_slice(message).expect("Message is 32 bytes; qed"); + let message = + Message::from_digest_slice(message).expect("Message is a 32 bytes hash; qed"); SECP256K1.sign_ecdsa_recoverable(&message, &self.secret).into() } #[cfg(not(feature = "std"))] { + // Signing fails only if the `message` number of bytes is less than the field length + // (unfallible as we're using a fixed message length of 32). self.secret .sign_prehash_recoverable(message) - .expect("signing may not fail (???). qed.") + .expect("Signing can't fail when using 32 bytes message hash. qed.") .into() } } diff --git a/substrate/primitives/core/src/ed25519.rs b/substrate/primitives/core/src/ed25519.rs index 9f42b36dc8b..0dda7b95972 100644 --- a/substrate/primitives/core/src/ed25519.rs +++ b/substrate/primitives/core/src/ed25519.rs @@ -15,119 +15,45 @@ // See the License for the specific language governing permissions and // limitations under the License. -// tag::description[] //! Simple Ed25519 API. -// end::description[] - -use sp_std::vec::Vec; - -use crate::{ - crypto::ByteArray, - hash::{H256, H512}, -}; -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ - CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, FromEntropy, Pair as TraitPair, - Public as TraitPublic, SecretStringError, UncheckedFrom, + ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, + Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, }; -#[cfg(feature = "full_crypto")] -use core::convert::TryFrom; + use ed25519_zebra::{SigningKey, VerificationKey}; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -use sp_runtime_interface::pass_by::PassByInner; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; -use sp_std::ops::Deref; +use sp_std::vec::Vec; /// An identifier used to match public keys against ed25519 keys pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ed25"); +/// The byte length of public key +pub const PUBLIC_KEY_SERIALIZED_SIZE: usize = 32; + +/// The byte length of signature +pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; + /// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys /// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we /// will need it later (such as for HDKD). type Seed = [u8; 32]; -/// A public key. -#[derive( - PartialEq, - Eq, - PartialOrd, - Ord, - Clone, - Copy, - Encode, - Decode, - PassByInner, - MaxEncodedLen, - TypeInfo, - Hash, -)] -pub struct Public(pub [u8; 32]); +#[doc(hidden)] +pub struct Ed25519Tag; -/// A key pair. -#[derive(Copy, Clone)] -pub struct Pair { - public: VerificationKey, - secret: SigningKey, -} - -impl FromEntropy for Public { - fn from_entropy(input: &mut impl codec::Input) -> Result { - let mut result = Self([0u8; 32]); - input.read(&mut result.0[..])?; - Ok(result) - } -} - -impl AsRef<[u8; 32]> for Public { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl Deref for Public { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl TryFrom<&[u8]> for Public { - type Error = (); +/// A public key. +pub type Public = PublicBytes; - fn try_from(data: &[u8]) -> Result { - if data.len() != Self::LEN { - return Err(()) - } - let mut r = [0u8; Self::LEN]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} +impl TraitPublic for Public {} -impl From for [u8; 32] { - fn from(x: Public) -> Self { - x.0 - } -} +impl Derive for Public {} #[cfg(feature = "full_crypto")] impl From for Public { @@ -136,12 +62,6 @@ impl From for Public { } } -impl From for H256 { - fn from(x: Public) -> Self { - x.0.into() - } -} - #[cfg(feature = "std")] impl std::str::FromStr for Public { type Err = crate::crypto::PublicError; @@ -151,18 +71,6 @@ impl std::str::FromStr for Public { } } -impl UncheckedFrom<[u8; 32]> for Public { - fn unchecked_from(x: [u8; 32]) -> Self { - Public::from_raw(x) - } -} - -impl UncheckedFrom for Public { - fn unchecked_from(x: H256) -> Self { - Public::from_h256(x) - } -} - #[cfg(feature = "std")] impl std::fmt::Display for Public { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -204,23 +112,8 @@ impl<'de> Deserialize<'de> for Public { } } -/// A signature (a 512-bit value). -#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq, Hash)] -pub struct Signature(pub [u8; 64]); - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 64 { - let mut inner = [0u8; 64]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} +/// A signature. +pub type Signature = SignatureBytes; #[cfg(feature = "serde")] impl Serialize for Signature { @@ -245,44 +138,6 @@ impl<'de> Deserialize<'de> for Signature { } } -impl Clone for Signature { - fn clone(&self) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&self.0[..]); - Signature(r) - } -} - -impl From for H512 { - fn from(v: Signature) -> H512 { - H512::from(v.0) - } -} - -impl From for [u8; 64] { - fn from(v: Signature) -> [u8; 64] { - v.0 - } -} - -impl AsRef<[u8; 64]> for Signature { - fn as_ref(&self) -> &[u8; 64] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - impl sp_std::fmt::Debug for Signature { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { @@ -295,76 +150,16 @@ impl sp_std::fmt::Debug for Signature { } } -impl UncheckedFrom<[u8; 64]> for Signature { - fn unchecked_from(data: [u8; 64]) -> Signature { - Signature(data) - } -} - -impl Signature { - /// A new instance from the given 64-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_raw(data: [u8; 64]) -> Signature { - Signature(data) - } - - /// A new instance from the given slice that should be 64 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Option { - if data.len() != 64 { - return None - } - let mut r = [0u8; 64]; - r.copy_from_slice(data); - Some(Signature(r)) - } - - /// A new instance from an H512. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_h512(v: H512) -> Signature { - Signature(v.into()) - } -} - -impl Public { - /// A new instance from the given 32-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_raw(data: [u8; 32]) -> Self { - Public(data) - } - - /// A new instance from an H256. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_h256(x: H256) -> Self { - Public(x.into()) - } - - /// Return a slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 32] { - self.as_ref() - } -} - -impl ByteArray for Public { - const LEN: usize = 32; +/// A key pair. +#[derive(Copy, Clone)] +pub struct Pair { + public: VerificationKey, + secret: SigningKey, } -impl TraitPublic for Public {} - -impl Derive for Public {} - /// Derive a single hard junction. fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + use codec::Encode; ("Ed25519HDKD", secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } @@ -402,7 +197,7 @@ impl TraitPair for Pair { /// Get the public key. fn public(&self) -> Public { - Public(self.public.into()) + Public::from_raw(self.public.into()) } /// Sign a message. diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs index c0b41234460..cf803c6fb49 100644 --- a/substrate/primitives/core/src/lib.rs +++ b/substrate/primitives/core/src/lib.rs @@ -62,6 +62,7 @@ mod address_uri; pub mod bandersnatch; #[cfg(feature = "bls-experimental")] pub mod bls; +pub mod crypto_bytes; pub mod defer; pub mod ecdsa; pub mod ed25519; diff --git a/substrate/primitives/core/src/paired_crypto.rs b/substrate/primitives/core/src/paired_crypto.rs index 6d2e6ddf334..27a7ab28dfd 100644 --- a/substrate/primitives/core/src/paired_crypto.rs +++ b/substrate/primitives/core/src/paired_crypto.rs @@ -17,25 +17,22 @@ //! API for using a pair of crypto schemes together. +use core::marker::PhantomData; + #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ ByteArray, CryptoType, Derive, DeriveError, DeriveJunction, Pair as PairT, Public as PublicT, - SecretStringError, UncheckedFrom, + PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, }; use sp_std::vec::Vec; -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; -use sp_runtime_interface::pass_by::{self, PassBy, PassByInner}; -use sp_std::convert::TryFrom; - /// ECDSA and BLS12-377 paired crypto scheme #[cfg(feature = "bls-experimental")] pub mod ecdsa_bls377 { @@ -54,12 +51,20 @@ pub mod ecdsa_bls377 { const SIGNATURE_LEN: usize = ecdsa::SIGNATURE_SERIALIZED_SIZE + bls377::SIGNATURE_SERIALIZED_SIZE; + #[doc(hidden)] + pub struct EcdsaBls377Tag(ecdsa::EcdsaTag, bls377::Bls377Tag); + + impl super::PairedCryptoSubTagBound for EcdsaBls377Tag {} + /// (ECDSA,BLS12-377) key-pair pair. - pub type Pair = super::Pair; + pub type Pair = + super::Pair; + /// (ECDSA,BLS12-377) public key pair. - pub type Public = super::Public; + pub type Public = super::Public; + /// (ECDSA,BLS12-377) signature pair. - pub type Signature = super::Signature; + pub type Signature = super::Signature; impl super::CryptoType for Public { type Pair = Pair; @@ -110,7 +115,7 @@ pub mod ecdsa_bls377 { let Ok(left_pub) = public.0[..ecdsa::PUBLIC_KEY_SERIALIZED_SIZE].try_into() else { return false }; - let Ok(left_sig) = sig.0[0..ecdsa::SIGNATURE_SERIALIZED_SIZE].try_into() else { + let Ok(left_sig) = sig.0[..ecdsa::SIGNATURE_SERIALIZED_SIZE].try_into() else { return false }; if !ecdsa::Pair::verify_prehashed(&left_sig, &msg_hash, &left_pub) { @@ -140,110 +145,49 @@ const SECURE_SEED_LEN: usize = 32; /// will need it later (such as for HDKD). type Seed = [u8; SECURE_SEED_LEN]; -/// A public key. -#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, PartialOrd, Ord)] -pub struct Public([u8; LEFT_PLUS_RIGHT_LEN]); - -impl sp_std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl ByteArray for Public { - const LEN: usize = LEFT_PLUS_RIGHT_LEN; -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != LEFT_PLUS_RIGHT_LEN { - return Err(()) - } - let mut inner = [0u8; LEFT_PLUS_RIGHT_LEN]; - inner.copy_from_slice(data); - Ok(Public(inner)) - } -} - -impl AsRef<[u8; LEFT_PLUS_RIGHT_LEN]> - for Public -{ - fn as_ref(&self) -> &[u8; LEFT_PLUS_RIGHT_LEN] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl PassByInner for Public { - type Inner = [u8; LEFT_PLUS_RIGHT_LEN]; - - fn into_inner(self) -> Self::Inner { - self.0 - } - - fn inner(&self) -> &Self::Inner { - &self.0 - } +#[doc(hidden)] +pub trait PairedCryptoSubTagBound {} +#[doc(hidden)] +pub struct PairedCryptoTag; - fn from_inner(inner: Self::Inner) -> Self { - Self(inner) - } -} - -impl PassBy for Public { - type PassBy = pass_by::Inner; -} +/// A public key. +pub type Public = + PublicBytes; impl< LeftPair: PairT, RightPair: PairT, const LEFT_PLUS_RIGHT_PUBLIC_LEN: usize, const SIGNATURE_LEN: usize, - > From> - for Public + SubTag: PairedCryptoSubTagBound, + > From> + for Public where - Pair: - PairT>, + Pair: + PairT>, { - fn from(x: Pair) -> Self { + fn from( + x: Pair, + ) -> Self { x.public() } } -impl UncheckedFrom<[u8; LEFT_PLUS_RIGHT_LEN]> - for Public -{ - fn unchecked_from(data: [u8; LEFT_PLUS_RIGHT_LEN]) -> Self { - Public(data) - } -} - #[cfg(feature = "std")] -impl std::fmt::Display for Public +impl std::fmt::Display + for Public where - Public: CryptoType, + Public: CryptoType, { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.to_ss58check()) } } -impl sp_std::fmt::Debug for Public +impl sp_std::fmt::Debug + for Public where - Public: CryptoType, + Public: CryptoType, [u8; LEFT_PLUS_RIGHT_LEN]: crate::hexdisplay::AsBytesRef, { #[cfg(feature = "std")] @@ -259,9 +203,10 @@ where } #[cfg(feature = "serde")] -impl Serialize for Public +impl Serialize + for Public where - Public: CryptoType, + Public: CryptoType, { fn serialize(&self, serializer: S) -> Result where @@ -272,9 +217,10 @@ where } #[cfg(feature = "serde")] -impl<'de, const LEFT_PLUS_RIGHT_LEN: usize> Deserialize<'de> for Public +impl<'de, const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> Deserialize<'de> + for Public where - Public: CryptoType, + Public: CryptoType, { fn deserialize(deserializer: D) -> Result where @@ -285,12 +231,17 @@ where } } -impl PublicT for Public where - Public: CryptoType +impl PublicT + for Public +where + Public: CryptoType, { } -impl Derive for Public {} +impl Derive + for Public +{ +} /// Trait characterizing a signature which could be used as individual component of an /// `paired_crypto:Signature` pair. @@ -299,54 +250,13 @@ pub trait SignatureBound: ByteArray {} impl SignatureBound for T {} /// A pair of signatures of different types -#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq)] -pub struct Signature([u8; LEFT_PLUS_RIGHT_LEN]); - -impl sp_std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl ByteArray for Signature { - const LEN: usize = LEFT_PLUS_RIGHT_LEN; -} - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != LEFT_PLUS_RIGHT_LEN { - return Err(()) - } - let mut inner = [0u8; LEFT_PLUS_RIGHT_LEN]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl AsRef<[u8; LEFT_PLUS_RIGHT_LEN]> - for Signature -{ - fn as_ref(&self) -> &[u8; LEFT_PLUS_RIGHT_LEN] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} +pub type Signature = + SignatureBytes; #[cfg(feature = "serde")] -impl Serialize for Signature { +impl Serialize + for Signature +{ fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -356,28 +266,23 @@ impl Serialize for Signature Deserialize<'de> for Signature { +impl<'de, const LEFT_PLUS_RIGHT_LEN: usize, SubTag> Deserialize<'de> + for Signature +{ fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let bytes = array_bytes::hex2bytes(&String::deserialize(deserializer)?) .map_err(|e| de::Error::custom(format!("{:?}", e)))?; - Signature::::try_from(bytes.as_ref()).map_err(|e| { + Signature::::try_from(bytes.as_ref()).map_err(|e| { de::Error::custom(format!("Error converting deserialized data into signature: {:?}", e)) }) } } -impl From> - for [u8; LEFT_PLUS_RIGHT_LEN] -{ - fn from(signature: Signature) -> [u8; LEFT_PLUS_RIGHT_LEN] { - signature.0 - } -} - -impl sp_std::fmt::Debug for Signature +impl sp_std::fmt::Debug + for Signature where [u8; LEFT_PLUS_RIGHT_LEN]: crate::hexdisplay::AsBytesRef, { @@ -392,24 +297,30 @@ where } } -impl UncheckedFrom<[u8; LEFT_PLUS_RIGHT_LEN]> - for Signature -{ - fn unchecked_from(data: [u8; LEFT_PLUS_RIGHT_LEN]) -> Self { - Signature(data) - } -} - /// A key pair. -#[derive(Clone)] pub struct Pair< LeftPair: PairT, RightPair: PairT, const PUBLIC_KEY_LEN: usize, const SIGNATURE_LEN: usize, + SubTag, > { left: LeftPair, right: RightPair, + _phantom: PhantomData SubTag>, +} + +impl< + LeftPair: PairT + Clone, + RightPair: PairT + Clone, + const PUBLIC_KEY_LEN: usize, + const SIGNATURE_LEN: usize, + SubTag, + > Clone for Pair +{ + fn clone(&self) -> Self { + Self { left: self.left.clone(), right: self.right.clone(), _phantom: PhantomData } + } } impl< @@ -417,18 +328,19 @@ impl< RightPair: PairT, const PUBLIC_KEY_LEN: usize, const SIGNATURE_LEN: usize, - > PairT for Pair + SubTag: PairedCryptoSubTagBound, + > PairT for Pair where - Pair: CryptoType, + Pair: CryptoType, LeftPair::Signature: SignatureBound, RightPair::Signature: SignatureBound, - Public: CryptoType, + Public: CryptoType, LeftPair::Seed: From + Into, RightPair::Seed: From + Into, { type Seed = Seed; - type Public = Public; - type Signature = Signature; + type Public = Public; + type Signature = Signature; fn from_seed_slice(seed_slice: &[u8]) -> Result { if seed_slice.len() != SECURE_SEED_LEN { @@ -436,7 +348,7 @@ where } let left = LeftPair::from_seed_slice(&seed_slice)?; let right = RightPair::from_seed_slice(&seed_slice)?; - Ok(Pair { left, right }) + Ok(Pair { left, right, _phantom: PhantomData }) } /// Derive a child key from a series of given junctions. @@ -459,7 +371,7 @@ where _ => None, }; - Ok((Self { left: left.0, right: right.0 }, seed)) + Ok((Self { left: left.0, right: right.0, _phantom: PhantomData }, seed)) } fn public(&self) -> Self::Public { @@ -479,16 +391,18 @@ where Self::Signature::unchecked_from(raw) } - fn verify>(sig: &Self::Signature, message: M, public: &Self::Public) -> bool { + fn verify>( + sig: &Self::Signature, + message: Msg, + public: &Self::Public, + ) -> bool { let Ok(left_pub) = public.0[..LeftPair::Public::LEN].try_into() else { return false }; let Ok(left_sig) = sig.0[0..LeftPair::Signature::LEN].try_into() else { return false }; if !LeftPair::verify(&left_sig, message.as_ref(), &left_pub) { return false } - let Ok(right_pub) = public.0[LeftPair::Public::LEN..PUBLIC_KEY_LEN].try_into() else { - return false - }; + let Ok(right_pub) = public.0[LeftPair::Public::LEN..].try_into() else { return false }; let Ok(right_sig) = sig.0[LeftPair::Signature::LEN..].try_into() else { return false }; RightPair::verify(&right_sig, message.as_ref(), &right_pub) } @@ -506,6 +420,7 @@ where mod test { use super::*; use crate::{crypto::DEV_PHRASE, KeccakHasher}; + use codec::{Decode, Encode}; use ecdsa_bls377::{Pair, Signature}; use crate::{bls377, ecdsa}; diff --git a/substrate/primitives/core/src/sr25519.rs b/substrate/primitives/core/src/sr25519.rs index 6c04eb8def1..ee0546bc534 100644 --- a/substrate/primitives/core/src/sr25519.rs +++ b/substrate/primitives/core/src/sr25519.rs @@ -19,6 +19,7 @@ //! //! Note: `CHAIN_CODE_LENGTH` must be equal to `crate::crypto::JUNCTION_ID_LEN` //! for this to work. + #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; @@ -30,20 +31,16 @@ use schnorrkel::{ }; use sp_std::vec::Vec; -use crate::{ - crypto::{ - ByteArray, CryptoType, CryptoTypeId, Derive, FromEntropy, Public as TraitPublic, - UncheckedFrom, - }, - hash::{H256, H512}, +use crate::crypto::{ + CryptoType, CryptoTypeId, Derive, Public as TraitPublic, PublicBytes, SignatureBytes, }; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_std::ops::Deref; use schnorrkel::keys::{MINI_SECRET_KEY_LENGTH, SECRET_KEY_LENGTH}; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "std")] use sp_runtime_interface::pass_by::PassByInner; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; @@ -54,22 +51,17 @@ const SIGNING_CTX: &[u8] = b"substrate"; /// An identifier used to match public keys against sr25519 keys pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"sr25"); +/// The byte length of public key +pub const PUBLIC_KEY_SERIALIZED_SIZE: usize = 32; + +/// The byte length of signature +pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; + +#[doc(hidden)] +pub struct Sr25519Tag; + /// An Schnorrkel/Ristretto x25519 ("sr25519") public key. -#[derive( - PartialEq, - Eq, - PartialOrd, - Ord, - Clone, - Copy, - Encode, - Decode, - PassByInner, - MaxEncodedLen, - TypeInfo, - Hash, -)] -pub struct Public(pub [u8; 32]); +pub type Public = PublicBytes; /// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. pub struct Pair(Keypair); @@ -84,52 +76,6 @@ impl Clone for Pair { } } -impl FromEntropy for Public { - fn from_entropy(input: &mut impl codec::Input) -> Result { - let mut result = Self([0u8; 32]); - input.read(&mut result.0[..])?; - Ok(result) - } -} - -impl AsRef<[u8; 32]> for Public { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl Deref for Public { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for [u8; 32] { - fn from(x: Public) -> [u8; 32] { - x.0 - } -} - -impl From for H256 { - fn from(x: Public) -> H256 { - x.0.into() - } -} - #[cfg(feature = "std")] impl std::str::FromStr for Public { type Err = crate::crypto::PublicError; @@ -139,31 +85,6 @@ impl std::str::FromStr for Public { } } -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != Self::LEN { - return Err(()) - } - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl UncheckedFrom<[u8; 32]> for Public { - fn unchecked_from(x: [u8; 32]) -> Self { - Public::from_raw(x) - } -} - -impl UncheckedFrom for Public { - fn unchecked_from(x: H256) -> Self { - Public::from_h256(x) - } -} - #[cfg(feature = "std")] impl std::fmt::Display for Public { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -175,7 +96,7 @@ impl sp_std::fmt::Debug for Public { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(self.inner()), &s[0..8]) } #[cfg(not(feature = "std"))] @@ -206,22 +127,7 @@ impl<'de> Deserialize<'de> for Public { } /// An Schnorrkel/Ristretto x25519 ("sr25519") signature. -#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq, Hash)] -pub struct Signature(pub [u8; 64]); - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 64 { - let mut inner = [0u8; 64]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} +pub type Signature = SignatureBytes; #[cfg(feature = "serde")] impl Serialize for Signature { @@ -246,48 +152,10 @@ impl<'de> Deserialize<'de> for Signature { } } -impl Clone for Signature { - fn clone(&self) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&self.0[..]); - Signature(r) - } -} - -impl From for [u8; 64] { - fn from(v: Signature) -> [u8; 64] { - v.0 - } -} - -impl From for H512 { - fn from(v: Signature) -> H512 { - H512::from(v.0) - } -} - -impl AsRef<[u8; 64]> for Signature { - fn as_ref(&self) -> &[u8; 64] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - #[cfg(feature = "full_crypto")] impl From for Signature { fn from(s: schnorrkel::Signature) -> Signature { - Signature(s.to_bytes()) + Signature::from(s.to_bytes()) } } @@ -303,45 +171,6 @@ impl sp_std::fmt::Debug for Signature { } } -impl UncheckedFrom<[u8; 64]> for Signature { - fn unchecked_from(data: [u8; 64]) -> Signature { - Signature(data) - } -} - -impl Signature { - /// A new instance from the given 64-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use - /// it if you are certain that the array actually is a signature, or if you - /// immediately verify the signature. All functions that verify signatures - /// will fail if the `Signature` is not actually a valid signature. - pub fn from_raw(data: [u8; 64]) -> Signature { - Signature(data) - } - - /// A new instance from the given slice that should be 64 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Option { - if data.len() != 64 { - return None - } - let mut r = [0u8; 64]; - r.copy_from_slice(data); - Some(Signature(r)) - } - - /// A new instance from an H512. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_h512(v: H512) -> Signature { - Signature(v.into()) - } -} - impl Derive for Public { /// Derive a child key from a series of given junctions. /// @@ -355,37 +184,10 @@ impl Derive for Public { DeriveJunction::Hard(_cc) => return None, } } - Some(Self(acc.to_bytes())) - } -} - -impl Public { - /// A new instance from the given 32-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_raw(data: [u8; 32]) -> Self { - Public(data) - } - - /// A new instance from an H256. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_h256(x: H256) -> Self { - Public(x.into()) - } - - /// Return a slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 32] { - self.as_ref() + Some(Self::from(acc.to_bytes())) } } -impl ByteArray for Public { - const LEN: usize = 32; -} - impl TraitPublic for Public {} #[cfg(feature = "std")] @@ -438,9 +240,7 @@ impl TraitPair for Pair { /// Get the public key. fn public(&self) -> Public { - let mut pk = [0u8; 32]; - pk.copy_from_slice(&self.0.public.to_bytes()); - Public(pk) + Public::from(self.0.public.to_bytes()) } /// Make a new key pair from raw secret seed material. @@ -720,7 +520,7 @@ pub mod vrf { impl VrfPublic for Public { fn vrf_verify(&self, data: &Self::VrfSignData, signature: &Self::VrfSignature) -> bool { let do_verify = || { - let public = schnorrkel::PublicKey::from_bytes(self)?; + let public = schnorrkel::PublicKey::from_bytes(&self.0)?; let inout = signature.pre_output.0.attach_input_hash(&public, data.transcript.0.clone())?; @@ -820,7 +620,10 @@ pub mod vrf { #[cfg(test)] mod tests { use super::{vrf::*, *}; - use crate::crypto::{Ss58Codec, VrfPublic, VrfSecret, DEV_ADDRESS, DEV_PHRASE}; + use crate::{ + crypto::{Ss58Codec, VrfPublic, VrfSecret, DEV_ADDRESS, DEV_PHRASE}, + ByteArray as _, + }; use serde_json; #[test] @@ -984,10 +787,10 @@ mod tests { let (pair, _) = Pair::generate(); let public = pair.public(); let message = b"Signed payload"; - let Signature(mut bytes) = pair.sign(&message[..]); + let mut signature = pair.sign(&message[..]); + let bytes = &mut signature.0; bytes[0] = !bytes[0]; bytes[2] = !bytes[2]; - let signature = Signature(bytes); assert!(!Pair::verify(&signature, &message[..], &public)); } diff --git a/substrate/primitives/keystore/src/testing.rs b/substrate/primitives/keystore/src/testing.rs index e10660b126a..d8610ecfa5b 100644 --- a/substrate/primitives/keystore/src/testing.rs +++ b/substrate/primitives/keystore/src/testing.rs @@ -528,7 +528,7 @@ mod tests { assert!(res.is_some()); // does not verify with default out-of-the-box verification - assert!(!ecdsa_bls377::Pair::verify(&res.clone().unwrap(), &msg[..], &pair.public())); + assert!(!ecdsa_bls377::Pair::verify(&res.unwrap(), &msg[..], &pair.public())); // should verify using keccak256 as hasher assert!(ecdsa_bls377::Pair::verify_with_hasher::( diff --git a/substrate/primitives/runtime/src/traits.rs b/substrate/primitives/runtime/src/traits.rs index caede5e2b59..9ee41339d50 100644 --- a/substrate/primitives/runtime/src/traits.rs +++ b/substrate/primitives/runtime/src/traits.rs @@ -133,7 +133,7 @@ impl Verify for sp_core::ecdsa::Signature { self.as_ref(), &sp_io::hashing::blake2_256(msg.get()), ) { - Ok(pubkey) => signer.as_ref() == &pubkey[..], + Ok(pubkey) => signer.0 == pubkey, _ => false, } } diff --git a/substrate/primitives/statement-store/src/lib.rs b/substrate/primitives/statement-store/src/lib.rs index bfcd0d1a52a..dbac017ff64 100644 --- a/substrate/primitives/statement-store/src/lib.rs +++ b/substrate/primitives/statement-store/src/lib.rs @@ -340,8 +340,8 @@ impl Statement { Some(Proof::OnChain { .. }) | None => SignatureVerificationResult::NoSignature, Some(Proof::Sr25519 { signature, signer }) => { let to_sign = self.signature_material(); - let signature = sp_core::sr25519::Signature(*signature); - let public = sp_core::sr25519::Public(*signer); + let signature = sp_core::sr25519::Signature::from(*signature); + let public = sp_core::sr25519::Public::from(*signer); if signature.verify(to_sign.as_slice(), &public) { SignatureVerificationResult::Valid(*signer) } else { @@ -350,8 +350,8 @@ impl Statement { }, Some(Proof::Ed25519 { signature, signer }) => { let to_sign = self.signature_material(); - let signature = sp_core::ed25519::Signature(*signature); - let public = sp_core::ed25519::Public(*signer); + let signature = sp_core::ed25519::Signature::from(*signature); + let public = sp_core::ed25519::Public::from(*signer); if signature.verify(to_sign.as_slice(), &public) { SignatureVerificationResult::Valid(*signer) } else { @@ -360,8 +360,8 @@ impl Statement { }, Some(Proof::Secp256k1Ecdsa { signature, signer }) => { let to_sign = self.signature_material(); - let signature = sp_core::ecdsa::Signature(*signature); - let public = sp_core::ecdsa::Public(*signer); + let signature = sp_core::ecdsa::Signature::from(*signature); + let public = sp_core::ecdsa::Public::from(*signer); if signature.verify(to_sign.as_slice(), &public) { let sender_hash = ::hash(signer); -- GitLab From c486da32b151a5d29276a9b5ee5b705f91b8bd01 Mon Sep 17 00:00:00 2001 From: Javier Viola <363911+pepoviola@users.noreply.github.com> Date: Tue, 19 Mar 2024 18:10:45 +0100 Subject: [PATCH 145/188] chore: bump zombienet version (1.3.95) (#3745) Bump zombienet version, this version have the latest version of `@polkadot/api` module and fix the failures in CI (e.g https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5570106). Thanks! --- .gitlab/pipeline/zombienet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/pipeline/zombienet.yml b/.gitlab/pipeline/zombienet.yml index 55120e66d0e..8d308714fab 100644 --- a/.gitlab/pipeline/zombienet.yml +++ b/.gitlab/pipeline/zombienet.yml @@ -1,7 +1,7 @@ .zombienet-refs: extends: .build-refs variables: - ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.91" + ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.95" include: # substrate tests -- GitLab From e659c4b3f744b1f04ec210e448485048b6eafa64 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Tue, 19 Mar 2024 20:13:51 +0100 Subject: [PATCH 146/188] Contracts: Test benchmarking v2 (#3585) Co-authored-by: command-bot <> --- .../frame/contracts/src/benchmarking/mod.rs | 2329 +++++++++-------- substrate/frame/contracts/src/weights.rs | 1497 ++++++----- 2 files changed, 2094 insertions(+), 1732 deletions(-) diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index 794777ef05c..ce2cf15d812 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -16,7 +16,6 @@ // limitations under the License. //! Benchmarks for the contracts pallet - #![cfg(feature = "runtime-benchmarks")] mod code; @@ -36,7 +35,7 @@ use crate::{ Pallet as Contracts, *, }; use codec::{Encode, MaxEncodedLen}; -use frame_benchmarking::v1::{account, benchmarks, whitelisted_caller}; +use frame_benchmarking::v2::*; use frame_support::{ self, pallet_prelude::StorageVersion, @@ -184,172 +183,215 @@ fn caller_funding() -> BalanceOf { BalanceOf::::max_value() / 10_000u32.into() } -benchmarks! { - where_clause { where +#[benchmarks( + where as codec::HasCompact>::Type: Clone + Eq + PartialEq + sp_std::fmt::Debug + scale_info::TypeInfo + codec::Encode, T: Config + pallet_balances::Config, BalanceOf: From< as Currency>::Balance>, as Currency>::Balance: From>, - } +)] +mod benchmarks { + use super::*; // The base weight consumed on processing contracts deletion queue. - #[pov_mode = Measured] - on_process_deletion_queue_batch {}: { - ContractInfo::::process_deletion_queue_batch(Weight::MAX) + #[benchmark(pov_mode = Measured)] + fn on_process_deletion_queue_batch() { + #[block] + { + ContractInfo::::process_deletion_queue_batch(Weight::MAX); + } } - #[skip_meta] - #[pov_mode = Measured] - on_initialize_per_trie_key { - let k in 0..1024; - let instance = Contract::::with_storage(WasmModule::dummy(), k, T::Schedule::get().limits.payload_len)?; + #[benchmark(skip_meta, pov_mode = Measured)] + fn on_initialize_per_trie_key(k: Linear<0, 1024>) -> Result<(), BenchmarkError> { + let instance = Contract::::with_storage( + WasmModule::dummy(), + k, + T::Schedule::get().limits.payload_len, + )?; instance.info()?.queue_trie_for_deletion(); - }: { - ContractInfo::::process_deletion_queue_batch(Weight::MAX) + + #[block] + { + ContractInfo::::process_deletion_queue_batch(Weight::MAX); + } + + Ok(()) } // This benchmarks the v9 migration step (update codeStorage). - #[pov_mode = Measured] - v9_migration_step { - let c in 0 .. T::MaxCodeLen::get(); + #[benchmark(pov_mode = Measured)] + fn v9_migration_step(c: Linear<0, { T::MaxCodeLen::get() }>) { v09::store_old_dummy_code::(c as usize); let mut m = v09::Migration::::default(); - }: { - m.step(); + #[block] + { + m.step(); + } } // This benchmarks the v10 migration step (use dedicated deposit_account). - #[pov_mode = Measured] - v10_migration_step { - let contract = >::with_caller( - whitelisted_caller(), WasmModule::dummy(), vec![], - )?; - - v10::store_old_contract_info::>(contract.account_id.clone(), contract.info()?); + #[benchmark(pov_mode = Measured)] + fn v10_migration_step() -> Result<(), BenchmarkError> { + let contract = + >::with_caller(whitelisted_caller(), WasmModule::dummy(), vec![])?; + + v10::store_old_contract_info::>( + contract.account_id.clone(), + contract.info()?, + ); let mut m = v10::Migration::>::default(); - }: { - m.step(); + + #[block] + { + m.step(); + } + + Ok(()) } - // This benchmarks the v11 migration step (Don't rely on reserved balances keeping an account alive). - #[pov_mode = Measured] - v11_migration_step { - let k in 0 .. 1024; + // This benchmarks the v11 migration step (Don't rely on reserved balances keeping an account + // alive). + #[benchmark(pov_mode = Measured)] + fn v11_migration_step(k: Linear<0, 1024>) { v11::fill_old_queue::(k as usize); let mut m = v11::Migration::::default(); - }: { - m.step(); + + #[block] + { + m.step(); + } } // This benchmarks the v12 migration step (Move `OwnerInfo` to `CodeInfo`, // add `determinism` field to the latter, clear `CodeStorage` // and repay deposits). - #[pov_mode = Measured] - v12_migration_step { - let c in 0 .. T::MaxCodeLen::get(); - v12::store_old_dummy_code::< - T, - pallet_balances::Pallet - >(c as usize, account::("account", 0, 0)); + #[benchmark(pov_mode = Measured)] + fn v12_migration_step(c: Linear<0, { T::MaxCodeLen::get() }>) { + v12::store_old_dummy_code::>( + c as usize, + account::("account", 0, 0), + ); let mut m = v12::Migration::>::default(); - }: { - m.step(); + + #[block] + { + m.step(); + } } // This benchmarks the v13 migration step (Add delegate_dependencies field). - #[pov_mode = Measured] - v13_migration_step { - let contract = >::with_caller( - whitelisted_caller(), WasmModule::dummy(), vec![], - )?; + #[benchmark(pov_mode = Measured)] + fn v13_migration_step() -> Result<(), BenchmarkError> { + let contract = + >::with_caller(whitelisted_caller(), WasmModule::dummy(), vec![])?; v13::store_old_contract_info::(contract.account_id.clone(), contract.info()?); let mut m = v13::Migration::::default(); - }: { - m.step(); + + #[block] + { + m.step(); + } + Ok(()) } - // This benchmarks the v14 migration step (Move code owners' reserved balance to be held instead). - #[pov_mode = Measured] - v14_migration_step { + // This benchmarks the v14 migration step (Move code owners' reserved balance to be held + // instead). + #[benchmark(pov_mode = Measured)] + fn v14_migration_step() { let account = account::("account", 0, 0); T::Currency::set_balance(&account, caller_funding::()); v14::store_dummy_code::>(account); let mut m = v14::Migration::>::default(); - }: { - m.step(); + + #[block] + { + m.step(); + } } // This benchmarks the v15 migration step (remove deposit account). - #[pov_mode = Measured] - v15_migration_step { - let contract = >::with_caller( - whitelisted_caller(), WasmModule::dummy(), vec![], - )?; + #[benchmark(pov_mode = Measured)] + fn v15_migration_step() -> Result<(), BenchmarkError> { + let contract = + >::with_caller(whitelisted_caller(), WasmModule::dummy(), vec![])?; v15::store_old_contract_info::(contract.account_id.clone(), contract.info()?); let mut m = v15::Migration::::default(); - }: { - m.step(); + + #[block] + { + m.step(); + } + + Ok(()) } // This benchmarks the weight of executing Migration::migrate to execute a noop migration. - #[pov_mode = Measured] - migration_noop { + #[benchmark(pov_mode = Measured)] + fn migration_noop() { let version = LATEST_MIGRATION_VERSION; assert_eq!(StorageVersion::get::>(), version); - }: { - Migration::::migrate(Weight::MAX) - } verify { + #[block] + { + Migration::::migrate(Weight::MAX); + } assert_eq!(StorageVersion::get::>(), version); } // This benchmarks the weight of dispatching migrate to execute 1 `NoopMigraton` - #[pov_mode = Measured] - migrate { + #[benchmark(pov_mode = Measured)] + fn migrate() { let latest_version = LATEST_MIGRATION_VERSION; StorageVersion::new(latest_version - 2).put::>(); - as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade(); - let caller: T::AccountId = whitelisted_caller(); - let origin = RawOrigin::Signed(caller.clone()); - }: _(origin, Weight::MAX) - verify { + as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade(); + + #[extrinsic_call] + _(RawOrigin::Signed(whitelisted_caller()), Weight::MAX); + assert_eq!(StorageVersion::get::>(), latest_version - 1); } - // This benchmarks the weight of running on_runtime_upgrade when there are no migration in progress. - #[pov_mode = Measured] - on_runtime_upgrade_noop { + // This benchmarks the weight of running on_runtime_upgrade when there are no migration in + // progress. + #[benchmark(pov_mode = Measured)] + fn on_runtime_upgrade_noop() { let latest_version = LATEST_MIGRATION_VERSION; assert_eq!(StorageVersion::get::>(), latest_version); - }: { - as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade() - } verify { + #[block] + { + as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade(); + } assert!(MigrationInProgress::::get().is_none()); } - // This benchmarks the weight of running on_runtime_upgrade when there is a migration in progress. - #[pov_mode = Measured] - on_runtime_upgrade_in_progress { + // This benchmarks the weight of running on_runtime_upgrade when there is a migration in + // progress. + #[benchmark(pov_mode = Measured)] + fn on_runtime_upgrade_in_progress() { let latest_version = LATEST_MIGRATION_VERSION; StorageVersion::new(latest_version - 2).put::>(); let v = vec![42u8].try_into().ok(); MigrationInProgress::::set(v.clone()); - }: { - as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade() - } verify { + #[block] + { + as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade(); + } assert!(MigrationInProgress::::get().is_some()); assert_eq!(MigrationInProgress::::get(), v); } - // This benchmarks the weight of running on_runtime_upgrade when there is a migration to process. - #[pov_mode = Measured] - on_runtime_upgrade { + // This benchmarks the weight of running on_runtime_upgrade when there is a migration to + // process. + #[benchmark(pov_mode = Measured)] + fn on_runtime_upgrade() { let latest_version = LATEST_MIGRATION_VERSION; StorageVersion::new(latest_version - 2).put::>(); - }: { - as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade() - } verify { + #[block] + { + as frame_support::traits::OnRuntimeUpgrade>::on_runtime_upgrade(); + } assert!(MigrationInProgress::::get().is_some()); } @@ -357,17 +399,25 @@ benchmarks! { // the sandbox. This does **not** include the actual execution for which the gas meter // is responsible. This is achieved by generating all code to the `deploy` function // which is in the wasm module but not executed on `call`. - // The results are supposed to be used as `call_with_code_per_byte(c) - call_with_code_per_byte(0)`. - #[pov_mode = Measured] - call_with_code_per_byte { - let c in 0 .. T::MaxCodeLen::get(); + // The results are supposed to be used as `call_with_code_per_byte(c) - + // call_with_code_per_byte(0)`. + #[benchmark(pov_mode = Measured)] + fn call_with_code_per_byte( + c: Linear<0, { T::MaxCodeLen::get() }>, + ) -> Result<(), BenchmarkError> { let instance = Contract::::with_caller( - whitelisted_caller(), WasmModule::sized(c, Location::Deploy, false), vec![], + whitelisted_caller(), + WasmModule::sized(c, Location::Deploy, false), + vec![], )?; let value = Pallet::::min_balance(); - let origin = RawOrigin::Signed(instance.caller.clone()); let callee = instance.addr; - }: call(origin, callee, value, Weight::MAX, None, vec![]) + + #[extrinsic_call] + call(RawOrigin::Signed(instance.caller.clone()), callee, value, Weight::MAX, None, vec![]); + + Ok(()) + } // This constructs a contract that is maximal expensive to instrument. // It creates a maximum number of metering blocks per byte. @@ -379,11 +429,12 @@ benchmarks! { // `c`: Size of the code in bytes. // `i`: Size of the input in bytes. // `s`: Size of the salt in bytes. - #[pov_mode = Measured] - instantiate_with_code { - let c in 0 .. T::MaxCodeLen::get(); - let i in 0 .. code::max_pages::() * 64 * 1024; - let s in 0 .. code::max_pages::() * 64 * 1024; + #[benchmark(pov_mode = Measured)] + fn instantiate_with_code( + c: Linear<0, { T::MaxCodeLen::get() }>, + i: Linear<0, { code::max_pages::() * 64 * 1024 }>, + s: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) { let input = vec![42u8; i as usize]; let salt = vec![42u8; s as usize]; let value = Pallet::::min_balance(); @@ -392,11 +443,14 @@ benchmarks! { let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call, false); let origin = RawOrigin::Signed(caller.clone()); let addr = Contracts::::contract_address(&caller, &hash, &input, &salt); - }: _(origin, value, Weight::MAX, None, code, input, salt) - verify { - let deposit = T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &addr); + #[extrinsic_call] + _(origin, value, Weight::MAX, None, code, input, salt); + + let deposit = + T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &addr); // uploading the code reserves some balance in the callers account - let code_deposit = T::Currency::balance_on_hold(&HoldReason::CodeUploadDepositReserve.into(), &caller); + let code_deposit = + T::Currency::balance_on_hold(&HoldReason::CodeUploadDepositReserve.into(), &caller); assert_eq!( T::Currency::balance(&caller), caller_funding::() - value - deposit - code_deposit - Pallet::::min_balance(), @@ -408,22 +462,25 @@ benchmarks! { // Instantiate uses a dummy contract constructor to measure the overhead of the instantiate. // `i`: Size of the input in bytes. // `s`: Size of the salt in bytes. - #[pov_mode = Measured] - instantiate { - let i in 0 .. code::max_pages::() * 64 * 1024; - let s in 0 .. code::max_pages::() * 64 * 1024; + #[benchmark(pov_mode = Measured)] + fn instantiate( + i: Linear<0, { code::max_pages::() * 64 * 1024 }>, + s: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { let input = vec![42u8; i as usize]; let salt = vec![42u8; s as usize]; let value = Pallet::::min_balance(); let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); let WasmModule { code, hash, .. } = WasmModule::::dummy(); - let origin = RawOrigin::Signed(caller.clone()); let addr = Contracts::::contract_address(&caller, &hash, &input, &salt); Contracts::::store_code_raw(code, caller.clone())?; - }: _(origin, value, Weight::MAX, None, hash, input, salt) - verify { - let deposit = T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &addr); + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), value, Weight::MAX, None, hash, input, salt); + + let deposit = + T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &addr); // value was removed from the caller assert_eq!( T::Currency::balance(&caller), @@ -431,6 +488,8 @@ benchmarks! { ); // contract has the full value assert_eq!(T::Currency::balance(&addr), value + Pallet::::min_balance()); + + Ok(()) } // We just call a dummy contract to measure the overhead of the call extrinsic. @@ -440,19 +499,21 @@ benchmarks! { // part of `seal_input`. The costs for invoking a contract of a specific size are not part // of this benchmark because we cannot know the size of the contract when issuing a call // transaction. See `call_with_code_per_byte` for this. - #[pov_mode = Measured] - call { + #[benchmark(pov_mode = Measured)] + fn call() -> Result<(), BenchmarkError> { let data = vec![42u8; 1024]; - let instance = Contract::::with_caller( - whitelisted_caller(), WasmModule::dummy(), vec![], - )?; + let instance = + Contract::::with_caller(whitelisted_caller(), WasmModule::dummy(), vec![])?; let value = Pallet::::min_balance(); let origin = RawOrigin::Signed(instance.caller.clone()); let callee = instance.addr.clone(); let before = T::Currency::balance(&instance.account_id); - }: _(origin, callee, value, Weight::MAX, None, data) - verify { - let deposit = T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &instance.account_id); + #[extrinsic_call] + _(origin, callee, value, Weight::MAX, None, data); + let deposit = T::Currency::balance_on_hold( + &HoldReason::StorageDepositReserve.into(), + &instance.account_id, + ); // value and value transferred via call should be removed from the caller assert_eq!( T::Currency::balance(&instance.caller), @@ -462,92 +523,93 @@ benchmarks! { assert_eq!(T::Currency::balance(&instance.account_id), before + value); // contract should still exist instance.info()?; + + Ok(()) } // This constructs a contract that is maximal expensive to instrument. // It creates a maximum number of metering blocks per byte. // `c`: Size of the code in bytes. - #[pov_mode = Measured] - upload_code_determinism_enforced { - let c in 0 .. T::MaxCodeLen::get(); + #[benchmark(pov_mode = Measured)] + fn upload_code_determinism_enforced(c: Linear<0, { T::MaxCodeLen::get() }>) { let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call, false); let origin = RawOrigin::Signed(caller.clone()); - }: upload_code(origin, code, None, Determinism::Enforced) - verify { + #[extrinsic_call] + upload_code(origin, code, None, Determinism::Enforced); // uploading the code reserves some balance in the callers account assert!(T::Currency::total_balance_on_hold(&caller) > 0u32.into()); assert!(>::code_exists(&hash)); } - // Uploading code with [`Determinism::Relaxed`] should be more expensive than uploading code with [`Determinism::Enforced`], - // as we always try to save the code with [`Determinism::Enforced`] first. - #[pov_mode = Measured] - upload_code_determinism_relaxed { - let c in 0 .. T::MaxCodeLen::get(); + // Uploading code with [`Determinism::Relaxed`] should be more expensive than uploading code + // with [`Determinism::Enforced`], as we always try to save the code with + // [`Determinism::Enforced`] first. + #[benchmark(pov_mode = Measured)] + fn upload_code_determinism_relaxed(c: Linear<0, { T::MaxCodeLen::get() }>) { let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); let WasmModule { code, hash, .. } = WasmModule::::sized(c, Location::Call, true); let origin = RawOrigin::Signed(caller.clone()); - }: upload_code(origin, code, None, Determinism::Relaxed) - verify { + #[extrinsic_call] + upload_code(origin, code, None, Determinism::Relaxed); assert!(T::Currency::total_balance_on_hold(&caller) > 0u32.into()); assert!(>::code_exists(&hash)); - // Ensure that the benchmark follows the most expensive path, i.e., the code is saved with [`Determinism::Relaxed`] after trying to save it with [`Determinism::Enforced`]. + // Ensure that the benchmark follows the most expensive path, i.e., the code is saved with assert_eq!(CodeInfoOf::::get(&hash).unwrap().determinism(), Determinism::Relaxed); } // Removing code does not depend on the size of the contract because all the information // needed to verify the removal claim (refcount, owner) is stored in a separate storage // item (`CodeInfoOf`). - #[pov_mode = Measured] - remove_code { + #[benchmark(pov_mode = Measured)] + fn remove_code() -> Result<(), BenchmarkError> { let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); let WasmModule { code, hash, .. } = WasmModule::::dummy(); let origin = RawOrigin::Signed(caller.clone()); - let uploaded = >::bare_upload_code(caller.clone(), code, None, Determinism::Enforced)?; + let uploaded = + >::bare_upload_code(caller.clone(), code, None, Determinism::Enforced)?; assert_eq!(uploaded.code_hash, hash); assert_eq!(uploaded.deposit, T::Currency::total_balance_on_hold(&caller)); assert!(>::code_exists(&hash)); - }: _(origin, hash) - verify { + #[extrinsic_call] + _(origin, hash); // removing the code should have unreserved the deposit assert_eq!(T::Currency::total_balance_on_hold(&caller), 0u32.into()); assert!(>::code_removed(&hash)); + Ok(()) } - #[pov_mode = Measured] - set_code { - let instance = >::with_caller( - whitelisted_caller(), WasmModule::dummy(), vec![], - )?; + #[benchmark(pov_mode = Measured)] + fn set_code() -> Result<(), BenchmarkError> { + let instance = + >::with_caller(whitelisted_caller(), WasmModule::dummy(), vec![])?; // we just add some bytes so that the code hash is different let WasmModule { code, hash, .. } = >::dummy_with_bytes(128); >::store_code_raw(code, instance.caller.clone())?; let callee = instance.addr.clone(); assert_ne!(instance.info()?.code_hash, hash); - }: _(RawOrigin::Root, callee, hash) - verify { + #[extrinsic_call] + _(RawOrigin::Root, callee, hash); assert_eq!(instance.info()?.code_hash, hash); + Ok(()) } - #[pov_mode = Measured] - seal_caller { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal0", "seal_caller", r - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_caller(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = Contract::::new(WasmModule::getter("seal0", "seal_caller", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); - #[pov_mode = Measured] - seal_is_contract { - let r in 0 .. API_BENCHMARK_RUNS; - let accounts = (0 .. r) - .map(|n| account::("account", n, 0)) - .collect::>(); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_is_contract(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let accounts = (0..r).map(|n| account::("account", n, 0)).collect::>(); let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); let accounts_bytes = accounts.iter().flat_map(|a| a.encode()).collect::>(); let code = WasmModule::::from(ModuleDefinition { @@ -558,18 +620,16 @@ benchmarks! { params: vec![ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: accounts_bytes - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, account_len as u32), // address_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: accounts_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, account_len as u32), // address_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; @@ -578,18 +638,17 @@ benchmarks! { >::insert(acc, info.clone()); } let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); - #[pov_mode = Measured] - seal_code_hash { - let r in 0 .. API_BENCHMARK_RUNS; - let accounts = (0 .. r) - .map(|n| account::("account", n, 0)) - .collect::>(); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_code_hash(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let accounts = (0..r).map(|n| account::("account", n, 0)).collect::>(); let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); let accounts_bytes = accounts.iter().flat_map(|a| a.encode()).collect::>(); - let accounts_len = accounts_bytes.len(); - let pages = code::max_pages::(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -603,19 +662,19 @@ benchmarks! { offset: 0, value: 32u32.to_le_bytes().to_vec(), // output length }, - DataSegment { - offset: 36, - value: accounts_bytes, - }, + DataSegment { offset: 36, value: accounts_bytes }, ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(36, account_len as u32), // address_ptr - Regular(Instruction::I32Const(4)), // ptr to output data - Regular(Instruction::I32Const(0)), // ptr to output length - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(36, account_len as u32), // address_ptr + Regular(Instruction::I32Const(4)), // ptr to output data + Regular(Instruction::I32Const(0)), // ptr to output length + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; @@ -624,20 +683,23 @@ benchmarks! { >::insert(acc, info.clone()); } let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_own_code_hash { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal0", "seal_own_code_hash", r - ), vec![])?; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_own_code_hash(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::getter("seal0", "seal_own_code_hash", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_caller_is_origin { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_caller_is_origin(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -646,20 +708,18 @@ benchmarks! { params: vec![], return_type: Some(ValueType::I32), }], - call_body: Some(body::repeated(r, &[ - Instruction::Call(0), - Instruction::Drop, - ])), - .. Default::default() + call_body: Some(body::repeated(r, &[Instruction::Call(0), Instruction::Drop])), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_caller_is_root { - let r in 0 .. API_BENCHMARK_RUNS; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + #[benchmark(pov_mode = Measured)] + fn seal_caller_is_root(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -668,82 +728,84 @@ benchmarks! { params: vec![], return_type: Some(ValueType::I32), }], - call_body: Some(body::repeated(r, &[ - Instruction::Call(0), - Instruction::Drop, - ])), - .. Default::default() + call_body: Some(body::repeated(r, &[Instruction::Call(0), Instruction::Drop])), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Root; - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_address { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal0", "seal_address", r - ), vec![])?; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_address(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = Contract::::new(WasmModule::getter("seal0", "seal_address", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_gas_left { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal1", "gas_left", r - ), vec![])?; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_gas_left(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = Contract::::new(WasmModule::getter("seal1", "gas_left", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_balance { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal0", "seal_balance", r - ), vec![])?; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_balance(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = Contract::::new(WasmModule::getter("seal0", "seal_balance", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_value_transferred { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal0", "seal_value_transferred", r - ), vec![])?; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_value_transferred(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::getter("seal0", "seal_value_transferred", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_minimum_balance { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal0", "seal_minimum_balance", r - ), vec![])?; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_minimum_balance(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::getter("seal0", "seal_minimum_balance", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_block_number { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal0", "seal_block_number", r - ), vec![])?; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_block_number(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::getter("seal0", "seal_block_number", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - - #[pov_mode = Measured] - seal_now { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::getter( - "seal0", "seal_now", r - ), vec![])?; + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } + + #[benchmark(pov_mode = Measured)] + fn seal_now(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = Contract::::new(WasmModule::getter("seal0", "seal_now", r), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_weight_to_fee { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_weight_to_fee(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let pages = code::max_pages::(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), @@ -757,22 +819,27 @@ benchmarks! { offset: 0, value: (pages * 64 * 1024 - 4).to_le_bytes().to_vec(), }], - call_body: Some(body::repeated(r, &[ - Instruction::I64Const(500_000), - Instruction::I64Const(300_000), - Instruction::I32Const(4), - Instruction::I32Const(0), - Instruction::Call(0), - ])), - .. Default::default() + call_body: Some(body::repeated( + r, + &[ + Instruction::I64Const(500_000), + Instruction::I64Const(300_000), + Instruction::I32Const(4), + Instruction::I32Const(0), + Instruction::Call(0), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_input { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_input(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -781,26 +848,28 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32], return_type: None, }], - data_segments: vec![ - DataSegment { - offset: 0, - value: 0u32.to_le_bytes().to_vec(), - }, - ], - call_body: Some(body::repeated(r, &[ - Instruction::I32Const(4), // ptr where to store output - Instruction::I32Const(0), // ptr to length - Instruction::Call(0), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: 0u32.to_le_bytes().to_vec() }], + call_body: Some(body::repeated( + r, + &[ + Instruction::I32Const(4), // ptr where to store output + Instruction::I32Const(0), // ptr to length + Instruction::Call(0), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_input_per_byte { - let n in 0 .. code::max_pages::() * 64 * 1024; + #[benchmark(pov_mode = Measured)] + fn seal_input_per_byte( + n: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { let buffer_size = code::max_pages::() * 64 * 1024 - 4; let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), @@ -810,31 +879,31 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32], return_type: None, }], - data_segments: vec![ - DataSegment { - offset: 0, - value: buffer_size.to_le_bytes().to_vec(), - }, - ], + data_segments: vec![DataSegment { + offset: 0, + value: buffer_size.to_le_bytes().to_vec(), + }], call_body: Some(body::plain(vec![ Instruction::I32Const(4), // ptr where to store output Instruction::I32Const(0), // ptr to length Instruction::Call(0), Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let data = vec![42u8; n.min(buffer_size) as usize]; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, data) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, data); + Ok(()) + } // We cannot call `seal_return` multiple times. Therefore our weight determination is not // as precise as with other APIs. Because this function can only be called once per // contract it cannot be used as an attack vector. - #[pov_mode = Measured] - seal_return { - let r in 0 .. 1; + #[benchmark(pov_mode = Measured)] + fn seal_return(r: Linear<0, 1>) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -843,21 +912,28 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32, ValueType::I32], return_type: None, }], - call_body: Some(body::repeated(r, &[ - Instruction::I32Const(0), // flags - Instruction::I32Const(0), // data_ptr - Instruction::I32Const(0), // data_len - Instruction::Call(0), - ])), - .. Default::default() + call_body: Some(body::repeated( + r, + &[ + Instruction::I32Const(0), // flags + Instruction::I32Const(0), // data_ptr + Instruction::I32Const(0), // data_len + Instruction::Call(0), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_return_per_byte { - let n in 0 .. code::max_pages::() * 64 * 1024; + #[benchmark(pov_mode = Measured)] + fn seal_return_per_byte( + n: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -867,22 +943,24 @@ benchmarks! { return_type: None, }], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // flags - Instruction::I32Const(0), // data_ptr + Instruction::I32Const(0), // flags + Instruction::I32Const(0), // data_ptr Instruction::I32Const(n as i32), // data_len Instruction::Call(0), Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // The same argument as for `seal_return` is true here. - #[pov_mode = Measured] - seal_terminate { - let r in 0 .. 1; + #[benchmark(pov_mode = Measured)] + fn seal_terminate(r: Linear<0, 1>) -> Result<(), BenchmarkError> { let beneficiary = account::("beneficiary", 0, 0); let beneficiary_bytes = beneficiary.encode(); let beneficiary_len = beneficiary_bytes.len(); @@ -915,50 +993,74 @@ benchmarks! { name: "lock_delegate_dependency", params: vec![ValueType::I32], return_type: None, - } + }, ], data_segments: vec![ - DataSegment { - offset: 0, - value: beneficiary_bytes, - }, - DataSegment { - offset: beneficiary_len as u32, - value: code_hashes_bytes, - }, + DataSegment { offset: 0, value: beneficiary_bytes }, + DataSegment { offset: beneficiary_len as u32, value: code_hashes_bytes }, ], - deploy_body: Some(body::repeated_dyn(T::MaxDelegateDependencies::get(), vec![ - Counter(beneficiary_len as u32, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(1)), - ])), - call_body: Some(body::repeated(r, &[ - Instruction::I32Const(0), // beneficiary_ptr - Instruction::I32Const(beneficiary_len as i32), // beneficiary_len - Instruction::Call(0), - ])), - .. Default::default() + deploy_body: Some(body::repeated_dyn( + T::MaxDelegateDependencies::get(), + vec![ + Counter(beneficiary_len as u32, code_hash_len as u32), // code_hash_ptr + Regular(Instruction::Call(1)), + ], + )), + call_body: Some(body::repeated( + r, + &[ + Instruction::I32Const(0), // beneficiary_ptr + Instruction::I32Const(beneficiary_len as i32), // beneficiary_len + Instruction::Call(0), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); assert_eq!(T::Currency::total_balance(&beneficiary), 0u32.into()); - assert_eq!(T::Currency::balance(&instance.account_id), Pallet::::min_balance() * 2u32.into()); - assert_ne!(T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &instance.account_id), 0u32.into()); - assert_eq!(ContractInfoOf::::get(&instance.account_id).unwrap().delegate_dependencies_count() as u32, T::MaxDelegateDependencies::get()); - }: call(origin, instance.addr.clone(), 0u32.into(), Weight::MAX, None, vec![]) - verify { + assert_eq!( + T::Currency::balance(&instance.account_id), + Pallet::::min_balance() * 2u32.into() + ); + assert_ne!( + T::Currency::balance_on_hold( + &HoldReason::StorageDepositReserve.into(), + &instance.account_id + ), + 0u32.into() + ); + assert_eq!( + ContractInfoOf::::get(&instance.account_id) + .unwrap() + .delegate_dependencies_count() as u32, + T::MaxDelegateDependencies::get() + ); + #[extrinsic_call] + call(origin, instance.addr.clone(), 0u32.into(), Weight::MAX, None, vec![]); + if r > 0 { assert_eq!(T::Currency::total_balance(&instance.account_id), 0u32.into()); - assert_eq!(T::Currency::balance_on_hold(&HoldReason::StorageDepositReserve.into(), &instance.account_id), 0u32.into()); - assert_eq!(T::Currency::total_balance(&beneficiary), Pallet::::min_balance() * 2u32.into()); + assert_eq!( + T::Currency::balance_on_hold( + &HoldReason::StorageDepositReserve.into(), + &instance.account_id + ), + 0u32.into() + ); + assert_eq!( + T::Currency::total_balance(&beneficiary), + Pallet::::min_balance() * 2u32.into() + ); } + Ok(()) } // We benchmark only for the maximum subject length. We assume that this is some lowish // number (< 1 KB). Therefore we are not overcharging too much in case a smaller subject is // used. - #[pov_mode = Measured] - seal_random { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_random(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let pages = code::max_pages::(); let subject_len = T::Schedule::get().limits.subject_len; assert!(subject_len < 1024); @@ -970,30 +1072,33 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], return_type: None, }], - data_segments: vec![ - DataSegment { - offset: 0, - value: (pages * 64 * 1024 - subject_len - 4).to_le_bytes().to_vec(), - }, - ], - call_body: Some(body::repeated(r, &[ - Instruction::I32Const(4), // subject_ptr - Instruction::I32Const(subject_len as i32), // subject_len - Instruction::I32Const((subject_len + 4) as i32), // out_ptr - Instruction::I32Const(0), // out_len_ptr - Instruction::Call(0), - ])), - .. Default::default() + data_segments: vec![DataSegment { + offset: 0, + value: (pages * 64 * 1024 - subject_len - 4).to_le_bytes().to_vec(), + }], + call_body: Some(body::repeated( + r, + &[ + Instruction::I32Const(4), // subject_ptr + Instruction::I32Const(subject_len as i32), // subject_len + Instruction::I32Const((subject_len + 4) as i32), // out_ptr + Instruction::I32Const(0), // out_len_ptr + Instruction::Call(0), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Overhead of calling the function without any topic. // We benchmark for the worst case (largest event). - #[pov_mode = Measured] - seal_deposit_event { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_deposit_event(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -1002,26 +1107,33 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], return_type: None, }], - call_body: Some(body::repeated(r, &[ - Instruction::I32Const(0), // topics_ptr - Instruction::I32Const(0), // topics_len - Instruction::I32Const(0), // data_ptr - Instruction::I32Const(0), // data_len - Instruction::Call(0), - ])), - .. Default::default() + call_body: Some(body::repeated( + r, + &[ + Instruction::I32Const(0), // topics_ptr + Instruction::I32Const(0), // topics_len + Instruction::I32Const(0), // data_ptr + Instruction::I32Const(0), // data_len + Instruction::Call(0), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Benchmark the overhead that topics generate. // `t`: Number of topics // `n`: Size of event payload in bytes - #[pov_mode = Measured] - seal_deposit_event_per_topic_and_byte { - let t in 0 .. T::Schedule::get().limits.event_topics; - let n in 0 .. T::Schedule::get().limits.payload_len; + #[benchmark(pov_mode = Measured)] + fn seal_deposit_event_per_topic_and_byte( + t: Linear<0, { T::Schedule::get().limits.event_topics }>, + n: Linear<0, { T::Schedule::get().limits.payload_len }>, + ) -> Result<(), BenchmarkError> { let topics = (0..t).map(|i| T::Hashing::hash_of(&i)).collect::>().encode(); let topics_len = topics.len(); let code = WasmModule::::from(ModuleDefinition { @@ -1032,32 +1144,29 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], return_type: None, }], - data_segments: vec![ - DataSegment { - offset: 0, - value: topics, - }, - ], + data_segments: vec![DataSegment { offset: 0, value: topics }], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // topics_ptr + Instruction::I32Const(0), // topics_ptr Instruction::I32Const(topics_len as i32), // topics_len - Instruction::I32Const(0), // data_ptr - Instruction::I32Const(n as i32), // data_len + Instruction::I32Const(0), // data_ptr + Instruction::I32Const(n as i32), // data_len Instruction::Call(0), Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Benchmark debug_message call with zero input data. // Whereas this function is used in RPC mode only, it still should be secured // against an excessive use. - #[pov_mode = Measured] - seal_debug_message { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_debug_message(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory { min_pages: 1, max_pages: 1 }), imported_functions: vec![ImportedFunction { @@ -1066,38 +1175,56 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - call_body: Some(body::repeated(r, &[ - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(0), // value_len - Instruction::Call(0), - Instruction::Drop, - ])), - .. Default::default() + call_body: Some(body::repeated( + r, + &[ + Instruction::I32Const(0), // value_ptr + Instruction::I32Const(0), // value_len + Instruction::Call(0), + Instruction::Drop, + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; - }: { - >::bare_call( - instance.caller, - instance.account_id, - 0u32.into(), - Weight::MAX, - None, - vec![], - DebugInfo::UnsafeDebug, - CollectEvents::Skip, - Determinism::Enforced, - ) - .result?; + + #[block] + { + >::bare_call( + instance.caller, + instance.account_id, + 0u32.into(), + Weight::MAX, + None, + vec![], + DebugInfo::UnsafeDebug, + CollectEvents::Skip, + Determinism::Enforced, + ) + .result?; + } + Ok(()) } - seal_debug_message_per_byte { - // Vary size of input in bytes up to maximum allowed contract memory - // or maximum allowed debug buffer size, whichever is less. - let i in 0 .. (T::Schedule::get().limits.memory_pages * 64 * 1024).min(T::MaxDebugBufferLen::get()); + // Vary size of input in bytes up to maximum allowed contract memory + // or maximum allowed debug buffer size, whichever is less. + #[benchmark] + fn seal_debug_message_per_byte( + i: Linear< + 0, + { + (T::Schedule::get().limits.memory_pages * 64 * 1024) + .min(T::MaxDebugBufferLen::get()) + }, + >, + ) -> Result<(), BenchmarkError> { // We benchmark versus messages containing printable ASCII codes. // About 1Kb goes to the contract code instructions, // whereas all the space left we use for the initialization of the debug messages data. - let message = (0 .. T::MaxCodeLen::get() - 1024).zip((32..127).cycle()).map(|i| i.1).collect::>(); + let message = (0..T::MaxCodeLen::get() - 1024) + .zip((32..127).cycle()) + .map(|i| i.1) + .collect::>(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory { min_pages: T::Schedule::get().limits.memory_pages, @@ -1108,15 +1235,10 @@ benchmarks! { name: "seal_debug_message", params: vec![ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), - }], - data_segments: vec![ - DataSegment { - offset: 0, - value: message, - }, - ], + }], + data_segments: vec![DataSegment { offset: 0, value: message }], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // value_ptr + Instruction::I32Const(0), // value_ptr Instruction::I32Const(i as i32), // value_len Instruction::Call(0), Instruction::Drop, @@ -1125,22 +1247,25 @@ benchmarks! { ..Default::default() }); let instance = Contract::::new(code, vec![])?; - }: { - >::bare_call( - instance.caller, - instance.account_id, - 0u32.into(), - Weight::MAX, - None, - vec![], - DebugInfo::UnsafeDebug, - CollectEvents::Skip, - Determinism::Enforced, - ) - .result?; - } - - // Only the overhead of calling the function itself with minimal arguments. + #[block] + { + >::bare_call( + instance.caller, + instance.account_id, + 0u32.into(), + Weight::MAX, + None, + vec![], + DebugInfo::UnsafeDebug, + CollectEvents::Skip, + Determinism::Enforced, + ) + .result?; + } + Ok(()) + } + + // Only the overhead of calling the function itself with minimal arguments. // The contract is a bit more complex because it needs to use different keys in order // to generate unique storage accesses. However, it is still dominated by the storage // accesses. We store something at all the keys that we are about to write to @@ -1151,15 +1276,16 @@ benchmarks! { // // We need to use a smaller `r` because the keys are big and writing them all into the wasm // might exceed the code size. - #[skip_meta] - #[pov_mode = Measured] - seal_set_storage { - let r in 0 .. API_BENCHMARK_RUNS/2; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_set_storage(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0 .. r) - .map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h }) - .collect::>(); + let keys = (0..r) + .map(|n| { + let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); + h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); + h + }) + .collect::>(); let keys_bytes = keys.iter().flatten().cloned().collect::>(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), @@ -1169,27 +1295,25 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: keys_bytes, - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, max_key_len as u32), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(0)), // value_len - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: keys_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, max_key_len as u32), // key_ptr + Regular(Instruction::I32Const(max_key_len as i32)), // key_len + Regular(Instruction::I32Const(0)), // value_ptr + Regular(Instruction::I32Const(0)), // value_len + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; for key in keys { info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![]), None, false, @@ -1197,12 +1321,15 @@ benchmarks! { .map_err(|_| "Failed to write to storage during setup.")?; } let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[skip_meta] - #[pov_mode = Measured] - seal_set_storage_per_new_byte { - let n in 0 .. T::Schedule::get().limits.payload_len; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_set_storage_per_new_byte( + n: Linear<0, { T::Schedule::get().limits.payload_len }>, + ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); let key = vec![0u8; max_key_len as usize]; let code = WasmModule::::from(ModuleDefinition { @@ -1213,39 +1340,37 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: key.clone(), - }, - ], + data_segments: vec![DataSegment { offset: 0, value: key.clone() }], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr + Instruction::I32Const(0), // key_ptr Instruction::I32Const(max_key_len as i32), // key_len - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(n as i32), // value_len + Instruction::I32Const(0), // value_ptr + Instruction::I32Const(n as i32), // value_len Instruction::Call(0), Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![]), None, false, ) .map_err(|_| "Failed to write to storage during setup.")?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[skip_meta] - #[pov_mode = Measured] - seal_set_storage_per_old_byte { - let n in 0 .. T::Schedule::get().limits.payload_len; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_set_storage_per_old_byte( + n: Linear<0, { T::Schedule::get().limits.payload_len }>, + ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); let key = vec![0u8; max_key_len as usize]; let code = WasmModule::::from(ModuleDefinition { @@ -1256,48 +1381,48 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: key.clone(), - }, - ], + data_segments: vec![DataSegment { offset: 0, value: key.clone() }], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr + Instruction::I32Const(0), // key_ptr Instruction::I32Const(max_key_len as i32), // key_len - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(0), // value_len is 0 as testing vs pre-existing value len + Instruction::I32Const(0), // value_ptr + Instruction::I32Const(0), /* value_len is 0 as testing vs + * pre-existing value len */ Instruction::Call(0), Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![42u8; n as usize]), None, false, ) .map_err(|_| "Failed to write to storage during setup.")?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Similar to seal_set_storage. We store all the keys that we are about to // delete beforehand in order to prevent any optimizations that could occur when // deleting a non existing key. We generate keys of a maximum length, and have to // the amount of runs in order to make resulting contract code size less than MaxCodeLen. - #[skip_meta] - #[pov_mode = Measured] - seal_clear_storage { - let r in 0 .. API_BENCHMARK_RUNS/2; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_clear_storage(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0 .. r) - .map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h }) - .collect::>(); + let keys = (0..r) + .map(|n| { + let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); + h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); + h + }) + .collect::>(); let key_bytes = keys.iter().flatten().cloned().collect::>(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), @@ -1307,25 +1432,23 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: key_bytes, - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, max_key_len as u32), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: key_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, max_key_len as u32), // key_ptr + Regular(Instruction::I32Const(max_key_len as i32)), // key_len + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; for key in keys { info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![]), None, false, @@ -1334,12 +1457,15 @@ benchmarks! { } >::insert(&instance.account_id, info); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[skip_meta] - #[pov_mode = Measured] - seal_clear_storage_per_byte { - let n in 0 .. T::Schedule::get().limits.payload_len; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_clear_storage_per_byte( + n: Linear<0, { T::Schedule::get().limits.payload_len }>, + ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); let key = vec![0u8; max_key_len as usize]; let code = WasmModule::::from(ModuleDefinition { @@ -1350,43 +1476,42 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: key.clone(), - }, - ], + data_segments: vec![DataSegment { offset: 0, value: key.clone() }], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr + Instruction::I32Const(0), // key_ptr Instruction::I32Const(max_key_len as i32), // key_len Instruction::Call(0), Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![42u8; n as usize]), None, false, ) .map_err(|_| "Failed to write to storage during setup.")?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // We make sure that all storage accesses are to unique keys. - #[skip_meta] - #[pov_mode = Measured] - seal_get_storage { - let r in 0 .. API_BENCHMARK_RUNS/2; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_get_storage(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0 .. r) - .map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h }) - .collect::>(); + let keys = (0..r) + .map(|n| { + let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); + h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); + h + }) + .collect::>(); let key_bytes = keys.iter().flatten().cloned().collect::>(); let key_bytes_len = key_bytes.len(); let code = WasmModule::::from(ModuleDefinition { @@ -1398,30 +1523,30 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: key_bytes, - }, + DataSegment { offset: 0, value: key_bytes }, DataSegment { offset: key_bytes_len as u32, value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), }, ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, max_key_len), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr - Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, max_key_len), // key_ptr + Regular(Instruction::I32Const(max_key_len as i32)), // key_len + Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr + Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; for key in keys { info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![]), None, false, @@ -1430,12 +1555,15 @@ benchmarks! { } >::insert(&instance.account_id, info); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[skip_meta] - #[pov_mode = Measured] - seal_get_storage_per_byte { - let n in 0 .. T::Schedule::get().limits.payload_len; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_get_storage_per_byte( + n: Linear<0, { T::Schedule::get().limits.payload_len }>, + ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); let key = vec![0u8; max_key_len as usize]; let code = WasmModule::::from(ModuleDefinition { @@ -1447,30 +1575,27 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: key.clone(), - }, + DataSegment { offset: 0, value: key.clone() }, DataSegment { offset: max_key_len, value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), }, ], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(max_key_len as i32), // key_len + Instruction::I32Const(0), // key_ptr + Instruction::I32Const(max_key_len as i32), // key_len Instruction::I32Const((max_key_len + 4) as i32), // out_ptr - Instruction::I32Const(max_key_len as i32), // out_len_ptr + Instruction::I32Const(max_key_len as i32), // out_len_ptr Instruction::Call(0), Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![42u8; n as usize]), None, false, @@ -1478,20 +1603,25 @@ benchmarks! { .map_err(|_| "Failed to write to storage during setup.")?; >::insert(&instance.account_id, info); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // We make sure that all storage accesses are to unique keys. - #[skip_meta] - #[pov_mode = Measured] - seal_contains_storage { - let r in 0 .. API_BENCHMARK_RUNS/2; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_contains_storage( + r: Linear<0, { API_BENCHMARK_RUNS / 2 }>, + ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0 .. r) - .map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h }) - .collect::>(); + let keys = (0..r) + .map(|n| { + let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); + h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); + h + }) + .collect::>(); let key_bytes = keys.iter().flatten().cloned().collect::>(); - let key_bytes_len = key_bytes.len(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -1500,25 +1630,23 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: key_bytes, - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, max_key_len as u32), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: key_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, max_key_len as u32), // key_ptr + Regular(Instruction::I32Const(max_key_len as i32)), // key_len + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; for key in keys { info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![]), None, false, @@ -1527,12 +1655,15 @@ benchmarks! { } >::insert(&instance.account_id, info); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[skip_meta] - #[pov_mode = Measured] - seal_contains_storage_per_byte { - let n in 0 .. T::Schedule::get().limits.payload_len; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_contains_storage_per_byte( + n: Linear<0, { T::Schedule::get().limits.payload_len }>, + ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); let key = vec![0u8; max_key_len as usize]; let code = WasmModule::::from(ModuleDefinition { @@ -1543,25 +1674,20 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: key.clone(), - }, - ], + data_segments: vec![DataSegment { offset: 0, value: key.clone() }], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr + Instruction::I32Const(0), // key_ptr Instruction::I32Const(max_key_len as i32), // key_len Instruction::Call(0), Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![42u8; n as usize]), None, false, @@ -1569,17 +1695,21 @@ benchmarks! { .map_err(|_| "Failed to write to storage during setup.")?; >::insert(&instance.account_id, info); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[skip_meta] - #[pov_mode = Measured] - seal_take_storage { - let r in 0 .. API_BENCHMARK_RUNS/2; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_take_storage(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); - let keys = (0 .. r) - .map(|n| { let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); - h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); h }) - .collect::>(); + let keys = (0..r) + .map(|n| { + let mut h = T::Hashing::hash_of(&n).as_ref().to_vec(); + h.resize(max_key_len.try_into().unwrap(), n.to_le_bytes()[0]); + h + }) + .collect::>(); let key_bytes = keys.iter().flatten().cloned().collect::>(); let key_bytes_len = key_bytes.len(); let code = WasmModule::::from(ModuleDefinition { @@ -1591,30 +1721,30 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: key_bytes, - }, + DataSegment { offset: 0, value: key_bytes }, DataSegment { offset: key_bytes_len as u32, value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), }, ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, max_key_len as u32), // key_ptr - Regular(Instruction::I32Const(max_key_len as i32)), // key_len - Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr - Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, max_key_len as u32), // key_ptr + Regular(Instruction::I32Const(max_key_len as i32)), // key_len + Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr + Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; for key in keys { info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![]), None, false, @@ -1623,12 +1753,15 @@ benchmarks! { } >::insert(&instance.account_id, info); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[skip_meta] - #[pov_mode = Measured] - seal_take_storage_per_byte { - let n in 0 .. T::Schedule::get().limits.payload_len; + #[benchmark(skip_meta, pov_mode = Measured)] + fn seal_take_storage_per_byte( + n: Linear<0, { T::Schedule::get().limits.payload_len }>, + ) -> Result<(), BenchmarkError> { let max_key_len = T::MaxStorageKeyLen::get(); let key = vec![0u8; max_key_len as usize]; let code = WasmModule::::from(ModuleDefinition { @@ -1640,30 +1773,27 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: key.clone(), - }, + DataSegment { offset: 0, value: key.clone() }, DataSegment { offset: max_key_len, value: T::Schedule::get().limits.payload_len.to_le_bytes().into(), }, ], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // key_ptr - Instruction::I32Const(max_key_len as i32), // key_len + Instruction::I32Const(0), // key_ptr + Instruction::I32Const(max_key_len as i32), // key_len Instruction::I32Const((max_key_len + 4) as i32), // out_ptr - Instruction::I32Const(max_key_len as i32), // out_len_ptr + Instruction::I32Const(max_key_len as i32), // out_len_ptr Instruction::Call(0), Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let info = instance.info()?; info.write( - &Key::::try_from_var(key).map_err(|e| "Key has wrong length")?, + &Key::::try_from_var(key).map_err(|_| "Key has wrong length")?, Some(vec![42u8; n as usize]), None, false, @@ -1671,15 +1801,16 @@ benchmarks! { .map_err(|_| "Failed to write to storage during setup.")?; >::insert(&instance.account_id, info); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // We transfer to unique accounts. - #[pov_mode = Measured] - seal_transfer { - let r in 0 .. API_BENCHMARK_RUNS; - let accounts = (0..r) - .map(|i| account::("receiver", i, 0)) - .collect::>(); + #[benchmark(pov_mode = Measured)] + fn seal_transfer(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let accounts = + (0..r).map(|i| account::("receiver", i, 0)).collect::>(); let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0); let account_bytes = accounts.iter().flat_map(|x| x.encode()).collect(); let value = Pallet::::min_balance(); @@ -1695,24 +1826,21 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: value_bytes, - }, - DataSegment { - offset: value_len as u32, - value: account_bytes, - }, + DataSegment { offset: 0, value: value_bytes }, + DataSegment { offset: value_len as u32, value: account_bytes }, ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(value_len as u32, account_len as u32), // account_ptr - Regular(Instruction::I32Const(account_len as i32)), // account_len - Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(value_len as i32)), // value_len - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(value_len as u32, account_len as u32), // account_ptr + Regular(Instruction::I32Const(account_len as i32)), // account_len + Regular(Instruction::I32Const(0)), // value_ptr + Regular(Instruction::I32Const(value_len as i32)), // value_len + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; instance.set_balance(value * (r + 1).into()); @@ -1720,19 +1848,20 @@ benchmarks! { for account in &accounts { assert_eq!(T::Currency::total_balance(account), 0u32.into()); } - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) - verify { + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + for account in &accounts { assert_eq!(T::Currency::total_balance(account), value); } + Ok(()) } // We call unique accounts. // // This is a slow call: We redeuce the number of runs. - #[pov_mode = Measured] - seal_call { - let r in 0 .. API_BENCHMARK_RUNS / 2; + #[benchmark(pov_mode = Measured)] + fn seal_call(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let dummy_code = WasmModule::::dummy_with_bytes(0); let callees = (0..r) .map(|i| Contract::with_index(i + 1, dummy_code.clone(), vec![])) @@ -1745,7 +1874,7 @@ benchmarks! { // Set an own limit every 2nd call let own_limit = (u32::MAX - 100).into(); let deposits = (0..r) - .map(|i| if i % 2 == 0 { 0u32.into() } else { own_limit } ) + .map(|i| if i % 2 == 0 { 0u32.into() } else { own_limit }) .collect::>>(); let deposits_bytes: Vec = deposits.iter().flat_map(|i| i.encode()).collect(); let deposits_len = deposits_bytes.len() as u32; @@ -1771,43 +1900,46 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: value_bytes, - }, - DataSegment { - offset: value_len, - value: deposits_bytes, - }, - DataSegment { - offset: callee_offset, - value: callee_bytes, - }, + DataSegment { offset: 0, value: value_bytes }, + DataSegment { offset: value_len, value: deposits_bytes }, + DataSegment { offset: callee_offset, value: callee_bytes }, ], - call_body: Some(body::repeated_dyn(r, vec![ - Regular(Instruction::I32Const(0)), // flags - Counter(callee_offset, callee_len as u32), // callee_ptr - Regular(Instruction::I64Const(0)), // ref_time weight - Regular(Instruction::I64Const(0)), // proof_size weight - Counter(value_len, deposit_len as u32), // deposit_limit_ptr - Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(0)), // input_data_ptr - Regular(Instruction::I32Const(0)), // input_data_len - Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr - Regular(Instruction::I32Const(0)), // output_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + call_body: Some(body::repeated_dyn( + r, + vec![ + Regular(Instruction::I32Const(0)), // flags + Counter(callee_offset, callee_len as u32), // callee_ptr + Regular(Instruction::I64Const(0)), // ref_time weight + Regular(Instruction::I64Const(0)), // proof_size weight + Counter(value_len, deposit_len as u32), // deposit_limit_ptr + Regular(Instruction::I32Const(0)), // value_ptr + Regular(Instruction::I32Const(0)), // input_data_ptr + Regular(Instruction::I32Const(0)), // input_data_len + Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr + Regular(Instruction::I32Const(0)), // output_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, Some(BalanceOf::::from(u32::MAX.into()).into()), vec![]) + #[extrinsic_call] + call( + origin, + instance.addr, + 0u32.into(), + Weight::MAX, + Some(BalanceOf::::from(u32::MAX.into()).into()), + vec![], + ); + Ok(()) + } // This is a slow call: We redeuce the number of runs. - #[pov_mode = Measured] - seal_delegate_call { - let r in 0 .. API_BENCHMARK_RUNS / 2; + #[benchmark(pov_mode = Measured)] + fn seal_delegate_call(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let hashes = (0..r) .map(|i| { let code = WasmModule::::dummy_with_bytes(i); @@ -1819,7 +1951,6 @@ benchmarks! { .collect::, &'static str>>()?; let hash_len = hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); let hashes_bytes = hashes.iter().flat_map(|x| x.encode()).collect::>(); - let hashes_len = hashes_bytes.len(); let hashes_offset = 0; let code = WasmModule::::from(ModuleDefinition { @@ -1837,33 +1968,35 @@ benchmarks! { ], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: hashes_offset as u32, - value: hashes_bytes, - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Regular(Instruction::I32Const(0)), // flags - Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr - Regular(Instruction::I32Const(0)), // input_data_ptr - Regular(Instruction::I32Const(0)), // input_data_len - Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr - Regular(Instruction::I32Const(0)), // output_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: hashes_offset as u32, value: hashes_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Regular(Instruction::I32Const(0)), // flags + Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr + Regular(Instruction::I32Const(0)), // input_data_ptr + Regular(Instruction::I32Const(0)), // input_data_len + Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr + Regular(Instruction::I32Const(0)), // output_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let callee = instance.addr.clone(); let origin = RawOrigin::Signed(instance.caller); - }: call(origin, callee, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, callee, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_call_per_transfer_clone_byte { - let t in 0 .. 1; - let c in 0 .. code::max_pages::() * 64 * 1024; + #[benchmark(pov_mode = Measured)] + fn seal_call_per_transfer_clone_byte( + t: Linear<0, { 1 }>, + c: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { let callee = Contract::with_index(5, >::dummy(), vec![])?; let value: BalanceOf = t.into(); let value_bytes = value.encode(); @@ -1886,40 +2019,36 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: value_bytes, - }, - DataSegment { - offset: value_len as u32, - value: callee.account_id.encode(), - }, + DataSegment { offset: 0, value: value_bytes }, + DataSegment { offset: value_len as u32, value: callee.account_id.encode() }, ], call_body: Some(body::plain(vec![ Instruction::I32Const(CallFlags::CLONE_INPUT.bits() as i32), // flags - Instruction::I32Const(value_len as i32), // callee_ptr - Instruction::I64Const(0), // gas - Instruction::I32Const(0), // value_ptr - Instruction::I32Const(0), // input_data_ptr - Instruction::I32Const(0), // input_data_len - Instruction::I32Const(SENTINEL as i32), // output_ptr - Instruction::I32Const(0), // output_len_ptr + Instruction::I32Const(value_len as i32), // callee_ptr + Instruction::I64Const(0), // gas + Instruction::I32Const(0), // value_ptr + Instruction::I32Const(0), // input_data_ptr + Instruction::I32Const(0), // input_data_len + Instruction::I32Const(SENTINEL as i32), // output_ptr + Instruction::I32Const(0), // output_len_ptr Instruction::Call(0), Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); let bytes = vec![42; c as usize]; - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, bytes) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, bytes); + Ok(()) + } // We assume that every instantiate sends at least the minimum balance. // This is a slow call: we reduce the number of runs. - #[pov_mode = Measured] - seal_instantiate { - let r in 1 .. API_BENCHMARK_RUNS / 2; + #[benchmark(pov_mode = Measured)] + fn seal_instantiate(r: Linear<1, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let hashes = (0..r) .map(|i| { let code = WasmModule::::from(ModuleDefinition { @@ -1931,7 +2060,7 @@ benchmarks! { Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); @@ -1974,37 +2103,35 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: value_bytes, - }, - DataSegment { - offset: hashes_offset as u32, - value: hashes_bytes, - }, + DataSegment { offset: 0, value: value_bytes }, + DataSegment { offset: hashes_offset as u32, value: hashes_bytes }, DataSegment { offset: addr_len_offset as u32, value: addr_len.to_le_bytes().into(), }, ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr - Regular(Instruction::I64Const(0)), // ref_time weight - Regular(Instruction::I64Const(0)), // proof_size weight - Regular(Instruction::I32Const(SENTINEL as i32)), // deposit limit ptr: use parent's limit - Regular(Instruction::I32Const(0)), // value_ptr - Regular(Instruction::I32Const(0)), // input_data_ptr - Regular(Instruction::I32Const(0)), // input_data_len - Regular(Instruction::I32Const(addr_offset as i32)), // address_ptr - Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr - Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr - Regular(Instruction::I32Const(0)), // output_len_ptr - Regular(Instruction::I32Const(0)), // salt_ptr - Regular(Instruction::I32Const(0)), // salt_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(hashes_offset as u32, hash_len as u32), // code_hash_ptr + Regular(Instruction::I64Const(0)), // ref_time weight + Regular(Instruction::I64Const(0)), // proof_size weight + Regular(Instruction::I32Const(SENTINEL as i32)), /* deposit limit ptr: use + * parent's limit */ + Regular(Instruction::I32Const(0)), // value_ptr + Regular(Instruction::I32Const(0)), // input_data_ptr + Regular(Instruction::I32Const(0)), // input_data_len + Regular(Instruction::I32Const(addr_offset as i32)), // address_ptr + Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr + Regular(Instruction::I32Const(SENTINEL as i32)), // output_ptr + Regular(Instruction::I32Const(0)), // output_len_ptr + Regular(Instruction::I32Const(0)), // salt_ptr + Regular(Instruction::I32Const(0)), // salt_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; instance.set_balance((value + Pallet::::min_balance()) * (r + 1).into()); @@ -2012,9 +2139,7 @@ benchmarks! { let callee = instance.addr.clone(); let addresses = hashes .iter() - .map(|hash| Contracts::::contract_address( - &instance.account_id, hash, &[], &[], - )) + .map(|hash| Contracts::::contract_address(&instance.account_id, hash, &[], &[])) .collect::>(); for addr in &addresses { @@ -2022,27 +2147,27 @@ benchmarks! { return Err("Expected that contract does not exist at this point.".into()); } } - }: call(origin, callee, 0u32.into(), Weight::MAX, None, vec![]) - verify { + #[extrinsic_call] + call(origin, callee, 0u32.into(), Weight::MAX, None, vec![]); for addr in &addresses { - ContractInfoOf::::get(&addr) - .ok_or("Contract should have been instantiated")?; + ContractInfoOf::::get(&addr).ok_or("Contract should have been instantiated")?; } + Ok(()) } - #[pov_mode = Measured] - seal_instantiate_per_transfer_input_salt_byte { - let t in 0 .. 1; - let i in 0 .. (code::max_pages::() - 1) * 64 * 1024; - let s in 0 .. (code::max_pages::() - 1) * 64 * 1024; + #[benchmark(pov_mode = Measured)] + fn seal_instantiate_per_transfer_input_salt_byte( + t: Linear<0, 1>, + i: Linear<0, { (code::max_pages::() - 1) * 64 * 1024 }>, + s: Linear<0, { (code::max_pages::() - 1) * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { let callee_code = WasmModule::::dummy(); - let hash = callee_code.hash; let hash_bytes = callee_code.hash.encode(); let hash_len = hash_bytes.len(); let caller = whitelisted_caller(); T::Currency::set_balance(&caller, caller_funding::()); Contracts::::store_code_raw(callee_code.code, caller)?; - let value: BalanceOf = t.into(); + let value: BalanceOf = t.into(); let value_bytes = value.encode(); let code = WasmModule::::from(ModuleDefinition { @@ -2066,27 +2191,21 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: hash_bytes, - }, - DataSegment { - offset: hash_len as u32, - value: value_bytes, - }, + DataSegment { offset: 0, value: hash_bytes }, + DataSegment { offset: hash_len as u32, value: value_bytes }, ], call_body: Some(body::plain(vec![ - Instruction::I32Const(0 as i32), // code_hash_ptr - Instruction::I64Const(0), // gas + Instruction::I32Const(0 as i32), // code_hash_ptr + Instruction::I64Const(0), // gas Instruction::I32Const(hash_len as i32), // value_ptr - Instruction::I32Const(0 as i32), // input_data_ptr - Instruction::I32Const(i as i32), // input_data_len + Instruction::I32Const(0 as i32), // input_data_ptr + Instruction::I32Const(i as i32), // input_data_len Instruction::I32Const(SENTINEL as i32), // address_ptr - Instruction::I32Const(0), // address_len_ptr + Instruction::I32Const(0), // address_len_ptr Instruction::I32Const(SENTINEL as i32), // output_ptr - Instruction::I32Const(0), // output_len_ptr - Instruction::I32Const(0 as i32), // salt_ptr - Instruction::I32Const(s as i32), // salt_len + Instruction::I32Const(0), // output_len_ptr + Instruction::I32Const(0 as i32), // salt_ptr + Instruction::I32Const(s as i32), // salt_len Instruction::Call(0), Instruction::I32Eqz, Instruction::If(BlockType::NoResult), @@ -2096,105 +2215,123 @@ benchmarks! { Instruction::End, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; instance.set_balance(value + (Pallet::::min_balance() * 2u32.into())); let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Only the overhead of calling the function itself with minimal arguments. - #[pov_mode = Measured] - seal_hash_sha2_256 { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::hasher( - "seal_hash_sha2_256", r, 0, - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_hash_sha2_256(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = Contract::::new(WasmModule::hasher("seal_hash_sha2_256", r, 0), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // `n`: Input to hash in bytes - #[pov_mode = Measured] - seal_hash_sha2_256_per_byte { - let n in 0 .. code::max_pages::() * 64 * 1024; - let instance = Contract::::new(WasmModule::hasher( - "seal_hash_sha2_256", 1, n, - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_hash_sha2_256_per_byte( + n: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { + let instance = Contract::::new(WasmModule::hasher("seal_hash_sha2_256", 1, n), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Only the overhead of calling the function itself with minimal arguments. - #[pov_mode = Measured] - seal_hash_keccak_256 { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::hasher( - "seal_hash_keccak_256", r, 0, - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_hash_keccak_256(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::hasher("seal_hash_keccak_256", r, 0), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // `n`: Input to hash in bytes - #[pov_mode = Measured] - seal_hash_keccak_256_per_byte { - let n in 0 .. code::max_pages::() * 64 * 1024; - let instance = Contract::::new(WasmModule::hasher( - "seal_hash_keccak_256", 1, n, - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_hash_keccak_256_per_byte( + n: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::hasher("seal_hash_keccak_256", 1, n), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Only the overhead of calling the function itself with minimal arguments. - #[pov_mode = Measured] - seal_hash_blake2_256 { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::hasher( - "seal_hash_blake2_256", r, 0, - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_hash_blake2_256(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::hasher("seal_hash_blake2_256", r, 0), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // `n`: Input to hash in bytes - #[pov_mode = Measured] - seal_hash_blake2_256_per_byte { - let n in 0 .. code::max_pages::() * 64 * 1024; - let instance = Contract::::new(WasmModule::hasher( - "seal_hash_blake2_256", 1, n, - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_hash_blake2_256_per_byte( + n: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::hasher("seal_hash_blake2_256", 1, n), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Only the overhead of calling the function itself with minimal arguments. - #[pov_mode = Measured] - seal_hash_blake2_128 { - let r in 0 .. API_BENCHMARK_RUNS; - let instance = Contract::::new(WasmModule::hasher( - "seal_hash_blake2_128", r, 0, - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_hash_blake2_128(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::hasher("seal_hash_blake2_128", r, 0), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // `n`: Input to hash in bytes - #[pov_mode = Measured] - seal_hash_blake2_128_per_byte { - let n in 0 .. code::max_pages::() * 64 * 1024; - let instance = Contract::::new(WasmModule::hasher( - "seal_hash_blake2_128", 1, n, - ), vec![])?; + #[benchmark(pov_mode = Measured)] + fn seal_hash_blake2_128_per_byte( + n: Linear<0, { code::max_pages::() * 64 * 1024 }>, + ) -> Result<(), BenchmarkError> { + let instance = + Contract::::new(WasmModule::hasher("seal_hash_blake2_128", 1, n), vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // `n`: Message input length to verify in bytes. - #[pov_mode = Measured] - seal_sr25519_verify_per_byte { - let n in 0 .. T::MaxCodeLen::get() - 255; // need some buffer so the code size does not - // exceed the max code size. - + // need some buffer so the code size does not exceed the max code size. + #[benchmark(pov_mode = Measured)] + fn seal_sr25519_verify_per_byte( + n: Linear<0, { T::MaxCodeLen::get() - 255 }>, + ) -> Result<(), BenchmarkError> { let message = (0..n).zip((32u8..127u8).cycle()).map(|(_, c)| c).collect::>(); let message_len = message.len() as i32; let key_type = sp_core::crypto::KeyTypeId(*b"code"); let pub_key = sp_io::crypto::sr25519_generate(key_type, None); - let sig = sp_io::crypto::sr25519_sign(key_type, &pub_key, &message).expect("Generates signature"); + let sig = + sp_io::crypto::sr25519_sign(key_type, &pub_key, &message).expect("Generates signature"); let sig = AsRef::<[u8; 64]>::as_ref(&sig).to_vec(); let code = WasmModule::::from(ModuleDefinition { @@ -2206,50 +2343,48 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: sig, - }, - DataSegment { - offset: 64, - value: pub_key.to_vec(), - }, - DataSegment { - offset: 96, - value: message, - }, + DataSegment { offset: 0, value: sig }, + DataSegment { offset: 64, value: pub_key.to_vec() }, + DataSegment { offset: 96, value: message }, ], call_body: Some(body::plain(vec![ - Instruction::I32Const(0), // signature_ptr - Instruction::I32Const(64), // pub_key_ptr + Instruction::I32Const(0), // signature_ptr + Instruction::I32Const(64), // pub_key_ptr Instruction::I32Const(message_len), // message_len - Instruction::I32Const(96), // message_ptr + Instruction::I32Const(96), // message_ptr Instruction::Call(0), Instruction::Drop, Instruction::End, ])), - .. Default::default() + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Only calling the function itself with valid arguments. // It generates different private keys and signatures for the message "Hello world". // This is a slow call: We reduce the number of runs. - #[pov_mode = Measured] - seal_sr25519_verify { - let r in 0 .. API_BENCHMARK_RUNS / 10; - + #[benchmark(pov_mode = Measured)] + fn seal_sr25519_verify( + r: Linear<0, { API_BENCHMARK_RUNS / 10 }>, + ) -> Result<(), BenchmarkError> { let message = b"Hello world".to_vec(); let message_len = message.len() as i32; let key_type = sp_core::crypto::KeyTypeId(*b"code"); let sig_params = (0..r) - .flat_map(|i| { + .flat_map(|_| { let pub_key = sp_io::crypto::sr25519_generate(key_type, None); - let sig = sp_io::crypto::sr25519_sign(key_type, &pub_key, &message).expect("Generates signature"); - let data: [u8; 96] = [AsRef::<[u8]>::as_ref(&sig), AsRef::<[u8]>::as_ref(&pub_key)].concat().try_into().unwrap(); + let sig = sp_io::crypto::sr25519_sign(key_type, &pub_key, &message) + .expect("Generates signature"); + let data: [u8; 96] = [AsRef::<[u8]>::as_ref(&sig), AsRef::<[u8]>::as_ref(&pub_key)] + .concat() + .try_into() + .unwrap(); data }) .collect::>(); @@ -2264,42 +2399,41 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: sig_params - }, - DataSegment { - offset: sig_params_len as u32, - value: message, - }, + DataSegment { offset: 0, value: sig_params }, + DataSegment { offset: sig_params_len as u32, value: message }, ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, 96), // signature_ptr - Counter(64, 96), // pub_key_ptr - Regular(Instruction::I32Const(message_len)), // message_len - Regular(Instruction::I32Const(sig_params_len)), // message_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, 96), // signature_ptr + Counter(64, 96), // pub_key_ptr + Regular(Instruction::I32Const(message_len)), // message_len + Regular(Instruction::I32Const(sig_params_len)), // message_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Only calling the function itself with valid arguments. // It generates different private keys and signatures for the message "Hello world". // This is a slow call: We reduce the number of runs. - #[pov_mode = Measured] - seal_ecdsa_recover { - let r in 0 .. API_BENCHMARK_RUNS / 10; - + #[benchmark(pov_mode = Measured)] + fn seal_ecdsa_recover(r: Linear<0, { API_BENCHMARK_RUNS / 10 }>) -> Result<(), BenchmarkError> { let message_hash = sp_io::hashing::blake2_256("Hello world".as_bytes()); let key_type = sp_core::crypto::KeyTypeId(*b"code"); let signatures = (0..r) - .map(|i| { + .map(|_| { let pub_key = sp_io::crypto::ecdsa_generate(key_type, None); - let sig = sp_io::crypto::ecdsa_sign_prehashed(key_type, &pub_key, &message_hash).expect("Generates signature"); + let sig = sp_io::crypto::ecdsa_sign_prehashed(key_type, &pub_key, &message_hash) + .expect("Generates signature"); AsRef::<[u8; 65]>::as_ref(&sig).to_vec() }) .collect::>(); @@ -2315,40 +2449,39 @@ benchmarks! { return_type: Some(ValueType::I32), }], data_segments: vec![ - DataSegment { - offset: 0, - value: message_hash[..].to_vec(), - }, - DataSegment { - offset: 32, - value: signatures, - }, + DataSegment { offset: 0, value: message_hash[..].to_vec() }, + DataSegment { offset: 32, value: signatures }, ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(32, 65), // signature_ptr - Regular(Instruction::I32Const(0)), // message_hash_ptr - Regular(Instruction::I32Const(signatures_bytes_len + 32)), // output_len_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(32, 65), // signature_ptr + Regular(Instruction::I32Const(0)), // message_hash_ptr + Regular(Instruction::I32Const(signatures_bytes_len + 32)), // output_len_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // Only calling the function itself for the list of // generated different ECDSA keys. // This is a slow call: We redeuce the number of runs. - #[pov_mode = Measured] - seal_ecdsa_to_eth_address { - let r in 0 .. API_BENCHMARK_RUNS / 10; + #[benchmark(pov_mode = Measured)] + fn seal_ecdsa_to_eth_address( + r: Linear<0, { API_BENCHMARK_RUNS / 10 }>, + ) -> Result<(), BenchmarkError> { let key_type = sp_core::crypto::KeyTypeId(*b"code"); let pub_keys_bytes = (0..r) - .flat_map(|_| { - sp_io::crypto::ecdsa_generate(key_type, None).0 - }) - .collect::>(); + .flat_map(|_| sp_io::crypto::ecdsa_generate(key_type, None).0) + .collect::>(); let pub_keys_bytes_len = pub_keys_bytes.len() as i32; let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), @@ -2358,27 +2491,27 @@ benchmarks! { params: vec![ValueType::I32, ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: pub_keys_bytes, - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, 33), // pub_key_ptr - Regular(Instruction::I32Const(pub_keys_bytes_len)), // out_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: pub_keys_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, 33), // pub_key_ptr + Regular(Instruction::I32Const(pub_keys_bytes_len)), // out_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_set_code_hash { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_set_code_hash(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let code_hashes = (0..r) .map(|i| { let new_code = WasmModule::::dummy_with_bytes(i); @@ -2390,38 +2523,37 @@ benchmarks! { .collect::, &'static str>>()?; let code_hash_len = code_hashes.get(0).map(|x| x.encode().len()).unwrap_or(0); let code_hashes_bytes = code_hashes.iter().flat_map(|x| x.encode()).collect::>(); - let code_hashes_len = code_hashes_bytes.len(); let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { module: "seal0", name: "seal_set_code_hash", - params: vec![ - ValueType::I32, - ], + params: vec![ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: code_hashes_bytes, - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: code_hashes_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, code_hash_len as u32), // code_hash_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - lock_delegate_dependency { - let r in 0 .. T::MaxDelegateDependencies::get(); + #[benchmark(pov_mode = Measured)] + fn lock_delegate_dependency( + r: Linear<0, { T::MaxDelegateDependencies::get() }>, + ) -> Result<(), BenchmarkError> { let code_hashes = (0..r) .map(|i| { let new_code = WasmModule::::dummy_with_bytes(65 + i); @@ -2442,24 +2574,27 @@ benchmarks! { params: vec![ValueType::I32], return_type: None, }], - data_segments: vec![ - DataSegment { - offset: 0, - value: code_hashes_bytes, - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(0)), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: code_hashes_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, code_hash_len as u32), // code_hash_ptr + Regular(Instruction::Call(0)), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - unlock_delegate_dependency { - let r in 0 .. T::MaxDelegateDependencies::get(); + #[benchmark] + fn unlock_delegate_dependency( + r: Linear<0, { T::MaxDelegateDependencies::get() }>, + ) -> Result<(), BenchmarkError> { let code_hashes = (0..r) .map(|i| { let new_code = WasmModule::::dummy_with_bytes(65 + i); @@ -2475,40 +2610,46 @@ benchmarks! { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), - imported_functions: vec![ImportedFunction { - module: "seal0", - name: "unlock_delegate_dependency", - params: vec![ValueType::I32], - return_type: None, - }, ImportedFunction { - module: "seal0", - name: "lock_delegate_dependency", - params: vec![ValueType::I32], - return_type: None - }], - data_segments: vec![ - DataSegment { - offset: 0, - value: code_hashes_bytes, + imported_functions: vec![ + ImportedFunction { + module: "seal0", + name: "unlock_delegate_dependency", + params: vec![ValueType::I32], + return_type: None, + }, + ImportedFunction { + module: "seal0", + name: "lock_delegate_dependency", + params: vec![ValueType::I32], + return_type: None, }, ], - deploy_body: Some(body::repeated_dyn(r, vec![ - Counter(0, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(1)), - ])), - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, code_hash_len as u32), // code_hash_ptr - Regular(Instruction::Call(0)), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: code_hashes_bytes }], + deploy_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, code_hash_len as u32), // code_hash_ptr + Regular(Instruction::Call(1)), + ], + )), + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, code_hash_len as u32), // code_hash_ptr + Regular(Instruction::Call(0)), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_reentrance_count { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_reentrance_count(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -2517,19 +2658,20 @@ benchmarks! { params: vec![], return_type: Some(ValueType::I32), }], - call_body: Some(body::repeated(r, &[ - Instruction::Call(0), - Instruction::Drop, - ])), - .. Default::default() + call_body: Some(body::repeated(r, &[Instruction::Call(0), Instruction::Drop])), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_account_reentrance_count { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_account_reentrance_count( + r: Linear<0, API_BENCHMARK_RUNS>, + ) -> Result<(), BenchmarkError> { let dummy_code = WasmModule::::dummy_with_bytes(0); let accounts = (0..r) .map(|i| Contract::with_index(i + 1, dummy_code.clone(), vec![])) @@ -2544,26 +2686,26 @@ benchmarks! { params: vec![ValueType::I32], return_type: Some(ValueType::I32), }], - data_segments: vec![ - DataSegment { - offset: 0, - value: account_id_bytes, - }, - ], - call_body: Some(body::repeated_dyn(r, vec![ - Counter(0, account_id_len as u32), // account_ptr - Regular(Instruction::Call(0)), - Regular(Instruction::Drop), - ])), - .. Default::default() + data_segments: vec![DataSegment { offset: 0, value: account_id_bytes }], + call_body: Some(body::repeated_dyn( + r, + vec![ + Counter(0, account_id_len as u32), // account_ptr + Regular(Instruction::Call(0)), + Regular(Instruction::Drop), + ], + )), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } - #[pov_mode = Measured] - seal_instantiation_nonce { - let r in 0 .. API_BENCHMARK_RUNS; + #[benchmark(pov_mode = Measured)] + fn seal_instantiation_nonce(r: Linear<0, API_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { let code = WasmModule::::from(ModuleDefinition { memory: Some(ImportedMemory::max::()), imported_functions: vec![ImportedFunction { @@ -2572,29 +2714,27 @@ benchmarks! { params: vec![], return_type: Some(ValueType::I64), }], - call_body: Some(body::repeated(r, &[ - Instruction::Call(0), - Instruction::Drop, - ])), - .. Default::default() + call_body: Some(body::repeated(r, &[Instruction::Call(0), Instruction::Drop])), + ..Default::default() }); let instance = Contract::::new(code, vec![])?; let origin = RawOrigin::Signed(instance.caller.clone()); - }: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]) + #[extrinsic_call] + call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![]); + Ok(()) + } // We load `i64` values from random linear memory locations and store the loaded // values back into yet another random linear memory location. - // The random addresses are uniformely distributed across the entire span of the linear memory. + // The random addresses are uniformly distributed across the entire span of the linear memory. // We do this to enforce random memory accesses which are particularly expensive. // // The combination of this computation is our weight base `w_base`. - #[pov_mode = Ignored] - instr_i64_load_store { - let r in 0 .. INSTR_BENCHMARK_RUNS; - + #[benchmark(pov_mode = Ignored)] + fn instr_i64_load_store(r: Linear<0, INSTR_BENCHMARK_RUNS>) -> Result<(), BenchmarkError> { use rand::prelude::*; - // We do not need to be secure here. Fixed seed allows for determinstic results. + // We do not need to be secure here. Fixed seed allows for deterministic results. let mut rng = rand_pcg::Pcg32::seed_from_u64(8446744073709551615); let memory = ImportedMemory::max::(); @@ -2614,24 +2754,27 @@ benchmarks! { [ Instruction::I32Const(c0), // address for `i64.load_8s` Instruction::I64Load8S(0, 0), - Instruction::SetLocal(0), // temporarily store value loaded in `i64.load_8s` + Instruction::SetLocal(0), /* temporarily store value loaded in + * `i64.load_8s` */ Instruction::I32Const(c1), // address for `i64.store8` Instruction::GetLocal(0), // value to be stores in `i64.store8` Instruction::I64Store8(0, 0), ] - } + }, )), - .. Default::default() + ..Default::default() })); - }: { - sbox.invoke(); + #[block] + { + sbox.invoke(); + } + Ok(()) } // This is no benchmark. It merely exist to have an easy way to pretty print the currently // configured `Schedule` during benchmark development. Check the README on how to print this. - #[extra] - #[pov_mode = Ignored] - print_schedule { + #[benchmark(extra, pov_mode = Ignored)] + fn print_schedule() -> Result<(), BenchmarkError> { let max_weight = ::BlockWeights::get().max_block; let (weight_per_key, key_budget) = ContractInfo::::deletion_budget(max_weight); let schedule = T::Schedule::get(); @@ -2641,11 +2784,15 @@ benchmarks! { Lazy deletion weight per key: {weight_per_key} Lazy deletion keys per block: {key_budget} "); - }: {} + #[block] + {} + + Err(BenchmarkError::Skip) + } impl_benchmark_test_suite!( Contracts, crate::tests::ExtBuilder::default().build(), crate::tests::Test, - ) + ); } diff --git a/substrate/frame/contracts/src/weights.rs b/substrate/frame/contracts/src/weights.rs index 99bc4d8d3eb..aa75ca8b29e 100644 --- a/substrate/frame/contracts/src/weights.rs +++ b/substrate/frame/contracts/src/weights.rs @@ -18,14 +18,13 @@ //! Autogenerated weights for `pallet_contracts` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-p5qp1txx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: // target/production/substrate-node -// target/production/substrate-node // benchmark // pallet // --steps=50 @@ -36,12 +35,8 @@ // --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json // --pallet=pallet_contracts // --chain=dev -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_contracts -// --chain=dev // --header=./substrate/HEADER-APACHE2 // --output=./substrate/frame/contracts/src/weights.rs -// --output=./substrate/frame/contracts/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -147,8 +142,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_054_000 picoseconds. - Weight::from_parts(2_178_000, 1627) + // Minimum execution time: 2_130_000 picoseconds. + Weight::from_parts(2_247_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -158,10 +153,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `452 + k * (69 ±0)` // Estimated: `442 + k * (70 ±0)` - // Minimum execution time: 12_119_000 picoseconds. - Weight::from_parts(12_536_000, 442) - // Standard Error: 1_254 - .saturating_add(Weight::from_parts(1_161_885, 0).saturating_mul(k.into())) + // Minimum execution time: 12_748_000 picoseconds. + Weight::from_parts(13_001_000, 442) + // Standard Error: 1_206 + .saturating_add(Weight::from_parts(1_146_159, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -175,10 +170,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_146_000 picoseconds. - Weight::from_parts(8_560_745, 6149) + // Minimum execution time: 8_636_000 picoseconds. + Weight::from_parts(8_664_917, 6149) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_182, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_188, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -191,8 +186,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 16_183_000 picoseconds. - Weight::from_parts(16_825_000, 6450) + // Minimum execution time: 16_838_000 picoseconds. + Weight::from_parts(17_400_000, 6450) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -205,10 +200,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_645_000 picoseconds. - Weight::from_parts(604_365, 3635) - // Standard Error: 1_013 - .saturating_add(Weight::from_parts(1_100_277, 0).saturating_mul(k.into())) + // Minimum execution time: 3_876_000 picoseconds. + Weight::from_parts(2_654_935, 3635) + // Standard Error: 2_001 + .saturating_add(Weight::from_parts(1_258_085, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -218,6 +213,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553053f13fd319a03c211337c76e0fe776df` (r:2 w:0) /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:0 w:1) @@ -227,10 +224,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `328 + c * (1 ±0)` // Estimated: `6266 + c * (1 ±0)` - // Minimum execution time: 19_500_000 picoseconds. - Weight::from_parts(20_074_895, 6266) + // Minimum execution time: 21_038_000 picoseconds. + Weight::from_parts(20_890_548, 6266) // Standard Error: 1 - .saturating_add(Weight::from_parts(422, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(435, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -241,8 +238,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 12_530_000 picoseconds. - Weight::from_parts(13_362_000, 6380) + // Minimum execution time: 12_579_000 picoseconds. + Weight::from_parts(13_486_000, 6380) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -251,13 +248,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) fn v14_migration_step() -> Weight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `6292` - // Minimum execution time: 44_275_000 picoseconds. - Weight::from_parts(45_718_000, 6292) + // Minimum execution time: 47_123_000 picoseconds. + Weight::from_parts(48_284_000, 6292) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -269,8 +266,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 55_095_000 picoseconds. - Weight::from_parts(58_009_000, 6534) + // Minimum execution time: 55_237_000 picoseconds. + Weight::from_parts(57_996_000, 6534) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -280,8 +277,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_455_000 picoseconds. - Weight::from_parts(2_608_000, 1627) + // Minimum execution time: 2_766_000 picoseconds. + Weight::from_parts(2_807_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -293,8 +290,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 11_207_000 picoseconds. - Weight::from_parts(11_802_000, 3631) + // Minimum execution time: 12_243_000 picoseconds. + Weight::from_parts(12_890_000, 3631) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -304,8 +301,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 4_581_000 picoseconds. - Weight::from_parts(4_781_000, 3607) + // Minimum execution time: 4_951_000 picoseconds. + Weight::from_parts(5_232_000, 3607) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -316,8 +313,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 5_887_000 picoseconds. - Weight::from_parts(6_393_000, 3632) + // Minimum execution time: 6_530_000 picoseconds. + Weight::from_parts(6_726_000, 3632) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -328,13 +325,15 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 6_025_000 picoseconds. - Weight::from_parts(6_298_000, 3607) + // Minimum execution time: 6_227_000 picoseconds. + Weight::from_parts(6_708_000, 3607) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -352,20 +351,22 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `804 + c * (1 ±0)` // Estimated: `9217 + c * (1 ±0)` - // Minimum execution time: 294_976_000 picoseconds. - Weight::from_parts(277_235_948, 9217) - // Standard Error: 65 - .saturating_add(Weight::from_parts(34_445, 0).saturating_mul(c.into())) + // Minimum execution time: 309_889_000 picoseconds. + Weight::from_parts(277_084_159, 9217) + // Standard Error: 71 + .saturating_add(Weight::from_parts(33_471, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:3 w:3) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) @@ -385,14 +386,14 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `326` // Estimated: `8740` - // Minimum execution time: 3_864_558_000 picoseconds. - Weight::from_parts(421_676_889, 8740) - // Standard Error: 188 - .saturating_add(Weight::from_parts(103_788, 0).saturating_mul(c.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(1_715, 0).saturating_mul(i.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(1_774, 0).saturating_mul(s.into())) + // Minimum execution time: 3_909_680_000 picoseconds. + Weight::from_parts(446_471_160, 8740) + // Standard Error: 159 + .saturating_add(Weight::from_parts(101_085, 0).saturating_mul(c.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_598, 0).saturating_mul(i.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_879, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } @@ -402,6 +403,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -413,24 +416,26 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:2 w:2) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `563` // Estimated: `8982` - // Minimum execution time: 2_069_276_000 picoseconds. - Weight::from_parts(377_210_279, 8982) - // Standard Error: 9 - .saturating_add(Weight::from_parts(1_719, 0).saturating_mul(i.into())) - // Standard Error: 9 - .saturating_add(Weight::from_parts(1_728, 0).saturating_mul(s.into())) + // Minimum execution time: 1_968_545_000 picoseconds. + Weight::from_parts(420_048_028, 8982) + // Standard Error: 20 + .saturating_add(Weight::from_parts(1_685, 0).saturating_mul(i.into())) + // Standard Error: 20 + .saturating_add(Weight::from_parts(1_645, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -447,17 +452,19 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `829` // Estimated: `9244` - // Minimum execution time: 199_037_000 picoseconds. - Weight::from_parts(213_931_000, 9244) + // Minimum execution time: 207_564_000 picoseconds. + Weight::from_parts(216_983_000, 9244) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -467,10 +474,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `145` // Estimated: `6085` - // Minimum execution time: 278_482_000 picoseconds. - Weight::from_parts(262_753_879, 6085) - // Standard Error: 112 - .saturating_add(Weight::from_parts(66_129, 0).saturating_mul(c.into())) + // Minimum execution time: 273_555_000 picoseconds. + Weight::from_parts(257_517_935, 6085) + // Standard Error: 148 + .saturating_add(Weight::from_parts(64_488, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -491,10 +498,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `145` // Estimated: `6085` - // Minimum execution time: 286_902_000 picoseconds. - Weight::from_parts(269_003_959, 6085) - // Standard Error: 123 - .saturating_add(Weight::from_parts(66_629, 0).saturating_mul(c.into())) + // Minimum execution time: 289_672_000 picoseconds. + Weight::from_parts(297_020_278, 6085) + // Standard Error: 86 + .saturating_add(Weight::from_parts(64_340, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -503,7 +510,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -512,8 +519,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 44_128_000 picoseconds. - Weight::from_parts(46_044_000, 3780) + // Minimum execution time: 45_930_000 picoseconds. + Weight::from_parts(47_288_000, 3780) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -529,8 +536,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `552` // Estimated: `8967` - // Minimum execution time: 33_567_000 picoseconds. - Weight::from_parts(35_057_000, 8967) + // Minimum execution time: 35_421_000 picoseconds. + Weight::from_parts(36_909_000, 8967) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -538,6 +545,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -553,10 +562,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `869 + r * (6 ±0)` // Estimated: `9284 + r * (6 ±0)` - // Minimum execution time: 272_376_000 picoseconds. - Weight::from_parts(284_162_161, 9284) - // Standard Error: 501 - .saturating_add(Weight::from_parts(341_575, 0).saturating_mul(r.into())) + // Minimum execution time: 275_531_000 picoseconds. + Weight::from_parts(292_269_656, 9284) + // Standard Error: 672 + .saturating_add(Weight::from_parts(339_728, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -565,6 +574,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -580,10 +591,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `925 + r * (209 ±0)` // Estimated: `9304 + r * (2684 ±0)` - // Minimum execution time: 256_990_000 picoseconds. - Weight::from_parts(107_167_044, 9304) - // Standard Error: 7_545 - .saturating_add(Weight::from_parts(3_628_112, 0).saturating_mul(r.into())) + // Minimum execution time: 275_829_000 picoseconds. + Weight::from_parts(124_543_289, 9304) + // Standard Error: 6_085 + .saturating_add(Weight::from_parts(3_702_964, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -593,6 +604,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -608,10 +621,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `924 + r * (213 ±0)` // Estimated: `9308 + r * (2688 ±0)` - // Minimum execution time: 272_889_000 picoseconds. - Weight::from_parts(110_341_799, 9308) - // Standard Error: 7_881 - .saturating_add(Weight::from_parts(4_427_043, 0).saturating_mul(r.into())) + // Minimum execution time: 276_666_000 picoseconds. + Weight::from_parts(96_951_288, 9308) + // Standard Error: 8_876 + .saturating_add(Weight::from_parts(4_604_699, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -621,6 +634,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -636,10 +651,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `876 + r * (6 ±0)` // Estimated: `9293 + r * (6 ±0)` - // Minimum execution time: 275_027_000 picoseconds. - Weight::from_parts(283_302_223, 9293) - // Standard Error: 1_179 - .saturating_add(Weight::from_parts(436_023, 0).saturating_mul(r.into())) + // Minimum execution time: 271_301_000 picoseconds. + Weight::from_parts(284_126_054, 9293) + // Standard Error: 886 + .saturating_add(Weight::from_parts(437_127, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -648,6 +663,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -663,16 +680,18 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866 + r * (3 ±0)` // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 270_137_000 picoseconds. - Weight::from_parts(282_756_362, 9282) - // Standard Error: 384 - .saturating_add(Weight::from_parts(171_660, 0).saturating_mul(r.into())) + // Minimum execution time: 274_778_000 picoseconds. + Weight::from_parts(289_355_269, 9282) + // Standard Error: 382 + .saturating_add(Weight::from_parts(175_342, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -688,10 +707,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `756 + r * (3 ±0)` // Estimated: `9171 + r * (3 ±0)` - // Minimum execution time: 255_131_000 picoseconds. - Weight::from_parts(269_207_006, 9171) - // Standard Error: 542 - .saturating_add(Weight::from_parts(161_597, 0).saturating_mul(r.into())) + // Minimum execution time: 257_310_000 picoseconds. + Weight::from_parts(276_410_847, 9171) + // Standard Error: 733 + .saturating_add(Weight::from_parts(160_094, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -700,6 +719,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -715,10 +736,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `870 + r * (6 ±0)` // Estimated: `9285 + r * (6 ±0)` - // Minimum execution time: 272_172_000 picoseconds. - Weight::from_parts(283_747_134, 9285) - // Standard Error: 885 - .saturating_add(Weight::from_parts(343_968, 0).saturating_mul(r.into())) + // Minimum execution time: 278_305_000 picoseconds. + Weight::from_parts(282_372_935, 9285) + // Standard Error: 1_154 + .saturating_add(Weight::from_parts(343_382, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -727,6 +748,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -742,10 +765,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866 + r * (6 ±0)` // Estimated: `9284 + r * (6 ±0)` - // Minimum execution time: 263_220_000 picoseconds. - Weight::from_parts(277_062_382, 9284) - // Standard Error: 1_783 - .saturating_add(Weight::from_parts(399_631, 0).saturating_mul(r.into())) + // Minimum execution time: 280_349_000 picoseconds. + Weight::from_parts(294_864_875, 9284) + // Standard Error: 1_010 + .saturating_add(Weight::from_parts(368_740, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -754,6 +777,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:2 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -769,10 +794,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1010 + r * (6 ±0)` // Estimated: `9409 + r * (6 ±0)` - // Minimum execution time: 253_218_000 picoseconds. - Weight::from_parts(282_251_452, 9409) - // Standard Error: 2_367 - .saturating_add(Weight::from_parts(1_604_060, 0).saturating_mul(r.into())) + // Minimum execution time: 274_578_000 picoseconds. + Weight::from_parts(313_285_034, 9409) + // Standard Error: 2_800 + .saturating_add(Weight::from_parts(1_653_468, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -781,6 +806,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -796,10 +823,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `880 + r * (6 ±0)` // Estimated: `9301 + r * (6 ±0)` - // Minimum execution time: 271_797_000 picoseconds. - Weight::from_parts(288_594_393, 9301) - // Standard Error: 846 - .saturating_add(Weight::from_parts(335_063, 0).saturating_mul(r.into())) + // Minimum execution time: 287_127_000 picoseconds. + Weight::from_parts(290_489_909, 9301) + // Standard Error: 864 + .saturating_add(Weight::from_parts(332_977, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -808,6 +835,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -823,10 +852,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `878 + r * (6 ±0)` // Estimated: `9294 + r * (6 ±0)` - // Minimum execution time: 254_997_000 picoseconds. - Weight::from_parts(284_331_894, 9294) - // Standard Error: 885 - .saturating_add(Weight::from_parts(337_073, 0).saturating_mul(r.into())) + // Minimum execution time: 273_291_000 picoseconds. + Weight::from_parts(293_650_716, 9294) + // Standard Error: 725 + .saturating_add(Weight::from_parts(323_281, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -835,6 +864,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -850,10 +881,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `875 + r * (6 ±0)` // Estimated: `9297 + r * (6 ±0)` - // Minimum execution time: 273_845_000 picoseconds. - Weight::from_parts(285_291_242, 9297) - // Standard Error: 690 - .saturating_add(Weight::from_parts(332_783, 0).saturating_mul(r.into())) + // Minimum execution time: 282_061_000 picoseconds. + Weight::from_parts(291_729_751, 9297) + // Standard Error: 929 + .saturating_add(Weight::from_parts(324_683, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -862,6 +893,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -877,10 +910,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866 + r * (6 ±0)` // Estimated: `9282 + r * (6 ±0)` - // Minimum execution time: 268_302_000 picoseconds. - Weight::from_parts(280_463_257, 9282) - // Standard Error: 1_035 - .saturating_add(Weight::from_parts(345_811, 0).saturating_mul(r.into())) + // Minimum execution time: 264_505_000 picoseconds. + Weight::from_parts(293_440_286, 9282) + // Standard Error: 704 + .saturating_add(Weight::from_parts(329_851, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -889,6 +922,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -906,10 +941,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `940 + r * (14 ±0)` // Estimated: `9350 + r * (14 ±0)` - // Minimum execution time: 263_433_000 picoseconds. - Weight::from_parts(290_098_370, 9350) - // Standard Error: 1_905 - .saturating_add(Weight::from_parts(805_299, 0).saturating_mul(r.into())) + // Minimum execution time: 277_208_000 picoseconds. + Weight::from_parts(304_294_691, 9350) + // Standard Error: 1_083 + .saturating_add(Weight::from_parts(824_245, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 14).saturating_mul(r.into())) @@ -918,6 +953,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -933,10 +970,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `868 + r * (6 ±0)` // Estimated: `9285 + r * (6 ±0)` - // Minimum execution time: 273_588_000 picoseconds. - Weight::from_parts(287_133_565, 9285) - // Standard Error: 799 - .saturating_add(Weight::from_parts(254_114, 0).saturating_mul(r.into())) + // Minimum execution time: 278_293_000 picoseconds. + Weight::from_parts(289_743_005, 9285) + // Standard Error: 672 + .saturating_add(Weight::from_parts(267_553, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -945,6 +982,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -960,10 +999,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `872` // Estimated: `9287` - // Minimum execution time: 257_843_000 picoseconds. - Weight::from_parts(228_177_495, 9287) - // Standard Error: 24 - .saturating_add(Weight::from_parts(985, 0).saturating_mul(n.into())) + // Minimum execution time: 279_495_000 picoseconds. + Weight::from_parts(232_736_994, 9287) + // Standard Error: 23 + .saturating_add(Weight::from_parts(1_008, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -971,6 +1010,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -986,10 +1027,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `856 + r * (45 ±0)` // Estimated: `9271 + r * (45 ±0)` - // Minimum execution time: 248_332_000 picoseconds. - Weight::from_parts(274_998_906, 9271) - // Standard Error: 949_561 - .saturating_add(Weight::from_parts(5_570_693, 0).saturating_mul(r.into())) + // Minimum execution time: 257_920_000 picoseconds. + Weight::from_parts(282_276_265, 9271) + // Standard Error: 948_490 + .saturating_add(Weight::from_parts(2_408_134, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 45).saturating_mul(r.into())) @@ -998,6 +1039,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1013,10 +1056,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866` // Estimated: `9288` - // Minimum execution time: 272_055_000 picoseconds. - Weight::from_parts(282_280_090, 9288) - // Standard Error: 1 - .saturating_add(Weight::from_parts(330, 0).saturating_mul(n.into())) + // Minimum execution time: 278_149_000 picoseconds. + Weight::from_parts(287_020_337, 9288) + // Standard Error: 0 + .saturating_add(Weight::from_parts(321, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1024,9 +1067,11 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `Contracts::CodeInfoOf` (r:2 w:2) + /// Storage: `Contracts::CodeInfoOf` (r:33 w:33) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) @@ -1037,28 +1082,30 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `Contracts::DeletionQueue` (r:0 w:1) /// Proof: `Contracts::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) /// The range of component `r` is `[0, 1]`. fn seal_terminate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2902 + r * (529 ±0)` - // Estimated: `11317 + r * (5479 ±0)` - // Minimum execution time: 274_842_000 picoseconds. - Weight::from_parts(299_824_497, 11317) - // Standard Error: 902_686 - .saturating_add(Weight::from_parts(106_562_902, 0).saturating_mul(r.into())) + // Measured: `4805 + r * (2121 ±0)` + // Estimated: `13220 + r * (81321 ±0)` + // Minimum execution time: 307_763_000 picoseconds. + Weight::from_parts(323_648_618, 13220) + // Standard Error: 879_890 + .saturating_add(Weight::from_parts(249_045_481, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().reads((36_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(T::DbWeight::get().writes((10_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 5266).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().writes((41_u64).saturating_mul(r.into()))) + .saturating_add(Weight::from_parts(0, 81321).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1076,10 +1123,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `947 + r * (10 ±0)` // Estimated: `9363 + r * (10 ±0)` - // Minimum execution time: 255_393_000 picoseconds. - Weight::from_parts(309_814_338, 9363) - // Standard Error: 2_978 - .saturating_add(Weight::from_parts(1_203_507, 0).saturating_mul(r.into())) + // Minimum execution time: 278_400_000 picoseconds. + Weight::from_parts(293_743_000, 9363) + // Standard Error: 1_686 + .saturating_add(Weight::from_parts(1_288_603, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -1088,6 +1135,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1103,10 +1152,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `866 + r * (10 ±0)` // Estimated: `9283 + r * (10 ±0)` - // Minimum execution time: 250_378_000 picoseconds. - Weight::from_parts(287_003_144, 9283) - // Standard Error: 2_726 - .saturating_add(Weight::from_parts(1_850_967, 0).saturating_mul(r.into())) + // Minimum execution time: 272_110_000 picoseconds. + Weight::from_parts(295_620_726, 9283) + // Standard Error: 5_481 + .saturating_add(Weight::from_parts(2_031_955, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -1115,6 +1164,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1131,12 +1182,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `883 + t * (32 ±0)` // Estimated: `9303 + t * (2508 ±0)` - // Minimum execution time: 266_787_000 picoseconds. - Weight::from_parts(284_368_661, 9303) - // Standard Error: 121_315 - .saturating_add(Weight::from_parts(2_690_211, 0).saturating_mul(t.into())) - // Standard Error: 33 - .saturating_add(Weight::from_parts(789, 0).saturating_mul(n.into())) + // Minimum execution time: 277_409_000 picoseconds. + Weight::from_parts(293_838_037, 9303) + // Standard Error: 87_977 + .saturating_add(Weight::from_parts(2_911_340, 0).saturating_mul(t.into())) + // Standard Error: 24 + .saturating_add(Weight::from_parts(531, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1147,6 +1198,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1162,10 +1215,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `865 + r * (7 ±0)` // Estimated: `9285 + r * (7 ±0)` - // Minimum execution time: 166_804_000 picoseconds. - Weight::from_parts(175_118_291, 9285) - // Standard Error: 398 - .saturating_add(Weight::from_parts(220_961, 0).saturating_mul(r.into())) + // Minimum execution time: 172_634_000 picoseconds. + Weight::from_parts(183_322_840, 9285) + // Standard Error: 384 + .saturating_add(Weight::from_parts(226_007, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) @@ -1174,6 +1227,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1189,10 +1244,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `125816` // Estimated: `131758` - // Minimum execution time: 398_436_000 picoseconds. - Weight::from_parts(385_003_285, 131758) + // Minimum execution time: 425_713_000 picoseconds. + Weight::from_parts(394_260_924, 131758) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_038, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(1_032, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1203,10 +1258,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `927 + r * (292 ±0)` // Estimated: `929 + r * (293 ±0)` - // Minimum execution time: 274_099_000 picoseconds. - Weight::from_parts(174_282_817, 929) - // Standard Error: 10_547 - .saturating_add(Weight::from_parts(6_262_173, 0).saturating_mul(r.into())) + // Minimum execution time: 268_128_000 picoseconds. + Weight::from_parts(186_787_113, 929) + // Standard Error: 10_796 + .saturating_add(Weight::from_parts(6_454_780, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1220,10 +1275,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1450` // Estimated: `1433` - // Minimum execution time: 274_061_000 picoseconds. - Weight::from_parts(334_755_333, 1433) - // Standard Error: 66 - .saturating_add(Weight::from_parts(771, 0).saturating_mul(n.into())) + // Minimum execution time: 286_565_000 picoseconds. + Weight::from_parts(349_504_932, 1433) + // Standard Error: 70 + .saturating_add(Weight::from_parts(530, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -1234,8 +1289,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1256 + n * (1 ±0)` // Estimated: `1256 + n * (1 ±0)` - // Minimum execution time: 272_657_000 picoseconds. - Weight::from_parts(299_061_594, 1256) + // Minimum execution time: 282_478_000 picoseconds. + Weight::from_parts(303_448_260, 1256) + // Standard Error: 34 + .saturating_add(Weight::from_parts(712, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1247,10 +1304,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `924 + r * (288 ±0)` // Estimated: `930 + r * (289 ±0)` - // Minimum execution time: 270_524_000 picoseconds. - Weight::from_parts(177_959_667, 930) - // Standard Error: 10_397 - .saturating_add(Weight::from_parts(6_270_181, 0).saturating_mul(r.into())) + // Minimum execution time: 271_793_000 picoseconds. + Weight::from_parts(179_158_648, 930) + // Standard Error: 11_868 + .saturating_add(Weight::from_parts(6_397_986, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1264,8 +1321,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1252 + n * (1 ±0)` // Estimated: `1252 + n * (1 ±0)` - // Minimum execution time: 270_757_000 picoseconds. - Weight::from_parts(298_627_896, 1252) + // Minimum execution time: 273_945_000 picoseconds. + Weight::from_parts(299_855_996, 1252) + // Standard Error: 31 + .saturating_add(Weight::from_parts(309, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1277,10 +1336,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `924 + r * (296 ±0)` // Estimated: `926 + r * (297 ±0)` - // Minimum execution time: 268_082_000 picoseconds. - Weight::from_parts(202_583_730, 926) - // Standard Error: 9_029 - .saturating_add(Weight::from_parts(5_028_517, 0).saturating_mul(r.into())) + // Minimum execution time: 275_285_000 picoseconds. + Weight::from_parts(207_735_572, 926) + // Standard Error: 9_736 + .saturating_add(Weight::from_parts(5_162_837, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1293,10 +1352,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1268 + n * (1 ±0)` // Estimated: `1268 + n * (1 ±0)` - // Minimum execution time: 274_100_000 picoseconds. - Weight::from_parts(296_981_515, 1268) + // Minimum execution time: 278_929_000 picoseconds. + Weight::from_parts(302_251_674, 1268) // Standard Error: 34 - .saturating_add(Weight::from_parts(578, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(583, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1308,10 +1367,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `935 + r * (288 ±0)` // Estimated: `932 + r * (289 ±0)` - // Minimum execution time: 269_697_000 picoseconds. - Weight::from_parts(198_346_516, 932) - // Standard Error: 8_623 - .saturating_add(Weight::from_parts(4_964_116, 0).saturating_mul(r.into())) + // Minimum execution time: 258_476_000 picoseconds. + Weight::from_parts(209_578_051, 932) + // Standard Error: 8_255 + .saturating_add(Weight::from_parts(4_942_572, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1324,10 +1383,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1255 + n * (1 ±0)` // Estimated: `1255 + n * (1 ±0)` - // Minimum execution time: 264_210_000 picoseconds. - Weight::from_parts(291_387_652, 1255) - // Standard Error: 36 - .saturating_add(Weight::from_parts(524, 0).saturating_mul(n.into())) + // Minimum execution time: 273_089_000 picoseconds. + Weight::from_parts(302_452_604, 1255) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1339,10 +1396,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `917 + r * (296 ±0)` // Estimated: `922 + r * (297 ±0)` - // Minimum execution time: 267_219_000 picoseconds. - Weight::from_parts(175_866_982, 922) - // Standard Error: 11_275 - .saturating_add(Weight::from_parts(6_424_755, 0).saturating_mul(r.into())) + // Minimum execution time: 274_301_000 picoseconds. + Weight::from_parts(172_245_469, 922) + // Standard Error: 11_306 + .saturating_add(Weight::from_parts(6_526_825, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1356,10 +1413,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1269 + n * (1 ±0)` // Estimated: `1269 + n * (1 ±0)` - // Minimum execution time: 274_634_000 picoseconds. - Weight::from_parts(294_272_009, 1269) + // Minimum execution time: 280_399_000 picoseconds. + Weight::from_parts(305_970_974, 1269) // Standard Error: 36 - .saturating_add(Weight::from_parts(1_219, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(568, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1368,6 +1425,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1602 w:1601) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1383,10 +1442,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1418 + r * (45 ±0)` // Estimated: `9785 + r * (2520 ±0)` - // Minimum execution time: 266_833_000 picoseconds. - Weight::from_parts(186_049_741, 9785) - // Standard Error: 40_311 - .saturating_add(Weight::from_parts(31_365_585, 0).saturating_mul(r.into())) + // Minimum execution time: 258_452_000 picoseconds. + Weight::from_parts(276_401_000, 9785) + // Standard Error: 65_648 + .saturating_add(Weight::from_parts(33_890_852, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -1397,6 +1456,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -1412,10 +1473,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1263 + r * (245 ±0)` // Estimated: `9635 + r * (2721 ±0)` - // Minimum execution time: 272_140_000 picoseconds. - Weight::from_parts(275_009_000, 9635) - // Standard Error: 99_187 - .saturating_add(Weight::from_parts(240_702_479, 0).saturating_mul(r.into())) + // Minimum execution time: 281_394_000 picoseconds. + Weight::from_parts(286_475_000, 9635) + // Standard Error: 156_302 + .saturating_add(Weight::from_parts(250_370_283, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) @@ -1426,6 +1487,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:736 w:0) @@ -1441,10 +1504,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + r * (576 ±0)` // Estimated: `9290 + r * (2637 ±10)` - // Minimum execution time: 263_664_000 picoseconds. - Weight::from_parts(277_240_000, 9290) - // Standard Error: 169_147 - .saturating_add(Weight::from_parts(240_084_929, 0).saturating_mul(r.into())) + // Minimum execution time: 278_193_000 picoseconds. + Weight::from_parts(280_814_000, 9290) + // Standard Error: 164_401 + .saturating_add(Weight::from_parts(251_272_834, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1455,6 +1518,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -1471,12 +1536,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1310 + t * (277 ±0)` // Estimated: `12200 + t * (5227 ±0)` - // Minimum execution time: 464_644_000 picoseconds. - Weight::from_parts(40_377_313, 12200) - // Standard Error: 12_060_226 - .saturating_add(Weight::from_parts(380_635_982, 0).saturating_mul(t.into())) + // Minimum execution time: 476_812_000 picoseconds. + Weight::from_parts(70_715_306, 12200) + // Standard Error: 12_232_109 + .saturating_add(Weight::from_parts(374_277_042, 0).saturating_mul(t.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(1_014, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_022, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(16_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(6_u64)) @@ -1487,6 +1552,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:802 w:802) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:801 w:800) @@ -1500,16 +1567,16 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:803 w:803) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:800 w:800) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `r` is `[1, 800]`. fn seal_instantiate(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1281 + r * (255 ±0)` // Estimated: `9623 + r * (2731 ±0)` - // Minimum execution time: 641_845_000 picoseconds. - Weight::from_parts(649_908_000, 9623) - // Standard Error: 278_514 - .saturating_add(Weight::from_parts(361_164_598, 0).saturating_mul(r.into())) + // Minimum execution time: 656_480_000 picoseconds. + Weight::from_parts(668_579_000, 9623) + // Standard Error: 365_458 + .saturating_add(Weight::from_parts(379_238_223, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(7_u64)) @@ -1520,6 +1587,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:1) @@ -1533,7 +1602,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. @@ -1541,12 +1610,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1306 + t * (104 ±0)` // Estimated: `12214 + t * (2549 ±1)` - // Minimum execution time: 2_111_632_000 picoseconds. - Weight::from_parts(1_213_125_745, 12214) - // Standard Error: 22 - .saturating_add(Weight::from_parts(1_055, 0).saturating_mul(i.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(1_192, 0).saturating_mul(s.into())) + // Minimum execution time: 2_148_964_000 picoseconds. + Weight::from_parts(1_557_685_999, 12214) + // Standard Error: 36 + .saturating_add(Weight::from_parts(864, 0).saturating_mul(i.into())) + // Standard Error: 36 + .saturating_add(Weight::from_parts(1_092, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(19_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(11_u64)) @@ -1557,6 +1626,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1572,10 +1643,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `865 + r * (8 ±0)` // Estimated: `9279 + r * (8 ±0)` - // Minimum execution time: 264_227_000 picoseconds. - Weight::from_parts(281_015_995, 9279) - // Standard Error: 710 - .saturating_add(Weight::from_parts(365_734, 0).saturating_mul(r.into())) + // Minimum execution time: 279_377_000 picoseconds. + Weight::from_parts(287_951_287, 9279) + // Standard Error: 659 + .saturating_add(Weight::from_parts(376_476, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1584,6 +1655,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1599,10 +1672,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `873` // Estimated: `9286` - // Minimum execution time: 270_709_000 picoseconds. - Weight::from_parts(268_416_051, 9286) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_080, 0).saturating_mul(n.into())) + // Minimum execution time: 276_151_000 picoseconds. + Weight::from_parts(267_656_959, 9286) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_108, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1610,6 +1683,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1625,10 +1700,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9284 + r * (8 ±0)` - // Minimum execution time: 267_283_000 picoseconds. - Weight::from_parts(280_706_659, 9284) - // Standard Error: 540 - .saturating_add(Weight::from_parts(790_312, 0).saturating_mul(r.into())) + // Minimum execution time: 275_247_000 picoseconds. + Weight::from_parts(286_675_317, 9284) + // Standard Error: 601 + .saturating_add(Weight::from_parts(788_160, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1637,6 +1712,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1652,10 +1729,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9292` - // Minimum execution time: 262_010_000 picoseconds. - Weight::from_parts(273_278_744, 9292) + // Minimum execution time: 281_585_000 picoseconds. + Weight::from_parts(287_637_844, 9292) // Standard Error: 1 - .saturating_add(Weight::from_parts(3_362, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_351, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1663,6 +1740,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1678,10 +1757,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9286 + r * (8 ±0)` - // Minimum execution time: 268_698_000 picoseconds. - Weight::from_parts(282_890_578, 9286) - // Standard Error: 622 - .saturating_add(Weight::from_parts(441_131, 0).saturating_mul(r.into())) + // Minimum execution time: 273_678_000 picoseconds. + Weight::from_parts(289_879_306, 9286) + // Standard Error: 607 + .saturating_add(Weight::from_parts(439_482, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1690,6 +1769,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1705,10 +1786,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9291` - // Minimum execution time: 252_846_000 picoseconds. - Weight::from_parts(267_657_561, 9291) + // Minimum execution time: 275_126_000 picoseconds. + Weight::from_parts(276_684_594, 9291) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_208, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_202, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1716,6 +1797,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1731,10 +1814,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9283 + r * (8 ±0)` - // Minimum execution time: 266_899_000 picoseconds. - Weight::from_parts(276_862_067, 9283) - // Standard Error: 1_249 - .saturating_add(Weight::from_parts(443_970, 0).saturating_mul(r.into())) + // Minimum execution time: 273_229_000 picoseconds. + Weight::from_parts(287_793_841, 9283) + // Standard Error: 451 + .saturating_add(Weight::from_parts(447_922, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -1743,6 +1826,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1758,10 +1843,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9289` - // Minimum execution time: 265_413_000 picoseconds. - Weight::from_parts(265_600_840, 9289) + // Minimum execution time: 277_843_000 picoseconds. + Weight::from_parts(279_900_099, 9289) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_203, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_204, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1769,6 +1854,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1784,10 +1871,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1000 + n * (1 ±0)` // Estimated: `9412 + n * (1 ±0)` - // Minimum execution time: 328_341_000 picoseconds. - Weight::from_parts(341_038_581, 9412) - // Standard Error: 10 - .saturating_add(Weight::from_parts(5_863, 0).saturating_mul(n.into())) + // Minimum execution time: 331_840_000 picoseconds. + Weight::from_parts(338_767_191, 9412) + // Standard Error: 11 + .saturating_add(Weight::from_parts(5_971, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1796,6 +1883,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1811,10 +1900,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `808 + r * (112 ±0)` // Estimated: `9226 + r * (112 ±0)` - // Minimum execution time: 272_730_000 picoseconds. - Weight::from_parts(339_349_232, 9226) - // Standard Error: 13_004 - .saturating_add(Weight::from_parts(41_649_026, 0).saturating_mul(r.into())) + // Minimum execution time: 277_912_000 picoseconds. + Weight::from_parts(344_538_960, 9226) + // Standard Error: 13_422 + .saturating_add(Weight::from_parts(41_592_887, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(r.into())) @@ -1823,6 +1912,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1838,10 +1929,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `910 + r * (76 ±0)` // Estimated: `9279 + r * (77 ±0)` - // Minimum execution time: 273_892_000 picoseconds. - Weight::from_parts(352_853_960, 9279) - // Standard Error: 16_745 - .saturating_add(Weight::from_parts(45_853_294, 0).saturating_mul(r.into())) + // Minimum execution time: 280_383_000 picoseconds. + Weight::from_parts(348_542_377, 9279) + // Standard Error: 13_985 + .saturating_add(Weight::from_parts(45_983_827, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 77).saturating_mul(r.into())) @@ -1850,6 +1941,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1865,10 +1958,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `880 + r * (42 ±0)` // Estimated: `9294 + r * (42 ±0)` - // Minimum execution time: 268_431_000 picoseconds. - Weight::from_parts(319_727_796, 9294) - // Standard Error: 10_276 - .saturating_add(Weight::from_parts(11_928_882, 0).saturating_mul(r.into())) + // Minimum execution time: 277_764_000 picoseconds. + Weight::from_parts(320_288_180, 9294) + // Standard Error: 10_140 + .saturating_add(Weight::from_parts(12_046_137, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(r.into())) @@ -1877,6 +1970,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536) @@ -1892,10 +1987,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + r * (965 ±0)` // Estimated: `9285 + r * (3090 ±7)` - // Minimum execution time: 275_482_000 picoseconds. - Weight::from_parts(279_155_000, 9285) - // Standard Error: 65_388 - .saturating_add(Weight::from_parts(26_634_187, 0).saturating_mul(r.into())) + // Minimum execution time: 271_356_000 picoseconds. + Weight::from_parts(282_924_000, 9285) + // Standard Error: 60_493 + .saturating_add(Weight::from_parts(28_319_267, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1906,6 +2001,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -1921,20 +2018,22 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `937 + r * (131 ±0)` // Estimated: `9346 + r * (2607 ±0)` - // Minimum execution time: 270_001_000 picoseconds. - Weight::from_parts(286_792_689, 9346) - // Standard Error: 21_074 - .saturating_add(Weight::from_parts(6_465_885, 0).saturating_mul(r.into())) + // Minimum execution time: 269_698_000 picoseconds. + Weight::from_parts(294_325_127, 9346) + // Standard Error: 22_352 + .saturating_add(Weight::from_parts(6_744_117, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2606).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 2607).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -1948,12 +2047,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `r` is `[0, 32]`. fn unlock_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `969 + r * (183 ±0)` + // Measured: `972 + r * (184 ±0)` // Estimated: `129453 + r * (2568 ±0)` - // Minimum execution time: 270_652_000 picoseconds. - Weight::from_parts(293_369_452, 129453) - // Standard Error: 24_321 - .saturating_add(Weight::from_parts(5_575_600, 0).saturating_mul(r.into())) + // Minimum execution time: 261_226_000 picoseconds. + Weight::from_parts(294_299_527, 129453) + // Standard Error: 27_898 + .saturating_add(Weight::from_parts(6_031_601, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(T::DbWeight::get().writes(3_u64)) @@ -1964,6 +2063,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -1979,10 +2080,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `861 + r * (3 ±0)` // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 267_749_000 picoseconds. - Weight::from_parts(280_373_341, 9282) - // Standard Error: 464 - .saturating_add(Weight::from_parts(170_398, 0).saturating_mul(r.into())) + // Minimum execution time: 270_729_000 picoseconds. + Weight::from_parts(289_622_807, 9282) + // Standard Error: 394 + .saturating_add(Weight::from_parts(167_010, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -1991,6 +2092,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2006,10 +2109,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2112 + r * (39 ±0)` // Estimated: `10377 + r * (40 ±0)` - // Minimum execution time: 270_260_000 picoseconds. - Weight::from_parts(337_969_172, 10377) - // Standard Error: 1_557 - .saturating_add(Weight::from_parts(305_735, 0).saturating_mul(r.into())) + // Minimum execution time: 272_228_000 picoseconds. + Weight::from_parts(351_059_276, 10377) + // Standard Error: 1_761 + .saturating_add(Weight::from_parts(312_269, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 40).saturating_mul(r.into())) @@ -2018,6 +2121,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2035,10 +2140,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `864 + r * (3 ±0)` // Estimated: `9279 + r * (3 ±0)` - // Minimum execution time: 265_607_000 picoseconds. - Weight::from_parts(283_396_630, 9279) - // Standard Error: 449 - .saturating_add(Weight::from_parts(149_018, 0).saturating_mul(r.into())) + // Minimum execution time: 272_497_000 picoseconds. + Weight::from_parts(288_213_060, 9279) + // Standard Error: 469 + .saturating_add(Weight::from_parts(155_530, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2048,10 +2153,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_813_000 picoseconds. - Weight::from_parts(1_264_945, 0) - // Standard Error: 19 - .saturating_add(Weight::from_parts(15_098, 0).saturating_mul(r.into())) + // Minimum execution time: 1_990_000 picoseconds. + Weight::from_parts(1_778_221, 0) + // Standard Error: 26 + .saturating_add(Weight::from_parts(14_888, 0).saturating_mul(r.into())) } } @@ -2063,8 +2168,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_054_000 picoseconds. - Weight::from_parts(2_178_000, 1627) + // Minimum execution time: 2_130_000 picoseconds. + Weight::from_parts(2_247_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -2074,10 +2179,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `452 + k * (69 ±0)` // Estimated: `442 + k * (70 ±0)` - // Minimum execution time: 12_119_000 picoseconds. - Weight::from_parts(12_536_000, 442) - // Standard Error: 1_254 - .saturating_add(Weight::from_parts(1_161_885, 0).saturating_mul(k.into())) + // Minimum execution time: 12_748_000 picoseconds. + Weight::from_parts(13_001_000, 442) + // Standard Error: 1_206 + .saturating_add(Weight::from_parts(1_146_159, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -2091,10 +2196,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `211 + c * (1 ±0)` // Estimated: `6149 + c * (1 ±0)` - // Minimum execution time: 8_146_000 picoseconds. - Weight::from_parts(8_560_745, 6149) + // Minimum execution time: 8_636_000 picoseconds. + Weight::from_parts(8_664_917, 6149) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_182, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_188, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -2107,8 +2212,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `510` // Estimated: `6450` - // Minimum execution time: 16_183_000 picoseconds. - Weight::from_parts(16_825_000, 6450) + // Minimum execution time: 16_838_000 picoseconds. + Weight::from_parts(17_400_000, 6450) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2121,10 +2226,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `171 + k * (1 ±0)` // Estimated: `3635 + k * (1 ±0)` - // Minimum execution time: 3_645_000 picoseconds. - Weight::from_parts(604_365, 3635) - // Standard Error: 1_013 - .saturating_add(Weight::from_parts(1_100_277, 0).saturating_mul(k.into())) + // Minimum execution time: 3_876_000 picoseconds. + Weight::from_parts(2_654_935, 3635) + // Standard Error: 2_001 + .saturating_add(Weight::from_parts(1_258_085, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -2134,6 +2239,8 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553053f13fd319a03c211337c76e0fe776df` (r:2 w:0) /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) /// Proof: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc553022fca90611ba8b7942f8bdb3b97f6580` (r:1 w:1) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:0 w:1) @@ -2143,10 +2250,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `328 + c * (1 ±0)` // Estimated: `6266 + c * (1 ±0)` - // Minimum execution time: 19_500_000 picoseconds. - Weight::from_parts(20_074_895, 6266) + // Minimum execution time: 21_038_000 picoseconds. + Weight::from_parts(20_890_548, 6266) // Standard Error: 1 - .saturating_add(Weight::from_parts(422, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(435, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) @@ -2157,8 +2264,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `440` // Estimated: `6380` - // Minimum execution time: 12_530_000 picoseconds. - Weight::from_parts(13_362_000, 6380) + // Minimum execution time: 12_579_000 picoseconds. + Weight::from_parts(13_486_000, 6380) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2167,13 +2274,13 @@ impl WeightInfo for () { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:0) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) fn v14_migration_step() -> Weight { // Proof Size summary in bytes: // Measured: `352` // Estimated: `6292` - // Minimum execution time: 44_275_000 picoseconds. - Weight::from_parts(45_718_000, 6292) + // Minimum execution time: 47_123_000 picoseconds. + Weight::from_parts(48_284_000, 6292) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2185,8 +2292,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `594` // Estimated: `6534` - // Minimum execution time: 55_095_000 picoseconds. - Weight::from_parts(58_009_000, 6534) + // Minimum execution time: 55_237_000 picoseconds. + Weight::from_parts(57_996_000, 6534) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2196,8 +2303,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 2_455_000 picoseconds. - Weight::from_parts(2_608_000, 1627) + // Minimum execution time: 2_766_000 picoseconds. + Weight::from_parts(2_807_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2209,8 +2316,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `166` // Estimated: `3631` - // Minimum execution time: 11_207_000 picoseconds. - Weight::from_parts(11_802_000, 3631) + // Minimum execution time: 12_243_000 picoseconds. + Weight::from_parts(12_890_000, 3631) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2220,8 +2327,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 4_581_000 picoseconds. - Weight::from_parts(4_781_000, 3607) + // Minimum execution time: 4_951_000 picoseconds. + Weight::from_parts(5_232_000, 3607) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -2232,8 +2339,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `167` // Estimated: `3632` - // Minimum execution time: 5_887_000 picoseconds. - Weight::from_parts(6_393_000, 3632) + // Minimum execution time: 6_530_000 picoseconds. + Weight::from_parts(6_726_000, 3632) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x4342193e496fab7ec59d615ed0dc55304e7b9012096b41c4eb3aaf947f6ea429` (r:1 w:0) @@ -2244,13 +2351,15 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `3607` - // Minimum execution time: 6_025_000 picoseconds. - Weight::from_parts(6_298_000, 3607) + // Minimum execution time: 6_227_000 picoseconds. + Weight::from_parts(6_708_000, 3607) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2268,20 +2377,22 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `804 + c * (1 ±0)` // Estimated: `9217 + c * (1 ±0)` - // Minimum execution time: 294_976_000 picoseconds. - Weight::from_parts(277_235_948, 9217) - // Standard Error: 65 - .saturating_add(Weight::from_parts(34_445, 0).saturating_mul(c.into())) + // Minimum execution time: 309_889_000 picoseconds. + Weight::from_parts(277_084_159, 9217) + // Standard Error: 71 + .saturating_add(Weight::from_parts(33_471, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:3 w:3) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) @@ -2301,14 +2412,14 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `326` // Estimated: `8740` - // Minimum execution time: 3_864_558_000 picoseconds. - Weight::from_parts(421_676_889, 8740) - // Standard Error: 188 - .saturating_add(Weight::from_parts(103_788, 0).saturating_mul(c.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(1_715, 0).saturating_mul(i.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(1_774, 0).saturating_mul(s.into())) + // Minimum execution time: 3_909_680_000 picoseconds. + Weight::from_parts(446_471_160, 8740) + // Standard Error: 159 + .saturating_add(Weight::from_parts(101_085, 0).saturating_mul(c.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_598, 0).saturating_mul(i.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_879, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } @@ -2318,6 +2429,8 @@ impl WeightInfo for () { /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::Nonce` (r:1 w:1) /// Proof: `Contracts::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) @@ -2329,24 +2442,26 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:2 w:2) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `i` is `[0, 1048576]`. /// The range of component `s` is `[0, 1048576]`. fn instantiate(i: u32, s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `563` // Estimated: `8982` - // Minimum execution time: 2_069_276_000 picoseconds. - Weight::from_parts(377_210_279, 8982) - // Standard Error: 9 - .saturating_add(Weight::from_parts(1_719, 0).saturating_mul(i.into())) - // Standard Error: 9 - .saturating_add(Weight::from_parts(1_728, 0).saturating_mul(s.into())) + // Minimum execution time: 1_968_545_000 picoseconds. + Weight::from_parts(420_048_028, 8982) + // Standard Error: 20 + .saturating_add(Weight::from_parts(1_685, 0).saturating_mul(i.into())) + // Standard Error: 20 + .saturating_add(Weight::from_parts(1_645, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2363,17 +2478,19 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `829` // Estimated: `9244` - // Minimum execution time: 199_037_000 picoseconds. - Weight::from_parts(213_931_000, 9244) + // Minimum execution time: 207_564_000 picoseconds. + Weight::from_parts(216_983_000, 9244) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -2383,10 +2500,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `145` // Estimated: `6085` - // Minimum execution time: 278_482_000 picoseconds. - Weight::from_parts(262_753_879, 6085) - // Standard Error: 112 - .saturating_add(Weight::from_parts(66_129, 0).saturating_mul(c.into())) + // Minimum execution time: 273_555_000 picoseconds. + Weight::from_parts(257_517_935, 6085) + // Standard Error: 148 + .saturating_add(Weight::from_parts(64_488, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2407,10 +2524,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `145` // Estimated: `6085` - // Minimum execution time: 286_902_000 picoseconds. - Weight::from_parts(269_003_959, 6085) - // Standard Error: 123 - .saturating_add(Weight::from_parts(66_629, 0).saturating_mul(c.into())) + // Minimum execution time: 289_672_000 picoseconds. + Weight::from_parts(297_020_278, 6085) + // Standard Error: 86 + .saturating_add(Weight::from_parts(64_340, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2419,7 +2536,7 @@ impl WeightInfo for () { /// Storage: `Contracts::CodeInfoOf` (r:1 w:1) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `System::EventTopics` (r:1 w:1) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:0 w:1) @@ -2428,8 +2545,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `315` // Estimated: `3780` - // Minimum execution time: 44_128_000 picoseconds. - Weight::from_parts(46_044_000, 3780) + // Minimum execution time: 45_930_000 picoseconds. + Weight::from_parts(47_288_000, 3780) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2445,8 +2562,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `552` // Estimated: `8967` - // Minimum execution time: 33_567_000 picoseconds. - Weight::from_parts(35_057_000, 8967) + // Minimum execution time: 35_421_000 picoseconds. + Weight::from_parts(36_909_000, 8967) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -2454,6 +2571,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2469,10 +2588,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `869 + r * (6 ±0)` // Estimated: `9284 + r * (6 ±0)` - // Minimum execution time: 272_376_000 picoseconds. - Weight::from_parts(284_162_161, 9284) - // Standard Error: 501 - .saturating_add(Weight::from_parts(341_575, 0).saturating_mul(r.into())) + // Minimum execution time: 275_531_000 picoseconds. + Weight::from_parts(292_269_656, 9284) + // Standard Error: 672 + .saturating_add(Weight::from_parts(339_728, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2481,6 +2600,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2496,10 +2617,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `925 + r * (209 ±0)` // Estimated: `9304 + r * (2684 ±0)` - // Minimum execution time: 256_990_000 picoseconds. - Weight::from_parts(107_167_044, 9304) - // Standard Error: 7_545 - .saturating_add(Weight::from_parts(3_628_112, 0).saturating_mul(r.into())) + // Minimum execution time: 275_829_000 picoseconds. + Weight::from_parts(124_543_289, 9304) + // Standard Error: 6_085 + .saturating_add(Weight::from_parts(3_702_964, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -2509,6 +2630,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1601 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2524,10 +2647,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `924 + r * (213 ±0)` // Estimated: `9308 + r * (2688 ±0)` - // Minimum execution time: 272_889_000 picoseconds. - Weight::from_parts(110_341_799, 9308) - // Standard Error: 7_881 - .saturating_add(Weight::from_parts(4_427_043, 0).saturating_mul(r.into())) + // Minimum execution time: 276_666_000 picoseconds. + Weight::from_parts(96_951_288, 9308) + // Standard Error: 8_876 + .saturating_add(Weight::from_parts(4_604_699, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -2537,6 +2660,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2552,10 +2677,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `876 + r * (6 ±0)` // Estimated: `9293 + r * (6 ±0)` - // Minimum execution time: 275_027_000 picoseconds. - Weight::from_parts(283_302_223, 9293) - // Standard Error: 1_179 - .saturating_add(Weight::from_parts(436_023, 0).saturating_mul(r.into())) + // Minimum execution time: 271_301_000 picoseconds. + Weight::from_parts(284_126_054, 9293) + // Standard Error: 886 + .saturating_add(Weight::from_parts(437_127, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2564,6 +2689,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2579,16 +2706,18 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866 + r * (3 ±0)` // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 270_137_000 picoseconds. - Weight::from_parts(282_756_362, 9282) - // Standard Error: 384 - .saturating_add(Weight::from_parts(171_660, 0).saturating_mul(r.into())) + // Minimum execution time: 274_778_000 picoseconds. + Weight::from_parts(289_355_269, 9282) + // Standard Error: 382 + .saturating_add(Weight::from_parts(175_342, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2604,10 +2733,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `756 + r * (3 ±0)` // Estimated: `9171 + r * (3 ±0)` - // Minimum execution time: 255_131_000 picoseconds. - Weight::from_parts(269_207_006, 9171) - // Standard Error: 542 - .saturating_add(Weight::from_parts(161_597, 0).saturating_mul(r.into())) + // Minimum execution time: 257_310_000 picoseconds. + Weight::from_parts(276_410_847, 9171) + // Standard Error: 733 + .saturating_add(Weight::from_parts(160_094, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(10_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -2616,6 +2745,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2631,10 +2762,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `870 + r * (6 ±0)` // Estimated: `9285 + r * (6 ±0)` - // Minimum execution time: 272_172_000 picoseconds. - Weight::from_parts(283_747_134, 9285) - // Standard Error: 885 - .saturating_add(Weight::from_parts(343_968, 0).saturating_mul(r.into())) + // Minimum execution time: 278_305_000 picoseconds. + Weight::from_parts(282_372_935, 9285) + // Standard Error: 1_154 + .saturating_add(Weight::from_parts(343_382, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2643,6 +2774,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2658,10 +2791,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866 + r * (6 ±0)` // Estimated: `9284 + r * (6 ±0)` - // Minimum execution time: 263_220_000 picoseconds. - Weight::from_parts(277_062_382, 9284) - // Standard Error: 1_783 - .saturating_add(Weight::from_parts(399_631, 0).saturating_mul(r.into())) + // Minimum execution time: 280_349_000 picoseconds. + Weight::from_parts(294_864_875, 9284) + // Standard Error: 1_010 + .saturating_add(Weight::from_parts(368_740, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2670,6 +2803,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:2 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2685,10 +2820,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1010 + r * (6 ±0)` // Estimated: `9409 + r * (6 ±0)` - // Minimum execution time: 253_218_000 picoseconds. - Weight::from_parts(282_251_452, 9409) - // Standard Error: 2_367 - .saturating_add(Weight::from_parts(1_604_060, 0).saturating_mul(r.into())) + // Minimum execution time: 274_578_000 picoseconds. + Weight::from_parts(313_285_034, 9409) + // Standard Error: 2_800 + .saturating_add(Weight::from_parts(1_653_468, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2697,6 +2832,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2712,10 +2849,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `880 + r * (6 ±0)` // Estimated: `9301 + r * (6 ±0)` - // Minimum execution time: 271_797_000 picoseconds. - Weight::from_parts(288_594_393, 9301) - // Standard Error: 846 - .saturating_add(Weight::from_parts(335_063, 0).saturating_mul(r.into())) + // Minimum execution time: 287_127_000 picoseconds. + Weight::from_parts(290_489_909, 9301) + // Standard Error: 864 + .saturating_add(Weight::from_parts(332_977, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2724,6 +2861,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2739,10 +2878,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `878 + r * (6 ±0)` // Estimated: `9294 + r * (6 ±0)` - // Minimum execution time: 254_997_000 picoseconds. - Weight::from_parts(284_331_894, 9294) - // Standard Error: 885 - .saturating_add(Weight::from_parts(337_073, 0).saturating_mul(r.into())) + // Minimum execution time: 273_291_000 picoseconds. + Weight::from_parts(293_650_716, 9294) + // Standard Error: 725 + .saturating_add(Weight::from_parts(323_281, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2751,6 +2890,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2766,10 +2907,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `875 + r * (6 ±0)` // Estimated: `9297 + r * (6 ±0)` - // Minimum execution time: 273_845_000 picoseconds. - Weight::from_parts(285_291_242, 9297) - // Standard Error: 690 - .saturating_add(Weight::from_parts(332_783, 0).saturating_mul(r.into())) + // Minimum execution time: 282_061_000 picoseconds. + Weight::from_parts(291_729_751, 9297) + // Standard Error: 929 + .saturating_add(Weight::from_parts(324_683, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2778,6 +2919,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2793,10 +2936,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866 + r * (6 ±0)` // Estimated: `9282 + r * (6 ±0)` - // Minimum execution time: 268_302_000 picoseconds. - Weight::from_parts(280_463_257, 9282) - // Standard Error: 1_035 - .saturating_add(Weight::from_parts(345_811, 0).saturating_mul(r.into())) + // Minimum execution time: 264_505_000 picoseconds. + Weight::from_parts(293_440_286, 9282) + // Standard Error: 704 + .saturating_add(Weight::from_parts(329_851, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2805,6 +2948,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2822,10 +2967,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `940 + r * (14 ±0)` // Estimated: `9350 + r * (14 ±0)` - // Minimum execution time: 263_433_000 picoseconds. - Weight::from_parts(290_098_370, 9350) - // Standard Error: 1_905 - .saturating_add(Weight::from_parts(805_299, 0).saturating_mul(r.into())) + // Minimum execution time: 277_208_000 picoseconds. + Weight::from_parts(304_294_691, 9350) + // Standard Error: 1_083 + .saturating_add(Weight::from_parts(824_245, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 14).saturating_mul(r.into())) @@ -2834,6 +2979,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2849,10 +2996,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `868 + r * (6 ±0)` // Estimated: `9285 + r * (6 ±0)` - // Minimum execution time: 273_588_000 picoseconds. - Weight::from_parts(287_133_565, 9285) - // Standard Error: 799 - .saturating_add(Weight::from_parts(254_114, 0).saturating_mul(r.into())) + // Minimum execution time: 278_293_000 picoseconds. + Weight::from_parts(289_743_005, 9285) + // Standard Error: 672 + .saturating_add(Weight::from_parts(267_553, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 6).saturating_mul(r.into())) @@ -2861,6 +3008,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2876,10 +3025,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `872` // Estimated: `9287` - // Minimum execution time: 257_843_000 picoseconds. - Weight::from_parts(228_177_495, 9287) - // Standard Error: 24 - .saturating_add(Weight::from_parts(985, 0).saturating_mul(n.into())) + // Minimum execution time: 279_495_000 picoseconds. + Weight::from_parts(232_736_994, 9287) + // Standard Error: 23 + .saturating_add(Weight::from_parts(1_008, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -2887,6 +3036,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2902,10 +3053,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `856 + r * (45 ±0)` // Estimated: `9271 + r * (45 ±0)` - // Minimum execution time: 248_332_000 picoseconds. - Weight::from_parts(274_998_906, 9271) - // Standard Error: 949_561 - .saturating_add(Weight::from_parts(5_570_693, 0).saturating_mul(r.into())) + // Minimum execution time: 257_920_000 picoseconds. + Weight::from_parts(282_276_265, 9271) + // Standard Error: 948_490 + .saturating_add(Weight::from_parts(2_408_134, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 45).saturating_mul(r.into())) @@ -2914,6 +3065,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2929,10 +3082,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866` // Estimated: `9288` - // Minimum execution time: 272_055_000 picoseconds. - Weight::from_parts(282_280_090, 9288) - // Standard Error: 1 - .saturating_add(Weight::from_parts(330, 0).saturating_mul(n.into())) + // Minimum execution time: 278_149_000 picoseconds. + Weight::from_parts(287_020_337, 9288) + // Standard Error: 0 + .saturating_add(Weight::from_parts(321, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -2940,9 +3093,11 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) - /// Storage: `Contracts::CodeInfoOf` (r:2 w:2) + /// Storage: `Contracts::CodeInfoOf` (r:33 w:33) /// Proof: `Contracts::CodeInfoOf` (`max_values`: None, `max_size`: Some(93), added: 2568, mode: `Measured`) /// Storage: `Contracts::PristineCode` (r:1 w:0) /// Proof: `Contracts::PristineCode` (`max_values`: None, `max_size`: Some(125988), added: 128463, mode: `Measured`) @@ -2953,28 +3108,30 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// Storage: `Contracts::DeletionQueue` (r:0 w:1) /// Proof: `Contracts::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) /// The range of component `r` is `[0, 1]`. fn seal_terminate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2902 + r * (529 ±0)` - // Estimated: `11317 + r * (5479 ±0)` - // Minimum execution time: 274_842_000 picoseconds. - Weight::from_parts(299_824_497, 11317) - // Standard Error: 902_686 - .saturating_add(Weight::from_parts(106_562_902, 0).saturating_mul(r.into())) + // Measured: `4805 + r * (2121 ±0)` + // Estimated: `13220 + r * (81321 ±0)` + // Minimum execution time: 307_763_000 picoseconds. + Weight::from_parts(323_648_618, 13220) + // Standard Error: 879_890 + .saturating_add(Weight::from_parts(249_045_481, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().reads((5_u64).saturating_mul(r.into()))) + .saturating_add(RocksDbWeight::get().reads((36_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(RocksDbWeight::get().writes((10_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 5266).saturating_mul(r.into())) + .saturating_add(RocksDbWeight::get().writes((41_u64).saturating_mul(r.into()))) + .saturating_add(Weight::from_parts(0, 81321).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -2992,10 +3149,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `947 + r * (10 ±0)` // Estimated: `9363 + r * (10 ±0)` - // Minimum execution time: 255_393_000 picoseconds. - Weight::from_parts(309_814_338, 9363) - // Standard Error: 2_978 - .saturating_add(Weight::from_parts(1_203_507, 0).saturating_mul(r.into())) + // Minimum execution time: 278_400_000 picoseconds. + Weight::from_parts(293_743_000, 9363) + // Standard Error: 1_686 + .saturating_add(Weight::from_parts(1_288_603, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -3004,6 +3161,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3019,10 +3178,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `866 + r * (10 ±0)` // Estimated: `9283 + r * (10 ±0)` - // Minimum execution time: 250_378_000 picoseconds. - Weight::from_parts(287_003_144, 9283) - // Standard Error: 2_726 - .saturating_add(Weight::from_parts(1_850_967, 0).saturating_mul(r.into())) + // Minimum execution time: 272_110_000 picoseconds. + Weight::from_parts(295_620_726, 9283) + // Standard Error: 5_481 + .saturating_add(Weight::from_parts(2_031_955, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 10).saturating_mul(r.into())) @@ -3031,6 +3190,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3047,12 +3208,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `883 + t * (32 ±0)` // Estimated: `9303 + t * (2508 ±0)` - // Minimum execution time: 266_787_000 picoseconds. - Weight::from_parts(284_368_661, 9303) - // Standard Error: 121_315 - .saturating_add(Weight::from_parts(2_690_211, 0).saturating_mul(t.into())) - // Standard Error: 33 - .saturating_add(Weight::from_parts(789, 0).saturating_mul(n.into())) + // Minimum execution time: 277_409_000 picoseconds. + Weight::from_parts(293_838_037, 9303) + // Standard Error: 87_977 + .saturating_add(Weight::from_parts(2_911_340, 0).saturating_mul(t.into())) + // Standard Error: 24 + .saturating_add(Weight::from_parts(531, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3063,6 +3224,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3078,10 +3241,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `865 + r * (7 ±0)` // Estimated: `9285 + r * (7 ±0)` - // Minimum execution time: 166_804_000 picoseconds. - Weight::from_parts(175_118_291, 9285) - // Standard Error: 398 - .saturating_add(Weight::from_parts(220_961, 0).saturating_mul(r.into())) + // Minimum execution time: 172_634_000 picoseconds. + Weight::from_parts(183_322_840, 9285) + // Standard Error: 384 + .saturating_add(Weight::from_parts(226_007, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 7).saturating_mul(r.into())) @@ -3090,6 +3253,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3105,10 +3270,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `125816` // Estimated: `131758` - // Minimum execution time: 398_436_000 picoseconds. - Weight::from_parts(385_003_285, 131758) + // Minimum execution time: 425_713_000 picoseconds. + Weight::from_parts(394_260_924, 131758) // Standard Error: 12 - .saturating_add(Weight::from_parts(1_038, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(1_032, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3119,10 +3284,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `927 + r * (292 ±0)` // Estimated: `929 + r * (293 ±0)` - // Minimum execution time: 274_099_000 picoseconds. - Weight::from_parts(174_282_817, 929) - // Standard Error: 10_547 - .saturating_add(Weight::from_parts(6_262_173, 0).saturating_mul(r.into())) + // Minimum execution time: 268_128_000 picoseconds. + Weight::from_parts(186_787_113, 929) + // Standard Error: 10_796 + .saturating_add(Weight::from_parts(6_454_780, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3136,10 +3301,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1450` // Estimated: `1433` - // Minimum execution time: 274_061_000 picoseconds. - Weight::from_parts(334_755_333, 1433) - // Standard Error: 66 - .saturating_add(Weight::from_parts(771, 0).saturating_mul(n.into())) + // Minimum execution time: 286_565_000 picoseconds. + Weight::from_parts(349_504_932, 1433) + // Standard Error: 70 + .saturating_add(Weight::from_parts(530, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(15_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } @@ -3150,8 +3315,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1256 + n * (1 ±0)` // Estimated: `1256 + n * (1 ±0)` - // Minimum execution time: 272_657_000 picoseconds. - Weight::from_parts(299_061_594, 1256) + // Minimum execution time: 282_478_000 picoseconds. + Weight::from_parts(303_448_260, 1256) + // Standard Error: 34 + .saturating_add(Weight::from_parts(712, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3163,10 +3330,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `924 + r * (288 ±0)` // Estimated: `930 + r * (289 ±0)` - // Minimum execution time: 270_524_000 picoseconds. - Weight::from_parts(177_959_667, 930) - // Standard Error: 10_397 - .saturating_add(Weight::from_parts(6_270_181, 0).saturating_mul(r.into())) + // Minimum execution time: 271_793_000 picoseconds. + Weight::from_parts(179_158_648, 930) + // Standard Error: 11_868 + .saturating_add(Weight::from_parts(6_397_986, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3180,8 +3347,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1252 + n * (1 ±0)` // Estimated: `1252 + n * (1 ±0)` - // Minimum execution time: 270_757_000 picoseconds. - Weight::from_parts(298_627_896, 1252) + // Minimum execution time: 273_945_000 picoseconds. + Weight::from_parts(299_855_996, 1252) + // Standard Error: 31 + .saturating_add(Weight::from_parts(309, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3193,10 +3362,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `924 + r * (296 ±0)` // Estimated: `926 + r * (297 ±0)` - // Minimum execution time: 268_082_000 picoseconds. - Weight::from_parts(202_583_730, 926) - // Standard Error: 9_029 - .saturating_add(Weight::from_parts(5_028_517, 0).saturating_mul(r.into())) + // Minimum execution time: 275_285_000 picoseconds. + Weight::from_parts(207_735_572, 926) + // Standard Error: 9_736 + .saturating_add(Weight::from_parts(5_162_837, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3209,10 +3378,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1268 + n * (1 ±0)` // Estimated: `1268 + n * (1 ±0)` - // Minimum execution time: 274_100_000 picoseconds. - Weight::from_parts(296_981_515, 1268) + // Minimum execution time: 278_929_000 picoseconds. + Weight::from_parts(302_251_674, 1268) // Standard Error: 34 - .saturating_add(Weight::from_parts(578, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(583, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3224,10 +3393,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `935 + r * (288 ±0)` // Estimated: `932 + r * (289 ±0)` - // Minimum execution time: 269_697_000 picoseconds. - Weight::from_parts(198_346_516, 932) - // Standard Error: 8_623 - .saturating_add(Weight::from_parts(4_964_116, 0).saturating_mul(r.into())) + // Minimum execution time: 258_476_000 picoseconds. + Weight::from_parts(209_578_051, 932) + // Standard Error: 8_255 + .saturating_add(Weight::from_parts(4_942_572, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3240,10 +3409,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1255 + n * (1 ±0)` // Estimated: `1255 + n * (1 ±0)` - // Minimum execution time: 264_210_000 picoseconds. - Weight::from_parts(291_387_652, 1255) - // Standard Error: 36 - .saturating_add(Weight::from_parts(524, 0).saturating_mul(n.into())) + // Minimum execution time: 273_089_000 picoseconds. + Weight::from_parts(302_452_604, 1255) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3255,10 +3422,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `917 + r * (296 ±0)` // Estimated: `922 + r * (297 ±0)` - // Minimum execution time: 267_219_000 picoseconds. - Weight::from_parts(175_866_982, 922) - // Standard Error: 11_275 - .saturating_add(Weight::from_parts(6_424_755, 0).saturating_mul(r.into())) + // Minimum execution time: 274_301_000 picoseconds. + Weight::from_parts(172_245_469, 922) + // Standard Error: 11_306 + .saturating_add(Weight::from_parts(6_526_825, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3272,10 +3439,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1269 + n * (1 ±0)` // Estimated: `1269 + n * (1 ±0)` - // Minimum execution time: 274_634_000 picoseconds. - Weight::from_parts(294_272_009, 1269) + // Minimum execution time: 280_399_000 picoseconds. + Weight::from_parts(305_970_974, 1269) // Standard Error: 36 - .saturating_add(Weight::from_parts(1_219, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(568, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3284,6 +3451,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1602 w:1601) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3299,10 +3468,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1418 + r * (45 ±0)` // Estimated: `9785 + r * (2520 ±0)` - // Minimum execution time: 266_833_000 picoseconds. - Weight::from_parts(186_049_741, 9785) - // Standard Error: 40_311 - .saturating_add(Weight::from_parts(31_365_585, 0).saturating_mul(r.into())) + // Minimum execution time: 258_452_000 picoseconds. + Weight::from_parts(276_401_000, 9785) + // Standard Error: 65_648 + .saturating_add(Weight::from_parts(33_890_852, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) @@ -3313,6 +3482,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -3328,10 +3499,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1263 + r * (245 ±0)` // Estimated: `9635 + r * (2721 ±0)` - // Minimum execution time: 272_140_000 picoseconds. - Weight::from_parts(275_009_000, 9635) - // Standard Error: 99_187 - .saturating_add(Weight::from_parts(240_702_479, 0).saturating_mul(r.into())) + // Minimum execution time: 281_394_000 picoseconds. + Weight::from_parts(286_475_000, 9635) + // Standard Error: 156_302 + .saturating_add(Weight::from_parts(250_370_283, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) @@ -3342,6 +3513,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:736 w:0) @@ -3357,10 +3530,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + r * (576 ±0)` // Estimated: `9290 + r * (2637 ±10)` - // Minimum execution time: 263_664_000 picoseconds. - Weight::from_parts(277_240_000, 9290) - // Standard Error: 169_147 - .saturating_add(Weight::from_parts(240_084_929, 0).saturating_mul(r.into())) + // Minimum execution time: 278_193_000 picoseconds. + Weight::from_parts(280_814_000, 9290) + // Standard Error: 164_401 + .saturating_add(Weight::from_parts(251_272_834, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3371,6 +3544,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:0) @@ -3387,12 +3562,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1310 + t * (277 ±0)` // Estimated: `12200 + t * (5227 ±0)` - // Minimum execution time: 464_644_000 picoseconds. - Weight::from_parts(40_377_313, 12200) - // Standard Error: 12_060_226 - .saturating_add(Weight::from_parts(380_635_982, 0).saturating_mul(t.into())) + // Minimum execution time: 476_812_000 picoseconds. + Weight::from_parts(70_715_306, 12200) + // Standard Error: 12_232_109 + .saturating_add(Weight::from_parts(374_277_042, 0).saturating_mul(t.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(1_014, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_022, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(16_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(6_u64)) @@ -3403,6 +3578,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:802 w:802) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:801 w:801) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:801 w:800) @@ -3416,16 +3593,16 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:803 w:803) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:800 w:800) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `r` is `[1, 800]`. fn seal_instantiate(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1281 + r * (255 ±0)` // Estimated: `9623 + r * (2731 ±0)` - // Minimum execution time: 641_845_000 picoseconds. - Weight::from_parts(649_908_000, 9623) - // Standard Error: 278_514 - .saturating_add(Weight::from_parts(361_164_598, 0).saturating_mul(r.into())) + // Minimum execution time: 656_480_000 picoseconds. + Weight::from_parts(668_579_000, 9623) + // Standard Error: 365_458 + .saturating_add(Weight::from_parts(379_238_223, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().reads((6_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(7_u64)) @@ -3436,6 +3613,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:2 w:2) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:2 w:1) @@ -3449,7 +3628,7 @@ impl WeightInfo for () { /// Storage: `System::EventTopics` (r:4 w:4) /// Proof: `System::EventTopics` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(193), added: 2668, mode: `Measured`) /// The range of component `t` is `[0, 1]`. /// The range of component `i` is `[0, 983040]`. /// The range of component `s` is `[0, 983040]`. @@ -3457,12 +3636,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1306 + t * (104 ±0)` // Estimated: `12214 + t * (2549 ±1)` - // Minimum execution time: 2_111_632_000 picoseconds. - Weight::from_parts(1_213_125_745, 12214) - // Standard Error: 22 - .saturating_add(Weight::from_parts(1_055, 0).saturating_mul(i.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(1_192, 0).saturating_mul(s.into())) + // Minimum execution time: 2_148_964_000 picoseconds. + Weight::from_parts(1_557_685_999, 12214) + // Standard Error: 36 + .saturating_add(Weight::from_parts(864, 0).saturating_mul(i.into())) + // Standard Error: 36 + .saturating_add(Weight::from_parts(1_092, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(19_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(11_u64)) @@ -3473,6 +3652,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3488,10 +3669,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `865 + r * (8 ±0)` // Estimated: `9279 + r * (8 ±0)` - // Minimum execution time: 264_227_000 picoseconds. - Weight::from_parts(281_015_995, 9279) - // Standard Error: 710 - .saturating_add(Weight::from_parts(365_734, 0).saturating_mul(r.into())) + // Minimum execution time: 279_377_000 picoseconds. + Weight::from_parts(287_951_287, 9279) + // Standard Error: 659 + .saturating_add(Weight::from_parts(376_476, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3500,6 +3681,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3515,10 +3698,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `873` // Estimated: `9286` - // Minimum execution time: 270_709_000 picoseconds. - Weight::from_parts(268_416_051, 9286) - // Standard Error: 1 - .saturating_add(Weight::from_parts(1_080, 0).saturating_mul(n.into())) + // Minimum execution time: 276_151_000 picoseconds. + Weight::from_parts(267_656_959, 9286) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_108, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3526,6 +3709,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3541,10 +3726,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9284 + r * (8 ±0)` - // Minimum execution time: 267_283_000 picoseconds. - Weight::from_parts(280_706_659, 9284) - // Standard Error: 540 - .saturating_add(Weight::from_parts(790_312, 0).saturating_mul(r.into())) + // Minimum execution time: 275_247_000 picoseconds. + Weight::from_parts(286_675_317, 9284) + // Standard Error: 601 + .saturating_add(Weight::from_parts(788_160, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3553,6 +3738,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3568,10 +3755,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9292` - // Minimum execution time: 262_010_000 picoseconds. - Weight::from_parts(273_278_744, 9292) + // Minimum execution time: 281_585_000 picoseconds. + Weight::from_parts(287_637_844, 9292) // Standard Error: 1 - .saturating_add(Weight::from_parts(3_362, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_351, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3579,6 +3766,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3594,10 +3783,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9286 + r * (8 ±0)` - // Minimum execution time: 268_698_000 picoseconds. - Weight::from_parts(282_890_578, 9286) - // Standard Error: 622 - .saturating_add(Weight::from_parts(441_131, 0).saturating_mul(r.into())) + // Minimum execution time: 273_678_000 picoseconds. + Weight::from_parts(289_879_306, 9286) + // Standard Error: 607 + .saturating_add(Weight::from_parts(439_482, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3606,6 +3795,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3621,10 +3812,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9291` - // Minimum execution time: 252_846_000 picoseconds. - Weight::from_parts(267_657_561, 9291) + // Minimum execution time: 275_126_000 picoseconds. + Weight::from_parts(276_684_594, 9291) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_208, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_202, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3632,6 +3823,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3647,10 +3840,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `867 + r * (8 ±0)` // Estimated: `9283 + r * (8 ±0)` - // Minimum execution time: 266_899_000 picoseconds. - Weight::from_parts(276_862_067, 9283) - // Standard Error: 1_249 - .saturating_add(Weight::from_parts(443_970, 0).saturating_mul(r.into())) + // Minimum execution time: 273_229_000 picoseconds. + Weight::from_parts(287_793_841, 9283) + // Standard Error: 451 + .saturating_add(Weight::from_parts(447_922, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 8).saturating_mul(r.into())) @@ -3659,6 +3852,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3674,10 +3869,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `875` // Estimated: `9289` - // Minimum execution time: 265_413_000 picoseconds. - Weight::from_parts(265_600_840, 9289) + // Minimum execution time: 277_843_000 picoseconds. + Weight::from_parts(279_900_099, 9289) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_203, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_204, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3685,6 +3880,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3700,10 +3897,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1000 + n * (1 ±0)` // Estimated: `9412 + n * (1 ±0)` - // Minimum execution time: 328_341_000 picoseconds. - Weight::from_parts(341_038_581, 9412) - // Standard Error: 10 - .saturating_add(Weight::from_parts(5_863, 0).saturating_mul(n.into())) + // Minimum execution time: 331_840_000 picoseconds. + Weight::from_parts(338_767_191, 9412) + // Standard Error: 11 + .saturating_add(Weight::from_parts(5_971, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -3712,6 +3909,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3727,10 +3926,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `808 + r * (112 ±0)` // Estimated: `9226 + r * (112 ±0)` - // Minimum execution time: 272_730_000 picoseconds. - Weight::from_parts(339_349_232, 9226) - // Standard Error: 13_004 - .saturating_add(Weight::from_parts(41_649_026, 0).saturating_mul(r.into())) + // Minimum execution time: 277_912_000 picoseconds. + Weight::from_parts(344_538_960, 9226) + // Standard Error: 13_422 + .saturating_add(Weight::from_parts(41_592_887, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 112).saturating_mul(r.into())) @@ -3739,6 +3938,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3754,10 +3955,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `910 + r * (76 ±0)` // Estimated: `9279 + r * (77 ±0)` - // Minimum execution time: 273_892_000 picoseconds. - Weight::from_parts(352_853_960, 9279) - // Standard Error: 16_745 - .saturating_add(Weight::from_parts(45_853_294, 0).saturating_mul(r.into())) + // Minimum execution time: 280_383_000 picoseconds. + Weight::from_parts(348_542_377, 9279) + // Standard Error: 13_985 + .saturating_add(Weight::from_parts(45_983_827, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 77).saturating_mul(r.into())) @@ -3766,6 +3967,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3781,10 +3984,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `880 + r * (42 ±0)` // Estimated: `9294 + r * (42 ±0)` - // Minimum execution time: 268_431_000 picoseconds. - Weight::from_parts(319_727_796, 9294) - // Standard Error: 10_276 - .saturating_add(Weight::from_parts(11_928_882, 0).saturating_mul(r.into())) + // Minimum execution time: 277_764_000 picoseconds. + Weight::from_parts(320_288_180, 9294) + // Standard Error: 10_140 + .saturating_add(Weight::from_parts(12_046_137, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 42).saturating_mul(r.into())) @@ -3793,6 +3996,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1536 w:1536) @@ -3808,10 +4013,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + r * (965 ±0)` // Estimated: `9285 + r * (3090 ±7)` - // Minimum execution time: 275_482_000 picoseconds. - Weight::from_parts(279_155_000, 9285) - // Standard Error: 65_388 - .saturating_add(Weight::from_parts(26_634_187, 0).saturating_mul(r.into())) + // Minimum execution time: 271_356_000 picoseconds. + Weight::from_parts(282_924_000, 9285) + // Standard Error: 60_493 + .saturating_add(Weight::from_parts(28_319_267, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3822,6 +4027,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -3837,20 +4044,22 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `937 + r * (131 ±0)` // Estimated: `9346 + r * (2607 ±0)` - // Minimum execution time: 270_001_000 picoseconds. - Weight::from_parts(286_792_689, 9346) - // Standard Error: 21_074 - .saturating_add(Weight::from_parts(6_465_885, 0).saturating_mul(r.into())) + // Minimum execution time: 269_698_000 picoseconds. + Weight::from_parts(294_325_127, 9346) + // Standard Error: 22_352 + .saturating_add(Weight::from_parts(6_744_117, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(r.into()))) - .saturating_add(Weight::from_parts(0, 2606).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(0, 2607).saturating_mul(r.into())) } /// Storage: `Contracts::MigrationInProgress` (r:1 w:0) /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `MaxEncodedLen`) /// Storage: `Contracts::CodeInfoOf` (r:33 w:32) @@ -3864,12 +4073,12 @@ impl WeightInfo for () { /// The range of component `r` is `[0, 32]`. fn unlock_delegate_dependency(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `969 + r * (183 ±0)` + // Measured: `972 + r * (184 ±0)` // Estimated: `129453 + r * (2568 ±0)` - // Minimum execution time: 270_652_000 picoseconds. - Weight::from_parts(293_369_452, 129453) - // Standard Error: 24_321 - .saturating_add(Weight::from_parts(5_575_600, 0).saturating_mul(r.into())) + // Minimum execution time: 261_226_000 picoseconds. + Weight::from_parts(294_299_527, 129453) + // Standard Error: 27_898 + .saturating_add(Weight::from_parts(6_031_601, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(r.into()))) .saturating_add(RocksDbWeight::get().writes(3_u64)) @@ -3880,6 +4089,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3895,10 +4106,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `861 + r * (3 ±0)` // Estimated: `9282 + r * (3 ±0)` - // Minimum execution time: 267_749_000 picoseconds. - Weight::from_parts(280_373_341, 9282) - // Standard Error: 464 - .saturating_add(Weight::from_parts(170_398, 0).saturating_mul(r.into())) + // Minimum execution time: 270_729_000 picoseconds. + Weight::from_parts(289_622_807, 9282) + // Standard Error: 394 + .saturating_add(Weight::from_parts(167_010, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -3907,6 +4118,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3922,10 +4135,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2112 + r * (39 ±0)` // Estimated: `10377 + r * (40 ±0)` - // Minimum execution time: 270_260_000 picoseconds. - Weight::from_parts(337_969_172, 10377) - // Standard Error: 1_557 - .saturating_add(Weight::from_parts(305_735, 0).saturating_mul(r.into())) + // Minimum execution time: 272_228_000 picoseconds. + Weight::from_parts(351_059_276, 10377) + // Standard Error: 1_761 + .saturating_add(Weight::from_parts(312_269, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) .saturating_add(Weight::from_parts(0, 40).saturating_mul(r.into())) @@ -3934,6 +4147,8 @@ impl WeightInfo for () { /// Proof: `Contracts::MigrationInProgress` (`max_values`: Some(1), `max_size`: Some(1026), added: 1521, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) + /// Storage: `Parameters::Parameters` (r:3 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `Measured`) /// Storage: `Contracts::ContractInfoOf` (r:1 w:1) /// Proof: `Contracts::ContractInfoOf` (`max_values`: None, `max_size`: Some(1795), added: 4270, mode: `Measured`) /// Storage: `Contracts::CodeInfoOf` (r:1 w:0) @@ -3951,10 +4166,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `864 + r * (3 ±0)` // Estimated: `9279 + r * (3 ±0)` - // Minimum execution time: 265_607_000 picoseconds. - Weight::from_parts(283_396_630, 9279) - // Standard Error: 449 - .saturating_add(Weight::from_parts(149_018, 0).saturating_mul(r.into())) + // Minimum execution time: 272_497_000 picoseconds. + Weight::from_parts(288_213_060, 9279) + // Standard Error: 469 + .saturating_add(Weight::from_parts(155_530, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(r.into())) @@ -3964,9 +4179,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_813_000 picoseconds. - Weight::from_parts(1_264_945, 0) - // Standard Error: 19 - .saturating_add(Weight::from_parts(15_098, 0).saturating_mul(r.into())) + // Minimum execution time: 1_990_000 picoseconds. + Weight::from_parts(1_778_221, 0) + // Standard Error: 26 + .saturating_add(Weight::from_parts(14_888, 0).saturating_mul(r.into())) } } -- GitLab From e58e854a328aeac9a8876476be21918c21707e64 Mon Sep 17 00:00:00 2001 From: Tsvetomir Dimitrov Date: Wed, 20 Mar 2024 08:55:58 +0200 Subject: [PATCH 147/188] Expose `ClaimQueue` via a runtime api and use it in `collation-generation` (#3580) The PR adds two things: 1. Runtime API exposing the whole claim queue 2. Consumes the API in `collation-generation` to fetch the next scheduled `ParaEntry` for an occupied core. Related to https://github.com/paritytech/polkadot-sdk/issues/1797 --- Cargo.lock | 1 + .../src/blockchain_rpc_client.rs | 13 +- .../src/rpc_client.rs | 17 +- polkadot/node/collation-generation/Cargo.toml | 1 + polkadot/node/collation-generation/src/lib.rs | 74 +++- .../node/collation-generation/src/tests.rs | 329 +++++++++++++++++- polkadot/node/core/runtime-api/src/cache.rs | 29 +- polkadot/node/core/runtime-api/src/lib.rs | 11 + polkadot/node/core/runtime-api/src/tests.rs | 18 +- polkadot/node/subsystem-types/src/messages.rs | 10 +- .../subsystem-types/src/runtime_client.rs | 22 +- polkadot/node/subsystem-util/src/lib.rs | 8 +- polkadot/primitives/src/runtime_api.rs | 17 +- .../src/runtime_api_impl/vstaging.rs | 21 +- prdoc/pr_3580.prdoc | 13 + 15 files changed, 532 insertions(+), 52 deletions(-) create mode 100644 prdoc/pr_3580.prdoc diff --git a/Cargo.lock b/Cargo.lock index 5c0066e9728..ee813b60218 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12396,6 +12396,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-primitives", "polkadot-primitives-test-helpers", + "rstest", "sp-core", "sp-keyring", "sp-maybe-compressed-blob", diff --git a/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs b/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs index ab56b62c4ca..8d8a2920b4e 100644 --- a/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs +++ b/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs @@ -14,7 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use std::pin::Pin; +use std::{ + collections::{BTreeMap, VecDeque}, + pin::Pin, +}; use cumulus_relay_chain_interface::{RelayChainError, RelayChainResult}; use cumulus_relay_chain_rpc_interface::RelayChainRpcClient; @@ -25,6 +28,7 @@ use polkadot_primitives::{ async_backing::{AsyncBackingParams, BackingState}, slashing, vstaging::{ApprovalVotingParams, NodeFeatures}, + CoreIndex, }; use sc_authority_discovery::{AuthorityDiscovery, Error as AuthorityDiscoveryError}; use sc_client_api::AuxStore; @@ -442,6 +446,13 @@ impl RuntimeApiSubsystemClient for BlockChainRpcClient { async fn node_features(&self, at: Hash) -> Result { Ok(self.rpc_client.parachain_host_node_features(at).await?) } + + async fn claim_queue( + &self, + at: Hash, + ) -> Result>, ApiError> { + Ok(self.rpc_client.parachain_host_claim_queue(at).await?) + } } #[async_trait::async_trait] diff --git a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs index 6578210a259..8cf5ccf0c70 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs @@ -24,6 +24,7 @@ use jsonrpsee::{ }; use serde::de::DeserializeOwned; use serde_json::Value as JsonValue; +use std::collections::VecDeque; use tokio::sync::mpsc::Sender as TokioSender; use parity_scale_codec::{Decode, Encode}; @@ -34,10 +35,10 @@ use cumulus_primitives_core::{ slashing, vstaging::{ApprovalVotingParams, NodeFeatures}, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, - CommittedCandidateReceipt, CoreState, DisputeState, ExecutorParams, GroupRotationInfo, - Hash as RelayHash, Header as RelayHeader, InboundHrmpMessage, OccupiedCoreAssumption, - PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode, - ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, + CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, ExecutorParams, + GroupRotationInfo, Hash as RelayHash, Header as RelayHeader, InboundHrmpMessage, + OccupiedCoreAssumption, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, + ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, }, InboundDownwardMessage, ParaId, PersistedValidationData, }; @@ -647,6 +648,14 @@ impl RelayChainRpcClient { .await } + pub async fn parachain_host_claim_queue( + &self, + at: RelayHash, + ) -> Result>, RelayChainError> { + self.call_remote_runtime_function("ParachainHost_claim_queue", at, None::<()>) + .await + } + pub async fn validation_code_hash( &self, at: RelayHash, diff --git a/polkadot/node/collation-generation/Cargo.toml b/polkadot/node/collation-generation/Cargo.toml index 8df0c2b1eda..f72af87c15e 100644 --- a/polkadot/node/collation-generation/Cargo.toml +++ b/polkadot/node/collation-generation/Cargo.toml @@ -26,4 +26,5 @@ parity-scale-codec = { version = "3.6.1", default-features = false, features = [ polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../primitives/test-helpers" } assert_matches = "1.4.0" +rstest = "0.18.2" sp-keyring = { path = "../../../substrate/primitives/keyring" } diff --git a/polkadot/node/collation-generation/src/lib.rs b/polkadot/node/collation-generation/src/lib.rs index a89351628a0..3b1a8f5ff23 100644 --- a/polkadot/node/collation-generation/src/lib.rs +++ b/polkadot/node/collation-generation/src/lib.rs @@ -38,21 +38,25 @@ use polkadot_node_primitives::{ SubmitCollationParams, }; use polkadot_node_subsystem::{ - messages::{CollationGenerationMessage, CollatorProtocolMessage}, + messages::{CollationGenerationMessage, CollatorProtocolMessage, RuntimeApiRequest}, overseer, ActiveLeavesUpdate, FromOrchestra, OverseerSignal, RuntimeApiError, SpawnedSubsystem, SubsystemContext, SubsystemError, SubsystemResult, }; use polkadot_node_subsystem_util::{ - request_async_backing_params, request_availability_cores, request_persisted_validation_data, - request_validation_code, request_validation_code_hash, request_validators, + has_required_runtime, request_async_backing_params, request_availability_cores, + request_claim_queue, request_persisted_validation_data, request_validation_code, + request_validation_code_hash, request_validators, }; use polkadot_primitives::{ collator_signature_payload, CandidateCommitments, CandidateDescriptor, CandidateReceipt, - CollatorPair, CoreState, Hash, Id as ParaId, OccupiedCoreAssumption, PersistedValidationData, - ValidationCodeHash, + CollatorPair, CoreIndex, CoreState, Hash, Id as ParaId, OccupiedCoreAssumption, + PersistedValidationData, ScheduledCore, ValidationCodeHash, }; use sp_core::crypto::Pair; -use std::sync::Arc; +use std::{ + collections::{BTreeMap, VecDeque}, + sync::Arc, +}; mod error; @@ -223,6 +227,7 @@ async fn handle_new_activations( let availability_cores = availability_cores??; let n_validators = validators??.len(); let async_backing_params = async_backing_params?.ok(); + let maybe_claim_queue = fetch_claim_queue(ctx.sender(), relay_parent).await?; for (core_idx, core) in availability_cores.into_iter().enumerate() { let _availability_core_timer = metrics.time_new_activations_availability_core(); @@ -239,10 +244,25 @@ async fn handle_new_activations( // TODO [now]: this assumes that next up == current. // in practice we should only set `OccupiedCoreAssumption::Included` // when the candidate occupying the core is also of the same para. - if let Some(scheduled) = occupied_core.next_up_on_available { - (scheduled, OccupiedCoreAssumption::Included) - } else { - continue + let res = match maybe_claim_queue { + Some(ref claim_queue) => { + // read what's in the claim queue for this core + fetch_next_scheduled_on_core( + claim_queue, + CoreIndex(core_idx as u32), + ) + }, + None => { + // Runtime doesn't support claim queue runtime api. Fallback to + // `next_up_on_available` + occupied_core.next_up_on_available + }, + } + .map(|scheduled| (scheduled, OccupiedCoreAssumption::Included)); + + match res { + Some(res) => res, + None => continue, } }, _ => { @@ -600,3 +620,37 @@ fn erasure_root( let chunks = polkadot_erasure_coding::obtain_chunks_v1(n_validators, &available_data)?; Ok(polkadot_erasure_coding::branches(&chunks).root()) } + +// Checks if the runtime supports `request_claim_queue` and executes it. Returns `Ok(None)` +// otherwise. Any [`RuntimeApiError`]s are bubbled up to the caller. +async fn fetch_claim_queue( + sender: &mut impl overseer::CollationGenerationSenderTrait, + relay_parent: Hash, +) -> crate::error::Result>>> { + if has_required_runtime( + sender, + relay_parent, + RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT, + ) + .await + { + let res = request_claim_queue(relay_parent, sender).await.await??; + Ok(Some(res)) + } else { + gum::trace!(target: LOG_TARGET, "Runtime doesn't support `request_claim_queue`"); + Ok(None) + } +} + +// Returns the next scheduled `ParaId` for a core in the claim queue, wrapped in `ScheduledCore`. +// This function is supposed to be used in `handle_new_activations` hence the return type. +fn fetch_next_scheduled_on_core( + claim_queue: &BTreeMap>, + core_idx: CoreIndex, +) -> Option { + claim_queue + .get(&core_idx)? + .front() + .cloned() + .map(|para_id| ScheduledCore { para_id, collator: None }) +} diff --git a/polkadot/node/collation-generation/src/tests.rs b/polkadot/node/collation-generation/src/tests.rs index eb0ede6ef6b..9b16980e6af 100644 --- a/polkadot/node/collation-generation/src/tests.rs +++ b/polkadot/node/collation-generation/src/tests.rs @@ -25,15 +25,18 @@ use polkadot_node_primitives::{BlockData, Collation, CollationResult, MaybeCompr use polkadot_node_subsystem::{ errors::RuntimeApiError, messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}, + ActivatedLeaf, }; use polkadot_node_subsystem_test_helpers::{subsystem_test_harness, TestSubsystemContextHandle}; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::{ - CollatorPair, HeadData, Id as ParaId, PersistedValidationData, ScheduledCore, ValidationCode, + AsyncBackingParams, CollatorPair, HeadData, Id as ParaId, Id, PersistedValidationData, + ScheduledCore, ValidationCode, }; +use rstest::rstest; use sp_keyring::sr25519::Keyring as Sr25519Keyring; use std::pin::Pin; -use test_helpers::{dummy_hash, dummy_head_data, dummy_validator}; +use test_helpers::{dummy_candidate_descriptor, dummy_hash, dummy_head_data, dummy_validator}; type VirtualOverseer = TestSubsystemContextHandle; @@ -132,8 +135,10 @@ fn scheduled_core_for>(para_id: Id) -> ScheduledCore { ScheduledCore { para_id: para_id.into(), collator: None } } -#[test] -fn requests_availability_per_relay_parent() { +#[rstest] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT - 1)] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] +fn requests_availability_per_relay_parent(#[case] runtime_version: u32) { let activated_hashes: Vec = vec![[1; 32].into(), [4; 32].into(), [9; 32].into(), [16; 32].into()]; @@ -159,6 +164,18 @@ fn requests_availability_per_relay_parent() { ))) => { tx.send(Err(RuntimeApiError::NotSupported { runtime_api_name: "doesnt_matter" })).unwrap(); }, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::Version(tx), + ))) => { + tx.send(Ok(runtime_version)).unwrap(); + }, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::ClaimQueue(tx), + ))) if runtime_version >= RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT => { + tx.send(Ok(BTreeMap::new())).unwrap(); + }, Some(msg) => panic!("didn't expect any other overseer requests given no availability cores; got {:?}", msg), } } @@ -184,8 +201,10 @@ fn requests_availability_per_relay_parent() { assert_eq!(requested_availability_cores, activated_hashes); } -#[test] -fn requests_validation_data_for_scheduled_matches() { +#[rstest] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT - 1)] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] +fn requests_validation_data_for_scheduled_matches(#[case] runtime_version: u32) { let activated_hashes: Vec = vec![ Hash::repeat_byte(1), Hash::repeat_byte(4), @@ -242,6 +261,18 @@ fn requests_validation_data_for_scheduled_matches() { })) .unwrap(); }, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::Version(tx), + ))) => { + tx.send(Ok(runtime_version)).unwrap(); + }, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::ClaimQueue(tx), + ))) if runtime_version >= RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT => { + tx.send(Ok(BTreeMap::new())).unwrap(); + }, Some(msg) => { panic!("didn't expect any other overseer requests; got {:?}", msg) }, @@ -271,8 +302,10 @@ fn requests_validation_data_for_scheduled_matches() { assert_eq!(requested_validation_data, vec![[4; 32].into()]); } -#[test] -fn sends_distribute_collation_message() { +#[rstest] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT - 1)] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] +fn sends_distribute_collation_message(#[case] runtime_version: u32) { let activated_hashes: Vec = vec![ Hash::repeat_byte(1), Hash::repeat_byte(4), @@ -339,6 +372,18 @@ fn sends_distribute_collation_message() { })) .unwrap(); }, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::Version(tx), + ))) => { + tx.send(Ok(runtime_version)).unwrap(); + }, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::ClaimQueue(tx), + ))) if runtime_version >= RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT => { + tx.send(Ok(BTreeMap::new())).unwrap(); + }, Some(msg @ AllMessages::CollatorProtocol(_)) => { inner_to_collator_protocol.lock().await.push(msg); }, @@ -423,8 +468,10 @@ fn sends_distribute_collation_message() { } } -#[test] -fn fallback_when_no_validation_code_hash_api() { +#[rstest] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT - 1)] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] +fn fallback_when_no_validation_code_hash_api(#[case] runtime_version: u32) { // This is a variant of the above test, but with the validation code hash API disabled. let activated_hashes: Vec = vec![ @@ -501,9 +548,22 @@ fn fallback_when_no_validation_code_hash_api() { })) .unwrap(); }, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::Version(tx), + ))) => { + tx.send(Ok(runtime_version)).unwrap(); + }, Some(msg @ AllMessages::CollatorProtocol(_)) => { inner_to_collator_protocol.lock().await.push(msg); }, + Some(AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _hash, + RuntimeApiRequest::ClaimQueue(tx), + ))) if runtime_version >= RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT => { + let res = BTreeMap::>::new(); + tx.send(Ok(res)).unwrap(); + }, Some(msg) => { panic!("didn't expect any other overseer requests; got {:?}", msg) }, @@ -635,3 +695,252 @@ fn submit_collation_leads_to_distribution() { virtual_overseer }); } + +// There is one core in `Occupied` state and async backing is enabled. On new head activation +// `CollationGeneration` should produce and distribute a new collation. +#[rstest] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT - 1)] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] +fn distribute_collation_for_occupied_core_with_async_backing_enabled(#[case] runtime_version: u32) { + let activated_hash: Hash = [1; 32].into(); + let para_id = ParaId::from(5); + + // One core, in occupied state. The data in `CoreState` and `ClaimQueue` should match. + let cores: Vec = vec![CoreState::Occupied(polkadot_primitives::OccupiedCore { + next_up_on_available: Some(ScheduledCore { para_id, collator: None }), + occupied_since: 1, + time_out_at: 10, + next_up_on_time_out: Some(ScheduledCore { para_id, collator: None }), + availability: Default::default(), // doesn't matter + group_responsible: polkadot_primitives::GroupIndex(0), + candidate_hash: Default::default(), + candidate_descriptor: dummy_candidate_descriptor(dummy_hash()), + })]; + let claim_queue = BTreeMap::from([(CoreIndex::from(0), VecDeque::from([para_id]))]); + + test_harness(|mut virtual_overseer| async move { + helpers::initialize_collator(&mut virtual_overseer, para_id).await; + helpers::activate_new_head(&mut virtual_overseer, activated_hash).await; + helpers::handle_runtime_calls_on_new_head_activation( + &mut virtual_overseer, + activated_hash, + AsyncBackingParams { max_candidate_depth: 1, allowed_ancestry_len: 1 }, + cores, + runtime_version, + claim_queue, + ) + .await; + helpers::handle_core_processing_for_a_leaf( + &mut virtual_overseer, + activated_hash, + para_id, + // `CoreState` is `Occupied` => `OccupiedCoreAssumption` is `Included` + OccupiedCoreAssumption::Included, + ) + .await; + + virtual_overseer + }); +} + +// There is one core in `Occupied` state and async backing is disabled. On new head activation +// no new collation should be generated. +#[rstest] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT - 1)] +#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] +fn no_collation_is_distributed_for_occupied_core_with_async_backing_disabled( + #[case] runtime_version: u32, +) { + let activated_hash: Hash = [1; 32].into(); + let para_id = ParaId::from(5); + + // One core, in occupied state. The data in `CoreState` and `ClaimQueue` should match. + let cores: Vec = vec![CoreState::Occupied(polkadot_primitives::OccupiedCore { + next_up_on_available: Some(ScheduledCore { para_id, collator: None }), + occupied_since: 1, + time_out_at: 10, + next_up_on_time_out: Some(ScheduledCore { para_id, collator: None }), + availability: Default::default(), // doesn't matter + group_responsible: polkadot_primitives::GroupIndex(0), + candidate_hash: Default::default(), + candidate_descriptor: dummy_candidate_descriptor(dummy_hash()), + })]; + let claim_queue = BTreeMap::from([(CoreIndex::from(0), VecDeque::from([para_id]))]); + + test_harness(|mut virtual_overseer| async move { + helpers::initialize_collator(&mut virtual_overseer, para_id).await; + helpers::activate_new_head(&mut virtual_overseer, activated_hash).await; + helpers::handle_runtime_calls_on_new_head_activation( + &mut virtual_overseer, + activated_hash, + AsyncBackingParams { max_candidate_depth: 0, allowed_ancestry_len: 0 }, + cores, + runtime_version, + claim_queue, + ) + .await; + + virtual_overseer + }); +} + +mod helpers { + use super::*; + + // Sends `Initialize` with a collator config + pub async fn initialize_collator(virtual_overseer: &mut VirtualOverseer, para_id: ParaId) { + virtual_overseer + .send(FromOrchestra::Communication { + msg: CollationGenerationMessage::Initialize(test_config(para_id)), + }) + .await; + } + + // Sends `ActiveLeaves` for a single leaf with the specified hash. Block number is hardcoded. + pub async fn activate_new_head(virtual_overseer: &mut VirtualOverseer, activated_hash: Hash) { + virtual_overseer + .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { + activated: Some(ActivatedLeaf { + hash: activated_hash, + number: 10, + unpin_handle: polkadot_node_subsystem_test_helpers::mock::dummy_unpin_handle( + activated_hash, + ), + span: Arc::new(overseer::jaeger::Span::Disabled), + }), + ..Default::default() + }))) + .await; + } + + // Handle all runtime calls performed in `handle_new_activations`. Conditionally expects a + // `CLAIM_QUEUE_RUNTIME_REQUIREMENT` call if the passed `runtime_version` is greater or equal to + // `CLAIM_QUEUE_RUNTIME_REQUIREMENT` + pub async fn handle_runtime_calls_on_new_head_activation( + virtual_overseer: &mut VirtualOverseer, + activated_hash: Hash, + async_backing_params: AsyncBackingParams, + cores: Vec, + runtime_version: u32, + claim_queue: BTreeMap>, + ) { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(hash, RuntimeApiRequest::AvailabilityCores(tx))) => { + assert_eq!(hash, activated_hash); + let _ = tx.send(Ok(cores)); + } + ); + + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(hash, RuntimeApiRequest::Validators(tx))) => { + assert_eq!(hash, activated_hash); + let _ = tx.send(Ok(vec![ + Sr25519Keyring::Alice.public().into(), + Sr25519Keyring::Bob.public().into(), + Sr25519Keyring::Charlie.public().into(), + ])); + } + ); + + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + hash, + RuntimeApiRequest::AsyncBackingParams( + tx, + ), + )) => { + assert_eq!(hash, activated_hash); + let _ = tx.send(Ok(async_backing_params)); + } + ); + + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + hash, + RuntimeApiRequest::Version(tx), + )) => { + assert_eq!(hash, activated_hash); + let _ = tx.send(Ok(runtime_version)); + } + ); + + if runtime_version == RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + hash, + RuntimeApiRequest::ClaimQueue(tx), + )) => { + assert_eq!(hash, activated_hash); + let _ = tx.send(Ok(claim_queue)); + } + ); + } + } + + // Handles all runtime requests performed in `handle_new_activations` for the case when a + // collation should be prepared for the new leaf + pub async fn handle_core_processing_for_a_leaf( + virtual_overseer: &mut VirtualOverseer, + activated_hash: Hash, + para_id: ParaId, + expected_occupied_core_assumption: OccupiedCoreAssumption, + ) { + // Some hardcoded data - if needed, extract to parameters + let validation_code_hash = ValidationCodeHash::from(Hash::repeat_byte(42)); + let parent_head = HeadData::from(vec![1, 2, 3]); + let pvd = PersistedValidationData { + parent_head: parent_head.clone(), + relay_parent_number: 10, + relay_parent_storage_root: Hash::repeat_byte(1), + max_pov_size: 1024, + }; + + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(hash, RuntimeApiRequest::PersistedValidationData(id, a, tx))) => { + assert_eq!(hash, activated_hash); + assert_eq!(id, para_id); + assert_eq!(a, expected_occupied_core_assumption); + + let _ = tx.send(Ok(Some(pvd.clone()))); + } + ); + + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + hash, + RuntimeApiRequest::ValidationCodeHash( + id, + assumption, + tx, + ), + )) => { + assert_eq!(hash, activated_hash); + assert_eq!(id, para_id); + assert_eq!(assumption, expected_occupied_core_assumption); + + let _ = tx.send(Ok(Some(validation_code_hash))); + } + ); + + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::CollatorProtocol(CollatorProtocolMessage::DistributeCollation{ + candidate_receipt, + parent_head_data_hash, + .. + }) => { + assert_eq!(parent_head_data_hash, parent_head.hash()); + assert_eq!(candidate_receipt.descriptor().persisted_validation_data_hash, pvd.hash()); + assert_eq!(candidate_receipt.descriptor().para_head, dummy_head_data().hash()); + assert_eq!(candidate_receipt.descriptor().validation_code_hash, validation_code_hash); + } + ); + } +} diff --git a/polkadot/node/core/runtime-api/src/cache.rs b/polkadot/node/core/runtime-api/src/cache.rs index 5eca551db0a..9674cda9838 100644 --- a/polkadot/node/core/runtime-api/src/cache.rs +++ b/polkadot/node/core/runtime-api/src/cache.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::collections::btree_map::BTreeMap; +use std::collections::{btree_map::BTreeMap, VecDeque}; use schnellru::{ByLength, LruMap}; use sp_consensus_babe::Epoch; @@ -23,10 +23,11 @@ use polkadot_primitives::{ async_backing, slashing, vstaging::{self, ApprovalVotingParams}, AuthorityDiscoveryId, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, - CommittedCandidateReceipt, CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Hash, - Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, OccupiedCoreAssumption, - PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, - ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, + CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, ExecutorParams, + GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, + OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, + SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + ValidatorSignature, }; /// For consistency we have the same capacity for all caches. We use 128 as we'll only need that @@ -70,6 +71,7 @@ pub(crate) struct RequestResultCache { async_backing_params: LruMap, node_features: LruMap, approval_voting_params: LruMap, + claim_queue: LruMap>>, } impl Default for RequestResultCache { @@ -105,6 +107,7 @@ impl Default for RequestResultCache { para_backing_state: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), async_backing_params: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), node_features: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), + claim_queue: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), } } } @@ -525,6 +528,21 @@ impl RequestResultCache { ) { self.approval_voting_params.insert(session_index, value); } + + pub(crate) fn claim_queue( + &mut self, + relay_parent: &Hash, + ) -> Option<&BTreeMap>> { + self.claim_queue.get(relay_parent).map(|v| &*v) + } + + pub(crate) fn cache_claim_queue( + &mut self, + relay_parent: Hash, + value: BTreeMap>, + ) { + self.claim_queue.insert(relay_parent, value); + } } pub(crate) enum RequestResult { @@ -577,4 +595,5 @@ pub(crate) enum RequestResult { ParaBackingState(Hash, ParaId, Option), AsyncBackingParams(Hash, async_backing::AsyncBackingParams), NodeFeatures(SessionIndex, vstaging::NodeFeatures), + ClaimQueue(Hash, BTreeMap>), } diff --git a/polkadot/node/core/runtime-api/src/lib.rs b/polkadot/node/core/runtime-api/src/lib.rs index 3ff1a35d068..2b7f6fc2d60 100644 --- a/polkadot/node/core/runtime-api/src/lib.rs +++ b/polkadot/node/core/runtime-api/src/lib.rs @@ -177,6 +177,9 @@ where self.requests_cache.cache_async_backing_params(relay_parent, params), NodeFeatures(session_index, params) => self.requests_cache.cache_node_features(session_index, params), + ClaimQueue(relay_parent, sender) => { + self.requests_cache.cache_claim_queue(relay_parent, sender); + }, } } @@ -329,6 +332,8 @@ where Some(Request::NodeFeatures(index, sender)) } }, + Request::ClaimQueue(sender) => + query!(claim_queue(), sender).map(|sender| Request::ClaimQueue(sender)), } } @@ -626,5 +631,11 @@ where sender, result = (index) ), + Request::ClaimQueue(sender) => query!( + ClaimQueue, + claim_queue(), + ver = Request::CLAIM_QUEUE_RUNTIME_REQUIREMENT, + sender + ), } } diff --git a/polkadot/node/core/runtime-api/src/tests.rs b/polkadot/node/core/runtime-api/src/tests.rs index f91723b3d39..fefd2d3f862 100644 --- a/polkadot/node/core/runtime-api/src/tests.rs +++ b/polkadot/node/core/runtime-api/src/tests.rs @@ -23,15 +23,16 @@ use polkadot_primitives::{ async_backing, slashing, vstaging::{ApprovalVotingParams, NodeFeatures}, AuthorityDiscoveryId, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, - CommittedCandidateReceipt, CoreState, DisputeState, ExecutorParams, GroupRotationInfo, - Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, OccupiedCoreAssumption, - PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, - Slot, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, + CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, ExecutorParams, + GroupRotationInfo, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, + OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, + SessionIndex, SessionInfo, Slot, ValidationCode, ValidationCodeHash, ValidatorId, + ValidatorIndex, ValidatorSignature, }; use sp_api::ApiError; use sp_core::testing::TaskExecutor; use std::{ - collections::{BTreeMap, HashMap}, + collections::{BTreeMap, HashMap, VecDeque}, sync::{Arc, Mutex}, }; use test_helpers::{dummy_committed_candidate_receipt, dummy_validation_code}; @@ -286,6 +287,13 @@ impl RuntimeApiSubsystemClient for MockSubsystemClient { async fn disabled_validators(&self, _: Hash) -> Result, ApiError> { todo!("Not required for tests") } + + async fn claim_queue( + &self, + _: Hash, + ) -> Result>, ApiError> { + todo!("Not required for tests") + } } #[test] diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 23773f7e325..5115efa853c 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -45,7 +45,7 @@ use polkadot_primitives::{ async_backing, slashing, vstaging::{ApprovalVotingParams, NodeFeatures}, AuthorityDiscoveryId, BackedCandidate, BlockNumber, CandidateEvent, CandidateHash, - CandidateIndex, CandidateReceipt, CollatorId, CommittedCandidateReceipt, CoreState, + CandidateIndex, CandidateReceipt, CollatorId, CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, HeadData, Header as BlockHeader, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, MultiDisputeStatementSet, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, @@ -55,7 +55,7 @@ use polkadot_primitives::{ }; use polkadot_statement_table::v2::Misbehavior; use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{BTreeMap, HashMap, HashSet, VecDeque}, sync::Arc, }; @@ -729,6 +729,9 @@ pub enum RuntimeApiRequest { /// Approval voting params /// `V10` ApprovalVotingParams(SessionIndex, RuntimeApiSender), + /// Fetch the `ClaimQueue` from scheduler pallet + /// `V11` + ClaimQueue(RuntimeApiSender>>), } impl RuntimeApiRequest { @@ -763,6 +766,9 @@ impl RuntimeApiRequest { /// `approval_voting_params` pub const APPROVAL_VOTING_PARAMS_REQUIREMENT: u32 = 10; + + /// `ClaimQueue` + pub const CLAIM_QUEUE_RUNTIME_REQUIREMENT: u32 = 11; } /// A message to the Runtime API subsystem. diff --git a/polkadot/node/subsystem-types/src/runtime_client.rs b/polkadot/node/subsystem-types/src/runtime_client.rs index 4039fc9127d..7474b4120cc 100644 --- a/polkadot/node/subsystem-types/src/runtime_client.rs +++ b/polkadot/node/subsystem-types/src/runtime_client.rs @@ -21,10 +21,11 @@ use polkadot_primitives::{ slashing, vstaging::{self, ApprovalVotingParams}, Block, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, - CommittedCandidateReceipt, CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Hash, - Header, Id, InboundDownwardMessage, InboundHrmpMessage, OccupiedCoreAssumption, - PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo, - ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, + CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, ExecutorParams, + GroupRotationInfo, Hash, Header, Id, InboundDownwardMessage, InboundHrmpMessage, + OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, + SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + ValidatorSignature, }; use sc_client_api::{AuxStore, HeaderBackend}; use sc_transaction_pool_api::OffchainTransactionPoolFactory; @@ -33,7 +34,10 @@ use sp_authority_discovery::AuthorityDiscoveryApi; use sp_blockchain::{BlockStatus, Info}; use sp_consensus_babe::{BabeApi, Epoch}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use std::{collections::BTreeMap, sync::Arc}; +use std::{ + collections::{BTreeMap, VecDeque}, + sync::Arc, +}; /// Offers header utilities. /// @@ -329,6 +333,10 @@ pub trait RuntimeApiSubsystemClient { at: Hash, session_index: SessionIndex, ) -> Result; + + // == v11: Claim queue == + /// Fetch the `ClaimQueue` from scheduler pallet + async fn claim_queue(&self, at: Hash) -> Result>, ApiError>; } /// Default implementation of [`RuntimeApiSubsystemClient`] using the client. @@ -594,6 +602,10 @@ where ) -> Result { self.client.runtime_api().approval_voting_params(at) } + + async fn claim_queue(&self, at: Hash) -> Result>, ApiError> { + self.client.runtime_api().claim_queue(at) + } } impl HeaderBackend for DefaultSubsystemClient diff --git a/polkadot/node/subsystem-util/src/lib.rs b/polkadot/node/subsystem-util/src/lib.rs index f13beb3502f..aaae30db50c 100644 --- a/polkadot/node/subsystem-util/src/lib.rs +++ b/polkadot/node/subsystem-util/src/lib.rs @@ -30,7 +30,7 @@ use polkadot_node_subsystem::{ messages::{RuntimeApiMessage, RuntimeApiRequest, RuntimeApiSender}, overseer, SubsystemSender, }; -use polkadot_primitives::{slashing, ExecutorParams}; +use polkadot_primitives::{slashing, CoreIndex, ExecutorParams}; pub use overseer::{ gen::{OrchestraError as OverseerError, Timeout}, @@ -53,7 +53,10 @@ pub use rand; use sp_application_crypto::AppCrypto; use sp_core::ByteArray; use sp_keystore::{Error as KeystoreError, KeystorePtr}; -use std::time::Duration; +use std::{ + collections::{BTreeMap, VecDeque}, + time::Duration, +}; use thiserror::Error; use vstaging::get_disabled_validators_with_fallback; @@ -304,6 +307,7 @@ specialize_requests! { fn request_submit_report_dispute_lost(dp: slashing::DisputeProof, okop: slashing::OpaqueKeyOwnershipProof) -> Option<()>; SubmitReportDisputeLost; fn request_disabled_validators() -> Vec; DisabledValidators; fn request_async_backing_params() -> AsyncBackingParams; AsyncBackingParams; + fn request_claim_queue() -> BTreeMap>; ClaimQueue; } /// Requests executor parameters from the runtime effective at given relay-parent. First obtains diff --git a/polkadot/primitives/src/runtime_api.rs b/polkadot/primitives/src/runtime_api.rs index d661005e32f..6dca33f8823 100644 --- a/polkadot/primitives/src/runtime_api.rs +++ b/polkadot/primitives/src/runtime_api.rs @@ -117,14 +117,18 @@ use crate::{ async_backing, slashing, vstaging::{self, ApprovalVotingParams}, AsyncBackingParams, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, - CommittedCandidateReceipt, CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Hash, - OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, - SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, ValidatorSignature, + CommittedCandidateReceipt, CoreIndex, CoreState, DisputeState, ExecutorParams, + GroupRotationInfo, Hash, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement, + ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, + ValidatorSignature, }; use polkadot_core_primitives as pcp; use polkadot_parachain_primitives::primitives as ppp; -use sp_std::{collections::btree_map::BTreeMap, prelude::*}; +use sp_std::{ + collections::{btree_map::BTreeMap, vec_deque::VecDeque}, + prelude::*, +}; sp_api::decl_runtime_apis! { /// The API for querying the state of parachains on-chain. @@ -281,5 +285,10 @@ sp_api::decl_runtime_apis! { /// Approval voting configuration parameters #[api_version(10)] fn approval_voting_params() -> ApprovalVotingParams; + + /***** Added in v11 *****/ + /// Claim queue + #[api_version(11)] + fn claim_queue() -> BTreeMap>; } } diff --git a/polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs b/polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs index 1fee1a4097d..296b872e8d4 100644 --- a/polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs +++ b/polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs @@ -16,12 +16,15 @@ //! Put implementations of functions from staging APIs here. -use crate::{configuration, initializer, shared}; +use crate::{configuration, initializer, scheduler, shared}; use primitives::{ vstaging::{ApprovalVotingParams, NodeFeatures}, - ValidatorIndex, + CoreIndex, Id as ParaId, ValidatorIndex, +}; +use sp_std::{ + collections::{btree_map::BTreeMap, vec_deque::VecDeque}, + prelude::Vec, }; -use sp_std::prelude::Vec; /// Implementation for `DisabledValidators` // CAVEAT: this should only be called on the node side @@ -38,8 +41,18 @@ pub fn node_features() -> NodeFeatures { >::config().node_features } -/// Approval voting subsystem configuration parameteres +/// Approval voting subsystem configuration parameters pub fn approval_voting_params() -> ApprovalVotingParams { let config = >::config(); config.approval_voting_params } + +/// Returns the claimqueue from the scheduler +pub fn claim_queue() -> BTreeMap> { + >::claimqueue() + .into_iter() + .map(|(core_index, entries)| { + (core_index, entries.into_iter().map(|e| e.para_id()).collect()) + }) + .collect() +} diff --git a/prdoc/pr_3580.prdoc b/prdoc/pr_3580.prdoc new file mode 100644 index 00000000000..042fcf7a1a8 --- /dev/null +++ b/prdoc/pr_3580.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Expose `ClaimQueue` via a runtime api and consume it in `collation-generation` + +doc: + - audience: Node Dev + description: | + Creates a new runtime api exposing the `ClaimQueue` from `scheduler` pallet. Consume the api + in collation generation (if available) by getting what's scheduled on a core from the + `ClaimQueue` instead of from `next_up_on_available` (from `AvailabilityCores` runtime api). + +crates: [ ] -- GitLab From bb973aa0550e59b35e8b427cebaf676f433be83a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 07:03:41 +0000 Subject: [PATCH 148/188] Bump anyhow from 1.0.75 to 1.0.81 (#3752) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.75 to 1.0.81.
Release notes

Sourced from anyhow's releases.

1.0.81

  • Make backtrace support available when using -Dwarnings (#354)

1.0.80

  • Fix unused_imports warnings when compiled by rustc 1.78

1.0.79

  • Work around improperly cached build script result by sccache (#340)

1.0.78

  • Reduce spurious rebuilds under RustRover IDE when using a nightly toolchain (#337)

1.0.77

1.0.76

  • Opt in to unsafe_op_in_unsafe_fn lint (#329)
Commits
  • 4aad4ed Release 1.0.81
  • 8be9091 Merge pull request #354 from dtolnay/deadcode
  • a2eb7dd Make compatible with -Dwarnings
  • 5443719 Release 1.0.80
  • dfc7bc0 Work around prelude redundant import warnings
  • 6e4f86b Import from alloc not std, where possible
  • f885a13 Ignore incompatible_msrv clippy false positives in test
  • fefbcbc Ignore incompatible_msrv clippy lint
  • 78f2d81 Update ui test suite to nightly-2024-02-08
  • edd88d3 Update ui test suite to nightly-2024-01-31
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=anyhow&package-manager=cargo&previous-version=1.0.75&new-version=1.0.81)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- substrate/client/executor/wasmtime/Cargo.toml | 2 +- substrate/frame/contracts/fixtures/Cargo.toml | 4 ++-- substrate/primitives/wasm-interface/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee813b60218..b055c79cbbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -309,9 +309,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "approx" diff --git a/substrate/client/executor/wasmtime/Cargo.toml b/substrate/client/executor/wasmtime/Cargo.toml index 75cc76a2354..f3fef404691 100644 --- a/substrate/client/executor/wasmtime/Cargo.toml +++ b/substrate/client/executor/wasmtime/Cargo.toml @@ -30,7 +30,7 @@ wasmtime = { version = "8.0.1", default-features = false, features = [ "parallel-compilation", "pooling-allocator", ] } -anyhow = "1.0.68" +anyhow = "1.0.81" sc-allocator = { path = "../../allocator" } sc-executor-common = { path = "../common" } sp-runtime-interface = { path = "../../../primitives/runtime-interface" } diff --git a/substrate/frame/contracts/fixtures/Cargo.toml b/substrate/frame/contracts/fixtures/Cargo.toml index 5ac140cd91b..8c93c6f16f6 100644 --- a/substrate/frame/contracts/fixtures/Cargo.toml +++ b/substrate/frame/contracts/fixtures/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] frame-system = { path = "../../system" } sp-runtime = { path = "../../../primitives/runtime" } -anyhow = "1.0.0" +anyhow = "1.0.81" [build-dependencies] parity-wasm = "0.45.0" @@ -21,7 +21,7 @@ tempfile = "3.8.1" toml = "0.8.2" twox-hash = "1.6.3" polkavm-linker = { workspace = true, optional = true } -anyhow = "1.0.0" +anyhow = "1.0.81" [features] riscv = ["polkavm-linker"] diff --git a/substrate/primitives/wasm-interface/Cargo.toml b/substrate/primitives/wasm-interface/Cargo.toml index 6c051b71c8e..c05cc05ff06 100644 --- a/substrate/primitives/wasm-interface/Cargo.toml +++ b/substrate/primitives/wasm-interface/Cargo.toml @@ -21,7 +21,7 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features = impl-trait-for-tuples = "0.2.2" log = { optional = true, workspace = true, default-features = true } wasmtime = { version = "8.0.1", default-features = false, optional = true } -anyhow = { version = "1.0.68", optional = true } +anyhow = { version = "1.0.81", optional = true } [features] default = ["std"] -- GitLab From 7241a8db7b3496816503c6058dae67f66c666b00 Mon Sep 17 00:00:00 2001 From: slicejoke <163888128+slicejoke@users.noreply.github.com> Date: Wed, 20 Mar 2024 18:20:59 +0800 Subject: [PATCH 149/188] Fix typos (#3753) --- bridges/bin/runtime-common/src/priority_calculator.rs | 2 +- bridges/bin/runtime-common/src/refund_relayer_extension.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bridges/bin/runtime-common/src/priority_calculator.rs b/bridges/bin/runtime-common/src/priority_calculator.rs index a597fb9e2f4..c2737128e34 100644 --- a/bridges/bin/runtime-common/src/priority_calculator.rs +++ b/bridges/bin/runtime-common/src/priority_calculator.rs @@ -128,7 +128,7 @@ mod integrity_tests { Runtime::RuntimeCall: Dispatchable, BalanceOf: Send + Sync + FixedPointOperand, { - // esimate priority of transaction that delivers one message and has large tip + // estimate priority of transaction that delivers one message and has large tip let maximal_messages_in_delivery_transaction = Runtime::MaxUnconfirmedMessagesAtInboundLane::get(); let small_with_tip_priority = diff --git a/bridges/bin/runtime-common/src/refund_relayer_extension.rs b/bridges/bin/runtime-common/src/refund_relayer_extension.rs index bfcb82ad166..8e901d72821 100644 --- a/bridges/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bridges/bin/runtime-common/src/refund_relayer_extension.rs @@ -16,7 +16,7 @@ //! Signed extension that refunds relayer if he has delivered some new messages. //! It also refunds transaction cost if the transaction is an `utility.batchAll()` -//! with calls that are: delivering new messsage and all necessary underlying headers +//! with calls that are: delivering new message and all necessary underlying headers //! (parachain or relay chain). use crate::messages_call_ext::{ -- GitLab From b686bfefba9c9f18261d8cc0ff1afc055645d436 Mon Sep 17 00:00:00 2001 From: bader y Date: Wed, 20 Mar 2024 09:26:59 -0400 Subject: [PATCH 150/188] Defensive Programming in Substrate Reference Document (#2615) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _This PR is being continued from https://github.com/paritytech/polkadot-sdk/pull/2206, which was closed when the developer_hub was merged._ closes https://github.com/paritytech/polkadot-sdk-docs/issues/44 --- # Description This PR adds a reference document to the `developer-hub` crate (see https://github.com/paritytech/polkadot-sdk/pull/2102). This specific reference document covers defensive programming practices common within the context of developing a runtime with Substrate. In particular, this covers the following areas: - Default behavior of how Rust deals with numbers in general - How to deal with floating point numbers in runtime / fixed point arithmetic - How to deal with Integer overflows - General "safe math" / defensive programming practices for common pallet development scenarios - Defensive traits that exist within Substrate, i.e., `defensive_saturating_add `, `defensive_unwrap_or` - More general defensive programming examples (keep it concise) - Link to relevant examples where these practices are actually in production / being used - Unwrapping (or rather lack thereof) 101 todo -- - [x] Apply feedback from previous PR - [x] This may warrant a PR to append some of these docs to `sp_arithmetic` --------- Co-authored-by: Oliver Tale-Yazdi Co-authored-by: Gonçalo Pestana Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Francisco Aguirre Co-authored-by: Radha <86818441+DrW3RK@users.noreply.github.com> --- Cargo.lock | 6 + docs/sdk/Cargo.toml | 7 + docs/sdk/src/guides/your_first_pallet/mod.rs | 6 +- .../reference_docs/defensive_programming.rs | 395 ++++++++++++++++++ docs/sdk/src/reference_docs/mod.rs | 3 +- .../safe_defensive_programming.rs | 1 - substrate/primitives/arithmetic/Cargo.toml | 3 + .../primitives/arithmetic/src/fixed_point.rs | 27 ++ substrate/primitives/arithmetic/src/lib.rs | 138 ++++-- .../primitives/arithmetic/src/per_things.rs | 36 ++ 10 files changed, 588 insertions(+), 34 deletions(-) create mode 100644 docs/sdk/src/reference_docs/defensive_programming.rs delete mode 100644 docs/sdk/src/reference_docs/safe_defensive_programming.rs diff --git a/Cargo.lock b/Cargo.lock index b055c79cbbf..9e48887e17a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13376,7 +13376,9 @@ dependencies = [ "pallet-assets", "pallet-aura", "pallet-authorship", + "pallet-babe", "pallet-balances", + "pallet-broker", "pallet-collective", "pallet-default-config-example", "pallet-democracy", @@ -13385,6 +13387,7 @@ dependencies = [ "pallet-examples", "pallet-multisig", "pallet-proxy", + "pallet-referenda", "pallet-scheduler", "pallet-timestamp", "pallet-transaction-payment", @@ -13404,6 +13407,7 @@ dependencies = [ "scale-info", "simple-mermaid", "sp-api", + "sp-arithmetic", "sp-core", "sp-io", "sp-keyring", @@ -18395,6 +18399,7 @@ name = "sp-arithmetic" version = "23.0.0" dependencies = [ "criterion 0.4.0", + "docify 0.2.7", "integer-sqrt", "num-traits", "parity-scale-codec", @@ -18403,6 +18408,7 @@ dependencies = [ "scale-info", "serde", "sp-crypto-hashing", + "sp-std 14.0.0", "static_assertions", ] diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index 3f40a950c28..3f84d45640f 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -81,6 +81,13 @@ sp-api = { path = "../../substrate/primitives/api" } sp-core = { path = "../../substrate/primitives/core" } sp-keyring = { path = "../../substrate/primitives/keyring" } sp-runtime = { path = "../../substrate/primitives/runtime" } +sp-arithmetic = { path = "../../substrate/primitives/arithmetic" } + +# Misc pallet dependencies +pallet-referenda = { path = "../../substrate/frame/referenda" } +pallet-broker = { path = "../../substrate/frame/broker" } +pallet-babe = { path = "../../substrate/frame/babe" } + sp-offchain = { path = "../../substrate/primitives/offchain" } sp-version = { path = "../../substrate/primitives/version" } diff --git a/docs/sdk/src/guides/your_first_pallet/mod.rs b/docs/sdk/src/guides/your_first_pallet/mod.rs index c633c0a69ed..c6e0dd0edf8 100644 --- a/docs/sdk/src/guides/your_first_pallet/mod.rs +++ b/docs/sdk/src/guides/your_first_pallet/mod.rs @@ -105,8 +105,8 @@ //! This macro will call `.into()` under the hood. #![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", transfer_better)] //! -//! Moreover, you will learn in the [Safe Defensive Programming -//! section](crate::reference_docs::safe_defensive_programming) that it is always recommended to use +//! Moreover, you will learn in the [Defensive Programming +//! section](crate::reference_docs::defensive_programming) that it is always recommended to use //! safe arithmetic operations in your runtime. By using [`frame::traits::CheckedSub`], we can not //! only take a step in that direction, but also improve the error handing and make it slightly more //! ergonomic. @@ -294,7 +294,7 @@ //! The following topics where used in this guide, but not covered in depth. It is suggested to //! study them subsequently: //! -//! - [`crate::reference_docs::safe_defensive_programming`]. +//! - [`crate::reference_docs::defensive_programming`]. //! - [`crate::reference_docs::frame_origin`]. //! - [`crate::reference_docs::frame_runtime_types`]. //! - The pallet we wrote in this guide was using `dev_mode`, learn more in diff --git a/docs/sdk/src/reference_docs/defensive_programming.rs b/docs/sdk/src/reference_docs/defensive_programming.rs new file mode 100644 index 00000000000..9828e1b5091 --- /dev/null +++ b/docs/sdk/src/reference_docs/defensive_programming.rs @@ -0,0 +1,395 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// 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. + +//! [Defensive programming](https://en.wikipedia.org/wiki/Defensive_programming) is a design paradigm that enables a program to continue +//! running despite unexpected behavior, input, or events that may arise in runtime. +//! Usually, unforeseen circumstances may cause the program to stop or, in the Rust context, +//! panic!. Defensive practices allow for these circumstances to be accounted for ahead of time +//! and for them to be handled gracefully, which is in line with the intended fault-tolerant and +//! deterministic nature of blockchains. +//! +//! The Polkadot SDK is built to reflect these principles and to facilitate their usage accordingly. +//! +//! ## General Overview +//! +//! When developing within the context of the Substrate runtime, there is one golden rule: +//! +//! ***DO NOT PANIC***. There are some exceptions, but generally, this is the default precedent. +//! +//! > It’s important to differentiate between the runtime and node. The runtime refers to the core +//! > business logic of a Substrate-based chain, whereas the node refers to the outer client, which +//! > deals with telemetry and gossip from other nodes. For more information, read about +//! > [Substrate's node +//! > architecture](crate::reference_docs::wasm_meta_protocol#node-vs-runtime). It’s also important +//! > to note that the criticality of the node is slightly lesser +//! > than that of the runtime, which is why you may see `unwrap()` or other “non-defensive” +//! > approaches +//! in a few places of the node's code repository. +//! +//! Most of these practices fall within Rust's +//! colloquial usage of proper error propagation, handling, and arithmetic-based edge cases. +//! +//! General guidelines: +//! +//! - **Avoid writing functions that could explicitly panic,** such as directly using `unwrap()` on +//! a [`Result`], or accessing an out-of-bounds index on a collection. Safer methods to access +//! collection types, i.e., `get()` which allow defensive handling of the resulting [`Option`] are +//! recommended to be used. +//! - **It may be acceptable to use `except()`,** but only if one is completely certain (and has +//! performed a check beforehand) that a value won't panic upon unwrapping. *Even this is +//! discouraged*, however, as future changes to that function could then cause that statement to +//! panic. It is important to ensure all possible errors are propagated and handled effectively. +//! - **If a function *can* panic,** it usually is prefaced with `unchecked_` to indicate its +//! unsafety. +//! - **If you are writing a function that could panic,** [document it!](https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html#documenting-components) +//! - **Carefully handle mathematical operations.** Many seemingly, simplistic operations, such as +//! **arithmetic** in the runtime, could present a number of issues [(see more later in this +//! document)](#integer-overflow). Use checked arithmetic wherever possible. +//! +//! These guidelines could be summarized in the following example, where `bad_pop` is prone to +//! panicking, and `good_pop` allows for proper error handling to take place: +//! +//!```ignore +//! // Bad pop always requires that we return something, even if vector/array is empty. +//! fn bad_pop(v: Vec) -> T {} +//! // Good pop allows us to return None from the Option if need be. +//! fn good_pop(v: Vec) -> Option {} +//! ``` +//! +//! ### Defensive Traits +//! +//! The [`Defensive`](frame::traits::Defensive) trait provides a number of functions, all of which +//! provide an alternative to 'vanilla' Rust functions, e.g.,: +//! +//! - [`defensive_unwrap_or()`](frame::traits::Defensive::defensive_unwrap_or) instead of +//! `unwrap_or()` +//! - [`defensive_ok_or()`](frame::traits::DefensiveOption::defensive_ok_or) instead of `ok_or()` +//! +//! Defensive methods use [`debug_assertions`](https://doc.rust-lang.org/reference/conditional-compilation.html#debug_assertions), which panic in development, but in +//! production/release, they will merely log an error (i.e., `log::error`). +//! +//! The [`Defensive`](frame::traits::Defensive) trait and its various implementations can be found +//! [here](frame::traits::Defensive). +//! +//! ## Integer Overflow +//! +//! The Rust compiler prevents static overflow from happening at compile time. +//! The compiler panics in **debug** mode in the event of an integer overflow. In +//! **release** mode, it resorts to silently _wrapping_ the overflowed amount in a modular fashion +//! (from the `MAX` back to zero). +//! +//! In runtime development, we don't always have control over what is being supplied +//! as a parameter. For example, even this simple add function could present one of two outcomes +//! depending on whether it is in **release** or **debug** mode: +//! +//! ```ignore +//! fn naive_add(x: u8, y: u8) -> u8 { +//! x + y +//! } +//! ``` +//! If we passed overflow-able values at runtime, this could panic (or wrap if in release). +//! +//! ```ignore +//! naive_add(250u8, 10u8); // In debug mode, this would panic. In release, this would return 4. +//! ``` +//! +//! It is the silent portion of this behavior that presents a real issue. Such behavior should be +//! made obvious, especially in blockchain development, where unsafe arithmetic could produce +//! unexpected consequences like a user balance over or underflowing. +//! +//! Fortunately, there are ways to both represent and handle these scenarios depending on our +//! specific use case natively built into Rust and libraries like [`sp_arithmetic`]. +//! +//! ## Infallible Arithmetic +//! +//! Both Rust and Substrate provide safe ways to deal with numbers and alternatives to floating +//! point arithmetic. +//! +//! Known scenarios that could be fallible should be avoided: i.e., avoiding the possibility of +//! dividing/modulo by zero at any point should be mitigated. One should be opting for a +//! `checked_*` method to introduce safe arithmetic in their code in most cases. +//! +//! A developer should use fixed-point instead of floating-point arithmetic to mitigate the +//! potential for inaccuracy, rounding errors, or other unexpected behavior. +//! +//! - [Fixed point types](sp_arithmetic::fixed_point) and their associated usage can be found here. +//! - [PerThing](sp_arithmetic::per_things) and its associated types can be found here. +//! +//! Using floating point number types (i.e., f32. f64) in the runtime should be avoided, as a single non-deterministic result could cause chaos for blockchain consensus along with the issues above. For more on the specifics of the peculiarities of floating point calculations, [watch this video by the Computerphile](https://www.youtube.com/watch?v=PZRI1IfStY0). +//! +//! The following methods demonstrate different ways to handle numbers natively in Rust safely, +//! without fear of panic or unexpected behavior from wrapping. +//! +//! ### Checked Arithmetic +//! +//! **Checked operations** utilize an `Option` as a return type. This allows for +//! catching any unexpected behavior in the event of an overflow through simple pattern matching. +//! +//! This is an example of a valid operation: +#![doc = docify::embed!("./src/reference_docs/defensive_programming.rs", checked_add_example)] +//! +//! This is an example of an invalid operation. In this case, a simulated integer overflow, which +//! would simply result in `None`: +#![doc = docify::embed!( + "./src/reference_docs/defensive_programming.rs", + checked_add_handle_error_example +)] +//! +//! Suppose you aren’t sure which operation to use for runtime math. In that case, checked +//! operations are the safest bet, presenting two predictable (and erroring) outcomes that can be +//! handled accordingly (Some and None). +//! +//! The following conventions can be seen within the Polkadot SDK, where it is +//! handled in two ways: +//! +//! - As an [`Option`], using the `if let` / `if` or `match` +//! - As a [`Result`], via `ok_or` (or similar conversion to [`Result`] from [`Option`]) +//! +//! #### Handling via Option - More Verbose +//! +//! Because wrapped operations return `Option`, you can use a more verbose/explicit form of error +//! handling via `if` or `if let`: +#![doc = docify::embed!("./src/reference_docs/defensive_programming.rs", increase_balance)] +//! +//! Optionally, match may also be directly used in a more concise manner: +#![doc = docify::embed!("./src/reference_docs/defensive_programming.rs", increase_balance_match)] +//! +//! This is generally a useful convention for handling checked types and most types that return +//! `Option`. +//! +//! #### Handling via Result - Less Verbose +//! +//! In the Polkadot SDK codebase, checked operations are handled as a `Result` via `ok_or`. This is +//! a less verbose way of expressing the above. This usage often boils down to the developer’s +//! preference: +#![doc = docify::embed!("./src/reference_docs/defensive_programming.rs", increase_balance_result)] +//! +//! ### Saturating Operations +//! +//! Saturating a number limits it to the type’s upper or lower bound, even if the integer type +//! overflowed in runtime. For example, adding to `u32::MAX` would simply limit itself to +//! `u32::MAX`: +#![doc = docify::embed!("./src/reference_docs/defensive_programming.rs", saturated_add_example)] +//! +//! Saturating calculations can be used if one is very sure that something won't overflow, but wants +//! to avoid introducing the notion of any potential-panic or wrapping behavior. +//! +//! There is also a series of defensive alternatives via +//! [`DefensiveSaturating`](frame::traits::DefensiveSaturating), which introduces the same behavior +//! of the [`Defensive`](frame::traits::Defensive) trait, only with saturating, mathematical +//! operations: +#![doc = docify::embed!( + "./src/reference_docs/defensive_programming.rs", + saturated_defensive_example +)] +//! +//! ### Mathematical Operations in Substrate Development - Further Context +//! +//! As a recap, we covered the following concepts: +//! +//! 1. **Checked** operations - using [`Option`] or [`Result`] +//! 2. **Saturating** operations - limited to the lower and upper bounds of a number type +//! 3. **Wrapped** operations (the default) - wrap around to above or below the bounds of a type +//! +//! #### The problem with 'default' wrapped operations +//! +//! **Wrapped operations** cause the overflow to wrap around to either the maximum or minimum of +//! that type. Imagine this in the context of a blockchain, where there are account balances, voting +//! counters, nonces for transactions, and other aspects of a blockchain. +//! +//! While it may seem trivial, choosing how to handle numbers is quite important. As a thought +//! exercise, here are some scenarios of which will shed more light on when to use which. +//! +//! #### Bob's Overflowed Balance +//! +//! **Bob's** balance exceeds the `Balance` type on the `EduChain`. Because the pallet developer did +//! not handle the calculation to add to Bob's balance with any regard to this overflow, **Bob's** +//! balance is now essentially `0`, the operation **wrapped**. +//! +//!
+//! Solution: Saturating or Checked +//! For Bob's balance problems, using a `saturating_add` or `checked_add` could've mitigated +//! this issue. They simply would've reached the upper, or lower bounds, of the particular type for +//! an on-chain balance. In other words: Bob's balance would've stayed at the maximum of the +//! Balance type.
+//! +//! #### Alice's 'Underflowed' Balance +//! +//! Alice’s balance has reached `0` after a transfer to Bob. Suddenly, she has been slashed on +//! EduChain, causing her balance to reach near the limit of `u32::MAX` - a very large amount - as +//! wrapped operations can go both ways. Alice can now successfully vote using her new, overpowered +//! token balance, destroying the chain's integrity. +//! +//!
+//! Solution: Saturating +//! For Alice's balance problem, using `saturated_sub` could've mitigated this issue. A saturating +//! calculation would've simply limited her balance to the lower bound of u32, as having a negative +//! balance is not a concept within blockchains. In other words: Alice's balance would've stayed +//! at "0", even after being slashed. +//! +//! This is also an example that while one system may work in isolation, shared interfaces, such +//! as the notion of balances, are often shared across multiple pallets - meaning these small +//! changes can make a big difference depending on the scenario.
+//! +//! #### Proposal ID Overwrite +//! +//! A `u8` parameter, called `proposals_count`, represents the type for counting the number of +//! proposals on-chain. Every time a new proposal is added to the system, this number increases. +//! With the proposal pallet's high usage, it has reached `u8::MAX`’s limit of 255, causing +//! `proposals_count` to go to 0. Unfortunately, this results in new proposals overwriting old ones, +//! effectively erasing any notion of past proposals! +//! +//!
+//! Solution: Checked +//! For the proposal IDs, proper handling via `checked` math would've been suitable, +//! Saturating could've been used - but it also would've 'failed' silently. Using `checked_add` to +//! ensure that the next proposal ID would've been valid would've been a viable way to let the user +//! know the state of their proposal: +//! +//! ```ignore +//! let next_proposal_id = current_count.checked_add(1).ok_or_else(|| Error::TooManyProposals)?; +//! ``` +//! +//!
+//! +//! From the above, we can clearly see the problematic nature of seemingly simple operations in the +//! runtime, and care should be given to ensure a defensive approach is taken. +//! +//! ### Edge cases of `panic!`-able instances in Substrate +//! +//! As you traverse through the codebase (particularly in `substrate/frame`, where the majority of +//! runtime code lives), you may notice that there (only a few!) occurrences where `panic!` is used +//! explicitly. This is used when the runtime should stall, rather than keep running, as that is +//! considered safer. Particularly when it comes to mission-critical components, such as block +//! authoring, consensus, or other protocol-level dependencies, going through with an action may +//! actually cause harm to the network, and thus stalling would be the better option. +//! +//! Take the example of the BABE pallet ([`pallet_babe`]), which doesn't allow for a validator to +//! participate if it is disabled (see: [`frame::traits::DisabledValidators`]): +//! +//! ```ignore +//! if T::DisabledValidators::is_disabled(authority_index) { +//! panic!( +//! "Validator with index {:?} is disabled and should not be attempting to author blocks.", +//! authority_index, +//! ); +//! } +//! ``` +//! +//! There are other examples in various pallets, mostly those crucial to the blockchain’s +//! functionality. Most of the time, you will not be writing pallets which operate at this level, +//! but these exceptions should be noted regardless. +//! +//! ## Other Resources +//! +//! - [PBA Book - FRAME Tips & Tricks](https://polkadot-blockchain-academy.github.io/pba-book/substrate/tips-tricks/page.html?highlight=perthing#substrate-and-frame-tips-and-tricks) +#![allow(dead_code)] +#[allow(unused_variables)] +mod fake_runtime_types { + // Note: The following types are purely for the purpose of example, and do not contain any + // *real* use case other than demonstrating various concepts. + pub enum RuntimeError { + Overflow, + UserDoesntExist, + } + + pub type Address = (); + + pub struct Runtime; + + impl Runtime { + fn get_balance(account: Address) -> Result { + Ok(0u64) + } + + fn set_balance(account: Address, new_balance: u64) {} + } + + #[docify::export] + fn increase_balance(account: Address, amount: u64) -> Result<(), RuntimeError> { + // Get a user's current balance + let balance = Runtime::get_balance(account)?; + // SAFELY increase the balance by some amount + if let Some(new_balance) = balance.checked_add(amount) { + Runtime::set_balance(account, new_balance); + Ok(()) + } else { + Err(RuntimeError::Overflow) + } + } + + #[docify::export] + fn increase_balance_match(account: Address, amount: u64) -> Result<(), RuntimeError> { + // Get a user's current balance + let balance = Runtime::get_balance(account)?; + // SAFELY increase the balance by some amount + let new_balance = match balance.checked_add(amount) { + Some(balance) => balance, + None => { + return Err(RuntimeError::Overflow); + }, + }; + Runtime::set_balance(account, new_balance); + Ok(()) + } + + #[docify::export] + fn increase_balance_result(account: Address, amount: u64) -> Result<(), RuntimeError> { + // Get a user's current balance + let balance = Runtime::get_balance(account)?; + // SAFELY increase the balance by some amount - this time, by using `ok_or` + let new_balance = balance.checked_add(amount).ok_or(RuntimeError::Overflow)?; + Runtime::set_balance(account, new_balance); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use frame::traits::DefensiveSaturating; + #[docify::export] + #[test] + fn checked_add_example() { + // This is valid, as 20 is perfectly within the bounds of u32. + let add = (10u32).checked_add(10); + assert_eq!(add, Some(20)) + } + + #[docify::export] + #[test] + fn checked_add_handle_error_example() { + // This is invalid - we are adding something to the max of u32::MAX, which would overflow. + // Luckily, checked_add just marks this as None! + let add = u32::MAX.checked_add(10); + assert_eq!(add, None) + } + + #[docify::export] + #[test] + fn saturated_add_example() { + // Saturating add simply saturates + // to the numeric bound of that type if it overflows. + let add = u32::MAX.saturating_add(10); + assert_eq!(add, u32::MAX) + } + + #[docify::export] + #[test] + #[cfg_attr(debug_assertions, should_panic(expected = "Defensive failure has been triggered!"))] + fn saturated_defensive_example() { + let saturated_defensive = u32::MAX.defensive_saturating_add(10); + assert_eq!(saturated_defensive, u32::MAX); + } +} diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index de0b012bb12..a0d8d05b449 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -47,8 +47,7 @@ pub mod signed_extensions; pub mod frame_origin; /// Learn about how to write safe and defensive code in your FRAME runtime. -// TODO: @CrackTheCode016 https://github.com/paritytech/polkadot-sdk-docs/issues/44 -pub mod safe_defensive_programming; +pub mod defensive_programming; /// Learn about composite enums and other runtime level types, such as "RuntimeEvent" and /// "RuntimeCall". diff --git a/docs/sdk/src/reference_docs/safe_defensive_programming.rs b/docs/sdk/src/reference_docs/safe_defensive_programming.rs deleted file mode 100644 index 9d0f028e570..00000000000 --- a/docs/sdk/src/reference_docs/safe_defensive_programming.rs +++ /dev/null @@ -1 +0,0 @@ -//! diff --git a/substrate/primitives/arithmetic/Cargo.toml b/substrate/primitives/arithmetic/Cargo.toml index 29c406b10b7..64c1025b585 100644 --- a/substrate/primitives/arithmetic/Cargo.toml +++ b/substrate/primitives/arithmetic/Cargo.toml @@ -26,6 +26,8 @@ num-traits = { version = "0.2.17", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], optional = true, workspace = true } static_assertions = "1.1.0" +sp-std = { path = "../std", default-features = false } +docify = "0.2.7" [dev-dependencies] criterion = "0.4.0" @@ -41,6 +43,7 @@ std = [ "scale-info/std", "serde/std", "sp-crypto-hashing/std", + "sp-std/std", ] # Serde support without relying on std features. serde = ["dep:serde", "scale-info/serde"] diff --git a/substrate/primitives/arithmetic/src/fixed_point.rs b/substrate/primitives/arithmetic/src/fixed_point.rs index 46c09df2186..736a900bde2 100644 --- a/substrate/primitives/arithmetic/src/fixed_point.rs +++ b/substrate/primitives/arithmetic/src/fixed_point.rs @@ -16,6 +16,33 @@ // limitations under the License. //! Decimal Fixed Point implementations for Substrate runtime. +//! Similar to types that implement [`PerThing`](crate::per_things), these are also +//! fixed-point types, however, they are able to represent larger fractions: +#![doc = docify::embed!("./src/lib.rs", fixed_u64)] +//! +//! ### Fixed Point Types in Practice +//! +//! If one needs to exceed the value of one (1), then +//! [`FixedU64`](FixedU64) (and its signed and `u128` counterparts) can be utilized. +//! Take for example this very rudimentary pricing mechanism, where we wish to calculate the demand +//! / supply to get a price for some on-chain compute: +#![doc = docify::embed!( + "./src/lib.rs", + fixed_u64_block_computation_example +)] +//! +//! For a much more comprehensive example, be sure to look at the source for broker (the "coretime") +//! pallet. +//! +//! #### Fixed Point Types in Practice +//! +//! Just as with [`PerThing`](PerThing), you can also perform regular mathematical +//! expressions: +#![doc = docify::embed!( + "./src/lib.rs", + fixed_u64_operation_example +)] +//! use crate::{ helpers_128bit::{multiply_by_rational_with_rounding, sqrt}, diff --git a/substrate/primitives/arithmetic/src/lib.rs b/substrate/primitives/arithmetic/src/lib.rs index 33992e15423..01c403a7c4a 100644 --- a/substrate/primitives/arithmetic/src/lib.rs +++ b/substrate/primitives/arithmetic/src/lib.rs @@ -101,7 +101,7 @@ where fn tcmp(&self, other: &T, threshold: T) -> Ordering { // early exit. if threshold.is_zero() { - return self.cmp(other) + return self.cmp(other); } let upper_bound = other.saturating_add(threshold); @@ -206,12 +206,12 @@ where // Nothing to do here. if count.is_zero() { - return Ok(Vec::::new()) + return Ok(Vec::::new()); } let diff = targeted_sum.max(sum) - targeted_sum.min(sum); if diff.is_zero() { - return Ok(input.to_vec()) + return Ok(input.to_vec()); } let needs_bump = targeted_sum > sum; @@ -254,7 +254,7 @@ where min_index += 1; min_index %= count; } - leftover -= One::one() + leftover -= One::one(); } } else { // must decrease the stakes a bit. decrement from the max element. index of maximum is now @@ -288,7 +288,7 @@ where if output_with_idx[max_index].1 <= threshold { max_index = max_index.checked_sub(1).unwrap_or(count - 1); } - leftover -= One::one() + leftover -= One::one(); } else { max_index = max_index.checked_sub(1).unwrap_or(count - 1); } @@ -300,7 +300,7 @@ where targeted_sum, "sum({:?}) != {:?}", output_with_idx, - targeted_sum, + targeted_sum ); // sort again based on the original index. @@ -356,7 +356,7 @@ mod normalize_tests { vec![ Perbill::from_parts(333333334), Perbill::from_parts(333333333), - Perbill::from_parts(333333333), + Perbill::from_parts(333333333) ] ); @@ -367,7 +367,7 @@ mod normalize_tests { vec![ Perbill::from_parts(316666668), Perbill::from_parts(383333332), - Perbill::from_parts(300000000), + Perbill::from_parts(300000000) ] ); } @@ -378,13 +378,13 @@ mod normalize_tests { // could have a situation where the sum cannot be calculated in the inner type. Calculating // using the upper type of the per_thing should assure this to be okay. assert_eq!( - vec![PerU16::from_percent(40), PerU16::from_percent(40), PerU16::from_percent(40),] + vec![PerU16::from_percent(40), PerU16::from_percent(40), PerU16::from_percent(40)] .normalize(PerU16::one()) .unwrap(), vec![ PerU16::from_parts(21845), // 33% PerU16::from_parts(21845), // 33% - PerU16::from_parts(21845), // 33% + PerU16::from_parts(21845) // 33% ] ); } @@ -428,6 +428,88 @@ mod normalize_tests { } } +#[cfg(test)] +mod per_and_fixed_examples { + use super::*; + + #[docify::export] + #[test] + fn percent_mult() { + let percent = Percent::from_rational(5u32, 100u32); // aka, 5% + let five_percent_of_100 = percent * 100u32; // 5% of 100 is 5. + assert_eq!(five_percent_of_100, 5) + } + #[docify::export] + #[test] + fn perbill_example() { + let p = Perbill::from_percent(80); + // 800000000 bil, or a representative of 0.800000000. + // Precision is in the billions place. + assert_eq!(p.deconstruct(), 800000000); + } + + #[docify::export] + #[test] + fn percent_example() { + let percent = Percent::from_rational(190u32, 400u32); + assert_eq!(percent.deconstruct(), 47); + } + + #[docify::export] + #[test] + fn fixed_u64_block_computation_example() { + // Calculate a very rudimentary on-chain price from supply / demand + // Supply: Cores available per block + // Demand: Cores being ordered per block + let price = FixedU64::from_rational(5u128, 10u128); + + // 0.5 DOT per core + assert_eq!(price, FixedU64::from_float(0.5)); + + // Now, the story has changed - lots of demand means we buy as many cores as there + // available. This also means that price goes up! For the sake of simplicity, we don't care + // about who gets a core - just about our very simple price model + + // Calculate a very rudimentary on-chain price from supply / demand + // Supply: Cores available per block + // Demand: Cores being ordered per block + let price = FixedU64::from_rational(19u128, 10u128); + + // 1.9 DOT per core + assert_eq!(price, FixedU64::from_float(1.9)); + } + + #[docify::export] + #[test] + fn fixed_u64() { + // The difference between this and perthings is perthings operates within the relam of [0, + // 1] In cases where we need > 1, we can used fixed types such as FixedU64 + + let rational_1 = FixedU64::from_rational(10, 5); //" 200%" aka 2. + let rational_2 = FixedU64::from_rational_with_rounding(5, 10, Rounding::Down); // "50%" aka 0.50... + + assert_eq!(rational_1, (2u64).into()); + assert_eq!(rational_2.into_perbill(), Perbill::from_float(0.5)); + } + + #[docify::export] + #[test] + fn fixed_u64_operation_example() { + let rational_1 = FixedU64::from_rational(10, 5); // "200%" aka 2. + let rational_2 = FixedU64::from_rational(8, 5); // "160%" aka 1.6. + + let addition = rational_1 + rational_2; + let multiplication = rational_1 * rational_2; + let division = rational_1 / rational_2; + let subtraction = rational_1 - rational_2; + + assert_eq!(addition, FixedU64::from_float(3.6)); + assert_eq!(multiplication, FixedU64::from_float(3.2)); + assert_eq!(division, FixedU64::from_float(1.25)); + assert_eq!(subtraction, FixedU64::from_float(0.4)); + } +} + #[cfg(test)] mod threshold_compare_tests { use super::*; @@ -440,15 +522,15 @@ mod threshold_compare_tests { let e = Perbill::from_percent(10).mul_ceil(b); // [115 - 11,5 (103,5), 115 + 11,5 (126,5)] is all equal - assert_eq!(103u32.tcmp(&b, e), Ordering::Equal); - assert_eq!(104u32.tcmp(&b, e), Ordering::Equal); - assert_eq!(115u32.tcmp(&b, e), Ordering::Equal); - assert_eq!(120u32.tcmp(&b, e), Ordering::Equal); - assert_eq!(126u32.tcmp(&b, e), Ordering::Equal); - assert_eq!(127u32.tcmp(&b, e), Ordering::Equal); - - assert_eq!(128u32.tcmp(&b, e), Ordering::Greater); - assert_eq!(102u32.tcmp(&b, e), Ordering::Less); + assert_eq!((103u32).tcmp(&b, e), Ordering::Equal); + assert_eq!((104u32).tcmp(&b, e), Ordering::Equal); + assert_eq!((115u32).tcmp(&b, e), Ordering::Equal); + assert_eq!((120u32).tcmp(&b, e), Ordering::Equal); + assert_eq!((126u32).tcmp(&b, e), Ordering::Equal); + assert_eq!((127u32).tcmp(&b, e), Ordering::Equal); + + assert_eq!((128u32).tcmp(&b, e), Ordering::Greater); + assert_eq!((102u32).tcmp(&b, e), Ordering::Less); } #[test] @@ -458,15 +540,15 @@ mod threshold_compare_tests { let e = Perbill::from_parts(100) * b; // [115 - 11,5 (103,5), 115 + 11,5 (126,5)] is all equal - assert_eq!(103u32.tcmp(&b, e), 103u32.cmp(&b)); - assert_eq!(104u32.tcmp(&b, e), 104u32.cmp(&b)); - assert_eq!(115u32.tcmp(&b, e), 115u32.cmp(&b)); - assert_eq!(120u32.tcmp(&b, e), 120u32.cmp(&b)); - assert_eq!(126u32.tcmp(&b, e), 126u32.cmp(&b)); - assert_eq!(127u32.tcmp(&b, e), 127u32.cmp(&b)); - - assert_eq!(128u32.tcmp(&b, e), 128u32.cmp(&b)); - assert_eq!(102u32.tcmp(&b, e), 102u32.cmp(&b)); + assert_eq!((103u32).tcmp(&b, e), (103u32).cmp(&b)); + assert_eq!((104u32).tcmp(&b, e), (104u32).cmp(&b)); + assert_eq!((115u32).tcmp(&b, e), (115u32).cmp(&b)); + assert_eq!((120u32).tcmp(&b, e), (120u32).cmp(&b)); + assert_eq!((126u32).tcmp(&b, e), (126u32).cmp(&b)); + assert_eq!((127u32).tcmp(&b, e), (127u32).cmp(&b)); + + assert_eq!((128u32).tcmp(&b, e), (128u32).cmp(&b)); + assert_eq!((102u32).tcmp(&b, e), (102u32).cmp(&b)); } #[test] diff --git a/substrate/primitives/arithmetic/src/per_things.rs b/substrate/primitives/arithmetic/src/per_things.rs index 057bfd7bf88..f73dbe30cec 100644 --- a/substrate/primitives/arithmetic/src/per_things.rs +++ b/substrate/primitives/arithmetic/src/per_things.rs @@ -15,6 +15,42 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Types that implement [`PerThing`](PerThing) can be used as a floating-point alternative for +//! numbers that operate within the realm of `[0, 1]`. The primary types may you encounter in +//! Substrate would be the following: +//! - [`Percent`](Percent) - parts of one hundred. +//! - [`Permill`](Permill) - parts of a million. +//! - [`Perbill`](Perbill) - parts of a billion. +//! +//! In use, you may see them being used as follows: +//! +//! > **[`Perbill`](Perbill), parts of a billion** +#![doc = docify::embed!("./src/lib.rs", perbill_example)] +//! > **[`Percent`](Percent), parts of a hundred** +#![doc = docify::embed!("./src/lib.rs", percent_example)] +//! +//! Note that `Percent` is represented as a _rounded down_, fixed point +//! number (see the example above). Unlike primitive types, types that implement +//! [`PerThing`](PerThing) will also not overflow, and are therefore safe to use. +//! They adopt the same behavior that a saturated calculation would provide, meaning that if one is +//! to go over "100%", it wouldn't overflow, but simply stop at the upper or lower bound. +//! +//! For use cases which require precision beyond the range of `[0, 1]`, there are fixed-point types +//! which can be used. +//! +//! Each of these can be used to construct and represent ratios within our runtime. +//! You will find types like [`Perbill`](Perbill) being used often in pallet +//! development. `pallet_referenda` is a good example of a pallet which makes good use of fixed +//! point arithmetic, as it relies on representing various curves and thresholds relating to +//! governance. +//! +//! #### Fixed Point Arithmetic with [`PerThing`](PerThing) +//! +//! As stated, one can also perform mathematics using these types directly. For example, finding the +//! percentage of a particular item: + +#![doc = docify::embed!("./src/lib.rs", percent_mult)] + #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -- GitLab From b74353d3e94ca685e953f5138f0676214140dcdd Mon Sep 17 00:00:00 2001 From: eskimor Date: Wed, 20 Mar 2024 14:53:55 +0100 Subject: [PATCH 151/188] Fix algorithmic complexity of on-demand scheduler with regards to number of cores. (#3190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We witnessed really poor performance on Rococo, where we ended up with 50 on-demand cores. This was due to the fact that for each core the full queue was processed. With this change full queue processing will happen way less often (most of the time complexity is O(1) or O(log(n))) and if it happens then only for one core (in expectation). Also spot price is now updated before each order to ensure economic back pressure. TODO: - [x] Implement - [x] Basic tests - [x] Add more tests (see todos) - [x] Run benchmark to confirm better performance, first results suggest > 100x faster. - [x] Write migrations - [x] Bump scale-info version and remove patch in Cargo.toml - [x] Write PR docs: on-demand performance improved, more on-demand cores are now non problematic anymore. If need by also the max queue size can be increased again. (Maybe not to 10k) Optional: Performance can be improved even more, if we called `pop_assignment_for_core()`, before calling `report_processed` (Avoid needless affinity drops). The effect gets smaller the larger the claim queue and I would only go for it, if it does not add complexity to the scheduler. --------- Co-authored-by: eskimor Co-authored-by: antonva Co-authored-by: command-bot <> Co-authored-by: Anton Vilhelm Ásgeirsson Co-authored-by: ordian --- Cargo.lock | 8 +- polkadot/primitives/src/lib.rs | 3 +- polkadot/primitives/src/v6/mod.rs | 7 + polkadot/runtime/parachains/Cargo.toml | 2 +- .../src/assigner_on_demand/benchmarking.rs | 11 +- .../src/assigner_on_demand/migration.rs | 181 +++++ .../parachains/src/assigner_on_demand/mod.rs | 690 ++++++++++++------ .../src/assigner_on_demand/tests.rs | 514 +++++++------ .../runtime/parachains/src/configuration.rs | 10 +- polkadot/runtime/rococo/src/lib.rs | 1 + .../runtime_parachains_assigner_on_demand.rs | 72 +- .../runtime_parachains_assigner_on_demand.rs | 76 +- prdoc/pr_3190.prdoc | 17 + 13 files changed, 1046 insertions(+), 546 deletions(-) create mode 100644 polkadot/runtime/parachains/src/assigner_on_demand/migration.rs create mode 100644 prdoc/pr_3190.prdoc diff --git a/Cargo.lock b/Cargo.lock index 9e48887e17a..5401dc5ecfb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17005,9 +17005,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "2ef2175c2907e7c8bc0a9c3f86aeb5ec1f3b275300ad58a44d0c3ae379a5e52e" dependencies = [ "bitvec", "cfg-if", @@ -17019,9 +17019,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "634d9b8eb8fd61c5cdd3390d9b2132300a7e7618955b98b8416f118c1b4e144f" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs index 2ddd9b58dfe..745195ce092 100644 --- a/polkadot/primitives/src/lib.rs +++ b/polkadot/primitives/src/lib.rs @@ -58,7 +58,8 @@ pub use v6::{ ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, ValidityAttestation, ValidityError, ASSIGNMENT_KEY_TYPE_ID, LEGACY_MIN_BACKING_VOTES, LOWEST_PUBLIC_ID, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, MIN_CODE_SIZE, - ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, PARACHAINS_INHERENT_IDENTIFIER, PARACHAIN_KEY_TYPE_ID, + ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, ON_DEMAND_MAX_QUEUE_MAX_SIZE, PARACHAINS_INHERENT_IDENTIFIER, + PARACHAIN_KEY_TYPE_ID, }; #[cfg(feature = "std")] diff --git a/polkadot/primitives/src/v6/mod.rs b/polkadot/primitives/src/v6/mod.rs index 742dbed1cd8..9e7f910314c 100644 --- a/polkadot/primitives/src/v6/mod.rs +++ b/polkadot/primitives/src/v6/mod.rs @@ -399,6 +399,13 @@ pub const MAX_POV_SIZE: u32 = 5 * 1024 * 1024; /// Can be adjusted in configuration. pub const ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE: u32 = 10_000; +/// Maximum for maximum queue size. +/// +/// Setting `on_demand_queue_max_size` to a value higher than this is unsound. This is more a +/// theoretical limit, just below enough what the target type supports, so comparisons are possible +/// even with indices that are overflowing the underyling type. +pub const ON_DEMAND_MAX_QUEUE_MAX_SIZE: u32 = 1_000_000_000; + /// Backing votes threshold used from the host prior to runtime API version 6 and from the runtime /// prior to v9 configuration migration. pub const LEGACY_MIN_BACKING_VOTES: u32 = 2; diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml index 61040145476..6e693b83ae1 100644 --- a/polkadot/runtime/parachains/Cargo.toml +++ b/polkadot/runtime/parachains/Cargo.toml @@ -15,7 +15,7 @@ bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] } log = { workspace = true } rustc-hex = { version = "2.1.0", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } derive_more = "0.99.17" bitflags = "1.3.2" diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/benchmarking.rs b/polkadot/runtime/parachains/src/assigner_on_demand/benchmarking.rs index 8360e7a78d0..779d6f04e39 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/benchmarking.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/benchmarking.rs @@ -70,11 +70,7 @@ mod benchmarks { let para_id = ParaId::from(111u32); init_parathread::(para_id); T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - let order = EnqueuedOrder::new(para_id); - - for _ in 0..s { - Pallet::::add_on_demand_order(order.clone(), QueuePushDirection::Back).unwrap(); - } + Pallet::::populate_queue(para_id, s); #[extrinsic_call] _(RawOrigin::Signed(caller.into()), BalanceOf::::max_value(), para_id) @@ -87,11 +83,8 @@ mod benchmarks { let para_id = ParaId::from(111u32); init_parathread::(para_id); T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - let order = EnqueuedOrder::new(para_id); - for _ in 0..s { - Pallet::::add_on_demand_order(order.clone(), QueuePushDirection::Back).unwrap(); - } + Pallet::::populate_queue(para_id, s); #[extrinsic_call] _(RawOrigin::Signed(caller.into()), BalanceOf::::max_value(), para_id) diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/migration.rs b/polkadot/runtime/parachains/src/assigner_on_demand/migration.rs new file mode 100644 index 00000000000..5071653377d --- /dev/null +++ b/polkadot/runtime/parachains/src/assigner_on_demand/migration.rs @@ -0,0 +1,181 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! A module that is responsible for migration of storage. +use super::*; +use frame_support::{ + migrations::VersionedMigration, pallet_prelude::ValueQuery, storage_alias, + traits::OnRuntimeUpgrade, weights::Weight, +}; + +mod v0 { + use super::*; + use sp_std::collections::vec_deque::VecDeque; + + #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone)] + pub(super) struct EnqueuedOrder { + pub para_id: ParaId, + } + + /// Keeps track of the multiplier used to calculate the current spot price for the on demand + /// assigner. + /// NOTE: Ignoring the `OnEmpty` field for the migration. + #[storage_alias] + pub(super) type SpotTraffic = StorageValue, FixedU128, ValueQuery>; + + /// The order storage entry. Uses a VecDeque to be able to push to the front of the + /// queue from the scheduler on session boundaries. + /// NOTE: Ignoring the `OnEmpty` field for the migration. + #[storage_alias] + pub(super) type OnDemandQueue = + StorageValue, VecDeque, ValueQuery>; +} + +mod v1 { + use super::*; + + use crate::assigner_on_demand::LOG_TARGET; + + /// Migration to V1 + pub struct UncheckedMigrateToV1(sp_std::marker::PhantomData); + impl OnRuntimeUpgrade for UncheckedMigrateToV1 { + fn on_runtime_upgrade() -> Weight { + let mut weight: Weight = Weight::zero(); + + // Migrate the current traffic value + let config = >::config(); + QueueStatus::::mutate(|mut queue_status| { + Pallet::::update_spot_traffic(&config, &mut queue_status); + + let v0_queue = v0::OnDemandQueue::::take(); + // Process the v0 queue into v1. + v0_queue.into_iter().for_each(|enqueued_order| { + // Readding the old orders will use the new systems. + Pallet::::add_on_demand_order( + queue_status, + enqueued_order.para_id, + QueuePushDirection::Back, + ); + }); + }); + + // Remove the old storage. + v0::OnDemandQueue::::kill(); // 1 write + v0::SpotTraffic::::kill(); // 1 write + + // Config read + weight.saturating_accrue(T::DbWeight::get().reads(1)); + // QueueStatus read write (update_spot_traffic) + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + // Kill x 2 + weight.saturating_accrue(T::DbWeight::get().writes(2)); + + log::info!(target: LOG_TARGET, "Migrated on demand assigner storage to v1"); + weight + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + let n: u32 = v0::OnDemandQueue::::get().len() as u32; + + log::info!( + target: LOG_TARGET, + "Number of orders waiting in the queue before: {n}", + ); + + Ok(n.encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + log::info!(target: LOG_TARGET, "Running post_upgrade()"); + + ensure!( + v0::OnDemandQueue::::get().is_empty(), + "OnDemandQueue should be empty after the migration" + ); + + let expected_len = u32::decode(&mut &state[..]).unwrap(); + let queue_status_size = QueueStatus::::get().size(); + ensure!( + expected_len == queue_status_size, + "Number of orders should be the same before and after migration" + ); + + let n_affinity_entries: u32 = + AffinityEntries::::iter().map(|(_index, heap)| heap.len() as u32).sum(); + let n_para_id_affinity: u32 = ParaIdAffinity::::iter() + .map(|(_para_id, affinity)| affinity.count as u32) + .sum(); + ensure!( + n_para_id_affinity == n_affinity_entries, + "Number of affinity entries should be the same as the counts in ParaIdAffinity" + ); + + Ok(()) + } + } +} + +/// Migrate `V0` to `V1` of the storage format. +pub type MigrateV0ToV1 = VersionedMigration< + 0, + 1, + v1::UncheckedMigrateToV1, + Pallet, + ::DbWeight, +>; + +#[cfg(test)] +mod tests { + use super::{v0, v1, OnRuntimeUpgrade, Weight}; + use crate::mock::{new_test_ext, MockGenesisConfig, OnDemandAssigner, Test}; + use primitives::Id as ParaId; + + #[test] + fn migration_to_v1_preserves_queue_ordering() { + new_test_ext(MockGenesisConfig::default()).execute_with(|| { + // Place orders for paraids 1..5 + for i in 1..=5 { + v0::OnDemandQueue::::mutate(|queue| { + queue.push_back(v0::EnqueuedOrder { para_id: ParaId::new(i) }) + }); + } + + // Queue has 5 orders + let old_queue = v0::OnDemandQueue::::get(); + assert_eq!(old_queue.len(), 5); + // New queue has 0 orders + assert_eq!(OnDemandAssigner::get_queue_status().size(), 0); + + // For tests, db weight is zero. + assert_eq!( + as OnRuntimeUpgrade>::on_runtime_upgrade(), + Weight::zero() + ); + + // New queue has 5 orders + assert_eq!(OnDemandAssigner::get_queue_status().size(), 5); + + // Compare each entry from the old queue with the entry in the new queue. + old_queue.iter().zip(OnDemandAssigner::get_free_entries().iter()).for_each( + |(old_enq, new_enq)| { + assert_eq!(old_enq.para_id, new_enq.para_id); + }, + ); + }); + } +} diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs index bc450dc7812..c47c8745e65 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs @@ -16,22 +16,32 @@ //! The parachain on demand assignment module. //! -//! Implements a mechanism for taking in orders for pay as you go (PAYG) or on demand -//! parachain (previously parathreads) assignments. This module is not handled by the -//! initializer but is instead instantiated in the `construct_runtime` macro. +//! Implements a mechanism for taking in orders for on-demand parachain (previously parathreads) +//! assignments. This module is not handled by the initializer but is instead instantiated in the +//! `construct_runtime` macro. //! //! The module currently limits parallel execution of blocks from the same `ParaId` via //! a core affinity mechanism. As long as there exists an affinity for a `CoreIndex` for //! a specific `ParaId`, orders for blockspace for that `ParaId` will only be assigned to -//! that `CoreIndex`. This affinity mechanism can be removed if it can be shown that parallel -//! execution is valid. +//! that `CoreIndex`. +//! +//! NOTE: Once we have elastic scaling implemented we might want to extend this module to support +//! ignoring core affinity up to a certain extend. This should be opt-in though as the parachain +//! needs to support multiple cores in the same block. If we want to enable a single parachain +//! occupying multiple cores in on-demand, we will likely add a separate order type, where the +//! intent can be made explicit. mod benchmarking; +pub mod migration; mod mock_helpers; +extern crate alloc; + #[cfg(test)] mod tests; +use core::mem::take; + use crate::{configuration, paras, scheduler::common::Assignment}; use frame_support::{ @@ -43,13 +53,17 @@ use frame_support::{ }, }; use frame_system::pallet_prelude::*; -use primitives::{CoreIndex, Id as ParaId}; +use primitives::{CoreIndex, Id as ParaId, ON_DEMAND_MAX_QUEUE_MAX_SIZE}; use sp_runtime::{ traits::{One, SaturatedConversion}, FixedPointNumber, FixedPointOperand, FixedU128, Perbill, Saturating, }; -use sp_std::{collections::vec_deque::VecDeque, prelude::*}; +use alloc::collections::BinaryHeap; +use sp_std::{ + cmp::{Ord, Ordering, PartialOrd}, + prelude::*, +}; const LOG_TARGET: &str = "runtime::parachains::assigner-on-demand"; @@ -73,17 +87,116 @@ impl WeightInfo for TestWeightInfo { } } +/// Meta data for full queue. +/// +/// This includes elements with affinity and free entries. +/// +/// The actual queue is implemented via multiple priority queues. One for each core, for entries +/// which currently have a core affinity and one free queue, with entries without any affinity yet. +/// +/// The design aims to have most queue accessess be O(1) or O(log(N)). Absolute worst case is O(N). +/// Importantly this includes all accessess that happen in a single block. Even with 50 cores, the +/// total complexity of all operations in the block should maintain above complexities. In +/// particular O(N) stays O(N), it should never be O(N*cores). +/// +/// More concrete rundown on complexity: +/// +/// - insert: O(1) for placing an order, O(log(N)) for push backs. +/// - pop_assignment_for_core: O(log(N)), O(N) worst case: Can only happen for one core, next core +/// is already less work. +/// - report_processed & push back: If affinity dropped to 0, then O(N) in the worst case. Again +/// this divides per core. +/// +/// Reads still exist, also improved slightly, but worst case we fetch all entries. +#[derive(Encode, Decode, TypeInfo)] +struct QueueStatusType { + /// Last calculated traffic value. + traffic: FixedU128, + /// The next index to use. + next_index: QueueIndex, + /// Smallest index still in use. + /// + /// In case of a completely empty queue (free + affinity queues), `next_index - smallest_index + /// == 0`. + smallest_index: QueueIndex, + /// Indices that have been freed already. + /// + /// But have a hole to `smallest_index`, so we can not yet bump `smallest_index`. This binary + /// heap is roughly bounded in the number of on demand cores: + /// + /// For a single core, elements will always be processed in order. With each core added, a + /// level of out of order execution is added. + freed_indices: BinaryHeap, +} + +impl Default for QueueStatusType { + fn default() -> QueueStatusType { + QueueStatusType { + traffic: FixedU128::default(), + next_index: QueueIndex(0), + smallest_index: QueueIndex(0), + freed_indices: BinaryHeap::new(), + } + } +} + +impl QueueStatusType { + /// How many orders are queued in total? + /// + /// This includes entries which have core affinity. + fn size(&self) -> u32 { + self.next_index + .0 + .overflowing_sub(self.smallest_index.0) + .0 + .saturating_sub(self.freed_indices.len() as u32) + } + + /// Get current next index + /// + /// to use for an element newly pushed to the back of the queue. + fn push_back(&mut self) -> QueueIndex { + let QueueIndex(next_index) = self.next_index; + self.next_index = QueueIndex(next_index.overflowing_add(1).0); + QueueIndex(next_index) + } + + /// Push something to the front of the queue + fn push_front(&mut self) -> QueueIndex { + self.smallest_index = QueueIndex(self.smallest_index.0.overflowing_sub(1).0); + self.smallest_index + } + + /// The given index is no longer part of the queue. + /// + /// This updates `smallest_index` if need be. + fn consume_index(&mut self, removed_index: QueueIndex) { + if removed_index != self.smallest_index { + self.freed_indices.push(removed_index.reverse()); + return + } + let mut index = self.smallest_index.0.overflowing_add(1).0; + // Even more to advance? + while self.freed_indices.peek() == Some(&ReverseQueueIndex(index)) { + index = index.overflowing_add(1).0; + self.freed_indices.pop(); + } + self.smallest_index = QueueIndex(index); + } +} + /// Keeps track of how many assignments a scheduler currently has at a specific `CoreIndex` for a /// specific `ParaId`. #[derive(Encode, Decode, Default, Clone, Copy, TypeInfo)] #[cfg_attr(test, derive(PartialEq, RuntimeDebug))] -pub struct CoreAffinityCount { - core_idx: CoreIndex, +struct CoreAffinityCount { + core_index: CoreIndex, count: u32, } /// An indicator as to which end of the `OnDemandQueue` an assignment will be placed. -pub enum QueuePushDirection { +#[cfg_attr(test, derive(RuntimeDebug))] +enum QueuePushDirection { Back, Front, } @@ -93,9 +206,8 @@ type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; /// Errors that can happen during spot traffic calculation. -#[derive(PartialEq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub enum SpotTrafficCalculationErr { +#[derive(PartialEq, RuntimeDebug)] +enum SpotTrafficCalculationErr { /// The order queue capacity is at 0. QueueCapacityIsZero, /// The queue size is larger than the queue capacity. @@ -104,15 +216,85 @@ pub enum SpotTrafficCalculationErr { Division, } +/// Type used for priority indices. +// NOTE: The `Ord` implementation for this type is unsound in the general case. +// Do not use it for anything but it's intended purpose. +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq, Copy)] +struct QueueIndex(u32); + +/// QueueIndex with reverse ordering. +/// +/// Same as `Reverse(QueueIndex)`, but with all the needed traits implemented. +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq, Copy)] +struct ReverseQueueIndex(u32); + +impl QueueIndex { + fn reverse(self) -> ReverseQueueIndex { + ReverseQueueIndex(self.0) + } +} + +impl Ord for QueueIndex { + fn cmp(&self, other: &Self) -> Ordering { + let diff = self.0.overflowing_sub(other.0).0; + if diff == 0 { + Ordering::Equal + } else if diff <= ON_DEMAND_MAX_QUEUE_MAX_SIZE { + Ordering::Greater + } else { + Ordering::Less + } + } +} + +impl PartialOrd for QueueIndex { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ReverseQueueIndex { + fn cmp(&self, other: &Self) -> Ordering { + QueueIndex(other.0).cmp(&QueueIndex(self.0)) + } +} +impl PartialOrd for ReverseQueueIndex { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(&other)) + } +} + /// Internal representation of an order after it has been enqueued already. -#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone)] -pub(super) struct EnqueuedOrder { - pub para_id: ParaId, +/// +/// This data structure is provided for a min BinaryHeap (Ord compares in reverse order with regards +/// to its elements) +#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Clone, Eq)] +struct EnqueuedOrder { + para_id: ParaId, + idx: QueueIndex, } impl EnqueuedOrder { - pub fn new(para_id: ParaId) -> Self { - Self { para_id } + fn new(idx: QueueIndex, para_id: ParaId) -> Self { + Self { idx, para_id } + } +} + +impl PartialOrd for EnqueuedOrder { + fn partial_cmp(&self, other: &Self) -> Option { + match other.idx.partial_cmp(&self.idx) { + Some(Ordering::Equal) => other.para_id.partial_cmp(&self.para_id), + o => o, + } + } +} + +impl Ord for EnqueuedOrder { + fn cmp(&self, other: &Self) -> Ordering { + match other.idx.cmp(&self.idx) { + Ordering::Equal => other.para_id.cmp(&self.para_id), + o => o, + } } } @@ -121,8 +303,11 @@ pub mod pallet { use super::*; + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + #[pallet::pallet] #[pallet::without_storage_info] + #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); #[pallet::config] @@ -141,36 +326,44 @@ pub mod pallet { type TrafficDefaultValue: Get; } - /// Creates an empty spot traffic value if one isn't present in storage already. + /// Creates an empty queue status for an empty queue with initial traffic value. #[pallet::type_value] - pub fn SpotTrafficOnEmpty() -> FixedU128 { - T::TrafficDefaultValue::get() + pub(super) fn QueueStatusOnEmpty() -> QueueStatusType { + QueueStatusType { traffic: T::TrafficDefaultValue::get(), ..Default::default() } } - /// Creates an empty on demand queue if one isn't present in storage already. #[pallet::type_value] - pub(super) fn OnDemandQueueOnEmpty() -> VecDeque { - VecDeque::new() + pub(super) fn EntriesOnEmpty() -> BinaryHeap { + BinaryHeap::new() } - /// Keeps track of the multiplier used to calculate the current spot price for the on demand - /// assigner. - #[pallet::storage] - pub(super) type SpotTraffic = - StorageValue<_, FixedU128, ValueQuery, SpotTrafficOnEmpty>; - - /// The order storage entry. Uses a VecDeque to be able to push to the front of the - /// queue from the scheduler on session boundaries. - #[pallet::storage] - pub(super) type OnDemandQueue = - StorageValue<_, VecDeque, ValueQuery, OnDemandQueueOnEmpty>; - /// Maps a `ParaId` to `CoreIndex` and keeps track of how many assignments the scheduler has in /// it's lookahead. Keeping track of this affinity prevents parallel execution of the same /// `ParaId` on two or more `CoreIndex`es. #[pallet::storage] pub(super) type ParaIdAffinity = - StorageMap<_, Twox256, ParaId, CoreAffinityCount, OptionQuery>; + StorageMap<_, Twox64Concat, ParaId, CoreAffinityCount, OptionQuery>; + + /// Overall status of queue (both free + affinity entries) + #[pallet::storage] + pub(super) type QueueStatus = + StorageValue<_, QueueStatusType, ValueQuery, QueueStatusOnEmpty>; + + /// Priority queue for all orders which don't yet (or not any more) have any core affinity. + #[pallet::storage] + pub(super) type FreeEntries = + StorageValue<_, BinaryHeap, ValueQuery, EntriesOnEmpty>; + + /// Queue entries that are currently bound to a particular core due to core affinity. + #[pallet::storage] + pub(super) type AffinityEntries = StorageMap< + _, + Twox64Concat, + CoreIndex, + BinaryHeap, + ValueQuery, + EntriesOnEmpty, + >; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -183,9 +376,6 @@ pub mod pallet { #[pallet::error] pub enum Error { - /// The `ParaId` supplied to the `place_order` call is not a valid `ParaThread`, making the - /// call is invalid. - InvalidParaId, /// The order queue is full, `place_order` will not continue. QueueFull, /// The current spot price is higher than the max amount specified in the `place_order` @@ -197,45 +387,14 @@ pub mod pallet { impl Hooks> for Pallet { fn on_initialize(_now: BlockNumberFor) -> Weight { let config = >::config(); - // Calculate spot price multiplier and store it. - let old_traffic = SpotTraffic::::get(); - match Self::calculate_spot_traffic( - old_traffic, - config.scheduler_params.on_demand_queue_max_size, - Self::queue_size(), - config.scheduler_params.on_demand_target_queue_utilization, - config.scheduler_params.on_demand_fee_variability, - ) { - Ok(new_traffic) => { - // Only update storage on change - if new_traffic != old_traffic { - SpotTraffic::::set(new_traffic); - Pallet::::deposit_event(Event::::SpotTrafficSet { - traffic: new_traffic, - }); - return T::DbWeight::get().reads_writes(2, 1) - } - }, - Err(SpotTrafficCalculationErr::QueueCapacityIsZero) => { - log::debug!( - target: LOG_TARGET, - "Error calculating spot traffic: The order queue capacity is at 0." - ); - }, - Err(SpotTrafficCalculationErr::QueueSizeLargerThanCapacity) => { - log::debug!( - target: LOG_TARGET, - "Error calculating spot traffic: The queue size is larger than the queue capacity." - ); - }, - Err(SpotTrafficCalculationErr::Division) => { - log::debug!( - target: LOG_TARGET, - "Error calculating spot traffic: Arithmetic error during division, either division by 0 or over/underflow." - ); - }, - }; - T::DbWeight::get().reads_writes(2, 0) + // We need to update the spot traffic on block initialize in order to account for idle + // blocks. + QueueStatus::::mutate(|queue_status| { + Self::update_spot_traffic(&config, queue_status); + }); + + // 2 reads in config and queuestatus, at maximum 1 write to queuestatus. + T::DbWeight::get().reads_writes(2, 1) } } @@ -258,7 +417,7 @@ pub mod pallet { /// Events: /// - `SpotOrderPlaced` #[pallet::call_index(0)] - #[pallet::weight(::WeightInfo::place_order_allow_death(OnDemandQueue::::get().len() as u32))] + #[pallet::weight(::WeightInfo::place_order_allow_death(QueueStatus::::get().size()))] pub fn place_order_allow_death( origin: OriginFor, max_amount: BalanceOf, @@ -285,7 +444,7 @@ pub mod pallet { /// Events: /// - `SpotOrderPlaced` #[pallet::call_index(1)] - #[pallet::weight(::WeightInfo::place_order_keep_alive(OnDemandQueue::::get().len() as u32))] + #[pallet::weight(::WeightInfo::place_order_keep_alive(QueueStatus::::get().size()))] pub fn place_order_keep_alive( origin: OriginFor, max_amount: BalanceOf, @@ -297,10 +456,78 @@ pub mod pallet { } } +// Internal functions and interface to scheduler/wrapping assignment provider. impl Pallet where BalanceOf: FixedPointOperand, { + /// Take the next queued entry that is available for a given core index. + /// + /// Parameters: + /// - `core_index`: The core index + pub fn pop_assignment_for_core(core_index: CoreIndex) -> Option { + let entry: Result = QueueStatus::::try_mutate(|queue_status| { + AffinityEntries::::try_mutate(core_index, |affinity_entries| { + let free_entry = FreeEntries::::try_mutate(|free_entries| { + let affinity_next = affinity_entries.peek(); + let free_next = free_entries.peek(); + let pick_free = match (affinity_next, free_next) { + (None, _) => true, + (Some(_), None) => false, + (Some(a), Some(f)) => f < a, + }; + if pick_free { + let entry = free_entries.pop().ok_or(())?; + let (mut affinities, free): (BinaryHeap<_>, BinaryHeap<_>) = + take(free_entries) + .into_iter() + .partition(|e| e.para_id == entry.para_id); + affinity_entries.append(&mut affinities); + *free_entries = free; + Ok(entry) + } else { + Err(()) + } + }); + let entry = free_entry.or_else(|()| affinity_entries.pop().ok_or(()))?; + queue_status.consume_index(entry.idx); + Ok(entry) + }) + }); + + let assignment = entry.map(|e| Assignment::Pool { para_id: e.para_id, core_index }).ok()?; + + Pallet::::increase_affinity(assignment.para_id(), core_index); + Some(assignment) + } + + /// Report that the `para_id` & `core_index` combination was processed. + /// + /// This should be called once it is clear that the assignment won't get pushed back anymore. + /// + /// In other words for each `pop_assignment_for_core` a call to this function or + /// `push_back_assignment` must follow, but only one. + pub fn report_processed(para_id: ParaId, core_index: CoreIndex) { + Pallet::::decrease_affinity_update_queue(para_id, core_index); + } + + /// Push an assignment back to the front of the queue. + /// + /// The assignment has not been processed yet. Typically used on session boundaries. + /// + /// NOTE: We are not checking queue size here. So due to push backs it is possible that we + /// exceed the maximum queue size slightly. + /// + /// Parameters: + /// - `para_id`: The para that did not make it. + /// - `core_index`: The core the para was scheduled on. + pub fn push_back_assignment(para_id: ParaId, core_index: CoreIndex) { + Pallet::::decrease_affinity_update_queue(para_id, core_index); + QueueStatus::::mutate(|queue_status| { + Pallet::::add_on_demand_order(queue_status, para_id, QueuePushDirection::Front); + }); + } + /// Helper function for `place_order_*` calls. Used to differentiate between placing orders /// with a keep alive check or to allow the account to be reaped. /// @@ -326,34 +553,62 @@ where ) -> DispatchResult { let config = >::config(); - // Traffic always falls back to 1.0 - let traffic = SpotTraffic::::get(); - - // Calculate spot price - let spot_price: BalanceOf = traffic.saturating_mul_int( - config.scheduler_params.on_demand_base_fee.saturated_into::>(), - ); - - // Is the current price higher than `max_amount` - ensure!(spot_price.le(&max_amount), Error::::SpotPriceHigherThanMaxAmount); + QueueStatus::::mutate(|queue_status| { + Self::update_spot_traffic(&config, queue_status); + let traffic = queue_status.traffic; - // Charge the sending account the spot price - let _ = T::Currency::withdraw( - &sender, - spot_price, - WithdrawReasons::FEE, - existence_requirement, - )?; + // Calculate spot price + let spot_price: BalanceOf = traffic.saturating_mul_int( + config.scheduler_params.on_demand_base_fee.saturated_into::>(), + ); - let order = EnqueuedOrder::new(para_id); + // Is the current price higher than `max_amount` + ensure!(spot_price.le(&max_amount), Error::::SpotPriceHigherThanMaxAmount); - let res = Pallet::::add_on_demand_order(order, QueuePushDirection::Back); + // Charge the sending account the spot price + let _ = T::Currency::withdraw( + &sender, + spot_price, + WithdrawReasons::FEE, + existence_requirement, + )?; - if res.is_ok() { - Pallet::::deposit_event(Event::::OnDemandOrderPlaced { para_id, spot_price }); - } + ensure!( + queue_status.size() < config.scheduler_params.on_demand_queue_max_size, + Error::::QueueFull + ); + Pallet::::add_on_demand_order(queue_status, para_id, QueuePushDirection::Back); + Ok(()) + }) + } - res + /// Calculate and update spot traffic. + fn update_spot_traffic( + config: &configuration::HostConfiguration>, + queue_status: &mut QueueStatusType, + ) { + let old_traffic = queue_status.traffic; + match Self::calculate_spot_traffic( + old_traffic, + config.scheduler_params.on_demand_queue_max_size, + queue_status.size(), + config.scheduler_params.on_demand_target_queue_utilization, + config.scheduler_params.on_demand_fee_variability, + ) { + Ok(new_traffic) => { + // Only update storage on change + if new_traffic != old_traffic { + queue_status.traffic = new_traffic; + Pallet::::deposit_event(Event::::SpotTrafficSet { traffic: new_traffic }); + } + }, + Err(err) => { + log::debug!( + target: LOG_TARGET, + "Error calculating spot traffic: {:?}", err + ); + }, + }; } /// The spot price multiplier. This is based on the transaction fee calculations defined in: @@ -378,7 +633,7 @@ where /// - `SpotTrafficCalculationErr::QueueCapacityIsZero` /// - `SpotTrafficCalculationErr::QueueSizeLargerThanCapacity` /// - `SpotTrafficCalculationErr::Division` - pub(crate) fn calculate_spot_traffic( + fn calculate_spot_traffic( traffic: FixedU128, queue_capacity: u32, queue_size: u32, @@ -430,175 +685,140 @@ where /// Adds an order to the on demand queue. /// /// Paramenters: - /// - `order`: The `EnqueuedOrder` to add to the queue. /// - `location`: Whether to push this entry to the back or the front of the queue. Pushing an /// entry to the front of the queue is only used when the scheduler wants to push back an /// entry it has already popped. - /// Returns: - /// - The unit type on success. - /// - /// Errors: - /// - `InvalidParaId` - /// - `QueueFull` fn add_on_demand_order( - order: EnqueuedOrder, + queue_status: &mut QueueStatusType, + para_id: ParaId, location: QueuePushDirection, - ) -> Result<(), DispatchError> { - // Only parathreads are valid paraids for on the go parachains. - ensure!(>::is_parathread(order.para_id), Error::::InvalidParaId); - - let config = >::config(); - - OnDemandQueue::::try_mutate(|queue| { - // Abort transaction if queue is too large - ensure!( - Self::queue_size() < config.scheduler_params.on_demand_queue_max_size, - Error::::QueueFull - ); - match location { - QueuePushDirection::Back => queue.push_back(order), - QueuePushDirection::Front => queue.push_front(order), - }; - Ok(()) - }) + ) { + let idx = match location { + QueuePushDirection::Back => queue_status.push_back(), + QueuePushDirection::Front => queue_status.push_front(), + }; + + let affinity = ParaIdAffinity::::get(para_id); + let order = EnqueuedOrder::new(idx, para_id); + #[cfg(test)] + log::debug!(target: LOG_TARGET, "add_on_demand_order, order: {:?}, affinity: {:?}, direction: {:?}", order, affinity, location); + + match affinity { + None => FreeEntries::::mutate(|entries| entries.push(order)), + Some(affinity) => + AffinityEntries::::mutate(affinity.core_index, |entries| entries.push(order)), + } } - /// Get the size of the on demand queue. + /// Decrease core affinity for para and update queue /// - /// Returns: - /// - The size of the on demand queue. - fn queue_size() -> u32 { - let config = >::config(); - match OnDemandQueue::::get().len().try_into() { - Ok(size) => return size, - Err(_) => { - log::debug!( - target: LOG_TARGET, - "Failed to fetch the on demand queue size, returning the max size." - ); - return config.scheduler_params.on_demand_queue_max_size - }, + /// if affinity dropped to 0, moving entries back to `FreeEntries`. + fn decrease_affinity_update_queue(para_id: ParaId, core_index: CoreIndex) { + let affinity = Pallet::::decrease_affinity(para_id, core_index); + #[cfg(not(test))] + debug_assert_ne!( + affinity, None, + "Decreased affinity for a para that has not been served on a core?" + ); + if affinity != Some(0) { + return } - } - - /// Getter for the order queue. - #[cfg(test)] - fn get_queue() -> VecDeque { - OnDemandQueue::::get() - } - - /// Getter for the affinity tracker. - pub fn get_affinity_map(para_id: ParaId) -> Option { - ParaIdAffinity::::get(para_id) + // No affinity more for entries on this core, free any entries: + // + // This is necessary to ensure them being served as the core might no longer exist at all. + AffinityEntries::::mutate(core_index, |affinity_entries| { + FreeEntries::::mutate(|free_entries| { + let (mut freed, affinities): (BinaryHeap<_>, BinaryHeap<_>) = + take(affinity_entries).into_iter().partition(|e| e.para_id == para_id); + free_entries.append(&mut freed); + *affinity_entries = affinities; + }) + }); } /// Decreases the affinity of a `ParaId` to a specified `CoreIndex`. - /// Subtracts from the count of the `CoreAffinityCount` if an entry is found and the core_idx + /// + /// Subtracts from the count of the `CoreAffinityCount` if an entry is found and the core_index /// matches. When the count reaches 0, the entry is removed. /// A non-existant entry is a no-op. - fn decrease_affinity(para_id: ParaId, core_idx: CoreIndex) { + /// + /// Returns: The new affinity of the para on that core. `None` if there is no affinity on this + /// core. + fn decrease_affinity(para_id: ParaId, core_index: CoreIndex) -> Option { ParaIdAffinity::::mutate(para_id, |maybe_affinity| { - if let Some(affinity) = maybe_affinity { - if affinity.core_idx == core_idx { - let new_count = affinity.count.saturating_sub(1); - if new_count > 0 { - *maybe_affinity = Some(CoreAffinityCount { core_idx, count: new_count }); - } else { - *maybe_affinity = None; - } + let affinity = maybe_affinity.as_mut()?; + if affinity.core_index == core_index { + let new_count = affinity.count.saturating_sub(1); + if new_count > 0 { + *maybe_affinity = Some(CoreAffinityCount { core_index, count: new_count }); + } else { + *maybe_affinity = None; } + return Some(new_count) + } else { + None } - }); + }) } /// Increases the affinity of a `ParaId` to a specified `CoreIndex`. - /// Adds to the count of the `CoreAffinityCount` if an entry is found and the core_idx matches. - /// A non-existant entry will be initialized with a count of 1 and uses the supplied + /// Adds to the count of the `CoreAffinityCount` if an entry is found and the core_index + /// matches. A non-existant entry will be initialized with a count of 1 and uses the supplied /// `CoreIndex`. - fn increase_affinity(para_id: ParaId, core_idx: CoreIndex) { + fn increase_affinity(para_id: ParaId, core_index: CoreIndex) { ParaIdAffinity::::mutate(para_id, |maybe_affinity| match maybe_affinity { Some(affinity) => - if affinity.core_idx == core_idx { + if affinity.core_index == core_index { *maybe_affinity = Some(CoreAffinityCount { - core_idx, + core_index, count: affinity.count.saturating_add(1), }); }, None => { - *maybe_affinity = Some(CoreAffinityCount { core_idx, count: 1 }); + *maybe_affinity = Some(CoreAffinityCount { core_index, count: 1 }); }, }) } -} -impl Pallet { - /// Take the next queued entry that is available for a given core index. - /// Invalidates and removes orders with a `para_id` that is not `ParaLifecycle::Parathread` - /// but only in [0..P] range slice of the order queue, where P is the element that is - /// removed from the order queue. - /// - /// Parameters: - /// - `core_idx`: The core index - pub fn pop_assignment_for_core(core_idx: CoreIndex) -> Option { - let mut queue: VecDeque = OnDemandQueue::::get(); - - let mut invalidated_para_id_indexes: Vec = vec![]; - - // Get the position of the next `ParaId`. Select either a valid `ParaId` that has an - // affinity to the same `CoreIndex` as the scheduler asks for or a valid `ParaId` with no - // affinity at all. - let pos = queue.iter().enumerate().position(|(index, assignment)| { - if >::is_parathread(assignment.para_id) { - match ParaIdAffinity::::get(&assignment.para_id) { - Some(affinity) => return affinity.core_idx == core_idx, - None => return true, - } - } - // Record no longer valid para_ids. - invalidated_para_id_indexes.push(index); - return false - }); + /// Getter for the affinity tracker. + #[cfg(test)] + fn get_affinity_map(para_id: ParaId) -> Option { + ParaIdAffinity::::get(para_id) + } - // Collect the popped value. - let popped = pos.and_then(|p: usize| { - if let Some(assignment) = queue.remove(p) { - Pallet::::increase_affinity(assignment.para_id, core_idx); - return Some(assignment) - }; - None - }); + /// Getter for the affinity entries. + #[cfg(test)] + fn get_affinity_entries(core_index: CoreIndex) -> BinaryHeap { + AffinityEntries::::get(core_index) + } - // Only remove the invalid indexes *after* using the index. - // Removed in reverse order so that the indexes don't shift. - invalidated_para_id_indexes.iter().rev().for_each(|idx| { - queue.remove(*idx); - }); + /// Getter for the free entries. + #[cfg(test)] + fn get_free_entries() -> BinaryHeap { + FreeEntries::::get() + } - // Write changes to storage. - OnDemandQueue::::set(queue); + #[cfg(feature = "runtime-benchmarks")] + pub fn populate_queue(para_id: ParaId, num: u32) { + QueueStatus::::mutate(|queue_status| { + for _ in 0..num { + Pallet::::add_on_demand_order(queue_status, para_id, QueuePushDirection::Back); + } + }); + } - popped.map(|p| Assignment::Pool { para_id: p.para_id, core_index: core_idx }) + #[cfg(test)] + fn set_queue_status(new_status: QueueStatusType) { + QueueStatus::::set(new_status); } - /// Report that the `para_id` & `core_index` combination was processed. - pub fn report_processed(para_id: ParaId, core_index: CoreIndex) { - Pallet::::decrease_affinity(para_id, core_index) + #[cfg(test)] + fn get_queue_status() -> QueueStatusType { + QueueStatus::::get() } - /// Push an assignment back to the front of the queue. - /// - /// The assignment has not been processed yet. Typically used on session boundaries. - /// Parameters: - /// - `assignment`: The on demand assignment. - pub fn push_back_assignment(para_id: ParaId, core_index: CoreIndex) { - Pallet::::decrease_affinity(para_id, core_index); - // Skip the queue on push backs from scheduler - match Pallet::::add_on_demand_order( - EnqueuedOrder::new(para_id), - QueuePushDirection::Front, - ) { - Ok(_) => {}, - Err(_) => {}, - } + #[cfg(test)] + fn get_traffic_default_value() -> FixedU128 { + ::TrafficDefaultValue::get() } } diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs b/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs index 8404700780c..982efe77b93 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/tests.rs @@ -73,11 +73,24 @@ fn run_to_block( Paras::initializer_initialize(b + 1); Scheduler::initializer_initialize(b + 1); + // We need to update the spot traffic on every block. + OnDemandAssigner::on_initialize(b + 1); + // In the real runtime this is expected to be called by the `InclusionInherent` pallet. Scheduler::free_cores_and_fill_claimqueue(BTreeMap::new(), b + 1); } } +fn place_order(para_id: ParaId) { + let alice = 100u64; + let amt = 10_000_000u128; + + Balances::make_free_balance_be(&alice, amt); + + run_to_block(101, |n| if n == 101 { Some(Default::default()) } else { None }); + OnDemandAssigner::place_order_allow_death(RuntimeOrigin::signed(alice), amt, para_id).unwrap() +} + #[test] fn spot_traffic_capacity_zero_returns_none() { match OnDemandAssigner::calculate_spot_traffic( @@ -201,6 +214,42 @@ fn spot_traffic_decreases_over_time() { assert_eq!(traffic, FixedU128::from_inner(3_125_000_000_000_000_000u128)) } +#[test] +fn spot_traffic_decreases_between_idle_blocks() { + // Testing spot traffic assumptions, but using the mock runtime and default on demand + // configuration values. Ensuring that blocks with no on demand activity (idle) + // decrease traffic. + + let para_id = ParaId::from(111); + + new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { + // Initialize the parathread and wait for it to be ready. + schedule_blank_para(para_id, ParaKind::Parathread); + assert!(!Paras::is_parathread(para_id)); + run_to_block(100, |n| if n == 100 { Some(Default::default()) } else { None }); + assert!(Paras::is_parathread(para_id)); + + // Set the spot traffic to a large number + OnDemandAssigner::set_queue_status(QueueStatusType { + traffic: FixedU128::from_u32(10), + ..Default::default() + }); + + assert_eq!(OnDemandAssigner::get_queue_status().traffic, FixedU128::from_u32(10)); + + // Run to block 101 and ensure that the traffic decreases. + run_to_block(101, |n| if n == 100 { Some(Default::default()) } else { None }); + assert!(OnDemandAssigner::get_queue_status().traffic < FixedU128::from_u32(10)); + + // Run to block 102 and observe that we've hit the default traffic value. + run_to_block(102, |n| if n == 100 { Some(Default::default()) } else { None }); + assert_eq!( + OnDemandAssigner::get_queue_status().traffic, + OnDemandAssigner::get_traffic_default_value() + ); + }) +} + #[test] fn place_order_works() { let alice = 1u64; @@ -278,74 +327,6 @@ fn place_order_keep_alive_keeps_alive() { }); } -#[test] -fn add_on_demand_order_works() { - let para_a = ParaId::from(111); - let order = EnqueuedOrder::new(para_a); - - let mut genesis = GenesisConfigBuilder::default(); - genesis.on_demand_max_queue_size = 1; - new_test_ext(genesis.build()).execute_with(|| { - // Initialize the parathread and wait for it to be ready. - schedule_blank_para(para_a, ParaKind::Parathread); - - // `para_a` is not onboarded as a parathread yet. - assert_noop!( - OnDemandAssigner::add_on_demand_order(order.clone(), QueuePushDirection::Back), - Error::::InvalidParaId - ); - - assert!(!Paras::is_parathread(para_a)); - run_to_block(100, |n| if n == 100 { Some(Default::default()) } else { None }); - assert!(Paras::is_parathread(para_a)); - - // `para_a` is now onboarded as a valid parathread. - assert_ok!(OnDemandAssigner::add_on_demand_order(order.clone(), QueuePushDirection::Back)); - - // Max queue size is 1, queue should be full. - assert_noop!( - OnDemandAssigner::add_on_demand_order(order, QueuePushDirection::Back), - Error::::QueueFull - ); - }); -} - -#[test] -fn spotqueue_push_directions() { - new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { - let para_a = ParaId::from(111); - let para_b = ParaId::from(222); - let para_c = ParaId::from(333); - - schedule_blank_para(para_a, ParaKind::Parathread); - schedule_blank_para(para_b, ParaKind::Parathread); - schedule_blank_para(para_c, ParaKind::Parathread); - - run_to_block(11, |n| if n == 11 { Some(Default::default()) } else { None }); - - let order_a = EnqueuedOrder::new(para_a); - let order_b = EnqueuedOrder::new(para_b); - let order_c = EnqueuedOrder::new(para_c); - - assert_ok!(OnDemandAssigner::add_on_demand_order( - order_a.clone(), - QueuePushDirection::Front - )); - assert_ok!(OnDemandAssigner::add_on_demand_order( - order_b.clone(), - QueuePushDirection::Front - )); - - assert_ok!(OnDemandAssigner::add_on_demand_order( - order_c.clone(), - QueuePushDirection::Back - )); - - assert_eq!(OnDemandAssigner::queue_size(), 3); - assert_eq!(OnDemandAssigner::get_queue(), VecDeque::from(vec![order_b, order_a, order_c])) - }); -} - #[test] fn pop_assignment_for_core_works() { new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { @@ -356,51 +337,32 @@ fn pop_assignment_for_core_works() { run_to_block(11, |n| if n == 11 { Some(Default::default()) } else { None }); - let order_a = EnqueuedOrder::new(para_a); - let order_b = EnqueuedOrder::new(para_b); - let assignment_a = Assignment::Pool { para_id: para_a, core_index: CoreIndex(0) }; - let assignment_b = Assignment::Pool { para_id: para_b, core_index: CoreIndex(1) }; - // Pop should return none with empty queue assert_eq!(OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)), None); // Add enough assignments to the order queue. for _ in 0..2 { - OnDemandAssigner::add_on_demand_order(order_a.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); - - OnDemandAssigner::add_on_demand_order(order_b.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); - } - - // Queue should contain orders a, b, a, b - { - let queue: Vec = OnDemandQueue::::get().into_iter().collect(); - assert_eq!( - queue, - vec![order_a.clone(), order_b.clone(), order_a.clone(), order_b.clone()] - ); + place_order(para_a); + place_order(para_b); } // Popped assignments should be for the correct paras and cores assert_eq!( - OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)), - Some(assignment_a.clone()) + OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)).map(|a| a.para_id()), + Some(para_a) ); assert_eq!( - OnDemandAssigner::pop_assignment_for_core(CoreIndex(1)), - Some(assignment_b.clone()) + OnDemandAssigner::pop_assignment_for_core(CoreIndex(1)).map(|a| a.para_id()), + Some(para_b) ); assert_eq!( - OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)), - Some(assignment_a.clone()) + OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)).map(|a| a.para_id()), + Some(para_a) + ); + assert_eq!( + OnDemandAssigner::pop_assignment_for_core(CoreIndex(1)).map(|a| a.para_id()), + Some(para_b) ); - - // Queue should contain one left over order - { - let queue: Vec = OnDemandQueue::::get().into_iter().collect(); - assert_eq!(queue, vec![order_b.clone(),]); - } }); } @@ -414,28 +376,19 @@ fn push_back_assignment_works() { run_to_block(11, |n| if n == 11 { Some(Default::default()) } else { None }); - let order_a = EnqueuedOrder::new(para_a); - let order_b = EnqueuedOrder::new(para_b); - // Add enough assignments to the order queue. - OnDemandAssigner::add_on_demand_order(order_a.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); - - OnDemandAssigner::add_on_demand_order(order_b.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); + place_order(para_a); + place_order(para_b); // Pop order a - OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)); + assert_eq!( + OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)).unwrap().para_id(), + para_a + ); // Para a should have affinity for core 0 assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().count, 1); - assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().core_idx, CoreIndex(0)); - - // Queue should still contain order b - { - let queue: Vec = OnDemandQueue::::get().into_iter().collect(); - assert_eq!(queue, vec![order_b.clone()]); - } + assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().core_index, CoreIndex(0)); // Push back order a OnDemandAssigner::push_back_assignment(para_a, CoreIndex(0)); @@ -444,10 +397,82 @@ fn push_back_assignment_works() { assert_eq!(OnDemandAssigner::get_affinity_map(para_a).is_none(), true); // Queue should contain orders a, b. A in front of b. - { - let queue: Vec = OnDemandQueue::::get().into_iter().collect(); - assert_eq!(queue, vec![order_a.clone(), order_b.clone()]); + assert_eq!( + OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)).unwrap().para_id(), + para_a + ); + assert_eq!( + OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)).unwrap().para_id(), + para_b + ); + }); +} + +#[test] +fn affinity_prohibits_parallel_scheduling() { + new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { + let para_a = ParaId::from(111); + let para_b = ParaId::from(222); + + schedule_blank_para(para_a, ParaKind::Parathread); + schedule_blank_para(para_b, ParaKind::Parathread); + + run_to_block(11, |n| if n == 11 { Some(Default::default()) } else { None }); + + // There should be no affinity before starting. + assert!(OnDemandAssigner::get_affinity_map(para_a).is_none()); + assert!(OnDemandAssigner::get_affinity_map(para_b).is_none()); + + // Add 2 assignments for para_a for every para_b. + place_order(para_a); + place_order(para_a); + place_order(para_b); + + // Approximate having 1 core. + for _ in 0..3 { + assert!(OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)).is_some()); } + assert!(OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)).is_none()); + + // Affinity on one core is meaningless. + assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().count, 2); + assert_eq!(OnDemandAssigner::get_affinity_map(para_b).unwrap().count, 1); + assert_eq!( + OnDemandAssigner::get_affinity_map(para_a).unwrap().core_index, + OnDemandAssigner::get_affinity_map(para_b).unwrap().core_index, + ); + + // Clear affinity + OnDemandAssigner::report_processed(para_a, 0.into()); + OnDemandAssigner::report_processed(para_a, 0.into()); + OnDemandAssigner::report_processed(para_b, 0.into()); + + // Add 2 assignments for para_a for every para_b. + place_order(para_a); + place_order(para_a); + place_order(para_b); + + // Approximate having 3 cores. CoreIndex 2 should be unable to obtain an assignment + for _ in 0..3 { + OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)); + OnDemandAssigner::pop_assignment_for_core(CoreIndex(1)); + assert!(OnDemandAssigner::pop_assignment_for_core(CoreIndex(2)).is_none()); + } + + // Affinity should be the same as before, but on different cores. + assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().count, 2); + assert_eq!(OnDemandAssigner::get_affinity_map(para_b).unwrap().count, 1); + assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().core_index, CoreIndex(0)); + assert_eq!(OnDemandAssigner::get_affinity_map(para_b).unwrap().core_index, CoreIndex(1)); + + // Clear affinity + OnDemandAssigner::report_processed(para_a, CoreIndex(0)); + OnDemandAssigner::report_processed(para_a, CoreIndex(0)); + OnDemandAssigner::report_processed(para_b, CoreIndex(1)); + + // There should be no affinity after clearing. + assert!(OnDemandAssigner::get_affinity_map(para_a).is_none()); + assert!(OnDemandAssigner::get_affinity_map(para_b).is_none()); }); } @@ -458,7 +483,6 @@ fn affinity_changes_work() { let core_index = CoreIndex(0); schedule_blank_para(para_a, ParaKind::Parathread); - let order_a = EnqueuedOrder::new(para_a); run_to_block(11, |n| if n == 11 { Some(Default::default()) } else { None }); // There should be no affinity before starting. @@ -466,8 +490,7 @@ fn affinity_changes_work() { // Add enough assignments to the order queue. for _ in 0..10 { - OnDemandAssigner::add_on_demand_order(order_a.clone(), QueuePushDirection::Front) - .expect("Invalid paraid or queue full"); + place_order(para_a); } // There should be no affinity before the scheduler pops. @@ -483,7 +506,6 @@ fn affinity_changes_work() { // Affinity count is 1 after popping with a previous para. assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().count, 1); - assert_eq!(OnDemandAssigner::queue_size(), 8); for _ in 0..3 { OnDemandAssigner::pop_assignment_for_core(core_index); @@ -491,147 +513,197 @@ fn affinity_changes_work() { // Affinity count is 4 after popping 3 times without a previous para. assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().count, 4); - assert_eq!(OnDemandAssigner::queue_size(), 5); for _ in 0..5 { OnDemandAssigner::report_processed(para_a, 0.into()); - OnDemandAssigner::pop_assignment_for_core(core_index); + assert!(OnDemandAssigner::pop_assignment_for_core(core_index).is_some()); } // Affinity count should still be 4 but queue should be empty. + assert!(OnDemandAssigner::pop_assignment_for_core(core_index).is_none()); assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().count, 4); - assert_eq!(OnDemandAssigner::queue_size(), 0); // Pop 4 times and get to exactly 0 (None) affinity. for _ in 0..4 { OnDemandAssigner::report_processed(para_a, 0.into()); - OnDemandAssigner::pop_assignment_for_core(core_index); + assert!(OnDemandAssigner::pop_assignment_for_core(core_index).is_none()); } assert!(OnDemandAssigner::get_affinity_map(para_a).is_none()); // Decreasing affinity beyond 0 should still be None. OnDemandAssigner::report_processed(para_a, 0.into()); - OnDemandAssigner::pop_assignment_for_core(core_index); + assert!(OnDemandAssigner::pop_assignment_for_core(core_index).is_none()); assert!(OnDemandAssigner::get_affinity_map(para_a).is_none()); }); } #[test] -fn affinity_prohibits_parallel_scheduling() { - new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { - let para_a = ParaId::from(111); - let para_b = ParaId::from(222); +fn new_affinity_for_a_core_must_come_from_free_entries() { + // If affinity count for a core was zero before, and is 1 now, then the entry + // must have come from free_entries. + let parachains = + vec![ParaId::from(111), ParaId::from(222), ParaId::from(333), ParaId::from(444)]; + let core_indices = vec![CoreIndex(0), CoreIndex(1), CoreIndex(2), CoreIndex(3)]; - schedule_blank_para(para_a, ParaKind::Parathread); - schedule_blank_para(para_b, ParaKind::Parathread); + new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { + parachains.iter().for_each(|chain| { + schedule_blank_para(*chain, ParaKind::Parathread); + }); run_to_block(11, |n| if n == 11 { Some(Default::default()) } else { None }); - let order_a = EnqueuedOrder::new(para_a); - let order_b = EnqueuedOrder::new(para_b); - - // There should be no affinity before starting. - assert!(OnDemandAssigner::get_affinity_map(para_a).is_none()); - assert!(OnDemandAssigner::get_affinity_map(para_b).is_none()); - - // Add 2 assignments for para_a for every para_b. - OnDemandAssigner::add_on_demand_order(order_a.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); - - OnDemandAssigner::add_on_demand_order(order_a.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); - - OnDemandAssigner::add_on_demand_order(order_b.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); - - assert_eq!(OnDemandAssigner::queue_size(), 3); + // Place orders for all chains. + parachains.iter().for_each(|chain| { + place_order(*chain); + }); + + // There are 4 entries in free_entries. + let start_free_entries = OnDemandAssigner::get_free_entries().len(); + assert_eq!(start_free_entries, 4); + + // Pop assignments on all cores. + core_indices.iter().enumerate().for_each(|(n, core_index)| { + // There is no affinity on the core prior to popping. + assert!(OnDemandAssigner::get_affinity_entries(*core_index).is_empty()); + + // There's always an order to be popped for each core. + let free_entries = OnDemandAssigner::get_free_entries(); + let next_order = free_entries.peek(); + + // There is no affinity on the paraid prior to popping. + assert!(OnDemandAssigner::get_affinity_map(next_order.unwrap().para_id).is_none()); + + match OnDemandAssigner::pop_assignment_for_core(*core_index) { + Some(assignment) => { + // The popped assignment came from free entries. + assert_eq!( + start_free_entries - 1 - n, + OnDemandAssigner::get_free_entries().len() + ); + // The popped assignment has the same para id as the next order. + assert_eq!(assignment.para_id(), next_order.unwrap().para_id); + }, + None => panic!("Should not happen"), + } + }); - // Approximate having 1 core. - for _ in 0..3 { - OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)); - } + // All entries have been removed from free_entries. + assert!(OnDemandAssigner::get_free_entries().is_empty()); - // Affinity on one core is meaningless. - assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().count, 2); - assert_eq!(OnDemandAssigner::get_affinity_map(para_b).unwrap().count, 1); - assert_eq!( - OnDemandAssigner::get_affinity_map(para_a).unwrap().core_idx, - OnDemandAssigner::get_affinity_map(para_b).unwrap().core_idx - ); - - // Clear affinity - OnDemandAssigner::report_processed(para_a, 0.into()); - OnDemandAssigner::report_processed(para_a, 0.into()); - OnDemandAssigner::report_processed(para_b, 0.into()); - - // Add 2 assignments for para_a for every para_b. - OnDemandAssigner::add_on_demand_order(order_a.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); + // All chains have an affinity count of 1. + parachains.iter().for_each(|chain| { + assert_eq!(OnDemandAssigner::get_affinity_map(*chain).unwrap().count, 1); + }); + }); +} - OnDemandAssigner::add_on_demand_order(order_a.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); +#[test] +#[should_panic] +fn queue_index_ordering_is_unsound_over_max_size() { + // NOTE: Unsoundness proof. If the number goes sufficiently over the max_queue_max_size + // the overflow will cause an opposite comparison to what would be expected. + let max_num = u32::MAX - ON_DEMAND_MAX_QUEUE_MAX_SIZE; + // 0 < some large number. + assert_eq!(QueueIndex(0).cmp(&QueueIndex(max_num + 1)), Ordering::Less); +} - OnDemandAssigner::add_on_demand_order(order_b.clone(), QueuePushDirection::Back) - .expect("Invalid paraid or queue full"); +#[test] +fn queue_index_ordering_works() { + // The largest accepted queue size. + let max_num = ON_DEMAND_MAX_QUEUE_MAX_SIZE; + + // 0 == 0 + assert_eq!(QueueIndex(0).cmp(&QueueIndex(0)), Ordering::Equal); + // 0 < 1 + assert_eq!(QueueIndex(0).cmp(&QueueIndex(1)), Ordering::Less); + // 1 > 0 + assert_eq!(QueueIndex(1).cmp(&QueueIndex(0)), Ordering::Greater); + // 0 < max_num + assert_eq!(QueueIndex(0).cmp(&QueueIndex(max_num)), Ordering::Less); + // 0 > max_num + 1 + assert_eq!(QueueIndex(0).cmp(&QueueIndex(max_num + 1)), Ordering::Less); + + // Ordering within the bounds of ON_DEMAND_MAX_QUEUE_MAX_SIZE works. + let mut v = vec![3, 6, 2, 1, 5, 4]; + v.sort_by_key(|&num| QueueIndex(num)); + assert_eq!(v, vec![1, 2, 3, 4, 5, 6]); + + v = vec![max_num, 4, 5, 1, 6]; + v.sort_by_key(|&num| QueueIndex(num)); + assert_eq!(v, vec![1, 4, 5, 6, max_num]); + + // Ordering with an element outside of the bounds of the max size also works. + v = vec![max_num + 2, 0, 6, 2, 1, 5, 4]; + v.sort_by_key(|&num| QueueIndex(num)); + assert_eq!(v, vec![0, 1, 2, 4, 5, 6, max_num + 2]); + + // Numbers way above the max size will overflow + v = vec![u32::MAX - 1, u32::MAX, 6, 2, 1, 5, 4]; + v.sort_by_key(|&num| QueueIndex(num)); + assert_eq!(v, vec![u32::MAX - 1, u32::MAX, 1, 2, 4, 5, 6]); +} - // Approximate having 3 cores. CoreIndex 2 should be unable to obtain an assignment - for _ in 0..3 { - OnDemandAssigner::pop_assignment_for_core(CoreIndex(0)); - OnDemandAssigner::pop_assignment_for_core(CoreIndex(1)); - assert_eq!(None, OnDemandAssigner::pop_assignment_for_core(CoreIndex(2))); - } +#[test] +fn reverse_queue_index_does_reverse() { + let mut v = vec![1, 2, 3, 4, 5, 6]; - // Affinity should be the same as before, but on different cores. - assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().count, 2); - assert_eq!(OnDemandAssigner::get_affinity_map(para_b).unwrap().count, 1); - assert_eq!(OnDemandAssigner::get_affinity_map(para_a).unwrap().core_idx, CoreIndex(0)); - assert_eq!(OnDemandAssigner::get_affinity_map(para_b).unwrap().core_idx, CoreIndex(1)); + // Basic reversal of a vector. + v.sort_by_key(|&num| ReverseQueueIndex(num)); + assert_eq!(v, vec![6, 5, 4, 3, 2, 1]); - // Clear affinity - OnDemandAssigner::report_processed(para_a, 0.into()); - OnDemandAssigner::report_processed(para_a, 0.into()); - OnDemandAssigner::report_processed(para_b, 1.into()); + // Example from rust docs on `Reverse`. Should work identically. + v.sort_by_key(|&num| (num > 3, ReverseQueueIndex(num))); + assert_eq!(v, vec![3, 2, 1, 6, 5, 4]); - // There should be no affinity after clearing. - assert!(OnDemandAssigner::get_affinity_map(para_a).is_none()); - assert!(OnDemandAssigner::get_affinity_map(para_b).is_none()); - }); + let mut v2 = vec![1, 2, u32::MAX]; + v2.sort_by_key(|&num| ReverseQueueIndex(num)); + assert_eq!(v2, vec![2, 1, u32::MAX]); } #[test] -fn on_demand_orders_cannot_be_popped_if_lifecycle_changes() { - let para_id = ParaId::from(10); - let core_index = CoreIndex(0); - let order = EnqueuedOrder::new(para_id); +fn queue_status_size_fn_works() { + // Add orders to the on demand queue, and make sure that they are properly represented + // by the QueueStatusType::size fn. + let parachains = vec![ParaId::from(111), ParaId::from(222), ParaId::from(333)]; + let core_indices = vec![CoreIndex(0), CoreIndex(1)]; new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { - // Register the para_id as a parathread - schedule_blank_para(para_id, ParaKind::Parathread); - - assert!(!Paras::is_parathread(para_id)); - run_to_block(10, |n| if n == 10 { Some(Default::default()) } else { None }); - assert!(Paras::is_parathread(para_id)); + parachains.iter().for_each(|chain| { + schedule_blank_para(*chain, ParaKind::Parathread); + }); - // Add two assignments for a para_id with a valid lifecycle. - assert_ok!(OnDemandAssigner::add_on_demand_order(order.clone(), QueuePushDirection::Back)); - assert_ok!(OnDemandAssigner::add_on_demand_order(order.clone(), QueuePushDirection::Back)); + assert_eq!(OnDemandAssigner::get_queue_status().size(), 0); - // First pop is fine - assert!( - OnDemandAssigner::pop_assignment_for_core(core_index) == - Some(Assignment::Pool { para_id, core_index }) - ); + run_to_block(11, |n| if n == 11 { Some(Default::default()) } else { None }); - // Deregister para - assert_ok!(Paras::schedule_para_cleanup(para_id)); + // Place orders for all chains. + parachains.iter().for_each(|chain| { + // 2 per chain for a total of 6 + place_order(*chain); + place_order(*chain); + }); - // Run to new session and verify that para_id is no longer a valid parathread. - assert!(Paras::is_parathread(para_id)); - run_to_block(20, |n| if n == 20 { Some(Default::default()) } else { None }); - assert!(!Paras::is_parathread(para_id)); + // 6 orders in free entries + assert_eq!(OnDemandAssigner::get_free_entries().len(), 6); + // 6 orders via queue status size + assert_eq!( + OnDemandAssigner::get_free_entries().len(), + OnDemandAssigner::get_queue_status().size() as usize + ); - // Second pop should be None. - OnDemandAssigner::report_processed(para_id, core_index); - assert_eq!(OnDemandAssigner::pop_assignment_for_core(core_index), None); + core_indices.iter().for_each(|core_index| { + OnDemandAssigner::pop_assignment_for_core(*core_index); + }); + + // There should be 2 orders in the scheduler's claimqueue, + // 2 in assorted AffinityMaps and 2 in free. + // ParaId 111 + assert_eq!(OnDemandAssigner::get_affinity_entries(core_indices[0]).len(), 1); + // ParaId 222 + assert_eq!(OnDemandAssigner::get_affinity_entries(core_indices[1]).len(), 1); + // Free entries are from ParaId 333 + assert_eq!(OnDemandAssigner::get_free_entries().len(), 2); + // For a total size of 4. + assert_eq!(OnDemandAssigner::get_queue_status().size(), 4) }); } diff --git a/polkadot/runtime/parachains/src/configuration.rs b/polkadot/runtime/parachains/src/configuration.rs index 364a15215d3..b7635dcd7b2 100644 --- a/polkadot/runtime/parachains/src/configuration.rs +++ b/polkadot/runtime/parachains/src/configuration.rs @@ -29,6 +29,7 @@ use primitives::{ vstaging::{ApprovalVotingParams, NodeFeatures}, AsyncBackingParams, Balance, ExecutorParamError, ExecutorParams, SessionIndex, LEGACY_MIN_BACKING_VOTES, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, + ON_DEMAND_MAX_QUEUE_MAX_SIZE, }; use sp_runtime::{traits::Zero, Perbill}; use sp_std::prelude::*; @@ -312,6 +313,8 @@ pub enum InconsistentError { InconsistentExecutorParams { inner: ExecutorParamError }, /// TTL should be bigger than lookahead LookaheadExceedsTTL, + /// Passed in queue size for on-demand was too large. + OnDemandQueueSizeTooLarge, } impl HostConfiguration @@ -405,6 +408,10 @@ where return Err(LookaheadExceedsTTL) } + if self.scheduler_params.on_demand_queue_max_size > ON_DEMAND_MAX_QUEUE_MAX_SIZE { + return Err(OnDemandQueueSizeTooLarge) + } + Ok(()) } @@ -630,7 +637,7 @@ pub mod pallet { /// Set the number of coretime execution cores. /// - /// Note that this configuration is managed by the coretime chain. Only manually change + /// NOTE: that this configuration is managed by the coretime chain. Only manually change /// this, if you really know what you are doing! #[pallet::call_index(6)] #[pallet::weight(( @@ -1133,6 +1140,7 @@ pub mod pallet { config.scheduler_params.on_demand_queue_max_size = new; }) } + /// Set the on demand (parathreads) fee variability. #[pallet::call_index(50)] #[pallet::weight(( diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index f68870c98ea..a773eeb5cbd 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -1659,6 +1659,7 @@ pub mod migrations { // This needs to come after the `parachains_configuration` above as we are reading the configuration. coretime::migration::MigrateToCoretime, parachains_configuration::migration::v12::MigrateToV12, + parachains_assigner_on_demand::migration::MigrateV0ToV1, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs index ac0f05301b4..dba9e7904c7 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_assigner_on_demand.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `runtime_parachains::assigner_on_demand` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-08-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-fljshgub-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -31,11 +31,11 @@ // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json // --pallet=runtime_parachains::assigner_on_demand // --chain=rococo-dev -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -48,44 +48,44 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::assigner_on_demand`. pub struct WeightInfo(PhantomData); impl runtime_parachains::assigner_on_demand::WeightInfo for WeightInfo { - /// Storage: `OnDemandAssignmentProvider::SpotTraffic` (r:1 w:0) - /// Proof: `OnDemandAssignmentProvider::SpotTraffic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `OnDemandAssignmentProvider::OnDemandQueue` (r:1 w:1) - /// Proof: `OnDemandAssignmentProvider::OnDemandQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::QueueStatus` (r:1 w:1) + /// Proof: `OnDemandAssignmentProvider::QueueStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::ParaIdAffinity` (r:1 w:0) + /// Proof: `OnDemandAssignmentProvider::ParaIdAffinity` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::FreeEntries` (r:1 w:1) + /// Proof: `OnDemandAssignmentProvider::FreeEntries` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `s` is `[1, 9999]`. fn place_order_keep_alive(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `297 + s * (4 ±0)` - // Estimated: `3762 + s * (4 ±0)` - // Minimum execution time: 33_522_000 picoseconds. - Weight::from_parts(35_436_835, 0) - .saturating_add(Weight::from_parts(0, 3762)) - // Standard Error: 129 - .saturating_add(Weight::from_parts(14_041, 0).saturating_mul(s.into())) + // Measured: `218 + s * (8 ±0)` + // Estimated: `3681 + s * (8 ±0)` + // Minimum execution time: 21_053_000 picoseconds. + Weight::from_parts(17_291_897, 0) + .saturating_add(Weight::from_parts(0, 3681)) + // Standard Error: 104 + .saturating_add(Weight::from_parts(18_779, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 8).saturating_mul(s.into())) } - /// Storage: `OnDemandAssignmentProvider::SpotTraffic` (r:1 w:0) - /// Proof: `OnDemandAssignmentProvider::SpotTraffic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `OnDemandAssignmentProvider::OnDemandQueue` (r:1 w:1) - /// Proof: `OnDemandAssignmentProvider::OnDemandQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::QueueStatus` (r:1 w:1) + /// Proof: `OnDemandAssignmentProvider::QueueStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::ParaIdAffinity` (r:1 w:0) + /// Proof: `OnDemandAssignmentProvider::ParaIdAffinity` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::FreeEntries` (r:1 w:1) + /// Proof: `OnDemandAssignmentProvider::FreeEntries` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `s` is `[1, 9999]`. fn place_order_allow_death(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `297 + s * (4 ±0)` - // Estimated: `3762 + s * (4 ±0)` - // Minimum execution time: 33_488_000 picoseconds. - Weight::from_parts(34_848_934, 0) - .saturating_add(Weight::from_parts(0, 3762)) - // Standard Error: 143 - .saturating_add(Weight::from_parts(14_215, 0).saturating_mul(s.into())) + // Measured: `218 + s * (8 ±0)` + // Estimated: `3681 + s * (8 ±0)` + // Minimum execution time: 20_843_000 picoseconds. + Weight::from_parts(16_881_986, 0) + .saturating_add(Weight::from_parts(0, 3681)) + // Standard Error: 104 + .saturating_add(Weight::from_parts(18_788, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 8).saturating_mul(s.into())) } } diff --git a/polkadot/runtime/westend/src/weights/runtime_parachains_assigner_on_demand.rs b/polkadot/runtime/westend/src/weights/runtime_parachains_assigner_on_demand.rs index ac0f05301b4..acd1834f79e 100644 --- a/polkadot/runtime/westend/src/weights/runtime_parachains_assigner_on_demand.rs +++ b/polkadot/runtime/westend/src/weights/runtime_parachains_assigner_on_demand.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::assigner_on_demand` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-08-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-fljshgub-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: // target/production/polkadot @@ -31,11 +31,11 @@ // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json // --pallet=runtime_parachains::assigner_on_demand -// --chain=rococo-dev -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ +// --chain=westend-dev +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/westend/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -48,44 +48,44 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::assigner_on_demand`. pub struct WeightInfo(PhantomData); impl runtime_parachains::assigner_on_demand::WeightInfo for WeightInfo { - /// Storage: `OnDemandAssignmentProvider::SpotTraffic` (r:1 w:0) - /// Proof: `OnDemandAssignmentProvider::SpotTraffic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `OnDemandAssignmentProvider::OnDemandQueue` (r:1 w:1) - /// Proof: `OnDemandAssignmentProvider::OnDemandQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::QueueStatus` (r:1 w:1) + /// Proof: `OnDemandAssignmentProvider::QueueStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::ParaIdAffinity` (r:1 w:0) + /// Proof: `OnDemandAssignmentProvider::ParaIdAffinity` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::FreeEntries` (r:1 w:1) + /// Proof: `OnDemandAssignmentProvider::FreeEntries` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `s` is `[1, 9999]`. fn place_order_keep_alive(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `297 + s * (4 ±0)` - // Estimated: `3762 + s * (4 ±0)` - // Minimum execution time: 33_522_000 picoseconds. - Weight::from_parts(35_436_835, 0) - .saturating_add(Weight::from_parts(0, 3762)) - // Standard Error: 129 - .saturating_add(Weight::from_parts(14_041, 0).saturating_mul(s.into())) + // Measured: `218 + s * (8 ±0)` + // Estimated: `3681 + s * (8 ±0)` + // Minimum execution time: 21_396_000 picoseconds. + Weight::from_parts(20_585_695, 0) + .saturating_add(Weight::from_parts(0, 3681)) + // Standard Error: 127 + .saturating_add(Weight::from_parts(20_951, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 8).saturating_mul(s.into())) } - /// Storage: `OnDemandAssignmentProvider::SpotTraffic` (r:1 w:0) - /// Proof: `OnDemandAssignmentProvider::SpotTraffic` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Paras::ParaLifecycles` (r:1 w:0) - /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `OnDemandAssignmentProvider::OnDemandQueue` (r:1 w:1) - /// Proof: `OnDemandAssignmentProvider::OnDemandQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::QueueStatus` (r:1 w:1) + /// Proof: `OnDemandAssignmentProvider::QueueStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::ParaIdAffinity` (r:1 w:0) + /// Proof: `OnDemandAssignmentProvider::ParaIdAffinity` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `OnDemandAssignmentProvider::FreeEntries` (r:1 w:1) + /// Proof: `OnDemandAssignmentProvider::FreeEntries` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `s` is `[1, 9999]`. fn place_order_allow_death(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `297 + s * (4 ±0)` - // Estimated: `3762 + s * (4 ±0)` - // Minimum execution time: 33_488_000 picoseconds. - Weight::from_parts(34_848_934, 0) - .saturating_add(Weight::from_parts(0, 3762)) - // Standard Error: 143 - .saturating_add(Weight::from_parts(14_215, 0).saturating_mul(s.into())) + // Measured: `218 + s * (8 ±0)` + // Estimated: `3681 + s * (8 ±0)` + // Minimum execution time: 21_412_000 picoseconds. + Weight::from_parts(19_731_554, 0) + .saturating_add(Weight::from_parts(0, 3681)) + // Standard Error: 128 + .saturating_add(Weight::from_parts(21_055, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 8).saturating_mul(s.into())) } } diff --git a/prdoc/pr_3190.prdoc b/prdoc/pr_3190.prdoc new file mode 100644 index 00000000000..2f7a89a0b1a --- /dev/null +++ b/prdoc/pr_3190.prdoc @@ -0,0 +1,17 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Fix algorithmic complexity of the on-demand scheduler. + +doc: + - audience: Runtime Dev + description: | + Improves on demand performance by a significant factor. Previously, having many on-demand cores + would cause really poor blocktimes due to the fact that for each core the full order queue was + processed. This allows for increasing the max size of the on-demand queue if needed. + + At the same time, the spot price for on-demand is now checked prior to every order, ensuring + that economic backpressure will be applied. + +crates: + - name: polkadot-runtime-parachains -- GitLab From 1da8a6b88f530b467394a9ead8f3042ebdc50a36 Mon Sep 17 00:00:00 2001 From: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Date: Wed, 20 Mar 2024 20:41:43 +0100 Subject: [PATCH 152/188] Enable PoV reclaim on `rococo-parachain` (#3765) This PR proposes enabling PoV reclaim on the `rococo-parachain` testchain to streamline testing and development of high-TPS stuff. --- Cargo.lock | 1 + cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml | 2 ++ cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 5401dc5ecfb..bdbf6ddac26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14973,6 +14973,7 @@ dependencies = [ "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-utility", "frame-benchmarking", "frame-executive", diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml index 577ed749167..790f38d94f5 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/Cargo.toml @@ -56,6 +56,7 @@ cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-f cumulus-ping = { path = "../../../pallets/ping", default-features = false } cumulus-primitives-aura = { path = "../../../../primitives/aura", default-features = false } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } +cumulus-primitives-storage-weight-reclaim = { path = "../../../../primitives/storage-weight-reclaim", default-features = false } cumulus-primitives-utility = { path = "../../../../primitives/utility", default-features = false } parachains-common = { path = "../../../common", default-features = false } testnet-parachains-constants = { path = "../../constants", default-features = false, features = ["rococo"] } @@ -75,6 +76,7 @@ std = [ "cumulus-ping/std", "cumulus-primitives-aura/std", "cumulus-primitives-core/std", + "cumulus-primitives-storage-weight-reclaim/std", "cumulus-primitives-utility/std", "frame-benchmarking?/std", "frame-executive/std", diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 1b7efa6f400..b3bea4d4e65 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -653,6 +653,7 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = -- GitLab From 93b1abb280cf9d6c64f00b66c3593c2b04d50a9e Mon Sep 17 00:00:00 2001 From: gupnik Date: Thu, 21 Mar 2024 08:41:51 +0530 Subject: [PATCH 153/188] Migrates Westend to Runtime V2 (#3754) Step in https://github.com/paritytech/polkadot-sdk/issues/3688 --- polkadot/runtime/westend/Cargo.toml | 2 +- polkadot/runtime/westend/src/lib.rs | 321 +++++++++++++++++----------- prdoc/pr_3754.prdoc | 13 ++ 3 files changed, 211 insertions(+), 125 deletions(-) create mode 100644 prdoc/pr_3754.prdoc diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml index 4180828bcfb..fcead1dd0b5 100644 --- a/polkadot/runtime/westend/Cargo.toml +++ b/polkadot/runtime/westend/Cargo.toml @@ -45,7 +45,7 @@ sp-npos-elections = { path = "../../../substrate/primitives/npos-elections", def frame-election-provider-support = { path = "../../../substrate/frame/election-provider-support", default-features = false } frame-executive = { path = "../../../substrate/frame/executive", default-features = false } -frame-support = { path = "../../../substrate/frame/support", default-features = false, features = ["tuples-96"] } +frame-support = { path = "../../../substrate/frame/support", default-features = false, features = ["experimental", "tuples-96"] } frame-system = { path = "../../../substrate/frame/system", default-features = false } frame-system-rpc-runtime-api = { path = "../../../substrate/frame/system/rpc/runtime-api", default-features = false } westend-runtime-constants = { package = "westend-runtime-constants", path = "constants", default-features = false } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index f1d8841989c..62821cae7e4 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -17,7 +17,7 @@ //! The Westend runtime. This can be compiled with `#[no_std]`, ready for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit. +// `#[frame_support::runtime]!` does a lot of recursion and requires us to increase the limit. #![recursion_limit = "512"] use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; @@ -27,7 +27,7 @@ use beefy_primitives::{ }; use frame_election_provider_support::{bounds::ElectionBoundsBuilder, onchain, SequentialPhragmen}; use frame_support::{ - construct_runtime, derive_impl, + derive_impl, genesis_builder_helper::{build_config, create_default_config}, parameter_types, traits::{ @@ -1414,128 +1414,201 @@ impl pallet_asset_rate::Config for Runtime { type BenchmarkHelper = runtime_common::impls::benchmarks::AssetRateArguments; } -construct_runtime! { - pub enum Runtime - { - // Basic stuff; balances is uncallable initially. - System: frame_system = 0, - - // Babe must be before session. - Babe: pallet_babe = 1, - - Timestamp: pallet_timestamp = 2, - Indices: pallet_indices = 3, - Balances: pallet_balances = 4, - TransactionPayment: pallet_transaction_payment = 26, - - // Consensus support. - // Authorship must be before session in order to note author in the correct session and era. - Authorship: pallet_authorship = 5, - Staking: pallet_staking = 6, - Offences: pallet_offences = 7, - Historical: session_historical = 27, - - Session: pallet_session = 8, - Grandpa: pallet_grandpa = 10, - AuthorityDiscovery: pallet_authority_discovery = 12, - - // Utility module. - Utility: pallet_utility = 16, - - // Less simple identity module. - Identity: pallet_identity = 17, - - // Social recovery module. - Recovery: pallet_recovery = 18, - - // Vesting. Usable initially, but removed once all vesting is finished. - Vesting: pallet_vesting = 19, - - // System scheduler. - Scheduler: pallet_scheduler = 20, - - // Preimage registrar. - Preimage: pallet_preimage = 28, - - // Sudo. - Sudo: pallet_sudo = 21, - - // Proxy module. Late addition. - Proxy: pallet_proxy = 22, - - // Multisig module. Late addition. - Multisig: pallet_multisig = 23, - - // Election pallet. Only works with staking, but placed here to maintain indices. - ElectionProviderMultiPhase: pallet_election_provider_multi_phase = 24, - - // Provides a semi-sorted list of nominators for staking. - VoterList: pallet_bags_list:: = 25, - - // Nomination pools for staking. - NominationPools: pallet_nomination_pools = 29, - - // Fast unstake pallet: extension to staking. - FastUnstake: pallet_fast_unstake = 30, - - // OpenGov - ConvictionVoting: pallet_conviction_voting = 31, - Referenda: pallet_referenda = 32, - Origins: pallet_custom_origins = 35, - Whitelist: pallet_whitelist = 36, - - // Treasury - Treasury: pallet_treasury = 37, - - // Parachains pallets. Start indices at 40 to leave room. - ParachainsOrigin: parachains_origin = 41, - Configuration: parachains_configuration = 42, - ParasShared: parachains_shared = 43, - ParaInclusion: parachains_inclusion = 44, - ParaInherent: parachains_paras_inherent = 45, - ParaScheduler: parachains_scheduler = 46, - Paras: parachains_paras = 47, - Initializer: parachains_initializer = 48, - Dmp: parachains_dmp = 49, - // RIP Ump 50 - Hrmp: parachains_hrmp = 51, - ParaSessionInfo: parachains_session_info = 52, - ParasDisputes: parachains_disputes = 53, - ParasSlashing: parachains_slashing = 54, - OnDemandAssignmentProvider: parachains_assigner_on_demand = 56, - CoretimeAssignmentProvider: parachains_assigner_coretime = 57, - - // Parachain Onboarding Pallets. Start indices at 60 to leave room. - Registrar: paras_registrar = 60, - Slots: slots = 61, - ParasSudoWrapper: paras_sudo_wrapper = 62, - Auctions: auctions = 63, - Crowdloan: crowdloan = 64, - AssignedSlots: assigned_slots = 65, - Coretime: coretime = 66, - - // Pallet for sending XCM. - XcmPallet: pallet_xcm = 99, - - // Generalized message queue - MessageQueue: pallet_message_queue = 100, - - // Asset rate. - AssetRate: pallet_asset_rate = 101, - - // Root testing pallet. - RootTesting: pallet_root_testing = 102, - - // BEEFY Bridges support. - Beefy: pallet_beefy = 200, - // MMR leaf construction must be after session in order to have a leaf's next_auth_set - // refer to block. See issue polkadot-fellows/runtimes#160 for details. - Mmr: pallet_mmr = 201, - BeefyMmrLeaf: pallet_beefy_mmr = 202, - - // Pallet for migrating Identity to a parachain. To be removed post-migration. - IdentityMigrator: identity_migrator = 248, - } +#[frame_support::runtime(legacy_ordering)] +mod runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + // Basic stuff; balances is uncallable initially. + #[runtime::pallet_index(0)] + pub type System = frame_system; + + // Babe must be before session. + #[runtime::pallet_index(1)] + pub type Babe = pallet_babe; + + #[runtime::pallet_index(2)] + pub type Timestamp = pallet_timestamp; + #[runtime::pallet_index(3)] + pub type Indices = pallet_indices; + #[runtime::pallet_index(4)] + pub type Balances = pallet_balances; + #[runtime::pallet_index(26)] + pub type TransactionPayment = pallet_transaction_payment; + + // Consensus support. + // Authorship must be before session in order to note author in the correct session and era. + #[runtime::pallet_index(5)] + pub type Authorship = pallet_authorship; + #[runtime::pallet_index(6)] + pub type Staking = pallet_staking; + #[runtime::pallet_index(7)] + pub type Offences = pallet_offences; + #[runtime::pallet_index(27)] + pub type Historical = session_historical; + + #[runtime::pallet_index(8)] + pub type Session = pallet_session; + #[runtime::pallet_index(10)] + pub type Grandpa = pallet_grandpa; + #[runtime::pallet_index(12)] + pub type AuthorityDiscovery = pallet_authority_discovery; + + // Utility module. + #[runtime::pallet_index(16)] + pub type Utility = pallet_utility; + + // Less simple identity module. + #[runtime::pallet_index(17)] + pub type Identity = pallet_identity; + + // Social recovery module. + #[runtime::pallet_index(18)] + pub type Recovery = pallet_recovery; + + // Vesting. Usable initially, but removed once all vesting is finished. + #[runtime::pallet_index(19)] + pub type Vesting = pallet_vesting; + + // System scheduler. + #[runtime::pallet_index(20)] + pub type Scheduler = pallet_scheduler; + + // Preimage registrar. + #[runtime::pallet_index(28)] + pub type Preimage = pallet_preimage; + + // Sudo. + #[runtime::pallet_index(21)] + pub type Sudo = pallet_sudo; + + // Proxy module. Late addition. + #[runtime::pallet_index(22)] + pub type Proxy = pallet_proxy; + + // Multisig module. Late addition. + #[runtime::pallet_index(23)] + pub type Multisig = pallet_multisig; + + // Election pallet. Only works with staking, but placed here to maintain indices. + #[runtime::pallet_index(24)] + pub type ElectionProviderMultiPhase = pallet_election_provider_multi_phase; + + // Provides a semi-sorted list of nominators for staking. + #[runtime::pallet_index(25)] + pub type VoterList = pallet_bags_list; + + // Nomination pools for staking. + #[runtime::pallet_index(29)] + pub type NominationPools = pallet_nomination_pools; + + // Fast unstake pallet = extension to staking. + #[runtime::pallet_index(30)] + pub type FastUnstake = pallet_fast_unstake; + + // OpenGov + #[runtime::pallet_index(31)] + pub type ConvictionVoting = pallet_conviction_voting; + #[runtime::pallet_index(32)] + pub type Referenda = pallet_referenda; + #[runtime::pallet_index(35)] + pub type Origins = pallet_custom_origins; + #[runtime::pallet_index(36)] + pub type Whitelist = pallet_whitelist; + + // Treasury + #[runtime::pallet_index(37)] + pub type Treasury = pallet_treasury; + + // Parachains pallets. Start indices at 40 to leave room. + #[runtime::pallet_index(41)] + pub type ParachainsOrigin = parachains_origin; + #[runtime::pallet_index(42)] + pub type Configuration = parachains_configuration; + #[runtime::pallet_index(43)] + pub type ParasShared = parachains_shared; + #[runtime::pallet_index(44)] + pub type ParaInclusion = parachains_inclusion; + #[runtime::pallet_index(45)] + pub type ParaInherent = parachains_paras_inherent; + #[runtime::pallet_index(46)] + pub type ParaScheduler = parachains_scheduler; + #[runtime::pallet_index(47)] + pub type Paras = parachains_paras; + #[runtime::pallet_index(48)] + pub type Initializer = parachains_initializer; + #[runtime::pallet_index(49)] + pub type Dmp = parachains_dmp; + // RIP Ump 50 + #[runtime::pallet_index(51)] + pub type Hrmp = parachains_hrmp; + #[runtime::pallet_index(52)] + pub type ParaSessionInfo = parachains_session_info; + #[runtime::pallet_index(53)] + pub type ParasDisputes = parachains_disputes; + #[runtime::pallet_index(54)] + pub type ParasSlashing = parachains_slashing; + #[runtime::pallet_index(56)] + pub type OnDemandAssignmentProvider = parachains_assigner_on_demand; + #[runtime::pallet_index(57)] + pub type CoretimeAssignmentProvider = parachains_assigner_coretime; + + // Parachain Onboarding Pallets. Start indices at 60 to leave room. + #[runtime::pallet_index(60)] + pub type Registrar = paras_registrar; + #[runtime::pallet_index(61)] + pub type Slots = slots; + #[runtime::pallet_index(62)] + pub type ParasSudoWrapper = paras_sudo_wrapper; + #[runtime::pallet_index(63)] + pub type Auctions = auctions; + #[runtime::pallet_index(64)] + pub type Crowdloan = crowdloan; + #[runtime::pallet_index(65)] + pub type AssignedSlots = assigned_slots; + #[runtime::pallet_index(66)] + pub type Coretime = coretime; + + // Pallet for sending XCM. + #[runtime::pallet_index(99)] + pub type XcmPallet = pallet_xcm; + + // Generalized message queue + #[runtime::pallet_index(100)] + pub type MessageQueue = pallet_message_queue; + + // Asset rate. + #[runtime::pallet_index(101)] + pub type AssetRate = pallet_asset_rate; + + // Root testing pallet. + #[runtime::pallet_index(102)] + pub type RootTesting = pallet_root_testing; + + // BEEFY Bridges support. + #[runtime::pallet_index(200)] + pub type Beefy = pallet_beefy; + // MMR leaf construction must be after session in order to have a leaf's next_auth_set + // refer to block. See issue polkadot-fellows/runtimes#160 for details. + #[runtime::pallet_index(201)] + pub type Mmr = pallet_mmr; + #[runtime::pallet_index(202)] + pub type BeefyMmrLeaf = pallet_beefy_mmr; + + // Pallet for migrating Identity to a parachain. To be removed post-migration. + #[runtime::pallet_index(248)] + pub type IdentityMigrator = identity_migrator; } /// The address format for describing accounts. diff --git a/prdoc/pr_3754.prdoc b/prdoc/pr_3754.prdoc new file mode 100644 index 00000000000..94ea6d56608 --- /dev/null +++ b/prdoc/pr_3754.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Migrates Westend to Runtime V2 + +doc: + - audience: Runtime Dev + description: | + This PR migrates Westend from `construct_runtime` to Runtime V2 + as introduced in https://github.com/paritytech/polkadot-sdk/pull/1378 + +crates: + - name: westend-runtime -- GitLab From 7b6b061e32f65b92574deaf8c199855e2c59d4c6 Mon Sep 17 00:00:00 2001 From: Egor_P Date: Thu, 21 Mar 2024 10:00:10 +0100 Subject: [PATCH 154/188] [Backport] version bumps and prdocs reordering 1.9.0 (#3758) This PR backports: - node version bump - `spec_vesion` bump - reordering of the `prdocs` to the appropriate folder from the `1.9.0` release branch --- .../parachains/runtimes/assets/asset-hub-rococo/src/lib.rs | 4 ++-- .../parachains/runtimes/assets/asset-hub-westend/src/lib.rs | 2 +- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 2 +- .../runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs | 2 +- .../runtimes/collectives/collectives-westend/src/lib.rs | 2 +- .../parachains/runtimes/contracts/contracts-rococo/src/lib.rs | 2 +- .../parachains/runtimes/coretime/coretime-rococo/src/lib.rs | 2 +- .../parachains/runtimes/coretime/coretime-westend/src/lib.rs | 2 +- .../parachains/runtimes/glutton/glutton-westend/src/lib.rs | 2 +- cumulus/parachains/runtimes/people/people-rococo/src/lib.rs | 2 +- cumulus/parachains/runtimes/people/people-westend/src/lib.rs | 2 +- .../parachains/runtimes/testing/rococo-parachain/src/lib.rs | 2 +- polkadot/node/primitives/src/lib.rs | 2 +- polkadot/runtime/rococo/src/lib.rs | 2 +- polkadot/runtime/westend/src/lib.rs | 2 +- prdoc/{ => 1.9.0}/pr_1378.prdoc | 0 prdoc/{ => 1.9.0}/pr_1554.prdoc | 0 prdoc/{ => 1.9.0}/pr_1781.prdoc | 0 prdoc/{ => 1.9.0}/pr_2393.prdoc | 0 prdoc/{ => 1.9.0}/pr_3002.prdoc | 0 prdoc/{ => 1.9.0}/pr_3187.prdoc | 0 prdoc/{ => 1.9.0}/pr_3231.prdoc | 0 prdoc/{ => 1.9.0}/pr_3233.prdoc | 0 prdoc/{ => 1.9.0}/pr_3324.prdoc | 0 prdoc/{ => 1.9.0}/pr_3371.prdoc | 0 prdoc/{ => 1.9.0}/pr_3377.prdoc | 0 prdoc/{ => 1.9.0}/pr_3378.prdoc | 0 prdoc/{ => 1.9.0}/pr_3403.prdoc | 0 prdoc/{ => 1.9.0}/pr_3411.prdoc | 0 prdoc/{ => 1.9.0}/pr_3412.prdoc | 0 prdoc/{ => 1.9.0}/pr_3447.prdoc | 0 prdoc/{ => 1.9.0}/pr_3453.prdoc | 0 prdoc/{ => 1.9.0}/pr_3454.prdoc | 0 prdoc/{ => 1.9.0}/pr_3456.prdoc | 0 prdoc/{ => 1.9.0}/pr_3460.prdoc | 0 prdoc/{ => 1.9.0}/pr_3491.prdoc | 0 prdoc/{ => 1.9.0}/pr_3504.prdoc | 0 prdoc/{ => 1.9.0}/pr_3505.prdoc | 0 prdoc/{ => 1.9.0}/pr_3510.prdoc | 0 prdoc/{ => 1.9.0}/pr_3513.prdoc | 0 prdoc/{ => 1.9.0}/pr_3523.prdoc | 0 prdoc/{ => 1.9.0}/pr_3532.prdoc | 0 prdoc/{ => 1.9.0}/pr_3540.prdoc | 0 prdoc/{ => 1.9.0}/pr_3574.prdoc | 0 prdoc/{ => 1.9.0}/pr_3589.prdoc | 0 prdoc/{ => 1.9.0}/pr_3606.prdoc | 0 prdoc/{ => 1.9.0}/pr_3636.prdoc | 0 prdoc/{ => 1.9.0}/pr_3639.prdoc | 0 prdoc/{ => 1.9.0}/pr_3643.prdoc | 0 prdoc/{ => 1.9.0}/pr_3665.prdoc | 0 50 files changed, 16 insertions(+), 16 deletions(-) rename prdoc/{ => 1.9.0}/pr_1378.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_1554.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_1781.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_2393.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3002.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3187.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3231.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3233.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3324.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3371.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3377.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3378.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3403.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3411.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3412.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3447.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3453.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3454.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3456.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3460.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3491.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3504.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3505.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3510.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3513.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3523.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3532.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3540.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3574.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3589.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3606.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3636.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3639.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3643.prdoc (100%) rename prdoc/{ => 1.9.0}/pr_3665.prdoc (100%) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index d3d8a495ea3..689d8d56c48 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -113,7 +113,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemine"), impl_name: create_runtime_str!("statemine"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 14, @@ -126,7 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("statemine"), impl_name: create_runtime_str!("statemine"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 14, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 711fadff92a..48106b5f302 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -110,7 +110,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("westmint"), impl_name: create_runtime_str!("westmint"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 14, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index bbafcd3c7dd..bf7483179f2 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -202,7 +202,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bridge-hub-rococo"), impl_name: create_runtime_str!("bridge-hub-rococo"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 4, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 11ab9aecc61..9bdea6b9a7d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -176,7 +176,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bridge-hub-westend"), impl_name: create_runtime_str!("bridge-hub-westend"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 4, diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 55269283e08..d3f588bf25f 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -117,7 +117,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("collectives-westend"), impl_name: create_runtime_str!("collectives-westend"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 5, diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 17bb45f6b1b..e1586c7d9b2 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -133,7 +133,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("contracts-rococo"), impl_name: create_runtime_str!("contracts-rococo"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 6, diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 26add2ee942..86eb5cdfcaf 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -133,7 +133,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("coretime-rococo"), impl_name: create_runtime_str!("coretime-rococo"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0, diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 76732c3fccc..c31e474cc2f 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -133,7 +133,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("coretime-westend"), impl_name: create_runtime_str!("coretime-westend"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0, diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index fe18f48fbb3..cee17cdc7b0 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -100,7 +100,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("glutton-westend"), impl_name: create_runtime_str!("glutton-westend"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 2bb5641b4af..ad369583f07 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -126,7 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("people-rococo"), impl_name: create_runtime_str!("people-rococo"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0, diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index b81f7a9c969..c76611ad2a3 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -126,7 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("people-westend"), impl_name: create_runtime_str!("people-westend"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 0, diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index b3bea4d4e65..c6006141981 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -107,7 +107,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("test-parachain"), impl_name: create_runtime_str!("test-parachain"), authoring_version: 1, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 6, diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index d295c21cce1..b6556e0be56 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -58,7 +58,7 @@ pub use disputes::{ /// relatively rare. /// /// The associated worker binaries should use the same version as the node that spawns them. -pub const NODE_VERSION: &'static str = "1.8.0"; +pub const NODE_VERSION: &'static str = "1.9.0"; // For a 16-ary Merkle Prefix Trie, we can expect at most 16 32-byte hashes per node // plus some overhead: diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index a773eeb5cbd..c9f5d81d286 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -149,7 +149,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("rococo"), impl_name: create_runtime_str!("parity-rococo-v2.0"), authoring_version: 0, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 24, diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 62821cae7e4..83d47508c7c 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -150,7 +150,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("westend"), impl_name: create_runtime_str!("parity-westend"), authoring_version: 2, - spec_version: 1_008_000, + spec_version: 1_009_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 24, diff --git a/prdoc/pr_1378.prdoc b/prdoc/1.9.0/pr_1378.prdoc similarity index 100% rename from prdoc/pr_1378.prdoc rename to prdoc/1.9.0/pr_1378.prdoc diff --git a/prdoc/pr_1554.prdoc b/prdoc/1.9.0/pr_1554.prdoc similarity index 100% rename from prdoc/pr_1554.prdoc rename to prdoc/1.9.0/pr_1554.prdoc diff --git a/prdoc/pr_1781.prdoc b/prdoc/1.9.0/pr_1781.prdoc similarity index 100% rename from prdoc/pr_1781.prdoc rename to prdoc/1.9.0/pr_1781.prdoc diff --git a/prdoc/pr_2393.prdoc b/prdoc/1.9.0/pr_2393.prdoc similarity index 100% rename from prdoc/pr_2393.prdoc rename to prdoc/1.9.0/pr_2393.prdoc diff --git a/prdoc/pr_3002.prdoc b/prdoc/1.9.0/pr_3002.prdoc similarity index 100% rename from prdoc/pr_3002.prdoc rename to prdoc/1.9.0/pr_3002.prdoc diff --git a/prdoc/pr_3187.prdoc b/prdoc/1.9.0/pr_3187.prdoc similarity index 100% rename from prdoc/pr_3187.prdoc rename to prdoc/1.9.0/pr_3187.prdoc diff --git a/prdoc/pr_3231.prdoc b/prdoc/1.9.0/pr_3231.prdoc similarity index 100% rename from prdoc/pr_3231.prdoc rename to prdoc/1.9.0/pr_3231.prdoc diff --git a/prdoc/pr_3233.prdoc b/prdoc/1.9.0/pr_3233.prdoc similarity index 100% rename from prdoc/pr_3233.prdoc rename to prdoc/1.9.0/pr_3233.prdoc diff --git a/prdoc/pr_3324.prdoc b/prdoc/1.9.0/pr_3324.prdoc similarity index 100% rename from prdoc/pr_3324.prdoc rename to prdoc/1.9.0/pr_3324.prdoc diff --git a/prdoc/pr_3371.prdoc b/prdoc/1.9.0/pr_3371.prdoc similarity index 100% rename from prdoc/pr_3371.prdoc rename to prdoc/1.9.0/pr_3371.prdoc diff --git a/prdoc/pr_3377.prdoc b/prdoc/1.9.0/pr_3377.prdoc similarity index 100% rename from prdoc/pr_3377.prdoc rename to prdoc/1.9.0/pr_3377.prdoc diff --git a/prdoc/pr_3378.prdoc b/prdoc/1.9.0/pr_3378.prdoc similarity index 100% rename from prdoc/pr_3378.prdoc rename to prdoc/1.9.0/pr_3378.prdoc diff --git a/prdoc/pr_3403.prdoc b/prdoc/1.9.0/pr_3403.prdoc similarity index 100% rename from prdoc/pr_3403.prdoc rename to prdoc/1.9.0/pr_3403.prdoc diff --git a/prdoc/pr_3411.prdoc b/prdoc/1.9.0/pr_3411.prdoc similarity index 100% rename from prdoc/pr_3411.prdoc rename to prdoc/1.9.0/pr_3411.prdoc diff --git a/prdoc/pr_3412.prdoc b/prdoc/1.9.0/pr_3412.prdoc similarity index 100% rename from prdoc/pr_3412.prdoc rename to prdoc/1.9.0/pr_3412.prdoc diff --git a/prdoc/pr_3447.prdoc b/prdoc/1.9.0/pr_3447.prdoc similarity index 100% rename from prdoc/pr_3447.prdoc rename to prdoc/1.9.0/pr_3447.prdoc diff --git a/prdoc/pr_3453.prdoc b/prdoc/1.9.0/pr_3453.prdoc similarity index 100% rename from prdoc/pr_3453.prdoc rename to prdoc/1.9.0/pr_3453.prdoc diff --git a/prdoc/pr_3454.prdoc b/prdoc/1.9.0/pr_3454.prdoc similarity index 100% rename from prdoc/pr_3454.prdoc rename to prdoc/1.9.0/pr_3454.prdoc diff --git a/prdoc/pr_3456.prdoc b/prdoc/1.9.0/pr_3456.prdoc similarity index 100% rename from prdoc/pr_3456.prdoc rename to prdoc/1.9.0/pr_3456.prdoc diff --git a/prdoc/pr_3460.prdoc b/prdoc/1.9.0/pr_3460.prdoc similarity index 100% rename from prdoc/pr_3460.prdoc rename to prdoc/1.9.0/pr_3460.prdoc diff --git a/prdoc/pr_3491.prdoc b/prdoc/1.9.0/pr_3491.prdoc similarity index 100% rename from prdoc/pr_3491.prdoc rename to prdoc/1.9.0/pr_3491.prdoc diff --git a/prdoc/pr_3504.prdoc b/prdoc/1.9.0/pr_3504.prdoc similarity index 100% rename from prdoc/pr_3504.prdoc rename to prdoc/1.9.0/pr_3504.prdoc diff --git a/prdoc/pr_3505.prdoc b/prdoc/1.9.0/pr_3505.prdoc similarity index 100% rename from prdoc/pr_3505.prdoc rename to prdoc/1.9.0/pr_3505.prdoc diff --git a/prdoc/pr_3510.prdoc b/prdoc/1.9.0/pr_3510.prdoc similarity index 100% rename from prdoc/pr_3510.prdoc rename to prdoc/1.9.0/pr_3510.prdoc diff --git a/prdoc/pr_3513.prdoc b/prdoc/1.9.0/pr_3513.prdoc similarity index 100% rename from prdoc/pr_3513.prdoc rename to prdoc/1.9.0/pr_3513.prdoc diff --git a/prdoc/pr_3523.prdoc b/prdoc/1.9.0/pr_3523.prdoc similarity index 100% rename from prdoc/pr_3523.prdoc rename to prdoc/1.9.0/pr_3523.prdoc diff --git a/prdoc/pr_3532.prdoc b/prdoc/1.9.0/pr_3532.prdoc similarity index 100% rename from prdoc/pr_3532.prdoc rename to prdoc/1.9.0/pr_3532.prdoc diff --git a/prdoc/pr_3540.prdoc b/prdoc/1.9.0/pr_3540.prdoc similarity index 100% rename from prdoc/pr_3540.prdoc rename to prdoc/1.9.0/pr_3540.prdoc diff --git a/prdoc/pr_3574.prdoc b/prdoc/1.9.0/pr_3574.prdoc similarity index 100% rename from prdoc/pr_3574.prdoc rename to prdoc/1.9.0/pr_3574.prdoc diff --git a/prdoc/pr_3589.prdoc b/prdoc/1.9.0/pr_3589.prdoc similarity index 100% rename from prdoc/pr_3589.prdoc rename to prdoc/1.9.0/pr_3589.prdoc diff --git a/prdoc/pr_3606.prdoc b/prdoc/1.9.0/pr_3606.prdoc similarity index 100% rename from prdoc/pr_3606.prdoc rename to prdoc/1.9.0/pr_3606.prdoc diff --git a/prdoc/pr_3636.prdoc b/prdoc/1.9.0/pr_3636.prdoc similarity index 100% rename from prdoc/pr_3636.prdoc rename to prdoc/1.9.0/pr_3636.prdoc diff --git a/prdoc/pr_3639.prdoc b/prdoc/1.9.0/pr_3639.prdoc similarity index 100% rename from prdoc/pr_3639.prdoc rename to prdoc/1.9.0/pr_3639.prdoc diff --git a/prdoc/pr_3643.prdoc b/prdoc/1.9.0/pr_3643.prdoc similarity index 100% rename from prdoc/pr_3643.prdoc rename to prdoc/1.9.0/pr_3643.prdoc diff --git a/prdoc/pr_3665.prdoc b/prdoc/1.9.0/pr_3665.prdoc similarity index 100% rename from prdoc/pr_3665.prdoc rename to prdoc/1.9.0/pr_3665.prdoc -- GitLab From 75074952a859f90213ea25257b71ec2189dbcfc1 Mon Sep 17 00:00:00 2001 From: Egor_P Date: Thu, 21 Mar 2024 10:00:40 +0100 Subject: [PATCH 155/188] [Backport] Reformat release notes generation (#3759) This PR backports small reformatting of the release notes templates. --- scripts/release/build-changelogs.sh | 1 + scripts/release/templates/audience.md.tera | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/release/build-changelogs.sh b/scripts/release/build-changelogs.sh index a9275f45a50..cbfb7ad0e48 100755 --- a/scripts/release/build-changelogs.sh +++ b/scripts/release/build-changelogs.sh @@ -48,6 +48,7 @@ for audience in "${audiences[@]}"; do echo "Processing audience: $audience ($audience_id)" export TARGET_AUDIENCE=$audience tera -t "${TEMPLATE_AUDIENCE}" --env --env-key env "${CONTEXT_JSON}" > "$OUTPUT/relnote_${audience_id}.md" + cat "$OUTPUT/relnote_${audience_id}.md" >> "$OUTPUT/relnote_combined.md" done # Show the files diff --git a/scripts/release/templates/audience.md.tera b/scripts/release/templates/audience.md.tera index dc507053dd5..0b47850e3a3 100644 --- a/scripts/release/templates/audience.md.tera +++ b/scripts/release/templates/audience.md.tera @@ -1,11 +1,9 @@ -## Release {{ env.PRODUCT }} {{ env.VERSION }} - -Changelog for `{{ env.TARGET_AUDIENCE }}`. +### Changelog for `{{ env.TARGET_AUDIENCE }}` {% for file in prdoc -%} -#### PR #{{file.doc_filename.number}}: {{ file.content.title }} {% for doc_item in file.content.doc %} {%- if doc_item.audience == env.TARGET_AUDIENCE %} +#### [#{{file.doc_filename.number}}]: {{ file.content.title }} {{ doc_item.description }} {% endif -%} -- GitLab From 4842faf65d3628586d304fbcb6cb19b17b4a629c Mon Sep 17 00:00:00 2001 From: Alin Dima Date: Thu, 21 Mar 2024 12:10:45 +0200 Subject: [PATCH 156/188] Elastic scaling: runtime dependency tracking and enactment (#3479) Changes needed to implement the runtime part of elastic scaling: https://github.com/paritytech/polkadot-sdk/issues/3131, https://github.com/paritytech/polkadot-sdk/issues/3132, https://github.com/paritytech/polkadot-sdk/issues/3202 Also fixes https://github.com/paritytech/polkadot-sdk/issues/3675 TODOs: - [x] storage migration - [x] optimise process_candidates from O(N^2) - [x] drop backable candidates which form cycles - [x] fix unit tests - [x] add more unit tests - [x] check the runtime APIs which use the pending availability storage. We need to expose all of them, see https://github.com/paritytech/polkadot-sdk/issues/3576 - [x] optimise the candidate selection. we're currently picking randomly until we satisfy the weight limit. we need to be smart about not breaking candidate chains while being fair to all paras - https://github.com/paritytech/polkadot-sdk/pull/3573 Relies on the changes made in https://github.com/paritytech/polkadot-sdk/pull/3233 in terms of the inclusion policy and the candidate ordering --------- Signed-off-by: alindima Co-authored-by: command-bot <> Co-authored-by: eskimor --- .../src/runtime/inclusion.md | 11 +- .../src/runtime/parainherent.md | 2 +- .../src/runtime/scheduler.md | 1 - polkadot/runtime/parachains/src/builder.rs | 109 +- .../parachains/src/inclusion/migration.rs | 317 ++++ .../runtime/parachains/src/inclusion/mod.rs | 803 ++++----- .../runtime/parachains/src/inclusion/tests.rs | 1241 ++++++++----- .../src/paras_inherent/benchmarking.rs | 8 - .../parachains/src/paras_inherent/mod.rs | 599 +++--- .../parachains/src/paras_inherent/tests.rs | 1604 +++++++++++++++-- .../parachains/src/runtime_api_impl/v7.rs | 84 +- polkadot/runtime/parachains/src/scheduler.rs | 10 - polkadot/runtime/parachains/src/util.rs | 19 +- polkadot/runtime/rococo/src/lib.rs | 2 + .../runtime_parachains_paras_inherent.rs | 421 +++-- polkadot/runtime/westend/src/lib.rs | 1 + .../runtime_parachains_paras_inherent.rs | 583 +++--- prdoc/pr_3479.prdoc | 8 + 18 files changed, 4075 insertions(+), 1748 deletions(-) create mode 100644 polkadot/runtime/parachains/src/inclusion/migration.rs create mode 100644 prdoc/pr_3479.prdoc diff --git a/polkadot/roadmap/implementers-guide/src/runtime/inclusion.md b/polkadot/roadmap/implementers-guide/src/runtime/inclusion.md index f6a32a01d50..fd74f33253b 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/inclusion.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/inclusion.md @@ -147,15 +147,16 @@ All failed checks should lead to an unrecoverable error making the block invalid // return a vector of cleaned-up core IDs. } ``` -* `force_enact(ParaId)`: Forcibly enact the candidate with the given ID as though it had been deemed available by - bitfields. Is a no-op if there is no candidate pending availability for this para-id. This should generally not be - used but it is useful during execution of Runtime APIs, where the changes to the state are expected to be discarded - directly after. +* `force_enact(ParaId)`: Forcibly enact the pending candidates of the given paraid as though they had been deemed + available by bitfields. Is a no-op if there is no candidate pending availability for this para-id. + If there are multiple candidates pending availability for this para-id, it will enact all of + them. This should generally not be used but it is useful during execution of Runtime APIs, + where the changes to the state are expected to be discarded directly after. * `candidate_pending_availability(ParaId) -> Option`: returns the `CommittedCandidateReceipt` pending availability for the para provided, if any. * `pending_availability(ParaId) -> Option`: returns the metadata around the candidate pending availability for the para, if any. -* `collect_disputed(disputed: Vec) -> Vec`: Sweeps through all paras pending availability. If +* `free_disputed(disputed: Vec) -> Vec`: Sweeps through all paras pending availability. If the candidate hash is one of the disputed candidates, then clean up the corresponding storage for that candidate and the commitments. Return a vector of cleaned-up core IDs. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md b/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md index 5419ddae83d..1345f0eea95 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md @@ -17,7 +17,7 @@ There are a couple of important notes to the operations in this inherent as they this fork. 1. When disputes are initiated, we remove the block from pending availability. This allows us to roll back chains to the block before blocks are included as opposed to backing. It's important to do this before processing bitfields. -1. `Inclusion::collect_disputed` is kind of expensive so it's important to gate this on whether there are actually any +1. `Inclusion::free_disputed` is kind of expensive so it's important to gate this on whether there are actually any new disputes. Which should be never. 1. And we don't accept parablocks that have open disputes or disputes that have concluded against the candidate. It's important to import dispute statements before backing, but this is already the case as disputes are imported before diff --git a/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md b/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md index 32a7fe652db..04b221a83e5 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md @@ -285,7 +285,6 @@ No finalization routine runs for this module. - This clears them from `Scheduled` and marks each corresponding `core` in the `AvailabilityCores` as occupied. - Since both the availability cores and the newly-occupied cores lists are sorted ascending, this method can be implemented efficiently. -- `core_para(CoreIndex) -> ParaId`: return the currently-scheduled or occupied ParaId for the given core. - `group_validators(GroupIndex) -> Option>`: return all validators in a given group, if the group index is valid for this session. - `availability_timeout_predicate() -> Option bool>`: returns an optional predicate diff --git a/polkadot/runtime/parachains/src/builder.rs b/polkadot/runtime/parachains/src/builder.rs index 05f6845f3b7..73617010f6d 100644 --- a/polkadot/runtime/parachains/src/builder.rs +++ b/polkadot/runtime/parachains/src/builder.rs @@ -40,7 +40,7 @@ use sp_runtime::{ RuntimeAppPublic, }; use sp_std::{ - collections::{btree_map::BTreeMap, vec_deque::VecDeque}, + collections::{btree_map::BTreeMap, btree_set::BTreeSet, vec_deque::VecDeque}, prelude::Vec, vec, }; @@ -104,6 +104,8 @@ pub(crate) struct BenchBuilder { code_upgrade: Option, /// Specifies whether the claimqueue should be filled. fill_claimqueue: bool, + /// Cores which should not be available when being populated with pending candidates. + unavailable_cores: Vec, _phantom: sp_std::marker::PhantomData, } @@ -133,6 +135,7 @@ impl BenchBuilder { elastic_paras: Default::default(), code_upgrade: None, fill_claimqueue: true, + unavailable_cores: vec![], _phantom: sp_std::marker::PhantomData::, } } @@ -149,6 +152,12 @@ impl BenchBuilder { self } + /// Set the cores which should not be available when being populated with pending candidates. + pub(crate) fn set_unavailable_cores(mut self, unavailable_cores: Vec) -> Self { + self.unavailable_cores = unavailable_cores; + self + } + /// Set a map from para id seed to number of validity votes. pub(crate) fn set_backed_and_concluding_paras( mut self, @@ -159,7 +168,6 @@ impl BenchBuilder { } /// Set a map from para id seed to number of cores assigned to it. - #[cfg(feature = "runtime-benchmarks")] pub(crate) fn set_elastic_paras(mut self, elastic_paras: BTreeMap) -> Self { self.elastic_paras = elastic_paras; self @@ -284,11 +292,13 @@ impl BenchBuilder { core_idx: CoreIndex, candidate_hash: CandidateHash, availability_votes: BitVec, + commitments: CandidateCommitments, ) -> inclusion::CandidatePendingAvailability> { inclusion::CandidatePendingAvailability::>::new( core_idx, // core candidate_hash, // hash Self::candidate_descriptor_mock(), // candidate descriptor + commitments, // commitments availability_votes, // availability votes Default::default(), // backers Zero::zero(), // relay parent @@ -309,12 +319,6 @@ impl BenchBuilder { availability_votes: BitVec, candidate_hash: CandidateHash, ) { - let candidate_availability = Self::candidate_availability_mock( - group_idx, - core_idx, - candidate_hash, - availability_votes, - ); let commitments = CandidateCommitments:: { upward_messages: Default::default(), horizontal_messages: Default::default(), @@ -323,16 +327,29 @@ impl BenchBuilder { processed_downward_messages: 0, hrmp_watermark: 0u32.into(), }; - inclusion::PendingAvailability::::insert(para_id, candidate_availability); - inclusion::PendingAvailabilityCommitments::::insert(¶_id, commitments); + let candidate_availability = Self::candidate_availability_mock( + group_idx, + core_idx, + candidate_hash, + availability_votes, + commitments, + ); + inclusion::PendingAvailability::::mutate(para_id, |maybe_andidates| { + if let Some(candidates) = maybe_andidates { + candidates.push_back(candidate_availability); + } else { + *maybe_andidates = + Some([candidate_availability].into_iter().collect::>()); + } + }); } /// Create an `AvailabilityBitfield` where `concluding` is a map where each key is a core index /// that is concluding and `cores` is the total number of cores in the system. - fn availability_bitvec(concluding: &BTreeMap, cores: usize) -> AvailabilityBitfield { + fn availability_bitvec(concluding_cores: &BTreeSet, cores: usize) -> AvailabilityBitfield { let mut bitfields = bitvec::bitvec![u8, bitvec::order::Lsb0; 0; 0]; for i in 0..cores { - if concluding.get(&(i as u32)).is_some() { + if concluding_cores.contains(&(i as u32)) { bitfields.push(true); } else { bitfields.push(false) @@ -356,13 +373,13 @@ impl BenchBuilder { } } - /// Register `cores` count of parachains. + /// Register `n_paras` count of parachains. /// /// Note that this must be called at least 2 sessions before the target session as there is a /// n+2 session delay for the scheduled actions to take effect. - fn setup_para_ids(cores: usize) { + fn setup_para_ids(n_paras: usize) { // make sure parachains exist prior to session change. - for i in 0..cores { + for i in 0..n_paras { let para_id = ParaId::from(i as u32); let validation_code = mock_validation_code(); @@ -472,24 +489,8 @@ impl BenchBuilder { let validators = self.validators.as_ref().expect("must have some validators prior to calling"); - let availability_bitvec = Self::availability_bitvec(concluding_paras, total_cores); - - let bitfields: Vec> = validators - .iter() - .enumerate() - .map(|(i, public)| { - let unchecked_signed = UncheckedSigned::::benchmark_sign( - public, - availability_bitvec.clone(), - &self.signing_context(), - ValidatorIndex(i as u32), - ); - - unchecked_signed - }) - .collect(); - let mut current_core_idx = 0u32; + let mut concluding_cores = BTreeSet::new(); for (seed, _) in concluding_paras.iter() { // make sure the candidates that will be concluding are marked as pending availability. @@ -505,13 +506,34 @@ impl BenchBuilder { para_id, core_idx, group_idx, - Self::validator_availability_votes_yes(validators.len()), + // No validators have made this candidate available yet. + bitvec::bitvec![u8, bitvec::order::Lsb0; 0; validators.len()], CandidateHash(H256::from(byte32_slice_from(current_core_idx))), ); + if !self.unavailable_cores.contains(¤t_core_idx) { + concluding_cores.insert(current_core_idx); + } current_core_idx += 1; } } + let availability_bitvec = Self::availability_bitvec(&concluding_cores, total_cores); + + let bitfields: Vec> = validators + .iter() + .enumerate() + .map(|(i, public)| { + let unchecked_signed = UncheckedSigned::::benchmark_sign( + public, + availability_bitvec.clone(), + &self.signing_context(), + ValidatorIndex(i as u32), + ); + + unchecked_signed + }) + .collect(); + bitfields } @@ -522,7 +544,7 @@ impl BenchBuilder { /// validity votes. fn create_backed_candidates( &self, - cores_with_backed_candidates: &BTreeMap, + paras_with_backed_candidates: &BTreeMap, elastic_paras: &BTreeMap, includes_code_upgrade: Option, ) -> Vec> { @@ -531,7 +553,7 @@ impl BenchBuilder { let config = configuration::Pallet::::config(); let mut current_core_idx = 0u32; - cores_with_backed_candidates + paras_with_backed_candidates .iter() .flat_map(|(seed, num_votes)| { assert!(*num_votes <= validators.len() as u32); @@ -760,7 +782,7 @@ impl BenchBuilder { // NOTE: there is an n+2 session delay for these actions to take effect. // We are currently in Session 0, so these changes will take effect in Session 2. - Self::setup_para_ids(used_cores); + Self::setup_para_ids(used_cores - extra_cores); configuration::ActiveConfig::::mutate(|c| { c.scheduler_params.num_cores = used_cores as u32; }); @@ -782,11 +804,11 @@ impl BenchBuilder { let disputes = builder.create_disputes( builder.backed_and_concluding_paras.len() as u32, - used_cores as u32, + (used_cores - extra_cores) as u32, builder.dispute_sessions.as_slice(), ); let mut disputed_cores = (builder.backed_and_concluding_paras.len() as u32.. - used_cores as u32) + ((used_cores - extra_cores) as u32)) .into_iter() .map(|idx| (idx, 0)) .collect::>(); @@ -794,7 +816,7 @@ impl BenchBuilder { let mut all_cores = builder.backed_and_concluding_paras.clone(); all_cores.append(&mut disputed_cores); - assert_eq!(inclusion::PendingAvailability::::iter().count(), used_cores as usize,); + assert_eq!(inclusion::PendingAvailability::::iter().count(), used_cores - extra_cores); // Mark all the used cores as occupied. We expect that there are // `backed_and_concluding_paras` that are pending availability and that there are @@ -831,7 +853,7 @@ impl BenchBuilder { .keys() .flat_map(|para_id| { (0..elastic_paras.get(¶_id).cloned().unwrap_or(1)) - .map(|_para_local_core_idx| { + .filter_map(|_para_local_core_idx| { let ttl = configuration::Pallet::::config().scheduler_params.ttl; // Load an assignment into provider so that one is present to pop let assignment = @@ -844,8 +866,13 @@ impl BenchBuilder { CoreIndex(core_idx), [ParasEntry::new(assignment, now + ttl)].into(), ); + let res = if builder.unavailable_cores.contains(&core_idx) { + None + } else { + Some(entry) + }; core_idx += 1; - entry + res }) .collect::>)>>() }) diff --git a/polkadot/runtime/parachains/src/inclusion/migration.rs b/polkadot/runtime/parachains/src/inclusion/migration.rs new file mode 100644 index 00000000000..1e63b209f4e --- /dev/null +++ b/polkadot/runtime/parachains/src/inclusion/migration.rs @@ -0,0 +1,317 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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. + +pub use v1::MigrateToV1; + +pub mod v0 { + use crate::inclusion::{Config, Pallet}; + use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; + use frame_support::{storage_alias, Twox64Concat}; + use frame_system::pallet_prelude::BlockNumberFor; + use parity_scale_codec::{Decode, Encode}; + use primitives::{ + AvailabilityBitfield, CandidateCommitments, CandidateDescriptor, CandidateHash, CoreIndex, + GroupIndex, Id as ParaId, ValidatorIndex, + }; + use scale_info::TypeInfo; + + #[derive(Encode, Decode, PartialEq, TypeInfo, Clone, Debug)] + pub struct CandidatePendingAvailability { + pub core: CoreIndex, + pub hash: CandidateHash, + pub descriptor: CandidateDescriptor, + pub availability_votes: BitVec, + pub backers: BitVec, + pub relay_parent_number: N, + pub backed_in_number: N, + pub backing_group: GroupIndex, + } + + #[derive(Encode, Decode, TypeInfo, Debug, PartialEq)] + pub struct AvailabilityBitfieldRecord { + pub bitfield: AvailabilityBitfield, + pub submitted_at: N, + } + + #[storage_alias] + pub type PendingAvailability = StorageMap< + Pallet, + Twox64Concat, + ParaId, + CandidatePendingAvailability<::Hash, BlockNumberFor>, + >; + + #[storage_alias] + pub type PendingAvailabilityCommitments = + StorageMap, Twox64Concat, ParaId, CandidateCommitments>; + + #[storage_alias] + pub type AvailabilityBitfields = StorageMap< + Pallet, + Twox64Concat, + ValidatorIndex, + AvailabilityBitfieldRecord>, + >; +} + +mod v1 { + use super::v0::{ + AvailabilityBitfields, PendingAvailability as V0PendingAvailability, + PendingAvailabilityCommitments as V0PendingAvailabilityCommitments, + }; + use crate::inclusion::{ + CandidatePendingAvailability as V1CandidatePendingAvailability, Config, Pallet, + PendingAvailability as V1PendingAvailability, + }; + use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; + use sp_core::Get; + use sp_std::{collections::vec_deque::VecDeque, vec::Vec}; + + #[cfg(feature = "try-runtime")] + use frame_support::{ + ensure, + traits::{GetStorageVersion, StorageVersion}, + }; + #[cfg(feature = "try-runtime")] + use parity_scale_codec::{Decode, Encode}; + + pub struct VersionUncheckedMigrateToV1(sp_std::marker::PhantomData); + + impl OnRuntimeUpgrade for VersionUncheckedMigrateToV1 { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + log::trace!(target: crate::inclusion::LOG_TARGET, "Running pre_upgrade() for inclusion MigrateToV1"); + let candidates_before_upgrade = V0PendingAvailability::::iter().count(); + let commitments_before_upgrade = V0PendingAvailabilityCommitments::::iter().count(); + + if candidates_before_upgrade != commitments_before_upgrade { + log::warn!( + target: crate::inclusion::LOG_TARGET, + "Number of pending candidates differ from the number of pending commitments. {} vs {}", + candidates_before_upgrade, + commitments_before_upgrade + ); + } + + Ok((candidates_before_upgrade as u32).encode()) + } + + fn on_runtime_upgrade() -> Weight { + let mut weight: Weight = Weight::zero(); + + let v0_candidates: Vec<_> = V0PendingAvailability::::drain().collect(); + + for (para_id, candidate) in v0_candidates { + let commitments = V0PendingAvailabilityCommitments::::take(para_id); + // One write for each removal (one candidate and one commitment). + weight = weight.saturating_add(T::DbWeight::get().writes(2)); + + if let Some(commitments) = commitments { + let mut per_para = VecDeque::new(); + per_para.push_back(V1CandidatePendingAvailability { + core: candidate.core, + hash: candidate.hash, + descriptor: candidate.descriptor, + availability_votes: candidate.availability_votes, + backers: candidate.backers, + relay_parent_number: candidate.relay_parent_number, + backed_in_number: candidate.backed_in_number, + backing_group: candidate.backing_group, + commitments, + }); + V1PendingAvailability::::insert(para_id, per_para); + + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + } + + // should've already been drained by the above for loop, but as a sanity check, in case + // there are more commitments than candidates. + // V0PendingAvailabilityCommitments should not contain too many keys so removing + // everything at once should be safe + let res = V0PendingAvailabilityCommitments::::clear(u32::MAX, None); + weight = weight.saturating_add( + T::DbWeight::get().reads_writes(res.loops as u64, res.backend as u64), + ); + + // AvailabilityBitfields should not contain too many keys so removing everything at once + // should be safe. + let res = AvailabilityBitfields::::clear(u32::MAX, None); + weight = weight.saturating_add( + T::DbWeight::get().reads_writes(res.loops as u64, res.backend as u64), + ); + + weight + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + log::trace!(target: crate::inclusion::LOG_TARGET, "Running post_upgrade() for inclusion MigrateToV1"); + ensure!( + Pallet::::on_chain_storage_version() >= StorageVersion::new(1), + "Storage version should be >= 1 after the migration" + ); + + let candidates_before_upgrade = + u32::decode(&mut &state[..]).expect("Was properly encoded") as usize; + let candidates_after_upgrade = V1PendingAvailability::::iter().fold( + 0usize, + |mut acc, (_paraid, para_candidates)| { + acc += para_candidates.len(); + acc + }, + ); + + ensure!( + candidates_before_upgrade == candidates_after_upgrade, + "Number of pending candidates should be the same as the one before the upgrade." + ); + ensure!( + V0PendingAvailability::::iter().next() == None, + "Pending availability candidates storage v0 should have been removed" + ); + ensure!( + V0PendingAvailabilityCommitments::::iter().next() == None, + "Pending availability commitments storage should have been removed" + ); + ensure!( + AvailabilityBitfields::::iter().next() == None, + "Availability bitfields storage should have been removed" + ); + + Ok(()) + } + } + + /// Migrate to v1 inclusion module storage. + /// - merges the `PendingAvailabilityCommitments` into the `CandidatePendingAvailability` + /// storage + /// - removes the `AvailabilityBitfields` storage, which was never read. + pub type MigrateToV1 = frame_support::migrations::VersionedMigration< + 0, + 1, + VersionUncheckedMigrateToV1, + Pallet, + ::DbWeight, + >; +} + +#[cfg(test)] +mod tests { + use super::{v1::VersionUncheckedMigrateToV1, *}; + use crate::{ + inclusion::{ + CandidatePendingAvailability as V1CandidatePendingAvailability, + PendingAvailability as V1PendingAvailability, *, + }, + mock::{new_test_ext, MockGenesisConfig, Test}, + }; + use frame_support::traits::OnRuntimeUpgrade; + use primitives::{AvailabilityBitfield, Id as ParaId}; + use test_helpers::{dummy_candidate_commitments, dummy_candidate_descriptor, dummy_hash}; + + #[test] + fn migrate_to_v1() { + new_test_ext(MockGenesisConfig::default()).execute_with(|| { + // No data to migrate. + assert_eq!( + as OnRuntimeUpgrade>::on_runtime_upgrade(), + Weight::zero() + ); + assert!(V1PendingAvailability::::iter().next().is_none()); + + let mut expected = vec![]; + + for i in 1..5 { + let descriptor = dummy_candidate_descriptor(dummy_hash()); + v0::PendingAvailability::::insert( + ParaId::from(i), + v0::CandidatePendingAvailability { + core: CoreIndex(i), + descriptor: descriptor.clone(), + relay_parent_number: i, + hash: CandidateHash(dummy_hash()), + availability_votes: Default::default(), + backed_in_number: i, + backers: Default::default(), + backing_group: GroupIndex(i), + }, + ); + v0::PendingAvailabilityCommitments::::insert( + ParaId::from(i), + dummy_candidate_commitments(HeadData(vec![i as _])), + ); + + v0::AvailabilityBitfields::::insert( + ValidatorIndex(i), + v0::AvailabilityBitfieldRecord { + bitfield: AvailabilityBitfield(Default::default()), + submitted_at: i, + }, + ); + + expected.push(( + ParaId::from(i), + [V1CandidatePendingAvailability { + core: CoreIndex(i), + descriptor, + relay_parent_number: i, + hash: CandidateHash(dummy_hash()), + availability_votes: Default::default(), + backed_in_number: i, + backers: Default::default(), + backing_group: GroupIndex(i), + commitments: dummy_candidate_commitments(HeadData(vec![i as _])), + }] + .into_iter() + .collect::>(), + )); + } + // add some wrong data also, candidates without commitments or commitments without + // candidates. + v0::PendingAvailability::::insert( + ParaId::from(6), + v0::CandidatePendingAvailability { + core: CoreIndex(6), + descriptor: dummy_candidate_descriptor(dummy_hash()), + relay_parent_number: 6, + hash: CandidateHash(dummy_hash()), + availability_votes: Default::default(), + backed_in_number: 6, + backers: Default::default(), + backing_group: GroupIndex(6), + }, + ); + v0::PendingAvailabilityCommitments::::insert( + ParaId::from(7), + dummy_candidate_commitments(HeadData(vec![7 as _])), + ); + + // For tests, db weight is zero. + assert_eq!( + as OnRuntimeUpgrade>::on_runtime_upgrade(), + Weight::zero() + ); + + assert_eq!(v0::PendingAvailabilityCommitments::::iter().next(), None); + assert_eq!(v0::PendingAvailability::::iter().next(), None); + assert_eq!(v0::AvailabilityBitfields::::iter().next(), None); + + let mut actual = V1PendingAvailability::::iter().collect::>(); + actual.sort_by(|(id1, _), (id2, _)| id1.cmp(id2)); + expected.sort_by(|(id1, _), (id2, _)| id1.cmp(id2)); + + assert_eq!(actual, expected); + }); + } +} diff --git a/polkadot/runtime/parachains/src/inclusion/mod.rs b/polkadot/runtime/parachains/src/inclusion/mod.rs index 16e2e93b561..e77f8d15b40 100644 --- a/polkadot/runtime/parachains/src/inclusion/mod.rs +++ b/polkadot/runtime/parachains/src/inclusion/mod.rs @@ -23,31 +23,35 @@ use crate::{ configuration::{self, HostConfiguration}, disputes, dmp, hrmp, paras::{self, SetGoAhead}, - scheduler::{self, AvailabilityTimeoutStatus}, + scheduler, shared::{self, AllowedRelayParentsTracker}, + util::make_persisted_validation_data_with_parent, }; use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec}; use frame_support::{ defensive, pallet_prelude::*, - traits::{Defensive, EnqueueMessage, Footprint, QueueFootprint}, + traits::{EnqueueMessage, Footprint, QueueFootprint}, BoundedSlice, }; use frame_system::pallet_prelude::*; use pallet_message_queue::OnQueueChanged; use parity_scale_codec::{Decode, Encode}; use primitives::{ - effective_minimum_backing_votes, supermajority_threshold, well_known_keys, - AvailabilityBitfield, BackedCandidate, CandidateCommitments, CandidateDescriptor, - CandidateHash, CandidateReceipt, CommittedCandidateReceipt, CoreIndex, GroupIndex, Hash, - HeadData, Id as ParaId, SignedAvailabilityBitfields, SigningContext, UpwardMessage, - ValidatorId, ValidatorIndex, ValidityAttestation, + effective_minimum_backing_votes, supermajority_threshold, well_known_keys, BackedCandidate, + CandidateCommitments, CandidateDescriptor, CandidateHash, CandidateReceipt, + CommittedCandidateReceipt, CoreIndex, GroupIndex, Hash, HeadData, Id as ParaId, + SignedAvailabilityBitfields, SigningContext, UpwardMessage, ValidatorId, ValidatorIndex, + ValidityAttestation, }; use scale_info::TypeInfo; use sp_runtime::{traits::One, DispatchError, SaturatedConversion, Saturating}; #[cfg(feature = "std")] use sp_std::fmt; -use sp_std::{collections::btree_set::BTreeSet, prelude::*}; +use sp_std::{ + collections::{btree_map::BTreeMap, btree_set::BTreeSet, vec_deque::VecDeque}, + prelude::*, +}; pub use pallet::*; @@ -57,6 +61,8 @@ pub(crate) mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; +pub mod migration; + pub trait WeightInfo { fn receive_upward_messages(i: u32) -> Weight; } @@ -80,20 +86,8 @@ impl WeightInfo for () { /// `configuration` pallet to check these values before setting. pub const MAX_UPWARD_MESSAGE_SIZE_BOUND: u32 = 128 * 1024; -/// A bitfield signed by a validator indicating that it is keeping its piece of the erasure-coding -/// for any backed candidates referred to by a `1` bit available. -/// -/// The bitfield's signature should be checked at the point of submission. Afterwards it can be -/// dropped. -#[derive(Encode, Decode, TypeInfo)] -#[cfg_attr(test, derive(Debug))] -pub struct AvailabilityBitfieldRecord { - bitfield: AvailabilityBitfield, // one bit per core. - submitted_at: N, // for accounting, as meaning of bits may change over time. -} - /// A backed candidate pending availability. -#[derive(Encode, Decode, PartialEq, TypeInfo)] +#[derive(Encode, Decode, PartialEq, TypeInfo, Clone)] #[cfg_attr(test, derive(Debug))] pub struct CandidatePendingAvailability { /// The availability core this is assigned to. @@ -102,6 +96,8 @@ pub struct CandidatePendingAvailability { hash: CandidateHash, /// The candidate descriptor. descriptor: CandidateDescriptor, + /// The candidate commitments. + commitments: CandidateCommitments, /// The received availability votes. One bit per validator. availability_votes: BitVec, /// The backers of the candidate pending availability. @@ -121,8 +117,11 @@ impl CandidatePendingAvailability { } /// Get the relay-chain block number this was backed in. - pub(crate) fn backed_in_number(&self) -> &N { - &self.backed_in_number + pub(crate) fn backed_in_number(&self) -> N + where + N: Clone, + { + self.backed_in_number.clone() } /// Get the core index. @@ -140,6 +139,11 @@ impl CandidatePendingAvailability { &self.descriptor } + /// Get the candidate commitments. + pub(crate) fn candidate_commitments(&self) -> &CandidateCommitments { + &self.commitments + } + /// Get the candidate's relay parent's number. pub(crate) fn relay_parent_number(&self) -> N where @@ -148,11 +152,22 @@ impl CandidatePendingAvailability { self.relay_parent_number.clone() } + /// Get the candidate backing group. + pub(crate) fn backing_group(&self) -> GroupIndex { + self.backing_group + } + + /// Get the candidate's backers. + pub(crate) fn backers(&self) -> &BitVec { + &self.backers + } + #[cfg(any(feature = "runtime-benchmarks", test))] pub(crate) fn new( core: CoreIndex, hash: CandidateHash, descriptor: CandidateDescriptor, + commitments: CandidateCommitments, availability_votes: BitVec, backers: BitVec, relay_parent_number: N, @@ -163,6 +178,7 @@ impl CandidatePendingAvailability { core, hash, descriptor, + commitments, availability_votes, backers, relay_parent_number, @@ -253,8 +269,10 @@ pub type MaxUmpMessageLenOf = pub mod pallet { use super::*; + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] #[pallet::without_storage_info] + #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); #[pallet::config] @@ -297,30 +315,10 @@ pub mod pallet { #[pallet::error] pub enum Error { - /// Validator indices are out of order or contains duplicates. - UnsortedOrDuplicateValidatorIndices, - /// Dispute statement sets are out of order or contain duplicates. - UnsortedOrDuplicateDisputeStatementSet, - /// Backed candidates are out of order (core index) or contain duplicates. - UnsortedOrDuplicateBackedCandidates, - /// A different relay parent was provided compared to the on-chain stored one. - UnexpectedRelayParent, - /// Availability bitfield has unexpected size. - WrongBitfieldSize, - /// Bitfield consists of zeros only. - BitfieldAllZeros, - /// Multiple bitfields submitted by same validator or validators out of order by index. - BitfieldDuplicateOrUnordered, /// Validator index out of bounds. ValidatorIndexOutOfBounds, - /// Invalid signature - InvalidBitfieldSignature, /// Candidate submitted but para not scheduled. UnscheduledCandidate, - /// Candidate scheduled despite pending candidate already existing for the para. - CandidateScheduledBeforeParaFree, - /// Scheduled cores out of order. - ScheduledOutOfOrder, /// Head data exceeds the configured maximum. HeadDataTooLarge, /// Code upgrade prematurely. @@ -356,31 +354,22 @@ pub mod pallet { /// The `para_head` hash in the candidate descriptor doesn't match the hash of the actual /// para head in the commitments. ParaHeadMismatch, - /// A bitfield that references a freed core, - /// either intentionally or as part of a concluded - /// invalid dispute. - BitfieldReferencesFreedCore, } - /// The latest bitfield for each validator, referred to by their index in the validator set. - #[pallet::storage] - pub(crate) type AvailabilityBitfields = - StorageMap<_, Twox64Concat, ValidatorIndex, AvailabilityBitfieldRecord>>; - - /// Candidates pending availability by `ParaId`. + /// Candidates pending availability by `ParaId`. They form a chain starting from the latest + /// included head of the para. + /// Use a different prefix post-migration to v1, since the v0 `PendingAvailability` storage + /// would otherwise have the exact same prefix which could cause undefined behaviour when doing + /// the migration. #[pallet::storage] + #[pallet::storage_prefix = "V1"] pub(crate) type PendingAvailability = StorageMap< _, Twox64Concat, ParaId, - CandidatePendingAvailability>, + VecDeque>>, >; - /// The commitments of candidates pending availability, by `ParaId`. - #[pallet::storage] - pub(crate) type PendingAvailabilityCommitments = - StorageMap<_, Twox64Concat, ParaId, CandidateCommitments>; - #[pallet::call] impl Pallet {} } @@ -469,9 +458,7 @@ impl Pallet { ) { // unlike most drain methods, drained elements are not cleared on `Drop` of the iterator // and require consumption. - for _ in >::drain() {} for _ in >::drain() {} - for _ in >::drain() {} Self::cleanup_outgoing_ump_dispatch_queues(outgoing_paras); } @@ -490,27 +477,18 @@ impl Pallet { /// /// Bitfields are expected to have been sanitized already. E.g. via `sanitize_bitfields`! /// - /// Updates storage items `PendingAvailability` and `AvailabilityBitfields`. + /// Updates storage items `PendingAvailability`. /// /// Returns a `Vec` of `CandidateHash`es and their respective `AvailabilityCore`s that became /// available, and cores free. - pub(crate) fn update_pending_availability_and_get_freed_cores( - expected_bits: usize, + pub(crate) fn update_pending_availability_and_get_freed_cores( validators: &[ValidatorId], signed_bitfields: SignedAvailabilityBitfields, - core_lookup: F, - ) -> Vec<(CoreIndex, CandidateHash)> - where - F: Fn(CoreIndex) -> Option, - { - let mut assigned_paras_record = (0..expected_bits) - .map(|bit_index| core_lookup(CoreIndex::from(bit_index as u32))) - .map(|opt_para_id| { - opt_para_id.map(|para_id| (para_id, PendingAvailability::::get(¶_id))) - }) - .collect::>(); + ) -> Vec<(CoreIndex, CandidateHash)> { + let threshold = availability_threshold(validators.len()); + + let mut votes_per_core: BTreeMap> = BTreeMap::new(); - let now = >::block_number(); for (checked_bitfield, validator_index) in signed_bitfields.into_iter().map(|signed_bitfield| { let validator_idx = signed_bitfield.validator_index(); @@ -518,310 +496,275 @@ impl Pallet { (checked_bitfield, validator_idx) }) { for (bit_idx, _) in checked_bitfield.0.iter().enumerate().filter(|(_, is_av)| **is_av) { - let pending_availability = if let Some((_, pending_availability)) = - assigned_paras_record[bit_idx].as_mut() - { - pending_availability - } else { - // For honest validators, this happens in case of unoccupied cores, - // which in turn happens in case of a disputed candidate. - // A malicious one might include arbitrary indices, but they are represented - // by `None` values and will be sorted out in the next if case. - continue - }; - - // defensive check - this is constructed by loading the availability bitfield - // record, which is always `Some` if the core is occupied - that's why we're here. - let validator_index = validator_index.0 as usize; - if let Some(mut bit) = - pending_availability.as_mut().and_then(|candidate_pending_availability| { - candidate_pending_availability.availability_votes.get_mut(validator_index) - }) { - *bit = true; - } + let core_index = CoreIndex(bit_idx as u32); + votes_per_core + .entry(core_index) + .or_insert_with(|| BTreeSet::new()) + .insert(validator_index); } - - let record = - AvailabilityBitfieldRecord { bitfield: checked_bitfield, submitted_at: now }; - - >::insert(&validator_index, record); } - let threshold = availability_threshold(validators.len()); + let mut freed_cores = vec![]; + + let pending_paraids: Vec<_> = >::iter_keys().collect(); + for paraid in pending_paraids { + >::mutate(paraid, |candidates| { + if let Some(candidates) = candidates { + let mut last_enacted_index: Option = None; + + for (candidate_index, candidate) in candidates.iter_mut().enumerate() { + if let Some(validator_indices) = votes_per_core.remove(&candidate.core) { + for validator_index in validator_indices.iter() { + // defensive check - this is constructed by loading the + // availability bitfield record, which is always `Some` if + // the core is occupied - that's why we're here. + if let Some(mut bit) = + candidate.availability_votes.get_mut(validator_index.0 as usize) + { + *bit = true; + } + } + } + + // We check for the candidate's availability even if we didn't get any new + // bitfields for its core, as it may have already been available at a + // previous block but wasn't enacted due to its predecessors not being + // available. + if candidate.availability_votes.count_ones() >= threshold { + // We can only enact a candidate if we've enacted all of its + // predecessors already. + let can_enact = if candidate_index == 0 { + last_enacted_index == None + } else { + let prev_candidate_index = usize::try_from(candidate_index - 1) + .expect("Previous `if` would have caught a 0 candidate index."); + matches!(last_enacted_index, Some(old_index) if old_index == prev_candidate_index) + }; + + if can_enact { + last_enacted_index = Some(candidate_index); + } + } + } - let mut freed_cores = Vec::with_capacity(expected_bits); - for (para_id, pending_availability) in assigned_paras_record - .into_iter() - .flatten() - .filter_map(|(id, p)| p.map(|p| (id, p))) - { - if pending_availability.availability_votes.count_ones() >= threshold { - >::remove(¶_id); - let commitments = match PendingAvailabilityCommitments::::take(¶_id) { - Some(commitments) => commitments, - None => { - log::warn!( - target: LOG_TARGET, - "Inclusion::process_bitfields: PendingAvailability and PendingAvailabilityCommitments - are out of sync, did someone mess with the storage?", - ); - continue - }, - }; - - let receipt = CommittedCandidateReceipt { - descriptor: pending_availability.descriptor, - commitments, - }; - let _weight = Self::enact_candidate( - pending_availability.relay_parent_number, - receipt, - pending_availability.backers, - pending_availability.availability_votes, - pending_availability.core, - pending_availability.backing_group, - ); - - freed_cores.push((pending_availability.core, pending_availability.hash)); - } else { - >::insert(¶_id, &pending_availability); - } + // Trim the pending availability candidates storage and enact candidates of this + // para now. + if let Some(last_enacted_index) = last_enacted_index { + let evicted_candidates = candidates.drain(0..=last_enacted_index); + for candidate in evicted_candidates { + freed_cores.push((candidate.core, candidate.hash)); + + let receipt = CommittedCandidateReceipt { + descriptor: candidate.descriptor, + commitments: candidate.commitments, + }; + let _weight = Self::enact_candidate( + candidate.relay_parent_number, + receipt, + candidate.backers, + candidate.availability_votes, + candidate.core, + candidate.backing_group, + ); + } + } + } + }); } freed_cores } - /// Process candidates that have been backed. Provide the relay storage root, a set of - /// candidates and scheduled cores. + /// Process candidates that have been backed. Provide a set of + /// candidates along with their scheduled cores. /// - /// Both should be sorted ascending by core index, and the candidates should be a subset of - /// scheduled cores. If these conditions are not met, the execution of the function fails. + /// Candidates of the same paraid should be sorted according to their dependency order (they + /// should form a chain). If this condition is not met, this function will return an error. + /// (This really should not happen here, if the candidates were properly sanitised in + /// paras_inherent). pub(crate) fn process_candidates( allowed_relay_parents: &AllowedRelayParentsTracker>, - candidates: Vec<(BackedCandidate, CoreIndex)>, + candidates: &BTreeMap, CoreIndex)>>, group_validators: GV, core_index_enabled: bool, ) -> Result, DispatchError> where GV: Fn(GroupIndex) -> Option>, { - let now = >::block_number(); - if candidates.is_empty() { return Ok(ProcessedCandidates::default()) } - let minimum_backing_votes = configuration::Pallet::::config().minimum_backing_votes; + let now = >::block_number(); let validators = shared::Pallet::::active_validator_keys(); // Collect candidate receipts with backers. let mut candidate_receipt_with_backing_validator_indices = Vec::with_capacity(candidates.len()); + let mut core_indices = Vec::with_capacity(candidates.len()); - // Do all checks before writing storage. - let core_indices_and_backers = { - let mut core_indices_and_backers = Vec::with_capacity(candidates.len()); - let mut last_core = None; - - let mut check_assignment_in_order = |core_idx| -> DispatchResult { - ensure!( - last_core.map_or(true, |core| core_idx > core), - Error::::ScheduledOutOfOrder, - ); - - last_core = Some(core_idx); - Ok(()) + for (para_id, para_candidates) in candidates { + let mut latest_head_data = match Self::para_latest_head_data(para_id) { + None => { + defensive!("Latest included head data for paraid {:?} is None", para_id); + continue + }, + Some(latest_head_data) => latest_head_data, }; - // We combine an outer loop over candidates with an inner loop over the scheduled, - // where each iteration of the outer loop picks up at the position - // in scheduled just after the past iteration left off. - // - // If the candidates appear in the same order as they appear in `scheduled`, - // then they should always be found. If the end of `scheduled` is reached, - // then the candidate was either not scheduled or out-of-order. - // - // In the meantime, we do certain sanity checks on the candidates and on the scheduled - // list. - for (candidate_idx, (backed_candidate, core_index)) in candidates.iter().enumerate() { - let relay_parent_hash = backed_candidate.descriptor().relay_parent; - let para_id = backed_candidate.descriptor().para_id; - - let prev_context = >::para_most_recent_context(para_id); - - let check_ctx = CandidateCheckContext::::new(prev_context); - let signing_context = SigningContext { - parent_hash: relay_parent_hash, - session_index: shared::Pallet::::session_index(), - }; - - let relay_parent_number = match check_ctx.verify_backed_candidate( + for (candidate, core) in para_candidates.iter() { + let candidate_hash = candidate.candidate().hash(); + + let check_ctx = CandidateCheckContext::::new(None); + let relay_parent_number = check_ctx.verify_backed_candidate( &allowed_relay_parents, - candidate_idx, - backed_candidate.candidate(), - )? { - Err(FailedToCreatePVD) => { - log::debug!( - target: LOG_TARGET, - "Failed to create PVD for candidate {}", - candidate_idx, - ); - // We don't want to error out here because it will - // brick the relay-chain. So we return early without - // doing anything. - return Ok(ProcessedCandidates::default()) - }, - Ok(rpn) => rpn, - }; - - let (validator_indices, _) = - backed_candidate.validator_indices_and_core_index(core_index_enabled); - - log::debug!( - target: LOG_TARGET, - "Candidate {:?} on {:?}, - core_index_enabled = {}", - backed_candidate.hash(), - core_index, - core_index_enabled - ); - - check_assignment_in_order(core_index)?; - - let mut backers = bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()]; - - ensure!( - >::get(¶_id).is_none() && - >::get(¶_id).is_none(), - Error::::CandidateScheduledBeforeParaFree, - ); - - // The candidate based upon relay parent `N` should be backed by a group - // assigned to core at block `N + 1`. Thus, `relay_parent_number + 1` - // will always land in the current session. + candidate.candidate(), + latest_head_data.clone(), + )?; + + // The candidate based upon relay parent `N` should be backed by a + // group assigned to core at block `N + 1`. Thus, + // `relay_parent_number + 1` will always land in the current + // session. let group_idx = >::group_assigned_to_core( - *core_index, + *core, relay_parent_number + One::one(), ) .ok_or_else(|| { log::warn!( target: LOG_TARGET, - "Failed to compute group index for candidate {}", - candidate_idx + "Failed to compute group index for candidate {:?}", + candidate_hash ); Error::::InvalidAssignment })?; let group_vals = group_validators(group_idx).ok_or_else(|| Error::::InvalidGroupIndex)?; - // check the signatures in the backing and that it is a majority. - { - let maybe_amount_validated = primitives::check_candidate_backing( - backed_candidate.candidate().hash(), - backed_candidate.validity_votes(), - validator_indices, - &signing_context, - group_vals.len(), - |intra_group_vi| { - group_vals - .get(intra_group_vi) - .and_then(|vi| validators.get(vi.0 as usize)) - .map(|v| v.clone()) - }, - ); - - match maybe_amount_validated { - Ok(amount_validated) => ensure!( - amount_validated >= - effective_minimum_backing_votes( - group_vals.len(), - minimum_backing_votes - ), - Error::::InsufficientBacking, - ), - Err(()) => { - Err(Error::::InvalidBacking)?; - }, - } - - let mut backer_idx_and_attestation = - Vec::<(ValidatorIndex, ValidityAttestation)>::with_capacity( - validator_indices.count_ones(), - ); - let candidate_receipt = backed_candidate.receipt(); - - for ((bit_idx, _), attestation) in validator_indices - .iter() - .enumerate() - .filter(|(_, signed)| **signed) - .zip(backed_candidate.validity_votes().iter().cloned()) - { - let val_idx = - group_vals.get(bit_idx).expect("this query succeeded above; qed"); - backer_idx_and_attestation.push((*val_idx, attestation)); - - backers.set(val_idx.0 as _, true); + // Check backing vote count and validity. + let (backers, backer_idx_and_attestation) = Self::check_backing_votes( + candidate, + &validators, + group_vals, + core_index_enabled, + )?; + + // Found a valid candidate. + latest_head_data = candidate.candidate().commitments.head_data.clone(); + candidate_receipt_with_backing_validator_indices + .push((candidate.receipt(), backer_idx_and_attestation)); + core_indices.push((*core, *para_id)); + + // Update storage now + >::mutate(¶_id, |pending_availability| { + let new_candidate = CandidatePendingAvailability { + core: *core, + hash: candidate_hash, + descriptor: candidate.candidate().descriptor.clone(), + commitments: candidate.candidate().commitments.clone(), + // initialize all availability votes to 0. + availability_votes: bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()], + relay_parent_number, + backers: backers.to_bitvec(), + backed_in_number: now, + backing_group: group_idx, + }; + + if let Some(pending_availability) = pending_availability { + pending_availability.push_back(new_candidate); + } else { + *pending_availability = + Some([new_candidate].into_iter().collect::>()) } - candidate_receipt_with_backing_validator_indices - .push((candidate_receipt, backer_idx_and_attestation)); - } + }); - core_indices_and_backers.push(( - (*core_index, para_id), - backers, + // Deposit backed event. + Self::deposit_event(Event::::CandidateBacked( + candidate.candidate().to_plain(), + candidate.candidate().commitments.head_data.clone(), + *core, group_idx, - relay_parent_number, )); } + } - core_indices_and_backers - }; + Ok(ProcessedCandidates:: { + core_indices, + candidate_receipt_with_backing_validator_indices, + }) + } - // one more sweep for actually writing to storage. - let core_indices = core_indices_and_backers.iter().map(|(c, ..)| *c).collect(); - for ((candidate, _), (core, backers, group, relay_parent_number)) in - candidates.into_iter().zip(core_indices_and_backers) - { - let para_id = candidate.descriptor().para_id; + // Get the latest backed output head data of this para. + pub(crate) fn para_latest_head_data(para_id: &ParaId) -> Option { + match >::get(para_id).and_then(|pending_candidates| { + pending_candidates.back().map(|x| x.commitments.head_data.clone()) + }) { + Some(head_data) => Some(head_data), + None => >::para_head(para_id), + } + } - // initialize all availability votes to 0. - let availability_votes: BitVec = - bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()]; + fn check_backing_votes( + backed_candidate: &BackedCandidate, + validators: &[ValidatorId], + group_vals: Vec, + core_index_enabled: bool, + ) -> Result<(BitVec, Vec<(ValidatorIndex, ValidityAttestation)>), Error> { + let minimum_backing_votes = configuration::Pallet::::config().minimum_backing_votes; - Self::deposit_event(Event::::CandidateBacked( - candidate.candidate().to_plain(), - candidate.candidate().commitments.head_data.clone(), - core.0, - group, - )); + let mut backers = bitvec::bitvec![u8, BitOrderLsb0; 0; validators.len()]; + let signing_context = SigningContext { + parent_hash: backed_candidate.descriptor().relay_parent, + session_index: shared::Pallet::::session_index(), + }; - let candidate_hash = candidate.candidate().hash(); + let (validator_indices, _) = + backed_candidate.validator_indices_and_core_index(core_index_enabled); + + // check the signatures in the backing and that it is a majority. + let maybe_amount_validated = primitives::check_candidate_backing( + backed_candidate.candidate().hash(), + backed_candidate.validity_votes(), + validator_indices, + &signing_context, + group_vals.len(), + |intra_group_vi| { + group_vals + .get(intra_group_vi) + .and_then(|vi| validators.get(vi.0 as usize)) + .map(|v| v.clone()) + }, + ); - let (descriptor, commitments) = ( - candidate.candidate().descriptor.clone(), - candidate.candidate().commitments.clone(), - ); + match maybe_amount_validated { + Ok(amount_validated) => ensure!( + amount_validated >= + effective_minimum_backing_votes(group_vals.len(), minimum_backing_votes), + Error::::InsufficientBacking, + ), + Err(()) => { + Err(Error::::InvalidBacking)?; + }, + } - >::insert( - ¶_id, - CandidatePendingAvailability { - core: core.0, - hash: candidate_hash, - descriptor, - availability_votes, - relay_parent_number, - backers: backers.to_bitvec(), - backed_in_number: now, - backing_group: group, - }, + let mut backer_idx_and_attestation = + Vec::<(ValidatorIndex, ValidityAttestation)>::with_capacity( + validator_indices.count_ones(), ); - >::insert(¶_id, commitments); + + for ((bit_idx, _), attestation) in validator_indices + .iter() + .enumerate() + .filter(|(_, signed)| **signed) + .zip(backed_candidate.validity_votes().iter().cloned()) + { + let val_idx = group_vals.get(bit_idx).expect("this query succeeded above; qed"); + backer_idx_and_attestation.push((*val_idx, attestation)); + + backers.set(val_idx.0 as _, true); } - Ok(ProcessedCandidates:: { - core_indices, - candidate_receipt_with_backing_validator_indices, - }) + Ok((backers, backer_idx_and_attestation)) } /// Run the acceptance criteria checks on the given candidate commitments. @@ -1028,110 +971,155 @@ impl Pallet { weight } - /// Cleans up all paras pending availability that the predicate returns true for. - /// - /// The predicate accepts the index of the core and the block number the core has been occupied - /// since (i.e. the block number the candidate was backed at in this fork of the relay chain). + /// Cleans up all timed out candidates as well as their descendant candidates. /// /// Returns a vector of cleaned-up core IDs. - pub(crate) fn collect_pending( - pred: impl Fn(BlockNumberFor) -> AvailabilityTimeoutStatus>, - ) -> Vec { - let mut cleaned_up_ids = Vec::new(); - let mut cleaned_up_cores = Vec::new(); - - for (para_id, pending_record) in >::iter() { - if pred(pending_record.backed_in_number).timed_out { - cleaned_up_ids.push(para_id); - cleaned_up_cores.push(pending_record.core); - } - } - - for para_id in cleaned_up_ids { - let pending = >::take(¶_id); - let commitments = >::take(¶_id); - - if let (Some(pending), Some(commitments)) = (pending, commitments) { - // defensive: this should always be true. - let candidate = CandidateReceipt { - descriptor: pending.descriptor, - commitments_hash: commitments.hash(), - }; + pub(crate) fn free_timedout() -> Vec { + let timeout_pred = >::availability_timeout_predicate(); + + let timed_out: Vec<_> = Self::free_failed_cores( + |candidate| timeout_pred(candidate.backed_in_number).timed_out, + None, + ) + .collect(); + + let mut timed_out_cores = Vec::with_capacity(timed_out.len()); + for candidate in timed_out.iter() { + timed_out_cores.push(candidate.core); + + let receipt = CandidateReceipt { + descriptor: candidate.descriptor.clone(), + commitments_hash: candidate.commitments.hash(), + }; - Self::deposit_event(Event::::CandidateTimedOut( - candidate, - commitments.head_data, - pending.core, - )); - } + Self::deposit_event(Event::::CandidateTimedOut( + receipt, + candidate.commitments.head_data.clone(), + candidate.core, + )); } - cleaned_up_cores + timed_out_cores } - /// Cleans up all paras pending availability that are in the given list of disputed candidates. + /// Cleans up all cores pending availability occupied by one of the disputed candidates or which + /// are descendants of a disputed candidate. /// - /// Returns a vector of cleaned-up core IDs. - pub(crate) fn collect_disputed(disputed: &BTreeSet) -> Vec { - let mut cleaned_up_ids = Vec::new(); - let mut cleaned_up_cores = Vec::new(); - - for (para_id, pending_record) in >::iter() { - if disputed.contains(&pending_record.hash) { - cleaned_up_ids.push(para_id); - cleaned_up_cores.push(pending_record.core); + /// Returns a vector of cleaned-up core IDs, along with the evicted candidate hashes. + pub(crate) fn free_disputed( + disputed: &BTreeSet, + ) -> Vec<(CoreIndex, CandidateHash)> { + Self::free_failed_cores( + |candidate| disputed.contains(&candidate.hash), + Some(disputed.len()), + ) + .map(|candidate| (candidate.core, candidate.hash)) + .collect() + } + + // Clean up cores whose candidates are deemed as failed by the predicate. `pred` returns true if + // a candidate is considered failed. + // A failed candidate also frees all subsequent cores which hold descendants of said candidate. + fn free_failed_cores< + P: Fn(&CandidatePendingAvailability>) -> bool, + >( + pred: P, + capacity_hint: Option, + ) -> impl Iterator>> { + let mut earliest_dropped_indices: BTreeMap = BTreeMap::new(); + + for (para_id, pending_candidates) in >::iter() { + // We assume that pending candidates are stored in dependency order. So we need to store + // the earliest dropped candidate. All others that follow will get freed as well. + let mut earliest_dropped_idx = None; + for (index, candidate) in pending_candidates.iter().enumerate() { + if pred(candidate) { + earliest_dropped_idx = Some(index); + // Since we're looping the candidates in dependency order, we've found the + // earliest failed index for this paraid. + break; + } + } + + if let Some(earliest_dropped_idx) = earliest_dropped_idx { + earliest_dropped_indices.insert(para_id, earliest_dropped_idx); } } - for para_id in cleaned_up_ids { - let _ = >::take(¶_id); - let _ = >::take(¶_id); + let mut cleaned_up_cores = + if let Some(capacity) = capacity_hint { Vec::with_capacity(capacity) } else { vec![] }; + + for (para_id, earliest_dropped_idx) in earliest_dropped_indices { + // Do cleanups and record the cleaned up cores + >::mutate(¶_id, |record| { + if let Some(record) = record { + let cleaned_up = record.drain(earliest_dropped_idx..); + cleaned_up_cores.extend(cleaned_up); + } + }); } - cleaned_up_cores + cleaned_up_cores.into_iter() } - /// Forcibly enact the candidate with the given ID as though it had been deemed available - /// by bitfields. + /// Forcibly enact the pending candidates of the given paraid as though they had been deemed + /// available by bitfields. /// /// Is a no-op if there is no candidate pending availability for this para-id. - /// This should generally not be used but it is useful during execution of Runtime APIs, + /// If there are multiple candidates pending availability for this para-id, it will enact all of + /// them. This should generally not be used but it is useful during execution of Runtime APIs, /// where the changes to the state are expected to be discarded directly after. pub(crate) fn force_enact(para: ParaId) { - let pending = >::take(¶); - let commitments = >::take(¶); - - if let (Some(pending), Some(commitments)) = (pending, commitments) { - let candidate = - CommittedCandidateReceipt { descriptor: pending.descriptor, commitments }; - - Self::enact_candidate( - pending.relay_parent_number, - candidate, - pending.backers, - pending.availability_votes, - pending.core, - pending.backing_group, - ); - } + >::mutate(¶, |candidates| { + if let Some(candidates) = candidates { + for candidate in candidates.drain(..) { + let receipt = CommittedCandidateReceipt { + descriptor: candidate.descriptor, + commitments: candidate.commitments, + }; + + Self::enact_candidate( + candidate.relay_parent_number, + receipt, + candidate.backers, + candidate.availability_votes, + candidate.core, + candidate.backing_group, + ); + } + } + }); } - /// Returns the `CommittedCandidateReceipt` pending availability for the para provided, if any. + /// Returns the first `CommittedCandidateReceipt` pending availability for the para provided, if + /// any. pub(crate) fn candidate_pending_availability( para: ParaId, ) -> Option> { - >::get(¶) - .map(|p| p.descriptor) - .and_then(|d| >::get(¶).map(move |c| (d, c))) - .map(|(d, c)| CommittedCandidateReceipt { descriptor: d, commitments: c }) + >::get(¶).and_then(|p| { + p.get(0).map(|p| CommittedCandidateReceipt { + descriptor: p.descriptor.clone(), + commitments: p.commitments.clone(), + }) + }) } - /// Returns the metadata around the candidate pending availability for the + /// Returns the metadata around the first candidate pending availability for the /// para provided, if any. pub(crate) fn pending_availability( para: ParaId, + ) -> Option>> { + >::get(¶).and_then(|p| p.get(0).cloned()) + } + + /// Returns the metadata around the candidate pending availability occupying the supplied core, + /// if any. + pub(crate) fn pending_availability_with_core( + para: ParaId, + core: CoreIndex, ) -> Option>> { >::get(¶) + .and_then(|p| p.iter().find(|c| c.core == core).cloned()) } } @@ -1182,10 +1170,6 @@ pub(crate) struct CandidateCheckContext { prev_context: Option>, } -/// An error indicating that creating Persisted Validation Data failed -/// while checking a candidate's validity. -pub(crate) struct FailedToCreatePVD; - impl CandidateCheckContext { pub(crate) fn new(prev_context: Option>) -> Self { Self { config: >::config(), prev_context } @@ -1203,9 +1187,9 @@ impl CandidateCheckContext { pub(crate) fn verify_backed_candidate( &self, allowed_relay_parents: &AllowedRelayParentsTracker>, - candidate_idx: usize, backed_candidate_receipt: &CommittedCandidateReceipt<::Hash>, - ) -> Result, FailedToCreatePVD>, Error> { + parent_head_data: HeadData, + ) -> Result, Error> { let para_id = backed_candidate_receipt.descriptor().para_id; let relay_parent = backed_candidate_receipt.descriptor().relay_parent; @@ -1218,16 +1202,11 @@ impl CandidateCheckContext { }; { - let persisted_validation_data = match crate::util::make_persisted_validation_data::( - para_id, + let persisted_validation_data = make_persisted_validation_data_with_parent::( relay_parent_number, relay_parent_storage_root, - ) - .defensive_proof("the para is registered") - { - Some(l) => l, - None => return Ok(Err(FailedToCreatePVD)), - }; + parent_head_data, + ); let expected = persisted_validation_data.hash(); @@ -1268,13 +1247,13 @@ impl CandidateCheckContext { ) { log::debug!( target: LOG_TARGET, - "Validation outputs checking during inclusion of a candidate {} for parachain `{}` failed", - candidate_idx, + "Validation outputs checking during inclusion of a candidate {:?} for parachain `{}` failed", + backed_candidate_receipt.hash(), u32::from(para_id), ); Err(err.strip_into_dispatch_err::())?; }; - Ok(Ok(relay_parent_number)) + Ok(relay_parent_number) } /// Check the given outputs after candidate validation on whether it passes the acceptance diff --git a/polkadot/runtime/parachains/src/inclusion/tests.rs b/polkadot/runtime/parachains/src/inclusion/tests.rs index 3fe7d7f0c7d..5ab3a13324d 100644 --- a/polkadot/runtime/parachains/src/inclusion/tests.rs +++ b/polkadot/runtime/parachains/src/inclusion/tests.rs @@ -27,7 +27,7 @@ use crate::{ shared::AllowedRelayParentsTracker, }; use primitives::{ - effective_minimum_backing_votes, SignedAvailabilityBitfields, + effective_minimum_backing_votes, AvailabilityBitfield, SignedAvailabilityBitfields, UncheckedSignedAvailabilityBitfields, }; @@ -360,81 +360,288 @@ fn simple_sanitize_bitfields( } /// Process a set of already sanitized bitfields. pub(crate) fn process_bitfields( - expected_bits: usize, signed_bitfields: SignedAvailabilityBitfields, - core_lookup: impl Fn(CoreIndex) -> Option, ) -> Vec<(CoreIndex, CandidateHash)> { let validators = shared::Pallet::::active_validator_keys(); - ParaInclusion::update_pending_availability_and_get_freed_cores::<_>( - expected_bits, + ParaInclusion::update_pending_availability_and_get_freed_cores( &validators[..], signed_bitfields, - core_lookup, ) } #[test] -fn collect_pending_cleans_up_pending() { +fn free_timedout() { let chain_a = ParaId::from(1_u32); let chain_b = ParaId::from(2_u32); - let thread_a = ParaId::from(3_u32); + let chain_c = ParaId::from(3_u32); + let chain_d = ParaId::from(4_u32); + let chain_e = ParaId::from(5_u32); + let chain_f = ParaId::from(6_u32); + let thread_a = ParaId::from(7_u32); let paras = vec![ (chain_a, ParaKind::Parachain), (chain_b, ParaKind::Parachain), + (chain_c, ParaKind::Parachain), + (chain_d, ParaKind::Parachain), + (chain_e, ParaKind::Parachain), + (chain_f, ParaKind::Parachain), (thread_a, ParaKind::Parathread), ]; let mut config = genesis_config(paras); config.configuration.config.scheduler_params.group_rotation_frequency = 3; new_test_ext(config).execute_with(|| { - let default_candidate = TestCandidateBuilder::default().build(); - >::insert( - chain_a, + let timed_out_cores = ParaInclusion::free_timedout(); + assert!(timed_out_cores.is_empty()); + + let make_candidate = |core_index: u32, timed_out: bool| { + let default_candidate = TestCandidateBuilder::default().build(); + let backed_in_number = if timed_out { 0 } else { 5 }; + CandidatePendingAvailability { - core: CoreIndex::from(0), + core: CoreIndex::from(core_index), hash: default_candidate.hash(), descriptor: default_candidate.descriptor.clone(), availability_votes: default_availability_votes(), relay_parent_number: 0, - backed_in_number: 0, + backed_in_number, backers: default_backing_bitfield(), - backing_group: GroupIndex::from(0), - }, - ); - PendingAvailabilityCommitments::::insert( + backing_group: GroupIndex::from(core_index), + commitments: default_candidate.commitments.clone(), + } + }; + + >::insert( chain_a, - default_candidate.commitments.clone(), + [make_candidate(0, true)].into_iter().collect::>(), ); >::insert( &chain_b, + [make_candidate(1, false)].into_iter().collect::>(), + ); + + // 2 chained candidates. The first one is timed out. The other will be evicted also. + let mut c_candidates = VecDeque::new(); + c_candidates.push_back(make_candidate(2, true)); + c_candidates.push_back(make_candidate(3, false)); + + >::insert(&chain_c, c_candidates); + + // 2 chained candidates. All are timed out. + let mut d_candidates = VecDeque::new(); + d_candidates.push_back(make_candidate(4, true)); + d_candidates.push_back(make_candidate(5, true)); + + >::insert(&chain_d, d_candidates); + + // 3 chained candidates. The second one is timed out. The first one will remain in place. + // With the current time out predicate this scenario is impossible. But this is not a + // concern for this module. + let mut e_candidates = VecDeque::new(); + e_candidates.push_back(make_candidate(6, false)); + e_candidates.push_back(make_candidate(7, true)); + e_candidates.push_back(make_candidate(8, false)); + + >::insert(&chain_e, e_candidates); + + // 3 chained candidates, none are timed out. + let mut f_candidates = VecDeque::new(); + f_candidates.push_back(make_candidate(9, false)); + f_candidates.push_back(make_candidate(10, false)); + f_candidates.push_back(make_candidate(11, false)); + + >::insert(&chain_f, f_candidates); + + run_to_block(5, |_| None); + + assert_eq!(>::get(&chain_a).unwrap().len(), 1); + assert_eq!(>::get(&chain_b).unwrap().len(), 1); + assert_eq!(>::get(&chain_c).unwrap().len(), 2); + assert_eq!(>::get(&chain_d).unwrap().len(), 2); + assert_eq!(>::get(&chain_e).unwrap().len(), 3); + assert_eq!(>::get(&chain_f).unwrap().len(), 3); + + let timed_out_cores = ParaInclusion::free_timedout(); + + assert_eq!( + timed_out_cores, + vec![ + CoreIndex(0), + CoreIndex(2), + CoreIndex(3), + CoreIndex(4), + CoreIndex(5), + CoreIndex(7), + CoreIndex(8), + ] + ); + + assert!(>::get(&chain_a).unwrap().is_empty()); + assert_eq!(>::get(&chain_b).unwrap().len(), 1); + assert!(>::get(&chain_c).unwrap().is_empty()); + assert!(>::get(&chain_d).unwrap().is_empty()); + assert_eq!( + >::get(&chain_e) + .unwrap() + .into_iter() + .map(|c| c.core) + .collect::>(), + vec![CoreIndex(6)] + ); + assert_eq!( + >::get(&chain_f) + .unwrap() + .into_iter() + .map(|c| c.core) + .collect::>(), + vec![CoreIndex(9), CoreIndex(10), CoreIndex(11)] + ); + }); +} + +#[test] +fn free_disputed() { + let chain_a = ParaId::from(1_u32); + let chain_b = ParaId::from(2_u32); + let chain_c = ParaId::from(3_u32); + let chain_d = ParaId::from(4_u32); + let chain_e = ParaId::from(5_u32); + let chain_f = ParaId::from(6_u32); + let thread_a = ParaId::from(7_u32); + + let paras = vec![ + (chain_a, ParaKind::Parachain), + (chain_b, ParaKind::Parachain), + (chain_c, ParaKind::Parachain), + (chain_d, ParaKind::Parachain), + (chain_e, ParaKind::Parachain), + (chain_f, ParaKind::Parachain), + (thread_a, ParaKind::Parathread), + ]; + let mut config = genesis_config(paras); + config.configuration.config.scheduler_params.group_rotation_frequency = 3; + new_test_ext(config).execute_with(|| { + let disputed_cores = ParaInclusion::free_disputed(&BTreeSet::new()); + assert!(disputed_cores.is_empty()); + + let disputed_cores = ParaInclusion::free_disputed( + &[CandidateHash::default()].into_iter().collect::>(), + ); + assert!(disputed_cores.is_empty()); + + let make_candidate = |core_index: u32| { + let default_candidate = TestCandidateBuilder::default().build(); + CandidatePendingAvailability { - core: CoreIndex::from(1), - hash: default_candidate.hash(), - descriptor: default_candidate.descriptor, + core: CoreIndex::from(core_index), + hash: CandidateHash(Hash::from_low_u64_be(core_index as _)), + descriptor: default_candidate.descriptor.clone(), availability_votes: default_availability_votes(), relay_parent_number: 0, - backed_in_number: 5, + backed_in_number: 0, backers: default_backing_bitfield(), - backing_group: GroupIndex::from(1), - }, + backing_group: GroupIndex::from(core_index), + commitments: default_candidate.commitments.clone(), + } + }; + + // Disputed + >::insert( + chain_a, + [make_candidate(0)].into_iter().collect::>(), + ); + + // Not disputed. + >::insert( + &chain_b, + [make_candidate(1)].into_iter().collect::>(), ); - PendingAvailabilityCommitments::::insert(chain_b, default_candidate.commitments); + + // 2 chained candidates. The first one is disputed. The other will be evicted also. + let mut c_candidates = VecDeque::new(); + c_candidates.push_back(make_candidate(2)); + c_candidates.push_back(make_candidate(3)); + + >::insert(&chain_c, c_candidates); + + // 2 chained candidates. All are disputed. + let mut d_candidates = VecDeque::new(); + d_candidates.push_back(make_candidate(4)); + d_candidates.push_back(make_candidate(5)); + + >::insert(&chain_d, d_candidates); + + // 3 chained candidates. The second one is disputed. The first one will remain in place. + let mut e_candidates = VecDeque::new(); + e_candidates.push_back(make_candidate(6)); + e_candidates.push_back(make_candidate(7)); + e_candidates.push_back(make_candidate(8)); + + >::insert(&chain_e, e_candidates); + + // 3 chained candidates, none are disputed. + let mut f_candidates = VecDeque::new(); + f_candidates.push_back(make_candidate(9)); + f_candidates.push_back(make_candidate(10)); + f_candidates.push_back(make_candidate(11)); + + >::insert(&chain_f, f_candidates); run_to_block(5, |_| None); - assert!(>::get(&chain_a).is_some()); - assert!(>::get(&chain_b).is_some()); - assert!(>::get(&chain_a).is_some()); - assert!(>::get(&chain_b).is_some()); + assert_eq!(>::get(&chain_a).unwrap().len(), 1); + assert_eq!(>::get(&chain_b).unwrap().len(), 1); + assert_eq!(>::get(&chain_c).unwrap().len(), 2); + assert_eq!(>::get(&chain_d).unwrap().len(), 2); + assert_eq!(>::get(&chain_e).unwrap().len(), 3); + assert_eq!(>::get(&chain_f).unwrap().len(), 3); + + let disputed_candidates = [ + CandidateHash(Hash::from_low_u64_be(0)), + CandidateHash(Hash::from_low_u64_be(2)), + CandidateHash(Hash::from_low_u64_be(4)), + CandidateHash(Hash::from_low_u64_be(5)), + CandidateHash(Hash::from_low_u64_be(7)), + ] + .into_iter() + .collect::>(); + let disputed_cores = ParaInclusion::free_disputed(&disputed_candidates); - ParaInclusion::collect_pending(Scheduler::availability_timeout_predicate()); + assert_eq!( + disputed_cores.into_iter().map(|(core, _)| core).collect::>(), + vec![ + CoreIndex(0), + CoreIndex(2), + CoreIndex(3), + CoreIndex(4), + CoreIndex(5), + CoreIndex(7), + CoreIndex(8), + ] + ); - assert!(>::get(&chain_a).is_none()); - assert!(>::get(&chain_b).is_some()); - assert!(>::get(&chain_a).is_none()); - assert!(>::get(&chain_b).is_some()); + assert!(>::get(&chain_a).unwrap().is_empty()); + assert_eq!(>::get(&chain_b).unwrap().len(), 1); + assert!(>::get(&chain_c).unwrap().is_empty()); + assert!(>::get(&chain_d).unwrap().is_empty()); + assert_eq!( + >::get(&chain_e) + .unwrap() + .into_iter() + .map(|c| c.core) + .collect::>(), + vec![CoreIndex(6)] + ); + assert_eq!( + >::get(&chain_f) + .unwrap() + .into_iter() + .map(|c| c.core) + .collect::>(), + vec![CoreIndex(9), CoreIndex(10), CoreIndex(11)] + ); }); } @@ -474,14 +681,6 @@ fn bitfield_checks() { let signing_context = SigningContext { parent_hash: System::parent_hash(), session_index: 5 }; - let core_lookup = |core| match core { - core if core == CoreIndex::from(0) => Some(chain_a), - core if core == CoreIndex::from(1) => Some(chain_b), - core if core == CoreIndex::from(2) => Some(thread_a), - core if core == CoreIndex::from(3) => None, // for the expected_cores() + 1 test below. - _ => panic!("out of bounds for testing"), - }; - // too many bits in bitfield { let mut bare_bitfield = default_bitfield(); @@ -550,7 +749,7 @@ fn bitfield_checks() { ); assert_eq!(checked_bitfields.len(), 1, "No bitfields should have been filtered!"); - let x = process_bitfields(expected_bits(), checked_bitfields, core_lookup); + let x = process_bitfields(checked_bitfields); assert!(x.is_empty(), "No core should be freed."); } @@ -571,7 +770,7 @@ fn bitfield_checks() { ); assert_eq!(checked_bitfields.len(), 1, "No bitfields should have been filtered!"); - let x = process_bitfields(expected_bits(), checked_bitfields, core_lookup); + let x = process_bitfields(checked_bitfields); assert!(x.is_empty(), "No core should be freed."); } @@ -579,12 +778,10 @@ fn bitfield_checks() { { let mut bare_bitfield = default_bitfield(); - assert_eq!(core_lookup(CoreIndex::from(0)), Some(chain_a)); - let default_candidate = TestCandidateBuilder::default().build(); >::insert( chain_a, - CandidatePendingAvailability { + [CandidatePendingAvailability { core: CoreIndex::from(0), hash: default_candidate.hash(), descriptor: default_candidate.descriptor, @@ -593,9 +790,11 @@ fn bitfield_checks() { backed_in_number: 0, backers: default_backing_bitfield(), backing_group: GroupIndex::from(0), - }, + commitments: default_candidate.commitments, + }] + .into_iter() + .collect::>(), ); - PendingAvailabilityCommitments::::insert(chain_a, default_candidate.commitments); *bare_bitfield.0.get_mut(0).unwrap() = true; let signed = sign_bitfield( @@ -613,53 +812,10 @@ fn bitfield_checks() { ); assert_eq!(checked_bitfields.len(), 1, "No bitfields should have been filtered!"); - let x = process_bitfields(expected_bits(), checked_bitfields, core_lookup); + let x = process_bitfields(checked_bitfields); assert!(x.is_empty(), "No core should be freed."); >::remove(chain_a); - PendingAvailabilityCommitments::::remove(chain_a); - } - - // bitfield signed with pending bit signed, but no commitments. - { - let mut bare_bitfield = default_bitfield(); - - assert_eq!(core_lookup(CoreIndex::from(0)), Some(chain_a)); - - let default_candidate = TestCandidateBuilder::default().build(); - >::insert( - chain_a, - CandidatePendingAvailability { - core: CoreIndex::from(0), - hash: default_candidate.hash(), - descriptor: default_candidate.descriptor, - availability_votes: default_availability_votes(), - relay_parent_number: 0, - backed_in_number: 0, - backers: default_backing_bitfield(), - backing_group: GroupIndex::from(0), - }, - ); - - *bare_bitfield.0.get_mut(0).unwrap() = true; - let signed = sign_bitfield( - &keystore, - &validators[0], - ValidatorIndex(0), - bare_bitfield, - &signing_context, - ); - - let checked_bitfields = simple_sanitize_bitfields( - vec![signed.into()], - DisputedBitfield::zeros(expected_bits()), - expected_bits(), - ); - assert_eq!(checked_bitfields.len(), 1, "No bitfields should have been filtered!"); - - let x = process_bitfields(expected_bits(), checked_bitfields, core_lookup); - // no core is freed - assert!(x.is_empty(), "No core should be freed."); } }); } @@ -673,13 +829,17 @@ fn availability_threshold_is_supermajority() { #[test] fn supermajority_bitfields_trigger_availability() { - let chain_a = ParaId::from(1_u32); - let chain_b = ParaId::from(2_u32); - let thread_a = ParaId::from(3_u32); + let chain_a = ParaId::from(0_u32); + let chain_b = ParaId::from(1_u32); + let chain_c = ParaId::from(2_u32); + let chain_d = ParaId::from(3_u32); + let thread_a = ParaId::from(4_u32); let paras = vec![ (chain_a, ParaKind::Parachain), (chain_b, ParaKind::Parachain), + (chain_c, ParaKind::Parachain), + (chain_d, ParaKind::Parachain), (thread_a, ParaKind::Parathread), ]; let validators = vec![ @@ -688,6 +848,8 @@ fn supermajority_bitfields_trigger_availability() { Sr25519Keyring::Charlie, Sr25519Keyring::Dave, Sr25519Keyring::Ferdie, + Sr25519Keyring::One, + Sr25519Keyring::Two, ]; let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); for validator in validators.iter() { @@ -707,13 +869,7 @@ fn supermajority_bitfields_trigger_availability() { let signing_context = SigningContext { parent_hash: System::parent_hash(), session_index: 5 }; - let core_lookup = |core| match core { - core if core == CoreIndex::from(0) => Some(chain_a), - core if core == CoreIndex::from(1) => Some(chain_b), - core if core == CoreIndex::from(2) => Some(thread_a), - _ => panic!("Core out of bounds for 2 parachains and 1 parathread core."), - }; - + // Chain A only has one candidate pending availability. It will be made available now. let candidate_a = TestCandidateBuilder { para_id: chain_a, head_data: vec![1, 2, 3, 4].into(), @@ -723,7 +879,7 @@ fn supermajority_bitfields_trigger_availability() { >::insert( chain_a, - CandidatePendingAvailability { + [CandidatePendingAvailability { core: CoreIndex::from(0), hash: candidate_a.hash(), descriptor: candidate_a.clone().descriptor, @@ -732,10 +888,13 @@ fn supermajority_bitfields_trigger_availability() { backed_in_number: 0, backers: backing_bitfield(&[3, 4]), backing_group: GroupIndex::from(0), - }, + commitments: candidate_a.clone().commitments, + }] + .into_iter() + .collect::>(), ); - PendingAvailabilityCommitments::::insert(chain_a, candidate_a.clone().commitments); + // Chain B only has one candidate pending availability. It won't be made available now. let candidate_b = TestCandidateBuilder { para_id: chain_b, head_data: vec![5, 6, 7, 8].into(), @@ -745,7 +904,7 @@ fn supermajority_bitfields_trigger_availability() { >::insert( chain_b, - CandidatePendingAvailability { + [CandidatePendingAvailability { core: CoreIndex::from(1), hash: candidate_b.hash(), descriptor: candidate_b.descriptor, @@ -754,40 +913,99 @@ fn supermajority_bitfields_trigger_availability() { backed_in_number: 0, backers: backing_bitfield(&[0, 2]), backing_group: GroupIndex::from(1), - }, + commitments: candidate_b.commitments, + }] + .into_iter() + .collect::>(), ); - PendingAvailabilityCommitments::::insert(chain_b, candidate_b.commitments); - // this bitfield signals that a and b are available. - let a_and_b_available = { - let mut bare_bitfield = default_bitfield(); - *bare_bitfield.0.get_mut(0).unwrap() = true; - *bare_bitfield.0.get_mut(1).unwrap() = true; + // Chain C has three candidates pending availability. The first and third candidates will be + // made available. Only the first candidate will be evicted from the core and enacted. + let candidate_c_1 = TestCandidateBuilder { + para_id: chain_c, + head_data: vec![7, 8].into(), + ..Default::default() + } + .build(); + let candidate_c_2 = TestCandidateBuilder { + para_id: chain_c, + head_data: vec![9, 10].into(), + ..Default::default() + } + .build(); + let candidate_c_3 = TestCandidateBuilder { + para_id: chain_c, + head_data: vec![11, 12].into(), + ..Default::default() + } + .build(); - bare_bitfield - }; + let mut c_candidates = VecDeque::new(); + c_candidates.push_back(CandidatePendingAvailability { + core: CoreIndex::from(2), + hash: candidate_c_1.hash(), + descriptor: candidate_c_1.descriptor.clone(), + availability_votes: default_availability_votes(), + relay_parent_number: 0, + backed_in_number: 0, + backers: backing_bitfield(&[1]), + backing_group: GroupIndex::from(2), + commitments: candidate_c_1.commitments.clone(), + }); + c_candidates.push_back(CandidatePendingAvailability { + core: CoreIndex::from(3), + hash: candidate_c_2.hash(), + descriptor: candidate_c_2.descriptor.clone(), + availability_votes: default_availability_votes(), + relay_parent_number: 0, + backed_in_number: 0, + backers: backing_bitfield(&[5]), + backing_group: GroupIndex::from(3), + commitments: candidate_c_2.commitments.clone(), + }); + c_candidates.push_back(CandidatePendingAvailability { + core: CoreIndex::from(4), + hash: candidate_c_3.hash(), + descriptor: candidate_c_3.descriptor.clone(), + availability_votes: default_availability_votes(), + relay_parent_number: 0, + backed_in_number: 0, + backers: backing_bitfield(&[6]), + backing_group: GroupIndex::from(4), + commitments: candidate_c_3.commitments.clone(), + }); - // this bitfield signals that only a is available. - let a_available = { + >::insert(chain_c, c_candidates); + + // this bitfield signals that a and b are available. + let all_available = { let mut bare_bitfield = default_bitfield(); - *bare_bitfield.0.get_mut(0).unwrap() = true; + for bit in 0..=4 { + *bare_bitfield.0.get_mut(bit).unwrap() = true; + } bare_bitfield }; let threshold = availability_threshold(validators.len()); - // 4 of 5 first value >= 2/3 - assert_eq!(threshold, 4); + // 5 of 7 first value >= 2/3 + assert_eq!(threshold, 5); let signed_bitfields = validators .iter() .enumerate() .filter_map(|(i, key)| { - let to_sign = if i < 3 { - a_and_b_available.clone() - } else if i < 4 { - a_available.clone() + let to_sign = if i < 4 { + all_available.clone() + } else if i < 5 { + // this bitfield signals that only a, c1 and c3 are available. + let mut bare_bitfield = default_bitfield(); + *bare_bitfield.0.get_mut(0).unwrap() = true; + *bare_bitfield.0.get_mut(2).unwrap() = true; + *bare_bitfield.0.get_mut(4).unwrap() = true; + + bare_bitfield } else { // sign nothing. return None @@ -814,46 +1032,129 @@ fn supermajority_bitfields_trigger_availability() { ); assert_eq!(checked_bitfields.len(), old_len, "No bitfields should have been filtered!"); - // only chain A's core is freed. - let v = process_bitfields(expected_bits(), checked_bitfields, core_lookup); - assert_eq!(vec![(CoreIndex(0), candidate_a.hash())], v); - - // chain A had 4 signing off, which is >= threshold. - // chain B has 3 signing off, which is < threshold. - assert!(>::get(&chain_a).is_none()); - assert!(>::get(&chain_a).is_none()); - assert!(>::get(&chain_b).is_some()); - assert_eq!(>::get(&chain_b).unwrap().availability_votes, { - // check that votes from first 3 were tracked. + // only chain A's core and candidate's C1 core are freed. + let v = process_bitfields(checked_bitfields); + assert_eq!( + vec![(CoreIndex(2), candidate_c_1.hash()), (CoreIndex(0), candidate_a.hash())], + v + ); + let votes = |bits: &[usize]| { let mut votes = default_availability_votes(); - *votes.get_mut(0).unwrap() = true; - *votes.get_mut(1).unwrap() = true; - *votes.get_mut(2).unwrap() = true; + for bit in bits { + *votes.get_mut(*bit).unwrap() = true; + } votes - }); + }; - // and check that chain head was enacted. + assert!(>::get(&chain_a).unwrap().is_empty()); + assert_eq!( + >::get(&chain_b) + .unwrap() + .pop_front() + .unwrap() + .availability_votes, + votes(&[0, 1, 2, 3]) + ); + let mut pending_c = >::get(&chain_c).unwrap(); + assert_eq!(pending_c.pop_front().unwrap().availability_votes, votes(&[0, 1, 2, 3])); + assert_eq!(pending_c.pop_front().unwrap().availability_votes, votes(&[0, 1, 2, 3, 4])); + assert!(pending_c.is_empty()); + + // and check that chain heads. assert_eq!(Paras::para_head(&chain_a), Some(vec![1, 2, 3, 4].into())); + assert_ne!(Paras::para_head(&chain_b), Some(vec![5, 6, 7, 8].into())); + assert_eq!(Paras::para_head(&chain_c), Some(vec![7, 8].into())); // Check that rewards are applied. { let rewards = crate::mock::availability_rewards(); - assert_eq!(rewards.len(), 4); - assert_eq!(rewards.get(&ValidatorIndex(0)).unwrap(), &1); - assert_eq!(rewards.get(&ValidatorIndex(1)).unwrap(), &1); - assert_eq!(rewards.get(&ValidatorIndex(2)).unwrap(), &1); + assert_eq!(rewards.len(), 5); + assert_eq!(rewards.get(&ValidatorIndex(0)).unwrap(), &2); + assert_eq!(rewards.get(&ValidatorIndex(1)).unwrap(), &2); + assert_eq!(rewards.get(&ValidatorIndex(2)).unwrap(), &2); + assert_eq!(rewards.get(&ValidatorIndex(3)).unwrap(), &2); + assert_eq!(rewards.get(&ValidatorIndex(4)).unwrap(), &2); + } + + { + let rewards = crate::mock::backing_rewards(); + + assert_eq!(rewards.len(), 3); assert_eq!(rewards.get(&ValidatorIndex(3)).unwrap(), &1); + assert_eq!(rewards.get(&ValidatorIndex(4)).unwrap(), &1); + assert_eq!(rewards.get(&ValidatorIndex(1)).unwrap(), &1); + } + + // Add a new bitfield which will make candidate C2 available also. This will also evict and + // enact C3. + let signed_bitfields = vec![sign_bitfield( + &keystore, + &validators[5], + ValidatorIndex(5), + { + let mut bare_bitfield = default_bitfield(); + *bare_bitfield.0.get_mut(3).unwrap() = true; + bare_bitfield + }, + &signing_context, + ) + .into()]; + + let old_len = signed_bitfields.len(); + let checked_bitfields = simple_sanitize_bitfields( + signed_bitfields, + DisputedBitfield::zeros(expected_bits()), + expected_bits(), + ); + assert_eq!(checked_bitfields.len(), old_len, "No bitfields should have been filtered!"); + + let v = process_bitfields(checked_bitfields); + assert_eq!( + vec![(CoreIndex(3), candidate_c_2.hash()), (CoreIndex(4), candidate_c_3.hash())], + v + ); + + assert!(>::get(&chain_a).unwrap().is_empty()); + assert_eq!( + >::get(&chain_b) + .unwrap() + .pop_front() + .unwrap() + .availability_votes, + votes(&[0, 1, 2, 3]) + ); + assert!(>::get(&chain_c).unwrap().is_empty()); + + // and check that chain heads. + assert_eq!(Paras::para_head(&chain_a), Some(vec![1, 2, 3, 4].into())); + assert_ne!(Paras::para_head(&chain_b), Some(vec![5, 6, 7, 8].into())); + assert_eq!(Paras::para_head(&chain_c), Some(vec![11, 12].into())); + + // Check that rewards are applied. + { + let rewards = crate::mock::availability_rewards(); + + assert_eq!(rewards.len(), 6); + assert_eq!(rewards.get(&ValidatorIndex(0)).unwrap(), &4); + assert_eq!(rewards.get(&ValidatorIndex(1)).unwrap(), &4); + assert_eq!(rewards.get(&ValidatorIndex(2)).unwrap(), &4); + assert_eq!(rewards.get(&ValidatorIndex(3)).unwrap(), &4); + assert_eq!(rewards.get(&ValidatorIndex(4)).unwrap(), &3); + assert_eq!(rewards.get(&ValidatorIndex(5)).unwrap(), &1); } { let rewards = crate::mock::backing_rewards(); - assert_eq!(rewards.len(), 2); + assert_eq!(rewards.len(), 5); assert_eq!(rewards.get(&ValidatorIndex(3)).unwrap(), &1); assert_eq!(rewards.get(&ValidatorIndex(4)).unwrap(), &1); + assert_eq!(rewards.get(&ValidatorIndex(1)).unwrap(), &1); + assert_eq!(rewards.get(&ValidatorIndex(5)).unwrap(), &1); + assert_eq!(rewards.get(&ValidatorIndex(6)).unwrap(), &1); } }); } @@ -878,6 +1179,7 @@ fn candidate_checks() { Sr25519Keyring::Charlie, Sr25519Keyring::Dave, Sr25519Keyring::Ferdie, + Sr25519Keyring::One, ]; let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); for validator in validators.iter() { @@ -904,7 +1206,8 @@ fn candidate_checks() { group_index if group_index == GroupIndex::from(0) => Some(vec![0, 1]), group_index if group_index == GroupIndex::from(1) => Some(vec![2, 3]), group_index if group_index == GroupIndex::from(2) => Some(vec![4]), - _ => panic!("Group index out of bounds for 2 parachains and 1 parathread core"), + group_index if group_index == GroupIndex::from(3) => Some(vec![5]), + _ => panic!("Group index out of bounds"), } .map(|m| m.into_iter().map(ValidatorIndex).collect::>()) }; @@ -914,12 +1217,12 @@ fn candidate_checks() { vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2), ValidatorIndex(3)], vec![ValidatorIndex(4)], + vec![ValidatorIndex(5)], ]; Scheduler::set_validator_groups(validator_groups); let thread_collator: CollatorId = Sr25519Keyring::Two.public().into(); let chain_a_assignment = (chain_a, CoreIndex::from(0)); - let chain_b_assignment = (chain_b, CoreIndex::from(1)); let thread_a_assignment = (thread_a, CoreIndex::from(2)); @@ -929,14 +1232,14 @@ fn candidate_checks() { assert_eq!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![], + &BTreeMap::new(), &group_validators, false ), Ok(ProcessedCandidates::default()) ); - // candidates out of order. + // Check candidate ordering { let mut candidate_a = TestCandidateBuilder { para_id: chain_a, @@ -947,19 +1250,37 @@ fn candidate_checks() { ..Default::default() } .build(); - let mut candidate_b = TestCandidateBuilder { + let mut candidate_b_1 = TestCandidateBuilder { para_id: chain_b, relay_parent: System::parent_hash(), pov_hash: Hash::repeat_byte(2), persisted_validation_data_hash: make_vdata_hash(chain_b).unwrap(), hrmp_watermark: RELAY_PARENT_NUM, + head_data: HeadData(vec![1, 2, 3]), ..Default::default() } .build(); - collator_sign_candidate(Sr25519Keyring::One, &mut candidate_a); + // Make candidate b2 a child of b1. + let mut candidate_b_2 = TestCandidateBuilder { + para_id: chain_b, + relay_parent: System::parent_hash(), + pov_hash: Hash::repeat_byte(3), + persisted_validation_data_hash: make_persisted_validation_data_with_parent::( + RELAY_PARENT_NUM, + Default::default(), + candidate_b_1.commitments.head_data.clone(), + ) + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + head_data: HeadData(vec![5, 6, 7]), + ..Default::default() + } + .build(); - collator_sign_candidate(Sr25519Keyring::Two, &mut candidate_b); + collator_sign_candidate(Sr25519Keyring::One, &mut candidate_a); + collator_sign_candidate(Sr25519Keyring::Two, &mut candidate_b_1); + collator_sign_candidate(Sr25519Keyring::Two, &mut candidate_b_2); let backed_a = back_candidate( candidate_a, @@ -971,8 +1292,18 @@ fn candidate_checks() { None, ); - let backed_b = back_candidate( - candidate_b, + let backed_b_1 = back_candidate( + candidate_b_1.clone(), + &validators, + group_validators(GroupIndex::from(2)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + None, + ); + + let backed_b_2 = back_candidate( + candidate_b_2, &validators, group_validators(GroupIndex::from(1)).unwrap().as_ref(), &keystore, @@ -981,15 +1312,82 @@ fn candidate_checks() { None, ); - // out-of-order manifests as unscheduled. + // candidates are required to be sorted in dependency order. assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed_b, chain_b_assignment.1), (backed_a, chain_a_assignment.1)], + &vec![( + chain_b, + vec![ + (backed_b_2.clone(), CoreIndex(1)), + (backed_b_1.clone(), CoreIndex(2)) + ] + ),] + .into_iter() + .collect(), &group_validators, false ), - Error::::ScheduledOutOfOrder + Error::::ValidationDataHashMismatch + ); + + // candidates are no longer required to be sorted by core index. + ParaInclusion::process_candidates( + &allowed_relay_parents, + &vec![ + ( + chain_b, + vec![ + (backed_b_1.clone(), CoreIndex(2)), + (backed_b_2.clone(), CoreIndex(1)), + ], + ), + (chain_a_assignment.0, vec![(backed_a.clone(), chain_a_assignment.1)]), + ] + .into_iter() + .collect(), + &group_validators, + false, + ) + .unwrap(); + + // candidate does not build on top of the latest unincluded head + + let mut candidate_b_3 = TestCandidateBuilder { + para_id: chain_b, + relay_parent: System::parent_hash(), + pov_hash: Hash::repeat_byte(4), + persisted_validation_data_hash: make_persisted_validation_data_with_parent::( + RELAY_PARENT_NUM, + Default::default(), + candidate_b_1.commitments.head_data.clone(), + ) + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + head_data: HeadData(vec![8, 9]), + ..Default::default() + } + .build(); + collator_sign_candidate(Sr25519Keyring::Two, &mut candidate_b_3); + + let backed_b_3 = back_candidate( + candidate_b_3, + &validators, + group_validators(GroupIndex::from(3)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + None, + ); + + assert_noop!( + ParaInclusion::process_candidates( + &allowed_relay_parents, + &vec![(chain_b, vec![(backed_b_3, CoreIndex(3))])].into_iter().collect(), + &group_validators, + false + ), + Error::::ValidationDataHashMismatch ); } @@ -1006,8 +1404,9 @@ fn candidate_checks() { .build(); collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + // Insufficient backing. let backed = back_candidate( - candidate, + candidate.clone(), &validators, group_validators(GroupIndex::from(0)).unwrap().as_ref(), &keystore, @@ -1019,12 +1418,37 @@ fn candidate_checks() { assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed, chain_a_assignment.1)], + &vec![(chain_a_assignment.0, vec![(backed, chain_a_assignment.1)])] + .into_iter() + .collect(), &group_validators, false ), Error::::InsufficientBacking ); + + // Wrong backing group. + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(1)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + None, + ); + + assert_noop!( + ParaInclusion::process_candidates( + &allowed_relay_parents, + &vec![(chain_a_assignment.0, vec![(backed, chain_a_assignment.1)])] + .into_iter() + .collect(), + &group_validators, + false + ), + Error::::InvalidBacking + ); } // one of candidates is not based on allowed relay parent. @@ -1078,7 +1502,12 @@ fn candidate_checks() { assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed_b, chain_b_assignment.1), (backed_a, chain_a_assignment.1)], + &vec![ + (chain_b_assignment.0, vec![(backed_b, chain_b_assignment.1)]), + (chain_a_assignment.0, vec![(backed_a, chain_a_assignment.1)]) + ] + .into_iter() + .collect(), &group_validators, false ), @@ -1117,7 +1546,9 @@ fn candidate_checks() { assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed, thread_a_assignment.1)], + &vec![(thread_a_assignment.0, vec![(backed, thread_a_assignment.1)])] + .into_iter() + .collect(), &group_validators, false ), @@ -1125,100 +1556,6 @@ fn candidate_checks() { ); } - // para occupied - reject. - { - let mut candidate = TestCandidateBuilder { - para_id: chain_a, - relay_parent: System::parent_hash(), - pov_hash: Hash::repeat_byte(1), - persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(), - hrmp_watermark: RELAY_PARENT_NUM, - ..Default::default() - } - .build(); - - collator_sign_candidate(Sr25519Keyring::One, &mut candidate); - - let backed = back_candidate( - candidate, - &validators, - group_validators(GroupIndex::from(0)).unwrap().as_ref(), - &keystore, - &signing_context, - BackingKind::Threshold, - None, - ); - - let candidate = TestCandidateBuilder::default().build(); - >::insert( - &chain_a, - CandidatePendingAvailability { - core: CoreIndex::from(0), - hash: candidate.hash(), - descriptor: candidate.descriptor, - availability_votes: default_availability_votes(), - relay_parent_number: 3, - backed_in_number: 4, - backers: default_backing_bitfield(), - backing_group: GroupIndex::from(0), - }, - ); - >::insert(&chain_a, candidate.commitments); - - assert_noop!( - ParaInclusion::process_candidates( - &allowed_relay_parents, - vec![(backed, chain_a_assignment.1)], - &group_validators, - false - ), - Error::::CandidateScheduledBeforeParaFree - ); - - >::remove(&chain_a); - >::remove(&chain_a); - } - - // messed up commitments storage - do not panic - reject. - { - let mut candidate = TestCandidateBuilder { - para_id: chain_a, - relay_parent: System::parent_hash(), - pov_hash: Hash::repeat_byte(1), - persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(), - hrmp_watermark: RELAY_PARENT_NUM, - ..Default::default() - } - .build(); - - collator_sign_candidate(Sr25519Keyring::One, &mut candidate); - - // this is not supposed to happen - >::insert(&chain_a, candidate.commitments.clone()); - - let backed = back_candidate( - candidate, - &validators, - group_validators(GroupIndex::from(0)).unwrap().as_ref(), - &keystore, - &signing_context, - BackingKind::Threshold, - None, - ); - - assert_noop!( - ParaInclusion::process_candidates( - &allowed_relay_parents, - vec![(backed, chain_a_assignment.1)], - &group_validators, - false - ), - Error::::CandidateScheduledBeforeParaFree - ); - - >::remove(&chain_a); - } - // interfering code upgrade - reject { let mut candidate = TestCandidateBuilder { @@ -1260,7 +1597,9 @@ fn candidate_checks() { assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed, chain_a_assignment.1)], + &vec![(chain_a_assignment.0, vec![(backed, chain_a_assignment.1)])] + .into_iter() + .collect(), &group_validators, false ), @@ -1292,14 +1631,16 @@ fn candidate_checks() { None, ); - assert_eq!( + assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed, chain_a_assignment.1)], + &vec![(chain_a_assignment.0, vec![(backed, chain_a_assignment.1)])] + .into_iter() + .collect(), &group_validators, - false + false, ), - Err(Error::::ValidationDataHashMismatch.into()), + Error::::ValidationDataHashMismatch ); } @@ -1331,7 +1672,9 @@ fn candidate_checks() { assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed, chain_a_assignment.1)], + &vec![(chain_a_assignment.0, vec![(backed, chain_a_assignment.1)])] + .into_iter() + .collect(), &group_validators, false ), @@ -1367,7 +1710,9 @@ fn candidate_checks() { assert_noop!( ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed, chain_a_assignment.1)], + &vec![(chain_a_assignment.0, vec![(backed, chain_a_assignment.1)])] + .into_iter() + .collect(), &group_validators, false ), @@ -1506,16 +1851,21 @@ fn backing_works() { ); let backed_candidates = vec![ - (backed_a.clone(), chain_a_assignment.1), - (backed_b.clone(), chain_b_assignment.1), - (backed_c, thread_a_assignment.1), - ]; + (chain_a_assignment.0, vec![(backed_a, chain_a_assignment.1)]), + (chain_b_assignment.0, vec![(backed_b, chain_b_assignment.1)]), + (thread_a_assignment.0, vec![(backed_c, thread_a_assignment.1)]), + ] + .into_iter() + .collect::>(); + let get_backing_group_idx = { // the order defines the group implicitly for this test case let backed_candidates_with_groups = backed_candidates - .iter() + .values() .enumerate() - .map(|(idx, (backed_candidate, _))| (backed_candidate.hash(), GroupIndex(idx as _))) + .map(|(idx, backed_candidates)| { + (backed_candidates.iter().next().unwrap().0.hash(), GroupIndex(idx as _)) + }) .collect::>(); move |candidate_hash_x: CandidateHash| -> Option { @@ -1534,7 +1884,7 @@ fn backing_works() { candidate_receipt_with_backing_validator_indices, } = ParaInclusion::process_candidates( &allowed_relay_parents, - backed_candidates.clone(), + &backed_candidates, &group_validators, false, ) @@ -1555,7 +1905,8 @@ fn backing_works() { CandidateHash, (CandidateReceipt, Vec<(ValidatorIndex, ValidityAttestation)>), >::new(); - backed_candidates.into_iter().for_each(|(backed_candidate, _)| { + backed_candidates.values().for_each(|backed_candidates| { + let backed_candidate = backed_candidates.iter().next().unwrap().0.clone(); let candidate_receipt_with_backers = intermediate .entry(backed_candidate.hash()) .or_insert_with(|| (backed_candidate.receipt(), Vec::new())); @@ -1606,20 +1957,21 @@ fn backing_works() { }; assert_eq!( >::get(&chain_a), - Some(CandidatePendingAvailability { - core: CoreIndex::from(0), - hash: candidate_a.hash(), - descriptor: candidate_a.descriptor, - availability_votes: default_availability_votes(), - relay_parent_number: System::block_number() - 1, - backed_in_number: System::block_number(), - backers, - backing_group: GroupIndex::from(0), - }) - ); - assert_eq!( - >::get(&chain_a), - Some(candidate_a.commitments), + Some( + [CandidatePendingAvailability { + core: CoreIndex::from(0), + hash: candidate_a.hash(), + descriptor: candidate_a.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers, + backing_group: GroupIndex::from(0), + commitments: candidate_a.commitments, + }] + .into_iter() + .collect::>() + ) ); let backers = { @@ -1631,38 +1983,40 @@ fn backing_works() { }; assert_eq!( >::get(&chain_b), - Some(CandidatePendingAvailability { - core: CoreIndex::from(1), - hash: candidate_b.hash(), - descriptor: candidate_b.descriptor, - availability_votes: default_availability_votes(), - relay_parent_number: System::block_number() - 1, - backed_in_number: System::block_number(), - backers, - backing_group: GroupIndex::from(1), - }) - ); - assert_eq!( - >::get(&chain_b), - Some(candidate_b.commitments), + Some( + [CandidatePendingAvailability { + core: CoreIndex::from(1), + hash: candidate_b.hash(), + descriptor: candidate_b.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers, + backing_group: GroupIndex::from(1), + commitments: candidate_b.commitments, + }] + .into_iter() + .collect::>() + ) ); assert_eq!( >::get(&thread_a), - Some(CandidatePendingAvailability { - core: CoreIndex::from(2), - hash: candidate_c.hash(), - descriptor: candidate_c.descriptor, - availability_votes: default_availability_votes(), - relay_parent_number: System::block_number() - 1, - backed_in_number: System::block_number(), - backers: backing_bitfield(&[4]), - backing_group: GroupIndex::from(2), - }) - ); - assert_eq!( - >::get(&thread_a), - Some(candidate_c.commitments), + Some( + [CandidatePendingAvailability { + core: CoreIndex::from(2), + hash: candidate_c.hash(), + descriptor: candidate_c.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers: backing_bitfield(&[4]), + backing_group: GroupIndex::from(2), + commitments: candidate_c.commitments + }] + .into_iter() + .collect::>() + ) ); }); } @@ -1750,11 +2104,17 @@ fn backing_works_with_elastic_scaling_mvp() { .build(); collator_sign_candidate(Sr25519Keyring::One, &mut candidate_b_1); + // Make candidate b2 a child of b1. let mut candidate_b_2 = TestCandidateBuilder { para_id: chain_b, relay_parent: System::parent_hash(), pov_hash: Hash::repeat_byte(3), - persisted_validation_data_hash: make_vdata_hash(chain_b).unwrap(), + persisted_validation_data_hash: make_persisted_validation_data_with_parent::( + RELAY_PARENT_NUM, + Default::default(), + candidate_b_1.commitments.head_data.clone(), + ) + .hash(), hrmp_watermark: RELAY_PARENT_NUM, ..Default::default() } @@ -1791,18 +2151,25 @@ fn backing_works_with_elastic_scaling_mvp() { Some(CoreIndex(2)), ); - let backed_candidates = vec![ - (backed_a.clone(), CoreIndex(0)), - (backed_b_1.clone(), CoreIndex(1)), - (backed_b_2.clone(), CoreIndex(2)), - ]; + let mut backed_candidates = BTreeMap::new(); + backed_candidates.insert(chain_a, vec![(backed_a, CoreIndex(0))]); + backed_candidates + .insert(chain_b, vec![(backed_b_1, CoreIndex(1)), (backed_b_2, CoreIndex(2))]); + let get_backing_group_idx = { // the order defines the group implicitly for this test case let backed_candidates_with_groups = backed_candidates - .iter() + .values() .enumerate() - .map(|(idx, (backed_candidate, _))| (backed_candidate.hash(), GroupIndex(idx as _))) - .collect::>(); + .map(|(idx, backed_candidates)| { + backed_candidates + .iter() + .enumerate() + .map(|(i, c)| (c.0.hash(), GroupIndex((idx + i) as _))) + .collect() + }) + .collect::>>() + .concat(); move |candidate_hash_x: CandidateHash| -> Option { backed_candidates_with_groups.iter().find_map(|(candidate_hash, grp)| { @@ -1820,14 +2187,13 @@ fn backing_works_with_elastic_scaling_mvp() { candidate_receipt_with_backing_validator_indices, } = ParaInclusion::process_candidates( &allowed_relay_parents, - backed_candidates.clone(), + &backed_candidates, &group_validators, true, ) .expect("candidates scheduled, in order, and backed"); - // Both b candidates will be backed. However, only one will be recorded on-chain and proceed - // with being made available. + // Both b candidates will be backed. assert_eq!( occupied_cores, vec![ @@ -1842,26 +2208,29 @@ fn backing_works_with_elastic_scaling_mvp() { CandidateHash, (CandidateReceipt, Vec<(ValidatorIndex, ValidityAttestation)>), >::new(); - backed_candidates.into_iter().for_each(|(backed_candidate, _)| { - let candidate_receipt_with_backers = expected - .entry(backed_candidate.hash()) - .or_insert_with(|| (backed_candidate.receipt(), Vec::new())); - let (validator_indices, _maybe_core_index) = - backed_candidate.validator_indices_and_core_index(true); - assert_eq!(backed_candidate.validity_votes().len(), validator_indices.count_ones()); - candidate_receipt_with_backers.1.extend( - validator_indices - .iter() - .enumerate() - .filter(|(_, signed)| **signed) - .zip(backed_candidate.validity_votes().iter().cloned()) - .filter_map(|((validator_index_within_group, _), attestation)| { - let grp_idx = get_backing_group_idx(backed_candidate.hash()).unwrap(); - group_validators(grp_idx).map(|validator_indices| { - (validator_indices[validator_index_within_group], attestation) - }) - }), - ); + backed_candidates.values().for_each(|backed_candidates| { + for backed_candidate in backed_candidates { + let backed_candidate = backed_candidate.0.clone(); + let candidate_receipt_with_backers = expected + .entry(backed_candidate.hash()) + .or_insert_with(|| (backed_candidate.receipt(), Vec::new())); + let (validator_indices, _maybe_core_index) = + backed_candidate.validator_indices_and_core_index(true); + assert_eq!(backed_candidate.validity_votes().len(), validator_indices.count_ones()); + candidate_receipt_with_backers.1.extend( + validator_indices + .iter() + .enumerate() + .filter(|(_, signed)| **signed) + .zip(backed_candidate.validity_votes().iter().cloned()) + .filter_map(|((validator_index_within_group, _), attestation)| { + let grp_idx = get_backing_group_idx(backed_candidate.hash()).unwrap(); + group_validators(grp_idx).map(|validator_indices| { + (validator_indices[validator_index_within_group], attestation) + }) + }), + ); + } }); assert_eq!( @@ -1881,39 +2250,54 @@ fn backing_works_with_elastic_scaling_mvp() { }; assert_eq!( >::get(&chain_a), - Some(CandidatePendingAvailability { - core: CoreIndex::from(0), - hash: candidate_a.hash(), - descriptor: candidate_a.descriptor, - availability_votes: default_availability_votes(), - relay_parent_number: System::block_number() - 1, - backed_in_number: System::block_number(), - backers, - backing_group: GroupIndex::from(0), - }) - ); - assert_eq!( - >::get(&chain_a), - Some(candidate_a.commitments), + Some( + [CandidatePendingAvailability { + core: CoreIndex::from(0), + hash: candidate_a.hash(), + descriptor: candidate_a.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers, + backing_group: GroupIndex::from(0), + commitments: candidate_a.commitments + }] + .into_iter() + .collect::>() + ) ); - // Only one candidate for b will be recorded on chain. + // Both candidates of b will be recorded on chain. assert_eq!( >::get(&chain_b), - Some(CandidatePendingAvailability { - core: CoreIndex::from(2), - hash: candidate_b_2.hash(), - descriptor: candidate_b_2.descriptor, - availability_votes: default_availability_votes(), - relay_parent_number: System::block_number() - 1, - backed_in_number: System::block_number(), - backers: backing_bitfield(&[4]), - backing_group: GroupIndex::from(2), - }) - ); - assert_eq!( - >::get(&chain_b), - Some(candidate_b_2.commitments), + Some( + [ + CandidatePendingAvailability { + core: CoreIndex::from(1), + hash: candidate_b_1.hash(), + descriptor: candidate_b_1.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers: backing_bitfield(&[2, 3]), + backing_group: GroupIndex::from(1), + commitments: candidate_b_1.commitments + }, + CandidatePendingAvailability { + core: CoreIndex::from(2), + hash: candidate_b_2.hash(), + descriptor: candidate_b_2.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers: backing_bitfield(&[4]), + backing_group: GroupIndex::from(2), + commitments: candidate_b_2.commitments + } + ] + .into_iter() + .collect::>() + ) ); }); } @@ -1998,8 +2382,10 @@ fn can_include_candidate_with_ok_code_upgrade() { let ProcessedCandidates { core_indices: occupied_cores, .. } = ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed_a, chain_a_assignment.1)], - &group_validators, + &vec![(chain_a_assignment.0, vec![(backed_a, chain_a_assignment.1)])] + .into_iter() + .collect::>(), + group_validators, false, ) .expect("candidates scheduled, in order, and backed"); @@ -2015,20 +2401,21 @@ fn can_include_candidate_with_ok_code_upgrade() { }; assert_eq!( >::get(&chain_a), - Some(CandidatePendingAvailability { - core: CoreIndex::from(0), - hash: candidate_a.hash(), - descriptor: candidate_a.descriptor, - availability_votes: default_availability_votes(), - relay_parent_number: System::block_number() - 1, - backed_in_number: System::block_number(), - backers, - backing_group: GroupIndex::from(0), - }) - ); - assert_eq!( - >::get(&chain_a), - Some(candidate_a.commitments), + Some( + [CandidatePendingAvailability { + core: CoreIndex::from(0), + hash: candidate_a.hash(), + descriptor: candidate_a.descriptor, + availability_votes: default_availability_votes(), + relay_parent_number: System::block_number() - 1, + backed_in_number: System::block_number(), + backers, + backing_group: GroupIndex::from(0), + commitments: candidate_a.commitments + }] + .into_iter() + .collect::>() + ) ); }); } @@ -2209,14 +2596,16 @@ fn check_allowed_relay_parents() { ); let backed_candidates = vec![ - (backed_a, chain_a_assignment.1), - (backed_b, chain_b_assignment.1), - (backed_c, thread_a_assignment.1), - ]; + (chain_a_assignment.0, vec![(backed_a, chain_a_assignment.1)]), + (chain_b_assignment.0, vec![(backed_b, chain_b_assignment.1)]), + (thread_a_assignment.0, vec![(backed_c, thread_a_assignment.1)]), + ] + .into_iter() + .collect::>(); ParaInclusion::process_candidates( &allowed_relay_parents, - backed_candidates.clone(), + &backed_candidates, &group_validators, false, ) @@ -2264,25 +2653,10 @@ fn session_change_wipes() { run_to_block(10, |_| None); - >::insert( - &ValidatorIndex(0), - AvailabilityBitfieldRecord { bitfield: default_bitfield(), submitted_at: 9 }, - ); - - >::insert( - &ValidatorIndex(1), - AvailabilityBitfieldRecord { bitfield: default_bitfield(), submitted_at: 9 }, - ); - - >::insert( - &ValidatorIndex(4), - AvailabilityBitfieldRecord { bitfield: default_bitfield(), submitted_at: 9 }, - ); - let candidate = TestCandidateBuilder::default().build(); >::insert( &chain_a, - CandidatePendingAvailability { + [CandidatePendingAvailability { core: CoreIndex::from(0), hash: candidate.hash(), descriptor: candidate.descriptor.clone(), @@ -2291,13 +2665,15 @@ fn session_change_wipes() { backed_in_number: 6, backers: default_backing_bitfield(), backing_group: GroupIndex::from(0), - }, + commitments: candidate.commitments.clone(), + }] + .into_iter() + .collect::>(), ); - >::insert(&chain_a, candidate.commitments.clone()); >::insert( &chain_b, - CandidatePendingAvailability { + [CandidatePendingAvailability { core: CoreIndex::from(1), hash: candidate.hash(), descriptor: candidate.descriptor, @@ -2306,22 +2682,18 @@ fn session_change_wipes() { backed_in_number: 7, backers: default_backing_bitfield(), backing_group: GroupIndex::from(1), - }, + commitments: candidate.commitments, + }] + .into_iter() + .collect::>(), ); - >::insert(&chain_b, candidate.commitments); run_to_block(11, |_| None); assert_eq!(shared::Pallet::::session_index(), 5); - assert!(>::get(&ValidatorIndex(0)).is_some()); - assert!(>::get(&ValidatorIndex(1)).is_some()); - assert!(>::get(&ValidatorIndex(4)).is_some()); - assert!(>::get(&chain_a).is_some()); assert!(>::get(&chain_b).is_some()); - assert!(>::get(&chain_a).is_some()); - assert!(>::get(&chain_b).is_some()); run_to_block(12, |n| match n { 12 => Some(SessionChangeNotification { @@ -2337,18 +2709,7 @@ fn session_change_wipes() { assert_eq!(shared::Pallet::::session_index(), 6); - assert!(>::get(&ValidatorIndex(0)).is_none()); - assert!(>::get(&ValidatorIndex(1)).is_none()); - assert!(>::get(&ValidatorIndex(4)).is_none()); - - assert!(>::get(&chain_a).is_none()); - assert!(>::get(&chain_b).is_none()); - assert!(>::get(&chain_a).is_none()); - assert!(>::get(&chain_b).is_none()); - - assert!(>::iter().collect::>().is_empty()); assert!(>::iter().collect::>().is_empty()); - assert!(>::iter().collect::>().is_empty()); }); } @@ -2420,11 +2781,6 @@ fn para_upgrade_delay_scheduled_from_inclusion() { ]]; Scheduler::set_validator_groups(validator_groups); - let core_lookup = |core| match core { - core if core == CoreIndex::from(0) => Some(chain_a), - _ => None, - }; - let allowed_relay_parents = default_allowed_relay_parent_tracker(); let chain_a_assignment = (chain_a, CoreIndex::from(0)); @@ -2453,7 +2809,9 @@ fn para_upgrade_delay_scheduled_from_inclusion() { let ProcessedCandidates { core_indices: occupied_cores, .. } = ParaInclusion::process_candidates( &allowed_relay_parents, - vec![(backed_a, chain_a_assignment.1)], + &vec![(chain_a_assignment.0, vec![(backed_a, chain_a_assignment.1)])] + .into_iter() + .collect::>(), &group_validators, false, ) @@ -2488,11 +2846,10 @@ fn para_upgrade_delay_scheduled_from_inclusion() { expected_bits(), ); - let v = process_bitfields(expected_bits(), checked_bitfields, core_lookup); + let v = process_bitfields(checked_bitfields); assert_eq!(vec![(CoreIndex(0), candidate_a.hash())], v); - assert!(>::get(&chain_a).is_none()); - assert!(>::get(&chain_a).is_none()); + assert!(>::get(&chain_a).unwrap().is_empty()); let active_vote_state = paras::Pallet::::active_vote_state(&new_validation_code_hash) .expect("prechecking must be initiated"); diff --git a/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs b/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs index f3365945758..1b07acffb15 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/benchmarking.rs @@ -145,10 +145,6 @@ benchmarks! { assert_eq!(backing_validators.1.len(), votes); } - assert_eq!( - inclusion::PendingAvailabilityCommitments::::iter().count(), - cores_with_backed.len() - ); assert_eq!( inclusion::PendingAvailability::::iter().count(), cores_with_backed.len() @@ -209,10 +205,6 @@ benchmarks! { ); } - assert_eq!( - inclusion::PendingAvailabilityCommitments::::iter().count(), - cores_with_backed.len() - ); assert_eq!( inclusion::PendingAvailability::::iter().count(), cores_with_backed.len() diff --git a/polkadot/runtime/parachains/src/paras_inherent/mod.rs b/polkadot/runtime/parachains/src/paras_inherent/mod.rs index 723a15bdba7..02ddfd0acca 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/mod.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/mod.rs @@ -24,8 +24,7 @@ use crate::{ configuration, disputes::DisputesHandler, - inclusion, - inclusion::CandidateCheckContext, + inclusion::{self, CandidateCheckContext}, initializer, metrics::METRICS, paras, @@ -35,6 +34,7 @@ use crate::{ }; use bitvec::prelude::BitVec; use frame_support::{ + defensive, dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo}, inherent::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent}, pallet_prelude::*, @@ -45,7 +45,7 @@ use pallet_babe::{self, ParentBlockRandomness}; use primitives::{ effective_minimum_backing_votes, vstaging::node_features::FeatureIndex, BackedCandidate, CandidateHash, CandidateReceipt, CheckedDisputeStatementSet, CheckedMultiDisputeStatementSet, - CoreIndex, DisputeStatementSet, InherentData as ParachainsInherentData, + CoreIndex, DisputeStatementSet, HeadData, InherentData as ParachainsInherentData, MultiDisputeStatementSet, ScrapedOnChainVotes, SessionIndex, SignedAvailabilityBitfields, SigningContext, UncheckedSignedAvailabilityBitfield, UncheckedSignedAvailabilityBitfields, ValidatorId, ValidatorIndex, ValidityAttestation, PARACHAINS_INHERENT_IDENTIFIER, @@ -134,18 +134,11 @@ pub mod pallet { /// The hash of the submitted parent header doesn't correspond to the saved block hash of /// the parent. InvalidParentHeader, - /// Disputed candidate that was concluded invalid. - CandidateConcludedInvalid, /// The data given to the inherent will result in an overweight block. InherentOverweight, - /// The ordering of dispute statements was invalid. - DisputeStatementsUnsortedOrDuplicates, - /// A dispute statement was invalid. - DisputeInvalid, - /// A candidate was backed by a disabled validator - BackedByDisabled, - /// A candidate was backed even though the paraid was not scheduled. - BackedOnUnscheduledCore, + /// A candidate was filtered during inherent execution. This should have only been done + /// during creation. + CandidatesFilteredDuringExecution, /// Too many candidates supplied. UnscheduledCandidate, } @@ -235,35 +228,6 @@ pub mod pallet { } } - /// Collect all freed cores based on storage data. (i.e. append cores freed from timeouts to - /// the given `freed_concluded`). - /// - /// The parameter `freed_concluded` contains all core indicies that became - /// free due to candidate that became available. - pub(crate) fn collect_all_freed_cores( - freed_concluded: I, - ) -> BTreeMap - where - I: core::iter::IntoIterator, - T: Config, - { - // Handle timeouts for any availability core work. - let freed_timeout = if >::availability_timeout_check_required() { - let pred = >::availability_timeout_predicate(); - >::collect_pending(pred) - } else { - Vec::new() - }; - - // Schedule paras again, given freed cores, and reasons for freeing. - let freed = freed_concluded - .into_iter() - .map(|(c, _hash)| (c, FreedReason::Concluded)) - .chain(freed_timeout.into_iter().map(|c| (c, FreedReason::TimedOut))) - .collect::>(); - freed - } - #[pallet::call] impl Pallet { /// Enter the paras inherent. This will process bitfields and backed candidates. @@ -319,7 +283,7 @@ impl Pallet { /// Process inherent data. /// /// The given inherent data is processed and state is altered accordingly. If any data could - /// not be applied (inconsitencies, weight limit, ...) it is removed. + /// not be applied (inconsistencies, weight limit, ...) it is removed. /// /// When called from `create_inherent` the `context` must be set to /// `ProcessInherentDataContext::ProvideInherent` so it guarantees the invariant that inherent @@ -526,7 +490,7 @@ impl Pallet { // Contains the disputes that are concluded in the current session only, // since these are the only ones that are relevant for the occupied cores - // and lightens the load on `collect_disputed` significantly. + // and lightens the load on `free_disputed` significantly. // Cores can't be occupied with candidates of the previous sessions, and only // things with new votes can have just concluded. We only need to collect // cores with disputes that conclude just now, because disputes that @@ -542,21 +506,17 @@ impl Pallet { .map(|(_session, candidate)| candidate) .collect::>(); - let freed_disputed: BTreeMap = - >::collect_disputed(¤t_concluded_invalid_disputes) + // Get the cores freed as a result of concluded invalid candidates. + let (freed_disputed, concluded_invalid_hashes): (Vec, BTreeSet) = + >::free_disputed(¤t_concluded_invalid_disputes) .into_iter() - .map(|core| (core, FreedReason::Concluded)) - .collect(); + .unzip(); // Create a bit index from the set of core indices where each index corresponds to // a core index that was freed due to a dispute. // // I.e. 010100 would indicate, the candidates on Core 1 and 3 would be disputed. - let disputed_bitfield = create_disputed_bitfield(expected_bits, freed_disputed.keys()); - - if !freed_disputed.is_empty() { - >::free_cores_and_fill_claimqueue(freed_disputed.clone(), now); - } + let disputed_bitfield = create_disputed_bitfield(expected_bits, freed_disputed.iter()); let bitfields = sanitize_bitfields::( bitfields, @@ -571,11 +531,9 @@ impl Pallet { // Process new availability bitfields, yielding any availability cores whose // work has now concluded. let freed_concluded = - >::update_pending_availability_and_get_freed_cores::<_>( - expected_bits, + >::update_pending_availability_and_get_freed_cores( &validator_public[..], bitfields.clone(), - >::core_para, ); // Inform the disputes module of all included candidates. @@ -585,8 +543,24 @@ impl Pallet { METRICS.on_candidates_included(freed_concluded.len() as u64); - let freed = collect_all_freed_cores::(freed_concluded.iter().cloned()); + // Get the timed out candidates + let freed_timeout = if >::availability_timeout_check_required() { + >::free_timedout() + } else { + Vec::new() + }; + + if !freed_timeout.is_empty() { + log::debug!(target: LOG_TARGET, "Evicted timed out cores: {:?}", freed_timeout); + } + // We'll schedule paras again, given freed cores, and reasons for freeing. + let freed = freed_concluded + .into_iter() + .map(|(c, _hash)| (c, FreedReason::Concluded)) + .chain(freed_disputed.into_iter().map(|core| (core, FreedReason::Concluded))) + .chain(freed_timeout.into_iter().map(|c| (c, FreedReason::TimedOut))) + .collect::>(); >::free_cores_and_fill_claimqueue(freed, now); METRICS.on_candidates_processed_total(backed_candidates.len() as u64); @@ -605,55 +579,28 @@ impl Pallet { scheduled.entry(para_id).or_default().insert(core_idx); } - let SanitizedBackedCandidates { - backed_candidates_with_core, - votes_from_disabled_were_dropped, - dropped_unscheduled_candidates, - } = sanitize_backed_candidates::( + let initial_candidate_count = backed_candidates.len(); + let backed_candidates_with_core = sanitize_backed_candidates::( backed_candidates, &allowed_relay_parents, - |candidate_idx: usize, - backed_candidate: &BackedCandidate<::Hash>| - -> bool { - let para_id = backed_candidate.descriptor().para_id; - let prev_context = >::para_most_recent_context(para_id); - let check_ctx = CandidateCheckContext::::new(prev_context); - - // never include a concluded-invalid candidate - current_concluded_invalid_disputes.contains(&backed_candidate.hash()) || - // Instead of checking the candidates with code upgrades twice - // move the checking up here and skip it in the training wheels fallback. - // That way we avoid possible duplicate checks while assuring all - // backed candidates fine to pass on. - // - // NOTE: this is the only place where we check the relay-parent. - check_ctx - .verify_backed_candidate(&allowed_relay_parents, candidate_idx, backed_candidate.candidate()) - .is_err() - }, + concluded_invalid_hashes, scheduled, core_index_enabled, ); + let count = count_backed_candidates(&backed_candidates_with_core); - ensure!( - backed_candidates_with_core.len() <= total_scheduled_cores, - Error::::UnscheduledCandidate - ); - - METRICS.on_candidates_sanitized(backed_candidates_with_core.len() as u64); + ensure!(count <= total_scheduled_cores, Error::::UnscheduledCandidate); - // In `Enter` context (invoked during execution) there should be no backing votes from - // disabled validators because they should have been filtered out during inherent data - // preparation (`ProvideInherent` context). Abort in such cases. - if context == ProcessInherentDataContext::Enter { - ensure!(!votes_from_disabled_were_dropped, Error::::BackedByDisabled); - } + METRICS.on_candidates_sanitized(count as u64); - // In `Enter` context (invoked during execution) we shouldn't have filtered any candidates - // due to a para not being scheduled. They have been filtered during inherent data - // preparation (`ProvideInherent` context). Abort in such cases. + // In `Enter` context (invoked during execution) no more candidates should be filtered, + // because they have already been filtered during `ProvideInherent` context. Abort in such + // cases. if context == ProcessInherentDataContext::Enter { - ensure!(!dropped_unscheduled_candidates, Error::::BackedOnUnscheduledCore); + ensure!( + initial_candidate_count == count, + Error::::CandidatesFilteredDuringExecution + ); } // Process backed candidates according to scheduled cores. @@ -662,7 +609,7 @@ impl Pallet { candidate_receipt_with_backing_validator_indices, } = >::process_candidates( &allowed_relay_parents, - backed_candidates_with_core.clone(), + &backed_candidates_with_core, >::group_validators, core_index_enabled, )?; @@ -683,10 +630,13 @@ impl Pallet { let processed = ParachainsInherentData { bitfields, - backed_candidates: backed_candidates_with_core - .into_iter() - .map(|(candidate, _)| candidate) - .collect(), + backed_candidates: backed_candidates_with_core.into_iter().fold( + Vec::with_capacity(count), + |mut acc, (_id, candidates)| { + acc.extend(candidates.into_iter().map(|(c, _)| c)); + acc + }, + ), disputes, parent_header, }; @@ -986,83 +936,86 @@ pub(crate) fn sanitize_bitfields( bitfields } -// Result from `sanitize_backed_candidates` -#[derive(Debug, PartialEq)] -struct SanitizedBackedCandidates { - // Sanitized backed candidates along with the assigned core. The `Vec` is sorted according to - // the occupied core index. - backed_candidates_with_core: Vec<(BackedCandidate, CoreIndex)>, - // Set to true if any votes from disabled validators were dropped from the input. - votes_from_disabled_were_dropped: bool, - // Set to true if any candidates were dropped due to filtering done in - // `map_candidates_to_cores` - dropped_unscheduled_candidates: bool, -} - +/// Performs various filtering on the backed candidates inherent data. +/// Must maintain the invariant that the returned candidate collection contains the candidates +/// sorted in dependency order for each para. When doing any filtering, we must therefore drop any +/// subsequent candidates after the filtered one. +/// /// Filter out: -/// 1. any candidates that have a concluded invalid dispute -/// 2. any unscheduled candidates, as well as candidates whose paraid has multiple cores assigned +/// 1. any candidates which don't form a chain with the other candidates of the paraid (even if they +/// do form a chain but are not in the right order). +/// 2. any candidates that have a concluded invalid dispute or who are descendants of a concluded +/// invalid candidate. +/// 3. any unscheduled candidates, as well as candidates whose paraid has multiple cores assigned /// but have no injected core index. -/// 3. all backing votes from disabled validators -/// 4. any candidates that end up with less than `effective_minimum_backing_votes` backing votes +/// 4. all backing votes from disabled validators +/// 5. any candidates that end up with less than `effective_minimum_backing_votes` backing votes /// -/// `scheduled` follows the same naming scheme as provided in the -/// guide: Currently `free` but might become `occupied`. -/// For the filtering here the relevant part is only the current `free` -/// state. -/// -/// `candidate_has_concluded_invalid_dispute` must return `true` if the candidate -/// is disputed, false otherwise. The passed `usize` is the candidate index. -/// -/// Returns struct `SanitizedBackedCandidates` where `backed_candidates` are sorted according to the -/// occupied core index. -fn sanitize_backed_candidates< - T: crate::inclusion::Config, - F: FnMut(usize, &BackedCandidate) -> bool, ->( - mut backed_candidates: Vec>, +/// Returns the scheduled +/// backed candidates which passed filtering, mapped by para id and in the right dependency order. +fn sanitize_backed_candidates( + backed_candidates: Vec>, allowed_relay_parents: &AllowedRelayParentsTracker>, - mut candidate_has_concluded_invalid_dispute_or_is_invalid: F, + concluded_invalid_with_descendants: BTreeSet, scheduled: BTreeMap>, core_index_enabled: bool, -) -> SanitizedBackedCandidates { - // Remove any candidates that were concluded invalid. - // This does not assume sorting. - backed_candidates.indexed_retain(move |candidate_idx, backed_candidate| { - !candidate_has_concluded_invalid_dispute_or_is_invalid(candidate_idx, backed_candidate) +) -> BTreeMap, CoreIndex)>> { + // Map the candidates to the right paraids, while making sure that the order between candidates + // of the same para is preserved. + let mut candidates_per_para: BTreeMap> = BTreeMap::new(); + for candidate in backed_candidates { + candidates_per_para + .entry(candidate.descriptor().para_id) + .or_default() + .push(candidate); + } + + // Check that candidates pertaining to the same para form a chain. Drop the ones that + // don't, along with the rest of candidates which follow them in the input vector. + filter_unchained_candidates::(&mut candidates_per_para, allowed_relay_parents); + + // Remove any candidates that were concluded invalid or who are descendants of concluded invalid + // candidates (along with their descendants). + retain_candidates::(&mut candidates_per_para, |_, candidate| { + let keep = !concluded_invalid_with_descendants.contains(&candidate.candidate().hash()); + + if !keep { + log::debug!( + target: LOG_TARGET, + "Found backed candidate {:?} which was concluded invalid or is a descendant of a concluded invalid candidate, for paraid {:?}.", + candidate.candidate().hash(), + candidate.descriptor().para_id + ); + } + keep }); - let initial_candidate_count = backed_candidates.len(); - // Map candidates to scheduled cores. Filter out any unscheduled candidates. + // Map candidates to scheduled cores. Filter out any unscheduled candidates along with their + // descendants. let mut backed_candidates_with_core = map_candidates_to_cores::( &allowed_relay_parents, scheduled, core_index_enabled, - backed_candidates, + candidates_per_para, ); - let dropped_unscheduled_candidates = - initial_candidate_count != backed_candidates_with_core.len(); - - // Filter out backing statements from disabled validators - let votes_from_disabled_were_dropped = filter_backed_statements_from_disabled_validators::( + // Filter out backing statements from disabled validators. If by that we render a candidate with + // less backing votes than required, filter that candidate also. As all the other filtering + // operations above, we drop the descendants of the dropped candidates also. + filter_backed_statements_from_disabled_validators::( &mut backed_candidates_with_core, &allowed_relay_parents, core_index_enabled, ); - // Sort the `Vec` last, once there is a guarantee that these - // `BackedCandidates` references the expected relay chain parent, - // but more importantly are scheduled for a free core. - // This both avoids extra work for obviously invalid candidates, - // but also allows this to be done in place. - backed_candidates_with_core.sort_by(|(_x, core_x), (_y, core_y)| core_x.cmp(&core_y)); - - SanitizedBackedCandidates { - dropped_unscheduled_candidates, - votes_from_disabled_were_dropped, - backed_candidates_with_core, - } + backed_candidates_with_core +} + +fn count_backed_candidates(backed_candidates: &BTreeMap>) -> usize { + backed_candidates.iter().fold(0, |mut count, (_id, candidates)| { + count += candidates.len(); + count + }) } /// Derive entropy from babe provided per block randomness. @@ -1146,48 +1099,82 @@ fn limit_and_sanitize_disputes< } } -// Filters statements from disabled validators in `BackedCandidate`, non-scheduled candidates and -// few more sanity checks. Returns `true` if at least one statement is removed and `false` -// otherwise. -fn filter_backed_statements_from_disabled_validators( - backed_candidates_with_core: &mut Vec<( - BackedCandidate<::Hash>, - CoreIndex, - )>, +// Helper function for filtering candidates which don't pass the given predicate. When/if the first +// candidate which failes the predicate is found, all the other candidates that follow are dropped. +fn retain_candidates< + T: inclusion::Config + paras::Config + inclusion::Config, + F: FnMut(ParaId, &mut C) -> bool, + C, +>( + candidates_per_para: &mut BTreeMap>, + mut pred: F, +) { + for (para_id, candidates) in candidates_per_para.iter_mut() { + let mut latest_valid_idx = None; + + for (idx, candidate) in candidates.iter_mut().enumerate() { + if pred(*para_id, candidate) { + // Found a valid candidate. + latest_valid_idx = Some(idx); + } else { + break + } + } + + if let Some(latest_valid_idx) = latest_valid_idx { + candidates.truncate(latest_valid_idx + 1); + } else { + candidates.clear(); + } + } + + candidates_per_para.retain(|_, c| !c.is_empty()); +} + +// Filters statements from disabled validators in `BackedCandidate` and does a few more sanity +// checks. +fn filter_backed_statements_from_disabled_validators< + T: shared::Config + scheduler::Config + inclusion::Config, +>( + backed_candidates_with_core: &mut BTreeMap< + ParaId, + Vec<(BackedCandidate<::Hash>, CoreIndex)>, + >, allowed_relay_parents: &AllowedRelayParentsTracker>, core_index_enabled: bool, -) -> bool { +) { let disabled_validators = BTreeSet::<_>::from_iter(shared::Pallet::::disabled_validators().into_iter()); if disabled_validators.is_empty() { // No disabled validators - nothing to do - return false + return } - let backed_len_before = backed_candidates_with_core.len(); - - // Flag which will be returned. Set to `true` if at least one vote is filtered. - let mut filtered = false; - let minimum_backing_votes = configuration::Pallet::::config().minimum_backing_votes; // Process all backed candidates. `validator_indices` in `BackedCandidates` are indices within // the validator group assigned to the parachain. To obtain this group we need: // 1. Core index assigned to the parachain which has produced the candidate // 2. The relay chain block number of the candidate - backed_candidates_with_core.retain_mut(|(bc, core_idx)| { - let (validator_indices, maybe_core_index) = bc.validator_indices_and_core_index(core_index_enabled); + retain_candidates::(backed_candidates_with_core, |para_id, (bc, core_idx)| { + let (validator_indices, maybe_core_index) = + bc.validator_indices_and_core_index(core_index_enabled); let mut validator_indices = BitVec::<_>::from(validator_indices); - // Get relay parent block number of the candidate. We need this to get the group index assigned to this core at this block number - let relay_parent_block_number = match allowed_relay_parents - .acquire_info(bc.descriptor().relay_parent, None) { + // Get relay parent block number of the candidate. We need this to get the group index + // assigned to this core at this block number + let relay_parent_block_number = + match allowed_relay_parents.acquire_info(bc.descriptor().relay_parent, None) { Some((_, block_num)) => block_num, None => { - log::debug!(target: LOG_TARGET, "Relay parent {:?} for candidate is not in the allowed relay parents. Dropping the candidate.", bc.descriptor().relay_parent); + log::debug!( + target: LOG_TARGET, + "Relay parent {:?} for candidate is not in the allowed relay parents. Dropping the candidate.", + bc.descriptor().relay_parent + ); return false - } + }, }; // Get the group index for the core @@ -1208,12 +1195,15 @@ fn filter_backed_statements_from_disabled_validators { log::debug!(target: LOG_TARGET, "Can't get the validators from group {:?}. Dropping the candidate.", group_idx); return false - } + }, }; // Bitmask with the disabled indices within the validator group - let disabled_indices = BitVec::::from_iter(validator_group.iter().map(|idx| disabled_validators.contains(idx))); - // The indices of statements from disabled validators in `BackedCandidate`. We have to drop these. + let disabled_indices = BitVec::::from_iter( + validator_group.iter().map(|idx| disabled_validators.contains(idx)), + ); + // The indices of statements from disabled validators in `BackedCandidate`. We have to drop + // these. let indices_to_drop = disabled_indices.clone() & &validator_indices; // Apply the bitmask to drop the disabled validator from `validator_indices` validator_indices &= !disabled_indices; @@ -1225,62 +1215,218 @@ fn filter_backed_statements_from_disabled_validators 0 { - filtered = true; - } - // By filtering votes we might render the candidate invalid and cause a failure in // [`process_candidates`]. To avoid this we have to perform a sanity check here. If there // are not enough backing votes after filtering we will remove the whole candidate. - if bc.validity_votes().len() < effective_minimum_backing_votes( - validator_group.len(), - minimum_backing_votes - ) { + if bc.validity_votes().len() < + effective_minimum_backing_votes(validator_group.len(), minimum_backing_votes) + { + log::debug!( + target: LOG_TARGET, + "Dropping candidate {:?} of paraid {:?} because it was left with too few backing votes after votes from disabled validators were filtered.", + bc.candidate().hash(), + para_id + ); + return false } true }); +} + +// Check that candidates pertaining to the same para form a chain. Drop the ones that +// don't, along with the rest of candidates which follow them in the input vector. +// In the process, duplicated candidates will also be dropped (even if they form a valid cycle; +// cycles are not allowed if they entail backing duplicated candidates). +fn filter_unchained_candidates( + candidates: &mut BTreeMap>>, + allowed_relay_parents: &AllowedRelayParentsTracker>, +) { + let mut para_latest_head_data: BTreeMap = BTreeMap::new(); + for para_id in candidates.keys() { + let latest_head_data = match >::para_latest_head_data(¶_id) { + None => { + defensive!("Latest included head data for paraid {:?} is None", para_id); + continue + }, + Some(latest_head_data) => latest_head_data, + }; + para_latest_head_data.insert(*para_id, latest_head_data); + } + + let mut para_visited_candidates: BTreeMap> = BTreeMap::new(); + + retain_candidates::(candidates, |para_id, candidate| { + let Some(latest_head_data) = para_latest_head_data.get(¶_id) else { return false }; + let candidate_hash = candidate.candidate().hash(); + + let visited_candidates = + para_visited_candidates.entry(para_id).or_insert_with(|| BTreeSet::new()); + if visited_candidates.contains(&candidate_hash) { + log::debug!( + target: LOG_TARGET, + "Found duplicate candidates for paraid {:?}. Dropping the candidates with hash {:?}", + para_id, + candidate_hash + ); + + // If we got a duplicate candidate, stop. + return false + } else { + visited_candidates.insert(candidate_hash); + } + + let prev_context = >::para_most_recent_context(para_id); + let check_ctx = CandidateCheckContext::::new(prev_context); + + let res = match check_ctx.verify_backed_candidate( + &allowed_relay_parents, + candidate.candidate(), + latest_head_data.clone(), + ) { + Ok(_) => true, + Err(err) => { + log::debug!( + target: LOG_TARGET, + "Backed candidate verification for candidate {:?} of paraid {:?} failed with {:?}", + candidate_hash, + para_id, + err + ); + false + }, + }; + + if res { + para_latest_head_data + .insert(para_id, candidate.candidate().commitments.head_data.clone()); + } - // Also return `true` if a whole candidate was dropped from the set - filtered || backed_len_before != backed_candidates_with_core.len() + res + }); } /// Map candidates to scheduled cores. -/// If the para only has one scheduled core and no `CoreIndex` is injected, map the candidate to the +/// If the para only has one scheduled core and one candidate supplied, map the candidate to the /// single core. If the para has multiple cores scheduled, only map the candidates which have a /// proper core injected. Filter out the rest. /// Also returns whether or not we dropped any candidates. +/// When dropping a candidate of a para, we must drop all subsequent candidates from that para +/// (because they form a chain). fn map_candidates_to_cores( allowed_relay_parents: &AllowedRelayParentsTracker>, mut scheduled: BTreeMap>, core_index_enabled: bool, - candidates: Vec>, -) -> Vec<(BackedCandidate, CoreIndex)> { - let mut backed_candidates_with_core = Vec::with_capacity(candidates.len()); - - // We keep a candidate if the parachain has only one core assigned or if - // a core index is provided by block author and it's indeed scheduled. - for backed_candidate in candidates { - let maybe_injected_core_index = get_injected_core_index::( - allowed_relay_parents, - &backed_candidate, - core_index_enabled, - ); + candidates: BTreeMap>>, +) -> BTreeMap, CoreIndex)>> { + let mut backed_candidates_with_core = BTreeMap::new(); + + for (para_id, backed_candidates) in candidates.into_iter() { + if backed_candidates.len() == 0 { + defensive!("Backed candidates for paraid {} is empty.", para_id); + continue + } - let scheduled_cores = scheduled.get_mut(&backed_candidate.descriptor().para_id); - // Candidates without scheduled cores are silently filtered out. + let scheduled_cores = scheduled.get_mut(¶_id); + + // ParaIds without scheduled cores are silently filtered out. if let Some(scheduled_cores) = scheduled_cores { - if let Some(core_idx) = maybe_injected_core_index { - if scheduled_cores.contains(&core_idx) { - scheduled_cores.remove(&core_idx); - backed_candidates_with_core.push((backed_candidate, core_idx)); + if scheduled_cores.len() == 0 { + log::debug!( + target: LOG_TARGET, + "Paraid: {:?} has no scheduled cores but {} candidates were supplied.", + para_id, + backed_candidates.len() + ); + + // Non-elastic scaling case. One core per para. + } else if scheduled_cores.len() == 1 && !core_index_enabled { + backed_candidates_with_core.insert( + para_id, + vec![( + // We need the first one here, as we assume candidates of a para are in + // dependency order. + backed_candidates.into_iter().next().expect("Length is at least 1"), + scheduled_cores.pop_first().expect("Length is 1"), + )], + ); + continue; + + // Elastic scaling case. We only allow candidates which have the right core + // indices injected. + } else if scheduled_cores.len() >= 1 && core_index_enabled { + // We must preserve the dependency order given in the input. + let mut temp_backed_candidates = Vec::with_capacity(scheduled_cores.len()); + + for candidate in backed_candidates { + if scheduled_cores.len() == 0 { + // We've got candidates for all of this para's assigned cores. Move on to + // the next para. + log::debug!( + target: LOG_TARGET, + "Found enough candidates for paraid: {:?}.", + candidate.descriptor().para_id + ); + break; + } + let maybe_injected_core_index: Option = + get_injected_core_index::(allowed_relay_parents, &candidate); + + if let Some(core_index) = maybe_injected_core_index { + if scheduled_cores.remove(&core_index) { + temp_backed_candidates.push((candidate, core_index)); + } else { + // if we got a candidate for a core index which is not scheduled, stop + // the work for this para. the already processed candidate chain in + // temp_backed_candidates is still fine though. + log::debug!( + target: LOG_TARGET, + "Found a backed candidate {:?} with injected core index {}, which is not scheduled for paraid {:?}.", + candidate.candidate().hash(), + core_index.0, + candidate.descriptor().para_id + ); + + break; + } + } else { + // if we got a candidate which does not contain its core index, stop the + // work for this para. the already processed candidate chain in + // temp_backed_candidates is still fine though. + + log::debug!( + target: LOG_TARGET, + "Found a backed candidate {:?} with no injected core index, for paraid {:?} which has multiple scheduled cores.", + candidate.candidate().hash(), + candidate.descriptor().para_id + ); + + break; + } } - } else if scheduled_cores.len() == 1 { - backed_candidates_with_core - .push((backed_candidate, scheduled_cores.pop_first().expect("Length is 1"))); + + if !temp_backed_candidates.is_empty() { + backed_candidates_with_core + .entry(para_id) + .or_insert_with(|| vec![]) + .extend(temp_backed_candidates); + } + } else { + log::warn!( + target: LOG_TARGET, + "Found a paraid {:?} which has multiple scheduled cores but ElasticScalingMVP feature is not enabled: {:?}", + para_id, + scheduled_cores + ); } + } else { + log::debug!( + target: LOG_TARGET, + "Paraid: {:?} has no scheduled cores but {} candidates were supplied.", + para_id, + backed_candidates.len() + ); } } @@ -1290,13 +1436,11 @@ fn map_candidates_to_cores( allowed_relay_parents: &AllowedRelayParentsTracker>, candidate: &BackedCandidate, - core_index_enabled: bool, ) -> Option { // After stripping the 8 bit extensions, the `validator_indices` field length is expected // to be equal to backing group size. If these don't match, the `CoreIndex` is badly encoded, // or not supported. - let (validator_indices, maybe_core_idx) = - candidate.validator_indices_and_core_index(core_index_enabled); + let (validator_indices, maybe_core_idx) = candidate.validator_indices_and_core_index(true); let Some(core_idx) = maybe_core_idx else { return None }; @@ -1306,7 +1450,7 @@ fn get_injected_core_index { log::debug!( target: LOG_TARGET, - "Relay parent {:?} for candidate {:?} is not in the allowed relay parents. Dropping the candidate.", + "Relay parent {:?} for candidate {:?} is not in the allowed relay parents.", candidate.descriptor().relay_parent, candidate.candidate().hash(), ); @@ -1323,9 +1467,8 @@ fn get_injected_core_index { log::debug!( target: LOG_TARGET, - "Can't get the group index for core idx {:?}. Dropping the candidate {:?}.", + "Can't get the group index for core idx {:?}.", core_idx, - candidate.candidate().hash(), ); return None }, @@ -1339,6 +1482,14 @@ fn get_injected_core_index MockGenesisConfig { + MockGenesisConfig { + configuration: configuration::GenesisConfig { + config: HostConfiguration { + max_head_data_size: 0b100000, + scheduler_params: SchedulerParams { + group_rotation_frequency: u32::MAX, + ..Default::default() + }, + ..Default::default() + }, + }, + ..Default::default() + } +} + // In order to facilitate benchmarks as tests we have a benchmark feature gated `WeightInfo` impl // that uses 0 for all the weights. Because all the weights are 0, the tests that rely on // weights for limiting data will fail, so we don't run them when using the benchmark feature. #[cfg(not(feature = "runtime-benchmarks"))] mod enter { - use super::{inclusion::tests::TestCandidateBuilder, *}; use crate::{ builder::{Bench, BenchBuilder}, - mock::{mock_assigner, new_test_ext, BlockLength, BlockWeights, MockGenesisConfig, Test}, + mock::{mock_assigner, new_test_ext, BlockLength, BlockWeights, RuntimeOrigin, Test}, scheduler::{ common::{Assignment, AssignmentProvider}, ParasEntry, }, + session_info, }; use assert_matches::assert_matches; + use core::panic; use frame_support::assert_ok; use frame_system::limits; - use primitives::vstaging::SchedulerParams; + use primitives::{vstaging::SchedulerParams, AvailabilityBitfield, UncheckedSigned}; use sp_runtime::Perbill; use sp_std::collections::btree_map::BTreeMap; @@ -45,6 +68,8 @@ mod enter { num_validators_per_core: u32, code_upgrade: Option, fill_claimqueue: bool, + elastic_paras: BTreeMap, + unavailable_cores: Vec, } fn make_inherent_data( @@ -55,25 +80,39 @@ mod enter { num_validators_per_core, code_upgrade, fill_claimqueue, + elastic_paras, + unavailable_cores, }: TestConfig, ) -> Bench { + let extra_cores = elastic_paras + .values() + .map(|count| *count as usize) + .sum::() + .saturating_sub(elastic_paras.len() as usize); + let total_cores = dispute_sessions.len() + backed_and_concluding.len() + extra_cores; + let builder = BenchBuilder::::new() - .set_max_validators( - (dispute_sessions.len() + backed_and_concluding.len()) as u32 * - num_validators_per_core, - ) + .set_max_validators((total_cores) as u32 * num_validators_per_core) + .set_elastic_paras(elastic_paras.clone()) .set_max_validators_per_core(num_validators_per_core) .set_dispute_statements(dispute_statements) - .set_backed_and_concluding_paras(backed_and_concluding) + .set_backed_and_concluding_paras(backed_and_concluding.clone()) .set_dispute_sessions(&dispute_sessions[..]) - .set_fill_claimqueue(fill_claimqueue); + .set_fill_claimqueue(fill_claimqueue) + .set_unavailable_cores(unavailable_cores); // Setup some assignments as needed: mock_assigner::Pallet::::set_core_count(builder.max_cores()); - for core_index in 0..builder.max_cores() { - // Core index == para_id in this case - mock_assigner::Pallet::::add_test_assignment(Assignment::Bulk(core_index.into())); - } + + (0..(builder.max_cores() as usize - extra_cores)).for_each(|para_id| { + (0..elastic_paras.get(&(para_id as u32)).cloned().unwrap_or(1)).for_each( + |_para_local_core_idx| { + mock_assigner::Pallet::::add_test_assignment(Assignment::Bulk( + para_id.into(), + )); + }, + ); + }); if let Some(code_size) = code_upgrade { builder.set_code_upgrade(code_size).build() @@ -104,6 +143,8 @@ mod enter { num_validators_per_core: 1, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); // We expect the scenario to have cores 0 & 1 with pending availability. The backed @@ -145,6 +186,305 @@ mod enter { Pallet::::on_chain_votes().unwrap().session, 2 ); + + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(0)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![CoreIndex(0)] + ); + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(1)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![CoreIndex(1)] + ); + }); + } + + #[test] + fn include_backed_candidates_elastic_scaling() { + // ParaId 0 has one pending candidate on core 0. + // ParaId 1 has one pending candidate on core 1. + // ParaId 2 has three pending candidates on cores 2, 3 and 4. + // All of them are being made available in this block. Propose 5 more candidates (one for + // each core) and check that they're successfully backed and the old ones enacted. + let config = default_config(); + assert!(config.configuration.config.scheduler_params.lookahead > 0); + new_test_ext(config).execute_with(|| { + // Set the elastic scaling MVP feature. + >::set_node_feature( + RuntimeOrigin::root(), + FeatureIndex::ElasticScalingMVP as u8, + true, + ) + .unwrap(); + + let dispute_statements = BTreeMap::new(); + + let mut backed_and_concluding = BTreeMap::new(); + backed_and_concluding.insert(0, 1); + backed_and_concluding.insert(1, 1); + backed_and_concluding.insert(2, 1); + + let scenario = make_inherent_data(TestConfig { + dispute_statements, + dispute_sessions: vec![], // No disputes + backed_and_concluding, + num_validators_per_core: 1, + code_upgrade: None, + fill_claimqueue: false, + elastic_paras: [(2, 3)].into_iter().collect(), + unavailable_cores: vec![], + }); + + let expected_para_inherent_data = scenario.data.clone(); + + // Check the para inherent data is as expected: + // * 1 bitfield per validator (5 validators) + assert_eq!(expected_para_inherent_data.bitfields.len(), 5); + // * 1 backed candidate per core (5 cores) + assert_eq!(expected_para_inherent_data.backed_candidates.len(), 5); + // * 0 disputes. + assert_eq!(expected_para_inherent_data.disputes.len(), 0); + let mut inherent_data = InherentData::new(); + inherent_data + .put_data(PARACHAINS_INHERENT_IDENTIFIER, &expected_para_inherent_data) + .unwrap(); + + // The current schedule is empty prior to calling `create_inherent_enter`. + assert!(>::claimqueue_is_empty()); + + assert!(Pallet::::on_chain_votes().is_none()); + + // Nothing is filtered out (including the backed candidates.) + assert_eq!( + Pallet::::create_inherent_inner(&inherent_data.clone()).unwrap(), + expected_para_inherent_data + ); + + assert_eq!( + // The length of this vec is equal to the number of candidates, so we know our 5 + // backed candidates did not get filtered out + Pallet::::on_chain_votes().unwrap().backing_validators_per_candidate.len(), + 5 + ); + + assert_eq!( + // The session of the on chain votes should equal the current session, which is 2 + Pallet::::on_chain_votes().unwrap().session, + 2 + ); + + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(0)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![CoreIndex(0)] + ); + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(1)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![CoreIndex(1)] + ); + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(2)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![CoreIndex(2), CoreIndex(3), CoreIndex(4)] + ); + }); + + // ParaId 0 has one pending candidate on core 0. + // ParaId 1 has one pending candidate on core 1. + // ParaId 2 has 4 pending candidates on cores 2, 3, 4 and 5. + // Cores 1, 2 and 3 are being made available in this block. Propose 6 more candidates (one + // for each core) and check that the right ones are successfully backed and the old ones + // enacted. + let config = default_config(); + assert!(config.configuration.config.scheduler_params.lookahead > 0); + new_test_ext(config).execute_with(|| { + // Set the elastic scaling MVP feature. + >::set_node_feature( + RuntimeOrigin::root(), + FeatureIndex::ElasticScalingMVP as u8, + true, + ) + .unwrap(); + + let mut backed_and_concluding = BTreeMap::new(); + backed_and_concluding.insert(0, 1); + backed_and_concluding.insert(1, 1); + backed_and_concluding.insert(2, 1); + + // Modify the availability bitfields so that cores 0, 4 and 5 are not being made + // available. + let unavailable_cores = vec![0, 4, 5]; + + let scenario = make_inherent_data(TestConfig { + dispute_statements: BTreeMap::new(), + dispute_sessions: vec![], // No disputes + backed_and_concluding, + num_validators_per_core: 1, + code_upgrade: None, + fill_claimqueue: true, + elastic_paras: [(2, 4)].into_iter().collect(), + unavailable_cores: unavailable_cores.clone(), + }); + + let mut expected_para_inherent_data = scenario.data.clone(); + + // Check the para inherent data is as expected: + // * 1 bitfield per validator (6 validators) + assert_eq!(expected_para_inherent_data.bitfields.len(), 6); + // * 1 backed candidate per core (6 cores) + assert_eq!(expected_para_inherent_data.backed_candidates.len(), 6); + // * 0 disputes. + assert_eq!(expected_para_inherent_data.disputes.len(), 0); + assert!(Pallet::::on_chain_votes().is_none()); + + expected_para_inherent_data.backed_candidates = expected_para_inherent_data + .backed_candidates + .into_iter() + .filter(|candidate| { + let (_, Some(core_index)) = candidate.validator_indices_and_core_index(true) + else { + panic!("Core index must have been injected"); + }; + !unavailable_cores.contains(&core_index.0) + }) + .collect(); + + let mut inherent_data = InherentData::new(); + inherent_data.put_data(PARACHAINS_INHERENT_IDENTIFIER, &scenario.data).unwrap(); + + assert!(!>::claimqueue_is_empty()); + + // The right candidates have been filtered out (the ones for cores 0,4,5) + assert_eq!( + Pallet::::create_inherent_inner(&inherent_data.clone()).unwrap(), + expected_para_inherent_data + ); + + // 3 candidates have been backed (for cores 1,2 and 3) + assert_eq!( + Pallet::::on_chain_votes().unwrap().backing_validators_per_candidate.len(), + 3 + ); + + assert_eq!( + // The session of the on chain votes should equal the current session, which is 2 + Pallet::::on_chain_votes().unwrap().session, + 2 + ); + + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(1)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![CoreIndex(1)] + ); + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(2)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![CoreIndex(4), CoreIndex(5), CoreIndex(2), CoreIndex(3)] + ); + + let expected_heads = (0..=2) + .map(|id| { + inclusion::PendingAvailability::::get(ParaId::from(id)) + .unwrap() + .back() + .unwrap() + .candidate_commitments() + .head_data + .clone() + }) + .collect::>(); + + // Now just make all candidates available. + let mut data = scenario.data.clone(); + let validators = session_info::Pallet::::session_info(2).unwrap().validators; + let signing_context = SigningContext { + parent_hash: BenchBuilder::::header(4).hash(), + session_index: 2, + }; + + data.backed_candidates.clear(); + + data.bitfields.iter_mut().enumerate().for_each(|(i, bitfield)| { + let unchecked_signed = UncheckedSigned::::benchmark_sign( + validators.get(ValidatorIndex(i as u32)).unwrap(), + bitvec::bitvec![u8, bitvec::order::Lsb0; 1; 6].into(), + &signing_context, + ValidatorIndex(i as u32), + ); + *bitfield = unchecked_signed; + }); + let mut inherent_data = InherentData::new(); + inherent_data.put_data(PARACHAINS_INHERENT_IDENTIFIER, &data).unwrap(); + + // Nothing has been filtered out. + assert_eq!( + Pallet::::create_inherent_inner(&inherent_data.clone()).unwrap(), + data + ); + + // No more candidates have been backed + assert!(Pallet::::on_chain_votes() + .unwrap() + .backing_validators_per_candidate + .is_empty()); + + // No more pending availability candidates + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(0)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![] + ); + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(1)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![] + ); + assert_eq!( + inclusion::PendingAvailability::::get(ParaId::from(2)) + .unwrap() + .into_iter() + .map(|c| c.core_occupied()) + .collect::>(), + vec![] + ); + + // Paras have the right on-chain heads now + expected_heads.into_iter().enumerate().for_each(|(id, head)| { + assert_eq!( + paras::Pallet::::para_head(ParaId::from(id as u32)).unwrap(), + head + ); + }); }); } @@ -255,6 +595,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -326,6 +668,8 @@ mod enter { num_validators_per_core: 6, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -395,6 +739,8 @@ mod enter { num_validators_per_core: 4, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -480,6 +826,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -565,6 +913,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -649,6 +999,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -754,6 +1106,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -820,6 +1174,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -884,6 +1240,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -985,6 +1343,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let mut para_inherent_data = scenario.data.clone(); @@ -1072,6 +1432,8 @@ mod enter { num_validators_per_core: 5, code_upgrade: None, fill_claimqueue: false, + elastic_paras: BTreeMap::new(), + unavailable_cores: vec![], }); let expected_para_inherent_data = scenario.data.clone(); @@ -1119,7 +1481,7 @@ mod sanitizers { inclusion::tests::{ back_candidate, collator_sign_candidate, BackingKind, TestCandidateBuilder, }, - mock::{new_test_ext, MockGenesisConfig}, + mock::new_test_ext, }; use bitvec::order::Lsb0; use primitives::{ @@ -1375,9 +1737,11 @@ mod sanitizers { mod candidates { use crate::{ - mock::set_disabled_validators, + mock::{set_disabled_validators, RuntimeOrigin}, scheduler::{common::Assignment, ParasEntry}, + util::{make_persisted_validation_data, make_persisted_validation_data_with_parent}, }; + use primitives::ValidationCode; use sp_std::collections::vec_deque::VecDeque; use super::*; @@ -1385,13 +1749,14 @@ mod sanitizers { // Backed candidates and scheduled parachains used for `sanitize_backed_candidates` testing struct TestData { backed_candidates: Vec, - all_backed_candidates_with_core: Vec<(BackedCandidate, CoreIndex)>, + expected_backed_candidates_with_core: + BTreeMap>, scheduled_paras: BTreeMap>, } - // Generate test data for the candidates and assert that the evnironment is set as expected + // Generate test data for the candidates and assert that the environment is set as expected // (check the comments for details) - fn get_test_data(core_index_enabled: bool) -> TestData { + fn get_test_data_one_core_per_para(core_index_enabled: bool) -> TestData { const RELAY_PARENT_NUM: u32 = 3; // Add the relay parent to `shared` pallet. Otherwise some code (e.g. filtering backing @@ -1467,6 +1832,24 @@ mod sanitizers { ), ])); + // Set the on-chain included head data for paras. + paras::Pallet::::set_current_head(ParaId::from(1), HeadData(vec![1])); + paras::Pallet::::set_current_head(ParaId::from(2), HeadData(vec![2])); + + // Set the current_code_hash + paras::Pallet::::force_set_current_code( + RuntimeOrigin::root(), + ParaId::from(1), + ValidationCode(vec![1]), + ) + .unwrap(); + paras::Pallet::::force_set_current_code( + RuntimeOrigin::root(), + ParaId::from(2), + ValidationCode(vec![2]), + ) + .unwrap(); + // Callback used for backing candidates let group_validators = |group_index: GroupIndex| { match group_index { @@ -1486,8 +1869,15 @@ mod sanitizers { para_id: ParaId::from(idx1), relay_parent, pov_hash: Hash::repeat_byte(idx1 as u8), - persisted_validation_data_hash: [42u8; 32].into(), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(idx1), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![idx1 as u8]), ..Default::default() } .build(); @@ -1523,36 +1913,34 @@ mod sanitizers { ] ); - let all_backed_candidates_with_core = backed_candidates - .iter() - .map(|candidate| { - // Only one entry for this test data. - ( - candidate.clone(), - scheduled - .get(&candidate.descriptor().para_id) - .unwrap() - .first() - .copied() - .unwrap(), - ) - }) - .collect(); + let mut expected_backed_candidates_with_core = BTreeMap::new(); + + for candidate in backed_candidates.iter() { + let para_id = candidate.descriptor().para_id; + + expected_backed_candidates_with_core.entry(para_id).or_insert(vec![]).push(( + candidate.clone(), + scheduled.get(¶_id).unwrap().first().copied().unwrap(), + )); + } TestData { backed_candidates, scheduled_paras: scheduled, - all_backed_candidates_with_core, + expected_backed_candidates_with_core, } } - // Generate test data for the candidates and assert that the evnironment is set as expected + // Generate test data for the candidates and assert that the environment is set as expected // (check the comments for details) // Para 1 scheduled on core 0 and core 1. Two candidates are supplied. // Para 2 scheduled on cores 2 and 3. One candidate supplied. // Para 3 scheduled on core 4. One candidate supplied. // Para 4 scheduled on core 5. Two candidates supplied. // Para 5 scheduled on core 6. No candidates supplied. + // Para 6 is not scheduled. One candidate supplied. + // Para 7 is scheduled on core 7 and 8, but the candidate contains the wrong core index. + // Para 8 is scheduled on core 9, but the candidate contains the wrong core index. fn get_test_data_multiple_cores_per_para(core_index_enabled: bool) -> TestData { const RELAY_PARENT_NUM: u32 = 3; @@ -1581,6 +1969,7 @@ mod sanitizers { keyring::Sr25519Keyring::Eve, keyring::Sr25519Keyring::Ferdie, keyring::Sr25519Keyring::One, + keyring::Sr25519Keyring::Two, ]; for validator in validators.iter() { Keystore::sr25519_generate_new( @@ -1605,6 +1994,7 @@ mod sanitizers { vec![ValidatorIndex(4)], vec![ValidatorIndex(5)], vec![ValidatorIndex(6)], + vec![ValidatorIndex(7)], ]); // Update scheduler's claimqueue with the parachains @@ -1658,8 +2048,40 @@ mod sanitizers { RELAY_PARENT_NUM, )]), ), + ( + CoreIndex::from(7), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 7.into(), core_index: CoreIndex(7) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(8), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 7.into(), core_index: CoreIndex(8) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(9), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 8.into(), core_index: CoreIndex(9) }, + RELAY_PARENT_NUM, + )]), + ), ])); + // Set the on-chain included head data and current code hash. + for id in 1..=8u32 { + paras::Pallet::::set_current_head(ParaId::from(id), HeadData(vec![id as u8])); + paras::Pallet::::force_set_current_code( + RuntimeOrigin::root(), + ParaId::from(id), + ValidationCode(vec![id as u8]), + ) + .unwrap(); + } + // Callback used for backing candidates let group_validators = |group_index: GroupIndex| { match group_index { @@ -1670,6 +2092,7 @@ mod sanitizers { group_index if group_index == GroupIndex::from(4) => Some(vec![4]), group_index if group_index == GroupIndex::from(5) => Some(vec![5]), group_index if group_index == GroupIndex::from(6) => Some(vec![6]), + group_index if group_index == GroupIndex::from(7) => Some(vec![7]), _ => panic!("Group index out of bounds"), } @@ -1677,7 +2100,7 @@ mod sanitizers { }; let mut backed_candidates = vec![]; - let mut all_backed_candidates_with_core = vec![]; + let mut expected_backed_candidates_with_core = BTreeMap::new(); // Para 1 { @@ -1685,14 +2108,23 @@ mod sanitizers { para_id: ParaId::from(1), relay_parent, pov_hash: Hash::repeat_byte(1 as u8), - persisted_validation_data_hash: [42u8; 32].into(), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(1), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), hrmp_watermark: RELAY_PARENT_NUM, + head_data: HeadData(vec![1, 1]), + validation_code: ValidationCode(vec![1]), ..Default::default() } .build(); collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + let prev_candidate = candidate.clone(); let backed: BackedCandidate = back_candidate( candidate, &validators, @@ -1704,15 +2136,26 @@ mod sanitizers { ); backed_candidates.push(backed.clone()); if core_index_enabled { - all_backed_candidates_with_core.push((backed, CoreIndex(0))); + expected_backed_candidates_with_core + .entry(ParaId::from(1)) + .or_insert(vec![]) + .push((backed, CoreIndex(0))); } let mut candidate = TestCandidateBuilder { para_id: ParaId::from(1), relay_parent, pov_hash: Hash::repeat_byte(2 as u8), - persisted_validation_data_hash: [42u8; 32].into(), + persisted_validation_data_hash: make_persisted_validation_data_with_parent::< + Test, + >( + RELAY_PARENT_NUM, + Default::default(), + prev_candidate.commitments.head_data, + ) + .hash(), hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![1]), ..Default::default() } .build(); @@ -1730,7 +2173,10 @@ mod sanitizers { ); backed_candidates.push(backed.clone()); if core_index_enabled { - all_backed_candidates_with_core.push((backed, CoreIndex(1))); + expected_backed_candidates_with_core + .entry(ParaId::from(1)) + .or_insert(vec![]) + .push((backed, CoreIndex(1))); } } @@ -1740,8 +2186,15 @@ mod sanitizers { para_id: ParaId::from(2), relay_parent, pov_hash: Hash::repeat_byte(3 as u8), - persisted_validation_data_hash: [42u8; 32].into(), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(2), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![2]), ..Default::default() } .build(); @@ -1759,7 +2212,10 @@ mod sanitizers { ); backed_candidates.push(backed.clone()); if core_index_enabled { - all_backed_candidates_with_core.push((backed, CoreIndex(2))); + expected_backed_candidates_with_core + .entry(ParaId::from(2)) + .or_insert(vec![]) + .push((backed, CoreIndex(2))); } } @@ -1769,8 +2225,15 @@ mod sanitizers { para_id: ParaId::from(3), relay_parent, pov_hash: Hash::repeat_byte(4 as u8), - persisted_validation_data_hash: [42u8; 32].into(), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(3), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![3]), ..Default::default() } .build(); @@ -1787,7 +2250,10 @@ mod sanitizers { core_index_enabled.then_some(CoreIndex(4 as u32)), ); backed_candidates.push(backed.clone()); - all_backed_candidates_with_core.push((backed, CoreIndex(4))); + expected_backed_candidates_with_core + .entry(ParaId::from(3)) + .or_insert(vec![]) + .push((backed, CoreIndex(4))); } // Para 4 @@ -1796,14 +2262,22 @@ mod sanitizers { para_id: ParaId::from(4), relay_parent, pov_hash: Hash::repeat_byte(5 as u8), - persisted_validation_data_hash: [42u8; 32].into(), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(4), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![4]), ..Default::default() } .build(); collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + let prev_candidate = candidate.clone(); let backed = back_candidate( candidate, &validators, @@ -1811,17 +2285,28 @@ mod sanitizers { &keystore, &signing_context, BackingKind::Threshold, - None, + core_index_enabled.then_some(CoreIndex(5 as u32)), ); backed_candidates.push(backed.clone()); - all_backed_candidates_with_core.push((backed, CoreIndex(5))); + expected_backed_candidates_with_core + .entry(ParaId::from(4)) + .or_insert(vec![]) + .push((backed, CoreIndex(5))); let mut candidate = TestCandidateBuilder { para_id: ParaId::from(4), relay_parent, pov_hash: Hash::repeat_byte(6 as u8), - persisted_validation_data_hash: [42u8; 32].into(), + persisted_validation_data_hash: make_persisted_validation_data_with_parent::< + Test, + >( + RELAY_PARENT_NUM, + Default::default(), + prev_candidate.commitments.head_data, + ) + .hash(), hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![4]), ..Default::default() } .build(); @@ -1842,25 +2327,635 @@ mod sanitizers { // No candidate for para 5. - // State sanity checks - assert_eq!( - >::scheduled_paras().collect::>(), - vec![ - (CoreIndex(0), ParaId::from(1)), - (CoreIndex(1), ParaId::from(1)), - (CoreIndex(2), ParaId::from(2)), - (CoreIndex(3), ParaId::from(2)), - (CoreIndex(4), ParaId::from(3)), - (CoreIndex(5), ParaId::from(4)), - (CoreIndex(6), ParaId::from(5)), - ] - ); - let mut scheduled: BTreeMap> = BTreeMap::new(); - for (core_idx, para_id) in >::scheduled_paras() { - scheduled.entry(para_id).or_default().insert(core_idx); + // Para 6. + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(6), + relay_parent, + pov_hash: Hash::repeat_byte(3 as u8), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(6), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![6]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(6 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(6 as u32)), + ); + backed_candidates.push(backed.clone()); } - assert_eq!( + // Para 7. + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(7), + relay_parent, + pov_hash: Hash::repeat_byte(3 as u8), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(7), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![7]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(6 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(6 as u32)), + ); + backed_candidates.push(backed.clone()); + } + + // Para 8. + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(8), + relay_parent, + pov_hash: Hash::repeat_byte(3 as u8), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(8), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![8]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(6 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(7 as u32)), + ); + backed_candidates.push(backed.clone()); + if !core_index_enabled { + expected_backed_candidates_with_core + .entry(ParaId::from(8)) + .or_insert(vec![]) + .push((backed, CoreIndex(9))); + } + } + + // State sanity checks + assert_eq!( + >::scheduled_paras().collect::>(), + vec![ + (CoreIndex(0), ParaId::from(1)), + (CoreIndex(1), ParaId::from(1)), + (CoreIndex(2), ParaId::from(2)), + (CoreIndex(3), ParaId::from(2)), + (CoreIndex(4), ParaId::from(3)), + (CoreIndex(5), ParaId::from(4)), + (CoreIndex(6), ParaId::from(5)), + (CoreIndex(7), ParaId::from(7)), + (CoreIndex(8), ParaId::from(7)), + (CoreIndex(9), ParaId::from(8)), + ] + ); + let mut scheduled: BTreeMap> = BTreeMap::new(); + for (core_idx, para_id) in >::scheduled_paras() { + scheduled.entry(para_id).or_default().insert(core_idx); + } + + assert_eq!( + shared::Pallet::::active_validator_indices(), + vec![ + ValidatorIndex(0), + ValidatorIndex(1), + ValidatorIndex(2), + ValidatorIndex(3), + ValidatorIndex(4), + ValidatorIndex(5), + ValidatorIndex(6), + ValidatorIndex(7), + ] + ); + + TestData { + backed_candidates, + scheduled_paras: scheduled, + expected_backed_candidates_with_core, + } + } + + // Para 1 scheduled on core 0 and core 1. Two candidates are supplied. They form a chain but + // in the wrong order. + // Para 2 scheduled on core 2, core 3 and core 4. Three candidates are supplied. The second + // one is not part of the chain. + // Para 3 scheduled on core 5 and 6. Two candidates are supplied and they all form a chain. + // Para 4 scheduled on core 7 and 8. Duplicated candidates. + fn get_test_data_for_order_checks(core_index_enabled: bool) -> TestData { + const RELAY_PARENT_NUM: u32 = 3; + + // Add the relay parent to `shared` pallet. Otherwise some code (e.g. filtering backing + // votes) won't behave correctly + shared::Pallet::::add_allowed_relay_parent( + default_header().hash(), + Default::default(), + RELAY_PARENT_NUM, + 1, + ); + + let header = default_header(); + let relay_parent = header.hash(); + let session_index = SessionIndex::from(0_u32); + + let keystore = LocalKeystore::in_memory(); + let keystore = Arc::new(keystore) as KeystorePtr; + let signing_context = SigningContext { parent_hash: relay_parent, session_index }; + + let validators = vec![ + keyring::Sr25519Keyring::Alice, + keyring::Sr25519Keyring::Bob, + keyring::Sr25519Keyring::Charlie, + keyring::Sr25519Keyring::Dave, + keyring::Sr25519Keyring::Eve, + keyring::Sr25519Keyring::Ferdie, + keyring::Sr25519Keyring::One, + keyring::Sr25519Keyring::Two, + keyring::Sr25519Keyring::AliceStash, + ]; + for validator in validators.iter() { + Keystore::sr25519_generate_new( + &*keystore, + PARACHAIN_KEY_TYPE_ID, + Some(&validator.to_seed()), + ) + .unwrap(); + } + + // Set active validators in `shared` pallet + let validator_ids = + validators.iter().map(|v| v.public().into()).collect::>(); + shared::Pallet::::set_active_validators_ascending(validator_ids); + + // Set the validator groups in `scheduler` + scheduler::Pallet::::set_validator_groups(vec![ + vec![ValidatorIndex(0)], + vec![ValidatorIndex(1)], + vec![ValidatorIndex(2)], + vec![ValidatorIndex(3)], + vec![ValidatorIndex(4)], + vec![ValidatorIndex(5)], + vec![ValidatorIndex(6)], + vec![ValidatorIndex(7)], + vec![ValidatorIndex(8)], + ]); + + // Update scheduler's claimqueue with the parachains + scheduler::Pallet::::set_claimqueue(BTreeMap::from([ + ( + CoreIndex::from(0), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 1.into(), core_index: CoreIndex(0) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(1), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 1.into(), core_index: CoreIndex(1) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(2), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 2.into(), core_index: CoreIndex(2) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(3), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 2.into(), core_index: CoreIndex(3) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(4), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 2.into(), core_index: CoreIndex(4) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(5), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 3.into(), core_index: CoreIndex(5) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(6), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 3.into(), core_index: CoreIndex(6) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(7), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 4.into(), core_index: CoreIndex(7) }, + RELAY_PARENT_NUM, + )]), + ), + ( + CoreIndex::from(8), + VecDeque::from([ParasEntry::new( + Assignment::Pool { para_id: 4.into(), core_index: CoreIndex(8) }, + RELAY_PARENT_NUM, + )]), + ), + ])); + + // Set the on-chain included head data and current code hash. + for id in 1..=4u32 { + paras::Pallet::::set_current_head(ParaId::from(id), HeadData(vec![id as u8])); + paras::Pallet::::force_set_current_code( + RuntimeOrigin::root(), + ParaId::from(id), + ValidationCode(vec![id as u8]), + ) + .unwrap(); + } + + // Callback used for backing candidates + let group_validators = |group_index: GroupIndex| { + match group_index { + group_index if group_index == GroupIndex::from(0) => Some(vec![0]), + group_index if group_index == GroupIndex::from(1) => Some(vec![1]), + group_index if group_index == GroupIndex::from(2) => Some(vec![2]), + group_index if group_index == GroupIndex::from(3) => Some(vec![3]), + group_index if group_index == GroupIndex::from(4) => Some(vec![4]), + group_index if group_index == GroupIndex::from(5) => Some(vec![5]), + group_index if group_index == GroupIndex::from(6) => Some(vec![6]), + group_index if group_index == GroupIndex::from(7) => Some(vec![7]), + group_index if group_index == GroupIndex::from(8) => Some(vec![8]), + + _ => panic!("Group index out of bounds"), + } + .map(|m| m.into_iter().map(ValidatorIndex).collect::>()) + }; + + let mut backed_candidates = vec![]; + let mut expected_backed_candidates_with_core = BTreeMap::new(); + + // Para 1 + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(1), + relay_parent, + pov_hash: Hash::repeat_byte(1 as u8), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(1), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), + head_data: HeadData(vec![1, 1]), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![1]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let prev_candidate = candidate.clone(); + let prev_backed: BackedCandidate = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(0 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(0 as u32)), + ); + + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(1), + relay_parent, + pov_hash: Hash::repeat_byte(2 as u8), + persisted_validation_data_hash: make_persisted_validation_data_with_parent::< + Test, + >( + RELAY_PARENT_NUM, + Default::default(), + prev_candidate.commitments.head_data, + ) + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![1]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(1 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(1 as u32)), + ); + backed_candidates.push(backed.clone()); + backed_candidates.push(prev_backed.clone()); + } + + // Para 2. + { + let mut candidate_1 = TestCandidateBuilder { + para_id: ParaId::from(2), + relay_parent, + pov_hash: Hash::repeat_byte(3 as u8), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(2), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), + head_data: HeadData(vec![2, 2]), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![2]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate_1); + + let backed_1: BackedCandidate = back_candidate( + candidate_1, + &validators, + group_validators(GroupIndex::from(2 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(2 as u32)), + ); + + backed_candidates.push(backed_1.clone()); + if core_index_enabled { + expected_backed_candidates_with_core + .entry(ParaId::from(2)) + .or_insert(vec![]) + .push((backed_1, CoreIndex(2))); + } + + let mut candidate_2 = TestCandidateBuilder { + para_id: ParaId::from(2), + relay_parent, + pov_hash: Hash::repeat_byte(4 as u8), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(2), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![2]), + head_data: HeadData(vec![3, 3]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate_2); + + let backed_2 = back_candidate( + candidate_2.clone(), + &validators, + group_validators(GroupIndex::from(3 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(3 as u32)), + ); + backed_candidates.push(backed_2.clone()); + + let mut candidate_3 = TestCandidateBuilder { + para_id: ParaId::from(2), + relay_parent, + pov_hash: Hash::repeat_byte(5 as u8), + persisted_validation_data_hash: make_persisted_validation_data_with_parent::< + Test, + >( + RELAY_PARENT_NUM, + Default::default(), + candidate_2.commitments.head_data, + ) + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![2]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate_3); + + let backed_3 = back_candidate( + candidate_3, + &validators, + group_validators(GroupIndex::from(4 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(4 as u32)), + ); + backed_candidates.push(backed_3.clone()); + } + + // Para 3 + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(3), + relay_parent, + pov_hash: Hash::repeat_byte(6 as u8), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(3), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), + head_data: HeadData(vec![3, 3]), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![3]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let prev_candidate = candidate.clone(); + let backed: BackedCandidate = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(5 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(5 as u32)), + ); + backed_candidates.push(backed.clone()); + if core_index_enabled { + expected_backed_candidates_with_core + .entry(ParaId::from(3)) + .or_insert(vec![]) + .push((backed, CoreIndex(5))); + } + + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(3), + relay_parent, + pov_hash: Hash::repeat_byte(6 as u8), + persisted_validation_data_hash: make_persisted_validation_data_with_parent::< + Test, + >( + RELAY_PARENT_NUM, + Default::default(), + prev_candidate.commitments.head_data, + ) + .hash(), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![3]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(6 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(6 as u32)), + ); + backed_candidates.push(backed.clone()); + if core_index_enabled { + expected_backed_candidates_with_core + .entry(ParaId::from(3)) + .or_insert(vec![]) + .push((backed, CoreIndex(6))); + } + } + + // Para 4 + { + let mut candidate = TestCandidateBuilder { + para_id: ParaId::from(4), + relay_parent, + pov_hash: Hash::repeat_byte(8 as u8), + persisted_validation_data_hash: make_persisted_validation_data::( + ParaId::from(4), + RELAY_PARENT_NUM, + Default::default(), + ) + .unwrap() + .hash(), + head_data: HeadData(vec![4]), + hrmp_watermark: RELAY_PARENT_NUM, + validation_code: ValidationCode(vec![4]), + ..Default::default() + } + .build(); + + collator_sign_candidate(Sr25519Keyring::One, &mut candidate); + + let backed: BackedCandidate = back_candidate( + candidate.clone(), + &validators, + group_validators(GroupIndex::from(7 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(7 as u32)), + ); + backed_candidates.push(backed.clone()); + if core_index_enabled { + expected_backed_candidates_with_core + .entry(ParaId::from(4)) + .or_insert(vec![]) + .push((backed, CoreIndex(7))); + } + + let backed: BackedCandidate = back_candidate( + candidate, + &validators, + group_validators(GroupIndex::from(7 as u32)).unwrap().as_ref(), + &keystore, + &signing_context, + BackingKind::Threshold, + core_index_enabled.then_some(CoreIndex(8 as u32)), + ); + backed_candidates.push(backed.clone()); + } + + // State sanity checks + assert_eq!( + >::scheduled_paras().collect::>(), + vec![ + (CoreIndex(0), ParaId::from(1)), + (CoreIndex(1), ParaId::from(1)), + (CoreIndex(2), ParaId::from(2)), + (CoreIndex(3), ParaId::from(2)), + (CoreIndex(4), ParaId::from(2)), + (CoreIndex(5), ParaId::from(3)), + (CoreIndex(6), ParaId::from(3)), + (CoreIndex(7), ParaId::from(4)), + (CoreIndex(8), ParaId::from(4)), + ] + ); + let mut scheduled: BTreeMap> = BTreeMap::new(); + for (core_idx, para_id) in >::scheduled_paras() { + scheduled.entry(para_id).or_default().insert(core_idx); + } + + assert_eq!( shared::Pallet::::active_validator_indices(), vec![ ValidatorIndex(0), @@ -1870,43 +2965,38 @@ mod sanitizers { ValidatorIndex(4), ValidatorIndex(5), ValidatorIndex(6), + ValidatorIndex(7), + ValidatorIndex(8), ] ); TestData { backed_candidates, scheduled_paras: scheduled, - all_backed_candidates_with_core, + expected_backed_candidates_with_core, } } #[rstest] #[case(false)] #[case(true)] - fn happy_path(#[case] core_index_enabled: bool) { - new_test_ext(MockGenesisConfig::default()).execute_with(|| { + fn happy_path_one_core_per_para(#[case] core_index_enabled: bool) { + new_test_ext(default_config()).execute_with(|| { let TestData { backed_candidates, - all_backed_candidates_with_core, + expected_backed_candidates_with_core, scheduled_paras: scheduled, - } = get_test_data(core_index_enabled); - - let has_concluded_invalid = - |_idx: usize, _backed_candidate: &BackedCandidate| -> bool { false }; + } = get_test_data_one_core_per_para(core_index_enabled); assert_eq!( - sanitize_backed_candidates::( + sanitize_backed_candidates::( backed_candidates.clone(), &>::allowed_relay_parents(), - has_concluded_invalid, + BTreeSet::new(), scheduled, core_index_enabled ), - SanitizedBackedCandidates { - backed_candidates_with_core: all_backed_candidates_with_core, - votes_from_disabled_were_dropped: false, - dropped_unscheduled_candidates: false - } + expected_backed_candidates_with_core, ); }); } @@ -1915,29 +3005,46 @@ mod sanitizers { #[case(false)] #[case(true)] fn test_with_multiple_cores_per_para(#[case] core_index_enabled: bool) { - new_test_ext(MockGenesisConfig::default()).execute_with(|| { + new_test_ext(default_config()).execute_with(|| { let TestData { backed_candidates, - all_backed_candidates_with_core: expected_all_backed_candidates_with_core, + expected_backed_candidates_with_core, scheduled_paras: scheduled, } = get_test_data_multiple_cores_per_para(core_index_enabled); - let has_concluded_invalid = - |_idx: usize, _backed_candidate: &BackedCandidate| -> bool { false }; - assert_eq!( - sanitize_backed_candidates::( + sanitize_backed_candidates::( backed_candidates.clone(), &>::allowed_relay_parents(), - has_concluded_invalid, + BTreeSet::new(), scheduled, core_index_enabled ), - SanitizedBackedCandidates { - backed_candidates_with_core: expected_all_backed_candidates_with_core, - votes_from_disabled_were_dropped: false, - dropped_unscheduled_candidates: true - } + expected_backed_candidates_with_core, + ); + }); + } + + #[rstest] + #[case(false)] + #[case(true)] + fn test_candidate_ordering(#[case] core_index_enabled: bool) { + new_test_ext(default_config()).execute_with(|| { + let TestData { + backed_candidates, + scheduled_paras: scheduled, + expected_backed_candidates_with_core, + } = get_test_data_for_order_checks(core_index_enabled); + + assert_eq!( + sanitize_backed_candidates::( + backed_candidates.clone(), + &>::allowed_relay_parents(), + BTreeSet::new(), + scheduled, + core_index_enabled, + ), + expected_backed_candidates_with_core ); }); } @@ -1952,31 +3059,23 @@ mod sanitizers { #[case] core_index_enabled: bool, #[case] multiple_cores_per_para: bool, ) { - new_test_ext(MockGenesisConfig::default()).execute_with(|| { + new_test_ext(default_config()).execute_with(|| { let TestData { backed_candidates, .. } = if multiple_cores_per_para { get_test_data_multiple_cores_per_para(core_index_enabled) } else { - get_test_data(core_index_enabled) + get_test_data_one_core_per_para(core_index_enabled) }; let scheduled = BTreeMap::new(); - let has_concluded_invalid = - |_idx: usize, _backed_candidate: &BackedCandidate| -> bool { false }; - - let SanitizedBackedCandidates { - backed_candidates_with_core: sanitized_backed_candidates, - votes_from_disabled_were_dropped, - dropped_unscheduled_candidates, - } = sanitize_backed_candidates::( + + let sanitized_backed_candidates = sanitize_backed_candidates::( backed_candidates.clone(), &>::allowed_relay_parents(), - has_concluded_invalid, + BTreeSet::new(), scheduled, core_index_enabled, ); assert!(sanitized_backed_candidates.is_empty()); - assert!(!votes_from_disabled_were_dropped); - assert!(dropped_unscheduled_candidates); }); } @@ -1984,14 +3083,16 @@ mod sanitizers { #[rstest] #[case(false)] #[case(true)] - fn invalid_are_filtered_out(#[case] core_index_enabled: bool) { - new_test_ext(MockGenesisConfig::default()).execute_with(|| { + fn concluded_invalid_are_filtered_out_single_core_per_para( + #[case] core_index_enabled: bool, + ) { + new_test_ext(default_config()).execute_with(|| { let TestData { backed_candidates, scheduled_paras: scheduled, .. } = - get_test_data(core_index_enabled); + get_test_data_one_core_per_para(core_index_enabled); // mark every second one as concluded invalid let set = { - let mut set = std::collections::HashSet::new(); + let mut set = std::collections::BTreeSet::new(); for (idx, backed_candidate) in backed_candidates.iter().enumerate() { if idx & 0x01 == 0 { set.insert(backed_candidate.hash()); @@ -1999,23 +3100,98 @@ mod sanitizers { } set }; - let has_concluded_invalid = - |_idx: usize, candidate: &BackedCandidate| set.contains(&candidate.hash()); - let SanitizedBackedCandidates { - backed_candidates_with_core: sanitized_backed_candidates, - votes_from_disabled_were_dropped, - dropped_unscheduled_candidates, - } = sanitize_backed_candidates::( + let sanitized_backed_candidates: BTreeMap< + ParaId, + Vec<(BackedCandidate<_>, CoreIndex)>, + > = sanitize_backed_candidates::( backed_candidates.clone(), &>::allowed_relay_parents(), - has_concluded_invalid, + set, scheduled, core_index_enabled, ); assert_eq!(sanitized_backed_candidates.len(), backed_candidates.len() / 2); - assert!(!votes_from_disabled_were_dropped); - assert!(!dropped_unscheduled_candidates); + }); + } + + // candidates that have concluded as invalid are filtered out, as well as their descendants. + #[test] + fn concluded_invalid_are_filtered_out_multiple_cores_per_para() { + // Mark the first candidate of paraid 1 as invalid. Its descendant should also + // be dropped. Also mark the candidate of paraid 3 as invalid. + new_test_ext(default_config()).execute_with(|| { + let TestData { + backed_candidates, + scheduled_paras: scheduled, + mut expected_backed_candidates_with_core, + .. + } = get_test_data_multiple_cores_per_para(true); + + let mut invalid_set = std::collections::BTreeSet::new(); + + for (idx, backed_candidate) in backed_candidates.iter().enumerate() { + if backed_candidate.descriptor().para_id == ParaId::from(1) && idx == 0 { + invalid_set.insert(backed_candidate.hash()); + } else if backed_candidate.descriptor().para_id == ParaId::from(3) { + invalid_set.insert(backed_candidate.hash()); + } + } + let sanitized_backed_candidates: BTreeMap< + ParaId, + Vec<(BackedCandidate<_>, CoreIndex)>, + > = sanitize_backed_candidates::( + backed_candidates.clone(), + &>::allowed_relay_parents(), + invalid_set, + scheduled, + true, + ); + + // We'll be left with candidates from paraid 2 and 4. + + expected_backed_candidates_with_core.remove(&ParaId::from(1)).unwrap(); + expected_backed_candidates_with_core.remove(&ParaId::from(3)).unwrap(); + + assert_eq!(sanitized_backed_candidates, sanitized_backed_candidates); + }); + + // Mark the second candidate of paraid 1 as invalid. Its predecessor should be left + // in place. + new_test_ext(default_config()).execute_with(|| { + let TestData { + backed_candidates, + scheduled_paras: scheduled, + mut expected_backed_candidates_with_core, + .. + } = get_test_data_multiple_cores_per_para(true); + + let mut invalid_set = std::collections::BTreeSet::new(); + + for (idx, backed_candidate) in backed_candidates.iter().enumerate() { + if backed_candidate.descriptor().para_id == ParaId::from(1) && idx == 1 { + invalid_set.insert(backed_candidate.hash()); + } + } + let sanitized_backed_candidates: BTreeMap< + ParaId, + Vec<(BackedCandidate<_>, CoreIndex)>, + > = sanitize_backed_candidates::( + backed_candidates.clone(), + &>::allowed_relay_parents(), + invalid_set, + scheduled, + true, + ); + + // Only the second candidate of paraid 1 should be removed. + expected_backed_candidates_with_core + .get_mut(&ParaId::from(1)) + .unwrap() + .remove(1); + + // We'll be left with candidates from paraid 1, 2, 3 and 4. + assert_eq!(sanitized_backed_candidates, expected_backed_candidates_with_core); }); } @@ -2023,34 +3199,35 @@ mod sanitizers { #[case(false)] #[case(true)] fn disabled_non_signing_validator_doesnt_get_filtered(#[case] core_index_enabled: bool) { - new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { mut all_backed_candidates_with_core, .. } = - get_test_data(core_index_enabled); + new_test_ext(default_config()).execute_with(|| { + let TestData { mut expected_backed_candidates_with_core, .. } = + get_test_data_one_core_per_para(core_index_enabled); // Disable Eve set_disabled_validators(vec![4]); - let before = all_backed_candidates_with_core.clone(); + let before = expected_backed_candidates_with_core.clone(); // Eve is disabled but no backing statement is signed by it so nothing should be // filtered - assert!(!filter_backed_statements_from_disabled_validators::( - &mut all_backed_candidates_with_core, + filter_backed_statements_from_disabled_validators::( + &mut expected_backed_candidates_with_core, &>::allowed_relay_parents(), - core_index_enabled - )); - assert_eq!(all_backed_candidates_with_core, before); + core_index_enabled, + ); + assert_eq!(expected_backed_candidates_with_core, before); }); } + #[rstest] #[case(false)] #[case(true)] fn drop_statements_from_disabled_without_dropping_candidate( #[case] core_index_enabled: bool, ) { - new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { mut all_backed_candidates_with_core, .. } = - get_test_data(core_index_enabled); + new_test_ext(default_config()).execute_with(|| { + let TestData { mut expected_backed_candidates_with_core, .. } = + get_test_data_one_core_per_para(core_index_enabled); // Disable Alice set_disabled_validators(vec![0]); @@ -2064,11 +3241,22 @@ mod sanitizers { // Verify the initial state is as expected assert_eq!( - all_backed_candidates_with_core.get(0).unwrap().0.validity_votes().len(), + expected_backed_candidates_with_core + .get(&ParaId::from(1)) + .unwrap() + .iter() + .next() + .unwrap() + .0 + .validity_votes() + .len(), 2 ); - let (validator_indices, maybe_core_index) = all_backed_candidates_with_core - .get(0) + let (validator_indices, maybe_core_index) = expected_backed_candidates_with_core + .get(&ParaId::from(1)) + .unwrap() + .iter() + .next() .unwrap() .0 .validator_indices_and_core_index(core_index_enabled); @@ -2080,16 +3268,28 @@ mod sanitizers { assert_eq!(validator_indices.get(0).unwrap(), true); assert_eq!(validator_indices.get(1).unwrap(), true); - let untouched = all_backed_candidates_with_core.get(1).unwrap().0.clone(); + let untouched = expected_backed_candidates_with_core + .get(&ParaId::from(2)) + .unwrap() + .iter() + .next() + .unwrap() + .0 + .clone(); - assert!(filter_backed_statements_from_disabled_validators::( - &mut all_backed_candidates_with_core, + let before = expected_backed_candidates_with_core.clone(); + filter_backed_statements_from_disabled_validators::( + &mut expected_backed_candidates_with_core, &>::allowed_relay_parents(), - core_index_enabled - )); + core_index_enabled, + ); + assert_eq!(before.len(), expected_backed_candidates_with_core.len()); - let (validator_indices, maybe_core_index) = all_backed_candidates_with_core - .get(0) + let (validator_indices, maybe_core_index) = expected_backed_candidates_with_core + .get(&ParaId::from(1)) + .unwrap() + .iter() + .next() .unwrap() .0 .validator_indices_and_core_index(core_index_enabled); @@ -2100,47 +3300,137 @@ mod sanitizers { } // there should still be two backed candidates - assert_eq!(all_backed_candidates_with_core.len(), 2); + assert_eq!(expected_backed_candidates_with_core.len(), 2); // but the first one should have only one validity vote assert_eq!( - all_backed_candidates_with_core.get(0).unwrap().0.validity_votes().len(), + expected_backed_candidates_with_core + .get(&ParaId::from(1)) + .unwrap() + .iter() + .next() + .unwrap() + .0 + .validity_votes() + .len(), 1 ); // Validator 0 vote should be dropped, validator 1 - retained assert_eq!(validator_indices.get(0).unwrap(), false); assert_eq!(validator_indices.get(1).unwrap(), true); // the second candidate shouldn't be modified - assert_eq!(all_backed_candidates_with_core.get(1).unwrap().0, untouched); + assert_eq!( + expected_backed_candidates_with_core + .get(&ParaId::from(2)) + .unwrap() + .iter() + .next() + .unwrap() + .0, + untouched + ); }); } #[rstest] #[case(false)] #[case(true)] - fn drop_candidate_if_all_statements_are_from_disabled(#[case] core_index_enabled: bool) { - new_test_ext(MockGenesisConfig::default()).execute_with(|| { - let TestData { mut all_backed_candidates_with_core, .. } = - get_test_data(core_index_enabled); + fn drop_candidate_if_all_statements_are_from_disabled_single_core_per_para( + #[case] core_index_enabled: bool, + ) { + new_test_ext(default_config()).execute_with(|| { + let TestData { mut expected_backed_candidates_with_core, .. } = + get_test_data_one_core_per_para(core_index_enabled); // Disable Alice and Bob set_disabled_validators(vec![0, 1]); // Verify the initial state is as expected assert_eq!( - all_backed_candidates_with_core.get(0).unwrap().0.validity_votes().len(), + expected_backed_candidates_with_core + .get(&ParaId::from(1)) + .unwrap() + .iter() + .next() + .unwrap() + .0 + .validity_votes() + .len(), 2 ); - let untouched = all_backed_candidates_with_core.get(1).unwrap().0.clone(); + let untouched = expected_backed_candidates_with_core + .get(&ParaId::from(2)) + .unwrap() + .iter() + .next() + .unwrap() + .0 + .clone(); - assert!(filter_backed_statements_from_disabled_validators::( - &mut all_backed_candidates_with_core, + filter_backed_statements_from_disabled_validators::( + &mut expected_backed_candidates_with_core, &>::allowed_relay_parents(), - core_index_enabled - )); + core_index_enabled, + ); + + assert_eq!(expected_backed_candidates_with_core.len(), 1); + assert_eq!( + expected_backed_candidates_with_core + .get(&ParaId::from(2)) + .unwrap() + .iter() + .next() + .unwrap() + .0, + untouched + ); + assert_eq!(expected_backed_candidates_with_core.get(&ParaId::from(1)), None); + }); + } + + #[test] + fn drop_candidate_if_all_statements_are_from_disabled_multiple_cores_per_para() { + // Disable Bob, only the second candidate of paraid 1 should be removed. + new_test_ext(default_config()).execute_with(|| { + let TestData { mut expected_backed_candidates_with_core, .. } = + get_test_data_multiple_cores_per_para(true); - assert_eq!(all_backed_candidates_with_core.len(), 1); - assert_eq!(all_backed_candidates_with_core.get(0).unwrap().0, untouched); + set_disabled_validators(vec![1]); + + let mut untouched = expected_backed_candidates_with_core.clone(); + + filter_backed_statements_from_disabled_validators::( + &mut expected_backed_candidates_with_core, + &>::allowed_relay_parents(), + true, + ); + + untouched.get_mut(&ParaId::from(1)).unwrap().remove(1); + + assert_eq!(expected_backed_candidates_with_core, untouched); }); + + // Disable Alice or disable both Alice and Bob, all candidates of paraid 1 should be + // removed. + for disabled in [vec![0], vec![0, 1]] { + new_test_ext(default_config()).execute_with(|| { + let TestData { mut expected_backed_candidates_with_core, .. } = + get_test_data_multiple_cores_per_para(true); + + set_disabled_validators(disabled); + + let mut untouched = expected_backed_candidates_with_core.clone(); + + filter_backed_statements_from_disabled_validators::( + &mut expected_backed_candidates_with_core, + &>::allowed_relay_parents(), + true, + ); + + untouched.remove(&ParaId::from(1)).unwrap(); + + assert_eq!(expected_backed_candidates_with_core, untouched); + }); + } } } } diff --git a/polkadot/runtime/parachains/src/runtime_api_impl/v7.rs b/polkadot/runtime/parachains/src/runtime_api_impl/v7.rs index 1bbd4dfb716..171f3f746a8 100644 --- a/polkadot/runtime/parachains/src/runtime_api_impl/v7.rs +++ b/polkadot/runtime/parachains/src/runtime_api_impl/v7.rs @@ -22,6 +22,7 @@ use crate::{ scheduler::{self, CoreOccupied}, session_info, shared, }; +use frame_support::traits::{GetStorageVersion, StorageVersion}; use frame_system::pallet_prelude::*; use primitives::{ async_backing::{ @@ -92,16 +93,41 @@ pub fn availability_cores() -> Vec { - let pending_availability = - >::pending_availability(entry.para_id()) - .expect("Occupied core always has pending availability; qed"); - - let backed_in_number = *pending_availability.backed_in_number(); + // Due to https://github.com/paritytech/polkadot-sdk/issues/64, using the new storage types would cause + // this runtime API to panic. We explicitly handle the storage for version 0 to + // prevent that. When removing the inclusion v0 -> v1 migration, this bit of code + // can also be removed. + let pending_availability = if >::on_chain_storage_version() == + StorageVersion::new(0) + { + inclusion::migration::v0::PendingAvailability::::get(entry.para_id()) + .expect("Occupied core always has pending availability; qed") + } else { + let candidate = >::pending_availability_with_core( + entry.para_id(), + CoreIndex(i as u32), + ) + .expect("Occupied core always has pending availability; qed"); + + // Translate to the old candidate format, as we don't need the commitments now. + inclusion::migration::v0::CandidatePendingAvailability { + core: candidate.core_occupied(), + hash: candidate.candidate_hash(), + descriptor: candidate.candidate_descriptor().clone(), + availability_votes: candidate.availability_votes().clone(), + backers: candidate.backers().clone(), + relay_parent_number: candidate.relay_parent_number(), + backed_in_number: candidate.backed_in_number(), + backing_group: candidate.backing_group(), + } + }; + + let backed_in_number = pending_availability.backed_in_number; // Use the same block number for determining the responsible group as what the // backing subsystem would use when it calls validator_groups api. let backing_group_allocation_time = - pending_availability.relay_parent_number() + One::one(); + pending_availability.relay_parent_number + One::one(); CoreState::Occupied(OccupiedCore { next_up_on_available: >::next_up_on_available(CoreIndex( i as u32, @@ -111,13 +137,13 @@ pub fn availability_cores() -> Vec>::next_up_on_time_out(CoreIndex( i as u32, )), - availability: pending_availability.availability_votes().clone(), + availability: pending_availability.availability_votes.clone(), group_responsible: group_responsible_for( backing_group_allocation_time, - pending_availability.core_occupied(), + pending_availability.core, ), - candidate_hash: pending_availability.candidate_hash(), - candidate_descriptor: pending_availability.candidate_descriptor().clone(), + candidate_hash: pending_availability.hash, + candidate_descriptor: pending_availability.descriptor, }) }, CoreOccupied::Free => { @@ -200,8 +226,8 @@ pub fn assumed_validation_data( }; let persisted_validation_data = make_validation_data().or_else(|| { - // Try again with force enacting the core. This check only makes sense if - // the core is occupied. + // Try again with force enacting the pending candidates. This check only makes sense if + // there are any pending candidates. >::pending_availability(para_id).and_then(|_| { >::force_enact(para_id); make_validation_data() @@ -465,27 +491,23 @@ pub fn backing_state( }; let pending_availability = { - // Note: the API deals with a `Vec` as it is future-proof for cases - // where there may be multiple candidates pending availability at a time. - // But at the moment only one candidate can be pending availability per - // parachain. crate::inclusion::PendingAvailability::::get(¶_id) - .and_then(|pending| { - let commitments = - crate::inclusion::PendingAvailabilityCommitments::::get(¶_id); - commitments.map(move |c| (pending, c)) - }) - .map(|(pending, commitments)| { - CandidatePendingAvailability { - candidate_hash: pending.candidate_hash(), - descriptor: pending.candidate_descriptor().clone(), - commitments, - relay_parent_number: pending.relay_parent_number(), - max_pov_size: constraints.max_pov_size, // assume always same in session. - } + .map(|pending_candidates| { + pending_candidates + .into_iter() + .map(|candidate| { + CandidatePendingAvailability { + candidate_hash: candidate.candidate_hash(), + descriptor: candidate.candidate_descriptor().clone(), + commitments: candidate.candidate_commitments().clone(), + relay_parent_number: candidate.relay_parent_number(), + max_pov_size: constraints.max_pov_size, /* assume always same in + * session. */ + } + }) + .collect() }) - .into_iter() - .collect() + .unwrap_or_else(|| vec![]) }; Some(BackingState { constraints, pending_availability }) diff --git a/polkadot/runtime/parachains/src/scheduler.rs b/polkadot/runtime/parachains/src/scheduler.rs index f231864a85e..25840d9707d 100644 --- a/polkadot/runtime/parachains/src/scheduler.rs +++ b/polkadot/runtime/parachains/src/scheduler.rs @@ -398,16 +398,6 @@ impl Pallet { }); } - /// Get the para (chain or thread) ID assigned to a particular core or index, if any. Core - /// indices out of bounds will return `None`, as will indices of unassigned cores. - pub(crate) fn core_para(core_index: CoreIndex) -> Option { - let cores = AvailabilityCores::::get(); - match cores.get(core_index.0 as usize) { - None | Some(CoreOccupied::Free) => None, - Some(CoreOccupied::Paras(entry)) => Some(entry.para_id()), - } - } - /// Get the validators in the given group, if the group index is valid for this session. pub(crate) fn group_validators(group_index: GroupIndex) -> Option> { ValidatorGroups::::get().get(group_index.0 as usize).map(|g| g.clone()) diff --git a/polkadot/runtime/parachains/src/util.rs b/polkadot/runtime/parachains/src/util.rs index aa07ef08005..493a9d055ef 100644 --- a/polkadot/runtime/parachains/src/util.rs +++ b/polkadot/runtime/parachains/src/util.rs @@ -18,7 +18,7 @@ //! on all modules. use frame_system::pallet_prelude::BlockNumberFor; -use primitives::{Id as ParaId, PersistedValidationData, ValidatorIndex}; +use primitives::{HeadData, Id as ParaId, PersistedValidationData, ValidatorIndex}; use sp_std::{collections::btree_set::BTreeSet, vec::Vec}; use crate::{configuration, hrmp, paras}; @@ -42,6 +42,23 @@ pub fn make_persisted_validation_data( }) } +/// Make the persisted validation data for a particular parachain, a specified relay-parent, its +/// storage root and parent head data. +pub fn make_persisted_validation_data_with_parent( + relay_parent_number: BlockNumberFor, + relay_parent_storage_root: T::Hash, + parent_head: HeadData, +) -> PersistedValidationData> { + let config = >::config(); + + PersistedValidationData { + parent_head, + relay_parent_number, + relay_parent_storage_root, + max_pov_size: config.max_pov_size, + } +} + /// Take an active subset of a set containing all validators. /// /// First item in pair will be all items in set have indices found in the `active` indices set (in diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index c9f5d81d286..90824a2f6f0 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -1663,6 +1663,8 @@ pub mod migrations { // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, + + parachains_inclusion::migration::MigrateToV1, ); } diff --git a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs index a102d1903b2..c250c86665b 100644 --- a/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs +++ b/polkadot/runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs @@ -13,161 +13,322 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . + //! Autogenerated weights for `runtime_parachains::paras_inherent` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-20, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 128 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// target/release/polkadot +// target/production/polkadot // benchmark -// --chain=rococo-dev +// pallet // --steps=50 // --repeat=20 -// --pallet=runtime_parachains::paras_inherent // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./runtime/rococo/src/weights/runtime_parachains_paras_inherent.rs -// --header=./file_header.txt +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=runtime_parachains::paras_inherent +// --chain=rococo-dev +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{traits::Get, weights::Weight}; -use sp_std::marker::PhantomData; +use core::marker::PhantomData; /// Weight functions for `runtime_parachains::paras_inherent`. pub struct WeightInfo(PhantomData); impl runtime_parachains::paras_inherent::WeightInfo for WeightInfo { - // Storage: ParaInherent Included (r:1 w:1) - // Storage: System ParentHash (r:1 w:0) - // Storage: ParaScheduler AvailabilityCores (r:1 w:1) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParaSessionInfo Sessions (r:1 w:0) - // Storage: ParasDisputes Disputes (r:1 w:1) - // Storage: ParasDisputes Included (r:1 w:1) - // Storage: ParasDisputes SpamSlots (r:1 w:1) - // Storage: ParasDisputes Frozen (r:1 w:0) - // Storage: ParaInclusion PendingAvailability (r:2 w:1) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: Paras Parachains (r:1 w:0) - // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - // Storage: Hrmp HrmpChannelDigests (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: ParaScheduler SessionStartBlock (r:1 w:0) - // Storage: ParaScheduler ParathreadQueue (r:1 w:1) - // Storage: ParaScheduler Scheduled (r:1 w:1) - // Storage: ParaScheduler ValidatorGroups (r:1 w:0) - // Storage: Ump NeedsDispatch (r:1 w:1) - // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) - // Storage: ParaInherent OnChainVotes (r:0 w:1) - // Storage: Hrmp HrmpWatermarks (r:0 w:1) - // Storage: Paras Heads (r:0 w:1) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaSessionInfo::Sessions` (r:1 w:0) + /// Proof: `ParaSessionInfo::Sessions` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:1) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::BackersOnDisputes` (r:1 w:1) + /// Proof: `ParasDisputes::BackersOnDisputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:1 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::V1` (r:2 w:1) + /// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `v` is `[10, 200]`. fn enter_variable_disputes(v: u32, ) -> Weight { - Weight::from_parts(352_590_000 as u64, 0) - // Standard Error: 13_000 - .saturating_add(Weight::from_parts(49_254_000 as u64, 0).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(24 as u64)) - .saturating_add(T::DbWeight::get().writes(16 as u64)) + // Proof Size summary in bytes: + // Measured: `67785` + // Estimated: `73725 + v * (23 ±0)` + // Minimum execution time: 949_716_000 picoseconds. + Weight::from_parts(482_361_515, 0) + .saturating_add(Weight::from_parts(0, 73725)) + // Standard Error: 17_471 + .saturating_add(Weight::from_parts(50_100_764, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(25)) + .saturating_add(T::DbWeight::get().writes(15)) + .saturating_add(Weight::from_parts(0, 23).saturating_mul(v.into())) } - // Storage: ParaInherent Included (r:1 w:1) - // Storage: System ParentHash (r:1 w:0) - // Storage: ParaScheduler AvailabilityCores (r:1 w:1) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasDisputes Frozen (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: Paras Parachains (r:1 w:0) - // Storage: ParaInclusion PendingAvailability (r:2 w:1) - // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - // Storage: Hrmp HrmpChannelDigests (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: ParasDisputes Disputes (r:1 w:0) - // Storage: ParaScheduler SessionStartBlock (r:1 w:0) - // Storage: ParaScheduler ParathreadQueue (r:1 w:1) - // Storage: ParaScheduler Scheduled (r:1 w:1) - // Storage: ParaScheduler ValidatorGroups (r:1 w:0) - // Storage: Ump NeedsDispatch (r:1 w:1) - // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) - // Storage: ParaInclusion AvailabilityBitfields (r:0 w:1) - // Storage: ParaInherent OnChainVotes (r:0 w:1) - // Storage: ParasDisputes Included (r:0 w:1) - // Storage: Hrmp HrmpWatermarks (r:0 w:1) - // Storage: Paras Heads (r:0 w:1) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::V1` (r:2 w:1) + /// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) fn enter_bitfields() -> Weight { - Weight::from_parts(299_878_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(21 as u64)) - .saturating_add(T::DbWeight::get().writes(15 as u64)) + // Proof Size summary in bytes: + // Measured: `42757` + // Estimated: `48697` + // Minimum execution time: 437_627_000 picoseconds. + Weight::from_parts(460_975_000, 0) + .saturating_add(Weight::from_parts(0, 48697)) + .saturating_add(T::DbWeight::get().reads(23)) + .saturating_add(T::DbWeight::get().writes(15)) } - // Storage: ParaInherent Included (r:1 w:1) - // Storage: System ParentHash (r:1 w:0) - // Storage: ParaScheduler AvailabilityCores (r:1 w:1) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasDisputes Frozen (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: Paras Parachains (r:1 w:0) - // Storage: ParaInclusion PendingAvailability (r:2 w:1) - // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - // Storage: Hrmp HrmpChannelDigests (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: ParasDisputes Disputes (r:2 w:0) - // Storage: ParaScheduler SessionStartBlock (r:1 w:0) - // Storage: ParaScheduler ParathreadQueue (r:1 w:1) - // Storage: ParaScheduler Scheduled (r:1 w:1) - // Storage: ParaScheduler ValidatorGroups (r:1 w:0) - // Storage: Paras PastCodeMeta (r:1 w:0) - // Storage: Paras CurrentCodeHash (r:1 w:0) - // Storage: Ump RelayDispatchQueueSize (r:1 w:0) - // Storage: Ump NeedsDispatch (r:1 w:1) - // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) - // Storage: ParaInherent OnChainVotes (r:0 w:1) - // Storage: ParasDisputes Included (r:0 w:1) - // Storage: Hrmp HrmpWatermarks (r:0 w:1) - // Storage: Paras Heads (r:0 w:1) - fn enter_backed_candidates_variable(_v: u32) -> Weight { - Weight::from_parts(442_472_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(25 as u64)) - .saturating_add(T::DbWeight::get().writes(14 as u64)) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::V1` (r:2 w:1) + /// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `v` is `[101, 200]`. + fn enter_backed_candidates_variable(v: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `42829` + // Estimated: `48769` + // Minimum execution time: 1_305_254_000 picoseconds. + Weight::from_parts(1_347_160_667, 0) + .saturating_add(Weight::from_parts(0, 48769)) + // Standard Error: 22_128 + .saturating_add(Weight::from_parts(57_229, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(26)) + .saturating_add(T::DbWeight::get().writes(15)) } - // Storage: ParaInherent Included (r:1 w:1) - // Storage: System ParentHash (r:1 w:0) - // Storage: ParaScheduler AvailabilityCores (r:1 w:1) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasDisputes Frozen (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: Paras Parachains (r:1 w:0) - // Storage: ParaInclusion PendingAvailability (r:2 w:1) - // Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - // Storage: Hrmp HrmpChannelDigests (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: ParasDisputes Disputes (r:2 w:0) - // Storage: ParaScheduler SessionStartBlock (r:1 w:0) - // Storage: ParaScheduler ParathreadQueue (r:1 w:1) - // Storage: ParaScheduler Scheduled (r:1 w:1) - // Storage: ParaScheduler ValidatorGroups (r:1 w:0) - // Storage: Paras PastCodeMeta (r:1 w:0) - // Storage: Paras CurrentCodeHash (r:1 w:0) - // Storage: Ump RelayDispatchQueueSize (r:1 w:0) - // Storage: Ump NeedsDispatch (r:1 w:1) - // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) - // Storage: ParaInherent OnChainVotes (r:0 w:1) - // Storage: ParasDisputes Included (r:0 w:1) - // Storage: Hrmp HrmpWatermarks (r:0 w:1) - // Storage: Paras Heads (r:0 w:1) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::V1` (r:2 w:1) + /// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Registrar::Paras` (r:1 w:0) + /// Proof: `Registrar::Paras` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeHash` (r:1 w:0) + /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeRestrictionSignal` (r:1 w:0) + /// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) fn enter_backed_candidate_code_upgrade() -> Weight { - Weight::from_parts(36_903_411_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(25 as u64)) - .saturating_add(T::DbWeight::get().writes(14 as u64)) + // Proof Size summary in bytes: + // Measured: `42842` + // Estimated: `48782` + // Minimum execution time: 38_637_547_000 picoseconds. + Weight::from_parts(41_447_412_000, 0) + .saturating_add(Weight::from_parts(0, 48782)) + .saturating_add(T::DbWeight::get().reads(28)) + .saturating_add(T::DbWeight::get().writes(15)) } } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 83d47508c7c..664044b713e 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1781,6 +1781,7 @@ pub mod migrations { crate::xcm_config::XcmRouter, GetLegacyLeaseImpl, >, + parachains_inclusion::migration::MigrateToV1, ); } diff --git a/polkadot/runtime/westend/src/weights/runtime_parachains_paras_inherent.rs b/polkadot/runtime/westend/src/weights/runtime_parachains_paras_inherent.rs index 0dd64f054d0..aa99ac9438c 100644 --- a/polkadot/runtime/westend/src/weights/runtime_parachains_paras_inherent.rs +++ b/polkadot/runtime/westend/src/weights/runtime_parachains_paras_inherent.rs @@ -16,11 +16,11 @@ //! Autogenerated weights for `runtime_parachains::paras_inherent` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-xerhrdyb-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: // target/production/polkadot @@ -29,14 +29,13 @@ // --steps=50 // --repeat=20 // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot/.git/.artifacts/bench.json +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json // --pallet=runtime_parachains::paras_inherent // --chain=westend-dev -// --header=./file_header.txt -// --output=./runtime/westend/src/weights/ +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/westend/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -49,297 +48,311 @@ use core::marker::PhantomData; /// Weight functions for `runtime_parachains::paras_inherent`. pub struct WeightInfo(PhantomData); impl runtime_parachains::paras_inherent::WeightInfo for WeightInfo { - /// Storage: ParaInherent Included (r:1 w:1) - /// Proof Skipped: ParaInherent Included (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System ParentHash (r:1 w:0) - /// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler AvailabilityCores (r:1 w:1) - /// Proof Skipped: ParaScheduler AvailabilityCores (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Babe AuthorVrfRandomness (r:1 w:0) - /// Proof: Babe AuthorVrfRandomness (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen) - /// Storage: ParaSessionInfo Sessions (r:1 w:0) - /// Proof Skipped: ParaSessionInfo Sessions (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasDisputes Disputes (r:1 w:1) - /// Proof Skipped: ParasDisputes Disputes (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasDisputes BackersOnDisputes (r:1 w:1) - /// Proof Skipped: ParasDisputes BackersOnDisputes (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasDisputes Included (r:1 w:1) - /// Proof Skipped: ParasDisputes Included (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaSessionInfo AccountKeys (r:1 w:0) - /// Proof Skipped: ParaSessionInfo AccountKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: Session Validators (r:1 w:0) - /// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Staking ActiveEra (r:1 w:0) - /// Proof: Staking ActiveEra (max_values: Some(1), max_size: Some(13), added: 508, mode: MaxEncodedLen) - /// Storage: Staking ErasRewardPoints (r:1 w:1) - /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaInherent OnChainVotes (r:1 w:1) - /// Proof Skipped: ParaInherent OnChainVotes (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasDisputes Frozen (r:1 w:0) - /// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion PendingAvailability (r:2 w:1) - /// Proof Skipped: ParaInclusion PendingAvailability (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Parachains (r:1 w:0) - /// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - /// Proof Skipped: ParaInclusion PendingAvailabilityCommitments (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DeliveryFeeFactor (r:1 w:1) - /// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelDigests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpChannelDigests (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras FutureCodeUpgrades (r:1 w:0) - /// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaScheduler SessionStartBlock (r:1 w:0) - /// Proof Skipped: ParaScheduler SessionStartBlock (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler ParathreadQueue (r:1 w:1) - /// Proof Skipped: ParaScheduler ParathreadQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler Scheduled (r:1 w:1) - /// Proof Skipped: ParaScheduler Scheduled (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler ValidatorGroups (r:1 w:0) - /// Proof Skipped: ParaScheduler ValidatorGroups (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Hrmp HrmpWatermarks (r:0 w:1) - /// Proof Skipped: Hrmp HrmpWatermarks (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Heads (r:0 w:1) - /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeGoAheadSignal (r:0 w:1) - /// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaSessionInfo::Sessions` (r:1 w:0) + /// Proof: `ParaSessionInfo::Sessions` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:1) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::BackersOnDisputes` (r:1 w:1) + /// Proof: `ParasDisputes::BackersOnDisputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:1 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaSessionInfo::AccountKeys` (r:1 w:0) + /// Proof: `ParaSessionInfo::AccountKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::Validators` (r:1 w:0) + /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Staking::ErasRewardPoints` (r:1 w:1) + /// Proof: `Staking::ErasRewardPoints` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::V1` (r:2 w:1) + /// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `v` is `[10, 200]`. fn enter_variable_disputes(v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `50518` - // Estimated: `56458 + v * (23 ±0)` - // Minimum execution time: 998_338_000 picoseconds. - Weight::from_parts(468_412_001, 0) - .saturating_add(Weight::from_parts(0, 56458)) - // Standard Error: 20_559 - .saturating_add(Weight::from_parts(56_965_025, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(27)) - .saturating_add(T::DbWeight::get().writes(15)) + // Measured: `67518` + // Estimated: `73458 + v * (23 ±0)` + // Minimum execution time: 844_022_000 picoseconds. + Weight::from_parts(456_682_337, 0) + .saturating_add(Weight::from_parts(0, 73458)) + // Standard Error: 16_403 + .saturating_add(Weight::from_parts(41_871_245, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(28)) + .saturating_add(T::DbWeight::get().writes(16)) .saturating_add(Weight::from_parts(0, 23).saturating_mul(v.into())) } - /// Storage: ParaInherent Included (r:1 w:1) - /// Proof Skipped: ParaInherent Included (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System ParentHash (r:1 w:0) - /// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler AvailabilityCores (r:1 w:1) - /// Proof Skipped: ParaScheduler AvailabilityCores (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Babe AuthorVrfRandomness (r:1 w:0) - /// Proof: Babe AuthorVrfRandomness (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen) - /// Storage: ParaInherent OnChainVotes (r:1 w:1) - /// Proof Skipped: ParaInherent OnChainVotes (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasDisputes Frozen (r:1 w:0) - /// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion PendingAvailability (r:2 w:1) - /// Proof Skipped: ParaInclusion PendingAvailability (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Parachains (r:1 w:0) - /// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - /// Proof Skipped: ParaInclusion PendingAvailabilityCommitments (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaSessionInfo AccountKeys (r:1 w:0) - /// Proof Skipped: ParaSessionInfo AccountKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: Session Validators (r:1 w:0) - /// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Staking ActiveEra (r:1 w:0) - /// Proof: Staking ActiveEra (max_values: Some(1), max_size: Some(13), added: 508, mode: MaxEncodedLen) - /// Storage: Staking ErasRewardPoints (r:1 w:1) - /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DeliveryFeeFactor (r:1 w:1) - /// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelDigests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpChannelDigests (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras FutureCodeUpgrades (r:1 w:0) - /// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasDisputes Disputes (r:1 w:0) - /// Proof Skipped: ParasDisputes Disputes (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaScheduler SessionStartBlock (r:1 w:0) - /// Proof Skipped: ParaScheduler SessionStartBlock (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler ParathreadQueue (r:1 w:1) - /// Proof Skipped: ParaScheduler ParathreadQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler Scheduled (r:1 w:1) - /// Proof Skipped: ParaScheduler Scheduled (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler ValidatorGroups (r:1 w:0) - /// Proof Skipped: ParaScheduler ValidatorGroups (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion AvailabilityBitfields (r:0 w:1) - /// Proof Skipped: ParaInclusion AvailabilityBitfields (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasDisputes Included (r:0 w:1) - /// Proof Skipped: ParasDisputes Included (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpWatermarks (r:0 w:1) - /// Proof Skipped: Hrmp HrmpWatermarks (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Heads (r:0 w:1) - /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeGoAheadSignal (r:0 w:1) - /// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::V1` (r:2 w:1) + /// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaSessionInfo::AccountKeys` (r:1 w:0) + /// Proof: `ParaSessionInfo::AccountKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::Validators` (r:1 w:0) + /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Staking::ErasRewardPoints` (r:1 w:1) + /// Proof: `Staking::ErasRewardPoints` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) fn enter_bitfields() -> Weight { // Proof Size summary in bytes: - // Measured: `42352` - // Estimated: `48292` - // Minimum execution time: 457_404_000 picoseconds. - Weight::from_parts(485_416_000, 0) - .saturating_add(Weight::from_parts(0, 48292)) - .saturating_add(T::DbWeight::get().reads(25)) + // Measured: `43196` + // Estimated: `49136` + // Minimum execution time: 438_637_000 picoseconds. + Weight::from_parts(458_342_000, 0) + .saturating_add(Weight::from_parts(0, 49136)) + .saturating_add(T::DbWeight::get().reads(26)) .saturating_add(T::DbWeight::get().writes(16)) } - /// Storage: ParaInherent Included (r:1 w:1) - /// Proof Skipped: ParaInherent Included (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System ParentHash (r:1 w:0) - /// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler AvailabilityCores (r:1 w:1) - /// Proof Skipped: ParaScheduler AvailabilityCores (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Babe AuthorVrfRandomness (r:1 w:0) - /// Proof: Babe AuthorVrfRandomness (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen) - /// Storage: ParaInherent OnChainVotes (r:1 w:1) - /// Proof Skipped: ParaInherent OnChainVotes (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasDisputes Frozen (r:1 w:0) - /// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion PendingAvailability (r:2 w:1) - /// Proof Skipped: ParaInclusion PendingAvailability (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Parachains (r:1 w:0) - /// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - /// Proof Skipped: ParaInclusion PendingAvailabilityCommitments (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaSessionInfo AccountKeys (r:1 w:0) - /// Proof Skipped: ParaSessionInfo AccountKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: Session Validators (r:1 w:0) - /// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Staking ActiveEra (r:1 w:0) - /// Proof: Staking ActiveEra (max_values: Some(1), max_size: Some(13), added: 508, mode: MaxEncodedLen) - /// Storage: Staking ErasRewardPoints (r:1 w:1) - /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DeliveryFeeFactor (r:1 w:1) - /// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelDigests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpChannelDigests (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras FutureCodeUpgrades (r:1 w:0) - /// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasDisputes Disputes (r:1 w:0) - /// Proof Skipped: ParasDisputes Disputes (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaScheduler SessionStartBlock (r:1 w:0) - /// Proof Skipped: ParaScheduler SessionStartBlock (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler ParathreadQueue (r:1 w:1) - /// Proof Skipped: ParaScheduler ParathreadQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler Scheduled (r:1 w:1) - /// Proof Skipped: ParaScheduler Scheduled (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler ValidatorGroups (r:1 w:0) - /// Proof Skipped: ParaScheduler ValidatorGroups (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras CurrentCodeHash (r:1 w:0) - /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: MessageQueue BookStateFor (r:1 w:0) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) - /// Storage: ParasDisputes Included (r:0 w:1) - /// Proof Skipped: ParasDisputes Included (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpWatermarks (r:0 w:1) - /// Proof Skipped: Hrmp HrmpWatermarks (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Heads (r:0 w:1) - /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeGoAheadSignal (r:0 w:1) - /// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::V1` (r:2 w:1) + /// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaSessionInfo::AccountKeys` (r:1 w:0) + /// Proof: `ParaSessionInfo::AccountKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::Validators` (r:1 w:0) + /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Staking::ErasRewardPoints` (r:1 w:1) + /// Proof: `Staking::ErasRewardPoints` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `v` is `[101, 200]`. fn enter_backed_candidates_variable(v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `42387` - // Estimated: `48327` - // Minimum execution time: 6_864_029_000 picoseconds. - Weight::from_parts(1_237_704_892, 0) - .saturating_add(Weight::from_parts(0, 48327)) - // Standard Error: 33_413 - .saturating_add(Weight::from_parts(56_199_819, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(28)) - .saturating_add(T::DbWeight::get().writes(15)) + // Measured: `43269` + // Estimated: `49209` + // Minimum execution time: 5_955_361_000 picoseconds. + Weight::from_parts(1_285_398_956, 0) + .saturating_add(Weight::from_parts(0, 49209)) + // Standard Error: 57_369 + .saturating_add(Weight::from_parts(47_073_853, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(29)) + .saturating_add(T::DbWeight::get().writes(16)) } - /// Storage: ParaInherent Included (r:1 w:1) - /// Proof Skipped: ParaInherent Included (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System ParentHash (r:1 w:0) - /// Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) - /// Storage: ParasShared CurrentSessionIndex (r:1 w:0) - /// Proof Skipped: ParasShared CurrentSessionIndex (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler AvailabilityCores (r:1 w:1) - /// Proof Skipped: ParaScheduler AvailabilityCores (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - /// Proof Skipped: ParasShared ActiveValidatorKeys (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Babe AuthorVrfRandomness (r:1 w:0) - /// Proof: Babe AuthorVrfRandomness (max_values: Some(1), max_size: Some(33), added: 528, mode: MaxEncodedLen) - /// Storage: ParaInherent OnChainVotes (r:1 w:1) - /// Proof Skipped: ParaInherent OnChainVotes (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParasDisputes Frozen (r:1 w:0) - /// Proof Skipped: ParasDisputes Frozen (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion PendingAvailability (r:2 w:1) - /// Proof Skipped: ParaInclusion PendingAvailability (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Parachains (r:1 w:0) - /// Proof Skipped: Paras Parachains (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaInclusion PendingAvailabilityCommitments (r:1 w:1) - /// Proof Skipped: ParaInclusion PendingAvailabilityCommitments (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaSessionInfo AccountKeys (r:1 w:0) - /// Proof Skipped: ParaSessionInfo AccountKeys (max_values: None, max_size: None, mode: Measured) - /// Storage: Session Validators (r:1 w:0) - /// Proof Skipped: Session Validators (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Staking ActiveEra (r:1 w:0) - /// Proof: Staking ActiveEra (max_values: Some(1), max_size: Some(13), added: 508, mode: MaxEncodedLen) - /// Storage: Staking ErasRewardPoints (r:1 w:1) - /// Proof Skipped: Staking ErasRewardPoints (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DownwardMessageQueues (r:1 w:1) - /// Proof Skipped: Dmp DownwardMessageQueues (max_values: None, max_size: None, mode: Measured) - /// Storage: Dmp DeliveryFeeFactor (r:1 w:1) - /// Proof Skipped: Dmp DeliveryFeeFactor (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpChannelDigests (r:1 w:1) - /// Proof Skipped: Hrmp HrmpChannelDigests (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras FutureCodeUpgrades (r:1 w:0) - /// Proof Skipped: Paras FutureCodeUpgrades (max_values: None, max_size: None, mode: Measured) - /// Storage: ParasDisputes Disputes (r:1 w:0) - /// Proof Skipped: ParasDisputes Disputes (max_values: None, max_size: None, mode: Measured) - /// Storage: ParaScheduler SessionStartBlock (r:1 w:0) - /// Proof Skipped: ParaScheduler SessionStartBlock (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler ParathreadQueue (r:1 w:1) - /// Proof Skipped: ParaScheduler ParathreadQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler Scheduled (r:1 w:1) - /// Proof Skipped: ParaScheduler Scheduled (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParaScheduler ValidatorGroups (r:1 w:0) - /// Proof Skipped: ParaScheduler ValidatorGroups (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Paras CurrentCodeHash (r:1 w:0) - /// Proof Skipped: Paras CurrentCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras FutureCodeHash (r:1 w:0) - /// Proof Skipped: Paras FutureCodeHash (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeRestrictionSignal (r:1 w:0) - /// Proof Skipped: Paras UpgradeRestrictionSignal (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras ParaLifecycles (r:1 w:0) - /// Proof Skipped: Paras ParaLifecycles (max_values: None, max_size: None, mode: Measured) - /// Storage: MessageQueue BookStateFor (r:1 w:0) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(55), added: 2530, mode: MaxEncodedLen) - /// Storage: ParasDisputes Included (r:0 w:1) - /// Proof Skipped: ParasDisputes Included (max_values: None, max_size: None, mode: Measured) - /// Storage: Hrmp HrmpWatermarks (r:0 w:1) - /// Proof Skipped: Hrmp HrmpWatermarks (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras Heads (r:0 w:1) - /// Proof Skipped: Paras Heads (max_values: None, max_size: None, mode: Measured) - /// Storage: Paras UpgradeGoAheadSignal (r:0 w:1) - /// Proof Skipped: Paras UpgradeGoAheadSignal (max_values: None, max_size: None, mode: Measured) + /// Storage: `ParaInherent::Included` (r:1 w:1) + /// Proof: `ParaInherent::Included` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `System::ParentHash` (r:1 w:0) + /// Proof: `System::ParentHash` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::AllowedRelayParents` (r:1 w:1) + /// Proof: `ParasShared::AllowedRelayParents` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::CurrentSessionIndex` (r:1 w:0) + /// Proof: `ParasShared::CurrentSessionIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::AvailabilityCores` (r:1 w:1) + /// Proof: `ParaScheduler::AvailabilityCores` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasShared::ActiveValidatorKeys` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorKeys` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Babe::AuthorVrfRandomness` (r:1 w:0) + /// Proof: `Babe::AuthorVrfRandomness` (`max_values`: Some(1), `max_size`: Some(33), added: 528, mode: `MaxEncodedLen`) + /// Storage: `ParaInherent::OnChainVotes` (r:1 w:1) + /// Proof: `ParaInherent::OnChainVotes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Frozen` (r:1 w:0) + /// Proof: `ParasDisputes::Frozen` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaInclusion::V1` (r:2 w:1) + /// Proof: `ParaInclusion::V1` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaSessionInfo::AccountKeys` (r:1 w:0) + /// Proof: `ParaSessionInfo::AccountKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::Validators` (r:1 w:0) + /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Staking::ActiveEra` (r:1 w:0) + /// Proof: `Staking::ActiveEra` (`max_values`: Some(1), `max_size`: Some(13), added: 508, mode: `MaxEncodedLen`) + /// Storage: `Staking::ErasRewardPoints` (r:1 w:1) + /// Proof: `Staking::ErasRewardPoints` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:1) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpChannelDigests` (r:1 w:1) + /// Proof: `Hrmp::HrmpChannelDigests` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeUpgrades` (r:1 w:0) + /// Proof: `Paras::FutureCodeUpgrades` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Disputes` (r:1 w:0) + /// Proof: `ParasDisputes::Disputes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::SessionStartBlock` (r:1 w:0) + /// Proof: `ParaScheduler::SessionStartBlock` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ValidatorGroups` (r:1 w:0) + /// Proof: `ParaScheduler::ValidatorGroups` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParaScheduler::ClaimQueue` (r:1 w:1) + /// Proof: `ParaScheduler::ClaimQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `CoretimeAssignmentProvider::CoreDescriptors` (r:1 w:1) + /// Proof: `CoretimeAssignmentProvider::CoreDescriptors` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::CurrentCodeHash` (r:1 w:0) + /// Proof: `Paras::CurrentCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::FutureCodeHash` (r:1 w:0) + /// Proof: `Paras::FutureCodeHash` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeRestrictionSignal` (r:1 w:0) + /// Proof: `Paras::UpgradeRestrictionSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::ParaLifecycles` (r:1 w:0) + /// Proof: `Paras::ParaLifecycles` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:0) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(55), added: 2530, mode: `MaxEncodedLen`) + /// Storage: `ParasShared::ActiveValidatorIndices` (r:1 w:0) + /// Proof: `ParasShared::ActiveValidatorIndices` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Session::DisabledValidators` (r:1 w:0) + /// Proof: `Session::DisabledValidators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParasDisputes::Included` (r:0 w:1) + /// Proof: `ParasDisputes::Included` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Hrmp::HrmpWatermarks` (r:0 w:1) + /// Proof: `Hrmp::HrmpWatermarks` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::Heads` (r:0 w:1) + /// Proof: `Paras::Heads` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::UpgradeGoAheadSignal` (r:0 w:1) + /// Proof: `Paras::UpgradeGoAheadSignal` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Paras::MostRecentContext` (r:0 w:1) + /// Proof: `Paras::MostRecentContext` (`max_values`: None, `max_size`: None, mode: `Measured`) fn enter_backed_candidate_code_upgrade() -> Weight { // Proof Size summary in bytes: - // Measured: `42414` - // Estimated: `48354` - // Minimum execution time: 43_320_529_000 picoseconds. - Weight::from_parts(45_622_613_000, 0) - .saturating_add(Weight::from_parts(0, 48354)) - .saturating_add(T::DbWeight::get().reads(30)) - .saturating_add(T::DbWeight::get().writes(15)) + // Measured: `43282` + // Estimated: `49222` + // Minimum execution time: 42_128_606_000 picoseconds. + Weight::from_parts(42_822_806_000, 0) + .saturating_add(Weight::from_parts(0, 49222)) + .saturating_add(T::DbWeight::get().reads(31)) + .saturating_add(T::DbWeight::get().writes(16)) } } diff --git a/prdoc/pr_3479.prdoc b/prdoc/pr_3479.prdoc new file mode 100644 index 00000000000..1e44ce5646b --- /dev/null +++ b/prdoc/pr_3479.prdoc @@ -0,0 +1,8 @@ +title: "Elastic scaling: runtime dependency tracking and enactment" + +doc: + - audience: Node Dev + description: | + Adds support in the inclusion and paras_inherent runtime modules for backing and including multiple candidates of the same para if they form a chain. + +crates: [ ] -- GitLab From 64a707a4824ad12eb9ab715966dbd0d2b0efaf01 Mon Sep 17 00:00:00 2001 From: ordian Date: Thu, 21 Mar 2024 12:22:16 +0100 Subject: [PATCH 157/188] approval-voting: remove some inefficiences on startup (#3747) Small refactoring to reduce the algorithmic complexity of the initial message distribution in approval voting after a sync from O(n_candidates ^ 2) to O(n_candidates). --- polkadot/node/core/approval-voting/src/lib.rs | 274 +++++++++--------- 1 file changed, 129 insertions(+), 145 deletions(-) diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index 8cc16a6e1ec..1d7ab3eee21 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -55,9 +55,9 @@ use polkadot_node_subsystem_util::{ }; use polkadot_primitives::{ vstaging::{ApprovalVoteMultipleCandidates, ApprovalVotingParams}, - BlockNumber, CandidateHash, CandidateIndex, CandidateReceipt, DisputeStatement, ExecutorParams, - GroupIndex, Hash, PvfExecKind, SessionIndex, SessionInfo, ValidDisputeStatementKind, - ValidatorId, ValidatorIndex, ValidatorPair, ValidatorSignature, + BlockNumber, CandidateHash, CandidateIndex, CandidateReceipt, CoreIndex, DisputeStatement, + ExecutorParams, GroupIndex, Hash, PvfExecKind, SessionIndex, SessionInfo, + ValidDisputeStatementKind, ValidatorId, ValidatorIndex, ValidatorPair, ValidatorSignature, }; use sc_keystore::LocalKeystore; use sp_application_crypto::Pair; @@ -1285,10 +1285,10 @@ fn cores_to_candidate_indices( // Map from core index to candidate index. for claimed_core_index in core_indices.iter_ones() { - if let Some(candidate_index) = block_entry + // Candidates are sorted by core index. + if let Ok(candidate_index) = block_entry .candidates() - .iter() - .position(|(core_index, _)| core_index.0 == claimed_core_index as u32) + .binary_search_by_key(&(claimed_core_index as u32), |(core_index, _)| core_index.0) { candidate_indices.push(candidate_index as _); } @@ -1297,6 +1297,21 @@ fn cores_to_candidate_indices( CandidateBitfield::try_from(candidate_indices) } +// Returns the claimed core bitfield from the assignment cert and the core index +// from the block entry. +fn get_core_indices_on_startup( + assignment: &AssignmentCertKindV2, + block_entry_core_index: CoreIndex, +) -> CoreBitfield { + match &assignment { + AssignmentCertKindV2::RelayVRFModuloCompact { core_bitfield } => core_bitfield.clone(), + AssignmentCertKindV2::RelayVRFModulo { sample: _ } => + CoreBitfield::try_from(vec![block_entry_core_index]).expect("Not an empty vec; qed"), + AssignmentCertKindV2::RelayVRFDelay { core_index } => + CoreBitfield::try_from(vec![*core_index]).expect("Not an empty vec; qed"), + } +} + // Returns the claimed core bitfield from the assignment cert, the candidate hash and a // `BlockEntry`. Can fail only for VRF Delay assignments for which we cannot find the candidate hash // in the block entry which indicates a bug or corrupted storage. @@ -1367,7 +1382,7 @@ async fn distribution_messages_for_activation( session: block_entry.session(), }); let mut signatures_queued = HashSet::new(); - for (_, candidate_hash) in block_entry.candidates() { + for (core_index, candidate_hash) in block_entry.candidates() { let _candidate_span = distribution_message_span.child("candidate").with_candidate(*candidate_hash); let candidate_entry = match db.load_candidate_entry(&candidate_hash)? { @@ -1389,152 +1404,121 @@ async fn distribution_messages_for_activation( match approval_entry.local_statements() { (None, None) | (None, Some(_)) => {}, // second is impossible case. (Some(assignment), None) => { - if let Some(claimed_core_indices) = get_assignment_core_indices( - &assignment.cert().kind, - &candidate_hash, - &block_entry, - ) { - if block_entry.has_candidates_pending_signature() { - delayed_approvals_timers.maybe_arm_timer( - state.clock.tick_now(), - state.clock.as_ref(), - block_entry.block_hash(), - assignment.validator_index(), - ) - } + let claimed_core_indices = + get_core_indices_on_startup(&assignment.cert().kind, *core_index); + + if block_entry.has_candidates_pending_signature() { + delayed_approvals_timers.maybe_arm_timer( + state.clock.tick_now(), + state.clock.as_ref(), + block_entry.block_hash(), + assignment.validator_index(), + ) + } - match cores_to_candidate_indices( - &claimed_core_indices, - &block_entry, - ) { - Ok(bitfield) => { - gum::debug!( - target: LOG_TARGET, - candidate_hash = ?candidate_entry.candidate_receipt().hash(), - ?block_hash, - "Discovered, triggered assignment, not approved yet", - ); - - let indirect_cert = IndirectAssignmentCertV2 { - block_hash, - validator: assignment.validator_index(), - cert: assignment.cert().clone(), - }; - messages.push( - ApprovalDistributionMessage::DistributeAssignment( - indirect_cert.clone(), - bitfield.clone(), - ), - ); - - if !block_entry - .candidate_is_pending_signature(*candidate_hash) - { - let ExtendedSessionInfo { ref executor_params, .. } = - match get_extended_session_info( - session_info_provider, - ctx.sender(), - block_entry.block_hash(), - block_entry.session(), - ) - .await - { - Some(i) => i, - None => continue, - }; - - actions.push(Action::LaunchApproval { - claimed_candidate_indices: bitfield, - candidate_hash: candidate_entry - .candidate_receipt() - .hash(), - indirect_cert, - assignment_tranche: assignment.tranche(), - relay_block_hash: block_hash, - session: block_entry.session(), - executor_params: executor_params.clone(), - candidate: candidate_entry - .candidate_receipt() - .clone(), - backing_group: approval_entry.backing_group(), - distribute_assignment: false, - }); - } - }, - Err(err) => { - // Should never happen. If we fail here it means the - // assignment is null (no cores claimed). - gum::warn!( - target: LOG_TARGET, - ?block_hash, - ?candidate_hash, - ?err, - "Failed to create assignment bitfield", - ); - }, - } - } else { - gum::warn!( - target: LOG_TARGET, - ?block_hash, - ?candidate_hash, - "Cannot get assignment claimed core indices", - ); + match cores_to_candidate_indices(&claimed_core_indices, &block_entry) { + Ok(bitfield) => { + gum::debug!( + target: LOG_TARGET, + candidate_hash = ?candidate_entry.candidate_receipt().hash(), + ?block_hash, + "Discovered, triggered assignment, not approved yet", + ); + + let indirect_cert = IndirectAssignmentCertV2 { + block_hash, + validator: assignment.validator_index(), + cert: assignment.cert().clone(), + }; + messages.push( + ApprovalDistributionMessage::DistributeAssignment( + indirect_cert.clone(), + bitfield.clone(), + ), + ); + + if !block_entry.candidate_is_pending_signature(*candidate_hash) + { + let ExtendedSessionInfo { ref executor_params, .. } = + match get_extended_session_info( + session_info_provider, + ctx.sender(), + block_entry.block_hash(), + block_entry.session(), + ) + .await + { + Some(i) => i, + None => continue, + }; + + actions.push(Action::LaunchApproval { + claimed_candidate_indices: bitfield, + candidate_hash: candidate_entry + .candidate_receipt() + .hash(), + indirect_cert, + assignment_tranche: assignment.tranche(), + relay_block_hash: block_hash, + session: block_entry.session(), + executor_params: executor_params.clone(), + candidate: candidate_entry.candidate_receipt().clone(), + backing_group: approval_entry.backing_group(), + distribute_assignment: false, + }); + } + }, + Err(err) => { + // Should never happen. If we fail here it means the + // assignment is null (no cores claimed). + gum::warn!( + target: LOG_TARGET, + ?block_hash, + ?candidate_hash, + ?err, + "Failed to create assignment bitfield", + ); + }, } }, (Some(assignment), Some(approval_sig)) => { - if let Some(claimed_core_indices) = get_assignment_core_indices( - &assignment.cert().kind, - &candidate_hash, - &block_entry, - ) { - match cores_to_candidate_indices( - &claimed_core_indices, - &block_entry, - ) { - Ok(bitfield) => messages.push( - ApprovalDistributionMessage::DistributeAssignment( - IndirectAssignmentCertV2 { - block_hash, - validator: assignment.validator_index(), - cert: assignment.cert().clone(), - }, - bitfield, - ), - ), - Err(err) => { - gum::warn!( - target: LOG_TARGET, - ?block_hash, - ?candidate_hash, - ?err, - "Failed to create assignment bitfield", - ); - // If we didn't send assignment, we don't send approval. - continue - }, - } - if signatures_queued - .insert(approval_sig.signed_candidates_indices.clone()) - { - messages.push(ApprovalDistributionMessage::DistributeApproval( - IndirectSignedApprovalVoteV2 { + let claimed_core_indices = + get_core_indices_on_startup(&assignment.cert().kind, *core_index); + match cores_to_candidate_indices(&claimed_core_indices, &block_entry) { + Ok(bitfield) => messages.push( + ApprovalDistributionMessage::DistributeAssignment( + IndirectAssignmentCertV2 { block_hash, - candidate_indices: approval_sig - .signed_candidates_indices, validator: assignment.validator_index(), - signature: approval_sig.signature, + cert: assignment.cert().clone(), }, - )) - }; - } else { - gum::warn!( - target: LOG_TARGET, - ?block_hash, - ?candidate_hash, - "Cannot get assignment claimed core indices", - ); + bitfield, + ), + ), + Err(err) => { + gum::warn!( + target: LOG_TARGET, + ?block_hash, + ?candidate_hash, + ?err, + "Failed to create assignment bitfield", + ); + // If we didn't send assignment, we don't send approval. + continue + }, } + if signatures_queued + .insert(approval_sig.signed_candidates_indices.clone()) + { + messages.push(ApprovalDistributionMessage::DistributeApproval( + IndirectSignedApprovalVoteV2 { + block_hash, + candidate_indices: approval_sig.signed_candidates_indices, + validator: assignment.validator_index(), + signature: approval_sig.signature, + }, + )) + }; }, } }, -- GitLab From 9922fd39437cea5797564145bfd1adb989fd57d1 Mon Sep 17 00:00:00 2001 From: kvalerio <24193167+kevin-valerio@users.noreply.github.com> Date: Thu, 21 Mar 2024 13:18:41 +0100 Subject: [PATCH 158/188] there's a typo (#3779) There was a typo, so now, there's no more typo. Co-authored-by: Liam Aharon --- substrate/primitives/runtime/src/multiaddress.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/primitives/runtime/src/multiaddress.rs b/substrate/primitives/runtime/src/multiaddress.rs index 89b0a3bcf8c..c435606312e 100644 --- a/substrate/primitives/runtime/src/multiaddress.rs +++ b/substrate/primitives/runtime/src/multiaddress.rs @@ -32,7 +32,7 @@ pub enum MultiAddress { Raw(Vec), /// It's a 32 byte representation. Address32([u8; 32]), - /// Its a 20 byte representation. + /// It's a 20 byte representation. Address20([u8; 20]), } -- GitLab From 46ba85500ffc77fa8e267c5f38b2c213550d68fa Mon Sep 17 00:00:00 2001 From: Tsvetomir Dimitrov Date: Thu, 21 Mar 2024 14:46:55 +0200 Subject: [PATCH 159/188] Fix toml formatting (#3782) Make taplo happy --- substrate/primitives/arithmetic/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/primitives/arithmetic/Cargo.toml b/substrate/primitives/arithmetic/Cargo.toml index 64c1025b585..120edd06a66 100644 --- a/substrate/primitives/arithmetic/Cargo.toml +++ b/substrate/primitives/arithmetic/Cargo.toml @@ -43,7 +43,7 @@ std = [ "scale-info/std", "serde/std", "sp-crypto-hashing/std", - "sp-std/std", + "sp-std/std", ] # Serde support without relying on std features. serde = ["dep:serde", "scale-info/serde"] -- GitLab From 01d65f6b995021bfe7be184581895dc374285f06 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Thu, 21 Mar 2024 17:49:23 +0100 Subject: [PATCH 160/188] Revert `SendXcmOrigin` in Rococo & Westend (#2571) Based on issue [#2512](https://github.com/paritytech/polkadot-sdk/issues/2512), it seems that some ecosystem teams are using these networks to set up their staging environments and test certain use cases, some of them involving sending XCMs from the relay with origins not allowed in the current configuration. This change reverts the configuration of `SendXcmOrigin`. --------- Co-authored-by: Adrian Catangiu --- polkadot/runtime/rococo/src/xcm_config.rs | 8 +++----- polkadot/runtime/westend/src/xcm_config.rs | 4 +++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index 328879715de..c7063bd7ad6 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -259,11 +259,9 @@ pub type LocalPalletOriginToLocation = ( impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; - // We only allow the root, fellows and the staking admin to send messages. - // This is basically safe to enable for everyone (safe the possibility of someone spamming the - // parachain if they're willing to pay the KSM to send from the Relay-chain), but it's useless - // until we bring in XCM v3 which will make `DescendOrigin` a bit more useful. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + // Note that this configuration of `SendXcmOrigin` is different from the one present in + // production. + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally. type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 73127cb1efd..400843c5835 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -272,7 +272,9 @@ pub type LocalPalletOriginToLocation = ( impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + // Note that this configuration of `SendXcmOrigin` is different from the one present in + // production. + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally... type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; -- GitLab From ea5f4e9a4d78234eb68bbb9130a24b0598c7893a Mon Sep 17 00:00:00 2001 From: "Will | Paradox | ParaNodes.io" <79228812+paradox-tt@users.noreply.github.com> Date: Fri, 22 Mar 2024 00:07:24 +0000 Subject: [PATCH 161/188] Adding LF's bootnodes to relay and system chains (#3514) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Good day, I'm seeking to add the following bootnodes for Kusama and Polkadot's relay and system chains. The following commands can be used to test connectivity. All node keys are backed up. Polkadot: ``` polkadot --chain polkadot --base-path /tmp/node --name "Boot" --reserved-only --reserved-nodes "/dns/boot-polkadot.luckyfriday.io/tcp/443/wss/p2p/12D3KooWAdyiVAaeGdtBt6vn5zVetwA4z4qfm9Fi2QCSykN1wTBJ" --no-hardware-benchmarks ``` Assethub-Polkadot: ``` polkadot-parachain --chain asset-hub-polkadot --base-path /tmp/node --name "Boot" --reserved-only --reserved-nodes "/dns/boot-polkadot-assethub.luckyfriday.io/tcp/443/wss/p2p/12D3KooWDR9M7CjV1xdjCRbRwkFn1E7sjMaL4oYxGyDWxuLrFc2J" --no-hardware-benchmarks ``` Bridgehub-Polkadot: ``` polkadot-parachain --chain bridge-hub-polkadot --base-path /tmp/node --name "Boot" --reserved-only --reserved-nodes "/dns/boot-polkadot-bridgehub.luckyfriday.io/tcp/443/wss/p2p/12D3KooWKf3mBXHjLbwtPqv1BdbQuwbFNcQQYxASS7iQ25264AXH" --no-hardware-benchmarks ``` Collectives-Polkadot ``` polkadot-parachain --chain collectives-polkadot --base-path /tmp/node --name "Boot" --reserved-only --reserved-nodes "/dns/boot-polkadot-collectives.luckyfriday.io/tcp/443/wss/p2p/12D3KooWCzifnPooTt4kvTnXT7FTKTymVL7xn7DURQLsS2AKpf6w" --no-hardware-benchmarks ``` Kusama: ``` polkadot --chain kusama --base-path /tmp/node --name "Boot" --reserved-only --reserved-nodes "/dns/boot-kusama.luckyfriday.io/tcp/443/wss/p2p/12D3KooWS1Lu6DmK8YHSvkErpxpcXmk14vG6y4KVEFEkd9g62PP8" --no-hardware-benchmarks ``` Assethub-Kusama: ``` polkadot-parachain --chain asset-hub-kusama --base-path /tmp/node --name "Boot" --reserved-only --reserved-nodes "/dns/boot-kusama-assethub.luckyfriday.io/tcp/443/wss/p2p/12D3KooWSwaeFs6FNgpgh54fdoxSDAA4nJNaPE3PAcse2GRrG7b3" --no-hardware-benchmarks ``` Bridgehub-Kusama: ``` polkadot-parachain --chain bridge-hub-kusama --base-path /tmp/node --name "Boot" --reserved-only --reserved-nodes "/dns/boot-kusama-bridgehub.luckyfriday.io/tcp/443/wss/p2p/12D3KooWQybw6AFmAvrFfwUQnNxUpS12RovapD6oorh2mAJr4xyd" --no-hardware-benchmarks ``` Co-authored-by: Bastian Köcher --- cumulus/parachains/chain-specs/asset-hub-kusama.json | 3 ++- cumulus/parachains/chain-specs/asset-hub-polkadot.json | 3 ++- cumulus/parachains/chain-specs/bridge-hub-kusama.json | 3 ++- cumulus/parachains/chain-specs/bridge-hub-polkadot.json | 3 ++- cumulus/parachains/chain-specs/collectives-polkadot.json | 3 ++- polkadot/node/service/chain-specs/kusama.json | 1 + polkadot/node/service/chain-specs/polkadot.json | 3 ++- 7 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cumulus/parachains/chain-specs/asset-hub-kusama.json b/cumulus/parachains/chain-specs/asset-hub-kusama.json index 654275eade8..66a705a4086 100644 --- a/cumulus/parachains/chain-specs/asset-hub-kusama.json +++ b/cumulus/parachains/chain-specs/asset-hub-kusama.json @@ -27,7 +27,8 @@ "/dns/mine14.rotko.net/tcp/34524/ws/p2p/12D3KooWJUFnjR2PNbsJhudwPVaWCoZy1acPGKjM2cSuGj345BBu", "/dns/mine14.rotko.net/tcp/35524/wss/p2p/12D3KooWJUFnjR2PNbsJhudwPVaWCoZy1acPGKjM2cSuGj345BBu", "/dns/asset-hub-kusama.bootnodes.polkadotters.com/tcp/30511/p2p/12D3KooWDpk7wVH7RgjErEvbvAZ2kY5VeaAwRJP5ojmn1e8b8UbU", - "/dns/asset-hub-kusama.bootnodes.polkadotters.com/tcp/30513/wss/p2p/12D3KooWDpk7wVH7RgjErEvbvAZ2kY5VeaAwRJP5ojmn1e8b8UbU" + "/dns/asset-hub-kusama.bootnodes.polkadotters.com/tcp/30513/wss/p2p/12D3KooWDpk7wVH7RgjErEvbvAZ2kY5VeaAwRJP5ojmn1e8b8UbU", + "/dns/boot-kusama-assethub.luckyfriday.io/tcp/443/wss/p2p/12D3KooWSwaeFs6FNgpgh54fdoxSDAA4nJNaPE3PAcse2GRrG7b3" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/asset-hub-polkadot.json b/cumulus/parachains/chain-specs/asset-hub-polkadot.json index 454060d2a87..16caa52ba91 100644 --- a/cumulus/parachains/chain-specs/asset-hub-polkadot.json +++ b/cumulus/parachains/chain-specs/asset-hub-polkadot.json @@ -27,7 +27,8 @@ "/dns/mint14.rotko.net/tcp/34514/ws/p2p/12D3KooWKkzLjYF6M5eEs7nYiqEtRqY8SGVouoCwo3nCWsRnThDW", "/dns/mint14.rotko.net/tcp/35514/wss/p2p/12D3KooWKkzLjYF6M5eEs7nYiqEtRqY8SGVouoCwo3nCWsRnThDW", "/dns/asset-hub-polkadot.bootnodes.polkadotters.com/tcp/30508/p2p/12D3KooWKbfY9a9oywxMJKiALmt7yhrdQkjXMtvxhhDDN23vG93R", - "/dns/asset-hub-polkadot.bootnodes.polkadotters.com/tcp/30510/wss/p2p/12D3KooWKbfY9a9oywxMJKiALmt7yhrdQkjXMtvxhhDDN23vG93R" + "/dns/asset-hub-polkadot.bootnodes.polkadotters.com/tcp/30510/wss/p2p/12D3KooWKbfY9a9oywxMJKiALmt7yhrdQkjXMtvxhhDDN23vG93R", + "/dns/boot-polkadot-assethub.luckyfriday.io/tcp/443/wss/p2p/12D3KooWDR9M7CjV1xdjCRbRwkFn1E7sjMaL4oYxGyDWxuLrFc2J" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/bridge-hub-kusama.json b/cumulus/parachains/chain-specs/bridge-hub-kusama.json index 90b70b05016..6644ea41ab7 100644 --- a/cumulus/parachains/chain-specs/bridge-hub-kusama.json +++ b/cumulus/parachains/chain-specs/bridge-hub-kusama.json @@ -27,7 +27,8 @@ "/dns/kbr13.rotko.net/tcp/34553/ws/p2p/12D3KooWAmBp54mUEYtvsk2kxNEsDbAvdUMcaghxKXgUQxmPEQ66", "/dns/kbr13.rotko.net/tcp/35553/wss/p2p/12D3KooWAmBp54mUEYtvsk2kxNEsDbAvdUMcaghxKXgUQxmPEQ66", "/dns/bridge-hub-kusama.bootnodes.polkadotters.com/tcp/30520/p2p/12D3KooWH3pucezRRS5esoYyzZsUkKWcPSByQxEvmM819QL1HPLV", - "/dns/bridge-hub-kusama.bootnodes.polkadotters.com/tcp/30522/wss/p2p/12D3KooWH3pucezRRS5esoYyzZsUkKWcPSByQxEvmM819QL1HPLV" + "/dns/bridge-hub-kusama.bootnodes.polkadotters.com/tcp/30522/wss/p2p/12D3KooWH3pucezRRS5esoYyzZsUkKWcPSByQxEvmM819QL1HPLV", + "/dns/boot-kusama-bridgehub.luckyfriday.io/tcp/443/wss/p2p/12D3KooWQybw6AFmAvrFfwUQnNxUpS12RovapD6oorh2mAJr4xyd" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/bridge-hub-polkadot.json b/cumulus/parachains/chain-specs/bridge-hub-polkadot.json index a9444b89e1e..c51c5eff89b 100644 --- a/cumulus/parachains/chain-specs/bridge-hub-polkadot.json +++ b/cumulus/parachains/chain-specs/bridge-hub-polkadot.json @@ -23,7 +23,8 @@ "/dns/pbr13.rotko.net/tcp/34543/ws/p2p/12D3KooWMxZY7tDc2Rh454VaJJ7RexKAXVS6xSBEvTnXSGCnuGDw", "/dns/pbr13.rotko.net/tcp/35543/wss/p2p/12D3KooWMxZY7tDc2Rh454VaJJ7RexKAXVS6xSBEvTnXSGCnuGDw", "/dns/bridge-hub-polkadot.bootnodes.polkadotters.com/tcp/30517/p2p/12D3KooWLUNE3LHPDa1WrrZaYT7ArK66CLM1bPv7kKz74UcLnQRB", - "/dns/bridge-hub-polkadot.bootnodes.polkadotters.com/tcp/30519/wss/p2p/12D3KooWLUNE3LHPDa1WrrZaYT7ArK66CLM1bPv7kKz74UcLnQRB" + "/dns/bridge-hub-polkadot.bootnodes.polkadotters.com/tcp/30519/wss/p2p/12D3KooWLUNE3LHPDa1WrrZaYT7ArK66CLM1bPv7kKz74UcLnQRB", + "/dns/boot-polkadot-bridgehub.luckyfriday.io/tcp/443/wss/p2p/12D3KooWKf3mBXHjLbwtPqv1BdbQuwbFNcQQYxASS7iQ25264AXH" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/cumulus/parachains/chain-specs/collectives-polkadot.json b/cumulus/parachains/chain-specs/collectives-polkadot.json index 259669cf37a..ce80e21ae62 100644 --- a/cumulus/parachains/chain-specs/collectives-polkadot.json +++ b/cumulus/parachains/chain-specs/collectives-polkadot.json @@ -27,7 +27,8 @@ "/dns/pch13.rotko.net/tcp/34573/ws/p2p/12D3KooWRXudHoazPZ9osMfdY38e8CBxQLD4RhrVeHpRSNNpcDtH", "/dns/pch13.rotko.net/tcp/35573/wss/p2p/12D3KooWRXudHoazPZ9osMfdY38e8CBxQLD4RhrVeHpRSNNpcDtH", "/dns/collectives-polkadot.bootnodes.polkadotters.com/tcp/30526/p2p/12D3KooWNohUjvJtGKUa8Vhy8C1ZBB5N8JATB6e7rdLVCioeb3ff", - "/dns/collectives-polkadot.bootnodes.polkadotters.com/tcp/30528/wss/p2p/12D3KooWNohUjvJtGKUa8Vhy8C1ZBB5N8JATB6e7rdLVCioeb3ff" + "/dns/collectives-polkadot.bootnodes.polkadotters.com/tcp/30528/wss/p2p/12D3KooWNohUjvJtGKUa8Vhy8C1ZBB5N8JATB6e7rdLVCioeb3ff", + "/dns/boot-polkadot-collectives.luckyfriday.io/tcp/443/wss/p2p/12D3KooWCzifnPooTt4kvTnXT7FTKTymVL7xn7DURQLsS2AKpf6w" ], "telemetryEndpoints": null, "protocolId": null, diff --git a/polkadot/node/service/chain-specs/kusama.json b/polkadot/node/service/chain-specs/kusama.json index fd60cb8b6c1..490b39ee696 100644 --- a/polkadot/node/service/chain-specs/kusama.json +++ b/polkadot/node/service/chain-specs/kusama.json @@ -35,6 +35,7 @@ "/dns/ksm14.rotko.net/tcp/35224/wss/p2p/12D3KooWAa5THTw8HPfnhEei23HdL8P9McBXdozG2oTtMMksjZkK", "/dns/ksm14.rotko.net/tcp/33224/p2p/12D3KooWAa5THTw8HPfnhEei23HdL8P9McBXdozG2oTtMMksjZkK", "/dns/ibp-boot-kusama.luckyfriday.io/tcp/30333/p2p/12D3KooW9vu1GWHBuxyhm7rZgD3fhGZpNajPXFexadvhujWMgwfT", + "/dns/boot-kusama.luckyfriday.io/tcp/443/wss/p2p/12D3KooWS1Lu6DmK8YHSvkErpxpcXmk14vG6y4KVEFEkd9g62PP8", "/dns/ibp-boot-kusama.luckyfriday.io/tcp/30334/wss/p2p/12D3KooW9vu1GWHBuxyhm7rZgD3fhGZpNajPXFexadvhujWMgwfT" ], "telemetryEndpoints": [ diff --git a/polkadot/node/service/chain-specs/polkadot.json b/polkadot/node/service/chain-specs/polkadot.json index c235cdd09d8..5f8d88102d7 100644 --- a/polkadot/node/service/chain-specs/polkadot.json +++ b/polkadot/node/service/chain-specs/polkadot.json @@ -36,7 +36,8 @@ "/dns/dot14.rotko.net/tcp/35214/wss/p2p/12D3KooWPyEvPEXghnMC67Gff6PuZiSvfx3fmziKiPZcGStZ5xff", "/dns/dot14.rotko.net/tcp/33214/p2p/12D3KooWPyEvPEXghnMC67Gff6PuZiSvfx3fmziKiPZcGStZ5xff", "/dns/ibp-boot-polkadot.luckyfriday.io/tcp/30333/p2p/12D3KooWEjk6QXrZJ26fLpaajisJGHiz6WiQsR8k7mkM9GmWKnRZ", - "/dns/ibp-boot-polkadot.luckyfriday.io/tcp/30334/wss/p2p/12D3KooWEjk6QXrZJ26fLpaajisJGHiz6WiQsR8k7mkM9GmWKnRZ" + "/dns/ibp-boot-polkadot.luckyfriday.io/tcp/30334/wss/p2p/12D3KooWEjk6QXrZJ26fLpaajisJGHiz6WiQsR8k7mkM9GmWKnRZ", + "/dns/boot-polkadot.luckyfriday.io/tcp/443/wss/p2p/12D3KooWAdyiVAaeGdtBt6vn5zVetwA4z4qfm9Fi2QCSykN1wTBJ" ], "telemetryEndpoints": [ [ -- GitLab From 3410dfb3929462da88be2da813f121d8b1cf46b3 Mon Sep 17 00:00:00 2001 From: Clara van Staden Date: Fri, 22 Mar 2024 11:25:28 +0200 Subject: [PATCH 162/188] Snowbridge Beacon header age check (#3727) ## Bug Explanation Adds a check that prevents finalized headers with a gap larger than the sync committee period being imported, which could cause execution headers in the gap being unprovable. The current version of the Ethereum client checks that there is a header at least every sync committee, but it doesn't check that the headers are within a sync period of each other. For example: Header 100 (sync committee period 1) Header 9000 (sync committee period 2) (8900 blocks apart) These headers are in adjacent sync committees, but more than the sync committee period (8192 blocks) apart. The reason we need a header every 8192 slots at least, is the header is used to prove messages within the last 8192 blocks. If we import header 9000, and we receive a message to be verified at header 200, the `block_roots` field of header 9000 won't contain the header in order to do the ancestry check. ## Environment While running in Rococo, this edge case was discovered after the relayer was offline for a few days. It is unlikely, but not impossible, to happen again and so it should be backported to polkadot-sdk 1.7.0 (so that [polkadot-fellows/runtimes](https://github.com/polkadot-fellows/runtimes) can be updated with the fix). Our Ethereum client has been operational on Rococo for the past few months, and this been the only major issue discovered so far. ### Unrelated Change An unrelated nit: Removes a left over file that should have been deleted when the `parachain` directory was removed. --------- Co-authored-by: claravanstaden --- .../pallets/ethereum-client/src/lib.rs | 15 + .../pallets/ethereum-client/src/tests.rs | 57 +++- .../ethereum-beacon-client/src/mock.rs | 259 ------------------ 3 files changed, 71 insertions(+), 260 deletions(-) delete mode 100644 bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs diff --git a/bridges/snowbridge/pallets/ethereum-client/src/lib.rs b/bridges/snowbridge/pallets/ethereum-client/src/lib.rs index a54d4a05ac5..fc2ab2fbb58 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/lib.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/lib.rs @@ -130,6 +130,10 @@ pub mod pallet { InvalidExecutionHeaderProof, InvalidAncestryMerkleProof, InvalidBlockRootsRootMerkleProof, + /// The gap between the finalized headers is larger than the sync committee period, + /// rendering execution headers unprovable using ancestry proofs (blocks root size is + /// the same as the sync committee period slots). + InvalidFinalizedHeaderGap, HeaderNotFinalized, BlockBodyHashTreeRootFailed, HeaderHashTreeRootFailed, @@ -398,6 +402,17 @@ pub mod pallet { Error::::IrrelevantUpdate ); + // Verify the finalized header gap between the current finalized header and new imported + // header is not larger than the sync committee period, otherwise we cannot do + // ancestry proofs for execution headers in the gap. + ensure!( + latest_finalized_state + .slot + .saturating_add(config::SLOTS_PER_HISTORICAL_ROOT as u64) >= + update.finalized_header.slot, + Error::::InvalidFinalizedHeaderGap + ); + // Verify that the `finality_branch`, if present, confirms `finalized_header` to match // the finalized checkpoint root saved in the state of `attested_header`. let finalized_block_root: H256 = update diff --git a/bridges/snowbridge/pallets/ethereum-client/src/tests.rs b/bridges/snowbridge/pallets/ethereum-client/src/tests.rs index 50b6a25c342..4a7b7b45886 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/tests.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/tests.rs @@ -15,7 +15,7 @@ use crate::mock::{ pub use crate::mock::*; -use crate::config::{EPOCHS_PER_SYNC_COMMITTEE_PERIOD, SLOTS_PER_EPOCH}; +use crate::config::{EPOCHS_PER_SYNC_COMMITTEE_PERIOD, SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT}; use frame_support::{assert_err, assert_noop, assert_ok}; use hex_literal::hex; use primitives::{ @@ -884,6 +884,61 @@ fn submit_execution_header_not_finalized() { }); } +/// Check that a gap of more than 8192 slots between finalized headers is not allowed. +#[test] +fn submit_finalized_header_update_with_too_large_gap() { + let checkpoint = Box::new(load_checkpoint_update_fixture()); + let update = Box::new(load_sync_committee_update_fixture()); + let mut next_update = Box::new(load_next_sync_committee_update_fixture()); + + // Adds 8193 slots, so that the next update is still in the next sync committee, but the + // gap between the finalized headers is more than 8192 slots. + let slot_with_large_gap = checkpoint.header.slot + SLOTS_PER_HISTORICAL_ROOT as u64 + 1; + + next_update.finalized_header.slot = slot_with_large_gap; + // Adding some slots to the attested header and signature slot since they need to be ahead + // of the finalized header. + next_update.attested_header.slot = slot_with_large_gap + 33; + next_update.signature_slot = slot_with_large_gap + 43; + + new_tester().execute_with(|| { + assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); + assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), update.clone())); + assert!(>::exists()); + assert_err!( + EthereumBeaconClient::submit(RuntimeOrigin::signed(1), next_update.clone()), + Error::::InvalidFinalizedHeaderGap + ); + }); +} + +/// Check that a gap of 8192 slots between finalized headers is allowed. +#[test] +fn submit_finalized_header_update_with_gap_at_limit() { + let checkpoint = Box::new(load_checkpoint_update_fixture()); + let update = Box::new(load_sync_committee_update_fixture()); + let mut next_update = Box::new(load_next_sync_committee_update_fixture()); + + next_update.finalized_header.slot = checkpoint.header.slot + SLOTS_PER_HISTORICAL_ROOT as u64; + // Adding some slots to the attested header and signature slot since they need to be ahead + // of the finalized header. + next_update.attested_header.slot = + checkpoint.header.slot + SLOTS_PER_HISTORICAL_ROOT as u64 + 33; + next_update.signature_slot = checkpoint.header.slot + SLOTS_PER_HISTORICAL_ROOT as u64 + 43; + + new_tester().execute_with(|| { + assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); + assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), update.clone())); + assert!(>::exists()); + assert_err!( + EthereumBeaconClient::submit(RuntimeOrigin::signed(1), next_update.clone()), + // The test should pass the InvalidFinalizedHeaderGap check, and will fail at the + // next check, the merkle proof, because we changed the next_update slots. + Error::::InvalidHeaderMerkleProof + ); + }); +} + /* IMPLS */ #[test] diff --git a/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs b/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs deleted file mode 100644 index d2cca373e92..00000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-beacon-client/src/mock.rs +++ /dev/null @@ -1,259 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate as ethereum_beacon_client; -use frame_support::parameter_types; -use pallet_timestamp; -use primitives::{Fork, ForkVersions}; -use sp_core::H256; -use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; - -#[cfg(not(feature = "beacon-spec-mainnet"))] -pub mod minimal { - use super::*; - - use crate::config; - use frame_support::derive_impl; - use hex_literal::hex; - use primitives::CompactExecutionHeader; - use snowbridge_core::inbound::{Log, Proof}; - use sp_runtime::BuildStorage; - use std::{fs::File, path::PathBuf}; - - type Block = frame_system::mocking::MockBlock; - - frame_support::construct_runtime!( - pub enum Test { - System: frame_system::{Pallet, Call, Storage, Event}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - EthereumBeaconClient: ethereum_beacon_client::{Pallet, Call, Storage, Event}, - } - ); - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; - } - - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] - impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeTask = RuntimeTask; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type PalletInfo = PalletInfo; - type SS58Prefix = SS58Prefix; - type Nonce = u64; - type Block = Block; - } - - impl pallet_timestamp::Config for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = (); - type WeightInfo = (); - } - - parameter_types! { - pub const ExecutionHeadersPruneThreshold: u32 = 10; - pub const ChainForkVersions: ForkVersions = ForkVersions{ - genesis: Fork { - version: [0, 0, 0, 1], // 0x00000001 - epoch: 0, - }, - altair: Fork { - version: [1, 0, 0, 1], // 0x01000001 - epoch: 0, - }, - bellatrix: Fork { - version: [2, 0, 0, 1], // 0x02000001 - epoch: 0, - }, - capella: Fork { - version: [3, 0, 0, 1], // 0x03000001 - epoch: 0, - }, - }; - } - - impl ethereum_beacon_client::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ForkVersions = ChainForkVersions; - type MaxExecutionHeadersToKeep = ExecutionHeadersPruneThreshold; - type WeightInfo = (); - } - - // Build genesis storage according to the mock runtime. - pub fn new_tester() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - let mut ext = sp_io::TestExternalities::new(t); - let _ = ext.execute_with(|| Timestamp::set(RuntimeOrigin::signed(1), 30_000)); - ext - } - - fn load_fixture(basename: &str) -> Result - where - T: for<'de> serde::Deserialize<'de>, - { - let filepath: PathBuf = - [env!("CARGO_MANIFEST_DIR"), "tests", "fixtures", basename].iter().collect(); - serde_json::from_reader(File::open(filepath).unwrap()) - } - - pub fn load_execution_header_update_fixture() -> primitives::ExecutionHeaderUpdate { - load_fixture("execution-header-update.minimal.json").unwrap() - } - - pub fn load_checkpoint_update_fixture( - ) -> primitives::CheckpointUpdate<{ config::SYNC_COMMITTEE_SIZE }> { - load_fixture("initial-checkpoint.minimal.json").unwrap() - } - - pub fn load_sync_committee_update_fixture( - ) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { - load_fixture("sync-committee-update.minimal.json").unwrap() - } - - pub fn load_finalized_header_update_fixture( - ) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { - load_fixture("finalized-header-update.minimal.json").unwrap() - } - - pub fn load_next_sync_committee_update_fixture( - ) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { - load_fixture("next-sync-committee-update.minimal.json").unwrap() - } - - pub fn load_next_finalized_header_update_fixture( - ) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { - load_fixture("next-finalized-header-update.minimal.json").unwrap() - } - - pub fn get_message_verification_payload() -> (Log, Proof) { - ( - Log { - address: hex!("ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0").into(), - topics: vec![ - hex!("1b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ad").into(), - hex!("00000000000000000000000000000000000000000000000000000000000003e8").into(), - hex!("0000000000000000000000000000000000000000000000000000000000000001").into(), - ], - data: hex!("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000").into(), - }, - Proof { - block_hash: hex!("05aaa60b0f27cce9e71909508527264b77ee14da7b5bf915fcc4e32715333213").into(), - tx_index: 0, - data: (vec![ - hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb").to_vec(), - hex!("d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c185510").to_vec(), - hex!("b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646").to_vec(), - ], vec![ - hex!("f90131a0b601337b3aa10a671caa724eba641e759399979856141d3aea6b6b4ac59b889ba00c7d5dd48be9060221a02fb8fa213860b4c50d47046c8fa65ffaba5737d569e0a094601b62a1086cd9c9cb71a7ebff9e718f3217fd6e837efe4246733c0a196f63a06a4b0dd0aefc37b3c77828c8f07d1b7a2455ceb5dbfd3c77d7d6aeeddc2f7e8ca0d6e8e23142cdd8ec219e1f5d8b56aa18e456702b195deeaa210327284d42ade4a08a313d4c87023005d1ab631bbfe3f5de1e405d0e66d0bef3e033f1e5711b5521a0bf09a5d9a48b10ade82b8d6a5362a15921c8b5228a3487479b467db97411d82fa0f95cccae2a7c572ef3c566503e30bac2b2feb2d2f26eebf6d870dcf7f8cf59cea0d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c1855108080808080808080").to_vec(), - hex!("f851a0b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646a060a634b9280e3a23fb63375e7bbdd9ab07fd379ab6a67e2312bbc112195fa358808080808080808080808080808080").to_vec(), - hex!("f9030820b9030402f90300018301d6e2b9010000000000000800000000000020040008000000000000000000000000400000008000000000000000000000000000000000000000000000000000000000042010000000001000000000000000000000000000000000040000000000000000000000000000000000000000000000008000000000000000002000000000000000000000000200000000000000200000000000100000000040000001000200008000000000000200000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000f901f5f87a942ffa5ecdbe006d30397c7636d3e015eee251369ff842a0c965575a00553e094ca7c5d14f02e107c258dda06867cbf9e0e69f80e71bbcc1a000000000000000000000000000000000000000000000000000000000000003e8a000000000000000000000000000000000000000000000000000000000000003e8f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000f858948cf6147918a5cbb672703f879f385036f8793a24e1a01449abf21e49fd025f33495e77f7b1461caefdd3d4bb646424a3f445c4576a5ba0000000000000000000000000440edffa1352b13227e8ee646f3ea37456dec701").to_vec(), - ]), - } - ) - } - - pub fn get_message_verification_header() -> CompactExecutionHeader { - CompactExecutionHeader { - parent_hash: hex!("04a7f6ab8282203562c62f38b0ab41d32aaebe2c7ea687702b463148a6429e04") - .into(), - block_number: 55, - state_root: hex!("894d968712976d613519f973a317cb0781c7b039c89f27ea2b7ca193f7befdb3") - .into(), - receipts_root: hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb") - .into(), - } - } -} - -#[cfg(feature = "beacon-spec-mainnet")] -pub mod mainnet { - use super::*; - use frame_support::derive_impl; - - type Block = frame_system::mocking::MockBlock; - use sp_runtime::BuildStorage; - - frame_support::construct_runtime!( - pub enum Test { - System: frame_system::{Pallet, Call, Storage, Event}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - EthereumBeaconClient: ethereum_beacon_client::{Pallet, Call, Storage, Event}, - } - ); - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; - } - - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] - impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeTask = RuntimeTask; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type PalletInfo = PalletInfo; - type SS58Prefix = SS58Prefix; - type Nonce = u64; - type Block = Block; - } - - impl pallet_timestamp::Config for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = (); - type WeightInfo = (); - } - - parameter_types! { - pub const ChainForkVersions: ForkVersions = ForkVersions{ - genesis: Fork { - version: [0, 0, 16, 32], // 0x00001020 - epoch: 0, - }, - altair: Fork { - version: [1, 0, 16, 32], // 0x01001020 - epoch: 36660, - }, - bellatrix: Fork { - version: [2, 0, 16, 32], // 0x02001020 - epoch: 112260, - }, - capella: Fork { - version: [3, 0, 16, 32], // 0x03001020 - epoch: 162304, - }, - }; - pub const ExecutionHeadersPruneThreshold: u32 = 10; - } - - impl ethereum_beacon_client::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ForkVersions = ChainForkVersions; - type MaxExecutionHeadersToKeep = ExecutionHeadersPruneThreshold; - type WeightInfo = (); - } - - // Build genesis storage according to the mock runtime. - pub fn new_tester() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - let mut ext = sp_io::TestExternalities::new(t); - let _ = ext.execute_with(|| Timestamp::set(RuntimeOrigin::signed(1), 30_000)); - ext - } -} -- GitLab From 22d5b80d4486f2e9d53bf8ad1eb3efa11a4136af Mon Sep 17 00:00:00 2001 From: Vincent Geddes Date: Fri, 22 Mar 2024 13:52:51 +0200 Subject: [PATCH 163/188] Add a linear fee multiplier (#127) (#3790) Bridging fees are calculated using a static ETH/DOT exchange rate that can deviate significantly from the real-world exchange rate. We therefore need to add a safety margin to the fee so that users almost aways cover the cost of relaying. # FAQ > Why introduce a `multiplier` parameter instead of configuring an exchange rate which already has a safety factor applied? When converting from ETH to DOT, we need to _divide_ the multiplier by the exchange rate, and to convert from DOT to ETH we need to _multiply_ the multiplier by the exchange rate. > Other input parameters to the fee calculation can also deviate from real-world values. These include substrate weights, gas prices, and so on. Why does the multiplier introduced here not adjust those? A single scalar multiplier won't be able to accommodate the different volatilities efficiently. For example, gas prices are much more volatile than exchange rates, and substrate weights hardly ever change. So the pricing config relating to weights and gas prices should already have some appropriate safety margin pre-applied. # Detailed Changes: * Added `multiplier` field to `PricingParameters` * Outbound-queue fee is multiplied by `multiplier` * This `multiplier` is synced to the Ethereum side * Improved Runtime API for calculating outbound-queue fees. This API makes it much easier to for configure parts of the system in preparation for launch. * Improve and clarify code documentation Upstreamed from https://github.com/Snowfork/polkadot-sdk/pull/127 --------- Co-authored-by: Clara van Staden Co-authored-by: Adrian Catangiu --- .../pallets/inbound-queue/src/mock.rs | 3 +- .../outbound-queue/runtime-api/src/lib.rs | 11 +++-- .../pallets/outbound-queue/src/api.rs | 18 +++++--- .../pallets/outbound-queue/src/lib.rs | 32 +++++++++---- .../pallets/outbound-queue/src/mock.rs | 3 +- .../pallets/outbound-queue/src/test.rs | 46 +++++++++++-------- bridges/snowbridge/pallets/system/src/lib.rs | 2 + bridges/snowbridge/pallets/system/src/mock.rs | 3 +- .../primitives/core/src/outbound.rs | 13 ++++-- .../snowbridge/primitives/core/src/pricing.rs | 5 ++ .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 11 +++-- 11 files changed, 97 insertions(+), 50 deletions(-) diff --git a/bridges/snowbridge/pallets/inbound-queue/src/mock.rs b/bridges/snowbridge/pallets/inbound-queue/src/mock.rs index 086b27cb828..39e9532ed32 100644 --- a/bridges/snowbridge/pallets/inbound-queue/src/mock.rs +++ b/bridges/snowbridge/pallets/inbound-queue/src/mock.rs @@ -173,7 +173,8 @@ parameter_types! { pub Parameters: PricingParameters = PricingParameters { exchange_rate: FixedU128::from_rational(1, 400), fee_per_gas: gwei(20), - rewards: Rewards { local: DOT, remote: meth(1) } + rewards: Rewards { local: DOT, remote: meth(1) }, + multiplier: FixedU128::from_rational(1, 1), }; } diff --git a/bridges/snowbridge/pallets/outbound-queue/runtime-api/src/lib.rs b/bridges/snowbridge/pallets/outbound-queue/runtime-api/src/lib.rs index 51f46a7b49c..e6ddaa43935 100644 --- a/bridges/snowbridge/pallets/outbound-queue/runtime-api/src/lib.rs +++ b/bridges/snowbridge/pallets/outbound-queue/runtime-api/src/lib.rs @@ -3,7 +3,10 @@ #![cfg_attr(not(feature = "std"), no_std)] use frame_support::traits::tokens::Balance as BalanceT; -use snowbridge_core::outbound::Message; +use snowbridge_core::{ + outbound::{Command, Fee}, + PricingParameters, +}; use snowbridge_outbound_queue_merkle_tree::MerkleProof; sp_api::decl_runtime_apis! { @@ -11,10 +14,10 @@ sp_api::decl_runtime_apis! { { /// Generate a merkle proof for a committed message identified by `leaf_index`. /// The merkle root is stored in the block header as a - /// `\[`sp_runtime::generic::DigestItem::Other`\]` + /// `sp_runtime::generic::DigestItem::Other` fn prove_message(leaf_index: u64) -> Option; - /// Calculate the delivery fee for `message` - fn calculate_fee(message: Message) -> Option; + /// Calculate the delivery fee for `command` + fn calculate_fee(command: Command, parameters: Option>) -> Fee; } } diff --git a/bridges/snowbridge/pallets/outbound-queue/src/api.rs b/bridges/snowbridge/pallets/outbound-queue/src/api.rs index 44d63f1e2d2..b904819b1b1 100644 --- a/bridges/snowbridge/pallets/outbound-queue/src/api.rs +++ b/bridges/snowbridge/pallets/outbound-queue/src/api.rs @@ -4,8 +4,12 @@ use crate::{Config, MessageLeaves}; use frame_support::storage::StorageStreamIter; -use snowbridge_core::outbound::{Message, SendMessage}; +use snowbridge_core::{ + outbound::{Command, Fee, GasMeter}, + PricingParameters, +}; use snowbridge_outbound_queue_merkle_tree::{merkle_proof, MerkleProof}; +use sp_core::Get; pub fn prove_message(leaf_index: u64) -> Option where @@ -19,12 +23,14 @@ where Some(proof) } -pub fn calculate_fee(message: Message) -> Option +pub fn calculate_fee( + command: Command, + parameters: Option>, +) -> Fee where T: Config, { - match crate::Pallet::::validate(&message) { - Ok((_, fees)) => Some(fees.total()), - _ => None, - } + let gas_used_at_most = T::GasMeter::maximum_gas_used_at_most(&command); + let parameters = parameters.unwrap_or(T::PricingParameters::get()); + crate::Pallet::::calculate_fee(gas_used_at_most, parameters) } diff --git a/bridges/snowbridge/pallets/outbound-queue/src/lib.rs b/bridges/snowbridge/pallets/outbound-queue/src/lib.rs index 9e949a4791a..9b9dbe854a5 100644 --- a/bridges/snowbridge/pallets/outbound-queue/src/lib.rs +++ b/bridges/snowbridge/pallets/outbound-queue/src/lib.rs @@ -47,24 +47,37 @@ //! consume on Ethereum. Using this upper bound, a final fee can be calculated. //! //! The fee calculation also requires the following parameters: -//! * ETH/DOT exchange rate -//! * Ether fee per unit of gas +//! * Average ETH/DOT exchange rate over some period +//! * Max fee per unit of gas that bridge is willing to refund relayers for //! //! By design, it is expected that governance should manually update these //! parameters every few weeks using the `set_pricing_parameters` extrinsic in the //! system pallet. //! +//! This is an interim measure. Once ETH/DOT liquidity pools are available in the Polkadot network, +//! we'll use them as a source of pricing info, subject to certain safeguards. +//! //! ## Fee Computation Function //! //! ```text //! LocalFee(Message) = WeightToFee(ProcessMessageWeight(Message)) -//! RemoteFee(Message) = MaxGasRequired(Message) * FeePerGas + Reward -//! Fee(Message) = LocalFee(Message) + (RemoteFee(Message) / Ratio("ETH/DOT")) +//! RemoteFee(Message) = MaxGasRequired(Message) * Params.MaxFeePerGas + Params.Reward +//! RemoteFeeAdjusted(Message) = Params.Multiplier * (RemoteFee(Message) / Params.Ratio("ETH/DOT")) +//! Fee(Message) = LocalFee(Message) + RemoteFeeAdjusted(Message) //! ``` //! -//! By design, the computed fee is always going to conservative, to cover worst-case -//! costs of dispatch on Ethereum. In future iterations of the design, we will optimize -//! this, or provide a mechanism to asynchronously refund a portion of collected fees. +//! By design, the computed fee includes a safety factor (the `Multiplier`) to cover +//! unfavourable fluctuations in the ETH/DOT exchange rate. +//! +//! ## Fee Settlement +//! +//! On the remote side, in the gateway contract, the relayer accrues +//! +//! ```text +//! Min(GasPrice, Message.MaxFeePerGas) * GasUsed() + Message.Reward +//! ``` +//! Or in plain english, relayers are refunded for gas consumption, using a +//! price that is a minimum of the actual gas price, or `Message.MaxFeePerGas`. //! //! # Extrinsics //! @@ -106,7 +119,7 @@ pub use snowbridge_outbound_queue_merkle_tree::MerkleProof; use sp_core::{H256, U256}; use sp_runtime::{ traits::{CheckedDiv, Hash}, - DigestItem, + DigestItem, Saturating, }; use sp_std::prelude::*; pub use types::{CommittedMessage, ProcessMessageOriginOf}; @@ -366,8 +379,9 @@ pub mod pallet { // downcast to u128 let fee: u128 = fee.try_into().defensive_unwrap_or(u128::MAX); - // convert to local currency + // multiply by multiplier and convert to local currency let fee = FixedU128::from_inner(fee) + .saturating_mul(params.multiplier) .checked_div(¶ms.exchange_rate) .expect("exchange rate is not zero; qed") .into_inner(); diff --git a/bridges/snowbridge/pallets/outbound-queue/src/mock.rs b/bridges/snowbridge/pallets/outbound-queue/src/mock.rs index 850b13dcf31..67877a05c79 100644 --- a/bridges/snowbridge/pallets/outbound-queue/src/mock.rs +++ b/bridges/snowbridge/pallets/outbound-queue/src/mock.rs @@ -77,7 +77,8 @@ parameter_types! { pub Parameters: PricingParameters = PricingParameters { exchange_rate: FixedU128::from_rational(1, 400), fee_per_gas: gwei(20), - rewards: Rewards { local: DOT, remote: meth(1) } + rewards: Rewards { local: DOT, remote: meth(1) }, + multiplier: FixedU128::from_rational(4, 3), }; } diff --git a/bridges/snowbridge/pallets/outbound-queue/src/test.rs b/bridges/snowbridge/pallets/outbound-queue/src/test.rs index 8ed4a318d68..4e9ea36e24b 100644 --- a/bridges/snowbridge/pallets/outbound-queue/src/test.rs +++ b/bridges/snowbridge/pallets/outbound-queue/src/test.rs @@ -268,28 +268,34 @@ fn encode_digest_item() { } #[test] -fn validate_messages_with_fees() { +fn test_calculate_fees_with_unit_multiplier() { new_tester().execute_with(|| { - let message = mock_message(1000); - let (_, fee) = OutboundQueue::validate(&message).unwrap(); + let gas_used: u64 = 250000; + let price_params: PricingParameters<::Balance> = PricingParameters { + exchange_rate: FixedU128::from_rational(1, 400), + fee_per_gas: 10000_u32.into(), + rewards: Rewards { local: 1_u32.into(), remote: 1_u32.into() }, + multiplier: FixedU128::from_rational(1, 1), + }; + let fee = OutboundQueue::calculate_fee(gas_used, price_params); assert_eq!(fee.local, 698000000); - assert_eq!(fee.remote, 2680000000000); + assert_eq!(fee.remote, 1000000); }); } #[test] -fn test_calculate_fees() { +fn test_calculate_fees_with_multiplier() { new_tester().execute_with(|| { let gas_used: u64 = 250000; - let illegal_price_params: PricingParameters<::Balance> = - PricingParameters { - exchange_rate: FixedU128::from_rational(1, 400), - fee_per_gas: 10000_u32.into(), - rewards: Rewards { local: 1_u32.into(), remote: 1_u32.into() }, - }; - let fee = OutboundQueue::calculate_fee(gas_used, illegal_price_params); + let price_params: PricingParameters<::Balance> = PricingParameters { + exchange_rate: FixedU128::from_rational(1, 400), + fee_per_gas: 10000_u32.into(), + rewards: Rewards { local: 1_u32.into(), remote: 1_u32.into() }, + multiplier: FixedU128::from_rational(4, 3), + }; + let fee = OutboundQueue::calculate_fee(gas_used, price_params); assert_eq!(fee.local, 698000000); - assert_eq!(fee.remote, 1000000); + assert_eq!(fee.remote, 1333333); }); } @@ -297,13 +303,13 @@ fn test_calculate_fees() { fn test_calculate_fees_with_valid_exchange_rate_but_remote_fee_calculated_as_zero() { new_tester().execute_with(|| { let gas_used: u64 = 250000; - let illegal_price_params: PricingParameters<::Balance> = - PricingParameters { - exchange_rate: FixedU128::from_rational(1, 1), - fee_per_gas: 1_u32.into(), - rewards: Rewards { local: 1_u32.into(), remote: 1_u32.into() }, - }; - let fee = OutboundQueue::calculate_fee(gas_used, illegal_price_params.clone()); + let price_params: PricingParameters<::Balance> = PricingParameters { + exchange_rate: FixedU128::from_rational(1, 1), + fee_per_gas: 1_u32.into(), + rewards: Rewards { local: 1_u32.into(), remote: 1_u32.into() }, + multiplier: FixedU128::from_rational(1, 1), + }; + let fee = OutboundQueue::calculate_fee(gas_used, price_params.clone()); assert_eq!(fee.local, 698000000); // Though none zero pricing params the remote fee calculated here is invalid // which should be avoided diff --git a/bridges/snowbridge/pallets/system/src/lib.rs b/bridges/snowbridge/pallets/system/src/lib.rs index 6e5ceb5e9b1..39c73e3630e 100644 --- a/bridges/snowbridge/pallets/system/src/lib.rs +++ b/bridges/snowbridge/pallets/system/src/lib.rs @@ -159,6 +159,7 @@ pub mod pallet { type DefaultPricingParameters: Get>; /// Cost of delivering a message from Ethereum + #[pallet::constant] type InboundDeliveryCost: Get>; type WeightInfo: WeightInfo; @@ -334,6 +335,7 @@ pub mod pallet { let command = Command::SetPricingParameters { exchange_rate: params.exchange_rate.into(), delivery_cost: T::InboundDeliveryCost::get().saturated_into::(), + multiplier: params.multiplier.into(), }; Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::::No)?; diff --git a/bridges/snowbridge/pallets/system/src/mock.rs b/bridges/snowbridge/pallets/system/src/mock.rs index a711eab5d3d..0312456c982 100644 --- a/bridges/snowbridge/pallets/system/src/mock.rs +++ b/bridges/snowbridge/pallets/system/src/mock.rs @@ -193,7 +193,8 @@ parameter_types! { pub Parameters: PricingParameters = PricingParameters { exchange_rate: FixedU128::from_rational(1, 400), fee_per_gas: gwei(20), - rewards: Rewards { local: DOT, remote: meth(1) } + rewards: Rewards { local: DOT, remote: meth(1) }, + multiplier: FixedU128::from_rational(4, 3) }; pub const InboundDeliveryCost: u128 = 1_000_000_000; diff --git a/bridges/snowbridge/primitives/core/src/outbound.rs b/bridges/snowbridge/primitives/core/src/outbound.rs index bce123878d3..0ba0fdb6108 100644 --- a/bridges/snowbridge/primitives/core/src/outbound.rs +++ b/bridges/snowbridge/primitives/core/src/outbound.rs @@ -136,6 +136,8 @@ mod v1 { exchange_rate: UD60x18, // Cost of delivering a message from Ethereum to BridgeHub, in ROC/KSM/DOT delivery_cost: u128, + // Fee multiplier + multiplier: UD60x18, }, } @@ -203,10 +205,11 @@ mod v1 { Token::Uint(U256::from(*transfer_asset_xcm)), Token::Uint(*register_token), ])]), - Command::SetPricingParameters { exchange_rate, delivery_cost } => + Command::SetPricingParameters { exchange_rate, delivery_cost, multiplier } => ethabi::encode(&[Token::Tuple(vec![ Token::Uint(exchange_rate.clone().into_inner()), Token::Uint(U256::from(*delivery_cost)), + Token::Uint(multiplier.clone().into_inner()), ])]), } } @@ -273,7 +276,8 @@ mod v1 { } } -#[cfg_attr(feature = "std", derive(PartialEq, Debug))] +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(PartialEq))] /// Fee for delivering message pub struct Fee where @@ -346,12 +350,13 @@ pub trait GasMeter { /// the command within the message const MAXIMUM_BASE_GAS: u64; + /// Total gas consumed at most, including verification & dispatch fn maximum_gas_used_at_most(command: &Command) -> u64 { Self::MAXIMUM_BASE_GAS + Self::maximum_dispatch_gas_used_at_most(command) } - /// Measures the maximum amount of gas a command payload will require to dispatch, AFTER - /// validation & verification. + /// Measures the maximum amount of gas a command payload will require to *dispatch*, NOT + /// including validation & verification. fn maximum_dispatch_gas_used_at_most(command: &Command) -> u64; } diff --git a/bridges/snowbridge/primitives/core/src/pricing.rs b/bridges/snowbridge/primitives/core/src/pricing.rs index 33aeda6d15c..0f392c7ad4b 100644 --- a/bridges/snowbridge/primitives/core/src/pricing.rs +++ b/bridges/snowbridge/primitives/core/src/pricing.rs @@ -13,6 +13,8 @@ pub struct PricingParameters { pub rewards: Rewards, /// Ether (wei) fee per gas unit pub fee_per_gas: U256, + /// Fee multiplier + pub multiplier: FixedU128, } #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] @@ -43,6 +45,9 @@ where if self.rewards.remote.is_zero() { return Err(InvalidPricingParameters) } + if self.multiplier == FixedU128::zero() { + return Err(InvalidPricingParameters) + } Ok(()) } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index bf7483179f2..3980fa0d501 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -38,7 +38,9 @@ pub mod xcm_config; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use snowbridge_beacon_primitives::{Fork, ForkVersions}; use snowbridge_core::{ - gwei, meth, outbound::Message, AgentId, AllowSiblingsOnly, PricingParameters, Rewards, + gwei, meth, + outbound::{Command, Fee}, + AgentId, AllowSiblingsOnly, PricingParameters, Rewards, }; use snowbridge_router_primitives::inbound::MessageToXcm; use sp_api::impl_runtime_apis; @@ -503,7 +505,8 @@ parameter_types! { pub Parameters: PricingParameters = PricingParameters { exchange_rate: FixedU128::from_rational(1, 400), fee_per_gas: gwei(20), - rewards: Rewards { local: 1 * UNITS, remote: meth(1) } + rewards: Rewards { local: 1 * UNITS, remote: meth(1) }, + multiplier: FixedU128::from_rational(1, 1), }; } @@ -1022,8 +1025,8 @@ impl_runtime_apis! { snowbridge_pallet_outbound_queue::api::prove_message::(leaf_index) } - fn calculate_fee(message: Message) -> Option { - snowbridge_pallet_outbound_queue::api::calculate_fee::(message) + fn calculate_fee(command: Command, parameters: Option>) -> Fee { + snowbridge_pallet_outbound_queue::api::calculate_fee::(command, parameters) } } -- GitLab From 9d2963c29d9b7ea949851a166e0cb2792fc66fff Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 22 Mar 2024 14:18:03 +0200 Subject: [PATCH 164/188] Make public addresses go first in authority discovery DHT records (#3757) Make sure explicitly set by the operator public addresses go first in the authority discovery DHT records. Also update `Discovery` behavior to eliminate duplicates in the returned addresses. This PR should improve situation with https://github.com/paritytech/polkadot-sdk/issues/3519. Obsoletes https://github.com/paritytech/polkadot-sdk/pull/3657. --- Cargo.lock | 1 + .../relay-chain-minimal-node/src/lib.rs | 2 + polkadot/node/service/src/lib.rs | 2 + substrate/bin/node/cli/src/service.rs | 2 + .../client/authority-discovery/Cargo.toml | 1 + .../client/authority-discovery/src/lib.rs | 5 + .../client/authority-discovery/src/worker.rs | 92 ++++++++++++++----- substrate/client/network/Cargo.toml | 2 +- substrate/client/network/src/discovery.rs | 19 +++- 9 files changed, 99 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bdbf6ddac26..074b657e767 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15555,6 +15555,7 @@ dependencies = [ "futures-timer", "ip_network", "libp2p", + "linked_hash_set", "log", "multihash 0.18.1", "multihash-codetable", diff --git a/cumulus/client/relay-chain-minimal-node/src/lib.rs b/cumulus/client/relay-chain-minimal-node/src/lib.rs index 4bccca59fe3..6aea043713d 100644 --- a/cumulus/client/relay-chain-minimal-node/src/lib.rs +++ b/cumulus/client/relay-chain-minimal-node/src/lib.rs @@ -55,6 +55,7 @@ fn build_authority_discovery_service( prometheus_registry: Option, ) -> AuthorityDiscoveryService { let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; + let auth_disc_public_addresses = config.network.public_addresses.clone(); let authority_discovery_role = sc_authority_discovery::Role::Discover; let dht_event_stream = network.event_stream("authority-discovery").filter_map(|e| async move { match e { @@ -65,6 +66,7 @@ fn build_authority_discovery_service( let (worker, service) = sc_authority_discovery::new_worker_and_service_with_config( sc_authority_discovery::WorkerConfig { publish_non_global_ips: auth_disc_publish_non_global_ips, + public_addresses: auth_disc_public_addresses, // Require that authority discovery records are signed. strict_record_validation: true, ..Default::default() diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs index 83a0afc077e..4f4ede53705 100644 --- a/polkadot/node/service/src/lib.rs +++ b/polkadot/node/service/src/lib.rs @@ -807,6 +807,7 @@ pub fn new_full( let shared_voter_state = rpc_setup; let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; + let auth_disc_public_addresses = config.network.public_addresses.clone(); let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network); let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); @@ -1061,6 +1062,7 @@ pub fn new_full( let (worker, service) = sc_authority_discovery::new_worker_and_service_with_config( sc_authority_discovery::WorkerConfig { publish_non_global_ips: auth_disc_publish_non_global_ips, + public_addresses: auth_disc_public_addresses, // Require that authority discovery records are signed. strict_record_validation: true, ..Default::default() diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index 8f2aba6b44c..e4b425e6f96 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -422,6 +422,7 @@ pub fn new_full_base( let shared_voter_state = rpc_setup; let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; + let auth_disc_public_addresses = config.network.public_addresses.clone(); let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network); let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); @@ -610,6 +611,7 @@ pub fn new_full_base( sc_authority_discovery::new_worker_and_service_with_config( sc_authority_discovery::WorkerConfig { publish_non_global_ips: auth_disc_publish_non_global_ips, + public_addresses: auth_disc_public_addresses, ..Default::default() }, client.clone(), diff --git a/substrate/client/authority-discovery/Cargo.toml b/substrate/client/authority-discovery/Cargo.toml index cdd4052f0b0..26580064b3c 100644 --- a/substrate/client/authority-discovery/Cargo.toml +++ b/substrate/client/authority-discovery/Cargo.toml @@ -29,6 +29,7 @@ multihash = { version = "0.18.1", default-features = false, features = [ "sha2", "std", ] } +linked_hash_set = "0.1.4" log = { workspace = true, default-features = true } prost = "0.12" rand = "0.8.5" diff --git a/substrate/client/authority-discovery/src/lib.rs b/substrate/client/authority-discovery/src/lib.rs index 6bb12804cad..281188de143 100644 --- a/substrate/client/authority-discovery/src/lib.rs +++ b/substrate/client/authority-discovery/src/lib.rs @@ -80,6 +80,10 @@ pub struct WorkerConfig { /// Defaults to `true` to avoid the surprise factor. pub publish_non_global_ips: bool, + /// Public addresses set by the node operator to always publish first in the authority + /// discovery DHT record. + pub public_addresses: Vec, + /// Reject authority discovery records that are not signed by their network identity (PeerId) /// /// Defaults to `false` to provide compatibility with old versions @@ -104,6 +108,7 @@ impl Default for WorkerConfig { // `authority_discovery_dht_event_received`. max_query_interval: Duration::from_secs(10 * 60), publish_non_global_ips: true, + public_addresses: Vec::new(), strict_record_validation: false, } } diff --git a/substrate/client/authority-discovery/src/worker.rs b/substrate/client/authority-discovery/src/worker.rs index 9bccb96ff37..b77f0241ec2 100644 --- a/substrate/client/authority-discovery/src/worker.rs +++ b/substrate/client/authority-discovery/src/worker.rs @@ -35,6 +35,7 @@ use addr_cache::AddrCache; use codec::{Decode, Encode}; use ip_network::IpNetwork; use libp2p::{core::multiaddr, identity::PublicKey, multihash::Multihash, Multiaddr, PeerId}; +use linked_hash_set::LinkedHashSet; use multihash_codetable::{Code, MultihashDigest}; use log::{debug, error, log_enabled}; @@ -120,14 +121,22 @@ pub struct Worker { /// Interval to be proactive, publishing own addresses. publish_interval: ExpIncInterval, + /// Pro-actively publish our own addresses at this interval, if the keys in the keystore /// have changed. publish_if_changed_interval: ExpIncInterval, + /// List of keys onto which addresses have been published at the latest publication. /// Used to check whether they have changed. latest_published_keys: HashSet, + /// Same value as in the configuration. publish_non_global_ips: bool, + + /// Public addresses set by the node operator to always publish first in the authority + /// discovery DHT record. + public_addresses: LinkedHashSet, + /// Same value as in the configuration. strict_record_validation: bool, @@ -136,6 +145,7 @@ pub struct Worker { /// Queue of throttled lookups pending to be passed to the network. pending_lookups: Vec, + /// Set of in-flight lookups. in_flight_lookups: HashMap, @@ -224,6 +234,29 @@ where None => None, }; + let public_addresses = { + let local_peer_id: Multihash = network.local_peer_id().into(); + + config + .public_addresses + .into_iter() + .map(|mut address| { + if let Some(multiaddr::Protocol::P2p(peer_id)) = address.iter().last() { + if peer_id != local_peer_id { + error!( + target: LOG_TARGET, + "Discarding invalid local peer ID in public address {address}.", + ); + } + // Always discard `/p2p/...` protocol for proper address comparison (local + // peer id will be added before publishing). + address.pop(); + } + address + }) + .collect() + }; + Worker { from_service: from_service.fuse(), client, @@ -233,6 +266,7 @@ where publish_if_changed_interval, latest_published_keys: HashSet::new(), publish_non_global_ips: config.publish_non_global_ips, + public_addresses, strict_record_validation: config.strict_record_validation, query_interval, pending_lookups: Vec::new(), @@ -304,32 +338,48 @@ where } fn addresses_to_publish(&self) -> impl Iterator { - let peer_id: Multihash = self.network.local_peer_id().into(); let publish_non_global_ips = self.publish_non_global_ips; - let addresses = self.network.external_addresses().into_iter().filter(move |a| { - if publish_non_global_ips { - return true - } + let addresses = self + .public_addresses + .clone() + .into_iter() + .chain(self.network.external_addresses().into_iter().filter_map(|mut address| { + // Make sure the reported external address does not contain `/p2p/...` protocol. + if let Some(multiaddr::Protocol::P2p(_)) = address.iter().last() { + address.pop(); + } - a.iter().all(|p| match p { - // The `ip_network` library is used because its `is_global()` method is stable, - // while `is_global()` in the standard library currently isn't. - multiaddr::Protocol::Ip4(ip) if !IpNetwork::from(ip).is_global() => false, - multiaddr::Protocol::Ip6(ip) if !IpNetwork::from(ip).is_global() => false, - _ => true, + if self.public_addresses.contains(&address) { + // Already added above. + None + } else { + Some(address) + } + })) + .filter(move |address| { + if publish_non_global_ips { + return true + } + + address.iter().all(|protocol| match protocol { + // The `ip_network` library is used because its `is_global()` method is stable, + // while `is_global()` in the standard library currently isn't. + multiaddr::Protocol::Ip4(ip) if !IpNetwork::from(ip).is_global() => false, + multiaddr::Protocol::Ip6(ip) if !IpNetwork::from(ip).is_global() => false, + _ => true, + }) }) - }); + .collect::>(); - debug!(target: LOG_TARGET, "Authority DHT record peer_id='{:?}' addresses='{:?}'", peer_id, addresses.clone().collect::>()); + let peer_id = self.network.local_peer_id(); + debug!( + target: LOG_TARGET, + "Authority DHT record peer_id='{peer_id}' addresses='{addresses:?}'", + ); - // The address must include the peer id if not already set. - addresses.map(move |a| { - if a.iter().any(|p| matches!(p, multiaddr::Protocol::P2p(_))) { - a - } else { - a.with(multiaddr::Protocol::P2p(peer_id)) - } - }) + // The address must include the peer id. + let peer_id: Multihash = peer_id.into(); + addresses.into_iter().map(move |a| a.with(multiaddr::Protocol::P2p(peer_id))) } /// Publish own public addresses. diff --git a/substrate/client/network/Cargo.toml b/substrate/client/network/Cargo.toml index cbf74440dc1..c6f17647166 100644 --- a/substrate/client/network/Cargo.toml +++ b/substrate/client/network/Cargo.toml @@ -29,7 +29,7 @@ futures = "0.3.21" futures-timer = "3.0.2" ip_network = "0.4.1" libp2p = { version = "0.51.4", features = ["dns", "identify", "kad", "macros", "mdns", "noise", "ping", "request-response", "tcp", "tokio", "websocket", "yamux"] } -linked_hash_set = "0.1.3" +linked_hash_set = "0.1.4" log = { workspace = true, default-features = true } mockall = "0.11.3" parking_lot = "0.12.1" diff --git a/substrate/client/network/src/discovery.rs b/substrate/client/network/src/discovery.rs index 77c26266aac..4e2121c5540 100644 --- a/substrate/client/network/src/discovery.rs +++ b/substrate/client/network/src/discovery.rs @@ -72,6 +72,7 @@ use libp2p::{ }, PeerId, }; +use linked_hash_set::LinkedHashSet; use log::{debug, info, trace, warn}; use sp_core::hexdisplay::HexDisplay; use std::{ @@ -550,14 +551,20 @@ impl NetworkBehaviour for DiscoveryBehaviour { ) -> Result, ConnectionDenied> { let Some(peer_id) = maybe_peer else { return Ok(Vec::new()) }; - let mut list = self + // Collect addresses into [`LinkedHashSet`] to eliminate duplicate entries preserving the + // order of addresses. Give priority to `permanent_addresses` (used with reserved nodes) and + // `ephemeral_addresses` (used for addresses discovered from other sources, like authority + // discovery DHT records). + let mut list: LinkedHashSet<_> = self .permanent_addresses .iter() .filter_map(|(p, a)| (*p == peer_id).then_some(a.clone())) - .collect::>(); + .collect(); if let Some(ephemeral_addresses) = self.ephemeral_addresses.get(&peer_id) { - list.extend(ephemeral_addresses.clone()); + ephemeral_addresses.iter().for_each(|address| { + list.insert_if_absent(address.clone()); + }); } { @@ -583,12 +590,14 @@ impl NetworkBehaviour for DiscoveryBehaviour { }); } - list.extend(list_to_filter); + list_to_filter.into_iter().for_each(|address| { + list.insert_if_absent(address); + }); } trace!(target: "sub-libp2p", "Addresses of {:?}: {:?}", peer_id, list); - Ok(list) + Ok(list.into_iter().collect()) } fn on_swarm_event(&mut self, event: FromSwarm) { -- GitLab From 2f59e9efa8142d02ee4893a1383debd3b6209019 Mon Sep 17 00:00:00 2001 From: PG Herveou Date: Fri, 22 Mar 2024 19:45:26 +0100 Subject: [PATCH 165/188] XCM remove extra QueryId types from traits (#3763) We do not need to make these traits generic over QueryId type, we can just use the QueryId alias everywhere --- polkadot/xcm/pallet-xcm/src/lib.rs | 11 +++---- polkadot/xcm/xcm-builder/src/controller.rs | 4 +-- polkadot/xcm/xcm-builder/src/pay.rs | 2 +- polkadot/xcm/xcm-builder/src/tests/mock.rs | 11 +++---- .../xcm-executor/src/traits/on_response.rs | 31 ++++++------------- 5 files changed, 22 insertions(+), 37 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 1a1f8b402a3..0761b375dfb 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -374,7 +374,7 @@ pub mod pallet { origin: OriginFor, timeout: BlockNumberFor, match_querier: VersionedLocation, - ) -> Result { + ) -> Result { let responder = ::ExecuteXcmOrigin::ensure_origin(origin)?; let query_id = ::new_query( responder, @@ -1478,7 +1478,6 @@ impl sp_std::fmt::Debug for FeesHandling { } impl QueryHandler for Pallet { - type QueryId = u64; type BlockNumber = BlockNumberFor; type Error = XcmError; type UniversalLocation = T::UniversalLocation; @@ -1488,7 +1487,7 @@ impl QueryHandler for Pallet { responder: impl Into, timeout: BlockNumberFor, match_querier: impl Into, - ) -> Self::QueryId { + ) -> QueryId { Self::do_new_query(responder, None, timeout, match_querier) } @@ -1498,7 +1497,7 @@ impl QueryHandler for Pallet { message: &mut Xcm<()>, responder: impl Into, timeout: Self::BlockNumber, - ) -> Result { + ) -> Result { let responder = responder.into(); let destination = Self::UniversalLocation::get() .invert_target(&responder) @@ -1511,7 +1510,7 @@ impl QueryHandler for Pallet { } /// Removes response when ready and emits [Event::ResponseTaken] event. - fn take_response(query_id: Self::QueryId) -> QueryResponseStatus { + fn take_response(query_id: QueryId) -> QueryResponseStatus { match Queries::::get(query_id) { Some(QueryStatus::Ready { response, at }) => match response.try_into() { Ok(response) => { @@ -1528,7 +1527,7 @@ impl QueryHandler for Pallet { } #[cfg(feature = "runtime-benchmarks")] - fn expect_response(id: Self::QueryId, response: Response) { + fn expect_response(id: QueryId, response: Response) { let response = response.into(); Queries::::insert( id, diff --git a/polkadot/xcm/xcm-builder/src/controller.rs b/polkadot/xcm/xcm-builder/src/controller.rs index ba2b1fb44b8..04b19eaa587 100644 --- a/polkadot/xcm/xcm-builder/src/controller.rs +++ b/polkadot/xcm/xcm-builder/src/controller.rs @@ -132,7 +132,7 @@ pub trait QueryController: QueryHandler { origin: Origin, timeout: Timeout, match_querier: VersionedLocation, - ) -> Result; + ) -> Result; } impl ExecuteController for () { @@ -186,7 +186,7 @@ impl QueryController for () { _origin: Origin, _timeout: Timeout, _match_querier: VersionedLocation, - ) -> Result { + ) -> Result { Ok(Default::default()) } } diff --git a/polkadot/xcm/xcm-builder/src/pay.rs b/polkadot/xcm/xcm-builder/src/pay.rs index 6b466483cfa..35b624b0415 100644 --- a/polkadot/xcm/xcm-builder/src/pay.rs +++ b/polkadot/xcm/xcm-builder/src/pay.rs @@ -88,7 +88,7 @@ impl< type Beneficiary = Beneficiary; type AssetKind = AssetKind; type Balance = u128; - type Id = Querier::QueryId; + type Id = QueryId; type Error = xcm::latest::Error; fn pay( diff --git a/polkadot/xcm/xcm-builder/src/tests/mock.rs b/polkadot/xcm/xcm-builder/src/tests/mock.rs index 4bf347ea771..3d03ab05424 100644 --- a/polkadot/xcm/xcm-builder/src/tests/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/mock.rs @@ -38,7 +38,7 @@ pub use sp_std::{ collections::{btree_map::BTreeMap, btree_set::BTreeSet}, fmt::Debug, }; -pub use xcm::latest::{prelude::*, Weight}; +pub use xcm::latest::{prelude::*, QueryId, Weight}; use xcm_executor::traits::{Properties, QueryHandler, QueryResponseStatus}; pub use xcm_executor::{ traits::{ @@ -414,7 +414,6 @@ pub struct TestQueryHandler(core::marker::PhantomData<(T, BlockN impl QueryHandler for TestQueryHandler { - type QueryId = u64; type BlockNumber = BlockNumber; type Error = XcmError; type UniversalLocation = T::UniversalLocation; @@ -423,7 +422,7 @@ impl QueryHandler responder: impl Into, _timeout: Self::BlockNumber, _match_querier: impl Into, - ) -> Self::QueryId { + ) -> QueryId { let query_id = 1; expect_response(query_id, responder.into()); query_id @@ -433,7 +432,7 @@ impl QueryHandler message: &mut Xcm<()>, responder: impl Into, timeout: Self::BlockNumber, - ) -> Result { + ) -> Result { let responder = responder.into(); let destination = Self::UniversalLocation::get() .invert_target(&responder) @@ -445,7 +444,7 @@ impl QueryHandler Ok(query_id) } - fn take_response(query_id: Self::QueryId) -> QueryResponseStatus { + fn take_response(query_id: QueryId) -> QueryResponseStatus { QUERIES .with(|q| { q.borrow().get(&query_id).and_then(|v| match v { @@ -460,7 +459,7 @@ impl QueryHandler } #[cfg(feature = "runtime-benchmarks")] - fn expect_response(_id: Self::QueryId, _response: xcm::latest::Response) { + fn expect_response(_id: QueryId, _response: xcm::latest::Response) { // Unnecessary since it's only a test implementation } } diff --git a/polkadot/xcm/xcm-executor/src/traits/on_response.rs b/polkadot/xcm/xcm-executor/src/traits/on_response.rs index 952bd2d0040..1049bacdca5 100644 --- a/polkadot/xcm/xcm-executor/src/traits/on_response.rs +++ b/polkadot/xcm/xcm-executor/src/traits/on_response.rs @@ -16,11 +16,8 @@ use crate::{Junctions::Here, Xcm}; use core::result; -use frame_support::{ - pallet_prelude::{Get, TypeInfo}, - parameter_types, -}; -use parity_scale_codec::{Decode, Encode, FullCodec, MaxEncodedLen}; +use frame_support::{pallet_prelude::Get, parameter_types}; +use parity_scale_codec::{Decode, Encode}; use sp_arithmetic::traits::Zero; use sp_std::fmt::Debug; use xcm::latest::{ @@ -115,15 +112,6 @@ pub enum QueryResponseStatus { /// Provides methods to expect responses from XCMs and query their status. pub trait QueryHandler { - type QueryId: From - + FullCodec - + MaxEncodedLen - + TypeInfo - + Clone - + Eq - + PartialEq - + Debug - + Copy; type BlockNumber: Zero + Encode; type Error; type UniversalLocation: Get; @@ -151,14 +139,14 @@ pub trait QueryHandler { message: &mut Xcm<()>, responder: impl Into, timeout: Self::BlockNumber, - ) -> result::Result; + ) -> result::Result; /// Attempt to remove and return the response of query with ID `query_id`. - fn take_response(id: Self::QueryId) -> QueryResponseStatus; + fn take_response(id: QueryId) -> QueryResponseStatus; /// Makes sure to expect a response with the given id. #[cfg(feature = "runtime-benchmarks")] - fn expect_response(id: Self::QueryId, response: Response); + fn expect_response(id: QueryId, response: Response); } parameter_types! { @@ -168,17 +156,16 @@ parameter_types! { impl QueryHandler for () { type BlockNumber = u64; type Error = (); - type QueryId = u64; type UniversalLocation = UniversalLocation; - fn take_response(_query_id: Self::QueryId) -> QueryResponseStatus { + fn take_response(_query_id: QueryId) -> QueryResponseStatus { QueryResponseStatus::NotFound } fn new_query( _responder: impl Into, _timeout: Self::BlockNumber, _match_querier: impl Into, - ) -> Self::QueryId { + ) -> QueryId { 0u64 } @@ -186,10 +173,10 @@ impl QueryHandler for () { _message: &mut Xcm<()>, _responder: impl Into, _timeout: Self::BlockNumber, - ) -> Result { + ) -> Result { Err(()) } #[cfg(feature = "runtime-benchmarks")] - fn expect_response(_id: Self::QueryId, _response: crate::Response) {} + fn expect_response(_id: QueryId, _response: crate::Response) {} } -- GitLab From 9a04ebbfb0b77f2dcdc46db6a1a2b455881edd03 Mon Sep 17 00:00:00 2001 From: girazoki Date: Fri, 22 Mar 2024 19:48:15 +0100 Subject: [PATCH 166/188] [pallet-xcm] fix transport fees for remote reserve transfers (#3792) Currently `transfer_assets` from pallet-xcm covers 4 main different transfer types: - `localReserve` - `DestinationReserve` - `Teleport` - `RemoteReserve` For the first three, the local execution and the remote message sending are separated, and fees are deducted in pallet-xcm itself: https://github.com/paritytech/polkadot-sdk/blob/3410dfb3929462da88be2da813f121d8b1cf46b3/polkadot/xcm/pallet-xcm/src/lib.rs#L1758. For the 4th case `RemoteReserve`, pallet-xcm is still relying on the xcm-executor itself to send the message (through the `initiateReserveWithdraw` instruction). In this case, if delivery fees need to be charged, it is not possible to do so because the `jit_withdraw` mode has not being set. This PR proposes to still use the `initiateReserveWithdraw` but prepending a `setFeesMode { jit_withdraw: true }` to make sure delivery fees can be paid. A test-case is also added to present the aforementioned case --------- Co-authored-by: Adrian Catangiu --- .../emulated/common/src/macros.rs | 2 +- .../tests/assets/asset-hub-rococo/src/lib.rs | 8 +- .../src/tests/reserve_transfer.rs | 73 ++------ .../asset-hub-rococo/src/tests/teleport.rs | 14 +- .../tests/assets/asset-hub-westend/src/lib.rs | 8 +- .../src/tests/reserve_transfer.rs | 71 ++------ .../asset-hub-westend/src/tests/teleport.rs | 14 +- .../people-rococo/src/tests/teleport.rs | 6 +- .../people-westend/src/tests/teleport.rs | 6 +- .../assets/test-utils/src/test_cases.rs | 4 +- .../assets/test-utils/src/xcm_helpers.rs | 5 +- .../runtimes/testing/penpal/src/lib.rs | 19 +- .../runtimes/testing/penpal/src/xcm_config.rs | 19 +- polkadot/xcm/pallet-xcm/src/lib.rs | 1 + polkadot/xcm/pallet-xcm/src/mock.rs | 15 +- .../pallet-xcm/src/tests/assets_transfer.rs | 171 ++++++++++++++++++ prdoc/pr_3792.prdoc | 19 ++ 17 files changed, 291 insertions(+), 164 deletions(-) create mode 100644 prdoc/pr_3792.prdoc diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index 6951de6faa7..6f6bbe41e01 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -115,7 +115,7 @@ macro_rules! test_parachain_is_trusted_teleporter { let para_receiver_balance_after = <$receiver_para as $crate::macros::Chain>::account_data_of(receiver.clone()).free; let delivery_fees = <$sender_para>::execute_with(|| { - $crate::macros::asset_test_utils::xcm_helpers::transfer_assets_delivery_fees::< + $crate::macros::asset_test_utils::xcm_helpers::teleport_assets_delivery_fees::< <$sender_xcm_config as xcm_executor::Config>::XcmSender, >($assets.clone(), fee_asset_item, weight_limit.clone(), beneficiary, para_destination) }); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs index 21d858f1fe5..a5a4914e21d 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs @@ -63,17 +63,13 @@ mod imports { // Runtimes pub use asset_hub_rococo_runtime::xcm_config::{ - TokenLocation as RelayLocation, UniversalLocation as AssetHubRococoUniversalLocation, - XcmConfig as AssetHubRococoXcmConfig, + TokenLocation as RelayLocation, XcmConfig as AssetHubRococoXcmConfig, }; pub use penpal_runtime::xcm_config::{ LocalReservableFromAssetHub as PenpalLocalReservableFromAssetHub, LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub, - UniversalLocation as PenpalUniversalLocation, XcmConfig as PenpalRococoXcmConfig, - }; - pub use rococo_runtime::xcm_config::{ - UniversalLocation as RococoUniversalLocation, XcmConfig as RococoXcmConfig, }; + pub use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig; pub const ASSET_ID: u32 = 3; pub const ASSET_MIN_BALANCE: u128 = 1000; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 705c9613b64..0a5956dedfd 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -524,7 +524,6 @@ fn reserve_transfer_native_asset_from_relay_to_para() { let destination = Rococo::child_location_of(PenpalA::para_id()); let sender = RococoSender::get(); let amount_to_send: Balance = ROCOCO_ED * 1000; - let assets: Assets = (Here, amount_to_send).into(); // Init values fot Parachain let relay_native_asset_location = @@ -552,15 +551,6 @@ fn reserve_transfer_native_asset_from_relay_to_para() { test.set_dispatchable::(relay_to_para_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = Rococo::execute_with(|| { - let reanchored_assets = - assets.reanchored(&destination, &RococoUniversalLocation::get()).unwrap(); - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_balance_after = test.sender.balance; let receiver_assets_after = PenpalA::execute_with(|| { @@ -568,8 +558,8 @@ fn reserve_transfer_native_asset_from_relay_to_para() { >::balance(relay_native_asset_location.into(), &receiver) }); - // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_balance_after < sender_balance_before - amount_to_send); // Receiver's asset balance is increased assert!(receiver_assets_after > receiver_assets_before); // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -595,7 +585,7 @@ fn reserve_transfer_native_asset_from_para_to_relay() { ::RuntimeOrigin::signed(asset_owner), relay_native_asset_location, sender.clone(), - amount_to_send, + amount_to_send * 2, ); // Init values for Relay @@ -634,15 +624,6 @@ fn reserve_transfer_native_asset_from_para_to_relay() { test.set_dispatchable::(para_to_relay_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = PenpalA::execute_with(|| { - let reanchored_assets = - assets.reanchored(&destination, &PenpalUniversalLocation::get()).unwrap(); - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_assets_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -650,8 +631,8 @@ fn reserve_transfer_native_asset_from_para_to_relay() { }); let receiver_balance_after = test.receiver.balance; - // Sender's balance is reduced - assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_assets_after < sender_assets_before - amount_to_send); // Receiver's asset balance is increased assert!(receiver_balance_after > receiver_balance_before); // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -705,16 +686,6 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = AssetHubRococo::execute_with(|| { - let reanchored_assets = assets - .reanchored(&destination, &AssetHubRococoUniversalLocation::get()) - .unwrap(); - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_balance_after = test.sender.balance; let receiver_assets_after = PenpalA::execute_with(|| { @@ -722,8 +693,8 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { >::balance(system_para_native_asset_location, &receiver) }); - // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_balance_after < sender_balance_before - amount_to_send); // Receiver's assets is increased assert!(receiver_assets_after > receiver_assets_before); // Receiver's assets increased by `amount_to_send - delivery_fees - bought_execution`; @@ -738,7 +709,7 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { // Init values for Parachain let destination = PenpalA::sibling_location_of(AssetHubRococo::para_id()); let sender = PenpalASender::get(); - let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000; + let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 10000; let assets: Assets = (Parent, amount_to_send).into(); let system_para_native_asset_location = v3::Location::try_from(RelayLocation::get()).expect("conversion works"); @@ -749,7 +720,7 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { ::RuntimeOrigin::signed(asset_owner), system_para_native_asset_location, sender.clone(), - amount_to_send, + amount_to_send * 2, ); // Init values for System Parachain @@ -788,15 +759,6 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = PenpalA::execute_with(|| { - let reanchored_assets = - assets.reanchored(&destination, &PenpalUniversalLocation::get()).unwrap(); - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_assets_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -804,8 +766,8 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { }); let receiver_balance_after = test.receiver.balance; - // Sender's balance is reduced - assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_assets_after < sender_assets_before - amount_to_send); // Receiver's balance is increased assert!(receiver_balance_after > receiver_balance_before); // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -1084,7 +1046,7 @@ fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { ::RuntimeOrigin::signed(asset_owner), relay_native_asset_location, sender.clone(), - amount_to_send, + amount_to_send * 2, ); // fund the Parachain Origin's SA on Relay Chain with the native tokens held in reserve @@ -1118,13 +1080,6 @@ fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { test.set_dispatchable::(para_to_para_through_relay_limited_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = PenpalA::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_assets_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -1135,8 +1090,8 @@ fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { >::balance(relay_native_asset_location, &receiver) }); - // Sender's balance is reduced - assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_assets_after < sender_assets_before - amount_to_send); // Receiver's balance is increased assert!(receiver_assets_after > receiver_assets_before); } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/teleport.rs index 0cc5ddb9f64..4432999aa95 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/teleport.rs @@ -322,7 +322,7 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -369,7 +369,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -410,7 +410,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -445,7 +445,7 @@ fn teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -492,7 +492,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -530,7 +530,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() { test.assert(); let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -593,7 +593,7 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { ::RuntimeOrigin::signed(asset_owner.clone()), system_para_native_asset_location, sender.clone(), - fee_amount_to_send, + fee_amount_to_send * 2, ); // No need to create the asset (only mint) as it exists in genesis. PenpalA::mint_asset( diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs index 3f899d1dbdb..c9f5fe0647e 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs @@ -67,17 +67,13 @@ mod imports { // Runtimes pub use asset_hub_westend_runtime::xcm_config::{ - UniversalLocation as AssetHubWestendUniversalLocation, WestendLocation as RelayLocation, - XcmConfig as AssetHubWestendXcmConfig, + WestendLocation as RelayLocation, XcmConfig as AssetHubWestendXcmConfig, }; pub use penpal_runtime::xcm_config::{ LocalReservableFromAssetHub as PenpalLocalReservableFromAssetHub, LocalTeleportableToAssetHub as PenpalLocalTeleportableToAssetHub, - UniversalLocation as PenpalUniversalLocation, XcmConfig as PenpalWestendXcmConfig, - }; - pub use westend_runtime::xcm_config::{ - UniversalLocation as WestendUniversalLocation, XcmConfig as WestendXcmConfig, }; + pub use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig; pub const ASSET_ID: u32 = 3; pub const ASSET_MIN_BALANCE: u128 = 1000; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 8c836132b54..64ad15ca312 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -524,7 +524,6 @@ fn reserve_transfer_native_asset_from_relay_to_para() { let destination = Westend::child_location_of(PenpalA::para_id()); let sender = WestendSender::get(); let amount_to_send: Balance = WESTEND_ED * 1000; - let assets: Assets = (Here, amount_to_send).into(); // Init values fot Parachain let relay_native_asset_location = @@ -552,15 +551,6 @@ fn reserve_transfer_native_asset_from_relay_to_para() { test.set_dispatchable::(relay_to_para_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = Westend::execute_with(|| { - let reanchored_assets = - assets.reanchored(&destination, &WestendUniversalLocation::get()).unwrap(); - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_balance_after = test.sender.balance; let receiver_assets_after = PenpalA::execute_with(|| { @@ -568,8 +558,8 @@ fn reserve_transfer_native_asset_from_relay_to_para() { >::balance(relay_native_asset_location.into(), &receiver) }); - // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_balance_after < sender_balance_before - amount_to_send); // Receiver's asset balance is increased assert!(receiver_assets_after > receiver_assets_before); // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -595,7 +585,7 @@ fn reserve_transfer_native_asset_from_para_to_relay() { ::RuntimeOrigin::signed(asset_owner), relay_native_asset_location, sender.clone(), - amount_to_send, + amount_to_send * 2, ); // Init values for Relay @@ -634,15 +624,6 @@ fn reserve_transfer_native_asset_from_para_to_relay() { test.set_dispatchable::(para_to_relay_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = PenpalA::execute_with(|| { - let reanchored_assets = - assets.reanchored(&destination, &PenpalUniversalLocation::get()).unwrap(); - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_assets_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -650,8 +631,8 @@ fn reserve_transfer_native_asset_from_para_to_relay() { }); let receiver_balance_after = test.receiver.balance; - // Sender's balance is reduced - assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_assets_after < sender_assets_before - amount_to_send); // Receiver's asset balance is increased assert!(receiver_balance_after > receiver_balance_before); // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -705,16 +686,6 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = AssetHubWestend::execute_with(|| { - let reanchored_assets = assets - .reanchored(&destination, &AssetHubWestendUniversalLocation::get()) - .unwrap(); - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_balance_after = test.sender.balance; let receiver_assets_after = PenpalA::execute_with(|| { @@ -722,8 +693,8 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { >::balance(system_para_native_asset_location, &receiver) }); - // Sender's balance is reduced - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_balance_after < sender_balance_before - amount_to_send); // Receiver's assets is increased assert!(receiver_assets_after > receiver_assets_before); // Receiver's assets increased by `amount_to_send - delivery_fees - bought_execution`; @@ -749,7 +720,7 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { ::RuntimeOrigin::signed(asset_owner), system_para_native_asset_location, sender.clone(), - amount_to_send, + amount_to_send * 2, ); // Init values for System Parachain @@ -789,15 +760,6 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = PenpalA::execute_with(|| { - let reanchored_assets = - assets.reanchored(&destination, &PenpalUniversalLocation::get()).unwrap(); - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(reanchored_assets, 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_assets_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -805,8 +767,8 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { }); let receiver_balance_after = test.receiver.balance; - // Sender's balance is reduced - assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_assets_after < sender_assets_before - amount_to_send); // Receiver's balance is increased assert!(receiver_balance_after > receiver_balance_before); // Receiver's balance increased by `amount_to_send - delivery_fees - bought_execution`; @@ -1086,7 +1048,7 @@ fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { ::RuntimeOrigin::signed(asset_owner), relay_native_asset_location, sender.clone(), - amount_to_send, + amount_to_send * 2, ); // fund the Parachain Origin's SA on Relay Chain with the native tokens held in reserve @@ -1120,13 +1082,6 @@ fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { test.set_dispatchable::(para_to_para_through_relay_limited_reserve_transfer_assets); test.assert(); - // Calculate delivery fees - let delivery_fees = PenpalA::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - // Query final balances let sender_assets_after = PenpalA::execute_with(|| { type ForeignAssets = ::ForeignAssets; @@ -1137,8 +1092,8 @@ fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { >::balance(relay_native_asset_location, &receiver) }); - // Sender's balance is reduced - assert_eq!(sender_assets_before - amount_to_send - delivery_fees, sender_assets_after); + // Sender's balance is reduced by amount sent plus delivery fees + assert!(sender_assets_after < sender_assets_before - amount_to_send); // Receiver's balance is increased assert!(receiver_assets_after > receiver_assets_before); } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/teleport.rs index 61f547fe7c5..aba05ea4322 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/teleport.rs @@ -322,7 +322,7 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Westend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -369,7 +369,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -410,7 +410,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -445,7 +445,7 @@ fn teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Westend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -492,7 +492,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -530,7 +530,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() { test.assert(); let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -593,7 +593,7 @@ fn bidirectional_teleport_foreign_assets_between_para_and_asset_hub() { ::RuntimeOrigin::signed(asset_owner.clone()), system_para_native_asset_location, sender.clone(), - fee_amount_to_send, + fee_amount_to_send * 2, ); // No need to create the asset (only mint) as it exists in genesis. PenpalA::mint_asset( diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/teleport.rs index 3abe5c6cf66..350d87d638a 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/src/tests/teleport.rs @@ -155,7 +155,7 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -204,7 +204,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = PeopleRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -248,7 +248,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let receiver_balance_after = test.receiver.balance; let delivery_fees = PeopleRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/teleport.rs index eef35a99a83..8697477ba76 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/teleport.rs @@ -155,7 +155,7 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Westend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -204,7 +204,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = PeopleWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -248,7 +248,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let receiver_balance_after = test.receiver.balance; let delivery_fees = PeopleWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 53e10956bd0..2f2624d8e52 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -186,7 +186,7 @@ pub fn teleports_for_native_asset_works< // Mint funds into account to ensure it has enough balance to pay delivery fees let delivery_fees = - xcm_helpers::transfer_assets_delivery_fees::( + xcm_helpers::teleport_assets_delivery_fees::( (native_asset_id.clone(), native_asset_to_teleport_away.into()).into(), 0, Unlimited, @@ -579,7 +579,7 @@ pub fn teleports_for_foreign_assets_works< // Make sure the target account has enough native asset to pay for delivery fees let delivery_fees = - xcm_helpers::transfer_assets_delivery_fees::( + xcm_helpers::teleport_assets_delivery_fees::( (foreign_asset_id_location_latest.clone(), asset_to_teleport_away).into(), 0, Unlimited, diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs b/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs index f509a3a8aca..ca0e81fae42 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs @@ -18,11 +18,10 @@ use xcm::latest::prelude::*; -/// Returns the delivery fees amount for pallet xcm's `teleport_assets` and -/// `reserve_transfer_assets` extrinsics. +/// Returns the delivery fees amount for pallet xcm's `teleport_assets` extrinsics. /// Because it returns only a `u128`, it assumes delivery fees are only paid /// in one asset and that asset is known. -pub fn transfer_assets_delivery_fees( +pub fn teleport_assets_delivery_fees( assets: Assets, fee_asset_item: u32, weight_limit: WeightLimit, diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 1e6d485d148..1d404feac3d 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -57,7 +57,6 @@ use parachains_common::{ impls::{AssetsToBlockAuthor, NonZeroIssuance}, message_queue::{NarrowOriginToSibling, ParaIdToSibling}, }; -use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; use smallvec::smallvec; use sp_api::impl_runtime_apis; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -85,7 +84,7 @@ use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; // XCM Imports use parachains_common::{AccountId, Signature}; -use xcm::latest::prelude::BodyId; +use xcm::latest::prelude::{AssetId as AssetLocationId, BodyId}; /// Balance of an account. pub type Balance = u128; @@ -545,6 +544,20 @@ impl pallet_message_queue::Config for Runtime { impl cumulus_pallet_aura_ext::Config for Runtime {} +parameter_types! { + /// The asset ID for the asset that we use to pay for message delivery fees. + pub FeeAssetId: AssetLocationId = AssetLocationId(xcm_config::RelayLocation::get()); + /// The base fee for the message delivery fees (3 CENTS). + pub const BaseDeliveryFee: u128 = (1_000_000_000_000u128 / 100).saturating_mul(3); +} + +pub type PriceForSiblingParachainDelivery = polkadot_runtime_common::xcm_sender::ExponentialPrice< + FeeAssetId, + BaseDeliveryFee, + TransactionByteFee, + XcmpQueue, +>; + impl cumulus_pallet_xcmp_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ChannelInfo = ParachainSystem; @@ -555,7 +568,7 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = (); - type PriceForSiblingDelivery = NoPriceForMessageDelivery; + type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } parameter_types! { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index d83a877c2f8..639bfd95834 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -28,6 +28,7 @@ use super::{ ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; +use crate::{BaseDeliveryFee, FeeAssetId, TransactionByteFee}; use core::marker::PhantomData; use frame_support::{ parameter_types, @@ -36,10 +37,10 @@ use frame_support::{ }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; -use parachains_common::xcm_config::AssetFeeAsExistentialDepositMultiplier; +use parachains_common::{xcm_config::AssetFeeAsExistentialDepositMultiplier, TREASURY_PALLET_ID}; use polkadot_parachain_primitives::primitives::Sibling; -use polkadot_runtime_common::impls::ToAuthor; -use sp_runtime::traits::ConvertInto; +use polkadot_runtime_common::{impls::ToAuthor, xcm_sender::ExponentialPrice}; +use sp_runtime::traits::{AccountIdConversion, ConvertInto}; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, @@ -49,6 +50,7 @@ use xcm_builder::{ SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, StartsWith, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, + XcmFeeManagerFromComponents, XcmFeeToAccount, }; use xcm_executor::{traits::JustTry, XcmExecutor}; @@ -59,6 +61,7 @@ parameter_types! { pub const RelayNetwork: Option = None; pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorLocation = [Parachain(ParachainInfo::parachain_id().into())].into(); + pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating(); } /// Type for specifying how a `Location` can be converted into an `AccountId`. This is used @@ -331,7 +334,10 @@ impl xcm_executor::Config for XcmConfig { type MaxAssetsIntoHolding = MaxAssetsIntoHolding; type AssetLocker = (); type AssetExchanger = (); - type FeeManager = (); + type FeeManager = XcmFeeManagerFromComponents< + (), + XcmFeeToAccount, + >; type MessageExporter = (); type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; @@ -355,11 +361,14 @@ pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger = /// No local origins on this chain are allowed to dispatch XCM sends/executions. pub type LocalOriginToLocation = SignedToAccountId32; +pub type PriceForParentDelivery = + ExponentialPrice; + /// The means for routing XCM messages which are not for local execution into the right message /// queues. pub type XcmRouter = WithUniqueTopic<( // Two routers - use UMP to communicate with the relay chain: - cumulus_primitives_utility::ParentAsUmp, + cumulus_primitives_utility::ParentAsUmp, // ..and XCMP to communicate with the sibling chains. XcmpQueue, )>; diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 0761b375dfb..8a9e5288f2e 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1990,6 +1990,7 @@ impl Pallet { ]); Ok(Xcm(vec![ WithdrawAsset(assets.into()), + SetFeesMode { jit_withdraw: true }, InitiateReserveWithdraw { assets: Wild(AllCounted(max_assets)), reserve, diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index b29562fc833..2cc228476ba 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -361,6 +361,10 @@ parameter_types! { 0, [Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)] ); + pub PaidParaForeignReserveLocation: Location = Location::new( + 0, + [Parachain(Para3000::get())] + ); pub ForeignAsset: Asset = Asset { fun: Fungible(10), id: AssetId(Location::new( @@ -368,6 +372,13 @@ parameter_types! { [Parachain(FOREIGN_ASSET_RESERVE_PARA_ID), FOREIGN_ASSET_INNER_JUNCTION], )), }; + pub PaidParaForeignAsset: Asset = Asset { + fun: Fungible(10), + id: AssetId(Location::new( + 0, + [Parachain(Para3000::get())], + )), + }; pub UsdcReserveLocation: Location = Location::new( 0, [Parachain(USDC_RESERVE_PARA_ID)] @@ -450,6 +461,8 @@ parameter_types! { pub TrustedFilteredTeleport: (AssetFilter, Location) = (FilteredTeleportAsset::get().into(), FilteredTeleportLocation::get()); pub TeleportUsdtToForeign: (AssetFilter, Location) = (Usdt::get().into(), ForeignReserveLocation::get()); pub TrustedForeign: (AssetFilter, Location) = (ForeignAsset::get().into(), ForeignReserveLocation::get()); + pub TrustedPaidParaForeign: (AssetFilter, Location) = (PaidParaForeignAsset::get().into(), PaidParaForeignReserveLocation::get()); + pub TrustedUsdc: (AssetFilter, Location) = (Usdc::get().into(), UsdcReserveLocation::get()); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; @@ -483,7 +496,7 @@ impl xcm_executor::Config for XcmConfig { type XcmSender = XcmRouter; type AssetTransactor = AssetTransactors; type OriginConverter = LocalOriginConverter; - type IsReserve = (Case, Case); + type IsReserve = (Case, Case, Case); type IsTeleporter = ( Case, Case, diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index 27be5cce145..7752d1355cd 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -2604,3 +2604,174 @@ fn teleport_assets_using_destination_reserve_fee_disallowed() { expected_result, ); } + +/// Test `tested_call` transferring single asset using remote reserve. +/// +/// Transferring Para3000 asset (`Para3000` reserve) to +/// `OTHER_PARA_ID` (no teleport trust), therefore triggering remote reserve. +/// Using the same asset asset (Para3000 reserve) for fees. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +/// +/// Verifies that XCM router fees (`SendXcm::validate` -> `Assets`) are withdrawn from correct +/// user account and deposited to a correct target account (`XcmFeesTargetAccount`). +/// Verifies `expected_result`. +fn remote_asset_reserve_and_remote_fee_reserve_paid_call( + tested_call: Call, + expected_result: DispatchResult, +) where + Call: FnOnce( + OriginFor, + Box, + Box, + Box, + u32, + WeightLimit, + ) -> DispatchResult, +{ + let weight = BaseXcmWeight::get() * 3; + let user_account = AccountId::from(XCM_FEES_NOT_WAIVED_USER_ACCOUNT); + let xcm_router_fee_amount = Para3000PaymentAmount::get(); + let paid_para_id = Para3000::get(); + let balances = vec![ + (user_account.clone(), INITIAL_BALANCE), + (ParaId::from(paid_para_id).into_account_truncating(), INITIAL_BALANCE), + (XcmFeesTargetAccount::get(), INITIAL_BALANCE), + ]; + let beneficiary: Location = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset BLA + let foreign_initial_amount = 142; + let (reserve_location, _, foreign_asset_id_location) = set_up_foreign_asset( + paid_para_id, + None, + user_account.clone(), + foreign_initial_amount, + true, + ); + + // transfer destination is another chain that is not the reserve location + // the goal is to trigger the remoteReserve case + let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); + + let transferred_asset: Assets = (foreign_asset_id_location.clone(), SEND_AMOUNT).into(); + + // balances checks before + assert_eq!( + AssetsPallet::balance(foreign_asset_id_location.clone(), user_account.clone()), + foreign_initial_amount + ); + assert_eq!(Balances::free_balance(user_account.clone()), INITIAL_BALANCE); + + // do the transfer + let result = tested_call( + RuntimeOrigin::signed(user_account.clone()), + Box::new(dest.clone().into()), + Box::new(beneficiary.clone().into()), + Box::new(transferred_asset.into()), + 0 as u32, + Unlimited, + ); + assert_eq!(result, expected_result); + if expected_result.is_err() { + // short-circuit here for tests where we expect failure + return; + } + + let mut last_events = last_events(7).into_iter(); + // asset events + // forceCreate + last_events.next().unwrap(); + // mint tokens + last_events.next().unwrap(); + // burn tokens + last_events.next().unwrap(); + // balance events + // burn delivery fee + last_events.next().unwrap(); + // mint delivery fee + last_events.next().unwrap(); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { + outcome: Outcome::Complete { used: weight } + }) + ); + + // user account spent (transferred) amount + assert_eq!( + AssetsPallet::balance(foreign_asset_id_location.clone(), user_account.clone()), + foreign_initial_amount - SEND_AMOUNT + ); + + // user account spent delivery fees + assert_eq!(Balances::free_balance(user_account), INITIAL_BALANCE - xcm_router_fee_amount); + + // XcmFeesTargetAccount where should lend xcm_router_fee_amount + assert_eq!( + Balances::free_balance(XcmFeesTargetAccount::get()), + INITIAL_BALANCE + xcm_router_fee_amount + ); + + // Verify total and active issuance of foreign BLA have decreased (burned on + // reserve-withdraw) + let expected_issuance = foreign_initial_amount - SEND_AMOUNT; + assert_eq!( + AssetsPallet::total_issuance(foreign_asset_id_location.clone()), + expected_issuance + ); + assert_eq!( + AssetsPallet::active_issuance(foreign_asset_id_location.clone()), + expected_issuance + ); + + let context = UniversalLocation::get(); + let foreign_id_location_reanchored = + foreign_asset_id_location.reanchored(&dest, &context).unwrap(); + let dest_reanchored = dest.reanchored(&reserve_location, &context).unwrap(); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![( + reserve_location, + // `assets` are burned on source and withdrawn from SA in remote reserve chain + Xcm(vec![ + WithdrawAsset((Location::here(), SEND_AMOUNT).into()), + ClearOrigin, + buy_execution((Location::here(), SEND_AMOUNT / 2)), + DepositReserveAsset { + assets: Wild(AllCounted(1)), + // final destination is `dest` as seen by `reserve` + dest: dest_reanchored, + // message sent onward to `dest` + xcm: Xcm(vec![ + buy_execution((foreign_id_location_reanchored, SEND_AMOUNT / 2)), + DepositAsset { assets: AllCounted(1).into(), beneficiary } + ]) + } + ]) + )] + ); + }); +} +/// Test `transfer_assets` with remote asset reserve and remote fee reserve. +#[test] +fn transfer_assets_with_remote_asset_reserve_and_remote_asset_fee_reserve_paid_works() { + let expected_result = Ok(()); + remote_asset_reserve_and_remote_fee_reserve_paid_call( + XcmPallet::transfer_assets, + expected_result, + ); +} +/// Test `limited_reserve_transfer_assets` with remote asset reserve and remote fee reserve. +#[test] +fn limited_reserve_transfer_assets_with_remote_asset_reserve_and_remote_asset_fee_reserve_paid_works( +) { + let expected_result = Ok(()); + remote_asset_reserve_and_remote_fee_reserve_paid_call( + XcmPallet::limited_reserve_transfer_assets, + expected_result, + ); +} diff --git a/prdoc/pr_3792.prdoc b/prdoc/pr_3792.prdoc new file mode 100644 index 00000000000..cbcdc29a9c6 --- /dev/null +++ b/prdoc/pr_3792.prdoc @@ -0,0 +1,19 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "[pallet-xcm] fix transport fees for remote reserve transfers" + +doc: + - audience: Runtime Dev + description: | + This PR fixes `pallet_xcm::transfer_assets` and + `pallet_xcm::limited_reserve_transfer_assets` extrinsics for transfers + that need to go through remote reserves. The fix is adding a + `SetFeesMode { jit_withdraw: true }` instruction before local execution of + `InitiateReserveWithdraw` so that delivery fees are correctly charged by + the xcm-executor. Without this change, a runtime that has implemented + delivery fees would not be able to execute remote reserve transfers using + these extrinsics. + +crates: + - name: pallet-xcm -- GitLab From 19490abae08570ce87c3cae57542e928aa9a149d Mon Sep 17 00:00:00 2001 From: eskimor Date: Sat, 23 Mar 2024 06:46:15 +0100 Subject: [PATCH 167/188] Fix xcm config for coretime. (#3768) Fixes https://github.com/paritytech/polkadot-sdk/issues/3762 . --------- Co-authored-by: eskimor Co-authored-by: Adrian Catangiu --- polkadot/runtime/westend/src/xcm_config.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 400843c5835..96d2a124ff9 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -41,10 +41,11 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, DescribeAllTerminal, DescribeFamily, FrameTransactionalProcessor, - FungibleAdapter, HashedDescription, IsConcrete, MintLocation, OriginToPluralityVoice, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, - XcmFeeManagerFromComponents, XcmFeeToAccount, + FungibleAdapter, HashedDescription, IsChildSystemParachain, IsConcrete, MintLocation, + OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, + WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, + XcmFeeToAccount, }; use xcm_executor::XcmExecutor; @@ -142,13 +143,12 @@ impl Contains for OnlyParachains { } } -pub struct CollectivesOrFellows; -impl Contains for CollectivesOrFellows { +pub struct Fellows; +impl Contains for Fellows { fn contains(location: &Location) -> bool { matches!( location.unpack(), - (0, [Parachain(COLLECTIVES_ID)]) | - (0, [Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }]) + (0, [Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }]) ) } } @@ -172,8 +172,8 @@ pub type Barrier = TrailingSetTopicAsId<( AllowTopLevelPaidExecutionFrom, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, - // Collectives and Fellows plurality get free execution. - AllowExplicitUnpaidExecutionFrom, + // Messages from system parachains or the Fellows plurality need not pay for execution. + AllowExplicitUnpaidExecutionFrom<(IsChildSystemParachain, Fellows)>, ), UniversalLocation, ConstU32<8>, -- GitLab From 463ccb8f9028ebf5f7fc53d7e835c21f43172253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sun, 24 Mar 2024 15:21:18 +0100 Subject: [PATCH 168/188] pallet-aura: Expose `SlotDuration` as constant (#3732) --- substrate/frame/aura/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/frame/aura/src/lib.rs b/substrate/frame/aura/src/lib.rs index 997f51ba428..3ca1444aaae 100644 --- a/substrate/frame/aura/src/lib.rs +++ b/substrate/frame/aura/src/lib.rs @@ -114,6 +114,7 @@ pub mod pallet { /// The effective value of this type should not change while the chain is running. /// /// For backwards compatibility either use [`MinimumPeriodTimesTwo`] or a const. + #[pallet::constant] type SlotDuration: Get<::Moment>; } -- GitLab From e88d1cb79315792a3dbccb6bdef2543093ecaf5b Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Mon, 25 Mar 2024 10:40:22 +0100 Subject: [PATCH 169/188] [docs] Update ci image in container.md (#3799) cc https://github.com/paritytech/ci_cd/issues/943 --- docs/contributor/container.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/contributor/container.md b/docs/contributor/container.md index dd44b31bfe9..9c542f411c8 100644 --- a/docs/contributor/container.md +++ b/docs/contributor/container.md @@ -16,7 +16,7 @@ Parity builds and publishes a container image that can be found as `docker.io/pa ## Parity CI image Parity maintains and uses internally a generic "CI" image that can be used as a base to build binaries: [Parity CI -container image](https://github.com/paritytech/scripts/tree/master/dockerfiles/ci-linux): +container image](https://github.com/paritytech/scripts/tree/master/dockerfiles/ci-unified): The command below allows building a Linux binary without having to even install Rust or any dependency locally: @@ -24,14 +24,11 @@ The command below allows building a Linux binary without having to even install docker run --rm -it \ -w /polkadot-sdk \ -v $(pwd):/polkadot-sdk \ - paritytech/ci-linux:production \ + paritytech/ci-unified:bullseye-1.75.0-2024-01-22-v20240222 \ cargo build --release --locked -p polkadot-parachain-bin --bin polkadot-parachain sudo chown -R $(id -u):$(id -g) target/ ``` -If you want to reproduce other steps of CI process you can use the following -[guide](https://github.com/paritytech/scripts#gitlab-ci-for-building-docker-images). - ## Injected image Injecting a binary inside a base image is the quickest option to get a working container image. This only works if you -- GitLab From 0711729d251efebf3486db602119ecfa67d98366 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 25 Mar 2024 13:11:30 +0100 Subject: [PATCH 170/188] [Bridges] Move chain definitions to separate folder (#3822) Related to https://github.com/paritytech/parity-bridges-common/issues/2538 This PR doesn't contain any functional changes. The PR moves specific bridged chain definitions from `bridges/primitives` to `bridges/chains` folder in order to facilitate the migration of the `parity-bridges-repo` into `polkadot-sdk` as discussed in https://hackmd.io/LprWjZ0bQXKpFeveYHIRXw?view Apart from this it also includes some cosmetic changes to some `Cargo.toml` files as a result of running `diener workspacify`. --- Cargo.toml | 24 +++++++++---------- .../chain-asset-hub-rococo/Cargo.toml | 2 +- .../chain-asset-hub-rococo/src/lib.rs | 0 .../chain-asset-hub-westend/Cargo.toml | 2 +- .../chain-asset-hub-westend/src/lib.rs | 0 .../chain-bridge-hub-cumulus/Cargo.toml | 6 ++--- .../chain-bridge-hub-cumulus/src/lib.rs | 0 .../chain-bridge-hub-kusama/Cargo.toml | 4 ++-- .../chain-bridge-hub-kusama/src/lib.rs | 0 .../chain-bridge-hub-polkadot/Cargo.toml | 4 ++-- .../chain-bridge-hub-polkadot/src/lib.rs | 0 .../chain-bridge-hub-rococo/Cargo.toml | 4 ++-- .../chain-bridge-hub-rococo/src/lib.rs | 0 .../chain-bridge-hub-westend/Cargo.toml | 4 ++-- .../chain-bridge-hub-westend/src/lib.rs | 0 .../chain-kusama/Cargo.toml | 6 ++--- .../chain-kusama/src/lib.rs | 0 .../chain-polkadot-bulletin/Cargo.toml | 8 +++---- .../chain-polkadot-bulletin/src/lib.rs | 0 .../chain-polkadot/Cargo.toml | 6 ++--- .../chain-polkadot/src/lib.rs | 0 .../chain-rococo/Cargo.toml | 6 ++--- .../chain-rococo/src/lib.rs | 0 .../chain-westend/Cargo.toml | 6 ++--- .../chain-westend/src/lib.rs | 0 .../pallets/ethereum-client/Cargo.toml | 4 ++-- .../pallets/inbound-queue/Cargo.toml | 2 +- cumulus/client/consensus/aura/Cargo.toml | 2 +- .../assets/asset-hub-rococo/Cargo.toml | 2 +- .../assets/asset-hub-westend/Cargo.toml | 2 +- .../bridges/bridge-hub-rococo/Cargo.toml | 2 +- .../bridges/bridge-hub-westend/Cargo.toml | 2 +- .../collectives-westend/Cargo.toml | 2 +- .../people/people-rococo/Cargo.toml | 2 +- .../people/people-westend/Cargo.toml | 2 +- .../parachains/testing/penpal/Cargo.toml | 2 +- .../emulated/chains/relays/rococo/Cargo.toml | 2 +- .../emulated/chains/relays/westend/Cargo.toml | 2 +- .../tests/assets/asset-hub-rococo/Cargo.toml | 2 +- .../tests/assets/asset-hub-westend/Cargo.toml | 6 ++--- .../bridges/bridge-hub-rococo/Cargo.toml | 4 ++-- .../bridges/bridge-hub-westend/Cargo.toml | 4 ++-- .../tests/people/people-rococo/Cargo.toml | 2 +- .../tests/people/people-westend/Cargo.toml | 2 +- .../pallets/collective-content/Cargo.toml | 2 +- .../assets/asset-hub-rococo/Cargo.toml | 8 +++---- .../assets/asset-hub-westend/Cargo.toml | 8 +++---- .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 16 ++++++------- .../bridge-hubs/bridge-hub-westend/Cargo.toml | 14 +++++------ .../storage-weight-reclaim/Cargo.toml | 4 ++-- polkadot/Cargo.toml | 2 +- polkadot/node/core/pvf/Cargo.toml | 2 +- templates/solochain/runtime/Cargo.toml | 2 +- 53 files changed, 94 insertions(+), 94 deletions(-) rename bridges/{primitives => chains}/chain-asset-hub-rococo/Cargo.toml (87%) rename bridges/{primitives => chains}/chain-asset-hub-rococo/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-asset-hub-westend/Cargo.toml (87%) rename bridges/{primitives => chains}/chain-asset-hub-westend/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-bridge-hub-cumulus/Cargo.toml (80%) rename bridges/{primitives => chains}/chain-bridge-hub-cumulus/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-bridge-hub-kusama/Cargo.toml (85%) rename bridges/{primitives => chains}/chain-bridge-hub-kusama/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-bridge-hub-polkadot/Cargo.toml (85%) rename bridges/{primitives => chains}/chain-bridge-hub-polkadot/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-bridge-hub-rococo/Cargo.toml (85%) rename bridges/{primitives => chains}/chain-bridge-hub-rococo/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-bridge-hub-westend/Cargo.toml (85%) rename bridges/{primitives => chains}/chain-bridge-hub-westend/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-kusama/Cargo.toml (73%) rename bridges/{primitives => chains}/chain-kusama/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-polkadot-bulletin/Cargo.toml (78%) rename bridges/{primitives => chains}/chain-polkadot-bulletin/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-polkadot/Cargo.toml (73%) rename bridges/{primitives => chains}/chain-polkadot/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-rococo/Cargo.toml (73%) rename bridges/{primitives => chains}/chain-rococo/src/lib.rs (100%) rename bridges/{primitives => chains}/chain-westend/Cargo.toml (73%) rename bridges/{primitives => chains}/chain-westend/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 01d6ef8e87b..5eeac597827 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,24 +10,24 @@ resolver = "2" members = [ "bridges/bin/runtime-common", + "bridges/chains/chain-asset-hub-rococo", + "bridges/chains/chain-asset-hub-westend", + "bridges/chains/chain-bridge-hub-cumulus", + "bridges/chains/chain-bridge-hub-kusama", + "bridges/chains/chain-bridge-hub-polkadot", + "bridges/chains/chain-bridge-hub-rococo", + "bridges/chains/chain-bridge-hub-westend", + "bridges/chains/chain-kusama", + "bridges/chains/chain-polkadot", + "bridges/chains/chain-polkadot-bulletin", + "bridges/chains/chain-rococo", + "bridges/chains/chain-westend", "bridges/modules/grandpa", "bridges/modules/messages", "bridges/modules/parachains", "bridges/modules/relayers", "bridges/modules/xcm-bridge-hub", "bridges/modules/xcm-bridge-hub-router", - "bridges/primitives/chain-asset-hub-rococo", - "bridges/primitives/chain-asset-hub-westend", - "bridges/primitives/chain-bridge-hub-cumulus", - "bridges/primitives/chain-bridge-hub-kusama", - "bridges/primitives/chain-bridge-hub-polkadot", - "bridges/primitives/chain-bridge-hub-rococo", - "bridges/primitives/chain-bridge-hub-westend", - "bridges/primitives/chain-kusama", - "bridges/primitives/chain-polkadot", - "bridges/primitives/chain-polkadot-bulletin", - "bridges/primitives/chain-rococo", - "bridges/primitives/chain-westend", "bridges/primitives/header-chain", "bridges/primitives/messages", "bridges/primitives/parachains", diff --git a/bridges/primitives/chain-asset-hub-rococo/Cargo.toml b/bridges/chains/chain-asset-hub-rococo/Cargo.toml similarity index 87% rename from bridges/primitives/chain-asset-hub-rococo/Cargo.toml rename to bridges/chains/chain-asset-hub-rococo/Cargo.toml index 4dfa149e0ea..07c9b3b5289 100644 --- a/bridges/primitives/chain-asset-hub-rococo/Cargo.toml +++ b/bridges/chains/chain-asset-hub-rococo/Cargo.toml @@ -17,7 +17,7 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive frame-support = { path = "../../../substrate/frame/support", default-features = false } # Bridge Dependencies -bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } +bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false } [features] default = ["std"] diff --git a/bridges/primitives/chain-asset-hub-rococo/src/lib.rs b/bridges/chains/chain-asset-hub-rococo/src/lib.rs similarity index 100% rename from bridges/primitives/chain-asset-hub-rococo/src/lib.rs rename to bridges/chains/chain-asset-hub-rococo/src/lib.rs diff --git a/bridges/primitives/chain-asset-hub-westend/Cargo.toml b/bridges/chains/chain-asset-hub-westend/Cargo.toml similarity index 87% rename from bridges/primitives/chain-asset-hub-westend/Cargo.toml rename to bridges/chains/chain-asset-hub-westend/Cargo.toml index c9bd437562b..f75236ee1b3 100644 --- a/bridges/primitives/chain-asset-hub-westend/Cargo.toml +++ b/bridges/chains/chain-asset-hub-westend/Cargo.toml @@ -17,7 +17,7 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive frame-support = { path = "../../../substrate/frame/support", default-features = false } # Bridge Dependencies -bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } +bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false } [features] default = ["std"] diff --git a/bridges/primitives/chain-asset-hub-westend/src/lib.rs b/bridges/chains/chain-asset-hub-westend/src/lib.rs similarity index 100% rename from bridges/primitives/chain-asset-hub-westend/src/lib.rs rename to bridges/chains/chain-asset-hub-westend/src/lib.rs diff --git a/bridges/primitives/chain-bridge-hub-cumulus/Cargo.toml b/bridges/chains/chain-bridge-hub-cumulus/Cargo.toml similarity index 80% rename from bridges/primitives/chain-bridge-hub-cumulus/Cargo.toml rename to bridges/chains/chain-bridge-hub-cumulus/Cargo.toml index d35eefa1c45..5e14cb052b7 100644 --- a/bridges/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/bridges/chains/chain-bridge-hub-cumulus/Cargo.toml @@ -12,9 +12,9 @@ workspace = true [dependencies] # Bridge Dependencies -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-messages = { path = "../messages", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs b/bridges/chains/chain-bridge-hub-cumulus/src/lib.rs similarity index 100% rename from bridges/primitives/chain-bridge-hub-cumulus/src/lib.rs rename to bridges/chains/chain-bridge-hub-cumulus/src/lib.rs diff --git a/bridges/primitives/chain-bridge-hub-kusama/Cargo.toml b/bridges/chains/chain-bridge-hub-kusama/Cargo.toml similarity index 85% rename from bridges/primitives/chain-bridge-hub-kusama/Cargo.toml rename to bridges/chains/chain-bridge-hub-kusama/Cargo.toml index 8d71b3f5eb7..77bc8e54a9d 100644 --- a/bridges/primitives/chain-bridge-hub-kusama/Cargo.toml +++ b/bridges/chains/chain-bridge-hub-kusama/Cargo.toml @@ -13,8 +13,8 @@ workspace = true # Bridge Dependencies bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } -bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs b/bridges/chains/chain-bridge-hub-kusama/src/lib.rs similarity index 100% rename from bridges/primitives/chain-bridge-hub-kusama/src/lib.rs rename to bridges/chains/chain-bridge-hub-kusama/src/lib.rs diff --git a/bridges/primitives/chain-bridge-hub-polkadot/Cargo.toml b/bridges/chains/chain-bridge-hub-polkadot/Cargo.toml similarity index 85% rename from bridges/primitives/chain-bridge-hub-polkadot/Cargo.toml rename to bridges/chains/chain-bridge-hub-polkadot/Cargo.toml index 4e89e8a5c9a..5d7a3bbcc1d 100644 --- a/bridges/primitives/chain-bridge-hub-polkadot/Cargo.toml +++ b/bridges/chains/chain-bridge-hub-polkadot/Cargo.toml @@ -14,8 +14,8 @@ workspace = true # Bridge Dependencies bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } -bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs b/bridges/chains/chain-bridge-hub-polkadot/src/lib.rs similarity index 100% rename from bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs rename to bridges/chains/chain-bridge-hub-polkadot/src/lib.rs diff --git a/bridges/primitives/chain-bridge-hub-rococo/Cargo.toml b/bridges/chains/chain-bridge-hub-rococo/Cargo.toml similarity index 85% rename from bridges/primitives/chain-bridge-hub-rococo/Cargo.toml rename to bridges/chains/chain-bridge-hub-rococo/Cargo.toml index 1643d934a98..3966ef72dcb 100644 --- a/bridges/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/bridges/chains/chain-bridge-hub-rococo/Cargo.toml @@ -13,8 +13,8 @@ workspace = true # Bridge Dependencies bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } -bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-bridge-hub-rococo/src/lib.rs b/bridges/chains/chain-bridge-hub-rococo/src/lib.rs similarity index 100% rename from bridges/primitives/chain-bridge-hub-rococo/src/lib.rs rename to bridges/chains/chain-bridge-hub-rococo/src/lib.rs diff --git a/bridges/primitives/chain-bridge-hub-westend/Cargo.toml b/bridges/chains/chain-bridge-hub-westend/Cargo.toml similarity index 85% rename from bridges/primitives/chain-bridge-hub-westend/Cargo.toml rename to bridges/chains/chain-bridge-hub-westend/Cargo.toml index 32a7850c539..d35eac8b3fe 100644 --- a/bridges/primitives/chain-bridge-hub-westend/Cargo.toml +++ b/bridges/chains/chain-bridge-hub-westend/Cargo.toml @@ -14,8 +14,8 @@ workspace = true # Bridge Dependencies bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } -bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-bridge-hub-westend/src/lib.rs b/bridges/chains/chain-bridge-hub-westend/src/lib.rs similarity index 100% rename from bridges/primitives/chain-bridge-hub-westend/src/lib.rs rename to bridges/chains/chain-bridge-hub-westend/src/lib.rs diff --git a/bridges/primitives/chain-kusama/Cargo.toml b/bridges/chains/chain-kusama/Cargo.toml similarity index 73% rename from bridges/primitives/chain-kusama/Cargo.toml rename to bridges/chains/chain-kusama/Cargo.toml index 0660f346023..4ff4cb46976 100644 --- a/bridges/primitives/chain-kusama/Cargo.toml +++ b/bridges/chains/chain-kusama/Cargo.toml @@ -13,9 +13,9 @@ workspace = true # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-kusama/src/lib.rs b/bridges/chains/chain-kusama/src/lib.rs similarity index 100% rename from bridges/primitives/chain-kusama/src/lib.rs rename to bridges/chains/chain-kusama/src/lib.rs diff --git a/bridges/primitives/chain-polkadot-bulletin/Cargo.toml b/bridges/chains/chain-polkadot-bulletin/Cargo.toml similarity index 78% rename from bridges/primitives/chain-polkadot-bulletin/Cargo.toml rename to bridges/chains/chain-polkadot-bulletin/Cargo.toml index 15c824fcbdb..d10c4043967 100644 --- a/bridges/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/bridges/chains/chain-polkadot-bulletin/Cargo.toml @@ -15,10 +15,10 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-messages = { path = "../messages", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-polkadot-bulletin/src/lib.rs b/bridges/chains/chain-polkadot-bulletin/src/lib.rs similarity index 100% rename from bridges/primitives/chain-polkadot-bulletin/src/lib.rs rename to bridges/chains/chain-polkadot-bulletin/src/lib.rs diff --git a/bridges/primitives/chain-polkadot/Cargo.toml b/bridges/chains/chain-polkadot/Cargo.toml similarity index 73% rename from bridges/primitives/chain-polkadot/Cargo.toml rename to bridges/chains/chain-polkadot/Cargo.toml index 6421b7f4010..0db6791f66e 100644 --- a/bridges/primitives/chain-polkadot/Cargo.toml +++ b/bridges/chains/chain-polkadot/Cargo.toml @@ -13,9 +13,9 @@ workspace = true # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-polkadot/src/lib.rs b/bridges/chains/chain-polkadot/src/lib.rs similarity index 100% rename from bridges/primitives/chain-polkadot/src/lib.rs rename to bridges/chains/chain-polkadot/src/lib.rs diff --git a/bridges/primitives/chain-rococo/Cargo.toml b/bridges/chains/chain-rococo/Cargo.toml similarity index 73% rename from bridges/primitives/chain-rococo/Cargo.toml rename to bridges/chains/chain-rococo/Cargo.toml index de373f0ae64..9c63f960ae4 100644 --- a/bridges/primitives/chain-rococo/Cargo.toml +++ b/bridges/chains/chain-rococo/Cargo.toml @@ -13,9 +13,9 @@ workspace = true # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-rococo/src/lib.rs b/bridges/chains/chain-rococo/src/lib.rs similarity index 100% rename from bridges/primitives/chain-rococo/src/lib.rs rename to bridges/chains/chain-rococo/src/lib.rs diff --git a/bridges/primitives/chain-westend/Cargo.toml b/bridges/chains/chain-westend/Cargo.toml similarity index 73% rename from bridges/primitives/chain-westend/Cargo.toml rename to bridges/chains/chain-westend/Cargo.toml index e55a8d649a8..f5de9b95c82 100644 --- a/bridges/primitives/chain-westend/Cargo.toml +++ b/bridges/chains/chain-westend/Cargo.toml @@ -13,9 +13,9 @@ workspace = true # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/bridges/primitives/chain-westend/src/lib.rs b/bridges/chains/chain-westend/src/lib.rs similarity index 100% rename from bridges/primitives/chain-westend/src/lib.rs rename to bridges/chains/chain-westend/src/lib.rs diff --git a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml index c8999633c97..cadd542432e 100644 --- a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml +++ b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml @@ -36,7 +36,7 @@ sp-io = { path = "../../../../substrate/primitives/io", default-features = false snowbridge-core = { path = "../../primitives/core", default-features = false } snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false } -snowbridge-pallet-ethereum-client-fixtures = { path = "./fixtures", default-features = false, optional = true } +snowbridge-pallet-ethereum-client-fixtures = { path = "fixtures", default-features = false, optional = true } primitives = { package = "snowbridge-beacon-primitives", path = "../../primitives/beacon", default-features = false } static_assertions = { version = "1.1.0", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } @@ -48,7 +48,7 @@ sp-keyring = { path = "../../../../substrate/primitives/keyring" } serde_json = { workspace = true, default-features = true } hex-literal = "0.4.1" pallet-timestamp = { path = "../../../../substrate/frame/timestamp" } -snowbridge-pallet-ethereum-client-fixtures = { path = "./fixtures" } +snowbridge-pallet-ethereum-client-fixtures = { path = "fixtures" } sp-io = { path = "../../../../substrate/primitives/io" } serde = { workspace = true, default-features = true } diff --git a/bridges/snowbridge/pallets/inbound-queue/Cargo.toml b/bridges/snowbridge/pallets/inbound-queue/Cargo.toml index b850496cd4e..9fc1f31fbf7 100644 --- a/bridges/snowbridge/pallets/inbound-queue/Cargo.toml +++ b/bridges/snowbridge/pallets/inbound-queue/Cargo.toml @@ -42,7 +42,7 @@ snowbridge-core = { path = "../../primitives/core", default-features = false } snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false } snowbridge-router-primitives = { path = "../../primitives/router", default-features = false } snowbridge-beacon-primitives = { path = "../../primitives/beacon", default-features = false } -snowbridge-pallet-inbound-queue-fixtures = { path = "./fixtures", default-features = false, optional = true } +snowbridge-pallet-inbound-queue-fixtures = { path = "fixtures", default-features = false, optional = true } [dev-dependencies] frame-benchmarking = { path = "../../../../substrate/frame/benchmarking" } diff --git a/cumulus/client/consensus/aura/Cargo.toml b/cumulus/client/consensus/aura/Cargo.toml index e815e89d8ce..58bb1dd5914 100644 --- a/cumulus/client/consensus/aura/Cargo.toml +++ b/cumulus/client/consensus/aura/Cargo.toml @@ -41,7 +41,7 @@ substrate-prometheus-endpoint = { path = "../../../../substrate/utils/prometheus cumulus-client-consensus-common = { path = "../common" } cumulus-relay-chain-interface = { path = "../../relay-chain-interface" } cumulus-client-consensus-proposer = { path = "../proposer" } -cumulus-client-parachain-inherent = { path = "../../../client/parachain-inherent" } +cumulus-client-parachain-inherent = { path = "../../parachain-inherent" } cumulus-primitives-aura = { path = "../../../primitives/aura" } cumulus-primitives-core = { path = "../../../primitives/core" } cumulus-client-collator = { path = "../../collator" } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/Cargo.toml index f4f8b3603ba..98762beb0cb 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/Cargo.toml @@ -17,7 +17,7 @@ sp-core = { path = "../../../../../../../../substrate/primitives/core", default- frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../../parachains/common" } +parachains-common = { path = "../../../../../../common" } cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false } emulated-integration-tests-common = { path = "../../../../common", default-features = false } asset-hub-rococo-runtime = { path = "../../../../../../runtimes/assets/asset-hub-rococo" } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/Cargo.toml index d4764f63bf6..a42a9abf618 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/Cargo.toml @@ -17,7 +17,7 @@ sp-core = { path = "../../../../../../../../substrate/primitives/core", default- frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../../parachains/common" } +parachains-common = { path = "../../../../../../common" } cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false } emulated-integration-tests-common = { path = "../../../../common", default-features = false } asset-hub-westend-runtime = { path = "../../../../../../runtimes/assets/asset-hub-westend" } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo/Cargo.toml index 322d8b44e6e..789f10a35f2 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo/Cargo.toml @@ -17,7 +17,7 @@ sp-core = { path = "../../../../../../../../substrate/primitives/core", default- frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../../parachains/common" } +parachains-common = { path = "../../../../../../common" } emulated-integration-tests-common = { path = "../../../../common", default-features = false } bridge-hub-rococo-runtime = { path = "../../../../../../runtimes/bridge-hubs/bridge-hub-rococo" } bridge-hub-common = { path = "../../../../../../runtimes/bridge-hubs/common", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend/Cargo.toml index ec1386b7f6e..d82971cf55a 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend/Cargo.toml @@ -17,7 +17,7 @@ sp-core = { path = "../../../../../../../../substrate/primitives/core", default- frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../../parachains/common" } +parachains-common = { path = "../../../../../../common" } emulated-integration-tests-common = { path = "../../../../common", default-features = false } bridge-hub-westend-runtime = { path = "../../../../../../runtimes/bridge-hubs/bridge-hub-westend" } bridge-hub-common = { path = "../../../../../../runtimes/bridge-hubs/common", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/collectives/collectives-westend/Cargo.toml index 03f755b666a..4c2a7d3c274 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/collectives/collectives-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/collectives/collectives-westend/Cargo.toml @@ -17,7 +17,7 @@ sp-core = { path = "../../../../../../../../substrate/primitives/core", default- frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../../parachains/common" } +parachains-common = { path = "../../../../../../common" } cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false } emulated-integration-tests-common = { path = "../../../../common", default-features = false } collectives-westend-runtime = { path = "../../../../../../runtimes/collectives/collectives-westend" } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-rococo/Cargo.toml index 65a358d0ef2..f7fe93d2777 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-rococo/Cargo.toml @@ -14,7 +14,7 @@ sp-core = { path = "../../../../../../../../substrate/primitives/core", default- frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../../parachains/common" } +parachains-common = { path = "../../../../../../common" } cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false } emulated-integration-tests-common = { path = "../../../../common", default-features = false } people-rococo-runtime = { path = "../../../../../../runtimes/people/people-rococo" } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-westend/Cargo.toml index 075698848bc..57a767e0c2a 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-westend/Cargo.toml @@ -14,7 +14,7 @@ sp-core = { path = "../../../../../../../../substrate/primitives/core", default- frame-support = { path = "../../../../../../../../substrate/frame/support", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../../parachains/common" } +parachains-common = { path = "../../../../../../common" } cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false } emulated-integration-tests-common = { path = "../../../../common", default-features = false } people-westend-runtime = { path = "../../../../../../runtimes/people/people-westend" } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml index f47350b00eb..2ac508273c6 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/Cargo.toml @@ -20,7 +20,7 @@ frame-support = { path = "../../../../../../../../substrate/frame/support", defa xcm = { package = "staging-xcm", path = "../../../../../../../../polkadot/xcm", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../../parachains/common" } +parachains-common = { path = "../../../../../../common" } cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false } emulated-integration-tests-common = { path = "../../../../common", default-features = false } penpal-runtime = { path = "../../../../../../runtimes/testing/penpal" } diff --git a/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/Cargo.toml index 2d27426cca7..7ac65b0ee1d 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/Cargo.toml @@ -25,5 +25,5 @@ rococo-runtime-constants = { path = "../../../../../../../polkadot/runtime/rococ rococo-runtime = { path = "../../../../../../../polkadot/runtime/rococo" } # Cumulus -parachains-common = { path = "../../../../../../parachains/common" } +parachains-common = { path = "../../../../../common" } emulated-integration-tests-common = { path = "../../../common", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml index abc40c20406..20aedb50e6a 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml @@ -27,5 +27,5 @@ westend-runtime-constants = { path = "../../../../../../../polkadot/runtime/west westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" } # Cumulus -parachains-common = { path = "../../../../../../parachains/common" } +parachains-common = { path = "../../../../../common" } emulated-integration-tests-common = { path = "../../../common", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml index 13eb7d8dfc4..9b519da4b1d 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml @@ -30,7 +30,7 @@ rococo-runtime = { path = "../../../../../../../polkadot/runtime/rococo" } # Cumulus asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" } -parachains-common = { path = "../../../../../../parachains/common" } +parachains-common = { path = "../../../../../common" } cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false } testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["rococo"] } asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml index 8ac8efb5218..3121ed028eb 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml @@ -31,12 +31,12 @@ pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-fe westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" } # Cumulus -parachains-common = { path = "../../../../../../parachains/common" } +parachains-common = { path = "../../../../../common" } testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["westend"] } penpal-runtime = { path = "../../../../../runtimes/testing/penpal" } asset-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" } asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" } -cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" } -cumulus-pallet-parachain-system = { default-features = false, path = "../../../../../../pallets/parachain-system" } +cumulus-pallet-xcmp-queue = { path = "../../../../../../pallets/xcmp-queue", default-features = false } +cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false } emulated-integration-tests-common = { path = "../../../common", default-features = false } westend-system-emulated-network = { path = "../../../networks/westend-system" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml index 89f0d2a9ca6..18c39f895fa 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml @@ -34,10 +34,10 @@ pallet-bridge-messages = { path = "../../../../../../../bridges/modules/messages bp-messages = { path = "../../../../../../../bridges/primitives/messages", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../parachains/common" } +parachains-common = { path = "../../../../../common" } testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["rococo"] } cumulus-pallet-xcmp-queue = { path = "../../../../../../pallets/xcmp-queue", default-features = false } -bridge-hub-rococo-runtime = { path = "../../../../../../parachains/runtimes/bridge-hubs/bridge-hub-rococo", default-features = false } +bridge-hub-rococo-runtime = { path = "../../../../../runtimes/bridge-hubs/bridge-hub-rococo", default-features = false } emulated-integration-tests-common = { path = "../../../common", default-features = false } rococo-westend-system-emulated-network = { path = "../../../networks/rococo-westend-system" } rococo-system-emulated-network = { path = "../../../networks/rococo-system" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml index 9d55903c858..9059d841a48 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml @@ -30,8 +30,8 @@ pallet-bridge-messages = { path = "../../../../../../../bridges/modules/messages bp-messages = { path = "../../../../../../../bridges/primitives/messages", default-features = false } # Cumulus -parachains-common = { path = "../../../../../../parachains/common" } +parachains-common = { path = "../../../../../common" } cumulus-pallet-xcmp-queue = { path = "../../../../../../pallets/xcmp-queue", default-features = false } -bridge-hub-westend-runtime = { path = "../../../../../../parachains/runtimes/bridge-hubs/bridge-hub-westend", default-features = false } +bridge-hub-westend-runtime = { path = "../../../../../runtimes/bridge-hubs/bridge-hub-westend", default-features = false } emulated-integration-tests-common = { path = "../../../common", default-features = false } rococo-westend-system-emulated-network = { path = "../../../networks/rococo-westend-system" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/Cargo.toml index 609376c1fee..1570aa7662f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-rococo/Cargo.toml @@ -26,7 +26,7 @@ polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common # Cumulus asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" } -parachains-common = { path = "../../../../../../parachains/common" } +parachains-common = { path = "../../../../../common" } people-rococo-runtime = { path = "../../../../../runtimes/people/people-rococo" } emulated-integration-tests-common = { path = "../../../common", default-features = false } rococo-system-emulated-network = { path = "../../../networks/rococo-system" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/Cargo.toml index f2f3366798a..bc093dc0de6 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/Cargo.toml @@ -26,7 +26,7 @@ polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common # Cumulus asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" } -parachains-common = { path = "../../../../../../parachains/common" } +parachains-common = { path = "../../../../../common" } people-westend-runtime = { path = "../../../../../runtimes/people/people-westend" } emulated-integration-tests-common = { path = "../../../common", default-features = false } westend-system-emulated-network = { path = "../../../networks/westend-system" } diff --git a/cumulus/parachains/pallets/collective-content/Cargo.toml b/cumulus/parachains/pallets/collective-content/Cargo.toml index 691be02f5b8..d4290dd2de2 100644 --- a/cumulus/parachains/pallets/collective-content/Cargo.toml +++ b/cumulus/parachains/pallets/collective-content/Cargo.toml @@ -13,7 +13,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -frame-benchmarking = { path = "../../../../substrate/frame/benchmarking", optional = true, default-features = false } +frame-benchmarking = { path = "../../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-support = { path = "../../../../substrate/frame/support", default-features = false } frame-system = { path = "../../../../substrate/frame/system", default-features = false } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index 95691a045b7..53abb620022 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -86,10 +86,10 @@ assets-common = { path = "../common", default-features = false } # Bridges pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } -bp-asset-hub-rococo = { path = "../../../../../bridges/primitives/chain-asset-hub-rococo", default-features = false } -bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false } -bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false } -bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false } +bp-asset-hub-rococo = { path = "../../../../../bridges/chains/chain-asset-hub-rococo", default-features = false } +bp-asset-hub-westend = { path = "../../../../../bridges/chains/chain-asset-hub-westend", default-features = false } +bp-bridge-hub-rococo = { path = "../../../../../bridges/chains/chain-bridge-hub-rococo", default-features = false } +bp-bridge-hub-westend = { path = "../../../../../bridges/chains/chain-bridge-hub-westend", default-features = false } snowbridge-router-primitives = { path = "../../../../../bridges/snowbridge/primitives/router", default-features = false } [dev-dependencies] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index 950c6e62d72..0f8a1182cd7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -84,10 +84,10 @@ assets-common = { path = "../common", default-features = false } # Bridges pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } -bp-asset-hub-rococo = { path = "../../../../../bridges/primitives/chain-asset-hub-rococo", default-features = false } -bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false } -bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false } -bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false } +bp-asset-hub-rococo = { path = "../../../../../bridges/chains/chain-asset-hub-rococo", default-features = false } +bp-asset-hub-westend = { path = "../../../../../bridges/chains/chain-asset-hub-westend", default-features = false } +bp-bridge-hub-rococo = { path = "../../../../../bridges/chains/chain-bridge-hub-rococo", default-features = false } +bp-bridge-hub-westend = { path = "../../../../../bridges/chains/chain-bridge-hub-westend", default-features = false } [dev-dependencies] hex-literal = "0.4.1" diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 8a6823ea3ee..13b4b624eef 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -85,20 +85,20 @@ parachains-common = { path = "../../../common", default-features = false } testnet-parachains-constants = { path = "../../constants", default-features = false, features = ["rococo"] } # Bridges -bp-asset-hub-rococo = { path = "../../../../../bridges/primitives/chain-asset-hub-rococo", default-features = false } -bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false } -bp-bridge-hub-polkadot = { path = "../../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false } -bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false } -bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false } +bp-asset-hub-rococo = { path = "../../../../../bridges/chains/chain-asset-hub-rococo", default-features = false } +bp-asset-hub-westend = { path = "../../../../../bridges/chains/chain-asset-hub-westend", default-features = false } +bp-bridge-hub-polkadot = { path = "../../../../../bridges/chains/chain-bridge-hub-polkadot", default-features = false } +bp-bridge-hub-rococo = { path = "../../../../../bridges/chains/chain-bridge-hub-rococo", default-features = false } +bp-bridge-hub-westend = { path = "../../../../../bridges/chains/chain-bridge-hub-westend", default-features = false } bp-header-chain = { path = "../../../../../bridges/primitives/header-chain", default-features = false } bp-messages = { path = "../../../../../bridges/primitives/messages", default-features = false } bp-parachains = { path = "../../../../../bridges/primitives/parachains", default-features = false } -bp-polkadot-bulletin = { path = "../../../../../bridges/primitives/chain-polkadot-bulletin", default-features = false } +bp-polkadot-bulletin = { path = "../../../../../bridges/chains/chain-polkadot-bulletin", default-features = false } bp-polkadot-core = { path = "../../../../../bridges/primitives/polkadot-core", default-features = false } bp-relayers = { path = "../../../../../bridges/primitives/relayers", default-features = false } bp-runtime = { path = "../../../../../bridges/primitives/runtime", default-features = false } -bp-rococo = { path = "../../../../../bridges/primitives/chain-rococo", default-features = false } -bp-westend = { path = "../../../../../bridges/primitives/chain-westend", default-features = false } +bp-rococo = { path = "../../../../../bridges/chains/chain-rococo", default-features = false } +bp-westend = { path = "../../../../../bridges/chains/chain-westend", default-features = false } pallet-bridge-grandpa = { path = "../../../../../bridges/modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../../../bridges/modules/messages", default-features = false } pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", default-features = false } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml index 4eb201eedc1..0c46e6c2e14 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/Cargo.toml @@ -77,25 +77,25 @@ parachains-common = { path = "../../../common", default-features = false } testnet-parachains-constants = { path = "../../constants", default-features = false, features = ["westend"] } # Bridges -bp-asset-hub-rococo = { path = "../../../../../bridges/primitives/chain-asset-hub-rococo", default-features = false } -bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false } -bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false } -bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false } +bp-asset-hub-rococo = { path = "../../../../../bridges/chains/chain-asset-hub-rococo", default-features = false } +bp-asset-hub-westend = { path = "../../../../../bridges/chains/chain-asset-hub-westend", default-features = false } +bp-bridge-hub-rococo = { path = "../../../../../bridges/chains/chain-bridge-hub-rococo", default-features = false } +bp-bridge-hub-westend = { path = "../../../../../bridges/chains/chain-bridge-hub-westend", default-features = false } bp-header-chain = { path = "../../../../../bridges/primitives/header-chain", default-features = false } bp-messages = { path = "../../../../../bridges/primitives/messages", default-features = false } bp-parachains = { path = "../../../../../bridges/primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../../../../bridges/primitives/polkadot-core", default-features = false } bp-relayers = { path = "../../../../../bridges/primitives/relayers", default-features = false } bp-runtime = { path = "../../../../../bridges/primitives/runtime", default-features = false } -bp-rococo = { path = "../../../../../bridges/primitives/chain-rococo", default-features = false } -bp-westend = { path = "../../../../../bridges/primitives/chain-westend", default-features = false } +bp-rococo = { path = "../../../../../bridges/chains/chain-rococo", default-features = false } +bp-westend = { path = "../../../../../bridges/chains/chain-westend", default-features = false } pallet-bridge-grandpa = { path = "../../../../../bridges/modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../../../bridges/modules/messages", default-features = false } pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", default-features = false } pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false } pallet-xcm-bridge-hub = { path = "../../../../../bridges/modules/xcm-bridge-hub", default-features = false } bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false } -bridge-hub-common = { path = "../../bridge-hubs/common", default-features = false } +bridge-hub-common = { path = "../common", default-features = false } [dev-dependencies] static_assertions = "1.1" diff --git a/cumulus/primitives/storage-weight-reclaim/Cargo.toml b/cumulus/primitives/storage-weight-reclaim/Cargo.toml index 4835fb5192b..73e0f03cd37 100644 --- a/cumulus/primitives/storage-weight-reclaim/Cargo.toml +++ b/cumulus/primitives/storage-weight-reclaim/Cargo.toml @@ -20,8 +20,8 @@ frame-system = { path = "../../../substrate/frame/system", default-features = fa sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } sp-std = { path = "../../../substrate/primitives/std", default-features = false } -cumulus-primitives-core = { path = "../../primitives/core", default-features = false } -cumulus-primitives-proof-size-hostfunction = { path = "../../primitives/proof-size-hostfunction", default-features = false } +cumulus-primitives-core = { path = "../core", default-features = false } +cumulus-primitives-proof-size-hostfunction = { path = "../proof-size-hostfunction", default-features = false } docify = "0.2.7" [dev-dependencies] diff --git a/polkadot/Cargo.toml b/polkadot/Cargo.toml index b0d71a18eaa..883568b23f7 100644 --- a/polkadot/Cargo.toml +++ b/polkadot/Cargo.toml @@ -46,7 +46,7 @@ assert_cmd = "2.0.4" nix = { version = "0.26.1", features = ["signal"] } tempfile = "3.2.0" tokio = "1.24.2" -substrate-rpc-client = { path = "../substrate/utils/frame/rpc/client/" } +substrate-rpc-client = { path = "../substrate/utils/frame/rpc/client" } polkadot-core-primitives = { path = "core-primitives" } [build-dependencies] diff --git a/polkadot/node/core/pvf/Cargo.toml b/polkadot/node/core/pvf/Cargo.toml index 9ed64b88ffd..6ad36a39be6 100644 --- a/polkadot/node/core/pvf/Cargo.toml +++ b/polkadot/node/core/pvf/Cargo.toml @@ -50,7 +50,7 @@ hex-literal = "0.4.1" polkadot-node-core-pvf-common = { path = "common", features = ["test-utils"] } # For benches and integration tests, depend on ourselves with the test-utils # feature. -polkadot-node-core-pvf = { path = ".", features = ["test-utils"] } +polkadot-node-core-pvf = { path = "", features = ["test-utils"] } rococo-runtime = { path = "../../../runtime/rococo" } adder = { package = "test-parachain-adder", path = "../../../parachain/test-parachains/adder" } diff --git a/templates/solochain/runtime/Cargo.toml b/templates/solochain/runtime/Cargo.toml index 33da035878a..90dd823eb64 100644 --- a/templates/solochain/runtime/Cargo.toml +++ b/templates/solochain/runtime/Cargo.toml @@ -62,7 +62,7 @@ sp-transaction-pool = { path = "../../../substrate/primitives/transaction-pool", sp-version = { path = "../../../substrate/primitives/version", default-features = false, features = [ "serde", ] } -sp-genesis-builder = { default-features = false, path = "../../../substrate/primitives/genesis-builder" } +sp-genesis-builder = { path = "../../../substrate/primitives/genesis-builder", default-features = false } # RPC related frame-system-rpc-runtime-api = { path = "../../../substrate/frame/system/rpc/runtime-api", default-features = false } -- GitLab From c6f7ccf51a54d0272643b2beaeab7458df8492e0 Mon Sep 17 00:00:00 2001 From: Alin Dima Date: Mon, 25 Mar 2024 15:38:13 +0200 Subject: [PATCH 171/188] elastic scaling: preserve candidate ordering in provisioner (#3778) https://github.com/paritytech/polkadot-sdk/issues/3742 --- polkadot/node/core/backing/src/error.rs | 6 +- polkadot/node/core/backing/src/lib.rs | 32 +- polkadot/node/core/backing/src/tests/mod.rs | 343 +++++++++++++++++- polkadot/node/core/provisioner/src/lib.rs | 61 ++-- polkadot/node/core/provisioner/src/tests.rs | 176 +++++++-- polkadot/node/overseer/src/tests.rs | 2 +- polkadot/node/subsystem-types/src/messages.rs | 11 +- .../src/types/overseer-protocol.md | 12 +- 8 files changed, 569 insertions(+), 74 deletions(-) diff --git a/polkadot/node/core/backing/src/error.rs b/polkadot/node/core/backing/src/error.rs index 64955a39396..52684f3fe30 100644 --- a/polkadot/node/core/backing/src/error.rs +++ b/polkadot/node/core/backing/src/error.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +use std::collections::HashMap; + use fatality::Nested; use futures::channel::{mpsc, oneshot}; @@ -24,7 +26,7 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_util::{runtime, Error as UtilError}; use polkadot_primitives::{BackedCandidate, ValidationCodeHash}; -use crate::LOG_TARGET; +use crate::{ParaId, LOG_TARGET}; pub type Result = std::result::Result; pub type FatalResult = std::result::Result; @@ -55,7 +57,7 @@ pub enum Error { InvalidSignature, #[error("Failed to send candidates {0:?}")] - Send(Vec), + Send(HashMap>), #[error("FetchPoV failed")] FetchPoV, diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index 69bf2e956a0..532ae2bd7cb 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -2231,15 +2231,16 @@ async fn handle_statement_message( fn handle_get_backed_candidates_message( state: &State, - requested_candidates: Vec<(CandidateHash, Hash)>, - tx: oneshot::Sender>, + requested_candidates: HashMap>, + tx: oneshot::Sender>>, metrics: &Metrics, ) -> Result<(), Error> { let _timer = metrics.time_get_backed_candidates(); - let backed = requested_candidates - .into_iter() - .filter_map(|(candidate_hash, relay_parent)| { + let mut backed = HashMap::with_capacity(requested_candidates.len()); + + for (para_id, para_candidates) in requested_candidates { + for (candidate_hash, relay_parent) in para_candidates.iter() { let rp_state = match state.per_relay_parent.get(&relay_parent) { Some(rp_state) => rp_state, None => { @@ -2249,13 +2250,13 @@ fn handle_get_backed_candidates_message( ?candidate_hash, "Requested candidate's relay parent is out of view", ); - return None + break }, }; - rp_state + let maybe_backed_candidate = rp_state .table .attested_candidate( - &candidate_hash, + candidate_hash, &rp_state.table_context, rp_state.minimum_backing_votes, ) @@ -2265,9 +2266,18 @@ fn handle_get_backed_candidates_message( &rp_state.table_context, rp_state.inject_core_index, ) - }) - }) - .collect(); + }); + + if let Some(backed_candidate) = maybe_backed_candidate { + backed + .entry(para_id) + .or_insert_with(|| Vec::with_capacity(para_candidates.len())) + .push(backed_candidate); + } else { + break + } + } + } tx.send(backed).map_err(|data| Error::Send(data))?; Ok(()) diff --git a/polkadot/node/core/backing/src/tests/mod.rs b/polkadot/node/core/backing/src/tests/mod.rs index e3cc5727435..fdb47581ea3 100644 --- a/polkadot/node/core/backing/src/tests/mod.rs +++ b/polkadot/node/core/backing/src/tests/mod.rs @@ -663,13 +663,19 @@ fn backing_works(#[case] elastic_scaling_mvp: bool) { let (tx, rx) = oneshot::channel(); let msg = CandidateBackingMessage::GetBackedCandidates( - vec![(candidate_a_hash, test_state.relay_parent)], + std::iter::once(( + test_state.chain_ids[0], + vec![(candidate_a_hash, test_state.relay_parent)], + )) + .collect(), tx, ); virtual_overseer.send(FromOrchestra::Communication { msg }).await; - let candidates = rx.await.unwrap(); + let mut candidates = rx.await.unwrap(); + assert_eq!(1, candidates.len()); + let candidates = candidates.remove(&test_state.chain_ids[0]).unwrap(); assert_eq!(1, candidates.len()); assert_eq!(candidates[0].validity_votes().len(), 3); @@ -695,6 +701,323 @@ fn backing_works(#[case] elastic_scaling_mvp: bool) { }); } +#[test] +fn get_backed_candidate_preserves_order() { + let mut test_state = TestState::default(); + test_state + .node_features + .resize((node_features::FeatureIndex::ElasticScalingMVP as u8 + 1) as usize, false); + test_state + .node_features + .set(node_features::FeatureIndex::ElasticScalingMVP as u8 as usize, true); + + // Set a single validator as the first validator group. It simplifies the test. + test_state.validator_groups.0[0] = vec![ValidatorIndex(2)]; + // Add another validator group for the third core. + test_state.validator_groups.0.push(vec![ValidatorIndex(3)]); + // Assign the second core to the same para as the first one. + test_state.availability_cores[1] = + CoreState::Scheduled(ScheduledCore { para_id: test_state.chain_ids[0], collator: None }); + // Add another availability core for paraid 2. + test_state.availability_cores.push(CoreState::Scheduled(ScheduledCore { + para_id: test_state.chain_ids[1], + collator: None, + })); + + test_harness(test_state.keystore.clone(), |mut virtual_overseer| async move { + test_startup(&mut virtual_overseer, &test_state).await; + + let pov_a = PoV { block_data: BlockData(vec![1, 2, 3]) }; + let pov_b = PoV { block_data: BlockData(vec![3, 4, 5]) }; + let pov_c = PoV { block_data: BlockData(vec![5, 6, 7]) }; + let validation_code_ab = ValidationCode(vec![1, 2, 3]); + let validation_code_c = ValidationCode(vec![4, 5, 6]); + + let parent_head_data_a = test_state.head_data.get(&test_state.chain_ids[0]).unwrap(); + let parent_head_data_b = { + let mut head = parent_head_data_a.clone(); + head.0[0] = 98; + head + }; + let output_head_data_b = { + let mut head = parent_head_data_a.clone(); + head.0[0] = 99; + head + }; + let parent_head_data_c = test_state.head_data.get(&test_state.chain_ids[1]).unwrap(); + let output_head_data_c = { + let mut head = parent_head_data_c.clone(); + head.0[0] = 97; + head + }; + + let pvd_a = PersistedValidationData { + parent_head: parent_head_data_a.clone(), + relay_parent_number: 0_u32.into(), + max_pov_size: 1024, + relay_parent_storage_root: dummy_hash(), + }; + let pvd_b = PersistedValidationData { + parent_head: parent_head_data_b.clone(), + relay_parent_number: 0_u32.into(), + max_pov_size: 1024, + relay_parent_storage_root: dummy_hash(), + }; + let pvd_c = PersistedValidationData { + parent_head: parent_head_data_c.clone(), + relay_parent_number: 0_u32.into(), + max_pov_size: 1024, + relay_parent_storage_root: dummy_hash(), + }; + + let candidate_a = TestCandidateBuilder { + para_id: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_hash: pov_a.hash(), + head_data: parent_head_data_b.clone(), + erasure_root: make_erasure_root(&test_state, pov_a.clone(), pvd_a.clone()), + validation_code: validation_code_ab.0.clone(), + persisted_validation_data_hash: pvd_a.hash(), + } + .build(); + let candidate_b = TestCandidateBuilder { + para_id: test_state.chain_ids[0], + relay_parent: test_state.relay_parent, + pov_hash: pov_b.hash(), + head_data: output_head_data_b.clone(), + erasure_root: make_erasure_root(&test_state, pov_b.clone(), pvd_b.clone()), + validation_code: validation_code_ab.0.clone(), + persisted_validation_data_hash: pvd_b.hash(), + } + .build(); + let candidate_c = TestCandidateBuilder { + para_id: test_state.chain_ids[1], + relay_parent: test_state.relay_parent, + pov_hash: pov_c.hash(), + head_data: output_head_data_c.clone(), + erasure_root: make_erasure_root(&test_state, pov_b.clone(), pvd_c.clone()), + validation_code: validation_code_c.0.clone(), + persisted_validation_data_hash: pvd_c.hash(), + } + .build(); + let candidate_a_hash = candidate_a.hash(); + let candidate_b_hash = candidate_b.hash(); + let candidate_c_hash = candidate_c.hash(); + + // Back a chain of two candidates for the first paraid. Back one candidate for the second + // paraid. + for (candidate, pvd, validator_index) in [ + (candidate_a, pvd_a, ValidatorIndex(2)), + (candidate_b, pvd_b, ValidatorIndex(1)), + (candidate_c, pvd_c, ValidatorIndex(3)), + ] { + let public = Keystore::sr25519_generate_new( + &*test_state.keystore, + ValidatorId::ID, + Some(&test_state.validators[validator_index.0 as usize].to_seed()), + ) + .expect("Insert key into keystore"); + + let signed = SignedFullStatementWithPVD::sign( + &test_state.keystore, + StatementWithPVD::Seconded(candidate.clone(), pvd.clone()), + &test_state.signing_context, + validator_index, + &public.into(), + ) + .ok() + .flatten() + .expect("should be signed"); + + let statement = + CandidateBackingMessage::Statement(test_state.relay_parent, signed.clone()); + + virtual_overseer.send(FromOrchestra::Communication { msg: statement }).await; + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::Provisioner( + ProvisionerMessage::ProvisionableData( + _, + ProvisionableData::BackedCandidate(candidate_receipt) + ) + ) => { + assert_eq!(candidate_receipt, candidate.to_plain()); + } + ); + } + + // Happy case, all candidates should be present. + let (tx, rx) = oneshot::channel(); + let msg = CandidateBackingMessage::GetBackedCandidates( + [ + ( + test_state.chain_ids[0], + vec![ + (candidate_a_hash, test_state.relay_parent), + (candidate_b_hash, test_state.relay_parent), + ], + ), + (test_state.chain_ids[1], vec![(candidate_c_hash, test_state.relay_parent)]), + ] + .into_iter() + .collect(), + tx, + ); + virtual_overseer.send(FromOrchestra::Communication { msg }).await; + let mut candidates = rx.await.unwrap(); + assert_eq!(2, candidates.len()); + assert_eq!( + candidates + .remove(&test_state.chain_ids[0]) + .unwrap() + .iter() + .map(|c| c.hash()) + .collect::>(), + vec![candidate_a_hash, candidate_b_hash] + ); + assert_eq!( + candidates + .remove(&test_state.chain_ids[1]) + .unwrap() + .iter() + .map(|c| c.hash()) + .collect::>(), + vec![candidate_c_hash] + ); + + // The first candidate of the first para is invalid (we supply the wrong relay parent or a + // wrong candidate hash). No candidates should be returned for paraid 1. ParaId 2 should be + // fine. + for candidates in [ + vec![ + (candidate_a_hash, Hash::repeat_byte(9)), + (candidate_b_hash, test_state.relay_parent), + ], + vec![ + (CandidateHash(Hash::repeat_byte(9)), test_state.relay_parent), + (candidate_b_hash, test_state.relay_parent), + ], + ] { + let (tx, rx) = oneshot::channel(); + let msg = CandidateBackingMessage::GetBackedCandidates( + [ + (test_state.chain_ids[0], candidates), + (test_state.chain_ids[1], vec![(candidate_c_hash, test_state.relay_parent)]), + ] + .into_iter() + .collect(), + tx, + ); + virtual_overseer.send(FromOrchestra::Communication { msg }).await; + let mut candidates = rx.await.unwrap(); + assert_eq!(candidates.len(), 1); + + assert!(candidates.remove(&test_state.chain_ids[0]).is_none()); + assert_eq!( + candidates + .remove(&test_state.chain_ids[1]) + .unwrap() + .iter() + .map(|c| c.hash()) + .collect::>(), + vec![candidate_c_hash] + ); + } + + // The second candidate of the first para is invalid (we supply the wrong relay parent or a + // wrong candidate hash). The first candidate of the first para should still be present. + // ParaId 2 is fine. + for candidates in [ + vec![ + (candidate_a_hash, test_state.relay_parent), + (candidate_b_hash, Hash::repeat_byte(9)), + ], + vec![ + (candidate_a_hash, test_state.relay_parent), + (CandidateHash(Hash::repeat_byte(9)), test_state.relay_parent), + ], + ] { + let (tx, rx) = oneshot::channel(); + let msg = CandidateBackingMessage::GetBackedCandidates( + [ + (test_state.chain_ids[0], candidates), + (test_state.chain_ids[1], vec![(candidate_c_hash, test_state.relay_parent)]), + ] + .into_iter() + .collect(), + tx, + ); + virtual_overseer.send(FromOrchestra::Communication { msg }).await; + let mut candidates = rx.await.unwrap(); + assert_eq!(2, candidates.len()); + assert_eq!( + candidates + .remove(&test_state.chain_ids[0]) + .unwrap() + .iter() + .map(|c| c.hash()) + .collect::>(), + vec![candidate_a_hash] + ); + assert_eq!( + candidates + .remove(&test_state.chain_ids[1]) + .unwrap() + .iter() + .map(|c| c.hash()) + .collect::>(), + vec![candidate_c_hash] + ); + } + + // Both candidates of para id 1 are invalid (we supply the wrong relay parent or a wrong + // candidate hash). No candidates should be returned for para id 1. Para Id 2 is fine. + for candidates in [ + vec![ + (CandidateHash(Hash::repeat_byte(9)), test_state.relay_parent), + (CandidateHash(Hash::repeat_byte(10)), test_state.relay_parent), + ], + vec![ + (candidate_a_hash, Hash::repeat_byte(9)), + (candidate_b_hash, Hash::repeat_byte(10)), + ], + ] { + let (tx, rx) = oneshot::channel(); + let msg = CandidateBackingMessage::GetBackedCandidates( + [ + (test_state.chain_ids[0], candidates), + (test_state.chain_ids[1], vec![(candidate_c_hash, test_state.relay_parent)]), + ] + .into_iter() + .collect(), + tx, + ); + virtual_overseer.send(FromOrchestra::Communication { msg }).await; + let mut candidates = rx.await.unwrap(); + assert_eq!(candidates.len(), 1); + + assert!(candidates.remove(&test_state.chain_ids[0]).is_none()); + assert_eq!( + candidates + .remove(&test_state.chain_ids[1]) + .unwrap() + .iter() + .map(|c| c.hash()) + .collect::>(), + vec![candidate_c_hash] + ); + } + + virtual_overseer + .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( + ActiveLeavesUpdate::stop_work(test_state.relay_parent), + ))) + .await; + virtual_overseer + }); +} + #[test] fn extract_core_index_from_statement_works() { let test_state = TestState::default(); @@ -950,13 +1273,19 @@ fn backing_works_while_validation_ongoing() { let (tx, rx) = oneshot::channel(); let msg = CandidateBackingMessage::GetBackedCandidates( - vec![(candidate_a.hash(), test_state.relay_parent)], + std::iter::once(( + test_state.chain_ids[0], + vec![(candidate_a.hash(), test_state.relay_parent)], + )) + .collect(), tx, ); virtual_overseer.send(FromOrchestra::Communication { msg }).await; - let candidates = rx.await.unwrap(); + let mut candidates = rx.await.unwrap(); + assert_eq!(candidates.len(), 1); + let candidates = candidates.remove(&test_state.chain_ids[0]).unwrap(); assert_eq!(1, candidates.len()); assert_eq!(candidates[0].validity_votes().len(), 3); @@ -1565,7 +1894,11 @@ fn backing_works_after_failed_validation() { // and check that it is still alive. let (tx, rx) = oneshot::channel(); let msg = CandidateBackingMessage::GetBackedCandidates( - vec![(candidate.hash(), test_state.relay_parent)], + std::iter::once(( + test_state.chain_ids[0], + vec![(candidate.hash(), test_state.relay_parent)], + )) + .collect(), tx, ); diff --git a/polkadot/node/core/provisioner/src/lib.rs b/polkadot/node/core/provisioner/src/lib.rs index c9ed873d3c2..3ccf499f325 100644 --- a/polkadot/node/core/provisioner/src/lib.rs +++ b/polkadot/node/core/provisioner/src/lib.rs @@ -46,7 +46,7 @@ use polkadot_primitives::{ BackedCandidate, BlockNumber, CandidateHash, CandidateReceipt, CoreIndex, CoreState, Hash, Id as ParaId, OccupiedCoreAssumption, SessionIndex, SignedAvailabilityBitfield, ValidatorIndex, }; -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap}; mod disputes; mod error; @@ -598,13 +598,11 @@ async fn select_candidate_hashes_from_tracked( candidates: &[CandidateReceipt], relay_parent: Hash, sender: &mut impl overseer::ProvisionerSenderTrait, -) -> Result, Error> { +) -> Result>, Error> { let block_number = get_block_number_under_construction(relay_parent, sender).await?; let mut selected_candidates = - Vec::with_capacity(candidates.len().min(availability_cores.len())); - let mut selected_parachains = - HashSet::with_capacity(candidates.len().min(availability_cores.len())); + HashMap::with_capacity(candidates.len().min(availability_cores.len())); gum::debug!( target: LOG_TARGET, @@ -638,7 +636,7 @@ async fn select_candidate_hashes_from_tracked( CoreState::Free => continue, }; - if selected_parachains.contains(&scheduled_core.para_id) { + if selected_candidates.contains_key(&scheduled_core.para_id) { // We already picked a candidate for this parachain. Elastic scaling only works with // prospective parachains mode. continue @@ -677,8 +675,10 @@ async fn select_candidate_hashes_from_tracked( "Selected candidate receipt", ); - selected_parachains.insert(candidate.descriptor.para_id); - selected_candidates.push((candidate_hash, candidate.descriptor.relay_parent)); + selected_candidates.insert( + candidate.descriptor.para_id, + vec![(candidate_hash, candidate.descriptor.relay_parent)], + ); } } @@ -695,12 +695,12 @@ async fn request_backable_candidates( bitfields: &[SignedAvailabilityBitfield], relay_parent: Hash, sender: &mut impl overseer::ProvisionerSenderTrait, -) -> Result, Error> { +) -> Result>, Error> { let block_number = get_block_number_under_construction(relay_parent, sender).await?; // Record how many cores are scheduled for each paraid. Use a BTreeMap because // we'll need to iterate through them. - let mut scheduled_cores: BTreeMap = BTreeMap::new(); + let mut scheduled_cores_per_para: BTreeMap = BTreeMap::new(); // The on-chain ancestors of a para present in availability-cores. let mut ancestors: HashMap = HashMap::with_capacity(availability_cores.len()); @@ -709,7 +709,7 @@ async fn request_backable_candidates( let core_idx = CoreIndex(core_idx as u32); match core { CoreState::Scheduled(scheduled_core) => { - *scheduled_cores.entry(scheduled_core.para_id).or_insert(0) += 1; + *scheduled_cores_per_para.entry(scheduled_core.para_id).or_insert(0) += 1; }, CoreState::Occupied(occupied_core) => { let is_available = bitfields_indicate_availability( @@ -726,14 +726,14 @@ async fn request_backable_candidates( if let Some(ref scheduled_core) = occupied_core.next_up_on_available { // Request a new backable candidate for the newly scheduled para id. - *scheduled_cores.entry(scheduled_core.para_id).or_insert(0) += 1; + *scheduled_cores_per_para.entry(scheduled_core.para_id).or_insert(0) += 1; } } else if occupied_core.time_out_at <= block_number { // Timed out before being available. if let Some(ref scheduled_core) = occupied_core.next_up_on_time_out { // Candidate's availability timed out, practically same as scheduled. - *scheduled_cores.entry(scheduled_core.para_id).or_insert(0) += 1; + *scheduled_cores_per_para.entry(scheduled_core.para_id).or_insert(0) += 1; } } else { // Not timed out and not available. @@ -747,10 +747,10 @@ async fn request_backable_candidates( }; } - let mut selected_candidates: Vec<(CandidateHash, Hash)> = - Vec::with_capacity(availability_cores.len()); + let mut selected_candidates: HashMap> = + HashMap::with_capacity(scheduled_cores_per_para.len()); - for (para_id, core_count) in scheduled_cores { + for (para_id, core_count) in scheduled_cores_per_para { let para_ancestors = ancestors.remove(¶_id).unwrap_or_default(); // If elastic scaling MVP is disabled, only allow one candidate per parachain. @@ -777,7 +777,7 @@ async fn request_backable_candidates( continue } - selected_candidates.extend(response.into_iter().take(core_count)); + selected_candidates.insert(para_id, response); } Ok(selected_candidates) @@ -826,33 +826,38 @@ async fn select_candidates( selected_candidates.clone(), tx, )); - let mut candidates = rx.await.map_err(|err| Error::CanceledBackedCandidates(err))?; + let candidates = rx.await.map_err(|err| Error::CanceledBackedCandidates(err))?; gum::trace!(target: LOG_TARGET, leaf_hash=?relay_parent, "Got {} backed candidates", candidates.len()); // keep only one candidate with validation code. let mut with_validation_code = false; - candidates.retain(|c| { - if c.candidate().commitments.new_validation_code.is_some() { - if with_validation_code { - return false + // merge the candidates into a common collection, preserving the order + let mut merged_candidates = Vec::with_capacity(availability_cores.len()); + + for para_candidates in candidates.into_values() { + for candidate in para_candidates { + if candidate.candidate().commitments.new_validation_code.is_some() { + if with_validation_code { + break + } else { + with_validation_code = true; + } } - with_validation_code = true; + merged_candidates.push(candidate); } - - true - }); + } gum::debug!( target: LOG_TARGET, - n_candidates = candidates.len(), + n_candidates = merged_candidates.len(), n_cores = availability_cores.len(), ?relay_parent, "Selected backed candidates", ); - Ok(candidates) + Ok(merged_candidates) } /// Produces a block number 1 higher than that of the relay parent diff --git a/polkadot/node/core/provisioner/src/tests.rs b/polkadot/node/core/provisioner/src/tests.rs index bdb4f85f400..823b1d86e46 100644 --- a/polkadot/node/core/provisioner/src/tests.rs +++ b/polkadot/node/core/provisioner/src/tests.rs @@ -258,6 +258,8 @@ mod select_candidates { BlockNumber, CandidateCommitments, CommittedCandidateReceipt, PersistedValidationData, }; use rstest::rstest; + use std::ops::Not; + use CoreState::{Free, Scheduled}; const BLOCK_UNDER_PRODUCTION: BlockNumber = 128; @@ -323,9 +325,6 @@ mod select_candidates { // 11: Occupied(next_up_on_available and available, but different successor para_id) // ] fn mock_availability_cores_one_per_para() -> Vec { - use std::ops::Not; - use CoreState::{Free, Scheduled}; - vec![ // 0: Free, Free, @@ -389,9 +388,6 @@ mod select_candidates { // For test purposes with multiple possible cores assigned to a para, we always return this set // of availability cores: fn mock_availability_cores_multiple_per_para() -> Vec { - use std::ops::Not; - use CoreState::{Free, Scheduled}; - vec![ // 0: Free, Free, @@ -562,7 +558,10 @@ mod select_candidates { use ChainApiMessage::BlockNumber; use RuntimeApiMessage::Request; - let mut backed_iter = expected.clone().into_iter(); + let mut backed = expected.clone().into_iter().fold(HashMap::new(), |mut acc, candidate| { + acc.entry(candidate.descriptor().para_id).or_insert(vec![]).push(candidate); + acc + }); expected.sort_by_key(|c| c.candidate().descriptor.para_id); let mut candidates_iter = expected @@ -583,11 +582,30 @@ mod select_candidates { hashes, sender, )) => { - let response: Vec = - backed_iter.by_ref().take(hashes.len()).collect(); - let expected_hashes: Vec<(CandidateHash, Hash)> = response + let mut response: HashMap> = HashMap::new(); + for (para_id, requested_candidates) in hashes.clone() { + response.insert( + para_id, + backed + .get_mut(¶_id) + .unwrap() + .drain(0..requested_candidates.len()) + .collect(), + ); + } + let expected_hashes: HashMap> = response .iter() - .map(|candidate| (candidate.hash(), candidate.descriptor().relay_parent)) + .map(|(para_id, candidates)| { + ( + *para_id, + candidates + .iter() + .map(|candidate| { + (candidate.hash(), candidate.descriptor().relay_parent) + }) + .collect(), + ) + }) .collect(); assert_eq!(expected_hashes, hashes); @@ -768,7 +786,7 @@ mod select_candidates { #[rstest] #[case(ProspectiveParachainsMode::Disabled)] #[case(ProspectiveParachainsMode::Enabled {max_candidate_depth: 0, allowed_ancestry_len: 0})] - fn selects_max_one_code_upgrade( + fn selects_max_one_code_upgrade_one_core_per_para( #[case] prospective_parachains_mode: ProspectiveParachainsMode, ) { let mock_cores = mock_availability_cores_one_per_para(); @@ -780,7 +798,12 @@ mod select_candidates { let cores = [1, 4, 7, 8, 10, 12]; let cores_with_code = [1, 4, 8]; - let expected_cores = [1, 7, 10, 12]; + // We can't be sure which one code upgrade the provisioner will pick. We can only assert + // that it only picks one. These are the possible cores for which the provisioner will + // supply candidates. + // There are multiple possibilities depending on which code upgrade it + // chooses. + let possible_expected_cores = [[1, 7, 10, 12], [4, 7, 10, 12], [7, 8, 10, 12]]; let committed_receipts: Vec<_> = (0..=mock_cores.len()) .map(|i| { @@ -820,8 +843,10 @@ mod select_candidates { // Then, some of them get filtered due to new validation code rule. let expected_backed: Vec<_> = cores.iter().map(|&idx| backed_candidates[idx].clone()).collect(); - let expected_backed_filtered: Vec<_> = - expected_cores.iter().map(|&idx| candidates[idx].clone()).collect(); + let expected_backed_filtered: Vec> = possible_expected_cores + .iter() + .map(|indices| indices.iter().map(|&idx| candidates[idx].clone()).collect()) + .collect(); let mock_cores_clone = mock_cores.clone(); @@ -850,13 +875,120 @@ mod select_candidates { assert_eq!(result.len(), 4); - result.into_iter().for_each(|c| { - assert!( - expected_backed_filtered.iter().any(|c2| c.candidate().corresponds_to(c2)), - "Failed to find candidate: {:?}", - c, - ) - }); + assert!(expected_backed_filtered.iter().any(|expected_backed_filtered| { + result.clone().into_iter().all(|c| { + expected_backed_filtered.iter().any(|c2| c.candidate().corresponds_to(c2)) + }) + })); + }, + ) + } + + #[test] + fn selects_max_one_code_upgrade_multiple_cores_per_para() { + let prospective_parachains_mode = + ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; + let mock_cores = vec![ + // 0: Scheduled(default), + Scheduled(scheduled_core(1)), + // 1: Scheduled(default), + Scheduled(scheduled_core(2)), + // 2: Scheduled(default), + Scheduled(scheduled_core(2)), + // 3: Scheduled(default), + Scheduled(scheduled_core(2)), + // 4: Scheduled(default), + Scheduled(scheduled_core(3)), + // 5: Scheduled(default), + Scheduled(scheduled_core(3)), + // 6: Scheduled(default), + Scheduled(scheduled_core(3)), + ]; + + let empty_hash = PersistedValidationData::::default().hash(); + let cores_with_code = [0, 2, 4, 5]; + + // We can't be sure which one code upgrade the provisioner will pick. We can only assert + // that it only picks one. + // These are the possible cores for which the provisioner will + // supply candidates. There are multiple possibilities depending on which code upgrade it + // chooses. + let possible_expected_cores = [vec![0, 1], vec![1, 2, 3], vec![4, 1]]; + + let committed_receipts: Vec<_> = (0..mock_cores.len()) + .map(|i| { + let mut descriptor = dummy_candidate_descriptor(dummy_hash()); + descriptor.para_id = mock_cores[i].para_id().unwrap(); + descriptor.persisted_validation_data_hash = empty_hash; + descriptor.pov_hash = Hash::from_low_u64_be(i as u64); + CommittedCandidateReceipt { + descriptor, + commitments: CandidateCommitments { + new_validation_code: if cores_with_code.contains(&i) { + Some(vec![].into()) + } else { + None + }, + ..Default::default() + }, + } + }) + .collect(); + + // Input to select_candidates + let candidates: Vec<_> = committed_receipts.iter().map(|r| r.to_plain()).collect(); + // Build possible outputs from select_candidates + let backed_candidates: Vec<_> = committed_receipts + .iter() + .map(|committed_receipt| { + BackedCandidate::new( + committed_receipt.clone(), + Vec::new(), + default_bitvec(MOCK_GROUP_SIZE), + None, + ) + }) + .collect(); + + // First, provisioner will request backable candidates for each scheduled core. + // Then, some of them get filtered due to new validation code rule. + let expected_backed: Vec<_> = + (0..mock_cores.len()).map(|idx| backed_candidates[idx].clone()).collect(); + let expected_backed_filtered: Vec> = possible_expected_cores + .iter() + .map(|indices| indices.iter().map(|&idx| candidates[idx].clone()).collect()) + .collect(); + + let mock_cores_clone = mock_cores.clone(); + + test_harness( + |r| { + mock_overseer( + r, + mock_cores_clone, + expected_backed, + HashMap::new(), + prospective_parachains_mode, + ) + }, + |mut tx: TestSubsystemSender| async move { + let result = select_candidates( + &mock_cores, + &[], + &candidates, + prospective_parachains_mode, + true, + Default::default(), + &mut tx, + ) + .await + .unwrap(); + + assert!(expected_backed_filtered.iter().any(|expected_backed_filtered| { + result.clone().into_iter().all(|c| { + expected_backed_filtered.iter().any(|c2| c.candidate().corresponds_to(c2)) + }) && (expected_backed_filtered.len() == result.len()) + })); }, ) } diff --git a/polkadot/node/overseer/src/tests.rs b/polkadot/node/overseer/src/tests.rs index 0494274367d..55a6bdb74ba 100644 --- a/polkadot/node/overseer/src/tests.rs +++ b/polkadot/node/overseer/src/tests.rs @@ -811,7 +811,7 @@ fn test_candidate_validation_msg() -> CandidateValidationMessage { fn test_candidate_backing_msg() -> CandidateBackingMessage { let (sender, _) = oneshot::channel(); - CandidateBackingMessage::GetBackedCandidates(Vec::new(), sender) + CandidateBackingMessage::GetBackedCandidates(Default::default(), sender) } fn test_chain_api_msg() -> ChainApiMessage { diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 5115efa853c..92c35d1b7b9 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -82,8 +82,15 @@ pub struct CanSecondRequest { pub enum CandidateBackingMessage { /// Requests a set of backable candidates attested by the subsystem. /// - /// Each pair is (candidate_hash, candidate_relay_parent). - GetBackedCandidates(Vec<(CandidateHash, Hash)>, oneshot::Sender>), + /// The order of candidates of the same para must be preserved in the response. + /// If a backed candidate of a para cannot be retrieved, the response should not contain any + /// candidates of the same para that follow it in the input vector. In other words, assuming + /// candidates are supplied in dependency order, we must ensure that this dependency order is + /// preserved. + GetBackedCandidates( + HashMap>, + oneshot::Sender>>, + ), /// Request the subsystem to check whether it's allowed to second given candidate. /// The rule is to only fetch collations that are either built on top of the root /// of some fragment tree or have a parent node which represents backed candidate. diff --git a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md index 54cdc2edd12..acfe309ba7b 100644 --- a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md +++ b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md @@ -340,9 +340,15 @@ enum BitfieldSigningMessage { } ```rust enum CandidateBackingMessage { /// Requests a set of backable candidates attested by the subsystem. - /// - /// Each pair is (candidate_hash, candidate_relay_parent). - GetBackedCandidates(Vec<(CandidateHash, Hash)>, oneshot::Sender>), + /// The order of candidates of the same para must be preserved in the response. + /// If a backed candidate of a para cannot be retrieved, the response should not contain any + /// candidates of the same para that follow it in the input vector. In other words, assuming + /// candidates are supplied in dependency order, we must ensure that this dependency order is + /// preserved. + GetBackedCandidates( + HashMap>, + oneshot::Sender>>, + ), /// Note that the Candidate Backing subsystem should second the given candidate in the context of the /// given relay-parent (ref. by hash). This candidate must be validated using the provided PoV. /// The PoV is expected to match the `pov_hash` in the descriptor. -- GitLab From ce7613a49ff15652c6b33927f2ac64a64ba09783 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 25 Mar 2024 16:24:58 +0200 Subject: [PATCH 172/188] =?UTF-8?q?[prdoc]=C2=A0Remove=20default=20audienc?= =?UTF-8?q?e=20(#3723)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Devs seem to not realize that this should be filled out manually. The default is also often wrong. --- prdoc/.template.prdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prdoc/.template.prdoc b/prdoc/.template.prdoc index 097741f388c..03a458876df 100644 --- a/prdoc/.template.prdoc +++ b/prdoc/.template.prdoc @@ -4,7 +4,7 @@ title: ... doc: - - audience: Node Dev + - audience: ... description: | ... -- GitLab From 9d122401f1d434235dfc08ee0509ab6e921bb286 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Mon, 25 Mar 2024 15:26:38 +0000 Subject: [PATCH 173/188] Refactor crypto-related traits implementations in term of Public/Signature Bytes (#3806) Another simple refactory to prune some duplicate code Follow up of: https://github.com/paritytech/polkadot-sdk/pull/3684 --- .../primitives/application-crypto/src/lib.rs | 14 +- substrate/primitives/core/src/bandersnatch.rs | 55 +------ substrate/primitives/core/src/bls.rs | 111 +------------ substrate/primitives/core/src/crypto.rs | 115 ++++--------- substrate/primitives/core/src/crypto_bytes.rs | 153 ++++++++++++++++-- substrate/primitives/core/src/ecdsa.rs | 92 +---------- substrate/primitives/core/src/ed25519.rs | 111 +------------ substrate/primitives/core/src/lib.rs | 20 +-- .../primitives/core/src/paired_crypto.rs | 144 +---------------- substrate/primitives/core/src/sr25519.rs | 95 ++++------- .../primitives/statement-store/src/ecies.rs | 2 +- 11 files changed, 254 insertions(+), 658 deletions(-) diff --git a/substrate/primitives/application-crypto/src/lib.rs b/substrate/primitives/application-crypto/src/lib.rs index ea2e5a83127..2355f1ba527 100644 --- a/substrate/primitives/application-crypto/src/lib.rs +++ b/substrate/primitives/application-crypto/src/lib.rs @@ -26,7 +26,7 @@ pub use sp_core::crypto::{DeriveError, Pair, SecretStringError}; #[doc(hidden)] pub use sp_core::{ self, - crypto::{ByteArray, CryptoType, Derive, IsWrappedBy, Public, UncheckedFrom, Wraps}, + crypto::{ByteArray, CryptoType, Derive, IsWrappedBy, Public, Signature, UncheckedFrom, Wraps}, RuntimeDebug, }; @@ -505,6 +505,12 @@ macro_rules! app_crypto_signature_common { } } + impl AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } + } + impl $crate::AppSignature for Signature { type Generic = $sig; } @@ -525,6 +531,12 @@ macro_rules! app_crypto_signature_common { } } + impl $crate::Signature for Signature {} + + impl $crate::ByteArray for Signature { + const LEN: usize = <$sig>::LEN; + } + impl Signature { /// Convert into wrapped generic signature type. pub fn into_inner(self) -> $sig { diff --git a/substrate/primitives/core/src/bandersnatch.rs b/substrate/primitives/core/src/bandersnatch.rs index c9d5f27b47b..42c8b293634 100644 --- a/substrate/primitives/core/src/bandersnatch.rs +++ b/substrate/primitives/core/src/bandersnatch.rs @@ -20,19 +20,12 @@ //! //! The primitive can operate both as a regular VRF or as an anonymized Ring VRF. -#[cfg(feature = "serde")] -use crate::crypto::Ss58Codec; #[cfg(feature = "full_crypto")] use crate::crypto::VrfSecret; use crate::crypto::{ - ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, - VrfPublic, + ByteArray, CryptoType, CryptoTypeId, DeriveError, DeriveJunction, Pair as TraitPair, + PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, VrfPublic, }; -#[cfg(feature = "serde")] -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(all(not(feature = "std"), feature = "serde"))] -use sp_std::alloc::{format, string::String}; use bandersnatch_vrfs::{CanonicalSerialize, SecretKey}; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; @@ -64,42 +57,10 @@ pub struct BandersnatchTag; /// Bandersnatch public key. pub type Public = PublicBytes; -impl TraitPublic for Public {} - impl CryptoType for Public { type Pair = Pair; } -impl Derive for Public {} - -impl sp_std::fmt::Debug for Public { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.as_ref()), &s[0..8]) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "serde")] -impl Serialize for Public { - fn serialize(&self, serializer: S) -> Result { - serializer.serialize_str(&self.to_ss58check()) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Public { - fn deserialize>(deserializer: D) -> Result { - Public::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - /// Bandersnatch signature. /// /// The signature is created via the [`VrfSecret::vrf_sign`] using [`SIGNING_CTX`] as transcript @@ -110,18 +71,6 @@ impl CryptoType for Signature { type Pair = Pair; } -impl sp_std::fmt::Debug for Signature { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - /// The raw secret seed, which can be used to reconstruct the secret [`Pair`]. type Seed = [u8; SEED_SERIALIZED_SIZE]; diff --git a/substrate/primitives/core/src/bls.rs b/substrate/primitives/core/src/bls.rs index 9492a14ff0d..bb04babb3f1 100644 --- a/substrate/primitives/core/src/bls.rs +++ b/substrate/primitives/core/src/bls.rs @@ -23,17 +23,11 @@ //! Chaum-Pedersen proof uses the same hash-to-field specified in RFC 9380 for the field of the BLS //! curve. -#[cfg(feature = "serde")] -use crate::crypto::Ss58Codec; use crate::crypto::{ - CryptoType, Derive, DeriveError, DeriveJunction, Pair as TraitPair, Public as TraitPublic, - PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, + CryptoType, DeriveError, DeriveJunction, Pair as TraitPair, PublicBytes, SecretStringError, + SignatureBytes, UncheckedFrom, }; -#[cfg(feature = "serde")] -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(all(not(feature = "std"), feature = "serde"))] -use sp_std::alloc::{format, string::String}; use sp_std::vec::Vec; use w3f_bls::{ @@ -115,68 +109,6 @@ pub struct BlsTag; /// A public key. pub type Public = PublicBytes; -impl From> for Public { - fn from(x: Pair) -> Self { - x.public() - } -} - -#[cfg(feature = "std")] -impl std::str::FromStr for Public { - type Err = crate::crypto::PublicError; - - fn from_str(s: &str) -> Result { - Self::from_ss58check(s) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } -} - -#[cfg(feature = "std")] -impl sp_std::fmt::Debug for Public { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } -} - -#[cfg(not(feature = "std"))] -impl sp_std::fmt::Debug for Public { - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "serde")] -impl Serialize for Public { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&self.to_ss58check()) - } -} - -#[cfg(feature = "serde")] -impl<'de, T: BlsBound> Deserialize<'de> for Public { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Public::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - -impl TraitPublic for Public {} - -impl Derive for Public {} - impl CryptoType for Public { type Pair = Pair; } @@ -184,41 +116,6 @@ impl CryptoType for Public { /// A generic BLS signature. pub type Signature = SignatureBytes; -#[cfg(feature = "serde")] -impl Serialize for Signature { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&array_bytes::bytes2hex("", self)) - } -} - -#[cfg(feature = "serde")] -impl<'de, T> Deserialize<'de> for Signature { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let signature_hex = array_bytes::hex2bytes(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e)))?; - Signature::try_from(signature_hex.as_ref()) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - -impl sp_std::fmt::Debug for Signature { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - impl CryptoType for Signature { type Pair = Pair; } @@ -333,8 +230,10 @@ impl CryptoType for Pair { // Test set exercising the BLS12-377 implementation #[cfg(test)] -mod test { +mod tests { use super::*; + #[cfg(feature = "serde")] + use crate::crypto::Ss58Codec; use crate::crypto::DEV_PHRASE; use bls377::{Pair, Signature}; diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs index a2bdc6ed58e..b13899fff51 100644 --- a/substrate/primitives/core/src/crypto.rs +++ b/substrate/primitives/core/src/crypto.rs @@ -485,8 +485,11 @@ pub trait ByteArray: AsRef<[u8]> + AsMut<[u8]> + for<'a> TryFrom<&'a [u8], Error } } -/// Trait suitable for typical cryptographic key public type. -pub trait Public: CryptoType + ByteArray + Derive + PartialEq + Eq + Clone + Send + Sync {} +/// Trait suitable for cryptographic public keys. +pub trait Public: CryptoType + ByteArray + PartialEq + Eq + Clone + Send + Sync + Derive {} + +/// Trait suitable for cryptographic signatures. +pub trait Signature: CryptoType + ByteArray + PartialEq + Eq + Clone + Send + Sync {} /// An opaque 32-byte cryptographic identifier. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, TypeInfo)] @@ -648,32 +651,11 @@ pub use self::dummy::*; mod dummy { use super::*; - /// Dummy cryptography. Doesn't do anything. - #[derive(Clone, Hash, Default, Eq, PartialEq)] - pub struct Dummy; - - impl AsRef<[u8]> for Dummy { - fn as_ref(&self) -> &[u8] { - &b""[..] - } - } + #[doc(hidden)] + pub struct DummyTag; - impl AsMut<[u8]> for Dummy { - fn as_mut(&mut self) -> &mut [u8] { - unsafe { - #[allow(mutable_transmutes)] - sp_std::mem::transmute::<_, &'static mut [u8]>(&b""[..]) - } - } - } - - impl<'a> TryFrom<&'a [u8]> for Dummy { - type Error = (); - - fn try_from(_: &'a [u8]) -> Result { - Ok(Self) - } - } + /// Dummy cryptography. Doesn't do anything. + pub type Dummy = CryptoBytes<0, DummyTag>; impl CryptoType for Dummy { type Pair = Dummy; @@ -681,21 +663,10 @@ mod dummy { impl Derive for Dummy {} - impl ByteArray for Dummy { - const LEN: usize = 0; - fn from_slice(_: &[u8]) -> Result { - Ok(Self) - } - #[cfg(feature = "std")] - fn to_raw_vec(&self) -> Vec { - vec![] - } - fn as_slice(&self) -> &[u8] { - b"" - } - } impl Public for Dummy {} + impl Signature for Dummy {} + impl Pair for Dummy { type Public = Dummy; type Seed = Dummy; @@ -716,15 +687,15 @@ mod dummy { _: Iter, _: Option, ) -> Result<(Self, Option), DeriveError> { - Ok((Self, None)) + Ok((Self::default(), None)) } fn from_seed_slice(_: &[u8]) -> Result { - Ok(Self) + Ok(Self::default()) } fn sign(&self, _: &[u8]) -> Self::Signature { - Self + Self::default() } fn verify>(_: &Self::Signature, _: M, _: &Self::Public) -> bool { @@ -732,11 +703,11 @@ mod dummy { } fn public(&self) -> Self::Public { - Self + Self::default() } fn to_raw_vec(&self) -> Vec { - vec![] + Default::default() } } } @@ -845,7 +816,7 @@ pub trait Pair: CryptoType + Sized { /// The type used to represent a signature. Can be created from a key pair and a message /// and verified with the message and a public key. - type Signature: AsRef<[u8]>; + type Signature: Signature; /// Generate new secure (random) key pair. /// @@ -1218,6 +1189,8 @@ mod tests { use super::*; use crate::DeriveJunction; + struct TestCryptoTag; + #[derive(Clone, Eq, PartialEq, Debug)] enum TestPair { Generated, @@ -1226,59 +1199,33 @@ mod tests { Standard { phrase: String, password: Option, path: Vec }, Seed(Vec), } + impl Default for TestPair { fn default() -> Self { TestPair::Generated } } + impl CryptoType for TestPair { type Pair = Self; } - #[derive(Clone, PartialEq, Eq, Hash, Default)] - struct TestPublic; - impl AsRef<[u8]> for TestPublic { - fn as_ref(&self) -> &[u8] { - &[] - } - } - impl AsMut<[u8]> for TestPublic { - fn as_mut(&mut self) -> &mut [u8] { - &mut [] - } - } - impl<'a> TryFrom<&'a [u8]> for TestPublic { - type Error = (); + type TestPublic = PublicBytes<0, TestCryptoTag>; - fn try_from(data: &'a [u8]) -> Result { - Self::from_slice(data) - } - } impl CryptoType for TestPublic { type Pair = TestPair; } - impl Derive for TestPublic {} - impl ByteArray for TestPublic { - const LEN: usize = 0; - fn from_slice(bytes: &[u8]) -> Result { - if bytes.is_empty() { - Ok(Self) - } else { - Err(()) - } - } - fn as_slice(&self) -> &[u8] { - &[] - } - fn to_raw_vec(&self) -> Vec { - vec![] - } + + type TestSignature = SignatureBytes<0, TestCryptoTag>; + + impl CryptoType for TestSignature { + type Pair = TestPair; } - impl Public for TestPublic {} + impl Pair for TestPair { type Public = TestPublic; type Seed = [u8; 8]; - type Signature = [u8; 0]; + type Signature = TestSignature; fn generate() -> (Self, ::Seed) { (TestPair::Generated, [0u8; 8]) @@ -1327,7 +1274,7 @@ mod tests { } fn sign(&self, _message: &[u8]) -> Self::Signature { - [] + TestSignature::default() } fn verify>(_: &Self::Signature, _: M, _: &Self::Public) -> bool { @@ -1335,7 +1282,7 @@ mod tests { } fn public(&self) -> Self::Public { - TestPublic + TestPublic::default() } fn from_seed_slice(seed: &[u8]) -> Result { diff --git a/substrate/primitives/core/src/crypto_bytes.rs b/substrate/primitives/core/src/crypto_bytes.rs index 069878e1654..ee5f3482f74 100644 --- a/substrate/primitives/core/src/crypto_bytes.rs +++ b/substrate/primitives/core/src/crypto_bytes.rs @@ -18,15 +18,27 @@ //! Generic byte array which can be specialized with a marker type. use crate::{ - crypto::{FromEntropy, UncheckedFrom}, + crypto::{CryptoType, Derive, FromEntropy, Public, Signature, UncheckedFrom}, hash::{H256, H512}, }; use codec::{Decode, Encode, MaxEncodedLen}; use core::marker::PhantomData; use scale_info::TypeInfo; + use sp_runtime_interface::pass_by::{self, PassBy, PassByInner}; +#[cfg(feature = "serde")] +use crate::crypto::Ss58Codec; +#[cfg(feature = "serde")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +#[cfg(all(not(feature = "std"), feature = "serde"))] +use sp_std::alloc::{format, string::String}; + +pub use public_bytes::*; +pub use signature_bytes::*; + /// Generic byte array holding some crypto-related raw data. /// /// The type is generic over a constant length `N` and a "tag" `T` which @@ -231,14 +243,137 @@ impl CryptoBytes<64, T> { } } -/// Tag used for generic public key bytes. -pub struct PublicTag; +mod public_bytes { + use super::*; + + /// Tag used for generic public key bytes. + pub struct PublicTag; + + /// Generic encoded public key. + pub type PublicBytes = CryptoBytes; + + impl Derive for PublicBytes where Self: CryptoType {} + + impl Public for PublicBytes where Self: CryptoType {} + + impl sp_std::fmt::Debug for PublicBytes + where + Self: CryptoType, + { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.as_ref()), &s[0..8]) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } + } + + #[cfg(feature = "std")] + impl std::fmt::Display for PublicBytes + where + Self: CryptoType, + { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } + } + + #[cfg(feature = "std")] + impl std::str::FromStr for PublicBytes + where + Self: CryptoType, + { + type Err = crate::crypto::PublicError; + + fn from_str(s: &str) -> Result { + Self::from_ss58check(s) + } + } + + #[cfg(feature = "serde")] + impl Serialize for PublicBytes + where + Self: CryptoType, + { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_ss58check()) + } + } + + #[cfg(feature = "serde")] + impl<'de, const N: usize, SubTag> Deserialize<'de> for PublicBytes + where + Self: CryptoType, + { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Self::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } + } +} + +mod signature_bytes { + use super::*; + + /// Tag used for generic signature bytes. + pub struct SignatureTag; + + /// Generic encoded signature. + pub type SignatureBytes = CryptoBytes; -/// Generic encoded public key. -pub type PublicBytes = CryptoBytes; + impl Signature for SignatureBytes where Self: CryptoType {} -/// Tag used for generic signature bytes. -pub struct SignatureTag; + #[cfg(feature = "serde")] + impl Serialize for SignatureBytes + where + Self: CryptoType, + { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&array_bytes::bytes2hex("", self)) + } + } + + #[cfg(feature = "serde")] + impl<'de, const N: usize, SubTag> Deserialize<'de> for SignatureBytes + where + Self: CryptoType, + { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let signature_hex = array_bytes::hex2bytes(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + Self::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } + } -/// Generic encoded signature. -pub type SignatureBytes = CryptoBytes; + impl sp_std::fmt::Debug for SignatureBytes + where + Self: CryptoType, + { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&&self.0[..])) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } + } +} diff --git a/substrate/primitives/core/src/ecdsa.rs b/substrate/primitives/core/src/ecdsa.rs index 0e6b06a34dc..9cba8cc3d35 100644 --- a/substrate/primitives/core/src/ecdsa.rs +++ b/substrate/primitives/core/src/ecdsa.rs @@ -17,11 +17,9 @@ //! Simple ECDSA secp256k1 API. -#[cfg(feature = "serde")] -use crate::crypto::Ss58Codec; use crate::crypto::{ - CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, + CryptoType, CryptoTypeId, DeriveError, DeriveJunction, Pair as TraitPair, PublicBytes, + SecretStringError, SignatureBytes, }; #[cfg(not(feature = "std"))] @@ -31,10 +29,6 @@ use secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, Message, PublicKey, SecretKey, SECP256K1, }; -#[cfg(feature = "serde")] -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(all(not(feature = "std"), feature = "serde"))] -use sp_std::alloc::{format, string::String}; #[cfg(not(feature = "std"))] use sp_std::vec::Vec; @@ -80,10 +74,6 @@ impl Public { } } -impl TraitPublic for Public {} - -impl Derive for Public {} - #[cfg(feature = "std")] impl From for Public { fn from(pubkey: PublicKey) -> Self { @@ -106,85 +96,9 @@ impl From for Public { } } -#[cfg(feature = "std")] -impl std::fmt::Display for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } -} - -impl sp_std::fmt::Debug for Public { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.as_ref()), &s[0..8]) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "serde")] -impl Serialize for Public { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&self.to_ss58check()) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Public { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Public::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - /// A signature (a 512-bit value, plus 8 bits for recovery ID). pub type Signature = SignatureBytes; -#[cfg(feature = "serde")] -impl Serialize for Signature { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&array_bytes::bytes2hex("", self)) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Signature { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let signature_hex = array_bytes::hex2bytes(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e)))?; - Signature::try_from(signature_hex.as_ref()) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - -impl sp_std::fmt::Debug for Signature { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - impl Signature { /// Recover the public key from this signature and a message. pub fn recover>(&self, message: M) -> Option { @@ -417,7 +331,7 @@ mod test { use super::*; use crate::crypto::{ set_default_ss58_version, PublicError, Ss58AddressFormat, Ss58AddressFormatRegistry, - DEV_PHRASE, + Ss58Codec, DEV_PHRASE, }; use serde_json; diff --git a/substrate/primitives/core/src/ed25519.rs b/substrate/primitives/core/src/ed25519.rs index 0dda7b95972..a9494f2860b 100644 --- a/substrate/primitives/core/src/ed25519.rs +++ b/substrate/primitives/core/src/ed25519.rs @@ -17,18 +17,13 @@ //! Simple Ed25519 API. -#[cfg(feature = "serde")] -use crate::crypto::Ss58Codec; use crate::crypto::{ - ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, + ByteArray, CryptoType, CryptoTypeId, DeriveError, DeriveJunction, Pair as TraitPair, + PublicBytes, SecretStringError, SignatureBytes, }; use ed25519_zebra::{SigningKey, VerificationKey}; -#[cfg(feature = "serde")] -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(all(not(feature = "std"), feature = "serde"))] -use sp_std::alloc::{format, string::String}; + use sp_std::vec::Vec; /// An identifier used to match public keys against ed25519 keys @@ -51,105 +46,9 @@ pub struct Ed25519Tag; /// A public key. pub type Public = PublicBytes; -impl TraitPublic for Public {} - -impl Derive for Public {} - -#[cfg(feature = "full_crypto")] -impl From for Public { - fn from(x: Pair) -> Self { - x.public() - } -} - -#[cfg(feature = "std")] -impl std::str::FromStr for Public { - type Err = crate::crypto::PublicError; - - fn from_str(s: &str) -> Result { - Self::from_ss58check(s) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } -} - -impl sp_std::fmt::Debug for Public { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "serde")] -impl Serialize for Public { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&self.to_ss58check()) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Public { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Public::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - /// A signature. pub type Signature = SignatureBytes; -#[cfg(feature = "serde")] -impl Serialize for Signature { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&array_bytes::bytes2hex("", self)) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Signature { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let signature_hex = array_bytes::hex2bytes(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e)))?; - Signature::try_from(signature_hex.as_ref()) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - -impl sp_std::fmt::Debug for Signature { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - /// A key pair. #[derive(Copy, Clone)] pub struct Pair { @@ -253,8 +152,10 @@ impl CryptoType for Pair { } #[cfg(test)] -mod test { +mod tests { use super::*; + #[cfg(feature = "serde")] + use crate::crypto::Ss58Codec; use crate::crypto::DEV_PHRASE; use serde_json; diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs index cf803c6fb49..098bd135bfe 100644 --- a/substrate/primitives/core/src/lib.rs +++ b/substrate/primitives/core/src/lib.rs @@ -56,27 +56,27 @@ pub mod const_hex2array; pub mod crypto; pub mod hexdisplay; pub use paste; - mod address_uri; -#[cfg(feature = "bandersnatch-experimental")] -pub mod bandersnatch; -#[cfg(feature = "bls-experimental")] -pub mod bls; -pub mod crypto_bytes; pub mod defer; -pub mod ecdsa; -pub mod ed25519; pub mod hash; #[cfg(feature = "std")] mod hasher; pub mod offchain; -pub mod paired_crypto; -pub mod sr25519; pub mod testing; #[cfg(feature = "std")] pub mod traits; pub mod uint; +#[cfg(feature = "bandersnatch-experimental")] +pub mod bandersnatch; +#[cfg(feature = "bls-experimental")] +pub mod bls; +pub mod crypto_bytes; +pub mod ecdsa; +pub mod ed25519; +pub mod paired_crypto; +pub mod sr25519; + #[cfg(feature = "bls-experimental")] pub use bls::{bls377, bls381}; #[cfg(feature = "bls-experimental")] diff --git a/substrate/primitives/core/src/paired_crypto.rs b/substrate/primitives/core/src/paired_crypto.rs index 27a7ab28dfd..3901846b375 100644 --- a/substrate/primitives/core/src/paired_crypto.rs +++ b/substrate/primitives/core/src/paired_crypto.rs @@ -19,20 +19,13 @@ use core::marker::PhantomData; -#[cfg(feature = "serde")] -use crate::crypto::Ss58Codec; use crate::crypto::{ - ByteArray, CryptoType, Derive, DeriveError, DeriveJunction, Pair as PairT, Public as PublicT, - PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, + ByteArray, CryptoType, DeriveError, DeriveJunction, Pair as PairT, Public as PublicT, + PublicBytes, SecretStringError, Signature as SignatureT, SignatureBytes, UncheckedFrom, }; use sp_std::vec::Vec; -#[cfg(feature = "serde")] -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(all(not(feature = "std"), feature = "serde"))] -use sp_std::alloc::{format, string::String}; - /// ECDSA and BLS12-377 paired crypto scheme #[cfg(feature = "bls-experimental")] pub mod ecdsa_bls377 { @@ -173,130 +166,10 @@ where } } -#[cfg(feature = "std")] -impl std::fmt::Display - for Public -where - Public: CryptoType, -{ - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } -} - -impl sp_std::fmt::Debug - for Public -where - Public: CryptoType, - [u8; LEFT_PLUS_RIGHT_LEN]: crate::hexdisplay::AsBytesRef, -{ - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "serde")] -impl Serialize - for Public -where - Public: CryptoType, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&self.to_ss58check()) - } -} - -#[cfg(feature = "serde")] -impl<'de, const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> Deserialize<'de> - for Public -where - Public: CryptoType, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Public::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - -impl PublicT - for Public -where - Public: CryptoType, -{ -} - -impl Derive - for Public -{ -} - -/// Trait characterizing a signature which could be used as individual component of an -/// `paired_crypto:Signature` pair. -pub trait SignatureBound: ByteArray {} - -impl SignatureBound for T {} - /// A pair of signatures of different types pub type Signature = SignatureBytes; -#[cfg(feature = "serde")] -impl Serialize - for Signature -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&array_bytes::bytes2hex("", self)) - } -} - -#[cfg(feature = "serde")] -impl<'de, const LEFT_PLUS_RIGHT_LEN: usize, SubTag> Deserialize<'de> - for Signature -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let bytes = array_bytes::hex2bytes(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e)))?; - Signature::::try_from(bytes.as_ref()).map_err(|e| { - de::Error::custom(format!("Error converting deserialized data into signature: {:?}", e)) - }) - } -} - -impl sp_std::fmt::Debug - for Signature -where - [u8; LEFT_PLUS_RIGHT_LEN]: crate::hexdisplay::AsBytesRef, -{ - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - /// A key pair. pub struct Pair< LeftPair: PairT, @@ -332,9 +205,8 @@ impl< > PairT for Pair where Pair: CryptoType, - LeftPair::Signature: SignatureBound, - RightPair::Signature: SignatureBound, - Public: CryptoType, + Public: PublicT, + Signature: SignatureT, LeftPair::Seed: From + Into, RightPair::Seed: From + Into, { @@ -417,14 +289,14 @@ where // Test set exercising the (ECDSA,BLS12-377) implementation #[cfg(all(test, feature = "bls-experimental"))] -mod test { +mod tests { use super::*; - use crate::{crypto::DEV_PHRASE, KeccakHasher}; + #[cfg(feature = "serde")] + use crate::crypto::Ss58Codec; + use crate::{bls377, crypto::DEV_PHRASE, ecdsa, KeccakHasher}; use codec::{Decode, Encode}; use ecdsa_bls377::{Pair, Signature}; - use crate::{bls377, ecdsa}; - #[test] fn test_length_of_paired_ecdsa_and_bls377_public_key_and_signature_is_correct() { assert_eq!( diff --git a/substrate/primitives/core/src/sr25519.rs b/substrate/primitives/core/src/sr25519.rs index ee0546bc534..54b9a98db3d 100644 --- a/substrate/primitives/core/src/sr25519.rs +++ b/substrate/primitives/core/src/sr25519.rs @@ -22,7 +22,9 @@ #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; -use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; +use crate::crypto::{ + CryptoBytes, DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError, +}; #[cfg(feature = "full_crypto")] use schnorrkel::signing_context; use schnorrkel::{ @@ -31,9 +33,7 @@ use schnorrkel::{ }; use sp_std::vec::Vec; -use crate::crypto::{ - CryptoType, CryptoTypeId, Derive, Public as TraitPublic, PublicBytes, SignatureBytes, -}; +use crate::crypto::{CryptoType, CryptoTypeId, Derive, Public as TraitPublic, SignatureBytes}; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -59,20 +59,28 @@ pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; #[doc(hidden)] pub struct Sr25519Tag; +#[doc(hidden)] +pub struct Sr25519PublicTag; /// An Schnorrkel/Ristretto x25519 ("sr25519") public key. -pub type Public = PublicBytes; +pub type Public = CryptoBytes; -/// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. -pub struct Pair(Keypair); +impl TraitPublic for Public {} -impl Clone for Pair { - fn clone(&self) -> Self { - Pair(schnorrkel::Keypair { - public: self.0.public, - secret: schnorrkel::SecretKey::from_bytes(&self.0.secret.to_bytes()[..]) - .expect("key is always the correct size; qed"), - }) +impl Derive for Public { + /// Derive a child key from a series of given junctions. + /// + /// `None` if there are any hard junctions in there. + #[cfg(feature = "serde")] + fn derive>(&self, path: Iter) -> Option { + let mut acc = PublicKey::from_bytes(self.as_ref()).ok()?; + for j in path { + match j { + DeriveJunction::Soft(cc) => acc = acc.derived_key_simple(ChainCode(cc), &[]).0, + DeriveJunction::Hard(_cc) => return None, + } + } + Some(Self::from(acc.to_bytes())) } } @@ -129,29 +137,6 @@ impl<'de> Deserialize<'de> for Public { /// An Schnorrkel/Ristretto x25519 ("sr25519") signature. pub type Signature = SignatureBytes; -#[cfg(feature = "serde")] -impl Serialize for Signature { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&array_bytes::bytes2hex("", self)) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Signature { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let signature_hex = array_bytes::hex2bytes(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e)))?; - Signature::try_from(signature_hex.as_ref()) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - #[cfg(feature = "full_crypto")] impl From for Signature { fn from(s: schnorrkel::Signature) -> Signature { @@ -159,37 +144,19 @@ impl From for Signature { } } -impl sp_std::fmt::Debug for Signature { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} +/// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. +pub struct Pair(Keypair); -impl Derive for Public { - /// Derive a child key from a series of given junctions. - /// - /// `None` if there are any hard junctions in there. - #[cfg(feature = "serde")] - fn derive>(&self, path: Iter) -> Option { - let mut acc = PublicKey::from_bytes(self.as_ref()).ok()?; - for j in path { - match j { - DeriveJunction::Soft(cc) => acc = acc.derived_key_simple(ChainCode(cc), &[]).0, - DeriveJunction::Hard(_cc) => return None, - } - } - Some(Self::from(acc.to_bytes())) +impl Clone for Pair { + fn clone(&self) -> Self { + Pair(schnorrkel::Keypair { + public: self.0.public, + secret: schnorrkel::SecretKey::from_bytes(&self.0.secret.to_bytes()[..]) + .expect("key is always the correct size; qed"), + }) } } -impl TraitPublic for Public {} - #[cfg(feature = "std")] impl From for Pair { fn from(sec: MiniSecretKey) -> Pair { diff --git a/substrate/primitives/statement-store/src/ecies.rs b/substrate/primitives/statement-store/src/ecies.rs index 80a040fd4c8..6fa16658e00 100644 --- a/substrate/primitives/statement-store/src/ecies.rs +++ b/substrate/primitives/statement-store/src/ecies.rs @@ -148,7 +148,7 @@ mod test { #[test] fn basic_ed25519_encryption() { let (pair, _) = sp_core::ed25519::Pair::generate(); - let pk = pair.into(); + let pk = pair.public(); let plain_message = b"An important secret message"; let encrypted = encrypt_ed25519(&pk, plain_message).unwrap(); -- GitLab From cc1e6ac301ea88e3cb3253a84e4c6aa28f2d8f87 Mon Sep 17 00:00:00 2001 From: Andrei Eres Date: Mon, 25 Mar 2024 16:57:46 +0100 Subject: [PATCH 174/188] [subsystem-benchmarks] Fix availability-write regression tests (#3698) Adds availability-write regression tests. The results for the `availability-distribution` subsystem are volatile, so I had to reduce the precision of the test. --- .gitlab/pipeline/test.yml | 1 + .../availability-distribution/Cargo.toml | 4 +- ...ilability-distribution-regression-bench.rs | 59 +-- .../availability-recovery-regression-bench.rs | 53 ++- polkadot/node/subsystem-bench/Cargo.toml | 2 +- .../src/cli/subsystem-bench.rs | 14 +- .../src/lib/availability/mod.rs | 396 ++++-------------- .../src/lib/availability/test_state.rs | 268 ++++++++++++ .../subsystem-bench/src/lib/environment.rs | 1 + polkadot/node/subsystem-bench/src/lib/lib.rs | 1 - .../subsystem-bench/src/lib/mock/av_store.rs | 1 + .../src/lib/mock/runtime_api.rs | 2 + .../node/subsystem-bench/src/lib/usage.rs | 15 +- .../node/subsystem-bench/src/lib/utils.rs | 76 ---- 14 files changed, 435 insertions(+), 458 deletions(-) rename polkadot/node/network/availability-distribution/{tests => benches}/availability-distribution-regression-bench.rs (57%) create mode 100644 polkadot/node/subsystem-bench/src/lib/availability/test_state.rs delete mode 100644 polkadot/node/subsystem-bench/src/lib/utils.rs diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index d244316000a..476ac6333f5 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -503,6 +503,7 @@ subsystem-regression-tests: - .run-immediately script: - cargo bench --profile=testnet -p polkadot-availability-recovery --bench availability-recovery-regression-bench --features subsystem-benchmarks + - cargo bench --profile=testnet -p polkadot-availability-distribution --bench availability-distribution-regression-bench --features subsystem-benchmarks tags: - benchmark allow_failure: true diff --git a/polkadot/node/network/availability-distribution/Cargo.toml b/polkadot/node/network/availability-distribution/Cargo.toml index 182d92cb163..ac606bd377f 100644 --- a/polkadot/node/network/availability-distribution/Cargo.toml +++ b/polkadot/node/network/availability-distribution/Cargo.toml @@ -39,9 +39,9 @@ polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } polkadot-subsystem-bench = { path = "../../subsystem-bench" } -[[test]] +[[bench]] name = "availability-distribution-regression-bench" -path = "tests/availability-distribution-regression-bench.rs" +path = "benches/availability-distribution-regression-bench.rs" harness = false required-features = ["subsystem-benchmarks"] diff --git a/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs b/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs similarity index 57% rename from polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs rename to polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs index bdab11298d5..019eb122208 100644 --- a/polkadot/node/network/availability-distribution/tests/availability-distribution-regression-bench.rs +++ b/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs @@ -24,46 +24,55 @@ //! - availability-store use polkadot_subsystem_bench::{ - availability::{benchmark_availability_write, prepare_test, TestDataAvailability, TestState}, + availability::{benchmark_availability_write, prepare_test, TestState}, configuration::TestConfiguration, - utils::{warm_up_and_benchmark, WarmUpOptions}, + usage::BenchmarkUsage, }; +use std::io::Write; + +const BENCH_COUNT: usize = 50; fn main() -> Result<(), String> { let mut messages = vec![]; let mut config = TestConfiguration::default(); - // A single node effort roughly n_cores * needed_approvals / n_validators = 60 * 30 / 300 - config.n_cores = 6; + // A single node effort roughly + config.n_cores = 10; + config.n_validators = 500; config.num_blocks = 3; config.generate_pov_sizes(); + let state = TestState::new(&config); - let usage = warm_up_and_benchmark( - WarmUpOptions::new(&[ - "availability-distribution", - "bitfield-distribution", - "availability-store", - ]), - || { - let mut state = TestState::new(&config); - let (mut env, _protocol_config) = - prepare_test(config.clone(), &mut state, TestDataAvailability::Write, false); + println!("Benchmarking..."); + let usages: Vec = (0..BENCH_COUNT) + .map(|n| { + print!("\r[{}{}]", "#".repeat(n), "_".repeat(BENCH_COUNT - n)); + std::io::stdout().flush().unwrap(); + let (mut env, _cfgs) = prepare_test( + &state, + polkadot_subsystem_bench::availability::TestDataAvailability::Write, + false, + ); env.runtime().block_on(benchmark_availability_write( "data_availability_write", &mut env, - state, + &state, )) - }, - )?; - println!("{}", usage); + }) + .collect(); + println!("\rDone!{}", " ".repeat(BENCH_COUNT)); + let average_usage = BenchmarkUsage::average(&usages); + println!("{}", average_usage); - messages.extend(usage.check_network_usage(&[ - ("Received from peers", 443.333, 0.05), - ("Sent to peers", 21818.555, 0.05), + // We expect no variance for received and sent + // but use 0.001 because we operate with floats + messages.extend(average_usage.check_network_usage(&[ + ("Received from peers", 433.3, 0.001), + ("Sent to peers", 18480.0, 0.001), ])); - messages.extend(usage.check_cpu_usage(&[ - ("availability-distribution", 0.011, 0.05), - ("bitfield-distribution", 0.029, 0.05), - ("availability-store", 0.232, 0.05), + messages.extend(average_usage.check_cpu_usage(&[ + ("availability-distribution", 0.012, 0.05), + ("availability-store", 0.153, 0.05), + ("bitfield-distribution", 0.026, 0.05), ])); if messages.is_empty() { diff --git a/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs b/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs index 42b1787e045..5e8b81be82d 100644 --- a/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs +++ b/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! availability-write regression tests +//! availability-read regression tests //! -//! Availability write benchmark based on Kusama parameters and scale. +//! Availability read benchmark based on Kusama parameters and scale. //! //! Subsystems involved: //! - availability-recovery @@ -27,8 +27,11 @@ use polkadot_subsystem_bench::{ TestDataAvailability, TestState, }, configuration::TestConfiguration, - utils::{warm_up_and_benchmark, WarmUpOptions}, + usage::BenchmarkUsage, }; +use std::io::Write; + +const BENCH_COUNT: usize = 50; fn main() -> Result<(), String> { let mut messages = vec![]; @@ -38,27 +41,33 @@ fn main() -> Result<(), String> { config.num_blocks = 3; config.generate_pov_sizes(); - let usage = warm_up_and_benchmark(WarmUpOptions::new(&["availability-recovery"]), || { - let mut state = TestState::new(&config); - let (mut env, _protocol_config) = prepare_test( - config.clone(), - &mut state, - TestDataAvailability::Read(options.clone()), - false, - ); - env.runtime().block_on(benchmark_availability_read( - "data_availability_read", - &mut env, - state, - )) - })?; - println!("{}", usage); + let state = TestState::new(&config); + + println!("Benchmarking..."); + let usages: Vec = (0..BENCH_COUNT) + .map(|n| { + print!("\r[{}{}]", "#".repeat(n), "_".repeat(BENCH_COUNT - n)); + std::io::stdout().flush().unwrap(); + let (mut env, _cfgs) = + prepare_test(&state, TestDataAvailability::Read(options.clone()), false); + env.runtime().block_on(benchmark_availability_read( + "data_availability_read", + &mut env, + &state, + )) + }) + .collect(); + println!("\rDone!{}", " ".repeat(BENCH_COUNT)); + let average_usage = BenchmarkUsage::average(&usages); + println!("{}", average_usage); - messages.extend(usage.check_network_usage(&[ - ("Received from peers", 307200.000, 0.05), - ("Sent to peers", 1.667, 0.05), + // We expect no variance for received and sent + // but use 0.001 because we operate with floats + messages.extend(average_usage.check_network_usage(&[ + ("Received from peers", 307200.000, 0.001), + ("Sent to peers", 1.667, 0.001), ])); - messages.extend(usage.check_cpu_usage(&[("availability-recovery", 11.500, 0.05)])); + messages.extend(average_usage.check_cpu_usage(&[("availability-recovery", 11.500, 0.05)])); if messages.is_empty() { Ok(()) diff --git a/polkadot/node/subsystem-bench/Cargo.toml b/polkadot/node/subsystem-bench/Cargo.toml index 71711ad0fbd..2570fe9cfa2 100644 --- a/polkadot/node/subsystem-bench/Cargo.toml +++ b/polkadot/node/subsystem-bench/Cargo.toml @@ -56,7 +56,7 @@ bitvec = "1.0.1" kvdb-memorydb = "0.13.0" parity-scale-codec = { version = "3.6.1", features = ["derive", "std"] } -tokio = "1.24.2" +tokio = { version = "1.24.2", features = ["rt-multi-thread", "parking_lot"] } clap-num = "1.0.2" polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } sp-keyring = { path = "../../../substrate/primitives/keyring" } diff --git a/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs b/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs index deb351360d7..10953b6c783 100644 --- a/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs +++ b/polkadot/node/subsystem-bench/src/cli/subsystem-bench.rs @@ -136,31 +136,29 @@ impl BenchCli { let usage = match objective { TestObjective::DataAvailabilityRead(opts) => { - let mut state = availability::TestState::new(&test_config); + let state = availability::TestState::new(&test_config); let (mut env, _protocol_config) = availability::prepare_test( - test_config, - &mut state, + &state, availability::TestDataAvailability::Read(opts), true, ); env.runtime().block_on(availability::benchmark_availability_read( &benchmark_name, &mut env, - state, + &state, )) }, TestObjective::DataAvailabilityWrite => { - let mut state = availability::TestState::new(&test_config); + let state = availability::TestState::new(&test_config); let (mut env, _protocol_config) = availability::prepare_test( - test_config, - &mut state, + &state, availability::TestDataAvailability::Write, true, ); env.runtime().block_on(availability::benchmark_availability_write( &benchmark_name, &mut env, - state, + &state, )) }, TestObjective::ApprovalVoting(ref options) => { diff --git a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs index dc4e1e40310..765afdd5912 100644 --- a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs @@ -15,11 +15,11 @@ // along with Polkadot. If not, see . use crate::{ - configuration::TestConfiguration, + availability::av_store_helpers::new_av_store, dummy_builder, environment::{TestEnvironment, TestEnvironmentDependencies, GENESIS_HASH}, mock::{ - av_store::{self, MockAvailabilityStore}, + av_store::{self, MockAvailabilityStore, NetworkAvailabilityState}, chain_api::{ChainApiState, MockChainApi}, network_bridge::{self, MockNetworkBridgeRx, MockNetworkBridgeTx}, runtime_api::{self, MockRuntimeApi}, @@ -28,12 +28,8 @@ use crate::{ network::new_network, usage::BenchmarkUsage, }; -use av_store::NetworkAvailabilityState; -use av_store_helpers::new_av_store; -use bitvec::bitvec; use colored::Colorize; use futures::{channel::oneshot, stream::FuturesUnordered, StreamExt}; -use itertools::Itertools; use parity_scale_codec::Encode; use polkadot_availability_bitfield_distribution::BitfieldDistribution; use polkadot_availability_distribution::{ @@ -43,37 +39,27 @@ use polkadot_availability_recovery::AvailabilityRecoverySubsystem; use polkadot_node_core_av_store::AvailabilityStoreSubsystem; use polkadot_node_metrics::metrics::Metrics; use polkadot_node_network_protocol::{ - request_response::{v1::ChunkFetchingRequest, IncomingRequest, ReqProtocolNames}, - OurView, Versioned, VersionedValidationProtocol, + request_response::{IncomingRequest, ReqProtocolNames}, + OurView, }; -use polkadot_node_primitives::{AvailableData, BlockData, ErasureChunk, PoV}; use polkadot_node_subsystem::{ messages::{AllMessages, AvailabilityRecoveryMessage}, Overseer, OverseerConnector, SpawnGlue, }; -use polkadot_node_subsystem_test_helpers::{ - derive_erasure_chunks_with_proofs_and_root, mock::new_block_import_info, -}; use polkadot_node_subsystem_types::{ messages::{AvailabilityStoreMessage, NetworkBridgeEvent}, Span, }; use polkadot_overseer::{metrics::Metrics as OverseerMetrics, Handle as OverseerHandle}; -use polkadot_primitives::{ - AvailabilityBitfield, BlockNumber, CandidateHash, CandidateReceipt, GroupIndex, Hash, HeadData, - Header, PersistedValidationData, Signed, SigningContext, ValidatorIndex, -}; -use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; -use sc_network::{ - request_responses::{IncomingRequest as RawIncomingRequest, ProtocolConfig}, - PeerId, -}; +use polkadot_primitives::GroupIndex; +use sc_network::request_responses::{IncomingRequest as RawIncomingRequest, ProtocolConfig}; use sc_service::SpawnTaskHandle; use serde::{Deserialize, Serialize}; -use sp_core::H256; -use std::{collections::HashMap, iter::Cycle, ops::Sub, sync::Arc, time::Instant}; +use std::{ops::Sub, sync::Arc, time::Instant}; +pub use test_state::TestState; mod av_store_helpers; +mod test_state; const LOG_TARGET: &str = "subsystem-bench::availability"; @@ -149,94 +135,48 @@ fn build_overseer_for_availability_write( (overseer, OverseerHandle::new(raw_handle)) } -/// Takes a test configuration and uses it to create the `TestEnvironment`. pub fn prepare_test( - config: TestConfiguration, - state: &mut TestState, - mode: TestDataAvailability, - with_prometheus_endpoint: bool, -) -> (TestEnvironment, Vec) { - prepare_test_inner( - config, - state, - mode, - TestEnvironmentDependencies::default(), - with_prometheus_endpoint, - ) -} - -fn prepare_test_inner( - config: TestConfiguration, - state: &mut TestState, + state: &TestState, mode: TestDataAvailability, - dependencies: TestEnvironmentDependencies, with_prometheus_endpoint: bool, ) -> (TestEnvironment, Vec) { - // Generate test authorities. - let test_authorities = config.generate_authorities(); - - let mut candidate_hashes: HashMap> = HashMap::new(); - - // Prepare per block candidates. - // Genesis block is always finalized, so we start at 1. - for block_num in 1..=config.num_blocks { - for _ in 0..config.n_cores { - candidate_hashes - .entry(Hash::repeat_byte(block_num as u8)) - .or_default() - .push(state.next_candidate().expect("Cycle iterator")) - } - - // First candidate is our backed candidate. - state.backed_candidates.push( - candidate_hashes - .get(&Hash::repeat_byte(block_num as u8)) - .expect("just inserted above") - .first() - .expect("just inserted above") - .clone(), - ); - } - - let runtime_api = runtime_api::MockRuntimeApi::new( - config.clone(), - test_authorities.clone(), - candidate_hashes, - Default::default(), - Default::default(), - 0, - ); - - let availability_state = NetworkAvailabilityState { - candidate_hashes: state.candidate_hashes.clone(), - available_data: state.available_data.clone(), - chunks: state.chunks.clone(), - }; - - let mut req_cfgs = Vec::new(); - let (collation_req_receiver, collation_req_cfg) = IncomingRequest::get_config_receiver(&ReqProtocolNames::new(GENESIS_HASH, None)); - req_cfgs.push(collation_req_cfg); - let (pov_req_receiver, pov_req_cfg) = IncomingRequest::get_config_receiver(&ReqProtocolNames::new(GENESIS_HASH, None)); - let (chunk_req_receiver, chunk_req_cfg) = IncomingRequest::get_config_receiver(&ReqProtocolNames::new(GENESIS_HASH, None)); - req_cfgs.push(pov_req_cfg); + let req_cfgs = vec![collation_req_cfg, pov_req_cfg]; - let (network, network_interface, network_receiver) = - new_network(&config, &dependencies, &test_authorities, vec![Arc::new(availability_state)]); + let dependencies = TestEnvironmentDependencies::default(); + let availability_state = NetworkAvailabilityState { + candidate_hashes: state.candidate_hashes.clone(), + available_data: state.available_data.clone(), + chunks: state.chunks.clone(), + }; + let (network, network_interface, network_receiver) = new_network( + &state.config, + &dependencies, + &state.test_authorities, + vec![Arc::new(availability_state.clone())], + ); let network_bridge_tx = network_bridge::MockNetworkBridgeTx::new( network.clone(), network_interface.subsystem_sender(), - test_authorities.clone(), + state.test_authorities.clone(), ); - let network_bridge_rx = - network_bridge::MockNetworkBridgeRx::new(network_receiver, Some(chunk_req_cfg.clone())); + network_bridge::MockNetworkBridgeRx::new(network_receiver, Some(chunk_req_cfg)); + + let runtime_api = runtime_api::MockRuntimeApi::new( + state.config.clone(), + state.test_authorities.clone(), + state.candidate_receipts.clone(), + Default::default(), + Default::default(), + 0, + ); let (overseer, overseer_handle) = match &mode { TestDataAvailability::Read(options) => { @@ -271,27 +211,12 @@ fn prepare_test_inner( }, TestDataAvailability::Write => { let availability_distribution = AvailabilityDistributionSubsystem::new( - test_authorities.keyring.keystore(), + state.test_authorities.keyring.keystore(), IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, Metrics::try_register(&dependencies.registry).unwrap(), ); - let block_headers = (1..=config.num_blocks) - .map(|block_number| { - ( - Hash::repeat_byte(block_number as u8), - Header { - digest: Default::default(), - number: block_number as BlockNumber, - parent_hash: Default::default(), - extrinsics_root: Default::default(), - state_root: Default::default(), - }, - ) - }) - .collect::>(); - - let chain_api_state = ChainApiState { block_headers }; + let chain_api_state = ChainApiState { block_headers: state.block_headers.clone() }; let chain_api = MockChainApi::new(chain_api_state); let bitfield_distribution = BitfieldDistribution::new(Metrics::try_register(&dependencies.registry).unwrap()); @@ -311,167 +236,42 @@ fn prepare_test_inner( ( TestEnvironment::new( dependencies, - config, + state.config.clone(), network, overseer, overseer_handle, - test_authorities, + state.test_authorities.clone(), with_prometheus_endpoint, ), req_cfgs, ) } -#[derive(Clone)] -pub struct TestState { - // Full test configuration - config: TestConfiguration, - // A cycle iterator on all PoV sizes used in the test. - pov_sizes: Cycle>, - // Generated candidate receipts to be used in the test - candidates: Cycle>, - // Map from pov size to candidate index - pov_size_to_candidate: HashMap, - // Map from generated candidate hashes to candidate index in `available_data` - // and `chunks`. - candidate_hashes: HashMap, - // Per candidate index receipts. - candidate_receipt_templates: Vec, - // Per candidate index `AvailableData` - available_data: Vec, - // Per candiadte index chunks - chunks: Vec>, - // Per relay chain block - candidate backed by our backing group - backed_candidates: Vec, -} - -impl TestState { - pub fn next_candidate(&mut self) -> Option { - let candidate = self.candidates.next(); - let candidate_hash = candidate.as_ref().unwrap().hash(); - gum::trace!(target: LOG_TARGET, "Next candidate selected {:?}", candidate_hash); - candidate - } - - /// Generate candidates to be used in the test. - fn generate_candidates(&mut self) { - let count = self.config.n_cores * self.config.num_blocks; - gum::info!(target: LOG_TARGET,"{}", format!("Pre-generating {} candidates.", count).bright_blue()); - - // Generate all candidates - self.candidates = (0..count) - .map(|index| { - let pov_size = self.pov_sizes.next().expect("This is a cycle; qed"); - let candidate_index = *self - .pov_size_to_candidate - .get(&pov_size) - .expect("pov_size always exists; qed"); - let mut candidate_receipt = - self.candidate_receipt_templates[candidate_index].clone(); - - // Make it unique. - candidate_receipt.descriptor.relay_parent = Hash::from_low_u64_be(index as u64); - // Store the new candidate in the state - self.candidate_hashes.insert(candidate_receipt.hash(), candidate_index); - - gum::debug!(target: LOG_TARGET, candidate_hash = ?candidate_receipt.hash(), "new candidate"); - - candidate_receipt - }) - .collect::>() - .into_iter() - .cycle(); - } - - pub fn new(config: &TestConfiguration) -> Self { - let config = config.clone(); - - let mut chunks = Vec::new(); - let mut available_data = Vec::new(); - let mut candidate_receipt_templates = Vec::new(); - let mut pov_size_to_candidate = HashMap::new(); - - // we use it for all candidates. - let persisted_validation_data = PersistedValidationData { - parent_head: HeadData(vec![7, 8, 9]), - relay_parent_number: Default::default(), - max_pov_size: 1024, - relay_parent_storage_root: Default::default(), - }; - - // For each unique pov we create a candidate receipt. - for (index, pov_size) in config.pov_sizes().iter().cloned().unique().enumerate() { - gum::info!(target: LOG_TARGET, index, pov_size, "{}", "Generating template candidate".bright_blue()); - - let mut candidate_receipt = dummy_candidate_receipt(dummy_hash()); - let pov = PoV { block_data: BlockData(vec![index as u8; pov_size]) }; - - let new_available_data = AvailableData { - validation_data: persisted_validation_data.clone(), - pov: Arc::new(pov), - }; - - let (new_chunks, erasure_root) = derive_erasure_chunks_with_proofs_and_root( - config.n_validators, - &new_available_data, - |_, _| {}, - ); - - candidate_receipt.descriptor.erasure_root = erasure_root; - - chunks.push(new_chunks); - available_data.push(new_available_data); - pov_size_to_candidate.insert(pov_size, index); - candidate_receipt_templates.push(candidate_receipt); - } - - gum::info!(target: LOG_TARGET, "{}","Created test environment.".bright_blue()); - - let mut _self = Self { - available_data, - candidate_receipt_templates, - chunks, - pov_size_to_candidate, - pov_sizes: Vec::from(config.pov_sizes()).into_iter().cycle(), - candidate_hashes: HashMap::new(), - candidates: Vec::new().into_iter().cycle(), - backed_candidates: Vec::new(), - config, - }; - - _self.generate_candidates(); - _self - } - - pub fn backed_candidates(&mut self) -> &mut Vec { - &mut self.backed_candidates - } -} - pub async fn benchmark_availability_read( benchmark_name: &str, env: &mut TestEnvironment, - mut state: TestState, + state: &TestState, ) -> BenchmarkUsage { let config = env.config().clone(); - env.import_block(new_block_import_info(Hash::repeat_byte(1), 1)).await; - - let test_start = Instant::now(); - let mut batch = FuturesUnordered::new(); - let mut availability_bytes = 0u128; - env.metrics().set_n_validators(config.n_validators); env.metrics().set_n_cores(config.n_cores); - for block_num in 1..=env.config().num_blocks { + let mut batch = FuturesUnordered::new(); + let mut availability_bytes = 0u128; + let mut candidates = state.candidates.clone(); + let test_start = Instant::now(); + for block_info in state.block_infos.iter() { + let block_num = block_info.number as usize; gum::info!(target: LOG_TARGET, "Current block {}/{}", block_num, env.config().num_blocks); env.metrics().set_current_block(block_num); let block_start_ts = Instant::now(); + env.import_block(block_info.clone()).await; + for candidate_num in 0..config.n_cores as u64 { let candidate = - state.next_candidate().expect("We always send up to n_cores*num_blocks; qed"); + candidates.next().expect("We always send up to n_cores*num_blocks; qed"); let (tx, rx) = oneshot::channel(); batch.push(rx); @@ -519,7 +319,7 @@ pub async fn benchmark_availability_read( pub async fn benchmark_availability_write( benchmark_name: &str, env: &mut TestEnvironment, - mut state: TestState, + state: &TestState, ) -> BenchmarkUsage { let config = env.config().clone(); @@ -527,7 +327,7 @@ pub async fn benchmark_availability_write( env.metrics().set_n_cores(config.n_cores); gum::info!(target: LOG_TARGET, "Seeding availability store with candidates ..."); - for backed_candidate in state.backed_candidates().clone() { + for backed_candidate in state.backed_candidates.clone() { let candidate_index = *state.candidate_hashes.get(&backed_candidate.hash()).unwrap(); let available_data = state.available_data[candidate_index].clone(); let (tx, rx) = oneshot::channel(); @@ -550,15 +350,14 @@ pub async fn benchmark_availability_write( gum::info!(target: LOG_TARGET, "Done"); let test_start = Instant::now(); - - for block_num in 1..=env.config().num_blocks { + for block_info in state.block_infos.iter() { + let block_num = block_info.number as usize; gum::info!(target: LOG_TARGET, "Current block #{}", block_num); env.metrics().set_current_block(block_num); let block_start_ts = Instant::now(); - let relay_block_hash = Hash::repeat_byte(block_num as u8); - env.import_block(new_block_import_info(relay_block_hash, block_num as BlockNumber)) - .await; + let relay_block_hash = block_info.hash; + env.import_block(block_info.clone()).await; // Inform bitfield distribution about our view of current test block let message = polkadot_node_subsystem_types::messages::BitfieldDistributionMessage::NetworkBridgeUpdate( @@ -569,20 +368,13 @@ pub async fn benchmark_availability_write( let chunk_fetch_start_ts = Instant::now(); // Request chunks of our own backed candidate from all other validators. - let mut receivers = Vec::new(); - for index in 1..config.n_validators { + let payloads = state.chunk_fetching_requests.get(block_num - 1).expect("pregenerated"); + let receivers = (1..config.n_validators).filter_map(|index| { let (pending_response, pending_response_receiver) = oneshot::channel(); - let request = RawIncomingRequest { - peer: PeerId::random(), - payload: ChunkFetchingRequest { - candidate_hash: state.backed_candidates()[block_num - 1].hash(), - index: ValidatorIndex(index as u32), - } - .encode(), - pending_response, - }; - + let peer_id = *env.authorities().peer_ids.get(index).expect("all validators have ids"); + let payload = payloads.get(index).expect("pregenerated").clone(); + let request = RawIncomingRequest { peer: peer_id, payload, pending_response }; let peer = env .authorities() .validator_authority_id @@ -592,59 +384,39 @@ pub async fn benchmark_availability_write( if env.network().is_peer_connected(peer) && env.network().send_request_from_peer(peer, request).is_ok() { - receivers.push(pending_response_receiver); + Some(pending_response_receiver) + } else { + None } - } + }); gum::info!(target: LOG_TARGET, "Waiting for all emulated peers to receive their chunk from us ..."); - for receiver in receivers.into_iter() { - let response = receiver.await.expect("Chunk is always served successfully"); - // TODO: check if chunk is the one the peer expects to receive. - assert!(response.result.is_ok()); - } - let chunk_fetch_duration = Instant::now().sub(chunk_fetch_start_ts).as_millis(); + let responses = futures::future::try_join_all(receivers) + .await + .expect("Chunk is always served successfully"); + // TODO: check if chunk is the one the peer expects to receive. + assert!(responses.iter().all(|v| v.result.is_ok())); + let chunk_fetch_duration = Instant::now().sub(chunk_fetch_start_ts).as_millis(); gum::info!(target: LOG_TARGET, "All chunks received in {}ms", chunk_fetch_duration); - let signing_context = SigningContext { session_index: 0, parent_hash: relay_block_hash }; let network = env.network().clone(); let authorities = env.authorities().clone(); - let n_validators = config.n_validators; // Spawn a task that will generate `n_validator` - 1 signed bitfiends and // send them from the emulated peers to the subsystem. // TODO: Implement topology. - env.spawn_blocking("send-bitfields", async move { - for index in 1..n_validators { - let validator_public = - authorities.validator_public.get(index).expect("All validator keys are known"); - - // Node has all the chunks in the world. - let payload: AvailabilityBitfield = - AvailabilityBitfield(bitvec![u8, bitvec::order::Lsb0; 1u8; 32]); - // TODO(soon): Use pre-signed messages. This is quite intensive on the CPU. - let signed_bitfield = Signed::::sign( - &authorities.keyring.keystore(), - payload, - &signing_context, - ValidatorIndex(index as u32), - validator_public, - ) - .ok() - .flatten() - .expect("should be signed"); - - let from_peer = &authorities.validator_authority_id[index]; - - let message = peer_bitfield_message_v2(relay_block_hash, signed_bitfield); + let messages = state.signed_bitfields.get(&relay_block_hash).expect("pregenerated").clone(); + for index in 1..config.n_validators { + let from_peer = &authorities.validator_authority_id[index]; + let message = messages.get(index).expect("pregenerated").clone(); - // Send the action from peer only if it is connected to our node. - if network.is_peer_connected(from_peer) { - let _ = network.send_message_from_peer(from_peer, message); - } + // Send the action from peer only if it is connected to our node. + if network.is_peer_connected(from_peer) { + let _ = network.send_message_from_peer(from_peer, message); } - }); + } gum::info!( "Waiting for {} bitfields to be received and processed", @@ -679,17 +451,3 @@ pub async fn benchmark_availability_write( &["availability-distribution", "bitfield-distribution", "availability-store"], ) } - -pub fn peer_bitfield_message_v2( - relay_hash: H256, - signed_bitfield: Signed, -) -> VersionedValidationProtocol { - let bitfield = polkadot_node_network_protocol::v2::BitfieldDistributionMessage::Bitfield( - relay_hash, - signed_bitfield.into(), - ); - - Versioned::V2(polkadot_node_network_protocol::v2::ValidationProtocol::BitfieldDistribution( - bitfield, - )) -} diff --git a/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs b/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs new file mode 100644 index 00000000000..c328ffedf91 --- /dev/null +++ b/polkadot/node/subsystem-bench/src/lib/availability/test_state.rs @@ -0,0 +1,268 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use crate::configuration::{TestAuthorities, TestConfiguration}; +use bitvec::bitvec; +use colored::Colorize; +use itertools::Itertools; +use parity_scale_codec::Encode; +use polkadot_node_network_protocol::{ + request_response::v1::ChunkFetchingRequest, Versioned, VersionedValidationProtocol, +}; +use polkadot_node_primitives::{AvailableData, BlockData, ErasureChunk, PoV}; +use polkadot_node_subsystem_test_helpers::{ + derive_erasure_chunks_with_proofs_and_root, mock::new_block_import_info, +}; +use polkadot_overseer::BlockInfo; +use polkadot_primitives::{ + AvailabilityBitfield, BlockNumber, CandidateHash, CandidateReceipt, Hash, HeadData, Header, + PersistedValidationData, Signed, SigningContext, ValidatorIndex, +}; +use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; +use sp_core::H256; +use std::{collections::HashMap, iter::Cycle, sync::Arc}; + +const LOG_TARGET: &str = "subsystem-bench::availability::test_state"; + +#[derive(Clone)] +pub struct TestState { + // Full test configuration + pub config: TestConfiguration, + // A cycle iterator on all PoV sizes used in the test. + pub pov_sizes: Cycle>, + // Generated candidate receipts to be used in the test + pub candidates: Cycle>, + // Map from pov size to candidate index + pub pov_size_to_candidate: HashMap, + // Map from generated candidate hashes to candidate index in `available_data` and `chunks`. + pub candidate_hashes: HashMap, + // Per candidate index receipts. + pub candidate_receipt_templates: Vec, + // Per candidate index `AvailableData` + pub available_data: Vec, + // Per candiadte index chunks + pub chunks: Vec>, + // Per relay chain block - candidate backed by our backing group + pub backed_candidates: Vec, + // Relay chain block infos + pub block_infos: Vec, + // Chung fetching requests for backed candidates + pub chunk_fetching_requests: Vec>>, + // Pregenerated signed availability bitfields + pub signed_bitfields: HashMap>, + // Relay chain block headers + pub block_headers: HashMap, + // Authority keys for the network emulation. + pub test_authorities: TestAuthorities, + // Map from generated candidate receipts + pub candidate_receipts: HashMap>, +} + +impl TestState { + pub fn new(config: &TestConfiguration) -> Self { + let mut test_state = Self { + available_data: Default::default(), + candidate_receipt_templates: Default::default(), + chunks: Default::default(), + pov_size_to_candidate: Default::default(), + pov_sizes: Vec::from(config.pov_sizes()).into_iter().cycle(), + candidate_hashes: HashMap::new(), + candidates: Vec::new().into_iter().cycle(), + backed_candidates: Vec::new(), + config: config.clone(), + block_infos: Default::default(), + chunk_fetching_requests: Default::default(), + signed_bitfields: Default::default(), + candidate_receipts: Default::default(), + block_headers: Default::default(), + test_authorities: config.generate_authorities(), + }; + + // we use it for all candidates. + let persisted_validation_data = PersistedValidationData { + parent_head: HeadData(vec![7, 8, 9]), + relay_parent_number: Default::default(), + max_pov_size: 1024, + relay_parent_storage_root: Default::default(), + }; + + // For each unique pov we create a candidate receipt. + for (index, pov_size) in config.pov_sizes().iter().cloned().unique().enumerate() { + gum::info!(target: LOG_TARGET, index, pov_size, "{}", "Generating template candidate".bright_blue()); + + let mut candidate_receipt = dummy_candidate_receipt(dummy_hash()); + let pov = PoV { block_data: BlockData(vec![index as u8; pov_size]) }; + + let new_available_data = AvailableData { + validation_data: persisted_validation_data.clone(), + pov: Arc::new(pov), + }; + + let (new_chunks, erasure_root) = derive_erasure_chunks_with_proofs_and_root( + config.n_validators, + &new_available_data, + |_, _| {}, + ); + + candidate_receipt.descriptor.erasure_root = erasure_root; + + test_state.chunks.push(new_chunks); + test_state.available_data.push(new_available_data); + test_state.pov_size_to_candidate.insert(pov_size, index); + test_state.candidate_receipt_templates.push(candidate_receipt); + } + + test_state.block_infos = (1..=config.num_blocks) + .map(|block_num| { + let relay_block_hash = Hash::repeat_byte(block_num as u8); + new_block_import_info(relay_block_hash, block_num as BlockNumber) + }) + .collect(); + + test_state.block_headers = test_state + .block_infos + .iter() + .map(|info| { + ( + info.hash, + Header { + digest: Default::default(), + number: info.number, + parent_hash: info.parent_hash, + extrinsics_root: Default::default(), + state_root: Default::default(), + }, + ) + }) + .collect::>(); + + // Generate all candidates + let candidates_count = config.n_cores * config.num_blocks; + gum::info!(target: LOG_TARGET,"{}", format!("Pre-generating {} candidates.", candidates_count).bright_blue()); + test_state.candidates = (0..candidates_count) + .map(|index| { + let pov_size = test_state.pov_sizes.next().expect("This is a cycle; qed"); + let candidate_index = *test_state + .pov_size_to_candidate + .get(&pov_size) + .expect("pov_size always exists; qed"); + let mut candidate_receipt = + test_state.candidate_receipt_templates[candidate_index].clone(); + + // Make it unique. + candidate_receipt.descriptor.relay_parent = Hash::from_low_u64_be(index as u64); + // Store the new candidate in the state + test_state.candidate_hashes.insert(candidate_receipt.hash(), candidate_index); + + gum::debug!(target: LOG_TARGET, candidate_hash = ?candidate_receipt.hash(), "new candidate"); + + candidate_receipt + }) + .collect::>() + .into_iter() + .cycle(); + + // Prepare per block candidates. + // Genesis block is always finalized, so we start at 1. + for info in test_state.block_infos.iter() { + for _ in 0..config.n_cores { + let receipt = test_state.candidates.next().expect("Cycle iterator"); + test_state.candidate_receipts.entry(info.hash).or_default().push(receipt); + } + + // First candidate is our backed candidate. + test_state.backed_candidates.push( + test_state + .candidate_receipts + .get(&info.hash) + .expect("just inserted above") + .first() + .expect("just inserted above") + .clone(), + ); + } + + test_state.chunk_fetching_requests = test_state + .backed_candidates + .iter() + .map(|candidate| { + (0..config.n_validators) + .map(|index| { + ChunkFetchingRequest { + candidate_hash: candidate.hash(), + index: ValidatorIndex(index as u32), + } + .encode() + }) + .collect::>() + }) + .collect::>(); + + test_state.signed_bitfields = test_state + .block_infos + .iter() + .map(|block_info| { + let signing_context = + SigningContext { session_index: 0, parent_hash: block_info.hash }; + let messages = (0..config.n_validators) + .map(|index| { + let validator_public = test_state + .test_authorities + .validator_public + .get(index) + .expect("All validator keys are known"); + + // Node has all the chunks in the world. + let payload: AvailabilityBitfield = + AvailabilityBitfield(bitvec![u8, bitvec::order::Lsb0; 1u8; 32]); + let signed_bitfield = Signed::::sign( + &test_state.test_authorities.keyring.keystore(), + payload, + &signing_context, + ValidatorIndex(index as u32), + validator_public, + ) + .ok() + .flatten() + .expect("should be signed"); + + peer_bitfield_message_v2(block_info.hash, signed_bitfield) + }) + .collect::>(); + + (block_info.hash, messages) + }) + .collect(); + + gum::info!(target: LOG_TARGET, "{}","Created test environment.".bright_blue()); + + test_state + } +} + +fn peer_bitfield_message_v2( + relay_hash: H256, + signed_bitfield: Signed, +) -> VersionedValidationProtocol { + let bitfield = polkadot_node_network_protocol::v2::BitfieldDistributionMessage::Bitfield( + relay_hash, + signed_bitfield.into(), + ); + + Versioned::V2(polkadot_node_network_protocol::v2::ValidationProtocol::BitfieldDistribution( + bitfield, + )) +} diff --git a/polkadot/node/subsystem-bench/src/lib/environment.rs b/polkadot/node/subsystem-bench/src/lib/environment.rs index 958ed50d089..2d80d75a14a 100644 --- a/polkadot/node/subsystem-bench/src/lib/environment.rs +++ b/polkadot/node/subsystem-bench/src/lib/environment.rs @@ -118,6 +118,7 @@ fn new_runtime() -> tokio::runtime::Runtime { .thread_name("subsystem-bench") .enable_all() .thread_stack_size(3 * 1024 * 1024) + .worker_threads(4) .build() .unwrap() } diff --git a/polkadot/node/subsystem-bench/src/lib/lib.rs b/polkadot/node/subsystem-bench/src/lib/lib.rs index ef2724abc98..d06f2822a89 100644 --- a/polkadot/node/subsystem-bench/src/lib/lib.rs +++ b/polkadot/node/subsystem-bench/src/lib/lib.rs @@ -26,4 +26,3 @@ pub(crate) mod keyring; pub(crate) mod mock; pub(crate) mod network; pub mod usage; -pub mod utils; diff --git a/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs index 9064f17940f..080644da92a 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs @@ -41,6 +41,7 @@ const LOG_TARGET: &str = "subsystem-bench::av-store-mock"; /// Mockup helper. Contains Ccunks and full availability data of all parachain blocks /// used in a test. +#[derive(Clone)] pub struct NetworkAvailabilityState { pub candidate_hashes: HashMap, pub available_data: Vec, diff --git a/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs b/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs index 53faf562f03..3c39de870a2 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/runtime_api.rs @@ -36,6 +36,7 @@ use std::collections::HashMap; const LOG_TARGET: &str = "subsystem-bench::runtime-api-mock"; /// Minimal state to answer requests. +#[derive(Clone)] pub struct RuntimeApiState { // All authorities in the test, authorities: TestAuthorities, @@ -49,6 +50,7 @@ pub struct RuntimeApiState { } /// A mocked `runtime-api` subsystem. +#[derive(Clone)] pub struct MockRuntimeApi { state: RuntimeApiState, config: TestConfiguration, diff --git a/polkadot/node/subsystem-bench/src/lib/usage.rs b/polkadot/node/subsystem-bench/src/lib/usage.rs index ef60d67372a..7172969a8f9 100644 --- a/polkadot/node/subsystem-bench/src/lib/usage.rs +++ b/polkadot/node/subsystem-bench/src/lib/usage.rs @@ -17,6 +17,7 @@ //! Test usage implementation use colored::Colorize; +use itertools::Itertools; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -37,10 +38,16 @@ impl std::fmt::Display for BenchmarkUsage { self.network_usage .iter() .map(|v| v.to_string()) + .sorted() .collect::>() .join("\n"), format!("{:<32}{:>12}{:>12}", "CPU usage, seconds", "total", "per block").blue(), - self.cpu_usage.iter().map(|v| v.to_string()).collect::>().join("\n") + self.cpu_usage + .iter() + .map(|v| v.to_string()) + .sorted() + .collect::>() + .join("\n") ) } } @@ -101,8 +108,8 @@ fn check_resource_usage( None } else { Some(format!( - "The resource `{}` is expected to be equal to {} with a precision {}, but the current value is {}", - resource_name, base, precision, usage.per_block + "The resource `{}` is expected to be equal to {} with a precision {}, but the current value is {} ({})", + resource_name, base, precision, usage.per_block, diff )) } } else { @@ -119,7 +126,7 @@ pub struct ResourceUsage { impl std::fmt::Display for ResourceUsage { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{:<32}{:>12.3}{:>12.3}", self.resource_name.cyan(), self.total, self.per_block) + write!(f, "{:<32}{:>12.4}{:>12.4}", self.resource_name.cyan(), self.total, self.per_block) } } diff --git a/polkadot/node/subsystem-bench/src/lib/utils.rs b/polkadot/node/subsystem-bench/src/lib/utils.rs deleted file mode 100644 index 75b72cc11b9..00000000000 --- a/polkadot/node/subsystem-bench/src/lib/utils.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Test utils - -use crate::usage::BenchmarkUsage; -use std::io::{stdout, Write}; - -pub struct WarmUpOptions<'a> { - /// The maximum number of runs considered for marming up. - pub warm_up: usize, - /// The number of runs considered for benchmarking. - pub bench: usize, - /// The difference in CPU usage between runs considered as normal - pub precision: f64, - /// The subsystems whose CPU usage is checked during warm-up cycles - pub subsystems: &'a [&'a str], -} - -impl<'a> WarmUpOptions<'a> { - pub fn new(subsystems: &'a [&'a str]) -> Self { - Self { warm_up: 100, bench: 3, precision: 0.02, subsystems } - } -} - -pub fn warm_up_and_benchmark( - options: WarmUpOptions, - run: impl Fn() -> BenchmarkUsage, -) -> Result { - println!("Warming up..."); - let mut usages = Vec::with_capacity(options.bench); - - for n in 1..=options.warm_up { - let curr = run(); - if let Some(prev) = usages.last() { - let diffs = options - .subsystems - .iter() - .map(|&v| { - curr.cpu_usage_diff(prev, v) - .ok_or(format!("{} not found in benchmark {:?}", v, prev)) - }) - .collect::, String>>()?; - if !diffs.iter().all(|&v| v < options.precision) { - usages.clear(); - } - } - usages.push(curr); - print!("\r{}%", n * 100 / options.warm_up); - if usages.len() == options.bench { - println!("\rTook {} runs to warm up", n.saturating_sub(options.bench)); - break; - } - stdout().flush().unwrap(); - } - - if usages.len() != options.bench { - println!("Didn't warm up after {} runs", options.warm_up); - return Err("Can't warm up".to_string()) - } - - Ok(BenchmarkUsage::average(&usages)) -} -- GitLab From ea97863c56c573879564891fc83a9543f46bd95f Mon Sep 17 00:00:00 2001 From: Dcompoze Date: Tue, 26 Mar 2024 12:45:53 +0000 Subject: [PATCH 175/188] Fix formatting in Cargo.toml (#3842) Fixes formatting for https://github.com/paritytech/polkadot-sdk/pull/3698 --- polkadot/node/subsystem-bench/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/node/subsystem-bench/Cargo.toml b/polkadot/node/subsystem-bench/Cargo.toml index 2570fe9cfa2..05907e428f9 100644 --- a/polkadot/node/subsystem-bench/Cargo.toml +++ b/polkadot/node/subsystem-bench/Cargo.toml @@ -56,7 +56,7 @@ bitvec = "1.0.1" kvdb-memorydb = "0.13.0" parity-scale-codec = { version = "3.6.1", features = ["derive", "std"] } -tokio = { version = "1.24.2", features = ["rt-multi-thread", "parking_lot"] } +tokio = { version = "1.24.2", features = ["parking_lot", "rt-multi-thread"] } clap-num = "1.0.2" polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } sp-keyring = { path = "../../../substrate/primitives/keyring" } -- GitLab From b839c995c0b889508f2f8ee6a1807f38c043e922 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 26 Mar 2024 14:09:11 +0100 Subject: [PATCH 176/188] Update bridges subtree (#3841) Updating the bridges subtree hopefully just one last time in this formula in order to make the final migration less verbose. --- bridges/bin/runtime-common/Cargo.toml | 2 +- .../chains/chain-asset-hub-rococo/Cargo.toml | 2 +- .../chains/chain-asset-hub-westend/Cargo.toml | 2 +- .../chains/chain-polkadot-bulletin/Cargo.toml | 2 +- .../docs/bridge-relayers-claim-rewards.png | Bin 0 -> 35621 bytes bridges/docs/bridge-relayers-deregister.png | Bin 0 -> 10115 bytes bridges/docs/bridge-relayers-register.png | Bin 0 -> 51026 bytes bridges/docs/running-relayer.md | 343 ++++++++++++++++++ bridges/modules/grandpa/Cargo.toml | 2 +- bridges/modules/messages/Cargo.toml | 2 +- bridges/modules/parachains/Cargo.toml | 2 +- bridges/modules/relayers/Cargo.toml | 2 +- .../modules/xcm-bridge-hub-router/Cargo.toml | 2 +- bridges/modules/xcm-bridge-hub/Cargo.toml | 2 +- bridges/primitives/header-chain/Cargo.toml | 2 +- bridges/primitives/messages/Cargo.toml | 2 +- bridges/primitives/parachains/Cargo.toml | 2 +- bridges/primitives/polkadot-core/Cargo.toml | 2 +- bridges/primitives/relayers/Cargo.toml | 2 +- bridges/primitives/runtime/Cargo.toml | 2 +- .../xcm-bridge-hub-router/Cargo.toml | 2 +- bridges/scripts/verify-pallets-build.sh | 3 + 22 files changed, 363 insertions(+), 17 deletions(-) create mode 100644 bridges/docs/bridge-relayers-claim-rewards.png create mode 100644 bridges/docs/bridge-relayers-deregister.png create mode 100644 bridges/docs/bridge-relayers-register.png create mode 100644 bridges/docs/running-relayer.md diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml index fac88b20ca5..f00ba1c9734 100644 --- a/bridges/bin/runtime-common/Cargo.toml +++ b/bridges/bin/runtime-common/Cargo.toml @@ -14,7 +14,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/bridges/chains/chain-asset-hub-rococo/Cargo.toml b/bridges/chains/chain-asset-hub-rococo/Cargo.toml index 07c9b3b5289..55dc384badd 100644 --- a/bridges/chains/chain-asset-hub-rococo/Cargo.toml +++ b/bridges/chains/chain-asset-hub-rococo/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { path = "../../../substrate/frame/support", default-features = false } diff --git a/bridges/chains/chain-asset-hub-westend/Cargo.toml b/bridges/chains/chain-asset-hub-westend/Cargo.toml index f75236ee1b3..1379b099a2a 100644 --- a/bridges/chains/chain-asset-hub-westend/Cargo.toml +++ b/bridges/chains/chain-asset-hub-westend/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { path = "../../../substrate/frame/support", default-features = false } diff --git a/bridges/chains/chain-polkadot-bulletin/Cargo.toml b/bridges/chains/chain-polkadot-bulletin/Cargo.toml index d10c4043967..37e060d897c 100644 --- a/bridges/chains/chain-polkadot-bulletin/Cargo.toml +++ b/bridges/chains/chain-polkadot-bulletin/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/bridges/docs/bridge-relayers-claim-rewards.png b/bridges/docs/bridge-relayers-claim-rewards.png new file mode 100644 index 0000000000000000000000000000000000000000..d56b8dd871e8445e7cab49517123b0092ce09137 GIT binary patch literal 35621 zcmb@tbzD^6+CB`TAd-U8ogzp|mjcqEfP}=*4MR7KG>Ej)r4l0D-JK)S-QC^HZ*jio zd5-7(=lSQ|A4F%|Ywxw!y5qX9``RII6{WBqkvu{|Lc)@fmQY4QLd`@%LdJcF3clgr z_1*%1-FFa^QGEyw&xc0A;4`t~8x2PlsEMPCzP&M$sSVWH_=SU^y|J;4gBjFu52aBA zoWyFbs^KVZZ>;ZV4z;0DHMcefUm_v>&K~roV&|h8^#5J{yM&69o%1CX2e$zGO96H+ zPqo{xNJvyjG7_&$Dn zWI4CLRG2cFT;{s@nwPNQIH@Ga+%MlSB!4BtS&ToVq<|lj9!N*`PAWuVyA2K2r^up;6KN zbwIpjWkdctr7KuPSytk&Lozv9`LFY7I2XTs!F&9lBkFN>#+Sb?5d4|XuY}Ou=P1Ej!?v~{($RhaYuOjiAtk>{@}>Ux8fY)T<-Y&k4W+iPDOu@ zxX}7DG$bx3hoNXn+q}f0o)S-@w!z~fsAkFTkV+JbqkVoFJcdtNqSW4r8ef zrNHK9;mPLuHVxJMCJ)Qs&jArZMn-mYbk;d>Zu}Y{oNG)yGDZ(z&CBDBwT0$5!l5V7ogznVFf!s*AXP-K9F3l$B}4zWO{4 zc0o8=2tia=3{6e-a>0dKRg{EJs_|r5<3b^b%dxui#n3cnijVnPm4~^In@^0XuD)Zs z9@brl;It==7yVEqGYgBwgHFn|LfFmLTKH0(rPF80)+uOXzv#`7=sOjaqlD4Ms4dq2 ztbx67%|f&?Ma0_o+1F|Bp-{H+^73SUhrodW#YY$z7duc`Z>q2dstzMFb13BYFm8Bc zMCS>7qSRE>MFXn&MIL81_V)H>R#t6BoE#pfRzegwZ{ECd_3$WlJupyKRz^Bs zqC`kLIBkd%w{>aG4cy4LU)mTj{iCoYj&7F7f#`9Q{AOS-Vx;CTIQMuZR|N6C^G0oE#xQ4^p0KKpKQ3IC5lctfafU02pXwVxp|2 zC8wc5Bp1g@&%@)a(Rl_YYGh>e_QQuyX=#*9OiV1=RgonnoVVwlqS5j3U6bXO6SXdE zg$oys0VUo#n6!NHQuW>m9B3CkuPThKFOfw6thc+taILD?Uj7 z_3M+%tXmNH_u$CL8)@l>p@eKE1IhexZKn%ClqC*pieQI>LqhaddcJC~5TtsYYRbyV zUDP&S32r+J!iA17fmK~^n~IVilNpJtf_&-*Q}tQ-K7JsLNRcuYdl zb9u6rlbhSR_9a-d?QnyB|M0I5+^0`xX2@glE*(_uj1Q5*B7F6$3+{co6nM4|Cz2ssDPP z%Z}+c27#sM)H;JlZJu$NQ;?SKN?%)V@<9QU29Mdf+#LfJsKE?IPEP(MHg*w=`%KKW zzP)WUlm(tf_4mw7e;^hqpT{W+?~Eh9N|rn|JNtfgyoZN}+d=^0cq2@7VPOG05DP(X z4{r9(RX`ug*M~-;R6X6Ww6?p01R{Cz*VEclYj1N z_N?k`)?))irO{;B&Iro2l-#n9PU# z%FWFU#`!`-Yy5+uo<+Z9%5mEFpx4i`GJ#*D?z~NIR*hsl@TIMM2aCMq}+1s(2w$ZK00IAjVCGW zYOk>oLH0E^_RrLmoRSibVQ08;$7kYc7~&?5{ID=1!~fT>=ZlMr=U0sg4+{5nYMbhn z*wSgp3@tlH!j->;=@(*m9&LRm18yS*N=pMZ>oKXdA5$ensh#x^LT(*>JF_Z+M z0o<0OdYmUt@`4D&+kvqh5IleWeD*6h7x~iT9x#W&nHdEoB_$YnZA}fUCgCNX=FZN} zjW~8kXQv@&!d)m55fNe0EXjbm3MBPAPb^)SqeMU*9bbYSpQ&{j`tzq{V<;OV19&^XQ#r>#O^qxn+NhuMBiHU$AYK$EQfkt_=!YYs zw>6q?WNcjQyfYcvld8m%Dw_J&a@adbaxB06gISf0F8Tr8JZ@j#O zLGYNF}kTFlCd1#vTn=+9C}(g5pNG%z?~0fnxCsDu*3 zsI;r(97fEw8f{-(Tznr5O+`ba3)nwQuUO+DI(qdlYQ{JJiF3EHVVlXy!otE|;^InO z_H==ZwjQqZ5{r5ZQBzZU9wp7S0qgcd!&y9VEt=W^cw}j5NgU(}Fysj#AwCgNSI<}G zYLFR3)mgy3SHlH&o2I6cT7z)TaK?CkgAM5c2<~oafiabpm0?!TKs}d8r=6#)%PK2X zR8=KZRECUWDB|!zx;<+|crnPwgE+;nudgq(--L1_ehBi{XAp!z_9YT@W?@z@prfMt z2*TFgRPP4h;ot`vYDOy{<0KjFPl0f-CODqw%Ix;!! zxS`>krmVF`_q<1BvAHX3r<*aY&7$0Z2vsVa>|1trP}5Vw*r~ec#U2)=?n*0m; z;z|!*{{D$Q#|WXIhzR=l5vixQ7X*K5A)#b?x!7ma^nW?b$7p5yFrvU_U<$2+*y4Z9 zqCn+`K=yx?Mc3AE|F62?|0=Ai0I221figNMjd0J|>@@Ef?bM%6-Q@i`wK8fwJ^a@U z3M3skG+`4GuR)<_?{%n37+GG9yT;xtC_14yAafSn;rK!adWL8JAfMi7?^%Xh+0s9l zsk);AIyV4JysN7VDZRG#D$%MEB;@R)7RYf}SeUC&s%6Q}H(*lp&U1WlG)ZLu9(8nd z)LFRpljCAzqobl;OG=^|8ynM-&ju5ZWT@`krYt`hvwt7wA%&jgeH3xM7C!m7gVo4{}iEmka^D4w3K0Fib{;u@TB~oqH1FdR8Mza01OSetG_?9 zrsmQCTG`N$8XD7Bd{p?x~i`!!yJp{~$UO?nAX=v=duIj9Z4iv6e8yzn3^cYZDMg3(sxMb=L(L!2Qu@cCt_HDgWq!o`j9eG}lqDQ&ZpmpZ=#)EVfvQPo&$rIn560ovnk|sbJN=ZopE{zJl$dXSG z)7B=_)zuyIM4(}lr32^TcUaXvvW885VNwAgm$o5oOViBkS#xtUnUHHFz{X+Dd}DoK zXBoXlv?t9$jZNe==FWag13}fj$T}|+6$y+=Pn6)l_h-_IEH2~Dk(0pw!`G~n1SV}= zCZxUe=tGcos#4xR*`4f=gZ(t@hmUcdNqVDw{}G(5G~HGxz1r)+ypd(APGM6@JSH{q zWxC-}XP8US1INMH%?^*%M-(+)c#c)Ju>_Gf0}et%`|L`2w%V1v;R}@+^WzC`bj<~r z4I~9g{$(*2T6Wjxc3@fVlB7v#LRJ>T_05fx6$}sypo+p3ZET1$sI9Ht*xp_S>9)g& zbHTp43l7iz@xxF8PioC$+w(C%;*CXKI&gp*6f7;b%!2F`!Y)f6D80wtO6^PEmM5J3 zhE3q<#Jz#;r8FnRSUM4zAf@Sq(yybJa)zWdZOO3JZOQ~W$DmNyU>@`23ss-%$y~l0 z_0Hcz2$x%rv7g>*?o0PB?faK5#PRtH)EICOWqVS|g`x z8jYn;>1UYPjVm_D6= zFZ|TMW4jjLGs}dte>8bC=lRtdtv5$_3$@hmxX~kC^+%*ap>Z^1H^cICKxD>OA$KT^ zY-UJs^4d3NC__@kn#$^Si{P_QZ_Y&J6VI}H`Mb3cED7z3)50csQ6Vh1m(_F4!YfAD zW=TSwm8CYl6wgVut7@CbHuajt(E0=1o}^ecS^LkQ_dFlXm|(jW;kkHBVcoflBf%dW z%3*t(CVz-sn;8 zuMbxh)vi0O8H)FnG&$NS1exKDZG#`gMsxR+-|B`8VXYo82^|j^kE2;HrJt`rN(QRq zAve#;3#|(V7F`4BVN>5(3 z;fh7aaGfu9++Oooez_8(^+fs*CDiVQ-ftSE*Om^;${ek_gMn+FB9nmEM9gHSl{RMN58KwvC_?!ch<@_5$Z97kd95YDbj}9}PTZ$~;7V z^MYInruwSe9xZ$+LFh;pyS$%*J!naz$d}s%Fri&uQ@o2m>sv0W_!PNDaogpkMi_F7+E>}wp;Ag+Q$D0>lZXt z+N^nM%mBe55z=P>_T?@Tm6YJMvP(-#H`!F;R9iiZlXDLv7mNjn6_3v!(_9zOn+hc3COck)ta1WJ)XJAfOH);Bj7 zN420UOA(^G2v2VW;CdV#9dRir6lG<5-dq7XY31f@F1x(^jzj=Cv!l#>=wrje6@yZ0 z-*Aq~1SoU?r2vM^Z*9o|_@1ql*0JHZxV9!`Z+{qB{|lQ^L>{0n0R91Dbhz571jt_O z^=o7-EG)pGL`O$I#KvY|V~YSYJ!L$-L*D>ez^pViHTx2|F<>wlAT9vkMg^c5h{f#Q z*RDv;d$Tj5>T#_LdZ2s-t980FC8eT*4{93#{LVUEK$Ht7;}-*2TP^qN@USXUU0ofh z7Kjd$XQU;Cncl?lRt$g52qYO^ZIl~LgXnD|Zqd#0zvWi=f8TtitX@bpJLflLiie6t zSO`gJ$AArVa51NF_qHA+Gf_jex&u~(-y7YG36yx?$w2BclO`0p!^4c?1UBwrD)DO~ z%2Vso>GQ5_FjpsqcwxF=n#{oV{2wrD)=rBZ-MVzU zx}o^sQ_wqIXXa`d5*AtY=-hX&&FSx@TN=S+cq7_2ZI0bi>!MrHdafR7HtYw$% zqRj<5G23@jPYe9N1bb3f*v#}Sv<9)&ZVS#`V1qjJ%9pmLZdHkAf7{YnV!Gion!&vd z3uk<@2Z^FOoVZsndNpE5f~$LF7HWx&>L|jOq;lepkv8pP-;ENrM04i`AKPRZNuf^7 z{iL&z5y*w&w0Q|7eLmwU>OW9o2_>Urhlpavpt(pvv>e)bs02Rk?+SlWZ=HTN-zW22 zOSr0sSw9uU*1n`gL0bC>K@(9P`5~IA3^jcg-KeK2gIWx!*o)uq#8xp#yDBqm$10Z| zZscX!j#Xe3t63R}tI?l6#VMZLRnV%(Xq<0&gO&Y!<55Duj_1-+!S{1Blm(Xp{r6vp zm4YZ2#LMll1v`?yesQB3{J44;^U~FVsc`?*Pvra+)f5iHhzewNGgGwOIovb60Ugrr zXFR1w{Xg0sI1kPrGZ;1D+LcqTz2mV%&dus?=VlBwJvua3l-+<;8~?W4{_gR`(JGLX zk%y&zTwL3BnBYPq*GfAaDTM0A1U>bnqKMp*TklZ~xGQ8nugjN!aK8WG0kRi*RdO;}OKWQaFO=fN zix+@HL;gK60V*#~F$;_5uV25enxW+~Jv=$gvl)(24iru}{!&f!YPt+}@>ipi4d_-N|t6}=q^1vS;UmgiVutZ^FF=-EJKyl81a?1 z+Vl1qhbszS`O~b!{n95C_R;QFnZzHCmL>4uUKJ58@7_kfal`5h3#VmuWPZ^3OD_>i zXyuD~b4Jq6s~2v9p%1Tn4D%A_&VKiM7shyHr}8xeR|FTpVs@>X|j)G<$`ON5~|)(b;w_I!j-*S z(4*oi@OQJGf2!QcxKAp#$bvb8+BW}iQnowfL-3>Q>N5Wilw8TrzY(A<Y&1X$fgDewmdHHdcL)mC#0oDkh7+DBvDG z+i?4aqgc_`$WV**AZvG;@LT(Gt46V#*f)X?_j0q3Wz62F^A3g4gTqI;tk4(JzN6mHon z(xL0QQ+i|ZYx|1!TMSXRN8D@fo+(4gQm49vc4s0TB@S#|dIWJFCzQ^&@{{Z@%El_I@WX6HcIXt$t+tTgx;KKp>; z;>C^B>>HitAu_%Zq#=0!kCTn7iiPBebeT3K2fcZ!43V_&I6HkQalte9!$mX>DAR2(HT!ZMnvEMK9P?M8?^I?d2PsUZ*M_}CV06ygQ>0Ou;|;6p&Aj? zaw59gxfXZfALF_vo|gzkPRtS7X;Y~Pf!sO{1)O*^O>XO8x(60SudGtUHIWFi()C@uaD2CO`PRZ8BnD$DQ6m zne{yQQglElYO++#hGj{XGpDIAdG27Rn}Zc^#mL$rKX725I3)IrnO|YpI#kaEon8S~ zSyQZffvO!_-6{xm@U0fcYdZ<7(HlC3fHxIRMz@`N&l2KfEiCZD?YyMQa(`f8F7BZGmw9W3)isKvBj)f!5P2S^re{0?6;SszCeJbz! zAd#}0*L-=LO~{o3!Nn$aMc)ZbyaOky#q#}sOM3LaeIWc2c1|XW*q@GL;95Z6$h(o83+3JY zM8*k9-k({>ye4&mLiam#7Z$5~jvn)|;!d+(!Z=w7uGd?3Q2RnM`rsxv%!q-ZH{C3< z^^xo5%Lu#P8p40l|x= zbE*m09uDVi4bWI)l_dgD-R_^33p*wXC1o0Q<%)AH)AQ%wfBpoN(FaWKm$Q0P#1=oB zKx-7h>ajGs16LvO0WDBpw8wK8UV0ea)g7s+6g9QAfL7@%TC%jZ&IIK}e-iH*tPn6S zr>D*x5tK@=ULiR-IlbiOeoRc<-5tYdZej7gqM|}{(0R3w82Bjoym^)MrFm@z@XMW@ zoogi=B!SH!nsk74{*09s(E2{05!h?Ba#RicNCzUr^l{g+HhgWGn_a_Z5QW`_)v}@S zd@<;q2c@-mu6y>IxwnlLaiN4@uIyVQL=|P;>fb~#e~A`)=(Z?MN4UNd(5ZSAJmHB z4RM-cDM`c@nVvb9KyJxvkJR?ZT~t^RYK_5N+|CWfQzgb2=;-Ku$^3n+6p%9g=~6xy zsGc}$MxKUv^oz)X9|?ILrtwo}Jo~F+N%v=o(r$&VN}^8dNBSO_{aD_K>k`73R$Xq_ zOlK}ferJbW2YHc|F(TXD{faDf&46r1=HS4jrB{~fl42WGyh2=^bG_A@QqWxVl5r7x zwZuV-0ls1qb2%fW$u2Ya%!TgYHTLeZZBFo=?LmG-VRU{+WnM zz}nBypIS>-lPmBKjm$H!&q@p5V771T7?Z38M~{|wB}RoR0wqF&qU$`9^KEo5J1HS` ziVhU?8_c%J2>0`|_Ey7tO7O4IuhUrPTo{MBKl7WvC{;UX+KJge9y0N&`zw$0*R@vmx^JdUS^8d zYXefQbp3&^=P21+J#gINjQ=9_IHT{OpoD~m{zy+pfqkt?^luOKQK#kE|@zxZZZal>$yN zqoyVi9JkfQz(s;)Z0>qApa9+nWi(ceC@5Jcr>210+@RCbwJt`A-vS_VwgQl&$ zMscs&@|W4ZU1Sa2m3RuOEwjeoCjCyAUvRLqLU3ZFc~+u^B0?V+oaiX9{(O1})bqfBB^p8m-$ zOM06vF7NCoTAs*5aX}`&)#fOopalIg@wmqZr3+pa{!69>Z@Y{-c$mYuMQ_o28F(X) z-l0=8kvw_Gx<*y{G==N)}AGhVZeo4DNW+c4zV#7+>LVD0Cq+Zt{#^Ar? zRgsLhmQCP46`UR&9fRWjC*{RL)libH7M~u&?>SNzuhz^T^4KwHmAsB+4jXA`s2VNB zN)`H~qEyrmY%5|X)tEzaa@yWZK1?HPKc|+AJ!cu4ddm{koguo9Pf;rzc{nZ9GcaRV zJy6qRK)-)kQ~UIe@`++A{`BdQVwwmbRGC53H#08}Gqn9q9CO#rN8H}L+=&p7qN1WeiDi3vY(8zndv}@AQv7rnQ7w>9 zkdTsY?Cxe|WMqg=aPJ>o?5Mtf52OKCfoIv!s@klqtlM!U5YIv9r`pQiECa|+^mvk( zo;?HDDgngoTSFvvfam~mY+E}6svrH*iMy_Tp#Cuq|2PngQD#rCZ-Wc zMK@PlySpCZ6(BJH@Bn((mxXCZou1E7A}(yhPD^Xv?J=$JYsn09V63t-(pPIPmkDST zH;HVY>|m(aEkg}jLs3Hs`HBDuBDCe>a3qzmq#}I?>8xe5Zn+9ixL=doCAu5fu!U-P zc~3bHUVM^?MHCuSq}k-v5#XZDX&1NSV?@6~>SDLQAdTSLa zGUwAi6;_J9&E(|}5r5O~8vZm|eTRx)D7h)z)4qbxpet=D#jL0H>zIce;^H~@l}wSZ z!sZxh>=nU?j;O1S+&m0vMyJH5KUzZ=SrYhQkb60qKhyoI&9U@T!aujNqpX0PuvXJP%o+7Ds0BdPn65^*vrb?J^^XnR~mn%WsFD zD!N8e>Nu^ubacZv;ISoKdFSspBI9g@;=(>C|HpsFs+Y}R<+!c6uy`YfPAiRms~yW$ z3Xg~DWo4pWpA6kemUUjQXNbIV$dQws?H12-@fbI{Z+oNtBDB~?kcxv%5AO^Kt@%Fl z>DKiJPO0rY=nhB7C8dUXczl9l(y9Dy*5ByKawB3|wynr8$nTS|CaZgI>~N(-ygpHV zS5!+-DxCaE`^#{d&qQ3q<3BU1sTNH_6W-lT-T&?iW#;FH0iDV$c#*ZvCGG^`!K0w{RRpupsg{twr(FAi_?PEe+B%(UFvai;s(j39rS$zFbM5W zw>3eduA`RdoS&038o(?7hU{u*02fNYrYkQmj|p1BcUJ@rX3(>91%#sfKD2kSFa>4c8-3~Y$2LgeBWOXMJvbMJV44@s5A&H5xay^- z6nOm_G9?$m79AN%;8CB+UT)?T6(a2ep)5s@+p02NGLv&v)f3Ofct83*yMf$}K6 z{Jqn50j?;SJ=H}ohd%)lZKgSQ#AU&zpVd@CNa={*0;S@x?|YV{m2dk>^tknjRdT20#Y`cfV|sm7NfJ0>YD-CjVu+FZbf6+>s}(*=ikXX z@8dCa6{vT=uT-t1!kIS79%4MBh7&j;CcVr;Qy`>$_JAW)(@Tqlv6`FZqv8p(Vn3ES`KylD}h`sexSw3yW6Emya=g^mT;z*5)0yD2dA~yfS zaNI}h7g_rm3FlLcUV&Jl|0;God4S*~j(ipS(w#O%$yU3+Bo~OF+Qu4hPjbWIy}hBp zu})zrk&&+e@92AoO#cS_p0 z7ip=fB4%XjhZ~08wEGs;HYE1@?UU||@7|q0##s$r__hykH2P5-IOol51KQmFG25a- z3J1w)`?jBE&z?SxB25U2=1n!y(Rr>U6#ZS7g_Fj@<(g4xul#5n9;YKD_4A)156fz* z!Wz&LNNNSz{5^x(b0AHlr3`JHPC+T7E)p8dKyl}J*v)u+ddlgts|~udQi60nJw50+ zwKdtoKSVs|x^gqwv&lMw@C|mqf1``*Yelu2tB7#ci?dD3Y1!}z^u?^;W-LB65w5`p zvr6$+cE<4{u<_dzUsAC(5+qtbE(ebEs5nwu@Bigcs6Fp*P`l{x*;E>Otz%Qip-u zazS~ottUsTDPWyHvsgZ2-nDz@dBa_Qn5k#-$Mw%&lOoOdTm;MhpBVq|-?WM{O#k%K{`pO8_y4=>ze=Az6U^#PzP+LGmlQ@~ zSzv5v$S*E#?0q3`Ud9)=1{A1^3f!0ep5WoipFe+m;Tn6nx=;-nCeczhp!H{slM~MR z`%1T{C&$NtOtKXq1uqZio?QOx4Tn~yaq#v)|BRxPDPetm>xaJtR}vBpbYM>V#9Lu$ z6NFIc(&iYY&40^qmP<)S_r3m}3r$+k|M!)Lz^`APi@I54{97#Z&l*Otah&{LuR;`# zu4c^+VvGI#6b;kED*ye8#dJ}$@(QC;m?If4S%hgBZ6v9f2gXi~T0yvX)qh4dd>K~R zv`D%AxP~}UzqXVdG?StktHw`gT%z>8x;OPpQZSlSLWxPU5%B_XeRak+!Zq3aAH(P> zH~H+0#G4#$k~k%VS<5Ch(_(_WFN~K8kd_$X#}VHv6+9 z8AO>P+&f-LhwZmktCYucNx}49i=4u&;)$D_J$GB~@}+}EdcKAvQTnrdN>58pR!)pk z>fQyaAN^jn$jF@0tE2VtA7{GnlDfE$sB7t{4{QA}H=>~=CwPDSdjg4mhmObR2u{dy z=JY}y%nQ6Ylu_J|(yS6Mz>n!L#e}`*owCOD$eeg*UL>@`)0xs7Ej^Pj?q*D%ep=yV zINAC_6>myhOAaGd*KeL_C|-b`h(vbcY!{+|czyHi&GY}YRL;YK%J2t-WnW92hCIml z-Yfl>^5b9)c`vH1Xk|&Q#Z@{18I-Pt5}{)>b_gFa&TC!rAb{3r=K!*nwkOwCy2p0C zl@yk7J^wCN{@F@C3<8%*LHFEZM1*#X-L{0sgq67v-}i5~-rF2htcG@X^QxZo~TIkGkZL9Avcdco(a-tgX#EBfWdC+_s2IE{3v=~3zo!S;s zRWOWT!#7X?g3<@_2LT<^PS;bl+3_{ob`;5kO$%X-i!0&;$_;0RfBZsSEtj0bhk1s! zZO{gLDOd4D{j}=#vjS++(roTolT$h7qeWP+8ZcPC>q}|!eQfG3$!O0 zXlkVg@G1W3-@cv8y{;a3F8Osa!*akJ>0 z{0_3T@IEB&^yR@LlhZ#V8G*jp>rO!2959?}bKm#ii_IEbGeDIeu7k5sJpIKPO%C-G z^$46=f+k)0+G8PC=wwn~k(^($*VpKtz}+HwEI&zUnK0BhFd$+6gHH@gNXt8=g_g1& zA)WN^%;Wd9wY^lENs%7gHNCj0AYr&Jl)4!F&TiJVaxvE^b+RmYadAd4KgHg~t%MO& zs%t9s4m{V6t7nUJ_1?SKbDf36`wR?oy?z+J&0jl@5T`uZ;RJSnVx)Zs2Xb_vQRRC? zBMN%Oj8P5Oig?$bTrcKy7mA|V{6rxGs%vQ13kf@}a~FJ~8uPsi>fXJ*L0;7>f)QL> zZ2~;2?}x@0nv3MAs81~Ol6jF0BQ=KnLc1mpDXw}*56;o_9I=E9UXab43ha4%eyYKK z_%PhK`zE(~V>%~iA`YIji)3ILzSh>PEYefBmR0Dl!#B(5;Ks!q)S5ljOxDrg+t{j} zeT9AK#rO4!0J=)>ZpZ@HN=|R^u(sN~4*C7w!PT0BT?Z@%0^>?O_1d~PiB)D`x!@4} zKr{`z;i)JanzhCiGA59Vo$Jqw#Ng(Sx)8jj#{Zl!w>*}cbqrBQmupn0!4i_vUCY4= z7=A+eYJ#z_!ui^O~bX>OjWPv&7(!8to4sqnd?w86$0 zynRyl^*~ntw!jCaULuGuV|K~v?F0GWRE7WR+xB6YTXu#Q-72)?ote|zWWpcBX`9T6LOt#{}hIPjGUk^wu ze_Eg#miXnEpgXvb#G!hS_#Nxq{VHH4v!(SB%}&Y+bwEq7ah7aqa;apH5@oU4H;9UdvF z6Qlja`7MXgtEG_E@6*0_OoX@dgyr~9SYWS4JJhA@cZFyO zZ1UH5an&lK>;xEDcQ2{d2IR<;#&ehpH7|J{Bj{`PyPXwn_Nfhn159vf36E&+0XKc8+5O4h@OLv9 z`1p(H>s2k>b3h zGPeca;=D#@`H(1)$2PpY28j>-#TplPdrg7%OW1$nM}kGU9{M5q@l}`yWFgZ9BWDBM zaPtYquF8d#`-XKmcHb+U#p@Hx@L+mp-`5VB6vSGGte4f8@n4!09Ac{6Hdlfgj$Nzv zJ=z_=HvaG|eB1CN>hP2M2YLOrjzImFv4?}Zo)%#t5`n~Js;f~4-qbs<6n0HYK5aI~ zb}57m5m6Gz7vcTq-Bf!lokrozfuy33@6YHLe1*q1%K{53*>44|f-(FO-6HH5~*TN^gDz6G^tFCBlM22&I@o;u-G;QnpYzW4*YHtIodQG}~4yLLGEiGz?9@F!^G$w}M=PZblvKl}i zPV&#D`g>ECNX6MNaW4_O|H9a$DzrAEa?|8cVK9y!69}m5;kJS~(Mn~-Msy@<4<9bF>3vM3+(CGIl`k(n)&C2P^1J;O zs;(ekShsLZoH5Jw^-DY*o%ahVS9+df5z9AX+WcEwrrS&-Cv$CTsaJ!_YUR7ebGJO} zyk8b&+#;hotzDGvQMqLVrrq=oS0HXFJTaEu^IAUR2t_;~4PatR~xQ!CQwJmUa|`|ZkZ&HOO3Q5{C=q%9mQWn$rzQ{ zYpa#uSS=!}$12h-+S zG%AV~lOjqFjJ}hn1SB>!2{C93#xT(;5spPehxa$Bi7uneKlhUjynjP%HCq-HCTPOp zEcP+$WaK3|2D|fVT=klglIU92r&97csg)Qo(_X{V6o|=cFrAjVcU+p)cvsCBbm7xb zzxvwXNy8e{aHa9~%Spe&OXn{fzbs$6Z07fgmS?M~S8ukx)@6ps4ju4$(4v{sHjT@) zV;ZkNxCy)0wRL*UNx+)ea{6>`!8A#4u``xkv@tNvbIrVB*Da==JTrq4`5q=2PpYMf zg1(i>9AeIoP9_@sWSqsFjTDAk7t^N5tyy~}L#>6pgnmy-Mq?H{qfpY5LkWY8%U;_u zxLp)^n4)YAk;08KyP$yzCIdTZtCvy4pPwbR1y@40GQ8dTZhPVq_*uH6 zb}U_wi_5J%Z{HNuY{opP+Zq0L;pT5fMIk75IQ*20h{Nt4aV^h~BVCjKM4F-VYot?0 z;h6Og-q-o%rrIkHi%T<#&&snkt1W01iiggGeio)>NxZ;ObhGYpKteWvRKyW4)HPMU`H3H7m3E`5f#YNZk&em1bcs1TI0? zrV=E3*Vu|xK1%ZDiwTqEdFO~f?v0@>rSCIP+mM3Zf~!s+@~2!%aZ( zks$4M@FE`QT9bCbm%22KSBo%h1&G(;G@=?=}1QJDUYR$E+tmpS{;$uegd~_4(XKg-pe+Pk;d> zauB%adzaG5NTBi?Mmja7HWaJd*FyT|Vq}TbZ3D+T(t|w4UT+TrUb1=OwXAbRY=V$M zokDD7tJb?U#HTz+_Uo@TH{^pt9=`Z7k9xZe?HSjp4P@-i)kJKE%HPH)MVH&r)+!<8 z*G|+O^sP)Mx|Tara@lNO9@H39_Fw5Ac3(=F1mhN+HQ6LawD`y9uxg5f`fDy9{{NaNulX;gv{vokmijeoIIy2Q}^K zHvP(-FeT#jg7z})`XTk(}3%_lY7?{Ak1q=-eixwyPvlp@JYd)j1 zUHj%Yx}`Q9AQ=|28sCo;+7oQt%S$^<-ZL6I5B?Kz5WpmOG2z#!cNEK=H!Bh{#gObt z8RXFKtCe7XXyj{zgMuo**fY(YH>uoy`GdM3RZDU^BwMrcl*;<1Q&~G184G^c*Nasa zmNL*1LC~6Is#$zHUri}x^7ANVwlb#U$57ScPK1c{GZhgB${6TmN6lJl=HdyrYMpYA z@YwEh`Q^Z`vF4rfJW<1*s28LYmj?#m9mtO$bV{YqFP~A{o-UbFmvH%Xb?+HOuk!wQ z^)auRnkZ5cM&-6lWyfd9wC^|o^+Nm^5=6{QM$ePa^?J7^*ulN}`e9oO^&^C*yqjVJ zqHdw^58AyfCcDCCN7-TA*PC(h(&9}`-OHFpZz=EpF;<)ULV?VCaY`${^7`}Ubh}kv z7NluOy;c-IH&@(=gjivq*)*}rF$#+X3Iq{8>i^*q@9 zyiA$fl3%RGLJs|4b6vq@UOIAT$YdE76H8V*qRHP-!X2HNv{8M+XXnDlA-OL{uc9 z^CRPRbM)zO`fV}f>tAJAc%Sau91fk9c!?Ux$M-CMi{x;|q`l-WI&+CQTJri~HaFtO z`g1_3Yd@-0|H#H0G5n)V67`{C-Pa5C6quSji7id@EIF2ysAur`!P)6`sYSkVJ8U?z zk6d=&Y)nPkZ#foWv;ns??@b*LhB@^L#_bE*MUHuwC$Anmf3GDO_rm1-^huHM`lDAP zEHUjR8sGTuSJCnXi9!^vTY+N4Z%X5JN)n!G@sw`z3MP1N8D(h~2ksO?SF24IpJ2j2 zN+kDf?HaX!w>ux*Lvz~^g*E%Xi9!E=t(|pTRNMFWK`;=Iln@DJC_!3ULK+DP>5^8E zZjcb^?gr_SMmhxP6p(HhKstubXV1MC^nQQwyq?$V;U5@g=A3=jS$nOu*E#3&PDk|h zU}a-9UspD~J)Ofa`%S#N@*TC>2r(p9wtHVAQEI9lwq+hwM6JpFv2o?g@U5Z}7ox(UiemFlT(1k4rxULGW@p+k z>JqMbJ;~F@sJ#}>2VWN)a%xjxH5_!}R)bjWbc=EGXq6^to{vVS6gp%`raFE^!4!O^ zFR-kfTuO?HAPokxOjQqtpr{x#e2HM`1ZQS4C z7qYJ$TwaX9&Sv8}kP#x=UCYh)eILiGss2`ZeZNpy9kKL%4(6)e&SK;{uNWvGMX`-x z!nY6}N+`N#5Sx)%+VQ^XaKpHeju8_JFQ-3B4SUHk0%LAW2dAMrtt&H*H^OQ8_BaWF z#drMU0a2=Oe2(@5_VRvkot`JI;~8p0`+NCT>~|kZVJzhk@iIfk<8Uo#d5$hhYuu;{ zHUBhJO}W-wb=megxk1Txx!f-Eyh-6iXMBgG2sGHR`P-)1n$MbYfqSMZFBe~``Q8FoSsbYiG3-*7lLb=~_1ZMchlh*md8N%w2vH59 z!(yNNVId)*^$-aks7?PuKq~bL>u(6G+m9bpANeNW#WFXprc!G@u6C*zX7Qkc4O5D! z7s{DzXxcxv`ZZQE_L)cRg}M3n2QH*t&^Vcyj`t%0RMzWKO_^NF1pM60s=#iS zZe}lKWU|R-EX1T>-t+1EfTO{_os6-JfF2*%64AsciEnt4ZFL^yRwoT~-y^`HMe>dw zV{!Ug4V%8@avfbvM{O`J%e*p9gVT<%%SZ&oO33ih#yWE>^JQih<9yo#LnhWDZZnc6nsYsGw zk&PF{ZpadFnb3KD@10;7%F(7oKYEeigMYvDlbdVJR9JrW&j!QNF&McsuD%@>VTt$W zi*wa^Z<#$??CTAlXqU=MT)(0jNlR6zET$Q9*z>(As377J=>PW(eh_zZ3L6$85)J-p zHUFtXBpS2oX&?@N?-5b#c29fZ2E}IOU-M&^(`Bs!M>$PKg86u+~pB&o$9>a$h z%nk|V<;dRmh##{W&ECY%bS!h$sw`g7ps-_dBsVZl4NMXA4vUR_D{%d#6*PB#SCGUB zxvZ)4ealgkwvyxwIUK(v1_T65OAB5NCa15ny?ypq@d0X*q3kLec#QqCt1I`lsl$3R zTrV%cGa2(Am;Wvz4?Z$D7dw(?UYk?yyEM&}p&=RS!T%V)pGxO?EHuy7BdQg`Q09H7 zrEiE)I&mXqg!L)?GlZX_DiPJl*oC~UBbS?NJSA)cPU6--fcy z>;L(5Ixqc?@bJ5+t(jcGyjU#y;}hcPwXZOt+gL`1lG+zLO+|* zms+7?TtIKywqQfTG4FV_6S8>5!j@#&a&H&D6ph(6;}cuFz|^<9#K4p0c}{h<&hD_y zE?Z)D@?@s++2sp9?U|DIH!ruhh9Hy-^J=baUk$a={dY;8Yh4|&qi>>|V_q}jJs}*( z?fY_$HZ;QIgPcYAe)nH?Wg_IKFf%^9^4U8GM?zUm zvJcUZzae>PruD|Okz32-+fgiCeHyM$(UPmHx8IV6km_gZ{HRF24?%%Fx4B?M%yD5D zeRDYM_pxpm`C_g4g_|gMnc4MfZxZ+@DivoK%jE0vh}^h?xHCd)zdH7A^^o!oT70u8 zZ&ip&ivXFlMhkPNYlTO<>>Yg>oy{qKnl9e9okv(tT+1ScxKknHNS{O`=gDFC%xk;7 z+~G!FQqPnke|n`s?qGNJ>JPNx6>qPakO>^I%gELj1ZjAa89Nigc)5cIOvtb@EsyVN zX8U7qkwR)_4WcHWhrWRs2rFOi+_GT zE_og=8Im_%J`~EL2~izF$Id2hzG9T=Zs=0v9D&38Z{9!m zC8Ey1gi-%Eo4?!1F09?H&{;tL$WDlDZ0dute_*S<75<%G0=Gx}?Y!FVah-F1D@tz~_uBV$YtPK4N{3XxGQ^xCq8se=2tW zYvE9-`TVbnR*qUvDRglHwr~oqSkXsc=}u3;Wn8l8Si9*qpQ#nx$b_%AZyyZHem&gd z6BNZTCqo>g!hrT^_lGfqCG~dVR{kS(4MC_^6|}s(e;l!~n4S5#6(=qG>ta)9yl1CK z5zdacz{8y%mxKa@ZhsodPva!~taqV77l#cwneaZ^gzf({dC6#l331;OIL7^OWRMxO z+F82ru&pC=J?NAgNlYaBtYYg`Jd)j<6{ z-XgI2=tz7`r&Sy`{@fyrszxnHkh}JMY&luVD@?H;F1Xm<3lM~NBnzbPq?7L(iPu^M zXGRe)xvi^P4%&<2OOe$SSvgc&-BGWLxxGp48FlBi3{P{Xl(GG0`)5Qj~kcSEqV-f02k^C=dQNkei+T0*EGS1;z1=rz+)hF%HnKB;-9GPh2 zTlf0BSYu8+PifATiC_2e2p=!q?Q~_2JT>j)UEA^Oh*U5M3b~vU?yh?xcJ4}_QBt+0 z7{EZro}bh{F6wY(j@4MlEj^Q8M)$(QElRzUmpwVhLq=bq_l`C{3aoxNc(PKLxbF+K zq2Qu?E#o3lH}^978qswYOs~%r70xl&9i-S&Uk!}O!S3#SOzd-J%ekmqKRPrPMpjan zbRsCL)8=HG$ZtV7cxyzi?*09)-~e4~Jc#N?$vRyo;pQ1fOQXB`6n(M{IdS?kfpReu zodxm}qQco{!MAhlS@=6PF55Lm>a9>3^aLq_&#jR*cJ9o1-AUJ%mkUFs>Y@$Ib6D@^ z8jr8Q+;p29pn+xyoGBYB$pF1SWWSh;(8uLpJP1kYkyDWe+=C$bZQ85enV~fWVN20T zI{Je~C4*tjTz8etWw1I%ly=XDZnqOB2{R8z+Pn5TBxIsZl$%CcriZdm$j zP&VpP>FIvqFy;emgPT;*Z%1(Dj!j}#BWZnc^>8F9eFAG^3)Pckj*h))%oXc}Qmaftkzt1E9dySxT(gBuzDNJD# z|3qaFi;R&v{;YTmZGDrg5gTu^#%C`wZ*26H%v2IW3YKuK)q8d~OnI|Q=KRL2?8!2Z zYA&t?TqurYmrnDj$&K3{(B=C47RnewX=?s6^O$iZcSM1bwg~3)Oowh_e7AFr<&3XZ zvw=^AxIaR*xTA$jVTeZWH@*aLKkJnbd~h+&1;5yNfX6xRXs906YqxfV!iooOg(uS}tmzsp7F8tlT!-$<;l04q*w4}((>W>@eAX<{M7g@+fa%-%E4=%N8zESqkhse+O}%G}9ve*ZB#-^B z@~ib6f70x?HT|wG(>LqlrE^F&cyUZk9FJ@Gg#&EDOiuR^LHq0;rCH?A3>#iBV9k~-5sZqocU_cJ~W=tz2WJ|kYQdkQN=H-M87pl}*xnG^t4Hsmr|ReBD$P4JvXf2;MbVcrc4{b% ze+_1un3c3=Zg(dudXToZHe@!1k$c{nn*_t#_a=DubQfyG<|(XF#=b!|(0|V1ky&y? zbXaPyh@vulz2-ULFO`2XG>+38^nwugj<{FyXfIpw%9Audv)anG@&FAV+2SLM4FWQ z0l6)1Nr|)_Bk?E+WfX}U`&#zY#P=$EZeD63Mb(eP4#!)d?P~dmtXO+`y`G=qo?j;+E$8++9C02tauq}6mhb_GyrQ0 zjUPU*yxPynLjUEO*6HbG)?Zx#G(zSh?DWAJCN)(YG-593^ZIvOoQ>2Bg*lXyu6I=O z_s>RHBG-x8qx+=$bP+6aT~A!IiR;`b*rh)gX(LP|IR$y8j93n33ruxyY>rO_+_r3g z_aRWL;po(2QS*z8VvSH=k?Ihi|nQ(lFkLW2Ki3K z3kW0+7Yu!V7G#z$$Q=C|a!{1GuG<#w5pxMGebzptN=gA)Seb#My>TEH$56u+Z-OoDS@n4xd%TSBOM7|ZIZ$IJqB=?@|(Hyp= zXp)nu-N>d3PvD~k|8`D=u9wD7a;EWge+Kkfwe{!{@?*4~>dPrJ$2G4p?8MKU1&w=f zs&ilZch{t@QLLMuq5Y0#j+gfA!Z|KacfM0qbJI+YT6Y}UgMuOSgKTRcZEZT!)j@_gBLV`XCsDjyqGsfomY3A#Bfdut=XK;`Dp_QCbXKMVtP%$1SCnVWs3)HYs- z(HVoo!^0DAuW}M(Uj;k_0lFsVpb=s0OUfJi(Rn(0d?LJAO_h*Y?@r?^|H)y6!Br0_ z3^_!SBrE@EW249Ij?RZdj*hb*m((I0;|~rX`MzvHB*x3lC}x3I7QnVP^gMr`89(h3wZ+YAf3>t~xHgmYMUPEX!Y2HatKzaBCzEqwLi9GTp=T+Ih{7N&_D zM<18=v+q++j_wtNRTI=LOw+}9ib~Y z;qUa>Mbz8*+JeT?H(dpatewTeo~)wyFn!CxyY+RoUbBJE&($>!luGw*%V5!{G%J}g zP}pP9h>kp6Jf&SDMcx(z1cKrCbNfeVsl z6cinA&_GIbpp!oLzyIZU3eQ$(0dnfy{xqh!TZTTJ6^lHsGNf-PgW?4w2~y21f!3=P zv6{VD+~5>2j;KGmAB;-lp!O)|Tr9wzxuc!LtCv1WU}f}0HEl|ZR-v}TvFhq!c{r~g zYep%4$?W)~mCKvQ3=E4g`18zH_X0Fht%>1wFA#zIru%JJ-WU?UCL({{eSIJp@G_)LdhjWM|JOo}Go zqlV#L-H2sD-1l0TwF07frJp{Zir@!T-VCK>^VxmX++_QJAHPmxPY(*7kyWK7v?Udg zTda!tgvBq(?mB*a=P!44>Je=vG~_~O=oi=Wbjog9#aMrTfj6xn7Q*qhk4|?#Q$y$; zh1k7z{iU!|n%oQem&PBvkGjklT^~Zq^WThh;%CpyNHa#bh#(^W@{v1r=FD?#@LaMF z<7bSYJX=#XKcu@mNLJ;FbYG?*Gjj*QH$Yv2&ygF|0BUDTEo@BVnwqfcMZMwiB0YJ` z<*V+q#b>ev3QcDX%1r^GiG?qjNwS_JTfaZOf4uK;wgKBnHw;c&FBk5vVMZqYZ~IxIzJt;j*=;};jlNzADX^!mr+8bS*w*lmLy^a-t#eZ7XOMWs_Mke=6FD)rS-OF~>J zvxF#HInX(8S`PE$4d=z6oKL;SkT8>@oe^cl=oh5ahf=h^EbhB}{hO>&dtW83iTmr6YLC_y0((o`?L zZckzqk!<9GiukWmY#(C%kgT>UX-N>#@}&d~VYtj@NJWqF z*f+mq#a9*hmVQ)Bj<4LHIgOAxzYL!8%qXKGpOQ6+jt!rI$s!LUZu7FFUC}7nV-Z@F zmT-a*z9z58VCz;&iJ@J61yg_QcG@>`oBY2xh|8-AlBh#8*bWs0?vi2Nt+VN<`(fng zXN4lPmZN@w`xS-kzxKp%HfM=-YMNNLWH28-^9?&gC}z)9z7QHxLFMUqzsOTZK5MqHurm7*`LOb+DvjO#%RO;R?La|1T4@qEY z9@AY&&gGE2LfdZaepPHhc{A-lfo^~k%80$5i%@hBLSiFzWUPkU- zIpy)4agkJH>f@hERdyX3bO|nwh~K_NqE>EgwoE!5s^4W;>glZy;w0_#ih_5A1oo34 zDf2nFo}afD>@2pTH|Oh*DT=J_(~bytBsy@HwxQMfxLr-!58GoC{iq+mTXv)dDZl&( znOZkPhN$X5+`mk&m+}2=QU!(meQEGTtS+V_qj9-zg$Et!DLP1Wj%Q-ce*~-17rwxVlwS{ zcOzsc3OPi$ce`||f~*SXC4*6NuC5_xl*t$EmM+;B@_3eq-PZ3qlT&wx^ywPrUCl?n zR^du@+{FHQVem9Gh|KeLF10JAL^_hsu-uO2qYBr`9}L&!v*EA)t);7+=8z*~$A*LS z(L?aLBSPaVJof?z6w4XaRtch>MNffTwqe;Da>dP8h>@6qSO;m?4I7uE#R!n!u93wMOLD)RJMKjunXAG6)WlPFTcwqJB&WyrCPZ90B05#v}Y}br#YX>SNThShAlx#F# za6?Vam)qxNS1x^SvC`km{nuqiPy%O4INI_GlMAMcuH{VOxnogut6Jh)we4-+0BxqT zRrs~%Z){#z6MCML|Ew=@ zC*G)v=+)?M%JYB(Q@p)hQqtSd7j;z?JLdhlHi;fw3yirm8zQNu_`I~-@ZCXk(4^`_kTPQRLsQt`IKXZuqBQ8qX z@nsCy69ML9*G~1No(eJ>w*L3871)}oYxSR0;q!2dJCVhobrtG~bU4&=5#P?%QW9Uh z@E23K+9pN}iH*d0v3-N>b&m$3A+ePyzp6o}O?h4AYQ%sN30(Ki=}nVqj<_<2+`G|# zEexptSS5g7M{bd}NiOUc4ilfx#Yy31b%p#tm(n5PCGx9sKBk(2$JI+#$wh`p_wN(= z)Os_8o0)#rdHuBGa69hG8^yO2|G4g&DFOY8pPlQUP|6=+l$%mgouu66gwN9dN_g>v zachp^dH~bU{^zUM?nwy>SIvi<2$KSxm5OAYwhP+<@B2*WOg4LJ!PI;nQu=TEJ9bF|45R)=)T$g5RXg__V7NR!>6u`)x7QpL(iu9ya&eE<(ZKm z7ruT~uS2M!Ti^Kw>qouW?fp}$nB(J{xEU2V$AT1n&o40h%NpM73_apdl{qHw%0}tY z?j@#xKJojPTRg)qOvl#?Tf(tvmeQnDj(9v`QZ<}L@GZ&@T=k7z5DWP>KdKboh^ z|LMdFP`|OQ z)ljmop+|Q$$i3;+{-o=5h4?@VXdvgZNA;h6rklEMBS50JoV4thcU_(z)&Xi$oz(SR z94i{XWV8Oe8$%ASlP2gGtNi)m?;9xo?&@9}|3B^|`J)j-D7MyCtk*^nd{thC?YUUc zjR}zD!f-hw9)yd7i zihsqh{@o8(dGNXcPxEZ@f9xGC|6z3r&VNOqKaT$TT&MrMvuAtbgVdil)6f!K?+Fp! zOakp97DmucJ@Jf=0SBH^_guU-Bl3};7b6e37}<}83i)e$ui}JtER=nv-~fP+6agfL zO2(l=3YSsa&-C89qU{fOVgx*H?b|-N{`?0yph{T$-J38W(m?>`SeEsZ)IY6lyraGS z*9Pmgg-*T%1fYSgQp2pnKc0WogrCQ*lLXXEFU~beWUjWiqJDC?)#r-?Z;&MZ_C5*D z-%DI^iK;)A+P_Dh^Cm0eBmyu+%%Sa})6xqcsA44#Z0}xeIZ^446p(92%()0Qv_hXfk3bpv)OeLFBNyqQsG5ET{eM@i_&}qfPtzW-p zGom$hrmAg((qx&LnPXVrVp}bBzuBH`tc%G1$J9Al>h&^PMTUJOL8N@WLrPje`(**> z)y<3YonQg2y%pO{a0tF4X=ntDZlI-T1@xwe^VQlgT(*&bm)~pJ@1iV&Up)lfe@>7)w)A8iM`iXnW52Y=LyykG5bI zaGEj!45HzDqCp>=&9gzia~wbrd(#m{0SCeH97Dr_3BADqz`6kPPT}_8_S|=sBJIYU zphO^>2?t~471m2MxSYoTAQK$ahIyyR<=hb0*ryG@_mLI5WMQgcm z0>Ts-fc*i>Cpq5p75W$!hP_z}lU6L$>;VippyES8Mdj_ZS+%Ti*yDzX1m|KQ!Xa6O zwYzr##s#i42jDd&mWvVqCL&FZJD)~+P7N@HPXShI{un$jaB+4F$T1#p`U;>4?(~?s zgo{C%?CN2}fYMh5&_PFY7_MR*4=H0Mncw}S<^{AmAgCB)wKP6D3P<0-!Bi=)emy;; z1%BO(BLhdR0XF1uyC`o{8}9)V0)R4Q=j6OOJKBLW+-5E>4#BytLN+IpxK!RwSnKd8OWi1IUFLEEn+>yJoOOb29HDF0g>)7r zQ`WPFcMrtV-_~KJU$irQo=3+uE2{D_aYwJLG8uLHe(X^q{YpXdW6Tol1U2dFFpS5z z@FvT4>=ukCXpCpu_}juxk=YEdgoFeT$9Tla8Ef`oO^yA%U6uM7fGjQm#Ugti5^&ET z95x6v<$$wZY9DS+@$CPUhm(;irXBr(^X&j*`VSdISj3F)l_$;m$ z&I`O;TwF&x!LDfE;O7^pv$h2hlLLKtIP(yw&;pcY7m-#j=S1Q+9Njc1 zjRogD7U-dAIxOC=-;FE;zJ3GF4YZtZMoDtLa9CYiqoJo?0;eC05w33!NO6EncC&JY zdmIRB0@bAK{QQixG>^}p$y^Rfljjx|th^hr{!p#3SD>-M2jG}(FlCbfstJfp0V1Rh zAW^ATS$e{y=z%aYP#;VKVpM<%l!i|B>=_`L;QNP^8 z{m$ci-X7iElHCR@;GWL;M7!y#l;HY$UO?OfEE@#CTN(t2Eih+p19l-$vT8FZg(Jb{ zthu}sy@8r8;5h>KMe_dM2#(vx%#4bK1;-8Wun>Ba`7q!?8tC!X0$H4x9s@Wx1xWn6 zUci#w-Ji$MYg7vXNFR`s1A4tck_zs~!1&-74j!JZ;OOAUh$sk-KsNguztQrJ{b;of zT=z~NNcI4`+pdqg550Sqv^Kk}255guO88PzQi4fq+FC%I3rN_#Qc^Np&v`bf?&Rob zf4)Bg@=k+@ni z!!8V_JCH68=!=6te+oG}^H^9|ByigW0SY1F?Nv^hg2dz#9IQn48^6T- zf;=~(WccUwerHB8fmIn$`kS?_3CsloYzACKBNsz~%vI z<)6dD*tobt>gox_*3%$T!ecWW*9pR^dYxk=m}3$zUjlEM9WzYMC@c)tI$u?S>!X9Y zMg+5;_oWK(O9y@nP*?%lP)DHNERuZ_lYl@>O^pbMjv)ZGv|`gKE+9e+kBh+CfF3l! z(Ew5yzNUTS(FFjkQE_p_0ifH0WfeSp0BYp)ZW<%E*%5|uY|Re2fqS@HXzE*#Kg2dT8!kjzczyN@L_lI#U2$%MS>^~BqK=Sh%W4sr7J^LxzA9S^(~NFc)V4ZveU0C)mUKm!*CVbE|H zY;Y{VVnEFquo|_=5+0yw-8%erGCopoFu4%*R1HK}!jg*Nwq;e2VF3vcUM=**JpRAr{psz72Jw%2f^IsXap!+o9|W+r2&WyL=Bc)_z!S~+qZHDL27!Rz+Gvk zXm5WM!h5S>YkeJA`($rLK~WJz1YI7bydeoNLI4;1@`Y|;8EqCsJ}Mxi8%V@1_xkls zehZ78_cQ%RNA{ptVNX59{Vf-RNPag1I!K5H0RmEp0TLL%Z2`#xh~g_KDZyte@YQGr zttEi_7&T!t0EZ7v{^fCtRvRb`GsXAp?eF(bPImh<)Egz}GRK;7Q2|vs01&E=C&55L znFHkx03%1IranH{oazE%`YNEL2!Vmg2Nb1KN=gPQW!!)sA0XHP%~mp2)`+ZRmj`Y@ zMi>E90i5Z%nfdt}UX0ld4auM?l2uoiR8oqz-~+ndAPNH^CGe%$_E2(AJP;rb&l1D~ z=Inr$n%YFsVO&Cjq^T)A1qH>~K}7=vIk|^nl0)kqZ4eR1#>Rl=IIbI<9}FS~!2&>h z%BiYy={;m%U;rEC04z}uDZT;CJ^(cUryx5oj~omQsN(@VE4STdI$$1DOuXk=i{EH? zR%r*IY|TY&$@cRo)6Os{pxZYJ6!r3y3MpAw29cn2>UH zIe-E>h{s3A$5VSe01N|<55@%}Gc#t$H}U*ivXy-U1NF~O z_Te)Pz!HJRp#wBjG{8v{$R>j5EW!tz5BLq@C0_`@;OYXEQ^_QrSOA?f--U{U@N1$D z&-6fY)PAe(kTF&g3WXvdJ@WoOHw%c+xlGfu1OO-d-6aanFa_$nfN^LAlurTmMQ7bY zk1ZZ7EYJaE@F9n}8=xRYqZ6?aB%cEJRVmT)?Vr)+2MD)DP{V`r00K%BAhigm)PU>& zib8~0PzERPIE39Mv3CQ)z}rA&Zb*6BjKf3s9{rAeop?B9F(56&!4q)cbZ;VeM|U^t zi&!w!?j6xW*-5`Tz^bYib4!y=wt- zd7zj^(Df|>Lk7MMtXq3|ae8!gMDVh9$`2^nAI`Y)!QroPx+XwO0>mzyCoCs7P&BeW z(*Q4f!$7V9#gQq;^w3ZX5J3i~bZ)-IA3^X2bHzjth%a!x*_@oWqvwG@s~N~BFN0-N zMp01+*fTs4gL($6@c?R<(R7jn%&0!TOP;#AI#5dhfGAL&W&G#`aEPGNkg>9YgPYe_88(L ztpL;#kmIV%=Wc+c2WqT9ko4f21|(yEF)c4=gM*y4wH;YBWdnGE#QiMEc+Twp|SrX@(l(pfnEEzEkc zognfbY|X&c*8!R7s5JY~knoaYhz2BUy`l4KX12FyI#PD8ATxeO7rw- z#@DYyclru|IAjml#@%l~%@yQq=fj#AIEow;;8j-3zqYp6pVWbU1{lVI;_tEP%t}a`c__o&!}$X(?iWo82}c5UPij>mpS+|B)Y{;Vd>><7TJHipEkK z8inc){F&ZM*@9rSwHlKw+HkhWV8QY5>|~^Yq?B`gq5@8^2e?qsg1Ny^yWR9On)Y`= zffd>(ZSys<9p#Okbs%_ft}g?S)Ip6R2;^-6COzQBANq`;P6;n)s&t6}vtx}0&VLWw z$NlZ2LeP5w*|ktphBS6X-9HGXKJCAL#2H>|NP$0?S4D6oRE*z=I*}YU$NcLZE(Mz3 zr8IaaO*-XYxYB@XEKfP#aBPvkzN*{eQtftjX-s_XUY#FNtMx7Cpr7J9oq9q??xdWk=y&*V_PZZy z8OJ0hf%s%ZEZzC8j@+jCreGEpzq0kif*)=&gMZ7U{w;v$ED%V&93n%{43Hw3)d=hd zB^v8IL~SKmq-4XW+vS+cH;2^@v?&*h(aBLG9%hZ!J8)<5h(qa>8wbQtIq0o+UND%l z{D9GzHq%CVUfO)m`o;gp=ixPRh@Uyn;FPm zWG85Dg7-2>_50b8dz;lkKK|Hn%}1^LzSi|}+1+003zq@E?+Y^Kdq`g{8+9R$Hdaqu z@%0M;AY-Rg&l~L^K}2zruVEeeM3veBM!{=hHM<)Kp)n*hCVfdhiuz5uquiD1@=M|- zuWJ*fezD%-UCY$&ABGgJgAKYL%*khxNdr!G5Y=W*eOjZ8In-zQc!OeJDwUcTq-#F8 zu6VJqsv3QEJ&Kh@wzS@?)N^AeG=*i1eR7!KbRtWxl{)}qWnoo92ri77`U?dWw<8p${R>%YzU)AX5*<977 zT=U~&LsxIk^P189Xfe4YEwNFXsmk>sg$l3I?YunkosCw-a__UmiQ?wVPc1ln6Tu>X z7@D^VF5fIG%d}n$#~Oe7H2FmNXgxc7k>pKMNK=f|{9&!UWpGxWX4U2Qo!EMTe%We3GMs#=dY^@8*TNL71_4d>8 zjU(repZb&A@3;J#q91^dj3CW zYO5Gb#!oWc#x5cRr5VOH%HHL8zRRsIu4DlxP47)k zdTgaR-9i}Yrl&>=MmJ5qSWLG@A6!oM9$*xP?rIJ1PLVn%?_*HSyNZ55tlTnj{=-=a zZ9EzkKpKWaC)V6?sUuFDflqFv3^`vm=K*MhwdtK<>EF`@&nw{DuGCMME8tnR-WP`+ zA*d_mmsQrH9I_)_=()b7p}3?Ceji`RblDi2E_Af8YLap>@N7Pcw{?TLuc)1oL%GRa z_l=(L?QcWIxlY)>2Orw^>Fyg|!-8iCOWzuu*Aq><-9sVIi{kVT&#gl1d|}5+7)>J?kumW>Y-S-0l-r!Of?8Ht zSlcpzs~umm$PXL$ae;B&#-*oQ) zuGbQvV|4w~o-I%Pzvovjn3&9-Jr4l?1%Wk3oZ7mG(|kHI0?2{y1)U;%o=lR+1^3iw;>0SfqOlh@w^ ze%*5vl~H{FF0TiWQ1EYJCkYKF6S@!>{sv1!>w%okkOU!Kw3=V2h?zJ|#+R?`xm7&b>c1{M zFZ2}gzb?oW9)DQqKiAJv2B*h=y&}dy z9^&e4Io)5+vLJWkNfBIp+Db- z4Q^x=6-DIcnsi2l?GOrLF*t46rFB@4OR1`k;WH@z{qbUJ$t?D0{HmHN_D-^4SHx?Q z&7FfsI5_tE(rJNfdNTTvacut*x;xcTN%JmX@TS`2QY30StqXzpA?W0Df}~FVtyp z(SV&@`J{TEXr}sHY#Q8`EGjCx?DD-t^}Rk!3sJ*vUGGmihuQk}u11LrklHrd4_~GE zT$rbN9mpUJB)@1c@i}I^2Jf<+ay}x-cjO{j@IhE#AM4$GQpr=)nb_A`J7xK2iX0@( zb{Vmg+c3`h4F@p)WJP)`EG#Ey=QmnfJ#e2>0T=j!&=ULk`T6BKZ_D!0=BW3Uxw$#9 zix4U{#oD~<;{7L2pWaXEcNsR~7Z5-eadmZ#a^pKVcjTH0c8Ksu;dlNJ8Tk;5%Td!? z#}cmd&&=1fOi5sOC85J+Yh_&&?c2wX2?!(|9XTT+BF?;;??mMn6tw?x(24O7zB*Dt z+HFSIkUi|e-&|Gpz9x&P&UlxlyNFmg{aR8&FD!greo;TM(C`mhepcD2iscm-v*`L> zIrsGT?jx>f>F5sHDX*ikh0osCEObeJcBTn`Y({7UY_Uw=%DMbcw zl?46T^z~16rVHQIJ&x`E5lJrajEO0`u8ufs_~*`a#lA;V+^0_lJV~1MP7Iownn;4D zbB?v|SZ+i1Qek_t#PsUo7y^OV4GNvUE8WdY^+10w0B?*nAI-h`($`^v15sORp37Vifr3?p$4=M%mrie0aWy=Lr+ipva9Nl3YBKLB|JtRdw}`pFf9; zZbB~4_UBw?t>x2%y`?v5a&m&ONO{1EWi&L1z;Ga@rYdS`9gc%SQXU@sb#--M$RU%u zo)J=%-f=Rqbo;h9C$=ES`)jdECoiO=q9}|AKt0O>gKgPy_`>8lMK8jo}V}l_c#HL*a z1_s`{#W28Al+el4`^jgltWoVD*rOvO{@sw3X2fpR*RP>b!WW@Z6z+iu2}BdcI=!2t zdG-zSfgvFkknWGI@U{%G5H|#@#@xaJ0M1|&-p`aHQCdbOqoEheeh0>(?(|y=r@JotKjnlb9&u zL2+ctHCQ2I!V zir%H7qDtnozxx}l4+-G#c8>ryp?&)F7^9Pfl=OxB0qvVNZ~7A0k@H5ods$n;yH+!@ zvH}Qo-Tah<&jZKCRC5(mWOa1r?^`mnu$TZ~Cdku)puKSV{ivk*;yFry-*~}WBaXzg zZM~ZwF!~qvEB6-9I(b7QBPsSsKE=fiO-)J5%A)V@?}wA}7AyItq@;i_8?q7A?$&Sr z-r6!;?Ti2;^xxgJnJChhl9R*GL(EJj2)c8Cfn8agAg&tER-j~jc1TJ6l3+qHF)@Tq z5C0AqeijM8v#TreBT~{{=9;#D$1m|IB^>r7Llt>CBM|AWv`lf7g7*15hRy} z6vS>rRAC|0rH=?VH#Z1SOibI>ctLkxADLYmSi4VPO0fV|Zq^5D-D~UX4&b#&uhrCo zW??3SsX{+~{D@9U>h(UI59u&mZuLV(u5N;KKUOc%?e9zEWO)Ak`}T3U#rSidvvx{{ zE^^nU!}H+E+~K@5AFz<*6{dsh86gxarXmPpuzG;A4Y)`Wg}wRv`}+YnBPoQ?UphNG zKVgznP#`}d11#yCos%=XurL4+{=#AH0SpFXdRH6W0B`mjI-De}pZA0}%{fo%fbE=e z8#A!03=Iu6$_(!-=EVYRfdKY=55hnk-<(@QxJbJD`+s$bT-&z{<$s>H*+4Ab_$-mA zsjIJ?BKFU{?xCVO&O1-;U%`EE{8bLrR8?PVYs-Q7iQJqIx-a>mYLx1?y@$W~i;4?O zRP!daYwf7gybjPBT;V40g(fE5#ssjC_yKKfYdoFd!~xxq`Xw#7CK`3HG49-@QSrzt zZ+Ps1*!lfCy{Za7ZBR-~47ug{xC9x2d3*(ea)-@+MLeB8S>WcljfQdUlmfrTZvtSknQ1z0p$X|M+o9pS{BDDO{BTTAMp zSaVN>#wR8|CM5jqj->~S<&KGhJU>4V5?ib1k(=OEWKe4Q7T_8`hC3=MD(oZ?jW^c_ zz?r31)8(y4_AU)q{u_sf10pRlGBQAexa>^5($*#gm_nxDb=lE)$3h4&<(l?JhMk=q z$!ew&4J^O7_&wW}D;|)Y1A~IFHc50oEG!0`A8y?8mGIdTGLP+oypNACSQGCP7#6PQ zVBSCZGW3Z1TgE6rp_GCG7TC0Y!%~1-{g8|hC$O=}NynY3GM}!Av9VGY*i7q~9q*i7 zd#Od)EDY&32h7Z9bw-l+)-)d%`5^EJ2@iW1OZ01IWdQh{V0qEek3b09udfj9s}a1R z5fM3nobF=~93_6SeR8Y%95KY9FFJI1X!w3j~E;j7j zx98P1^F1pa&_p(ayHB4!y-m1WJUjsM$SU7K5Tn6b4`)f$0Y;KmRHWnLimR^XDK9T) zIlt`q@x$(P-t};|0bXvqDEz&>-47#btEaDT?ME1H8+SCI|WU%!6ca+Rx;Hc)H7`izCGc2kAI>ikC3u`1ts3j!92{qF$uc5r~EhSa!W(@ruR3 zz<^B9?NQ039AL=h%X>1Pa0WmT0<<@~MO0EmtOWTmXG-kHd0%0guEPFh|bQ{-YeDuK_Q z8Vn_zQX~~botMpcq307LNLx8TU@tA{gO34lq&GFCfPwlPWl_e&$9DoKqoJd(RL|OM zR|t>H)j8g|<$tzB`Rwd$Bq2*Wok$=J_E>KYSOu?+Mu7%FPE#;Mx~P_H@>j&@TI*yJ3c=CEhEm_ zG!!lR01%*3dPNg+nk+f-zwkIR)1Q(2XMJ(*h&61>-_)%OcWEw)8ybGcXO(Q8O7+-c zC{$+zk4A}H6QvDy8AS;ZB#bEiLw(}SWZAABn)08~0< z#RCW-xAm{OW{puaBR2d2(1c397o)>0Vt>6$viocC=6}^hdJq4vMHSDt43*L4qBU4C z`MygEYR$(M)3w>AcU28~rt=e9|N4IL4~cVxJD$3`R73Qe;Ywe|psu+k%SFGWY5ix;TN?(#^%xAHoeylgp5LEc%)aee5 z45G=}kM)jAt#{eN!HIcww)N~PJ^H|7@b|bKb((4F8S6o$4n*WF^DoLt4#T>kL~5SG z#kM?VB#PvaL$|Ax4{{Ak(0>!tPwsyB>FOy$v&sU0dV1PTkm8oYq@=n^XIVgo-rR9_ z(bLl#1S*Lyd$qoy0f_w1e$K z)C@H}eaO_*RIl*cw*lsr7`2dfwnE(1y>N^M{;N7U&C@ad4?03obMo=hnXr7wT&4e0 zPU;dxENbe5al^1qp0?m|jx(Eq%t?&~-XN*#=}7M>J(_*xt0-pGA1v$pngp$)6Fuj6 z&9$HAd0+f2e^}%F2dl)-Yi9ca8RnOibiq$?ad6ri-48=Qd?49x?la*8#XW!=;ng2NEz~ zx59Z_U0GQ<6bfx96b2%Kh}VV;lxh&bU!TW2&CXVW6eR_qyPkW`U4D1|Lg_j{tsB3S zT1^*;Pgr^$H8|pS!>TE?O09Gca4L(MJe{Rayt^}EhbhahC24GybF=@md>BTe$TG3Z zuKmZVITz>cKNCAgp9NZ*A}XWq0t{(xYfI@O@OJcTh~mPGsIG?v zvKkgeANxZBpFN6HW|k;4=(yzfNp%M}htwb%pNiu3h1UnhluD8; zd!~2YI=w10*8C$Yzc1jX&(6O3ClhZbAf4uEPwx%b^jK;eSWzd|6q)=g z#PDTqblE;EoL84nq1Px3gZMadGn#7I!#q-NE|Y>9u7y6=ZQPxoalL_>%9$Sg%wjAh zogdrnp|SO3P*ZqhtYo^mMaE&I@E$r+qifXLW|7QnQ_82YAB(C9d2YN)>b_H8^BosY z#!2!a_F_zACI?Q8uFdo6X2pd_4vTq{!hN1T9lLA#GySyv0ilwLvh?sTD1^J|(jzTb z&*~1TSv_p+)1J}7`|rvsaV>ZHJByNS))X52>XSBmwv?C$l|IkYD>HmtD?G4K#p|j( zyo3Uc7_$|Ax!ag}-IP~z(3hosCp7uyNlVk{9bNhkchYHPWeKCt_h-X9*5>L$?_mt- zzPh&b&8w{srsLJ1gY36vF@_a9&znnnshGy9GL?{MVsyA1!1sCf_0Au9ba1Y$uKoy0 zI-+T(>j!xtSAT#)&8@6xK^YkyjtOL<>##K;*dD_hi$G$7l$1^%$M3R3l&6#iDx||< zDato0Dgnc0kd+@{pwNDVhsR}x0NnlY<6{d8i`%3GiY}l%rcytDMr{R}5{Szs%9}G( zz$BoGi9B8KjLKKZTe0KYa}(T|t-;P44eN$bKYR8d309FuAQefLk(qg0(d5b}ih?2< z37d0nm zEWrBh+-z;>LApz_sYiq6Y@Ex&kNnjOK7ozyKD1q7)b;R7QW7u~_{bib3?zrO>Hl`s zDR$1H;9q7p(u-@)B*Go=_NBjJWqo|9)B@?I-Q#0?CP3Vg*L|gdN~@l{(*YzO^YQ1 zNke!tBDRbVI(0U|uUjEJfP9FOAUtSB)pyq^Mf=x^(;e0;b5f>0DpxhyVq{;_cE;_{ zFK28}x+9S}es3y9`bF8e>4=JFQCKC`PgpkZtSdU|Z!f&+U{4UhYE@8hril*}-;uO~ zd8UY57R4Od7A>nMg(xk~wr=}Y>w9`VMdMQTt|fC_fz2fmhvbinjq&kHY)_Px2tdcN zO&%#QDn=>z#fHAaPvW&*-&<}coI44iyj;o@i!O=J{r=hA+>s_-D za}Lz2lUFTH*`QCqAKS!`yPk^fF^h|>`LnfOga>BwT9O0UxsRrGdIyfrRrv(;*Ee>B z790-rn9~_xEEKg}!FBUto;#*72@G_x+;z}WV!u7JR)zD<&u*~Md+KxNkI+wR%L%e^h&672q^Tm{xa{#utx3~9u39>+iX@(=57IlR4pcxf=jxALn40|M+2xIZ_@33k7SsDN+LJuuK|ShlwuLOC)qF#-1`=d*hc^kHmr zGDy&<85tRV)))j#tu{4AY(y*`-dkH+KYMx%K^f6rtA*U4HMk`yd=Czw6 zQk;3>uMWQq-c29D!s9x!VTEiYsyg^o2RdOy6Ls}u_;BQMrxcOww32#;_>#T$K{ zE+_hNMdAug6gJtQLgoGpDhQnOA(XCr2=st%v%Fn$R zvXLGIdrR_1%A|3t%#Yn$Efn`{z9}0Pcb*(_LaA*fWcVW&A!|8#dAP*HGVbm#K)H2m zFNL(f0@e=jo|rVt?_~{3TUb1&^u1&U{xpy%*tIZ+34aS48xvp#op}iZcmsga($gb9 zBA!0PPha(phd}_w!y5nZQ+e>4sO+4OT^vJ4h_0aJ6r13^`QbNV< zYv7FSR9RYaW<6(2P&dJz`fJA-sN**0rQx=F|GB(|_U0*OdB~^m9Vc`>AVZFc=MtJi zgDSX2WW!RUcMx)6Z#~$fWB;m@}}QxzgdA`*jcnwP@E5 z`_Rdw6|&_^Ay3ETh8*Atmi6{p>)|BA1cqY_@Z*5}1q>p(XU{^x@&nNgEK(JHy_Utn z=?WlXwn*$|e+4Q62LU()Sip$_$`yGT?I?UVKR>^1bzh&2D1pPcC*AsZ;sj{%BX=P> zllQ2n$RG#%tYo;F3r7^cxn_lY<^bBk!r@YZrjcvrgw z4F?)^h!rLqJH@#{aS;|ycrla`rBXTnb#;bX_|N>~u3GMH{JO!f8|H2IE#Mn$txxV+DRzq3&G z$^Y#&lw6|b@aL7L2I_-NadAmyc>hj6?;RRQc-Aev`(o}>Q|QizJAAnxKzNGROMrPxd(a3 zF4jQEnkIm&%Ss`CPtVhr{g0pH_4G$)=VMCBD9|UEsWbnqEuJ#X`##-4xNS32?}}*xd1<&V`& zYR*^T3%M0Ah^*7~P;_-1ioKU!G0d`~EJ*iwZ>z7}rJa!z|Lu1g zquwqbVNHqO$mT-IR~GaRek#0Cg)?RLpc>$V-QuRE^yK8^pp#0cl-lQqjA~|M(+P7y&2{HY z>c4e@LF)$Odoye6oQjIr@83oF`8`rSypD#Y#>U4D*oeSZ0`5&%vN8QJ&Of|M`|trBG~ZY^6Bw@wZN^$^cC7O=cBE+ulyLC{4jHUm?GWDs zsVLK;n;vvEM-(C|!g4UkHTrEVv>N@K>6!91A%QJF7WEcF&*Kxt>nx{F^GOGaI*h-R zMKf(5TKTw>=jISk(X`DEeR%OSHVz~5N%=?TjUqBHx+tt!jJ(m!RpP&B?XyG6w*JB_@`?Uz*D5Js+>YxO+I}xBrBO4aOuiZ zn#1{}PpxUS$f|G9rPT2XMVDg3WSNVRAPPFeLJD2StW=Io+7d#Tk&{YQ-X~#9vLnq3 z9l7+NrrwzP+4v%byrgkJ?u|`+t_J%X8J>A?7Gd!AEP%86(Aw1wihJ4M8Ajby(^KPD zDAi5(8!sjC7+Xx*Ro=?GA0jQL?u{!qwue1!lf)}hP2NJ1duH%5Tj(LQAkg0*5*m;@ zV8&r;QffCrpnE;5#p6N9&N<;f`77Jm3MDZNc@Zgd6_z0KHDdy+`q0I3Vr(gq4WnU~ z{EzefRsp2(+X4q50+9HQivS>JfFR(OK4W27zdBvKbtWh&l_VuQ(`Ny9eJ$uu;ss49 z1!?IApihYWlt`xr969df!G%T#APjgK1w}GG> z1r5ntRDf%YAe zvWg05gQ2)<@pK)0HjQ>Z!oBba>K?OKO5P$RUmbD7UJPV&#U7NUv zi*x=Rnp_ba;^l5N_pxh+d^Z&_94Nl7J$Qv<9|Is*KhsYn7 zM=*AFcH|aZ7;+Vo2p)U{)hE|Ojm2!4*aR+f<)y`qNkfiA6if}^xraqX!4GG?sTJH6 zVbyCE+;e>W`cZ{Rzag-(v+P8DLFLzVphFMII6!0#uiF-CKKcZH!H2zEs4fP5;dp>oR#yae_ZR@VTV1~tT zpj>v%pv&JB+C|y(9o>#8ieB$4-S%hfir*s>$A20FF_x-;J#Cwg2|(Kew5Ow_rH_rB z_Lg2fXJiCs0BD4B8g*gR z?-mLAG&3t1Wrpsft&ui0dJ+z_0MSFLQ_gK|e6eL5|7Sg)$#lTc`b3bxEDWDBKe zJHB0cKn(i;1my>_{G3{SRBnah)Xj?>2BwBnZAj$FQQicT&5b(auML|R^)3zv8~Jne z%d-ERQleRAF>MrUV-9#VnQACz|blJPiAe*TvPV3bEu-a@ z-x&9gyT(w5Yp?aLH=cLSXFhYjp>i^x(O$fM0RsbrCN3td00V>A1Oo%h_#6?q!+%p~ z1^k2HASkZ%9JoB68-)P>CvX%|b5yi3adgqQH-<5_wy`p1a4@ttHnw*7V&ixM-^LF- z#Av3Z<|t%utnX-MV@;-HW@QZAgn{|>ecYFfnUich;8)GBDl%4P*7syA>^$$ec$m3z zT(sL@V8~#^g+D2|rXMbQIVx?pfFE3_u{&j0;icfP(_xUA+Yyj43K8B+=yklSEeuwx zpYC+c!X0fm0 z(SAl^Cb6gkhf>}?2!fr8uFw5`@7Aa!rf7NS&eniQ(n}x%;01YxjyxIRrx)Uzp@dA| zkSAAvkHQ=k`IE~(v6B(&$wlz91fE@v%W~p1kEo_c@~8|SwbYX)w}vR+y$hRr!_rM4 z6dJnM7GnOfv&?pG>x&|0upz=|00KQOPJHN-4|=8ulVhc(rJdeIu^J?ouELeWA~$IW z_1SWX>eVeG8E`%MHde!+8hzq%NkMKyiarZ6WYVVXVj{TqiWwOh!lwW9L4xL&FJFGK zzyNFdz`t~Ma&|V~6MXu6he749`T2Pt$fc(2lfjac!%OKWJ?UKts>X|^C&Lpq`gJ=I zq`hwYz;|6Dkeufx(u;-wx4i1&>^!lw^&0bOs>{jw z`GHAUfsr^_emC(?%D`^|&`p8sP0|Nf@pD+UHgCSR`)ww-t(ecQd$~!sOV9xt(AH@m zDN%jSZ zr6H0{%Ox%hNfc84H~XyRS3;-0XrT7ZxNG6(>c$In@w9 z{W4y{rG%_rMU@);{h_Hq*L&%WjSVjMi??WKXu{+%)yEFMf4%wIv1Xhy*6MW!Q-4s_ zWZSfyWE_Fw^uJq=dbo}v;54F6|jp7Ln>6~!$r88sHO3hL_OrlvGz zW@bwsCoRo)$4$*w3l>Y>cSpk+ACmBNJ!7h>SiNs2K`%*3G1^T*UcK2-{1Qq^uh>k6 z$v8Rjil+zjq|@Hg(ysp=&sL+yH5pF!GfO>OX-P{?#>ZvQ5O#LvfN6VxoFF6m^WJR5 zEjzg1Y$v$^e+Gt!x0+TV#{|2OZfsc?+dg6!X0r)On5&c3u`UdO;a}f{)GPF0xw*NQ z`_z<_y8B3dq=4^Mn~WHoZuF>?wlFPM8ur1sUd@}rs@2=R3CCkHd4NJ*;o@$b-{5oG zQ`W7x)5X!q@|T}4&drH^`UHCiKA~Y`j66KF+!+JODl6kW_G_TOUvIw3*z->ZQi*zX zP%w#mh(%dLkk4J6Pc|?`z*n1Rxo| zqvLyB$i8aBUS8VhfyO^D2J(uTi{ZBj^sV@lAbi`3_$Mg z?Nv}v=v=gEL;GlD#qc?j=nXr20v3fRFj=G(4!bhcQpq1RH3`d`&t3pOa$B?kI5ILe zX0hAouC`|Lx^=9os&Z#w|5BrI>dNcr=qRVA)(>C^vAwvwbr8VYXM1~A^kDyu4TG@o z@UaCj(D#ACL4)CBmiO=9|5N*GZx4&0t~yZ{DFqhRr?!D9bM# z*9*sk(z-K$(t8+~q@f-@@RAU)6EiY0reYN|Cl(gJI@ zEI|0dnf|er1KkH67-ePU0Kqr>*K6>xv9W5kmIUA>2aF*73aiE1>Z=ypbwQww!JlT6 zZy6YR-b-6I9dR7DfOV|fAkO45{ce2K=Buq~@2roT&t<4(Glw(zJib_2QPI+d_JreYp5MHsr+-B6a2n^y&r{hJ zQQYuA3_c<`R_y0#L5g55fG>Qnak5m%H7ueo0-SESj2{$Ov$NcGf8a9EYWo7e!{P=oyW)GnG(Ru)` zkcxw&wyA}wD+mof3z#GTV7|wYvE0H!WUdCHE#zk)8xO=%HQ(+R->+l%ka2UT08_4~;lQgt0suamFD4`{=PLYwCDy}7{DtFvvAx#epPU!kwa!&~BrIlct~N10@3v4& zBbYifGgBSOZqy&mU$@8I8!FdhQXK;VMfFT5hq!FCd2!oG0T{^1&3)YTzQ=>P091H* zctV89m;3P1gJl=-8sVx8`y!o~T9Pv}BYOZHk(j z;mg)1Wwl|Ek;mvVD}Yf23}UArJd(^}U2ScmaF5~&S?*xU4vFmem>}YUZ=9MayXqkE=mBJoTTF(y0vAbp{dyby*=+E1$Z2iV@%356 zYxc0C#k%vm)rZWWAVdKAO-U<~Vq#pfdx=QsZ8FK z2k6Oz$#SF9*6uE7mc3D~FOqoErR|Q`us324ef&puw(O!cUJ|rvhBg}knv~NJLBJLS*zSYw?(PbU*|KBf1NYPq zE{trZqd7G-2`wIAz+)_#wz(|XA#pC*!UH`v1RpQIXJ^k~k>ZX6e6aU*7b&az#h0Su zVgi6)2hhb0IG^$H@g?_z z(w0mgc8eK$n6j2DjS>|)fF=HRr=IBnSOfLL8Ph{2KyC-_Z_fSVBtKs{0=_*C@an++ zpKtNt1o=R@fmR%yozDj8$}tHEhekM8hk@qpnwH~}k`$Gdopfe@3)cMn2_vVY6FGZe z49xH2H}kDbYc$j=4W23HNp%2(1K=IbOi@oK8IP%mYR>UC)e|!8(k-i@vA<0sir7Gt z=?WLz%=7HKh4E_GLaLgmVC0ugj<(hIX?|~`m=H? z{`CMNL!kB(xRA4cp*?*0Pm@?NpDg5pwV~RCv`ZSZCy-lb%bef-&=au1w3YVI{g^~FW=gZOvS558BO|@{>aw%p+g4X0w*VPV-sxGgxHi~x^9G-+$^!KB*|TR#%F5au z>e?j!Jcnmi9>K8^q<9yJR_9g6r@DU@>%2_o+jEYyFD>WJs1PZfP&(iZ0Ug)fJxAsc@rkMD6S-VX1oWw_4v0E_;8q^7I zx(LO@IZ2drqx95S2J>*{M@}C&;jfkn&a|$#RIFnEJ;Pg7dxwWc$4d=c+uN`eZs#WG zB)qNz5E3AE08BjT?-#Bd)=OfVnu~5n9#n#r06mr0&~P8M0;~rUEow=5`R=mID%HzS z7-sK#*R!)TF&UY>>gw|!cP$#~)~6Ux zklFbbuFloN!R&wutPxf34yAECF~!c(;*G>?#XbcF#{E*@LF|KPPtNUwb$eQ~@8>+i zq=k8LQSwoF8KT|EZJOenp7U)}^b>j+dlJ{=XS;6J6tvJBUn46n_v9Wm!1Rm{Oe0=;6>k42M=9=Bu9-RbmA7CT^<(2mE_yBCRNAC%c zGhPx5d3kvVKlJKo5g-hJVXj`i<4=;$76tr#g@bjq-KHon$(RV}4zLlA4m*W>63#<;OwoS)+dyrHUsgMPA z%j*$NZY~LrE@!Y?kvNF*_3U7H8m%5S{}%dtYu!}M)!C2&Y;`z=4XKOyi@7;DKR>kU zn`zx*ihvKlot<_MEkH?s*43SVv+;xv?-3-!%ql5~sI9FXdMTDs;Qsmx5E&dgq(PGx zf!X?EX4bIfjp+Z0)H%h8s>Jh$Z_zC?i@5cU*SQR?>`_rNE5@tp#)|kNe>8-ywPY{O zs3mK;i*7chF`xLm>ZV$h<97xls~nr97}#;~L6h&_l=hK*Vj`TysoIO<`KnJB)Fr;J zYTs~2?J|pOS(Nj8n|u&__gw9z-Pq9fXd2%|$s((0lQ`c>zK8jXqlcSUJ*4gfX|aAd z&yNmN>p(TeU7(yrwT+DePQD45Ii}V#7$~lIp*fXnHffih6tx zHXaV+Ydz9zTi**a?2l2h#1}~l7+fzbK1f!+4nDm1P^~OhfEf4 z?=7EC$ID%tv*56M3*vK$=0=}hdfMmDKliGL?OUm+zOT%!XTZGA31Kg{?$soP>k_}^ zOsckYo;3|{bES~w`-ug!n2vLQhR&JHKZr70sqcY?zs|LqWM>`wjePgef^J!N+i!UlqhMO?OVq#w zZ$T{hzIs$#ues8{ukQX^zGF z`oiZwMf8x_H6wuw;+8LYIK6a;X(sb{)Y~kOTGKM#9{+8Bx$8cX`F5?7(b6Jkss1uf zrCzMF$*--&1#|xbyP0#z*1_vl;2Exh@rNf{Xyh2bAlDaEefR~Ol z>CZTa-Io)a(t?$=YG%J%9y-V~9~4=3E_$|Bce+c!3XL5eReTDc#~;+i?I`_wTy{2C z1zlHlBu~8s^xMr<6fb;KN@nXH}|uPoEE&f{arH!#}0N{v_2!xv*uS zd$=P`PU@>#v_zLv0T$_E_B(0<=Xb*{v3)G}IAU^+4oK2Fl9=K! ze`5sh1$4g~5|_?j+<8yMRAKK0zlU;SbgD+@2g$YMT0C#Q^>eU%!E&M`KZ`gzH^dqF zAA-=2*8$J~KwCmdNJx-MX7+m{6y#WEwc45iI2b@BdX4~Rxzd~h_zOU59i4Zkh4X^} z4D_6(Hdqqi)8aBR)BuVev_Xj36|^8Da@(Kwbg@ zFc?f691#Np1F%E0yZ7qURDeGIFh~Go%Oz!LNpEayY|3{Gv}C{4j|J#oQTq6gs>yp! zP7p^M5YRt5Ick}7F$)Vipn0%30Adkg5s`5~b4_H>wB^YFq@73Ncm};Ysdhaz zfB_<_M|}@)n{7D`-W;lTEscOfP*<#0OXowOTT6)-vshNNT-Y#PKk9o}@d$wjzvnEZ z$uxesN9^oY7q5^M-{rqLzzuE2=5&=T;9Id)Y3%rx%Msy~(Jokv<@vcOTu{u%C8s33;s>;=nn-b4dMb+ANVK!LaQqUh z^WPxF7!{6@#TKiJkVEgPfUrg_1#K9W!_Bu&EX4BinaE-jN5?L<2Ga9nfXZGHoFK~^=zig4N^ z!QXx;J`iO~a(yHN4C_}yFg{`Wt&c(Yw{9a-)wySw^x4PSjSp(3FZ{noK(28a>>U35}@DM7(b?nTC4fKG{0 zz63G@kHVB{>lu#k@isavAYsi{o63T`lvP#P0A29-MZwRX?*ZgY6`z&tp11c#k^1zW zz#14DvY=)+o$YJ&wE(hASsT=yD6-7so`uEK8>V5}{0O~c)N$;fd+9YHp_#R{$$DoX z5aI)p9iS=80y}B$$QcIMMvc2Ot7TUnPX7Fd`#l@vRwbWK^+`W1?b_LX@(dQjH=K+_ z($2RiD5g04!_2aGc=SCwYB~zaR_wu1e~*wwcNmteRB~$yy%E+diHk@}s&Qo zAEjOs*+-(`V*l`*>nkkRk5)%*bS};j>w-tHMhdMeg?vr(=X3j(C+D&utf4CK=ILcTMHal9YMvDB}oscA0G&-!%yv z>7f$y#M}7XE#6<2`{cH^w%&EIQBY)`WRzC`5JD&{MbV2mC&FmF)ia9b%THGJxslCW z$msc+PMFNTL!ZzE)5?RM@~L_3A$>vz%^L1|^$D&uivRQiWZq0_pj{dk$3xmg8l&Cwo1I-F`dLF=|!1BS@Ay7Lns_Rlkp*4}iw#`?q6hC>nXX@|h z%HCQgA3J|ioD5SBheIDTm z12WO0z6z)pfSlUhd({#l`Sz6o5LN?e0>a-fzQ`cRC2eT+Ew8LZnx!t|nC-Fxa#gL( z>L{U2^Cu0B*ML9mGT??FN=izi0KU5!2z{3Y4gjHauF`N>e|FokX0`avAW$2I7}6Bw zc28hyI;z!yfX@+rPs+GYoUDFC141*X+|cnPZBR6LZb_%7Y?myLt>7LgI#Vd=x|Y@g z-FLu~2YKNIEu-0vKl%$Ar@;-2W;eec0v@p>O2)5mw%E&S#( z?@pa3d$*sZJA=ZpW@LCb#!jc!dO_?oyiH$m?SH7Bkru_QzNqC;V7!u-p6UcxfBF>Ycrj_$5zLFaxh-sTBec$J}(VR=Gn~ zaD(|sxFpwbunFNAsHyvWxS4s4WWIh4TTb4DKP;$>I~`GixldE6c4sqU8lagprfJTP zPOwQoIfWtCM?6%;oTQ9Mc%$3A>iT!Y$4J+-9ND+|y}3CZ$kEW_qM+c?b1}T#KRo2M zSnLUlilX6Z1dqhYy%h!oA0YigNlguGVj;kRfV|KEfZA>LvbddXO)k*mN`hGf@%BAO z#oxZ#KTk0L)S<_$5#Zh)wS7-dUThkfZi7n9P+@oCU_e5sU9>*HfkDqHzR_96qpM;r zF671RJeK%=()_AjRH7>57cA4XshhwDQJ$>I$fC8B#fHGlqlT$)jNzE+}^15iXv zVSSn1x_Y|ov8zCj5ABb}QVaA^c@8NMs3O~iH1e9nWhb&NUkEfij(I@6n}@1UZnyCo zBv?Mo;fAhWhBzotq~~JHFj_d-D9BkHCojHs{;UF=zWWxbmcP@cxJ&w~PUTNOxH@FM zDWx=ctfeJH%;zOx za!fpIc&olIN9@;cV;Rt<*n2NYJmQbi6B;7dou6NO(C2=MKE=T}WXR8PL{g?OiDAzx z?omDP2U;0)+>~&Rl^Qav@+DPY78Jqovc3rv2)uxO3_cFFl z0c?QF@i!&|1H*d`4h3c9z!8&2-U(#Is;m|{B1!lpfMwAcJ=U^<6joPP-xZraN6?mp zt*xmUUswq1F?dYk&doh%58NgCQPtr$vHJnds^aCKSoOtpR8zuwIQ|BuJPTuIp zRZb<)>;#eXB`$;a^Hli%tpyOA;z(T{yJViI9*EE#NMkCY*g2T22;P6Yi1&4K%(Yr3 z<#X+(`b=BJ>w_OsS{%=(kwQ+5*0~LP;{6XlSnKyG2EJ;J8}R3BvNc`xJ@CIQfyO2D zI4sQ>2wr0dnLE#(%SE`tJJ>wSMOrrE&X`*qd^@k^HytOI?v{*sQSY}$#x^89PWa67 zizMYiE%v3c%+9b&_02Y%4nCH_3MG;#mzZ`_TzZPB$4k|aeT>29sIqUyeS;w0g18@? zOAX(W+sgn{*R^b{`$nFHso97IOefPBJXpxGSGe&0>?dw>FS+1^|BQQ@UDx%MI*FZ095w(lG ztU={ysZUI}!VKp{FR{|O-w}Zd+V88?D(d=|*Czfc*sH&o|GTZkWA+3frDO55ir2rhqwx9M-vdg2E|6;lsOk8`L?@tsrT{vvP!OvAQoS7! zuWR(>!7MhQe*!|OnWg0+db+!}5A`n3F~Ec6R8)FzFAoSSAq1;QsYOeNI$KwhSAo+eIf`Xg3 zCBN&z2l^~YaIJ_-pwd`u7%Xo=C+$lP!d!QA6A-#oEXA#Hb4@zt6OkN^s*OI;%0gDj zCCYVWRL%sCn`R|C2&rD(n^C+$B`Q4c2gSjv*qSnt8?L6kYEhKlalwmeo0ILxo94Ys zM6N{S`26CSBq6#sW!?ztMU@*#*e`X=a+q$sgh!iGQ6D|s^CrY8IyU9=jMS_;bU`4X z+@4LO$rC}EPE_FqK^>FvXoAm7dPx6tY57=?T?73?*}wuCp_(#Dr(HApp45^C~ zADwP2EFqeh*mUTshz*i>jto&;c33Vea*`cEc&@cw?c8)x7iNsCi7TI>gn@u6mKuwT zT|6Sv%Q-Pd;H*w#vQ}GW3|_&k&I5@xEg6|E(0Vb&lpM$;Zho+-k88e#<0$b++`v>r zBfJ_CV?t8RynxHmlHG3j?lWXy7$FBXL zTD7bf@eli?sBXuxf!simzcs%SAU){WyA91McHg(`7;IQz>;~#IZm#OuygJUq!@>-p z_czPs`7#-gVnma!Z0h?^@i^*?T3snAsd5NRS<`VNn>Pr^NiIMEXhlY%n~bK512To* zM_&fb+UVqDR}I}q@3{$m1W{g^_5Niw5cW^*cyu<5F3w-@wstTAs``{$1JWt+X2nip{Sj_71O z+x|yhUI8sTo$|H*>*h4tCF7p+s6thDgM8%a*>%qE-kr|lEq_~xrYOmem%C|H;RF*h*qOYb9!<>y`1+1dW@9<6)wbbC)PFgF%Z2lJL z8!Uk`5y#woW<8*g#95hd)*R@Nsz|$2!`s7s$$r_(KEk&jUXjfK+FfA8Qqw@o3mdo@ zT!FD_O`$n0f~6{YJeR|S%$Sgnba_MK?VhxPOQfd6GAFnCyxJC^tE}t)KSu#n zdI13>kUIZ}`mYi))k-l+Ag8Rl4ZSMdh%2Z(|4dDGR*c90f}^$pR2du%#k^qt~70SG11e021Sm~kmOZ6 zd<=T^^qpd1py;Mj$RLC*=q0w{QJXi?yMN_Yu=Z@=t0MlJ6ZtE8?BCA%Kk_rBKuuZ^ zh9?JR*Wcmgf1XQ<0HU5Jm(j2Pvv^KLNwT8wTtZgx$y35x25LZNfid59E{EMQ0w`b0 z$QZnM`aoGcFpmbo-I%7RRMdG7e&CM+c;$m4bg`7}=rN1(iqLT8b#|WX7%>0HW z)_wZ24C@GbBr(ck5e@@?*?;QkczDR+S)`aszZ*X0DzC4vVM#TgzT;l4ku44+QUUh$ zQ4zb#;N@+uu4LPVJ&w5r2AkvWUvzwEPv#VBPyhF??>}pT?@HT%o*}v;3;B+Y%KXT# zaeO+D{nL~@JgK9jquvKL05pF8X0n7$c{+bupWtH!iFsYWkOe($J%%X-Xmz3M2%aV4 z>EoUQU%WbCjSz*B@v6MG$dO(=Lr&Rs^~%-$WtS45!RU2n5>D##=N&iljxuW$Tf-bU z{hzn{aahUpXW6skkPMQGRdXVL(D;mwJ*dJqQD~QQ@l9ehM(1&Ry&@OR$f_8zK_U?bZW@C)}}taJL!Db`w}W4@P;^=qv2?ovGPGCiE; zaUhT#1+Sx|UJHP+VTL)d$yt^c({FDLl7k0n-8YE`ucomMnQbG-HWC*d2E^c`NO2BU zjfD2B_chuRx2O+lKdAHeI0t3k$2T`-?(30bA0a{+=-hUsnf#(dLvbuT$;~q9t#3@w z3r|0G=dgQ#nC2Z}v5*WnM_b#(zqKo=kj2OI*0vM}l z{^$16oLZ9GP|Q#>0#{MZ(<26xOG&D0zh7mX>P?k!Z81Tn&BW)nRD=)ruW?M@_3+3E zo_b>+z>vlAPDHa^{otZu&ehh`>log&6AG6qT9Sffvb@PJUm z#kB`s&sY{@0ojWYF7?r^-Yv#B_dYifq=B(TZ4j|-Ir$Lxj$s)6XDZLaACM@#(CB~}&n26SKH3@7 zN{g^h+gC5%ncIsKyX1lYt3Lv!r+?b`ek^4`+XNhH~bLUjs!<@j88@U=l)cIQ>QJ86+u>k zC7N}S(?0Y+-Wf#mc<_|5W%&COxQ0K-&mTNV^=|KVnBaa4$oq=53QbXSQP5=0Ex~%5C&Qa;C+SJBd%qtd> zr7o#`e#Sgkn~<%auMVyF->qs4eL(UUh2Mx>s{c%Q4Nj=o=`rx+i!A>^8#z^Iy%DJ* zcac9GkK`vuoRHvjE#A#GEtEPWz7cBtf&xtm;L-_W-9-21iWgOb&~$`b=2>P`A=XaOVA#b zPqOf9@iSRV+39U8eraP&+^wphjxi%n;EJj@VW1)fM~+#fHMIGl9d>fgCSX&XUu3m- zYS?p*fl=jI>u0m6c%N5r%sRX(J_sko{h1LFsSY1n5sIPneIk{f@>2kkV#w6-J*30DN&Dz`Y%IpyJi zk1#3?%D&0XOOW_f#!i4+wjv$m8XIDxd&EbhNGM%~2awZ42q7osCen(}`wl&iTL-4^ zMo#+4AE-abmcPqg+kREW=t>~)VQ*D!H1@izsJzjlYM_lXIB1q+x9)^PPL=R0_82tm z(sroj#z^k-dYr7hmg1*ef#6@Ko9FcEGEhhOhdfi)eFi3D520ZmdE@QDHxI`po5}{C zieQ*eN&jpJw1!%_q9a($H&Z;1v`pmtiBOjdcv6sop)sv7lwM{EhNrD6z!*gqdiV2N zg+7d5FCy2`i+@%jM9T}2@{l!Ru9fpOWkg|0y&+xUQcK3*_q&2{wNoQ!hM`?L&7piG^29m<*1xL97yvOWavw-PX6gA*@!0_n>$TT>8&6^-t@6Ok^o3x4{q5 zM-*)iE}=yvqR-V+WXIn#$|d}z(vilLq(E#}eSM5mq84lCt}PWD>bCI0O~sM}{<+*; z%EMG|_$z86{&R~-UFn`kp0D{zj0BY|FbJ>VcMs>qB&eKnaL7v$;91Rs6RE#;o!$$#<6HMt z5b0JiA7)?uNx5?wRTt~6z?>E-etW$o703L?lP#)5pSq=*)<0P-E7wnNaehoXDY=z{ ztFSb2zYE6suuHZXqom$it2gXU#nESbq&~#aUX9!tMNap#6(Q!S`~h2sL7#Wz*HSq$ zVSMHdCVFLYx$PT=1bt6 z&BIG~ET{l9@rS<(uM0GGyIL0Uwdg)qIxbVIbg}D9lHhf9oLSVvvZ-6+D}{7K1oKms z6wH%eHbgFfQ}AO)2$v`msyV=r1#Jy$;mYh0By-t*tL^X;QkwlVlM}}fyrMg_&xgsY zATs@_-MQK3P+M66iKD{Y>jiiu#oxjLYen@TF29!QWl>r0Pp;&+ZNw6zQG0nUrM}(= z2qAie-N(0xV=jqKO!KBrMpYLd`U<>S114&oxsnXhY))Z+aqS-&$=VphSso%auw%80 z_%v`Oq2pmqg%d>j@Qle}PH1i@NSSWlGv{?VX@r@&RGr^Zqg1+Pc%etRuM;SDts)tL ze6#;9hLG`s0Sna8Y$oC=z_=dxP(;07ERACHsR>_#m^D~`c^(d@E@2J2EzGkc?K@694bOz{}N5SO#&RDtnIly zQ?FrzL?4?snUsHyO4|>RG^^6=B2fxn@{BqOF>+%QcfWsT_Ko|pCIbkN)zD}dcWJ$7 zR)wLl>h(d0e~uTVOU=5td%v-fbh2=~9MNe0@UEZ)IfjcRoC>@XqwhQan+68+O#a4> zd)s(BJ}IGU(ZzjRDYft0r|9Ly=49WPwRU|q!IQe6x%)fd35bj;@f`_IcbJJXXOI?o~S`Nt1ko z_sW}m<~{6uN!t&}J?hnrlS7f(pF+TE;!XYfPhx*WwZB48dkmnSRM6A&ew!o@Zxu_x z%&ZWeC-0&IpkM>53QHUMdlW+hJbm`=tbe{5)46T*NJJdoxfzM?x5s<^Q#Rh81jzL4 zqcM1=_#ig?=)p2S^v11s#?r>)rPUQR%8K#?%@frzI$sZ0RHXY8KOK`lds5fP>WV66 zJUgEKnSjNh`>`9!&f2AbV4cDht32a09g1*zQ_2+=(OQS|Pc+zo;9pi%Oq=zNgu6rT zms3sE+$+a_xORUQ8`-~)YxQq419uF4lbHV{0x$&w5#^yXgXWWfi<}(t7?%2G{#OzH z50H~Od;_$h*`JXN@c-!s7S>H{rOqBQs>bDZiMKTxH2rgfK+`VkH)nzD^(puQ1Pk7=AI#$QA-#p60#OEv5yh z<+BGn}QlcSrj+A5J&6&iI!4*dMP)%UcTLr+w6-Y%Umk8?I0mK=L?hq_^mSJCJFixej!}GBt$pQOxjqz7M3>*k{rfg!`nBl=wL}zUYel=AA zRqk0MlHz9Yv?xhcu6amf>A71Ym5MD50gYk;KS|%_=1|9^=SudcZs^Z&o~gfY^czW| zW7%t32J0iQyh+*erXd{5LB;iUVaZHnm8cC~<6U?HZDGU(V6A}k(PMWiWYh=SphNb! zvMw(j%nfr=_g~vax;Pk23m&*~(oQL88+NY0+h2H@!Uf%`@+-tvWO-d&_`-hRsAJz8 zPV}AG0F4H5PUBI4z++;pcsb|T7eisGUe?I<)Ou+^PE#A@Vw&+EQ%BDF2cR-M3aiYR zU0QDIn0_40FC*dv!fOnp0zZ-=Fnof;@~^)pxtlwhL&o~D9=izN0h6b%cQS8TEhHJO za%+x(`Gq4il+&HJeYs4s0m|V3saWyk0LtX&9m1in z-;pbQ5edV6l^gF~xAIftV75xT>2BF#S-Wi!>I^w9TeNPQaW1Y^-bbr?`@_UfR7nnV zJPSc8K+ix-j5_6wR4f5&+?LVV9mS_EX=-Gtpr+Z)M)$quF>VlecX-X|^!P4)%ye$^ z>F8tdVoX#uG|VX{(!IyylH;E-)ZB4R9J87qaJ36l8>f+Zk*lAUdg^%m9+KQ|E$9OA zhN6_DpPj~w$BCWIo{F5uWCzcwPJXhSd1fSx;j$#GVvR^N*N6AHQ9T%3Sx!JLllmOh zMeB(KMtNocg|4^V2IzvLbeD&pL%9x$ccMeYxn1m3L$qYWE-Z_Sk9AiVa1$F38!ik5bVW> zQ9OmhZc51erpBfwiWt!+%OyO@hGpi=&Yku@-Tucx0Hiu15O{yXV3YiRc;DDWCPeu4 z(_V0o3FpjDFA_%lPq%H?K2lEn!_$EX-;J7lq-^pHAe*kNtW5q}BqhkHt4k^3Rht8C~jfd`>=m-Cc3w&1$m)P`lpfqX2 z%&h+DfW!p4ep6xo**tX>tBRoDn0b|GH#TpAcfr}r1A%R9^!R=7!PMsI5udFHJfN)3 zQ;R+nd8dNCkxX!;tPyf4H8?_W@c!vU+h>k1c>n9hjKaUqF^p>LUSvLT=;Y+~){|-f zzVUy*^KSt3s}H>@6mDs00S>SLrx>~B+eHij6khwHa1LXNUuNRgolPw zdu(*G@tfec5PjjLo>?67^E;Qy!>2Ye{>H_@)fZ~Ol80Z_M`nVLi1a!wC?dr`T55Qh zH`{=ZkMBJPcW^{cZ%^#DZMqgcM`Fove>Z?XGkcDxcer?jpG|fG*!X9rrvs}SjQiC* zwTRIBQb=r(}!tMhK*COup4x(9x>g|9E;mp&@4j&&9vte_B&*u9nIOpyyKS|Ca-X$8< zM90S3FBlLL>!7=d;t_(3fMaXlxMqNJ;4Utl;^N{IMa81;_ABaIm@Ko=z84pxBrT3~ zm(c(C@uQa~<1e)LC;#5t`#!K|Bq%D{-zmlZAC0R&6c{6VEeYl1IvF)JHNBx|&iuA> zQ>9u7C1r9SPr~1?p54J;d+GpZL!);K5dTwDO`xHxtE)ze8iBqj_NKe1uecxkaSz5g z2nv2piI1Op`XrFNIU*+3Cu9OP+Nrqse~rUSEEbmUlC;ww{{z_XZoF3dgml0&JANZf z|8bV1&z$ZKgh*7;DF1rqB{yI&o;5c9*A8q&WW5&q%c4-e*F3wf_=Xc>@~@Ns{aBlQ zAmfp;h>Huc9B!+KHE|vM_nlm!Fs&a$#=5k=4^$hbY*0v%I6& z#qUBIw=AS2cx&7coLjoH+q?q#PLr4oC+au(qel4tGoNy!;jh1ZO_P@89|f(P7;WU@ z#j;Y@5v?rjeL-YD$XpAZZu*_3)tQrdbiZDiufC{fIAffWp4OK2_xLxK7?CAPjvlm@UKRHJdy`a5^ZfK1;xL(G%;qKWl8|m!@I^!MZ;N7@!BtUR8%}u^ zy9+8x?1Xfo_?GB`L%I-&G@hMvZYFcG$ybT@zhO-ft+oO#zZJ)A_iQ_EvTc9+%36G6E2u%PxQRwI9mX@$ZewQNieJx*)W+{w-R_NH&>cd zcxW`cLSXTCv-Ebz6Nd+SQT6Hz-_mVoWL(xaO3j_^*zIPpiJjOhw6?~(@LP3azu$bD zJo1fmlsx}|Je{<8a44T^rkZS43y1Q0k8~6}gIv z2=bg+HC*JcZmFF)T%RW&z0&r==G57{Hjjt|;1_d*xvdA)Jd)3D6}K>g4)!eMqQlzg1x~H#vwcoC! z%lct$tZuZ>p#18J>g-hxj$HJN5G1(R?UaEAW^{y3T~SAtj3xN1IBhq2O-ayrd!qn< zU*0>6x%_BQ!q*XVzc1J()d@=|`SPCM(Ylny=NF`>qU>qAe}Q2tPfZl6P~I{Qce&4r z_Yjt!b*#}4#ht%xZ4TH=+S2<*(sA>bp)$-GyQFQ&9oq9c!Ruph44Q6?S^;~1ve~o0 z)dFQILB$)m-$a2(*?)~kaL}-ikf2JUi{LG=)TmT%Z!5fmhq12ZeIPP!N+T;yPMKt7 zsc9&jKiQcRnHHLn(XJ`ctxRR8@h-u`jV3(G`*9&#vdH-*9{Ez*M|&qVO)~74jz1f@A8>tCv-D*U9<$I`P&s5j8lH#O)!&ydZRvmU_1@8NesA=s z79xU#=skkyy$>RVB!o{$^j=2v-bZgCdhZf~h;FpedpDvRox$jgUIur<=kvYyuKQcp z9~O&u)_LFeoafokv-jDj^*GFyF>{l#AIE@=c@77!(dq1AQ3htq`}dppVd>1q^wWI| z^m7t!|48h^w{VPhrh+vOp8gq@!>}_!&^GGGn{lU2#2@TRi~2FA$;eaj{T8i%2>P*$ z$&j$62Hu5h0raKUzdR_XI{Gqn+vpG%Zp|1XMV-O+BOyEZ>j#g$Hg=es@@#y(dTQ#? zDew6+LGo`@`=g_TM??+orUH*?4(k3?seW&l$M|l<5~T(r6LrSr6GPJKN={bf75QI8 zmd;-bMEnHyX0=Cj9ye55au#MzDZy4CT-qXL2JZ5AIVlc}_Ju{#1k-TC@-ZSyc~>ub z^*_^wnv1N9pKQx=sTKJaj=wXeSm`G2h_lkj!Rs`h6RLaowIbF;Ja$L{j!C>iuj)=m zC0OwFji|1y$G{7~#QQ}2bn@?=?{Y}PDuSCh!MV+h$3hT%gPRH+M{C|(t0eLc{Wxxm~tZLxOUf3sveL8$YNR26jxt^u| z>+lxYv~iumrprX@nrJWKW=!)W)uIi5L4jC651hKGIi0gDk1^ZANKC%3n%n+ zVKD+5Eq)`E@Q2O1xzY!2LNvmjH`y@@Usi*cMU@UzKb%Eal{9;bsFU0L1fII+o$<11 z4)a(L`HSB;gjpGIvNK)f42~s9b(YEuu?)k-JqG+E#U7MX#}aHfe2WCvQ~U(<}?#@xkej z7V}`!3yhA|o(ayHr*>E6S^3_daS$POA(UV5f#{SrEkFE`c;0)axQ$%=J=Zfjw8tDO z1RNr=Z~D8I-clYzqzU^+f_~uCNXdTM40@fb56E*@>ZJON9TChPWtqhD9bUz~J*O=j zG7g&6)4ke8ujtXBBu8@k_d|ML4VsPD29S?{9m*K$ae^VyET>$+wR>ve zYg#80b@$J(HOzR7ynkS)x|W$9s#!>I|1^^<>%uq(*CHM862Ifw{&7MfT3^n++SRc+ zyLd8EzXhvy7o6E7u(NcZf0bSoFZs` z_o+=?8UN(?Y{MEAXrSG`pX76u|N2AIu1OxpD}i4+S7Npn6vK_HXSEMInYDPqTq-oxeLaAb^)+SE|9w`bkgh4t&uLEBk(R5PNIQ0cJZa0 z^M_CAtAWV%6{`XD8>h2i^)2ZOqFp8q>&;&WM0wQf8suT*GB1XgN2Q4GE>xY09jcJ} zR|%&ihsN@Tbi5McG^0NYpJuAxj`nq=h&SjgRrj$w*m6L`jQsC~F^*bU^%hf(Mu*L^ zs3JVfb?btko`~Q4Lz1&~2fzL9u6t=|YfG%%&iT~Vh2>fDf88D^znArKd!}*SKFtfC z9L`wxS0Dc?^HTGR|H2V;7iV^sB=oMs;Sd>mP!n;cbCbo;dV`RE8e3!IvkpwQV7wiF zOi$=rutJ*Pt;1MP@A}q`H0R;(e`{6z!9-Bv4vfW&8hf%kx5&Ld_TmI%ZA^2v3WSNS zDDSwDaGg(zv*zY*Z#p~P0P=5PQP24^ol9rgz*Jr18ga1SVY|A!yDHgkJ8)ao%n|+p z+(XrRa8{x$TIQ{KPuPZ`W4b3pBy@q9 zp^b{T>ZU~MO7r`B6De+9YoeS14qKI_-rEy9Mef$T<&L(?mlRq|Us$E6K@5QQoZPAa zTs~D0VgYP*(6c7AeSABcbHX${BC;jC7Glr~-v#n{Sr4_8O)+_ZH zOyVr7+4nitxT4TXV~gU&!3vd3hNRvF5T~aJ#EUS#xzVp8Y7=RgzyE6+_t>^%B|*7( zKo3L!nfn}HtlfJU+7IzbB(wvsb|!%SsJ9W;C^J>N2$mLmN4m{8teHiur19H*wq6~q z`0$Bdh>wikv9jDR?+nW(P4(^d_Zo=i$XsDP1K75}KojZF^EhDRRLxeU)#n7wva?$j86VHWNi<=g8I6Y4;y8d4gJJiY5S zAS9G$G$;OV%tgI8xN-;cPlsU0!-=Yer<1Rm$pyTy z_+XJWC-&$T+n}gz=EzNs^C#7l3v?@J)-A_+Wk{nX))IIA;a1V|pflNimA1xMZR~M3 z$T4_0U|6#^Oy1=P?||a4XO86v7c05TELNt~9yK|~hf05W_v{=<@=NnnTW>0* zW&Cuue-^(z>NMAYdy8Jb7f+5~#_fxtNunmP1ngkMV!rs$DEh^2cqdmqE3u%og$Np? zcoJsXyzNWtuV4XRs9&r*R9FvM%oiYET0CC3-ZctSje1D={W=5T*5pFn-z;N16~cF$ zN1p-E2$?z#&A=aziN3r@2Sfq{%~Rv$$#b`Dg_5PL$-k|sAzy2j*-$2pgyI|n3=?nesM_Jfz zv-DUQdRo&DllfBX7=3G)ePbvmHiF5m5hJ#9?Fj|sikUk_XQegIZ?x#aalZC(=g@$K z_Q&v_+fhD0iz)&oc}3wKH=nEdl2(Z+Mj)$H-e|S;c}#al zivbsqmjP!}5W@#aq@!zQMs5RqU}>5LZ~iy6>~6G#mlF=@TUr1`VZyU?H_6tmL!)Hy zJ8ICBQIHZthVREKOa`YXc5pAp=K|OeqLRz(Sc=~k_&U-NkGYdcth*9z*sl8XGW{M~ z2c@c?k2jZe#mBejF6aypj_xE=dMmZ--o^w6f$WjImzySE=0sP-8}X!BS#!Py+Fqdo zy92BVa}-h~ATp)tIR9%#L4)771hP~$dkcDCQQG%TEn{%4DDzT@bt|cbg$CPT@Bh;{ zsc>C2TJ}0%HLSmPx*{sIgd_~U^Tc~gy5zVNk)*9Wx^tUR(%-aI1u~&~SWif!)YSD5BpCyw7m5;Nn62|u*YhN@>W7Fg z2yLg!IW_(rL(jXf>J^ZjnKEqb*Mq>sL^CW%1qA*cM;&zPb|^ImFz`yd2uB&>WLSA@Mm2b~Fdn8}J{Mav z%5mr16E+bzoFTt2vWV1t7g}gE=wsCZI>ahs<<(<|wqTQ?pseHNyiI)pl{L2$wRdfx zeC=AafQZ;5?)S{M8iJyU(gV8RmMt`v{%aN-#89J?#o&bAmmY~hM@3c+Idg!EX_pgd z)=Ol|YLk@Z`BkcxgH2OZT0T)-$m2D7mF%FO>mCw#rB=(w%WRmIPm{UT6f-a-e3|R@ z?}7B*Hu%2ARbx?1?W(9>Tc(`#4J#)}jFlLc9j+p<-}6d8<=kSDv7HhpbiI2qy! zx{scdqln+s2kE;Rg~0%k-#QyXfAM8}H&q<<7p~gsgY7WFvD0MxmDQLr>dtUn-Q`wq3!M5qG%E>~-^P%=?;X>F! zkROZXgL5FUFkO@EmVXfIGct{3mcWh`H2O*l@0z zK;Hr1m50(ahk$Xqb@uWm6INXBX4?6F0>NcA9D{d4w7VFD;Ox( zK5b2G_sWLUwz-^cC>nlz1MkPfmy*<|0`gYha|LfN8_(aTdAIw|h=6^E=da>R3z6eX zn)~5Hz}S0M;xLV?<845!UdPs!t4F&MzTuucOat9hpUzy`p-?wY z)edjR@_VJHsQO;6vZx2&{r6O5f0Wc{FckxIPTOtL8eS2Ey=RY3fd9RodmlF_NTm*C z{bw>M!L-AI49_^OmdnD0MTGyUrE;5Y@J%SvnHiR+t~u;0O#5YpG&~~2@r=^+xO%41 zt<8_wIEU-xahYaT?bjF>AfH9EzJDyEqfs6!&)F1~CV@@q+Y1OvNt$B!86vEHnTN=F zo!`H|v>{}yAmCS;_`8mN1OdYcNR6Pe({zoiFfx-67Tg_Lj3upF*Hv;4Zg0(JP zF5b=dq{0+KEuLkmJK7>k2Y<`F-i*3vPm1`5T<_O&%6kKrru)Kfs4KyCpNJ-9oOr?3 zKOBjNUPFaz%6?jMn_6ZWD^w<+QfkUfCSLeaS(}{{*Ze`gXWzqSx8_RRK#3XrD>>q@&6vzSVceUCxhIR#D!*v zC9T#BF<$*nOTOx}@ID_ZHL9RE+}R@>#@&lU2 z{>Cb-?__z`Vp&#v4kRbWlI?U@<{lGw} zmsxa98Lr3HgcPj3`4P0@qz+y~BA)N@8Ky+PN+d&N;6L#>^&F^#zz)W2H4%M=!`KAt zT31g@2VK^#*D==$A-6@0gW4Bcnf{Y)37Rm#-MvY^)~`%X4r+eN(YPPq75bj{8E~nz zYbBxtoQo^4%Cm^q5B!L39Zg$Uq+?>u4eNN!VTG}=E*4Dp<++|ZJZ}v)&W?E9!taO) z<}EYa+#ja$L?L3p|9}pqxat5Qfl!Z=U1w5Cv-X&s7FxpOe7kljg_IOqY*%hi8MJdU zx^3fci@=?iHi(us#uOZ-9k^D*uhwJJzGmx?9=uJ~4suBJwlwP^bSOiY|7Z_gD&veh z*$7n7>vCdL`&goKm*)IUL0l*r$o%S^%y63jR}6t>aQ|%w{0S~Blw*EM!;wMvUsC|a zYH{G4%&ITH&?GDS)mNU&9DO`|lYRt}IZSgu)-X>_5&N zzxXfBLRh+97B29R%>C|erT>4s9#0>CtZ9~BvHx!*F{EgQ`@i1HVd(#E*Q$4E2F7Dk?bLeA|K@3^xOC=PBDnw^5!y_LIY#C7 zGoNjT&+E>1;yv(E!+haHpyzk^MZXd{E_Q!X9I3Yin7lZup#Yf3LP`;n-05)By)^YBJt7Ii5pB!OK#PNA^J%wagE9HyF9J4bpd3`Nz17f=o($8XP5wh z`%C9gTkUi5`C1f%fz5O%uF(Ihesy9qRR(nCRll^k49R^`#Smv3KYF|aYdOr7v~y;Q zmb7H=Uo$z48m{{$eAAeztj)yk!&AePA$w6q=Hz?fnh8IjHs`vze#j-?Cd;;WtxQ(^ z#;5m`Esb9S`)aF5$Y!xT-{nu-9~ry8@aDy9Td`m$T@i4wxnyN@-H&yl1H#qp^$-2u zXB-25TYIvF^%dQv+#{IzayS3{7Z}8RPIoNk`bvGOFwN#)92OX2M@d1*lqayf4{|hr zGB`W<9++JR30D!V-K=5{L`=65@LHKP8$TxI<)#(umOl^EF9T+UF3;Q~nyRK3U5=|- zAwO){y0}O7il#zv(fH$x)e61A0Hn=r>0N_)II^mfwPQRZ*!*KN+w<(2jI~c66n2pA zS$kt~`N!D#6S7NzW(tnIcczKj%SqM!+_1k+#B-e{`8<-r>4PWfx@pvr3#++W{9TU(klCXj$HL@9_!i?+l1y^ElD4 z-Nq51uXZZ!9#_HU-JdrBAio-%GqLte{XCPl??jbcL=?6* z-x146+f9*DtnI!g8Zh4=FdLs#l53?d)%2wwKWR~rL;YZ12BY^jE1WHyadUEzB)jju z;_4$>;J%OmQId1cyJoE+FZv;uSezLj^w#%>4XX{zXIn}qaB5u&B3_qQvqnfOmynpq@YM5>J>-6_ft!W9=b(j}RW&kBA-IPyTIAc_&7S5XJ5`9iaG{#^ zIr7xZKr$umwyiBbcpFd^{)?yLne0*7?Bsni^F#9<0cb>*dcl}qR@Mx0IHm*LSTKJ1 z=VlF#+La=Xuwm?|R>R3abJwrp1I}F+`nSiJJzePHBrMS-0uSl{%!zWv^X&w-SI!W) zgKMRUHz&`_^E8-x6;xV6hg5n{wtnSi!Wk3ST{KgW%@VxiH1a0*WGi=&qZ|(dXzaB? zBFpPtOrYc&M}@OR^<$xXW(K3zw`s|N{J|tiFvbOE`R!DEn{4`%xL$Hxv*q0B5 z4GUjhm%zTkmgDfU4XIs}yYim6ir-zVttL zQfA^(q)>#%uFzRsI$@jY;^w^@tsTStKX9t@`m@G%IyBFx--q4%Vn4DTm|bKX*?p4q zORhy39wUUcccWPf&z{yH`_Fqql5v@opu#*0GzsZguI_NS4De-gte4RnJlqpq+QW_WdazJy&VzWV{rUE8l{2eP${Oc# z|COh`O%@id;WK>MwUOCXAh^okI0da9v;ifvbFg<|JsNEei7#z`=T(fag}3ut82VmC zNQ_1ViIPk~8B8x??mW>;Y@gZMf>kctQ?tU>oroj=(xje%S_{#Gqr=O$Pa|M8P)QG^ zVe(iKzgM2@p5~H~x!o(5awoqY==P7@o0V~HMdFR**&has)}Bwf8PPl1dig@SyK)X| zz0VgMu0ms9Q#i~p2X*6ED>j>ok19J|KZ4MyFAOf|NOeTq1-kCa#k;+kZ+Fa!E;Lpp~aQN#B%io*PqbJWCCUf{pHkE4*!4bs2?iFi;LDE%$b9 zo1>l5mZjaI+e0LkdDf(RmY_Mtc*NDqlAu~2sChv+jVO;*dF9v>wB;K5Oc*yWV^W0= z<%U&S;%E~uI=uzWAxO;lNxQBR6C0o5*eY;k?G=4 z-qC?Gvg0Cg<*mbW`pXDTLRvPnLwj;*&mhj*s_5Y%k>Q6?LO!|A?}L$K=~RvbP6-cp zLS18U8-}Bm*{OJIW|2{5XyHs*=Q4cRPK@=>t@M}0s(g3XCN+H!qocDcCWWd=1MN|& znL^~@;qk@FA=874Cy}drm|wLhG&CiJGPu>RD^E4DGufyI+Lw*ig$H9t3KV;^!{#c{-~_Eg|O(#20eiO9iWjK zIoc1(IODD)H5ovk1Y=aL@ii(+W={1EQ;S;$Ilc-1x(yp29`=*s{t$78@Wr=S!fE8u zUuXo5H@|(Wlzbdh{#T{00|EfS;v@yP(ED}Qr)(H%Rbcg%ctv>S?TYxCp3E%{P@sH? z<~8AQvHxjlpFI^2sARh%m3s>APkQS<`TAm9!myvNDmw;e+VT*2<{5CHx9X4s#9Pbh;b-F@cmrOz@C z5N<~|sBkid5WUhHH?#;B6)W$3@+6HY^8$cXueXelxunR1?Mg2pTEl-=0ZxWw;FEiF zKHDaNp0@>Y47e3tVdi^2K->>_f#{XO`QqfUf7W(}v2@>ASag588_zt#ZB0-?_ZR`V zgzVwSqqe6$4)#OmzYc}AFwIYC^G&`+d-oo>866pL#beXs`YqG64;yCrK^mHYR z)2AM>vT$EAaro7D-VQ`-2$mkeZ=Wo1iC+2dJ6f??JPq+)+K=ng!Q@U`u$!y+e&9<-he{J{R#47-vdnt zvVH0L$d^WAoBl@W=8c$)TSAiP=cS{xvS+ladd}kP`ptgapO0xDX!W8+zGhx_zeqUgD@ z1=-WSHd7!ha~s;*X1PfJ^q1rjsj%s|Ipq-S@7VrGe{wA?>7QH4otEXrb{QY?uCXkd zjpt!IXx+3MVFNnRDUo37Ys%T{K7B(*Y%SiwqW+`;Q1xxHW^DgYmzbWGnEh1VKY&MR ziS7FOB1D!5CcW$Li6Npa2YuP0KbOtgPb5yXz#87>B=+=d$~HIQ%?f4Surn$VS2G%0 zkj7wKf_0_9ZtdmNmF&H!i4KSUStFhed*sT*gKOoshnckl0{-xJALS2K`ukg_r{LaE z1r+~a9uI=)_XijH#$}iXxOsPYb8Zbr&20G*g*1 zWcU}PxSf1fsjk4AQQrMt+y6>8gGSju!2cV`{@8@d`P#QzywcuaZjV}|642;2^)i!=kG|V0NxHv##c=;&IqHr6BdndHd(#_^KDb$p zL~F>`6ri+Z^MxE<5oE_CVLL6uMMUBYb+L&s$)QS{)szLRmXw;?-Vyj%TyK6pu$zMM zk7Zk;>Hw;ffL*#8{%5?UF8`({kzBA-;fA6=FCrWJ@LXxF#MORfavEtx)qHla7&36I z*Oq51i7QPLzbA>KNx^^BGqmT7Tv?;;BXSy{HU%O=7V@SG9miSu{VW&>z?`Z|C}C$SSm3s^sd_yRZe_9Tu;Q_{vyiA<0r2E0b%wA z|BRzw^Gx<>b8UTe?3b2(u=%AKKy&p6)c2D%tBkh8W0sG4^KJ;$%wpuonAuZ7=chML zhfjFK4{qowcdVvu?U1=t*n?R-E+Q|ctlw|xgZ)ln7WK;SePb+ zcY)XYvSn@ej#N%zde`tAp!D&{V@YVAH9^T@3BKuo9>W8STwo=3N1o!E)=~##$(7b@HSUuBvc!z4Jfq7#ta_t zdd{-{^q8|MJQ{ftIJS<{1YX|)A$pE@%4ENNYqqq>Nib2_SkCwd(*5d~Edk)k7sQ|! zH_*RF3$}Gp=H&GuH|RU+KVKTdVI;Kl(l>m!d0$;0GKgQnr1VE+kK#{PT0_8-~UJJ}J+u)jxt6mIqs9NS= ztHuI$?(VzHOxz@nmcLJsptQ5r%8!r7gli37N@;U|qCd4+6LaM)zE$n22_XIrLhneK zp-0`o>Q8Hbl>&xtc*9;kD8f?sHG(CJg-`jB-zZy7!lHYMwK$Z&cY19EqR8fzqEs!K zk}@}lsy6d*nVExa9OcxEj!N|cW1SF2W)Y#G)zrpMtV`+My$*Q%5J&cTG1mKn*x&xy zXIGdGAAe!JiCDV=0Z;*lSKdRbo=RT1O$<=+Z$12Cu%oR76`gDROQ|3+qQs@vxAWNy z$bBKw66@wwbq1HKr;{oZ?mO!+E-yQtjim?S&3bP(5T;_bK>?;VU+v2lhr8L|AsKM+{T$x(ljfWVVv1W%l*U#xwlH`!74thNbODTc8=bf#5 z3KXl+o_Pnj1W_PQk_Bq~a7w@SKT5s)qAbDXsO^(-vHP;`0Y|XYUm3WQ?}$=qQA65R z8g1S#yOM2=G#ovbyT^(|qWf(jRYEH($XRQkT;v7Gs;n&!m%d=8_N{DNh$u%n# z^%X9y{XaLoW&m~4Ze{|T<+TpJc*UCjFXybL?tz_d;WP9b{fo~WAir?wV6oFgA9FJ>gn zb_10T+Aeb&tnK!%?z#UwpKE|@F)HIOOJFPDu+Jai578+v$Ji>GI)FII^O0eonlYDIy%-_S2;Rgxs2^~yZPI9O4|)0 z+Yvf04qOnh8JN1|@SbhfTvDPQ%WV6)F|tY(f3{oUn@H}z3rc(=cahST~{PeukC|;CEakT`j>90jW50) z2sf`}O&rl8vre)ct65JX0-TtABlumIh1|?fg32m! zFbHx~FH$O;Scmd5P?upDje@yUGEL-+(BN^8-Q31|smdf6v{WfxKAJWK*=HHfRx-=1 zc56v}$$vEULBV~2;=MR$=9UpU!Nw;q!U)I@Jok)5j(W6We5^BckI=|9O&QL#JWL!wV8nu%zWsTWT93A_I^97~Z)6OZS zs%EmcjD-dyQMBg-&1dV3n%!wB*AcLRovY{f#m_^Mh$;#QmsJJaY=9Qcm-XX5dR>Jd z$mtyT@{gJ;|-eM!49cLD$QYv!{3S~xm1Ka?8Zjm}3Z0+|)tjH@o?j3^+vDvM= z-A|5Jc)OoO~d? zL-0J2U`Ft7Rox^IEa>9&&R@43(yKwt3quyURt5hSrBbl!pd8yiYlnyq4K0Lxr)ZyT zW;haN)8VP;G9z*Ws4yx*16uvXAMfMcKfWlT_;P~D%2l8Sy@|Xm5F3}BsC|avPtTy_ zNTTW0^tu{cUlCe;q+_$o(F3!i*54Pp*&kuO{&8BsUMz$SG-6Lr=uV$J1sAX+WX-wn zZf62lUug5W*n(^$>&jzNqe>7XOeRhNq91qQ# z7z0tX`!Dob*Bwh->r%~W#8cb!VjdmV4(pJXEPp2;r_uUF#J2Bi>^n)##Jig5@|(t0 zaBEa=V@ZRSd*{VAWQXcuPSC33$k}3smNXb~uoeimu&F#8^AfesM?7QLE?iC#wr_CT ztCAAD@a^IyIvA)P9k`tMFiW#aY{Z+e4nIfzTv0Z4mVWd=#r|h(maSxupqwD5E&V`6 zVEI7C4dEIVPQ#NV5OnC943oFX;~|qyIfxp1MwQ^SQ%TlkBYY9F|M*_PGsIkrO?S$L zih>^vEP=yK|6dQ1JbzCDwEJPZ64)w#?hT$7&X7lL(ODbQI;)PqY?tAhNfx^=t zl9Jl?nDhrzhxy!CT7Zix#V$)zk<;ueY5mW+wL5uzlHPe3-S_FE-9;P8f1Zbb{=}MW zcbeJ&tZ>5Z(WzfB^|~;gwLcjm#l5VuT@)B1w{@Qiz*PL#pMfC(x&F3soa>eJI~L?Smyt zH%NP0zHAbu9*QUq(^G)W| zLknUp4@<8#1l@M))m-R`md2H3maeghu95S-1H#yBN@auSpeJrNC=gb${1&9fQ%atD z@{Zbd-s_uPx*m;s-zgi>{ zDkwrut-F0-l0jA$#=>Iygq=O-d1X+6cVlWzlx{y*Gee%HkO&DMWJ^H}ZU7uVlp^_h zD)8dbagEK~#&5SkgTE3@gd7xC}_${~slO6A>S((^P@o6KL*vd4qu1Ng`eyrF^R z%@s@hmoFD!dKk%E0~uaYZ`Lcl2er-5b4IX%o+4Cg#%7tP(p}3NFb%D(0#tTb9q{Yc#p;~2r#SIK zVpRM3kAuSpvxb5vM~YTvJ`{o74FhrmTVLbR@)~wmXMCzo zE;kb^>%bBRLo8FV9j5|BtpKM8*$QF}xv$lB_ie4kFQvs>hRXs_=ih2gt&RY<+Wp{H zXFb77nst0CR9Vf+=$~aXEW@H`EAQh3w13PkoOw&|4)=R?@?_0~9I@Lm^MqE5)agJ= zScunNNp6wpS1Oa0gXK1%itrrw&3USZ^Ng4D<=wH`d=a91%_$2$%=df^cJN)Q*aS~g zGxyXZ$6}JPr8gsh6-ABLnsre8jFs`IO)CD}XbM{auqOiXBcDe>`=2#CV;{8U4Q z7Jhb}or2mLb0ebvg#d#CKIV}23RK#C_x81?Hd|XWCv~?!e+{gXaIdd8YzUC2{-Q|L zo-U}5j37TK`p3HnU%#2E({XU!%|F7sA+hO{otvLL9C#4>12y#yS`ykW9a}rf#=b#@ zj~o|9=C&%@a70@$4gG0rO2wT1li=#5%2_bcWSZ~PC?b|Gg-Z~(Qx4K}t*Do3^&nnd zdYva$hh>t7G#O+Uoez>B@LoYL=ginS*T?VY6VY-~e{X z*x{U>2+LIiFJ+AK?A>S5--6gfhoj`_hT5|;=3hw<8ZzZprFiWMvU|VZyy}Rc>O508 zsQ$ZInx|$doK813MYp{<(2#g5@EpKrcn!f*0UoaSWX&BO{@mMFzR8)iSH%VIdZue4 zbk+?fM!Hj~oO};hp@^l>t9U#E2R_T*oB^$o1zACH$ENl;M_h|{#5s-8oj#v?mcb*4 z`I{W*#wDWcW7(1X6E3=Sgx=@$lSiC+$Eb8igb%PY!_2#nvNn8%9${;{#U^ERXLv)w zlUE$H-_5HVThYeQ{Mu@QR$`fiIWu2VyS+sy=3Wf~&d$^Ad4Xz9Pjy&xG&8){yx{74 ztPPBh?Fm zkg=>$SM?cu=AB~NYBjhPknkCB0|~fs_X3QEG#j{jl0e9raZ=fNir2pPb}{STqva~d z>)193Y77V?)%^%~_0XIhI1v2BRQ_>NTO;WQ0A!Dm_nCFz$mG-6Xhs;}PJAHfVcO^k;k z;m+j;c8@}=pOO22qAge^RK_B(g}Ch{qv!m}2sLzSm<8X35W#AEi_;E{N4yuK9*GH` z5g5roa@`RPeYbv2G%~!F-?*#V#%9T^Pb2o`(oe?dIf!f7+}nq7xk<-(`=oX9)UyAp z@tW&d?|`6;+0l7GXT#-nCfRAmd2g40{o=SFgJ#6R%4IZu3RDCCi zfyp4RO_FT0BOJ%N@}sscpe@DaA~0uJ?r>~QHFUuxP&7>DN4XRl#BxT34}Rx6q2vW^ znn7o2Qmk;w_FK3lEkzR#U1T|;rf5MoG=!*0U9@oL9{LO=q}47TPQ8}4xQ1Tuw63gw zM=TKCEI5a)P>WfvCB#5#$Pd7}A?~ZZc<%LN1Bp*E--F{Oo%}^lGqNS7lp5Im+EAf@ z6ib|>Z*%jno1Co|=F(JH71u=R$N>5dfo85wvao^0#PbeuW~xvQ<$gY}&;89s zrEO+>vB3Tn2DX{j`{r@^2c@6(w_=$A^)fhlF9eO0r3v&2c<>!K?bnU~-1)D6_)LiGY=$Bw4k2+YQC7GgvNV$^n zzC@j;hN3FgAIU7ZMl;lOMW?wFHa9ravcK5x=XGl}UyH%3+l)?cRgJT7H?n2HEA3~V zUl^Deq1F?l^Ph6-%9lKYi8?~W>06W`Gs0h=ompig(Jz)(urf1%^s~sf@biWM-5nv3^u--){eKq7zqy+{6E(Wo zzD>?6oQ3f9$RC57SVnTmmmfsK`&yj(1u5lBUqcz~euHNT>`-T+1a*2%9MkLtR&Am# z4@G?T@&@Y`mQjD%XPs1oNjn>XJFSL31Kn}fLrd@Ak5rUko2EsF z4@l(WC_MjGrg4R)?3eUmQNhXa84^9YDf?CF?2m%oK#Pqw2-W$ zcI~{oTGF`>nV$Y@SLYCPyUtT!&YNR@66yZ7_8vdRT;HFNm+E%g0elzy<6O{pe2M)y zDyn=Yr1)PaN%frDjA)RA`04-eDCqs?WwSPK7W2a<=$C`4(f1AZYLB*S~Yzewr^CQ6b|H6JHHkiU$MdL6u5S!b8yj@1WQ>%>ac2Rp`wc`U#F zGL_d2EX#(fAW#R~&%jR1^3Dd(VVvr31a+qoNApj|WNqh3uI}|`k9J2{tw_Uaw{~GB zM5dk5UDyrBef4f(nM-(rgLA!p(~Y27cit?udi+k!cWGj2^-WUP@+*6lbA4*p;i7%e zj5&j>LuPM>G-iuAY`l5XV>YJ$tGvJ9ifie*Kw%`fyE}p4?v?<7Bv>E>cXx-zA-EIV zAvnR^T^fhr?(R1h2VGl?Y30H(zn&lstgIvw|8*h#v2j9-uY9 zFxq=aBwH=W>e}(4&?OVG5-b*C9f={fi&Rt^Xn(K3#eu^Biwu{Cds|;$OdI=N2se&@ z38;5Nuks$1y8Z5f_;!9EttzBt*LX@>Jbvp(b6Y8RN?x?&NYHzW`n0+3$Thy5LUsvO zx}oZ!jVzuoh+P0#tLi0^?PfuW7dJ`i;Pyj$!o|1Un!6|lCo=NuM#LucD#In6 zTOW0W8f#GnF~QuD7n?70W%^Su?yXWx0(`97nM)2Wi>JAsNAUHD%3pmL12_aCTQ%|R z$K_1n275#;Zt<@66c~%Fd`V7yQu`M6xCN?#*xq2Dxvv7=0^nLt1As%G2Tqyw#OX>O zcHOes7DpJ$J+suwRAn4X39k~Di73W$%x7^#=G=|$%nmB8N4^?;4~B$DXhL%u+g*dx zrnj&-s2lf7S?|V!Dx)u>SB-o6zc>0xl^)!WXii$91}-0KHUyPr&1|8iRcebtq;{Ne z8;qj3*cW)45TeCmz-;cM6{M#c@s?%t0#b2MD<}0;7PK<{js8HYYBj%uuISuwZmq5l zyS@k6_Y-1x%-ZhG0GNfn!14QRA`+sEARE2sSy+D9p9_1xf))7A^2P-HTTB+%c@r-; z3Y=R-IU_rsRe-+^6KmFyyuVIg`L&NW#WlPrE6CS7e|4@XDW{Kj7D6d70Xa=xU{-CJ z*v+x<$`)EKRGD+xwpwnTk+U9K*doqlXLvULPOc8Z1crJY;a15?(0yF<^7E_L0c3A$ zt5DR(Z4vg~Z|Y86S2HKktaG-ShKUPsqu51ETGn z3E;Qw3*qE{)?Z)-Zbwy^7g9~rUMLK6q=%dBsAX%yIj#@S6!Ej`FF%mZQV16S3xj!( z_HW)K_`T$q-7>or}^mvlaB+2>lWIRLv>zrI|R2zY@?q)+-ufMHKnxl)-- z9USUg6M(_jHY}7&`m~Nu;!j4KIVCXX?J&`r zdx+eT>ZSYUw&gfVF=n7G}we(TTc_f}j-bLB>HTjr+j>EHMtFFFbS2g`WXqo9_s&ngu4UA8NCvt(=P1tNX$|)08 zlSXfzj&$(j6_qxQO=;eR&>nwAKI{%LOncpO4i~wjS31#9BYs2a zB-;5M0XGgmZD`RY%`f{8E$Y0c)O32nH&15?9t&&yfz&RSXJCy8`w5@z4RaI3mW7MS z@MHP5X!@jGgC_^BvtzWcc93%Jd}X<3x05O+B2U~k%>eG=!H1yB zN8Pd=GebnfFT7j?wXJ zavRjVCWPDV(y|3+PFR{OXMaBiR|X7EIC{gg3Koh5s`V9eDo-m^jQyVSYo4FX}Vn9s#`#a0)ZmZ(M~J%j7K zrTf)MEp+KpRo_%bzJkvfReCwFc6wR5o&9XHN?SiJZDb6cmSkqIkmfov+G(uDIPYmSE%a!(k;* z-x`0x$t910(f@0oQFFFdv8?&nxGY_s6I>q=Lq6<&f?#on0R{us2#KP$GCBK;W7@P%V@ zwIfB23EUY%@e#v-4cDbqpddx?BE+}ht1H%!uDs&yAG1HWT$?wWfK&|I%De! zB2>jgielrb5~hVD;iMMwA>cNv{>j7l(s~y-%^$l{-Vs5Vth$IT_odM~J@PtUUI-&< zBd}|{TS9kOXJzhbc~#Nh;uk^FjzAo}2=2_>+YCO3B^c<%Pn1=2s8}AUXrlHT=>8&$ z7qle!Uw#*zvswL5H(nm;I~})sUkU+qM4d37e!V-H{DaaY6%^5 z{{19>+ML=}5o`?NV@>w}D3Qa1DY6Vb97EoCuzn0D;9^>NgT}+}uR>>X69C|>;bK22 z%U?u@T9t_i^5h4R{hIta*lIaes_Gsh=Ck=D-oU$IQ~L=XWy>~sJflIb*Fx{>*3ebb z_ooA8s_2(sEsfb58<}eloGR<<(UK02y@i_CHQS4yd>|YA2(HaCR((tBieX~VCGd=I zGF}8SSRK6&{f@--(#j zE(uen&-ZT9+`P&nJ6hNXXcR@mwRa50OuO2ys@@dOSDBMl)T+C>FZ9;DVC)wvK%=S@ ztU>bSEm){X5d}dYw(WZquYU8Aq+Jz5Fqh1u$4d}|RpExmC4jzK@4%B32t`hsjBugV zpdt6Bn5hWKB#sCpQ-fY799EhW6MY>+-0yec36R63bb8Y&Ky+fs8>}0$TE6e~mRc8q zV=KHfUbx7s#&B2!>S5TU>_hwFZS2b<+0e1jGrPEo1TJ zLqwwSXwxIr@526vH-z1gO+#|x2Z7sJ#`lQd_Axd4qL(-bBlhnzpO5AbN4D!*93Ge1 z4Na&}Ok7Sw6Os(``|dSep7X<+0Jq*tl*^qVU8gGh;2TK8JxlCa}VNKemg`k2h zU;k3Hopf3`cXNn>Sbr=i9;v*=Acqs@;#8PqIE{=;$=cx8`!S9ys~dri!fL2|4$YNXbUfn`N@)czg+ z)g5UO#7`;9k08sc=eTJBe2X`H!`WDvABIPQp-43Lb{zA*2GO@`s8_%-Srnf#=>iz{ zbT;F0Kg}1TzWdG#*%!;P*#C5<#E;4fI}JuospI&~DIFkQ&-SI3@hkpY6ovN^Ns zp=g-<9M^t?Mn(EPz;UaD$?d?6{(dXFfKze;_NoP@h$sTknHZZfy*)-Xh1)&1oiDO1 zwWPjueDeqvpLRjZsgT^Z?D+|@?#{PGcWr&1r|*p#q~Fj4PeYEf4K8|5(IgN=GKgMk zRQ=Fn-?aZ5sfej)`5TDQ9;9aM_}1*_+w9z`hkI!(}Ei`pQTw!3ua@mmaYy%5l=<=~pxFxv3CL^?blu=007zyR{^Ul1?6#M5}^8vXGp@5@a zTetc~RdO<^QXNVThiAuhc^GIu2scm1h02*=o|_rGEa9N;CGNe9FFw7o5MT8}+g#@Z zu8bqhbjCSmv3h?Pc-GQF9zo4Z^nn?|7`TN5KfxEc+?1C%H`mr3rVS+(0ii?+%osMM zlM;~kE!ZOe#HJ@zADU`Hv&ts(&QUI}2sG&id;MHlE8@ty_V@vs+>}U@uVNE$#=n*MkG7TBex9O_HGeZnwyX#UNrK?n(zhsiHye=^8;nWHk-}XmGqS^H>luIp zAl7Z*iW%*5;t2FZk95XVID<$_)-O54xtB<*dBv`YI2}TLYFu>v6A=>UUl2EkFDVY^ zM3hnYndtE$J|&V5idO1@`F0Kan>)OV%b)ceAy%HRSvo}n<7-d}N4mRZVce$&pr$qO zRm1PG&+i11(y!)^7`Gt+xT;t_L+XQ7WD5;T{%dnQK2zD=h=ddw0!7fS;EQ#i2~-44 zL_j6y1a_Ow#1hYSJ9bQo>T&!TCM$T#x28p7c=r8rXIJ4L0!?_`WQLS^hP7;(A@kI_ ze@}qu|MkmP@&AdWuWZU@_;`6Y&*}CxxL?3`863EMo>$fm=Nm)pXL@Iu>@^l^7juVR zv5^lb9?*JtBSVi$eLm%F6MMBzm8wL?SqGX7@-OuOMvG~$cKgwIpi7>M9;7hJiLDSjko)z=bN&C@GJxDe0TLgS|ky?t_85@|9@Bjq0F4nS%CjO$x-}U zVF7cj_HR0$LblE|$1l9C=nk~4Bb|huj35LNCdOS;;mMhZH6~+5Ye(Q<5MMm!%|!PY zFqqiqXZ_`;{6w|}_8Q6Mx&$-q<(ayu!mTPH|<78OXcT3vuVtpplN8`y5?s80bVakZumyNn<5%UNCJ3Qpm3N!U!`BnhWN z@AgjBY+)MTH$thsGlRy~U$@6A*YBso$egOUn2IgGM)ys4x&~a`UtpL@xA9>uxtNrq zI-QLzFWV`cK8Kyqmz5{;sV3>Cv?NPkTKCq)U#^~kZbj(Dvp$kWlf93K%sFE>!} z6;Sh>(1(W}Hn|JJDf_hB7iqqrhH<9 z#M%!5F?k!i0z_V3&s1DSu?J9d6O1t0pR*4&4nG-sy3c8L2W7NgnX>VTp3|I?>W(MY zd0e12Prhxvkr$W^jIOqtquqHY7+R(3G<0>{Zm9K6ER4Sv_tMyb$DN6!M?}04R0Ny#H33z>y0D@$$3= z>1?4fJOSuYH81Rd+MXX5%6Q-9{LPMt(7r2Ya&Fo=wTVPd7fO-TCu} zQPDa+ON2sF6(rHwpgP{;S;UI;9$zYScEg4gq$XhqU7^#cZ`G?hWyFao{c;^mqP9JH*@Y$wm1J7g{#tgV zAV2I2L7r(rMjG0+r%iKB6gw-b3NVlOf~@4g&E;;n@ky$bf$o!B57t?Bar54wl4EV+ zdk3ii^$;m>Z68LP+ColZg0W_<1PuF4SDc7yjzvskEh0#;`R?1(w%F~HW~yy>a?MW) zA5-{SGZ3A|QqGD{ZlsfDNHdMdRxulwOIqlAIlM8uHJTqd@~N9O45@rEBUQYl>gH+> zqq$iQEmQD>(Yz#vsO0H|*bl2U%2%DxzfQ*uz@EA)>%b_(P7ED|tXo|$isuW2rO49F z%a*i3xYn~%9SAGpBOP63DEwV!X8{Z?RiZjCrwyy70WkN>*5A}a@dUS(^|A?F6T`V@sWRdgT!a%3`l zHoo`c_k_PHk5GgCv{onV0d#tQ#)`4ViHfW?n~p@`AwvbXp~cnLCIDB9X0^I7O)h<$ z9*eWhr^g_}5a+Y3qfTD*Kr5pNPAm)iZ&kU;#4@Z`)j?a{&h{?t`{{hA$Jrc>M=N#m z;tV*0!jIAVXbZ9(UBLF}xhhdFDn8og`SvE#shit9945(q8fl#k`#l<5Gb1&DD?R-{QqdBcGOG%y=fD`@h+>ya^=G>;S@V+)_PT)N z1+-W_Hxr#FKgOwE%hC{9xM083*hmWhmoT@ZXeoTzaUdx{=T^{23XX@L5NuQ-%E{w9 zFW5K48I7sS)A31_k6Xl>Cd_-~I$Xb~$r^OxM)xsf?#^>%ZPJc?3nZ+b=R+9)RJ;<` z?a{L?j}V&S`zyiO_M`P%bNuuczHgaoojvz-oznNW*r`%NmGs0&+}|rrW#E9vZ_|H! zZ`ymeS*SU|1ZpvbQt?6ma{NB9?}cwKOozwrsKj9l(LIZQ ztmqcy0z7S62jOHXY{MSZkGK1^)jt@A$M{}BX^IwiE8V?|8}Z+tx_Ur$Av(W5G8s>l z=-pY7(~I-<41 zkfkLqe4y&?_rf<>0rO>Vx=(YPz=PZMV$t5ymA8#j<9jihTn|qU91szkSmY^!m?IS= zJ*9<|`){@CobRs2GUrmj>;m@PeaRfDE3ZZfCxkF>WB4fc&EI6%sw@uv#eT!u&IwD& z9iRj25dvv(0O5`}v1Zi&=8beyaA8S{=k#APIo`=1?NgT5m>$PgY`ZTi0bx3vY=b(M z7UD?b2FVn}<%0ZVQ&ODUk_5A* zW={bRTTSk0fZ?P#xk!!eWT=LGE&O?zN6h7_vAjn}7V9Wnu0LF~u;gZzr~&A)qKd(+ zmwWPyi48G6tZ&M7sVpNS?X*gokFr^tow#K$7YoZ5ZNcp2OCz^D6&sdZ2J(X@Iwtyi*pb%W^6|EYkN6nSvdPvd zvby!@aHb}L^LyuaJyNSnwMifq8ya6E%U#q&xvcpshDi3m#t+t#l%b!qzEzZ! zjaGd~PH4RjM)bRWu3bm47uBqd`moGW%jr?xTVZ#PxmC@H2S@-l4q4r$BYNhD_X=1- zC2I}`IqHGsb^+zxiiUT*q8Kqu(ak>zyn|TJp89i_q5gyf1(5en9IdLYv3m`^Jh?wT z$kW%F`thYWZMDZlx_GQKu84(D@f}Q9_A(c=^`rHm6h?LGPo1_P4_I9g12~fKd`#rx zGPc59=}1om@KwL;V2fYyUhXpQWtwY?;8<&Y#JO0NwA8HiK-gsfUACP|&Enf`N3Q%B zGtFj+Bayy|IFcsky<81yD}CuP5w|xXbXzK9DFXn&5B8;B!*lzN`GUN$K(3!7S!uci>0Y7oe$Kzu~Y@|AY`^-uU!K(}(@z zIPD}$lTr?3l5o^oV#;jW1{Nuk`;ER`Q=Fc@bd1&5qIEF2=vNtYZjeM@u9qH{w>^x7 ze627$37b`=zN|A&egt9KQa#;2_9X4y0MG^g7>7}~MzcftQw6=J^c~D2(s>P@J`)L< z+}(;tL0}4a)@R25`lj*cF=zo|-bgS6mB)b$L_LvfB-fLH5?HA4_Dw5B5L$v`x4%rc zAzFhlKcJ*?v2yM2UW)EtrIh3EMX-F6>+u&co?`6ovx4xiA-INtN8YM$?Gn;jVlu?2 z5E>-H>vk>HhO|U{F(~t>st7_3zlVpd+WIE z86g#2g(4R2yjuGMbHYgAaH5K)sK-HO~EG#iL(VmRra!d@p; z&5#yA;sHXwQ>H9@t@;dG|ItgGQS*qh983q7S} zLlBCD6hX`r*4VhQl=cjnr{d^YCotzinivu>WNj4o>VKWu`@=s#f>&@vUpSF2H}ePP*FQ8}66Rz%Y?S8K24w%W zkF-Q&FD{Z=kY5+uk0NI_jJ1^R=_{t8pu!HFa+iG-$H#MTBwk0oH1E~Cqvl3{h|Gz+rQnd1u6IM zln1=pZm+Kc_l>k%Evc!gtRFdEJC!6EzUK2kT_|a5BZG8{A?$B)0Ia4WjVEaNN6(}d z;{X4Hy=jS!jkV)zWc#T2`W=DXyXmN<6KV#A0|(W=$Q((@W-SP7zo4LCNN8x+)`ea1 z0*dd74GjksbkdTXOt_DkdA%}(`NW=&+wQ?>_&&dhgntE+7|hPbT05A6npgTpDB!SN znV(+}0kq~|qOdQ{6+bx=vB;?V`WO=vzs+~}YW%imXomHfz ze`|la{aHTKqJ6z~0`fV-YqiKIHZD%U`4BfVu8@`ATG;_RS1NK-*^!HUd@wvVG2N)k zqHc2eIDc@9sGhrGPR8(?sYYzy$o@nw+q==dtBF7JP0GLfgkvELA^I|0(WIX(ERYKo zvVbdpToos!=;#b;@*(w){f1ZA?G^_lt$yz%B_=2Pu9)QZo%QcHU@%x48Nl$SMNWB( zopSBHO@=Up)V_gflyA%_yoYVnl8}*MPa)(2My*k-_p%p2XhEU?Gvl}v!WdpfQY^MHp+j3uZ$kHX{SyVoyzbuC5B66Bv1v zw#Hsagvw!LVublu?p?afIXE~X#z%hT=KAOI)b%97fAy*j;({Fd(7CR?NFjohS+x7B zQ=%Zln8JbX-}PS3nq}iWu+TU{hMt!$0 zmc%^&YGu8yScoEE9pnu9_rt%d*#BRg)W6?4^eI)!yvpC}Yq=Wo{|Mm#p3J|}`YM80 zO$H4Adlyw^xPM94Uaznnmaq3ebpW-haF1UF?e!8dOo{(r>4b6XGTtlW%0G|ZgzY?? z@JA8EK~_F~U{>z0=eYOdj@BS{GPFupLG~fCH;+JPH7xAc1*2+1^3>`#vZNO5|C>G4 zu=9<&fZ^4^Z#@1jlma*sFDry}%K*s|Cts}L^3pK#It)evhwPyW>H{f zwEk{%=;t<@WJ@{+)=1TRLB;<}J8hWVca9Bfre8Fk`b2$%>?3aY61U46MTws}xOH}p zq&)t!A|x@(86gLy#DeH+qU-=V$dm(pkpAjQ2MudO|GPpUrzR?jqk?EMxQv3-U6+s{ z+YqWp`{hjmq@C)2R~IT}>mDCLJFb?GV0VUFI4TXKW6l3vk9iauJ(dS{3EH(!LR!WF z7!_@1_pq+$wuaB5dmmZ0jz%FKU*xeUaq}`>6C;obn*LFASxWt?k436n^uIT{rqQ}R zb<;LwUm|o{lS%GqA-)2rav29Q~dwEYGah>eO-~`<3ua1q#s+9l(-^m2%9YP!z=fV%+j4a)G4Ax6N6?*X0Zmo|FR`K^Z7xz|0e?hq_Ta zt1(44wOyOy7%Siv!*wD%K5{T}(8O)Mm?>XKZ$V;-R;9!K1!+~O6_ZK_yVQUZD_rs` zzzIiv2xcri5-Q*X7Fc<& zYRH3yl+spfHBnmMY$B@hUh4S0sq-_nHaWJiO%Cd>n#}6Cuqu?7 z1UM5mnb8b6E7$vm=@l^PTGm0+uB$bW>uE}&y$fT&d^7UOKnkrrl+7<2r{euNl(DT% zesO!~tP5-*kpkrv)vf|)i}X*ajqkv_5sr)6H8S*{yN5H(YjNE*qT}fSzqXn4tMp>y9_?iz=Q-r1a>l&fLax%YiFxbQqPLFt~iLLC0Cv#34D8`Px4V=t3jmhsDvAlSEoZ@E{Q#=h%m1CQk6qVR$ z(<+NJE-B(uP~3iZQiwVkkW{o*M^Bq(ncgO!Q$4D^9oAvp82C&=GpiuKDr^$%7&ty- zYq$_(L97s1x!6T?L~k0FHJfUIPL5_kMEB$O)w|Tp5S+@@XIL=?$C`ZvxD}K=UP$4Q zevBrQeg_I$gcxkj;O6d@!EQSM`dBqIOBQ=j>yKx<2ZzO>feSkgD7v=2{>@B z?oV^g`4w#T5_FYyd3Dov+w$YBR{CS&Rub%1l}*MlRJ*-Q#C*SZMAjM4kXj&j7136k z5U`uJx?QBqS!?zLWdxg9aIxdGN@gO|6nDFg2<>f zd^tx7u1ErbH=7XgyZZwS2I!EqF;G@kU&?pz*yZh$%y?5>V%gEq!o>%fJCQ8@aOtZ_ zb}|uR(_j=^3-o)qDWnL}uZ_#xU;d-cwepW-4J-E2AyrudhL^UQx@a*U4w>l2dik}7 z+ZVNBn{kw3O-Sw>t_CA{%oa4|7sA%KAnGld1O8Y6GUTCy{tEa%2^YSsEWNeT21HD! z)Fg|IMt<+esN3nYy6xyp@69CULmcrAda{St!xWjPa*3t^g~GtlFsFhNYV4gkPCYUW zrP4pn01a*-2^jEiR0G5bD-ZWlT#FSje21oUz(kW9bK_jVx;JlmSz&g9U3JO0w=d3; z`hy0X(O%6u7D3sWwSn~oiDa}}>M}p#sYX}z=m#a!5yM*%`0VK71&5Mbl$MdNp{hY1 zq4qtQpki}kF}$^3Lrqq8`CN~o>WyXYj6<_Ec`KtRAIVX^5sF0nb4os>weB(Ge(v4zNATz5MGVJ6HQwIaUYAj05W>3fowQ zGfIlherp-J10WP7R*^jq6t$oF;zgNZlMX8F2U`e%3=*7G+_?R(1(p8l4a*FnsUrp& z_L^}`g!K3OxooN`&{yDgzq(;?8VGxGU}#W(C_qw6jp+L80 zE5qGHcu{-8Aepw{4vC+V{fY2Vw3yz_fbMryXHu@&{1qb_1w2*NUa#+!4TjDcnwkZ# zEX-DOe~i^1J3Bb%o3fD*%YF;Eo+J97$33CZnSgs_rMhR#+dFZ5&$le;>}J;4IeG0_ z&y8mD-v_HWYVNvJ=>l-xBE@i%dnSM|-VA1#)I4Umr>BH7q#j_fl_R8cE6?FHzbxox zQDIl`W4krl;g9z1v|j4Y2yO_i-8a}cbw34^Nx(1iy2C}`4>`Wd; z|41L3Is1Ip8*H`!wp@Mmzy#_PVUx&Ok+}93V99@@!}dAF{BBFSlZ;mIUE-s2$aH@u z4fsbUXIM-!ImW6^G4qK(-myif>FpJqY!uvi+_Bk4VM#-csmf6P9%s8`={lSwJGdOzN zBVD<+_D>ji5zZiqgb&|z9Hz>*Cv*vIR^X_)kdrcKaNo=fxel6~PX4puUNPR&cqnRt zY|59hJ95UBV>)87plvH3Fetb=hr&#lyw^r;T*15XWs*l*ufE=oEN3V0Lw7ALODU); zML5H@)os5e=VFBywceovEBvu_r~lU}hj=07 zywt>{3hu%)-ghjd6BnwaB)o#pn;qk4K3;l{l#zGGr3v~EgYNSRv)fK8FD7u7!&9HU zgpo+~0Jqget7%c9V;_knVaPHFJb)qlEluNxE9{+uJ~!X3o#uIaB1995g0(GHc(Q-` z$d{Ue#;lcb!G2^jj&3gckn;q_&Y%s#^=gpuGZf+0?xj_xm}jHr_9q5g%I?KaB=Vc{j%A8?S%>H#4pvuJ+SV z?LH3FEntIt4{8P3lBDgfri_lJ&9e=ha8^1D_;mjL(~>nUZy0ia zuP#b_hDK>(HG02V@#se!?Hl!TA4puuWeAK%&j5mhevFde{gA4~KGBG(Wmuf*|tP@JrD*TYVj}mPk&FWxhln=zA+KKXxNHxf>QbZ%%{P(^tTOG-d-YODdzud>R&8FhSUb0`PK#2kQ*Mz{uYS&>!A`k zP-D||J=$I$Ena!3PR`sSodmx)T&Qh(IffG26JWj=X+3Tkt1&A6q{V+`Yg;BM}Dm-$-2`esnY(HiLKL-c)F6z{9XYynoo!&%A z@IL%1nRKb*w--D?9Qk1G%ZH@lY^aPqwIsx{@VB$BDFFkEWq z15U9Ib>b^hSJ_{N(Chy!>aRzHnm!rA$%etp>$v6ffh?K%8&a!>3=*w*Lq4-}`077D zr)K~J71%h{G*t!{@s=v>4Csu%#V5eSH_{1r0R&|j7Bq$~GgR(U++&lSKxNt%6vP+E z^Y9Z<_{F?uhK>W>QBE6jvh+TR3-zB zyR}jOFe*UOb3)^MDZVSr?dvuFu$k5MG$>cP)a(a7vfCUTFx5(}@cACoMikRc6F8+_ zSLL_U!PMtM$iG4dT_Z+wDpDVr?k4Q+Afh?Tmfa20bI>h92Rp|OMSpOWnNwsXqB#`4 zumCU5l^_smerGV1%*E$F2eG^ADYSBHQnI{_t5JITk8QosW)qa^bFi5vY26H{!Y`GA zl>0W{OL`IuuI$Z`{oh7#DtTL6xbD>Bd*&z^t#8y-!TPdt0a{64YKtHH(?6#p%!p+8 zQZmOSdm!T|zy>Z(EZxhZ0R_?C1+n&(EDtLG$LE@am3|Nw1Uz|mf}At&lWX3xVR8s- zu}#{yg2smhCil?XJsnt%KJj?Sw_K#!P?s6DcI3x?%hXbO=-`>RmbqXAaK8OdoXmZl zFiBw!VFz{<1?d-;>o!+K=y|~wVUk#K_Gh*+QZd;KzZNSJFWG4}P;>FX`29hM$^LR-^hJ_F}6A=?eq=a2G|<>GpN{|_~{ BGcy1H literal 0 HcmV?d00001 diff --git a/bridges/docs/running-relayer.md b/bridges/docs/running-relayer.md new file mode 100644 index 00000000000..710810a476e --- /dev/null +++ b/bridges/docs/running-relayer.md @@ -0,0 +1,343 @@ +# Running your own bridge relayer + +:warning: :construction: Please read the [Disclaimer](#disclaimer) section first :construction: :warning: + +## Disclaimer + +There are several things you should know before running your own relayer: + +- initial bridge version (we call it bridges v1) supports any number of relayers, but **there's no guaranteed +compensation** for running a relayer and/or submitting valid bridge transactions. Most probably you'll end up +spending more funds than getting from rewards - please accept this fact; + +- even if your relayer has managed to submit a valid bridge transaction that has been included into the bridge +hub block, there's no guarantee that you will be able to claim your compensation for that transaction. That's +because compensations are paid from the account, controlled by relay chain governance and it could have no funds +to compensate your useful actions. We'll be working on a proper process to resupply it on-time, but we can't +provide any guarantee until that process is well established. + +## A Brief Introduction into Relayers and our Compensations Scheme + +Omitting details, relayer is an offchain process that is connected to both bridged chains. It looks at the +outbound bridge messages queue and submits message delivery transactions to the target chain. There's a lot +of details behind that simple phrase - you could find more info in the +[High-Level Bridge Overview](./high-level-overview.md) document. + +Reward that is paid to relayer has two parts. The first part static and is controlled by the governance. +It is rather small initially - e.g. you need to deliver `10_000` Kusama -> Polkadot messages to gain single +KSM token. + +The other reward part is dynamic. So to deliver an XCM message from one BridgeHub to another, we'll need to +submit two transactions on different chains. Every transaction has its cost, which is: + +- dynamic, because e.g. message size can change and/or fee factor of the target chain may change; + +- quite large, because those transactions are quite heavy (mostly in terms of size, not weight). + +We are compensating the cost of **valid**, **minimal** and **useful** bridge-related transactions to +relayer, that has submitted such transaction. Valid here means that the transaction doesn't fail. Minimal +means that all data within transaction call is actually required for the transaction to succeed. Useful +means that all supplied data in transaction is new and yet unknown to the target chain. + +We have implemented a relayer that is able to craft such transactions. The rest of document contains a detailed +information on how to deploy this software on your own node. + +## Relayers Concurrency + +As it has been said above, we are not compensating cost of transactions that are not **useful**. For +example, if message `100` has already been delivered from Kusama Bridge Hub to Polkadot Bridge Hub, then another +transaction that delivers the same message `100` won't be **useful**. Hence, no compensation to relayer that +has submitted that second transaction. + +But what if there are several relayers running? They are noticing the same queued message `100` and +simultaneously submit identical message delivery transactions. You may expect that there'll be one lucky +relayer, whose transaction would win the "race" and which will receive the compensation and reward. And +there'll be several other relayers, losing some funds on their unuseful transactions. + +But actually, we have a solution that invalidates transactions of "unlucky" relayers before they are +included into the block. So at least you may be sure that you won't waste your funds on duplicate transactions. + +
+Some details? + +All **unuseful** transactions are rejected by our +[transaction extension](https://github.com/paritytech/polkadot-sdk/blob/master/bridges/bin/runtime-common/src/refund_relayer_extension.rs), +which also handles transaction fee compensations. You may find more info on unuseful (aka obsolete) transactions +by lurking in the code. + +We also have the WiP prototype of relayers coordination protocol, where relayers will get some guarantee +that their transactions will be prioritized over other relayers transactions at their assigned slots. +That is planned for the future version of bridge and the progress is +[tracked here](https://github.com/paritytech/parity-bridges-common/issues/2486). + +
+ +## Prerequisites + +Let's focus on the bridge between Polkadot and Kusama Bridge Hubs. Let's also assume that we want to start +a relayer that "serves" an initial lane [`0x00000001`](https://github.com/polkadot-fellows/runtimes/blob/9ce1bbbbcd7843b3c76ba4d43c036bc311959e9f/system-parachains/bridge-hubs/bridge-hub-kusama/src/bridge_to_polkadot_config.rs#L54). + +
+Lane? + +Think of lane as a queue of messages that need to be delivered to the other/bridged chain. The lane is +bidirectional, meaning that there are four "endpoints". Two "outbound" endpoints (one at every chain), contain +messages that need to be delivered to the bridged chain. Two "inbound" are accepting messages from the bridged +chain and also remember the relayer, who has delivered message(s) to reward it later. + +
+ +The same steps may be performed for other lanes and bridges as well - you'll just need to change several parameters. + +So to start your relayer instance, you'll need to prepare: + +- an address of ws/wss RPC endpoint of the Kusama relay chain; + +- an address of ws/wss RPC endpoint of the Polkadot relay chain; + +- an address of ws/wss RPC endpoint of the Kusama Bridge Hub chain; + +- an address of ws/wss RPC endpoint of the Polkadot Bridge Hub chain; + +- an account on Kusama Bridge Hub; + +- an account on Polkadot Bridge Hub. + +For RPC endpoints, you could start your own nodes, or use some public community nodes. Nodes are not meant to be +archive or provide access to insecure RPC calls. + +To create an account on Bridge Hubs, you could use XCM teleport functionality. E.g. if you have an account on +the relay chain, you could use the `teleportAssets` call of `xcmPallet` and send asset +`V3 { id: Concrete(0, Here), Fungible: }` to beneficiary `V3(0, X1(AccountId32()))` +on destination `V3(0, X1(Parachain(1002)))`. To estimate amounts you need, please refer to the [Costs](#costs) +section of the document. + +## Registering your Relayer Account (Optional, But Please Read) + +Bridge transactions are quite heavy and expensive. We want to minimize block space that can be occupied by +invalid bridge transactions and prioritize valid transactions over invalid. That is achieved by **optional** +relayer registration. Transactions, signed by relayers with active registration, gain huge priority boost. +In exchange, such relayers may be slashed if they submit **invalid** or **non-minimal** transaction. + +Transactions, signed by relayers **without** active registration, on the other hand, receive no priority +boost. It means that if there is active registered relayer, most likely all transactions from unregistered +will be counted as **unuseful**, not included into the block and unregistered relayer won't get any reward +for his operations. + +Before registering, you should know several things about your funds: + +- to register, you need to hold significant amount of funds on your relayer account. As of now, it is + [100 KSM](https://github.com/polkadot-fellows/runtimes/blob/9ce1bbbbcd7843b3c76ba4d43c036bc311959e9f/system-parachains/bridge-hubs/bridge-hub-kusama/src/bridge_to_polkadot_config.rs#L71C14-L71C43) + for registration on Kusama Bridge Hub and + [500 DOT](https://github.com/polkadot-fellows/runtimes/blob/9ce1bbbbcd7843b3c76ba4d43c036bc311959e9f/system-parachains/bridge-hubs/bridge-hub-polkadot/src/bridge_to_kusama_config.rs#L71C14-L71C43) + for registration on Polkadot Bridge Hub; + +- when you are registered, those funds are reserved on relayer account and you can't transfer them. + +The registration itself, has three states: active, inactive or expired. Initially, it is active, meaning that all +your transactions that are **validated** on top of block, where it is active get priority boost. Registration +becomes expired when the block with the number you have specified during registration is "mined". It is the +`validTill` parameter of the `register` call (see below). After that `validTill` block, you may unregister and get +your reserved funds back. There's also an intermediate point between those blocks - it is the `validTill - LEASE`, +where `LEASE` is the the chain constant, controlled by the governance. Initially it is set to `300` blocks. +All your transactions, **validated** between the `validTill - LEASE` and `validTill` blocks do not get the +priority boost. Also, it is forbidden to specify `validTill` such that the `validTill - currentBlock` is less +than the `LEASE`. + +
+Example? + +| Bridge Hub Block | Registration State | Comment | +| ----------------- | ------------------ | ------------------------------------------------------ | +| 100 | Active | You have submitted a tx with the `register(1000)` call | +| 101 | Active | Your message delivery transactions are boosted | +| 102 | Active | Your message delivery transactions are boosted | +| ... | Active | Your message delivery transactions are boosted | +| 700 | Inactive | Your message delivery transactions are not boosted | +| 701 | Inactive | Your message delivery transactions are not boosted | +| ... | Inactive | Your message delivery transactions are not boosted | +| 1000 | Expired | Your may submit a tx with the `deregister` call | + +
+ +So once you have enough funds on your account and have selected the `validTill` parameter value, you +could use the Polkadot JS apps to submit an extrinsic. If you want priority boost for your transactions +on the Kusama Bridge Hub, open the +[Polkadot JS Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama-bridge-hub-rpc.polkadot.io#/extrinsics) +and submit the `register` extrinsic from the `bridgeRelayers` pallet: + +![Register Extrinsic](./bridge-relayers-register.png) + +To deregister, submit the simple `deregister` extrinsic when registration is expired: + +![Deregister Extrinsic](./bridge-relayers-deregister.png) + +At any time, you can prolong your registration by calling the `register` with the larger `validTill`. + +## Costs + +Your relayer account (on both Bridge Hubs) must hold enough funds to be able to pay costs of bridge +transactions. If your relayer behaves correctly, those costs will be compensated and you will be +able to claim it later. + +**IMPORTANT**: you may add tip to your bridge transactions to boost their priority. But our +compensation mechanism never refunds transaction tip, so all tip tokens will be lost. + +
+Types of bridge transactions + +There are two types of bridge transactions: + +- message delivery transaction brings queued message(s) from one Bridge Hub to another. We record + the fact that this specific (your) relayer has delivered those messages; + +- message confirmation transaction confirms that some message have been delivered and also brings + back information on how many messages (your) relayer has delivered. We use this information later + to register delivery rewards on the source chain. + +Several messages/confirmations may be included in a single bridge transaction. Apart from this +data, bridge transaction may include finality and storage proofs, required to prove authenticity of +this data. + +
+ +To deliver and get reward for a single message, the relayer needs to submit two transactions. One +at the source Bridge Hub and one at the target Bridge Hub. Below are costs for Polkadot <> Kusama +messages (as of today): + +- to deliver a single Polkadot -> Kusama message, you would need to pay around `0.06 KSM` at Kusama + Bridge Hub and around `1.62 DOT` at Polkadot Bridge Hub; + +- to deliver a single Kusama -> Polkadot message, you would need to pay around `1.70 DOT` at Polkadot + Bridge Hub and around `0.05 KSM` at Kusama Bridge Hub. + +Those values are not constants - they depend on call weights (that may change from release to release), +on transaction sizes (that depends on message size and chain state) and congestion factor. In any +case - it is your duty to make sure that the relayer has enough funds to pay transaction fees. + +## Claiming your Compensations and Rewards + +Hopefully you have successfully delivered some messages and now can claim your compensation and reward. +This requires submitting several transactions. But first, let's check that you actually have something to +claim. For that, let's check the state of the pallet that tracks all rewards. + +To check your rewards at the Kusama Bridge Hub, go to the +[Polkadot JS Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama-bridge-hub-rpc.polkadot.io#/chainstate) +targeting Kusama Bridge Hub, select the `bridgeRelayers` pallet, choose `relayerRewards` map and +your relayer account. Then: + +- set the `laneId` to `0x00000001` + +- set the `bridgedChainId` to `bhpd`; + +- check the both variants of the `owner` field: `ThisChain` is used to pay for message delivery transactions + and `BridgedChain` is used to pay for message confirmation transactions. + +If check shows that you have some rewards, you can craft the claim transaction, with similar parameters. +For that, go to `Extrinsics` tab of the +[Polkadot JS Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama-bridge-hub-rpc.polkadot.io#/extrinsics) +and submit the following transaction (make sure to change `owner` before): + +![Claim Rewards Extrinsic](./bridge-relayers-claim-rewards.png) + +To claim rewards on Polkadot Bridge Hub you can follow the same process. The only difference is that you +need to set value of the `bridgedChainId` to `bhks`. + +## Starting your Relayer + +### Starting your Rococo <> Westend Relayer + +You may find the relayer image reference in the +[Releases](https://github.com/paritytech/parity-bridges-common/releases) +of this repository. Make sure to check supported (bundled) versions +of release there. For Rococo <> Westend bridge, normally you may use the +latest published release. The release notes always contain the docker +image reference and source files, required to build relayer manually. + +Once you have the docker image, update variables and run the following script: +```sh +export DOCKER_IMAGE= + +export ROCOCO_HOST= +export ROCOCO_PORT= +# or set it to '--rococo-secure' if wss is used above +export ROCOCO_IS_SECURE= +export BRIDGE_HUB_ROCOCO_HOST= +export BRIDGE_HUB_ROCOCO_PORT= +# or set it to '--bridge-hub-rococo-secure' if wss is used above +export BRIDGE_HUB_ROCOCO_IS_SECURE= +export BRIDGE_HUB_ROCOCO_KEY_FILE= + +export WESTEND_HOST= +export WESTEND_PORT= +# or set it to '--westend-secure' if wss is used above +export WESTEND_IS_SECURE= +export BRIDGE_HUB_WESTEND_HOST= +export BRIDGE_HUB_WESTEND_PORT= +# or set it to '--bridge-hub-westend-secure ' if wss is used above +export BRIDGE_HUB_WESTEND_IS_SECURE= +export BRIDGE_HUB_WESTEND_KEY_FILE= + +# you can get extended relay logs (e.g. for debugging issues) by passing `-e RUST_LOG=bridge=trace` +# argument to the `docker` binary +docker run \ + -v $BRIDGE_HUB_ROCOCO_KEY_FILE:/bhr.key \ + -v $BRIDGE_HUB_WESTEND_KEY_FILE:/bhw.key \ + $DOCKER_IMAGE \ + relay-headers-and-messages bridge-hub-rococo-bridge-hub-westend \ + --rococo-host $ROCOCO_HOST \ + --rococo-port $ROCOCO_PORT \ + $ROCOCO_IS_SECURE \ + --rococo-version-mode Auto \ + --bridge-hub-rococo-host $BRIDGE_HUB_ROCOCO_HOST \ + --bridge-hub-rococo-port $BRIDGE_HUB_ROCOCO_PORT \ + $BRIDGE_HUB_ROCOCO_IS_SECURE \ + --bridge-hub-rococo-version-mode Auto \ + --bridge-hub-rococo-signer-file /bhr.key \ + --bridge-hub-rococo-transactions-mortality 16 \ + --westend-host $WESTEND_HOST \ + --westend-port $WESTEND_PORT \ + $WESTEND_IS_SECURE \ + --westend-version-mode Auto \ + --bridge-hub-westend-host $BRIDGE_HUB_WESTEND_HOST \ + --bridge-hub-westend-port $BRIDGE_HUB_WESTEND_PORT \ + $BRIDGE_HUB_WESTEND_IS_SECURE \ + --bridge-hub-westend-version-mode Auto \ + --bridge-hub-westend-signer-file /bhw.key \ + --bridge-hub-westend-transactions-mortality 16 \ + --lane 00000002 +``` + +### Starting your Polkadot <> Kusama Relayer + +*Work in progress, coming soon* + +### Watching your relayer state + +Our relayer provides some Prometheus metrics that you may convert into some fancy Grafana dashboards +and alerts. By default, metrics are exposed at port `9616`. To expose endpoint to the localhost, change +the docker command by adding following two lines: + +```sh +docker run \ + .. + -p 127.0.0.1:9616:9616 \ # tell Docker to bind container port 9616 to host port 9616 + # and listen for connections on the host' localhost interface + .. + $DOCKER_IMAGE \ + relay-headers-and-messages bridge-hub-rococo-bridge-hub-westend \ + --prometheus-host 0.0.0.0 \ # tell `substrate-relay` binary to accept Prometheus endpoint + # connections from everywhere + .. +``` + +You can find more info on configuring Prometheus and Grafana in the +[Monitor your node](https://wiki.polkadot.network/docs/maintain-guides-how-to-monitor-your-node) +guide from Polkadot wiki. + +We have our own set of Grafana dashboards and alerts. You may use them for inspiration. +Please find them in this folder: + +- for Rococo <> Westend bridge: [rococo-westend](https://github.com/paritytech/parity-bridges-common/tree/master/deployments/bridges/rococo-westend). + +- for Polkadot <> Kusama bridge: *work in progress, coming soon* diff --git a/bridges/modules/grandpa/Cargo.toml b/bridges/modules/grandpa/Cargo.toml index dccd7b3bdca..25c6c4e03d5 100644 --- a/bridges/modules/grandpa/Cargo.toml +++ b/bridges/modules/grandpa/Cargo.toml @@ -15,7 +15,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/bridges/modules/messages/Cargo.toml b/bridges/modules/messages/Cargo.toml index 173d6f1c164..7d0e1b94959 100644 --- a/bridges/modules/messages/Cargo.toml +++ b/bridges/modules/messages/Cargo.toml @@ -13,7 +13,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bridges/modules/parachains/Cargo.toml b/bridges/modules/parachains/Cargo.toml index e454a6f2888..a9dd9beeb1f 100644 --- a/bridges/modules/parachains/Cargo.toml +++ b/bridges/modules/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/bridges/modules/relayers/Cargo.toml b/bridges/modules/relayers/Cargo.toml index b78da5cbeec..f3de72da771 100644 --- a/bridges/modules/relayers/Cargo.toml +++ b/bridges/modules/relayers/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bridges/modules/xcm-bridge-hub-router/Cargo.toml b/bridges/modules/xcm-bridge-hub-router/Cargo.toml index 20f8ff4407b..98477f2df18 100644 --- a/bridges/modules/xcm-bridge-hub-router/Cargo.toml +++ b/bridges/modules/xcm-bridge-hub-router/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive", "serde"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive", "serde"] } # Bridge dependencies diff --git a/bridges/modules/xcm-bridge-hub/Cargo.toml b/bridges/modules/xcm-bridge-hub/Cargo.toml index e10119e8649..d910319d9bf 100644 --- a/bridges/modules/xcm-bridge-hub/Cargo.toml +++ b/bridges/modules/xcm-bridge-hub/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge Dependencies bp-messages = { path = "../../primitives/messages", default-features = false } diff --git a/bridges/primitives/header-chain/Cargo.toml b/bridges/primitives/header-chain/Cargo.toml index 205b593365e..d96a02efba8 100644 --- a/bridges/primitives/header-chain/Cargo.toml +++ b/bridges/primitives/header-chain/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Bridge dependencies diff --git a/bridges/primitives/messages/Cargo.toml b/bridges/primitives/messages/Cargo.toml index 8aa6b4b05e5..9d742e3eded 100644 --- a/bridges/primitives/messages/Cargo.toml +++ b/bridges/primitives/messages/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Bridge dependencies diff --git a/bridges/primitives/parachains/Cargo.toml b/bridges/primitives/parachains/Cargo.toml index 575f26193eb..3846c563575 100644 --- a/bridges/primitives/parachains/Cargo.toml +++ b/bridges/primitives/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bridges/primitives/polkadot-core/Cargo.toml b/bridges/primitives/polkadot-core/Cargo.toml index c0dae684b5f..5ab502569e4 100644 --- a/bridges/primitives/polkadot-core/Cargo.toml +++ b/bridges/primitives/polkadot-core/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } serde = { optional = true, features = ["derive"], workspace = true, default-features = true } # Bridge Dependencies diff --git a/bridges/primitives/relayers/Cargo.toml b/bridges/primitives/relayers/Cargo.toml index 3bd6809d278..71d0fbf2ec3 100644 --- a/bridges/primitives/relayers/Cargo.toml +++ b/bridges/primitives/relayers/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/bridges/primitives/runtime/Cargo.toml b/bridges/primitives/runtime/Cargo.toml index 22206fb2c37..2d454d264a1 100644 --- a/bridges/primitives/runtime/Cargo.toml +++ b/bridges/primitives/runtime/Cargo.toml @@ -15,7 +15,7 @@ hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" log = { workspace = true } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Substrate Dependencies diff --git a/bridges/primitives/xcm-bridge-hub-router/Cargo.toml b/bridges/primitives/xcm-bridge-hub-router/Cargo.toml index 9297a8603c0..734930f18c4 100644 --- a/bridges/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/bridges/primitives/xcm-bridge-hub-router/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } # Substrate Dependencies sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } diff --git a/bridges/scripts/verify-pallets-build.sh b/bridges/scripts/verify-pallets-build.sh index b96bbf1833b..4eefaa8efa0 100755 --- a/bridges/scripts/verify-pallets-build.sh +++ b/bridges/scripts/verify-pallets-build.sh @@ -68,6 +68,7 @@ rm -rf $BRIDGES_FOLDER/modules/beefy rm -rf $BRIDGES_FOLDER/modules/shift-session-manager rm -rf $BRIDGES_FOLDER/primitives/beefy rm -rf $BRIDGES_FOLDER/relays +rm -rf $BRIDGES_FOLDER/relay-clients rm -rf $BRIDGES_FOLDER/scripts/add_license.sh rm -rf $BRIDGES_FOLDER/scripts/build-containers.sh rm -rf $BRIDGES_FOLDER/scripts/ci-cache.sh @@ -77,6 +78,7 @@ rm -rf $BRIDGES_FOLDER/scripts/regenerate_runtimes.sh rm -rf $BRIDGES_FOLDER/scripts/update-weights.sh rm -rf $BRIDGES_FOLDER/scripts/update-weights-setup.sh rm -rf $BRIDGES_FOLDER/scripts/update_substrate.sh +rm -rf $BRIDGES_FOLDER/substrate-relay rm -rf $BRIDGES_FOLDER/tools rm -f $BRIDGES_FOLDER/.dockerignore rm -f $BRIDGES_FOLDER/local.Dockerfile.dockerignore @@ -89,6 +91,7 @@ rm -f $BRIDGES_FOLDER/local.Dockerfile rm -f $BRIDGES_FOLDER/CODEOWNERS rm -f $BRIDGES_FOLDER/Dockerfile rm -f $BRIDGES_FOLDER/rustfmt.toml +rm -f $BRIDGES_FOLDER/RELEASE.md # let's fix Cargo.toml a bit (it'll be helpful if we are in the bridges repo) if [[ ! -f "Cargo.toml" ]]; then -- GitLab From 002d9260f9a0f844f87eefd0abce8bd95aae351b Mon Sep 17 00:00:00 2001 From: Dcompoze Date: Tue, 26 Mar 2024 13:57:57 +0000 Subject: [PATCH 177/188] Fix spelling mistakes across the whole repository (#3808) **Update:** Pushed additional changes based on the review comments. **This pull request fixes various spelling mistakes in this repository.** Most of the changes are contained in the first **3** commits: - `Fix spelling mistakes in comments and docs` - `Fix spelling mistakes in test names` - `Fix spelling mistakes in error messages, panic messages, logs and tracing` Other source code spelling mistakes are separated into individual commits for easier reviewing: - `Fix the spelling of 'authority'` - `Fix the spelling of 'REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY'` - `Fix the spelling of 'prev_enqueud_messages'` - `Fix the spelling of 'endpoint'` - `Fix the spelling of 'children'` - `Fix the spelling of 'PenpalSiblingSovereignAccount'` - `Fix the spelling of 'PenpalSudoAccount'` - `Fix the spelling of 'insufficient'` - `Fix the spelling of 'PalletXcmExtrinsicsBenchmark'` - `Fix the spelling of 'subtracted'` - `Fix the spelling of 'CandidatePendingAvailability'` - `Fix the spelling of 'exclusive'` - `Fix the spelling of 'until'` - `Fix the spelling of 'discriminator'` - `Fix the spelling of 'nonexistent'` - `Fix the spelling of 'subsystem'` - `Fix the spelling of 'indices'` - `Fix the spelling of 'committed'` - `Fix the spelling of 'topology'` - `Fix the spelling of 'response'` - `Fix the spelling of 'beneficiary'` - `Fix the spelling of 'formatted'` - `Fix the spelling of 'UNKNOWN_PROOF_REQUEST'` - `Fix the spelling of 'succeeded'` - `Fix the spelling of 'reopened'` - `Fix the spelling of 'proposer'` - `Fix the spelling of 'InstantiationNonce'` - `Fix the spelling of 'depositor'` - `Fix the spelling of 'expiration'` - `Fix the spelling of 'phantom'` - `Fix the spelling of 'AggregatedKeyValue'` - `Fix the spelling of 'randomness'` - `Fix the spelling of 'defendant'` - `Fix the spelling of 'AquaticMammal'` - `Fix the spelling of 'transactions'` - `Fix the spelling of 'PassingTracingSubscriber'` - `Fix the spelling of 'TxSignaturePayload'` - `Fix the spelling of 'versioning'` - `Fix the spelling of 'descendant'` - `Fix the spelling of 'overridden'` - `Fix the spelling of 'network'` Let me know if this structure is adequate. **Note:** The usage of the words `Merkle`, `Merkelize`, `Merklization`, `Merkelization`, `Merkleization`, is somewhat inconsistent but I left it as it is. ~~**Note:** In some places the term `Receival` is used to refer to message reception, IMO `Reception` is the correct word here, but I left it as it is.~~ ~~**Note:** In some places the term `Overlayed` is used instead of the more acceptable version `Overlaid` but I also left it as it is.~~ ~~**Note:** In some places the term `Applyable` is used instead of the correct version `Applicable` but I also left it as it is.~~ **Note:** Some usage of British vs American english e.g. `judgement` vs `judgment`, `initialise` vs `initialize`, `optimise` vs `optimize` etc. are both present in different places, but I suppose that's understandable given the number of contributors. ~~**Note:** There is a spelling mistake in `.github/CODEOWNERS` but it triggers errors in CI when I make changes to it, so I left it as it is.~~ --- .github/CODEOWNERS | 2 +- .github/scripts/common/lib.sh | 2 +- .gitlab/pipeline/build.yml | 2 +- .gitlab/rust-features.sh | 2 +- .../bin/runtime-common/src/messages_api.rs | 2 +- .../src/messages_xcm_extension.rs | 2 +- bridges/bin/runtime-common/src/mock.rs | 2 +- .../runtime-common/src/priority_calculator.rs | 2 +- .../src/refund_relayer_extension.rs | 4 +- bridges/chains/chain-kusama/src/lib.rs | 4 +- .../chains/chain-polkadot-bulletin/src/lib.rs | 8 +- bridges/chains/chain-polkadot/src/lib.rs | 4 +- bridges/chains/chain-rococo/src/lib.rs | 4 +- bridges/chains/chain-westend/src/lib.rs | 4 +- bridges/modules/grandpa/README.md | 2 +- bridges/modules/grandpa/src/call_ext.rs | 8 +- bridges/modules/grandpa/src/lib.rs | 4 +- bridges/modules/grandpa/src/mock.rs | 2 +- bridges/modules/messages/src/inbound_lane.rs | 40 +++++----- bridges/modules/messages/src/lib.rs | 30 ++++---- bridges/modules/messages/src/outbound_lane.rs | 30 ++++---- bridges/modules/parachains/src/mock.rs | 4 +- .../modules/xcm-bridge-hub-router/src/lib.rs | 2 +- bridges/modules/xcm-bridge-hub/Cargo.toml | 2 +- .../header-chain/src/justification/mod.rs | 2 +- .../src/justification/verification/mod.rs | 2 +- bridges/primitives/header-chain/src/lib.rs | 8 +- bridges/primitives/messages/src/lib.rs | 8 +- bridges/primitives/polkadot-core/src/lib.rs | 2 +- bridges/primitives/runtime/src/chain.rs | 6 +- bridges/primitives/runtime/src/lib.rs | 4 +- bridges/primitives/test-utils/src/lib.rs | 2 +- bridges/scripts/verify-pallets-build.sh | 2 +- .../pallets/ethereum-client/src/lib.rs | 2 +- .../pallets/ethereum-client/src/tests.rs | 2 +- .../register_token_with_insufficient_fee.rs | 2 +- .../environments/rococo-westend/rococo.zndsl | 4 +- .../environments/rococo-westend/westend.zndsl | 4 +- .../utils/generate_hex_encoded_call/index.js | 18 ++--- bridges/testing/run-tests.sh | 2 +- .../run.sh | 2 +- .../consensus/common/src/level_monitor.rs | 2 +- cumulus/client/consensus/common/src/tests.rs | 2 +- cumulus/client/pov-recovery/src/lib.rs | 10 +-- .../src/reconnecting_ws_client.rs | 3 +- cumulus/pallets/parachain-system/src/lib.rs | 2 +- .../src/relay_state_snapshot.rs | 2 +- cumulus/pallets/xcmp-queue/src/lib.rs | 2 +- .../assets/asset-hub-rococo/src/genesis.rs | 4 +- .../assets/asset-hub-westend/src/genesis.rs | 4 +- .../parachains/testing/penpal/src/genesis.rs | 6 +- .../parachains/testing/penpal/src/lib.rs | 2 +- .../emulated/common/src/impls.rs | 6 +- .../emulated/common/src/lib.rs | 2 +- .../src/tests/reserve_transfer.rs | 2 +- .../src/tests/reserve_transfer.rs | 6 +- .../bridge-hub-rococo/src/tests/snowbridge.rs | 4 +- .../assets/asset-hub-rococo/src/xcm_config.rs | 2 +- .../asset-hub-westend/src/xcm_config.rs | 2 +- .../assets/asset-hub-westend/tests/tests.rs | 4 +- .../assets/test-utils/src/test_cases.rs | 2 +- .../test-utils/src/test_cases_over_bridge.rs | 2 +- .../runtimes/people/people-rococo/src/lib.rs | 6 +- .../runtimes/people/people-westend/src/lib.rs | 8 +- .../runtimes/testing/penpal/src/xcm_config.rs | 2 +- cumulus/polkadot-parachain/src/command.rs | 2 +- .../storage-weight-reclaim/src/lib.rs | 8 +- cumulus/primitives/timestamp/src/lib.rs | 2 +- cumulus/primitives/utility/src/lib.rs | 25 +++--- cumulus/scripts/scale_encode_genesis/index.js | 8 +- cumulus/scripts/temp_parachain_types.json | 2 +- cumulus/test/runtime/src/lib.rs | 2 +- .../test/service/benches/validate_block.rs | 2 +- cumulus/test/service/src/lib.rs | 4 +- docker/dockerfiles/binary_injected.Dockerfile | 2 +- docker/scripts/build-injected.sh | 2 +- docs/sdk/Cargo.toml | 2 +- .../frame_runtime_upgrades_and_migrations.rs | 8 +- polkadot/cli/src/cli.rs | 2 +- polkadot/grafana/README.md | 2 +- .../src/approval_db/v1/tests.rs | 2 +- .../src/approval_db/v2/migration_helpers.rs | 2 +- .../src/approval_db/v2/tests.rs | 2 +- .../src/approval_db/v3/migration_helpers.rs | 4 +- .../src/approval_db/v3/tests.rs | 2 +- .../node/core/approval-voting/src/criteria.rs | 2 +- .../node/core/approval-voting/src/import.rs | 2 +- polkadot/node/core/approval-voting/src/lib.rs | 2 +- .../node/core/approval-voting/src/tests.rs | 24 +++--- .../node/core/approval-voting/src/time.rs | 4 +- polkadot/node/core/av-store/src/lib.rs | 2 +- polkadot/node/core/backing/src/lib.rs | 2 +- .../node/core/candidate-validation/src/lib.rs | 2 +- polkadot/node/core/chain-selection/src/lib.rs | 4 +- .../node/core/chain-selection/src/tests.rs | 4 +- .../core/dispute-coordinator/src/db/v1.rs | 2 +- .../node/core/dispute-coordinator/src/lib.rs | 2 +- .../src/scraping/candidates.rs | 2 +- .../dispute-coordinator/src/scraping/mod.rs | 2 +- .../dispute-coordinator/src/scraping/tests.rs | 4 +- .../core/dispute-coordinator/src/tests.rs | 6 +- .../src/disputes/prioritized_selection/mod.rs | 2 +- polkadot/node/core/pvf-checker/src/tests.rs | 6 +- polkadot/node/core/pvf/common/src/pvf.rs | 4 +- polkadot/node/core/pvf/src/host.rs | 2 +- polkadot/node/core/pvf/src/priority.rs | 2 +- .../node/core/pvf/src/worker_interface.rs | 6 +- polkadot/node/core/pvf/tests/it/main.rs | 4 +- polkadot/node/core/runtime-api/src/tests.rs | 8 +- polkadot/node/jaeger/src/spans.rs | 2 +- polkadot/node/malus/README.md | 2 +- .../network/approval-distribution/src/lib.rs | 16 ++-- .../approval-distribution/src/metrics.rs | 2 +- .../approval-distribution/src/tests.rs | 32 ++++---- .../src/requester/fetch_task/mod.rs | 4 +- .../network/availability-recovery/src/lib.rs | 2 +- .../availability-recovery/src/metrics.rs | 4 +- .../bitfield-distribution/src/metrics.rs | 4 +- .../bitfield-distribution/src/tests.rs | 2 +- .../dispute-distribution/src/sender/mod.rs | 10 +-- .../dispute-distribution/src/tests/mock.rs | 2 +- .../node/network/gossip-support/src/tests.rs | 4 +- .../network/protocol/src/grid_topology.rs | 6 +- polkadot/node/network/protocol/src/lib.rs | 2 +- .../node/network/protocol/src/peer_set.rs | 2 +- .../src/request_response/incoming/mod.rs | 2 +- .../protocol/src/request_response/mod.rs | 2 +- .../protocol/src/request_response/v1.rs | 2 +- .../src/legacy_v1/responder.rs | 2 +- .../src/legacy_v1/tests.rs | 2 +- .../statement-distribution/src/v2/cluster.rs | 4 +- .../statement-distribution/src/v2/mod.rs | 6 +- .../statement-distribution/src/v2/requests.rs | 2 +- polkadot/node/overseer/src/lib.rs | 2 +- polkadot/node/primitives/src/approval.rs | 2 +- polkadot/node/primitives/src/disputes/mod.rs | 4 +- polkadot/node/primitives/src/lib.rs | 2 +- polkadot/node/service/src/overseer.rs | 2 +- .../node/service/src/parachains_db/upgrade.rs | 4 +- .../node/service/src/relay_chain_selection.rs | 4 +- .../grafana/availability-read.json | 6 +- .../src/lib/approval/message_generator.rs | 10 +-- .../subsystem-bench/src/lib/approval/mod.rs | 16 ++-- .../src/lib/approval/test_message.rs | 14 ++-- .../src/lib/availability/mod.rs | 6 +- .../subsystem-bench/src/lib/configuration.rs | 6 +- .../subsystem-bench/src/lib/mock/av_store.rs | 2 +- .../subsystem-bench/src/lib/mock/chain_api.rs | 2 +- .../src/lib/mock/network_bridge.rs | 12 +-- .../node/subsystem-bench/src/lib/network.rs | 10 +-- .../node/subsystem-bench/src/lib/utils.rs | 76 +++++++++++++++++++ polkadot/node/subsystem-types/src/messages.rs | 2 +- .../src/inclusion_emulator/mod.rs | 2 +- polkadot/node/subsystem-util/src/lib.rs | 2 +- polkadot/primitives/src/v6/mod.rs | 4 +- polkadot/primitives/src/vstaging/mod.rs | 4 +- polkadot/primitives/test-helpers/src/lib.rs | 2 +- .../implementers-guide/src/disputes-flow.md | 2 +- .../node/approval/approval-distribution.md | 4 +- .../availability/availability-recovery.md | 2 +- .../src/node/disputes/dispute-coordinator.md | 8 +- .../implementers-guide/src/node/overseer.md | 4 +- .../src/node/utility/pvf-prechecker.md | 2 +- .../implementers-guide/src/runtime/README.md | 2 +- .../implementers-guide/src/runtime/hrmp.md | 4 +- .../src/runtime/parainherent.md | 2 +- .../implementers-guide/src/types/approval.md | 4 +- .../implementers-guide/src/types/disputes.md | 2 +- .../src/types/overseer-protocol.md | 2 +- polkadot/roadmap/phase-1.toml | 2 +- polkadot/runtime/common/src/xcm_sender.rs | 2 +- .../parachains/src/assigner_coretime/tests.rs | 2 +- .../parachains/src/assigner_on_demand/mod.rs | 4 +- .../parachains/src/coretime/migration.rs | 2 +- polkadot/runtime/parachains/src/disputes.rs | 2 +- .../parachains/src/disputes/slashing.rs | 2 +- polkadot/runtime/parachains/src/hrmp.rs | 6 +- polkadot/runtime/parachains/src/hrmp/tests.rs | 2 +- polkadot/runtime/parachains/src/paras/mod.rs | 2 +- .../runtime/parachains/src/paras/tests.rs | 4 +- .../parachains/src/paras_inherent/mod.rs | 4 +- .../parachains/src/scheduler/migration.rs | 2 +- .../runtime/parachains/src/scheduler/tests.rs | 2 +- .../runtime/parachains/src/session_info.rs | 2 +- polkadot/runtime/parachains/src/ump_tests.rs | 4 +- polkadot/runtime/rococo/README.md | 2 +- .../runtime/westend/src/weights/xcm/mod.rs | 2 +- polkadot/tests/common.rs | 4 +- .../tests/running_the_node_and_interrupt.rs | 2 +- .../pallet-xcm/src/tests/assets_transfer.rs | 4 +- polkadot/xcm/src/v2/multilocation.rs | 2 +- polkadot/xcm/src/v3/multilocation.rs | 2 +- polkadot/xcm/src/v4/location.rs | 2 +- polkadot/xcm/xcm-builder/src/barriers.rs | 2 +- polkadot/xcm/xcm-builder/src/tests/origins.rs | 4 +- polkadot/xcm/xcm-builder/tests/scenarios.rs | 2 +- .../xcm-executor/integration-tests/src/lib.rs | 2 +- .../xcm-executor/src/traits/should_execute.rs | 2 +- polkadot/xcm/xcm-simulator/example/src/lib.rs | 4 +- prdoc/pr_3808.prdoc | 20 +++++ scripts/bridges_update_subtree.sh | 2 +- scripts/snowbridge_update_subtree.sh | 2 +- .../bin/node/cli/benches/block_production.rs | 4 +- substrate/bin/node/cli/src/cli.rs | 2 +- substrate/bin/node/cli/src/service.rs | 2 +- substrate/bin/node/cli/tests/fees.rs | 2 +- substrate/bin/node/testing/src/bench.rs | 6 +- .../bin/utils/chain-spec-builder/src/lib.rs | 2 +- substrate/bin/utils/subkey/README.md | 4 +- substrate/bin/utils/subkey/src/lib.rs | 10 +-- .../basic-authorship/src/basic_authorship.rs | 2 +- substrate/client/chain-spec/src/chain_spec.rs | 10 +-- substrate/client/chain-spec/src/extension.rs | 2 +- .../chain-spec/src/genesis_config_builder.rs | 2 +- substrate/client/chain-spec/src/lib.rs | 2 +- substrate/client/cli/src/commands/vanity.rs | 4 +- .../client/cli/src/params/network_params.rs | 2 +- substrate/client/consensus/aura/src/lib.rs | 2 +- .../client/consensus/babe/src/authorship.rs | 2 +- substrate/client/consensus/babe/src/lib.rs | 2 +- .../client/consensus/babe/src/migration.rs | 2 +- substrate/client/consensus/beefy/README.md | 2 +- .../consensus/beefy/src/communication/mod.rs | 2 +- .../incoming_requests_handler.rs | 2 +- .../client/consensus/beefy/src/keystore.rs | 8 +- .../client/consensus/beefy/src/worker.rs | 6 +- substrate/client/consensus/common/Cargo.toml | 2 +- .../consensus/common/src/import_queue.rs | 2 +- .../common/src/import_queue/basic_queue.rs | 4 +- substrate/client/consensus/epochs/src/lib.rs | 4 +- .../grandpa/src/communication/mod.rs | 6 +- .../grandpa/src/communication/periodic.rs | 2 +- .../client/consensus/grandpa/src/tests.rs | 4 +- .../consensus/grandpa/src/until_imported.rs | 2 +- .../consensus/grandpa/src/voting_rule.rs | 2 +- .../consensus/grandpa/src/warp_proof.rs | 2 +- .../manual-seal/src/consensus/babe.rs | 2 +- substrate/client/consensus/slots/src/lib.rs | 6 +- substrate/client/db/src/upgrade.rs | 2 +- substrate/client/db/src/utils.rs | 2 +- substrate/client/executor/common/src/error.rs | 2 +- .../client/executor/wasmtime/src/runtime.rs | 2 +- .../client/executor/wasmtime/src/tests.rs | 4 +- substrate/client/network/bitswap/src/lib.rs | 2 +- .../src/protocol/notifications/behaviour.rs | 2 +- .../src/protocol/notifications/handler.rs | 2 +- .../src/protocol/notifications/service/mod.rs | 6 +- .../protocol/notifications/service/tests.rs | 2 +- .../notifications/upgrade/notifications.rs | 4 +- .../client/network/src/protocol_controller.rs | 4 +- substrate/client/network/sync/src/engine.rs | 6 +- substrate/client/network/sync/src/strategy.rs | 12 +-- .../network/sync/src/strategy/chain_sync.rs | 4 +- .../sync/src/strategy/chain_sync/test.rs | 8 +- .../client/network/sync/src/strategy/state.rs | 16 ++-- .../client/network/sync/src/strategy/warp.rs | 2 +- .../network/sync/src/warp_request_handler.rs | 2 +- substrate/client/network/test/src/sync.rs | 2 +- substrate/client/offchain/src/api/http.rs | 2 +- .../rpc-servers/src/middleware/metrics.rs | 2 +- .../client/rpc-spec-v2/src/archive/tests.rs | 4 +- .../rpc-spec-v2/src/chain_head/event.rs | 4 +- .../rpc-spec-v2/src/chain_head/tests.rs | 6 +- .../tests/transaction_broadcast_tests.rs | 6 +- .../src/transaction/transaction_broadcast.rs | 4 +- substrate/client/rpc/src/statement/mod.rs | 2 +- .../service/src/chain_ops/import_blocks.rs | 2 +- substrate/client/service/src/config.rs | 2 +- substrate/client/state-db/src/lib.rs | 4 +- substrate/client/state-db/src/noncanonical.rs | 10 +-- substrate/client/telemetry/src/lib.rs | 2 +- substrate/client/transaction-pool/README.md | 2 +- .../client/transaction-pool/tests/pool.rs | 2 +- substrate/client/utils/src/notification.rs | 2 +- substrate/frame/alliance/README.md | 2 +- substrate/frame/alliance/src/lib.rs | 6 +- substrate/frame/alliance/src/tests.rs | 2 +- substrate/frame/asset-conversion/src/lib.rs | 2 +- substrate/frame/asset-rate/src/lib.rs | 2 +- substrate/frame/assets/src/lib.rs | 2 +- substrate/frame/assets/src/tests.rs | 2 +- substrate/frame/babe/src/benchmarking.rs | 2 +- substrate/frame/bags-list/src/list/tests.rs | 2 +- substrate/frame/balances/src/lib.rs | 6 +- .../balances/src/tests/currency_tests.rs | 4 +- .../balances/src/tests/reentrancy_tests.rs | 4 +- substrate/frame/benchmarking/src/analysis.rs | 2 +- substrate/frame/benchmarking/src/lib.rs | 2 +- substrate/frame/benchmarking/src/v1.rs | 6 +- substrate/frame/broker/src/lib.rs | 2 +- substrate/frame/broker/src/types.rs | 4 +- substrate/frame/collective/README.md | 2 +- substrate/frame/collective/src/lib.rs | 2 +- substrate/frame/collective/src/tests.rs | 2 +- substrate/frame/contracts/README.md | 2 +- .../fixtures/contracts/multi_store.rs | 2 +- .../frame/contracts/src/benchmarking/code.rs | 2 +- .../frame/contracts/src/benchmarking/mod.rs | 8 +- substrate/frame/contracts/src/exec.rs | 4 +- substrate/frame/contracts/src/gas.rs | 2 +- substrate/frame/contracts/src/lib.rs | 2 +- .../frame/contracts/src/migration/v09.rs | 2 +- substrate/frame/contracts/src/schedule.rs | 2 +- substrate/frame/contracts/src/tests.rs | 18 ++--- substrate/frame/contracts/src/wasm/mod.rs | 2 +- substrate/frame/contracts/src/wasm/runtime.rs | 6 +- .../frame/conviction-voting/src/tests.rs | 2 +- .../core-fellowship/src/tests/integration.rs | 2 +- substrate/frame/democracy/src/lib.rs | 2 +- .../unlock_and_unreserve_all_funds.rs | 42 +++++----- substrate/frame/democracy/src/tests.rs | 2 +- .../frame/democracy/src/tests/cancellation.rs | 2 +- .../src/helpers.rs | 4 +- .../election-provider-multi-phase/src/lib.rs | 4 +- .../src/unsigned.rs | 4 +- .../test-staking-e2e/src/lib.rs | 10 +-- .../test-staking-e2e/src/mock.rs | 4 +- .../election-provider-support/src/bounds.rs | 4 +- .../frame/examples/offchain-worker/src/lib.rs | 2 +- .../single-block-migrations/src/lib.rs | 4 +- substrate/frame/examples/split/Cargo.toml | 2 +- substrate/frame/examples/tasks/Cargo.toml | 2 +- substrate/frame/fast-unstake/src/tests.rs | 2 +- substrate/frame/grandpa/src/benchmarking.rs | 2 +- substrate/frame/grandpa/src/tests.rs | 2 +- substrate/frame/identity/src/benchmarking.rs | 4 +- substrate/frame/identity/src/lib.rs | 2 +- substrate/frame/im-online/src/tests.rs | 2 +- .../frame/merkle-mountain-range/src/lib.rs | 2 +- substrate/frame/message-queue/src/lib.rs | 2 +- substrate/frame/message-queue/src/tests.rs | 2 +- .../frame/migrations/src/mock_helpers.rs | 2 +- substrate/frame/nis/README.md | 2 +- substrate/frame/nis/src/lib.rs | 4 +- substrate/frame/nis/src/tests.rs | 2 +- substrate/frame/node-authorization/src/lib.rs | 10 +-- substrate/frame/nomination-pools/src/lib.rs | 8 +- .../frame/nomination-pools/src/migration.rs | 2 +- substrate/frame/offences/src/tests.rs | 2 +- substrate/frame/paged-list/src/paged_list.rs | 2 +- substrate/frame/parameters/src/lib.rs | 34 ++++----- substrate/frame/parameters/src/tests/unit.rs | 2 +- substrate/frame/proxy/src/lib.rs | 2 +- substrate/frame/root-testing/src/lib.rs | 2 +- .../frame/salary/src/tests/integration.rs | 2 +- substrate/frame/salary/src/tests/unit.rs | 8 +- substrate/frame/sassafras/src/benchmarking.rs | 2 +- substrate/frame/sassafras/src/lib.rs | 8 +- substrate/frame/scheduler/README.md | 2 +- substrate/frame/scheduler/src/benchmarking.rs | 4 +- substrate/frame/scheduler/src/lib.rs | 2 +- substrate/frame/scheduler/src/tests.rs | 4 +- substrate/frame/society/src/lib.rs | 8 +- substrate/frame/society/src/migrations.rs | 8 +- substrate/frame/society/src/tests.rs | 2 +- substrate/frame/staking/src/ledger.rs | 2 +- substrate/frame/staking/src/migrations.rs | 2 +- substrate/frame/staking/src/pallet/impls.rs | 4 +- substrate/frame/staking/src/pallet/mod.rs | 8 +- substrate/frame/staking/src/tests.rs | 10 +-- substrate/frame/sudo/src/lib.rs | 2 +- .../frame/support/procedural/src/benchmark.rs | 4 +- .../procedural/src/construct_runtime/mod.rs | 6 +- .../procedural/src/construct_runtime/parse.rs | 10 +-- .../support/procedural/src/derive_impl.rs | 2 +- .../support/procedural/src/dynamic_params.rs | 18 ++--- substrate/frame/support/procedural/src/lib.rs | 6 +- .../procedural/src/pallet/parse/mod.rs | 2 +- .../frame/support/src/dispatch_context.rs | 4 +- substrate/frame/support/src/instances.rs | 32 ++++---- substrate/frame/support/src/lib.rs | 12 +-- .../frame/support/src/storage/migration.rs | 8 +- substrate/frame/support/src/storage/mod.rs | 21 ++--- .../frame/support/src/storage/stream_iter.rs | 2 +- .../support/src/storage/types/counted_map.rs | 10 +-- .../support/src/storage/types/counted_nmap.rs | 2 +- .../support/src/storage/types/double_map.rs | 5 +- .../frame/support/src/storage/types/map.rs | 5 +- .../frame/support/src/storage/types/mod.rs | 2 +- .../frame/support/src/storage/types/nmap.rs | 2 +- .../frame/support/src/storage/types/value.rs | 5 +- .../frame/support/src/traits/dispatch.rs | 2 +- .../support/src/traits/dynamic_params.rs | 40 +++++----- substrate/frame/support/src/traits/hooks.rs | 2 +- substrate/frame/support/src/traits/misc.rs | 2 +- .../conformance_tests/regular/unbalanced.rs | 2 +- .../traits/tokens/imbalance/split_two_ways.rs | 2 +- .../frame/support/src/traits/tokens/misc.rs | 2 +- .../derive_impl_ui/attached_to_non_impl.rs | 2 +- .../derive_impl_ui/bad_default_impl_path.rs | 4 +- .../derive_impl_ui/bad_disambiguation_path.rs | 4 +- .../missing_disambiguation_path.rs | 4 +- .../derive_impl_ui/pass/basic_overriding.rs | 12 +-- .../test/tests/pallet_outer_enums_explicit.rs | 2 +- .../test/tests/pallet_outer_enums_implicit.rs | 6 +- .../pallet_ui/pass/inherited_call_weight3.rs | 2 +- substrate/frame/system/src/limits.rs | 2 +- substrate/frame/system/src/offchain.rs | 6 +- substrate/frame/tips/src/migrations/mod.rs | 2 +- .../frame/transaction-payment/src/tests.rs | 2 +- substrate/frame/transaction-storage/README.md | 2 +- .../frame/transaction-storage/src/lib.rs | 2 +- .../frame/transaction-storage/src/tests.rs | 6 +- substrate/frame/treasury/src/lib.rs | 6 +- substrate/frame/uniques/src/tests.rs | 4 +- substrate/frame/utility/README.md | 2 +- substrate/frame/vesting/src/migrations.rs | 2 +- .../arithmetic/fuzzer/src/fixed_point.rs | 2 +- .../primitives/arithmetic/src/fixed_point.rs | 2 +- .../primitives/blockchain/src/backend.rs | 2 +- substrate/primitives/blockchain/src/error.rs | 2 +- .../blockchain/src/header_metadata.rs | 4 +- .../primitives/consensus/babe/src/lib.rs | 4 +- .../primitives/consensus/beefy/src/lib.rs | 2 +- .../primitives/consensus/beefy/src/mmr.rs | 4 +- .../primitives/consensus/beefy/src/payload.rs | 2 +- .../primitives/consensus/common/src/lib.rs | 2 +- .../consensus/sassafras/src/ticket.rs | 2 +- .../primitives/consensus/sassafras/src/vrf.rs | 2 +- substrate/primitives/core/src/address_uri.rs | 2 +- substrate/primitives/core/src/bandersnatch.rs | 2 +- .../primitives/core/src/paired_crypto.rs | 2 +- .../primitives/inherents/src/client_side.rs | 2 +- substrate/primitives/io/Cargo.toml | 2 +- substrate/primitives/io/src/lib.rs | 8 +- .../maybe-compressed-blob/Cargo.toml | 2 +- substrate/primitives/metadata-ir/src/types.rs | 2 +- .../primitives/npos-elections/src/pjr.rs | 2 +- .../primitives/npos-elections/src/reduce.rs | 2 +- .../primitives/runtime-interface/src/lib.rs | 2 +- .../test-wasm-deprecated/src/lib.rs | 12 +-- .../runtime-interface/test-wasm/src/lib.rs | 22 +++--- .../runtime-interface/test/src/lib.rs | 10 +-- .../src/generic/unchecked_extrinsic.rs | 2 +- .../runtime/src/offchain/storage_lock.rs | 2 +- substrate/primitives/runtime/src/testing.rs | 8 +- substrate/primitives/runtime/src/traits.rs | 4 +- substrate/primitives/staking/src/offence.rs | 2 +- substrate/primitives/state-machine/src/ext.rs | 4 +- substrate/primitives/state-machine/src/lib.rs | 12 +-- .../src/overlayed_changes/changeset.rs | 14 ++-- .../src/overlayed_changes/mod.rs | 8 +- .../primitives/state-machine/src/testing.rs | 2 +- .../state-machine/src/trie_backend_essence.rs | 8 +- substrate/primitives/storage/src/lib.rs | 2 +- substrate/primitives/tracing/src/lib.rs | 8 +- substrate/primitives/tracing/src/types.rs | 10 +-- .../transaction-storage-proof/src/lib.rs | 2 +- substrate/primitives/trie/src/cache/mod.rs | 2 +- substrate/primitives/trie/src/lib.rs | 4 +- .../proc-macro/src/decl_runtime_version.rs | 2 +- substrate/primitives/version/src/lib.rs | 2 +- substrate/utils/fork-tree/src/lib.rs | 6 +- .../benchmarking-cli/src/pallet/command.rs | 6 +- .../utils/frame/generate-bags/src/lib.rs | 2 +- .../frame/remote-externalities/src/lib.rs | 2 +- .../rpc/state-trie-migration-rpc/src/lib.rs | 2 +- substrate/utils/substrate-bip39/README.md | 8 +- substrate/utils/substrate-bip39/src/lib.rs | 2 +- substrate/utils/wasm-builder/src/lib.rs | 2 +- .../utils/wasm-builder/src/wasm_project.rs | 14 ++-- templates/minimal/node/Cargo.toml | 2 +- templates/minimal/runtime/Cargo.toml | 2 +- 463 files changed, 1119 insertions(+), 1017 deletions(-) create mode 100644 polkadot/node/subsystem-bench/src/lib/utils.rs create mode 100644 prdoc/pr_3808.prdoc diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fdaa0c8628f..4fc5b97caae 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -13,7 +13,7 @@ # - Multiple owners are supported. # - Either handle (e.g, @github_user or @github/team) or email can be used. Keep in mind, # that handles might work better because they are more recognizable on GitHub, -# eyou can use them for mentioning unlike an email. +# you can use them for mentioning unlike an email. # - The latest matching rule, if multiple, takes precedence. # CI diff --git a/.github/scripts/common/lib.sh b/.github/scripts/common/lib.sh index 29dc269ffd2..932a6d546c3 100755 --- a/.github/scripts/common/lib.sh +++ b/.github/scripts/common/lib.sh @@ -237,7 +237,7 @@ fetch_release_artifacts() { popd > /dev/null } -# Fetch the release artifacts like binary and sigantures from S3. Assumes the ENV are set: +# Fetch the release artifacts like binary and signatures from S3. Assumes the ENV are set: # - RELEASE_ID # - GITHUB_TOKEN # - REPO in the form paritytech/polkadot diff --git a/.gitlab/pipeline/build.yml b/.gitlab/pipeline/build.yml index f8de6135572..44d66eb2f5e 100644 --- a/.gitlab/pipeline/build.yml +++ b/.gitlab/pipeline/build.yml @@ -350,7 +350,7 @@ build-runtimes-polkavm: - .run-immediately # - .collect-artifact variables: - # this variable gets overriden by "rusty-cachier environment inject", use the value as default + # this variable gets overridden by "rusty-cachier environment inject", use the value as default CARGO_TARGET_DIR: "$CI_PROJECT_DIR/target" before_script: - mkdir -p ./artifacts/subkey diff --git a/.gitlab/rust-features.sh b/.gitlab/rust-features.sh index c0ac192a6ec..c3ec61ab871 100755 --- a/.gitlab/rust-features.sh +++ b/.gitlab/rust-features.sh @@ -15,7 +15,7 @@ # # The steps of this script: # 1. Check that all required dependencies are installed. -# 2. Check that all rules are fullfilled for the whole workspace. If not: +# 2. Check that all rules are fulfilled for the whole workspace. If not: # 4. Check all crates to find the offending ones. # 5. Print all offending crates and exit with code 1. # diff --git a/bridges/bin/runtime-common/src/messages_api.rs b/bridges/bin/runtime-common/src/messages_api.rs index ccf1c754041..7fbdeb36612 100644 --- a/bridges/bin/runtime-common/src/messages_api.rs +++ b/bridges/bin/runtime-common/src/messages_api.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Helpers for implementing various message-related runtime API mthods. +//! Helpers for implementing various message-related runtime API methods. use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, diff --git a/bridges/bin/runtime-common/src/messages_xcm_extension.rs b/bridges/bin/runtime-common/src/messages_xcm_extension.rs index e3da6155f08..46ed4da0d85 100644 --- a/bridges/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bridges/bin/runtime-common/src/messages_xcm_extension.rs @@ -248,7 +248,7 @@ impl LocalXcmQueueManager { sender_and_lane: &SenderAndLane, enqueued_messages: MessageNonce, ) { - // skip if we dont want to handle congestion + // skip if we don't want to handle congestion if !H::supports_congestion_detection() { return } diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs index deee4524e85..8c4cb2233e1 100644 --- a/bridges/bin/runtime-common/src/mock.rs +++ b/bridges/bin/runtime-common/src/mock.rs @@ -379,7 +379,7 @@ impl Chain for BridgedUnderlyingChain { impl ChainWithGrandpa for BridgedUnderlyingChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8; const MAX_MANDATORY_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE: u32 = 64; } diff --git a/bridges/bin/runtime-common/src/priority_calculator.rs b/bridges/bin/runtime-common/src/priority_calculator.rs index c2737128e34..5035553f508 100644 --- a/bridges/bin/runtime-common/src/priority_calculator.rs +++ b/bridges/bin/runtime-common/src/priority_calculator.rs @@ -163,7 +163,7 @@ mod integrity_tests { { // just an estimation of extra transaction bytes that are added to every transaction // (including signature, signed extensions extra and etc + in our case it includes - // all call arguments extept the proof itself) + // all call arguments except the proof itself) let base_tx_size = 512; // let's say we are relaying similar small messages and for every message we add more trie // nodes to the proof (x0.5 because we expect some nodes to be reused) diff --git a/bridges/bin/runtime-common/src/refund_relayer_extension.rs b/bridges/bin/runtime-common/src/refund_relayer_extension.rs index 8e901d72821..455392a0a27 100644 --- a/bridges/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bridges/bin/runtime-common/src/refund_relayer_extension.rs @@ -1538,7 +1538,7 @@ mod tests { } #[test] - fn validate_boosts_priority_of_message_delivery_transactons() { + fn validate_boosts_priority_of_message_delivery_transactions() { run_test(|| { initialize_environment(100, 100, 100); @@ -1568,7 +1568,7 @@ mod tests { } #[test] - fn validate_does_not_boost_priority_of_message_delivery_transactons_with_too_many_messages() { + fn validate_does_not_boost_priority_of_message_delivery_transactions_with_too_many_messages() { run_test(|| { initialize_environment(100, 100, 100); diff --git a/bridges/chains/chain-kusama/src/lib.rs b/bridges/chains/chain-kusama/src/lib.rs index e3b4d0520f6..a81004afe81 100644 --- a/bridges/chains/chain-kusama/src/lib.rs +++ b/bridges/chains/chain-kusama/src/lib.rs @@ -53,8 +53,8 @@ impl Chain for Kusama { impl ChainWithGrandpa for Kusama { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_KUSAMA_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/bridges/chains/chain-polkadot-bulletin/src/lib.rs b/bridges/chains/chain-polkadot-bulletin/src/lib.rs index f2eebf93124..f3d300567f2 100644 --- a/bridges/chains/chain-polkadot-bulletin/src/lib.rs +++ b/bridges/chains/chain-polkadot-bulletin/src/lib.rs @@ -43,7 +43,7 @@ use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidi pub use bp_polkadot_core::{ AccountAddress, AccountId, Balance, Block, BlockNumber, Hash, Hasher, Header, Nonce, Signature, SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE, EXTRA_STORAGE_PROOF_SIZE, - MAX_MANDATORY_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, + MAX_MANDATORY_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY, }; /// Maximal number of GRANDPA authorities at Polkadot Bulletin chain. @@ -62,7 +62,7 @@ const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(90); // Re following constants - we are using the same values at Cumulus parachains. They are limited // by the maximal transaction weight/size. Since block limits at Bulletin Chain are larger than -// at the Cumulus Bridgeg Hubs, we could reuse the same values. +// at the Cumulus Bridge Hubs, we could reuse the same values. /// Maximal number of unrewarded relayer entries at inbound lane for Cumulus-based parachains. pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; @@ -207,8 +207,8 @@ impl Chain for PolkadotBulletin { impl ChainWithGrandpa for PolkadotBulletin { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_POLKADOT_BULLETIN_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/bridges/chains/chain-polkadot/src/lib.rs b/bridges/chains/chain-polkadot/src/lib.rs index fc5e10308a8..00d35783a9b 100644 --- a/bridges/chains/chain-polkadot/src/lib.rs +++ b/bridges/chains/chain-polkadot/src/lib.rs @@ -55,8 +55,8 @@ impl Chain for Polkadot { impl ChainWithGrandpa for Polkadot { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_POLKADOT_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/bridges/chains/chain-rococo/src/lib.rs b/bridges/chains/chain-rococo/src/lib.rs index f1b256f0f09..2385dd2cbb2 100644 --- a/bridges/chains/chain-rococo/src/lib.rs +++ b/bridges/chains/chain-rococo/src/lib.rs @@ -53,8 +53,8 @@ impl Chain for Rococo { impl ChainWithGrandpa for Rococo { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_ROCOCO_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/bridges/chains/chain-westend/src/lib.rs b/bridges/chains/chain-westend/src/lib.rs index f03fd2160a7..b344b7f4bf9 100644 --- a/bridges/chains/chain-westend/src/lib.rs +++ b/bridges/chains/chain-westend/src/lib.rs @@ -53,8 +53,8 @@ impl Chain for Westend { impl ChainWithGrandpa for Westend { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_WESTEND_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/bridges/modules/grandpa/README.md b/bridges/modules/grandpa/README.md index 992bd2cc472..4a3099b8afc 100644 --- a/bridges/modules/grandpa/README.md +++ b/bridges/modules/grandpa/README.md @@ -10,7 +10,7 @@ It is used by the parachains light client (bridge parachains pallet) and by mess ## A Brief Introduction into GRANDPA Finality You can find detailed information on GRANDPA, by exploring its [repository](https://github.com/paritytech/finality-grandpa). -Here is the minimal reqiuired GRANDPA information to understand how pallet works. +Here is the minimal required GRANDPA information to understand how pallet works. Any Substrate chain may use different block authorship algorithms (like BABE or Aura) to determine block producers and generate blocks. This has nothing common with finality, though - the task of block authorship is to coordinate diff --git a/bridges/modules/grandpa/src/call_ext.rs b/bridges/modules/grandpa/src/call_ext.rs index e3c778b480b..4a7ebb3cc8d 100644 --- a/bridges/modules/grandpa/src/call_ext.rs +++ b/bridges/modules/grandpa/src/call_ext.rs @@ -205,7 +205,7 @@ pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( // as an extra weight. let votes_ancestries_len = justification.votes_ancestries.len().saturated_into(); let extra_weight = - if votes_ancestries_len > T::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY { + if votes_ancestries_len > T::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY { T::WeightInfo::submit_finality_proof(precommits_len, votes_ancestries_len) } else { Weight::zero() @@ -396,11 +396,11 @@ mod tests { let finality_target = test_header(1); let mut justification_params = JustificationGeneratorParams { header: finality_target.clone(), - ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, + ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY, ..Default::default() }; - // when there are `REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY` headers => no refund + // when there are `REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY` headers => no refund let justification = make_justification_for_header(justification_params.clone()); let call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof_ex { finality_target: Box::new(finality_target.clone()), @@ -409,7 +409,7 @@ mod tests { }); assert_eq!(call.submit_finality_proof_info().unwrap().extra_weight, Weight::zero()); - // when there are `REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY + 1` headers => full refund + // when there are `REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY + 1` headers => full refund justification_params.ancestors += 1; let justification = make_justification_for_header(justification_params); let call_weight = ::WeightInfo::submit_finality_proof( diff --git a/bridges/modules/grandpa/src/lib.rs b/bridges/modules/grandpa/src/lib.rs index ce2c47da954..9e095651ef8 100644 --- a/bridges/modules/grandpa/src/lib.rs +++ b/bridges/modules/grandpa/src/lib.rs @@ -935,7 +935,7 @@ mod tests { } #[test] - fn succesfully_imports_header_with_valid_finality() { + fn successfully_imports_header_with_valid_finality() { run_test(|| { initialize_substrate_bridge(); @@ -1192,7 +1192,7 @@ mod tests { header.digest = change_log(0); let justification = make_justification_for_header(JustificationGeneratorParams { header: header.clone(), - ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY + 1, + ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY + 1, ..Default::default() }); diff --git a/bridges/modules/grandpa/src/mock.rs b/bridges/modules/grandpa/src/mock.rs index 4318d663a2e..e689e520c92 100644 --- a/bridges/modules/grandpa/src/mock.rs +++ b/bridges/modules/grandpa/src/mock.rs @@ -87,7 +87,7 @@ impl Chain for TestBridgedChain { impl ChainWithGrandpa for TestBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = MAX_BRIDGED_AUTHORITIES; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8; const MAX_MANDATORY_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE: u32 = 64; } diff --git a/bridges/modules/messages/src/inbound_lane.rs b/bridges/modules/messages/src/inbound_lane.rs index 966ec939e70..da1698e6e03 100644 --- a/bridges/modules/messages/src/inbound_lane.rs +++ b/bridges/modules/messages/src/inbound_lane.rs @@ -21,7 +21,7 @@ use crate::Config; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, - ReceivalResult, UnrewardedRelayer, + ReceptionResult, UnrewardedRelayer, }; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; use frame_support::traits::Get; @@ -170,21 +170,21 @@ impl InboundLane { relayer_at_bridged_chain: &S::Relayer, nonce: MessageNonce, message_data: DispatchMessageData, - ) -> ReceivalResult { + ) -> ReceptionResult { let mut data = self.storage.get_or_init_data(); if Some(nonce) != data.last_delivered_nonce().checked_add(1) { - return ReceivalResult::InvalidNonce + return ReceptionResult::InvalidNonce } // if there are more unrewarded relayer entries than we may accept, reject this message if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() { - return ReceivalResult::TooManyUnrewardedRelayers + return ReceptionResult::TooManyUnrewardedRelayers } // if there are more unconfirmed messages than we may accept, reject this message let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce); if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() { - return ReceivalResult::TooManyUnconfirmedMessages + return ReceptionResult::TooManyUnconfirmedMessages } // then, dispatch message @@ -207,7 +207,7 @@ impl InboundLane { }; self.storage.set_data(data); - ReceivalResult::Dispatched(dispatch_result) + ReceptionResult::Dispatched(dispatch_result) } } @@ -235,7 +235,7 @@ mod tests { nonce, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); } @@ -362,7 +362,7 @@ mod tests { 10, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::InvalidNonce + ReceptionResult::InvalidNonce ); assert_eq!(lane.storage.get_or_init_data().last_delivered_nonce(), 0); }); @@ -381,7 +381,7 @@ mod tests { current_nonce, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); } // Fails to dispatch new message from different than latest relayer. @@ -391,7 +391,7 @@ mod tests { max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::TooManyUnrewardedRelayers, + ReceptionResult::TooManyUnrewardedRelayers, ); // Fails to dispatch new messages from latest relayer. Prevents griefing attacks. assert_eq!( @@ -400,7 +400,7 @@ mod tests { max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::TooManyUnrewardedRelayers, + ReceptionResult::TooManyUnrewardedRelayers, ); }); } @@ -417,7 +417,7 @@ mod tests { current_nonce, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); } // Fails to dispatch new message from different than latest relayer. @@ -427,7 +427,7 @@ mod tests { max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::TooManyUnconfirmedMessages, + ReceptionResult::TooManyUnconfirmedMessages, ); // Fails to dispatch new messages from latest relayer. assert_eq!( @@ -436,7 +436,7 @@ mod tests { max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::TooManyUnconfirmedMessages, + ReceptionResult::TooManyUnconfirmedMessages, ); }); } @@ -451,7 +451,7 @@ mod tests { 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); assert_eq!( lane.receive_message::( @@ -459,7 +459,7 @@ mod tests { 2, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); assert_eq!( lane.receive_message::( @@ -467,7 +467,7 @@ mod tests { 3, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); assert_eq!( lane.storage.get_or_init_data().relayers, @@ -490,7 +490,7 @@ mod tests { 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); assert_eq!( lane.receive_message::( @@ -498,7 +498,7 @@ mod tests { 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::InvalidNonce, + ReceptionResult::InvalidNonce, ); }); } @@ -524,7 +524,7 @@ mod tests { 1, inbound_message_data(payload) ), - ReceivalResult::Dispatched(dispatch_result(1)) + ReceptionResult::Dispatched(dispatch_result(1)) ); }); } diff --git a/bridges/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs index a86cb326cf0..bc00db9eba5 100644 --- a/bridges/modules/messages/src/lib.rs +++ b/bridges/modules/messages/src/lib.rs @@ -47,7 +47,7 @@ pub use weights_ext::{ use crate::{ inbound_lane::{InboundLane, InboundLaneStorage}, - outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationError}, + outbound_lane::{OutboundLane, OutboundLaneStorage, ReceptionConfirmationError}, }; use bp_messages::{ @@ -90,7 +90,7 @@ pub const LOG_TARGET: &str = "runtime::bridge-messages"; #[frame_support::pallet] pub mod pallet { use super::*; - use bp_messages::{ReceivalResult, ReceivedMessages}; + use bp_messages::{ReceivedMessages, ReceptionResult}; use bp_runtime::RangeInclusiveExt; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -376,13 +376,13 @@ pub mod pallet { // delivery transaction cost anyway. And base cost covers everything except // dispatch, so we have a balance here. let unspent_weight = match &receival_result { - ReceivalResult::Dispatched(dispatch_result) => { + ReceptionResult::Dispatched(dispatch_result) => { valid_messages += 1; dispatch_result.unspent_weight }, - ReceivalResult::InvalidNonce | - ReceivalResult::TooManyUnrewardedRelayers | - ReceivalResult::TooManyUnconfirmedMessages => message_dispatch_weight, + ReceptionResult::InvalidNonce | + ReceptionResult::TooManyUnrewardedRelayers | + ReceptionResult::TooManyUnconfirmedMessages => message_dispatch_weight, }; lane_messages_received_status.push(message.key.nonce, receival_result); @@ -455,7 +455,7 @@ pub mod pallet { last_delivered_nonce, &lane_data.relayers, ) - .map_err(Error::::ReceivalConfirmation)?; + .map_err(Error::::ReceptionConfirmation)?; if let Some(confirmed_messages) = confirmed_messages { // emit 'delivered' event @@ -563,7 +563,7 @@ pub mod pallet { /// The message someone is trying to work with (i.e. increase fee) is not yet sent. MessageIsNotYetSent, /// Error confirming messages receival. - ReceivalConfirmation(ReceivalConfirmationError), + ReceptionConfirmation(ReceptionConfirmationError), /// Error generated by the `OwnedBridgeModule` trait. BridgeModule(bp_runtime::OwnedBridgeModuleError), } @@ -923,7 +923,7 @@ mod tests { PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B, }, - outbound_lane::ReceivalConfirmationError, + outbound_lane::ReceptionConfirmationError, }; use bp_messages::{ source_chain::MessagesBridge, BridgeMessagesCall, UnrewardedRelayer, @@ -950,11 +950,11 @@ mod tests { let outbound_lane = outbound_lane::(lane_id); let message_nonce = outbound_lane.data().latest_generated_nonce + 1; - let prev_enqueud_messages = outbound_lane.data().queued_messages().saturating_len(); + let prev_enqueued_messages = outbound_lane.data().queued_messages().saturating_len(); let valid_message = Pallet::::validate_message(lane_id, ®ULAR_PAYLOAD) .expect("validate_message has failed"); let artifacts = Pallet::::send_message(valid_message); - assert_eq!(artifacts.enqueued_messages, prev_enqueud_messages + 1); + assert_eq!(artifacts.enqueued_messages, prev_enqueued_messages + 1); // check event with assigned nonce assert_eq!( @@ -1541,7 +1541,7 @@ mod tests { } #[test] - fn actual_dispatch_weight_does_not_overlow() { + fn actual_dispatch_weight_does_not_overflow() { run_test(|| { let message1 = message(1, message_payload(0, u64::MAX / 2)); let message2 = message(2, message_payload(0, u64::MAX / 2)); @@ -1775,7 +1775,7 @@ mod tests { // returns `last_confirmed_nonce`; // 3) it means that we're going to confirm delivery of messages 1..=1; // 4) so the number of declared messages (see `UnrewardedRelayersState`) is `0` and - // numer of actually confirmed messages is `1`. + // number of actually confirmed messages is `1`. assert_noop!( Pallet::::receive_messages_delivery_proof( RuntimeOrigin::signed(1), @@ -1785,8 +1785,8 @@ mod tests { ))), UnrewardedRelayersState { last_delivered_nonce: 1, ..Default::default() }, ), - Error::::ReceivalConfirmation( - ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected + Error::::ReceptionConfirmation( + ReceptionConfirmationError::TryingToConfirmMoreMessagesThanExpected ), ); }); diff --git a/bridges/modules/messages/src/outbound_lane.rs b/bridges/modules/messages/src/outbound_lane.rs index 431c2cfb7ee..acef5546d2a 100644 --- a/bridges/modules/messages/src/outbound_lane.rs +++ b/bridges/modules/messages/src/outbound_lane.rs @@ -53,7 +53,7 @@ pub type StoredMessagePayload = BoundedVec>::MaximalOu /// Result of messages receival confirmation. #[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)] -pub enum ReceivalConfirmationError { +pub enum ReceptionConfirmationError { /// Bridged chain is trying to confirm more messages than we have generated. May be a result /// of invalid bridged chain storage. FailedToConfirmFutureMessages, @@ -103,7 +103,7 @@ impl OutboundLane { max_allowed_messages: MessageNonce, latest_delivered_nonce: MessageNonce, relayers: &VecDeque>, - ) -> Result, ReceivalConfirmationError> { + ) -> Result, ReceptionConfirmationError> { let mut data = self.storage.data(); let confirmed_messages = DeliveredMessages { begin: data.latest_received_nonce.saturating_add(1), @@ -113,7 +113,7 @@ impl OutboundLane { return Ok(None) } if confirmed_messages.end > data.latest_generated_nonce { - return Err(ReceivalConfirmationError::FailedToConfirmFutureMessages) + return Err(ReceptionConfirmationError::FailedToConfirmFutureMessages) } if confirmed_messages.total_messages() > max_allowed_messages { // that the relayer has declared correct number of messages that the proof contains (it @@ -127,7 +127,7 @@ impl OutboundLane { confirmed_messages.total_messages(), max_allowed_messages, ); - return Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected) + return Err(ReceptionConfirmationError::TryingToConfirmMoreMessagesThanExpected) } ensure_unrewarded_relayers_are_correct(confirmed_messages.end, relayers)?; @@ -176,24 +176,24 @@ impl OutboundLane { fn ensure_unrewarded_relayers_are_correct( latest_received_nonce: MessageNonce, relayers: &VecDeque>, -) -> Result<(), ReceivalConfirmationError> { +) -> Result<(), ReceptionConfirmationError> { let mut expected_entry_begin = relayers.front().map(|entry| entry.messages.begin); for entry in relayers { // unrewarded relayer entry must have at least 1 unconfirmed message // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end < entry.messages.begin { - return Err(ReceivalConfirmationError::EmptyUnrewardedRelayerEntry) + return Err(ReceptionConfirmationError::EmptyUnrewardedRelayerEntry) } // every entry must confirm range of messages that follows previous entry range // (guaranteed by the `InboundLane::receive_message()`) if expected_entry_begin != Some(entry.messages.begin) { - return Err(ReceivalConfirmationError::NonConsecutiveUnrewardedRelayerEntries) + return Err(ReceptionConfirmationError::NonConsecutiveUnrewardedRelayerEntries) } expected_entry_begin = entry.messages.end.checked_add(1); // entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()` // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end > latest_received_nonce { - return Err(ReceivalConfirmationError::FailedToConfirmFutureMessages) + return Err(ReceptionConfirmationError::FailedToConfirmFutureMessages) } } @@ -228,7 +228,7 @@ mod tests { fn assert_3_messages_confirmation_fails( latest_received_nonce: MessageNonce, relayers: &VecDeque>, - ) -> Result, ReceivalConfirmationError> { + ) -> Result, ReceptionConfirmationError> { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); @@ -299,7 +299,7 @@ mod tests { fn confirm_delivery_rejects_nonce_larger_than_last_generated() { assert_eq!( assert_3_messages_confirmation_fails(10, &unrewarded_relayers(1..=10),), - Err(ReceivalConfirmationError::FailedToConfirmFutureMessages), + Err(ReceptionConfirmationError::FailedToConfirmFutureMessages), ); } @@ -314,7 +314,7 @@ mod tests { .chain(unrewarded_relayers(3..=3).into_iter()) .collect(), ), - Err(ReceivalConfirmationError::FailedToConfirmFutureMessages), + Err(ReceptionConfirmationError::FailedToConfirmFutureMessages), ); } @@ -330,7 +330,7 @@ mod tests { .chain(unrewarded_relayers(2..=3).into_iter()) .collect(), ), - Err(ReceivalConfirmationError::EmptyUnrewardedRelayerEntry), + Err(ReceptionConfirmationError::EmptyUnrewardedRelayerEntry), ); } @@ -345,7 +345,7 @@ mod tests { .chain(unrewarded_relayers(2..=2).into_iter()) .collect(), ), - Err(ReceivalConfirmationError::NonConsecutiveUnrewardedRelayerEntries), + Err(ReceptionConfirmationError::NonConsecutiveUnrewardedRelayerEntries), ); } @@ -409,11 +409,11 @@ mod tests { lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!( lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)), - Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected), + Err(ReceptionConfirmationError::TryingToConfirmMoreMessagesThanExpected), ); assert_eq!( lane.confirm_delivery(2, 3, &unrewarded_relayers(1..=3)), - Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected), + Err(ReceptionConfirmationError::TryingToConfirmMoreMessagesThanExpected), ); assert_eq!( lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), diff --git a/bridges/modules/parachains/src/mock.rs b/bridges/modules/parachains/src/mock.rs index 3af3fd3e763..d9cbabf850e 100644 --- a/bridges/modules/parachains/src/mock.rs +++ b/bridges/modules/parachains/src/mock.rs @@ -261,7 +261,7 @@ impl Chain for TestBridgedChain { impl ChainWithGrandpa for TestBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8; const MAX_MANDATORY_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE: u32 = 64; } @@ -294,7 +294,7 @@ impl Chain for OtherBridgedChain { impl ChainWithGrandpa for OtherBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8; const MAX_MANDATORY_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE: u32 = 64; } diff --git a/bridges/modules/xcm-bridge-hub-router/src/lib.rs b/bridges/modules/xcm-bridge-hub-router/src/lib.rs index f219be78f9e..5d0be41b1b5 100644 --- a/bridges/modules/xcm-bridge-hub-router/src/lib.rs +++ b/bridges/modules/xcm-bridge-hub-router/src/lib.rs @@ -427,7 +427,7 @@ mod tests { run_test(|| { Bridge::::put(uncongested_bridge(FixedU128::from_rational(125, 100))); - // it shold eventually decreased to one + // it should eventually decreased to one while XcmBridgeHubRouter::bridge().delivery_fee_factor > MINIMAL_DELIVERY_FEE_FACTOR { XcmBridgeHubRouter::on_initialize(One::one()); } diff --git a/bridges/modules/xcm-bridge-hub/Cargo.toml b/bridges/modules/xcm-bridge-hub/Cargo.toml index d910319d9bf..68ac32281f3 100644 --- a/bridges/modules/xcm-bridge-hub/Cargo.toml +++ b/bridges/modules/xcm-bridge-hub/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-xcm-bridge-hub" -description = "Module that adds dynamic bridges/lanes support to XCM infrastucture at the bridge hub." +description = "Module that adds dynamic bridges/lanes support to XCM infrastructure at the bridge hub." version = "0.2.0" authors.workspace = true edition.workspace = true diff --git a/bridges/primitives/header-chain/src/justification/mod.rs b/bridges/primitives/header-chain/src/justification/mod.rs index b32d8bdb5f1..d7c2cbf429e 100644 --- a/bridges/primitives/header-chain/src/justification/mod.rs +++ b/bridges/primitives/header-chain/src/justification/mod.rs @@ -83,7 +83,7 @@ impl GrandpaJustification { .saturating_add(HashOf::::max_encoded_len().saturated_into()); let max_expected_votes_ancestries_size = - C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY.saturating_mul(C::AVERAGE_HEADER_SIZE); + C::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY.saturating_mul(C::AVERAGE_HEADER_SIZE); // justification is round number (u64=8b), a signed GRANDPA commit and the // `votes_ancestries` vector diff --git a/bridges/primitives/header-chain/src/justification/verification/mod.rs b/bridges/primitives/header-chain/src/justification/verification/mod.rs index c71149bf9c2..9df3511e103 100644 --- a/bridges/primitives/header-chain/src/justification/verification/mod.rs +++ b/bridges/primitives/header-chain/src/justification/verification/mod.rs @@ -318,7 +318,7 @@ trait JustificationVerifier { } // check that the cumulative weight of validators that voted for the justification target - // (or one of its descendents) is larger than the required threshold. + // (or one of its descendants) is larger than the required threshold. if cumulative_weight < threshold { return Err(Error::TooLowCumulativeWeight) } diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs index 84a6a881a83..98fb9ff83d8 100644 --- a/bridges/primitives/header-chain/src/lib.rs +++ b/bridges/primitives/header-chain/src/lib.rs @@ -283,7 +283,7 @@ pub trait ChainWithGrandpa: Chain { /// ancestry and the pallet will accept such justification. The limit is only used to compute /// maximal refund amount and submitting justifications which exceed the limit, may be costly /// to submitter. - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32; /// Maximal size of the mandatory chain header. Mandatory header is the header that enacts new /// GRANDPA authorities set (so it has large digest inside). @@ -317,8 +317,8 @@ where const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ::WITH_CHAIN_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = ::MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - ::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + ::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = ::MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = ::AVERAGE_HEADER_SIZE; @@ -373,7 +373,7 @@ mod tests { impl ChainWithGrandpa for TestChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "Test"; const MAX_AUTHORITIES_COUNT: u32 = 128; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 2; const MAX_MANDATORY_HEADER_SIZE: u32 = 100_000; const AVERAGE_HEADER_SIZE: u32 = 1_024; } diff --git a/bridges/primitives/messages/src/lib.rs b/bridges/primitives/messages/src/lib.rs index 51b3f25f715..c3f79b3ee38 100644 --- a/bridges/primitives/messages/src/lib.rs +++ b/bridges/primitives/messages/src/lib.rs @@ -289,27 +289,27 @@ pub struct ReceivedMessages { /// Id of the lane which is receiving messages. pub lane: LaneId, /// Result of messages which we tried to dispatch - pub receive_results: Vec<(MessageNonce, ReceivalResult)>, + pub receive_results: Vec<(MessageNonce, ReceptionResult)>, } impl ReceivedMessages { /// Creates new `ReceivedMessages` structure from given results. pub fn new( lane: LaneId, - receive_results: Vec<(MessageNonce, ReceivalResult)>, + receive_results: Vec<(MessageNonce, ReceptionResult)>, ) -> Self { ReceivedMessages { lane, receive_results } } /// Push `result` of the `message` delivery onto `receive_results` vector. - pub fn push(&mut self, message: MessageNonce, result: ReceivalResult) { + pub fn push(&mut self, message: MessageNonce, result: ReceptionResult) { self.receive_results.push((message, result)); } } /// Result of single message receival. #[derive(RuntimeDebug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)] -pub enum ReceivalResult { +pub enum ReceptionResult { /// Message has been received and dispatched. Note that we don't care whether dispatch has /// been successful or not - in both case message falls into this category. /// diff --git a/bridges/primitives/polkadot-core/src/lib.rs b/bridges/primitives/polkadot-core/src/lib.rs index df2836495bb..e83be59b238 100644 --- a/bridges/primitives/polkadot-core/src/lib.rs +++ b/bridges/primitives/polkadot-core/src/lib.rs @@ -71,7 +71,7 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 1_256; /// justifications with any additional headers in votes ancestry, so reasonable headers may /// be set to zero. But we assume that there may be small GRANDPA lags, so we're leaving some /// reserve here. -pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; +pub const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 2; /// Average header size in `votes_ancestries` field of justification on Polkadot-like /// chains. diff --git a/bridges/primitives/runtime/src/chain.rs b/bridges/primitives/runtime/src/chain.rs index 9ba21a1cddf..4ec5a001a99 100644 --- a/bridges/primitives/runtime/src/chain.rs +++ b/bridges/primitives/runtime/src/chain.rs @@ -104,7 +104,7 @@ pub trait Chain: Send + Sync + 'static { const ID: ChainId; /// A type that fulfills the abstract idea of what a Substrate block number is. - // Constraits come from the associated Number type of `sp_runtime::traits::Header` + // Constraints come from the associated Number type of `sp_runtime::traits::Header` // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Number // @@ -125,7 +125,7 @@ pub trait Chain: Send + Sync + 'static { + MaxEncodedLen; /// A type that fulfills the abstract idea of what a Substrate hash is. - // Constraits come from the associated Hash type of `sp_runtime::traits::Header` + // Constraints come from the associated Hash type of `sp_runtime::traits::Header` // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Hash type Hash: Parameter @@ -143,7 +143,7 @@ pub trait Chain: Send + Sync + 'static { /// A type that fulfills the abstract idea of what a Substrate hasher (a type /// that produces hashes) is. - // Constraits come from the associated Hashing type of `sp_runtime::traits::Header` + // Constraints come from the associated Hashing type of `sp_runtime::traits::Header` // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Hashing type Hasher: HashT; diff --git a/bridges/primitives/runtime/src/lib.rs b/bridges/primitives/runtime/src/lib.rs index 850318923dc..c9c5c941291 100644 --- a/bridges/primitives/runtime/src/lib.rs +++ b/bridges/primitives/runtime/src/lib.rs @@ -56,7 +56,7 @@ mod chain; mod storage_proof; mod storage_types; -// Re-export macro to aviod include paste dependency everywhere +// Re-export macro to avoid include paste dependency everywhere pub use sp_runtime::paste; /// Use this when something must be shared among all instances. @@ -461,7 +461,7 @@ macro_rules! generate_static_str_provider { }; } -/// Error message that is only dispayable in `std` environment. +/// Error message that is only displayable in `std` environment. #[derive(Encode, Decode, Clone, Eq, PartialEq, PalletError, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct StrippableError { diff --git a/bridges/primitives/test-utils/src/lib.rs b/bridges/primitives/test-utils/src/lib.rs index 1d80890779b..f4fe4a242e7 100644 --- a/bridges/primitives/test-utils/src/lib.rs +++ b/bridges/primitives/test-utils/src/lib.rs @@ -88,7 +88,7 @@ pub fn make_default_justification(header: &H) -> GrandpaJustificatio /// Generate justifications in a way where we are able to tune the number of pre-commits /// and vote ancestries which are included in the justification. /// -/// This is useful for benchmarkings where we want to generate valid justifications with +/// This is useful for benchmarks where we want to generate valid justifications with /// a specific number of pre-commits (tuned with the number of "authorities") and/or a specific /// number of vote ancestries (tuned with the "votes" parameter). /// diff --git a/bridges/scripts/verify-pallets-build.sh b/bridges/scripts/verify-pallets-build.sh index 4eefaa8efa0..9c57a2a3c47 100755 --- a/bridges/scripts/verify-pallets-build.sh +++ b/bridges/scripts/verify-pallets-build.sh @@ -134,7 +134,7 @@ cargo check -p bridge-runtime-common cargo check -p bridge-runtime-common --features runtime-benchmarks cargo check -p bridge-runtime-common --features integrity-test -# we're removing lock file after all chechs are done. Otherwise we may use different +# we're removing lock file after all checks are done. Otherwise we may use different # Substrate/Polkadot/Cumulus commits and our checks will fail rm -f $BRIDGES_FOLDER/Cargo.lock diff --git a/bridges/snowbridge/pallets/ethereum-client/src/lib.rs b/bridges/snowbridge/pallets/ethereum-client/src/lib.rs index fc2ab2fbb58..f57f5199020 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/lib.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/lib.rs @@ -10,7 +10,7 @@ //! //! * [`Call::force_checkpoint`]: Set the initial trusted consensus checkpoint. //! * [`Call::set_operating_mode`]: Set the operating mode of the pallet. Can be used to disable -//! processing of conensus updates. +//! processing of consensus updates. //! //! ## Consensus Updates //! diff --git a/bridges/snowbridge/pallets/ethereum-client/src/tests.rs b/bridges/snowbridge/pallets/ethereum-client/src/tests.rs index 4a7b7b45886..20a184490fd 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/tests.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/tests.rs @@ -249,7 +249,7 @@ pub fn execution_header_pruning() { stored_hashes.push(hash); } - // We should have only stored upto `execution_header_prune_threshold` + // We should have only stored up to `execution_header_prune_threshold` assert_eq!( ExecutionHeaders::::iter().count() as u32, execution_header_prune_threshold diff --git a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/register_token_with_insufficient_fee.rs b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/register_token_with_insufficient_fee.rs index 82ff2283101..dfda0b2b427 100644 --- a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/register_token_with_insufficient_fee.rs +++ b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/register_token_with_insufficient_fee.rs @@ -9,7 +9,7 @@ use snowbridge_beacon_primitives::CompactExecutionHeader; use snowbridge_core::inbound::{Log, Message, Proof}; use sp_std::vec; -pub fn make_register_token_with_infufficient_fee_message() -> InboundQueueFixture { +pub fn make_register_token_with_insufficient_fee_message() -> InboundQueueFixture { InboundQueueFixture { execution_header: CompactExecutionHeader{ parent_hash: hex!("998e81dc6df788a920b67e058fbde0dc3f4ec6f11f3f7cd8c3148e6d99584885").into(), diff --git a/bridges/testing/environments/rococo-westend/rococo.zndsl b/bridges/testing/environments/rococo-westend/rococo.zndsl index 5b49c7c632f..a75286445a2 100644 --- a/bridges/testing/environments/rococo-westend/rococo.zndsl +++ b/bridges/testing/environments/rococo-westend/rococo.zndsl @@ -1,7 +1,7 @@ -Description: Check if the with-Westend GRANPDA pallet was initialized at Rococo BH +Description: Check if the with-Westend GRANDPA pallet was initialized at Rococo BH Network: ./bridge_hub_rococo_local_network.toml Creds: config -# relay is already started - let's wait until with-Westend GRANPDA pallet is initialized at Rococo +# relay is already started - let's wait until with-Westend GRANDPA pallet is initialized at Rococo bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Westend,0" within 400 seconds diff --git a/bridges/testing/environments/rococo-westend/westend.zndsl b/bridges/testing/environments/rococo-westend/westend.zndsl index 07968838852..21d4ebf3b05 100644 --- a/bridges/testing/environments/rococo-westend/westend.zndsl +++ b/bridges/testing/environments/rococo-westend/westend.zndsl @@ -1,6 +1,6 @@ -Description: Check if the with-Rococo GRANPDA pallet was initialized at Westend BH +Description: Check if the with-Rococo GRANDPA pallet was initialized at Westend BH Network: ./bridge_hub_westend_local_network.toml Creds: config -# relay is already started - let's wait until with-Rococo GRANPDA pallet is initialized at Westend +# relay is already started - let's wait until with-Rococo GRANDPA pallet is initialized at Westend bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds diff --git a/bridges/testing/framework/utils/generate_hex_encoded_call/index.js b/bridges/testing/framework/utils/generate_hex_encoded_call/index.js index 30f89d754ce..c8e361b25a9 100644 --- a/bridges/testing/framework/utils/generate_hex_encoded_call/index.js +++ b/bridges/testing/framework/utils/generate_hex_encoded_call/index.js @@ -126,36 +126,36 @@ if (!process.argv[2] || !process.argv[3]) { } const type = process.argv[2]; -const rpcEnpoint = process.argv[3]; +const rpcEndpoint = process.argv[3]; const output = process.argv[4]; const inputArgs = process.argv.slice(5, process.argv.length); console.log(`Generating hex-encoded call data for:`); console.log(` type: ${type}`); -console.log(` rpcEnpoint: ${rpcEnpoint}`); +console.log(` rpcEndpoint: ${rpcEndpoint}`); console.log(` output: ${output}`); console.log(` inputArgs: ${inputArgs}`); switch (type) { case 'remark-with-event': - remarkWithEvent(rpcEnpoint, output); + remarkWithEvent(rpcEndpoint, output); break; case 'add-exporter-config': - addExporterConfig(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + addExporterConfig(rpcEndpoint, output, inputArgs[0], inputArgs[1]); break; case 'remove-exporter-config': - removeExporterConfig(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + removeExporterConfig(rpcEndpoint, output, inputArgs[0], inputArgs[1]); break; case 'add-universal-alias': - addUniversalAlias(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + addUniversalAlias(rpcEndpoint, output, inputArgs[0], inputArgs[1]); break; case 'add-reserve-location': - addReserveLocation(rpcEnpoint, output, inputArgs[0]); + addReserveLocation(rpcEndpoint, output, inputArgs[0]); break; case 'force-create-asset': - forceCreateAsset(rpcEnpoint, output, inputArgs[0], inputArgs[1], inputArgs[2], inputArgs[3]); + forceCreateAsset(rpcEndpoint, output, inputArgs[0], inputArgs[1], inputArgs[2], inputArgs[3]); break; case 'force-xcm-version': - forceXcmVersion(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + forceXcmVersion(rpcEndpoint, output, inputArgs[0], inputArgs[1]); break; case 'check': console.log(`Checking nodejs installation, if you see this everything is ready!`); diff --git a/bridges/testing/run-tests.sh b/bridges/testing/run-tests.sh index 6149d991265..fd12b57f533 100755 --- a/bridges/testing/run-tests.sh +++ b/bridges/testing/run-tests.sh @@ -30,7 +30,7 @@ done export POLKADOT_SDK_PATH=`realpath $(dirname "$0")/../..` export BRIDGE_TESTS_FOLDER=$POLKADOT_SDK_PATH/bridges/testing/tests -# set pathc to binaries +# set path to binaries if [ "$ZOMBIENET_DOCKER_PATHS" -eq 1 ]; then export POLKADOT_BINARY=/usr/local/bin/polkadot export POLKADOT_PARACHAIN_BINARY=/usr/local/bin/polkadot-parachain diff --git a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh index 7d5b8d92736..3a604b3876d 100755 --- a/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh +++ b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh @@ -24,7 +24,7 @@ echo -e "Sleeping 90s before starting relayer ...\n" sleep 90 ${BASH_SOURCE%/*}/../../environments/rococo-westend/start_relayer.sh $rococo_dir $westend_dir relayer_pid -# Sometimes the relayer syncs multiple parachain heads in the begining leading to test failures. +# Sometimes the relayer syncs multiple parachain heads in the beginning leading to test failures. # See issue: https://github.com/paritytech/parity-bridges-common/issues/2838. # TODO: Remove this sleep after the issue is fixed. echo -e "Sleeping 180s before runing the tests ...\n" diff --git a/cumulus/client/consensus/common/src/level_monitor.rs b/cumulus/client/consensus/common/src/level_monitor.rs index 270e3f57ae5..fb4b0498f68 100644 --- a/cumulus/client/consensus/common/src/level_monitor.rs +++ b/cumulus/client/consensus/common/src/level_monitor.rs @@ -158,7 +158,7 @@ where /// the limit passed to the constructor. /// /// If the given level is found to have a number of blocks greater than or equal the limit - /// then the limit is enforced by chosing one (or more) blocks to remove. + /// then the limit is enforced by choosing one (or more) blocks to remove. /// /// The removal strategy is driven by the block freshness. /// diff --git a/cumulus/client/consensus/common/src/tests.rs b/cumulus/client/consensus/common/src/tests.rs index bfb95ae388a..7816d3a4c40 100644 --- a/cumulus/client/consensus/common/src/tests.rs +++ b/cumulus/client/consensus/common/src/tests.rs @@ -832,7 +832,7 @@ fn restore_limit_monitor() { .collect::>(); // Scenario before limit application (with B11 imported as best) - // Import order (freshess): B00, B10, B11, B12, B20, B21 + // Import order (freshness): B00, B10, B11, B12, B20, B21 // // B00 --+-- B10 --+-- B20 // | +-- B21 diff --git a/cumulus/client/pov-recovery/src/lib.rs b/cumulus/client/pov-recovery/src/lib.rs index 32aba6c8993..0ca21749c3e 100644 --- a/cumulus/client/pov-recovery/src/lib.rs +++ b/cumulus/client/pov-recovery/src/lib.rs @@ -18,7 +18,7 @@ //! //! A parachain needs to build PoVs that are send to the relay chain to progress. These PoVs are //! erasure encoded and one piece of it is stored by each relay chain validator. As the relay chain -//! decides on which PoV per parachain to include and thus, to progess the parachain it can happen +//! decides on which PoV per parachain to include and thus, to progress the parachain it can happen //! that the block corresponding to this PoV isn't propagated in the parachain network. This can //! have several reasons, either a malicious collator that managed to include its own PoV and //! doesn't want to share it with the rest of the network or maybe a collator went down before it @@ -338,8 +338,8 @@ where let mut blocks_to_delete = vec![hash]; while let Some(delete) = blocks_to_delete.pop() { - if let Some(childs) = self.waiting_for_parent.remove(&delete) { - blocks_to_delete.extend(childs.iter().map(BlockT::hash)); + if let Some(children) = self.waiting_for_parent.remove(&delete) { + blocks_to_delete.extend(children.iter().map(BlockT::hash)); } } self.clear_waiting_recovery(&hash); @@ -448,7 +448,7 @@ where /// Import the given `block`. /// - /// This will also recursivley drain `waiting_for_parent` and import them as well. + /// This will also recursively drain `waiting_for_parent` and import them as well. fn import_block(&mut self, block: Block) { let mut blocks = VecDeque::new(); @@ -495,7 +495,7 @@ where tracing::debug!( target: LOG_TARGET, block_hash = ?hash, - "Cound not recover. Block was never announced as candidate" + "Could not recover. Block was never announced as candidate" ); return }, diff --git a/cumulus/client/relay-chain-rpc-interface/src/reconnecting_ws_client.rs b/cumulus/client/relay-chain-rpc-interface/src/reconnecting_ws_client.rs index b716feef1c9..48d35dd3a55 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/reconnecting_ws_client.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/reconnecting_ws_client.rs @@ -293,7 +293,8 @@ impl ReconnectingWebsocketWorker { /// listeners. If an error occurs during sending, the receiver has been closed and we remove /// the sender from the list. /// - Find a new valid RPC server to connect to in case the websocket connection is terminated. - /// If the worker is not able to connec to an RPC server from the list, the worker shuts down. + /// If the worker is not able to connect to an RPC server from the list, the worker shuts + /// down. pub async fn run(mut self) { let mut pending_requests = FuturesUnordered::new(); diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index 1c01ef33c7e..54a1def5960 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -464,7 +464,7 @@ pub mod pallet { // One complication here, is that the `host_configuration` is updated by an inherent // and those are processed after the block initialization phase. Therefore, we have to // be content only with the configuration as per the previous block. That means that - // the configuration can be either stale (or be abscent altogether in case of the + // the configuration can be either stale (or be absent altogether in case of the // beginning of the chain). // // In order to mitigate this, we do the following. At the time, we are only concerned diff --git a/cumulus/pallets/parachain-system/src/relay_state_snapshot.rs b/cumulus/pallets/parachain-system/src/relay_state_snapshot.rs index 5519d1521ea..60eccfb072f 100644 --- a/cumulus/pallets/parachain-system/src/relay_state_snapshot.rs +++ b/cumulus/pallets/parachain-system/src/relay_state_snapshot.rs @@ -90,7 +90,7 @@ pub enum Error { DmqMqcHead(ReadEntryErr), /// Relay dispatch queue cannot be extracted. RelayDispatchQueueRemainingCapacity(ReadEntryErr), - /// The hrmp inress channel index cannot be extracted. + /// The hrmp ingress channel index cannot be extracted. HrmpIngressChannelIndex(ReadEntryErr), /// The hrmp egress channel index cannot be extracted. HrmpEgressChannelIndex(ReadEntryErr), diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index e92169be16b..b4cd925d540 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -462,7 +462,7 @@ impl Pallet { // Max message size refers to aggregates, or pages. Not to individual fragments. let max_message_size = channel_info.max_message_size as usize; let format_size = format.encoded_size(); - // We check the encoded fragment length plus the format size agains the max message size + // We check the encoded fragment length plus the format size against the max message size // because the format is concatenated if a new page is needed. let size_to_check = encoded_fragment .len() diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/genesis.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/genesis.rs index 2acccb9649b..e5378b35f5e 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/genesis.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/genesis.rs @@ -20,7 +20,7 @@ use sp_core::{sr25519, storage::Storage}; // Cumulus use emulated_integration_tests_common::{ accounts, build_genesis_storage, collators, get_account_id_from_seed, - PenpalSiblingSovereigAccount, PenpalTeleportableAssetLocation, RESERVABLE_ASSET_ID, + PenpalSiblingSovereignAccount, PenpalTeleportableAssetLocation, RESERVABLE_ASSET_ID, SAFE_XCM_VERSION, }; use parachains_common::{AccountId, Balance}; @@ -76,7 +76,7 @@ pub fn genesis() -> Storage { // Penpal's teleportable asset representation ( PenpalTeleportableAssetLocation::get(), - PenpalSiblingSovereigAccount::get(), + PenpalSiblingSovereignAccount::get(), true, ED, ), diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/genesis.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/genesis.rs index e30529aff42..219d1306906 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/genesis.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/genesis.rs @@ -20,7 +20,7 @@ use sp_core::{sr25519, storage::Storage}; // Cumulus use emulated_integration_tests_common::{ accounts, build_genesis_storage, collators, get_account_id_from_seed, - PenpalSiblingSovereigAccount, PenpalTeleportableAssetLocation, RESERVABLE_ASSET_ID, + PenpalSiblingSovereignAccount, PenpalTeleportableAssetLocation, RESERVABLE_ASSET_ID, SAFE_XCM_VERSION, }; use parachains_common::{AccountId, Balance}; @@ -72,7 +72,7 @@ pub fn genesis() -> Storage { // Penpal's teleportable asset representation ( PenpalTeleportableAssetLocation::get(), - PenpalSiblingSovereigAccount::get(), + PenpalSiblingSovereignAccount::get(), true, ED, ), diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/genesis.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/genesis.rs index 48901647fd0..d81ab8143dd 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/genesis.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/genesis.rs @@ -31,8 +31,8 @@ pub const PARA_ID_B: u32 = 2001; pub const ED: Balance = penpal_runtime::EXISTENTIAL_DEPOSIT; parameter_types! { - pub PenpalSudoAcccount: AccountId = get_account_id_from_seed::("Alice"); - pub PenpalAssetOwner: AccountId = PenpalSudoAcccount::get(); + pub PenpalSudoAccount: AccountId = get_account_id_from_seed::("Alice"); + pub PenpalAssetOwner: AccountId = PenpalSudoAccount::get(); } pub fn genesis(para_id: u32) -> Storage { @@ -66,7 +66,7 @@ pub fn genesis(para_id: u32) -> Storage { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, - sudo: penpal_runtime::SudoConfig { key: Some(PenpalSudoAcccount::get()) }, + sudo: penpal_runtime::SudoConfig { key: Some(PenpalSudoAccount::get()) }, assets: penpal_runtime::AssetsConfig { assets: vec![( penpal_runtime::xcm_config::TELEPORTABLE_ASSET_ID, diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs index 651b3a52306..0b49c7a3e09 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/testing/penpal/src/lib.rs @@ -14,7 +14,7 @@ // limitations under the License. mod genesis; -pub use genesis::{genesis, PenpalAssetOwner, PenpalSudoAcccount, ED, PARA_ID_A, PARA_ID_B}; +pub use genesis::{genesis, PenpalAssetOwner, PenpalSudoAccount, ED, PARA_ID_A, PARA_ID_B}; pub use penpal_runtime::xcm_config::{ CustomizableAssetFromSystemAssetHub, LocalTeleportableToAssetHub, XcmConfig, }; diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs index 5fc08dff32c..ae69bf991e5 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -114,7 +114,7 @@ where .expect("Bridge message does not exist") .into(); let payload = Vec::::decode(&mut &encoded_payload[..]) - .expect("Decodign XCM message failed"); + .expect("Decoding XCM message failed"); let id: u32 = LaneIdWrapper(*lane).into(); let message = BridgeMessage { id, nonce, payload }; @@ -265,7 +265,7 @@ macro_rules! impl_assert_events_helpers_for_relay_chain { $crate::impls::assert_expected_events!( Self, vec![ - // XCM is successfully received and proccessed + // XCM is successfully received and processed [<$chain RuntimeEvent>]::::MessageQueue($crate::impls::pallet_message_queue::Event::Processed { origin: $crate::impls::AggregateMessageOrigin::Ump($crate::impls::UmpQueueId::Para(id)), weight_used, @@ -343,7 +343,7 @@ macro_rules! impl_hrmp_channels_helpers_for_relay_chain { ::Runtime, >::contains_key(&channel_id); - // Check the HRMP channel has been successfully registrered + // Check the HRMP channel has been successfully registered assert!(hrmp_channel_exist) }); } diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 40204ca297a..cbde0642f1a 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -67,7 +67,7 @@ parameter_types! { xcm::v3::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into()), ] ); - pub PenpalSiblingSovereigAccount: AccountId = Sibling::from(PENPAL_ID).into_account_truncating(); + pub PenpalSiblingSovereignAccount: AccountId = Sibling::from(PENPAL_ID).into_account_truncating(); } /// Helper function to generate a crypto pair from seed diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 0a5956dedfd..a0738839087 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -1052,7 +1052,7 @@ fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { // fund the Parachain Origin's SA on Relay Chain with the native tokens held in reserve Rococo::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); - // Init values for Parachain Desitnation + // Init values for Parachain Destination let receiver = PenpalBReceiver::get(); // Init Test diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 64ad15ca312..a26dfef8e8e 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -215,7 +215,7 @@ fn para_to_system_para_assets_sender_assertions(t: ParaToSystemParaTest) { let system_para_native_asset_location = v3::Location::try_from(RelayLocation::get()).expect("conversion works"); let reservable_asset_location = - v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("coversion works"); + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); PenpalA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8799))); assert_expected_events!( PenpalA, @@ -246,7 +246,7 @@ fn para_to_system_para_assets_sender_assertions(t: ParaToSystemParaTest) { fn system_para_to_para_assets_receiver_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; let system_para_asset_location = - v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("coversion works"); + v3::Location::try_from(PenpalLocalReservableFromAssetHub::get()).expect("conversion works"); PenpalA::assert_xcmp_queue_success(None); assert_expected_events!( PenpalA, @@ -1054,7 +1054,7 @@ fn reserve_transfer_native_asset_from_para_to_para_trough_relay() { // fund the Parachain Origin's SA on Relay Chain with the native tokens held in reserve Westend::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); - // Init values for Parachain Desitnation + // Init values for Parachain Destination let receiver = PenpalBReceiver::get(); // Init Test diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index 1e74d63e1d5..26b82375e07 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -23,7 +23,7 @@ use rococo_westend_system_emulated_network::BridgeHubRococoParaSender as BridgeH use snowbridge_core::outbound::OperatingMode; use snowbridge_pallet_inbound_queue_fixtures::{ register_token::make_register_token_message, - register_token_with_insufficient_fee::make_register_token_with_infufficient_fee_message, + register_token_with_insufficient_fee::make_register_token_with_insufficient_fee_message, send_token::make_send_token_message, send_token_to_penpal::make_send_token_to_penpal_message, InboundQueueFixture, }; @@ -514,7 +514,7 @@ fn register_weth_token_in_asset_hub_fail_for_insufficient_fee() { type RuntimeEvent = ::RuntimeEvent; // Construct RegisterToken message and sent to inbound queue - let message = make_register_token_with_infufficient_fee_message(); + let message = make_register_token_with_insufficient_fee_message(); send_inbound_message(message).unwrap(); assert_expected_events!( diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index c438361cc17..47c3ed36888 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -192,7 +192,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter< LocationToAccountId, // Our chain's account ID type (we can't get away without mentioning it explicitly): AccountId, - // We dont need to check teleports here. + // We don't need to check teleports here. NoChecking, // The account to use for tracking teleports. CheckingAccount, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index c993d61545a..7d3ed650e6b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -185,7 +185,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter< LocationToAccountId, // Our chain's account ID type (we can't get away without mentioning it explicitly): AccountId, - // We dont need to check teleports here. + // We don't need to check teleports here. NoChecking, // The account to use for tracking teleports. CheckingAccount, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index 3ba9b9587d8..6696cb23223 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -618,7 +618,7 @@ fn test_asset_xcm_take_first_trader_with_refund() { // We actually use half of the weight let weight_used = bought / 2; - // Make sure refurnd works. + // Make sure refund works. let amount_refunded = WeightToFee::weight_to_fee(&(bought - weight_used)); assert_eq!( @@ -745,7 +745,7 @@ fn test_that_buying_ed_refund_does_not_refund_for_take_first_trader() { // Buy weight should work assert_ok!(trader.buy_weight(bought, asset.into(), &ctx)); - // Should return None. We have a specific check making sure we dont go below ED for + // Should return None. We have a specific check making sure we don't go below ED for // drop payment assert_eq!(trader.refund_weight(bought, &ctx), None); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 2f2624d8e52..884b71369e7 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -1120,7 +1120,7 @@ pub fn create_and_manage_foreign_assets_for_local_consensus_parachain_assets_wor AssetId: Clone, AssetIdConverter: MaybeEquivalence, { - // foreign parachain with the same consenus currency as asset + // foreign parachain with the same consensus currency as asset let foreign_asset_id_location = Location::new(1, [Parachain(2222), GeneralIndex(1234567)]); let asset_id = AssetIdConverter::convert(&foreign_asset_id_location).unwrap(); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 1cce3b647cf..0b2364dbb8b 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -386,7 +386,7 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< existential_deposit, ); - // create foreign asset for wrapped/derivated representation + // create foreign asset for wrapped/derived representation assert_ok!( >::force_create( RuntimeHelper::::root_origin(), diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index ad369583f07..cd5f1ad3272 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -456,7 +456,7 @@ mod benches { [cumulus_pallet_xcmp_queue, XcmpQueue] [pallet_collator_selection, CollatorSelection] // XCM - [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] + [pallet_xcm, PalletXcmExtrinsicsBenchmark::] [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] ); @@ -644,7 +644,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; - use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -680,7 +680,7 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} - use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< xcm_config::XcmConfig, diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index c76611ad2a3..e840a40f5ac 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -344,7 +344,7 @@ parameter_types! { pub const StakingAdminBodyId: BodyId = BodyId::Defense; } -/// We allow Root and the `StakingAdmi` to execute privileged collator selection operations. +/// We allow Root and the `StakingAdmin` to execute privileged collator selection operations. pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< EnsureRoot, EnsureXcm>, @@ -456,7 +456,7 @@ mod benches { [cumulus_pallet_xcmp_queue, XcmpQueue] [pallet_collator_selection, CollatorSelection] // XCM - [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] + [pallet_xcm, PalletXcmExtrinsicsBenchmark::] [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] ); @@ -644,7 +644,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; - use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -680,7 +680,7 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} - use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; impl pallet_xcm::benchmarking::Config for Runtime { type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< xcm_config::XcmConfig, diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index 639bfd95834..7b8e40e0428 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -145,7 +145,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter< LocationToAccountId, // Our chain's account ID type (we can't get away without mentioning it explicitly): AccountId, - // We dont need to check teleports here. + // We don't need to check teleports here. NoChecking, // The account to use for tracking teleports. CheckingAccount, diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index 9ba7b7876b3..ac9c6b6f978 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -135,7 +135,7 @@ fn runtime(id: &str) -> Runtime { fn load_spec(id: &str) -> std::result::Result, String> { let (id, _, para_id) = extract_parachain_id(id); Ok(match id { - // - Defaul-like + // - Default-like "staging" => Box::new(chain_spec::rococo_parachain::staging_rococo_parachain_local_config()), "tick" => Box::new(GenericChainSpec::from_json_bytes( diff --git a/cumulus/primitives/storage-weight-reclaim/src/lib.rs b/cumulus/primitives/storage-weight-reclaim/src/lib.rs index 5dddc92e395..c09c12d7a0a 100644 --- a/cumulus/primitives/storage-weight-reclaim/src/lib.rs +++ b/cumulus/primitives/storage-weight-reclaim/src/lib.rs @@ -421,7 +421,7 @@ mod tests { .unwrap(); assert_eq!(pre, Some(100)); - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo` // we always need to call `post_dispatch` to verify that they interoperate correctly. assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); assert_ok!(StorageWeightReclaim::::post_dispatch( @@ -456,7 +456,7 @@ mod tests { .unwrap(); assert_eq!(pre, Some(100)); - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo` // we always need to call `post_dispatch` to verify that they interoperate correctly. assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); assert_ok!(StorageWeightReclaim::::post_dispatch( @@ -500,7 +500,7 @@ mod tests { &Ok(()) )); // `CheckWeight` gets called after `StorageWeightReclaim` this time. - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo` // we always need to call `post_dispatch` to verify that they interoperate correctly. assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); @@ -536,7 +536,7 @@ mod tests { &Ok(()) )); // `CheckWeight` gets called after `StorageWeightReclaim` this time. - // The `CheckWeight` extension will refunt `actual_weight` from `PostDispatchInfo` + // The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo` // we always need to call `post_dispatch` to verify that they interoperate correctly. assert_ok!(CheckWeight::::post_dispatch(None, &info, &post_info, 0, &Ok(()))); diff --git a/cumulus/primitives/timestamp/src/lib.rs b/cumulus/primitives/timestamp/src/lib.rs index 535c4a2a726..e6aba6d0bb7 100644 --- a/cumulus/primitives/timestamp/src/lib.rs +++ b/cumulus/primitives/timestamp/src/lib.rs @@ -22,7 +22,7 @@ //! access to any clock from the runtime the timestamp is always passed as an inherent into the //! runtime. To check this inherent when validating the block, we will use the relay chain slot. As //! the relay chain slot is derived from a timestamp, we can easily convert it back to a timestamp -//! by muliplying it with the slot duration. By comparing the relay chain slot derived timestamp +//! by multiplying it with the slot duration. By comparing the relay chain slot derived timestamp //! with the timestamp we can ensure that the parachain timestamp is reasonable. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/cumulus/primitives/utility/src/lib.rs b/cumulus/primitives/utility/src/lib.rs index abc391bdcb8..d5d411356dc 100644 --- a/cumulus/primitives/utility/src/lib.rs +++ b/cumulus/primitives/utility/src/lib.rs @@ -141,7 +141,7 @@ impl< ) -> Result { log::trace!(target: "xcm::weight", "TakeFirstAssetTrader::buy_weight weight: {:?}, payment: {:?}, context: {:?}", weight, payment, context); - // Make sure we dont enter twice + // Make sure we don't enter twice if self.0.is_some() { return Err(XcmError::NotWithdrawable) } @@ -176,7 +176,7 @@ impl< // Convert to the same kind of asset, with the required fungible balance let required = first.id.clone().into_asset(asset_balance.into()); - // Substract payment + // Subtract payment let unused = payment.checked_sub(required.clone()).map_err(|_| XcmError::TooExpensive)?; // record weight and asset @@ -203,7 +203,7 @@ impl< // Calculate asset_balance // This read should have already be cached in buy_weight - let (asset_balance, outstanding_minus_substracted) = + let (asset_balance, outstanding_minus_subtracted) = FeeCharger::charge_weight_in_fungibles(local_asset_id, weight).ok().map( |asset_balance| { // Require at least a drop of minimum_balance @@ -221,16 +221,15 @@ impl< )?; // Convert balances into u128 - let outstanding_minus_substracted: u128 = - outstanding_minus_substracted.saturated_into(); + let outstanding_minus_subtracted: u128 = outstanding_minus_subtracted.saturated_into(); let asset_balance: u128 = asset_balance.saturated_into(); - // Construct outstanding_concrete_asset with the same location id and substracted + // Construct outstanding_concrete_asset with the same location id and subtracted // balance let outstanding_concrete_asset: Asset = - (id.clone(), outstanding_minus_substracted).into(); + (id.clone(), outstanding_minus_subtracted).into(); - // Substract from existing weight and balance + // Subtract from existing weight and balance weight_outstanding = weight_outstanding.saturating_sub(weight); // Override AssetTraderRefunder @@ -263,9 +262,10 @@ impl< } } -/// XCM fee depositor to which we implement the TakeRevenue trait -/// It receives a Transact implemented argument, a 32 byte convertible acocuntId, and the fee -/// receiver account FungiblesMutateAdapter should be identical to that implemented by WithdrawAsset +/// XCM fee depositor to which we implement the `TakeRevenue` trait. +/// It receives a `Transact` implemented argument and a 32 byte convertible `AccountId`, and the fee +/// receiver account's `FungiblesMutateAdapter` should be identical to that implemented by +/// `WithdrawAsset`. pub struct XcmFeesTo32ByteAccount( PhantomData<(FungiblesMutateAdapter, AccountId, ReceiverAccount)>, ); @@ -763,7 +763,8 @@ mod test_trader { /// Implementation of `xcm_builder::EnsureDelivery` which helps to ensure delivery to the /// parent relay chain. Deposits existential deposit for origin (if needed). /// Deposits estimated fee to the origin account (if needed). -/// Allows to trigger additional logic for specific `ParaId` (e.g. open HRMP channel) (if neeeded). +/// Allows triggering of additional logic for a specific `ParaId` (e.g. to open an HRMP channel) if +/// needed. #[cfg(feature = "runtime-benchmarks")] pub struct ToParentDeliveryHelper( sp_std::marker::PhantomData<(XcmConfig, ExistentialDeposit, PriceForDelivery)>, diff --git a/cumulus/scripts/scale_encode_genesis/index.js b/cumulus/scripts/scale_encode_genesis/index.js index f612e6da79d..c6600e40636 100644 --- a/cumulus/scripts/scale_encode_genesis/index.js +++ b/cumulus/scripts/scale_encode_genesis/index.js @@ -19,14 +19,14 @@ async function connect(endpoint, types = {}) { } if (!process.argv[2] || !process.argv[3]) { - console.log("usage: node generate_keys [rpc enpoint]"); + console.log("usage: node generate_keys [rpc endpoint]"); exit(); } const input = process.argv[2]; const output = process.argv[3]; // default to localhost and the default Substrate port -const rpcEnpoint = process.argv[4] || "ws://localhost:9944"; +const rpcEndpoint = process.argv[4] || "ws://localhost:9944"; console.log("Processing", input, output); fs.readFile(input, "utf8", (err, data) => { @@ -38,8 +38,8 @@ fs.readFile(input, "utf8", (err, data) => { const genesis = JSON.parse(data); console.log("loaded genesis, length = ", genesis.length); - console.log(`Connecting to RPC endpoint: ${rpcEnpoint}`); - connect(rpcEnpoint) + console.log(`Connecting to RPC endpoint: ${rpcEndpoint}`); + connect(rpcEndpoint) .then((api) => { console.log('Connected'); const setStorage = api.tx.system.setStorage(genesis); diff --git a/cumulus/scripts/temp_parachain_types.json b/cumulus/scripts/temp_parachain_types.json index f550a677445..2509d32be9f 100644 --- a/cumulus/scripts/temp_parachain_types.json +++ b/cumulus/scripts/temp_parachain_types.json @@ -54,7 +54,7 @@ "validity_votes": "Vec", "validator_indices": "BitVec" }, - "CandidatePendingAvailablility": { + "CandidatePendingAvailability": { "core": "u32", "descriptor": "CandidateDescriptor", "availability_votes": "BitVec", diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index 8e3569b02a1..5127b63f271 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -139,7 +139,7 @@ pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } -/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers. +/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers. /// This is used to limit the maximal weight of a single extrinsic. const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used diff --git a/cumulus/test/service/benches/validate_block.rs b/cumulus/test/service/benches/validate_block.rs index a614863803e..d95f733969b 100644 --- a/cumulus/test/service/benches/validate_block.rs +++ b/cumulus/test/service/benches/validate_block.rs @@ -47,7 +47,7 @@ fn create_extrinsics( src_accounts: &[sr25519::Pair], dst_accounts: &[sr25519::Pair], ) -> (usize, Vec) { - // Add as many tranfer extrinsics as possible into a single block. + // Add as many transfer extrinsics as possible into a single block. let mut block_builder = BlockBuilderBuilder::new(client) .on_parent_block(client.chain_info().best_hash) .with_parent_block_number(client.chain_info().best_number) diff --git a/cumulus/test/service/src/lib.rs b/cumulus/test/service/src/lib.rs index 3554a383f21..3af3901d175 100644 --- a/cumulus/test/service/src/lib.rs +++ b/cumulus/test/service/src/lib.rs @@ -735,7 +735,7 @@ pub fn node_config( tokio_handle: tokio::runtime::Handle, key: Sr25519Keyring, nodes: Vec, - nodes_exlusive: bool, + nodes_exclusive: bool, para_id: ParaId, is_collator: bool, endowed_accounts: Vec, @@ -759,7 +759,7 @@ pub fn node_config( None, ); - if nodes_exlusive { + if nodes_exclusive { network_config.default_peers_set.reserved_nodes = nodes; network_config.default_peers_set.non_reserved_mode = sc_network::config::NonReservedPeerMode::Deny; diff --git a/docker/dockerfiles/binary_injected.Dockerfile b/docker/dockerfiles/binary_injected.Dockerfile index ac1fd5317c6..c8930bd83f0 100644 --- a/docker/dockerfiles/binary_injected.Dockerfile +++ b/docker/dockerfiles/binary_injected.Dockerfile @@ -2,7 +2,7 @@ FROM docker.io/parity/base-bin # This file allows building a Generic container image # based on one or multiple pre-built Linux binaries. -# Some defaults are set to polkadot but all can be overriden. +# Some defaults are set to polkadot but all can be overridden. SHELL ["/bin/bash", "-c"] diff --git a/docker/scripts/build-injected.sh b/docker/scripts/build-injected.sh index f415cf43c0e..749d0fa335c 100755 --- a/docker/scripts/build-injected.sh +++ b/docker/scripts/build-injected.sh @@ -20,7 +20,7 @@ PROJECT_ROOT=${PROJECT_ROOT:-$(git rev-parse --show-toplevel)} DOCKERFILE=${DOCKERFILE:-docker/dockerfiles/binary_injected.Dockerfile} VERSION_TOML=$(grep "^version " $PROJECT_ROOT/Cargo.toml | grep -oE "([0-9\.]+-?[0-9]+)") -#n The following VAR have default that can be overriden +#n The following VAR have default that can be overridden DOCKER_OWNER=${DOCKER_OWNER:-parity} # We may get 1..n binaries, comma separated diff --git a/docs/sdk/Cargo.toml b/docs/sdk/Cargo.toml index 3f84d45640f..434202ed693 100644 --- a/docs/sdk/Cargo.toml +++ b/docs/sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "polkadot-sdk-docs" -description = "The one stop shop for developers of the polakdot-sdk" +description = "The one stop shop for developers of the polkadot-sdk" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "paritytech.github.io" repository.workspace = true diff --git a/docs/sdk/src/reference_docs/frame_runtime_upgrades_and_migrations.rs b/docs/sdk/src/reference_docs/frame_runtime_upgrades_and_migrations.rs index 7d870b43221..cbbf611f9dc 100644 --- a/docs/sdk/src/reference_docs/frame_runtime_upgrades_and_migrations.rs +++ b/docs/sdk/src/reference_docs/frame_runtime_upgrades_and_migrations.rs @@ -16,7 +16,7 @@ //! in a process called "Runtime Upgrades". //! //! Forkless runtime upgrades are a defining feature of the Substrate framework. Updating the -//! runtime logic without forking the code base enables your blockchain to seemlessly evolve +//! runtime logic without forking the code base enables your blockchain to seamlessly evolve //! over time in a deterministic, rules-based manner. It also removes ambiguity for node operators //! and other participants in the network about what is the canonical runtime. //! @@ -24,7 +24,7 @@ //! //! ## Performing a Runtime Upgrade //! -//! To upgrade a runtime, an [`Origin`](frame_system::RawOrigin) with the necesarry permissions +//! To upgrade a runtime, an [`Origin`](frame_system::RawOrigin) with the necessary permissions //! (usually via governance) changes the `:code` storage. Usually, this is performed via a call to //! [`set_code`] (or [`set_code_without_checks`]) with the desired new runtime blob, scheduled //! using [`pallet_scheduler`]. @@ -41,7 +41,7 @@ //! //! The typical use case of a migration is to 'migrate' pallet storage from one layout to another, //! for example when the encoding of a storage item is changed. However, they can also execute -//! arbitary logic such as: +//! arbitrary logic such as: //! //! - Calling arbitrary pallet methods //! - Mutating arbitrary on-chain state @@ -88,7 +88,7 @@ //! //! Prior to deploying migrations, it is critical to perform additional checks to ensure that when //! run in our real runtime they will not brick the chain due to: -//! - Panicing +//! - Panicking //! - Touching too many storage keys and resulting in an excessively large PoV //! - Taking too long to execute //! diff --git a/polkadot/cli/src/cli.rs b/polkadot/cli/src/cli.rs index e1bc2309a94..74e19044469 100644 --- a/polkadot/cli/src/cli.rs +++ b/polkadot/cli/src/cli.rs @@ -122,7 +122,7 @@ pub struct RunCmd { /// Overseer message capacity override. /// - /// **Dangerous!** Do not touch unless explicitly adviced to. + /// **Dangerous!** Do not touch unless explicitly advised to. #[arg(long)] pub overseer_channel_capacity_override: Option, diff --git a/polkadot/grafana/README.md b/polkadot/grafana/README.md index 7350001bfa1..e909fdd29a7 100644 --- a/polkadot/grafana/README.md +++ b/polkadot/grafana/README.md @@ -8,7 +8,7 @@ monitor the liveliness and performance of a network and its validators. # How does it work ? Just import the dashboard JSON files from this folder in your Grafana installation. All dashboards are grouped in -folder percategory (like for example `parachains`). The files have been created by Grafana export functionality and +folder per category (like for example `parachains`). The files have been created by Grafana export functionality and follow the data model specified [here](https://grafana.com/docs/grafana/latest/dashboards/json-model/). We aim to keep the dashboards here in sync with the implementation, except dashboards for development and diff --git a/polkadot/node/core/approval-voting/src/approval_db/v1/tests.rs b/polkadot/node/core/approval-voting/src/approval_db/v1/tests.rs index b979cb7ef45..b0966ad01f7 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v1/tests.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v1/tests.rs @@ -254,7 +254,7 @@ fn canonicalize_works() { // -> B1 -> C1 -> D1 // A -> B2 -> C2 -> D2 // - // We'll canonicalize C1. Everytning except D1 should disappear. + // We'll canonicalize C1. Everything except D1 should disappear. // // Candidates: // Cand1 in B2 diff --git a/polkadot/node/core/approval-voting/src/approval_db/v2/migration_helpers.rs b/polkadot/node/core/approval-voting/src/approval_db/v2/migration_helpers.rs index df6e4754dbd..1081d79884f 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v2/migration_helpers.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v2/migration_helpers.rs @@ -79,7 +79,7 @@ pub fn v1_to_latest(db: Arc, config: Config) -> Result<()> { block.candidates().iter().enumerate() { // Loading the candidate will also perform the conversion to the updated format and - // return that represantation. + // return that representation. if let Some(candidate_entry) = backend .load_candidate_entry_v1(&candidate_hash, candidate_index as CandidateIndex) .map_err(|e| Error::InternalError(e))? diff --git a/polkadot/node/core/approval-voting/src/approval_db/v2/tests.rs b/polkadot/node/core/approval-voting/src/approval_db/v2/tests.rs index 6021b44c276..5fa915add41 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v2/tests.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v2/tests.rs @@ -269,7 +269,7 @@ fn canonicalize_works() { // -> B1 -> C1 -> D1 // A -> B2 -> C2 -> D2 // - // We'll canonicalize C1. Everytning except D1 should disappear. + // We'll canonicalize C1. Everything except D1 should disappear. // // Candidates: // Cand1 in B2 diff --git a/polkadot/node/core/approval-voting/src/approval_db/v3/migration_helpers.rs b/polkadot/node/core/approval-voting/src/approval_db/v3/migration_helpers.rs index ad5e89ef3de..d1e7ee08225 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v3/migration_helpers.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v3/migration_helpers.rs @@ -60,7 +60,7 @@ pub fn v2_to_latest(db: Arc, config: Config) -> Result<()> { block.candidates().iter().enumerate() { // Loading the candidate will also perform the conversion to the updated format and - // return that represantation. + // return that representation. if let Some(candidate_entry) = backend .load_candidate_entry_v2(&candidate_hash, candidate_index as CandidateIndex) .map_err(|e| Error::InternalError(e))? @@ -104,7 +104,7 @@ pub fn v1_to_latest_sanity_check( for block in all_blocks { for (_core_index, candidate_hash) in block.candidates() { // Loading the candidate will also perform the conversion to the updated format and - // return that represantation. + // return that representation. if let Some(candidate_entry) = backend.load_candidate_entry(&candidate_hash).unwrap() { candidates.insert(candidate_entry.candidate.hash()); } diff --git a/polkadot/node/core/approval-voting/src/approval_db/v3/tests.rs b/polkadot/node/core/approval-voting/src/approval_db/v3/tests.rs index 08c65461bca..7c0cf9d4f7d 100644 --- a/polkadot/node/core/approval-voting/src/approval_db/v3/tests.rs +++ b/polkadot/node/core/approval-voting/src/approval_db/v3/tests.rs @@ -264,7 +264,7 @@ fn canonicalize_works() { // -> B1 -> C1 -> D1 // A -> B2 -> C2 -> D2 // - // We'll canonicalize C1. Everytning except D1 should disappear. + // We'll canonicalize C1. Everything except D1 should disappear. // // Candidates: // Cand1 in B2 diff --git a/polkadot/node/core/approval-voting/src/criteria.rs b/polkadot/node/core/approval-voting/src/criteria.rs index 1ebea2641b6..57c0ac272dc 100644 --- a/polkadot/node/core/approval-voting/src/criteria.rs +++ b/polkadot/node/core/approval-voting/src/criteria.rs @@ -148,7 +148,7 @@ fn relay_vrf_modulo_cores( generate_samples(rand_chacha, num_samples as usize, max_cores as usize) } -/// Generates `num_sumples` randomly from (0..max_cores) range +/// Generates `num_samples` randomly from (0..max_cores) range /// /// Note! The algorithm can't change because validators on the other /// side won't be able to check the assignments until they update. diff --git a/polkadot/node/core/approval-voting/src/import.rs b/polkadot/node/core/approval-voting/src/import.rs index 7a56e9fd112..d34191fba31 100644 --- a/polkadot/node/core/approval-voting/src/import.rs +++ b/polkadot/node/core/approval-voting/src/import.rs @@ -91,7 +91,7 @@ enum ImportedBlockInfoError { #[error(transparent)] RuntimeError(RuntimeApiError), - #[error("future cancalled while requesting {0}")] + #[error("future cancelled while requesting {0}")] FutureCancelled(&'static str, futures::channel::oneshot::Canceled), #[error(transparent)] diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index 1d7ab3eee21..1a62c9ee55e 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -1850,7 +1850,7 @@ async fn get_approval_signatures_for_candidate( gum::trace!( target: LOG_TARGET, ?candidate_hash, - "Spawning task for fetching sinatures from approval-distribution" + "Spawning task for fetching signatures from approval-distribution" ); ctx.spawn("get-approval-signatures", Box::pin(get_approvals)) } diff --git a/polkadot/node/core/approval-voting/src/tests.rs b/polkadot/node/core/approval-voting/src/tests.rs index c9053232a4c..a3013eab46d 100644 --- a/polkadot/node/core/approval-voting/src/tests.rs +++ b/polkadot/node/core/approval-voting/src/tests.rs @@ -3154,7 +3154,7 @@ where // starting configuration. The relevant ticks (all scheduled wakeups) are printed after no further // ticks are scheduled. To create a valid test, a prefix of the relevant ticks should be included // in the final test configuration, ending at the tick with the desired inputs to -// should_trigger_assignemnt. +// should_trigger_assignment. async fn step_until_done(clock: &MockClock) { let mut relevant_ticks = Vec::new(); loop { @@ -3837,7 +3837,7 @@ fn test_approval_is_sent_on_max_approval_coalesce_count() { async fn handle_approval_on_max_coalesce_count( virtual_overseer: &mut VirtualOverseer, - candidate_indicies: Vec, + candidate_indices: Vec, ) { assert_matches!( overseer_recv(virtual_overseer).await, @@ -3845,16 +3845,16 @@ async fn handle_approval_on_max_coalesce_count( _, c_indices, )) => { - assert_eq!(TryInto::::try_into(candidate_indicies.clone()).unwrap(), c_indices); + assert_eq!(TryInto::::try_into(candidate_indices.clone()).unwrap(), c_indices); } ); - for _ in &candidate_indicies { + for _ in &candidate_indices { recover_available_data(virtual_overseer).await; fetch_validation_code(virtual_overseer).await; } - for _ in &candidate_indicies { + for _ in &candidate_indices { assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::CandidateValidation(CandidateValidationMessage::ValidateFromExhaustive{exec_kind, response_sender, ..}) if exec_kind == PvfExecKind::Approval => { @@ -3885,7 +3885,7 @@ async fn handle_approval_on_max_coalesce_count( assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeApproval(vote)) => { - assert_eq!(TryInto::::try_into(candidate_indicies).unwrap(), vote.candidate_indices); + assert_eq!(TryInto::::try_into(candidate_indices).unwrap(), vote.candidate_indices); } ); @@ -3895,7 +3895,7 @@ async fn handle_approval_on_max_coalesce_count( async fn handle_approval_on_max_wait_time( virtual_overseer: &mut VirtualOverseer, - candidate_indicies: Vec, + candidate_indices: Vec, clock: Box, ) { const TICK_NOW_BEGIN: u64 = 1; @@ -3909,16 +3909,16 @@ async fn handle_approval_on_max_wait_time( _, c_indices, )) => { - assert_eq!(TryInto::::try_into(candidate_indicies.clone()).unwrap(), c_indices); + assert_eq!(TryInto::::try_into(candidate_indices.clone()).unwrap(), c_indices); } ); - for _ in &candidate_indicies { + for _ in &candidate_indices { recover_available_data(virtual_overseer).await; fetch_validation_code(virtual_overseer).await; } - for _ in &candidate_indicies { + for _ in &candidate_indices { assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::CandidateValidation(CandidateValidationMessage::ValidateFromExhaustive{exec_kind, response_sender, ..}) if exec_kind == PvfExecKind::Approval => { @@ -3978,7 +3978,7 @@ async fn handle_approval_on_max_wait_time( assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeApproval(vote)) => { - assert_eq!(TryInto::::try_into(candidate_indicies).unwrap(), vote.candidate_indices); + assert_eq!(TryInto::::try_into(candidate_indices).unwrap(), vote.candidate_indices); } ); @@ -4319,7 +4319,7 @@ fn subsystem_relaunches_approval_work_on_restart() { virtual_overseer }); - // Restart a new approval voting subsystem with the same database and major syncing true untill + // Restart a new approval voting subsystem with the same database and major syncing true until // the last leaf. let config = HarnessConfigBuilder::default().backend(store_clone).major_syncing(true).build(); diff --git a/polkadot/node/core/approval-voting/src/time.rs b/polkadot/node/core/approval-voting/src/time.rs index 99dfbe07678..5c3e7e85a17 100644 --- a/polkadot/node/core/approval-voting/src/time.rs +++ b/polkadot/node/core/approval-voting/src/time.rs @@ -126,13 +126,13 @@ impl DelayedApprovalTimer { /// no additional timer is started. pub(crate) fn maybe_arm_timer( &mut self, - wait_untill: Tick, + wait_until: Tick, clock: &dyn Clock, block_hash: Hash, validator_index: ValidatorIndex, ) { if self.blocks.insert(block_hash) { - let clock_wait = clock.wait(wait_untill); + let clock_wait = clock.wait(wait_until); self.timers.push(Box::pin(async move { clock_wait.await; (block_hash, validator_index) diff --git a/polkadot/node/core/av-store/src/lib.rs b/polkadot/node/core/av-store/src/lib.rs index ef7dcecac07..68db4686a97 100644 --- a/polkadot/node/core/av-store/src/lib.rs +++ b/polkadot/node/core/av-store/src/lib.rs @@ -1218,7 +1218,7 @@ fn process_message( // tx channel is dropped and that error is caught by the caller subsystem. // // We bubble up the specific error here so `av-store` logs still tell what - // happend. + // happened. return Err(e.into()) }, } diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index 532ae2bd7cb..4b6beb5592e 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -292,7 +292,7 @@ struct State { /// Cache the per-session Validator->Group mapping. validator_to_group_cache: LruMap>>>, - /// A cloneable sender which is dispatched to background candidate validation tasks to inform + /// A clonable sender which is dispatched to background candidate validation tasks to inform /// the main task of the result. background_validation_tx: mpsc::Sender<(Hash, ValidatedCandidateCommand)>, /// The handle to the keystore used for signing. diff --git a/polkadot/node/core/candidate-validation/src/lib.rs b/polkadot/node/core/candidate-validation/src/lib.rs index 8237137fdca..ec24434db24 100644 --- a/polkadot/node/core/candidate-validation/src/lib.rs +++ b/polkadot/node/core/candidate-validation/src/lib.rs @@ -617,7 +617,7 @@ async fn validate_candidate_exhaustive( Err(e) => { gum::info!(target: LOG_TARGET, ?para_id, err=?e, "Invalid candidate (validation code)"); - // Code already passed pre-checking, if decompression fails now this most likley means + // Code already passed pre-checking, if decompression fails now this most likely means // some local corruption happened. return Err(ValidationFailed("Code decompression failed".to_string())) }, diff --git a/polkadot/node/core/chain-selection/src/lib.rs b/polkadot/node/core/chain-selection/src/lib.rs index aa5bb9548ad..6f864fefb61 100644 --- a/polkadot/node/core/chain-selection/src/lib.rs +++ b/polkadot/node/core/chain-selection/src/lib.rs @@ -51,7 +51,7 @@ type Timestamp = u64; // If a block isn't approved in 120 seconds, nodes will abandon it // and begin building on another chain. const STAGNANT_TIMEOUT: Timestamp = 120; -// Delay prunning of the stagnant keys in prune only mode by 25 hours to avoid interception with the +// Delay pruning of the stagnant keys in prune only mode by 25 hours to avoid interception with the // finality const STAGNANT_PRUNE_DELAY: Timestamp = 25 * 60 * 60; // Maximum number of stagnant entries cleaned during one `STAGNANT_TIMEOUT` iteration @@ -237,7 +237,7 @@ impl Clock for SystemClock { // // The exact time that a block becomes stagnant in the local node is always expected // to differ from other nodes due to network asynchrony and delays in block propagation. - // Non-monotonicity exarcerbates that somewhat, but not meaningfully. + // Non-monotonicity exacerbates that somewhat, but not meaningfully. match SystemTime::now().duration_since(UNIX_EPOCH) { Ok(d) => d.as_secs(), diff --git a/polkadot/node/core/chain-selection/src/tests.rs b/polkadot/node/core/chain-selection/src/tests.rs index cf021c0efeb..bc998f268a0 100644 --- a/polkadot/node/core/chain-selection/src/tests.rs +++ b/polkadot/node/core/chain-selection/src/tests.rs @@ -406,7 +406,7 @@ async fn import_chains_into_empty( // some pre-blocks may need to be supplied to answer ancestry requests // that gather batches beyond the beginning of the new chain. // pre-blocks are those already known by the subsystem, however, -// the subsystem has no way of knowin that until requesting ancestry. +// the subsystem has no way of knowing that until requesting ancestry. async fn import_all_blocks_into( virtual_overseer: &mut VirtualOverseer, backend: &TestBackend, @@ -1300,7 +1300,7 @@ fn finalize_erases_unviable_from_one_but_not_all_reverts() { // F <- A1 <- A2 <- A3 // // A3 reverts A2 and A1. - // Finalize A1. A2 is stil unviable. + // Finalize A1. A2 is still unviable. let (a3_hash, chain_a) = construct_chain_on_base(vec![1, 2, 3], finalized_number, finalized_hash, |h| { diff --git a/polkadot/node/core/dispute-coordinator/src/db/v1.rs b/polkadot/node/core/dispute-coordinator/src/db/v1.rs index f0f17d2325d..4950765cf51 100644 --- a/polkadot/node/core/dispute-coordinator/src/db/v1.rs +++ b/polkadot/node/core/dispute-coordinator/src/db/v1.rs @@ -341,7 +341,7 @@ pub(crate) fn note_earliest_session( let lower_bound = (new_earliest_session, CandidateHash(Hash::repeat_byte(0x00))); let new_recent_disputes = recent_disputes.split_off(&lower_bound); - // Any remanining disputes are considered ancient and must be pruned. + // Any remaining disputes are considered ancient and must be pruned. let pruned_disputes = recent_disputes; if pruned_disputes.len() != 0 { diff --git a/polkadot/node/core/dispute-coordinator/src/lib.rs b/polkadot/node/core/dispute-coordinator/src/lib.rs index 4b511e7430a..daa384b36ff 100644 --- a/polkadot/node/core/dispute-coordinator/src/lib.rs +++ b/polkadot/node/core/dispute-coordinator/src/lib.rs @@ -462,7 +462,7 @@ async fn wait_for_first_leaf(ctx: &mut Context) -> Result { // Rare case where same candidate was present on multiple heights, but all are // pruned at the same time. This candidate was already pruned in the previous - // occurence so it is skipped now. + // occurrence so it is skipped now. }, Entry::Occupied(mut e) => { let mut blocks_including = std::mem::take(e.get_mut()); diff --git a/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs b/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs index 748f9a16f49..726dda596d7 100644 --- a/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/scraping/tests.rs @@ -542,8 +542,8 @@ fn scraper_handles_backed_but_not_included_candidate() { } #[test] -fn scraper_handles_the_same_candidate_incuded_in_two_different_block_heights() { - // Same candidate will be inclued in these two leaves +fn scraper_handles_the_same_candidate_included_in_two_different_block_heights() { + // Same candidate will be included in these two leaves let test_targets = vec![2, 3]; // How many blocks should we skip before sending a leaf update. diff --git a/polkadot/node/core/dispute-coordinator/src/tests.rs b/polkadot/node/core/dispute-coordinator/src/tests.rs index 0360e357bee..7c1f4ff241d 100644 --- a/polkadot/node/core/dispute-coordinator/src/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/tests.rs @@ -2226,7 +2226,7 @@ fn resume_dispute_without_local_statement() { test_state }) }) - // Alice should send a DisputeParticiationMessage::Participate on restart since she has no + // Alice should send a DisputeParticipationMessage::Participate on restart since she has no // local statement for the active dispute. .resume(|mut test_state, mut virtual_overseer| { Box::pin(async move { @@ -2390,7 +2390,7 @@ fn resume_dispute_with_local_statement() { test_state }) }) - // Alice should not send a DisputeParticiationMessage::Participate on restart since she has a + // Alice should not send a DisputeParticipationMessage::Participate on restart since she has a // local statement for the active dispute, instead she should try to (re-)send her vote. .resume(|mut test_state, mut virtual_overseer| { let candidate_receipt = make_valid_candidate_receipt(); @@ -2495,7 +2495,7 @@ fn resume_dispute_without_local_statement_or_local_key() { test_state }) }) - // Two should not send a DisputeParticiationMessage::Participate on restart since she is no + // Two should not send a DisputeParticipationMessage::Participate on restart since she is no // validator in that dispute. .resume(|mut test_state, mut virtual_overseer| { Box::pin(async move { diff --git a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/mod.rs b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/mod.rs index cb55ce39bc8..d7a5a811336 100644 --- a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/mod.rs +++ b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/mod.rs @@ -52,7 +52,7 @@ pub const MAX_DISPUTE_VOTES_FORWARDED_TO_RUNTIME: usize = 200; /// `dispute-coordinator`. /// /// This value should be less than `MAX_DISPUTE_VOTES_FORWARDED_TO_RUNTIME`. Increase it in case -/// `provisioner` sends too many `QueryCandidateVotes` messages to `dispite-coordinator`. +/// `provisioner` sends too many `QueryCandidateVotes` messages to `dispute-coordinator`. #[cfg(not(test))] const VOTES_SELECTION_BATCH_SIZE: usize = 1_100; #[cfg(test)] diff --git a/polkadot/node/core/pvf-checker/src/tests.rs b/polkadot/node/core/pvf-checker/src/tests.rs index b0401ecdc3b..b2365fe53e5 100644 --- a/polkadot/node/core/pvf-checker/src/tests.rs +++ b/polkadot/node/core/pvf-checker/src/tests.rs @@ -39,8 +39,8 @@ use std::{collections::HashMap, sync::Arc, time::Duration}; type VirtualOverseer = TestSubsystemContextHandle; -fn dummy_validation_code_hash(descriminator: u8) -> ValidationCodeHash { - ValidationCode(vec![descriminator]).hash() +fn dummy_validation_code_hash(discriminator: u8) -> ValidationCodeHash { + ValidationCode(vec![discriminator]).hash() } struct StartsNewSession { @@ -511,7 +511,7 @@ fn reactivating_pvf_leads_to_second_check() { .reply(PreCheckOutcome::Valid); test_state.expect_submit_vote(&mut handle).await.reply_ok(); - // Now activate a descdedant leaf, where the PVF is not present. + // Now activate a descendant leaf, where the PVF is not present. test_state .active_leaves_update( &mut handle, diff --git a/polkadot/node/core/pvf/common/src/pvf.rs b/polkadot/node/core/pvf/common/src/pvf.rs index 3f5b4d7ca70..340dffe07c3 100644 --- a/polkadot/node/core/pvf/common/src/pvf.rs +++ b/polkadot/node/core/pvf/common/src/pvf.rs @@ -85,9 +85,9 @@ impl PvfPrepData { /// Creates a structure for tests. #[cfg(feature = "test-utils")] pub fn from_discriminator_and_timeout(num: u32, timeout: Duration) -> Self { - let descriminator_buf = num.to_le_bytes().to_vec(); + let discriminator_buf = num.to_le_bytes().to_vec(); Self::from_code( - descriminator_buf, + discriminator_buf, ExecutorParams::default(), timeout, PrepareJobKind::Compilation, diff --git a/polkadot/node/core/pvf/src/host.rs b/polkadot/node/core/pvf/src/host.rs index 8ec46f4b08f..59d5a7e20a8 100644 --- a/polkadot/node/core/pvf/src/host.rs +++ b/polkadot/node/core/pvf/src/host.rs @@ -917,7 +917,7 @@ async fn sweeper_task(mut sweeper_rx: mpsc::Receiver) { gum::trace!( target: LOG_TARGET, ?result, - "Sweeped the artifact file {}", + "Swept the artifact file {}", condemned.display(), ); }, diff --git a/polkadot/node/core/pvf/src/priority.rs b/polkadot/node/core/pvf/src/priority.rs index d4bd49eaee8..d1ef9c604b1 100644 --- a/polkadot/node/core/pvf/src/priority.rs +++ b/polkadot/node/core/pvf/src/priority.rs @@ -29,7 +29,7 @@ pub enum Priority { } impl Priority { - /// Returns `true` if `self` is `Crticial` + /// Returns `true` if `self` is `Critical` pub fn is_critical(self) -> bool { self == Priority::Critical } diff --git a/polkadot/node/core/pvf/src/worker_interface.rs b/polkadot/node/core/pvf/src/worker_interface.rs index ad9f0294c09..93fffc80662 100644 --- a/polkadot/node/core/pvf/src/worker_interface.rs +++ b/polkadot/node/core/pvf/src/worker_interface.rs @@ -130,11 +130,11 @@ where fn make_tmppath(prefix: &str, dir: &Path) -> PathBuf { use rand::distributions::Alphanumeric; - const DESCRIMINATOR_LEN: usize = 10; + const DISCRIMINATOR_LEN: usize = 10; - let mut buf = Vec::with_capacity(prefix.len() + DESCRIMINATOR_LEN); + let mut buf = Vec::with_capacity(prefix.len() + DISCRIMINATOR_LEN); buf.extend(prefix.as_bytes()); - buf.extend(rand::thread_rng().sample_iter(&Alphanumeric).take(DESCRIMINATOR_LEN)); + buf.extend(rand::thread_rng().sample_iter(&Alphanumeric).take(DISCRIMINATOR_LEN)); let s = std::str::from_utf8(&buf) .expect("the string is collected from a valid utf-8 sequence; qed"); diff --git a/polkadot/node/core/pvf/tests/it/main.rs b/polkadot/node/core/pvf/tests/it/main.rs index cdfbcd8e578..16ef23c69ca 100644 --- a/polkadot/node/core/pvf/tests/it/main.rs +++ b/polkadot/node/core/pvf/tests/it/main.rs @@ -543,9 +543,9 @@ async fn all_security_features_work() { // artifacts cache existing. #[cfg(all(feature = "ci-only-tests", target_os = "linux"))] #[tokio::test] -async fn nonexistant_cache_dir() { +async fn nonexistent_cache_dir() { let host = TestHost::new_with_config(|cfg| { - cfg.cache_path = cfg.cache_path.join("nonexistant_cache_dir"); + cfg.cache_path = cfg.cache_path.join("nonexistent_cache_dir"); }) .await; diff --git a/polkadot/node/core/runtime-api/src/tests.rs b/polkadot/node/core/runtime-api/src/tests.rs index fefd2d3f862..b51682aa0f4 100644 --- a/polkadot/node/core/runtime-api/src/tests.rs +++ b/polkadot/node/core/runtime-api/src/tests.rs @@ -299,12 +299,12 @@ impl RuntimeApiSubsystemClient for MockSubsystemClient { #[test] fn requests_authorities() { let (ctx, mut ctx_handle) = make_subsystem_context(TaskExecutor::new()); - let substem_client = Arc::new(MockSubsystemClient::default()); + let subsystem_client = Arc::new(MockSubsystemClient::default()); let relay_parent = [1; 32].into(); let spawner = sp_core::testing::TaskExecutor::new(); let subsystem = - RuntimeApiSubsystem::new(substem_client.clone(), Metrics(None), SpawnGlue(spawner)); + RuntimeApiSubsystem::new(subsystem_client.clone(), Metrics(None), SpawnGlue(spawner)); let subsystem_task = run(ctx, subsystem).map(|x| x.unwrap()); let test_task = async move { let (tx, rx) = oneshot::channel(); @@ -315,7 +315,7 @@ fn requests_authorities() { }) .await; - assert_eq!(rx.await.unwrap().unwrap(), substem_client.authorities); + assert_eq!(rx.await.unwrap().unwrap(), subsystem_client.authorities); ctx_handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; }; @@ -1042,7 +1042,7 @@ fn requests_submit_pvf_check_statement() { let _ = rx.await.unwrap().unwrap(); assert_eq!( - &*subsystem_client.submitted_pvf_check_statement.lock().expect("poisened mutex"), + &*subsystem_client.submitted_pvf_check_statement.lock().expect("poisoned mutex"), &[(stmt.clone(), sig.clone()), (stmt.clone(), sig.clone())] ); diff --git a/polkadot/node/jaeger/src/spans.rs b/polkadot/node/jaeger/src/spans.rs index 4038d41344f..4816fccf3b9 100644 --- a/polkadot/node/jaeger/src/spans.rs +++ b/polkadot/node/jaeger/src/spans.rs @@ -70,7 +70,7 @@ //! let root_span = //! jaeger::Span::new(relay_parent, "root_of_aaall_spans"); //! -//! // the prefered way of adding additional delayed information: +//! // the preferred way of adding additional delayed information: //! let span = root_span.child("inner"); //! //! // ... more operations ... diff --git a/polkadot/node/malus/README.md b/polkadot/node/malus/README.md index e0c7893a753..25453a1980e 100644 --- a/polkadot/node/malus/README.md +++ b/polkadot/node/malus/README.md @@ -18,7 +18,7 @@ defined in the [(DSL[(**D**omain **S**pecific **L**anguage)]) doc](https://parit ## Usage -> Assumes you already gained permissiones, ping in element `@javier:matrix.parity.io` to get access. +> Assumes you already gained permissions, ping in element `@javier:matrix.parity.io` to get access. > and you have cloned the [zombienet][zombienet] repo. To launch a test case in the development cluster use (e.g. for the ./node/malus/integrationtests/0001-dispute-valid-block.toml): diff --git a/polkadot/node/network/approval-distribution/src/lib.rs b/polkadot/node/network/approval-distribution/src/lib.rs index f4e40270160..d360a18423e 100644 --- a/polkadot/node/network/approval-distribution/src/lib.rs +++ b/polkadot/node/network/approval-distribution/src/lib.rs @@ -230,7 +230,7 @@ impl ApprovalEntry { Ok(()) } - // Get the assignment certiticate and claimed candidates. + // Get the assignment certificate and claimed candidates. pub fn assignment(&self) -> (IndirectAssignmentCertV2, CandidateBitfield) { (self.assignment.clone(), self.assignment_claimed_candidates.clone()) } @@ -404,7 +404,7 @@ impl Knowledge { }, }; - // In case of succesful insertion of multiple candidate assignments create additional + // In case of successful insertion of multiple candidate assignments create additional // entries for each assigned candidate. This fakes knowledge of individual assignments, but // we need to share the same `MessageSubject` with the followup approval candidate index. if kind == MessageKind::Assignment && success && message.1.count_ones() > 1 { @@ -1897,10 +1897,10 @@ impl State { _ => break, }; - // Any peer which is in the `known_by` see and we know its peer_id authorithy id + // Any peer which is in the `known_by` see and we know its peer_id authority id // mapping has already been sent all messages it's meant to get for that block and // all in-scope prior blocks. In case, we just learnt about its peer_id - // authorithy-id mapping we have to retry sending the messages that should be sent + // authority-id mapping we have to retry sending the messages that should be sent // to it for all un-finalized blocks. if entry.known_by.contains_key(&peer_id) && !retry_known_blocks { break @@ -2199,7 +2199,7 @@ impl State { sanitized_assignments } - // Filter out obviously invalid candidate indicies. + // Filter out obviously invalid candidate indices. async fn sanitize_v1_approvals( &mut self, peer_id: PeerId, @@ -2226,7 +2226,7 @@ impl State { sanitized_approvals } - // Filter out obviously invalid candidate indicies. + // Filter out obviously invalid candidate indices. async fn sanitize_v2_approvals( &mut self, peer_id: PeerId, @@ -2260,7 +2260,7 @@ impl State { // The modifier accepts as inputs the current required-routing state, whether // the message is locally originating, and the validator index of the message issuer. // -// Then, if the topology is known, this progates messages to all peers in the required +// Then, if the topology is known, this propagates messages to all peers in the required // routing set which are aware of the block. Peers which are unaware of the block // will have the message sent when it enters their view in `unify_with_peer`. // @@ -2440,7 +2440,7 @@ impl ApprovalDistribution { gum::trace!(target: LOG_TARGET, "active leaves signal (ignored)"); // the relay chain blocks relevant to the approval subsystems // are those that are available, but not finalized yet - // actived and deactivated heads hence are irrelevant to this subsystem, other than + // activated and deactivated heads hence are irrelevant to this subsystem, other than // for tracing purposes. if let Some(activated) = update.activated { let head = activated.hash; diff --git a/polkadot/node/network/approval-distribution/src/metrics.rs b/polkadot/node/network/approval-distribution/src/metrics.rs index 0642b1b2e0c..60c7f2f6d3b 100644 --- a/polkadot/node/network/approval-distribution/src/metrics.rs +++ b/polkadot/node/network/approval-distribution/src/metrics.rs @@ -299,7 +299,7 @@ impl MetricsTrait for Metrics { prometheus::CounterVec::new( prometheus::Opts::new( "polkadot_parachain_assignments_received_result", - "Result of a processed assignement", + "Result of a processed assignment", ), &["status"] )?, diff --git a/polkadot/node/network/approval-distribution/src/tests.rs b/polkadot/node/network/approval-distribution/src/tests.rs index 6c88dd53ad3..3159fe2ae5e 100644 --- a/polkadot/node/network/approval-distribution/src/tests.rs +++ b/polkadot/node/network/approval-distribution/src/tests.rs @@ -394,7 +394,7 @@ fn try_import_the_same_assignment() { setup_peer_with_view(overseer, &peer_b, view![hash], ValidationVersion::V1).await; setup_peer_with_view(overseer, &peer_c, view![hash], ValidationVersion::V1).await; - // Set up a gossip topology, where a, b, c and d are topology neighboors to the node under + // Set up a gossip topology, where a, b, c and d are topology neighbors to the node under // testing. let peers_with_optional_peer_id = peers .iter() @@ -491,7 +491,7 @@ fn try_import_the_same_assignment_v2() { setup_peer_with_view(overseer, &peer_b, view![hash], ValidationVersion::V3).await; setup_peer_with_view(overseer, &peer_c, view![hash], ValidationVersion::V3).await; - // Set up a gossip topology, where a, b, c and d are topology neighboors to the node under + // Set up a gossip topology, where a, b, c and d are topology neighbors to the node under // testing. let peers_with_optional_peer_id = peers .iter() @@ -744,7 +744,7 @@ fn peer_sending_us_the_same_we_just_sent_them_is_ok() { .iter() .map(|(peer_id, authority)| (Some(*peer_id), authority.clone())) .collect_vec(); - // Setup a topology where peer_a is neigboor to current node. + // Setup a topology where peer_a is neighbor to current node. setup_gossip_topology( overseer, make_gossip_topology(1, &peers_with_optional_peer_id, &[0], &[2], 1), @@ -850,7 +850,7 @@ fn import_approval_happy_path_v1_v2_peers() { .iter() .map(|(peer_id, authority)| (Some(*peer_id), authority.clone())) .collect_vec(); - // Set up a gossip topology, where a, b, and c are topology neighboors to the node. + // Set up a gossip topology, where a, b, and c are topology neighbors to the node. setup_gossip_topology( overseer, make_gossip_topology(1, &peers_with_optional_peer_id, &[0, 1], &[2, 4], 3), @@ -972,7 +972,7 @@ fn import_approval_happy_path_v2() { .iter() .map(|(peer_id, authority)| (Some(*peer_id), authority.clone())) .collect_vec(); - // Set up a gossip topology, where a, b, and c are topology neighboors to the node. + // Set up a gossip topology, where a, b, and c are topology neighbors to the node. setup_gossip_topology( overseer, make_gossip_topology(1, &peers_with_optional_peer_id, &[0, 1], &[2, 4], 3), @@ -1083,7 +1083,7 @@ fn multiple_assignments_covered_with_one_approval_vote() { .iter() .map(|(peer_id, authority)| (Some(*peer_id), authority.clone())) .collect_vec(); - // Set up a gossip topology, where a, b, and c, d are topology neighboors to the node. + // Set up a gossip topology, where a, b, and c, d are topology neighbors to the node. setup_gossip_topology( overseer, make_gossip_topology(1, &peers_with_optional_peer_id, &[0, 1], &[2, 4], 3), @@ -1273,7 +1273,7 @@ fn unify_with_peer_multiple_assignments_covered_with_one_approval_vote() { .iter() .map(|(peer_id, authority)| (Some(*peer_id), authority.clone())) .collect_vec(); - // Set up a gossip topology, where a, b, and c, d are topology neighboors to the node. + // Set up a gossip topology, where a, b, and c, d are topology neighbors to the node. setup_gossip_topology( overseer, make_gossip_topology(1, &peers_with_optional_peer_id, &[0, 1], &[2, 4], 3), @@ -1631,7 +1631,7 @@ fn update_peer_view() { .iter() .map(|(peer_id, authority)| (Some(*peer_id), authority.clone())) .collect_vec(); - // Setup a topology where peer_a is neigboor to current node. + // Setup a topology where peer_a is neighbor to current node. setup_gossip_topology( overseer, make_gossip_topology(1, &peers_with_optional_peer_id, &[0], &[2], 1), @@ -1758,7 +1758,7 @@ fn update_peer_view() { assert!(state.blocks.get(&hash_c).unwrap().known_by.get(peer).is_none()); } -// Tests that updating the known peer_id for a given authorithy updates the topology +// Tests that updating the known peer_id for a given authority updates the topology // and sends the required messages #[test] fn update_peer_authority_id() { @@ -1770,9 +1770,9 @@ fn update_peer_authority_id() { let neighbour_x_index = 0; let neighbour_y_index = 2; let local_index = 1; - // X neighbour, we simulate that PeerId is not known in the beginining. + // X neighbour, we simulate that PeerId is not known in the beginning. let neighbour_x = peers.get(neighbour_x_index).unwrap().0; - // Y neighbour, we simulate that PeerId is not known in the beginining. + // Y neighbour, we simulate that PeerId is not known in the beginning. let neighbour_y = peers.get(neighbour_y_index).unwrap().0; let _state = test_harness(State::default(), |mut virtual_overseer| async move { @@ -1814,7 +1814,7 @@ fn update_peer_authority_id() { }) .collect_vec(); - // Setup a topology where peer_a is neigboor to current node. + // Setup a topology where peer_a is neighbor to current node. setup_gossip_topology( overseer, make_gossip_topology( @@ -2053,7 +2053,7 @@ fn sends_assignments_even_when_state_is_approved() { .iter() .map(|(peer_id, authority)| (Some(*peer_id), authority.clone())) .collect_vec(); - // Setup a topology where peer_a is neigboor to current node. + // Setup a topology where peer_a is neighbor to current node. setup_gossip_topology( overseer, make_gossip_topology(1, &peers_with_optional_peer_id, &[0], &[2], 1), @@ -2125,7 +2125,7 @@ fn sends_assignments_even_when_state_is_approved() { } /// Same as `sends_assignments_even_when_state_is_approved_v2` but with `VRFModuloCompact` -/// assignemnts. +/// assignments. #[test] fn sends_assignments_even_when_state_is_approved_v2() { let peers = make_peers_and_authority_ids(8); @@ -2153,7 +2153,7 @@ fn sends_assignments_even_when_state_is_approved_v2() { .iter() .map(|(peer_id, authority)| (Some(*peer_id), authority.clone())) .collect_vec(); - // Setup a topology where peer_a is neigboor to current node. + // Setup a topology where peer_a is neighbor to current node. setup_gossip_topology( overseer, make_gossip_topology(1, &peers_with_optional_peer_id, &[0], &[2], 1), @@ -3509,7 +3509,7 @@ fn import_versioned_approval() { setup_peer_with_view(overseer, &peer_b, view![hash], ValidationVersion::V1).await; setup_peer_with_view(overseer, &peer_c, view![hash], ValidationVersion::V2).await; - // Set up a gossip topology, where a, b, c and d are topology neighboors to the node under + // Set up a gossip topology, where a, b, c and d are topology neighbors to the node under // testing. let peers_with_optional_peer_id = peers .iter() diff --git a/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs b/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs index 191ee2acd97..f478defcaa9 100644 --- a/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs +++ b/polkadot/node/network/availability-distribution/src/requester/fetch_task/mod.rs @@ -348,7 +348,7 @@ impl RunningTask { async fn do_request( &mut self, validator: &AuthorityDiscoveryId, - nerwork_error_freq: &mut gum::Freq, + network_error_freq: &mut gum::Freq, canceled_freq: &mut gum::Freq, ) -> std::result::Result { gum::trace!( @@ -395,7 +395,7 @@ impl RunningTask { }, Err(RequestError::NetworkError(err)) => { gum::warn_if_frequent!( - freq: nerwork_error_freq, + freq: network_error_freq, max_rate: gum::Times::PerHour(100), target: LOG_TARGET, origin = ?validator, diff --git a/polkadot/node/network/availability-recovery/src/lib.rs b/polkadot/node/network/availability-recovery/src/lib.rs index fb8064878f4..94b9d9546cd 100644 --- a/polkadot/node/network/availability-recovery/src/lib.rs +++ b/polkadot/node/network/availability-recovery/src/lib.rs @@ -408,7 +408,7 @@ async fn handle_recover( ) -> error::Result<()> { let candidate_hash = receipt.hash(); - let span = jaeger::Span::new(candidate_hash, "availbility-recovery") + let span = jaeger::Span::new(candidate_hash, "availability-recovery") .with_stage(jaeger::Stage::AvailabilityRecovery); if let Some(result) = diff --git a/polkadot/node/network/availability-recovery/src/metrics.rs b/polkadot/node/network/availability-recovery/src/metrics.rs index d82a8f9ae5f..9f4cddc57e4 100644 --- a/polkadot/node/network/availability-recovery/src/metrics.rs +++ b/polkadot/node/network/availability-recovery/src/metrics.rs @@ -31,7 +31,7 @@ struct MetricsInner { chunk_requests_issued: Counter, /// Total number of bytes recovered /// - /// Gets incremented on each succesful recovery + /// Gets incremented on each successful recovery recovered_bytes_total: Counter, /// A counter for finished chunk requests. /// @@ -232,7 +232,7 @@ impl metrics::Metrics for Metrics { )?, full_recoveries_started: prometheus::register( Counter::new( - "polkadot_parachain_availability_recovery_recovieries_started", + "polkadot_parachain_availability_recovery_recoveries_started", "Total number of started recoveries.", )?, registry, diff --git a/polkadot/node/network/bitfield-distribution/src/metrics.rs b/polkadot/node/network/bitfield-distribution/src/metrics.rs index 71d8a01300f..bd956bcbe4a 100644 --- a/polkadot/node/network/bitfield-distribution/src/metrics.rs +++ b/polkadot/node/network/bitfield-distribution/src/metrics.rs @@ -69,14 +69,14 @@ impl MetricsTrait for Metrics { let metrics = MetricsInner { sent_own_availability_bitfields: prometheus::register( prometheus::Counter::new( - "polkadot_parachain_sent_own_availabilty_bitfields_total", + "polkadot_parachain_sent_own_availability_bitfields_total", "Number of own availability bitfields sent to other peers.", )?, registry, )?, received_availability_bitfields: prometheus::register( prometheus::Counter::new( - "polkadot_parachain_received_availabilty_bitfields_total", + "polkadot_parachain_received_availability_bitfields_total", "Number of valid availability bitfields received from other peers.", )?, registry, diff --git a/polkadot/node/network/bitfield-distribution/src/tests.rs b/polkadot/node/network/bitfield-distribution/src/tests.rs index ba2434ea47d..188b51ebccc 100644 --- a/polkadot/node/network/bitfield-distribution/src/tests.rs +++ b/polkadot/node/network/bitfield-distribution/src/tests.rs @@ -150,7 +150,7 @@ fn receive_invalid_signature() { let signing_context = SigningContext { session_index: 1, parent_hash: hash_a }; - // another validator not part of the validatorset + // another validator not part of the validator set let keystore: KeystorePtr = Arc::new(MemoryKeystore::new()); let malicious = Keystore::sr25519_generate_new(&*keystore, ValidatorId::ID, None) .expect("Malicious key created"); diff --git a/polkadot/node/network/dispute-distribution/src/sender/mod.rs b/polkadot/node/network/dispute-distribution/src/sender/mod.rs index f4acc72318a..8187f20146c 100644 --- a/polkadot/node/network/dispute-distribution/src/sender/mod.rs +++ b/polkadot/node/network/dispute-distribution/src/sender/mod.rs @@ -76,7 +76,7 @@ pub struct DisputeSender { /// Value is the hash that was used for the query. active_sessions: HashMap, - /// All ongoing dispute sendings this subsystem is aware of. + /// All ongoing dispute sending this subsystem is aware of. /// /// Using an `IndexMap` so items can be iterated in the order of insertion. disputes: IndexMap>, @@ -105,7 +105,7 @@ struct WaitForActiveDisputesState { #[overseer::contextbounds(DisputeDistribution, prefix = self::overseer)] impl DisputeSender { - /// Create a new `DisputeSender` which can be used to start dispute sendings. + /// Create a new `DisputeSender` which can be used to start dispute sending. pub fn new(tx: NestingSender, metrics: Metrics) -> Self { Self { active_heads: Vec::new(), @@ -362,7 +362,7 @@ async fn get_active_session_indices( runtime: &mut RuntimeInfo, active_heads: &Vec, ) -> Result> { - let mut indeces = HashMap::new(); + let mut indices = HashMap::new(); // Iterate all heads we track as active and fetch the child' session indices. for head in active_heads { let session_index = runtime.get_session_index_for_child(ctx.sender(), *head).await?; @@ -372,9 +372,9 @@ async fn get_active_session_indices( { gum::debug!(target: LOG_TARGET, ?err, ?session_index, "Can't cache SessionInfo"); } - indeces.insert(session_index, *head); + indices.insert(session_index, *head); } - Ok(indeces) + Ok(indices) } /// Retrieve Set of active disputes from the dispute coordinator. diff --git a/polkadot/node/network/dispute-distribution/src/tests/mock.rs b/polkadot/node/network/dispute-distribution/src/tests/mock.rs index e6a49f14c09..ccc050233e8 100644 --- a/polkadot/node/network/dispute-distribution/src/tests/mock.rs +++ b/polkadot/node/network/dispute-distribution/src/tests/mock.rs @@ -163,7 +163,7 @@ pub fn make_dispute_message( let invalid_vote = make_explicit_signed(MOCK_VALIDATORS[invalid_validator.0 as usize], candidate_hash, false); gum::trace!( - "Passed time for invald vote: {:#?}", + "Passed time for invalid vote: {:#?}", Instant::now().saturating_duration_since(before_request) ); DisputeMessage::from_signed_statements( diff --git a/polkadot/node/network/gossip-support/src/tests.rs b/polkadot/node/network/gossip-support/src/tests.rs index 6817c85f98d..cce78df38f3 100644 --- a/polkadot/node/network/gossip-support/src/tests.rs +++ b/polkadot/node/network/gossip-support/src/tests.rs @@ -122,7 +122,7 @@ impl MockAuthorityDiscovery { self.authorities.lock().clone() } - fn add_more_authorties( + fn add_more_authorities( &self, new_known: Vec, ) -> HashMap> { @@ -720,7 +720,7 @@ fn issues_update_authorities_after_session() { assert!(overseer.recv().timeout(TIMEOUT).await.is_none()); // 4. Connect more authorities except one - let newly_added = authority_discovery_mock.add_more_authorties(unknown_at_session); + let newly_added = authority_discovery_mock.add_more_authorities(unknown_at_session); let mut newly_added_iter = newly_added.iter(); let unconnected_at_last_retry = newly_added_iter .next() diff --git a/polkadot/node/network/protocol/src/grid_topology.rs b/polkadot/node/network/protocol/src/grid_topology.rs index 3c4372a27a2..a14d2461072 100644 --- a/polkadot/node/network/protocol/src/grid_topology.rs +++ b/polkadot/node/network/protocol/src/grid_topology.rs @@ -89,7 +89,7 @@ impl SessionGridTopology { SessionGridTopology { shuffled_indices, canonical_shuffling, peer_ids } } - /// Updates the known peer ids for the passed authorithies ids. + /// Updates the known peer ids for the passed authorities ids. pub fn update_authority_ids( &mut self, peer_id: PeerId, @@ -313,7 +313,7 @@ impl SessionGridTopologyEntry { self.topology.is_validator(peer) } - /// Updates the known peer ids for the passed authorithies ids. + /// Updates the known peer ids for the passed authorities ids. pub fn update_authority_ids( &mut self, peer_id: PeerId, @@ -345,7 +345,7 @@ impl SessionGridTopologies { self.inner.get(&session).and_then(|val| val.0.as_ref()) } - /// Updates the known peer ids for the passed authorithies ids. + /// Updates the known peer ids for the passed authorities ids. pub fn update_authority_ids( &mut self, peer_id: PeerId, diff --git a/polkadot/node/network/protocol/src/lib.rs b/polkadot/node/network/protocol/src/lib.rs index 7a0ff9f4fa9..4dd94b5eac4 100644 --- a/polkadot/node/network/protocol/src/lib.rs +++ b/polkadot/node/network/protocol/src/lib.rs @@ -871,7 +871,7 @@ pub mod v2 { } /// v3 network protocol types. -/// Purpose is for chaning ApprovalDistributionMessage to +/// Purpose is for changing ApprovalDistributionMessage to /// include more than one assignment and approval in a message. pub mod v3 { use parity_scale_codec::{Decode, Encode}; diff --git a/polkadot/node/network/protocol/src/peer_set.rs b/polkadot/node/network/protocol/src/peer_set.rs index cb329607ad6..d0ae5b4a1bf 100644 --- a/polkadot/node/network/protocol/src/peer_set.rs +++ b/polkadot/node/network/protocol/src/peer_set.rs @@ -234,7 +234,7 @@ pub enum ValidationVersion { /// The second version. V2 = 2, /// The third version where changes to ApprovalDistributionMessage had been made. - /// The changes are translatable to V2 format untill assignments v2 and approvals + /// The changes are translatable to V2 format until assignments v2 and approvals /// coalescing is enabled through a runtime upgrade. V3 = 3, } diff --git a/polkadot/node/network/protocol/src/request_response/incoming/mod.rs b/polkadot/node/network/protocol/src/request_response/incoming/mod.rs index 44554483867..1d7c4a63e0c 100644 --- a/polkadot/node/network/protocol/src/request_response/incoming/mod.rs +++ b/polkadot/node/network/protocol/src/request_response/incoming/mod.rs @@ -47,7 +47,7 @@ where Req: IsRequest + Decode + Encode, Req::Response: Encode, { - /// Create configuration for `NetworkConfiguration::request_response_porotocols` and a + /// Create configuration for `NetworkConfiguration::request_response_protocols` and a /// corresponding typed receiver. /// /// This Register that config with substrate networking and receive incoming requests via the diff --git a/polkadot/node/network/protocol/src/request_response/mod.rs b/polkadot/node/network/protocol/src/request_response/mod.rs index 2fb62f56d10..87217bf084f 100644 --- a/polkadot/node/network/protocol/src/request_response/mod.rs +++ b/polkadot/node/network/protocol/src/request_response/mod.rs @@ -287,7 +287,7 @@ impl Protocol { match self { // Hundreds of validators will start requesting their chunks once they see a candidate // awaiting availability on chain. Given that they will see that block at different - // times (due to network delays), 100 seems big enough to accomodate for "bursts", + // times (due to network delays), 100 seems big enough to accommodate for "bursts", // assuming we can service requests relatively quickly, which would need to be measured // as well. Protocol::ChunkFetchingV1 => 100, diff --git a/polkadot/node/network/protocol/src/request_response/v1.rs b/polkadot/node/network/protocol/src/request_response/v1.rs index ba29b32c4ce..60eecb69f73 100644 --- a/polkadot/node/network/protocol/src/request_response/v1.rs +++ b/polkadot/node/network/protocol/src/request_response/v1.rs @@ -183,7 +183,7 @@ impl IsRequest for AvailableDataFetchingRequest { pub struct StatementFetchingRequest { /// Data needed to locate and identify the needed statement. pub relay_parent: Hash, - /// Hash of candidate that was used create the `CommitedCandidateRecept`. + /// Hash of candidate that was used create the `CommittedCandidateReceipt`. pub candidate_hash: CandidateHash, } diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/responder.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/responder.rs index 81e226c4ff8..8d1683759a0 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/responder.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/responder.rs @@ -64,7 +64,7 @@ pub async fn respond( // late, as each requester having the data will help distributing it. // 2. If we take too long, the requests timing out will not yet have had any data sent, thus // we wasted no bandwidth. - // 3. If the queue is full, requestes will get an immediate error instead of running in a + // 3. If the queue is full, requests will get an immediate error instead of running in a // timeout, thus requesters can immediately try another peer and be faster. // // From this perspective we would not want parallel response sending at all, but we don't diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs index 2766ec9815a..08e9d69d8ee 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs @@ -1494,7 +1494,7 @@ fn receiving_large_statement_from_one_sends_to_another_and_to_candidate_backing( Err(()) => {} ); - // And now the succeding request from peer_b: + // And now the succeeding request from peer_b: let (pending_response, response_rx) = oneshot::channel(); let inner_req = StatementFetchingRequest { relay_parent: metadata.relay_parent, diff --git a/polkadot/node/network/statement-distribution/src/v2/cluster.rs b/polkadot/node/network/statement-distribution/src/v2/cluster.rs index c09916e5620..87cdc389cb3 100644 --- a/polkadot/node/network/statement-distribution/src/v2/cluster.rs +++ b/polkadot/node/network/statement-distribution/src/v2/cluster.rs @@ -430,8 +430,8 @@ impl ClusterTracker { /// /// Normally we should not have pending statements to validators in our cluster, /// but if we do for all validators in our cluster, then we don't participate - /// in backing. Ocasional pending statements are expected if two authorities - /// can't detect each otehr or after restart, where it takes a while to discover + /// in backing. Occasional pending statements are expected if two authorities + /// can't detect each other or after restart, where it takes a while to discover /// the whole network. pub fn warn_if_too_many_pending_statements(&self, parent_hash: Hash) { diff --git a/polkadot/node/network/statement-distribution/src/v2/mod.rs b/polkadot/node/network/statement-distribution/src/v2/mod.rs index 2c9cdba4ea8..d782e37f10b 100644 --- a/polkadot/node/network/statement-distribution/src/v2/mod.rs +++ b/polkadot/node/network/statement-distribution/src/v2/mod.rs @@ -112,7 +112,7 @@ const COST_EXCESSIVE_SECONDED: Rep = Rep::CostMinor("Sent Excessive `Seconded` S const COST_DISABLED_VALIDATOR: Rep = Rep::CostMinor("Sent a statement from a disabled validator"); const COST_UNEXPECTED_MANIFEST_MISSING_KNOWLEDGE: Rep = - Rep::CostMinor("Unexpected Manifest, missing knowlege for relay parent"); + Rep::CostMinor("Unexpected Manifest, missing knowledge for relay parent"); const COST_UNEXPECTED_MANIFEST_DISALLOWED: Rep = Rep::CostMinor("Unexpected Manifest, Peer Disallowed"); const COST_UNEXPECTED_MANIFEST_PEER_UNKNOWN: Rep = @@ -628,8 +628,8 @@ pub(crate) async fn handle_active_leaves_update( request_min_backing_votes(new_relay_parent, session_index, ctx.sender()).await?; let mut per_session_state = PerSessionState::new(session_info, &state.keystore, minimum_backing_votes); - if let Some(toplogy) = state.unused_topologies.remove(&session_index) { - per_session_state.supply_topology(&toplogy.topology, toplogy.local_index); + if let Some(topology) = state.unused_topologies.remove(&session_index) { + per_session_state.supply_topology(&topology.topology, topology.local_index); } state.per_session.insert(session_index, per_session_state); } diff --git a/polkadot/node/network/statement-distribution/src/v2/requests.rs b/polkadot/node/network/statement-distribution/src/v2/requests.rs index bbcb268415e..fe270c8a58e 100644 --- a/polkadot/node/network/statement-distribution/src/v2/requests.rs +++ b/polkadot/node/network/statement-distribution/src/v2/requests.rs @@ -320,7 +320,7 @@ impl RequestManager { // need for the current node to limit itself to the same amount the // requests, because the requests are going to different nodes anyways. // While looking at https://github.com/paritytech/polkadot-sdk/issues/3314, - // found out that this requests take around 100ms to fullfill, so it + // found out that this requests take around 100ms to fulfill, so it // would make sense to try to request things as early as we can, given // we would need to request it for each candidate, around 25 right now // on kusama. diff --git a/polkadot/node/overseer/src/lib.rs b/polkadot/node/overseer/src/lib.rs index e16a3fd27ab..167b32a15bc 100644 --- a/polkadot/node/overseer/src/lib.rs +++ b/polkadot/node/overseer/src/lib.rs @@ -871,7 +871,7 @@ where gum::trace!( target: LOG_TARGET, relay_parent = ?hash, - "Leaf got activated, notifying exterinal listeners" + "Leaf got activated, notifying external listeners" ); for listener in listeners { // it's fine if the listener is no longer interested diff --git a/polkadot/node/primitives/src/approval.rs b/polkadot/node/primitives/src/approval.rs index f2a79e025af..b73cb4c717d 100644 --- a/polkadot/node/primitives/src/approval.rs +++ b/polkadot/node/primitives/src/approval.rs @@ -382,7 +382,7 @@ pub mod v2 { /// The core index chosen in this cert. core_index: CoreIndex, }, - /// Deprectated assignment. Soon to be removed. + /// Deprecated assignment. Soon to be removed. /// An assignment story based on the VRF that authorized the relay-chain block where the /// candidate was included combined with a sample number. /// diff --git a/polkadot/node/primitives/src/disputes/mod.rs b/polkadot/node/primitives/src/disputes/mod.rs index 768b95f6553..5814ecee44f 100644 --- a/polkadot/node/primitives/src/disputes/mod.rs +++ b/polkadot/node/primitives/src/disputes/mod.rs @@ -84,7 +84,7 @@ impl CandidateVotes { #[derive(Debug, Clone)] /// Valid candidate votes. /// -/// Prefere backing votes over other votes. +/// Prefer backing votes over other votes. pub struct ValidCandidateVotes { votes: BTreeMap, } @@ -133,7 +133,7 @@ impl ValidCandidateVotes { self.votes.retain(f) } - /// Get all the validator indeces we have votes for. + /// Get all the validator indices we have votes for. pub fn keys( &self, ) -> Bkeys<'_, ValidatorIndex, (ValidDisputeStatementKind, ValidatorSignature)> { diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index b6556e0be56..b102cf06c38 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -74,7 +74,7 @@ pub const VALIDATION_CODE_BOMB_LIMIT: usize = (MAX_CODE_SIZE * 4u32) as usize; pub const POV_BOMB_LIMIT: usize = (MAX_POV_SIZE * 4u32) as usize; /// How many blocks after finalization an information about backed/included candidate should be -/// pre-loaded (when scraoing onchain votes) and kept locally (when pruning). +/// pre-loaded (when scraping onchain votes) and kept locally (when pruning). /// /// We don't want to remove scraped candidates on finalization because we want to /// be sure that disputes will conclude on abandoned forks. diff --git a/polkadot/node/service/src/overseer.rs b/polkadot/node/service/src/overseer.rs index a8167370464..9575b2458a2 100644 --- a/polkadot/node/service/src/overseer.rs +++ b/polkadot/node/service/src/overseer.rs @@ -77,7 +77,7 @@ pub struct OverseerGenArgs<'a, Spawner, RuntimeClient> where Spawner: 'static + SpawnNamed + Clone + Unpin, { - /// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others. + /// Runtime client generic, providing the `ProvideRuntimeApi` trait besides others. pub runtime_client: Arc, /// Underlying network service implementation. pub network_service: Arc>, diff --git a/polkadot/node/service/src/parachains_db/upgrade.rs b/polkadot/node/service/src/parachains_db/upgrade.rs index 2eceb391b15..4d737085960 100644 --- a/polkadot/node/service/src/parachains_db/upgrade.rs +++ b/polkadot/node/service/src/parachains_db/upgrade.rs @@ -115,7 +115,7 @@ pub(crate) fn try_upgrade_db_to_next_version( Some(CURRENT_VERSION) => CURRENT_VERSION, // This is an arbitrary future version, we don't handle it. Some(v) => return Err(Error::FutureVersion { current: CURRENT_VERSION, got: v }), - // No version file. For `RocksDB` we dont need to do anything. + // No version file. For `RocksDB` we don't need to do anything. None if db_kind == DatabaseKind::RocksDB => CURRENT_VERSION, // No version file. `ParityDB` did not previously have a version defined. // We handle this as a `0 -> 1` migration. @@ -183,7 +183,7 @@ fn migrate_from_version_1_to_2(path: &Path, db_kind: DatabaseKind) -> Result { // The total lag accounting for disputes. let lag_disputes = initial_leaf_number.saturating_sub(subchain_number); diff --git a/polkadot/node/subsystem-bench/grafana/availability-read.json b/polkadot/node/subsystem-bench/grafana/availability-read.json index 31c4ad3c795..96a83d2d70f 100644 --- a/polkadot/node/subsystem-bench/grafana/availability-read.json +++ b/polkadot/node/subsystem-bench/grafana/availability-read.json @@ -119,7 +119,7 @@ "editorMode": "code", "expr": "subsystem_benchmark_n_validators{}", "instant": false, - "legendFormat": "n_vaidators", + "legendFormat": "n_validators", "range": true, "refId": "A" }, @@ -1046,7 +1046,7 @@ "refId": "A" } ], - "title": "Availability subystem metrics", + "title": "Availability subsystem metrics", "type": "row" }, { @@ -1397,7 +1397,7 @@ "refId": "B" } ], - "title": "Recovery throughtput", + "title": "Recovery throughput", "transformations": [], "type": "timeseries" }, diff --git a/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs b/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs index c1b31a509f6..3b08d0ed861 100644 --- a/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/message_generator.rs @@ -74,8 +74,8 @@ pub struct PeerMessagesGenerator { pub validator_index: ValidatorIndex, /// An array of pre-generated random samplings, that is used to determine, which nodes would /// send a given assignment, to the node under test because of the random samplings. - /// As an optimization we generate this sampling at the begining of the test and just pick - /// one randomly, because always taking the samples would be too expensive for benchamrk. + /// As an optimization we generate this sampling at the beginning of the test and just pick + /// one randomly, because always taking the samples would be too expensive for benchmark. pub random_samplings: Vec>, /// Channel for sending the generated messages to the aggregator pub tx_messages: futures::channel::mpsc::UnboundedSender<(Hash, Vec)>, @@ -234,7 +234,7 @@ impl PeerMessagesGenerator { let all_messages = all_messages .into_iter() .flat_map(|(_, mut messages)| { - // Shuffle the messages inside the same tick, so that we don't priorites messages + // Shuffle the messages inside the same tick, so that we don't priorities messages // for older nodes. we try to simulate the same behaviour as in real world. messages.shuffle(&mut rand_chacha); messages @@ -560,12 +560,12 @@ struct TestSignInfo { candidate_index: CandidateIndex, /// The validator sending the assignments validator_index: ValidatorIndex, - /// The assignments convering this candidate + /// The assignments covering this candidate assignment: TestMessageInfo, } impl TestSignInfo { - /// Helper function to create a signture for all candidates in `to_sign` parameter. + /// Helper function to create a signature for all candidates in `to_sign` parameter. /// Returns a TestMessage fn sign_candidates( to_sign: &mut Vec, diff --git a/polkadot/node/subsystem-bench/src/lib/approval/mod.rs b/polkadot/node/subsystem-bench/src/lib/approval/mod.rs index 450faf06123..6ab5b86baed 100644 --- a/polkadot/node/subsystem-bench/src/lib/approval/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/mod.rs @@ -115,7 +115,7 @@ pub struct ApprovalsOptions { #[clap(short, long, default_value_t = 1.0)] /// Max candidate to be signed in a single approval. pub coalesce_std_dev: f32, - /// The maximum tranche diff between approvals coalesced toghther. + /// The maximum tranche diff between approvals coalesced together. pub coalesce_tranche_diff: u32, #[clap(short, long, default_value_t = false)] /// Enable assignments v2. @@ -170,7 +170,7 @@ struct BlockTestData { total_candidates_before: u64, /// The votes we sent. /// votes[validator_index][candidate_index] tells if validator sent vote for candidate. - /// We use this to mark the test as succesfull if GetApprovalSignatures returns all the votes + /// We use this to mark the test as successful if GetApprovalSignatures returns all the votes /// from here. votes: Arc>>, } @@ -237,7 +237,7 @@ struct GeneratedState { } /// Approval test state used by all mock subsystems to be able to answer messages emitted -/// by the approval-voting and approval-distribution-subystems. +/// by the approval-voting and approval-distribution-subsystems. /// /// This gets cloned across all mock subsystems, so if there is any information that gets /// updated between subsystems, they would have to be wrapped in Arc's. @@ -498,7 +498,7 @@ struct PeerMessageProducer { impl PeerMessageProducer { /// Generates messages by spawning a blocking task in the background which begins creating - /// the assignments/approvals and peer view changes at the begining of each block. + /// the assignments/approvals and peer view changes at the beginning of each block. fn produce_messages( mut self, env: &TestEnvironment, @@ -740,7 +740,7 @@ impl PeerMessageProducer { } } - // Initializes the candidates test data. This is used for bookeeping if more assignments and + // Initializes the candidates test data. This is used for bookkeeping if more assignments and // approvals would be needed. fn initialize_candidates_test_data( &self, @@ -767,7 +767,7 @@ impl PeerMessageProducer { } /// Helper function to build an overseer with the real implementation for `ApprovalDistribution` and -/// `ApprovalVoting` subystems and mock subsytems for all others. +/// `ApprovalVoting` subsystems and mock subsystems for all others. fn build_overseer( state: &ApprovalTestState, network: &NetworkEmulatorHandle, @@ -936,7 +936,7 @@ pub async fn bench_approvals_run( for block_num in 0..env.config().num_blocks { let mut current_slot = tick_to_slot_number(SLOT_DURATION_MILLIS, system_clock.tick_now()); - // Wait untill the time arrieves at the first slot under test. + // Wait until the time arrives at the first slot under test. while current_slot < state.generated_state.initial_slot { sleep(Duration::from_millis(5)).await; current_slot = tick_to_slot_number(SLOT_DURATION_MILLIS, system_clock.tick_now()); @@ -961,7 +961,7 @@ pub async fn bench_approvals_run( } // Wait for all blocks to be approved before exiting. - // This is an invariant of the benchmark, if this does not happen something went teribbly wrong. + // This is an invariant of the benchmark, if this does not happen something went terribly wrong. while state.last_approved_block.load(std::sync::atomic::Ordering::SeqCst) < env.config().num_blocks as u32 { diff --git a/polkadot/node/subsystem-bench/src/lib/approval/test_message.rs b/polkadot/node/subsystem-bench/src/lib/approval/test_message.rs index 63e383509be..f55ed99205e 100644 --- a/polkadot/node/subsystem-bench/src/lib/approval/test_message.rs +++ b/polkadot/node/subsystem-bench/src/lib/approval/test_message.rs @@ -31,7 +31,7 @@ pub struct TestMessageInfo { pub msg: protocol_v3::ApprovalDistributionMessage, /// The list of peers that would sends this message in a real topology. /// It includes both the peers that would send the message because of the topology - /// or because of randomly chosing so. + /// or because of randomly choosing so. pub sent_by: Vec, /// The tranche at which this message should be sent. pub tranche: u32, @@ -90,7 +90,7 @@ impl MessagesBundle { /// Tells if the bundle is needed for sending. /// We either send it because we need more assignments and approvals to approve the candidates - /// or because we configured the test to send messages untill a given tranche. + /// or because we configured the test to send messages until a given tranche. pub fn should_send( &self, candidates_test_data: &HashMap<(Hash, CandidateIndex), CandidateTestData>, @@ -174,24 +174,24 @@ impl TestMessageInfo { } } - /// Returns a list of candidates indicies in this message + /// Returns a list of candidates indices in this message pub fn candidate_indices(&self) -> HashSet { - let mut unique_candidate_indicies = HashSet::new(); + let mut unique_candidate_indices = HashSet::new(); match &self.msg { protocol_v3::ApprovalDistributionMessage::Assignments(assignments) => for (_assignment, candidate_indices) in assignments { for candidate_index in candidate_indices.iter_ones() { - unique_candidate_indicies.insert(candidate_index); + unique_candidate_indices.insert(candidate_index); } }, protocol_v3::ApprovalDistributionMessage::Approvals(approvals) => for approval in approvals { for candidate_index in approval.candidate_indices.iter_ones() { - unique_candidate_indicies.insert(candidate_index); + unique_candidate_indices.insert(candidate_index); } }, } - unique_candidate_indicies + unique_candidate_indices } /// Marks this message as no-shows if the number of configured no-shows is above the registered diff --git a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs index 765afdd5912..fe986669061 100644 --- a/polkadot/node/subsystem-bench/src/lib/availability/mod.rs +++ b/polkadot/node/subsystem-bench/src/lib/availability/mod.rs @@ -69,7 +69,7 @@ const LOG_TARGET: &str = "subsystem-bench::availability"; pub struct DataAvailabilityReadOptions { #[clap(short, long, default_value_t = false)] /// Turbo boost AD Read by fetching the full availability datafrom backers first. Saves CPU as - /// we don't need to re-construct from chunks. Tipically this is only faster if nodes have + /// we don't need to re-construct from chunks. Typically this is only faster if nodes have /// enough bandwidth. pub fetch_from_backers: bool, } @@ -404,7 +404,7 @@ pub async fn benchmark_availability_write( let network = env.network().clone(); let authorities = env.authorities().clone(); - // Spawn a task that will generate `n_validator` - 1 signed bitfiends and + // Spawn a task that will generate `n_validator` - 1 signed bitfields and // send them from the emulated peers to the subsystem. // TODO: Implement topology. let messages = state.signed_bitfields.get(&relay_block_hash).expect("pregenerated").clone(); @@ -425,7 +425,7 @@ pub async fn benchmark_availability_write( // Wait for all bitfields to be processed. env.wait_until_metric( - "polkadot_parachain_received_availabilty_bitfields_total", + "polkadot_parachain_received_availability_bitfields_total", None, |value| value == (config.connected_count() * block_num) as f64, ) diff --git a/polkadot/node/subsystem-bench/src/lib/configuration.rs b/polkadot/node/subsystem-bench/src/lib/configuration.rs index 17c81c4fd35..5725a5137ec 100644 --- a/polkadot/node/subsystem-bench/src/lib/configuration.rs +++ b/polkadot/node/subsystem-bench/src/lib/configuration.rs @@ -122,10 +122,10 @@ pub struct TestConfiguration { /// Randomly sampled pov_sizes #[serde(skip)] pub pov_sizes: Vec, - /// The amount of bandiwdth remote validators have. + /// The amount of bandwidth remote validators have. #[serde(default = "default_bandwidth")] pub peer_bandwidth: usize, - /// The amount of bandiwdth our node has. + /// The amount of bandwidth our node has. #[serde(default = "default_bandwidth")] pub bandwidth: usize, /// Optional peer emulation latency (round trip time) wrt node under test @@ -205,7 +205,7 @@ impl TestConfiguration { let peer_id_to_authority = peer_ids .iter() .zip(validator_authority_id.iter()) - .map(|(peer_id, authorithy_id)| (*peer_id, authorithy_id.clone())) + .map(|(peer_id, authority_id)| (*peer_id, authority_id.clone())) .collect(); TestAuthorities { diff --git a/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs index 080644da92a..fba33523be8 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/av_store.rs @@ -39,7 +39,7 @@ pub struct AvailabilityStoreState { const LOG_TARGET: &str = "subsystem-bench::av-store-mock"; -/// Mockup helper. Contains Ccunks and full availability data of all parachain blocks +/// Mockup helper. Contains Chunks and full availability data of all parachain blocks /// used in a test. #[derive(Clone)] pub struct NetworkAvailabilityState { diff --git a/polkadot/node/subsystem-bench/src/lib/mock/chain_api.rs b/polkadot/node/subsystem-bench/src/lib/mock/chain_api.rs index bee15c3cefd..86b030fb6fd 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/chain_api.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/chain_api.rs @@ -89,7 +89,7 @@ impl MockChainApi { let hash = self .state .get_header_by_number(requested_number) - .expect("Unknow block number") + .expect("Unknown block number") .hash(); sender.send(Ok(Some(hash))).unwrap(); }, diff --git a/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs b/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs index d598f6447d3..ec66ad4e279 100644 --- a/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs +++ b/polkadot/node/subsystem-bench/src/lib/mock/network_bridge.rs @@ -42,8 +42,8 @@ pub struct MockNetworkBridgeTx { network: NetworkEmulatorHandle, /// A channel to the network interface, to_network_interface: UnboundedSender, - /// Test authorithies - test_authorithies: TestAuthorities, + /// Test authorities + test_authorities: TestAuthorities, } /// A mock of the network bridge tx subsystem. @@ -58,9 +58,9 @@ impl MockNetworkBridgeTx { pub fn new( network: NetworkEmulatorHandle, to_network_interface: UnboundedSender, - test_authorithies: TestAuthorities, + test_authorities: TestAuthorities, ) -> MockNetworkBridgeTx { - Self { network, to_network_interface, test_authorithies } + Self { network, to_network_interface, test_authorities } } } @@ -125,13 +125,13 @@ impl MockNetworkBridgeTx { } }, NetworkBridgeTxMessage::ReportPeer(_) => { - // ingore rep changes + // ignore rep changes }, NetworkBridgeTxMessage::SendValidationMessage(peers, message) => { for peer in peers { self.to_network_interface .unbounded_send(NetworkMessage::MessageFromNode( - self.test_authorithies + self.test_authorities .peer_id_to_authority .get(&peer) .unwrap() diff --git a/polkadot/node/subsystem-bench/src/lib/network.rs b/polkadot/node/subsystem-bench/src/lib/network.rs index 1bc35a014ff..0f7b7d741e7 100644 --- a/polkadot/node/subsystem-bench/src/lib/network.rs +++ b/polkadot/node/subsystem-bench/src/lib/network.rs @@ -154,7 +154,7 @@ pub enum NetworkMessage { MessageFromNode(AuthorityDiscoveryId, VersionedValidationProtocol), /// A request originating from our node RequestFromNode(AuthorityDiscoveryId, Requests), - /// A request originating from an emultated peer + /// A request originating from an emulated peer RequestFromPeer(IncomingRequest), } @@ -790,9 +790,9 @@ pub fn new_network( let connected_count = config.connected_count(); - let mut peers_indicies = (0..n_peers).collect_vec(); + let mut peers_indices = (0..n_peers).collect_vec(); let (_connected, to_disconnect) = - peers_indicies.partial_shuffle(&mut thread_rng(), connected_count); + peers_indices.partial_shuffle(&mut thread_rng(), connected_count); // Node under test is always mark as disconnected. peers[NODE_UNDER_TEST as usize].disconnect(); @@ -958,7 +958,7 @@ impl Metrics { .inc_by(bytes as u64); } - /// Increment total receioved for a peer. + /// Increment total received for a peer. pub fn on_peer_received(&self, peer_index: usize, bytes: usize) { self.peer_total_received .with_label_values(vec![format!("node{}", peer_index).as_str()].as_slice()) @@ -1041,7 +1041,7 @@ mod tests { async fn test_expected_rate() { let tick_rate = 200; let budget = 1_000_000; - // rate must not exceeed 100 credits per second + // rate must not exceed 100 credits per second let mut rate_limiter = RateLimit::new(tick_rate, budget); let mut total_sent = 0usize; let start = Instant::now(); diff --git a/polkadot/node/subsystem-bench/src/lib/utils.rs b/polkadot/node/subsystem-bench/src/lib/utils.rs new file mode 100644 index 00000000000..cd206d8f322 --- /dev/null +++ b/polkadot/node/subsystem-bench/src/lib/utils.rs @@ -0,0 +1,76 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Test utils + +use crate::usage::BenchmarkUsage; +use std::io::{stdout, Write}; + +pub struct WarmUpOptions<'a> { + /// The maximum number of runs considered for warming up. + pub warm_up: usize, + /// The number of runs considered for benchmarking. + pub bench: usize, + /// The difference in CPU usage between runs considered as normal + pub precision: f64, + /// The subsystems whose CPU usage is checked during warm-up cycles + pub subsystems: &'a [&'a str], +} + +impl<'a> WarmUpOptions<'a> { + pub fn new(subsystems: &'a [&'a str]) -> Self { + Self { warm_up: 100, bench: 3, precision: 0.02, subsystems } + } +} + +pub fn warm_up_and_benchmark( + options: WarmUpOptions, + run: impl Fn() -> BenchmarkUsage, +) -> Result { + println!("Warming up..."); + let mut usages = Vec::with_capacity(options.bench); + + for n in 1..=options.warm_up { + let curr = run(); + if let Some(prev) = usages.last() { + let diffs = options + .subsystems + .iter() + .map(|&v| { + curr.cpu_usage_diff(prev, v) + .ok_or(format!("{} not found in benchmark {:?}", v, prev)) + }) + .collect::, String>>()?; + if !diffs.iter().all(|&v| v < options.precision) { + usages.clear(); + } + } + usages.push(curr); + print!("\r{}%", n * 100 / options.warm_up); + if usages.len() == options.bench { + println!("\rTook {} runs to warm up", n.saturating_sub(options.bench)); + break; + } + stdout().flush().unwrap(); + } + + if usages.len() != options.bench { + println!("Didn't warm up after {} runs", options.warm_up); + return Err("Can't warm up".to_string()) + } + + Ok(BenchmarkUsage::average(&usages)) +} diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 92c35d1b7b9..5d05d2b56ed 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -805,7 +805,7 @@ pub enum StatementDistributionMessage { /// This data becomes intrinsics or extrinsics which should be included in a future relay chain /// block. -// It needs to be cloneable because multiple potential block authors can request copies. +// It needs to be clonable because multiple potential block authors can request copies. #[derive(Debug, Clone)] pub enum ProvisionableData { /// This bitfield indicates the availability of various candidate blocks. diff --git a/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs b/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs index c7b91bffb3d..d38d838fede 100644 --- a/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs +++ b/polkadot/node/subsystem-util/src/inclusion_emulator/mod.rs @@ -78,7 +78,7 @@ /// /// 2. The root fragment is invalid under the new constraints because it has been subsumed by /// the relay-chain. In this case, we can discard the root and split & re-root the fragment -/// tree under its descendents and compare to the new constraints again. This is the +/// tree under its descendants and compare to the new constraints again. This is the /// "prediction came true" case. /// /// 3. The root fragment is invalid under the new constraints because a competing parachain diff --git a/polkadot/node/subsystem-util/src/lib.rs b/polkadot/node/subsystem-util/src/lib.rs index aaae30db50c..6ff09ed5f22 100644 --- a/polkadot/node/subsystem-util/src/lib.rs +++ b/polkadot/node/subsystem-util/src/lib.rs @@ -382,7 +382,7 @@ pub fn signing_key_and_index<'a>( /// Sign the given data with the given validator ID. /// -/// Returns `Ok(None)` if the private key that correponds to that validator ID is not found in the +/// Returns `Ok(None)` if the private key that corresponds to that validator ID is not found in the /// given keystore. Returns an error if the key could not be used for signing. pub fn sign( keystore: &KeystorePtr, diff --git a/polkadot/primitives/src/v6/mod.rs b/polkadot/primitives/src/v6/mod.rs index 9e7f910314c..21cee753265 100644 --- a/polkadot/primitives/src/v6/mod.rs +++ b/polkadot/primitives/src/v6/mod.rs @@ -1457,7 +1457,7 @@ pub enum ValidDisputeStatementKind { #[codec(index = 3)] ApprovalChecking, /// An approval vote from the new version. - /// We can't create this version untill all nodes + /// We can't create this version until all nodes /// have been updated to support it and max_approval_coalesce_count /// is set to more than 1. #[codec(index = 4)] @@ -1604,7 +1604,7 @@ impl ValidityAttestation { pub fn to_compact_statement(&self, candidate_hash: CandidateHash) -> CompactStatement { // Explicit and implicit map directly from // `ValidityVote::Valid` and `ValidityVote::Issued`, and hence there is a - // `1:1` relationshow which enables the conversion. + // `1:1` relationship which enables the conversion. match *self { ValidityAttestation::Implicit(_) => CompactStatement::Seconded(candidate_hash), ValidityAttestation::Explicit(_) => CompactStatement::Valid(candidate_hash), diff --git a/polkadot/primitives/src/vstaging/mod.rs b/polkadot/primitives/src/vstaging/mod.rs index bd2a5106c44..94e9e892029 100644 --- a/polkadot/primitives/src/vstaging/mod.rs +++ b/polkadot/primitives/src/vstaging/mod.rs @@ -102,7 +102,7 @@ pub struct SchedulerParams { pub on_demand_fee_variability: Perbill, /// The minimum amount needed to claim a slot in the spot pricing queue. pub on_demand_base_fee: Balance, - /// The number of blocks a claim stays in the scheduler's claimqueue before getting cleared. + /// The number of blocks a claim stays in the scheduler's claim queue before getting cleared. /// This number should go reasonably higher than the number of blocks in the async backing /// lookahead. pub ttl: BlockNumber, @@ -133,7 +133,7 @@ pub type NodeFeatures = BitVec; /// Module containing feature-specific bit indices into the `NodeFeatures` bitvec. pub mod node_features { - /// A feature index used to indentify a bit into the node_features array stored + /// A feature index used to identify a bit into the node_features array stored /// in the HostConfiguration. #[repr(u8)] pub enum FeatureIndex { diff --git a/polkadot/primitives/test-helpers/src/lib.rs b/polkadot/primitives/test-helpers/src/lib.rs index b7c5d82341a..d43cf3317e5 100644 --- a/polkadot/primitives/test-helpers/src/lib.rs +++ b/polkadot/primitives/test-helpers/src/lib.rs @@ -249,7 +249,7 @@ pub fn resign_candidate_descriptor_with_collator>( descriptor.signature = signature; } -/// Extracts validators's public keus (`ValidatorId`) from `Sr25519Keyring` +/// Extracts validators's public keys (`ValidatorId`) from `Sr25519Keyring` pub fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec { val_ids.iter().map(|v| v.public().into()).collect() } diff --git a/polkadot/roadmap/implementers-guide/src/disputes-flow.md b/polkadot/roadmap/implementers-guide/src/disputes-flow.md index b5cc5611c6f..540b3c45bad 100644 --- a/polkadot/roadmap/implementers-guide/src/disputes-flow.md +++ b/polkadot/roadmap/implementers-guide/src/disputes-flow.md @@ -74,7 +74,7 @@ The set of validators eligible to vote consists of the validators that had duty votes by the backing validators. If a validator receives an initial dispute message (a set of votes where there are at least two opposing votes -contained), and the PoV or Code are hence not reconstructable from local storage, that validator must request the +contained), and the PoV or Code are hence not reconstructible from local storage, that validator must request the required data from its peers. The dispute availability message must contain code, persisted validation data, and the proof of validity. diff --git a/polkadot/roadmap/implementers-guide/src/node/approval/approval-distribution.md b/polkadot/roadmap/implementers-guide/src/node/approval/approval-distribution.md index ce71de6f76b..c987b7fe5be 100644 --- a/polkadot/roadmap/implementers-guide/src/node/approval/approval-distribution.md +++ b/polkadot/roadmap/implementers-guide/src/node/approval/approval-distribution.md @@ -101,7 +101,7 @@ struct State { } enum MessageFingerprint { - Assigment(Hash, u32, ValidatorIndex), + Assignment(Hash, u32, ValidatorIndex), Approval(Hash, u32, ValidatorIndex), } @@ -203,7 +203,7 @@ For all peers: * Compute `view_intersection` as the intersection of the peer's view blocks with the hashes of the new blocks. * Invoke `unify_with_peer(peer, view_intersection)`. -#### `ApprovalDistributionMessage::DistributeAsignment` +#### `ApprovalDistributionMessage::DistributeAssignment` Call `import_and_circulate_assignment` with `MessageSource::Local`. diff --git a/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md b/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md index e3bb14db3a5..c57c4589244 100644 --- a/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md +++ b/polkadot/roadmap/implementers-guide/src/node/availability/availability-recovery.md @@ -115,7 +115,7 @@ On `Conclude`, shut down the subsystem. Launch the source as a background task running `run(recovery_task)`. -#### `run(recovery_task) -> Result` +#### `run(recovery_task) -> Result` ```rust // How many parallel requests to have going at once. diff --git a/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md b/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md index e0738e219d1..90b29249f3e 100644 --- a/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md +++ b/polkadot/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md @@ -76,7 +76,7 @@ dispute is raised reconsider their vote and send an explicit invalid vote. If th recorded, then they could avoid a slash. This is not a problem for our basic security assumptions: The backers are the ones to be supposed to have skin in the -game, so we are not too woried about colluding approval voters getting away slash free as the gambler's ruin property is +game, so we are not too worried about colluding approval voters getting away slash free as the gambler's ruin property is maintained anyway. There is however a separate problem, from colluding approval-voters, that is "lazy" approval voters. If it were easy and reliable for approval-voters to reconsider their vote, in case of an actual dispute, then they don't have a direct incentive (apart from playing a part in securing the network) to properly run the validation function at @@ -331,13 +331,13 @@ off-chain. The reason for this is a dispute can be raised for a candidate in a p validator that is going to be slashed for it might not even be in the current active set. That means it can't be disabled on-chain. We need a way to prevent someone from disputing all valid candidates in the previous era. We do this by keeping track of the validators who lost a dispute in the past few sessions and use that list in addition to the -on-chain disabled validators state. In addition to past session misbehavior, this also heps in case a slash is delayed. +on-chain disabled validators state. In addition to past session misbehavior, this also helps in case a slash is delayed. When we receive a dispute statements set, we do the following: 1. Take the on-chain state of disabled validators at the relay parent block. 1. Take a list of those who lost a dispute in that session in the order that prioritizes the biggest and newest offence. 1. Combine the two lists and take the first byzantine threshold validators from it. -1. If the dispute is unconfimed, check if all votes against the candidate are from disabled validators. +1. If the dispute is unconfirmed, check if all votes against the candidate are from disabled validators. If so, we don't participate in the dispute, but record the votes. ### Backing Votes @@ -591,7 +591,7 @@ Initiates processing via the `Participation` module and updates the internal sta ### On `MuxedMessage::Participation` -This message is sent from `Participatuion` module and indicates a processed dispute participation. It's the result of +This message is sent from `Participation` module and indicates a processed dispute participation. It's the result of the processing job initiated with `OverseerSignal::ActiveLeaves`. The subsystem issues a `DisputeMessage` with the result. diff --git a/polkadot/roadmap/implementers-guide/src/node/overseer.md b/polkadot/roadmap/implementers-guide/src/node/overseer.md index 53a11530810..960539b8499 100644 --- a/polkadot/roadmap/implementers-guide/src/node/overseer.md +++ b/polkadot/roadmap/implementers-guide/src/node/overseer.md @@ -108,11 +108,11 @@ way that the receiving subsystem can further address the communication to one of This communication prevents a certain class of race conditions. When the Overseer determines that it is time for subsystems to begin working on top of a particular relay-parent, it will dispatch a `ActiveLeavesUpdate` message to all subsystems to do so, and those messages will be handled asynchronously by those subsystems. Some subsystems will receive -those messsages before others, and it is important that a message sent by subsystem A after receiving +those messages before others, and it is important that a message sent by subsystem A after receiving `ActiveLeavesUpdate` message will arrive at subsystem B after its `ActiveLeavesUpdate` message. If subsystem A maintained an independent channel with subsystem B to communicate, it would be possible for subsystem B to handle the side message before the `ActiveLeavesUpdate` message, but it wouldn't have any logical course of action to take with the -side message - leading to it being discarded or improperly handled. Well-architectured state machines should have a +side message - leading to it being discarded or improperly handled. Well-architected state machines should have a single source of inputs, so that is what we do here. One exception is reasonable to make for responses to requests. A request should be made via the overseer in order to diff --git a/polkadot/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md b/polkadot/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md index 7f6fef7ddf6..f8e88a67fcb 100644 --- a/polkadot/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md +++ b/polkadot/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md @@ -8,7 +8,7 @@ pre-checking. Head over to [overview] for the PVF pre-checking process overview. There is no dedicated input mechanism for PVF pre-checker. Instead, PVF pre-checker looks on the `ActiveLeavesUpdate` event stream for work. -This subsytem does not produce any output messages either. The subsystem will, however, send messages to the +This subsystem does not produce any output messages either. The subsystem will, however, send messages to the [Runtime API] subsystem to query for the pending PVFs and to submit votes. In addition to that, it will also communicate with [Candidate Validation] Subsystem to request PVF pre-check. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/README.md b/polkadot/roadmap/implementers-guide/src/runtime/README.md index 459f0e6b69d..10eedb49ec3 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/README.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/README.md @@ -89,7 +89,7 @@ struct SessionChangeNotification { prev_config: HostConfiguration, // The configuration after handling the session change. new_config: HostConfiguration, - // A secure randomn seed for the session, gathered from BABE. + // A secure random seed for the session, gathered from BABE. random_seed: [u8; 32], // The session index of the beginning session. session_index: SessionIndex, diff --git a/polkadot/roadmap/implementers-guide/src/runtime/hrmp.md b/polkadot/roadmap/implementers-guide/src/runtime/hrmp.md index 69d33ca8670..ed765634b59 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/hrmp.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/hrmp.md @@ -62,7 +62,7 @@ HRMP related storage layout HrmpOpenChannelRequests: map HrmpChannelId => Option; HrmpOpenChannelRequestsList: Vec; -/// This mapping tracks how many open channel requests are inititated by a given sender para. +/// This mapping tracks how many open channel requests are initiated by a given sender para. /// Invariant: `HrmpOpenChannelRequests` should contain the same number of items that has `(X, _)` /// as the number of `HrmpOpenChannelRequestCount` for `X`. HrmpOpenChannelRequestCount: map ParaId => u32; @@ -233,7 +233,7 @@ executed the message. 1. Send a downward message to the opposite party notifying about the channel closing. * The DM is sent using `queue_downward_message`. * The DM is represented by the `HrmpChannelClosing` XCM message with: - * `initator` is set to `origin`, + * `initiator` is set to `origin`, * `sender` is set to `ch.sender`, * `recipient` is set to `ch.recipient`. * The opposite party is `ch.sender` if `origin` is `ch.recipient` and `ch.recipient` if `origin` is `ch.sender`. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md b/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md index 1345f0eea95..7972c706b9e 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/parainherent.md @@ -88,7 +88,7 @@ to `sanitize_bitfields` function for implementation details. Backed candidates sanitization removes malformed ones, candidates which have got concluded invalid disputes against them or candidates produced by unassigned cores. Furthermore any backing votes from disabled validators for a candidate are dropped. This is part of the validator disabling strategy. After filtering the statements from disabled validators a -backed candidate may end up with votes count less than `minimum_backing_votes` (a parameter from `HostConfiguiration`). +backed candidate may end up with votes count less than `minimum_backing_votes` (a parameter from `HostConfiguration`). In this case the whole candidate is dropped otherwise it will be rejected by `process_candidates` from pallet inclusion. All checks related to backed candidates are implemented in `sanitize_backed_candidates` and `filter_backed_statements_from_disabled_validators`. diff --git a/polkadot/roadmap/implementers-guide/src/types/approval.md b/polkadot/roadmap/implementers-guide/src/types/approval.md index c19ffa53762..29d973ca0ab 100644 --- a/polkadot/roadmap/implementers-guide/src/types/approval.md +++ b/polkadot/roadmap/implementers-guide/src/types/approval.md @@ -39,7 +39,7 @@ enum AssignmentCertKindV2 { /// The core index chosen in this cert. core_index: CoreIndex, }, - /// Deprectated assignment. Soon to be removed. + /// Deprecated assignment. Soon to be removed. /// /// An assignment story based on the VRF that authorized the relay-chain block where the /// candidate was included combined with a sample number. @@ -117,7 +117,7 @@ struct IndirectSignedApprovalVote { ## `CheckedAssignmentCert` An assignment cert which has checked both the VRF and the validity of the implied assignment according to the selection -criteria rules of the protocol. This type should be declared in such a way as to be instantiatable only when the checks +criteria rules of the protocol. This type should be declared in such a way as to be instantiable only when the checks have actually been done. Fields should be accessible via getters, not direct struct access. ```rust diff --git a/polkadot/roadmap/implementers-guide/src/types/disputes.md b/polkadot/roadmap/implementers-guide/src/types/disputes.md index c49e0fea262..ac09084c48a 100644 --- a/polkadot/roadmap/implementers-guide/src/types/disputes.md +++ b/polkadot/roadmap/implementers-guide/src/types/disputes.md @@ -82,7 +82,7 @@ struct DisputeState { struct ScrapedOnChainVotes { /// The session index at which the block was included. session: SessionIndex, - /// The backing and seconding validity attestations for all candidates, provigind the full candidate receipt. + /// The backing and seconding validity attestations for all candidates, providing the full candidate receipt. backing_validators_per_candidate: Vec<(CandidateReceipt, Vec<(ValidatorIndex, ValidityAttestation)>)> /// Set of concluded disputes that were recorded /// on chain within the inherent. diff --git a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md index acfe309ba7b..e011afb9708 100644 --- a/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md +++ b/polkadot/roadmap/implementers-guide/src/types/overseer-protocol.md @@ -22,7 +22,7 @@ All subsystems have their own message types; all of them need to be able to list are currently two proposals for how to handle that with unified communication channels: 1. Retaining the `OverseerSignal` definition above, add `enum FromOrchestra {Signal(OverseerSignal), Message(T)}`. -1. Add a generic varint to `OverseerSignal`: `Message(T)`. +1. Add a generic variant to `OverseerSignal`: `Message(T)`. Either way, there will be some top-level type encapsulating messages from the overseer to each subsystem. diff --git a/polkadot/roadmap/phase-1.toml b/polkadot/roadmap/phase-1.toml index 3a5f0d752de..9b9374d234b 100644 --- a/polkadot/roadmap/phase-1.toml +++ b/polkadot/roadmap/phase-1.toml @@ -34,7 +34,7 @@ requires = ["two-phase-inclusion"] items = [ { label = "Submit secondary checks to runtime", port = "submitsecondary", requires = ["secondary-checking"] }, { label = "Track all candidates within the slash period as well as their session" }, - { label = "Track reports and attestatations for candidates" }, + { label = "Track reports and attestations for candidates" }, ] [[group]] diff --git a/polkadot/runtime/common/src/xcm_sender.rs b/polkadot/runtime/common/src/xcm_sender.rs index 46d09afcfb2..4bbf6a14a40 100644 --- a/polkadot/runtime/common/src/xcm_sender.rs +++ b/polkadot/runtime/common/src/xcm_sender.rs @@ -139,7 +139,7 @@ where /// Implementation of `xcm_builder::EnsureDelivery` which helps to ensure delivery to the /// `ParaId` parachain (sibling or child). Deposits existential deposit for origin (if needed). /// Deposits estimated fee to the origin account (if needed). -/// Allows to trigger additional logic for specific `ParaId` (e.g. open HRMP channel) (if neeeded). +/// Allows to trigger additional logic for specific `ParaId` (e.g. open HRMP channel) (if needed). #[cfg(feature = "runtime-benchmarks")] pub struct ToParachainDeliveryHelper< XcmConfig, diff --git a/polkadot/runtime/parachains/src/assigner_coretime/tests.rs b/polkadot/runtime/parachains/src/assigner_coretime/tests.rs index 998e39670f9..5d42a9d0c8e 100644 --- a/polkadot/runtime/parachains/src/assigner_coretime/tests.rs +++ b/polkadot/runtime/parachains/src/assigner_coretime/tests.rs @@ -622,7 +622,7 @@ fn assignment_proportions_in_core_state_work() { ); } - // Case 2: Current assignment remaning < step after pop + // Case 2: Current assignment remaining < step after pop { assert_eq!( CoretimeAssigner::pop_assignment_for_core(core_idx), diff --git a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs index c47c8745e65..26951f34252 100644 --- a/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs +++ b/polkadot/runtime/parachains/src/assigner_on_demand/mod.rs @@ -684,7 +684,7 @@ where /// Adds an order to the on demand queue. /// - /// Paramenters: + /// Parameters: /// - `location`: Whether to push this entry to the back or the front of the queue. Pushing an /// entry to the front of the queue is only used when the scheduler wants to push back an /// entry it has already popped. @@ -763,7 +763,7 @@ where /// Increases the affinity of a `ParaId` to a specified `CoreIndex`. /// Adds to the count of the `CoreAffinityCount` if an entry is found and the core_index - /// matches. A non-existant entry will be initialized with a count of 1 and uses the supplied + /// matches. A non-existent entry will be initialized with a count of 1 and uses the supplied /// `CoreIndex`. fn increase_affinity(para_id: ParaId, core_index: CoreIndex) { ParaIdAffinity::::mutate(para_id, |maybe_affinity| match maybe_affinity { diff --git a/polkadot/runtime/parachains/src/coretime/migration.rs b/polkadot/runtime/parachains/src/coretime/migration.rs index 03fecc58570..193a5e46b99 100644 --- a/polkadot/runtime/parachains/src/coretime/migration.rs +++ b/polkadot/runtime/parachains/src/coretime/migration.rs @@ -238,7 +238,7 @@ mod v_coretime { return None }, }; - // We assume the coretime chain set this parameter to the recommened value in RFC-1: + // We assume the coretime chain set this parameter to the recommended value in RFC-1: const TIME_SLICE_PERIOD: u32 = 80; let round_up = if valid_until % TIME_SLICE_PERIOD > 0 { 1 } else { 0 }; let time_slice = valid_until / TIME_SLICE_PERIOD + TIME_SLICE_PERIOD * round_up; diff --git a/polkadot/runtime/parachains/src/disputes.rs b/polkadot/runtime/parachains/src/disputes.rs index da95b060c14..cffad42e0ec 100644 --- a/polkadot/runtime/parachains/src/disputes.rs +++ b/polkadot/runtime/parachains/src/disputes.rs @@ -181,7 +181,7 @@ pub trait DisputesHandler { fn is_frozen() -> bool; /// Remove dispute statement duplicates and sort the non-duplicates based on - /// local (lower indicies) vs remotes (higher indices) and age (older with lower indices). + /// local (lower indices) vs remotes (higher indices) and age (older with lower indices). /// /// Returns `Ok(())` if no duplicates were present, `Err(())` otherwise. /// diff --git a/polkadot/runtime/parachains/src/disputes/slashing.rs b/polkadot/runtime/parachains/src/disputes/slashing.rs index 9b2b7a48dc8..9f8fa123918 100644 --- a/polkadot/runtime/parachains/src/disputes/slashing.rs +++ b/polkadot/runtime/parachains/src/disputes/slashing.rs @@ -643,7 +643,7 @@ fn is_known_offence( } } -/// Actual `HandleReports` implemention. +/// Actual `HandleReports` implementation. /// /// When configured properly, should be instantiated with /// `T::KeyOwnerIdentification, Offences, ReportLongevity` parameters. diff --git a/polkadot/runtime/parachains/src/hrmp.rs b/polkadot/runtime/parachains/src/hrmp.rs index 42592d9d9f1..d62533dc919 100644 --- a/polkadot/runtime/parachains/src/hrmp.rs +++ b/polkadot/runtime/parachains/src/hrmp.rs @@ -229,12 +229,12 @@ impl fmt::Debug for OutboundHrmpAcceptanceErr { ), TotalSizeExceeded { idx, total_size, limit } => write!( fmt, - "sending the HRMP message at index {} would exceed the neogitiated channel total size ({} > {})", + "sending the HRMP message at index {} would exceed the negotiated channel total size ({} > {})", idx, total_size, limit, ), CapacityExceeded { idx, count, limit } => write!( fmt, - "sending the HRMP message at index {} would exceed the neogitiated channel capacity ({} > {})", + "sending the HRMP message at index {} would exceed the negotiated channel capacity ({} > {})", idx, count, limit, ), } @@ -790,7 +790,7 @@ pub mod pallet { .ok_or(ArithmeticError::Underflow)?; T::Currency::unreserve( &channel_id.sender.into_account_truncating(), - // The difference should always be convertable into `Balance`, but be + // The difference should always be convertible into `Balance`, but be // paranoid and do nothing in case. amount.try_into().unwrap_or(Zero::zero()), ); diff --git a/polkadot/runtime/parachains/src/hrmp/tests.rs b/polkadot/runtime/parachains/src/hrmp/tests.rs index 7e7b67c8059..162c1412160 100644 --- a/polkadot/runtime/parachains/src/hrmp/tests.rs +++ b/polkadot/runtime/parachains/src/hrmp/tests.rs @@ -702,7 +702,7 @@ fn verify_externally_accessible() { sp_io::storage::get(&well_known_keys::hrmp_ingress_channel_index(para_b)) .expect("the ingress index must be present for para_b"); let ingress_index = >::decode(&mut &raw_ingress_index[..]) - .expect("ingress indexx should be decodable as a list of para ids"); + .expect("ingress index should be decodable as a list of para ids"); assert_eq!(ingress_index, vec![para_a]); // Now, verify that we can access and decode the egress index. diff --git a/polkadot/runtime/parachains/src/paras/mod.rs b/polkadot/runtime/parachains/src/paras/mod.rs index 5acdb9683bb..017cd87f13b 100644 --- a/polkadot/runtime/parachains/src/paras/mod.rs +++ b/polkadot/runtime/parachains/src/paras/mod.rs @@ -1756,7 +1756,7 @@ impl Pallet { // // - Empty value is treated as the current code is already inserted during the onboarding. // - // This is only an intermediate solution and should be fixed in foreseable future. + // This is only an intermediate solution and should be fixed in foreseeable future. // // [soaking issue]: https://github.com/paritytech/polkadot/issues/3918 let validation_code = diff --git a/polkadot/runtime/parachains/src/paras/tests.rs b/polkadot/runtime/parachains/src/paras/tests.rs index 262ec9d3fdb..39abd2367b7 100644 --- a/polkadot/runtime/parachains/src/paras/tests.rs +++ b/polkadot/runtime/parachains/src/paras/tests.rs @@ -1210,7 +1210,7 @@ fn code_hash_at_returns_up_to_end_of_code_retention_period() { assert_eq!(Paras::past_code_meta(¶_id).upgrade_times, vec![upgrade_at(4, 10)]); assert_eq!(Paras::current_code(¶_id), Some(new_code.clone())); - // Make sure that the old code is available **before** the code retion period passes. + // Make sure that the old code is available **before** the code retention period passes. run_to_block(10 + code_retention_period, None); assert_eq!(Paras::code_by_hash(&old_code.hash()), Some(old_code.clone())); assert_eq!(Paras::code_by_hash(&new_code.hash()), Some(new_code.clone())); @@ -1717,7 +1717,7 @@ fn poke_unused_validation_code_doesnt_remove_code_with_users() { #[test] fn increase_code_ref_doesnt_have_allergy_on_add_trusted_validation_code() { - // Verify that accidential calling of increase_code_ref or decrease_code_ref does not lead + // Verify that accidental calling of increase_code_ref or decrease_code_ref does not lead // to a disaster. // NOTE that this test is extra paranoid, as it is not really possible to hit // `decrease_code_ref` without calling `increase_code_ref` first. diff --git a/polkadot/runtime/parachains/src/paras_inherent/mod.rs b/polkadot/runtime/parachains/src/paras_inherent/mod.rs index 02ddfd0acca..6a20a10a8d7 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/mod.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/mod.rs @@ -733,7 +733,7 @@ fn random_sel Weight>( /// are preferred. And for disputes, local and older disputes are preferred (see /// `limit_and_sanitize_disputes`). for backed candidates, since with a increasing number of /// parachains their chances of inclusion become slim. All backed candidates are checked -/// beforehands in `fn create_inherent_inner` which guarantees sanity. +/// beforehand in `fn create_inherent_inner` which guarantees sanity. /// /// Assumes disputes are already filtered by the time this is called. /// @@ -1070,7 +1070,7 @@ fn limit_and_sanitize_disputes< log::debug!(target: LOG_TARGET, "Above max consumable weight: {}/{}", disputes_weight, max_consumable_weight); let mut checked_acc = Vec::::with_capacity(disputes.len()); - // Accumualated weight of all disputes picked, that passed the checks. + // Accumulated weight of all disputes picked, that passed the checks. let mut weight_acc = Weight::zero(); // Select disputes in-order until the remaining weight is attained diff --git a/polkadot/runtime/parachains/src/scheduler/migration.rs b/polkadot/runtime/parachains/src/scheduler/migration.rs index 4c0a07d7367..c47fbab046f 100644 --- a/polkadot/runtime/parachains/src/scheduler/migration.rs +++ b/polkadot/runtime/parachains/src/scheduler/migration.rs @@ -24,7 +24,7 @@ use frame_support::{ /// Old/legacy assignment representation (v0). /// -/// `Assignment` used to be a concrete type with the same layout V0Assignment, idential on all +/// `Assignment` used to be a concrete type with the same layout V0Assignment, identical on all /// assignment providers. This can be removed once storage has been migrated. #[derive(Encode, Decode, RuntimeDebug, TypeInfo, PartialEq, Clone)] struct V0Assignment { diff --git a/polkadot/runtime/parachains/src/scheduler/tests.rs b/polkadot/runtime/parachains/src/scheduler/tests.rs index e6a1e66b3a5..720f645e3bd 100644 --- a/polkadot/runtime/parachains/src/scheduler/tests.rs +++ b/polkadot/runtime/parachains/src/scheduler/tests.rs @@ -836,7 +836,7 @@ fn on_demand_claims_are_pruned_after_timing_out() { // #26 now += 1; - // Run to block #n but this time have group 1 conclude the availabilty. + // Run to block #n but this time have group 1 conclude the availability. for n in now..=(now + max_timeouts + 1) { // #n run_to_block(n, |_| None); diff --git a/polkadot/runtime/parachains/src/session_info.rs b/polkadot/runtime/parachains/src/session_info.rs index 9e1b3d05842..4ca5a73d42b 100644 --- a/polkadot/runtime/parachains/src/session_info.rs +++ b/polkadot/runtime/parachains/src/session_info.rs @@ -158,7 +158,7 @@ impl Pallet { for idx in old_earliest_stored_session..new_earliest_stored_session { Sessions::::remove(&idx); // Idx will be missing for a few sessions after the runtime upgrade. - // But it shouldn'be be a problem. + // But it shouldn't be a problem. AccountKeys::::remove(&idx); SessionExecutorParams::::remove(&idx); } diff --git a/polkadot/runtime/parachains/src/ump_tests.rs b/polkadot/runtime/parachains/src/ump_tests.rs index 2ed1d64336b..5867a8fca66 100644 --- a/polkadot/runtime/parachains/src/ump_tests.rs +++ b/polkadot/runtime/parachains/src/ump_tests.rs @@ -456,7 +456,7 @@ fn verify_relay_dispatch_queue_size_is_externally_accessible() { fn assert_queue_size(para: ParaId, count: u32, size: u32) { #[allow(deprecated)] let raw_queue_size = sp_io::storage::get(&well_known_keys::relay_dispatch_queue_size(para)).expect( - "enqueing a message should create the dispatch queue\ + "enqueuing a message should create the dispatch queue\ and it should be accessible via the well known keys", ); let (c, s) = <(u32, u32)>::decode(&mut &raw_queue_size[..]) @@ -466,7 +466,7 @@ fn assert_queue_size(para: ParaId, count: u32, size: u32) { // Test the deprecated but at least type-safe `relay_dispatch_queue_size_typed`: #[allow(deprecated)] let (c, s) = well_known_keys::relay_dispatch_queue_size_typed(para).get().expect( - "enqueing a message should create the dispatch queue\ + "enqueuing a message should create the dispatch queue\ and it should be accessible via the well known keys", ); assert_eq!((c, s), (count, size)); diff --git a/polkadot/runtime/rococo/README.md b/polkadot/runtime/rococo/README.md index 5b2c296f0ce..c19c3654fe4 100644 --- a/polkadot/runtime/rococo/README.md +++ b/polkadot/runtime/rococo/README.md @@ -4,7 +4,7 @@ Rococo is a testnet runtime with no stability guarantees. ## How to build `rococo` runtime `EpochDurationInBlocks` parameter is configurable via `ROCOCO_EPOCH_DURATION` environment variable. To build wasm -runtime blob with customized epoch duration the following command shall be exectuted: +runtime blob with customized epoch duration the following command shall be executed: ```bash ROCOCO_EPOCH_DURATION=10 ./polkadot/scripts/build-only-wasm.sh rococo-runtime /path/to/output/directory/ ``` diff --git a/polkadot/runtime/westend/src/weights/xcm/mod.rs b/polkadot/runtime/westend/src/weights/xcm/mod.rs index 0162012825f..09e883a9f7a 100644 --- a/polkadot/runtime/westend/src/weights/xcm/mod.rs +++ b/polkadot/runtime/westend/src/weights/xcm/mod.rs @@ -142,7 +142,7 @@ impl XcmWeightInfo for WestendXcmWeight { fn descend_origin(_who: &InteriorLocation) -> Weight { XcmGeneric::::descend_origin() } - fn report_error(_query_repsonse_info: &QueryResponseInfo) -> Weight { + fn report_error(_query_response_info: &QueryResponseInfo) -> Weight { XcmGeneric::::report_error() } diff --git a/polkadot/tests/common.rs b/polkadot/tests/common.rs index 15721c990e0..dbee2d36503 100644 --- a/polkadot/tests/common.rs +++ b/polkadot/tests/common.rs @@ -48,8 +48,8 @@ pub async fn wait_n_finalized_blocks(n: usize, url: &str) { /// Read the WS address from the output. /// -/// This is hack to get the actual binded sockaddr because -/// polkadot assigns a random port if the specified port was already binded. +/// This is hack to get the actual bound sockaddr because +/// polkadot assigns a random port if the specified port was already bound. /// /// You must call /// `Command::new("cmd").stdout(process::Stdio::piped()).stderr(process::Stdio::piped())` diff --git a/polkadot/tests/running_the_node_and_interrupt.rs b/polkadot/tests/running_the_node_and_interrupt.rs index 079c34e0421..85c073d3023 100644 --- a/polkadot/tests/running_the_node_and_interrupt.rs +++ b/polkadot/tests/running_the_node_and_interrupt.rs @@ -32,7 +32,7 @@ async fn running_the_node_works_and_can_be_interrupted() { }; async fn run_command_and_kill(signal: Signal) { - let tmpdir = tempdir().expect("coult not create temp dir"); + let tmpdir = tempdir().expect("could not create temp dir"); let mut cmd = Command::new(cargo_bin("polkadot")) .stdout(process::Stdio::piped()) diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index 7752d1355cd..92d23cfd281 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -248,7 +248,7 @@ fn reserve_transfer_assets_with_paid_router_works() { pub(crate) fn set_up_foreign_asset( reserve_para_id: u32, inner_junction: Option, - benficiary: AccountId, + beneficiary: AccountId, initial_amount: u128, is_sufficient: bool, ) -> (Location, AccountId, Location) { @@ -276,7 +276,7 @@ pub(crate) fn set_up_foreign_asset( assert_ok!(AssetsPallet::mint( RuntimeOrigin::signed(BOB), foreign_asset_id_location.clone(), - benficiary, + beneficiary, initial_amount )); diff --git a/polkadot/xcm/src/v2/multilocation.rs b/polkadot/xcm/src/v2/multilocation.rs index 60aa1f6cead..ac98da8d08c 100644 --- a/polkadot/xcm/src/v2/multilocation.rs +++ b/polkadot/xcm/src/v2/multilocation.rs @@ -176,7 +176,7 @@ impl MultiLocation { } /// Consumes `self` and returns a `MultiLocation` suffixed with `new`, or an `Err` with - /// theoriginal value of `self` in case of overflow. + /// the original value of `self` in case of overflow. pub fn pushed_with_interior(self, new: Junction) -> result::Result { match self.interior.pushed_with(new) { Ok(i) => Ok(MultiLocation { interior: i, parents: self.parents }), diff --git a/polkadot/xcm/src/v3/multilocation.rs b/polkadot/xcm/src/v3/multilocation.rs index c588b924ac7..18fe01ec8fa 100644 --- a/polkadot/xcm/src/v3/multilocation.rs +++ b/polkadot/xcm/src/v3/multilocation.rs @@ -205,7 +205,7 @@ impl MultiLocation { } /// Consumes `self` and returns a `MultiLocation` suffixed with `new`, or an `Err` with - /// theoriginal value of `self` in case of overflow. + /// the original value of `self` in case of overflow. pub fn pushed_with_interior( self, new: impl Into, diff --git a/polkadot/xcm/src/v4/location.rs b/polkadot/xcm/src/v4/location.rs index db55c3d3034..0e7c69864fa 100644 --- a/polkadot/xcm/src/v4/location.rs +++ b/polkadot/xcm/src/v4/location.rs @@ -210,7 +210,7 @@ impl Location { } /// Consumes `self` and returns a `Location` suffixed with `new`, or an `Err` with - /// theoriginal value of `self` in case of overflow. + /// the original value of `self` in case of overflow. pub fn pushed_with_interior( self, new: impl Into, diff --git a/polkadot/xcm/xcm-builder/src/barriers.rs b/polkadot/xcm/xcm-builder/src/barriers.rs index 80411ab5a22..b8923a4d5c6 100644 --- a/polkadot/xcm/xcm-builder/src/barriers.rs +++ b/polkadot/xcm/xcm-builder/src/barriers.rs @@ -142,7 +142,7 @@ impl> ShouldExecute for AllowTopLevelPaidExecutionFrom /// In the above example, `AllowUnpaidExecutionFrom` appears once underneath /// `WithComputedOrigin`. This is in order to distinguish between messages which are notionally /// from a derivative location of `ParentLocation` but that just happened to be sent via -/// `ParentLocaction` rather than messages that were sent by the parent. +/// `ParentLocation` rather than messages that were sent by the parent. /// /// Similarly `AllowTopLevelPaidExecutionFrom` appears twice: once inside of `WithComputedOrigin` /// where we provide the list of origins which are derivative origins, and then secondly outside diff --git a/polkadot/xcm/xcm-builder/src/tests/origins.rs b/polkadot/xcm/xcm-builder/src/tests/origins.rs index c717d1e2af8..b6a1a9f1052 100644 --- a/polkadot/xcm/xcm-builder/src/tests/origins.rs +++ b/polkadot/xcm/xcm-builder/src/tests/origins.rs @@ -80,8 +80,8 @@ fn universal_origin_should_work() { fn export_message_should_work() { // Bridge chain (assumed to be Relay) lets Parachain #1 have message execution for free. AllowUnpaidFrom::set(vec![[Parachain(1)].into()]); - // Local parachain #1 issues a transfer asset on Polkadot Relay-chain, transfering 100 Planck to - // Polkadot parachain #2. + // Local parachain #1 issues a transfer asset on Polkadot Relay-chain, transferring 100 Planck + // to Polkadot parachain #2. let expected_message = Xcm(vec![TransferAsset { assets: (Here, 100u128).into(), beneficiary: Parachain(2).into(), diff --git a/polkadot/xcm/xcm-builder/tests/scenarios.rs b/polkadot/xcm/xcm-builder/tests/scenarios.rs index db37f85acdb..ee1aeffbb4e 100644 --- a/polkadot/xcm/xcm-builder/tests/scenarios.rs +++ b/polkadot/xcm/xcm-builder/tests/scenarios.rs @@ -132,7 +132,7 @@ fn report_holding_works() { assets: AllCounted(1).into(), beneficiary: OnlyChild.into(), // invalid destination }, - // is not triggered becasue the deposit fails + // is not triggered because the deposit fails ReportHolding { response_info: response_info.clone(), assets: All.into() }, ]); let mut hash = fake_message_hash(&message); diff --git a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs index da7fc0d9782..1d1ee40d092 100644 --- a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs +++ b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs @@ -328,7 +328,7 @@ fn query_response_elicits_handler() { /// Simulates a cross-chain message from Parachain to Parachain through Relay Chain /// that deposits assets into the reserve of the destination. -/// Regression test for `DepostiReserveAsset` changes in +/// Regression test for `DepositReserveAsset` changes in /// #[test] fn deposit_reserve_asset_works_for_any_xcm_sender() { diff --git a/polkadot/xcm/xcm-executor/src/traits/should_execute.rs b/polkadot/xcm/xcm-executor/src/traits/should_execute.rs index 449e82b5a6e..12e8fd6b87f 100644 --- a/polkadot/xcm/xcm-executor/src/traits/should_execute.rs +++ b/polkadot/xcm/xcm-executor/src/traits/should_execute.rs @@ -18,7 +18,7 @@ use frame_support::traits::ProcessMessageError; use sp_std::result::Result; use xcm::latest::{Instruction, Location, Weight, XcmHash}; -/// Properyies of an XCM message and its imminent execution. +/// Properties of an XCM message and its imminent execution. #[derive(Clone, Eq, PartialEq, Debug)] pub struct Properties { /// The amount of weight that the system has determined this diff --git a/polkadot/xcm/xcm-simulator/example/src/lib.rs b/polkadot/xcm/xcm-simulator/example/src/lib.rs index d134957fbc1..13210179e91 100644 --- a/polkadot/xcm/xcm-simulator/example/src/lib.rs +++ b/polkadot/xcm/xcm-simulator/example/src/lib.rs @@ -424,7 +424,7 @@ mod tests { /// Scenario: /// The relay-chain transfers an NFT into a parachain's sovereign account, who then mints a - /// trustless-backed-derivated locally. + /// trustless-backed-derived locally. /// /// Asserts that the parachain accounts are updated as expected. #[test] @@ -479,7 +479,7 @@ mod tests { assert_ok!(ParachainPalletXcm::send_xcm(alice, Parent, message)); }); ParaA::execute_with(|| { - log::debug!(target: "xcm-exceutor", "Hello"); + log::debug!(target: "xcm-executor", "Hello"); assert_eq!( parachain::ForeignUniques::owner((Parent, GeneralIndex(2)).into(), 69u32.into()), Some(ALICE), diff --git a/prdoc/pr_3808.prdoc b/prdoc/pr_3808.prdoc new file mode 100644 index 00000000000..9b50f721df3 --- /dev/null +++ b/prdoc/pr_3808.prdoc @@ -0,0 +1,20 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Fix spelling mistakes in source code + +doc: + - audience: Node Operator + description: | + Some spelling mistakes in log output, error messages and tracing (prometheus/grafana) have been fixed. + - audience: Runtime Dev + description: | + Public crate changes: + - The public trait `RuntimeParameterStore` in `substrate/frame/support` had the associated type renamed from `AggregratedKeyValue` to `AggregatedKeyValue`. + - The public trait `AggregratedKeyValue` in `substrate/frame/support` was similarly renamed to `AggregatedKeyValue`. + - The public methods `test_versioning` and `test_versioning_register_only` of the `TestApi` trait in `substrate/primitives/runtime-interface/test-wasm` had the spelling of `versionning` changed to `versioning`. + - The public functions `read_trie_first_descendant_value` and `read_child_trie_first_descendant_value` in `substrate/primitives/trie` had the spelling of `descedant` changed to `descendant`. +crates: + - name: frame-support + - name: sp-runtime-interface-test-wasm + - name: sp-trie diff --git a/scripts/bridges_update_subtree.sh b/scripts/bridges_update_subtree.sh index 5c5c7a322a1..2cd6d968d2b 100755 --- a/scripts/bridges_update_subtree.sh +++ b/scripts/bridges_update_subtree.sh @@ -1,6 +1,6 @@ #!/bin/bash -# A script to udpate bridges repo as subtree to Cumulus +# A script to update bridges repo as subtree to Cumulus # Usage: # ./scripts/bridges_update_subtree.sh fetch # ./scripts/bridges_update_subtree.sh patch diff --git a/scripts/snowbridge_update_subtree.sh b/scripts/snowbridge_update_subtree.sh index 2276bb35469..c572eaa18fa 100755 --- a/scripts/snowbridge_update_subtree.sh +++ b/scripts/snowbridge_update_subtree.sh @@ -1,6 +1,6 @@ #!/bin/bash -# A script to udpate bridges repo as subtree to Cumulus +# A script to update bridges repo as subtree to Cumulus # Usage: # ./scripts/update_subtree_snowbridge.sh fetch # ./scripts/update_subtree_snowbridge.sh patch diff --git a/substrate/bin/node/cli/benches/block_production.rs b/substrate/bin/node/cli/benches/block_production.rs index 23a62cc0bd2..d04780d5f95 100644 --- a/substrate/bin/node/cli/benches/block_production.rs +++ b/substrate/bin/node/cli/benches/block_production.rs @@ -145,7 +145,7 @@ fn prepare_benchmark(client: &FullClient) -> (usize, Vec) { let src = Sr25519Keyring::Alice.pair(); let dst: MultiAddress = Sr25519Keyring::Bob.to_account_id().into(); - // Add as many tranfer extrinsics as possible into a single block. + // Add as many transfer extrinsics as possible into a single block. for nonce in 0.. { let extrinsic: OpaqueExtrinsic = create_extrinsic( client, @@ -179,7 +179,7 @@ fn block_production(c: &mut Criterion) { let node = new_node(tokio_handle.clone()); let client = &*node.client; - // Buliding the very first block is around ~30x slower than any subsequent one, + // Building the very first block is around ~30x slower than any subsequent one, // so let's make sure it's built and imported before we benchmark anything. let mut block_builder = BlockBuilderBuilder::new(client) .on_parent_block(client.chain_info().best_hash) diff --git a/substrate/bin/node/cli/src/cli.rs b/substrate/bin/node/cli/src/cli.rs index 3345afae4fd..56fbed51f8a 100644 --- a/substrate/bin/node/cli/src/cli.rs +++ b/substrate/bin/node/cli/src/cli.rs @@ -49,7 +49,7 @@ pub struct Cli { /// Possible subcommands of the main binary. #[derive(Debug, clap::Subcommand)] pub enum Subcommand { - /// The custom inspect subcommmand for decoding blocks and extrinsics. + /// The custom inspect subcommand for decoding blocks and extrinsics. #[command( name = "inspect", about = "Decode given block or extrinsic using current native runtime." diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index e4b425e6f96..dddb261a71d 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -53,7 +53,7 @@ pub type HostFunctions = ( frame_benchmarking::benchmarking::HostFunctions, ); -/// A specialized `WasmExecutor` intended to use accross substrate node. It provides all required +/// A specialized `WasmExecutor` intended to use across substrate node. It provides all required /// HostFunctions. pub type RuntimeExecutor = sc_executor::WasmExecutor; diff --git a/substrate/bin/node/cli/tests/fees.rs b/substrate/bin/node/cli/tests/fees.rs index 8c7b3c87315..69c96bf63a6 100644 --- a/substrate/bin/node/cli/tests/fees.rs +++ b/substrate/bin/node/cli/tests/fees.rs @@ -135,7 +135,7 @@ fn transaction_fee_is_correct() { // if weight of the cheapest weight would be 10^7, this would be 10^9, which is: // - 1 MILLICENTS in substrate node. // - 1 milli-dot based on current polkadot runtime. - // (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`) + // (this based on assigning 0.1 CENT to the cheapest tx with `weight = 100`) let mut t = new_test_ext(compact_code_unwrap()); t.insert(>::hashed_key_for(alice()), new_account_info(100)); t.insert(>::hashed_key_for(bob()), new_account_info(10)); diff --git a/substrate/bin/node/testing/src/bench.rs b/substrate/bin/node/testing/src/bench.rs index df302a6453b..e5c2563905e 100644 --- a/substrate/bin/node/testing/src/bench.rs +++ b/substrate/bin/node/testing/src/bench.rs @@ -84,7 +84,7 @@ impl BenchPair { /// Drop system cache. /// -/// Will panic if cache drop is impossbile. +/// Will panic if cache drop is impossible. pub fn drop_system_cache() { #[cfg(target_os = "windows")] { @@ -173,7 +173,7 @@ impl Clone for BenchDb { // We clear system cache after db clone but before any warmups. // This populates system cache with some data unrelated to actual - // data we will be quering further under benchmark (like what + // data we will be querying further under benchmark (like what // would have happened in real system that queries random entries // from database). drop_system_cache(); @@ -443,7 +443,7 @@ impl BenchDb { BlockContentIterator::new(content, &self.keyring, client) } - /// Get cliet for this database operations. + /// Get client for this database operations. pub fn client(&mut self) -> Client { let (client, _backend, _task_executor) = Self::bench_client(self.database_type, self.directory_guard.path(), &self.keyring); diff --git a/substrate/bin/utils/chain-spec-builder/src/lib.rs b/substrate/bin/utils/chain-spec-builder/src/lib.rs index 8c78030c885..dbd0437921f 100644 --- a/substrate/bin/utils/chain-spec-builder/src/lib.rs +++ b/substrate/bin/utils/chain-spec-builder/src/lib.rs @@ -185,7 +185,7 @@ pub struct ConvertToRawCmd { /// Verifies the provided input chain spec. /// /// Silently checks if given input chain spec can be converted to raw. It allows to check if all -/// RuntimeGenesisConfig fiels are properly initialized and if the json does not contain invalid +/// RuntimeGenesisConfig fields are properly initialized and if the json does not contain invalid /// fields. #[derive(Parser, Debug, Clone)] pub struct VerifyCmd { diff --git a/substrate/bin/utils/subkey/README.md b/substrate/bin/utils/subkey/README.md index a5f27cfd370..fc1053e232d 100644 --- a/substrate/bin/utils/subkey/README.md +++ b/substrate/bin/utils/subkey/README.md @@ -77,7 +77,7 @@ below can be derived from those secrets. The output above also show the **public key** and the **Account ID**. Those are the independent from the network where you will use the key. -The **SS58 address** (or **Public Address**) of a new account is a reprensentation of the public keys of an account for +The **SS58 address** (or **Public Address**) of a new account is a representation of the public keys of an account for a given network (for instance Kusama or Polkadot). You can read more about the [SS58 format in the Substrate Docs](https://docs.substrate.io/reference/address-formats/) @@ -143,7 +143,7 @@ Secret phrase `soup lyrics media market way crouch elevator put moon useful ques SS58 Address: 5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC ``` -Using the `inspect` command (see more details below), we see that knowning only the **secret seed** is no longer +Using the `inspect` command (see more details below), we see that knowing only the **secret seed** is no longer sufficient to recover the account: ```bash diff --git a/substrate/bin/utils/subkey/src/lib.rs b/substrate/bin/utils/subkey/src/lib.rs index f3023acde40..33f28ef46a5 100644 --- a/substrate/bin/utils/subkey/src/lib.rs +++ b/substrate/bin/utils/subkey/src/lib.rs @@ -94,10 +94,10 @@ //! seed** (also called **Private Key**). Those 2 secrets are the pieces of information you MUST //! keep safe and secret. All the other information below can be derived from those secrets. //! -//! The output above also show the **public key** and the **Account ID**. Those are the independant +//! The output above also show the **public key** and the **Account ID**. Those are the independent //! from the network where you will use the key. //! -//! The **SS58 address** (or **Public Address**) of a new account is a reprensentation of the public +//! The **SS58 address** (or **Public Address**) of a new account is a representation of the public //! keys of an account for a given network (for instance Kusama or Polkadot). //! //! You can read more about the [SS58 format in the Substrate Docs](https://docs.substrate.io/reference/address-formats/) and see the list of reserved prefixes in the [SS58 Registry](https://github.com/paritytech/ss58-registry). @@ -110,7 +110,7 @@ //! //! ### Json output //! -//! `subkey` can calso generate the output as *json*. This is useful for automation. +//! `subkey` can also generate the output as *json*. This is useful for automation. //! //! command: //! @@ -163,7 +163,7 @@ //! SS58 Address: 5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC //! ``` //! -//! Using the `inspect` command (see more details below), we see that knowning only the **secret +//! Using the `inspect` command (see more details below), we see that knowing only the **secret //! seed** is no longer sufficient to recover the account: //! //! ```bash @@ -184,7 +184,7 @@ //! //! ### Inspecting a key //! -//! If you have *some data* about a key, `subkey inpsect` will help you discover more information +//! If you have *some data* about a key, `subkey inspect` will help you discover more information //! about it. //! //! If you have **secrets** that you would like to verify for instance, you can use: diff --git a/substrate/client/basic-authorship/src/basic_authorship.rs b/substrate/client/basic-authorship/src/basic_authorship.rs index 932287ac865..1519c76c42c 100644 --- a/substrate/client/basic-authorship/src/basic_authorship.rs +++ b/substrate/client/basic-authorship/src/basic_authorship.rs @@ -180,7 +180,7 @@ impl ProposerFactory { /// The soft deadline indicates where we should stop attempting to add transactions /// to the block, which exhaust resources. After soft deadline is reached, /// we switch to a fixed-amount mode, in which after we see `MAX_SKIPPED_TRANSACTIONS` - /// transactions which exhaust resrouces, we will conclude that the block is full. + /// transactions which exhaust resources, we will conclude that the block is full. /// /// Setting the value too low will significantly limit the amount of transactions /// we try in case they exhaust resources. Setting the value too high can diff --git a/substrate/client/chain-spec/src/chain_spec.rs b/substrate/client/chain-spec/src/chain_spec.rs index 78e81e10d2b..4ec8527de26 100644 --- a/substrate/client/chain-spec/src/chain_spec.rs +++ b/substrate/client/chain-spec/src/chain_spec.rs @@ -52,7 +52,7 @@ enum GenesisSource { File(PathBuf), Binary(Cow<'static, [u8]>), /// factory function + code - //Factory and G type parameter shall be removed togheter with `ChainSpec::from_genesis` + //Factory and G type parameter shall be removed together with `ChainSpec::from_genesis` Factory(Arc G + Send + Sync>, Vec), Storage(Storage), /// build action + code @@ -264,7 +264,7 @@ struct RuntimeInnerWrapper { enum Genesis { /// (Deprecated) Contains the JSON representation of G (the native type representing the /// runtime's `RuntimeGenesisConfig` struct) (will be removed with `ChainSpec::from_genesis`) - /// without the runtime code. It is required to deserialize the legacy chainspecs genereted + /// without the runtime code. It is required to deserialize the legacy chainspecs generated /// with `ChainsSpec::from_genesis` method. Runtime(G), /// (Deprecated) Contains the JSON representation of G (the native type representing the @@ -276,13 +276,13 @@ enum Genesis { Raw(RawGenesis), /// State root hash of the genesis storage. StateRootHash(StorageData), - /// Represents the runtime genesis config in JSON format toghether with runtime code. + /// Represents the runtime genesis config in JSON format together with runtime code. RuntimeGenesis(RuntimeGenesisInner), } /// A configuration of a client. Does not include runtime storage initialization. /// Note: `genesis` field is ignored due to way how the chain specification is serialized into -/// JSON file. Refer to [`ChainSpecJsonContainer`], which flattens [`ClientSpec`] and denies uknown +/// JSON file. Refer to [`ChainSpecJsonContainer`], which flattens [`ClientSpec`] and denies unknown /// fields. #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] @@ -508,7 +508,7 @@ impl ChainSpec { self.client_spec.fork_id.as_deref() } - /// Additional loosly-typed properties of the chain. + /// Additional loosely-typed properties of the chain. /// /// Returns an empty JSON object if 'properties' not defined in config pub fn properties(&self) -> Properties { diff --git a/substrate/client/chain-spec/src/extension.rs b/substrate/client/chain-spec/src/extension.rs index f2939741535..d1f03539349 100644 --- a/substrate/client/chain-spec/src/extension.rs +++ b/substrate/client/chain-spec/src/extension.rs @@ -284,7 +284,7 @@ where } } -/// A subset of the `Extension` trait that only allows for quering extensions. +/// A subset of the `Extension` trait that only allows for querying extensions. pub trait GetExtension { /// Get an extension of specific type. fn get_any(&self, t: TypeId) -> &dyn Any; diff --git a/substrate/client/chain-spec/src/genesis_config_builder.rs b/substrate/client/chain-spec/src/genesis_config_builder.rs index c8b54f66be6..61f065e213c 100644 --- a/substrate/client/chain-spec/src/genesis_config_builder.rs +++ b/substrate/client/chain-spec/src/genesis_config_builder.rs @@ -33,7 +33,7 @@ use std::borrow::Cow; /// A utility that facilitates calling the GenesisBuilder API from the runtime wasm code blob. /// /// `EHF` type allows to specify the extended host function required for building runtime's genesis -/// config. The type will be compbined with default `sp_io::SubstrateHostFunctions`. +/// config. The type will be combined with default `sp_io::SubstrateHostFunctions`. pub struct GenesisConfigBuilderRuntimeCaller<'a, EHF = ()> where EHF: HostFunctions, diff --git a/substrate/client/chain-spec/src/lib.rs b/substrate/client/chain-spec/src/lib.rs index eab5f789f29..e8b87a60404 100644 --- a/substrate/client/chain-spec/src/lib.rs +++ b/substrate/client/chain-spec/src/lib.rs @@ -393,7 +393,7 @@ pub trait ChainSpec: BuildStorage + Send + Sync { fn protocol_id(&self) -> Option<&str>; /// Optional network fork identifier. `None` by default. fn fork_id(&self) -> Option<&str>; - /// Additional loosly-typed properties of the chain. + /// Additional loosely-typed properties of the chain. /// /// Returns an empty JSON object if 'properties' not defined in config fn properties(&self) -> Properties; diff --git a/substrate/client/cli/src/commands/vanity.rs b/substrate/client/cli/src/commands/vanity.rs index ce751613298..330a59493ef 100644 --- a/substrate/client/cli/src/commands/vanity.rs +++ b/substrate/client/cli/src/commands/vanity.rs @@ -51,7 +51,7 @@ pub struct VanityCmd { impl VanityCmd { /// Run the command pub fn run(&self) -> error::Result<()> { - let formated_seed = with_crypto_scheme!( + let formatted_seed = with_crypto_scheme!( self.crypto_scheme.scheme, generate_key( &self.pattern, @@ -62,7 +62,7 @@ impl VanityCmd { with_crypto_scheme!( self.crypto_scheme.scheme, print_from_uri( - &formated_seed, + &formatted_seed, None, self.network_scheme.network, self.output_scheme.output_type, diff --git a/substrate/client/cli/src/params/network_params.rs b/substrate/client/cli/src/params/network_params.rs index 12f19df2a68..94efb428091 100644 --- a/substrate/client/cli/src/params/network_params.rs +++ b/substrate/client/cli/src/params/network_params.rs @@ -310,7 +310,7 @@ mod tests { } #[test] - fn sync_ingores_case() { + fn sync_ignores_case() { let params = Cli::try_parse_from(["", "--sync", "wArP"]).expect("Parses network params"); assert_eq!(SyncMode::Warp, params.network_params.sync); diff --git a/substrate/client/consensus/aura/src/lib.rs b/substrate/client/consensus/aura/src/lib.rs index 1be7be8eeea..e220aaac508 100644 --- a/substrate/client/consensus/aura/src/lib.rs +++ b/substrate/client/consensus/aura/src/lib.rs @@ -82,7 +82,7 @@ pub enum CompatibilityMode { None, /// Call `initialize_block` before doing any runtime calls. /// - /// Previously the node would execute `initialize_block` before fetchting the authorities + /// Previously the node would execute `initialize_block` before fetching the authorities /// from the runtime. This behaviour changed in: /// /// By calling `initialize_block` before fetching the authorities, on a block that diff --git a/substrate/client/consensus/babe/src/authorship.rs b/substrate/client/consensus/babe/src/authorship.rs index 11f5233abc6..57ee706a04f 100644 --- a/substrate/client/consensus/babe/src/authorship.rs +++ b/substrate/client/consensus/babe/src/authorship.rs @@ -59,7 +59,7 @@ pub(super) fn calculate_primary_threshold( assert!(theta > 0.0, "authority with weight 0."); // NOTE: in the equation `p = 1 - (1 - c)^theta` the value of `p` is always - // capped by `c`. For all pratical purposes `c` should always be set to a + // capped by `c`. For all practical purposes `c` should always be set to a // value < 0.5, as such in the computations below we should never be near // edge cases like `0.999999`. diff --git a/substrate/client/consensus/babe/src/lib.rs b/substrate/client/consensus/babe/src/lib.rs index ccf72939631..d10bdd8c7e4 100644 --- a/substrate/client/consensus/babe/src/lib.rs +++ b/substrate/client/consensus/babe/src/lib.rs @@ -1418,7 +1418,7 @@ where // Skip babe logic if block already in chain or importing blocks during initial sync, // otherwise the check for epoch changes will error because trying to re-import an - // epoch change or because of missing epoch data in the tree, respectivelly. + // epoch change or because of missing epoch data in the tree, respectively. if info.block_gap.map_or(false, |(s, e)| s <= number && number <= e) || block_status == BlockStatus::InChain { diff --git a/substrate/client/consensus/babe/src/migration.rs b/substrate/client/consensus/babe/src/migration.rs index bec2d0a61f4..5f1ece3ec0e 100644 --- a/substrate/client/consensus/babe/src/migration.rs +++ b/substrate/client/consensus/babe/src/migration.rs @@ -64,7 +64,7 @@ impl EpochT for EpochV0 { // Implement From for Epoch impl EpochV0 { - /// Migrate the sturct to current epoch version. + /// Migrate the struct to current epoch version. pub fn migrate(self, config: &BabeConfiguration) -> Epoch { sp_consensus_babe::Epoch { epoch_index: self.epoch_index, diff --git a/substrate/client/consensus/beefy/README.md b/substrate/client/consensus/beefy/README.md index 13f88303a97..a7956cfcd42 100644 --- a/substrate/client/consensus/beefy/README.md +++ b/substrate/client/consensus/beefy/README.md @@ -297,7 +297,7 @@ periodically on the global topic. Let's now dive into description of the message - Justification is considered worthwhile to gossip when: - It is for a recent (implementation specific) round or the latest mandatory round. - All signatures are valid and there is at least `2/3rd + 1` of them. - - Signatorees are part of the current validator set. + - Signatories are part of the current validator set. - Mandatory justifications should be announced periodically. ## Misbehavior diff --git a/substrate/client/consensus/beefy/src/communication/mod.rs b/substrate/client/consensus/beefy/src/communication/mod.rs index 6fda63688e6..09c540e3b8a 100644 --- a/substrate/client/consensus/beefy/src/communication/mod.rs +++ b/substrate/client/consensus/beefy/src/communication/mod.rs @@ -99,7 +99,7 @@ mod cost { // On-demand request was refused by peer. pub(super) const REFUSAL_RESPONSE: Rep = Rep::new(-100, "BEEFY: Proof request refused"); // On-demand request for a proof that can't be found in the backend. - pub(super) const UNKOWN_PROOF_REQUEST: Rep = Rep::new(-150, "BEEFY: Unknown proof request"); + pub(super) const UNKNOWN_PROOF_REQUEST: Rep = Rep::new(-150, "BEEFY: Unknown proof request"); } // benefit scalars for reporting peers. diff --git a/substrate/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs b/substrate/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs index d856e9748a1..ce184769fa7 100644 --- a/substrate/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs +++ b/substrate/client/consensus/beefy/src/communication/request_response/incoming_requests_handler.rs @@ -170,7 +170,7 @@ where .flatten() .and_then(|hash| self.client.justifications(hash).ok().flatten()) .and_then(|justifs| justifs.get(BEEFY_ENGINE_ID).cloned()) - .ok_or_else(|| reputation_changes.push(cost::UNKOWN_PROOF_REQUEST)); + .ok_or_else(|| reputation_changes.push(cost::UNKNOWN_PROOF_REQUEST)); request .pending_response .send(netconfig::OutgoingResponse { diff --git a/substrate/client/consensus/beefy/src/keystore.rs b/substrate/client/consensus/beefy/src/keystore.rs index 2ddc938fbc6..9582c2661c3 100644 --- a/substrate/client/consensus/beefy/src/keystore.rs +++ b/substrate/client/consensus/beefy/src/keystore.rs @@ -404,7 +404,7 @@ pub mod tests { let store: BeefyKeystore = Some(store).into(); - let msg = b"are you involved or commited?"; + let msg = b"are you involved or committed?"; let sig1 = store.sign(&alice, msg).unwrap(); let sig2 = Keyring::::Alice.sign(msg); @@ -440,7 +440,7 @@ pub mod tests { let alice = Keyring::Alice.public(); - let msg = b"are you involved or commited?"; + let msg = b"are you involved or committed?"; let sig = store.sign(&alice, msg).err().unwrap(); let err = Error::Signature(expected_error_message.to_string()); @@ -463,7 +463,7 @@ pub mod tests { let store: BeefyKeystore = None.into(); let alice = Keyring::Alice.public(); - let msg = b"are you involved or commited"; + let msg = b"are you involved or committed"; let sig = store.sign(&alice, msg).err().unwrap(); let err = Error::Keystore("no Keystore".to_string()); @@ -487,7 +487,7 @@ pub mod tests { let alice = Keyring::Alice.public(); // `msg` and `sig` match - let msg = b"are you involved or commited?"; + let msg = b"are you involved or committed?"; let sig = store.sign(&alice, msg).unwrap(); assert!(BeefyKeystore::verify(&alice, &sig, msg)); diff --git a/substrate/client/consensus/beefy/src/worker.rs b/substrate/client/consensus/beefy/src/worker.rs index c8eb19621ba..7a47f286ef7 100644 --- a/substrate/client/consensus/beefy/src/worker.rs +++ b/substrate/client/consensus/beefy/src/worker.rs @@ -76,13 +76,13 @@ pub(crate) enum RoundAction { pub(crate) struct VoterOracle { /// Queue of known sessions. Keeps track of voting rounds (block numbers) within each session. /// - /// There are three voter states coresponding to three queue states: + /// There are three voter states corresponding to three queue states: /// 1. voter uninitialized: queue empty, /// 2. up-to-date - all mandatory blocks leading up to current GRANDPA finalized: queue has ONE /// element, the 'current session' where `mandatory_done == true`, /// 3. lagging behind GRANDPA: queue has [1, N] elements, where all `mandatory_done == false`. - /// In this state, everytime a session gets its mandatory block BEEFY finalized, it's popped - /// off the queue, eventually getting to state `2. up-to-date`. + /// In this state, every time a session gets its mandatory block BEEFY finalized, it's + /// popped off the queue, eventually getting to state `2. up-to-date`. sessions: VecDeque>, /// Min delta in block numbers between two blocks, BEEFY should vote on. min_block_delta: u32, diff --git a/substrate/client/consensus/common/Cargo.toml b/substrate/client/consensus/common/Cargo.toml index 7f36dfc09ef..f691e84717d 100644 --- a/substrate/client/consensus/common/Cargo.toml +++ b/substrate/client/consensus/common/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.io" repository.workspace = true -description = "Collection of common consensus specific imlementations for Substrate (client)" +description = "Collection of common consensus specific implementations for Substrate (client)" readme = "README.md" [lints] diff --git a/substrate/client/consensus/common/src/import_queue.rs b/substrate/client/consensus/common/src/import_queue.rs index 39d5bf8ed35..062e244a912 100644 --- a/substrate/client/consensus/common/src/import_queue.rs +++ b/substrate/client/consensus/common/src/import_queue.rs @@ -133,7 +133,7 @@ pub trait ImportQueue: Send { /// Start asynchronous runner for import queue. /// /// Takes an object implementing [`Link`] which allows the import queue to - /// influece the synchronization process. + /// influence the synchronization process. async fn run(self, link: Box>); } diff --git a/substrate/client/consensus/common/src/import_queue/basic_queue.rs b/substrate/client/consensus/common/src/import_queue/basic_queue.rs index 1cc7ec26fd1..125d4f104c1 100644 --- a/substrate/client/consensus/common/src/import_queue/basic_queue.rs +++ b/substrate/client/consensus/common/src/import_queue/basic_queue.rs @@ -187,7 +187,7 @@ impl ImportQueue for BasicQueue { /// Start asynchronous runner for import queue. /// /// Takes an object implementing [`Link`] which allows the import queue to - /// influece the synchronization process. + /// influence the synchronization process. async fn run(mut self, mut link: Box>) { loop { if let Err(_) = self.result_port.next_action(&mut *link).await { @@ -198,7 +198,7 @@ impl ImportQueue for BasicQueue { } } -/// Messages destinated to the background worker. +/// Messages designated to the background worker. mod worker_messages { use super::*; diff --git a/substrate/client/consensus/epochs/src/lib.rs b/substrate/client/consensus/epochs/src/lib.rs index 29bb18e147c..bbc143b7bd3 100644 --- a/substrate/client/consensus/epochs/src/lib.rs +++ b/substrate/client/consensus/epochs/src/lib.rs @@ -326,7 +326,7 @@ impl AsRef for IncrementedEpoch { /// /// The first epoch, epoch_0, is special cased by saying that it starts at /// slot number of the first block in the chain. When bootstrapping a chain, -/// there can be multiple competing block #1s, so we have to ensure that the overlayed +/// there can be multiple competing block #1s, so we have to ensure that the overlaid /// DAG doesn't get confused. /// /// The first block of every epoch should be producing a descriptor for the next @@ -655,7 +655,7 @@ where /// Revert to a specified block given its `hash` and `number`. /// This removes all the epoch changes information that were announced by - /// all the given block descendents. + /// all the given block descendants. pub fn revert>( &mut self, descendent_of_builder: D, diff --git a/substrate/client/consensus/grandpa/src/communication/mod.rs b/substrate/client/consensus/grandpa/src/communication/mod.rs index 5c7e1276297..6e87d6bf9a2 100644 --- a/substrate/client/consensus/grandpa/src/communication/mod.rs +++ b/substrate/client/consensus/grandpa/src/communication/mod.rs @@ -222,13 +222,13 @@ pub(crate) struct NetworkBridge, S: Syncing> { neighbor_sender: periodic::NeighborPacketSender, /// `NeighborPacketWorker` processing packets sent through the `NeighborPacketSender`. - // `NetworkBridge` is required to be cloneable, thus one needs to be able to clone its + // `NetworkBridge` is required to be clonable, thus one needs to be able to clone its // children, thus one has to wrap `neighbor_packet_worker` with an `Arc` `Mutex`. neighbor_packet_worker: Arc>>, /// Receiver side of the peer report stream populated by the gossip validator, forwarded to the /// gossip engine. - // `NetworkBridge` is required to be cloneable, thus one needs to be able to clone its + // `NetworkBridge` is required to be clonable, thus one needs to be able to clone its // children, thus one has to wrap gossip_validator_report_stream with an `Arc` `Mutex`. Given // that it is just an `UnboundedReceiver`, one could also switch to a // multi-producer-*multi*-consumer channel implementation. @@ -766,7 +766,7 @@ impl Sink> for OutgoingMessages { ) .ok_or_else(|| { Error::Signing(format!( - "Failed to sign GRANDPA vote for round {} targetting {:?}", + "Failed to sign GRANDPA vote for round {} targeting {:?}", self.round, target_hash )) })?; diff --git a/substrate/client/consensus/grandpa/src/communication/periodic.rs b/substrate/client/consensus/grandpa/src/communication/periodic.rs index daa75292028..9d0e76b7c80 100644 --- a/substrate/client/consensus/grandpa/src/communication/periodic.rs +++ b/substrate/client/consensus/grandpa/src/communication/periodic.rs @@ -106,7 +106,7 @@ impl Stream for NeighborPacketWorker { // Make sure the underlying task is scheduled for wake-up. // - // Note: In case poll_unpin is called after the resetted delay fires again, this + // Note: In case poll_unpin is called after the reset delay fires again, this // will drop one tick. Deemed as very unlikely and also not critical. while this.delay.poll_unpin(cx).is_ready() {} diff --git a/substrate/client/consensus/grandpa/src/tests.rs b/substrate/client/consensus/grandpa/src/tests.rs index 7e42c2d45c7..14708cc89e8 100644 --- a/substrate/client/consensus/grandpa/src/tests.rs +++ b/substrate/client/consensus/grandpa/src/tests.rs @@ -1805,7 +1805,7 @@ async fn grandpa_environment_checks_if_best_block_is_descendent_of_finality_targ ); // best block is higher than finality target and it's on the same fork, - // the best block passed to the voting rule should not be overriden + // the best block passed to the voting rule should not be overridden select_chain.set_best_chain(client.expect_header(hashof10_a).unwrap()); select_chain.set_finality_target(client.expect_header(hashof5_a).unwrap().hash()); voting_rule.set_expected_best_block(hashof10_a); @@ -1940,7 +1940,7 @@ async fn justification_with_equivocation() { precommits.push(precommit); } - // we create an equivocation for the 67th validator targetting blocks #1 and #2. + // we create an equivocation for the 67th validator targeting blocks #1 and #2. // this should be accounted as "voting for all blocks" and therefore block #3 will // have 67/100 votes, reaching finality threshold. { diff --git a/substrate/client/consensus/grandpa/src/until_imported.rs b/substrate/client/consensus/grandpa/src/until_imported.rs index 14f32ecc883..f3874086b58 100644 --- a/substrate/client/consensus/grandpa/src/until_imported.rs +++ b/substrate/client/consensus/grandpa/src/until_imported.rs @@ -1002,7 +1002,7 @@ mod tests { } #[test] - fn block_global_message_wait_completed_return_none_on_block_number_missmatch() { + fn block_global_message_wait_completed_return_none_on_block_number_mismatch() { let msg_inner = test_catch_up(); let waiting_block_1 = diff --git a/substrate/client/consensus/grandpa/src/voting_rule.rs b/substrate/client/consensus/grandpa/src/voting_rule.rs index e09780739c7..c37596d20f6 100644 --- a/substrate/client/consensus/grandpa/src/voting_rule.rs +++ b/substrate/client/consensus/grandpa/src/voting_rule.rs @@ -196,7 +196,7 @@ where target_header = backend .header(target_hash) .ok()? - .expect("Header known to exist due to the existence of one of its descendents; qed"); + .expect("Header known to exist due to the existence of one of its descendants; qed"); } } diff --git a/substrate/client/consensus/grandpa/src/warp_proof.rs b/substrate/client/consensus/grandpa/src/warp_proof.rs index 29111712ec3..7169a424c14 100644 --- a/substrate/client/consensus/grandpa/src/warp_proof.rs +++ b/substrate/client/consensus/grandpa/src/warp_proof.rs @@ -249,7 +249,7 @@ impl> NetworkProvider: BlockNumberOps, { - /// Create a new istance for a given backend and authority set. + /// Create a new instance for a given backend and authority set. pub fn new( backend: Arc, authority_set: SharedAuthoritySet>, diff --git a/substrate/client/consensus/manual-seal/src/consensus/babe.rs b/substrate/client/consensus/manual-seal/src/consensus/babe.rs index 26fa8145980..bc56ce02271 100644 --- a/substrate/client/consensus/manual-seal/src/consensus/babe.rs +++ b/substrate/client/consensus/manual-seal/src/consensus/babe.rs @@ -82,7 +82,7 @@ pub struct BabeVerifier { } impl BabeVerifier { - /// create a nrew verifier + /// create a new verifier pub fn new(epoch_changes: SharedEpochChanges, client: Arc) -> BabeVerifier { BabeVerifier { epoch_changes, client } } diff --git a/substrate/client/consensus/slots/src/lib.rs b/substrate/client/consensus/slots/src/lib.rs index 12636aae7a4..d9d79200531 100644 --- a/substrate/client/consensus/slots/src/lib.rs +++ b/substrate/client/consensus/slots/src/lib.rs @@ -555,7 +555,7 @@ impl SlotProportion { Self(inner.clamp(0.0, 1.0)) } - /// Returns the inner that is guaranted to be in the range `[0,1]`. + /// Returns the inner that is guaranteed to be in the range `[0,1]`. pub fn get(&self) -> f32 { self.0 } @@ -648,7 +648,7 @@ pub fn proposing_remaining_duration( } /// Calculate a slot duration lenience based on the number of missed slots from current -/// to parent. If the number of skipped slots is greated than 0 this method will apply +/// to parent. If the number of skipped slots is greater than 0 this method will apply /// an exponential backoff of at most `2^7 * slot_duration`, if no slots were skipped /// this method will return `None.` pub fn slot_lenience_exponential( @@ -680,7 +680,7 @@ pub fn slot_lenience_exponential( } /// Calculate a slot duration lenience based on the number of missed slots from current -/// to parent. If the number of skipped slots is greated than 0 this method will apply +/// to parent. If the number of skipped slots is greater than 0 this method will apply /// a linear backoff of at most `20 * slot_duration`, if no slots were skipped /// this method will return `None.` pub fn slot_lenience_linear( diff --git a/substrate/client/db/src/upgrade.rs b/substrate/client/db/src/upgrade.rs index f1e503867df..475220d9991 100644 --- a/substrate/client/db/src/upgrade.rs +++ b/substrate/client/db/src/upgrade.rs @@ -79,7 +79,7 @@ impl fmt::Display for UpgradeError { write!(f, "Database version comes from future version of the client: {}", version) }, UpgradeError::DecodingJustificationBlock => { - write!(f, "Decodoning justification block failed") + write!(f, "Decoding justification block failed") }, UpgradeError::Io(err) => write!(f, "Io error: {}", err), } diff --git a/substrate/client/db/src/utils.rs b/substrate/client/db/src/utils.rs index abf9c4629ce..b532e0d4666 100644 --- a/substrate/client/db/src/utils.rs +++ b/substrate/client/db/src/utils.rs @@ -338,7 +338,7 @@ fn open_kvdb_rocksdb( db_config.memory_budget = memory_budget; let db = kvdb_rocksdb::Database::open(&db_config, path)?; - // write database version only after the database is succesfully opened + // write database version only after the database is successfully opened crate::upgrade::update_version(path)?; Ok(sp_database::as_database(db)) } diff --git a/substrate/client/executor/common/src/error.rs b/substrate/client/executor/common/src/error.rs index b7c7e2b7019..9d489eaae42 100644 --- a/substrate/client/executor/common/src/error.rs +++ b/substrate/client/executor/common/src/error.rs @@ -145,7 +145,7 @@ pub enum WasmError { #[error("{0}")] Instantiation(String), - /// Other error happenend. + /// Other error happened. #[error("Other error happened while constructing the runtime: {0}")] Other(String), } diff --git a/substrate/client/executor/wasmtime/src/runtime.rs b/substrate/client/executor/wasmtime/src/runtime.rs index 595cc503272..286d134ecd1 100644 --- a/substrate/client/executor/wasmtime/src/runtime.rs +++ b/substrate/client/executor/wasmtime/src/runtime.rs @@ -462,7 +462,7 @@ pub struct Semantics { pub struct Config { /// The WebAssembly standard requires all imports of an instantiated module to be resolved, /// otherwise, the instantiation fails. If this option is set to `true`, then this behavior is - /// overriden and imports that are requested by the module and not provided by the host + /// overridden and imports that are requested by the module and not provided by the host /// functions will be resolved using stubs. These stubs will trap upon a call. pub allow_missing_func_imports: bool, diff --git a/substrate/client/executor/wasmtime/src/tests.rs b/substrate/client/executor/wasmtime/src/tests.rs index 1c06da1e3c1..f86a4275769 100644 --- a/substrate/client/executor/wasmtime/src/tests.rs +++ b/substrate/client/executor/wasmtime/src/tests.rs @@ -254,7 +254,7 @@ fn test_nan_canonicalization(instantiation_strategy: InstantiationStrategy) { /// A NaN with canonical payload bits. const CANONICAL_NAN_BITS: u32 = 0x7fc00000; - /// A NaN value with an abitrary payload. + /// A NaN value with an arbitrary payload. const ARBITRARY_NAN_BITS: u32 = 0x7f812345; // This test works like this: we essentially do @@ -272,7 +272,7 @@ fn test_nan_canonicalization(instantiation_strategy: InstantiationStrategy) { // However, with the `canonicalize_nans` option turned on above, we expect that the output will // be a canonical NaN. // - // We exterpolate the results of this tests so that we assume that all intermediate computations + // We extrapolate the results of this tests so that we assume that all intermediate computations // that involve floats are sanitized and cannot produce a non-deterministic NaN. let params = (u32::to_le_bytes(ARBITRARY_NAN_BITS), u32::to_le_bytes(1)).encode(); diff --git a/substrate/client/network/bitswap/src/lib.rs b/substrate/client/network/bitswap/src/lib.rs index 0586354d6a0..1ba95e30bad 100644 --- a/substrate/client/network/bitswap/src/lib.rs +++ b/substrate/client/network/bitswap/src/lib.rs @@ -301,7 +301,7 @@ mod tests { use substrate_test_runtime_client::{self, prelude::*, TestClientBuilder}; #[tokio::test] - async fn undecodeable_message() { + async fn undecodable_message() { let client = substrate_test_runtime_client::new(); let (bitswap, config) = BitswapRequestHandler::new(Arc::new(client)); diff --git a/substrate/client/network/src/protocol/notifications/behaviour.rs b/substrate/client/network/src/protocol/notifications/behaviour.rs index 9ad41e376e8..b945d4bfc60 100644 --- a/substrate/client/network/src/protocol/notifications/behaviour.rs +++ b/substrate/client/network/src/protocol/notifications/behaviour.rs @@ -2668,7 +2668,7 @@ mod tests { // // there is not straight-forward way of adding backoff to `PeerState::Disabled` // so manually adjust the value in order to progress on to the next stage. - // This modification together with `ConnectionClosed` will conver the peer + // This modification together with `ConnectionClosed` will convert the peer // state into `PeerState::Backoff`. if let Some(PeerState::Disabled { ref mut backoff_until, .. }) = notif.peers.get_mut(&(peer, set_id)) diff --git a/substrate/client/network/src/protocol/notifications/handler.rs b/substrate/client/network/src/protocol/notifications/handler.rs index 28662be29fe..391252c3ffe 100644 --- a/substrate/client/network/src/protocol/notifications/handler.rs +++ b/substrate/client/network/src/protocol/notifications/handler.rs @@ -211,7 +211,7 @@ enum State { /// consequently trying to open the various notifications substreams. /// /// A [`NotifsHandlerOut::OpenResultOk`] or a [`NotifsHandlerOut::OpenResultErr`] event must - /// be emitted when transitionning to respectively [`State::Open`] or [`State::Closed`]. + /// be emitted when transitioning to respectively [`State::Open`] or [`State::Closed`]. Opening { /// Substream opened by the remote. If `Some`, has been accepted. in_substream: Option>, diff --git a/substrate/client/network/src/protocol/notifications/service/mod.rs b/substrate/client/network/src/protocol/notifications/service/mod.rs index 62e6d88a3d5..6d9873f45d5 100644 --- a/substrate/client/network/src/protocol/notifications/service/mod.rs +++ b/substrate/client/network/src/protocol/notifications/service/mod.rs @@ -54,7 +54,7 @@ const COMMAND_QUEUE_SIZE: usize = 64; /// Type representing subscribers of a notification protocol. type Subscribers = Arc>>>; -/// Type represending a distributable message sink. +/// Type representing a distributable message sink. /// Detached message sink must carry the protocol name for registering metrics. /// /// See documentation for [`PeerContext`] for more details. @@ -175,11 +175,11 @@ pub enum NotificationCommand { /// and an additional, distributable `NotificationsSink` which the protocol may acquire /// if it wishes to send notifications through `NotificationsSink` directly. /// -/// The distributable `NoticationsSink` is wrapped in an `Arc>` to allow +/// The distributable `NotificationsSink` is wrapped in an `Arc>` to allow /// `NotificationsService` to swap the underlying sink in case it's replaced. #[derive(Debug, Clone)] struct PeerContext { - /// Sink for sending notificaitons. + /// Sink for sending notifications. sink: NotificationsSink, /// Distributable notification sink. diff --git a/substrate/client/network/src/protocol/notifications/service/tests.rs b/substrate/client/network/src/protocol/notifications/service/tests.rs index 02ba9e1711c..238e0ccf566 100644 --- a/substrate/client/network/src/protocol/notifications/service/tests.rs +++ b/substrate/client/network/src/protocol/notifications/service/tests.rs @@ -437,7 +437,7 @@ async fn peer_disconnects_then_async_notification_is_sent() { notif.send_async_notification(&peer_id, vec![1, 3, 3, 7]).await { } else { - panic!("invalid state after calling `send_async_notificatio()` on closed connection") + panic!("invalid state after calling `send_async_notification()` on closed connection") } } diff --git a/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs b/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs index 4e1c033f33b..85209a888cd 100644 --- a/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs +++ b/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs @@ -188,7 +188,7 @@ where } } -/// Yielded by the [`NotificationsIn`] after a successfuly upgrade. +/// Yielded by the [`NotificationsIn`] after a successfully upgrade. pub struct NotificationsInOpen { /// Handshake sent by the remote. pub handshake: Vec, @@ -415,7 +415,7 @@ where } } -/// Yielded by the [`NotificationsOut`] after a successfuly upgrade. +/// Yielded by the [`NotificationsOut`] after a successfully upgrade. pub struct NotificationsOutOpen { /// Handshake returned by the remote. pub handshake: Vec, diff --git a/substrate/client/network/src/protocol_controller.rs b/substrate/client/network/src/protocol_controller.rs index 4c8f119baa2..7f851fd8e9c 100644 --- a/substrate/client/network/src/protocol_controller.rs +++ b/substrate/client/network/src/protocol_controller.rs @@ -448,7 +448,7 @@ impl ProtocolController { self.peer_store.report_disconnect(peer_id); } - /// Ask `Peerset` if the peer has a reputation value not sufficent for connection with it. + /// Ask `Peerset` if the peer has a reputation value not sufficient for connection with it. fn is_banned(&self, peer_id: &PeerId) -> bool { self.peer_store.is_banned(peer_id) } @@ -2020,7 +2020,7 @@ mod tests { ProtocolController::new(SetId::from(0), config, tx, Box::new(peer_store)); assert!(matches!(controller.reserved_nodes.get(&reserved1), Some(PeerState::NotConnected))); - // Initiate connectios + // Initiate connections controller.alloc_slots(); assert!(matches!(controller.reserved_nodes.get(&reserved1), Some(PeerState::NotConnected))); assert_eq!(rx.try_recv().unwrap_err(), TryRecvError::Empty); diff --git a/substrate/client/network/sync/src/engine.rs b/substrate/client/network/sync/src/engine.rs index 24640fdc455..ff40ae95624 100644 --- a/substrate/client/network/sync/src/engine.rs +++ b/substrate/client/network/sync/src/engine.rs @@ -110,7 +110,7 @@ const INACTIVITY_EVICT_THRESHOLD: Duration = Duration::from_secs(30); /// Parachain collator may incorrectly get evicted because it's waiting to receive a number of /// relaychain blocks before it can start creating parachain blocks. During this wait, /// `SyncingEngine` still counts it as active and as the peer is not sending blocks, it may get -/// evicted if a block is not received within the first 30 secons since the peer connected. +/// evicted if a block is not received within the first 30 seconds since the peer connected. /// /// To prevent this from happening, define a threshold for how long `SyncingEngine` should wait /// before it starts evicting peers. @@ -424,7 +424,7 @@ where .expect("Genesis block exists; qed"), ); - // Split warp sync params into warp sync config and a channel to retreive target block + // Split warp sync params into warp sync config and a channel to retrieve target block // header. let (warp_sync_config, warp_sync_target_block_header_rx) = warp_sync_params.map_or((None, None), |params| { @@ -1057,7 +1057,7 @@ where // still be under validation. If the peer has different genesis than the // local node the validation fails but the peer cannot be reported in // `validate_connection()` as that is also called by - // `ValiateInboundSubstream` which means that the peer is still being + // `ValidateInboundSubstream` which means that the peer is still being // validated and banning the peer when handling that event would // result in peer getting dropped twice. // diff --git a/substrate/client/network/sync/src/strategy.rs b/substrate/client/network/sync/src/strategy.rs index dabcf37ae63..610fd7c6560 100644 --- a/substrate/client/network/sync/src/strategy.rs +++ b/substrate/client/network/sync/src/strategy.rs @@ -185,7 +185,7 @@ where + Sync + 'static, { - /// Initialize a new syncing startegy. + /// Initialize a new syncing strategy. pub fn new( config: SyncingConfig, client: Arc, @@ -418,7 +418,7 @@ where self.state.is_some() || match self.chain_sync { Some(ref s) => s.status().state.is_major_syncing(), - None => unreachable!("At least one syncing startegy is active; qed"), + None => unreachable!("At least one syncing strategy is active; qed"), } } @@ -429,7 +429,7 @@ where /// Returns the current sync status. pub fn status(&self) -> SyncStatus { - // This function presumes that startegies are executed serially and must be refactored + // This function presumes that strategies are executed serially and must be refactored // once we have parallel strategies. if let Some(ref warp) = self.warp { warp.status() @@ -438,7 +438,7 @@ where } else if let Some(ref chain_sync) = self.chain_sync { chain_sync.status() } else { - unreachable!("At least one syncing startegy is always active; qed") + unreachable!("At least one syncing strategy is always active; qed") } } @@ -518,7 +518,7 @@ where /// Proceed with the next strategy if the active one finished. pub fn proceed_to_next(&mut self) -> Result<(), ClientError> { - // The strategies are switched as `WarpSync` -> `StateStartegy` -> `ChainSync`. + // The strategies are switched as `WarpSync` -> `StateStrategy` -> `ChainSync`. if let Some(ref mut warp) = self.warp { match warp.take_result() { Some(res) => { @@ -569,7 +569,7 @@ where }, } } else if let Some(state) = &self.state { - if state.is_succeded() { + if state.is_succeeded() { info!(target: LOG_TARGET, "State sync is complete, continuing with block sync."); } else { error!(target: LOG_TARGET, "State sync failed. Falling back to full sync."); diff --git a/substrate/client/network/sync/src/strategy/chain_sync.rs b/substrate/client/network/sync/src/strategy/chain_sync.rs index ad0c75363e7..da04bbbeccc 100644 --- a/substrate/client/network/sync/src/strategy/chain_sync.rs +++ b/substrate/client/network/sync/src/strategy/chain_sync.rs @@ -117,7 +117,7 @@ mod rep { /// Reputation change for peers which send us a block with bad justifications. pub const BAD_JUSTIFICATION: Rep = Rep::new(-(1 << 16), "Bad justification"); - /// Reputation change when a peer sent us invlid ancestry result. + /// Reputation change when a peer sent us invalid ancestry result. pub const UNKNOWN_ANCESTOR: Rep = Rep::new(-(1 << 16), "DB Error"); /// Peer response data does not have requested bits. @@ -1334,7 +1334,7 @@ where PeerSyncState::DownloadingJustification(_) => { // Peers that were downloading justifications // should be kept in that state. - // We make sure our commmon number is at least something we have. + // We make sure our common number is at least something we have. trace!( target: LOG_TARGET, "Keeping peer {} after restart, updating common number from={} => to={} (our best).", diff --git a/substrate/client/network/sync/src/strategy/chain_sync/test.rs b/substrate/client/network/sync/src/strategy/chain_sync/test.rs index 127b6862f0e..cd955113542 100644 --- a/substrate/client/network/sync/src/strategy/chain_sync/test.rs +++ b/substrate/client/network/sync/src/strategy/chain_sync/test.rs @@ -189,7 +189,7 @@ fn restart_doesnt_affect_peers_downloading_finality_data() { assert_eq!(sync.peers.get(&peer_id3).unwrap().common_number, 50); } -/// Send a block annoucnement for the given `header`. +/// Send a block announcement for the given `header`. fn send_block_announce(header: Header, peer_id: PeerId, sync: &mut ChainSync) { let announce = BlockAnnounce { header: header.clone(), @@ -278,7 +278,7 @@ fn unwrap_from_block_number(from: FromBlock) -> u64 { /// announcement from this node in its sync process. Meaning our common number didn't change. It /// is now expected that we start an ancestor search to find the common number. #[test] -fn do_ancestor_search_when_common_block_to_best_qeued_gap_is_to_big() { +fn do_ancestor_search_when_common_block_to_best_queued_gap_is_to_big() { sp_tracing::try_init_simple(); let blocks = { @@ -472,7 +472,7 @@ fn can_sync_huge_fork() { let actions = sync.take_actions().collect::>(); request = if actions.is_empty() { - // We found the ancenstor + // We found the ancestor break } else { assert_eq!(actions.len(), 1); @@ -607,7 +607,7 @@ fn syncs_fork_without_duplicate_requests() { let actions = sync.take_actions().collect::>(); request = if actions.is_empty() { - // We found the ancenstor + // We found the ancestor break } else { assert_eq!(actions.len(), 1); diff --git a/substrate/client/network/sync/src/strategy/state.rs b/substrate/client/network/sync/src/strategy/state.rs index 12d36ff9e01..6d3b215f7f3 100644 --- a/substrate/client/network/sync/src/strategy/state.rs +++ b/substrate/client/network/sync/src/strategy/state.rs @@ -79,7 +79,7 @@ pub struct StateStrategy { state_sync: Box>, peers: HashMap>, actions: Vec>, - succeded: bool, + succeeded: bool, } impl StateStrategy { @@ -110,7 +110,7 @@ impl StateStrategy { )), peers, actions: Vec::new(), - succeded: false, + succeeded: false, } } @@ -129,7 +129,7 @@ impl StateStrategy { }) .collect(), actions: Vec::new(), - succeded: false, + succeeded: false, } } @@ -260,7 +260,7 @@ impl StateStrategy { "Failed to import target block with state: {e:?}." ); }); - self.succeded |= results.into_iter().any(|result| result.is_ok()); + self.succeeded |= results.into_iter().any(|result| result.is_ok()); self.actions.push(StateStrategyAction::Finished); } } @@ -342,10 +342,10 @@ impl StateStrategy { std::mem::take(&mut self.actions).into_iter() } - /// Check if state sync has succeded. + /// Check if state sync has succeeded. #[must_use] - pub fn is_succeded(&self) -> bool { - self.succeded + pub fn is_succeeded(&self) -> bool { + self.succeeded } } @@ -669,7 +669,7 @@ mod test { } #[test] - fn succesfully_importing_target_block_finishes_strategy() { + fn successfully_importing_target_block_finishes_strategy() { let target_hash = Hash::random(); let mut state_sync_provider = MockStateSync::::new(); state_sync_provider.expect_target_hash().return_const(target_hash); diff --git a/substrate/client/network/sync/src/strategy/warp.rs b/substrate/client/network/sync/src/strategy/warp.rs index 7935b5f29b6..c7b79228efe 100644 --- a/substrate/client/network/sync/src/strategy/warp.rs +++ b/substrate/client/network/sync/src/strategy/warp.rs @@ -968,7 +968,7 @@ mod test { warp_sync.on_warp_proof_response(&request_peer_id, EncodedProof(Vec::new())); - // We only interested in alredy generated actions, not new requests. + // We only interested in already generated actions, not new requests. let actions = std::mem::take(&mut warp_sync.actions); assert_eq!(actions.len(), 1); assert!(matches!( diff --git a/substrate/client/network/sync/src/warp_request_handler.rs b/substrate/client/network/sync/src/warp_request_handler.rs index 39cf1c5d806..eda67cac95f 100644 --- a/substrate/client/network/sync/src/warp_request_handler.rs +++ b/substrate/client/network/sync/src/warp_request_handler.rs @@ -57,7 +57,7 @@ pub fn generate_request_response_config>( } } -/// Generate the grandpa warp sync protocol name from the genesi hash and fork id. +/// Generate the grandpa warp sync protocol name from the genesis hash and fork id. fn generate_protocol_name>(genesis_hash: Hash, fork_id: Option<&str>) -> String { let genesis_hash = genesis_hash.as_ref(); if let Some(fork_id) = fork_id { diff --git a/substrate/client/network/test/src/sync.rs b/substrate/client/network/test/src/sync.rs index c025a8262f0..f1c1b741430 100644 --- a/substrate/client/network/test/src/sync.rs +++ b/substrate/client/network/test/src/sync.rs @@ -749,7 +749,7 @@ async fn sync_blocks_when_block_announce_validator_says_it_is_new_best() { } } -/// Waits for some time until the validation is successfull. +/// Waits for some time until the validation is successful. struct DeferredBlockAnnounceValidator; impl BlockAnnounceValidator for DeferredBlockAnnounceValidator { diff --git a/substrate/client/offchain/src/api/http.rs b/substrate/client/offchain/src/api/http.rs index 7ca5e3fd13a..46f573341c5 100644 --- a/substrate/client/offchain/src/api/http.rs +++ b/substrate/client/offchain/src/api/http.rs @@ -604,7 +604,7 @@ enum WorkerToApi { /// because we don't want the `HttpApi` to have to drive the reading. /// Instead, reading an item from the channel will notify the worker task, which will push /// the next item. - /// Can also be used to send an error, in case an error happend on the HTTP socket. After + /// Can also be used to send an error, in case an error happened on the HTTP socket. After /// an error is sent, the channel will close. body: mpsc::Receiver>, }, diff --git a/substrate/client/rpc-servers/src/middleware/metrics.rs b/substrate/client/rpc-servers/src/middleware/metrics.rs index 17849dc0c44..688c3c2a9fc 100644 --- a/substrate/client/rpc-servers/src/middleware/metrics.rs +++ b/substrate/client/rpc-servers/src/middleware/metrics.rs @@ -182,7 +182,7 @@ impl RpcMetrics { transport_label, req.method_name(), // the label "is_error", so `success` should be regarded as false - // and vice-versa to be registrered correctly. + // and vice-versa to be registered correctly. if rp.is_success() { "false" } else { "true" }, if is_rate_limited { "true" } else { "false" }, ]) diff --git a/substrate/client/rpc-spec-v2/src/archive/tests.rs b/substrate/client/rpc-spec-v2/src/archive/tests.rs index 1803ffa3a31..de71ed82a12 100644 --- a/substrate/client/rpc-spec-v2/src/archive/tests.rs +++ b/substrate/client/rpc-spec-v2/src/archive/tests.rs @@ -435,7 +435,7 @@ async fn archive_storage_closest_merkle_value() { /// The core of this test. /// - /// Checks keys that are exact match, keys with descedant and keys that should not return + /// Checks keys that are exact match, keys with descendant and keys that should not return /// values. /// /// Returns (key, merkle value) pairs. @@ -459,7 +459,7 @@ async fn archive_storage_closest_merkle_value() { query_type: StorageQueryType::ClosestDescendantMerkleValue, pagination_start_key: None, }, - // Key with descedent. + // Key with descendant. PaginatedStorageQuery { key: hex_string(b":A"), query_type: StorageQueryType::ClosestDescendantMerkleValue, diff --git a/substrate/client/rpc-spec-v2/src/chain_head/event.rs b/substrate/client/rpc-spec-v2/src/chain_head/event.rs index e0c804d16eb..bd986306091 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/event.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/event.rs @@ -111,7 +111,7 @@ impl From for RuntimeEvent { #[derive(Debug, Clone, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Initialized { - /// The hash of the lastest finalized blocks. + /// The hash of the latest finalized blocks. pub finalized_block_hashes: Vec, /// The runtime version of the finalized block. /// @@ -315,7 +315,7 @@ pub enum FollowEvent { Stop, } -/// The method respose of `chainHead_body`, `chainHead_call` and `chainHead_storage`. +/// The method response of `chainHead_body`, `chainHead_call` and `chainHead_storage`. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(tag = "result")] diff --git a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs index 4d9dfb24e0a..30152efb5b6 100644 --- a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs @@ -2786,7 +2786,7 @@ async fn ensure_operation_limits_works() { FollowEvent::OperationStorageDone(done) if done.operation_id == operation_id ); - // The storage is finished and capactiy must be released. + // The storage is finished and capacity must be released. let alice_id = AccountKeyring::Alice.to_account_id(); // Hex encoded scale encoded bytes representing the call parameters. let call_parameters = hex_string(&alice_id.encode()); @@ -3113,7 +3113,7 @@ async fn storage_closest_merkle_value() { /// The core of this test. /// - /// Checks keys that are exact match, keys with descedant and keys that should not return + /// Checks keys that are exact match, keys with descendant and keys that should not return /// values. /// /// Returns (key, merkle value) pairs. @@ -3139,7 +3139,7 @@ async fn storage_closest_merkle_value() { key: hex_string(b":AAAB"), query_type: StorageQueryType::ClosestDescendantMerkleValue }, - // Key with descedent. + // Key with descendant. StorageQuery { key: hex_string(b":A"), query_type: StorageQueryType::ClosestDescendantMerkleValue diff --git a/substrate/client/rpc-spec-v2/src/transaction/tests/transaction_broadcast_tests.rs b/substrate/client/rpc-spec-v2/src/transaction/tests/transaction_broadcast_tests.rs index 690a1a64d74..77a28968aed 100644 --- a/substrate/client/rpc-spec-v2/src/transaction/tests/transaction_broadcast_tests.rs +++ b/substrate/client/rpc-spec-v2/src/transaction/tests/transaction_broadcast_tests.rs @@ -372,7 +372,7 @@ async fn tx_broadcast_resubmits_invalid_tx() { client_mock.trigger_import_stream(block_2_header).await; // Ensure we propagate the temporary ban error to `submit_and_watch`. - // This ensures we'll loop again with the next annmounced block and try to resubmit the + // This ensures we'll loop again with the next announced block and try to resubmit the // transaction. The transaction remains temporarily banned until the pool is maintained. let event = get_next_event!(&mut pool_middleware); assert_matches!(event, MiddlewarePoolEvent::PoolError { transaction, err } if transaction == xt && err.contains("Transaction temporarily Banned")); @@ -429,7 +429,7 @@ async fn tx_broadcast_resubmits_invalid_tx() { } /// This is similar to `tx_broadcast_resubmits_invalid_tx`. -/// However, it forces the tx to be resubmited because of the pool +/// However, it forces the tx to be resubmitted because of the pool /// limits. Which is a different code path than the invalid tx. #[tokio::test] async fn tx_broadcast_resubmits_dropped_tx() { @@ -509,7 +509,7 @@ async fn tx_broadcast_resubmits_dropped_tx() { pool.inner_pool.maintain(event).await; client_mock.trigger_import_stream(block_3_header.clone()).await; - // The first tx is in a finalzied block; the future tx must enter the pool. + // The first tx is in a finalized block; the future tx must enter the pool. let events = get_next_tx_events!(&mut pool_middleware, 3); assert_eq!( events.get(¤t_xt).unwrap(), diff --git a/substrate/client/rpc-spec-v2/src/transaction/transaction_broadcast.rs b/substrate/client/rpc-spec-v2/src/transaction/transaction_broadcast.rs index 92c83826187..6eaf50d6b2e 100644 --- a/substrate/client/rpc-spec-v2/src/transaction/transaction_broadcast.rs +++ b/substrate/client/rpc-spec-v2/src/transaction/transaction_broadcast.rs @@ -44,7 +44,7 @@ pub struct TransactionBroadcast { pool: Arc, /// Executor to spawn subscriptions. executor: SubscriptionTaskExecutor, - /// The brodcast operation IDs. + /// The broadcast operation IDs. broadcast_ids: Arc>>, } @@ -200,7 +200,7 @@ where } } -/// Returns the last element of the providided stream, or `None` if the stream is closed. +/// Returns the last element of the provided stream, or `None` if the stream is closed. async fn last_stream_element(stream: &mut S) -> Option where S: Stream + Unpin, diff --git a/substrate/client/rpc/src/statement/mod.rs b/substrate/client/rpc/src/statement/mod.rs index b4f432bbbb0..e99135aec38 100644 --- a/substrate/client/rpc/src/statement/mod.rs +++ b/substrate/client/rpc/src/statement/mod.rs @@ -89,7 +89,7 @@ impl StatementApiServer for StatementStore { fn submit(&self, encoded: Bytes) -> RpcResult<()> { let statement = Decode::decode(&mut &*encoded) - .map_err(|e| Error::StatementStore(format!("Eror decoding statement: {:?}", e)))?; + .map_err(|e| Error::StatementStore(format!("Error decoding statement: {:?}", e)))?; match self.store.submit(statement, StatementSource::Local) { SubmitResult::New(_) | SubmitResult::Known => Ok(()), // `KnownExpired` should not happen. Expired statements submitted with diff --git a/substrate/client/service/src/chain_ops/import_blocks.rs b/substrate/client/service/src/chain_ops/import_blocks.rs index 34f7669d010..661fc09a8f1 100644 --- a/substrate/client/service/src/chain_ops/import_blocks.rs +++ b/substrate/client/service/src/chain_ops/import_blocks.rs @@ -73,7 +73,7 @@ where reader: CodecIoReader, }, Json { - // Nubmer of blocks we have decoded thus far. + // Number of blocks we have decoded thus far. read_block_count: u64, // Stream to the data, used for decoding new blocks. reader: StreamDeserializer<'static, JsonIoRead, SignedBlock>, diff --git a/substrate/client/service/src/config.rs b/substrate/client/service/src/config.rs index 35262ff493b..59e307d7f93 100644 --- a/substrate/client/service/src/config.rs +++ b/substrate/client/service/src/config.rs @@ -236,7 +236,7 @@ impl Configuration { ProtocolId::from(protocol_id_full) } - /// Returns true if the genesis state writting will be skipped while initializing the genesis + /// Returns true if the genesis state writing will be skipped while initializing the genesis /// block. pub fn no_genesis(&self) -> bool { matches!(self.network.sync_mode, SyncMode::LightState { .. } | SyncMode::Warp { .. }) diff --git a/substrate/client/state-db/src/lib.rs b/substrate/client/state-db/src/lib.rs index 41c231c31aa..6c37c87a611 100644 --- a/substrate/client/state-db/src/lib.rs +++ b/substrate/client/state-db/src/lib.rs @@ -872,7 +872,7 @@ mod tests { fn check_stored_and_requested_mode_compatibility( mode_when_created: Option, mode_when_reopened: Option, - expected_effective_mode_when_reopenned: Result, + expected_effective_mode_when_reopened: Result, ) { let mut db = make_db(&[]); let (state_db_init, state_db) = @@ -883,7 +883,7 @@ mod tests { let state_db_reopen_result = StateDb::::open(db.clone(), mode_when_reopened, false, false); - if let Ok(expected_mode) = expected_effective_mode_when_reopenned { + if let Ok(expected_mode) = expected_effective_mode_when_reopened { let (state_db_init, state_db_reopened) = state_db_reopen_result.unwrap(); db.commit(&state_db_init); assert_eq!(state_db_reopened.pruning_mode(), expected_mode,) diff --git a/substrate/client/state-db/src/noncanonical.rs b/substrate/client/state-db/src/noncanonical.rs index bdbe8318371..4492a7bd077 100644 --- a/substrate/client/state-db/src/noncanonical.rs +++ b/substrate/client/state-db/src/noncanonical.rs @@ -46,26 +46,26 @@ pub struct NonCanonicalOverlay { #[cfg_attr(test, derive(PartialEq, Debug))] struct OverlayLevel { blocks: Vec>, - used_indicies: u64, // Bitmask of available journal indicies. + used_indices: u64, // Bitmask of available journal indices. } impl OverlayLevel { fn push(&mut self, overlay: BlockOverlay) { - self.used_indicies |= 1 << overlay.journal_index; + self.used_indices |= 1 << overlay.journal_index; self.blocks.push(overlay) } fn available_index(&self) -> u64 { - self.used_indicies.trailing_ones() as u64 + self.used_indices.trailing_ones() as u64 } fn remove(&mut self, index: usize) -> BlockOverlay { - self.used_indicies &= !(1 << self.blocks[index].journal_index); + self.used_indices &= !(1 << self.blocks[index].journal_index); self.blocks.remove(index) } fn new() -> OverlayLevel { - OverlayLevel { blocks: Vec::new(), used_indicies: 0 } + OverlayLevel { blocks: Vec::new(), used_indices: 0 } } } diff --git a/substrate/client/telemetry/src/lib.rs b/substrate/client/telemetry/src/lib.rs index 113d8303a20..7e3a4ee8639 100644 --- a/substrate/client/telemetry/src/lib.rs +++ b/substrate/client/telemetry/src/lib.rs @@ -413,7 +413,7 @@ impl Telemetry { .map_err(|_| Error::TelemetryWorkerDropped) } - /// Make a new cloneable handle to this [`Telemetry`]. This is used for reporting telemetries. + /// Make a new clonable handle to this [`Telemetry`]. This is used for reporting telemetries. pub fn handle(&self) -> TelemetryHandle { TelemetryHandle { message_sender: Arc::new(Mutex::new(self.message_sender.clone())), diff --git a/substrate/client/transaction-pool/README.md b/substrate/client/transaction-pool/README.md index b55dc6482d6..7a53727d576 100644 --- a/substrate/client/transaction-pool/README.md +++ b/substrate/client/transaction-pool/README.md @@ -171,7 +171,7 @@ This parameter instructs the pool propagate/gossip a transaction to node peers. By default this should be `true`, however in some cases it might be undesirable to propagate transactions further. Examples might include heavy transactions produced by block authors in offchain workers (DoS) or risking being front -runned by someone else after finding some non trivial solution or equivocation, +ran by someone else after finding some non trivial solution or equivocation, etc. ### 'TransactionSource` diff --git a/substrate/client/transaction-pool/tests/pool.rs b/substrate/client/transaction-pool/tests/pool.rs index 461b9860d41..49bd2203c12 100644 --- a/substrate/client/transaction-pool/tests/pool.rs +++ b/substrate/client/transaction-pool/tests/pool.rs @@ -999,7 +999,7 @@ fn import_notification_to_pool_maintain_works() { .0, ); - // Prepare the extrisic, push it to the pool and check that it was added. + // Prepare the extrinsic, push it to the pool and check that it was added. let xt = uxt(Alice, 0); block_on(pool.submit_one( pool.api().block_id_to_hash(&BlockId::Number(0)).unwrap().unwrap(), diff --git a/substrate/client/utils/src/notification.rs b/substrate/client/utils/src/notification.rs index dabb85d613c..3f606aabe3a 100644 --- a/substrate/client/utils/src/notification.rs +++ b/substrate/client/utils/src/notification.rs @@ -44,7 +44,7 @@ mod tests; /// and identify the mpsc channels. pub trait TracingKeyStr { /// Const `str` representing the "tracing key" used to tag and identify - /// the mpsc channels owned by the object implemeting this trait. + /// the mpsc channels owned by the object implementing this trait. const TRACING_KEY: &'static str; } diff --git a/substrate/frame/alliance/README.md b/substrate/frame/alliance/README.md index 9930008e2d6..16335a98f59 100644 --- a/substrate/frame/alliance/README.md +++ b/substrate/frame/alliance/README.md @@ -58,7 +58,7 @@ to update the Alliance's rule and make announcements. - `add_unscrupulous_items` - Add some items, either accounts or websites, to the list of unscrupulous items. - `remove_unscrupulous_items` - Remove some items from the list of unscrupulous items. -- `abdicate_fellow_status` - Abdicate one's voting rights, demoting themself to Ally. +- `abdicate_fellow_status` - Abdicate one's voting rights, demoting themselves to Ally. #### Root Calls diff --git a/substrate/frame/alliance/src/lib.rs b/substrate/frame/alliance/src/lib.rs index d4703db68db..414d550c53a 100644 --- a/substrate/frame/alliance/src/lib.rs +++ b/substrate/frame/alliance/src/lib.rs @@ -505,10 +505,10 @@ pub mod pallet { proposal: Box<>::Proposal>, #[pallet::compact] length_bound: u32, ) -> DispatchResult { - let proposor = ensure_signed(origin)?; - ensure!(Self::has_voting_rights(&proposor), Error::::NoVotingRights); + let proposer = ensure_signed(origin)?; + ensure!(Self::has_voting_rights(&proposer), Error::::NoVotingRights); - T::ProposalProvider::propose_proposal(proposor, threshold, proposal, length_bound)?; + T::ProposalProvider::propose_proposal(proposer, threshold, proposal, length_bound)?; Ok(()) } diff --git a/substrate/frame/alliance/src/tests.rs b/substrate/frame/alliance/src/tests.rs index 710de5a54bc..c65f10228e7 100644 --- a/substrate/frame/alliance/src/tests.rs +++ b/substrate/frame/alliance/src/tests.rs @@ -26,7 +26,7 @@ use crate::mock::*; type AllianceMotionEvent = pallet_collective::Event; fn assert_powerless(user: RuntimeOrigin, user_is_member: bool) { - //vote / veto with a valid propsal + //vote / veto with a valid proposal let cid = test_cid(); let (proposal, _, _) = make_kick_member_proposal(42); diff --git a/substrate/frame/asset-conversion/src/lib.rs b/substrate/frame/asset-conversion/src/lib.rs index c9725f9d39d..0bf73e8809c 100644 --- a/substrate/frame/asset-conversion/src/lib.rs +++ b/substrate/frame/asset-conversion/src/lib.rs @@ -205,7 +205,7 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// A successful call of the `CretaPool` extrinsic will create this event. + /// A successful call of the `CreatePool` extrinsic will create this event. PoolCreated { /// The account that created the pool. creator: T::AccountId, diff --git a/substrate/frame/asset-rate/src/lib.rs b/substrate/frame/asset-rate/src/lib.rs index befabfe54aa..69f8267a4f2 100644 --- a/substrate/frame/asset-rate/src/lib.rs +++ b/substrate/frame/asset-rate/src/lib.rs @@ -112,7 +112,7 @@ pub mod pallet { /// The origin permissioned to remove an existing conversion rate for an asset. type RemoveOrigin: EnsureOrigin; - /// The origin permissioned to update an existiing conversion rate for an asset. + /// The origin permissioned to update an existing conversion rate for an asset. type UpdateOrigin: EnsureOrigin; /// The currency mechanism for this pallet. diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs index 583c75b3827..c5468e4237d 100644 --- a/substrate/frame/assets/src/lib.rs +++ b/substrate/frame/assets/src/lib.rs @@ -183,7 +183,7 @@ pub use weights::WeightInfo; type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; const LOG_TARGET: &str = "runtime::assets"; -/// Trait with callbacks that are executed after successfull asset creation or destruction. +/// Trait with callbacks that are executed after successful asset creation or destruction. pub trait AssetsCallback { /// Indicates that asset with `id` was successfully created by the `owner` fn created(_id: &AssetId, _owner: &AccountId) -> Result<(), ()> { diff --git a/substrate/frame/assets/src/tests.rs b/substrate/frame/assets/src/tests.rs index e09648a51ec..c7021bcad53 100644 --- a/substrate/frame/assets/src/tests.rs +++ b/substrate/frame/assets/src/tests.rs @@ -1453,7 +1453,7 @@ fn force_asset_status_should_work() { )); assert_eq!(Assets::balance(0, 1), 50); - // account can recieve assets for balance < min_balance + // account can receive assets for balance < min_balance assert_ok!(Assets::transfer(RuntimeOrigin::signed(2), 0, 1, 1)); assert_eq!(Assets::balance(0, 1), 51); diff --git a/substrate/frame/babe/src/benchmarking.rs b/substrate/frame/babe/src/benchmarking.rs index 92f55665913..6b0e31e8471 100644 --- a/substrate/frame/babe/src/benchmarking.rs +++ b/substrate/frame/babe/src/benchmarking.rs @@ -31,7 +31,7 @@ benchmarks! { // NOTE: generated with the test below `test_generate_equivocation_report_blob`. // the output is not deterministic since keys are generated randomly (and therefore // signature content changes). it should not affect the benchmark. - // with the current benchmark setup it is not possible to generate this programatically + // with the current benchmark setup it is not possible to generate this programmatically // from the benchmark setup. const EQUIVOCATION_PROOF_BLOB: [u8; 416] = [ 222, 241, 46, 66, 243, 228, 135, 233, 177, 64, 149, 170, 141, 92, 193, 106, 51, 73, 31, diff --git a/substrate/frame/bags-list/src/list/tests.rs b/substrate/frame/bags-list/src/list/tests.rs index fd4ad8f893a..cd39b083172 100644 --- a/substrate/frame/bags-list/src/list/tests.rs +++ b/substrate/frame/bags-list/src/list/tests.rs @@ -431,7 +431,7 @@ mod list { #[test] fn insert_at_unchecked_at_is_only_node() { // Note that this `insert_at_unchecked` test should fail post checks because node 42 does - // not get re-assigned the correct bagu pper. This is because `insert_at_unchecked` assumes + // not get re-assigned the correct bag upper. This is because `insert_at_unchecked` assumes // both nodes are already in the same bag with the correct bag upper. ExtBuilder::default().build_and_execute_no_post_check(|| { // given diff --git a/substrate/frame/balances/src/lib.rs b/substrate/frame/balances/src/lib.rs index 3fd3102cd35..80278752207 100644 --- a/substrate/frame/balances/src/lib.rs +++ b/substrate/frame/balances/src/lib.rs @@ -677,7 +677,7 @@ pub mod pallet { /// /// This will waive the transaction fee if at least all but 10% of the accounts needed to /// be upgraded. (We let some not have to be upgraded just in order to allow for the - /// possibililty of churn). + /// possibility of churn). #[pallet::call_index(6)] #[pallet::weight(T::WeightInfo::upgrade_accounts(who.len() as u32))] pub fn upgrade_accounts( @@ -905,14 +905,14 @@ pub mod pallet { Self::try_mutate_account(who, |a, _| -> Result { Ok(f(a)) }) } - /// Returns `true` when `who` has some providers or `insecure_zero_ed` feature is disnabled. + /// Returns `true` when `who` has some providers or `insecure_zero_ed` feature is disabled. /// Returns `false` otherwise. #[cfg(not(feature = "insecure_zero_ed"))] fn have_providers_or_no_zero_ed(_: &T::AccountId) -> bool { true } - /// Returns `true` when `who` has some providers or `insecure_zero_ed` feature is disnabled. + /// Returns `true` when `who` has some providers or `insecure_zero_ed` feature is disabled. /// Returns `false` otherwise. #[cfg(feature = "insecure_zero_ed")] fn have_providers_or_no_zero_ed(who: &T::AccountId) -> bool { diff --git a/substrate/frame/balances/src/tests/currency_tests.rs b/substrate/frame/balances/src/tests/currency_tests.rs index 46a4c4caefc..bd4ff762c74 100644 --- a/substrate/frame/balances/src/tests/currency_tests.rs +++ b/substrate/frame/balances/src/tests/currency_tests.rs @@ -1024,7 +1024,7 @@ fn slash_consumed_slash_partial_works() { } #[test] -fn slash_on_non_existant_works() { +fn slash_on_non_existent_works() { ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { // Slash on non-existent account is okay. assert_eq!(Balances::slash(&12345, 1_300), (NegativeImbalance::new(0), 1300)); @@ -1071,7 +1071,7 @@ fn slash_reserved_overslash_does_not_touch_free_balance() { } #[test] -fn slash_reserved_on_non_existant_works() { +fn slash_reserved_on_non_existent_works() { ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { // Slash on non-existent account is okay. assert_eq!(Balances::slash_reserved(&12345, 1_300), (NegativeImbalance::new(0), 1300)); diff --git a/substrate/frame/balances/src/tests/reentrancy_tests.rs b/substrate/frame/balances/src/tests/reentrancy_tests.rs index 1afbe82c7e2..717f0497857 100644 --- a/substrate/frame/balances/src/tests/reentrancy_tests.rs +++ b/substrate/frame/balances/src/tests/reentrancy_tests.rs @@ -44,7 +44,7 @@ fn transfer_dust_removal_tst1_should_work() { assert_eq!(Balances::free_balance(&2), 0); // As expected beneficiary account 3 - // received the transfered fund. + // received the transferred fund. assert_eq!(Balances::free_balance(&3), 450); // Dust balance is deposited to account 1 @@ -123,7 +123,7 @@ fn repatriating_reserved_balance_dust_removal_should_work() { // Reserve a value on account 2, // Such that free balance is lower than - // Exestintial deposit. + // Existential deposit. assert_ok!(Balances::transfer_allow_death(RuntimeOrigin::signed(2), 1, 450)); // Since free balance of account 2 is lower than diff --git a/substrate/frame/benchmarking/src/analysis.rs b/substrate/frame/benchmarking/src/analysis.rs index 5fc3abb5a27..987078ff79a 100644 --- a/substrate/frame/benchmarking/src/analysis.rs +++ b/substrate/frame/benchmarking/src/analysis.rs @@ -41,7 +41,7 @@ pub enum BenchmarkSelector { /// Multiplies the value by 1000 and converts it into an u128. fn mul_1000_into_u128(value: f64) -> u128 { - // This is slighly more precise than the alternative of `(value * 1000.0) as u128`. + // This is slightly more precise than the alternative of `(value * 1000.0) as u128`. (value as u128) .saturating_mul(1000) .saturating_add((value.fract() * 1000.0) as u128) diff --git a/substrate/frame/benchmarking/src/lib.rs b/substrate/frame/benchmarking/src/lib.rs index f79582d03e5..d4ee0abbecc 100644 --- a/substrate/frame/benchmarking/src/lib.rs +++ b/substrate/frame/benchmarking/src/lib.rs @@ -203,7 +203,7 @@ pub use v1::*; /// ## Where Clause /// /// Some pallets require a where clause specifying constraints on their generics to make -/// writing benchmarks feasible. To accomodate this situation, you can provide such a where +/// writing benchmarks feasible. To accommodate this situation, you can provide such a where /// clause as the (only) argument to the `#[benchmarks]` or `#[instance_benchmarks]` attribute /// macros. Below is an example of this taken from the `message-queue` pallet. /// diff --git a/substrate/frame/benchmarking/src/v1.rs b/substrate/frame/benchmarking/src/v1.rs index 4ad8cc0edd4..b2449db3d67 100644 --- a/substrate/frame/benchmarking/src/v1.rs +++ b/substrate/frame/benchmarking/src/v1.rs @@ -874,7 +874,7 @@ macro_rules! impl_bench_name_tests { $crate::BenchmarkError::Override(_) => { // This is still considered a success condition. $crate::__private::log::error!( - "WARNING: benchmark error overrided - {}", + "WARNING: benchmark error overridden - {}", stringify!($name), ); }, @@ -1704,7 +1704,7 @@ macro_rules! impl_test_function { $crate::BenchmarkError::Override(_) => { // This is still considered a success condition. $crate::__private::log::error!( - "WARNING: benchmark error overrided - {}", + "WARNING: benchmark error overridden - {}", $crate::__private::str::from_utf8(benchmark_name) .expect("benchmark name is always a valid string!"), ); @@ -1851,7 +1851,7 @@ macro_rules! add_benchmark { Err($crate::BenchmarkError::Override(mut result)) => { // Insert override warning as the first storage key. $crate::__private::log::error!( - "WARNING: benchmark error overrided - {}", + "WARNING: benchmark error overridden - {}", $crate::__private::str::from_utf8(benchmark) .expect("benchmark name is always a valid string!") ); diff --git a/substrate/frame/broker/src/lib.rs b/substrate/frame/broker/src/lib.rs index a669463aa02..f1b49a73a52 100644 --- a/substrate/frame/broker/src/lib.rs +++ b/substrate/frame/broker/src/lib.rs @@ -683,7 +683,7 @@ pub mod pallet { /// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`. /// - `region_id`: The Region which was assigned to the Pool. /// - `max_timeslices`: The maximum number of timeslices which should be processed. This may - /// effect the weight of the call but should be ideally made equivalant to the length of + /// effect the weight of the call but should be ideally made equivalent to the length of /// the Region `region_id`. If it is less than this, then further dispatches will be /// required with the `region_id` which makes up any remainders of the region to be /// collected. diff --git a/substrate/frame/broker/src/types.rs b/substrate/frame/broker/src/types.rs index 7e9f351723a..e8119d29ef5 100644 --- a/substrate/frame/broker/src/types.rs +++ b/substrate/frame/broker/src/types.rs @@ -55,7 +55,7 @@ pub enum Finality { pub struct RegionId { /// The timeslice at which this Region begins. pub begin: Timeslice, - /// The index of the Polakdot Core on which this Region will be scheduled. + /// The index of the Polkadot Core on which this Region will be scheduled. pub core: CoreIndex, /// The regularity parts in which this Region will be scheduled. pub mask: CoreMask, @@ -198,7 +198,7 @@ pub struct PoolIoRecord { /// The total change of the portion of the pool supplied by purchased Bulk Coretime, measured /// in Core Mask Bits. pub private: SignedCoreMaskBitCount, - /// The total change of the portion of the pool supplied by the Polkaot System, measured in + /// The total change of the portion of the pool supplied by the Polkadot System, measured in /// Core Mask Bits. pub system: SignedCoreMaskBitCount, } diff --git a/substrate/frame/collective/README.md b/substrate/frame/collective/README.md index 444927e51da..e860edbd484 100644 --- a/substrate/frame/collective/README.md +++ b/substrate/frame/collective/README.md @@ -9,7 +9,7 @@ calculations, but enforces this neither in `set_members` nor in `change_members_ A "prime" member may be set to help determine the default vote behavior based on chain config. If `PrimeDefaultVote` is used, the prime vote acts as the default vote in case of any abstentions after the voting period. If `MoreThanMajorityThenPrimeDefaultVote` is used, then -abstentations will first follow the majority of the collective voting, and then the prime +abstentions will first follow the majority of the collective voting, and then the prime member. Voting happens through motions comprising a proposal (i.e. a dispatchable) plus a diff --git a/substrate/frame/collective/src/lib.rs b/substrate/frame/collective/src/lib.rs index 882e99a6d00..d0009d02f68 100644 --- a/substrate/frame/collective/src/lib.rs +++ b/substrate/frame/collective/src/lib.rs @@ -283,7 +283,7 @@ pub mod pallet { pub type Members, I: 'static = ()> = StorageValue<_, Vec, ValueQuery>; - /// The prime member that helps determine the default vote behavior in case of absentations. + /// The prime member that helps determine the default vote behavior in case of abstentions. #[pallet::storage] pub type Prime, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; diff --git a/substrate/frame/collective/src/tests.rs b/substrate/frame/collective/src/tests.rs index 8a80dd167e3..5240dc215ff 100644 --- a/substrate/frame/collective/src/tests.rs +++ b/substrate/frame/collective/src/tests.rs @@ -995,7 +995,7 @@ fn motions_all_first_vote_free_works() { Collective::vote(RuntimeOrigin::signed(3), hash, 0, false); assert_eq!(vote_rval.unwrap().pays_fee, Pays::Yes); - // Test close() Extrincis | Check DispatchResultWithPostInfo with Pay Info + // Test close() Extrinsics | Check DispatchResultWithPostInfo with Pay Info let proposal_weight = proposal.get_dispatch_info().weight; let close_rval: DispatchResultWithPostInfo = diff --git a/substrate/frame/contracts/README.md b/substrate/frame/contracts/README.md index 6e817292e66..09dc770300c 100644 --- a/substrate/frame/contracts/README.md +++ b/substrate/frame/contracts/README.md @@ -59,7 +59,7 @@ In general, a contract execution needs to be deterministic so that all nodes com it. To that end we disallow any instructions that could cause indeterminism. Most notable are any floating point arithmetic. That said, sometimes contracts are executed off-chain and hence are not subject to consensus. If code is only executed by a single node and implicitly trusted by other actors is such a case. Trusted execution environments -come to mind. To that end we allow the execution of indeterminstic code for off-chain usages with the following +come to mind. To that end we allow the execution of indeterministic code for off-chain usages with the following constraints: 1. No contract can ever be instantiated from an indeterministic code. The only way to execute the code is to use a diff --git a/substrate/frame/contracts/fixtures/contracts/multi_store.rs b/substrate/frame/contracts/fixtures/contracts/multi_store.rs index b83f3995a42..a78115f0148 100644 --- a/substrate/frame/contracts/fixtures/contracts/multi_store.rs +++ b/substrate/frame/contracts/fixtures/contracts/multi_store.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Does two stores to two seperate storage items +//! Does two stores to two separate storage items #![no_std] #![no_main] diff --git a/substrate/frame/contracts/src/benchmarking/code.rs b/substrate/frame/contracts/src/benchmarking/code.rs index 96ce11f8c41..b97cf168e26 100644 --- a/substrate/frame/contracts/src/benchmarking/code.rs +++ b/substrate/frame/contracts/src/benchmarking/code.rs @@ -164,7 +164,7 @@ impl From for WasmModule { // Grant access to linear memory. // Every contract module is required to have an imported memory. - // If no memory is specified in the passed ModuleDefenition, then + // If no memory is specified in the passed ModuleDefinition, then // default to (1, 1). let (init, max) = if let Some(memory) = &def.memory { (memory.min_pages, Some(memory.max_pages)) diff --git a/substrate/frame/contracts/src/benchmarking/mod.rs b/substrate/frame/contracts/src/benchmarking/mod.rs index ce2cf15d812..9fb107537ba 100644 --- a/substrate/frame/contracts/src/benchmarking/mod.rs +++ b/substrate/frame/contracts/src/benchmarking/mod.rs @@ -340,7 +340,7 @@ mod benchmarks { assert_eq!(StorageVersion::get::>(), version); } - // This benchmarks the weight of dispatching migrate to execute 1 `NoopMigraton` + // This benchmarks the weight of dispatching migrate to execute 1 `NoopMigration` #[benchmark(pov_mode = Measured)] fn migrate() { let latest_version = LATEST_MIGRATION_VERSION; @@ -1859,7 +1859,7 @@ mod benchmarks { // We call unique accounts. // - // This is a slow call: We redeuce the number of runs. + // This is a slow call: We reduce the number of runs. #[benchmark(pov_mode = Measured)] fn seal_call(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let dummy_code = WasmModule::::dummy_with_bytes(0); @@ -1937,7 +1937,7 @@ mod benchmarks { Ok(()) } - // This is a slow call: We redeuce the number of runs. + // This is a slow call: We reduce the number of runs. #[benchmark(pov_mode = Measured)] fn seal_delegate_call(r: Linear<0, { API_BENCHMARK_RUNS / 2 }>) -> Result<(), BenchmarkError> { let hashes = (0..r) @@ -2473,7 +2473,7 @@ mod benchmarks { // Only calling the function itself for the list of // generated different ECDSA keys. - // This is a slow call: We redeuce the number of runs. + // This is a slow call: We reduce the number of runs. #[benchmark(pov_mode = Measured)] fn seal_ecdsa_to_eth_address( r: Linear<0, { API_BENCHMARK_RUNS / 10 }>, diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs index d24657b65b2..41a0383811f 100644 --- a/substrate/frame/contracts/src/exec.rs +++ b/substrate/frame/contracts/src/exec.rs @@ -531,9 +531,9 @@ enum FrameArgs<'a, T: Config, E> { nonce: u64, /// The executable whose `deploy` function is run. executable: E, - /// A salt used in the contract address deriviation of the new contract. + /// A salt used in the contract address derivation of the new contract. salt: &'a [u8], - /// The input data is used in the contract address deriviation of the new contract. + /// The input data is used in the contract address derivation of the new contract. input_data: &'a [u8], }, } diff --git a/substrate/frame/contracts/src/gas.rs b/substrate/frame/contracts/src/gas.rs index b9d91f38f16..32fad2140f1 100644 --- a/substrate/frame/contracts/src/gas.rs +++ b/substrate/frame/contracts/src/gas.rs @@ -352,7 +352,7 @@ mod tests { assert!(gas_meter.charge(SimpleToken(1)).is_err()); } - // Make sure that the gas meter does not charge in case of overcharger + // Make sure that the gas meter does not charge in case of overcharge #[test] fn overcharge_does_not_charge() { let mut gas_meter = GasMeter::::new(Weight::from_parts(200, 0)); diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs index de84d5220c5..6433d4eecdc 100644 --- a/substrate/frame/contracts/src/lib.rs +++ b/substrate/frame/contracts/src/lib.rs @@ -1104,7 +1104,7 @@ pub mod pallet { /// A more detailed error can be found on the node console if debug messages are enabled /// by supplying `-lruntime::contracts=debug`. CodeRejected, - /// An indetermistic code was used in a context where this is not permitted. + /// An indeterministic code was used in a context where this is not permitted. Indeterministic, /// A pending migration needs to complete before the extrinsic can be called. MigrationInProgress, diff --git a/substrate/frame/contracts/src/migration/v09.rs b/substrate/frame/contracts/src/migration/v09.rs index f19bff9d674..8e718871ecb 100644 --- a/substrate/frame/contracts/src/migration/v09.rs +++ b/substrate/frame/contracts/src/migration/v09.rs @@ -131,7 +131,7 @@ impl MigrationStep for Migration { let module = CodeStorage::::get(&code_hash).unwrap(); ensure!( module.instruction_weights_version == old.instruction_weights_version, - "invalid isntruction weights version" + "invalid instruction weights version" ); ensure!(module.determinism == Determinism::Enforced, "invalid determinism"); ensure!(module.initial == old.initial, "invalid initial"); diff --git a/substrate/frame/contracts/src/schedule.rs b/substrate/frame/contracts/src/schedule.rs index b2e3801deae..06a7c2005aa 100644 --- a/substrate/frame/contracts/src/schedule.rs +++ b/substrate/frame/contracts/src/schedule.rs @@ -193,7 +193,7 @@ pub struct HostFnWeights { /// Weight of calling `seal_set_storage`. pub set_storage: Weight, - /// Weight per written byten of an item stored with `seal_set_storage`. + /// Weight per written byte of an item stored with `seal_set_storage`. pub set_storage_per_new_byte: Weight, /// Weight per overwritten byte of an item stored with `seal_set_storage`. diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index db6b2e80d07..ed486fc4a67 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -1347,7 +1347,7 @@ fn transfer_expendable_cannot_kill_account() { } #[test] -fn cannot_self_destruct_through_draning() { +fn cannot_self_destruct_through_draining() { let (wasm, _code_hash) = compile_module::("drain").unwrap(); ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 1_000_000); @@ -1662,7 +1662,7 @@ fn cannot_self_destruct_in_constructor() { ExtBuilder::default().existential_deposit(50).build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 1_000_000); - // Fail to instantiate the BOB because the contructor calls seal_terminate. + // Fail to instantiate the BOB because the constructor calls seal_terminate. assert_err_ignore_postinfo!( Contracts::instantiate_with_code( RuntimeOrigin::signed(ALICE), @@ -5096,7 +5096,7 @@ fn cannot_instantiate_indeterministic_code() { >::CodeRejected, ); - // Try to upload a non deterministic code as deterministic + // Try to upload a non-deterministic code as deterministic assert_err!( Contracts::upload_code( RuntimeOrigin::signed(ALICE), @@ -5176,7 +5176,7 @@ fn cannot_instantiate_indeterministic_code() { >::Indeterministic, ); - // Instantiations are not allowed even in non determinism mode + // Instantiations are not allowed even in non-determinism mode assert_err!( >::bare_call( ALICE, @@ -5202,7 +5202,7 @@ fn cannot_set_code_indeterministic_code() { ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 1_000_000); - // Put the non deterministic contract on-chain + // Put the non-deterministic contract on-chain assert_ok!(Contracts::upload_code( RuntimeOrigin::signed(ALICE), wasm, @@ -5226,7 +5226,7 @@ fn cannot_set_code_indeterministic_code() { .unwrap() .account_id; - // We do not allow to set the code hash to a non determinstic wasm + // We do not allow to set the code hash to a non-deterministic wasm assert_err!( >::bare_call( ALICE, @@ -5252,7 +5252,7 @@ fn delegate_call_indeterministic_code() { ExtBuilder::default().existential_deposit(200).build().execute_with(|| { let _ = ::Currency::set_balance(&ALICE, 1_000_000); - // Put the non deterministic contract on-chain + // Put the non-deterministic contract on-chain assert_ok!(Contracts::upload_code( RuntimeOrigin::signed(ALICE), wasm, @@ -5293,7 +5293,7 @@ fn delegate_call_indeterministic_code() { >::Indeterministic, ); - // The delegate call will work on non deterministic mode + // The delegate call will work on non-deterministic mode assert_ok!( >::bare_call( ALICE, @@ -5429,7 +5429,7 @@ fn locking_delegate_dependency_works() { contract.storage_base_deposit() - ED ); - // Removing an unexisting dependency should fail. + // Removing a nonexistent dependency should fail. assert_err!( call(&addr_caller, &unlock_delegate_dependency_input).result, Error::::DelegateDependencyNotFound diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs index af287a6f2df..e6af62c7289 100644 --- a/substrate/frame/contracts/src/wasm/mod.rs +++ b/substrate/frame/contracts/src/wasm/mod.rs @@ -1425,7 +1425,7 @@ mod tests { #[test] fn contract_ecdsa_to_eth_address() { - /// calls `seal_ecdsa_to_eth_address` for the contstant and ensures the result equals the + /// calls `seal_ecdsa_to_eth_address` for the constant and ensures the result equals the /// expected one. const CODE_ECDSA_TO_ETH_ADDRESS: &str = r#" (module diff --git a/substrate/frame/contracts/src/wasm/runtime.rs b/substrate/frame/contracts/src/wasm/runtime.rs index 7d43d30ba58..160dfa0d2f3 100644 --- a/substrate/frame/contracts/src/wasm/runtime.rs +++ b/substrate/frame/contracts/src/wasm/runtime.rs @@ -245,7 +245,7 @@ pub enum RuntimeCosts { /// Weight of calling `account_reentrance_count` AccountEntranceCount, /// Weight of calling `instantiation_nonce` - InstantationNonce, + InstantiationNonce, /// Weight of calling `lock_delegate_dependency` LockDelegateDependency, /// Weight of calling `unlock_delegate_dependency` @@ -337,7 +337,7 @@ impl Token for RuntimeCosts { EcdsaToEthAddress => s.ecdsa_to_eth_address, ReentrantCount => s.reentrance_count, AccountEntranceCount => s.account_reentrance_count, - InstantationNonce => s.instantiation_nonce, + InstantiationNonce => s.instantiation_nonce, LockDelegateDependency => s.lock_delegate_dependency, UnlockDelegateDependency => s.unlock_delegate_dependency, } @@ -2298,7 +2298,7 @@ pub mod env { /// Returns a nonce that is unique per contract instantiation. /// See [`pallet_contracts_uapi::HostFn::instantiation_nonce`]. fn instantiation_nonce(ctx: _, _memory: _) -> Result { - ctx.charge_gas(RuntimeCosts::InstantationNonce)?; + ctx.charge_gas(RuntimeCosts::InstantiationNonce)?; Ok(ctx.ext.nonce()) } diff --git a/substrate/frame/conviction-voting/src/tests.rs b/substrate/frame/conviction-voting/src/tests.rs index 5c582a35362..74baeace898 100644 --- a/substrate/frame/conviction-voting/src/tests.rs +++ b/substrate/frame/conviction-voting/src/tests.rs @@ -39,7 +39,7 @@ frame_support::construct_runtime!( } ); -// Test that a fitlered call can be dispatched. +// Test that a filtered call can be dispatched. pub struct BaseFilter; impl Contains for BaseFilter { fn contains(call: &RuntimeCall) -> bool { diff --git a/substrate/frame/core-fellowship/src/tests/integration.rs b/substrate/frame/core-fellowship/src/tests/integration.rs index 3c2dc1de595..d3bbac15805 100644 --- a/substrate/frame/core-fellowship/src/tests/integration.rs +++ b/substrate/frame/core-fellowship/src/tests/integration.rs @@ -251,7 +251,7 @@ fn swap_exhaustive_works() { }); assert_eq!(root_add, root_swap); - // Ensure that we dont compare trivial stuff like `()` from a type error above. + // Ensure that we don't compare trivial stuff like `()` from a type error above. assert_eq!(root_add.len(), 32); }); } diff --git a/substrate/frame/democracy/src/lib.rs b/substrate/frame/democracy/src/lib.rs index 08e2a7599f5..f3d33a72f3a 100644 --- a/substrate/frame/democracy/src/lib.rs +++ b/substrate/frame/democracy/src/lib.rs @@ -484,7 +484,7 @@ pub mod pallet { Blacklisted { proposal_hash: T::Hash }, /// An account has voted in a referendum Voted { voter: T::AccountId, ref_index: ReferendumIndex, vote: AccountVote> }, - /// An account has secconded a proposal + /// An account has seconded a proposal Seconded { seconder: T::AccountId, prop_index: PropIndex }, /// A proposal got canceled. ProposalCanceled { prop_index: PropIndex }, diff --git a/substrate/frame/democracy/src/migrations/unlock_and_unreserve_all_funds.rs b/substrate/frame/democracy/src/migrations/unlock_and_unreserve_all_funds.rs index 188c475f64d..1cb50a157b1 100644 --- a/substrate/frame/democracy/src/migrations/unlock_and_unreserve_all_funds.rs +++ b/substrate/frame/democracy/src/migrations/unlock_and_unreserve_all_funds.rs @@ -321,40 +321,40 @@ mod test { } #[test] - fn unreserve_works_for_depositer() { - let depositer_0 = 10; - let depositer_1 = 11; + fn unreserve_works_for_depositor() { + let depositor_0 = 10; + let depositor_1 = 11; let deposit = 25; - let depositer_0_initial_reserved = 0; - let depositer_1_initial_reserved = 15; + let depositor_0_initial_reserved = 0; + let depositor_1_initial_reserved = 15; let initial_balance = 100_000; new_test_ext().execute_with(|| { // Set up initial state. - ::Currency::make_free_balance_be(&depositer_0, initial_balance); - ::Currency::make_free_balance_be(&depositer_1, initial_balance); + ::Currency::make_free_balance_be(&depositor_0, initial_balance); + ::Currency::make_free_balance_be(&depositor_1, initial_balance); assert_ok!(::Currency::reserve( - &depositer_0, - depositer_0_initial_reserved + deposit + &depositor_0, + depositor_0_initial_reserved + deposit )); assert_ok!(::Currency::reserve( - &depositer_1, - depositer_1_initial_reserved + deposit + &depositor_1, + depositor_1_initial_reserved + deposit )); let depositors = BoundedVec::<_, ::MaxDeposits>::truncate_from(vec![ - depositer_0, - depositer_1, + depositor_0, + depositor_1, ]); DepositOf::::insert(0, (depositors, deposit)); // Sanity check: ensure initial reserved balance was set correctly. assert_eq!( - ::Currency::reserved_balance(&depositer_0), - depositer_0_initial_reserved + deposit + ::Currency::reserved_balance(&depositor_0), + depositor_0_initial_reserved + deposit ); assert_eq!( - ::Currency::reserved_balance(&depositer_1), - depositer_1_initial_reserved + deposit + ::Currency::reserved_balance(&depositor_1), + depositor_1_initial_reserved + deposit ); // Run the migration. @@ -365,12 +365,12 @@ mod test { // Assert the reserved balance was reduced by the expected amount. assert_eq!( - ::Currency::reserved_balance(&depositer_0), - depositer_0_initial_reserved + ::Currency::reserved_balance(&depositor_0), + depositor_0_initial_reserved ); assert_eq!( - ::Currency::reserved_balance(&depositer_1), - depositer_1_initial_reserved + ::Currency::reserved_balance(&depositor_1), + depositor_1_initial_reserved ); }); } diff --git a/substrate/frame/democracy/src/tests.rs b/substrate/frame/democracy/src/tests.rs index dd69f48dbc1..e2946ba9815 100644 --- a/substrate/frame/democracy/src/tests.rs +++ b/substrate/frame/democracy/src/tests.rs @@ -62,7 +62,7 @@ frame_support::construct_runtime!( } ); -// Test that a fitlered call can be dispatched. +// Test that a filtered call can be dispatched. pub struct BaseFilter; impl Contains for BaseFilter { fn contains(call: &RuntimeCall) -> bool { diff --git a/substrate/frame/democracy/src/tests/cancellation.rs b/substrate/frame/democracy/src/tests/cancellation.rs index 4384fe6a164..b4c42f9c790 100644 --- a/substrate/frame/democracy/src/tests/cancellation.rs +++ b/substrate/frame/democracy/src/tests/cancellation.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! The tests for cancelation functionality. +//! The tests for cancellation functionality. use super::*; diff --git a/substrate/frame/election-provider-multi-phase/src/helpers.rs b/substrate/frame/election-provider-multi-phase/src/helpers.rs index 57d580e9301..a3f27fc18f0 100644 --- a/substrate/frame/election-provider-multi-phase/src/helpers.rs +++ b/substrate/frame/election-provider-multi-phase/src/helpers.rs @@ -160,7 +160,7 @@ pub fn target_index_fn_linear( } /// Create a function that can map a voter index ([`SolutionVoterIndexOf`]) to the actual voter -/// account using a linearly indexible snapshot. +/// account using a linearly indexable snapshot. pub fn voter_at_fn( snapshot: &Vec>, ) -> impl Fn(SolutionVoterIndexOf) -> Option + '_ { @@ -172,7 +172,7 @@ pub fn voter_at_fn( } /// Create a function that can map a target index ([`SolutionTargetIndexOf`]) to the actual target -/// account using a linearly indexible snapshot. +/// account using a linearly indexable snapshot. pub fn target_at_fn( snapshot: &Vec, ) -> impl Fn(SolutionTargetIndexOf) -> Option + '_ { diff --git a/substrate/frame/election-provider-multi-phase/src/lib.rs b/substrate/frame/election-provider-multi-phase/src/lib.rs index 6bf4dfe4f1e..31a79577d1f 100644 --- a/substrate/frame/election-provider-multi-phase/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/src/lib.rs @@ -1134,7 +1134,7 @@ pub mod pallet { /// A solution was stored with the given compute. /// /// The `origin` indicates the origin of the solution. If `origin` is `Some(AccountId)`, - /// the stored solution was submited in the signed phase by a miner with the `AccountId`. + /// the stored solution was submitted in the signed phase by a miner with the `AccountId`. /// Otherwise, the solution was stored either during the unsigned phase or by /// `T::ForceOrigin`. The `bool` is `true` when a previous solution was ejected to make /// room for this one. @@ -1192,7 +1192,7 @@ pub mod pallet { BoundNotMet, /// Submitted solution has too many winners TooManyWinners, - /// Sumission was prepared for a different round. + /// Submission was prepared for a different round. PreDispatchDifferentRound, } diff --git a/substrate/frame/election-provider-multi-phase/src/unsigned.rs b/substrate/frame/election-provider-multi-phase/src/unsigned.rs index 94348181334..8b25815eca1 100644 --- a/substrate/frame/election-provider-multi-phase/src/unsigned.rs +++ b/substrate/frame/election-provider-multi-phase/src/unsigned.rs @@ -1445,7 +1445,7 @@ mod tests { ) .unwrap(); let solution = RawSolution { solution: raw, score, round: MultiPhase::round() }; - // 12 is not better than 12. We need score of atleast 13 to be accepted. + // 12 is not better than 12. We need score of at least 13 to be accepted. assert_eq!(solution.score.minimal_stake, 12); // submitting this will panic. assert_noop!( @@ -1483,7 +1483,7 @@ mod tests { )); // trial 4: a solution who's minimal stake is 17, i.e. 4 better than the last - // soluton. + // solution. let result = ElectionResult { winners: vec![(10, 12)], assignments: vec![ diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs index 53bff50f748..83083c91209 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs @@ -208,8 +208,8 @@ fn enters_emergency_phase_after_forcing_before_elect() { /// active validators. Thus, slashing a percentage of the current validators that is lower than /// `OffendingValidatorsThreshold` will never force a new era. However, as the slashes progress, if /// the subsequent elections do not meet the minimum election untrusted score, the election will -/// fail and enter in emenergency mode. -fn continous_slashes_below_offending_threshold() { +/// fail and enter in emergency mode. +fn continuous_slashes_below_offending_threshold() { let staking_builder = StakingExtBuilder::default().validator_count(10); let epm_builder = EpmExtBuilder::default().disable_emergency_throttling(); @@ -323,7 +323,7 @@ fn set_validation_intention_after_chilled() { } #[test] -/// Active ledger balance may fall below ED if account chills before unbounding. +/// Active ledger balance may fall below ED if account chills before unbonding. /// /// Unbonding call fails if the remaining ledger's stash balance falls below the existential /// deposit. However, if the stash is chilled before unbonding, the ledger's active balance may @@ -350,7 +350,7 @@ fn ledger_consistency_active_balance_below_ed() { // however, chilling works as expected. assert_ok!(Staking::chill(RuntimeOrigin::signed(11))); - // now unbonding the full active balance works, since remainer of the active balance is + // now unbonding the full active balance works, since remainder of the active balance is // not enforced to be below `MinNominatorBond` if the stash has been chilled. assert_ok!(Staking::unbond(RuntimeOrigin::signed(11), 1000)); @@ -479,7 +479,7 @@ fn automatic_unbonding_pools() { staking_events(), [ // auto-withdraw happened as expected to release 2's unbonding funds, but the funds - // were not transfered to 2 and stay in the pool's tranferrable balance instead. + // were not transferred to 2 and stay in the pool's transferrable balance instead. pallet_staking::Event::Withdrawn { stash: 7939698191839293293, amount: 10 }, pallet_staking::Event::Unbonded { stash: 7939698191839293293, amount: 10 } ] diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs index d7d2006d219..7efcc4701e2 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs @@ -167,7 +167,7 @@ parameter_types! { pub static SignedPhase: BlockNumber = 10; pub static UnsignedPhase: BlockNumber = 10; // we expect a minimum of 3 blocks in signed phase and unsigned phases before trying - // enetering in emergency phase after the election failed. + // entering in emergency phase after the election failed. pub static MinBlocksBeforeEmergency: BlockNumber = 3; pub static MaxActiveValidators: u32 = 1000; pub static OffchainRepeat: u32 = 5; @@ -661,7 +661,7 @@ pub fn roll_to(n: BlockNumber, delay_solution: bool) { Session::on_initialize(b); Timestamp::set_timestamp(System::block_number() * BLOCK_TIME + INIT_TIMESTAMP); - // TODO(gpestana): implement a realistic OCW worker insted of simulating it + // TODO(gpestana): implement a realistic OCW worker instead of simulating it // https://github.com/paritytech/substrate/issues/13589 // if there's no solution queued and the solution should not be delayed, try mining and // queue a solution. diff --git a/substrate/frame/election-provider-support/src/bounds.rs b/substrate/frame/election-provider-support/src/bounds.rs index b9ae21e49ca..6b2423b7fec 100644 --- a/substrate/frame/election-provider-support/src/bounds.rs +++ b/substrate/frame/election-provider-support/src/bounds.rs @@ -62,7 +62,7 @@ use sp_runtime::traits::Zero; /// Encapsulates the counting of things that can be bounded in an election, such as voters, /// targets or anything else. /// -/// This struct is defined mostly to prevent callers from mistankingly using `CountBound` instead of +/// This struct is defined mostly to prevent callers from mistakenly using `CountBound` instead of /// `SizeBound` and vice-versa. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct CountBound(pub u32); @@ -96,7 +96,7 @@ impl Zero for CountBound { /// logic and implementation, but it most likely will represent bytes in SCALE encoding in this /// context. /// -/// This struct is defined mostly to prevent callers from mistankingly using `CountBound` instead of +/// This struct is defined mostly to prevent callers from mistakenly using `CountBound` instead of /// `SizeBound` and vice-versa. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct SizeBound(pub u32); diff --git a/substrate/frame/examples/offchain-worker/src/lib.rs b/substrate/frame/examples/offchain-worker/src/lib.rs index d21c8b4cfd2..0a90e896188 100644 --- a/substrate/frame/examples/offchain-worker/src/lib.rs +++ b/substrate/frame/examples/offchain-worker/src/lib.rs @@ -495,7 +495,7 @@ impl Pallet { // Here we showcase two ways to send an unsigned transaction / unsigned payload (raw) // // By default unsigned transactions are disallowed, so we need to whitelist this case - // by writing `UnsignedValidator`. Note that it's EXTREMELY important to carefuly + // by writing `UnsignedValidator`. Note that it's EXTREMELY important to carefully // implement unsigned validation logic, as any mistakes can lead to opening DoS or spam // attack vectors. See validation logic docs for more details. // diff --git a/substrate/frame/examples/single-block-migrations/src/lib.rs b/substrate/frame/examples/single-block-migrations/src/lib.rs index 86a9e5d6e95..b36d5262267 100644 --- a/substrate/frame/examples/single-block-migrations/src/lib.rs +++ b/substrate/frame/examples/single-block-migrations/src/lib.rs @@ -20,7 +20,7 @@ //! An example pallet demonstrating best-practices for writing single-block migrations in the //! context of upgrading pallet storage. //! -//! ## Forwarning +//! ## Forewarning //! //! Single block migrations **MUST** execute in a single block, therefore when executed on a //! parachain are only appropriate when guaranteed to not exceed block weight limits. If a @@ -66,7 +66,7 @@ //! //! ## Adding a migration module //! -//! Writing a pallets migrations in a seperate module is strongly recommended. +//! Writing a pallets migrations in a separate module is strongly recommended. //! //! Here's how the migration module is defined for this pallet: //! diff --git a/substrate/frame/examples/split/Cargo.toml b/substrate/frame/examples/split/Cargo.toml index d140fc3eef4..230dc980b1a 100644 --- a/substrate/frame/examples/split/Cargo.toml +++ b/substrate/frame/examples/split/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true license = "MIT-0" homepage = "https://substrate.io" repository.workspace = true -description = "FRAME example splitted pallet" +description = "FRAME example split pallet" readme = "README.md" [lints] diff --git a/substrate/frame/examples/tasks/Cargo.toml b/substrate/frame/examples/tasks/Cargo.toml index 41521114366..4d14bf313d7 100644 --- a/substrate/frame/examples/tasks/Cargo.toml +++ b/substrate/frame/examples/tasks/Cargo.toml @@ -5,7 +5,7 @@ authors.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Pallet to demonstrate the usage of Tasks to recongnize and execute service work" +description = "Pallet to demonstrate the usage of Tasks to recognize and execute service work" [lints] workspace = true diff --git a/substrate/frame/fast-unstake/src/tests.rs b/substrate/frame/fast-unstake/src/tests.rs index b19fe3b8c46..77128872f28 100644 --- a/substrate/frame/fast-unstake/src/tests.rs +++ b/substrate/frame/fast-unstake/src/tests.rs @@ -110,7 +110,7 @@ fn cannot_register_if_head() { stashes: bounded_vec![(1, Deposit::get())], checked: bounded_vec![], }); - // Controller attempts to regsiter + // Controller attempts to register assert_noop!( FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)), Error::::AlreadyHead diff --git a/substrate/frame/grandpa/src/benchmarking.rs b/substrate/frame/grandpa/src/benchmarking.rs index 7a87f0c4b07..c89592b3b35 100644 --- a/substrate/frame/grandpa/src/benchmarking.rs +++ b/substrate/frame/grandpa/src/benchmarking.rs @@ -29,7 +29,7 @@ benchmarks! { // NOTE: generated with the test below `test_generate_equivocation_report_blob`. // the output should be deterministic since the keys we use are static. // with the current benchmark setup it is not possible to generate this - // programatically from the benchmark setup. + // programmatically from the benchmark setup. const EQUIVOCATION_PROOF_BLOB: [u8; 257] = [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 136, 220, 52, 23, 213, 5, 142, 196, 180, 80, 62, 12, 18, 234, 26, 10, 137, 190, 32, diff --git a/substrate/frame/grandpa/src/tests.rs b/substrate/frame/grandpa/src/tests.rs index 993d72af6d4..8b12d63adaa 100644 --- a/substrate/frame/grandpa/src/tests.rs +++ b/substrate/frame/grandpa/src/tests.rs @@ -634,7 +634,7 @@ fn report_equivocation_invalid_equivocation_proof() { (1, H256::zero(), 10, &equivocation_keyring), )); - // votes targetting different rounds, there is no equivocation. + // votes targeting different rounds, there is no equivocation. assert_invalid_equivocation_proof(generate_equivocation_proof( set_id, (1, H256::random(), 10, &equivocation_keyring), diff --git a/substrate/frame/identity/src/benchmarking.rs b/substrate/frame/identity/src/benchmarking.rs index e0b45eeecd1..cdcdb952261 100644 --- a/substrate/frame/identity/src/benchmarking.rs +++ b/substrate/frame/identity/src/benchmarking.rs @@ -671,10 +671,10 @@ mod benchmarks { let username = bounded_username::(bench_username(), bench_suffix()); Identity::::queue_acceptance(&caller, username.clone()); - let expected_exiration = + let expected_expiration = frame_system::Pallet::::block_number() + T::PendingUsernameExpiration::get(); - run_to_block::(expected_exiration + One::one()); + run_to_block::(expected_expiration + One::one()); #[extrinsic_call] _(RawOrigin::Signed(caller.clone()), username); diff --git a/substrate/frame/identity/src/lib.rs b/substrate/frame/identity/src/lib.rs index 78d59180b3f..4a977880b31 100644 --- a/substrate/frame/identity/src/lib.rs +++ b/substrate/frame/identity/src/lib.rs @@ -161,7 +161,7 @@ pub mod pallet { /// Structure holding information about an identity. type IdentityInformation: IdentityInformationProvider; - /// Maxmimum number of registrars allowed in the system. Needed to bound the complexity + /// Maximum number of registrars allowed in the system. Needed to bound the complexity /// of, e.g., updating judgements. #[pallet::constant] type MaxRegistrars: Get; diff --git a/substrate/frame/im-online/src/tests.rs b/substrate/frame/im-online/src/tests.rs index 5e5212e1d56..f9959593494 100644 --- a/substrate/frame/im-online/src/tests.rs +++ b/substrate/frame/im-online/src/tests.rs @@ -416,7 +416,7 @@ fn should_handle_non_linear_session_progress() { Session::rotate_session(); - // if we don't have valid results for the current session progres then + // if we don't have valid results for the current session progress then // we'll fallback to `HeartbeatAfter` and only heartbeat on block 5. MockCurrentSessionProgress::mutate(|p| *p = Some(None)); assert_eq!(ImOnline::send_heartbeats(2).err(), Some(OffchainErr::TooEarly)); diff --git a/substrate/frame/merkle-mountain-range/src/lib.rs b/substrate/frame/merkle-mountain-range/src/lib.rs index e3eb0dc8cf5..7b6edb37b7f 100644 --- a/substrate/frame/merkle-mountain-range/src/lib.rs +++ b/substrate/frame/merkle-mountain-range/src/lib.rs @@ -89,7 +89,7 @@ mod tests; /// is not available (since the block is not finished yet), /// we use the `parent_hash` here along with parent block number. pub struct ParentNumberAndHash { - _phanthom: sp_std::marker::PhantomData, + _phantom: sp_std::marker::PhantomData, } impl LeafDataProvider for ParentNumberAndHash { diff --git a/substrate/frame/message-queue/src/lib.rs b/substrate/frame/message-queue/src/lib.rs index 61028057394..93cd760eeb9 100644 --- a/substrate/frame/message-queue/src/lib.rs +++ b/substrate/frame/message-queue/src/lib.rs @@ -1460,7 +1460,7 @@ impl Pallet { /// Run a closure that errors on re-entrance. Meant to be used by anything that services queues. pub(crate) fn with_service_mutex R, R>(f: F) -> Result { - // Holds the singelton token instance. + // Holds the singleton token instance. environmental::environmental!(token: Option<()>); token::using_once(&mut Some(()), || { diff --git a/substrate/frame/message-queue/src/tests.rs b/substrate/frame/message-queue/src/tests.rs index dbef94b3b10..1f6e7777f01 100644 --- a/substrate/frame/message-queue/src/tests.rs +++ b/substrate/frame/message-queue/src/tests.rs @@ -90,7 +90,7 @@ fn queue_priority_retains() { MessageQueue::enqueue_message(msg("d"), Everywhere(2)); assert_ring(&[Everywhere(1), Everywhere(2), Everywhere(3)]); // service head is 1, it will process a, leaving service head at 2. it also processes b but - // doees not empty queue 2, so service head will end at 2. + // does not empty queue 2, so service head will end at 2. assert_eq!(MessageQueue::service_queues(2.into_weight()), 2.into_weight()); assert_eq!( MessagesProcessed::take(), diff --git a/substrate/frame/migrations/src/mock_helpers.rs b/substrate/frame/migrations/src/mock_helpers.rs index c5e23efb4e3..995ec0a922c 100644 --- a/substrate/frame/migrations/src/mock_helpers.rs +++ b/substrate/frame/migrations/src/mock_helpers.rs @@ -107,7 +107,7 @@ impl SteppedMigrations for MockedMigrations { cursor: Option>, meter: &mut WeightMeter, ) -> Option>, SteppedMigrationError>> { - // This is a hack but should be fine. We dont need it in testing. + // This is a hack but should be fine. We don't need it in testing. Self::nth_step(n, cursor, meter) } diff --git a/substrate/frame/nis/README.md b/substrate/frame/nis/README.md index 032df7d0186..8a1a30f17e1 100644 --- a/substrate/frame/nis/README.md +++ b/substrate/frame/nis/README.md @@ -1,5 +1,5 @@ # NIS Module -Provides a non-interactiove variant of staking. +Provides a non-interactive variant of staking. License: Apache-2.0 diff --git a/substrate/frame/nis/src/lib.rs b/substrate/frame/nis/src/lib.rs index 5e547b63e54..7655cd1a824 100644 --- a/substrate/frame/nis/src/lib.rs +++ b/substrate/frame/nis/src/lib.rs @@ -426,7 +426,7 @@ pub mod pallet { }, /// An automatic funding of the deficit was made. Funded { deficit: BalanceOf }, - /// A receipt was transfered. + /// A receipt was transferred. Transferred { from: T::AccountId, to: T::AccountId, index: ReceiptIndex }, } @@ -457,7 +457,7 @@ pub mod pallet { AlreadyFunded, /// The thaw throttle has been reached for this period. Throttled, - /// The operation would result in a receipt worth an insignficant value. + /// The operation would result in a receipt worth an insignificant value. MakesDust, /// The receipt is already communal. AlreadyCommunal, diff --git a/substrate/frame/nis/src/tests.rs b/substrate/frame/nis/src/tests.rs index 7350da97dc6..01724999ae7 100644 --- a/substrate/frame/nis/src/tests.rs +++ b/substrate/frame/nis/src/tests.rs @@ -414,7 +414,7 @@ fn thaw_respects_transfers() { assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!(Balances::reserved_balance(&2), 40); - // Transfering the receipt... + // Transferring the receipt... assert_noop!(Nis::thaw_private(signed(1), 0, None), Error::::NotOwner); // ...and thawing is possible. diff --git a/substrate/frame/node-authorization/src/lib.rs b/substrate/frame/node-authorization/src/lib.rs index 8a823d29f23..9019a863ad8 100644 --- a/substrate/frame/node-authorization/src/lib.rs +++ b/substrate/frame/node-authorization/src/lib.rs @@ -18,7 +18,7 @@ //! # Node authorization pallet //! //! This pallet manages a configurable set of nodes for a permissioned network. -//! Each node is dentified by a PeerId (i.e. `Vec`). It provides two ways to +//! Each node is identified by a PeerId (i.e. `Vec`). It provides two ways to //! authorize a node, //! //! - a set of well known nodes across different organizations in which the @@ -102,7 +102,7 @@ pub mod pallet { #[pallet::getter(fn owners)] pub type Owners = StorageMap<_, Blake2_128Concat, PeerId, T::AccountId>; - /// The additional adapative connections of each node. + /// The additional adaptive connections of each node. #[pallet::storage] #[pallet::getter(fn additional_connection)] pub type AdditionalConnections = @@ -161,7 +161,7 @@ pub mod pallet { NotClaimed, /// You are not the owner of the node. NotOwner, - /// No permisson to perform specific operation. + /// No permission to perform specific operation. PermissionDenied, } @@ -377,7 +377,7 @@ pub mod pallet { /// Add additional connections to a given node. /// /// - `node`: identifier of the node. - /// - `connections`: additonal nodes from which the connections are allowed. + /// - `connections`: additional nodes from which the connections are allowed. #[pallet::call_index(7)] #[pallet::weight(T::WeightInfo::add_connections())] pub fn add_connections( @@ -412,7 +412,7 @@ pub mod pallet { /// Remove additional connections of a given node. /// /// - `node`: identifier of the node. - /// - `connections`: additonal nodes from which the connections are not allowed anymore. + /// - `connections`: additional nodes from which the connections are not allowed anymore. #[pallet::call_index(8)] #[pallet::weight(T::WeightInfo::remove_connections())] pub fn remove_connections( diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index a0dbdb3aaa4..f29a49a2b1b 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -451,7 +451,7 @@ enum AccountType { /// The permission a pool member can set for other accounts to claim rewards on their behalf. #[derive(Encode, Decode, MaxEncodedLen, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)] pub enum ClaimPermission { - /// Only the pool member themself can claim their rewards. + /// Only the pool member themselves can claim their rewards. Permissioned, /// Anyone can compound rewards on a pool member's behalf. PermissionlessCompound, @@ -2066,7 +2066,7 @@ pub mod pallet { /// The member will earn rewards pro rata based on the members stake vs the sum of the /// members in the pools stake. Rewards do not "expire". /// - /// See `claim_payout_other` to caim rewards on bahalf of some `other` pool member. + /// See `claim_payout_other` to claim rewards on behalf of some `other` pool member. #[pallet::call_index(2)] #[pallet::weight(T::WeightInfo::claim_payout())] pub fn claim_payout(origin: OriginFor) -> DispatchResult { @@ -2797,7 +2797,7 @@ pub mod pallet { /// Set or remove a pool's commission claim permission. /// /// Determines who can claim the pool's pending commission. Only the `Root` role of the pool - /// is able to conifigure commission claim permissions. + /// is able to configure commission claim permissions. #[pallet::call_index(22)] #[pallet::weight(T::WeightInfo::set_commission_claim_permission())] pub fn set_commission_claim_permission( @@ -2836,7 +2836,7 @@ pub mod pallet { assert!( T::Staking::bonding_duration() < TotalUnbondingPools::::get(), "There must be more unbonding pools then the bonding duration / - so a slash can be applied to relevant unboding pools. (We assume / + so a slash can be applied to relevant unbonding pools. (We assume / the bonding duration > slash deffer duration.", ); } diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 14410339f59..ca9c0874a83 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -70,7 +70,7 @@ pub mod unversioned { fn on_runtime_upgrade() -> Weight { let migrated = BondedPools::::count(); - // recalcuate the `TotalValueLocked` to compare with the current on-chain TVL which may + // recalculate the `TotalValueLocked` to compare with the current on-chain TVL which may // be out of sync. let tvl: BalanceOf = helpers::calculate_tvl_by_total_stake::(); let onchain_tvl = TotalValueLocked::::get(); diff --git a/substrate/frame/offences/src/tests.rs b/substrate/frame/offences/src/tests.rs index d525c7c3ab1..4897b78f3e4 100644 --- a/substrate/frame/offences/src/tests.rs +++ b/substrate/frame/offences/src/tests.rs @@ -204,7 +204,7 @@ fn reports_if_an_offence_is_dup() { assert_eq!(Offences::report_offence(vec![], test_offence.clone()), Ok(())); // creating a new offence for the same authorities on the next slot - // should be considered a new offence and thefore not known + // should be considered a new offence and therefore not known let test_offence_next_slot = offence(time_slot + 1, vec![0, 1]); assert!(!>::is_known_offence( &test_offence_next_slot.offenders, diff --git a/substrate/frame/paged-list/src/paged_list.rs b/substrate/frame/paged-list/src/paged_list.rs index 75467f3ceeb..eecc728cd62 100644 --- a/substrate/frame/paged-list/src/paged_list.rs +++ b/substrate/frame/paged-list/src/paged_list.rs @@ -190,7 +190,7 @@ impl Page { let values = sp_io::storage::get(&key) .and_then(|raw| sp_std::vec::Vec::::decode(&mut &raw[..]).ok())?; if values.is_empty() { - // Dont create empty pages. + // Don't create empty pages. return None } let values = values.into_iter().skip(value_index as usize); diff --git a/substrate/frame/parameters/src/lib.rs b/substrate/frame/parameters/src/lib.rs index 3e54eb6d67f..55a6f1ff91d 100644 --- a/substrate/frame/parameters/src/lib.rs +++ b/substrate/frame/parameters/src/lib.rs @@ -122,7 +122,7 @@ use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use frame_support::traits::{ - dynamic_params::{AggregratedKeyValue, IntoKey, Key, RuntimeParameterStore, TryIntoKey}, + dynamic_params::{AggregatedKeyValue, IntoKey, Key, RuntimeParameterStore, TryIntoKey}, EnsureOriginWithArg, }; @@ -135,10 +135,10 @@ pub use pallet::*; pub use weights::WeightInfo; /// The key type of a parameter. -type KeyOf = <::RuntimeParameters as AggregratedKeyValue>::Key; +type KeyOf = <::RuntimeParameters as AggregatedKeyValue>::Key; /// The value type of a parameter. -type ValueOf = <::RuntimeParameters as AggregratedKeyValue>::Value; +type ValueOf = <::RuntimeParameters as AggregatedKeyValue>::Value; #[frame_support::pallet] pub mod pallet { @@ -154,7 +154,7 @@ pub mod pallet { /// /// Usually created by [`frame_support::dynamic_params`] or equivalent. #[pallet::no_default_bounds] - type RuntimeParameters: AggregratedKeyValue; + type RuntimeParameters: AggregatedKeyValue; /// The origin which may update a parameter. /// @@ -175,11 +175,11 @@ pub mod pallet { /// Is also emitted when the value was not changed. Updated { /// The key that was updated. - key: ::Key, + key: ::Key, /// The old value before this call. - old_value: Option<::Value>, + old_value: Option<::Value>, /// The new value after this call. - new_value: Option<::Value>, + new_value: Option<::Value>, }, } @@ -245,23 +245,23 @@ pub mod pallet { } impl RuntimeParameterStore for Pallet { - type AggregratedKeyValue = T::RuntimeParameters; + type AggregatedKeyValue = T::RuntimeParameters; fn get(key: K) -> Option where - KV: AggregratedKeyValue, - K: Key + Into<::Key>, - ::Key: IntoKey< - <::AggregratedKeyValue as AggregratedKeyValue>::Key, + KV: AggregatedKeyValue, + K: Key + Into<::Key>, + ::Key: IntoKey< + <::AggregatedKeyValue as AggregatedKeyValue>::Key, >, - <::AggregratedKeyValue as AggregratedKeyValue>::Value: - TryIntoKey<::Value>, - ::Value: TryInto, + <::AggregatedKeyValue as AggregatedKeyValue>::Value: + TryIntoKey<::Value>, + ::Value: TryInto, { - let key: ::Key = key.into(); + let key: ::Key = key.into(); let val = Parameters::::get(key.into_key()); val.and_then(|v| { - let val: ::Value = v.try_into_key().ok()?; + let val: ::Value = v.try_into_key().ok()?; let val: K::WrappedValue = val.try_into().ok()?; let val = val.into(); Some(val) diff --git a/substrate/frame/parameters/src/tests/unit.rs b/substrate/frame/parameters/src/tests/unit.rs index d3f11ba9640..d811a835646 100644 --- a/substrate/frame/parameters/src/tests/unit.rs +++ b/substrate/frame/parameters/src/tests/unit.rs @@ -25,7 +25,7 @@ use crate::tests::mock::{ RuntimeParametersValue, }; use codec::Encode; -use frame_support::{assert_noop, assert_ok, traits::dynamic_params::AggregratedKeyValue}; +use frame_support::{assert_noop, assert_ok, traits::dynamic_params::AggregatedKeyValue}; use sp_core::Get; use sp_runtime::DispatchError; diff --git a/substrate/frame/proxy/src/lib.rs b/substrate/frame/proxy/src/lib.rs index 4d4da0433af..2b3fac5f59e 100644 --- a/substrate/frame/proxy/src/lib.rs +++ b/substrate/frame/proxy/src/lib.rs @@ -119,7 +119,7 @@ pub mod pallet { /// The currency mechanism. type Currency: ReservableCurrency; - /// A kind of proxy; specified with the proxy and passed in to the `IsProxyable` fitler. + /// A kind of proxy; specified with the proxy and passed in to the `IsProxyable` filter. /// The instance filter determines whether a given call may be proxied under this type. /// /// IMPORTANT: `Default` must be provided and MUST BE the the *most permissive* value. diff --git a/substrate/frame/root-testing/src/lib.rs b/substrate/frame/root-testing/src/lib.rs index 51fd835409a..98e1f5c5b66 100644 --- a/substrate/frame/root-testing/src/lib.rs +++ b/substrate/frame/root-testing/src/lib.rs @@ -17,7 +17,7 @@ //! # Root Testing Pallet //! -//! Pallet that contains extrinsics that can be usefull in testing. +//! Pallet that contains extrinsics that can be useful in testing. //! //! NOTE: This pallet should only be used for testing purposes and should not be used in production //! runtimes! diff --git a/substrate/frame/salary/src/tests/integration.rs b/substrate/frame/salary/src/tests/integration.rs index 26afb2d8aba..124ab38c565 100644 --- a/substrate/frame/salary/src/tests/integration.rs +++ b/substrate/frame/salary/src/tests/integration.rs @@ -250,7 +250,7 @@ fn swap_exhaustive_works() { }); assert_eq!(root_add, root_swap); - // Ensure that we dont compare trivial stuff like `()` from a type error above. + // Ensure that we don't compare trivial stuff like `()` from a type error above. assert_eq!(root_add.len(), 32); }); } diff --git a/substrate/frame/salary/src/tests/unit.rs b/substrate/frame/salary/src/tests/unit.rs index 5e308354116..db1c8b947ef 100644 --- a/substrate/frame/salary/src/tests/unit.rs +++ b/substrate/frame/salary/src/tests/unit.rs @@ -508,7 +508,7 @@ fn zero_payment_fails() { } #[test] -fn unregistered_bankrupcy_fails_gracefully() { +fn unregistered_bankruptcy_fails_gracefully() { new_test_ext().execute_with(|| { assert_ok!(Salary::init(RuntimeOrigin::signed(1))); set_rank(1, 2); @@ -532,7 +532,7 @@ fn unregistered_bankrupcy_fails_gracefully() { } #[test] -fn registered_bankrupcy_fails_gracefully() { +fn registered_bankruptcy_fails_gracefully() { new_test_ext().execute_with(|| { assert_ok!(Salary::init(RuntimeOrigin::signed(1))); set_rank(1, 2); @@ -561,7 +561,7 @@ fn registered_bankrupcy_fails_gracefully() { } #[test] -fn mixed_bankrupcy_fails_gracefully() { +fn mixed_bankruptcy_fails_gracefully() { new_test_ext().execute_with(|| { assert_ok!(Salary::init(RuntimeOrigin::signed(1))); set_rank(1, 2); @@ -589,7 +589,7 @@ fn mixed_bankrupcy_fails_gracefully() { } #[test] -fn other_mixed_bankrupcy_fails_gracefully() { +fn other_mixed_bankruptcy_fails_gracefully() { new_test_ext().execute_with(|| { assert_ok!(Salary::init(RuntimeOrigin::signed(1))); set_rank(1, 2); diff --git a/substrate/frame/sassafras/src/benchmarking.rs b/substrate/frame/sassafras/src/benchmarking.rs index 1c9626ad260..2b2467c6f84 100644 --- a/substrate/frame/sassafras/src/benchmarking.rs +++ b/substrate/frame/sassafras/src/benchmarking.rs @@ -84,7 +84,7 @@ mod benchmarks { // - load the full ring context. // - recompute the ring verifier. // - sorting the epoch tickets in one shot - // (here we account for the very unluky scenario where we haven't done any sort work yet) + // (here we account for the very unlucky scenario where we haven't done any sort work yet) // - pending epoch change config. // // For this bench we assume a redundancy factor of 2 (suggested value to be used in prod). diff --git a/substrate/frame/sassafras/src/lib.rs b/substrate/frame/sassafras/src/lib.rs index 0ee8657489b..8cbf1e47e32 100644 --- a/substrate/frame/sassafras/src/lib.rs +++ b/substrate/frame/sassafras/src/lib.rs @@ -234,7 +234,7 @@ pub mod pallet { /// Epoch X first N-th ticket has key (X mod 2, N) /// /// Note that the ticket's index doesn't directly correspond to the slot index within the epoch. - /// The assigment is computed dynamically using an *outside-in* strategy. + /// The assignment is computed dynamically using an *outside-in* strategy. /// /// Be aware that entries within this map are never removed, only overwritten. /// Last element index should be fetched from the [`TicketsMeta`] value. @@ -465,7 +465,7 @@ pub mod pallet { /// Plan an epoch configuration change. /// - /// The epoch configuration change is recorded and will be announced at the begining + /// The epoch configuration change is recorded and will be announced at the beginning /// of the next epoch together with next epoch authorities information. /// In other words, the configuration will be enacted one epoch later. /// @@ -758,11 +758,11 @@ impl Pallet { let randomness = hashing::blake2_256(buf.as_slice()); RandomnessAccumulator::::put(randomness); - let next_randoness = Self::update_epoch_randomness(1); + let next_randomness = Self::update_epoch_randomness(1); // Deposit a log as this is the first block in first epoch. let next_epoch = NextEpochDescriptor { - randomness: next_randoness, + randomness: next_randomness, authorities: Self::next_authorities().into_inner(), config: None, }; diff --git a/substrate/frame/scheduler/README.md b/substrate/frame/scheduler/README.md index 6aec2ddb0e4..5e233fdbdb0 100644 --- a/substrate/frame/scheduler/README.md +++ b/substrate/frame/scheduler/README.md @@ -16,7 +16,7 @@ for the origin: namely `frame_system::Config::BaseCallFilter` for all origin except root which will get no filter. And not the filter contained in origin use to call `fn schedule`. -If a call is scheduled using proxy or whatever mecanism which adds filter, +If a call is scheduled using proxy or whatever mechanism which adds filter, then those filter will not be used when dispatching the schedule call. ## Interface diff --git a/substrate/frame/scheduler/src/benchmarking.rs b/substrate/frame/scheduler/src/benchmarking.rs index 18441d54b39..884f7800038 100644 --- a/substrate/frame/scheduler/src/benchmarking.rs +++ b/substrate/frame/scheduler/src/benchmarking.rs @@ -211,7 +211,7 @@ benchmarks! { } verify { } - // `execute_dispatch` when the origin is `Signed`, not counting the dispatable's weight. + // `execute_dispatch` when the origin is `Signed`, not counting the dispatchable's weight. execute_dispatch_signed { let mut counter = WeightMeter::new(); let origin = make_origin::(true); @@ -222,7 +222,7 @@ benchmarks! { verify { } - // `execute_dispatch` when the origin is not `Signed`, not counting the dispatable's weight. + // `execute_dispatch` when the origin is not `Signed`, not counting the dispatchable's weight. execute_dispatch_unsigned { let mut counter = WeightMeter::new(); let origin = make_origin::(false); diff --git a/substrate/frame/scheduler/src/lib.rs b/substrate/frame/scheduler/src/lib.rs index af3abd8ac4f..62417b8d2cc 100644 --- a/substrate/frame/scheduler/src/lib.rs +++ b/substrate/frame/scheduler/src/lib.rs @@ -46,7 +46,7 @@ //! 1. Scheduling a runtime call at a specific block. #![doc = docify::embed!("src/tests.rs", basic_scheduling_works)] //! -//! 2. Scheduling a preimage hash of a runtime call at a specifc block +//! 2. Scheduling a preimage hash of a runtime call at a specific block #![doc = docify::embed!("src/tests.rs", scheduling_with_preimages_works)] //! diff --git a/substrate/frame/scheduler/src/tests.rs b/substrate/frame/scheduler/src/tests.rs index 1ed2ca9e2f3..bb02320ad75 100644 --- a/substrate/frame/scheduler/src/tests.rs +++ b/substrate/frame/scheduler/src/tests.rs @@ -1119,7 +1119,7 @@ fn reschedule_named_works() { } #[test] -fn reschedule_named_perodic_works() { +fn reschedule_named_periodic_works() { new_test_ext().execute_with(|| { let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_parts(10, 0) }); @@ -2980,7 +2980,7 @@ fn reschedule_named_last_task_removes_agenda() { }); } -/// Ensures that an unvailable call sends an event. +/// Ensures that an unavailable call sends an event. #[test] fn unavailable_call_is_detected() { use frame_support::traits::schedule::v3::Named; diff --git a/substrate/frame/society/src/lib.rs b/substrate/frame/society/src/lib.rs index 99dd580a403..5bce245f73f 100644 --- a/substrate/frame/society/src/lib.rs +++ b/substrate/frame/society/src/lib.rs @@ -1509,7 +1509,7 @@ impl, I: 'static> Pallet { // the Founder. if MemberCount::::get() > 2 { let defender = next_defender - .or_else(|| Self::pick_defendent(rng)) + .or_else(|| Self::pick_defendant(rng)) .expect("exited if members empty; qed"); let skeptic = Self::pick_member_except(rng, &defender).expect("exited if members empty; qed"); @@ -1871,7 +1871,7 @@ impl, I: 'static> Pallet { /// /// If only the Founder and Head members exist (or the state is inconsistent), then `None` /// may be returned. - fn pick_defendent(rng: &mut impl RngCore) -> Option { + fn pick_defendant(rng: &mut impl RngCore) -> Option { let member_count = MemberCount::::get(); if member_count <= 2 { return None @@ -1976,7 +1976,7 @@ impl, I: 'static> Pallet { /// Transfer some `amount` from the main account into the payouts account and reduce the Pot /// by this amount. fn reserve_payout(amount: BalanceOf) { - // Tramsfer payout from the Pot into the payouts account. + // Transfer payout from the Pot into the payouts account. Pot::::mutate(|pot| pot.saturating_reduce(amount)); // this should never fail since we ensure we can afford the payouts in a previous @@ -1988,7 +1988,7 @@ impl, I: 'static> Pallet { /// Transfer some `amount` from the main account into the payouts account and increase the Pot /// by this amount. fn unreserve_payout(amount: BalanceOf) { - // Tramsfer payout from the Pot into the payouts account. + // Transfer payout from the Pot into the payouts account. Pot::::mutate(|pot| pot.saturating_accrue(amount)); // this should never fail since we ensure we can afford the payouts in a previous diff --git a/substrate/frame/society/src/migrations.rs b/substrate/frame/society/src/migrations.rs index 6a102911451..8fd87b1163a 100644 --- a/substrate/frame/society/src/migrations.rs +++ b/substrate/frame/society/src/migrations.rs @@ -240,7 +240,7 @@ pub fn assert_internal_consistency, I: Instance + 'static>() { pub fn from_original, I: Instance + 'static>( past_payouts: &mut [(::AccountId, BalanceOf)], ) -> Result { - // Migrate Bids from old::Bids (just a trunctation). + // Migrate Bids from old::Bids (just a truncation). Bids::::put(BoundedVec::<_, T::MaxBids>::truncate_from(v0::Bids::::take())); // Initialise round counter. @@ -287,13 +287,13 @@ pub fn from_original, I: Instance + 'static>( .defensive_ok_or("member_count > 0, we must have at least 1 member")?; // Swap the founder with the first member in MemberByIndex. MemberByIndex::::swap(0, member_count); - // Update the indicies of the swapped member MemberRecords. + // Update the indices of the swapped member MemberRecords. Members::::mutate(&member, |m| { if let Some(member) = m { member.index = 0; } else { frame_support::defensive!( - "Member somehow disapeared from storage after it was inserted" + "Member somehow disappeared from storage after it was inserted" ); } }); @@ -302,7 +302,7 @@ pub fn from_original, I: Instance + 'static>( member.index = member_count; } else { frame_support::defensive!( - "Member somehow disapeared from storage after it was queried" + "Member somehow disappeared from storage after it was queried" ); } }); diff --git a/substrate/frame/society/src/tests.rs b/substrate/frame/society/src/tests.rs index 411567e1ded..5f8ecc9a7c5 100644 --- a/substrate/frame/society/src/tests.rs +++ b/substrate/frame/society/src/tests.rs @@ -541,7 +541,7 @@ fn suspended_candidate_rejected_works() { assert_ok!(Society::vote(Origin::signed(30), x, true)); } - // Voting continues, as no canidate is clearly accepted yet and the founder chooses not to + // Voting continues, as no candidate is clearly accepted yet and the founder chooses not to // act. conclude_intake(false, None); assert_eq!(members(), vec![10, 20, 30]); diff --git a/substrate/frame/staking/src/ledger.rs b/substrate/frame/staking/src/ledger.rs index 67be1e15bc6..9461daefed6 100644 --- a/substrate/frame/staking/src/ledger.rs +++ b/substrate/frame/staking/src/ledger.rs @@ -130,7 +130,7 @@ impl StakingLedger { // if ledger bond is in a bad state, return error to prevent applying operations that may // further spoil the ledger's state. A bond is in bad state when the bonded controller is - // associted with a different ledger (i.e. a ledger with a different stash). + // associated with a different ledger (i.e. a ledger with a different stash). // // See for more details. ensure!( diff --git a/substrate/frame/staking/src/migrations.rs b/substrate/frame/staking/src/migrations.rs index 3e3b1113a81..d5b18421d5b 100644 --- a/substrate/frame/staking/src/migrations.rs +++ b/substrate/frame/staking/src/migrations.rs @@ -30,7 +30,7 @@ use frame_support::ensure; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; -/// Used for release versioning upto v12. +/// Used for release versioning up to v12. /// /// Obsolete from v13. Keeping around to make encoding/decoding of old migration code easier. #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index d42456e53b1..407b301fad2 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -1906,7 +1906,7 @@ impl Pallet { /// Invariants: /// * A bonded ledger should always have an assigned `Payee`. /// * The number of entries in `Payee` and of bonded staking ledgers *must* match. - /// * The stash account in the ledger must match that of the bonded acount. + /// * The stash account in the ledger must match that of the bonded account. fn check_payees() -> Result<(), TryRuntimeError> { for (stash, _) in Bonded::::iter() { ensure!(Payee::::get(&stash).is_some(), "bonded ledger does not have payee set"); @@ -1947,7 +1947,7 @@ impl Pallet { /// Invariants: /// * `ledger.controller` is not stored in the storage (but populated at retrieval). /// * Stake consistency: ledger.total == ledger.active + sum(ledger.unlocking). - /// * The controller keyeing the ledger and the ledger stash matches the state of the `Bonded` + /// * The controller keying the ledger and the ledger stash matches the state of the `Bonded` /// storage. fn check_ledgers() -> Result<(), TryRuntimeError> { Bonded::::iter() diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 1bf8bd8b09c..6afbf12032d 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -54,7 +54,7 @@ use crate::{ }; // The speculative number of spans are used as an input of the weight annotation of -// [`Call::unbond`], as the post dipatch weight may depend on the number of slashing span on the +// [`Call::unbond`], as the post dispatch weight may depend on the number of slashing span on the // account which is not provided as an input. The value set should be conservative but sensible. pub(crate) const SPECULATIVE_NUM_SPANS: u32 = 32; @@ -1134,7 +1134,7 @@ pub mod pallet { /// this call results in a complete removal of all the data related to the stash account. /// In this case, the `num_slashing_spans` must be larger or equal to the number of /// slashing spans associated with the stash account in the [`SlashingSpans`] storage type, - /// otherwise the call will fail. The call weight is directly propotional to + /// otherwise the call will fail. The call weight is directly proportional to /// `num_slashing_spans`. /// /// ## Complexity @@ -1376,7 +1376,7 @@ pub mod pallet { Ok(()) } - /// Increments the ideal number of validators upto maximum of + /// Increments the ideal number of validators up to maximum of /// `ElectionProviderBase::MaxWinners`. /// /// The dispatch origin must be Root. @@ -1401,7 +1401,7 @@ pub mod pallet { Ok(()) } - /// Scale up the ideal number of validators by a factor upto maximum of + /// Scale up the ideal number of validators by a factor up to maximum of /// `ElectionProviderBase::MaxWinners`. /// /// The dispatch origin must be Root. diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index 3725c9e3c2c..ef156e19552 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -270,7 +270,7 @@ fn change_controller_works() { assert_eq!(ledger.controller(), Some(stash)); // the raw storage ledger's controller is always `None`. however, we can still fetch the - // correct controller with `ledger.controler()`. + // correct controller with `ledger.controller()`. let raw_ledger = >::get(&stash).unwrap(); assert_eq!(raw_ledger.controller, None); @@ -1257,7 +1257,7 @@ fn bond_extra_controller_bad_state_works() { Bonded::::insert(31, 41); // we confirm that the ledger is in bad state: 31 has 41 as controller and when fetching - // the ledger associated with the controler 41, its stash is 41 (and not 31). + // the ledger associated with the controller 41, its stash is 41 (and not 31). assert_eq!(Ledger::::get(41).unwrap().stash, 41); // if the ledger is in this bad state, the `bond_extra` should fail. @@ -1815,7 +1815,7 @@ fn max_staked_rewards_works() { let total_payout = treasury_payout + validators_payout; // max stakers payout (without max staked rewards cap applied) is larger than the final - // validator rewards. The final payment and remainder should be adjusted by redestributing + // validator rewards. The final payment and remainder should be adjusted by redistributing // the era inflation to apply the cap... assert!(max_stakers_payout > validators_payout); @@ -4686,7 +4686,7 @@ fn bond_during_era_does_not_populate_legacy_claimed_rewards() { } ); - // make sure only era upto history depth is stored + // make sure only era up to history depth is stored let current_era = 99; mock::start_active_era(current_era); bond_validator(13, 1000); @@ -5412,7 +5412,7 @@ mod election_data_provider { Event::SnapshotVotersSizeExceeded { size: 75 } ); - // however, if the election voter size bounds were largers, the snapshot would + // however, if the election voter size bounds were larger, the snapshot would // include the electing voters of 70. let bounds = ElectionBoundsBuilder::default().voters_size(1_000.into()).build(); assert_eq!( diff --git a/substrate/frame/sudo/src/lib.rs b/substrate/frame/sudo/src/lib.rs index d8b734e6bbe..63b68e69430 100644 --- a/substrate/frame/sudo/src/lib.rs +++ b/substrate/frame/sudo/src/lib.rs @@ -38,7 +38,7 @@ //! In Substrate blockchains, pallets may contain dispatchable calls that can only be called at //! the system level of the chain (i.e. dispatchables that require a `Root` origin). //! Setting a privileged account, called the _sudo key_, allows you to make such calls as an -//! extrinisic. +//! extrinsic. //! //! Here's an example of a privileged function in another pallet: //! diff --git a/substrate/frame/support/procedural/src/benchmark.rs b/substrate/frame/support/procedural/src/benchmark.rs index ea53ad263a1..0a62c3f92a6 100644 --- a/substrate/frame/support/procedural/src/benchmark.rs +++ b/substrate/frame/support/procedural/src/benchmark.rs @@ -249,7 +249,7 @@ impl BenchmarkCallDef { } } -/// Represents a parsed `#[benchmark]` or `#[instance_banchmark]` item. +/// Represents a parsed `#[benchmark]` or `#[instance_benchmark]` item. #[derive(Clone)] struct BenchmarkDef { params: Vec, @@ -466,7 +466,7 @@ pub fn benchmarks( let mod_vis = module.vis; let mod_name = module.ident; - // consume #[benchmarks] attribute by exclusing it from mod_attrs + // consume #[benchmarks] attribute by excluding it from mod_attrs let mod_attrs: Vec<&Attribute> = module .attrs .iter() diff --git a/substrate/frame/support/procedural/src/construct_runtime/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/mod.rs index 1937dfa9ca4..b083abbb2a8 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/mod.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/mod.rs @@ -24,7 +24,7 @@ //! - Implicitly: `System: frame_system` //! - Explicitly: `System: frame_system::{Pallet, Call}` //! -//! The `construct_runtime` transitions from the implicit definition to the explict one. +//! The `construct_runtime` transitions from the implicit definition to the explicit one. //! From the explicit state, Substrate expands the pallets with additional information //! that is to be included in the runtime metadata. This expansion makes visible some extra //! parts of the pallets, mainly the `Error` if defined. The expanded state looks like @@ -55,7 +55,7 @@ //! +----------+ +------------------+ //! ``` //! -//! When all pallet parts are implcit, then the `construct_runtime!` macro expands to its final +//! When all pallet parts are implicit, then the `construct_runtime!` macro expands to its final //! state, the `ExplicitExpanded`. Otherwise, all implicit parts are converted to an explicit //! expanded part allow the `construct_runtime!` to expand any remaining explicit parts to an //! explicit expanded part. @@ -202,7 +202,7 @@ //! Similarly to the previous transition, the macro expansion transforms `System: //! frame_system::{Pallet, Call}` into `System: frame_system expanded::{Error} ::{Pallet, Call}`. //! The `expanded` section adds extra parts that the Substrate would like to expose for each pallet -//! by default. This is done to expose the approprite types for metadata construction. +//! by default. This is done to expose the appropriate types for metadata construction. //! //! This time, instead of calling `tt_default_parts` we are using the `tt_extra_parts` macro. //! This macro returns the ` :: expanded { Error }` list of additional parts we would like to diff --git a/substrate/frame/support/procedural/src/construct_runtime/parse.rs b/substrate/frame/support/procedural/src/construct_runtime/parse.rs index 88f3f14dc86..31866c787b0 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/parse.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/parse.rs @@ -322,7 +322,7 @@ impl Parse for PalletDeclaration { /// A struct representing a path to a pallet. `PalletPath` is almost identical to the standard /// Rust path with a few restrictions: /// - No leading colons allowed -/// - Path segments can only consist of identifers separated by colons +/// - Path segments can only consist of identifiers separated by colons #[derive(Debug, Clone)] pub struct PalletPath { pub inner: Path, @@ -595,7 +595,7 @@ pub struct Pallet { pub is_expanded: bool, /// The name of the pallet, e.g.`System` in `System: frame_system`. pub name: Ident, - /// Either automatically infered, or defined (e.g. `MyPallet ... = 3,`). + /// Either automatically inferred, or defined (e.g. `MyPallet ... = 3,`). pub index: u8, /// The path of the pallet, e.g. `frame_system` in `System: frame_system`. pub path: PalletPath, @@ -634,7 +634,7 @@ impl Pallet { /// +----------+ +----------+ +------------------+ /// ``` enum PalletsConversion { - /// Pallets implicitely declare parts. + /// Pallets implicitly declare parts. /// /// `System: frame_system`. Implicit(Vec), @@ -648,7 +648,7 @@ enum PalletsConversion { /// Pallets explicitly declare parts that are fully expanded. /// /// This is the end state that contains extra parts included by - /// default by Subtrate. + /// default by Substrate. /// /// `System: frame_system expanded::{Error} ::{Pallet, Call}` /// @@ -660,7 +660,7 @@ enum PalletsConversion { /// /// Check if all pallet have explicit declaration of their parts, if so then assign index to each /// pallet using same rules as rust for fieldless enum. I.e. implicit are assigned number -/// incrementedly from last explicit or 0. +/// incrementally from last explicit or 0. fn convert_pallets(pallets: Vec) -> syn::Result { if pallets.iter().any(|pallet| pallet.pallet_parts.is_none()) { return Ok(PalletsConversion::Implicit(pallets)) diff --git a/substrate/frame/support/procedural/src/derive_impl.rs b/substrate/frame/support/procedural/src/derive_impl.rs index 8740ccd401a..54755f1163a 100644 --- a/substrate/frame/support/procedural/src/derive_impl.rs +++ b/substrate/frame/support/procedural/src/derive_impl.rs @@ -279,7 +279,7 @@ fn test_runtime_type_with_doc() { } #[test] -fn test_disambugation_path() { +fn test_disambiguation_path() { let foreign_impl: ItemImpl = parse_quote!(impl SomeTrait for SomeType {}); let default_impl_path: Path = parse_quote!(SomeScope::SomeType); diff --git a/substrate/frame/support/procedural/src/dynamic_params.rs b/substrate/frame/support/procedural/src/dynamic_params.rs index b718ccbc955..29399a885bc 100644 --- a/substrate/frame/support/procedural/src/dynamic_params.rs +++ b/substrate/frame/support/procedural/src/dynamic_params.rs @@ -147,8 +147,8 @@ fn ensure_codec_index(attrs: &Vec, span: Span) -> Result<()> { /// Used to inject arguments into the inner `#[dynamic_pallet_params(..)]` attribute. /// -/// This allows the outer `#[dynamic_params(..)]` attribute to specify some arguments that dont need -/// to be repeated every time. +/// This allows the outer `#[dynamic_params(..)]` attribute to specify some arguments that don't +/// need to be repeated every time. struct MacroInjectArgs { runtime_params: syn::Ident, params_pallet: syn::Type, @@ -311,7 +311,7 @@ impl ToTokens for DynamicPalletParamAttr { )* } - impl #scrate::traits::dynamic_params::AggregratedKeyValue for Parameters { + impl #scrate::traits::dynamic_params::AggregatedKeyValue for Parameters { type Key = #key_ident; type Value = #value_ident; @@ -497,7 +497,7 @@ impl ToTokens for DynamicParamAggregatedEnum { #vis enum #params_key_ident { #( #(#attributes)* - #param_names(<#param_types as #scrate::traits::dynamic_params::AggregratedKeyValue>::Key), + #param_names(<#param_types as #scrate::traits::dynamic_params::AggregatedKeyValue>::Key), )* } @@ -515,11 +515,11 @@ impl ToTokens for DynamicParamAggregatedEnum { #vis enum #params_value_ident { #( #(#attributes)* - #param_names(<#param_types as #scrate::traits::dynamic_params::AggregratedKeyValue>::Value), + #param_names(<#param_types as #scrate::traits::dynamic_params::AggregatedKeyValue>::Value), )* } - impl #scrate::traits::dynamic_params::AggregratedKeyValue for #name { + impl #scrate::traits::dynamic_params::AggregatedKeyValue for #name { type Key = #params_key_ident; type Value = #params_value_ident; @@ -536,13 +536,13 @@ impl ToTokens for DynamicParamAggregatedEnum { } #( - impl ::core::convert::From<<#param_types as #scrate::traits::dynamic_params::AggregratedKeyValue>::Key> for #params_key_ident { - fn from(key: <#param_types as #scrate::traits::dynamic_params::AggregratedKeyValue>::Key) -> Self { + impl ::core::convert::From<<#param_types as #scrate::traits::dynamic_params::AggregatedKeyValue>::Key> for #params_key_ident { + fn from(key: <#param_types as #scrate::traits::dynamic_params::AggregatedKeyValue>::Key) -> Self { #params_key_ident::#param_names(key) } } - impl ::core::convert::TryFrom<#params_value_ident> for <#param_types as #scrate::traits::dynamic_params::AggregratedKeyValue>::Value { + impl ::core::convert::TryFrom<#params_value_ident> for <#param_types as #scrate::traits::dynamic_params::AggregatedKeyValue>::Value { type Error = (); fn try_from(value: #params_value_ident) -> Result { diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index dee6d522d25..bc62c0509b0 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -137,7 +137,7 @@ fn counter_prefix(prefix: &str) -> String { /// - `Call` - If the pallet has callable functions /// - `Storage` - If the pallet uses storage /// - `Event` or `Event` (if the event is generic) - If the pallet emits events -/// - `Origin` or `Origin` (if the origin is generic) - If the pallet has instanciable origins +/// - `Origin` or `Origin` (if the origin is generic) - If the pallet has instantiable origins /// - `Config` or `Config` (if the config is generic) - If the pallet builds the genesis /// storage with `GenesisConfig` /// - `Inherent` - If the pallet provides/can check inherents. @@ -166,7 +166,7 @@ fn counter_prefix(prefix: &str) -> String { /// and `Event` are encoded, and to define the ModuleToIndex value. /// /// if `= $n` is not given, then index is resolved in the same way as fieldless enum in Rust -/// (i.e. incrementedly from previous index): +/// (i.e. incrementally from previous index): /// ```nocompile /// pallet1 .. = 2, /// pallet2 .., // Here pallet2 is given index 3 @@ -460,7 +460,7 @@ pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream } /// This attribute can be used to derive a full implementation of a trait based on a local partial -/// impl and an external impl containing defaults that can be overriden in the local impl. +/// impl and an external impl containing defaults that can be overridden in the local impl. /// /// For a full end-to-end example, see [below](#use-case-auto-derive-test-pallet-config-traits). /// diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index b55f130a93a..6e12774611d 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -321,7 +321,7 @@ impl Def { Ok(()) } - /// Tries to locate a manual tasks impl (an impl impling a trait whose last path segment is + /// Tries to locate a manual tasks impl (an impl implementing a trait whose last path segment is /// `Task`) in the event that one has not been found already via the attribute macro pub fn resolve_manual_tasks_impl( tasks: &mut Option, diff --git a/substrate/frame/support/src/dispatch_context.rs b/substrate/frame/support/src/dispatch_context.rs index 608187b7220..254302c8f14 100644 --- a/substrate/frame/support/src/dispatch_context.rs +++ b/substrate/frame/support/src/dispatch_context.rs @@ -18,7 +18,7 @@ //! Provides functions to interact with the dispatch context. //! //! A Dispatch context is created by calling [`run_in_context`] and then the given closure will be -//! executed in this dispatch context. Everyting run in this `closure` will have access to the same +//! executed in this dispatch context. Everything run in this `closure` will have access to the same //! dispatch context. This also applies to nested calls of [`run_in_context`]. The dispatch context //! can be used to store and retrieve information locally in this context. The dispatch context can //! be accessed by using [`with_context`]. This function will execute the given closure and give it @@ -51,7 +51,7 @@ //! //! run_in_context(|| { //! with_context::(|v| { -//! // Intitialize the value to the default value. +//! // Initialize the value to the default value. //! assert_eq!(0, v.or_default().0); //! v.or_default().0 = 10; //! }); diff --git a/substrate/frame/support/src/instances.rs b/substrate/frame/support/src/instances.rs index 396018d5cbd..ecb356af50b 100644 --- a/substrate/frame/support/src/instances.rs +++ b/substrate/frame/support/src/instances.rs @@ -31,83 +31,83 @@ //! NOTE: [`frame_support::pallet`] will reexport them inside the module, in order to make them //! accessible to [`frame_support::construct_runtime`]. -/// `Instance1` to be used for instantiable palllets defined with the +/// `Instance1` to be used for instantiable pallets defined with the /// [`#[pallet]`](`frame_support::pallet`) macro. Instances 2-16 are also available but are hidden /// from docs. #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance1; -/// `Instance2` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance2` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance2; -/// `Instance3` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance3` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance3; -/// `Instance4` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance4` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance4; -/// `Instance5` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance5` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance5; -/// `Instance6` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance6` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance6; -/// `Instance7` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance7` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance7; -/// `Instance8` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance8` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance8; -/// `Instance9` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance9` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance9; -/// `Instance10` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance10` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance10; -/// `Instance11` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance11` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance11; -/// `Instance12` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance12` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance12; -/// `Instance13` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance13` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance13; -/// `Instance14` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance14` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance14; -/// `Instance15` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance15` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance15; -/// `Instance16` to be used for instantiable palllets defined with the `#[pallet]` macro. +/// `Instance16` to be used for instantiable pallets defined with the `#[pallet]` macro. #[doc(hidden)] #[derive(Clone, Copy, PartialEq, Eq, crate::RuntimeDebugNoBound)] pub struct Instance16; diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index c524f8953a4..895215d364e 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -145,7 +145,7 @@ impl TypeId for PalletId { /// # Examples /// /// There are different ways to declare the `prefix` to use. The `prefix` type can either be -/// declared explicetly by passing it to the macro as an attribute or by letting the macro +/// declared explicitly by passing it to the macro as an attribute or by letting the macro /// guess on what the `prefix` type is. The `prefix` is always passed as the first generic /// argument to the type declaration. When using [`#[pallet::storage]`](pallet_macros::storage) /// this first generic argument is always `_`. Besides declaring the `prefix`, the rest of the @@ -1110,7 +1110,7 @@ pub mod pallet_macros { /// Declares a storage as unbounded in potential size. /// - /// When implementating the storage info (when `#[pallet::generate_storage_info]` is + /// When implementing the storage info (when `#[pallet::generate_storage_info]` is /// specified on the pallet struct placeholder), the size of the storage will be declared /// as unbounded. This can be useful for storage which can never go into PoV (Proof of /// Validity). @@ -2340,7 +2340,7 @@ pub mod pallet_macros { /// Allows defining conditions for a task to run. /// - /// This attribute is attached to a function inside an `impl` block annoated with + /// This attribute is attached to a function inside an `impl` block annotated with /// [`pallet::tasks_experimental`](`tasks_experimental`) to define the conditions for a /// given work item to be valid. /// @@ -2351,7 +2351,7 @@ pub mod pallet_macros { /// Allows defining an index for a task. /// - /// This attribute is attached to a function inside an `impl` block annoated with + /// This attribute is attached to a function inside an `impl` block annotated with /// [`pallet::tasks_experimental`](`tasks_experimental`) to define the index of a given /// work item. /// @@ -2361,7 +2361,7 @@ pub mod pallet_macros { /// Allows defining an iterator over available work items for a task. /// - /// This attribute is attached to a function inside an `impl` block annoated with + /// This attribute is attached to a function inside an `impl` block annotated with /// [`pallet::tasks_experimental`](`tasks_experimental`). /// /// It takes an iterator as input that yields a tuple with same types as the function @@ -2370,7 +2370,7 @@ pub mod pallet_macros { /// Allows defining the weight of a task. /// - /// This attribute is attached to a function inside an `impl` block annoated with + /// This attribute is attached to a function inside an `impl` block annotated with /// [`pallet::tasks_experimental`](`tasks_experimental`) define the weight of a given work /// item. /// diff --git a/substrate/frame/support/src/storage/migration.rs b/substrate/frame/support/src/storage/migration.rs index 568c475bdc6..252625cf4f7 100644 --- a/substrate/frame/support/src/storage/migration.rs +++ b/substrate/frame/support/src/storage/migration.rs @@ -303,11 +303,11 @@ pub fn take_storage_item /// Move a storage from a pallet prefix to another pallet prefix. /// /// Keys used in pallet storages always start with: -/// `concat(twox_128(pallet_name), towx_128(storage_name))`. +/// `concat(twox_128(pallet_name), twox_128(storage_name))`. /// /// This function will remove all value for which the key start with -/// `concat(twox_128(old_pallet_name), towx_128(storage_name))` and insert them at the key with -/// the start replaced by `concat(twox_128(new_pallet_name), towx_128(storage_name))`. +/// `concat(twox_128(old_pallet_name), twox_128(storage_name))` and insert them at the key with +/// the start replaced by `concat(twox_128(new_pallet_name), twox_128(storage_name))`. /// /// # Example /// @@ -339,7 +339,7 @@ pub fn move_storage_from_pallet( /// Move all storages from a pallet prefix to another pallet prefix. /// /// Keys used in pallet storages always start with: -/// `concat(twox_128(pallet_name), towx_128(storage_name))`. +/// `concat(twox_128(pallet_name), twox_128(storage_name))`. /// /// This function will remove all value for which the key start with `twox_128(old_pallet_name)` /// and insert them at the key with the start replaced by `twox_128(new_pallet_name)`. diff --git a/substrate/frame/support/src/storage/mod.rs b/substrate/frame/support/src/storage/mod.rs index 8ebe7b31da8..f7d7447482d 100644 --- a/substrate/frame/support/src/storage/mod.rs +++ b/substrate/frame/support/src/storage/mod.rs @@ -159,7 +159,7 @@ pub trait StorageValue { /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. fn decode_len() -> Option where @@ -363,7 +363,7 @@ pub trait StorageMap { /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. fn decode_len>(key: KeyArg) -> Option where @@ -381,7 +381,8 @@ pub trait StorageMap { /// /// # Warning /// - /// - `None` does not mean that `get()` does not return a value. The default value is completly + /// - `None` does not mean that `get()` does not return a value. The default value is + /// completely /// ignored by this function. /// /// - The value returned is the non-deduplicated length of the underlying Vector in storage.This @@ -410,7 +411,7 @@ pub trait StorageMap { pub trait IterableStorageMap: StorageMap { /// The type that iterates over all `(key, value)`. type Iterator: Iterator; - /// The type that itereates over all `key`s. + /// The type that iterates over all `key`s. type KeyIterator: Iterator; /// Enumerate all elements in the map in lexicographical order of the encoded key. If you @@ -777,7 +778,7 @@ pub trait StorageDoubleMap { /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. fn decode_len(key1: KArg1, key2: KArg2) -> Option where @@ -798,7 +799,7 @@ pub trait StorageDoubleMap { /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. fn decode_non_dedup_len(key1: KArg1, key2: KArg2) -> Option where @@ -980,7 +981,7 @@ pub trait StorageNMap { /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. fn decode_len + TupleToEncodedIter>(key: KArg) -> Option where @@ -1488,8 +1489,8 @@ pub trait StorageDecodeLength: private::Sealed + codec::DecodeLength { } } -/// It is expected that the length is at the beginning of the encoded objectand that the length is a -/// `Compact`. +/// It is expected that the length is at the beginning of the encoded object and that the length is +/// a `Compact`. /// /// # Note /// The length returned by this trait is not deduplicated, i.e. it is the length of the underlying @@ -1790,7 +1791,7 @@ mod test { }); } - // This test ensures that the Digest encoding does not change without being noticied. + // This test ensures that the Digest encoding does not change without being noticed. #[test] fn digest_storage_append_works_as_expected() { TestExternalities::default().execute_with(|| { diff --git a/substrate/frame/support/src/storage/stream_iter.rs b/substrate/frame/support/src/storage/stream_iter.rs index 2205601938b..529b2f387c7 100644 --- a/substrate/frame/support/src/storage/stream_iter.rs +++ b/substrate/frame/support/src/storage/stream_iter.rs @@ -217,7 +217,7 @@ const STORAGE_INPUT_BUFFER_CAPACITY: usize = 2 * 1024; /// Implementation of [`codec::Input`] using [`sp_io::storage::read`]. /// /// Keeps an internal buffer with a size of [`STORAGE_INPUT_BUFFER_CAPACITY`]. All read accesses -/// are tried to be served by this buffer. If the buffer doesn't hold enough bytes to fullfill the +/// are tried to be served by this buffer. If the buffer doesn't hold enough bytes to fulfill the /// current read access, the buffer is re-filled from the state. A read request that is bigger than /// the internal buffer is directly forwarded to the state to reduce the number of reads from the /// state. diff --git a/substrate/frame/support/src/storage/types/counted_map.rs b/substrate/frame/support/src/storage/types/counted_map.rs index 04e69751c16..0444e269928 100644 --- a/substrate/frame/support/src/storage/types/counted_map.rs +++ b/substrate/frame/support/src/storage/types/counted_map.rs @@ -310,7 +310,7 @@ where /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. pub fn decode_len>(key: KeyArg) -> Option where @@ -775,13 +775,13 @@ mod test { assert_eq!(A::try_get(1), Err(())); assert_eq!(A::count(), 3); - // Take exsisting. + // Take existing. assert_eq!(A::take(4), 10); assert_eq!(A::try_get(4), Err(())); assert_eq!(A::count(), 2); - // Take non-exsisting. + // Take non-existing. assert_eq!(A::take(4), ADefault::get()); assert_eq!(A::try_get(4), Err(())); @@ -1022,13 +1022,13 @@ mod test { assert_eq!(B::try_get(1), Err(())); assert_eq!(B::count(), 3); - // Take exsisting. + // Take existing. assert_eq!(B::take(4), Some(10)); assert_eq!(B::try_get(4), Err(())); assert_eq!(B::count(), 2); - // Take non-exsisting. + // Take non-existing. assert_eq!(B::take(4), None); assert_eq!(B::try_get(4), Err(())); diff --git a/substrate/frame/support/src/storage/types/counted_nmap.rs b/substrate/frame/support/src/storage/types/counted_nmap.rs index 279894ee973..51cde93f28c 100644 --- a/substrate/frame/support/src/storage/types/counted_nmap.rs +++ b/substrate/frame/support/src/storage/types/counted_nmap.rs @@ -378,7 +378,7 @@ where /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. pub fn decode_len + TupleToEncodedIter>( key: KArg, diff --git a/substrate/frame/support/src/storage/types/double_map.rs b/substrate/frame/support/src/storage/types/double_map.rs index cb9479d491c..2a7af7a9846 100644 --- a/substrate/frame/support/src/storage/types/double_map.rs +++ b/substrate/frame/support/src/storage/types/double_map.rs @@ -445,7 +445,7 @@ where /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. pub fn decode_len(key1: KArg1, key2: KArg2) -> Option where @@ -465,7 +465,8 @@ where /// /// # Warning /// - /// - `None` does not mean that `get()` does not return a value. The default value is completly + /// - `None` does not mean that `get()` does not return a value. The default value is + /// completely /// ignored by this function. /// /// - The value returned is the non-deduplicated length of the underlying Vector in storage.This diff --git a/substrate/frame/support/src/storage/types/map.rs b/substrate/frame/support/src/storage/types/map.rs index ee5db74583b..b79a6ae9b84 100644 --- a/substrate/frame/support/src/storage/types/map.rs +++ b/substrate/frame/support/src/storage/types/map.rs @@ -277,7 +277,7 @@ where /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. pub fn decode_len>(key: KeyArg) -> Option where @@ -295,7 +295,8 @@ where /// /// # Warning /// - /// - `None` does not mean that `get()` does not return a value. The default value is completly + /// - `None` does not mean that `get()` does not return a value. The default value is + /// completely /// ignored by this function. /// /// - The value returned is the non-deduplicated length of the underlying Vector in storage.This diff --git a/substrate/frame/support/src/storage/types/mod.rs b/substrate/frame/support/src/storage/types/mod.rs index 9dd6f4066e4..631410f425d 100644 --- a/substrate/frame/support/src/storage/types/mod.rs +++ b/substrate/frame/support/src/storage/types/mod.rs @@ -195,7 +195,7 @@ mod test { // result query returns error assert_eq!(C::get(), Err(())); - // value query with custom onempty returns 42 + // value query with custom on empty returns 42 assert_eq!(D::get(), 42); }); } diff --git a/substrate/frame/support/src/storage/types/nmap.rs b/substrate/frame/support/src/storage/types/nmap.rs index 0723db68900..253f02a14f0 100755 --- a/substrate/frame/support/src/storage/types/nmap.rs +++ b/substrate/frame/support/src/storage/types/nmap.rs @@ -348,7 +348,7 @@ where /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. pub fn decode_len + TupleToEncodedIter>( key: KArg, diff --git a/substrate/frame/support/src/storage/types/value.rs b/substrate/frame/support/src/storage/types/value.rs index 263091dd252..a2d93a6a165 100644 --- a/substrate/frame/support/src/storage/types/value.rs +++ b/substrate/frame/support/src/storage/types/value.rs @@ -225,7 +225,7 @@ where /// /// # Warning /// - /// `None` does not mean that `get()` does not return a value. The default value is completly + /// `None` does not mean that `get()` does not return a value. The default value is completely /// ignored by this function. pub fn decode_len() -> Option where @@ -243,7 +243,8 @@ where /// /// # Warning /// - /// - `None` does not mean that `get()` does not return a value. The default value is completly + /// - `None` does not mean that `get()` does not return a value. The default value is + /// completely /// ignored by this function. /// /// - The value returned is the non-deduplicated length of the underlying Vector in storage.This diff --git a/substrate/frame/support/src/traits/dispatch.rs b/substrate/frame/support/src/traits/dispatch.rs index de50ce7a26c..7dc8d3e4f5a 100644 --- a/substrate/frame/support/src/traits/dispatch.rs +++ b/substrate/frame/support/src/traits/dispatch.rs @@ -540,7 +540,7 @@ pub trait OriginTrait: Sized { }) } - /// Extract a reference to the sytsem origin, if that's what the caller is. + /// Extract a reference to the system origin, if that's what the caller is. fn as_system_ref(&self) -> Option<&RawOrigin> { self.caller().as_system_ref() } diff --git a/substrate/frame/support/src/traits/dynamic_params.rs b/substrate/frame/support/src/traits/dynamic_params.rs index 8881df04141..32dae6799ea 100644 --- a/substrate/frame/support/src/traits/dynamic_params.rs +++ b/substrate/frame/support/src/traits/dynamic_params.rs @@ -25,30 +25,30 @@ use frame_support::Parameter; /// A dynamic parameter store across an aggregated KV type. pub trait RuntimeParameterStore { - type AggregratedKeyValue: AggregratedKeyValue; + type AggregatedKeyValue: AggregatedKeyValue; /// Get the value of a parametrized key. /// /// Should return `None` if no explicit value was set instead of a default. fn get(key: K) -> Option where - KV: AggregratedKeyValue, - K: Key + Into<::Key>, - ::Key: IntoKey< - <::AggregratedKeyValue as AggregratedKeyValue>::Key, + KV: AggregatedKeyValue, + K: Key + Into<::Key>, + ::Key: IntoKey< + <::AggregatedKeyValue as AggregatedKeyValue>::Key, >, - <::AggregratedKeyValue as AggregratedKeyValue>::Value: - TryIntoKey<::Value>, - ::Value: TryInto; + <::AggregatedKeyValue as AggregatedKeyValue>::Value: + TryIntoKey<::Value>, + ::Value: TryInto; } /// A dynamic parameter store across a concrete KV type. -pub trait ParameterStore { +pub trait ParameterStore { /// Get the value of a parametrized key. fn get(key: K) -> Option where - K: Key + Into<::Key>, - ::Value: TryInto; + K: Key + Into<::Key>, + ::Value: TryInto; } /// Key of a dynamic parameter. @@ -61,7 +61,7 @@ pub trait Key { } /// The aggregated key-value type of a dynamic parameter store. -pub trait AggregratedKeyValue: Parameter { +pub trait AggregatedKeyValue: Parameter { /// The aggregated key type. type Key: Parameter + MaxEncodedLen; @@ -72,7 +72,7 @@ pub trait AggregratedKeyValue: Parameter { fn into_parts(self) -> (Self::Key, Option); } -impl AggregratedKeyValue for () { +impl AggregatedKeyValue for () { type Key = (); type Value = (); @@ -90,17 +90,17 @@ pub struct ParameterStoreAdapter(sp_std::marker::PhantomData<(PS, KV)>); impl ParameterStore for ParameterStoreAdapter where PS: RuntimeParameterStore, - KV: AggregratedKeyValue, - ::Key: - IntoKey<<::AggregratedKeyValue as AggregratedKeyValue>::Key>, - ::Value: TryFromKey< - <::AggregratedKeyValue as AggregratedKeyValue>::Value, + KV: AggregatedKeyValue, + ::Key: + IntoKey<<::AggregatedKeyValue as AggregatedKeyValue>::Key>, + ::Value: TryFromKey< + <::AggregatedKeyValue as AggregatedKeyValue>::Value, >, { fn get(key: K) -> Option where - K: Key + Into<::Key>, - ::Value: TryInto, + K: Key + Into<::Key>, + ::Value: TryInto, { PS::get::(key) } diff --git a/substrate/frame/support/src/traits/hooks.rs b/substrate/frame/support/src/traits/hooks.rs index 7d0e5aa1e89..d83e2704745 100644 --- a/substrate/frame/support/src/traits/hooks.rs +++ b/substrate/frame/support/src/traits/hooks.rs @@ -167,7 +167,7 @@ pub trait OnGenesis { /// /// This hook is intended to be used internally in FRAME and not be exposed to FRAME developers. /// -/// It is defined as a seperate trait from [`OnRuntimeUpgrade`] precisely to not pollute the public +/// It is defined as a separate trait from [`OnRuntimeUpgrade`] precisely to not pollute the public /// API. pub trait BeforeAllRuntimeMigrations { /// Something that should happen before runtime migrations are executed. diff --git a/substrate/frame/support/src/traits/misc.rs b/substrate/frame/support/src/traits/misc.rs index 1f634a64282..bc7407a7be6 100644 --- a/substrate/frame/support/src/traits/misc.rs +++ b/substrate/frame/support/src/traits/misc.rs @@ -1424,7 +1424,7 @@ mod test { assert_eq!(>::max_encoded_len(), 2usize.pow(14) + 4); let data = 4u64; - // Ensure that we check that the `Vec` is consumed completly on decode. + // Ensure that we check that the `Vec` is consumed completely on decode. assert!(WrapperOpaque::::decode(&mut &data.encode().encode()[..]).is_err()); } diff --git a/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/regular/unbalanced.rs b/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/regular/unbalanced.rs index e7fcc15472e..a5220736898 100644 --- a/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/regular/unbalanced.rs +++ b/substrate/frame/support/src/traits/tokens/fungible/conformance_tests/regular/unbalanced.rs @@ -94,7 +94,7 @@ where ); assert_eq!(T::balance(&account_0), account_0_initial_balance - amount); - // Decreasing the balance below funds avalibale should fail when Precision::Exact + // Decreasing the balance below funds available should fail when Precision::Exact let balance_before = T::balance(&account_0); assert_eq!( T::decrease_balance( diff --git a/substrate/frame/support/src/traits/tokens/imbalance/split_two_ways.rs b/substrate/frame/support/src/traits/tokens/imbalance/split_two_ways.rs index c1afac35fc9..59a582389ba 100644 --- a/substrate/frame/support/src/traits/tokens/imbalance/split_two_ways.rs +++ b/substrate/frame/support/src/traits/tokens/imbalance/split_two_ways.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Means for splitting an imbalance into two and hanlding them differently. +//! Means for splitting an imbalance into two and handling them differently. use super::super::imbalance::{Imbalance, OnUnbalanced}; use sp_runtime::traits::Saturating; diff --git a/substrate/frame/support/src/traits/tokens/misc.rs b/substrate/frame/support/src/traits/tokens/misc.rs index fd497bc4eda..a4dd5e49142 100644 --- a/substrate/frame/support/src/traits/tokens/misc.rs +++ b/substrate/frame/support/src/traits/tokens/misc.rs @@ -130,7 +130,7 @@ impl WithdrawConsequence { pub enum DepositConsequence { /// Deposit couldn't happen due to the amount being too low. This is usually because the /// account doesn't yet exist and the deposit wouldn't bring it to at least the minimum needed - /// for existance. + /// for existence. BelowMinimum, /// Deposit cannot happen since the account cannot be created (usually because it's a consumer /// and there exists no provider reference). diff --git a/substrate/frame/support/test/tests/derive_impl_ui/attached_to_non_impl.rs b/substrate/frame/support/test/tests/derive_impl_ui/attached_to_non_impl.rs index 332e1e78730..3f3148a03a9 100644 --- a/substrate/frame/support/test/tests/derive_impl_ui/attached_to_non_impl.rs +++ b/substrate/frame/support/test/tests/derive_impl_ui/attached_to_non_impl.rs @@ -50,7 +50,7 @@ impl Animal for FourLeggedAnimal { } } -pub struct AcquaticMammal {} +pub struct AquaticMammal {} #[derive_impl(FourLeggedAnimal as Animal)] struct Something {} diff --git a/substrate/frame/support/test/tests/derive_impl_ui/bad_default_impl_path.rs b/substrate/frame/support/test/tests/derive_impl_ui/bad_default_impl_path.rs index bc118acdf1e..7093c32400b 100644 --- a/substrate/frame/support/test/tests/derive_impl_ui/bad_default_impl_path.rs +++ b/substrate/frame/support/test/tests/derive_impl_ui/bad_default_impl_path.rs @@ -50,14 +50,14 @@ impl Animal for FourLeggedAnimal { } } -pub struct AcquaticMammal {} +pub struct AquaticMammal {} // Should throw: `error: cannot find macro `__export_tokens_tt_tiger` in this scope` // // Note that there is really no better way to clean up this error, tt_call suffers from the // same downside but this is really the only rough edge when using macro magic. #[derive_impl(Tiger as Animal)] -impl Animal for AcquaticMammal { +impl Animal for AquaticMammal { type Locomotion = (Swims, RunsOnFourLegs); type Environment = (Land, Sea); } diff --git a/substrate/frame/support/test/tests/derive_impl_ui/bad_disambiguation_path.rs b/substrate/frame/support/test/tests/derive_impl_ui/bad_disambiguation_path.rs index 9535ac3deda..8e0253e45c1 100644 --- a/substrate/frame/support/test/tests/derive_impl_ui/bad_disambiguation_path.rs +++ b/substrate/frame/support/test/tests/derive_impl_ui/bad_disambiguation_path.rs @@ -50,10 +50,10 @@ impl Animal for FourLeggedAnimal { } } -pub struct AcquaticMammal {} +pub struct AquaticMammal {} #[derive_impl(FourLeggedAnimal as Insect)] -impl Animal for AcquaticMammal { +impl Animal for AquaticMammal { type Locomotion = (Swims, RunsOnFourLegs); type Environment = (Land, Sea); } diff --git a/substrate/frame/support/test/tests/derive_impl_ui/missing_disambiguation_path.rs b/substrate/frame/support/test/tests/derive_impl_ui/missing_disambiguation_path.rs index f26c28313e5..4914ceea0b6 100644 --- a/substrate/frame/support/test/tests/derive_impl_ui/missing_disambiguation_path.rs +++ b/substrate/frame/support/test/tests/derive_impl_ui/missing_disambiguation_path.rs @@ -50,10 +50,10 @@ impl Animal for FourLeggedAnimal { } } -pub struct AcquaticMammal {} +pub struct AquaticMammal {} #[derive_impl(FourLeggedAnimal as)] -impl Animal for AcquaticMammal { +impl Animal for AquaticMammal { type Locomotion = (Swims, RunsOnFourLegs); type Environment = (Land, Sea); } diff --git a/substrate/frame/support/test/tests/derive_impl_ui/pass/basic_overriding.rs b/substrate/frame/support/test/tests/derive_impl_ui/pass/basic_overriding.rs index 37c0742f195..20744b8cba2 100644 --- a/substrate/frame/support/test/tests/derive_impl_ui/pass/basic_overriding.rs +++ b/substrate/frame/support/test/tests/derive_impl_ui/pass/basic_overriding.rs @@ -51,19 +51,19 @@ impl Animal for FourLeggedAnimal { } } -pub struct AcquaticMammal {} +pub struct AquaticMammal {} // without omitting the `as X` #[derive_impl(FourLeggedAnimal as Animal)] -impl Animal for AcquaticMammal { +impl Animal for AquaticMammal { type Locomotion = (Swims, RunsOnFourLegs); type Environment = (Land, Sea); } -assert_type_eq_all!(::Locomotion, (Swims, RunsOnFourLegs)); -assert_type_eq_all!(::Environment, (Land, Sea)); -assert_type_eq_all!(::Diet, Omnivore); -assert_type_eq_all!(::SleepingStrategy, Diurnal); +assert_type_eq_all!(::Locomotion, (Swims, RunsOnFourLegs)); +assert_type_eq_all!(::Environment, (Land, Sea)); +assert_type_eq_all!(::Diet, Omnivore); +assert_type_eq_all!(::SleepingStrategy, Diurnal); pub struct Lion {} diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs index 8e8079b183c..6c71b544426 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs @@ -82,7 +82,7 @@ fn module_error_outer_enum_expand_explicit() { // Check that all error types are propagated match RuntimeError::Example(pallet::Error::InsufficientProposersBalance) { - // Error passed implicitely to the pallet system. + // Error passed implicitly to the pallet system. RuntimeError::System(system) => match system { frame_system::Error::InvalidSpecName => (), frame_system::Error::SpecVersionNeedsToIncrease => (), diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs index 08b0b919e21..79828119742 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs @@ -62,11 +62,11 @@ frame_support::construct_runtime!( // Exclude part `Storage` in order not to check its metadata in tests. System: frame_system exclude_parts { Storage }, - // Pallet exposes `Error` implicitely. + // Pallet exposes `Error` implicitly. Example: common::outer_enums::pallet, Instance1Example: common::outer_enums::pallet::, - // Pallet exposes `Error` implicitely. + // Pallet exposes `Error` implicitly. Example2: common::outer_enums::pallet2, Instance1Example2: common::outer_enums::pallet2::, @@ -82,7 +82,7 @@ fn module_error_outer_enum_expand_implicit() { // Check that all error types are propagated match RuntimeError::Example(pallet::Error::InsufficientProposersBalance) { - // Error passed implicitely to the pallet system. + // Error passed implicitly to the pallet system. RuntimeError::System(system) => match system { frame_system::Error::InvalidSpecName => (), frame_system::Error::SpecVersionNeedsToIncrease => (), diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight3.rs b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight3.rs index f40d1040858..ddccd0b3e19 100644 --- a/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight3.rs +++ b/substrate/frame/support/test/tests/pallet_ui/pass/inherited_call_weight3.rs @@ -18,7 +18,7 @@ use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; -// If, for whatever reason, you dont to not use a `WeightInfo` trait - it will still work. +// If, for whatever reason, you don't to not use a `WeightInfo` trait - it will still work. struct Impl; impl Impl { diff --git a/substrate/frame/system/src/limits.rs b/substrate/frame/system/src/limits.rs index 5fd7a5af875..ab5a98a6b97 100644 --- a/substrate/frame/system/src/limits.rs +++ b/substrate/frame/system/src/limits.rs @@ -378,7 +378,7 @@ impl BlockWeightsBuilder { /// class, based on the allowance. /// /// This is to make sure that extrinsics don't stay forever in the pool, - /// because they could seamingly fit the block (since they are below `max_block`), + /// because they could seemingly fit the block (since they are below `max_block`), /// but the cost of calling `on_initialize` always prevents them from being included. pub fn avg_block_initialization(mut self, init_cost: Perbill) -> Self { self.init_cost = Some(init_cost); diff --git a/substrate/frame/system/src/offchain.rs b/substrate/frame/system/src/offchain.rs index a019cfd666e..a64b3261964 100644 --- a/substrate/frame/system/src/offchain.rs +++ b/substrate/frame/system/src/offchain.rs @@ -22,7 +22,7 @@ //! This module provides transaction related helpers to: //! - Submit a raw unsigned transaction //! - Submit an unsigned transaction with a signed payload -//! - Submit a signed transction. +//! - Submit a signed transaction. //! //! ## Usage //! @@ -384,7 +384,7 @@ where /// /// // runtime-specific public key /// type Public = MultiSigner: From; -/// type Signature = MulitSignature: From; +/// type Signature = MultiSignature: From; /// ``` // TODO [#5662] Potentially use `IsWrappedBy` types, or find some other way to make it easy to // obtain unwrapped crypto (and wrap it back). @@ -444,7 +444,7 @@ pub trait SigningTypes: crate::Config { /// A public key that is capable of identifying `AccountId`s. /// /// Usually that's either a raw crypto public key (e.g. `sr25519::Public`) or - /// an aggregate type for multiple crypto public keys, like `MulitSigner`. + /// an aggregate type for multiple crypto public keys, like `MultiSigner`. type Public: Clone + PartialEq + IdentifyAccount diff --git a/substrate/frame/tips/src/migrations/mod.rs b/substrate/frame/tips/src/migrations/mod.rs index 9cdd01c17fb..a7917bfce16 100644 --- a/substrate/frame/tips/src/migrations/mod.rs +++ b/substrate/frame/tips/src/migrations/mod.rs @@ -17,7 +17,7 @@ /// Version 4. /// -/// For backward compatability reasons, pallet-tips uses `Treasury` for storage module prefix +/// For backward compatibility reasons, pallet-tips uses `Treasury` for storage module prefix /// before calling this migration. After calling this migration, it will get replaced with /// own storage identifier. pub mod v4; diff --git a/substrate/frame/transaction-payment/src/tests.rs b/substrate/frame/transaction-payment/src/tests.rs index d3a1721ccb9..bc0efd2d64a 100644 --- a/substrate/frame/transaction-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/src/tests.rs @@ -384,7 +384,7 @@ fn query_call_info_and_fee_details_works() { adjusted_weight_fee: info .weight .min(BlockWeights::get().max_block) - .ref_time() as u64 * 2 * 3 / 2 /* weight * weight_fee * multipler */ + .ref_time() as u64 * 2 * 3 / 2 /* weight * weight_fee * multiplier */ }), tip: 0, }, diff --git a/substrate/frame/transaction-storage/README.md b/substrate/frame/transaction-storage/README.md index 1066968469d..b173c0a84d5 100644 --- a/substrate/frame/transaction-storage/README.md +++ b/substrate/frame/transaction-storage/README.md @@ -79,7 +79,7 @@ ipfs block get /ipfs/ > kitten.jpeg ``` To renew data and prevent it from being disposed after the storage period, use `transactionStorage.renew(block, index)` -where `block` is the block number of the previous store or renew transction, and index is the index of that transaction +where `block` is the block number of the previous store or renew transaction, and index is the index of that transaction in the block. diff --git a/substrate/frame/transaction-storage/src/lib.rs b/substrate/frame/transaction-storage/src/lib.rs index d32cfe169ce..398cb350c50 100644 --- a/substrate/frame/transaction-storage/src/lib.rs +++ b/substrate/frame/transaction-storage/src/lib.rs @@ -137,7 +137,7 @@ pub mod pallet { InvalidProof, /// Missing storage proof. MissingProof, - /// Unable to verify proof becasue state data is missing. + /// Unable to verify proof because state data is missing. MissingStateData, /// Double proof check in the block. DoubleCheck, diff --git a/substrate/frame/transaction-storage/src/tests.rs b/substrate/frame/transaction-storage/src/tests.rs index e17b3ca3beb..621f74804ec 100644 --- a/substrate/frame/transaction-storage/src/tests.rs +++ b/substrate/frame/transaction-storage/src/tests.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Tests for transction-storage pallet. +//! Tests for transaction-storage pallet. use super::{Pallet as TransactionStorage, *}; use crate::mock::*; @@ -53,8 +53,8 @@ fn discards_data() { }; run_to_block(11, proof_provider); assert!(Transactions::::get(1).is_some()); - let transctions = Transactions::::get(1).unwrap(); - assert_eq!(transctions.len(), 2); + let transactions = Transactions::::get(1).unwrap(); + assert_eq!(transactions.len(), 2); assert_eq!(ChunkCount::::get(1), 16); run_to_block(12, proof_provider); assert!(Transactions::::get(1).is_none()); diff --git a/substrate/frame/treasury/src/lib.rs b/substrate/frame/treasury/src/lib.rs index 5e429d3914b..d569ae406ea 100644 --- a/substrate/frame/treasury/src/lib.rs +++ b/substrate/frame/treasury/src/lib.rs @@ -621,7 +621,7 @@ pub mod pallet { with_context::>, _>(|v| { let context = v.or_default(); - // We group based on `max_amount`, to dinstinguish between different kind of + // We group based on `max_amount`, to distinguish between different kind of // origins. (assumes that all origins have different `max_amount`) // // Worst case is that we reject some "valid" request. @@ -1042,7 +1042,7 @@ impl, I: 'static> Pallet { /// ### Invariants of proposal storage items /// /// 1. [`ProposalCount`] >= Number of elements in [`Proposals`]. - /// 2. Each entry in [`Proposals`] should be saved under a key stricly less than current + /// 2. Each entry in [`Proposals`] should be saved under a key strictly less than current /// [`ProposalCount`]. /// 3. Each [`ProposalIndex`] contained in [`Approvals`] should exist in [`Proposals`]. /// Note, that this automatically implies [`Approvals`].count() <= [`Proposals`].count(). @@ -1078,7 +1078,7 @@ impl, I: 'static> Pallet { /// ## Invariants of spend storage items /// /// 1. [`SpendCount`] >= Number of elements in [`Spends`]. - /// 2. Each entry in [`Spends`] should be saved under a key stricly less than current + /// 2. Each entry in [`Spends`] should be saved under a key strictly less than current /// [`SpendCount`]. /// 3. For each spend entry contained in [`Spends`] we should have spend.expire_at /// > spend.valid_from. diff --git a/substrate/frame/uniques/src/tests.rs b/substrate/frame/uniques/src/tests.rs index 351dac09f7f..afd0352bf90 100644 --- a/substrate/frame/uniques/src/tests.rs +++ b/substrate/frame/uniques/src/tests.rs @@ -289,7 +289,7 @@ fn transfer_owner_should_work() { assert_eq!(Balances::reserved_balance(&2), 0); assert_eq!(Balances::reserved_balance(&3), 45); - // 2's acceptence from before is reset when it became owner, so it cannot be transfered + // 2's acceptance from before is reset when it became owner, so it cannot be transferred // without a fresh acceptance. assert_noop!( Uniques::transfer_ownership(RuntimeOrigin::signed(3), 0, 2), @@ -692,7 +692,7 @@ fn approved_account_gets_reset_after_transfer() { assert_ok!(Uniques::approve_transfer(RuntimeOrigin::signed(2), 0, 42, 3)); assert_ok!(Uniques::transfer(RuntimeOrigin::signed(2), 0, 42, 5)); - // this shouldn't work because we have just transfered the item to another account. + // this shouldn't work because we have just transferred the item to another account. assert_noop!( Uniques::transfer(RuntimeOrigin::signed(3), 0, 42, 4), Error::::NoPermission diff --git a/substrate/frame/utility/README.md b/substrate/frame/utility/README.md index 00fff76cd62..0a6769ae1c7 100644 --- a/substrate/frame/utility/README.md +++ b/substrate/frame/utility/README.md @@ -17,7 +17,7 @@ This module contains two basic pieces of functionality: need multiple distinct accounts (e.g. as controllers for many staking accounts), but where it's perfectly fine to have each of them controlled by the same underlying keypair. Derivative accounts are, for the purposes of proxy filtering considered exactly the same as - the oigin and are thus hampered with the origin's filters. + the origin and are thus hampered with the origin's filters. Since proxy filters are respected in all dispatches of this module, it should never need to be filtered by any proxy. diff --git a/substrate/frame/vesting/src/migrations.rs b/substrate/frame/vesting/src/migrations.rs index cac3c90b403..6fe82312b63 100644 --- a/substrate/frame/vesting/src/migrations.rs +++ b/substrate/frame/vesting/src/migrations.rs @@ -29,7 +29,7 @@ pub mod v1 { log::debug!( target: "runtime::vesting", - "migration: Vesting storage version v1 PRE migration checks succesful!" + "migration: Vesting storage version v1 PRE migration checks successful!" ); Ok(()) diff --git a/substrate/primitives/arithmetic/fuzzer/src/fixed_point.rs b/substrate/primitives/arithmetic/fuzzer/src/fixed_point.rs index e76dd1503e3..e2d31065635 100644 --- a/substrate/primitives/arithmetic/fuzzer/src/fixed_point.rs +++ b/substrate/primitives/arithmetic/fuzzer/src/fixed_point.rs @@ -66,7 +66,7 @@ fn main() { let c = FixedI64::saturating_from_integer(x.saturating_add(y)); assert_eq!(a.saturating_add(b), c); - // Check substraction. + // Check subtraction. let a = FixedI64::saturating_from_integer(x); let b = FixedI64::saturating_from_integer(y); let c = FixedI64::saturating_from_integer(x.saturating_sub(y)); diff --git a/substrate/primitives/arithmetic/src/fixed_point.rs b/substrate/primitives/arithmetic/src/fixed_point.rs index 736a900bde2..c4e9259c5fc 100644 --- a/substrate/primitives/arithmetic/src/fixed_point.rs +++ b/substrate/primitives/arithmetic/src/fixed_point.rs @@ -568,7 +568,7 @@ macro_rules! implement_fixed { let v = self.0 as u128; // Want x' = sqrt(x) where x = n/D and x' = n'/D (D is fixed) - // Our prefered way is: + // Our preferred way is: // sqrt(n/D) = sqrt(nD / D^2) = sqrt(nD)/sqrt(D^2) = sqrt(nD)/D // ergo n' = sqrt(nD) // but this requires nD to fit into our type. diff --git a/substrate/primitives/blockchain/src/backend.rs b/substrate/primitives/blockchain/src/backend.rs index 8208f9128e7..7a09865f858 100644 --- a/substrate/primitives/blockchain/src/backend.rs +++ b/substrate/primitives/blockchain/src/backend.rs @@ -187,7 +187,7 @@ pub trait Backend: /// a block with the given `base_hash`. /// /// The search space is always limited to blocks which are in the finalized - /// chain or descendents of it. + /// chain or descendants of it. /// /// Returns `Ok(None)` if `base_hash` is not found in search space. // TODO: document time complexity of this, see [#1444](https://github.com/paritytech/substrate/issues/1444) diff --git a/substrate/primitives/blockchain/src/error.rs b/substrate/primitives/blockchain/src/error.rs index 74a2ed3fba5..e8ac148d751 100644 --- a/substrate/primitives/blockchain/src/error.rs +++ b/substrate/primitives/blockchain/src/error.rs @@ -34,7 +34,7 @@ pub enum ApplyExtrinsicFailed { /// The transaction cannot be included into the current block. /// /// This doesn't necessary mean that the transaction itself is invalid, but it might be just - /// unappliable onto the current block. + /// unapplicable onto the current block. #[error("Extrinsic is not valid: {0:?}")] Validity(#[from] TransactionValidityError), diff --git a/substrate/primitives/blockchain/src/header_metadata.rs b/substrate/primitives/blockchain/src/header_metadata.rs index 08b3c9ab3df..ccd640c0567 100644 --- a/substrate/primitives/blockchain/src/header_metadata.rs +++ b/substrate/primitives/blockchain/src/header_metadata.rs @@ -178,7 +178,7 @@ pub struct TreeRoute { impl TreeRoute { /// Creates a new `TreeRoute`. /// - /// To preserve the structure safety invariats it is required that `pivot < route.len()`. + /// To preserve the structure safety invariants it is required that `pivot < route.len()`. pub fn new(route: Vec>, pivot: usize) -> Result { if pivot < route.len() { Ok(TreeRoute { route, pivot }) @@ -212,7 +212,7 @@ impl TreeRoute { ) } - /// Get a slice of enacted blocks (descendents of the common ancestor) + /// Get a slice of enacted blocks (descendants of the common ancestor) pub fn enacted(&self) -> &[HashAndNumber] { &self.route[self.pivot + 1..] } diff --git a/substrate/primitives/consensus/babe/src/lib.rs b/substrate/primitives/consensus/babe/src/lib.rs index 6eb75b270a0..ee07da6829f 100644 --- a/substrate/primitives/consensus/babe/src/lib.rs +++ b/substrate/primitives/consensus/babe/src/lib.rs @@ -266,7 +266,7 @@ impl Default for BabeEpochConfiguration { } /// Verifies the equivocation proof by making sure that: both headers have -/// different hashes, are targetting the same slot, and have valid signatures by +/// different hashes, are targeting the same slot, and have valid signatures by /// the same authority. pub fn check_equivocation_proof(proof: EquivocationProof) -> bool where @@ -298,7 +298,7 @@ where let first_pre_digest = find_pre_digest(&proof.first_header)?; let second_pre_digest = find_pre_digest(&proof.second_header)?; - // both headers must be targetting the same slot and it must + // both headers must be targeting the same slot and it must // be the same as the one in the proof. if proof.slot != first_pre_digest.slot() || first_pre_digest.slot() != second_pre_digest.slot() diff --git a/substrate/primitives/consensus/beefy/src/lib.rs b/substrate/primitives/consensus/beefy/src/lib.rs index b3f62ead736..70978ca559d 100644 --- a/substrate/primitives/consensus/beefy/src/lib.rs +++ b/substrate/primitives/consensus/beefy/src/lib.rs @@ -200,7 +200,7 @@ pub mod ecdsa_bls_crypto { fn verify(&self, signature: &::Signature, msg: &[u8]) -> bool { // We can not simply call // `EcdsaBlsPair::verify(signature.as_inner_ref(), msg, self.as_inner_ref())` - // because that invokes ECDSA default verification which perfoms Blake2b hash + // because that invokes ECDSA default verification which performs Blake2b hash // which we don't want. This is because ECDSA signatures are meant to be verified // on Ethereum network where Keccak hasher is significantly cheaper than Blake2b. // See Figure 3 of [OnSc21](https://www.scitepress.org/Papers/2021/106066/106066.pdf) diff --git a/substrate/primitives/consensus/beefy/src/mmr.rs b/substrate/primitives/consensus/beefy/src/mmr.rs index 74851ece7ac..0bc303d51c0 100644 --- a/substrate/primitives/consensus/beefy/src/mmr.rs +++ b/substrate/primitives/consensus/beefy/src/mmr.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! BEEFY + MMR utilties. +//! BEEFY + MMR utilities. //! //! While BEEFY can be used completely independently as an additional consensus gadget, //! it is designed around a main use case of bridging standalone networks together. @@ -77,7 +77,7 @@ pub struct MmrLeaf { /// /// Given that adding new struct elements in SCALE is backward compatible (i.e. old format can be /// still decoded, the new fields will simply be ignored). We expect the major version to be bumped -/// very rarely (hopefuly never). +/// very rarely (hopefully never). #[derive(Debug, Default, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] pub struct MmrLeafVersion(u8); impl MmrLeafVersion { diff --git a/substrate/primitives/consensus/beefy/src/payload.rs b/substrate/primitives/consensus/beefy/src/payload.rs index dff017b49e0..1a06e620e7a 100644 --- a/substrate/primitives/consensus/beefy/src/payload.rs +++ b/substrate/primitives/consensus/beefy/src/payload.rs @@ -43,7 +43,7 @@ pub mod known_payloads { pub struct Payload(Vec<(BeefyPayloadId, Vec)>); impl Payload { - /// Construct a new payload given an initial vallue + /// Construct a new payload given an initial value pub fn from_single_entry(id: BeefyPayloadId, value: Vec) -> Self { Self(vec![(id, value)]) } diff --git a/substrate/primitives/consensus/common/src/lib.rs b/substrate/primitives/consensus/common/src/lib.rs index 6505d005deb..01d3b7a24f9 100644 --- a/substrate/primitives/consensus/common/src/lib.rs +++ b/substrate/primitives/consensus/common/src/lib.rs @@ -182,7 +182,7 @@ pub trait Proposer { + Send + Unpin + 'static; - /// The supported proof recording by the implementator of this trait. See [`ProofRecording`] + /// The supported proof recording by the implementor of this trait. See [`ProofRecording`] /// for more information. type ProofRecording: self::ProofRecording + Send + Sync + 'static; /// The proof type used by [`Self::ProofRecording`]. diff --git a/substrate/primitives/consensus/sassafras/src/ticket.rs b/substrate/primitives/consensus/sassafras/src/ticket.rs index dc0a61990d3..345de99be28 100644 --- a/substrate/primitives/consensus/sassafras/src/ticket.rs +++ b/substrate/primitives/consensus/sassafras/src/ticket.rs @@ -115,7 +115,7 @@ mod tests { let threshold = ticket_id_threshold(redundancy, slots, attempts, validators); let threshold = threshold as f64 / TicketId::MAX as f64; - // We expect that the total number of tickets allowed to be submited + // We expect that the total number of tickets allowed to be submitted // is slots*redundancy let avt = ((attempts * validators) as f64 * threshold) as u32; assert_eq!(avt, slots * redundancy); diff --git a/substrate/primitives/consensus/sassafras/src/vrf.rs b/substrate/primitives/consensus/sassafras/src/vrf.rs index 815edb5eb66..537cff52ab6 100644 --- a/substrate/primitives/consensus/sassafras/src/vrf.rs +++ b/substrate/primitives/consensus/sassafras/src/vrf.rs @@ -101,7 +101,7 @@ pub fn make_ticket_id(input: &VrfInput, pre_output: &VrfPreOutput) -> TicketId { u128::from_le_bytes(bytes) } -/// Make revealed key seed from a given VRF input and pre-ouput. +/// Make revealed key seed from a given VRF input and pre-output. /// /// Input should have been obtained via [`revealed_key_input`]. /// Pre-output should have been obtained from the input directly using the vrf diff --git a/substrate/primitives/core/src/address_uri.rs b/substrate/primitives/core/src/address_uri.rs index 2e32d0cd86d..d44f3c0c87c 100644 --- a/substrate/primitives/core/src/address_uri.rs +++ b/substrate/primitives/core/src/address_uri.rs @@ -85,7 +85,7 @@ impl Error { /// Complementary error information. /// -/// Strucutre contains complementary information about parsing address URI string. +/// Structure contains complementary information about parsing address URI string. /// String contains a copy of an original URI string, 0-based integer indicates position of invalid /// character. #[derive(Debug, PartialEq, Eq, Clone)] diff --git a/substrate/primitives/core/src/bandersnatch.rs b/substrate/primitives/core/src/bandersnatch.rs index 42c8b293634..71ee2da5383 100644 --- a/substrate/primitives/core/src/bandersnatch.rs +++ b/substrate/primitives/core/src/bandersnatch.rs @@ -249,7 +249,7 @@ pub mod vrf { /// /// The `transcript` summarizes a set of messages which are defining a particular /// protocol by automating the Fiat-Shamir transform for challenge generation. - /// A good explaination of the topic can be found in Merlin [docs](https://merlin.cool/) + /// A good explanation of the topic can be found in Merlin [docs](https://merlin.cool/) /// /// The `inputs` is a sequence of [`VrfInput`]s which, during the signing procedure, are /// first transformed to [`VrfPreOutput`]s. Both inputs and pre-outputs are then appended to diff --git a/substrate/primitives/core/src/paired_crypto.rs b/substrate/primitives/core/src/paired_crypto.rs index 3901846b375..260e86b6ff9 100644 --- a/substrate/primitives/core/src/paired_crypto.rs +++ b/substrate/primitives/core/src/paired_crypto.rs @@ -73,7 +73,7 @@ pub mod ecdsa_bls377 { #[cfg(feature = "full_crypto")] impl Pair { - /// Hashes the `message` with the specified [`Hasher`] before signing sith the ECDSA secret + /// Hashes the `message` with the specified [`Hasher`] before signing with the ECDSA secret /// component. /// /// The hasher does not affect the BLS12-377 component. This generates BLS12-377 Signature diff --git a/substrate/primitives/inherents/src/client_side.rs b/substrate/primitives/inherents/src/client_side.rs index 27479de136f..3c299dfa4ee 100644 --- a/substrate/primitives/inherents/src/client_side.rs +++ b/substrate/primitives/inherents/src/client_side.rs @@ -23,7 +23,7 @@ use sp_runtime::traits::Block as BlockT; /// It is possible for the caller to provide custom arguments to the callee by setting the /// `ExtraArgs` generic parameter. /// -/// The crate already provides some convience implementations of this trait for +/// The crate already provides some convince implementations of this trait for /// `Box` and closures. So, it should not be required to implement /// this trait manually. #[async_trait::async_trait] diff --git a/substrate/primitives/io/Cargo.toml b/substrate/primitives/io/Cargo.toml index e47775d56d9..dddea4ffa23 100644 --- a/substrate/primitives/io/Cargo.toml +++ b/substrate/primitives/io/Cargo.toml @@ -85,7 +85,7 @@ disable_allocator = [] # This gives the caller direct programmatic access to the error message. # # When disabled the error message will only be printed out in the -# logs, with the caller receving a generic "wasm `unreachable` instruction executed" +# logs, with the caller receiving a generic "wasm `unreachable` instruction executed" # error message. # # This has no effect if both `disable_panic_handler` and `disable_oom` diff --git a/substrate/primitives/io/src/lib.rs b/substrate/primitives/io/src/lib.rs index 684854ea5c8..ec32b729033 100644 --- a/substrate/primitives/io/src/lib.rs +++ b/substrate/primitives/io/src/lib.rs @@ -1081,7 +1081,7 @@ pub trait Crypto { /// Register a `ecdsa` signature for batch verification. /// /// Batch verification must be enabled by calling [`start_batch_verify`]. - /// If batch verification is not enabled, the signature will be verified immediatley. + /// If batch verification is not enabled, the signature will be verified immediately. /// To get the result of the batch verification, [`finish_batch_verify`] /// needs to be called. /// @@ -1696,9 +1696,9 @@ mod tracing_setup { /// The PassingTracingSubscriber implements `tracing_core::Subscriber` /// and pushes the information across the runtime interface to the host - struct PassingTracingSubsciber; + struct PassingTracingSubscriber; - impl tracing_core::Subscriber for PassingTracingSubsciber { + impl tracing_core::Subscriber for PassingTracingSubscriber { fn enabled(&self, metadata: &Metadata<'_>) -> bool { wasm_tracing::enabled(Crossing(metadata.into())) } @@ -1731,7 +1731,7 @@ mod tracing_setup { /// set the global bridging subscriber once. pub fn init_tracing() { if TRACING_SET.load(Ordering::Relaxed) == false { - set_global_default(Dispatch::new(PassingTracingSubsciber {})) + set_global_default(Dispatch::new(PassingTracingSubscriber {})) .expect("We only ever call this once"); TRACING_SET.store(true, Ordering::Relaxed); } diff --git a/substrate/primitives/maybe-compressed-blob/Cargo.toml b/substrate/primitives/maybe-compressed-blob/Cargo.toml index fa5383d03b1..178c915ce83 100644 --- a/substrate/primitives/maybe-compressed-blob/Cargo.toml +++ b/substrate/primitives/maybe-compressed-blob/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true license = "Apache-2.0" homepage = "https://substrate.io" repository.workspace = true -description = "Handling of blobs, usually Wasm code, which may be compresed" +description = "Handling of blobs, usually Wasm code, which may be compressed" documentation = "https://docs.rs/sp-maybe-compressed-blob" readme = "README.md" diff --git a/substrate/primitives/metadata-ir/src/types.rs b/substrate/primitives/metadata-ir/src/types.rs index b107d20a8e2..b05f26ff55d 100644 --- a/substrate/primitives/metadata-ir/src/types.rs +++ b/substrate/primitives/metadata-ir/src/types.rs @@ -160,7 +160,7 @@ pub struct ExtrinsicMetadataIR { pub ty: T::Type, /// Extrinsic version. pub version: u8, - /// The type of the address that signes the extrinsic + /// The type of the address that signs the extrinsic pub address_ty: T::Type, /// The type of the outermost Call enum. pub call_ty: T::Type, diff --git a/substrate/primitives/npos-elections/src/pjr.rs b/substrate/primitives/npos-elections/src/pjr.rs index 08e40a014ea..6e3775199a2 100644 --- a/substrate/primitives/npos-elections/src/pjr.rs +++ b/substrate/primitives/npos-elections/src/pjr.rs @@ -261,7 +261,7 @@ fn prepare_pjr_input( } } - // Convert Suppports into a SupportMap + // Convert Supports into a SupportMap // // As a flat list, we're limited to linear search. That gives the production of `candidates`, // below, a complexity of `O(s*c)`, where `s == supports.len()` and `c == all_candidates.len()`. diff --git a/substrate/primitives/npos-elections/src/reduce.rs b/substrate/primitives/npos-elections/src/reduce.rs index c9ed493daf3..3fd291f88ab 100644 --- a/substrate/primitives/npos-elections/src/reduce.rs +++ b/substrate/primitives/npos-elections/src/reduce.rs @@ -393,7 +393,7 @@ fn reduce_all(assignments: &mut Vec>) -> u32 // voter_root_path.last().unwrap()); TODO: @kian // the common path must be non-void.. debug_assert!(common_count > 0); - // and smaller than btoh + // and smaller than both debug_assert!(common_count <= voter_root_path.len()); debug_assert!(common_count <= target_root_path.len()); diff --git a/substrate/primitives/runtime-interface/src/lib.rs b/substrate/primitives/runtime-interface/src/lib.rs index 8b0edf1ec81..f6ef27789b3 100644 --- a/substrate/primitives/runtime-interface/src/lib.rs +++ b/substrate/primitives/runtime-interface/src/lib.rs @@ -283,7 +283,7 @@ pub use sp_std; /// /// `key` holds the pointer and the length to the `data` slice. /// pub fn call(data: &[u8]) -> Vec { /// extern "C" { pub fn ext_call_version_2(key: u64); } -/// // Should call into extenal `ext_call_version_2(<[u8] as IntoFFIValue>::into_ffi_value(key))` +/// // Should call into external `ext_call_version_2(<[u8] as IntoFFIValue>::into_ffi_value(key))` /// // But this is too much to replicate in a doc test so here we just return a dummy vector. /// // Note that we jump into the latest version not marked as `register_only` (i.e. version 2). /// Vec::new() diff --git a/substrate/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs b/substrate/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs index 2f42e60504e..871a4922ce3 100644 --- a/substrate/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs +++ b/substrate/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs @@ -45,19 +45,19 @@ pub fn import_sp_io() { #[runtime_interface] pub trait TestApi { - fn test_versionning(&self, _data: u32) -> bool { + fn test_versioning(&self, _data: u32) -> bool { // should not be called unimplemented!() } } wasm_export_functions! { - fn test_versionning_works() { + fn test_versioning_works() { // old api allows only 42 and 50 - assert!(test_api::test_versionning(42)); - assert!(test_api::test_versionning(50)); + assert!(test_api::test_versioning(42)); + assert!(test_api::test_versioning(50)); - assert!(!test_api::test_versionning(142)); - assert!(!test_api::test_versionning(0)); + assert!(!test_api::test_versioning(142)); + assert!(!test_api::test_versioning(0)); } } diff --git a/substrate/primitives/runtime-interface/test-wasm/src/lib.rs b/substrate/primitives/runtime-interface/test-wasm/src/lib.rs index cf1ff3bca08..2b3fc728f6f 100644 --- a/substrate/primitives/runtime-interface/test-wasm/src/lib.rs +++ b/substrate/primitives/runtime-interface/test-wasm/src/lib.rs @@ -126,21 +126,21 @@ pub trait TestApi { val } - fn test_versionning(&self, data: u32) -> bool { + fn test_versioning(&self, data: u32) -> bool { data == 42 || data == 50 } #[version(2)] - fn test_versionning(&self, data: u32) -> bool { + fn test_versioning(&self, data: u32) -> bool { data == 42 } - fn test_versionning_register_only(&self, data: u32) -> bool { + fn test_versioning_register_only(&self, data: u32) -> bool { data == 80 } #[version(2, register_only)] - fn test_versionning_register_only(&self, data: u32) -> bool { + fn test_versioning_register_only(&self, data: u32) -> bool { data == 42 } @@ -282,21 +282,21 @@ wasm_export_functions! { assert_eq!(0, len); } - fn test_versionning_works() { + fn test_versioning_works() { // we fix new api to accept only 42 as a proper input // as opposed to sp-runtime-interface-test-wasm-deprecated::test_api::verify_input // which accepted 42 and 50. - assert!(test_api::test_versionning(42)); + assert!(test_api::test_versioning(42)); - assert!(!test_api::test_versionning(50)); - assert!(!test_api::test_versionning(102)); + assert!(!test_api::test_versioning(50)); + assert!(!test_api::test_versioning(102)); } - fn test_versionning_register_only_works() { + fn test_versioning_register_only_works() { // Ensure that we will import the version of the runtime interface function that // isn't tagged with `register_only`. - assert!(!test_api::test_versionning_register_only(42)); - assert!(test_api::test_versionning_register_only(80)); + assert!(!test_api::test_versioning_register_only(42)); + assert!(test_api::test_versioning_register_only(80)); } fn test_return_input_as_tuple() { diff --git a/substrate/primitives/runtime-interface/test/src/lib.rs b/substrate/primitives/runtime-interface/test/src/lib.rs index 215704a1121..05a955fbe3f 100644 --- a/substrate/primitives/runtime-interface/test/src/lib.rs +++ b/substrate/primitives/runtime-interface/test/src/lib.rs @@ -163,18 +163,18 @@ fn test_array_return_value_memory_is_freed() { } #[test] -fn test_versionining_with_new_host_works() { +fn test_versioning_with_new_host_works() { // We call to the new wasm binary with new host function. - call_wasm_method::(wasm_binary_unwrap(), "test_versionning_works"); + call_wasm_method::(wasm_binary_unwrap(), "test_versioning_works"); // we call to the old wasm binary with a new host functions // old versions of host functions should be called and test should be ok! - call_wasm_method::(wasm_binary_deprecated_unwrap(), "test_versionning_works"); + call_wasm_method::(wasm_binary_deprecated_unwrap(), "test_versioning_works"); } #[test] -fn test_versionining_register_only() { - call_wasm_method::(wasm_binary_unwrap(), "test_versionning_register_only_works"); +fn test_versioning_register_only() { + call_wasm_method::(wasm_binary_unwrap(), "test_versioning_register_only_works"); } fn run_test_in_another_process( diff --git a/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs b/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs index 5b54caf597b..8f6c0c6f650 100644 --- a/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/substrate/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -40,7 +40,7 @@ use sp_std::{fmt, prelude::*}; /// the decoding fails. const EXTRINSIC_FORMAT_VERSION: u8 = 4; -/// The `SingaturePayload` of `UncheckedExtrinsic`. +/// The `SignaturePayload` of `UncheckedExtrinsic`. type UncheckedSignaturePayload = (Address, Signature, Extra); /// An extrinsic right from the external world. This is unchecked and so can contain a signature. diff --git a/substrate/primitives/runtime/src/offchain/storage_lock.rs b/substrate/primitives/runtime/src/offchain/storage_lock.rs index 56d0eeae527..cfdaa954fe5 100644 --- a/substrate/primitives/runtime/src/offchain/storage_lock.rs +++ b/substrate/primitives/runtime/src/offchain/storage_lock.rs @@ -556,7 +556,7 @@ mod tests { let res = lock.try_lock(); assert_eq!(res.is_ok(), false); - // sleep again untill sleep_until > deadline + // sleep again until sleep_until > deadline offchain::sleep_until(offchain::timestamp().add(Duration::from_millis(200))); // the lock has expired, failed to extend it diff --git a/substrate/primitives/runtime/src/testing.rs b/substrate/primitives/runtime/src/testing.rs index 5f94c834a8f..b4aeda5a0e7 100644 --- a/substrate/primitives/runtime/src/testing.rs +++ b/substrate/primitives/runtime/src/testing.rs @@ -284,9 +284,9 @@ where } /// The signature payload of a `TestXt`. -type TxSingaturePayload = (u64, Extra); +type TxSignaturePayload = (u64, Extra); -impl SignaturePayload for TxSingaturePayload { +impl SignaturePayload for TxSignaturePayload { type SignatureAddress = u64; type Signature = (); type SignatureExtra = Extra; @@ -299,7 +299,7 @@ impl SignaturePayload for TxSingaturePayload { #[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] pub struct TestXt { /// Signature of the extrinsic. - pub signature: Option>, + pub signature: Option>, /// Call of the extrinsic. pub call: Call, } @@ -348,7 +348,7 @@ impl traits::Extrinsic for TestXt { type Call = Call; - type SignaturePayload = TxSingaturePayload; + type SignaturePayload = TxSignaturePayload; fn is_signed(&self) -> Option { Some(self.signature.is_some()) diff --git a/substrate/primitives/runtime/src/traits.rs b/substrate/primitives/runtime/src/traits.rs index 9ee41339d50..5a6c306dd2a 100644 --- a/substrate/primitives/runtime/src/traits.rs +++ b/substrate/primitives/runtime/src/traits.rs @@ -330,7 +330,7 @@ impl> Morph
for MorphInto { } } -/// Implementation of `TryMorph` which attmepts to convert between types using `TryInto`. +/// Implementation of `TryMorph` which attempts to convert between types using `TryInto`. pub struct TryMorphInto(sp_std::marker::PhantomData); impl> TryMorph for TryMorphInto { type Outcome = T; @@ -1449,7 +1449,7 @@ pub trait Dispatchable { /// to represent the dispatch class and weight. type Info; /// Additional information that is returned by `dispatch`. Can be used to supply the caller - /// with information about a `Dispatchable` that is ownly known post dispatch. + /// with information about a `Dispatchable` that is only known post dispatch. type PostInfo: Eq + PartialEq + Clone + Copy + Encode + Decode + Printable; /// Actually dispatch this call and return the result of it. fn dispatch(self, origin: Self::RuntimeOrigin) diff --git a/substrate/primitives/staking/src/offence.rs b/substrate/primitives/staking/src/offence.rs index 64aa4692eb5..30d96d0cbaf 100644 --- a/substrate/primitives/staking/src/offence.rs +++ b/substrate/primitives/staking/src/offence.rs @@ -117,7 +117,7 @@ pub trait Offence { /// Errors that may happen on offence reports. #[derive(PartialEq, sp_runtime::RuntimeDebug)] pub enum OffenceError { - /// The report has already been sumbmitted. + /// The report has already been submitted. DuplicateReport, /// Other error has happened. diff --git a/substrate/primitives/state-machine/src/ext.rs b/substrate/primitives/state-machine/src/ext.rs index 73110f55cba..9aa32bc866c 100644 --- a/substrate/primitives/state-machine/src/ext.rs +++ b/substrate/primitives/state-machine/src/ext.rs @@ -44,7 +44,7 @@ const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within const BENCHMARKING_FN: &str = "\ This is a special fn only for benchmarking where a database commit happens from the runtime. For that reason client started transactions before calling into runtime are not allowed. - Without client transactions the loop condition garantuees the success of the tx close."; + Without client transactions the loop condition guarantees the success of the tx close."; #[cfg(feature = "std")] fn guard() -> sp_panic_handler::AbortGuard { @@ -722,7 +722,7 @@ impl Encode for EncodeOpaqueValue { } } -/// Auxialiary structure for appending a value to a storage item. +/// Auxiliary structure for appending a value to a storage item. pub(crate) struct StorageAppend<'a>(&'a mut Vec); impl<'a> StorageAppend<'a> { diff --git a/substrate/primitives/state-machine/src/lib.rs b/substrate/primitives/state-machine/src/lib.rs index 200cebe68de..13087431d38 100644 --- a/substrate/primitives/state-machine/src/lib.rs +++ b/substrate/primitives/state-machine/src/lib.rs @@ -1451,7 +1451,7 @@ mod tests { enum Item { InitializationItem, DiscardedItem, - CommitedItem, + CommittedItem, } let key = b"events".to_vec(); @@ -1488,21 +1488,21 @@ mod tests { assert_eq!(ext.storage(key.as_slice()), Some(vec![Item::InitializationItem].encode())); - ext.storage_append(key.clone(), Item::CommitedItem.encode()); + ext.storage_append(key.clone(), Item::CommittedItem.encode()); assert_eq!( ext.storage(key.as_slice()), - Some(vec![Item::InitializationItem, Item::CommitedItem].encode()), + Some(vec![Item::InitializationItem, Item::CommittedItem].encode()), ); } overlay.start_transaction(); - // Then only initlaization item and second (committed) item should persist. + // Then only initialization item and second (committed) item should persist. { let ext = Ext::new(&mut overlay, backend, None); assert_eq!( ext.storage(key.as_slice()), - Some(vec![Item::InitializationItem, Item::CommitedItem].encode()), + Some(vec![Item::InitializationItem, Item::CommittedItem].encode()), ); } } @@ -1866,7 +1866,7 @@ mod tests { // a inner hashable node (&b"k"[..], Some(&long_vec[..])), // need to ensure this is not an inline node - // otherwhise we do not know what is accessed when + // otherwise we do not know what is accessed when // storing proof. (&b"key1"[..], Some(&vec![5u8; 32][..])), (&b"key2"[..], Some(&b"val3"[..])), diff --git a/substrate/primitives/state-machine/src/overlayed_changes/changeset.rs b/substrate/primitives/state-machine/src/overlayed_changes/changeset.rs index a25a5b81052..601bc2e2919 100644 --- a/substrate/primitives/state-machine/src/overlayed_changes/changeset.rs +++ b/substrate/primitives/state-machine/src/overlayed_changes/changeset.rs @@ -47,7 +47,7 @@ pub struct NoOpenTransaction; #[cfg_attr(test, derive(PartialEq))] pub struct AlreadyInRuntime; -/// Error when calling `exit_runtime` when not being in runtime exection mdde. +/// Error when calling `exit_runtime` when not being in runtime execution mode. #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] pub struct NotInRuntime; @@ -269,7 +269,7 @@ impl OverlayedMap { /// /// Panics: /// Panics if there are open transactions: `transaction_depth() > 0` - pub fn drain_commited(self) -> impl Iterator { + pub fn drain_committed(self) -> impl Iterator { assert!(self.transaction_depth() == 0, "Drain is not allowed with open transactions."); self.changes.into_iter().map(|(k, mut v)| (k, v.pop_transaction().value)) } @@ -281,7 +281,7 @@ impl OverlayedMap { self.dirty_keys.len() } - /// Call this before transfering control to the runtime. + /// Call this before transferring control to the runtime. /// /// This protects all existing transactions from being removed by the runtime. /// Calling this while already inside the runtime will return an error. @@ -471,7 +471,7 @@ mod test { } fn assert_drained_changes(is: OverlayedChangeSet, expected: Changes) { - let is = is.drain_commited().collect::>(); + let is = is.drain_committed().collect::>(); let expected = expected .iter() .map(|(k, v)| (k.to_vec(), v.0.map(From::from))) @@ -480,7 +480,7 @@ mod test { } fn assert_drained(is: OverlayedChangeSet, expected: Drained) { - let is = is.drain_commited().collect::>(); + let is = is.drain_committed().collect::>(); let expected = expected .iter() .map(|(k, v)| (k.to_vec(), v.map(From::from))) @@ -526,7 +526,7 @@ mod test { changeset.set(b"key0".to_vec(), Some(b"val0-rolled".to_vec()), Some(1000)); changeset.set(b"key5".to_vec(), Some(b"val5-rolled".to_vec()), None); - // changes contain all changes not only the commmited ones. + // changes contain all changes not only the committed ones. let all_changes: Changes = vec![ (b"key0", (Some(b"val0-rolled"), vec![1, 10, 1000])), (b"key1", (Some(b"val1"), vec![1])), @@ -807,7 +807,7 @@ mod test { fn drain_with_open_transaction_panics() { let mut changeset = OverlayedChangeSet::default(); changeset.start_transaction(); - let _ = changeset.drain_commited(); + let _ = changeset.drain_committed(); } #[test] diff --git a/substrate/primitives/state-machine/src/overlayed_changes/mod.rs b/substrate/primitives/state-machine/src/overlayed_changes/mod.rs index 039631e4a63..d6fc404e84f 100644 --- a/substrate/primitives/state-machine/src/overlayed_changes/mod.rs +++ b/substrate/primitives/state-machine/src/overlayed_changes/mod.rs @@ -480,7 +480,7 @@ impl OverlayedChanges { Ok(()) } - /// Call this before transfering control to the runtime. + /// Call this before transferring control to the runtime. /// /// This protects all existing transactions from being removed by the runtime. /// Calling this while already inside the runtime will return an error. @@ -575,10 +575,10 @@ impl OverlayedChanges { }; use core::mem::take; - let main_storage_changes = take(&mut self.top).drain_commited(); + let main_storage_changes = take(&mut self.top).drain_committed(); let child_storage_changes = take(&mut self.children) .into_iter() - .map(|(key, (val, info))| (key, (val.drain_commited(), info))); + .map(|(key, (val, info))| (key, (val.drain_committed(), info))); let offchain_storage_changes = self.offchain_drain_committed().collect(); @@ -809,7 +809,7 @@ pub struct OverlayedExtensions<'a> { #[cfg(feature = "std")] impl<'a> OverlayedExtensions<'a> { - /// Create a new instance of overalyed extensions from the given extensions. + /// Create a new instance of overlaid extensions from the given extensions. pub fn new(extensions: &'a mut Extensions) -> Self { Self { extensions: extensions diff --git a/substrate/primitives/state-machine/src/testing.rs b/substrate/primitives/state-machine/src/testing.rs index 0eb7b6d1118..e19ba95755c 100644 --- a/substrate/primitives/state-machine/src/testing.rs +++ b/substrate/primitives/state-machine/src/testing.rs @@ -417,7 +417,7 @@ mod tests { original_ext.backend.clone().into_storage(), ); - // Ensure all have the correct ref counrt + // Ensure all have the correct ref count assert!(original_ext.backend.backend_storage().keys().values().all(|r| *r == 2)); // Drain the raw storage and root. diff --git a/substrate/primitives/state-machine/src/trie_backend_essence.rs b/substrate/primitives/state-machine/src/trie_backend_essence.rs index 1824a77c370..a1f00579874 100644 --- a/substrate/primitives/state-machine/src/trie_backend_essence.rs +++ b/substrate/primitives/state-machine/src/trie_backend_essence.rs @@ -34,8 +34,8 @@ use parking_lot::RwLock; use sp_core::storage::{ChildInfo, ChildType, StateVersion}; use sp_trie::{ child_delta_trie_root, delta_trie_root, empty_child_trie_root, - read_child_trie_first_descedant_value, read_child_trie_hash, read_child_trie_value, - read_trie_first_descedant_value, read_trie_value, + read_child_trie_first_descendant_value, read_child_trie_hash, read_child_trie_value, + read_trie_first_descendant_value, read_trie_value, trie_types::{TrieDBBuilder, TrieError}, DBValue, KeySpacedDB, MerkleValue, NodeCodec, PrefixedMemoryDB, Trie, TrieCache, TrieDBRawIterator, TrieRecorder, TrieRecorderProvider, @@ -554,7 +554,7 @@ where let map_e = |e| format!("Trie lookup error: {}", e); self.with_recorder_and_cache(None, |recorder, cache| { - read_trie_first_descedant_value::, _>(self, &self.root, key, recorder, cache) + read_trie_first_descendant_value::, _>(self, &self.root, key, recorder, cache) .map_err(map_e) }) } @@ -570,7 +570,7 @@ where let map_e = |e| format!("Trie lookup error: {}", e); self.with_recorder_and_cache(Some(child_root), |recorder, cache| { - read_child_trie_first_descedant_value::, _>( + read_child_trie_first_descendant_value::, _>( child_info.keyspace(), self, &child_root, diff --git a/substrate/primitives/storage/src/lib.rs b/substrate/primitives/storage/src/lib.rs index b55cc8f2174..197994f5747 100644 --- a/substrate/primitives/storage/src/lib.rs +++ b/substrate/primitives/storage/src/lib.rs @@ -452,7 +452,7 @@ impl TryFrom for StateVersion { impl StateVersion { /// If defined, values in state of size bigger or equal /// to this threshold will use a separate trie node. - /// Otherwhise, value will be inlined in branch or leaf + /// Otherwise, value will be inlined in branch or leaf /// node. pub fn state_value_threshold(&self) -> Option { match self { diff --git a/substrate/primitives/tracing/src/lib.rs b/substrate/primitives/tracing/src/lib.rs index b8b99230db5..34ed088aed0 100644 --- a/substrate/primitives/tracing/src/lib.rs +++ b/substrate/primitives/tracing/src/lib.rs @@ -17,7 +17,7 @@ //! Substrate tracing primitives and macros. //! -//! To trace functions or invidual code in Substrate, this crate provides [`within_span`] +//! To trace functions or individual code in Substrate, this crate provides [`within_span`] //! and [`enter_span`]. See the individual docs for how to use these macros. //! //! Note that to allow traces from wasm execution environment there are @@ -70,7 +70,7 @@ pub use crate::types::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; /// directly as they yield nothing without the feature present. Instead you should use /// `enter_span!` and `within_span!` – which would strip away even any parameter conversion /// you do within the span-definition (and thus optimise your performance). For your -/// convineience you directly specify the `Level` and name of the span or use the full +/// convenience you directly specify the `Level` and name of the span or use the full /// feature set of `span!`/`span_*!` on it: /// /// # Example @@ -98,7 +98,7 @@ pub use crate::types::{WASM_NAME_KEY, WASM_TARGET_KEY, WASM_TRACE_IDENTIFIER}; /// This project only provides the macros and facilities to manage tracing /// it doesn't implement the tracing subscriber or backend directly – that is /// up to the developer integrating it into a specific environment. In native -/// this can and must be done through the regular `tracing`-facitilies, please +/// this can and must be done through the regular `tracing`-facilities, please /// see their documentation for details. /// /// On the wasm-side we've adopted a similar approach of having a global @@ -139,7 +139,7 @@ pub fn init_for_tests() { /// Runs given code within a tracing span, measuring it's execution time. /// /// If tracing is not enabled, the code is still executed. Pass in level and name or -/// use any valid `sp_tracing::Span`followe by `;` and the code to execute, +/// use any valid `sp_tracing::Span`followed by `;` and the code to execute, /// /// # Example /// diff --git a/substrate/primitives/tracing/src/types.rs b/substrate/primitives/tracing/src/types.rs index 3692a81e03c..46f38383d98 100644 --- a/substrate/primitives/tracing/src/types.rs +++ b/substrate/primitives/tracing/src/types.rs @@ -17,7 +17,7 @@ use alloc::{vec, vec::Vec}; use codec::{Decode, Encode}; -/// Types for wasm based tracing. Loosly inspired by `tracing-core` but +/// Types for wasm based tracing. Loosely inspired by `tracing-core` but /// optimised for the specific use case. use core::{fmt::Debug, format_args}; @@ -54,7 +54,7 @@ impl core::default::Default for WasmLevel { } } -/// A paramter value provided to the span/event +/// A parameter value provided to the span/event #[derive(Encode, Decode, Clone)] pub enum WasmValue { U8(u8), @@ -180,9 +180,9 @@ impl From for WasmValue { } } -/// The name of a field provided as the argument name when contstructing an +/// The name of a field provided as the argument name when constructing an /// `event!` or `span!`. -/// Generally generated automaticaly via `stringify` from an `'static &str`. +/// Generally generated automatically via `stringify` from an `'static &str`. /// Likely print-able. #[derive(Encode, Decode, Clone)] pub struct WasmFieldName(Vec); @@ -320,7 +320,7 @@ impl tracing_core::field::Visit for WasmValuesSet { self.0.push((field.name().into(), Some(WasmValue::from(value)))) } } -/// Metadata provides generic information about the specifc location of the +/// Metadata provides generic information about the specific location of the /// `span!` or `event!` call on the wasm-side. #[derive(Encode, Decode, Clone)] pub struct WasmMetadata { diff --git a/substrate/primitives/transaction-storage-proof/src/lib.rs b/substrate/primitives/transaction-storage-proof/src/lib.rs index 352f2aec26e..893b2e33bee 100644 --- a/substrate/primitives/transaction-storage-proof/src/lib.rs +++ b/substrate/primitives/transaction-storage-proof/src/lib.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Storage proof primitives. Constains types and basic code to extract storage +//! Storage proof primitives. Contains types and basic code to extract storage //! proofs for indexed transactions. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/substrate/primitives/trie/src/cache/mod.rs b/substrate/primitives/trie/src/cache/mod.rs index 01f08a78adc..32078169b50 100644 --- a/substrate/primitives/trie/src/cache/mod.rs +++ b/substrate/primitives/trie/src/cache/mod.rs @@ -323,7 +323,7 @@ type ValueAccessSet = /// /// This cache should be used per state instance created by the backend. One state instance is /// referring to the state of one block. It will cache all the accesses that are done to the state -/// which could not be fullfilled by the [`SharedTrieCache`]. These locally cached items are merged +/// which could not be fulfilled by the [`SharedTrieCache`]. These locally cached items are merged /// back to the shared trie cache when this instance is dropped. /// /// When using [`Self::as_trie_db_cache`] or [`Self::as_trie_db_mut_cache`], it will lock Mutexes. diff --git a/substrate/primitives/trie/src/lib.rs b/substrate/primitives/trie/src/lib.rs index 81b37a0c9a6..0ae448aff6e 100644 --- a/substrate/primitives/trie/src/lib.rs +++ b/substrate/primitives/trie/src/lib.rs @@ -326,7 +326,7 @@ pub fn read_trie_value( +pub fn read_trie_first_descendant_value( db: &DB, root: &TrieHash, key: &[u8], @@ -447,7 +447,7 @@ where /// Read the [`trie_db::MerkleValue`] of the node that is the closest descendant for /// the provided child key. -pub fn read_child_trie_first_descedant_value( +pub fn read_child_trie_first_descendant_value( keyspace: &[u8], db: &DB, root: &TrieHash, diff --git a/substrate/primitives/version/proc-macro/src/decl_runtime_version.rs b/substrate/primitives/version/proc-macro/src/decl_runtime_version.rs index 7ca2d9b71f6..3671d4aff6b 100644 --- a/substrate/primitives/version/proc-macro/src/decl_runtime_version.rs +++ b/substrate/primitives/version/proc-macro/src/decl_runtime_version.rs @@ -52,7 +52,7 @@ fn decl_runtime_version_impl_inner(item: ItemConst) -> Result { /// enable `std` feature even for `no_std` wasm runtime builds. /// /// One difference from the original definition is the `apis` field. Since we don't actually parse -/// `apis` from this macro it will always be emitteed as empty. An empty vector can be encoded as +/// `apis` from this macro it will always be emitted as empty. An empty vector can be encoded as /// a zero-byte, thus `u8` is sufficient here. #[derive(Encode)] struct RuntimeVersion { diff --git a/substrate/primitives/version/src/lib.rs b/substrate/primitives/version/src/lib.rs index 9b14a809ac1..789c507742f 100644 --- a/substrate/primitives/version/src/lib.rs +++ b/substrate/primitives/version/src/lib.rs @@ -327,7 +327,7 @@ impl RuntimeVersion { /// /// For runtime with core api version less than 4, /// V0 trie version will be applied to state. - /// Otherwhise, V1 trie version will be use. + /// Otherwise, V1 trie version will be use. pub fn state_version(&self) -> StateVersion { // If version > than 1, keep using latest version. self.state_version.try_into().unwrap_or(StateVersion::V1) diff --git a/substrate/utils/fork-tree/src/lib.rs b/substrate/utils/fork-tree/src/lib.rs index cd175166b9c..ff86467c85d 100644 --- a/substrate/utils/fork-tree/src/lib.rs +++ b/substrate/utils/fork-tree/src/lib.rs @@ -683,7 +683,7 @@ where node.data }); - // Retain only roots that are descendents of the finalized block (this + // Retain only roots that are descendants of the finalized block (this // happens if the node has been properly finalized) or that are // ancestors (or equal) to the finalized block (in this case the node // wasn't finalized earlier presumably because the predicate didn't @@ -1168,7 +1168,7 @@ mod test { Ok(Some(false)), ); - // finalizing "E" is not allowed since there are not finalized anchestors. + // finalizing "E" is not allowed since there are not finalized ancestors. assert_eq!( tree.finalizes_any_with_descendent_if(&"E", 15, &is_descendent_of, |c| c.effective == 10), @@ -1309,7 +1309,7 @@ mod test { fn map_works() { let (mut tree, _) = test_fork_tree(); - // Extend the single root fork-tree to also excercise the roots order during map. + // Extend the single root fork-tree to also exercise the roots order during map. let is_descendent_of = |_: &&str, _: &&str| -> Result { Ok(false) }; let is_root = tree.import("A1", 10, 1, &is_descendent_of).unwrap(); assert!(is_root); diff --git a/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs b/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs index c6ba2824016..80a5d27d8c2 100644 --- a/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs +++ b/substrate/utils/frame/benchmarking-cli/src/pallet/command.rs @@ -415,7 +415,7 @@ impl PalletCmd { .map_err(|e| { format!("Error executing and verifying runtime benchmark: {}", e) })?; - // Dont use these results since verification code will add overhead. + // Don't use these results since verification code will add overhead. let _batch = , String> as Decode>::decode( &mut &result[..], @@ -437,7 +437,7 @@ impl PalletCmd { &pallet.clone(), &extrinsic.clone(), &selected_components.clone(), - false, // dont run verification code for final values + false, // don't run verification code for final values self.repeat, ) .encode(), @@ -469,7 +469,7 @@ impl PalletCmd { &pallet.clone(), &extrinsic.clone(), &selected_components.clone(), - false, // dont run verification code for final values + false, // don't run verification code for final values self.repeat, ) .encode(), diff --git a/substrate/utils/frame/generate-bags/src/lib.rs b/substrate/utils/frame/generate-bags/src/lib.rs index 923017261a4..62485c442d3 100644 --- a/substrate/utils/frame/generate-bags/src/lib.rs +++ b/substrate/utils/frame/generate-bags/src/lib.rs @@ -183,7 +183,7 @@ pub fn generate_thresholds( total_issuance: u128, minimum_balance: u128, ) -> Result<(), std::io::Error> { - // ensure the file is accessable + // ensure the file is accessible if let Some(parent) = output.parent() { if !parent.exists() { std::fs::create_dir_all(parent)?; diff --git a/substrate/utils/frame/remote-externalities/src/lib.rs b/substrate/utils/frame/remote-externalities/src/lib.rs index c7399468da9..254d33deec8 100644 --- a/substrate/utils/frame/remote-externalities/src/lib.rs +++ b/substrate/utils/frame/remote-externalities/src/lib.rs @@ -762,7 +762,7 @@ where let mut sp = Spinner::with_timer(Spinners::Dots, "Inserting keys into DB...".into()); let start = Instant::now(); pending_ext.batch_insert(key_values.clone().into_iter().filter_map(|(k, v)| { - // Don't insert the child keys here, they need to be inserted seperately with all their + // Don't insert the child keys here, they need to be inserted separately with all their // data in the load_child_remote function. match is_default_child_storage_key(&k.0) { true => None, diff --git a/substrate/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs b/substrate/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs index f45258ea593..c0333bb7dac 100644 --- a/substrate/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs +++ b/substrate/utils/frame/rpc/state-trie-migration-rpc/src/lib.rs @@ -132,7 +132,7 @@ pub trait StateMigrationApi { /// Check current migration state. /// /// This call is performed locally without submitting any transactions. Thus executing this - /// won't change any state. Nonetheless it is a VERY costy call that should be + /// won't change any state. Nonetheless it is a VERY costly call that should be /// only exposed to trusted peers. #[method(name = "state_trieMigrationStatus")] fn call(&self, at: Option) -> RpcResult; diff --git a/substrate/utils/substrate-bip39/README.md b/substrate/utils/substrate-bip39/README.md index 368d18f406b..e7a80ca5f2c 100644 --- a/substrate/utils/substrate-bip39/README.md +++ b/substrate/utils/substrate-bip39/README.md @@ -21,12 +21,12 @@ to wallets providing their own dictionaries and checksum mechanism. Issues with to CSPRNG supplied dictionary phrases. 2. Providing own dictionaries felt into the _you ain't gonna need it_ anti-pattern category on day 1. Wallet providers - (be it hardware or software) typically want their products to be compatibile with other wallets so that users can + (be it hardware or software) typically want their products to be compatible with other wallets so that users can migrate to their product without having to migrate all their assets. To achieve the above phrases have to be precisely encoded in _The One True Canonical Encoding_, for which UTF-8 NFKD was chosen. This is largely irrelevant (and even ignored) for English phrases, as they encode to basically just ASCII in -virtualy every character encoding known to mankind, but immedietly becomes a problem for dictionaries that do use +virtually every character encoding known to mankind, but immediately becomes a problem for dictionaries that do use non-ASCII characters. Even if the right encoding is used and implemented correctly, there are still [other caveats present for some non-english dictionaries](https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md), such as normalizing spaces to a canonical form, or making some latin based characters equivalent to their base in @@ -34,8 +34,8 @@ dictionary lookups (eg. Spanish `ñ` and `n` are meant to be interchangeable). T headache, and opens doors for disagreements between buggy implementations, breaking compatibility. BIP39 does already provide a form of the mnemonic that is free from all of these issues: the entropy byte array. Since -veryfing the checksum requires that we recover the entropy from which the phrase was generated, no extra work is -actually needed here. Wallet implementators can encode the dictionaries in whatever encoding they find convenient (as +verifying the checksum requires that we recover the entropy from which the phrase was generated, no extra work is +actually needed here. Wallet implementors can encode the dictionaries in whatever encoding they find convenient (as long as they are the standard BIP39 dictionaries), no harm in using UTF-16 string primitives that Java and JavaScript provide. Since the dictionary is fixed and known, and the checksum is done on the entropy itself, the exact character encoding used becomes irrelevant, as are the precise codepoints and amount of whitespace around the words. It is thus diff --git a/substrate/utils/substrate-bip39/src/lib.rs b/substrate/utils/substrate-bip39/src/lib.rs index 3673d20faed..5b68bef0c39 100644 --- a/substrate/utils/substrate-bip39/src/lib.rs +++ b/substrate/utils/substrate-bip39/src/lib.rs @@ -43,7 +43,7 @@ pub enum Error { /// /// Any other length will return an error. /// -/// `password` is analog to BIP39 seed generation itself, with an empty string being defalt. +/// `password` is analog to BIP39 seed generation itself, with an empty string being default. pub fn mini_secret_from_entropy(entropy: &[u8], password: &str) -> Result { let seed = seed_from_entropy(entropy, password)?; Ok(MiniSecretKey::from_bytes(&seed[..32]).expect("Length is always correct; qed")) diff --git a/substrate/utils/wasm-builder/src/lib.rs b/substrate/utils/wasm-builder/src/lib.rs index 5cde48c0950..178e499e8f5 100644 --- a/substrate/utils/wasm-builder/src/lib.rs +++ b/substrate/utils/wasm-builder/src/lib.rs @@ -207,7 +207,7 @@ fn get_cargo_command(target: RuntimeTarget) -> CargoCommand { } else { // If no command before provided us with a cargo that supports our Substrate wasm env, we // try to search one with rustup. If that fails as well, we return the default cargo and let - // the prequisities check fail. + // the perquisites check fail. get_rustup_command(target).unwrap_or(default_cargo) } } diff --git a/substrate/utils/wasm-builder/src/wasm_project.rs b/substrate/utils/wasm-builder/src/wasm_project.rs index 13db9fce431..b58e6bfa36b 100644 --- a/substrate/utils/wasm-builder/src/wasm_project.rs +++ b/substrate/utils/wasm-builder/src/wasm_project.rs @@ -695,7 +695,7 @@ impl BuildConfiguration { /// "production". It would only contain the builtin profile where the custom profile /// inherits from. This is why we inspect the build path to learn which profile is used. /// - /// When not overriden by a env variable we always default to building wasm with the `Release` + /// When not overridden by a env variable we always default to building wasm with the `Release` /// profile even when the main build uses the debug build. This is because wasm built with the /// `Debug` profile is too slow for normal development activities and almost never intended. /// @@ -704,9 +704,9 @@ impl BuildConfiguration { /// /// # Note /// - /// Can be overriden by setting [`crate::WASM_BUILD_TYPE_ENV`]. + /// Can be overridden by setting [`crate::WASM_BUILD_TYPE_ENV`]. fn detect(target: RuntimeTarget, wasm_project: &Path) -> Self { - let (name, overriden) = if let Ok(name) = env::var(crate::WASM_BUILD_TYPE_ENV) { + let (name, overridden) = if let Ok(name) = env::var(crate::WASM_BUILD_TYPE_ENV) { (name, true) } else { // First go backwards to the beginning of the target directory. @@ -731,14 +731,14 @@ impl BuildConfiguration { (name, false) }; let outer_build_profile = Profile::iter().find(|p| p.directory() == name); - let blob_build_profile = match (outer_build_profile.clone(), overriden) { - // When not overriden by a env variable we default to using the `Release` profile + let blob_build_profile = match (outer_build_profile.clone(), overridden) { + // When not overridden by a env variable we default to using the `Release` profile // for the wasm build even when the main build uses the debug build. This // is because the `Debug` profile is too slow for normal development activities. (Some(Profile::Debug), false) => Profile::Release, - // For any other profile or when overriden we take it at face value. + // For any other profile or when overridden we take it at face value. (Some(profile), _) => profile, - // For non overriden unknown profiles we fall back to `Release`. + // For non overridden unknown profiles we fall back to `Release`. // This allows us to continue building when a custom profile is used for the // main builds cargo. When explicitly passing a profile via env variable we are // not doing a fallback. diff --git a/templates/minimal/node/Cargo.toml b/templates/minimal/node/Cargo.toml index 65aa1e20752..41d9708ea60 100644 --- a/templates/minimal/node/Cargo.toml +++ b/templates/minimal/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal-template-node" -description = "A miniaml Substrate-based Substrate node, ready for hacking." +description = "A minimal Substrate-based Substrate node, ready for hacking." version = "0.0.0" license = "MIT-0" authors.workspace = true diff --git a/templates/minimal/runtime/Cargo.toml b/templates/minimal/runtime/Cargo.toml index 20ffb706eb4..a99a1e43f85 100644 --- a/templates/minimal/runtime/Cargo.toml +++ b/templates/minimal/runtime/Cargo.toml @@ -29,7 +29,7 @@ pallet-timestamp = { path = "../../../substrate/frame/timestamp", default-featur pallet-transaction-payment = { path = "../../../substrate/frame/transaction-payment", default-features = false } pallet-transaction-payment-rpc-runtime-api = { path = "../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false } -# genesis builder that allows us to interacto with runtime genesis config +# genesis builder that allows us to interact with runtime genesis config sp-genesis-builder = { path = "../../../substrate/primitives/genesis-builder", default-features = false } # local pallet templates -- GitLab From fd79b3b08a9bd8f57cd6183b84fd34705e83a7a0 Mon Sep 17 00:00:00 2001 From: Andrei Eres Date: Tue, 26 Mar 2024 16:51:47 +0100 Subject: [PATCH 178/188] [subsystem-benchmarks] Save results to json (#3829) Here we add the ability to save subsystem benchmark results in JSON format to display them as graphs To draw graphs, CI team will use [github-action-benchmark](https://github.com/benchmark-action/github-action-benchmark). Since we are using custom benchmarks, we need to prepare [a specific data type](https://github.com/benchmark-action/github-action-benchmark?tab=readme-ov-file#examples): ``` [ { "name": "CPU Load", "unit": "Percent", "value": 50 } ] ``` Then we'll get graphs like this: ![example](https://raw.githubusercontent.com/rhysd/ss/master/github-action-benchmark/main.png) [A live page with graphs](https://benchmark-action.github.io/github-action-benchmark/dev/bench/) --------- Co-authored-by: ordian --- Cargo.lock | 1 + ...ilability-distribution-regression-bench.rs | 7 ++ .../availability-recovery-regression-bench.rs | 7 ++ polkadot/node/subsystem-bench/Cargo.toml | 1 + .../subsystem-bench/src/lib/environment.rs | 2 +- polkadot/node/subsystem-bench/src/lib/lib.rs | 1 + .../node/subsystem-bench/src/lib/usage.rs | 28 +++++++ .../node/subsystem-bench/src/lib/utils.rs | 75 +++++-------------- 8 files changed, 66 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 074b657e767..9e52bfcf9a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13644,6 +13644,7 @@ dependencies = [ "sc-service", "schnorrkel 0.11.4", "serde", + "serde_json", "serde_yaml", "sha1", "sp-application-crypto", diff --git a/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs b/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs index 019eb122208..c33674a8f2f 100644 --- a/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs +++ b/polkadot/node/network/availability-distribution/benches/availability-distribution-regression-bench.rs @@ -27,6 +27,7 @@ use polkadot_subsystem_bench::{ availability::{benchmark_availability_write, prepare_test, TestState}, configuration::TestConfiguration, usage::BenchmarkUsage, + utils::save_to_file, }; use std::io::Write; @@ -60,7 +61,13 @@ fn main() -> Result<(), String> { }) .collect(); println!("\rDone!{}", " ".repeat(BENCH_COUNT)); + let average_usage = BenchmarkUsage::average(&usages); + save_to_file( + "charts/availability-distribution-regression-bench.json", + average_usage.to_chart_json().map_err(|e| e.to_string())?, + ) + .map_err(|e| e.to_string())?; println!("{}", average_usage); // We expect no variance for received and sent diff --git a/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs b/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs index 5e8b81be82d..46a38516898 100644 --- a/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs +++ b/polkadot/node/network/availability-recovery/benches/availability-recovery-regression-bench.rs @@ -28,6 +28,7 @@ use polkadot_subsystem_bench::{ }, configuration::TestConfiguration, usage::BenchmarkUsage, + utils::save_to_file, }; use std::io::Write; @@ -58,7 +59,13 @@ fn main() -> Result<(), String> { }) .collect(); println!("\rDone!{}", " ".repeat(BENCH_COUNT)); + let average_usage = BenchmarkUsage::average(&usages); + save_to_file( + "charts/availability-recovery-regression-bench.json", + average_usage.to_chart_json().map_err(|e| e.to_string())?, + ) + .map_err(|e| e.to_string())?; println!("{}", average_usage); // We expect no variance for received and sent diff --git a/polkadot/node/subsystem-bench/Cargo.toml b/polkadot/node/subsystem-bench/Cargo.toml index 05907e428f9..b494f05180d 100644 --- a/polkadot/node/subsystem-bench/Cargo.toml +++ b/polkadot/node/subsystem-bench/Cargo.toml @@ -71,6 +71,7 @@ prometheus_endpoint = { package = "substrate-prometheus-endpoint", path = "../.. prometheus = { version = "0.13.0", default-features = false } serde = { workspace = true, default-features = true } serde_yaml = { workspace = true } +serde_json = { workspace = true } polkadot-node-core-approval-voting = { path = "../core/approval-voting" } polkadot-approval-distribution = { path = "../network/approval-distribution" } diff --git a/polkadot/node/subsystem-bench/src/lib/environment.rs b/polkadot/node/subsystem-bench/src/lib/environment.rs index 2d80d75a14a..42955d03022 100644 --- a/polkadot/node/subsystem-bench/src/lib/environment.rs +++ b/polkadot/node/subsystem-bench/src/lib/environment.rs @@ -404,7 +404,7 @@ impl TestEnvironment { let total_cpu = test_env_cpu_metrics.sum_by("substrate_tasks_polling_duration_sum"); usage.push(ResourceUsage { - resource_name: "Test environment".to_string(), + resource_name: "test-environment".to_string(), total: total_cpu, per_block: total_cpu / num_blocks, }); diff --git a/polkadot/node/subsystem-bench/src/lib/lib.rs b/polkadot/node/subsystem-bench/src/lib/lib.rs index d06f2822a89..ef2724abc98 100644 --- a/polkadot/node/subsystem-bench/src/lib/lib.rs +++ b/polkadot/node/subsystem-bench/src/lib/lib.rs @@ -26,3 +26,4 @@ pub(crate) mod keyring; pub(crate) mod mock; pub(crate) mod network; pub mod usage; +pub mod utils; diff --git a/polkadot/node/subsystem-bench/src/lib/usage.rs b/polkadot/node/subsystem-bench/src/lib/usage.rs index 7172969a8f9..59296746ec3 100644 --- a/polkadot/node/subsystem-bench/src/lib/usage.rs +++ b/polkadot/node/subsystem-bench/src/lib/usage.rs @@ -82,6 +82,27 @@ impl BenchmarkUsage { _ => None, } } + + // Prepares a json string for a graph representation + // See: https://github.com/benchmark-action/github-action-benchmark?tab=readme-ov-file#examples + pub fn to_chart_json(&self) -> color_eyre::eyre::Result { + let chart = self + .network_usage + .iter() + .map(|v| ChartItem { + name: v.resource_name.clone(), + unit: "KiB".to_string(), + value: v.per_block, + }) + .chain(self.cpu_usage.iter().map(|v| ChartItem { + name: v.resource_name.clone(), + unit: "seconds".to_string(), + value: v.per_block, + })) + .collect::>(); + + Ok(serde_json::to_string(&chart)?) + } } fn check_usage( @@ -151,3 +172,10 @@ impl ResourceUsage { } type ResourceUsageCheck<'a> = (&'a str, f64, f64); + +#[derive(Debug, Serialize)] +pub struct ChartItem { + pub name: String, + pub unit: String, + pub value: f64, +} diff --git a/polkadot/node/subsystem-bench/src/lib/utils.rs b/polkadot/node/subsystem-bench/src/lib/utils.rs index cd206d8f322..b3cd3a88b6c 100644 --- a/polkadot/node/subsystem-bench/src/lib/utils.rs +++ b/polkadot/node/subsystem-bench/src/lib/utils.rs @@ -16,61 +16,26 @@ //! Test utils -use crate::usage::BenchmarkUsage; -use std::io::{stdout, Write}; - -pub struct WarmUpOptions<'a> { - /// The maximum number of runs considered for warming up. - pub warm_up: usize, - /// The number of runs considered for benchmarking. - pub bench: usize, - /// The difference in CPU usage between runs considered as normal - pub precision: f64, - /// The subsystems whose CPU usage is checked during warm-up cycles - pub subsystems: &'a [&'a str], -} - -impl<'a> WarmUpOptions<'a> { - pub fn new(subsystems: &'a [&'a str]) -> Self { - Self { warm_up: 100, bench: 3, precision: 0.02, subsystems } - } -} - -pub fn warm_up_and_benchmark( - options: WarmUpOptions, - run: impl Fn() -> BenchmarkUsage, -) -> Result { - println!("Warming up..."); - let mut usages = Vec::with_capacity(options.bench); - - for n in 1..=options.warm_up { - let curr = run(); - if let Some(prev) = usages.last() { - let diffs = options - .subsystems - .iter() - .map(|&v| { - curr.cpu_usage_diff(prev, v) - .ok_or(format!("{} not found in benchmark {:?}", v, prev)) - }) - .collect::, String>>()?; - if !diffs.iter().all(|&v| v < options.precision) { - usages.clear(); - } - } - usages.push(curr); - print!("\r{}%", n * 100 / options.warm_up); - if usages.len() == options.bench { - println!("\rTook {} runs to warm up", n.saturating_sub(options.bench)); - break; - } - stdout().flush().unwrap(); - } - - if usages.len() != options.bench { - println!("Didn't warm up after {} runs", options.warm_up); - return Err("Can't warm up".to_string()) +use std::{fs::File, io::Write}; + +// Saves a given string to a file +pub fn save_to_file(path: &str, value: String) -> color_eyre::eyre::Result<()> { + let output = std::process::Command::new(env!("CARGO")) + .arg("locate-project") + .arg("--workspace") + .arg("--message-format=plain") + .output() + .unwrap() + .stdout; + let workspace_dir = std::path::Path::new(std::str::from_utf8(&output).unwrap().trim()) + .parent() + .unwrap(); + let path = workspace_dir.join(path); + if let Some(dir) = path.parent() { + std::fs::create_dir_all(dir)?; } + let mut file = File::create(path)?; + file.write_all(value.as_bytes())?; - Ok(BenchmarkUsage::average(&usages)) + Ok(()) } -- GitLab From 90234543f3039ce29bf0c9badfc6ec2037308eea Mon Sep 17 00:00:00 2001 From: Tsvetomir Dimitrov Date: Tue, 26 Mar 2024 17:54:24 +0200 Subject: [PATCH 179/188] Migrate parachain swaps to Coretime (#3714) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR notifies broker pallet for any parachain slot swaps performed on the relay chain. This is achieved by registering an `OnSwap` for the the `coretime` pallet. The hook sends XCM message to the broker chain and invokes a new extrinsic `swap_leases` which updates `Leases` storage item (which keeps the legacy parachain leases). I made two assumptions in this PR: 1. [`Leases`](https://github.com/paritytech/polkadot-sdk/blob/4987d7982461e2e5ffe219cdf71ec697284cea7c/substrate/frame/broker/src/lib.rs#L120) in `broker` pallet and [`Leases`](https://github.com/paritytech/polkadot-sdk/blob/4987d7982461e2e5ffe219cdf71ec697284cea7c/polkadot/runtime/common/src/slots/mod.rs#L118) in `slots` pallet are in sync. 2. `swap_leases` extrinsic from `broker` pallet can be triggered only by root or by the XCM message from the relay chain. If not - the extrinsic will generate an error and do nothing. As a side effect from the changes `OnSwap` trait is moved from runtime/common/traits.rs to runtime/parachains. Otherwise it is not accessible from `broker` pallet. Closes https://github.com/paritytech/polkadot-sdk/issues/3552 TODOs: - [x] Weights - [x] Tests --------- Co-authored-by: command-bot <> Co-authored-by: eskimor Co-authored-by: Bastian Köcher --- .../src/weights/pallet_broker.rs | 158 ++++---- .../src/weights/pallet_broker.rs | 160 ++++---- .../runtime/parachains/src/coretime/mod.rs | 20 + polkadot/runtime/rococo/src/lib.rs | 12 +- polkadot/runtime/westend/src/lib.rs | 12 +- prdoc/pr_3714.prdoc | 10 + substrate/frame/broker/src/benchmarking.rs | 17 + .../frame/broker/src/dispatchable_impls.rs | 18 + substrate/frame/broker/src/lib.rs | 8 + substrate/frame/broker/src/weights.rs | 368 ++++++++++-------- 10 files changed, 461 insertions(+), 322 deletions(-) create mode 100644 prdoc/pr_3714.prdoc diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs index 2d30ddc612c..89b1c4c8663 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_broker.rs @@ -16,26 +16,24 @@ //! Autogenerated weights for `pallet_broker` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=coretime-rococo-dev -// --wasm-execution=compiled -// --pallet=pallet_broker -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_broker +// --chain=coretime-rococo-dev // --header=./cumulus/file_header.txt // --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/ @@ -56,8 +54,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_462_000 picoseconds. - Weight::from_parts(2_552_000, 0) + // Minimum execution time: 1_918_000 picoseconds. + Weight::from_parts(2_092_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -67,8 +65,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `10888` // Estimated: `13506` - // Minimum execution time: 25_494_000 picoseconds. - Weight::from_parts(26_063_000, 0) + // Minimum execution time: 21_943_000 picoseconds. + Weight::from_parts(22_570_000, 0) .saturating_add(Weight::from_parts(0, 13506)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -79,8 +77,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `12090` // Estimated: `13506` - // Minimum execution time: 22_299_000 picoseconds. - Weight::from_parts(22_911_000, 0) + // Minimum execution time: 20_923_000 picoseconds. + Weight::from_parts(21_354_000, 0) .saturating_add(Weight::from_parts(0, 13506)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -95,8 +93,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `466` // Estimated: `1951` - // Minimum execution time: 11_590_000 picoseconds. - Weight::from_parts(12_007_000, 0) + // Minimum execution time: 10_687_000 picoseconds. + Weight::from_parts(11_409_000, 0) .saturating_add(Weight::from_parts(0, 1951)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -124,11 +122,11 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `12567` // Estimated: `14052` - // Minimum execution time: 120_928_000 picoseconds. - Weight::from_parts(124_947_252, 0) + // Minimum execution time: 111_288_000 picoseconds. + Weight::from_parts(117_804_282, 0) .saturating_add(Weight::from_parts(0, 14052)) - // Standard Error: 435 - .saturating_add(Weight::from_parts(1_246, 0).saturating_mul(n.into())) + // Standard Error: 391 + .saturating_add(Weight::from_parts(1_243, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(66)) } @@ -144,8 +142,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `316` // Estimated: `3593` - // Minimum execution time: 32_826_000 picoseconds. - Weight::from_parts(33_889_000, 0) + // Minimum execution time: 33_006_000 picoseconds. + Weight::from_parts(34_256_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -166,8 +164,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `434` // Estimated: `4698` - // Minimum execution time: 57_362_000 picoseconds. - Weight::from_parts(58_994_000, 0) + // Minimum execution time: 61_473_000 picoseconds. + Weight::from_parts(66_476_000, 0) .saturating_add(Weight::from_parts(0, 4698)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -178,8 +176,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `357` // Estimated: `3550` - // Minimum execution time: 13_982_000 picoseconds. - Weight::from_parts(14_447_000, 0) + // Minimum execution time: 13_771_000 picoseconds. + Weight::from_parts(14_374_000, 0) .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -190,8 +188,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `357` // Estimated: `3550` - // Minimum execution time: 15_070_000 picoseconds. - Weight::from_parts(15_735_000, 0) + // Minimum execution time: 15_162_000 picoseconds. + Weight::from_parts(15_742_000, 0) .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -202,8 +200,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `357` // Estimated: `3550` - // Minimum execution time: 16_527_000 picoseconds. - Weight::from_parts(16_894_000, 0) + // Minimum execution time: 16_196_000 picoseconds. + Weight::from_parts(16_796_000, 0) .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(3)) @@ -220,8 +218,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `936` // Estimated: `4681` - // Minimum execution time: 25_493_000 picoseconds. - Weight::from_parts(26_091_000, 0) + // Minimum execution time: 25_653_000 picoseconds. + Weight::from_parts(27_006_000, 0) .saturating_add(Weight::from_parts(0, 4681)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) @@ -240,8 +238,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `1002` // Estimated: `5996` - // Minimum execution time: 31_498_000 picoseconds. - Weight::from_parts(32_560_000, 0) + // Minimum execution time: 31_114_000 picoseconds. + Weight::from_parts(32_235_000, 0) .saturating_add(Weight::from_parts(0, 5996)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) @@ -257,11 +255,11 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `652` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 57_183_000 picoseconds. - Weight::from_parts(58_024_898, 0) + // Minimum execution time: 57_280_000 picoseconds. + Weight::from_parts(58_127_480, 0) .saturating_add(Weight::from_parts(0, 6196)) - // Standard Error: 35_831 - .saturating_add(Weight::from_parts(1_384_446, 0).saturating_mul(m.into())) + // Standard Error: 41_670 + .saturating_add(Weight::from_parts(1_203_066, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().writes(5)) @@ -283,8 +281,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `215` // Estimated: `3680` - // Minimum execution time: 59_762_000 picoseconds. - Weight::from_parts(61_114_000, 0) + // Minimum execution time: 59_968_000 picoseconds. + Weight::from_parts(62_315_000, 0) .saturating_add(Weight::from_parts(0, 3680)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) @@ -297,8 +295,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `465` // Estimated: `3550` - // Minimum execution time: 41_473_000 picoseconds. - Weight::from_parts(44_155_000, 0) + // Minimum execution time: 50_887_000 picoseconds. + Weight::from_parts(57_366_000, 0) .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -313,8 +311,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `463` // Estimated: `3533` - // Minimum execution time: 56_672_000 picoseconds. - Weight::from_parts(58_086_000, 0) + // Minimum execution time: 84_472_000 picoseconds. + Weight::from_parts(96_536_000, 0) .saturating_add(Weight::from_parts(0, 3533)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -331,8 +329,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `857` // Estimated: `3593` - // Minimum execution time: 64_460_000 picoseconds. - Weight::from_parts(65_894_000, 0) + // Minimum execution time: 96_371_000 picoseconds. + Weight::from_parts(104_659_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(1)) @@ -345,8 +343,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `957` // Estimated: `4698` - // Minimum execution time: 37_447_000 picoseconds. - Weight::from_parts(42_318_000, 0) + // Minimum execution time: 51_741_000 picoseconds. + Weight::from_parts(54_461_000, 0) .saturating_add(Weight::from_parts(0, 4698)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -366,8 +364,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 21_219_000 picoseconds. - Weight::from_parts(22_084_648, 0) + // Minimum execution time: 19_901_000 picoseconds. + Weight::from_parts(21_028_116, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -379,11 +377,11 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `266` // Estimated: `1487` - // Minimum execution time: 5_792_000 picoseconds. - Weight::from_parts(6_358_588, 0) + // Minimum execution time: 5_987_000 picoseconds. + Weight::from_parts(6_412_478, 0) .saturating_add(Weight::from_parts(0, 1487)) - // Standard Error: 20 - .saturating_add(Weight::from_parts(26, 0).saturating_mul(n.into())) + // Standard Error: 16 + .saturating_add(Weight::from_parts(47, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -397,8 +395,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `447` // Estimated: `6196` - // Minimum execution time: 38_690_000 picoseconds. - Weight::from_parts(39_706_000, 0) + // Minimum execution time: 38_623_000 picoseconds. + Weight::from_parts(39_773_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -414,15 +412,13 @@ impl pallet_broker::WeightInfo for WeightInfo { /// Storage: `Broker::Workplan` (r:0 w:60) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn rotate_sale(n: u32, ) -> Weight { + fn rotate_sale(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `12514` // Estimated: `13506` - // Minimum execution time: 93_531_000 picoseconds. - Weight::from_parts(95_836_318, 0) + // Minimum execution time: 97_074_000 picoseconds. + Weight::from_parts(101_247_740, 0) .saturating_add(Weight::from_parts(0, 13506)) - // Standard Error: 113 - .saturating_add(Weight::from_parts(329, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(65)) } @@ -434,8 +430,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3493` - // Minimum execution time: 6_506_000 picoseconds. - Weight::from_parts(6_783_000, 0) + // Minimum execution time: 6_317_000 picoseconds. + Weight::from_parts(6_521_000, 0) .saturating_add(Weight::from_parts(0, 3493)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -458,8 +454,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `1321` // Estimated: `4786` - // Minimum execution time: 31_927_000 picoseconds. - Weight::from_parts(32_748_000, 0) + // Minimum execution time: 32_575_000 picoseconds. + Weight::from_parts(33_299_000, 0) .saturating_add(Weight::from_parts(0, 4786)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -478,8 +474,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 15_682_000 picoseconds. - Weight::from_parts(16_012_000, 0) + // Minimum execution time: 15_256_000 picoseconds. + Weight::from_parts(15_927_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -490,8 +486,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_147_000 picoseconds. - Weight::from_parts(2_281_000, 0) + // Minimum execution time: 1_783_000 picoseconds. + Weight::from_parts(1_904_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -509,10 +505,22 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `398` // Estimated: `3863` - // Minimum execution time: 12_015_000 picoseconds. - Weight::from_parts(12_619_000, 0) + // Minimum execution time: 12_307_000 picoseconds. + Weight::from_parts(12_967_000, 0) .saturating_add(Weight::from_parts(0, 3863)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(401), added: 896, mode: `MaxEncodedLen`) + fn swap_leases() -> Weight { + // Proof Size summary in bytes: + // Measured: `470` + // Estimated: `1886` + // Minimum execution time: 6_597_000 picoseconds. + Weight::from_parts(6_969_000, 0) + .saturating_add(Weight::from_parts(0, 1886)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs index 8727b9633b1..13d5fcf3898 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_broker.rs @@ -17,25 +17,23 @@ //! Autogenerated weights for `pallet_broker` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=coretime-westend-dev -// --wasm-execution=compiled -// --pallet=pallet_broker -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* // --steps=50 // --repeat=20 -// --json +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_broker +// --chain=coretime-westend-dev // --header=./cumulus/file_header.txt // --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/ @@ -56,8 +54,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_944_000 picoseconds. - Weight::from_parts(2_045_000, 0) + // Minimum execution time: 1_897_000 picoseconds. + Weight::from_parts(2_053_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -67,8 +65,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `10888` // Estimated: `13506` - // Minimum execution time: 21_158_000 picoseconds. - Weight::from_parts(21_572_000, 0) + // Minimum execution time: 22_550_000 picoseconds. + Weight::from_parts(22_871_000, 0) .saturating_add(Weight::from_parts(0, 13506)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -79,8 +77,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `12090` // Estimated: `13506` - // Minimum execution time: 20_497_000 picoseconds. - Weight::from_parts(20_995_000, 0) + // Minimum execution time: 21_170_000 picoseconds. + Weight::from_parts(21_645_000, 0) .saturating_add(Weight::from_parts(0, 13506)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -95,8 +93,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `146` // Estimated: `1631` - // Minimum execution time: 10_280_000 picoseconds. - Weight::from_parts(10_686_000, 0) + // Minimum execution time: 10_494_000 picoseconds. + Weight::from_parts(10_942_000, 0) .saturating_add(Weight::from_parts(0, 1631)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -120,15 +118,13 @@ impl pallet_broker::WeightInfo for WeightInfo { /// Storage: `Broker::Workplan` (r:0 w:20) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(n: u32, ) -> Weight { + fn start_sales(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `12247` // Estimated: `13732` - // Minimum execution time: 61_020_000 picoseconds. - Weight::from_parts(63_240_622, 0) + // Minimum execution time: 61_014_000 picoseconds. + Weight::from_parts(63_267_651, 0) .saturating_add(Weight::from_parts(0, 13732)) - // Standard Error: 102 - .saturating_add(Weight::from_parts(255, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(26)) } @@ -144,8 +140,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `316` // Estimated: `3593` - // Minimum execution time: 30_627_000 picoseconds. - Weight::from_parts(31_648_000, 0) + // Minimum execution time: 30_931_000 picoseconds. + Weight::from_parts(31_941_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -166,8 +162,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `434` // Estimated: `4698` - // Minimum execution time: 57_701_000 picoseconds. - Weight::from_parts(59_825_000, 0) + // Minimum execution time: 57_466_000 picoseconds. + Weight::from_parts(65_042_000, 0) .saturating_add(Weight::from_parts(0, 4698)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -178,8 +174,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `357` // Estimated: `3550` - // Minimum execution time: 12_898_000 picoseconds. - Weight::from_parts(13_506_000, 0) + // Minimum execution time: 12_799_000 picoseconds. + Weight::from_parts(13_401_000, 0) .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -190,8 +186,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `357` // Estimated: `3550` - // Minimum execution time: 14_284_000 picoseconds. - Weight::from_parts(14_791_000, 0) + // Minimum execution time: 14_107_000 picoseconds. + Weight::from_parts(14_630_000, 0) .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -202,8 +198,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `357` // Estimated: `3550` - // Minimum execution time: 15_570_000 picoseconds. - Weight::from_parts(16_158_000, 0) + // Minimum execution time: 15_254_000 picoseconds. + Weight::from_parts(16_062_000, 0) .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(3)) @@ -220,8 +216,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `735` // Estimated: `4681` - // Minimum execution time: 23_329_000 picoseconds. - Weight::from_parts(24_196_000, 0) + // Minimum execution time: 23_557_000 picoseconds. + Weight::from_parts(24_382_000, 0) .saturating_add(Weight::from_parts(0, 4681)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) @@ -240,8 +236,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `801` // Estimated: `5996` - // Minimum execution time: 29_288_000 picoseconds. - Weight::from_parts(30_066_000, 0) + // Minimum execution time: 29_371_000 picoseconds. + Weight::from_parts(30_200_000, 0) .saturating_add(Weight::from_parts(0, 5996)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) @@ -257,11 +253,11 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `652` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 54_833_000 picoseconds. - Weight::from_parts(55_577_423, 0) + // Minimum execution time: 54_331_000 picoseconds. + Weight::from_parts(55_322_165, 0) .saturating_add(Weight::from_parts(0, 6196)) - // Standard Error: 35_105 - .saturating_add(Weight::from_parts(1_267_911, 0).saturating_mul(m.into())) + // Standard Error: 35_225 + .saturating_add(Weight::from_parts(1_099_614, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().writes(5)) @@ -283,8 +279,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `215` // Estimated: `3680` - // Minimum execution time: 55_289_000 picoseconds. - Weight::from_parts(56_552_000, 0) + // Minimum execution time: 53_789_000 picoseconds. + Weight::from_parts(55_439_000, 0) .saturating_add(Weight::from_parts(0, 3680)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) @@ -297,8 +293,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `465` // Estimated: `3550` - // Minimum execution time: 39_736_000 picoseconds. - Weight::from_parts(41_346_000, 0) + // Minimum execution time: 43_941_000 picoseconds. + Weight::from_parts(49_776_000, 0) .saturating_add(Weight::from_parts(0, 3550)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -313,8 +309,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `463` // Estimated: `3533` - // Minimum execution time: 57_319_000 picoseconds. - Weight::from_parts(60_204_000, 0) + // Minimum execution time: 64_917_000 picoseconds. + Weight::from_parts(70_403_000, 0) .saturating_add(Weight::from_parts(0, 3533)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -331,8 +327,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `857` // Estimated: `3593` - // Minimum execution time: 85_216_000 picoseconds. - Weight::from_parts(91_144_000, 0) + // Minimum execution time: 72_633_000 picoseconds. + Weight::from_parts(79_305_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(1)) @@ -345,8 +341,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `556` // Estimated: `4698` - // Minimum execution time: 32_331_000 picoseconds. - Weight::from_parts(39_877_000, 0) + // Minimum execution time: 36_643_000 picoseconds. + Weight::from_parts(48_218_000, 0) .saturating_add(Weight::from_parts(0, 4698)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -362,28 +358,28 @@ impl pallet_broker::WeightInfo for WeightInfo { /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 1000]`. - fn request_core_count(n: u32, ) -> Weight { + fn request_core_count(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 18_128_000 picoseconds. - Weight::from_parts(19_061_234, 0) + // Minimum execution time: 17_617_000 picoseconds. + Weight::from_parts(18_904_788, 0) .saturating_add(Weight::from_parts(0, 3539)) - // Standard Error: 48 - .saturating_add(Weight::from_parts(141, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Broker::CoreCountInbox` (r:1 w:1) /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn process_core_count(_n: u32, ) -> Weight { + fn process_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `266` // Estimated: `1487` - // Minimum execution time: 5_368_000 picoseconds. - Weight::from_parts(5_837_005, 0) + // Minimum execution time: 5_575_000 picoseconds. + Weight::from_parts(5_887_598, 0) .saturating_add(Weight::from_parts(0, 1487)) + // Standard Error: 16 + .saturating_add(Weight::from_parts(41, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -397,8 +393,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `447` // Estimated: `6196` - // Minimum execution time: 36_047_000 picoseconds. - Weight::from_parts(37_101_000, 0) + // Minimum execution time: 36_415_000 picoseconds. + Weight::from_parts(37_588_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -414,13 +410,15 @@ impl pallet_broker::WeightInfo for WeightInfo { /// Storage: `Broker::Workplan` (r:0 w:20) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn rotate_sale(_n: u32, ) -> Weight { + fn rotate_sale(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `12194` // Estimated: `13506` - // Minimum execution time: 48_158_000 picoseconds. - Weight::from_parts(49_891_920, 0) + // Minimum execution time: 48_362_000 picoseconds. + Weight::from_parts(49_616_106, 0) .saturating_add(Weight::from_parts(0, 13506)) + // Standard Error: 61 + .saturating_add(Weight::from_parts(59, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(25)) } @@ -432,8 +430,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3493` - // Minimum execution time: 5_911_000 picoseconds. - Weight::from_parts(6_173_000, 0) + // Minimum execution time: 6_148_000 picoseconds. + Weight::from_parts(6_374_000, 0) .saturating_add(Weight::from_parts(0, 3493)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -456,8 +454,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `1321` // Estimated: `4786` - // Minimum execution time: 30_140_000 picoseconds. - Weight::from_parts(30_912_000, 0) + // Minimum execution time: 30_267_000 picoseconds. + Weight::from_parts(30_825_000, 0) .saturating_add(Weight::from_parts(0, 4786)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -476,8 +474,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 13_684_000 picoseconds. - Weight::from_parts(14_252_000, 0) + // Minimum execution time: 13_491_000 picoseconds. + Weight::from_parts(13_949_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -488,8 +486,8 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_718_000 picoseconds. - Weight::from_parts(1_843_000, 0) + // Minimum execution time: 1_711_000 picoseconds. + Weight::from_parts(1_913_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -507,10 +505,22 @@ impl pallet_broker::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `398` // Estimated: `3863` - // Minimum execution time: 11_771_000 picoseconds. - Weight::from_parts(12_120_000, 0) + // Minimum execution time: 12_035_000 picoseconds. + Weight::from_parts(12_383_000, 0) .saturating_add(Weight::from_parts(0, 3863)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(81), added: 576, mode: `MaxEncodedLen`) + fn swap_leases() -> Weight { + // Proof Size summary in bytes: + // Measured: `150` + // Estimated: `1566` + // Minimum execution time: 6_142_000 picoseconds. + Weight::from_parts(6_538_000, 0) + .saturating_add(Weight::from_parts(0, 1566)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/polkadot/runtime/parachains/src/coretime/mod.rs b/polkadot/runtime/parachains/src/coretime/mod.rs index eb9646d7e86..9095cd90ae0 100644 --- a/polkadot/runtime/parachains/src/coretime/mod.rs +++ b/polkadot/runtime/parachains/src/coretime/mod.rs @@ -83,6 +83,8 @@ enum CoretimeCalls { SetLease(pallet_broker::TaskId, pallet_broker::Timeslice), #[codec(index = 19)] NotifyCoreCount(u16), + #[codec(index = 99)] + SwapLeases(ParaId, ParaId), } #[frame_support::pallet] @@ -233,6 +235,24 @@ impl Pallet { } } } + + // Handle legacy swaps in coretime. Notifies broker parachain that a lease swap has occurred via + // XCM message. This function is meant to be used in an implementation of `OnSwap` trait. + pub fn on_legacy_lease_swap(one: ParaId, other: ParaId) { + let message = Xcm(vec![ + Instruction::UnpaidExecution { + weight_limit: WeightLimit::Unlimited, + check_origin: None, + }, + mk_coretime_call(crate::coretime::CoretimeCalls::SwapLeases(one, other)), + ]); + if let Err(err) = send_xcm::( + Location::new(0, [Junction::Parachain(T::BrokerId::get())]), + message, + ) { + log::error!("Sending `SwapLeases` to coretime chain failed: {:?}", err); + } + } } impl OnNewSession> for Pallet { diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 90824a2f6f0..b26317490cd 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -38,7 +38,7 @@ use runtime_common::{ LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter, }, paras_registrar, paras_sudo_wrapper, prod_or_fast, slots, - traits::Leaser, + traits::{Leaser, OnSwap}, BlockHashCount, BlockLength, SlowAdjustingFeeUpdate, }; use scale_info::TypeInfo; @@ -1078,7 +1078,7 @@ impl paras_registrar::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type OnSwap = (Crowdloan, Slots); + type OnSwap = (Crowdloan, Slots, SwapLeases); type ParaDeposit = ParaDeposit; type DataDepositPerByte = DataDepositPerByte; type WeightInfo = weights::runtime_common_paras_registrar::WeightInfo; @@ -1306,6 +1306,14 @@ impl pallet_asset_rate::Config for Runtime { type BenchmarkHelper = runtime_common::impls::benchmarks::AssetRateArguments; } +// Notify `coretime` pallet when a lease swap occurs +pub struct SwapLeases; +impl OnSwap for SwapLeases { + fn on_swap(one: ParaId, other: ParaId) { + coretime::Pallet::::on_legacy_lease_swap(one, other); + } +} + construct_runtime! { pub enum Runtime { diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 664044b713e..12e6174ab6c 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -62,7 +62,7 @@ use runtime_common::{ LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter, }, paras_registrar, paras_sudo_wrapper, prod_or_fast, slots, - traits::Leaser, + traits::{Leaser, OnSwap}, BalanceToU256, BlockHashCount, BlockLength, CurrencyToVote, SlowAdjustingFeeUpdate, U256ToBalance, }; @@ -1302,7 +1302,7 @@ impl paras_registrar::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type OnSwap = (Crowdloan, Slots); + type OnSwap = (Crowdloan, Slots, SwapLeases); type ParaDeposit = ParaDeposit; type DataDepositPerByte = RegistrarDataDepositPerByte; type WeightInfo = weights::runtime_common_paras_registrar::WeightInfo; @@ -1414,6 +1414,14 @@ impl pallet_asset_rate::Config for Runtime { type BenchmarkHelper = runtime_common::impls::benchmarks::AssetRateArguments; } +// Notify `coretime` pallet when a lease swap occurs +pub struct SwapLeases; +impl OnSwap for SwapLeases { + fn on_swap(one: ParaId, other: ParaId) { + coretime::Pallet::::on_legacy_lease_swap(one, other); + } +} + #[frame_support::runtime(legacy_ordering)] mod runtime { #[runtime::runtime] diff --git a/prdoc/pr_3714.prdoc b/prdoc/pr_3714.prdoc new file mode 100644 index 00000000000..e276d0d2d37 --- /dev/null +++ b/prdoc/pr_3714.prdoc @@ -0,0 +1,10 @@ +title: Handle legacy lease swaps on coretime + +doc: + - audience: Runtime Dev + description: | + When a `registar::swap` extrinsic is executed it swaps two leases on the relay chain but the + broker chain never knows about this swap. This change notifies the broker chain via a XCM + message for a swap so that it can update its state. +crates: + - name: pallet-broker diff --git a/substrate/frame/broker/src/benchmarking.rs b/substrate/frame/broker/src/benchmarking.rs index 70f488e998c..98ac074ca91 100644 --- a/substrate/frame/broker/src/benchmarking.rs +++ b/substrate/frame/broker/src/benchmarking.rs @@ -918,6 +918,23 @@ mod benches { Ok(()) } + #[benchmark] + fn swap_leases() -> Result<(), BenchmarkError> { + let admin_origin = + T::AdminOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + + // Add two leases in `Leases` + let n = (T::MaxLeasedCores::get() / 2) as usize; + let mut leases = vec![LeaseRecordItem { task: 1, until: 10u32.into() }; n]; + leases.extend(vec![LeaseRecordItem { task: 2, until: 20u32.into() }; n]); + Leases::::put(BoundedVec::try_from(leases).unwrap()); + + #[extrinsic_call] + _(admin_origin as T::RuntimeOrigin, 1, 2); + + Ok(()) + } + // Implements a test for each benchmark. Execute with: // `cargo test -p pallet-broker --features runtime-benchmarks`. impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs index f2451013251..74cda9c4f4c 100644 --- a/substrate/frame/broker/src/dispatchable_impls.rs +++ b/substrate/frame/broker/src/dispatchable_impls.rs @@ -437,4 +437,22 @@ impl Pallet { Self::deposit_event(Event::AllowedRenewalDropped { core, when }); Ok(()) } + + pub(crate) fn do_swap_leases(id: TaskId, other: TaskId) -> DispatchResult { + let mut id_leases_count = 0; + let mut other_leases_count = 0; + Leases::::mutate(|leases| { + leases.iter_mut().for_each(|lease| { + if lease.task == id { + lease.task = other; + id_leases_count += 1; + } else if lease.task == other { + lease.task = id; + other_leases_count += 1; + } + }) + }); + + Ok(()) + } } diff --git a/substrate/frame/broker/src/lib.rs b/substrate/frame/broker/src/lib.rs index f1b49a73a52..b9b5e309ca9 100644 --- a/substrate/frame/broker/src/lib.rs +++ b/substrate/frame/broker/src/lib.rs @@ -786,5 +786,13 @@ pub mod pallet { Self::do_notify_core_count(core_count)?; Ok(()) } + + #[pallet::call_index(99)] + #[pallet::weight(T::WeightInfo::swap_leases())] + pub fn swap_leases(origin: OriginFor, id: TaskId, other: TaskId) -> DispatchResult { + T::AdminOrigin::ensure_origin_or_root(origin)?; + Self::do_swap_leases(id, other)?; + Ok(()) + } } } diff --git a/substrate/frame/broker/src/weights.rs b/substrate/frame/broker/src/weights.rs index a8f50eeee6e..a8b9fb598b8 100644 --- a/substrate/frame/broker/src/weights.rs +++ b/substrate/frame/broker/src/weights.rs @@ -17,10 +17,10 @@ //! Autogenerated weights for `pallet_broker` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-09-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-pzhd7p6z-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: @@ -76,6 +76,7 @@ pub trait WeightInfo { fn request_revenue_info_at() -> Weight; fn notify_core_count() -> Weight; fn do_tick_base() -> Weight; + fn swap_leases() -> Weight; } /// Weights for `pallet_broker` using the Substrate node and recommended hardware. @@ -87,8 +88,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_040_000 picoseconds. - Weight::from_parts(3_344_000, 0) + // Minimum execution time: 2_865_000 picoseconds. + Weight::from_parts(3_061_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -97,8 +98,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 21_259_000 picoseconds. - Weight::from_parts(22_110_000, 7496) + // Minimum execution time: 18_431_000 picoseconds. + Weight::from_parts(19_558_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -108,8 +109,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 20_330_000 picoseconds. - Weight::from_parts(20_826_000, 7496) + // Minimum execution time: 17_724_000 picoseconds. + Weight::from_parts(18_688_000, 7496) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -119,8 +120,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 13_411_000 picoseconds. - Weight::from_parts(13_960_000, 1526) + // Minimum execution time: 10_513_000 picoseconds. + Weight::from_parts(11_138_000, 1526) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -139,14 +140,12 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(n: u32, ) -> Weight { + fn start_sales(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 57_770_000 picoseconds. - Weight::from_parts(61_047_512, 8499) - // Standard Error: 165 - .saturating_add(Weight::from_parts(3, 0).saturating_mul(n.into())) + // Minimum execution time: 50_864_000 picoseconds. + Weight::from_parts(54_000_280, 8499) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(16_u64)) } @@ -162,10 +161,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn purchase() -> Weight { // Proof Size summary in bytes: - // Measured: `568` - // Estimated: `2053` - // Minimum execution time: 51_196_000 picoseconds. - Weight::from_parts(52_382_000, 2053) + // Measured: `635` + // Estimated: `2120` + // Minimum execution time: 43_630_000 picoseconds. + Weight::from_parts(44_622_000, 2120) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -185,10 +184,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `686` + // Measured: `753` // Estimated: `4698` - // Minimum execution time: 71_636_000 picoseconds. - Weight::from_parts(73_679_000, 4698) + // Minimum execution time: 62_453_000 picoseconds. + Weight::from_parts(63_882_000, 4698) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -198,8 +197,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 19_182_000 picoseconds. - Weight::from_parts(19_775_000, 3550) + // Minimum execution time: 17_237_000 picoseconds. + Weight::from_parts(17_757_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -209,21 +208,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 20_688_000 picoseconds. - Weight::from_parts(21_557_000, 3550) + // Minimum execution time: 18_504_000 picoseconds. + Weight::from_parts(19_273_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: `Broker::Regions` (r:1 w:2) + /// Storage: `Broker::Regions` (r:1 w:3) /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn interlace() -> Weight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 21_190_000 picoseconds. - Weight::from_parts(22_215_000, 3550) + // Minimum execution time: 20_477_000 picoseconds. + Weight::from_parts(21_328_000, 3550) .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) @@ -237,8 +236,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `740` // Estimated: `4681` - // Minimum execution time: 34_591_000 picoseconds. - Weight::from_parts(36_227_000, 4681) + // Minimum execution time: 31_815_000 picoseconds. + Weight::from_parts(32_700_000, 4681) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -256,8 +255,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `775` // Estimated: `5996` - // Minimum execution time: 40_346_000 picoseconds. - Weight::from_parts(41_951_000, 5996) + // Minimum execution time: 38_313_000 picoseconds. + Weight::from_parts(38_985_000, 5996) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -272,10 +271,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 75_734_000 picoseconds. - Weight::from_parts(78_168_395, 6196) - // Standard Error: 63_180 - .saturating_add(Weight::from_parts(1_076_259, 0).saturating_mul(m.into())) + // Minimum execution time: 70_170_000 picoseconds. + Weight::from_parts(71_245_388, 6196) + // Standard Error: 54_382 + .saturating_add(Weight::from_parts(1_488_794, 0).saturating_mul(m.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(T::DbWeight::get().writes(5_u64)) @@ -287,8 +286,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 46_383_000 picoseconds. - Weight::from_parts(47_405_000, 3593) + // Minimum execution time: 43_414_000 picoseconds. + Weight::from_parts(44_475_000, 3593) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -300,8 +299,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `603` // Estimated: `3550` - // Minimum execution time: 30_994_000 picoseconds. - Weight::from_parts(31_979_000, 3550) + // Minimum execution time: 31_327_000 picoseconds. + Weight::from_parts(32_050_000, 3550) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -315,8 +314,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 37_584_000 picoseconds. - Weight::from_parts(44_010_000, 3533) + // Minimum execution time: 41_315_000 picoseconds. + Weight::from_parts(42_421_000, 3533) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -330,10 +329,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_history() -> Weight { // Proof Size summary in bytes: - // Measured: `830` + // Measured: `995` // Estimated: `3593` - // Minimum execution time: 45_266_000 picoseconds. - Weight::from_parts(48_000_000, 3593) + // Minimum execution time: 49_707_000 picoseconds. + Weight::from_parts(51_516_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -343,10 +342,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: - // Measured: `525` + // Measured: `661` // Estimated: `4698` - // Minimum execution time: 25_365_000 picoseconds. - Weight::from_parts(26_920_000, 4698) + // Minimum execution time: 26_207_000 picoseconds. + Weight::from_parts(27_227_000, 4698) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -355,22 +354,22 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_519_000 picoseconds. - Weight::from_parts(7_098_698, 0) - // Standard Error: 20 - .saturating_add(Weight::from_parts(8, 0).saturating_mul(n.into())) + // Minimum execution time: 4_670_000 picoseconds. + Weight::from_parts(5_170_450, 0) + // Standard Error: 16 + .saturating_add(Weight::from_parts(37, 0).saturating_mul(n.into())) } - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: `Broker::CoreCountInbox` (r:1 w:1) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn process_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `98` - // Estimated: `3563` - // Minimum execution time: 7_608_000 picoseconds. - Weight::from_parts(8_157_815, 3563) - // Standard Error: 26 - .saturating_add(Weight::from_parts(48, 0).saturating_mul(n.into())) + // Measured: `404` + // Estimated: `1487` + // Minimum execution time: 6_916_000 picoseconds. + Weight::from_parts(7_485_053, 1487) + // Standard Error: 23 + .saturating_add(Weight::from_parts(30, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -386,10 +385,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn process_revenue() -> Weight { // Proof Size summary in bytes: - // Measured: `905` - // Estimated: `4370` - // Minimum execution time: 59_993_000 picoseconds. - Weight::from_parts(61_752_000, 4370) + // Measured: `972` + // Estimated: `4437` + // Minimum execution time: 50_987_000 picoseconds. + Weight::from_parts(52_303_000, 4437) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -408,10 +407,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 41_863_000 picoseconds. - Weight::from_parts(44_033_031, 8499) - // Standard Error: 116 - .saturating_add(Weight::from_parts(764, 0).saturating_mul(n.into())) + // Minimum execution time: 38_334_000 picoseconds. + Weight::from_parts(40_517_609, 8499) + // Standard Error: 90 + .saturating_add(Weight::from_parts(338, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)) } @@ -423,8 +422,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 9_588_000 picoseconds. - Weight::from_parts(9_925_000, 3493) + // Minimum execution time: 7_850_000 picoseconds. + Weight::from_parts(8_157_000, 3493) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -436,8 +435,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 19_308_000 picoseconds. - Weight::from_parts(20_482_000, 4681) + // Minimum execution time: 17_313_000 picoseconds. + Weight::from_parts(17_727_000, 4681) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -445,28 +444,46 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 147_000 picoseconds. - Weight::from_parts(184_000, 0) + // Minimum execution time: 171_000 picoseconds. + Weight::from_parts(196_000, 0) } + /// Storage: `Broker::CoreCountInbox` (r:0 w:1) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) fn notify_core_count() -> Weight { - T::DbWeight::get().reads_writes(1, 1) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_413_000 picoseconds. + Weight::from_parts(2_587_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:1) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: `Broker::CoreCountInbox` (r:1 w:0) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) fn do_tick_base() -> Weight { // Proof Size summary in bytes: - // Measured: `699` - // Estimated: `4164` - // Minimum execution time: 19_824_000 picoseconds. - Weight::from_parts(20_983_000, 4164) + // Measured: `603` + // Estimated: `4068` + // Minimum execution time: 13_121_000 picoseconds. + Weight::from_parts(13_685_000, 4068) .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + fn swap_leases() -> Weight { + // Proof Size summary in bytes: + // Measured: `239` + // Estimated: `1526` + // Minimum execution time: 6_847_000 picoseconds. + Weight::from_parts(7_185_000, 1526) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } @@ -478,8 +495,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_040_000 picoseconds. - Weight::from_parts(3_344_000, 0) + // Minimum execution time: 2_865_000 picoseconds. + Weight::from_parts(3_061_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Reservations` (r:1 w:1) @@ -488,8 +505,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `5016` // Estimated: `7496` - // Minimum execution time: 21_259_000 picoseconds. - Weight::from_parts(22_110_000, 7496) + // Minimum execution time: 18_431_000 picoseconds. + Weight::from_parts(19_558_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -499,8 +516,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6218` // Estimated: `7496` - // Minimum execution time: 20_330_000 picoseconds. - Weight::from_parts(20_826_000, 7496) + // Minimum execution time: 17_724_000 picoseconds. + Weight::from_parts(18_688_000, 7496) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -510,8 +527,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `239` // Estimated: `1526` - // Minimum execution time: 13_411_000 picoseconds. - Weight::from_parts(13_960_000, 1526) + // Minimum execution time: 10_513_000 picoseconds. + Weight::from_parts(11_138_000, 1526) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -530,14 +547,12 @@ impl WeightInfo for () { /// Storage: `Broker::Workplan` (r:0 w:10) /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. - fn start_sales(n: u32, ) -> Weight { + fn start_sales(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `6330` // Estimated: `8499` - // Minimum execution time: 57_770_000 picoseconds. - Weight::from_parts(61_047_512, 8499) - // Standard Error: 165 - .saturating_add(Weight::from_parts(3, 0).saturating_mul(n.into())) + // Minimum execution time: 50_864_000 picoseconds. + Weight::from_parts(54_000_280, 8499) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(16_u64)) } @@ -553,10 +568,10 @@ impl WeightInfo for () { /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn purchase() -> Weight { // Proof Size summary in bytes: - // Measured: `568` - // Estimated: `2053` - // Minimum execution time: 51_196_000 picoseconds. - Weight::from_parts(52_382_000, 2053) + // Measured: `635` + // Estimated: `2120` + // Minimum execution time: 43_630_000 picoseconds. + Weight::from_parts(44_622_000, 2120) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -576,10 +591,10 @@ impl WeightInfo for () { /// Proof: `Broker::Workplan` (`max_values`: None, `max_size`: Some(1216), added: 3691, mode: `MaxEncodedLen`) fn renew() -> Weight { // Proof Size summary in bytes: - // Measured: `686` + // Measured: `753` // Estimated: `4698` - // Minimum execution time: 71_636_000 picoseconds. - Weight::from_parts(73_679_000, 4698) + // Minimum execution time: 62_453_000 picoseconds. + Weight::from_parts(63_882_000, 4698) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -589,8 +604,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 19_182_000 picoseconds. - Weight::from_parts(19_775_000, 3550) + // Minimum execution time: 17_237_000 picoseconds. + Weight::from_parts(17_757_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -600,21 +615,21 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 20_688_000 picoseconds. - Weight::from_parts(21_557_000, 3550) + // Minimum execution time: 18_504_000 picoseconds. + Weight::from_parts(19_273_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: `Broker::Regions` (r:1 w:2) + /// Storage: `Broker::Regions` (r:1 w:3) /// Proof: `Broker::Regions` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) fn interlace() -> Weight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `3550` - // Minimum execution time: 21_190_000 picoseconds. - Weight::from_parts(22_215_000, 3550) + // Minimum execution time: 20_477_000 picoseconds. + Weight::from_parts(21_328_000, 3550) .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) @@ -628,8 +643,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `740` // Estimated: `4681` - // Minimum execution time: 34_591_000 picoseconds. - Weight::from_parts(36_227_000, 4681) + // Minimum execution time: 31_815_000 picoseconds. + Weight::from_parts(32_700_000, 4681) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -647,8 +662,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `775` // Estimated: `5996` - // Minimum execution time: 40_346_000 picoseconds. - Weight::from_parts(41_951_000, 5996) + // Minimum execution time: 38_313_000 picoseconds. + Weight::from_parts(38_985_000, 5996) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -663,10 +678,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `859` // Estimated: `6196 + m * (2520 ±0)` - // Minimum execution time: 75_734_000 picoseconds. - Weight::from_parts(78_168_395, 6196) - // Standard Error: 63_180 - .saturating_add(Weight::from_parts(1_076_259, 0).saturating_mul(m.into())) + // Minimum execution time: 70_170_000 picoseconds. + Weight::from_parts(71_245_388, 6196) + // Standard Error: 54_382 + .saturating_add(Weight::from_parts(1_488_794, 0).saturating_mul(m.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(m.into()))) .saturating_add(RocksDbWeight::get().writes(5_u64)) @@ -678,8 +693,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `103` // Estimated: `3593` - // Minimum execution time: 46_383_000 picoseconds. - Weight::from_parts(47_405_000, 3593) + // Minimum execution time: 43_414_000 picoseconds. + Weight::from_parts(44_475_000, 3593) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -691,8 +706,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `603` // Estimated: `3550` - // Minimum execution time: 30_994_000 picoseconds. - Weight::from_parts(31_979_000, 3550) + // Minimum execution time: 31_327_000 picoseconds. + Weight::from_parts(32_050_000, 3550) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -706,8 +721,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `601` // Estimated: `3533` - // Minimum execution time: 37_584_000 picoseconds. - Weight::from_parts(44_010_000, 3533) + // Minimum execution time: 41_315_000 picoseconds. + Weight::from_parts(42_421_000, 3533) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -721,10 +736,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn drop_history() -> Weight { // Proof Size summary in bytes: - // Measured: `830` + // Measured: `995` // Estimated: `3593` - // Minimum execution time: 45_266_000 picoseconds. - Weight::from_parts(48_000_000, 3593) + // Minimum execution time: 49_707_000 picoseconds. + Weight::from_parts(51_516_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -734,10 +749,10 @@ impl WeightInfo for () { /// Proof: `Broker::AllowedRenewals` (`max_values`: None, `max_size`: Some(1233), added: 3708, mode: `MaxEncodedLen`) fn drop_renewal() -> Weight { // Proof Size summary in bytes: - // Measured: `525` + // Measured: `661` // Estimated: `4698` - // Minimum execution time: 25_365_000 picoseconds. - Weight::from_parts(26_920_000, 4698) + // Minimum execution time: 26_207_000 picoseconds. + Weight::from_parts(27_227_000, 4698) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -746,22 +761,22 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_519_000 picoseconds. - Weight::from_parts(7_098_698, 0) - // Standard Error: 20 - .saturating_add(Weight::from_parts(8, 0).saturating_mul(n.into())) + // Minimum execution time: 4_670_000 picoseconds. + Weight::from_parts(5_170_450, 0) + // Standard Error: 16 + .saturating_add(Weight::from_parts(37, 0).saturating_mul(n.into())) } - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: `Broker::CoreCountInbox` (r:1 w:1) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 1000]`. fn process_core_count(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `98` - // Estimated: `3563` - // Minimum execution time: 7_608_000 picoseconds. - Weight::from_parts(8_157_815, 3563) - // Standard Error: 26 - .saturating_add(Weight::from_parts(48, 0).saturating_mul(n.into())) + // Measured: `404` + // Estimated: `1487` + // Minimum execution time: 6_916_000 picoseconds. + Weight::from_parts(7_485_053, 1487) + // Standard Error: 23 + .saturating_add(Weight::from_parts(30, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -777,10 +792,10 @@ impl WeightInfo for () { /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn process_revenue() -> Weight { // Proof Size summary in bytes: - // Measured: `905` - // Estimated: `4370` - // Minimum execution time: 59_993_000 picoseconds. - Weight::from_parts(61_752_000, 4370) + // Measured: `972` + // Estimated: `4437` + // Minimum execution time: 50_987_000 picoseconds. + Weight::from_parts(52_303_000, 4437) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -799,10 +814,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `6281` // Estimated: `8499` - // Minimum execution time: 41_863_000 picoseconds. - Weight::from_parts(44_033_031, 8499) - // Standard Error: 116 - .saturating_add(Weight::from_parts(764, 0).saturating_mul(n.into())) + // Minimum execution time: 38_334_000 picoseconds. + Weight::from_parts(40_517_609, 8499) + // Standard Error: 90 + .saturating_add(Weight::from_parts(338, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(15_u64)) } @@ -814,8 +829,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3493` - // Minimum execution time: 9_588_000 picoseconds. - Weight::from_parts(9_925_000, 3493) + // Minimum execution time: 7_850_000 picoseconds. + Weight::from_parts(8_157_000, 3493) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -827,8 +842,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1423` // Estimated: `4681` - // Minimum execution time: 19_308_000 picoseconds. - Weight::from_parts(20_482_000, 4681) + // Minimum execution time: 17_313_000 picoseconds. + Weight::from_parts(17_727_000, 4681) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -836,28 +851,45 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 147_000 picoseconds. - Weight::from_parts(184_000, 0) + // Minimum execution time: 171_000 picoseconds. + Weight::from_parts(196_000, 0) } + /// Storage: `Broker::CoreCountInbox` (r:0 w:1) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) fn notify_core_count() -> Weight { - RocksDbWeight::get().reads(1) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_413_000 picoseconds. + Weight::from_parts(2_587_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Broker::Status` (r:1 w:1) /// Proof: `Broker::Status` (`max_values`: Some(1), `max_size`: Some(18), added: 513, mode: `MaxEncodedLen`) /// Storage: `Broker::Configuration` (r:1 w:0) /// Proof: `Broker::Configuration` (`max_values`: Some(1), `max_size`: Some(31), added: 526, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) - /// Proof: UNKNOWN KEY `0x18194fcb5c1fcace44d2d0a004272614` (r:1 w:1) + /// Storage: `Broker::CoreCountInbox` (r:1 w:0) + /// Proof: `Broker::CoreCountInbox` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) /// Storage: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) /// Proof: UNKNOWN KEY `0xf308d869daf021a7724e69c557dd8dbe` (r:1 w:1) fn do_tick_base() -> Weight { // Proof Size summary in bytes: - // Measured: `699` - // Estimated: `4164` - // Minimum execution time: 19_824_000 picoseconds. - Weight::from_parts(20_983_000, 4164) + // Measured: `603` + // Estimated: `4068` + // Minimum execution time: 13_121_000 picoseconds. + Weight::from_parts(13_685_000, 4068) .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `Broker::Leases` (r:1 w:1) + /// Proof: `Broker::Leases` (`max_values`: Some(1), `max_size`: Some(41), added: 536, mode: `MaxEncodedLen`) + fn swap_leases() -> Weight { + // Proof Size summary in bytes: + // Measured: `239` + // Estimated: `1526` + // Minimum execution time: 6_847_000 picoseconds. + Weight::from_parts(7_185_000, 1526) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } } -- GitLab From 0c15d887519d58c50880ccd149b6ee9a7635b5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 26 Mar 2024 18:00:39 +0000 Subject: [PATCH 180/188] westend: `SignedPhase` is a constant (#3646) In preparation for the merkleized metadata, we need to ensure that constants are actually constant. If we want to test the unsigned phase we could for example just disable signed voter. Or we add some extra mechanism to the pallet to disable the signed phase from time to time. --------- Co-authored-by: Ankan <10196091+Ank4n@users.noreply.github.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- substrate/frame/election-provider-multi-phase/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/substrate/frame/election-provider-multi-phase/src/lib.rs b/substrate/frame/election-provider-multi-phase/src/lib.rs index 31a79577d1f..11577cd3526 100644 --- a/substrate/frame/election-provider-multi-phase/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/src/lib.rs @@ -586,10 +586,8 @@ pub mod pallet { type EstimateCallFee: EstimateCallFee, BalanceOf>; /// Duration of the unsigned phase. - #[pallet::constant] type UnsignedPhase: Get>; /// Duration of the signed phase. - #[pallet::constant] type SignedPhase: Get>; /// The minimum amount of improvement to the solution score that defines a solution as -- GitLab From 3c972fc19e14b55e8a077145cf2620bccb0a6f8d Mon Sep 17 00:00:00 2001 From: Pavel Orlov <45266194+PraetorP@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:34:28 +0700 Subject: [PATCH 181/188] XCM Fee Payment Runtime API (#3607) The PR provides API for obtaining: - the weight required to execute an XCM message, - a list of acceptable `AssetId`s for message execution payment, - the cost of the weight in the specified acceptable `AssetId`. It is meant to address an issue where one has to guess how much fee to pay for execution. Also, at the moment, a client has to guess which assets are acceptable for fee execution payment. See the related issue https://github.com/paritytech/polkadot-sdk/issues/690. With this API, a client is supposed to query the list of the supported asset IDs (in the XCM version format the client understands), weigh the XCM program the client wants to execute and convert the weight into one of the acceptable assets. Note that the client is supposed to know what program will be executed on what chains. However, having a small companion JS library for the pallet-xcm and xtokens should be enough to determine what XCM programs will be executed and where (since these pallets compose a known small set of programs). ```Rust pub trait XcmPaymentApi where Call: Codec, { /// Returns a list of acceptable payment assets. /// /// # Arguments /// /// * `xcm_version`: Version. fn query_acceptable_payment_assets(xcm_version: Version) -> Result, Error>; /// Returns a weight needed to execute a XCM. /// /// # Arguments /// /// * `message`: `VersionedXcm`. fn query_xcm_weight(message: VersionedXcm) -> Result; /// Converts a weight into a fee for the specified `AssetId`. /// /// # Arguments /// /// * `weight`: convertible `Weight`. /// * `asset`: `VersionedAssetId`. fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result; /// Get delivery fees for sending a specific `message` to a `destination`. /// These always come in a specific asset, defined by the chain. /// /// # Arguments /// * `message`: The message that'll be sent, necessary because most delivery fees are based on the /// size of the message. /// * `destination`: The destination to send the message to. Different destinations may use /// different senders that charge different fees. fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result; } ``` An [example](https://gist.github.com/PraetorP/4bc323ff85401abe253897ba990ec29d) of a client side code. --------- Co-authored-by: Francisco Aguirre Co-authored-by: Adrian Catangiu Co-authored-by: Daniel Shiposha --- Cargo.lock | 19 ++++ Cargo.toml | 1 + polkadot/node/service/Cargo.toml | 3 + polkadot/node/service/src/fake_runtime_api.rs | 21 +++- polkadot/runtime/rococo/Cargo.toml | 2 + polkadot/runtime/rococo/src/lib.rs | 53 ++++++++-- polkadot/runtime/westend/Cargo.toml | 2 + polkadot/runtime/westend/src/lib.rs | 51 ++++++++-- polkadot/runtime/westend/src/tests.rs | 1 - polkadot/xcm/pallet-xcm/Cargo.toml | 2 + polkadot/xcm/pallet-xcm/src/lib.rs | 32 ++++++ polkadot/xcm/src/lib.rs | 10 ++ .../xcm-fee-payment-runtime-api/Cargo.toml | 40 ++++++++ .../xcm-fee-payment-runtime-api/src/lib.rs | 99 +++++++++++++++++++ prdoc/pr_3607.prdoc | 26 +++++ 15 files changed, 342 insertions(+), 20 deletions(-) create mode 100644 polkadot/xcm/xcm-fee-payment-runtime-api/Cargo.toml create mode 100644 polkadot/xcm/xcm-fee-payment-runtime-api/src/lib.rs create mode 100644 prdoc/pr_3607.prdoc diff --git a/Cargo.lock b/Cargo.lock index 9e52bfcf9a4..f246a978fd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11188,6 +11188,7 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -13540,12 +13541,14 @@ dependencies = [ "sp-transaction-pool", "sp-version", "sp-weights", + "staging-xcm", "substrate-prometheus-endpoint", "tempfile", "thiserror", "tracing-gum", "westend-runtime", "westend-runtime-constants", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -15116,6 +15119,7 @@ dependencies = [ "substrate-wasm-builder", "tiny-keccak", "tokio", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -21970,6 +21974,7 @@ dependencies = [ "tiny-keccak", "tokio", "westend-runtime-constants", + "xcm-fee-payment-runtime-api", ] [[package]] @@ -22443,6 +22448,20 @@ dependencies = [ "staging-xcm-executor", ] +[[package]] +name = "xcm-fee-payment-runtime-api" +version = "0.1.0" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-runtime", + "sp-std 14.0.0", + "sp-weights", + "staging-xcm", +] + [[package]] name = "xcm-procedural" version = "7.0.0" diff --git a/Cargo.toml b/Cargo.toml index 5eeac597827..e6162830375 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -214,6 +214,7 @@ members = [ "polkadot/xcm/xcm-builder", "polkadot/xcm/xcm-executor", "polkadot/xcm/xcm-executor/integration-tests", + "polkadot/xcm/xcm-fee-payment-runtime-api", "polkadot/xcm/xcm-simulator", "polkadot/xcm/xcm-simulator/example", "polkadot/xcm/xcm-simulator/fuzzer", diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml index e2bccfa5510..5a42443c84c 100644 --- a/polkadot/node/service/Cargo.toml +++ b/polkadot/node/service/Cargo.toml @@ -142,6 +142,9 @@ polkadot-node-core-pvf-checker = { path = "../core/pvf-checker", optional = true polkadot-node-core-runtime-api = { path = "../core/runtime-api", optional = true } polkadot-statement-distribution = { path = "../network/statement-distribution", optional = true } +xcm = { package = "staging-xcm", path = "../../xcm" } +xcm-fee-payment-runtime-api = { path = "../../xcm/xcm-fee-payment-runtime-api" } + [dev-dependencies] polkadot-test-client = { path = "../test/client" } polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } diff --git a/polkadot/node/service/src/fake_runtime_api.rs b/polkadot/node/service/src/fake_runtime_api.rs index 085ea93fdc7..c6cfb7a27d0 100644 --- a/polkadot/node/service/src/fake_runtime_api.rs +++ b/polkadot/node/service/src/fake_runtime_api.rs @@ -30,6 +30,7 @@ use polkadot_primitives::{ ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, }; + use sp_core::OpaqueMetadata; use sp_runtime::{ traits::Block as BlockT, @@ -39,7 +40,7 @@ use sp_runtime::{ use sp_version::RuntimeVersion; use sp_weights::Weight; use std::collections::BTreeMap; - +use xcm::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; sp_api::decl_runtime_apis! { /// This runtime API is only implemented for the test runtime! pub trait GetLastTimestamp { @@ -396,4 +397,22 @@ sp_api::impl_runtime_apis! { unimplemented!() } } + + impl xcm_fee_payment_runtime_api::XcmPaymentApi for Runtime { + fn query_acceptable_payment_assets(_: xcm::Version) -> Result, xcm_fee_payment_runtime_api::Error> { + unimplemented!() + } + + fn query_weight_to_asset_fee(_: Weight, _: VersionedAssetId) -> Result { + unimplemented!() + } + + fn query_xcm_weight(_: VersionedXcm<()>) -> Result { + unimplemented!() + } + + fn query_delivery_fees(_: VersionedLocation, _: VersionedXcm<()>) -> Result { + unimplemented!() + } + } } diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index 3dc59cc1728..6f63a93cebe 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -104,6 +104,7 @@ polkadot-parachain-primitives = { path = "../../parachain", default-features = f xcm = { package = "staging-xcm", path = "../../xcm", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../xcm/xcm-executor", default-features = false } xcm-builder = { package = "staging-xcm-builder", path = "../../xcm/xcm-builder", default-features = false } +xcm-fee-payment-runtime-api = { path = "../../xcm/xcm-fee-payment-runtime-api", default-features = false } [dev-dependencies] tiny-keccak = { version = "2.0.2", features = ["keccak"] } @@ -208,6 +209,7 @@ std = [ "tx-pool-api/std", "xcm-builder/std", "xcm-executor/std", + "xcm-fee-payment-runtime-api/std", "xcm/std", ] runtime-benchmarks = [ diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index b26317490cd..8c8abe97ede 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -75,7 +75,7 @@ use frame_support::{ InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage, ProcessMessageError, StorageMapShim, WithdrawReasons, }, - weights::{ConstantMultiplier, WeightMeter}, + weights::{ConstantMultiplier, WeightMeter, WeightToFee as _}, PalletId, }; use frame_system::{EnsureRoot, EnsureSigned}; @@ -98,7 +98,10 @@ use sp_staking::SessionIndex; #[cfg(any(feature = "std", test))] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use xcm::{latest::prelude::*, VersionedLocation}; +use xcm::{ + latest::prelude::*, IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, + VersionedXcm, +}; use xcm_builder::PayOverXcm; pub use frame_system::Call as SystemCall; @@ -123,6 +126,7 @@ use governance::{ pallet_custom_origins, AuctionAdmin, Fellows, GeneralAdmin, LeaseAdmin, Treasurer, TreasurySpender, }; +use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; #[cfg(test)] mod tests; @@ -216,7 +220,7 @@ pub struct OriginPrivilegeCmp; impl PrivilegeCmp for OriginPrivilegeCmp { fn cmp_privilege(left: &OriginCaller, right: &OriginCaller) -> Option { if left == right { - return Some(Ordering::Equal) + return Some(Ordering::Equal); } match (left, right) { @@ -1493,11 +1497,11 @@ pub mod migrations { let now = frame_system::Pallet::::block_number(); let lease = slots::Pallet::::lease(para); if lease.is_empty() { - return None + return None; } // Lease not yet started, ignore: if lease.iter().any(Option::is_none) { - return None + return None; } let (index, _) = as Leaser>::lease_period_index(now)?; @@ -1559,7 +1563,7 @@ pub mod migrations { fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { log::warn!(target: "runtime::session_keys", "Skipping session keys migration pre-upgrade check due to spec version (already applied?)"); - return Ok(Vec::new()) + return Ok(Vec::new()); } log::info!(target: "runtime::session_keys", "Collecting pre-upgrade session keys state"); @@ -1588,7 +1592,7 @@ pub mod migrations { fn on_runtime_upgrade() -> Weight { if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { log::info!("Skipping session keys upgrade: already applied"); - return ::DbWeight::get().reads(1) + return ::DbWeight::get().reads(1); } log::trace!("Upgrading session keys"); Session::upgrade_keys::(transform_session_keys); @@ -1601,7 +1605,7 @@ pub mod migrations { ) -> Result<(), sp_runtime::TryRuntimeError> { if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { log::warn!(target: "runtime::session_keys", "Skipping session keys migration post-upgrade check due to spec version (already applied?)"); - return Ok(()) + return Ok(()); } let key_ids = SessionKeys::key_ids(); @@ -1785,6 +1789,37 @@ sp_api::impl_runtime_apis! { } } + impl xcm_fee_payment_runtime_api::XcmPaymentApi for Runtime { + fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result, XcmPaymentApiError> { + if !matches!(xcm_version, 3 | 4) { + return Err(XcmPaymentApiError::UnhandledXcmVersion); + } + Ok([VersionedAssetId::V4(xcm_config::TokenLocation::get().into())] + .into_iter() + .filter_map(|asset| asset.into_version(xcm_version).ok()) + .collect()) + } + + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { + let local_asset = VersionedAssetId::V4(xcm_config::TokenLocation::get().into()); + let asset = asset + .into_version(4) + .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; + + if asset != local_asset { return Err(XcmPaymentApiError::AssetNotFound); } + + Ok(WeightToFee::weight_to_fee(&weight)) + } + + fn query_xcm_weight(message: VersionedXcm<()>) -> Result { + XcmPallet::query_xcm_weight(message) + } + + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result { + XcmPallet::query_delivery_fees(destination, message) + } + } + impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) @@ -2493,7 +2528,7 @@ mod remote_tests { #[tokio::test] async fn run_migrations() { if var("RUN_MIGRATION_TESTS").is_err() { - return + return; } sp_tracing::try_init_simple(); diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml index fcead1dd0b5..587a6c9a590 100644 --- a/polkadot/runtime/westend/Cargo.toml +++ b/polkadot/runtime/westend/Cargo.toml @@ -114,6 +114,7 @@ runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parac xcm = { package = "staging-xcm", path = "../../xcm", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../xcm/xcm-executor", default-features = false } xcm-builder = { package = "staging-xcm-builder", path = "../../xcm/xcm-builder", default-features = false } +xcm-fee-payment-runtime-api = { path = "../../xcm/xcm-fee-payment-runtime-api", default-features = false } [dev-dependencies] hex-literal = "0.4.1" @@ -227,6 +228,7 @@ std = [ "westend-runtime-constants/std", "xcm-builder/std", "xcm-executor/std", + "xcm-fee-payment-runtime-api/std", "xcm/std", ] runtime-benchmarks = [ diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 12e6174ab6c..02397f35368 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -35,7 +35,7 @@ use frame_support::{ InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, ProcessMessage, ProcessMessageError, WithdrawReasons, }, - weights::{ConstantMultiplier, WeightMeter}, + weights::{ConstantMultiplier, WeightMeter, WeightToFee as _}, PalletId, }; use frame_system::{EnsureRoot, EnsureSigned}; @@ -101,11 +101,13 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use sp_version::NativeVersion; use sp_version::RuntimeVersion; use xcm::{ - latest::{InteriorLocation, Junction, Junction::PalletInstance}, - VersionedLocation, + latest::prelude::*, IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation, + VersionedXcm, }; use xcm_builder::PayOverXcm; +use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError; + pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_election_provider_multi_phase::{Call as EPMCall, GeometricDepositBase}; @@ -1667,11 +1669,11 @@ pub mod migrations { let now = frame_system::Pallet::::block_number(); let lease = slots::Pallet::::lease(para); if lease.is_empty() { - return None + return None; } // Lease not yet started, ignore: if lease.iter().any(Option::is_none) { - return None + return None; } let (index, _) = as Leaser>::lease_period_index(now)?; @@ -1693,7 +1695,7 @@ pub mod migrations { fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { log::warn!(target: "runtime::session_keys", "Skipping session keys migration pre-upgrade check due to spec version (already applied?)"); - return Ok(Vec::new()) + return Ok(Vec::new()); } log::info!(target: "runtime::session_keys", "Collecting pre-upgrade session keys state"); @@ -1722,7 +1724,7 @@ pub mod migrations { fn on_runtime_upgrade() -> Weight { if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { log::warn!("Skipping session keys upgrade: already applied"); - return ::DbWeight::get().reads(1) + return ::DbWeight::get().reads(1); } log::info!("Upgrading session keys"); Session::upgrade_keys::(transform_session_keys); @@ -1735,7 +1737,7 @@ pub mod migrations { ) -> Result<(), sp_runtime::TryRuntimeError> { if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { log::warn!(target: "runtime::session_keys", "Skipping session keys migration post-upgrade check due to spec version (already applied?)"); - return Ok(()) + return Ok(()); } let key_ids = SessionKeys::key_ids(); @@ -2332,6 +2334,37 @@ sp_api::impl_runtime_apis! { } } + impl xcm_fee_payment_runtime_api::XcmPaymentApi for Runtime { + fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result, XcmPaymentApiError> { + if !matches!(xcm_version, 3 | 4) { + return Err(XcmPaymentApiError::UnhandledXcmVersion); + } + Ok([VersionedAssetId::V4(xcm_config::TokenLocation::get().into())] + .into_iter() + .filter_map(|asset| asset.into_version(xcm_version).ok()) + .collect()) + } + + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { + let local_asset = VersionedAssetId::V4(xcm_config::TokenLocation::get().into()); + let asset = asset + .into_version(4) + .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?; + + if asset != local_asset { return Err(XcmPaymentApiError::AssetNotFound); } + + Ok(WeightToFee::weight_to_fee(&weight)) + } + + fn query_xcm_weight(message: VersionedXcm<()>) -> Result { + XcmPallet::query_xcm_weight(message) + } + + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result { + XcmPallet::query_delivery_fees(destination, message) + } + } + impl pallet_nomination_pools_runtime_api::NominationPoolsApi< Block, AccountId, @@ -2650,7 +2683,7 @@ mod remote_tests { #[tokio::test] async fn run_migrations() { if var("RUN_MIGRATION_TESTS").is_err() { - return + return; } sp_tracing::try_init_simple(); diff --git a/polkadot/runtime/westend/src/tests.rs b/polkadot/runtime/westend/src/tests.rs index 9f996316059..bdd599d2b75 100644 --- a/polkadot/runtime/westend/src/tests.rs +++ b/polkadot/runtime/westend/src/tests.rs @@ -21,7 +21,6 @@ use std::collections::HashSet; use crate::*; use frame_support::traits::WhitelistedStorageKeys; use sp_core::hexdisplay::HexDisplay; -use xcm::latest::prelude::*; #[test] fn remove_keys_weight_is_sensible() { diff --git a/polkadot/xcm/pallet-xcm/Cargo.toml b/polkadot/xcm/pallet-xcm/Cargo.toml index 4840b6127f5..08307c34f8a 100644 --- a/polkadot/xcm/pallet-xcm/Cargo.toml +++ b/polkadot/xcm/pallet-xcm/Cargo.toml @@ -26,6 +26,7 @@ sp-std = { path = "../../../substrate/primitives/std", default-features = false xcm = { package = "staging-xcm", path = "..", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../xcm-executor", default-features = false } xcm-builder = { package = "staging-xcm-builder", path = "../xcm-builder", default-features = false } +xcm-fee-payment-runtime-api = { path = "../xcm-fee-payment-runtime-api", default-features = false } # marked optional, used in benchmarking frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } @@ -54,6 +55,7 @@ std = [ "sp-std/std", "xcm-builder/std", "xcm-executor/std", + "xcm-fee-payment-runtime-api/std", "xcm/std", ] runtime-benchmarks = [ diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 8a9e5288f2e..58a597de5ab 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -61,6 +61,7 @@ use xcm_executor::{ }, AssetsInHolding, }; +use xcm_fee_payment_runtime_api::Error as FeePaymentError; #[cfg(any(feature = "try-runtime", test))] use sp_runtime::TryRuntimeError; @@ -2363,6 +2364,37 @@ impl Pallet { AccountIdConversion::::into_account_truncating(&ID) } + pub fn query_xcm_weight(message: VersionedXcm<()>) -> Result { + let message = + Xcm::<()>::try_from(message).map_err(|_| FeePaymentError::VersionedConversionFailed)?; + + T::Weigher::weight(&mut message.into()).map_err(|()| { + log::error!(target: "xcm::pallet_xcm::query_xcm_weight", "Error when querying XCM weight"); + FeePaymentError::WeightNotComputable + }) + } + + pub fn query_delivery_fees( + destination: VersionedLocation, + message: VersionedXcm<()>, + ) -> Result { + let result_version = destination.identify_version().max(message.identify_version()); + + let destination = + destination.try_into().map_err(|_| FeePaymentError::VersionedConversionFailed)?; + + let message = message.try_into().map_err(|_| FeePaymentError::VersionedConversionFailed)?; + + let (_, fees) = validate_send::(destination, message).map_err(|error| { + log::error!(target: "xcm::pallet_xcm::query_delivery_fees", "Error when querying delivery fees: {:?}", error); + FeePaymentError::Unroutable + })?; + + VersionedAssets::from(fees) + .into_version(result_version) + .map_err(|_| FeePaymentError::VersionedConversionFailed) + } + /// Create a new expectation of a query response with the querier being here. fn do_new_query( responder: impl Into, diff --git a/polkadot/xcm/src/lib.rs b/polkadot/xcm/src/lib.rs index ba8d726aecf..86a17fa1e88 100644 --- a/polkadot/xcm/src/lib.rs +++ b/polkadot/xcm/src/lib.rs @@ -443,6 +443,16 @@ impl IntoVersion for VersionedXcm { } } +impl IdentifyVersion for VersionedXcm { + fn identify_version(&self) -> Version { + match self { + Self::V2(_) => v2::VERSION, + Self::V3(_) => v3::VERSION, + Self::V4(_) => v4::VERSION, + } + } +} + impl From> for VersionedXcm { fn from(x: v2::Xcm) -> Self { VersionedXcm::V2(x) diff --git a/polkadot/xcm/xcm-fee-payment-runtime-api/Cargo.toml b/polkadot/xcm/xcm-fee-payment-runtime-api/Cargo.toml new file mode 100644 index 00000000000..682642d13c3 --- /dev/null +++ b/polkadot/xcm/xcm-fee-payment-runtime-api/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "xcm-fee-payment-runtime-api" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license = "Apache-2.0" +repository.workspace = true +description = "XCM fee payment runtime API" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ + "derive", +] } + +sp-api = { path = "../../../substrate/primitives/api", default-features = false } +scale-info = { version = "2.10.0", default-features = false, features = [ + "derive", + "serde", +] } +sp-std = { path = "../../../substrate/primitives/std", default-features = false } +sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false } +sp-weights = { path = "../../../substrate/primitives/weights", default-features = false } +xcm = { package = "staging-xcm", path = "../", default-features = false } +frame-support = { path = "../../../substrate/frame/support", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "scale-info/std", + "sp-api/std", + "sp-runtime/std", + "sp-std/std", + "sp-weights/std", + "xcm/std", +] diff --git a/polkadot/xcm/xcm-fee-payment-runtime-api/src/lib.rs b/polkadot/xcm/xcm-fee-payment-runtime-api/src/lib.rs new file mode 100644 index 00000000000..20bf9236f1f --- /dev/null +++ b/polkadot/xcm/xcm-fee-payment-runtime-api/src/lib.rs @@ -0,0 +1,99 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Substrate 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. + +// Substrate 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 Polkadot. If not, see . + +//! Runtime API definition for xcm transaction payment. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use frame_support::pallet_prelude::TypeInfo; +use sp_std::vec::Vec; +use sp_weights::Weight; +use xcm::{Version, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}; + +sp_api::decl_runtime_apis! { + /// A trait of XCM payment API. + /// + /// API provides functionality for obtaining: + /// + /// * the weight required to execute an XCM message, + /// * a list of acceptable `AssetId`s for message execution payment, + /// * the cost of the weight in the specified acceptable `AssetId`. + /// * the fees for an XCM message delivery. + /// + /// To determine the execution weight of the calls required for + /// [`xcm::latest::Instruction::Transact`] instruction, `TransactionPaymentCallApi` can be used. + pub trait XcmPaymentApi { + /// Returns a list of acceptable payment assets. + /// + /// # Arguments + /// + /// * `xcm_version`: Version. + fn query_acceptable_payment_assets(xcm_version: Version) -> Result, Error>; + + /// Returns a weight needed to execute a XCM. + /// + /// # Arguments + /// + /// * `message`: `VersionedXcm`. + fn query_xcm_weight(message: VersionedXcm<()>) -> Result; + + /// Converts a weight into a fee for the specified `AssetId`. + /// + /// # Arguments + /// + /// * `weight`: convertible `Weight`. + /// * `asset`: `VersionedAssetId`. + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result; + + /// Get delivery fees for sending a specific `message` to a `destination`. + /// These always come in a specific asset, defined by the chain. + /// + /// # Arguments + /// * `message`: The message that'll be sent, necessary because most delivery fees are based on the + /// size of the message. + /// * `destination`: The destination to send the message to. Different destinations may use + /// different senders that charge different fees. + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result; + } +} + +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] +pub enum Error { + /// An API part is unsupported. + #[codec(index = 0)] + Unimplemented, + + /// Converting a versioned data structure from one version to another failed. + #[codec(index = 1)] + VersionedConversionFailed, + + /// XCM message weight calculation failed. + #[codec(index = 2)] + WeightNotComputable, + + /// XCM version not able to be handled. + #[codec(index = 3)] + UnhandledXcmVersion, + + /// The given asset is not handled as a fee asset. + #[codec(index = 4)] + AssetNotFound, + + /// Destination is known to be unroutable. + #[codec(index = 5)] + Unroutable, +} diff --git a/prdoc/pr_3607.prdoc b/prdoc/pr_3607.prdoc new file mode 100644 index 00000000000..1a69b25ad25 --- /dev/null +++ b/prdoc/pr_3607.prdoc @@ -0,0 +1,26 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "XCM fee payment API" + +doc: + - audience: Runtime Dev + description: | + A runtime API was added for estimating the fees required for XCM execution and delivery. + This is the basic building block needed for UIs to accurately estimate fees. + An example implementation is shown in the PR. Ideally it's simple to implement, you only need to call existing parts of your XCM config. + The API looks like so: + ```rust + fn query_acceptable_payment_assets(xcm_version: Version) -> Result, Error>; + fn query_xcm_weight(message: VersionedXcm) -> Result; + fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result; + fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result; + ``` + The first three relate to XCM execution fees, given an XCM, you can query its weight, then which assets are acceptable for buying weight and convert weight to a number of those assets. + The last one takes in a destination and a message you want to send from the runtime you're executing this on, it will give you the delivery fees. + +crates: + - name: xcm-fee-payment-runtime-api + - name: rococo-runtime + - name: westend-runtime + -- GitLab From ed907819c64fd0a185ff4109dfc7512d6162f7e9 Mon Sep 17 00:00:00 2001 From: Derek Colley Date: Tue, 26 Mar 2024 22:31:15 +0000 Subject: [PATCH 182/188] add metaspan boot node to coretime-westend.json (#3781) --- cumulus/parachains/chain-specs/coretime-westend.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cumulus/parachains/chain-specs/coretime-westend.json b/cumulus/parachains/chain-specs/coretime-westend.json index c79fd582348..adb35b8a349 100644 --- a/cumulus/parachains/chain-specs/coretime-westend.json +++ b/cumulus/parachains/chain-specs/coretime-westend.json @@ -4,7 +4,8 @@ "chainType": "Live", "bootNodes": [ "/dns/westend-coretime-collator-node-0.parity-testnet.parity.io/tcp/30333/p2p/12D3KooWP93Dzk8T7GWxyWw9jhLcz8Pksokk3R9vL2eEH337bNkT", - "/dns/westend-coretime-collator-node-1.parity-testnet.parity.io/tcp/30333/p2p/12D3KooWMh2imeAzsZKGQgm2cv6Uoep3GBYtwGfujt1bs5YfVzkH" + "/dns/westend-coretime-collator-node-1.parity-testnet.parity.io/tcp/30333/p2p/12D3KooWMh2imeAzsZKGQgm2cv6Uoep3GBYtwGfujt1bs5YfVzkH", + "/dns/boot.metaspan.io/tcp/33019/p2p/12D3KooWCa1uNnEZqiqJY9jkKNQxwSLGPeZ5MjWHhjQMGwga9JMM" ], "telemetryEndpoints": null, "protocolId": null, -- GitLab From 3fc5b826534438313d03f6e0404db44099be6d9d Mon Sep 17 00:00:00 2001 From: ordian Date: Tue, 26 Mar 2024 23:59:47 +0100 Subject: [PATCH 183/188] fix regression in approval-voting introduced in #3747 (#3831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #3826. The docs on the `candidates` field of `BlockEntry` were incorrectly stating that they are sorted by core index. The (incorrect) optimization was introduced in #3747 based on this assumption. The actual ordering is based on `CandidateIncluded` events ordering in the runtime. We revert this optimization here. - [x] verify the underlying issue - [x] add a regression test --------- Co-authored-by: Bastian Köcher --- polkadot/node/core/approval-voting/src/lib.rs | 6 +- .../approval-voting/src/persisted_entries.rs | 2 +- .../node/core/approval-voting/src/tests.rs | 167 ++++++++++++++++++ 3 files changed, 171 insertions(+), 4 deletions(-) diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index 1a62c9ee55e..76b3d476e28 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -1285,10 +1285,10 @@ fn cores_to_candidate_indices( // Map from core index to candidate index. for claimed_core_index in core_indices.iter_ones() { - // Candidates are sorted by core index. - if let Ok(candidate_index) = block_entry + if let Some(candidate_index) = block_entry .candidates() - .binary_search_by_key(&(claimed_core_index as u32), |(core_index, _)| core_index.0) + .iter() + .position(|(core_index, _)| core_index.0 == claimed_core_index as u32) { candidate_indices.push(candidate_index as _); } diff --git a/polkadot/node/core/approval-voting/src/persisted_entries.rs b/polkadot/node/core/approval-voting/src/persisted_entries.rs index b924a1b52cc..6eeb99cb99f 100644 --- a/polkadot/node/core/approval-voting/src/persisted_entries.rs +++ b/polkadot/node/core/approval-voting/src/persisted_entries.rs @@ -454,7 +454,7 @@ pub struct BlockEntry { slot: Slot, relay_vrf_story: RelayVRFStory, // The candidates included as-of this block and the index of the core they are - // leaving. Sorted ascending by core index. + // leaving. candidates: Vec<(CoreIndex, CandidateHash)>, // A bitfield where the i'th bit corresponds to the i'th candidate in `candidates`. // The i'th bit is `true` iff the candidate has been approved in the context of this diff --git a/polkadot/node/core/approval-voting/src/tests.rs b/polkadot/node/core/approval-voting/src/tests.rs index a3013eab46d..1483af56585 100644 --- a/polkadot/node/core/approval-voting/src/tests.rs +++ b/polkadot/node/core/approval-voting/src/tests.rs @@ -2479,6 +2479,173 @@ fn subsystem_import_checked_approval_sets_one_block_bit_at_a_time() { }); } +// See https://github.com/paritytech/polkadot-sdk/issues/3826 +#[test] +fn inclusion_events_can_be_unordered_by_core_index() { + let assignment_criteria = Box::new(MockAssignmentCriteria( + || { + let mut assignments = HashMap::new(); + for core in 0..3 { + let _ = assignments.insert( + CoreIndex(core), + approval_db::v2::OurAssignment { + cert: garbage_assignment_cert_v2( + AssignmentCertKindV2::RelayVRFModuloCompact { + core_bitfield: vec![CoreIndex(0), CoreIndex(1), CoreIndex(2)] + .try_into() + .unwrap(), + }, + ), + tranche: 0, + validator_index: ValidatorIndex(0), + triggered: false, + } + .into(), + ); + } + assignments + }, + |_| Ok(0), + )); + let config = HarnessConfigBuilder::default().assignment_criteria(assignment_criteria).build(); + let store = config.backend(); + + test_harness(config, |test_harness| async move { + let TestHarness { + mut virtual_overseer, + clock, + sync_oracle_handle: _sync_oracle_handle, + .. + } = test_harness; + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber(rx)) => { + rx.send(Ok(0)).unwrap(); + } + ); + + let block_hash = Hash::repeat_byte(0x01); + + let candidate_receipt0 = { + let mut receipt = dummy_candidate_receipt(block_hash); + receipt.descriptor.para_id = ParaId::from(0_u32); + receipt + }; + let candidate_receipt1 = { + let mut receipt = dummy_candidate_receipt(block_hash); + receipt.descriptor.para_id = ParaId::from(1_u32); + receipt + }; + let candidate_receipt2 = { + let mut receipt = dummy_candidate_receipt(block_hash); + receipt.descriptor.para_id = ParaId::from(2_u32); + receipt + }; + let candidate_index0 = 0; + let candidate_index1 = 1; + let candidate_index2 = 2; + + let validator0 = ValidatorIndex(0); + let validator1 = ValidatorIndex(1); + let validator2 = ValidatorIndex(2); + let validator3 = ValidatorIndex(3); + + let validators = vec![ + Sr25519Keyring::Alice, + Sr25519Keyring::Bob, + Sr25519Keyring::Charlie, + Sr25519Keyring::Dave, + Sr25519Keyring::Eve, + ]; + let session_info = SessionInfo { + validator_groups: IndexedVec::>::from(vec![ + vec![validator0, validator1], + vec![validator2], + vec![validator3], + ]), + needed_approvals: 1, + zeroth_delay_tranche_width: 1, + relay_vrf_modulo_samples: 1, + n_delay_tranches: 1, + no_show_slots: 1, + ..session_info(&validators) + }; + + ChainBuilder::new() + .add_block( + block_hash, + ChainBuilder::GENESIS_HASH, + 1, + BlockConfig { + slot: Slot::from(0), + candidates: Some(vec![ + (candidate_receipt0.clone(), CoreIndex(2), GroupIndex(2)), + (candidate_receipt1.clone(), CoreIndex(1), GroupIndex(0)), + (candidate_receipt2.clone(), CoreIndex(0), GroupIndex(1)), + ]), + session_info: Some(session_info), + end_syncing: true, + }, + ) + .build(&mut virtual_overseer) + .await; + + assert_eq!(clock.inner.lock().next_wakeup().unwrap(), 2); + clock.inner.lock().wakeup_all(100); + + assert_eq!(clock.inner.lock().wakeups.len(), 0); + + futures_timer::Delay::new(Duration::from_millis(100)).await; + + // Assignment is distributed only once from `approval-voting` + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeAssignment( + _, + c_indices, + )) => { + assert_eq!(c_indices, vec![candidate_index0, candidate_index1, candidate_index2].try_into().unwrap()); + } + ); + + // Candidate 0 + recover_available_data(&mut virtual_overseer).await; + fetch_validation_code(&mut virtual_overseer).await; + + // Candidate 1 + recover_available_data(&mut virtual_overseer).await; + fetch_validation_code(&mut virtual_overseer).await; + + // Candidate 2 + recover_available_data(&mut virtual_overseer).await; + fetch_validation_code(&mut virtual_overseer).await; + + // Check if assignment was triggered for candidate 0. + let candidate_entry = + store.load_candidate_entry(&candidate_receipt0.hash()).unwrap().unwrap(); + let our_assignment = + candidate_entry.approval_entry(&block_hash).unwrap().our_assignment().unwrap(); + assert!(our_assignment.triggered()); + + // Check if assignment was triggered for candidate 1. + let candidate_entry = + store.load_candidate_entry(&candidate_receipt1.hash()).unwrap().unwrap(); + let our_assignment = + candidate_entry.approval_entry(&block_hash).unwrap().our_assignment().unwrap(); + assert!(our_assignment.triggered()); + + // Check if assignment was triggered for candidate 2. + let candidate_entry = + store.load_candidate_entry(&candidate_receipt2.hash()).unwrap().unwrap(); + let our_assignment = + candidate_entry.approval_entry(&block_hash).unwrap().our_assignment().unwrap(); + assert!(our_assignment.triggered()); + + virtual_overseer + }); +} + fn approved_ancestor_test( skip_approval: impl Fn(BlockNumber) -> bool, approved_height: BlockNumber, -- GitLab From f394477988ac8b610862565c31dc7d3a96d73122 Mon Sep 17 00:00:00 2001 From: Javier Viola <363911+pepoviola@users.noreply.github.com> Date: Wed, 27 Mar 2024 03:45:29 +0100 Subject: [PATCH 184/188] chore: bump zombienet version (#3830) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bump version to `1.3.97` (follow up from https://github.com/paritytech/polkadot-sdk/pull/3805) --------- Co-authored-by: Bastian Köcher --- .gitlab/pipeline/zombienet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/pipeline/zombienet.yml b/.gitlab/pipeline/zombienet.yml index 8d308714fab..82341eb709f 100644 --- a/.gitlab/pipeline/zombienet.yml +++ b/.gitlab/pipeline/zombienet.yml @@ -1,7 +1,7 @@ .zombienet-refs: extends: .build-refs variables: - ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.95" + ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.98" include: # substrate tests -- GitLab From 66051adb619d2119771920218e2de75fa037d7e8 Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Wed, 27 Mar 2024 06:16:03 +0200 Subject: [PATCH 185/188] testnet genesis: enable approval voting v2 assignments and coalescing (#3827) This is a long due chore ... --------- Signed-off-by: Andrei Sandu Co-authored-by: ordian --- polkadot/node/service/src/chain_spec.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/polkadot/node/service/src/chain_spec.rs b/polkadot/node/service/src/chain_spec.rs index 1c44b17b6fd..c03ce1db094 100644 --- a/polkadot/node/service/src/chain_spec.rs +++ b/polkadot/node/service/src/chain_spec.rs @@ -123,7 +123,8 @@ fn default_parachains_host_configuration( ) -> polkadot_runtime_parachains::configuration::HostConfiguration { use polkadot_primitives::{ - vstaging::node_features::FeatureIndex, AsyncBackingParams, MAX_CODE_SIZE, MAX_POV_SIZE, + vstaging::{node_features::FeatureIndex, ApprovalVotingParams}, + AsyncBackingParams, MAX_CODE_SIZE, MAX_POV_SIZE, }; polkadot_runtime_parachains::configuration::HostConfiguration { @@ -158,7 +159,8 @@ fn default_parachains_host_configuration( allowed_ancestry_len: 2, }, node_features: bitvec::vec::BitVec::from_element( - 1u8 << (FeatureIndex::ElasticScalingMVP as usize), + 1u8 << (FeatureIndex::ElasticScalingMVP as usize) | + 1u8 << (FeatureIndex::EnableAssignmentsV2 as usize), ), scheduler_params: SchedulerParams { lookahead: 2, @@ -166,6 +168,7 @@ fn default_parachains_host_configuration( paras_availability_period: 4, ..Default::default() }, + approval_voting_params: ApprovalVotingParams { max_approval_coalesce_count: 5 }, ..Default::default() } } -- GitLab From feee773d15d5237765b520b03854d46652181de5 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Wed, 27 Mar 2024 09:31:01 +0100 Subject: [PATCH 186/188] pallet-xcm: Deprecate `execute` and `send` in favor of `execute_blob` and `send_blob` (#3749) `execute` and `send` try to decode the xcm in the parameters before reaching the filter line. The new extrinsics decode only after the filter line. These should be used instead of the old ones. ## TODO - [x] Tests - [x] Generate weights - [x] Deprecation issue -> https://github.com/paritytech/polkadot-sdk/issues/3771 - [x] PRDoc - [x] Handle error in pallet-contracts This would make writing XCMs in PJS Apps more difficult, but here's the fix for that: https://github.com/polkadot-js/apps/pull/10350. Already deployed! https://polkadot.js.org/apps/#/utilities/xcm Supersedes https://github.com/paritytech/polkadot-sdk/pull/1798/ --------- Co-authored-by: PG Herveou Co-authored-by: command-bot <> Co-authored-by: Adrian Catangiu --- Cargo.lock | 1 + .../emulated/chains/relays/westend/Cargo.toml | 1 - .../emulated/common/src/impls.rs | 6 +- .../assets/asset-hub-rococo/src/tests/send.rs | 8 +- .../assets/asset-hub-rococo/src/tests/swap.rs | 4 +- .../asset-hub-westend/src/tests/send.rs | 8 +- .../asset-hub-westend/src/tests/swap.rs | 4 +- .../bridge-hub-rococo/src/tests/send_xcm.rs | 7 +- .../bridge-hub-rococo/src/tests/snowbridge.rs | 18 +- .../bridges/bridge-hub-westend/Cargo.toml | 1 + .../bridge-hub-westend/src/tests/send_xcm.rs | 7 +- .../src/weights/pallet_xcm.rs | 112 ++++++---- .../src/weights/pallet_xcm.rs | 114 ++++++---- .../src/weights/pallet_xcm.rs | 108 ++++++---- .../src/weights/pallet_xcm.rs | 108 ++++++---- .../src/weights/pallet_xcm.rs | 106 +++++---- .../coretime-rococo/src/weights/pallet_xcm.rs | 102 +++++---- .../src/weights/pallet_xcm.rs | 102 +++++---- .../people-rococo/src/weights/pallet_xcm.rs | 102 +++++---- .../people-westend/src/weights/pallet_xcm.rs | 102 +++++---- polkadot/runtime/rococo/src/impls.rs | 9 +- .../runtime/rococo/src/weights/pallet_xcm.rs | 110 ++++++---- polkadot/runtime/westend/src/impls.rs | 9 +- .../runtime/westend/src/weights/pallet_xcm.rs | 108 ++++++---- polkadot/xcm/pallet-xcm/src/benchmarking.rs | 29 +++ polkadot/xcm/pallet-xcm/src/lib.rs | 202 +++++++++++++----- polkadot/xcm/pallet-xcm/src/tests/mod.rs | 77 ++++--- polkadot/xcm/src/lib.rs | 3 + polkadot/xcm/src/v4/mod.rs | 20 +- polkadot/xcm/xcm-builder/src/controller.rs | 39 ++-- polkadot/xcm/xcm-builder/src/lib.rs | 2 +- prdoc/pr_3749.prdoc | 47 ++++ .../frame/contracts/mock-network/src/tests.rs | 40 +--- substrate/frame/contracts/src/lib.rs | 3 + substrate/frame/contracts/src/wasm/runtime.rs | 54 +---- substrate/frame/contracts/uapi/src/host.rs | 2 +- 36 files changed, 1133 insertions(+), 642 deletions(-) create mode 100644 prdoc/pr_3749.prdoc diff --git a/Cargo.lock b/Cargo.lock index f246a978fd2..2382dc8d162 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2148,6 +2148,7 @@ dependencies = [ "pallet-message-queue", "pallet-xcm", "parachains-common", + "parity-scale-codec", "rococo-westend-system-emulated-network", "sp-runtime", "staging-xcm", diff --git a/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml index 20aedb50e6a..12a3ad60e0e 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/chains/relays/westend/Cargo.toml @@ -11,7 +11,6 @@ publish = false workspace = true [dependencies] - # Substrate sp-core = { path = "../../../../../../../substrate/primitives/core", default-features = false } sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs index ae69bf991e5..618c3addc5d 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -362,7 +362,7 @@ macro_rules! impl_send_transact_helpers_for_relay_chain { recipient: $crate::impls::ParaId, call: $crate::impls::DoubleEncoded<()> ) { - use $crate::impls::{bx, Chain, RelayChain}; + use $crate::impls::{bx, Chain, RelayChain, Encode}; ::execute_with(|| { let root_origin = ::RuntimeOrigin::root(); @@ -370,10 +370,10 @@ macro_rules! impl_send_transact_helpers_for_relay_chain { let xcm = $crate::impls::xcm_transact_unpaid_execution(call, $crate::impls::OriginKind::Superuser); // Send XCM `Transact` - $crate::impls::assert_ok!(]>::XcmPallet::send( + $crate::impls::assert_ok!(]>::XcmPallet::send_blob( root_origin, bx!(destination.into()), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); Self::assert_xcm_pallet_sent(); }); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs index 364fbd0d439..1d120f1dc4c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/send.rs @@ -75,10 +75,10 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_system_assets_works() { )]); PenpalA::execute_with(|| { - assert_ok!(::PolkadotXcm::send( + assert_ok!(::PolkadotXcm::send_blob( root_origin, bx!(system_para_destination), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); PenpalA::assert_xcm_pallet_sent(); @@ -159,10 +159,10 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { )]); PenpalA::execute_with(|| { - assert_ok!(::PolkadotXcm::send( + assert_ok!(::PolkadotXcm::send_blob( root_origin, bx!(system_para_destination), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); PenpalA::assert_xcm_pallet_sent(); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs index 87f0b3d9f90..e13300b7c11 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/swap.rs @@ -370,10 +370,10 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { penpal.clone(), ); - assert_ok!(::PolkadotXcm::send( + assert_ok!(::PolkadotXcm::send_blob( penpal_root, bx!(asset_hub_location), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); PenpalA::assert_xcm_pallet_sent(); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs index eb0e985cc0c..f218b539c38 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/send.rs @@ -75,10 +75,10 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_system_assets_works() { )]); PenpalA::execute_with(|| { - assert_ok!(::PolkadotXcm::send( + assert_ok!(::PolkadotXcm::send_blob( root_origin, bx!(system_para_destination), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); PenpalA::assert_xcm_pallet_sent(); @@ -159,10 +159,10 @@ fn send_xcm_from_para_to_system_para_paying_fee_with_assets_works() { )]); PenpalA::execute_with(|| { - assert_ok!(::PolkadotXcm::send( + assert_ok!(::PolkadotXcm::send_blob( root_origin, bx!(system_para_destination), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); PenpalA::assert_xcm_pallet_sent(); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs index 04740d31158..aa673c03483 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/swap.rs @@ -369,10 +369,10 @@ fn pay_xcm_fee_with_some_asset_swapped_for_native() { penpal.clone(), ); - assert_ok!(::PolkadotXcm::send( + assert_ok!(::PolkadotXcm::send_blob( penpal_root, bx!(asset_hub_location), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); PenpalA::assert_xcm_pallet_sent(); diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs index a1d871cdb61..4bd041dc03f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs @@ -14,6 +14,7 @@ // limitations under the License. use crate::tests::*; +use codec::Encode; #[test] fn send_xcm_from_rococo_relay_to_westend_asset_hub_should_fail_on_not_applicable() { @@ -26,7 +27,7 @@ fn send_xcm_from_rococo_relay_to_westend_asset_hub_should_fail_on_not_applicable let remote_xcm = Xcm(vec![ClearOrigin]); - let xcm = VersionedXcm::from(Xcm(vec![ + let xcm = VersionedXcm::from(Xcm::<()>(vec![ UnpaidExecution { weight_limit, check_origin }, ExportMessage { network: WestendId.into(), @@ -38,10 +39,10 @@ fn send_xcm_from_rococo_relay_to_westend_asset_hub_should_fail_on_not_applicable // Rococo Global Consensus // Send XCM message from Relay Chain to Bridge Hub source Parachain Rococo::execute_with(|| { - assert_ok!(::XcmPallet::send( + assert_ok!(::XcmPallet::send_blob( sudo_origin, bx!(destination), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); type RuntimeEvent = ::RuntimeEvent; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index 26b82375e07..caaf24e00a8 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -83,7 +83,7 @@ fn create_agent() { let create_agent_call = SnowbridgeControl::Control(ControlCall::CreateAgent {}); // Construct XCM to create an agent for para 1001 - let remote_xcm = VersionedXcm::from(Xcm(vec![ + let remote_xcm = VersionedXcm::from(Xcm::<()>(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, DescendOrigin(Parachain(origin_para).into()), Transact { @@ -96,10 +96,10 @@ fn create_agent() { // Rococo Global Consensus // Send XCM message from Relay Chain to Bridge Hub source Parachain Rococo::execute_with(|| { - assert_ok!(::XcmPallet::send( + assert_ok!(::XcmPallet::send_blob( sudo_origin, bx!(destination), - bx!(remote_xcm), + remote_xcm.encode().try_into().unwrap(), )); type RuntimeEvent = ::RuntimeEvent; @@ -141,7 +141,7 @@ fn create_channel() { let create_agent_call = SnowbridgeControl::Control(ControlCall::CreateAgent {}); // Construct XCM to create an agent for para 1001 - let create_agent_xcm = VersionedXcm::from(Xcm(vec![ + let create_agent_xcm = VersionedXcm::from(Xcm::<()>(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, DescendOrigin(Parachain(origin_para).into()), Transact { @@ -154,7 +154,7 @@ fn create_channel() { let create_channel_call = SnowbridgeControl::Control(ControlCall::CreateChannel { mode: OperatingMode::Normal }); // Construct XCM to create a channel for para 1001 - let create_channel_xcm = VersionedXcm::from(Xcm(vec![ + let create_channel_xcm = VersionedXcm::from(Xcm::<()>(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, DescendOrigin(Parachain(origin_para).into()), Transact { @@ -167,16 +167,16 @@ fn create_channel() { // Rococo Global Consensus // Send XCM message from Relay Chain to Bridge Hub source Parachain Rococo::execute_with(|| { - assert_ok!(::XcmPallet::send( + assert_ok!(::XcmPallet::send_blob( sudo_origin.clone(), bx!(destination.clone()), - bx!(create_agent_xcm), + create_agent_xcm.encode().try_into().unwrap(), )); - assert_ok!(::XcmPallet::send( + assert_ok!(::XcmPallet::send_blob( sudo_origin, bx!(destination), - bx!(create_channel_xcm), + create_channel_xcm.encode().try_into().unwrap(), )); type RuntimeEvent = ::RuntimeEvent; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml index 9059d841a48..9c45a7adeb4 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml @@ -11,6 +11,7 @@ publish = false workspace = true [dependencies] +codec = { package = "parity-scale-codec", version = "3.6.0" } # Substrate frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs index b01be5e8dc8..f69747c1770 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs @@ -14,6 +14,7 @@ // limitations under the License. use crate::tests::*; +use codec::Encode; #[test] fn send_xcm_from_westend_relay_to_rococo_asset_hub_should_fail_on_not_applicable() { @@ -26,7 +27,7 @@ fn send_xcm_from_westend_relay_to_rococo_asset_hub_should_fail_on_not_applicable let remote_xcm = Xcm(vec![ClearOrigin]); - let xcm = VersionedXcm::from(Xcm(vec![ + let xcm = VersionedXcm::from(Xcm::<()>(vec![ UnpaidExecution { weight_limit, check_origin }, ExportMessage { network: RococoId, @@ -38,10 +39,10 @@ fn send_xcm_from_westend_relay_to_rococo_asset_hub_should_fail_on_not_applicable // Westend Global Consensus // Send XCM message from Relay Chain to Bridge Hub source Parachain Westend::execute_with(|| { - assert_ok!(::XcmPallet::send( + assert_ok!(::XcmPallet::send_blob( sudo_origin, bx!(destination), - bx!(xcm), + xcm.encode().try_into().unwrap(), )); type RuntimeEvent = ::RuntimeEvent; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm.rs index 51b6543bae8..e0e231d7da2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,30 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 22_136_000 picoseconds. - Weight::from_parts(22_518_000, 0) + // Minimum execution time: 21_224_000 picoseconds. + Weight::from_parts(21_821_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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) + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 21_474_000 picoseconds. + Weight::from_parts(22_072_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +112,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 92_277_000 picoseconds. - Weight::from_parts(94_843_000, 0) + // Minimum execution time: 90_677_000 picoseconds. + Weight::from_parts(93_658_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -118,8 +140,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `400` // Estimated: `6196` - // Minimum execution time: 120_110_000 picoseconds. - Weight::from_parts(122_968_000, 0) + // Minimum execution time: 116_767_000 picoseconds. + Weight::from_parts(118_843_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) @@ -148,8 +170,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `496` // Estimated: `6208` - // Minimum execution time: 143_116_000 picoseconds. - Weight::from_parts(147_355_000, 0) + // Minimum execution time: 137_983_000 picoseconds. + Weight::from_parts(141_396_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(7)) @@ -164,14 +186,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_517_000 picoseconds. - Weight::from_parts(6_756_000, 0) + // Minimum execution time: 6_232_000 picoseconds. + Weight::from_parts(6_507_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -181,8 +213,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_894_000 picoseconds. - Weight::from_parts(2_024_000, 0) + // Minimum execution time: 1_884_000 picoseconds. + Weight::from_parts(2_016_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -208,8 +240,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 27_314_000 picoseconds. - Weight::from_parts(28_787_000, 0) + // Minimum execution time: 26_637_000 picoseconds. + Weight::from_parts(27_616_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -234,8 +266,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `363` // Estimated: `3828` - // Minimum execution time: 29_840_000 picoseconds. - Weight::from_parts(30_589_000, 0) + // Minimum execution time: 28_668_000 picoseconds. + Weight::from_parts(29_413_000, 0) .saturating_add(Weight::from_parts(0, 3828)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -246,8 +278,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_893_000 picoseconds. - Weight::from_parts(2_017_000, 0) + // Minimum execution time: 1_990_000 picoseconds. + Weight::from_parts(2_114_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -257,8 +289,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `159` // Estimated: `13524` - // Minimum execution time: 19_211_000 picoseconds. - Weight::from_parts(19_552_000, 0) + // Minimum execution time: 18_856_000 picoseconds. + Weight::from_parts(19_430_000, 0) .saturating_add(Weight::from_parts(0, 13524)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -269,8 +301,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `163` // Estimated: `13528` - // Minimum execution time: 19_177_000 picoseconds. - Weight::from_parts(19_704_000, 0) + // Minimum execution time: 19_068_000 picoseconds. + Weight::from_parts(19_434_000, 0) .saturating_add(Weight::from_parts(0, 13528)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -281,8 +313,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `173` // Estimated: `16013` - // Minimum execution time: 20_449_000 picoseconds. - Weight::from_parts(21_075_000, 0) + // Minimum execution time: 21_055_000 picoseconds. + Weight::from_parts(21_379_000, 0) .saturating_add(Weight::from_parts(0, 16013)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -304,8 +336,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `6152` - // Minimum execution time: 26_578_000 picoseconds. - Weight::from_parts(27_545_000, 0) + // Minimum execution time: 25_736_000 picoseconds. + Weight::from_parts(26_423_000, 0) .saturating_add(Weight::from_parts(0, 6152)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -316,8 +348,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `206` // Estimated: `11096` - // Minimum execution time: 11_646_000 picoseconds. - Weight::from_parts(11_944_000, 0) + // Minimum execution time: 11_853_000 picoseconds. + Weight::from_parts(12_215_000, 0) .saturating_add(Weight::from_parts(0, 11096)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -327,8 +359,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `170` // Estimated: `13535` - // Minimum execution time: 19_301_000 picoseconds. - Weight::from_parts(19_664_000, 0) + // Minimum execution time: 19_418_000 picoseconds. + Weight::from_parts(19_794_000, 0) .saturating_add(Weight::from_parts(0, 13535)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -351,8 +383,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `13577` - // Minimum execution time: 35_715_000 picoseconds. - Weight::from_parts(36_915_000, 0) + // Minimum execution time: 34_719_000 picoseconds. + Weight::from_parts(35_260_000, 0) .saturating_add(Weight::from_parts(0, 13577)) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) @@ -365,8 +397,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `1588` - // Minimum execution time: 4_871_000 picoseconds. - Weight::from_parts(5_066_000, 0) + // Minimum execution time: 4_937_000 picoseconds. + Weight::from_parts(5_203_000, 0) .saturating_add(Weight::from_parts(0, 1588)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -377,8 +409,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7740` // Estimated: `11205` - // Minimum execution time: 25_150_000 picoseconds. - Weight::from_parts(26_119_000, 0) + // Minimum execution time: 26_064_000 picoseconds. + Weight::from_parts(26_497_000, 0) .saturating_add(Weight::from_parts(0, 11205)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -389,8 +421,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `160` // Estimated: `3625` - // Minimum execution time: 38_248_000 picoseconds. - Weight::from_parts(39_122_000, 0) + // Minimum execution time: 37_132_000 picoseconds. + Weight::from_parts(37_868_000, 0) .saturating_add(Weight::from_parts(0, 3625)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm.rs index 71facff87d3..299e4b8b3cd 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,30 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 21_630_000 picoseconds. - Weight::from_parts(22_306_000, 0) + // Minimum execution time: 21_722_000 picoseconds. + Weight::from_parts(22_253_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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) + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 21_694_000 picoseconds. + Weight::from_parts(22_326_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +112,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 91_802_000 picoseconds. - Weight::from_parts(93_672_000, 0) + // Minimum execution time: 94_422_000 picoseconds. + Weight::from_parts(96_997_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -118,8 +140,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `367` // Estimated: `6196` - // Minimum execution time: 118_930_000 picoseconds. - Weight::from_parts(122_306_000, 0) + // Minimum execution time: 123_368_000 picoseconds. + Weight::from_parts(125_798_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) @@ -148,8 +170,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `496` // Estimated: `6208` - // Minimum execution time: 140_527_000 picoseconds. - Weight::from_parts(144_501_000, 0) + // Minimum execution time: 142_033_000 picoseconds. + Weight::from_parts(145_702_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(7)) @@ -158,8 +180,16 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_556_000 picoseconds. - Weight::from_parts(7_798_000, 0) + // Minimum execution time: 7_558_000 picoseconds. + Weight::from_parts(7_916_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn execute_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_978_000 picoseconds. + Weight::from_parts(8_210_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) @@ -168,8 +198,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_373_000 picoseconds. - Weight::from_parts(6_603_000, 0) + // Minimum execution time: 6_439_000 picoseconds. + Weight::from_parts(6_711_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -179,8 +209,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_941_000 picoseconds. - Weight::from_parts(2_088_000, 0) + // Minimum execution time: 1_982_000 picoseconds. + Weight::from_parts(2_260_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -206,8 +236,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 27_080_000 picoseconds. - Weight::from_parts(27_820_000, 0) + // Minimum execution time: 27_120_000 picoseconds. + Weight::from_parts(28_048_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -232,8 +262,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `363` // Estimated: `3828` - // Minimum execution time: 28_850_000 picoseconds. - Weight::from_parts(29_506_000, 0) + // Minimum execution time: 29_354_000 picoseconds. + Weight::from_parts(30_205_000, 0) .saturating_add(Weight::from_parts(0, 3828)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -244,8 +274,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_033_000 picoseconds. - Weight::from_parts(2_201_000, 0) + // Minimum execution time: 1_926_000 picoseconds. + Weight::from_parts(2_013_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -255,8 +285,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `159` // Estimated: `13524` - // Minimum execution time: 18_844_000 picoseconds. - Weight::from_parts(19_197_000, 0) + // Minimum execution time: 18_611_000 picoseconds. + Weight::from_parts(19_120_000, 0) .saturating_add(Weight::from_parts(0, 13524)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -267,8 +297,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `163` // Estimated: `13528` - // Minimum execution time: 18_940_000 picoseconds. - Weight::from_parts(19_450_000, 0) + // Minimum execution time: 18_373_000 picoseconds. + Weight::from_parts(18_945_000, 0) .saturating_add(Weight::from_parts(0, 13528)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -279,8 +309,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `173` // Estimated: `16013` - // Minimum execution time: 20_521_000 picoseconds. - Weight::from_parts(21_076_000, 0) + // Minimum execution time: 20_459_000 picoseconds. + Weight::from_parts(20_951_000, 0) .saturating_add(Weight::from_parts(0, 16013)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -302,8 +332,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `6152` - // Minimum execution time: 26_007_000 picoseconds. - Weight::from_parts(26_448_000, 0) + // Minimum execution time: 26_003_000 picoseconds. + Weight::from_parts(26_678_000, 0) .saturating_add(Weight::from_parts(0, 6152)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -314,8 +344,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `206` // Estimated: `11096` - // Minimum execution time: 11_584_000 picoseconds. - Weight::from_parts(12_080_000, 0) + // Minimum execution time: 11_557_000 picoseconds. + Weight::from_parts(11_868_000, 0) .saturating_add(Weight::from_parts(0, 11096)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -325,8 +355,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `170` // Estimated: `13535` - // Minimum execution time: 19_157_000 picoseconds. - Weight::from_parts(19_513_000, 0) + // Minimum execution time: 18_710_000 picoseconds. + Weight::from_parts(19_240_000, 0) .saturating_add(Weight::from_parts(0, 13535)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -349,8 +379,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `13577` - // Minimum execution time: 34_878_000 picoseconds. - Weight::from_parts(35_623_000, 0) + // Minimum execution time: 34_393_000 picoseconds. + Weight::from_parts(35_138_000, 0) .saturating_add(Weight::from_parts(0, 13577)) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) @@ -363,8 +393,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `1588` - // Minimum execution time: 3_900_000 picoseconds. - Weight::from_parts(4_161_000, 0) + // Minimum execution time: 4_043_000 picoseconds. + Weight::from_parts(4_216_000, 0) .saturating_add(Weight::from_parts(0, 1588)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -375,8 +405,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7740` // Estimated: `11205` - // Minimum execution time: 25_731_000 picoseconds. - Weight::from_parts(26_160_000, 0) + // Minimum execution time: 25_410_000 picoseconds. + Weight::from_parts(26_019_000, 0) .saturating_add(Weight::from_parts(0, 11205)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -387,8 +417,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `160` // Estimated: `3625` - // Minimum execution time: 37_251_000 picoseconds. - Weight::from_parts(38_075_000, 0) + // Minimum execution time: 38_850_000 picoseconds. + Weight::from_parts(39_593_000, 0) .saturating_add(Weight::from_parts(0, 3625)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_xcm.rs index a732e1a5734..adfaa9ea202 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,30 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 18_513_000 picoseconds. - Weight::from_parts(19_156_000, 0) + // Minimum execution time: 18_732_000 picoseconds. + Weight::from_parts(19_386_000, 0) + .saturating_add(Weight::from_parts(0, 3503)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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) + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `38` + // Estimated: `3503` + // Minimum execution time: 18_943_000 picoseconds. + Weight::from_parts(19_455_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +112,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `70` // Estimated: `3593` - // Minimum execution time: 88_096_000 picoseconds. - Weight::from_parts(89_732_000, 0) + // Minimum execution time: 88_917_000 picoseconds. + Weight::from_parts(91_611_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -126,8 +148,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `70` // Estimated: `3593` - // Minimum execution time: 88_239_000 picoseconds. - Weight::from_parts(89_729_000, 0) + // Minimum execution time: 88_587_000 picoseconds. + Weight::from_parts(90_303_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -142,14 +164,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_955_000 picoseconds. - Weight::from_parts(6_266_000, 0) + // Minimum execution time: 5_856_000 picoseconds. + Weight::from_parts(6_202_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -159,8 +191,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_868_000 picoseconds. - Weight::from_parts(1_961_000, 0) + // Minimum execution time: 1_797_000 picoseconds. + Weight::from_parts(1_970_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -186,8 +218,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 24_388_000 picoseconds. - Weight::from_parts(25_072_000, 0) + // Minimum execution time: 24_479_000 picoseconds. + Weight::from_parts(25_058_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -212,8 +244,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `255` // Estimated: `3720` - // Minimum execution time: 26_762_000 picoseconds. - Weight::from_parts(27_631_000, 0) + // Minimum execution time: 27_282_000 picoseconds. + Weight::from_parts(27_924_000, 0) .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -224,8 +256,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_856_000 picoseconds. - Weight::from_parts(2_033_000, 0) + // Minimum execution time: 1_801_000 picoseconds. + Weight::from_parts(1_988_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -235,8 +267,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 17_718_000 picoseconds. - Weight::from_parts(18_208_000, 0) + // Minimum execution time: 16_509_000 picoseconds. + Weight::from_parts(16_939_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -247,8 +279,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 17_597_000 picoseconds. - Weight::from_parts(18_090_000, 0) + // Minimum execution time: 16_140_000 picoseconds. + Weight::from_parts(16_843_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -259,8 +291,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 19_533_000 picoseconds. - Weight::from_parts(20_164_000, 0) + // Minimum execution time: 18_160_000 picoseconds. + Weight::from_parts(18_948_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -282,8 +314,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `6046` - // Minimum execution time: 24_958_000 picoseconds. - Weight::from_parts(25_628_000, 0) + // Minimum execution time: 24_409_000 picoseconds. + Weight::from_parts(25_261_000, 0) .saturating_add(Weight::from_parts(0, 6046)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -294,8 +326,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 12_209_000 picoseconds. - Weight::from_parts(12_612_000, 0) + // Minimum execution time: 10_848_000 picoseconds. + Weight::from_parts(11_241_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -305,8 +337,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 17_844_000 picoseconds. - Weight::from_parts(18_266_000, 0) + // Minimum execution time: 16_609_000 picoseconds. + Weight::from_parts(17_044_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -329,8 +361,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `13471` - // Minimum execution time: 34_131_000 picoseconds. - Weight::from_parts(34_766_000, 0) + // Minimum execution time: 32_500_000 picoseconds. + Weight::from_parts(33_475_000, 0) .saturating_add(Weight::from_parts(0, 13471)) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) @@ -343,8 +375,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_525_000 picoseconds. - Weight::from_parts(3_724_000, 0) + // Minimum execution time: 3_484_000 picoseconds. + Weight::from_parts(3_673_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -355,8 +387,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 24_975_000 picoseconds. - Weight::from_parts(25_517_000, 0) + // Minimum execution time: 25_225_000 picoseconds. + Weight::from_parts(25_731_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -367,8 +399,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 33_761_000 picoseconds. - Weight::from_parts(34_674_000, 0) + // Minimum execution time: 33_961_000 picoseconds. + Weight::from_parts(34_818_000, 0) .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_xcm.rs index a78ff2355ef..9cf4c61466a 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,30 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 19_527_000 picoseconds. - Weight::from_parts(19_839_000, 0) + // Minimum execution time: 19_702_000 picoseconds. + Weight::from_parts(20_410_000, 0) + .saturating_add(Weight::from_parts(0, 3503)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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) + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `38` + // Estimated: `3503` + // Minimum execution time: 19_525_000 picoseconds. + Weight::from_parts(20_071_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +112,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `107` // Estimated: `3593` - // Minimum execution time: 90_938_000 picoseconds. - Weight::from_parts(92_822_000, 0) + // Minimum execution time: 91_793_000 picoseconds. + Weight::from_parts(93_761_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -126,8 +148,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `107` // Estimated: `3593` - // Minimum execution time: 90_133_000 picoseconds. - Weight::from_parts(92_308_000, 0) + // Minimum execution time: 91_819_000 picoseconds. + Weight::from_parts(93_198_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -142,14 +164,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_205_000 picoseconds. - Weight::from_parts(6_595_000, 0) + // Minimum execution time: 6_183_000 picoseconds. + Weight::from_parts(6_598_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -159,8 +191,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_927_000 picoseconds. - Weight::from_parts(2_062_000, 0) + // Minimum execution time: 1_987_000 picoseconds. + Weight::from_parts(2_076_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -186,8 +218,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 25_078_000 picoseconds. - Weight::from_parts(25_782_000, 0) + // Minimum execution time: 25_375_000 picoseconds. + Weight::from_parts(26_165_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -212,8 +244,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `255` // Estimated: `3720` - // Minimum execution time: 28_188_000 picoseconds. - Weight::from_parts(28_826_000, 0) + // Minimum execution time: 28_167_000 picoseconds. + Weight::from_parts(28_792_000, 0) .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -224,8 +256,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_886_000 picoseconds. - Weight::from_parts(1_991_000, 0) + // Minimum execution time: 2_039_000 picoseconds. + Weight::from_parts(2_211_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -235,8 +267,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 17_443_000 picoseconds. - Weight::from_parts(17_964_000, 0) + // Minimum execution time: 17_127_000 picoseconds. + Weight::from_parts(17_519_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -247,8 +279,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 17_357_000 picoseconds. - Weight::from_parts(18_006_000, 0) + // Minimum execution time: 16_701_000 picoseconds. + Weight::from_parts(17_250_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -259,8 +291,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 18_838_000 picoseconds. - Weight::from_parts(19_688_000, 0) + // Minimum execution time: 18_795_000 picoseconds. + Weight::from_parts(19_302_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -282,8 +314,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `6046` - // Minimum execution time: 25_517_000 picoseconds. - Weight::from_parts(26_131_000, 0) + // Minimum execution time: 25_007_000 picoseconds. + Weight::from_parts(25_786_000, 0) .saturating_add(Weight::from_parts(0, 6046)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -294,8 +326,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 11_587_000 picoseconds. - Weight::from_parts(11_963_000, 0) + // Minimum execution time: 11_534_000 picoseconds. + Weight::from_parts(11_798_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -305,8 +337,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 17_490_000 picoseconds. - Weight::from_parts(18_160_000, 0) + // Minimum execution time: 17_357_000 picoseconds. + Weight::from_parts(17_629_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -329,8 +361,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `13471` - // Minimum execution time: 34_088_000 picoseconds. - Weight::from_parts(34_598_000, 0) + // Minimum execution time: 33_487_000 picoseconds. + Weight::from_parts(34_033_000, 0) .saturating_add(Weight::from_parts(0, 13471)) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) @@ -343,8 +375,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_566_000 picoseconds. - Weight::from_parts(3_754_000, 0) + // Minimum execution time: 3_688_000 picoseconds. + Weight::from_parts(3_854_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -355,8 +387,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 25_078_000 picoseconds. - Weight::from_parts(25_477_000, 0) + // Minimum execution time: 26_336_000 picoseconds. + Weight::from_parts(26_873_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -367,8 +399,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 34_661_000 picoseconds. - Weight::from_parts(35_411_000, 0) + // Minimum execution time: 34_633_000 picoseconds. + Weight::from_parts(35_171_000, 0) .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs index 5d427d85004..0edd5dfff2b 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,30 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 21_813_000 picoseconds. - Weight::from_parts(22_332_000, 0) + // Minimum execution time: 21_911_000 picoseconds. + Weight::from_parts(22_431_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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) + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 22_143_000 picoseconds. + Weight::from_parts(22_843_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -90,8 +112,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `214` // Estimated: `3679` - // Minimum execution time: 93_243_000 picoseconds. - Weight::from_parts(95_650_000, 0) + // Minimum execution time: 96_273_000 picoseconds. + Weight::from_parts(98_351_000, 0) .saturating_add(Weight::from_parts(0, 3679)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -126,8 +148,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `214` // Estimated: `3679` - // Minimum execution time: 96_199_000 picoseconds. - Weight::from_parts(98_620_000, 0) + // Minimum execution time: 95_571_000 picoseconds. + Weight::from_parts(96_251_000, 0) .saturating_add(Weight::from_parts(0, 3679)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -142,14 +164,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_442_000 picoseconds. - Weight::from_parts(6_682_000, 0) + // Minimum execution time: 6_227_000 picoseconds. + Weight::from_parts(6_419_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -159,8 +191,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_833_000 picoseconds. - Weight::from_parts(1_973_000, 0) + // Minimum execution time: 1_851_000 picoseconds. + Weight::from_parts(1_940_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -186,8 +218,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `145` // Estimated: `3610` - // Minimum execution time: 27_318_000 picoseconds. - Weight::from_parts(28_224_000, 0) + // Minimum execution time: 27_449_000 picoseconds. + Weight::from_parts(28_513_000, 0) .saturating_add(Weight::from_parts(0, 3610)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -212,8 +244,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `363` // Estimated: `3828` - // Minimum execution time: 29_070_000 picoseconds. - Weight::from_parts(30_205_000, 0) + // Minimum execution time: 29_477_000 picoseconds. + Weight::from_parts(30_251_000, 0) .saturating_add(Weight::from_parts(0, 3828)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) @@ -224,8 +256,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_904_000 picoseconds. - Weight::from_parts(2_033_000, 0) + // Minimum execution time: 1_894_000 picoseconds. + Weight::from_parts(2_009_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -235,8 +267,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `159` // Estimated: `13524` - // Minimum execution time: 18_348_000 picoseconds. - Weight::from_parts(18_853_000, 0) + // Minimum execution time: 17_991_000 picoseconds. + Weight::from_parts(18_651_000, 0) .saturating_add(Weight::from_parts(0, 13524)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -247,8 +279,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `163` // Estimated: `13528` - // Minimum execution time: 17_964_000 picoseconds. - Weight::from_parts(18_548_000, 0) + // Minimum execution time: 18_321_000 picoseconds. + Weight::from_parts(18_701_000, 0) .saturating_add(Weight::from_parts(0, 13528)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -259,8 +291,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `173` // Estimated: `16013` - // Minimum execution time: 19_708_000 picoseconds. - Weight::from_parts(20_157_000, 0) + // Minimum execution time: 19_762_000 picoseconds. + Weight::from_parts(20_529_000, 0) .saturating_add(Weight::from_parts(0, 16013)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -282,8 +314,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `6152` - // Minimum execution time: 26_632_000 picoseconds. - Weight::from_parts(27_314_000, 0) + // Minimum execution time: 26_927_000 picoseconds. + Weight::from_parts(27_629_000, 0) .saturating_add(Weight::from_parts(0, 6152)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) @@ -294,8 +326,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `206` // Estimated: `11096` - // Minimum execution time: 11_929_000 picoseconds. - Weight::from_parts(12_304_000, 0) + // Minimum execution time: 11_957_000 picoseconds. + Weight::from_parts(12_119_000, 0) .saturating_add(Weight::from_parts(0, 11096)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -305,8 +337,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `170` // Estimated: `13535` - // Minimum execution time: 18_599_000 picoseconds. - Weight::from_parts(19_195_000, 0) + // Minimum execution time: 17_942_000 picoseconds. + Weight::from_parts(18_878_000, 0) .saturating_add(Weight::from_parts(0, 13535)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -329,8 +361,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `212` // Estimated: `13577` - // Minimum execution time: 35_524_000 picoseconds. - Weight::from_parts(36_272_000, 0) + // Minimum execution time: 35_640_000 picoseconds. + Weight::from_parts(36_340_000, 0) .saturating_add(Weight::from_parts(0, 13577)) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) @@ -344,7 +376,7 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Measured: `103` // Estimated: `1588` // Minimum execution time: 4_044_000 picoseconds. - Weight::from_parts(4_238_000, 0) + Weight::from_parts(4_229_000, 0) .saturating_add(Weight::from_parts(0, 1588)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -355,8 +387,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7740` // Estimated: `11205` - // Minimum execution time: 25_741_000 picoseconds. - Weight::from_parts(26_301_000, 0) + // Minimum execution time: 26_262_000 picoseconds. + Weight::from_parts(26_842_000, 0) .saturating_add(Weight::from_parts(0, 11205)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -367,8 +399,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `160` // Estimated: `3625` - // Minimum execution time: 35_925_000 picoseconds. - Weight::from_parts(36_978_000, 0) + // Minimum execution time: 36_775_000 picoseconds. + Weight::from_parts(37_265_000, 0) .saturating_add(Weight::from_parts(0, 3625)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs index c5d315467c1..df0044089c8 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -62,8 +62,28 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 35_051_000 picoseconds. - Weight::from_parts(35_200_000, 0) + // Minimum execution time: 18_767_000 picoseconds. + Weight::from_parts(19_420_000, 0) + .saturating_add(Weight::from_parts(0, 3539)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `74` + // Estimated: `3539` + // Minimum execution time: 19_184_000 picoseconds. + Weight::from_parts(19_695_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -84,8 +104,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 56_235_000 picoseconds. - Weight::from_parts(58_178_000, 0) + // Minimum execution time: 58_120_000 picoseconds. + Weight::from_parts(59_533_000, 0) .saturating_add(Weight::from_parts(0, 3571)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -120,14 +140,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_226_000 picoseconds. - Weight::from_parts(6_403_000, 0) + // Minimum execution time: 6_074_000 picoseconds. + Weight::from_parts(6_398_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -137,8 +167,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_020_000 picoseconds. - Weight::from_parts(2_100_000, 0) + // Minimum execution time: 2_036_000 picoseconds. + Weight::from_parts(2_180_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -162,8 +192,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 24_387_000 picoseconds. - Weight::from_parts(24_814_000, 0) + // Minimum execution time: 25_014_000 picoseconds. + Weight::from_parts(25_374_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) @@ -186,8 +216,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `292` // Estimated: `3757` - // Minimum execution time: 27_039_000 picoseconds. - Weight::from_parts(27_693_000, 0) + // Minimum execution time: 27_616_000 picoseconds. + Weight::from_parts(28_499_000, 0) .saturating_add(Weight::from_parts(0, 3757)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -198,8 +228,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_920_000 picoseconds. - Weight::from_parts(2_082_000, 0) + // Minimum execution time: 2_061_000 picoseconds. + Weight::from_parts(2_153_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -209,8 +239,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 17_141_000 picoseconds. - Weight::from_parts(17_500_000, 0) + // Minimum execution time: 16_592_000 picoseconds. + Weight::from_parts(16_900_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -221,8 +251,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 17_074_000 picoseconds. - Weight::from_parts(17_431_000, 0) + // Minimum execution time: 16_694_000 picoseconds. + Weight::from_parts(16_905_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -233,8 +263,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 19_139_000 picoseconds. - Weight::from_parts(19_474_000, 0) + // Minimum execution time: 17_779_000 picoseconds. + Weight::from_parts(18_490_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -254,8 +284,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `6082` - // Minimum execution time: 24_346_000 picoseconds. - Weight::from_parts(25_318_000, 0) + // Minimum execution time: 24_526_000 picoseconds. + Weight::from_parts(25_182_000, 0) .saturating_add(Weight::from_parts(0, 6082)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -266,8 +296,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 11_777_000 picoseconds. - Weight::from_parts(12_051_000, 0) + // Minimum execution time: 10_467_000 picoseconds. + Weight::from_parts(10_934_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -277,8 +307,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 17_538_000 picoseconds. - Weight::from_parts(17_832_000, 0) + // Minimum execution time: 16_377_000 picoseconds. + Weight::from_parts(17_114_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -299,8 +329,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `13507` - // Minimum execution time: 33_623_000 picoseconds. - Weight::from_parts(34_186_000, 0) + // Minimum execution time: 32_575_000 picoseconds. + Weight::from_parts(33_483_000, 0) .saturating_add(Weight::from_parts(0, 13507)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) @@ -313,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_363_000 picoseconds. - Weight::from_parts(3_511_000, 0) + // Minimum execution time: 3_604_000 picoseconds. + Weight::from_parts(3_744_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -325,8 +355,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 23_969_000 picoseconds. - Weight::from_parts(24_347_000, 0) + // Minimum execution time: 23_983_000 picoseconds. + Weight::from_parts(24_404_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -337,8 +367,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 34_071_000 picoseconds. - Weight::from_parts(35_031_000, 0) + // Minimum execution time: 34_446_000 picoseconds. + Weight::from_parts(35_465_000, 0) .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs index 0082db3099d..a1701c5f1c2 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -62,8 +62,28 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 18_410_000 picoseconds. - Weight::from_parts(18_657_000, 0) + // Minimum execution time: 17_681_000 picoseconds. + Weight::from_parts(18_350_000, 0) + .saturating_add(Weight::from_parts(0, 3539)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `74` + // Estimated: `3539` + // Minimum execution time: 18_091_000 picoseconds. + Weight::from_parts(18_327_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -84,8 +104,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `3571` - // Minimum execution time: 56_616_000 picoseconds. - Weight::from_parts(57_751_000, 0) + // Minimum execution time: 54_943_000 picoseconds. + Weight::from_parts(56_519_000, 0) .saturating_add(Weight::from_parts(0, 3571)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -120,14 +140,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_014_000 picoseconds. - Weight::from_parts(6_412_000, 0) + // Minimum execution time: 5_887_000 picoseconds. + Weight::from_parts(6_101_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -137,8 +167,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_844_000 picoseconds. - Weight::from_parts(1_957_000, 0) + // Minimum execution time: 1_940_000 picoseconds. + Weight::from_parts(2_022_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -162,8 +192,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `74` // Estimated: `3539` - // Minimum execution time: 24_067_000 picoseconds. - Weight::from_parts(24_553_000, 0) + // Minimum execution time: 23_165_000 picoseconds. + Weight::from_parts(23_800_000, 0) .saturating_add(Weight::from_parts(0, 3539)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) @@ -186,8 +216,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `292` // Estimated: `3757` - // Minimum execution time: 27_023_000 picoseconds. - Weight::from_parts(27_620_000, 0) + // Minimum execution time: 26_506_000 picoseconds. + Weight::from_parts(27_180_000, 0) .saturating_add(Weight::from_parts(0, 3757)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -198,8 +228,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_866_000 picoseconds. - Weight::from_parts(1_984_000, 0) + // Minimum execution time: 1_868_000 picoseconds. + Weight::from_parts(2_002_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -209,8 +239,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 16_425_000 picoseconds. - Weight::from_parts(16_680_000, 0) + // Minimum execution time: 16_138_000 picoseconds. + Weight::from_parts(16_447_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -221,8 +251,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 16_171_000 picoseconds. - Weight::from_parts(16_564_000, 0) + // Minimum execution time: 16_099_000 picoseconds. + Weight::from_parts(16_592_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -233,8 +263,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 17_785_000 picoseconds. - Weight::from_parts(18_123_000, 0) + // Minimum execution time: 17_972_000 picoseconds. + Weight::from_parts(18_379_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -254,8 +284,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `6082` - // Minimum execution time: 23_903_000 picoseconds. - Weight::from_parts(24_769_000, 0) + // Minimum execution time: 23_554_000 picoseconds. + Weight::from_parts(24_446_000, 0) .saturating_add(Weight::from_parts(0, 6082)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -266,8 +296,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 10_617_000 picoseconds. - Weight::from_parts(10_843_000, 0) + // Minimum execution time: 10_541_000 picoseconds. + Weight::from_parts(10_894_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -277,8 +307,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 16_656_000 picoseconds. - Weight::from_parts(17_106_000, 0) + // Minimum execution time: 16_404_000 picoseconds. + Weight::from_parts(16_818_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -299,8 +329,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `142` // Estimated: `13507` - // Minimum execution time: 31_721_000 picoseconds. - Weight::from_parts(32_547_000, 0) + // Minimum execution time: 31_617_000 picoseconds. + Weight::from_parts(32_336_000, 0) .saturating_add(Weight::from_parts(0, 13507)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) @@ -313,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_439_000 picoseconds. - Weight::from_parts(3_619_000, 0) + // Minimum execution time: 3_328_000 picoseconds. + Weight::from_parts(3_501_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -325,8 +355,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 24_657_000 picoseconds. - Weight::from_parts(24_971_000, 0) + // Minimum execution time: 23_571_000 picoseconds. + Weight::from_parts(24_312_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -337,8 +367,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 34_028_000 picoseconds. - Weight::from_parts(34_697_000, 0) + // Minimum execution time: 32_879_000 picoseconds. + Weight::from_parts(33_385_000, 0) .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_xcm.rs index fabce29b5fd..ac494fdc719 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -62,8 +62,28 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 17_830_000 picoseconds. - Weight::from_parts(18_411_000, 0) + // Minimum execution time: 17_935_000 picoseconds. + Weight::from_parts(18_482_000, 0) + .saturating_add(Weight::from_parts(0, 3503)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `38` + // Estimated: `3503` + // Minimum execution time: 18_311_000 picoseconds. + Weight::from_parts(18_850_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -84,8 +104,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `70` // Estimated: `3535` - // Minimum execution time: 55_456_000 picoseconds. - Weight::from_parts(56_808_000, 0) + // Minimum execution time: 56_182_000 picoseconds. + Weight::from_parts(58_136_000, 0) .saturating_add(Weight::from_parts(0, 3535)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -120,14 +140,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_996_000 picoseconds. - Weight::from_parts(6_154_000, 0) + // Minimum execution time: 5_979_000 picoseconds. + Weight::from_parts(6_289_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -137,8 +167,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_768_000 picoseconds. - Weight::from_parts(1_914_000, 0) + // Minimum execution time: 1_853_000 picoseconds. + Weight::from_parts(2_045_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -162,8 +192,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 24_120_000 picoseconds. - Weight::from_parts(24_745_000, 0) + // Minimum execution time: 23_827_000 picoseconds. + Weight::from_parts(24_493_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) @@ -186,8 +216,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `255` // Estimated: `3720` - // Minimum execution time: 26_630_000 picoseconds. - Weight::from_parts(27_289_000, 0) + // Minimum execution time: 26_755_000 picoseconds. + Weight::from_parts(27_125_000, 0) .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -198,8 +228,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_821_000 picoseconds. - Weight::from_parts(1_946_000, 0) + // Minimum execution time: 1_898_000 picoseconds. + Weight::from_parts(2_028_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -209,8 +239,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 16_586_000 picoseconds. - Weight::from_parts(16_977_000, 0) + // Minimum execution time: 16_300_000 picoseconds. + Weight::from_parts(16_995_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -221,8 +251,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 16_923_000 picoseconds. - Weight::from_parts(17_415_000, 0) + // Minimum execution time: 16_495_000 picoseconds. + Weight::from_parts(16_950_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -233,8 +263,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 18_596_000 picoseconds. - Weight::from_parts(18_823_000, 0) + // Minimum execution time: 18_153_000 picoseconds. + Weight::from_parts(18_595_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -254,8 +284,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `6046` - // Minimum execution time: 23_817_000 picoseconds. - Weight::from_parts(24_520_000, 0) + // Minimum execution time: 23_387_000 picoseconds. + Weight::from_parts(24_677_000, 0) .saturating_add(Weight::from_parts(0, 6046)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -266,8 +296,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 11_042_000 picoseconds. - Weight::from_parts(11_578_000, 0) + // Minimum execution time: 10_939_000 picoseconds. + Weight::from_parts(11_210_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -277,8 +307,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 17_306_000 picoseconds. - Weight::from_parts(17_817_000, 0) + // Minimum execution time: 16_850_000 picoseconds. + Weight::from_parts(17_195_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -299,8 +329,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `13471` - // Minimum execution time: 32_141_000 picoseconds. - Weight::from_parts(32_954_000, 0) + // Minimum execution time: 31_931_000 picoseconds. + Weight::from_parts(32_494_000, 0) .saturating_add(Weight::from_parts(0, 13471)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) @@ -313,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_410_000 picoseconds. - Weight::from_parts(3_556_000, 0) + // Minimum execution time: 3_514_000 picoseconds. + Weight::from_parts(3_709_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -325,8 +355,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 25_021_000 picoseconds. - Weight::from_parts(25_240_000, 0) + // Minimum execution time: 24_863_000 picoseconds. + Weight::from_parts(25_293_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -337,8 +367,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 33_801_000 picoseconds. - Weight::from_parts(34_655_000, 0) + // Minimum execution time: 33_799_000 picoseconds. + Weight::from_parts(34_665_000, 0) .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_xcm.rs index c337289243b..62a9c802808 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -62,8 +62,28 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 17_856_000 picoseconds. - Weight::from_parts(18_473_000, 0) + // Minimum execution time: 17_450_000 picoseconds. + Weight::from_parts(17_913_000, 0) + .saturating_add(Weight::from_parts(0, 3503)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// 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::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 send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `38` + // Estimated: `3503` + // Minimum execution time: 18_082_000 picoseconds. + Weight::from_parts(18_293_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -84,8 +104,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `70` // Estimated: `3535` - // Minimum execution time: 56_112_000 picoseconds. - Weight::from_parts(57_287_000, 0) + // Minimum execution time: 54_939_000 picoseconds. + Weight::from_parts(55_721_000, 0) .saturating_add(Weight::from_parts(0, 3535)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -120,14 +140,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_186_000 picoseconds. - Weight::from_parts(6_420_000, 0) + // Minimum execution time: 5_789_000 picoseconds. + Weight::from_parts(5_995_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -137,8 +167,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_824_000 picoseconds. - Weight::from_parts(1_999_000, 0) + // Minimum execution time: 1_795_000 picoseconds. + Weight::from_parts(1_924_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -162,8 +192,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `38` // Estimated: `3503` - // Minimum execution time: 23_833_000 picoseconds. - Weight::from_parts(24_636_000, 0) + // Minimum execution time: 23_445_000 picoseconds. + Weight::from_parts(23_906_000, 0) .saturating_add(Weight::from_parts(0, 3503)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(5)) @@ -186,8 +216,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `255` // Estimated: `3720` - // Minimum execution time: 26_557_000 picoseconds. - Weight::from_parts(27_275_000, 0) + // Minimum execution time: 26_590_000 picoseconds. + Weight::from_parts(27_056_000, 0) .saturating_add(Weight::from_parts(0, 3720)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -198,8 +228,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_921_000 picoseconds. - Weight::from_parts(2_040_000, 0) + // Minimum execution time: 1_889_000 picoseconds. + Weight::from_parts(1_962_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -209,8 +239,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `89` // Estimated: `13454` - // Minimum execution time: 16_832_000 picoseconds. - Weight::from_parts(17_312_000, 0) + // Minimum execution time: 16_408_000 picoseconds. + Weight::from_parts(16_877_000, 0) .saturating_add(Weight::from_parts(0, 13454)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -221,8 +251,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `93` // Estimated: `13458` - // Minimum execution time: 16_687_000 picoseconds. - Weight::from_parts(17_123_000, 0) + // Minimum execution time: 16_791_000 picoseconds. + Weight::from_parts(17_111_000, 0) .saturating_add(Weight::from_parts(0, 13458)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -233,8 +263,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `15946` - // Minimum execution time: 18_164_000 picoseconds. - Weight::from_parts(18_580_000, 0) + // Minimum execution time: 18_355_000 picoseconds. + Weight::from_parts(19_110_000, 0) .saturating_add(Weight::from_parts(0, 15946)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -254,8 +284,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `6046` - // Minimum execution time: 23_577_000 picoseconds. - Weight::from_parts(24_324_000, 0) + // Minimum execution time: 23_354_000 picoseconds. + Weight::from_parts(23_999_000, 0) .saturating_add(Weight::from_parts(0, 6046)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -266,8 +296,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `136` // Estimated: `11026` - // Minimum execution time: 11_014_000 picoseconds. - Weight::from_parts(11_223_000, 0) + // Minimum execution time: 11_065_000 picoseconds. + Weight::from_parts(11_302_000, 0) .saturating_add(Weight::from_parts(0, 11026)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -277,8 +307,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `100` // Estimated: `13465` - // Minimum execution time: 16_887_000 picoseconds. - Weight::from_parts(17_361_000, 0) + // Minimum execution time: 16_998_000 picoseconds. + Weight::from_parts(17_509_000, 0) .saturating_add(Weight::from_parts(0, 13465)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -299,8 +329,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `106` // Estimated: `13471` - // Minimum execution time: 31_705_000 picoseconds. - Weight::from_parts(32_166_000, 0) + // Minimum execution time: 31_068_000 picoseconds. + Weight::from_parts(31_978_000, 0) .saturating_add(Weight::from_parts(0, 13471)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(4)) @@ -313,8 +343,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `32` // Estimated: `1517` - // Minimum execution time: 3_568_000 picoseconds. - Weight::from_parts(3_669_000, 0) + // Minimum execution time: 3_478_000 picoseconds. + Weight::from_parts(3_595_000, 0) .saturating_add(Weight::from_parts(0, 1517)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -325,8 +355,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7669` // Estimated: `11134` - // Minimum execution time: 24_823_000 picoseconds. - Weight::from_parts(25_344_000, 0) + // Minimum execution time: 24_962_000 picoseconds. + Weight::from_parts(25_404_000, 0) .saturating_add(Weight::from_parts(0, 11134)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -337,8 +367,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `90` // Estimated: `3555` - // Minimum execution time: 34_516_000 picoseconds. - Weight::from_parts(35_478_000, 0) + // Minimum execution time: 32_685_000 picoseconds. + Weight::from_parts(33_592_000, 0) .saturating_add(Weight::from_parts(0, 3555)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/rococo/src/impls.rs b/polkadot/runtime/rococo/src/impls.rs index ac7100d7858..cf364b6ac79 100644 --- a/polkadot/runtime/rococo/src/impls.rs +++ b/polkadot/runtime/rococo/src/impls.rs @@ -167,11 +167,16 @@ where }, ]); + let encoded_versioned_xcm = + VersionedXcm::V4(program).encode().try_into().map_err(|error| { + log::error!(target: "runtime::on_reap_identity", "XCM too large, error: {:?}", error); + pallet_xcm::Error::::XcmTooLarge + })?; // send - let _ = >::send( + let _ = >::send_blob( RawOrigin::Root.into(), Box::new(VersionedLocation::V4(destination)), - Box::new(VersionedXcm::V4(program)), + encoded_versioned_xcm, )?; Ok(()) } diff --git a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs index 5544ca44658..42972baa1c8 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_xcm.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -60,8 +60,26 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 25_043_000 picoseconds. - Weight::from_parts(25_682_000, 0) + // Minimum execution time: 24_724_000 picoseconds. + Weight::from_parts(25_615_000, 0) + .saturating_add(Weight::from_parts(0, 3645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `180` + // Estimated: `3645` + // Minimum execution time: 24_709_000 picoseconds. + Weight::from_parts(25_326_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) @@ -80,8 +98,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 107_570_000 picoseconds. - Weight::from_parts(109_878_000, 0) + // Minimum execution time: 106_600_000 picoseconds. + Weight::from_parts(110_781_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -100,8 +118,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `232` // Estimated: `3697` - // Minimum execution time: 106_341_000 picoseconds. - Weight::from_parts(109_135_000, 0) + // Minimum execution time: 103_030_000 picoseconds. + Weight::from_parts(106_018_000, 0) .saturating_add(Weight::from_parts(0, 3697)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -120,8 +138,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 108_372_000 picoseconds. - Weight::from_parts(112_890_000, 0) + // Minimum execution time: 107_017_000 picoseconds. + Weight::from_parts(109_214_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(3)) @@ -130,8 +148,16 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_957_000 picoseconds. - Weight::from_parts(7_417_000, 0) + // Minimum execution time: 6_864_000 picoseconds. + Weight::from_parts(7_135_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn execute_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 6_955_000 picoseconds. + Weight::from_parts(7_165_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::SupportedVersion` (r:0 w:1) @@ -140,8 +166,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_053_000 picoseconds. - Weight::from_parts(7_462_000, 0) + // Minimum execution time: 6_827_000 picoseconds. + Weight::from_parts(7_211_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -149,8 +175,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_918_000 picoseconds. - Weight::from_parts(2_037_000, 0) + // Minimum execution time: 1_788_000 picoseconds. + Weight::from_parts(2_021_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::VersionNotifiers` (r:1 w:1) @@ -171,8 +197,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `180` // Estimated: `3645` - // Minimum execution time: 30_417_000 picoseconds. - Weight::from_parts(31_191_000, 0) + // Minimum execution time: 30_627_000 picoseconds. + Weight::from_parts(31_350_000, 0) .saturating_add(Weight::from_parts(0, 3645)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) @@ -193,8 +219,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `360` // Estimated: `3825` - // Minimum execution time: 36_666_000 picoseconds. - Weight::from_parts(37_779_000, 0) + // Minimum execution time: 36_688_000 picoseconds. + Weight::from_parts(37_345_000, 0) .saturating_add(Weight::from_parts(0, 3825)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -205,8 +231,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_869_000 picoseconds. - Weight::from_parts(2_003_000, 0) + // Minimum execution time: 1_829_000 picoseconds. + Weight::from_parts(1_986_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -216,8 +242,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `22` // Estimated: `13387` - // Minimum execution time: 16_188_000 picoseconds. - Weight::from_parts(16_435_000, 0) + // Minimum execution time: 16_104_000 picoseconds. + Weight::from_parts(16_464_000, 0) .saturating_add(Weight::from_parts(0, 13387)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -228,8 +254,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `26` // Estimated: `13391` - // Minimum execution time: 16_431_000 picoseconds. - Weight::from_parts(16_935_000, 0) + // Minimum execution time: 16_267_000 picoseconds. + Weight::from_parts(16_675_000, 0) .saturating_add(Weight::from_parts(0, 13391)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -240,8 +266,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `40` // Estimated: `15880` - // Minimum execution time: 18_460_000 picoseconds. - Weight::from_parts(18_885_000, 0) + // Minimum execution time: 18_487_000 picoseconds. + Weight::from_parts(19_102_000, 0) .saturating_add(Weight::from_parts(0, 15880)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -259,8 +285,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `216` // Estimated: `6156` - // Minimum execution time: 29_623_000 picoseconds. - Weight::from_parts(30_661_000, 0) + // Minimum execution time: 29_603_000 picoseconds. + Weight::from_parts(31_002_000, 0) .saturating_add(Weight::from_parts(0, 6156)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) @@ -271,8 +297,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `69` // Estimated: `10959` - // Minimum execution time: 12_043_000 picoseconds. - Weight::from_parts(12_360_000, 0) + // Minimum execution time: 12_183_000 picoseconds. + Weight::from_parts(12_587_000, 0) .saturating_add(Weight::from_parts(0, 10959)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -282,8 +308,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `33` // Estimated: `13398` - // Minimum execution time: 16_511_000 picoseconds. - Weight::from_parts(17_011_000, 0) + // Minimum execution time: 16_372_000 picoseconds. + Weight::from_parts(16_967_000, 0) .saturating_add(Weight::from_parts(0, 13398)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -302,8 +328,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `216` // Estimated: `13581` - // Minimum execution time: 39_041_000 picoseconds. - Weight::from_parts(39_883_000, 0) + // Minimum execution time: 38_904_000 picoseconds. + Weight::from_parts(39_983_000, 0) .saturating_add(Weight::from_parts(0, 13581)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(4)) @@ -316,8 +342,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 2_030_000 picoseconds. - Weight::from_parts(2_150_000, 0) + // Minimum execution time: 2_067_000 picoseconds. + Weight::from_parts(2_195_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -328,8 +354,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7576` // Estimated: `11041` - // Minimum execution time: 22_615_000 picoseconds. - Weight::from_parts(23_008_000, 0) + // Minimum execution time: 23_982_000 picoseconds. + Weight::from_parts(24_409_000, 0) .saturating_add(Weight::from_parts(0, 11041)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -340,8 +366,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `23` // Estimated: `3488` - // Minimum execution time: 34_438_000 picoseconds. - Weight::from_parts(35_514_000, 0) + // Minimum execution time: 33_430_000 picoseconds. + Weight::from_parts(34_433_000, 0) .saturating_add(Weight::from_parts(0, 3488)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/runtime/westend/src/impls.rs b/polkadot/runtime/westend/src/impls.rs index 71e6b696a20..d8741c939a5 100644 --- a/polkadot/runtime/westend/src/impls.rs +++ b/polkadot/runtime/westend/src/impls.rs @@ -167,11 +167,16 @@ where }, ]); + let encoded_versioned_xcm = + VersionedXcm::V4(program).encode().try_into().map_err(|error| { + log::error!(target: "runtime::on_reap_identity", "XCM too large, error: {:?}", error); + pallet_xcm::Error::::XcmTooLarge + })?; // send - let _ = >::send( + let _ = >::send_blob( RawOrigin::Root.into(), Box::new(VersionedLocation::V4(destination)), - Box::new(VersionedXcm::V4(program)), + encoded_versioned_xcm, )?; Ok(()) } diff --git a/polkadot/runtime/westend/src/weights/pallet_xcm.rs b/polkadot/runtime/westend/src/weights/pallet_xcm.rs index 10725cecf24..80bc551ba1e 100644 --- a/polkadot/runtime/westend/src/weights/pallet_xcm.rs +++ b/polkadot/runtime/westend/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -60,8 +60,26 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `147` // Estimated: `3612` - // Minimum execution time: 25_725_000 picoseconds. - Weight::from_parts(26_174_000, 0) + // Minimum execution time: 24_535_000 picoseconds. + Weight::from_parts(25_618_000, 0) + .saturating_add(Weight::from_parts(0, 3612)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `Dmp::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `Dmp::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `XcmPallet::SupportedVersion` (r:1 w:0) + /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueues` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueues` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Dmp::DownwardMessageQueueHeads` (r:1 w:1) + /// Proof: `Dmp::DownwardMessageQueueHeads` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn send_blob() -> Weight { + // Proof Size summary in bytes: + // Measured: `147` + // Estimated: `3612` + // Minimum execution time: 25_376_000 picoseconds. + Weight::from_parts(26_180_000, 0) .saturating_add(Weight::from_parts(0, 3612)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) @@ -80,8 +98,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `250` // Estimated: `6196` - // Minimum execution time: 113_140_000 picoseconds. - Weight::from_parts(116_204_000, 0) + // Minimum execution time: 108_786_000 picoseconds. + Weight::from_parts(112_208_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -100,8 +118,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `302` // Estimated: `6196` - // Minimum execution time: 108_571_000 picoseconds. - Weight::from_parts(110_650_000, 0) + // Minimum execution time: 105_190_000 picoseconds. + Weight::from_parts(107_140_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -120,8 +138,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `250` // Estimated: `6196` - // Minimum execution time: 111_836_000 picoseconds. - Weight::from_parts(114_435_000, 0) + // Minimum execution time: 109_027_000 picoseconds. + Weight::from_parts(111_404_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -136,14 +154,24 @@ impl pallet_xcm::WeightInfo for WeightInfo { Weight::from_parts(18_446_744_073_709_551_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn execute_blob() -> 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)) + } /// Storage: `XcmPallet::SupportedVersion` (r:0 w:1) /// Proof: `XcmPallet::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_160_000 picoseconds. - Weight::from_parts(7_477_000, 0) + // Minimum execution time: 6_668_000 picoseconds. + Weight::from_parts(7_013_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -151,8 +179,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_934_000 picoseconds. - Weight::from_parts(2_053_000, 0) + // Minimum execution time: 1_740_000 picoseconds. + Weight::from_parts(1_884_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `XcmPallet::VersionNotifiers` (r:1 w:1) @@ -173,8 +201,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `147` // Estimated: `3612` - // Minimum execution time: 31_123_000 picoseconds. - Weight::from_parts(31_798_000, 0) + // Minimum execution time: 30_200_000 picoseconds. + Weight::from_parts(30_768_000, 0) .saturating_add(Weight::from_parts(0, 3612)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) @@ -195,8 +223,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `327` // Estimated: `3792` - // Minimum execution time: 35_175_000 picoseconds. - Weight::from_parts(36_098_000, 0) + // Minimum execution time: 33_928_000 picoseconds. + Weight::from_parts(35_551_000, 0) .saturating_add(Weight::from_parts(0, 3792)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -207,8 +235,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_974_000 picoseconds. - Weight::from_parts(2_096_000, 0) + // Minimum execution time: 1_759_000 picoseconds. + Weight::from_parts(1_880_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -218,8 +246,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `22` // Estimated: `13387` - // Minimum execution time: 16_626_000 picoseconds. - Weight::from_parts(17_170_000, 0) + // Minimum execution time: 16_507_000 picoseconds. + Weight::from_parts(17_219_000, 0) .saturating_add(Weight::from_parts(0, 13387)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -230,8 +258,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `26` // Estimated: `13391` - // Minimum execution time: 16_937_000 picoseconds. - Weight::from_parts(17_447_000, 0) + // Minimum execution time: 16_633_000 picoseconds. + Weight::from_parts(16_889_000, 0) .saturating_add(Weight::from_parts(0, 13391)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -242,8 +270,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `40` // Estimated: `15880` - // Minimum execution time: 19_157_000 picoseconds. - Weight::from_parts(19_659_000, 0) + // Minimum execution time: 19_297_000 picoseconds. + Weight::from_parts(19_820_000, 0) .saturating_add(Weight::from_parts(0, 15880)) .saturating_add(T::DbWeight::get().reads(6)) } @@ -261,8 +289,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `183` // Estimated: `6123` - // Minimum execution time: 30_699_000 picoseconds. - Weight::from_parts(31_537_000, 0) + // Minimum execution time: 30_364_000 picoseconds. + Weight::from_parts(31_122_000, 0) .saturating_add(Weight::from_parts(0, 6123)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) @@ -273,8 +301,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `69` // Estimated: `10959` - // Minimum execution time: 12_303_000 picoseconds. - Weight::from_parts(12_670_000, 0) + // Minimum execution time: 11_997_000 picoseconds. + Weight::from_parts(12_392_000, 0) .saturating_add(Weight::from_parts(0, 10959)) .saturating_add(T::DbWeight::get().reads(4)) } @@ -284,8 +312,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `33` // Estimated: `13398` - // Minimum execution time: 17_129_000 picoseconds. - Weight::from_parts(17_668_000, 0) + // Minimum execution time: 16_894_000 picoseconds. + Weight::from_parts(17_452_000, 0) .saturating_add(Weight::from_parts(0, 13398)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) @@ -304,8 +332,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `183` // Estimated: `13548` - // Minimum execution time: 39_960_000 picoseconds. - Weight::from_parts(41_068_000, 0) + // Minimum execution time: 39_864_000 picoseconds. + Weight::from_parts(40_859_000, 0) .saturating_add(Weight::from_parts(0, 13548)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(4)) @@ -318,8 +346,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 2_333_000 picoseconds. - Weight::from_parts(2_504_000, 0) + // Minimum execution time: 2_363_000 picoseconds. + Weight::from_parts(2_519_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -330,8 +358,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `7576` // Estimated: `11041` - // Minimum execution time: 22_932_000 picoseconds. - Weight::from_parts(23_307_000, 0) + // Minimum execution time: 22_409_000 picoseconds. + Weight::from_parts(22_776_000, 0) .saturating_add(Weight::from_parts(0, 11041)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -342,8 +370,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `23` // Estimated: `3488` - // Minimum execution time: 34_558_000 picoseconds. - Weight::from_parts(35_299_000, 0) + // Minimum execution time: 33_551_000 picoseconds. + Weight::from_parts(34_127_000, 0) .saturating_add(Weight::from_parts(0, 3488)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index ed42f93692b..e2903d592dc 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -16,6 +16,7 @@ use super::*; use bounded_collections::{ConstU32, WeakBoundedVec}; +use codec::Encode; use frame_benchmarking::{benchmarks, whitelisted_caller, BenchmarkError, BenchmarkResult}; use frame_support::{ traits::fungible::{Inspect, Mutate}, @@ -108,6 +109,21 @@ benchmarks! { let versioned_msg = VersionedXcm::from(msg); }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_msg)) + send_blob { + let send_origin = + T::SendXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + if T::SendXcmOrigin::try_origin(send_origin.clone()).is_err() { + return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) + } + let msg = Xcm::<()>(vec![ClearOrigin]); + let versioned_dest: VersionedLocation = T::reachable_dest().ok_or( + BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), + )? + .into(); + let versioned_msg = VersionedXcm::from(msg); + let encoded_versioned_msg = versioned_msg.encode().try_into().unwrap(); + }: _>(send_origin, Box::new(versioned_dest), encoded_versioned_msg) + teleport_assets { let (asset, destination) = T::teleportable_asset_and_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), @@ -227,6 +243,19 @@ benchmarks! { let versioned_msg = VersionedXcm::from(msg); }: _>(execute_origin, Box::new(versioned_msg), Weight::MAX) + execute_blob { + let execute_origin = + T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + let origin_location = T::ExecuteXcmOrigin::try_origin(execute_origin.clone()) + .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; + let msg = Xcm(vec![ClearOrigin]); + if !T::XcmExecuteFilter::contains(&(origin_location, msg.clone())) { + return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) + } + let versioned_msg = VersionedXcm::from(msg); + let encoded_versioned_msg = versioned_msg.encode().try_into().unwrap(); + }: _>(execute_origin, encoded_versioned_msg, Weight::MAX) + force_xcm_version { let loc = T::reachable_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 58a597de5ab..29b61988f73 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -50,8 +50,8 @@ use sp_runtime::{ use sp_std::{boxed::Box, marker::PhantomData, prelude::*, result::Result, vec}; use xcm::{latest::QueryResponseInfo, prelude::*}; use xcm_builder::{ - ExecuteController, ExecuteControllerWeightInfo, QueryController, QueryControllerWeightInfo, - SendController, SendControllerWeightInfo, + ExecuteController, ExecuteControllerWeightInfo, MaxXcmEncodedSize, QueryController, + QueryControllerWeightInfo, SendController, SendControllerWeightInfo, }; use xcm_executor::{ traits::{ @@ -87,6 +87,8 @@ pub trait WeightInfo { fn new_query() -> Weight; fn take_response() -> Weight; fn claim_assets() -> Weight; + fn execute_blob() -> Weight; + fn send_blob() -> Weight; } /// fallback implementation @@ -171,6 +173,14 @@ impl WeightInfo for TestWeightInfo { fn claim_assets() -> Weight { Weight::from_parts(100_000_000, 0) } + + fn execute_blob() -> Weight { + Weight::from_parts(100_000_000, 0) + } + + fn send_blob() -> Weight { + Weight::from_parts(100_000_000, 0) + } } #[frame_support::pallet] @@ -286,76 +296,49 @@ pub mod pallet { } impl ExecuteControllerWeightInfo for Pallet { - fn execute() -> Weight { - T::WeightInfo::execute() + fn execute_blob() -> Weight { + T::WeightInfo::execute_blob() } } impl ExecuteController, ::RuntimeCall> for Pallet { type WeightInfo = Self; - fn execute( + fn execute_blob( origin: OriginFor, - message: Box::RuntimeCall>>, + encoded_message: BoundedVec, max_weight: Weight, ) -> Result { - log::trace!(target: "xcm::pallet_xcm::execute", "message {:?}, max_weight {:?}", message, max_weight); - let outcome = (|| { - let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let mut hash = message.using_encoded(sp_io::hashing::blake2_256); - let message = (*message).try_into().map_err(|()| Error::::BadVersion)?; - let value = (origin_location, message); - ensure!(T::XcmExecuteFilter::contains(&value), Error::::Filtered); - let (origin_location, message) = value; - Ok(T::XcmExecutor::prepare_and_execute( - origin_location, - message, - &mut hash, - max_weight, - max_weight, - )) - })() - .map_err(|e: DispatchError| { - e.with_weight(::execute()) - })?; - - Self::deposit_event(Event::Attempted { outcome: outcome.clone() }); - let weight_used = outcome.weight_used(); - outcome.ensure_complete().map_err(|error| { - log::error!(target: "xcm::pallet_xcm::execute", "XCM execution failed with error {:?}", error); - Error::::LocalExecutionIncomplete.with_weight( - weight_used.saturating_add( - ::execute(), - ), - ) - })?; - Ok(weight_used) + let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; + let message = + VersionedXcm::<::RuntimeCall>::decode(&mut &encoded_message[..]) + .map_err(|error| { + log::error!(target: "xcm::execute_blob", "Unable to decode XCM, error: {:?}", error); + Error::::UnableToDecode + })?; + Self::execute_base(origin_location, Box::new(message), max_weight) } } impl SendControllerWeightInfo for Pallet { - fn send() -> Weight { - T::WeightInfo::send() + fn send_blob() -> Weight { + T::WeightInfo::send_blob() } } impl SendController> for Pallet { type WeightInfo = Self; - fn send( + fn send_blob( origin: OriginFor, dest: Box, - message: Box>, + encoded_message: BoundedVec, ) -> Result { let origin_location = T::SendXcmOrigin::ensure_origin(origin)?; - let interior: Junctions = - origin_location.clone().try_into().map_err(|_| Error::::InvalidOrigin)?; - let dest = Location::try_from(*dest).map_err(|()| Error::::BadVersion)?; - let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; - - let message_id = Self::send_xcm(interior, dest.clone(), message.clone()) - .map_err(Error::::from)?; - let e = Event::Sent { origin: origin_location, destination: dest, message, message_id }; - Self::deposit_event(e); - Ok(message_id) + let message = + VersionedXcm::<()>::decode(&mut &encoded_message[..]).map_err(|error| { + log::error!(target: "xcm::send_blob", "Unable to decode XCM, error: {:?}", error); + Error::::UnableToDecode + })?; + Self::send_base(origin_location, dest, Box::new(message)) } } @@ -562,6 +545,11 @@ pub mod pallet { TooManyReserves, /// Local XCM execution incomplete. LocalExecutionIncomplete, + /// Could not decode XCM. + UnableToDecode, + /// XCM encoded length is too large. + /// Returned when an XCM encoded length is larger than `MaxXcmEncodedSize`. + XcmTooLarge, } impl From for Error { @@ -899,8 +887,64 @@ pub mod pallet { } } + impl Pallet { + /// Underlying logic for both [`execute_blob`] and [`execute`]. + fn execute_base( + origin_location: Location, + message: Box::RuntimeCall>>, + max_weight: Weight, + ) -> Result { + log::trace!(target: "xcm::pallet_xcm::execute", "message {:?}, max_weight {:?}", message, max_weight); + let outcome = (|| { + let mut hash = message.using_encoded(sp_io::hashing::blake2_256); + let message = (*message).try_into().map_err(|()| Error::::BadVersion)?; + let value = (origin_location, message); + ensure!(T::XcmExecuteFilter::contains(&value), Error::::Filtered); + let (origin_location, message) = value; + Ok(T::XcmExecutor::prepare_and_execute( + origin_location, + message, + &mut hash, + max_weight, + max_weight, + )) + })() + .map_err(|e: DispatchError| e.with_weight(T::WeightInfo::execute()))?; + + Self::deposit_event(Event::Attempted { outcome: outcome.clone() }); + let weight_used = outcome.weight_used(); + outcome.ensure_complete().map_err(|error| { + log::error!(target: "xcm::pallet_xcm::execute", "XCM execution failed with error {:?}", error); + Error::::LocalExecutionIncomplete + .with_weight(weight_used.saturating_add(T::WeightInfo::execute())) + })?; + Ok(weight_used) + } + + /// Underlying logic for both [`send_blob`] and [`send`]. + fn send_base( + origin_location: Location, + dest: Box, + message: Box>, + ) -> Result { + let interior: Junctions = + origin_location.clone().try_into().map_err(|_| Error::::InvalidOrigin)?; + let dest = Location::try_from(*dest).map_err(|()| Error::::BadVersion)?; + let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; + + let message_id = Self::send_xcm(interior, dest.clone(), message.clone()) + .map_err(Error::::from)?; + let e = Event::Sent { origin: origin_location, destination: dest, message, message_id }; + Self::deposit_event(e); + Ok(message_id) + } + } + #[pallet::call] impl Pallet { + /// WARNING: DEPRECATED. `send` will be removed after June 2024. Use `send_blob` instead. + #[allow(deprecated)] + #[deprecated(note = "`send` will be removed after June 2024. Use `send_blob` instead.")] #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::send())] pub fn send( @@ -908,7 +952,8 @@ pub mod pallet { dest: Box, message: Box>, ) -> DispatchResult { - >::send(origin, dest, message)?; + let origin_location = T::SendXcmOrigin::ensure_origin(origin)?; + Self::send_base(origin_location, dest, message)?; Ok(()) } @@ -1031,6 +1076,13 @@ pub mod pallet { /// No more than `max_weight` will be used in its attempted execution. If this is less than /// the maximum amount of weight that the message could take to be executed, then no /// execution attempt will be made. + /// + /// WARNING: DEPRECATED. `execute` will be removed after June 2024. Use `execute_blob` + /// instead. + #[allow(deprecated)] + #[deprecated( + note = "`execute` will be removed after June 2024. Use `execute_blob` instead." + )] #[pallet::call_index(3)] #[pallet::weight(max_weight.saturating_add(T::WeightInfo::execute()))] pub fn execute( @@ -1038,8 +1090,8 @@ pub mod pallet { message: Box::RuntimeCall>>, max_weight: Weight, ) -> DispatchResultWithPostInfo { - let weight_used = - >::execute(origin, message, max_weight)?; + let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; + let weight_used = Self::execute_base(origin_location, message, max_weight)?; Ok(Some(weight_used.saturating_add(T::WeightInfo::execute())).into()) } @@ -1450,6 +1502,48 @@ pub mod pallet { })?; Ok(()) } + + /// Execute an XCM from a local, signed, origin. + /// + /// An event is deposited indicating whether the message could be executed completely + /// or only partially. + /// + /// No more than `max_weight` will be used in its attempted execution. If this is less than + /// the maximum amount of weight that the message could take to be executed, then no + /// execution attempt will be made. + /// + /// The message is passed in encoded. It needs to be decodable as a [`VersionedXcm`]. + #[pallet::call_index(13)] + #[pallet::weight(T::WeightInfo::execute_blob())] + pub fn execute_blob( + origin: OriginFor, + encoded_message: BoundedVec, + max_weight: Weight, + ) -> DispatchResultWithPostInfo { + let weight_used = >::execute_blob( + origin, + encoded_message, + max_weight, + )?; + Ok(Some(weight_used.saturating_add(T::WeightInfo::execute_blob())).into()) + } + + /// Send an XCM from a local, signed, origin. + /// + /// The destination, `dest`, will receive this message with a `DescendOrigin` instruction + /// that makes the origin of the message be the origin on this system. + /// + /// The message is passed in encoded. It needs to be decodable as a [`VersionedXcm`]. + #[pallet::call_index(14)] + #[pallet::weight(T::WeightInfo::send_blob())] + pub fn send_blob( + origin: OriginFor, + dest: Box, + encoded_message: BoundedVec, + ) -> DispatchResult { + >::send_blob(origin, dest, encoded_message)?; + Ok(()) + } } } diff --git a/polkadot/xcm/pallet-xcm/src/tests/mod.rs b/polkadot/xcm/pallet-xcm/src/tests/mod.rs index 13022d9a8b1..763d768e154 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/mod.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/mod.rs @@ -20,10 +20,10 @@ pub(crate) mod assets_transfer; use crate::{ mock::*, pallet::SupportedVersion, AssetTraps, Config, CurrentMigration, Error, - ExecuteControllerWeightInfo, LatestVersionedLocation, Pallet, Queries, QueryStatus, - VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers, VersionNotifyTargets, - WeightInfo, + LatestVersionedLocation, Pallet, Queries, QueryStatus, VersionDiscoveryQueue, + VersionMigrationStage, VersionNotifiers, VersionNotifyTargets, WeightInfo, }; +use codec::Encode; use frame_support::{ assert_err_ignore_postinfo, assert_noop, assert_ok, traits::{Currency, Hooks}, @@ -305,11 +305,12 @@ fn send_works() { ]); let versioned_dest = Box::new(RelayLocation::get().into()); - let versioned_message = Box::new(VersionedXcm::from(message.clone())); - assert_ok!(XcmPallet::send( + let versioned_message = VersionedXcm::from(message.clone()); + let encoded_versioned_message = versioned_message.encode().try_into().unwrap(); + assert_ok!(XcmPallet::send_blob( RuntimeOrigin::signed(ALICE), versioned_dest, - versioned_message + encoded_versioned_message )); let sent_message = Xcm(Some(DescendOrigin(sender.clone().try_into().unwrap())) .into_iter() @@ -341,16 +342,16 @@ fn send_fails_when_xcm_router_blocks() { ]; new_test_ext_with_balances(balances).execute_with(|| { let sender: Location = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - let message = Xcm(vec![ + let message = Xcm::<()>(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), buy_execution((Parent, SEND_AMOUNT)), DepositAsset { assets: AllCounted(1).into(), beneficiary: sender }, ]); assert_noop!( - XcmPallet::send( + XcmPallet::send_blob( RuntimeOrigin::signed(ALICE), Box::new(Location::ancestor(8).into()), - Box::new(VersionedXcm::from(message.clone())), + VersionedXcm::from(message.clone()).encode().try_into().unwrap(), ), crate::Error::::SendFailure ); @@ -371,13 +372,16 @@ fn execute_withdraw_to_deposit_works() { let weight = BaseXcmWeight::get() * 3; let dest: Location = Junction::AccountId32 { network: None, id: BOB.into() }.into(); assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - assert_ok!(XcmPallet::execute( + assert_ok!(XcmPallet::execute_blob( RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ + VersionedXcm::from(Xcm::(vec![ WithdrawAsset((Here, SEND_AMOUNT).into()), buy_execution((Here, SEND_AMOUNT)), DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]))), + ])) + .encode() + .try_into() + .unwrap(), weight )); assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); @@ -399,18 +403,21 @@ fn trapped_assets_can_be_claimed() { let weight = BaseXcmWeight::get() * 6; let dest: Location = Junction::AccountId32 { network: None, id: BOB.into() }.into(); - assert_ok!(XcmPallet::execute( + assert_ok!(XcmPallet::execute_blob( RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ + VersionedXcm::from(Xcm(vec![ WithdrawAsset((Here, SEND_AMOUNT).into()), buy_execution((Here, SEND_AMOUNT)), // Don't propagated the error into the result. - SetErrorHandler(Xcm(vec![ClearError])), + SetErrorHandler(Xcm::(vec![ClearError])), // This will make an error. Trap(0), // This would succeed, but we never get to it. DepositAsset { assets: AllCounted(1).into(), beneficiary: dest.clone() }, - ]))), + ])) + .encode() + .try_into() + .unwrap(), weight )); let source: Location = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); @@ -437,13 +444,16 @@ fn trapped_assets_can_be_claimed() { assert_eq!(trapped, expected); let weight = BaseXcmWeight::get() * 3; - assert_ok!(XcmPallet::execute( + assert_ok!(XcmPallet::execute_blob( RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ + VersionedXcm::from(Xcm::(vec![ ClaimAsset { assets: (Here, SEND_AMOUNT).into(), ticket: Here.into() }, buy_execution((Here, SEND_AMOUNT)), DepositAsset { assets: AllCounted(1).into(), beneficiary: dest.clone() }, - ]))), + ])) + .encode() + .try_into() + .unwrap(), weight )); @@ -453,13 +463,16 @@ fn trapped_assets_can_be_claimed() { // Can't claim twice. assert_err_ignore_postinfo!( - XcmPallet::execute( + XcmPallet::execute_blob( RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ + VersionedXcm::from(Xcm::(vec![ ClaimAsset { assets: (Here, SEND_AMOUNT).into(), ticket: Here.into() }, buy_execution((Here, SEND_AMOUNT)), DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]))), + ])) + .encode() + .try_into() + .unwrap(), weight ), Error::::LocalExecutionIncomplete @@ -473,12 +486,13 @@ fn claim_assets_works() { let balances = vec![(ALICE, INITIAL_BALANCE)]; new_test_ext_with_balances(balances).execute_with(|| { // First trap some assets. - let trapping_program = - Xcm::builder_unsafe().withdraw_asset((Here, SEND_AMOUNT).into()).build(); + let trapping_program = Xcm::::builder_unsafe() + .withdraw_asset((Here, SEND_AMOUNT).into()) + .build(); // Even though assets are trapped, the extrinsic returns success. - assert_ok!(XcmPallet::execute( + assert_ok!(XcmPallet::execute_blob( RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::V4(trapping_program)), + VersionedXcm::V4(trapping_program).encode().try_into().unwrap(), BaseXcmWeight::get() * 2, )); assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); @@ -531,9 +545,9 @@ fn incomplete_execute_reverts_side_effects() { assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); let amount_to_send = INITIAL_BALANCE - ExistentialDeposit::get(); let assets: Assets = (Here, amount_to_send).into(); - let result = XcmPallet::execute( + let result = XcmPallet::execute_blob( RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ + VersionedXcm::from(Xcm::(vec![ // Withdraw + BuyExec + Deposit should work WithdrawAsset(assets.clone()), buy_execution(assets.inner()[0].clone()), @@ -541,7 +555,10 @@ fn incomplete_execute_reverts_side_effects() { // Withdrawing once more will fail because of InsufficientBalance, and we expect to // revert the effects of the above instructions as well WithdrawAsset(assets), - ]))), + ])) + .encode() + .try_into() + .unwrap(), weight, ); // all effects are reverted and balances unchanged for either sender or receiver @@ -553,7 +570,7 @@ fn incomplete_execute_reverts_side_effects() { Err(sp_runtime::DispatchErrorWithPostInfo { post_info: frame_support::dispatch::PostDispatchInfo { actual_weight: Some( - as ExecuteControllerWeightInfo>::execute() + weight + <::WeightInfo>::execute_blob() + weight ), pays_fee: frame_support::dispatch::Pays::Yes, }, diff --git a/polkadot/xcm/src/lib.rs b/polkadot/xcm/src/lib.rs index 86a17fa1e88..e836486e86e 100644 --- a/polkadot/xcm/src/lib.rs +++ b/polkadot/xcm/src/lib.rs @@ -48,6 +48,9 @@ mod tests; /// Maximum nesting level for XCM decoding. pub const MAX_XCM_DECODE_DEPTH: u32 = 8; +/// Maximum encoded size. +/// See `decoding_respects_limit` test for more reasoning behind this value. +pub const MAX_XCM_ENCODED_SIZE: u32 = 12402; /// A version of XCM. pub type Version = u32; diff --git a/polkadot/xcm/src/v4/mod.rs b/polkadot/xcm/src/v4/mod.rs index 30ee485589a..6635408282e 100644 --- a/polkadot/xcm/src/v4/mod.rs +++ b/polkadot/xcm/src/v4/mod.rs @@ -1488,7 +1488,21 @@ mod tests { let encoded = big_xcm.encode(); assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err()); - let nested_xcm = Xcm::<()>(vec![ + let mut many_assets = Assets::new(); + for index in 0..MAX_ITEMS_IN_ASSETS { + many_assets.push((GeneralIndex(index as u128), 1u128).into()); + } + + let full_xcm_pass = + Xcm::<()>(vec![ + TransferAsset { assets: many_assets, beneficiary: Here.into() }; + MAX_INSTRUCTIONS_TO_DECODE as usize + ]); + let encoded = full_xcm_pass.encode(); + assert_eq!(encoded.len(), 12402); + assert!(Xcm::<()>::decode(&mut &encoded[..]).is_ok()); + + let nested_xcm_fail = Xcm::<()>(vec![ DepositReserveAsset { assets: All.into(), dest: Here.into(), @@ -1496,10 +1510,10 @@ mod tests { }; (MAX_INSTRUCTIONS_TO_DECODE / 2) as usize ]); - let encoded = nested_xcm.encode(); + let encoded = nested_xcm_fail.encode(); assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err()); - let even_more_nested_xcm = Xcm::<()>(vec![SetAppendix(nested_xcm); 64]); + let even_more_nested_xcm = Xcm::<()>(vec![SetAppendix(nested_xcm_fail); 64]); let encoded = even_more_nested_xcm.encode(); assert_eq!(encoded.len(), 342530); // This should not decode since the limit is 100 diff --git a/polkadot/xcm/xcm-builder/src/controller.rs b/polkadot/xcm/xcm-builder/src/controller.rs index 04b19eaa587..6bdde2a967d 100644 --- a/polkadot/xcm/xcm-builder/src/controller.rs +++ b/polkadot/xcm/xcm-builder/src/controller.rs @@ -21,6 +21,7 @@ use frame_support::{ dispatch::{DispatchErrorWithPostInfo, WithPostDispatchInfo}, pallet_prelude::DispatchError, + parameter_types, BoundedVec, }; use sp_std::boxed::Box; use xcm::prelude::*; @@ -41,8 +42,12 @@ impl Controller f /// Weight functions needed for [`ExecuteController`]. pub trait ExecuteControllerWeightInfo { - /// Weight for [`ExecuteController::execute`] - fn execute() -> Weight; + /// Weight for [`ExecuteController::execute_blob`] + fn execute_blob() -> Weight; +} + +parameter_types! { + pub const MaxXcmEncodedSize: u32 = xcm::MAX_XCM_ENCODED_SIZE; } /// Execute an XCM locally, for a given origin. @@ -61,19 +66,19 @@ pub trait ExecuteController { /// # Parameters /// /// - `origin`: the origin of the call. - /// - `message`: the XCM program to be executed. + /// - `msg`: the encoded XCM to be executed, should be decodable as a [`VersionedXcm`] /// - `max_weight`: the maximum weight that can be consumed by the execution. - fn execute( + fn execute_blob( origin: Origin, - message: Box>, + message: BoundedVec, max_weight: Weight, ) -> Result; } /// Weight functions needed for [`SendController`]. pub trait SendControllerWeightInfo { - /// Weight for [`SendController::send`] - fn send() -> Weight; + /// Weight for [`SendController::send_blob`] + fn send_blob() -> Weight; } /// Send an XCM from a given origin. @@ -93,11 +98,11 @@ pub trait SendController { /// /// - `origin`: the origin of the call. /// - `dest`: the destination of the message. - /// - `msg`: the XCM to be sent. - fn send( + /// - `msg`: the encoded XCM to be sent, should be decodable as a [`VersionedXcm`] + fn send_blob( origin: Origin, dest: Box, - message: Box>, + message: BoundedVec, ) -> Result; } @@ -137,35 +142,35 @@ pub trait QueryController: QueryHandler { impl ExecuteController for () { type WeightInfo = (); - fn execute( + fn execute_blob( _origin: Origin, - _message: Box>, + _message: BoundedVec, _max_weight: Weight, ) -> Result { - Err(DispatchError::Other("ExecuteController::execute not implemented") + Err(DispatchError::Other("ExecuteController::execute_blob not implemented") .with_weight(Weight::zero())) } } impl ExecuteControllerWeightInfo for () { - fn execute() -> Weight { + fn execute_blob() -> Weight { Weight::zero() } } impl SendController for () { type WeightInfo = (); - fn send( + fn send_blob( _origin: Origin, _dest: Box, - _message: Box>, + _message: BoundedVec, ) -> Result { Ok(Default::default()) } } impl SendControllerWeightInfo for () { - fn send() -> Weight { + fn send_blob() -> Weight { Weight::zero() } } diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs index e2af8187136..46d0ad227bf 100644 --- a/polkadot/xcm/xcm-builder/src/lib.rs +++ b/polkadot/xcm/xcm-builder/src/lib.rs @@ -43,7 +43,7 @@ pub use barriers::{ mod controller; pub use controller::{ - Controller, ExecuteController, ExecuteControllerWeightInfo, QueryController, + Controller, ExecuteController, ExecuteControllerWeightInfo, MaxXcmEncodedSize, QueryController, QueryControllerWeightInfo, QueryHandler, SendController, SendControllerWeightInfo, }; diff --git a/prdoc/pr_3749.prdoc b/prdoc/pr_3749.prdoc new file mode 100644 index 00000000000..1ebde9670e0 --- /dev/null +++ b/prdoc/pr_3749.prdoc @@ -0,0 +1,47 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "pallet-xcm: deprecate execute and send in favor of execute_blob and send_blob" + +doc: + - audience: Runtime Dev + description: | + pallet-xcm's extrinsics `execute` and `send` have been marked as deprecated. + Please change their usage to the new `execute_blob` and `send_blob`. + The migration from the old extrinsic to the new is very simple. + If you have your message `xcm: VersionedXcm`, then instead of passing in + `Box::new(xcm)` to both `execute` and `send`, you would pass in + `xcm.encode().try_into()` and handle the potential error of its encoded length + being bigger than `MAX_XCM_ENCODED_SIZE`. + + pallet-contracts takes the XCM encoded now as well. It follows the same API as + `execute_blob` and `send_blob`. + - audience: Runtime User + description: | + pallet-xcm has a new pair of extrinsics, `execute_blob` and `send_blob`. + These are meant to be used instead of `execute` and `send`, which are now deprecated + and will be removed eventually. + These new extrinsics just require you to input the encoded XCM. + There's a new utility in PolkadotJS Apps for encoding XCMs you can use: + https://polkadot.js.org/apps/#/utilities/xcm + Just pass in the encoded XCM to the new extrinsics and you're done. + + pallet-contracts takes the XCM encoded now as well. It follows the same API as + `execute_blob` and `send_blob`. + +crates: +- name: pallet-xcm +- name: staging-xcm +- name: staging-xcm-builder +- name: pallet-contracts +- name: asset-hub-rococo-runtime +- name: asset-hub-westend-runtime +- name: bridge-hub-rococo-runtime +- name: bridge-hub-westend-runtime +- name: collectives-westend-runtime +- name: coretime-rococo-runtime +- name: coretime-westend-runtime +- name: people-rococo-runtime +- name: people-westend-runtime +- name: rococo-runtime +- name: westend-runtime diff --git a/substrate/frame/contracts/mock-network/src/tests.rs b/substrate/frame/contracts/mock-network/src/tests.rs index d22221fe8ee..39aa9bebc0f 100644 --- a/substrate/frame/contracts/mock-network/src/tests.rs +++ b/substrate/frame/contracts/mock-network/src/tests.rs @@ -23,7 +23,6 @@ use crate::{ }; use codec::{Decode, Encode}; use frame_support::{ - assert_err, pallet_prelude::Weight, traits::{fungibles::Mutate, Currency}, }; @@ -102,7 +101,7 @@ fn test_xcm_execute() { 0, Weight::MAX, None, - VersionedXcm::V4(message).encode(), + VersionedXcm::V4(message).encode().encode(), DebugInfo::UnsafeDebug, CollectEvents::UnsafeCollect, Determinism::Enforced, @@ -146,7 +145,7 @@ fn test_xcm_execute_incomplete() { 0, Weight::MAX, None, - VersionedXcm::V4(message).encode(), + VersionedXcm::V4(message).encode().encode(), DebugInfo::UnsafeDebug, CollectEvents::UnsafeCollect, Determinism::Enforced, @@ -160,37 +159,6 @@ fn test_xcm_execute_incomplete() { }); } -#[test] -fn test_xcm_execute_filtered_call() { - MockNet::reset(); - - let contract_addr = instantiate_test_contract("xcm_execute"); - - ParaA::execute_with(|| { - // `remark` should be rejected, as it is not allowed by our CallFilter. - let call = parachain::RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); - let message: Xcm = Xcm(vec![Transact { - origin_kind: OriginKind::Native, - require_weight_at_most: Weight::MAX, - call: call.encode().into(), - }]); - - let result = ParachainContracts::bare_call( - ALICE, - contract_addr.clone(), - 0, - Weight::MAX, - None, - VersionedXcm::V4(message).encode(), - DebugInfo::UnsafeDebug, - CollectEvents::UnsafeCollect, - Determinism::Enforced, - ); - - assert_err!(result.result, frame_system::Error::::CallFiltered); - }); -} - #[test] fn test_xcm_execute_reentrant_call() { MockNet::reset(); @@ -222,7 +190,7 @@ fn test_xcm_execute_reentrant_call() { 0, Weight::MAX, None, - VersionedXcm::V4(message).encode(), + VersionedXcm::V4(message).encode().encode(), DebugInfo::UnsafeDebug, CollectEvents::UnsafeCollect, Determinism::Enforced, @@ -258,7 +226,7 @@ fn test_xcm_send() { 0, Weight::MAX, None, - (dest, message).encode(), + (dest, message.encode()).encode(), DebugInfo::UnsafeDebug, CollectEvents::UnsafeCollect, Determinism::Enforced, diff --git a/substrate/frame/contracts/src/lib.rs b/substrate/frame/contracts/src/lib.rs index 6433d4eecdc..e14a4b8bcb8 100644 --- a/substrate/frame/contracts/src/lib.rs +++ b/substrate/frame/contracts/src/lib.rs @@ -298,6 +298,9 @@ pub mod pallet { /// Therefore please make sure to be restrictive about which dispatchables are allowed /// in order to not introduce a new DoS vector like memory allocation patterns that can /// be exploited to drive the runtime into a panic. + /// + /// This filter does not apply to XCM transact calls. To impose restrictions on XCM transact + /// calls, you must configure them separately within the XCM pallet itself. type CallFilter: Contains<::RuntimeCall>; /// Used to answer contracts' queries regarding the current weight price. This is **not** diff --git a/substrate/frame/contracts/src/wasm/runtime.rs b/substrate/frame/contracts/src/wasm/runtime.rs index 160dfa0d2f3..28a08ab0224 100644 --- a/substrate/frame/contracts/src/wasm/runtime.rs +++ b/substrate/frame/contracts/src/wasm/runtime.rs @@ -25,12 +25,8 @@ use crate::{ }; use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; use frame_support::{ - dispatch::DispatchInfo, - ensure, - pallet_prelude::{DispatchResult, DispatchResultWithPostInfo}, - parameter_types, - traits::Get, - weights::Weight, + dispatch::DispatchInfo, ensure, pallet_prelude::DispatchResultWithPostInfo, parameter_types, + traits::Get, weights::Weight, }; use pallet_contracts_proc_macro::define_env; use pallet_contracts_uapi::{CallFlags, ReturnFlags}; @@ -41,9 +37,6 @@ use sp_runtime::{ }; use sp_std::{fmt, prelude::*}; use wasmi::{core::HostError, errors::LinkerError, Linker, Memory, Store}; -use xcm::VersionedXcm; - -type CallOf = ::RuntimeCall; /// The maximum nesting depth a contract can use when encoding types. const MAX_DECODE_NESTING: u32 = 256; @@ -378,29 +371,6 @@ fn already_charged(_: u32) -> Option { None } -/// Ensure that the XCM program is executable, by checking that it does not contain any [`Transact`] -/// instruction with a call that is not allowed by the CallFilter. -fn ensure_executable(message: &VersionedXcm>) -> DispatchResult { - use frame_support::traits::Contains; - use xcm::prelude::{Transact, Xcm}; - - let mut message: Xcm> = - message.clone().try_into().map_err(|_| Error::::XCMDecodeFailed)?; - - message.iter_mut().try_for_each(|inst| -> DispatchResult { - let Transact { ref mut call, .. } = inst else { return Ok(()) }; - let call = call.ensure_decoded().map_err(|_| Error::::XCMDecodeFailed)?; - - if !::CallFilter::contains(call) { - return Err(frame_system::Error::::CallFiltered.into()) - } - - Ok(()) - })?; - - Ok(()) -} - /// Can only be used for one call. pub struct Runtime<'a, E: Ext + 'a> { ext: &'a mut E, @@ -2112,16 +2082,13 @@ pub mod env { msg_len: u32, ) -> Result { use frame_support::dispatch::DispatchInfo; - use xcm::VersionedXcm; use xcm_builder::{ExecuteController, ExecuteControllerWeightInfo}; ctx.charge_gas(RuntimeCosts::CopyFromContract(msg_len))?; - let message: VersionedXcm> = - ctx.read_sandbox_memory_as_unbounded(memory, msg_ptr, msg_len)?; - ensure_executable::(&message)?; + let message = ctx.read_sandbox_memory_as_unbounded(memory, msg_ptr, msg_len)?; let execute_weight = - <::Xcm as ExecuteController<_, _>>::WeightInfo::execute(); + <::Xcm as ExecuteController<_, _>>::WeightInfo::execute_blob(); let weight = ctx.ext.gas_meter().gas_left().max(execute_weight); let dispatch_info = DispatchInfo { weight, ..Default::default() }; @@ -2130,9 +2097,9 @@ pub mod env { RuntimeCosts::CallXcmExecute, |ctx| { let origin = crate::RawOrigin::Signed(ctx.ext.address().clone()).into(); - let weight_used = <::Xcm>::execute( + let weight_used = <::Xcm>::execute_blob( origin, - Box::new(message), + message, weight.saturating_sub(execute_weight), )?; @@ -2152,19 +2119,18 @@ pub mod env { msg_len: u32, output_ptr: u32, ) -> Result { - use xcm::{VersionedLocation, VersionedXcm}; + use xcm::VersionedLocation; use xcm_builder::{SendController, SendControllerWeightInfo}; ctx.charge_gas(RuntimeCosts::CopyFromContract(msg_len))?; let dest: VersionedLocation = ctx.read_sandbox_memory_as(memory, dest_ptr)?; - let message: VersionedXcm<()> = - ctx.read_sandbox_memory_as_unbounded(memory, msg_ptr, msg_len)?; - let weight = <::Xcm as SendController<_>>::WeightInfo::send(); + let message = ctx.read_sandbox_memory_as_unbounded(memory, msg_ptr, msg_len)?; + let weight = <::Xcm as SendController<_>>::WeightInfo::send_blob(); ctx.charge_gas(RuntimeCosts::CallRuntime(weight))?; let origin = crate::RawOrigin::Signed(ctx.ext.address().clone()).into(); - match <::Xcm>::send(origin, dest.into(), message.into()) { + match <::Xcm>::send_blob(origin, dest.into(), message) { Ok(message_id) => { ctx.write_sandbox_memory(memory, output_ptr, &message_id.encode())?; Ok(ReturnErrorCode::Success) diff --git a/substrate/frame/contracts/uapi/src/host.rs b/substrate/frame/contracts/uapi/src/host.rs index 04f58895ab4..459cb59bead 100644 --- a/substrate/frame/contracts/uapi/src/host.rs +++ b/substrate/frame/contracts/uapi/src/host.rs @@ -790,7 +790,7 @@ pub trait HostFn { /// /// # Parameters /// - /// - `dest`: The XCM destination, should be decodable as [VersionedMultiLocation](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/enum.VersionedMultiLocation.html), + /// - `dest`: The XCM destination, should be decodable as [MultiLocation](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/enum.VersionedLocation.html), /// traps otherwise. /// - `msg`: The message, should be decodable as a [VersionedXcm](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/enum.VersionedXcm.html), /// traps otherwise. -- GitLab From 5ac32ee2bdd9df47e4578c51810db4d2139757eb Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:49:10 +0200 Subject: [PATCH 187/188] authority-discovery: Set intervals to start when authority keys changes (#3764) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The authority-discovery mechanism has implemented a few exponential timers for: - publishing the authority records - goes from 2 seconds (when freshly booted) to 1 hour if the node is long-running - set to 1 hour after successfully publishing the authority record - discovering other authority records - goes from 2 seconds (when freshly booted) to 10 minutes if the node is long-running This PR resets the exponential publishing and discovery interval to defaults ensuring that long-running nodes: - will retry publishing the authority records as aggressively as freshly booted nodes - Currently, if a long-running node fails to publish the DHT record when the keys change (ie DhtEvent::ValuePutFailed), it will only retry after 1 hour - will rediscover other authorities faster (since there is a chance that other authority keys changed) The subp2p-explorer has difficulties discovering the authorities when the authority set changes in the first few hours. This might be entirely due to the recursive nature of the DHT and the needed time to propagate the records. However, there is a small chance that the authority publishing failed and is only retried in 1h. Let me know if this makes sense 🙏 cc @paritytech/networking --------- Signed-off-by: Alexandru Vasile Co-authored-by: Dmitry Markin --- .../authority-discovery/src/interval.rs | 20 +++++++++++-- .../client/authority-discovery/src/worker.rs | 28 +++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/substrate/client/authority-discovery/src/interval.rs b/substrate/client/authority-discovery/src/interval.rs index 23c7ce266e3..0eee0d159cd 100644 --- a/substrate/client/authority-discovery/src/interval.rs +++ b/substrate/client/authority-discovery/src/interval.rs @@ -28,6 +28,7 @@ use std::{ /// /// Doubles interval duration on each tick until the configured maximum is reached. pub struct ExpIncInterval { + start: Duration, max: Duration, next: Duration, delay: Delay, @@ -37,14 +38,29 @@ impl ExpIncInterval { /// Create a new [`ExpIncInterval`]. pub fn new(start: Duration, max: Duration) -> Self { let delay = Delay::new(start); - Self { max, next: start * 2, delay } + Self { start, max, next: start * 2, delay } } - /// Fast forward the exponentially increasing interval to the configured maximum. + /// Fast forward the exponentially increasing interval to the configured maximum, if not already + /// set. pub fn set_to_max(&mut self) { + if self.next == self.max { + return; + } + self.next = self.max; self.delay = Delay::new(self.next); } + + /// Rewind the exponentially increasing interval to the configured start, if not already set. + pub fn set_to_start(&mut self) { + if self.next == self.start * 2 { + return; + } + + self.next = self.start * 2; + self.delay = Delay::new(self.start); + } } impl Stream for ExpIncInterval { diff --git a/substrate/client/authority-discovery/src/worker.rs b/substrate/client/authority-discovery/src/worker.rs index b77f0241ec2..4ad7db5f7da 100644 --- a/substrate/client/authority-discovery/src/worker.rs +++ b/substrate/client/authority-discovery/src/worker.rs @@ -129,6 +129,9 @@ pub struct Worker { /// List of keys onto which addresses have been published at the latest publication. /// Used to check whether they have changed. latest_published_keys: HashSet, + /// List of the kademlia keys that have been published at the latest publication. + /// Used to associate DHT events with our published records. + latest_published_kad_keys: HashSet, /// Same value as in the configuration. publish_non_global_ips: bool, @@ -265,6 +268,7 @@ where publish_interval, publish_if_changed_interval, latest_published_keys: HashSet::new(), + latest_published_kad_keys: HashSet::new(), publish_non_global_ips: config.publish_non_global_ips, public_addresses, strict_record_validation: config.strict_record_validation, @@ -397,8 +401,17 @@ where self.client.as_ref(), ).await?.into_iter().collect::>(); - if only_if_changed && keys == self.latest_published_keys { - return Ok(()) + if only_if_changed { + // If the authority keys did not change and the `publish_if_changed_interval` was + // triggered then do nothing. + if keys == self.latest_published_keys { + return Ok(()) + } + + // We have detected a change in the authority keys, reset the timers to + // publish and gather data faster. + self.publish_interval.set_to_start(); + self.query_interval.set_to_start(); } let addresses = serialize_addresses(self.addresses_to_publish()); @@ -422,6 +435,8 @@ where keys_vec, )?; + self.latest_published_kad_keys = kv_pairs.iter().map(|(k, _)| k.clone()).collect(); + for (key, value) in kv_pairs.into_iter() { self.network.put_value(key, value); } @@ -523,6 +538,10 @@ where } }, DhtEvent::ValuePut(hash) => { + if !self.latest_published_kad_keys.contains(&hash) { + return; + } + // Fast forward the exponentially increasing interval to the configured maximum. In // case this was the first successful address publishing there is no need for a // timely retry. @@ -535,6 +554,11 @@ where debug!(target: LOG_TARGET, "Successfully put hash '{:?}' on Dht.", hash) }, DhtEvent::ValuePutFailed(hash) => { + if !self.latest_published_kad_keys.contains(&hash) { + // Not a value we have published or received multiple times. + return; + } + if let Some(metrics) = &self.metrics { metrics.dht_event_received.with_label_values(&["value_put_failed"]).inc(); } -- GitLab From 25af0adf7836c67e28083276ec6f06d974e4f685 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Wed, 27 Mar 2024 12:50:03 +0100 Subject: [PATCH 188/188] [ci] Collect subsystem-benchmarks results and add graphs for them (#3853) PR adds CI jobs that collect subsystem-benchmarks results and publishes them to gh-pages. cc https://github.com/paritytech/ci_cd/issues/934 cc @AndreiEres --- .github/workflows/subsystem-benchmarks.yml | 42 ++++++++++++ .gitlab-ci.yml | 7 ++ .gitlab/pipeline/publish.yml | 76 ++++++++++++++++++++-- .gitlab/pipeline/test.yml | 6 ++ 4 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/subsystem-benchmarks.yml diff --git a/.github/workflows/subsystem-benchmarks.yml b/.github/workflows/subsystem-benchmarks.yml new file mode 100644 index 00000000000..37a9e0f4680 --- /dev/null +++ b/.github/workflows/subsystem-benchmarks.yml @@ -0,0 +1,42 @@ +# The actions takes json file as input and runs github-action-benchmark for it. + +on: + workflow_dispatch: + inputs: + benchmark-data-dir-path: + description: "Path to the benchmark data directory" + required: true + type: string + output-file-path: + description: "Path to the benchmark data file" + required: true + type: string + +jobs: + subsystem-benchmarks: + runs-on: ubuntu-latest + steps: + - name: Checkout Sources + uses: actions/checkout@v4.1.2 + with: + fetch-depth: 0 + ref: "gh-pages" + + - name: Copy bench results + id: step_one + run: | + cp bench/gitlab/${{ github.event.inputs.output-file-path }} ${{ github.event.inputs.output-file-path }} + + - name: Switch branch + id: step_two + run: | + git checkout master + + - name: Store benchmark result + uses: benchmark-action/github-action-benchmark@v1 + with: + tool: "customSmallerIsBetter" + output-file-path: ${{ github.event.inputs.output-file-path }} + benchmark-data-dir-path: "bench/${{ github.event.inputs.benchmark-data-dir-path }}" + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7f8796ca512..93a6ccb9f8f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -147,6 +147,13 @@ default: - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs - if: $CI_COMMIT_REF_NAME =~ /^gh-readonly-queue.*$/ # merge queues +.publish-gh-pages-refs: + rules: + - if: $CI_PIPELINE_SOURCE == "pipeline" + when: never + - if: $CI_PIPELINE_SOURCE == "web" && $CI_COMMIT_REF_NAME == "master" + - if: $CI_COMMIT_REF_NAME == "master" + # handle the specific case where benches could store incorrect bench data because of the downstream staging runs # exclude cargo-check-benches from such runs .test-refs-check-benches: diff --git a/.gitlab/pipeline/publish.yml b/.gitlab/pipeline/publish.yml index b73acb560f6..bd9387f3c07 100644 --- a/.gitlab/pipeline/publish.yml +++ b/.gitlab/pipeline/publish.yml @@ -3,16 +3,13 @@ publish-rustdoc: stage: publish - extends: .kubernetes-env + extends: + - .kubernetes-env + - .publish-gh-pages-refs variables: CI_IMAGE: node:18 GIT_DEPTH: 100 RUSTDOCS_DEPLOY_REFS: "master" - rules: - - if: $CI_PIPELINE_SOURCE == "pipeline" - when: never - - if: $CI_PIPELINE_SOURCE == "web" && $CI_COMMIT_REF_NAME == "master" - - if: $CI_COMMIT_REF_NAME == "master" needs: - job: build-rustdoc artifacts: true @@ -60,9 +57,76 @@ publish-rustdoc: - git commit -m "___Updated docs for ${CI_COMMIT_REF_NAME}___" || echo "___Nothing to commit___" - git push origin gh-pages --force + # artificial sleep to publish gh-pages + - sleep 300 after_script: - rm -rf .git/ ./* +publish-subsystem-benchmarks: + stage: publish + variables: + CI_IMAGE: "paritytech/tools:latest" + extends: + - .kubernetes-env + - .publish-gh-pages-refs + needs: + - job: subsystem-regression-tests + artifacts: true + - job: publish-rustdoc + artifacts: false + script: + # setup ssh + - eval $(ssh-agent) + - ssh-add - <<< ${GITHUB_SSH_PRIV_KEY} + - mkdir ~/.ssh && touch ~/.ssh/known_hosts + - ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts + # Set git config + - rm -rf .git/config + - git config user.email "devops-team@parity.io" + - git config user.name "${GITHUB_USER}" + - git config remote.origin.url "git@github.com:/paritytech/${CI_PROJECT_NAME}.git" + - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" + - git fetch origin gh-pages + # Push result to github + - git checkout gh-pages + - mkdir -p bench/gitlab/ || echo "Directory exists" + - rm -rf bench/gitlab/*.json || echo "No json files" + - cp -r charts/*.json bench/gitlab/ + - git add bench/gitlab/ + - git commit -m "Add json files with benchmark results for ${CI_COMMIT_REF_NAME}" + - git push origin gh-pages + # artificial sleep to publish gh-pages + - sleep 300 + allow_failure: true + after_script: + - rm -rf .git/ ./* + +trigger_workflow: + stage: deploy + extends: + - .kubernetes-env + - .publish-gh-pages-refs + needs: + - job: publish-subsystem-benchmarks + artifacts: false + - job: subsystem-regression-tests + artifacts: true + script: + - echo "Triggering workflow" + - | + for benchmark in $(ls charts/*.json); do + export bencmark_name=$(basename $benchmark) + echo "Benchmark: $bencmark_name" + export benchmark_dir=$(echo $bencmark_name | sed 's/\.json//') + curl -q -X POST \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: token $GITHUB_TOKEN" \ + https://api.github.com/repos/paritytech-stg/${CI_PROJECT_NAME}/actions/workflows/subsystem-benchmarks.yml/dispatches \ + -d '{"ref":"refs/heads/master","inputs":{"benchmark-data-dir-path":"'$benchmark_dir'","output-file-path":"'$bencmark_name'"}}' + sleep 300 + done + allow_failure: true + # note: images are used not only in zombienet but also in rococo, wococo and versi .build-push-image: image: $BUILDAH_IMAGE diff --git a/.gitlab/pipeline/test.yml b/.gitlab/pipeline/test.yml index 476ac6333f5..d97f9da986c 100644 --- a/.gitlab/pipeline/test.yml +++ b/.gitlab/pipeline/test.yml @@ -497,6 +497,12 @@ test-syscalls: subsystem-regression-tests: stage: test + artifacts: + name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}" + when: on_success + expire_in: 1 days + paths: + - charts/ extends: - .docker-env - .common-refs -- GitLab